From dbb04b0d29f884dbb6d0a52dd7877445d2e776f1 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 18 Aug 2015 12:07:48 +0300 Subject: iwlwifi: mvm: remove netdetect debugfs entry This debugfs entry was implemented just as a proof-of-concept before the full support for netdetect via cfg80211/mac80211 was implemented. Now that we have a proper way to enable netdetect from userspace, this entry is redundant and should be removed to avoid unnecessary maintenance work. Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 114 ----------------------------- 1 file changed, 114 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 7d69a556bcc8..08d2ae355700 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -1214,118 +1214,6 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, return ret; } - -#define MAX_NUM_ND_MATCHSETS 10 - -static ssize_t iwl_dbgfs_netdetect_write(struct iwl_mvm *mvm, char *buf, - size_t count, loff_t *ppos) -{ - const char *seps = ",\n"; - char *buf_ptr = buf; - char *value_str = NULL; - int ret, i; - - /* TODO: don't free if write is being called several times in one go */ - if (mvm->nd_config) { - kfree(mvm->nd_config->match_sets); - kfree(mvm->nd_config); - mvm->nd_config = NULL; - } - - mvm->nd_config = kzalloc(sizeof(*mvm->nd_config) + - (11 * sizeof(struct ieee80211_channel *)), - GFP_KERNEL); - if (!mvm->nd_config) { - ret = -ENOMEM; - goto out_free; - } - - mvm->nd_config->n_channels = 11; - mvm->nd_config->scan_width = NL80211_BSS_CHAN_WIDTH_20; - mvm->nd_config->interval = 5; - mvm->nd_config->min_rssi_thold = -80; - for (i = 0; i < mvm->nd_config->n_channels; i++) - mvm->nd_config->channels[i] = &mvm->nvm_data->channels[i]; - - mvm->nd_config->match_sets = - kcalloc(MAX_NUM_ND_MATCHSETS, - sizeof(*mvm->nd_config->match_sets), - GFP_KERNEL); - if (!mvm->nd_config->match_sets) { - ret = -ENOMEM; - goto out_free; - } - - while ((value_str = strsep(&buf_ptr, seps)) && - strlen(value_str)) { - struct cfg80211_match_set *set; - - if (mvm->nd_config->n_match_sets >= MAX_NUM_ND_MATCHSETS) { - ret = -EINVAL; - goto out_free; - } - - set = &mvm->nd_config->match_sets[mvm->nd_config->n_match_sets]; - set->ssid.ssid_len = strlen(value_str); - - if (set->ssid.ssid_len > IEEE80211_MAX_SSID_LEN) { - ret = -EINVAL; - goto out_free; - } - - memcpy(set->ssid.ssid, value_str, set->ssid.ssid_len); - - mvm->nd_config->n_match_sets++; - } - - ret = count; - - if (mvm->nd_config->n_match_sets) - goto out; - -out_free: - if (mvm->nd_config) - kfree(mvm->nd_config->match_sets); - kfree(mvm->nd_config); - mvm->nd_config = NULL; -out: - return ret; -} - -static ssize_t -iwl_dbgfs_netdetect_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_mvm *mvm = file->private_data; - size_t bufsz, ret; - char *buf; - int i, n_match_sets, pos = 0; - - n_match_sets = mvm->nd_config ? mvm->nd_config->n_match_sets : 0; - - bufsz = n_match_sets * (IEEE80211_MAX_SSID_LEN + 1) + 1; - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - for (i = 0; i < n_match_sets; i++) { - if (pos + - mvm->nd_config->match_sets[i].ssid.ssid_len + 2 > bufsz) { - ret = -EIO; - goto out; - } - - memcpy(buf + pos, mvm->nd_config->match_sets[i].ssid.ssid, - mvm->nd_config->match_sets[i].ssid.ssid_len); - pos += mvm->nd_config->match_sets[i].ssid.ssid_len; - buf[pos++] = '\n'; - } - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -out: - kfree(buf); - return ret; -} #endif #define PRINT_MVM_REF(ref) do { \ @@ -1503,7 +1391,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); #ifdef CONFIG_PM_SLEEP MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); -MVM_DEBUGFS_READ_WRITE_FILE_OPS(netdetect, 384); #endif int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) @@ -1572,7 +1459,6 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) if (!debugfs_create_u32("last_netdetect_scans", S_IRUSR, mvm->debugfs_dir, &mvm->last_netdetect_scans)) goto err; - MVM_DEBUGFS_ADD_FILE(netdetect, mvm->debugfs_dir, S_IRUSR | S_IWUSR); #endif if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR, -- cgit v1.2.3 From 62e004fe941d56cb70ea9148bb79cf6698751248 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 20 Aug 2015 14:12:58 +0300 Subject: iwlwifi: mvm: fix statistics variables type When receiving statistics notification there is a field of average energy. This is defines as signed 8 bit, while FW refers to it as unsigned. when the energy is higher than 127 this causes in iwl_mvm_stat_iterator a wrong computation of the signal int sig = -stats->general.beacon_filter_average_energy; resulting in incorrect CQM event (change from low to high). While at it - update the rest of the fields to the correct type. Signed-off-by: Sara Sharon Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h | 16 ++++++++-------- drivers/net/wireless/iwlwifi/mvm/mvm.h | 10 +++++----- drivers/net/wireless/iwlwifi/mvm/rx.c | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h index 709e28d8b1b0..4ca4bceb95a4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h @@ -237,10 +237,10 @@ struct mvm_statistics_general_v5 { __le32 num_of_sos_states; __le32 beacon_filtered; __le32 missed_beacons; - __s8 beacon_filter_average_energy; - __s8 beacon_filter_reason; - __s8 beacon_filter_current_energy; - __s8 beacon_filter_reserved; + u8 beacon_filter_average_energy; + u8 beacon_filter_reason; + u8 beacon_filter_current_energy; + u8 beacon_filter_reserved; __le32 beacon_filter_delta_time; struct mvm_statistics_bt_activity bt_activity; } __packed; /* STATISTICS_GENERAL_API_S_VER_5 */ @@ -263,10 +263,10 @@ struct mvm_statistics_general_v8 { __le32 num_of_sos_states; __le32 beacon_filtered; __le32 missed_beacons; - __s8 beacon_filter_average_energy; - __s8 beacon_filter_reason; - __s8 beacon_filter_current_energy; - __s8 beacon_filter_reserved; + u8 beacon_filter_average_energy; + u8 beacon_filter_reason; + u8 beacon_filter_current_energy; + u8 beacon_filter_reserved; __le32 beacon_filter_delta_time; struct mvm_statistics_bt_activity bt_activity; __le64 rx_time; diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index b95a07ec9e36..72cd67eab06f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -323,11 +323,11 @@ enum iwl_bt_force_ant_mode { struct iwl_mvm_vif_bf_data { bool bf_enabled; bool ba_enabled; - s8 ave_beacon_signal; - s8 last_cqm_event; - s8 bt_coex_min_thold; - s8 bt_coex_max_thold; - s8 last_bt_coex_event; + int ave_beacon_signal; + int last_cqm_event; + int bt_coex_min_thold; + int bt_coex_max_thold; + int last_bt_coex_event; }; /** diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index c37c10a423ce..2ad814df0b3c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c @@ -459,7 +459,7 @@ static void iwl_mvm_update_rx_statistics(struct iwl_mvm *mvm, struct iwl_mvm_stat_data { struct iwl_mvm *mvm; __le32 mac_id; - __s8 beacon_filter_average_energy; + u8 beacon_filter_average_energy; struct mvm_statistics_general_v8 *general; }; -- cgit v1.2.3 From e50460192e6e326fc748037c7ba69565fc18f992 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 17 Aug 2015 10:45:50 +0300 Subject: iwlwifi: mvm: add debugfs hook to send ECHO_CMD to the firmware ECHO_CMD is a simple command that can be sent to the firmware just to check that it is alive. This command is useful for debug purpose, provide a debugfs hook to send it. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 15 +++++++++++++++ drivers/net/wireless/iwlwifi/mvm/fw-api.h | 1 + drivers/net/wireless/iwlwifi/mvm/ops.c | 1 + 3 files changed, 17 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 08d2ae355700..3b8481f34a18 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -1361,11 +1361,25 @@ out: return count; } +static ssize_t +iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf, + size_t count, loff_t *ppos) +{ + int ret; + + mutex_lock(&mvm->mutex); + ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL); + mutex_unlock(&mvm->mutex); + + return ret ?: count; +} + MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64); /* Device wide debugfs entries */ MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16); MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8); +MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64); MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64); MVM_DEBUGFS_READ_FILE_OPS(nic_temp); @@ -1425,6 +1439,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR); + MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR); if (!debugfs_create_bool("enable_scan_iteration_notif", S_IRUSR | S_IWUSR, mvm->debugfs_dir, diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 4af7513adda2..cd293d27677e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h @@ -100,6 +100,7 @@ enum iwl_mvm_tx_fifo { enum { MVM_ALIVE = 0x1, REPLY_ERROR = 0x2, + ECHO_CMD = 0x3, INIT_COMPLETE_NOTIF = 0x4, diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index a37de3f410a0..009228615d26 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -271,6 +271,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { static const char *const iwl_mvm_cmd_strings[REPLY_MAX + 1] = { CMD(MVM_ALIVE), CMD(REPLY_ERROR), + CMD(ECHO_CMD), CMD(INIT_COMPLETE_NOTIF), CMD(PHY_CONTEXT_CMD), CMD(MGMT_MCAST_KEY), -- cgit v1.2.3 From a73a2cea922de5d2dd03ad456e280ef92c8bb9f6 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 23 Aug 2015 13:29:36 +0300 Subject: iwlwifi: Deinline iwl_{read,write}(8,32} With CONFIG_IWLWIFI_DEVICE_TRACING=y, these functions are rather large, too big for inlining. With this .config: http://busybox.net/~vda/kernel_config, after uninlining these functions have sizes and callsite counts as follows: iwl_read32 475 bytes, 51 callsites iwl_write32 477 bytes, 90 callsites iwl_write8 493 bytes, 3 callsites Reduction in size is about 74,000 bytes: text data bss dec hex filename 90758147 17226024 36659200 144643371 89f152b vmlinux0 90687995 17221928 36659200 144569123 89df323 vmlinux.after Reported-by: Denys Vlasenko Signed-off-by: Emmanuel Grumbach Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/iwl-io.c | 22 ++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-io.h | 21 +++------------------ 2 files changed, 25 insertions(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 27c66e477833..3c263a15df89 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -36,6 +36,28 @@ #include "iwl-prph.h" #include "iwl-fh.h" +void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) +{ + trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val); + iwl_trans_write8(trans, ofs, val); +} +IWL_EXPORT_SYMBOL(iwl_write8); + +void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val) +{ + trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val); + iwl_trans_write32(trans, ofs, val); +} +IWL_EXPORT_SYMBOL(iwl_write32); + +u32 iwl_read32(struct iwl_trans *trans, u32 ofs) +{ + u32 val = iwl_trans_read32(trans, ofs); + trace_iwlwifi_dev_ioread32(trans->dev, ofs, val); + return val; +} +IWL_EXPORT_SYMBOL(iwl_read32); + #define IWL_POLL_INTERVAL 10 /* microseconds */ int iwl_poll_bit(struct iwl_trans *trans, u32 addr, diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 705d12c079e8..501d0560c061 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -32,24 +32,9 @@ #include "iwl-devtrace.h" #include "iwl-trans.h" -static inline void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) -{ - trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val); - iwl_trans_write8(trans, ofs, val); -} - -static inline void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val) -{ - trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val); - iwl_trans_write32(trans, ofs, val); -} - -static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs) -{ - u32 val = iwl_trans_read32(trans, ofs); - trace_iwlwifi_dev_ioread32(trans->dev, ofs, val); - return val; -} +void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val); +void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val); +u32 iwl_read32(struct iwl_trans *trans, u32 ofs); static inline void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask) { -- cgit v1.2.3 From 9493908095a3d0b4fa24ff529975376b3a2b8394 Mon Sep 17 00:00:00 2001 From: Gregory Greenman Date: Mon, 24 Aug 2015 14:38:35 +0300 Subject: iwlwifi: mvm: don't ask for beacons when AP vif and no assoc sta When in AP mode, we need beacons from other APs for HT protection. However, when there's no any associated station we will not do any Tx and thus don't really need beacons. On the other hand, these beacons will cause a lot of unnecessary wakeups which increase our power consumption. Handle this by asking FW to pass beacons only when there's at least one associated station. Signed-off-by: Gregory Greenman Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 21 +++++++++++++++------ drivers/net/wireless/iwlwifi/mvm/mac80211.c | 9 +++++++++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 6 ++++++ drivers/net/wireless/iwlwifi/mvm/sta.c | 5 +++++ 4 files changed, 35 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 3424315dd876..5af0090ffb6e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * * 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 @@ -33,6 +34,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1124,10 +1126,11 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id); } -static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - u32 action) +int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + u32 action) { + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mac_ctx_cmd cmd = {}; WARN_ON(vif->type != NL80211_IFTYPE_AP || vif->p2p); @@ -1137,10 +1140,16 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, /* * pass probe requests and beacons from other APs (needed - * for ht protection) + * for ht protection); when there're no any associated station + * don't ask FW to pass beacons to prevent unnecessary wake-ups. */ - cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST | - MAC_FILTER_IN_BEACON); + cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); + if (mvmvif->ap_assoc_sta_count) { + cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON); + IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n"); + } else { + IWL_DEBUG_HC(mvm, "No need to receive beacons\n"); + } /* Fill the data specific for ap mode */ iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap, diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index aa8c2b7f23c7..f9f88e913e03 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -2319,6 +2319,8 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, if (vif->type == NL80211_IFTYPE_AP) iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif); + mvmvif->ap_assoc_sta_count = 0; + /* Add the mac context */ ret = iwl_mvm_mac_ctxt_add(mvm, vif); if (ret) @@ -2613,6 +2615,7 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); /* @@ -2627,6 +2630,12 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id])) rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], ERR_PTR(-ENOENT)); + + if (mvm_sta->vif->type == NL80211_IFTYPE_AP) { + mvmvif->ap_assoc_sta_count--; + iwl_mvm_mac_ctxt_cmd_ap(mvm, vif, FW_CTXT_ACTION_MODIFY); + } + mutex_unlock(&mvm->mutex); } diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 72cd67eab06f..ed9b0cc14edd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -338,6 +338,8 @@ struct iwl_mvm_vif_bf_data { * @bssid: BSSID for this (client) interface * @associated: indicates that we're currently associated, used only for * managing the firmware state in iwl_mvm_bss_info_changed_station() + * @ap_assoc_sta_count: count of stations associated to us - valid only + * if VIF type is AP * @uploaded: indicates the MAC context has been added to the device * @ap_ibss_active: indicates that AP/IBSS is configured and that the interface * should get quota etc. @@ -367,6 +369,7 @@ struct iwl_mvm_vif { u8 bssid[ETH_ALEN]; bool associated; + u8 ap_assoc_sta_count; bool uploaded; bool ap_ibss_active; @@ -1131,6 +1134,9 @@ void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif); unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, struct ieee80211_vif *exclude_vif); +int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + u32 action); /* Bindings */ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index df216cd0c98f..fe2f53850d36 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -275,6 +275,11 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, if (sta_id == IWL_MVM_STATION_COUNT) return -ENOSPC; + if (vif->type == NL80211_IFTYPE_AP) { + mvmvif->ap_assoc_sta_count++; + iwl_mvm_mac_ctxt_cmd_ap(mvm, vif, FW_CTXT_ACTION_MODIFY); + } + spin_lock_init(&mvm_sta->lock); mvm_sta->sta_id = sta_id; -- cgit v1.2.3 From cf8c3cff3fcce966c6d31001c09c92778f961eea Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Mon, 24 Aug 2015 14:53:25 +0300 Subject: iwlwifi: mvm: make sure d0i3 exit work runs before suspending If we are in d0i3 when entering suspend, we leave d0i3 so that mac80211 can call us to remove connections or whatever before going to suspend. We do this by calling pm_runtime_resume() early in the slave transport flow and reactivating it later, when the wiphy suspend flow runs. The problem is that we queue a work in order to leave d0i3. If this work hasn't run yet when the wiphy suspend flow is called, we have a race and entering d0i3 fails (because we're still holding the IWL_MVM_REF_EXIT_WORK reference). To solve this, simply flush the d0i3_exit_work at the beginning of the iwl_mvm_suspend() function. Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/mvm/d3.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 04264e417c1c..1d54355ad76a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -1170,6 +1170,9 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); int ret; + /* make sure the d0i3 exit work is not pending */ + flush_work(&mvm->d0i3_exit_work); + ret = iwl_trans_suspend(mvm->trans); if (ret) return ret; -- cgit v1.2.3 From cfe417bc47ba8f470941a1b8ad60911e163f1b34 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 26 Aug 2015 12:22:12 +0200 Subject: iwlwifi: mvm: don't NUL-terminate low-latency debugfs file There's obviously no reason to write a NUL-terminating byte into the debugfs file. Apparently nobody tried to use this from a tool that doesn't strip NUL bytes though, so we never noticed. Fix it. Signed-off-by: Johannes Berg Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 383a3162046c..334ae56e5d8b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c @@ -1250,11 +1250,10 @@ static ssize_t iwl_dbgfs_low_latency_read(struct file *file, { struct ieee80211_vif *vif = file->private_data; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - char buf[3]; + char buf[2]; buf[0] = mvmvif->low_latency ? '1' : '0'; buf[1] = '\n'; - buf[2] = '\0'; return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf)); } -- cgit v1.2.3 From 3c1f84a174e425f2e7a687a6cfd791f609cbc9eb Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 26 Aug 2015 13:48:55 +0300 Subject: iwlwifi: mvm: don't load -12.ucode anymore -13.ucode has been published long ago. Deprecate old versions of the firmware. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/iwl-7000.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-8000.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 6951aba620eb..22c2430c9389 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -72,11 +72,11 @@ #define IWL7260_UCODE_API_MAX 17 /* Oldest version we won't warn about */ -#define IWL7260_UCODE_API_OK 12 +#define IWL7260_UCODE_API_OK 13 #define IWL3165_UCODE_API_OK 13 /* Lowest firmware API version supported */ -#define IWL7260_UCODE_API_MIN 12 +#define IWL7260_UCODE_API_MIN 13 #define IWL3165_UCODE_API_MIN 13 /* NVM versions */ diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c index 197abe43ddc5..6efef46f55d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/iwlwifi/iwl-8000.c @@ -72,10 +72,10 @@ #define IWL8000_UCODE_API_MAX 17 /* Oldest version we won't warn about */ -#define IWL8000_UCODE_API_OK 12 +#define IWL8000_UCODE_API_OK 13 /* Lowest firmware API version supported */ -#define IWL8000_UCODE_API_MIN 12 +#define IWL8000_UCODE_API_MIN 13 /* NVM versions */ #define IWL8000_NVM_VERSION 0x0a1d -- cgit v1.2.3 From 79f682806240741f62faaa33d933ebe768caa07f Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Mon, 24 Aug 2015 16:23:58 +0300 Subject: iwlwifi: mvm: remove SCD_QUEUE_CONFIG TLV flag We don't support firmwares that don't use the new API. This also allows to use all the SCD queues, so increase the reported number of queues to 31. Signed-off-by: Liad Kaufman Signed-off-by: Emmanuel Grumbach Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/iwl-7000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-8000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-fw-file.h | 3 --- drivers/net/wireless/iwlwifi/mvm/mvm.h | 5 ----- drivers/net/wireless/iwlwifi/mvm/utils.c | 11 ----------- 5 files changed, 2 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 22c2430c9389..5b25f367ef48 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -113,7 +113,7 @@ static const struct iwl_base_params iwl7000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_7000, - .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_queues = 31, .pll_cfg_val = 0, .shadow_ram_support = true, .led_compensation = 57, diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c index 6efef46f55d4..0116e5a4c393 100644 --- a/drivers/net/wireless/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/iwlwifi/iwl-8000.c @@ -107,7 +107,7 @@ static const struct iwl_base_params iwl8000_base_params = { .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000, - .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_queues = 31, .pll_cfg_val = 0, .shadow_ram_support = true, .led_compensation = 57, diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 84653e3d02ba..483b12741b2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h @@ -250,8 +250,6 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t; * IWL_UCODE_TLV_API_HDC_PHASE_0: ucode supports finer configuration of LTR * @IWL_UCODE_TLV_API_TX_POWER_DEV: new API for tx power. * @IWL_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header - * @IWL_UCODE_TLV_API_SCD_CFG: This firmware can configure the scheduler - * through the dedicated host command. * @IWL_UCODE_TLV_API_SINGLE_SCAN_EBS: EBS is supported for single scans too. * @IWL_UCODE_TLV_API_ASYNC_DTM: Async temperature notifications are supported. * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params @@ -269,7 +267,6 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_HDC_PHASE_0 = (__force iwl_ucode_tlv_api_t)10, IWL_UCODE_TLV_API_TX_POWER_DEV = (__force iwl_ucode_tlv_api_t)11, IWL_UCODE_TLV_API_WIDE_CMD_HDR = (__force iwl_ucode_tlv_api_t)14, - IWL_UCODE_TLV_API_SCD_CFG = (__force iwl_ucode_tlv_api_t)15, IWL_UCODE_TLV_API_SINGLE_SCAN_EBS = (__force iwl_ucode_tlv_api_t)16, IWL_UCODE_TLV_API_ASYNC_DTM = (__force iwl_ucode_tlv_api_t)17, IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18, diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index ed9b0cc14edd..cf1f5140127a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -937,11 +937,6 @@ static inline bool iwl_mvm_is_wifi_mcc_supported(struct iwl_mvm *mvm) IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC); } -static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm) -{ - return fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_SCD_CFG); -} - static inline bool iwl_mvm_bt_is_plcr_supported(struct iwl_mvm *mvm) { return fw_has_capa(&mvm->fw->ucode_capa, diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index a7d434256423..06cba97418b3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -672,12 +672,6 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, .tid = cfg->tid, }; - if (!iwl_mvm_is_scd_cfg_supported(mvm)) { - iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, cfg, - wdg_timeout); - return; - } - 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), &cmd), "Failed to configure queue %d on FIFO %d\n", queue, cfg->fifo); @@ -691,11 +685,6 @@ void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags) }; int ret; - if (!iwl_mvm_is_scd_cfg_supported(mvm)) { - iwl_trans_txq_disable(mvm->trans, queue, true); - return; - } - iwl_trans_txq_disable(mvm->trans, queue, false); ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, flags, sizeof(cmd), &cmd); -- cgit v1.2.3 From 6986fdd699f9be57cc1478c738ea6347e3d52547 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 27 Aug 2015 14:47:33 +0200 Subject: ath10k: fix mu-mimo rx status reporting MU-MIMO Rx involves different interpretation of the VHT-SIG-A compared to SU-MIMO. The incorrect interpretation led ath10k to report VHT MCS values greater than 9 which subsequently prompted mac80211 to drop such frames. This effectively broke Rx with MU-MIMO in many cases and manifested with a kernel warning in the log which looked like this: [ 14.552520] WARNING: CPU: 2 PID: 0 at net/mac80211/rx.c:3578 ieee80211_rx+0x26c/0x940 [mac80211]() [ 14.552522] Rate marked as a VHT rate but data is invalid: MCS: 10, NSS: 2 ... call trace follows ... Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 1b7a04366256..8ba8fa9004cf 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -643,6 +643,8 @@ struct amsdu_subframe_hdr { __be16 len; } __packed; +#define GROUP_ID_IS_SU_MIMO(x) ((x) == 0 || (x) == 63) + static void ath10k_htt_rx_h_rates(struct ath10k *ar, struct ieee80211_rx_status *status, struct htt_rx_desc *rxd) @@ -650,6 +652,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, struct ieee80211_supported_band *sband; u8 cck, rate, bw, sgi, mcs, nss; u8 preamble = 0; + u8 group_id; u32 info1, info2, info3; info1 = __le32_to_cpu(rxd->ppdu_start.info1); @@ -692,10 +695,27 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, case HTT_RX_VHT_WITH_TXBF: /* VHT-SIG-A1 in info2, VHT-SIG-A2 in info3 TODO check this */ - mcs = (info3 >> 4) & 0x0F; - nss = ((info2 >> 10) & 0x07) + 1; bw = info2 & 3; sgi = info3 & 1; + group_id = (info2 >> 4) & 0x3F; + + if (GROUP_ID_IS_SU_MIMO(group_id)) { + mcs = (info3 >> 4) & 0x0F; + nss = ((info2 >> 10) & 0x07) + 1; + } else { + /* Hardware doesn't decode VHT-SIG-B into Rx descriptor + * so it's impossible to decode MCS. Also since + * firmware consumes Group Id Management frames host + * has no knowledge regarding group/user position + * mapping so it's impossible to pick the correct Nsts + * from VHT-SIG-A1. + * + * Bandwidth and SGI are valid so report the rateinfo + * on best-effort basis. + */ + mcs = 0; + nss = 1; + } status->rate_idx = mcs; status->vht_nss = nss; -- cgit v1.2.3 From a925a3763982799460b9e9b5299520172652b785 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Fri, 28 Aug 2015 17:21:34 +0530 Subject: ath10k: fix DMA alloc failure for target requested memory chunks During long hours of stress testing like AP interface up/down along with continuous ping flood from a station doing connect/disconnect, it is observed that the system is not able to allocate DMA consistent memory of size > 512KB chunks as requested by firmware in WMI_SERVICE_EVENTID. With the system memory getting fragmented during the run based on the size of the memory requested, the failure to return physically continguous memory of high order can happen. Once the system gets to this situation, bringing up the wifi interface will fail and a system reboot may be needed to make it work again. This problem is obseved with QCA99X0. To fix this issue, allocate the DMA memory requested by firmware during device probe time and keep it during the life time of the device. WMI service ready event handler is changed to allocate the memory chunks if it is not already allocated or if the memory allocated for the previous ready event is not same as the current requested ones. After this patch the memory usage when wifi is inactive will be inceased by few 100KB to 3MB based on the target type. Failure happens with the following stack trace [29557.488773] kworker/u4:1: page allocation failure: order:8, mode:0xd0 [29557.494297] CPU: 0 PID: 8402 Comm: kworker/u4:1 Not tainted 3.14.43 #7 [29557.500793] Workqueue: ath10k_aux_wq ath10k_wmi_event_service_ready_work [ath10k_core] [29557.508602] [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [29557.516580] [] (show_stack) from [] (dump_stack+0x88/0xcc) [29557.523612] [] (dump_stack) from [] (warn_alloc_failed+0xdc/0x108) [29557.531515] [] (warn_alloc_failed) from [] (__alloc_pages_nodemask+0x4f0/0x654) [29557.540485] [] (__alloc_pages_nodemask) from [] (__dma_alloc_buffer.isra.20+0x2c/0x104) [29557.550260] [] (__dma_alloc_buffer.isra.20) from [] (__alloc_remap_buffer.isra.23+0x14/0xb8) [29557.560413] [] (__alloc_remap_buffer.isra.23) from [] (__dma_alloc+0x224/0x2b8) [29557.569490] [] (__dma_alloc) from [] (arm_dma_alloc+0x84/0x90) [29557.577010] [] (arm_dma_alloc) from [] (ath10k_wmi_event_service_ready_work+0x2f8/0x420 [ath10k_core]) [29557.588055] [] (ath10k_wmi_event_service_ready_work [ath10k_core]) from [] (process_one_work+0x20c/0x328) [29557.599305] [] (process_one_work) from [] (worker_thread+0x228/0x360) [29557.607470] [] (worker_thread) from [] (kthread+0xd8/0xec) [29557.614750] [] (kthread) from [] (ret_from_fork+0x14/0x3c) [29557.712751] Normal: 696*4kB (UEMR) 512*8kB (UEMR) 367*16kB (UEMR) 404*32kB (UEMR) 455*64kB (UEMR) 424*128kB (UEMR) 379*256kB (UMR) 327*512kB (UMR) 1*1024kB (R) 0*2048kB 0*4096kB = 374544kB Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 1 + drivers/net/wireless/ath/ath10k/wmi.c | 76 +++++++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath10k/wmi.h | 1 + 3 files changed, 72 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index b87b98617073..6e5aeed5faee 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1714,6 +1714,7 @@ void ath10k_core_destroy(struct ath10k *ar) destroy_workqueue(ar->workqueue_aux); ath10k_debug_destroy(ar); + ath10k_wmi_free_host_mem(ar); ath10k_mac_destroy(ar); } EXPORT_SYMBOL(ath10k_core_destroy); diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index ce01107ef37a..87d9de2aa8c5 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3917,6 +3917,53 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, return 0; } +static bool +ath10k_wmi_is_host_mem_allocated(struct ath10k *ar, + const struct wlan_host_mem_req **mem_reqs, + u32 num_mem_reqs) +{ + u32 req_id, num_units, unit_size, num_unit_info; + u32 pool_size; + int i, j; + bool found; + + if (ar->wmi.num_mem_chunks != num_mem_reqs) + return false; + + for (i = 0; i < num_mem_reqs; ++i) { + req_id = __le32_to_cpu(mem_reqs[i]->req_id); + num_units = __le32_to_cpu(mem_reqs[i]->num_units); + unit_size = __le32_to_cpu(mem_reqs[i]->unit_size); + num_unit_info = __le32_to_cpu(mem_reqs[i]->num_unit_info); + + if (num_unit_info & NUM_UNITS_IS_NUM_ACTIVE_PEERS) { + if (ar->num_active_peers) + num_units = ar->num_active_peers + 1; + else + num_units = ar->max_num_peers + 1; + } else if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) { + num_units = ar->max_num_peers + 1; + } else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS) { + num_units = ar->max_num_vdevs + 1; + } + + found = false; + for (j = 0; j < ar->wmi.num_mem_chunks; j++) { + if (ar->wmi.mem_chunks[j].req_id == req_id) { + pool_size = num_units * round_up(unit_size, 4); + if (ar->wmi.mem_chunks[j].len == pool_size) { + found = true; + break; + } + } + } + if (!found) + return false; + } + + return true; +} + static int ath10k_wmi_main_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb, struct wmi_svc_rdy_ev_arg *arg) @@ -3997,6 +4044,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) struct wmi_svc_rdy_ev_arg arg = {}; u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; int ret; + bool allocated; if (!skb) { ath10k_warn(ar, "invalid service ready event skb\n"); @@ -4073,6 +4121,18 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) * and WMI_SERVICE_IRAM_TIDS, etc. */ + allocated = ath10k_wmi_is_host_mem_allocated(ar, arg.mem_reqs, + num_mem_reqs); + if (allocated) + goto skip_mem_alloc; + + /* Either this event is received during boot time or there is a change + * in memory requirement from firmware when compared to last request. + * Free any old memory and do a fresh allocation based on the current + * memory requirement. + */ + ath10k_wmi_free_host_mem(ar); + for (i = 0; i < num_mem_reqs; ++i) { req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id); num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units); @@ -4108,6 +4168,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) return; } +skip_mem_alloc: ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n", __le32_to_cpu(arg.min_tx_power), @@ -6660,15 +6721,10 @@ int ath10k_wmi_attach(struct ath10k *ar) return 0; } -void ath10k_wmi_detach(struct ath10k *ar) +void ath10k_wmi_free_host_mem(struct ath10k *ar) { int i; - cancel_work_sync(&ar->svc_rdy_work); - - if (ar->svc_rdy_skb) - dev_kfree_skb(ar->svc_rdy_skb); - /* free the host memory chunks requested by firmware */ for (i = 0; i < ar->wmi.num_mem_chunks; i++) { dma_free_coherent(ar->dev, @@ -6679,3 +6735,11 @@ void ath10k_wmi_detach(struct ath10k *ar) ar->wmi.num_mem_chunks = 0; } + +void ath10k_wmi_detach(struct ath10k *ar) +{ + cancel_work_sync(&ar->svc_rdy_work); + + if (ar->svc_rdy_skb) + dev_kfree_skb(ar->svc_rdy_skb); +} diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 52d35032d53e..3e5a1591f772 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -6067,6 +6067,7 @@ struct ath10k_fw_stats_peer; int ath10k_wmi_attach(struct ath10k *ar); void ath10k_wmi_detach(struct ath10k *ar); +void ath10k_wmi_free_host_mem(struct ath10k *ar); int ath10k_wmi_wait_for_service_ready(struct ath10k *ar); int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar); -- cgit v1.2.3 From 7b7da0a02192fd518c26c46dad6b14aca4569605 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Mon, 31 Aug 2015 16:34:55 +0530 Subject: ath10k: drop probe responses when too many are queued In a noisy environment, when multiple interfaces are created, the management tx descriptors are fully occupied by the probe responses from all the interfaces. This prevents a new station from a successful association. Fix this by limiting the probe responses when the specified threshold limit is reached. Signed-off-by: Vivek Natarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 5 +++ drivers/net/wireless/ath/ath10k/core.h | 5 +++ drivers/net/wireless/ath/ath10k/htt.h | 3 +- drivers/net/wireless/ath/ath10k/htt_tx.c | 52 +++++++++++++++++++++++++++----- drivers/net/wireless/ath/ath10k/txrx.c | 14 +++++++-- 5 files changed, 68 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 6e5aeed5faee..6e5033bac2b4 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -54,6 +54,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .has_shifted_cc_wraparound = true, .otp_exe_param = 0, .channel_counters_freq_hz = 88000, + .max_probe_resp_desc_thres = 0, .fw = { .dir = QCA988X_HW_2_0_FW_DIR, .fw = QCA988X_HW_2_0_FW_FILE, @@ -70,6 +71,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .uart_pin = 6, .otp_exe_param = 0, .channel_counters_freq_hz = 88000, + .max_probe_resp_desc_thres = 0, .fw = { .dir = QCA6174_HW_2_1_FW_DIR, .fw = QCA6174_HW_2_1_FW_FILE, @@ -86,6 +88,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .uart_pin = 6, .otp_exe_param = 0, .channel_counters_freq_hz = 88000, + .max_probe_resp_desc_thres = 0, .fw = { .dir = QCA6174_HW_3_0_FW_DIR, .fw = QCA6174_HW_3_0_FW_FILE, @@ -102,6 +105,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .uart_pin = 6, .otp_exe_param = 0, .channel_counters_freq_hz = 88000, + .max_probe_resp_desc_thres = 0, .fw = { /* uses same binaries as hw3.0 */ .dir = QCA6174_HW_3_0_FW_DIR, @@ -120,6 +124,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .otp_exe_param = 0x00000700, .continuous_frag_desc = true, .channel_counters_freq_hz = 150000, + .max_probe_resp_desc_thres = 24, .fw = { .dir = QCA99X0_HW_2_0_FW_DIR, .fw = QCA99X0_HW_2_0_FW_FILE, diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 12542144fe12..04e040a06cb1 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -612,6 +612,11 @@ struct ath10k { u32 channel_counters_freq_hz; + /* Mgmt tx descriptors threshold for limiting probe response + * frames. + */ + u32 max_probe_resp_desc_thres; + struct ath10k_hw_params_fw { const char *dir; const char *fw; diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 573187512895..5a8e4eae7a9c 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1485,6 +1485,7 @@ struct ath10k_htt { spinlock_t tx_lock; int max_num_pending_tx; int num_pending_tx; + int num_pending_mgmt_tx; struct idr pending_tx; wait_queue_head_t empty_tx_wq; struct dma_pool *tx_pool; @@ -1587,7 +1588,7 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, u8 max_subfrms_ampdu, u8 max_subfrms_amsdu); -void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); +void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc); int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb); void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 43aa5e2d1b87..ea53c2151122 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -22,22 +22,28 @@ #include "txrx.h" #include "debug.h" -void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) +void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc) { + if (limit_mgmt_desc) + htt->num_pending_mgmt_tx--; + htt->num_pending_tx--; if (htt->num_pending_tx == htt->max_num_pending_tx - 1) ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); } -static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) +static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, + bool limit_mgmt_desc) { spin_lock_bh(&htt->tx_lock); - __ath10k_htt_tx_dec_pending(htt); + __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); spin_unlock_bh(&htt->tx_lock); } -static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) +static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, + bool limit_mgmt_desc, bool is_probe_resp) { + struct ath10k *ar = htt->ar; int ret = 0; spin_lock_bh(&htt->tx_lock); @@ -47,6 +53,15 @@ static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) goto exit; } + if (limit_mgmt_desc) { + if (is_probe_resp && (htt->num_pending_mgmt_tx > + ar->hw_params.max_probe_resp_desc_thres)) { + ret = -EBUSY; + goto exit; + } + htt->num_pending_mgmt_tx++; + } + htt->num_pending_tx++; if (htt->num_pending_tx == htt->max_num_pending_tx) ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); @@ -417,8 +432,19 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) int len = 0; int msdu_id = -1; int res; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; + bool limit_mgmt_desc = false; + bool is_probe_resp = false; + + if (ar->hw_params.max_probe_resp_desc_thres) { + limit_mgmt_desc = true; + + if (ieee80211_is_probe_resp(hdr->frame_control)) + is_probe_resp = true; + } + + res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp); - res = ath10k_htt_tx_inc_pending(htt); if (res) goto err; @@ -476,7 +502,7 @@ err_free_msdu_id: ath10k_htt_tx_free_msdu_id(htt, msdu_id); spin_unlock_bh(&htt->tx_lock); err_tx_dec: - ath10k_htt_tx_dec_pending(htt); + ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); err: return res; } @@ -498,8 +524,18 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) dma_addr_t paddr = 0; u32 frags_paddr = 0; struct htt_msdu_ext_desc *ext_desc = NULL; + bool limit_mgmt_desc = false; + bool is_probe_resp = false; + + if (unlikely(ieee80211_is_mgmt(hdr->frame_control)) && + ar->hw_params.max_probe_resp_desc_thres) { + limit_mgmt_desc = true; + + if (ieee80211_is_probe_resp(hdr->frame_control)) + is_probe_resp = true; + } - res = ath10k_htt_tx_inc_pending(htt); + res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp); if (res) goto err; @@ -678,7 +714,7 @@ err_free_msdu_id: ath10k_htt_tx_free_msdu_id(htt, msdu_id); spin_unlock_bh(&htt->tx_lock); err_tx_dec: - ath10k_htt_tx_dec_pending(htt); + ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); err: return res; } diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index e4a9c4c8d0cb..7db7d501726b 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -52,6 +52,9 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct ieee80211_tx_info *info; struct ath10k_skb_cb *skb_cb; struct sk_buff *msdu; + struct ieee80211_hdr *hdr; + __le16 fc; + bool limit_mgmt_desc = false; ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d success %d\n", @@ -72,14 +75,21 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, spin_unlock_bh(&htt->tx_lock); return; } + + hdr = (struct ieee80211_hdr *)msdu->data; + fc = hdr->frame_control; + + if (unlikely(ieee80211_is_mgmt(fc)) && + ar->hw_params.max_probe_resp_desc_thres) + limit_mgmt_desc = true; + ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); - __ath10k_htt_tx_dec_pending(htt); + __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); if (htt->num_pending_tx == 0) wake_up(&htt->empty_tx_wq); spin_unlock_bh(&htt->tx_lock); skb_cb = ATH10K_SKB_CB(msdu); - dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); if (skb_cb->htt.txbuf) -- cgit v1.2.3 From 707a0c811ca02861f1500f0696efebcf3bd2e2e2 Mon Sep 17 00:00:00 2001 From: Bartosz Markowski Date: Wed, 2 Sep 2015 13:20:19 +0200 Subject: ath10k: fix beamformee VHT STS capability The VHT STS CAP shall be reported by firmware to host, like in case of QCA99x0. For QCA6174 hw family this isn't set for some reason. So for this particular chips, let's assume it has the ability to support VHT NDP in up to 4 STSs (which is true by the way). Change the published beamformee STS cap accordingly to 3 or to what the firmware reports. Assumption so far, it suppose to be the num_rf_chains-1, was completely wrong. Signed-off-by: Bartosz Markowski Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 64674c955d44..3ecc448f8ed6 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4064,17 +4064,35 @@ static u32 get_nss_from_chainmask(u16 chain_mask) return 1; } +static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar) +{ + int nsts = ar->vht_cap_info; + nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; + nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; + + /* If firmware does not deliver to host number of space-time + * streams supported, assume it support up to 4 BF STS and return + * the value for VHT CAP: nsts-1) + * */ + if (nsts == 0) + return 3; + + return nsts; +} + static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif) { u32 value = 0; struct ath10k *ar = arvif->ar; + int nsts; if (ath10k_wmi_get_txbf_conf_scheme(ar) != WMI_TXBF_CONF_BEFORE_ASSOC) return 0; + nsts = ath10k_mac_get_vht_cap_bf_sts(ar); if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) - value |= SM((ar->num_rf_chains - 1), WMI_TXBF_STS_CAP_OFFSET); + value |= SM(nsts, WMI_TXBF_STS_CAP_OFFSET); if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) @@ -6804,7 +6822,7 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { - val = ar->num_rf_chains - 1; + val = ath10k_mac_get_vht_cap_bf_sts(ar); val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; -- cgit v1.2.3 From 0c6d6f2606dfe3758265fb29bfe8103e89d99bab Mon Sep 17 00:00:00 2001 From: Bartosz Markowski Date: Wed, 2 Sep 2015 13:20:20 +0200 Subject: ath10k: fix beamformer VHT sounding dimensions capability Similarly to the VHT STS, this is supposed to be propagated by firmware. In case it's not, use the default value, but as last resort. Signed-off-by: Bartosz Markowski Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 3ecc448f8ed6..989d2a154f8f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4080,11 +4080,27 @@ static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar) return nsts; } +static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar) +{ + int sound_dim = ar->vht_cap_info; + sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; + sound_dim >>=IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; + + /* If the sounding dimension is not advertised by the firmware, + * let's use a default value of 1 + */ + if (sound_dim == 0) + return 1; + + return sound_dim; +} + static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif) { u32 value = 0; struct ath10k *ar = arvif->ar; int nsts; + int sound_dim; if (ath10k_wmi_get_txbf_conf_scheme(ar) != WMI_TXBF_CONF_BEFORE_ASSOC) return 0; @@ -4094,9 +4110,10 @@ static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif) IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) value |= SM(nsts, WMI_TXBF_STS_CAP_OFFSET); + sound_dim = ath10k_mac_get_vht_cap_bf_sound_dim(ar); if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) - value |= SM((ar->num_rf_chains - 1), WMI_BF_SOUND_DIM_OFFSET); + value |= SM(sound_dim, WMI_BF_SOUND_DIM_OFFSET); if (!value) return 0; @@ -6831,7 +6848,7 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) { - val = ar->num_rf_chains - 1; + val = ath10k_mac_get_vht_cap_bf_sound_dim(ar); val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; -- cgit v1.2.3 From 6ccea107eba46fbc7de40e944bf17145c2809666 Mon Sep 17 00:00:00 2001 From: Manikanta Pubbisetty Date: Wed, 2 Sep 2015 17:05:27 +0300 Subject: ath10k: print invalid mcs reported in rx descriptor Sometimes hardware reports invalid mcs index in rx descriptor when operating in VHT80 mode and all packets with invalid mcs will be eventually dropped in mac80211. This issue is observerd during testing on QCA99X0 chipsets. This patch adds a warn message for dumping the rx desc info which helps in analysing the issue when invalid mcs is received. Signed-off-by: Manikanta Pubbisetty Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 8ba8fa9004cf..606c1a34f004 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -717,6 +717,29 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, nss = 1; } + if (mcs > 0x09) { + ath10k_warn(ar, "invalid MCS received %u\n", mcs); + ath10k_warn(ar, "rxd %08x mpdu start %08x %08x msdu start %08x %08x ppdu start %08x %08x %08x %08x %08x\n", + __le32_to_cpu(rxd->attention.flags), + __le32_to_cpu(rxd->mpdu_start.info0), + __le32_to_cpu(rxd->mpdu_start.info1), + __le32_to_cpu(rxd->msdu_start.common.info0), + __le32_to_cpu(rxd->msdu_start.common.info1), + rxd->ppdu_start.info0, + __le32_to_cpu(rxd->ppdu_start.info1), + __le32_to_cpu(rxd->ppdu_start.info2), + __le32_to_cpu(rxd->ppdu_start.info3), + __le32_to_cpu(rxd->ppdu_start.info4)); + + ath10k_warn(ar, "msdu end %08x mpdu end %08x\n", + __le32_to_cpu(rxd->msdu_end.common.info0), + __le32_to_cpu(rxd->mpdu_end.info0)); + + ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, + "rx desc msdu payload: ", + rxd->msdu_payload, 50); + } + status->rate_idx = mcs; status->vht_nss = nss; -- cgit v1.2.3 From 84567995612258c23bc55795575babe7ef605dd9 Mon Sep 17 00:00:00 2001 From: Boqun Feng Date: Wed, 26 Aug 2015 19:52:46 +0800 Subject: locking/atomics, cmpxchg: Privatize the inclusion of asm/cmpxchg.h After commit: 654672d4ba1a ("locking/atomics: Add _{acquire|release|relaxed}() variants of some atomic operations") Architectures may only provide {cmp,}xchg_relaxed definitions in asm/cmpxchg.h. Other variants, such as {cmp,}xchg, may be built in linux/atomic.h, which means simply including asm/cmpxchg.h may not get the definitions of all the{cmp,}xchg variants. Therefore, we should privatize the inclusions of asm/cmpxchg.h to keep it only included in arch/* and replace the inclusions outside with linux/atomic.h Signed-off-by: Boqun Feng Signed-off-by: Peter Zijlstra (Intel) Acked-by: Greg Kroah-Hartman Acked-by: Will Deacon Cc: Andrew Morton Cc: Aybuke Ozdemir Cc: Chris Brannon Cc: Davidlohr Bueso Cc: Greg Kroah-Hartman Cc: Jonathan Corbet Cc: Kirk Reiser Cc: Kishon Vijay Abraham I Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Samuel Thibault Cc: Shradha Shah Cc: Thomas Gleixner Cc: William Hubbs Cc: devel@driverdev.osuosl.org Cc: linux-net-drivers@solarflare.com Cc: speakup@linux-speakup.org Link: http://lkml.kernel.org/r/1440589966-26280-1-git-send-email-boqun.feng@gmail.com Signed-off-by: Ingo Molnar --- drivers/net/ethernet/sfc/mcdi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 98d172b04f71..a9b9460de0d6 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include "net_driver.h" #include "nic.h" #include "io.h" -- cgit v1.2.3 From b7503e0cdb5dbec5d201aa69d8888c14679b5ae8 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Wed, 2 Sep 2015 13:58:35 -0700 Subject: net: Add FIB table id to rtable Add the FIB table id to rtable to make the information available for IPv4 as it is for IPv6. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index e7094fbd7568..8c9ab5ebea23 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -320,6 +320,7 @@ static void vrf_rtable_destroy(struct net_vrf *vrf) static struct rtable *vrf_rtable_create(struct net_device *dev) { + struct net_vrf *vrf = netdev_priv(dev); struct rtable *rth; rth = dst_alloc(&vrf_dst_ops, dev, 2, @@ -335,6 +336,7 @@ static struct rtable *vrf_rtable_create(struct net_device *dev) rth->rt_pmtu = 0; rth->rt_gateway = 0; rth->rt_uses_gateway = 0; + rth->rt_table_id = vrf->tb_id; INIT_LIST_HEAD(&rth->rt_uncached); rth->rt_uncached_list = NULL; } -- cgit v1.2.3 From 70cc99d10ca17b8688575d2579e5a2f6c4fa6f29 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Sep 2015 14:34:10 -0400 Subject: net: dsa: mv88e6xxx: extract FID write from ATU command Not every ATU commands apply to an FID, thus remove the FID writing from mv88e6xxx_atu_cmd and write it explicitly where needed, in order to ease introduction of such commands. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 6f13f7206762..bf455f9abf8b 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1036,14 +1036,10 @@ out: return ret; } -static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd) +static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 cmd) { int ret; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); - if (ret < 0) - return ret; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_OP, cmd); if (ret < 0) return ret; @@ -1059,7 +1055,11 @@ static int _mv88e6xxx_flush_fid(struct dsa_switch *ds, int fid) if (ret < 0) return ret; - return _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_FLUSH_NON_STATIC_DB); + ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); + if (ret < 0) + return ret; + + return _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_FLUSH_NON_STATIC_DB); } static int mv88e6xxx_set_port_state(struct dsa_switch *ds, int port, u8 state) @@ -1793,7 +1793,11 @@ static int _mv88e6xxx_atu_load(struct dsa_switch *ds, if (ret < 0) return ret; - return _mv88e6xxx_atu_cmd(ds, entry->fid, GLOBAL_ATU_OP_LOAD_DB); + ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, entry->fid); + if (ret < 0) + return ret; + + return _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_LOAD_DB); } static int _mv88e6xxx_port_vid_to_fid(struct dsa_switch *ds, int port, u16 vid) @@ -1884,7 +1888,11 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, if (ret < 0) return ret; - ret = _mv88e6xxx_atu_cmd(ds, fid, GLOBAL_ATU_OP_GET_NEXT_DB); + ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); + if (ret < 0) + return ret; + + ret = _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_GET_NEXT_DB); if (ret < 0) return ret; @@ -2308,9 +2316,15 @@ static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds, return ret; do { - ret = _mv88e6xxx_atu_cmd(ds, dbnum, GLOBAL_ATU_OP_GET_NEXT_DB); + ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, + dbnum); if (ret < 0) return ret; + + ret = _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_GET_NEXT_DB); + if (ret < 0) + return ret; + data = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA); if (data < 0) return data; -- cgit v1.2.3 From 37705b731500b0ce9fb4ead21a7cdfc241a401fe Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Sep 2015 14:34:11 -0400 Subject: net: dsa: mv88e6xxx: extract ATU data write access Other ATU commands need to write the ATU data register. To ease the introduction of such commands, extract the ATU data write access from _mv88e6xxx_atu_load to its own function. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index bf455f9abf8b..25e103c5ed16 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1047,6 +1047,29 @@ static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, u16 cmd) return _mv88e6xxx_atu_wait(ds); } +static int _mv88e6xxx_atu_data_write(struct dsa_switch *ds, + struct mv88e6xxx_atu_entry *entry) +{ + u16 data = entry->state & GLOBAL_ATU_DATA_STATE_MASK; + + if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) { + unsigned int mask, shift; + + if (entry->trunk) { + data |= GLOBAL_ATU_DATA_TRUNK; + mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK; + shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT; + } else { + mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK; + shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT; + } + + data |= (entry->portv_trunkid << shift) & mask; + } + + return _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, data); +} + static int _mv88e6xxx_flush_fid(struct dsa_switch *ds, int fid) { int ret; @@ -1761,7 +1784,6 @@ static int _mv88e6xxx_atu_mac_read(struct dsa_switch *ds, unsigned char *addr) static int _mv88e6xxx_atu_load(struct dsa_switch *ds, struct mv88e6xxx_atu_entry *entry) { - u16 reg = 0; int ret; ret = _mv88e6xxx_atu_wait(ds); @@ -1772,24 +1794,7 @@ static int _mv88e6xxx_atu_load(struct dsa_switch *ds, if (ret < 0) return ret; - if (entry->state != GLOBAL_ATU_DATA_STATE_UNUSED) { - unsigned int mask, shift; - - if (entry->trunk) { - reg |= GLOBAL_ATU_DATA_TRUNK; - mask = GLOBAL_ATU_DATA_TRUNK_ID_MASK; - shift = GLOBAL_ATU_DATA_TRUNK_ID_SHIFT; - } else { - mask = GLOBAL_ATU_DATA_PORT_VECTOR_MASK; - shift = GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT; - } - - reg |= (entry->portv_trunkid << shift) & mask; - } - - reg |= entry->state & GLOBAL_ATU_DATA_STATE_MASK; - - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, reg); + ret = _mv88e6xxx_atu_data_write(ds, entry); if (ret < 0) return ret; -- cgit v1.2.3 From 7fb5e755153d7b40dd321f7c766dbd4e76c66711 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Sep 2015 14:34:12 -0400 Subject: net: dsa: mv88e6xxx: rework ATU Flush operation These Marvell switches have 4 operations to flush or (re)move, all or only non-static MAC addresses, from the entire set of databases or from just a particular one. The value of the EntryState bits will determine if the operation is either a Flush (0x0) or a Move (0xF). When moving entries from one port to another, entries will be removed if the destination port is 0xF. This patch renames these operations for consistency, add a new generic _mv88e6xxx_atu_flush_move function, and change _mv88e6xxx_flush_fid to use it. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 49 ++++++++++++++++++++++++++++++++++++--------- drivers/net/dsa/mv88e6xxx.h | 8 ++++---- 2 files changed, 44 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 25e103c5ed16..c67090f0814d 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1070,19 +1070,50 @@ static int _mv88e6xxx_atu_data_write(struct dsa_switch *ds, return _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_DATA, data); } -static int _mv88e6xxx_flush_fid(struct dsa_switch *ds, int fid) +static int _mv88e6xxx_atu_flush_move(struct dsa_switch *ds, + struct mv88e6xxx_atu_entry *entry, + bool static_too) { - int ret; + int op; + int err; - ret = _mv88e6xxx_atu_wait(ds); - if (ret < 0) - return ret; + err = _mv88e6xxx_atu_wait(ds); + if (err) + return err; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); - if (ret < 0) - return ret; + err = _mv88e6xxx_atu_data_write(ds, entry); + if (err) + return err; + + if (entry->fid) { + err = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, + entry->fid); + if (err) + return err; + + op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB : + GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB; + } else { + op = static_too ? GLOBAL_ATU_OP_FLUSH_MOVE_ALL : + GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC; + } + + return _mv88e6xxx_atu_cmd(ds, op); +} - return _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_FLUSH_NON_STATIC_DB); +static int _mv88e6xxx_atu_flush(struct dsa_switch *ds, u16 fid, bool static_too) +{ + struct mv88e6xxx_atu_entry entry = { + .fid = fid, + .state = 0, /* EntryState bits must be 0 */ + }; + + return _mv88e6xxx_atu_flush_move(ds, &entry, static_too); +} + +static int _mv88e6xxx_flush_fid(struct dsa_switch *ds, int fid) +{ + return _mv88e6xxx_atu_flush(ds, fid, false); } static int mv88e6xxx_set_port_state(struct dsa_switch *ds, int port, u8 state) diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 9b6f3d9d5ae1..1cf3cf887902 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -226,12 +226,12 @@ #define GLOBAL_ATU_OP 0x0b #define GLOBAL_ATU_OP_BUSY BIT(15) #define GLOBAL_ATU_OP_NOP (0 << 12) -#define GLOBAL_ATU_OP_FLUSH_ALL ((1 << 12) | GLOBAL_ATU_OP_BUSY) -#define GLOBAL_ATU_OP_FLUSH_NON_STATIC ((2 << 12) | GLOBAL_ATU_OP_BUSY) +#define GLOBAL_ATU_OP_FLUSH_MOVE_ALL ((1 << 12) | GLOBAL_ATU_OP_BUSY) +#define GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC ((2 << 12) | GLOBAL_ATU_OP_BUSY) #define GLOBAL_ATU_OP_LOAD_DB ((3 << 12) | GLOBAL_ATU_OP_BUSY) #define GLOBAL_ATU_OP_GET_NEXT_DB ((4 << 12) | GLOBAL_ATU_OP_BUSY) -#define GLOBAL_ATU_OP_FLUSH_DB ((5 << 12) | GLOBAL_ATU_OP_BUSY) -#define GLOBAL_ATU_OP_FLUSH_NON_STATIC_DB ((6 << 12) | GLOBAL_ATU_OP_BUSY) +#define GLOBAL_ATU_OP_FLUSH_MOVE_ALL_DB ((5 << 12) | GLOBAL_ATU_OP_BUSY) +#define GLOBAL_ATU_OP_FLUSH_MOVE_NON_STATIC_DB ((6 << 12) | GLOBAL_ATU_OP_BUSY) #define GLOBAL_ATU_OP_GET_CLR_VIOLATION ((7 << 12) | GLOBAL_ATU_OP_BUSY) #define GLOBAL_ATU_DATA 0x0c #define GLOBAL_ATU_DATA_TRUNK BIT(15) -- cgit v1.2.3 From c161d0a5edf35dfbb18e859825355791dd6fb2cc Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Sep 2015 14:34:13 -0400 Subject: net: dsa: mv88e6xxx: flush ATU on initial setup Purge all MAC addresses from the entire set of address databases when the driver initializes the device. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index c67090f0814d..38c8d4ab296e 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -2685,6 +2685,11 @@ int mv88e6xxx_setup_global(struct dsa_switch *ds) if (ret < 0) goto unlock; + /* Clear all ATU entries */ + ret = _mv88e6xxx_atu_flush(ds, 0, true); + if (ret < 0) + goto unlock; + /* Clear all the VTU and STU entries */ ret = _mv88e6xxx_vtu_stu_flush(ds); unlock: -- cgit v1.2.3 From 7c400018c003d221a2db1ce46a5b88d7a37add1c Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Sep 2015 14:34:14 -0400 Subject: net: dsa: mv88e6xxx: flush all addresses when adding a VLAN When choosing an address database for a new VLAN, flush every entries, not only the non-static ones. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 38c8d4ab296e..88d669c9a200 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1630,7 +1630,8 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid, return -ENOSPC; } - err = _mv88e6xxx_flush_fid(ds, vlan.fid); + /* Clear all MAC addresses from the new database */ + err = _mv88e6xxx_atu_flush(ds, vlan.fid, true); if (err) return err; -- cgit v1.2.3 From 9f4d55d2869d86bd5dc59ff28109f7fefedc325d Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Sep 2015 14:34:15 -0400 Subject: net: dsa: mv88e6xxx: remove addresses when a port leaves a VLAN Add a new _mv88e6xxx_atu_move function to prepare the ATU data register for the move operation. The ports vector will contain the source port and destination port of the Move operation. If the destination port is 0xF, the MAC addresses mapped to the source port are removed for the address database(s). Then add a _mv88e6xxx_atu_remove wrapper to remove the MAC addresses from a VLAN database that are mapped to a given port, when it leaves it. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 88d669c9a200..63407a1bf81e 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1116,6 +1116,31 @@ static int _mv88e6xxx_flush_fid(struct dsa_switch *ds, int fid) return _mv88e6xxx_atu_flush(ds, fid, false); } +static int _mv88e6xxx_atu_move(struct dsa_switch *ds, u16 fid, int from_port, + int to_port, bool static_too) +{ + struct mv88e6xxx_atu_entry entry = { + .trunk = false, + .fid = fid, + }; + + /* EntryState bits must be 0xF */ + entry.state = GLOBAL_ATU_DATA_STATE_MASK; + + /* ToPort and FromPort are respectively in PortVec bits 7:4 and 3:0 */ + entry.portv_trunkid = (to_port & 0x0f) << 4; + entry.portv_trunkid |= from_port & 0x0f; + + return _mv88e6xxx_atu_flush_move(ds, &entry, static_too); +} + +static int _mv88e6xxx_atu_remove(struct dsa_switch *ds, u16 fid, int port, + bool static_too) +{ + /* Destination port 0xF means remove the entries */ + return _mv88e6xxx_atu_move(ds, fid, port, 0x0f, static_too); +} + static int mv88e6xxx_set_port_state(struct dsa_switch *ds, int port, u8 state) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); @@ -1708,6 +1733,10 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) if (err) goto unlock; + err = _mv88e6xxx_atu_remove(ds, vlan.fid, port, false); + if (err) + goto unlock; + if (!keep) clear_bit(vlan.fid, ps->fid_bitmap); -- cgit v1.2.3 From 2b8157b1c20bdac0e0b856b2cb1499c7f18f2b07 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 4 Sep 2015 14:34:16 -0400 Subject: net: dsa: mv88e6xxx: remove all MACs when disabling a port When we're moving a port from Learning or Forwarding state to Disabled or Blocking or Listening state, remove all non-static MAC addresses mapped to this port in the entire set of databases, not only one. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 63407a1bf81e..30227ca2d5db 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1163,7 +1163,7 @@ static int mv88e6xxx_set_port_state(struct dsa_switch *ds, int port, u8 state) */ if (oldstate >= PORT_CONTROL_STATE_LEARNING && state <= PORT_CONTROL_STATE_BLOCKING) { - ret = _mv88e6xxx_flush_fid(ds, ps->fid[port]); + ret = _mv88e6xxx_atu_remove(ds, 0, port, false); if (ret) goto abort; } -- cgit v1.2.3 From 1d147ccbfc35d7d45c87fb0c767e6e40c316aa32 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Mon, 7 Sep 2015 15:16:44 +0530 Subject: drivers: net: cpsw: Add support to drive gpios for ethernet to be functional In DRA72x EVM, by default slave 1 is connected to the onboard phy, but slave 2 pins are also muxed with video input module which is controlled by pcf857x gpio and currently to select slave 0 to connect to phy gpio hogging is used, but with omap2plus_defconfig the pcf857x gpio is built as module. So when using NFS on DRA72x EVM, board doesn't boot as gpio hogging do not set proper gpio state to connect slave 0 to phy as it is built as module and you do not see any errors for not setting gpio and just mentions dhcp reply not got. To solve this issue, introducing "mode-gpios" in DT when gpio based muxing is required. This will throw a warning when gpio get fails and returns probe defer. When gpio-pcf857x module is installed, cpsw probes again and ethernet becomes functional. Verified this on DRA72x with pcf as module and ramdisk. Signed-off-by: Mugunthan V N Acked-by: Tony Lindgren Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 8fc90f1c872c..c670317f3cb0 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -2207,6 +2208,7 @@ static int cpsw_probe(struct platform_device *pdev) void __iomem *ss_regs; struct resource *res, *ss_res; const struct of_device_id *of_id; + struct gpio_descs *mode; u32 slave_offset, sliver_offset, slave_size; int ret = 0, i; int irq; @@ -2232,6 +2234,13 @@ static int cpsw_probe(struct platform_device *pdev) goto clean_ndev_ret; } + mode = devm_gpiod_get_array_optional(&pdev->dev, "mode", GPIOD_OUT_LOW); + if (IS_ERR(mode)) { + ret = PTR_ERR(mode); + dev_err(&pdev->dev, "gpio request failed, ret %d\n", ret); + goto clean_ndev_ret; + } + /* * This may be required here for child devices. */ -- cgit v1.2.3 From c40a2c8817e42273a4627c48c884b805475a733f Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 7 Sep 2015 16:05:38 +0200 Subject: CDC: common parser for extra headers CDC drivers all implement their own parser for the extra headers. This patch fixes the code duplication introducing a single common parser in usbnet. Signed-off-by: Oliver Neukum Signed-off-by: David S. Miller --- drivers/net/usb/usbnet.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index b4cf10781348..060918f49fea 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -1962,6 +1963,143 @@ out: return err; } +int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, + struct usb_interface *intf, + u8 *buffer, + int buflen) +{ + /* duplicates are ignored */ + struct usb_cdc_union_desc *union_header = NULL; + + /* duplicates are not tolerated */ + struct usb_cdc_header_desc *header = NULL; + struct usb_cdc_ether_desc *ether = NULL; + struct usb_cdc_mdlm_detail_desc *detail = NULL; + struct usb_cdc_mdlm_desc *desc = NULL; + + unsigned int elength; + int cnt = 0; + + memset(hdr, 0x00, sizeof(struct usb_cdc_parsed_header)); + hdr->phonet_magic_present = false; + while (buflen > 0) { + elength = buffer[0]; + if (!elength) { + dev_err(&intf->dev, "skipping garbage byte\n"); + elength = 1; + goto next_desc; + } + if (buffer[1] != USB_DT_CS_INTERFACE) { + dev_err(&intf->dev, "skipping garbage\n"); + goto next_desc; + } + + switch (buffer[2]) { + case USB_CDC_UNION_TYPE: /* we've found it */ + if (elength < sizeof(struct usb_cdc_union_desc)) + goto next_desc; + if (union_header) { + dev_err(&intf->dev, "More than one union descriptor, skipping ...\n"); + goto next_desc; + } + union_header = (struct usb_cdc_union_desc *)buffer; + break; + case USB_CDC_COUNTRY_TYPE: + if (elength < sizeof(struct usb_cdc_country_functional_desc)) + goto next_desc; + hdr->usb_cdc_country_functional_desc = + (struct usb_cdc_country_functional_desc *)buffer; + break; + case USB_CDC_HEADER_TYPE: + if (elength != sizeof(struct usb_cdc_header_desc)) + goto next_desc; + if (header) + return -EINVAL; + header = (struct usb_cdc_header_desc *)buffer; + break; + case USB_CDC_ACM_TYPE: + if (elength < sizeof(struct usb_cdc_acm_descriptor)) + goto next_desc; + hdr->usb_cdc_acm_descriptor = + (struct usb_cdc_acm_descriptor *)buffer; + break; + case USB_CDC_ETHERNET_TYPE: + if (elength != sizeof(struct usb_cdc_ether_desc)) + goto next_desc; + if (ether) + return -EINVAL; + ether = (struct usb_cdc_ether_desc *)buffer; + break; + case USB_CDC_CALL_MANAGEMENT_TYPE: + if (elength < sizeof(struct usb_cdc_call_mgmt_descriptor)) + goto next_desc; + hdr->usb_cdc_call_mgmt_descriptor = + (struct usb_cdc_call_mgmt_descriptor *)buffer; + break; + case USB_CDC_DMM_TYPE: + if (elength < sizeof(struct usb_cdc_dmm_desc)) + goto next_desc; + hdr->usb_cdc_dmm_desc = + (struct usb_cdc_dmm_desc *)buffer; + break; + case USB_CDC_MDLM_TYPE: + if (elength < sizeof(struct usb_cdc_mdlm_desc *)) + goto next_desc; + if (desc) + return -EINVAL; + desc = (struct usb_cdc_mdlm_desc *)buffer; + break; + case USB_CDC_MDLM_DETAIL_TYPE: + if (elength < sizeof(struct usb_cdc_mdlm_detail_desc *)) + goto next_desc; + if (detail) + return -EINVAL; + detail = (struct usb_cdc_mdlm_detail_desc *)buffer; + break; + case USB_CDC_NCM_TYPE: + if (elength < sizeof(struct usb_cdc_ncm_desc)) + goto next_desc; + hdr->usb_cdc_ncm_desc = (struct usb_cdc_ncm_desc *)buffer; + break; + case USB_CDC_MBIM_TYPE: + if (elength < sizeof(struct usb_cdc_mbim_desc)) + goto next_desc; + + hdr->usb_cdc_mbim_desc = (struct usb_cdc_mbim_desc *)buffer; + break; + case USB_CDC_MBIM_EXTENDED_TYPE: + if (elength < sizeof(struct usb_cdc_mbim_extended_desc)) + break; + hdr->usb_cdc_mbim_extended_desc = + (struct usb_cdc_mbim_extended_desc *)buffer; + break; + case CDC_PHONET_MAGIC_NUMBER: + hdr->phonet_magic_present = true; + break; + default: + /* + * there are LOTS more CDC descriptors that + * could legitimately be found here. + */ + dev_dbg(&intf->dev, "Ignoring descriptor: type %02x, length %ud\n", + buffer[2], elength); + goto next_desc; + } + cnt++; +next_desc: + buflen -= elength; + buffer += elength; + } + hdr->usb_cdc_union_desc = union_header; + hdr->usb_cdc_header_desc = header; + hdr->usb_cdc_mdlm_detail_desc = detail; + hdr->usb_cdc_mdlm_desc = desc; + hdr->usb_cdc_ether_desc = ether; + return cnt; +} + +EXPORT_SYMBOL(cdc_parse_cdc_header); + /* * The function can't be called inside suspend/resume callback, * otherwise deadlock will be caused. -- cgit v1.2.3 From 77b0a099674ac1c43b631445d8d50453e4805b29 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 7 Sep 2015 16:05:39 +0200 Subject: cdc-ncm: use common parser This moves cdc-ncm to the common parser for CDC user to reduce code duplication. Signed-off-by: Oliver Neukum Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ncm.c | 69 +++++++---------------------------------------- 1 file changed, 9 insertions(+), 60 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index db40175b1a0b..a187f08113ec 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -698,6 +698,7 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ int len; int temp; u8 iface_no; + struct usb_cdc_parsed_header hdr; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) @@ -722,66 +723,14 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_ len = intf->cur_altsetting->extralen; /* parse through descriptors associated with control interface */ - while ((len > 0) && (buf[0] > 2) && (buf[0] <= len)) { - - if (buf[1] != USB_DT_CS_INTERFACE) - goto advance; - - switch (buf[2]) { - case USB_CDC_UNION_TYPE: - if (buf[0] < sizeof(*union_desc)) - break; - - union_desc = (const struct usb_cdc_union_desc *)buf; - /* the master must be the interface we are probing */ - if (intf->cur_altsetting->desc.bInterfaceNumber != - union_desc->bMasterInterface0) { - dev_dbg(&intf->dev, "bogus CDC Union\n"); - goto error; - } - ctx->data = usb_ifnum_to_if(dev->udev, - union_desc->bSlaveInterface0); - break; - - case USB_CDC_ETHERNET_TYPE: - if (buf[0] < sizeof(*(ctx->ether_desc))) - break; - - ctx->ether_desc = - (const struct usb_cdc_ether_desc *)buf; - break; - - case USB_CDC_NCM_TYPE: - if (buf[0] < sizeof(*(ctx->func_desc))) - break; - - ctx->func_desc = (const struct usb_cdc_ncm_desc *)buf; - break; - - case USB_CDC_MBIM_TYPE: - if (buf[0] < sizeof(*(ctx->mbim_desc))) - break; - - ctx->mbim_desc = (const struct usb_cdc_mbim_desc *)buf; - break; - - case USB_CDC_MBIM_EXTENDED_TYPE: - if (buf[0] < sizeof(*(ctx->mbim_extended_desc))) - break; - - ctx->mbim_extended_desc = - (const struct usb_cdc_mbim_extended_desc *)buf; - break; - - default: - break; - } -advance: - /* advance to next descriptor */ - temp = buf[0]; - buf += temp; - len -= temp; - } + cdc_parse_cdc_header(&hdr, intf, buf, len); + + ctx->data = usb_ifnum_to_if(dev->udev, + hdr.usb_cdc_union_desc->bSlaveInterface0); + ctx->ether_desc = hdr.usb_cdc_ether_desc; + ctx->func_desc = hdr.usb_cdc_ncm_desc; + ctx->mbim_desc = hdr.usb_cdc_mbim_desc; + ctx->mbim_extended_desc = hdr.usb_cdc_mbim_extended_desc; /* some buggy devices have an IAD but no CDC Union */ if (!union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) { -- cgit v1.2.3 From 823bd3433424aa959499e6fd8f2da842430a8d42 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 7 Sep 2015 16:05:40 +0200 Subject: cdc-ether: switch to common CDC parser This patch uses the common parser to parse extra CDC headers in order to reduce code duplication. Signed-off-by: Oliver Neukum Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ether.c | 230 ++++++++++++++++---------------------------- 1 file changed, 81 insertions(+), 149 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 35a2bffe848a..c78d3cb1b464 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -112,8 +112,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) int rndis; bool android_rndis_quirk = false; struct usb_driver *driver = driver_of(intf); - struct usb_cdc_mdlm_desc *desc = NULL; - struct usb_cdc_mdlm_detail_desc *detail = NULL; + struct usb_cdc_parsed_header header; if (sizeof(dev->data) < sizeof(*info)) return -EDOM; @@ -155,156 +154,89 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) memset(info, 0, sizeof(*info)); info->control = intf; - while (len > 3) { - if (buf[1] != USB_DT_CS_INTERFACE) - goto next_desc; - - /* use bDescriptorSubType to identify the CDC descriptors. - * We expect devices with CDC header and union descriptors. - * For CDC Ethernet we need the ethernet descriptor. - * For RNDIS, ignore two (pointless) CDC modem descriptors - * in favor of a complicated OID-based RPC scheme doing what - * CDC Ethernet achieves with a simple descriptor. - */ - switch (buf[2]) { - case USB_CDC_HEADER_TYPE: - if (info->header) { - dev_dbg(&intf->dev, "extra CDC header\n"); - goto bad_desc; - } - info->header = (void *) buf; - if (info->header->bLength != sizeof(*info->header)) { - dev_dbg(&intf->dev, "CDC header len %u\n", - info->header->bLength); - goto bad_desc; - } - break; - case USB_CDC_ACM_TYPE: - /* paranoia: disambiguate a "real" vendor-specific - * modem interface from an RNDIS non-modem. - */ - if (rndis) { - struct usb_cdc_acm_descriptor *acm; - - acm = (void *) buf; - if (acm->bmCapabilities) { - dev_dbg(&intf->dev, - "ACM capabilities %02x, " - "not really RNDIS?\n", - acm->bmCapabilities); - goto bad_desc; - } - } - break; - case USB_CDC_UNION_TYPE: - if (info->u) { - dev_dbg(&intf->dev, "extra CDC union\n"); - goto bad_desc; - } - info->u = (void *) buf; - if (info->u->bLength != sizeof(*info->u)) { - dev_dbg(&intf->dev, "CDC union len %u\n", - info->u->bLength); - goto bad_desc; - } - - /* we need a master/control interface (what we're - * probed with) and a slave/data interface; union - * descriptors sort this all out. - */ - info->control = usb_ifnum_to_if(dev->udev, - info->u->bMasterInterface0); - info->data = usb_ifnum_to_if(dev->udev, - info->u->bSlaveInterface0); - if (!info->control || !info->data) { - dev_dbg(&intf->dev, - "master #%u/%p slave #%u/%p\n", - info->u->bMasterInterface0, - info->control, - info->u->bSlaveInterface0, - info->data); - /* fall back to hard-wiring for RNDIS */ - if (rndis) { - android_rndis_quirk = true; - goto next_desc; - } - goto bad_desc; - } - if (info->control != intf) { - dev_dbg(&intf->dev, "bogus CDC Union\n"); - /* Ambit USB Cable Modem (and maybe others) - * interchanges master and slave interface. - */ - if (info->data == intf) { - info->data = info->control; - info->control = intf; - } else - goto bad_desc; - } - - /* some devices merge these - skip class check */ - if (info->control == info->data) - goto next_desc; - - /* a data interface altsetting does the real i/o */ - d = &info->data->cur_altsetting->desc; - if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { - dev_dbg(&intf->dev, "slave class %u\n", - d->bInterfaceClass); - goto bad_desc; - } - break; - case USB_CDC_ETHERNET_TYPE: - if (info->ether) { - dev_dbg(&intf->dev, "extra CDC ether\n"); - goto bad_desc; - } - info->ether = (void *) buf; - if (info->ether->bLength != sizeof(*info->ether)) { - dev_dbg(&intf->dev, "CDC ether len %u\n", - info->ether->bLength); - goto bad_desc; - } - dev->hard_mtu = le16_to_cpu( - info->ether->wMaxSegmentSize); - /* because of Zaurus, we may be ignoring the host - * side link address we were given. - */ - break; - case USB_CDC_MDLM_TYPE: - if (desc) { - dev_dbg(&intf->dev, "extra MDLM descriptor\n"); - goto bad_desc; - } - - desc = (void *)buf; - - if (desc->bLength != sizeof(*desc)) - goto bad_desc; - - if (memcmp(&desc->bGUID, mbm_guid, 16)) - goto bad_desc; - break; - case USB_CDC_MDLM_DETAIL_TYPE: - if (detail) { - dev_dbg(&intf->dev, "extra MDLM detail descriptor\n"); - goto bad_desc; - } - - detail = (void *)buf; - - if (detail->bGuidDescriptorType == 0) { - if (detail->bLength < (sizeof(*detail) + 1)) - goto bad_desc; - } else - goto bad_desc; - break; + + cdc_parse_cdc_header(&header, intf, buf, len); + + info->u = header.usb_cdc_union_desc; + info->header = header.usb_cdc_header_desc; + info->ether = header.usb_cdc_ether_desc; + /* we need a master/control interface (what we're + * probed with) and a slave/data interface; union + * descriptors sort this all out. + */ + info->control = usb_ifnum_to_if(dev->udev, + info->u->bMasterInterface0); + info->data = usb_ifnum_to_if(dev->udev, + info->u->bSlaveInterface0); + if (!info->control || !info->data) { + dev_dbg(&intf->dev, + "master #%u/%p slave #%u/%p\n", + info->u->bMasterInterface0, + info->control, + info->u->bSlaveInterface0, + info->data); + /* fall back to hard-wiring for RNDIS */ + if (rndis) { + android_rndis_quirk = true; + goto skip; } -next_desc: - len -= buf[0]; /* bLength */ - buf += buf[0]; + goto bad_desc; + } + if (info->control != intf) { + dev_dbg(&intf->dev, "bogus CDC Union\n"); + /* Ambit USB Cable Modem (and maybe others) + * interchanges master and slave interface. + */ + if (info->data == intf) { + info->data = info->control; + info->control = intf; + } else + goto bad_desc; + } + + /* some devices merge these - skip class check */ + if (info->control == info->data) + goto skip; + + /* a data interface altsetting does the real i/o */ + d = &info->data->cur_altsetting->desc; + if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { + dev_dbg(&intf->dev, "slave class %u\n", + d->bInterfaceClass); + goto bad_desc; + } +skip: + if ( rndis && + header.usb_cdc_acm_descriptor && + header.usb_cdc_acm_descriptor->bmCapabilities) { + dev_dbg(&intf->dev, + "ACM capabilities %02x, not really RNDIS?\n", + header.usb_cdc_acm_descriptor->bmCapabilities); + goto bad_desc; } + if (header.usb_cdc_ether_desc) { + dev->hard_mtu = le16_to_cpu(info->ether->wMaxSegmentSize); + /* because of Zaurus, we may be ignoring the host + * side link address we were given. + */ + } + + if (header.usb_cdc_mdlm_desc && + memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) { + dev_dbg(&intf->dev, "GUID doesn't match\n"); + goto bad_desc; + } + + if (header.usb_cdc_mdlm_detail_desc && + header.usb_cdc_mdlm_detail_desc->bLength < + (sizeof(struct usb_cdc_mdlm_detail_desc) + 1)) { + dev_dbg(&intf->dev, "Descriptor too short\n"); + goto bad_desc; + } + + + /* Microsoft ActiveSync based and some regular RNDIS devices lack the * CDC descriptors, so we'll hard-wire the interfaces and not check * for descriptors. -- cgit v1.2.3 From 8492ed45aa5dbb5c4f0786f90ff12d8511615505 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 7 Sep 2015 16:05:41 +0200 Subject: qmi-wwan: use common parser This moves qmi-wwan to the common parser for CDC user to reduce code duplication. Signed-off-by: Oliver Neukum Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 66 +++++----------------------------------------- 1 file changed, 6 insertions(+), 60 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 355842b85ee9..4752e69de00e 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -229,11 +229,11 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) u8 *buf = intf->cur_altsetting->extra; int len = intf->cur_altsetting->extralen; struct usb_interface_descriptor *desc = &intf->cur_altsetting->desc; - struct usb_cdc_union_desc *cdc_union = NULL; - struct usb_cdc_ether_desc *cdc_ether = NULL; - u32 found = 0; + struct usb_cdc_union_desc *cdc_union; + struct usb_cdc_ether_desc *cdc_ether; struct usb_driver *driver = driver_of(intf); struct qmi_wwan_state *info = (void *)&dev->data; + struct usb_cdc_parsed_header hdr; BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state))); @@ -243,63 +243,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) info->data = intf; /* and a number of CDC descriptors */ - while (len > 3) { - struct usb_descriptor_header *h = (void *)buf; - - /* ignore any misplaced descriptors */ - if (h->bDescriptorType != USB_DT_CS_INTERFACE) - goto next_desc; - - /* buf[2] is CDC descriptor subtype */ - switch (buf[2]) { - case USB_CDC_HEADER_TYPE: - if (found & 1 << USB_CDC_HEADER_TYPE) { - dev_dbg(&intf->dev, "extra CDC header\n"); - goto err; - } - if (h->bLength != sizeof(struct usb_cdc_header_desc)) { - dev_dbg(&intf->dev, "CDC header len %u\n", - h->bLength); - goto err; - } - break; - case USB_CDC_UNION_TYPE: - if (found & 1 << USB_CDC_UNION_TYPE) { - dev_dbg(&intf->dev, "extra CDC union\n"); - goto err; - } - if (h->bLength != sizeof(struct usb_cdc_union_desc)) { - dev_dbg(&intf->dev, "CDC union len %u\n", - h->bLength); - goto err; - } - cdc_union = (struct usb_cdc_union_desc *)buf; - break; - case USB_CDC_ETHERNET_TYPE: - if (found & 1 << USB_CDC_ETHERNET_TYPE) { - dev_dbg(&intf->dev, "extra CDC ether\n"); - goto err; - } - if (h->bLength != sizeof(struct usb_cdc_ether_desc)) { - dev_dbg(&intf->dev, "CDC ether len %u\n", - h->bLength); - goto err; - } - cdc_ether = (struct usb_cdc_ether_desc *)buf; - break; - } - - /* Remember which CDC functional descriptors we've seen. Works - * for all types we care about, of which USB_CDC_ETHERNET_TYPE - * (0x0f) is the highest numbered - */ - if (buf[2] < 32) - found |= 1 << buf[2]; - -next_desc: - len -= h->bLength; - buf += h->bLength; - } + cdc_parse_cdc_header(&hdr, intf, buf, len); + cdc_union = hdr.usb_cdc_union_desc; + cdc_ether = hdr.usb_cdc_ether_desc; /* Use separate control and data interfaces if we found a CDC Union */ if (cdc_union) { -- cgit v1.2.3 From 7b6ee48d3f4d432bfa6c9c9662fbdbd97681240e Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 7 Sep 2015 16:05:42 +0200 Subject: cdc-phonet: use common parser This moves cdc-phonet to the common parser for CDC users to reduce code duplication. Signed-off-by: Oliver Neukum Signed-off-by: David S. Miller --- drivers/net/usb/cdc-phonet.c | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index 415ce8b882c6..ff2270ead2e6 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -340,32 +340,13 @@ static int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *i u8 *data; int phonet = 0; int len, err; + struct usb_cdc_parsed_header hdr; data = intf->altsetting->extra; len = intf->altsetting->extralen; - while (len >= 3) { - u8 dlen = data[0]; - if (dlen < 3) - return -EINVAL; - - /* bDescriptorType */ - if (data[1] == USB_DT_CS_INTERFACE) { - /* bDescriptorSubType */ - switch (data[2]) { - case USB_CDC_UNION_TYPE: - if (union_header || dlen < 5) - break; - union_header = - (struct usb_cdc_union_desc *)data; - break; - case 0xAB: - phonet = 1; - break; - } - } - data += dlen; - len -= dlen; - } + cdc_parse_cdc_header(&hdr, intf, data, len); + union_header = hdr.usb_cdc_union_desc; + phonet = hdr.phonet_magic_present; if (!union_header || !phonet) return -EINVAL; -- cgit v1.2.3 From 149e9ab495a4ba50fc6b52cb9b2710566adcf56e Mon Sep 17 00:00:00 2001 From: Iyappan Subramanian Date: Tue, 8 Sep 2015 15:50:26 -0700 Subject: driver: net: xgene: Add support for 2nd 10GbE port Adding support for the second 10GbE port on APM X-Gene SoC Signed-off-by: Iyappan Subramanian Signed-off-by: David S. Miller --- drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 3 ++- drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 16 ++++++++++++---- drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 5 +++++ 3 files changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c index cfa37041ab71..21749f01827d 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c @@ -107,7 +107,8 @@ static void xgene_enet_set_ring_state(struct xgene_enet_desc_ring *ring) { xgene_enet_ring_set_type(ring); - if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0) + if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0 || + xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH1) xgene_enet_ring_set_recombbuf(ring); xgene_enet_ring_init(ring); diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index e47298faf78d..6b1846df7b0c 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -1305,10 +1305,17 @@ static void xgene_enet_setup_ops(struct xgene_enet_pdata *pdata) pdata->ring_num = START_RING_NUM_0; break; case 1: - pdata->cpu_bufnum = START_CPU_BUFNUM_1; - pdata->eth_bufnum = START_ETH_BUFNUM_1; - pdata->bp_bufnum = START_BP_BUFNUM_1; - pdata->ring_num = START_RING_NUM_1; + if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) { + pdata->cpu_bufnum = XG_START_CPU_BUFNUM_1; + pdata->eth_bufnum = XG_START_ETH_BUFNUM_1; + pdata->bp_bufnum = XG_START_BP_BUFNUM_1; + pdata->ring_num = XG_START_RING_NUM_1; + } else { + pdata->cpu_bufnum = START_CPU_BUFNUM_1; + pdata->eth_bufnum = START_ETH_BUFNUM_1; + pdata->bp_bufnum = START_BP_BUFNUM_1; + pdata->ring_num = START_RING_NUM_1; + } break; default: break; @@ -1478,6 +1485,7 @@ static const struct acpi_device_id xgene_enet_acpi_match[] = { { "APMC0D05", XGENE_ENET1}, { "APMC0D30", XGENE_ENET1}, { "APMC0D31", XGENE_ENET1}, + { "APMC0D3F", XGENE_ENET1}, { "APMC0D26", XGENE_ENET2}, { "APMC0D25", XGENE_ENET2}, { } diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h index 50f92c39ed2a..ff89a5d98d01 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h @@ -56,6 +56,11 @@ #define START_BP_BUFNUM_1 0x2A #define START_RING_NUM_1 264 +#define XG_START_CPU_BUFNUM_1 12 +#define XG_START_ETH_BUFNUM_1 2 +#define XG_START_BP_BUFNUM_1 0x22 +#define XG_START_RING_NUM_1 264 + #define X2_START_CPU_BUFNUM_0 0 #define X2_START_ETH_BUFNUM_0 0 #define X2_START_BP_BUFNUM_0 0x20 -- cgit v1.2.3 From 8b711d6db5c78a6d1969fb0fccb93daa7df53762 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 9 Sep 2015 17:40:56 -0700 Subject: mv643xx_eth: Neaten mv643xx_eth_program_multicast_filter The code around the allocation and loops are a bit obfuscated. Neaten it by using: o kcalloc with decimal count and sizeof(u32) o Decimal loop indexing and i++ not i += 4 o A promiscuous block using a similar style to the multicast block o Remove unnecessary variables Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 43 +++++++++++++++--------------- 1 file changed, 22 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 960169efe636..c78ae1868097 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -1845,29 +1845,19 @@ static void mv643xx_eth_program_multicast_filter(struct net_device *dev) struct netdev_hw_addr *ha; int i; - if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) { - int port_num; - u32 accept; + if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) + goto promiscuous; -oom: - port_num = mp->port_num; - accept = 0x01010101; - for (i = 0; i < 0x100; i += 4) { - wrl(mp, SPECIAL_MCAST_TABLE(port_num) + i, accept); - wrl(mp, OTHER_MCAST_TABLE(port_num) + i, accept); - } - return; - } - - mc_spec = kzalloc(0x200, GFP_ATOMIC); - if (mc_spec == NULL) - goto oom; - mc_other = mc_spec + (0x100 >> 2); + /* Allocate both mc_spec and mc_other tables */ + mc_spec = kcalloc(128, sizeof(u32), GFP_ATOMIC); + if (!mc_spec) + goto promiscuous; + mc_other = &mc_spec[64]; netdev_for_each_mc_addr(ha, dev) { u8 *a = ha->addr; u32 *table; - int entry; + u8 entry; if (memcmp(a, "\x01\x00\x5e\x00\x00", 5) == 0) { table = mc_spec; @@ -1880,12 +1870,23 @@ oom: table[entry >> 2] |= 1 << (8 * (entry & 3)); } - for (i = 0; i < 0x100; i += 4) { - wrl(mp, SPECIAL_MCAST_TABLE(mp->port_num) + i, mc_spec[i >> 2]); - wrl(mp, OTHER_MCAST_TABLE(mp->port_num) + i, mc_other[i >> 2]); + for (i = 0; i < 64; i++) { + wrl(mp, SPECIAL_MCAST_TABLE(mp->port_num) + i * sizeof(u32), + mc_spec[i]); + wrl(mp, OTHER_MCAST_TABLE(mp->port_num) + i * sizeof(u32), + mc_other[i]); } kfree(mc_spec); + return; + +promiscuous: + for (i = 0; i < 64; i++) { + wrl(mp, SPECIAL_MCAST_TABLE(mp->port_num) + i * sizeof(u32), + 0x01010101u); + wrl(mp, OTHER_MCAST_TABLE(mp->port_num) + i * sizeof(u32), + 0x01010101u); + } } static void mv643xx_eth_set_rx_mode(struct net_device *dev) -- cgit v1.2.3 From 4ccc650cc845476885f73660b2e6335852f0f75c Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Wed, 2 Sep 2015 13:47:54 -0700 Subject: ixgbe: fix issue with SFP events with new X550 devices Add checks for systems that don't have SFP's to avoid incorrectly acting on interrupts that are falsely interpreted as SFP events. This also includes a modified check generating the EICR mask to be more forward-looking. Signed-off-by: Don Skidmore Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 63b2cfe9416b..b9267e20e269 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2495,17 +2495,26 @@ static inline bool ixgbe_is_sfp(struct ixgbe_hw *hw) static void ixgbe_check_sfp_event(struct ixgbe_adapter *adapter, u32 eicr) { struct ixgbe_hw *hw = &adapter->hw; + u32 eicr_mask = IXGBE_EICR_GPI_SDP2(hw); - if (eicr & IXGBE_EICR_GPI_SDP2(hw)) { + if (!ixgbe_is_sfp(hw)) + return; + + /* Later MAC's use different SDP */ + if (hw->mac.type >= ixgbe_mac_X540) + eicr_mask = IXGBE_EICR_GPI_SDP0_X540; + + if (eicr & eicr_mask) { /* Clear the interrupt */ - IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2(hw)); + IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); if (!test_bit(__IXGBE_DOWN, &adapter->state)) { adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET; ixgbe_service_event_schedule(adapter); } } - if (eicr & IXGBE_EICR_GPI_SDP1(hw)) { + if (adapter->hw.mac.type == ixgbe_mac_82599EB && + (eicr & IXGBE_EICR_GPI_SDP1(hw))) { /* Clear the interrupt */ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1(hw)); if (!test_bit(__IXGBE_DOWN, &adapter->state)) { -- cgit v1.2.3 From 6b010e9b1f0a406d1d35202a694fa724a559bf77 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 29 Jul 2015 14:38:21 -0600 Subject: ixgbe: Teardown SR-IOV before unregister_netdev() When the .remove() callback for a PF is called, SR-IOV support for the device is disabled, which requires unbinding and removing the VFs. The VFs may be in-use either by the host kernel or userspace, such as assigned to a VM through vfio-pci. In this latter case, the VFs may be removed either by shutting down the VM or hot-unplugging the devices from the VM. Unfortunately in the case of a Windows 2012 R2 guest, hot-unplug is broken due to the ordering of the PF driver teardown. Disabling SR-IOV prior to unregister_netdev() avoids this issue. Signed-off-by: Alex Williamson Acked-by: Mitch Williams Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index b9267e20e269..c04480ed905e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -9028,12 +9028,12 @@ static void ixgbe_remove(struct pci_dev *pdev) /* remove the added san mac */ ixgbe_del_sanmac_netdev(netdev); - if (netdev->reg_state == NETREG_REGISTERED) - unregister_netdev(netdev); - #ifdef CONFIG_PCI_IOV ixgbe_disable_sriov(adapter); #endif + if (netdev->reg_state == NETREG_REGISTERED) + unregister_netdev(netdev); + ixgbe_clear_interrupt_scheme(adapter); ixgbe_release_hw_control(adapter); -- cgit v1.2.3 From 8ac34f10a5ea4c7b6f57dfd52b0693a2b67d9ac4 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 30 Jul 2015 15:19:28 -0700 Subject: ixgbe: Limit lowest interrupt rate for adaptive interrupt moderation to 12K This patch updates the lowest limit for adaptive interrupt interrupt moderation to roughly 12K interrupts per second. The way I came about reaching 12K as the desired interrupt rate is by testing with UDP flows. Specifically I had a simple test that ran a netperf UDP_STREAM test at varying sizes. What I found was as the packet sizes increased the performance fell steadily behind until we were only able to receive at ~4Gb/s with a message size of 65507. A bit of digging found that we were dropping packets for the socket in the network stack, and looking at things further what I found was I could solve it by increasing the interrupt rate, or increasing the rmem_default/rmem_max. What I found was that when the interrupt coalescing resulted in more data being processed per interrupt than could be stored in the socket buffer we started losing packets and the performance dropped. So I reached 12K based on the following math. rmem_default = 212992 skb->truesize = 2994 212992 / 2994 = 71.14 packets to fill the buffer packet rate at 1514 packet size is 812744pps 71.14 / 812744 = 87.9us to fill socket buffer From there it was just a matter of choosing the interrupt rate and providing a bit of wiggle room which is why I decided to go with 12K interrupts per second as that uses a value of 84us. The data below is based on VM to VM over a direct assigned ixgbe interface. The test run was: netperf -H -t UDP_STREAM" Socket Message Elapsed Messages CPU Service Size Size Time Okay Errors Throughput Util Demand bytes bytes secs # # 10^6bits/sec % SS us/KB Before: 212992 65507 60.00 1100662 0 9613.4 10.89 0.557 212992 60.00 473474 4135.4 11.27 0.576 After: 212992 65507 60.00 1100413 0 9611.2 10.73 0.549 212992 60.00 974132 8508.3 11.69 0.598 Using bare metal the data is similar but not as dramatic as the throughput increases from about 8.5Gb/s to 9.5Gb/s. Signed-off-by: Alexander Duyck Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 3 +-- drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index edf1fb913209..a699c991ad2c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -539,8 +539,7 @@ struct hwmon_buff { #define IXGBE_MIN_RSC_ITR 24 #define IXGBE_100K_ITR 40 #define IXGBE_20K_ITR 200 -#define IXGBE_10K_ITR 400 -#define IXGBE_8K_ITR 500 +#define IXGBE_12K_ITR 336 /* ixgbe_test_staterr - tests bits in Rx descriptor status and error fields */ static inline __le32 ixgbe_test_staterr(union ixgbe_adv_rx_desc *rx_desc, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index ab2edc8e7703..94c4912b2330 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2286,7 +2286,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev, adapter->tx_itr_setting = ec->tx_coalesce_usecs; if (adapter->tx_itr_setting == 1) - tx_itr_param = IXGBE_10K_ITR; + tx_itr_param = IXGBE_12K_ITR; else tx_itr_param = adapter->tx_itr_setting; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index 68e1e757ecef..f3168bcc7d87 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -866,7 +866,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, if (txr_count && !rxr_count) { /* tx only vector */ if (adapter->tx_itr_setting == 1) - q_vector->itr = IXGBE_10K_ITR; + q_vector->itr = IXGBE_12K_ITR; else q_vector->itr = adapter->tx_itr_setting; } else { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index c04480ed905e..acb1b91408ec 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2261,7 +2261,7 @@ static void ixgbe_update_itr(struct ixgbe_q_vector *q_vector, /* simple throttlerate management * 0-10MB/s lowest (100000 ints/s) * 10-20MB/s low (20000 ints/s) - * 20-1249MB/s bulk (8000 ints/s) + * 20-1249MB/s bulk (12000 ints/s) */ /* what was last interrupt timeslice? */ timepassed_us = q_vector->itr >> 2; @@ -2350,7 +2350,7 @@ static void ixgbe_set_itr(struct ixgbe_q_vector *q_vector) new_itr = IXGBE_20K_ITR; break; case bulk_latency: - new_itr = IXGBE_8K_ITR; + new_itr = IXGBE_12K_ITR; break; default: break; -- cgit v1.2.3 From e40296628bec7400f529927eef4bc87cb425a22a Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 15 Jun 2015 15:00:51 -0700 Subject: fm10k: disable service task during suspend The service task reads some registers as part of its normal routine, even while the interface is down. Normally this is ok. However, during suspend we have disabled the PCI device. Due to this, registers will read in the same way as a surprise-remove event. Disable the service task while we suspend, and re-enable it after we resume. If we don't do this, the device could be UP when you suspend and come back from resume as closed (since fm10k closes the device when it gets a surprise remove). Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index ce53ff25f88d..8413ab548eba 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1983,6 +1983,16 @@ static int fm10k_resume(struct pci_dev *pdev) if (err) return err; + /* assume host is not ready, to prevent race with watchdog in case we + * actually don't have connection to the switch + */ + interface->host_ready = false; + fm10k_watchdog_host_not_ready(interface); + + /* clear the service task disable bit to allow service task to start */ + clear_bit(__FM10K_SERVICE_DISABLE, &interface->state); + fm10k_service_event_schedule(interface); + /* restore SR-IOV interface */ fm10k_iov_resume(pdev); @@ -2010,6 +2020,15 @@ static int fm10k_suspend(struct pci_dev *pdev, fm10k_iov_suspend(pdev); + /* the watchdog tasks may read registers, which will appear like a + * surprise-remove event once the PCI device is disabled. This will + * cause us to close the netdevice, so we don't retain the open/closed + * state post-resume. Prevent this by disabling the service task while + * suspended, until we actually resume. + */ + set_bit(__FM10K_SERVICE_DISABLE, &interface->state); + cancel_work_sync(&interface->service_task); + rtnl_lock(); if (netif_running(netdev)) -- cgit v1.2.3 From 56f0569e3ab741d3c5cebc4b4c882b471df53738 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 15 Jun 2015 15:00:53 -0700 Subject: fm10k: only prevent removal of default VID rules This allows us to correctly add a VLAN even if it matches our default VID. However, we don't want to remove the VID rules once that VLAN is deleted. Correctly remove the stack layers information of the VLAN, but then return to forwarding that VID as untagged frames. If we deleted the VID rules here, we would begin dropping traffic due to VLAN membership violations. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 99228bf46c12..818bc8b1fa58 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -775,8 +775,8 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) if (!set) clear_bit(vid, interface->active_vlans); - /* if default VLAN is already present do nothing */ - if (vid == hw->mac.default_vid) + /* Do not remove default VID related entries from VLAN and MAC tables */ + if (!set && vid == hw->mac.default_vid) return 0; fm10k_mbx_lock(interface); -- cgit v1.2.3 From 106c07a49506359f7663770ef33f4997d68316c1 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 15 Jun 2015 15:00:55 -0700 Subject: fm10k: update fm10k_slot_warn to use pcie_get_minimum link This is useful in cases where we connect to a slot at Gen3, but the slot is behind a bus which only connected at Gen2. This generally only happens when a PCIe switch is in the sequence of devices, and can be very confusing when you see slow performance with no obvious cause. I am aware this patch has a few lines that break 80 characters, but there does not seem to be a readable way to format them to less than 80 characters. Suggestions welcome. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 105 +++++++++++++++++++-------- 1 file changed, 76 insertions(+), 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 8413ab548eba..2d87c3282c0c 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1705,22 +1705,86 @@ static int fm10k_sw_init(struct fm10k_intfc *interface, static void fm10k_slot_warn(struct fm10k_intfc *interface) { - struct device *dev = &interface->pdev->dev; + enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN; + enum pci_bus_speed speed = PCI_SPEED_UNKNOWN; struct fm10k_hw *hw = &interface->hw; + int max_gts = 0, expected_gts = 0; - if (hw->mac.ops.is_slot_appropriate(hw)) + if (pcie_get_minimum_link(interface->pdev, &speed, &width) || + speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN) { + dev_warn(&interface->pdev->dev, + "Unable to determine PCI Express bandwidth.\n"); return; + } + + switch (speed) { + case PCIE_SPEED_2_5GT: + /* 8b/10b encoding reduces max throughput by 20% */ + max_gts = 2 * width; + break; + case PCIE_SPEED_5_0GT: + /* 8b/10b encoding reduces max throughput by 20% */ + max_gts = 4 * width; + break; + case PCIE_SPEED_8_0GT: + /* 128b/130b encoding has less than 2% impact on throughput */ + max_gts = 8 * width; + break; + default: + dev_warn(&interface->pdev->dev, + "Unable to determine PCI Express bandwidth.\n"); + return; + } + + dev_info(&interface->pdev->dev, + "PCI Express bandwidth of %dGT/s available\n", + max_gts); + dev_info(&interface->pdev->dev, + "(Speed:%s, Width: x%d, Encoding Loss:%s, Payload:%s)\n", + (speed == PCIE_SPEED_8_0GT ? "8.0GT/s" : + speed == PCIE_SPEED_5_0GT ? "5.0GT/s" : + speed == PCIE_SPEED_2_5GT ? "2.5GT/s" : + "Unknown"), + hw->bus.width, + (speed == PCIE_SPEED_2_5GT ? "20%" : + speed == PCIE_SPEED_5_0GT ? "20%" : + speed == PCIE_SPEED_8_0GT ? "<2%" : + "Unknown"), + (hw->bus.payload == fm10k_bus_payload_128 ? "128B" : + hw->bus.payload == fm10k_bus_payload_256 ? "256B" : + hw->bus.payload == fm10k_bus_payload_512 ? "512B" : + "Unknown")); - dev_warn(dev, - "For optimal performance, a %s %s slot is recommended.\n", - (hw->bus_caps.width == fm10k_bus_width_pcie_x1 ? "x1" : - hw->bus_caps.width == fm10k_bus_width_pcie_x4 ? "x4" : - "x8"), - (hw->bus_caps.speed == fm10k_bus_speed_2500 ? "2.5GT/s" : - hw->bus_caps.speed == fm10k_bus_speed_5000 ? "5.0GT/s" : - "8.0GT/s")); - dev_warn(dev, - "A slot with more lanes and/or higher speed is suggested.\n"); + switch (hw->bus_caps.speed) { + case fm10k_bus_speed_2500: + /* 8b/10b encoding reduces max throughput by 20% */ + expected_gts = 2 * hw->bus_caps.width; + break; + case fm10k_bus_speed_5000: + /* 8b/10b encoding reduces max throughput by 20% */ + expected_gts = 4 * hw->bus_caps.width; + break; + case fm10k_bus_speed_8000: + /* 128b/130b encoding has less than 2% impact on throughput */ + expected_gts = 8 * hw->bus_caps.width; + break; + default: + dev_warn(&interface->pdev->dev, + "Unable to determine expected PCI Express bandwidth.\n"); + return; + } + + if (max_gts < expected_gts) { + dev_warn(&interface->pdev->dev, + "This device requires %dGT/s of bandwidth for optimal performance.\n", + expected_gts); + dev_warn(&interface->pdev->dev, + "A %sslot with x%d lanes is suggested.\n", + (hw->bus_caps.speed == fm10k_bus_speed_2500 ? "2.5GT/s " : + hw->bus_caps.speed == fm10k_bus_speed_5000 ? "5.0GT/s " : + hw->bus_caps.speed == fm10k_bus_speed_8000 ? "8.0GT/s " : ""), + hw->bus_caps.width); + } } /** @@ -1739,7 +1803,6 @@ static int fm10k_probe(struct pci_dev *pdev, { struct net_device *netdev; struct fm10k_intfc *interface; - struct fm10k_hw *hw; int err; err = pci_enable_device_mem(pdev); @@ -1783,7 +1846,6 @@ static int fm10k_probe(struct pci_dev *pdev, interface->netdev = netdev; interface->pdev = pdev; - hw = &interface->hw; interface->uc_addr = ioremap(pci_resource_start(pdev, 0), FM10K_UC_ADDR_SIZE); @@ -1825,21 +1887,6 @@ static int fm10k_probe(struct pci_dev *pdev, /* Register PTP interface */ fm10k_ptp_register(interface); - /* print bus type/speed/width info */ - dev_info(&pdev->dev, "(PCI Express:%s Width: %s Payload: %s)\n", - (hw->bus.speed == fm10k_bus_speed_8000 ? "8.0GT/s" : - hw->bus.speed == fm10k_bus_speed_5000 ? "5.0GT/s" : - hw->bus.speed == fm10k_bus_speed_2500 ? "2.5GT/s" : - "Unknown"), - (hw->bus.width == fm10k_bus_width_pcie_x8 ? "x8" : - hw->bus.width == fm10k_bus_width_pcie_x4 ? "x4" : - hw->bus.width == fm10k_bus_width_pcie_x1 ? "x1" : - "Unknown"), - (hw->bus.payload == fm10k_bus_payload_128 ? "128B" : - hw->bus.payload == fm10k_bus_payload_256 ? "256B" : - hw->bus.payload == fm10k_bus_payload_512 ? "512B" : - "Unknown")); - /* print warning for non-optimal configurations */ fm10k_slot_warn(interface); -- cgit v1.2.3 From bdc7f5902d22e7297b8f0d7a8d6ed8429cdba636 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 15 Jun 2015 15:00:56 -0700 Subject: fm10k: update netdev perm_addr during reinit, instead of at up Update the netdev permanent address during fm10k_reinit enables the user to immediately see the new MAC address on the VF even if the device isn't up. The previous code required that the device by opened before changes would appear. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 15 --------------- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 818bc8b1fa58..b2065cb44edc 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -996,21 +996,6 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) int xcast_mode; u16 vid, glort; - /* restore our address if perm_addr is set */ - if (hw->mac.type == fm10k_mac_vf) { - if (is_valid_ether_addr(hw->mac.perm_addr)) { - ether_addr_copy(hw->mac.addr, hw->mac.perm_addr); - ether_addr_copy(netdev->perm_addr, hw->mac.perm_addr); - ether_addr_copy(netdev->dev_addr, hw->mac.perm_addr); - netdev->addr_assign_type &= ~NET_ADDR_RANDOM; - } - - if (hw->mac.vlan_override) - netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX; - else - netdev->features |= NETIF_F_HW_VLAN_CTAG_RX; - } - /* record glort for this interface */ glort = interface->glort; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 2d87c3282c0c..db237b7dd088 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -170,6 +170,21 @@ static void fm10k_reinit(struct fm10k_intfc *interface) /* reassociate interrupts */ fm10k_mbx_request_irq(interface); + /* update hardware address for VFs if perm_addr has changed */ + if (hw->mac.type == fm10k_mac_vf) { + if (is_valid_ether_addr(hw->mac.perm_addr)) { + ether_addr_copy(hw->mac.addr, hw->mac.perm_addr); + ether_addr_copy(netdev->perm_addr, hw->mac.perm_addr); + ether_addr_copy(netdev->dev_addr, hw->mac.perm_addr); + netdev->addr_assign_type &= ~NET_ADDR_RANDOM; + } + + if (hw->mac.vlan_override) + netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX; + else + netdev->features |= NETIF_F_HW_VLAN_CTAG_RX; + } + /* reset clock */ fm10k_ts_reset(interface); -- cgit v1.2.3 From aae072e363bed4e91c00d57f753c799276ddb161 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 16 Jun 2015 11:47:12 -0700 Subject: fm10k: Don't assume page fragments are page size This change pulls out the optimization that assumed that all fragments would be limited to page size. That hasn't been the case for some time now and to assume this is incorrect as the TCP allocator can provide up to a 32K page fragment. Signed-off-by: Alexander Duyck Acked-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index b5b2925103ec..6ad03e0f2e30 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1079,9 +1079,7 @@ netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb, struct fm10k_tx_buffer *first; int tso; u32 tx_flags = 0; -#if PAGE_SIZE > FM10K_MAX_DATA_PER_TXD unsigned short f; -#endif u16 count = TXD_USE_COUNT(skb_headlen(skb)); /* need: 1 descriptor per page * PAGE_SIZE/FM10K_MAX_DATA_PER_TXD, @@ -1089,12 +1087,9 @@ netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb, * + 2 desc gap to keep tail from touching head * otherwise try next time */ -#if PAGE_SIZE > FM10K_MAX_DATA_PER_TXD for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); -#else - count += skb_shinfo(skb)->nr_frags; -#endif + if (fm10k_maybe_stop_tx(tx_ring, count + 3)) { tx_ring->tx_stats.tx_busy++; return NETDEV_TX_BUSY; -- cgit v1.2.3 From 0ff36676a3778d0655933ace201fca7c11b4e8b5 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 18 Jun 2015 19:41:10 -0700 Subject: fm10k: Report MAC address on driver load This change adds the MAC address to the list of values recorded on driver load. The MAC address represents the serial number of the unit and allows us to track the value should a card be replaced in a system. The log message should now be similar in output to that of ixgbe. Signed-off-by: Alexander Duyck Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index db237b7dd088..9f2b2f19e2a4 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -1905,6 +1905,9 @@ static int fm10k_probe(struct pci_dev *pdev, /* print warning for non-optimal configurations */ fm10k_slot_warn(interface); + /* report MAC address for logging */ + dev_info(&pdev->dev, "%pM\n", netdev->dev_addr); + /* enable SR-IOV after registering netdev to enforce PF/VF ordering */ fm10k_iov_configure(pdev, 0); -- cgit v1.2.3 From 3f0bdb2e2ce7db7425856686d9ccd8fd0ddf9bf0 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 19 Jun 2015 10:56:09 -0700 Subject: fm10k: allow creation of VLAN interfaces even while down We re-sync upon going up, so there is little reason to worry about not syncing immediately with switch. This prevents an error that occurs if you add a VLAN interface while down. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index b2065cb44edc..e1ceb3a2e2cd 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -779,6 +779,12 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) if (!set && vid == hw->mac.default_vid) return 0; + /* Do not throw an error if the interface is down. We will sync once + * we come up + */ + if (test_bit(__FM10K_DOWN, &interface->state)) + return 0; + fm10k_mbx_lock(interface); /* only need to update the VLAN if not in promiscuous mode */ -- cgit v1.2.3 From b655a5c735867c1a80e7ceaa1f1c45d1dd34909f Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 19 Jun 2015 10:56:10 -0700 Subject: fm10k: don't store sw_vid at reset If we store the sw_vid at reset of PF, then we accidentally prevent the VF from receiving the message to update its default VID. This only occurs if the VF is created before the PF has come up, which is the standard way of creating VFs when using the module parameter. This fixes an issue where we request the incorrect MAC/VLAN combinations, and prevents us from accidentally reporting some frames as VLAN tagged. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_iov.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c index 94571e6e790c..0e25a80417b9 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c @@ -228,9 +228,6 @@ int fm10k_iov_resume(struct pci_dev *pdev) hw->iov.ops.set_lport(hw, vf_info, i, FM10K_VF_FLAG_MULTI_CAPABLE); - /* assign our default vid to the VF following reset */ - vf_info->sw_vid = hw->mac.default_vid; - /* mailbox is disconnected so we don't send a message */ hw->iov.ops.assign_default_mac_vlan(hw, vf_info); -- cgit v1.2.3 From 855c40fc31ca2392845558235f7e92e406936fbe Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 24 Jun 2015 13:34:41 -0700 Subject: fm10k: remove is_slot_appropriate This function is no longer used now that we have updated fm10k_slot_warn functionality. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 14 -------------- drivers/net/ethernet/intel/fm10k/fm10k_type.h | 1 - drivers/net/ethernet/intel/fm10k/fm10k_vf.c | 14 -------------- 3 files changed, 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index 3ca0233b3ea2..241b969626bc 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -184,19 +184,6 @@ static s32 fm10k_init_hw_pf(struct fm10k_hw *hw) return 0; } -/** - * fm10k_is_slot_appropriate_pf - Indicate appropriate slot for this SKU - * @hw: pointer to hardware structure - * - * Looks at the PCIe bus info to confirm whether or not this slot can support - * the necessary bandwidth for this device. - **/ -static bool fm10k_is_slot_appropriate_pf(struct fm10k_hw *hw) -{ - return (hw->bus.speed == hw->bus_caps.speed) && - (hw->bus.width == hw->bus_caps.width); -} - /** * fm10k_update_vlan_pf - Update status of VLAN ID in VLAN filter table * @hw: pointer to hardware structure @@ -1849,7 +1836,6 @@ static struct fm10k_mac_ops mac_ops_pf = { .init_hw = &fm10k_init_hw_pf, .start_hw = &fm10k_start_hw_generic, .stop_hw = &fm10k_stop_hw_generic, - .is_slot_appropriate = &fm10k_is_slot_appropriate_pf, .update_vlan = &fm10k_update_vlan_pf, .read_mac_addr = &fm10k_read_mac_addr_pf, .update_uc_addr = &fm10k_update_uc_addr_pf, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/drivers/net/ethernet/intel/fm10k/fm10k_type.h index 2a17d82fa37d..bac8d486d75f 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_type.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_type.h @@ -521,7 +521,6 @@ struct fm10k_mac_ops { s32 (*stop_hw)(struct fm10k_hw *); s32 (*get_bus_info)(struct fm10k_hw *); s32 (*get_host_state)(struct fm10k_hw *, bool *); - bool (*is_slot_appropriate)(struct fm10k_hw *); s32 (*update_vlan)(struct fm10k_hw *, u32, u8, bool); s32 (*read_mac_addr)(struct fm10k_hw *); s32 (*update_uc_addr)(struct fm10k_hw *, u16, const u8 *, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c index 94f0f6a146d9..36c8b0aa08fd 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_vf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_vf.c @@ -131,19 +131,6 @@ static s32 fm10k_init_hw_vf(struct fm10k_hw *hw) return 0; } -/** - * fm10k_is_slot_appropriate_vf - Indicate appropriate slot for this SKU - * @hw: pointer to hardware structure - * - * Looks at the PCIe bus info to confirm whether or not this slot can support - * the necessary bandwidth for this device. Since the VF has no control over - * the "slot" it is in, always indicate that the slot is appropriate. - **/ -static bool fm10k_is_slot_appropriate_vf(struct fm10k_hw *hw) -{ - return true; -} - /* This structure defines the attibutes to be parsed below */ const struct fm10k_tlv_attr fm10k_mac_vlan_msg_attr[] = { FM10K_TLV_ATTR_U32(FM10K_MAC_VLAN_MSG_VLAN), @@ -552,7 +539,6 @@ static struct fm10k_mac_ops mac_ops_vf = { .init_hw = &fm10k_init_hw_vf, .start_hw = &fm10k_start_hw_generic, .stop_hw = &fm10k_stop_hw_vf, - .is_slot_appropriate = &fm10k_is_slot_appropriate_vf, .update_vlan = &fm10k_update_vlan_vf, .read_mac_addr = &fm10k_read_mac_addr_vf, .update_uc_addr = &fm10k_update_uc_addr_vf, -- cgit v1.2.3 From 6fbc6b358b3f63e701d15e9d330a3b0dbb03f802 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 24 Jun 2015 13:34:44 -0700 Subject: fm10k: TRIVIAL fix up ordering of __always_unused and style Fix some style issues in debugfs code, and correct ordering of void and __always_unused. Technically, the order does not matter, but preferred style is to put the macro between the type and name. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c b/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c index f45b4d71adb8..08ecf43dffc7 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c @@ -37,7 +37,8 @@ static void *fm10k_dbg_desc_seq_start(struct seq_file *s, loff_t *pos) } static void *fm10k_dbg_desc_seq_next(struct seq_file *s, - void __always_unused *v, loff_t *pos) + void __always_unused *v, + loff_t *pos) { struct fm10k_ring *ring = s->private; @@ -45,7 +46,7 @@ static void *fm10k_dbg_desc_seq_next(struct seq_file *s, } static void fm10k_dbg_desc_seq_stop(struct seq_file __always_unused *s, - __always_unused void *v) + void __always_unused *v) { /* Do nothing. */ } -- cgit v1.2.3 From e71c9318428fb16de808b497e0229994010d32a1 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 24 Jun 2015 13:34:46 -0700 Subject: fm10k: send traffic on default VID to VLAN device if we have one This patch ensures that VLAN traffic on the default VID will go to the corresponding VLAN device if it exists. To do this, mask the rx_ring VID if we have an active VLAN on that VID. For this to work correctly, we need to update fm10k_process_skb_fields to correctly mask off the VLAN_PRIO_MASK bits and compare them separately, otherwise we incorrectly compare the priority bits with the cleared flag. This also happens to fix a related bug where having priority bits set causes us to incorrectly classify traffic. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 5 ++++- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 12 ++++++++++++ drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 4 ++++ 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 6ad03e0f2e30..92d415584749 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -497,8 +497,11 @@ static unsigned int fm10k_process_skb_fields(struct fm10k_ring *rx_ring, if (rx_desc->w.vlan) { u16 vid = le16_to_cpu(rx_desc->w.vlan); - if (vid != rx_ring->vid) + if ((vid & VLAN_VID_MASK) != rx_ring->vid) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); + else if (vid & VLAN_PRIO_MASK) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + vid & VLAN_PRIO_MASK); } fm10k_type_trans(rx_ring, rx_desc, skb); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index e1ceb3a2e2cd..3a6230b405fe 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -758,6 +758,7 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) struct fm10k_intfc *interface = netdev_priv(netdev); struct fm10k_hw *hw = &interface->hw; s32 err; + int i; /* updates do not apply to VLAN 0 */ if (!vid) @@ -775,6 +776,17 @@ static int fm10k_update_vid(struct net_device *netdev, u16 vid, bool set) if (!set) clear_bit(vid, interface->active_vlans); + /* disable the default VID on ring if we have an active VLAN */ + for (i = 0; i < interface->num_rx_queues; i++) { + struct fm10k_ring *rx_ring = interface->rx_ring[i]; + u16 rx_vid = rx_ring->vid & (VLAN_N_VID - 1); + + if (test_bit(rx_vid, interface->active_vlans)) + rx_ring->vid |= FM10K_VLAN_CLEAR; + else + rx_ring->vid &= ~FM10K_VLAN_CLEAR; + } + /* Do not remove default VID related entries from VLAN and MAC tables */ if (!set && vid == hw->mac.default_vid) return 0; diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 9f2b2f19e2a4..9bdc04da451e 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -678,6 +678,10 @@ static void fm10k_configure_rx_ring(struct fm10k_intfc *interface, /* assign default VLAN to queue */ ring->vid = hw->mac.default_vid; + /* if we have an active VLAN, disable default VID */ + if (test_bit(hw->mac.default_vid, interface->active_vlans)) + ring->vid |= FM10K_VLAN_CLEAR; + /* Map interrupt */ if (ring->q_vector) { rxint = ring->q_vector->v_idx + NON_Q_VECTORS(hw); -- cgit v1.2.3 From 5c2d642fd0cf0f4f7396dfd3754bc03f6e50e359 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 24 Jun 2015 13:34:47 -0700 Subject: fm10k: TRIVIAL fix typo in fm10k_netdev.c Signed-off-by: Jacob Keller Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c index 3a6230b405fe..639263d5e833 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c @@ -1048,7 +1048,7 @@ void fm10k_restore_rx_state(struct fm10k_intfc *interface) vid, true, 0); } - /* update xcast mode before syncronizing addresses */ + /* update xcast mode before synchronizing addresses */ hw->mac.ops.update_xcast_mode(hw, glort, xcast_mode); /* synchronize all of the addresses */ -- cgit v1.2.3 From 95f4f8da644256d8c0ff5bab2c93ba33d2a42cd8 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 24 Jun 2015 13:34:48 -0700 Subject: fm10k: re-enable VF after a full reset on detection of a Malicious event Modify behavior of Malicious Driver Detection events. Presently, the hardware disables the VF queues and re-assigns them to the PF. This causes the VF in question to continuously Tx hang, because it assumes that it can transmit over the queues in question. For transient events, this results in continuous logging of malicious events. New behavior is to reset the LPORT and VF state, so that the VF will have to reset and re-enable itself. This does mean that malicious VFs will possibly be able to continue and attempt malicious events again. However, it is expected that system administrators will step in and manually remove or disable the VF in question. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 30 ++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 9bdc04da451e..3d71c5206110 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -880,10 +880,12 @@ void fm10k_netpoll(struct net_device *netdev) #endif #define FM10K_ERR_MSG(type) case (type): error = #type; break -static void fm10k_print_fault(struct fm10k_intfc *interface, int type, +static void fm10k_handle_fault(struct fm10k_intfc *interface, int type, struct fm10k_fault *fault) { struct pci_dev *pdev = interface->pdev; + struct fm10k_hw *hw = &interface->hw; + struct fm10k_iov_data *iov_data = interface->iov_data; char *error; switch (type) { @@ -937,6 +939,30 @@ static void fm10k_print_fault(struct fm10k_intfc *interface, int type, "%s Address: 0x%llx SpecInfo: 0x%x Func: %02x.%0x\n", error, fault->address, fault->specinfo, PCI_SLOT(fault->func), PCI_FUNC(fault->func)); + + /* For VF faults, clear out the respective LPORT, reset the queue + * resources, and then reconnect to the mailbox. This allows the + * VF in question to resume behavior. For transient faults that are + * the result of non-malicious behavior this will log the fault and + * allow the VF to resume functionality. Obviously for malicious VFs + * they will be able to attempt malicious behavior again. In this + * case, the system administrator will need to step in and manually + * remove or disable the VF in question. + */ + if (fault->func && iov_data) { + int vf = fault->func - 1; + struct fm10k_vf_info *vf_info = &iov_data->vf_info[vf]; + + hw->iov.ops.reset_lport(hw, vf_info); + hw->iov.ops.reset_resources(hw, vf_info); + + /* reset_lport disables the VF, so re-enable it */ + hw->iov.ops.set_lport(hw, vf_info, vf, + FM10K_VF_FLAG_MULTI_CAPABLE); + + /* reset_resources will disconnect from the mbx */ + vf_info->mbx.ops.connect(hw, &vf_info->mbx); + } } static void fm10k_report_fault(struct fm10k_intfc *interface, u32 eicr) @@ -960,7 +986,7 @@ static void fm10k_report_fault(struct fm10k_intfc *interface, u32 eicr) continue; } - fm10k_print_fault(interface, type, &fault); + fm10k_handle_fault(interface, type, &fault); } } -- cgit v1.2.3 From ac98100359e098d03dbd98783ca4becaf2ea7ec3 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 24 Jun 2015 13:34:49 -0700 Subject: fm10k: Only trigger data path reset if fabric is up This change makes it so that we only trigger the data path reset if the fabric is ready to handle traffic. The general idea is to avoid triggering the reset unless the switch API is ready for us. Otherwise we can just postpone the reset until we receive a switch ready notification. Signed-off-by: Alexander Duyck Signed-off-by: Jacob Keller Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index 241b969626bc..d806d87a6192 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -59,6 +59,11 @@ static s32 fm10k_reset_hw_pf(struct fm10k_hw *hw) if (reg & (FM10K_DMA_CTRL_TX_ACTIVE | FM10K_DMA_CTRL_RX_ACTIVE)) return FM10K_ERR_DMA_PENDING; + /* verify the switch is ready for reset */ + reg = fm10k_read_reg(hw, FM10K_DMA_CTRL2); + if (!(reg & FM10K_DMA_CTRL2_SWITCH_READY)) + goto out; + /* Inititate data path reset */ reg |= FM10K_DMA_CTRL_DATAPATH_RESET; fm10k_write_reg(hw, FM10K_DMA_CTRL, reg); @@ -72,6 +77,7 @@ static s32 fm10k_reset_hw_pf(struct fm10k_hw *hw) if (!(reg & FM10K_IP_NOTINRESET)) err = FM10K_ERR_RESET_FAILED; +out: return err; } -- cgit v1.2.3 From 9adbac599a71bc25a2617850ffcaa4388dc5c20d Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 24 Jun 2015 13:34:50 -0700 Subject: fm10k: fix iov_msg_mac_vlan_pf VID checks The VF will send a message to request multicast addresses with the default VID. In the current code, if the PF has statically assigned a VLAN to a VF, then the VF will not get the multicast addresses. Fix up all of the various VLAN messages to use identical checks (since each check was different). Also use set as a variable, so that it simplifies our check for whether VLAN matches the pf_vid. The new logic will allow set of a VLAN if it is zero, automatically converting to the default VID. Otherwise it will allow setting the PF VID, or any VLAN if PF has not statically assigned a VLAN. This is consistent behavior, and allows VF to request either 0 or the default_vid without silently failing. Note that we need the check for zero since VFs might not get the default VID message in time to actually request non-zero VLANs. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pf.c | 85 ++++++++++++++++++----------- 1 file changed, 52 insertions(+), 33 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c index d806d87a6192..8c0bdc4e4edd 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c @@ -1154,6 +1154,24 @@ s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *hw, u32 **results, return hw->iov.ops.assign_int_moderator(hw, vf_idx); } +/** + * fm10k_iov_select_vid - Select correct default VID + * @hw: Pointer to hardware structure + * @vid: VID to correct + * + * Will report an error if VID is out of range. For VID = 0, it will return + * either the pf_vid or sw_vid depending on which one is set. + */ +static inline s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid) +{ + if (!vid) + return vf_info->pf_vid ? vf_info->pf_vid : vf_info->sw_vid; + else if (vf_info->pf_vid && vid != vf_info->pf_vid) + return FM10K_ERR_PARAM; + else + return vid; +} + /** * fm10k_iov_msg_mac_vlan_pf - Message handler for MAC/VLAN request from VF * @hw: Pointer to hardware structure @@ -1168,9 +1186,10 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, struct fm10k_mbx_info *mbx) { struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx; - int err = 0; u8 mac[ETH_ALEN]; u32 *result; + int err = 0; + bool set; u16 vlan; u32 vid; @@ -1186,19 +1205,21 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, if (err) return err; - /* if VLAN ID is 0, set the default VLAN ID instead of 0 */ - if (!vid || (vid == FM10K_VLAN_CLEAR)) { - if (vf_info->pf_vid) - vid |= vf_info->pf_vid; - else - vid |= vf_info->sw_vid; - } else if (vid != vf_info->pf_vid) { + /* verify upper 16 bits are zero */ + if (vid >> 16) return FM10K_ERR_PARAM; - } + + set = !(vid & FM10K_VLAN_CLEAR); + vid &= ~FM10K_VLAN_CLEAR; + + err = fm10k_iov_select_vid(vf_info, vid); + if (err < 0) + return err; + else + vid = err; /* update VSI info for VF in regards to VLAN table */ - err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, - !(vid & FM10K_VLAN_CLEAR)); + err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, set); } if (!err && !!results[FM10K_MAC_VLAN_MSG_MAC]) { @@ -1214,19 +1235,18 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, memcmp(mac, vf_info->mac, ETH_ALEN)) return FM10K_ERR_PARAM; - /* if VLAN ID is 0, set the default VLAN ID instead of 0 */ - if (!vlan || (vlan == FM10K_VLAN_CLEAR)) { - if (vf_info->pf_vid) - vlan |= vf_info->pf_vid; - else - vlan |= vf_info->sw_vid; - } else if (vf_info->pf_vid) { - return FM10K_ERR_PARAM; - } + set = !(vlan & FM10K_VLAN_CLEAR); + vlan &= ~FM10K_VLAN_CLEAR; + + err = fm10k_iov_select_vid(vf_info, vlan); + if (err < 0) + return err; + else + vlan = err; /* notify switch of request for new unicast address */ - err = hw->mac.ops.update_uc_addr(hw, vf_info->glort, mac, vlan, - !(vlan & FM10K_VLAN_CLEAR), 0); + err = hw->mac.ops.update_uc_addr(hw, vf_info->glort, + mac, vlan, set, 0); } if (!err && !!results[FM10K_MAC_VLAN_MSG_MULTICAST]) { @@ -1241,19 +1261,18 @@ s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, if (!(vf_info->vf_flags & FM10K_VF_FLAG_MULTI_ENABLED)) return FM10K_ERR_PARAM; - /* if VLAN ID is 0, set the default VLAN ID instead of 0 */ - if (!vlan || (vlan == FM10K_VLAN_CLEAR)) { - if (vf_info->pf_vid) - vlan |= vf_info->pf_vid; - else - vlan |= vf_info->sw_vid; - } else if (vf_info->pf_vid) { - return FM10K_ERR_PARAM; - } + set = !(vlan & FM10K_VLAN_CLEAR); + vlan &= ~FM10K_VLAN_CLEAR; + + err = fm10k_iov_select_vid(vf_info, vlan); + if (err < 0) + return err; + else + vlan = err; /* notify switch of request for new multicast address */ - err = hw->mac.ops.update_mc_addr(hw, vf_info->glort, mac, vlan, - !(vlan & FM10K_VLAN_CLEAR)); + err = hw->mac.ops.update_mc_addr(hw, vf_info->glort, + mac, vlan, set); } return err; -- cgit v1.2.3 From 37d2dbcdcca88e392009d7cbe8617d5af0ebcb32 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 16 Sep 2015 11:32:41 -0700 Subject: net: fix cdc-phonet.c dependency and build error Fix build error caused by missing Kconfig dependency: ERROR: "cdc_parse_cdc_header" [drivers/net/usb/cdc-phonet.ko] undefined! Reported-by: Fengguang Wu Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- drivers/net/usb/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 1610b79ae386..975357ddeae6 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -541,7 +541,7 @@ config USB_NET_INT51X1 config USB_CDC_PHONET tristate "CDC Phonet support" - depends on PHONET + depends on PHONET && USB_USBNET help Choose this option to support the Phonet interface to a Nokia cellular modem, as found on most Nokia handsets with the -- cgit v1.2.3 From 0d031c8995bcc065f9c5778069f2131f7d92d4d5 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 9 Sep 2015 12:47:34 -0400 Subject: ath10k: enable monitor when OTHER_BSS requested By default, ath10k restricts received frames to those matching BSSID. When other BSS frames are requested (e.g. in mesh mode), add an internal monitor device so those frames are not filtered. Signed-off-by: Bob Copeland Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 989d2a154f8f..80efcc8debfe 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1070,6 +1070,7 @@ static bool ath10k_mac_monitor_vdev_is_needed(struct ath10k *ar) return false; return ar->monitor || + ar->filter_flags & FIF_OTHER_BSS || test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); } -- cgit v1.2.3 From bc76c28719d4333248a516fd4d469ab741b44b63 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 9 Sep 2015 12:47:35 -0400 Subject: ath10k: check for encryption before adding MIC_LEN In the case of raw mode without nohwcrypt parameter, we should still make sure the frame is protected before adding MIC_LEN to avoid skb_under_panic errors. Signed-off-by: Bob Copeland Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_tx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index ea53c2151122..eb5ba9bb8b4d 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -564,7 +564,8 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ieee80211_has_protected(hdr->frame_control)) { skb_put(msdu, IEEE80211_CCMP_MIC_LEN); } else if (!skb_cb->htt.nohwcrypt && - skb_cb->txmode == ATH10K_HW_TXRX_RAW) { + skb_cb->txmode == ATH10K_HW_TXRX_RAW && + ieee80211_has_protected(hdr->frame_control)) { skb_put(msdu, IEEE80211_CCMP_MIC_LEN); } -- cgit v1.2.3 From b6c7bafa7d4b1398cce93e4af0a48603919fa933 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 9 Sep 2015 12:47:36 -0400 Subject: ath10k: implement mesh support Add support for mesh to ath10k. We simply use an AP virtual interface in the firmware in order to enable beaconing without TSF adoption, and use the raw (802.11) transmit mode. Due to firmware limitations, the firmware must operate in raw (non-native 802.11) mode. As this is configured at firmware init time, a new "rawmode" modparam is added, and mesh interfaces are available only if rawmode=true. The firmware must advertise support for rawmode; tested successfully with firmware 10.2.4.70.6-2. When the module is loaded with (newly implemented) modparam rawmode=1, it will enable operating an open mesh STA via something like the following: ip link set wlan0 down iw dev wlan0 set type mp ip link set wlan0 up iw dev wlan0 set freq 5745 80 5775 iw dev wlan0 mesh join mesh-vht Signed-off-by: Bob Copeland Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 12 ++++++++++++ drivers/net/wireless/ath/ath10k/mac.c | 36 +++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 6e5033bac2b4..09a74a8e082e 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -34,16 +34,19 @@ unsigned int ath10k_debug_mask; static unsigned int ath10k_cryptmode_param; static bool uart_print; static bool skip_otp; +static bool rawmode; module_param_named(debug_mask, ath10k_debug_mask, uint, 0644); module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644); module_param(uart_print, bool, 0644); module_param(skip_otp, bool, 0644); +module_param(rawmode, bool, 0644); MODULE_PARM_DESC(debug_mask, "Debugging mask"); MODULE_PARM_DESC(uart_print, "Uart target debugging"); MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode"); MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software"); +MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath"); static const struct ath10k_hw_params ath10k_hw_params_list[] = { { @@ -1122,6 +1125,15 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT; ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT; + if (rawmode) { + if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT, + ar->fw_features)) { + ath10k_err(ar, "rawmode = 1 requires support from firmware"); + return -EINVAL; + } + set_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags); + } + if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_RAW; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 80efcc8debfe..1cda4f9dd453 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4211,6 +4211,14 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, case NL80211_IFTYPE_ADHOC: arvif->vdev_type = WMI_VDEV_TYPE_IBSS; break; + case NL80211_IFTYPE_MESH_POINT: + if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { + ret = -EINVAL; + ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n"); + goto err; + } + arvif->vdev_type = WMI_VDEV_TYPE_AP; + break; case NL80211_IFTYPE_AP: arvif->vdev_type = WMI_VDEV_TYPE_AP; @@ -4251,6 +4259,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, * become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap. */ if (vif->type == NL80211_IFTYPE_ADHOC || + vif->type == NL80211_IFTYPE_MESH_POINT || vif->type == NL80211_IFTYPE_AP) { arvif->beacon_buf = dma_zalloc_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, @@ -4590,6 +4599,13 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, if (ret) ath10k_warn(ar, "failed to update beacon template: %d\n", ret); + + if (ieee80211_vif_is_mesh(vif)) { + /* mesh doesn't use SSID but firmware needs it */ + strncpy(arvif->u.ap.ssid, "mesh", + sizeof(arvif->u.ap.ssid)); + arvif->u.ap.ssid_len = 4; + } } if (changed & BSS_CHANGED_AP_PROBE_RESP) { @@ -5329,6 +5345,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, } else if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC && (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT || vif->type == NL80211_IFTYPE_ADHOC)) { /* * New association. @@ -5364,6 +5381,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTH && (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT || vif->type == NL80211_IFTYPE_ADHOC)) { /* * Disassociation. @@ -6678,6 +6696,9 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = { { .max = 7, .types = BIT(NL80211_IFTYPE_AP) +#ifdef CONFIG_MAC80211_MESH + | BIT(NL80211_IFTYPE_MESH_POINT) +#endif }, }; @@ -6685,6 +6706,9 @@ static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = { { .max = 8, .types = BIT(NL80211_IFTYPE_AP) +#ifdef CONFIG_MAC80211_MESH + | BIT(NL80211_IFTYPE_MESH_POINT) +#endif }, }; @@ -6722,6 +6746,9 @@ static const struct ieee80211_iface_limit ath10k_tlv_if_limit[] = { { .max = 2, .types = BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO), }, @@ -6743,6 +6770,9 @@ static const struct ieee80211_iface_limit ath10k_tlv_qcs_if_limit[] = { { .max = 1, .types = BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH + BIT(NL80211_IFTYPE_MESH_POINT) | +#endif BIT(NL80211_IFTYPE_P2P_GO), }, { @@ -6809,6 +6839,9 @@ static const struct ieee80211_iface_limit ath10k_10_4_if_limits[] = { { .max = 16, .types = BIT(NL80211_IFTYPE_AP) +#ifdef CONFIG_MAC80211_MESH + | BIT(NL80211_IFTYPE_MESH_POINT) +#endif }, }; @@ -7033,7 +7066,8 @@ int ath10k_mac_register(struct ath10k *ar) ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP); + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_MESH_POINT); ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask; ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask; -- cgit v1.2.3 From 634349bae0b2a23f71cabbdb770d35fffc1aad8c Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 3 Sep 2015 10:43:45 +0200 Subject: ath10k: move hw_scan worker queuing The remain_on_channel callback needs different timeout. Calling ieee80211_queue_work() with a shorter delay after calling it with a longer delay will not change the timer. This caused the offchannel timeout worker to not trigger in time and caused the device to stay on channel longer then expected. This could cause some problems and was be easily reproduced with `iw offchannel` command. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 1cda4f9dd453..c7e3165d6cd7 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3618,9 +3618,6 @@ static int ath10k_start_scan(struct ath10k *ar, } spin_unlock_bh(&ar->data_lock); - /* Add a 200ms margin to account for event/command processing */ - ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout, - msecs_to_jiffies(arg->max_scan_time+200)); return 0; } @@ -4803,6 +4800,11 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw, spin_unlock_bh(&ar->data_lock); } + /* Add a 200ms margin to account for event/command processing */ + ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout, + msecs_to_jiffies(arg.max_scan_time + + 200)); + exit: mutex_unlock(&ar->conf_mutex); return ret; -- cgit v1.2.3 From 7be6d1b7625ab20e1dfde07a0c6dc77784efbb48 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 3 Sep 2015 10:44:51 +0200 Subject: ath10k: split switch_vif_chanctx guts This is necessary to make vdev restarting logic reusable later. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 168 ++++++++++++++++++---------------- 1 file changed, 89 insertions(+), 79 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index c7e3165d6cd7..eee5aa9636f8 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6274,6 +6274,94 @@ ath10k_mac_update_rx_channel(struct ath10k *ar, rcu_read_unlock(); } +static void +ath10k_mac_update_vif_chan(struct ath10k *ar, + struct ieee80211_vif_chanctx_switch *vifs, + int n_vifs) +{ + struct ath10k_vif *arvif; + int ret; + int i; + + lockdep_assert_held(&ar->conf_mutex); + + /* First stop monitor interface. Some FW versions crash if there's a + * lone monitor interface. + */ + if (ar->monitor_started) + ath10k_monitor_stop(ar); + + for (i = 0; i < n_vifs; i++) { + arvif = ath10k_vif_to_arvif(vifs[i].vif); + + ath10k_dbg(ar, ATH10K_DBG_MAC, + "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n", + arvif->vdev_id, + vifs[i].old_ctx->def.chan->center_freq, + vifs[i].new_ctx->def.chan->center_freq, + vifs[i].old_ctx->def.width, + vifs[i].new_ctx->def.width); + + if (WARN_ON(!arvif->is_started)) + continue; + + if (WARN_ON(!arvif->is_up)) + continue; + + ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); + if (ret) { + ath10k_warn(ar, "failed to down vdev %d: %d\n", + arvif->vdev_id, ret); + continue; + } + } + + /* All relevant vdevs are downed and associated channel resources + * should be available for the channel switch now. + */ + + spin_lock_bh(&ar->data_lock); + ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs); + spin_unlock_bh(&ar->data_lock); + + for (i = 0; i < n_vifs; i++) { + arvif = ath10k_vif_to_arvif(vifs[i].vif); + + if (WARN_ON(!arvif->is_started)) + continue; + + if (WARN_ON(!arvif->is_up)) + continue; + + ret = ath10k_mac_setup_bcn_tmpl(arvif); + if (ret) + ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n", + ret); + + ret = ath10k_mac_setup_prb_tmpl(arvif); + if (ret) + ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n", + ret); + + ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def); + if (ret) { + ath10k_warn(ar, "failed to restart vdev %d: %d\n", + arvif->vdev_id, ret); + continue; + } + + ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, + arvif->bssid); + if (ret) { + ath10k_warn(ar, "failed to bring vdev up %d: %d\n", + arvif->vdev_id, ret); + continue; + } + } + + ath10k_monitor_recalc(ar); +} + static int ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) @@ -6458,91 +6546,13 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, enum ieee80211_chanctx_switch_mode mode) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif; - int ret; - int i; mutex_lock(&ar->conf_mutex); ath10k_dbg(ar, ATH10K_DBG_MAC, "mac chanctx switch n_vifs %d mode %d\n", n_vifs, mode); - - /* First stop monitor interface. Some FW versions crash if there's a - * lone monitor interface. - */ - if (ar->monitor_started) - ath10k_monitor_stop(ar); - - for (i = 0; i < n_vifs; i++) { - arvif = ath10k_vif_to_arvif(vifs[i].vif); - - ath10k_dbg(ar, ATH10K_DBG_MAC, - "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n", - arvif->vdev_id, - vifs[i].old_ctx->def.chan->center_freq, - vifs[i].new_ctx->def.chan->center_freq, - vifs[i].old_ctx->def.width, - vifs[i].new_ctx->def.width); - - if (WARN_ON(!arvif->is_started)) - continue; - - if (WARN_ON(!arvif->is_up)) - continue; - - ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); - if (ret) { - ath10k_warn(ar, "failed to down vdev %d: %d\n", - arvif->vdev_id, ret); - continue; - } - } - - /* All relevant vdevs are downed and associated channel resources - * should be available for the channel switch now. - */ - - spin_lock_bh(&ar->data_lock); - ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs); - spin_unlock_bh(&ar->data_lock); - - for (i = 0; i < n_vifs; i++) { - arvif = ath10k_vif_to_arvif(vifs[i].vif); - - if (WARN_ON(!arvif->is_started)) - continue; - - if (WARN_ON(!arvif->is_up)) - continue; - - ret = ath10k_mac_setup_bcn_tmpl(arvif); - if (ret) - ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n", - ret); - - ret = ath10k_mac_setup_prb_tmpl(arvif); - if (ret) - ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n", - ret); - - ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def); - if (ret) { - ath10k_warn(ar, "failed to restart vdev %d: %d\n", - arvif->vdev_id, ret); - continue; - } - - ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, - arvif->bssid); - if (ret) { - ath10k_warn(ar, "failed to bring vdev up %d: %d\n", - arvif->vdev_id, ret); - continue; - } - } - - ath10k_monitor_recalc(ar); + ath10k_mac_update_vif_chan(ar, vifs, n_vifs); mutex_unlock(&ar->conf_mutex); return 0; -- cgit v1.2.3 From 9713e3de801eb9c2dd2221ba8c1dddd5bc7ba360 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 3 Sep 2015 10:44:52 +0200 Subject: ath10k: handle IEEE80211_CHANCTX_CHANGE_WIDTH properly Vdevs associated with a given chanctx should be restarted if the bandwidth changes. Otherwise traffic may cease. This is known to fix STA CSA with bandwidths wider than 20MHz. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index eee5aa9636f8..bb4416186b2b 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6408,12 +6408,52 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw, mutex_unlock(&ar->conf_mutex); } +struct ath10k_mac_change_chanctx_arg { + struct ieee80211_chanctx_conf *ctx; + struct ieee80211_vif_chanctx_switch *vifs; + int n_vifs; + int next_vif; +}; + +static void +ath10k_mac_change_chanctx_cnt_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct ath10k_mac_change_chanctx_arg *arg = data; + + if (rcu_access_pointer(vif->chanctx_conf) != arg->ctx) + return; + + arg->n_vifs++; +} + +static void +ath10k_mac_change_chanctx_fill_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct ath10k_mac_change_chanctx_arg *arg = data; + struct ieee80211_chanctx_conf *ctx; + + ctx = rcu_access_pointer(vif->chanctx_conf); + if (ctx != arg->ctx) + return; + + if (WARN_ON(arg->next_vif == arg->n_vifs)) + return; + + arg->vifs[arg->next_vif].vif = vif; + arg->vifs[arg->next_vif].old_ctx = ctx; + arg->vifs[arg->next_vif].new_ctx = ctx; + arg->next_vif++; +} + static void ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx, u32 changed) { struct ath10k *ar = hw->priv; + struct ath10k_mac_change_chanctx_arg arg = { .ctx = ctx }; mutex_lock(&ar->conf_mutex); @@ -6427,6 +6467,30 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw, if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL)) goto unlock; + if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) { + ieee80211_iterate_active_interfaces_atomic( + hw, + IEEE80211_IFACE_ITER_NORMAL, + ath10k_mac_change_chanctx_cnt_iter, + &arg); + if (arg.n_vifs == 0) + goto radar; + + arg.vifs = kcalloc(arg.n_vifs, sizeof(arg.vifs[0]), + GFP_KERNEL); + if (!arg.vifs) + goto radar; + + ieee80211_iterate_active_interfaces_atomic( + hw, + IEEE80211_IFACE_ITER_NORMAL, + ath10k_mac_change_chanctx_fill_iter, + &arg); + ath10k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs); + kfree(arg.vifs); + } + +radar: ath10k_recalc_radar_detection(ar); /* FIXME: How to configure Rx chains properly? */ -- cgit v1.2.3 From 5af82fa66a7ee8dfc29fadb487a02e2ef14ea965 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Wed, 9 Sep 2015 11:34:37 +0300 Subject: ath10k: add ATH10K_FW_FEATURE_RAW_MODE_SUPPORT to ath10k_core_fw_feature_str[] This was missed in the original commit adding the flag and ath10k only printed "bit10": ath10k_pci 0000:02:00.0: qca988x hw2.0 (0x4100016c, 0x043202ff) fw 10.2.4.70.6-2 api 3 htt-ver 2.1 wmi-op 5 htt-op 2 cal otp max-sta 128 raw 0 hwcrypto 1 features no-p2p,bit10 Also add a build test to avoid this happening again. Fixes: ccec9038c721 ("ath10k: enable raw encap mode and software crypto engine") Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 09a74a8e082e..879625adc63a 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -150,12 +150,17 @@ static const char *const ath10k_core_fw_feature_str[] = { [ATH10K_FW_FEATURE_IGNORE_OTP_RESULT] = "ignore-otp", [ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad", [ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init", + [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode", }; static unsigned int ath10k_core_get_fw_feature_str(char *buf, size_t buf_len, enum ath10k_fw_features feat) { + /* make sure that ath10k_core_fw_feature_str[] gets updated */ + BUILD_BUG_ON(ARRAY_SIZE(ath10k_core_fw_feature_str) != + ATH10K_FW_FEATURE_COUNT); + if (feat >= ARRAY_SIZE(ath10k_core_fw_feature_str) || WARN_ON(!ath10k_core_fw_feature_str[feat])) { return scnprintf(buf, buf_len, "bit%d", feat); -- cgit v1.2.3 From 346ce4bbddfd40aa62b899db8982c728ed3d42a5 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Thu, 27 Aug 2015 21:49:17 +0200 Subject: at86rf230: change trac status check behaviour When transmit is done, indicated by trx_end irq, we do first a force state change to TX_ON and then checking the trac status, if the trac status is unequal zero we do a state change to TRX_OFF. This patch changes to the following behaviour, we first check on trac status after trx_end occurs and then doing a normal change to TX_ON without do the state change to TRX_OFF when trac status is unequal zero. The reasons are that the datasheet doesn't described when the trac status register is cleared, we should doing to evaluate the trac status at first. The reason to remove the TRX_OFF change if the trac status is unequal to zero and it was force is the following paragraph inside The at86rf2xx datasheets: "Using FORCE_PLL_ON to interrupt an TX_ARET transaction, it is recommended to check register bits [7:5] of register address 0x32 for value 0. If this value is different, TRX_CMD sequence FORCE_TRX_OFF shall be used immediately followed by TRX_CMD sequence PLL_ON. This performs a state transition to PLL_ON." The meaning is here "to interrupt an TX_ARET transaction" in case of trx_end interrupt the "TX_ARET transaction" is already done and we don't interrupt the "TX_ARET transaction" by doing the change to TX_ON (PLL_ON) here. Additional I changed the force change to normal TX_ON which seems to work here. Signed-off-by: Alexander Aring Reviewed-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/at86rf230.c | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 6422caac8d40..39485d06bea1 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -667,28 +667,9 @@ at86rf230_tx_trac_check(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; - const u8 *buf = ctx->buf; - const u8 trac = (buf[1] & 0xe0) >> 5; - /* If trac status is different than zero we need to do a state change - * to STATE_FORCE_TRX_OFF then STATE_RX_AACK_ON to recover the - * transceiver. - */ - if (trac) - at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF, - at86rf230_tx_on, true); - else - at86rf230_tx_on(context); -} - -static void -at86rf230_tx_trac_status(void *context) -{ - struct at86rf230_state_change *ctx = context; - struct at86rf230_local *lp = ctx->lp; - - at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx, - at86rf230_tx_trac_check, true); + at86rf230_async_state_change(lp, &lp->irq, STATE_TX_ON, + at86rf230_tx_on, true); } static void @@ -758,10 +739,8 @@ at86rf230_irq_trx_end(struct at86rf230_local *lp) { if (lp->is_tx) { lp->is_tx = 0; - at86rf230_async_state_change(lp, &lp->irq, - STATE_FORCE_TX_ON, - at86rf230_tx_trac_status, - true); + at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq, + at86rf230_tx_trac_check, true); } else { at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq, at86rf230_rx_trac_check, true); -- cgit v1.2.3 From ed4a26b0995baf10807ebb3f18fba3db2c6539fc Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Thu, 27 Aug 2015 21:49:18 +0200 Subject: at86rf230: interrupt tx with force trx_off To abort a TX_ARET_BUSY state it's recommended to switch into TRX_OFF state by doing STATE_TRX_FORCE_OFF. This patch will do always a TRX_OFF state change when the transceiver stucks in any state. From TRX_OFF we can switch to the states which are also possible by TX_ON state. Signed-off-by: Alexander Aring Reviewed-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/at86rf230.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 39485d06bea1..1e71a9781f33 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -377,14 +377,6 @@ at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg, } } -static inline u8 at86rf230_state_to_force(u8 state) -{ - if (state == STATE_TX_ON) - return STATE_FORCE_TX_ON; - else - return STATE_FORCE_TRX_OFF; -} - static void at86rf230_async_state_assert(void *context) { @@ -426,7 +418,7 @@ at86rf230_async_state_assert(void *context) u8 state = ctx->to_state; if (lp->tx_retry >= AT86RF2XX_MAX_TX_RETRIES) - state = at86rf230_state_to_force(state); + state = STATE_FORCE_TRX_OFF; lp->tx_retry++; at86rf230_async_state_change(lp, ctx, state, -- cgit v1.2.3 From 493bc90a96839ffde5e6216c62c025d2f9e6efc3 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Thu, 27 Aug 2015 21:49:19 +0200 Subject: at86rf230: add debugfs support This patch introduce debugfs support for collect trac status stats. To clear the stats ifdown the interface of at86rf230 and start the interface again. Signed-off-by: Alexander Aring Reviewed-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/Kconfig | 7 ++ drivers/net/ieee802154/at86rf230.c | 158 +++++++++++++++++++++++++++++++++---- drivers/net/ieee802154/at86rf230.h | 8 ++ 3 files changed, 159 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig index 1dd5ab8e5054..5a614b2d0767 100644 --- a/drivers/net/ieee802154/Kconfig +++ b/drivers/net/ieee802154/Kconfig @@ -32,6 +32,13 @@ config IEEE802154_AT86RF230 This driver can also be built as a module. To do so, say M here. the module will be called 'at86rf230'. +config IEEE802154_AT86RF230_DEBUGFS + depends on IEEE802154_AT86RF230 + bool "AT86RF230 debugfs interface" + depends on DEBUG_FS + ---help--- + This option compiles debugfs code for the at86rf230 driver. + config IEEE802154_MRF24J40 tristate "Microchip MRF24J40 transceiver driver" depends on IEEE802154_DRIVERS && MAC802154 diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 1e71a9781f33..19c16b97659c 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -83,6 +84,15 @@ struct at86rf230_state_change { bool irq_enable; }; +struct at86rf230_trac { + u64 success; + u64 success_data_pending; + u64 success_wait_for_ack; + u64 channel_access_failure; + u64 no_ack; + u64 invalid; +}; + struct at86rf230_local { struct spi_device *spi; @@ -103,6 +113,8 @@ struct at86rf230_local { u8 tx_retry; struct sk_buff *tx_skb; struct at86rf230_state_change tx; + + struct at86rf230_trac trac; }; #define AT86RF2XX_NUMREGS 0x3F @@ -660,6 +672,31 @@ at86rf230_tx_trac_check(void *context) struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; + if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) { + u8 trac = TRAC_MASK(ctx->buf[1]); + + switch (trac) { + case TRAC_SUCCESS: + lp->trac.success++; + break; + case TRAC_SUCCESS_DATA_PENDING: + lp->trac.success_data_pending++; + break; + case TRAC_CHANNEL_ACCESS_FAILURE: + lp->trac.channel_access_failure++; + break; + case TRAC_NO_ACK: + lp->trac.no_ack++; + break; + case TRAC_INVALID: + lp->trac.invalid++; + break; + default: + WARN_ONCE(1, "received tx trac status %d\n", trac); + break; + } + } + at86rf230_async_state_change(lp, &lp->irq, STATE_TX_ON, at86rf230_tx_on, true); } @@ -696,13 +733,32 @@ at86rf230_rx_read_frame_complete(void *context) } static void -at86rf230_rx_read_frame(void *context) +at86rf230_rx_trac_check(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; u8 *buf = ctx->buf; int rc; + if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) { + u8 trac = TRAC_MASK(buf[1]); + + switch (trac) { + case TRAC_SUCCESS: + lp->trac.success++; + break; + case TRAC_SUCCESS_WAIT_FOR_ACK: + lp->trac.success_wait_for_ack++; + break; + case TRAC_INVALID: + lp->trac.invalid++; + break; + default: + WARN_ONCE(1, "received rx trac status %d\n", trac); + break; + } + } + buf[0] = CMD_FB; ctx->trx.len = AT86RF2XX_MAX_BUF; ctx->msg.complete = at86rf230_rx_read_frame_complete; @@ -714,18 +770,6 @@ at86rf230_rx_read_frame(void *context) } } -static void -at86rf230_rx_trac_check(void *context) -{ - /* Possible check on trac status here. This could be useful to make - * some stats why receive is failed. Not used at the moment, but it's - * maybe timing relevant. Datasheet doesn't say anything about this. - * The programming guide say do it so. - */ - - at86rf230_rx_read_frame(context); -} - static void at86rf230_irq_trx_end(struct at86rf230_local *lp) { @@ -891,6 +935,10 @@ at86rf230_start(struct ieee802154_hw *hw) { struct at86rf230_local *lp = hw->priv; + /* reset trac stats on start */ + if (IS_ENABLED(CONFIG_IEEE802154_AT86RF230_DEBUGFS)) + memset(&lp->trac, 0, sizeof(struct at86rf230_trac)); + at86rf230_awake(lp); enable_irq(lp->spi->irq); @@ -1591,6 +1639,81 @@ at86rf230_setup_spi_messages(struct at86rf230_local *lp) lp->tx.timer.function = at86rf230_async_state_timer; } +#ifdef CONFIG_IEEE802154_AT86RF230_DEBUGFS +static struct dentry *at86rf230_debugfs_root; + +static int at86rf230_stats_show(struct seq_file *file, void *offset) +{ + struct at86rf230_local *lp = file->private; + int ret; + + ret = seq_printf(file, "SUCCESS:\t\t%8llu\n", lp->trac.success); + if (ret < 0) + return ret; + + ret = seq_printf(file, "SUCCESS_DATA_PENDING:\t%8llu\n", + lp->trac.success_data_pending); + if (ret < 0) + return ret; + + ret = seq_printf(file, "SUCCESS_WAIT_FOR_ACK:\t%8llu\n", + lp->trac.success_wait_for_ack); + if (ret < 0) + return ret; + + ret = seq_printf(file, "CHANNEL_ACCESS_FAILURE:\t%8llu\n", + lp->trac.channel_access_failure); + if (ret < 0) + return ret; + + ret = seq_printf(file, "NO_ACK:\t\t\t%8llu\n", lp->trac.no_ack); + if (ret < 0) + return ret; + + return seq_printf(file, "INVALID:\t\t%8llu\n", lp->trac.invalid); +} + +static int at86rf230_stats_open(struct inode *inode, struct file *file) +{ + return single_open(file, at86rf230_stats_show, inode->i_private); +} + +static const struct file_operations at86rf230_stats_fops = { + .open = at86rf230_stats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int at86rf230_debugfs_init(struct at86rf230_local *lp) +{ + char debugfs_dir_name[DNAME_INLINE_LEN + 1] = "at86rf230-"; + struct dentry *stats; + + strncat(debugfs_dir_name, dev_name(&lp->spi->dev), DNAME_INLINE_LEN); + + at86rf230_debugfs_root = debugfs_create_dir(debugfs_dir_name, NULL); + if (!at86rf230_debugfs_root) + return -ENOMEM; + + stats = debugfs_create_file("trac_stats", S_IRUGO, + at86rf230_debugfs_root, lp, + &at86rf230_stats_fops); + if (!stats) + return -ENOMEM; + + return 0; +} + +static void at86rf230_debugfs_remove(void) +{ + debugfs_remove_recursive(at86rf230_debugfs_root); +} +#else +static int at86rf230_debugfs_init(struct at86rf230_local *lp) { return 0; } +static void at86rf230_debugfs_remove(void) { } +#endif + static int at86rf230_probe(struct spi_device *spi) { struct ieee802154_hw *hw; @@ -1686,12 +1809,18 @@ static int at86rf230_probe(struct spi_device *spi) /* going into sleep by default */ at86rf230_sleep(lp); - rc = ieee802154_register_hw(lp->hw); + rc = at86rf230_debugfs_init(lp); if (rc) goto free_dev; + rc = ieee802154_register_hw(lp->hw); + if (rc) + goto free_debugfs; + return rc; +free_debugfs: + at86rf230_debugfs_remove(); free_dev: ieee802154_free_hw(lp->hw); @@ -1706,6 +1835,7 @@ static int at86rf230_remove(struct spi_device *spi) at86rf230_write_subreg(lp, SR_IRQ_MASK, 0); ieee802154_unregister_hw(lp->hw); ieee802154_free_hw(lp->hw); + at86rf230_debugfs_remove(); dev_dbg(&spi->dev, "unregistered at86rf230\n"); return 0; diff --git a/drivers/net/ieee802154/at86rf230.h b/drivers/net/ieee802154/at86rf230.h index 1e6d1cc677f6..fd9c1f467f63 100644 --- a/drivers/net/ieee802154/at86rf230.h +++ b/drivers/net/ieee802154/at86rf230.h @@ -216,5 +216,13 @@ #define STATE_TRANSITION_IN_PROGRESS 0x1F #define TRX_STATE_MASK (0x1F) +#define TRAC_MASK(x) ((x & 0xe0) >> 5) + +#define TRAC_SUCCESS 0 +#define TRAC_SUCCESS_DATA_PENDING 1 +#define TRAC_SUCCESS_WAIT_FOR_ACK 2 +#define TRAC_CHANNEL_ACCESS_FAILURE 3 +#define TRAC_NO_ACK 5 +#define TRAC_INVALID 7 #endif /* !_AT86RF230_H */ -- cgit v1.2.3 From 5c3c4736370961a121994cffd87f4dddc95ea8f2 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Thu, 27 Aug 2015 21:49:20 +0200 Subject: at86rf230: detailed edge triggered irq warning This patch introduce a more detailed information why edge triggered irq's are currently not recommended. It could be that rising/falling edge detection can happen while the irq is disabled. Suggested-by: Stefan Schmidt Signed-off-by: Alexander Aring Reviewed-by: Stefan Schmidt Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/at86rf230.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 19c16b97659c..b8b0628dc2f3 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1376,7 +1376,7 @@ static int at86rf230_hw_init(struct at86rf230_local *lp, u8 xtal_trim) if (irq_type == IRQ_TYPE_EDGE_RISING || irq_type == IRQ_TYPE_EDGE_FALLING) dev_warn(&lp->spi->dev, - "Using edge triggered irq's are not recommended!\n"); + "Using edge triggered irq's are not recommended, because it can cause races and result in a non-functional driver!\n"); if (irq_type == IRQ_TYPE_EDGE_FALLING || irq_type == IRQ_TYPE_LEVEL_LOW) irq_pol = IRQ_ACTIVE_LOW; -- cgit v1.2.3 From 9def9afde77a298bfc6ad84a6c5a9e9523aa8bab Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sat, 5 Sep 2015 12:27:59 +0200 Subject: atusb: add handling for different chipnames This patch supports handling for printout different chipnames between atusb and rzusb. The rzusb contains an at86rf230 and atusb an at86rf231 transceiver. Cc: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/atusb.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index 80dfc725b8dc..199a94a9c8bc 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -559,6 +559,7 @@ static int atusb_get_and_show_chip(struct atusb *atusb) { struct usb_device *usb_dev = atusb->usb_dev; uint8_t man_id_0, man_id_1, part_num, version_num; + const char *chip; man_id_0 = atusb_read_reg(atusb, RG_MAN_ID_0); man_id_1 = atusb_read_reg(atusb, RG_MAN_ID_1); @@ -574,14 +575,22 @@ static int atusb_get_and_show_chip(struct atusb *atusb) man_id_1, man_id_0); goto fail; } - if (part_num != 3 && part_num != 2) { + + switch (part_num) { + case 2: + chip = "AT86RF230"; + break; + case 3: + chip = "AT86RF231"; + break; + default: dev_err(&usb_dev->dev, "unexpected transceiver, part 0x%02x version 0x%02x\n", part_num, version_num); goto fail; } - dev_info(&usb_dev->dev, "ATUSB: AT86RF231 version %d\n", version_num); + dev_info(&usb_dev->dev, "ATUSB: %s version %d\n", chip, version_num); return 0; -- cgit v1.2.3 From d24c8f24ea897ae89738b865a41b0a5d70137c46 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Thu, 10 Sep 2015 21:26:04 +0200 Subject: net: smc91x: convert pxa dma to dmaengine Convert the dma transfers to be dmaengine based, now pxa has a dmaengine slave driver. This makes this driver a bit more PXA agnostic. The driver was tested on pxa27x (mainstone) and pxa310 (zylonite), ie. only pxa platforms. Signed-off-by: Robert Jarzmik Cc: Russell King Cc: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/smsc/smc91x.c | 29 +++++++---- drivers/net/ethernet/smsc/smc91x.h | 99 +++++++++++++++++++++++++------------- 2 files changed, 84 insertions(+), 44 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 630f0b7800e4..0e2fc1a844ab 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -2018,10 +2018,18 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr, lp->cfg.flags |= SMC91X_USE_DMA; # endif if (lp->cfg.flags & SMC91X_USE_DMA) { - int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW, - smc_pxa_dma_irq, NULL); - if (dma >= 0) - dev->dma = dma; + dma_cap_mask_t mask; + struct pxad_param param; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + param.prio = PXAD_PRIO_LOWEST; + param.drcmr = -1UL; + + lp->dma_chan = + dma_request_slave_channel_compat(mask, pxad_filter_fn, + ¶m, &dev->dev, + "data"); } #endif @@ -2032,8 +2040,8 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr, version_string, revision_register & 0x0f, lp->base, dev->irq); - if (dev->dma != (unsigned char)-1) - pr_cont(" DMA %d", dev->dma); + if (lp->dma_chan) + pr_cont(" DMA %p", lp->dma_chan); pr_cont("%s%s\n", lp->cfg.flags & SMC91X_NOWAIT ? " [nowait]" : "", @@ -2058,8 +2066,8 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr, err_out: #ifdef CONFIG_ARCH_PXA - if (retval && dev->dma != (unsigned char)-1) - pxa_free_dma(dev->dma); + if (retval && lp->dma_chan) + dma_release_channel(lp->dma_chan); #endif return retval; } @@ -2370,6 +2378,7 @@ static int smc_drv_probe(struct platform_device *pdev) struct smc_local *lp = netdev_priv(ndev); lp->device = &pdev->dev; lp->physaddr = res->start; + } #endif @@ -2406,8 +2415,8 @@ static int smc_drv_remove(struct platform_device *pdev) free_irq(ndev->irq, ndev); #ifdef CONFIG_ARCH_PXA - if (ndev->dma != (unsigned char)-1) - pxa_free_dma(ndev->dma); + if (lp->dma_chan) + dma_release_channel(lp->dma_chan); #endif iounmap(lp->base); diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index 3a18501d1068..a3c129e1e40a 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h @@ -33,6 +33,7 @@ #ifndef _SMC91X_H_ #define _SMC91X_H_ +#include #include /* @@ -244,6 +245,7 @@ struct smc_local { u_long physaddr; struct device *device; #endif + struct dma_chan *dma_chan; void __iomem *base; void __iomem *datacs; @@ -265,21 +267,47 @@ struct smc_local { * as RX which can overrun memory and lose packets. */ #include -#include +#include #ifdef SMC_insl #undef SMC_insl #define SMC_insl(a, r, p, l) \ smc_pxa_dma_insl(a, lp, r, dev->dma, p, l) +static inline void +smc_pxa_dma_inpump(struct smc_local *lp, u_char *buf, int len) +{ + dma_addr_t dmabuf; + struct dma_async_tx_descriptor *tx; + dma_cookie_t cookie; + enum dma_status status; + struct dma_tx_state state; + + dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE); + tx = dmaengine_prep_slave_single(lp->dma_chan, dmabuf, len, + DMA_DEV_TO_MEM, 0); + if (tx) { + cookie = dmaengine_submit(tx); + dma_async_issue_pending(lp->dma_chan); + do { + status = dmaengine_tx_status(lp->dma_chan, cookie, + &state); + cpu_relax(); + } while (status != DMA_COMPLETE && status != DMA_ERROR && + state.residue); + dmaengine_terminate_all(lp->dma_chan); + } + dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE); +} + static inline void smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma, u_char *buf, int len) { - u_long physaddr = lp->physaddr; - dma_addr_t dmabuf; + struct dma_slave_config config; + int ret; /* fallback if no DMA available */ - if (dma == (unsigned char)-1) { + if (!lp->dma_chan) { readsl(ioaddr + reg, buf, len); return; } @@ -291,18 +319,22 @@ smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma, len--; } + memset(&config, 0, sizeof(config)); + config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + config.src_addr = lp->physaddr + reg; + config.dst_addr = lp->physaddr + reg; + config.src_maxburst = 32; + config.dst_maxburst = 32; + ret = dmaengine_slave_config(lp->dma_chan, &config); + if (ret) { + dev_err(lp->device, "dma channel configuration failed: %d\n", + ret); + return; + } + len *= 4; - dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE); - DCSR(dma) = DCSR_NODESC; - DTADR(dma) = dmabuf; - DSADR(dma) = physaddr + reg; - DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | - DCMD_WIDTH4 | (DCMD_LENGTH & len)); - DCSR(dma) = DCSR_NODESC | DCSR_RUN; - while (!(DCSR(dma) & DCSR_STOPSTATE)) - cpu_relax(); - DCSR(dma) = 0; - dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE); + smc_pxa_dma_inpump(lp, buf, len); } #endif @@ -314,11 +346,11 @@ static inline void smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma, u_char *buf, int len) { - u_long physaddr = lp->physaddr; - dma_addr_t dmabuf; + struct dma_slave_config config; + int ret; /* fallback if no DMA available */ - if (dma == (unsigned char)-1) { + if (!lp->dma_chan) { readsw(ioaddr + reg, buf, len); return; } @@ -330,26 +362,25 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma, len--; } + memset(&config, 0, sizeof(config)); + config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + config.src_addr = lp->physaddr + reg; + config.dst_addr = lp->physaddr + reg; + config.src_maxburst = 32; + config.dst_maxburst = 32; + ret = dmaengine_slave_config(lp->dma_chan, &config); + if (ret) { + dev_err(lp->device, "dma channel configuration failed: %d\n", + ret); + return; + } + len *= 2; - dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE); - DCSR(dma) = DCSR_NODESC; - DTADR(dma) = dmabuf; - DSADR(dma) = physaddr + reg; - DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | - DCMD_WIDTH2 | (DCMD_LENGTH & len)); - DCSR(dma) = DCSR_NODESC | DCSR_RUN; - while (!(DCSR(dma) & DCSR_STOPSTATE)) - cpu_relax(); - DCSR(dma) = 0; - dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE); + smc_pxa_dma_inpump(lp, buf, len); } #endif -static void -smc_pxa_dma_irq(int dma, void *dummy) -{ - DCSR(dma) = 0; -} #endif /* CONFIG_ARCH_PXA */ -- cgit v1.2.3 From 0738eff14d817a02ab082c392c96a1613006f158 Mon Sep 17 00:00:00 2001 From: Gerhard Bertelsmann Date: Wed, 16 Sep 2015 13:21:22 +0200 Subject: can: Allwinner A10/A20 CAN Controller support - Kernel module Kernel module for Allwinner A10/A20 CAN controller. Signed-off-by: Gerhard Bertelsmann Acked-by: Maxime Ripard Signed-off-by: Marc Kleine-Budde --- drivers/net/can/Kconfig | 10 + drivers/net/can/Makefile | 1 + drivers/net/can/sun4i_can.c | 857 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 868 insertions(+) create mode 100644 drivers/net/can/sun4i_can.c (limited to 'drivers/net') diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index e8c96b8e86f4..6d04183ed955 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -129,6 +129,16 @@ config CAN_RCAR To compile this driver as a module, choose M here: the module will be called rcar_can. +config CAN_SUN4I + tristate "Allwinner A10 CAN controller" + depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST + ---help--- + Say Y here if you want to use CAN controller found on Allwinner + A10/A20 SoCs. + + To compile this driver as a module, choose M here: the module will + be called sun4i_can. + config CAN_XILINXCAN tristate "Xilinx CAN" depends on ARCH_ZYNQ || ARM64 || MICROBLAZE || COMPILE_TEST diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index c533c62b0f5e..1f21cef1d458 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o obj-$(CONFIG_PCH_CAN) += pch_can.o obj-$(CONFIG_CAN_GRCAN) += grcan.o obj-$(CONFIG_CAN_RCAR) += rcar_can.o +obj-$(CONFIG_CAN_SUN4I) += sun4i_can.o obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o subdir-ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c new file mode 100644 index 000000000000..10d8497635e8 --- /dev/null +++ b/drivers/net/can/sun4i_can.c @@ -0,0 +1,857 @@ +/* + * sun4i_can.c - CAN bus controller driver for Allwinner SUN4I&SUN7I based SoCs + * + * Copyright (C) 2013 Peter Chen + * Copyright (C) 2015 Gerhard Bertelsmann + * All rights reserved. + * + * Parts of this software are based on (derived from) the SJA1000 code by: + * Copyright (C) 2014 Oliver Hartkopp + * Copyright (C) 2007 Wolfgang Grandegger + * Copyright (C) 2002-2007 Volkswagen Group Electronic Research + * Copyright (C) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33, + * 38106 Braunschweig, GERMANY + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Volkswagen nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * Alternatively, provided that this notice is retained in full, this + * software may be distributed under the terms of the GNU General + * Public License ("GPL") version 2, in which case the provisions of the + * GPL apply INSTEAD OF those given above. + * + * The provided data structures and external interfaces from this code + * are not restricted to be used by modules with a GPL compatible license. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "sun4i_can" + +/* Registers address (physical base address 0x01C2BC00) */ +#define SUN4I_REG_MSEL_ADDR 0x0000 /* CAN Mode Select */ +#define SUN4I_REG_CMD_ADDR 0x0004 /* CAN Command */ +#define SUN4I_REG_STA_ADDR 0x0008 /* CAN Status */ +#define SUN4I_REG_INT_ADDR 0x000c /* CAN Interrupt Flag */ +#define SUN4I_REG_INTEN_ADDR 0x0010 /* CAN Interrupt Enable */ +#define SUN4I_REG_BTIME_ADDR 0x0014 /* CAN Bus Timing 0 */ +#define SUN4I_REG_TEWL_ADDR 0x0018 /* CAN Tx Error Warning Limit */ +#define SUN4I_REG_ERRC_ADDR 0x001c /* CAN Error Counter */ +#define SUN4I_REG_RMCNT_ADDR 0x0020 /* CAN Receive Message Counter */ +#define SUN4I_REG_RBUFSA_ADDR 0x0024 /* CAN Receive Buffer Start Address */ +#define SUN4I_REG_BUF0_ADDR 0x0040 /* CAN Tx/Rx Buffer 0 */ +#define SUN4I_REG_BUF1_ADDR 0x0044 /* CAN Tx/Rx Buffer 1 */ +#define SUN4I_REG_BUF2_ADDR 0x0048 /* CAN Tx/Rx Buffer 2 */ +#define SUN4I_REG_BUF3_ADDR 0x004c /* CAN Tx/Rx Buffer 3 */ +#define SUN4I_REG_BUF4_ADDR 0x0050 /* CAN Tx/Rx Buffer 4 */ +#define SUN4I_REG_BUF5_ADDR 0x0054 /* CAN Tx/Rx Buffer 5 */ +#define SUN4I_REG_BUF6_ADDR 0x0058 /* CAN Tx/Rx Buffer 6 */ +#define SUN4I_REG_BUF7_ADDR 0x005c /* CAN Tx/Rx Buffer 7 */ +#define SUN4I_REG_BUF8_ADDR 0x0060 /* CAN Tx/Rx Buffer 8 */ +#define SUN4I_REG_BUF9_ADDR 0x0064 /* CAN Tx/Rx Buffer 9 */ +#define SUN4I_REG_BUF10_ADDR 0x0068 /* CAN Tx/Rx Buffer 10 */ +#define SUN4I_REG_BUF11_ADDR 0x006c /* CAN Tx/Rx Buffer 11 */ +#define SUN4I_REG_BUF12_ADDR 0x0070 /* CAN Tx/Rx Buffer 12 */ +#define SUN4I_REG_ACPC_ADDR 0x0040 /* CAN Acceptance Code 0 */ +#define SUN4I_REG_ACPM_ADDR 0x0044 /* CAN Acceptance Mask 0 */ +#define SUN4I_REG_RBUF_RBACK_START_ADDR 0x0180 /* CAN transmit buffer start */ +#define SUN4I_REG_RBUF_RBACK_END_ADDR 0x01b0 /* CAN transmit buffer end */ + +/* Controller Register Description */ + +/* mode select register (r/w) + * offset:0x0000 default:0x0000_0001 + */ +#define SUN4I_MSEL_SLEEP_MODE (0x01 << 4) /* write in reset mode */ +#define SUN4I_MSEL_WAKE_UP (0x00 << 4) +#define SUN4I_MSEL_SINGLE_FILTER (0x01 << 3) /* write in reset mode */ +#define SUN4I_MSEL_DUAL_FILTERS (0x00 << 3) +#define SUN4I_MSEL_LOOPBACK_MODE BIT(2) +#define SUN4I_MSEL_LISTEN_ONLY_MODE BIT(1) +#define SUN4I_MSEL_RESET_MODE BIT(0) + +/* command register (w) + * offset:0x0004 default:0x0000_0000 + */ +#define SUN4I_CMD_BUS_OFF_REQ BIT(5) +#define SUN4I_CMD_SELF_RCV_REQ BIT(4) +#define SUN4I_CMD_CLEAR_OR_FLAG BIT(3) +#define SUN4I_CMD_RELEASE_RBUF BIT(2) +#define SUN4I_CMD_ABORT_REQ BIT(1) +#define SUN4I_CMD_TRANS_REQ BIT(0) + +/* status register (r) + * offset:0x0008 default:0x0000_003c + */ +#define SUN4I_STA_BIT_ERR (0x00 << 22) +#define SUN4I_STA_FORM_ERR (0x01 << 22) +#define SUN4I_STA_STUFF_ERR (0x02 << 22) +#define SUN4I_STA_OTHER_ERR (0x03 << 22) +#define SUN4I_STA_MASK_ERR (0x03 << 22) +#define SUN4I_STA_ERR_DIR BIT(21) +#define SUN4I_STA_ERR_SEG_CODE (0x1f << 16) +#define SUN4I_STA_START (0x03 << 16) +#define SUN4I_STA_ID28_21 (0x02 << 16) +#define SUN4I_STA_ID20_18 (0x06 << 16) +#define SUN4I_STA_SRTR (0x04 << 16) +#define SUN4I_STA_IDE (0x05 << 16) +#define SUN4I_STA_ID17_13 (0x07 << 16) +#define SUN4I_STA_ID12_5 (0x0f << 16) +#define SUN4I_STA_ID4_0 (0x0e << 16) +#define SUN4I_STA_RTR (0x0c << 16) +#define SUN4I_STA_RB1 (0x0d << 16) +#define SUN4I_STA_RB0 (0x09 << 16) +#define SUN4I_STA_DLEN (0x0b << 16) +#define SUN4I_STA_DATA_FIELD (0x0a << 16) +#define SUN4I_STA_CRC_SEQUENCE (0x08 << 16) +#define SUN4I_STA_CRC_DELIMITER (0x18 << 16) +#define SUN4I_STA_ACK (0x19 << 16) +#define SUN4I_STA_ACK_DELIMITER (0x1b << 16) +#define SUN4I_STA_END (0x1a << 16) +#define SUN4I_STA_INTERMISSION (0x12 << 16) +#define SUN4I_STA_ACTIVE_ERROR (0x11 << 16) +#define SUN4I_STA_PASSIVE_ERROR (0x16 << 16) +#define SUN4I_STA_TOLERATE_DOMINANT_BITS (0x13 << 16) +#define SUN4I_STA_ERROR_DELIMITER (0x17 << 16) +#define SUN4I_STA_OVERLOAD (0x1c << 16) +#define SUN4I_STA_BUS_OFF BIT(7) +#define SUN4I_STA_ERR_STA BIT(6) +#define SUN4I_STA_TRANS_BUSY BIT(5) +#define SUN4I_STA_RCV_BUSY BIT(4) +#define SUN4I_STA_TRANS_OVER BIT(3) +#define SUN4I_STA_TBUF_RDY BIT(2) +#define SUN4I_STA_DATA_ORUN BIT(1) +#define SUN4I_STA_RBUF_RDY BIT(0) + +/* interrupt register (r) + * offset:0x000c default:0x0000_0000 + */ +#define SUN4I_INT_BUS_ERR BIT(7) +#define SUN4I_INT_ARB_LOST BIT(6) +#define SUN4I_INT_ERR_PASSIVE BIT(5) +#define SUN4I_INT_WAKEUP BIT(4) +#define SUN4I_INT_DATA_OR BIT(3) +#define SUN4I_INT_ERR_WRN BIT(2) +#define SUN4I_INT_TBUF_VLD BIT(1) +#define SUN4I_INT_RBUF_VLD BIT(0) + +/* interrupt enable register (r/w) + * offset:0x0010 default:0x0000_0000 + */ +#define SUN4I_INTEN_BERR BIT(7) +#define SUN4I_INTEN_ARB_LOST BIT(6) +#define SUN4I_INTEN_ERR_PASSIVE BIT(5) +#define SUN4I_INTEN_WAKEUP BIT(4) +#define SUN4I_INTEN_OR BIT(3) +#define SUN4I_INTEN_ERR_WRN BIT(2) +#define SUN4I_INTEN_TX BIT(1) +#define SUN4I_INTEN_RX BIT(0) + +/* error code */ +#define SUN4I_ERR_INRCV (0x1 << 5) +#define SUN4I_ERR_INTRANS (0x0 << 5) + +/* filter mode */ +#define SUN4I_FILTER_CLOSE 0 +#define SUN4I_SINGLE_FLTER_MODE 1 +#define SUN4I_DUAL_FILTER_MODE 2 + +/* message buffer flags */ +#define SUN4I_MSG_EFF_FLAG BIT(7) +#define SUN4I_MSG_RTR_FLAG BIT(6) + +/* max. number of interrupts handled in ISR */ +#define SUN4I_CAN_MAX_IRQ 20 +#define SUN4I_MODE_MAX_RETRIES 100 + +struct sun4ican_priv { + struct can_priv can; + void __iomem *base; + struct clk *clk; + spinlock_t cmdreg_lock; /* lock for concurrent cmd register writes */ +}; + +static const struct can_bittiming_const sun4ican_bittiming_const = { + .name = DRV_NAME, + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, +}; + +static void sun4i_can_write_cmdreg(struct sun4ican_priv *priv, u8 val) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->cmdreg_lock, flags); + writel(val, priv->base + SUN4I_REG_CMD_ADDR); + spin_unlock_irqrestore(&priv->cmdreg_lock, flags); +} + +static int set_normal_mode(struct net_device *dev) +{ + struct sun4ican_priv *priv = netdev_priv(dev); + int retry = SUN4I_MODE_MAX_RETRIES; + u32 mod_reg_val = 0; + + do { + mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR); + mod_reg_val &= ~SUN4I_MSEL_RESET_MODE; + writel(mod_reg_val, priv->base + SUN4I_REG_MSEL_ADDR); + } while (retry-- && (mod_reg_val & SUN4I_MSEL_RESET_MODE)); + + if (readl(priv->base + SUN4I_REG_MSEL_ADDR) & SUN4I_MSEL_RESET_MODE) { + netdev_err(dev, + "setting controller into normal mode failed!\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int set_reset_mode(struct net_device *dev) +{ + struct sun4ican_priv *priv = netdev_priv(dev); + int retry = SUN4I_MODE_MAX_RETRIES; + u32 mod_reg_val = 0; + + do { + mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR); + mod_reg_val |= SUN4I_MSEL_RESET_MODE; + writel(mod_reg_val, priv->base + SUN4I_REG_MSEL_ADDR); + } while (retry-- && !(mod_reg_val & SUN4I_MSEL_RESET_MODE)); + + if (!(readl(priv->base + SUN4I_REG_MSEL_ADDR) & + SUN4I_MSEL_RESET_MODE)) { + netdev_err(dev, "setting controller into reset mode failed!\n"); + return -ETIMEDOUT; + } + + return 0; +} + +/* bittiming is called in reset_mode only */ +static int sun4ican_set_bittiming(struct net_device *dev) +{ + struct sun4ican_priv *priv = netdev_priv(dev); + struct can_bittiming *bt = &priv->can.bittiming; + u32 cfg; + + cfg = ((bt->brp - 1) & 0x3FF) | + (((bt->sjw - 1) & 0x3) << 14) | + (((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) << 16) | + (((bt->phase_seg2 - 1) & 0x7) << 20); + if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) + cfg |= 0x800000; + + netdev_dbg(dev, "setting BITTIMING=0x%08x\n", cfg); + writel(cfg, priv->base + SUN4I_REG_BTIME_ADDR); + + return 0; +} + +static int sun4ican_get_berr_counter(const struct net_device *dev, + struct can_berr_counter *bec) +{ + struct sun4ican_priv *priv = netdev_priv(dev); + u32 errors; + int err; + + err = clk_prepare_enable(priv->clk); + if (err) { + netdev_err(dev, "could not enable clock\n"); + return err; + } + + errors = readl(priv->base + SUN4I_REG_ERRC_ADDR); + + bec->txerr = errors & 0xFF; + bec->rxerr = (errors >> 16) & 0xFF; + + clk_disable_unprepare(priv->clk); + + return 0; +} + +static int sun4i_can_start(struct net_device *dev) +{ + struct sun4ican_priv *priv = netdev_priv(dev); + int err; + u32 mod_reg_val; + + /* we need to enter the reset mode */ + err = set_reset_mode(dev); + if (err) { + netdev_err(dev, "could not enter reset mode\n"); + return err; + } + + /* set filters - we accept all */ + writel(0x00000000, priv->base + SUN4I_REG_ACPC_ADDR); + writel(0xFFFFFFFF, priv->base + SUN4I_REG_ACPM_ADDR); + + /* clear error counters and error code capture */ + writel(0, priv->base + SUN4I_REG_ERRC_ADDR); + + /* enable interrupts */ + if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) + writel(0xFF, priv->base + SUN4I_REG_INTEN_ADDR); + else + writel(0xFF & ~SUN4I_INTEN_BERR, + priv->base + SUN4I_REG_INTEN_ADDR); + + /* enter the selected mode */ + mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR); + if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK) + mod_reg_val |= SUN4I_MSEL_LOOPBACK_MODE; + else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + mod_reg_val |= SUN4I_MSEL_LISTEN_ONLY_MODE; + writel(mod_reg_val, priv->base + SUN4I_REG_MSEL_ADDR); + + err = sun4ican_set_bittiming(dev); + if (err) + return err; + + /* we are ready to enter the normal mode */ + err = set_normal_mode(dev); + if (err) { + netdev_err(dev, "could not enter normal mode\n"); + return err; + } + + priv->can.state = CAN_STATE_ERROR_ACTIVE; + + return 0; +} + +static int sun4i_can_stop(struct net_device *dev) +{ + struct sun4ican_priv *priv = netdev_priv(dev); + int err; + + priv->can.state = CAN_STATE_STOPPED; + /* we need to enter reset mode */ + err = set_reset_mode(dev); + if (err) { + netdev_err(dev, "could not enter reset mode\n"); + return err; + } + + /* disable all interrupts */ + writel(0, priv->base + SUN4I_REG_INTEN_ADDR); + + return 0; +} + +static int sun4ican_set_mode(struct net_device *dev, enum can_mode mode) +{ + int err; + + switch (mode) { + case CAN_MODE_START: + err = sun4i_can_start(dev); + if (err) { + netdev_err(dev, "starting CAN controller failed!\n"); + return err; + } + if (netif_queue_stopped(dev)) + netif_wake_queue(dev); + break; + + default: + return -EOPNOTSUPP; + } + return 0; +} + +/* transmit a CAN message + * message layout in the sk_buff should be like this: + * xx xx xx xx ff ll 00 11 22 33 44 55 66 77 + * [ can_id ] [flags] [len] [can data (up to 8 bytes] + */ +static int sun4ican_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct sun4ican_priv *priv = netdev_priv(dev); + struct can_frame *cf = (struct can_frame *)skb->data; + u8 dlc; + u32 dreg, msg_flag_n; + canid_t id; + int i; + + if (can_dropped_invalid_skb(dev, skb)) + return NETDEV_TX_OK; + + netif_stop_queue(dev); + + id = cf->can_id; + dlc = cf->can_dlc; + msg_flag_n = dlc; + + if (id & CAN_RTR_FLAG) + msg_flag_n |= SUN4I_MSG_RTR_FLAG; + + if (id & CAN_EFF_FLAG) { + msg_flag_n |= SUN4I_MSG_EFF_FLAG; + dreg = SUN4I_REG_BUF5_ADDR; + writel((id >> 21) & 0xFF, priv->base + SUN4I_REG_BUF1_ADDR); + writel((id >> 13) & 0xFF, priv->base + SUN4I_REG_BUF2_ADDR); + writel((id >> 5) & 0xFF, priv->base + SUN4I_REG_BUF3_ADDR); + writel((id << 3) & 0xF8, priv->base + SUN4I_REG_BUF4_ADDR); + } else { + dreg = SUN4I_REG_BUF3_ADDR; + writel((id >> 3) & 0xFF, priv->base + SUN4I_REG_BUF1_ADDR); + writel((id << 5) & 0xE0, priv->base + SUN4I_REG_BUF2_ADDR); + } + + for (i = 0; i < dlc; i++) + writel(cf->data[i], priv->base + (dreg + i * 4)); + + writel(msg_flag_n, priv->base + SUN4I_REG_BUF0_ADDR); + + can_put_echo_skb(skb, dev, 0); + + if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) + sun4i_can_write_cmdreg(priv, SUN4I_CMD_SELF_RCV_REQ); + else + sun4i_can_write_cmdreg(priv, SUN4I_CMD_TRANS_REQ); + + return NETDEV_TX_OK; +} + +static void sun4i_can_rx(struct net_device *dev) +{ + struct sun4ican_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct can_frame *cf; + struct sk_buff *skb; + u8 fi; + u32 dreg; + canid_t id; + int i; + + /* create zero'ed CAN frame buffer */ + skb = alloc_can_skb(dev, &cf); + if (!skb) + return; + + fi = readl(priv->base + SUN4I_REG_BUF0_ADDR); + cf->can_dlc = get_can_dlc(fi & 0x0F); + if (fi & SUN4I_MSG_EFF_FLAG) { + dreg = SUN4I_REG_BUF5_ADDR; + id = (readl(priv->base + SUN4I_REG_BUF1_ADDR) << 21) | + (readl(priv->base + SUN4I_REG_BUF2_ADDR) << 13) | + (readl(priv->base + SUN4I_REG_BUF3_ADDR) << 5) | + ((readl(priv->base + SUN4I_REG_BUF4_ADDR) >> 3) & 0x1f); + id |= CAN_EFF_FLAG; + } else { + dreg = SUN4I_REG_BUF3_ADDR; + id = (readl(priv->base + SUN4I_REG_BUF1_ADDR) << 3) | + ((readl(priv->base + SUN4I_REG_BUF2_ADDR) >> 5) & 0x7); + } + + /* remote frame ? */ + if (fi & SUN4I_MSG_RTR_FLAG) + id |= CAN_RTR_FLAG; + else + for (i = 0; i < cf->can_dlc; i++) + cf->data[i] = readl(priv->base + dreg + i * 4); + + cf->can_id = id; + + sun4i_can_write_cmdreg(priv, SUN4I_CMD_RELEASE_RBUF); + + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; + netif_rx(skb); + + can_led_event(dev, CAN_LED_EVENT_RX); +} + +static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status) +{ + struct sun4ican_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct can_frame *cf; + struct sk_buff *skb; + enum can_state state = priv->can.state; + enum can_state rx_state, tx_state; + unsigned int rxerr, txerr, errc; + u32 ecc, alc; + + /* we don't skip if alloc fails because we want the stats anyhow */ + skb = alloc_can_err_skb(dev, &cf); + + errc = readl(priv->base + SUN4I_REG_ERRC_ADDR); + rxerr = (errc >> 16) & 0xFF; + txerr = errc & 0xFF; + + if (skb) { + cf->data[6] = txerr; + cf->data[7] = rxerr; + } + + if (isrc & SUN4I_INT_DATA_OR) { + /* data overrun interrupt */ + netdev_dbg(dev, "data overrun interrupt\n"); + if (likely(skb)) { + cf->can_id |= CAN_ERR_CRTL; + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; + } + stats->rx_over_errors++; + stats->rx_errors++; + /* clear bit */ + sun4i_can_write_cmdreg(priv, SUN4I_CMD_CLEAR_OR_FLAG); + } + if (isrc & SUN4I_INT_ERR_WRN) { + /* error warning interrupt */ + netdev_dbg(dev, "error warning interrupt\n"); + + if (status & SUN4I_STA_BUS_OFF) + state = CAN_STATE_BUS_OFF; + else if (status & SUN4I_STA_ERR_STA) + state = CAN_STATE_ERROR_WARNING; + else + state = CAN_STATE_ERROR_ACTIVE; + } + if (isrc & SUN4I_INT_BUS_ERR) { + /* bus error interrupt */ + netdev_dbg(dev, "bus error interrupt\n"); + priv->can.can_stats.bus_error++; + stats->rx_errors++; + + if (likely(skb)) { + ecc = readl(priv->base + SUN4I_REG_STA_ADDR); + + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + + switch (ecc & SUN4I_STA_MASK_ERR) { + case SUN4I_STA_BIT_ERR: + cf->data[2] |= CAN_ERR_PROT_BIT; + break; + case SUN4I_STA_FORM_ERR: + cf->data[2] |= CAN_ERR_PROT_FORM; + break; + case SUN4I_STA_STUFF_ERR: + cf->data[2] |= CAN_ERR_PROT_STUFF; + break; + default: + cf->data[2] |= CAN_ERR_PROT_UNSPEC; + cf->data[3] = (ecc & SUN4I_STA_ERR_SEG_CODE) + >> 16; + break; + } + /* error occurred during transmission? */ + if ((ecc & SUN4I_STA_ERR_DIR) == 0) + cf->data[2] |= CAN_ERR_PROT_TX; + } + } + if (isrc & SUN4I_INT_ERR_PASSIVE) { + /* error passive interrupt */ + netdev_dbg(dev, "error passive interrupt\n"); + if (state == CAN_STATE_ERROR_PASSIVE) + state = CAN_STATE_ERROR_WARNING; + else + state = CAN_STATE_ERROR_PASSIVE; + } + if (isrc & SUN4I_INT_ARB_LOST) { + /* arbitration lost interrupt */ + netdev_dbg(dev, "arbitration lost interrupt\n"); + alc = readl(priv->base + SUN4I_REG_STA_ADDR); + priv->can.can_stats.arbitration_lost++; + stats->tx_errors++; + if (likely(skb)) { + cf->can_id |= CAN_ERR_LOSTARB; + cf->data[0] = (alc & 0x1f) >> 8; + } + } + + if (state != priv->can.state) { + tx_state = txerr >= rxerr ? state : 0; + rx_state = txerr <= rxerr ? state : 0; + + if (likely(skb)) + can_change_state(dev, cf, tx_state, rx_state); + else + priv->can.state = state; + if (state == CAN_STATE_BUS_OFF) + can_bus_off(dev); + } + + if (likely(skb)) { + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; + netif_rx(skb); + } else { + return -ENOMEM; + } + + return 0; +} + +static irqreturn_t sun4i_can_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = (struct net_device *)dev_id; + struct sun4ican_priv *priv = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + u8 isrc, status; + int n = 0; + + while ((isrc = readl(priv->base + SUN4I_REG_INT_ADDR)) && + (n < SUN4I_CAN_MAX_IRQ)) { + n++; + status = readl(priv->base + SUN4I_REG_STA_ADDR); + + if (isrc & SUN4I_INT_WAKEUP) + netdev_warn(dev, "wakeup interrupt\n"); + + if (isrc & SUN4I_INT_TBUF_VLD) { + /* transmission complete interrupt */ + stats->tx_bytes += + readl(priv->base + + SUN4I_REG_RBUF_RBACK_START_ADDR) & 0xf; + stats->tx_packets++; + can_get_echo_skb(dev, 0); + netif_wake_queue(dev); + can_led_event(dev, CAN_LED_EVENT_TX); + } + if (isrc & SUN4I_INT_RBUF_VLD) { + /* receive interrupt */ + while (status & SUN4I_STA_RBUF_RDY) { + /* RX buffer is not empty */ + sun4i_can_rx(dev); + status = readl(priv->base + SUN4I_REG_STA_ADDR); + } + } + if (isrc & + (SUN4I_INT_DATA_OR | SUN4I_INT_ERR_WRN | SUN4I_INT_BUS_ERR | + SUN4I_INT_ERR_PASSIVE | SUN4I_INT_ARB_LOST)) { + /* error interrupt */ + if (sun4i_can_err(dev, isrc, status)) + netdev_err(dev, "can't allocate buffer - clearing pending interrupts\n"); + } + /* clear interrupts */ + writel(isrc, priv->base + SUN4I_REG_INT_ADDR); + readl(priv->base + SUN4I_REG_INT_ADDR); + } + if (n >= SUN4I_CAN_MAX_IRQ) + netdev_dbg(dev, "%d messages handled in ISR", n); + + return (n) ? IRQ_HANDLED : IRQ_NONE; +} + +static int sun4ican_open(struct net_device *dev) +{ + struct sun4ican_priv *priv = netdev_priv(dev); + int err; + + /* common open */ + err = open_candev(dev); + if (err) + return err; + + /* register interrupt handler */ + err = request_irq(dev->irq, sun4i_can_interrupt, 0, dev->name, dev); + if (err) { + netdev_err(dev, "request_irq err: %d\n", err); + goto exit_irq; + } + + /* turn on clocking for CAN peripheral block */ + err = clk_prepare_enable(priv->clk); + if (err) { + netdev_err(dev, "could not enable CAN peripheral clock\n"); + goto exit_clock; + } + + err = sun4i_can_start(dev); + if (err) { + netdev_err(dev, "could not start CAN peripheral\n"); + goto exit_can_start; + } + + can_led_event(dev, CAN_LED_EVENT_OPEN); + netif_start_queue(dev); + + return 0; + +exit_can_start: + clk_disable_unprepare(priv->clk); +exit_clock: + free_irq(dev->irq, dev); +exit_irq: + close_candev(dev); + return err; +} + +static int sun4ican_close(struct net_device *dev) +{ + struct sun4ican_priv *priv = netdev_priv(dev); + + netif_stop_queue(dev); + sun4i_can_stop(dev); + clk_disable_unprepare(priv->clk); + + free_irq(dev->irq, dev); + close_candev(dev); + can_led_event(dev, CAN_LED_EVENT_STOP); + + return 0; +} + +static const struct net_device_ops sun4ican_netdev_ops = { + .ndo_open = sun4ican_open, + .ndo_stop = sun4ican_close, + .ndo_start_xmit = sun4ican_start_xmit, +}; + +static const struct of_device_id sun4ican_of_match[] = { + {.compatible = "allwinner,sun4i-a10-can"}, + {}, +}; + +MODULE_DEVICE_TABLE(of, sun4ican_of_match); + +static int sun4ican_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + + unregister_netdev(dev); + free_candev(dev); + + return 0; +} + +static int sun4ican_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct resource *mem; + struct clk *clk; + void __iomem *addr; + int err, irq; + struct net_device *dev; + struct sun4ican_priv *priv; + + clk = of_clk_get(np, 0); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "unable to request clock\n"); + err = -ENODEV; + goto exit; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "could not get a valid irq\n"); + err = -ENODEV; + goto exit; + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + addr = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(addr)) { + err = -EBUSY; + goto exit; + } + + dev = alloc_candev(sizeof(struct sun4ican_priv), 1); + if (!dev) { + dev_err(&pdev->dev, + "could not allocate memory for CAN device\n"); + err = -ENOMEM; + goto exit; + } + + dev->netdev_ops = &sun4ican_netdev_ops; + dev->irq = irq; + dev->flags |= IFF_ECHO; + + priv = netdev_priv(dev); + priv->can.clock.freq = clk_get_rate(clk); + priv->can.bittiming_const = &sun4ican_bittiming_const; + priv->can.do_set_mode = sun4ican_set_mode; + priv->can.do_get_berr_counter = sun4ican_get_berr_counter; + priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_LISTENONLY | + CAN_CTRLMODE_LOOPBACK | + CAN_CTRLMODE_PRESUME_ACK | + CAN_CTRLMODE_3_SAMPLES; + priv->base = addr; + priv->clk = clk; + spin_lock_init(&priv->cmdreg_lock); + + platform_set_drvdata(pdev, dev); + SET_NETDEV_DEV(dev, &pdev->dev); + + err = register_candev(dev); + if (err) { + dev_err(&pdev->dev, "registering %s failed (err=%d)\n", + DRV_NAME, err); + goto exit_free; + } + devm_can_led_init(dev); + + dev_info(&pdev->dev, "device registered (base=%p, irq=%d)\n", + priv->base, dev->irq); + + return 0; + +exit_free: + free_candev(dev); +exit: + return err; +} + +static struct platform_driver sun4i_can_driver = { + .driver = { + .name = DRV_NAME, + .of_match_table = sun4ican_of_match, + }, + .probe = sun4ican_probe, + .remove = sun4ican_remove, +}; + +module_platform_driver(sun4i_can_driver); + +MODULE_AUTHOR("Peter Chen "); +MODULE_AUTHOR("Gerhard Bertelsmann "); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION(DRV_NAME "CAN driver for Allwinner SoCs (A10/A20)"); -- cgit v1.2.3 From 29a26a56803855a79dbd028cd61abee56237d6e5 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 15 Sep 2015 20:04:16 -0500 Subject: netfilter: Pass struct net into the netfilter hooks Pass a network namespace parameter into the netfilter hooks. At the call site of the netfilter hooks the path a packet is taking through the network stack is well known which allows the network namespace to be easily and reliabily. This allows the replacement of magic code like "dev_net(state->in?:state->out)" that appears at the start of most netfilter hooks with "state->net". In almost all cases the network namespace passed in is derived from the first network device passed in, guaranteeing those paths will not see any changes in practice. The exceptions are: xfrm/xfrm_output.c:xfrm_output_resume() xs_net(skb_dst(skb)->xfrm) ipvs/ip_vs_xmit.c:ip_vs_nat_send_or_cont() ip_vs_conn_net(cp) ipvs/ip_vs_xmit.c:ip_vs_send_or_cont() ip_vs_conn_net(cp) ipv4/raw.c:raw_send_hdrinc() sock_net(sk) ipv6/ip6_output.c:ip6_xmit() sock_net(sk) ipv6/ndisc.c:ndisc_send_skb() dev_net(skb->dev) not dev_net(dst->dev) ipv6/raw.c:raw6_send_hdrinc() sock_net(sk) br_netfilter_hooks.c:br_nf_pre_routing_finish() dev_net(skb->dev) before skb->dev is set to nf_bridge->physindev In all cases these exceptions seem to be a better expression for the network namespace the packet is being processed in then the historic "dev_net(in?in:out)". I am documenting them in case something odd pops up and someone starts trying to track down what happened. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/vrf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 8c9ab5ebea23..979a4db9c6bc 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -298,14 +298,15 @@ err: static int vrf_output(struct sock *sk, struct sk_buff *skb) { struct net_device *dev = skb_dst(skb)->dev; + struct net *net = dev_net(dev); - IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUT, skb->len); + IP_UPD_PO_STATS(net, IPSTATS_MIB_OUT, skb->len); skb->dev = dev; skb->protocol = htons(ETH_P_IP); - return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, sk, skb, - NULL, dev, + return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, + net, sk, skb, NULL, dev, vrf_finish_output, !(IPCB(skb)->flags & IPSKB_REROUTED)); } -- cgit v1.2.3 From 0c4b51f0054ce85c0ec578ab818f0631834573eb Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 15 Sep 2015 20:04:18 -0500 Subject: netfilter: Pass net into okfn This is immediately motivated by the bridge code that chains functions that call into netfilter. Without passing net into the okfns the bridge code would need to guess about the best expression for the network namespace to process packets in. As net is frequently one of the first things computed in continuation functions after netfilter has done it's job passing in the desired network namespace is in many cases a code simplification. To support this change the function dst_output_okfn is introduced to simplify passing dst_output as an okfn. For the moment dst_output_okfn just silently drops the struct net. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/vrf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 979a4db9c6bc..637e9fd1e14c 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -253,7 +253,7 @@ static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev) } /* modelled after ip_finish_output2 */ -static int vrf_finish_output(struct sock *sk, struct sk_buff *skb) +static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); struct rtable *rt = (struct rtable *)dst; -- cgit v1.2.3 From 79afe839ab1a5e1e9232845f430d5c500e956e8d Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 23 Jul 2015 16:54:33 -0400 Subject: i40e: rename variable to prevent clash of understanding This code returns something that becomes the errno value from ethtool and passes around a pointer to an errno variable. This patch changes the name slightly to differentiate it from the actual user errno variable. Change-ID: Idaa37845c069e66f4cea072e90f471bb2142454d Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 114 ++++++++++++++--------------- 1 file changed, 57 insertions(+), 57 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 9b83abc0e774..3f2fec9c8f99 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -592,25 +592,25 @@ i40e_validate_nvm_checksum_exit: static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - u8 *bytes, int *errno); + u8 *bytes, int *perrno); static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - u8 *bytes, int *errno); + u8 *bytes, int *perrno); static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *errno); static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - int *errno); + int *perrno); static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - int *errno); + int *perrno); static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - u8 *bytes, int *errno); + u8 *bytes, int *perrno); static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - u8 *bytes, int *errno); + u8 *bytes, int *perrno); static inline u8 i40e_nvmupd_get_module(u32 val) { return (u8)(val & I40E_NVM_MOD_PNT_MASK); @@ -641,30 +641,30 @@ static char *i40e_nvm_update_state_str[] = { * @hw: pointer to hardware structure * @cmd: pointer to nvm update command * @bytes: pointer to the data buffer - * @errno: pointer to return error code + * @perrno: pointer to return error code * * Dispatches command depending on what update state is current **/ i40e_status i40e_nvmupd_command(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - u8 *bytes, int *errno) + u8 *bytes, int *perrno) { i40e_status status; /* assume success */ - *errno = 0; + *perrno = 0; switch (hw->nvmupd_state) { case I40E_NVMUPD_STATE_INIT: - status = i40e_nvmupd_state_init(hw, cmd, bytes, errno); + status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno); break; case I40E_NVMUPD_STATE_READING: - status = i40e_nvmupd_state_reading(hw, cmd, bytes, errno); + status = i40e_nvmupd_state_reading(hw, cmd, bytes, perrno); break; case I40E_NVMUPD_STATE_WRITING: - status = i40e_nvmupd_state_writing(hw, cmd, bytes, errno); + status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno); break; default: @@ -672,7 +672,7 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: no such state %d\n", hw->nvmupd_state); status = I40E_NOT_SUPPORTED; - *errno = -ESRCH; + *perrno = -ESRCH; break; } return status; @@ -683,28 +683,28 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw, * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer * @bytes: pointer to the data buffer - * @errno: pointer to return error code + * @perrno: pointer to return error code * * Process legitimate commands of the Init state and conditionally set next * state. Reject all other commands. **/ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - u8 *bytes, int *errno) + u8 *bytes, int *perrno) { i40e_status status = 0; enum i40e_nvmupd_cmd upd_cmd; - upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno); + upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno); switch (upd_cmd) { case I40E_NVMUPD_READ_SA: status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); if (status) { - *errno = i40e_aq_rc_to_posix(status, + *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } else { - status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno); + status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno); i40e_release_nvm(hw); } break; @@ -712,10 +712,10 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, case I40E_NVMUPD_READ_SNT: status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); if (status) { - *errno = i40e_aq_rc_to_posix(status, + *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } else { - status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno); + status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno); if (status) i40e_release_nvm(hw); else @@ -726,10 +726,10 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, case I40E_NVMUPD_WRITE_ERA: status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); if (status) { - *errno = i40e_aq_rc_to_posix(status, + *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } else { - status = i40e_nvmupd_nvm_erase(hw, cmd, errno); + status = i40e_nvmupd_nvm_erase(hw, cmd, perrno); if (status) i40e_release_nvm(hw); else @@ -740,10 +740,10 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, case I40E_NVMUPD_WRITE_SA: status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); if (status) { - *errno = i40e_aq_rc_to_posix(status, + *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } else { - status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); + status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); if (status) i40e_release_nvm(hw); else @@ -754,10 +754,10 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, case I40E_NVMUPD_WRITE_SNT: status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); if (status) { - *errno = i40e_aq_rc_to_posix(status, + *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } else { - status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); + status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); if (status) i40e_release_nvm(hw); else @@ -768,12 +768,12 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, case I40E_NVMUPD_CSUM_SA: status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE); if (status) { - *errno = i40e_aq_rc_to_posix(status, + *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } else { status = i40e_update_nvm_checksum(hw); if (status) { - *errno = hw->aq.asq_last_status ? + *perrno = hw->aq.asq_last_status ? i40e_aq_rc_to_posix(status, hw->aq.asq_last_status) : -EIO; @@ -789,7 +789,7 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, "NVMUPD: bad cmd %s in init state\n", i40e_nvm_update_state_str[upd_cmd]); status = I40E_ERR_NVM; - *errno = -ESRCH; + *perrno = -ESRCH; break; } return status; @@ -800,28 +800,28 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer * @bytes: pointer to the data buffer - * @errno: pointer to return error code + * @perrno: pointer to return error code * * NVM ownership is already held. Process legitimate commands and set any * change in state; reject all other commands. **/ static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - u8 *bytes, int *errno) + u8 *bytes, int *perrno) { i40e_status status; enum i40e_nvmupd_cmd upd_cmd; - upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno); + upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno); switch (upd_cmd) { case I40E_NVMUPD_READ_SA: case I40E_NVMUPD_READ_CON: - status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno); + status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno); break; case I40E_NVMUPD_READ_LCB: - status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno); + status = i40e_nvmupd_nvm_read(hw, cmd, bytes, perrno); i40e_release_nvm(hw); hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; break; @@ -831,7 +831,7 @@ static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw, "NVMUPD: bad cmd %s in reading state.\n", i40e_nvm_update_state_str[upd_cmd]); status = I40E_NOT_SUPPORTED; - *errno = -ESRCH; + *perrno = -ESRCH; break; } return status; @@ -842,29 +842,29 @@ static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw, * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer * @bytes: pointer to the data buffer - * @errno: pointer to return error code + * @perrno: pointer to return error code * * NVM ownership is already held. Process legitimate commands and set any * change in state; reject all other commands **/ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - u8 *bytes, int *errno) + u8 *bytes, int *perrno) { i40e_status status; enum i40e_nvmupd_cmd upd_cmd; bool retry_attempt = false; - upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno); + upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno); retry: switch (upd_cmd) { case I40E_NVMUPD_WRITE_CON: - status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); + status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); break; case I40E_NVMUPD_WRITE_LCB: - status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno); + status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); if (!status) hw->aq.nvm_release_on_done = true; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; @@ -873,7 +873,7 @@ retry: case I40E_NVMUPD_CSUM_CON: status = i40e_update_nvm_checksum(hw); if (status) { - *errno = hw->aq.asq_last_status ? + *perrno = hw->aq.asq_last_status ? i40e_aq_rc_to_posix(status, hw->aq.asq_last_status) : -EIO; @@ -884,7 +884,7 @@ retry: case I40E_NVMUPD_CSUM_LCB: status = i40e_update_nvm_checksum(hw); if (status) - *errno = hw->aq.asq_last_status ? + *perrno = hw->aq.asq_last_status ? i40e_aq_rc_to_posix(status, hw->aq.asq_last_status) : -EIO; @@ -898,7 +898,7 @@ retry: "NVMUPD: bad cmd %s in writing state.\n", i40e_nvm_update_state_str[upd_cmd]); status = I40E_NOT_SUPPORTED; - *errno = -ESRCH; + *perrno = -ESRCH; break; } @@ -941,13 +941,13 @@ retry: * i40e_nvmupd_validate_command - Validate given command * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer - * @errno: pointer to return error code + * @perrno: pointer to return error code * * Return one of the valid command types or I40E_NVMUPD_INVALID **/ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - int *errno) + int *perrno) { enum i40e_nvmupd_cmd upd_cmd; u8 transaction; @@ -963,7 +963,7 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_validate_command data_size %d\n", cmd->data_size); - *errno = -EFAULT; + *perrno = -EFAULT; return I40E_NVMUPD_INVALID; } @@ -1020,10 +1020,10 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, hw->aq.nvm_release_on_done); if (upd_cmd == I40E_NVMUPD_INVALID) { - *errno = -EFAULT; + *perrno = -EFAULT; i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_validate_command returns %d errno %d\n", - upd_cmd, *errno); + upd_cmd, *perrno); } return upd_cmd; } @@ -1033,13 +1033,13 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer * @bytes: pointer to the data buffer - * @errno: pointer to return error code + * @perrno: pointer to return error code * * cmd structure contains identifiers and data buffer **/ static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - u8 *bytes, int *errno) + u8 *bytes, int *perrno) { i40e_status status; u8 module, transaction; @@ -1058,7 +1058,7 @@ static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_nvm_read status %d aq %d\n", status, hw->aq.asq_last_status); - *errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); + *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } return status; @@ -1068,13 +1068,13 @@ static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw, * i40e_nvmupd_nvm_erase - Erase an NVM module * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer - * @errno: pointer to return error code + * @perrno: pointer to return error code * * module, offset, data_size and data are in cmd structure **/ static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - int *errno) + int *perrno) { i40e_status status = 0; u8 module, transaction; @@ -1092,7 +1092,7 @@ static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_nvm_erase status %d aq %d\n", status, hw->aq.asq_last_status); - *errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); + *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } return status; @@ -1103,13 +1103,13 @@ static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw, * @hw: pointer to hardware structure * @cmd: pointer to nvm update command buffer * @bytes: pointer to the data buffer - * @errno: pointer to return error code + * @perrno: pointer to return error code * * module, offset, data_size and data are in cmd structure **/ static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw, struct i40e_nvm_access *cmd, - u8 *bytes, int *errno) + u8 *bytes, int *perrno) { i40e_status status = 0; u8 module, transaction; @@ -1128,7 +1128,7 @@ static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw, i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_nvm_write status %d aq %d\n", status, hw->aq.asq_last_status); - *errno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); + *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); } return status; -- cgit v1.2.3 From 87db27a9e21fdeb20f77a024b30b406915e083d6 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 27 Aug 2015 11:42:42 -0400 Subject: i40e/i40evf: save aq writeback for future inspection Add the ability to save the AdminQ write back descriptor if a caller supplies a buffer for it to be saved into. Change-ID: I3d1301d26360b39a2d66dc8569e851f54133a3af Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 4 ++++ drivers/net/ethernet/intel/i40e/i40e_adminq.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_adminq.c | 4 ++++ drivers/net/ethernet/intel/i40evf/i40e_adminq.h | 1 + 4 files changed, 10 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 3e0d20037675..8a77f59f57aa 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -889,6 +889,10 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, "AQTX: desc and buffer writeback:\n"); i40e_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff, buff_size); + /* save writeback aq if requested */ + if (details->wb_desc) + *details->wb_desc = *desc_on_ring; + /* update the error if time out occurred */ if ((!cmd_completed) && (!details->async && !details->postpone)) { diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h index 28e519a50de4..b67b34c35533 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h @@ -69,6 +69,7 @@ struct i40e_asq_cmd_details { u16 flags_dis; bool async; bool postpone; + struct i40e_aq_desc *wb_desc; }; #define I40E_ADMINQ_DETAILS(R, i) \ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c index f08450b90774..15c8ac892704 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c @@ -830,6 +830,10 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw, i40evf_debug_aq(hw, I40E_DEBUG_AQ_COMMAND, (void *)desc, buff, buff_size); + /* save writeback aq if requested */ + if (details->wb_desc) + *details->wb_desc = *desc_on_ring; + /* update the error if time out occurred */ if ((!cmd_completed) && (!details->async && !details->postpone)) { diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h index ef43d68f67b3..547b79b81ffe 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h @@ -69,6 +69,7 @@ struct i40e_asq_cmd_details { u16 flags_dis; bool async; bool postpone; + struct i40e_aq_desc *wb_desc; }; #define I40E_ADMINQ_DETAILS(R, i) \ -- cgit v1.2.3 From 6b5c1b89c37791d89eac5f276cc095acf4f8ab6b Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 28 Aug 2015 17:55:47 -0400 Subject: i40e/i40evf: add handling of writeback descriptor If the writeback descriptor buffer was previously created, this gives it to the AQ command request to be used to save the results. Change-ID: I8c8a1af81e6ebed6d0a15ed31697fe1a6c4e3708 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 26 ++++++++++++++++++++++---- drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_type.h | 1 + 3 files changed, 24 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 3f2fec9c8f99..e71ce23d5797 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -418,6 +418,10 @@ static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer, bool last_command) { i40e_status ret_code = I40E_ERR_NVM; + struct i40e_asq_cmd_details cmd_details; + + memset(&cmd_details, 0, sizeof(cmd_details)); + cmd_details.wb_desc = &hw->nvm_wb_desc; /* Here we are checking the SR limit only for the flat memory model. * We cannot do it for the module-based model, as we did not acquire @@ -443,7 +447,7 @@ static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer, ret_code = i40e_aq_update_nvm(hw, module_pointer, 2 * offset, /*bytes*/ 2 * words, /*bytes*/ - data, last_command, NULL); + data, last_command, &cmd_details); return ret_code; } @@ -1041,6 +1045,7 @@ static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno) { + struct i40e_asq_cmd_details cmd_details; i40e_status status; u8 module, transaction; bool last; @@ -1049,8 +1054,11 @@ static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw, module = i40e_nvmupd_get_module(cmd->config); last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA); + memset(&cmd_details, 0, sizeof(cmd_details)); + cmd_details.wb_desc = &hw->nvm_wb_desc; + status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size, - bytes, last, NULL); + bytes, last, &cmd_details); if (status) { i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n", @@ -1077,14 +1085,19 @@ static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw, int *perrno) { i40e_status status = 0; + struct i40e_asq_cmd_details cmd_details; u8 module, transaction; bool last; transaction = i40e_nvmupd_get_transaction(cmd->config); module = i40e_nvmupd_get_module(cmd->config); last = (transaction & I40E_NVM_LCB); + + memset(&cmd_details, 0, sizeof(cmd_details)); + cmd_details.wb_desc = &hw->nvm_wb_desc; + status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size, - last, NULL); + last, &cmd_details); if (status) { i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n", @@ -1112,6 +1125,7 @@ static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw, u8 *bytes, int *perrno) { i40e_status status = 0; + struct i40e_asq_cmd_details cmd_details; u8 module, transaction; bool last; @@ -1119,8 +1133,12 @@ static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw, module = i40e_nvmupd_get_module(cmd->config); last = (transaction & I40E_NVM_LCB); + memset(&cmd_details, 0, sizeof(cmd_details)); + cmd_details.wb_desc = &hw->nvm_wb_desc; + status = i40e_aq_update_nvm(hw, module, cmd->offset, - (u16)cmd->data_size, bytes, last, NULL); + (u16)cmd->data_size, bytes, last, + &cmd_details); if (status) { i40e_debug(hw, I40E_DEBUG_NVM, "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n", diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 4842239ee777..a4fec8b7bef2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -492,6 +492,7 @@ struct i40e_hw { /* state of nvm update process */ enum i40e_nvmupd_state nvmupd_state; + struct i40e_aq_desc nvm_wb_desc; /* HMC info */ struct i40e_hmc_info hmc; /* HMC info struct */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 24a2693869a1..cf865cc8d1b3 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -486,6 +486,7 @@ struct i40e_hw { /* state of nvm update process */ enum i40e_nvmupd_state nvmupd_state; + struct i40e_aq_desc nvm_wb_desc; /* HMC info */ struct i40e_hmc_info hmc; /* HMC info struct */ -- cgit v1.2.3 From 0af8e9db2ce93d17c25a0ff0a044dfebf66ea5af Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 28 Aug 2015 17:55:48 -0400 Subject: i40e/i40evf: add GetStatus command for nvmupdate This adds a new GetStatus command so that the NVM update tool can query the current status instead of doing fake write requests to probe for readiness. Change-ID: I671ec6ccd4dfc9dbac3a03b964589d693fda5cd8 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 42 ++++++++++++++++++++------- drivers/net/ethernet/intel/i40e/i40e_type.h | 2 ++ drivers/net/ethernet/intel/i40evf/i40e_type.h | 2 ++ 3 files changed, 35 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index e71ce23d5797..7ff309945d6f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -638,6 +638,7 @@ static char *i40e_nvm_update_state_str[] = { "I40E_NVMUPD_CSUM_CON", "I40E_NVMUPD_CSUM_SA", "I40E_NVMUPD_CSUM_LCB", + "I40E_NVMUPD_STATUS", }; /** @@ -654,10 +655,34 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw, u8 *bytes, int *perrno) { i40e_status status; + enum i40e_nvmupd_cmd upd_cmd; /* assume success */ *perrno = 0; + /* early check for status command and debug msgs */ + upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno); + + i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d\n", + i40e_nvm_update_state_str[upd_cmd], + hw->nvmupd_state, + hw->aq.nvm_release_on_done); + + if (upd_cmd == I40E_NVMUPD_INVALID) { + *perrno = -EFAULT; + i40e_debug(hw, I40E_DEBUG_NVM, + "i40e_nvmupd_validate_command returns %d errno %d\n", + upd_cmd, *perrno); + } + + /* a status request returns immediately rather than + * going into the state machine + */ + if (upd_cmd == I40E_NVMUPD_STATUS) { + bytes[0] = hw->nvmupd_state; + return 0; + } + switch (hw->nvmupd_state) { case I40E_NVMUPD_STATE_INIT: status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno); @@ -954,12 +979,13 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, int *perrno) { enum i40e_nvmupd_cmd upd_cmd; - u8 transaction; + u8 module, transaction; /* anything that doesn't match a recognized case is an error */ upd_cmd = I40E_NVMUPD_INVALID; transaction = i40e_nvmupd_get_transaction(cmd->config); + module = i40e_nvmupd_get_module(cmd->config); /* limits on data size */ if ((cmd->data_size < 1) || @@ -986,6 +1012,10 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, case I40E_NVM_SA: upd_cmd = I40E_NVMUPD_READ_SA; break; + case I40E_NVM_EXEC: + if (module == 0xf) + upd_cmd = I40E_NVMUPD_STATUS; + break; } break; @@ -1018,17 +1048,7 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, } break; } - i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d\n", - i40e_nvm_update_state_str[upd_cmd], - hw->nvmupd_state, - hw->aq.nvm_release_on_done); - if (upd_cmd == I40E_NVMUPD_INVALID) { - *perrno = -EFAULT; - i40e_debug(hw, I40E_DEBUG_NVM, - "i40e_nvmupd_validate_command returns %d errno %d\n", - upd_cmd, *perrno); - } return upd_cmd; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index a4fec8b7bef2..f63f538d75c5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -305,6 +305,7 @@ enum i40e_nvmupd_cmd { I40E_NVMUPD_CSUM_CON, I40E_NVMUPD_CSUM_SA, I40E_NVMUPD_CSUM_LCB, + I40E_NVMUPD_STATUS, }; enum i40e_nvmupd_state { @@ -329,6 +330,7 @@ enum i40e_nvmupd_state { #define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB) #define I40E_NVM_ERA 0x4 #define I40E_NVM_CSUM 0x8 +#define I40E_NVM_EXEC 0xf #define I40E_NVM_ADAPT_SHIFT 16 #define I40E_NVM_ADAPT_MASK (0xffff << I40E_NVM_ADAPT_SHIFT) diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index cf865cc8d1b3..7f3c05c7655e 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -304,6 +304,7 @@ enum i40e_nvmupd_cmd { I40E_NVMUPD_CSUM_CON, I40E_NVMUPD_CSUM_SA, I40E_NVMUPD_CSUM_LCB, + I40E_NVMUPD_STATUS, }; enum i40e_nvmupd_state { @@ -328,6 +329,7 @@ enum i40e_nvmupd_state { #define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB) #define I40E_NVM_ERA 0x4 #define I40E_NVM_CSUM 0x8 +#define I40E_NVM_EXEC 0xf #define I40E_NVM_ADAPT_SHIFT 16 #define I40E_NVM_ADAPT_MASK (0xffff << I40E_NVM_ADAPT_SHIFT) -- cgit v1.2.3 From 2f1b5bc844a7c13a3ec997a7ce029f27403adc57 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 28 Aug 2015 17:55:49 -0400 Subject: i40e/i40evf: add wait states to NVM state machine This adds wait states to the NVM update state machine to signify when waiting for an update operation to finish, whether we're in the middle of a set of Write operations, or we're now idle but waiting. Change-ID: Iabe91d6579ef6a2ea560647e374035656211ab43 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 13 ++++++++ drivers/net/ethernet/intel/i40e/i40e_nvm.c | 48 ++++++++++++++++++++------- drivers/net/ethernet/intel/i40e/i40e_type.h | 4 ++- drivers/net/ethernet/intel/i40evf/i40e_type.h | 4 ++- 4 files changed, 55 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 8a77f59f57aa..ea1e930b52cf 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -1018,6 +1018,19 @@ clean_arq_element_out: i40e_release_nvm(hw); hw->aq.nvm_release_on_done = false; } + + switch (hw->nvmupd_state) { + case I40E_NVMUPD_STATE_INIT_WAIT: + hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; + break; + + case I40E_NVMUPD_STATE_WRITE_WAIT: + hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING; + break; + + default: + break; + } } return ret_code; diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 7ff309945d6f..7bcbe59ae47e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -696,6 +696,12 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw, status = i40e_nvmupd_state_writing(hw, cmd, bytes, perrno); break; + case I40E_NVMUPD_STATE_INIT_WAIT: + case I40E_NVMUPD_STATE_WRITE_WAIT: + status = I40E_ERR_NOT_READY; + *perrno = -EBUSY; + break; + default: /* invalid state, should never happen */ i40e_debug(hw, I40E_DEBUG_NVM, @@ -759,10 +765,12 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, hw->aq.asq_last_status); } else { status = i40e_nvmupd_nvm_erase(hw, cmd, perrno); - if (status) + if (status) { i40e_release_nvm(hw); - else + } else { hw->aq.nvm_release_on_done = true; + hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; + } } break; @@ -773,10 +781,12 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, hw->aq.asq_last_status); } else { status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); - if (status) + if (status) { i40e_release_nvm(hw); - else + } else { hw->aq.nvm_release_on_done = true; + hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; + } } break; @@ -790,7 +800,7 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, if (status) i40e_release_nvm(hw); else - hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING; + hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT; } break; @@ -809,6 +819,7 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, i40e_release_nvm(hw); } else { hw->aq.nvm_release_on_done = true; + hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; } } break; @@ -838,7 +849,7 @@ static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno) { - i40e_status status; + i40e_status status = 0; enum i40e_nvmupd_cmd upd_cmd; upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno); @@ -880,7 +891,7 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno) { - i40e_status status; + i40e_status status = 0; enum i40e_nvmupd_cmd upd_cmd; bool retry_attempt = false; @@ -890,13 +901,22 @@ retry: switch (upd_cmd) { case I40E_NVMUPD_WRITE_CON: status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); + if (!status) + hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT; break; case I40E_NVMUPD_WRITE_LCB: status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno); - if (!status) + if (status) { + *perrno = hw->aq.asq_last_status ? + i40e_aq_rc_to_posix(status, + hw->aq.asq_last_status) : + -EIO; + hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; + } else { hw->aq.nvm_release_on_done = true; - hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; + hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; + } break; case I40E_NVMUPD_CSUM_CON: @@ -907,19 +927,23 @@ retry: hw->aq.asq_last_status) : -EIO; hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; + } else { + hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT; } break; case I40E_NVMUPD_CSUM_LCB: status = i40e_update_nvm_checksum(hw); - if (status) + if (status) { *perrno = hw->aq.asq_last_status ? i40e_aq_rc_to_posix(status, hw->aq.asq_last_status) : -EIO; - else + hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; + } else { hw->aq.nvm_release_on_done = true; - hw->nvmupd_state = I40E_NVMUPD_STATE_INIT; + hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT; + } break; default: diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index f63f538d75c5..3f7993016494 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -311,7 +311,9 @@ enum i40e_nvmupd_cmd { enum i40e_nvmupd_state { I40E_NVMUPD_STATE_INIT, I40E_NVMUPD_STATE_READING, - I40E_NVMUPD_STATE_WRITING + I40E_NVMUPD_STATE_WRITING, + I40E_NVMUPD_STATE_INIT_WAIT, + I40E_NVMUPD_STATE_WRITE_WAIT, }; /* nvm_access definition and its masks/shifts need to be accessible to diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 7f3c05c7655e..439a4e1f2689 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -310,7 +310,9 @@ enum i40e_nvmupd_cmd { enum i40e_nvmupd_state { I40E_NVMUPD_STATE_INIT, I40E_NVMUPD_STATE_READING, - I40E_NVMUPD_STATE_WRITING + I40E_NVMUPD_STATE_WRITING, + I40E_NVMUPD_STATE_INIT_WAIT, + I40E_NVMUPD_STATE_WRITE_WAIT, }; /* nvm_access definition and its masks/shifts need to be accessible to -- cgit v1.2.3 From e4c83c20f87fe1d3da6b3a7ecaf40ae8717c7842 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 28 Aug 2015 17:55:50 -0400 Subject: i40e/i40evf: add exec_aq command to nvmupdate utility Add a facility to run AQ commands through the nvmupdate utility in order to allow the update tools to interact with the FW and do special commands needed for updates and configuration changes. Change-ID: I5c41523e4055b37f8e4ee479f7a0574368f4a588 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 3 + drivers/net/ethernet/intel/i40e/i40e_nvm.c | 83 +++++++++++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_type.h | 2 + drivers/net/ethernet/intel/i40evf/i40e_adminq.c | 3 + drivers/net/ethernet/intel/i40evf/i40e_type.h | 2 + 5 files changed, 93 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index ea1e930b52cf..199275dbe624 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -657,6 +657,9 @@ i40e_status i40e_shutdown_adminq(struct i40e_hw *hw) /* destroy the locks */ + if (hw->nvm_buff.va) + i40e_free_virt_mem(hw, &hw->nvm_buff); + return ret_code; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 7bcbe59ae47e..50d4aa3cf658 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -615,6 +615,9 @@ static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw, static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno); +static i40e_status i40e_nvmupd_exec_aq(struct i40e_hw *hw, + struct i40e_nvm_access *cmd, + u8 *bytes, int *perrno); static inline u8 i40e_nvmupd_get_module(u32 val) { return (u8)(val & I40E_NVM_MOD_PNT_MASK); @@ -639,6 +642,7 @@ static char *i40e_nvm_update_state_str[] = { "I40E_NVMUPD_CSUM_SA", "I40E_NVMUPD_CSUM_LCB", "I40E_NVMUPD_STATUS", + "I40E_NVMUPD_EXEC_AQ", }; /** @@ -824,6 +828,10 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, } break; + case I40E_NVMUPD_EXEC_AQ: + status = i40e_nvmupd_exec_aq(hw, cmd, bytes, perrno); + break; + default: i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: bad cmd %s in init state\n", @@ -1069,6 +1077,10 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, case (I40E_NVM_CSUM|I40E_NVM_LCB): upd_cmd = I40E_NVMUPD_CSUM_LCB; break; + case I40E_NVM_EXEC: + if (module == 0) + upd_cmd = I40E_NVMUPD_EXEC_AQ; + break; } break; } @@ -1076,6 +1088,77 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, return upd_cmd; } +/** + * i40e_nvmupd_exec_aq - Run an AQ command + * @hw: pointer to hardware structure + * @cmd: pointer to nvm update command buffer + * @bytes: pointer to the data buffer + * @perrno: pointer to return error code + * + * cmd structure contains identifiers and data buffer + **/ +static i40e_status i40e_nvmupd_exec_aq(struct i40e_hw *hw, + struct i40e_nvm_access *cmd, + u8 *bytes, int *perrno) +{ + struct i40e_asq_cmd_details cmd_details; + i40e_status status; + struct i40e_aq_desc *aq_desc; + u32 buff_size = 0; + u8 *buff = NULL; + u32 aq_desc_len; + u32 aq_data_len; + + i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__); + memset(&cmd_details, 0, sizeof(cmd_details)); + cmd_details.wb_desc = &hw->nvm_wb_desc; + + aq_desc_len = sizeof(struct i40e_aq_desc); + memset(&hw->nvm_wb_desc, 0, aq_desc_len); + + /* get the aq descriptor */ + if (cmd->data_size < aq_desc_len) { + i40e_debug(hw, I40E_DEBUG_NVM, + "NVMUPD: not enough aq desc bytes for exec, size %d < %d\n", + cmd->data_size, aq_desc_len); + *perrno = -EINVAL; + return I40E_ERR_PARAM; + } + aq_desc = (struct i40e_aq_desc *)bytes; + + /* if data buffer needed, make sure it's ready */ + aq_data_len = cmd->data_size - aq_desc_len; + buff_size = max_t(u32, aq_data_len, le16_to_cpu(aq_desc->datalen)); + if (buff_size) { + if (!hw->nvm_buff.va) { + status = i40e_allocate_virt_mem(hw, &hw->nvm_buff, + hw->aq.asq_buf_size); + if (status) + i40e_debug(hw, I40E_DEBUG_NVM, + "NVMUPD: i40e_allocate_virt_mem for exec buff failed, %d\n", + status); + } + + if (hw->nvm_buff.va) { + buff = hw->nvm_buff.va; + memcpy(buff, &bytes[aq_desc_len], aq_data_len); + } + } + + /* and away we go! */ + status = i40e_asq_send_command(hw, aq_desc, buff, + buff_size, &cmd_details); + if (status) { + i40e_debug(hw, I40E_DEBUG_NVM, + "i40e_nvmupd_exec_aq err %s aq_err %s\n", + i40e_stat_str(hw, status), + i40e_aq_str(hw, hw->aq.asq_last_status)); + *perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status); + } + + return status; +} + /** * i40e_nvmupd_nvm_read - Read NVM * @hw: pointer to hardware structure diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 3f7993016494..a78b0771476c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -306,6 +306,7 @@ enum i40e_nvmupd_cmd { I40E_NVMUPD_CSUM_SA, I40E_NVMUPD_CSUM_LCB, I40E_NVMUPD_STATUS, + I40E_NVMUPD_EXEC_AQ, }; enum i40e_nvmupd_state { @@ -497,6 +498,7 @@ struct i40e_hw { /* state of nvm update process */ enum i40e_nvmupd_state nvmupd_state; struct i40e_aq_desc nvm_wb_desc; + struct i40e_virt_mem nvm_buff; /* HMC info */ struct i40e_hmc_info hmc; /* HMC info struct */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c index 15c8ac892704..0940db731382 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c @@ -596,6 +596,9 @@ i40e_status i40evf_shutdown_adminq(struct i40e_hw *hw) /* destroy the locks */ + if (hw->nvm_buff.va) + i40e_free_virt_mem(hw, &hw->nvm_buff); + return ret_code; } diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 439a4e1f2689..4d36615403f5 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -305,6 +305,7 @@ enum i40e_nvmupd_cmd { I40E_NVMUPD_CSUM_SA, I40E_NVMUPD_CSUM_LCB, I40E_NVMUPD_STATUS, + I40E_NVMUPD_EXEC_AQ, }; enum i40e_nvmupd_state { @@ -491,6 +492,7 @@ struct i40e_hw { /* state of nvm update process */ enum i40e_nvmupd_state nvmupd_state; struct i40e_aq_desc nvm_wb_desc; + struct i40e_virt_mem nvm_buff; /* HMC info */ struct i40e_hmc_info hmc; /* HMC info struct */ -- cgit v1.2.3 From b72dc7b19398b238698fbc5954a3c3de6cbc815d Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 28 Aug 2015 17:55:51 -0400 Subject: i40e/i40evf: add get AQ result command to nvmupdate utility Add a facility to recover the result of a previously run AQ command. Change-ID: I21afec2c20c1a5e6ba60c7fbfcbedfff78c10e45 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 79 +++++++++++++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_type.h | 1 + 3 files changed, 81 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 50d4aa3cf658..d0288ad4e9b2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -618,6 +618,9 @@ static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw, static i40e_status i40e_nvmupd_exec_aq(struct i40e_hw *hw, struct i40e_nvm_access *cmd, u8 *bytes, int *perrno); +static i40e_status i40e_nvmupd_get_aq_result(struct i40e_hw *hw, + struct i40e_nvm_access *cmd, + u8 *bytes, int *perrno); static inline u8 i40e_nvmupd_get_module(u32 val) { return (u8)(val & I40E_NVM_MOD_PNT_MASK); @@ -643,6 +646,7 @@ static char *i40e_nvm_update_state_str[] = { "I40E_NVMUPD_CSUM_LCB", "I40E_NVMUPD_STATUS", "I40E_NVMUPD_EXEC_AQ", + "I40E_NVMUPD_GET_AQ_RESULT", }; /** @@ -832,6 +836,10 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw, status = i40e_nvmupd_exec_aq(hw, cmd, bytes, perrno); break; + case I40E_NVMUPD_GET_AQ_RESULT: + status = i40e_nvmupd_get_aq_result(hw, cmd, bytes, perrno); + break; + default: i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: bad cmd %s in init state\n", @@ -1047,6 +1055,8 @@ static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw, case I40E_NVM_EXEC: if (module == 0xf) upd_cmd = I40E_NVMUPD_STATUS; + else if (module == 0) + upd_cmd = I40E_NVMUPD_GET_AQ_RESULT; break; } break; @@ -1159,6 +1169,75 @@ static i40e_status i40e_nvmupd_exec_aq(struct i40e_hw *hw, return status; } +/** + * i40e_nvmupd_get_aq_result - Get the results from the previous exec_aq + * @hw: pointer to hardware structure + * @cmd: pointer to nvm update command buffer + * @bytes: pointer to the data buffer + * @perrno: pointer to return error code + * + * cmd structure contains identifiers and data buffer + **/ +static i40e_status i40e_nvmupd_get_aq_result(struct i40e_hw *hw, + struct i40e_nvm_access *cmd, + u8 *bytes, int *perrno) +{ + u32 aq_total_len; + u32 aq_desc_len; + int remainder; + u8 *buff; + + i40e_debug(hw, I40E_DEBUG_NVM, "NVMUPD: %s\n", __func__); + + aq_desc_len = sizeof(struct i40e_aq_desc); + aq_total_len = aq_desc_len + le16_to_cpu(hw->nvm_wb_desc.datalen); + + /* check offset range */ + if (cmd->offset > aq_total_len) { + i40e_debug(hw, I40E_DEBUG_NVM, "%s: offset too big %d > %d\n", + __func__, cmd->offset, aq_total_len); + *perrno = -EINVAL; + return I40E_ERR_PARAM; + } + + /* check copylength range */ + if (cmd->data_size > (aq_total_len - cmd->offset)) { + int new_len = aq_total_len - cmd->offset; + + i40e_debug(hw, I40E_DEBUG_NVM, "%s: copy length %d too big, trimming to %d\n", + __func__, cmd->data_size, new_len); + cmd->data_size = new_len; + } + + remainder = cmd->data_size; + if (cmd->offset < aq_desc_len) { + u32 len = aq_desc_len - cmd->offset; + + len = min(len, cmd->data_size); + i40e_debug(hw, I40E_DEBUG_NVM, "%s: aq_desc bytes %d to %d\n", + __func__, cmd->offset, cmd->offset + len); + + buff = ((u8 *)&hw->nvm_wb_desc) + cmd->offset; + memcpy(bytes, buff, len); + + bytes += len; + remainder -= len; + buff = hw->nvm_buff.va; + } else { + buff = hw->nvm_buff.va + (cmd->offset - aq_desc_len); + } + + if (remainder > 0) { + int start_byte = buff - (u8 *)hw->nvm_buff.va; + + i40e_debug(hw, I40E_DEBUG_NVM, "%s: databuf bytes %d to %d\n", + __func__, start_byte, start_byte + remainder); + memcpy(bytes, buff, remainder); + } + + return 0; +} + /** * i40e_nvmupd_nvm_read - Read NVM * @hw: pointer to hardware structure diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index a78b0771476c..af4829065af6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -307,6 +307,7 @@ enum i40e_nvmupd_cmd { I40E_NVMUPD_CSUM_LCB, I40E_NVMUPD_STATUS, I40E_NVMUPD_EXEC_AQ, + I40E_NVMUPD_GET_AQ_RESULT, }; enum i40e_nvmupd_state { diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 4d36615403f5..ed7166693e5f 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -306,6 +306,7 @@ enum i40e_nvmupd_cmd { I40E_NVMUPD_CSUM_LCB, I40E_NVMUPD_STATUS, I40E_NVMUPD_EXEC_AQ, + I40E_NVMUPD_GET_AQ_RESULT, }; enum i40e_nvmupd_state { -- cgit v1.2.3 From f91638af0ef7cf85c204e3ebc853a35a99992e93 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Fri, 28 Aug 2015 17:56:01 -0400 Subject: i40e/i40evf: Bump i40e to 1.3.21 and i40evf to 1.3.13 Bump. Change-ID: If7ce84218361defa209142d1d8c6f69d48c2d7ad Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 851c1a159be8..530d8b6739f9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -39,7 +39,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 3 -#define DRV_VERSION_BUILD 9 +#define DRV_VERSION_BUILD 21 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index e85849b9ff98..5fc820412fca 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -34,7 +34,7 @@ char i40evf_driver_name[] = "i40evf"; static const char i40evf_driver_string[] = "Intel(R) XL710/X710 Virtual Function Network Driver"; -#define DRV_VERSION "1.3.5" +#define DRV_VERSION "1.3.13" const char i40evf_driver_version[] = DRV_VERSION; static const char i40evf_copyright[] = "Copyright (c) 2013 - 2015 Intel Corporation."; -- cgit v1.2.3 From 4b1b865e4e97e336316f30e32af36d71e98bdabc Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 15 Sep 2015 15:24:28 -0700 Subject: bonding: use l4 hash if available If skb carries a l4 hash, no need to perform a flow dissection. Performance is slightly better : lpaa5:~# ./super_netperf 200 -H lpaa6 -t TCP_RR -l 100 2.39012e+06 lpaa5:~# ./super_netperf 200 -H lpaa6 -t TCP_RR -l 100 2.39393e+06 lpaa5:~# ./super_netperf 200 -H lpaa6 -t TCP_RR -l 100 2.39988e+06 After patch : lpaa5:~# ./super_netperf 200 -H lpaa6 -t TCP_RR -l 100 2.43579e+06 lpaa5:~# ./super_netperf 200 -H lpaa6 -t TCP_RR -l 100 2.44304e+06 lpaa5:~# ./super_netperf 200 -H lpaa6 -t TCP_RR -l 100 2.44312e+06 Signed-off-by: Eric Dumazet Cc: Tom Herbert Cc: Mahesh Bandewar Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 771a449d2f56..90f2615428c0 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3136,6 +3136,10 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb) struct flow_keys flow; u32 hash; + if (bond->params.xmit_policy == BOND_XMIT_POLICY_ENCAP34 && + skb->l4_hash) + return skb->hash; + if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER2 || !bond_flow_dissect(bond, skb, &flow)) return bond_eth_hash(skb); -- cgit v1.2.3 From 6c595b03b1087f9f18a809ee7ce1a79c746037d5 Mon Sep 17 00:00:00 2001 From: "Woojung.Huh@microchip.com" Date: Wed, 16 Sep 2015 23:40:39 +0000 Subject: lan78xx: Check device ready bit (PMT_CTL_READY_) after reset the PHY Check device ready bit (PMT_CTL_READY_) after reset the PHY. Device may not be ready even if PHY_RST_ is cleared depends on configuration. Signed-off-by: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index a39518fc93aa..d0d8790d5d1b 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -2002,7 +2002,7 @@ static int lan78xx_reset(struct lan78xx_net *dev) netdev_warn(dev->net, "timeout waiting for PHY Reset"); return -EIO; } - } while (buf & PMT_CTL_PHY_RST_); + } while ((buf & PMT_CTL_PHY_RST_) || !(buf & PMT_CTL_READY_)); lan78xx_mii_init(dev); -- cgit v1.2.3 From 05fe68c008daaa641531f3cb44c567f04bf19ef7 Mon Sep 17 00:00:00 2001 From: "Woojung.Huh@microchip.com" Date: Wed, 16 Sep 2015 23:40:47 +0000 Subject: lan78xx: Add PHYLIB and MICROCHIP_PHY as default config. Add PHYLIB and MICROCHIP_PHY as default configuration for lan78xx. Signed-off-by: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/usb/Kconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 975357ddeae6..167cfc503a78 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -109,6 +109,8 @@ config USB_RTL8152 config USB_LAN78XX tristate "Microchip LAN78XX Based USB Ethernet Adapters" select MII + select PHYLIB + select MICROCHIP_PHY help This option adds support for Microchip LAN78XX based USB 2 & USB 3 10/100/1000 Ethernet adapters. -- cgit v1.2.3 From ce85e13ad6ef47ddcd34684889dc38a9901868ef Mon Sep 17 00:00:00 2001 From: "Woojung.Huh@microchip.com" Date: Wed, 16 Sep 2015 23:40:54 +0000 Subject: lan78xx: Update to use phylib instead of mii_if_info. Update to use phylib instead of mii_if_info. Signed-off-by: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 618 +++++++++++++++++++--------------------------- 1 file changed, 256 insertions(+), 362 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index d0d8790d5d1b..5d9c527356a2 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -36,7 +35,7 @@ #define DRIVER_AUTHOR "WOOJUNG HUH " #define DRIVER_DESC "LAN78XX USB 3.0 Gigabit Ethernet Devices" #define DRIVER_NAME "lan78xx" -#define DRIVER_VERSION "1.0.0" +#define DRIVER_VERSION "1.0.1" #define TX_TIMEOUT_JIFFIES (5 * HZ) #define THROTTLE_JIFFIES (HZ / 8) @@ -57,7 +56,6 @@ #define DEFAULT_RX_CSUM_ENABLE (true) #define DEFAULT_TSO_CSUM_ENABLE (true) #define DEFAULT_VLAN_FILTER_ENABLE (true) -#define INTERNAL_PHY_ID (2) /* 2: GMII */ #define TX_OVERHEAD (8) #define RXW_PADDING 2 @@ -275,10 +273,12 @@ struct lan78xx_net { struct timer_list delay; unsigned long data[5]; - struct mii_if_info mii; int link_on; u8 mdix_ctrl; + + u32 devid; + struct mii_bus *mdiobus; }; /* use ethtool to change the level for any given device */ @@ -411,222 +411,6 @@ static inline u32 mii_access(int id, int index, int read) return ret; } -static int lan78xx_mdio_read(struct net_device *netdev, int phy_id, int idx) -{ - struct lan78xx_net *dev = netdev_priv(netdev); - u32 val, addr; - int ret; - - ret = usb_autopm_get_interface(dev->intf); - if (ret < 0) - return ret; - - mutex_lock(&dev->phy_mutex); - - /* confirm MII not busy */ - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - - /* set the address, index & direction (read from PHY) */ - phy_id &= dev->mii.phy_id_mask; - idx &= dev->mii.reg_num_mask; - addr = mii_access(phy_id, idx, MII_READ); - ret = lan78xx_write_reg(dev, MII_ACC, addr); - - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - - ret = lan78xx_read_reg(dev, MII_DATA, &val); - - ret = (int)(val & 0xFFFF); - -done: - mutex_unlock(&dev->phy_mutex); - usb_autopm_put_interface(dev->intf); - return ret; -} - -static void lan78xx_mdio_write(struct net_device *netdev, int phy_id, - int idx, int regval) -{ - struct lan78xx_net *dev = netdev_priv(netdev); - u32 val, addr; - int ret; - - if (usb_autopm_get_interface(dev->intf) < 0) - return; - - mutex_lock(&dev->phy_mutex); - - /* confirm MII not busy */ - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - - val = regval; - ret = lan78xx_write_reg(dev, MII_DATA, val); - - /* set the address, index & direction (write to PHY) */ - phy_id &= dev->mii.phy_id_mask; - idx &= dev->mii.reg_num_mask; - addr = mii_access(phy_id, idx, MII_WRITE); - ret = lan78xx_write_reg(dev, MII_ACC, addr); - - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - -done: - mutex_unlock(&dev->phy_mutex); - usb_autopm_put_interface(dev->intf); -} - -static void lan78xx_mmd_write(struct net_device *netdev, int phy_id, - int mmddev, int mmdidx, int regval) -{ - struct lan78xx_net *dev = netdev_priv(netdev); - u32 val, addr; - int ret; - - if (usb_autopm_get_interface(dev->intf) < 0) - return; - - mutex_lock(&dev->phy_mutex); - - /* confirm MII not busy */ - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - - mmddev &= 0x1F; - - /* set up device address for MMD */ - ret = lan78xx_write_reg(dev, MII_DATA, mmddev); - - phy_id &= dev->mii.phy_id_mask; - addr = mii_access(phy_id, PHY_MMD_CTL, MII_WRITE); - ret = lan78xx_write_reg(dev, MII_ACC, addr); - - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - - /* select register of MMD */ - val = mmdidx; - ret = lan78xx_write_reg(dev, MII_DATA, val); - - phy_id &= dev->mii.phy_id_mask; - addr = mii_access(phy_id, PHY_MMD_REG_DATA, MII_WRITE); - ret = lan78xx_write_reg(dev, MII_ACC, addr); - - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - - /* select register data for MMD */ - val = PHY_MMD_CTRL_OP_DNI_ | mmddev; - ret = lan78xx_write_reg(dev, MII_DATA, val); - - phy_id &= dev->mii.phy_id_mask; - addr = mii_access(phy_id, PHY_MMD_CTL, MII_WRITE); - ret = lan78xx_write_reg(dev, MII_ACC, addr); - - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - - /* write to MMD */ - val = regval; - ret = lan78xx_write_reg(dev, MII_DATA, val); - - phy_id &= dev->mii.phy_id_mask; - addr = mii_access(phy_id, PHY_MMD_REG_DATA, MII_WRITE); - ret = lan78xx_write_reg(dev, MII_ACC, addr); - - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - -done: - mutex_unlock(&dev->phy_mutex); - usb_autopm_put_interface(dev->intf); -} - -static int lan78xx_mmd_read(struct net_device *netdev, int phy_id, - int mmddev, int mmdidx) -{ - struct lan78xx_net *dev = netdev_priv(netdev); - u32 val, addr; - int ret; - - ret = usb_autopm_get_interface(dev->intf); - if (ret < 0) - return ret; - - mutex_lock(&dev->phy_mutex); - - /* confirm MII not busy */ - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - - /* set up device address for MMD */ - ret = lan78xx_write_reg(dev, MII_DATA, mmddev); - - phy_id &= dev->mii.phy_id_mask; - addr = mii_access(phy_id, PHY_MMD_CTL, MII_WRITE); - ret = lan78xx_write_reg(dev, MII_ACC, addr); - - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - - /* select register of MMD */ - val = mmdidx; - ret = lan78xx_write_reg(dev, MII_DATA, val); - - phy_id &= dev->mii.phy_id_mask; - addr = mii_access(phy_id, PHY_MMD_REG_DATA, MII_WRITE); - ret = lan78xx_write_reg(dev, MII_ACC, addr); - - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - - /* select register data for MMD */ - val = PHY_MMD_CTRL_OP_DNI_ | mmddev; - ret = lan78xx_write_reg(dev, MII_DATA, val); - - phy_id &= dev->mii.phy_id_mask; - addr = mii_access(phy_id, PHY_MMD_CTL, MII_WRITE); - ret = lan78xx_write_reg(dev, MII_ACC, addr); - - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - - /* set the address, index & direction (read from PHY) */ - phy_id &= dev->mii.phy_id_mask; - addr = mii_access(phy_id, PHY_MMD_REG_DATA, MII_READ); - ret = lan78xx_write_reg(dev, MII_ACC, addr); - - ret = lan78xx_phy_wait_not_busy(dev); - if (ret < 0) - goto done; - - /* read from MMD */ - ret = lan78xx_read_reg(dev, MII_DATA, &val); - - ret = (int)(val & 0xFFFF); - -done: - mutex_unlock(&dev->phy_mutex); - usb_autopm_put_interface(dev->intf); - return ret; -} - static int lan78xx_wait_eeprom(struct lan78xx_net *dev) { unsigned long start_time = jiffies; @@ -1047,14 +831,14 @@ static int lan78xx_update_flowcontrol(struct lan78xx_net *dev, u8 duplex, static int lan78xx_link_reset(struct lan78xx_net *dev) { - struct mii_if_info *mii = &dev->mii; + struct phy_device *phydev = dev->net->phydev; struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; int ladv, radv, ret; u32 buf; /* clear PHY interrupt status */ /* VTSE PHY */ - ret = lan78xx_mdio_read(dev->net, mii->phy_id, PHY_VTSE_INT_STS); + ret = phy_read(phydev, PHY_VTSE_INT_STS); if (unlikely(ret < 0)) return -EIO; @@ -1063,7 +847,9 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) if (unlikely(ret < 0)) return -EIO; - if (!mii_link_ok(mii) && dev->link_on) { + phy_read_status(phydev); + + if (!phydev->link && dev->link_on) { dev->link_on = false; netif_carrier_off(dev->net); @@ -1075,13 +861,12 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) ret = lan78xx_write_reg(dev, MAC_CR, buf); if (unlikely(ret < 0)) return -EIO; - } else if (mii_link_ok(mii) && !dev->link_on) { + } else if (phydev->link && !dev->link_on) { dev->link_on = true; - mii_check_media(mii, 1, 1); - mii_ethtool_gset(&dev->mii, &ecmd); + phy_ethtool_gset(phydev, &ecmd); - mii->mdio_read(mii->dev, mii->phy_id, PHY_VTSE_INT_STS); + ret = phy_read(phydev, PHY_VTSE_INT_STS); if (dev->udev->speed == USB_SPEED_SUPER) { if (ethtool_cmd_speed(&ecmd) == 1000) { @@ -1102,11 +887,11 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) } } - ladv = lan78xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); + ladv = phy_read(phydev, MII_ADVERTISE); if (ladv < 0) return ladv; - radv = lan78xx_mdio_read(dev->net, mii->phy_id, MII_LPA); + radv = phy_read(phydev, MII_LPA); if (radv < 0) return radv; @@ -1279,6 +1064,8 @@ static int lan78xx_set_wol(struct net_device *netdev, device_set_wakeup_enable(&dev->udev->dev, (bool)wol->wolopts); + phy_ethtool_set_wol(netdev->phydev, wol); + usb_autopm_put_interface(dev->intf); return ret; @@ -1287,49 +1074,39 @@ static int lan78xx_set_wol(struct net_device *netdev, static int lan78xx_get_eee(struct net_device *net, struct ethtool_eee *edata) { struct lan78xx_net *dev = netdev_priv(net); + struct phy_device *phydev = net->phydev; int ret; u32 buf; - u32 adv, lpadv; ret = usb_autopm_get_interface(dev->intf); if (ret < 0) return ret; + ret = phy_ethtool_get_eee(phydev, edata); + if (ret < 0) + goto exit; + ret = lan78xx_read_reg(dev, MAC_CR, &buf); if (buf & MAC_CR_EEE_EN_) { - buf = lan78xx_mmd_read(dev->net, dev->mii.phy_id, - PHY_MMD_DEV_7, PHY_EEE_ADVERTISEMENT); - adv = mmd_eee_adv_to_ethtool_adv_t(buf); - buf = lan78xx_mmd_read(dev->net, dev->mii.phy_id, - PHY_MMD_DEV_7, PHY_EEE_LP_ADVERTISEMENT); - lpadv = mmd_eee_adv_to_ethtool_adv_t(buf); - edata->eee_enabled = true; - edata->supported = true; - edata->eee_active = !!(adv & lpadv); - edata->advertised = adv; - edata->lp_advertised = lpadv; + edata->eee_active = !!(edata->advertised & + edata->lp_advertised); edata->tx_lpi_enabled = true; /* EEE_TX_LPI_REQ_DLY & tx_lpi_timer are same uSec unit */ ret = lan78xx_read_reg(dev, EEE_TX_LPI_REQ_DLY, &buf); edata->tx_lpi_timer = buf; } else { - buf = lan78xx_mmd_read(dev->net, dev->mii.phy_id, - PHY_MMD_DEV_7, PHY_EEE_LP_ADVERTISEMENT); - lpadv = mmd_eee_adv_to_ethtool_adv_t(buf); - edata->eee_enabled = false; edata->eee_active = false; - edata->supported = false; - edata->advertised = 0; - edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(lpadv); edata->tx_lpi_enabled = false; edata->tx_lpi_timer = 0; } + ret = 0; +exit: usb_autopm_put_interface(dev->intf); - return 0; + return ret; } static int lan78xx_set_eee(struct net_device *net, struct ethtool_eee *edata) @@ -1347,9 +1124,10 @@ static int lan78xx_set_eee(struct net_device *net, struct ethtool_eee *edata) buf |= MAC_CR_EEE_EN_; ret = lan78xx_write_reg(dev, MAC_CR, buf); - buf = ethtool_adv_to_mmd_eee_adv_t(edata->advertised); - lan78xx_mmd_write(dev->net, dev->mii.phy_id, - PHY_MMD_DEV_7, PHY_EEE_ADVERTISEMENT, buf); + phy_ethtool_set_eee(net->phydev, edata); + + buf = (u32)edata->tx_lpi_timer; + ret = lan78xx_write_reg(dev, EEE_TX_LPI_REQ_DLY, buf); } else { ret = lan78xx_read_reg(dev, MAC_CR, &buf); buf &= ~MAC_CR_EEE_EN_; @@ -1363,19 +1141,14 @@ static int lan78xx_set_eee(struct net_device *net, struct ethtool_eee *edata) static u32 lan78xx_get_link(struct net_device *net) { - struct lan78xx_net *dev = netdev_priv(net); + phy_read_status(net->phydev); - return mii_link_ok(&dev->mii); + return net->phydev->link; } int lan78xx_nway_reset(struct net_device *net) { - struct lan78xx_net *dev = netdev_priv(net); - - if ((!dev->mii.mdio_read) || (!dev->mii.mdio_write)) - return -EOPNOTSUPP; - - return mii_nway_restart(&dev->mii); + return phy_start_aneg(net->phydev); } static void lan78xx_get_drvinfo(struct net_device *net, @@ -1405,24 +1178,19 @@ static void lan78xx_set_msglevel(struct net_device *net, u32 level) static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd) { struct lan78xx_net *dev = netdev_priv(net); - struct mii_if_info *mii = &dev->mii; + struct phy_device *phydev = net->phydev; int ret; int buf; - if ((!dev->mii.mdio_read) || (!dev->mii.mdio_write)) - return -EOPNOTSUPP; - ret = usb_autopm_get_interface(dev->intf); if (ret < 0) return ret; - ret = mii_ethtool_gset(&dev->mii, cmd); + ret = phy_ethtool_gset(phydev, cmd); - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_1); - buf = mii->mdio_read(mii->dev, mii->phy_id, PHY_EXT_MODE_CTRL); - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_0); + phy_write(phydev, PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_1); + buf = phy_read(phydev, PHY_EXT_MODE_CTRL); + phy_write(phydev, PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_0); buf &= PHY_EXT_MODE_CTRL_MDIX_MASK_; if (buf == PHY_EXT_MODE_CTRL_AUTO_MDIX_) { @@ -1444,70 +1212,54 @@ static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd) static int lan78xx_set_settings(struct net_device *net, struct ethtool_cmd *cmd) { struct lan78xx_net *dev = netdev_priv(net); - struct mii_if_info *mii = &dev->mii; + struct phy_device *phydev = net->phydev; int ret = 0; int temp; - if ((!dev->mii.mdio_read) || (!dev->mii.mdio_write)) - return -EOPNOTSUPP; - ret = usb_autopm_get_interface(dev->intf); if (ret < 0) return ret; if (dev->mdix_ctrl != cmd->eth_tp_mdix_ctrl) { if (cmd->eth_tp_mdix_ctrl == ETH_TP_MDI) { - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_GPIO_PAGE, - PHY_EXT_GPIO_PAGE_SPACE_1); - temp = mii->mdio_read(mii->dev, mii->phy_id, - PHY_EXT_MODE_CTRL); + phy_write(phydev, PHY_EXT_GPIO_PAGE, + PHY_EXT_GPIO_PAGE_SPACE_1); + temp = phy_read(phydev, PHY_EXT_MODE_CTRL); temp &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_; - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_MODE_CTRL, - temp | PHY_EXT_MODE_CTRL_MDI_); - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_GPIO_PAGE, - PHY_EXT_GPIO_PAGE_SPACE_0); + phy_write(phydev, PHY_EXT_MODE_CTRL, + temp | PHY_EXT_MODE_CTRL_MDI_); + phy_write(phydev, PHY_EXT_GPIO_PAGE, + PHY_EXT_GPIO_PAGE_SPACE_0); } else if (cmd->eth_tp_mdix_ctrl == ETH_TP_MDI_X) { - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_GPIO_PAGE, - PHY_EXT_GPIO_PAGE_SPACE_1); - temp = mii->mdio_read(mii->dev, mii->phy_id, - PHY_EXT_MODE_CTRL); + phy_write(phydev, PHY_EXT_GPIO_PAGE, + PHY_EXT_GPIO_PAGE_SPACE_1); + temp = phy_read(phydev, PHY_EXT_MODE_CTRL); temp &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_; - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_MODE_CTRL, - temp | PHY_EXT_MODE_CTRL_MDI_X_); - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_GPIO_PAGE, - PHY_EXT_GPIO_PAGE_SPACE_0); + phy_write(phydev, PHY_EXT_MODE_CTRL, + temp | PHY_EXT_MODE_CTRL_MDI_X_); + phy_write(phydev, PHY_EXT_GPIO_PAGE, + PHY_EXT_GPIO_PAGE_SPACE_0); } else if (cmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) { - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_GPIO_PAGE, - PHY_EXT_GPIO_PAGE_SPACE_1); - temp = mii->mdio_read(mii->dev, mii->phy_id, - PHY_EXT_MODE_CTRL); + phy_write(phydev, PHY_EXT_GPIO_PAGE, + PHY_EXT_GPIO_PAGE_SPACE_1); + temp = phy_read(phydev, PHY_EXT_MODE_CTRL); temp &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_; - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_MODE_CTRL, - temp | PHY_EXT_MODE_CTRL_AUTO_MDIX_); - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_GPIO_PAGE, - PHY_EXT_GPIO_PAGE_SPACE_0); + phy_write(phydev, PHY_EXT_MODE_CTRL, + temp | PHY_EXT_MODE_CTRL_AUTO_MDIX_); + phy_write(phydev, PHY_EXT_GPIO_PAGE, + PHY_EXT_GPIO_PAGE_SPACE_0); } } /* change speed & duplex */ - ret = mii_ethtool_sset(&dev->mii, cmd); + ret = phy_ethtool_sset(phydev, cmd); if (!cmd->autoneg) { /* force link down */ - temp = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR); - mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, - temp | BMCR_LOOPBACK); + temp = phy_read(phydev, MII_BMCR); + phy_write(phydev, MII_BMCR, temp | BMCR_LOOPBACK); mdelay(1); - mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, temp); + phy_write(phydev, MII_BMCR, temp); } usb_autopm_put_interface(dev->intf); @@ -1537,12 +1289,10 @@ static const struct ethtool_ops lan78xx_ethtool_ops = { static int lan78xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) { - struct lan78xx_net *dev = netdev_priv(netdev); - if (!netif_running(netdev)) return -EINVAL; - return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); + return phy_mii_ioctl(netdev->phydev, rq, cmd); } static void lan78xx_init_mac_address(struct lan78xx_net *dev) @@ -1598,53 +1348,189 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev) ether_addr_copy(dev->net->dev_addr, addr); } -static void lan78xx_mii_init(struct lan78xx_net *dev) +/* MDIO read and write wrappers for phylib */ +static int lan78xx_mdiobus_read(struct mii_bus *bus, int phy_id, int idx) +{ + struct lan78xx_net *dev = bus->priv; + u32 val, addr; + int ret; + + ret = usb_autopm_get_interface(dev->intf); + if (ret < 0) + return ret; + + mutex_lock(&dev->phy_mutex); + + /* confirm MII not busy */ + ret = lan78xx_phy_wait_not_busy(dev); + if (ret < 0) + goto done; + + /* set the address, index & direction (read from PHY) */ + addr = mii_access(phy_id, idx, MII_READ); + ret = lan78xx_write_reg(dev, MII_ACC, addr); + + ret = lan78xx_phy_wait_not_busy(dev); + if (ret < 0) + goto done; + + ret = lan78xx_read_reg(dev, MII_DATA, &val); + + ret = (int)(val & 0xFFFF); + +done: + mutex_unlock(&dev->phy_mutex); + usb_autopm_put_interface(dev->intf); + return ret; +} + +static int lan78xx_mdiobus_write(struct mii_bus *bus, int phy_id, int idx, + u16 regval) +{ + struct lan78xx_net *dev = bus->priv; + u32 val, addr; + int ret; + + ret = usb_autopm_get_interface(dev->intf); + if (ret < 0) + return ret; + + mutex_lock(&dev->phy_mutex); + + /* confirm MII not busy */ + ret = lan78xx_phy_wait_not_busy(dev); + if (ret < 0) + goto done; + + val = (u32)regval; + ret = lan78xx_write_reg(dev, MII_DATA, val); + + /* set the address, index & direction (write to PHY) */ + addr = mii_access(phy_id, idx, MII_WRITE); + ret = lan78xx_write_reg(dev, MII_ACC, addr); + + ret = lan78xx_phy_wait_not_busy(dev); + if (ret < 0) + goto done; + +done: + mutex_unlock(&dev->phy_mutex); + usb_autopm_put_interface(dev->intf); + return 0; +} + +static int lan78xx_mdio_init(struct lan78xx_net *dev) { - /* Initialize MII structure */ - dev->mii.dev = dev->net; - dev->mii.mdio_read = lan78xx_mdio_read; - dev->mii.mdio_write = lan78xx_mdio_write; - dev->mii.phy_id_mask = 0x1f; - dev->mii.reg_num_mask = 0x1f; - dev->mii.phy_id = INTERNAL_PHY_ID; - dev->mii.supports_gmii = true; + int ret; + int i; + + dev->mdiobus = mdiobus_alloc(); + if (!dev->mdiobus) { + netdev_err(dev->net, "can't allocate MDIO bus\n"); + return -ENOMEM; + } + + dev->mdiobus->priv = (void *)dev; + dev->mdiobus->read = lan78xx_mdiobus_read; + dev->mdiobus->write = lan78xx_mdiobus_write; + dev->mdiobus->name = "lan78xx-mdiobus"; + + snprintf(dev->mdiobus->id, MII_BUS_ID_SIZE, "usb-%03d:%03d", + dev->udev->bus->busnum, dev->udev->devnum); + + dev->mdiobus->irq = kzalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); + if (!dev->mdiobus->irq) { + ret = -ENOMEM; + goto exit1; + } + + /* handle our own interrupt */ + for (i = 0; i < PHY_MAX_ADDR; i++) + dev->mdiobus->irq[i] = PHY_IGNORE_INTERRUPT; + + switch (dev->devid & ID_REV_CHIP_ID_MASK_) { + case 0x78000000: + case 0x78500000: + /* set to internal PHY id */ + dev->mdiobus->phy_mask = ~(1 << 1); + break; + } + + ret = mdiobus_register(dev->mdiobus); + if (ret) { + netdev_err(dev->net, "can't register MDIO bus\n"); + goto exit2; + } + + netdev_dbg(dev->net, "registered mdiobus bus %s\n", dev->mdiobus->id); + return 0; +exit2: + kfree(dev->mdiobus->irq); +exit1: + mdiobus_free(dev->mdiobus); + return ret; +} + +static void lan78xx_remove_mdio(struct lan78xx_net *dev) +{ + mdiobus_unregister(dev->mdiobus); + kfree(dev->mdiobus->irq); + mdiobus_free(dev->mdiobus); +} + +static void lan78xx_link_status_change(struct net_device *net) +{ + /* nothing to do */ } static int lan78xx_phy_init(struct lan78xx_net *dev) { - int temp; - struct mii_if_info *mii = &dev->mii; + int ret; + struct phy_device *phydev = dev->net->phydev; - if ((!mii->mdio_write) || (!mii->mdio_read)) - return -EOPNOTSUPP; + phydev = phy_find_first(dev->mdiobus); + if (!phydev) { + netdev_err(dev->net, "no PHY found\n"); + return -EIO; + } - temp = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE); - temp |= ADVERTISE_ALL; - mii->mdio_write(mii->dev, mii->phy_id, MII_ADVERTISE, - temp | ADVERTISE_CSMA | - ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + ret = phy_connect_direct(dev->net, phydev, + lan78xx_link_status_change, + PHY_INTERFACE_MODE_GMII); + if (ret) { + netdev_err(dev->net, "can't attach PHY to %s\n", + dev->mdiobus->id); + return -EIO; + } /* set to AUTOMDIX */ - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_1); - temp = mii->mdio_read(mii->dev, mii->phy_id, PHY_EXT_MODE_CTRL); - temp &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_; - mii->mdio_write(mii->dev, mii->phy_id, PHY_EXT_MODE_CTRL, - temp | PHY_EXT_MODE_CTRL_AUTO_MDIX_); - mii->mdio_write(mii->dev, mii->phy_id, - PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_0); + phy_write(phydev, PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_1); + ret = phy_read(phydev, PHY_EXT_MODE_CTRL); + ret &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_; + phy_write(phydev, PHY_EXT_MODE_CTRL, + ret | PHY_EXT_MODE_CTRL_AUTO_MDIX_); + phy_write(phydev, PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_0); dev->mdix_ctrl = ETH_TP_MDI_AUTO; - /* MAC doesn't support 1000HD */ - temp = mii->mdio_read(mii->dev, mii->phy_id, MII_CTRL1000); - mii->mdio_write(mii->dev, mii->phy_id, MII_CTRL1000, - temp & ~ADVERTISE_1000HALF); - - /* clear interrupt */ - mii->mdio_read(mii->dev, mii->phy_id, PHY_VTSE_INT_STS); - mii->mdio_write(mii->dev, mii->phy_id, PHY_VTSE_INT_MASK, - PHY_VTSE_INT_MASK_MDINTPIN_EN_ | - PHY_VTSE_INT_MASK_LINK_CHANGE_); + /* MAC doesn't support 1000T Half */ + phydev->supported &= ~SUPPORTED_1000baseT_Half; + phydev->supported |= (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_Pause | SUPPORTED_Asym_Pause); + genphy_config_aneg(phydev); + + /* Workaround to enable PHY interrupt. + * phy_start_interrupts() is API for requesting and enabling + * PHY interrupt. However, USB-to-Ethernet device can't use + * request_irq() called in phy_start_interrupts(). + * Set PHY to PHY_HALTED and call phy_start() + * to make a call to phy_enable_interrupts() + */ + phy_stop(phydev); + phy_start(phydev); netif_dbg(dev, ifup, dev->net, "phy initialised successfully"); @@ -1930,6 +1816,10 @@ static int lan78xx_reset(struct lan78xx_net *dev) lan78xx_init_mac_address(dev); + /* save DEVID for later usage */ + ret = lan78xx_read_reg(dev, ID_REV, &buf); + dev->devid = buf; + /* Respond to the IN token with a NAK */ ret = lan78xx_read_reg(dev, USB_CFG0, &buf); buf |= USB_CFG_BIR_; @@ -2004,10 +1894,6 @@ static int lan78xx_reset(struct lan78xx_net *dev) } } while ((buf & PMT_CTL_PHY_RST_) || !(buf & PMT_CTL_READY_)); - lan78xx_mii_init(dev); - - ret = lan78xx_phy_init(dev); - ret = lan78xx_read_reg(dev, MAC_CR, &buf); buf |= MAC_CR_GMII_EN_; @@ -2015,10 +1901,6 @@ static int lan78xx_reset(struct lan78xx_net *dev) ret = lan78xx_write_reg(dev, MAC_CR, buf); - /* enable on PHY */ - if (buf & MAC_CR_EEE_EN_) - lan78xx_mmd_write(dev->net, dev->mii.phy_id, 0x07, 0x3C, 0x06); - /* enable PHY interrupts */ ret = lan78xx_read_reg(dev, INT_EP_CTL, &buf); buf |= INT_ENP_PHY_INT; @@ -2042,9 +1924,6 @@ static int lan78xx_reset(struct lan78xx_net *dev) buf |= FCT_RX_CTL_EN_; ret = lan78xx_write_reg(dev, FCT_RX_CTL, buf); - if (!mii_nway_restart(&dev->mii)) - netif_dbg(dev, link, dev->net, "autoneg initiated"); - return 0; } @@ -2061,6 +1940,10 @@ static int lan78xx_open(struct net_device *net) if (ret < 0) goto done; + ret = lan78xx_phy_init(dev); + if (ret < 0) + goto done; + /* for Link Check */ if (dev->urb_intr) { ret = usb_submit_urb(dev->urb_intr, GFP_KERNEL); @@ -2115,6 +1998,10 @@ int lan78xx_stop(struct net_device *net) { struct lan78xx_net *dev = netdev_priv(net); + phy_stop(net->phydev); + phy_disconnect(net->phydev); + net->phydev = NULL; + clear_bit(EVENT_DEV_OPEN, &dev->flags); netif_stop_queue(net); @@ -2395,6 +2282,8 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf) /* Init all registers */ ret = lan78xx_reset(dev); + lan78xx_mdio_init(dev); + dev->net->flags |= IFF_MULTICAST; pdata->wol = WAKE_MAGIC; @@ -2406,6 +2295,8 @@ static void lan78xx_unbind(struct lan78xx_net *dev, struct usb_interface *intf) { struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]); + lan78xx_remove_mdio(dev); + if (pdata) { netif_dbg(dev, ifdown, dev->net, "free pdata"); kfree(pdata); @@ -3459,6 +3350,9 @@ int lan78xx_reset_resume(struct usb_interface *intf) struct lan78xx_net *dev = usb_get_intfdata(intf); lan78xx_reset(dev); + + lan78xx_phy_init(dev); + return lan78xx_resume(intf); } -- cgit v1.2.3 From bdfba55e0d541a9547d737573ae11db7ed72e2bb Mon Sep 17 00:00:00 2001 From: "Woojung.Huh@microchip.com" Date: Wed, 16 Sep 2015 23:41:07 +0000 Subject: lan78xx: Remove phy defines in lan78xx.h and use defines in include/linux/microchipphy.h Remove phy defines in lan78xx.h and use defines in include/linux/microchipphy.h. Signed-off-by: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 80 +++++++++---------- drivers/net/usb/lan78xx.h | 192 ---------------------------------------------- 2 files changed, 40 insertions(+), 232 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 5d9c527356a2..6bb2923396de 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "lan78xx.h" #define DRIVER_AUTHOR "WOOJUNG HUH " @@ -837,8 +838,7 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) u32 buf; /* clear PHY interrupt status */ - /* VTSE PHY */ - ret = phy_read(phydev, PHY_VTSE_INT_STS); + ret = phy_read(phydev, LAN88XX_INT_STS); if (unlikely(ret < 0)) return -EIO; @@ -866,7 +866,7 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) phy_ethtool_gset(phydev, &ecmd); - ret = phy_read(phydev, PHY_VTSE_INT_STS); + ret = phy_read(phydev, LAN88XX_INT_STS); if (dev->udev->speed == USB_SPEED_SUPER) { if (ethtool_cmd_speed(&ecmd) == 1000) { @@ -1188,18 +1188,18 @@ static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd) ret = phy_ethtool_gset(phydev, cmd); - phy_write(phydev, PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_1); - buf = phy_read(phydev, PHY_EXT_MODE_CTRL); - phy_write(phydev, PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_0); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_1); + buf = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_0); - buf &= PHY_EXT_MODE_CTRL_MDIX_MASK_; - if (buf == PHY_EXT_MODE_CTRL_AUTO_MDIX_) { + buf &= LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; + if (buf == LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_) { cmd->eth_tp_mdix = ETH_TP_MDI_AUTO; cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; - } else if (buf == PHY_EXT_MODE_CTRL_MDI_) { + } else if (buf == LAN88XX_EXT_MODE_CTRL_MDI_) { cmd->eth_tp_mdix = ETH_TP_MDI; cmd->eth_tp_mdix_ctrl = ETH_TP_MDI; - } else if (buf == PHY_EXT_MODE_CTRL_MDI_X_) { + } else if (buf == LAN88XX_EXT_MODE_CTRL_MDI_X_) { cmd->eth_tp_mdix = ETH_TP_MDI_X; cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_X; } @@ -1222,32 +1222,32 @@ static int lan78xx_set_settings(struct net_device *net, struct ethtool_cmd *cmd) if (dev->mdix_ctrl != cmd->eth_tp_mdix_ctrl) { if (cmd->eth_tp_mdix_ctrl == ETH_TP_MDI) { - phy_write(phydev, PHY_EXT_GPIO_PAGE, - PHY_EXT_GPIO_PAGE_SPACE_1); - temp = phy_read(phydev, PHY_EXT_MODE_CTRL); - temp &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_; - phy_write(phydev, PHY_EXT_MODE_CTRL, - temp | PHY_EXT_MODE_CTRL_MDI_); - phy_write(phydev, PHY_EXT_GPIO_PAGE, - PHY_EXT_GPIO_PAGE_SPACE_0); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, + LAN88XX_EXT_PAGE_SPACE_1); + temp = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); + temp &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; + phy_write(phydev, LAN88XX_EXT_MODE_CTRL, + temp | LAN88XX_EXT_MODE_CTRL_MDI_); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, + LAN88XX_EXT_PAGE_SPACE_0); } else if (cmd->eth_tp_mdix_ctrl == ETH_TP_MDI_X) { - phy_write(phydev, PHY_EXT_GPIO_PAGE, - PHY_EXT_GPIO_PAGE_SPACE_1); - temp = phy_read(phydev, PHY_EXT_MODE_CTRL); - temp &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_; - phy_write(phydev, PHY_EXT_MODE_CTRL, - temp | PHY_EXT_MODE_CTRL_MDI_X_); - phy_write(phydev, PHY_EXT_GPIO_PAGE, - PHY_EXT_GPIO_PAGE_SPACE_0); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, + LAN88XX_EXT_PAGE_SPACE_1); + temp = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); + temp &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; + phy_write(phydev, LAN88XX_EXT_MODE_CTRL, + temp | LAN88XX_EXT_MODE_CTRL_MDI_X_); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, + LAN88XX_EXT_PAGE_SPACE_0); } else if (cmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) { - phy_write(phydev, PHY_EXT_GPIO_PAGE, - PHY_EXT_GPIO_PAGE_SPACE_1); - temp = phy_read(phydev, PHY_EXT_MODE_CTRL); - temp &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_; - phy_write(phydev, PHY_EXT_MODE_CTRL, - temp | PHY_EXT_MODE_CTRL_AUTO_MDIX_); - phy_write(phydev, PHY_EXT_GPIO_PAGE, - PHY_EXT_GPIO_PAGE_SPACE_0); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, + LAN88XX_EXT_PAGE_SPACE_1); + temp = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); + temp &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; + phy_write(phydev, LAN88XX_EXT_MODE_CTRL, + temp | LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, + LAN88XX_EXT_PAGE_SPACE_0); } } @@ -1504,12 +1504,12 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) } /* set to AUTOMDIX */ - phy_write(phydev, PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_1); - ret = phy_read(phydev, PHY_EXT_MODE_CTRL); - ret &= ~PHY_EXT_MODE_CTRL_MDIX_MASK_; - phy_write(phydev, PHY_EXT_MODE_CTRL, - ret | PHY_EXT_MODE_CTRL_AUTO_MDIX_); - phy_write(phydev, PHY_EXT_GPIO_PAGE, PHY_EXT_GPIO_PAGE_SPACE_0); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_1); + ret = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); + ret &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; + phy_write(phydev, LAN88XX_EXT_MODE_CTRL, + ret | LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_0); dev->mdix_ctrl = ETH_TP_MDI_AUTO; /* MAC doesn't support 1000T Half */ diff --git a/drivers/net/usb/lan78xx.h b/drivers/net/usb/lan78xx.h index ae7562ee72ad..e0a5a8f529c1 100644 --- a/drivers/net/usb/lan78xx.h +++ b/drivers/net/usb/lan78xx.h @@ -874,196 +874,4 @@ #define OTP_TPVSR_VAL (OTP_BASE_ADDR + 4 * 0x3A) #define OTP_TPVHR_VAL (OTP_BASE_ADDR + 4 * 0x3B) #define OTP_TPVSA_VAL (OTP_BASE_ADDR + 4 * 0x3C) - -#define PHY_ID1 (0x02) -#define PHY_ID2 (0x03) - -#define PHY_DEV_ID_OUI_VTSE (0x04001C) -#define PHY_DEV_ID_MODEL_VTSE_8502 (0x23) - -#define PHY_AUTONEG_ADV (0x04) -#define NWAY_AR_NEXT_PAGE_ (0x8000) -#define NWAY_AR_REMOTE_FAULT_ (0x2000) -#define NWAY_AR_ASM_DIR_ (0x0800) -#define NWAY_AR_PAUSE_ (0x0400) -#define NWAY_AR_100T4_CAPS_ (0x0200) -#define NWAY_AR_100TX_FD_CAPS_ (0x0100) -#define NWAY_AR_SELECTOR_FIELD_ (0x001F) -#define NWAY_AR_100TX_HD_CAPS_ (0x0080) -#define NWAY_AR_10T_FD_CAPS_ (0x0040) -#define NWAY_AR_10T_HD_CAPS_ (0x0020) -#define NWAY_AR_ALL_CAPS_ (NWAY_AR_10T_HD_CAPS_ | \ - NWAY_AR_10T_FD_CAPS_ | \ - NWAY_AR_100TX_HD_CAPS_ | \ - NWAY_AR_100TX_FD_CAPS_) -#define NWAY_AR_PAUSE_MASK (NWAY_AR_PAUSE_ | NWAY_AR_ASM_DIR_) - -#define PHY_LP_ABILITY (0x05) -#define NWAY_LPAR_NEXT_PAGE_ (0x8000) -#define NWAY_LPAR_ACKNOWLEDGE_ (0x4000) -#define NWAY_LPAR_REMOTE_FAULT_ (0x2000) -#define NWAY_LPAR_ASM_DIR_ (0x0800) -#define NWAY_LPAR_PAUSE_ (0x0400) -#define NWAY_LPAR_100T4_CAPS_ (0x0200) -#define NWAY_LPAR_100TX_FD_CAPS_ (0x0100) -#define NWAY_LPAR_100TX_HD_CAPS_ (0x0080) -#define NWAY_LPAR_10T_FD_CAPS_ (0x0040) -#define NWAY_LPAR_10T_HD_CAPS_ (0x0020) -#define NWAY_LPAR_SELECTOR_FIELD_ (0x001F) - -#define PHY_AUTONEG_EXP (0x06) -#define NWAY_ER_PAR_DETECT_FAULT_ (0x0010) -#define NWAY_ER_LP_NEXT_PAGE_CAPS_ (0x0008) -#define NWAY_ER_NEXT_PAGE_CAPS_ (0x0004) -#define NWAY_ER_PAGE_RXD_ (0x0002) -#define NWAY_ER_LP_NWAY_CAPS_ (0x0001) - -#define PHY_NEXT_PAGE_TX (0x07) -#define NPTX_NEXT_PAGE_ (0x8000) -#define NPTX_MSG_PAGE_ (0x2000) -#define NPTX_ACKNOWLDGE2_ (0x1000) -#define NPTX_TOGGLE_ (0x0800) -#define NPTX_MSG_CODE_FIELD_ (0x0001) - -#define PHY_LP_NEXT_PAGE (0x08) -#define LP_RNPR_NEXT_PAGE_ (0x8000) -#define LP_RNPR_ACKNOWLDGE_ (0x4000) -#define LP_RNPR_MSG_PAGE_ (0x2000) -#define LP_RNPR_ACKNOWLDGE2_ (0x1000) -#define LP_RNPR_TOGGLE_ (0x0800) -#define LP_RNPR_MSG_CODE_FIELD_ (0x0001) - -#define PHY_1000T_CTRL (0x09) -#define CR_1000T_TEST_MODE_4_ (0x8000) -#define CR_1000T_TEST_MODE_3_ (0x6000) -#define CR_1000T_TEST_MODE_2_ (0x4000) -#define CR_1000T_TEST_MODE_1_ (0x2000) -#define CR_1000T_MS_ENABLE_ (0x1000) -#define CR_1000T_MS_VALUE_ (0x0800) -#define CR_1000T_REPEATER_DTE_ (0x0400) -#define CR_1000T_FD_CAPS_ (0x0200) -#define CR_1000T_HD_CAPS_ (0x0100) -#define CR_1000T_ASYM_PAUSE_ (0x0080) -#define CR_1000T_TEST_MODE_NORMAL_ (0x0000) - -#define PHY_1000T_STATUS (0x0A) -#define SR_1000T_MS_CONFIG_FAULT_ (0x8000) -#define SR_1000T_MS_CONFIG_RES_ (0x4000) -#define SR_1000T_LOCAL_RX_STATUS_ (0x2000) -#define SR_1000T_REMOTE_RX_STATUS_ (0x1000) -#define SR_1000T_LP_FD_CAPS_ (0x0800) -#define SR_1000T_LP_HD_CAPS_ (0x0400) -#define SR_1000T_ASYM_PAUSE_DIR_ (0x0100) -#define SR_1000T_IDLE_ERROR_CNT_ (0x00FF) -#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 -#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 -#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 -#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20 -#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100 - -#define PHY_EXT_STATUS (0x0F) -#define IEEE_ESR_1000X_FD_CAPS_ (0x8000) -#define IEEE_ESR_1000X_HD_CAPS_ (0x4000) -#define IEEE_ESR_1000T_FD_CAPS_ (0x2000) -#define IEEE_ESR_1000T_HD_CAPS_ (0x1000) -#define PHY_TX_POLARITY_MASK_ (0x0100) -#define PHY_TX_NORMAL_POLARITY_ (0x0000) -#define AUTO_POLARITY_DISABLE_ (0x0010) - -#define PHY_MMD_CTL (0x0D) -#define PHY_MMD_CTRL_OP_MASK_ (0xC000) -#define PHY_MMD_CTRL_OP_REG_ (0x0000) -#define PHY_MMD_CTRL_OP_DNI_ (0x4000) -#define PHY_MMD_CTRL_OP_DPIRW_ (0x8000) -#define PHY_MMD_CTRL_OP_DPIWO_ (0xC000) -#define PHY_MMD_CTRL_DEV_ADDR_MASK_ (0x001F) - -#define PHY_MMD_REG_DATA (0x0E) - -/* VTSE Vendor Specific registers */ -#define PHY_VTSE_BYPASS (0x12) -#define PHY_VTSE_BYPASS_DISABLE_PAIR_SWAP_ (0x0020) - -#define PHY_VTSE_INT_MASK (0x19) -#define PHY_VTSE_INT_MASK_MDINTPIN_EN_ (0x8000) -#define PHY_VTSE_INT_MASK_SPEED_CHANGE_ (0x4000) -#define PHY_VTSE_INT_MASK_LINK_CHANGE_ (0x2000) -#define PHY_VTSE_INT_MASK_FDX_CHANGE_ (0x1000) -#define PHY_VTSE_INT_MASK_AUTONEG_ERR_ (0x0800) -#define PHY_VTSE_INT_MASK_AUTONEG_DONE_ (0x0400) -#define PHY_VTSE_INT_MASK_POE_DETECT_ (0x0200) -#define PHY_VTSE_INT_MASK_SYMBOL_ERR_ (0x0100) -#define PHY_VTSE_INT_MASK_FAST_LINK_FAIL_ (0x0080) -#define PHY_VTSE_INT_MASK_WOL_EVENT_ (0x0040) -#define PHY_VTSE_INT_MASK_EXTENDED_INT_ (0x0020) -#define PHY_VTSE_INT_MASK_RESERVED_ (0x0010) -#define PHY_VTSE_INT_MASK_FALSE_CARRIER_ (0x0008) -#define PHY_VTSE_INT_MASK_LINK_SPEED_DS_ (0x0004) -#define PHY_VTSE_INT_MASK_MASTER_SLAVE_DONE_ (0x0002) -#define PHY_VTSE_INT_MASK_RX__ER_ (0x0001) - -#define PHY_VTSE_INT_STS (0x1A) -#define PHY_VTSE_INT_STS_INT_ACTIVE_ (0x8000) -#define PHY_VTSE_INT_STS_SPEED_CHANGE_ (0x4000) -#define PHY_VTSE_INT_STS_LINK_CHANGE_ (0x2000) -#define PHY_VTSE_INT_STS_FDX_CHANGE_ (0x1000) -#define PHY_VTSE_INT_STS_AUTONEG_ERR_ (0x0800) -#define PHY_VTSE_INT_STS_AUTONEG_DONE_ (0x0400) -#define PHY_VTSE_INT_STS_POE_DETECT_ (0x0200) -#define PHY_VTSE_INT_STS_SYMBOL_ERR_ (0x0100) -#define PHY_VTSE_INT_STS_FAST_LINK_FAIL_ (0x0080) -#define PHY_VTSE_INT_STS_WOL_EVENT_ (0x0040) -#define PHY_VTSE_INT_STS_EXTENDED_INT_ (0x0020) -#define PHY_VTSE_INT_STS_RESERVED_ (0x0010) -#define PHY_VTSE_INT_STS_FALSE_CARRIER_ (0x0008) -#define PHY_VTSE_INT_STS_LINK_SPEED_DS_ (0x0004) -#define PHY_VTSE_INT_STS_MASTER_SLAVE_DONE_ (0x0002) -#define PHY_VTSE_INT_STS_RX_ER_ (0x0001) - -/* VTSE PHY registers */ -#define PHY_EXT_GPIO_PAGE (0x1F) -#define PHY_EXT_GPIO_PAGE_SPACE_0 (0x0000) -#define PHY_EXT_GPIO_PAGE_SPACE_1 (0x0001) -#define PHY_EXT_GPIO_PAGE_SPACE_2 (0x0002) - -/* Extended Register Page 1 space */ -#define PHY_EXT_MODE_CTRL (0x13) -#define PHY_EXT_MODE_CTRL_MDIX_MASK_ (0x000C) -#define PHY_EXT_MODE_CTRL_AUTO_MDIX_ (0x0000) -#define PHY_EXT_MODE_CTRL_MDI_ (0x0008) -#define PHY_EXT_MODE_CTRL_MDI_X_ (0x000C) - -#define PHY_ANA_10BASE_T_HD 0x01 -#define PHY_ANA_10BASE_T_FD 0x02 -#define PHY_ANA_100BASE_TX_HD 0x04 -#define PHY_ANA_100BASE_TX_FD 0x08 -#define PHY_ANA_1000BASE_T_FD 0x10 -#define PHY_ANA_ALL_SUPPORTED_MEDIA (PHY_ANA_10BASE_T_HD | \ - PHY_ANA_10BASE_T_FD | \ - PHY_ANA_100BASE_TX_HD | \ - PHY_ANA_100BASE_TX_FD | \ - PHY_ANA_1000BASE_T_FD) -/* PHY MMD registers */ -#define PHY_MMD_DEV_3 3 - -#define PHY_EEE_PCS_STATUS (0x1) -#define PHY_EEE_PCS_STATUS_TX_LPI_RCVD_ ((WORD)0x0800) -#define PHY_EEE_PCS_STATUS_RX_LPI_RCVD_ ((WORD)0x0400) -#define PHY_EEE_PCS_STATUS_TX_LPI_IND_ ((WORD)0x0200) -#define PHY_EEE_PCS_STATUS_RX_LPI_IND_ ((WORD)0x0100) -#define PHY_EEE_PCS_STATUS_PCS_RCV_LNK_STS_ ((WORD)0x0004) - -#define PHY_EEE_CAPABILITIES (0x14) -#define PHY_EEE_CAPABILITIES_1000BT_EEE_ ((WORD)0x0004) -#define PHY_EEE_CAPABILITIES_100BT_EEE_ ((WORD)0x0002) - -#define PHY_MMD_DEV_7 7 - -#define PHY_EEE_ADVERTISEMENT (0x3C) -#define PHY_EEE_ADVERTISEMENT_1000BT_EEE_ ((WORD)0x0004) -#define PHY_EEE_ADVERTISEMENT_100BT_EEE_ ((WORD)0x0002) - -#define PHY_EEE_LP_ADVERTISEMENT (0x3D) -#define PHY_EEE_1000BT_EEE_CAPABLE_ ((WORD)0x0004) -#define PHY_EEE_100BT_EEE_CAPABLE_ ((WORD)0x0002) #endif /* _LAN78XX_H */ -- cgit v1.2.3 From 758c5c1174343a134031ff817c19c732b3729747 Mon Sep 17 00:00:00 2001 From: "Woojung.Huh@microchip.com" Date: Wed, 16 Sep 2015 23:41:14 +0000 Subject: lan78xx: Create lan78xx_get_mdix_status() and lan78xx_set_mdix_status() for MDIX control. Create lan78xx_get_mdix_status() and lan78xx_set_mdix_status() for MDIX control. Signed-off-by: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 90 +++++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 38 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 6bb2923396de..dce55636bc9b 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1175,6 +1175,55 @@ static void lan78xx_set_msglevel(struct net_device *net, u32 level) dev->msg_enable = level; } +static int lan78xx_get_mdix_status(struct net_device *net) +{ + struct phy_device *phydev = net->phydev; + int buf; + + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_1); + buf = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_0); + + return buf; +} + +static void lan78xx_set_mdix_status(struct net_device *net, __u8 mdix_ctrl) +{ + struct lan78xx_net *dev = netdev_priv(net); + struct phy_device *phydev = net->phydev; + int buf; + + if (mdix_ctrl == ETH_TP_MDI) { + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, + LAN88XX_EXT_PAGE_SPACE_1); + buf = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); + buf &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; + phy_write(phydev, LAN88XX_EXT_MODE_CTRL, + buf | LAN88XX_EXT_MODE_CTRL_MDI_); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, + LAN88XX_EXT_PAGE_SPACE_0); + } else if (mdix_ctrl == ETH_TP_MDI_X) { + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, + LAN88XX_EXT_PAGE_SPACE_1); + buf = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); + buf &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; + phy_write(phydev, LAN88XX_EXT_MODE_CTRL, + buf | LAN88XX_EXT_MODE_CTRL_MDI_X_); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, + LAN88XX_EXT_PAGE_SPACE_0); + } else if (mdix_ctrl == ETH_TP_MDI_AUTO) { + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, + LAN88XX_EXT_PAGE_SPACE_1); + buf = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); + buf &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; + phy_write(phydev, LAN88XX_EXT_MODE_CTRL, + buf | LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_); + phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, + LAN88XX_EXT_PAGE_SPACE_0); + } + dev->mdix_ctrl = mdix_ctrl; +} + static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd) { struct lan78xx_net *dev = netdev_priv(net); @@ -1188,9 +1237,7 @@ static int lan78xx_get_settings(struct net_device *net, struct ethtool_cmd *cmd) ret = phy_ethtool_gset(phydev, cmd); - phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_1); - buf = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); - phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_0); + buf = lan78xx_get_mdix_status(net); buf &= LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; if (buf == LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_) { @@ -1221,34 +1268,7 @@ static int lan78xx_set_settings(struct net_device *net, struct ethtool_cmd *cmd) return ret; if (dev->mdix_ctrl != cmd->eth_tp_mdix_ctrl) { - if (cmd->eth_tp_mdix_ctrl == ETH_TP_MDI) { - phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, - LAN88XX_EXT_PAGE_SPACE_1); - temp = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); - temp &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; - phy_write(phydev, LAN88XX_EXT_MODE_CTRL, - temp | LAN88XX_EXT_MODE_CTRL_MDI_); - phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, - LAN88XX_EXT_PAGE_SPACE_0); - } else if (cmd->eth_tp_mdix_ctrl == ETH_TP_MDI_X) { - phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, - LAN88XX_EXT_PAGE_SPACE_1); - temp = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); - temp &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; - phy_write(phydev, LAN88XX_EXT_MODE_CTRL, - temp | LAN88XX_EXT_MODE_CTRL_MDI_X_); - phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, - LAN88XX_EXT_PAGE_SPACE_0); - } else if (cmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) { - phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, - LAN88XX_EXT_PAGE_SPACE_1); - temp = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); - temp &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; - phy_write(phydev, LAN88XX_EXT_MODE_CTRL, - temp | LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_); - phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, - LAN88XX_EXT_PAGE_SPACE_0); - } + lan78xx_set_mdix_status(net, cmd->eth_tp_mdix_ctrl); } /* change speed & duplex */ @@ -1504,13 +1524,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) } /* set to AUTOMDIX */ - phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_1); - ret = phy_read(phydev, LAN88XX_EXT_MODE_CTRL); - ret &= ~LAN88XX_EXT_MODE_CTRL_MDIX_MASK_; - phy_write(phydev, LAN88XX_EXT_MODE_CTRL, - ret | LAN88XX_EXT_MODE_CTRL_AUTO_MDIX_); - phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_0); - dev->mdix_ctrl = ETH_TP_MDI_AUTO; + lan78xx_set_mdix_status(dev->net, ETH_TP_MDI_AUTO); /* MAC doesn't support 1000T Half */ phydev->supported &= ~SUPPORTED_1000baseT_Half; -- cgit v1.2.3 From 9110fe4a17743e5f416f7fbe01a2a83cffd807d6 Mon Sep 17 00:00:00 2001 From: "Woojung.Huh@microchip.com" Date: Wed, 16 Sep 2015 23:41:19 +0000 Subject: lan78xx: Remove not defined MAC_CR_GMII_EN_ bit from MAC_CR. Remove not defined MAC_CR_GMII_EN_ bit from MAC_CR. Signed-off-by: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 3 --- drivers/net/usb/lan78xx.h | 1 - 2 files changed, 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index dce55636bc9b..6a70a72b565d 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1909,10 +1909,7 @@ static int lan78xx_reset(struct lan78xx_net *dev) } while ((buf & PMT_CTL_PHY_RST_) || !(buf & PMT_CTL_READY_)); ret = lan78xx_read_reg(dev, MAC_CR, &buf); - - buf |= MAC_CR_GMII_EN_; buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_; - ret = lan78xx_write_reg(dev, MAC_CR, buf); /* enable PHY interrupts */ diff --git a/drivers/net/usb/lan78xx.h b/drivers/net/usb/lan78xx.h index e0a5a8f529c1..a93fb653e7c5 100644 --- a/drivers/net/usb/lan78xx.h +++ b/drivers/net/usb/lan78xx.h @@ -549,7 +549,6 @@ #define LTM_INACTIVE1_TIMER10_ (0x0000FFFF) #define MAC_CR (0x100) -#define MAC_CR_GMII_EN_ (0x00080000) #define MAC_CR_EEE_TX_CLK_STOP_EN_ (0x00040000) #define MAC_CR_EEE_EN_ (0x00020000) #define MAC_CR_EEE_TLAR_EN_ (0x00010000) -- cgit v1.2.3 From 2f9130709d2c19e2eef336bda0fb0c807cbc1f64 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 16 Sep 2015 16:47:39 -0700 Subject: net: bcmgenet: Implement TX coalescing control knobs Configuring the ethtool tx-frames property, which translates into N packets before a TX interrupt is the simplest configuration scheme because it requires no locking neither at the softare nor hardware level, and is completely indepedent from the link speed. Since ethtool does not allow per-tx queue coalescing parameters, we apply the same setting to any transmit queue. We can no longer enable the BDONE/PDONE interrupts as those would fire for each packet/buffer received, which would defeat the MBDONE interrupt purpose. The MBDONE interrupt is guaranteed to correspond to a PDONE/BDONE interrupt when the threshold is set to 1, but offers interrupt coalescing when the value is > 1. Since the HW is configured to generate an interrupt when the ring becomes emtpy, we have to deny any timeout/timer settings coming from user-space to indicate we can only generate an interrupt very packets. While we are at it, fix the DMA_INTR_THRESHOLD_MASK value which was off by one bit (0xff vs. 0x1ff). Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 47 ++++++++++++++++++++++++++ drivers/net/ethernet/broadcom/genet/bcmgenet.h | 6 ++-- 2 files changed, 50 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index fadbd0088d3e..5e247c7b379e 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -498,6 +498,51 @@ static void bcmgenet_set_msglevel(struct net_device *dev, u32 level) priv->msg_enable = level; } +static int bcmgenet_get_coalesce(struct net_device *dev, + struct ethtool_coalesce *ec) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + + ec->tx_max_coalesced_frames = + bcmgenet_tdma_ring_readl(priv, DESC_INDEX, + DMA_MBUF_DONE_THRESH); + + return 0; +} + +static int bcmgenet_set_coalesce(struct net_device *dev, + struct ethtool_coalesce *ec) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + unsigned int i; + + if (ec->tx_max_coalesced_frames > DMA_INTR_THRESHOLD_MASK || + ec->tx_max_coalesced_frames == 0) + return -EINVAL; + + /* GENET TDMA hardware does not support a configurable timeout, but will + * always generate an interrupt either after MBDONE packets have been + * transmitted, or when the ring is emtpy. + */ + if (ec->tx_coalesce_usecs || ec->tx_coalesce_usecs_high || + ec->tx_coalesce_usecs_irq || ec->tx_coalesce_usecs_high || + ec->tx_coalesce_usecs_low) + return -EOPNOTSUPP; + + /* Program all TX queues with the same values, as there is no + * ethtool knob to do coalescing on a per-queue basis + */ + for (i = 0; i < priv->hw_params->tx_queues; i++) + bcmgenet_tdma_ring_writel(priv, i, + ec->tx_max_coalesced_frames, + DMA_MBUF_DONE_THRESH); + bcmgenet_tdma_ring_writel(priv, DESC_INDEX, + ec->tx_max_coalesced_frames, + DMA_MBUF_DONE_THRESH); + + return 0; +} + /* standard ethtool support functions. */ enum bcmgenet_stat_type { BCMGENET_STAT_NETDEV = -1, @@ -844,6 +889,8 @@ static struct ethtool_ops bcmgenet_ethtool_ops = { .get_eee = bcmgenet_get_eee, .set_eee = bcmgenet_set_eee, .nway_reset = bcmgenet_nway_reset, + .get_coalesce = bcmgenet_get_coalesce, + .set_coalesce = bcmgenet_set_coalesce, }; /* Power down the unimac, based on mode. */ diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 7299d1075422..ef7829524d46 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -309,8 +309,8 @@ struct bcmgenet_mib_counters { #define UMAC_IRQ_TXDMA_MBDONE (1 << 16) #define UMAC_IRQ_TXDMA_PDONE (1 << 17) #define UMAC_IRQ_TXDMA_BDONE (1 << 18) -#define UMAC_IRQ_TXDMA_DONE (UMAC_IRQ_TXDMA_PDONE | \ - UMAC_IRQ_TXDMA_BDONE) +#define UMAC_IRQ_TXDMA_DONE UMAC_IRQ_TXDMA_MBDONE + /* Only valid for GENETv3+ */ #define UMAC_IRQ_MDIO_DONE (1 << 23) #define UMAC_IRQ_MDIO_ERROR (1 << 24) @@ -386,7 +386,7 @@ struct bcmgenet_mib_counters { #define DMA_RING_BUFFER_SIZE_MASK 0xFFFF /* DMA interrupt threshold register */ -#define DMA_INTR_THRESHOLD_MASK 0x00FF +#define DMA_INTR_THRESHOLD_MASK 0x01FF /* DMA XON/XOFF register */ #define DMA_XON_THREHOLD_MASK 0xFFFF -- cgit v1.2.3 From 4a29645bfe6c20f06f041109ca578a0b4156f29a Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 16 Sep 2015 16:47:40 -0700 Subject: net: bcmgenet: Implement RX coalescing control knobs Add support for the ethtool rx-frames coalescing parameter which allows defining the number of RX interrupts per frames received. The RDMA engine supports a configurable timeout with a resolution of approximately 8.192 us. We can no longer enable the BDONE/PDONE interrupts as those would fire for each packet/buffer received, which would defeat the MBDONE interrupt purpose. The MBDONE interrupt is guaranteed to correspond to a PDONE/BDONE interrupt when the threshold is set to 1. Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 105 ++++++++++++++++++++++++- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 3 +- 2 files changed, 105 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 5e247c7b379e..1e72722abbf1 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -205,6 +205,23 @@ enum dma_reg { DMA_INDEX2RING_5, DMA_INDEX2RING_6, DMA_INDEX2RING_7, + DMA_RING0_TIMEOUT, + DMA_RING1_TIMEOUT, + DMA_RING2_TIMEOUT, + DMA_RING3_TIMEOUT, + DMA_RING4_TIMEOUT, + DMA_RING5_TIMEOUT, + DMA_RING6_TIMEOUT, + DMA_RING7_TIMEOUT, + DMA_RING8_TIMEOUT, + DMA_RING9_TIMEOUT, + DMA_RING10_TIMEOUT, + DMA_RING11_TIMEOUT, + DMA_RING12_TIMEOUT, + DMA_RING13_TIMEOUT, + DMA_RING14_TIMEOUT, + DMA_RING15_TIMEOUT, + DMA_RING16_TIMEOUT, }; static const u8 bcmgenet_dma_regs_v3plus[] = { @@ -216,6 +233,23 @@ static const u8 bcmgenet_dma_regs_v3plus[] = { [DMA_PRIORITY_0] = 0x30, [DMA_PRIORITY_1] = 0x34, [DMA_PRIORITY_2] = 0x38, + [DMA_RING0_TIMEOUT] = 0x2C, + [DMA_RING1_TIMEOUT] = 0x30, + [DMA_RING2_TIMEOUT] = 0x34, + [DMA_RING3_TIMEOUT] = 0x38, + [DMA_RING4_TIMEOUT] = 0x3c, + [DMA_RING5_TIMEOUT] = 0x40, + [DMA_RING6_TIMEOUT] = 0x44, + [DMA_RING7_TIMEOUT] = 0x48, + [DMA_RING8_TIMEOUT] = 0x4c, + [DMA_RING9_TIMEOUT] = 0x50, + [DMA_RING10_TIMEOUT] = 0x54, + [DMA_RING11_TIMEOUT] = 0x58, + [DMA_RING12_TIMEOUT] = 0x5c, + [DMA_RING13_TIMEOUT] = 0x60, + [DMA_RING14_TIMEOUT] = 0x64, + [DMA_RING15_TIMEOUT] = 0x68, + [DMA_RING16_TIMEOUT] = 0x6C, [DMA_INDEX2RING_0] = 0x70, [DMA_INDEX2RING_1] = 0x74, [DMA_INDEX2RING_2] = 0x78, @@ -235,6 +269,23 @@ static const u8 bcmgenet_dma_regs_v2[] = { [DMA_PRIORITY_0] = 0x34, [DMA_PRIORITY_1] = 0x38, [DMA_PRIORITY_2] = 0x3C, + [DMA_RING0_TIMEOUT] = 0x2C, + [DMA_RING1_TIMEOUT] = 0x30, + [DMA_RING2_TIMEOUT] = 0x34, + [DMA_RING3_TIMEOUT] = 0x38, + [DMA_RING4_TIMEOUT] = 0x3c, + [DMA_RING5_TIMEOUT] = 0x40, + [DMA_RING6_TIMEOUT] = 0x44, + [DMA_RING7_TIMEOUT] = 0x48, + [DMA_RING8_TIMEOUT] = 0x4c, + [DMA_RING9_TIMEOUT] = 0x50, + [DMA_RING10_TIMEOUT] = 0x54, + [DMA_RING11_TIMEOUT] = 0x58, + [DMA_RING12_TIMEOUT] = 0x5c, + [DMA_RING13_TIMEOUT] = 0x60, + [DMA_RING14_TIMEOUT] = 0x64, + [DMA_RING15_TIMEOUT] = 0x68, + [DMA_RING16_TIMEOUT] = 0x6C, }; static const u8 bcmgenet_dma_regs_v1[] = { @@ -245,6 +296,23 @@ static const u8 bcmgenet_dma_regs_v1[] = { [DMA_PRIORITY_0] = 0x34, [DMA_PRIORITY_1] = 0x38, [DMA_PRIORITY_2] = 0x3C, + [DMA_RING0_TIMEOUT] = 0x2C, + [DMA_RING1_TIMEOUT] = 0x30, + [DMA_RING2_TIMEOUT] = 0x34, + [DMA_RING3_TIMEOUT] = 0x38, + [DMA_RING4_TIMEOUT] = 0x3c, + [DMA_RING5_TIMEOUT] = 0x40, + [DMA_RING6_TIMEOUT] = 0x44, + [DMA_RING7_TIMEOUT] = 0x48, + [DMA_RING8_TIMEOUT] = 0x4c, + [DMA_RING9_TIMEOUT] = 0x50, + [DMA_RING10_TIMEOUT] = 0x54, + [DMA_RING11_TIMEOUT] = 0x58, + [DMA_RING12_TIMEOUT] = 0x5c, + [DMA_RING13_TIMEOUT] = 0x60, + [DMA_RING14_TIMEOUT] = 0x64, + [DMA_RING15_TIMEOUT] = 0x68, + [DMA_RING16_TIMEOUT] = 0x6C, }; /* Set at runtime once bcmgenet version is known */ @@ -506,6 +574,11 @@ static int bcmgenet_get_coalesce(struct net_device *dev, ec->tx_max_coalesced_frames = bcmgenet_tdma_ring_readl(priv, DESC_INDEX, DMA_MBUF_DONE_THRESH); + ec->rx_max_coalesced_frames = + bcmgenet_rdma_ring_readl(priv, DESC_INDEX, + DMA_MBUF_DONE_THRESH); + ec->rx_coalesce_usecs = + bcmgenet_rdma_readl(priv, DMA_RING16_TIMEOUT) * 8192 / 1000; return 0; } @@ -515,9 +588,19 @@ static int bcmgenet_set_coalesce(struct net_device *dev, { struct bcmgenet_priv *priv = netdev_priv(dev); unsigned int i; + u32 reg; + /* Base system clock is 125Mhz, DMA timeout is this reference clock + * divided by 1024, which yields roughly 8.192us, our maximum value + * has to fit in the DMA_TIMEOUT_MASK (16 bits) + */ if (ec->tx_max_coalesced_frames > DMA_INTR_THRESHOLD_MASK || - ec->tx_max_coalesced_frames == 0) + ec->tx_max_coalesced_frames == 0 || + ec->rx_max_coalesced_frames > DMA_INTR_THRESHOLD_MASK || + ec->rx_coalesce_usecs > (DMA_TIMEOUT_MASK * 8) + 1) + return -EINVAL; + + if (ec->rx_coalesce_usecs == 0 && ec->rx_max_coalesced_frames == 0) return -EINVAL; /* GENET TDMA hardware does not support a configurable timeout, but will @@ -540,6 +623,26 @@ static int bcmgenet_set_coalesce(struct net_device *dev, ec->tx_max_coalesced_frames, DMA_MBUF_DONE_THRESH); + for (i = 0; i < priv->hw_params->rx_queues; i++) { + bcmgenet_rdma_ring_writel(priv, i, + ec->rx_max_coalesced_frames, + DMA_MBUF_DONE_THRESH); + + reg = bcmgenet_rdma_readl(priv, DMA_RING0_TIMEOUT + i); + reg &= ~DMA_TIMEOUT_MASK; + reg |= DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000, 8192); + bcmgenet_rdma_writel(priv, reg, DMA_RING0_TIMEOUT + i); + } + + bcmgenet_rdma_ring_writel(priv, DESC_INDEX, + ec->rx_max_coalesced_frames, + DMA_MBUF_DONE_THRESH); + + reg = bcmgenet_rdma_readl(priv, DMA_RING16_TIMEOUT); + reg &= ~DMA_TIMEOUT_MASK; + reg |= DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000, 8192); + bcmgenet_rdma_writel(priv, reg, DMA_RING16_TIMEOUT); + return 0; } diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index ef7829524d46..29dc2f1bbb19 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -304,8 +304,7 @@ struct bcmgenet_mib_counters { #define UMAC_IRQ_RXDMA_MBDONE (1 << 13) #define UMAC_IRQ_RXDMA_PDONE (1 << 14) #define UMAC_IRQ_RXDMA_BDONE (1 << 15) -#define UMAC_IRQ_RXDMA_DONE (UMAC_IRQ_RXDMA_PDONE | \ - UMAC_IRQ_RXDMA_BDONE) +#define UMAC_IRQ_RXDMA_DONE UMAC_IRQ_RXDMA_MBDONE #define UMAC_IRQ_TXDMA_MBDONE (1 << 16) #define UMAC_IRQ_TXDMA_PDONE (1 << 17) #define UMAC_IRQ_TXDMA_BDONE (1 << 18) -- cgit v1.2.3 From e904cf6fe23022cde4e0ea9d41601411a315a3dc Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Sun, 6 Sep 2015 13:09:01 +0200 Subject: ath9k_htc: introduce support for different fw versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current kernel support only one fw name with theoretically only one fw version located in “firmware/htc_[9271|7010].fw”. Which is ok so far we have only one fw version (1.3). After we realised new fw 1.4, we faced compatibility problem which was decided to solve by firmware name and location: - new firmware is located now in firmware/ath9k_htc/htc_[9271|7010]-1.4.0.fw - old version 1.3 should be on old place, so old kernel have no issues with it. - new kernels including this patch should be able to try different supported (min..max) fw version. - new kernel should be able to support old fw location too. At least for now. At same time this patch will add new module option which should allow user to play with development fw version without replacing stable one. If user will set “ath9k_htc use_dev_fw=1” module will try to find firmware/ath9k_htc/htc_[9271|7010]-1.dev.0.fw first and if it fails, use stable version: for example...1.4.0.fw. Signed-off-by: Oleksij Rempel Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/hif_usb.c | 106 ++++++++++++++++++++------ drivers/net/wireless/ath/ath9k/hif_usb.h | 21 ++++- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 4 + 3 files changed, 105 insertions(+), 26 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 10c02f5cbc5e..165dd202c365 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -17,12 +17,8 @@ #include #include "htc.h" -/* identify firmware images */ -#define FIRMWARE_AR7010_1_1 "htc_7010.fw" -#define FIRMWARE_AR9271 "htc_9271.fw" - -MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); -MODULE_FIRMWARE(FIRMWARE_AR9271); +MODULE_FIRMWARE(HTC_7010_MODULE_FW); +MODULE_FIRMWARE(HTC_9271_MODULE_FW); static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */ @@ -1080,12 +1076,88 @@ static void ath9k_hif_usb_firmware_fail(struct hif_device_usb *hif_dev) device_unlock(parent); } +static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context); + +/* taken from iwlwifi */ +static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev, + bool first) +{ + char index[8], *chip; + int ret; + + if (first) { + if (htc_use_dev_fw) { + hif_dev->fw_minor_index = FIRMWARE_MINOR_IDX_MAX + 1; + sprintf(index, "%s", "dev"); + } else { + hif_dev->fw_minor_index = FIRMWARE_MINOR_IDX_MAX; + sprintf(index, "%d", hif_dev->fw_minor_index); + } + } else { + hif_dev->fw_minor_index--; + sprintf(index, "%d", hif_dev->fw_minor_index); + } + + /* test for FW 1.3 */ + if (MAJOR_VERSION_REQ == 1 && hif_dev->fw_minor_index == 3) { + const char *filename; + + if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info)) + filename = FIRMWARE_AR7010_1_1; + else + filename = FIRMWARE_AR9271; + + /* expected fw locations: + * - htc_9271.fw (stable version 1.3, depricated) + */ + snprintf(hif_dev->fw_name, sizeof(hif_dev->fw_name), + "%s", filename); + + } else if (hif_dev->fw_minor_index < FIRMWARE_MINOR_IDX_MIN) { + dev_err(&hif_dev->udev->dev, "no suitable firmware found!\n"); + + return -ENOENT; + } else { + if (IS_AR7010_DEVICE(hif_dev->usb_device_id->driver_info)) + chip = "7010"; + else + chip = "9271"; + + /* expected fw locations: + * - ath9k_htc/htc_9271-1.dev.0.fw (development version) + * - ath9k_htc/htc_9271-1.4.0.fw (stable version) + */ + snprintf(hif_dev->fw_name, sizeof(hif_dev->fw_name), + "%s/htc_%s-%d.%s.0.fw", HTC_FW_PATH, + chip, MAJOR_VERSION_REQ, index); + } + + ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, + &hif_dev->udev->dev, GFP_KERNEL, + hif_dev, ath9k_hif_usb_firmware_cb); + if (ret) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Async request for firmware %s failed\n", + hif_dev->fw_name); + return ret; + } + + dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", + hif_dev->fw_name); + + return ret; +} + static void ath9k_hif_usb_firmware_cb(const struct firmware *fw, void *context) { struct hif_device_usb *hif_dev = context; int ret; if (!fw) { + ret = ath9k_hif_request_firmware(hif_dev, false); + if (!ret) + return; + dev_err(&hif_dev->udev->dev, "ath9k_htc: Failed to get firmware %s\n", hif_dev->fw_name); @@ -1215,27 +1287,11 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, init_completion(&hif_dev->fw_done); - /* Find out which firmware to load */ - - if (IS_AR7010_DEVICE(id->driver_info)) - hif_dev->fw_name = FIRMWARE_AR7010_1_1; - else - hif_dev->fw_name = FIRMWARE_AR9271; - - ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, - &hif_dev->udev->dev, GFP_KERNEL, - hif_dev, ath9k_hif_usb_firmware_cb); - if (ret) { - dev_err(&hif_dev->udev->dev, - "ath9k_htc: Async request for firmware %s failed\n", - hif_dev->fw_name); + ret = ath9k_hif_request_firmware(hif_dev, true); + if (ret) goto err_fw_req; - } - dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", - hif_dev->fw_name); - - return 0; + return ret; err_fw_req: usb_set_intfdata(interface, NULL); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 51496e74b83e..7c2ef7ecd98b 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -17,8 +17,26 @@ #ifndef HTC_USB_H #define HTC_USB_H +/* old firmware images */ +#define FIRMWARE_AR7010_1_1 "htc_7010.fw" +#define FIRMWARE_AR9271 "htc_9271.fw" + +/* supported Major FW version */ #define MAJOR_VERSION_REQ 1 #define MINOR_VERSION_REQ 3 +/* minimal and maximal supported Minor FW version. */ +#define FIRMWARE_MINOR_IDX_MAX 4 +#define FIRMWARE_MINOR_IDX_MIN 3 +#define HTC_FW_PATH "ath9k_htc" + +#define HTC_9271_MODULE_FW HTC_FW_PATH "/htc_9271-" \ + __stringify(MAJOR_VERSION_REQ) \ + "." __stringify(FIRMWARE_MINOR_IDX_MAX) ".0.fw" +#define HTC_7010_MODULE_FW HTC_FW_PATH "/htc_7010-" \ + __stringify(MAJOR_VERSION_REQ) \ + "." __stringify(FIRMWARE_MINOR_IDX_MAX) ".0.fw" + +extern int htc_use_dev_fw; #define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB)) @@ -101,7 +119,8 @@ struct hif_device_usb { struct usb_anchor reg_in_submitted; struct usb_anchor mgmt_submitted; struct sk_buff *remain_skb; - const char *fw_name; + char fw_name[32]; + int fw_minor_index; int rx_remain_len; int rx_pkt_len; int rx_transfer_len; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 1e84882f8c5b..efe77db96570 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -38,6 +38,10 @@ static int ath9k_ps_enable; module_param_named(ps_enable, ath9k_ps_enable, int, 0444); MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); +int htc_use_dev_fw = 0; +module_param_named(use_dev_fw, htc_use_dev_fw, int, 0444); +MODULE_PARM_DESC(use_dev_fw, "Use development FW version"); + #ifdef CONFIG_MAC80211_LEDS int ath9k_htc_led_blink = 1; module_param_named(blink, ath9k_htc_led_blink, int, 0444); -- cgit v1.2.3 From 812494d9a0cacf77e0a538be18183c7b471812aa Mon Sep 17 00:00:00 2001 From: chas williams <3chas3@gmail.com> Date: Wed, 16 Sep 2015 16:28:25 -0400 Subject: xen-netfront: always set num queues if possible If netfront connects with two (or more) queues and then reconnects with only one queue it fails to delete or rewrite the multi-queue-num-queues key and netback will try to use the wrong number of queues. Always write the num-queues field if the backend has multi-queue support. Signed-off-by: Chas Williams <3chas3@gmail.com> Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index f821a97d7827..9bf63c27a9b7 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1819,19 +1819,22 @@ again: goto destroy_ring; } - if (num_queues == 1) { - err = write_queue_xenstore_keys(&info->queues[0], &xbt, 0); /* flat */ - if (err) - goto abort_transaction_no_dev_fatal; - } else { + if (xenbus_exists(XBT_NIL, + info->xbdev->otherend, "multi-queue-max-queues")) { /* Write the number of queues */ - err = xenbus_printf(xbt, dev->nodename, "multi-queue-num-queues", - "%u", num_queues); + err = xenbus_printf(xbt, dev->nodename, + "multi-queue-num-queues", "%u", num_queues); if (err) { message = "writing multi-queue-num-queues"; goto abort_transaction_no_dev_fatal; } + } + if (num_queues == 1) { + err = write_queue_xenstore_keys(&info->queues[0], &xbt, 0); /* flat */ + if (err) + goto abort_transaction_no_dev_fatal; + } else { /* Write the keys for each queue */ for (i = 0; i < num_queues; ++i) { queue = &info->queues[i]; -- cgit v1.2.3 From 5b904d39406a61c056c3fe1b45867f0161827ef1 Mon Sep 17 00:00:00 2001 From: huangdaode Date: Thu, 17 Sep 2015 14:51:47 +0800 Subject: net: add Hisilicon Network Subsystem MDIO support The MDIO support for Hisilicon Network Subsystem. It is used in Hislicon hip04, hip05 and Hi1610 SoC to control the external PHY Signed-off-by: huangdaode Signed-off-by: Yisen Zhuang Signed-off-by: Kenneth Lee Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/Kconfig | 10 +- drivers/net/ethernet/hisilicon/Makefile | 3 +- drivers/net/ethernet/hisilicon/hip04_mdio.c | 185 ---------- drivers/net/ethernet/hisilicon/hns_mdio.c | 520 ++++++++++++++++++++++++++++ 4 files changed, 531 insertions(+), 187 deletions(-) delete mode 100644 drivers/net/ethernet/hisilicon/hip04_mdio.c create mode 100644 drivers/net/ethernet/hisilicon/hns_mdio.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig index dead17b5d769..9184f1d0f92b 100644 --- a/drivers/net/ethernet/hisilicon/Kconfig +++ b/drivers/net/ethernet/hisilicon/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_HISILICON bool "Hisilicon devices" default y - depends on ARM + depends on ARM || ARM64 ---help--- If you have a network (Ethernet) card belonging to this class, say Y. @@ -27,8 +27,16 @@ config HIP04_ETH select PHYLIB select MARVELL_PHY select MFD_SYSCON + select HNS_MDIO ---help--- If you wish to compile a kernel for a hardware with hisilicon p04 SoC and want to use the internal ethernet then you should answer Y to this. +config HNS_MDIO + tristate "Hisilicon HNS MDIO device Support" + select MDIO + ---help--- + This selects the HNS MDIO support. It is needed by HNS_DSAF to access + the PHY + endif # NET_VENDOR_HISILICON diff --git a/drivers/net/ethernet/hisilicon/Makefile b/drivers/net/ethernet/hisilicon/Makefile index 6c14540a4dc5..04b4b2177ff4 100644 --- a/drivers/net/ethernet/hisilicon/Makefile +++ b/drivers/net/ethernet/hisilicon/Makefile @@ -3,4 +3,5 @@ # obj-$(CONFIG_HIX5HD2_GMAC) += hix5hd2_gmac.o -obj-$(CONFIG_HIP04_ETH) += hip04_mdio.o hip04_eth.o +obj-$(CONFIG_HIP04_ETH) += hip04_eth.o +obj-$(CONFIG_HNS_MDIO) += hns_mdio.o diff --git a/drivers/net/ethernet/hisilicon/hip04_mdio.c b/drivers/net/ethernet/hisilicon/hip04_mdio.c deleted file mode 100644 index fca0a5be1f0f..000000000000 --- a/drivers/net/ethernet/hisilicon/hip04_mdio.c +++ /dev/null @@ -1,185 +0,0 @@ -/* Copyright (c) 2014 Linaro Ltd. - * Copyright (c) 2014 Hisilicon Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include - -#define MDIO_CMD_REG 0x0 -#define MDIO_ADDR_REG 0x4 -#define MDIO_WDATA_REG 0x8 -#define MDIO_RDATA_REG 0xc -#define MDIO_STA_REG 0x10 - -#define MDIO_START BIT(14) -#define MDIO_R_VALID BIT(1) -#define MDIO_READ (BIT(12) | BIT(11) | MDIO_START) -#define MDIO_WRITE (BIT(12) | BIT(10) | MDIO_START) - -struct hip04_mdio_priv { - void __iomem *base; -}; - -#define WAIT_TIMEOUT 10 -static int hip04_mdio_wait_ready(struct mii_bus *bus) -{ - struct hip04_mdio_priv *priv = bus->priv; - int i; - - for (i = 0; readl_relaxed(priv->base + MDIO_CMD_REG) & MDIO_START; i++) { - if (i == WAIT_TIMEOUT) - return -ETIMEDOUT; - msleep(20); - } - - return 0; -} - -static int hip04_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -{ - struct hip04_mdio_priv *priv = bus->priv; - u32 val; - int ret; - - ret = hip04_mdio_wait_ready(bus); - if (ret < 0) - goto out; - - val = regnum | (mii_id << 5) | MDIO_READ; - writel_relaxed(val, priv->base + MDIO_CMD_REG); - - ret = hip04_mdio_wait_ready(bus); - if (ret < 0) - goto out; - - val = readl_relaxed(priv->base + MDIO_STA_REG); - if (val & MDIO_R_VALID) { - dev_err(bus->parent, "SMI bus read not valid\n"); - ret = -ENODEV; - goto out; - } - - val = readl_relaxed(priv->base + MDIO_RDATA_REG); - ret = val & 0xFFFF; -out: - return ret; -} - -static int hip04_mdio_write(struct mii_bus *bus, int mii_id, - int regnum, u16 value) -{ - struct hip04_mdio_priv *priv = bus->priv; - u32 val; - int ret; - - ret = hip04_mdio_wait_ready(bus); - if (ret < 0) - goto out; - - writel_relaxed(value, priv->base + MDIO_WDATA_REG); - val = regnum | (mii_id << 5) | MDIO_WRITE; - writel_relaxed(val, priv->base + MDIO_CMD_REG); -out: - return ret; -} - -static int hip04_mdio_reset(struct mii_bus *bus) -{ - int temp, i; - - for (i = 0; i < PHY_MAX_ADDR; i++) { - hip04_mdio_write(bus, i, 22, 0); - temp = hip04_mdio_read(bus, i, MII_BMCR); - if (temp < 0) - continue; - - temp |= BMCR_RESET; - if (hip04_mdio_write(bus, i, MII_BMCR, temp) < 0) - continue; - } - - mdelay(500); - return 0; -} - -static int hip04_mdio_probe(struct platform_device *pdev) -{ - struct resource *r; - struct mii_bus *bus; - struct hip04_mdio_priv *priv; - int ret; - - bus = mdiobus_alloc_size(sizeof(struct hip04_mdio_priv)); - if (!bus) { - dev_err(&pdev->dev, "Cannot allocate MDIO bus\n"); - return -ENOMEM; - } - - bus->name = "hip04_mdio_bus"; - bus->read = hip04_mdio_read; - bus->write = hip04_mdio_write; - bus->reset = hip04_mdio_reset; - snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev)); - bus->parent = &pdev->dev; - priv = bus->priv; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, r); - if (IS_ERR(priv->base)) { - ret = PTR_ERR(priv->base); - goto out_mdio; - } - - ret = of_mdiobus_register(bus, pdev->dev.of_node); - if (ret < 0) { - dev_err(&pdev->dev, "Cannot register MDIO bus (%d)\n", ret); - goto out_mdio; - } - - platform_set_drvdata(pdev, bus); - - return 0; - -out_mdio: - mdiobus_free(bus); - return ret; -} - -static int hip04_mdio_remove(struct platform_device *pdev) -{ - struct mii_bus *bus = platform_get_drvdata(pdev); - - mdiobus_unregister(bus); - mdiobus_free(bus); - - return 0; -} - -static const struct of_device_id hip04_mdio_match[] = { - { .compatible = "hisilicon,hip04-mdio" }, - { } -}; -MODULE_DEVICE_TABLE(of, hip04_mdio_match); - -static struct platform_driver hip04_mdio_driver = { - .probe = hip04_mdio_probe, - .remove = hip04_mdio_remove, - .driver = { - .name = "hip04-mdio", - .of_match_table = hip04_mdio_match, - }, -}; - -module_platform_driver(hip04_mdio_driver); - -MODULE_DESCRIPTION("HISILICON P04 MDIO interface driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:hip04-mdio"); diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c new file mode 100644 index 000000000000..e4ec52ae61ff --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -0,0 +1,520 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MDIO_DRV_NAME "Hi-HNS_MDIO" +#define MDIO_BUS_NAME "Hisilicon MII Bus" +#define MDIO_DRV_VERSION "1.3.0" +#define MDIO_COPYRIGHT "Copyright(c) 2015 Huawei Corporation." +#define MDIO_DRV_STRING MDIO_BUS_NAME +#define MDIO_DEFAULT_DEVICE_DESCR MDIO_BUS_NAME + +#define MDIO_CTL_DEV_ADDR(x) (x & 0x1f) +#define MDIO_CTL_PORT_ADDR(x) ((x & 0x1f) << 5) + +#define MDIO_TIMEOUT 1000000 + +struct hns_mdio_device { + void *vbase; /* mdio reg base address */ + void *sys_vbase; +}; + +/* mdio reg */ +#define MDIO_COMMAND_REG 0x0 +#define MDIO_ADDR_REG 0x4 +#define MDIO_WDATA_REG 0x8 +#define MDIO_RDATA_REG 0xc +#define MDIO_STA_REG 0x10 + +/* cfg phy bit map */ +#define MDIO_CMD_DEVAD_M 0x1f +#define MDIO_CMD_DEVAD_S 0 +#define MDIO_CMD_PRTAD_M 0x1f +#define MDIO_CMD_PRTAD_S 5 +#define MDIO_CMD_OP_M 0x3 +#define MDIO_CMD_OP_S 10 +#define MDIO_CMD_ST_M 0x3 +#define MDIO_CMD_ST_S 12 +#define MDIO_CMD_START_B 14 + +#define MDIO_ADDR_DATA_M 0xffff +#define MDIO_ADDR_DATA_S 0 + +#define MDIO_WDATA_DATA_M 0xffff +#define MDIO_WDATA_DATA_S 0 + +#define MDIO_RDATA_DATA_M 0xffff +#define MDIO_RDATA_DATA_S 0 + +#define MDIO_STATE_STA_B 0 + +enum mdio_st_clause { + MDIO_ST_CLAUSE_45 = 0, + MDIO_ST_CLAUSE_22 +}; + +enum mdio_c22_op_seq { + MDIO_C22_WRITE = 1, + MDIO_C22_READ = 2 +}; + +enum mdio_c45_op_seq { + MDIO_C45_WRITE_ADDR = 0, + MDIO_C45_WRITE_DATA, + MDIO_C45_READ_INCREMENT, + MDIO_C45_READ +}; + +/* peri subctrl reg */ +#define MDIO_SC_CLK_EN 0x338 +#define MDIO_SC_CLK_DIS 0x33C +#define MDIO_SC_RESET_REQ 0xA38 +#define MDIO_SC_RESET_DREQ 0xA3C +#define MDIO_SC_CTRL 0x2010 +#define MDIO_SC_CLK_ST 0x531C +#define MDIO_SC_RESET_ST 0x5A1C + +static void mdio_write_reg(void *base, u32 reg, u32 value) +{ + u8 __iomem *reg_addr = (u8 __iomem *)base; + + writel_relaxed(value, reg_addr + reg); +} + +#define MDIO_WRITE_REG(a, reg, value) \ + mdio_write_reg((a)->vbase, (reg), (value)) + +static u32 mdio_read_reg(void *base, u32 reg) +{ + u8 __iomem *reg_addr = (u8 __iomem *)base; + + return readl_relaxed(reg_addr + reg); +} + +#define mdio_set_field(origin, mask, shift, val) \ + do { \ + (origin) &= (~((mask) << (shift))); \ + (origin) |= (((val) & (mask)) << (shift)); \ + } while (0) + +#define mdio_get_field(origin, mask, shift) (((origin) >> (shift)) & (mask)) + +static void mdio_set_reg_field(void *base, u32 reg, u32 mask, u32 shift, + u32 val) +{ + u32 origin = mdio_read_reg(base, reg); + + mdio_set_field(origin, mask, shift, val); + mdio_write_reg(base, reg, origin); +} + +#define MDIO_SET_REG_FIELD(dev, reg, mask, shift, val) \ + mdio_set_reg_field((dev)->vbase, (reg), (mask), (shift), (val)) + +static u32 mdio_get_reg_field(void *base, u32 reg, u32 mask, u32 shift) +{ + u32 origin; + + origin = mdio_read_reg(base, reg); + return mdio_get_field(origin, mask, shift); +} + +#define MDIO_GET_REG_FIELD(dev, reg, mask, shift) \ + mdio_get_reg_field((dev)->vbase, (reg), (mask), (shift)) + +#define MDIO_GET_REG_BIT(dev, reg, bit) \ + mdio_get_reg_field((dev)->vbase, (reg), 0x1ull, (bit)) + +#define MDIO_CHECK_SET_ST 1 +#define MDIO_CHECK_CLR_ST 0 + +static int mdio_sc_cfg_reg_write(struct hns_mdio_device *mdio_dev, + u32 cfg_reg, u32 set_val, + u32 st_reg, u32 st_msk, u8 check_st) +{ + u32 time_cnt; + u32 reg_value; + + mdio_write_reg((void *)mdio_dev->sys_vbase, cfg_reg, set_val); + + for (time_cnt = MDIO_TIMEOUT; time_cnt; time_cnt--) { + reg_value = mdio_read_reg((void *)mdio_dev->sys_vbase, st_reg); + reg_value &= st_msk; + if ((!!check_st) == (!!reg_value)) + break; + } + + if ((!!check_st) != (!!reg_value)) + return -EBUSY; + + return 0; +} + +static int hns_mdio_wait_ready(struct mii_bus *bus) +{ + struct hns_mdio_device *mdio_dev = bus->priv; + int i; + u32 cmd_reg_value = 1; + + /* waitting for MDIO_COMMAND_REG 's mdio_start==0 */ + /* after that can do read or write*/ + for (i = 0; cmd_reg_value; i++) { + cmd_reg_value = MDIO_GET_REG_BIT(mdio_dev, + MDIO_COMMAND_REG, + MDIO_CMD_START_B); + if (i == MDIO_TIMEOUT) + return -ETIMEDOUT; + } + + return 0; +} + +static void hns_mdio_cmd_write(struct hns_mdio_device *mdio_dev, + u8 is_c45, u8 op, u8 phy_id, u16 cmd) +{ + u32 cmd_reg_value; + u8 st = is_c45 ? MDIO_ST_CLAUSE_45 : MDIO_ST_CLAUSE_22; + + cmd_reg_value = st << MDIO_CMD_ST_S; + cmd_reg_value |= op << MDIO_CMD_OP_S; + cmd_reg_value |= + (phy_id & MDIO_CMD_PRTAD_M) << MDIO_CMD_PRTAD_S; + cmd_reg_value |= (cmd & MDIO_CMD_DEVAD_M) << MDIO_CMD_DEVAD_S; + cmd_reg_value |= 1 << MDIO_CMD_START_B; + + MDIO_WRITE_REG(mdio_dev, MDIO_COMMAND_REG, cmd_reg_value); +} + +/** + * hns_mdio_write - access phy register + * @bus: mdio bus + * @phy_id: phy id + * @regnum: register num + * @value: register value + * + * Return 0 on success, negative on failure + */ +static int hns_mdio_write(struct mii_bus *bus, + int phy_id, int regnum, u16 data) +{ + int ret; + struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; + u8 devad = ((regnum >> 16) & 0x1f); + u8 is_c45 = !!(regnum & MII_ADDR_C45); + u16 reg = (u16)(regnum & 0xffff); + u8 op; + u16 cmd_reg_cfg; + + dev_dbg(&bus->dev, "mdio write %s,base is %p\n", + bus->id, mdio_dev->vbase); + dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x, write data=%d\n", + phy_id, is_c45, devad, reg, data); + + /* wait for ready */ + ret = hns_mdio_wait_ready(bus); + if (ret) { + dev_err(&bus->dev, "MDIO bus is busy\n"); + return ret; + } + + if (!is_c45) { + cmd_reg_cfg = reg; + op = MDIO_C22_WRITE; + } else { + /* config the cmd-reg to write addr*/ + MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M, + MDIO_ADDR_DATA_S, reg); + + hns_mdio_cmd_write(mdio_dev, is_c45, + MDIO_C45_WRITE_ADDR, phy_id, devad); + + /* check for read or write opt is finished */ + ret = hns_mdio_wait_ready(bus); + if (ret) { + dev_err(&bus->dev, "MDIO bus is busy\n"); + return ret; + } + + /* config the data needed writing */ + cmd_reg_cfg = devad; + op = MDIO_C45_WRITE_ADDR; + } + + MDIO_SET_REG_FIELD(mdio_dev, MDIO_WDATA_REG, MDIO_WDATA_DATA_M, + MDIO_WDATA_DATA_S, data); + + hns_mdio_cmd_write(mdio_dev, is_c45, op, phy_id, cmd_reg_cfg); + + return 0; +} + +/** + * hns_mdio_read - access phy register + * @bus: mdio bus + * @phy_id: phy id + * @regnum: register num + * @value: register value + * + * Return phy register value + */ +static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum) +{ + int ret; + u16 reg_val = 0; + u8 devad = ((regnum >> 16) & 0x1f); + u8 is_c45 = !!(regnum & MII_ADDR_C45); + u16 reg = (u16)(regnum & 0xffff); + struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; + + dev_dbg(&bus->dev, "mdio read %s,base is %p\n", + bus->id, mdio_dev->vbase); + dev_dbg(&bus->dev, "phy id=%d, is_c45=%d, devad=%d, reg=%#x!\n", + phy_id, is_c45, devad, reg); + + /* Step 1: wait for ready */ + ret = hns_mdio_wait_ready(bus); + if (ret) { + dev_err(&bus->dev, "MDIO bus is busy\n"); + return ret; + } + + if (!is_c45) { + hns_mdio_cmd_write(mdio_dev, is_c45, + MDIO_C22_READ, phy_id, reg); + } else { + MDIO_SET_REG_FIELD(mdio_dev, MDIO_ADDR_REG, MDIO_ADDR_DATA_M, + MDIO_ADDR_DATA_S, reg); + + /* Step 2; config the cmd-reg to write addr*/ + hns_mdio_cmd_write(mdio_dev, is_c45, + MDIO_C45_WRITE_ADDR, phy_id, devad); + + /* Step 3: check for read or write opt is finished */ + ret = hns_mdio_wait_ready(bus); + if (ret) { + dev_err(&bus->dev, "MDIO bus is busy\n"); + return ret; + } + + hns_mdio_cmd_write(mdio_dev, is_c45, + MDIO_C45_WRITE_ADDR, phy_id, devad); + } + + /* Step 5: waitting for MDIO_COMMAND_REG 's mdio_start==0,*/ + /* check for read or write opt is finished */ + ret = hns_mdio_wait_ready(bus); + if (ret) { + dev_err(&bus->dev, "MDIO bus is busy\n"); + return ret; + } + + reg_val = MDIO_GET_REG_BIT(mdio_dev, MDIO_STA_REG, MDIO_STATE_STA_B); + if (reg_val) { + dev_err(&bus->dev, " ERROR! MDIO Read failed!\n"); + return -EBUSY; + } + + /* Step 6; get out data*/ + reg_val = (u16)MDIO_GET_REG_FIELD(mdio_dev, MDIO_RDATA_REG, + MDIO_RDATA_DATA_M, MDIO_RDATA_DATA_S); + + return reg_val; +} + +/** + * hns_mdio_reset - reset mdio bus + * @bus: mdio bus + * + * Return 0 on success, negative on failure + */ +static int hns_mdio_reset(struct mii_bus *bus) +{ + struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; + int ret; + + if (!mdio_dev->sys_vbase) { + dev_err(&bus->dev, "mdio sys ctl reg has not maped\n"); + return -ENODEV; + } + + /*1. reset req, and read reset st check*/ + ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_RESET_REQ, 0x1, + MDIO_SC_RESET_ST, 0x1, + MDIO_CHECK_SET_ST); + if (ret) { + dev_err(&bus->dev, "MDIO reset fail\n"); + return ret; + } + + /*2. dis clk, and read clk st check*/ + ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_CLK_DIS, + 0x1, MDIO_SC_CLK_ST, 0x1, + MDIO_CHECK_CLR_ST); + if (ret) { + dev_err(&bus->dev, "MDIO dis clk fail\n"); + return ret; + } + + /*3. reset dreq, and read reset st check*/ + ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_RESET_DREQ, 0x1, + MDIO_SC_RESET_ST, 0x1, + MDIO_CHECK_CLR_ST); + if (ret) { + dev_err(&bus->dev, "MDIO dis clk fail\n"); + return ret; + } + + /*4. en clk, and read clk st check*/ + ret = mdio_sc_cfg_reg_write(mdio_dev, MDIO_SC_CLK_EN, + 0x1, MDIO_SC_CLK_ST, 0x1, + MDIO_CHECK_SET_ST); + if (ret) + dev_err(&bus->dev, "MDIO en clk fail\n"); + + return ret; +} + +/** + * hns_mdio_bus_name - get mdio bus name + * @name: mdio bus name + * @np: mdio device node pointer + */ +static void hns_mdio_bus_name(char *name, struct device_node *np) +{ + const u32 *addr; + u64 taddr = OF_BAD_ADDR; + + addr = of_get_address(np, 0, NULL, NULL); + if (addr) + taddr = of_translate_address(np, addr); + + snprintf(name, MII_BUS_ID_SIZE, "%s@%llx", np->name, + (unsigned long long)taddr); +} + +/** + * hns_mdio_probe - probe mdio device + * @pdev: mdio platform device + * + * Return 0 on success, negative on failure + */ +static int hns_mdio_probe(struct platform_device *pdev) +{ + struct device_node *np; + struct hns_mdio_device *mdio_dev; + struct mii_bus *new_bus; + struct resource *res; + int ret; + + if (!pdev) { + dev_err(NULL, "pdev is NULL!\r\n"); + return -ENODEV; + } + np = pdev->dev.of_node; + mdio_dev = devm_kzalloc(&pdev->dev, sizeof(*mdio_dev), GFP_KERNEL); + if (!mdio_dev) + return -ENOMEM; + + new_bus = devm_mdiobus_alloc(&pdev->dev); + if (!new_bus) { + dev_err(&pdev->dev, "mdiobus_alloc fail!\n"); + return -ENOMEM; + } + + new_bus->name = MDIO_BUS_NAME; + new_bus->read = hns_mdio_read; + new_bus->write = hns_mdio_write; + new_bus->reset = hns_mdio_reset; + new_bus->priv = mdio_dev; + hns_mdio_bus_name(new_bus->id, np); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mdio_dev->vbase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mdio_dev->vbase)) { + ret = PTR_ERR(mdio_dev->vbase); + return ret; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + mdio_dev->sys_vbase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mdio_dev->sys_vbase)) { + ret = PTR_ERR(mdio_dev->sys_vbase); + return ret; + } + + new_bus->irq = devm_kcalloc(&pdev->dev, PHY_MAX_ADDR, + sizeof(int), GFP_KERNEL); + if (!new_bus->irq) + return -ENOMEM; + + new_bus->parent = &pdev->dev; + platform_set_drvdata(pdev, new_bus); + + ret = of_mdiobus_register(new_bus, np); + if (ret) { + dev_err(&pdev->dev, "Cannot register as MDIO bus!\n"); + platform_set_drvdata(pdev, NULL); + return ret; + } + + return 0; +} + +/** + * hns_mdio_remove - remove mdio device + * @pdev: mdio platform device + * + * Return 0 on success, negative on failure + */ +static int hns_mdio_remove(struct platform_device *pdev) +{ + struct mii_bus *bus; + + bus = platform_get_drvdata(pdev); + + mdiobus_unregister(bus); + platform_set_drvdata(pdev, NULL); + return 0; +} + +static const struct of_device_id hns_mdio_match[] = { + {.compatible = "hisilicon,mdio"}, + {.compatible = "hisilicon,hns-mdio"}, + {} +}; + +static struct platform_driver hns_mdio_driver = { + .probe = hns_mdio_probe, + .remove = hns_mdio_remove, + .driver = { + .name = MDIO_DRV_NAME, + .of_match_table = hns_mdio_match, + }, +}; + +module_platform_driver(hns_mdio_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Huawei Tech. Co., Ltd."); +MODULE_DESCRIPTION("Hisilicon HNS MDIO driver"); +MODULE_ALIAS("platform:" MDIO_DRV_NAME); -- cgit v1.2.3 From 6fe6611ff275522a4e4c0359e2f46cdd07780d2f Mon Sep 17 00:00:00 2001 From: huangdaode Date: Thu, 17 Sep 2015 14:51:48 +0800 Subject: net: add Hisilicon Network Subsystem hnae framework support HNAE (Hisilicon Network Acceleration Engine) is a framework to provide a unified ring buffer interface for Hisilicon Network Acceleration Engines. With the interface, upper layer can work as ethernet driver, ODP driver or other service driver on purpose. Signed-off-by: huangdaode Signed-off-by: Kenneth Lee Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/Kconfig | 7 + drivers/net/ethernet/hisilicon/Makefile | 1 + drivers/net/ethernet/hisilicon/hns/Makefile | 5 + drivers/net/ethernet/hisilicon/hns/hnae.c | 507 ++++++++++++++++++++++++ drivers/net/ethernet/hisilicon/hns/hnae.h | 583 ++++++++++++++++++++++++++++ 5 files changed, 1103 insertions(+) create mode 100644 drivers/net/ethernet/hisilicon/hns/Makefile create mode 100644 drivers/net/ethernet/hisilicon/hns/hnae.c create mode 100644 drivers/net/ethernet/hisilicon/hns/hnae.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig index 9184f1d0f92b..85a2609185ad 100644 --- a/drivers/net/ethernet/hisilicon/Kconfig +++ b/drivers/net/ethernet/hisilicon/Kconfig @@ -39,4 +39,11 @@ config HNS_MDIO This selects the HNS MDIO support. It is needed by HNS_DSAF to access the PHY +config HNS + tristate "Hisilicon Network Subsystem Support (Framework)" + ---help--- + This selects the framework support for Hisilicon Network Subsystem. It + is needed by any driver which provides HNS acceleration engine or make + use of the engine + endif # NET_VENDOR_HISILICON diff --git a/drivers/net/ethernet/hisilicon/Makefile b/drivers/net/ethernet/hisilicon/Makefile index 04b4b2177ff4..390b71fb3000 100644 --- a/drivers/net/ethernet/hisilicon/Makefile +++ b/drivers/net/ethernet/hisilicon/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_HIX5HD2_GMAC) += hix5hd2_gmac.o obj-$(CONFIG_HIP04_ETH) += hip04_eth.o obj-$(CONFIG_HNS_MDIO) += hns_mdio.o +obj-$(CONFIG_HNS) += hns/ diff --git a/drivers/net/ethernet/hisilicon/hns/Makefile b/drivers/net/ethernet/hisilicon/hns/Makefile new file mode 100644 index 000000000000..8a5f1e70e936 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the HISILICON network device drivers. +# + +obj-$(CONFIG_HNS) += hnae.o diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c new file mode 100644 index 000000000000..0a0a9e80dcd7 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hnae.c @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include + +#include "hnae.h" + +#define cls_to_ae_dev(dev) container_of(dev, struct hnae_ae_dev, cls_dev) + +static struct class *hnae_class; + +static void +hnae_list_add(spinlock_t *lock, struct list_head *node, struct list_head *head) +{ + unsigned long flags; + + spin_lock_irqsave(lock, flags); + list_add_tail_rcu(node, head); + spin_unlock_irqrestore(lock, flags); +} + +static void hnae_list_del(spinlock_t *lock, struct list_head *node) +{ + unsigned long flags; + + spin_lock_irqsave(lock, flags); + list_del_rcu(node); + spin_unlock_irqrestore(lock, flags); +} + +static int hnae_alloc_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb) +{ + unsigned int order = hnae_page_order(ring); + struct page *p = dev_alloc_pages(order); + + if (!p) + return -ENOMEM; + + cb->priv = p; + cb->page_offset = 0; + cb->reuse_flag = 0; + cb->buf = page_address(p); + cb->length = hnae_page_size(ring); + cb->type = DESC_TYPE_PAGE; + + return 0; +} + +static void hnae_free_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb) +{ + if (cb->type == DESC_TYPE_SKB) + dev_kfree_skb_any((struct sk_buff *)cb->priv); + else if (unlikely(is_rx_ring(ring))) + put_page((struct page *)cb->priv); + memset(cb, 0, sizeof(*cb)); +} + +static int hnae_map_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb) +{ + cb->dma = dma_map_page(ring_to_dev(ring), cb->priv, 0, + cb->length, ring_to_dma_dir(ring)); + + if (dma_mapping_error(ring_to_dev(ring), cb->dma)) + return -EIO; + + return 0; +} + +static void hnae_unmap_buffer(struct hnae_ring *ring, struct hnae_desc_cb *cb) +{ + if (cb->type == DESC_TYPE_SKB) + dma_unmap_single(ring_to_dev(ring), cb->dma, cb->length, + ring_to_dma_dir(ring)); + else + dma_unmap_page(ring_to_dev(ring), cb->dma, cb->length, + ring_to_dma_dir(ring)); +} + +static struct hnae_buf_ops hnae_bops = { + .alloc_buffer = hnae_alloc_buffer, + .free_buffer = hnae_free_buffer, + .map_buffer = hnae_map_buffer, + .unmap_buffer = hnae_unmap_buffer, +}; + +static int __ae_match(struct device *dev, const void *data) +{ + struct hnae_ae_dev *hdev = cls_to_ae_dev(dev); + const char *ae_id = data; + + if (!strncmp(ae_id, hdev->name, AE_NAME_SIZE)) + return 1; + + return 0; +} + +static struct hnae_ae_dev *find_ae(const char *ae_id) +{ + struct device *dev; + + WARN_ON(!ae_id); + + dev = class_find_device(hnae_class, NULL, ae_id, __ae_match); + + return dev ? cls_to_ae_dev(dev) : NULL; +} + +static void hnae_free_buffers(struct hnae_ring *ring) +{ + int i; + + for (i = 0; i < ring->desc_num; i++) + hnae_free_buffer_detach(ring, i); +} + +/* Allocate memory for raw pkg, and map with dma */ +static int hnae_alloc_buffers(struct hnae_ring *ring) +{ + int i, j, ret; + + for (i = 0; i < ring->desc_num; i++) { + ret = hnae_alloc_buffer_attach(ring, i); + if (ret) + goto out_buffer_fail; + } + + return 0; + +out_buffer_fail: + for (j = i - 1; j >= 0; j--) + hnae_free_buffer_detach(ring, j); + return ret; +} + +/* free desc along with its attached buffer */ +static void hnae_free_desc(struct hnae_ring *ring) +{ + hnae_free_buffers(ring); + dma_unmap_single(ring_to_dev(ring), ring->desc_dma_addr, + ring->desc_num * sizeof(ring->desc[0]), + ring_to_dma_dir(ring)); + ring->desc_dma_addr = 0; + kfree(ring->desc); + ring->desc = NULL; +} + +/* alloc desc, without buffer attached */ +static int hnae_alloc_desc(struct hnae_ring *ring) +{ + int size = ring->desc_num * sizeof(ring->desc[0]); + + ring->desc = kzalloc(size, GFP_KERNEL); + if (!ring->desc) + return -ENOMEM; + + ring->desc_dma_addr = dma_map_single(ring_to_dev(ring), + ring->desc, size, ring_to_dma_dir(ring)); + if (dma_mapping_error(ring_to_dev(ring), ring->desc_dma_addr)) { + ring->desc_dma_addr = 0; + kfree(ring->desc); + ring->desc = NULL; + return -ENOMEM; + } + + return 0; +} + +/* fini ring, also free the buffer for the ring */ +static void hnae_fini_ring(struct hnae_ring *ring) +{ + hnae_free_desc(ring); + kfree(ring->desc_cb); + ring->desc_cb = NULL; + ring->next_to_clean = 0; + ring->next_to_use = 0; +} + +/* init ring, and with buffer for rx ring */ +static int +hnae_init_ring(struct hnae_queue *q, struct hnae_ring *ring, int flags) +{ + int ret; + + if (ring->desc_num <= 0 || ring->buf_size <= 0) + return -EINVAL; + + ring->q = q; + ring->flags = flags; + assert(!ring->desc && !ring->desc_cb && !ring->desc_dma_addr); + + /* not matter for tx or rx ring, the ntc and ntc start from 0 */ + assert(ring->next_to_use == 0); + assert(ring->next_to_clean == 0); + + ring->desc_cb = kcalloc(ring->desc_num, sizeof(ring->desc_cb[0]), + GFP_KERNEL); + if (!ring->desc_cb) { + ret = -ENOMEM; + goto out; + } + + ret = hnae_alloc_desc(ring); + if (ret) + goto out_with_desc_cb; + + if (is_rx_ring(ring)) { + ret = hnae_alloc_buffers(ring); + if (ret) + goto out_with_desc; + } + + return 0; + +out_with_desc: + hnae_free_desc(ring); +out_with_desc_cb: + kfree(ring->desc_cb); + ring->desc_cb = NULL; +out: + return ret; +} + +static int hnae_init_queue(struct hnae_handle *h, struct hnae_queue *q, + struct hnae_ae_dev *dev) +{ + int ret; + + q->dev = dev; + q->handle = h; + + ret = hnae_init_ring(q, &q->tx_ring, q->tx_ring.flags | RINGF_DIR); + if (ret) + goto out; + + ret = hnae_init_ring(q, &q->rx_ring, q->rx_ring.flags & ~RINGF_DIR); + if (ret) + goto out_with_tx_ring; + + if (dev->ops->init_queue) + dev->ops->init_queue(q); + + return 0; + +out_with_tx_ring: + hnae_fini_ring(&q->tx_ring); +out: + return ret; +} + +static void hnae_fini_queue(struct hnae_queue *q) +{ + if (q->dev->ops->fini_queue) + q->dev->ops->fini_queue(q); + + hnae_fini_ring(&q->tx_ring); + hnae_fini_ring(&q->rx_ring); +} + +/** + * ae_chain - define ae chain head + */ +static RAW_NOTIFIER_HEAD(ae_chain); + +int hnae_register_notifier(struct notifier_block *nb) +{ + return raw_notifier_chain_register(&ae_chain, nb); +} +EXPORT_SYMBOL(hnae_register_notifier); + +void hnae_unregister_notifier(struct notifier_block *nb) +{ + if (raw_notifier_chain_unregister(&ae_chain, nb)) + dev_err(NULL, "notifier chain unregister fail\n"); +} +EXPORT_SYMBOL(hnae_unregister_notifier); + +int hnae_reinit_handle(struct hnae_handle *handle) +{ + int i, j; + int ret; + + for (i = 0; i < handle->q_num; i++) /* free ring*/ + hnae_fini_queue(handle->qs[i]); + + if (handle->dev->ops->reset) + handle->dev->ops->reset(handle); + + for (i = 0; i < handle->q_num; i++) {/* reinit ring*/ + ret = hnae_init_queue(handle, handle->qs[i], handle->dev); + if (ret) + goto out_when_init_queue; + } + return 0; +out_when_init_queue: + for (j = i - 1; j >= 0; j--) + hnae_fini_queue(handle->qs[j]); + return ret; +} +EXPORT_SYMBOL(hnae_reinit_handle); + +/* hnae_get_handle - get a handle from the AE + * @owner_dev: the dev use this handle + * @ae_id: the id of the ae to be used + * @ae_opts: the options set for the handle + * @bops: the callbacks for buffer management + * + * return handle ptr or ERR_PTR + */ +struct hnae_handle *hnae_get_handle(struct device *owner_dev, + const char *ae_id, u32 port_id, + struct hnae_buf_ops *bops) +{ + struct hnae_ae_dev *dev; + struct hnae_handle *handle; + int i, j; + int ret; + + dev = find_ae(ae_id); + if (!dev) + return ERR_PTR(-ENODEV); + + handle = dev->ops->get_handle(dev, port_id); + if (IS_ERR(handle)) + return handle; + + handle->dev = dev; + handle->owner_dev = owner_dev; + handle->bops = bops ? bops : &hnae_bops; + handle->eport_id = port_id; + + for (i = 0; i < handle->q_num; i++) { + ret = hnae_init_queue(handle, handle->qs[i], dev); + if (ret) + goto out_when_init_queue; + } + + __module_get(dev->owner); + + hnae_list_add(&dev->lock, &handle->node, &dev->handle_list); + + return handle; + +out_when_init_queue: + for (j = i - 1; j >= 0; j--) + hnae_fini_queue(handle->qs[j]); + + return ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL(hnae_get_handle); + +void hnae_put_handle(struct hnae_handle *h) +{ + struct hnae_ae_dev *dev = h->dev; + int i; + + for (i = 0; i < h->q_num; i++) + hnae_fini_queue(h->qs[i]); + + if (h->dev->ops->reset) + h->dev->ops->reset(h); + + hnae_list_del(&dev->lock, &h->node); + + if (dev->ops->put_handle) + dev->ops->put_handle(h); + + module_put(dev->owner); +} +EXPORT_SYMBOL(hnae_put_handle); + +static void hnae_release(struct device *dev) +{ +} + +/** + * hnae_ae_register - register a AE engine to hnae framework + * @hdev: the hnae ae engine device + * @owner: the module who provides this dev + * NOTE: the duplicated name will not be checked + */ +int hnae_ae_register(struct hnae_ae_dev *hdev, struct module *owner) +{ + static atomic_t id = ATOMIC_INIT(-1); + int ret; + + if (!hdev->dev) + return -ENODEV; + + if (!hdev->ops || !hdev->ops->get_handle || + !hdev->ops->toggle_ring_irq || + !hdev->ops->toggle_queue_status || + !hdev->ops->get_status || !hdev->ops->adjust_link) + return -EINVAL; + + hdev->owner = owner; + hdev->id = (int)atomic_inc_return(&id); + hdev->cls_dev.parent = hdev->dev; + hdev->cls_dev.class = hnae_class; + hdev->cls_dev.release = hnae_release; + (void)dev_set_name(&hdev->cls_dev, "hnae%d", hdev->id); + ret = device_register(&hdev->cls_dev); + if (ret) + return ret; + + __module_get(THIS_MODULE); + + INIT_LIST_HEAD(&hdev->handle_list); + spin_lock_init(&hdev->lock); + + ret = raw_notifier_call_chain(&ae_chain, HNAE_AE_REGISTER, NULL); + if (ret) + dev_dbg(hdev->dev, + "has not notifier for AE: %s\n", hdev->name); + + return 0; +} +EXPORT_SYMBOL(hnae_ae_register); + +/** + * hnae_ae_unregister - unregisters a HNAE AE engine + * @cdev: the device to unregister + */ +void hnae_ae_unregister(struct hnae_ae_dev *hdev) +{ + device_unregister(&hdev->cls_dev); + module_put(THIS_MODULE); +} +EXPORT_SYMBOL(hnae_ae_unregister); + +static ssize_t handles_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t s = 0; + struct hnae_ae_dev *hdev = cls_to_ae_dev(dev); + struct hnae_handle *h; + int i = 0, j; + + list_for_each_entry_rcu(h, &hdev->handle_list, node) { + s += sprintf(buf + s, "handle %d (eport_id=%u from %s):\n", + i++, h->eport_id, h->dev->name); + for (j = 0; j < h->q_num; j++) { + s += sprintf(buf + s, "\tqueue[%d] on 0x%llx\n", + j, (u64)h->qs[i]->io_base); +#define HANDEL_TX_MSG "\t\ttx_ring on 0x%llx:%u,%u,%u,%u,%u,%llu,%llu\n" + s += sprintf(buf + s, + HANDEL_TX_MSG, + (u64)h->qs[i]->tx_ring.io_base, + h->qs[i]->tx_ring.buf_size, + h->qs[i]->tx_ring.desc_num, + h->qs[i]->tx_ring.max_desc_num_per_pkt, + h->qs[i]->tx_ring.max_raw_data_sz_per_desc, + h->qs[i]->tx_ring.max_pkt_size, + h->qs[i]->tx_ring.stats.sw_err_cnt, + h->qs[i]->tx_ring.stats.io_err_cnt); + s += sprintf(buf + s, + "\t\trx_ring on 0x%llx:%u,%u,%llu,%llu,%llu\n", + (u64)h->qs[i]->rx_ring.io_base, + h->qs[i]->rx_ring.buf_size, + h->qs[i]->rx_ring.desc_num, + h->qs[i]->rx_ring.stats.sw_err_cnt, + h->qs[i]->rx_ring.stats.io_err_cnt, + h->qs[i]->rx_ring.stats.seg_pkt_cnt); + } + } + + return s; +} + +static DEVICE_ATTR_RO(handles); +static struct attribute *hnae_class_attrs[] = { + &dev_attr_handles.attr, + NULL, +}; +ATTRIBUTE_GROUPS(hnae_class); + +static int __init hnae_init(void) +{ + hnae_class = class_create(THIS_MODULE, "hnae"); + if (IS_ERR(hnae_class)) + return PTR_ERR(hnae_class); + + hnae_class->dev_groups = hnae_class_groups; + return 0; +} + +static void __exit hnae_exit(void) +{ + class_destroy(hnae_class); +} + +subsys_initcall(hnae_init); +module_exit(hnae_exit); + +MODULE_AUTHOR("Hisilicon, Inc."); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Hisilicon Network Acceleration Engine Framework"); + +/* vi: set tw=78 noet: */ diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h new file mode 100644 index 000000000000..5edd8cdc2485 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __HNAE_H +#define __HNAE_H + +/* Names used in this framework: + * ae handle (handle): + * a set of queues provided by AE + * ring buffer queue (rbq): + * the channel between upper layer and the AE, can do tx and rx + * ring: + * a tx or rx channel within a rbq + * ring description (desc): + * an element in the ring with packet information + * buffer: + * a memory region referred by desc with the full packet payload + * + * "num" means a static number set as a parameter, "count" mean a dynamic + * number set while running + * "cb" means control block + */ + +#include +#include +#include +#include +#include +#include + +#define HNAE_DRIVER_VERSION "1.3.0" +#define HNAE_DRIVER_NAME "hns" +#define HNAE_COPYRIGHT "Copyright(c) 2015 Huawei Corporation." +#define HNAE_DRIVER_STRING "Hisilicon Network Subsystem Driver" +#define HNAE_DEFAULT_DEVICE_DESCR "Hisilicon Network Subsystem" + +#ifdef DEBUG + +#ifndef assert +#define assert(expr) \ +do { \ + if (!(expr)) { \ + pr_err("Assertion failed! %s, %s, %s, line %d\n", \ + #expr, __FILE__, __func__, __LINE__); \ + } \ +} while (0) +#endif + +#else + +#ifndef assert +#define assert(expr) +#endif + +#endif + +#define AE_VERSION_1 ('6' << 16 | '6' << 8 | '0') +#define AE_VERSION_2 ('1' << 24 | '6' << 16 | '1' << 8 | '0') +#define AE_NAME_SIZE 16 + +/* some said the RX and TX RCB format should not be the same in the future. But + * it is the same now... + */ +#define RCB_REG_BASEADDR_L 0x00 /* P660 support only 32bit accessing */ +#define RCB_REG_BASEADDR_H 0x04 +#define RCB_REG_BD_NUM 0x08 +#define RCB_REG_BD_LEN 0x0C +#define RCB_REG_PKTLINE 0x10 +#define RCB_REG_TAIL 0x18 +#define RCB_REG_HEAD 0x1C +#define RCB_REG_FBDNUM 0x20 +#define RCB_REG_OFFSET 0x24 /* pkt num to be handled */ +#define RCB_REG_PKTNUM_RECORD 0x2C /* total pkt received */ + +#define HNS_RX_HEAD_SIZE 256 + +#define HNAE_AE_REGISTER 0x1 + +#define RCB_RING_NAME_LEN 16 + +enum hnae_led_state { + HNAE_LED_INACTIVE, + HNAE_LED_ACTIVE, + HNAE_LED_ON, + HNAE_LED_OFF +}; + +#define HNS_RX_FLAG_VLAN_PRESENT 0x1 +#define HNS_RX_FLAG_L3ID_IPV4 0x0 +#define HNS_RX_FLAG_L3ID_IPV6 0x1 +#define HNS_RX_FLAG_L4ID_UDP 0x0 +#define HNS_RX_FLAG_L4ID_TCP 0x1 + +#define HNS_TXD_ASID_S 0 +#define HNS_TXD_ASID_M (0xff << HNS_TXD_ASID_S) +#define HNS_TXD_BUFNUM_S 8 +#define HNS_TXD_BUFNUM_M (0x3 << HNS_TXD_BUFNUM_S) +#define HNS_TXD_PORTID_S 10 +#define HNS_TXD_PORTID_M (0x7 << HNS_TXD_PORTID_S) + +#define HNS_TXD_RA_B 8 +#define HNS_TXD_RI_B 9 +#define HNS_TXD_L4CS_B 10 +#define HNS_TXD_L3CS_B 11 +#define HNS_TXD_FE_B 12 +#define HNS_TXD_VLD_B 13 +#define HNS_TXD_IPOFFSET_S 14 +#define HNS_TXD_IPOFFSET_M (0xff << HNS_TXD_IPOFFSET_S) + +#define HNS_RXD_IPOFFSET_S 0 +#define HNS_RXD_IPOFFSET_M (0xff << HNS_TXD_IPOFFSET_S) +#define HNS_RXD_BUFNUM_S 8 +#define HNS_RXD_BUFNUM_M (0x3 << HNS_RXD_BUFNUM_S) +#define HNS_RXD_PORTID_S 10 +#define HNS_RXD_PORTID_M (0x7 << HNS_RXD_PORTID_S) +#define HNS_RXD_DMAC_S 13 +#define HNS_RXD_DMAC_M (0x3 << HNS_RXD_DMAC_S) +#define HNS_RXD_VLAN_S 15 +#define HNS_RXD_VLAN_M (0x3 << HNS_RXD_VLAN_S) +#define HNS_RXD_L3ID_S 17 +#define HNS_RXD_L3ID_M (0xf << HNS_RXD_L3ID_S) +#define HNS_RXD_L4ID_S 21 +#define HNS_RXD_L4ID_M (0xf << HNS_RXD_L4ID_S) +#define HNS_RXD_FE_B 25 +#define HNS_RXD_FRAG_B 26 +#define HNS_RXD_VLD_B 27 +#define HNS_RXD_L2E_B 28 +#define HNS_RXD_L3E_B 29 +#define HNS_RXD_L4E_B 30 +#define HNS_RXD_DROP_B 31 + +#define HNS_RXD_VLANID_S 8 +#define HNS_RXD_VLANID_M (0xfff << HNS_RXD_VLANID_S) +#define HNS_RXD_CFI_B 20 +#define HNS_RXD_PRI_S 21 +#define HNS_RXD_PRI_M (0x7 << HNS_RXD_PRI_S) +#define HNS_RXD_ASID_S 24 +#define HNS_RXD_ASID_M (0xff << HNS_RXD_ASID_S) + +/* hardware spec ring buffer format */ +struct __packed hnae_desc { + __le64 addr; + union { + struct { + __le16 asid_bufnum_pid; + __le16 send_size; + __le32 flag_ipoffset; + __le32 reserved_3[4]; + } tx; + + struct { + __le32 ipoff_bnum_pid_flag; + __le16 pkt_len; + __le16 size; + __le32 vlan_pri_asid; + __le32 reserved_2[3]; + } rx; + }; +}; + +struct hnae_desc_cb { + dma_addr_t dma; /* dma address of this desc */ + void *buf; /* cpu addr for a desc */ + + /* priv data for the desc, e.g. skb when use with ip stack*/ + void *priv; + u16 page_offset; + u16 reuse_flag; + + u16 length; /* length of the buffer */ + + /* desc type, used by the ring user to mark the type of the priv data */ + u16 type; +}; + +#define setflags(flags, bits) ((flags) |= (bits)) +#define unsetflags(flags, bits) ((flags) &= ~(bits)) + +/* hnae_ring->flags fields */ +#define RINGF_DIR 0x1 /* TX or RX ring, set if TX */ +#define is_tx_ring(ring) ((ring)->flags & RINGF_DIR) +#define is_rx_ring(ring) (!is_tx_ring(ring)) +#define ring_to_dma_dir(ring) (is_tx_ring(ring) ? \ + DMA_TO_DEVICE : DMA_FROM_DEVICE) + +struct ring_stats { + u64 io_err_cnt; + u64 sw_err_cnt; + u64 seg_pkt_cnt; + union { + struct { + u64 tx_pkts; + u64 tx_bytes; + u64 tx_err_cnt; + u64 restart_queue; + u64 tx_busy; + }; + struct { + u64 rx_pkts; + u64 rx_bytes; + u64 rx_err_cnt; + u64 reuse_pg_cnt; + u64 err_pkt_len; + u64 non_vld_descs; + u64 err_bd_num; + u64 l2_err; + u64 l3l4_csum_err; + }; + }; +}; + +struct hnae_queue; + +struct hnae_ring { + u8 __iomem *io_base; /* base io address for the ring */ + struct hnae_desc *desc; /* dma map address space */ + struct hnae_desc_cb *desc_cb; + struct hnae_queue *q; + int irq; + char ring_name[RCB_RING_NAME_LEN]; + + /* statistic */ + struct ring_stats stats; + + dma_addr_t desc_dma_addr; + u32 buf_size; /* size for hnae_desc->addr, preset by AE */ + u16 desc_num; /* total number of desc */ + u16 max_desc_num_per_pkt; + u16 max_raw_data_sz_per_desc; + u16 max_pkt_size; + int next_to_use; /* idx of next spare desc */ + + /* idx of lastest sent desc, the ring is empty when equal to + * next_to_use + */ + int next_to_clean; + + int flags; /* ring attribute */ + int irq_init_flag; +}; + +#define ring_ptr_move_fw(ring, p) \ + ((ring)->p = ((ring)->p + 1) % (ring)->desc_num) +#define ring_ptr_move_bw(ring, p) \ + ((ring)->p = ((ring)->p - 1 + (ring)->desc_num) % (ring)->desc_num) + +enum hns_desc_type { + DESC_TYPE_SKB, + DESC_TYPE_PAGE, +}; + +#define assert_is_ring_idx(ring, idx) \ + assert((idx) >= 0 && (idx) < (ring)->desc_num) + +/* the distance between [begin, end) in a ring buffer + * note: there is a unuse slot between the begin and the end + */ +static inline int ring_dist(struct hnae_ring *ring, int begin, int end) +{ + assert_is_ring_idx(ring, begin); + assert_is_ring_idx(ring, end); + + return (end - begin + ring->desc_num) % ring->desc_num; +} + +static inline int ring_space(struct hnae_ring *ring) +{ + return ring->desc_num - + ring_dist(ring, ring->next_to_clean, ring->next_to_use) - 1; +} + +static inline int is_ring_empty(struct hnae_ring *ring) +{ + assert_is_ring_idx(ring, ring->next_to_use); + assert_is_ring_idx(ring, ring->next_to_clean); + + return ring->next_to_use == ring->next_to_clean; +} + +#define hnae_buf_size(_ring) ((_ring)->buf_size) +#define hnae_page_order(_ring) (get_order(hnae_buf_size(_ring))) +#define hnae_page_size(_ring) (PAGE_SIZE << hnae_page_order(_ring)) + +struct hnae_handle; + +/* allocate and dma map space for hnae desc */ +struct hnae_buf_ops { + int (*alloc_buffer)(struct hnae_ring *ring, struct hnae_desc_cb *cb); + void (*free_buffer)(struct hnae_ring *ring, struct hnae_desc_cb *cb); + int (*map_buffer)(struct hnae_ring *ring, struct hnae_desc_cb *cb); + void (*unmap_buffer)(struct hnae_ring *ring, struct hnae_desc_cb *cb); +}; + +struct hnae_queue { + void __iomem *io_base; + phys_addr_t phy_base; + struct hnae_ae_dev *dev; /* the device who use this queue */ + struct hnae_ring rx_ring, tx_ring; + struct hnae_handle *handle; +}; + +/*hnae loop mode*/ +enum hnae_loop { + MAC_INTERNALLOOP_MAC = 0, + MAC_INTERNALLOOP_SERDES, + MAC_INTERNALLOOP_PHY, + MAC_LOOP_NONE, +}; + +/*hnae port type*/ +enum hnae_port_type { + HNAE_PORT_SERVICE = 0, + HNAE_PORT_DEBUG +}; + +/* This struct defines the operation on the handle. + * + * get_handle(): (mandatory) + * Get a handle from AE according to its name and options. + * the AE driver should manage the space used by handle and its queues while + * the HNAE framework will allocate desc and desc_cb for all rings in the + * queues. + * put_handle(): + * Release the handle. + * start(): + * Enable the hardware, include all queues + * stop(): + * Disable the hardware + * set_opts(): (mandatory) + * Set options to the AE + * get_opts(): (mandatory) + * Get options from the AE + * get_status(): + * Get the carrier state of the back channel of the handle, 1 for ok, 0 for + * non-ok + * toggle_ring_irq(): (mandatory) + * Set the ring irq to be enabled(0) or disable(1) + * toggle_queue_status(): (mandatory) + * Set the queue to be enabled(1) or disable(0), this will not change the + * ring irq state + * adjust_link() + * adjust link status + * set_loopback() + * set loopback + * get_ring_bdnum_limit() + * get ring bd number limit + * get_pauseparam() + * get tx and rx of pause frame use + * set_autoneg() + * set auto autonegotiation of pause frame use + * get_autoneg() + * get auto autonegotiation of pause frame use + * set_pauseparam() + * set tx and rx of pause frame use + * get_coalesce_usecs() + * get usecs to delay a TX interrupt after a packet is sent + * get_rx_max_coalesced_frames() + * get Maximum number of packets to be sent before a TX interrupt. + * set_coalesce_usecs() + * set usecs to delay a TX interrupt after a packet is sent + * set_coalesce_frames() + * set Maximum number of packets to be sent before a TX interrupt. + * get_ringnum() + * get RX/TX ring number + * get_max_ringnum() + * get RX/TX ring maximum number + * get_mac_addr() + * get mac address + * set_mac_addr() + * set mac address + * set_mc_addr() + * set multicast mode + * set_mtu() + * set mtu + * update_stats() + * update Old network device statistics + * get_ethtool_stats() + * get ethtool network device statistics + * get_strings() + * get a set of strings that describe the requested objects + * get_sset_count() + * get number of strings that @get_strings will write + * update_led_status() + * update the led status + * set_led_id() + * set led id + * get_regs() + * get regs dump + * get_regs_len() + * get the len of the regs dump + */ +struct hnae_ae_ops { + struct hnae_handle *(*get_handle)(struct hnae_ae_dev *dev, + u32 port_id); + void (*put_handle)(struct hnae_handle *handle); + void (*init_queue)(struct hnae_queue *q); + void (*fini_queue)(struct hnae_queue *q); + int (*start)(struct hnae_handle *handle); + void (*stop)(struct hnae_handle *handle); + void (*reset)(struct hnae_handle *handle); + int (*set_opts)(struct hnae_handle *handle, int type, void *opts); + int (*get_opts)(struct hnae_handle *handle, int type, void **opts); + int (*get_status)(struct hnae_handle *handle); + int (*get_info)(struct hnae_handle *handle, + u8 *auto_neg, u16 *speed, u8 *duplex); + void (*toggle_ring_irq)(struct hnae_ring *ring, u32 val); + void (*toggle_queue_status)(struct hnae_queue *queue, u32 val); + void (*adjust_link)(struct hnae_handle *handle, int speed, int duplex); + int (*set_loopback)(struct hnae_handle *handle, + enum hnae_loop loop_mode, int en); + void (*get_ring_bdnum_limit)(struct hnae_queue *queue, + u32 *uplimit); + void (*get_pauseparam)(struct hnae_handle *handle, + u32 *auto_neg, u32 *rx_en, u32 *tx_en); + int (*set_autoneg)(struct hnae_handle *handle, u8 enable); + int (*get_autoneg)(struct hnae_handle *handle); + int (*set_pauseparam)(struct hnae_handle *handle, + u32 auto_neg, u32 rx_en, u32 tx_en); + void (*get_coalesce_usecs)(struct hnae_handle *handle, + u32 *tx_usecs, u32 *rx_usecs); + void (*get_rx_max_coalesced_frames)(struct hnae_handle *handle, + u32 *tx_frames, u32 *rx_frames); + void (*set_coalesce_usecs)(struct hnae_handle *handle, u32 timeout); + int (*set_coalesce_frames)(struct hnae_handle *handle, + u32 coalesce_frames); + int (*get_mac_addr)(struct hnae_handle *handle, void **p); + int (*set_mac_addr)(struct hnae_handle *handle, void *p); + int (*set_mc_addr)(struct hnae_handle *handle, void *addr); + int (*set_mtu)(struct hnae_handle *handle, int new_mtu); + void (*update_stats)(struct hnae_handle *handle, + struct net_device_stats *net_stats); + void (*get_stats)(struct hnae_handle *handle, u64 *data); + void (*get_strings)(struct hnae_handle *handle, + u32 stringset, u8 *data); + int (*get_sset_count)(struct hnae_handle *handle, int stringset); + void (*update_led_status)(struct hnae_handle *handle); + int (*set_led_id)(struct hnae_handle *handle, + enum hnae_led_state status); + void (*get_regs)(struct hnae_handle *handle, void *data); + int (*get_regs_len)(struct hnae_handle *handle); +}; + +struct hnae_ae_dev { + struct device cls_dev; /* the class dev */ + struct device *dev; /* the presented dev */ + struct hnae_ae_ops *ops; + struct list_head node; + struct module *owner; /* the module who provides this dev */ + int id; + char name[AE_NAME_SIZE]; + struct list_head handle_list; + spinlock_t lock; /* lock to protect the handle_list */ +}; + +struct hnae_handle { + struct device *owner_dev; /* the device which make use of this handle */ + struct hnae_ae_dev *dev; /* the device who provides this handle */ + struct device_node *phy_node; + phy_interface_t phy_if; + u32 if_support; + int q_num; + int vf_id; + u32 eport_id; + enum hnae_port_type port_type; + struct list_head node; /* list to hnae_ae_dev->handle_list */ + struct hnae_buf_ops *bops; /* operation for the buffer */ + struct hnae_queue **qs; /* array base of all queues */ +}; + +#define ring_to_dev(ring) ((ring)->q->dev->dev) + +struct hnae_handle *hnae_get_handle(struct device *owner_dev, const char *ae_id, + u32 port_id, struct hnae_buf_ops *bops); +void hnae_put_handle(struct hnae_handle *handle); +int hnae_ae_register(struct hnae_ae_dev *dev, struct module *owner); +void hnae_ae_unregister(struct hnae_ae_dev *dev); + +int hnae_register_notifier(struct notifier_block *nb); +void hnae_unregister_notifier(struct notifier_block *nb); +int hnae_reinit_handle(struct hnae_handle *handle); + +#define hnae_queue_xmit(q, buf_num) writel_relaxed(buf_num, \ + (q)->tx_ring.io_base + RCB_REG_TAIL) + +#ifndef assert +#define assert(cond) +#endif + +static inline int hnae_reserve_buffer_map(struct hnae_ring *ring, + struct hnae_desc_cb *cb) +{ + struct hnae_buf_ops *bops = ring->q->handle->bops; + int ret; + + ret = bops->alloc_buffer(ring, cb); + if (ret) + goto out; + + ret = bops->map_buffer(ring, cb); + if (ret) + goto out_with_buf; + + return 0; + +out_with_buf: + bops->free_buffer(ring, cb); +out: + return ret; +} + +static inline int hnae_alloc_buffer_attach(struct hnae_ring *ring, int i) +{ + int ret = hnae_reserve_buffer_map(ring, &ring->desc_cb[i]); + + if (ret) + return ret; + + ring->desc[i].addr = (__le64)ring->desc_cb[i].dma; + + return 0; +} + +static inline void hnae_buffer_detach(struct hnae_ring *ring, int i) +{ + ring->q->handle->bops->unmap_buffer(ring, &ring->desc_cb[i]); + ring->desc[i].addr = 0; +} + +static inline void hnae_free_buffer_detach(struct hnae_ring *ring, int i) +{ + struct hnae_buf_ops *bops = ring->q->handle->bops; + struct hnae_desc_cb *cb = &ring->desc_cb[i]; + + if (!ring->desc_cb[i].dma) + return; + + hnae_buffer_detach(ring, i); + bops->free_buffer(ring, cb); +} + +/* detach a in-used buffer and replace with a reserved one */ +static inline void hnae_replace_buffer(struct hnae_ring *ring, int i, + struct hnae_desc_cb *res_cb) +{ + struct hnae_buf_ops *bops = ring->q->handle->bops; + struct hnae_desc_cb tmp_cb = ring->desc_cb[i]; + + bops->unmap_buffer(ring, &ring->desc_cb[i]); + ring->desc_cb[i] = *res_cb; + *res_cb = tmp_cb; + ring->desc[i].addr = (__le64)ring->desc_cb[i].dma; + ring->desc[i].rx.ipoff_bnum_pid_flag = 0; +} + +static inline void hnae_reuse_buffer(struct hnae_ring *ring, int i) +{ + ring->desc_cb[i].reuse_flag = 0; + ring->desc[i].addr = (__le64)(ring->desc_cb[i].dma + + ring->desc_cb[i].page_offset); + ring->desc[i].rx.ipoff_bnum_pid_flag = 0; +} + +#define hnae_set_field(origin, mask, shift, val) \ + do { \ + (origin) &= (~(mask)); \ + (origin) |= ((val) << (shift)) & (mask); \ + } while (0) + +#define hnae_set_bit(origin, shift, val) \ + hnae_set_field((origin), (0x1 << (shift)), (shift), (val)) + +#define hnae_get_field(origin, mask, shift) (((origin) & (mask)) >> (shift)) + +#define hnae_get_bit(origin, shift) \ + hnae_get_field((origin), (0x1 << (shift)), (shift)) + +#endif -- cgit v1.2.3 From 511e6bc071db1484d1a3d1d0bd4c244cf33910ff Mon Sep 17 00:00:00 2001 From: huangdaode Date: Thu, 17 Sep 2015 14:51:49 +0800 Subject: net: add Hisilicon Network Subsystem DSAF support DSAF, namely Distributed System Area Fabric, is one of the HNS acceleration engine implementation. This patch add DSAF driver to the system. hns_ae_adapt: the adaptor for registering the driver to HNAE framework hns_dsaf_mac: MAC cover interface for GE and XGE hns_dsaf_gmac: GE (10/100/1000G Ethernet) MAC function hns_dsaf_xgmac: XGE (10000+G Ethernet) MAC function hns_dsaf_main: the platform device driver for the whole hardware hns_dsaf_misc: some misc helper function, such as LED support hns_dsaf_ppe: packet process engine function hns_dsaf_rcb: ring buffer function Signed-off-by: huangdaode Signed-off-by: Yisen Zhuang Signed-off-by: Kenneth Lee Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/Kconfig | 9 + drivers/net/ethernet/hisilicon/hns/Makefile | 4 + drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c | 777 +++++++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c | 704 ++++++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h | 45 + drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 900 +++++++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 456 ++++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 2445 ++++++++++++++++++++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h | 427 ++++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c | 317 +++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h | 43 + drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 583 +++++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h | 105 + drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 1023 ++++++++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h | 137 ++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 972 ++++++++ .../net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c | 836 +++++++ .../net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h | 15 + 18 files changed, 9798 insertions(+) create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig index 85a2609185ad..aae2c479a7d5 100644 --- a/drivers/net/ethernet/hisilicon/Kconfig +++ b/drivers/net/ethernet/hisilicon/Kconfig @@ -46,4 +46,13 @@ config HNS is needed by any driver which provides HNS acceleration engine or make use of the engine +config HNS_DSAF + tristate "Hisilicon HNS DSAF device Support" + select HNS + select HNS_MDIO + ---help--- + This selects the DSAF (Distributed System Area Frabric) network + acceleration engine support. The engine is used in Hisilicon hip05, + Hi1610 and further ICT SoC + endif # NET_VENDOR_HISILICON diff --git a/drivers/net/ethernet/hisilicon/hns/Makefile b/drivers/net/ethernet/hisilicon/hns/Makefile index 8a5f1e70e936..0516af7e1a19 100644 --- a/drivers/net/ethernet/hisilicon/hns/Makefile +++ b/drivers/net/ethernet/hisilicon/hns/Makefile @@ -3,3 +3,7 @@ # obj-$(CONFIG_HNS) += hnae.o + +obj-$(CONFIG_HNS_DSAF) += hns_dsaf.o +hns_dsaf-objs = hns_ae_adapt.o hns_dsaf_gmac.o hns_dsaf_mac.o hns_dsaf_misc.o \ + hns_dsaf_main.o hns_dsaf_ppe.o hns_dsaf_rcb.o hns_dsaf_xgmac.o diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c new file mode 100644 index 000000000000..a2c72f84e397 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -0,0 +1,777 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include + +#include "hnae.h" +#include "hns_dsaf_mac.h" +#include "hns_dsaf_main.h" +#include "hns_dsaf_ppe.h" +#include "hns_dsaf_rcb.h" + +#define AE_NAME_PORT_ID_IDX 6 +#define ETH_STATIC_REG 1 +#define ETH_DUMP_REG 5 +#define ETH_GSTRING_LEN 32 + +static struct hns_mac_cb *hns_get_mac_cb(struct hnae_handle *handle) +{ + struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); + + return vf_cb->mac_cb; +} + +/** + * hns_ae_map_eport_to_dport - translate enet port id to dsaf port id + * @port_id: enet port id + *: debug port 0-1, service port 2 -7 (dsaf mode only 2) + * return: dsaf port id + *: service ports 0 - 5, debug port 6-7 + **/ +static int hns_ae_map_eport_to_dport(u32 port_id) +{ + int port_index; + + if (port_id < DSAF_DEBUG_NW_NUM) + port_index = port_id + DSAF_SERVICE_PORT_NUM_PER_DSAF; + else + port_index = port_id - DSAF_DEBUG_NW_NUM; + + return port_index; +} + +static struct dsaf_device *hns_ae_get_dsaf_dev(struct hnae_ae_dev *dev) +{ + return container_of(dev, struct dsaf_device, ae_dev); +} + +static struct hns_ppe_cb *hns_get_ppe_cb(struct hnae_handle *handle) +{ + int ppe_index; + int ppe_common_index; + struct ppe_common_cb *ppe_comm; + struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); + + if (vf_cb->port_index < DSAF_SERVICE_PORT_NUM_PER_DSAF) { + ppe_index = vf_cb->port_index; + ppe_common_index = 0; + } else { + ppe_index = 0; + ppe_common_index = + vf_cb->port_index - DSAF_SERVICE_PORT_NUM_PER_DSAF + 1; + } + ppe_comm = vf_cb->dsaf_dev->ppe_common[ppe_common_index]; + return &ppe_comm->ppe_cb[ppe_index]; +} + +static int hns_ae_get_q_num_per_vf( + struct dsaf_device *dsaf_dev, int port) +{ + int common_idx = hns_dsaf_get_comm_idx_by_port(port); + + return dsaf_dev->rcb_common[common_idx]->max_q_per_vf; +} + +static int hns_ae_get_vf_num_per_port( + struct dsaf_device *dsaf_dev, int port) +{ + int common_idx = hns_dsaf_get_comm_idx_by_port(port); + + return dsaf_dev->rcb_common[common_idx]->max_vfn; +} + +static struct ring_pair_cb *hns_ae_get_base_ring_pair( + struct dsaf_device *dsaf_dev, int port) +{ + int common_idx = hns_dsaf_get_comm_idx_by_port(port); + struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[common_idx]; + int q_num = rcb_comm->max_q_per_vf; + int vf_num = rcb_comm->max_vfn; + + if (common_idx == HNS_DSAF_COMM_SERVICE_NW_IDX) + return &rcb_comm->ring_pair_cb[port * q_num * vf_num]; + else + return &rcb_comm->ring_pair_cb[0]; +} + +static struct ring_pair_cb *hns_ae_get_ring_pair(struct hnae_queue *q) +{ + return container_of(q, struct ring_pair_cb, q); +} + +struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev, + u32 port_id) +{ + int port_idx; + int vfnum_per_port; + int qnum_per_vf; + int i; + struct dsaf_device *dsaf_dev; + struct hnae_handle *ae_handle; + struct ring_pair_cb *ring_pair_cb; + struct hnae_vf_cb *vf_cb; + + dsaf_dev = hns_ae_get_dsaf_dev(dev); + port_idx = hns_ae_map_eport_to_dport(port_id); + + ring_pair_cb = hns_ae_get_base_ring_pair(dsaf_dev, port_idx); + vfnum_per_port = hns_ae_get_vf_num_per_port(dsaf_dev, port_idx); + qnum_per_vf = hns_ae_get_q_num_per_vf(dsaf_dev, port_idx); + + vf_cb = kzalloc(sizeof(*vf_cb) + + qnum_per_vf * sizeof(struct hnae_queue *), GFP_KERNEL); + if (unlikely(!vf_cb)) { + dev_err(dsaf_dev->dev, "malloc vf_cb fail!\n"); + ae_handle = ERR_PTR(-ENOMEM); + goto handle_err; + } + ae_handle = &vf_cb->ae_handle; + /* ae_handle Init */ + ae_handle->owner_dev = dsaf_dev->dev; + ae_handle->dev = dev; + ae_handle->q_num = qnum_per_vf; + + /* find ring pair, and set vf id*/ + for (ae_handle->vf_id = 0; + ae_handle->vf_id < vfnum_per_port; ae_handle->vf_id++) { + if (!ring_pair_cb->used_by_vf) + break; + ring_pair_cb += qnum_per_vf; + } + if (ae_handle->vf_id >= vfnum_per_port) { + dev_err(dsaf_dev->dev, "malloc queue fail!\n"); + ae_handle = ERR_PTR(-EINVAL); + goto vf_id_err; + } + + ae_handle->qs = (struct hnae_queue **)(&ae_handle->qs + 1); + for (i = 0; i < qnum_per_vf; i++) { + ae_handle->qs[i] = &ring_pair_cb->q; + ae_handle->qs[i]->rx_ring.q = ae_handle->qs[i]; + ae_handle->qs[i]->tx_ring.q = ae_handle->qs[i]; + + ring_pair_cb->used_by_vf = 1; + if (port_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF) + ring_pair_cb->port_id_in_dsa = port_idx; + else + ring_pair_cb->port_id_in_dsa = 0; + + ring_pair_cb++; + } + + vf_cb->dsaf_dev = dsaf_dev; + vf_cb->port_index = port_idx; + vf_cb->mac_cb = &dsaf_dev->mac_cb[port_idx]; + + ae_handle->phy_if = vf_cb->mac_cb->phy_if; + ae_handle->phy_node = vf_cb->mac_cb->phy_node; + ae_handle->if_support = vf_cb->mac_cb->if_support; + ae_handle->port_type = vf_cb->mac_cb->mac_type; + + return ae_handle; +vf_id_err: + kfree(vf_cb); +handle_err: + return ae_handle; +} + +static void hns_ae_put_handle(struct hnae_handle *handle) +{ + struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); + int i; + + vf_cb->mac_cb = NULL; + + kfree(vf_cb); + + for (i = 0; i < handle->q_num; i++) + hns_ae_get_ring_pair(handle->qs[i])->used_by_vf = 0; +} + +static void hns_ae_ring_enable_all(struct hnae_handle *handle, int val) +{ + int q_num = handle->q_num; + int i; + + for (i = 0; i < q_num; i++) + hns_rcb_ring_enable_hw(handle->qs[i], val); +} + +static void hns_ae_init_queue(struct hnae_queue *q) +{ + struct ring_pair_cb *ring = + container_of(q, struct ring_pair_cb, q); + + hns_rcb_init_hw(ring); +} + +static void hns_ae_fini_queue(struct hnae_queue *q) +{ + struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(q->handle); + + if (vf_cb->mac_cb->mac_type == HNAE_PORT_SERVICE) + hns_rcb_reset_ring_hw(q); +} + +static int hns_ae_set_mac_address(struct hnae_handle *handle, void *p) +{ + int ret; + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + + if (!p || !is_valid_ether_addr((const u8 *)p)) { + dev_err(handle->owner_dev, "is not valid ether addr !\n"); + return -EADDRNOTAVAIL; + } + + ret = hns_mac_change_vf_addr(mac_cb, handle->vf_id, p); + if (ret != 0) { + dev_err(handle->owner_dev, + "set_mac_address fail, ret=%d!\n", ret); + return ret; + } + + return 0; +} + +static int hns_ae_set_multicast_one(struct hnae_handle *handle, void *addr) +{ + int ret; + char *mac_addr = (char *)addr; + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + + assert(mac_cb); + + if (mac_cb->mac_type != HNAE_PORT_SERVICE) + return 0; + + ret = hns_mac_set_multi(mac_cb, mac_cb->mac_id, mac_addr, ENABLE); + if (ret) { + dev_err(handle->owner_dev, + "mac add mul_mac:%pM port%d fail, ret = %#x!\n", + mac_addr, mac_cb->mac_id, ret); + return ret; + } + + ret = hns_mac_set_multi(mac_cb, DSAF_BASE_INNER_PORT_NUM, + mac_addr, ENABLE); + if (ret) + dev_err(handle->owner_dev, + "mac add mul_mac:%pM port%d fail, ret = %#x!\n", + mac_addr, DSAF_BASE_INNER_PORT_NUM, ret); + + return ret; +} + +static int hns_ae_set_mtu(struct hnae_handle *handle, int new_mtu) +{ + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + + return hns_mac_set_mtu(mac_cb, new_mtu); +} + +static int hns_ae_start(struct hnae_handle *handle) +{ + int ret; + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + + ret = hns_mac_vm_config_bc_en(mac_cb, 0, ENABLE); + if (ret) + return ret; + + hns_ae_ring_enable_all(handle, 1); + msleep(100); + + hns_mac_start(mac_cb); + + return 0; +} + +void hns_ae_stop(struct hnae_handle *handle) +{ + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + + /* just clean tx fbd, neednot rx fbd*/ + hns_rcb_wait_fbd_clean(handle->qs, handle->q_num, RCB_INT_FLAG_TX); + + msleep(20); + + hns_mac_stop(mac_cb); + + usleep_range(10000, 20000); + + hns_ae_ring_enable_all(handle, 0); + + (void)hns_mac_vm_config_bc_en(mac_cb, 0, DISABLE); +} + +static void hns_ae_reset(struct hnae_handle *handle) +{ + struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); + + if (vf_cb->mac_cb->mac_type == HNAE_PORT_DEBUG) { + u8 ppe_common_index = + vf_cb->port_index - DSAF_SERVICE_PORT_NUM_PER_DSAF + 1; + + hns_mac_reset(vf_cb->mac_cb); + hns_ppe_reset_common(vf_cb->dsaf_dev, ppe_common_index); + } +} + +void hns_ae_toggle_ring_irq(struct hnae_ring *ring, u32 mask) +{ + u32 flag; + + if (is_tx_ring(ring)) + flag = RCB_INT_FLAG_TX; + else + flag = RCB_INT_FLAG_RX; + + hns_rcb_int_clr_hw(ring->q, flag); + hns_rcb_int_ctrl_hw(ring->q, flag, mask); +} + +static void hns_ae_toggle_queue_status(struct hnae_queue *queue, u32 val) +{ + hns_rcb_start(queue, val); +} + +static int hns_ae_get_link_status(struct hnae_handle *handle) +{ + u32 link_status; + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + + hns_mac_get_link_status(mac_cb, &link_status); + + return !!link_status; +} + +static int hns_ae_get_mac_info(struct hnae_handle *handle, + u8 *auto_neg, u16 *speed, u8 *duplex) +{ + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + + return hns_mac_get_port_info(mac_cb, auto_neg, speed, duplex); +} + +static void hns_ae_adjust_link(struct hnae_handle *handle, int speed, + int duplex) +{ + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + + hns_mac_adjust_link(mac_cb, speed, duplex); +} + +static void hns_ae_get_ring_bdnum_limit(struct hnae_queue *queue, + u32 *uplimit) +{ + *uplimit = HNS_RCB_RING_MAX_PENDING_BD; +} + +static void hns_ae_get_pauseparam(struct hnae_handle *handle, + u32 *auto_neg, u32 *rx_en, u32 *tx_en) +{ + assert(handle); + + hns_mac_get_autoneg(hns_get_mac_cb(handle), auto_neg); + + hns_mac_get_pauseparam(hns_get_mac_cb(handle), rx_en, tx_en); +} + +static int hns_ae_set_autoneg(struct hnae_handle *handle, u8 enable) +{ + assert(handle); + + return hns_mac_set_autoneg(hns_get_mac_cb(handle), enable); +} + +static int hns_ae_get_autoneg(struct hnae_handle *handle) +{ + u32 auto_neg; + + assert(handle); + + hns_mac_get_autoneg(hns_get_mac_cb(handle), &auto_neg); + + return auto_neg; +} + +static int hns_ae_set_pauseparam(struct hnae_handle *handle, + u32 autoneg, u32 rx_en, u32 tx_en) +{ + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + int ret; + + ret = hns_mac_set_autoneg(mac_cb, autoneg); + if (ret) + return ret; + + return hns_mac_set_pauseparam(mac_cb, rx_en, tx_en); +} + +static void hns_ae_get_coalesce_usecs(struct hnae_handle *handle, + u32 *tx_usecs, u32 *rx_usecs) +{ + int port; + + port = hns_ae_map_eport_to_dport(handle->eport_id); + + *tx_usecs = hns_rcb_get_coalesce_usecs( + hns_ae_get_dsaf_dev(handle->dev), + hns_dsaf_get_comm_idx_by_port(port)); + *rx_usecs = hns_rcb_get_coalesce_usecs( + hns_ae_get_dsaf_dev(handle->dev), + hns_dsaf_get_comm_idx_by_port(port)); +} + +static void hns_ae_get_rx_max_coalesced_frames(struct hnae_handle *handle, + u32 *tx_frames, u32 *rx_frames) +{ + int port; + + assert(handle); + + port = hns_ae_map_eport_to_dport(handle->eport_id); + + *tx_frames = hns_rcb_get_coalesced_frames( + hns_ae_get_dsaf_dev(handle->dev), port); + *rx_frames = hns_rcb_get_coalesced_frames( + hns_ae_get_dsaf_dev(handle->dev), port); +} + +static void hns_ae_set_coalesce_usecs(struct hnae_handle *handle, + u32 timeout) +{ + int port; + + assert(handle); + + port = hns_ae_map_eport_to_dport(handle->eport_id); + + hns_rcb_set_coalesce_usecs(hns_ae_get_dsaf_dev(handle->dev), + port, timeout); +} + +static int hns_ae_set_coalesce_frames(struct hnae_handle *handle, + u32 coalesce_frames) +{ + int port; + int ret; + + assert(handle); + + port = hns_ae_map_eport_to_dport(handle->eport_id); + + ret = hns_rcb_set_coalesced_frames(hns_ae_get_dsaf_dev(handle->dev), + port, coalesce_frames); + return ret; +} + +void hns_ae_update_stats(struct hnae_handle *handle, + struct net_device_stats *net_stats) +{ + int port; + int idx; + struct dsaf_device *dsaf_dev; + struct hns_mac_cb *mac_cb; + struct hns_ppe_cb *ppe_cb; + struct hnae_queue *queue; + struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); + u64 tx_bytes = 0, rx_bytes = 0, tx_packets = 0, rx_packets = 0; + u64 rx_errors = 0, tx_errors = 0, tx_dropped = 0; + u64 rx_missed_errors = 0; + + dsaf_dev = hns_ae_get_dsaf_dev(handle->dev); + if (!dsaf_dev) + return; + port = vf_cb->port_index; + ppe_cb = hns_get_ppe_cb(handle); + mac_cb = hns_get_mac_cb(handle); + + for (idx = 0; idx < handle->q_num; idx++) { + queue = handle->qs[idx]; + hns_rcb_update_stats(queue); + + tx_bytes += queue->tx_ring.stats.tx_bytes; + tx_packets += queue->tx_ring.stats.tx_pkts; + rx_bytes += queue->rx_ring.stats.rx_bytes; + rx_packets += queue->rx_ring.stats.rx_pkts; + + rx_errors += queue->rx_ring.stats.err_pkt_len + + queue->rx_ring.stats.l2_err + + queue->rx_ring.stats.l3l4_csum_err; + } + + hns_ppe_update_stats(ppe_cb); + rx_missed_errors = ppe_cb->hw_stats.rx_drop_no_buf; + tx_errors += ppe_cb->hw_stats.tx_err_checksum + + ppe_cb->hw_stats.tx_err_fifo_empty; + + if (mac_cb->mac_type == HNAE_PORT_SERVICE) { + hns_dsaf_update_stats(dsaf_dev, port); + /* for port upline direction, i.e., rx. */ + rx_missed_errors += dsaf_dev->hw_stats[port].bp_drop; + rx_missed_errors += dsaf_dev->hw_stats[port].pad_drop; + rx_missed_errors += dsaf_dev->hw_stats[port].crc_false; + + /* for port downline direction, i.e., tx. */ + port = port + DSAF_PPE_INODE_BASE; + hns_dsaf_update_stats(dsaf_dev, port); + tx_dropped += dsaf_dev->hw_stats[port].bp_drop; + tx_dropped += dsaf_dev->hw_stats[port].pad_drop; + tx_dropped += dsaf_dev->hw_stats[port].crc_false; + tx_dropped += dsaf_dev->hw_stats[port].rslt_drop; + tx_dropped += dsaf_dev->hw_stats[port].vlan_drop; + tx_dropped += dsaf_dev->hw_stats[port].stp_drop; + } + + hns_mac_update_stats(mac_cb); + rx_errors += mac_cb->hw_stats.rx_fifo_overrun_err; + + tx_errors += mac_cb->hw_stats.tx_bad_pkts + + mac_cb->hw_stats.tx_fragment_err + + mac_cb->hw_stats.tx_jabber_err + + mac_cb->hw_stats.tx_underrun_err + + mac_cb->hw_stats.tx_crc_err; + + net_stats->tx_bytes = tx_bytes; + net_stats->tx_packets = tx_packets; + net_stats->rx_bytes = rx_bytes; + net_stats->rx_dropped = 0; + net_stats->rx_packets = rx_packets; + net_stats->rx_errors = rx_errors; + net_stats->tx_errors = tx_errors; + net_stats->tx_dropped = tx_dropped; + net_stats->rx_missed_errors = rx_missed_errors; + net_stats->rx_crc_errors = mac_cb->hw_stats.rx_fcs_err; + net_stats->rx_frame_errors = mac_cb->hw_stats.rx_align_err; + net_stats->rx_fifo_errors = mac_cb->hw_stats.rx_fifo_overrun_err; + net_stats->rx_length_errors = mac_cb->hw_stats.rx_len_err; + net_stats->multicast = mac_cb->hw_stats.rx_mc_pkts; +} + +void hns_ae_get_stats(struct hnae_handle *handle, u64 *data) +{ + int idx; + struct hns_mac_cb *mac_cb; + struct hns_ppe_cb *ppe_cb; + u64 *p = data; + struct hnae_vf_cb *vf_cb; + + if (!handle || !data) { + pr_err("hns_ae_get_stats NULL handle or data pointer!\n"); + return; + } + + vf_cb = hns_ae_get_vf_cb(handle); + mac_cb = hns_get_mac_cb(handle); + ppe_cb = hns_get_ppe_cb(handle); + + for (idx = 0; idx < handle->q_num; idx++) { + hns_rcb_get_stats(handle->qs[idx], p); + p += hns_rcb_get_ring_sset_count((int)ETH_SS_STATS); + } + + hns_ppe_get_stats(ppe_cb, p); + p += hns_ppe_get_sset_count((int)ETH_SS_STATS); + + hns_mac_get_stats(mac_cb, p); + p += hns_mac_get_sset_count(mac_cb, (int)ETH_SS_STATS); + + if (mac_cb->mac_type == HNAE_PORT_SERVICE) + hns_dsaf_get_stats(vf_cb->dsaf_dev, p, vf_cb->port_index); +} + +void hns_ae_get_strings(struct hnae_handle *handle, + u32 stringset, u8 *data) +{ + int port; + int idx; + struct hns_mac_cb *mac_cb; + struct hns_ppe_cb *ppe_cb; + u8 *p = data; + struct hnae_vf_cb *vf_cb; + + assert(handle); + + vf_cb = hns_ae_get_vf_cb(handle); + port = vf_cb->port_index; + mac_cb = hns_get_mac_cb(handle); + ppe_cb = hns_get_ppe_cb(handle); + + for (idx = 0; idx < handle->q_num; idx++) { + hns_rcb_get_strings(stringset, p, idx); + p += ETH_GSTRING_LEN * hns_rcb_get_ring_sset_count(stringset); + } + + hns_ppe_get_strings(ppe_cb, stringset, p); + p += ETH_GSTRING_LEN * hns_ppe_get_sset_count(stringset); + + hns_mac_get_strings(mac_cb, stringset, p); + p += ETH_GSTRING_LEN * hns_mac_get_sset_count(mac_cb, stringset); + + if (mac_cb->mac_type == HNAE_PORT_SERVICE) + hns_dsaf_get_strings(stringset, p, port); +} + +int hns_ae_get_sset_count(struct hnae_handle *handle, int stringset) +{ + u32 sset_count = 0; + struct hns_mac_cb *mac_cb; + + assert(handle); + + mac_cb = hns_get_mac_cb(handle); + + sset_count += hns_rcb_get_ring_sset_count(stringset) * handle->q_num; + sset_count += hns_ppe_get_sset_count(stringset); + sset_count += hns_mac_get_sset_count(mac_cb, stringset); + + if (mac_cb->mac_type == HNAE_PORT_SERVICE) + sset_count += hns_dsaf_get_sset_count(stringset); + + return sset_count; +} + +static int hns_ae_config_loopback(struct hnae_handle *handle, + enum hnae_loop loop, int en) +{ + int ret; + struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); + + switch (loop) { + case MAC_INTERNALLOOP_SERDES: + ret = hns_mac_config_sds_loopback(vf_cb->mac_cb, en); + break; + case MAC_INTERNALLOOP_MAC: + ret = hns_mac_config_mac_loopback(vf_cb->mac_cb, loop, en); + break; + default: + ret = -EINVAL; + } + return ret; +} + +void hns_ae_update_led_status(struct hnae_handle *handle) +{ + struct hns_mac_cb *mac_cb; + + assert(handle); + mac_cb = hns_get_mac_cb(handle); + if (!mac_cb->cpld_vaddr) + return; + hns_set_led_opt(mac_cb); +} + +int hns_ae_cpld_set_led_id(struct hnae_handle *handle, + enum hnae_led_state status) +{ + struct hns_mac_cb *mac_cb; + + assert(handle); + + mac_cb = hns_get_mac_cb(handle); + + return hns_cpld_led_set_id(mac_cb, status); +} + +void hns_ae_get_regs(struct hnae_handle *handle, void *data) +{ + u32 *p = data; + u32 rcb_com_idx; + int i; + struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); + struct hns_ppe_cb *ppe_cb = hns_get_ppe_cb(handle); + + hns_ppe_get_regs(ppe_cb, p); + p += hns_ppe_get_regs_count(); + + rcb_com_idx = hns_dsaf_get_comm_idx_by_port(vf_cb->port_index); + hns_rcb_get_common_regs(vf_cb->dsaf_dev->rcb_common[rcb_com_idx], p); + p += hns_rcb_get_common_regs_count(); + + for (i = 0; i < handle->q_num; i++) { + hns_rcb_get_ring_regs(handle->qs[i], p); + p += hns_rcb_get_ring_regs_count(); + } + + hns_mac_get_regs(vf_cb->mac_cb, p); + p += hns_mac_get_regs_count(vf_cb->mac_cb); + + if (vf_cb->mac_cb->mac_type == HNAE_PORT_SERVICE) + hns_dsaf_get_regs(vf_cb->dsaf_dev, vf_cb->port_index, p); +} + +int hns_ae_get_regs_len(struct hnae_handle *handle) +{ + u32 total_num; + struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); + + total_num = hns_ppe_get_regs_count(); + total_num += hns_rcb_get_common_regs_count(); + total_num += hns_rcb_get_ring_regs_count() * handle->q_num; + total_num += hns_mac_get_regs_count(vf_cb->mac_cb); + + if (vf_cb->mac_cb->mac_type == HNAE_PORT_SERVICE) + total_num += hns_dsaf_get_regs_count(); + + return total_num; +} + +static struct hnae_ae_ops hns_dsaf_ops = { + .get_handle = hns_ae_get_handle, + .put_handle = hns_ae_put_handle, + .init_queue = hns_ae_init_queue, + .fini_queue = hns_ae_fini_queue, + .start = hns_ae_start, + .stop = hns_ae_stop, + .reset = hns_ae_reset, + .toggle_ring_irq = hns_ae_toggle_ring_irq, + .toggle_queue_status = hns_ae_toggle_queue_status, + .get_status = hns_ae_get_link_status, + .get_info = hns_ae_get_mac_info, + .adjust_link = hns_ae_adjust_link, + .set_loopback = hns_ae_config_loopback, + .get_ring_bdnum_limit = hns_ae_get_ring_bdnum_limit, + .get_pauseparam = hns_ae_get_pauseparam, + .set_autoneg = hns_ae_set_autoneg, + .get_autoneg = hns_ae_get_autoneg, + .set_pauseparam = hns_ae_set_pauseparam, + .get_coalesce_usecs = hns_ae_get_coalesce_usecs, + .get_rx_max_coalesced_frames = hns_ae_get_rx_max_coalesced_frames, + .set_coalesce_usecs = hns_ae_set_coalesce_usecs, + .set_coalesce_frames = hns_ae_set_coalesce_frames, + .set_mac_addr = hns_ae_set_mac_address, + .set_mc_addr = hns_ae_set_multicast_one, + .set_mtu = hns_ae_set_mtu, + .update_stats = hns_ae_update_stats, + .get_stats = hns_ae_get_stats, + .get_strings = hns_ae_get_strings, + .get_sset_count = hns_ae_get_sset_count, + .update_led_status = hns_ae_update_led_status, + .set_led_id = hns_ae_cpld_set_led_id, + .get_regs = hns_ae_get_regs, + .get_regs_len = hns_ae_get_regs_len +}; + +int hns_dsaf_ae_init(struct dsaf_device *dsaf_dev) +{ + struct hnae_ae_dev *ae_dev = &dsaf_dev->ae_dev; + + ae_dev->ops = &hns_dsaf_ops; + ae_dev->dev = dsaf_dev->dev; + + return hnae_ae_register(ae_dev, THIS_MODULE); +} + +void hns_dsaf_ae_uninit(struct dsaf_device *dsaf_dev) +{ + hnae_ae_unregister(&dsaf_dev->ae_dev); +} diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c new file mode 100644 index 000000000000..b8517b00e706 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c @@ -0,0 +1,704 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include "hns_dsaf_main.h" +#include "hns_dsaf_mac.h" +#include "hns_dsaf_gmac.h" + +static const struct mac_stats_string g_gmac_stats_string[] = { + {"gmac_rx_octets_total_ok", MAC_STATS_FIELD_OFF(rx_good_bytes)}, + {"gmac_rx_octets_bad", MAC_STATS_FIELD_OFF(rx_bad_bytes)}, + {"gmac_rx_uc_pkts", MAC_STATS_FIELD_OFF(rx_uc_pkts)}, + {"gamc_rx_mc_pkts", MAC_STATS_FIELD_OFF(rx_mc_pkts)}, + {"gmac_rx_bc_pkts", MAC_STATS_FIELD_OFF(rx_bc_pkts)}, + {"gmac_rx_pkts_64octets", MAC_STATS_FIELD_OFF(rx_64bytes)}, + {"gmac_rx_pkts_65to127", MAC_STATS_FIELD_OFF(rx_65to127)}, + {"gmac_rx_pkts_128to255", MAC_STATS_FIELD_OFF(rx_128to255)}, + {"gmac_rx_pkts_256to511", MAC_STATS_FIELD_OFF(rx_256to511)}, + {"gmac_rx_pkts_512to1023", MAC_STATS_FIELD_OFF(rx_512to1023)}, + {"gmac_rx_pkts_1024to1518", MAC_STATS_FIELD_OFF(rx_1024to1518)}, + {"gmac_rx_pkts_1519tomax", MAC_STATS_FIELD_OFF(rx_1519tomax)}, + {"gmac_rx_fcs_errors", MAC_STATS_FIELD_OFF(rx_fcs_err)}, + {"gmac_rx_tagged", MAC_STATS_FIELD_OFF(rx_vlan_pkts)}, + {"gmac_rx_data_err", MAC_STATS_FIELD_OFF(rx_data_err)}, + {"gmac_rx_align_errors", MAC_STATS_FIELD_OFF(rx_align_err)}, + {"gmac_rx_long_errors", MAC_STATS_FIELD_OFF(rx_oversize)}, + {"gmac_rx_jabber_errors", MAC_STATS_FIELD_OFF(rx_jabber_err)}, + {"gmac_rx_pause_maccontrol", MAC_STATS_FIELD_OFF(rx_pfc_tc0)}, + {"gmac_rx_unknown_maccontrol", MAC_STATS_FIELD_OFF(rx_unknown_ctrl)}, + {"gmac_rx_very_long_err", MAC_STATS_FIELD_OFF(rx_long_err)}, + {"gmac_rx_runt_err", MAC_STATS_FIELD_OFF(rx_minto64)}, + {"gmac_rx_short_err", MAC_STATS_FIELD_OFF(rx_under_min)}, + {"gmac_rx_filt_pkt", MAC_STATS_FIELD_OFF(rx_filter_bytes)}, + {"gmac_rx_octets_total_filt", MAC_STATS_FIELD_OFF(rx_filter_pkts)}, + {"gmac_rx_overrun_cnt", MAC_STATS_FIELD_OFF(rx_fifo_overrun_err)}, + {"gmac_rx_length_err", MAC_STATS_FIELD_OFF(rx_len_err)}, + {"gmac_rx_fail_comma", MAC_STATS_FIELD_OFF(rx_comma_err)}, + + {"gmac_tx_octets_ok", MAC_STATS_FIELD_OFF(tx_good_bytes)}, + {"gmac_tx_octets_bad", MAC_STATS_FIELD_OFF(tx_bad_bytes)}, + {"gmac_tx_uc_pkts", MAC_STATS_FIELD_OFF(tx_uc_pkts)}, + {"gmac_tx_mc_pkts", MAC_STATS_FIELD_OFF(tx_mc_pkts)}, + {"gmac_tx_bc_pkts", MAC_STATS_FIELD_OFF(tx_bc_pkts)}, + {"gmac_tx_pkts_64octets", MAC_STATS_FIELD_OFF(tx_64bytes)}, + {"gmac_tx_pkts_65to127", MAC_STATS_FIELD_OFF(tx_65to127)}, + {"gmac_tx_pkts_128to255", MAC_STATS_FIELD_OFF(tx_128to255)}, + {"gmac_tx_pkts_256to511", MAC_STATS_FIELD_OFF(tx_256to511)}, + {"gmac_tx_pkts_512to1023", MAC_STATS_FIELD_OFF(tx_512to1023)}, + {"gmac_tx_pkts_1024to1518", MAC_STATS_FIELD_OFF(tx_1024to1518)}, + {"gmac_tx_pkts_1519tomax", MAC_STATS_FIELD_OFF(tx_1519tomax)}, + {"gmac_tx_excessive_length_drop", MAC_STATS_FIELD_OFF(tx_jabber_err)}, + {"gmac_tx_underrun", MAC_STATS_FIELD_OFF(tx_underrun_err)}, + {"gmac_tx_tagged", MAC_STATS_FIELD_OFF(tx_vlan)}, + {"gmac_tx_crc_error", MAC_STATS_FIELD_OFF(tx_crc_err)}, + {"gmac_tx_pause_frames", MAC_STATS_FIELD_OFF(tx_pfc_tc0)} +}; + +static void hns_gmac_enable(void *mac_drv, enum mac_commom_mode mode) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + /*enable GE rX/tX */ + if ((mode == MAC_COMM_MODE_TX) || (mode == MAC_COMM_MODE_RX_AND_TX)) + dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_TX_EN_B, 1); + + if ((mode == MAC_COMM_MODE_RX) || (mode == MAC_COMM_MODE_RX_AND_TX)) + dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_RX_EN_B, 1); +} + +static void hns_gmac_disable(void *mac_drv, enum mac_commom_mode mode) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + /*disable GE rX/tX */ + if ((mode == MAC_COMM_MODE_TX) || (mode == MAC_COMM_MODE_RX_AND_TX)) + dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_TX_EN_B, 0); + + if ((mode == MAC_COMM_MODE_RX) || (mode == MAC_COMM_MODE_RX_AND_TX)) + dsaf_set_dev_bit(drv, GMAC_PORT_EN_REG, GMAC_PORT_RX_EN_B, 0); +} + +/** +*hns_gmac_get_en - get port enable +*@mac_drv:mac device +*@rx:rx enable +*@tx:tx enable +*/ +static void hns_gmac_get_en(void *mac_drv, u32 *rx, u32 *tx) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + u32 porten; + + porten = dsaf_read_dev(drv, GMAC_PORT_EN_REG); + *tx = dsaf_get_bit(porten, GMAC_PORT_TX_EN_B); + *rx = dsaf_get_bit(porten, GMAC_PORT_RX_EN_B); +} + +static void hns_gmac_free(void *mac_drv) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + struct dsaf_device *dsaf_dev + = (struct dsaf_device *)dev_get_drvdata(drv->dev); + + u32 mac_id = drv->mac_id; + + hns_dsaf_ge_srst_by_port(dsaf_dev, mac_id, 0); +} + +static void hns_gmac_set_tx_auto_pause_frames(void *mac_drv, u16 newval) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + dsaf_set_dev_field(drv, GMAC_FC_TX_TIMER_REG, GMAC_FC_TX_TIMER_M, + GMAC_FC_TX_TIMER_S, newval); +} + +static void hns_gmac_get_tx_auto_pause_frames(void *mac_drv, u16 *newval) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + *newval = dsaf_get_dev_field(drv, GMAC_FC_TX_TIMER_REG, + GMAC_FC_TX_TIMER_M, GMAC_FC_TX_TIMER_S); +} + +static void hns_gmac_set_rx_auto_pause_frames(void *mac_drv, u32 newval) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + dsaf_set_dev_bit(drv, GMAC_PAUSE_EN_REG, + GMAC_PAUSE_EN_RX_FDFC_B, !!newval); +} + +static void hns_gmac_config_max_frame_length(void *mac_drv, u16 newval) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + dsaf_set_dev_field(drv, GMAC_MAX_FRM_SIZE_REG, GMAC_MAX_FRM_SIZE_M, + GMAC_MAX_FRM_SIZE_S, newval); + + dsaf_set_dev_field(drv, GAMC_RX_MAX_FRAME, GMAC_MAX_FRM_SIZE_M, + GMAC_MAX_FRM_SIZE_S, newval); +} + +static void hns_gmac_config_an_mode(void *mac_drv, u8 newval) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + dsaf_set_dev_bit(drv, GMAC_TRANSMIT_CONTROL_REG, + GMAC_TX_AN_EN_B, !!newval); +} + +static void hns_gmac_tx_loop_pkt_dis(void *mac_drv) +{ + u32 tx_loop_pkt_pri; + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + tx_loop_pkt_pri = dsaf_read_dev(drv, GMAC_TX_LOOP_PKT_PRI_REG); + dsaf_set_bit(tx_loop_pkt_pri, GMAC_TX_LOOP_PKT_EN_B, 1); + dsaf_set_bit(tx_loop_pkt_pri, GMAC_TX_LOOP_PKT_HIG_PRI_B, 0); + dsaf_write_dev(drv, GMAC_TX_LOOP_PKT_PRI_REG, tx_loop_pkt_pri); +} + +static void hns_gmac_set_duplex_type(void *mac_drv, u8 newval) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + dsaf_set_dev_bit(drv, GMAC_DUPLEX_TYPE_REG, + GMAC_DUPLEX_TYPE_B, !!newval); +} + +static void hns_gmac_get_duplex_type(void *mac_drv, + enum hns_gmac_duplex_mdoe *duplex_mode) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + *duplex_mode = (enum hns_gmac_duplex_mdoe)dsaf_get_dev_bit( + drv, GMAC_DUPLEX_TYPE_REG, GMAC_DUPLEX_TYPE_B); +} + +static void hns_gmac_get_port_mode(void *mac_drv, enum hns_port_mode *port_mode) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + *port_mode = (enum hns_port_mode)dsaf_get_dev_field( + drv, GMAC_PORT_MODE_REG, GMAC_PORT_MODE_M, GMAC_PORT_MODE_S); +} + +static void hns_gmac_port_mode_get(void *mac_drv, + struct hns_gmac_port_mode_cfg *port_mode) +{ + u32 tx_ctrl; + u32 recv_ctrl; + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + port_mode->port_mode = (enum hns_port_mode)dsaf_get_dev_field( + drv, GMAC_PORT_MODE_REG, GMAC_PORT_MODE_M, GMAC_PORT_MODE_S); + + tx_ctrl = dsaf_read_dev(drv, GMAC_TRANSMIT_CONTROL_REG); + recv_ctrl = dsaf_read_dev(drv, GMAC_RECV_CONTROL_REG); + + port_mode->max_frm_size = + dsaf_get_dev_field(drv, GMAC_MAX_FRM_SIZE_REG, + GMAC_MAX_FRM_SIZE_M, GMAC_MAX_FRM_SIZE_S); + port_mode->short_runts_thr = + dsaf_get_dev_field(drv, GMAC_SHORT_RUNTS_THR_REG, + GMAC_SHORT_RUNTS_THR_M, + GMAC_SHORT_RUNTS_THR_S); + + port_mode->pad_enable = dsaf_get_bit(tx_ctrl, GMAC_TX_PAD_EN_B); + port_mode->crc_add = dsaf_get_bit(tx_ctrl, GMAC_TX_CRC_ADD_B); + port_mode->an_enable = dsaf_get_bit(tx_ctrl, GMAC_TX_AN_EN_B); + + port_mode->runt_pkt_en = + dsaf_get_bit(recv_ctrl, GMAC_RECV_CTRL_RUNT_PKT_EN_B); + port_mode->strip_pad_en = + dsaf_get_bit(recv_ctrl, GMAC_RECV_CTRL_STRIP_PAD_EN_B); +} + +static void hns_gmac_pause_frm_cfg(void *mac_drv, u32 rx_pause_en, + u32 tx_pause_en) +{ + u32 pause_en; + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + pause_en = dsaf_read_dev(drv, GMAC_PAUSE_EN_REG); + dsaf_set_bit(pause_en, GMAC_PAUSE_EN_RX_FDFC_B, !!rx_pause_en); + dsaf_set_bit(pause_en, GMAC_PAUSE_EN_TX_FDFC_B, !!tx_pause_en); + dsaf_write_dev(drv, GMAC_PAUSE_EN_REG, pause_en); +} + +static void hns_gmac_get_pausefrm_cfg(void *mac_drv, u32 *rx_pause_en, + u32 *tx_pause_en) +{ + u32 pause_en; + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + pause_en = dsaf_read_dev(drv, GMAC_PAUSE_EN_REG); + + *rx_pause_en = dsaf_get_bit(pause_en, GMAC_PAUSE_EN_RX_FDFC_B); + *tx_pause_en = dsaf_get_bit(pause_en, GMAC_PAUSE_EN_TX_FDFC_B); +} + +static int hns_gmac_adjust_link(void *mac_drv, enum mac_speed speed, + u32 full_duplex) +{ + u32 tx_ctrl; + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + dsaf_set_dev_bit(drv, GMAC_DUPLEX_TYPE_REG, + GMAC_DUPLEX_TYPE_B, !!full_duplex); + + switch (speed) { + case MAC_SPEED_10: + dsaf_set_dev_field( + drv, GMAC_PORT_MODE_REG, + GMAC_PORT_MODE_M, GMAC_PORT_MODE_S, 0x6); + break; + case MAC_SPEED_100: + dsaf_set_dev_field( + drv, GMAC_PORT_MODE_REG, + GMAC_PORT_MODE_M, GMAC_PORT_MODE_S, 0x7); + break; + case MAC_SPEED_1000: + dsaf_set_dev_field( + drv, GMAC_PORT_MODE_REG, + GMAC_PORT_MODE_M, GMAC_PORT_MODE_S, 0x8); + break; + default: + dev_err(drv->dev, + "hns_gmac_adjust_link fail, speed%d mac%d\n", + speed, drv->mac_id); + return -EINVAL; + } + + tx_ctrl = dsaf_read_dev(drv, GMAC_TRANSMIT_CONTROL_REG); + dsaf_set_bit(tx_ctrl, GMAC_TX_PAD_EN_B, 1); + dsaf_set_bit(tx_ctrl, GMAC_TX_CRC_ADD_B, 1); + dsaf_write_dev(drv, GMAC_TRANSMIT_CONTROL_REG, tx_ctrl); + + dsaf_set_dev_bit(drv, GMAC_MODE_CHANGE_EN_REG, + GMAC_MODE_CHANGE_EB_B, 1); + + return 0; +} + +static void hns_gmac_init(void *mac_drv) +{ + u32 port; + struct mac_driver *drv = (struct mac_driver *)mac_drv; + struct dsaf_device *dsaf_dev + = (struct dsaf_device *)dev_get_drvdata(drv->dev); + + port = drv->mac_id; + + hns_dsaf_ge_srst_by_port(dsaf_dev, port, 0); + mdelay(10); + hns_dsaf_ge_srst_by_port(dsaf_dev, port, 1); + mdelay(10); + hns_gmac_disable(mac_drv, MAC_COMM_MODE_RX_AND_TX); + hns_gmac_tx_loop_pkt_dis(mac_drv); +} + +void hns_gmac_update_stats(void *mac_drv) +{ + struct mac_hw_stats *hw_stats = NULL; + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + hw_stats = &drv->mac_cb->hw_stats; + + /* RX */ + hw_stats->rx_good_bytes + += dsaf_read_dev(drv, GMAC_RX_OCTETS_TOTAL_OK_REG); + hw_stats->rx_bad_bytes + += dsaf_read_dev(drv, GMAC_RX_OCTETS_BAD_REG); + hw_stats->rx_uc_pkts += dsaf_read_dev(drv, GMAC_RX_UC_PKTS_REG); + hw_stats->rx_mc_pkts += dsaf_read_dev(drv, GMAC_RX_MC_PKTS_REG); + hw_stats->rx_bc_pkts += dsaf_read_dev(drv, GMAC_RX_BC_PKTS_REG); + hw_stats->rx_64bytes + += dsaf_read_dev(drv, GMAC_RX_PKTS_64OCTETS_REG); + hw_stats->rx_65to127 + += dsaf_read_dev(drv, GMAC_RX_PKTS_65TO127OCTETS_REG); + hw_stats->rx_128to255 + += dsaf_read_dev(drv, GMAC_RX_PKTS_128TO255OCTETS_REG); + hw_stats->rx_256to511 + += dsaf_read_dev(drv, GMAC_RX_PKTS_255TO511OCTETS_REG); + hw_stats->rx_512to1023 + += dsaf_read_dev(drv, GMAC_RX_PKTS_512TO1023OCTETS_REG); + hw_stats->rx_1024to1518 + += dsaf_read_dev(drv, GMAC_RX_PKTS_1024TO1518OCTETS_REG); + hw_stats->rx_1519tomax + += dsaf_read_dev(drv, GMAC_RX_PKTS_1519TOMAXOCTETS_REG); + hw_stats->rx_fcs_err += dsaf_read_dev(drv, GMAC_RX_FCS_ERRORS_REG); + hw_stats->rx_vlan_pkts += dsaf_read_dev(drv, GMAC_RX_TAGGED_REG); + hw_stats->rx_data_err += dsaf_read_dev(drv, GMAC_RX_DATA_ERR_REG); + hw_stats->rx_align_err + += dsaf_read_dev(drv, GMAC_RX_ALIGN_ERRORS_REG); + hw_stats->rx_oversize + += dsaf_read_dev(drv, GMAC_RX_LONG_ERRORS_REG); + hw_stats->rx_jabber_err + += dsaf_read_dev(drv, GMAC_RX_JABBER_ERRORS_REG); + hw_stats->rx_pfc_tc0 + += dsaf_read_dev(drv, GMAC_RX_PAUSE_MACCTRL_FRAM_REG); + hw_stats->rx_unknown_ctrl + += dsaf_read_dev(drv, GMAC_RX_UNKNOWN_MACCTRL_FRAM_REG); + hw_stats->rx_long_err + += dsaf_read_dev(drv, GMAC_RX_VERY_LONG_ERR_CNT_REG); + hw_stats->rx_minto64 + += dsaf_read_dev(drv, GMAC_RX_RUNT_ERR_CNT_REG); + hw_stats->rx_under_min + += dsaf_read_dev(drv, GMAC_RX_SHORT_ERR_CNT_REG); + hw_stats->rx_filter_pkts + += dsaf_read_dev(drv, GMAC_RX_FILT_PKT_CNT_REG); + hw_stats->rx_filter_bytes + += dsaf_read_dev(drv, GMAC_RX_OCTETS_TOTAL_FILT_REG); + hw_stats->rx_fifo_overrun_err + += dsaf_read_dev(drv, GMAC_RX_OVERRUN_CNT_REG); + hw_stats->rx_len_err + += dsaf_read_dev(drv, GMAC_RX_LENGTHFIELD_ERR_CNT_REG); + hw_stats->rx_comma_err + += dsaf_read_dev(drv, GMAC_RX_FAIL_COMMA_CNT_REG); + + /* TX */ + hw_stats->tx_good_bytes + += dsaf_read_dev(drv, GMAC_OCTETS_TRANSMITTED_OK_REG); + hw_stats->tx_bad_bytes + += dsaf_read_dev(drv, GMAC_OCTETS_TRANSMITTED_BAD_REG); + hw_stats->tx_uc_pkts += dsaf_read_dev(drv, GMAC_TX_UC_PKTS_REG); + hw_stats->tx_mc_pkts += dsaf_read_dev(drv, GMAC_TX_MC_PKTS_REG); + hw_stats->tx_bc_pkts += dsaf_read_dev(drv, GMAC_TX_BC_PKTS_REG); + hw_stats->tx_64bytes + += dsaf_read_dev(drv, GMAC_TX_PKTS_64OCTETS_REG); + hw_stats->tx_65to127 + += dsaf_read_dev(drv, GMAC_TX_PKTS_65TO127OCTETS_REG); + hw_stats->tx_128to255 + += dsaf_read_dev(drv, GMAC_TX_PKTS_128TO255OCTETS_REG); + hw_stats->tx_256to511 + += dsaf_read_dev(drv, GMAC_TX_PKTS_255TO511OCTETS_REG); + hw_stats->tx_512to1023 + += dsaf_read_dev(drv, GMAC_TX_PKTS_512TO1023OCTETS_REG); + hw_stats->tx_1024to1518 + += dsaf_read_dev(drv, GMAC_TX_PKTS_1024TO1518OCTETS_REG); + hw_stats->tx_1519tomax + += dsaf_read_dev(drv, GMAC_TX_PKTS_1519TOMAXOCTETS_REG); + hw_stats->tx_jabber_err + += dsaf_read_dev(drv, GMAC_TX_EXCESSIVE_LENGTH_DROP_REG); + hw_stats->tx_underrun_err + += dsaf_read_dev(drv, GMAC_TX_UNDERRUN_REG); + hw_stats->tx_vlan += dsaf_read_dev(drv, GMAC_TX_TAGGED_REG); + hw_stats->tx_crc_err += dsaf_read_dev(drv, GMAC_TX_CRC_ERROR_REG); + hw_stats->tx_pfc_tc0 + += dsaf_read_dev(drv, GMAC_TX_PAUSE_FRAMES_REG); +} + +static void hns_gmac_set_mac_addr(void *mac_drv, char *mac_addr) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + if (drv->mac_id >= DSAF_SERVICE_NW_NUM) { + u32 high_val = mac_addr[1] | (mac_addr[0] << 8); + + u32 low_val = mac_addr[5] | (mac_addr[4] << 8) + | (mac_addr[3] << 16) | (mac_addr[2] << 24); + dsaf_write_dev(drv, GMAC_STATION_ADDR_LOW_2_REG, low_val); + dsaf_write_dev(drv, GMAC_STATION_ADDR_HIGH_2_REG, high_val); + } +} + +static int hns_gmac_config_loopback(void *mac_drv, enum hnae_loop loop_mode, + u8 enable) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + switch (loop_mode) { + case MAC_INTERNALLOOP_MAC: + dsaf_set_dev_bit(drv, GMAC_LOOP_REG, GMAC_LP_REG_CF2MI_LP_EN_B, + !!enable); + break; + default: + dev_err(drv->dev, "loop_mode error\n"); + return -EINVAL; + } + + return 0; +} + +static void hns_gmac_config_pad_and_crc(void *mac_drv, u8 newval) +{ + u32 tx_ctrl; + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + tx_ctrl = dsaf_read_dev(drv, GMAC_TRANSMIT_CONTROL_REG); + dsaf_set_bit(tx_ctrl, GMAC_TX_PAD_EN_B, !!newval); + dsaf_set_bit(tx_ctrl, GMAC_TX_CRC_ADD_B, !!newval); + dsaf_write_dev(drv, GMAC_TRANSMIT_CONTROL_REG, tx_ctrl); +} + +static void hns_gmac_get_id(void *mac_drv, u8 *mac_id) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + *mac_id = drv->mac_id; +} + +static void hns_gmac_get_info(void *mac_drv, struct mac_info *mac_info) +{ + enum hns_gmac_duplex_mdoe duplex; + enum hns_port_mode speed; + u32 rx_pause; + u32 tx_pause; + u32 rx; + u32 tx; + u16 fc_tx_timer; + struct hns_gmac_port_mode_cfg port_mode = { GMAC_10M_MII, 0 }; + + hns_gmac_port_mode_get(mac_drv, &port_mode); + mac_info->pad_and_crc_en = port_mode.crc_add && port_mode.pad_enable; + mac_info->auto_neg = port_mode.an_enable; + + hns_gmac_get_tx_auto_pause_frames(mac_drv, &fc_tx_timer); + mac_info->tx_pause_time = fc_tx_timer; + + hns_gmac_get_en(mac_drv, &rx, &tx); + mac_info->port_en = rx && tx; + + hns_gmac_get_duplex_type(mac_drv, &duplex); + mac_info->duplex = duplex; + + hns_gmac_get_port_mode(mac_drv, &speed); + switch (speed) { + case GMAC_10M_SGMII: + mac_info->speed = MAC_SPEED_10; + break; + case GMAC_100M_SGMII: + mac_info->speed = MAC_SPEED_100; + break; + case GMAC_1000M_SGMII: + mac_info->speed = MAC_SPEED_1000; + break; + default: + mac_info->speed = 0; + break; + } + + hns_gmac_get_pausefrm_cfg(mac_drv, &rx_pause, &tx_pause); + mac_info->rx_pause_en = rx_pause; + mac_info->tx_pause_en = tx_pause; +} + +static void hns_gmac_autoneg_stat(void *mac_drv, u32 *enable) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + *enable = dsaf_get_dev_bit(drv, GMAC_TRANSMIT_CONTROL_REG, + GMAC_TX_AN_EN_B); +} + +static void hns_gmac_get_link_status(void *mac_drv, u32 *link_stat) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + *link_stat = dsaf_get_dev_bit(drv, GMAC_AN_NEG_STATE_REG, + GMAC_AN_NEG_STAT_RX_SYNC_OK_B); +} + +static void hns_gmac_get_regs(void *mac_drv, void *data) +{ + u32 *regs = data; + int i; + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + /* base config registers */ + regs[0] = dsaf_read_dev(drv, GMAC_DUPLEX_TYPE_REG); + regs[1] = dsaf_read_dev(drv, GMAC_FD_FC_TYPE_REG); + regs[2] = dsaf_read_dev(drv, GMAC_FC_TX_TIMER_REG); + regs[3] = dsaf_read_dev(drv, GMAC_FD_FC_ADDR_LOW_REG); + regs[4] = dsaf_read_dev(drv, GMAC_FD_FC_ADDR_HIGH_REG); + regs[5] = dsaf_read_dev(drv, GMAC_IPG_TX_TIMER_REG); + regs[6] = dsaf_read_dev(drv, GMAC_PAUSE_THR_REG); + regs[7] = dsaf_read_dev(drv, GMAC_MAX_FRM_SIZE_REG); + regs[8] = dsaf_read_dev(drv, GMAC_PORT_MODE_REG); + regs[9] = dsaf_read_dev(drv, GMAC_PORT_EN_REG); + regs[10] = dsaf_read_dev(drv, GMAC_PAUSE_EN_REG); + regs[11] = dsaf_read_dev(drv, GMAC_SHORT_RUNTS_THR_REG); + regs[12] = dsaf_read_dev(drv, GMAC_AN_NEG_STATE_REG); + regs[13] = dsaf_read_dev(drv, GMAC_TX_LOCAL_PAGE_REG); + regs[14] = dsaf_read_dev(drv, GMAC_TRANSMIT_CONTROL_REG); + regs[15] = dsaf_read_dev(drv, GMAC_REC_FILT_CONTROL_REG); + regs[16] = dsaf_read_dev(drv, GMAC_PTP_CONFIG_REG); + + /* rx static registers */ + regs[17] = dsaf_read_dev(drv, GMAC_RX_OCTETS_TOTAL_OK_REG); + regs[18] = dsaf_read_dev(drv, GMAC_RX_OCTETS_BAD_REG); + regs[19] = dsaf_read_dev(drv, GMAC_RX_UC_PKTS_REG); + regs[20] = dsaf_read_dev(drv, GMAC_RX_MC_PKTS_REG); + regs[21] = dsaf_read_dev(drv, GMAC_RX_BC_PKTS_REG); + regs[22] = dsaf_read_dev(drv, GMAC_RX_PKTS_64OCTETS_REG); + regs[23] = dsaf_read_dev(drv, GMAC_RX_PKTS_65TO127OCTETS_REG); + regs[24] = dsaf_read_dev(drv, GMAC_RX_PKTS_128TO255OCTETS_REG); + regs[25] = dsaf_read_dev(drv, GMAC_RX_PKTS_255TO511OCTETS_REG); + regs[26] = dsaf_read_dev(drv, GMAC_RX_PKTS_512TO1023OCTETS_REG); + regs[27] = dsaf_read_dev(drv, GMAC_RX_PKTS_1024TO1518OCTETS_REG); + regs[28] = dsaf_read_dev(drv, GMAC_RX_PKTS_1519TOMAXOCTETS_REG); + regs[29] = dsaf_read_dev(drv, GMAC_RX_FCS_ERRORS_REG); + regs[30] = dsaf_read_dev(drv, GMAC_RX_TAGGED_REG); + regs[31] = dsaf_read_dev(drv, GMAC_RX_DATA_ERR_REG); + regs[32] = dsaf_read_dev(drv, GMAC_RX_ALIGN_ERRORS_REG); + regs[33] = dsaf_read_dev(drv, GMAC_RX_LONG_ERRORS_REG); + regs[34] = dsaf_read_dev(drv, GMAC_RX_JABBER_ERRORS_REG); + regs[35] = dsaf_read_dev(drv, GMAC_RX_PAUSE_MACCTRL_FRAM_REG); + regs[36] = dsaf_read_dev(drv, GMAC_RX_UNKNOWN_MACCTRL_FRAM_REG); + regs[37] = dsaf_read_dev(drv, GMAC_RX_VERY_LONG_ERR_CNT_REG); + regs[38] = dsaf_read_dev(drv, GMAC_RX_RUNT_ERR_CNT_REG); + regs[39] = dsaf_read_dev(drv, GMAC_RX_SHORT_ERR_CNT_REG); + regs[40] = dsaf_read_dev(drv, GMAC_RX_FILT_PKT_CNT_REG); + regs[41] = dsaf_read_dev(drv, GMAC_RX_OCTETS_TOTAL_FILT_REG); + + /* tx static registers */ + regs[42] = dsaf_read_dev(drv, GMAC_OCTETS_TRANSMITTED_OK_REG); + regs[43] = dsaf_read_dev(drv, GMAC_OCTETS_TRANSMITTED_BAD_REG); + regs[44] = dsaf_read_dev(drv, GMAC_TX_UC_PKTS_REG); + regs[45] = dsaf_read_dev(drv, GMAC_TX_MC_PKTS_REG); + regs[46] = dsaf_read_dev(drv, GMAC_TX_BC_PKTS_REG); + regs[47] = dsaf_read_dev(drv, GMAC_TX_PKTS_64OCTETS_REG); + regs[48] = dsaf_read_dev(drv, GMAC_TX_PKTS_65TO127OCTETS_REG); + regs[49] = dsaf_read_dev(drv, GMAC_TX_PKTS_128TO255OCTETS_REG); + regs[50] = dsaf_read_dev(drv, GMAC_TX_PKTS_255TO511OCTETS_REG); + regs[51] = dsaf_read_dev(drv, GMAC_TX_PKTS_512TO1023OCTETS_REG); + regs[52] = dsaf_read_dev(drv, GMAC_TX_PKTS_1024TO1518OCTETS_REG); + regs[53] = dsaf_read_dev(drv, GMAC_TX_PKTS_1519TOMAXOCTETS_REG); + regs[54] = dsaf_read_dev(drv, GMAC_TX_EXCESSIVE_LENGTH_DROP_REG); + regs[55] = dsaf_read_dev(drv, GMAC_TX_UNDERRUN_REG); + regs[56] = dsaf_read_dev(drv, GMAC_TX_TAGGED_REG); + regs[57] = dsaf_read_dev(drv, GMAC_TX_CRC_ERROR_REG); + regs[58] = dsaf_read_dev(drv, GMAC_TX_PAUSE_FRAMES_REG); + + regs[59] = dsaf_read_dev(drv, GAMC_RX_MAX_FRAME); + regs[60] = dsaf_read_dev(drv, GMAC_LINE_LOOP_BACK_REG); + regs[61] = dsaf_read_dev(drv, GMAC_CF_CRC_STRIP_REG); + regs[62] = dsaf_read_dev(drv, GMAC_MODE_CHANGE_EN_REG); + regs[63] = dsaf_read_dev(drv, GMAC_SIXTEEN_BIT_CNTR_REG); + regs[64] = dsaf_read_dev(drv, GMAC_LD_LINK_COUNTER_REG); + regs[65] = dsaf_read_dev(drv, GMAC_LOOP_REG); + regs[66] = dsaf_read_dev(drv, GMAC_RECV_CONTROL_REG); + regs[67] = dsaf_read_dev(drv, GMAC_VLAN_CODE_REG); + regs[68] = dsaf_read_dev(drv, GMAC_RX_OVERRUN_CNT_REG); + regs[69] = dsaf_read_dev(drv, GMAC_RX_LENGTHFIELD_ERR_CNT_REG); + regs[70] = dsaf_read_dev(drv, GMAC_RX_FAIL_COMMA_CNT_REG); + + regs[71] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_0_REG); + regs[72] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_0_REG); + regs[73] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_1_REG); + regs[74] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_1_REG); + regs[75] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_2_REG); + regs[76] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_2_REG); + regs[77] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_3_REG); + regs[78] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_3_REG); + regs[79] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_4_REG); + regs[80] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_4_REG); + regs[81] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_5_REG); + regs[82] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_5_REG); + regs[83] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_MSK_0_REG); + regs[84] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_MSK_0_REG); + regs[85] = dsaf_read_dev(drv, GMAC_STATION_ADDR_LOW_MSK_1_REG); + regs[86] = dsaf_read_dev(drv, GMAC_STATION_ADDR_HIGH_MSK_1_REG); + regs[87] = dsaf_read_dev(drv, GMAC_MAC_SKIP_LEN_REG); + regs[88] = dsaf_read_dev(drv, GMAC_TX_LOOP_PKT_PRI_REG); + + /* mark end of mac regs */ + for (i = 89; i < 96; i++) + regs[i] = 0xaaaaaaaa; +} + +static void hns_gmac_get_stats(void *mac_drv, u64 *data) +{ + u32 i; + u64 *buf = data; + struct mac_driver *drv = (struct mac_driver *)mac_drv; + struct mac_hw_stats *hw_stats = NULL; + + hw_stats = &drv->mac_cb->hw_stats; + + for (i = 0; i < ARRAY_SIZE(g_gmac_stats_string); i++) { + buf[i] = DSAF_STATS_READ(hw_stats, + g_gmac_stats_string[i].offset); + } +} + +static void hns_gmac_get_strings(u32 stringset, u8 *data) +{ + char *buff = (char *)data; + u32 i; + + if (stringset != ETH_SS_STATS) + return; + + for (i = 0; i < ARRAY_SIZE(g_gmac_stats_string); i++) { + snprintf(buff, ETH_GSTRING_LEN, g_gmac_stats_string[i].desc); + buff = buff + ETH_GSTRING_LEN; + } +} + +static int hns_gmac_get_sset_count(int stringset) +{ + if (stringset == ETH_SS_STATS) + return ARRAY_SIZE(g_gmac_stats_string); + + return 0; +} + +static int hns_gmac_get_regs_count(void) +{ + return ETH_GMAC_DUMP_NUM; +} + +void *hns_gmac_config(struct hns_mac_cb *mac_cb, struct mac_params *mac_param) +{ + struct mac_driver *mac_drv; + + mac_drv = devm_kzalloc(mac_cb->dev, sizeof(*mac_drv), GFP_KERNEL); + if (!mac_drv) + return NULL; + + mac_drv->mac_init = hns_gmac_init; + mac_drv->mac_enable = hns_gmac_enable; + mac_drv->mac_disable = hns_gmac_disable; + mac_drv->mac_free = hns_gmac_free; + mac_drv->adjust_link = hns_gmac_adjust_link; + mac_drv->set_tx_auto_pause_frames = hns_gmac_set_tx_auto_pause_frames; + mac_drv->config_max_frame_length = hns_gmac_config_max_frame_length; + mac_drv->mac_pausefrm_cfg = hns_gmac_pause_frm_cfg; + + mac_drv->mac_id = mac_param->mac_id; + mac_drv->mac_mode = mac_param->mac_mode; + mac_drv->io_base = mac_param->vaddr; + mac_drv->dev = mac_param->dev; + mac_drv->mac_cb = mac_cb; + + mac_drv->set_mac_addr = hns_gmac_set_mac_addr; + mac_drv->set_an_mode = hns_gmac_config_an_mode; + mac_drv->config_loopback = hns_gmac_config_loopback; + mac_drv->config_pad_and_crc = hns_gmac_config_pad_and_crc; + mac_drv->config_half_duplex = hns_gmac_set_duplex_type; + mac_drv->set_rx_ignore_pause_frames = hns_gmac_set_rx_auto_pause_frames; + mac_drv->mac_get_id = hns_gmac_get_id; + mac_drv->get_info = hns_gmac_get_info; + mac_drv->autoneg_stat = hns_gmac_autoneg_stat; + mac_drv->get_pause_enable = hns_gmac_get_pausefrm_cfg; + mac_drv->get_link_status = hns_gmac_get_link_status; + mac_drv->get_regs = hns_gmac_get_regs; + mac_drv->get_regs_count = hns_gmac_get_regs_count; + mac_drv->get_ethtool_stats = hns_gmac_get_stats; + mac_drv->get_sset_count = hns_gmac_get_sset_count; + mac_drv->get_strings = hns_gmac_get_strings; + mac_drv->update_stats = hns_gmac_update_stats; + + return (void *)mac_drv; +} diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h new file mode 100644 index 000000000000..44fe3010dc6d --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _HNS_GMAC_H +#define _HNS_GMAC_H + +#include "hns_dsaf_mac.h" + +enum hns_port_mode { + GMAC_10M_MII = 0, + GMAC_100M_MII, + GMAC_1000M_GMII, + GMAC_10M_RGMII, + GMAC_100M_RGMII, + GMAC_1000M_RGMII, + GMAC_10M_SGMII, + GMAC_100M_SGMII, + GMAC_1000M_SGMII, + GMAC_10000M_SGMII /* 10GE */ +}; + +enum hns_gmac_duplex_mdoe { + GMAC_HALF_DUPLEX_MODE = 0, + GMAC_FULL_DUPLEX_MODE +}; + +struct hns_gmac_port_mode_cfg { + enum hns_port_mode port_mode; + u32 max_frm_size; + u32 short_runts_thr; + u32 pad_enable; + u32 crc_add; + u32 an_enable; /*auto-nego enable */ + u32 runt_pkt_en; + u32 strip_pad_en; +}; + +#define ETH_GMAC_DUMP_NUM 96 +#endif /* __HNS_GMAC_H__ */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c new file mode 100644 index 000000000000..a8bd27b7f439 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -0,0 +1,900 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hns_dsaf_misc.h" +#include "hns_dsaf_main.h" +#include "hns_dsaf_rcb.h" + +#define MAC_EN_FLAG_V 0xada0328 + +static const u16 mac_phy_to_speed[] = { + [PHY_INTERFACE_MODE_MII] = MAC_SPEED_100, + [PHY_INTERFACE_MODE_GMII] = MAC_SPEED_1000, + [PHY_INTERFACE_MODE_SGMII] = MAC_SPEED_1000, + [PHY_INTERFACE_MODE_TBI] = MAC_SPEED_1000, + [PHY_INTERFACE_MODE_RMII] = MAC_SPEED_100, + [PHY_INTERFACE_MODE_RGMII] = MAC_SPEED_1000, + [PHY_INTERFACE_MODE_RGMII_ID] = MAC_SPEED_1000, + [PHY_INTERFACE_MODE_RGMII_RXID] = MAC_SPEED_1000, + [PHY_INTERFACE_MODE_RGMII_TXID] = MAC_SPEED_1000, + [PHY_INTERFACE_MODE_RTBI] = MAC_SPEED_1000, + [PHY_INTERFACE_MODE_XGMII] = MAC_SPEED_10000 +}; + +static const enum mac_mode g_mac_mode_100[] = { + [PHY_INTERFACE_MODE_MII] = MAC_MODE_MII_100, + [PHY_INTERFACE_MODE_RMII] = MAC_MODE_RMII_100 +}; + +static const enum mac_mode g_mac_mode_1000[] = { + [PHY_INTERFACE_MODE_GMII] = MAC_MODE_GMII_1000, + [PHY_INTERFACE_MODE_SGMII] = MAC_MODE_SGMII_1000, + [PHY_INTERFACE_MODE_TBI] = MAC_MODE_TBI_1000, + [PHY_INTERFACE_MODE_RGMII] = MAC_MODE_RGMII_1000, + [PHY_INTERFACE_MODE_RGMII_ID] = MAC_MODE_RGMII_1000, + [PHY_INTERFACE_MODE_RGMII_RXID] = MAC_MODE_RGMII_1000, + [PHY_INTERFACE_MODE_RGMII_TXID] = MAC_MODE_RGMII_1000, + [PHY_INTERFACE_MODE_RTBI] = MAC_MODE_RTBI_1000 +}; + +static enum mac_mode hns_mac_dev_to_enet_if(const struct hns_mac_cb *mac_cb) +{ + switch (mac_cb->max_speed) { + case MAC_SPEED_100: + return g_mac_mode_100[mac_cb->phy_if]; + case MAC_SPEED_1000: + return g_mac_mode_1000[mac_cb->phy_if]; + case MAC_SPEED_10000: + return MAC_MODE_XGMII_10000; + default: + return MAC_MODE_MII_100; + } +} + +static enum mac_mode hns_get_enet_interface(const struct hns_mac_cb *mac_cb) +{ + switch (mac_cb->max_speed) { + case MAC_SPEED_100: + return g_mac_mode_100[mac_cb->phy_if]; + case MAC_SPEED_1000: + return g_mac_mode_1000[mac_cb->phy_if]; + case MAC_SPEED_10000: + return MAC_MODE_XGMII_10000; + default: + return MAC_MODE_MII_100; + } +} + +int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int *sfp_prsnt) +{ + if (!mac_cb->cpld_vaddr) + return -ENODEV; + + *sfp_prsnt = !dsaf_read_b((u64)mac_cb->cpld_vaddr + + MAC_SFP_PORT_OFFSET); + + return 0; +} + +void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status) +{ + struct mac_driver *mac_ctrl_drv; + int ret, sfp_prsnt; + + mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + if (mac_ctrl_drv->get_link_status) + mac_ctrl_drv->get_link_status(mac_ctrl_drv, link_status); + else + *link_status = 0; + + ret = hns_mac_get_sfp_prsnt(mac_cb, &sfp_prsnt); + if (!ret) + *link_status = *link_status && sfp_prsnt; + + mac_cb->link = *link_status; +} + +int hns_mac_get_port_info(struct hns_mac_cb *mac_cb, + u8 *auto_neg, u16 *speed, u8 *duplex) +{ + struct mac_driver *mac_ctrl_drv; + struct mac_info info; + + mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + if (!mac_ctrl_drv->get_info) + return -ENODEV; + + mac_ctrl_drv->get_info(mac_ctrl_drv, &info); + if (auto_neg) + *auto_neg = info.auto_neg; + if (speed) + *speed = info.speed; + if (duplex) + *duplex = info.duplex; + + return 0; +} + +void hns_mac_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex) +{ + int ret; + struct mac_driver *mac_ctrl_drv; + + mac_ctrl_drv = (struct mac_driver *)(mac_cb->priv.mac); + + mac_cb->speed = speed; + mac_cb->half_duplex = !duplex; + mac_ctrl_drv->mac_mode = hns_mac_dev_to_enet_if(mac_cb); + + if (mac_ctrl_drv->adjust_link) { + ret = mac_ctrl_drv->adjust_link(mac_ctrl_drv, + (enum mac_speed)speed, duplex); + if (ret) { + dev_err(mac_cb->dev, + "adjust_link failed,%s mac%d ret = %#x!\n", + mac_cb->dsaf_dev->ae_dev.name, + mac_cb->mac_id, ret); + return; + } + } +} + +/** + *hns_mac_get_inner_port_num - get mac table inner port number + *@mac_cb: mac device + *@vmid: vm id + *@port_num:port number + * + */ +static int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb, + u8 vmid, u8 *port_num) +{ + u8 tmp_port; + u32 comm_idx; + + if (mac_cb->dsaf_dev->dsaf_mode <= DSAF_MODE_ENABLE) { + if (mac_cb->mac_id != DSAF_MAX_PORT_NUM_PER_CHIP) { + dev_err(mac_cb->dev, + "input invalid,%s mac%d vmid%d !\n", + mac_cb->dsaf_dev->ae_dev.name, + mac_cb->mac_id, vmid); + return -EINVAL; + } + } else if (mac_cb->dsaf_dev->dsaf_mode < DSAF_MODE_MAX) { + if (mac_cb->mac_id <= DSAF_MAX_PORT_NUM_PER_CHIP) { + dev_err(mac_cb->dev, + "input invalid,%s mac%d vmid%d!\n", + mac_cb->dsaf_dev->ae_dev.name, + mac_cb->mac_id, vmid); + return -EINVAL; + } + } else { + dev_err(mac_cb->dev, "dsaf mode invalid,%s mac%d!\n", + mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id); + return -EINVAL; + } + + comm_idx = hns_dsaf_get_comm_idx_by_port(mac_cb->mac_id); + + if (vmid >= mac_cb->dsaf_dev->rcb_common[comm_idx]->max_vfn) { + dev_err(mac_cb->dev, "input invalid,%s mac%d vmid%d !\n", + mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id, vmid); + return -EINVAL; + } + + switch (mac_cb->dsaf_dev->dsaf_mode) { + case DSAF_MODE_ENABLE_FIX: + tmp_port = 0; + break; + case DSAF_MODE_DISABLE_FIX: + tmp_port = 0; + break; + case DSAF_MODE_ENABLE_0VM: + case DSAF_MODE_ENABLE_8VM: + case DSAF_MODE_ENABLE_16VM: + case DSAF_MODE_ENABLE_32VM: + case DSAF_MODE_ENABLE_128VM: + case DSAF_MODE_DISABLE_2PORT_8VM: + case DSAF_MODE_DISABLE_2PORT_16VM: + case DSAF_MODE_DISABLE_2PORT_64VM: + case DSAF_MODE_DISABLE_6PORT_0VM: + case DSAF_MODE_DISABLE_6PORT_2VM: + case DSAF_MODE_DISABLE_6PORT_4VM: + case DSAF_MODE_DISABLE_6PORT_16VM: + tmp_port = vmid; + break; + default: + dev_err(mac_cb->dev, "dsaf mode invalid,%s mac%d!\n", + mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id); + return -EINVAL; + } + tmp_port += DSAF_BASE_INNER_PORT_NUM; + + *port_num = tmp_port; + + return 0; +} + +/** + *hns_mac_get_inner_port_num - change vf mac address + *@mac_cb: mac device + *@vmid: vmid + *@addr:mac address + */ +int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb, + u32 vmid, char *addr) +{ + int ret; + struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; + struct dsaf_drv_mac_single_dest_entry mac_entry; + struct mac_entry_idx *old_entry; + + old_entry = &mac_cb->addr_entry_idx[vmid]; + if (dsaf_dev) { + memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); + mac_entry.in_vlan_id = old_entry->vlan_id; + mac_entry.in_port_num = mac_cb->mac_id; + ret = hns_mac_get_inner_port_num(mac_cb, (u8)vmid, + &mac_entry.port_num); + if (ret) + return ret; + + if ((old_entry->valid != 0) && + (memcmp(old_entry->addr, + addr, sizeof(mac_entry.addr)) != 0)) { + ret = hns_dsaf_del_mac_entry(dsaf_dev, + old_entry->vlan_id, + mac_cb->mac_id, + old_entry->addr); + if (ret) + return ret; + } + + ret = hns_dsaf_set_mac_uc_entry(dsaf_dev, &mac_entry); + if (ret) + return ret; + } + + if ((mac_ctrl_drv->set_mac_addr) && (vmid == 0)) + mac_ctrl_drv->set_mac_addr(mac_cb->priv.mac, addr); + + memcpy(old_entry->addr, addr, sizeof(old_entry->addr)); + old_entry->valid = 1; + return 0; +} + +int hns_mac_set_multi(struct hns_mac_cb *mac_cb, + u32 port_num, char *addr, u8 en) +{ + int ret; + struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; + struct dsaf_drv_mac_single_dest_entry mac_entry; + + if (dsaf_dev && addr) { + memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); + mac_entry.in_vlan_id = 0;/*vlan_id;*/ + mac_entry.in_port_num = mac_cb->mac_id; + mac_entry.port_num = port_num; + + if (en == DISABLE) + ret = hns_dsaf_del_mac_mc_port(dsaf_dev, &mac_entry); + else + ret = hns_dsaf_add_mac_mc_port(dsaf_dev, &mac_entry); + if (ret) { + dev_err(dsaf_dev->dev, + "set mac mc port failed,%s mac%d ret = %#x!\n", + mac_cb->dsaf_dev->ae_dev.name, + mac_cb->mac_id, ret); + return ret; + } + } + + return 0; +} + +/** + *hns_mac_del_mac - delete mac address into dsaf table,can't delete the same + * address twice + *@net_dev: net device + *@vfn : vf lan + *@mac : mac address + *return status + */ +int hns_mac_del_mac(struct hns_mac_cb *mac_cb, u32 vfn, char *mac) +{ + struct mac_entry_idx *old_mac; + struct dsaf_device *dsaf_dev; + u32 ret; + + dsaf_dev = mac_cb->dsaf_dev; + + if (vfn < DSAF_MAX_VM_NUM) { + old_mac = &mac_cb->addr_entry_idx[vfn]; + } else { + dev_err(mac_cb->dev, + "vf queue is too large,%s mac%d queue = %#x!\n", + mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id, vfn); + return -EINVAL; + } + + if (dsaf_dev) { + ret = hns_dsaf_del_mac_entry(dsaf_dev, old_mac->vlan_id, + mac_cb->mac_id, old_mac->addr); + if (ret) + return ret; + + if (memcmp(old_mac->addr, mac, sizeof(old_mac->addr)) == 0) + old_mac->valid = 0; + } + + return 0; +} + +static void hns_mac_param_get(struct mac_params *param, + struct hns_mac_cb *mac_cb) +{ + param->vaddr = (void *)mac_cb->vaddr; + param->mac_mode = hns_get_enet_interface(mac_cb); + memcpy(param->addr, mac_cb->addr_entry_idx[0].addr, + MAC_NUM_OCTETS_PER_ADDR); + param->mac_id = mac_cb->mac_id; + param->dev = mac_cb->dev; +} + +/** + *hns_mac_queue_config_bc_en - set broadcast rx&tx enable + *@mac_cb: mac device + *@queue: queue number + *@en:enable + *retuen 0 - success , negative --fail + */ +static int hns_mac_port_config_bc_en(struct hns_mac_cb *mac_cb, + u32 port_num, u16 vlan_id, u8 en) +{ + int ret; + struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; + u8 addr[MAC_NUM_OCTETS_PER_ADDR] + = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + struct dsaf_drv_mac_single_dest_entry mac_entry; + + /* directy return ok in debug network mode */ + if (mac_cb->mac_type == HNAE_PORT_DEBUG) + return 0; + + if (dsaf_dev) { + memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); + mac_entry.in_vlan_id = vlan_id; + mac_entry.in_port_num = mac_cb->mac_id; + mac_entry.port_num = port_num; + + if (en == DISABLE) + ret = hns_dsaf_del_mac_mc_port(dsaf_dev, &mac_entry); + else + ret = hns_dsaf_add_mac_mc_port(dsaf_dev, &mac_entry); + return ret; + } + + return 0; +} + +/** + *hns_mac_vm_config_bc_en - set broadcast rx&tx enable + *@mac_cb: mac device + *@vmid: vm id + *@en:enable + *retuen 0 - success , negative --fail + */ +int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vmid, u8 en) +{ + int ret; + struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; + u8 port_num; + u8 addr[MAC_NUM_OCTETS_PER_ADDR] + = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + struct mac_entry_idx *uc_mac_entry; + struct dsaf_drv_mac_single_dest_entry mac_entry; + + if (mac_cb->mac_type == HNAE_PORT_DEBUG) + return 0; + + uc_mac_entry = &mac_cb->addr_entry_idx[vmid]; + + if (dsaf_dev) { + memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); + mac_entry.in_vlan_id = uc_mac_entry->vlan_id; + mac_entry.in_port_num = mac_cb->mac_id; + ret = hns_mac_get_inner_port_num(mac_cb, vmid, &port_num); + if (ret) + return ret; + mac_entry.port_num = port_num; + + if (en == DISABLE) + ret = hns_dsaf_del_mac_mc_port(dsaf_dev, &mac_entry); + else + ret = hns_dsaf_add_mac_mc_port(dsaf_dev, &mac_entry); + return ret; + } + + return 0; +} + +void hns_mac_reset(struct hns_mac_cb *mac_cb) +{ + struct mac_driver *drv; + + drv = hns_mac_get_drv(mac_cb); + + drv->mac_init(drv); + + if (drv->config_max_frame_length) + drv->config_max_frame_length(drv, mac_cb->max_frm); + + if (drv->set_tx_auto_pause_frames) + drv->set_tx_auto_pause_frames(drv, mac_cb->tx_pause_frm_time); + + if (drv->set_an_mode) + drv->set_an_mode(drv, 1); + + if (drv->mac_pausefrm_cfg) { + if (mac_cb->mac_type == HNAE_PORT_DEBUG) + drv->mac_pausefrm_cfg(drv, 0, 0); + else /* mac rx must disable, dsaf pfc close instead of it*/ + drv->mac_pausefrm_cfg(drv, 0, 1); + } +} + +int hns_mac_set_mtu(struct hns_mac_cb *mac_cb, u32 new_mtu) +{ + struct mac_driver *drv = hns_mac_get_drv(mac_cb); + u32 buf_size = mac_cb->dsaf_dev->buf_size; + u32 new_frm = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; + + if ((new_mtu < MAC_MIN_MTU) || (new_frm > MAC_MAX_MTU) || + (new_frm > HNS_RCB_RING_MAX_BD_PER_PKT * buf_size)) + return -EINVAL; + + if (!drv->config_max_frame_length) + return -ECHILD; + + /* adjust max frame to be at least the size of a standard frame */ + if (new_frm < (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)) + new_frm = (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN); + + drv->config_max_frame_length(drv, new_frm); + + mac_cb->max_frm = new_frm; + + return 0; +} + +void hns_mac_start(struct hns_mac_cb *mac_cb) +{ + struct mac_driver *mac_drv = hns_mac_get_drv(mac_cb); + + /* for virt */ + if (mac_drv->mac_en_flg == MAC_EN_FLAG_V) { + /*plus 1 when the virtual mac has been enabled */ + mac_drv->virt_dev_num += 1; + return; + } + + if (mac_drv->mac_enable) { + mac_drv->mac_enable(mac_cb->priv.mac, MAC_COMM_MODE_RX_AND_TX); + mac_drv->mac_en_flg = MAC_EN_FLAG_V; + } +} + +void hns_mac_stop(struct hns_mac_cb *mac_cb) +{ + struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + /*modified for virtualization */ + if (mac_ctrl_drv->virt_dev_num > 0) { + mac_ctrl_drv->virt_dev_num -= 1; + if (mac_ctrl_drv->virt_dev_num > 0) + return; + } + + if (mac_ctrl_drv->mac_disable) + mac_ctrl_drv->mac_disable(mac_cb->priv.mac, + MAC_COMM_MODE_RX_AND_TX); + + mac_ctrl_drv->mac_en_flg = 0; + mac_cb->link = 0; + cpld_led_reset(mac_cb); +} + +/** + * hns_mac_get_autoneg - get auto autonegotiation + * @mac_cb: mac control block + * @enable: enable or not + * retuen 0 - success , negative --fail + */ +void hns_mac_get_autoneg(struct hns_mac_cb *mac_cb, u32 *auto_neg) +{ + struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + if (mac_ctrl_drv->autoneg_stat) + mac_ctrl_drv->autoneg_stat(mac_ctrl_drv, auto_neg); + else + *auto_neg = 0; +} + +/** + * hns_mac_get_pauseparam - set rx & tx pause parameter + * @mac_cb: mac control block + * @rx_en: rx enable status + * @tx_en: tx enable status + * retuen 0 - success , negative --fail + */ +void hns_mac_get_pauseparam(struct hns_mac_cb *mac_cb, u32 *rx_en, u32 *tx_en) +{ + struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + if (mac_ctrl_drv->get_pause_enable) { + mac_ctrl_drv->get_pause_enable(mac_ctrl_drv, rx_en, tx_en); + } else { + *rx_en = 0; + *tx_en = 0; + } + + /* Due to the chip defect, the service mac's rx pause CAN'T be enabled. + * We set the rx pause frm always be true (1), because DSAF deals with + * the rx pause frm instead of service mac. After all, we still support + * rx pause frm. + */ + if (mac_cb->mac_type == HNAE_PORT_SERVICE) + *rx_en = 1; +} + +/** + * hns_mac_set_autoneg - set auto autonegotiation + * @mac_cb: mac control block + * @enable: enable or not + * retuen 0 - success , negative --fail + */ +int hns_mac_set_autoneg(struct hns_mac_cb *mac_cb, u8 enable) +{ + struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + if (mac_cb->phy_if == PHY_INTERFACE_MODE_XGMII && enable) { + dev_err(mac_cb->dev, "enable autoneg is not allowed!"); + return -ENOTSUPP; + } + + if (mac_ctrl_drv->set_an_mode) + mac_ctrl_drv->set_an_mode(mac_ctrl_drv, enable); + + return 0; +} + +/** + * hns_mac_set_autoneg - set rx & tx pause parameter + * @mac_cb: mac control block + * @rx_en: rx enable or not + * @tx_en: tx enable or not + * return 0 - success , negative --fail + */ +int hns_mac_set_pauseparam(struct hns_mac_cb *mac_cb, u32 rx_en, u32 tx_en) +{ + struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + if (mac_cb->mac_type == HNAE_PORT_SERVICE) { + if (!rx_en) { + dev_err(mac_cb->dev, "disable rx_pause is not allowed!"); + return -EINVAL; + } + } else if (mac_cb->mac_type == HNAE_PORT_DEBUG) { + if (tx_en || rx_en) { + dev_err(mac_cb->dev, "enable tx_pause or enable rx_pause are not allowed!"); + return -EINVAL; + } + } else { + dev_err(mac_cb->dev, "Unsupport this operation!"); + return -EINVAL; + } + + if (mac_ctrl_drv->mac_pausefrm_cfg) + mac_ctrl_drv->mac_pausefrm_cfg(mac_ctrl_drv, rx_en, tx_en); + + return 0; +} + +/** + * hns_mac_init_ex - mac init + * @mac_cb: mac control block + * retuen 0 - success , negative --fail + */ +static int hns_mac_init_ex(struct hns_mac_cb *mac_cb) +{ + int ret; + struct mac_params param; + struct mac_driver *drv; + + hns_dsaf_fix_mac_mode(mac_cb); + + memset(¶m, 0, sizeof(struct mac_params)); + hns_mac_param_get(¶m, mac_cb); + + if (MAC_SPEED_FROM_MODE(param.mac_mode) < MAC_SPEED_10000) + drv = (struct mac_driver *)hns_gmac_config(mac_cb, ¶m); + else + drv = (struct mac_driver *)hns_xgmac_config(mac_cb, ¶m); + + if (!drv) + return -ENOMEM; + + mac_cb->priv.mac = (void *)drv; + hns_mac_reset(mac_cb); + + hns_mac_adjust_link(mac_cb, mac_cb->speed, !mac_cb->half_duplex); + + ret = hns_mac_port_config_bc_en(mac_cb, mac_cb->mac_id, 0, ENABLE); + if (ret) + goto free_mac_drv; + + return 0; + +free_mac_drv: + drv->mac_free(mac_cb->priv.mac); + mac_cb->priv.mac = NULL; + + return ret; +} + +/** + *mac_free_dev - get mac information from device node + *@mac_cb: mac device + *@np:device node + *@mac_mode_idx:mac mode index + */ +static void hns_mac_get_info(struct hns_mac_cb *mac_cb, + struct device_node *np, u32 mac_mode_idx) +{ + mac_cb->link = false; + mac_cb->half_duplex = false; + mac_cb->speed = mac_phy_to_speed[mac_cb->phy_if]; + mac_cb->max_speed = mac_cb->speed; + + if (mac_cb->phy_if == PHY_INTERFACE_MODE_SGMII) { + mac_cb->if_support = MAC_GMAC_SUPPORTED; + mac_cb->if_support |= SUPPORTED_1000baseT_Full; + } else if (mac_cb->phy_if == PHY_INTERFACE_MODE_XGMII) { + mac_cb->if_support = SUPPORTED_10000baseR_FEC; + mac_cb->if_support |= SUPPORTED_10000baseKR_Full; + } + + mac_cb->max_frm = MAC_DEFAULT_MTU; + mac_cb->tx_pause_frm_time = MAC_DEFAULT_PAUSE_TIME; + + /* Get the rest of the PHY information */ + mac_cb->phy_node = of_parse_phandle(np, "phy-handle", mac_cb->mac_id); + if (mac_cb->phy_node) + dev_dbg(mac_cb->dev, "mac%d phy_node: %s\n", + mac_cb->mac_id, mac_cb->phy_node->name); +} + +/** + * hns_mac_get_mode - get mac mode + * @phy_if: phy interface + * retuen 0 - gmac, 1 - xgmac , negative --fail + */ +static int hns_mac_get_mode(phy_interface_t phy_if) +{ + switch (phy_if) { + case PHY_INTERFACE_MODE_SGMII: + return MAC_GMAC_IDX; + case PHY_INTERFACE_MODE_XGMII: + return MAC_XGMAC_IDX; + default: + return -EINVAL; + } +} + +u8 __iomem *hns_mac_get_vaddr(struct dsaf_device *dsaf_dev, + struct hns_mac_cb *mac_cb, u32 mac_mode_idx) +{ + u8 __iomem *base = dsaf_dev->io_base; + int mac_id = mac_cb->mac_id; + + if (mac_cb->mac_type == HNAE_PORT_SERVICE) + return base + 0x40000 + mac_id * 0x4000 - + mac_mode_idx * 0x20000; + else + return mac_cb->serdes_vaddr + 0x1000 + + (mac_id - DSAF_SERVICE_PORT_NUM_PER_DSAF) * 0x100000; +} + +/** + * hns_mac_get_cfg - get mac cfg from dtb or acpi table + * @dsaf_dev: dsa fabric device struct pointer + * @mac_idx: mac index + * retuen 0 - success , negative --fail + */ +int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, int mac_idx) +{ + int ret; + u32 mac_mode_idx; + struct hns_mac_cb *mac_cb = &dsaf_dev->mac_cb[mac_idx]; + + mac_cb->dsaf_dev = dsaf_dev; + mac_cb->dev = dsaf_dev->dev; + mac_cb->mac_id = mac_idx; + + mac_cb->sys_ctl_vaddr = dsaf_dev->sc_base; + mac_cb->serdes_vaddr = dsaf_dev->sds_base; + + if (dsaf_dev->cpld_base && + mac_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF) + mac_cb->cpld_vaddr = dsaf_dev->cpld_base + + mac_cb->mac_id * CPLD_ADDR_PORT_OFFSET; + mac_cb->sfp_prsnt = 0; + mac_cb->txpkt_for_led = 0; + mac_cb->rxpkt_for_led = 0; + + if (mac_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF) + mac_cb->mac_type = HNAE_PORT_SERVICE; + else + mac_cb->mac_type = HNAE_PORT_DEBUG; + + mac_cb->phy_if = hns_mac_get_phy_if(mac_cb); + + ret = hns_mac_get_mode(mac_cb->phy_if); + if (ret < 0) { + dev_err(dsaf_dev->dev, + "hns_mac_get_mode failed,mac%d ret = %#x!\n", + mac_cb->mac_id, ret); + return ret; + } + mac_mode_idx = (u32)ret; + + hns_mac_get_info(mac_cb, mac_cb->dev->of_node, mac_mode_idx); + + mac_cb->vaddr = hns_mac_get_vaddr(dsaf_dev, mac_cb, mac_mode_idx); + + return 0; +} + +/** + * hns_mac_init - init mac + * @dsaf_dev: dsa fabric device struct pointer + * retuen 0 - success , negative --fail + */ +int hns_mac_init(struct dsaf_device *dsaf_dev) +{ + int i; + int ret; + size_t size; + struct hns_mac_cb *mac_cb; + + size = sizeof(struct hns_mac_cb) * DSAF_MAX_PORT_NUM_PER_CHIP; + dsaf_dev->mac_cb = devm_kzalloc(dsaf_dev->dev, size, GFP_KERNEL); + if (!dsaf_dev->mac_cb) + return -ENOMEM; + + for (i = 0; i < DSAF_MAX_PORT_NUM_PER_CHIP; i++) { + ret = hns_mac_get_cfg(dsaf_dev, i); + if (ret) + goto free_mac_cb; + + mac_cb = &dsaf_dev->mac_cb[i]; + ret = hns_mac_init_ex(mac_cb); + if (ret) + goto free_mac_cb; + } + + return 0; + +free_mac_cb: + dsaf_dev->mac_cb = NULL; + + return ret; +} + +void hns_mac_uninit(struct dsaf_device *dsaf_dev) +{ + cpld_led_reset(dsaf_dev->mac_cb); + dsaf_dev->mac_cb = NULL; +} + +int hns_mac_config_mac_loopback(struct hns_mac_cb *mac_cb, + enum hnae_loop loop, int en) +{ + int ret; + struct mac_driver *drv = hns_mac_get_drv(mac_cb); + + if (drv->config_loopback) + ret = drv->config_loopback(drv, loop, en); + else + ret = -ENOTSUPP; + + return ret; +} + +void hns_mac_update_stats(struct hns_mac_cb *mac_cb) +{ + struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + mac_ctrl_drv->update_stats(mac_ctrl_drv); +} + +void hns_mac_get_stats(struct hns_mac_cb *mac_cb, u64 *data) +{ + struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + mac_ctrl_drv->get_ethtool_stats(mac_ctrl_drv, data); +} + +void hns_mac_get_strings(struct hns_mac_cb *mac_cb, + int stringset, u8 *data) +{ + struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + mac_ctrl_drv->get_strings(stringset, data); +} + +int hns_mac_get_sset_count(struct hns_mac_cb *mac_cb, int stringset) +{ + struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + return mac_ctrl_drv->get_sset_count(stringset); +} + +int hns_mac_get_regs_count(struct hns_mac_cb *mac_cb) +{ + struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + return mac_ctrl_drv->get_regs_count(); +} + +void hns_mac_get_regs(struct hns_mac_cb *mac_cb, void *data) +{ + struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + + mac_ctrl_drv->get_regs(mac_ctrl_drv, data); +} + +void hns_set_led_opt(struct hns_mac_cb *mac_cb) +{ + int nic_data = 0; + int txpkts, rxpkts; + + txpkts = mac_cb->txpkt_for_led - mac_cb->hw_stats.tx_good_pkts; + rxpkts = mac_cb->rxpkt_for_led - mac_cb->hw_stats.rx_good_pkts; + if (txpkts || rxpkts) + nic_data = 1; + else + nic_data = 0; + mac_cb->txpkt_for_led = mac_cb->hw_stats.tx_good_pkts; + mac_cb->rxpkt_for_led = mac_cb->hw_stats.rx_good_pkts; + hns_cpld_set_led(mac_cb, (int)mac_cb->link, + mac_cb->speed, nic_data); +} + +int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb, + enum hnae_led_state status) +{ + if (!mac_cb || !mac_cb->cpld_vaddr) + return 0; + + return cpld_set_led_id(mac_cb, status); +} diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h new file mode 100644 index 000000000000..7da95a7581f9 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _HNS_DSAF_MAC_H +#define _HNS_DSAF_MAC_H + +#include +#include +#include +#include "hns_dsaf_main.h" + +struct dsaf_device; + +#define MAC_GMAC_SUPPORTED \ + (SUPPORTED_10baseT_Half \ + | SUPPORTED_10baseT_Full \ + | SUPPORTED_100baseT_Half \ + | SUPPORTED_100baseT_Full \ + | SUPPORTED_Autoneg) + +#define MAC_DEFAULT_MTU (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN + ETH_DATA_LEN) +#define MAC_MAX_MTU 9600 +#define MAC_MIN_MTU 68 + +#define MAC_DEFAULT_PAUSE_TIME 0xff + +#define MAC_GMAC_IDX 0 +#define MAC_XGMAC_IDX 1 + +#define ETH_STATIC_REG 1 +#define ETH_DUMP_REG 5 +/* check mac addr broadcast */ +#define MAC_IS_BROADCAST(p) ((*(p) == 0xff) && (*((p) + 1) == 0xff) && \ + (*((p) + 2) == 0xff) && (*((p) + 3) == 0xff) && \ + (*((p) + 4) == 0xff) && (*((p) + 5) == 0xff)) + +/* check mac addr is 01-00-5e-xx-xx-xx*/ +#define MAC_IS_L3_MULTICAST(p) ((*((p) + 0) == 0x01) && \ + (*((p) + 1) == 0x00) && \ + (*((p) + 2) == 0x5e)) + +/*check the mac addr is 0 in all bit*/ +#define MAC_IS_ALL_ZEROS(p) ((*(p) == 0) && (*((p) + 1) == 0) && \ + (*((p) + 2) == 0) && (*((p) + 3) == 0) && \ + (*((p) + 4) == 0) && (*((p) + 5) == 0)) + +/*check mac addr multicast*/ +#define MAC_IS_MULTICAST(p) ((*((u8 *)((p) + 0)) & 0x01) ? (1) : (0)) + +/**< Number of octets (8-bit bytes) in an ethernet address */ +#define MAC_NUM_OCTETS_PER_ADDR 6 + +struct mac_priv { + void *mac; +}; + +/* net speed */ +enum mac_speed { + MAC_SPEED_10 = 10, /**< 10 Mbps */ + MAC_SPEED_100 = 100, /**< 100 Mbps */ + MAC_SPEED_1000 = 1000, /**< 1000 Mbps = 1 Gbps */ + MAC_SPEED_10000 = 10000 /**< 10000 Mbps = 10 Gbps */ +}; + +/*mac interface keyword */ +enum mac_intf { + MAC_IF_NONE = 0x00000000, /**< interface not invalid */ + MAC_IF_MII = 0x00010000, /**< MII interface */ + MAC_IF_RMII = 0x00020000, /**< RMII interface */ + MAC_IF_SMII = 0x00030000, /**< SMII interface */ + MAC_IF_GMII = 0x00040000, /**< GMII interface */ + MAC_IF_RGMII = 0x00050000, /**< RGMII interface */ + MAC_IF_TBI = 0x00060000, /**< TBI interface */ + MAC_IF_RTBI = 0x00070000, /**< RTBI interface */ + MAC_IF_SGMII = 0x00080000, /**< SGMII interface */ + MAC_IF_XGMII = 0x00090000, /**< XGMII interface */ + MAC_IF_QSGMII = 0x000a0000 /**< QSGMII interface */ +}; + +/*mac mode */ +enum mac_mode { + /**< Invalid Ethernet mode */ + MAC_MODE_INVALID = 0, + /**< 10 Mbps MII */ + MAC_MODE_MII_10 = (MAC_IF_MII | MAC_SPEED_10), + /**< 100 Mbps MII */ + MAC_MODE_MII_100 = (MAC_IF_MII | MAC_SPEED_100), + /**< 10 Mbps RMII */ + MAC_MODE_RMII_10 = (MAC_IF_RMII | MAC_SPEED_10), + /**< 100 Mbps RMII */ + MAC_MODE_RMII_100 = (MAC_IF_RMII | MAC_SPEED_100), + /**< 10 Mbps SMII */ + MAC_MODE_SMII_10 = (MAC_IF_SMII | MAC_SPEED_10), + /**< 100 Mbps SMII */ + MAC_MODE_SMII_100 = (MAC_IF_SMII | MAC_SPEED_100), + /**< 1000 Mbps GMII */ + MAC_MODE_GMII_1000 = (MAC_IF_GMII | MAC_SPEED_1000), + /**< 10 Mbps RGMII */ + MAC_MODE_RGMII_10 = (MAC_IF_RGMII | MAC_SPEED_10), + /**< 100 Mbps RGMII */ + MAC_MODE_RGMII_100 = (MAC_IF_RGMII | MAC_SPEED_100), + /**< 1000 Mbps RGMII */ + MAC_MODE_RGMII_1000 = (MAC_IF_RGMII | MAC_SPEED_1000), + /**< 1000 Mbps TBI */ + MAC_MODE_TBI_1000 = (MAC_IF_TBI | MAC_SPEED_1000), + /**< 1000 Mbps RTBI */ + MAC_MODE_RTBI_1000 = (MAC_IF_RTBI | MAC_SPEED_1000), + /**< 10 Mbps SGMII */ + MAC_MODE_SGMII_10 = (MAC_IF_SGMII | MAC_SPEED_10), + /**< 100 Mbps SGMII */ + MAC_MODE_SGMII_100 = (MAC_IF_SGMII | MAC_SPEED_100), + /**< 1000 Mbps SGMII */ + MAC_MODE_SGMII_1000 = (MAC_IF_SGMII | MAC_SPEED_1000), + /**< 10000 Mbps XGMII */ + MAC_MODE_XGMII_10000 = (MAC_IF_XGMII | MAC_SPEED_10000), + /**< 1000 Mbps QSGMII */ + MAC_MODE_QSGMII_1000 = (MAC_IF_QSGMII | MAC_SPEED_1000) +}; + +/*mac communicate mode*/ +enum mac_commom_mode { + MAC_COMM_MODE_NONE = 0, /**< No transmit/receive communication */ + MAC_COMM_MODE_RX = 1, /**< Only receive communication */ + MAC_COMM_MODE_TX = 2, /**< Only transmit communication */ + MAC_COMM_MODE_RX_AND_TX = 3 /**< Both tx and rx communication */ +}; + +/*mac statistics */ +struct mac_statistics { + u64 stat_pkts64; /* r-10G tr-DT 64 byte frame counter */ + u64 stat_pkts65to127; /* r-10G 65 to 127 byte frame counter */ + u64 stat_pkts128to255; /* r-10G 128 to 255 byte frame counter */ + u64 stat_pkts256to511; /*r-10G 256 to 511 byte frame counter */ + u64 stat_pkts512to1023;/* r-10G 512 to 1023 byte frame counter */ + u64 stat_pkts1024to1518; /* r-10G 1024 to 1518 byte frame counter */ + u64 stat_pkts1519to1522; /* r-10G 1519 to 1522 byte good frame count*/ + /* Total number of packets that were less than 64 octets */ + /* long with a wrong CRC.*/ + u64 stat_fragments; + /* Total number of packets longer than valid maximum length octets */ + u64 stat_jabbers; + /* number of dropped packets due to internal errors of */ + /* the MAC Client. */ + u64 stat_drop_events; + /* Incremented when frames of correct length but with */ + /* CRC error are received.*/ + u64 stat_crc_align_errors; + /* Total number of packets that were less than 64 octets */ + /* long with a good CRC.*/ + u64 stat_undersize_pkts; + u64 stat_oversize_pkts; /**< T,B.D*/ + + u64 stat_rx_pause; /**< Pause MAC Control received */ + u64 stat_tx_pause; /**< Pause MAC Control sent */ + + u64 in_octets; /**< Total number of byte received. */ + u64 in_pkts; /* Total number of packets received.*/ + u64 in_mcast_pkts; /* Total number of multicast frame received */ + u64 in_bcast_pkts; /* Total number of broadcast frame received */ + /* Frames received, but discarded due to */ + /* problems within the MAC RX. */ + u64 in_discards; + u64 in_errors; /* Number of frames received with error: */ + /* - FIFO Overflow Error */ + /* - CRC Error */ + /* - Frame Too Long Error */ + /* - Alignment Error */ + u64 out_octets; /*Total number of byte sent. */ + u64 out_pkts; /**< Total number of packets sent .*/ + u64 out_mcast_pkts; /* Total number of multicast frame sent */ + u64 out_bcast_pkts; /* Total number of multicast frame sent */ + /* Frames received, but discarded due to problems within */ + /* the MAC TX N/A!.*/ + u64 out_discards; + u64 out_errors; /*Number of frames transmitted with error: */ + /* - FIFO Overflow Error */ + /* - FIFO Underflow Error */ + /* - Other */ +}; + +/*mac para struct ,mac get param from nic or dsaf when initialize*/ +struct mac_params { + char addr[MAC_NUM_OCTETS_PER_ADDR]; + void *vaddr; /*virtual address*/ + struct device *dev; + u8 mac_id; + /**< Ethernet operation mode (MAC-PHY interface and speed) */ + enum mac_mode mac_mode; +}; + +struct mac_info { + u16 speed;/* The forced speed (lower bits) in */ + /* *mbps. Please use */ + /* * ethtool_cmd_speed()/_set() to */ + /* * access it */ + u8 duplex; /* Duplex, half or full */ + u8 auto_neg; /* Enable or disable autonegotiation */ + enum hnae_loop loop_mode; + u8 tx_pause_en; + u8 tx_pause_time; + u8 rx_pause_en; + u8 pad_and_crc_en; + u8 promiscuous_en; + u8 port_en; /*port enable*/ +}; + +struct mac_entry_idx { + u8 addr[MAC_NUM_OCTETS_PER_ADDR]; + u16 vlan_id:12; + u16 valid:1; + u16 qos:3; +}; + +struct mac_hw_stats { + u64 rx_good_pkts; /* only for xgmac */ + u64 rx_good_bytes; + u64 rx_total_pkts; /* only for xgmac */ + u64 rx_total_bytes; /* only for xgmac */ + u64 rx_bad_bytes; /* only for gmac */ + u64 rx_uc_pkts; + u64 rx_mc_pkts; + u64 rx_bc_pkts; + u64 rx_fragment_err; /* only for xgmac */ + u64 rx_undersize; /* only for xgmac */ + u64 rx_under_min; + u64 rx_minto64; /* only for gmac */ + u64 rx_64bytes; + u64 rx_65to127; + u64 rx_128to255; + u64 rx_256to511; + u64 rx_512to1023; + u64 rx_1024to1518; + u64 rx_1519tomax; + u64 rx_1519tomax_good; /* only for xgmac */ + u64 rx_oversize; + u64 rx_jabber_err; + u64 rx_fcs_err; + u64 rx_vlan_pkts; /* only for gmac */ + u64 rx_data_err; /* only for gmac */ + u64 rx_align_err; /* only for gmac */ + u64 rx_long_err; /* only for gmac */ + u64 rx_pfc_tc0; + u64 rx_pfc_tc1; /* only for xgmac */ + u64 rx_pfc_tc2; /* only for xgmac */ + u64 rx_pfc_tc3; /* only for xgmac */ + u64 rx_pfc_tc4; /* only for xgmac */ + u64 rx_pfc_tc5; /* only for xgmac */ + u64 rx_pfc_tc6; /* only for xgmac */ + u64 rx_pfc_tc7; /* only for xgmac */ + u64 rx_unknown_ctrl; + u64 rx_filter_pkts; /* only for gmac */ + u64 rx_filter_bytes; /* only for gmac */ + u64 rx_fifo_overrun_err;/* only for gmac */ + u64 rx_len_err; /* only for gmac */ + u64 rx_comma_err; /* only for gmac */ + u64 rx_symbol_err; /* only for xgmac */ + u64 tx_good_to_sw; /* only for xgmac */ + u64 tx_bad_to_sw; /* only for xgmac */ + u64 rx_1731_pkts; /* only for xgmac */ + + u64 tx_good_bytes; + u64 tx_good_pkts; /* only for xgmac */ + u64 tx_total_bytes; /* only for xgmac */ + u64 tx_total_pkts; /* only for xgmac */ + u64 tx_bad_bytes; /* only for gmac */ + u64 tx_bad_pkts; /* only for xgmac */ + u64 tx_uc_pkts; + u64 tx_mc_pkts; + u64 tx_bc_pkts; + u64 tx_undersize; /* only for xgmac */ + u64 tx_fragment_err; /* only for xgmac */ + u64 tx_under_min_pkts; /* only for gmac */ + u64 tx_64bytes; + u64 tx_65to127; + u64 tx_128to255; + u64 tx_256to511; + u64 tx_512to1023; + u64 tx_1024to1518; + u64 tx_1519tomax; + u64 tx_1519tomax_good; /* only for xgmac */ + u64 tx_oversize; /* only for xgmac */ + u64 tx_jabber_err; + u64 tx_underrun_err; /* only for gmac */ + u64 tx_vlan; /* only for gmac */ + u64 tx_crc_err; /* only for gmac */ + u64 tx_pfc_tc0; + u64 tx_pfc_tc1; /* only for xgmac */ + u64 tx_pfc_tc2; /* only for xgmac */ + u64 tx_pfc_tc3; /* only for xgmac */ + u64 tx_pfc_tc4; /* only for xgmac */ + u64 tx_pfc_tc5; /* only for xgmac */ + u64 tx_pfc_tc6; /* only for xgmac */ + u64 tx_pfc_tc7; /* only for xgmac */ + u64 tx_ctrl; /* only for xgmac */ + u64 tx_1731_pkts; /* only for xgmac */ + u64 tx_1588_pkts; /* only for xgmac */ + u64 rx_good_from_sw; /* only for xgmac */ + u64 rx_bad_from_sw; /* only for xgmac */ +}; + +struct hns_mac_cb { + struct device *dev; + struct dsaf_device *dsaf_dev; + struct mac_priv priv; + u8 __iomem *vaddr; + u8 __iomem *cpld_vaddr; + u8 __iomem *sys_ctl_vaddr; + u8 __iomem *serdes_vaddr; + struct mac_entry_idx addr_entry_idx[DSAF_MAX_VM_NUM]; + u8 sfp_prsnt; + u8 cpld_led_value; + u8 mac_id; + + u8 link; + u8 half_duplex; + u16 speed; + u16 max_speed; + u16 max_frm; + u16 tx_pause_frm_time; + u32 if_support; + u64 txpkt_for_led; + u64 rxpkt_for_led; + enum hnae_port_type mac_type; + phy_interface_t phy_if; + enum hnae_loop loop_mode; + + struct device_node *phy_node; + + struct mac_hw_stats hw_stats; +}; + +struct mac_driver { + /*init Mac when init nic or dsaf*/ + void (*mac_init)(void *mac_drv); + /*remove mac when remove nic or dsaf*/ + void (*mac_free)(void *mac_drv); + /*enable mac when enable nic or dsaf*/ + void (*mac_enable)(void *mac_drv, enum mac_commom_mode mode); + /*disable mac when disable nic or dsaf*/ + void (*mac_disable)(void *mac_drv, enum mac_commom_mode mode); + /* config mac address*/ + void (*set_mac_addr)(void *mac_drv, char *mac_addr); + /*adjust mac mode of port,include speed and duplex*/ + int (*adjust_link)(void *mac_drv, enum mac_speed speed, + u32 full_duplex); + /* config autoegotaite mode of port*/ + void (*set_an_mode)(void *mac_drv, u8 enable); + /* config loopbank mode */ + int (*config_loopback)(void *mac_drv, enum hnae_loop loop_mode, + u8 enable); + /* config mtu*/ + void (*config_max_frame_length)(void *mac_drv, u16 newval); + /*config PAD and CRC enable */ + void (*config_pad_and_crc)(void *mac_drv, u8 newval); + /* config duplex mode*/ + void (*config_half_duplex)(void *mac_drv, u8 newval); + /*config tx pause time,if pause_time is zero,disable tx pause enable*/ + void (*set_tx_auto_pause_frames)(void *mac_drv, u16 pause_time); + /*config rx pause enable*/ + void (*set_rx_ignore_pause_frames)(void *mac_drv, u32 enable); + /* config rx mode for promiscuous*/ + int (*set_promiscuous)(void *mac_drv, u8 enable); + /* get mac id */ + void (*mac_get_id)(void *mac_drv, u8 *mac_id); + void (*mac_pausefrm_cfg)(void *mac_drv, u32 rx_en, u32 tx_en); + + void (*autoneg_stat)(void *mac_drv, u32 *enable); + int (*set_pause_enable)(void *mac_drv, u32 rx_en, u32 tx_en); + void (*get_pause_enable)(void *mac_drv, u32 *rx_en, u32 *tx_en); + void (*get_link_status)(void *mac_drv, u32 *link_stat); + /* get the imporant regs*/ + void (*get_regs)(void *mac_drv, void *data); + int (*get_regs_count)(void); + /* get strings name for ethtool statistic */ + void (*get_strings)(u32 stringset, u8 *data); + /* get the number of strings*/ + int (*get_sset_count)(int stringset); + + /* get the statistic by ethtools*/ + void (*get_ethtool_stats)(void *mac_drv, u64 *data); + + /* get mac information */ + void (*get_info)(void *mac_drv, struct mac_info *mac_info); + + void (*update_stats)(void *mac_drv); + + enum mac_mode mac_mode; + u8 mac_id; + struct hns_mac_cb *mac_cb; + void __iomem *io_base; + unsigned int mac_en_flg;/*you'd better don't enable mac twice*/ + unsigned int virt_dev_num; + struct device *dev; +}; + +struct mac_stats_string { + char desc[64]; + unsigned long offset; +}; + +#define MAC_MAKE_MODE(interface, speed) (enum mac_mode)((interface) | (speed)) +#define MAC_INTERFACE_FROM_MODE(mode) (enum mac_intf)((mode) & 0xFFFF0000) +#define MAC_SPEED_FROM_MODE(mode) (enum mac_speed)((mode) & 0x0000FFFF) +#define MAC_STATS_FIELD_OFF(field) (offsetof(struct mac_hw_stats, field)) + +static inline struct mac_driver *hns_mac_get_drv( + const struct hns_mac_cb *mac_cb) +{ + return (struct mac_driver *)(mac_cb->priv.mac); +} + +void *hns_gmac_config(struct hns_mac_cb *mac_cb, + struct mac_params *mac_param); +void *hns_xgmac_config(struct hns_mac_cb *mac_cb, + struct mac_params *mac_param); + +int hns_mac_init(struct dsaf_device *dsaf_dev); +void mac_adjust_link(struct net_device *net_dev); +void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status); +int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb, u32 vmid, char *addr); +int hns_mac_set_multi(struct hns_mac_cb *mac_cb, + u32 port_num, char *addr, u8 en); +int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vm, u8 en); +void hns_mac_start(struct hns_mac_cb *mac_cb); +void hns_mac_stop(struct hns_mac_cb *mac_cb); +int hns_mac_del_mac(struct hns_mac_cb *mac_cb, u32 vfn, char *mac); +void hns_mac_uninit(struct dsaf_device *dsaf_dev); +void hns_mac_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex); +void hns_mac_reset(struct hns_mac_cb *mac_cb); +void hns_mac_get_autoneg(struct hns_mac_cb *mac_cb, u32 *auto_neg); +void hns_mac_get_pauseparam(struct hns_mac_cb *mac_cb, u32 *rx_en, u32 *tx_en); +int hns_mac_set_autoneg(struct hns_mac_cb *mac_cb, u8 enable); +int hns_mac_set_pauseparam(struct hns_mac_cb *mac_cb, u32 rx_en, u32 tx_en); +int hns_mac_set_mtu(struct hns_mac_cb *mac_cb, u32 new_mtu); +int hns_mac_get_port_info(struct hns_mac_cb *mac_cb, + u8 *auto_neg, u16 *speed, u8 *duplex); +phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb); +int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, u8 en); +int hns_mac_config_mac_loopback(struct hns_mac_cb *mac_cb, + enum hnae_loop loop, int en); +void hns_mac_update_stats(struct hns_mac_cb *mac_cb); +void hns_mac_get_stats(struct hns_mac_cb *mac_cb, u64 *data); +void hns_mac_get_strings(struct hns_mac_cb *mac_cb, int stringset, u8 *data); +int hns_mac_get_sset_count(struct hns_mac_cb *mac_cb, int stringset); +void hns_mac_get_regs(struct hns_mac_cb *mac_cb, void *data); +int hns_mac_get_regs_count(struct hns_mac_cb *mac_cb); +void hns_set_led_opt(struct hns_mac_cb *mac_cb); +int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb, + enum hnae_led_state status); +#endif /* _HNS_DSAF_MAC_H */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c new file mode 100644 index 000000000000..26ae6c64d74c --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -0,0 +1,2445 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hns_dsaf_main.h" +#include "hns_dsaf_rcb.h" +#include "hns_dsaf_ppe.h" +#include "hns_dsaf_mac.h" + +const char *g_dsaf_mode_match[DSAF_MODE_MAX] = { + [DSAF_MODE_DISABLE_2PORT_64VM] = "2port-64vf", + [DSAF_MODE_DISABLE_6PORT_0VM] = "6port-16rss", + [DSAF_MODE_DISABLE_6PORT_16VM] = "6port-16vf", +}; + +int hns_dsaf_get_cfg(struct dsaf_device *dsaf_dev) +{ + int ret, i; + u32 desc_num; + u32 buf_size; + const char *name, *mode_str; + struct device_node *np = dsaf_dev->dev->of_node; + + if (of_device_is_compatible(np, "hisilicon,hns-dsaf-v2")) + dsaf_dev->dsaf_ver = AE_VERSION_2; + else + dsaf_dev->dsaf_ver = AE_VERSION_1; + + ret = of_property_read_string(np, "dsa_name", &name); + if (ret) { + dev_err(dsaf_dev->dev, "get dsaf name fail, ret=%d!\n", ret); + return ret; + } + strncpy(dsaf_dev->ae_dev.name, name, AE_NAME_SIZE); + dsaf_dev->ae_dev.name[AE_NAME_SIZE - 1] = '\0'; + + ret = of_property_read_string(np, "mode", &mode_str); + if (ret) { + dev_err(dsaf_dev->dev, "get dsaf mode fail, ret=%d!\n", ret); + return ret; + } + for (i = 0; i < DSAF_MODE_MAX; i++) { + if (g_dsaf_mode_match[i] && + !strcmp(mode_str, g_dsaf_mode_match[i])) + break; + } + if (i >= DSAF_MODE_MAX || + i == DSAF_MODE_INVALID || i == DSAF_MODE_ENABLE) { + dev_err(dsaf_dev->dev, + "%s prs mode str fail!\n", dsaf_dev->ae_dev.name); + return -EINVAL; + } + dsaf_dev->dsaf_mode = (enum dsaf_mode)i; + + if (dsaf_dev->dsaf_mode > DSAF_MODE_ENABLE) + dsaf_dev->dsaf_en = HRD_DSAF_NO_DSAF_MODE; + else + dsaf_dev->dsaf_en = HRD_DSAF_MODE; + + if ((i == DSAF_MODE_ENABLE_16VM) || + (i == DSAF_MODE_DISABLE_2PORT_8VM) || + (i == DSAF_MODE_DISABLE_6PORT_2VM)) + dsaf_dev->dsaf_tc_mode = HRD_DSAF_8TC_MODE; + else + dsaf_dev->dsaf_tc_mode = HRD_DSAF_4TC_MODE; + + dsaf_dev->sc_base = of_iomap(np, 0); + if (!dsaf_dev->sc_base) { + dev_err(dsaf_dev->dev, + "%s of_iomap 0 fail!\n", dsaf_dev->ae_dev.name); + ret = -ENOMEM; + goto unmap_base_addr; + } + + dsaf_dev->sds_base = of_iomap(np, 1); + if (!dsaf_dev->sds_base) { + dev_err(dsaf_dev->dev, + "%s of_iomap 1 fail!\n", dsaf_dev->ae_dev.name); + ret = -ENOMEM; + goto unmap_base_addr; + } + + dsaf_dev->ppe_base = of_iomap(np, 2); + if (!dsaf_dev->ppe_base) { + dev_err(dsaf_dev->dev, + "%s of_iomap 2 fail!\n", dsaf_dev->ae_dev.name); + ret = -ENOMEM; + goto unmap_base_addr; + } + + dsaf_dev->io_base = of_iomap(np, 3); + if (!dsaf_dev->io_base) { + dev_err(dsaf_dev->dev, + "%s of_iomap 3 fail!\n", dsaf_dev->ae_dev.name); + ret = -ENOMEM; + goto unmap_base_addr; + } + + dsaf_dev->cpld_base = of_iomap(np, 4); + if (!dsaf_dev->cpld_base) + dev_dbg(dsaf_dev->dev, "NO CPLD ADDR"); + + ret = of_property_read_u32(np, "desc-num", &desc_num); + if (ret < 0 || desc_num < HNS_DSAF_MIN_DESC_CNT || + desc_num > HNS_DSAF_MAX_DESC_CNT) { + dev_err(dsaf_dev->dev, "get desc-num(%d) fail, ret=%d!\n", + desc_num, ret); + goto unmap_base_addr; + } + dsaf_dev->desc_num = desc_num; + + ret = of_property_read_u32(np, "buf-size", &buf_size); + if (ret < 0) { + dev_err(dsaf_dev->dev, + "get buf-size fail, ret=%d!\r\n", ret); + goto unmap_base_addr; + } + dsaf_dev->buf_size = buf_size; + + dsaf_dev->buf_size_type = hns_rcb_buf_size2type(buf_size); + if (dsaf_dev->buf_size_type < 0) { + dev_err(dsaf_dev->dev, + "buf_size(%d) is wrong!\n", buf_size); + goto unmap_base_addr; + } + + if (!dma_set_mask_and_coherent(dsaf_dev->dev, DMA_BIT_MASK(64ULL))) + dev_dbg(dsaf_dev->dev, "set mask to 64bit\n"); + else + dev_err(dsaf_dev->dev, "set mask to 64bit fail!\n"); + + return 0; + +unmap_base_addr: + if (dsaf_dev->io_base) + iounmap(dsaf_dev->io_base); + if (dsaf_dev->ppe_base) + iounmap(dsaf_dev->ppe_base); + if (dsaf_dev->sds_base) + iounmap(dsaf_dev->sds_base); + if (dsaf_dev->sc_base) + iounmap(dsaf_dev->sc_base); + if (dsaf_dev->cpld_base) + iounmap(dsaf_dev->cpld_base); + return ret; +} + +static void hns_dsaf_free_cfg(struct dsaf_device *dsaf_dev) +{ + if (dsaf_dev->io_base) + iounmap(dsaf_dev->io_base); + + if (dsaf_dev->ppe_base) + iounmap(dsaf_dev->ppe_base); + + if (dsaf_dev->sds_base) + iounmap(dsaf_dev->sds_base); + + if (dsaf_dev->sc_base) + iounmap(dsaf_dev->sc_base); + + if (dsaf_dev->cpld_base) + iounmap(dsaf_dev->cpld_base); +} + +/** + * hns_dsaf_sbm_link_sram_init_en - config dsaf_sbm_init_en + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_sbm_link_sram_init_en(struct dsaf_device *dsaf_dev) +{ + dsaf_set_dev_bit(dsaf_dev, DSAF_CFG_0_REG, DSAF_CFG_SBM_INIT_S, 1); +} + +/** + * hns_dsaf_reg_cnt_clr_ce - config hns_dsaf_reg_cnt_clr_ce + * @dsaf_id: dsa fabric id + * @hns_dsaf_reg_cnt_clr_ce: config value + */ +static void +hns_dsaf_reg_cnt_clr_ce(struct dsaf_device *dsaf_dev, u32 reg_cnt_clr_ce) +{ + dsaf_set_dev_bit(dsaf_dev, DSAF_DSA_REG_CNT_CLR_CE_REG, + DSAF_CNT_CLR_CE_S, reg_cnt_clr_ce); +} + +/** + * hns_ppe_qid_cfg - config ppe qid + * @dsaf_id: dsa fabric id + * @pppe_qid_cfg: value array + */ +static void +hns_dsaf_ppe_qid_cfg(struct dsaf_device *dsaf_dev, u32 qid_cfg) +{ + u32 i; + + for (i = 0; i < DSAF_COMM_CHN; i++) { + dsaf_set_dev_field(dsaf_dev, + DSAF_PPE_QID_CFG_0_REG + 0x0004 * i, + DSAF_PPE_QID_CFG_M, DSAF_PPE_QID_CFG_S, + qid_cfg); + } +} + +/** + * hns_dsaf_sw_port_type_cfg - cfg sw type + * @dsaf_id: dsa fabric id + * @psw_port_type: array + */ +static void hns_dsaf_sw_port_type_cfg(struct dsaf_device *dsaf_dev, + enum dsaf_sw_port_type port_type) +{ + u32 i; + + for (i = 0; i < DSAF_SW_PORT_NUM; i++) { + dsaf_set_dev_field(dsaf_dev, + DSAF_SW_PORT_TYPE_0_REG + 0x0004 * i, + DSAF_SW_PORT_TYPE_M, DSAF_SW_PORT_TYPE_S, + port_type); + } +} + +/** + * hns_dsaf_stp_port_type_cfg - cfg stp type + * @dsaf_id: dsa fabric id + * @pstp_port_type: array + */ +static void hns_dsaf_stp_port_type_cfg(struct dsaf_device *dsaf_dev, + enum dsaf_stp_port_type port_type) +{ + u32 i; + + for (i = 0; i < DSAF_COMM_CHN; i++) { + dsaf_set_dev_field(dsaf_dev, + DSAF_STP_PORT_TYPE_0_REG + 0x0004 * i, + DSAF_STP_PORT_TYPE_M, DSAF_STP_PORT_TYPE_S, + port_type); + } +} + +/** + * hns_dsaf_sbm_cfg - config sbm + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_sbm_cfg(struct dsaf_device *dsaf_dev) +{ + u32 o_sbm_cfg; + u32 i; + + for (i = 0; i < DSAF_SBM_NUM; i++) { + o_sbm_cfg = dsaf_read_dev(dsaf_dev, + DSAF_SBM_CFG_REG_0_REG + 0x80 * i); + dsaf_set_bit(o_sbm_cfg, DSAF_SBM_CFG_EN_S, 1); + dsaf_set_bit(o_sbm_cfg, DSAF_SBM_CFG_SHCUT_EN_S, 0); + dsaf_write_dev(dsaf_dev, + DSAF_SBM_CFG_REG_0_REG + 0x80 * i, o_sbm_cfg); + } +} + +/** + * hns_dsaf_sbm_cfg_mib_en - config sbm + * @dsaf_id: dsa fabric id + */ +static int hns_dsaf_sbm_cfg_mib_en(struct dsaf_device *dsaf_dev) +{ + u32 sbm_cfg_mib_en; + u32 i; + u32 reg; + u32 read_cnt; + + for (i = 0; i < DSAF_SBM_NUM; i++) { + reg = DSAF_SBM_CFG_REG_0_REG + 0x80 * i; + dsaf_set_dev_bit(dsaf_dev, reg, DSAF_SBM_CFG_MIB_EN_S, 1); + } + + /* waitint for all sbm enable finished */ + for (i = 0; i < DSAF_SBM_NUM; i++) { + read_cnt = 0; + reg = DSAF_SBM_CFG_REG_0_REG + 0x80 * i; + do { + udelay(1); + sbm_cfg_mib_en = dsaf_get_dev_bit( + dsaf_dev, reg, DSAF_SBM_CFG_MIB_EN_S); + read_cnt++; + } while (sbm_cfg_mib_en == 0 && + read_cnt < DSAF_CFG_READ_CNT); + + if (sbm_cfg_mib_en == 0) { + dev_err(dsaf_dev->dev, + "sbm_cfg_mib_en fail,%s,sbm_num=%d\n", + dsaf_dev->ae_dev.name, i); + return -ENODEV; + } + } + + return 0; +} + +/** + * hns_dsaf_sbm_bp_wl_cfg - config sbm + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_sbm_bp_wl_cfg(struct dsaf_device *dsaf_dev) +{ + u32 o_sbm_bp_cfg0; + u32 o_sbm_bp_cfg1; + u32 o_sbm_bp_cfg2; + u32 o_sbm_bp_cfg3; + u32 reg; + u32 i; + + /* XGE */ + for (i = 0; i < DSAF_XGE_NUM; i++) { + reg = DSAF_SBM_BP_CFG_0_XGE_REG_0_REG + 0x80 * i; + o_sbm_bp_cfg0 = dsaf_read_dev(dsaf_dev, reg); + dsaf_set_field(o_sbm_bp_cfg0, DSAF_SBM_CFG0_COM_MAX_BUF_NUM_M, + DSAF_SBM_CFG0_COM_MAX_BUF_NUM_S, 512); + dsaf_set_field(o_sbm_bp_cfg0, DSAF_SBM_CFG0_VC0_MAX_BUF_NUM_M, + DSAF_SBM_CFG0_VC0_MAX_BUF_NUM_S, 0); + dsaf_set_field(o_sbm_bp_cfg0, DSAF_SBM_CFG0_VC1_MAX_BUF_NUM_M, + DSAF_SBM_CFG0_VC1_MAX_BUF_NUM_S, 0); + dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg0); + + reg = DSAF_SBM_BP_CFG_1_REG_0_REG + 0x80 * i; + o_sbm_bp_cfg1 = dsaf_read_dev(dsaf_dev, reg); + dsaf_set_field(o_sbm_bp_cfg1, DSAF_SBM_CFG1_TC4_MAX_BUF_NUM_M, + DSAF_SBM_CFG1_TC4_MAX_BUF_NUM_S, 0); + dsaf_set_field(o_sbm_bp_cfg1, DSAF_SBM_CFG1_TC0_MAX_BUF_NUM_M, + DSAF_SBM_CFG1_TC0_MAX_BUF_NUM_S, 0); + dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg1); + + reg = DSAF_SBM_BP_CFG_2_XGE_REG_0_REG + 0x80 * i; + o_sbm_bp_cfg2 = dsaf_read_dev(dsaf_dev, reg); + dsaf_set_field(o_sbm_bp_cfg2, DSAF_SBM_CFG2_SET_BUF_NUM_M, + DSAF_SBM_CFG2_SET_BUF_NUM_S, 104); + dsaf_set_field(o_sbm_bp_cfg2, DSAF_SBM_CFG2_RESET_BUF_NUM_M, + DSAF_SBM_CFG2_RESET_BUF_NUM_S, 128); + dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg2); + + reg = DSAF_SBM_BP_CFG_3_REG_0_REG + 0x80 * i; + o_sbm_bp_cfg3 = dsaf_read_dev(dsaf_dev, reg); + dsaf_set_field(o_sbm_bp_cfg3, + DSAF_SBM_CFG3_SET_BUF_NUM_NO_PFC_M, + DSAF_SBM_CFG3_SET_BUF_NUM_NO_PFC_S, 110); + dsaf_set_field(o_sbm_bp_cfg3, + DSAF_SBM_CFG3_RESET_BUF_NUM_NO_PFC_M, + DSAF_SBM_CFG3_RESET_BUF_NUM_NO_PFC_S, 160); + dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg3); + + /* for no enable pfc mode */ + reg = DSAF_SBM_BP_CFG_4_REG_0_REG + 0x80 * i; + o_sbm_bp_cfg3 = dsaf_read_dev(dsaf_dev, reg); + dsaf_set_field(o_sbm_bp_cfg3, + DSAF_SBM_CFG3_SET_BUF_NUM_NO_PFC_M, + DSAF_SBM_CFG3_SET_BUF_NUM_NO_PFC_S, 128); + dsaf_set_field(o_sbm_bp_cfg3, + DSAF_SBM_CFG3_RESET_BUF_NUM_NO_PFC_M, + DSAF_SBM_CFG3_RESET_BUF_NUM_NO_PFC_S, 192); + dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg3); + } + + /* PPE */ + for (i = 0; i < DSAF_COMM_CHN; i++) { + reg = DSAF_SBM_BP_CFG_2_PPE_REG_0_REG + 0x80 * i; + o_sbm_bp_cfg2 = dsaf_read_dev(dsaf_dev, reg); + dsaf_set_field(o_sbm_bp_cfg2, DSAF_SBM_CFG2_SET_BUF_NUM_M, + DSAF_SBM_CFG2_SET_BUF_NUM_S, 10); + dsaf_set_field(o_sbm_bp_cfg2, DSAF_SBM_CFG2_RESET_BUF_NUM_M, + DSAF_SBM_CFG2_RESET_BUF_NUM_S, 12); + dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg2); + } + + /* RoCEE */ + for (i = 0; i < DSAF_COMM_CHN; i++) { + reg = DSAF_SBM_BP_CFG_2_ROCEE_REG_0_REG + 0x80 * i; + o_sbm_bp_cfg2 = dsaf_read_dev(dsaf_dev, reg); + dsaf_set_field(o_sbm_bp_cfg2, DSAF_SBM_CFG2_SET_BUF_NUM_M, + DSAF_SBM_CFG2_SET_BUF_NUM_S, 2); + dsaf_set_field(o_sbm_bp_cfg2, DSAF_SBM_CFG2_RESET_BUF_NUM_M, + DSAF_SBM_CFG2_RESET_BUF_NUM_S, 4); + dsaf_write_dev(dsaf_dev, reg, o_sbm_bp_cfg2); + } +} + +/** + * hns_dsaf_voq_bp_all_thrd_cfg - voq + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_voq_bp_all_thrd_cfg(struct dsaf_device *dsaf_dev) +{ + u32 voq_bp_all_thrd; + u32 i; + + for (i = 0; i < DSAF_VOQ_NUM; i++) { + voq_bp_all_thrd = dsaf_read_dev( + dsaf_dev, DSAF_VOQ_BP_ALL_THRD_0_REG + 0x40 * i); + if (i < DSAF_XGE_NUM) { + dsaf_set_field(voq_bp_all_thrd, + DSAF_VOQ_BP_ALL_DOWNTHRD_M, + DSAF_VOQ_BP_ALL_DOWNTHRD_S, 930); + dsaf_set_field(voq_bp_all_thrd, + DSAF_VOQ_BP_ALL_UPTHRD_M, + DSAF_VOQ_BP_ALL_UPTHRD_S, 950); + } else { + dsaf_set_field(voq_bp_all_thrd, + DSAF_VOQ_BP_ALL_DOWNTHRD_M, + DSAF_VOQ_BP_ALL_DOWNTHRD_S, 220); + dsaf_set_field(voq_bp_all_thrd, + DSAF_VOQ_BP_ALL_UPTHRD_M, + DSAF_VOQ_BP_ALL_UPTHRD_S, 230); + } + dsaf_write_dev( + dsaf_dev, DSAF_VOQ_BP_ALL_THRD_0_REG + 0x40 * i, + voq_bp_all_thrd); + } +} + +/** + * hns_dsaf_tbl_tcam_data_cfg - tbl + * @dsaf_id: dsa fabric id + * @ptbl_tcam_data: addr + */ +static void hns_dsaf_tbl_tcam_data_cfg( + struct dsaf_device *dsaf_dev, + struct dsaf_tbl_tcam_data *ptbl_tcam_data) +{ + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_LOW_0_REG, + ptbl_tcam_data->tbl_tcam_data_low); + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_HIGH_0_REG, + ptbl_tcam_data->tbl_tcam_data_high); +} + +/** + * dsaf_tbl_tcam_mcast_cfg - tbl + * @dsaf_id: dsa fabric id + * @ptbl_tcam_mcast: addr + */ +static void hns_dsaf_tbl_tcam_mcast_cfg( + struct dsaf_device *dsaf_dev, + struct dsaf_tbl_tcam_mcast_cfg *mcast) +{ + u32 mcast_cfg4; + + mcast_cfg4 = dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_4_0_REG); + dsaf_set_bit(mcast_cfg4, DSAF_TBL_MCAST_CFG4_ITEM_VLD_S, + mcast->tbl_mcast_item_vld); + dsaf_set_bit(mcast_cfg4, DSAF_TBL_MCAST_CFG4_OLD_EN_S, + mcast->tbl_mcast_old_en); + dsaf_set_field(mcast_cfg4, DSAF_TBL_MCAST_CFG4_VM128_112_M, + DSAF_TBL_MCAST_CFG4_VM128_112_S, + mcast->tbl_mcast_port_msk[4]); + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_4_0_REG, mcast_cfg4); + + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_3_0_REG, + mcast->tbl_mcast_port_msk[3]); + + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_2_0_REG, + mcast->tbl_mcast_port_msk[2]); + + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_1_0_REG, + mcast->tbl_mcast_port_msk[1]); + + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_0_0_REG, + mcast->tbl_mcast_port_msk[0]); +} + +/** + * hns_dsaf_tbl_tcam_ucast_cfg - tbl + * @dsaf_id: dsa fabric id + * @ptbl_tcam_ucast: addr + */ +static void hns_dsaf_tbl_tcam_ucast_cfg( + struct dsaf_device *dsaf_dev, + struct dsaf_tbl_tcam_ucast_cfg *tbl_tcam_ucast) +{ + u32 ucast_cfg1; + + ucast_cfg1 = dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_UCAST_CFG_0_REG); + dsaf_set_bit(ucast_cfg1, DSAF_TBL_UCAST_CFG1_MAC_DISCARD_S, + tbl_tcam_ucast->tbl_ucast_mac_discard); + dsaf_set_bit(ucast_cfg1, DSAF_TBL_UCAST_CFG1_ITEM_VLD_S, + tbl_tcam_ucast->tbl_ucast_item_vld); + dsaf_set_bit(ucast_cfg1, DSAF_TBL_UCAST_CFG1_OLD_EN_S, + tbl_tcam_ucast->tbl_ucast_old_en); + dsaf_set_bit(ucast_cfg1, DSAF_TBL_UCAST_CFG1_DVC_S, + tbl_tcam_ucast->tbl_ucast_dvc); + dsaf_set_field(ucast_cfg1, DSAF_TBL_UCAST_CFG1_OUT_PORT_M, + DSAF_TBL_UCAST_CFG1_OUT_PORT_S, + tbl_tcam_ucast->tbl_ucast_out_port); + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_UCAST_CFG_0_REG, ucast_cfg1); +} + +/** + * hns_dsaf_tbl_line_cfg - tbl + * @dsaf_id: dsa fabric id + * @ptbl_lin: addr + */ +static void hns_dsaf_tbl_line_cfg(struct dsaf_device *dsaf_dev, + struct dsaf_tbl_line_cfg *tbl_lin) +{ + u32 tbl_line; + + tbl_line = dsaf_read_dev(dsaf_dev, DSAF_TBL_LIN_CFG_0_REG); + dsaf_set_bit(tbl_line, DSAF_TBL_LINE_CFG_MAC_DISCARD_S, + tbl_lin->tbl_line_mac_discard); + dsaf_set_bit(tbl_line, DSAF_TBL_LINE_CFG_DVC_S, + tbl_lin->tbl_line_dvc); + dsaf_set_field(tbl_line, DSAF_TBL_LINE_CFG_OUT_PORT_M, + DSAF_TBL_LINE_CFG_OUT_PORT_S, + tbl_lin->tbl_line_out_port); + dsaf_write_dev(dsaf_dev, DSAF_TBL_LIN_CFG_0_REG, tbl_line); +} + +/** + * hns_dsaf_tbl_tcam_mcast_pul - tbl + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_tbl_tcam_mcast_pul(struct dsaf_device *dsaf_dev) +{ + u32 o_tbl_pul; + + o_tbl_pul = dsaf_read_dev(dsaf_dev, DSAF_TBL_PUL_0_REG); + dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_MCAST_VLD_S, 1); + dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul); + dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_MCAST_VLD_S, 0); + dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul); +} + +/** + * hns_dsaf_tbl_line_pul - tbl + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_tbl_line_pul(struct dsaf_device *dsaf_dev) +{ + u32 tbl_pul; + + tbl_pul = dsaf_read_dev(dsaf_dev, DSAF_TBL_PUL_0_REG); + dsaf_set_bit(tbl_pul, DSAF_TBL_PUL_LINE_VLD_S, 1); + dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, tbl_pul); + dsaf_set_bit(tbl_pul, DSAF_TBL_PUL_LINE_VLD_S, 0); + dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, tbl_pul); +} + +/** + * hns_dsaf_tbl_tcam_data_mcast_pul - tbl + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_tbl_tcam_data_mcast_pul( + struct dsaf_device *dsaf_dev) +{ + u32 o_tbl_pul; + + o_tbl_pul = dsaf_read_dev(dsaf_dev, DSAF_TBL_PUL_0_REG); + dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_TCAM_DATA_VLD_S, 1); + dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_MCAST_VLD_S, 1); + dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul); + dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_TCAM_DATA_VLD_S, 0); + dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_MCAST_VLD_S, 0); + dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul); +} + +/** + * hns_dsaf_tbl_tcam_data_ucast_pul - tbl + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_tbl_tcam_data_ucast_pul( + struct dsaf_device *dsaf_dev) +{ + u32 o_tbl_pul; + + o_tbl_pul = dsaf_read_dev(dsaf_dev, DSAF_TBL_PUL_0_REG); + dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_TCAM_DATA_VLD_S, 1); + dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_UCAST_VLD_S, 1); + dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul); + dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_TCAM_DATA_VLD_S, 0); + dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_UCAST_VLD_S, 0); + dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul); +} + +/** + * hns_dsaf_tbl_stat_en - tbl + * @dsaf_id: dsa fabric id + * @ptbl_stat_en: addr + */ +static void hns_dsaf_tbl_stat_en(struct dsaf_device *dsaf_dev) +{ + u32 o_tbl_ctrl; + + o_tbl_ctrl = dsaf_read_dev(dsaf_dev, DSAF_TBL_DFX_CTRL_0_REG); + dsaf_set_bit(o_tbl_ctrl, DSAF_TBL_DFX_LINE_LKUP_NUM_EN_S, 1); + dsaf_set_bit(o_tbl_ctrl, DSAF_TBL_DFX_UC_LKUP_NUM_EN_S, 1); + dsaf_set_bit(o_tbl_ctrl, DSAF_TBL_DFX_MC_LKUP_NUM_EN_S, 1); + dsaf_set_bit(o_tbl_ctrl, DSAF_TBL_DFX_BC_LKUP_NUM_EN_S, 1); + dsaf_write_dev(dsaf_dev, DSAF_TBL_DFX_CTRL_0_REG, o_tbl_ctrl); +} + +/** + * hns_dsaf_rocee_bp_en - rocee back press enable + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_rocee_bp_en(struct dsaf_device *dsaf_dev) +{ + dsaf_set_dev_bit(dsaf_dev, DSAF_XGE_CTRL_SIG_CFG_0_REG, + DSAF_FC_XGE_TX_PAUSE_S, 1); +} + +/* set msk for dsaf exception irq*/ +static void hns_dsaf_int_xge_msk_set(struct dsaf_device *dsaf_dev, + u32 chnn_num, u32 mask_set) +{ + dsaf_write_dev(dsaf_dev, + DSAF_XGE_INT_MSK_0_REG + 0x4 * chnn_num, mask_set); +} + +static void hns_dsaf_int_ppe_msk_set(struct dsaf_device *dsaf_dev, + u32 chnn_num, u32 msk_set) +{ + dsaf_write_dev(dsaf_dev, + DSAF_PPE_INT_MSK_0_REG + 0x4 * chnn_num, msk_set); +} + +static void hns_dsaf_int_rocee_msk_set(struct dsaf_device *dsaf_dev, + u32 chnn, u32 msk_set) +{ + dsaf_write_dev(dsaf_dev, + DSAF_ROCEE_INT_MSK_0_REG + 0x4 * chnn, msk_set); +} + +static void +hns_dsaf_int_tbl_msk_set(struct dsaf_device *dsaf_dev, u32 msk_set) +{ + dsaf_write_dev(dsaf_dev, DSAF_TBL_INT_MSK_0_REG, msk_set); +} + +/* clr dsaf exception irq*/ +static void hns_dsaf_int_xge_src_clr(struct dsaf_device *dsaf_dev, + u32 chnn_num, u32 int_src) +{ + dsaf_write_dev(dsaf_dev, + DSAF_XGE_INT_SRC_0_REG + 0x4 * chnn_num, int_src); +} + +static void hns_dsaf_int_ppe_src_clr(struct dsaf_device *dsaf_dev, + u32 chnn, u32 int_src) +{ + dsaf_write_dev(dsaf_dev, + DSAF_PPE_INT_SRC_0_REG + 0x4 * chnn, int_src); +} + +static void hns_dsaf_int_rocee_src_clr(struct dsaf_device *dsaf_dev, + u32 chnn, u32 int_src) +{ + dsaf_write_dev(dsaf_dev, + DSAF_ROCEE_INT_SRC_0_REG + 0x4 * chnn, int_src); +} + +static void hns_dsaf_int_tbl_src_clr(struct dsaf_device *dsaf_dev, + u32 int_src) +{ + dsaf_write_dev(dsaf_dev, DSAF_TBL_INT_SRC_0_REG, int_src); +} + +/** + * hns_dsaf_single_line_tbl_cfg - INT + * @dsaf_id: dsa fabric id + * @address: + * @ptbl_line: + */ +static void hns_dsaf_single_line_tbl_cfg( + struct dsaf_device *dsaf_dev, + u32 address, struct dsaf_tbl_line_cfg *ptbl_line) +{ + /*Write Addr*/ + hns_dsaf_tbl_line_addr_cfg(dsaf_dev, address); + + /*Write Line*/ + hns_dsaf_tbl_line_cfg(dsaf_dev, ptbl_line); + + /*Write Plus*/ + hns_dsaf_tbl_line_pul(dsaf_dev); +} + +/** + * hns_dsaf_tcam_uc_cfg - INT + * @dsaf_id: dsa fabric id + * @address, + * @ptbl_tcam_data, + */ +static void hns_dsaf_tcam_uc_cfg( + struct dsaf_device *dsaf_dev, u32 address, + struct dsaf_tbl_tcam_data *ptbl_tcam_data, + struct dsaf_tbl_tcam_ucast_cfg *ptbl_tcam_ucast) +{ + /*Write Addr*/ + hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address); + /*Write Tcam Data*/ + hns_dsaf_tbl_tcam_data_cfg(dsaf_dev, ptbl_tcam_data); + /*Write Tcam Ucast*/ + hns_dsaf_tbl_tcam_ucast_cfg(dsaf_dev, ptbl_tcam_ucast); + /*Write Plus*/ + hns_dsaf_tbl_tcam_data_ucast_pul(dsaf_dev); +} + +/** + * hns_dsaf_tcam_mc_cfg - INT + * @dsaf_id: dsa fabric id + * @address, + * @ptbl_tcam_data, + * @ptbl_tcam_mcast, + */ +static void hns_dsaf_tcam_mc_cfg( + struct dsaf_device *dsaf_dev, u32 address, + struct dsaf_tbl_tcam_data *ptbl_tcam_data, + struct dsaf_tbl_tcam_mcast_cfg *ptbl_tcam_mcast) +{ + /*Write Addr*/ + hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address); + /*Write Tcam Data*/ + hns_dsaf_tbl_tcam_data_cfg(dsaf_dev, ptbl_tcam_data); + /*Write Tcam Mcast*/ + hns_dsaf_tbl_tcam_mcast_cfg(dsaf_dev, ptbl_tcam_mcast); + /*Write Plus*/ + hns_dsaf_tbl_tcam_data_mcast_pul(dsaf_dev); +} + +/** + * hns_dsaf_tcam_mc_invld - INT + * @dsaf_id: dsa fabric id + * @address + */ +static void hns_dsaf_tcam_mc_invld(struct dsaf_device *dsaf_dev, u32 address) +{ + /*Write Addr*/ + hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address); + + /*write tcam mcast*/ + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_0_0_REG, 0); + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_1_0_REG, 0); + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_2_0_REG, 0); + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_3_0_REG, 0); + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MCAST_CFG_4_0_REG, 0); + + /*Write Plus*/ + hns_dsaf_tbl_tcam_mcast_pul(dsaf_dev); +} + +/** + * hns_dsaf_tcam_uc_get - INT + * @dsaf_id: dsa fabric id + * @address + * @ptbl_tcam_data + * @ptbl_tcam_ucast + */ +static void hns_dsaf_tcam_uc_get( + struct dsaf_device *dsaf_dev, u32 address, + struct dsaf_tbl_tcam_data *ptbl_tcam_data, + struct dsaf_tbl_tcam_ucast_cfg *ptbl_tcam_ucast) +{ + u32 tcam_read_data0; + u32 tcam_read_data4; + + /*Write Addr*/ + hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address); + + /*read tcam item puls*/ + hns_dsaf_tbl_tcam_load_pul(dsaf_dev); + + /*read tcam data*/ + ptbl_tcam_data->tbl_tcam_data_high + = dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_LOW_0_REG); + ptbl_tcam_data->tbl_tcam_data_low + = dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_HIGH_0_REG); + + /*read tcam mcast*/ + tcam_read_data0 = dsaf_read_dev(dsaf_dev, + DSAF_TBL_TCAM_RAM_RDATA0_0_REG); + tcam_read_data4 = dsaf_read_dev(dsaf_dev, + DSAF_TBL_TCAM_RAM_RDATA4_0_REG); + + ptbl_tcam_ucast->tbl_ucast_item_vld + = dsaf_get_bit(tcam_read_data4, + DSAF_TBL_MCAST_CFG4_ITEM_VLD_S); + ptbl_tcam_ucast->tbl_ucast_old_en + = dsaf_get_bit(tcam_read_data4, DSAF_TBL_MCAST_CFG4_OLD_EN_S); + ptbl_tcam_ucast->tbl_ucast_mac_discard + = dsaf_get_bit(tcam_read_data0, + DSAF_TBL_UCAST_CFG1_MAC_DISCARD_S); + ptbl_tcam_ucast->tbl_ucast_out_port + = dsaf_get_field(tcam_read_data0, + DSAF_TBL_UCAST_CFG1_OUT_PORT_M, + DSAF_TBL_UCAST_CFG1_OUT_PORT_S); + ptbl_tcam_ucast->tbl_ucast_dvc + = dsaf_get_bit(tcam_read_data0, DSAF_TBL_UCAST_CFG1_DVC_S); +} + +/** + * hns_dsaf_tcam_mc_get - INT + * @dsaf_id: dsa fabric id + * @address + * @ptbl_tcam_data + * @ptbl_tcam_ucast + */ +static void hns_dsaf_tcam_mc_get( + struct dsaf_device *dsaf_dev, u32 address, + struct dsaf_tbl_tcam_data *ptbl_tcam_data, + struct dsaf_tbl_tcam_mcast_cfg *ptbl_tcam_mcast) +{ + u32 data_tmp; + + /*Write Addr*/ + hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address); + + /*read tcam item puls*/ + hns_dsaf_tbl_tcam_load_pul(dsaf_dev); + + /*read tcam data*/ + ptbl_tcam_data->tbl_tcam_data_high = + dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_LOW_0_REG); + ptbl_tcam_data->tbl_tcam_data_low = + dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RDATA_HIGH_0_REG); + + /*read tcam mcast*/ + ptbl_tcam_mcast->tbl_mcast_port_msk[0] = + dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RAM_RDATA0_0_REG); + ptbl_tcam_mcast->tbl_mcast_port_msk[1] = + dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RAM_RDATA1_0_REG); + ptbl_tcam_mcast->tbl_mcast_port_msk[2] = + dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RAM_RDATA2_0_REG); + ptbl_tcam_mcast->tbl_mcast_port_msk[3] = + dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RAM_RDATA3_0_REG); + + data_tmp = dsaf_read_dev(dsaf_dev, DSAF_TBL_TCAM_RAM_RDATA4_0_REG); + ptbl_tcam_mcast->tbl_mcast_item_vld = + dsaf_get_bit(data_tmp, DSAF_TBL_MCAST_CFG4_ITEM_VLD_S); + ptbl_tcam_mcast->tbl_mcast_old_en = + dsaf_get_bit(data_tmp, DSAF_TBL_MCAST_CFG4_OLD_EN_S); + ptbl_tcam_mcast->tbl_mcast_port_msk[4] = + dsaf_get_field(data_tmp, DSAF_TBL_MCAST_CFG4_VM128_112_M, + DSAF_TBL_MCAST_CFG4_VM128_112_S); +} + +/** + * hns_dsaf_tbl_line_init - INT + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_tbl_line_init(struct dsaf_device *dsaf_dev) +{ + u32 i; + /* defaultly set all lineal mac table entry resulting discard */ + struct dsaf_tbl_line_cfg tbl_line[] = {{1, 0, 0} }; + + for (i = 0; i < DSAF_LINE_SUM; i++) + hns_dsaf_single_line_tbl_cfg(dsaf_dev, i, tbl_line); +} + +/** + * hns_dsaf_tbl_tcam_init - INT + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_tbl_tcam_init(struct dsaf_device *dsaf_dev) +{ + u32 i; + struct dsaf_tbl_tcam_data tcam_data[] = {{0, 0} }; + struct dsaf_tbl_tcam_ucast_cfg tcam_ucast[] = {{0, 0, 0, 0, 0} }; + + /*tcam tbl*/ + for (i = 0; i < DSAF_TCAM_SUM; i++) + hns_dsaf_tcam_uc_cfg(dsaf_dev, i, tcam_data, tcam_ucast); +} + +/** + * hns_dsaf_pfc_en_cfg - dsaf pfc pause cfg + * @mac_cb: mac contrl block + */ +static void hns_dsaf_pfc_en_cfg(struct dsaf_device *dsaf_dev, + int mac_id, int en) +{ + if (!en) + dsaf_write_dev(dsaf_dev, DSAF_PFC_EN_0_REG + mac_id * 4, 0); + else + dsaf_write_dev(dsaf_dev, DSAF_PFC_EN_0_REG + mac_id * 4, 0xff); +} + +/** + * hns_dsaf_tbl_tcam_init - INT + * @dsaf_id: dsa fabric id + * @dsaf_mode + */ +static void hns_dsaf_comm_init(struct dsaf_device *dsaf_dev) +{ + u32 i; + u32 o_dsaf_cfg; + + o_dsaf_cfg = dsaf_read_dev(dsaf_dev, DSAF_CFG_0_REG); + dsaf_set_bit(o_dsaf_cfg, DSAF_CFG_EN_S, dsaf_dev->dsaf_en); + dsaf_set_bit(o_dsaf_cfg, DSAF_CFG_TC_MODE_S, dsaf_dev->dsaf_tc_mode); + dsaf_set_bit(o_dsaf_cfg, DSAF_CFG_CRC_EN_S, 0); + dsaf_set_bit(o_dsaf_cfg, DSAF_CFG_MIX_MODE_S, 0); + dsaf_set_bit(o_dsaf_cfg, DSAF_CFG_LOCA_ADDR_EN_S, 0); + dsaf_write_dev(dsaf_dev, DSAF_CFG_0_REG, o_dsaf_cfg); + + hns_dsaf_reg_cnt_clr_ce(dsaf_dev, 1); + hns_dsaf_stp_port_type_cfg(dsaf_dev, DSAF_STP_PORT_TYPE_FORWARD); + + /* set 22 queue per tx ppe engine, only used in switch mode */ + hns_dsaf_ppe_qid_cfg(dsaf_dev, DSAF_DEFAUTL_QUEUE_NUM_PER_PPE); + + /* in non switch mode, set all port to access mode */ + hns_dsaf_sw_port_type_cfg(dsaf_dev, DSAF_SW_PORT_TYPE_NON_VLAN); + + /*set dsaf pfc to 0 for parseing rx pause*/ + for (i = 0; i < DSAF_COMM_CHN; i++) + hns_dsaf_pfc_en_cfg(dsaf_dev, i, 0); + + /*msk and clr exception irqs */ + for (i = 0; i < DSAF_COMM_CHN; i++) { + hns_dsaf_int_xge_src_clr(dsaf_dev, i, 0xfffffffful); + hns_dsaf_int_ppe_src_clr(dsaf_dev, i, 0xfffffffful); + hns_dsaf_int_rocee_src_clr(dsaf_dev, i, 0xfffffffful); + + hns_dsaf_int_xge_msk_set(dsaf_dev, i, 0xfffffffful); + hns_dsaf_int_ppe_msk_set(dsaf_dev, i, 0xfffffffful); + hns_dsaf_int_rocee_msk_set(dsaf_dev, i, 0xfffffffful); + } + hns_dsaf_int_tbl_src_clr(dsaf_dev, 0xfffffffful); + hns_dsaf_int_tbl_msk_set(dsaf_dev, 0xfffffffful); +} + +/** + * hns_dsaf_inode_init - INT + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_inode_init(struct dsaf_device *dsaf_dev) +{ + u32 reg; + u32 tc_cfg; + u32 i; + + if (dsaf_dev->dsaf_tc_mode == HRD_DSAF_4TC_MODE) + tc_cfg = HNS_DSAF_I4TC_CFG; + else + tc_cfg = HNS_DSAF_I8TC_CFG; + + for (i = 0; i < DSAF_INODE_NUM; i++) { + reg = DSAF_INODE_IN_PORT_NUM_0_REG + 0x80 * i; + dsaf_set_dev_field(dsaf_dev, reg, DSAF_INODE_IN_PORT_NUM_M, + DSAF_INODE_IN_PORT_NUM_S, i % DSAF_XGE_NUM); + + reg = DSAF_INODE_PRI_TC_CFG_0_REG + 0x80 * i; + dsaf_write_dev(dsaf_dev, reg, tc_cfg); + } +} + +/** + * hns_dsaf_sbm_init - INT + * @dsaf_id: dsa fabric id + */ +static int hns_dsaf_sbm_init(struct dsaf_device *dsaf_dev) +{ + u32 flag; + u32 cnt = 0; + int ret; + + hns_dsaf_sbm_bp_wl_cfg(dsaf_dev); + + /* enable sbm chanel, disable sbm chanel shcut function*/ + hns_dsaf_sbm_cfg(dsaf_dev); + + /* enable sbm mib */ + ret = hns_dsaf_sbm_cfg_mib_en(dsaf_dev); + if (ret) { + dev_err(dsaf_dev->dev, + "hns_dsaf_sbm_cfg_mib_en fail,%s, ret=%d\n", + dsaf_dev->ae_dev.name, ret); + return ret; + } + + /* enable sbm initial link sram */ + hns_dsaf_sbm_link_sram_init_en(dsaf_dev); + + do { + usleep_range(200, 210);/*udelay(200);*/ + flag = dsaf_read_dev(dsaf_dev, DSAF_SRAM_INIT_OVER_0_REG); + cnt++; + } while (flag != DSAF_SRAM_INIT_FINISH_FLAG && cnt < DSAF_CFG_READ_CNT); + + if (flag != DSAF_SRAM_INIT_FINISH_FLAG) { + dev_err(dsaf_dev->dev, + "hns_dsaf_sbm_init fail %s, flag=%d, cnt=%d\n", + dsaf_dev->ae_dev.name, flag, cnt); + return -ENODEV; + } + + hns_dsaf_rocee_bp_en(dsaf_dev); + + return 0; +} + +/** + * hns_dsaf_tbl_init - INT + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_tbl_init(struct dsaf_device *dsaf_dev) +{ + hns_dsaf_tbl_stat_en(dsaf_dev); + + hns_dsaf_tbl_tcam_init(dsaf_dev); + hns_dsaf_tbl_line_init(dsaf_dev); +} + +/** + * hns_dsaf_voq_init - INT + * @dsaf_id: dsa fabric id + */ +static void hns_dsaf_voq_init(struct dsaf_device *dsaf_dev) +{ + hns_dsaf_voq_bp_all_thrd_cfg(dsaf_dev); +} + +/** + * hns_dsaf_init_hw - init dsa fabric hardware + * @dsaf_dev: dsa fabric device struct pointer + */ +static int hns_dsaf_init_hw(struct dsaf_device *dsaf_dev) +{ + int ret; + + dev_dbg(dsaf_dev->dev, + "hns_dsaf_init_hw begin %s !\n", dsaf_dev->ae_dev.name); + + hns_dsaf_rst(dsaf_dev, 0); + mdelay(10); + hns_dsaf_rst(dsaf_dev, 1); + + hns_dsaf_comm_init(dsaf_dev); + + /*init XBAR_INODE*/ + hns_dsaf_inode_init(dsaf_dev); + + /*init SBM*/ + ret = hns_dsaf_sbm_init(dsaf_dev); + if (ret) + return ret; + + /*init TBL*/ + hns_dsaf_tbl_init(dsaf_dev); + + /*init VOQ*/ + hns_dsaf_voq_init(dsaf_dev); + + return 0; +} + +/** + * hns_dsaf_remove_hw - uninit dsa fabric hardware + * @dsaf_dev: dsa fabric device struct pointer + */ +static void hns_dsaf_remove_hw(struct dsaf_device *dsaf_dev) +{ + /*reset*/ + hns_dsaf_rst(dsaf_dev, 0); +} + +/** + * hns_dsaf_init - init dsa fabric + * @dsaf_dev: dsa fabric device struct pointer + * retuen 0 - success , negative --fail + */ +static int hns_dsaf_init(struct dsaf_device *dsaf_dev) +{ + struct dsaf_drv_priv *priv = + (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); + u32 i; + int ret; + + ret = hns_dsaf_init_hw(dsaf_dev); + if (ret) + return ret; + + /* malloc mem for tcam mac key(vlan+mac) */ + priv->soft_mac_tbl = vzalloc(sizeof(*priv->soft_mac_tbl) + * DSAF_TCAM_SUM); + if (!priv->soft_mac_tbl) { + ret = -ENOMEM; + goto remove_hw; + } + + /*all entry invall */ + for (i = 0; i < DSAF_TCAM_SUM; i++) + (priv->soft_mac_tbl + i)->index = DSAF_INVALID_ENTRY_IDX; + + return 0; + +remove_hw: + hns_dsaf_remove_hw(dsaf_dev); + return ret; +} + +/** + * hns_dsaf_free - free dsa fabric + * @dsaf_dev: dsa fabric device struct pointer + */ +static void hns_dsaf_free(struct dsaf_device *dsaf_dev) +{ + struct dsaf_drv_priv *priv = + (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); + + hns_dsaf_remove_hw(dsaf_dev); + + /* free all mac mem */ + vfree(priv->soft_mac_tbl); + priv->soft_mac_tbl = NULL; +} + +/** + * hns_dsaf_find_soft_mac_entry - find dsa fabric soft entry + * @dsaf_dev: dsa fabric device struct pointer + * @mac_key: mac entry struct pointer + */ +static u16 hns_dsaf_find_soft_mac_entry( + struct dsaf_device *dsaf_dev, + struct dsaf_drv_tbl_tcam_key *mac_key) +{ + struct dsaf_drv_priv *priv = + (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); + struct dsaf_drv_soft_mac_tbl *soft_mac_entry; + u32 i; + + soft_mac_entry = priv->soft_mac_tbl; + for (i = 0; i < DSAF_TCAM_SUM; i++) { + /* invall tab entry */ + if ((soft_mac_entry->index != DSAF_INVALID_ENTRY_IDX) && + (soft_mac_entry->tcam_key.high.val == mac_key->high.val) && + (soft_mac_entry->tcam_key.low.val == mac_key->low.val)) + /* return find result --soft index */ + return soft_mac_entry->index; + + soft_mac_entry++; + } + return DSAF_INVALID_ENTRY_IDX; +} + +/** + * hns_dsaf_find_empty_mac_entry - search dsa fabric soft empty-entry + * @dsaf_dev: dsa fabric device struct pointer + */ +static u16 hns_dsaf_find_empty_mac_entry(struct dsaf_device *dsaf_dev) +{ + struct dsaf_drv_priv *priv = + (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); + struct dsaf_drv_soft_mac_tbl *soft_mac_entry; + u32 i; + + soft_mac_entry = priv->soft_mac_tbl; + for (i = 0; i < DSAF_TCAM_SUM; i++) { + /* inv all entry */ + if (soft_mac_entry->index == DSAF_INVALID_ENTRY_IDX) + /* return find result --soft index */ + return i; + + soft_mac_entry++; + } + return DSAF_INVALID_ENTRY_IDX; +} + +/** + * hns_dsaf_set_mac_key - set mac key + * @dsaf_dev: dsa fabric device struct pointer + * @mac_key: tcam key pointer + * @vlan_id: vlan id + * @in_port_num: input port num + * @addr: mac addr + */ +static void hns_dsaf_set_mac_key( + struct dsaf_device *dsaf_dev, + struct dsaf_drv_tbl_tcam_key *mac_key, u16 vlan_id, u8 in_port_num, + u8 *addr) +{ + u8 port; + + if (dsaf_dev->dsaf_mode <= DSAF_MODE_ENABLE) + /*DSAF mode : in port id fixed 0*/ + port = 0; + else + /*non-dsaf mode*/ + port = in_port_num; + + mac_key->high.bits.mac_0 = addr[0]; + mac_key->high.bits.mac_1 = addr[1]; + mac_key->high.bits.mac_2 = addr[2]; + mac_key->high.bits.mac_3 = addr[3]; + mac_key->low.bits.mac_4 = addr[4]; + mac_key->low.bits.mac_5 = addr[5]; + mac_key->low.bits.vlan = vlan_id; + mac_key->low.bits.port = port; +} + +/** + * hns_dsaf_set_mac_uc_entry - set mac uc-entry + * @dsaf_dev: dsa fabric device struct pointer + * @mac_entry: uc-mac entry + */ +int hns_dsaf_set_mac_uc_entry( + struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_single_dest_entry *mac_entry) +{ + u16 entry_index = DSAF_INVALID_ENTRY_IDX; + struct dsaf_drv_tbl_tcam_key mac_key; + struct dsaf_tbl_tcam_ucast_cfg mac_data; + struct dsaf_drv_priv *priv = + (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); + struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl; + + /* mac addr check */ + if (MAC_IS_ALL_ZEROS(mac_entry->addr) || + MAC_IS_BROADCAST(mac_entry->addr) || + MAC_IS_MULTICAST(mac_entry->addr)) { + dev_err(dsaf_dev->dev, + "set_uc %s Mac %02x:%02x:%02x:%02x:%02x:%02x err!\n", + dsaf_dev->ae_dev.name, mac_entry->addr[0], + mac_entry->addr[1], mac_entry->addr[2], + mac_entry->addr[3], mac_entry->addr[4], + mac_entry->addr[5]); + return -EINVAL; + } + + /* config key */ + hns_dsaf_set_mac_key(dsaf_dev, &mac_key, mac_entry->in_vlan_id, + mac_entry->in_port_num, mac_entry->addr); + + /* entry ie exist? */ + entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key); + if (entry_index == DSAF_INVALID_ENTRY_IDX) { + /*if has not inv entry,find a empty entry */ + entry_index = hns_dsaf_find_empty_mac_entry(dsaf_dev); + if (entry_index == DSAF_INVALID_ENTRY_IDX) { + /* has not empty,return error */ + dev_err(dsaf_dev->dev, + "set_uc_entry failed, %s Mac key(%#x:%#x)\n", + dsaf_dev->ae_dev.name, + mac_key.high.val, mac_key.low.val); + return -EINVAL; + } + } + + dev_dbg(dsaf_dev->dev, + "set_uc_entry, %s Mac key(%#x:%#x) entry_index%d\n", + dsaf_dev->ae_dev.name, mac_key.high.val, + mac_key.low.val, entry_index); + + /* config hardware entry */ + mac_data.tbl_ucast_item_vld = 1; + mac_data.tbl_ucast_mac_discard = 0; + mac_data.tbl_ucast_old_en = 0; + /* default config dvc to 0 */ + mac_data.tbl_ucast_dvc = 0; + mac_data.tbl_ucast_out_port = mac_entry->port_num; + hns_dsaf_tcam_uc_cfg( + dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data); + + /* config software entry */ + soft_mac_entry += entry_index; + soft_mac_entry->index = entry_index; + soft_mac_entry->tcam_key.high.val = mac_key.high.val; + soft_mac_entry->tcam_key.low.val = mac_key.low.val; + + return 0; +} + +/** + * hns_dsaf_set_mac_mc_entry - set mac mc-entry + * @dsaf_dev: dsa fabric device struct pointer + * @mac_entry: mc-mac entry + */ +int hns_dsaf_set_mac_mc_entry( + struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_multi_dest_entry *mac_entry) +{ + u16 entry_index = DSAF_INVALID_ENTRY_IDX; + struct dsaf_drv_tbl_tcam_key mac_key; + struct dsaf_tbl_tcam_mcast_cfg mac_data; + struct dsaf_drv_priv *priv = + (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); + struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl; + struct dsaf_drv_tbl_tcam_key tmp_mac_key; + + /* mac addr check */ + if (MAC_IS_ALL_ZEROS(mac_entry->addr)) { + dev_err(dsaf_dev->dev, + "set uc %s Mac %02x:%02x:%02x:%02x:%02x:%02x err!\n", + dsaf_dev->ae_dev.name, mac_entry->addr[0], + mac_entry->addr[1], mac_entry->addr[2], + mac_entry->addr[3], + mac_entry->addr[4], mac_entry->addr[5]); + return -EINVAL; + } + + /*config key */ + hns_dsaf_set_mac_key(dsaf_dev, &mac_key, + mac_entry->in_vlan_id, + mac_entry->in_port_num, mac_entry->addr); + + /* entry ie exist? */ + entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key); + if (entry_index == DSAF_INVALID_ENTRY_IDX) { + /*if hasnot, find enpty entry*/ + entry_index = hns_dsaf_find_empty_mac_entry(dsaf_dev); + if (entry_index == DSAF_INVALID_ENTRY_IDX) { + /*if hasnot empty, error*/ + dev_err(dsaf_dev->dev, + "set_uc_entry failed, %s Mac key(%#x:%#x)\n", + dsaf_dev->ae_dev.name, + mac_key.high.val, mac_key.low.val); + return -EINVAL; + } + + /* config hardware entry */ + memset(mac_data.tbl_mcast_port_msk, + 0, sizeof(mac_data.tbl_mcast_port_msk)); + } else { + /* config hardware entry */ + hns_dsaf_tcam_mc_get( + dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)(&tmp_mac_key), &mac_data); + } + mac_data.tbl_mcast_old_en = 0; + mac_data.tbl_mcast_item_vld = 1; + dsaf_set_field(mac_data.tbl_mcast_port_msk[0], + 0x3F, 0, mac_entry->port_mask[0]); + + dev_dbg(dsaf_dev->dev, + "set_uc_entry, %s key(%#x:%#x) entry_index%d\n", + dsaf_dev->ae_dev.name, mac_key.high.val, + mac_key.low.val, entry_index); + + hns_dsaf_tcam_mc_cfg( + dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data); + + /* config software entry */ + soft_mac_entry += entry_index; + soft_mac_entry->index = entry_index; + soft_mac_entry->tcam_key.high.val = mac_key.high.val; + soft_mac_entry->tcam_key.low.val = mac_key.low.val; + + return 0; +} + +/** + * hns_dsaf_add_mac_mc_port - add mac mc-port + * @dsaf_dev: dsa fabric device struct pointer + * @mac_entry: mc-mac entry + */ +int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_single_dest_entry *mac_entry) +{ + u16 entry_index = DSAF_INVALID_ENTRY_IDX; + struct dsaf_drv_tbl_tcam_key mac_key; + struct dsaf_tbl_tcam_mcast_cfg mac_data; + struct dsaf_drv_priv *priv = + (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); + struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl; + struct dsaf_drv_tbl_tcam_key tmp_mac_key; + int mskid; + + /*chechk mac addr */ + if (MAC_IS_ALL_ZEROS(mac_entry->addr)) { + dev_err(dsaf_dev->dev, + "set_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x!\n", + mac_entry->addr[0], mac_entry->addr[1], + mac_entry->addr[2], mac_entry->addr[3], + mac_entry->addr[4], mac_entry->addr[5]); + return -EINVAL; + } + + /*config key */ + hns_dsaf_set_mac_key( + dsaf_dev, &mac_key, mac_entry->in_vlan_id, + mac_entry->in_port_num, mac_entry->addr); + + memset(&mac_data, 0, sizeof(struct dsaf_tbl_tcam_mcast_cfg)); + + /*check exist? */ + entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key); + if (entry_index == DSAF_INVALID_ENTRY_IDX) { + /*if hasnot , find a empty*/ + entry_index = hns_dsaf_find_empty_mac_entry(dsaf_dev); + if (entry_index == DSAF_INVALID_ENTRY_IDX) { + /*if hasnot empty, error*/ + dev_err(dsaf_dev->dev, + "set_uc_entry failed, %s Mac key(%#x:%#x)\n", + dsaf_dev->ae_dev.name, mac_key.high.val, + mac_key.low.val); + return -EINVAL; + } + } else { + /*if exist, add in */ + hns_dsaf_tcam_mc_get( + dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)(&tmp_mac_key), &mac_data); + } + /* config hardware entry */ + if (mac_entry->port_num < DSAF_SERVICE_NW_NUM) { + mskid = mac_entry->port_num; + } else if (mac_entry->port_num >= DSAF_BASE_INNER_PORT_NUM) { + mskid = mac_entry->port_num - + DSAF_BASE_INNER_PORT_NUM + DSAF_SERVICE_NW_NUM; + } else { + dev_err(dsaf_dev->dev, + "%s,pnum(%d)error,key(%#x:%#x)\n", + dsaf_dev->ae_dev.name, mac_entry->port_num, + mac_key.high.val, mac_key.low.val); + return -EINVAL; + } + dsaf_set_bit(mac_data.tbl_mcast_port_msk[mskid / 32], mskid % 32, 1); + mac_data.tbl_mcast_old_en = 0; + mac_data.tbl_mcast_item_vld = 1; + + dev_dbg(dsaf_dev->dev, + "set_uc_entry, %s Mac key(%#x:%#x) entry_index%d\n", + dsaf_dev->ae_dev.name, mac_key.high.val, + mac_key.low.val, entry_index); + + hns_dsaf_tcam_mc_cfg( + dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data); + + /*config software entry */ + soft_mac_entry += entry_index; + soft_mac_entry->index = entry_index; + soft_mac_entry->tcam_key.high.val = mac_key.high.val; + soft_mac_entry->tcam_key.low.val = mac_key.low.val; + + return 0; +} + +/** + * hns_dsaf_del_mac_entry - del mac mc-port + * @dsaf_dev: dsa fabric device struct pointer + * @vlan_id: vlian id + * @in_port_num: input port num + * @addr : mac addr + */ +int hns_dsaf_del_mac_entry(struct dsaf_device *dsaf_dev, u16 vlan_id, + u8 in_port_num, u8 *addr) +{ + u16 entry_index = DSAF_INVALID_ENTRY_IDX; + struct dsaf_drv_tbl_tcam_key mac_key; + struct dsaf_drv_priv *priv = + (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); + struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl; + + /*check mac addr */ + if (MAC_IS_ALL_ZEROS(addr) || MAC_IS_BROADCAST(addr)) { + dev_err(dsaf_dev->dev, + "del_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x!\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + return -EINVAL; + } + + /*config key */ + hns_dsaf_set_mac_key(dsaf_dev, &mac_key, vlan_id, in_port_num, addr); + + /*exist ?*/ + entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key); + if (entry_index == DSAF_INVALID_ENTRY_IDX) { + /*not exist, error */ + dev_err(dsaf_dev->dev, + "del_mac_entry failed, %s Mac key(%#x:%#x)\n", + dsaf_dev->ae_dev.name, + mac_key.high.val, mac_key.low.val); + return -EINVAL; + } + dev_dbg(dsaf_dev->dev, + "del_mac_entry, %s Mac key(%#x:%#x) entry_index%d\n", + dsaf_dev->ae_dev.name, mac_key.high.val, + mac_key.low.val, entry_index); + + /*do del opt*/ + hns_dsaf_tcam_mc_invld(dsaf_dev, entry_index); + + /*del soft emtry */ + soft_mac_entry += entry_index; + soft_mac_entry->index = DSAF_INVALID_ENTRY_IDX; + + return 0; +} + +/** + * hns_dsaf_del_mac_mc_port - del mac mc- port + * @dsaf_dev: dsa fabric device struct pointer + * @mac_entry: mac entry + */ +int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_single_dest_entry *mac_entry) +{ + u16 entry_index = DSAF_INVALID_ENTRY_IDX; + struct dsaf_drv_tbl_tcam_key mac_key; + struct dsaf_drv_priv *priv = + (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); + struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl; + u16 vlan_id; + u8 in_port_num; + struct dsaf_tbl_tcam_mcast_cfg mac_data; + struct dsaf_drv_tbl_tcam_key tmp_mac_key; + int mskid; + const u8 empty_msk[sizeof(mac_data.tbl_mcast_port_msk)] = {0}; + + if (!(void *)mac_entry) { + dev_err(dsaf_dev->dev, + "hns_dsaf_del_mac_mc_port mac_entry is NULL\n"); + return -EINVAL; + } + + /*get key info*/ + vlan_id = mac_entry->in_vlan_id; + in_port_num = mac_entry->in_port_num; + + /*check mac addr */ + if (MAC_IS_ALL_ZEROS(mac_entry->addr)) { + dev_err(dsaf_dev->dev, + "del_port failed, addr %02x:%02x:%02x:%02x:%02x:%02x!\n", + mac_entry->addr[0], mac_entry->addr[1], + mac_entry->addr[2], mac_entry->addr[3], + mac_entry->addr[4], mac_entry->addr[5]); + return -EINVAL; + } + + /*config key */ + hns_dsaf_set_mac_key(dsaf_dev, &mac_key, vlan_id, in_port_num, + mac_entry->addr); + + /*check is exist? */ + entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key); + if (entry_index == DSAF_INVALID_ENTRY_IDX) { + /*find none */ + dev_err(dsaf_dev->dev, + "find_soft_mac_entry failed, %s Mac key(%#x:%#x)\n", + dsaf_dev->ae_dev.name, + mac_key.high.val, mac_key.low.val); + return -EINVAL; + } + + dev_dbg(dsaf_dev->dev, + "del_mac_mc_port, %s key(%#x:%#x) index%d\n", + dsaf_dev->ae_dev.name, mac_key.high.val, + mac_key.low.val, entry_index); + + /*read entry*/ + hns_dsaf_tcam_mc_get( + dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)(&tmp_mac_key), &mac_data); + + /*del the port*/ + if (mac_entry->port_num < DSAF_SERVICE_NW_NUM) { + mskid = mac_entry->port_num; + } else if (mac_entry->port_num >= DSAF_BASE_INNER_PORT_NUM) { + mskid = mac_entry->port_num - + DSAF_BASE_INNER_PORT_NUM + DSAF_SERVICE_NW_NUM; + } else { + dev_err(dsaf_dev->dev, + "%s,pnum(%d)error,key(%#x:%#x)\n", + dsaf_dev->ae_dev.name, mac_entry->port_num, + mac_key.high.val, mac_key.low.val); + return -EINVAL; + } + dsaf_set_bit(mac_data.tbl_mcast_port_msk[mskid / 32], mskid % 32, 0); + + /*check non port, do del entry */ + if (!memcmp(mac_data.tbl_mcast_port_msk, empty_msk, + sizeof(mac_data.tbl_mcast_port_msk))) { + hns_dsaf_tcam_mc_invld(dsaf_dev, entry_index); + + /* del soft entry */ + soft_mac_entry += entry_index; + soft_mac_entry->index = DSAF_INVALID_ENTRY_IDX; + } else { /* not zer, just del port, updata*/ + hns_dsaf_tcam_mc_cfg( + dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data); + } + + return 0; +} + +/** + * hns_dsaf_get_mac_uc_entry - get mac uc entry + * @dsaf_dev: dsa fabric device struct pointer + * @mac_entry: mac entry + */ +int hns_dsaf_get_mac_uc_entry(struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_single_dest_entry *mac_entry) +{ + u16 entry_index = DSAF_INVALID_ENTRY_IDX; + struct dsaf_drv_tbl_tcam_key mac_key; + + struct dsaf_tbl_tcam_ucast_cfg mac_data; + + /* check macaddr */ + if (MAC_IS_ALL_ZEROS(mac_entry->addr) || + MAC_IS_BROADCAST(mac_entry->addr)) { + dev_err(dsaf_dev->dev, + "get_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_entry->addr[0], mac_entry->addr[1], + mac_entry->addr[2], mac_entry->addr[3], + mac_entry->addr[4], mac_entry->addr[5]); + return -EINVAL; + } + + /*config key */ + hns_dsaf_set_mac_key(dsaf_dev, &mac_key, mac_entry->in_vlan_id, + mac_entry->in_port_num, mac_entry->addr); + + /*check exist? */ + entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key); + if (entry_index == DSAF_INVALID_ENTRY_IDX) { + /*find none, error */ + dev_err(dsaf_dev->dev, + "get_uc_entry failed, %s Mac key(%#x:%#x)\n", + dsaf_dev->ae_dev.name, + mac_key.high.val, mac_key.low.val); + return -EINVAL; + } + dev_dbg(dsaf_dev->dev, + "get_uc_entry, %s Mac key(%#x:%#x) entry_index%d\n", + dsaf_dev->ae_dev.name, mac_key.high.val, + mac_key.low.val, entry_index); + + /*read entry*/ + hns_dsaf_tcam_uc_get(dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data); + mac_entry->port_num = mac_data.tbl_ucast_out_port; + + return 0; +} + +/** + * hns_dsaf_get_mac_mc_entry - get mac mc entry + * @dsaf_dev: dsa fabric device struct pointer + * @mac_entry: mac entry + */ +int hns_dsaf_get_mac_mc_entry(struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_multi_dest_entry *mac_entry) +{ + u16 entry_index = DSAF_INVALID_ENTRY_IDX; + struct dsaf_drv_tbl_tcam_key mac_key; + + struct dsaf_tbl_tcam_mcast_cfg mac_data; + + /*check mac addr */ + if (MAC_IS_ALL_ZEROS(mac_entry->addr) || + MAC_IS_BROADCAST(mac_entry->addr)) { + dev_err(dsaf_dev->dev, + "get_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x\n", + mac_entry->addr[0], mac_entry->addr[1], + mac_entry->addr[2], mac_entry->addr[3], + mac_entry->addr[4], mac_entry->addr[5]); + return -EINVAL; + } + + /*config key */ + hns_dsaf_set_mac_key(dsaf_dev, &mac_key, mac_entry->in_vlan_id, + mac_entry->in_port_num, mac_entry->addr); + + /*check exist? */ + entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key); + if (entry_index == DSAF_INVALID_ENTRY_IDX) { + /* find none, error */ + dev_err(dsaf_dev->dev, + "get_mac_uc_entry failed, %s Mac key(%#x:%#x)\n", + dsaf_dev->ae_dev.name, mac_key.high.val, + mac_key.low.val); + return -EINVAL; + } + dev_dbg(dsaf_dev->dev, + "get_mac_uc_entry, %s Mac key(%#x:%#x) entry_index%d\n", + dsaf_dev->ae_dev.name, mac_key.high.val, + mac_key.low.val, entry_index); + + /*read entry */ + hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data); + + mac_entry->port_mask[0] = mac_data.tbl_mcast_port_msk[0] & 0x3F; + return 0; +} + +/** + * hns_dsaf_get_mac_entry_by_index - get mac entry by tab index + * @dsaf_dev: dsa fabric device struct pointer + * @entry_index: tab entry index + * @mac_entry: mac entry + */ +int hns_dsaf_get_mac_entry_by_index( + struct dsaf_device *dsaf_dev, + u16 entry_index, struct dsaf_drv_mac_multi_dest_entry *mac_entry) +{ + struct dsaf_drv_tbl_tcam_key mac_key; + + struct dsaf_tbl_tcam_mcast_cfg mac_data; + struct dsaf_tbl_tcam_ucast_cfg mac_uc_data; + char mac_addr[MAC_NUM_OCTETS_PER_ADDR] = {0}; + + if (entry_index >= DSAF_TCAM_SUM) { + /* find none, del error */ + dev_err(dsaf_dev->dev, "get_uc_entry failed, %s\n", + dsaf_dev->ae_dev.name); + return -EINVAL; + } + + /* mc entry, do read opt */ + hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data); + + mac_entry->port_mask[0] = mac_data.tbl_mcast_port_msk[0] & 0x3F; + + /***get mac addr*/ + mac_addr[0] = mac_key.high.bits.mac_0; + mac_addr[1] = mac_key.high.bits.mac_1; + mac_addr[2] = mac_key.high.bits.mac_2; + mac_addr[3] = mac_key.high.bits.mac_3; + mac_addr[4] = mac_key.low.bits.mac_4; + mac_addr[5] = mac_key.low.bits.mac_5; + /**is mc or uc*/ + if (MAC_IS_MULTICAST((u8 *)mac_addr) || + MAC_IS_L3_MULTICAST((u8 *)mac_addr)) { + /**mc donot do*/ + } else { + /*is not mc, just uc... */ + hns_dsaf_tcam_uc_get(dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)&mac_key, + &mac_uc_data); + mac_entry->port_mask[0] = (1 << mac_uc_data.tbl_ucast_out_port); + } + + return 0; +} + +static struct dsaf_device *hns_dsaf_alloc_dev(struct device *dev, + size_t sizeof_priv) +{ + struct dsaf_device *dsaf_dev; + + dsaf_dev = devm_kzalloc(dev, + sizeof(*dsaf_dev) + sizeof_priv, GFP_KERNEL); + if (unlikely(!dsaf_dev)) { + dsaf_dev = ERR_PTR(-ENOMEM); + } else { + dsaf_dev->dev = dev; + dev_set_drvdata(dev, dsaf_dev); + } + + return dsaf_dev; +} + +/** + * hns_dsaf_free_dev - free dev mem + * @dev: struct device pointer + */ +static void hns_dsaf_free_dev(struct dsaf_device *dsaf_dev) +{ + (void)dev_set_drvdata(dsaf_dev->dev, NULL); +} + +/** + * dsaf_pfc_unit_cnt - set pfc unit count + * @dsaf_id: dsa fabric id + * @pport_rate: value array + * @pdsaf_pfc_unit_cnt: value array + */ +static void hns_dsaf_pfc_unit_cnt(struct dsaf_device *dsaf_dev, int mac_id, + enum dsaf_port_rate_mode rate) +{ + u32 unit_cnt; + + switch (rate) { + case DSAF_PORT_RATE_10000: + unit_cnt = HNS_DSAF_PFC_UNIT_CNT_FOR_XGE; + break; + case DSAF_PORT_RATE_1000: + unit_cnt = HNS_DSAF_PFC_UNIT_CNT_FOR_GE_1000; + break; + case DSAF_PORT_RATE_2500: + unit_cnt = HNS_DSAF_PFC_UNIT_CNT_FOR_GE_1000; + break; + default: + unit_cnt = HNS_DSAF_PFC_UNIT_CNT_FOR_XGE; + } + + dsaf_set_dev_field(dsaf_dev, + (DSAF_PFC_UNIT_CNT_0_REG + 0x4 * (u64)mac_id), + DSAF_PFC_UNINT_CNT_M, DSAF_PFC_UNINT_CNT_S, + unit_cnt); +} + +/** + * dsaf_port_work_rate_cfg - fifo + * @dsaf_id: dsa fabric id + * @xge_ge_work_mode + */ +void hns_dsaf_port_work_rate_cfg(struct dsaf_device *dsaf_dev, int mac_id, + enum dsaf_port_rate_mode rate_mode) +{ + u32 port_work_mode; + + port_work_mode = dsaf_read_dev( + dsaf_dev, DSAF_XGE_GE_WORK_MODE_0_REG + 0x4 * (u64)mac_id); + + if (rate_mode == DSAF_PORT_RATE_10000) + dsaf_set_bit(port_work_mode, DSAF_XGE_GE_WORK_MODE_S, 1); + else + dsaf_set_bit(port_work_mode, DSAF_XGE_GE_WORK_MODE_S, 0); + + dsaf_write_dev(dsaf_dev, + DSAF_XGE_GE_WORK_MODE_0_REG + 0x4 * (u64)mac_id, + port_work_mode); + + hns_dsaf_pfc_unit_cnt(dsaf_dev, mac_id, rate_mode); +} + +/** + * hns_dsaf_fix_mac_mode - dsaf modify mac mode + * @mac_cb: mac contrl block + */ +void hns_dsaf_fix_mac_mode(struct hns_mac_cb *mac_cb) +{ + enum dsaf_port_rate_mode mode; + struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; + int mac_id = mac_cb->mac_id; + + if (mac_cb->mac_type != HNAE_PORT_SERVICE) + return; + if (mac_cb->phy_if == PHY_INTERFACE_MODE_XGMII) + mode = DSAF_PORT_RATE_10000; + else + mode = DSAF_PORT_RATE_1000; + + hns_dsaf_port_work_rate_cfg(dsaf_dev, mac_id, mode); +} + +void hns_dsaf_update_stats(struct dsaf_device *dsaf_dev, u32 node_num) +{ + struct dsaf_hw_stats *hw_stats + = &dsaf_dev->hw_stats[node_num]; + + hw_stats->pad_drop += dsaf_read_dev(dsaf_dev, + DSAF_INODE_PAD_DISCARD_NUM_0_REG + 0x80 * (u64)node_num); + hw_stats->man_pkts += dsaf_read_dev(dsaf_dev, + DSAF_INODE_FINAL_IN_MAN_NUM_0_REG + 0x80 * (u64)node_num); + hw_stats->rx_pkts += dsaf_read_dev(dsaf_dev, + DSAF_INODE_FINAL_IN_PKT_NUM_0_REG + 0x80 * (u64)node_num); + hw_stats->rx_pkt_id += dsaf_read_dev(dsaf_dev, + DSAF_INODE_SBM_PID_NUM_0_REG + 0x80 * (u64)node_num); + hw_stats->rx_pause_frame += dsaf_read_dev(dsaf_dev, + DSAF_INODE_FINAL_IN_PAUSE_NUM_0_REG + 0x80 * (u64)node_num); + hw_stats->release_buf_num += dsaf_read_dev(dsaf_dev, + DSAF_INODE_SBM_RELS_NUM_0_REG + 0x80 * (u64)node_num); + hw_stats->sbm_drop += dsaf_read_dev(dsaf_dev, + DSAF_INODE_SBM_DROP_NUM_0_REG + 0x80 * (u64)node_num); + hw_stats->crc_false += dsaf_read_dev(dsaf_dev, + DSAF_INODE_CRC_FALSE_NUM_0_REG + 0x80 * (u64)node_num); + hw_stats->bp_drop += dsaf_read_dev(dsaf_dev, + DSAF_INODE_BP_DISCARD_NUM_0_REG + 0x80 * (u64)node_num); + hw_stats->rslt_drop += dsaf_read_dev(dsaf_dev, + DSAF_INODE_RSLT_DISCARD_NUM_0_REG + 0x80 * (u64)node_num); + hw_stats->local_addr_false += dsaf_read_dev(dsaf_dev, + DSAF_INODE_LOCAL_ADDR_FALSE_NUM_0_REG + 0x80 * (u64)node_num); + + hw_stats->vlan_drop += dsaf_read_dev(dsaf_dev, + DSAF_INODE_SW_VLAN_TAG_DISC_0_REG + 0x80 * (u64)node_num); + hw_stats->stp_drop += dsaf_read_dev(dsaf_dev, + DSAF_INODE_IN_DATA_STP_DISC_0_REG + 0x80 * (u64)node_num); + + hw_stats->tx_pkts += dsaf_read_dev(dsaf_dev, + DSAF_XOD_RCVPKT_CNT_0_REG + 0x90 * (u64)node_num); +} + +/** + *hns_dsaf_get_regs - dump dsaf regs + *@dsaf_dev: dsaf device + *@data:data for value of regs + */ +void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data) +{ + u32 i = 0; + u32 j; + u32 *p = data; + + /* dsaf common registers */ + p[0] = dsaf_read_dev(ddev, DSAF_SRAM_INIT_OVER_0_REG); + p[1] = dsaf_read_dev(ddev, DSAF_CFG_0_REG); + p[2] = dsaf_read_dev(ddev, DSAF_ECC_ERR_INVERT_0_REG); + p[3] = dsaf_read_dev(ddev, DSAF_ABNORMAL_TIMEOUT_0_REG); + p[4] = dsaf_read_dev(ddev, DSAF_FSM_TIMEOUT_0_REG); + p[5] = dsaf_read_dev(ddev, DSAF_DSA_REG_CNT_CLR_CE_REG); + p[6] = dsaf_read_dev(ddev, DSAF_DSA_SBM_INF_FIFO_THRD_REG); + p[7] = dsaf_read_dev(ddev, DSAF_DSA_SRAM_1BIT_ECC_SEL_REG); + p[8] = dsaf_read_dev(ddev, DSAF_DSA_SRAM_1BIT_ECC_CNT_REG); + + p[9] = dsaf_read_dev(ddev, DSAF_PFC_EN_0_REG + port * 4); + p[10] = dsaf_read_dev(ddev, DSAF_PFC_UNIT_CNT_0_REG + port * 4); + p[11] = dsaf_read_dev(ddev, DSAF_XGE_INT_MSK_0_REG + port * 4); + p[12] = dsaf_read_dev(ddev, DSAF_XGE_INT_SRC_0_REG + port * 4); + p[13] = dsaf_read_dev(ddev, DSAF_XGE_INT_STS_0_REG + port * 4); + p[14] = dsaf_read_dev(ddev, DSAF_XGE_INT_MSK_0_REG + port * 4); + p[15] = dsaf_read_dev(ddev, DSAF_PPE_INT_MSK_0_REG + port * 4); + p[16] = dsaf_read_dev(ddev, DSAF_ROCEE_INT_MSK_0_REG + port * 4); + p[17] = dsaf_read_dev(ddev, DSAF_XGE_INT_SRC_0_REG + port * 4); + p[18] = dsaf_read_dev(ddev, DSAF_PPE_INT_SRC_0_REG + port * 4); + p[19] = dsaf_read_dev(ddev, DSAF_ROCEE_INT_SRC_0_REG + port * 4); + p[20] = dsaf_read_dev(ddev, DSAF_XGE_INT_STS_0_REG + port * 4); + p[21] = dsaf_read_dev(ddev, DSAF_PPE_INT_STS_0_REG + port * 4); + p[22] = dsaf_read_dev(ddev, DSAF_ROCEE_INT_STS_0_REG + port * 4); + p[23] = dsaf_read_dev(ddev, DSAF_PPE_QID_CFG_0_REG + port * 4); + + for (i = 0; i < DSAF_SW_PORT_NUM; i++) + p[24 + i] = dsaf_read_dev(ddev, + DSAF_SW_PORT_TYPE_0_REG + i * 4); + + p[32] = dsaf_read_dev(ddev, DSAF_MIX_DEF_QID_0_REG + port * 4); + + for (i = 0; i < DSAF_SW_PORT_NUM; i++) + p[33 + i] = dsaf_read_dev(ddev, + DSAF_PORT_DEF_VLAN_0_REG + i * 4); + + for (i = 0; i < DSAF_TOTAL_QUEUE_NUM; i++) + p[41 + i] = dsaf_read_dev(ddev, + DSAF_VM_DEF_VLAN_0_REG + i * 4); + + /* dsaf inode registers */ + p[170] = dsaf_read_dev(ddev, DSAF_INODE_CUT_THROUGH_CFG_0_REG); + + p[171] = dsaf_read_dev(ddev, + DSAF_INODE_ECC_ERR_ADDR_0_REG + port * 0x80); + + for (i = 0; i < DSAF_INODE_NUM / DSAF_COMM_CHN; i++) { + j = i * DSAF_COMM_CHN + port; + p[172 + i] = dsaf_read_dev(ddev, + DSAF_INODE_IN_PORT_NUM_0_REG + j * 0x80); + p[175 + i] = dsaf_read_dev(ddev, + DSAF_INODE_PRI_TC_CFG_0_REG + j * 0x80); + p[178 + i] = dsaf_read_dev(ddev, + DSAF_INODE_BP_STATUS_0_REG + j * 0x80); + p[181 + i] = dsaf_read_dev(ddev, + DSAF_INODE_PAD_DISCARD_NUM_0_REG + j * 0x80); + p[184 + i] = dsaf_read_dev(ddev, + DSAF_INODE_FINAL_IN_MAN_NUM_0_REG + j * 0x80); + p[187 + i] = dsaf_read_dev(ddev, + DSAF_INODE_FINAL_IN_PKT_NUM_0_REG + j * 0x80); + p[190 + i] = dsaf_read_dev(ddev, + DSAF_INODE_SBM_PID_NUM_0_REG + j * 0x80); + p[193 + i] = dsaf_read_dev(ddev, + DSAF_INODE_FINAL_IN_PAUSE_NUM_0_REG + j * 0x80); + p[196 + i] = dsaf_read_dev(ddev, + DSAF_INODE_SBM_RELS_NUM_0_REG + j * 0x80); + p[199 + i] = dsaf_read_dev(ddev, + DSAF_INODE_SBM_DROP_NUM_0_REG + j * 0x80); + p[202 + i] = dsaf_read_dev(ddev, + DSAF_INODE_CRC_FALSE_NUM_0_REG + j * 0x80); + p[205 + i] = dsaf_read_dev(ddev, + DSAF_INODE_BP_DISCARD_NUM_0_REG + j * 0x80); + p[208 + i] = dsaf_read_dev(ddev, + DSAF_INODE_RSLT_DISCARD_NUM_0_REG + j * 0x80); + p[211 + i] = dsaf_read_dev(ddev, + DSAF_INODE_LOCAL_ADDR_FALSE_NUM_0_REG + j * 0x80); + p[214 + i] = dsaf_read_dev(ddev, + DSAF_INODE_VOQ_OVER_NUM_0_REG + j * 0x80); + p[217 + i] = dsaf_read_dev(ddev, + DSAF_INODE_BD_SAVE_STATUS_0_REG + j * 4); + p[220 + i] = dsaf_read_dev(ddev, + DSAF_INODE_BD_ORDER_STATUS_0_REG + j * 4); + p[223 + i] = dsaf_read_dev(ddev, + DSAF_INODE_SW_VLAN_TAG_DISC_0_REG + j * 4); + p[224 + i] = dsaf_read_dev(ddev, + DSAF_INODE_IN_DATA_STP_DISC_0_REG + j * 4); + } + + p[227] = dsaf_read_dev(ddev, DSAF_INODE_GE_FC_EN_0_REG + port * 4); + + for (i = 0; i < DSAF_INODE_NUM / DSAF_COMM_CHN; i++) { + j = i * DSAF_COMM_CHN + port; + p[228 + i] = dsaf_read_dev(ddev, + DSAF_INODE_VC0_IN_PKT_NUM_0_REG + j * 4); + } + + p[231] = dsaf_read_dev(ddev, + DSAF_INODE_VC1_IN_PKT_NUM_0_REG + port * 4); + + /* dsaf inode registers */ + for (i = 0; i < DSAF_SBM_NUM / DSAF_COMM_CHN; i++) { + j = i * DSAF_COMM_CHN + port; + p[232 + i] = dsaf_read_dev(ddev, + DSAF_SBM_CFG_REG_0_REG + j * 0x80); + p[235 + i] = dsaf_read_dev(ddev, + DSAF_SBM_BP_CFG_0_XGE_REG_0_REG + j * 0x80); + p[238 + i] = dsaf_read_dev(ddev, + DSAF_SBM_BP_CFG_1_REG_0_REG + j * 0x80); + p[241 + i] = dsaf_read_dev(ddev, + DSAF_SBM_BP_CFG_2_XGE_REG_0_REG + j * 0x80); + p[244 + i] = dsaf_read_dev(ddev, + DSAF_SBM_FREE_CNT_0_0_REG + j * 0x80); + p[245 + i] = dsaf_read_dev(ddev, + DSAF_SBM_FREE_CNT_1_0_REG + j * 0x80); + p[248 + i] = dsaf_read_dev(ddev, + DSAF_SBM_BP_CNT_0_0_REG + j * 0x80); + p[251 + i] = dsaf_read_dev(ddev, + DSAF_SBM_BP_CNT_1_0_REG + j * 0x80); + p[254 + i] = dsaf_read_dev(ddev, + DSAF_SBM_BP_CNT_2_0_REG + j * 0x80); + p[257 + i] = dsaf_read_dev(ddev, + DSAF_SBM_BP_CNT_3_0_REG + j * 0x80); + p[260 + i] = dsaf_read_dev(ddev, + DSAF_SBM_INER_ST_0_REG + j * 0x80); + p[263 + i] = dsaf_read_dev(ddev, + DSAF_SBM_MIB_REQ_FAILED_TC_0_REG + j * 0x80); + p[266 + i] = dsaf_read_dev(ddev, + DSAF_SBM_LNK_INPORT_CNT_0_REG + j * 0x80); + p[269 + i] = dsaf_read_dev(ddev, + DSAF_SBM_LNK_DROP_CNT_0_REG + j * 0x80); + p[272 + i] = dsaf_read_dev(ddev, + DSAF_SBM_INF_OUTPORT_CNT_0_REG + j * 0x80); + p[275 + i] = dsaf_read_dev(ddev, + DSAF_SBM_LNK_INPORT_TC0_CNT_0_REG + j * 0x80); + p[278 + i] = dsaf_read_dev(ddev, + DSAF_SBM_LNK_INPORT_TC1_CNT_0_REG + j * 0x80); + p[281 + i] = dsaf_read_dev(ddev, + DSAF_SBM_LNK_INPORT_TC2_CNT_0_REG + j * 0x80); + p[284 + i] = dsaf_read_dev(ddev, + DSAF_SBM_LNK_INPORT_TC3_CNT_0_REG + j * 0x80); + p[287 + i] = dsaf_read_dev(ddev, + DSAF_SBM_LNK_INPORT_TC4_CNT_0_REG + j * 0x80); + p[290 + i] = dsaf_read_dev(ddev, + DSAF_SBM_LNK_INPORT_TC5_CNT_0_REG + j * 0x80); + p[293 + i] = dsaf_read_dev(ddev, + DSAF_SBM_LNK_INPORT_TC6_CNT_0_REG + j * 0x80); + p[296 + i] = dsaf_read_dev(ddev, + DSAF_SBM_LNK_INPORT_TC7_CNT_0_REG + j * 0x80); + p[299 + i] = dsaf_read_dev(ddev, + DSAF_SBM_LNK_REQ_CNT_0_REG + j * 0x80); + p[302 + i] = dsaf_read_dev(ddev, + DSAF_SBM_LNK_RELS_CNT_0_REG + j * 0x80); + p[305 + i] = dsaf_read_dev(ddev, + DSAF_SBM_BP_CFG_3_REG_0_REG + j * 0x80); + p[308 + i] = dsaf_read_dev(ddev, + DSAF_SBM_BP_CFG_4_REG_0_REG + j * 0x80); + } + + /* dsaf onode registers */ + for (i = 0; i < DSAF_XOD_NUM; i++) { + p[311 + i] = dsaf_read_dev(ddev, + DSAF_XOD_ETS_TSA_TC0_TC3_CFG_0_REG + j * 0x90); + p[319 + i] = dsaf_read_dev(ddev, + DSAF_XOD_ETS_TSA_TC4_TC7_CFG_0_REG + j * 0x90); + p[327 + i] = dsaf_read_dev(ddev, + DSAF_XOD_ETS_BW_TC0_TC3_CFG_0_REG + j * 0x90); + p[335 + i] = dsaf_read_dev(ddev, + DSAF_XOD_ETS_BW_TC4_TC7_CFG_0_REG + j * 0x90); + p[343 + i] = dsaf_read_dev(ddev, + DSAF_XOD_ETS_BW_OFFSET_CFG_0_REG + j * 0x90); + p[351 + i] = dsaf_read_dev(ddev, + DSAF_XOD_ETS_TOKEN_CFG_0_REG + j * 0x90); + } + + p[359] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_0_0_REG + port * 0x90); + p[360] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_1_0_REG + port * 0x90); + p[361] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_2_0_REG + port * 0x90); + + for (i = 0; i < DSAF_XOD_BIG_NUM / DSAF_COMM_CHN; i++) { + j = i * DSAF_COMM_CHN + port; + p[362 + i] = dsaf_read_dev(ddev, + DSAF_XOD_GNT_L_0_REG + j * 0x90); + p[365 + i] = dsaf_read_dev(ddev, + DSAF_XOD_GNT_H_0_REG + j * 0x90); + p[368 + i] = dsaf_read_dev(ddev, + DSAF_XOD_CONNECT_STATE_0_REG + j * 0x90); + p[371 + i] = dsaf_read_dev(ddev, + DSAF_XOD_RCVPKT_CNT_0_REG + j * 0x90); + p[374 + i] = dsaf_read_dev(ddev, + DSAF_XOD_RCVTC0_CNT_0_REG + j * 0x90); + p[377 + i] = dsaf_read_dev(ddev, + DSAF_XOD_RCVTC1_CNT_0_REG + j * 0x90); + p[380 + i] = dsaf_read_dev(ddev, + DSAF_XOD_RCVTC2_CNT_0_REG + j * 0x90); + p[383 + i] = dsaf_read_dev(ddev, + DSAF_XOD_RCVTC3_CNT_0_REG + j * 0x90); + p[386 + i] = dsaf_read_dev(ddev, + DSAF_XOD_RCVVC0_CNT_0_REG + j * 0x90); + p[389 + i] = dsaf_read_dev(ddev, + DSAF_XOD_RCVVC1_CNT_0_REG + j * 0x90); + } + + p[392] = dsaf_read_dev(ddev, + DSAF_XOD_XGE_RCVIN0_CNT_0_REG + port * 0x90); + p[393] = dsaf_read_dev(ddev, + DSAF_XOD_XGE_RCVIN1_CNT_0_REG + port * 0x90); + p[394] = dsaf_read_dev(ddev, + DSAF_XOD_XGE_RCVIN2_CNT_0_REG + port * 0x90); + p[395] = dsaf_read_dev(ddev, + DSAF_XOD_XGE_RCVIN3_CNT_0_REG + port * 0x90); + p[396] = dsaf_read_dev(ddev, + DSAF_XOD_XGE_RCVIN4_CNT_0_REG + port * 0x90); + p[397] = dsaf_read_dev(ddev, + DSAF_XOD_XGE_RCVIN5_CNT_0_REG + port * 0x90); + p[398] = dsaf_read_dev(ddev, + DSAF_XOD_XGE_RCVIN6_CNT_0_REG + port * 0x90); + p[399] = dsaf_read_dev(ddev, + DSAF_XOD_XGE_RCVIN7_CNT_0_REG + port * 0x90); + p[400] = dsaf_read_dev(ddev, + DSAF_XOD_PPE_RCVIN0_CNT_0_REG + port * 0x90); + p[401] = dsaf_read_dev(ddev, + DSAF_XOD_PPE_RCVIN1_CNT_0_REG + port * 0x90); + p[402] = dsaf_read_dev(ddev, + DSAF_XOD_ROCEE_RCVIN0_CNT_0_REG + port * 0x90); + p[403] = dsaf_read_dev(ddev, + DSAF_XOD_ROCEE_RCVIN1_CNT_0_REG + port * 0x90); + p[404] = dsaf_read_dev(ddev, + DSAF_XOD_FIFO_STATUS_0_REG + port * 0x90); + + /* dsaf voq registers */ + for (i = 0; i < DSAF_VOQ_NUM / DSAF_COMM_CHN; i++) { + j = (i * DSAF_COMM_CHN + port) * 0x90; + p[405 + i] = dsaf_read_dev(ddev, + DSAF_VOQ_ECC_INVERT_EN_0_REG + j); + p[408 + i] = dsaf_read_dev(ddev, + DSAF_VOQ_SRAM_PKT_NUM_0_REG + j); + p[411 + i] = dsaf_read_dev(ddev, DSAF_VOQ_IN_PKT_NUM_0_REG + j); + p[414 + i] = dsaf_read_dev(ddev, + DSAF_VOQ_OUT_PKT_NUM_0_REG + j); + p[417 + i] = dsaf_read_dev(ddev, + DSAF_VOQ_ECC_ERR_ADDR_0_REG + j); + p[420 + i] = dsaf_read_dev(ddev, DSAF_VOQ_BP_STATUS_0_REG + j); + p[423 + i] = dsaf_read_dev(ddev, DSAF_VOQ_SPUP_IDLE_0_REG + j); + p[426 + i] = dsaf_read_dev(ddev, + DSAF_VOQ_XGE_XOD_REQ_0_0_REG + j); + p[429 + i] = dsaf_read_dev(ddev, + DSAF_VOQ_XGE_XOD_REQ_1_0_REG + j); + p[432 + i] = dsaf_read_dev(ddev, + DSAF_VOQ_PPE_XOD_REQ_0_REG + j); + p[435 + i] = dsaf_read_dev(ddev, + DSAF_VOQ_ROCEE_XOD_REQ_0_REG + j); + p[438 + i] = dsaf_read_dev(ddev, + DSAF_VOQ_BP_ALL_THRD_0_REG + j); + } + + /* dsaf tbl registers */ + p[441] = dsaf_read_dev(ddev, DSAF_TBL_CTRL_0_REG); + p[442] = dsaf_read_dev(ddev, DSAF_TBL_INT_MSK_0_REG); + p[443] = dsaf_read_dev(ddev, DSAF_TBL_INT_SRC_0_REG); + p[444] = dsaf_read_dev(ddev, DSAF_TBL_INT_STS_0_REG); + p[445] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_ADDR_0_REG); + p[446] = dsaf_read_dev(ddev, DSAF_TBL_LINE_ADDR_0_REG); + p[447] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_HIGH_0_REG); + p[448] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_LOW_0_REG); + p[449] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_4_0_REG); + p[450] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_3_0_REG); + p[451] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_2_0_REG); + p[452] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_1_0_REG); + p[453] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_MCAST_CFG_0_0_REG); + p[454] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_UCAST_CFG_0_REG); + p[455] = dsaf_read_dev(ddev, DSAF_TBL_LIN_CFG_0_REG); + p[456] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RDATA_HIGH_0_REG); + p[457] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RDATA_LOW_0_REG); + p[458] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA4_0_REG); + p[459] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA3_0_REG); + p[460] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA2_0_REG); + p[461] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA1_0_REG); + p[462] = dsaf_read_dev(ddev, DSAF_TBL_TCAM_RAM_RDATA0_0_REG); + p[463] = dsaf_read_dev(ddev, DSAF_TBL_LIN_RDATA_0_REG); + + for (i = 0; i < DSAF_SW_PORT_NUM; i++) { + j = i * 0x8; + p[464 + 2 * i] = dsaf_read_dev(ddev, + DSAF_TBL_DA0_MIS_INFO1_0_REG + j); + p[465 + 2 * i] = dsaf_read_dev(ddev, + DSAF_TBL_DA0_MIS_INFO0_0_REG + j); + } + + p[480] = dsaf_read_dev(ddev, DSAF_TBL_SA_MIS_INFO2_0_REG); + p[481] = dsaf_read_dev(ddev, DSAF_TBL_SA_MIS_INFO1_0_REG); + p[482] = dsaf_read_dev(ddev, DSAF_TBL_SA_MIS_INFO0_0_REG); + p[483] = dsaf_read_dev(ddev, DSAF_TBL_PUL_0_REG); + p[484] = dsaf_read_dev(ddev, DSAF_TBL_OLD_RSLT_0_REG); + p[485] = dsaf_read_dev(ddev, DSAF_TBL_OLD_SCAN_VAL_0_REG); + p[486] = dsaf_read_dev(ddev, DSAF_TBL_DFX_CTRL_0_REG); + p[487] = dsaf_read_dev(ddev, DSAF_TBL_DFX_STAT_0_REG); + p[488] = dsaf_read_dev(ddev, DSAF_TBL_DFX_STAT_2_0_REG); + p[489] = dsaf_read_dev(ddev, DSAF_TBL_LKUP_NUM_I_0_REG); + p[490] = dsaf_read_dev(ddev, DSAF_TBL_LKUP_NUM_O_0_REG); + p[491] = dsaf_read_dev(ddev, DSAF_TBL_UCAST_BCAST_MIS_INFO_0_0_REG); + + /* dsaf other registers */ + p[492] = dsaf_read_dev(ddev, DSAF_INODE_FIFO_WL_0_REG + port * 0x4); + p[493] = dsaf_read_dev(ddev, DSAF_ONODE_FIFO_WL_0_REG + port * 0x4); + p[494] = dsaf_read_dev(ddev, DSAF_XGE_GE_WORK_MODE_0_REG + port * 0x4); + p[495] = dsaf_read_dev(ddev, + DSAF_XGE_APP_RX_LINK_UP_0_REG + port * 0x4); + p[496] = dsaf_read_dev(ddev, DSAF_NETPORT_CTRL_SIG_0_REG + port * 0x4); + p[497] = dsaf_read_dev(ddev, DSAF_XGE_CTRL_SIG_CFG_0_REG + port * 0x4); + + /* mark end of dsaf regs */ + for (i = 498; i < 504; i++) + p[i] = 0xdddddddd; +} + +static char *hns_dsaf_get_node_stats_strings(char *data, int node) +{ + char *buff = data; + + snprintf(buff, ETH_GSTRING_LEN, "innod%d_pad_drop_pkts", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "innod%d_manage_pkts", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "innod%d_rx_pkts", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "innod%d_rx_pkt_id", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "innod%d_rx_pause_frame", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "innod%d_release_buf_num", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "innod%d_sbm_drop_pkts", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "innod%d_crc_false_pkts", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "innod%d_bp_drop_pkts", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "innod%d_lookup_rslt_drop_pkts", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "innod%d_local_rslt_fail_pkts", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "innod%d_vlan_drop_pkts", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "innod%d_stp_drop_pkts", node); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "onnod%d_tx_pkts", node); + buff = buff + ETH_GSTRING_LEN; + + return buff; +} + +static u64 *hns_dsaf_get_node_stats(struct dsaf_device *ddev, u64 *data, + int node_num) +{ + u64 *p = data; + struct dsaf_hw_stats *hw_stats = &ddev->hw_stats[node_num]; + + p[0] = hw_stats->pad_drop; + p[1] = hw_stats->man_pkts; + p[2] = hw_stats->rx_pkts; + p[3] = hw_stats->rx_pkt_id; + p[4] = hw_stats->rx_pause_frame; + p[5] = hw_stats->release_buf_num; + p[6] = hw_stats->sbm_drop; + p[7] = hw_stats->crc_false; + p[8] = hw_stats->bp_drop; + p[9] = hw_stats->rslt_drop; + p[10] = hw_stats->local_addr_false; + p[11] = hw_stats->vlan_drop; + p[12] = hw_stats->stp_drop; + p[13] = hw_stats->tx_pkts; + + return &p[14]; +} + +/** + *hns_dsaf_get_stats - get dsaf statistic + *@ddev: dsaf device + *@data:statistic value + *@port: port num + */ +void hns_dsaf_get_stats(struct dsaf_device *ddev, u64 *data, int port) +{ + u64 *p = data; + int node_num = port; + + /* for ge/xge node info */ + p = hns_dsaf_get_node_stats(ddev, p, node_num); + + /* for ppe node info */ + node_num = port + DSAF_PPE_INODE_BASE; + (void)hns_dsaf_get_node_stats(ddev, p, node_num); +} + +/** + *hns_dsaf_get_sset_count - get dsaf string set count + *@stringset: type of values in data + *return dsaf string name count + */ +int hns_dsaf_get_sset_count(int stringset) +{ + if (stringset == ETH_SS_STATS) + return DSAF_STATIC_NUM; + + return 0; +} + +/** + *hns_dsaf_get_strings - get dsaf string set + *@stringset:srting set index + *@data:strings name value + *@port:port index + */ +void hns_dsaf_get_strings(int stringset, u8 *data, int port) +{ + char *buff = (char *)data; + int node = port; + + if (stringset != ETH_SS_STATS) + return; + + /* for ge/xge node info */ + buff = hns_dsaf_get_node_stats_strings(buff, node); + + /* for ppe node info */ + node = port + DSAF_PPE_INODE_BASE; + (void)hns_dsaf_get_node_stats_strings(buff, node); +} + +/** + *hns_dsaf_get_sset_count - get dsaf regs count + *return dsaf regs count + */ +int hns_dsaf_get_regs_count(void) +{ + return DSAF_DUMP_REGS_NUM; +} + +/** + * dsaf_probe - probo dsaf dev + * @pdev: dasf platform device + * retuen 0 - success , negative --fail + */ +static int hns_dsaf_probe(struct platform_device *pdev) +{ + struct dsaf_device *dsaf_dev; + int ret; + + dsaf_dev = hns_dsaf_alloc_dev(&pdev->dev, sizeof(struct dsaf_drv_priv)); + if (IS_ERR(dsaf_dev)) { + ret = PTR_ERR(dsaf_dev); + dev_err(&pdev->dev, + "dsaf_probe dsaf_alloc_dev failed, ret = %#x!\n", ret); + return ret; + } + + ret = hns_dsaf_get_cfg(dsaf_dev); + if (ret) + goto free_dev; + + ret = hns_dsaf_init(dsaf_dev); + if (ret) + goto free_cfg; + + ret = hns_mac_init(dsaf_dev); + if (ret) + goto uninit_dsaf; + + ret = hns_ppe_init(dsaf_dev); + if (ret) + goto uninit_mac; + + ret = hns_dsaf_ae_init(dsaf_dev); + if (ret) + goto uninit_ppe; + + return 0; + +uninit_ppe: + hns_ppe_uninit(dsaf_dev); + +uninit_mac: + hns_mac_uninit(dsaf_dev); + +uninit_dsaf: + hns_dsaf_free(dsaf_dev); + +free_cfg: + hns_dsaf_free_cfg(dsaf_dev); + +free_dev: + hns_dsaf_free_dev(dsaf_dev); + + return ret; +} + +/** + * dsaf_remove - remove dsaf dev + * @pdev: dasf platform device + */ +static int hns_dsaf_remove(struct platform_device *pdev) +{ + struct dsaf_device *dsaf_dev = dev_get_drvdata(&pdev->dev); + + hns_dsaf_ae_uninit(dsaf_dev); + + hns_ppe_uninit(dsaf_dev); + + hns_mac_uninit(dsaf_dev); + + hns_dsaf_free(dsaf_dev); + + hns_dsaf_free_cfg(dsaf_dev); + + hns_dsaf_free_dev(dsaf_dev); + + return 0; +} + +static const struct of_device_id g_dsaf_match[] = { + {.compatible = "hisilicon,hns-dsaf-v1"}, + {.compatible = "hisilicon,hns-dsaf-v2"}, + {} +}; + +static struct platform_driver g_dsaf_driver = { + .probe = hns_dsaf_probe, + .remove = hns_dsaf_remove, + .driver = { + .name = DSAF_DRV_NAME, + .of_match_table = g_dsaf_match, + }, +}; + +module_platform_driver(g_dsaf_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Huawei Tech. Co., Ltd."); +MODULE_DESCRIPTION("HNS DSAF driver"); +MODULE_VERSION(DSAF_MOD_VERSION); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h new file mode 100644 index 000000000000..e0417c09ba79 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -0,0 +1,427 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __HNS_DSAF_MAIN_H +#define __HNS_DSAF_MAIN_H +#include "hnae.h" + +#include "hns_dsaf_reg.h" +#include "hns_dsaf_mac.h" + +struct hns_mac_cb; + +#define DSAF_DRV_NAME "hns_dsaf" +#define DSAF_MOD_VERSION "v1.0" + +#define ENABLE (0x1) +#define DISABLE (0x0) + +#define HNS_DSAF_DEBUG_NW_REG_OFFSET (0x100000) + +#define DSAF_BASE_INNER_PORT_NUM (127) /* mac tbl qid*/ + +#define DSAF_MAX_CHIP_NUM (2) /*max 2 chips */ + +#define DSAF_DEFAUTL_QUEUE_NUM_PER_PPE (22) + +#define HNS_DSAF_MAX_DESC_CNT (1024) +#define HNS_DSAF_MIN_DESC_CNT (16) + +#define DSAF_INVALID_ENTRY_IDX (0xffff) + +#define DSAF_CFG_READ_CNT (30) +#define DSAF_SRAM_INIT_FINISH_FLAG (0xff) + +#define MAC_NUM_OCTETS_PER_ADDR 6 + +#define DSAF_DUMP_REGS_NUM 504 +#define DSAF_STATIC_NUM 28 + +#define DSAF_STATS_READ(p, offset) (*((u64 *)((u64)(p) + (offset)))) + +enum hal_dsaf_mode { + HRD_DSAF_NO_DSAF_MODE = 0x0, + HRD_DSAF_MODE = 0x1, +}; + +enum hal_dsaf_tc_mode { + HRD_DSAF_4TC_MODE = 0X0, + HRD_DSAF_8TC_MODE = 0X1, +}; + +struct dsaf_vm_def_vlan { + u32 vm_def_vlan_id; + u32 vm_def_vlan_cfi; + u32 vm_def_vlan_pri; +}; + +struct dsaf_tbl_tcam_data { + u32 tbl_tcam_data_high; + u32 tbl_tcam_data_low; +}; + +#define DSAF_PORT_MSK_NUM \ + ((DSAF_TOTAL_QUEUE_NUM + DSAF_SERVICE_NW_NUM - 1) / 32 + 1) +struct dsaf_tbl_tcam_mcast_cfg { + u8 tbl_mcast_old_en; + u8 tbl_mcast_item_vld; + u32 tbl_mcast_port_msk[DSAF_PORT_MSK_NUM]; +}; + +struct dsaf_tbl_tcam_ucast_cfg { + u32 tbl_ucast_old_en; + u32 tbl_ucast_item_vld; + u32 tbl_ucast_mac_discard; + u32 tbl_ucast_dvc; + u32 tbl_ucast_out_port; +}; + +struct dsaf_tbl_line_cfg { + u32 tbl_line_mac_discard; + u32 tbl_line_dvc; + u32 tbl_line_out_port; +}; + +enum dsaf_port_rate_mode { + DSAF_PORT_RATE_1000 = 0, + DSAF_PORT_RATE_2500, + DSAF_PORT_RATE_10000 +}; + +enum dsaf_stp_port_type { + DSAF_STP_PORT_TYPE_DISCARD = 0, + DSAF_STP_PORT_TYPE_BLOCK = 1, + DSAF_STP_PORT_TYPE_LISTEN = 2, + DSAF_STP_PORT_TYPE_LEARN = 3, + DSAF_STP_PORT_TYPE_FORWARD = 4 +}; + +enum dsaf_sw_port_type { + DSAF_SW_PORT_TYPE_NON_VLAN = 0, + DSAF_SW_PORT_TYPE_ACCESS = 1, + DSAF_SW_PORT_TYPE_TRUNK = 2, +}; + +#define DSAF_SUB_BASE_SIZE (0x10000) + +/* dsaf mode define */ +enum dsaf_mode { + DSAF_MODE_INVALID = 0, /**< Invalid dsaf mode */ + DSAF_MODE_ENABLE_FIX, /**< en DSAF-mode, fixed to queue*/ + DSAF_MODE_ENABLE_0VM, /**< en DSAF-mode, support 0 VM */ + DSAF_MODE_ENABLE_8VM, /**< en DSAF-mode, support 8 VM */ + DSAF_MODE_ENABLE_16VM, /**< en DSAF-mode, support 16 VM */ + DSAF_MODE_ENABLE_32VM, /**< en DSAF-mode, support 32 VM */ + DSAF_MODE_ENABLE_128VM, /**< en DSAF-mode, support 128 VM */ + DSAF_MODE_ENABLE, /**< before is enable DSAF mode*/ + DSAF_MODE_DISABLE_FIX, /**< non-dasf, fixed to queue*/ + DSAF_MODE_DISABLE_2PORT_8VM, /**< non-dasf, 2port 8VM */ + DSAF_MODE_DISABLE_2PORT_16VM, /**< non-dasf, 2port 16VM */ + DSAF_MODE_DISABLE_2PORT_64VM, /**< non-dasf, 2port 64VM */ + DSAF_MODE_DISABLE_6PORT_0VM, /**< non-dasf, 6port 0VM */ + DSAF_MODE_DISABLE_6PORT_2VM, /**< non-dasf, 6port 2VM */ + DSAF_MODE_DISABLE_6PORT_4VM, /**< non-dasf, 6port 4VM */ + DSAF_MODE_DISABLE_6PORT_16VM, /**< non-dasf, 6port 16VM */ + DSAF_MODE_MAX /**< the last one, use as the num */ +}; + +#define DSAF_DEST_PORT_NUM 256 /* DSAF max port num */ +#define DSAF_WORD_BIT_CNT 32 /* the num bit of word */ + +/*mac entry, mc or uc entry*/ +struct dsaf_drv_mac_single_dest_entry { + /* mac addr, match the entry*/ + u8 addr[MAC_NUM_OCTETS_PER_ADDR]; + u16 in_vlan_id; /* value of VlanId */ + + /* the vld input port num, dsaf-mode fix 0, */ + /* non-dasf is the entry whitch port vld*/ + u8 in_port_num; + + u8 port_num; /*output port num*/ + u8 rsv[6]; +}; + +/*only mc entry*/ +struct dsaf_drv_mac_multi_dest_entry { + /* mac addr, match the entry*/ + u8 addr[MAC_NUM_OCTETS_PER_ADDR]; + u16 in_vlan_id; + /* this mac addr output port,*/ + /* bit0-bit5 means Port0-Port5(1bit is vld)**/ + u32 port_mask[DSAF_DEST_PORT_NUM / DSAF_WORD_BIT_CNT]; + + /* the vld input port num, dsaf-mode fix 0,*/ + /* non-dasf is the entry whitch port vld*/ + u8 in_port_num; + u8 rsv[7]; +}; + +struct dsaf_hw_stats { + u64 pad_drop; + u64 man_pkts; + u64 rx_pkts; + u64 rx_pkt_id; + u64 rx_pause_frame; + u64 release_buf_num; + u64 sbm_drop; + u64 crc_false; + u64 bp_drop; + u64 rslt_drop; + u64 local_addr_false; + u64 vlan_drop; + u64 stp_drop; + u64 tx_pkts; +}; + +struct hnae_vf_cb { + u8 port_index; + struct hns_mac_cb *mac_cb; + struct dsaf_device *dsaf_dev; + struct hnae_handle ae_handle; /* must be the last number */ +}; + +struct dsaf_int_xge_src { + u32 xid_xge_ecc_err_int_src; + u32 xid_xge_fsm_timout_int_src; + u32 sbm_xge_lnk_fsm_timout_int_src; + u32 sbm_xge_lnk_ecc_2bit_int_src; + u32 sbm_xge_mib_req_failed_int_src; + u32 sbm_xge_mib_req_fsm_timout_int_src; + u32 sbm_xge_mib_rels_fsm_timout_int_src; + u32 sbm_xge_sram_ecc_2bit_int_src; + u32 sbm_xge_mib_buf_sum_err_int_src; + u32 sbm_xge_mib_req_extra_int_src; + u32 sbm_xge_mib_rels_extra_int_src; + u32 voq_xge_start_to_over_0_int_src; + u32 voq_xge_start_to_over_1_int_src; + u32 voq_xge_ecc_err_int_src; +}; + +struct dsaf_int_ppe_src { + u32 xid_ppe_fsm_timout_int_src; + u32 sbm_ppe_lnk_fsm_timout_int_src; + u32 sbm_ppe_lnk_ecc_2bit_int_src; + u32 sbm_ppe_mib_req_failed_int_src; + u32 sbm_ppe_mib_req_fsm_timout_int_src; + u32 sbm_ppe_mib_rels_fsm_timout_int_src; + u32 sbm_ppe_sram_ecc_2bit_int_src; + u32 sbm_ppe_mib_buf_sum_err_int_src; + u32 sbm_ppe_mib_req_extra_int_src; + u32 sbm_ppe_mib_rels_extra_int_src; + u32 voq_ppe_start_to_over_0_int_src; + u32 voq_ppe_ecc_err_int_src; + u32 xod_ppe_fifo_rd_empty_int_src; + u32 xod_ppe_fifo_wr_full_int_src; +}; + +struct dsaf_int_rocee_src { + u32 xid_rocee_fsm_timout_int_src; + u32 sbm_rocee_lnk_fsm_timout_int_src; + u32 sbm_rocee_lnk_ecc_2bit_int_src; + u32 sbm_rocee_mib_req_failed_int_src; + u32 sbm_rocee_mib_req_fsm_timout_int_src; + u32 sbm_rocee_mib_rels_fsm_timout_int_src; + u32 sbm_rocee_sram_ecc_2bit_int_src; + u32 sbm_rocee_mib_buf_sum_err_int_src; + u32 sbm_rocee_mib_req_extra_int_src; + u32 sbm_rocee_mib_rels_extra_int_src; + u32 voq_rocee_start_to_over_0_int_src; + u32 voq_rocee_ecc_err_int_src; +}; + +struct dsaf_int_tbl_src { + u32 tbl_da0_mis_src; + u32 tbl_da1_mis_src; + u32 tbl_da2_mis_src; + u32 tbl_da3_mis_src; + u32 tbl_da4_mis_src; + u32 tbl_da5_mis_src; + u32 tbl_da6_mis_src; + u32 tbl_da7_mis_src; + u32 tbl_sa_mis_src; + u32 tbl_old_sech_end_src; + u32 lram_ecc_err1_src; + u32 lram_ecc_err2_src; + u32 tram_ecc_err1_src; + u32 tram_ecc_err2_src; + u32 tbl_ucast_bcast_xge0_src; + u32 tbl_ucast_bcast_xge1_src; + u32 tbl_ucast_bcast_xge2_src; + u32 tbl_ucast_bcast_xge3_src; + u32 tbl_ucast_bcast_xge4_src; + u32 tbl_ucast_bcast_xge5_src; + u32 tbl_ucast_bcast_ppe_src; + u32 tbl_ucast_bcast_rocee_src; +}; + +struct dsaf_int_stat { + struct dsaf_int_xge_src dsaf_int_xge_stat[DSAF_COMM_CHN]; + struct dsaf_int_ppe_src dsaf_int_ppe_stat[DSAF_COMM_CHN]; + struct dsaf_int_rocee_src dsaf_int_rocee_stat[DSAF_COMM_CHN]; + struct dsaf_int_tbl_src dsaf_int_tbl_stat[1]; + +}; + +/* Dsaf device struct define ,and mac -> dsaf */ +struct dsaf_device { + struct device *dev; + struct hnae_ae_dev ae_dev; + + void *priv; + + int virq[DSAF_IRQ_NUM]; + + u8 __iomem *sc_base; + u8 __iomem *sds_base; + u8 __iomem *ppe_base; + u8 __iomem *io_base; + u8 __iomem *cpld_base; + + u32 desc_num; /* desc num per queue*/ + u32 buf_size; /* ring buffer size */ + int buf_size_type; /* ring buffer size-type */ + enum dsaf_mode dsaf_mode; /* dsaf mode */ + enum hal_dsaf_mode dsaf_en; + enum hal_dsaf_tc_mode dsaf_tc_mode; + u32 dsaf_ver; + + struct ppe_common_cb *ppe_common[DSAF_COMM_DEV_NUM]; + struct rcb_common_cb *rcb_common[DSAF_COMM_DEV_NUM]; + struct hns_mac_cb *mac_cb; + + struct dsaf_hw_stats hw_stats[DSAF_NODE_NUM]; + struct dsaf_int_stat int_stat; +}; + +static inline void *hns_dsaf_dev_priv(const struct dsaf_device *dsaf_dev) +{ + return (void *)((u64)dsaf_dev + sizeof(*dsaf_dev)); +} + +struct dsaf_drv_tbl_tcam_key { + union { + struct { + u8 mac_3; + u8 mac_2; + u8 mac_1; + u8 mac_0; + } bits; + + u32 val; + } high; + union { + struct { + u32 port:4; /* port id, */ + /* dsaf-mode fixed 0, non-dsaf-mode port id*/ + u32 vlan:12; /* vlan id */ + u32 mac_5:8; + u32 mac_4:8; + } bits; + + u32 val; + } low; +}; + +struct dsaf_drv_soft_mac_tbl { + struct dsaf_drv_tbl_tcam_key tcam_key; + u16 index; /*the entry's index in tcam tab*/ +}; + +struct dsaf_drv_priv { + /* soft tab Mac key, for hardware tab*/ + struct dsaf_drv_soft_mac_tbl *soft_mac_tbl; +}; + +static inline void hns_dsaf_tbl_tcam_addr_cfg(struct dsaf_device *dsaf_dev, + u32 tab_tcam_addr) +{ + dsaf_set_dev_field(dsaf_dev, DSAF_TBL_TCAM_ADDR_0_REG, + DSAF_TBL_TCAM_ADDR_M, DSAF_TBL_TCAM_ADDR_S, + tab_tcam_addr); +} + +static inline void hns_dsaf_tbl_tcam_load_pul(struct dsaf_device *dsaf_dev) +{ + u32 o_tbl_pul; + + o_tbl_pul = dsaf_read_dev(dsaf_dev, DSAF_TBL_PUL_0_REG); + dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_TCAM_LOAD_S, 1); + dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul); + dsaf_set_bit(o_tbl_pul, DSAF_TBL_PUL_TCAM_LOAD_S, 0); + dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul); +} + +static inline void hns_dsaf_tbl_line_addr_cfg(struct dsaf_device *dsaf_dev, + u32 tab_line_addr) +{ + dsaf_set_dev_field(dsaf_dev, DSAF_TBL_LINE_ADDR_0_REG, + DSAF_TBL_LINE_ADDR_M, DSAF_TBL_LINE_ADDR_S, + tab_line_addr); +} + +static inline int hns_dsaf_get_comm_idx_by_port(int port) +{ + if ((port < DSAF_COMM_CHN) || (port == DSAF_MAX_PORT_NUM_PER_CHIP)) + return 0; + else + return (port - DSAF_COMM_CHN + 1); +} + +static inline struct hnae_vf_cb *hns_ae_get_vf_cb( + struct hnae_handle *handle) +{ + return container_of(handle, struct hnae_vf_cb, ae_handle); +} + +int hns_dsaf_set_mac_uc_entry(struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_single_dest_entry *mac_entry); +int hns_dsaf_set_mac_mc_entry(struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_multi_dest_entry *mac_entry); +int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_single_dest_entry *mac_entry); +int hns_dsaf_del_mac_entry(struct dsaf_device *dsaf_dev, u16 vlan_id, + u8 in_port_num, u8 *addr); +int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_single_dest_entry *mac_entry); +int hns_dsaf_get_mac_uc_entry(struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_single_dest_entry *mac_entry); +int hns_dsaf_get_mac_mc_entry(struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_multi_dest_entry *mac_entry); +int hns_dsaf_get_mac_entry_by_index( + struct dsaf_device *dsaf_dev, + u16 entry_index, + struct dsaf_drv_mac_multi_dest_entry *mac_entry); + +void hns_dsaf_rst(struct dsaf_device *dsaf_dev, u32 val); + +void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val); + +void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val); + +void hns_dsaf_fix_mac_mode(struct hns_mac_cb *mac_cb); + +int hns_dsaf_ae_init(struct dsaf_device *dsaf_dev); +void hns_dsaf_ae_uninit(struct dsaf_device *dsaf_dev); + +void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val); +void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val); +void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, + u32 port, u32 val); + +void hns_dsaf_update_stats(struct dsaf_device *dsaf_dev, u32 inode_num); + +int hns_dsaf_get_sset_count(int stringset); +void hns_dsaf_get_stats(struct dsaf_device *ddev, u64 *data, int port); +void hns_dsaf_get_strings(int stringset, u8 *data, int port); + +void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data); +int hns_dsaf_get_regs_count(void); + +#endif /* __HNS_DSAF_MAIN_H__ */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c new file mode 100644 index 000000000000..d611388aecef --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include "hns_dsaf_misc.h" +#include "hns_dsaf_mac.h" +#include "hns_dsaf_reg.h" +#include "hns_dsaf_ppe.h" + +void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status, + u16 speed, int data) +{ + int speed_reg = 0; + u8 value; + + if (!mac_cb) { + pr_err("sfp_led_opt mac_dev is null!\n"); + return; + } + if (!mac_cb->cpld_vaddr) { + dev_err(mac_cb->dev, "mac_id=%d, cpld_vaddr is null !\n", + mac_cb->mac_id); + return; + } + + if (speed == MAC_SPEED_10000) + speed_reg = 1; + + value = mac_cb->cpld_led_value; + + if (link_status) { + dsaf_set_bit(value, DSAF_LED_LINK_B, link_status); + dsaf_set_field(value, DSAF_LED_SPEED_M, + DSAF_LED_SPEED_S, speed_reg); + dsaf_set_bit(value, DSAF_LED_DATA_B, data); + + if (value != mac_cb->cpld_led_value) { + dsaf_write_b(mac_cb->cpld_vaddr, value); + mac_cb->cpld_led_value = value; + } + } else { + dsaf_write_b(mac_cb->cpld_vaddr, CPLD_LED_DEFAULT_VALUE); + mac_cb->cpld_led_value = CPLD_LED_DEFAULT_VALUE; + } +} + +void cpld_led_reset(struct hns_mac_cb *mac_cb) +{ + if (!mac_cb || !mac_cb->cpld_vaddr) + return; + + dsaf_write_b(mac_cb->cpld_vaddr, CPLD_LED_DEFAULT_VALUE); + mac_cb->cpld_led_value = CPLD_LED_DEFAULT_VALUE; +} + +int cpld_set_led_id(struct hns_mac_cb *mac_cb, + enum hnae_led_state status) +{ + switch (status) { + case HNAE_LED_ACTIVE: + mac_cb->cpld_led_value = dsaf_read_b(mac_cb->cpld_vaddr); + return 2; + case HNAE_LED_ON: + dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, + CPLD_LED_ON_VALUE); + dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value); + break; + case HNAE_LED_OFF: + dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, + CPLD_LED_DEFAULT_VALUE); + dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value); + break; + case HNAE_LED_INACTIVE: + dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, + CPLD_LED_DEFAULT_VALUE); + dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value); + break; + default: + break; + } + + return 0; +} + +#define RESET_REQ_OR_DREQ 1 + +void hns_dsaf_rst(struct dsaf_device *dsaf_dev, u32 val) +{ + u32 xbar_reg_addr; + u32 nt_reg_addr; + + if (!val) { + xbar_reg_addr = DSAF_SUB_SC_XBAR_RESET_REQ_REG; + nt_reg_addr = DSAF_SUB_SC_NT_RESET_REQ_REG; + } else { + xbar_reg_addr = DSAF_SUB_SC_XBAR_RESET_DREQ_REG; + nt_reg_addr = DSAF_SUB_SC_NT_RESET_DREQ_REG; + } + + dsaf_write_reg(dsaf_dev->sc_base, xbar_reg_addr, + RESET_REQ_OR_DREQ); + dsaf_write_reg(dsaf_dev->sc_base, nt_reg_addr, + RESET_REQ_OR_DREQ); +} + +void hns_dsaf_xge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) +{ + u32 reg_val = 0; + u32 reg_addr; + + if (port >= DSAF_XGE_NUM) + return; + + reg_val |= RESET_REQ_OR_DREQ; + reg_val |= 0x2082082 << port; + + if (val == 0) + reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; + else + reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG; + + dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); +} + +void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, + u32 port, u32 val) +{ + u32 reg_val = 0; + u32 reg_addr; + + if (port >= DSAF_XGE_NUM) + return; + + reg_val |= XGMAC_TRX_CORE_SRST_M << port; + + if (val == 0) + reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; + else + reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG; + + dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); +} + +void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) +{ + u32 reg_val_1; + u32 reg_val_2; + + if (port >= DSAF_GE_NUM) + return; + + if (port < DSAF_SERVICE_NW_NUM) { + reg_val_1 = 0x1 << port; + reg_val_2 = 0x1041041 << port; + + if (val == 0) { + dsaf_write_reg(dsaf_dev->sc_base, + DSAF_SUB_SC_GE_RESET_REQ1_REG, + reg_val_1); + + dsaf_write_reg(dsaf_dev->sc_base, + DSAF_SUB_SC_GE_RESET_REQ0_REG, + reg_val_2); + } else { + dsaf_write_reg(dsaf_dev->sc_base, + DSAF_SUB_SC_GE_RESET_DREQ0_REG, + reg_val_2); + + dsaf_write_reg(dsaf_dev->sc_base, + DSAF_SUB_SC_GE_RESET_DREQ1_REG, + reg_val_1); + } + } else { + reg_val_1 = 0x15540 << (port - 6); + reg_val_2 = 0x100 << (port - 6); + + if (val == 0) { + dsaf_write_reg(dsaf_dev->sc_base, + DSAF_SUB_SC_GE_RESET_REQ1_REG, + reg_val_1); + + dsaf_write_reg(dsaf_dev->sc_base, + DSAF_SUB_SC_PPE_RESET_REQ_REG, + reg_val_2); + } else { + dsaf_write_reg(dsaf_dev->sc_base, + DSAF_SUB_SC_GE_RESET_DREQ1_REG, + reg_val_1); + + dsaf_write_reg(dsaf_dev->sc_base, + DSAF_SUB_SC_PPE_RESET_DREQ_REG, + reg_val_2); + } + } +} + +void hns_ppe_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, u32 val) +{ + u32 reg_val = 0; + u32 reg_addr; + + reg_val |= RESET_REQ_OR_DREQ << port; + + if (val == 0) + reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; + else + reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG; + + dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); +} + +void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) +{ + int comm_index = ppe_common->comm_index; + struct dsaf_device *dsaf_dev = ppe_common->dsaf_dev; + u32 reg_val; + u32 reg_addr; + + if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { + reg_val = RESET_REQ_OR_DREQ; + if (val == 0) + reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_REQ_REG; + else + reg_addr = DSAF_SUB_SC_RCB_PPE_COM_RESET_DREQ_REG; + + } else { + reg_val = 0x100 << (comm_index - 1); + + if (val == 0) + reg_addr = DSAF_SUB_SC_PPE_RESET_REQ_REG; + else + reg_addr = DSAF_SUB_SC_PPE_RESET_DREQ_REG; + } + + dsaf_write_reg(dsaf_dev->sc_base, reg_addr, reg_val); +} + +/** + * hns_mac_get_sds_mode - get phy ifterface form serdes mode + * @mac_cb: mac control block + * retuen phy interface + */ +phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) +{ + u32 hilink3_mode; + u32 hilink4_mode; + void __iomem *sys_ctl_vaddr = mac_cb->sys_ctl_vaddr; + int dev_id = mac_cb->mac_id; + phy_interface_t phy_if = PHY_INTERFACE_MODE_NA; + + hilink3_mode = dsaf_read_reg(sys_ctl_vaddr, HNS_MAC_HILINK3_REG); + hilink4_mode = dsaf_read_reg(sys_ctl_vaddr, HNS_MAC_HILINK4_REG); + if (dev_id >= 0 && dev_id <= 3) { + if (hilink4_mode == 0) + phy_if = PHY_INTERFACE_MODE_SGMII; + else + phy_if = PHY_INTERFACE_MODE_XGMII; + } else if (dev_id >= 4 && dev_id <= 5) { + if (hilink3_mode == 0) + phy_if = PHY_INTERFACE_MODE_SGMII; + else + phy_if = PHY_INTERFACE_MODE_XGMII; + } else { + phy_if = PHY_INTERFACE_MODE_SGMII; + } + + dev_dbg(mac_cb->dev, + "hilink3_mode=%d, hilink4_mode=%d dev_id=%d, phy_if=%d\n", + hilink3_mode, hilink4_mode, dev_id, phy_if); + return phy_if; +} + +/** + * hns_mac_config_sds_loopback - set loop back for serdes + * @mac_cb: mac control block + * retuen 0 == success + */ +int hns_mac_config_sds_loopback(struct hns_mac_cb *mac_cb, u8 en) +{ + /* port 0-3 hilink4 base is serdes_vaddr + 0x00280000 + * port 4-7 hilink3 base is serdes_vaddr + 0x00200000 + */ + u8 *base_addr = (u8 *)mac_cb->serdes_vaddr + + (mac_cb->mac_id <= 3 ? 0x00280000 : 0x00200000); + const u8 lane_id[] = { + 0, /* mac 0 -> lane 0 */ + 1, /* mac 1 -> lane 1 */ + 2, /* mac 2 -> lane 2 */ + 3, /* mac 3 -> lane 3 */ + 2, /* mac 4 -> lane 2 */ + 3, /* mac 5 -> lane 3 */ + 0, /* mac 6 -> lane 0 */ + 1 /* mac 7 -> lane 1 */ + }; +#define RX_CSR(lane, reg) ((0x4080 + (reg) * 0x0002 + (lane) * 0x0200) * 2) + u64 reg_offset = RX_CSR(lane_id[mac_cb->mac_id], 0); + + int sfp_prsnt; + int ret = hns_mac_get_sfp_prsnt(mac_cb, &sfp_prsnt); + + if (!mac_cb->phy_node) { + if (ret) + pr_info("please confirm sfp is present or not\n"); + else + if (!sfp_prsnt) + pr_info("no sfp in this eth\n"); + } + + dsaf_set_reg_field(base_addr, reg_offset, 1ull << 10, 10, !!en); + + return 0; +} diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h new file mode 100644 index 000000000000..419f07aa9734 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _HNS_DSAF_MISC_H +#define _HNS_DSAF_MISC_H + +#include +#include +#include + +#include "hns_dsaf_mac.h" + +#define CPLD_ADDR_PORT_OFFSET 0x4 + +#define HS_LED_ON 0xE +#define HS_LED_OFF 0xF + +#define CPLD_LED_ON_VALUE 1 +#define CPLD_LED_DEFAULT_VALUE 0 + +#define MAC_SFP_PORT_OFFSET 0x2 + +#define DSAF_LED_SPEED_S 0 +#define DSAF_LED_SPEED_M (0x3 << DSAF_LED_SPEED_S) + +#define DSAF_LED_LINK_B 2 +#define DSAF_LED_DATA_B 4 +#define DSAF_LED_ANCHOR_B 5 + +void hns_cpld_set_led(struct hns_mac_cb *mac_cb, int link_status, + u16 speed, int data); +void cpld_led_reset(struct hns_mac_cb *mac_cb); +int cpld_set_led_id(struct hns_mac_cb *mac_cb, + enum hnae_led_state status); +int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int *sfp_prsnt); + +#endif diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c new file mode 100644 index 000000000000..67f33f185a44 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hns_dsaf_ppe.h" + +static void __iomem *hns_ppe_common_get_ioaddr( + struct ppe_common_cb *ppe_common) +{ + void __iomem *base_addr; + + int idx = ppe_common->comm_index; + + if (idx == HNS_DSAF_COMM_SERVICE_NW_IDX) + base_addr = ppe_common->dsaf_dev->ppe_base + + PPE_COMMON_REG_OFFSET; + else + base_addr = ppe_common->dsaf_dev->sds_base + + (idx - 1) * HNS_DSAF_DEBUG_NW_REG_OFFSET + + PPE_COMMON_REG_OFFSET; + + return base_addr; +} + +/** + * hns_ppe_common_get_cfg - get ppe common config + * @dsaf_dev: dasf device + * comm_index: common index + * retuen 0 - success , negative --fail + */ +int hns_ppe_common_get_cfg(struct dsaf_device *dsaf_dev, int comm_index) +{ + struct ppe_common_cb *ppe_common; + int ppe_num; + + if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) + ppe_num = HNS_PPE_SERVICE_NW_ENGINE_NUM; + else + ppe_num = HNS_PPE_DEBUG_NW_ENGINE_NUM; + + ppe_common = devm_kzalloc(dsaf_dev->dev, sizeof(*ppe_common) + + ppe_num * sizeof(struct hns_ppe_cb), GFP_KERNEL); + if (!ppe_common) + return -ENOMEM; + + ppe_common->ppe_num = ppe_num; + ppe_common->dsaf_dev = dsaf_dev; + ppe_common->comm_index = comm_index; + if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) + ppe_common->ppe_mode = PPE_COMMON_MODE_SERVICE; + else + ppe_common->ppe_mode = PPE_COMMON_MODE_DEBUG; + ppe_common->dev = dsaf_dev->dev; + + ppe_common->io_base = hns_ppe_common_get_ioaddr(ppe_common); + + dsaf_dev->ppe_common[comm_index] = ppe_common; + + return 0; +} + +void hns_ppe_common_free_cfg(struct dsaf_device *dsaf_dev, u32 comm_index) +{ + dsaf_dev->ppe_common[comm_index] = NULL; +} + +static void __iomem *hns_ppe_get_iobase(struct ppe_common_cb *ppe_common, + int ppe_idx) +{ + void __iomem *base_addr; + int common_idx = ppe_common->comm_index; + + if (ppe_common->ppe_mode == PPE_COMMON_MODE_SERVICE) { + base_addr = ppe_common->dsaf_dev->ppe_base + + ppe_idx * PPE_REG_OFFSET; + + } else { + base_addr = ppe_common->dsaf_dev->sds_base + + (common_idx - 1) * HNS_DSAF_DEBUG_NW_REG_OFFSET; + } + + return base_addr; +} + +static int hns_ppe_get_port(struct ppe_common_cb *ppe_common, int idx) +{ + int port; + + if (ppe_common->ppe_mode == PPE_COMMON_MODE_SERVICE) + port = idx; + else + port = HNS_PPE_SERVICE_NW_ENGINE_NUM + + ppe_common->comm_index - 1; + + return port; +} + +static void hns_ppe_get_cfg(struct ppe_common_cb *ppe_common) +{ + u32 i; + struct hns_ppe_cb *ppe_cb; + u32 ppe_num = ppe_common->ppe_num; + + for (i = 0; i < ppe_num; i++) { + ppe_cb = &ppe_common->ppe_cb[i]; + ppe_cb->dev = ppe_common->dev; + ppe_cb->next = NULL; + ppe_cb->ppe_common_cb = ppe_common; + ppe_cb->index = i; + ppe_cb->port = hns_ppe_get_port(ppe_common, i); + ppe_cb->io_base = hns_ppe_get_iobase(ppe_common, i); + ppe_cb->virq = 0; + } +} + +static void hns_ppe_cnt_clr_ce(struct hns_ppe_cb *ppe_cb) +{ + dsaf_set_dev_bit(ppe_cb, PPE_TNL_0_5_CNT_CLR_CE_REG, + PPE_CNT_CLR_CE_B, 1); +} + +/** + * hns_ppe_checksum_hw - set ppe checksum caculate + * @ppe_device: ppe device + * @value: value + */ +static void hns_ppe_checksum_hw(struct hns_ppe_cb *ppe_cb, u32 value) +{ + dsaf_set_dev_field(ppe_cb, PPE_CFG_PRO_CHECK_EN_REG, + 0xfffffff, 0, value); +} + +static void hns_ppe_set_qid_mode(struct ppe_common_cb *ppe_common, + enum ppe_qid_mode qid_mdoe) +{ + dsaf_set_dev_field(ppe_common, PPE_COM_CFG_QID_MODE_REG, + PPE_CFG_QID_MODE_CF_QID_MODE_M, + PPE_CFG_QID_MODE_CF_QID_MODE_S, qid_mdoe); +} + +/** + * hns_ppe_set_qid - set ppe qid + * @ppe_common: ppe common device + * @qid: queue id + */ +static void hns_ppe_set_qid(struct ppe_common_cb *ppe_common, u32 qid) +{ + u32 qid_mod = dsaf_read_dev(ppe_common, PPE_COM_CFG_QID_MODE_REG); + + if (!dsaf_get_field(qid_mod, PPE_CFG_QID_MODE_DEF_QID_M, + PPE_CFG_QID_MODE_DEF_QID_S)) { + dsaf_set_field(qid_mod, PPE_CFG_QID_MODE_DEF_QID_M, + PPE_CFG_QID_MODE_DEF_QID_S, qid); + dsaf_write_dev(ppe_common, PPE_COM_CFG_QID_MODE_REG, qid_mod); + } +} + +/** + * hns_ppe_set_port_mode - set port mode + * @ppe_device: ppe device + * @mode: port mode + */ +static void hns_ppe_set_port_mode(struct hns_ppe_cb *ppe_cb, + enum ppe_port_mode mode) +{ + dsaf_write_dev(ppe_cb, PPE_CFG_XGE_MODE_REG, mode); +} + +/** + * hns_ppe_common_init_hw - init ppe common device + * @ppe_common: ppe common device + * + * Return 0 on success, negative on failure + */ +static int hns_ppe_common_init_hw(struct ppe_common_cb *ppe_common) +{ + enum ppe_qid_mode qid_mode; + enum dsaf_mode dsaf_mode = ppe_common->dsaf_dev->dsaf_mode; + + hns_ppe_com_srst(ppe_common, 0); + mdelay(100); + hns_ppe_com_srst(ppe_common, 1); + mdelay(100); + + if (ppe_common->ppe_mode == PPE_COMMON_MODE_SERVICE) { + switch (dsaf_mode) { + case DSAF_MODE_ENABLE_FIX: + case DSAF_MODE_DISABLE_FIX: + qid_mode = PPE_QID_MODE0; + hns_ppe_set_qid(ppe_common, 0); + break; + case DSAF_MODE_ENABLE_0VM: + case DSAF_MODE_DISABLE_2PORT_64VM: + qid_mode = PPE_QID_MODE3; + break; + case DSAF_MODE_ENABLE_8VM: + case DSAF_MODE_DISABLE_2PORT_16VM: + qid_mode = PPE_QID_MODE4; + break; + case DSAF_MODE_ENABLE_16VM: + case DSAF_MODE_DISABLE_6PORT_0VM: + qid_mode = PPE_QID_MODE5; + break; + case DSAF_MODE_ENABLE_32VM: + case DSAF_MODE_DISABLE_6PORT_16VM: + qid_mode = PPE_QID_MODE2; + break; + case DSAF_MODE_ENABLE_128VM: + case DSAF_MODE_DISABLE_6PORT_4VM: + qid_mode = PPE_QID_MODE1; + break; + case DSAF_MODE_DISABLE_2PORT_8VM: + qid_mode = PPE_QID_MODE7; + break; + case DSAF_MODE_DISABLE_6PORT_2VM: + qid_mode = PPE_QID_MODE6; + break; + default: + dev_err(ppe_common->dev, + "get ppe queue mode failed! dsaf_mode=%d\n", + dsaf_mode); + return -EINVAL; + } + hns_ppe_set_qid_mode(ppe_common, qid_mode); + } + + dsaf_set_dev_bit(ppe_common, PPE_COM_COMMON_CNT_CLR_CE_REG, + PPE_COMMON_CNT_CLR_CE_B, 1); + + return 0; +} + +/*clr ppe exception irq*/ +static void hns_ppe_exc_irq_en(struct hns_ppe_cb *ppe_cb, int en) +{ + u32 clr_vlue = 0xfffffffful; + u32 msk_vlue = en ? 0xfffffffful : 0; /*1 is en, 0 is dis*/ + u32 vld_msk = 0; + + /*only care bit 0,1,7*/ + dsaf_set_bit(vld_msk, 0, 1); + dsaf_set_bit(vld_msk, 1, 1); + dsaf_set_bit(vld_msk, 7, 1); + + /*clr sts**/ + dsaf_write_dev(ppe_cb, PPE_RINT_REG, clr_vlue); + + /*for some reserved bits, so set 0**/ + dsaf_write_dev(ppe_cb, PPE_INTEN_REG, msk_vlue & vld_msk); +} + +/** + * ppe_init_hw - init ppe + * @ppe_device: ppe device + */ +static void hns_ppe_init_hw(struct hns_ppe_cb *ppe_cb) +{ + struct ppe_common_cb *ppe_common_cb = ppe_cb->ppe_common_cb; + u32 port = ppe_cb->port; + struct dsaf_device *dsaf_dev = ppe_common_cb->dsaf_dev; + + hns_ppe_srst_by_port(dsaf_dev, port, 0); + mdelay(10); + hns_ppe_srst_by_port(dsaf_dev, port, 1); + + /* clr and msk except irq*/ + hns_ppe_exc_irq_en(ppe_cb, 0); + + if (ppe_common_cb->ppe_mode == PPE_COMMON_MODE_DEBUG) + hns_ppe_set_port_mode(ppe_cb, PPE_MODE_GE); + else + hns_ppe_set_port_mode(ppe_cb, PPE_MODE_XGE); + hns_ppe_checksum_hw(ppe_cb, 0xffffffff); + hns_ppe_cnt_clr_ce(ppe_cb); +} + +/** + * ppe_uninit_hw - uninit ppe + * @ppe_device: ppe device + */ +static void hns_ppe_uninit_hw(struct hns_ppe_cb *ppe_cb) +{ + u32 port; + + if (ppe_cb->ppe_common_cb) { + port = ppe_cb->index; + hns_ppe_srst_by_port(ppe_cb->ppe_common_cb->dsaf_dev, port, 0); + } +} + +void hns_ppe_uninit_ex(struct ppe_common_cb *ppe_common) +{ + u32 i; + + for (i = 0; i < ppe_common->ppe_num; i++) { + hns_ppe_uninit_hw(&ppe_common->ppe_cb[i]); + memset(&ppe_common->ppe_cb[i], 0, sizeof(struct hns_ppe_cb)); + } +} + +void hns_ppe_uninit(struct dsaf_device *dsaf_dev) +{ + u32 i; + + for (i = 0; i < HNS_PPE_COM_NUM; i++) { + if (dsaf_dev->ppe_common[i]) + hns_ppe_uninit_ex(dsaf_dev->ppe_common[i]); + hns_rcb_common_free_cfg(dsaf_dev, i); + hns_ppe_common_free_cfg(dsaf_dev, i); + } +} + +/** + * hns_ppe_reset - reinit ppe/rcb hw + * @dsaf_dev: dasf device + * retuen void + */ +void hns_ppe_reset_common(struct dsaf_device *dsaf_dev, u8 ppe_common_index) +{ + u32 i; + int ret; + struct ppe_common_cb *ppe_common; + + ppe_common = dsaf_dev->ppe_common[ppe_common_index]; + ret = hns_ppe_common_init_hw(ppe_common); + if (ret) + return; + + ret = hns_rcb_common_init_hw(dsaf_dev->rcb_common[ppe_common_index]); + if (ret) + return; + + for (i = 0; i < ppe_common->ppe_num; i++) + hns_ppe_init_hw(&ppe_common->ppe_cb[i]); + + hns_rcb_common_init_commit_hw(dsaf_dev->rcb_common[ppe_common_index]); +} + +void hns_ppe_update_stats(struct hns_ppe_cb *ppe_cb) +{ + struct hns_ppe_hw_stats *hw_stats = &ppe_cb->hw_stats; + + hw_stats->rx_pkts_from_sw + += dsaf_read_dev(ppe_cb, PPE_HIS_RX_SW_PKT_CNT_REG); + hw_stats->rx_pkts + += dsaf_read_dev(ppe_cb, PPE_HIS_RX_WR_BD_OK_PKT_CNT_REG); + hw_stats->rx_drop_no_bd + += dsaf_read_dev(ppe_cb, PPE_HIS_RX_PKT_NO_BUF_CNT_REG); + hw_stats->rx_alloc_buf_fail + += dsaf_read_dev(ppe_cb, PPE_HIS_RX_APP_BUF_FAIL_CNT_REG); + hw_stats->rx_alloc_buf_wait + += dsaf_read_dev(ppe_cb, PPE_HIS_RX_APP_BUF_WAIT_CNT_REG); + hw_stats->rx_drop_no_buf + += dsaf_read_dev(ppe_cb, PPE_HIS_RX_PKT_DROP_FUL_CNT_REG); + hw_stats->rx_err_fifo_full + += dsaf_read_dev(ppe_cb, PPE_HIS_RX_PKT_DROP_PRT_CNT_REG); + + hw_stats->tx_bd_form_rcb + += dsaf_read_dev(ppe_cb, PPE_HIS_TX_BD_CNT_REG); + hw_stats->tx_pkts_from_rcb + += dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_CNT_REG); + hw_stats->tx_pkts + += dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_OK_CNT_REG); + hw_stats->tx_err_fifo_empty + += dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_EPT_CNT_REG); + hw_stats->tx_err_checksum + += dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_CS_FAIL_CNT_REG); +} + +int hns_ppe_get_sset_count(int stringset) +{ + if (stringset == ETH_SS_STATS) + return ETH_PPE_STATIC_NUM; + return 0; +} + +int hns_ppe_get_regs_count(void) +{ + return ETH_PPE_DUMP_NUM; +} + +/** + * ppe_get_strings - get ppe srting + * @ppe_device: ppe device + * @stringset: string set type + * @data: output string + */ +void hns_ppe_get_strings(struct hns_ppe_cb *ppe_cb, int stringset, u8 *data) +{ + char *buff = (char *)data; + int index = ppe_cb->index; + + snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_sw_pkt", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_pkt_ok", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_drop_pkt_no_bd", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_alloc_buf_fail", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_alloc_buf_wait", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_pkt_drop_no_buf", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "ppe%d_rx_pkt_err_fifo_full", index); + buff = buff + ETH_GSTRING_LEN; + + snprintf(buff, ETH_GSTRING_LEN, "ppe%d_tx_bd", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "ppe%d_tx_pkt", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "ppe%d_tx_pkt_ok", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "ppe%d_tx_pkt_err_fifo_empty", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "ppe%d_tx_pkt_err_csum_fail", index); +} + +void hns_ppe_get_stats(struct hns_ppe_cb *ppe_cb, u64 *data) +{ + u64 *regs_buff = data; + struct hns_ppe_hw_stats *hw_stats = &ppe_cb->hw_stats; + + regs_buff[0] = hw_stats->rx_pkts_from_sw; + regs_buff[1] = hw_stats->rx_pkts; + regs_buff[2] = hw_stats->rx_drop_no_bd; + regs_buff[3] = hw_stats->rx_alloc_buf_fail; + regs_buff[4] = hw_stats->rx_alloc_buf_wait; + regs_buff[5] = hw_stats->rx_drop_no_buf; + regs_buff[6] = hw_stats->rx_err_fifo_full; + + regs_buff[7] = hw_stats->tx_bd_form_rcb; + regs_buff[8] = hw_stats->tx_pkts_from_rcb; + regs_buff[9] = hw_stats->tx_pkts; + regs_buff[10] = hw_stats->tx_err_fifo_empty; + regs_buff[11] = hw_stats->tx_err_checksum; +} + +/** + * hns_ppe_init - init ppe device + * @dsaf_dev: dasf device + * retuen 0 - success , negative --fail + */ +int hns_ppe_init(struct dsaf_device *dsaf_dev) +{ + int i, k; + int ret; + + for (i = 0; i < HNS_PPE_COM_NUM; i++) { + ret = hns_ppe_common_get_cfg(dsaf_dev, i); + if (ret) + goto get_ppe_cfg_fail; + + ret = hns_rcb_common_get_cfg(dsaf_dev, i); + if (ret) + goto get_rcb_cfg_fail; + + hns_ppe_get_cfg(dsaf_dev->ppe_common[i]); + + hns_rcb_get_cfg(dsaf_dev->rcb_common[i]); + } + + for (i = 0; i < HNS_PPE_COM_NUM; i++) + hns_ppe_reset_common(dsaf_dev, i); + + return 0; + +get_rcb_cfg_fail: + hns_ppe_common_free_cfg(dsaf_dev, i); +get_ppe_cfg_fail: + for (k = i - 1; k >= 0; k--) { + hns_rcb_common_free_cfg(dsaf_dev, k); + hns_ppe_common_free_cfg(dsaf_dev, k); + } + return ret; +} + +void hns_ppe_get_regs(struct hns_ppe_cb *ppe_cb, void *data) +{ + struct ppe_common_cb *ppe_common = ppe_cb->ppe_common_cb; + u32 *regs = data; + u32 i; + u32 offset; + + /* ppe common registers */ + regs[0] = dsaf_read_dev(ppe_common, PPE_COM_CFG_QID_MODE_REG); + regs[1] = dsaf_read_dev(ppe_common, PPE_COM_INTEN_REG); + regs[2] = dsaf_read_dev(ppe_common, PPE_COM_RINT_REG); + regs[3] = dsaf_read_dev(ppe_common, PPE_COM_INTSTS_REG); + regs[4] = dsaf_read_dev(ppe_common, PPE_COM_COMMON_CNT_CLR_CE_REG); + + for (i = 0; i < DSAF_TOTAL_QUEUE_NUM; i++) { + offset = PPE_COM_HIS_RX_PKT_QID_DROP_CNT_REG + 0x4 * i; + regs[5 + i] = dsaf_read_dev(ppe_common, offset); + offset = PPE_COM_HIS_RX_PKT_QID_OK_CNT_REG + 0x4 * i; + regs[5 + i + DSAF_TOTAL_QUEUE_NUM] + = dsaf_read_dev(ppe_common, offset); + offset = PPE_COM_HIS_TX_PKT_QID_ERR_CNT_REG + 0x4 * i; + regs[5 + i + DSAF_TOTAL_QUEUE_NUM * 2] + = dsaf_read_dev(ppe_common, offset); + offset = PPE_COM_HIS_TX_PKT_QID_OK_CNT_REG + 0x4 * i; + regs[5 + i + DSAF_TOTAL_QUEUE_NUM * 3] + = dsaf_read_dev(ppe_common, offset); + } + + /* mark end of ppe regs */ + for (i = 521; i < 524; i++) + regs[i] = 0xeeeeeeee; + + /* ppe channel registers */ + regs[525] = dsaf_read_dev(ppe_cb, PPE_CFG_TX_FIFO_THRSLD_REG); + regs[526] = dsaf_read_dev(ppe_cb, PPE_CFG_RX_FIFO_THRSLD_REG); + regs[527] = dsaf_read_dev(ppe_cb, PPE_CFG_RX_FIFO_PAUSE_THRSLD_REG); + regs[528] = dsaf_read_dev(ppe_cb, PPE_CFG_RX_FIFO_SW_BP_THRSLD_REG); + regs[529] = dsaf_read_dev(ppe_cb, PPE_CFG_PAUSE_IDLE_CNT_REG); + regs[530] = dsaf_read_dev(ppe_cb, PPE_CFG_BUS_CTRL_REG); + regs[531] = dsaf_read_dev(ppe_cb, PPE_CFG_TNL_TO_BE_RST_REG); + regs[532] = dsaf_read_dev(ppe_cb, PPE_CURR_TNL_CAN_RST_REG); + + regs[533] = dsaf_read_dev(ppe_cb, PPE_CFG_XGE_MODE_REG); + regs[534] = dsaf_read_dev(ppe_cb, PPE_CFG_MAX_FRAME_LEN_REG); + regs[535] = dsaf_read_dev(ppe_cb, PPE_CFG_RX_PKT_MODE_REG); + regs[536] = dsaf_read_dev(ppe_cb, PPE_CFG_RX_VLAN_TAG_REG); + regs[537] = dsaf_read_dev(ppe_cb, PPE_CFG_TAG_GEN_REG); + regs[538] = dsaf_read_dev(ppe_cb, PPE_CFG_PARSE_TAG_REG); + regs[539] = dsaf_read_dev(ppe_cb, PPE_CFG_PRO_CHECK_EN_REG); + + regs[540] = dsaf_read_dev(ppe_cb, PPE_INTEN_REG); + regs[541] = dsaf_read_dev(ppe_cb, PPE_RINT_REG); + regs[542] = dsaf_read_dev(ppe_cb, PPE_INTSTS_REG); + regs[543] = dsaf_read_dev(ppe_cb, PPE_CFG_RX_PKT_INT_REG); + + regs[544] = dsaf_read_dev(ppe_cb, PPE_CFG_HEAT_DECT_TIME0_REG); + regs[545] = dsaf_read_dev(ppe_cb, PPE_CFG_HEAT_DECT_TIME1_REG); + + /* ppe static */ + regs[546] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_SW_PKT_CNT_REG); + regs[547] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_WR_BD_OK_PKT_CNT_REG); + regs[548] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_PKT_NO_BUF_CNT_REG); + regs[549] = dsaf_read_dev(ppe_cb, PPE_HIS_TX_BD_CNT_REG); + regs[550] = dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_CNT_REG); + regs[551] = dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_OK_CNT_REG); + regs[552] = dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_EPT_CNT_REG); + regs[553] = dsaf_read_dev(ppe_cb, PPE_HIS_TX_PKT_CS_FAIL_CNT_REG); + regs[554] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_APP_BUF_FAIL_CNT_REG); + regs[555] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_APP_BUF_WAIT_CNT_REG); + regs[556] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_PKT_DROP_FUL_CNT_REG); + regs[557] = dsaf_read_dev(ppe_cb, PPE_HIS_RX_PKT_DROP_PRT_CNT_REG); + + regs[558] = dsaf_read_dev(ppe_cb, PPE_TNL_0_5_CNT_CLR_CE_REG); + regs[559] = dsaf_read_dev(ppe_cb, PPE_CFG_AXI_DBG_REG); + regs[560] = dsaf_read_dev(ppe_cb, PPE_HIS_PRO_ERR_REG); + regs[561] = dsaf_read_dev(ppe_cb, PPE_HIS_TNL_FIFO_ERR_REG); + regs[562] = dsaf_read_dev(ppe_cb, PPE_CURR_CFF_DATA_NUM_REG); + regs[563] = dsaf_read_dev(ppe_cb, PPE_CURR_RX_ST_REG); + regs[564] = dsaf_read_dev(ppe_cb, PPE_CURR_TX_ST_REG); + regs[565] = dsaf_read_dev(ppe_cb, PPE_CURR_RX_FIFO0_REG); + regs[566] = dsaf_read_dev(ppe_cb, PPE_CURR_RX_FIFO1_REG); + regs[567] = dsaf_read_dev(ppe_cb, PPE_CURR_TX_FIFO0_REG); + regs[568] = dsaf_read_dev(ppe_cb, PPE_CURR_TX_FIFO1_REG); + regs[569] = dsaf_read_dev(ppe_cb, PPE_ECO0_REG); + regs[570] = dsaf_read_dev(ppe_cb, PPE_ECO1_REG); + regs[571] = dsaf_read_dev(ppe_cb, PPE_ECO2_REG); + + /* mark end of ppe regs */ + for (i = 572; i < 576; i++) + regs[i] = 0xeeeeeeee; +} diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h new file mode 100644 index 000000000000..4894f9a0d39f --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _HNS_DSAF_PPE_H +#define _HNS_DSAF_PPE_H + +#include + +#include "hns_dsaf_main.h" +#include "hns_dsaf_mac.h" +#include "hns_dsaf_rcb.h" + +#define HNS_PPE_SERVICE_NW_ENGINE_NUM DSAF_COMM_CHN +#define HNS_PPE_DEBUG_NW_ENGINE_NUM 1 +#define HNS_PPE_COM_NUM DSAF_COMM_DEV_NUM + +#define PPE_COMMON_REG_OFFSET 0x70000 +#define PPE_REG_OFFSET 0x10000 + +#define ETH_PPE_DUMP_NUM 576 +#define ETH_PPE_STATIC_NUM 12 +enum ppe_qid_mode { + PPE_QID_MODE0 = 0, /* fixed queue id mode */ + PPE_QID_MODE1, /* switch:128VM non switch:6Port/4VM/4TC */ + PPE_QID_MODE2, /* switch:32VM/4TC non switch:6Port/16VM */ + PPE_QID_MODE3, /* switch:4TC/8TAG non switch:2Port/64VM */ + PPE_QID_MODE4, /* switch:8VM/16TAG non switch:2Port/16VM/4TC */ + PPE_QID_MODE5, /* non switch:6Port/16TAG */ + PPE_QID_MODE6, /* non switch:6Port/2VM/8TC */ + PPE_QID_MODE7, /* non switch:2Port/8VM/8TC */ +}; + +enum ppe_port_mode { + PPE_MODE_GE = 0, + PPE_MODE_XGE, +}; + +enum ppe_common_mode { + PPE_COMMON_MODE_DEBUG = 0, + PPE_COMMON_MODE_SERVICE, + PPE_COMMON_MODE_MAX +}; + +struct hns_ppe_hw_stats { + u64 rx_pkts_from_sw; + u64 rx_pkts; + u64 rx_drop_no_bd; + u64 rx_alloc_buf_fail; + u64 rx_alloc_buf_wait; + u64 rx_drop_no_buf; + u64 rx_err_fifo_full; + u64 tx_bd_form_rcb; + u64 tx_pkts_from_rcb; + u64 tx_pkts; + u64 tx_err_fifo_empty; + u64 tx_err_checksum; +}; + +struct hns_ppe_cb { + struct device *dev; + struct hns_ppe_cb *next; /* pointer to next ppe device */ + struct ppe_common_cb *ppe_common_cb; /* belong to */ + struct hns_ppe_hw_stats hw_stats; + + u8 index; /* index in a ppe common device */ + u8 port; /* port id in dsaf */ + void __iomem *io_base; + int virq; +}; + +struct ppe_common_cb { + struct device *dev; + struct dsaf_device *dsaf_dev; + void __iomem *io_base; + + enum ppe_common_mode ppe_mode; + + u8 comm_index; /*ppe_common index*/ + + u32 ppe_num; + struct hns_ppe_cb ppe_cb[0]; + +}; + +int hns_ppe_init(struct dsaf_device *dsaf_dev); + +void hns_ppe_uninit(struct dsaf_device *dsaf_dev); + +void hns_ppe_reset_common(struct dsaf_device *dsaf_dev, u8 ppe_common_index); + +void hns_ppe_update_stats(struct hns_ppe_cb *ppe_cb); + +int hns_ppe_get_sset_count(int stringset); +int hns_ppe_get_regs_count(void); +void hns_ppe_get_regs(struct hns_ppe_cb *ppe_cb, void *data); + +void hns_ppe_get_strings(struct hns_ppe_cb *ppe_cb, int stringset, u8 *data); +void hns_ppe_get_stats(struct hns_ppe_cb *ppe_cb, u64 *data); +#endif /* _HNS_DSAF_PPE_H */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c new file mode 100644 index 000000000000..50f3427709d9 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -0,0 +1,1023 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hns_dsaf_main.h" +#include "hns_dsaf_ppe.h" +#include "hns_dsaf_rcb.h" + +#define RCB_COMMON_REG_OFFSET 0x80000 +#define TX_RING 0 +#define RX_RING 1 + +#define RCB_RESET_WAIT_TIMES 30 +#define RCB_RESET_TRY_TIMES 10 + +/** + *hns_rcb_wait_fbd_clean - clean fbd + *@qs: ring struct pointer array + *@qnum: num of array + *@flag: tx or rx flag + */ +void hns_rcb_wait_fbd_clean(struct hnae_queue **qs, int q_num, u32 flag) +{ + int i, wait_cnt; + u32 fbd_num; + + for (wait_cnt = i = 0; i < q_num; wait_cnt++) { + usleep_range(200, 300); + fbd_num = 0; + if (flag & RCB_INT_FLAG_TX) + fbd_num += dsaf_read_dev(qs[i], + RCB_RING_TX_RING_FBDNUM_REG); + if (flag & RCB_INT_FLAG_RX) + fbd_num += dsaf_read_dev(qs[i], + RCB_RING_RX_RING_FBDNUM_REG); + if (!fbd_num) + i++; + if (wait_cnt >= 10000) + break; + } + + if (i < q_num) + dev_err(qs[i]->handle->owner_dev, + "queue(%d) wait fbd(%d) clean fail!!\n", i, fbd_num); +} + +/** + *hns_rcb_reset_ring_hw - ring reset + *@q: ring struct pointer + */ +void hns_rcb_reset_ring_hw(struct hnae_queue *q) +{ + u32 wait_cnt; + u32 try_cnt = 0; + u32 could_ret; + + u32 tx_fbd_num; + + while (try_cnt++ < RCB_RESET_TRY_TIMES) { + usleep_range(100, 200); + tx_fbd_num = dsaf_read_dev(q, RCB_RING_TX_RING_FBDNUM_REG); + if (tx_fbd_num) + continue; + + dsaf_write_dev(q, RCB_RING_PREFETCH_EN_REG, 0); + + dsaf_write_dev(q, RCB_RING_T0_BE_RST, 1); + + msleep(20); + could_ret = dsaf_read_dev(q, RCB_RING_COULD_BE_RST); + + wait_cnt = 0; + while (!could_ret && (wait_cnt < RCB_RESET_WAIT_TIMES)) { + dsaf_write_dev(q, RCB_RING_T0_BE_RST, 0); + + dsaf_write_dev(q, RCB_RING_T0_BE_RST, 1); + + msleep(20); + could_ret = dsaf_read_dev(q, RCB_RING_COULD_BE_RST); + + wait_cnt++; + } + + dsaf_write_dev(q, RCB_RING_T0_BE_RST, 0); + + if (could_ret) + break; + } + + if (try_cnt >= RCB_RESET_TRY_TIMES) + dev_err(q->dev->dev, "port%d reset ring fail\n", + hns_ae_get_vf_cb(q->handle)->port_index); +} + +/** + *hns_rcb_int_ctrl_hw - rcb irq enable control + *@q: hnae queue struct pointer + *@flag:ring flag tx or rx + *@mask:mask + */ +void hns_rcb_int_ctrl_hw(struct hnae_queue *q, u32 flag, u32 mask) +{ + u32 int_mask_en = !!mask; + + if (flag & RCB_INT_FLAG_TX) { + dsaf_write_dev(q, RCB_RING_INTMSK_TXWL_REG, int_mask_en); + dsaf_write_dev(q, RCB_RING_INTMSK_TX_OVERTIME_REG, + int_mask_en); + } + + if (flag & RCB_INT_FLAG_RX) { + dsaf_write_dev(q, RCB_RING_INTMSK_RXWL_REG, int_mask_en); + dsaf_write_dev(q, RCB_RING_INTMSK_RX_OVERTIME_REG, + int_mask_en); + } +} + +void hns_rcb_int_clr_hw(struct hnae_queue *q, u32 flag) +{ + u32 clr = 1; + + if (flag & RCB_INT_FLAG_TX) { + dsaf_write_dev(q, RCB_RING_INTSTS_TX_RING_REG, clr); + dsaf_write_dev(q, RCB_RING_INTSTS_TX_OVERTIME_REG, clr); + } + + if (flag & RCB_INT_FLAG_RX) { + dsaf_write_dev(q, RCB_RING_INTSTS_RX_RING_REG, clr); + dsaf_write_dev(q, RCB_RING_INTSTS_RX_OVERTIME_REG, clr); + } +} + +/** + *hns_rcb_ring_enable_hw - enable ring + *@ring: rcb ring + */ +void hns_rcb_ring_enable_hw(struct hnae_queue *q, u32 val) +{ + dsaf_write_dev(q, RCB_RING_PREFETCH_EN_REG, !!val); +} + +void hns_rcb_start(struct hnae_queue *q, u32 val) +{ + hns_rcb_ring_enable_hw(q, val); +} + +/** + *hns_rcb_common_init_commit_hw - make rcb common init completed + *@rcb_common: rcb common device + */ +void hns_rcb_common_init_commit_hw(struct rcb_common_cb *rcb_common) +{ + wmb(); /* Sync point before breakpoint */ + dsaf_write_dev(rcb_common, RCB_COM_CFG_SYS_FSH_REG, 1); + wmb(); /* Sync point after breakpoint */ +} + +/** + *hns_rcb_ring_init - init rcb ring + *@ring_pair: ring pair control block + *@ring_type: ring type, RX_RING or TX_RING + */ +static void hns_rcb_ring_init(struct ring_pair_cb *ring_pair, int ring_type) +{ + struct hnae_queue *q = &ring_pair->q; + struct rcb_common_cb *rcb_common = ring_pair->rcb_common; + u32 bd_size_type = rcb_common->dsaf_dev->buf_size_type; + struct hnae_ring *ring = + (ring_type == RX_RING) ? &q->rx_ring : &q->tx_ring; + dma_addr_t dma = ring->desc_dma_addr; + + if (ring_type == RX_RING) { + dsaf_write_dev(q, RCB_RING_RX_RING_BASEADDR_L_REG, + (u32)dma); + dsaf_write_dev(q, RCB_RING_RX_RING_BASEADDR_H_REG, + (u32)(dma >> 32)); + + dsaf_write_dev(q, RCB_RING_RX_RING_BD_LEN_REG, + bd_size_type); + dsaf_write_dev(q, RCB_RING_RX_RING_BD_NUM_REG, + ring_pair->port_id_in_dsa); + dsaf_write_dev(q, RCB_RING_RX_RING_PKTLINE_REG, + ring_pair->port_id_in_dsa); + } else { + dsaf_write_dev(q, RCB_RING_TX_RING_BASEADDR_L_REG, + (u32)dma); + dsaf_write_dev(q, RCB_RING_TX_RING_BASEADDR_H_REG, + (u32)(dma >> 32)); + + dsaf_write_dev(q, RCB_RING_TX_RING_BD_LEN_REG, + bd_size_type); + dsaf_write_dev(q, RCB_RING_TX_RING_BD_NUM_REG, + ring_pair->port_id_in_dsa); + dsaf_write_dev(q, RCB_RING_TX_RING_PKTLINE_REG, + ring_pair->port_id_in_dsa); + } +} + +/** + *hns_rcb_init_hw - init rcb hardware + *@ring: rcb ring + */ +void hns_rcb_init_hw(struct ring_pair_cb *ring) +{ + hns_rcb_ring_init(ring, RX_RING); + hns_rcb_ring_init(ring, TX_RING); +} + +/** + *hns_rcb_set_port_desc_cnt - set rcb port description num + *@rcb_common: rcb_common device + *@port_idx:port index + *@desc_cnt:BD num + */ +static void hns_rcb_set_port_desc_cnt(struct rcb_common_cb *rcb_common, + u32 port_idx, u32 desc_cnt) +{ + if (port_idx >= HNS_RCB_SERVICE_NW_ENGINE_NUM) + port_idx = 0; + + dsaf_write_dev(rcb_common, RCB_CFG_BD_NUM_REG + port_idx * 4, + desc_cnt); +} + +/** + *hns_rcb_set_port_coalesced_frames - set rcb port coalesced frames + *@rcb_common: rcb_common device + *@port_idx:port index + *@coalesced_frames:BD num for coalesced frames + */ +static int hns_rcb_set_port_coalesced_frames(struct rcb_common_cb *rcb_common, + u32 port_idx, + u32 coalesced_frames) +{ + if (port_idx >= HNS_RCB_SERVICE_NW_ENGINE_NUM) + port_idx = 0; + if (coalesced_frames >= rcb_common->desc_num || + coalesced_frames > HNS_RCB_MAX_COALESCED_FRAMES) + return -EINVAL; + + dsaf_write_dev(rcb_common, RCB_CFG_PKTLINE_REG + port_idx * 4, + coalesced_frames); + return 0; +} + +/** + *hns_rcb_get_port_coalesced_frames - set rcb port coalesced frames + *@rcb_common: rcb_common device + *@port_idx:port index + * return coaleseced frames value + */ +static u32 hns_rcb_get_port_coalesced_frames(struct rcb_common_cb *rcb_common, + u32 port_idx) +{ + if (port_idx >= HNS_RCB_SERVICE_NW_ENGINE_NUM) + port_idx = 0; + + return dsaf_read_dev(rcb_common, + RCB_CFG_PKTLINE_REG + port_idx * 4); +} + +/** + *hns_rcb_set_timeout - set rcb port coalesced time_out + *@rcb_common: rcb_common device + *@time_out:time for coalesced time_out + */ +static void hns_rcb_set_timeout(struct rcb_common_cb *rcb_common, + u32 timeout) +{ + dsaf_write_dev(rcb_common, RCB_CFG_OVERTIME_REG, timeout); +} + +static int hns_rcb_common_get_port_num(struct rcb_common_cb *rcb_common) +{ + if (rcb_common->comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) + return HNS_RCB_SERVICE_NW_ENGINE_NUM; + else + return HNS_RCB_DEBUG_NW_ENGINE_NUM; +} + +/*clr rcb comm exception irq**/ +static void hns_rcb_comm_exc_irq_en( + struct rcb_common_cb *rcb_common, int en) +{ + u32 clr_vlue = 0xfffffffful; + u32 msk_vlue = en ? 0 : 0xfffffffful; + + /* clr int*/ + dsaf_write_dev(rcb_common, RCB_COM_INTSTS_ECC_ERR_REG, clr_vlue); + + dsaf_write_dev(rcb_common, RCB_COM_SF_CFG_RING_STS, clr_vlue); + + dsaf_write_dev(rcb_common, RCB_COM_SF_CFG_BD_RINT_STS, clr_vlue); + + dsaf_write_dev(rcb_common, RCB_COM_RINT_TX_PKT_REG, clr_vlue); + dsaf_write_dev(rcb_common, RCB_COM_AXI_ERR_STS, clr_vlue); + + /*en msk*/ + dsaf_write_dev(rcb_common, RCB_COM_INTMASK_ECC_ERR_REG, msk_vlue); + + dsaf_write_dev(rcb_common, RCB_COM_SF_CFG_INTMASK_RING, msk_vlue); + + /*for tx bd neednot cacheline, so msk sf_txring_fbd_intmask (bit 1)**/ + dsaf_write_dev(rcb_common, RCB_COM_SF_CFG_INTMASK_BD, msk_vlue | 2); + + dsaf_write_dev(rcb_common, RCB_COM_INTMSK_TX_PKT_REG, msk_vlue); + dsaf_write_dev(rcb_common, RCB_COM_AXI_WR_ERR_INTMASK, msk_vlue); +} + +/** + *hns_rcb_common_init_hw - init rcb common hardware + *@rcb_common: rcb_common device + *retuen 0 - success , negative --fail + */ +int hns_rcb_common_init_hw(struct rcb_common_cb *rcb_common) +{ + u32 reg_val; + int i; + int port_num = hns_rcb_common_get_port_num(rcb_common); + + hns_rcb_comm_exc_irq_en(rcb_common, 0); + + reg_val = dsaf_read_dev(rcb_common, RCB_COM_CFG_INIT_FLAG_REG); + if (0x1 != (reg_val & 0x1)) { + dev_err(rcb_common->dsaf_dev->dev, + "RCB_COM_CFG_INIT_FLAG_REG reg = 0x%x\n", reg_val); + return -EBUSY; + } + + for (i = 0; i < port_num; i++) { + hns_rcb_set_port_desc_cnt(rcb_common, i, rcb_common->desc_num); + (void)hns_rcb_set_port_coalesced_frames( + rcb_common, i, rcb_common->coalesced_frames); + } + hns_rcb_set_timeout(rcb_common, rcb_common->timeout); + + dsaf_write_dev(rcb_common, RCB_COM_CFG_ENDIAN_REG, + HNS_RCB_COMMON_ENDIAN); + + return 0; +} + +int hns_rcb_buf_size2type(u32 buf_size) +{ + int bd_size_type; + + switch (buf_size) { + case 512: + bd_size_type = HNS_BD_SIZE_512_TYPE; + break; + case 1024: + bd_size_type = HNS_BD_SIZE_1024_TYPE; + break; + case 2048: + bd_size_type = HNS_BD_SIZE_2048_TYPE; + break; + case 4096: + bd_size_type = HNS_BD_SIZE_4096_TYPE; + break; + default: + bd_size_type = -EINVAL; + } + + return bd_size_type; +} + +static void hns_rcb_ring_get_cfg(struct hnae_queue *q, int ring_type) +{ + struct hnae_ring *ring; + struct rcb_common_cb *rcb_common; + struct ring_pair_cb *ring_pair_cb; + u32 buf_size; + u16 desc_num; + int irq_idx; + + ring_pair_cb = container_of(q, struct ring_pair_cb, q); + if (ring_type == RX_RING) { + ring = &q->rx_ring; + ring->io_base = ring_pair_cb->q.io_base; + irq_idx = HNS_RCB_IRQ_IDX_RX; + } else { + ring = &q->tx_ring; + ring->io_base = (u8 __iomem *)ring_pair_cb->q.io_base + + HNS_RCB_TX_REG_OFFSET; + irq_idx = HNS_RCB_IRQ_IDX_TX; + } + + rcb_common = ring_pair_cb->rcb_common; + buf_size = rcb_common->dsaf_dev->buf_size; + desc_num = rcb_common->dsaf_dev->desc_num; + + ring->desc = NULL; + ring->desc_cb = NULL; + + ring->irq = ring_pair_cb->virq[irq_idx]; + ring->desc_dma_addr = 0; + + ring->buf_size = buf_size; + ring->desc_num = desc_num; + ring->max_desc_num_per_pkt = HNS_RCB_RING_MAX_BD_PER_PKT; + ring->max_raw_data_sz_per_desc = HNS_RCB_MAX_PKT_SIZE; + ring->max_pkt_size = HNS_RCB_MAX_PKT_SIZE; + ring->next_to_use = 0; + ring->next_to_clean = 0; +} + +static void hns_rcb_ring_pair_get_cfg(struct ring_pair_cb *ring_pair_cb) +{ + ring_pair_cb->q.handle = NULL; + + hns_rcb_ring_get_cfg(&ring_pair_cb->q, RX_RING); + hns_rcb_ring_get_cfg(&ring_pair_cb->q, TX_RING); +} + +static int hns_rcb_get_port(struct rcb_common_cb *rcb_common, int ring_idx) +{ + int comm_index = rcb_common->comm_index; + int port; + int q_num; + + if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { + q_num = (int)rcb_common->max_q_per_vf * rcb_common->max_vfn; + port = ring_idx / q_num; + } else { + port = HNS_RCB_SERVICE_NW_ENGINE_NUM + comm_index - 1; + } + + return port; +} + +static int hns_rcb_get_base_irq_idx(struct rcb_common_cb *rcb_common) +{ + int comm_index = rcb_common->comm_index; + + if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) + return HNS_SERVICE_RING_IRQ_IDX; + else + return HNS_DEBUG_RING_IRQ_IDX + (comm_index - 1) * 2; +} + +#define RCB_COMM_BASE_TO_RING_BASE(base, ringid)\ + ((base) + 0x10000 + HNS_RCB_REG_OFFSET * (ringid)) +/** + *hns_rcb_get_cfg - get rcb config + *@rcb_common: rcb common device + */ +void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common) +{ + struct ring_pair_cb *ring_pair_cb; + u32 i; + u32 ring_num = rcb_common->ring_num; + int base_irq_idx = hns_rcb_get_base_irq_idx(rcb_common); + struct device_node *np = rcb_common->dsaf_dev->dev->of_node; + + for (i = 0; i < ring_num; i++) { + ring_pair_cb = &rcb_common->ring_pair_cb[i]; + ring_pair_cb->rcb_common = rcb_common; + ring_pair_cb->dev = rcb_common->dsaf_dev->dev; + ring_pair_cb->index = i; + ring_pair_cb->q.io_base = + RCB_COMM_BASE_TO_RING_BASE(rcb_common->io_base, i); + ring_pair_cb->port_id_in_dsa = hns_rcb_get_port(rcb_common, i); + ring_pair_cb->virq[HNS_RCB_IRQ_IDX_TX] + = irq_of_parse_and_map(np, base_irq_idx + i * 2); + ring_pair_cb->virq[HNS_RCB_IRQ_IDX_RX] + = irq_of_parse_and_map(np, base_irq_idx + i * 2 + 1); + ring_pair_cb->q.phy_base = + RCB_COMM_BASE_TO_RING_BASE(rcb_common->phy_base, i); + hns_rcb_ring_pair_get_cfg(ring_pair_cb); + } +} + +/** + *hns_rcb_get_coalesced_frames - get rcb port coalesced frames + *@rcb_common: rcb_common device + *@comm_index:port index + *return coalesced_frames + */ +u32 hns_rcb_get_coalesced_frames(struct dsaf_device *dsaf_dev, int port) +{ + int comm_index = hns_dsaf_get_comm_idx_by_port(port); + struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index]; + + return hns_rcb_get_port_coalesced_frames(rcb_comm, port); +} + +/** + *hns_rcb_get_coalesce_usecs - get rcb port coalesced time_out + *@rcb_common: rcb_common device + *@comm_index:port index + *return time_out + */ +u32 hns_rcb_get_coalesce_usecs(struct dsaf_device *dsaf_dev, int comm_index) +{ + struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index]; + + return rcb_comm->timeout; +} + +/** + *hns_rcb_set_coalesce_usecs - set rcb port coalesced time_out + *@rcb_common: rcb_common device + *@comm_index: comm :index + *@etx_usecs:tx time for coalesced time_out + *@rx_usecs:rx time for coalesced time_out + */ +void hns_rcb_set_coalesce_usecs(struct dsaf_device *dsaf_dev, + int port, u32 timeout) +{ + int comm_index = hns_dsaf_get_comm_idx_by_port(port); + struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index]; + + if (rcb_comm->timeout == timeout) + return; + + if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { + dev_err(dsaf_dev->dev, + "error: not support coalesce_usecs setting!\n"); + return; + } + rcb_comm->timeout = timeout; + hns_rcb_set_timeout(rcb_comm, rcb_comm->timeout); +} + +/** + *hns_rcb_set_coalesced_frames - set rcb coalesced frames + *@rcb_common: rcb_common device + *@tx_frames:tx BD num for coalesced frames + *@rx_frames:rx BD num for coalesced frames + *Return 0 on success, negative on failure + */ +int hns_rcb_set_coalesced_frames(struct dsaf_device *dsaf_dev, + int port, u32 coalesced_frames) +{ + int comm_index = hns_dsaf_get_comm_idx_by_port(port); + struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index]; + u32 coalesced_reg_val; + int ret; + + coalesced_reg_val = hns_rcb_get_port_coalesced_frames(rcb_comm, port); + + if (coalesced_reg_val == coalesced_frames) + return 0; + + if (coalesced_frames >= HNS_RCB_MIN_COALESCED_FRAMES) { + ret = hns_rcb_set_port_coalesced_frames(rcb_comm, port, + coalesced_frames); + return ret; + } else { + return -EINVAL; + } +} + +/** + *hns_rcb_get_queue_mode - get max VM number and max ring number per VM + * accordding to dsaf mode + *@dsaf_mode: dsaf mode + *@max_vfn : max vfn number + *@max_q_per_vf:max ring number per vm + */ +static void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, int comm_index, + u16 *max_vfn, u16 *max_q_per_vf) +{ + if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { + switch (dsaf_mode) { + case DSAF_MODE_DISABLE_6PORT_0VM: + *max_vfn = 1; + *max_q_per_vf = 16; + break; + case DSAF_MODE_DISABLE_FIX: + *max_vfn = 1; + *max_q_per_vf = 1; + break; + case DSAF_MODE_DISABLE_2PORT_64VM: + *max_vfn = 64; + *max_q_per_vf = 1; + break; + case DSAF_MODE_DISABLE_6PORT_16VM: + *max_vfn = 16; + *max_q_per_vf = 1; + break; + default: + *max_vfn = 1; + *max_q_per_vf = 16; + break; + } + } else { + *max_vfn = 1; + *max_q_per_vf = 1; + } +} + +int hns_rcb_get_ring_num(struct dsaf_device *dsaf_dev, int comm_index) +{ + if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { + switch (dsaf_dev->dsaf_mode) { + case DSAF_MODE_ENABLE_FIX: + return 1; + + case DSAF_MODE_DISABLE_FIX: + return 6; + + case DSAF_MODE_ENABLE_0VM: + return 32; + + case DSAF_MODE_DISABLE_6PORT_0VM: + case DSAF_MODE_ENABLE_16VM: + case DSAF_MODE_DISABLE_6PORT_2VM: + case DSAF_MODE_DISABLE_6PORT_16VM: + case DSAF_MODE_DISABLE_6PORT_4VM: + case DSAF_MODE_ENABLE_8VM: + return 96; + + case DSAF_MODE_DISABLE_2PORT_16VM: + case DSAF_MODE_DISABLE_2PORT_8VM: + case DSAF_MODE_ENABLE_32VM: + case DSAF_MODE_DISABLE_2PORT_64VM: + case DSAF_MODE_ENABLE_128VM: + return 128; + + default: + dev_warn(dsaf_dev->dev, + "get ring num fail,use default!dsaf_mode=%d\n", + dsaf_dev->dsaf_mode); + return 128; + } + } else { + return 1; + } +} + +void __iomem *hns_rcb_common_get_vaddr(struct dsaf_device *dsaf_dev, + int comm_index) +{ + void __iomem *base_addr; + + if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) + base_addr = dsaf_dev->ppe_base + RCB_COMMON_REG_OFFSET; + else + base_addr = dsaf_dev->sds_base + + (comm_index - 1) * HNS_DSAF_DEBUG_NW_REG_OFFSET + + RCB_COMMON_REG_OFFSET; + + return base_addr; +} + +static phys_addr_t hns_rcb_common_get_paddr(struct dsaf_device *dsaf_dev, + int comm_index) +{ + struct device_node *np = dsaf_dev->dev->of_node; + phys_addr_t phy_addr; + const __be32 *tmp_addr; + u64 addr_offset = 0; + u64 size = 0; + int index = 0; + + if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { + index = 2; + addr_offset = RCB_COMMON_REG_OFFSET; + } else { + index = 1; + addr_offset = (comm_index - 1) * HNS_DSAF_DEBUG_NW_REG_OFFSET + + RCB_COMMON_REG_OFFSET; + } + tmp_addr = of_get_address(np, index, &size, NULL); + phy_addr = of_translate_address(np, tmp_addr); + return phy_addr + addr_offset; +} + +int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev, + int comm_index) +{ + struct rcb_common_cb *rcb_common; + enum dsaf_mode dsaf_mode = dsaf_dev->dsaf_mode; + u16 max_vfn; + u16 max_q_per_vf; + int ring_num = hns_rcb_get_ring_num(dsaf_dev, comm_index); + + rcb_common = + devm_kzalloc(dsaf_dev->dev, sizeof(*rcb_common) + + ring_num * sizeof(struct ring_pair_cb), GFP_KERNEL); + if (!rcb_common) { + dev_err(dsaf_dev->dev, "rcb common devm_kzalloc fail!\n"); + return -ENOMEM; + } + rcb_common->comm_index = comm_index; + rcb_common->ring_num = ring_num; + rcb_common->dsaf_dev = dsaf_dev; + + rcb_common->desc_num = dsaf_dev->desc_num; + rcb_common->coalesced_frames = HNS_RCB_DEF_COALESCED_FRAMES; + rcb_common->timeout = HNS_RCB_MAX_TIME_OUT; + + hns_rcb_get_queue_mode(dsaf_mode, comm_index, &max_vfn, &max_q_per_vf); + rcb_common->max_vfn = max_vfn; + rcb_common->max_q_per_vf = max_q_per_vf; + + rcb_common->io_base = hns_rcb_common_get_vaddr(dsaf_dev, comm_index); + rcb_common->phy_base = hns_rcb_common_get_paddr(dsaf_dev, comm_index); + + dsaf_dev->rcb_common[comm_index] = rcb_common; + return 0; +} + +void hns_rcb_common_free_cfg(struct dsaf_device *dsaf_dev, + u32 comm_index) +{ + dsaf_dev->rcb_common[comm_index] = NULL; +} + +void hns_rcb_update_stats(struct hnae_queue *queue) +{ + struct ring_pair_cb *ring = + container_of(queue, struct ring_pair_cb, q); + struct dsaf_device *dsaf_dev = ring->rcb_common->dsaf_dev; + struct ppe_common_cb *ppe_common + = dsaf_dev->ppe_common[ring->rcb_common->comm_index]; + struct hns_ring_hw_stats *hw_stats = &ring->hw_stats; + + hw_stats->rx_pkts += dsaf_read_dev(queue, + RCB_RING_RX_RING_PKTNUM_RECORD_REG); + dsaf_write_dev(queue, RCB_RING_RX_RING_PKTNUM_RECORD_REG, 0x1); + + hw_stats->ppe_rx_ok_pkts += dsaf_read_dev(ppe_common, + PPE_COM_HIS_RX_PKT_QID_OK_CNT_REG + 4 * ring->index); + hw_stats->ppe_rx_drop_pkts += dsaf_read_dev(ppe_common, + PPE_COM_HIS_RX_PKT_QID_DROP_CNT_REG + 4 * ring->index); + + hw_stats->tx_pkts += dsaf_read_dev(queue, + RCB_RING_TX_RING_PKTNUM_RECORD_REG); + dsaf_write_dev(queue, RCB_RING_TX_RING_PKTNUM_RECORD_REG, 0x1); + + hw_stats->ppe_tx_ok_pkts += dsaf_read_dev(ppe_common, + PPE_COM_HIS_TX_PKT_QID_OK_CNT_REG + 4 * ring->index); + hw_stats->ppe_tx_drop_pkts += dsaf_read_dev(ppe_common, + PPE_COM_HIS_TX_PKT_QID_ERR_CNT_REG + 4 * ring->index); +} + +/** + *hns_rcb_get_stats - get rcb statistic + *@ring: rcb ring + *@data:statistic value + */ +void hns_rcb_get_stats(struct hnae_queue *queue, u64 *data) +{ + u64 *regs_buff = data; + struct ring_pair_cb *ring = + container_of(queue, struct ring_pair_cb, q); + struct hns_ring_hw_stats *hw_stats = &ring->hw_stats; + + regs_buff[0] = hw_stats->tx_pkts; + regs_buff[1] = hw_stats->ppe_tx_ok_pkts; + regs_buff[2] = hw_stats->ppe_tx_drop_pkts; + regs_buff[3] = + dsaf_read_dev(queue, RCB_RING_TX_RING_FBDNUM_REG); + + regs_buff[4] = queue->tx_ring.stats.tx_pkts; + regs_buff[5] = queue->tx_ring.stats.tx_bytes; + regs_buff[6] = queue->tx_ring.stats.tx_err_cnt; + regs_buff[7] = queue->tx_ring.stats.io_err_cnt; + regs_buff[8] = queue->tx_ring.stats.sw_err_cnt; + regs_buff[9] = queue->tx_ring.stats.seg_pkt_cnt; + regs_buff[10] = queue->tx_ring.stats.restart_queue; + regs_buff[11] = queue->tx_ring.stats.tx_busy; + + regs_buff[12] = hw_stats->rx_pkts; + regs_buff[13] = hw_stats->ppe_rx_ok_pkts; + regs_buff[14] = hw_stats->ppe_rx_drop_pkts; + regs_buff[15] = + dsaf_read_dev(queue, RCB_RING_RX_RING_FBDNUM_REG); + + regs_buff[16] = queue->rx_ring.stats.rx_pkts; + regs_buff[17] = queue->rx_ring.stats.rx_bytes; + regs_buff[18] = queue->rx_ring.stats.rx_err_cnt; + regs_buff[19] = queue->rx_ring.stats.io_err_cnt; + regs_buff[20] = queue->rx_ring.stats.sw_err_cnt; + regs_buff[21] = queue->rx_ring.stats.seg_pkt_cnt; + regs_buff[22] = queue->rx_ring.stats.reuse_pg_cnt; + regs_buff[23] = queue->rx_ring.stats.err_pkt_len; + regs_buff[24] = queue->rx_ring.stats.non_vld_descs; + regs_buff[25] = queue->rx_ring.stats.err_bd_num; + regs_buff[26] = queue->rx_ring.stats.l2_err; + regs_buff[27] = queue->rx_ring.stats.l3l4_csum_err; +} + +/** + *hns_rcb_get_ring_sset_count - rcb string set count + *@stringset:ethtool cmd + *return rcb ring string set count + */ +int hns_rcb_get_ring_sset_count(int stringset) +{ + if (stringset == ETH_SS_STATS) + return HNS_RING_STATIC_REG_NUM; + + return 0; +} + +/** + *hns_rcb_get_common_regs_count - rcb common regs count + *return regs count + */ +int hns_rcb_get_common_regs_count(void) +{ + return HNS_RCB_COMMON_DUMP_REG_NUM; +} + +/** + *rcb_get_sset_count - rcb ring regs count + *return regs count + */ +int hns_rcb_get_ring_regs_count(void) +{ + return HNS_RCB_RING_DUMP_REG_NUM; +} + +/** + *hns_rcb_get_strings - get rcb string set + *@stringset:string set index + *@data:strings name value + *@index:queue index + */ +void hns_rcb_get_strings(int stringset, u8 *data, int index) +{ + char *buff = (char *)data; + + if (stringset != ETH_SS_STATS) + return; + + snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_rcb_pkt_num", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_ppe_tx_pkt_num", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_ppe_drop_pkt_num", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_fbd_num", index); + buff = buff + ETH_GSTRING_LEN; + + snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_pkt_num", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_bytes", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_err_cnt", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_io_err", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_sw_err", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_seg_pkt", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_restart_queue", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_ring%d_tx_busy", index); + buff = buff + ETH_GSTRING_LEN; + + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_rcb_pkt_num", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_ppe_pkt_num", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_ppe_drop_pkt_num", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_fbd_num", index); + buff = buff + ETH_GSTRING_LEN; + + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_pkt_num", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_bytes", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_err_cnt", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_io_err", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_sw_err", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_seg_pkt", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_reuse_pg", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_len_err", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_non_vld_desc_err", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_bd_num_err", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_l2_err", index); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_ring%d_l3l4csum_err", index); +} + +void hns_rcb_get_common_regs(struct rcb_common_cb *rcb_com, void *data) +{ + u32 *regs = data; + u32 i = 0; + + /*rcb common registers */ + regs[0] = dsaf_read_dev(rcb_com, RCB_COM_CFG_ENDIAN_REG); + regs[1] = dsaf_read_dev(rcb_com, RCB_COM_CFG_SYS_FSH_REG); + regs[2] = dsaf_read_dev(rcb_com, RCB_COM_CFG_INIT_FLAG_REG); + + regs[3] = dsaf_read_dev(rcb_com, RCB_COM_CFG_PKT_REG); + regs[4] = dsaf_read_dev(rcb_com, RCB_COM_CFG_RINVLD_REG); + regs[5] = dsaf_read_dev(rcb_com, RCB_COM_CFG_FNA_REG); + regs[6] = dsaf_read_dev(rcb_com, RCB_COM_CFG_FA_REG); + regs[7] = dsaf_read_dev(rcb_com, RCB_COM_CFG_PKT_TC_BP_REG); + regs[8] = dsaf_read_dev(rcb_com, RCB_COM_CFG_PPE_TNL_CLKEN_REG); + + regs[9] = dsaf_read_dev(rcb_com, RCB_COM_INTMSK_TX_PKT_REG); + regs[10] = dsaf_read_dev(rcb_com, RCB_COM_RINT_TX_PKT_REG); + regs[11] = dsaf_read_dev(rcb_com, RCB_COM_INTMASK_ECC_ERR_REG); + regs[12] = dsaf_read_dev(rcb_com, RCB_COM_INTSTS_ECC_ERR_REG); + regs[13] = dsaf_read_dev(rcb_com, RCB_COM_EBD_SRAM_ERR_REG); + regs[14] = dsaf_read_dev(rcb_com, RCB_COM_RXRING_ERR_REG); + regs[15] = dsaf_read_dev(rcb_com, RCB_COM_TXRING_ERR_REG); + regs[16] = dsaf_read_dev(rcb_com, RCB_COM_TX_FBD_ERR_REG); + regs[17] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK_EN_REG); + regs[18] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK0_REG); + regs[19] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK1_REG); + regs[20] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK2_REG); + regs[21] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK3_REG); + regs[22] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK4_REG); + regs[23] = dsaf_read_dev(rcb_com, RCB_SRAM_ECC_CHK5_REG); + regs[24] = dsaf_read_dev(rcb_com, RCB_ECC_ERR_ADDR0_REG); + regs[25] = dsaf_read_dev(rcb_com, RCB_ECC_ERR_ADDR3_REG); + regs[26] = dsaf_read_dev(rcb_com, RCB_ECC_ERR_ADDR4_REG); + regs[27] = dsaf_read_dev(rcb_com, RCB_ECC_ERR_ADDR5_REG); + + regs[28] = dsaf_read_dev(rcb_com, RCB_COM_SF_CFG_INTMASK_RING); + regs[29] = dsaf_read_dev(rcb_com, RCB_COM_SF_CFG_RING_STS); + regs[30] = dsaf_read_dev(rcb_com, RCB_COM_SF_CFG_RING); + regs[31] = dsaf_read_dev(rcb_com, RCB_COM_SF_CFG_INTMASK_BD); + regs[32] = dsaf_read_dev(rcb_com, RCB_COM_SF_CFG_BD_RINT_STS); + regs[33] = dsaf_read_dev(rcb_com, RCB_COM_RCB_RD_BD_BUSY); + regs[34] = dsaf_read_dev(rcb_com, RCB_COM_RCB_FBD_CRT_EN); + regs[35] = dsaf_read_dev(rcb_com, RCB_COM_AXI_WR_ERR_INTMASK); + regs[36] = dsaf_read_dev(rcb_com, RCB_COM_AXI_ERR_STS); + regs[37] = dsaf_read_dev(rcb_com, RCB_COM_CHK_TX_FBD_NUM_REG); + + /* rcb common entry registers */ + for (i = 0; i < 16; i++) { /* total 16 model registers */ + regs[38 + i] + = dsaf_read_dev(rcb_com, RCB_CFG_BD_NUM_REG + 4 * i); + regs[54 + i] + = dsaf_read_dev(rcb_com, RCB_CFG_PKTLINE_REG + 4 * i); + } + + regs[70] = dsaf_read_dev(rcb_com, RCB_CFG_OVERTIME_REG); + regs[71] = dsaf_read_dev(rcb_com, RCB_CFG_PKTLINE_INT_NUM_REG); + regs[72] = dsaf_read_dev(rcb_com, RCB_CFG_OVERTIME_INT_NUM_REG); + + /* mark end of rcb common regs */ + for (i = 73; i < 80; i++) + regs[i] = 0xcccccccc; +} + +void hns_rcb_get_ring_regs(struct hnae_queue *queue, void *data) +{ + u32 *regs = data; + struct ring_pair_cb *ring_pair + = container_of(queue, struct ring_pair_cb, q); + u32 i = 0; + + /*rcb ring registers */ + regs[0] = dsaf_read_dev(queue, RCB_RING_RX_RING_BASEADDR_L_REG); + regs[1] = dsaf_read_dev(queue, RCB_RING_RX_RING_BASEADDR_H_REG); + regs[2] = dsaf_read_dev(queue, RCB_RING_RX_RING_BD_NUM_REG); + regs[3] = dsaf_read_dev(queue, RCB_RING_RX_RING_BD_LEN_REG); + regs[4] = dsaf_read_dev(queue, RCB_RING_RX_RING_PKTLINE_REG); + regs[5] = dsaf_read_dev(queue, RCB_RING_RX_RING_TAIL_REG); + regs[6] = dsaf_read_dev(queue, RCB_RING_RX_RING_HEAD_REG); + regs[7] = dsaf_read_dev(queue, RCB_RING_RX_RING_FBDNUM_REG); + regs[8] = dsaf_read_dev(queue, RCB_RING_RX_RING_PKTNUM_RECORD_REG); + + regs[9] = dsaf_read_dev(queue, RCB_RING_TX_RING_BASEADDR_L_REG); + regs[10] = dsaf_read_dev(queue, RCB_RING_TX_RING_BASEADDR_H_REG); + regs[11] = dsaf_read_dev(queue, RCB_RING_TX_RING_BD_NUM_REG); + regs[12] = dsaf_read_dev(queue, RCB_RING_TX_RING_BD_LEN_REG); + regs[13] = dsaf_read_dev(queue, RCB_RING_TX_RING_PKTLINE_REG); + regs[15] = dsaf_read_dev(queue, RCB_RING_TX_RING_TAIL_REG); + regs[16] = dsaf_read_dev(queue, RCB_RING_TX_RING_HEAD_REG); + regs[17] = dsaf_read_dev(queue, RCB_RING_TX_RING_FBDNUM_REG); + regs[18] = dsaf_read_dev(queue, RCB_RING_TX_RING_OFFSET_REG); + regs[19] = dsaf_read_dev(queue, RCB_RING_TX_RING_PKTNUM_RECORD_REG); + + regs[20] = dsaf_read_dev(queue, RCB_RING_PREFETCH_EN_REG); + regs[21] = dsaf_read_dev(queue, RCB_RING_CFG_VF_NUM_REG); + regs[22] = dsaf_read_dev(queue, RCB_RING_ASID_REG); + regs[23] = dsaf_read_dev(queue, RCB_RING_RX_VM_REG); + regs[24] = dsaf_read_dev(queue, RCB_RING_T0_BE_RST); + regs[25] = dsaf_read_dev(queue, RCB_RING_COULD_BE_RST); + regs[26] = dsaf_read_dev(queue, RCB_RING_WRR_WEIGHT_REG); + + regs[27] = dsaf_read_dev(queue, RCB_RING_INTMSK_RXWL_REG); + regs[28] = dsaf_read_dev(queue, RCB_RING_INTSTS_RX_RING_REG); + regs[29] = dsaf_read_dev(queue, RCB_RING_INTMSK_TXWL_REG); + regs[30] = dsaf_read_dev(queue, RCB_RING_INTSTS_TX_RING_REG); + regs[31] = dsaf_read_dev(queue, RCB_RING_INTMSK_RX_OVERTIME_REG); + regs[32] = dsaf_read_dev(queue, RCB_RING_INTSTS_RX_OVERTIME_REG); + regs[33] = dsaf_read_dev(queue, RCB_RING_INTMSK_TX_OVERTIME_REG); + regs[34] = dsaf_read_dev(queue, RCB_RING_INTSTS_TX_OVERTIME_REG); + + /* mark end of ring regs */ + for (i = 35; i < 40; i++) + regs[i] = 0xcccccc00 + ring_pair->index; +} diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h new file mode 100644 index 000000000000..c7db6130a3cf --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _HNS_DSAF_RCB_H +#define _HNS_DSAF_RCB_H + +#include +#include + +#include "hnae.h" +#include "hns_dsaf_main.h" + +struct rcb_common_cb; + +#define HNS_RCB_IRQ_NUM_PER_QUEUE 2 +#define HNS_RCB_IRQ_IDX_TX 0 +#define HNS_RCB_IRQ_IDX_RX 1 +#define HNS_RCB_TX_REG_OFFSET 0x40 + +#define HNS_RCB_SERVICE_NW_ENGINE_NUM DSAF_COMM_CHN +#define HNS_RCB_DEBUG_NW_ENGINE_NUM 1 +#define HNS_RCB_RING_MAX_BD_PER_PKT 3 +#define HNS_RCB_MAX_PKT_SIZE MAC_MAX_MTU + +#define HNS_RCB_RING_MAX_PENDING_BD 1024 +#define HNS_RCB_RING_MIN_PENDING_BD 16 + +#define HNS_RCB_REG_OFFSET 0x10000 + +#define HNS_RCB_MAX_COALESCED_FRAMES 1023 +#define HNS_RCB_MIN_COALESCED_FRAMES 1 +#define HNS_RCB_DEF_COALESCED_FRAMES 50 +#define HNS_RCB_MAX_TIME_OUT 0x500 + +#define HNS_RCB_COMMON_ENDIAN 1 + +#define HNS_BD_SIZE_512_TYPE 0 +#define HNS_BD_SIZE_1024_TYPE 1 +#define HNS_BD_SIZE_2048_TYPE 2 +#define HNS_BD_SIZE_4096_TYPE 3 + +#define HNS_RCB_COMMON_DUMP_REG_NUM 80 +#define HNS_RCB_RING_DUMP_REG_NUM 40 +#define HNS_RING_STATIC_REG_NUM 28 + +#define HNS_DUMP_REG_NUM 500 +#define HNS_STATIC_REG_NUM 12 + +enum rcb_int_flag { + RCB_INT_FLAG_TX = 0x1, + RCB_INT_FLAG_RX = (0x1 << 1), + RCB_INT_FLAG_MAX = (0x1 << 2), /*must be the last element */ +}; + +struct hns_ring_hw_stats { + u64 tx_pkts; + u64 ppe_tx_ok_pkts; + u64 ppe_tx_drop_pkts; + u64 rx_pkts; + u64 ppe_rx_ok_pkts; + u64 ppe_rx_drop_pkts; +}; + +struct ring_pair_cb { + struct rcb_common_cb *rcb_common; /* ring belongs to */ + struct device *dev; /*device for DMA mapping */ + struct hnae_queue q; + + u16 index; /* global index in a rcb common device */ + u16 buf_size; + + int virq[HNS_RCB_IRQ_NUM_PER_QUEUE]; + + u8 port_id_in_dsa; + u8 used_by_vf; + + struct hns_ring_hw_stats hw_stats; +}; + +struct rcb_common_cb { + u8 __iomem *io_base; + phys_addr_t phy_base; + struct dsaf_device *dsaf_dev; + u16 max_vfn; + u16 max_q_per_vf; + + u8 comm_index; + u32 ring_num; + u32 coalesced_frames; /* frames threshold of rx interrupt */ + u32 timeout; /* time threshold of rx interrupt */ + u32 desc_num; /* desc num per queue*/ + + struct ring_pair_cb ring_pair_cb[0]; +}; + +int hns_rcb_buf_size2type(u32 buf_size); + +int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev, int comm_index); +void hns_rcb_common_free_cfg(struct dsaf_device *dsaf_dev, u32 comm_index); +int hns_rcb_common_init_hw(struct rcb_common_cb *rcb_common); +void hns_rcb_start(struct hnae_queue *q, u32 val); +void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common); +void hns_rcb_common_init_commit_hw(struct rcb_common_cb *rcb_common); + +void hns_rcb_ring_enable_hw(struct hnae_queue *q, u32 val); +void hns_rcb_int_clr_hw(struct hnae_queue *q, u32 flag); +void hns_rcb_int_ctrl_hw(struct hnae_queue *q, u32 flag, u32 enable); +void hns_rcb_init_hw(struct ring_pair_cb *ring); +void hns_rcb_reset_ring_hw(struct hnae_queue *q); +void hns_rcb_wait_fbd_clean(struct hnae_queue **qs, int q_num, u32 flag); + +u32 hns_rcb_get_coalesced_frames(struct dsaf_device *dsaf_dev, int comm_index); +u32 hns_rcb_get_coalesce_usecs(struct dsaf_device *dsaf_dev, int comm_index); +void hns_rcb_set_coalesce_usecs(struct dsaf_device *dsaf_dev, + int comm_index, u32 timeout); +int hns_rcb_set_coalesced_frames(struct dsaf_device *dsaf_dev, + int comm_index, u32 coalesce_frames); +void hns_rcb_update_stats(struct hnae_queue *queue); + +void hns_rcb_get_stats(struct hnae_queue *queue, u64 *data); + +void hns_rcb_get_common_regs(struct rcb_common_cb *rcb_common, void *data); + +int hns_rcb_get_ring_sset_count(int stringset); +int hns_rcb_get_common_regs_count(void); +int hns_rcb_get_ring_regs_count(void); + +void hns_rcb_get_ring_regs(struct hnae_queue *queue, void *data); + +void hns_rcb_get_strings(int stringset, u8 *data, int index); +#endif /* _HNS_DSAF_RCB_H */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h new file mode 100644 index 000000000000..6fc58ba01f87 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -0,0 +1,972 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _DSAF_REG_H_ +#define _DSAF_REG_H_ + +#define HNS_GE_FIFO_ERR_INTNUM 8 +#define HNS_XGE_ERR_INTNUM 6 +#define HNS_RCB_COMM_ERR_INTNUM 12 +#define HNS_PPE_TNL_ERR_INTNUM 8 +#define HNS_DSAF_EVENT_INTNUM 21 +#define HNS_DEBUG_RING_INTNUM 4 +#define HNS_SERVICE_RING_INTNUM 256 + +#define HNS_DEBUG_RING_IRQ_IDX (HNS_GE_FIFO_ERR_INTNUM + HNS_XGE_ERR_INTNUM +\ + HNS_RCB_COMM_ERR_INTNUM + HNS_PPE_TNL_ERR_INTNUM +\ + HNS_DSAF_EVENT_INTNUM) +#define HNS_SERVICE_RING_IRQ_IDX (HNS_DEBUG_RING_IRQ_IDX +\ + HNS_DEBUG_RING_INTNUM) + +#define DSAF_IRQ_NUM 18 + +#define DSAF_MAX_PORT_NUM_PER_CHIP 8 +#define DSAF_SERVICE_PORT_NUM_PER_DSAF 6 +#define DSAF_MAX_VM_NUM 128 + +#define DSAF_COMM_DEV_NUM 3 +#define DSAF_PPE_INODE_BASE 6 +#define HNS_DSAF_COMM_SERVICE_NW_IDX 0 +#define DSAF_DEBUG_NW_NUM 2 +#define DSAF_SERVICE_NW_NUM 6 +#define DSAF_COMM_CHN DSAF_SERVICE_NW_NUM +#define DSAF_GE_NUM ((DSAF_SERVICE_NW_NUM) + (DSAF_DEBUG_NW_NUM)) +#define DSAF_PORT_NUM ((DSAF_SERVICE_NW_NUM) + (DSAF_DEBUG_NW_NUM)) +#define DSAF_XGE_NUM DSAF_SERVICE_NW_NUM +#define DSAF_NODE_NUM 18 +#define DSAF_XOD_BIG_NUM DSAF_NODE_NUM +#define DSAF_SBM_NUM DSAF_NODE_NUM +#define DSAF_VOQ_NUM DSAF_NODE_NUM +#define DSAF_INODE_NUM DSAF_NODE_NUM +#define DSAF_XOD_NUM 8 +#define DSAF_TBL_NUM 8 +#define DSAF_SW_PORT_NUM 8 +#define DSAF_TOTAL_QUEUE_NUM 129 + +#define DSAF_TCAM_SUM 512 +#define DSAF_LINE_SUM (2048 * 14) + +#define DSAF_SUB_SC_NT_SRAM_CLK_SEL_REG 0x100 +#define DSAF_SUB_SC_HILINK3_CRG_CTRL0_REG 0x180 +#define DSAF_SUB_SC_HILINK3_CRG_CTRL1_REG 0x184 +#define DSAF_SUB_SC_HILINK3_CRG_CTRL2_REG 0x188 +#define DSAF_SUB_SC_HILINK3_CRG_CTRL3_REG 0x18C +#define DSAF_SUB_SC_HILINK4_CRG_CTRL0_REG 0x190 +#define DSAF_SUB_SC_HILINK4_CRG_CTRL1_REG 0x194 +#define DSAF_SUB_SC_DSAF_CLK_EN_REG 0x300 +#define DSAF_SUB_SC_DSAF_CLK_DIS_REG 0x304 +#define DSAF_SUB_SC_NT_CLK_EN_REG 0x308 +#define DSAF_SUB_SC_NT_CLK_DIS_REG 0x30C +#define DSAF_SUB_SC_XGE_CLK_EN_REG 0x310 +#define DSAF_SUB_SC_XGE_CLK_DIS_REG 0x314 +#define DSAF_SUB_SC_GE_CLK_EN_REG 0x318 +#define DSAF_SUB_SC_GE_CLK_DIS_REG 0x31C +#define DSAF_SUB_SC_PPE_CLK_EN_REG 0x320 +#define DSAF_SUB_SC_PPE_CLK_DIS_REG 0x324 +#define DSAF_SUB_SC_RCB_PPE_COM_CLK_EN_REG 0x350 +#define DSAF_SUB_SC_RCB_PPE_COM_CLK_DIS_REG 0x354 +#define DSAF_SUB_SC_XBAR_RESET_REQ_REG 0xA00 +#define DSAF_SUB_SC_XBAR_RESET_DREQ_REG 0xA04 +#define DSAF_SUB_SC_NT_RESET_REQ_REG 0xA08 +#define DSAF_SUB_SC_NT_RESET_DREQ_REG 0xA0C +#define DSAF_SUB_SC_XGE_RESET_REQ_REG 0xA10 +#define DSAF_SUB_SC_XGE_RESET_DREQ_REG 0xA14 +#define DSAF_SUB_SC_GE_RESET_REQ0_REG 0xA18 +#define DSAF_SUB_SC_GE_RESET_DREQ0_REG 0xA1C +#define DSAF_SUB_SC_GE_RESET_REQ1_REG 0xA20 +#define DSAF_SUB_SC_GE_RESET_DREQ1_REG 0xA24 +#define DSAF_SUB_SC_PPE_RESET_REQ_REG 0xA48 +#define DSAF_SUB_SC_PPE_RESET_DREQ_REG 0xA4C +#define DSAF_SUB_SC_RCB_PPE_COM_RESET_REQ_REG 0xA88 +#define DSAF_SUB_SC_RCB_PPE_COM_RESET_DREQ_REG 0xA8C +#define DSAF_SUB_SC_LIGHT_MODULE_DETECT_EN_REG 0x2060 +#define DSAF_SUB_SC_TCAM_MBIST_EN_REG 0x2300 +#define DSAF_SUB_SC_DSAF_CLK_ST_REG 0x5300 +#define DSAF_SUB_SC_NT_CLK_ST_REG 0x5304 +#define DSAF_SUB_SC_XGE_CLK_ST_REG 0x5308 +#define DSAF_SUB_SC_GE_CLK_ST_REG 0x530C +#define DSAF_SUB_SC_PPE_CLK_ST_REG 0x5310 +#define DSAF_SUB_SC_ROCEE_CLK_ST_REG 0x5314 +#define DSAF_SUB_SC_CPU_CLK_ST_REG 0x5318 +#define DSAF_SUB_SC_RCB_PPE_COM_CLK_ST_REG 0x5328 +#define DSAF_SUB_SC_XBAR_RESET_ST_REG 0x5A00 +#define DSAF_SUB_SC_NT_RESET_ST_REG 0x5A04 +#define DSAF_SUB_SC_XGE_RESET_ST_REG 0x5A08 +#define DSAF_SUB_SC_GE_RESET_ST0_REG 0x5A0C +#define DSAF_SUB_SC_GE_RESET_ST1_REG 0x5A10 +#define DSAF_SUB_SC_PPE_RESET_ST_REG 0x5A24 +#define DSAF_SUB_SC_RCB_PPE_COM_RESET_ST_REG 0x5A44 + +/*serdes offset**/ +#define HNS_MAC_HILINK3_REG DSAF_SUB_SC_HILINK3_CRG_CTRL0_REG +#define HNS_MAC_HILINK4_REG DSAF_SUB_SC_HILINK4_CRG_CTRL0_REG +#define HNS_MAC_LANE0_CTLEDFE_REG 0x000BFFCCULL +#define HNS_MAC_LANE1_CTLEDFE_REG 0x000BFFBCULL +#define HNS_MAC_LANE2_CTLEDFE_REG 0x000BFFACULL +#define HNS_MAC_LANE3_CTLEDFE_REG 0x000BFF9CULL +#define HNS_MAC_LANE0_STATE_REG 0x000BFFD4ULL +#define HNS_MAC_LANE1_STATE_REG 0x000BFFC4ULL +#define HNS_MAC_LANE2_STATE_REG 0x000BFFB4ULL +#define HNS_MAC_LANE3_STATE_REG 0x000BFFA4ULL + +#define HILINK_RESET_TIMOUT 10000 + +#define DSAF_SRAM_INIT_OVER_0_REG 0x0 +#define DSAF_CFG_0_REG 0x4 +#define DSAF_ECC_ERR_INVERT_0_REG 0x8 +#define DSAF_ABNORMAL_TIMEOUT_0_REG 0x1C +#define DSAF_FSM_TIMEOUT_0_REG 0x20 +#define DSAF_DSA_REG_CNT_CLR_CE_REG 0x2C +#define DSAF_DSA_SBM_INF_FIFO_THRD_REG 0x30 +#define DSAF_DSA_SRAM_1BIT_ECC_SEL_REG 0x34 +#define DSAF_DSA_SRAM_1BIT_ECC_CNT_REG 0x38 +#define DSAF_PFC_EN_0_REG 0x50 +#define DSAF_PFC_UNIT_CNT_0_REG 0x70 +#define DSAF_XGE_INT_MSK_0_REG 0x100 +#define DSAF_PPE_INT_MSK_0_REG 0x120 +#define DSAF_ROCEE_INT_MSK_0_REG 0x140 +#define DSAF_XGE_INT_SRC_0_REG 0x160 +#define DSAF_PPE_INT_SRC_0_REG 0x180 +#define DSAF_ROCEE_INT_SRC_0_REG 0x1A0 +#define DSAF_XGE_INT_STS_0_REG 0x1C0 +#define DSAF_PPE_INT_STS_0_REG 0x1E0 +#define DSAF_ROCEE_INT_STS_0_REG 0x200 +#define DSAF_PPE_QID_CFG_0_REG 0x300 +#define DSAF_SW_PORT_TYPE_0_REG 0x320 +#define DSAF_STP_PORT_TYPE_0_REG 0x340 +#define DSAF_MIX_DEF_QID_0_REG 0x360 +#define DSAF_PORT_DEF_VLAN_0_REG 0x380 +#define DSAF_VM_DEF_VLAN_0_REG 0x400 + +#define DSAF_INODE_CUT_THROUGH_CFG_0_REG 0x1000 +#define DSAF_INODE_ECC_INVERT_EN_0_REG 0x1008 +#define DSAF_INODE_ECC_ERR_ADDR_0_REG 0x100C +#define DSAF_INODE_IN_PORT_NUM_0_REG 0x1018 +#define DSAF_INODE_PRI_TC_CFG_0_REG 0x101C +#define DSAF_INODE_BP_STATUS_0_REG 0x1020 +#define DSAF_INODE_PAD_DISCARD_NUM_0_REG 0x1028 +#define DSAF_INODE_FINAL_IN_MAN_NUM_0_REG 0x102C +#define DSAF_INODE_FINAL_IN_PKT_NUM_0_REG 0x1030 +#define DSAF_INODE_SBM_PID_NUM_0_REG 0x1038 +#define DSAF_INODE_FINAL_IN_PAUSE_NUM_0_REG 0x103C +#define DSAF_INODE_SBM_RELS_NUM_0_REG 0x104C +#define DSAF_INODE_SBM_DROP_NUM_0_REG 0x1050 +#define DSAF_INODE_CRC_FALSE_NUM_0_REG 0x1054 +#define DSAF_INODE_BP_DISCARD_NUM_0_REG 0x1058 +#define DSAF_INODE_RSLT_DISCARD_NUM_0_REG 0x105C +#define DSAF_INODE_LOCAL_ADDR_FALSE_NUM_0_REG 0x1060 +#define DSAF_INODE_VOQ_OVER_NUM_0_REG 0x1068 +#define DSAF_INODE_BD_SAVE_STATUS_0_REG 0x1900 +#define DSAF_INODE_BD_ORDER_STATUS_0_REG 0x1950 +#define DSAF_INODE_SW_VLAN_TAG_DISC_0_REG 0x1A00 +#define DSAF_INODE_IN_DATA_STP_DISC_0_REG 0x1A50 +#define DSAF_INODE_GE_FC_EN_0_REG 0x1B00 +#define DSAF_INODE_VC0_IN_PKT_NUM_0_REG 0x1B50 +#define DSAF_INODE_VC1_IN_PKT_NUM_0_REG 0x1C00 + +#define DSAF_SBM_CFG_REG_0_REG 0x2000 +#define DSAF_SBM_BP_CFG_0_XGE_REG_0_REG 0x2004 +#define DSAF_SBM_BP_CFG_0_PPE_REG_0_REG 0x2304 +#define DSAF_SBM_BP_CFG_0_ROCEE_REG_0_REG 0x2604 +#define DSAF_SBM_BP_CFG_1_REG_0_REG 0x2008 +#define DSAF_SBM_BP_CFG_2_XGE_REG_0_REG 0x200C +#define DSAF_SBM_BP_CFG_2_PPE_REG_0_REG 0x230C +#define DSAF_SBM_BP_CFG_2_ROCEE_REG_0_REG 0x260C +#define DSAF_SBM_FREE_CNT_0_0_REG 0x2010 +#define DSAF_SBM_FREE_CNT_1_0_REG 0x2014 +#define DSAF_SBM_BP_CNT_0_0_REG 0x2018 +#define DSAF_SBM_BP_CNT_1_0_REG 0x201C +#define DSAF_SBM_BP_CNT_2_0_REG 0x2020 +#define DSAF_SBM_BP_CNT_3_0_REG 0x2024 +#define DSAF_SBM_INER_ST_0_REG 0x2028 +#define DSAF_SBM_MIB_REQ_FAILED_TC_0_REG 0x202C +#define DSAF_SBM_LNK_INPORT_CNT_0_REG 0x2030 +#define DSAF_SBM_LNK_DROP_CNT_0_REG 0x2034 +#define DSAF_SBM_INF_OUTPORT_CNT_0_REG 0x2038 +#define DSAF_SBM_LNK_INPORT_TC0_CNT_0_REG 0x203C +#define DSAF_SBM_LNK_INPORT_TC1_CNT_0_REG 0x2040 +#define DSAF_SBM_LNK_INPORT_TC2_CNT_0_REG 0x2044 +#define DSAF_SBM_LNK_INPORT_TC3_CNT_0_REG 0x2048 +#define DSAF_SBM_LNK_INPORT_TC4_CNT_0_REG 0x204C +#define DSAF_SBM_LNK_INPORT_TC5_CNT_0_REG 0x2050 +#define DSAF_SBM_LNK_INPORT_TC6_CNT_0_REG 0x2054 +#define DSAF_SBM_LNK_INPORT_TC7_CNT_0_REG 0x2058 +#define DSAF_SBM_LNK_REQ_CNT_0_REG 0x205C +#define DSAF_SBM_LNK_RELS_CNT_0_REG 0x2060 +#define DSAF_SBM_BP_CFG_3_REG_0_REG 0x2068 +#define DSAF_SBM_BP_CFG_4_REG_0_REG 0x206C + +#define DSAF_XOD_ETS_TSA_TC0_TC3_CFG_0_REG 0x3000 +#define DSAF_XOD_ETS_TSA_TC4_TC7_CFG_0_REG 0x3004 +#define DSAF_XOD_ETS_BW_TC0_TC3_CFG_0_REG 0x3008 +#define DSAF_XOD_ETS_BW_TC4_TC7_CFG_0_REG 0x300C +#define DSAF_XOD_ETS_BW_OFFSET_CFG_0_REG 0x3010 +#define DSAF_XOD_ETS_TOKEN_CFG_0_REG 0x3014 +#define DSAF_XOD_PFS_CFG_0_0_REG 0x3018 +#define DSAF_XOD_PFS_CFG_1_0_REG 0x301C +#define DSAF_XOD_PFS_CFG_2_0_REG 0x3020 +#define DSAF_XOD_GNT_L_0_REG 0x3024 +#define DSAF_XOD_GNT_H_0_REG 0x3028 +#define DSAF_XOD_CONNECT_STATE_0_REG 0x302C +#define DSAF_XOD_RCVPKT_CNT_0_REG 0x3030 +#define DSAF_XOD_RCVTC0_CNT_0_REG 0x3034 +#define DSAF_XOD_RCVTC1_CNT_0_REG 0x3038 +#define DSAF_XOD_RCVTC2_CNT_0_REG 0x303C +#define DSAF_XOD_RCVTC3_CNT_0_REG 0x3040 +#define DSAF_XOD_RCVVC0_CNT_0_REG 0x3044 +#define DSAF_XOD_RCVVC1_CNT_0_REG 0x3048 +#define DSAF_XOD_XGE_RCVIN0_CNT_0_REG 0x304C +#define DSAF_XOD_XGE_RCVIN1_CNT_0_REG 0x3050 +#define DSAF_XOD_XGE_RCVIN2_CNT_0_REG 0x3054 +#define DSAF_XOD_XGE_RCVIN3_CNT_0_REG 0x3058 +#define DSAF_XOD_XGE_RCVIN4_CNT_0_REG 0x305C +#define DSAF_XOD_XGE_RCVIN5_CNT_0_REG 0x3060 +#define DSAF_XOD_XGE_RCVIN6_CNT_0_REG 0x3064 +#define DSAF_XOD_XGE_RCVIN7_CNT_0_REG 0x3068 +#define DSAF_XOD_PPE_RCVIN0_CNT_0_REG 0x306C +#define DSAF_XOD_PPE_RCVIN1_CNT_0_REG 0x3070 +#define DSAF_XOD_ROCEE_RCVIN0_CNT_0_REG 0x3074 +#define DSAF_XOD_ROCEE_RCVIN1_CNT_0_REG 0x3078 +#define DSAF_XOD_FIFO_STATUS_0_REG 0x307C + +#define DSAF_VOQ_ECC_INVERT_EN_0_REG 0x4004 +#define DSAF_VOQ_SRAM_PKT_NUM_0_REG 0x4008 +#define DSAF_VOQ_IN_PKT_NUM_0_REG 0x400C +#define DSAF_VOQ_OUT_PKT_NUM_0_REG 0x4010 +#define DSAF_VOQ_ECC_ERR_ADDR_0_REG 0x4014 +#define DSAF_VOQ_BP_STATUS_0_REG 0x4018 +#define DSAF_VOQ_SPUP_IDLE_0_REG 0x401C +#define DSAF_VOQ_XGE_XOD_REQ_0_0_REG 0x4024 +#define DSAF_VOQ_XGE_XOD_REQ_1_0_REG 0x4028 +#define DSAF_VOQ_PPE_XOD_REQ_0_REG 0x402C +#define DSAF_VOQ_ROCEE_XOD_REQ_0_REG 0x4030 +#define DSAF_VOQ_BP_ALL_THRD_0_REG 0x4034 + +#define DSAF_TBL_CTRL_0_REG 0x5000 +#define DSAF_TBL_INT_MSK_0_REG 0x5004 +#define DSAF_TBL_INT_SRC_0_REG 0x5008 +#define DSAF_TBL_INT_STS_0_REG 0x5100 +#define DSAF_TBL_TCAM_ADDR_0_REG 0x500C +#define DSAF_TBL_LINE_ADDR_0_REG 0x5010 +#define DSAF_TBL_TCAM_HIGH_0_REG 0x5014 +#define DSAF_TBL_TCAM_LOW_0_REG 0x5018 +#define DSAF_TBL_TCAM_MCAST_CFG_4_0_REG 0x501C +#define DSAF_TBL_TCAM_MCAST_CFG_3_0_REG 0x5020 +#define DSAF_TBL_TCAM_MCAST_CFG_2_0_REG 0x5024 +#define DSAF_TBL_TCAM_MCAST_CFG_1_0_REG 0x5028 +#define DSAF_TBL_TCAM_MCAST_CFG_0_0_REG 0x502C +#define DSAF_TBL_TCAM_UCAST_CFG_0_REG 0x5030 +#define DSAF_TBL_LIN_CFG_0_REG 0x5034 +#define DSAF_TBL_TCAM_RDATA_HIGH_0_REG 0x5038 +#define DSAF_TBL_TCAM_RDATA_LOW_0_REG 0x503C +#define DSAF_TBL_TCAM_RAM_RDATA4_0_REG 0x5040 +#define DSAF_TBL_TCAM_RAM_RDATA3_0_REG 0x5044 +#define DSAF_TBL_TCAM_RAM_RDATA2_0_REG 0x5048 +#define DSAF_TBL_TCAM_RAM_RDATA1_0_REG 0x504C +#define DSAF_TBL_TCAM_RAM_RDATA0_0_REG 0x5050 +#define DSAF_TBL_LIN_RDATA_0_REG 0x5054 +#define DSAF_TBL_DA0_MIS_INFO1_0_REG 0x5058 +#define DSAF_TBL_DA0_MIS_INFO0_0_REG 0x505C +#define DSAF_TBL_SA_MIS_INFO2_0_REG 0x5104 +#define DSAF_TBL_SA_MIS_INFO1_0_REG 0x5098 +#define DSAF_TBL_SA_MIS_INFO0_0_REG 0x509C +#define DSAF_TBL_PUL_0_REG 0x50A0 +#define DSAF_TBL_OLD_RSLT_0_REG 0x50A4 +#define DSAF_TBL_OLD_SCAN_VAL_0_REG 0x50A8 +#define DSAF_TBL_DFX_CTRL_0_REG 0x50AC +#define DSAF_TBL_DFX_STAT_0_REG 0x50B0 +#define DSAF_TBL_DFX_STAT_2_0_REG 0x5108 +#define DSAF_TBL_LKUP_NUM_I_0_REG 0x50C0 +#define DSAF_TBL_LKUP_NUM_O_0_REG 0x50E0 +#define DSAF_TBL_UCAST_BCAST_MIS_INFO_0_0_REG 0x510C + +#define DSAF_INODE_FIFO_WL_0_REG 0x6000 +#define DSAF_ONODE_FIFO_WL_0_REG 0x6020 +#define DSAF_XGE_GE_WORK_MODE_0_REG 0x6040 +#define DSAF_XGE_APP_RX_LINK_UP_0_REG 0x6080 +#define DSAF_NETPORT_CTRL_SIG_0_REG 0x60A0 +#define DSAF_XGE_CTRL_SIG_CFG_0_REG 0x60C0 + +#define PPE_COM_CFG_QID_MODE_REG 0x0 +#define PPE_COM_INTEN_REG 0x110 +#define PPE_COM_RINT_REG 0x114 +#define PPE_COM_INTSTS_REG 0x118 +#define PPE_COM_COMMON_CNT_CLR_CE_REG 0x1120 +#define PPE_COM_HIS_RX_PKT_QID_DROP_CNT_REG 0x300 +#define PPE_COM_HIS_RX_PKT_QID_OK_CNT_REG 0x600 +#define PPE_COM_HIS_TX_PKT_QID_ERR_CNT_REG 0x900 +#define PPE_COM_HIS_TX_PKT_QID_OK_CNT_REG 0xC00 +#define PPE_COM_COMMON_CNT_CLR_CE_REG 0x1120 + +#define PPE_CFG_TX_FIFO_THRSLD_REG 0x0 +#define PPE_CFG_RX_FIFO_THRSLD_REG 0x4 +#define PPE_CFG_RX_FIFO_PAUSE_THRSLD_REG 0x8 +#define PPE_CFG_RX_FIFO_SW_BP_THRSLD_REG 0xC +#define PPE_CFG_PAUSE_IDLE_CNT_REG 0x10 +#define PPE_CFG_BUS_CTRL_REG 0x40 +#define PPE_CFG_TNL_TO_BE_RST_REG 0x48 +#define PPE_CURR_TNL_CAN_RST_REG 0x4C +#define PPE_CFG_XGE_MODE_REG 0x80 +#define PPE_CFG_MAX_FRAME_LEN_REG 0x84 +#define PPE_CFG_RX_PKT_MODE_REG 0x88 +#define PPE_CFG_RX_VLAN_TAG_REG 0x8C +#define PPE_CFG_TAG_GEN_REG 0x90 +#define PPE_CFG_PARSE_TAG_REG 0x94 +#define PPE_CFG_PRO_CHECK_EN_REG 0x98 +#define PPE_INTEN_REG 0x100 +#define PPE_RINT_REG 0x104 +#define PPE_INTSTS_REG 0x108 +#define PPE_CFG_RX_PKT_INT_REG 0x140 +#define PPE_CFG_HEAT_DECT_TIME0_REG 0x144 +#define PPE_CFG_HEAT_DECT_TIME1_REG 0x148 +#define PPE_HIS_RX_SW_PKT_CNT_REG 0x200 +#define PPE_HIS_RX_WR_BD_OK_PKT_CNT_REG 0x204 +#define PPE_HIS_RX_PKT_NO_BUF_CNT_REG 0x208 +#define PPE_HIS_TX_BD_CNT_REG 0x20C +#define PPE_HIS_TX_PKT_CNT_REG 0x210 +#define PPE_HIS_TX_PKT_OK_CNT_REG 0x214 +#define PPE_HIS_TX_PKT_EPT_CNT_REG 0x218 +#define PPE_HIS_TX_PKT_CS_FAIL_CNT_REG 0x21C +#define PPE_HIS_RX_APP_BUF_FAIL_CNT_REG 0x220 +#define PPE_HIS_RX_APP_BUF_WAIT_CNT_REG 0x224 +#define PPE_HIS_RX_PKT_DROP_FUL_CNT_REG 0x228 +#define PPE_HIS_RX_PKT_DROP_PRT_CNT_REG 0x22C +#define PPE_TNL_0_5_CNT_CLR_CE_REG 0x300 +#define PPE_CFG_AXI_DBG_REG 0x304 +#define PPE_HIS_PRO_ERR_REG 0x308 +#define PPE_HIS_TNL_FIFO_ERR_REG 0x30C +#define PPE_CURR_CFF_DATA_NUM_REG 0x310 +#define PPE_CURR_RX_ST_REG 0x314 +#define PPE_CURR_TX_ST_REG 0x318 +#define PPE_CURR_RX_FIFO0_REG 0x31C +#define PPE_CURR_RX_FIFO1_REG 0x320 +#define PPE_CURR_TX_FIFO0_REG 0x324 +#define PPE_CURR_TX_FIFO1_REG 0x328 +#define PPE_ECO0_REG 0x32C +#define PPE_ECO1_REG 0x330 +#define PPE_ECO2_REG 0x334 + +#define RCB_COM_CFG_ENDIAN_REG 0x0 +#define RCB_COM_CFG_SYS_FSH_REG 0xC +#define RCB_COM_CFG_INIT_FLAG_REG 0x10 +#define RCB_COM_CFG_PKT_REG 0x30 +#define RCB_COM_CFG_RINVLD_REG 0x34 +#define RCB_COM_CFG_FNA_REG 0x38 +#define RCB_COM_CFG_FA_REG 0x3C +#define RCB_COM_CFG_PKT_TC_BP_REG 0x40 +#define RCB_COM_CFG_PPE_TNL_CLKEN_REG 0x44 + +#define RCB_COM_INTMSK_TX_PKT_REG 0x3A0 +#define RCB_COM_RINT_TX_PKT_REG 0x3A8 +#define RCB_COM_INTMASK_ECC_ERR_REG 0x400 +#define RCB_COM_INTSTS_ECC_ERR_REG 0x408 +#define RCB_COM_EBD_SRAM_ERR_REG 0x410 +#define RCB_COM_RXRING_ERR_REG 0x41C +#define RCB_COM_TXRING_ERR_REG 0x420 +#define RCB_COM_TX_FBD_ERR_REG 0x424 +#define RCB_SRAM_ECC_CHK_EN_REG 0x428 +#define RCB_SRAM_ECC_CHK0_REG 0x42C +#define RCB_SRAM_ECC_CHK1_REG 0x430 +#define RCB_SRAM_ECC_CHK2_REG 0x434 +#define RCB_SRAM_ECC_CHK3_REG 0x438 +#define RCB_SRAM_ECC_CHK4_REG 0x43c +#define RCB_SRAM_ECC_CHK5_REG 0x440 +#define RCB_ECC_ERR_ADDR0_REG 0x450 +#define RCB_ECC_ERR_ADDR3_REG 0x45C +#define RCB_ECC_ERR_ADDR4_REG 0x460 +#define RCB_ECC_ERR_ADDR5_REG 0x464 + +#define RCB_COM_SF_CFG_INTMASK_RING 0x480 +#define RCB_COM_SF_CFG_RING_STS 0x484 +#define RCB_COM_SF_CFG_RING 0x488 +#define RCB_COM_SF_CFG_INTMASK_BD 0x48C +#define RCB_COM_SF_CFG_BD_RINT_STS 0x470 +#define RCB_COM_RCB_RD_BD_BUSY 0x490 +#define RCB_COM_RCB_FBD_CRT_EN 0x494 +#define RCB_COM_AXI_WR_ERR_INTMASK 0x498 +#define RCB_COM_AXI_ERR_STS 0x49C +#define RCB_COM_CHK_TX_FBD_NUM_REG 0x4a0 + +#define RCB_CFG_BD_NUM_REG 0x9000 +#define RCB_CFG_PKTLINE_REG 0x9050 + +#define RCB_CFG_OVERTIME_REG 0x9300 +#define RCB_CFG_PKTLINE_INT_NUM_REG 0x9304 +#define RCB_CFG_OVERTIME_INT_NUM_REG 0x9308 + +#define RCB_RING_RX_RING_BASEADDR_L_REG 0x00000 +#define RCB_RING_RX_RING_BASEADDR_H_REG 0x00004 +#define RCB_RING_RX_RING_BD_NUM_REG 0x00008 +#define RCB_RING_RX_RING_BD_LEN_REG 0x0000C +#define RCB_RING_RX_RING_PKTLINE_REG 0x00010 +#define RCB_RING_RX_RING_TAIL_REG 0x00018 +#define RCB_RING_RX_RING_HEAD_REG 0x0001C +#define RCB_RING_RX_RING_FBDNUM_REG 0x00020 +#define RCB_RING_RX_RING_PKTNUM_RECORD_REG 0x0002C + +#define RCB_RING_TX_RING_BASEADDR_L_REG 0x00040 +#define RCB_RING_TX_RING_BASEADDR_H_REG 0x00044 +#define RCB_RING_TX_RING_BD_NUM_REG 0x00048 +#define RCB_RING_TX_RING_BD_LEN_REG 0x0004C +#define RCB_RING_TX_RING_PKTLINE_REG 0x00050 +#define RCB_RING_TX_RING_TAIL_REG 0x00058 +#define RCB_RING_TX_RING_HEAD_REG 0x0005C +#define RCB_RING_TX_RING_FBDNUM_REG 0x00060 +#define RCB_RING_TX_RING_OFFSET_REG 0x00064 +#define RCB_RING_TX_RING_PKTNUM_RECORD_REG 0x0006C + +#define RCB_RING_PREFETCH_EN_REG 0x0007C +#define RCB_RING_CFG_VF_NUM_REG 0x00080 +#define RCB_RING_ASID_REG 0x0008C +#define RCB_RING_RX_VM_REG 0x00090 +#define RCB_RING_T0_BE_RST 0x00094 +#define RCB_RING_COULD_BE_RST 0x00098 +#define RCB_RING_WRR_WEIGHT_REG 0x0009c + +#define RCB_RING_INTMSK_RXWL_REG 0x000A0 +#define RCB_RING_INTSTS_RX_RING_REG 0x000A4 +#define RCB_RING_INTMSK_TXWL_REG 0x000AC +#define RCB_RING_INTSTS_TX_RING_REG 0x000B0 +#define RCB_RING_INTMSK_RX_OVERTIME_REG 0x000B8 +#define RCB_RING_INTSTS_RX_OVERTIME_REG 0x000BC +#define RCB_RING_INTMSK_TX_OVERTIME_REG 0x000C4 +#define RCB_RING_INTSTS_TX_OVERTIME_REG 0x000C8 + +#define GMAC_DUPLEX_TYPE_REG 0x0008UL +#define GMAC_FD_FC_TYPE_REG 0x000CUL +#define GMAC_FC_TX_TIMER_REG 0x001CUL +#define GMAC_FD_FC_ADDR_LOW_REG 0x0020UL +#define GMAC_FD_FC_ADDR_HIGH_REG 0x0024UL +#define GMAC_IPG_TX_TIMER_REG 0x0030UL +#define GMAC_PAUSE_THR_REG 0x0038UL +#define GMAC_MAX_FRM_SIZE_REG 0x003CUL +#define GMAC_PORT_MODE_REG 0x0040UL +#define GMAC_PORT_EN_REG 0x0044UL +#define GMAC_PAUSE_EN_REG 0x0048UL +#define GMAC_SHORT_RUNTS_THR_REG 0x0050UL +#define GMAC_AN_NEG_STATE_REG 0x0058UL +#define GMAC_TX_LOCAL_PAGE_REG 0x005CUL +#define GMAC_TRANSMIT_CONTROL_REG 0x0060UL +#define GMAC_REC_FILT_CONTROL_REG 0x0064UL +#define GMAC_PTP_CONFIG_REG 0x0074UL + +#define GMAC_RX_OCTETS_TOTAL_OK_REG 0x0080UL +#define GMAC_RX_OCTETS_BAD_REG 0x0084UL +#define GMAC_RX_UC_PKTS_REG 0x0088UL +#define GMAC_RX_MC_PKTS_REG 0x008CUL +#define GMAC_RX_BC_PKTS_REG 0x0090UL +#define GMAC_RX_PKTS_64OCTETS_REG 0x0094UL +#define GMAC_RX_PKTS_65TO127OCTETS_REG 0x0098UL +#define GMAC_RX_PKTS_128TO255OCTETS_REG 0x009CUL +#define GMAC_RX_PKTS_255TO511OCTETS_REG 0x00A0UL +#define GMAC_RX_PKTS_512TO1023OCTETS_REG 0x00A4UL +#define GMAC_RX_PKTS_1024TO1518OCTETS_REG 0x00A8UL +#define GMAC_RX_PKTS_1519TOMAXOCTETS_REG 0x00ACUL +#define GMAC_RX_FCS_ERRORS_REG 0x00B0UL +#define GMAC_RX_TAGGED_REG 0x00B4UL +#define GMAC_RX_DATA_ERR_REG 0x00B8UL +#define GMAC_RX_ALIGN_ERRORS_REG 0x00BCUL +#define GMAC_RX_LONG_ERRORS_REG 0x00C0UL +#define GMAC_RX_JABBER_ERRORS_REG 0x00C4UL +#define GMAC_RX_PAUSE_MACCTRL_FRAM_REG 0x00C8UL +#define GMAC_RX_UNKNOWN_MACCTRL_FRAM_REG 0x00CCUL +#define GMAC_RX_VERY_LONG_ERR_CNT_REG 0x00D0UL +#define GMAC_RX_RUNT_ERR_CNT_REG 0x00D4UL +#define GMAC_RX_SHORT_ERR_CNT_REG 0x00D8UL +#define GMAC_RX_FILT_PKT_CNT_REG 0x00E8UL +#define GMAC_RX_OCTETS_TOTAL_FILT_REG 0x00ECUL +#define GMAC_OCTETS_TRANSMITTED_OK_REG 0x0100UL +#define GMAC_OCTETS_TRANSMITTED_BAD_REG 0x0104UL +#define GMAC_TX_UC_PKTS_REG 0x0108UL +#define GMAC_TX_MC_PKTS_REG 0x010CUL +#define GMAC_TX_BC_PKTS_REG 0x0110UL +#define GMAC_TX_PKTS_64OCTETS_REG 0x0114UL +#define GMAC_TX_PKTS_65TO127OCTETS_REG 0x0118UL +#define GMAC_TX_PKTS_128TO255OCTETS_REG 0x011CUL +#define GMAC_TX_PKTS_255TO511OCTETS_REG 0x0120UL +#define GMAC_TX_PKTS_512TO1023OCTETS_REG 0x0124UL +#define GMAC_TX_PKTS_1024TO1518OCTETS_REG 0x0128UL +#define GMAC_TX_PKTS_1519TOMAXOCTETS_REG 0x012CUL +#define GMAC_TX_EXCESSIVE_LENGTH_DROP_REG 0x014CUL +#define GMAC_TX_UNDERRUN_REG 0x0150UL +#define GMAC_TX_TAGGED_REG 0x0154UL +#define GMAC_TX_CRC_ERROR_REG 0x0158UL +#define GMAC_TX_PAUSE_FRAMES_REG 0x015CUL +#define GAMC_RX_MAX_FRAME 0x0170UL +#define GMAC_LINE_LOOP_BACK_REG 0x01A8UL +#define GMAC_CF_CRC_STRIP_REG 0x01B0UL +#define GMAC_MODE_CHANGE_EN_REG 0x01B4UL +#define GMAC_SIXTEEN_BIT_CNTR_REG 0x01CCUL +#define GMAC_LD_LINK_COUNTER_REG 0x01D0UL +#define GMAC_LOOP_REG 0x01DCUL +#define GMAC_RECV_CONTROL_REG 0x01E0UL +#define GMAC_VLAN_CODE_REG 0x01E8UL +#define GMAC_RX_OVERRUN_CNT_REG 0x01ECUL +#define GMAC_RX_LENGTHFIELD_ERR_CNT_REG 0x01F4UL +#define GMAC_RX_FAIL_COMMA_CNT_REG 0x01F8UL +#define GMAC_STATION_ADDR_LOW_0_REG 0x0200UL +#define GMAC_STATION_ADDR_HIGH_0_REG 0x0204UL +#define GMAC_STATION_ADDR_LOW_1_REG 0x0208UL +#define GMAC_STATION_ADDR_HIGH_1_REG 0x020CUL +#define GMAC_STATION_ADDR_LOW_2_REG 0x0210UL +#define GMAC_STATION_ADDR_HIGH_2_REG 0x0214UL +#define GMAC_STATION_ADDR_LOW_3_REG 0x0218UL +#define GMAC_STATION_ADDR_HIGH_3_REG 0x021CUL +#define GMAC_STATION_ADDR_LOW_4_REG 0x0220UL +#define GMAC_STATION_ADDR_HIGH_4_REG 0x0224UL +#define GMAC_STATION_ADDR_LOW_5_REG 0x0228UL +#define GMAC_STATION_ADDR_HIGH_5_REG 0x022CUL +#define GMAC_STATION_ADDR_LOW_MSK_0_REG 0x0230UL +#define GMAC_STATION_ADDR_HIGH_MSK_0_REG 0x0234UL +#define GMAC_STATION_ADDR_LOW_MSK_1_REG 0x0238UL +#define GMAC_STATION_ADDR_HIGH_MSK_1_REG 0x023CUL +#define GMAC_MAC_SKIP_LEN_REG 0x0240UL +#define GMAC_TX_LOOP_PKT_PRI_REG 0x0378UL + +#define XGMAC_INT_STATUS_REG 0x0 +#define XGMAC_INT_ENABLE_REG 0x4 +#define XGMAC_INT_SET_REG 0x8 +#define XGMAC_IERR_U_INFO_REG 0xC +#define XGMAC_OVF_INFO_REG 0x10 +#define XGMAC_OVF_CNT_REG 0x14 +#define XGMAC_PORT_MODE_REG 0x40 +#define XGMAC_CLK_ENABLE_REG 0x44 +#define XGMAC_RESET_REG 0x48 +#define XGMAC_LINK_CONTROL_REG 0x50 +#define XGMAC_LINK_STATUS_REG 0x54 +#define XGMAC_SPARE_REG 0xC0 +#define XGMAC_SPARE_CNT_REG 0xC4 + +#define XGMAC_MAC_ENABLE_REG 0x100 +#define XGMAC_MAC_CONTROL_REG 0x104 +#define XGMAC_MAC_IPG_REG 0x120 +#define XGMAC_MAC_MSG_CRC_EN_REG 0x124 +#define XGMAC_MAC_MSG_IMG_REG 0x128 +#define XGMAC_MAC_MSG_FC_CFG_REG 0x12C +#define XGMAC_MAC_MSG_TC_CFG_REG 0x130 +#define XGMAC_MAC_PAD_SIZE_REG 0x134 +#define XGMAC_MAC_MIN_PKT_SIZE_REG 0x138 +#define XGMAC_MAC_MAX_PKT_SIZE_REG 0x13C +#define XGMAC_MAC_PAUSE_CTRL_REG 0x160 +#define XGMAC_MAC_PAUSE_TIME_REG 0x164 +#define XGMAC_MAC_PAUSE_GAP_REG 0x168 +#define XGMAC_MAC_PAUSE_LOCAL_MAC_H_REG 0x16C +#define XGMAC_MAC_PAUSE_LOCAL_MAC_L_REG 0x170 +#define XGMAC_MAC_PAUSE_PEER_MAC_H_REG 0x174 +#define XGMAC_MAC_PAUSE_PEER_MAC_L_REG 0x178 +#define XGMAC_MAC_PFC_PRI_EN_REG 0x17C +#define XGMAC_MAC_1588_CTRL_REG 0x180 +#define XGMAC_MAC_1588_TX_PORT_DLY_REG 0x184 +#define XGMAC_MAC_1588_RX_PORT_DLY_REG 0x188 +#define XGMAC_MAC_1588_ASYM_DLY_REG 0x18C +#define XGMAC_MAC_1588_ADJUST_CFG_REG 0x190 +#define XGMAC_MAC_Y1731_ETH_TYPE_REG 0x194 +#define XGMAC_MAC_MIB_CONTROL_REG 0x198 +#define XGMAC_MAC_WAN_RATE_ADJUST_REG 0x19C +#define XGMAC_MAC_TX_ERR_MARK_REG 0x1A0 +#define XGMAC_MAC_TX_LF_RF_CONTROL_REG 0x1A4 +#define XGMAC_MAC_RX_LF_RF_STATUS_REG 0x1A8 +#define XGMAC_MAC_TX_RUNT_PKT_CNT_REG 0x1C0 +#define XGMAC_MAC_RX_RUNT_PKT_CNT_REG 0x1C4 +#define XGMAC_MAC_RX_PREAM_ERR_PKT_CNT_REG 0x1C8 +#define XGMAC_MAC_TX_LF_RF_TERM_PKT_CNT_REG 0x1CC +#define XGMAC_MAC_TX_SN_MISMATCH_PKT_CNT_REG 0x1D0 +#define XGMAC_MAC_RX_ERR_MSG_CNT_REG 0x1D4 +#define XGMAC_MAC_RX_ERR_EFD_CNT_REG 0x1D8 +#define XGMAC_MAC_ERR_INFO_REG 0x1DC +#define XGMAC_MAC_DBG_INFO_REG 0x1E0 + +#define XGMAC_PCS_BASER_SYNC_THD_REG 0x330 +#define XGMAC_PCS_STATUS1_REG 0x404 +#define XGMAC_PCS_BASER_STATUS1_REG 0x410 +#define XGMAC_PCS_BASER_STATUS2_REG 0x414 +#define XGMAC_PCS_BASER_SEEDA_0_REG 0x420 +#define XGMAC_PCS_BASER_SEEDA_1_REG 0x424 +#define XGMAC_PCS_BASER_SEEDB_0_REG 0x428 +#define XGMAC_PCS_BASER_SEEDB_1_REG 0x42C +#define XGMAC_PCS_BASER_TEST_CONTROL_REG 0x430 +#define XGMAC_PCS_BASER_TEST_ERR_CNT_REG 0x434 +#define XGMAC_PCS_DBG_INFO_REG 0x4C0 +#define XGMAC_PCS_DBG_INFO1_REG 0x4C4 +#define XGMAC_PCS_DBG_INFO2_REG 0x4C8 +#define XGMAC_PCS_DBG_INFO3_REG 0x4CC + +#define XGMAC_PMA_ENABLE_REG 0x700 +#define XGMAC_PMA_CONTROL_REG 0x704 +#define XGMAC_PMA_SIGNAL_STATUS_REG 0x708 +#define XGMAC_PMA_DBG_INFO_REG 0x70C +#define XGMAC_PMA_FEC_ABILITY_REG 0x740 +#define XGMAC_PMA_FEC_CONTROL_REG 0x744 +#define XGMAC_PMA_FEC_CORR_BLOCK_CNT__REG 0x750 +#define XGMAC_PMA_FEC_UNCORR_BLOCK_CNT__REG 0x760 + +#define XGMAC_TX_PKTS_FRAGMENT 0x0000 +#define XGMAC_TX_PKTS_UNDERSIZE 0x0008 +#define XGMAC_TX_PKTS_UNDERMIN 0x0010 +#define XGMAC_TX_PKTS_64OCTETS 0x0018 +#define XGMAC_TX_PKTS_65TO127OCTETS 0x0020 +#define XGMAC_TX_PKTS_128TO255OCTETS 0x0028 +#define XGMAC_TX_PKTS_256TO511OCTETS 0x0030 +#define XGMAC_TX_PKTS_512TO1023OCTETS 0x0038 +#define XGMAC_TX_PKTS_1024TO1518OCTETS 0x0040 +#define XGMAC_TX_PKTS_1519TOMAXOCTETS 0x0048 +#define XGMAC_TX_PKTS_1519TOMAXOCTETSOK 0x0050 +#define XGMAC_TX_PKTS_OVERSIZE 0x0058 +#define XGMAC_TX_PKTS_JABBER 0x0060 +#define XGMAC_TX_GOODPKTS 0x0068 +#define XGMAC_TX_GOODOCTETS 0x0070 +#define XGMAC_TX_TOTAL_PKTS 0x0078 +#define XGMAC_TX_TOTALOCTETS 0x0080 +#define XGMAC_TX_UNICASTPKTS 0x0088 +#define XGMAC_TX_MULTICASTPKTS 0x0090 +#define XGMAC_TX_BROADCASTPKTS 0x0098 +#define XGMAC_TX_PRI0PAUSEPKTS 0x00a0 +#define XGMAC_TX_PRI1PAUSEPKTS 0x00a8 +#define XGMAC_TX_PRI2PAUSEPKTS 0x00b0 +#define XGMAC_TX_PRI3PAUSEPKTS 0x00b8 +#define XGMAC_TX_PRI4PAUSEPKTS 0x00c0 +#define XGMAC_TX_PRI5PAUSEPKTS 0x00c8 +#define XGMAC_TX_PRI6PAUSEPKTS 0x00d0 +#define XGMAC_TX_PRI7PAUSEPKTS 0x00d8 +#define XGMAC_TX_MACCTRLPKTS 0x00e0 +#define XGMAC_TX_1731PKTS 0x00e8 +#define XGMAC_TX_1588PKTS 0x00f0 +#define XGMAC_RX_FROMAPPGOODPKTS 0x00f8 +#define XGMAC_RX_FROMAPPBADPKTS 0x0100 +#define XGMAC_TX_ERRALLPKTS 0x0108 + +#define XGMAC_RX_PKTS_FRAGMENT 0x0110 +#define XGMAC_RX_PKTSUNDERSIZE 0x0118 +#define XGMAC_RX_PKTS_UNDERMIN 0x0120 +#define XGMAC_RX_PKTS_64OCTETS 0x0128 +#define XGMAC_RX_PKTS_65TO127OCTETS 0x0130 +#define XGMAC_RX_PKTS_128TO255OCTETS 0x0138 +#define XGMAC_RX_PKTS_256TO511OCTETS 0x0140 +#define XGMAC_RX_PKTS_512TO1023OCTETS 0x0148 +#define XGMAC_RX_PKTS_1024TO1518OCTETS 0x0150 +#define XGMAC_RX_PKTS_1519TOMAXOCTETS 0x0158 +#define XGMAC_RX_PKTS_1519TOMAXOCTETSOK 0x0160 +#define XGMAC_RX_PKTS_OVERSIZE 0x0168 +#define XGMAC_RX_PKTS_JABBER 0x0170 +#define XGMAC_RX_GOODPKTS 0x0178 +#define XGMAC_RX_GOODOCTETS 0x0180 +#define XGMAC_RX_TOTAL_PKTS 0x0188 +#define XGMAC_RX_TOTALOCTETS 0x0190 +#define XGMAC_RX_UNICASTPKTS 0x0198 +#define XGMAC_RX_MULTICASTPKTS 0x01a0 +#define XGMAC_RX_BROADCASTPKTS 0x01a8 +#define XGMAC_RX_PRI0PAUSEPKTS 0x01b0 +#define XGMAC_RX_PRI1PAUSEPKTS 0x01b8 +#define XGMAC_RX_PRI2PAUSEPKTS 0x01c0 +#define XGMAC_RX_PRI3PAUSEPKTS 0x01c8 +#define XGMAC_RX_PRI4PAUSEPKTS 0x01d0 +#define XGMAC_RX_PRI5PAUSEPKTS 0x01d8 +#define XGMAC_RX_PRI6PAUSEPKTS 0x01e0 +#define XGMAC_RX_PRI7PAUSEPKTS 0x01e8 +#define XGMAC_RX_MACCTRLPKTS 0x01f0 +#define XGMAC_TX_SENDAPPGOODPKTS 0x01f8 +#define XGMAC_TX_SENDAPPBADPKTS 0x0200 +#define XGMAC_RX_1731PKTS 0x0208 +#define XGMAC_RX_SYMBOLERRPKTS 0x0210 +#define XGMAC_RX_FCSERRPKTS 0x0218 + +#define XGMAC_TRX_CORE_SRST_M 0x2080 + +#define DSAF_CFG_EN_S 0 +#define DSAF_CFG_TC_MODE_S 1 +#define DSAF_CFG_CRC_EN_S 2 +#define DSAF_CFG_SBM_INIT_S 3 +#define DSAF_CFG_MIX_MODE_S 4 +#define DSAF_CFG_STP_MODE_S 5 +#define DSAF_CFG_LOCA_ADDR_EN_S 6 + +#define DSAF_CNT_CLR_CE_S 0 +#define DSAF_SNAP_EN_S 1 + +#define HNS_DSAF_PFC_UNIT_CNT_FOR_XGE 41 +#define HNS_DSAF_PFC_UNIT_CNT_FOR_GE_1000 410 +#define HNS_DSAF_PFC_UNIT_CNT_FOR_GE_2500 103 + +#define DSAF_PFC_UNINT_CNT_M ((1ULL << 9) - 1) +#define DSAF_PFC_UNINT_CNT_S 0 + +#define DSAF_PPE_QID_CFG_M 0xFF +#define DSAF_PPE_QID_CFG_S 0 + +#define DSAF_SW_PORT_TYPE_M 3 +#define DSAF_SW_PORT_TYPE_S 0 + +#define DSAF_STP_PORT_TYPE_M 7 +#define DSAF_STP_PORT_TYPE_S 0 + +#define DSAF_INODE_IN_PORT_NUM_M 7 +#define DSAF_INODE_IN_PORT_NUM_S 0 + +#define HNS_DSAF_I4TC_CFG 0x18688688 +#define HNS_DSAF_I8TC_CFG 0x18FAC688 + +#define DSAF_SBM_CFG_SHCUT_EN_S 0 +#define DSAF_SBM_CFG_EN_S 1 +#define DSAF_SBM_CFG_MIB_EN_S 2 +#define DSAF_SBM_CFG_ECC_INVERT_EN_S 3 + +#define DSAF_SBM_CFG0_VC1_MAX_BUF_NUM_S 0 +#define DSAF_SBM_CFG0_VC1_MAX_BUF_NUM_M (((1ULL << 10) - 1) << 0) +#define DSAF_SBM_CFG0_VC0_MAX_BUF_NUM_S 10 +#define DSAF_SBM_CFG0_VC0_MAX_BUF_NUM_M (((1ULL << 10) - 1) << 10) +#define DSAF_SBM_CFG0_COM_MAX_BUF_NUM_S 20 +#define DSAF_SBM_CFG0_COM_MAX_BUF_NUM_M (((1ULL << 11) - 1) << 20) + +#define DSAF_SBM_CFG1_TC4_MAX_BUF_NUM_S 0 +#define DSAF_SBM_CFG1_TC4_MAX_BUF_NUM_M (((1ULL << 10) - 1) << 0) +#define DSAF_SBM_CFG1_TC0_MAX_BUF_NUM_S 10 +#define DSAF_SBM_CFG1_TC0_MAX_BUF_NUM_M (((1ULL << 10) - 1) << 10) + +#define DSAF_SBM_CFG2_SET_BUF_NUM_S 0 +#define DSAF_SBM_CFG2_SET_BUF_NUM_M (((1ULL << 10) - 1) << 0) +#define DSAF_SBM_CFG2_RESET_BUF_NUM_S 10 +#define DSAF_SBM_CFG2_RESET_BUF_NUM_M (((1ULL << 10) - 1) << 10) + +#define DSAF_SBM_CFG3_SET_BUF_NUM_NO_PFC_S 0 +#define DSAF_SBM_CFG3_SET_BUF_NUM_NO_PFC_M (((1ULL << 10) - 1) << 0) +#define DSAF_SBM_CFG3_RESET_BUF_NUM_NO_PFC_S 10 +#define DSAF_SBM_CFG3_RESET_BUF_NUM_NO_PFC_M (((1ULL << 10) - 1) << 10) + +#define DSAF_TBL_TCAM_ADDR_S 0 +#define DSAF_TBL_TCAM_ADDR_M ((1ULL << 9) - 1) + +#define DSAF_TBL_LINE_ADDR_S 0 +#define DSAF_TBL_LINE_ADDR_M ((1ULL << 15) - 1) + +#define DSAF_TBL_MCAST_CFG4_VM128_112_S 0 +#define DSAF_TBL_MCAST_CFG4_VM128_112_M (((1ULL << 7) - 1) << 0) +#define DSAF_TBL_MCAST_CFG4_ITEM_VLD_S 7 +#define DSAF_TBL_MCAST_CFG4_OLD_EN_S 8 + +#define DSAF_TBL_MCAST_CFG0_XGE5_0_S 0 +#define DSAF_TBL_MCAST_CFG0_XGE5_0_M (((1ULL << 6) - 1) << 0) +#define DSAF_TBL_MCAST_CFG0_VM25_0_S 6 +#define DSAF_TBL_MCAST_CFG0_VM25_0_M (((1ULL << 26) - 1) << 6) + +#define DSAF_TBL_UCAST_CFG1_OUT_PORT_S 0 +#define DSAF_TBL_UCAST_CFG1_OUT_PORT_M (((1ULL << 8) - 1) << 0) +#define DSAF_TBL_UCAST_CFG1_DVC_S 8 +#define DSAF_TBL_UCAST_CFG1_MAC_DISCARD_S 9 +#define DSAF_TBL_UCAST_CFG1_ITEM_VLD_S 10 +#define DSAF_TBL_UCAST_CFG1_OLD_EN_S 11 + +#define DSAF_TBL_LINE_CFG_OUT_PORT_S 0 +#define DSAF_TBL_LINE_CFG_OUT_PORT_M (((1ULL << 8) - 1) << 0) +#define DSAF_TBL_LINE_CFG_DVC_S 8 +#define DSAF_TBL_LINE_CFG_MAC_DISCARD_S 9 + +#define DSAF_TBL_PUL_OLD_RSLT_RE_S 0 +#define DSAF_TBL_PUL_MCAST_VLD_S 1 +#define DSAF_TBL_PUL_TCAM_DATA_VLD_S 2 +#define DSAF_TBL_PUL_UCAST_VLD_S 3 +#define DSAF_TBL_PUL_LINE_VLD_S 4 +#define DSAF_TBL_PUL_TCAM_LOAD_S 5 +#define DSAF_TBL_PUL_LINE_LOAD_S 6 + +#define DSAF_TBL_DFX_LINE_LKUP_NUM_EN_S 0 +#define DSAF_TBL_DFX_UC_LKUP_NUM_EN_S 1 +#define DSAF_TBL_DFX_MC_LKUP_NUM_EN_S 2 +#define DSAF_TBL_DFX_BC_LKUP_NUM_EN_S 3 +#define DSAF_TBL_DFX_RAM_ERR_INJECT_EN_S 4 + +#define DSAF_VOQ_BP_ALL_DOWNTHRD_S 0 +#define DSAF_VOQ_BP_ALL_DOWNTHRD_M (((1ULL << 10) - 1) << 0) +#define DSAF_VOQ_BP_ALL_UPTHRD_S 10 +#define DSAF_VOQ_BP_ALL_UPTHRD_M (((1ULL << 10) - 1) << 10) + +#define DSAF_XGE_GE_WORK_MODE_S 0 +#define DSAF_XGE_GE_LOOPBACK_S 1 + +#define DSAF_FC_XGE_TX_PAUSE_S 0 +#define DSAF_REGS_XGE_CNT_CAR_S 1 + +#define PPE_CFG_QID_MODE_DEF_QID_S 0 +#define PPE_CFG_QID_MODE_DEF_QID_M (0xff << PPE_CFG_QID_MODE_DEF_QID_S) + +#define PPE_CFG_QID_MODE_CF_QID_MODE_S 8 +#define PPE_CFG_QID_MODE_CF_QID_MODE_M (0x7 << PPE_CFG_QID_MODE_CF_QID_MODE_S) + +#define PPE_CNT_CLR_CE_B 0 +#define PPE_CNT_CLR_SNAP_EN_B 1 + +#define PPE_COMMON_CNT_CLR_CE_B 0 +#define PPE_COMMON_CNT_CLR_SNAP_EN_B 1 + +#define GMAC_DUPLEX_TYPE_B 0 + +#define GMAC_FC_TX_TIMER_S 0 +#define GMAC_FC_TX_TIMER_M 0xffff + +#define GMAC_MAX_FRM_SIZE_S 0 +#define GMAC_MAX_FRM_SIZE_M 0xffff + +#define GMAC_PORT_MODE_S 0 +#define GMAC_PORT_MODE_M 0xf + +#define GMAC_RGMII_1000M_DELAY_B 4 +#define GMAC_MII_TX_EDGE_SEL_B 5 +#define GMAC_FIFO_ERR_AUTO_RST_B 6 +#define GMAC_DBG_CLK_LOS_MSK_B 7 + +#define GMAC_PORT_RX_EN_B 1 +#define GMAC_PORT_TX_EN_B 2 + +#define GMAC_PAUSE_EN_RX_FDFC_B 0 +#define GMAC_PAUSE_EN_TX_FDFC_B 1 +#define GMAC_PAUSE_EN_TX_HDFC_B 2 + +#define GMAC_SHORT_RUNTS_THR_S 0 +#define GMAC_SHORT_RUNTS_THR_M 0x1f + +#define GMAC_AN_NEG_STAT_FD_B 5 +#define GMAC_AN_NEG_STAT_HD_B 6 +#define GMAC_AN_NEG_STAT_RF1_DUPLIEX_B 12 +#define GMAC_AN_NEG_STAT_RF2_B 13 + +#define GMAC_AN_NEG_STAT_NP_LNK_OK_B 15 +#define GMAC_AN_NEG_STAT_RX_SYNC_OK_B 20 +#define GMAC_AN_NEG_STAT_AN_DONE_B 21 + +#define GMAC_AN_NEG_STAT_PS_S 7 +#define GMAC_AN_NEG_STAT_PS_M (0x3 << GMAC_AN_NEG_STAT_PS_S) + +#define GMAC_AN_NEG_STAT_SPEED_S 10 +#define GMAC_AN_NEG_STAT_SPEED_M (0x3 << GMAC_AN_NEG_STAT_SPEED_S) + +#define GMAC_TX_AN_EN_B 5 +#define GMAC_TX_CRC_ADD_B 6 +#define GMAC_TX_PAD_EN_B 7 + +#define GMAC_LINE_LOOPBACK_B 0 + +#define GMAC_LP_REG_CF_EXT_DRV_LP_B 1 +#define GMAC_LP_REG_CF2MI_LP_EN_B 2 + +#define GMAC_MODE_CHANGE_EB_B 0 + +#define GMAC_RECV_CTRL_STRIP_PAD_EN_B 3 +#define GMAC_RECV_CTRL_RUNT_PKT_EN_B 4 + +#define GMAC_TX_LOOP_PKT_HIG_PRI_B 0 +#define GMAC_TX_LOOP_PKT_EN_B 1 + +#define XGMAC_PORT_MODE_TX_S 0x0 +#define XGMAC_PORT_MODE_TX_M (0x3 << XGMAC_PORT_MODE_TX_S) +#define XGMAC_PORT_MODE_TX_40G_B 0x3 +#define XGMAC_PORT_MODE_RX_S 0x4 +#define XGMAC_PORT_MODE_RX_M (0x3 << XGMAC_PORT_MODE_RX_S) +#define XGMAC_PORT_MODE_RX_40G_B 0x7 + +#define XGMAC_ENABLE_TX_B 0 +#define XGMAC_ENABLE_RX_B 1 + +#define XGMAC_CTL_TX_FCS_B 0 +#define XGMAC_CTL_TX_PAD_B 1 +#define XGMAC_CTL_TX_PREAMBLE_TRANS_B 3 +#define XGMAC_CTL_TX_UNDER_MIN_ERR_B 4 +#define XGMAC_CTL_TX_TRUNCATE_B 5 +#define XGMAC_CTL_TX_1588_B 8 +#define XGMAC_CTL_TX_1731_B 9 +#define XGMAC_CTL_TX_PFC_B 10 +#define XGMAC_CTL_RX_FCS_B 16 +#define XGMAC_CTL_RX_FCS_STRIP_B 17 +#define XGMAC_CTL_RX_PREAMBLE_TRANS_B 19 +#define XGMAC_CTL_RX_UNDER_MIN_ERR_B 20 +#define XGMAC_CTL_RX_TRUNCATE_B 21 +#define XGMAC_CTL_RX_1588_B 24 +#define XGMAC_CTL_RX_1731_B 25 +#define XGMAC_CTL_RX_PFC_B 26 + +#define XGMAC_PMA_FEC_CTL_TX_B 0 +#define XGMAC_PMA_FEC_CTL_RX_B 1 +#define XGMAC_PMA_FEC_CTL_ERR_EN 2 +#define XGMAC_PMA_FEC_CTL_ERR_SH 3 + +#define XGMAC_PAUSE_CTL_TX_B 0 +#define XGMAC_PAUSE_CTL_RX_B 1 +#define XGMAC_PAUSE_CTL_RSP_MODE_B 2 +#define XGMAC_PAUSE_CTL_TX_XOFF_B 3 + +static inline void dsaf_write_reg(void *base, u32 reg, u32 value) +{ + u8 __iomem *reg_addr = ACCESS_ONCE(base); + + writel(value, reg_addr + reg); +} + +#define dsaf_write_dev(a, reg, value) \ + dsaf_write_reg((a)->io_base, (reg), (value)) + +static inline u32 dsaf_read_reg(u8 *base, u32 reg) +{ + u8 __iomem *reg_addr = ACCESS_ONCE(base); + + return readl(reg_addr + reg); +} + +#define dsaf_read_dev(a, reg) \ + dsaf_read_reg((a)->io_base, (reg)) + +#define dsaf_set_field(origin, mask, shift, val) \ + do { \ + (origin) &= (~(mask)); \ + (origin) |= (((val) << (shift)) & (mask)); \ + } while (0) + +#define dsaf_set_bit(origin, shift, val) \ + dsaf_set_field((origin), (1ull << (shift)), (shift), (val)) + +static inline void dsaf_set_reg_field(void *base, u32 reg, u32 mask, u32 shift, + u32 val) +{ + u32 origin = dsaf_read_reg(base, reg); + + dsaf_set_field(origin, mask, shift, val); + dsaf_write_reg(base, reg, origin); +} + +#define dsaf_set_dev_field(dev, reg, mask, shift, val) \ + dsaf_set_reg_field((dev)->io_base, (reg), (mask), (shift), (val)) + +#define dsaf_set_dev_bit(dev, reg, bit, val) \ + dsaf_set_reg_field((dev)->io_base, (reg), (1ull << (bit)), (bit), (val)) + +#define dsaf_get_field(origin, mask, shift) (((origin) & (mask)) >> (shift)) + +#define dsaf_get_bit(origin, shift) \ + dsaf_get_field((origin), (1ull << (shift)), (shift)) + +static inline u32 dsaf_get_reg_field(void *base, u32 reg, u32 mask, u32 shift) +{ + u32 origin; + + origin = dsaf_read_reg(base, reg); + return dsaf_get_field(origin, mask, shift); +} + +#define dsaf_get_dev_field(dev, reg, mask, shift) \ + dsaf_get_reg_field((dev)->io_base, (reg), (mask), (shift)) + +#define dsaf_get_dev_bit(dev, reg, bit) \ + dsaf_get_reg_field((dev)->io_base, (reg), (1ull << (bit)), (bit)) + +#define dsaf_write_b(addr, data)\ + writeb((data), (__iomem unsigned char *)(addr)) +#define dsaf_read_b(addr)\ + readb((__iomem unsigned char *)(addr)) + +#define hns_mac_reg_read64(drv, offset) \ + readq((__iomem void *)(((u64)(drv)->io_base + 0xc00 + (offset)))) + +#endif /* _DSAF_REG_H */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c new file mode 100644 index 000000000000..fe7fa1d6852b --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c @@ -0,0 +1,836 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include "hns_dsaf_main.h" +#include "hns_dsaf_mac.h" +#include "hns_dsaf_xgmac.h" +#include "hns_dsaf_reg.h" + +static const struct mac_stats_string g_xgmac_stats_string[] = { + {"xgmac_tx_bad_pkts_minto64", MAC_STATS_FIELD_OFF(tx_fragment_err)}, + {"xgmac_tx_good_pkts_minto64", MAC_STATS_FIELD_OFF(tx_undersize)}, + {"xgmac_tx_total_pkts_minto64", MAC_STATS_FIELD_OFF(tx_under_min_pkts)}, + {"xgmac_tx_pkts_64", MAC_STATS_FIELD_OFF(tx_64bytes)}, + {"xgmac_tx_pkts_65to127", MAC_STATS_FIELD_OFF(tx_65to127)}, + {"xgmac_tx_pkts_128to255", MAC_STATS_FIELD_OFF(tx_128to255)}, + {"xgmac_tx_pkts_256to511", MAC_STATS_FIELD_OFF(tx_256to511)}, + {"xgmac_tx_pkts_512to1023", MAC_STATS_FIELD_OFF(tx_512to1023)}, + {"xgmac_tx_pkts_1024to1518", MAC_STATS_FIELD_OFF(tx_1024to1518)}, + {"xgmac_tx_pkts_1519tomax", MAC_STATS_FIELD_OFF(tx_1519tomax)}, + {"xgmac_tx_good_pkts_1519tomax", + MAC_STATS_FIELD_OFF(tx_1519tomax_good)}, + {"xgmac_tx_good_pkts_untralmax", MAC_STATS_FIELD_OFF(tx_oversize)}, + {"xgmac_tx_bad_pkts_untralmax", MAC_STATS_FIELD_OFF(tx_jabber_err)}, + {"xgmac_tx_good_pkts_all", MAC_STATS_FIELD_OFF(tx_good_pkts)}, + {"xgmac_tx_good_byte_all", MAC_STATS_FIELD_OFF(tx_good_bytes)}, + {"xgmac_tx_total_pkt", MAC_STATS_FIELD_OFF(tx_total_pkts)}, + {"xgmac_tx_total_byt", MAC_STATS_FIELD_OFF(tx_total_bytes)}, + {"xgmac_tx_uc_pkt", MAC_STATS_FIELD_OFF(tx_uc_pkts)}, + {"xgmac_tx_mc_pkt", MAC_STATS_FIELD_OFF(tx_mc_pkts)}, + {"xgmac_tx_bc_pkt", MAC_STATS_FIELD_OFF(tx_bc_pkts)}, + {"xgmac_tx_pause_frame_num", MAC_STATS_FIELD_OFF(tx_pfc_tc0)}, + {"xgmac_tx_pfc_per_1pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc1)}, + {"xgmac_tx_pfc_per_2pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc2)}, + {"xgmac_tx_pfc_per_3pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc3)}, + {"xgmac_tx_pfc_per_4pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc4)}, + {"xgmac_tx_pfc_per_5pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc5)}, + {"xgmac_tx_pfc_per_6pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc6)}, + {"xgmac_tx_pfc_per_7pause_framer", MAC_STATS_FIELD_OFF(tx_pfc_tc7)}, + {"xgmac_tx_mac_ctrol_frame", MAC_STATS_FIELD_OFF(tx_ctrl)}, + {"xgmac_tx_1731_pkts", MAC_STATS_FIELD_OFF(tx_1731_pkts)}, + {"xgmac_tx_1588_pkts", MAC_STATS_FIELD_OFF(tx_1588_pkts)}, + {"xgmac_rx_good_pkt_from_dsaf", MAC_STATS_FIELD_OFF(rx_good_from_sw)}, + {"xgmac_rx_bad_pkt_from_dsaf", MAC_STATS_FIELD_OFF(rx_bad_from_sw)}, + {"xgmac_tx_bad_pkt_64tomax", MAC_STATS_FIELD_OFF(tx_bad_pkts)}, + + {"xgmac_rx_not_well_pkt", MAC_STATS_FIELD_OFF(rx_fragment_err)}, + {"xgmac_rx_good_well_pkt", MAC_STATS_FIELD_OFF(rx_undersize)}, + {"xgmac_rx_total_pkt", MAC_STATS_FIELD_OFF(rx_under_min)}, + {"xgmac_rx_pkt_64", MAC_STATS_FIELD_OFF(rx_64bytes)}, + {"xgmac_rx_pkt_65to127", MAC_STATS_FIELD_OFF(rx_65to127)}, + {"xgmac_rx_pkt_128to255", MAC_STATS_FIELD_OFF(rx_128to255)}, + {"xgmac_rx_pkt_256to511", MAC_STATS_FIELD_OFF(rx_256to511)}, + {"xgmac_rx_pkt_512to1023", MAC_STATS_FIELD_OFF(rx_512to1023)}, + {"xgmac_rx_pkt_1024to1518", MAC_STATS_FIELD_OFF(rx_1024to1518)}, + {"xgmac_rx_pkt_1519tomax", MAC_STATS_FIELD_OFF(rx_1519tomax)}, + {"xgmac_rx_good_pkt_1519tomax", MAC_STATS_FIELD_OFF(rx_1519tomax_good)}, + {"xgmac_rx_good_pkt_untramax", MAC_STATS_FIELD_OFF(rx_oversize)}, + {"xgmac_rx_bad_pkt_untramax", MAC_STATS_FIELD_OFF(rx_jabber_err)}, + {"xgmac_rx_good_pkt", MAC_STATS_FIELD_OFF(rx_good_pkts)}, + {"xgmac_rx_good_byt", MAC_STATS_FIELD_OFF(rx_good_bytes)}, + {"xgmac_rx_pkt", MAC_STATS_FIELD_OFF(rx_total_pkts)}, + {"xgmac_rx_byt", MAC_STATS_FIELD_OFF(rx_total_bytes)}, + {"xgmac_rx_uc_pkt", MAC_STATS_FIELD_OFF(rx_uc_pkts)}, + {"xgmac_rx_mc_pkt", MAC_STATS_FIELD_OFF(rx_mc_pkts)}, + {"xgmac_rx_bc_pkt", MAC_STATS_FIELD_OFF(rx_bc_pkts)}, + {"xgmac_rx_pause_frame_num", MAC_STATS_FIELD_OFF(rx_pfc_tc0)}, + {"xgmac_rx_pfc_per_1pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc1)}, + {"xgmac_rx_pfc_per_2pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc2)}, + {"xgmac_rx_pfc_per_3pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc3)}, + {"xgmac_rx_pfc_per_4pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc4)}, + {"xgmac_rx_pfc_per_5pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc5)}, + {"xgmac_rx_pfc_per_6pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc6)}, + {"xgmac_rx_pfc_per_7pause_frame", MAC_STATS_FIELD_OFF(rx_pfc_tc7)}, + {"xgmac_rx_mac_control", MAC_STATS_FIELD_OFF(rx_unknown_ctrl)}, + {"xgmac_tx_good_pkt_todsaf", MAC_STATS_FIELD_OFF(tx_good_to_sw)}, + {"xgmac_tx_bad_pkt_todsaf", MAC_STATS_FIELD_OFF(tx_bad_to_sw)}, + {"xgmac_rx_1731_pkt", MAC_STATS_FIELD_OFF(rx_1731_pkts)}, + {"xgmac_rx_symbol_err_pkt", MAC_STATS_FIELD_OFF(rx_symbol_err)}, + {"xgmac_rx_fcs_pkt", MAC_STATS_FIELD_OFF(rx_fcs_err)} +}; + +/** + *hns_xgmac_tx_enable - xgmac port tx enable + *@drv: mac driver + *@value: value of enable + */ +static void hns_xgmac_tx_enable(struct mac_driver *drv, u32 value) +{ + dsaf_set_dev_bit(drv, XGMAC_MAC_ENABLE_REG, XGMAC_ENABLE_TX_B, !!value); +} + +/** + *hns_xgmac_rx_enable - xgmac port rx enable + *@drv: mac driver + *@value: value of enable + */ +static void hns_xgmac_rx_enable(struct mac_driver *drv, u32 value) +{ + dsaf_set_dev_bit(drv, XGMAC_MAC_ENABLE_REG, XGMAC_ENABLE_RX_B, !!value); +} + +/** + *hns_xgmac_enable - enable xgmac port + *@drv: mac driver + *@mode: mode of mac port + */ +static void hns_xgmac_enable(void *mac_drv, enum mac_commom_mode mode) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + struct dsaf_device *dsaf_dev + = (struct dsaf_device *)dev_get_drvdata(drv->dev); + u32 port = drv->mac_id; + + hns_dsaf_xge_core_srst_by_port(dsaf_dev, port, 1); + mdelay(10); + + /*enable XGE rX/tX */ + if (mode == MAC_COMM_MODE_TX) { + hns_xgmac_tx_enable(drv, 1); + } else if (mode == MAC_COMM_MODE_RX) { + hns_xgmac_rx_enable(drv, 1); + } else if (mode == MAC_COMM_MODE_RX_AND_TX) { + hns_xgmac_tx_enable(drv, 1); + hns_xgmac_rx_enable(drv, 1); + } else { + dev_err(drv->dev, "error mac mode:%d\n", mode); + } +} + +/** + *hns_xgmac_disable - disable xgmac port + *@mac_drv: mac driver + *@mode: mode of mac port + */ +static void hns_xgmac_disable(void *mac_drv, enum mac_commom_mode mode) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + struct dsaf_device *dsaf_dev + = (struct dsaf_device *)dev_get_drvdata(drv->dev); + u32 port = drv->mac_id; + + if (mode == MAC_COMM_MODE_TX) { + hns_xgmac_tx_enable(drv, 0); + } else if (mode == MAC_COMM_MODE_RX) { + hns_xgmac_rx_enable(drv, 0); + } else if (mode == MAC_COMM_MODE_RX_AND_TX) { + hns_xgmac_tx_enable(drv, 0); + hns_xgmac_rx_enable(drv, 0); + } + + mdelay(10); + hns_dsaf_xge_core_srst_by_port(dsaf_dev, port, 0); +} + +/** + *hns_xgmac_pma_fec_enable - xgmac PMA FEC enable + *@drv: mac driver + *@tx_value: tx value + *@rx_value: rx value + *return status + */ +static void hns_xgmac_pma_fec_enable(struct mac_driver *drv, u32 tx_value, + u32 rx_value) +{ + u32 origin = dsaf_read_dev(drv, XGMAC_PMA_FEC_CONTROL_REG); + + dsaf_set_bit(origin, XGMAC_PMA_FEC_CTL_TX_B, !!tx_value); + dsaf_set_bit(origin, XGMAC_PMA_FEC_CTL_RX_B, !!rx_value); + dsaf_write_dev(drv, XGMAC_PMA_FEC_CONTROL_REG, origin); +} + +/* clr exc irq for xge*/ +static void hns_xgmac_exc_irq_en(struct mac_driver *drv, u32 en) +{ + u32 clr_vlue = 0xfffffffful; + u32 msk_vlue = en ? 0xfffffffful : 0; /*1 is en, 0 is dis*/ + + dsaf_write_dev(drv, XGMAC_INT_STATUS_REG, clr_vlue); + dsaf_write_dev(drv, XGMAC_INT_ENABLE_REG, msk_vlue); +} + +/** + *hns_xgmac_init - initialize XGE + *@mac_drv: mac driver + */ +static void hns_xgmac_init(void *mac_drv) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + struct dsaf_device *dsaf_dev + = (struct dsaf_device *)dev_get_drvdata(drv->dev); + u32 port = drv->mac_id; + + hns_dsaf_xge_srst_by_port(dsaf_dev, port, 0); + mdelay(100); + hns_dsaf_xge_srst_by_port(dsaf_dev, port, 1); + + mdelay(100); + hns_xgmac_exc_irq_en(drv, 0); + + hns_xgmac_pma_fec_enable(drv, 0x0, 0x0); + + hns_xgmac_disable(mac_drv, MAC_COMM_MODE_RX_AND_TX); +} + +/** + *hns_xgmac_config_pad_and_crc - set xgmac pad and crc enable the same time + *@mac_drv: mac driver + *@newval:enable of pad and crc + */ +static void hns_xgmac_config_pad_and_crc(void *mac_drv, u8 newval) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + u32 origin = dsaf_read_dev(drv, XGMAC_MAC_CONTROL_REG); + + dsaf_set_bit(origin, XGMAC_CTL_TX_PAD_B, !!newval); + dsaf_set_bit(origin, XGMAC_CTL_TX_FCS_B, !!newval); + dsaf_set_bit(origin, XGMAC_CTL_RX_FCS_B, !!newval); + dsaf_write_dev(drv, XGMAC_MAC_CONTROL_REG, origin); +} + +/** + *hns_xgmac_pausefrm_cfg - set pause param about xgmac + *@mac_drv: mac driver + *@newval:enable of pad and crc + */ +static void hns_xgmac_pausefrm_cfg(void *mac_drv, u32 rx_en, u32 tx_en) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + u32 origin = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_CTRL_REG); + + dsaf_set_bit(origin, XGMAC_PAUSE_CTL_TX_B, !!tx_en); + dsaf_set_bit(origin, XGMAC_PAUSE_CTL_RX_B, !!rx_en); + dsaf_write_dev(drv, XGMAC_MAC_PAUSE_CTRL_REG, origin); +} + +static void hns_xgmac_set_pausefrm_mac_addr(void *mac_drv, char *mac_addr) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + u32 high_val = mac_addr[1] | (mac_addr[0] << 8); + u32 low_val = mac_addr[5] | (mac_addr[4] << 8) + | (mac_addr[3] << 16) | (mac_addr[2] << 24); + dsaf_write_dev(drv, XGMAC_MAC_PAUSE_LOCAL_MAC_L_REG, low_val); + dsaf_write_dev(drv, XGMAC_MAC_PAUSE_LOCAL_MAC_H_REG, high_val); +} + +/** + *hns_xgmac_set_rx_ignore_pause_frames - set rx pause param about xgmac + *@mac_drv: mac driver + *@enable:enable rx pause param + */ +static void hns_xgmac_set_rx_ignore_pause_frames(void *mac_drv, u32 enable) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + dsaf_set_dev_bit(drv, XGMAC_MAC_PAUSE_CTRL_REG, + XGMAC_PAUSE_CTL_RX_B, !!enable); +} + +/** + *hns_xgmac_set_tx_auto_pause_frames - set tx pause param about xgmac + *@mac_drv: mac driver + *@enable:enable tx pause param + */ +static void hns_xgmac_set_tx_auto_pause_frames(void *mac_drv, u16 enable) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + dsaf_set_dev_bit(drv, XGMAC_MAC_PAUSE_CTRL_REG, + XGMAC_PAUSE_CTL_TX_B, !!enable); + + /*if enable is not zero ,set tx pause time */ + if (enable) + dsaf_write_dev(drv, XGMAC_MAC_PAUSE_TIME_REG, enable); +} + +/** + *hns_xgmac_get_id - get xgmac port id + *@mac_drv: mac driver + *@newval:xgmac max frame length + */ +static void hns_xgmac_get_id(void *mac_drv, u8 *mac_id) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + *mac_id = drv->mac_id; +} + +/** + *hns_xgmac_config_max_frame_length - set xgmac max frame length + *@mac_drv: mac driver + *@newval:xgmac max frame length + */ +static void hns_xgmac_config_max_frame_length(void *mac_drv, u16 newval) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + dsaf_write_dev(drv, XGMAC_MAC_MAX_PKT_SIZE_REG, newval); +} + +void hns_xgmac_update_stats(void *mac_drv) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + struct mac_hw_stats *hw_stats = &drv->mac_cb->hw_stats; + + /* TX */ + hw_stats->tx_fragment_err + = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_FRAGMENT); + hw_stats->tx_undersize + = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_UNDERSIZE); + hw_stats->tx_under_min_pkts + = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_UNDERMIN); + hw_stats->tx_64bytes = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_64OCTETS); + hw_stats->tx_65to127 + = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_65TO127OCTETS); + hw_stats->tx_128to255 + = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_128TO255OCTETS); + hw_stats->tx_256to511 + = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_256TO511OCTETS); + hw_stats->tx_512to1023 + = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_512TO1023OCTETS); + hw_stats->tx_1024to1518 + = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_1024TO1518OCTETS); + hw_stats->tx_1519tomax + = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_1519TOMAXOCTETS); + hw_stats->tx_1519tomax_good + = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_1519TOMAXOCTETSOK); + hw_stats->tx_oversize = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_OVERSIZE); + hw_stats->tx_jabber_err = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_JABBER); + hw_stats->tx_good_pkts = hns_mac_reg_read64(drv, XGMAC_TX_GOODPKTS); + hw_stats->tx_good_bytes = hns_mac_reg_read64(drv, XGMAC_TX_GOODOCTETS); + hw_stats->tx_total_pkts = hns_mac_reg_read64(drv, XGMAC_TX_TOTAL_PKTS); + hw_stats->tx_total_bytes + = hns_mac_reg_read64(drv, XGMAC_TX_TOTALOCTETS); + hw_stats->tx_uc_pkts = hns_mac_reg_read64(drv, XGMAC_TX_UNICASTPKTS); + hw_stats->tx_mc_pkts = hns_mac_reg_read64(drv, XGMAC_TX_MULTICASTPKTS); + hw_stats->tx_bc_pkts = hns_mac_reg_read64(drv, XGMAC_TX_BROADCASTPKTS); + hw_stats->tx_pfc_tc0 = hns_mac_reg_read64(drv, XGMAC_TX_PRI0PAUSEPKTS); + hw_stats->tx_pfc_tc1 = hns_mac_reg_read64(drv, XGMAC_TX_PRI1PAUSEPKTS); + hw_stats->tx_pfc_tc2 = hns_mac_reg_read64(drv, XGMAC_TX_PRI2PAUSEPKTS); + hw_stats->tx_pfc_tc3 = hns_mac_reg_read64(drv, XGMAC_TX_PRI3PAUSEPKTS); + hw_stats->tx_pfc_tc4 = hns_mac_reg_read64(drv, XGMAC_TX_PRI4PAUSEPKTS); + hw_stats->tx_pfc_tc5 = hns_mac_reg_read64(drv, XGMAC_TX_PRI5PAUSEPKTS); + hw_stats->tx_pfc_tc6 = hns_mac_reg_read64(drv, XGMAC_TX_PRI6PAUSEPKTS); + hw_stats->tx_pfc_tc7 = hns_mac_reg_read64(drv, XGMAC_TX_PRI7PAUSEPKTS); + hw_stats->tx_ctrl = hns_mac_reg_read64(drv, XGMAC_TX_MACCTRLPKTS); + hw_stats->tx_1731_pkts = hns_mac_reg_read64(drv, XGMAC_TX_1731PKTS); + hw_stats->tx_1588_pkts = hns_mac_reg_read64(drv, XGMAC_TX_1588PKTS); + hw_stats->rx_good_from_sw + = hns_mac_reg_read64(drv, XGMAC_RX_FROMAPPGOODPKTS); + hw_stats->rx_bad_from_sw + = hns_mac_reg_read64(drv, XGMAC_RX_FROMAPPBADPKTS); + hw_stats->tx_bad_pkts = hns_mac_reg_read64(drv, XGMAC_TX_ERRALLPKTS); + + /* RX */ + hw_stats->rx_fragment_err + = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_FRAGMENT); + hw_stats->rx_undersize + = hns_mac_reg_read64(drv, XGMAC_RX_PKTSUNDERSIZE); + hw_stats->rx_under_min + = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_UNDERMIN); + hw_stats->rx_64bytes = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_64OCTETS); + hw_stats->rx_65to127 + = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_65TO127OCTETS); + hw_stats->rx_128to255 + = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_128TO255OCTETS); + hw_stats->rx_256to511 + = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_256TO511OCTETS); + hw_stats->rx_512to1023 + = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_512TO1023OCTETS); + hw_stats->rx_1024to1518 + = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_1024TO1518OCTETS); + hw_stats->rx_1519tomax + = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_1519TOMAXOCTETS); + hw_stats->rx_1519tomax_good + = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_1519TOMAXOCTETSOK); + hw_stats->rx_oversize = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_OVERSIZE); + hw_stats->rx_jabber_err = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_JABBER); + hw_stats->rx_good_pkts = hns_mac_reg_read64(drv, XGMAC_RX_GOODPKTS); + hw_stats->rx_good_bytes = hns_mac_reg_read64(drv, XGMAC_RX_GOODOCTETS); + hw_stats->rx_total_pkts = hns_mac_reg_read64(drv, XGMAC_RX_TOTAL_PKTS); + hw_stats->rx_total_bytes + = hns_mac_reg_read64(drv, XGMAC_RX_TOTALOCTETS); + hw_stats->rx_uc_pkts = hns_mac_reg_read64(drv, XGMAC_RX_UNICASTPKTS); + hw_stats->rx_mc_pkts = hns_mac_reg_read64(drv, XGMAC_RX_MULTICASTPKTS); + hw_stats->rx_bc_pkts = hns_mac_reg_read64(drv, XGMAC_RX_BROADCASTPKTS); + hw_stats->rx_pfc_tc0 = hns_mac_reg_read64(drv, XGMAC_RX_PRI0PAUSEPKTS); + hw_stats->rx_pfc_tc1 = hns_mac_reg_read64(drv, XGMAC_RX_PRI1PAUSEPKTS); + hw_stats->rx_pfc_tc2 = hns_mac_reg_read64(drv, XGMAC_RX_PRI2PAUSEPKTS); + hw_stats->rx_pfc_tc3 = hns_mac_reg_read64(drv, XGMAC_RX_PRI3PAUSEPKTS); + hw_stats->rx_pfc_tc4 = hns_mac_reg_read64(drv, XGMAC_RX_PRI4PAUSEPKTS); + hw_stats->rx_pfc_tc5 = hns_mac_reg_read64(drv, XGMAC_RX_PRI5PAUSEPKTS); + hw_stats->rx_pfc_tc6 = hns_mac_reg_read64(drv, XGMAC_RX_PRI6PAUSEPKTS); + hw_stats->rx_pfc_tc7 = hns_mac_reg_read64(drv, XGMAC_RX_PRI7PAUSEPKTS); + + hw_stats->rx_unknown_ctrl + = hns_mac_reg_read64(drv, XGMAC_RX_MACCTRLPKTS); + hw_stats->tx_good_to_sw + = hns_mac_reg_read64(drv, XGMAC_TX_SENDAPPGOODPKTS); + hw_stats->tx_bad_to_sw + = hns_mac_reg_read64(drv, XGMAC_TX_SENDAPPBADPKTS); + hw_stats->rx_1731_pkts = hns_mac_reg_read64(drv, XGMAC_RX_1731PKTS); + hw_stats->rx_symbol_err + = hns_mac_reg_read64(drv, XGMAC_RX_SYMBOLERRPKTS); + hw_stats->rx_fcs_err = hns_mac_reg_read64(drv, XGMAC_RX_FCSERRPKTS); +} + +/** + *hns_xgmac_free - free xgmac driver + *@mac_drv: mac driver + */ +static void hns_xgmac_free(void *mac_drv) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + struct dsaf_device *dsaf_dev + = (struct dsaf_device *)dev_get_drvdata(drv->dev); + + u32 mac_id = drv->mac_id; + + hns_dsaf_xge_srst_by_port(dsaf_dev, mac_id, 0); +} + +/** + *hns_xgmac_get_info - get xgmac information + *@mac_drv: mac driver + *@mac_info:mac information + */ +static void hns_xgmac_get_info(void *mac_drv, struct mac_info *mac_info) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + u32 pause_time, pause_ctrl, port_mode, ctrl_val; + + ctrl_val = dsaf_read_dev(drv, XGMAC_MAC_CONTROL_REG); + mac_info->pad_and_crc_en = dsaf_get_bit(ctrl_val, XGMAC_CTL_TX_PAD_B); + mac_info->auto_neg = 0; + + pause_time = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_TIME_REG); + mac_info->tx_pause_time = pause_time; + + port_mode = dsaf_read_dev(drv, XGMAC_PORT_MODE_REG); + mac_info->port_en = dsaf_get_field(port_mode, XGMAC_PORT_MODE_TX_M, + XGMAC_PORT_MODE_TX_S) && + dsaf_get_field(port_mode, XGMAC_PORT_MODE_RX_M, + XGMAC_PORT_MODE_RX_S); + mac_info->duplex = 1; + mac_info->speed = MAC_SPEED_10000; + + pause_ctrl = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_CTRL_REG); + mac_info->rx_pause_en = dsaf_get_bit(pause_ctrl, XGMAC_PAUSE_CTL_RX_B); + mac_info->tx_pause_en = dsaf_get_bit(pause_ctrl, XGMAC_PAUSE_CTL_TX_B); +} + +/** + *hns_xgmac_get_pausefrm_cfg - get xgmac pause param + *@mac_drv: mac driver + *@rx_en:xgmac rx pause enable + *@tx_en:xgmac tx pause enable + */ +static void hns_xgmac_get_pausefrm_cfg(void *mac_drv, u32 *rx_en, u32 *tx_en) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + u32 pause_ctrl; + + pause_ctrl = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_CTRL_REG); + *rx_en = dsaf_get_bit(pause_ctrl, XGMAC_PAUSE_CTL_RX_B); + *tx_en = dsaf_get_bit(pause_ctrl, XGMAC_PAUSE_CTL_TX_B); +} + +/** + *hns_xgmac_get_link_status - get xgmac link status + *@mac_drv: mac driver + *@link_stat: xgmac link stat + */ +static void hns_xgmac_get_link_status(void *mac_drv, u32 *link_stat) +{ + struct mac_driver *drv = (struct mac_driver *)mac_drv; + + *link_stat = dsaf_read_dev(drv, XGMAC_LINK_STATUS_REG); +} + +/** + *hns_xgmac_get_regs - dump xgmac regs + *@mac_drv: mac driver + *@cmd:ethtool cmd + *@data:data for value of regs + */ +static void hns_xgmac_get_regs(void *mac_drv, void *data) +{ + u32 i = 0; + struct mac_driver *drv = (struct mac_driver *)mac_drv; + u32 *regs = data; + u64 qtmp; + + /* base config registers */ + regs[0] = dsaf_read_dev(drv, XGMAC_INT_STATUS_REG); + regs[1] = dsaf_read_dev(drv, XGMAC_INT_ENABLE_REG); + regs[2] = dsaf_read_dev(drv, XGMAC_INT_SET_REG); + regs[3] = dsaf_read_dev(drv, XGMAC_IERR_U_INFO_REG); + regs[4] = dsaf_read_dev(drv, XGMAC_OVF_INFO_REG); + regs[5] = dsaf_read_dev(drv, XGMAC_OVF_CNT_REG); + regs[6] = dsaf_read_dev(drv, XGMAC_PORT_MODE_REG); + regs[7] = dsaf_read_dev(drv, XGMAC_CLK_ENABLE_REG); + regs[8] = dsaf_read_dev(drv, XGMAC_RESET_REG); + regs[9] = dsaf_read_dev(drv, XGMAC_LINK_CONTROL_REG); + regs[10] = dsaf_read_dev(drv, XGMAC_LINK_STATUS_REG); + + regs[11] = dsaf_read_dev(drv, XGMAC_SPARE_REG); + regs[12] = dsaf_read_dev(drv, XGMAC_SPARE_CNT_REG); + regs[13] = dsaf_read_dev(drv, XGMAC_MAC_ENABLE_REG); + regs[14] = dsaf_read_dev(drv, XGMAC_MAC_CONTROL_REG); + regs[15] = dsaf_read_dev(drv, XGMAC_MAC_IPG_REG); + regs[16] = dsaf_read_dev(drv, XGMAC_MAC_MSG_CRC_EN_REG); + regs[17] = dsaf_read_dev(drv, XGMAC_MAC_MSG_IMG_REG); + regs[18] = dsaf_read_dev(drv, XGMAC_MAC_MSG_FC_CFG_REG); + regs[19] = dsaf_read_dev(drv, XGMAC_MAC_MSG_TC_CFG_REG); + regs[20] = dsaf_read_dev(drv, XGMAC_MAC_PAD_SIZE_REG); + regs[21] = dsaf_read_dev(drv, XGMAC_MAC_MIN_PKT_SIZE_REG); + regs[22] = dsaf_read_dev(drv, XGMAC_MAC_MAX_PKT_SIZE_REG); + regs[23] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_CTRL_REG); + regs[24] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_TIME_REG); + regs[25] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_GAP_REG); + regs[26] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_LOCAL_MAC_H_REG); + regs[27] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_LOCAL_MAC_L_REG); + regs[28] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_PEER_MAC_H_REG); + regs[29] = dsaf_read_dev(drv, XGMAC_MAC_PAUSE_PEER_MAC_L_REG); + regs[30] = dsaf_read_dev(drv, XGMAC_MAC_PFC_PRI_EN_REG); + regs[31] = dsaf_read_dev(drv, XGMAC_MAC_1588_CTRL_REG); + regs[32] = dsaf_read_dev(drv, XGMAC_MAC_1588_TX_PORT_DLY_REG); + regs[33] = dsaf_read_dev(drv, XGMAC_MAC_1588_RX_PORT_DLY_REG); + regs[34] = dsaf_read_dev(drv, XGMAC_MAC_1588_ASYM_DLY_REG); + regs[35] = dsaf_read_dev(drv, XGMAC_MAC_1588_ADJUST_CFG_REG); + + regs[36] = dsaf_read_dev(drv, XGMAC_MAC_Y1731_ETH_TYPE_REG); + regs[37] = dsaf_read_dev(drv, XGMAC_MAC_MIB_CONTROL_REG); + regs[38] = dsaf_read_dev(drv, XGMAC_MAC_WAN_RATE_ADJUST_REG); + regs[39] = dsaf_read_dev(drv, XGMAC_MAC_TX_ERR_MARK_REG); + regs[40] = dsaf_read_dev(drv, XGMAC_MAC_TX_LF_RF_CONTROL_REG); + regs[41] = dsaf_read_dev(drv, XGMAC_MAC_RX_LF_RF_STATUS_REG); + regs[42] = dsaf_read_dev(drv, XGMAC_MAC_TX_RUNT_PKT_CNT_REG); + regs[43] = dsaf_read_dev(drv, XGMAC_MAC_RX_RUNT_PKT_CNT_REG); + regs[44] = dsaf_read_dev(drv, XGMAC_MAC_RX_PREAM_ERR_PKT_CNT_REG); + regs[45] = dsaf_read_dev(drv, XGMAC_MAC_TX_LF_RF_TERM_PKT_CNT_REG); + regs[46] = dsaf_read_dev(drv, XGMAC_MAC_TX_SN_MISMATCH_PKT_CNT_REG); + regs[47] = dsaf_read_dev(drv, XGMAC_MAC_RX_ERR_MSG_CNT_REG); + regs[48] = dsaf_read_dev(drv, XGMAC_MAC_RX_ERR_EFD_CNT_REG); + regs[49] = dsaf_read_dev(drv, XGMAC_MAC_ERR_INFO_REG); + regs[50] = dsaf_read_dev(drv, XGMAC_MAC_DBG_INFO_REG); + + regs[51] = dsaf_read_dev(drv, XGMAC_PCS_BASER_SYNC_THD_REG); + regs[52] = dsaf_read_dev(drv, XGMAC_PCS_STATUS1_REG); + regs[53] = dsaf_read_dev(drv, XGMAC_PCS_BASER_STATUS1_REG); + regs[54] = dsaf_read_dev(drv, XGMAC_PCS_BASER_STATUS2_REG); + regs[55] = dsaf_read_dev(drv, XGMAC_PCS_BASER_SEEDA_0_REG); + regs[56] = dsaf_read_dev(drv, XGMAC_PCS_BASER_SEEDA_1_REG); + regs[57] = dsaf_read_dev(drv, XGMAC_PCS_BASER_SEEDB_0_REG); + regs[58] = dsaf_read_dev(drv, XGMAC_PCS_BASER_SEEDB_1_REG); + regs[59] = dsaf_read_dev(drv, XGMAC_PCS_BASER_TEST_CONTROL_REG); + regs[60] = dsaf_read_dev(drv, XGMAC_PCS_BASER_TEST_ERR_CNT_REG); + regs[61] = dsaf_read_dev(drv, XGMAC_PCS_DBG_INFO_REG); + regs[62] = dsaf_read_dev(drv, XGMAC_PCS_DBG_INFO1_REG); + regs[63] = dsaf_read_dev(drv, XGMAC_PCS_DBG_INFO2_REG); + regs[64] = dsaf_read_dev(drv, XGMAC_PCS_DBG_INFO3_REG); + + regs[65] = dsaf_read_dev(drv, XGMAC_PMA_ENABLE_REG); + regs[66] = dsaf_read_dev(drv, XGMAC_PMA_CONTROL_REG); + regs[67] = dsaf_read_dev(drv, XGMAC_PMA_SIGNAL_STATUS_REG); + regs[68] = dsaf_read_dev(drv, XGMAC_PMA_DBG_INFO_REG); + regs[69] = dsaf_read_dev(drv, XGMAC_PMA_FEC_ABILITY_REG); + regs[70] = dsaf_read_dev(drv, XGMAC_PMA_FEC_CONTROL_REG); + regs[71] = dsaf_read_dev(drv, XGMAC_PMA_FEC_CORR_BLOCK_CNT__REG); + regs[72] = dsaf_read_dev(drv, XGMAC_PMA_FEC_UNCORR_BLOCK_CNT__REG); + + /* status registers */ +#define hns_xgmac_cpy_q(p, q) \ + do {\ + *(p) = (u32)(q);\ + *((p) + 1) = (u32)((q) >> 32);\ + } while (0) + + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_FRAGMENT); + hns_xgmac_cpy_q(®s[73], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_UNDERSIZE); + hns_xgmac_cpy_q(®s[75], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_UNDERMIN); + hns_xgmac_cpy_q(®s[77], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_64OCTETS); + hns_xgmac_cpy_q(®s[79], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_65TO127OCTETS); + hns_xgmac_cpy_q(®s[81], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_128TO255OCTETS); + hns_xgmac_cpy_q(®s[83], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_256TO511OCTETS); + hns_xgmac_cpy_q(®s[85], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_512TO1023OCTETS); + hns_xgmac_cpy_q(®s[87], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_1024TO1518OCTETS); + hns_xgmac_cpy_q(®s[89], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_1519TOMAXOCTETS); + hns_xgmac_cpy_q(®s[91], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_1519TOMAXOCTETSOK); + hns_xgmac_cpy_q(®s[93], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_OVERSIZE); + hns_xgmac_cpy_q(®s[95], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PKTS_JABBER); + hns_xgmac_cpy_q(®s[97], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_GOODPKTS); + hns_xgmac_cpy_q(®s[99], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_GOODOCTETS); + hns_xgmac_cpy_q(®s[101], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_TOTAL_PKTS); + hns_xgmac_cpy_q(®s[103], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_TOTALOCTETS); + hns_xgmac_cpy_q(®s[105], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_UNICASTPKTS); + hns_xgmac_cpy_q(®s[107], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_MULTICASTPKTS); + hns_xgmac_cpy_q(®s[109], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_BROADCASTPKTS); + hns_xgmac_cpy_q(®s[111], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI0PAUSEPKTS); + hns_xgmac_cpy_q(®s[113], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI1PAUSEPKTS); + hns_xgmac_cpy_q(®s[115], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI2PAUSEPKTS); + hns_xgmac_cpy_q(®s[117], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI3PAUSEPKTS); + hns_xgmac_cpy_q(®s[119], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI4PAUSEPKTS); + hns_xgmac_cpy_q(®s[121], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI5PAUSEPKTS); + hns_xgmac_cpy_q(®s[123], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI6PAUSEPKTS); + hns_xgmac_cpy_q(®s[125], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_PRI7PAUSEPKTS); + hns_xgmac_cpy_q(®s[127], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_MACCTRLPKTS); + hns_xgmac_cpy_q(®s[129], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_1731PKTS); + hns_xgmac_cpy_q(®s[131], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_1588PKTS); + hns_xgmac_cpy_q(®s[133], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_FROMAPPGOODPKTS); + hns_xgmac_cpy_q(®s[135], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_FROMAPPBADPKTS); + hns_xgmac_cpy_q(®s[137], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_ERRALLPKTS); + hns_xgmac_cpy_q(®s[139], qtmp); + + /* RX */ + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_FRAGMENT); + hns_xgmac_cpy_q(®s[141], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTSUNDERSIZE); + hns_xgmac_cpy_q(®s[143], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_UNDERMIN); + hns_xgmac_cpy_q(®s[145], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_64OCTETS); + hns_xgmac_cpy_q(®s[147], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_65TO127OCTETS); + hns_xgmac_cpy_q(®s[149], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_128TO255OCTETS); + hns_xgmac_cpy_q(®s[151], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_256TO511OCTETS); + hns_xgmac_cpy_q(®s[153], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_512TO1023OCTETS); + hns_xgmac_cpy_q(®s[155], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_1024TO1518OCTETS); + hns_xgmac_cpy_q(®s[157], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_1519TOMAXOCTETS); + hns_xgmac_cpy_q(®s[159], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_1519TOMAXOCTETSOK); + hns_xgmac_cpy_q(®s[161], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_OVERSIZE); + hns_xgmac_cpy_q(®s[163], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PKTS_JABBER); + hns_xgmac_cpy_q(®s[165], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_GOODPKTS); + hns_xgmac_cpy_q(®s[167], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_GOODOCTETS); + hns_xgmac_cpy_q(®s[169], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_TOTAL_PKTS); + hns_xgmac_cpy_q(®s[171], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_TOTALOCTETS); + hns_xgmac_cpy_q(®s[173], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_UNICASTPKTS); + hns_xgmac_cpy_q(®s[175], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_MULTICASTPKTS); + hns_xgmac_cpy_q(®s[177], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_BROADCASTPKTS); + hns_xgmac_cpy_q(®s[179], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI0PAUSEPKTS); + hns_xgmac_cpy_q(®s[181], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI1PAUSEPKTS); + hns_xgmac_cpy_q(®s[183], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI2PAUSEPKTS); + hns_xgmac_cpy_q(®s[185], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI3PAUSEPKTS); + hns_xgmac_cpy_q(®s[187], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI4PAUSEPKTS); + hns_xgmac_cpy_q(®s[189], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI5PAUSEPKTS); + hns_xgmac_cpy_q(®s[191], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI6PAUSEPKTS); + hns_xgmac_cpy_q(®s[193], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_PRI7PAUSEPKTS); + hns_xgmac_cpy_q(®s[195], qtmp); + + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_MACCTRLPKTS); + hns_xgmac_cpy_q(®s[197], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_SENDAPPGOODPKTS); + hns_xgmac_cpy_q(®s[199], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_TX_SENDAPPBADPKTS); + hns_xgmac_cpy_q(®s[201], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_1731PKTS); + hns_xgmac_cpy_q(®s[203], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_SYMBOLERRPKTS); + hns_xgmac_cpy_q(®s[205], qtmp); + qtmp = hns_mac_reg_read64(drv, XGMAC_RX_FCSERRPKTS); + hns_xgmac_cpy_q(®s[207], qtmp); + + /* mark end of mac regs */ + for (i = 208; i < 214; i++) + regs[i] = 0xaaaaaaaa; +} + +/** + *hns_xgmac_get_stats - get xgmac statistic + *@mac_drv: mac driver + *@data:data for value of stats regs + */ +static void hns_xgmac_get_stats(void *mac_drv, u64 *data) +{ + u32 i; + u64 *buf = data; + struct mac_driver *drv = (struct mac_driver *)mac_drv; + struct mac_hw_stats *hw_stats = NULL; + + hw_stats = &drv->mac_cb->hw_stats; + + for (i = 0; i < ARRAY_SIZE(g_xgmac_stats_string); i++) { + buf[i] = DSAF_STATS_READ(hw_stats, + g_xgmac_stats_string[i].offset); + } +} + +/** + *hns_xgmac_get_strings - get xgmac strings name + *@stringset: type of values in data + *@data:data for value of string name + */ +static void hns_xgmac_get_strings(u32 stringset, u8 *data) +{ + char *buff = (char *)data; + u32 i; + + if (stringset != ETH_SS_STATS) + return; + + for (i = 0; i < ARRAY_SIZE(g_xgmac_stats_string); i++) { + snprintf(buff, ETH_GSTRING_LEN, g_xgmac_stats_string[i].desc); + buff = buff + ETH_GSTRING_LEN; + } +} + +/** + *hns_xgmac_get_sset_count - get xgmac string set count + *@stringset: type of values in data + *return xgmac string set count + */ +static int hns_xgmac_get_sset_count(int stringset) +{ + if (stringset == ETH_SS_STATS) + return ARRAY_SIZE(g_xgmac_stats_string); + + return 0; +} + +/** + *hns_xgmac_get_regs_count - get xgmac regs count + *return xgmac regs count + */ +static int hns_xgmac_get_regs_count(void) +{ + return ETH_XGMAC_DUMP_NUM; +} + +void *hns_xgmac_config(struct hns_mac_cb *mac_cb, struct mac_params *mac_param) +{ + struct mac_driver *mac_drv; + + mac_drv = devm_kzalloc(mac_cb->dev, sizeof(*mac_drv), GFP_KERNEL); + if (!mac_drv) + return NULL; + + mac_drv->mac_init = hns_xgmac_init; + mac_drv->mac_enable = hns_xgmac_enable; + mac_drv->mac_disable = hns_xgmac_disable; + + mac_drv->mac_id = mac_param->mac_id; + mac_drv->mac_mode = mac_param->mac_mode; + mac_drv->io_base = mac_param->vaddr; + mac_drv->dev = mac_param->dev; + mac_drv->mac_cb = mac_cb; + + mac_drv->set_mac_addr = hns_xgmac_set_pausefrm_mac_addr; + mac_drv->set_an_mode = NULL; + mac_drv->config_loopback = NULL; + mac_drv->config_pad_and_crc = hns_xgmac_config_pad_and_crc; + mac_drv->config_half_duplex = NULL; + mac_drv->set_rx_ignore_pause_frames = + hns_xgmac_set_rx_ignore_pause_frames; + mac_drv->mac_get_id = hns_xgmac_get_id; + mac_drv->mac_free = hns_xgmac_free; + mac_drv->adjust_link = NULL; + mac_drv->set_tx_auto_pause_frames = hns_xgmac_set_tx_auto_pause_frames; + mac_drv->config_max_frame_length = hns_xgmac_config_max_frame_length; + mac_drv->mac_pausefrm_cfg = hns_xgmac_pausefrm_cfg; + mac_drv->autoneg_stat = NULL; + mac_drv->get_info = hns_xgmac_get_info; + mac_drv->get_pause_enable = hns_xgmac_get_pausefrm_cfg; + mac_drv->get_link_status = hns_xgmac_get_link_status; + mac_drv->get_regs = hns_xgmac_get_regs; + mac_drv->get_ethtool_stats = hns_xgmac_get_stats; + mac_drv->get_sset_count = hns_xgmac_get_sset_count; + mac_drv->get_regs_count = hns_xgmac_get_regs_count; + mac_drv->get_strings = hns_xgmac_get_strings; + mac_drv->update_stats = hns_xgmac_update_stats; + + return (void *)mac_drv; +} diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h new file mode 100644 index 000000000000..139f7297c7b4 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _HNS_XGMAC_H +#define _HNS_XGMAC_H + +#define ETH_XGMAC_DUMP_NUM (214) + +#endif -- cgit v1.2.3 From b5996f11ea5496d0445078f47d22c987888ed467 Mon Sep 17 00:00:00 2001 From: huangdaode Date: Thu, 17 Sep 2015 14:51:50 +0800 Subject: net: add Hisilicon Network Subsystem basic ethernet support This is to add basic ethernet support for HNS. It is one of the way to use the HNS acceleration engine. But most of the decoding/encoding capability of the AE cannot be used in this way. This submit contains the basic feature as a ethernet driver. More will be added later. Signed-off-by: huangdaode Signed-off-by: Kenneth Lee Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/Kconfig | 8 + drivers/net/ethernet/hisilicon/hns/Makefile | 3 + drivers/net/ethernet/hisilicon/hns/hns_enet.c | 1646 ++++++++++++++++++++++ drivers/net/ethernet/hisilicon/hns/hns_enet.h | 84 ++ drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 1230 ++++++++++++++++ 5 files changed, 2971 insertions(+) create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_enet.c create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_enet.h create mode 100644 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig index aae2c479a7d5..165b5a8aa2ea 100644 --- a/drivers/net/ethernet/hisilicon/Kconfig +++ b/drivers/net/ethernet/hisilicon/Kconfig @@ -55,4 +55,12 @@ config HNS_DSAF acceleration engine support. The engine is used in Hisilicon hip05, Hi1610 and further ICT SoC +config HNS_ENET + tristate "Hisilicon HNS Ethernet Device Support" + select PHYLIB + select HNS + ---help--- + This selects the general ethernet driver for HNS. This module make + use of any HNS AE driver, such as HNS_DSAF + endif # NET_VENDOR_HISILICON diff --git a/drivers/net/ethernet/hisilicon/hns/Makefile b/drivers/net/ethernet/hisilicon/hns/Makefile index 0516af7e1a19..6010c83e38d8 100644 --- a/drivers/net/ethernet/hisilicon/hns/Makefile +++ b/drivers/net/ethernet/hisilicon/hns/Makefile @@ -7,3 +7,6 @@ obj-$(CONFIG_HNS) += hnae.o obj-$(CONFIG_HNS_DSAF) += hns_dsaf.o hns_dsaf-objs = hns_ae_adapt.o hns_dsaf_gmac.o hns_dsaf_mac.o hns_dsaf_misc.o \ hns_dsaf_main.o hns_dsaf_ppe.o hns_dsaf_rcb.o hns_dsaf_xgmac.o + +obj-$(CONFIG_HNS_ENET) += hns_enet_drv.o +hns_enet_drv-objs = hns_enet.o hns_ethtool.o diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c new file mode 100644 index 000000000000..0713ced120b6 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -0,0 +1,1646 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hnae.h" +#include "hns_enet.h" + +#define NIC_MAX_Q_PER_VF 16 +#define HNS_NIC_TX_TIMEOUT (5 * HZ) + +#define SERVICE_TIMER_HZ (1 * HZ) + +#define NIC_TX_CLEAN_MAX_NUM 256 +#define NIC_RX_CLEAN_MAX_NUM 64 + +#define RCB_ERR_PRINT_CYCLE 1000 + +#define RCB_IRQ_NOT_INITED 0 +#define RCB_IRQ_INITED 1 + +static void fill_desc(struct hnae_ring *ring, void *priv, + int size, dma_addr_t dma, int frag_end, + int buf_num, enum hns_desc_type type) +{ + struct hnae_desc *desc = &ring->desc[ring->next_to_use]; + struct hnae_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use]; + struct sk_buff *skb; + __be16 protocol; + u32 ip_offset; + u32 asid_bufnum_pid = 0; + u32 flag_ipoffset = 0; + + desc_cb->priv = priv; + desc_cb->length = size; + desc_cb->dma = dma; + desc_cb->type = type; + + desc->addr = cpu_to_le64(dma); + desc->tx.send_size = cpu_to_le16((u16)size); + + /*config bd buffer end */ + flag_ipoffset |= 1 << HNS_TXD_VLD_B; + + asid_bufnum_pid |= buf_num << HNS_TXD_BUFNUM_S; + + if (type == DESC_TYPE_SKB) { + skb = (struct sk_buff *)priv; + + if (skb->ip_summed == CHECKSUM_PARTIAL) { + protocol = skb->protocol; + ip_offset = ETH_HLEN; + + /*if it is a SW VLAN check the next protocol*/ + if (protocol == htons(ETH_P_8021Q)) { + ip_offset += VLAN_HLEN; + protocol = vlan_get_protocol(skb); + skb->protocol = protocol; + } + + if (skb->protocol == htons(ETH_P_IP)) { + flag_ipoffset |= 1 << HNS_TXD_L3CS_B; + /* check for tcp/udp header */ + flag_ipoffset |= 1 << HNS_TXD_L4CS_B; + + } else if (skb->protocol == htons(ETH_P_IPV6)) { + /* ipv6 has not l3 cs, check for L4 header */ + flag_ipoffset |= 1 << HNS_TXD_L4CS_B; + } + + flag_ipoffset |= ip_offset << HNS_TXD_IPOFFSET_S; + } + } + + flag_ipoffset |= frag_end << HNS_TXD_FE_B; + + desc->tx.asid_bufnum_pid = cpu_to_le16(asid_bufnum_pid); + desc->tx.flag_ipoffset = cpu_to_le32(flag_ipoffset); + + ring_ptr_move_fw(ring, next_to_use); +} + +static void unfill_desc(struct hnae_ring *ring) +{ + ring_ptr_move_bw(ring, next_to_use); +} + +int hns_nic_net_xmit_hw(struct net_device *ndev, + struct sk_buff *skb, + struct hns_nic_ring_data *ring_data) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct device *dev = priv->dev; + struct hnae_ring *ring = ring_data->ring; + struct netdev_queue *dev_queue; + struct skb_frag_struct *frag; + int buf_num; + dma_addr_t dma; + int size, next_to_use; + int i, j; + struct sk_buff *new_skb; + + assert(ring->max_desc_num_per_pkt <= ring->desc_num); + + /* no. of segments (plus a header) */ + buf_num = skb_shinfo(skb)->nr_frags + 1; + + if (unlikely(buf_num > ring->max_desc_num_per_pkt)) { + if (ring_space(ring) < 1) { + ring->stats.tx_busy++; + goto out_net_tx_busy; + } + + new_skb = skb_copy(skb, GFP_ATOMIC); + if (!new_skb) { + ring->stats.sw_err_cnt++; + netdev_err(ndev, "no memory to xmit!\n"); + goto out_err_tx_ok; + } + + dev_kfree_skb_any(skb); + skb = new_skb; + buf_num = 1; + assert(skb_shinfo(skb)->nr_frags == 1); + } else if (buf_num > ring_space(ring)) { + ring->stats.tx_busy++; + goto out_net_tx_busy; + } + next_to_use = ring->next_to_use; + + /* fill the first part */ + size = skb_headlen(skb); + dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma)) { + netdev_err(ndev, "TX head DMA map failed\n"); + ring->stats.sw_err_cnt++; + goto out_err_tx_ok; + } + fill_desc(ring, skb, size, dma, buf_num == 1 ? 1 : 0, buf_num, + DESC_TYPE_SKB); + + /* fill the fragments */ + for (i = 1; i < buf_num; i++) { + frag = &skb_shinfo(skb)->frags[i - 1]; + size = skb_frag_size(frag); + dma = skb_frag_dma_map(dev, frag, 0, size, DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma)) { + netdev_err(ndev, "TX frag(%d) DMA map failed\n", i); + ring->stats.sw_err_cnt++; + goto out_map_frag_fail; + } + fill_desc(ring, skb_frag_page(frag), size, dma, + buf_num - 1 == i ? 1 : 0, buf_num, DESC_TYPE_PAGE); + } + + /*complete translate all packets*/ + dev_queue = netdev_get_tx_queue(ndev, skb->queue_mapping); + netdev_tx_sent_queue(dev_queue, skb->len); + + wmb(); /* commit all data before submit */ + assert(skb->queue_mapping < priv->ae_handle->q_num); + hnae_queue_xmit(priv->ae_handle->qs[skb->queue_mapping], buf_num); + ring->stats.tx_pkts++; + ring->stats.tx_bytes += skb->len; + + return NETDEV_TX_OK; + +out_map_frag_fail: + + for (j = i - 1; j > 0; j--) { + unfill_desc(ring); + next_to_use = ring->next_to_use; + dma_unmap_page(dev, ring->desc_cb[next_to_use].dma, + ring->desc_cb[next_to_use].length, + DMA_TO_DEVICE); + } + + unfill_desc(ring); + next_to_use = ring->next_to_use; + dma_unmap_single(dev, ring->desc_cb[next_to_use].dma, + ring->desc_cb[next_to_use].length, DMA_TO_DEVICE); + +out_err_tx_ok: + + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + +out_net_tx_busy: + + netif_stop_subqueue(ndev, skb->queue_mapping); + + /* Herbert's original patch had: + * smp_mb__after_netif_stop_queue(); + * but since that doesn't exist yet, just open code it. + */ + smp_mb(); + return NETDEV_TX_BUSY; +} + +/** + * hns_nic_get_headlen - determine size of header for RSC/LRO/GRO/FCOE + * @data: pointer to the start of the headers + * @max: total length of section to find headers in + * + * This function is meant to determine the length of headers that will + * be recognized by hardware for LRO, GRO, and RSC offloads. The main + * motivation of doing this is to only perform one pull for IPv4 TCP + * packets so that we can do basic things like calculating the gso_size + * based on the average data per packet. + **/ +static unsigned int hns_nic_get_headlen(unsigned char *data, u32 flag, + unsigned int max_size) +{ + unsigned char *network; + u8 hlen; + + /* this should never happen, but better safe than sorry */ + if (max_size < ETH_HLEN) + return max_size; + + /* initialize network frame pointer */ + network = data; + + /* set first protocol and move network header forward */ + network += ETH_HLEN; + + /* handle any vlan tag if present */ + if (hnae_get_field(flag, HNS_RXD_VLAN_M, HNS_RXD_VLAN_S) + == HNS_RX_FLAG_VLAN_PRESENT) { + if ((typeof(max_size))(network - data) > (max_size - VLAN_HLEN)) + return max_size; + + network += VLAN_HLEN; + } + + /* handle L3 protocols */ + if (hnae_get_field(flag, HNS_RXD_L3ID_M, HNS_RXD_L3ID_S) + == HNS_RX_FLAG_L3ID_IPV4) { + if ((typeof(max_size))(network - data) > + (max_size - sizeof(struct iphdr))) + return max_size; + + /* access ihl as a u8 to avoid unaligned access on ia64 */ + hlen = (network[0] & 0x0F) << 2; + + /* verify hlen meets minimum size requirements */ + if (hlen < sizeof(struct iphdr)) + return network - data; + + /* record next protocol if header is present */ + } else if (hnae_get_field(flag, HNS_RXD_L3ID_M, HNS_RXD_L3ID_S) + == HNS_RX_FLAG_L3ID_IPV6) { + if ((typeof(max_size))(network - data) > + (max_size - sizeof(struct ipv6hdr))) + return max_size; + + /* record next protocol */ + hlen = sizeof(struct ipv6hdr); + } else { + return network - data; + } + + /* relocate pointer to start of L4 header */ + network += hlen; + + /* finally sort out TCP/UDP */ + if (hnae_get_field(flag, HNS_RXD_L4ID_M, HNS_RXD_L4ID_S) + == HNS_RX_FLAG_L4ID_TCP) { + if ((typeof(max_size))(network - data) > + (max_size - sizeof(struct tcphdr))) + return max_size; + + /* access doff as a u8 to avoid unaligned access on ia64 */ + hlen = (network[12] & 0xF0) >> 2; + + /* verify hlen meets minimum size requirements */ + if (hlen < sizeof(struct tcphdr)) + return network - data; + + network += hlen; + } else if (hnae_get_field(flag, HNS_RXD_L4ID_M, HNS_RXD_L4ID_S) + == HNS_RX_FLAG_L4ID_UDP) { + if ((typeof(max_size))(network - data) > + (max_size - sizeof(struct udphdr))) + return max_size; + + network += sizeof(struct udphdr); + } + + /* If everything has gone correctly network should be the + * data section of the packet and will be the end of the header. + * If not then it probably represents the end of the last recognized + * header. + */ + if ((typeof(max_size))(network - data) < max_size) + return network - data; + else + return max_size; +} + +static void +hns_nic_reuse_page(struct hnae_desc_cb *desc_cb, int tsize, int last_offset) +{ + /* avoid re-using remote pages,flag default unreuse */ + if (likely(page_to_nid(desc_cb->priv) == numa_node_id())) { + /* move offset up to the next cache line */ + desc_cb->page_offset += tsize; + + if (desc_cb->page_offset <= last_offset) { + desc_cb->reuse_flag = 1; + /* bump ref count on page before it is given*/ + get_page(desc_cb->priv); + } + } +} + +static int hns_nic_poll_rx_skb(struct hns_nic_ring_data *ring_data, + struct sk_buff **out_skb, int *out_bnum) +{ + struct hnae_ring *ring = ring_data->ring; + struct net_device *ndev = ring_data->napi.dev; + struct sk_buff *skb; + struct hnae_desc *desc; + struct hnae_desc_cb *desc_cb; + unsigned char *va; + int bnum, length, size, i, truesize, last_offset; + int pull_len; + u32 bnum_flag; + + last_offset = hnae_page_size(ring) - hnae_buf_size(ring); + desc = &ring->desc[ring->next_to_clean]; + desc_cb = &ring->desc_cb[ring->next_to_clean]; + length = le16_to_cpu(desc->rx.pkt_len); + bnum_flag = le32_to_cpu(desc->rx.ipoff_bnum_pid_flag); + bnum = hnae_get_field(bnum_flag, HNS_RXD_BUFNUM_M, HNS_RXD_BUFNUM_S); + *out_bnum = bnum; + va = (unsigned char *)desc_cb->buf + desc_cb->page_offset; + + skb = *out_skb = napi_alloc_skb(&ring_data->napi, HNS_RX_HEAD_SIZE); + if (unlikely(!skb)) { + netdev_err(ndev, "alloc rx skb fail\n"); + ring->stats.sw_err_cnt++; + return -ENOMEM; + } + + if (length <= HNS_RX_HEAD_SIZE) { + memcpy(__skb_put(skb, length), va, ALIGN(length, sizeof(long))); + + /* we can reuse buffer as-is, just make sure it is local */ + if (likely(page_to_nid(desc_cb->priv) == numa_node_id())) + desc_cb->reuse_flag = 1; + else /* this page cannot be reused so discard it */ + put_page(desc_cb->priv); + + ring_ptr_move_fw(ring, next_to_clean); + + if (unlikely(bnum != 1)) { /* check err*/ + *out_bnum = 1; + goto out_bnum_err; + } + } else { + ring->stats.seg_pkt_cnt++; + + pull_len = hns_nic_get_headlen(va, bnum_flag, HNS_RX_HEAD_SIZE); + memcpy(__skb_put(skb, pull_len), va, + ALIGN(pull_len, sizeof(long))); + + size = le16_to_cpu(desc->rx.size); + truesize = ALIGN(size, L1_CACHE_BYTES); + skb_add_rx_frag(skb, 0, desc_cb->priv, + desc_cb->page_offset + pull_len, + size - pull_len, truesize - pull_len); + + hns_nic_reuse_page(desc_cb, truesize, last_offset); + ring_ptr_move_fw(ring, next_to_clean); + + if (unlikely(bnum >= (int)MAX_SKB_FRAGS)) { /* check err*/ + *out_bnum = 1; + goto out_bnum_err; + } + for (i = 1; i < bnum; i++) { + desc = &ring->desc[ring->next_to_clean]; + desc_cb = &ring->desc_cb[ring->next_to_clean]; + size = le16_to_cpu(desc->rx.size); + truesize = ALIGN(size, L1_CACHE_BYTES); + skb_add_rx_frag(skb, i, desc_cb->priv, + desc_cb->page_offset, + size, truesize); + + hns_nic_reuse_page(desc_cb, truesize, last_offset); + ring_ptr_move_fw(ring, next_to_clean); + } + } + + /* check except process, free skb and jump the desc */ + if (unlikely((!bnum) || (bnum > ring->max_desc_num_per_pkt))) { +out_bnum_err: + *out_bnum = *out_bnum ? *out_bnum : 1; /* ntc moved,cannot 0*/ + netdev_err(ndev, "invalid bnum(%d,%d,%d,%d),%016llx,%016llx\n", + bnum, ring->max_desc_num_per_pkt, + length, (int)MAX_SKB_FRAGS, + ((u64 *)desc)[0], ((u64 *)desc)[1]); + ring->stats.err_bd_num++; + dev_kfree_skb_any(skb); + return -EDOM; + } + + bnum_flag = le32_to_cpu(desc->rx.ipoff_bnum_pid_flag); + + if (unlikely(!hnae_get_bit(bnum_flag, HNS_RXD_VLD_B))) { + netdev_err(ndev, "no valid bd,%016llx,%016llx\n", + ((u64 *)desc)[0], ((u64 *)desc)[1]); + ring->stats.non_vld_descs++; + dev_kfree_skb_any(skb); + return -EINVAL; + } + + if (unlikely((!desc->rx.pkt_len) || + hnae_get_bit(bnum_flag, HNS_RXD_DROP_B))) { + if (!(ring->stats.err_pkt_len % RCB_ERR_PRINT_CYCLE)) + netdev_dbg(ndev, + "pkt_len(%u),drop(%u),%#llx,%#llx\n", + le16_to_cpu(desc->rx.pkt_len), + hnae_get_bit(bnum_flag, HNS_RXD_DROP_B), + ((u64 *)desc)[0], ((u64 *)desc)[1]); + ring->stats.err_pkt_len++; + dev_kfree_skb_any(skb); + return -EFAULT; + } + + if (unlikely(hnae_get_bit(bnum_flag, HNS_RXD_L2E_B))) { + if (!(ring->stats.l2_err % RCB_ERR_PRINT_CYCLE)) + netdev_dbg(ndev, "L2 check err,%#llx,%#llx\n", + ((u64 *)desc)[0], ((u64 *)desc)[1]); + ring->stats.l2_err++; + dev_kfree_skb_any(skb); + return -EFAULT; + } + + ring->stats.rx_pkts++; + ring->stats.rx_bytes += skb->len; + + if (unlikely(hnae_get_bit(bnum_flag, HNS_RXD_L3E_B) || + hnae_get_bit(bnum_flag, HNS_RXD_L4E_B))) { + if (!(ring->stats.l3l4_csum_err % RCB_ERR_PRINT_CYCLE)) + netdev_dbg(ndev, + "check err(%#x),%#llx,%#llx\n", + hnae_get_bit(bnum_flag, HNS_RXD_L3E_B) | + hnae_get_bit(bnum_flag, HNS_RXD_L4E_B), + ((u64 *)desc)[0], ((u64 *)desc)[1]); + ring->stats.l3l4_csum_err++; + return 0; + } + + skb->ip_summed = CHECKSUM_UNNECESSARY; + + return 0; +} + +static void +hns_nic_alloc_rx_buffers(struct hns_nic_ring_data *ring_data, int cleand_count) +{ + int i, ret; + struct hnae_desc_cb res_cbs; + struct hnae_desc_cb *desc_cb; + struct hnae_ring *ring = ring_data->ring; + struct net_device *ndev = ring_data->napi.dev; + + for (i = 0; i < cleand_count; i++) { + desc_cb = &ring->desc_cb[ring->next_to_use]; + if (desc_cb->reuse_flag) { + ring->stats.reuse_pg_cnt++; + hnae_reuse_buffer(ring, ring->next_to_use); + } else { + ret = hnae_reserve_buffer_map(ring, &res_cbs); + if (ret) { + ring->stats.sw_err_cnt++; + netdev_err(ndev, "hnae reserve buffer map failed.\n"); + break; + } + hnae_replace_buffer(ring, ring->next_to_use, &res_cbs); + } + + ring_ptr_move_fw(ring, next_to_use); + } + + wmb(); /* make all data has been write before submit */ + writel_relaxed(i, ring->io_base + RCB_REG_HEAD); +} + +/* return error number for error or number of desc left to take + */ +static void hns_nic_rx_up_pro(struct hns_nic_ring_data *ring_data, + struct sk_buff *skb) +{ + struct net_device *ndev = ring_data->napi.dev; + + skb->protocol = eth_type_trans(skb, ndev); + (void)napi_gro_receive(&ring_data->napi, skb); + ndev->last_rx = jiffies; +} + +static int hns_nic_rx_poll_one(struct hns_nic_ring_data *ring_data, + int budget, void *v) +{ + struct hnae_ring *ring = ring_data->ring; + struct sk_buff *skb; + int num, bnum, ex_num; +#define RCB_NOF_ALLOC_RX_BUFF_ONCE 16 + int recv_pkts, recv_bds, clean_count, err; + + num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM); + rmb(); /* make sure num taken effect before the other data is touched */ + + recv_pkts = 0, recv_bds = 0, clean_count = 0; +recv: + while (recv_pkts < budget && recv_bds < num) { + /* reuse or realloc buffers*/ + if (clean_count >= RCB_NOF_ALLOC_RX_BUFF_ONCE) { + hns_nic_alloc_rx_buffers(ring_data, clean_count); + clean_count = 0; + } + + /* poll one pkg*/ + err = hns_nic_poll_rx_skb(ring_data, &skb, &bnum); + if (unlikely(!skb)) /* this fault cannot be repaired */ + break; + + recv_bds += bnum; + clean_count += bnum; + if (unlikely(err)) { /* do jump the err */ + recv_pkts++; + continue; + } + + /* do update ip stack process*/ + ((void (*)(struct hns_nic_ring_data *, struct sk_buff *))v)( + ring_data, skb); + recv_pkts++; + } + + /* make all data has been write before submit */ + if (clean_count > 0) { + hns_nic_alloc_rx_buffers(ring_data, clean_count); + clean_count = 0; + } + + if (recv_pkts < budget) { + ex_num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM); + rmb(); /*complete read rx ring bd number*/ + if (ex_num > 0) { + num += ex_num; + goto recv; + } + } + + return recv_pkts; +} + +static void hns_nic_rx_fini_pro(struct hns_nic_ring_data *ring_data) +{ + struct hnae_ring *ring = ring_data->ring; + int num = 0; + + /* for hardware bug fixed */ + num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM); + + if (num > 0) { + ring_data->ring->q->handle->dev->ops->toggle_ring_irq( + ring_data->ring, 1); + + napi_schedule(&ring_data->napi); + } +} + +static inline void hns_nic_reclaim_one_desc(struct hnae_ring *ring, + int *bytes, int *pkts) +{ + struct hnae_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_clean]; + + (*pkts) += (desc_cb->type == DESC_TYPE_SKB); + (*bytes) += desc_cb->length; + /* desc_cb will be cleaned, after hnae_free_buffer_detach*/ + hnae_free_buffer_detach(ring, ring->next_to_clean); + + ring_ptr_move_fw(ring, next_to_clean); +} + +static int is_valid_clean_head(struct hnae_ring *ring, int h) +{ + int u = ring->next_to_use; + int c = ring->next_to_clean; + + if (unlikely(h > ring->desc_num)) + return 0; + + assert(u > 0 && u < ring->desc_num); + assert(c > 0 && c < ring->desc_num); + assert(u != c && h != c); /* must be checked before call this func */ + + return u > c ? (h > c && h <= u) : (h > c || h <= u); +} + +/* netif_tx_lock will turn down the performance, set only when necessary */ +#ifdef CONFIG_NET_POLL_CONTROLLER +#define NETIF_TX_LOCK(ndev) netif_tx_lock(ndev) +#define NETIF_TX_UNLOCK(ndev) netif_tx_unlock(ndev) +#else +#define NETIF_TX_LOCK(ndev) +#define NETIF_TX_UNLOCK(ndev) +#endif +/* reclaim all desc in one budget + * return error or number of desc left + */ +static int hns_nic_tx_poll_one(struct hns_nic_ring_data *ring_data, + int budget, void *v) +{ + struct hnae_ring *ring = ring_data->ring; + struct net_device *ndev = ring_data->napi.dev; + struct netdev_queue *dev_queue; + struct hns_nic_priv *priv = netdev_priv(ndev); + int head; + int bytes, pkts; + + NETIF_TX_LOCK(ndev); + + head = readl_relaxed(ring->io_base + RCB_REG_HEAD); + rmb(); /* make sure head is ready before touch any data */ + + if (is_ring_empty(ring) || head == ring->next_to_clean) { + NETIF_TX_UNLOCK(ndev); + return 0; /* no data to poll */ + } + + if (!is_valid_clean_head(ring, head)) { + netdev_err(ndev, "wrong head (%d, %d-%d)\n", head, + ring->next_to_use, ring->next_to_clean); + ring->stats.io_err_cnt++; + NETIF_TX_UNLOCK(ndev); + return -EIO; + } + + bytes = 0; + pkts = 0; + while (head != ring->next_to_clean) + hns_nic_reclaim_one_desc(ring, &bytes, &pkts); + + NETIF_TX_UNLOCK(ndev); + + dev_queue = netdev_get_tx_queue(ndev, ring_data->queue_index); + netdev_tx_completed_queue(dev_queue, pkts, bytes); + + if (unlikely(pkts && netif_carrier_ok(ndev) && + (ring_space(ring) >= ring->max_desc_num_per_pkt * 2))) { + /* Make sure that anybody stopping the queue after this + * sees the new next_to_clean. + */ + smp_mb(); + if (netif_tx_queue_stopped(dev_queue) && + !test_bit(NIC_STATE_DOWN, &priv->state)) { + netif_tx_wake_queue(dev_queue); + ring->stats.restart_queue++; + } + } + return 0; +} + +static void hns_nic_tx_fini_pro(struct hns_nic_ring_data *ring_data) +{ + struct hnae_ring *ring = ring_data->ring; + int head = ring->next_to_clean; + + /* for hardware bug fixed */ + head = readl_relaxed(ring->io_base + RCB_REG_HEAD); + + if (head != ring->next_to_clean) { + ring_data->ring->q->handle->dev->ops->toggle_ring_irq( + ring_data->ring, 1); + + napi_schedule(&ring_data->napi); + } +} + +static void hns_nic_tx_clr_all_bufs(struct hns_nic_ring_data *ring_data) +{ + struct hnae_ring *ring = ring_data->ring; + struct net_device *ndev = ring_data->napi.dev; + struct netdev_queue *dev_queue; + int head; + int bytes, pkts; + + NETIF_TX_LOCK(ndev); + + head = ring->next_to_use; /* ntu :soft setted ring position*/ + bytes = 0; + pkts = 0; + while (head != ring->next_to_clean) + hns_nic_reclaim_one_desc(ring, &bytes, &pkts); + + NETIF_TX_UNLOCK(ndev); + + dev_queue = netdev_get_tx_queue(ndev, ring_data->queue_index); + netdev_tx_reset_queue(dev_queue); +} + +static int hns_nic_common_poll(struct napi_struct *napi, int budget) +{ + struct hns_nic_ring_data *ring_data = + container_of(napi, struct hns_nic_ring_data, napi); + int clean_complete = ring_data->poll_one( + ring_data, budget, ring_data->ex_process); + + if (clean_complete >= 0 && clean_complete < budget) { + napi_complete(napi); + ring_data->ring->q->handle->dev->ops->toggle_ring_irq( + ring_data->ring, 0); + + ring_data->fini_process(ring_data); + } + + return clean_complete; +} + +static irqreturn_t hns_irq_handle(int irq, void *dev) +{ + struct hns_nic_ring_data *ring_data = (struct hns_nic_ring_data *)dev; + + ring_data->ring->q->handle->dev->ops->toggle_ring_irq( + ring_data->ring, 1); + napi_schedule(&ring_data->napi); + + return IRQ_HANDLED; +} + +/** + *hns_nic_adjust_link - adjust net work mode by the phy stat or new param + *@ndev: net device + */ +static void hns_nic_adjust_link(struct net_device *ndev) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *h = priv->ae_handle; + + h->dev->ops->adjust_link(h, ndev->phydev->speed, ndev->phydev->duplex); +} + +/** + *hns_nic_init_phy - init phy + *@ndev: net device + *@h: ae handle + * Return 0 on success, negative on failure + */ +int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct phy_device *phy_dev = NULL; + + if (!h->phy_node) + return 0; + + if (h->phy_if != PHY_INTERFACE_MODE_XGMII) + phy_dev = of_phy_connect(ndev, h->phy_node, + hns_nic_adjust_link, 0, h->phy_if); + else + phy_dev = of_phy_attach(ndev, h->phy_node, 0, h->phy_if); + + if (unlikely(!phy_dev) || IS_ERR(phy_dev)) + return !phy_dev ? -ENODEV : PTR_ERR(phy_dev); + + phy_dev->supported &= h->if_support; + phy_dev->advertising = phy_dev->supported; + + if (h->phy_if == PHY_INTERFACE_MODE_XGMII) + phy_dev->autoneg = false; + + priv->phy = phy_dev; + + return 0; +} + +static int hns_nic_ring_open(struct net_device *netdev, int idx) +{ + struct hns_nic_priv *priv = netdev_priv(netdev); + struct hnae_handle *h = priv->ae_handle; + + napi_enable(&priv->ring_data[idx].napi); + + enable_irq(priv->ring_data[idx].ring->irq); + h->dev->ops->toggle_ring_irq(priv->ring_data[idx].ring, 0); + + return 0; +} + +static int hns_nic_net_set_mac_address(struct net_device *ndev, void *p) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *h = priv->ae_handle; + struct sockaddr *mac_addr = p; + int ret; + + if (!mac_addr || !is_valid_ether_addr((const u8 *)mac_addr->sa_data)) + return -EADDRNOTAVAIL; + + ret = h->dev->ops->set_mac_addr(h, mac_addr->sa_data); + if (ret) { + netdev_err(ndev, "set_mac_address fail, ret=%d!\n", ret); + return ret; + } + + memcpy(ndev->dev_addr, mac_addr->sa_data, ndev->addr_len); + + return 0; +} + +void hns_nic_update_stats(struct net_device *netdev) +{ + struct hns_nic_priv *priv = netdev_priv(netdev); + struct hnae_handle *h = priv->ae_handle; + + h->dev->ops->update_stats(h, &netdev->stats); +} + +/* set mac addr if it is configed. or leave it to the AE driver */ +static void hns_init_mac_addr(struct net_device *ndev) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct device_node *node = priv->dev->of_node; + const void *mac_addr_temp; + + mac_addr_temp = of_get_mac_address(node); + if (mac_addr_temp && is_valid_ether_addr(mac_addr_temp)) { + memcpy(ndev->dev_addr, mac_addr_temp, ndev->addr_len); + } else { + eth_hw_addr_random(ndev); + dev_warn(priv->dev, "No valid mac, use random mac %pM", + ndev->dev_addr); + } +} + +static void hns_nic_ring_close(struct net_device *netdev, int idx) +{ + struct hns_nic_priv *priv = netdev_priv(netdev); + struct hnae_handle *h = priv->ae_handle; + + h->dev->ops->toggle_ring_irq(priv->ring_data[idx].ring, 1); + disable_irq(priv->ring_data[idx].ring->irq); + + napi_disable(&priv->ring_data[idx].napi); +} + +static int hns_nic_init_irq(struct hns_nic_priv *priv) +{ + struct hnae_handle *h = priv->ae_handle; + struct hns_nic_ring_data *rd; + int i; + int ret; + int cpu; + cpumask_t mask; + + for (i = 0; i < h->q_num * 2; i++) { + rd = &priv->ring_data[i]; + + if (rd->ring->irq_init_flag == RCB_IRQ_INITED) + break; + + snprintf(rd->ring->ring_name, RCB_RING_NAME_LEN, + "%s-%s%d", priv->netdev->name, + (i < h->q_num ? "tx" : "rx"), rd->queue_index); + + rd->ring->ring_name[RCB_RING_NAME_LEN - 1] = '\0'; + + ret = request_irq(rd->ring->irq, + hns_irq_handle, 0, rd->ring->ring_name, rd); + if (ret) { + netdev_err(priv->netdev, "request irq(%d) fail\n", + rd->ring->irq); + return ret; + } + disable_irq(rd->ring->irq); + rd->ring->irq_init_flag = RCB_IRQ_INITED; + + /*set cpu affinity*/ + if (cpu_online(rd->queue_index)) { + cpumask_clear(&mask); + cpu = rd->queue_index; + cpumask_set_cpu(cpu, &mask); + irq_set_affinity_hint(rd->ring->irq, &mask); + } + } + + return 0; +} + +static int hns_nic_net_up(struct net_device *ndev) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *h = priv->ae_handle; + int i, j, k; + int ret; + + ret = hns_nic_init_irq(priv); + if (ret != 0) { + netdev_err(ndev, "hns init irq failed! ret=%d\n", ret); + return ret; + } + + for (i = 0; i < h->q_num * 2; i++) { + ret = hns_nic_ring_open(ndev, i); + if (ret) + goto out_has_some_queues; + } + + for (k = 0; k < h->q_num; k++) + h->dev->ops->toggle_queue_status(h->qs[k], 1); + + ret = h->dev->ops->set_mac_addr(h, ndev->dev_addr); + if (ret) + goto out_set_mac_addr_err; + + ret = h->dev->ops->start ? h->dev->ops->start(h) : 0; + if (ret) + goto out_start_err; + + if (priv->phy) + phy_start(priv->phy); + + clear_bit(NIC_STATE_DOWN, &priv->state); + (void)mod_timer(&priv->service_timer, jiffies + SERVICE_TIMER_HZ); + + return 0; + +out_start_err: + netif_stop_queue(ndev); +out_set_mac_addr_err: + for (k = 0; k < h->q_num; k++) + h->dev->ops->toggle_queue_status(h->qs[k], 0); +out_has_some_queues: + for (j = i - 1; j >= 0; j--) + hns_nic_ring_close(ndev, j); + + set_bit(NIC_STATE_DOWN, &priv->state); + + return ret; +} + +static void hns_nic_net_down(struct net_device *ndev) +{ + int i; + struct hnae_ae_ops *ops; + struct hns_nic_priv *priv = netdev_priv(ndev); + + if (test_and_set_bit(NIC_STATE_DOWN, &priv->state)) + return; + + (void)del_timer_sync(&priv->service_timer); + netif_tx_stop_all_queues(ndev); + netif_carrier_off(ndev); + netif_tx_disable(ndev); + priv->link = 0; + + if (priv->phy) + phy_stop(priv->phy); + + ops = priv->ae_handle->dev->ops; + + if (ops->stop) + ops->stop(priv->ae_handle); + + netif_tx_stop_all_queues(ndev); + + for (i = priv->ae_handle->q_num - 1; i >= 0; i--) { + hns_nic_ring_close(ndev, i); + hns_nic_ring_close(ndev, i + priv->ae_handle->q_num); + + /* clean tx buffers*/ + hns_nic_tx_clr_all_bufs(priv->ring_data + i); + } +} + +void hns_nic_net_reset(struct net_device *ndev) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *handle = priv->ae_handle; + + while (test_and_set_bit(NIC_STATE_RESETTING, &priv->state)) + usleep_range(1000, 2000); + + (void)hnae_reinit_handle(handle); + + clear_bit(NIC_STATE_RESETTING, &priv->state); +} + +void hns_nic_net_reinit(struct net_device *netdev) +{ + struct hns_nic_priv *priv = netdev_priv(netdev); + + priv->netdev->trans_start = jiffies; + while (test_and_set_bit(NIC_STATE_REINITING, &priv->state)) + usleep_range(1000, 2000); + + hns_nic_net_down(netdev); + hns_nic_net_reset(netdev); + (void)hns_nic_net_up(netdev); + clear_bit(NIC_STATE_REINITING, &priv->state); +} + +static int hns_nic_net_open(struct net_device *ndev) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *h = priv->ae_handle; + int ret; + + if (test_bit(NIC_STATE_TESTING, &priv->state)) + return -EBUSY; + + priv->link = 0; + netif_carrier_off(ndev); + + ret = netif_set_real_num_tx_queues(ndev, h->q_num); + if (ret < 0) { + netdev_err(ndev, "netif_set_real_num_tx_queues fail, ret=%d!\n", + ret); + return ret; + } + + ret = netif_set_real_num_rx_queues(ndev, h->q_num); + if (ret < 0) { + netdev_err(ndev, + "netif_set_real_num_rx_queues fail, ret=%d!\n", ret); + return ret; + } + + ret = hns_nic_net_up(ndev); + if (ret) { + netdev_err(ndev, + "hns net up fail, ret=%d!\n", ret); + return ret; + } + + return 0; +} + +static int hns_nic_net_stop(struct net_device *ndev) +{ + hns_nic_net_down(ndev); + + return 0; +} + +static void hns_tx_timeout_reset(struct hns_nic_priv *priv); +static void hns_nic_net_timeout(struct net_device *ndev) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + + hns_tx_timeout_reset(priv); +} + +static int hns_nic_do_ioctl(struct net_device *netdev, struct ifreq *ifr, + int cmd) +{ + struct hns_nic_priv *priv = netdev_priv(netdev); + struct phy_device *phy_dev = priv->phy; + + if (!netif_running(netdev)) + return -EINVAL; + + if (!phy_dev) + return -ENOTSUPP; + + return phy_mii_ioctl(phy_dev, ifr, cmd); +} + +/* use only for netconsole to poll with the device without interrupt */ +#ifdef CONFIG_NET_POLL_CONTROLLER +void hns_nic_poll_controller(struct net_device *ndev) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + unsigned long flags; + int i; + + local_irq_save(flags); + for (i = 0; i < priv->ae_handle->q_num * 2; i++) + napi_schedule(&priv->ring_data[i].napi); + local_irq_restore(flags); +} +#endif + +static netdev_tx_t hns_nic_net_xmit(struct sk_buff *skb, + struct net_device *ndev) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + int ret; + + assert(skb->queue_mapping < ndev->ae_handle->q_num); + ret = hns_nic_net_xmit_hw(ndev, skb, + &tx_ring_data(priv, skb->queue_mapping)); + if (ret == NETDEV_TX_OK) { + ndev->trans_start = jiffies; + ndev->stats.tx_bytes += skb->len; + ndev->stats.tx_packets++; + } + return (netdev_tx_t)ret; +} + +static int hns_nic_change_mtu(struct net_device *ndev, int new_mtu) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *h = priv->ae_handle; + int ret; + + /* MTU < 68 is an error and causes problems on some kernels */ + if (new_mtu < 68) + return -EINVAL; + + if (!h->dev->ops->set_mtu) + return -ENOTSUPP; + + if (netif_running(ndev)) { + (void)hns_nic_net_stop(ndev); + msleep(100); + + ret = h->dev->ops->set_mtu(h, new_mtu); + if (ret) + netdev_err(ndev, "set mtu fail, return value %d\n", + ret); + + if (hns_nic_net_open(ndev)) + netdev_err(ndev, "hns net open fail\n"); + } else { + ret = h->dev->ops->set_mtu(h, new_mtu); + } + + if (!ret) + ndev->mtu = new_mtu; + + return ret; +} + +/** + * nic_set_multicast_list - set mutl mac address + * @netdev: net device + * @p: mac address + * + * return void + */ +void hns_set_multicast_list(struct net_device *ndev) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *h = priv->ae_handle; + struct netdev_hw_addr *ha = NULL; + + if (!h) { + netdev_err(ndev, "hnae handle is null\n"); + return; + } + + if (h->dev->ops->set_mc_addr) { + netdev_for_each_mc_addr(ha, ndev) + if (h->dev->ops->set_mc_addr(h, ha->addr)) + netdev_err(ndev, "set multicast fail\n"); + } +} + +struct rtnl_link_stats64 *hns_nic_get_stats64(struct net_device *ndev, + struct rtnl_link_stats64 *stats) +{ + int idx = 0; + u64 tx_bytes = 0; + u64 rx_bytes = 0; + u64 tx_pkts = 0; + u64 rx_pkts = 0; + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *h = priv->ae_handle; + + for (idx = 0; idx < h->q_num; idx++) { + tx_bytes += h->qs[idx]->tx_ring.stats.tx_bytes; + tx_pkts += h->qs[idx]->tx_ring.stats.tx_pkts; + rx_bytes += h->qs[idx]->rx_ring.stats.rx_bytes; + rx_pkts += h->qs[idx]->rx_ring.stats.rx_pkts; + } + + stats->tx_bytes = tx_bytes; + stats->tx_packets = tx_pkts; + stats->rx_bytes = rx_bytes; + stats->rx_packets = rx_pkts; + + stats->rx_errors = ndev->stats.rx_errors; + stats->multicast = ndev->stats.multicast; + stats->rx_length_errors = ndev->stats.rx_length_errors; + stats->rx_crc_errors = ndev->stats.rx_crc_errors; + stats->rx_missed_errors = ndev->stats.rx_missed_errors; + + stats->tx_errors = ndev->stats.tx_errors; + stats->rx_dropped = ndev->stats.rx_dropped; + stats->tx_dropped = ndev->stats.tx_dropped; + stats->collisions = ndev->stats.collisions; + stats->rx_over_errors = ndev->stats.rx_over_errors; + stats->rx_frame_errors = ndev->stats.rx_frame_errors; + stats->rx_fifo_errors = ndev->stats.rx_fifo_errors; + stats->tx_aborted_errors = ndev->stats.tx_aborted_errors; + stats->tx_carrier_errors = ndev->stats.tx_carrier_errors; + stats->tx_fifo_errors = ndev->stats.tx_fifo_errors; + stats->tx_heartbeat_errors = ndev->stats.tx_heartbeat_errors; + stats->tx_window_errors = ndev->stats.tx_window_errors; + stats->rx_compressed = ndev->stats.rx_compressed; + stats->tx_compressed = ndev->stats.tx_compressed; + + return stats; +} + +static const struct net_device_ops hns_nic_netdev_ops = { + .ndo_open = hns_nic_net_open, + .ndo_stop = hns_nic_net_stop, + .ndo_start_xmit = hns_nic_net_xmit, + .ndo_tx_timeout = hns_nic_net_timeout, + .ndo_set_mac_address = hns_nic_net_set_mac_address, + .ndo_change_mtu = hns_nic_change_mtu, + .ndo_do_ioctl = hns_nic_do_ioctl, + .ndo_get_stats64 = hns_nic_get_stats64, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = hns_nic_poll_controller, +#endif + .ndo_set_rx_mode = hns_set_multicast_list, +}; + +static void hns_nic_update_link_status(struct net_device *netdev) +{ + struct hns_nic_priv *priv = netdev_priv(netdev); + + struct hnae_handle *h = priv->ae_handle; + int state = 1; + + if (priv->phy) { + if (!genphy_update_link(priv->phy)) + state = priv->phy->link; + else + state = 0; + } + state = state && h->dev->ops->get_status(h); + + if (state != priv->link) { + if (state) { + netif_carrier_on(netdev); + netif_tx_wake_all_queues(netdev); + netdev_info(netdev, "link up\n"); + } else { + netif_carrier_off(netdev); + netdev_info(netdev, "link down\n"); + } + priv->link = state; + } +} + +/* for dumping key regs*/ +static void hns_nic_dump(struct hns_nic_priv *priv) +{ + struct hnae_handle *h = priv->ae_handle; + struct hnae_ae_ops *ops = h->dev->ops; + u32 *data, reg_num, i; + + if (ops->get_regs_len && ops->get_regs) { + reg_num = ops->get_regs_len(priv->ae_handle); + reg_num = (reg_num + 3ul) & ~3ul; + data = kcalloc(reg_num, sizeof(u32), GFP_KERNEL); + if (data) { + ops->get_regs(priv->ae_handle, data); + for (i = 0; i < reg_num; i += 4) + pr_info("0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + i, data[i], data[i + 1], + data[i + 2], data[i + 3]); + kfree(data); + } + } + + for (i = 0; i < h->q_num; i++) { + pr_info("tx_queue%d_next_to_clean:%d\n", + i, h->qs[i]->tx_ring.next_to_clean); + pr_info("tx_queue%d_next_to_use:%d\n", + i, h->qs[i]->tx_ring.next_to_use); + pr_info("rx_queue%d_next_to_clean:%d\n", + i, h->qs[i]->rx_ring.next_to_clean); + pr_info("rx_queue%d_next_to_use:%d\n", + i, h->qs[i]->rx_ring.next_to_use); + } +} + +/* for resetting suntask*/ +static void hns_nic_reset_subtask(struct hns_nic_priv *priv) +{ + enum hnae_port_type type = priv->ae_handle->port_type; + + if (!test_bit(NIC_STATE2_RESET_REQUESTED, &priv->state)) + return; + clear_bit(NIC_STATE2_RESET_REQUESTED, &priv->state); + + /* If we're already down, removing or resetting, just bail */ + if (test_bit(NIC_STATE_DOWN, &priv->state) || + test_bit(NIC_STATE_REMOVING, &priv->state) || + test_bit(NIC_STATE_RESETTING, &priv->state)) + return; + + hns_nic_dump(priv); + netdev_err(priv->netdev, "Reset %s port\n", + (type == HNAE_PORT_DEBUG ? "debug" : "business")); + + rtnl_lock(); + if (type == HNAE_PORT_DEBUG) { + hns_nic_net_reinit(priv->netdev); + } else { + hns_nic_net_down(priv->netdev); + hns_nic_net_reset(priv->netdev); + } + rtnl_unlock(); +} + +/* for doing service complete*/ +static void hns_nic_service_event_complete(struct hns_nic_priv *priv) +{ + assert(!test_bit(NIC_STATE_SERVICE_SCHED, &priv->state)); + + smp_mb__before_atomic(); + clear_bit(NIC_STATE_SERVICE_SCHED, &priv->state); +} + +static void hns_nic_service_task(struct work_struct *work) +{ + struct hns_nic_priv *priv + = container_of(work, struct hns_nic_priv, service_task); + struct hnae_handle *h = priv->ae_handle; + + hns_nic_update_link_status(priv->netdev); + h->dev->ops->update_led_status(h); + hns_nic_update_stats(priv->netdev); + + hns_nic_reset_subtask(priv); + hns_nic_service_event_complete(priv); +} + +static void hns_nic_task_schedule(struct hns_nic_priv *priv) +{ + if (!test_bit(NIC_STATE_DOWN, &priv->state) && + !test_bit(NIC_STATE_REMOVING, &priv->state) && + !test_and_set_bit(NIC_STATE_SERVICE_SCHED, &priv->state)) + (void)schedule_work(&priv->service_task); +} + +static void hns_nic_service_timer(unsigned long data) +{ + struct hns_nic_priv *priv = (struct hns_nic_priv *)data; + + (void)mod_timer(&priv->service_timer, jiffies + SERVICE_TIMER_HZ); + + hns_nic_task_schedule(priv); +} + +/** + * hns_tx_timeout_reset - initiate reset due to Tx timeout + * @priv: driver private struct + **/ +static void hns_tx_timeout_reset(struct hns_nic_priv *priv) +{ + /* Do the reset outside of interrupt context */ + if (!test_bit(NIC_STATE_DOWN, &priv->state)) { + set_bit(NIC_STATE2_RESET_REQUESTED, &priv->state); + netdev_warn(priv->netdev, + "initiating reset due to tx timeout(%llu,0x%lx)\n", + priv->tx_timeout_count, priv->state); + priv->tx_timeout_count++; + hns_nic_task_schedule(priv); + } +} + +static int hns_nic_init_ring_data(struct hns_nic_priv *priv) +{ + struct hnae_handle *h = priv->ae_handle; + struct hns_nic_ring_data *rd; + int i; + + if (h->q_num > NIC_MAX_Q_PER_VF) { + netdev_err(priv->netdev, "too much queue (%d)\n", h->q_num); + return -EINVAL; + } + + priv->ring_data = kzalloc(h->q_num * sizeof(*priv->ring_data) * 2, + GFP_KERNEL); + if (!priv->ring_data) + return -ENOMEM; + + for (i = 0; i < h->q_num; i++) { + rd = &priv->ring_data[i]; + rd->queue_index = i; + rd->ring = &h->qs[i]->tx_ring; + rd->poll_one = hns_nic_tx_poll_one; + rd->fini_process = hns_nic_tx_fini_pro; + + netif_napi_add(priv->netdev, &rd->napi, + hns_nic_common_poll, NIC_TX_CLEAN_MAX_NUM); + rd->ring->irq_init_flag = RCB_IRQ_NOT_INITED; + } + for (i = h->q_num; i < h->q_num * 2; i++) { + rd = &priv->ring_data[i]; + rd->queue_index = i - h->q_num; + rd->ring = &h->qs[i - h->q_num]->rx_ring; + rd->poll_one = hns_nic_rx_poll_one; + rd->ex_process = hns_nic_rx_up_pro; + rd->fini_process = hns_nic_rx_fini_pro; + + netif_napi_add(priv->netdev, &rd->napi, + hns_nic_common_poll, NIC_RX_CLEAN_MAX_NUM); + rd->ring->irq_init_flag = RCB_IRQ_NOT_INITED; + } + + return 0; +} + +static void hns_nic_uninit_ring_data(struct hns_nic_priv *priv) +{ + struct hnae_handle *h = priv->ae_handle; + int i; + + for (i = 0; i < h->q_num * 2; i++) { + netif_napi_del(&priv->ring_data[i].napi); + if (priv->ring_data[i].ring->irq_init_flag == RCB_IRQ_INITED) { + irq_set_affinity_hint(priv->ring_data[i].ring->irq, + NULL); + free_irq(priv->ring_data[i].ring->irq, + &priv->ring_data[i]); + } + + priv->ring_data[i].ring->irq_init_flag = RCB_IRQ_NOT_INITED; + } + kfree(priv->ring_data); +} + +static int hns_nic_try_get_ae(struct net_device *ndev) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *h; + int ret; + + h = hnae_get_handle(&priv->netdev->dev, + priv->ae_name, priv->port_id, NULL); + if (IS_ERR_OR_NULL(h)) { + ret = PTR_ERR(h); + dev_dbg(priv->dev, "has not handle, register notifier!\n"); + goto out; + } + priv->ae_handle = h; + + ret = hns_nic_init_phy(ndev, h); + if (ret) { + dev_err(priv->dev, "probe phy device fail!\n"); + goto out_init_phy; + } + + ret = hns_nic_init_ring_data(priv); + if (ret) { + ret = -ENOMEM; + goto out_init_ring_data; + } + + ret = register_netdev(ndev); + if (ret) { + dev_err(priv->dev, "probe register netdev fail!\n"); + goto out_reg_ndev_fail; + } + return 0; + +out_reg_ndev_fail: + hns_nic_uninit_ring_data(priv); + priv->ring_data = NULL; +out_init_phy: +out_init_ring_data: + hnae_put_handle(priv->ae_handle); + priv->ae_handle = NULL; +out: + return ret; +} + +static int hns_nic_notifier_action(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct hns_nic_priv *priv = + container_of(nb, struct hns_nic_priv, notifier_block); + + assert(action == HNAE_AE_REGISTER); + + if (!hns_nic_try_get_ae(priv->netdev)) { + hnae_unregister_notifier(&priv->notifier_block); + priv->notifier_block.notifier_call = NULL; + } + return 0; +} + +static int hns_nic_dev_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct net_device *ndev; + struct hns_nic_priv *priv; + struct device_node *node = dev->of_node; + int ret; + + ndev = alloc_etherdev_mq(sizeof(struct hns_nic_priv), NIC_MAX_Q_PER_VF); + if (!ndev) + return -ENOMEM; + + platform_set_drvdata(pdev, ndev); + + priv = netdev_priv(ndev); + priv->dev = dev; + priv->netdev = ndev; + + if (of_device_is_compatible(node, "hisilicon,hns-nic-v2")) + priv->enet_ver = AE_VERSION_2; + else + priv->enet_ver = AE_VERSION_1; + + ret = of_property_read_string(node, "ae-name", &priv->ae_name); + if (ret) + goto out_read_string_fail; + + ret = of_property_read_u32(node, "port-id", &priv->port_id); + if (ret) + goto out_read_string_fail; + + hns_init_mac_addr(ndev); + + ndev->watchdog_timeo = HNS_NIC_TX_TIMEOUT; + ndev->priv_flags |= IFF_UNICAST_FLT; + ndev->netdev_ops = &hns_nic_netdev_ops; + hns_ethtool_set_ops(ndev); + ndev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO | + NETIF_F_GRO; + ndev->vlan_features |= + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; + ndev->vlan_features |= NETIF_F_SG | NETIF_F_GSO | NETIF_F_GRO; + + SET_NETDEV_DEV(ndev, dev); + + if (!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) + dev_dbg(dev, "set mask to 64bit\n"); + else + dev_err(dev, "set mask to 32bit fail!\n"); + + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(ndev); + + setup_timer(&priv->service_timer, hns_nic_service_timer, + (unsigned long)priv); + INIT_WORK(&priv->service_task, hns_nic_service_task); + + set_bit(NIC_STATE_SERVICE_INITED, &priv->state); + clear_bit(NIC_STATE_SERVICE_SCHED, &priv->state); + set_bit(NIC_STATE_DOWN, &priv->state); + + if (hns_nic_try_get_ae(priv->netdev)) { + priv->notifier_block.notifier_call = hns_nic_notifier_action; + ret = hnae_register_notifier(&priv->notifier_block); + if (ret) { + dev_err(dev, "register notifier fail!\n"); + goto out_notify_fail; + } + dev_dbg(dev, "has not handle, register notifier!\n"); + } + + return 0; + +out_notify_fail: + (void)cancel_work_sync(&priv->service_task); +out_read_string_fail: + free_netdev(ndev); + return ret; +} + +static int hns_nic_dev_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct hns_nic_priv *priv = netdev_priv(ndev); + + if (ndev->reg_state != NETREG_UNINITIALIZED) + unregister_netdev(ndev); + + if (priv->ring_data) + hns_nic_uninit_ring_data(priv); + priv->ring_data = NULL; + + if (priv->phy) + phy_disconnect(priv->phy); + priv->phy = NULL; + + if (!IS_ERR_OR_NULL(priv->ae_handle)) + hnae_put_handle(priv->ae_handle); + priv->ae_handle = NULL; + if (priv->notifier_block.notifier_call) + hnae_unregister_notifier(&priv->notifier_block); + priv->notifier_block.notifier_call = NULL; + + set_bit(NIC_STATE_REMOVING, &priv->state); + (void)cancel_work_sync(&priv->service_task); + + free_netdev(ndev); + return 0; +} + +static const struct of_device_id hns_enet_of_match[] = { + {.compatible = "hisilicon,hns-nic-v1",}, + {.compatible = "hisilicon,hns-nic-v2",}, + {}, +}; + +MODULE_DEVICE_TABLE(of, hns_enet_of_match); + +static struct platform_driver hns_nic_dev_driver = { + .driver = { + .name = "hns-nic", + .owner = THIS_MODULE, + .of_match_table = hns_enet_of_match, + }, + .probe = hns_nic_dev_probe, + .remove = hns_nic_dev_remove, +}; + +module_platform_driver(hns_nic_dev_driver); + +MODULE_DESCRIPTION("HISILICON HNS Ethernet driver"); +MODULE_AUTHOR("Hisilicon, Inc."); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:hns-nic"); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.h b/drivers/net/ethernet/hisilicon/hns/hns_enet.h new file mode 100644 index 000000000000..dae0ed19ac6d --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __HNS_ENET_H +#define __HNS_ENET_H + +#include +#include +#include +#include +#include + +#include "hnae.h" + +enum hns_nic_state { + NIC_STATE_TESTING = 0, + NIC_STATE_RESETTING, + NIC_STATE_REINITING, + NIC_STATE_DOWN, + NIC_STATE_DISABLED, + NIC_STATE_REMOVING, + NIC_STATE_SERVICE_INITED, + NIC_STATE_SERVICE_SCHED, + NIC_STATE2_RESET_REQUESTED, + NIC_STATE_MAX +}; + +struct hns_nic_ring_data { + struct hnae_ring *ring; + struct napi_struct napi; + int queue_index; + int (*poll_one)(struct hns_nic_ring_data *, int, void *); + void (*ex_process)(struct hns_nic_ring_data *, struct sk_buff *); + void (*fini_process)(struct hns_nic_ring_data *); +}; + +struct hns_nic_priv { + const char *ae_name; + u32 enet_ver; + u32 port_id; + int phy_mode; + int phy_led_val; + struct phy_device *phy; + struct net_device *netdev; + struct device *dev; + struct hnae_handle *ae_handle; + + /* the cb for nic to manage the ring buffer, the first half of the + * array is for tx_ring and vice versa for the second half + */ + struct hns_nic_ring_data *ring_data; + + /* The most recently read link state */ + int link; + u64 tx_timeout_count; + + unsigned long state; + + struct timer_list service_timer; + + struct work_struct service_task; + + struct notifier_block notifier_block; +}; + +#define tx_ring_data(priv, idx) ((priv)->ring_data[idx]) +#define rx_ring_data(priv, idx) \ + ((priv)->ring_data[(priv)->ae_handle->q_num + (idx)]) + +void hns_ethtool_set_ops(struct net_device *ndev); +void hns_nic_net_reset(struct net_device *ndev); +void hns_nic_net_reinit(struct net_device *netdev); +int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h); +int hns_nic_net_xmit_hw(struct net_device *ndev, + struct sk_buff *skb, + struct hns_nic_ring_data *ring_data); + +#endif /**__HNS_ENET_H */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c new file mode 100644 index 000000000000..2550208cb22e --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -0,0 +1,1230 @@ +/* + * Copyright (c) 2014-2015 Hisilicon Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include + +#include "hns_enet.h" + +#define HNS_PHY_PAGE_MDIX 0 +#define HNS_PHY_PAGE_LED 3 +#define HNS_PHY_PAGE_COPPER 0 + +#define HNS_PHY_PAGE_REG 22 /* Page Selection Reg. */ +#define HNS_PHY_CSC_REG 16 /* Copper Specific Control Register */ +#define HNS_PHY_CSS_REG 17 /* Copper Specific Status Register */ +#define HNS_LED_FC_REG 16 /* LED Function Control Reg. */ +#define HNS_LED_PC_REG 17 /* LED Polarity Control Reg. */ + +#define HNS_LED_FORCE_ON 9 +#define HNS_LED_FORCE_OFF 8 + +#define HNS_CHIP_VERSION 660 +#define HNS_NET_STATS_CNT 26 + +#define PHY_MDIX_CTRL_S (5) +#define PHY_MDIX_CTRL_M (3 << PHY_MDIX_CTRL_S) + +#define PHY_MDIX_STATUS_B (6) +#define PHY_SPEED_DUP_RESOLVE_B (11) + +/** + *hns_nic_get_link - get current link status + *@net_dev: net_device + *retuen 0 - success , negative --fail + */ +static u32 hns_nic_get_link(struct net_device *net_dev) +{ + struct hns_nic_priv *priv = netdev_priv(net_dev); + u32 link_stat = priv->link; + struct hnae_handle *h; + + assert(priv && priv->ae_handle); + h = priv->ae_handle; + + if (priv->phy) { + if (!genphy_update_link(priv->phy)) + link_stat = priv->phy->link; + else + link_stat = 0; + } + + if (h->dev && h->dev->ops && h->dev->ops->get_status) + link_stat = link_stat && h->dev->ops->get_status(h); + else + link_stat = 0; + + return link_stat; +} + +static void hns_get_mdix_mode(struct net_device *net_dev, + struct ethtool_cmd *cmd) +{ + int mdix_ctrl, mdix, retval, is_resolved; + struct hns_nic_priv *priv = netdev_priv(net_dev); + struct phy_device *phy_dev = priv->phy; + + if (!phy_dev || !phy_dev->bus) { + cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID; + cmd->eth_tp_mdix = ETH_TP_MDI_INVALID; + return; + } + + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, HNS_PHY_PAGE_REG, + HNS_PHY_PAGE_MDIX); + + retval = mdiobus_read(phy_dev->bus, phy_dev->addr, HNS_PHY_CSC_REG); + mdix_ctrl = hnae_get_field(retval, PHY_MDIX_CTRL_M, PHY_MDIX_CTRL_S); + + retval = mdiobus_read(phy_dev->bus, phy_dev->addr, HNS_PHY_CSS_REG); + mdix = hnae_get_bit(retval, PHY_MDIX_STATUS_B); + is_resolved = hnae_get_bit(retval, PHY_SPEED_DUP_RESOLVE_B); + + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, HNS_PHY_PAGE_REG, + HNS_PHY_PAGE_COPPER); + + switch (mdix_ctrl) { + case 0x0: + cmd->eth_tp_mdix_ctrl = ETH_TP_MDI; + break; + case 0x1: + cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_X; + break; + case 0x3: + cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; + break; + default: + cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID; + break; + } + + if (!is_resolved) + cmd->eth_tp_mdix = ETH_TP_MDI_INVALID; + else if (mdix) + cmd->eth_tp_mdix = ETH_TP_MDI_X; + else + cmd->eth_tp_mdix = ETH_TP_MDI; +} + +/** + *hns_nic_get_settings - implement ethtool get settings + *@net_dev: net_device + *@cmd: ethtool_cmd + *retuen 0 - success , negative --fail + */ +static int hns_nic_get_settings(struct net_device *net_dev, + struct ethtool_cmd *cmd) +{ + struct hns_nic_priv *priv = netdev_priv(net_dev); + struct hnae_handle *h; + u32 link_stat; + int ret; + u8 duplex; + u16 speed; + + if (!priv || !priv->ae_handle) + return -ESRCH; + + h = priv->ae_handle; + if (!h->dev || !h->dev->ops || !h->dev->ops->get_info) + return -ESRCH; + + ret = h->dev->ops->get_info(h, NULL, &speed, &duplex); + if (ret < 0) { + netdev_err(net_dev, "%s get_info error!\n", __func__); + return -EINVAL; + } + + /* When there is no phy, autoneg is off. */ + cmd->autoneg = false; + ethtool_cmd_speed_set(cmd, speed); + cmd->duplex = duplex; + + if (priv->phy) + (void)phy_ethtool_gset(priv->phy, cmd); + + link_stat = hns_nic_get_link(net_dev); + if (!link_stat) { + ethtool_cmd_speed_set(cmd, (u32)SPEED_UNKNOWN); + cmd->duplex = DUPLEX_UNKNOWN; + } + + if (cmd->autoneg) + cmd->advertising |= ADVERTISED_Autoneg; + + cmd->supported |= h->if_support; + if (h->phy_if == PHY_INTERFACE_MODE_SGMII) { + cmd->supported |= SUPPORTED_TP; + cmd->advertising |= ADVERTISED_1000baseT_Full; + } else if (h->phy_if == PHY_INTERFACE_MODE_XGMII) { + cmd->supported |= SUPPORTED_FIBRE; + cmd->advertising |= ADVERTISED_10000baseKR_Full; + } + + if (h->port_type == HNAE_PORT_SERVICE) { + cmd->port = PORT_FIBRE; + cmd->supported |= SUPPORTED_Pause; + } else { + cmd->port = PORT_TP; + } + + cmd->transceiver = XCVR_EXTERNAL; + cmd->mdio_support = (ETH_MDIO_SUPPORTS_C45 | ETH_MDIO_SUPPORTS_C22); + hns_get_mdix_mode(net_dev, cmd); + + return 0; +} + +/** + *hns_nic_set_settings - implement ethtool set settings + *@net_dev: net_device + *@cmd: ethtool_cmd + *retuen 0 - success , negative --fail + */ +static int hns_nic_set_settings(struct net_device *net_dev, + struct ethtool_cmd *cmd) +{ + struct hns_nic_priv *priv = netdev_priv(net_dev); + struct hnae_handle *h; + int link_stat; + u32 speed; + u8 duplex, autoneg; + + if (!netif_running(net_dev)) + return -ESRCH; + + if (!priv || !priv->ae_handle || !priv->ae_handle->dev || + !priv->ae_handle->dev->ops) + return -ENODEV; + + h = priv->ae_handle; + link_stat = hns_nic_get_link(net_dev); + duplex = cmd->duplex; + speed = ethtool_cmd_speed(cmd); + autoneg = cmd->autoneg; + + if (!link_stat) { + if (duplex != (u8)DUPLEX_UNKNOWN || speed != (u32)SPEED_UNKNOWN) + return -EINVAL; + + if (h->phy_if == PHY_INTERFACE_MODE_SGMII && h->phy_node) { + priv->phy->autoneg = autoneg; + return phy_start_aneg(priv->phy); + } + } + + if (h->phy_if == PHY_INTERFACE_MODE_XGMII) { + if (autoneg != AUTONEG_DISABLE) + return -EINVAL; + + if (speed != SPEED_10000 || duplex != DUPLEX_FULL) + return -EINVAL; + } else if (h->phy_if == PHY_INTERFACE_MODE_SGMII) { + if (!h->phy_node && autoneg != AUTONEG_DISABLE) + return -EINVAL; + + if (speed == SPEED_1000 && duplex == DUPLEX_HALF) + return -EINVAL; + + if (speed != SPEED_10 && speed != SPEED_100 && + speed != SPEED_1000) + return -EINVAL; + } else { + netdev_err(net_dev, "Not supported!"); + return -ENOTSUPP; + } + + if (priv->phy) { + return phy_ethtool_sset(priv->phy, cmd); + } else if (h->dev->ops->adjust_link && link_stat) { + h->dev->ops->adjust_link(h, speed, duplex); + return 0; + } + netdev_err(net_dev, "Not supported!"); + return -ENOTSUPP; +} + +static const char hns_nic_test_strs[][ETH_GSTRING_LEN] = { + "Mac Loopback test", + "Serdes Loopback test", + "Phy Loopback test" +}; + +static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en) +{ +#define COPPER_CONTROL_REG 0 +#define PHY_LOOP_BACK BIT(14) + u16 val = 0; + + if (phy_dev->is_c45) /* c45 branch adding for XGE PHY */ + return -ENOTSUPP; + + if (en) { + /* speed : 1000M */ + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + HNS_PHY_PAGE_REG, 2); + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + 21, 0x1046); + /* Force Master */ + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + 9, 0x1F00); + /* Soft-reset */ + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + 0, 0x9140); + /* If autoneg disabled,two soft-reset operations */ + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + 0, 0x9140); + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + 22, 0xFA); + + /* Default is 0x0400 */ + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + 1, 0x418); + + /* Force 1000M Link, Default is 0x0200 */ + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + 7, 0x20C); + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + 22, 0); + + /* Enable MAC loop-back */ + val = (u16)mdiobus_read(phy_dev->bus, phy_dev->addr, + COPPER_CONTROL_REG); + val |= PHY_LOOP_BACK; + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + COPPER_CONTROL_REG, val); + } else { + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + 22, 0xFA); + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + 1, 0x400); + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + 7, 0x200); + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + 22, 0); + + val = (u16)mdiobus_read(phy_dev->bus, phy_dev->addr, + COPPER_CONTROL_REG); + val &= ~PHY_LOOP_BACK; + (void)mdiobus_write(phy_dev->bus, phy_dev->addr, + COPPER_CONTROL_REG, val); + } + return 0; +} + +static int __lb_setup(struct net_device *ndev, + enum hnae_loop loop) +{ + int ret = 0; + struct hns_nic_priv *priv = netdev_priv(ndev); + struct phy_device *phy_dev = priv->phy; + struct hnae_handle *h = priv->ae_handle; + + switch (loop) { + case MAC_INTERNALLOOP_PHY: + if ((phy_dev) && (!phy_dev->is_c45)) + ret = hns_nic_config_phy_loopback(phy_dev, 0x1); + break; + case MAC_INTERNALLOOP_MAC: + if ((h->dev->ops->set_loopback) && + (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII)) + ret = h->dev->ops->set_loopback(h, loop, 0x1); + break; + case MAC_INTERNALLOOP_SERDES: + if (h->dev->ops->set_loopback) + ret = h->dev->ops->set_loopback(h, loop, 0x1); + break; + case MAC_LOOP_NONE: + if ((phy_dev) && (!phy_dev->is_c45)) + ret |= hns_nic_config_phy_loopback(phy_dev, 0x0); + + if (h->dev->ops->set_loopback) { + if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII) + ret |= h->dev->ops->set_loopback(h, + MAC_INTERNALLOOP_MAC, 0x0); + + ret |= h->dev->ops->set_loopback(h, + MAC_INTERNALLOOP_SERDES, 0x0); + } + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int __lb_up(struct net_device *ndev, + enum hnae_loop loop_mode) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *h = priv->ae_handle; + int speed, duplex; + int ret; + + hns_nic_net_reset(ndev); + + if (priv->phy) { + phy_disconnect(priv->phy); + msleep(100); + + ret = hns_nic_init_phy(ndev, h); + if (ret) + return ret; + } + + ret = __lb_setup(ndev, loop_mode); + if (ret) + return ret; + + msleep(100); + + ret = h->dev->ops->start ? h->dev->ops->start(h) : 0; + if (ret) + return ret; + + if (priv->phy) + phy_start(priv->phy); + + /* link adjust duplex*/ + if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII) + speed = 1000; + else + speed = 10000; + duplex = 1; + + h->dev->ops->adjust_link(h, speed, duplex); + + return 0; +} + +static void __lb_other_process(struct hns_nic_ring_data *ring_data, + struct sk_buff *skb) +{ + struct net_device *ndev; + struct hnae_ring *ring; + struct netdev_queue *dev_queue; + struct sk_buff *new_skb; + unsigned int frame_size; + int check_ok; + u32 i; + char buff[33]; /* 32B data and the last character '\0' */ + + if (!ring_data) { /* Just for doing create frame*/ + frame_size = skb->len; + memset(skb->data, 0xFF, frame_size); + frame_size &= ~1ul; + memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); + memset(&skb->data[frame_size / 2 + 10], 0xBE, + frame_size / 2 - 11); + memset(&skb->data[frame_size / 2 + 12], 0xAF, + frame_size / 2 - 13); + return; + } + + ring = ring_data->ring; + ndev = ring_data->napi.dev; + if (is_tx_ring(ring)) { /* for tx queue reset*/ + dev_queue = netdev_get_tx_queue(ndev, ring_data->queue_index); + netdev_tx_reset_queue(dev_queue); + return; + } + + frame_size = skb->len; + frame_size &= ~1ul; + /* for mutl buffer*/ + new_skb = skb_copy(skb, GFP_ATOMIC); + dev_kfree_skb_any(skb); + skb = new_skb; + + check_ok = 0; + if (*(skb->data + 10) == 0xFF) { /* for rx check frame*/ + if ((*(skb->data + frame_size / 2 + 10) == 0xBE) && + (*(skb->data + frame_size / 2 + 12) == 0xAF)) + check_ok = 1; + } + + if (check_ok) { + ndev->stats.rx_packets++; + ndev->stats.rx_bytes += skb->len; + } else { + ndev->stats.rx_frame_errors++; + for (i = 0; i < skb->len; i++) { + snprintf(buff + i % 16 * 2, 3, /* tailing \0*/ + "%02x", *(skb->data + i)); + if ((i % 16 == 15) || (i == skb->len - 1)) + pr_info("%s\n", buff); + } + } + dev_kfree_skb_any(skb); +} + +static int __lb_clean_rings(struct hns_nic_priv *priv, + int ringid0, int ringid1, int budget) +{ + int i, ret; + struct hns_nic_ring_data *ring_data; + struct net_device *ndev = priv->netdev; + unsigned long rx_packets = ndev->stats.rx_packets; + unsigned long rx_bytes = ndev->stats.rx_bytes; + unsigned long rx_frame_errors = ndev->stats.rx_frame_errors; + + for (i = ringid0; i <= ringid1; i++) { + ring_data = &priv->ring_data[i]; + (void)ring_data->poll_one(ring_data, + budget, __lb_other_process); + } + ret = (int)(ndev->stats.rx_packets - rx_packets); + ndev->stats.rx_packets = rx_packets; + ndev->stats.rx_bytes = rx_bytes; + ndev->stats.rx_frame_errors = rx_frame_errors; + return ret; +} + +/** + * nic_run_loopback_test - run loopback test + * @nic_dev: net device + * @loopback_type: loopback type + */ +static int __lb_run_test(struct net_device *ndev, + enum hnae_loop loop_mode) +{ +#define NIC_LB_TEST_PKT_NUM_PER_CYCLE 1 +#define NIC_LB_TEST_RING_ID 0 +#define NIC_LB_TEST_FRAME_SIZE 128 +/* nic loopback test err */ +#define NIC_LB_TEST_NO_MEM_ERR 1 +#define NIC_LB_TEST_TX_CNT_ERR 2 +#define NIC_LB_TEST_RX_CNT_ERR 3 +#define NIC_LB_TEST_RX_PKG_ERR 4 + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *h = priv->ae_handle; + int i, j, lc, good_cnt, ret_val = 0; + unsigned int size; + netdev_tx_t tx_ret_val; + struct sk_buff *skb; + + size = NIC_LB_TEST_FRAME_SIZE; + /* allocate test skb */ + skb = alloc_skb(size, GFP_KERNEL); + if (!skb) + return NIC_LB_TEST_NO_MEM_ERR; + + /* place data into test skb */ + (void)skb_put(skb, size); + __lb_other_process(NULL, skb); + skb->queue_mapping = NIC_LB_TEST_RING_ID; + + lc = 1; + for (j = 0; j < lc; j++) { + /* reset count of good packets */ + good_cnt = 0; + /* place 64 packets on the transmit queue*/ + for (i = 0; i < NIC_LB_TEST_PKT_NUM_PER_CYCLE; i++) { + (void)skb_get(skb); + + tx_ret_val = (netdev_tx_t)hns_nic_net_xmit_hw( + ndev, skb, + &tx_ring_data(priv, skb->queue_mapping)); + if (tx_ret_val == NETDEV_TX_OK) + good_cnt++; + else + break; + } + if (good_cnt != NIC_LB_TEST_PKT_NUM_PER_CYCLE) { + ret_val = NIC_LB_TEST_TX_CNT_ERR; + dev_err(priv->dev, "%s sent fail, cnt=0x%x, budget=0x%x\n", + hns_nic_test_strs[loop_mode], good_cnt, + NIC_LB_TEST_PKT_NUM_PER_CYCLE); + break; + } + + /* allow 100 milliseconds for packets to go from Tx to Rx */ + msleep(100); + + good_cnt = __lb_clean_rings(priv, + h->q_num, h->q_num * 2 - 1, + NIC_LB_TEST_PKT_NUM_PER_CYCLE); + if (good_cnt != NIC_LB_TEST_PKT_NUM_PER_CYCLE) { + ret_val = NIC_LB_TEST_RX_CNT_ERR; + dev_err(priv->dev, "%s recv fail, cnt=0x%x, budget=0x%x\n", + hns_nic_test_strs[loop_mode], good_cnt, + NIC_LB_TEST_PKT_NUM_PER_CYCLE); + break; + } + (void)__lb_clean_rings(priv, + NIC_LB_TEST_RING_ID, NIC_LB_TEST_RING_ID, + NIC_LB_TEST_PKT_NUM_PER_CYCLE); + } + + /* free the original skb */ + kfree_skb(skb); + + return ret_val; +} + +static int __lb_down(struct net_device *ndev) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *h = priv->ae_handle; + int ret; + + ret = __lb_setup(ndev, MAC_LOOP_NONE); + if (ret) + netdev_err(ndev, "%s: __lb_setup return error(%d)!\n", + __func__, + ret); + + if (priv->phy) + phy_stop(priv->phy); + + if (h->dev->ops->stop) + h->dev->ops->stop(h); + + usleep_range(10000, 20000); + (void)__lb_clean_rings(priv, 0, h->q_num - 1, 256); + + hns_nic_net_reset(ndev); + + return 0; +} + +/** + * hns_nic_self_test - self test + * @dev: net device + * @eth_test: test cmd + * @data: test result + */ +static void hns_nic_self_test(struct net_device *ndev, + struct ethtool_test *eth_test, u64 *data) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + bool if_running = netif_running(ndev); +#define SELF_TEST_TPYE_NUM 3 + int st_param[SELF_TEST_TPYE_NUM][2]; + int i; + int test_index = 0; + + st_param[0][0] = MAC_INTERNALLOOP_MAC; /* XGE not supported lb */ + st_param[0][1] = (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII); + st_param[1][0] = MAC_INTERNALLOOP_SERDES; + st_param[1][1] = 1; /*serdes must exist*/ + st_param[2][0] = MAC_INTERNALLOOP_PHY; /* only supporte phy node*/ + st_param[2][1] = ((!!(priv->ae_handle->phy_node)) && + (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII)); + + if (eth_test->flags == ETH_TEST_FL_OFFLINE) { + set_bit(NIC_STATE_TESTING, &priv->state); + + if (if_running) + (void)dev_close(ndev); + + for (i = 0; i < SELF_TEST_TPYE_NUM; i++) { + if (!st_param[i][1]) + continue; /* NEXT testing */ + + data[test_index] = __lb_up(ndev, + (enum hnae_loop)st_param[i][0]); + if (!data[test_index]) { + data[test_index] = __lb_run_test( + ndev, (enum hnae_loop)st_param[i][0]); + (void)__lb_down(ndev); + } + + if (data[test_index]) + eth_test->flags |= ETH_TEST_FL_FAILED; + + test_index++; + } + + hns_nic_net_reset(priv->netdev); + + clear_bit(NIC_STATE_TESTING, &priv->state); + + if (if_running) + (void)dev_open(ndev); + } + /* Online tests aren't run; pass by default */ + + (void)msleep_interruptible(4 * 1000); +} + +/** + * hns_nic_get_drvinfo - get net driver info + * @dev: net device + * @drvinfo: driver info + */ +static void hns_nic_get_drvinfo(struct net_device *net_dev, + struct ethtool_drvinfo *drvinfo) +{ + struct hns_nic_priv *priv = netdev_priv(net_dev); + + assert(priv); + + strncpy(drvinfo->version, HNAE_DRIVER_VERSION, + sizeof(drvinfo->version)); + drvinfo->version[sizeof(drvinfo->version) - 1] = '\0'; + + strncpy(drvinfo->driver, HNAE_DRIVER_NAME, sizeof(drvinfo->driver)); + drvinfo->driver[sizeof(drvinfo->driver) - 1] = '\0'; + + strncpy(drvinfo->bus_info, priv->dev->bus->name, + sizeof(drvinfo->bus_info)); + drvinfo->bus_info[ETHTOOL_BUSINFO_LEN - 1] = '\0'; + + strncpy(drvinfo->fw_version, "N/A", ETHTOOL_FWVERS_LEN); + drvinfo->eedump_len = 0; +} + +/** + * hns_get_ringparam - get ring parameter + * @dev: net device + * @param: ethtool parameter + */ +void hns_get_ringparam(struct net_device *net_dev, + struct ethtool_ringparam *param) +{ + struct hns_nic_priv *priv = netdev_priv(net_dev); + struct hnae_ae_ops *ops; + struct hnae_queue *queue; + u32 uplimit = 0; + + queue = priv->ae_handle->qs[0]; + ops = priv->ae_handle->dev->ops; + + if (ops->get_ring_bdnum_limit) + ops->get_ring_bdnum_limit(queue, &uplimit); + + param->rx_max_pending = uplimit; + param->tx_max_pending = uplimit; + param->rx_pending = queue->rx_ring.desc_num; + param->tx_pending = queue->tx_ring.desc_num; +} + +/** + * hns_get_pauseparam - get pause parameter + * @dev: net device + * @param: pause parameter + */ +static void hns_get_pauseparam(struct net_device *net_dev, + struct ethtool_pauseparam *param) +{ + struct hns_nic_priv *priv = netdev_priv(net_dev); + struct hnae_ae_ops *ops; + + ops = priv->ae_handle->dev->ops; + + if (ops->get_pauseparam) + ops->get_pauseparam(priv->ae_handle, ¶m->autoneg, + ¶m->rx_pause, ¶m->tx_pause); +} + +/** + * hns_set_pauseparam - set pause parameter + * @dev: net device + * @param: pause parameter + * + * Return 0 on success, negative on failure + */ +static int hns_set_pauseparam(struct net_device *net_dev, + struct ethtool_pauseparam *param) +{ + struct hns_nic_priv *priv = netdev_priv(net_dev); + struct hnae_handle *h; + struct hnae_ae_ops *ops; + + assert(priv || priv->ae_handle); + + h = priv->ae_handle; + ops = h->dev->ops; + + if (!ops->set_pauseparam) + return -ESRCH; + + return ops->set_pauseparam(priv->ae_handle, param->autoneg, + param->rx_pause, param->tx_pause); +} + +/** + * hns_get_coalesce - get coalesce info. + * @dev: net device + * @ec: coalesce info. + * + * Return 0 on success, negative on failure. + */ +static int hns_get_coalesce(struct net_device *net_dev, + struct ethtool_coalesce *ec) +{ + struct hns_nic_priv *priv = netdev_priv(net_dev); + struct hnae_ae_ops *ops; + + ops = priv->ae_handle->dev->ops; + + ec->use_adaptive_rx_coalesce = 1; + ec->use_adaptive_tx_coalesce = 1; + + if ((!ops->get_coalesce_usecs) || + (!ops->get_rx_max_coalesced_frames)) + return -ESRCH; + + ops->get_coalesce_usecs(priv->ae_handle, + &ec->tx_coalesce_usecs, + &ec->rx_coalesce_usecs); + + ops->get_rx_max_coalesced_frames( + priv->ae_handle, + &ec->tx_max_coalesced_frames, + &ec->rx_max_coalesced_frames); + + return 0; +} + +/** + * hns_set_coalesce - set coalesce info. + * @dev: net device + * @ec: coalesce info. + * + * Return 0 on success, negative on failure. + */ +static int hns_set_coalesce(struct net_device *net_dev, + struct ethtool_coalesce *ec) +{ + struct hns_nic_priv *priv = netdev_priv(net_dev); + struct hnae_ae_ops *ops; + int ret; + + assert(priv || priv->ae_handle); + + ops = priv->ae_handle->dev->ops; + + if (ec->tx_coalesce_usecs != ec->rx_coalesce_usecs) + return -EINVAL; + + if (ec->rx_max_coalesced_frames != ec->tx_max_coalesced_frames) + return -EINVAL; + + if ((!ops->set_coalesce_usecs) || + (!ops->set_coalesce_frames)) + return -ESRCH; + + ops->set_coalesce_usecs(priv->ae_handle, + ec->rx_coalesce_usecs); + + ret = ops->set_coalesce_frames( + priv->ae_handle, + ec->rx_max_coalesced_frames); + + return ret; +} + +/** + * hns_get_channels - get channel info. + * @dev: net device + * @ch: channel info. + */ +void hns_get_channels(struct net_device *net_dev, struct ethtool_channels *ch) +{ + struct hns_nic_priv *priv = netdev_priv(net_dev); + + ch->max_rx = priv->ae_handle->q_num; + ch->max_tx = priv->ae_handle->q_num; + + ch->rx_count = priv->ae_handle->q_num; + ch->tx_count = priv->ae_handle->q_num; +} + +/** + * get_ethtool_stats - get detail statistics. + * @dev: net device + * @stats: statistics info. + * @data: statistics data. + */ +void hns_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) +{ + u64 *p = data; + struct hns_nic_priv *priv = netdev_priv(netdev); + struct hnae_handle *h = priv->ae_handle; + const struct rtnl_link_stats64 *net_stats; + struct rtnl_link_stats64 temp; + + if (!h->dev->ops->get_stats || !h->dev->ops->update_stats) { + netdev_err(netdev, "get_stats or update_stats is null!\n"); + return; + } + + h->dev->ops->update_stats(h, &netdev->stats); + + net_stats = dev_get_stats(netdev, &temp); + + /* get netdev statistics */ + p[0] = net_stats->rx_packets; + p[1] = net_stats->tx_packets; + p[2] = net_stats->rx_bytes; + p[3] = net_stats->tx_bytes; + p[4] = net_stats->rx_errors; + p[5] = net_stats->tx_errors; + p[6] = net_stats->rx_dropped; + p[7] = net_stats->tx_dropped; + p[8] = net_stats->multicast; + p[9] = net_stats->collisions; + p[10] = net_stats->rx_over_errors; + p[11] = net_stats->rx_crc_errors; + p[12] = net_stats->rx_frame_errors; + p[13] = net_stats->rx_fifo_errors; + p[14] = net_stats->rx_missed_errors; + p[15] = net_stats->tx_aborted_errors; + p[16] = net_stats->tx_carrier_errors; + p[17] = net_stats->tx_fifo_errors; + p[18] = net_stats->tx_heartbeat_errors; + p[19] = net_stats->rx_length_errors; + p[20] = net_stats->tx_window_errors; + p[21] = net_stats->rx_compressed; + p[22] = net_stats->tx_compressed; + + p[23] = netdev->rx_dropped.counter; + p[24] = netdev->tx_dropped.counter; + + p[25] = priv->tx_timeout_count; + + /* get driver statistics */ + h->dev->ops->get_stats(h, &p[26]); +} + +/** + * get_strings: Return a set of strings that describe the requested objects + * @dev: net device + * @stats: string set ID. + * @data: objects data. + */ +void hns_get_strings(struct net_device *netdev, u32 stringset, u8 *data) +{ + struct hns_nic_priv *priv = netdev_priv(netdev); + struct hnae_handle *h = priv->ae_handle; + char *buff = (char *)data; + + if (!h->dev->ops->get_strings) { + netdev_err(netdev, "h->dev->ops->get_strings is null!\n"); + return; + } + + if (stringset == ETH_SS_TEST) { + if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII) { + memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_MAC], + ETH_GSTRING_LEN); + buff += ETH_GSTRING_LEN; + } + memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_SERDES], + ETH_GSTRING_LEN); + buff += ETH_GSTRING_LEN; + if ((priv->phy) && (!priv->phy->is_c45)) + memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_PHY], + ETH_GSTRING_LEN); + + } else { + snprintf(buff, ETH_GSTRING_LEN, "rx_packets"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_packets"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_bytes"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_bytes"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_dropped"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_dropped"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "multicast"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "collisions"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_over_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_crc_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_frame_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_fifo_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_missed_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_aborted_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_carrier_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_fifo_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_heartbeat_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_length_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_window_errors"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "rx_compressed"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "tx_compressed"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "netdev_rx_dropped"); + buff = buff + ETH_GSTRING_LEN; + snprintf(buff, ETH_GSTRING_LEN, "netdev_tx_dropped"); + buff = buff + ETH_GSTRING_LEN; + + snprintf(buff, ETH_GSTRING_LEN, "netdev_tx_timeout"); + buff = buff + ETH_GSTRING_LEN; + + h->dev->ops->get_strings(h, stringset, (u8 *)buff); + } +} + +/** + * nic_get_sset_count - get string set count witch returned by nic_get_strings. + * @dev: net device + * @stringset: string set index, 0: self test string; 1: statistics string. + * + * Return string set count. + */ +int hns_get_sset_count(struct net_device *netdev, int stringset) +{ + struct hns_nic_priv *priv = netdev_priv(netdev); + struct hnae_handle *h = priv->ae_handle; + struct hnae_ae_ops *ops = h->dev->ops; + + if (!ops->get_sset_count) { + netdev_err(netdev, "get_sset_count is null!\n"); + return -EOPNOTSUPP; + } + if (stringset == ETH_SS_TEST) { + u32 cnt = (sizeof(hns_nic_test_strs) / ETH_GSTRING_LEN); + + if (priv->ae_handle->phy_if == PHY_INTERFACE_MODE_XGMII) + cnt--; + + if ((!priv->phy) || (priv->phy->is_c45)) + cnt--; + + return cnt; + } else { + return (HNS_NET_STATS_CNT + ops->get_sset_count(h, stringset)); + } +} + +/** + * hns_phy_led_set - set phy LED status. + * @dev: net device + * @value: LED state. + * + * Return 0 on success, negative on failure. + */ +int hns_phy_led_set(struct net_device *netdev, int value) +{ + int retval; + struct hns_nic_priv *priv = netdev_priv(netdev); + struct phy_device *phy_dev = priv->phy; + + if (!phy_dev->bus) { + netdev_err(netdev, "phy_dev->bus is null!\n"); + return -EINVAL; + } + retval = mdiobus_write(phy_dev->bus, phy_dev->addr, + HNS_PHY_PAGE_REG, HNS_PHY_PAGE_LED); + retval = mdiobus_write(phy_dev->bus, phy_dev->addr, HNS_LED_FC_REG, + value); + retval = mdiobus_write(phy_dev->bus, phy_dev->addr, + HNS_PHY_PAGE_REG, HNS_PHY_PAGE_COPPER); + if (retval) { + netdev_err(netdev, "mdiobus_write fail !\n"); + return retval; + } + return 0; +} + +/** + * nic_set_phys_id - set phy identify LED. + * @dev: net device + * @state: LED state. + * + * Return 0 on success, negative on failure. + */ +int hns_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) +{ + struct hns_nic_priv *priv = netdev_priv(netdev); + struct hnae_handle *h = priv->ae_handle; + struct phy_device *phy_dev = priv->phy; + int ret; + + if (phy_dev) + switch (state) { + case ETHTOOL_ID_ACTIVE: + ret = mdiobus_write(phy_dev->bus, phy_dev->addr, + HNS_PHY_PAGE_REG, + HNS_PHY_PAGE_LED); + if (ret) + return ret; + + priv->phy_led_val = (u16)mdiobus_read(phy_dev->bus, + phy_dev->addr, + HNS_LED_FC_REG); + + ret = mdiobus_write(phy_dev->bus, phy_dev->addr, + HNS_PHY_PAGE_REG, + HNS_PHY_PAGE_COPPER); + if (ret) + return ret; + return 2; + case ETHTOOL_ID_ON: + ret = hns_phy_led_set(netdev, HNS_LED_FORCE_ON); + if (ret) + return ret; + break; + case ETHTOOL_ID_OFF: + ret = hns_phy_led_set(netdev, HNS_LED_FORCE_OFF); + if (ret) + return ret; + break; + case ETHTOOL_ID_INACTIVE: + ret = mdiobus_write(phy_dev->bus, phy_dev->addr, + HNS_PHY_PAGE_REG, + HNS_PHY_PAGE_LED); + if (ret) + return ret; + + ret = mdiobus_write(phy_dev->bus, phy_dev->addr, + HNS_LED_FC_REG, priv->phy_led_val); + if (ret) + return ret; + + ret = mdiobus_write(phy_dev->bus, phy_dev->addr, + HNS_PHY_PAGE_REG, + HNS_PHY_PAGE_COPPER); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + else + switch (state) { + case ETHTOOL_ID_ACTIVE: + return h->dev->ops->set_led_id(h, HNAE_LED_ACTIVE); + case ETHTOOL_ID_ON: + return h->dev->ops->set_led_id(h, HNAE_LED_ON); + case ETHTOOL_ID_OFF: + return h->dev->ops->set_led_id(h, HNAE_LED_OFF); + case ETHTOOL_ID_INACTIVE: + return h->dev->ops->set_led_id(h, HNAE_LED_INACTIVE); + default: + return -EINVAL; + } + + return 0; +} + +/** + * hns_get_regs - get net device register + * @dev: net device + * @cmd: ethtool cmd + * @date: register data + */ +void hns_get_regs(struct net_device *net_dev, struct ethtool_regs *cmd, + void *data) +{ + struct hns_nic_priv *priv = netdev_priv(net_dev); + struct hnae_ae_ops *ops; + + assert(priv || priv->ae_handle); + + ops = priv->ae_handle->dev->ops; + + cmd->version = HNS_CHIP_VERSION; + if (!ops->get_regs) { + netdev_err(net_dev, "ops->get_regs is null!\n"); + return; + } + ops->get_regs(priv->ae_handle, data); +} + +/** + * nic_get_regs_len - get total register len. + * @dev: net device + * + * Return total register len. + */ +static int hns_get_regs_len(struct net_device *net_dev) +{ + u32 reg_num; + struct hns_nic_priv *priv = netdev_priv(net_dev); + struct hnae_ae_ops *ops; + + assert(priv || priv->ae_handle); + + ops = priv->ae_handle->dev->ops; + if (!ops->get_regs_len) { + netdev_err(net_dev, "ops->get_regs_len is null!\n"); + return -EOPNOTSUPP; + } + + reg_num = ops->get_regs_len(priv->ae_handle); + if (reg_num > 0) + return reg_num * sizeof(u32); + else + return reg_num; /* error code */ +} + +/** + * hns_nic_nway_reset - nway reset + * @dev: net device + * + * Return 0 on success, negative on failure + */ +static int hns_nic_nway_reset(struct net_device *netdev) +{ + int ret = 0; + struct hns_nic_priv *priv = netdev_priv(netdev); + struct phy_device *phy = priv->phy; + + if (netif_running(netdev)) { + if (phy) + ret = genphy_restart_aneg(phy); + } + + return ret; +} + +static struct ethtool_ops hns_ethtool_ops = { + .get_drvinfo = hns_nic_get_drvinfo, + .get_link = hns_nic_get_link, + .get_settings = hns_nic_get_settings, + .set_settings = hns_nic_set_settings, + .get_ringparam = hns_get_ringparam, + .get_pauseparam = hns_get_pauseparam, + .set_pauseparam = hns_set_pauseparam, + .get_coalesce = hns_get_coalesce, + .set_coalesce = hns_set_coalesce, + .get_channels = hns_get_channels, + .self_test = hns_nic_self_test, + .get_strings = hns_get_strings, + .get_sset_count = hns_get_sset_count, + .get_ethtool_stats = hns_get_ethtool_stats, + .set_phys_id = hns_set_phys_id, + .get_regs_len = hns_get_regs_len, + .get_regs = hns_get_regs, + .nway_reset = hns_nic_nway_reset, +}; + +void hns_ethtool_set_ops(struct net_device *ndev) +{ + ndev->ethtool_ops = &hns_ethtool_ops; +} -- cgit v1.2.3 From 0012e5c9315c33fe8d62cb8cb87a95484d7761c1 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 6 Aug 2015 14:53:57 +0200 Subject: can: flexcan: cleanup coding style and fix typos This patch fixes up the coding style to make checkpatch happier. Some typos are also fixed. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 90 ++++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 52 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index c83f0f03482b..e9e8f095461c 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -63,10 +63,10 @@ #define FLEXCAN_MCR_LPRIO_EN BIT(13) #define FLEXCAN_MCR_AEN BIT(12) #define FLEXCAN_MCR_MAXMB(x) ((x) & 0x7f) -#define FLEXCAN_MCR_IDAM_A (0 << 8) -#define FLEXCAN_MCR_IDAM_B (1 << 8) -#define FLEXCAN_MCR_IDAM_C (2 << 8) -#define FLEXCAN_MCR_IDAM_D (3 << 8) +#define FLEXCAN_MCR_IDAM_A (0x0 << 8) +#define FLEXCAN_MCR_IDAM_B (0x1 << 8) +#define FLEXCAN_MCR_IDAM_C (0x2 << 8) +#define FLEXCAN_MCR_IDAM_D (0x3 << 8) /* FLEXCAN control register (CANCTRL) bits */ #define FLEXCAN_CTRL_PRESDIV(x) (((x) & 0xff) << 24) @@ -161,7 +161,7 @@ #define FLEXCAN_MB_CODE_RX_INACTIVE (0x0 << 24) #define FLEXCAN_MB_CODE_RX_EMPTY (0x4 << 24) #define FLEXCAN_MB_CODE_RX_FULL (0x2 << 24) -#define FLEXCAN_MB_CODE_RX_OVERRRUN (0x6 << 24) +#define FLEXCAN_MB_CODE_RX_OVERRUN (0x6 << 24) #define FLEXCAN_MB_CODE_RX_RANSWER (0xa << 24) #define FLEXCAN_MB_CODE_TX_INACTIVE (0x8 << 24) @@ -175,12 +175,9 @@ #define FLEXCAN_MB_CNT_LENGTH(x) (((x) & 0xf) << 16) #define FLEXCAN_MB_CNT_TIMESTAMP(x) ((x) & 0xffff) -#define FLEXCAN_MB_CODE_MASK (0xf0ffffff) +#define FLEXCAN_TIMEOUT_US (50) -#define FLEXCAN_TIMEOUT_US (50) - -/* - * FLEXCAN hardware feature flags +/* FLEXCAN hardware feature flags * * Below is some version info we got: * SOC Version IP-Version Glitch- [TR]WRN_INT Memory err RTR re- @@ -236,7 +233,7 @@ struct flexcan_regs { * 0x0e0...0x0ff 6-7 8 entry ID table * (mx25, mx28, mx35, mx53) * 0x0e0...0x2df 6-7..37 8..128 entry ID table - * size conf'ed via ctrl2::RFFN + * size conf'ed via ctrl2::RFFN * (mx6, vf610) */ u32 _reserved4[408]; @@ -272,10 +269,13 @@ struct flexcan_priv { static struct flexcan_devtype_data fsl_p1010_devtype_data = { .features = FLEXCAN_HAS_BROKEN_ERR_STATE, }; + static struct flexcan_devtype_data fsl_imx28_devtype_data; + static struct flexcan_devtype_data fsl_imx6q_devtype_data = { .features = FLEXCAN_HAS_V10_FEATURES, }; + static struct flexcan_devtype_data fsl_vf610_devtype_data = { .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_MECR_FEATURES, }; @@ -292,11 +292,10 @@ static const struct can_bittiming_const flexcan_bittiming_const = { .brp_inc = 1, }; -/* - * Abstract off the read/write for arm versus ppc. This +/* Abstract off the read/write for arm versus ppc. This * assumes that PPC uses big-endian registers and everything * else uses little-endian registers, independent of CPU - * endianess. + * endianness. */ #if defined(CONFIG_PPC) static inline u32 flexcan_read(void __iomem *addr) @@ -434,7 +433,6 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv) return 0; } - static int __flexcan_get_berr_counter(const struct net_device *dev, struct can_berr_counter *bec) { @@ -477,6 +475,7 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) struct flexcan_regs __iomem *regs = priv->base; struct can_frame *cf = (struct can_frame *)skb->data; u32 can_id; + u32 data; u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cf->can_dlc << 16); if (can_dropped_invalid_skb(dev, skb)) @@ -495,11 +494,11 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) ctrl |= FLEXCAN_MB_CNT_RTR; if (cf->can_dlc > 0) { - u32 data = be32_to_cpup((__be32 *)&cf->data[0]); + data = be32_to_cpup((__be32 *)&cf->data[0]); flexcan_write(data, ®s->cantxfg[FLEXCAN_TX_BUF_ID].data[0]); } if (cf->can_dlc > 3) { - u32 data = be32_to_cpup((__be32 *)&cf->data[4]); + data = be32_to_cpup((__be32 *)&cf->data[4]); flexcan_write(data, ®s->cantxfg[FLEXCAN_TX_BUF_ID].data[1]); } @@ -597,14 +596,14 @@ static int flexcan_poll_state(struct net_device *dev, u32 reg_esr) flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK; if (likely(flt == FLEXCAN_ESR_FLT_CONF_ACTIVE)) { tx_state = unlikely(reg_esr & FLEXCAN_ESR_TX_WRN) ? - CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE; + CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE; rx_state = unlikely(reg_esr & FLEXCAN_ESR_RX_WRN) ? - CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE; + CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE; new_state = max(tx_state, rx_state); } else { __flexcan_get_berr_counter(dev, &bec); new_state = flt == FLEXCAN_ESR_FLT_CONF_PASSIVE ? - CAN_STATE_ERROR_PASSIVE : CAN_STATE_BUS_OFF; + CAN_STATE_ERROR_PASSIVE : CAN_STATE_BUS_OFF; rx_state = bec.rxerr >= bec.txerr ? new_state : 0; tx_state = bec.rxerr <= bec.txerr ? new_state : 0; } @@ -687,8 +686,7 @@ static int flexcan_poll(struct napi_struct *napi, int quota) u32 reg_iflag1, reg_esr; int work_done = 0; - /* - * The error bits are cleared on read, + /* The error bits are cleared on read, * use saved value from irq handler. */ reg_esr = flexcan_read(®s->esr) | priv->reg_esr; @@ -728,12 +726,12 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) reg_iflag1 = flexcan_read(®s->iflag1); reg_esr = flexcan_read(®s->esr); + /* ACK all bus error and state change IRQ sources */ if (reg_esr & FLEXCAN_ESR_ALL_INT) flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, ®s->esr); - /* - * schedule NAPI in case of: + /* schedule NAPI in case of: * - rx IRQ * - state change IRQ * - bus error IRQ and bus error reporting is activated @@ -741,15 +739,14 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) if ((reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) || (reg_esr & FLEXCAN_ESR_ERR_STATE) || flexcan_has_and_handle_berr(priv, reg_esr)) { - /* - * The error bits are cleared on read, + /* The error bits are cleared on read, * save them for later use. */ priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS; flexcan_write(FLEXCAN_IFLAG_DEFAULT & - ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->imask1); + ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->imask1); flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, - ®s->ctrl); + ®s->ctrl); napi_schedule(&priv->napi); } @@ -765,7 +762,8 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) stats->tx_bytes += can_get_echo_skb(dev, 0); stats->tx_packets++; can_led_event(dev, CAN_LED_EVENT_TX); - /* after sending a RTR frame mailbox is in RX mode */ + + /* after sending a RTR frame MB is in RX mode */ flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1); @@ -813,8 +811,7 @@ static void flexcan_set_bittiming(struct net_device *dev) flexcan_read(®s->mcr), flexcan_read(®s->ctrl)); } -/* - * flexcan_chip_start +/* flexcan_chip_start * * this functions is entered with clocks enabled * @@ -838,8 +835,7 @@ static int flexcan_chip_start(struct net_device *dev) flexcan_set_bittiming(dev); - /* - * MCR + /* MCR * * enable freeze * enable fifo @@ -848,7 +844,6 @@ static int flexcan_chip_start(struct net_device *dev) * enable warning int * choose format C * disable local echo - * */ reg_mcr = flexcan_read(®s->mcr); reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff); @@ -859,8 +854,7 @@ static int flexcan_chip_start(struct net_device *dev) netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr); flexcan_write(reg_mcr, ®s->mcr); - /* - * CTRL + /* CTRL * * disable timer sync feature * @@ -875,8 +869,8 @@ static int flexcan_chip_start(struct net_device *dev) reg_ctrl &= ~FLEXCAN_CTRL_TSYN; reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF | FLEXCAN_CTRL_ERR_STATE; - /* - * enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK), + + /* enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK), * on most Flexcan cores, too. Otherwise we don't get * any error warning or passive interrupts. */ @@ -913,16 +907,14 @@ static int flexcan_chip_start(struct net_device *dev) if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) flexcan_write(0x0, ®s->rxfgmask); - /* - * On Vybrid, disable memory error detection interrupts + /* On Vybrid, disable memory error detection interrupts * and freeze mode. * This also works around errata e5295 which generates * false positive memory errors and put the device in * freeze mode. */ if (priv->devtype_data->features & FLEXCAN_HAS_MECR_FEATURES) { - /* - * Follow the protocol as described in "Detection + /* Follow the protocol as described in "Detection * and Correction of Memory Errors" to write to * MECR register */ @@ -934,7 +926,7 @@ static int flexcan_chip_start(struct net_device *dev) reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS; flexcan_write(reg_mecr, ®s->mecr); reg_mecr &= ~(FLEXCAN_MECR_NCEFAFRZ | FLEXCAN_MECR_HANCEI_MSK | - FLEXCAN_MECR_FANCEI_MSK); + FLEXCAN_MECR_FANCEI_MSK); flexcan_write(reg_mecr, ®s->mecr); } @@ -965,11 +957,9 @@ static int flexcan_chip_start(struct net_device *dev) return err; } -/* - * flexcan_chip_stop +/* flexcan_chip_stop * * this functions is entered with clocks enabled - * */ static void flexcan_chip_stop(struct net_device *dev) { @@ -987,8 +977,6 @@ static void flexcan_chip_stop(struct net_device *dev) flexcan_transceiver_disable(priv); priv->can.state = CAN_STATE_STOPPED; - - return; } static int flexcan_open(struct net_device *dev) @@ -1114,8 +1102,7 @@ static int register_flexcandev(struct net_device *dev) FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV; flexcan_write(reg, ®s->mcr); - /* - * Currently we only support newer versions of this core + /* Currently we only support newer versions of this core * featuring a RX FIFO. Older cores found on some Coldfire * derivates are not yet supported. */ @@ -1180,7 +1167,7 @@ static int flexcan_probe(struct platform_device *pdev) if (pdev->dev.of_node) of_property_read_u32(pdev->dev.of_node, - "clock-frequency", &clock_freq); + "clock-frequency", &clock_freq); if (!clock_freq) { clk_ipg = devm_clk_get(&pdev->dev, "ipg"); @@ -1237,7 +1224,6 @@ static int flexcan_probe(struct platform_device *pdev) priv->clk_per = clk_per; priv->pdata = dev_get_platdata(&pdev->dev); priv->devtype_data = devtype_data; - priv->reg_xceiver = reg_xceiver; netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT); -- cgit v1.2.3 From 8c411745dd6ddbe745ee25cd1f6db856e920e7fa Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Sat, 9 May 2015 18:25:05 +0200 Subject: can: flexcan: remove unused header files This patch removes unused header files from the flexcan driver. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index e9e8f095461c..83ea6f4f7164 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -26,12 +26,8 @@ #include #include #include -#include -#include #include #include -#include -#include #include #include #include -- cgit v1.2.3 From 749de6fce2dd67b40f4118bf694be37f9093c3f5 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 31 Aug 2015 21:32:34 +0200 Subject: can: flexcan: flexcan_chip_start(): cleanup writing of reg_mcr This patch changes the order the individual bits of the mcr register in flexcan_chip_start() are or'ed together to match the datasheet. The inline documentation is adjusted accordingly. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 83ea6f4f7164..70cdbfcebb46 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -838,15 +838,15 @@ static int flexcan_chip_start(struct net_device *dev) * halt now * only supervisor access * enable warning int - * choose format C * disable local echo + * choose format C + * set max mailbox number */ reg_mcr = flexcan_read(®s->mcr); reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff); reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT | - FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | - FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS | - FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID); + FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS | + FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID); netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr); flexcan_write(reg_mcr, ®s->mcr); -- cgit v1.2.3 From f377bff0235708ded5f94e581855d6bd678cd2d1 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 8 May 2015 15:22:36 +0200 Subject: can: flexcan: rename feature into quirks This patch renames the "features" member of struct flexcan_devtype_data to "quirks". The corresponding defines are renamed too, to reflect what they actually do. FLEXCAN_HAS_V10_FEATURES -> FLEXCAN_QUIRK_DISABLE_RXFG FLEXCAN_HAS_BROKEN_ERR_STATE -> FLEXCAN_QUIRK_BROKEN_ERR_STATE FLEXCAN_HAS_MECR_FEATURES -> FLEXCAN_QUIRK_DISABLE_MECR Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 70cdbfcebb46..dd5a9353e0c5 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -187,9 +187,9 @@ * * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. */ -#define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ -#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */ -#define FLEXCAN_HAS_MECR_FEATURES BIT(3) /* Memory error detection */ +#define FLEXCAN_QUIRK_BROKEN_ERR_STATE BIT(1) /* [TR]WRN_INT not connected */ +#define FLEXCAN_QUIRK_DISABLE_RXFG BIT(2) /* Disable RX FIFO Global mask */ +#define FLEXCAN_QUIRK_DISABLE_MECR BIT(3) /* Disble Memory error detection */ /* Structure of the message buffer */ struct flexcan_mb { @@ -244,7 +244,7 @@ struct flexcan_regs { }; struct flexcan_devtype_data { - u32 features; /* hardware controller features */ + u32 quirks; /* quirks needed for different IP cores */ }; struct flexcan_priv { @@ -263,17 +263,17 @@ struct flexcan_priv { }; static struct flexcan_devtype_data fsl_p1010_devtype_data = { - .features = FLEXCAN_HAS_BROKEN_ERR_STATE, + .quirks = FLEXCAN_QUIRK_BROKEN_ERR_STATE, }; static struct flexcan_devtype_data fsl_imx28_devtype_data; static struct flexcan_devtype_data fsl_imx6q_devtype_data = { - .features = FLEXCAN_HAS_V10_FEATURES, + .quirks = FLEXCAN_QUIRK_DISABLE_RXFG, }; static struct flexcan_devtype_data fsl_vf610_devtype_data = { - .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_MECR_FEATURES, + .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_DISABLE_MECR, }; static const struct can_bittiming_const flexcan_bittiming_const = { @@ -870,7 +870,7 @@ static int flexcan_chip_start(struct net_device *dev) * on most Flexcan cores, too. Otherwise we don't get * any error warning or passive interrupts. */ - if (priv->devtype_data->features & FLEXCAN_HAS_BROKEN_ERR_STATE || + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_ERR_STATE || priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) reg_ctrl |= FLEXCAN_CTRL_ERR_MSK; else @@ -900,7 +900,7 @@ static int flexcan_chip_start(struct net_device *dev) flexcan_write(0x0, ®s->rx14mask); flexcan_write(0x0, ®s->rx15mask); - if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG) flexcan_write(0x0, ®s->rxfgmask); /* On Vybrid, disable memory error detection interrupts @@ -909,7 +909,7 @@ static int flexcan_chip_start(struct net_device *dev) * false positive memory errors and put the device in * freeze mode. */ - if (priv->devtype_data->features & FLEXCAN_HAS_MECR_FEATURES) { + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_MECR) { /* Follow the protocol as described in "Detection * and Correction of Memory Errors" to write to * MECR register -- cgit v1.2.3 From 89af8746dea940c66f414866eed2a964a348dc09 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 8 May 2015 09:32:58 +0200 Subject: can: flexcan: use pointer to struct regs instead of void pointer for mmio address space This patch renames the pointer to the mmio address space from "base" to "regs" and changes the type from "void __iomem *" to "struct flexcan_regs __iomem *". Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index dd5a9353e0c5..72831c52ff53 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -251,7 +251,7 @@ struct flexcan_priv { struct can_priv can; struct napi_struct napi; - void __iomem *base; + struct flexcan_regs __iomem *regs; u32 reg_esr; u32 reg_ctrl_default; @@ -340,7 +340,7 @@ static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv, static int flexcan_chip_enable(struct flexcan_priv *priv) { - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; u32 reg; @@ -359,7 +359,7 @@ static int flexcan_chip_enable(struct flexcan_priv *priv) static int flexcan_chip_disable(struct flexcan_priv *priv) { - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; u32 reg; @@ -378,7 +378,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv) static int flexcan_chip_freeze(struct flexcan_priv *priv) { - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate; u32 reg; @@ -397,7 +397,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv) static int flexcan_chip_unfreeze(struct flexcan_priv *priv) { - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; u32 reg; @@ -416,7 +416,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv) static int flexcan_chip_softreset(struct flexcan_priv *priv) { - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); @@ -433,7 +433,7 @@ static int __flexcan_get_berr_counter(const struct net_device *dev, struct can_berr_counter *bec) { const struct flexcan_priv *priv = netdev_priv(dev); - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; u32 reg = flexcan_read(®s->ecr); bec->txerr = (reg >> 0) & 0xff; @@ -468,7 +468,7 @@ static int flexcan_get_berr_counter(const struct net_device *dev, static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) { const struct flexcan_priv *priv = netdev_priv(dev); - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; struct can_frame *cf = (struct can_frame *)skb->data; u32 can_id; u32 data; @@ -628,7 +628,7 @@ static void flexcan_read_fifo(const struct net_device *dev, struct can_frame *cf) { const struct flexcan_priv *priv = netdev_priv(dev); - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; struct flexcan_mb __iomem *mb = ®s->cantxfg[0]; u32 reg_ctrl, reg_id; @@ -678,7 +678,7 @@ static int flexcan_poll(struct napi_struct *napi, int quota) { struct net_device *dev = napi->dev; const struct flexcan_priv *priv = netdev_priv(dev); - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; u32 reg_iflag1, reg_esr; int work_done = 0; @@ -717,7 +717,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) struct net_device *dev = dev_id; struct net_device_stats *stats = &dev->stats; struct flexcan_priv *priv = netdev_priv(dev); - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; u32 reg_iflag1, reg_esr; reg_iflag1 = flexcan_read(®s->iflag1); @@ -773,7 +773,7 @@ static void flexcan_set_bittiming(struct net_device *dev) { const struct flexcan_priv *priv = netdev_priv(dev); const struct can_bittiming *bt = &priv->can.bittiming; - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; u32 reg; reg = flexcan_read(®s->ctrl); @@ -815,7 +815,7 @@ static void flexcan_set_bittiming(struct net_device *dev) static int flexcan_chip_start(struct net_device *dev) { struct flexcan_priv *priv = netdev_priv(dev); - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; u32 reg_mcr, reg_ctrl, reg_ctrl2, reg_mecr; int err, i; @@ -960,7 +960,7 @@ static int flexcan_chip_start(struct net_device *dev) static void flexcan_chip_stop(struct net_device *dev) { struct flexcan_priv *priv = netdev_priv(dev); - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; /* freeze + disable module */ flexcan_chip_freeze(priv); @@ -1069,7 +1069,7 @@ static const struct net_device_ops flexcan_netdev_ops = { static int register_flexcandev(struct net_device *dev) { struct flexcan_priv *priv = netdev_priv(dev); - struct flexcan_regs __iomem *regs = priv->base; + struct flexcan_regs __iomem *regs = priv->regs; u32 reg, err; err = clk_prepare_enable(priv->clk_ipg); @@ -1151,7 +1151,7 @@ static int flexcan_probe(struct platform_device *pdev) struct regulator *reg_xceiver; struct resource *mem; struct clk *clk_ipg = NULL, *clk_per = NULL; - void __iomem *base; + struct flexcan_regs __iomem *regs; int err, irq; u32 clock_freq = 0; @@ -1185,9 +1185,9 @@ static int flexcan_probe(struct platform_device *pdev) if (irq <= 0) return -ENODEV; - base = devm_ioremap_resource(&pdev->dev, mem); - if (IS_ERR(base)) - return PTR_ERR(base); + regs = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(regs)) + return PTR_ERR(regs); of_id = of_match_device(flexcan_of_match, &pdev->dev); if (of_id) { @@ -1215,7 +1215,7 @@ static int flexcan_probe(struct platform_device *pdev) priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_BERR_REPORTING; - priv->base = base; + priv->regs = regs; priv->clk_ipg = clk_ipg; priv->clk_per = clk_per; priv->pdata = dev_get_platdata(&pdev->dev); @@ -1236,7 +1236,7 @@ static int flexcan_probe(struct platform_device *pdev) devm_can_led_init(dev); dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n", - priv->base, dev->irq); + priv->regs, dev->irq); return 0; -- cgit v1.2.3 From 1ba763d1d4bda61bfb9b8e5154e6cf39a3e2d0e6 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 25 Aug 2015 10:39:19 +0200 Subject: can: flexcan: give member of flexcan_priv holding mailboxes a sensible name This patch gives the member of flexcan_priv holding mailboxes a sensible name, by renaming from "cantxfg" to "mb": struct flexcan_priv::cantxfg -> struct flexcan_priv::mb Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 72831c52ff53..28b6283aacf2 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -221,7 +221,7 @@ struct flexcan_regs { u32 rxfgmask; /* 0x48 */ u32 rxfir; /* 0x4c */ u32 _reserved3[12]; /* 0x50 */ - struct flexcan_mb cantxfg[64]; /* 0x80 */ + struct flexcan_mb mb[64]; /* 0x80 */ /* FIFO-mode: * MB * 0x080...0x08f 0 RX message buffer @@ -491,25 +491,25 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) if (cf->can_dlc > 0) { data = be32_to_cpup((__be32 *)&cf->data[0]); - flexcan_write(data, ®s->cantxfg[FLEXCAN_TX_BUF_ID].data[0]); + flexcan_write(data, ®s->mb[FLEXCAN_TX_BUF_ID].data[0]); } if (cf->can_dlc > 3) { data = be32_to_cpup((__be32 *)&cf->data[4]); - flexcan_write(data, ®s->cantxfg[FLEXCAN_TX_BUF_ID].data[1]); + flexcan_write(data, ®s->mb[FLEXCAN_TX_BUF_ID].data[1]); } can_put_echo_skb(skb, dev, 0); - flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id); - flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); + flexcan_write(can_id, ®s->mb[FLEXCAN_TX_BUF_ID].can_id); + flexcan_write(ctrl, ®s->mb[FLEXCAN_TX_BUF_ID].can_ctrl); /* Errata ERR005829 step8: * Write twice INACTIVE(0x8) code to first MB. */ flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, - ®s->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl); + ®s->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl); flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, - ®s->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl); + ®s->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl); return NETDEV_TX_OK; } @@ -629,7 +629,7 @@ static void flexcan_read_fifo(const struct net_device *dev, { const struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_regs __iomem *regs = priv->regs; - struct flexcan_mb __iomem *mb = ®s->cantxfg[0]; + struct flexcan_mb __iomem *mb = ®s->mb[0]; u32 reg_ctrl, reg_id; reg_ctrl = flexcan_read(&mb->can_ctrl); @@ -761,7 +761,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) /* after sending a RTR frame MB is in RX mode */ flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, - ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); + ®s->mb[FLEXCAN_TX_BUF_ID].can_ctrl); flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1); netif_wake_queue(dev); } @@ -882,18 +882,18 @@ static int flexcan_chip_start(struct net_device *dev) flexcan_write(reg_ctrl, ®s->ctrl); /* clear and invalidate all mailboxes first */ - for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->cantxfg); i++) { + for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->mb); i++) { flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE, - ®s->cantxfg[i].can_ctrl); + ®s->mb[i].can_ctrl); } /* Errata ERR005829: mark first TX mailbox as INACTIVE */ flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, - ®s->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl); + ®s->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl); /* mark TX mailbox as INACTIVE */ flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, - ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); + ®s->mb[FLEXCAN_TX_BUF_ID].can_ctrl); /* acceptance mask/acceptance code (accept everything) */ flexcan_write(0x0, ®s->rxgmask); -- cgit v1.2.3 From 6fa7da249269a6146ce456c43098901c81c8afdf Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 27 Aug 2015 14:24:48 +0200 Subject: can: flexcan: enable interrupts atomically at the end of flexcan_chip_start() This patch defers the writing of the interrupts bits of the CTRL register order to enables all interrupts atomically at the the of the flexcan_chip_start() function. Suggested-by: Torsten Lang Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 28b6283aacf2..868fe945e35a 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -878,6 +878,8 @@ static int flexcan_chip_start(struct net_device *dev) /* save for later use */ priv->reg_ctrl_default = reg_ctrl; + /* leave interrupts disabled for now */ + reg_ctrl &= ~FLEXCAN_CTRL_ERR_ALL; netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); flexcan_write(reg_ctrl, ®s->ctrl); @@ -937,8 +939,11 @@ static int flexcan_chip_start(struct net_device *dev) priv->can.state = CAN_STATE_ERROR_ACTIVE; - /* enable FIFO interrupts */ + /* enable interrupts atomically */ + disable_irq(dev->irq); + flexcan_write(priv->reg_ctrl_default, ®s->ctrl); flexcan_write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); + enable_irq(dev->irq); /* print chip status */ netdev_dbg(dev, "%s: reading mcr=0x%08x ctrl=0x%08x\n", __func__, -- cgit v1.2.3 From 89ced540eb3527669bac0a3239a408fb1129f0dc Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 26 Aug 2015 13:50:59 +0300 Subject: iwlwifi: mvm: remove IWL_UCODE_TLV_API_HDC_PHASE_0 TLV flag All the supported firwmares support the new API. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luciano Coelho Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/iwl-fw-file.h | 2 -- drivers/net/wireless/iwlwifi/iwl-io.c | 1 + drivers/net/wireless/iwlwifi/mvm/fw.c | 16 ---------------- 3 files changed, 1 insertion(+), 18 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 483b12741b2d..55ff72e1563e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h @@ -247,7 +247,6 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t; * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time * longer than the passive one, which is essential for fragmented scan. * @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source. - * IWL_UCODE_TLV_API_HDC_PHASE_0: ucode supports finer configuration of LTR * @IWL_UCODE_TLV_API_TX_POWER_DEV: new API for tx power. * @IWL_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header * @IWL_UCODE_TLV_API_SINGLE_SCAN_EBS: EBS is supported for single scans too. @@ -264,7 +263,6 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_BT_COEX_SPLIT = (__force iwl_ucode_tlv_api_t)3, IWL_UCODE_TLV_API_FRAGMENTED_SCAN = (__force iwl_ucode_tlv_api_t)8, IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = (__force iwl_ucode_tlv_api_t)9, - IWL_UCODE_TLV_API_HDC_PHASE_0 = (__force iwl_ucode_tlv_api_t)10, IWL_UCODE_TLV_API_TX_POWER_DEV = (__force iwl_ucode_tlv_api_t)11, IWL_UCODE_TLV_API_WIDE_CMD_HDR = (__force iwl_ucode_tlv_api_t)14, IWL_UCODE_TLV_API_SINGLE_SCAN_EBS = (__force iwl_ucode_tlv_api_t)16, diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 3c263a15df89..0bd9d4aad0c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -53,6 +53,7 @@ IWL_EXPORT_SYMBOL(iwl_write32); u32 iwl_read32(struct iwl_trans *trans, u32 ofs) { u32 val = iwl_trans_read32(trans, ofs); + trace_iwlwifi_dev_ioread32(trans->dev, ofs, val); return val; } diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 4a0ce83315bd..248b025b5c59 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c @@ -940,19 +940,6 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id) return ret; } -static int iwl_mvm_config_ltr_v1(struct iwl_mvm *mvm) -{ - struct iwl_ltr_config_cmd_v1 cmd_v1 = { - .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE), - }; - - if (!mvm->trans->ltr_enabled) - return 0; - - return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, - sizeof(cmd_v1), &cmd_v1); -} - static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) { struct iwl_ltr_config_cmd cmd = { @@ -962,9 +949,6 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) if (!mvm->trans->ltr_enabled) return 0; - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_HDC_PHASE_0)) - return iwl_mvm_config_ltr_v1(mvm); - return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, sizeof(cmd), &cmd); } -- cgit v1.2.3 From 4d31eed13f2a2234e86aa178918e129b6e33a9ee Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 26 Aug 2015 13:52:54 +0300 Subject: iwlwifi: mvm: remove IWL_UCODE_TLV_API_TX_POWER_DEV TLV flag All the supported firmwares use the new API. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/iwl-fw-file.h | 2 -- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 17 ----------------- 2 files changed, 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 55ff72e1563e..7af0ec20c4cc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h @@ -247,7 +247,6 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t; * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time * longer than the passive one, which is essential for fragmented scan. * @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source. - * @IWL_UCODE_TLV_API_TX_POWER_DEV: new API for tx power. * @IWL_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header * @IWL_UCODE_TLV_API_SINGLE_SCAN_EBS: EBS is supported for single scans too. * @IWL_UCODE_TLV_API_ASYNC_DTM: Async temperature notifications are supported. @@ -263,7 +262,6 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_BT_COEX_SPLIT = (__force iwl_ucode_tlv_api_t)3, IWL_UCODE_TLV_API_FRAGMENTED_SCAN = (__force iwl_ucode_tlv_api_t)8, IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = (__force iwl_ucode_tlv_api_t)9, - IWL_UCODE_TLV_API_TX_POWER_DEV = (__force iwl_ucode_tlv_api_t)11, IWL_UCODE_TLV_API_WIDE_CMD_HDR = (__force iwl_ucode_tlv_api_t)14, IWL_UCODE_TLV_API_SINGLE_SCAN_EBS = (__force iwl_ucode_tlv_api_t)16, IWL_UCODE_TLV_API_ASYNC_DTM = (__force iwl_ucode_tlv_api_t)17, diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index f9f88e913e03..4c497fe99878 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1577,20 +1577,6 @@ static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm) return NULL; } -static int iwl_mvm_set_tx_power_old(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, s8 tx_power) -{ - /* FW is in charge of regulatory enforcement */ - struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = { - .mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id, - .pwr_restriction = cpu_to_le16(tx_power), - }; - - return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, - sizeof(reduce_txpwr_cmd), - &reduce_txpwr_cmd); -} - static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, s16 tx_power) { @@ -1602,9 +1588,6 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, }; int len = sizeof(cmd); - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_TX_POWER_DEV)) - return iwl_mvm_set_tx_power_old(mvm, vif, tx_power); - if (tx_power == IWL_DEFAULT_MAX_TX_POWER) cmd.v2.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER); -- cgit v1.2.3 From eb991c5ec18ba41bfa2c206c22bceae94f6f3c15 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 26 Aug 2015 13:55:11 +0300 Subject: iwlwifi: mvm: remove IWL_UCODE_TLV_API_SINGLE_SCAN_EBS TLV flag All the supported firmwares have this flag set. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/iwl-fw-file.h | 2 -- drivers/net/wireless/iwlwifi/mvm/scan.c | 2 -- 2 files changed, 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 7af0ec20c4cc..880962ebd9cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h @@ -248,7 +248,6 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t; * longer than the passive one, which is essential for fragmented scan. * @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source. * @IWL_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header - * @IWL_UCODE_TLV_API_SINGLE_SCAN_EBS: EBS is supported for single scans too. * @IWL_UCODE_TLV_API_ASYNC_DTM: Async temperature notifications are supported. * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params * @IWL_UCODE_TLV_API_STATS_V10: uCode supports/uses statistics API version 10 @@ -263,7 +262,6 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_FRAGMENTED_SCAN = (__force iwl_ucode_tlv_api_t)8, IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = (__force iwl_ucode_tlv_api_t)9, IWL_UCODE_TLV_API_WIDE_CMD_HDR = (__force iwl_ucode_tlv_api_t)14, - IWL_UCODE_TLV_API_SINGLE_SCAN_EBS = (__force iwl_ucode_tlv_api_t)16, IWL_UCODE_TLV_API_ASYNC_DTM = (__force iwl_ucode_tlv_api_t)17, IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18, IWL_UCODE_TLV_API_STATS_V10 = (__force iwl_ucode_tlv_api_t)19, diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 56559d4d34ad..4a1f9af63bf0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -750,8 +750,6 @@ static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, */ return ((capa->flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT) && mvm->last_ebs_successful && - (n_iterations > 1 || - fw_has_api(capa, IWL_UCODE_TLV_API_SINGLE_SCAN_EBS)) && vif->type != NL80211_IFTYPE_P2P_DEVICE); } -- cgit v1.2.3 From 9d43fa4b4a0e46881d7d4fb3bc689a17d2f72257 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 26 Aug 2015 13:57:37 +0300 Subject: iwlwifi: mvm: remove IWL_UCODE_TLV_API_ASYNC_DTM TLV flag This flag is set in all supported firmwares. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/iwl-fw-file.h | 2 -- drivers/net/wireless/iwlwifi/mvm/rx.c | 6 ------ 2 files changed, 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 880962ebd9cb..104468bf70e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h @@ -248,7 +248,6 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t; * longer than the passive one, which is essential for fragmented scan. * @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source. * @IWL_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header - * @IWL_UCODE_TLV_API_ASYNC_DTM: Async temperature notifications are supported. * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params * @IWL_UCODE_TLV_API_STATS_V10: uCode supports/uses statistics API version 10 * @IWL_UCODE_TLV_API_NEW_VERSION: new versioning format @@ -262,7 +261,6 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_FRAGMENTED_SCAN = (__force iwl_ucode_tlv_api_t)8, IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = (__force iwl_ucode_tlv_api_t)9, IWL_UCODE_TLV_API_WIDE_CMD_HDR = (__force iwl_ucode_tlv_api_t)14, - IWL_UCODE_TLV_API_ASYNC_DTM = (__force iwl_ucode_tlv_api_t)17, IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18, IWL_UCODE_TLV_API_STATS_V10 = (__force iwl_ucode_tlv_api_t)19, IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20, diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 2ad814df0b3c..b620142953b6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c @@ -621,12 +621,6 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm, iwl_mvm_rx_stats_check_trigger(mvm, pkt); - /* Only handle rx statistics temperature changes if async temp - * notifications are not supported - */ - if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_ASYNC_DTM)) - iwl_mvm_tt_temp_changed(mvm, temperature); - ieee80211_iterate_active_interfaces(mvm->hw, IEEE80211_IFACE_ITER_NORMAL, iwl_mvm_stat_iterator, -- cgit v1.2.3 From 38d5f66f062a65bfc436013135a817e53037ccca Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 26 Aug 2015 14:03:02 +0300 Subject: iwlwifi: mvm: remove IWL_UCODE_TLV_API_STATS_V10 TLV flag This flag is set in all supported firmwares. Signed-off-by: Emmanuel Grumbach Signed-off-by: Luciano Coelho --- drivers/net/wireless/iwlwifi/iwl-fw-file.h | 2 -- drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h | 33 ----------------- drivers/net/wireless/iwlwifi/mvm/rx.c | 47 ++++++++----------------- 3 files changed, 15 insertions(+), 67 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 104468bf70e1..352d245765e7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h @@ -249,7 +249,6 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t; * @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source. * @IWL_UCODE_TLV_API_WIDE_CMD_HDR: ucode supports wide command header * @IWL_UCODE_TLV_API_LQ_SS_PARAMS: Configure STBC/BFER via LQ CMD ss_params - * @IWL_UCODE_TLV_API_STATS_V10: uCode supports/uses statistics API version 10 * @IWL_UCODE_TLV_API_NEW_VERSION: new versioning format * @IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY: scan APIs use 8-level priority * instead of 3. @@ -262,7 +261,6 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = (__force iwl_ucode_tlv_api_t)9, IWL_UCODE_TLV_API_WIDE_CMD_HDR = (__force iwl_ucode_tlv_api_t)14, IWL_UCODE_TLV_API_LQ_SS_PARAMS = (__force iwl_ucode_tlv_api_t)18, - IWL_UCODE_TLV_API_STATS_V10 = (__force iwl_ucode_tlv_api_t)19, IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20, IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY = (__force iwl_ucode_tlv_api_t)24, IWL_UCODE_TLV_API_TX_POWER_CHAIN = (__force iwl_ucode_tlv_api_t)27, diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h index 4ca4bceb95a4..0c321f63ee42 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h @@ -219,32 +219,6 @@ struct mvm_statistics_bt_activity { __le32 lo_priority_rx_denied_cnt; } __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */ -struct mvm_statistics_general_v5 { - __le32 radio_temperature; - __le32 radio_voltage; - struct mvm_statistics_dbg dbg; - __le32 sleep_time; - __le32 slots_out; - __le32 slots_idle; - __le32 ttl_timestamp; - struct mvm_statistics_div slow_div; - __le32 rx_enable_counter; - /* - * num_of_sos_states: - * count the number of times we have to re-tune - * in order to get out of bad PHY status - */ - __le32 num_of_sos_states; - __le32 beacon_filtered; - __le32 missed_beacons; - u8 beacon_filter_average_energy; - u8 beacon_filter_reason; - u8 beacon_filter_current_energy; - u8 beacon_filter_reserved; - __le32 beacon_filter_delta_time; - struct mvm_statistics_bt_activity bt_activity; -} __packed; /* STATISTICS_GENERAL_API_S_VER_5 */ - struct mvm_statistics_general_v8 { __le32 radio_temperature; __le32 radio_voltage; @@ -293,13 +267,6 @@ struct mvm_statistics_rx { * STATISTICS_CMD (0x9c), below. */ -struct iwl_notif_statistics_v8 { - __le32 flag; - struct mvm_statistics_rx rx; - struct mvm_statistics_tx tx; - struct mvm_statistics_general_v5 general; -} __packed; /* STATISTICS_NTFY_API_S_VER_8 */ - struct iwl_notif_statistics_v10 { __le32 flag; struct mvm_statistics_rx rx; diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index b620142953b6..c203a1bc3902 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c @@ -577,47 +577,30 @@ iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt) void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt) { - size_t v8_len = sizeof(struct iwl_notif_statistics_v8); - size_t v10_len = sizeof(struct iwl_notif_statistics_v10); + struct iwl_notif_statistics_v10 *stats = (void *)&pkt->data; struct iwl_mvm_stat_data data = { .mvm = mvm, }; u32 temperature; - if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STATS_V10)) { - struct iwl_notif_statistics_v10 *stats = (void *)&pkt->data; + if (iwl_rx_packet_payload_len(pkt) != sizeof(*stats)) + goto invalid; - if (iwl_rx_packet_payload_len(pkt) != v10_len) - 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; - 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; + iwl_mvm_update_rx_statistics(mvm, &stats->rx); - iwl_mvm_update_rx_statistics(mvm, &stats->rx); + mvm->radio_stats.rx_time = le64_to_cpu(stats->general.rx_time); + mvm->radio_stats.tx_time = le64_to_cpu(stats->general.tx_time); + mvm->radio_stats.on_time_rf = + le64_to_cpu(stats->general.on_time_rf); + mvm->radio_stats.on_time_scan = + le64_to_cpu(stats->general.on_time_scan); - mvm->radio_stats.rx_time = le64_to_cpu(stats->general.rx_time); - mvm->radio_stats.tx_time = le64_to_cpu(stats->general.tx_time); - mvm->radio_stats.on_time_rf = - le64_to_cpu(stats->general.on_time_rf); - mvm->radio_stats.on_time_scan = - le64_to_cpu(stats->general.on_time_scan); - - data.general = &stats->general; - } else { - struct iwl_notif_statistics_v8 *stats = (void *)&pkt->data; - - if (iwl_rx_packet_payload_len(pkt) != v8_len) - 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; - - iwl_mvm_update_rx_statistics(mvm, &stats->rx); - } + data.general = &stats->general; iwl_mvm_rx_stats_check_trigger(mvm, pkt); -- cgit v1.2.3 From da583fdfececf69571d3b8fafed278310592eec1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 26 Aug 2015 15:55:04 +0200 Subject: iwlwifi: mvm: make sure AP is operating for ToF It's possible for an AP interface to be UP but not actually operating (i.e. not beaconing etc.) - in this case it can't actually do ToF, so check for it. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/tof.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/tof.c b/drivers/net/wireless/iwlwifi/mvm/tof.c index 380972f8fb82..7ae0bd894c82 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tof.c +++ b/drivers/net/wireless/iwlwifi/mvm/tof.c @@ -178,7 +178,8 @@ int iwl_mvm_tof_responder_cmd(struct iwl_mvm *mvm, if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT)) return -EINVAL; - if (vif->p2p || vif->type != NL80211_IFTYPE_AP) { + if (vif->p2p || vif->type != NL80211_IFTYPE_AP || + !mvmvif->ap_ibss_active) { IWL_ERR(mvm, "Cannot start responder, not in AP mode\n"); return -EIO; } -- cgit v1.2.3 From 7f89a58efc0a18ec4a6eb7fdcf9ab73d426ce11f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 2 Sep 2015 11:51:23 +0200 Subject: iwlwifi: mvm: remove useless debug message from RX This message is useless - it's in the good case that always happens so enabling it doesn't really help. Just remove it. There are other ways to debug this (e.g. tracing) so there's no need to add a message in the bad case. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/rx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index c203a1bc3902..623c2198b2ba 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c @@ -202,7 +202,6 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm, return -1; stats->flag |= RX_FLAG_DECRYPTED; - IWL_DEBUG_WEP(mvm, "hw decrypted CCMP successfully\n"); *crypt_len = IEEE80211_CCMP_HDR_LEN; return 0; -- cgit v1.2.3 From abfd794c59c7cbfe31a5d1471e5868d4dbd74205 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 2 Sep 2015 12:26:45 +0200 Subject: iwlwifi: mvm: remove pointless cfg_phy_cnt length check Since the driver can never configure the data here, this field will always be reported as 0 by the firmware. Even if this was not the case, however, it wouldn't matter since the extra data would be added beyond the end of the phy_info structure we use in the driver, so wouldn't harm anything in this code either. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/rx.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 623c2198b2ba..0a6d47c5bfc8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c @@ -298,13 +298,6 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, return; } - if ((unlikely(phy_info->cfg_phy_cnt > 20))) { - IWL_DEBUG_DROP(mvm, "dsp size out of range [0,20]: %d\n", - phy_info->cfg_phy_cnt); - kfree_skb(skb); - return; - } - /* * Keep packets with CRC errors (and with overrun) for monitor mode * (otherwise the firmware discards them) but mark them as bad. -- cgit v1.2.3 From 2df5328e7853e33155312970036f05c27c189b71 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 2 Sep 2015 14:47:16 +0200 Subject: iwlwifi: mvm: remove some unused defines from RX API Remove some unused values from the RX API; these were used with older firmware API that didn't have the RX energy API, support for which was removed a long time ago. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/fw-api.h | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index cd293d27677e..54db5159c694 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h @@ -1080,23 +1080,6 @@ struct iwl_hs20_roc_res { #define IWL_RX_INFO_ENERGY_ANT_B_POS 8 #define IWL_RX_INFO_ENERGY_ANT_C_POS 16 -#define IWL_RX_INFO_AGC_IDX 1 -#define IWL_RX_INFO_RSSI_AB_IDX 2 -#define IWL_OFDM_AGC_A_MSK 0x0000007f -#define IWL_OFDM_AGC_A_POS 0 -#define IWL_OFDM_AGC_B_MSK 0x00003f80 -#define IWL_OFDM_AGC_B_POS 7 -#define IWL_OFDM_AGC_CODE_MSK 0x3fe00000 -#define IWL_OFDM_AGC_CODE_POS 20 -#define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff -#define IWL_OFDM_RSSI_A_POS 0 -#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00 -#define IWL_OFDM_RSSI_ALLBAND_A_POS 8 -#define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000 -#define IWL_OFDM_RSSI_B_POS 16 -#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000 -#define IWL_OFDM_RSSI_ALLBAND_B_POS 24 - /** * struct iwl_rx_phy_info - phy info * (REPLY_RX_PHY_CMD = 0xc0) -- cgit v1.2.3 From ee6dbb29377f6055093cccefc0cd0ac2670b12b3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 2 Sep 2015 14:53:39 +0200 Subject: iwlwifi: mvm: move RX API into its own file The RX API is currently mixed up into the general fw-api.h file, but we're going to need to extend it significantly in the future, so move it to its own file. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h | 238 +++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/fw-api.h | 168 +------------------ 2 files changed, 239 insertions(+), 167 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h new file mode 100644 index 000000000000..9b7e49d4620f --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h @@ -0,0 +1,238 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called COPYING. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#ifndef __fw_api_rx_h__ +#define __fw_api_rx_h__ + +#define IWL_RX_INFO_PHY_CNT 8 +#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1 +#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff +#define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00 +#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000 +#define IWL_RX_INFO_ENERGY_ANT_A_POS 0 +#define IWL_RX_INFO_ENERGY_ANT_B_POS 8 +#define IWL_RX_INFO_ENERGY_ANT_C_POS 16 + +/** + * struct iwl_rx_phy_info - phy info + * (REPLY_RX_PHY_CMD = 0xc0) + * @non_cfg_phy_cnt: non configurable DSP phy data byte count + * @cfg_phy_cnt: configurable DSP phy data byte count + * @stat_id: configurable DSP phy data set ID + * @reserved1: + * @system_timestamp: GP2 at on air rise + * @timestamp: TSF at on air rise + * @beacon_time_stamp: beacon at on-air rise + * @phy_flags: general phy flags: band, modulation, ... + * @channel: channel number + * @non_cfg_phy_buf: for various implementations of non_cfg_phy + * @rate_n_flags: RATE_MCS_* + * @byte_count: frame's byte-count + * @frame_time: frame's time on the air, based on byte count and frame rate + * calculation + * @mac_active_msk: what MACs were active when the frame was received + * + * Before each Rx, the device sends this data. It contains PHY information + * about the reception of the packet. + */ +struct iwl_rx_phy_info { + u8 non_cfg_phy_cnt; + u8 cfg_phy_cnt; + u8 stat_id; + u8 reserved1; + __le32 system_timestamp; + __le64 timestamp; + __le32 beacon_time_stamp; + __le16 phy_flags; + __le16 channel; + __le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT]; + __le32 rate_n_flags; + __le32 byte_count; + __le16 mac_active_msk; + __le16 frame_time; +} __packed; + +/* + * TCP offload Rx assist info + * + * bits 0:3 - reserved + * bits 4:7 - MIC CRC length + * bits 8:12 - MAC header length + * bit 13 - Padding indication + * bit 14 - A-AMSDU indication + * bit 15 - Offload enabled + */ +enum iwl_csum_rx_assist_info { + CSUM_RXA_RESERVED_MASK = 0x000f, + CSUM_RXA_MICSIZE_MASK = 0x00f0, + CSUM_RXA_HEADERLEN_MASK = 0x1f00, + CSUM_RXA_PADD = BIT(13), + CSUM_RXA_AMSDU = BIT(14), + CSUM_RXA_ENA = BIT(15) +}; + +/** + * struct iwl_rx_mpdu_res_start - phy info + * @assist: see CSUM_RX_ASSIST_ above + */ +struct iwl_rx_mpdu_res_start { + __le16 byte_count; + __le16 assist; +} __packed; /* _RX_MPDU_RES_START_API_S_VER_2 */ + +/** + * enum iwl_rx_phy_flags - to parse %iwl_rx_phy_info phy_flags + * @RX_RES_PHY_FLAGS_BAND_24: true if the packet was received on 2.4 band + * @RX_RES_PHY_FLAGS_MOD_CCK: + * @RX_RES_PHY_FLAGS_SHORT_PREAMBLE: true if packet's preamble was short + * @RX_RES_PHY_FLAGS_NARROW_BAND: + * @RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received + * @RX_RES_PHY_FLAGS_AGG: set if the packet was part of an A-MPDU + * @RX_RES_PHY_FLAGS_OFDM_HT: The frame was an HT frame + * @RX_RES_PHY_FLAGS_OFDM_GF: The frame used GF preamble + * @RX_RES_PHY_FLAGS_OFDM_VHT: The frame was a VHT frame + */ +enum iwl_rx_phy_flags { + RX_RES_PHY_FLAGS_BAND_24 = BIT(0), + RX_RES_PHY_FLAGS_MOD_CCK = BIT(1), + RX_RES_PHY_FLAGS_SHORT_PREAMBLE = BIT(2), + RX_RES_PHY_FLAGS_NARROW_BAND = BIT(3), + RX_RES_PHY_FLAGS_ANTENNA = (0x7 << 4), + RX_RES_PHY_FLAGS_ANTENNA_POS = 4, + RX_RES_PHY_FLAGS_AGG = BIT(7), + RX_RES_PHY_FLAGS_OFDM_HT = BIT(8), + RX_RES_PHY_FLAGS_OFDM_GF = BIT(9), + RX_RES_PHY_FLAGS_OFDM_VHT = BIT(10), +}; + +/** + * enum iwl_mvm_rx_status - written by fw for each Rx packet + * @RX_MPDU_RES_STATUS_CRC_OK: CRC is fine + * @RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow + * @RX_MPDU_RES_STATUS_SRC_STA_FOUND: + * @RX_MPDU_RES_STATUS_KEY_VALID: + * @RX_MPDU_RES_STATUS_KEY_PARAM_OK: + * @RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed + * @RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked + * in the driver. + * @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine + * @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR: valid for alg = CCM_CMAC or + * alg = CCM only. Checks replay attack for 11w frames. Relevant only if + * %RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set. + * @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted + * @RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP + * @RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM + * @RX_MPDU_RES_STATUS_SEC_TKIP_ENC: this frame is encrypted using TKIP + * @RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC: this frame is encrypted using CCM_CMAC + * @RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted + * @RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm + * @RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted + * @RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP: + * @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP: + * @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT: + * @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame + * @RX_MPDU_RES_STATUS_CSUM_DONE: checksum was done by the hw + * @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors + * @RX_MPDU_RES_STATUS_HASH_INDEX_MSK: + * @RX_MPDU_RES_STATUS_STA_ID_MSK: + * @RX_MPDU_RES_STATUS_RRF_KILL: + * @RX_MPDU_RES_STATUS_FILTERING_MSK: + * @RX_MPDU_RES_STATUS2_FILTERING_MSK: + */ +enum iwl_mvm_rx_status { + RX_MPDU_RES_STATUS_CRC_OK = BIT(0), + RX_MPDU_RES_STATUS_OVERRUN_OK = BIT(1), + RX_MPDU_RES_STATUS_SRC_STA_FOUND = BIT(2), + RX_MPDU_RES_STATUS_KEY_VALID = BIT(3), + RX_MPDU_RES_STATUS_KEY_PARAM_OK = BIT(4), + RX_MPDU_RES_STATUS_ICV_OK = BIT(5), + RX_MPDU_RES_STATUS_MIC_OK = BIT(6), + RX_MPDU_RES_STATUS_TTAK_OK = BIT(7), + RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR = BIT(7), + RX_MPDU_RES_STATUS_SEC_NO_ENC = (0 << 8), + RX_MPDU_RES_STATUS_SEC_WEP_ENC = (1 << 8), + RX_MPDU_RES_STATUS_SEC_CCM_ENC = (2 << 8), + RX_MPDU_RES_STATUS_SEC_TKIP_ENC = (3 << 8), + RX_MPDU_RES_STATUS_SEC_EXT_ENC = (4 << 8), + RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC = (6 << 8), + RX_MPDU_RES_STATUS_SEC_ENC_ERR = (7 << 8), + RX_MPDU_RES_STATUS_SEC_ENC_MSK = (7 << 8), + RX_MPDU_RES_STATUS_DEC_DONE = BIT(11), + RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP = BIT(12), + RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP = BIT(13), + RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT = BIT(14), + RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME = BIT(15), + RX_MPDU_RES_STATUS_CSUM_DONE = BIT(16), + RX_MPDU_RES_STATUS_CSUM_OK = BIT(17), + RX_MPDU_RES_STATUS_HASH_INDEX_MSK = (0x3F0000), + RX_MPDU_RES_STATUS_STA_ID_MSK = (0x1f000000), + RX_MPDU_RES_STATUS_RRF_KILL = BIT(29), + RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000), + RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000), +}; + +#endif /* __fw_api_rx_h__ */ diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 54db5159c694..5e4014a87222 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h @@ -67,6 +67,7 @@ #define __fw_api_h__ #include "fw-api-rs.h" +#include "fw-api-rx.h" #include "fw-api-tx.h" #include "fw-api-sta.h" #include "fw-api-mac.h" @@ -1071,173 +1072,6 @@ struct iwl_hs20_roc_res { __le32 status; } __packed; /* HOT_SPOT_RSP_API_S_VER_1 */ -#define IWL_RX_INFO_PHY_CNT 8 -#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1 -#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff -#define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00 -#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000 -#define IWL_RX_INFO_ENERGY_ANT_A_POS 0 -#define IWL_RX_INFO_ENERGY_ANT_B_POS 8 -#define IWL_RX_INFO_ENERGY_ANT_C_POS 16 - -/** - * struct iwl_rx_phy_info - phy info - * (REPLY_RX_PHY_CMD = 0xc0) - * @non_cfg_phy_cnt: non configurable DSP phy data byte count - * @cfg_phy_cnt: configurable DSP phy data byte count - * @stat_id: configurable DSP phy data set ID - * @reserved1: - * @system_timestamp: GP2 at on air rise - * @timestamp: TSF at on air rise - * @beacon_time_stamp: beacon at on-air rise - * @phy_flags: general phy flags: band, modulation, ... - * @channel: channel number - * @non_cfg_phy_buf: for various implementations of non_cfg_phy - * @rate_n_flags: RATE_MCS_* - * @byte_count: frame's byte-count - * @frame_time: frame's time on the air, based on byte count and frame rate - * calculation - * @mac_active_msk: what MACs were active when the frame was received - * - * Before each Rx, the device sends this data. It contains PHY information - * about the reception of the packet. - */ -struct iwl_rx_phy_info { - u8 non_cfg_phy_cnt; - u8 cfg_phy_cnt; - u8 stat_id; - u8 reserved1; - __le32 system_timestamp; - __le64 timestamp; - __le32 beacon_time_stamp; - __le16 phy_flags; - __le16 channel; - __le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT]; - __le32 rate_n_flags; - __le32 byte_count; - __le16 mac_active_msk; - __le16 frame_time; -} __packed; - -/* - * TCP offload Rx assist info - * - * bits 0:3 - reserved - * bits 4:7 - MIC CRC length - * bits 8:12 - MAC header length - * bit 13 - Padding indication - * bit 14 - A-AMSDU indication - * bit 15 - Offload enabled - */ -enum iwl_csum_rx_assist_info { - CSUM_RXA_RESERVED_MASK = 0x000f, - CSUM_RXA_MICSIZE_MASK = 0x00f0, - CSUM_RXA_HEADERLEN_MASK = 0x1f00, - CSUM_RXA_PADD = BIT(13), - CSUM_RXA_AMSDU = BIT(14), - CSUM_RXA_ENA = BIT(15) -}; - -/** - * struct iwl_rx_mpdu_res_start - phy info - * @assist: see CSUM_RX_ASSIST_ above - */ -struct iwl_rx_mpdu_res_start { - __le16 byte_count; - __le16 assist; -} __packed; /* _RX_MPDU_RES_START_API_S_VER_2 */ - -/** - * enum iwl_rx_phy_flags - to parse %iwl_rx_phy_info phy_flags - * @RX_RES_PHY_FLAGS_BAND_24: true if the packet was received on 2.4 band - * @RX_RES_PHY_FLAGS_MOD_CCK: - * @RX_RES_PHY_FLAGS_SHORT_PREAMBLE: true if packet's preamble was short - * @RX_RES_PHY_FLAGS_NARROW_BAND: - * @RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received - * @RX_RES_PHY_FLAGS_AGG: set if the packet was part of an A-MPDU - * @RX_RES_PHY_FLAGS_OFDM_HT: The frame was an HT frame - * @RX_RES_PHY_FLAGS_OFDM_GF: The frame used GF preamble - * @RX_RES_PHY_FLAGS_OFDM_VHT: The frame was a VHT frame - */ -enum iwl_rx_phy_flags { - RX_RES_PHY_FLAGS_BAND_24 = BIT(0), - RX_RES_PHY_FLAGS_MOD_CCK = BIT(1), - RX_RES_PHY_FLAGS_SHORT_PREAMBLE = BIT(2), - RX_RES_PHY_FLAGS_NARROW_BAND = BIT(3), - RX_RES_PHY_FLAGS_ANTENNA = (0x7 << 4), - RX_RES_PHY_FLAGS_ANTENNA_POS = 4, - RX_RES_PHY_FLAGS_AGG = BIT(7), - RX_RES_PHY_FLAGS_OFDM_HT = BIT(8), - RX_RES_PHY_FLAGS_OFDM_GF = BIT(9), - RX_RES_PHY_FLAGS_OFDM_VHT = BIT(10), -}; - -/** - * enum iwl_mvm_rx_status - written by fw for each Rx packet - * @RX_MPDU_RES_STATUS_CRC_OK: CRC is fine - * @RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow - * @RX_MPDU_RES_STATUS_SRC_STA_FOUND: - * @RX_MPDU_RES_STATUS_KEY_VALID: - * @RX_MPDU_RES_STATUS_KEY_PARAM_OK: - * @RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed - * @RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked - * in the driver. - * @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine - * @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR: valid for alg = CCM_CMAC or - * alg = CCM only. Checks replay attack for 11w frames. Relevant only if - * %RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set. - * @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted - * @RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP - * @RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM - * @RX_MPDU_RES_STATUS_SEC_TKIP_ENC: this frame is encrypted using TKIP - * @RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC: this frame is encrypted using CCM_CMAC - * @RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted - * @RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm - * @RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted - * @RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP: - * @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP: - * @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT: - * @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame - * @RX_MPDU_RES_STATUS_CSUM_DONE: checksum was done by the hw - * @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors - * @RX_MPDU_RES_STATUS_HASH_INDEX_MSK: - * @RX_MPDU_RES_STATUS_STA_ID_MSK: - * @RX_MPDU_RES_STATUS_RRF_KILL: - * @RX_MPDU_RES_STATUS_FILTERING_MSK: - * @RX_MPDU_RES_STATUS2_FILTERING_MSK: - */ -enum iwl_mvm_rx_status { - RX_MPDU_RES_STATUS_CRC_OK = BIT(0), - RX_MPDU_RES_STATUS_OVERRUN_OK = BIT(1), - RX_MPDU_RES_STATUS_SRC_STA_FOUND = BIT(2), - RX_MPDU_RES_STATUS_KEY_VALID = BIT(3), - RX_MPDU_RES_STATUS_KEY_PARAM_OK = BIT(4), - RX_MPDU_RES_STATUS_ICV_OK = BIT(5), - RX_MPDU_RES_STATUS_MIC_OK = BIT(6), - RX_MPDU_RES_STATUS_TTAK_OK = BIT(7), - RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR = BIT(7), - RX_MPDU_RES_STATUS_SEC_NO_ENC = (0 << 8), - RX_MPDU_RES_STATUS_SEC_WEP_ENC = (1 << 8), - RX_MPDU_RES_STATUS_SEC_CCM_ENC = (2 << 8), - RX_MPDU_RES_STATUS_SEC_TKIP_ENC = (3 << 8), - RX_MPDU_RES_STATUS_SEC_EXT_ENC = (4 << 8), - RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC = (6 << 8), - RX_MPDU_RES_STATUS_SEC_ENC_ERR = (7 << 8), - RX_MPDU_RES_STATUS_SEC_ENC_MSK = (7 << 8), - RX_MPDU_RES_STATUS_DEC_DONE = BIT(11), - RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP = BIT(12), - RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP = BIT(13), - RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT = BIT(14), - RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME = BIT(15), - RX_MPDU_RES_STATUS_CSUM_DONE = BIT(16), - RX_MPDU_RES_STATUS_CSUM_OK = BIT(17), - RX_MPDU_RES_STATUS_HASH_INDEX_MSK = (0x3F0000), - RX_MPDU_RES_STATUS_STA_ID_MSK = (0x1f000000), - RX_MPDU_RES_STATUS_RRF_KILL = BIT(29), - RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000), - RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000), -}; - /** * struct iwl_radio_version_notif - information on the radio version * ( RADIO_VERSION_NOTIFICATION = 0x68 ) -- cgit v1.2.3 From 183edd8484fd375d0f6d5e73b071c21b17243424 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 1 Sep 2015 14:16:00 +0300 Subject: iwlwifi: mvm: configure wowlan configuration only if connected Recent fw version added assert to make sure wowlan configuration is configured only when a station is connected. Change the driver behavior to pass this configuration only if we indeed have ap station id (i.e. connected). Signed-off-by: Eliad Peller Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/ops.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 009228615d26..62eefab21f07 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -1146,12 +1146,17 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) /* make sure we have no running tx while configuring the seqno */ synchronize_net(); - iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd, &d0i3_iter_data); - ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags, - sizeof(wowlan_config_cmd), - &wowlan_config_cmd); - if (ret) - return ret; + /* configure wowlan configuration only if needed */ + if (mvm->d0i3_ap_sta_id != IWL_MVM_STATION_COUNT) { + iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd, + &d0i3_iter_data); + + ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags, + sizeof(wowlan_config_cmd), + &wowlan_config_cmd); + if (ret) + return ret; + } return iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, flags | CMD_MAKE_TRANS_IDLE, -- cgit v1.2.3 From 7c014e35a018187462f2cd6c85259e080663ba2d Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 6 Sep 2015 14:17:17 +0300 Subject: iwlwifi: mvm: add debug print for d0i3 exit indication In order to verify d0i3 flow, add debug print to indicate d0i3 exit was completed (right after tx was re-enabled), along with the wakeup reasons. Signed-off-by: Eliad Peller Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/ops.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 62eefab21f07..3f6428c260de 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -1263,7 +1263,7 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) }; struct iwl_wowlan_status *status; int ret; - u32 handled_reasons, wakeup_reasons; + u32 handled_reasons, wakeup_reasons = 0; __le16 *qos_seq = NULL; mutex_lock(&mvm->mutex); @@ -1295,6 +1295,9 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) out: iwl_mvm_d0i3_enable_tx(mvm, qos_seq); + IWL_DEBUG_INFO(mvm, "d0i3 exit completed (wakeup reasons: 0x%x)\n", + wakeup_reasons); + /* qos_seq might point inside resp_pkt, so free it only now */ if (get_status_cmd.resp_pkt) iwl_free_resp(&get_status_cmd); -- cgit v1.2.3 From 852bcafb99247abb3a2876625a3adf684c42e015 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 18 Sep 2015 14:16:53 -0700 Subject: net: bcmgenet: Remove duplicate test for tx_coalesce_usecs_high We were checking twice for ec->tx_coalesce_usecs_high, remove the duplicate test. Reported-by: Julia Lawall Reported-by: kbuild-all@01.org Fixes: 2f9130709d2c19 ("net: bcmgenet: Implement TX coalescing control knobs") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 1e72722abbf1..efcb1119076f 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -608,8 +608,7 @@ static int bcmgenet_set_coalesce(struct net_device *dev, * transmitted, or when the ring is emtpy. */ if (ec->tx_coalesce_usecs || ec->tx_coalesce_usecs_high || - ec->tx_coalesce_usecs_irq || ec->tx_coalesce_usecs_high || - ec->tx_coalesce_usecs_low) + ec->tx_coalesce_usecs_irq || ec->tx_coalesce_usecs_low) return -EOPNOTSUPP; /* Program all TX queues with the same values, as there is no -- cgit v1.2.3 From b6745f6e4e63f23fd5bf46ea2745783be13a0960 Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Mon, 21 Sep 2015 15:56:50 +0530 Subject: drivers: net: cpsw: davinci_emac: move reading mac id to common file Moving mac address reading from ethernet driver to common file for better maintenance and for code reusable. Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw-common.c | 58 ++++++++++++++++++++++++++++------ drivers/net/ethernet/ti/cpsw.c | 11 +++---- drivers/net/ethernet/ti/cpsw.h | 3 +- drivers/net/ethernet/ti/davinci_emac.c | 44 ++------------------------ 4 files changed, 57 insertions(+), 59 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/cpsw-common.c b/drivers/net/ethernet/ti/cpsw-common.c index f59509486113..c70417ce0a8b 100644 --- a/drivers/net/ethernet/ti/cpsw-common.c +++ b/drivers/net/ethernet/ti/cpsw-common.c @@ -19,11 +19,38 @@ #include "cpsw.h" -#define AM33XX_CTRL_MAC_LO_REG(offset, id) ((offset) + 0x8 * (id)) -#define AM33XX_CTRL_MAC_HI_REG(offset, id) ((offset) + 0x8 * (id) + 0x4) +#define CTRL_MAC_LO_REG(offset, id) ((offset) + 0x8 * (id)) +#define CTRL_MAC_HI_REG(offset, id) ((offset) + 0x8 * (id) + 0x4) -int cpsw_am33xx_cm_get_macid(struct device *dev, u16 offset, int slave, - u8 *mac_addr) +static int davinci_emac_3517_get_macid(struct device *dev, u16 offset, + int slave, u8 *mac_addr) +{ + u32 macid_lsb; + u32 macid_msb; + struct regmap *syscon; + + syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); + if (IS_ERR(syscon)) { + if (PTR_ERR(syscon) == -ENODEV) + return 0; + return PTR_ERR(syscon); + } + + regmap_read(syscon, CTRL_MAC_LO_REG(offset, slave), &macid_lsb); + regmap_read(syscon, CTRL_MAC_HI_REG(offset, slave), &macid_msb); + + mac_addr[0] = (macid_msb >> 16) & 0xff; + mac_addr[1] = (macid_msb >> 8) & 0xff; + mac_addr[2] = macid_msb & 0xff; + mac_addr[3] = (macid_lsb >> 16) & 0xff; + mac_addr[4] = (macid_lsb >> 8) & 0xff; + mac_addr[5] = macid_lsb & 0xff; + + return 0; +} + +static int cpsw_am33xx_cm_get_macid(struct device *dev, u16 offset, int slave, + u8 *mac_addr) { u32 macid_lo; u32 macid_hi; @@ -36,10 +63,8 @@ int cpsw_am33xx_cm_get_macid(struct device *dev, u16 offset, int slave, return PTR_ERR(syscon); } - regmap_read(syscon, AM33XX_CTRL_MAC_LO_REG(offset, slave), - &macid_lo); - regmap_read(syscon, AM33XX_CTRL_MAC_HI_REG(offset, slave), - &macid_hi); + regmap_read(syscon, CTRL_MAC_LO_REG(offset, slave), &macid_lo); + regmap_read(syscon, CTRL_MAC_HI_REG(offset, slave), &macid_hi); mac_addr[5] = (macid_lo >> 8) & 0xff; mac_addr[4] = macid_lo & 0xff; @@ -50,6 +75,21 @@ int cpsw_am33xx_cm_get_macid(struct device *dev, u16 offset, int slave, return 0; } -EXPORT_SYMBOL_GPL(cpsw_am33xx_cm_get_macid); + +int ti_cm_get_macid(struct device *dev, int slave, u8 *mac_addr) +{ + if (of_machine_is_compatible("ti,am33xx")) + return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr); + + if (of_device_is_compatible(dev->of_node, "ti,am3517-emac")) + return davinci_emac_3517_get_macid(dev, 0x110, slave, mac_addr); + + if (of_device_is_compatible(dev->of_node, "ti,dm816-emac")) + return cpsw_am33xx_cm_get_macid(dev, 0x30, slave, mac_addr); + + dev_err(dev, "incompatible machine/device type for reading mac address\n"); + return -ENOENT; +} +EXPORT_SYMBOL_GPL(ti_cm_get_macid); MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index c670317f3cb0..75584cc36339 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -2058,13 +2058,10 @@ no_phy_slave: if (mac_addr) { memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN); } else { - if (of_machine_is_compatible("ti,am33xx")) { - ret = cpsw_am33xx_cm_get_macid(&pdev->dev, - 0x630, i, - slave_data->mac_addr); - if (ret) - return ret; - } + ret = ti_cm_get_macid(&pdev->dev, i, + slave_data->mac_addr); + if (ret) + return ret; } if (data->dual_emac) { if (of_property_read_u32(slave_node, "dual_emac_res_vlan", diff --git a/drivers/net/ethernet/ti/cpsw.h b/drivers/net/ethernet/ti/cpsw.h index ca90efafd156..442a7038e660 100644 --- a/drivers/net/ethernet/ti/cpsw.h +++ b/drivers/net/ethernet/ti/cpsw.h @@ -41,7 +41,6 @@ struct cpsw_platform_data { }; void cpsw_phy_sel(struct device *dev, phy_interface_t phy_mode, int slave); -int cpsw_am33xx_cm_get_macid(struct device *dev, u16 offset, int slave, - u8 *mac_addr); +int ti_cm_get_macid(struct device *dev, int slave, u8 *mac_addr); #endif /* __CPSW_H__ */ diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index a21c77bc1b27..39a54b27db66 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1882,51 +1882,13 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv) return pdata; } -static int davinci_emac_3517_get_macid(struct device *dev, u16 offset, - int slave, u8 *mac_addr) -{ - u32 macid_lsb; - u32 macid_msb; - struct regmap *syscon; - - syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); - if (IS_ERR(syscon)) { - if (PTR_ERR(syscon) == -ENODEV) - return 0; - return PTR_ERR(syscon); - } - - regmap_read(syscon, offset, &macid_lsb); - regmap_read(syscon, offset + 4, &macid_msb); - - mac_addr[0] = (macid_msb >> 16) & 0xff; - mac_addr[1] = (macid_msb >> 8) & 0xff; - mac_addr[2] = macid_msb & 0xff; - mac_addr[3] = (macid_lsb >> 16) & 0xff; - mac_addr[4] = (macid_lsb >> 8) & 0xff; - mac_addr[5] = macid_lsb & 0xff; - - return 0; -} - static int davinci_emac_try_get_mac(struct platform_device *pdev, int instance, u8 *mac_addr) { - int error = -EINVAL; - if (!pdev->dev.of_node) - return error; - - if (of_device_is_compatible(pdev->dev.of_node, "ti,am3517-emac")) - error = davinci_emac_3517_get_macid(&pdev->dev, 0x110, - 0, mac_addr); - else if (of_device_is_compatible(pdev->dev.of_node, - "ti,dm816-emac")) - error = cpsw_am33xx_cm_get_macid(&pdev->dev, 0x30, - instance, - mac_addr); - - return error; + return -EINVAL; + + return ti_cm_get_macid(&pdev->dev, instance, mac_addr); } /** -- cgit v1.2.3 From d230a11abc97e118365b12a472ff758d867c4bac Mon Sep 17 00:00:00 2001 From: Mugunthan V N Date: Mon, 21 Sep 2015 15:56:51 +0530 Subject: drivers: net: cpsw-common: add support for reading mac address for dra7 and am437x platforms Adding support for reading mac address using syscon driver for dra7 and am437x platforms Signed-off-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw-common.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/cpsw-common.c b/drivers/net/ethernet/ti/cpsw-common.c index c70417ce0a8b..c08be62bceba 100644 --- a/drivers/net/ethernet/ti/cpsw-common.c +++ b/drivers/net/ethernet/ti/cpsw-common.c @@ -87,6 +87,12 @@ int ti_cm_get_macid(struct device *dev, int slave, u8 *mac_addr) if (of_device_is_compatible(dev->of_node, "ti,dm816-emac")) return cpsw_am33xx_cm_get_macid(dev, 0x30, slave, mac_addr); + if (of_machine_is_compatible("ti,am4372")) + return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr); + + if (of_machine_is_compatible("ti,dra7")) + return davinci_emac_3517_get_macid(dev, 0x514, slave, mac_addr); + dev_err(dev, "incompatible machine/device type for reading mac address\n"); return -ENOENT; } -- cgit v1.2.3 From 97170ea1823bf00cf6ed0f503129e9053a66c53a Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 21 Sep 2015 20:41:44 -0700 Subject: drivers/net/ieee802154/at86rf230.c: seq_printf() now returns NULL Signed-off-by: Stephen Rothwell Cc: Alexander Aring Cc: Stefan Schmidt Cc: Marcel Holtmann Signed-off-by: Andrew Morton Signed-off-by: Alexander Aring Signed-off-by: David S. Miller --- drivers/net/ieee802154/at86rf230.c | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index b8b0628dc2f3..9756e6451038 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1645,32 +1645,17 @@ static struct dentry *at86rf230_debugfs_root; static int at86rf230_stats_show(struct seq_file *file, void *offset) { struct at86rf230_local *lp = file->private; - int ret; - - ret = seq_printf(file, "SUCCESS:\t\t%8llu\n", lp->trac.success); - if (ret < 0) - return ret; - - ret = seq_printf(file, "SUCCESS_DATA_PENDING:\t%8llu\n", - lp->trac.success_data_pending); - if (ret < 0) - return ret; - - ret = seq_printf(file, "SUCCESS_WAIT_FOR_ACK:\t%8llu\n", - lp->trac.success_wait_for_ack); - if (ret < 0) - return ret; - - ret = seq_printf(file, "CHANNEL_ACCESS_FAILURE:\t%8llu\n", - lp->trac.channel_access_failure); - if (ret < 0) - return ret; - ret = seq_printf(file, "NO_ACK:\t\t\t%8llu\n", lp->trac.no_ack); - if (ret < 0) - return ret; - - return seq_printf(file, "INVALID:\t\t%8llu\n", lp->trac.invalid); + seq_printf(file, "SUCCESS:\t\t%8llu\n", lp->trac.success); + seq_printf(file, "SUCCESS_DATA_PENDING:\t%8llu\n", + lp->trac.success_data_pending); + seq_printf(file, "SUCCESS_WAIT_FOR_ACK:\t%8llu\n", + lp->trac.success_wait_for_ack); + seq_printf(file, "CHANNEL_ACCESS_FAILURE:\t%8llu\n", + lp->trac.channel_access_failure); + seq_printf(file, "NO_ACK:\t\t\t%8llu\n", lp->trac.no_ack); + seq_printf(file, "INVALID:\t\t%8llu\n", lp->trac.invalid); + return 0; } static int at86rf230_stats_open(struct inode *inode, struct file *file) -- cgit v1.2.3 From 57c1bc7ea8a4857070722c23ce98e01f256c9306 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 09:37:54 +0200 Subject: at86rf230: support edge triggered irq This patch adds support for edge triggered irq types. We remove the locking for irq resources by enable/disable irq and allocate directly some heap buffer at isr. We have still a enable/disable irq path but this is for level-triggered irq's which need to be disabled until spi_async clear the irq line. There is usually a little race condition between "irq line cleared" and "enable_irq". When in this time a edge triggered irq arrived, we will not recognize this interrupt. This case can't happend at at86rf230. The reason is that we unmask TRX_END irq's only which indicates a transmit or receive completion, which depends on the current state. On Transmit: TRX_END arrived and transceiver is in TX_ARET_ON state again, in this state no other TRX_END can happen until we leave the state. On Receive: This is protected with the RX_SAFE_MODE bit which leaves the transceiver in RX_AACK_BUSY until we readed the framebuffer. In this state no other TRX_END can happen. Tested with RPi where I first detected issues between edge/level irq's. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/at86rf230.c | 211 ++++++++++++++++--------------------- 1 file changed, 89 insertions(+), 122 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 9756e6451038..de6e4fa2d6aa 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -81,7 +81,7 @@ struct at86rf230_state_change { u8 from_state; u8 to_state; - bool irq_enable; + bool free; }; struct at86rf230_trac { @@ -105,8 +105,6 @@ struct at86rf230_local { struct completion state_complete; struct at86rf230_state_change state; - struct at86rf230_state_change irq; - unsigned long cal_timeout; bool is_tx; bool is_tx_from_off; @@ -122,8 +120,7 @@ struct at86rf230_local { static void at86rf230_async_state_change(struct at86rf230_local *lp, struct at86rf230_state_change *ctx, - const u8 state, void (*complete)(void *context), - const bool irq_enable); + const u8 state, void (*complete)(void *context)); static inline void at86rf230_sleep(struct at86rf230_local *lp) @@ -352,8 +349,10 @@ at86rf230_async_error_recover(void *context) struct at86rf230_local *lp = ctx->lp; lp->is_tx = 0; - at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL, false); + at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL); ieee802154_wake_queue(lp->hw); + if (ctx->free) + kfree(ctx); } static inline void @@ -363,15 +362,14 @@ at86rf230_async_error(struct at86rf230_local *lp, dev_err(&lp->spi->dev, "spi_async error %d\n", rc); at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF, - at86rf230_async_error_recover, false); + at86rf230_async_error_recover); } /* Generic function to get some register value in async mode */ static void -at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg, +at86rf230_async_read_reg(struct at86rf230_local *lp, u8 reg, struct at86rf230_state_change *ctx, - void (*complete)(void *context), - const bool irq_enable) + void (*complete)(void *context)) { int rc; @@ -379,14 +377,24 @@ at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg, tx_buf[0] = (reg & CMD_REG_MASK) | CMD_REG; ctx->msg.complete = complete; - ctx->irq_enable = irq_enable; rc = spi_async(lp->spi, &ctx->msg); - if (rc) { - if (irq_enable) - enable_irq(ctx->irq); + if (rc) + at86rf230_async_error(lp, ctx, rc); +} +static void +at86rf230_async_write_reg(struct at86rf230_local *lp, u8 reg, u8 val, + struct at86rf230_state_change *ctx, + void (*complete)(void *context)) +{ + int rc; + + ctx->buf[0] = (reg & CMD_REG_MASK) | CMD_REG | CMD_WRITE; + ctx->buf[1] = val; + ctx->msg.complete = complete; + rc = spi_async(lp->spi, &ctx->msg); + if (rc) at86rf230_async_error(lp, ctx, rc); - } } static void @@ -434,8 +442,7 @@ at86rf230_async_state_assert(void *context) lp->tx_retry++; at86rf230_async_state_change(lp, ctx, state, - ctx->complete, - ctx->irq_enable); + ctx->complete); return; } } @@ -456,8 +463,7 @@ static enum hrtimer_restart at86rf230_async_state_timer(struct hrtimer *timer) struct at86rf230_local *lp = ctx->lp; at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, - at86rf230_async_state_assert, - ctx->irq_enable); + at86rf230_async_state_assert); return HRTIMER_NORESTART; } @@ -562,14 +568,12 @@ at86rf230_async_state_change_start(void *context) struct at86rf230_local *lp = ctx->lp; u8 *buf = ctx->buf; const u8 trx_state = buf[1] & TRX_STATE_MASK; - int rc; /* Check for "possible" STATE_TRANSITION_IN_PROGRESS */ if (trx_state == STATE_TRANSITION_IN_PROGRESS) { udelay(1); at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, - at86rf230_async_state_change_start, - ctx->irq_enable); + at86rf230_async_state_change_start); return; } @@ -586,31 +590,20 @@ at86rf230_async_state_change_start(void *context) /* Going into the next step for a state change which do a timing * relevant delay. */ - buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE; - buf[1] = ctx->to_state; - ctx->msg.complete = at86rf230_async_state_delay; - rc = spi_async(lp->spi, &ctx->msg); - if (rc) { - if (ctx->irq_enable) - enable_irq(ctx->irq); - - at86rf230_async_error(lp, ctx, rc); - } + at86rf230_async_write_reg(lp, RG_TRX_STATE, ctx->to_state, ctx, + at86rf230_async_state_delay); } static void at86rf230_async_state_change(struct at86rf230_local *lp, struct at86rf230_state_change *ctx, - const u8 state, void (*complete)(void *context), - const bool irq_enable) + const u8 state, void (*complete)(void *context)) { /* Initialization for the state change context */ ctx->to_state = state; ctx->complete = complete; - ctx->irq_enable = irq_enable; at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx, - at86rf230_async_state_change_start, - irq_enable); + at86rf230_async_state_change_start); } static void @@ -632,8 +625,7 @@ at86rf230_sync_state_change(struct at86rf230_local *lp, unsigned int state) unsigned long rc; at86rf230_async_state_change(lp, &lp->state, state, - at86rf230_sync_state_change_complete, - false); + at86rf230_sync_state_change_complete); rc = wait_for_completion_timeout(&lp->state_complete, msecs_to_jiffies(100)); @@ -651,9 +643,8 @@ at86rf230_tx_complete(void *context) struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; - enable_irq(ctx->irq); - ieee802154_xmit_complete(lp->hw, lp->tx_skb, false); + kfree(ctx); } static void @@ -663,7 +654,7 @@ at86rf230_tx_on(void *context) struct at86rf230_local *lp = ctx->lp; at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, - at86rf230_tx_complete, true); + at86rf230_tx_complete); } static void @@ -697,8 +688,7 @@ at86rf230_tx_trac_check(void *context) } } - at86rf230_async_state_change(lp, &lp->irq, STATE_TX_ON, - at86rf230_tx_on, true); + at86rf230_async_state_change(lp, ctx, STATE_TX_ON, at86rf230_tx_on); } static void @@ -706,7 +696,6 @@ at86rf230_rx_read_frame_complete(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; - u8 rx_local_buf[AT86RF2XX_MAX_BUF]; const u8 *buf = ctx->buf; struct sk_buff *skb; u8 len, lqi; @@ -718,18 +707,16 @@ at86rf230_rx_read_frame_complete(void *context) } lqi = buf[2 + len]; - memcpy(rx_local_buf, buf + 2, len); - ctx->trx.len = 2; - enable_irq(ctx->irq); - skb = dev_alloc_skb(IEEE802154_MTU); if (!skb) { dev_vdbg(&lp->spi->dev, "failed to allocate sk_buff\n"); + kfree(ctx); return; } - memcpy(skb_put(skb, len), rx_local_buf, len); + memcpy(skb_put(skb, len), buf + 2, len); ieee802154_rx_irqsafe(lp->hw, skb, lqi); + kfree(ctx); } static void @@ -765,21 +752,23 @@ at86rf230_rx_trac_check(void *context) rc = spi_async(lp->spi, &ctx->msg); if (rc) { ctx->trx.len = 2; - enable_irq(ctx->irq); at86rf230_async_error(lp, ctx, rc); } } static void -at86rf230_irq_trx_end(struct at86rf230_local *lp) +at86rf230_irq_trx_end(void *context) { + struct at86rf230_state_change *ctx = context; + struct at86rf230_local *lp = ctx->lp; + if (lp->is_tx) { lp->is_tx = 0; - at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq, - at86rf230_tx_trac_check, true); + at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx, + at86rf230_tx_trac_check); } else { - at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq, - at86rf230_rx_trac_check, true); + at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx, + at86rf230_rx_trac_check); } } @@ -789,32 +778,59 @@ at86rf230_irq_status(void *context) struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; const u8 *buf = ctx->buf; - const u8 irq = buf[1]; + u8 irq = buf[1]; + + enable_irq(lp->spi->irq); if (irq & IRQ_TRX_END) { - at86rf230_irq_trx_end(lp); + at86rf230_irq_trx_end(ctx); } else { - enable_irq(ctx->irq); dev_err(&lp->spi->dev, "not supported irq %02x received\n", irq); + kfree(ctx); } } +static void +at86rf230_setup_spi_messages(struct at86rf230_local *lp, + struct at86rf230_state_change *state) +{ + state->lp = lp; + state->irq = lp->spi->irq; + spi_message_init(&state->msg); + state->msg.context = state; + state->trx.len = 2; + state->trx.tx_buf = state->buf; + state->trx.rx_buf = state->buf; + spi_message_add_tail(&state->trx, &state->msg); + hrtimer_init(&state->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + state->timer.function = at86rf230_async_state_timer; +} + static irqreturn_t at86rf230_isr(int irq, void *data) { struct at86rf230_local *lp = data; - struct at86rf230_state_change *ctx = &lp->irq; - u8 *buf = ctx->buf; + struct at86rf230_state_change *ctx; int rc; disable_irq_nosync(irq); - buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG; + ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC); + if (!ctx) { + enable_irq(irq); + return IRQ_NONE; + } + + at86rf230_setup_spi_messages(lp, ctx); + /* tell on error handling to free ctx */ + ctx->free = true; + + ctx->buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG; ctx->msg.complete = at86rf230_irq_status; rc = spi_async(lp->spi, &ctx->msg); if (rc) { - enable_irq(irq); at86rf230_async_error(lp, ctx, rc); + enable_irq(irq); return IRQ_NONE; } @@ -826,21 +842,14 @@ at86rf230_write_frame_complete(void *context) { struct at86rf230_state_change *ctx = context; struct at86rf230_local *lp = ctx->lp; - u8 *buf = ctx->buf; - int rc; ctx->trx.len = 2; - if (gpio_is_valid(lp->slp_tr)) { + if (gpio_is_valid(lp->slp_tr)) at86rf230_slp_tr_rising_edge(lp); - } else { - buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE; - buf[1] = STATE_BUSY_TX; - ctx->msg.complete = NULL; - rc = spi_async(lp->spi, &ctx->msg); - if (rc) - at86rf230_async_error(lp, ctx, rc); - } + else + at86rf230_async_write_reg(lp, RG_TRX_STATE, STATE_BUSY_TX, ctx, + NULL); } static void @@ -873,7 +882,7 @@ at86rf230_xmit_tx_on(void *context) struct at86rf230_local *lp = ctx->lp; at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON, - at86rf230_write_frame, false); + at86rf230_write_frame); } static void @@ -886,12 +895,10 @@ at86rf230_xmit_start(void *context) if (lp->is_tx_from_off) { lp->is_tx_from_off = false; at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON, - at86rf230_write_frame, - false); + at86rf230_write_frame); } else { at86rf230_async_state_change(lp, ctx, STATE_TX_ON, - at86rf230_xmit_tx_on, - false); + at86rf230_xmit_tx_on); } } @@ -914,7 +921,7 @@ at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb) if (time_is_before_jiffies(lp->cal_timeout)) { lp->is_tx_from_off = true; at86rf230_async_state_change(lp, ctx, STATE_TRX_OFF, - at86rf230_xmit_start, false); + at86rf230_xmit_start); } else { at86rf230_xmit_start(ctx); } @@ -1373,10 +1380,6 @@ static int at86rf230_hw_init(struct at86rf230_local *lp, u8 xtal_trim) return rc; irq_type = irq_get_trigger_type(lp->spi->irq); - if (irq_type == IRQ_TYPE_EDGE_RISING || - irq_type == IRQ_TYPE_EDGE_FALLING) - dev_warn(&lp->spi->dev, - "Using edge triggered irq's are not recommended, because it can cause races and result in a non-functional driver!\n"); if (irq_type == IRQ_TYPE_EDGE_FALLING || irq_type == IRQ_TYPE_LEVEL_LOW) irq_pol = IRQ_ACTIVE_LOW; @@ -1602,43 +1605,6 @@ not_supp: return rc; } -static void -at86rf230_setup_spi_messages(struct at86rf230_local *lp) -{ - lp->state.lp = lp; - lp->state.irq = lp->spi->irq; - spi_message_init(&lp->state.msg); - lp->state.msg.context = &lp->state; - lp->state.trx.len = 2; - lp->state.trx.tx_buf = lp->state.buf; - lp->state.trx.rx_buf = lp->state.buf; - spi_message_add_tail(&lp->state.trx, &lp->state.msg); - hrtimer_init(&lp->state.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - lp->state.timer.function = at86rf230_async_state_timer; - - lp->irq.lp = lp; - lp->irq.irq = lp->spi->irq; - spi_message_init(&lp->irq.msg); - lp->irq.msg.context = &lp->irq; - lp->irq.trx.len = 2; - lp->irq.trx.tx_buf = lp->irq.buf; - lp->irq.trx.rx_buf = lp->irq.buf; - spi_message_add_tail(&lp->irq.trx, &lp->irq.msg); - hrtimer_init(&lp->irq.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - lp->irq.timer.function = at86rf230_async_state_timer; - - lp->tx.lp = lp; - lp->tx.irq = lp->spi->irq; - spi_message_init(&lp->tx.msg); - lp->tx.msg.context = &lp->tx; - lp->tx.trx.len = 2; - lp->tx.trx.tx_buf = lp->tx.buf; - lp->tx.trx.rx_buf = lp->tx.buf; - spi_message_add_tail(&lp->tx.trx, &lp->tx.msg); - hrtimer_init(&lp->tx.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - lp->tx.timer.function = at86rf230_async_state_timer; -} - #ifdef CONFIG_IEEE802154_AT86RF230_DEBUGFS static struct dentry *at86rf230_debugfs_root; @@ -1760,7 +1726,8 @@ static int at86rf230_probe(struct spi_device *spi) goto free_dev; } - at86rf230_setup_spi_messages(lp); + at86rf230_setup_spi_messages(lp, &lp->state); + at86rf230_setup_spi_messages(lp, &lp->tx); rc = at86rf230_detect_device(lp); if (rc < 0) -- cgit v1.2.3 From c9f883f6fe66ff08ea968494709f4c0b28bc619a Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:22 +0200 Subject: mrf24j40: cleanup define identation This patch replaces the spaces after define by a tab. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 76 +++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 997724b8e434..2b7fc00f1487 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -23,46 +23,46 @@ #include /* MRF24J40 Short Address Registers */ -#define REG_RXMCR 0x00 /* Receive MAC control */ -#define REG_PANIDL 0x01 /* PAN ID (low) */ -#define REG_PANIDH 0x02 /* PAN ID (high) */ -#define REG_SADRL 0x03 /* Short address (low) */ -#define REG_SADRH 0x04 /* Short address (high) */ -#define REG_EADR0 0x05 /* Long address (low) (high is EADR7) */ -#define REG_TXMCR 0x11 /* Transmit MAC control */ -#define REG_PACON0 0x16 /* Power Amplifier Control */ -#define REG_PACON1 0x17 /* Power Amplifier Control */ -#define REG_PACON2 0x18 /* Power Amplifier Control */ -#define REG_TXNCON 0x1B /* Transmit Normal FIFO Control */ -#define REG_TXSTAT 0x24 /* TX MAC Status Register */ -#define REG_SOFTRST 0x2A /* Soft Reset */ -#define REG_TXSTBL 0x2E /* TX Stabilization */ -#define REG_INTSTAT 0x31 /* Interrupt Status */ -#define REG_INTCON 0x32 /* Interrupt Control */ -#define REG_GPIO 0x33 /* GPIO */ -#define REG_TRISGPIO 0x34 /* GPIO direction */ -#define REG_RFCTL 0x36 /* RF Control Mode Register */ -#define REG_BBREG1 0x39 /* Baseband Registers */ -#define REG_BBREG2 0x3A /* */ -#define REG_BBREG6 0x3E /* */ -#define REG_CCAEDTH 0x3F /* Energy Detection Threshold */ +#define REG_RXMCR 0x00 /* Receive MAC control */ +#define REG_PANIDL 0x01 /* PAN ID (low) */ +#define REG_PANIDH 0x02 /* PAN ID (high) */ +#define REG_SADRL 0x03 /* Short address (low) */ +#define REG_SADRH 0x04 /* Short address (high) */ +#define REG_EADR0 0x05 /* Long address (low) (high is EADR7) */ +#define REG_TXMCR 0x11 /* Transmit MAC control */ +#define REG_PACON0 0x16 /* Power Amplifier Control */ +#define REG_PACON1 0x17 /* Power Amplifier Control */ +#define REG_PACON2 0x18 /* Power Amplifier Control */ +#define REG_TXNCON 0x1B /* Transmit Normal FIFO Control */ +#define REG_TXSTAT 0x24 /* TX MAC Status Register */ +#define REG_SOFTRST 0x2A /* Soft Reset */ +#define REG_TXSTBL 0x2E /* TX Stabilization */ +#define REG_INTSTAT 0x31 /* Interrupt Status */ +#define REG_INTCON 0x32 /* Interrupt Control */ +#define REG_GPIO 0x33 /* GPIO */ +#define REG_TRISGPIO 0x34 /* GPIO direction */ +#define REG_RFCTL 0x36 /* RF Control Mode Register */ +#define REG_BBREG1 0x39 /* Baseband Registers */ +#define REG_BBREG2 0x3A /* */ +#define REG_BBREG6 0x3E /* */ +#define REG_CCAEDTH 0x3F /* Energy Detection Threshold */ /* MRF24J40 Long Address Registers */ -#define REG_RFCON0 0x200 /* RF Control Registers */ -#define REG_RFCON1 0x201 -#define REG_RFCON2 0x202 -#define REG_RFCON3 0x203 -#define REG_RFCON5 0x205 -#define REG_RFCON6 0x206 -#define REG_RFCON7 0x207 -#define REG_RFCON8 0x208 -#define REG_RSSI 0x210 -#define REG_SLPCON0 0x211 /* Sleep Clock Control Registers */ -#define REG_SLPCON1 0x220 -#define REG_WAKETIMEL 0x222 /* Wake-up Time Match Value Low */ -#define REG_WAKETIMEH 0x223 /* Wake-up Time Match Value High */ -#define REG_TESTMODE 0x22F /* Test mode */ -#define REG_RX_FIFO 0x300 /* Receive FIFO */ +#define REG_RFCON0 0x200 /* RF Control Registers */ +#define REG_RFCON1 0x201 +#define REG_RFCON2 0x202 +#define REG_RFCON3 0x203 +#define REG_RFCON5 0x205 +#define REG_RFCON6 0x206 +#define REG_RFCON7 0x207 +#define REG_RFCON8 0x208 +#define REG_RSSI 0x210 +#define REG_SLPCON0 0x211 /* Sleep Clock Control Registers */ +#define REG_SLPCON1 0x220 +#define REG_WAKETIMEL 0x222 /* Wake-up Time Match Value Low */ +#define REG_WAKETIMEH 0x223 /* Wake-up Time Match Value High */ +#define REG_TESTMODE 0x22F /* Test mode */ +#define REG_RX_FIFO 0x300 /* Receive FIFO */ /* Device configuration: Only channels 11-26 on page 0 are supported. */ #define MRF24J40_CHAN_MIN 11 -- cgit v1.2.3 From b2cfdf3c6720b9b77758ef229401f28f48c3372b Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:23 +0200 Subject: mrf24j40: use ieee802154_alloc_hw for private data This patch removes the own private dataroom allocation by calling devm_kzalloc for devrec and assign this pointer to "devrec->hw->priv". Instead we using like all other drivers ieee802154_alloc_hw and give the size for the private driver dataroom at the first argument. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 2b7fc00f1487..1023cd2b4095 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -723,16 +723,28 @@ err_ret: static int mrf24j40_probe(struct spi_device *spi) { int ret = -ENOMEM; + struct ieee802154_hw *hw; struct mrf24j40 *devrec; dev_info(&spi->dev, "probe(). IRQ: %d\n", spi->irq); - devrec = devm_kzalloc(&spi->dev, sizeof(struct mrf24j40), GFP_KERNEL); - if (!devrec) + /* Register with the 802154 subsystem */ + + hw = ieee802154_alloc_hw(sizeof(*devrec), &mrf24j40_ops); + if (!hw) goto err_ret; + + devrec = hw->priv; + devrec->spi = spi; + spi_set_drvdata(spi, devrec); + devrec->hw = hw; + devrec->hw->parent = &spi->dev; + devrec->hw->phy->supported.channels[0] = CHANNEL_MASK; + devrec->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AFILT; + devrec->buf = devm_kzalloc(&spi->dev, 3, GFP_KERNEL); if (!devrec->buf) - goto err_ret; + goto err_register_device; spi->mode = SPI_MODE_0; /* TODO: Is this appropriate for right here? */ if (spi->max_speed_hz > MAX_SPI_SPEED_HZ) @@ -740,19 +752,6 @@ static int mrf24j40_probe(struct spi_device *spi) mutex_init(&devrec->buffer_mutex); init_completion(&devrec->tx_complete); - devrec->spi = spi; - spi_set_drvdata(spi, devrec); - - /* Register with the 802154 subsystem */ - - devrec->hw = ieee802154_alloc_hw(0, &mrf24j40_ops); - if (!devrec->hw) - goto err_ret; - - devrec->hw->priv = devrec; - devrec->hw->parent = &devrec->spi->dev; - devrec->hw->phy->supported.channels[0] = CHANNEL_MASK; - devrec->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AFILT; dev_dbg(printdev(devrec), "registered mrf24j40\n"); ret = ieee802154_register_hw(devrec->hw); -- cgit v1.2.3 From a339e1849b9504b6e9631777e41ea2a240e58621 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:24 +0200 Subject: mrf24j40: calling ieee802154_register_hw at last The function ieee802154_register_hw should always called at last. Currently we do hardware init and such things after register hardware into the subsystem. It could be that the subsystem already call driver operations while running hardware init. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 1023cd2b4095..de63cba88fa0 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -753,14 +753,9 @@ static int mrf24j40_probe(struct spi_device *spi) mutex_init(&devrec->buffer_mutex); init_completion(&devrec->tx_complete); - dev_dbg(printdev(devrec), "registered mrf24j40\n"); - ret = ieee802154_register_hw(devrec->hw); - if (ret) - goto err_register_device; - ret = mrf24j40_hw_init(devrec); if (ret) - goto err_hw_init; + goto err_register_device; ret = devm_request_threaded_irq(&spi->dev, spi->irq, @@ -772,14 +767,16 @@ static int mrf24j40_probe(struct spi_device *spi) if (ret) { dev_err(printdev(devrec), "Unable to get IRQ"); - goto err_irq; + goto err_register_device; } + dev_dbg(printdev(devrec), "registered mrf24j40\n"); + ret = ieee802154_register_hw(devrec->hw); + if (ret) + goto err_register_device; + return 0; -err_irq: -err_hw_init: - ieee802154_unregister_hw(devrec->hw); err_register_device: ieee802154_free_hw(devrec->hw); err_ret: -- cgit v1.2.3 From 78aedb6bfa43f43dacd8fc7b06452a87d33e3886 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:25 +0200 Subject: mrf24j40: remove spi settings overwrite This patch removes spi settings while mrf24j40 probing. These settings cannot be overwrite while device probing where spi controller should be already configured. These settings need to be setup by device tree or platform data. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index de63cba88fa0..41d9f5770148 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -746,9 +746,11 @@ static int mrf24j40_probe(struct spi_device *spi) if (!devrec->buf) goto err_register_device; - spi->mode = SPI_MODE_0; /* TODO: Is this appropriate for right here? */ - if (spi->max_speed_hz > MAX_SPI_SPEED_HZ) - spi->max_speed_hz = MAX_SPI_SPEED_HZ; + if (spi->max_speed_hz > MAX_SPI_SPEED_HZ) { + dev_warn(&spi->dev, "spi clock above possible maximum: %d", + MAX_SPI_SPEED_HZ); + return -EINVAL; + } mutex_init(&devrec->buffer_mutex); init_completion(&devrec->tx_complete); -- cgit v1.2.3 From 2e6fd648b6b87e6a2289c875c6067acc3bd88b3e Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:26 +0200 Subject: mrf24j40: add device-tree support This patch adds devicetree support to mrf24j40 with proper devicetree compatible strings. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 41d9f5770148..89150bd43ab2 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -799,6 +799,14 @@ static int mrf24j40_remove(struct spi_device *spi) return 0; } +static const struct of_device_id mrf24j40_of_match[] = { + { .compatible = "microchip,mrf24j40", .data = (void *)MRF24J40 }, + { .compatible = "microchip,mrf24j40ma", .data = (void *)MRF24J40MA }, + { .compatible = "microchip,mrf24j40mc", .data = (void *)MRF24J40MC }, + { }, +}; +MODULE_DEVICE_TABLE(of, mrf24j40_of_match); + static const struct spi_device_id mrf24j40_ids[] = { { "mrf24j40", MRF24J40 }, { "mrf24j40ma", MRF24J40MA }, @@ -809,6 +817,7 @@ MODULE_DEVICE_TABLE(spi, mrf24j40_ids); static struct spi_driver mrf24j40_driver = { .driver = { + .of_match_table = of_match_ptr(mrf24j40_of_match), .name = "mrf24j40", .owner = THIS_MODULE, }, -- cgit v1.2.3 From 766928fbf8c989f65184c3ed0d48fd3004213c46 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:27 +0200 Subject: mrf24j40: add default channel setting Per default mrf24j40 has the channel 11 after reset. This patch adds the right phy default value for the channel setting. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 89150bd43ab2..7c224cdbe561 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -720,6 +720,11 @@ err_ret: return ret; } +static void mrf24j40_phy_setup(struct mrf24j40 *devrec) +{ + devrec->hw->phy->current_channel = 11; +} + static int mrf24j40_probe(struct spi_device *spi) { int ret = -ENOMEM; @@ -759,6 +764,8 @@ static int mrf24j40_probe(struct spi_device *spi) if (ret) goto err_register_device; + mrf24j40_phy_setup(devrec); + ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, -- cgit v1.2.3 From d344c91280326469e5f9c5a3b1b92ef0d1c5d25f Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:28 +0200 Subject: mrf24j40: add random extended addr generation The mrf24j40 has no source to get a permanent extended address. This patch will add a random generated permanent extended address source. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 7c224cdbe561..80b3c6e72cb3 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -722,6 +722,7 @@ err_ret: static void mrf24j40_phy_setup(struct mrf24j40 *devrec) { + ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr); devrec->hw->phy->current_channel = 11; } -- cgit v1.2.3 From 554b49493b89b068643b7360334b40d5f5ca8ff2 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:29 +0200 Subject: mrf24j40: add more register defines For supporting regmap, this patch will add more register defines to prepare a full register dump by regmap debugfs. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 68 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 80b3c6e72cb3..12f0606dce3e 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -29,21 +29,56 @@ #define REG_SADRL 0x03 /* Short address (low) */ #define REG_SADRH 0x04 /* Short address (high) */ #define REG_EADR0 0x05 /* Long address (low) (high is EADR7) */ +#define REG_EADR1 0x06 +#define REG_EADR2 0x07 +#define REG_EADR3 0x08 +#define REG_EADR4 0x09 +#define REG_EADR5 0x0A +#define REG_EADR6 0x0B +#define REG_EADR7 0x0C +#define REG_RXFLUSH 0x0D +#define REG_ORDER 0x10 #define REG_TXMCR 0x11 /* Transmit MAC control */ +#define REG_ACKTMOUT 0x12 +#define REG_ESLOTG1 0x13 +#define REG_SYMTICKL 0x14 +#define REG_SYMTICKH 0x15 #define REG_PACON0 0x16 /* Power Amplifier Control */ #define REG_PACON1 0x17 /* Power Amplifier Control */ #define REG_PACON2 0x18 /* Power Amplifier Control */ +#define REG_TXBCON0 0x1A #define REG_TXNCON 0x1B /* Transmit Normal FIFO Control */ +#define REG_TXG1CON 0x1C +#define REG_TXG2CON 0x1D +#define REG_ESLOTG23 0x1E +#define REG_ESLOTG45 0x1F +#define REG_ESLOTG67 0x20 +#define REG_TXPEND 0x21 +#define REG_WAKECON 0x22 +#define REG_FROMOFFSET 0x23 #define REG_TXSTAT 0x24 /* TX MAC Status Register */ +#define REG_TXBCON1 0x25 +#define REG_GATECLK 0x26 +#define REG_TXTIME 0x27 +#define REG_HSYMTMRL 0x28 +#define REG_HSYMTMRH 0x29 #define REG_SOFTRST 0x2A /* Soft Reset */ +#define REG_SECCON0 0x2C +#define REG_SECCON1 0x2D #define REG_TXSTBL 0x2E /* TX Stabilization */ +#define REG_RXSR 0x30 #define REG_INTSTAT 0x31 /* Interrupt Status */ #define REG_INTCON 0x32 /* Interrupt Control */ #define REG_GPIO 0x33 /* GPIO */ #define REG_TRISGPIO 0x34 /* GPIO direction */ +#define REG_SLPACK 0x35 #define REG_RFCTL 0x36 /* RF Control Mode Register */ +#define REG_SECCR2 0x37 +#define REG_BBREG0 0x38 #define REG_BBREG1 0x39 /* Baseband Registers */ #define REG_BBREG2 0x3A /* */ +#define REG_BBREG3 0x3B +#define REG_BBREG4 0x3C #define REG_BBREG6 0x3E /* */ #define REG_CCAEDTH 0x3F /* Energy Detection Threshold */ @@ -56,12 +91,45 @@ #define REG_RFCON6 0x206 #define REG_RFCON7 0x207 #define REG_RFCON8 0x208 +#define REG_SLPCAL0 0x209 +#define REG_SLPCAL1 0x20A +#define REG_SLPCAL2 0x20B +#define REG_RFSTATE 0x20F #define REG_RSSI 0x210 #define REG_SLPCON0 0x211 /* Sleep Clock Control Registers */ #define REG_SLPCON1 0x220 #define REG_WAKETIMEL 0x222 /* Wake-up Time Match Value Low */ #define REG_WAKETIMEH 0x223 /* Wake-up Time Match Value High */ +#define REG_REMCNTL 0x224 +#define REG_REMCNTH 0x225 +#define REG_MAINCNT0 0x226 +#define REG_MAINCNT1 0x227 +#define REG_MAINCNT2 0x228 +#define REG_MAINCNT3 0x229 #define REG_TESTMODE 0x22F /* Test mode */ +#define REG_ASSOEAR0 0x230 +#define REG_ASSOEAR1 0x231 +#define REG_ASSOEAR2 0x232 +#define REG_ASSOEAR3 0x233 +#define REG_ASSOEAR4 0x234 +#define REG_ASSOEAR5 0x235 +#define REG_ASSOEAR6 0x236 +#define REG_ASSOEAR7 0x237 +#define REG_ASSOSAR0 0x238 +#define REG_ASSOSAR1 0x239 +#define REG_UNONCE0 0x240 +#define REG_UNONCE1 0x241 +#define REG_UNONCE2 0x242 +#define REG_UNONCE3 0x243 +#define REG_UNONCE4 0x244 +#define REG_UNONCE5 0x245 +#define REG_UNONCE6 0x246 +#define REG_UNONCE7 0x247 +#define REG_UNONCE8 0x248 +#define REG_UNONCE9 0x249 +#define REG_UNONCE10 0x24A +#define REG_UNONCE11 0x24B +#define REG_UNONCE12 0x24C #define REG_RX_FIFO 0x300 /* Receive FIFO */ /* Device configuration: Only channels 11-26 on page 0 are supported. */ -- cgit v1.2.3 From b0156792001b7a19bc115dcc32aebb9b9a0b6a01 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:30 +0200 Subject: mrf24j40: add regmap support This patch introduce regmap support for short and long address space of mrf24j40. It's only possible to use regmap_read/write/update_bits for long address range. This is because I added lowlevel bus operation because the write operation need to set the 12th bit to mark a register write, but regmap only supports to set bits for register write access in the first byte. We use other regmap register functions than read/write/update_bits, so this should be fine. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/Kconfig | 1 + drivers/net/ieee802154/mrf24j40.c | 312 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 313 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig index 5a614b2d0767..ce5f1a21e6d7 100644 --- a/drivers/net/ieee802154/Kconfig +++ b/drivers/net/ieee802154/Kconfig @@ -43,6 +43,7 @@ config IEEE802154_MRF24J40 tristate "Microchip MRF24J40 transceiver driver" depends on IEEE802154_DRIVERS && MAC802154 depends on SPI + select REGMAP_SPI ---help--- Say Y here to enable the MRF24J20 SPI 802.15.4 wireless controller. diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 12f0606dce3e..c8b7ce6b5462 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -149,11 +150,22 @@ struct mrf24j40 { struct spi_device *spi; struct ieee802154_hw *hw; + struct regmap *regmap_short; + struct regmap *regmap_long; struct mutex buffer_mutex; /* only used to protect buf */ struct completion tx_complete; u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */ }; +/* regmap information for short address register access */ +#define MRF24J40_SHORT_WRITE 0x01 +#define MRF24J40_SHORT_READ 0x00 +#define MRF24J40_SHORT_NUMREGS 0x3F + +/* regmap information for long address register access */ +#define MRF24J40_LONG_ACCESS 0x80 +#define MRF24J40_LONG_NUMREGS 0x38F + /* Read/Write SPI Commands for Short and Long Address registers. */ #define MRF24J40_READSHORT(reg) ((reg) << 1) #define MRF24J40_WRITESHORT(reg) ((reg) << 1 | 1) @@ -165,6 +177,287 @@ struct mrf24j40 { #define printdev(X) (&X->spi->dev) +static bool +mrf24j40_short_reg_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case REG_RXMCR: + case REG_PANIDL: + case REG_PANIDH: + case REG_SADRL: + case REG_SADRH: + case REG_EADR0: + case REG_EADR1: + case REG_EADR2: + case REG_EADR3: + case REG_EADR4: + case REG_EADR5: + case REG_EADR6: + case REG_EADR7: + case REG_RXFLUSH: + case REG_ORDER: + case REG_TXMCR: + case REG_ACKTMOUT: + case REG_ESLOTG1: + case REG_SYMTICKL: + case REG_SYMTICKH: + case REG_PACON0: + case REG_PACON1: + case REG_PACON2: + case REG_TXBCON0: + case REG_TXNCON: + case REG_TXG1CON: + case REG_TXG2CON: + case REG_ESLOTG23: + case REG_ESLOTG45: + case REG_ESLOTG67: + case REG_TXPEND: + case REG_WAKECON: + case REG_FROMOFFSET: + case REG_TXBCON1: + case REG_GATECLK: + case REG_TXTIME: + case REG_HSYMTMRL: + case REG_HSYMTMRH: + case REG_SOFTRST: + case REG_SECCON0: + case REG_SECCON1: + case REG_TXSTBL: + case REG_RXSR: + case REG_INTCON: + case REG_TRISGPIO: + case REG_GPIO: + case REG_RFCTL: + case REG_SLPACK: + case REG_BBREG0: + case REG_BBREG1: + case REG_BBREG2: + case REG_BBREG3: + case REG_BBREG4: + case REG_BBREG6: + case REG_CCAEDTH: + return true; + default: + return false; + } +} + +static bool +mrf24j40_short_reg_readable(struct device *dev, unsigned int reg) +{ + bool rc; + + /* all writeable are also readable */ + rc = mrf24j40_short_reg_writeable(dev, reg); + if (rc) + return rc; + + /* readonly regs */ + switch (reg) { + case REG_TXSTAT: + case REG_INTSTAT: + return true; + default: + return false; + } +} + +static bool +mrf24j40_short_reg_volatile(struct device *dev, unsigned int reg) +{ + /* can be changed during runtime */ + switch (reg) { + case REG_TXSTAT: + case REG_INTSTAT: + case REG_RXFLUSH: + case REG_TXNCON: + case REG_SOFTRST: + case REG_RFCTL: + case REG_TXBCON0: + case REG_TXG1CON: + case REG_TXG2CON: + case REG_TXBCON1: + case REG_SECCON0: + case REG_RXSR: + case REG_SLPACK: + case REG_SECCR2: + case REG_BBREG6: + /* use them in spi_async and regmap so it's volatile */ + case REG_BBREG1: + return true; + default: + return false; + } +} + +static bool +mrf24j40_short_reg_precious(struct device *dev, unsigned int reg) +{ + /* don't clear irq line on read */ + switch (reg) { + case REG_INTSTAT: + return true; + default: + return false; + } +} + +static const struct regmap_config mrf24j40_short_regmap = { + .name = "mrf24j40_short", + .reg_bits = 7, + .val_bits = 8, + .pad_bits = 1, + .write_flag_mask = MRF24J40_SHORT_WRITE, + .read_flag_mask = MRF24J40_SHORT_READ, + .cache_type = REGCACHE_RBTREE, + .max_register = MRF24J40_SHORT_NUMREGS, + .writeable_reg = mrf24j40_short_reg_writeable, + .readable_reg = mrf24j40_short_reg_readable, + .volatile_reg = mrf24j40_short_reg_volatile, + .precious_reg = mrf24j40_short_reg_precious, +}; + +static bool +mrf24j40_long_reg_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case REG_RFCON0: + case REG_RFCON1: + case REG_RFCON2: + case REG_RFCON3: + case REG_RFCON5: + case REG_RFCON6: + case REG_RFCON7: + case REG_RFCON8: + case REG_SLPCAL2: + case REG_SLPCON0: + case REG_SLPCON1: + case REG_WAKETIMEL: + case REG_WAKETIMEH: + case REG_REMCNTL: + case REG_REMCNTH: + case REG_MAINCNT0: + case REG_MAINCNT1: + case REG_MAINCNT2: + case REG_MAINCNT3: + case REG_TESTMODE: + case REG_ASSOEAR0: + case REG_ASSOEAR1: + case REG_ASSOEAR2: + case REG_ASSOEAR3: + case REG_ASSOEAR4: + case REG_ASSOEAR5: + case REG_ASSOEAR6: + case REG_ASSOEAR7: + case REG_ASSOSAR0: + case REG_ASSOSAR1: + case REG_UNONCE0: + case REG_UNONCE1: + case REG_UNONCE2: + case REG_UNONCE3: + case REG_UNONCE4: + case REG_UNONCE5: + case REG_UNONCE6: + case REG_UNONCE7: + case REG_UNONCE8: + case REG_UNONCE9: + case REG_UNONCE10: + case REG_UNONCE11: + case REG_UNONCE12: + return true; + default: + return false; + } +} + +static bool +mrf24j40_long_reg_readable(struct device *dev, unsigned int reg) +{ + bool rc; + + /* all writeable are also readable */ + rc = mrf24j40_long_reg_writeable(dev, reg); + if (rc) + return rc; + + /* readonly regs */ + switch (reg) { + case REG_SLPCAL0: + case REG_SLPCAL1: + case REG_RFSTATE: + case REG_RSSI: + return true; + default: + return false; + } +} + +static bool +mrf24j40_long_reg_volatile(struct device *dev, unsigned int reg) +{ + /* can be changed during runtime */ + switch (reg) { + case REG_SLPCAL0: + case REG_SLPCAL1: + case REG_SLPCAL2: + case REG_RFSTATE: + case REG_RSSI: + case REG_MAINCNT3: + return true; + default: + return false; + } +} + +static const struct regmap_config mrf24j40_long_regmap = { + .name = "mrf24j40_long", + .reg_bits = 11, + .val_bits = 8, + .pad_bits = 5, + .write_flag_mask = MRF24J40_LONG_ACCESS, + .read_flag_mask = MRF24J40_LONG_ACCESS, + .cache_type = REGCACHE_RBTREE, + .max_register = MRF24J40_LONG_NUMREGS, + .writeable_reg = mrf24j40_long_reg_writeable, + .readable_reg = mrf24j40_long_reg_readable, + .volatile_reg = mrf24j40_long_reg_volatile, +}; + +static int mrf24j40_long_regmap_write(void *context, const void *data, + size_t count) +{ + struct spi_device *spi = context; + u8 buf[3]; + + if (count > 3) + return -EINVAL; + + /* regmap supports read/write mask only in frist byte + * long write access need to set the 12th bit, so we + * make special handling for write. + */ + memcpy(buf, data, count); + buf[1] |= (1 << 4); + + return spi_write(spi, buf, count); +} + +static int +mrf24j40_long_regmap_read(void *context, const void *reg, size_t reg_size, + void *val, size_t val_size) +{ + struct spi_device *spi = context; + + return spi_write_then_read(spi, reg, reg_size, val, val_size); +} + +static const struct regmap_bus mrf24j40_long_regmap_bus = { + .write = mrf24j40_long_regmap_write, + .read = mrf24j40_long_regmap_read, + .reg_format_endian_default = REGMAP_ENDIAN_BIG, + .val_format_endian_default = REGMAP_ENDIAN_BIG, +}; + static int write_short_reg(struct mrf24j40 *devrec, u8 reg, u8 value) { int ret; @@ -816,6 +1109,25 @@ static int mrf24j40_probe(struct spi_device *spi) devrec->hw->phy->supported.channels[0] = CHANNEL_MASK; devrec->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AFILT; + devrec->regmap_short = devm_regmap_init_spi(spi, + &mrf24j40_short_regmap); + if (IS_ERR(devrec->regmap_short)) { + ret = PTR_ERR(devrec->regmap_short); + dev_err(&spi->dev, "Failed to allocate short register map: %d\n", + ret); + goto err_register_device; + } + + devrec->regmap_long = devm_regmap_init(&spi->dev, + &mrf24j40_long_regmap_bus, + spi, &mrf24j40_long_regmap); + if (IS_ERR(devrec->regmap_long)) { + ret = PTR_ERR(devrec->regmap_long); + dev_err(&spi->dev, "Failed to allocate long register map: %d\n", + ret); + goto err_register_device; + } + devrec->buf = devm_kzalloc(&spi->dev, 3, GFP_KERNEL); if (!devrec->buf) goto err_register_device; -- cgit v1.2.3 From 42c7148e06661ae0ca1bb511e1b98878b5f522f8 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:31 +0200 Subject: mrf24j40: use regmap for register access This patch uses the regmap functions for transceiver register settings where it's possible. This means everything except the hotpaths like receive/transmit handling. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 147 +++++++++++++------------------------- 1 file changed, 50 insertions(+), 97 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index c8b7ce6b5462..ca98b5c603ce 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -543,35 +543,6 @@ static int read_long_reg(struct mrf24j40 *devrec, u16 reg, u8 *value) return ret; } -static int write_long_reg(struct mrf24j40 *devrec, u16 reg, u8 val) -{ - int ret; - u16 cmd; - struct spi_message msg; - struct spi_transfer xfer = { - .len = 3, - .tx_buf = devrec->buf, - .rx_buf = devrec->buf, - }; - - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - - cmd = MRF24J40_WRITELONG(reg); - mutex_lock(&devrec->buffer_mutex); - devrec->buf[0] = cmd >> 8 & 0xff; - devrec->buf[1] = cmd & 0xff; - devrec->buf[2] = val; - - ret = spi_sync(devrec->spi, &msg); - if (ret) - dev_err(printdev(devrec), - "SPI write Failed for long register 0x%hx\n", reg); - - mutex_unlock(&devrec->buffer_mutex); - return ret; -} - /* This function relies on an undocumented write method. Once a write command and address is set, as many bytes of data as desired can be clocked into the device. The datasheet only shows setting one byte at a time. */ @@ -755,33 +726,23 @@ static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level) static int mrf24j40_start(struct ieee802154_hw *hw) { struct mrf24j40 *devrec = hw->priv; - u8 val; - int ret; dev_dbg(printdev(devrec), "start\n"); - ret = read_short_reg(devrec, REG_INTCON, &val); - if (ret) - return ret; - val &= ~(0x1|0x8); /* Clear TXNIE and RXIE. Enable interrupts */ - write_short_reg(devrec, REG_INTCON, val); - - return 0; + /* Clear TXNIE and RXIE. Enable interrupts */ + return regmap_update_bits(devrec->regmap_short, REG_INTCON, + 0x01 | 0x08, 0x00); } static void mrf24j40_stop(struct ieee802154_hw *hw) { struct mrf24j40 *devrec = hw->priv; - u8 val; - int ret; dev_dbg(printdev(devrec), "stop\n"); - ret = read_short_reg(devrec, REG_INTCON, &val); - if (ret) - return; - val |= 0x1|0x8; /* Set TXNIE and RXIE. Disable Interrupts */ - write_short_reg(devrec, REG_INTCON, val); + /* Set TXNIE and RXIE. Disable Interrupts */ + regmap_update_bits(devrec->regmap_short, REG_INTCON, 0x01 | 0x08, + 0x01 | 0x08); } static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel) @@ -798,20 +759,20 @@ static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel) /* Set Channel TODO */ val = (channel-11) << 4 | 0x03; - write_long_reg(devrec, REG_RFCON0, val); + ret = regmap_update_bits(devrec->regmap_long, REG_RFCON0, 0xf0, val); + if (ret) + return ret; /* RF Reset */ - ret = read_short_reg(devrec, REG_RFCTL, &val); + ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, 0x04, 0x04); if (ret) return ret; - val |= 0x04; - write_short_reg(devrec, REG_RFCTL, val); - val &= ~0x04; - write_short_reg(devrec, REG_RFCTL, val); - udelay(SET_CHANNEL_DELAY_US); /* per datasheet */ + ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, 0x04, 0x00); + if (!ret) + udelay(SET_CHANNEL_DELAY_US); /* per datasheet */ - return 0; + return ret; } static int mrf24j40_filter(struct ieee802154_hw *hw, @@ -829,8 +790,8 @@ static int mrf24j40_filter(struct ieee802154_hw *hw, addrh = le16_to_cpu(filt->short_addr) >> 8 & 0xff; addrl = le16_to_cpu(filt->short_addr) & 0xff; - write_short_reg(devrec, REG_SADRH, addrh); - write_short_reg(devrec, REG_SADRL, addrl); + regmap_write(devrec->regmap_short, REG_SADRH, addrh); + regmap_write(devrec->regmap_short, REG_SADRL, addrl); dev_dbg(printdev(devrec), "Set short addr to %04hx\n", filt->short_addr); } @@ -841,7 +802,8 @@ static int mrf24j40_filter(struct ieee802154_hw *hw, memcpy(addr, &filt->ieee_addr, 8); for (i = 0; i < 8; i++) - write_short_reg(devrec, REG_EADR0 + i, addr[i]); + regmap_write(devrec->regmap_short, REG_EADR0 + i, + addr[i]); #ifdef DEBUG pr_debug("Set long addr to: "); @@ -857,8 +819,8 @@ static int mrf24j40_filter(struct ieee802154_hw *hw, panidh = le16_to_cpu(filt->pan_id) >> 8 & 0xff; panidl = le16_to_cpu(filt->pan_id) & 0xff; - write_short_reg(devrec, REG_PANIDH, panidh); - write_short_reg(devrec, REG_PANIDL, panidl); + regmap_write(devrec->regmap_short, REG_PANIDH, panidh); + regmap_write(devrec->regmap_short, REG_PANIDL, panidl); dev_dbg(printdev(devrec), "Set PANID to %04hx\n", filt->pan_id); } @@ -868,14 +830,14 @@ static int mrf24j40_filter(struct ieee802154_hw *hw, u8 val; int ret; - ret = read_short_reg(devrec, REG_RXMCR, &val); - if (ret) - return ret; if (filt->pan_coord) - val |= 0x8; + val = 0x8; else - val &= ~0x8; - write_short_reg(devrec, REG_RXMCR, val); + val = 0x0; + ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x8, + val); + if (ret) + return ret; /* REG_SLOTTED is maintained as default (unslotted/CSMA-CA). * REG_ORDER is maintained as default (no beacon/superframe). @@ -976,80 +938,73 @@ out: static int mrf24j40_hw_init(struct mrf24j40 *devrec) { int ret; - u8 val; /* Initialize the device. From datasheet section 3.2: Initialization. */ - ret = write_short_reg(devrec, REG_SOFTRST, 0x07); + ret = regmap_write(devrec->regmap_short, REG_SOFTRST, 0x07); if (ret) goto err_ret; - ret = write_short_reg(devrec, REG_PACON2, 0x98); + ret = regmap_write(devrec->regmap_short, REG_PACON2, 0x98); if (ret) goto err_ret; - ret = write_short_reg(devrec, REG_TXSTBL, 0x95); + ret = regmap_write(devrec->regmap_short, REG_TXSTBL, 0x95); if (ret) goto err_ret; - ret = write_long_reg(devrec, REG_RFCON0, 0x03); + ret = regmap_write(devrec->regmap_long, REG_RFCON0, 0x03); if (ret) goto err_ret; - ret = write_long_reg(devrec, REG_RFCON1, 0x01); + ret = regmap_write(devrec->regmap_long, REG_RFCON1, 0x01); if (ret) goto err_ret; - ret = write_long_reg(devrec, REG_RFCON2, 0x80); + ret = regmap_write(devrec->regmap_long, REG_RFCON2, 0x80); if (ret) goto err_ret; - ret = write_long_reg(devrec, REG_RFCON6, 0x90); + ret = regmap_write(devrec->regmap_long, REG_RFCON6, 0x90); if (ret) goto err_ret; - ret = write_long_reg(devrec, REG_RFCON7, 0x80); + ret = regmap_write(devrec->regmap_long, REG_RFCON7, 0x80); if (ret) goto err_ret; - ret = write_long_reg(devrec, REG_RFCON8, 0x10); + ret = regmap_write(devrec->regmap_long, REG_RFCON8, 0x10); if (ret) goto err_ret; - ret = write_long_reg(devrec, REG_SLPCON1, 0x21); + ret = regmap_write(devrec->regmap_long, REG_SLPCON1, 0x21); if (ret) goto err_ret; - ret = write_short_reg(devrec, REG_BBREG2, 0x80); + ret = regmap_write(devrec->regmap_short, REG_BBREG2, 0x80); if (ret) goto err_ret; - ret = write_short_reg(devrec, REG_CCAEDTH, 0x60); + ret = regmap_write(devrec->regmap_short, REG_CCAEDTH, 0x60); if (ret) goto err_ret; - ret = write_short_reg(devrec, REG_BBREG6, 0x40); + ret = regmap_write(devrec->regmap_short, REG_BBREG6, 0x40); if (ret) goto err_ret; - ret = write_short_reg(devrec, REG_RFCTL, 0x04); + ret = regmap_write(devrec->regmap_short, REG_RFCTL, 0x04); if (ret) goto err_ret; - ret = write_short_reg(devrec, REG_RFCTL, 0x0); + ret = regmap_write(devrec->regmap_short, REG_RFCTL, 0x0); if (ret) goto err_ret; udelay(192); /* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */ - ret = read_short_reg(devrec, REG_RXMCR, &val); - if (ret) - goto err_ret; - - val &= ~0x3; /* Clear RX mode (normal) */ - - ret = write_short_reg(devrec, REG_RXMCR, val); + ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x03, 0x00); if (ret) goto err_ret; @@ -1057,22 +1012,20 @@ static int mrf24j40_hw_init(struct mrf24j40 *devrec) /* Enable external amplifier. * From MRF24J40MC datasheet section 1.3: Operation. */ - read_long_reg(devrec, REG_TESTMODE, &val); - val |= 0x7; /* Configure GPIO 0-2 to control amplifier */ - write_long_reg(devrec, REG_TESTMODE, val); + regmap_update_bits(devrec->regmap_long, REG_TESTMODE, 0x07, + 0x07); - read_short_reg(devrec, REG_TRISGPIO, &val); - val |= 0x8; /* Set GPIO3 as output. */ - write_short_reg(devrec, REG_TRISGPIO, val); + /* Set GPIO3 as output. */ + regmap_update_bits(devrec->regmap_short, REG_TRISGPIO, 0x08, + 0x08); - read_short_reg(devrec, REG_GPIO, &val); - val |= 0x8; /* Set GPIO3 HIGH to enable U5 voltage regulator */ - write_short_reg(devrec, REG_GPIO, val); + /* Set GPIO3 HIGH to enable U5 voltage regulator */ + regmap_update_bits(devrec->regmap_short, REG_GPIO, 0x08, 0x08); /* Reduce TX pwr to meet FCC requirements. * From MRF24J40MC datasheet section 3.1.1 */ - write_long_reg(devrec, REG_RFCON3, 0x28); + regmap_write(devrec->regmap_long, REG_RFCON3, 0x28); } return 0; -- cgit v1.2.3 From ab40ff7508d2f54ed03b99523493c46250649c52 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:32 +0200 Subject: mrf24j40: change to frame delivery with crc This patch changes the frame delivery to mac802154 with crc. This is useful for monitor interface types which deliver the crc to userspace. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index ca98b5c603ce..788adb654f32 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -881,9 +881,6 @@ static int mrf24j40_handle_rx(struct mrf24j40 *devrec) goto out; } - /* Cut off the checksum */ - skb_trim(skb, len-2); - /* TODO: Other drivers call ieee20154_rx_irqsafe() here (eg: cc2040, * also from a workqueue). I think irqsafe is not necessary here. * Can someone confirm? */ @@ -1060,7 +1057,7 @@ static int mrf24j40_probe(struct spi_device *spi) devrec->hw = hw; devrec->hw->parent = &spi->dev; devrec->hw->phy->supported.channels[0] = CHANNEL_MASK; - devrec->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AFILT; + devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT; devrec->regmap_short = devm_regmap_init_spi(spi, &mrf24j40_short_regmap); -- cgit v1.2.3 From 6844a0e4debd67c9bcf6a8fed3c7f9c24413c349 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:34 +0200 Subject: mrf24j40: rework tx handling to async tx handling This patch reworks the current transmit API to spi_async handling. We removed the error handling check, because mac802154 has no chance to report it. Also the transmit timeout handling can't be handled by xmit async handling, for this usecase we need to implement the netdev watchdog. These are all unlikely cases which we drop now and should be provided by netdev watchdog. We also drop the bit setting for TXNACKREQ at register TXNCON, this is not necessary. The TXNCON register should set only once for each frame, previous settings doesn't matter. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 161 ++++++++++++++++++-------------------- 1 file changed, 78 insertions(+), 83 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 788adb654f32..3cf06257b19f 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -152,8 +152,22 @@ struct mrf24j40 { struct regmap *regmap_short; struct regmap *regmap_long; + + /* for writing txfifo */ + struct spi_message tx_msg; + u8 tx_hdr_buf[2]; + struct spi_transfer tx_hdr_trx; + u8 tx_len_buf[2]; + struct spi_transfer tx_len_trx; + struct spi_transfer tx_buf_trx; + struct sk_buff *tx_skb; + + /* post transmit message to send frame out */ + struct spi_message tx_post_msg; + u8 tx_post_buf[2]; + struct spi_transfer tx_post_trx; + struct mutex buffer_mutex; /* only used to protect buf */ - struct completion tx_complete; u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */ }; @@ -543,28 +557,33 @@ static int read_long_reg(struct mrf24j40 *devrec, u16 reg, u8 *value) return ret; } +static void write_tx_buf_complete(void *context) +{ + struct mrf24j40 *devrec = context; + __le16 fc = ieee802154_get_fc_from_skb(devrec->tx_skb); + u8 val = 0x01; + int ret; + + if (ieee802154_is_ackreq(fc)) + val |= 0x04; + + devrec->tx_post_msg.complete = NULL; + devrec->tx_post_buf[0] = MRF24J40_WRITESHORT(REG_TXNCON); + devrec->tx_post_buf[1] = val; + + ret = spi_async(devrec->spi, &devrec->tx_post_msg); + if (ret) + dev_err(printdev(devrec), "SPI write Failed for transmit buf\n"); +} + /* This function relies on an undocumented write method. Once a write command and address is set, as many bytes of data as desired can be clocked into the device. The datasheet only shows setting one byte at a time. */ static int write_tx_buf(struct mrf24j40 *devrec, u16 reg, const u8 *data, size_t length) { - int ret; u16 cmd; - u8 lengths[2]; - struct spi_message msg; - struct spi_transfer addr_xfer = { - .len = 2, - .tx_buf = devrec->buf, - }; - struct spi_transfer lengths_xfer = { - .len = 2, - .tx_buf = &lengths, /* TODO: Is DMA really required for SPI? */ - }; - struct spi_transfer data_xfer = { - .len = length, - .tx_buf = data, - }; + int ret; /* Range check the length. 2 bytes are used for the length fields.*/ if (length > TX_FIFO_SIZE-2) { @@ -572,26 +591,31 @@ static int write_tx_buf(struct mrf24j40 *devrec, u16 reg, length = TX_FIFO_SIZE-2; } - spi_message_init(&msg); - spi_message_add_tail(&addr_xfer, &msg); - spi_message_add_tail(&lengths_xfer, &msg); - spi_message_add_tail(&data_xfer, &msg); - cmd = MRF24J40_WRITELONG(reg); - mutex_lock(&devrec->buffer_mutex); - devrec->buf[0] = cmd >> 8 & 0xff; - devrec->buf[1] = cmd & 0xff; - lengths[0] = 0x0; /* Header Length. Set to 0 for now. TODO */ - lengths[1] = length; /* Total length */ - - ret = spi_sync(devrec->spi, &msg); + devrec->tx_hdr_buf[0] = cmd >> 8 & 0xff; + devrec->tx_hdr_buf[1] = cmd & 0xff; + devrec->tx_len_buf[0] = 0x0; /* Header Length. Set to 0 for now. TODO */ + devrec->tx_len_buf[1] = length; /* Total length */ + devrec->tx_buf_trx.tx_buf = data; + devrec->tx_buf_trx.len = length; + + ret = spi_async(devrec->spi, &devrec->tx_msg); if (ret) dev_err(printdev(devrec), "SPI write Failed for TX buf\n"); - mutex_unlock(&devrec->buffer_mutex); return ret; } +static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb) +{ + struct mrf24j40 *devrec = hw->priv; + + dev_dbg(printdev(devrec), "tx packet of %d bytes\n", skb->len); + devrec->tx_skb = skb; + + return write_tx_buf(devrec, 0x000, skb->data, skb->len); +} + static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec, u8 *data, u8 *len, u8 *lqi) { @@ -664,57 +688,6 @@ out: return ret; } -static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb) -{ - struct mrf24j40 *devrec = hw->priv; - u8 val; - int ret = 0; - - dev_dbg(printdev(devrec), "tx packet of %d bytes\n", skb->len); - - ret = write_tx_buf(devrec, 0x000, skb->data, skb->len); - if (ret) - goto err; - - reinit_completion(&devrec->tx_complete); - - /* Set TXNTRIG bit of TXNCON to send packet */ - ret = read_short_reg(devrec, REG_TXNCON, &val); - if (ret) - goto err; - val |= 0x1; - /* Set TXNACKREQ if the ACK bit is set in the packet. */ - if (skb->data[0] & IEEE802154_FC_ACK_REQ) - val |= 0x4; - write_short_reg(devrec, REG_TXNCON, val); - - /* Wait for the device to send the TX complete interrupt. */ - ret = wait_for_completion_interruptible_timeout( - &devrec->tx_complete, - 5 * HZ); - if (ret == -ERESTARTSYS) - goto err; - if (ret == 0) { - dev_warn(printdev(devrec), "Timeout waiting for TX interrupt\n"); - ret = -ETIMEDOUT; - goto err; - } - - /* Check for send error from the device. */ - ret = read_short_reg(devrec, REG_TXSTAT, &val); - if (ret) - goto err; - if (val & 0x1) { - dev_dbg(printdev(devrec), "Error Sending. Retry count exceeded\n"); - ret = -ECOMM; /* TODO: Better error code ? */ - } else - dev_dbg(printdev(devrec), "Packet Sent\n"); - -err: - - return ret; -} - static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level) { /* TODO: */ @@ -901,7 +874,7 @@ out: static const struct ieee802154_ops mrf24j40_ops = { .owner = THIS_MODULE, - .xmit_sync = mrf24j40_tx, + .xmit_async = mrf24j40_tx, .ed = mrf24j40_ed, .start = mrf24j40_start, .stop = mrf24j40_stop, @@ -922,7 +895,7 @@ static irqreturn_t mrf24j40_isr(int irq, void *data) /* Check for TX complete */ if (intstat & 0x1) - complete(&devrec->tx_complete); + ieee802154_xmit_complete(devrec->hw, devrec->tx_skb, false); /* Check for Rx */ if (intstat & 0x8) @@ -1031,6 +1004,27 @@ err_ret: return ret; } +static void +mrf24j40_setup_tx_spi_messages(struct mrf24j40 *devrec) +{ + spi_message_init(&devrec->tx_msg); + devrec->tx_msg.context = devrec; + devrec->tx_msg.complete = write_tx_buf_complete; + devrec->tx_hdr_trx.len = 2; + devrec->tx_hdr_trx.tx_buf = devrec->tx_hdr_buf; + spi_message_add_tail(&devrec->tx_hdr_trx, &devrec->tx_msg); + devrec->tx_len_trx.len = 2; + devrec->tx_len_trx.tx_buf = devrec->tx_len_buf; + spi_message_add_tail(&devrec->tx_len_trx, &devrec->tx_msg); + spi_message_add_tail(&devrec->tx_buf_trx, &devrec->tx_msg); + + spi_message_init(&devrec->tx_post_msg); + devrec->tx_post_msg.context = devrec; + devrec->tx_post_trx.len = 2; + devrec->tx_post_trx.tx_buf = devrec->tx_post_buf; + spi_message_add_tail(&devrec->tx_post_trx, &devrec->tx_post_msg); +} + static void mrf24j40_phy_setup(struct mrf24j40 *devrec) { ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr); @@ -1059,6 +1053,8 @@ static int mrf24j40_probe(struct spi_device *spi) devrec->hw->phy->supported.channels[0] = CHANNEL_MASK; devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT; + mrf24j40_setup_tx_spi_messages(devrec); + devrec->regmap_short = devm_regmap_init_spi(spi, &mrf24j40_short_regmap); if (IS_ERR(devrec->regmap_short)) { @@ -1089,7 +1085,6 @@ static int mrf24j40_probe(struct spi_device *spi) } mutex_init(&devrec->buffer_mutex); - init_completion(&devrec->tx_complete); ret = mrf24j40_hw_init(devrec); if (ret) -- cgit v1.2.3 From c91a301162899ee100c1eab397958cb9aef50d0c Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:35 +0200 Subject: mrf24j40: rework rx handling to async rx handling This patch prepares that we can do the receive handling inside interrupt context by using spi_async. This is necessary for introduce a non-threaded irq handling. Also we drop the bit setting for "RXDECINV" at register "BBREG1", we do a driectly full write of register "BBREG1", because it contains the bit RXDECINV only. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 282 ++++++++++++++++---------------------- 1 file changed, 118 insertions(+), 164 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 3cf06257b19f..0cb251efdc0e 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -167,6 +167,20 @@ struct mrf24j40 { u8 tx_post_buf[2]; struct spi_transfer tx_post_trx; + /* for protect/unprotect/read length rxfifo */ + struct spi_message rx_msg; + u8 rx_buf[3]; + struct spi_transfer rx_trx; + + /* receive handling */ + struct spi_message rx_buf_msg; + u8 rx_addr_buf[2]; + struct spi_transfer rx_addr_trx; + u8 rx_lqi_buf[2]; + struct spi_transfer rx_lqi_trx; + u8 rx_fifo_buf[RX_FIFO_SIZE]; + struct spi_transfer rx_fifo_buf_trx; + struct mutex buffer_mutex; /* only used to protect buf */ u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */ }; @@ -472,32 +486,6 @@ static const struct regmap_bus mrf24j40_long_regmap_bus = { .val_format_endian_default = REGMAP_ENDIAN_BIG, }; -static int write_short_reg(struct mrf24j40 *devrec, u8 reg, u8 value) -{ - int ret; - struct spi_message msg; - struct spi_transfer xfer = { - .len = 2, - .tx_buf = devrec->buf, - .rx_buf = devrec->buf, - }; - - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - - mutex_lock(&devrec->buffer_mutex); - devrec->buf[0] = MRF24J40_WRITESHORT(reg); - devrec->buf[1] = value; - - ret = spi_sync(devrec->spi, &msg); - if (ret) - dev_err(printdev(devrec), - "SPI write Failed for short register 0x%hhx\n", reg); - - mutex_unlock(&devrec->buffer_mutex); - return ret; -} - static int read_short_reg(struct mrf24j40 *devrec, u8 reg, u8 *val) { int ret = -1; @@ -526,37 +514,6 @@ static int read_short_reg(struct mrf24j40 *devrec, u8 reg, u8 *val) return ret; } -static int read_long_reg(struct mrf24j40 *devrec, u16 reg, u8 *value) -{ - int ret; - u16 cmd; - struct spi_message msg; - struct spi_transfer xfer = { - .len = 3, - .tx_buf = devrec->buf, - .rx_buf = devrec->buf, - }; - - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - - cmd = MRF24J40_READLONG(reg); - mutex_lock(&devrec->buffer_mutex); - devrec->buf[0] = cmd >> 8 & 0xff; - devrec->buf[1] = cmd & 0xff; - devrec->buf[2] = 0; - - ret = spi_sync(devrec->spi, &msg); - if (ret) - dev_err(printdev(devrec), - "SPI read Failed for long register 0x%hx\n", reg); - else - *value = devrec->buf[2]; - - mutex_unlock(&devrec->buffer_mutex); - return ret; -} - static void write_tx_buf_complete(void *context) { struct mrf24j40 *devrec = context; @@ -616,78 +573,6 @@ static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb) return write_tx_buf(devrec, 0x000, skb->data, skb->len); } -static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec, - u8 *data, u8 *len, u8 *lqi) -{ - u8 rx_len; - u8 addr[2]; - u8 lqi_rssi[2]; - u16 cmd; - int ret; - struct spi_message msg; - struct spi_transfer addr_xfer = { - .len = 2, - .tx_buf = &addr, - }; - struct spi_transfer data_xfer = { - .len = 0x0, /* set below */ - .rx_buf = data, - }; - struct spi_transfer status_xfer = { - .len = 2, - .rx_buf = &lqi_rssi, - }; - - /* Get the length of the data in the RX FIFO. The length in this - * register exclues the 1-byte length field at the beginning. */ - ret = read_long_reg(devrec, REG_RX_FIFO, &rx_len); - if (ret) - goto out; - - /* Range check the RX FIFO length, accounting for the one-byte - * length field at the beginning. */ - if (rx_len > RX_FIFO_SIZE-1) { - dev_err(printdev(devrec), "Invalid length read from device. Performing short read.\n"); - rx_len = RX_FIFO_SIZE-1; - } - - if (rx_len > *len) { - /* Passed in buffer wasn't big enough. Should never happen. */ - dev_err(printdev(devrec), "Buffer not big enough. Performing short read\n"); - rx_len = *len; - } - - /* Set up the commands to read the data. */ - cmd = MRF24J40_READLONG(REG_RX_FIFO+1); - addr[0] = cmd >> 8 & 0xff; - addr[1] = cmd & 0xff; - data_xfer.len = rx_len; - - spi_message_init(&msg); - spi_message_add_tail(&addr_xfer, &msg); - spi_message_add_tail(&data_xfer, &msg); - spi_message_add_tail(&status_xfer, &msg); - - ret = spi_sync(devrec->spi, &msg); - if (ret) { - dev_err(printdev(devrec), "SPI RX Buffer Read Failed.\n"); - goto out; - } - - *lqi = lqi_rssi[0]; - *len = rx_len; - -#ifdef DEBUG - print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ", - DUMP_PREFIX_OFFSET, 16, 1, data, *len, 0); - pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n", - lqi_rssi[0], lqi_rssi[1]); -#endif - -out: - return ret; -} - static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level) { /* TODO: */ @@ -823,53 +708,98 @@ static int mrf24j40_filter(struct ieee802154_hw *hw, return 0; } -static int mrf24j40_handle_rx(struct mrf24j40 *devrec) +static void mrf24j40_handle_rx_read_buf_unlock(struct mrf24j40 *devrec) { - u8 len = RX_FIFO_SIZE; - u8 lqi = 0; - u8 val; - int ret = 0; - int ret2; - struct sk_buff *skb; + int ret; - /* Turn off reception of packets off the air. This prevents the - * device from overwriting the buffer while we're reading it. */ - ret = read_short_reg(devrec, REG_BBREG1, &val); + /* Turn back on reception of packets off the air. */ + devrec->rx_msg.complete = NULL; + devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1); + devrec->rx_buf[1] = 0x00; /* CLR RXDECINV */ + ret = spi_async(devrec->spi, &devrec->rx_msg); if (ret) - goto out; - val |= 4; /* SET RXDECINV */ - write_short_reg(devrec, REG_BBREG1, val); + dev_err(printdev(devrec), "failed to unlock rx buffer\n"); +} - skb = dev_alloc_skb(len); +static void mrf24j40_handle_rx_read_buf_complete(void *context) +{ + struct mrf24j40 *devrec = context; + u8 len = devrec->rx_buf[2]; + u8 rx_local_buf[RX_FIFO_SIZE]; + struct sk_buff *skb; + + memcpy(rx_local_buf, devrec->rx_fifo_buf, len); + mrf24j40_handle_rx_read_buf_unlock(devrec); + + skb = dev_alloc_skb(IEEE802154_MTU); if (!skb) { - ret = -ENOMEM; - goto out; + dev_err(printdev(devrec), "failed to allocate skb\n"); + return; } - ret = mrf24j40_read_rx_buf(devrec, skb_put(skb, len), &len, &lqi); - if (ret < 0) { - dev_err(printdev(devrec), "Failure reading RX FIFO\n"); - kfree_skb(skb); - ret = -EINVAL; - goto out; + memcpy(skb_put(skb, len), rx_local_buf, len); + ieee802154_rx_irqsafe(devrec->hw, skb, 0); + +#ifdef DEBUG + print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ", DUMP_PREFIX_OFFSET, 16, 1, + rx_local_buf, len, 0); + pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n", + devrec->rx_lqi_buf[0], devrec->rx_lqi_buf[1]); +#endif +} + +static void mrf24j40_handle_rx_read_buf(void *context) +{ + struct mrf24j40 *devrec = context; + u16 cmd; + int ret; + + /* if length is invalid read the full MTU */ + if (!ieee802154_is_valid_psdu_len(devrec->rx_buf[2])) + devrec->rx_buf[2] = IEEE802154_MTU; + + cmd = MRF24J40_READLONG(REG_RX_FIFO + 1); + devrec->rx_addr_buf[0] = cmd >> 8 & 0xff; + devrec->rx_addr_buf[1] = cmd & 0xff; + devrec->rx_fifo_buf_trx.len = devrec->rx_buf[2]; + ret = spi_async(devrec->spi, &devrec->rx_buf_msg); + if (ret) { + dev_err(printdev(devrec), "failed to read rx buffer\n"); + mrf24j40_handle_rx_read_buf_unlock(devrec); } +} - /* TODO: Other drivers call ieee20154_rx_irqsafe() here (eg: cc2040, - * also from a workqueue). I think irqsafe is not necessary here. - * Can someone confirm? */ - ieee802154_rx_irqsafe(devrec->hw, skb, lqi); +static void mrf24j40_handle_rx_read_len(void *context) +{ + struct mrf24j40 *devrec = context; + u16 cmd; + int ret; - dev_dbg(printdev(devrec), "RX Handled\n"); + /* read the length of received frame */ + devrec->rx_msg.complete = mrf24j40_handle_rx_read_buf; + devrec->rx_trx.len = 3; + cmd = MRF24J40_READLONG(REG_RX_FIFO); + devrec->rx_buf[0] = cmd >> 8 & 0xff; + devrec->rx_buf[1] = cmd & 0xff; -out: - /* Turn back on reception of packets off the air. */ - ret2 = read_short_reg(devrec, REG_BBREG1, &val); - if (ret2) - return ret2; - val &= ~0x4; /* Clear RXDECINV */ - write_short_reg(devrec, REG_BBREG1, val); + ret = spi_async(devrec->spi, &devrec->rx_msg); + if (ret) { + dev_err(printdev(devrec), "failed to read rx buffer length\n"); + mrf24j40_handle_rx_read_buf_unlock(devrec); + } +} - return ret; +static int mrf24j40_handle_rx(struct mrf24j40 *devrec) +{ + /* Turn off reception of packets off the air. This prevents the + * device from overwriting the buffer while we're reading it. + */ + devrec->rx_msg.complete = mrf24j40_handle_rx_read_len; + devrec->rx_trx.len = 2; + devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1); + devrec->rx_buf[1] = 0x04; /* SET RXDECINV */ + + return spi_async(devrec->spi, &devrec->rx_msg); } static const struct ieee802154_ops mrf24j40_ops = { @@ -1025,6 +955,29 @@ mrf24j40_setup_tx_spi_messages(struct mrf24j40 *devrec) spi_message_add_tail(&devrec->tx_post_trx, &devrec->tx_post_msg); } +static void +mrf24j40_setup_rx_spi_messages(struct mrf24j40 *devrec) +{ + spi_message_init(&devrec->rx_msg); + devrec->rx_msg.context = devrec; + devrec->rx_trx.len = 2; + devrec->rx_trx.tx_buf = devrec->rx_buf; + devrec->rx_trx.rx_buf = devrec->rx_buf; + spi_message_add_tail(&devrec->rx_trx, &devrec->rx_msg); + + spi_message_init(&devrec->rx_buf_msg); + devrec->rx_buf_msg.context = devrec; + devrec->rx_buf_msg.complete = mrf24j40_handle_rx_read_buf_complete; + devrec->rx_addr_trx.len = 2; + devrec->rx_addr_trx.tx_buf = devrec->rx_addr_buf; + spi_message_add_tail(&devrec->rx_addr_trx, &devrec->rx_buf_msg); + devrec->rx_fifo_buf_trx.rx_buf = devrec->rx_fifo_buf; + spi_message_add_tail(&devrec->rx_fifo_buf_trx, &devrec->rx_buf_msg); + devrec->rx_lqi_trx.len = 2; + devrec->rx_lqi_trx.rx_buf = devrec->rx_lqi_buf; + spi_message_add_tail(&devrec->rx_lqi_trx, &devrec->rx_buf_msg); +} + static void mrf24j40_phy_setup(struct mrf24j40 *devrec) { ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr); @@ -1054,6 +1007,7 @@ static int mrf24j40_probe(struct spi_device *spi) devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT; mrf24j40_setup_tx_spi_messages(devrec); + mrf24j40_setup_rx_spi_messages(devrec); devrec->regmap_short = devm_regmap_init_spi(spi, &mrf24j40_short_regmap); -- cgit v1.2.3 From 374416112bb0f83c5b4d8bb3fbb157fbe0b2814b Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:36 +0200 Subject: mrf24j40: async interrupt handling This patch removes the threaded irq handling and do a hardirq instead. We need to switch to spi_async for this step for getting the irq status register. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 93 +++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 53 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 0cb251efdc0e..940fc0ad6bc1 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -181,8 +181,10 @@ struct mrf24j40 { u8 rx_fifo_buf[RX_FIFO_SIZE]; struct spi_transfer rx_fifo_buf_trx; - struct mutex buffer_mutex; /* only used to protect buf */ - u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */ + /* isr handling for reading intstat */ + struct spi_message irq_msg; + u8 irq_buf[2]; + struct spi_transfer irq_trx; }; /* regmap information for short address register access */ @@ -486,34 +488,6 @@ static const struct regmap_bus mrf24j40_long_regmap_bus = { .val_format_endian_default = REGMAP_ENDIAN_BIG, }; -static int read_short_reg(struct mrf24j40 *devrec, u8 reg, u8 *val) -{ - int ret = -1; - struct spi_message msg; - struct spi_transfer xfer = { - .len = 2, - .tx_buf = devrec->buf, - .rx_buf = devrec->buf, - }; - - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - - mutex_lock(&devrec->buffer_mutex); - devrec->buf[0] = MRF24J40_READSHORT(reg); - devrec->buf[1] = 0; - - ret = spi_sync(devrec->spi, &msg); - if (ret) - dev_err(printdev(devrec), - "SPI read Failed for short register 0x%hhx\n", reg); - else - *val = devrec->buf[1]; - - mutex_unlock(&devrec->buffer_mutex); - return ret; -} - static void write_tx_buf_complete(void *context) { struct mrf24j40 *devrec = context; @@ -812,16 +786,12 @@ static const struct ieee802154_ops mrf24j40_ops = { .set_hw_addr_filt = mrf24j40_filter, }; -static irqreturn_t mrf24j40_isr(int irq, void *data) +static void mrf24j40_intstat_complete(void *context) { - struct mrf24j40 *devrec = data; - u8 intstat; - int ret; + struct mrf24j40 *devrec = context; + u8 intstat = devrec->irq_buf[1]; - /* Read the interrupt status */ - ret = read_short_reg(devrec, REG_INTSTAT, &intstat); - if (ret) - goto out; + enable_irq(devrec->spi->irq); /* Check for TX complete */ if (intstat & 0x1) @@ -830,8 +800,23 @@ static irqreturn_t mrf24j40_isr(int irq, void *data) /* Check for Rx */ if (intstat & 0x8) mrf24j40_handle_rx(devrec); +} + +static irqreturn_t mrf24j40_isr(int irq, void *data) +{ + struct mrf24j40 *devrec = data; + int ret; + + disable_irq_nosync(irq); + + devrec->irq_buf[0] = MRF24J40_READSHORT(REG_INTSTAT); + /* Read the interrupt status */ + ret = spi_async(devrec->spi, &devrec->irq_msg); + if (ret) { + enable_irq(irq); + return IRQ_NONE; + } -out: return IRQ_HANDLED; } @@ -978,6 +963,18 @@ mrf24j40_setup_rx_spi_messages(struct mrf24j40 *devrec) spi_message_add_tail(&devrec->rx_lqi_trx, &devrec->rx_buf_msg); } +static void +mrf24j40_setup_irq_spi_messages(struct mrf24j40 *devrec) +{ + spi_message_init(&devrec->irq_msg); + devrec->irq_msg.context = devrec; + devrec->irq_msg.complete = mrf24j40_intstat_complete; + devrec->irq_trx.len = 2; + devrec->irq_trx.tx_buf = devrec->irq_buf; + devrec->irq_trx.rx_buf = devrec->irq_buf; + spi_message_add_tail(&devrec->irq_trx, &devrec->irq_msg); +} + static void mrf24j40_phy_setup(struct mrf24j40 *devrec) { ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr); @@ -1008,6 +1005,7 @@ static int mrf24j40_probe(struct spi_device *spi) mrf24j40_setup_tx_spi_messages(devrec); mrf24j40_setup_rx_spi_messages(devrec); + mrf24j40_setup_irq_spi_messages(devrec); devrec->regmap_short = devm_regmap_init_spi(spi, &mrf24j40_short_regmap); @@ -1028,32 +1026,21 @@ static int mrf24j40_probe(struct spi_device *spi) goto err_register_device; } - devrec->buf = devm_kzalloc(&spi->dev, 3, GFP_KERNEL); - if (!devrec->buf) - goto err_register_device; - if (spi->max_speed_hz > MAX_SPI_SPEED_HZ) { dev_warn(&spi->dev, "spi clock above possible maximum: %d", MAX_SPI_SPEED_HZ); return -EINVAL; } - mutex_init(&devrec->buffer_mutex); - ret = mrf24j40_hw_init(devrec); if (ret) goto err_register_device; mrf24j40_phy_setup(devrec); - ret = devm_request_threaded_irq(&spi->dev, - spi->irq, - NULL, - mrf24j40_isr, - IRQF_TRIGGER_LOW|IRQF_ONESHOT, - dev_name(&spi->dev), - devrec); - + ret = devm_request_irq(&spi->dev, spi->irq, mrf24j40_isr, + IRQF_TRIGGER_LOW, dev_name(&spi->dev), + devrec); if (ret) { dev_err(printdev(devrec), "Unable to get IRQ"); goto err_register_device; -- cgit v1.2.3 From 2323cf38f949439bc4ac4252cf1d91d1297cce92 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:37 +0200 Subject: mrf24j40: add csma params support This patch adds supports to change the CSMA parameters. The datasheet doesn't say anything about max_be value. Seems not configurable and we assume the 802.15.4 default. But this value must exists because there is a min_be value. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 940fc0ad6bc1..fe7991d3b428 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -776,6 +776,21 @@ static int mrf24j40_handle_rx(struct mrf24j40 *devrec) return spi_async(devrec->spi, &devrec->rx_msg); } +static int +mrf24j40_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be, + u8 retries) +{ + struct mrf24j40 *devrec = hw->priv; + u8 val; + + /* min_be */ + val = min_be << 3; + /* csma backoffs */ + val |= retries; + + return regmap_update_bits(devrec->regmap_short, REG_TXMCR, 0x1f, val); +} + static const struct ieee802154_ops mrf24j40_ops = { .owner = THIS_MODULE, .xmit_async = mrf24j40_tx, @@ -784,6 +799,7 @@ static const struct ieee802154_ops mrf24j40_ops = { .stop = mrf24j40_stop, .set_channel = mrf24j40_set_channel, .set_hw_addr_filt = mrf24j40_filter, + .set_csma_params = mrf24j40_csma_params, }; static void mrf24j40_intstat_complete(void *context) @@ -979,6 +995,14 @@ static void mrf24j40_phy_setup(struct mrf24j40 *devrec) { ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr); devrec->hw->phy->current_channel = 11; + + /* mrf24j40 supports max_minbe 0 - 3 */ + devrec->hw->phy->supported.max_minbe = 3; + /* datasheet doesn't say anything about max_be, but we have min_be + * So we assume the max_be default. + */ + devrec->hw->phy->supported.min_maxbe = 5; + devrec->hw->phy->supported.max_maxbe = 5; } static int mrf24j40_probe(struct spi_device *spi) @@ -1001,7 +1025,8 @@ static int mrf24j40_probe(struct spi_device *spi) devrec->hw = hw; devrec->hw->parent = &spi->dev; devrec->hw->phy->supported.channels[0] = CHANNEL_MASK; - devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT; + devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT | + IEEE802154_HW_CSMA_PARAMS; mrf24j40_setup_tx_spi_messages(devrec); mrf24j40_setup_rx_spi_messages(devrec); -- cgit v1.2.3 From f1d781272231dc4d1cdfdce13ad3e6f3f96b7ec0 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:38 +0200 Subject: mrf24j40: add cca mode support This patch supports cca mode handling for mrf24j40. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index fe7991d3b428..086eee0ff51c 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -791,6 +791,37 @@ mrf24j40_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be, return regmap_update_bits(devrec->regmap_short, REG_TXMCR, 0x1f, val); } +static int mrf24j40_set_cca_mode(struct ieee802154_hw *hw, + const struct wpan_phy_cca *cca) +{ + struct mrf24j40 *devrec = hw->priv; + u8 val; + + /* mapping 802.15.4 to driver spec */ + switch (cca->mode) { + case NL802154_CCA_ENERGY: + val = 2; + break; + case NL802154_CCA_CARRIER: + val = 1; + break; + case NL802154_CCA_ENERGY_CARRIER: + switch (cca->opt) { + case NL802154_CCA_OPT_ENERGY_CARRIER_AND: + val = 3; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return regmap_update_bits(devrec->regmap_short, REG_BBREG2, 0xc0, + val << 6); +} + static const struct ieee802154_ops mrf24j40_ops = { .owner = THIS_MODULE, .xmit_async = mrf24j40_tx, @@ -800,6 +831,7 @@ static const struct ieee802154_ops mrf24j40_ops = { .set_channel = mrf24j40_set_channel, .set_hw_addr_filt = mrf24j40_filter, .set_csma_params = mrf24j40_csma_params, + .set_cca_mode = mrf24j40_set_cca_mode, }; static void mrf24j40_intstat_complete(void *context) @@ -1003,6 +1035,12 @@ static void mrf24j40_phy_setup(struct mrf24j40 *devrec) */ devrec->hw->phy->supported.min_maxbe = 5; devrec->hw->phy->supported.max_maxbe = 5; + + devrec->hw->phy->cca.mode = NL802154_CCA_CARRIER;; + devrec->hw->phy->supported.cca_modes = BIT(NL802154_CCA_ENERGY) | + BIT(NL802154_CCA_CARRIER) | + BIT(NL802154_CCA_ENERGY_CARRIER); + devrec->hw->phy->supported.cca_opts = BIT(NL802154_CCA_OPT_ENERGY_CARRIER_AND); } static int mrf24j40_probe(struct spi_device *spi) @@ -1028,6 +1066,8 @@ static int mrf24j40_probe(struct spi_device *spi) devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT | IEEE802154_HW_CSMA_PARAMS; + devrec->hw->phy->flags = WPAN_PHY_FLAG_CCA_MODE; + mrf24j40_setup_tx_spi_messages(devrec); mrf24j40_setup_rx_spi_messages(devrec); mrf24j40_setup_irq_spi_messages(devrec); -- cgit v1.2.3 From e33a0f96ac518d4c7ffcf98d2f030e6e23fab6b3 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:39 +0200 Subject: mrf24j40: add cca ed level support This patch supports handling to set the cca energy detection level for the mrf24j40 transceiver. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 50 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 086eee0ff51c..c23936e3dd4f 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -822,6 +822,48 @@ static int mrf24j40_set_cca_mode(struct ieee802154_hw *hw, val << 6); } +/* array for representing ed levels */ +static const s32 mrf24j40_ed_levels[] = { + -9000, -8900, -8800, -8700, -8600, -8500, -8400, -8300, -8200, -8100, + -8000, -7900, -7800, -7700, -7600, -7500, -7400, -7300, -7200, -7100, + -7000, -6900, -6800, -6700, -6600, -6500, -6400, -6300, -6200, -6100, + -6000, -5900, -5800, -5700, -5600, -5500, -5400, -5300, -5200, -5100, + -5000, -4900, -4800, -4700, -4600, -4500, -4400, -4300, -4200, -4100, + -4000, -3900, -3800, -3700, -3600, -3500 +}; + +/* map ed levels to register value */ +static const s32 mrf24j40_ed_levels_map[][2] = { + { -9000, 0 }, { -8900, 1 }, { -8800, 2 }, { -8700, 5 }, { -8600, 9 }, + { -8500, 13 }, { -8400, 18 }, { -8300, 23 }, { -8200, 27 }, + { -8100, 32 }, { -8000, 37 }, { -7900, 43 }, { -7800, 48 }, + { -7700, 53 }, { -7600, 58 }, { -7500, 63 }, { -7400, 68 }, + { -7300, 73 }, { -7200, 78 }, { -7100, 83 }, { -7000, 89 }, + { -6900, 95 }, { -6800, 100 }, { -6700, 107 }, { -6600, 111 }, + { -6500, 117 }, { -6400, 121 }, { -6300, 125 }, { -6200, 129 }, + { -6100, 133 }, { -6000, 138 }, { -5900, 143 }, { -5800, 148 }, + { -5700, 153 }, { -5600, 159 }, { -5500, 165 }, { -5400, 170 }, + { -5300, 176 }, { -5200, 183 }, { -5100, 188 }, { -5000, 193 }, + { -4900, 198 }, { -4800, 203 }, { -4700, 207 }, { -4600, 212 }, + { -4500, 216 }, { -4400, 221 }, { -4300, 225 }, { -4200, 228 }, + { -4100, 233 }, { -4000, 239 }, { -3900, 245 }, { -3800, 250 }, + { -3700, 253 }, { -3600, 254 }, { -3500, 255 }, +}; + +static int mrf24j40_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm) +{ + struct mrf24j40 *devrec = hw->priv; + int i; + + for (i = 0; i < ARRAY_SIZE(mrf24j40_ed_levels_map); i++) { + if (mrf24j40_ed_levels_map[i][0] == mbm) + return regmap_write(devrec->regmap_short, REG_CCAEDTH, + mrf24j40_ed_levels_map[i][1]); + } + + return -EINVAL; +} + static const struct ieee802154_ops mrf24j40_ops = { .owner = THIS_MODULE, .xmit_async = mrf24j40_tx, @@ -832,6 +874,7 @@ static const struct ieee802154_ops mrf24j40_ops = { .set_hw_addr_filt = mrf24j40_filter, .set_csma_params = mrf24j40_csma_params, .set_cca_mode = mrf24j40_set_cca_mode, + .set_cca_ed_level = mrf24j40_set_cca_ed_level, }; static void mrf24j40_intstat_complete(void *context) @@ -1041,6 +1084,10 @@ static void mrf24j40_phy_setup(struct mrf24j40 *devrec) BIT(NL802154_CCA_CARRIER) | BIT(NL802154_CCA_ENERGY_CARRIER); devrec->hw->phy->supported.cca_opts = BIT(NL802154_CCA_OPT_ENERGY_CARRIER_AND); + + devrec->hw->phy->cca_ed_level = -6900; + devrec->hw->phy->supported.cca_ed_levels = mrf24j40_ed_levels; + devrec->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(mrf24j40_ed_levels); } static int mrf24j40_probe(struct spi_device *spi) @@ -1066,7 +1113,8 @@ static int mrf24j40_probe(struct spi_device *spi) devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT | IEEE802154_HW_CSMA_PARAMS; - devrec->hw->phy->flags = WPAN_PHY_FLAG_CCA_MODE; + devrec->hw->phy->flags = WPAN_PHY_FLAG_CCA_MODE | + WPAN_PHY_FLAG_CCA_ED_LEVEL; mrf24j40_setup_tx_spi_messages(devrec); mrf24j40_setup_rx_spi_messages(devrec); -- cgit v1.2.3 From 00250f78896bc52fd4606c4de7e3fb174e702123 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:40 +0200 Subject: mrf24j40: add tx power support This patch supports setting of transmit power for the mrf24j40ma transceiver only. The mrf24j40mc has some amplifier to change the transmit power, I am currently not sure how the mapping for this amplifier looks like. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 71 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index c23936e3dd4f..91687c1a56ce 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -864,6 +864,65 @@ static int mrf24j40_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm) return -EINVAL; } +static const s32 mrf24j40ma_powers[] = { + 0, -50, -120, -190, -280, -370, -490, -630, -1000, -1050, -1120, -1190, + -1280, -1370, -1490, -1630, -2000, -2050, -2120, -2190, -2280, -2370, + -2490, -2630, -3000, -3050, -3120, -3190, -3280, -3370, -3490, -3630, +}; + +static int mrf24j40_set_txpower(struct ieee802154_hw *hw, s32 mbm) +{ + struct mrf24j40 *devrec = hw->priv; + s32 small_scale; + u8 val; + + if (0 >= mbm && mbm > -1000) { + val = 0; + small_scale = mbm; + } else if (-1000 >= mbm && mbm > -2000) { + val = 0x40; + small_scale = mbm + 1000; + } else if (-2000 >= mbm && mbm > -3000) { + val = 0x80; + small_scale = mbm + 2000; + } else if (-3000 >= mbm && mbm > -4000) { + val = 0xc0; + small_scale = mbm + 3000; + } else { + return -EINVAL; + } + + switch (small_scale) { + case 0: + break; + case -50: + val |= 0x08; + break; + case -120: + val |= 0x10; + break; + case -190: + val |= 0x18; + break; + case -280: + val |= 0x20; + break; + case -370: + val |= 0x28; + break; + case -490: + val |= 0x30; + break; + case -630: + val |= 0x38; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(devrec->regmap_long, REG_RFCON3, 0xf8, val); +} + static const struct ieee802154_ops mrf24j40_ops = { .owner = THIS_MODULE, .xmit_async = mrf24j40_tx, @@ -875,6 +934,7 @@ static const struct ieee802154_ops mrf24j40_ops = { .set_csma_params = mrf24j40_csma_params, .set_cca_mode = mrf24j40_set_cca_mode, .set_cca_ed_level = mrf24j40_set_cca_ed_level, + .set_txpower = mrf24j40_set_txpower, }; static void mrf24j40_intstat_complete(void *context) @@ -1088,6 +1148,17 @@ static void mrf24j40_phy_setup(struct mrf24j40 *devrec) devrec->hw->phy->cca_ed_level = -6900; devrec->hw->phy->supported.cca_ed_levels = mrf24j40_ed_levels; devrec->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(mrf24j40_ed_levels); + + switch (spi_get_device_id(devrec->spi)->driver_data) { + case MRF24J40: + case MRF24J40MA: + devrec->hw->phy->supported.tx_powers = mrf24j40ma_powers; + devrec->hw->phy->supported.tx_powers_size = ARRAY_SIZE(mrf24j40ma_powers); + devrec->hw->phy->flags |= WPAN_PHY_FLAG_TXPOWER; + break; + default: + break; + } } static int mrf24j40_probe(struct spi_device *spi) -- cgit v1.2.3 From 8ba40417401ce771769d847900f08c978bb61632 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:41 +0200 Subject: mrf24j40: add promiscuous mode support This patch adds support for promiscuous mode by setting promiscuous (no frame filtering), disable automatic ack handling and not filtering frames where the crc is invalid. Reviewed-by: Stefan Schmidt Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 91687c1a56ce..146ad57165ea 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -923,6 +923,24 @@ static int mrf24j40_set_txpower(struct ieee802154_hw *hw, s32 mbm) return regmap_update_bits(devrec->regmap_long, REG_RFCON3, 0xf8, val); } +static int mrf24j40_set_promiscuous_mode(struct ieee802154_hw *hw, bool on) +{ + struct mrf24j40 *devrec = hw->priv; + int ret; + + if (on) { + /* set PROMI, ERRPKT and NOACKRSP */ + ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x23, + 0x23); + } else { + /* clear PROMI, ERRPKT and NOACKRSP */ + ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x23, + 0x00); + } + + return ret; +} + static const struct ieee802154_ops mrf24j40_ops = { .owner = THIS_MODULE, .xmit_async = mrf24j40_tx, @@ -935,6 +953,7 @@ static const struct ieee802154_ops mrf24j40_ops = { .set_cca_mode = mrf24j40_set_cca_mode, .set_cca_ed_level = mrf24j40_set_cca_ed_level, .set_txpower = mrf24j40_set_txpower, + .set_promiscuous_mode = mrf24j40_set_promiscuous_mode, }; static void mrf24j40_intstat_complete(void *context) @@ -1182,7 +1201,8 @@ static int mrf24j40_probe(struct spi_device *spi) devrec->hw->parent = &spi->dev; devrec->hw->phy->supported.channels[0] = CHANNEL_MASK; devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT | - IEEE802154_HW_CSMA_PARAMS; + IEEE802154_HW_CSMA_PARAMS | + IEEE802154_HW_PROMISCUOUS; devrec->hw->phy->flags = WPAN_PHY_FLAG_CCA_MODE | WPAN_PHY_FLAG_CCA_ED_LEVEL; -- cgit v1.2.3 From afaf7fdedb6cc484b4eccf48227632c7d81dcf5a Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:42 +0200 Subject: mrf24j40: change irq trigger type behaviour This patch changes the irq trigger type value while calling devm_request_irq by using IRQF_TRIGGER_LOW when no irq type was given. Additional we add support for change the irq polarity while hw init if high level or low level triggered irq type are given. For rising edge triggered irq's the mrf24j40 can't deal with that, this races at position of tx completion irq, while the irq is disabled we readout the irq status registers. This will resets the irq line so other irq's can occur. Wile readout the irq status register the irq is still disabled and edge triggered interrupts will be ignored. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 146ad57165ea..9a8d517d0121 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -992,6 +993,7 @@ static irqreturn_t mrf24j40_isr(int irq, void *data) static int mrf24j40_hw_init(struct mrf24j40 *devrec) { + u32 irq_type; int ret; /* Initialize the device. @@ -1083,6 +1085,25 @@ static int mrf24j40_hw_init(struct mrf24j40 *devrec) regmap_write(devrec->regmap_long, REG_RFCON3, 0x28); } + irq_type = irq_get_trigger_type(devrec->spi->irq); + if (irq_type == IRQ_TYPE_EDGE_RISING || + irq_type == IRQ_TYPE_EDGE_FALLING) + dev_warn(&devrec->spi->dev, + "Using edge triggered irq's are not recommended, because it can cause races and result in a non-functional driver!\n"); + switch (irq_type) { + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_LEVEL_HIGH: + /* set interrupt polarity to rising */ + ret = regmap_update_bits(devrec->regmap_long, REG_SLPCON0, + 0x02, 0x02); + if (ret) + goto err_ret; + break; + default: + /* default is falling edge */ + break; + } + return 0; err_ret: @@ -1182,7 +1203,7 @@ static void mrf24j40_phy_setup(struct mrf24j40 *devrec) static int mrf24j40_probe(struct spi_device *spi) { - int ret = -ENOMEM; + int ret = -ENOMEM, irq_type; struct ieee802154_hw *hw; struct mrf24j40 *devrec; @@ -1242,9 +1263,13 @@ static int mrf24j40_probe(struct spi_device *spi) mrf24j40_phy_setup(devrec); + /* request IRQF_TRIGGER_LOW as fallback default */ + irq_type = irq_get_trigger_type(spi->irq); + if (!irq_type) + irq_type = IRQF_TRIGGER_LOW; + ret = devm_request_irq(&spi->dev, spi->irq, mrf24j40_isr, - IRQF_TRIGGER_LOW, dev_name(&spi->dev), - devrec); + irq_type, dev_name(&spi->dev), devrec); if (ret) { dev_err(printdev(devrec), "Unable to get IRQ"); goto err_register_device; -- cgit v1.2.3 From 7d840545e5b933028e7423b127459d0d5e5e04fb Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Mon, 21 Sep 2015 11:24:43 +0200 Subject: mrf24j40: replace magic numbers This patch replaces some magic numbers with defines for register bits, mask and shifts. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 136 +++++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 38 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 9a8d517d0121..2770df11f883 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -26,6 +26,11 @@ /* MRF24J40 Short Address Registers */ #define REG_RXMCR 0x00 /* Receive MAC control */ +#define BIT_PROMI BIT(0) +#define BIT_ERRPKT BIT(1) +#define BIT_NOACKRSP BIT(5) +#define BIT_PANCOORD BIT(3) + #define REG_PANIDL 0x01 /* PAN ID (low) */ #define REG_PANIDH 0x02 /* PAN ID (high) */ #define REG_SADRL 0x03 /* Short address (low) */ @@ -41,6 +46,11 @@ #define REG_RXFLUSH 0x0D #define REG_ORDER 0x10 #define REG_TXMCR 0x11 /* Transmit MAC control */ +#define TXMCR_MIN_BE_SHIFT 3 +#define TXMCR_MIN_BE_MASK 0x18 +#define TXMCR_CSMA_RETRIES_SHIFT 0 +#define TXMCR_CSMA_RETRIES_MASK 0x07 + #define REG_ACKTMOUT 0x12 #define REG_ESLOTG1 0x13 #define REG_SYMTICKL 0x14 @@ -50,6 +60,9 @@ #define REG_PACON2 0x18 /* Power Amplifier Control */ #define REG_TXBCON0 0x1A #define REG_TXNCON 0x1B /* Transmit Normal FIFO Control */ +#define BIT_TXNTRIG BIT(0) +#define BIT_TXNACKREQ BIT(2) + #define REG_TXG1CON 0x1C #define REG_TXG2CON 0x1D #define REG_ESLOTG23 0x1E @@ -70,15 +83,28 @@ #define REG_TXSTBL 0x2E /* TX Stabilization */ #define REG_RXSR 0x30 #define REG_INTSTAT 0x31 /* Interrupt Status */ +#define BIT_TXNIF BIT(0) +#define BIT_RXIF BIT(3) + #define REG_INTCON 0x32 /* Interrupt Control */ +#define BIT_TXNIE BIT(0) +#define BIT_RXIE BIT(3) + #define REG_GPIO 0x33 /* GPIO */ #define REG_TRISGPIO 0x34 /* GPIO direction */ #define REG_SLPACK 0x35 #define REG_RFCTL 0x36 /* RF Control Mode Register */ +#define BIT_RFRST BIT(2) + #define REG_SECCR2 0x37 #define REG_BBREG0 0x38 #define REG_BBREG1 0x39 /* Baseband Registers */ +#define BIT_RXDECINV BIT(2) + #define REG_BBREG2 0x3A /* */ +#define BBREG2_CCA_MODE_SHIFT 6 +#define BBREG2_CCA_MODE_MASK 0xc0 + #define REG_BBREG3 0x3B #define REG_BBREG4 0x3C #define REG_BBREG6 0x3E /* */ @@ -86,9 +112,32 @@ /* MRF24J40 Long Address Registers */ #define REG_RFCON0 0x200 /* RF Control Registers */ +#define RFCON0_CH_SHIFT 4 +#define RFCON0_CH_MASK 0xf0 +#define RFOPT_RECOMMEND 3 + #define REG_RFCON1 0x201 #define REG_RFCON2 0x202 #define REG_RFCON3 0x203 + +#define TXPWRL_MASK 0xc0 +#define TXPWRL_SHIFT 6 +#define TXPWRL_30 0x3 +#define TXPWRL_20 0x2 +#define TXPWRL_10 0x1 +#define TXPWRL_0 0x0 + +#define TXPWRS_MASK 0x38 +#define TXPWRS_SHIFT 3 +#define TXPWRS_6_3 0x7 +#define TXPWRS_4_9 0x6 +#define TXPWRS_3_7 0x5 +#define TXPWRS_2_8 0x4 +#define TXPWRS_1_9 0x3 +#define TXPWRS_1_2 0x2 +#define TXPWRS_0_5 0x1 +#define TXPWRS_0 0x0 + #define REG_RFCON5 0x205 #define REG_RFCON6 0x206 #define REG_RFCON7 0x207 @@ -99,6 +148,8 @@ #define REG_RFSTATE 0x20F #define REG_RSSI 0x210 #define REG_SLPCON0 0x211 /* Sleep Clock Control Registers */ +#define BIT_INTEDGE BIT(1) + #define REG_SLPCON1 0x220 #define REG_WAKETIMEL 0x222 /* Wake-up Time Match Value Low */ #define REG_WAKETIMEH 0x223 /* Wake-up Time Match Value High */ @@ -493,11 +544,11 @@ static void write_tx_buf_complete(void *context) { struct mrf24j40 *devrec = context; __le16 fc = ieee802154_get_fc_from_skb(devrec->tx_skb); - u8 val = 0x01; + u8 val = BIT_TXNTRIG; int ret; if (ieee802154_is_ackreq(fc)) - val |= 0x04; + val |= BIT_TXNACKREQ; devrec->tx_post_msg.complete = NULL; devrec->tx_post_buf[0] = MRF24J40_WRITESHORT(REG_TXNCON); @@ -564,7 +615,7 @@ static int mrf24j40_start(struct ieee802154_hw *hw) /* Clear TXNIE and RXIE. Enable interrupts */ return regmap_update_bits(devrec->regmap_short, REG_INTCON, - 0x01 | 0x08, 0x00); + BIT_TXNIE | BIT_RXIE, 0); } static void mrf24j40_stop(struct ieee802154_hw *hw) @@ -574,8 +625,8 @@ static void mrf24j40_stop(struct ieee802154_hw *hw) dev_dbg(printdev(devrec), "stop\n"); /* Set TXNIE and RXIE. Disable Interrupts */ - regmap_update_bits(devrec->regmap_short, REG_INTCON, 0x01 | 0x08, - 0x01 | 0x08); + regmap_update_bits(devrec->regmap_short, REG_INTCON, + BIT_TXNIE | BIT_TXNIE, BIT_TXNIE | BIT_TXNIE); } static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel) @@ -591,17 +642,19 @@ static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel) WARN_ON(channel > MRF24J40_CHAN_MAX); /* Set Channel TODO */ - val = (channel-11) << 4 | 0x03; - ret = regmap_update_bits(devrec->regmap_long, REG_RFCON0, 0xf0, val); + val = (channel - 11) << RFCON0_CH_SHIFT | RFOPT_RECOMMEND; + ret = regmap_update_bits(devrec->regmap_long, REG_RFCON0, + RFCON0_CH_MASK, val); if (ret) return ret; /* RF Reset */ - ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, 0x04, 0x04); + ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, BIT_RFRST, + BIT_RFRST); if (ret) return ret; - ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, 0x04, 0x00); + ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, BIT_RFRST, 0); if (!ret) udelay(SET_CHANNEL_DELAY_US); /* per datasheet */ @@ -664,11 +717,11 @@ static int mrf24j40_filter(struct ieee802154_hw *hw, int ret; if (filt->pan_coord) - val = 0x8; + val = BIT_PANCOORD; else - val = 0x0; - ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x8, - val); + val = 0; + ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, + BIT_PANCOORD, val); if (ret) return ret; @@ -772,7 +825,7 @@ static int mrf24j40_handle_rx(struct mrf24j40 *devrec) devrec->rx_msg.complete = mrf24j40_handle_rx_read_len; devrec->rx_trx.len = 2; devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1); - devrec->rx_buf[1] = 0x04; /* SET RXDECINV */ + devrec->rx_buf[1] = BIT_RXDECINV; /* SET RXDECINV */ return spi_async(devrec->spi, &devrec->rx_msg); } @@ -785,11 +838,13 @@ mrf24j40_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be, u8 val; /* min_be */ - val = min_be << 3; + val = min_be << TXMCR_MIN_BE_SHIFT; /* csma backoffs */ - val |= retries; + val |= retries << TXMCR_CSMA_RETRIES_SHIFT; - return regmap_update_bits(devrec->regmap_short, REG_TXMCR, 0x1f, val); + return regmap_update_bits(devrec->regmap_short, REG_TXMCR, + TXMCR_MIN_BE_MASK | TXMCR_CSMA_RETRIES_MASK, + val); } static int mrf24j40_set_cca_mode(struct ieee802154_hw *hw, @@ -819,8 +874,9 @@ static int mrf24j40_set_cca_mode(struct ieee802154_hw *hw, return -EINVAL; } - return regmap_update_bits(devrec->regmap_short, REG_BBREG2, 0xc0, - val << 6); + return regmap_update_bits(devrec->regmap_short, REG_BBREG2, + BBREG2_CCA_MODE_MASK, + val << BBREG2_CCA_MODE_SHIFT); } /* array for representing ed levels */ @@ -878,16 +934,16 @@ static int mrf24j40_set_txpower(struct ieee802154_hw *hw, s32 mbm) u8 val; if (0 >= mbm && mbm > -1000) { - val = 0; + val = TXPWRL_0 << TXPWRL_SHIFT; small_scale = mbm; } else if (-1000 >= mbm && mbm > -2000) { - val = 0x40; + val = TXPWRL_10 << TXPWRL_SHIFT; small_scale = mbm + 1000; } else if (-2000 >= mbm && mbm > -3000) { - val = 0x80; + val = TXPWRL_20 << TXPWRL_SHIFT; small_scale = mbm + 2000; } else if (-3000 >= mbm && mbm > -4000) { - val = 0xc0; + val = TXPWRL_30 << TXPWRL_SHIFT; small_scale = mbm + 3000; } else { return -EINVAL; @@ -895,33 +951,35 @@ static int mrf24j40_set_txpower(struct ieee802154_hw *hw, s32 mbm) switch (small_scale) { case 0: + val |= (TXPWRS_0 << TXPWRS_SHIFT); break; case -50: - val |= 0x08; + val |= (TXPWRS_0_5 << TXPWRS_SHIFT); break; case -120: - val |= 0x10; + val |= (TXPWRS_1_2 << TXPWRS_SHIFT); break; case -190: - val |= 0x18; + val |= (TXPWRS_1_9 << TXPWRS_SHIFT); break; case -280: - val |= 0x20; + val |= (TXPWRS_2_8 << TXPWRS_SHIFT); break; case -370: - val |= 0x28; + val |= (TXPWRS_3_7 << TXPWRS_SHIFT); break; case -490: - val |= 0x30; + val |= (TXPWRS_4_9 << TXPWRS_SHIFT); break; case -630: - val |= 0x38; + val |= (TXPWRS_6_3 << TXPWRS_SHIFT); break; default: return -EINVAL; } - return regmap_update_bits(devrec->regmap_long, REG_RFCON3, 0xf8, val); + return regmap_update_bits(devrec->regmap_long, REG_RFCON3, + TXPWRL_MASK | TXPWRS_MASK, val); } static int mrf24j40_set_promiscuous_mode(struct ieee802154_hw *hw, bool on) @@ -931,12 +989,14 @@ static int mrf24j40_set_promiscuous_mode(struct ieee802154_hw *hw, bool on) if (on) { /* set PROMI, ERRPKT and NOACKRSP */ - ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x23, - 0x23); + ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, + BIT_PROMI | BIT_ERRPKT | BIT_NOACKRSP, + BIT_PROMI | BIT_ERRPKT | BIT_NOACKRSP); } else { /* clear PROMI, ERRPKT and NOACKRSP */ - ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x23, - 0x00); + ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, + BIT_PROMI | BIT_ERRPKT | BIT_NOACKRSP, + 0); } return ret; @@ -965,11 +1025,11 @@ static void mrf24j40_intstat_complete(void *context) enable_irq(devrec->spi->irq); /* Check for TX complete */ - if (intstat & 0x1) + if (intstat & BIT_TXNIF) ieee802154_xmit_complete(devrec->hw, devrec->tx_skb, false); /* Check for Rx */ - if (intstat & 0x8) + if (intstat & BIT_RXIF) mrf24j40_handle_rx(devrec); } @@ -1095,7 +1155,7 @@ static int mrf24j40_hw_init(struct mrf24j40 *devrec) case IRQ_TYPE_LEVEL_HIGH: /* set interrupt polarity to rising */ ret = regmap_update_bits(devrec->regmap_long, REG_SLPCON0, - 0x02, 0x02); + BIT_INTEDGE, BIT_INTEDGE); if (ret) goto err_ret; break; -- cgit v1.2.3 From e3abc8ff0fc18b3925fd5d5c5fbd1613856f4e7c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 16 Aug 2015 11:13:22 +0300 Subject: mac80211: allow to transmit A-MSDU within A-MPDU Advertise the capability to send A-MSDU within A-MPDU in the AddBA request sent by mac80211. Let the driver know about the peer's capabilities. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath10k/mac.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 2 +- drivers/net/wireless/ath/ath9k/main.c | 2 +- drivers/net/wireless/ath/carl9170/main.c | 2 +- drivers/net/wireless/ath/wcn36xx/main.c | 2 +- drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 2 +- drivers/net/wireless/cw1200/sta.c | 2 +- drivers/net/wireless/cw1200/sta.h | 2 +- drivers/net/wireless/iwlegacy/4965-mac.c | 2 +- drivers/net/wireless/iwlegacy/4965.h | 2 +- drivers/net/wireless/iwlwifi/dvm/mac80211.c | 2 +- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 2 +- drivers/net/wireless/mac80211_hwsim.c | 2 +- drivers/net/wireless/mediatek/mt7601u/main.c | 3 ++- drivers/net/wireless/mwl8k.c | 2 +- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 4 +++- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- drivers/net/wireless/rt2x00/rt2800lib.h | 2 +- drivers/net/wireless/rtlwifi/core.c | 2 +- drivers/net/wireless/ti/wlcore/main.c | 2 +- 20 files changed, 23 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 64674c955d44..b04e7694c105 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6144,7 +6144,7 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 172a9ff4aaab..a680a970b7f7 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1659,7 +1659,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size) + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) { struct ath9k_htc_priv *priv = hw->priv; struct ath9k_htc_sta *ista; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c27143ba9ffb..323eb33c3c6e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1856,7 +1856,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size) + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 170c209f99b8..19d3d64416bf 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1415,7 +1415,7 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size) + u16 tid, u16 *ssn, u8 buf_size, bool amsdu) { struct ar9170 *ar = hw->priv; struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 900e72a089d8..7c169abdbafe 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -859,7 +859,7 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct wcn36xx *wcn = hw->priv; struct wcn36xx_sta *sta_priv = NULL; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index d2c5747e3ac9..bec2dc1ca2e4 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -820,7 +820,7 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct brcms_info *wl = hw->priv; struct scb *scb = &wl->wlc->pri_scb; diff --git a/drivers/net/wireless/cw1200/sta.c b/drivers/net/wireless/cw1200/sta.c index b86500b4418f..95a7fdb3cc1c 100644 --- a/drivers/net/wireless/cw1200/sta.c +++ b/drivers/net/wireless/cw1200/sta.c @@ -2137,7 +2137,7 @@ int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { /* Aggregation is implemented fully in firmware, * including block ack negotiation. Do not allow diff --git a/drivers/net/wireless/cw1200/sta.h b/drivers/net/wireless/cw1200/sta.h index b7e386b7662b..bebb3379017f 100644 --- a/drivers/net/wireless/cw1200/sta.h +++ b/drivers/net/wireless/cw1200/sta.h @@ -111,7 +111,7 @@ int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size); + u8 buf_size, bool amsdu); void cw1200_suspend_resume(struct cw1200_common *priv, struct wsm_suspend_resume *arg); diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 44fa422f255e..6656215a13a9 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -5984,7 +5984,7 @@ int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 * ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct il_priv *il = hw->priv; int ret = -EINVAL; diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h index 3a57f71b8ed5..8ab8706f9422 100644 --- a/drivers/net/wireless/iwlegacy/4965.h +++ b/drivers/net/wireless/iwlegacy/4965.h @@ -184,7 +184,7 @@ void il4965_mac_update_tkip_key(struct ieee80211_hw *hw, int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 * ssn, - u8 buf_size); + u8 buf_size, bool amsdu); int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 453f7c315ab5..b3ad34e8bf5a 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -731,7 +731,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); int ret = -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index aa8c2b7f23c7..f70452c41d63 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -820,7 +820,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size) + u16 *ssn, u8 buf_size, bool amsdu) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); int ret; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 520bef80747f..2af2f3d0cc31 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1819,7 +1819,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { switch (action) { case IEEE80211_AMPDU_TX_START: diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c index 169384b48b27..f715eee39851 100644 --- a/drivers/net/wireless/mediatek/mt7601u/main.c +++ b/drivers/net/wireless/mediatek/mt7601u/main.c @@ -335,7 +335,8 @@ static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value) static int mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) + struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, + bool amsdu) { struct mt7601u_dev *dev = hw->priv; struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9420fc61c2e6..30e3aaae32e2 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -5423,7 +5423,7 @@ static int mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { int i, rc = 0; diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 7e804324bfa7..b5bcc933a2a6 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -664,6 +664,7 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw, * @tid: Traffic identifier. * @ssn: Pointer to ssn value. * @buf_size: Buffer size (for kernel version > 2.6.38). + * @amsdu: is AMSDU in AMPDU allowed * * Return: status: 0 on success, negative error code on failure. */ @@ -673,7 +674,8 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_sta *sta, unsigned short tid, unsigned short *ssn, - unsigned char buf_size) + unsigned char buf_size, + bool amsdu) { int status = -EOPNOTSUPP; struct rsi_hw *adapter = hw->priv; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 9524564f873b..9733b31a780d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -7937,7 +7937,7 @@ EXPORT_SYMBOL_GPL(rt2800_get_tsf); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv; int ret = 0; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 1609b8a7f7eb..440790b92b19 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -220,7 +220,7 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size); + u8 buf_size, bool amsdu); int rt2800_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 585d0883c7e5..c925a4dff599 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -1373,7 +1373,7 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct rtl_priv *rtlpriv = rtl_priv(hw); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index e819369d8f8f..ec7f6af3fab2 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5263,7 +5263,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum ieee80211_ampdu_mlme_action action, struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size) + u8 buf_size, bool amsdu) { struct wl1271 *wl = hw->priv; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); -- cgit v1.2.3 From 0edd5faeb07bfd3ec5402f9467e4c169dcd131e8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 28 Aug 2015 14:31:48 +0200 Subject: wireless: mark element IDs 8 and 9 reserved These were never used in the tree, and are marked as reserved in the IEEE 802.11 documentation (ANA). Signed-off-by: Johannes Berg --- drivers/net/wireless/ipw2x00/libipw_rx.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index a6877dd6ba73..cef7f7d79cd9 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -1091,8 +1091,6 @@ static const char *get_info_element_string(u16 id) MFIE_STRING(TIM); MFIE_STRING(IBSS_PARAMS); MFIE_STRING(COUNTRY); - MFIE_STRING(HP_PARAMS); - MFIE_STRING(HP_TABLE); MFIE_STRING(REQUEST); MFIE_STRING(CHALLENGE); MFIE_STRING(PWR_CONSTRAINT); -- cgit v1.2.3 From 8427672abdc9e405f86755fad5a035511a5b1534 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 15 Jun 2015 15:00:52 -0700 Subject: fm10k: remove comment about rtnl_lock around mbx operations This comment is no longer true due to a couple of mailbox locking refactors, and we now don't actually do any rtnl protected operations directly in the mailbox path. Remove this comment as it is factually incorrect and confusing. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index 3d71c5206110..dfefd06447e5 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -274,8 +274,6 @@ static void fm10k_watchdog_update_host_state(struct fm10k_intfc *interface) * @interface: board private structure * * This function will process both the upstream and downstream mailboxes. - * It is necessary for us to hold the rtnl_lock while doing this as the - * mailbox accesses are protected by this lock. **/ static void fm10k_mbx_subtask(struct fm10k_intfc *interface) { @@ -498,7 +496,7 @@ static void fm10k_service_task(struct work_struct *work) interface = container_of(work, struct fm10k_intfc, service_task); - /* tasks always capable of running, but must be rtnl protected */ + /* tasks run even when interface is down */ fm10k_mbx_subtask(interface); fm10k_detach_subtask(interface); fm10k_reset_subtask(interface); -- cgit v1.2.3 From a023bbd0b1a3716397d8d54ba5b95e09b8e27699 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Wed, 24 Jun 2015 16:38:53 -0400 Subject: ixgbe: Add SFP+ detection for X550 hardware This patch is part of the future enablement of X550 SFP+ support. This HW uses different SDP so the interrupts need to be set up accordingly. Signed-off-by: Donald C Skidmore Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index acb1b91408ec..5f04ad42fec4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -4904,9 +4904,15 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter) if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) gpie |= IXGBE_SDP1_GPIEN(hw); - if (hw->mac.type == ixgbe_mac_82599EB) { - gpie |= IXGBE_SDP1_GPIEN_8259X; - gpie |= IXGBE_SDP2_GPIEN_8259X; + switch (hw->mac.type) { + case ixgbe_mac_82599EB: + gpie |= IXGBE_SDP1_GPIEN_8259X | IXGBE_SDP2_GPIEN_8259X; + break; + case ixgbe_mac_X550EM_x: + gpie |= IXGBE_SDP0_GPIEN_X540; + break; + default: + break; } IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); -- cgit v1.2.3 From 5532408b48834bd762ed53c22aabed5dae0748d6 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Wed, 24 Jun 2015 17:03:30 -0400 Subject: ixgbe: Add fdir support for SCTP on X550 X550 has HW support for SCTP flow director filters SCTP mask. This patch adds it like we do for UDP and TCP. Signed-off-by: Donald C Skidmore Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | 10 ++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1 + 2 files changed, 11 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index dd7062fed61a..85156fb53b62 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -1766,6 +1766,16 @@ s32 ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw, IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm); IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm); + /* also use it for SCTP */ + switch (hw->mac.type) { + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: + IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm); + break; + default: + break; + } + /* store source and destination IP masks (big-enian) */ IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M, ~input_mask->formatted.src_ip[0]); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 63689192b149..4e16d146739c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -402,6 +402,7 @@ struct ixgbe_thermal_sensor_data { #define IXGBE_FDIRSIP4M 0x0EE40 #define IXGBE_FDIRTCPM 0x0EE44 #define IXGBE_FDIRUDPM 0x0EE48 +#define IXGBE_FDIRSCTPM 0x0EE78 #define IXGBE_FDIRIP6M 0x0EE74 #define IXGBE_FDIRM 0x0EE70 -- cgit v1.2.3 From 4b09728e9d34170c375f41d9b454f067ce39591f Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 25 Jun 2015 14:43:43 -0700 Subject: fm10k: drop transmitted messages in Tx FIFO as part of reset_work This patch fixes a corner case issue with the PF/VF mailbox code. Currently, fm10k_mbx_reset_work clears various state about the mailbox. However, it does not clear the Tx FIFO head/tail pointers. We can't simply clear these pointers as we unintentionally drop untransmitted messages without error. Doing nothing results in a possible phantom re-transmission of messages, since we leave tx.head and tx.tail intact, but clear the tx_pulled and tail_len values. This means that the PF could continuously re-send a message which triggers a reset in the VF. Upon reset, the VF will re-receive the same message after a reconnect. If we reset the tx.head and tx.tail pointers completely, we end up dropping some messages that were pending before connect. This results in missing LPORT_MSG_READY bits, and VFs will end up reporting no link. However, we can resolve both issues by simply incrementing head to account for the already transmitted messages, before we reset tx_pulled. We do this via the same logic as fm10k_mbx_head_pull. We account for the tail_len which includes all data not yet transmitted, once we account for the acked data which means re-reading the HEAD variable from the message header. Then, we drop messages until we've dropped more than the new tx_pulled value. At this point, resetting tail_len and tx_pulled, but not tx.head and tx.tail will result in prevention of the phantom message. It also prevents us from dropping untransmitted messages upon attempting to Tx into a connect or disconnect header. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_mbx.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c index 1a4b52637de9..0ff21d1fb9db 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c @@ -1046,9 +1046,26 @@ static s32 fm10k_mbx_create_reply(struct fm10k_hw *hw, **/ static void fm10k_mbx_reset_work(struct fm10k_mbx_info *mbx) { + u16 len, head, ack; + /* reset our outgoing max size back to Rx limits */ mbx->max_size = mbx->rx.size - 1; + /* update mbx->pulled to account for tail_len and ack */ + head = FM10K_MSG_HDR_FIELD_GET(mbx->mbx_hdr, HEAD); + ack = fm10k_mbx_index_len(mbx, head, mbx->tail); + mbx->pulled += mbx->tail_len - ack; + + /* now drop any messages which have started or finished transmitting */ + while (fm10k_fifo_head_len(&mbx->tx) && mbx->pulled) { + len = fm10k_fifo_head_drop(&mbx->tx); + mbx->tx_dropped++; + if (mbx->pulled >= len) + mbx->pulled -= len; + else + mbx->pulled = 0; + } + /* just do a quick resysnc to start of message */ mbx->pushed = 0; mbx->pulled = 0; @@ -1725,7 +1742,7 @@ static void fm10k_sm_mbx_disconnect(struct fm10k_hw *hw, mbx->state = FM10K_STATE_CLOSED; mbx->remote = 0; fm10k_mbx_reset_work(mbx); - fm10k_mbx_update_max_size(mbx, 0); + fm10k_fifo_drop_all(&mbx->tx); fm10k_write_reg(hw, mbx->mbmem_reg, 0); } -- cgit v1.2.3 From afadfd224f53106e4fd52f3b6885a93431a5a6f5 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 26 Jun 2015 08:54:06 -0700 Subject: fm10k: create "correct" header for the remote end on connect When we connect to the mailbox, we insert a fake disconnect header so that the code does not see an invalid header and thus instantly error every time we bring up the mailbox. However, we incorrectly record the tail and head from the local perspective. Since the remote end shouldn't have anything for us, add a "create_fake_disconnect_hdr" function which inverts the TAIL and HEAD fields. This enables us to connect without any errors of either TAIL or HEAD incorrectness, and prevents creating extraneous error messages. This is necessary now since mbx_reset_work does not actually reset the Tx FIFO head and tail pointers, thus head and tail might not be equivalent on a reconnect. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_mbx.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c index 0ff21d1fb9db..5403d8602fce 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c @@ -898,6 +898,27 @@ static void fm10k_mbx_create_disconnect_hdr(struct fm10k_mbx_info *mbx) mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC); } +/** + * fm10k_mbx_create_fake_disconnect_hdr - Generate a false disconnect mailbox header + * @mbx: pointer to mailbox + * + * This function creates a fake disconnect header for loading into remote + * mailbox header. The primary purpose is to prevent errors on immediate + * start up after mbx->connect. + **/ +static void fm10k_mbx_create_fake_disconnect_hdr(struct fm10k_mbx_info *mbx) +{ + u32 hdr = FM10K_MSG_HDR_FIELD_SET(FM10K_MSG_DISCONNECT, TYPE) | + FM10K_MSG_HDR_FIELD_SET(mbx->head, TAIL) | + FM10K_MSG_HDR_FIELD_SET(mbx->tail, HEAD); + u16 crc = fm10k_crc_16b(&hdr, mbx->local, 1); + + mbx->mbx_lock |= FM10K_MBX_ACK; + + /* load header to memory to be written */ + mbx->mbx_hdr = hdr | FM10K_MSG_HDR_FIELD_SET(crc, CRC); +} + /** * fm10k_mbx_create_error_msg - Generate a error message * @mbx: pointer to mailbox @@ -1435,8 +1456,10 @@ static s32 fm10k_mbx_connect(struct fm10k_hw *hw, struct fm10k_mbx_info *mbx) /* Place mbx in ready to connect state */ mbx->state = FM10K_STATE_CONNECT; + fm10k_mbx_reset_work(mbx); + /* initialize header of remote mailbox */ - fm10k_mbx_create_disconnect_hdr(mbx); + fm10k_mbx_create_fake_disconnect_hdr(mbx); fm10k_write_reg(hw, mbx->mbmem_reg ^ mbx->mbmem_len, mbx->mbx_hdr); /* enable interrupt and notify other party of new message */ -- cgit v1.2.3 From 15aa49cb99c128e1484b6373382e264588067cab Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 26 Jun 2015 08:54:07 -0700 Subject: fm10k: TRIVIAL remove unnecessary comma Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_mbx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c index 5403d8602fce..af09a1b272e6 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_mbx.c @@ -129,8 +129,8 @@ static u16 fm10k_fifo_head_drop(struct fm10k_mbx_fifo *fifo) * fm10k_fifo_drop_all - Drop all messages in FIFO * @fifo: pointer to FIFO * - * This function resets the head pointer to drop all messages in the FIFO, - * and ensure the FIFO is empty. + * This function resets the head pointer to drop all messages in the FIFO and + * ensure the FIFO is empty. **/ static void fm10k_fifo_drop_all(struct fm10k_mbx_fifo *fifo) { -- cgit v1.2.3 From 80043f3bf5bdb187566620a8f183c15b94e961cb Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 1 Jul 2015 17:38:36 -0700 Subject: fm10k: add support for extra debug statistics Add a private ethtool flag to enable display of these statistics, which are generally less useful. However, sometimes it can be useful for debugging purposes. The most useful portion is the ability to see what the PF thinks the VF mailboxes look like. Signed-off-by: Jacob Keller Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k.h | 19 ++ drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 216 +++++++++++++++++++---- drivers/net/ethernet/intel/fm10k/fm10k_iov.c | 5 +- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 15 ++ drivers/net/ethernet/intel/fm10k/fm10k_pci.c | 18 ++ drivers/net/ethernet/intel/fm10k/fm10k_type.h | 6 + 6 files changed, 243 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h index c8c8c5baefda..14440200499b 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k.h @@ -101,12 +101,19 @@ struct fm10k_tx_queue_stats { u64 csum_err; u64 tx_busy; u64 tx_done_old; + u64 csum_good; }; struct fm10k_rx_queue_stats { u64 alloc_failed; u64 csum_err; u64 errors; + u64 csum_good; + u64 switch_errors; + u64 drops; + u64 pp_errors; + u64 link_errors; + u64 length_errors; }; struct fm10k_ring { @@ -251,6 +258,7 @@ struct fm10k_intfc { #define FM10K_FLAG_RSS_FIELD_IPV6_UDP (u32)(1 << 2) #define FM10K_FLAG_RX_TS_ENABLED (u32)(1 << 3) #define FM10K_FLAG_SWPRI_CONFIG (u32)(1 << 4) +#define FM10K_FLAG_DEBUG_STATS (u32)(1 << 5) int xcast_mode; /* Tx fast path data */ @@ -277,6 +285,17 @@ struct fm10k_intfc { u64 rx_drops_nic; u64 rx_overrun_pf; u64 rx_overrun_vf; + + /* Debug Statistics */ + u64 hw_sm_mbx_full; + u64 hw_csum_tx_good; + u64 hw_csum_rx_good; + u64 rx_switch_errors; + u64 rx_drops; + u64 rx_pp_errors; + u64 rx_link_errors; + u64 rx_length_errors; + u32 tx_timeout_count; /* RX */ diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index c6dc9683429e..4ef2fbd22911 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -76,19 +76,22 @@ static const struct fm10k_stats fm10k_gstrings_global_stats[] = { FM10K_STAT("mac_rules_used", hw.swapi.mac.used), FM10K_STAT("mac_rules_avail", hw.swapi.mac.avail), - FM10K_STAT("mbx_tx_busy", hw.mbx.tx_busy), - FM10K_STAT("mbx_tx_oversized", hw.mbx.tx_dropped), - FM10K_STAT("mbx_tx_messages", hw.mbx.tx_messages), - FM10K_STAT("mbx_tx_dwords", hw.mbx.tx_dwords), - FM10K_STAT("mbx_rx_messages", hw.mbx.rx_messages), - FM10K_STAT("mbx_rx_dwords", hw.mbx.rx_dwords), - FM10K_STAT("mbx_rx_parse_err", hw.mbx.rx_parse_err), - FM10K_STAT("tx_hang_count", tx_timeout_count), FM10K_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts), }; +static const struct fm10k_stats fm10k_gstrings_debug_stats[] = { + FM10K_STAT("hw_sm_mbx_full", hw_sm_mbx_full), + FM10K_STAT("hw_csum_tx_good", hw_csum_tx_good), + FM10K_STAT("hw_csum_rx_good", hw_csum_rx_good), + FM10K_STAT("rx_switch_errors", rx_switch_errors), + FM10K_STAT("rx_drops", rx_drops), + FM10K_STAT("rx_pp_errors", rx_pp_errors), + FM10K_STAT("rx_link_errors", rx_link_errors), + FM10K_STAT("rx_length_errors", rx_length_errors), +}; + static const struct fm10k_stats fm10k_gstrings_pf_stats[] = { FM10K_STAT("timeout", stats.timeout.count), FM10K_STAT("ur", stats.ur.count), @@ -100,14 +103,33 @@ static const struct fm10k_stats fm10k_gstrings_pf_stats[] = { FM10K_STAT("nodesc_drop", stats.nodesc_drop.count), }; +#define FM10K_MBX_STAT(_name, _stat) { \ + .stat_string = _name, \ + .sizeof_stat = FIELD_SIZEOF(struct fm10k_mbx_info, _stat), \ + .stat_offset = offsetof(struct fm10k_mbx_info, _stat) \ +} + +static const struct fm10k_stats fm10k_gstrings_mbx_stats[] = { + FM10K_MBX_STAT("mbx_tx_busy", tx_busy), + FM10K_MBX_STAT("mbx_tx_oversized", tx_dropped), + FM10K_MBX_STAT("mbx_tx_messages", tx_messages), + FM10K_MBX_STAT("mbx_tx_dwords", tx_dwords), + FM10K_MBX_STAT("mbx_rx_messages", rx_messages), + FM10K_MBX_STAT("mbx_rx_dwords", rx_dwords), + FM10K_MBX_STAT("mbx_rx_parse_err", rx_parse_err), +}; + #define FM10K_GLOBAL_STATS_LEN ARRAY_SIZE(fm10k_gstrings_global_stats) +#define FM10K_DEBUG_STATS_LEN ARRAY_SIZE(fm10k_gstrings_debug_stats) #define FM10K_PF_STATS_LEN ARRAY_SIZE(fm10k_gstrings_pf_stats) +#define FM10K_MBX_STATS_LEN ARRAY_SIZE(fm10k_gstrings_mbx_stats) #define FM10K_QUEUE_STATS_LEN(_n) \ ( (_n) * 2 * (sizeof(struct fm10k_queue_stats) / sizeof(u64))) #define FM10K_STATIC_STATS_LEN (FM10K_GLOBAL_STATS_LEN + \ - FM10K_NETDEV_STATS_LEN) + FM10K_NETDEV_STATS_LEN + \ + FM10K_MBX_STATS_LEN) static const char fm10k_gstrings_test[][ETH_GSTRING_LEN] = { "Mailbox test (on/offline)" @@ -120,47 +142,97 @@ enum fm10k_self_test_types { FM10K_TEST_MAX = FM10K_TEST_LEN }; -static void fm10k_get_strings(struct net_device *dev, u32 stringset, u8 *data) +enum { + FM10K_PRV_FLAG_DEBUG_STATS, + FM10K_PRV_FLAG_LEN, +}; + +static const char fm10k_prv_flags[FM10K_PRV_FLAG_LEN][ETH_GSTRING_LEN] = { + "debug-statistics", +}; + +static void fm10k_get_stat_strings(struct net_device *dev, u8 *data) { struct fm10k_intfc *interface = netdev_priv(dev); + struct fm10k_iov_data *iov_data = interface->iov_data; char *p = (char *)data; unsigned int i; + unsigned int j; - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *fm10k_gstrings_test, - FM10K_TEST_LEN * ETH_GSTRING_LEN); - break; - case ETH_SS_STATS: - for (i = 0; i < FM10K_NETDEV_STATS_LEN; i++) { - memcpy(p, fm10k_gstrings_net_stats[i].stat_string, + for (i = 0; i < FM10K_NETDEV_STATS_LEN; i++) { + memcpy(p, fm10k_gstrings_net_stats[i].stat_string, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + + for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) { + memcpy(p, fm10k_gstrings_global_stats[i].stat_string, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + + if (interface->flags & FM10K_FLAG_DEBUG_STATS) { + for (i = 0; i < FM10K_DEBUG_STATS_LEN; i++) { + memcpy(p, fm10k_gstrings_debug_stats[i].stat_string, ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } - for (i = 0; i < FM10K_GLOBAL_STATS_LEN; i++) { - memcpy(p, fm10k_gstrings_global_stats[i].stat_string, + } + + for (i = 0; i < FM10K_MBX_STATS_LEN; i++) { + memcpy(p, fm10k_gstrings_mbx_stats[i].stat_string, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + + if (interface->hw.mac.type != fm10k_mac_vf) { + for (i = 0; i < FM10K_PF_STATS_LEN; i++) { + memcpy(p, fm10k_gstrings_pf_stats[i].stat_string, ETH_GSTRING_LEN); p += ETH_GSTRING_LEN; } + } - if (interface->hw.mac.type != fm10k_mac_vf) { - for (i = 0; i < FM10K_PF_STATS_LEN; i++) { - memcpy(p, fm10k_gstrings_pf_stats[i].stat_string, - ETH_GSTRING_LEN); + if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) { + for (i = 0; i < iov_data->num_vfs; i++) { + for (j = 0; j < FM10K_MBX_STATS_LEN; j++) { + snprintf(p, + ETH_GSTRING_LEN, + "vf_%u_%s", i, + fm10k_gstrings_mbx_stats[j].stat_string); p += ETH_GSTRING_LEN; } } + } - for (i = 0; i < interface->hw.mac.max_queues; i++) { - sprintf(p, "tx_queue_%u_packets", i); - p += ETH_GSTRING_LEN; - sprintf(p, "tx_queue_%u_bytes", i); - p += ETH_GSTRING_LEN; - sprintf(p, "rx_queue_%u_packets", i); - p += ETH_GSTRING_LEN; - sprintf(p, "rx_queue_%u_bytes", i); - p += ETH_GSTRING_LEN; - } + for (i = 0; i < interface->hw.mac.max_queues; i++) { + sprintf(p, "tx_queue_%u_packets", i); + p += ETH_GSTRING_LEN; + sprintf(p, "tx_queue_%u_bytes", i); + p += ETH_GSTRING_LEN; + sprintf(p, "rx_queue_%u_packets", i); + p += ETH_GSTRING_LEN; + sprintf(p, "rx_queue_%u_bytes", i); + p += ETH_GSTRING_LEN; + } +} + +static void fm10k_get_strings(struct net_device *dev, + u32 stringset, u8 *data) +{ + char *p = (char *)data; + + switch (stringset) { + case ETH_SS_TEST: + memcpy(data, *fm10k_gstrings_test, + FM10K_TEST_LEN * ETH_GSTRING_LEN); + break; + case ETH_SS_STATS: + fm10k_get_stat_strings(dev, data); + break; + case ETH_SS_PRIV_FLAGS: + memcpy(p, fm10k_prv_flags, + FM10K_PRV_FLAG_LEN * ETH_GSTRING_LEN); break; } } @@ -168,6 +240,7 @@ static void fm10k_get_strings(struct net_device *dev, u32 stringset, u8 *data) static int fm10k_get_sset_count(struct net_device *dev, int sset) { struct fm10k_intfc *interface = netdev_priv(dev); + struct fm10k_iov_data *iov_data = interface->iov_data; struct fm10k_hw *hw = &interface->hw; int stats_len = FM10K_STATIC_STATS_LEN; @@ -180,7 +253,16 @@ static int fm10k_get_sset_count(struct net_device *dev, int sset) if (hw->mac.type != fm10k_mac_vf) stats_len += FM10K_PF_STATS_LEN; + if (interface->flags & FM10K_FLAG_DEBUG_STATS) { + stats_len += FM10K_DEBUG_STATS_LEN; + + if (iov_data) + stats_len += FM10K_MBX_STATS_LEN * iov_data->num_vfs; + } + return stats_len; + case ETH_SS_PRIV_FLAGS: + return FM10K_PRV_FLAG_LEN; default: return -EOPNOTSUPP; } @@ -192,6 +274,7 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, { const int stat_count = sizeof(struct fm10k_queue_stats) / sizeof(u64); struct fm10k_intfc *interface = netdev_priv(netdev); + struct fm10k_iov_data *iov_data = interface->iov_data; struct net_device_stats *net_stats = &netdev->stats; char *p; int i, j; @@ -211,13 +294,47 @@ static void fm10k_get_ethtool_stats(struct net_device *netdev, sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } - if (interface->hw.mac.type != fm10k_mac_vf) + if (interface->flags & FM10K_FLAG_DEBUG_STATS) { + for (i = 0; i < FM10K_DEBUG_STATS_LEN; i++) { + p = (char *)interface + fm10k_gstrings_debug_stats[i].stat_offset; + *(data++) = (fm10k_gstrings_debug_stats[i].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + } + + for (i = 0; i < FM10K_MBX_STATS_LEN; i++) { + p = (char *)&interface->hw.mbx + fm10k_gstrings_mbx_stats[i].stat_offset; + *(data++) = (fm10k_gstrings_mbx_stats[i].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + + if (interface->hw.mac.type != fm10k_mac_vf) { for (i = 0; i < FM10K_PF_STATS_LEN; i++) { p = (char *)interface + fm10k_gstrings_pf_stats[i].stat_offset; *(data++) = (fm10k_gstrings_pf_stats[i].sizeof_stat == sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } + } + + if ((interface->flags & FM10K_FLAG_DEBUG_STATS) && iov_data) { + for (i = 0; i < iov_data->num_vfs; i++) { + struct fm10k_vf_info *vf_info; + vf_info = &iov_data->vf_info[i]; + + /* skip stats if we don't have a vf info */ + if (!vf_info) { + data += FM10K_MBX_STATS_LEN; + continue; + } + + for (j = 0; j < FM10K_MBX_STATS_LEN; j++) { + p = (char *)&vf_info->mbx + fm10k_gstrings_mbx_stats[j].stat_offset; + *(data++) = (fm10k_gstrings_mbx_stats[j].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : *(u32 *)p; + } + } + } for (i = 0; i < interface->hw.mac.max_queues; i++) { struct fm10k_ring *ring; @@ -881,6 +998,33 @@ static void fm10k_self_test(struct net_device *dev, eth_test->flags |= ETH_TEST_FL_FAILED; } +static u32 fm10k_get_priv_flags(struct net_device *netdev) +{ + struct fm10k_intfc *interface = netdev_priv(netdev); + u32 priv_flags = 0; + + if (interface->flags & FM10K_FLAG_DEBUG_STATS) + priv_flags |= 1 << FM10K_PRV_FLAG_DEBUG_STATS; + + return priv_flags; +} + +static int fm10k_set_priv_flags(struct net_device *netdev, u32 priv_flags) +{ + struct fm10k_intfc *interface = netdev_priv(netdev); + + if (priv_flags >= (1 << FM10K_PRV_FLAG_LEN)) + return -EINVAL; + + if (priv_flags & (1 << FM10K_PRV_FLAG_DEBUG_STATS)) + interface->flags |= FM10K_FLAG_DEBUG_STATS; + else + interface->flags &= ~FM10K_FLAG_DEBUG_STATS; + + return 0; +} + + static u32 fm10k_get_reta_size(struct net_device __always_unused *netdev) { return FM10K_RETA_SIZE * FM10K_RETA_ENTRIES_PER_REG; @@ -1094,6 +1238,8 @@ static const struct ethtool_ops fm10k_ethtool_ops = { .get_regs = fm10k_get_regs, .get_regs_len = fm10k_get_regs_len, .self_test = fm10k_self_test, + .get_priv_flags = fm10k_get_priv_flags, + .set_priv_flags = fm10k_set_priv_flags, .get_rxfh_indir_size = fm10k_get_reta_size, .get_rxfh_key_size = fm10k_get_rssrk_size, .get_rxfh = fm10k_get_rssh, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c index 0e25a80417b9..acfb8b1f88a7 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_iov.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_iov.c @@ -137,8 +137,11 @@ process_mbx: } /* guarantee we have free space in the SM mailbox */ - if (!hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU)) + if (!hw->mbx.ops.tx_ready(&hw->mbx, FM10K_VFMBX_MSG_MTU)) { + /* keep track of how many times this occurs */ + interface->hw_sm_mbx_full++; break; + } /* cleanup mailbox and process received messages */ mbx->ops.process(hw, mbx); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 92d415584749..2f47bfe6cc90 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -398,6 +398,8 @@ static inline void fm10k_rx_checksum(struct fm10k_ring *ring, return; skb->ip_summed = CHECKSUM_UNNECESSARY; + + ring->rx_stats.csum_good++; } #define FM10K_RSS_L4_TYPES_MASK \ @@ -556,6 +558,18 @@ static bool fm10k_cleanup_headers(struct fm10k_ring *rx_ring, { if (unlikely((fm10k_test_staterr(rx_desc, FM10K_RXD_STATUS_RXE)))) { +#define FM10K_TEST_RXD_BIT(rxd, bit) \ + ((rxd)->w.csum_err & cpu_to_le16(bit)) + if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_SWITCH_ERROR)) + rx_ring->rx_stats.switch_errors++; + if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_NO_DESCRIPTOR)) + rx_ring->rx_stats.drops++; + if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_PP_ERROR)) + rx_ring->rx_stats.pp_errors++; + if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_SWITCH_READY)) + rx_ring->rx_stats.link_errors++; + if (FM10K_TEST_RXD_BIT(rx_desc, FM10K_RXD_ERR_TOO_BIG)) + rx_ring->rx_stats.length_errors++; dev_kfree_skb_any(skb); rx_ring->rx_stats.errors++; return true; @@ -881,6 +895,7 @@ static void fm10k_tx_csum(struct fm10k_ring *tx_ring, /* update TX checksum flag */ first->tx_flags |= FM10K_TX_FLAGS_CSUM; + tx_ring->tx_stats.csum_good++; no_csum: /* populate Tx descriptor header size and mss */ diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c index dfefd06447e5..74be792f3f1b 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c @@ -328,6 +328,9 @@ void fm10k_update_stats(struct fm10k_intfc *interface) { struct net_device_stats *net_stats = &interface->netdev->stats; struct fm10k_hw *hw = &interface->hw; + u64 hw_csum_tx_good = 0, hw_csum_rx_good = 0, rx_length_errors = 0; + u64 rx_switch_errors = 0, rx_drops = 0, rx_pp_errors = 0; + u64 rx_link_errors = 0; u64 rx_errors = 0, rx_csum_errors = 0, tx_csum_errors = 0; u64 restart_queue = 0, tx_busy = 0, alloc_failed = 0; u64 rx_bytes_nic = 0, rx_pkts_nic = 0, rx_drops_nic = 0; @@ -347,6 +350,7 @@ void fm10k_update_stats(struct fm10k_intfc *interface) tx_csum_errors += tx_ring->tx_stats.csum_err; bytes += tx_ring->stats.bytes; pkts += tx_ring->stats.packets; + hw_csum_tx_good += tx_ring->tx_stats.csum_good; } interface->restart_queue = restart_queue; @@ -354,6 +358,8 @@ void fm10k_update_stats(struct fm10k_intfc *interface) net_stats->tx_bytes = bytes; net_stats->tx_packets = pkts; interface->tx_csum_errors = tx_csum_errors; + interface->hw_csum_tx_good = hw_csum_tx_good; + /* gather some stats to the interface struct that are per queue */ for (bytes = 0, pkts = 0, i = 0; i < interface->num_rx_queues; i++) { struct fm10k_ring *rx_ring = interface->rx_ring[i]; @@ -363,12 +369,24 @@ void fm10k_update_stats(struct fm10k_intfc *interface) alloc_failed += rx_ring->rx_stats.alloc_failed; rx_csum_errors += rx_ring->rx_stats.csum_err; rx_errors += rx_ring->rx_stats.errors; + hw_csum_rx_good += rx_ring->rx_stats.csum_good; + rx_switch_errors += rx_ring->rx_stats.switch_errors; + rx_drops += rx_ring->rx_stats.drops; + rx_pp_errors += rx_ring->rx_stats.pp_errors; + rx_link_errors += rx_ring->rx_stats.link_errors; + rx_length_errors += rx_ring->rx_stats.length_errors; } net_stats->rx_bytes = bytes; net_stats->rx_packets = pkts; interface->alloc_failed = alloc_failed; interface->rx_csum_errors = rx_csum_errors; + interface->hw_csum_rx_good = hw_csum_rx_good; + interface->rx_switch_errors = rx_switch_errors; + interface->rx_drops = rx_drops; + interface->rx_pp_errors = rx_pp_errors; + interface->rx_link_errors = rx_link_errors; + interface->rx_length_errors = rx_length_errors; hw->mac.ops.update_hw_stats(hw, &interface->stats); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_type.h b/drivers/net/ethernet/intel/fm10k/fm10k_type.h index bac8d486d75f..318a212f0a78 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_type.h +++ b/drivers/net/ethernet/intel/fm10k/fm10k_type.h @@ -762,6 +762,12 @@ enum fm10k_rxdesc_xc { #define FM10K_RXD_STATUS_L4E 0x4000 /* L4 csum error */ #define FM10K_RXD_STATUS_IPE 0x8000 /* IPv4 csum error */ +#define FM10K_RXD_ERR_SWITCH_ERROR 0x0001 /* Switch found bad packet */ +#define FM10K_RXD_ERR_NO_DESCRIPTOR 0x0002 /* No descriptor available */ +#define FM10K_RXD_ERR_PP_ERROR 0x0004 /* RAM error during processing */ +#define FM10K_RXD_ERR_SWITCH_READY 0x0008 /* Link transition mid-packet */ +#define FM10K_RXD_ERR_TOO_BIG 0x0010 /* Pkt too big for single buf */ + struct fm10k_ftag { __be16 swpri_type_user; __be16 vlan; -- cgit v1.2.3 From 307723255a05242ab252dd7047d4970ab60c7dfd Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Thu, 6 Aug 2015 00:52:37 +0200 Subject: e1000: remove dead e1000_init_eeprom_params calls The device probe method e1000_probe calls e1000_init_eeprom_params itself so there's no reason to call it again from e1000_do_write_eeprom or e1000_do_read_eeprom. The sentence above assumes that e1000_init_eeprom_params is effective. e1000_init_eeprom_params depends mostly on hw->mac_type and e1000_probe bails out early if it can't set mac_type (see e1000_init_hw_struct, then e1000_set_mac_type), qed. Btw, if effective, the removed paths would had been deadlock prone when e1000_eeprom_spi was set: -> e1000_write_eeprom (takes e1000_eeprom_lock) -> e1000_do_write_eeprom -> e1000_init_eeprom_params -> e1000_read_eeprom (takes e1000_eeprom_lock) (same narrative with e1000_read_eeprom -> e1000_do_read_eeprom etc.) As a final note, the candidate deadlock above can't happen in e1000_probe due to the way eeprom->word_size is set / tested. Signed-off-by: Francois Romieu Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000/e1000_hw.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/e1000/e1000_hw.c b/drivers/net/ethernet/intel/e1000/e1000_hw.c index 45c8c864104e..b1af0d613caa 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_hw.c +++ b/drivers/net/ethernet/intel/e1000/e1000_hw.c @@ -3900,10 +3900,6 @@ static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, return E1000_SUCCESS; } - /* If eeprom is not yet detected, do so now */ - if (eeprom->word_size == 0) - e1000_init_eeprom_params(hw); - /* A check for invalid values: offset too large, too many words, and * not enough words. */ @@ -4074,10 +4070,6 @@ static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, return E1000_SUCCESS; } - /* If eeprom is not yet detected, do so now */ - if (eeprom->word_size == 0) - e1000_init_eeprom_params(hw); - /* A check for invalid values: offset too large, too many words, and * not enough words. */ -- cgit v1.2.3 From 213246d3fade6772e07138597bca0bdf9fbe754d Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Thu, 6 Aug 2015 17:57:28 +0900 Subject: igbvf: Enable TSO for stacked VLAN Setting ndo_features_check to passthru_features_check allows the driver to skip the check for multiple tagged TSO packets and enables stacked VLAN TSO. Tested with I350. Signed-off-by: Toshiaki Makita Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igbvf/netdev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index 686fa7184179..e86d41ed9260 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -2615,6 +2615,7 @@ static const struct net_device_ops igbvf_netdev_ops = { .ndo_poll_controller = igbvf_netpoll, #endif .ndo_set_features = igbvf_set_features, + .ndo_features_check = passthru_features_check, }; /** -- cgit v1.2.3 From f2701b185e05d0897a47f6a14da40a068b0644ff Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Thu, 6 Aug 2015 17:57:29 +0900 Subject: e1000e: Enable TSO for stacked VLAN Setting ndo_features_check to passthru_features_check allows the driver to skip the check for multiple tagged TSO packets and enables stacked VLAN TSO. Tested with I217-LM. Signed-off-by: Toshiaki Makita Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000e/netdev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index faf4b3f3d0b5..2e2ddec04a50 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -6952,6 +6952,7 @@ static const struct net_device_ops e1000e_netdev_ops = { #endif .ndo_set_features = e1000_set_features, .ndo_fix_features = e1000_fix_features, + .ndo_features_check = passthru_features_check, }; /** -- cgit v1.2.3 From 0f90300f4fd30968a4d40fe47a9043be9912cb31 Mon Sep 17 00:00:00 2001 From: Toshiaki Makita Date: Thu, 6 Aug 2015 17:57:31 +0900 Subject: ixgbevf: Enables TSO for stacked VLAN Setting ndo_features_check to passthru_features_check allows the driver to skip the check for multiple tagged TSO packets and enables stacked VLAN TSO. Tested with 82599ES. Signed-off-by: Toshiaki Makita Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 149a0b4489be..35da2d74e73e 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -3896,6 +3896,7 @@ static const struct net_device_ops ixgbevf_netdev_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ixgbevf_netpoll, #endif + .ndo_features_check = passthru_features_check, }; static void ixgbevf_assign_netdev_ops(struct net_device *dev) -- cgit v1.2.3 From 29a8dca1997f880563e53e9ba0fcb50b03bd23af Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:17:46 -0700 Subject: ixgbe: Accept SFP not present errors on all devices When an SFP not present error is returned by the reset_hw method, accept it and go on, since an SFP can still be inserted. Previously it was only accepted for 82598 devices. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 5f04ad42fec4..c53bef63f921 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -8710,8 +8710,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->phy.reset_if_overtemp = true; err = hw->mac.ops.reset_hw(hw); hw->phy.reset_if_overtemp = false; - if (err == IXGBE_ERR_SFP_NOT_PRESENT && - hw->mac.type == ixgbe_mac_82598EB) { + if (err == IXGBE_ERR_SFP_NOT_PRESENT) { err = 0; } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) { e_dev_err("failed to load because an unsupported SFP+ or QSFP module type was detected.\n"); -- cgit v1.2.3 From cbd45ec7aae9a20835d1a64c7a1910eb5dcec57b Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:17:51 -0700 Subject: ixgbe: Add X550EM support for SFP insertion interrupt Add support for the SFP insertion interrupt on X550EM devices with SFPs. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index c53bef63f921..369204c18832 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2631,6 +2631,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_SFP) + mask |= IXGBE_EIMS_GPI_SDP0(&adapter->hw); if (adapter->hw.phy.type == ixgbe_phy_x550em_ext_t) mask |= IXGBE_EICR_GPI_SDP0_X540; mask |= IXGBE_EIMS_ECC; -- cgit v1.2.3 From 4f9e3a3de0e2fbc49c036322cb2ee656ea8b93fc Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:17:57 -0700 Subject: ixgbe: Provide I2C combined on X550EM Provide I2C combined operations on X550EM, not X550 devices. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 9fe9445cd73b..2906f08d9824 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -2039,14 +2039,14 @@ static struct ixgbe_phy_operations phy_ops_X550 = { X550_COMMON_PHY .init = NULL, .identify = &ixgbe_identify_phy_generic, - .read_i2c_combined = &ixgbe_read_i2c_combined_generic, - .write_i2c_combined = &ixgbe_write_i2c_combined_generic, }; static struct ixgbe_phy_operations phy_ops_X550EM_x = { X550_COMMON_PHY .init = &ixgbe_init_phy_ops_X550em, .identify = &ixgbe_identify_phy_x550em, + .read_i2c_combined = &ixgbe_read_i2c_combined_generic, + .write_i2c_combined = &ixgbe_write_i2c_combined_generic, }; static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { -- cgit v1.2.3 From bb5ce9a5cb6e915a2b284a8785686716823679d1 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:18:02 -0700 Subject: ixgbe: Provide unlocked I2C methods Most I2C accesses take and release semaphores for each access. Now there is a reason to perform multiple I2C operations under the same holding of the semaphore, so provide unlocked I2C methods for that purpose. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c | 199 ++++++++++++++++++++++---- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h | 8 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 4 + drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 3 + 4 files changed, 186 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 597d0b1c2370..0856d0bf821e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -100,16 +100,17 @@ static u8 ixgbe_ones_comp_byte_add(u8 add1, u8 add2) } /** - * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation + * ixgbe_read_i2c_combined_generic_int - Perform I2C read combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to read from * @reg: I2C device register to read from * @val: pointer to location to receive read value + * @lock: true if to take and release semaphore * * Returns an error code on error. - **/ -s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, - u16 reg, u16 *val) + */ +static s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, + u16 reg, u16 *val, bool lock) { u32 swfw_mask = hw->phy.phy_semaphore_mask; int max_retry = 10; @@ -124,7 +125,7 @@ s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, csum = ixgbe_ones_comp_byte_add(reg_high, reg & 0xFF); csum = ~csum; do { - if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) + if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) return IXGBE_ERR_SWFW_SYNC; ixgbe_i2c_start(hw); /* Device Address and write indication */ @@ -157,13 +158,15 @@ s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, if (ixgbe_clock_out_i2c_bit(hw, false)) goto fail; ixgbe_i2c_stop(hw); - hw->mac.ops.release_swfw_sync(hw, swfw_mask); + if (lock) + hw->mac.ops.release_swfw_sync(hw, swfw_mask); *val = (high_bits << 8) | low_bits; return 0; fail: ixgbe_i2c_bus_clear(hw); - hw->mac.ops.release_swfw_sync(hw, swfw_mask); + if (lock) + hw->mac.ops.release_swfw_sync(hw, swfw_mask); retry++; if (retry < max_retry) hw_dbg(hw, "I2C byte read combined error - Retry.\n"); @@ -175,17 +178,49 @@ fail: } /** - * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation + * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation + * @hw: pointer to the hardware structure + * @addr: I2C bus address to read from + * @reg: I2C device register to read from + * @val: pointer to location to receive read value + * + * Returns an error code on error. + */ +s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, + u16 reg, u16 *val) +{ + return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true); +} + +/** + * ixgbe_read_i2c_combined_generic_unlocked - Unlocked I2C read combined + * @hw: pointer to the hardware structure + * @addr: I2C bus address to read from + * @reg: I2C device register to read from + * @val: pointer to location to receive read value + * + * Returns an error code on error. + */ +s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, + u16 reg, u16 *val) +{ + return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false); +} + +/** + * ixgbe_write_i2c_combined_generic_int - Perform I2C write combined operation * @hw: pointer to the hardware structure * @addr: I2C bus address to write to * @reg: I2C device register to write to * @val: value to write + * @lock: true if to take and release semaphore * * Returns an error code on error. - **/ -s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, - u8 addr, u16 reg, u16 val) + */ +static s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr, + u16 reg, u16 val, bool lock) { + u32 swfw_mask = hw->phy.phy_semaphore_mask; int max_retry = 1; int retry = 0; u8 reg_high; @@ -197,6 +232,8 @@ s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, csum = ixgbe_ones_comp_byte_add(csum, val & 0xFF); csum = ~csum; do { + if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) + return IXGBE_ERR_SWFW_SYNC; ixgbe_i2c_start(hw); /* Device Address and write indication */ if (ixgbe_out_i2c_byte_ack(hw, addr)) @@ -217,10 +254,14 @@ s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, if (ixgbe_out_i2c_byte_ack(hw, csum)) goto fail; ixgbe_i2c_stop(hw); + if (lock) + hw->mac.ops.release_swfw_sync(hw, swfw_mask); return 0; fail: ixgbe_i2c_bus_clear(hw); + if (lock) + hw->mac.ops.release_swfw_sync(hw, swfw_mask); retry++; if (retry < max_retry) hw_dbg(hw, "I2C byte write combined error - Retry.\n"); @@ -231,6 +272,36 @@ fail: return IXGBE_ERR_I2C; } +/** + * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation + * @hw: pointer to the hardware structure + * @addr: I2C bus address to write to + * @reg: I2C device register to write to + * @val: value to write + * + * Returns an error code on error. + */ +s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, + u8 addr, u16 reg, u16 val) +{ + return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true); +} + +/** + * ixgbe_write_i2c_combined_generic_unlocked - Unlocked I2C write combined + * @hw: pointer to the hardware structure + * @addr: I2C bus address to write to + * @reg: I2C device register to write to + * @val: value to write + * + * Returns an error code on error. + */ +s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, + u8 addr, u16 reg, u16 val) +{ + return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false); +} + /** * ixgbe_identify_phy_generic - Get physical layer module * @hw: pointer to hardware structure @@ -1660,26 +1731,28 @@ s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, } /** - * ixgbe_read_i2c_byte_generic - Reads 8 bit word over I2C + * ixgbe_read_i2c_byte_generic_int - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @data: value read + * @lock: true if to take and release semaphore * * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. - **/ -s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 *data) + */ +static s32 ixgbe_read_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset, + u8 dev_addr, u8 *data, bool lock) { s32 status; u32 max_retry = 10; u32 retry = 0; u32 swfw_mask = hw->phy.phy_semaphore_mask; bool nack = true; + *data = 0; do { - if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) + if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) return IXGBE_ERR_SWFW_SYNC; ixgbe_i2c_start(hw); @@ -1721,12 +1794,16 @@ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, goto fail; ixgbe_i2c_stop(hw); - break; + if (lock) + hw->mac.ops.release_swfw_sync(hw, swfw_mask); + return 0; fail: ixgbe_i2c_bus_clear(hw); - hw->mac.ops.release_swfw_sync(hw, swfw_mask); - msleep(100); + if (lock) { + hw->mac.ops.release_swfw_sync(hw, swfw_mask); + msleep(100); + } retry++; if (retry < max_retry) hw_dbg(hw, "I2C byte read error - Retrying.\n"); @@ -1735,29 +1812,60 @@ fail: } while (retry < max_retry); - hw->mac.ops.release_swfw_sync(hw, swfw_mask); - return status; } /** - * ixgbe_write_i2c_byte_generic - Writes 8 bit word over I2C + * ixgbe_read_i2c_byte_generic - Reads 8 bit word over I2C + * @hw: pointer to hardware structure + * @byte_offset: byte offset to read + * @data: value read + * + * Performs byte read operation to SFP module's EEPROM over I2C interface at + * a specified device address. + */ +s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, + u8 dev_addr, u8 *data) +{ + return ixgbe_read_i2c_byte_generic_int(hw, byte_offset, dev_addr, + data, true); +} + +/** + * ixgbe_read_i2c_byte_generic_unlocked - Reads 8 bit word over I2C + * @hw: pointer to hardware structure + * @byte_offset: byte offset to read + * @data: value read + * + * Performs byte read operation to SFP module's EEPROM over I2C interface at + * a specified device address. + */ +s32 ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset, + u8 dev_addr, u8 *data) +{ + return ixgbe_read_i2c_byte_generic_int(hw, byte_offset, dev_addr, + data, false); +} + +/** + * ixgbe_write_i2c_byte_generic_int - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @data: value to write + * @lock: true if to take and release semaphore * * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. - **/ -s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data) + */ +static s32 ixgbe_write_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset, + u8 dev_addr, u8 data, bool lock) { s32 status; u32 max_retry = 1; u32 retry = 0; u32 swfw_mask = hw->phy.phy_semaphore_mask; - if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) + if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)) return IXGBE_ERR_SWFW_SYNC; do { @@ -1788,7 +1896,9 @@ s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, goto fail; ixgbe_i2c_stop(hw); - break; + if (lock) + hw->mac.ops.release_swfw_sync(hw, swfw_mask); + return 0; fail: ixgbe_i2c_bus_clear(hw); @@ -1799,11 +1909,44 @@ fail: hw_dbg(hw, "I2C byte write error.\n"); } while (retry < max_retry); - hw->mac.ops.release_swfw_sync(hw, swfw_mask); + if (lock) + hw->mac.ops.release_swfw_sync(hw, swfw_mask); return status; } +/** + * ixgbe_write_i2c_byte_generic - Writes 8 bit word over I2C + * @hw: pointer to hardware structure + * @byte_offset: byte offset to write + * @data: value to write + * + * Performs byte write operation to SFP module's EEPROM over I2C interface at + * a specified device address. + */ +s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, + u8 dev_addr, u8 data) +{ + return ixgbe_write_i2c_byte_generic_int(hw, byte_offset, dev_addr, + data, true); +} + +/** + * ixgbe_write_i2c_byte_generic_unlocked - Writes 8 bit word over I2C + * @hw: pointer to hardware structure + * @byte_offset: byte offset to write + * @data: value to write + * + * Performs byte write operation to SFP module's EEPROM over I2C interface at + * a specified device address. + */ +s32 ixgbe_write_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset, + u8 dev_addr, u8 data) +{ + return ixgbe_write_i2c_byte_generic_int(hw, byte_offset, dev_addr, + data, false); +} + /** * ixgbe_i2c_start - Sets I2C start condition * @hw: pointer to hardware structure diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h index e45988c4dad5..4c06484fdebc 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h @@ -154,8 +154,12 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw); s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); +s32 ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset, + u8 dev_addr, u8 *data); s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); +s32 ixgbe_write_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset, + u8 dev_addr, u8 data); s32 ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); s32 ixgbe_read_i2c_sff8472_generic(struct ixgbe_hw *hw, u8 byte_offset, @@ -164,6 +168,10 @@ s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data); s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 *val); +s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, + u16 reg, u16 *val); s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr, u16 reg, u16 val); +s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr, + u16 reg, u16 val); #endif /* _IXGBE_PHY_H_ */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 4e16d146739c..3be743b4f6ba 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -3329,6 +3329,10 @@ struct ixgbe_phy_operations { s32 (*set_phy_power)(struct ixgbe_hw *, bool on); s32 (*enter_lplu)(struct ixgbe_hw *); s32 (*handle_lasi)(struct ixgbe_hw *hw); + s32 (*read_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg, + u16 *value); + s32 (*write_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg, + u16 value); }; struct ixgbe_eeprom_info { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 2906f08d9824..2a1dca6e8d44 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -2047,6 +2047,9 @@ static struct ixgbe_phy_operations phy_ops_X550EM_x = { .identify = &ixgbe_identify_phy_x550em, .read_i2c_combined = &ixgbe_read_i2c_combined_generic, .write_i2c_combined = &ixgbe_write_i2c_combined_generic, + .read_i2c_combined_unlocked = &ixgbe_read_i2c_combined_generic_unlocked, + .write_i2c_combined_unlocked = + &ixgbe_write_i2c_combined_generic_unlocked, }; static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = { -- cgit v1.2.3 From da4ea4baf77c9e45c53671e465043ffaf26fd45d Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:18:07 -0700 Subject: ixgbe: Set lan_id before first I2C eeprom access The lan_id is being set after a previous I2C eeprom access which makes no sense because it needs to be set before any access. Move the setting to before the access. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 0856d0bf821e..2b238caec826 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -1171,6 +1171,9 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) return IXGBE_ERR_SFP_NOT_PRESENT; } + /* LAN ID is needed for sfp_type determination */ + hw->mac.ops.set_lan_id(hw); + status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER, &identifier); @@ -1178,9 +1181,6 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) if (status) goto err_read_i2c_eeprom; - /* LAN ID is needed for sfp_type determination */ - hw->mac.ops.set_lan_id(hw); - if (identifier != IXGBE_SFF_IDENTIFIER_SFP) { hw->phy.type = ixgbe_phy_sfp_unsupported; return IXGBE_ERR_SFP_NOT_SUPPORTED; -- cgit v1.2.3 From 25b1029789f98f945a03a2d04662a94b357aacb9 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:18:12 -0700 Subject: ixgbe: Enable bit-banging mode on X550 Set the bit banging mode in the hardware when performing bit banging I2C operations on X550. Also control the output enable on both the clock and data lines. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c | 65 +++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 2b238caec826..315f0597fbc0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -1952,11 +1952,14 @@ s32 ixgbe_write_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset, * @hw: pointer to hardware structure * * Sets I2C start condition (High -> Low on SDA while SCL is High) + * Set bit-bang mode on X550 hardware. **/ static void ixgbe_i2c_start(struct ixgbe_hw *hw) { u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw)); + i2cctl |= IXGBE_I2C_BB_EN(hw); + /* Start condition must begin with data and clock high */ ixgbe_set_i2c_data(hw, &i2cctl, 1); ixgbe_raise_i2c_clk(hw, &i2cctl); @@ -1981,10 +1984,15 @@ static void ixgbe_i2c_start(struct ixgbe_hw *hw) * @hw: pointer to hardware structure * * Sets I2C stop condition (Low -> High on SDA while SCL is High) + * Disables bit-bang mode and negates data output enable on X550 + * hardware. **/ static void ixgbe_i2c_stop(struct ixgbe_hw *hw) { u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw)); + u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw); + u32 clk_oe_bit = IXGBE_I2C_CLK_OE_N_EN(hw); + u32 bb_en_bit = IXGBE_I2C_BB_EN(hw); /* Stop condition must begin with data low and clock high */ ixgbe_set_i2c_data(hw, &i2cctl, 0); @@ -1997,6 +2005,13 @@ static void ixgbe_i2c_stop(struct ixgbe_hw *hw) /* bus free time between stop and start (4.7us)*/ udelay(IXGBE_I2C_T_BUF); + + if (bb_en_bit || data_oe_bit || clk_oe_bit) { + i2cctl &= ~bb_en_bit; + i2cctl |= data_oe_bit | clk_oe_bit; + IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl); + IXGBE_WRITE_FLUSH(hw); + } } /** @@ -2044,6 +2059,7 @@ static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data) /* Release SDA line (set high) */ i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw)); i2cctl |= IXGBE_I2C_DATA_OUT(hw); + i2cctl |= IXGBE_I2C_DATA_OE_N_EN(hw); IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl); IXGBE_WRITE_FLUSH(hw); @@ -2058,15 +2074,21 @@ static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data) **/ static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw) { + u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw); s32 status = 0; u32 i = 0; u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw)); u32 timeout = 10; bool ack = true; + if (data_oe_bit) { + i2cctl |= IXGBE_I2C_DATA_OUT(hw); + i2cctl |= data_oe_bit; + IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl); + IXGBE_WRITE_FLUSH(hw); + } ixgbe_raise_i2c_clk(hw, &i2cctl); - /* Minimum high period of clock is 4us */ udelay(IXGBE_I2C_T_HIGH); @@ -2104,7 +2126,14 @@ static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw) static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data) { u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw)); + u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw); + if (data_oe_bit) { + i2cctl |= IXGBE_I2C_DATA_OUT(hw); + i2cctl |= data_oe_bit; + IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), i2cctl); + IXGBE_WRITE_FLUSH(hw); + } ixgbe_raise_i2c_clk(hw, &i2cctl); /* Minimum high period of clock is 4us */ @@ -2159,13 +2188,20 @@ static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data) * @i2cctl: Current value of I2CCTL register * * Raises the I2C clock line '0'->'1' + * Negates the I2C clock output enable on X550 hardware. **/ static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) { + u32 clk_oe_bit = IXGBE_I2C_CLK_OE_N_EN(hw); u32 i = 0; u32 timeout = IXGBE_I2C_CLOCK_STRETCHING_TIMEOUT; u32 i2cctl_r = 0; + if (clk_oe_bit) { + *i2cctl |= clk_oe_bit; + IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl); + } + for (i = 0; i < timeout; i++) { *i2cctl |= IXGBE_I2C_CLK_OUT(hw); IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl); @@ -2185,11 +2221,13 @@ static void ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) * @i2cctl: Current value of I2CCTL register * * Lowers the I2C clock line '1'->'0' + * Asserts the I2C clock output enable on X550 hardware. **/ static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) { *i2cctl &= ~IXGBE_I2C_CLK_OUT(hw); + *i2cctl &= ~IXGBE_I2C_CLK_OE_N_EN(hw); IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl); IXGBE_WRITE_FLUSH(hw); @@ -2205,13 +2243,17 @@ static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl) * @data: I2C data value (0 or 1) to set * * Sets the I2C data bit + * Asserts the I2C data output enable on X550 hardware. **/ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data) { + u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw); + if (data) *i2cctl |= IXGBE_I2C_DATA_OUT(hw); else *i2cctl &= ~IXGBE_I2C_DATA_OUT(hw); + *i2cctl &= ~data_oe_bit; IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl); IXGBE_WRITE_FLUSH(hw); @@ -2219,6 +2261,14 @@ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data) /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */ udelay(IXGBE_I2C_T_RISE + IXGBE_I2C_T_FALL + IXGBE_I2C_T_SU_DATA); + if (!data) /* Can't verify data in this case */ + return 0; + if (data_oe_bit) { + *i2cctl |= data_oe_bit; + IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl); + IXGBE_WRITE_FLUSH(hw); + } + /* Verify data was set correctly */ *i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw)); if (data != ixgbe_get_i2c_data(hw, i2cctl)) { @@ -2235,9 +2285,19 @@ static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data) * @i2cctl: Current value of I2CCTL register * * Returns the I2C data bit value + * Negates the I2C data output enable on X550 hardware. **/ static bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl) { + u32 data_oe_bit = IXGBE_I2C_DATA_OE_N_EN(hw); + + if (data_oe_bit) { + *i2cctl |= data_oe_bit; + IXGBE_WRITE_REG(hw, IXGBE_I2CCTL(hw), *i2cctl); + IXGBE_WRITE_FLUSH(hw); + udelay(IXGBE_I2C_T_FALL); + } + if (*i2cctl & IXGBE_I2C_DATA_IN(hw)) return true; return false; @@ -2252,10 +2312,11 @@ static bool ixgbe_get_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl) **/ static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw) { - u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw)); + u32 i2cctl; u32 i; ixgbe_i2c_start(hw); + i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw)); ixgbe_set_i2c_data(hw, &i2cctl, 1); -- cgit v1.2.3 From 7d2fa71048b85c29a3265a6ed3fae3a568aae49e Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 21 Sep 2015 15:33:50 +0200 Subject: net/ibm/emac: fix type of phy_mode phy_mode can be negative. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/emac/core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ibm/emac/core.h b/drivers/net/ethernet/ibm/emac/core.h index 28df37420da9..f379e474ba7c 100644 --- a/drivers/net/ethernet/ibm/emac/core.h +++ b/drivers/net/ethernet/ibm/emac/core.h @@ -181,7 +181,7 @@ struct emac_instance { struct mal_commac commac; /* PHY infos */ - u32 phy_mode; + int phy_mode; u32 phy_map; u32 phy_address; u32 phy_feat_exc; -- cgit v1.2.3 From 23c2412d6296b4719c2c60054af00062174dd464 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 21 Sep 2015 15:33:51 +0200 Subject: net: stmmac: fix type of entry variable Variable can store negative values. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 925f2f8659b8..934143e1193b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1945,7 +1945,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) { struct stmmac_priv *priv = netdev_priv(dev); unsigned int txsize = priv->dma_tx_size; - unsigned int entry; + int entry; int i, csum_insertion = 0, is_jumbo = 0; int nfrags = skb_shinfo(skb)->nr_frags; struct dma_desc *desc, *first; -- cgit v1.2.3 From 94926121692381247090b35ec68aed124260f05e Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 21 Sep 2015 15:33:52 +0200 Subject: net: brcm80211: fix range check Unsigned minus constant is still unsigned so checking its sign makes no sense. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Signed-off-by: David S. Miller --- drivers/net/wireless/brcm80211/brcmsmac/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 9728be0e704b..218cbc8bf3a7 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -4585,7 +4585,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, wlc_hw->machwcap_backup = wlc_hw->machwcap; /* init tx fifo size */ - WARN_ON((wlc_hw->corerev - XMTFIFOTBL_STARTREV) < 0 || + WARN_ON(wlc_hw->corerev < XMTFIFOTBL_STARTREV || (wlc_hw->corerev - XMTFIFOTBL_STARTREV) > ARRAY_SIZE(xmtfifo_sz)); wlc_hw->xmtfifo_sz = -- cgit v1.2.3 From cc7514985919238ef7ce94e80f0d0ad87193de47 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 21 Sep 2015 15:33:53 +0200 Subject: mwifiex: fix comparison expression To avoid underflows signed variables should be used in expression. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Acked-by: Amitkumar Karwar Signed-off-by: David S. Miller --- drivers/net/wireless/mwifiex/11n_rxreorder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 2906cd543532..b3970a8c9e48 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -615,10 +615,10 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, ((end_win > start_win) && ((seq_num > end_win) || (seq_num < start_win)))) { end_win = seq_num; - if (((seq_num - win_size) + 1) >= 0) + if (((end_win - win_size) + 1) >= 0) start_win = (end_win - win_size) + 1; else - start_win = (MAX_TID_VALUE - (win_size - seq_num)) + 1; + start_win = (MAX_TID_VALUE - (win_size - end_win)) + 1; mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); } -- cgit v1.2.3 From e79dd09b605f42d85d1a5605ad0fe96b970695e9 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 21 Sep 2015 15:33:54 +0200 Subject: orinoco: fix checking for default value Thresholds uses -1 to indicate that default value should be used. Since thresholds are unsigned sign checking makes no sense. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Signed-off-by: David S. Miller --- drivers/net/wireless/orinoco/cfg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c index a9e94b6db5b7..0f6ea316e38e 100644 --- a/drivers/net/wireless/orinoco/cfg.c +++ b/drivers/net/wireless/orinoco/cfg.c @@ -220,7 +220,7 @@ static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed) if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { /* Set fragmentation */ if (priv->has_mwo) { - if (wiphy->frag_threshold < 0) + if (wiphy->frag_threshold == -1) frag_value = 0; else { printk(KERN_WARNING "%s: Fixed fragmentation " @@ -230,7 +230,7 @@ static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed) frag_value = 1; } } else { - if (wiphy->frag_threshold < 0) + if (wiphy->frag_threshold == -1) frag_value = 2346; else if ((wiphy->frag_threshold < 257) || (wiphy->frag_threshold > 2347)) @@ -252,7 +252,7 @@ static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed) * the upper limit. */ - if (wiphy->rts_threshold < 0) + if (wiphy->rts_threshold == -1) rts_value = 2347; else if (wiphy->rts_threshold > 2347) err = -EINVAL; -- cgit v1.2.3 From 7e724da64491b20257d46f100bcc6d6214c37b70 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 21 Sep 2015 15:33:55 +0200 Subject: rndis_wlan: fix checking for default value Thresholds uses -1 to indicate that default value should be used. Since thresholds are unsigned sign checking makes no sense. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Signed-off-by: David S. Miller --- drivers/net/wireless/rndis_wlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 71a825c750cf..a13d1f2b5912 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1236,7 +1236,7 @@ static int set_rts_threshold(struct usbnet *usbdev, u32 rts_threshold) netdev_dbg(usbdev->net, "%s(): %i\n", __func__, rts_threshold); - if (rts_threshold < 0 || rts_threshold > 2347) + if (rts_threshold == -1 || rts_threshold > 2347) rts_threshold = 2347; tmp = cpu_to_le32(rts_threshold); -- cgit v1.2.3 From 227b9e8708b14a8a26ef67bbbe19b13626df4a35 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 21 Sep 2015 15:33:59 +0200 Subject: usbnet: remove invalid check skb->len is always non-negative. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 5 ----- drivers/net/usb/smsc75xx.c | 5 ----- drivers/net/usb/smsc95xx.c | 5 ----- 3 files changed, 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 6a70a72b565d..d2a5f3f88b13 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -2424,11 +2424,6 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb) skb_pull(skb, align_count); } - if (unlikely(skb->len < 0)) { - netdev_warn(dev->net, "invalid rx length<0 %d", skb->len); - return 0; - } - return 1; } diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index d9e7892262fa..30033dbe6662 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -2185,11 +2185,6 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) skb_pull(skb, align_count); } - if (unlikely(skb->len < 0)) { - netdev_warn(dev->net, "invalid rx length<0 %d\n", skb->len); - return 0; - } - return 1; } diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 26423adc35ee..66b3ab9f614e 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1815,11 +1815,6 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) skb_pull(skb, align_count); } - if (unlikely(skb->len < 0)) { - netdev_warn(dev->net, "invalid rx length<0 %d\n", skb->len); - return 0; - } - return 1; } -- cgit v1.2.3 From cb334648a10c7fa6f0f163c22602f4dc1c6d56b4 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:47 -0700 Subject: arcnet: Use normal kernel spacing style Standardized spacing is easier to read. git diff -w shows no differences. objdiff shows no differences. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 10 +- drivers/net/arcnet/arc-rimi.c | 30 ++-- drivers/net/arcnet/arcnet.c | 170 ++++++++++----------- drivers/net/arcnet/capmode.c | 36 ++--- drivers/net/arcnet/com20020-isa.c | 2 +- drivers/net/arcnet/com20020-pci.c | 2 +- drivers/net/arcnet/com20020.c | 38 ++--- drivers/net/arcnet/com20020_cs.c | 306 +++++++++++++++++++------------------- drivers/net/arcnet/com90io.c | 24 +-- drivers/net/arcnet/com90xx.c | 32 ++-- drivers/net/arcnet/rfc1051.c | 12 +- drivers/net/arcnet/rfc1201.c | 36 ++--- 12 files changed, 349 insertions(+), 349 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 705e6ce2eb90..49f5819a0367 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - "raw mode" packet encapsulation (no soft headers) - * + * * Written 1994-1999 by Avery Pennarun. * Derived from skeleton.c by Donald Becker. * @@ -109,7 +109,7 @@ static void rx(struct net_device *dev, int bufnum, skb_put(skb, length + ARC_HDR_SIZE); skb->dev = dev; - pkt = (struct archdr *) skb->data; + pkt = (struct archdr *)skb->data; skb_reset_mac_header(skb); skb_pull(skb, ARC_HDR_SIZE); @@ -136,7 +136,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, uint8_t daddr) { int hdr_size = ARC_HDR_SIZE; - struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); + struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size); /* * Set the source hardware address. @@ -150,7 +150,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, /* see linux/net/ethernet/eth.c to see where I got the following */ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - /* + /* * FIXME: fill in the last byte of the dest ipaddr here to better * comply with RFC1051 in "noarp" mode. */ @@ -192,7 +192,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, hard->offset[0] = ofs = 256 - length; BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", - length,ofs); + length, ofs); lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length); diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index b8b4c7ba884f..4644d46b6a5f 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - "RIM I" (entirely mem-mapped) cards - * + * * Written 1994-1999 by Avery Pennarun. * Written 1999-2000 by Martin Mares . * Derived from skeleton.c by Donald Becker. @@ -56,27 +56,27 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse /* Handy defines for ARCnet specific stuff */ /* Amount of I/O memory used by the card */ -#define BUFFER_SIZE (512) -#define MIRROR_SIZE (BUFFER_SIZE*4) +#define BUFFER_SIZE (512) +#define MIRROR_SIZE (BUFFER_SIZE * 4) /* COM 9026 controller chip --> ARCnet register addresses */ -#define _INTMASK (ioaddr+0) /* writable */ -#define _STATUS (ioaddr+0) /* readable */ -#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ -#define _RESET (ioaddr+8) /* software reset (on read) */ -#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */ -#define _ADDR_HI (ioaddr+15) /* Control registers for said */ -#define _ADDR_LO (ioaddr+14) -#define _CONFIG (ioaddr+2) /* Configuration register */ +#define _INTMASK (ioaddr + 0) /* writable */ +#define _STATUS (ioaddr + 0) /* readable */ +#define _COMMAND (ioaddr + 1) /* writable, returns random vals on read (?) */ +#define _RESET (ioaddr + 8) /* software reset (on read) */ +#define _MEMDATA (ioaddr + 12) /* Data port for IO-mapped memory */ +#define _ADDR_HI (ioaddr + 15) /* Control registers for said */ +#define _ADDR_LO (ioaddr + 14) +#define _CONFIG (ioaddr + 2) /* Configuration register */ #undef ASTATUS #undef ACOMMAND #undef AINTMASK #define ASTATUS() readb(_STATUS) -#define ACOMMAND(cmd) writeb((cmd),_COMMAND) -#define AINTMASK(msk) writeb((msk),_INTMASK) -#define SETCONF() writeb(lp->config,_CONFIG) +#define ACOMMAND(cmd) writeb((cmd), _COMMAND) +#define AINTMASK(msk) writeb((msk), _INTMASK) +#define SETCONF() writeb(lp->config, _CONFIG) /* @@ -90,7 +90,7 @@ static int __init arcrimi_probe(struct net_device *dev) BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n"); BUGLVL(D_NORMAL) printk("Given: node %02Xh, shmem %lXh, irq %d\n", - dev->dev_addr[0], dev->mem_start, dev->irq); + dev->dev_addr[0], dev->mem_start, dev->irq); if (dev->mem_start <= 0 || dev->irq <= 0) { BUGLVL(D_NORMAL) printk("No autoprobe for RIM I; you " diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 10f71c732b59..2a594d1c4b55 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - device-independent routines - * + * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. * Written 1999-2000 by Martin Mares . @@ -20,12 +20,12 @@ * modified by SRC, incorporated herein by reference. * * ********************** - * + * * The change log is now in a file called ChangeLog in this directory. * * Sources: * - Crynwr arcnet.com/arcether.com packet drivers. - * - arcnet.c v0.00 dated 1/1/94 and apparently by + * - arcnet.c v0.00 dated 1/1/94 and apparently by * Donald Becker - it didn't work :) * - skeleton.c v0.05 dated 11/16/93 by Donald Becker * (from Linux Kernel 1.1.45) @@ -69,8 +69,8 @@ static void arcnet_rx(struct net_device *dev, int bufnum); * arc_proto_default instead. It also must not be NULL; if you would like * to set it to NULL, set it to &arc_proto_null instead. */ - struct ArcProto *arc_proto_map[256], *arc_proto_default, - *arc_bcast_proto, *arc_raw_proto; +struct ArcProto *arc_proto_map[256], *arc_proto_default, + *arc_bcast_proto, *arc_raw_proto; static struct ArcProto arc_proto_null = { @@ -136,8 +136,8 @@ static int __init arcnet_init(void) BUGLVL(D_DURING) printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n", - sizeof(struct arc_hardware), sizeof(struct arc_rfc1201), - sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap), + sizeof(struct arc_hardware), sizeof(struct arc_rfc1201), + sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap), sizeof(struct archdr)); return 0; @@ -184,11 +184,11 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, /* hw.copy_from_card expects IRQ context so take the IRQ lock to keep it single threaded */ - if(take_arcnet_lock) + if (take_arcnet_lock) spin_lock_irqsave(&lp->lock, flags); lp->hw.copy_from_card(dev, bufnum, 0, buf, 512); - if(take_arcnet_lock) + if (take_arcnet_lock) spin_unlock_irqrestore(&lp->lock, flags); /* if the offset[0] byte is nonzero, this is a 256-byte packet */ @@ -202,7 +202,7 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, #else -#define arcnet_dump_packet(dev, bufnum, desc,take_arcnet_lock) do { } while (0) +#define arcnet_dump_packet(dev, bufnum, desc, take_arcnet_lock) do { } while (0) #endif @@ -233,7 +233,7 @@ void arcnet_unregister_proto(struct ArcProto *proto) /* * Add a buffer to the queue. Only the interrupt handler is allowed to do * this, unless interrupts are disabled. - * + * * Note: we don't check for a full queue, since there aren't enough buffers * to more than fill it. */ @@ -248,7 +248,7 @@ static void release_arcbuf(struct net_device *dev, int bufnum) BUGLVL(D_DURING) { BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ", bufnum); - for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5) + for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); BUGMSG2(D_DURING, "\n"); } @@ -284,7 +284,7 @@ static int get_arcbuf(struct net_device *dev) BUGLVL(D_DURING) { BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf); - for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5) + for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); BUGMSG2(D_DURING, "\n"); } @@ -346,7 +346,7 @@ struct net_device *alloc_arcdev(const char *name) dev = alloc_netdev(sizeof(struct arcnet_local), name && *name ? name : "arc%d", NET_NAME_UNKNOWN, arcdev_setup); - if(dev) { + if (dev) { struct arcnet_local *lp = netdev_priv(dev); spin_lock_init(&lp->lock); } @@ -367,7 +367,7 @@ int arcnet_open(struct net_device *dev) struct arcnet_local *lp = netdev_priv(dev); int count, newmtu, error; - BUGMSG(D_INIT,"opened."); + BUGMSG(D_INIT, "opened."); if (!try_module_get(lp->hw.owner)) return -ENODEV; @@ -431,24 +431,24 @@ int arcnet_open(struct net_device *dev) BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse " "DOS networking programs!\n"); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (ASTATUS() & RESETflag) { - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); ACOMMAND(CFLAGScmd | RESETclear); } - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); /* make sure we're ready to receive IRQ's. */ AINTMASK(0); udelay(1); /* give it time to set the mask before * we reset it again. (may not even be * necessary) */ - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->intmask = NORXflag | RECONflag; AINTMASK(lp->intmask); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); netif_start_queue(dev); @@ -489,29 +489,29 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, struct ArcProto *proto; BUGMSG(D_DURING, - "create header from %d to %d; protocol %d (%Xh); size %u.\n", - saddr ? *(uint8_t *) saddr : -1, - daddr ? *(uint8_t *) daddr : -1, + "create header from %d to %d; protocol %d (%Xh); size %u.\n", + saddr ? *(uint8_t *)saddr : -1, + daddr ? *(uint8_t *)daddr : -1, type, type, len); - if (skb->len!=0 && len != skb->len) + if (skb->len != 0 && len != skb->len) BUGMSG(D_NORMAL, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n", skb->len, len); - /* Type is host order - ? */ - if(type == ETH_P_ARCNET) { - proto = arc_raw_proto; - BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n",proto->suffix); - _daddr = daddr ? *(uint8_t *) daddr : 0; - } + /* Type is host order - ? */ + if (type == ETH_P_ARCNET) { + proto = arc_raw_proto; + BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n", proto->suffix); + _daddr = daddr ? *(uint8_t *)daddr : 0; + } else if (!daddr) { /* * if the dest addr isn't provided, we can't choose an encapsulation! * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a * real header when we do rebuild_header. */ - *(uint16_t *) skb_push(skb, 2) = type; + *(uint16_t *)skb_push(skb, 2) = type; /* * XXX: Why not use skb->mac_len? */ @@ -522,7 +522,7 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, } else { /* otherwise, we can just add the header as usual. */ - _daddr = *(uint8_t *) daddr; + _daddr = *(uint8_t *)daddr; proto_num = lp->default_proto[_daddr]; proto = arc_proto_map[proto_num]; BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n", @@ -538,7 +538,7 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, /* Called by the kernel in order to transmit a packet. */ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, - struct net_device *dev) + struct net_device *dev) { struct arcnet_local *lp = netdev_priv(dev); struct archdr *pkt; @@ -550,14 +550,14 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, BUGMSG(D_DURING, "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n", - ASTATUS(), lp->cur_tx, lp->next_tx, skb->len,skb->protocol); + ASTATUS(), lp->cur_tx, lp->next_tx, skb->len, skb->protocol); - pkt = (struct archdr *) skb->data; + pkt = (struct archdr *)skb->data; soft = &pkt->soft.rfc1201; proto = arc_proto_map[soft->proto]; BUGMSG(D_SKB_SIZE, "skb: transmitting %d bytes to %02X\n", - skb->len, pkt->hard.dest); + skb->len, pkt->hard.dest); BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx"); /* fits in one packet? */ @@ -572,7 +572,7 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, spin_lock_irqsave(&lp->lock, flags); AINTMASK(0); - if(lp->next_tx == -1) + if (lp->next_tx == -1) txbuf = get_arcbuf(dev); else { txbuf = -1; @@ -594,9 +594,9 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, if (proto->continue_tx && proto->continue_tx(dev, txbuf)) { - BUGMSG(D_NORMAL, - "bug! continue_tx finished the first time! " - "(proto='%c')\n", proto->suffix); + BUGMSG(D_NORMAL, + "bug! continue_tx finished the first time! " + "(proto='%c')\n", proto->suffix); } } retval = NETDEV_TX_OK; @@ -606,14 +606,14 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, freeskb = 0; } - BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__func__,ASTATUS()); + BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, ASTATUS()); /* make sure we didn't ignore a TX IRQ while we were in here */ AINTMASK(0); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); - lp->intmask |= TXFREEflag|EXCNAKflag; + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + lp->intmask |= TXFREEflag | EXCNAKflag; AINTMASK(lp->intmask); - BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__func__,ASTATUS()); + BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, ASTATUS()); spin_unlock_irqrestore(&lp->lock, flags); if (freeskb) { @@ -649,7 +649,7 @@ static int go_tx(struct net_device *dev) lp->lasttrans_dest = lp->lastload_dest; lp->lastload_dest = 0; lp->excnak_pending = 0; - lp->intmask |= TXFREEflag|EXCNAKflag; + lp->intmask |= TXFREEflag | EXCNAKflag; return 1; } @@ -676,12 +676,12 @@ void arcnet_timeout(struct net_device *dev) /* make sure we didn't miss a TX or a EXC NAK IRQ */ AINTMASK(0); - lp->intmask |= TXFREEflag|EXCNAKflag; + lp->intmask |= TXFREEflag | EXCNAKflag; AINTMASK(lp->intmask); - + spin_unlock_irqrestore(&lp->lock, flags); - if (time_after(jiffies, lp->last_timeout + 10*HZ)) { + if (time_after(jiffies, lp->last_timeout + 10 * HZ)) { BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n", msg, status, lp->intmask, lp->lasttrans_dest); lp->last_timeout = jiffies; @@ -710,7 +710,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) lp = netdev_priv(dev); BUG_ON(!lp); - + spin_lock(&lp->lock); /* @@ -731,16 +731,16 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) boguscount = 5; do { status = ASTATUS(); - diagstatus = (status >> 8) & 0xFF; + diagstatus = (status >> 8) & 0xFF; BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n", - __FILE__,__LINE__,__func__,status); + __FILE__, __LINE__, __func__, status); didsomething = 0; /* * RESET flag was enabled - card is resetting and if RX is * disabled, it's NOT because we just got a packet. - * + * * The card is in an undefined state. Clear it out and start over. */ if (status & RESETflag) { @@ -751,14 +751,14 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) /* get out of the interrupt handler! */ break; } - /* + /* * RX is inhibited - we must have received something. Prepare to * receive into the next buffer. - * + * * We don't actually copy the received packet from the card until * after the transmit handler runs (and possibly launches the next * tx); this should improve latency slightly if we get both types - * of interrupts at once. + * of interrupts at once. */ recbuf = -1; if (status & lp->intmask & NORXflag) { @@ -775,27 +775,27 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) didsomething++; } - if((diagstatus & EXCNAKflag)) { + if ((diagstatus & EXCNAKflag)) { BUGMSG(D_DURING, "EXCNAK IRQ (diagstat=%Xh)\n", diagstatus); - ACOMMAND(NOTXcmd); /* disable transmit */ - lp->excnak_pending = 1; + ACOMMAND(NOTXcmd); /* disable transmit */ + lp->excnak_pending = 1; - ACOMMAND(EXCNAKclear); + ACOMMAND(EXCNAKclear); lp->intmask &= ~(EXCNAKflag); - didsomething++; - } + didsomething++; + } /* a transmit finished, and we're interested in it. */ if ((status & lp->intmask & TXFREEflag) || lp->timed_out) { - lp->intmask &= ~(TXFREEflag|EXCNAKflag); + lp->intmask &= ~(TXFREEflag | EXCNAKflag); BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status); if (lp->cur_tx != -1 && !lp->timed_out) { - if(!(status & TXACKflag)) { + if (!(status & TXACKflag)) { if (lp->lasttrans_dest != 0) { BUGMSG(D_EXTRA, "transmit was not acknowledged! " @@ -813,16 +813,16 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if (lp->outgoing.proto && lp->outgoing.proto->ack_tx) { - int ackstatus; - if(status & TXACKflag) - ackstatus=2; - else if(lp->excnak_pending) - ackstatus=1; - else - ackstatus=0; - - lp->outgoing.proto - ->ack_tx(dev, ackstatus); + int ackstatus; + if (status & TXACKflag) + ackstatus = 2; + else if (lp->excnak_pending) + ackstatus = 1; + else + ackstatus = 0; + + lp->outgoing.proto + ->ack_tx(dev, ackstatus); } } if (lp->cur_tx != -1) @@ -842,11 +842,11 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if (lp->outgoing.proto->continue_tx(dev, txbuf)) { /* that was the last segment */ dev->stats.tx_bytes += lp->outgoing.skb->len; - if(!lp->outgoing.proto->ack_tx) - { - dev_kfree_skb_irq(lp->outgoing.skb); - lp->outgoing.proto = NULL; - } + if (!lp->outgoing.proto->ack_tx) + { + dev_kfree_skb_irq(lp->outgoing.skb); + lp->outgoing.proto = NULL; + } } lp->next_tx = txbuf; } @@ -871,8 +871,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n", status); /* MYRECON bit is at bit 7 of diagstatus */ - if(diagstatus & 0x80) - BUGMSG(D_RECON,"Put out that recon myself\n"); + if (diagstatus & 0x80) + BUGMSG(D_RECON, "Put out that recon myself\n"); /* is the RECON info empty or old? */ if (!lp->first_recon || !lp->last_recon || @@ -889,7 +889,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) BUGMSG(D_DURING, "recon: counter=%d, time=%lds, net=%d\n", lp->num_recons, - (lp->last_recon - lp->first_recon) / HZ, + (lp->last_recon - lp->first_recon) / HZ, lp->network_down); /* if network is marked up; @@ -911,7 +911,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) } } } else if (lp->network_down && - time_after(jiffies, lp->last_recon + HZ * 10)) { + time_after(jiffies, lp->last_recon + HZ * 10)) { if (lp->network_down) BUGMSG(D_NORMAL, "cabling restored?\n"); lp->first_recon = lp->last_recon = 0; @@ -920,7 +920,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) BUGMSG(D_DURING, "not recon: clearing counters anyway.\n"); } - if(didsomething) { + if (didsomething) { retval |= IRQ_HANDLED; } } @@ -934,7 +934,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) AINTMASK(0); udelay(1); AINTMASK(lp->intmask); - + spin_unlock(&lp->lock); return retval; } @@ -1007,7 +1007,7 @@ static void null_rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) { BUGMSG(D_PROTO, - "rx: don't know how to deal with proto %02Xh from host %02Xh.\n", + "rx: don't know how to deal with proto %02Xh from host %02Xh.\n", pkthdr->soft.rfc1201.proto, pkthdr->hard.source); } diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 42fce91b71fc..95a6cf07965c 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -71,12 +71,12 @@ static void rx(struct net_device *dev, int bufnum, /* use these variables to be sure we count in bytes, not in sizeof(struct archdr) */ - pktbuf=(char*)pkt; - pkthdrbuf=(char*)pkthdr; - memcpy(pktbuf, pkthdrbuf, ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto)); - memcpy(pktbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto)+sizeof(int), - pkthdrbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto), - sizeof(struct archdr)-ARC_HDR_SIZE-sizeof(pkt->soft.cap.proto)); + pktbuf = (char *)pkt; + pkthdrbuf = (char *)pkthdr; + memcpy(pktbuf, pkthdrbuf, ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto)); + memcpy(pktbuf + ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto) + sizeof(int), + pkthdrbuf + ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto), + sizeof(struct archdr) - ARC_HDR_SIZE - sizeof(pkt->soft.cap.proto)); if (length > sizeof(pkt->soft)) lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft), @@ -101,10 +101,10 @@ static int build_header(struct sk_buff *skb, uint8_t daddr) { int hdr_size = ARC_HDR_SIZE; - struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); + struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size); BUGMSG(D_PROTO, "Preparing header for cap packet %x.\n", - *((int*)&pkt->soft.cap.cookie[0])); + *((int *)&pkt->soft.cap.cookie[0])); /* * Set the source hardware address. * @@ -148,7 +148,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, lp->next_tx, lp->cur_tx, bufnum); BUGMSG(D_PROTO, "Sending for cap packet %x.\n", - *((int*)&pkt->soft.cap.cookie[0])); + *((int *)&pkt->soft.cap.cookie[0])); if (length > XMTU) { /* should never happen! other people already check for this. */ @@ -166,7 +166,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, hard->offset[0] = ofs = 256 - length; BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", - length,ofs); + length, ofs); /* Copy the arcnet-header + the protocol byte down: */ lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); @@ -175,8 +175,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, /* Skip the extra integer we have written into it as a cookie but write the rest of the message: */ - lp->hw.copy_to_card(dev, bufnum, ofs+1, - ((unsigned char*)&pkt->soft.cap.mes),length-1); + lp->hw.copy_to_card(dev, bufnum, ofs + 1, + ((unsigned char *)&pkt->soft.cap.mes), length - 1); lp->lastload_dest = hard->dest; @@ -188,21 +188,21 @@ static int ack_tx(struct net_device *dev, int acked) struct arcnet_local *lp = netdev_priv(dev); struct sk_buff *ackskb; struct archdr *ackpkt; - int length=sizeof(struct arc_cap); + int length = sizeof(struct arc_cap); BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n", - lp->outgoing.skb->protocol, acked); + lp->outgoing.skb->protocol, acked); BUGLVL(D_SKB) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx"); /* Now alloc a skb to send back up through the layers: */ - ackskb = alloc_skb(length + ARC_HDR_SIZE , GFP_ATOMIC); + ackskb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (ackskb == NULL) { BUGMSG(D_NORMAL, "Memory squeeze, can't acknowledge.\n"); goto free_outskb; } - skb_put(ackskb, length + ARC_HDR_SIZE ); + skb_put(ackskb, length + ARC_HDR_SIZE); ackskb->dev = dev; skb_reset_mac_header(ackskb); @@ -212,10 +212,10 @@ static int ack_tx(struct net_device *dev, int acked) skb_copy_from_linear_data(lp->outgoing.skb, ackpkt, ARC_HDR_SIZE + sizeof(struct arc_cap)); ackpkt->soft.cap.proto = 0; /* using protocol 0 for acknowledge */ - ackpkt->soft.cap.mes.ack=acked; + ackpkt->soft.cap.mes.ack = acked; BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n", - *((int*)&ackpkt->soft.cap.cookie[0])); + *((int *)&ackpkt->soft.cap.cookie[0])); ackskb->protocol = cpu_to_be16(ETH_P_ARCNET); diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index 45c61a2c5fbd..d8746caf8e7a 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - COM20020 chipset support - * + * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. * Written 1999-2000 by Martin Mares . diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 96edc1346124..e0f489a117f1 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -1,7 +1,7 @@ /* * Linux ARCnet driver - COM20020 PCI support * Contemporary Controls PCI20 and SOHARD SH-ARC PCI - * + * * Written 1994-1999 by Avery Pennarun, * based on an ISA version by David Woodhouse. * Written 1999-2000 by Martin Mares . diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 1a8437842fbc..cd2a5ca56ce5 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - COM20020 chipset support - * + * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. * Written 1999 by Martin Mares . @@ -108,7 +108,7 @@ int com20020_check(struct net_device *dev) { SET_SUBADR(SUB_SETUP2); outb(lp->setup2, _XREG); - + /* must now write the magic "restart operation" command */ mdelay(1); outb(0x18, _COMMAND); @@ -117,7 +117,7 @@ int com20020_check(struct net_device *dev) lp->config = 0x21 | (lp->timeout << 3) | (lp->backplane << 2); /* set node ID to 0x42 (but transmitter is disabled, so it's okay) */ SETCONF; - outb(0x42, ioaddr + BUS_ALIGN*7); + outb(0x42, ioaddr + BUS_ALIGN * 7); status = ASTATUS(); @@ -129,7 +129,7 @@ int com20020_check(struct net_device *dev) /* Enable TX */ outb(0x39, _CONFIG); - outb(inb(ioaddr + BUS_ALIGN*8), ioaddr + BUS_ALIGN*7); + outb(inb(ioaddr + BUS_ALIGN * 8), ioaddr + BUS_ALIGN * 7); ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); @@ -193,7 +193,7 @@ int com20020_found(struct net_device *dev, int shared) lp->hw.close = com20020_close; if (!dev->dev_addr[0]) - dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN*8); /* FIXME: do this some other way! */ + dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN * 8); /* FIXME: do this some other way! */ SET_SUBADR(SUB_SETUP1); outb(lp->setup, _XREG); @@ -202,7 +202,7 @@ int com20020_found(struct net_device *dev, int shared) { SET_SUBADR(SUB_SETUP2); outb(lp->setup2, _XREG); - + /* must now write the magic "restart operation" command */ mdelay(1); outb(0x18, _COMMAND); @@ -232,7 +232,7 @@ int com20020_found(struct net_device *dev, int shared) BUGMSG(D_NORMAL, "Using extended timeout value of %d.\n", lp->timeout); BUGMSG(D_NORMAL, "Using CKP %d - data rate %s.\n", - lp->setup >> 1, + lp->setup >> 1, clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]); if (register_netdev(dev)) { @@ -243,9 +243,9 @@ int com20020_found(struct net_device *dev, int shared) } -/* +/* * Do a hardware reset on the card, and set up necessary registers. - * + * * This should be called as little as possible, because it disrupts the * token on the network (causes a RECON) and requires a significant delay. * @@ -258,15 +258,15 @@ static int com20020_reset(struct net_device *dev, int really_reset) u_char inbyte; BUGMSG(D_DEBUG, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n", - __FILE__,__LINE__,__func__,dev,lp,dev->name); + __FILE__, __LINE__, __func__, dev, lp, dev->name); BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS()); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2); /* power-up defaults */ SETCONF; - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (really_reset) { /* reset the card */ @@ -274,22 +274,22 @@ static int com20020_reset(struct net_device *dev, int really_reset) mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */ } /* clear flags & end reset */ - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); /* verify that the ARCnet signature byte is present */ - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); com20020_copy_from_card(dev, 0, 0, &inbyte, 1); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (inbyte != TESTvalue) { - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ ACOMMAND(CONFIGcmd | EXTconf); - BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__func__); + BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); /* done! return success. */ return 0; @@ -299,7 +299,7 @@ static int com20020_reset(struct net_device *dev, int really_reset) static void com20020_setmask(struct net_device *dev, int mask) { u_int ioaddr = dev->base_addr; - BUGMSG(D_DURING, "Setting mask to %x at %x\n",mask,ioaddr); + BUGMSG(D_DURING, "Setting mask to %x at %x\n", mask, ioaddr); AINTMASK(mask); } @@ -315,7 +315,7 @@ static int com20020_status(struct net_device *dev) { u_int ioaddr = dev->base_addr; - return ASTATUS() + (ADIAGSTATUS()<<8); + return ASTATUS() + (ADIAGSTATUS() << 8); } static void com20020_close(struct net_device *dev) diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c index 057d9582132a..f68752102379 100644 --- a/drivers/net/arcnet/com20020_cs.c +++ b/drivers/net/arcnet/com20020_cs.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - COM20020 PCMCIA support - * + * * Written 1994-1999 by Avery Pennarun, * based on an ISA version by David Woodhouse. * Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4) @@ -19,14 +19,14 @@ * Director, National Security Agency. This software may only be used * and distributed according to the terms of the GNU General Public License as * modified by SRC, incorporated herein by reference. - * + * * ********************** * Changes: * Arnaldo Carvalho de Melo - 08/08/2000 * - reorganize kmallocs in com20020_attach, checking all for failure * and releasing the previous allocations if one fails * ********************** - * + * * For more details, see drivers/net/arcnet.c * * ********************** @@ -53,33 +53,33 @@ static void regdump(struct net_device *dev) { #ifdef DEBUG - int ioaddr = dev->base_addr; - int count; - - netdev_dbg(dev, "register dump:\n"); - for (count = ioaddr; count < ioaddr + 16; count++) - { - if (!(count % 16)) - pr_cont("%04X:", count); - pr_cont(" %02X", inb(count)); - } - pr_cont("\n"); - - netdev_dbg(dev, "buffer0 dump:\n"); + int ioaddr = dev->base_addr; + int count; + + netdev_dbg(dev, "register dump:\n"); + for (count = ioaddr; count < ioaddr + 16; count++) + { + if (!(count % 16)) + pr_cont("%04X:", count); + pr_cont(" %02X", inb(count)); + } + pr_cont("\n"); + + netdev_dbg(dev, "buffer0 dump:\n"); /* set up the address register */ - count = 0; + count = 0; outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI); outb(count & 0xff, _ADDR_LO); - - for (count = 0; count < 256+32; count++) - { - if (!(count % 16)) - pr_cont("%04X:", count); - - /* copy the data */ - pr_cont(" %02X", inb(_MEMDATA)); - } - pr_cont("\n"); + + for (count = 0; count < 256 + 32; count++) + { + if (!(count % 16)) + pr_cont("%04X:", count); + + /* copy the data */ + pr_cont(" %02X", inb(_MEMDATA)); + } + pr_cont("\n"); #endif } @@ -114,169 +114,169 @@ static void com20020_detach(struct pcmcia_device *p_dev); static int com20020_probe(struct pcmcia_device *p_dev) { - struct com20020_dev *info; - struct net_device *dev; - struct arcnet_local *lp; + struct com20020_dev *info; + struct net_device *dev; + struct arcnet_local *lp; - dev_dbg(&p_dev->dev, "com20020_attach()\n"); + dev_dbg(&p_dev->dev, "com20020_attach()\n"); - /* Create new network device */ - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - goto fail_alloc_info; + /* Create new network device */ + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + goto fail_alloc_info; - dev = alloc_arcdev(""); - if (!dev) - goto fail_alloc_dev; + dev = alloc_arcdev(""); + if (!dev) + goto fail_alloc_dev; - lp = netdev_priv(dev); - lp->timeout = timeout; - lp->backplane = backplane; - lp->clockp = clockp; - lp->clockm = clockm & 3; - lp->hw.owner = THIS_MODULE; + lp = netdev_priv(dev); + lp->timeout = timeout; + lp->backplane = backplane; + lp->clockp = clockp; + lp->clockm = clockm & 3; + lp->hw.owner = THIS_MODULE; - /* fill in our module parameters as defaults */ - dev->dev_addr[0] = node; + /* fill in our module parameters as defaults */ + dev->dev_addr[0] = node; - p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - p_dev->resource[0]->end = 16; - p_dev->config_flags |= CONF_ENABLE_IRQ; + p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + p_dev->resource[0]->end = 16; + p_dev->config_flags |= CONF_ENABLE_IRQ; - info->dev = dev; - p_dev->priv = info; + info->dev = dev; + p_dev->priv = info; - return com20020_config(p_dev); + return com20020_config(p_dev); fail_alloc_dev: - kfree(info); + kfree(info); fail_alloc_info: - return -ENOMEM; + return -ENOMEM; } /* com20020_attach */ static void com20020_detach(struct pcmcia_device *link) { - struct com20020_dev *info = link->priv; - struct net_device *dev = info->dev; + struct com20020_dev *info = link->priv; + struct net_device *dev = info->dev; - dev_dbg(&link->dev, "detach...\n"); + dev_dbg(&link->dev, "detach...\n"); - dev_dbg(&link->dev, "com20020_detach\n"); + dev_dbg(&link->dev, "com20020_detach\n"); - dev_dbg(&link->dev, "unregister...\n"); + dev_dbg(&link->dev, "unregister...\n"); - unregister_netdev(dev); + unregister_netdev(dev); - /* - * this is necessary because we register our IRQ separately - * from card services. - */ - if (dev->irq) - free_irq(dev->irq, dev); + /* + * this is necessary because we register our IRQ separately + * from card services. + */ + if (dev->irq) + free_irq(dev->irq, dev); - com20020_release(link); + com20020_release(link); - /* Unlink device structure, free bits */ - dev_dbg(&link->dev, "unlinking...\n"); - if (link->priv) - { - dev = info->dev; - if (dev) + /* Unlink device structure, free bits */ + dev_dbg(&link->dev, "unlinking...\n"); + if (link->priv) { - dev_dbg(&link->dev, "kfree...\n"); - free_netdev(dev); + dev = info->dev; + if (dev) + { + dev_dbg(&link->dev, "kfree...\n"); + free_netdev(dev); + } + dev_dbg(&link->dev, "kfree2...\n"); + kfree(info); } - dev_dbg(&link->dev, "kfree2...\n"); - kfree(info); - } } /* com20020_detach */ static int com20020_config(struct pcmcia_device *link) { - struct arcnet_local *lp; - struct com20020_dev *info; - struct net_device *dev; - int i, ret; - int ioaddr; + struct arcnet_local *lp; + struct com20020_dev *info; + struct net_device *dev; + int i, ret; + int ioaddr; + + info = link->priv; + dev = info->dev; - info = link->priv; - dev = info->dev; + dev_dbg(&link->dev, "config...\n"); - dev_dbg(&link->dev, "config...\n"); + dev_dbg(&link->dev, "com20020_config\n"); - dev_dbg(&link->dev, "com20020_config\n"); + dev_dbg(&link->dev, "baseport1 is %Xh\n", + (unsigned int)link->resource[0]->start); - dev_dbg(&link->dev, "baseport1 is %Xh\n", - (unsigned int) link->resource[0]->start); + i = -ENODEV; + link->io_lines = 16; - i = -ENODEV; - link->io_lines = 16; + if (!link->resource[0]->start) + { + for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) + { + link->resource[0]->start = ioaddr; + i = pcmcia_request_io(link); + if (i == 0) + break; + } + } + else + i = pcmcia_request_io(link); + + if (i != 0) + { + dev_dbg(&link->dev, "requestIO failed totally!\n"); + goto failed; + } + + ioaddr = dev->base_addr = link->resource[0]->start; + dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr); + + dev_dbg(&link->dev, "request IRQ %d\n", + link->irq); + if (!link->irq) + { + dev_dbg(&link->dev, "requestIRQ failed totally!\n"); + goto failed; + } - if (!link->resource[0]->start) - { - for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) + dev->irq = link->irq; + + ret = pcmcia_enable_device(link); + if (ret) + goto failed; + + if (com20020_check(dev)) { - link->resource[0]->start = ioaddr; - i = pcmcia_request_io(link); - if (i == 0) - break; + regdump(dev); + goto failed; } - } - else - i = pcmcia_request_io(link); - - if (i != 0) - { - dev_dbg(&link->dev, "requestIO failed totally!\n"); - goto failed; - } - - ioaddr = dev->base_addr = link->resource[0]->start; - dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr); - - dev_dbg(&link->dev, "request IRQ %d\n", - link->irq); - if (!link->irq) - { - dev_dbg(&link->dev, "requestIRQ failed totally!\n"); - goto failed; - } - - dev->irq = link->irq; - - ret = pcmcia_enable_device(link); - if (ret) - goto failed; - - if (com20020_check(dev)) - { - regdump(dev); - goto failed; - } - - lp = netdev_priv(dev); - lp->card_name = "PCMCIA COM20020"; - lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ - - SET_NETDEV_DEV(dev, &link->dev); - - i = com20020_found(dev, 0); /* calls register_netdev */ - - if (i != 0) { - dev_notice(&link->dev, - "com20020_found() failed\n"); - goto failed; - } - - netdev_dbg(dev, "port %#3lx, irq %d\n", - dev->base_addr, dev->irq); - return 0; + + lp = netdev_priv(dev); + lp->card_name = "PCMCIA COM20020"; + lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ + + SET_NETDEV_DEV(dev, &link->dev); + + i = com20020_found(dev, 0); /* calls register_netdev */ + + if (i != 0) { + dev_notice(&link->dev, + "com20020_found() failed\n"); + goto failed; + } + + netdev_dbg(dev, "port %#3lx, irq %d\n", + dev->base_addr, dev->irq); + return 0; failed: - dev_dbg(&link->dev, "com20020_config failed...\n"); - com20020_release(link); - return -ENODEV; + dev_dbg(&link->dev, "com20020_config failed...\n"); + com20020_release(link); + return -ENODEV; } /* com20020_config */ static void com20020_release(struct pcmcia_device *link) @@ -312,9 +312,9 @@ static int com20020_resume(struct pcmcia_device *link) static const struct pcmcia_device_id com20020_ids[] = { PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", - "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), + "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), PCMCIA_DEVICE_PROD_ID12("SoHard AG", - "SH ARC PCMCIA", 0xf8991729, 0x69dff0c7), + "SH ARC PCMCIA", 0xf8991729, 0x69dff0c7), PCMCIA_DEVICE_NULL }; MODULE_DEVICE_TABLE(pcmcia, com20020_ids); diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 487d780ebbdf..23ac9edbe91c 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - COM90xx chipset (IO-mapped buffers) - * + * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. * Written 1999-2000 by Martin Mares . @@ -60,23 +60,23 @@ static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offse #define ARCNET_TOTAL_SIZE 16 /* COM 9026 controller chip --> ARCnet register addresses */ -#define _INTMASK (ioaddr+0) /* writable */ -#define _STATUS (ioaddr+0) /* readable */ -#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ -#define _RESET (ioaddr+8) /* software reset (on read) */ -#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */ -#define _ADDR_HI (ioaddr+15) /* Control registers for said */ -#define _ADDR_LO (ioaddr+14) -#define _CONFIG (ioaddr+2) /* Configuration register */ +#define _INTMASK (ioaddr + 0) /* writable */ +#define _STATUS (ioaddr + 0) /* readable */ +#define _COMMAND (ioaddr + 1) /* writable, returns random vals on read (?) */ +#define _RESET (ioaddr + 8) /* software reset (on read) */ +#define _MEMDATA (ioaddr + 12) /* Data port for IO-mapped memory */ +#define _ADDR_HI (ioaddr + 15) /* Control registers for said */ +#define _ADDR_LO (ioaddr + 14) +#define _CONFIG (ioaddr + 2) /* Configuration register */ #undef ASTATUS #undef ACOMMAND #undef AINTMASK #define ASTATUS() inb(_STATUS) -#define ACOMMAND(cmd) outb((cmd),_COMMAND) -#define AINTMASK(msk) outb((msk),_INTMASK) -#define SETCONF() outb((lp->config),_CONFIG) +#define ACOMMAND(cmd) outb((cmd), _COMMAND) +#define AINTMASK(msk) outb((msk), _INTMASK) +#define SETCONF() outb((lp->config), _CONFIG) /**************************************************************************** diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index b80fbe40aa0e..a4c5d5909b13 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - COM90xx chipset (memory-mapped buffers) - * + * * Written 1994-1999 by Avery Pennarun. * Written 1999 by Martin Mares . * Derived from skeleton.c by Donald Becker. @@ -77,25 +77,25 @@ static int numcards; /* Amount of I/O memory used by the card */ #define BUFFER_SIZE (512) -#define MIRROR_SIZE (BUFFER_SIZE*4) +#define MIRROR_SIZE (BUFFER_SIZE * 4) /* COM 9026 controller chip --> ARCnet register addresses */ -#define _INTMASK (ioaddr+0) /* writable */ -#define _STATUS (ioaddr+0) /* readable */ -#define _COMMAND (ioaddr+1) /* writable, returns random vals on read (?) */ -#define _CONFIG (ioaddr+2) /* Configuration register */ -#define _RESET (ioaddr+8) /* software reset (on read) */ -#define _MEMDATA (ioaddr+12) /* Data port for IO-mapped memory */ -#define _ADDR_HI (ioaddr+15) /* Control registers for said */ -#define _ADDR_LO (ioaddr+14) +#define _INTMASK (ioaddr + 0) /* writable */ +#define _STATUS (ioaddr + 0) /* readable */ +#define _COMMAND (ioaddr + 1) /* writable, returns random vals on read (?) */ +#define _CONFIG (ioaddr + 2) /* Configuration register */ +#define _RESET (ioaddr + 8) /* software reset (on read) */ +#define _MEMDATA (ioaddr + 12) /* Data port for IO-mapped memory */ +#define _ADDR_HI (ioaddr + 15) /* Control registers for said */ +#define _ADDR_LO (ioaddr + 14) #undef ASTATUS #undef ACOMMAND #undef AINTMASK #define ASTATUS() inb(_STATUS) -#define ACOMMAND(cmd) outb((cmd),_COMMAND) -#define AINTMASK(msk) outb((msk),_INTMASK) +#define ACOMMAND(cmd) outb((cmd), _COMMAND) +#define AINTMASK(msk) outb((msk), _INTMASK) static int com90xx_skip_probe __initdata = 0; @@ -127,12 +127,12 @@ static void __init com90xx_probe(void) if (!io && !irq && !shmem && !*device && com90xx_skip_probe) return; - shmems = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(unsigned long), + shmems = kzalloc(((0x100000 - 0xa0000) / 0x800) * sizeof(unsigned long), GFP_KERNEL); if (!shmems) return; - iomem = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(void __iomem *), - GFP_KERNEL); + iomem = kzalloc(((0x100000 - 0xa0000) / 0x800) * sizeof(void __iomem *), + GFP_KERNEL); if (!iomem) { kfree(shmems); return; @@ -579,7 +579,7 @@ static void com90xx_setmask(struct net_device *dev, int mask) /* * Do a hardware reset on the card, and set up necessary registers. - * + * * This should be called as little as possible, because it disrupts the * token on the network (causes a RECON) and requires a significant delay. * diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index f81db4070a57..ae1ded286897 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - RFC1051 ("simple" standard) packet encapsulation - * + * * Written 1994-1999 by Avery Pennarun. * Derived from skeleton.c by Donald Becker. * @@ -84,12 +84,12 @@ MODULE_LICENSE("GPL"); /* * Determine a packet's protocol ID. - * + * * With ARCnet we have to convert everything to Ethernet-style stuff. */ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) { - struct archdr *pkt = (struct archdr *) skb->data; + struct archdr *pkt = (struct archdr *)skb->data; struct arc_rfc1051 *soft = &pkt->soft.rfc1051; int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE; @@ -146,7 +146,7 @@ static void rx(struct net_device *dev, int bufnum, skb_put(skb, length + ARC_HDR_SIZE); skb->dev = dev; - pkt = (struct archdr *) skb->data; + pkt = (struct archdr *)skb->data; /* up to sizeof(pkt->soft) has already been copied from the card */ memcpy(pkt, pkthdr, sizeof(struct archdr)); @@ -169,7 +169,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, uint8_t daddr) { int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE; - struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); + struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size); struct arc_rfc1051 *soft = &pkt->soft.rfc1051; /* set the protocol ID according to RFC1051 */ @@ -201,7 +201,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, /* see linux/net/ethernet/eth.c to see where I got the following */ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - /* + /* * FIXME: fill in the last byte of the dest ipaddr here to better * comply with RFC1051 in "noarp" mode. */ diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index b71431aae084..bf2a8cb3f0e2 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - RFC1201 (standard) packet encapsulation - * + * * Written 1994-1999 by Avery Pennarun. * Derived from skeleton.c by Donald Becker. * @@ -86,12 +86,12 @@ module_exit(arcnet_rfc1201_exit); /* * Determine a packet's protocol ID. - * + * * With ARCnet we have to convert everything to Ethernet-style stuff. */ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) { - struct archdr *pkt = (struct archdr *) skb->data; + struct archdr *pkt = (struct archdr *)skb->data; struct arc_rfc1201 *soft = &pkt->soft.rfc1201; int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE; @@ -169,7 +169,7 @@ static void rx(struct net_device *dev, int bufnum, if (in->skb) { /* already assembling one! */ BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", - in->sequence, soft->split_flag, soft->sequence); + in->sequence, soft->split_flag, soft->sequence); lp->rfc1201.aborted_seq = soft->sequence; dev_kfree_skb_irq(in->skb); dev->stats.rx_errors++; @@ -187,7 +187,7 @@ static void rx(struct net_device *dev, int bufnum, skb_put(skb, length + ARC_HDR_SIZE); skb->dev = dev; - pkt = (struct archdr *) skb->data; + pkt = (struct archdr *)skb->data; soft = &pkt->soft.rfc1201; /* up to sizeof(pkt->soft) has already been copied from the card */ @@ -203,11 +203,11 @@ static void rx(struct net_device *dev, int bufnum, * (which is impossible to fumble) and insert it ourselves. */ if (soft->proto == ARC_P_ARP) { - struct arphdr *arp = (struct arphdr *) soft->payload; + struct arphdr *arp = (struct arphdr *)soft->payload; /* make sure addresses are the right length */ if (arp->ar_hln == 1 && arp->ar_pln == 4) { - uint8_t *cptr = (uint8_t *) arp + sizeof(struct arphdr); + uint8_t *cptr = (uint8_t *)arp + sizeof(struct arphdr); if (!*cptr) { /* is saddr = 00? */ BUGMSG(D_EXTRA, @@ -274,7 +274,7 @@ static void rx(struct net_device *dev, int bufnum, dev_kfree_skb_irq(in->skb); } in->sequence = soft->sequence; - in->numpackets = ((unsigned) soft->split_flag >> 1) + 2; + in->numpackets = ((unsigned)soft->split_flag >> 1) + 2; in->lastpacket = 1; if (in->numpackets > 16) { @@ -294,7 +294,7 @@ static void rx(struct net_device *dev, int bufnum, return; } skb->dev = dev; - pkt = (struct archdr *) skb->data; + pkt = (struct archdr *)skb->data; soft = &pkt->soft.rfc1201; memcpy(pkt, pkthdr, ARC_HDR_SIZE + RFC1201_HDR_SIZE); @@ -302,7 +302,7 @@ static void rx(struct net_device *dev, int bufnum, soft->split_flag = 0; /* end result won't be split */ } else { /* not first packet */ - int packetnum = ((unsigned) soft->split_flag >> 1) + 1; + int packetnum = ((unsigned)soft->split_flag >> 1) + 1; /* * if we're not assembling, there's no point trying to @@ -341,7 +341,7 @@ static void rx(struct net_device *dev, int bufnum, in->lastpacket = in->numpackets = 0; return; } - pkt = (struct archdr *) in->skb->data; + pkt = (struct archdr *)in->skb->data; soft = &pkt->soft.rfc1201; } @@ -357,10 +357,10 @@ static void rx(struct net_device *dev, int bufnum, in->skb = NULL; in->lastpacket = in->numpackets = 0; - BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (unsplit)\n", - skb->len, pkt->hard.source); - BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n", - skb->len, pkt->hard.source); + BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (unsplit)\n", + skb->len, pkt->hard.source); + BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n", + skb->len, pkt->hard.source); BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); skb->protocol = type_trans(skb, dev); @@ -376,7 +376,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, { struct arcnet_local *lp = netdev_priv(dev); int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE; - struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); + struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size); struct arc_rfc1201 *soft = &pkt->soft.rfc1201; /* set the protocol ID according to RFC1201 */ @@ -424,7 +424,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, /* see linux/net/ethernet/eth.c to see where I got the following */ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - /* + /* * FIXME: fill in the last byte of the dest ipaddr here to better * comply with RFC1051 in "noarp" mode. For now, always broadcasting * will probably at least get packets sent out :) @@ -517,7 +517,7 @@ static int continue_tx(struct net_device *dev, int bufnum) int seglen; BUGMSG(D_DURING, - "rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n", + "rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n", out->segnum, out->numsegs, soft->sequence); /* the "new" soft header comes right before the data chunk */ -- cgit v1.2.3 From 01a1d5ac4e1a5890fd6c0d0ae900e1b6e4f851d6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:48 -0700 Subject: arcnet: Add and remove blank lines Use a more current kernel line style. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 5 ----- drivers/net/arcnet/arc-rimi.c | 8 +++----- drivers/net/arcnet/arcnet.c | 23 +++-------------------- drivers/net/arcnet/capmode.c | 3 --- drivers/net/arcnet/com20020-isa.c | 1 - drivers/net/arcnet/com20020-pci.c | 2 -- drivers/net/arcnet/com20020.c | 8 ++------ drivers/net/arcnet/com20020_cs.c | 4 +--- drivers/net/arcnet/com90io.c | 12 +----------- drivers/net/arcnet/com90xx.c | 13 +++---------- drivers/net/arcnet/rfc1051.c | 7 ------- drivers/net/arcnet/rfc1201.c | 8 -------- 12 files changed, 13 insertions(+), 81 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 49f5819a0367..251a98b0bf78 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -35,7 +35,6 @@ #define VERSION "arcnet: raw mode (`r') encapsulation support loaded.\n" - static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); static int build_header(struct sk_buff *skb, struct net_device *dev, @@ -54,7 +53,6 @@ static struct ArcProto rawmode_proto = .ack_tx = NULL }; - static int __init arcnet_raw_init(void) { int count; @@ -83,7 +81,6 @@ module_exit(arcnet_raw_exit); MODULE_LICENSE("GPL"); - /* packet receiver */ static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) @@ -127,7 +124,6 @@ static void rx(struct net_device *dev, int bufnum, netif_rx(skb); } - /* * Create the ARCnet hard/soft headers for raw mode. * There aren't any soft headers in raw mode - not even the protocol id. @@ -163,7 +159,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, return hdr_size; /* success */ } - static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum) { diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 4644d46b6a5f..e8c15016bb8e 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -36,10 +36,8 @@ #include #include - #define VERSION "arcnet: RIM I (entirely mem-mapped) support\n" - /* Internal function declarations */ static int arcrimi_probe(struct net_device *dev); @@ -78,7 +76,6 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse #define AINTMASK(msk) writeb((msk), _INTMASK) #define SETCONF() writeb(lp->config, _CONFIG) - /* * We cannot probe for a RIM I card; one reason is I don't know how to reset * them. In fact, we can't even get their node ID automatically. So, we @@ -249,7 +246,6 @@ err_free_irq: return -EIO; } - /* * Do a hardware reset on the card, and set up necessary registers. * @@ -308,15 +304,16 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset, { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; + TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } - static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; + TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); } @@ -374,6 +371,7 @@ static void __exit arc_rimi_exit(void) static int __init arcrimi_setup(char *s) { int ints[8]; + s = get_options(s, 8, ints); if (!ints[0]) return 1; diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 2a594d1c4b55..bb49753f8203 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -168,7 +168,6 @@ void arcnet_dump_skb(struct net_device *dev, EXPORT_SYMBOL(arcnet_dump_skb); #endif - /* * Dump the contents of an ARCnet buffer */ @@ -206,7 +205,6 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, #endif - /* * Unregister a protocol driver from the arc_proto_map. Protocol drivers * are responsible for registering themselves, but the unregister routine @@ -229,7 +227,6 @@ void arcnet_unregister_proto(struct ArcProto *proto) } } - /* * Add a buffer to the queue. Only the interrupt handler is allowed to do * this, unless interrupts are disabled. @@ -254,7 +251,6 @@ static void release_arcbuf(struct net_device *dev, int bufnum) } } - /* * Get a buffer from the queue. If this returns -1, there are no buffers * available. @@ -281,7 +277,6 @@ static int get_arcbuf(struct net_device *dev) } } - BUGLVL(D_DURING) { BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf); for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) @@ -293,7 +288,6 @@ static int get_arcbuf(struct net_device *dev) return buf; } - static int choose_mtu(void) { int count, mtu = 65535; @@ -348,6 +342,7 @@ struct net_device *alloc_arcdev(const char *name) arcdev_setup); if (dev) { struct arcnet_local *lp = netdev_priv(dev); + spin_lock_init(&lp->lock); } @@ -380,7 +375,6 @@ int arcnet_open(struct net_device *dev) BUGMSG2(D_PROTO, "\n"); } - BUGMSG(D_INIT, "arcnet_open: resetting card.\n"); /* try to put the card in a defined state - if it fails the first @@ -437,7 +431,6 @@ int arcnet_open(struct net_device *dev) ACOMMAND(CFLAGScmd | RESETclear); } - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); /* make sure we're ready to receive IRQ's. */ AINTMASK(0); @@ -459,7 +452,6 @@ int arcnet_open(struct net_device *dev) return error; } - /* The inverse routine to arcnet_open - shuts down the card. */ int arcnet_close(struct net_device *dev) { @@ -479,7 +471,6 @@ int arcnet_close(struct net_device *dev) return 0; } - static int arcnet_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, const void *saddr, unsigned len) @@ -498,7 +489,6 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, BUGMSG(D_NORMAL, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n", skb->len, len); - /* Type is host order - ? */ if (type == ETH_P_ARCNET) { proto = arc_raw_proto; @@ -622,7 +612,6 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, return retval; /* no need to try again */ } - /* * Actually start transmitting a packet that was loaded into a buffer * by prepare_tx. This should _only_ be called by the interrupt handler. @@ -654,7 +643,6 @@ static int go_tx(struct net_device *dev) return 1; } - /* Called by the kernel when transmit times out */ void arcnet_timeout(struct net_device *dev) { @@ -691,7 +679,6 @@ void arcnet_timeout(struct net_device *dev) netif_wake_queue(dev); } - /* * The typical workload of the driver: Handle the network interface * interrupts. Establish which device needs attention, and call the correct @@ -787,7 +774,6 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) didsomething++; } - /* a transmit finished, and we're interested in it. */ if ((status & lp->intmask & TXFREEflag) || lp->timed_out) { lp->intmask &= ~(TXFREEflag | EXCNAKflag); @@ -814,6 +800,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if (lp->outgoing.proto && lp->outgoing.proto->ack_tx) { int ackstatus; + if (status & TXACKflag) ackstatus = 2; else if (lp->excnak_pending) @@ -838,6 +825,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) /* continue a split packet, if any */ if (lp->outgoing.proto && lp->outgoing.proto->continue_tx) { int txbuf = get_arcbuf(dev); + if (txbuf != -1) { if (lp->outgoing.proto->continue_tx(dev, txbuf)) { /* that was the last segment */ @@ -930,7 +918,6 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) ASTATUS(), boguscount); BUGMSG(D_DURING, "\n"); - AINTMASK(0); udelay(1); AINTMASK(lp->intmask); @@ -939,7 +926,6 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) return retval; } - /* * This is a generic packet receiver that calls arcnet??_rx depending on the * protocol ID found. @@ -1002,7 +988,6 @@ static void arcnet_rx(struct net_device *dev, int bufnum) arc_proto_map[soft->proto]->rx(dev, bufnum, &pkt, length); } - static void null_rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) { @@ -1011,7 +996,6 @@ static void null_rx(struct net_device *dev, int bufnum, pkthdr->soft.rfc1201.proto, pkthdr->hard.source); } - static int null_build_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, uint8_t daddr) { @@ -1025,7 +1009,6 @@ static int null_build_header(struct sk_buff *skb, struct net_device *dev, return 0; } - /* the "do nothing" prepare_tx function warns that there's nothing to do. */ static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum) diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 95a6cf07965c..02815ff891f2 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -90,7 +90,6 @@ static void rx(struct net_device *dev, int bufnum, netif_rx(skb); } - /* * Create the ARCnet hard/soft headers for cap mode. * There aren't any soft headers in cap mode - not even the protocol id. @@ -130,7 +129,6 @@ static int build_header(struct sk_buff *skb, return hdr_size; /* success */ } - static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum) { @@ -138,7 +136,6 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, struct arc_hardware *hard = &pkt->hard; int ofs; - /* hard header is not included in packet length */ length -= ARC_HDR_SIZE; /* And neither is the cookie field */ diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index d8746caf8e7a..c7d3377a45fe 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -43,7 +43,6 @@ #define VERSION "arcnet: COM20020 ISA support (by David Woodhouse et al.)\n" - /* * We cannot (yet) probe for an IO mapped card, although we can check that * it's where we were told it was, and even do autoirq. diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index e0f489a117f1..06621e95bd38 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -42,7 +42,6 @@ #include - #define VERSION "arcnet: COM20020 PCI support\n" /* Module parameters */ @@ -86,7 +85,6 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i INIT_LIST_HEAD(&priv->list_dev); - for (i = 0; i < ci->devcount; i++) { struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i]; struct com20020_dev *card; diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index cd2a5ca56ce5..c749af6db94e 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -70,7 +70,6 @@ static void com20020_copy_from_card(struct net_device *dev, int bufnum, TIME("insb", count, insb(_MEMDATA, buf, count)); } - static void com20020_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { @@ -84,7 +83,6 @@ static void com20020_copy_to_card(struct net_device *dev, int bufnum, TIME("outsb", count, outsb(_MEMDATA, buf, count)); } - /* Reset the card and check some basic stuff during the detection stage. */ int com20020_check(struct net_device *dev) { @@ -242,7 +240,6 @@ int com20020_found(struct net_device *dev, int shared) return 0; } - /* * Do a hardware reset on the card, and set up necessary registers. * @@ -295,22 +292,21 @@ static int com20020_reset(struct net_device *dev, int really_reset) return 0; } - static void com20020_setmask(struct net_device *dev, int mask) { u_int ioaddr = dev->base_addr; + BUGMSG(D_DURING, "Setting mask to %x at %x\n", mask, ioaddr); AINTMASK(mask); } - static void com20020_command(struct net_device *dev, int cmd) { u_int ioaddr = dev->base_addr; + ACOMMAND(cmd); } - static int com20020_status(struct net_device *dev) { u_int ioaddr = dev->base_addr; diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c index f68752102379..2eafb298626b 100644 --- a/drivers/net/arcnet/com20020_cs.c +++ b/drivers/net/arcnet/com20020_cs.c @@ -49,7 +49,6 @@ #define VERSION "arcnet: COM20020 PCMCIA support loaded.\n" - static void regdump(struct net_device *dev) { #ifdef DEBUG @@ -83,8 +82,6 @@ static void regdump(struct net_device *dev) #endif } - - /*====================================================================*/ /* Parameters that can be set with 'insmod' */ @@ -304,6 +301,7 @@ static int com20020_resume(struct pcmcia_device *link) if (link->open) { int ioaddr = dev->base_addr; struct arcnet_local *lp = netdev_priv(dev); + ARCRESET; } diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 23ac9edbe91c..11d2d0b4ccea 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -37,10 +37,8 @@ #include #include - #define VERSION "arcnet: COM90xx IO-mapped mode support (by David Woodhouse et el.)\n" - /* Internal function declarations */ static int com90io_found(struct net_device *dev); @@ -53,7 +51,6 @@ static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count); - /* Handy defines for ARCnet specific stuff */ /* The number of low I/O ports used by the card. */ @@ -78,7 +75,6 @@ static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offse #define AINTMASK(msk) outb((msk), _INTMASK) #define SETCONF() outb((lp->config), _CONFIG) - /**************************************************************************** * * * IO-mapped operation routines * @@ -111,7 +107,6 @@ static void put_buffer_byte(struct net_device *dev, unsigned offset, u_char datu #endif - static void get_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest) { int ioaddr = dev->base_addr; @@ -227,7 +222,6 @@ err_out: return -ENODEV; } - /* Set up the struct net_device associated with this card. Called after * probing succeeds. */ @@ -279,7 +273,6 @@ static int __init com90io_found(struct net_device *dev) return 0; } - /* * Do a hardware reset on the card, and set up necessary registers. * @@ -319,7 +312,6 @@ static int com90io_reset(struct net_device *dev, int really_reset) return 0; } - static void com90io_command(struct net_device *dev, int cmd) { short ioaddr = dev->base_addr; @@ -327,7 +319,6 @@ static void com90io_command(struct net_device *dev, int cmd) ACOMMAND(cmd); } - static int com90io_status(struct net_device *dev) { short ioaddr = dev->base_addr; @@ -335,7 +326,6 @@ static int com90io_status(struct net_device *dev) return ASTATUS(); } - static void com90io_setmask(struct net_device *dev, int mask) { short ioaddr = dev->base_addr; @@ -349,7 +339,6 @@ static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, TIME("put_whole_buffer", count, put_whole_buffer(dev, bufnum * 512 + offset, count, buf)); } - static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { @@ -369,6 +358,7 @@ MODULE_LICENSE("GPL"); static int __init com90io_setup(char *s) { int ints[4]; + s = get_options(s, 4, ints); if (!ints[0]) return 0; diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index a4c5d5909b13..f0f06a274045 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -35,10 +35,8 @@ #include #include - #define VERSION "arcnet: COM90xx chipset support\n" - /* Define this to speed up the autoprobe by assuming if only one io port and * shmem are left in the list at Stage 5, they must correspond to each * other. @@ -53,7 +51,6 @@ */ #undef FAST_PROBE - /* Internal function declarations */ static int com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *); static void com90xx_command(struct net_device *dev, int command); @@ -97,7 +94,6 @@ static int numcards; #define ACOMMAND(cmd) outb((cmd), _COMMAND) #define AINTMASK(msk) outb((msk), _INTMASK) - static int com90xx_skip_probe __initdata = 0; /* Module parameters */ @@ -308,6 +304,7 @@ static void __init com90xx_probe(void) numprint = -1; for (port = &ports[0]; port < ports + numports; port++) { int found = 0; + numprint++; numprint %= 8; if (!numprint) { @@ -552,7 +549,6 @@ err_free_dev: return -EIO; } - static void com90xx_command(struct net_device *dev, int cmd) { short ioaddr = dev->base_addr; @@ -560,7 +556,6 @@ static void com90xx_command(struct net_device *dev, int cmd) ACOMMAND(cmd); } - static int com90xx_status(struct net_device *dev) { short ioaddr = dev->base_addr; @@ -568,7 +563,6 @@ static int com90xx_status(struct net_device *dev) return ASTATUS(); } - static void com90xx_setmask(struct net_device *dev, int mask) { short ioaddr = dev->base_addr; @@ -576,7 +570,6 @@ static void com90xx_setmask(struct net_device *dev, int mask) AINTMASK(mask); } - /* * Do a hardware reset on the card, and set up necessary registers. * @@ -625,19 +618,19 @@ static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; + TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } - static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; + TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); } - MODULE_LICENSE("GPL"); static int __init com90xx_init(void) diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index ae1ded286897..49d35c972bca 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -34,7 +34,6 @@ #define VERSION "arcnet: RFC1051 \"simple standard\" (`s') encapsulation support loaded.\n" - static __be16 type_trans(struct sk_buff *skb, struct net_device *dev); static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); @@ -43,7 +42,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); - static struct ArcProto rfc1051_proto = { .suffix = 's', @@ -56,7 +54,6 @@ static struct ArcProto rfc1051_proto = .ack_tx = NULL }; - static int __init arcnet_rfc1051_init(void) { printk(VERSION); @@ -120,7 +117,6 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) return htons(ETH_P_IP); } - /* packet receiver */ static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) @@ -161,7 +157,6 @@ static void rx(struct net_device *dev, int bufnum, netif_rx(skb); } - /* * Create the ARCnet hard/soft headers for RFC1051. */ @@ -188,7 +183,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, return 0; } - /* * Set the source hardware address. * @@ -214,7 +208,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, return hdr_size; /* success */ } - static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum) { diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index bf2a8cb3f0e2..15f103a8a9db 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -34,7 +34,6 @@ MODULE_LICENSE("GPL"); #define VERSION "arcnet: RFC1201 \"standard\" (`a') encapsulation support loaded.\n" - static __be16 type_trans(struct sk_buff *skb, struct net_device *dev); static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); @@ -56,7 +55,6 @@ static struct ArcProto rfc1201_proto = .ack_tx = NULL }; - static int __init arcnet_rfc1201_init(void) { printk(VERSION); @@ -129,7 +127,6 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) return htons(ETH_P_IP); } - /* packet receiver */ static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) @@ -369,7 +366,6 @@ static void rx(struct net_device *dev, int bufnum, } } - /* Create the ARCnet hard/soft headers for RFC1201. */ static int build_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, uint8_t daddr) @@ -437,7 +433,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, return hdr_size; } - static void load_pkt(struct net_device *dev, struct arc_hardware *hard, struct arc_rfc1201 *soft, int softlen, int bufnum) { @@ -470,7 +465,6 @@ static void load_pkt(struct net_device *dev, struct arc_hardware *hard, lp->lastload_dest = hard->dest; } - static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum) { @@ -478,7 +472,6 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, const int maxsegsize = XMTU - RFC1201_HDR_SIZE; struct Outgoing *out; - BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", lp->next_tx, lp->cur_tx, bufnum); @@ -506,7 +499,6 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, return 1; /* done */ } - static int continue_tx(struct net_device *dev, int bufnum) { struct arcnet_local *lp = netdev_priv(dev); -- cgit v1.2.3 From 7f5e760c1b269044a4ba1b269263beca80ae2741 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:49 -0700 Subject: arcnet: Use normal kernel brace style Move braces normal kernel locations. Add missing braces. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 6 +++--- drivers/net/arcnet/arcnet.c | 38 +++++++++++++++----------------------- drivers/net/arcnet/capmode.c | 6 +++--- drivers/net/arcnet/com20020.c | 15 +++++++-------- drivers/net/arcnet/com20020_cs.c | 31 +++++++++++-------------------- drivers/net/arcnet/com90xx.c | 3 +-- drivers/net/arcnet/rfc1051.c | 10 +++++----- drivers/net/arcnet/rfc1201.c | 14 +++++++------- 8 files changed, 52 insertions(+), 71 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 251a98b0bf78..500b5bb2cff4 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -42,8 +42,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); -static struct ArcProto rawmode_proto = -{ +static struct ArcProto rawmode_proto = { .suffix = 'r', .mtu = XMTU, .rx = rx, @@ -183,8 +182,9 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, } else if (length > MTU) { hard->offset[0] = 0; hard->offset[1] = ofs = 512 - length - 3; - } else + } else { hard->offset[0] = ofs = 256 - length; + } BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", length, ofs); diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index bb49753f8203..24c0a6415023 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -72,8 +72,7 @@ static void arcnet_rx(struct net_device *dev, int bufnum); struct ArcProto *arc_proto_map[256], *arc_proto_default, *arc_bcast_proto, *arc_raw_proto; -static struct ArcProto arc_proto_null = -{ +static struct ArcProto arc_proto_null = { .suffix = '?', .mtu = XMTU, .is_ip = 0, @@ -264,14 +263,13 @@ static int get_arcbuf(struct net_device *dev) /* already in this function */ BUGMSG(D_NORMAL, "get_arcbuf: overlap (%d)!\n", lp->buf_lock.counter); - } - else { /* we can continue */ + } else { /* we can continue */ if (lp->next_buf >= 5) lp->next_buf -= 5; - if (lp->next_buf == lp->first_free_buf) + if (lp->next_buf == lp->first_free_buf) { BUGMSG(D_NORMAL, "get_arcbuf: BUG: no buffers are available??\n"); - else { + } else { buf = lp->buf_queue[lp->next_buf++]; lp->next_buf %= 5; } @@ -330,7 +328,6 @@ static void arcdev_setup(struct net_device *dev) /* New-style flags. */ dev->flags = IFF_BROADCAST; - } struct net_device *alloc_arcdev(const char *name) @@ -494,8 +491,7 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, proto = arc_raw_proto; BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n", proto->suffix); _daddr = daddr ? *(uint8_t *)daddr : 0; - } - else if (!daddr) { + } else if (!daddr) { /* * if the dest addr isn't provided, we can't choose an encapsulation! * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a @@ -509,8 +505,7 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, BUGMSG(D_NORMAL, "arcnet_header: Yikes! diff (%d) is not 2!\n", (int)(skb->network_header - skb->mac_header)); return -2; /* return error -- can't transmit yet! */ - } - else { + } else { /* otherwise, we can just add the header as usual. */ _daddr = *(uint8_t *)daddr; proto_num = lp->default_proto[_daddr]; @@ -564,9 +559,9 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, AINTMASK(0); if (lp->next_tx == -1) txbuf = get_arcbuf(dev); - else { + else txbuf = -1; - } + if (txbuf != -1) { if (proto->prepare_tx(dev, pkt, skb->len, txbuf) && !proto->ack_tx) { @@ -606,9 +601,9 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, ASTATUS()); spin_unlock_irqrestore(&lp->lock, flags); - if (freeskb) { + if (freeskb) dev_kfree_skb(skb); - } + return retval; /* no need to try again */ } @@ -830,8 +825,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if (lp->outgoing.proto->continue_tx(dev, txbuf)) { /* that was the last segment */ dev->stats.tx_bytes += lp->outgoing.skb->len; - if (!lp->outgoing.proto->ack_tx) - { + if (!lp->outgoing.proto->ack_tx) { dev_kfree_skb_irq(lp->outgoing.skb); lp->outgoing.proto = NULL; } @@ -908,11 +902,9 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) BUGMSG(D_DURING, "not recon: clearing counters anyway.\n"); } - if (didsomething) { + if (didsomething) retval |= IRQ_HANDLED; - } - } - while (--boguscount && didsomething); + } while (--boguscount && didsomething); BUGMSG(D_DURING, "arcnet_interrupt complete (status=%Xh, count=%d)\n", ASTATUS(), boguscount); @@ -949,9 +941,9 @@ static void arcnet_rx(struct net_device *dev, int bufnum) } /* get the full header, if possible */ - if (sizeof(pkt.soft) <= length) + if (sizeof(pkt.soft) <= length) { lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(pkt.soft)); - else { + } else { memset(&pkt.soft, 0, sizeof(pkt.soft)); lp->hw.copy_from_card(dev, bufnum, ofs, soft, length); } diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 02815ff891f2..36648d350959 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -159,8 +159,9 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, } else if (length > MTU) { hard->offset[0] = 0; hard->offset[1] = ofs = 512 - length - 3; - } else + } else { hard->offset[0] = ofs = 256 - length; + } BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", length, ofs); @@ -226,8 +227,7 @@ free_outskb: return 0; } -static struct ArcProto capmode_proto = -{ +static struct ArcProto capmode_proto = { 'r', XMTU, 0, diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index c749af6db94e..48a45d30b2e5 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -41,10 +41,11 @@ #define VERSION "arcnet: COM20020 chipset support (by David Woodhouse et al.)\n" -static char *clockrates[] = -{"10 Mb/s", "Reserved", "5 Mb/s", - "2.5 Mb/s", "1.25Mb/s", "625 Kb/s", "312.5 Kb/s", - "156.25 Kb/s", "Reserved", "Reserved", "Reserved"}; +static char *clockrates[] = { + "XXXXXXX", "XXXXXXXX", "XXXXXX", + "2.5 Mb/s", "1.25Mb/s", "625 Kb/s", "312.5 Kb/s", + "156.25 Kb/s", "Reserved", "Reserved", "Reserved" +}; static void com20020_command(struct net_device *dev, int command); static int com20020_status(struct net_device *dev); @@ -102,8 +103,7 @@ int com20020_check(struct net_device *dev) SET_SUBADR(SUB_SETUP1); outb(lp->setup, _XREG); - if (lp->clockm != 0) - { + if (lp->clockm != 0) { SET_SUBADR(SUB_SETUP2); outb(lp->setup2, _XREG); @@ -196,8 +196,7 @@ int com20020_found(struct net_device *dev, int shared) SET_SUBADR(SUB_SETUP1); outb(lp->setup, _XREG); - if (lp->card_flags & ARC_CAN_10MBIT) - { + if (lp->card_flags & ARC_CAN_10MBIT) { SET_SUBADR(SUB_SETUP2); outb(lp->setup2, _XREG); diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c index 2eafb298626b..532410bb3dd8 100644 --- a/drivers/net/arcnet/com20020_cs.c +++ b/drivers/net/arcnet/com20020_cs.c @@ -56,8 +56,7 @@ static void regdump(struct net_device *dev) int count; netdev_dbg(dev, "register dump:\n"); - for (count = ioaddr; count < ioaddr + 16; count++) - { + for (count = ioaddr; count < ioaddr + 16; count++) { if (!(count % 16)) pr_cont("%04X:", count); pr_cont(" %02X", inb(count)); @@ -70,8 +69,7 @@ static void regdump(struct net_device *dev) outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI); outb(count & 0xff, _ADDR_LO); - for (count = 0; count < 256 + 32; count++) - { + for (count = 0; count < 256 + 32; count++) { if (!(count % 16)) pr_cont("%04X:", count); @@ -175,11 +173,9 @@ static void com20020_detach(struct pcmcia_device *link) /* Unlink device structure, free bits */ dev_dbg(&link->dev, "unlinking...\n"); - if (link->priv) - { + if (link->priv) { dev = info->dev; - if (dev) - { + if (dev) { dev_dbg(&link->dev, "kfree...\n"); free_netdev(dev); } @@ -210,21 +206,18 @@ static int com20020_config(struct pcmcia_device *link) i = -ENODEV; link->io_lines = 16; - if (!link->resource[0]->start) - { - for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) - { + if (!link->resource[0]->start) { + for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) { link->resource[0]->start = ioaddr; i = pcmcia_request_io(link); if (i == 0) break; } - } - else + } else { i = pcmcia_request_io(link); + } - if (i != 0) - { + if (i != 0) { dev_dbg(&link->dev, "requestIO failed totally!\n"); goto failed; } @@ -234,8 +227,7 @@ static int com20020_config(struct pcmcia_device *link) dev_dbg(&link->dev, "request IRQ %d\n", link->irq); - if (!link->irq) - { + if (!link->irq) { dev_dbg(&link->dev, "requestIRQ failed totally!\n"); goto failed; } @@ -246,8 +238,7 @@ static int com20020_config(struct pcmcia_device *link) if (ret) goto failed; - if (com20020_check(dev)) - { + if (com20020_check(dev)) { regdump(dev); goto failed; } diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index f0f06a274045..c16bfde97fbe 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -112,8 +112,7 @@ static void __init com90xx_probe(void) { int count, status, ioaddr, numprint, airq, openparen = 0; unsigned long airqmask; - int ports[(0x3f0 - 0x200) / 16 + 1] = - {0}; + int ports[(0x3f0 - 0x200) / 16 + 1] = { 0 }; unsigned long *shmems; void __iomem **iomem; int numports, numshmems, *port; diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index 49d35c972bca..ed7b6459bbfa 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -42,8 +42,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); -static struct ArcProto rfc1051_proto = -{ +static struct ArcProto rfc1051_proto = { .suffix = 's', .mtu = XMTU - RFC1051_HDR_SIZE, .is_ip = 1, @@ -94,9 +93,9 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) skb_reset_mac_header(skb); skb_pull(skb, hdr_size); - if (pkt->hard.dest == 0) + if (pkt->hard.dest == 0) { skb->pkt_type = PACKET_BROADCAST; - else if (dev->flags & IFF_PROMISC) { + } else if (dev->flags & IFF_PROMISC) { /* if we're not sending to ourselves :) */ if (pkt->hard.dest != dev->dev_addr[0]) skb->pkt_type = PACKET_OTHERHOST; @@ -232,8 +231,9 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, } else if (length > MTU) { hard->offset[0] = 0; hard->offset[1] = ofs = 512 - length - 3; - } else + } else { hard->offset[0] = ofs = 256 - length; + } lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length); diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 15f103a8a9db..4abb20e26ead 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -43,8 +43,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); static int continue_tx(struct net_device *dev, int bufnum); -static struct ArcProto rfc1201_proto = -{ +static struct ArcProto rfc1201_proto = { .suffix = 'a', .mtu = 1500, /* could be more, but some receivers can't handle it... */ .is_ip = 1, /* This is for sending IP and ARP packages */ @@ -97,9 +96,9 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev) skb_reset_mac_header(skb); skb_pull(skb, hdr_size); - if (pkt->hard.dest == 0) + if (pkt->hard.dest == 0) { skb->pkt_type = PACKET_BROADCAST; - else if (dev->flags & IFF_PROMISC) { + } else if (dev->flags & IFF_PROMISC) { /* if we're not sending to ourselves :) */ if (pkt->hard.dest != dev->dev_addr[0]) skb->pkt_type = PACKET_OTHERHOST; @@ -146,9 +145,9 @@ static void rx(struct net_device *dev, int bufnum, ofs = 256 - length; if (soft->split_flag == 0xFF) { /* Exception Packet */ - if (length >= 4 + RFC1201_HDR_SIZE) + if (length >= 4 + RFC1201_HDR_SIZE) { BUGMSG(D_DURING, "compensating for exception packet\n"); - else { + } else { BUGMSG(D_EXTRA, "short RFC1201 exception packet from %02Xh", saddr); return; @@ -456,8 +455,9 @@ static void load_pkt(struct net_device *dev, struct arc_hardware *hard, hard->offset[1] = ofs - RFC1201_HDR_SIZE; lp->hw.copy_to_card(dev, bufnum, ofs - RFC1201_HDR_SIZE, &excsoft, RFC1201_HDR_SIZE); - } else + } else { hard->offset[0] = ofs = 256 - softlen; + } lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); lp->hw.copy_to_card(dev, bufnum, ofs, soft, softlen); -- cgit v1.2.3 From 3b4e55510f3151cd906cd221f6fba5cb56b8cfed Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:50 -0700 Subject: arcnet: Coalesce string fragments Using coalesced strings helps grep for specific messages. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rimi.c | 9 +++------ drivers/net/arcnet/arcnet.c | 23 +++++++++-------------- drivers/net/arcnet/com20020-isa.c | 3 +-- drivers/net/arcnet/com90io.c | 7 +++---- drivers/net/arcnet/com90xx.c | 3 +-- drivers/net/arcnet/rfc1201.c | 13 +++++-------- 6 files changed, 22 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index e8c15016bb8e..6eedd6b6b041 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -90,13 +90,11 @@ static int __init arcrimi_probe(struct net_device *dev) dev->dev_addr[0], dev->mem_start, dev->irq); if (dev->mem_start <= 0 || dev->irq <= 0) { - BUGLVL(D_NORMAL) printk("No autoprobe for RIM I; you " - "must specify the shmem and irq!\n"); + BUGLVL(D_NORMAL) printk("No autoprobe for RIM I; you must specify the shmem and irq!\n"); return -ENODEV; } if (dev->dev_addr[0] == 0) { - BUGLVL(D_NORMAL) printk("You need to specify your card's station " - "ID!\n"); + BUGLVL(D_NORMAL) printk("You need to specify your card's station ID!\n"); return -ENODEV; } /* @@ -225,8 +223,7 @@ static int __init arcrimi_found(struct net_device *dev) /* get and check the station ID from offset 1 in shmem */ dev->dev_addr[0] = readb(lp->mem_start + 1); - BUGMSG(D_NORMAL, "ARCnet RIM I: station %02Xh found at IRQ %d, " - "ShMem %lXh (%ld*%d bytes).\n", + BUGMSG(D_NORMAL, "ARCnet RIM I: station %02Xh found at IRQ %d, ShMem %lXh (%ld*%d bytes)\n", dev->dev_addr[0], dev->irq, dev->mem_start, (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size); diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 24c0a6415023..d70efda777c5 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -416,11 +416,9 @@ int arcnet_open(struct net_device *dev) lp->hw.open(dev); if (dev->dev_addr[0] == 0) - BUGMSG(D_NORMAL, "WARNING! Station address 00 is reserved " - "for broadcasts!\n"); + BUGMSG(D_NORMAL, "WARNING! Station address 00 is reserved for broadcasts!\n"); else if (dev->dev_addr[0] == 255) - BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse " - "DOS networking programs!\n"); + BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse DOS networking programs!\n"); BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (ASTATUS() & RESETflag) { @@ -580,8 +578,8 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, if (proto->continue_tx && proto->continue_tx(dev, txbuf)) { BUGMSG(D_NORMAL, - "bug! continue_tx finished the first time! " - "(proto='%c')\n", proto->suffix); + "bug! continue_tx finished the first time! (proto='%c')\n", + proto->suffix); } } retval = NETDEV_TX_OK; @@ -779,15 +777,13 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if (!(status & TXACKflag)) { if (lp->lasttrans_dest != 0) { BUGMSG(D_EXTRA, - "transmit was not acknowledged! " - "(status=%Xh, dest=%02Xh)\n", + "transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n", status, lp->lasttrans_dest); dev->stats.tx_errors++; dev->stats.tx_carrier_errors++; } else { BUGMSG(D_DURING, - "broadcast was not acknowledged; that's normal " - "(status=%Xh, dest=%02Xh)\n", + "broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n", status, lp->lasttrans_dest); } } @@ -948,8 +944,7 @@ static void arcnet_rx(struct net_device *dev, int bufnum) lp->hw.copy_from_card(dev, bufnum, ofs, soft, length); } - BUGMSG(D_DURING, "Buffer #%d: received packet from %02Xh to %02Xh " - "(%d+4 bytes)\n", + BUGMSG(D_DURING, "Buffer #%d: received packet from %02Xh to %02Xh (%d+4 bytes)\n", bufnum, pkt.hard.source, pkt.hard.dest, length); dev->stats.rx_packets++; @@ -964,8 +959,8 @@ static void arcnet_rx(struct net_device *dev, int bufnum) if (oldp != newp) { BUGMSG(D_PROTO, - "got protocol %02Xh; encap for host %02Xh is now '%c'" - " (was '%c')\n", soft->proto, pkt.hard.source, + "got protocol %02Xh; encap for host %02Xh is now '%c' (was '%c')\n", + soft->proto, pkt.hard.source, newp->suffix, oldp->suffix); } } diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index c7d3377a45fe..b8129360b756 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -58,8 +58,7 @@ static int __init com20020isa_probe(struct net_device *dev) ioaddr = dev->base_addr; if (!ioaddr) { - BUGMSG(D_NORMAL, "No autoprobe (yet) for IO mapped cards; you " - "must specify the base address!\n"); + BUGMSG(D_NORMAL, "No autoprobe (yet) for IO mapped cards; you must specify the base address!\n"); return -ENODEV; } if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) { diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 11d2d0b4ccea..1742fa7c1e89 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -150,8 +150,7 @@ static int __init com90io_probe(struct net_device *dev) BUGLVL(D_NORMAL) printk("E-mail me if you actually test this driver, please!\n"); if (!ioaddr) { - BUGMSG(D_NORMAL, "No autoprobe for IO mapped cards; you " - "must specify the base address!\n"); + BUGMSG(D_NORMAL, "No autoprobe for IO mapped cards; you must specify the base address!\n"); return -ENODEV; } if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) { @@ -192,8 +191,8 @@ static int __init com90io_probe(struct net_device *dev) outb(0, _ADDR_LO); if ((status = inb(_MEMDATA)) != 0xd1) { - BUGMSG(D_INIT_REASONS, "Signature byte not found" - " (%Xh instead).\n", status); + BUGMSG(D_INIT_REASONS, "Signature byte not found (%Xh instead).\n", + status); goto err_out; } if (!dev->irq) { diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index c16bfde97fbe..2e2908435f81 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -525,8 +525,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem dev->base_addr = ioaddr; - BUGMSG(D_NORMAL, "COM90xx station %02Xh found at %03lXh, IRQ %d, " - "ShMem %lXh (%ld*%xh).\n", + BUGMSG(D_NORMAL, "COM90xx station %02Xh found at %03lXh, IRQ %d, ShMem %lXh (%ld*%xh).\n", dev->dev_addr[0], dev->base_addr, dev->irq, dev->mem_start, (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size); diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 4abb20e26ead..47750173fd14 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -261,8 +261,7 @@ static void rx(struct net_device *dev, int bufnum, BUGMSG(D_RX, "brand new splitpacket (splitflag=%d)\n", soft->split_flag); if (in->skb) { /* already assembling one! */ - BUGMSG(D_EXTRA, "aborting previous (seq=%d) assembly " - "(splitflag=%d, seq=%d)\n", + BUGMSG(D_EXTRA, "aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n", in->sequence, soft->split_flag, soft->sequence); dev->stats.rx_errors++; @@ -306,8 +305,7 @@ static void rx(struct net_device *dev, int bufnum, */ if (!in->skb) { if (lp->rfc1201.aborted_seq != soft->sequence) { - BUGMSG(D_EXTRA, "can't continue split without starting " - "first! (splitflag=%d, seq=%d, aborted=%d)\n", + BUGMSG(D_EXTRA, "can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n", soft->split_flag, soft->sequence, lp->rfc1201.aborted_seq); dev->stats.rx_errors++; @@ -326,8 +324,7 @@ static void rx(struct net_device *dev, int bufnum, return; } /* "bad" duplicate, kill reassembly */ - BUGMSG(D_EXTRA, "out-of-order splitpacket, reassembly " - "(seq=%d) aborted (splitflag=%d, seq=%d)\n", + BUGMSG(D_EXTRA, "out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n", in->sequence, soft->split_flag, soft->sequence); lp->rfc1201.aborted_seq = soft->sequence; dev_kfree_skb_irq(in->skb); @@ -487,8 +484,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, out->numsegs = (out->dataleft + maxsegsize - 1) / maxsegsize; out->segnum = 0; - BUGMSG(D_DURING, "rfc1201 prep_tx: ready for %d-segment split " - "(%d bytes, seq=%d)\n", out->numsegs, out->length, + BUGMSG(D_DURING, "rfc1201 prep_tx: ready for %d-segment split (%d bytes, seq=%d)\n", + out->numsegs, out->length, pkt->soft.rfc1201.sequence); return 0; /* not done */ -- cgit v1.2.3 From 5e7ef9134ce1b8ae8d686ce08b9746b32535964d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:51 -0700 Subject: arcnet: Use include/linux path for asm Use the preferred kernel include path for asm paths. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rimi.c | 2 +- drivers/net/arcnet/com20020-isa.c | 2 +- drivers/net/arcnet/com20020-pci.c | 2 +- drivers/net/arcnet/com20020.c | 2 +- drivers/net/arcnet/com20020_cs.c | 2 +- drivers/net/arcnet/com90io.c | 2 +- drivers/net/arcnet/com90xx.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 6eedd6b6b041..88e61574931c 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #define VERSION "arcnet: RIM I (entirely mem-mapped) support\n" diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index b8129360b756..d829e605470f 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -39,7 +39,7 @@ #include #include -#include +#include #define VERSION "arcnet: COM20020 ISA support (by David Woodhouse et al.)\n" diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 06621e95bd38..72334b59aa26 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -40,7 +40,7 @@ #include #include -#include +#include #define VERSION "arcnet: COM20020 PCI support\n" diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 48a45d30b2e5..bdf883f9870e 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -37,7 +37,7 @@ #include #include -#include +#include #define VERSION "arcnet: COM20020 chipset support (by David Woodhouse et al.)\n" diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c index 532410bb3dd8..437b456afe68 100644 --- a/drivers/net/arcnet/com20020_cs.c +++ b/drivers/net/arcnet/com20020_cs.c @@ -45,7 +45,7 @@ #include #include -#include +#include #define VERSION "arcnet: COM20020 PCMCIA support loaded.\n" diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 1742fa7c1e89..32333465327a 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #define VERSION "arcnet: COM90xx IO-mapped mode support (by David Woodhouse et el.)\n" diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 2e2908435f81..0b7bc869db21 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #define VERSION "arcnet: COM90xx chipset support\n" -- cgit v1.2.3 From f2f0a16bf89a1bbf2f774e060de85ffbd8fff162 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:52 -0700 Subject: arcnet: Use network block comment style Conformity can be useful. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 15 ++++---- drivers/net/arcnet/arc-rimi.c | 17 ++++----- drivers/net/arcnet/arcnet.c | 76 ++++++++++++++++----------------------- drivers/net/arcnet/capmode.c | 25 +++++++------ drivers/net/arcnet/com20020-isa.c | 3 +- drivers/net/arcnet/com20020.c | 3 +- drivers/net/arcnet/com20020_cs.c | 3 +- drivers/net/arcnet/com90io.c | 9 ++--- drivers/net/arcnet/com90xx.c | 3 +- drivers/net/arcnet/rfc1051.c | 19 ++++------ drivers/net/arcnet/rfc1201.c | 54 ++++++++++++++-------------- 11 files changed, 95 insertions(+), 132 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 500b5bb2cff4..efdd8e95a2bf 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -123,8 +123,7 @@ static void rx(struct net_device *dev, int bufnum, netif_rx(skb); } -/* - * Create the ARCnet hard/soft headers for raw mode. +/* Create the ARCnet hard/soft headers for raw mode. * There aren't any soft headers in raw mode - not even the protocol id. */ static int build_header(struct sk_buff *skb, struct net_device *dev, @@ -133,21 +132,19 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, int hdr_size = ARC_HDR_SIZE; struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size); - /* - * Set the source hardware address. + /* Set the source hardware address. * * This is pretty pointless for most purposes, but it can help in - * debugging. ARCnet does not allow us to change the source address in - * the actual packet sent) + * debugging. ARCnet does not allow us to change the source address + * in the actual packet sent. */ pkt->hard.source = *dev->dev_addr; /* see linux/net/ethernet/eth.c to see where I got the following */ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - /* - * FIXME: fill in the last byte of the dest ipaddr here to better - * comply with RFC1051 in "noarp" mode. + /* FIXME: fill in the last byte of the dest ipaddr here + * to better comply with RFC1051 in "noarp" mode. */ pkt->hard.dest = 0; return hdr_size; diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 88e61574931c..c7ab23e8ec6a 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -76,8 +76,7 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse #define AINTMASK(msk) writeb((msk), _INTMASK) #define SETCONF() writeb(lp->config, _CONFIG) -/* - * We cannot probe for a RIM I card; one reason is I don't know how to reset +/* We cannot probe for a RIM I card; one reason is I don't know how to reset * them. In fact, we can't even get their node ID automatically. So, we * need to be passed a specific shmem address, IRQ, and node ID. */ @@ -97,8 +96,7 @@ static int __init arcrimi_probe(struct net_device *dev) BUGLVL(D_NORMAL) printk("You need to specify your card's station ID!\n"); return -ENODEV; } - /* - * Grab the memory region at mem_start for MIRROR_SIZE bytes. + /* Grab the memory region at mem_start for MIRROR_SIZE bytes. * Later in arcrimi_found() the real size will be determined * and this reserve will be released and the correct size * will be taken. @@ -131,9 +129,8 @@ static int check_mirror(unsigned long addr, size_t size) return res; } -/* - * Set up the struct net_device associated with this card. Called after - * probing succeeds. +/* Set up the struct net_device associated with this card. + * Called after probing succeeds. */ static int __init arcrimi_found(struct net_device *dev) { @@ -199,8 +196,7 @@ static int __init arcrimi_found(struct net_device *dev) lp->hw.copy_to_card = arcrimi_copy_to_card; lp->hw.copy_from_card = arcrimi_copy_from_card; - /* - * re-reserve the memory region - arcrimi_probe() alloced this reqion + /* re-reserve the memory region - arcrimi_probe() alloced this reqion * but didn't know the real size. Free that region and then re-get * with the correct size. There is a VERY slim chance this could * fail. @@ -243,8 +239,7 @@ err_free_irq: return -EIO; } -/* - * Do a hardware reset on the card, and set up necessary registers. +/* Do a hardware reset on the card, and set up necessary registers. * * This should be called as little as possible, because it disrupts the * token on the network (causes a RECON) and requires a significant delay. diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index d70efda777c5..605b4a7abecc 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -63,8 +63,7 @@ static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, static void arcnet_rx(struct net_device *dev, int bufnum); -/* - * one ArcProto per possible proto ID. None of the elements of +/* one ArcProto per possible proto ID. None of the elements of * arc_proto_map are allowed to be NULL; they will get set to * arc_proto_default instead. It also must not be NULL; if you would like * to set it to NULL, set it to &arc_proto_null instead. @@ -149,9 +148,7 @@ static void __exit arcnet_exit(void) module_init(arcnet_init); module_exit(arcnet_exit); -/* - * Dump the contents of an sk_buff - */ +/* Dump the contents of an sk_buff */ #if ARCNET_DEBUG_MAX & D_SKB void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc) @@ -167,9 +164,7 @@ void arcnet_dump_skb(struct net_device *dev, EXPORT_SYMBOL(arcnet_dump_skb); #endif -/* - * Dump the contents of an ARCnet buffer - */ +/* Dump the contents of an ARCnet buffer */ #if (ARCNET_DEBUG_MAX & (D_RX | D_TX)) static void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc, int take_arcnet_lock) @@ -181,7 +176,8 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, char hdr[32]; /* hw.copy_from_card expects IRQ context so take the IRQ lock - to keep it single threaded */ + * to keep it single threaded + */ if (take_arcnet_lock) spin_lock_irqsave(&lp->lock, flags); @@ -204,8 +200,7 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, #endif -/* - * Unregister a protocol driver from the arc_proto_map. Protocol drivers +/* Unregister a protocol driver from the arc_proto_map. Protocol drivers * are responsible for registering themselves, but the unregister routine * is pretty generic so we'll do it here. */ @@ -226,8 +221,7 @@ void arcnet_unregister_proto(struct ArcProto *proto) } } -/* - * Add a buffer to the queue. Only the interrupt handler is allowed to do +/* Add a buffer to the queue. Only the interrupt handler is allowed to do * this, unless interrupts are disabled. * * Note: we don't check for a full queue, since there aren't enough buffers @@ -250,9 +244,8 @@ static void release_arcbuf(struct net_device *dev, int bufnum) } } -/* - * Get a buffer from the queue. If this returns -1, there are no buffers - * available. +/* Get a buffer from the queue. + * If this returns -1, there are no buffers available. */ static int get_arcbuf(struct net_device *dev) { @@ -346,8 +339,7 @@ struct net_device *alloc_arcdev(const char *name) return dev; } -/* - * Open/initialize the board. This is called sometime after booting when +/* Open/initialize the board. This is called sometime after booting when * the 'ifconfig' program is run. * * This routine should set everything up anew at each open, even registers @@ -490,15 +482,13 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n", proto->suffix); _daddr = daddr ? *(uint8_t *)daddr : 0; } else if (!daddr) { - /* - * if the dest addr isn't provided, we can't choose an encapsulation! - * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a - * real header when we do rebuild_header. + /* if the dest addr isn't provided, we can't choose an + * encapsulation! Store the packet type (eg. ETH_P_IP) + * for now, and we'll push on a real header when we do + * rebuild_header. */ *(uint16_t *)skb_push(skb, 2) = type; - /* - * XXX: Why not use skb->mac_len? - */ + /* XXX: Why not use skb->mac_len? */ if (skb->network_header - skb->mac_header != 2) BUGMSG(D_NORMAL, "arcnet_header: Yikes! diff (%d) is not 2!\n", (int)(skb->network_header - skb->mac_header)); @@ -564,7 +554,8 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, if (proto->prepare_tx(dev, pkt, skb->len, txbuf) && !proto->ack_tx) { /* done right away and we don't want to acknowledge - the package later - forget about it now */ + * the package later - forget about it now + */ dev->stats.tx_bytes += skb->len; freeskb = 1; } else { @@ -605,8 +596,7 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, return retval; /* no need to try again */ } -/* - * Actually start transmitting a packet that was loaded into a buffer +/* Actually start transmitting a packet that was loaded into a buffer * by prepare_tx. This should _only_ be called by the interrupt handler. */ static int go_tx(struct net_device *dev) @@ -672,8 +662,7 @@ void arcnet_timeout(struct net_device *dev) netif_wake_queue(dev); } -/* - * The typical workload of the driver: Handle the network interface +/* The typical workload of the driver: Handle the network interface * interrupts. Establish which device needs attention, and call the correct * chipset interrupt handler. */ @@ -693,9 +682,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) spin_lock(&lp->lock); - /* - * RESET flag was enabled - if device is not running, we must clear it right - * away (but nothing else). + /* RESET flag was enabled - if device is not running, we must + * clear it right away (but nothing else). */ if (!netif_running(dev)) { if (ASTATUS() & RESETflag) @@ -717,11 +705,11 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) __FILE__, __LINE__, __func__, status); didsomething = 0; - /* - * RESET flag was enabled - card is resetting and if RX is + /* RESET flag was enabled - card is resetting and if RX is * disabled, it's NOT because we just got a packet. * - * The card is in an undefined state. Clear it out and start over. + * The card is in an undefined state. + * Clear it out and start over. */ if (status & RESETflag) { BUGMSG(D_NORMAL, "spurious reset (status=%Xh)\n", status); @@ -731,14 +719,13 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) /* get out of the interrupt handler! */ break; } - /* - * RX is inhibited - we must have received something. Prepare to - * receive into the next buffer. + /* RX is inhibited - we must have received something. + * Prepare to receive into the next buffer. * - * We don't actually copy the received packet from the card until - * after the transmit handler runs (and possibly launches the next - * tx); this should improve latency slightly if we get both types - * of interrupts at once. + * We don't actually copy the received packet from the card + * until after the transmit handler runs (and possibly + * launches the next tx); this should improve latency slightly + * if we get both types of interrupts at once. */ recbuf = -1; if (status & lp->intmask & NORXflag) { @@ -914,8 +901,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) return retval; } -/* - * This is a generic packet receiver that calls arcnet??_rx depending on the +/* This is a generic packet receiver that calls arcnet??_rx depending on the * protocol ID found. */ static void arcnet_rx(struct net_device *dev, int bufnum) diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 36648d350959..8391324f684b 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -66,11 +66,11 @@ static void rx(struct net_device *dev, int bufnum, pkt = (struct archdr *)skb_mac_header(skb); skb_pull(skb, ARC_HDR_SIZE); - /* up to sizeof(pkt->soft) has already been copied from the card */ - /* squeeze in an int for the cap encapsulation */ - - /* use these variables to be sure we count in bytes, not in - sizeof(struct archdr) */ + /* up to sizeof(pkt->soft) has already been copied from the card + * squeeze in an int for the cap encapsulation + * use these variables to be sure we count in bytes, not in + * sizeof(struct archdr) + */ pktbuf = (char *)pkt; pkthdrbuf = (char *)pkthdr; memcpy(pktbuf, pkthdrbuf, ARC_HDR_SIZE + sizeof(pkt->soft.cap.proto)); @@ -90,8 +90,7 @@ static void rx(struct net_device *dev, int bufnum, netif_rx(skb); } -/* - * Create the ARCnet hard/soft headers for cap mode. +/* Create the ARCnet hard/soft headers for cap mode. * There aren't any soft headers in cap mode - not even the protocol id. */ static int build_header(struct sk_buff *skb, @@ -104,8 +103,8 @@ static int build_header(struct sk_buff *skb, BUGMSG(D_PROTO, "Preparing header for cap packet %x.\n", *((int *)&pkt->soft.cap.cookie[0])); - /* - * Set the source hardware address. + + /* Set the source hardware address. * * This is pretty pointless for most purposes, but it can help in * debugging. ARCnet does not allow us to change the source address in @@ -116,9 +115,8 @@ static int build_header(struct sk_buff *skb, /* see linux/net/ethernet/eth.c to see where I got the following */ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - /* - * FIXME: fill in the last byte of the dest ipaddr here to better - * comply with RFC1051 in "noarp" mode. + /* FIXME: fill in the last byte of the dest ipaddr here to + * better comply with RFC1051 in "noarp" mode. */ pkt->hard.dest = 0; return hdr_size; @@ -172,7 +170,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, sizeof(pkt->soft.cap.proto)); /* Skip the extra integer we have written into it as a cookie - but write the rest of the message: */ + * but write the rest of the message: + */ lp->hw.copy_to_card(dev, bufnum, ofs + 1, ((unsigned char *)&pkt->soft.cap.mes), length - 1); diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index d829e605470f..6e38a19d7210 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -43,8 +43,7 @@ #define VERSION "arcnet: COM20020 ISA support (by David Woodhouse et al.)\n" -/* - * We cannot (yet) probe for an IO mapped card, although we can check that +/* We cannot (yet) probe for an IO mapped card, although we can check that * it's where we were told it was, and even do autoirq. */ static int __init com20020isa_probe(struct net_device *dev) diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index bdf883f9870e..63697272f146 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -239,8 +239,7 @@ int com20020_found(struct net_device *dev, int shared) return 0; } -/* - * Do a hardware reset on the card, and set up necessary registers. +/* Do a hardware reset on the card, and set up necessary registers. * * This should be called as little as possible, because it disrupts the * token on the network (causes a RECON) and requires a significant delay. diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c index 437b456afe68..13fe53864383 100644 --- a/drivers/net/arcnet/com20020_cs.c +++ b/drivers/net/arcnet/com20020_cs.c @@ -162,8 +162,7 @@ static void com20020_detach(struct pcmcia_device *link) unregister_netdev(dev); - /* - * this is necessary because we register our IRQ separately + /* this is necessary because we register our IRQ separately * from card services. */ if (dev->irq) diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 32333465327a..6ec36f9975ba 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -137,8 +137,7 @@ static void put_whole_buffer(struct net_device *dev, unsigned offset, unsigned l #endif } -/* - * We cannot probe for an IO mapped card either, although we can check that +/* We cannot probe for an IO mapped card either, although we can check that * it's where we were told it was, and even autoirq */ static int __init com90io_probe(struct net_device *dev) @@ -196,8 +195,7 @@ static int __init com90io_probe(struct net_device *dev) goto err_out; } if (!dev->irq) { - /* - * if we do this, we're sure to get an IRQ since the + /* if we do this, we're sure to get an IRQ since the * card has just reset and the NORXflag is on until * we tell it to start receiving. */ @@ -272,8 +270,7 @@ static int __init com90io_found(struct net_device *dev) return 0; } -/* - * Do a hardware reset on the card, and set up necessary registers. +/* Do a hardware reset on the card, and set up necessary registers. * * This should be called as little as possible, because it disrupts the * token on the network (causes a RECON) and requires a significant delay. diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 0b7bc869db21..4781cd696dd1 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -568,8 +568,7 @@ static void com90xx_setmask(struct net_device *dev, int mask) AINTMASK(mask); } -/* - * Do a hardware reset on the card, and set up necessary registers. +/* Do a hardware reset on the card, and set up necessary registers. * * This should be called as little as possible, because it disrupts the * token on the network (causes a RECON) and requires a significant delay. diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index ed7b6459bbfa..e78b76535acc 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -78,8 +78,7 @@ module_exit(arcnet_rfc1051_exit); MODULE_LICENSE("GPL"); -/* - * Determine a packet's protocol ID. +/* Determine a packet's protocol ID. * * With ARCnet we have to convert everything to Ethernet-style stuff. */ @@ -156,9 +155,7 @@ static void rx(struct net_device *dev, int bufnum, netif_rx(skb); } -/* - * Create the ARCnet hard/soft headers for RFC1051. - */ +/* Create the ARCnet hard/soft headers for RFC1051 */ static int build_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, uint8_t daddr) { @@ -182,21 +179,19 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, return 0; } - /* - * Set the source hardware address. + /* Set the source hardware address. * * This is pretty pointless for most purposes, but it can help in - * debugging. ARCnet does not allow us to change the source address in - * the actual packet sent) + * debugging. ARCnet does not allow us to change the source address + * in the actual packet sent. */ pkt->hard.source = *dev->dev_addr; /* see linux/net/ethernet/eth.c to see where I got the following */ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - /* - * FIXME: fill in the last byte of the dest ipaddr here to better - * comply with RFC1051 in "noarp" mode. + /* FIXME: fill in the last byte of the dest ipaddr here to + * better comply with RFC1051 in "noarp" mode. */ pkt->hard.dest = 0; return hdr_size; diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 47750173fd14..4ebfbcbe5de3 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -81,8 +81,7 @@ static void __exit arcnet_rfc1201_exit(void) module_init(arcnet_rfc1201_init); module_exit(arcnet_rfc1201_exit); -/* - * Determine a packet's protocol ID. +/* Determine a packet's protocol ID. * * With ARCnet we have to convert everything to Ethernet-style stuff. */ @@ -193,10 +192,10 @@ static void rx(struct net_device *dev, int bufnum, pkt->soft.raw + sizeof(pkt->soft), length - sizeof(pkt->soft)); - /* - * ARP packets have problems when sent from some DOS systems: the - * source address is always 0! So we take the hardware source addr - * (which is impossible to fumble) and insert it ourselves. + /* ARP packets have problems when sent from some DOS systems: + * the source address is always 0! + * So we take the hardware source addr (which is impossible + * to fumble) and insert it ourselves. */ if (soft->proto == ARC_P_ARP) { struct arphdr *arp = (struct arphdr *)soft->payload; @@ -227,21 +226,22 @@ static void rx(struct net_device *dev, int bufnum, skb->protocol = type_trans(skb, dev); netif_rx(skb); } else { /* split packet */ - /* - * NOTE: MSDOS ARP packet correction should only need to apply to - * unsplit packets, since ARP packets are so short. + /* NOTE: MSDOS ARP packet correction should only need to + * apply to unsplit packets, since ARP packets are so short. * - * My interpretation of the RFC1201 document is that if a packet is - * received out of order, the entire assembly process should be - * aborted. + * My interpretation of the RFC1201 document is that if a + * packet is received out of order, the entire assembly + * process should be aborted. * - * The RFC also mentions "it is possible for successfully received - * packets to be retransmitted." As of 0.40 all previously received - * packets are allowed, not just the most recent one. + * The RFC also mentions "it is possible for successfully + * received packets to be retransmitted." As of 0.40 all + * previously received packets are allowed, not just the + * most recent one. * - * We allow multiple assembly processes, one for each ARCnet card - * possible on the network. Seems rather like a waste of memory, - * but there's no other way to be reliable. + * We allow multiple assembly processes, one for each + * ARCnet card possible on the network. + * Seems rather like a waste of memory, but there's no + * other way to be reliable. */ BUGMSG(D_RX, "packet is split (splitflag=%d, seq=%d)\n", @@ -299,8 +299,7 @@ static void rx(struct net_device *dev, int bufnum, } else { /* not first packet */ int packetnum = ((unsigned)soft->split_flag >> 1) + 1; - /* - * if we're not assembling, there's no point trying to + /* if we're not assembling, there's no point trying to * continue. */ if (!in->skb) { @@ -401,12 +400,11 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, return 0; } - /* - * Set the source hardware address. + /* Set the source hardware address. * * This is pretty pointless for most purposes, but it can help in - * debugging. ARCnet does not allow us to change the source address in - * the actual packet sent) + * debugging. ARCnet does not allow us to change the source address + * in the actual packet sent. */ pkt->hard.source = *dev->dev_addr; @@ -416,10 +414,10 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, /* see linux/net/ethernet/eth.c to see where I got the following */ if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - /* - * FIXME: fill in the last byte of the dest ipaddr here to better - * comply with RFC1051 in "noarp" mode. For now, always broadcasting - * will probably at least get packets sent out :) + /* FIXME: fill in the last byte of the dest ipaddr here + * to better comply with RFC1051 in "noarp" mode. + * For now, always broadcasting will probably at least get + * packets sent out :) */ pkt->hard.dest = 0; return hdr_size; -- cgit v1.2.3 From 72aeea4841c037b9b3abf65859673cbd7b6664a9 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:54 -0700 Subject: arcnet: Expand odd BUGLVL macro with if and uses Don't hide what should be obvious. Make the macro a simple test instead of using if and test. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 3 ++- drivers/net/arcnet/arc-rimi.c | 20 +++++++++------- drivers/net/arcnet/arcnet.c | 29 ++++++++++++----------- drivers/net/arcnet/capmode.c | 9 ++++--- drivers/net/arcnet/com20020-isa.c | 3 ++- drivers/net/arcnet/com20020-pci.c | 3 ++- drivers/net/arcnet/com20020.c | 3 ++- drivers/net/arcnet/com90io.c | 6 +++-- drivers/net/arcnet/com90xx.c | 49 +++++++++++++++++++++++++-------------- drivers/net/arcnet/rfc1051.c | 3 ++- drivers/net/arcnet/rfc1201.c | 6 +++-- 11 files changed, 84 insertions(+), 50 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index efdd8e95a2bf..998c8356e576 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -117,7 +117,8 @@ static void rx(struct net_device *dev, int bufnum, pkt->soft.raw + sizeof(pkt->soft), length - sizeof(pkt->soft)); - BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, skb, "rx"); skb->protocol = cpu_to_be16(ETH_P_ARCNET); netif_rx(skb); diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index c7ab23e8ec6a..cd47a1b3008c 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -82,18 +82,21 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse */ static int __init arcrimi_probe(struct net_device *dev) { - BUGLVL(D_NORMAL) printk(VERSION); - BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n"); - - BUGLVL(D_NORMAL) printk("Given: node %02Xh, shmem %lXh, irq %d\n", - dev->dev_addr[0], dev->mem_start, dev->irq); + if (BUGLVL(D_NORMAL)) { + printk(VERSION); + printk("E-mail me if you actually test the RIM I driver, please!\n"); + printk("Given: node %02Xh, shmem %lXh, irq %d\n", + dev->dev_addr[0], dev->mem_start, dev->irq); + } if (dev->mem_start <= 0 || dev->irq <= 0) { - BUGLVL(D_NORMAL) printk("No autoprobe for RIM I; you must specify the shmem and irq!\n"); + if (BUGLVL(D_NORMAL)) + printk("No autoprobe for RIM I; you must specify the shmem and irq!\n"); return -ENODEV; } if (dev->dev_addr[0] == 0) { - BUGLVL(D_NORMAL) printk("You need to specify your card's station ID!\n"); + if (BUGLVL(D_NORMAL)) + printk("You need to specify your card's station ID!\n"); return -ENODEV; } /* Grab the memory region at mem_start for MIRROR_SIZE bytes. @@ -102,7 +105,8 @@ static int __init arcrimi_probe(struct net_device *dev) * will be taken. */ if (!request_mem_region(dev->mem_start, MIRROR_SIZE, "arcnet (90xx)")) { - BUGLVL(D_NORMAL) printk("Card memory already allocated\n"); + if (BUGLVL(D_NORMAL)) + printk("Card memory already allocated\n"); return -ENODEV; } return arcrimi_found(dev); diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 605b4a7abecc..7a90b8a45a37 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -117,7 +117,7 @@ static int __init arcnet_init(void) printk("arcnet loaded.\n"); #ifdef ALPHA_WARNING - BUGLVL(D_EXTRA) { + if (BUGLVL(D_EXTRA)) { printk("arcnet: ***\n" "arcnet: * Read arcnet.txt for important release notes!\n" "arcnet: *\n" @@ -132,11 +132,11 @@ static int __init arcnet_init(void) for (count = 0; count < 256; count++) arc_proto_map[count] = arc_proto_default; - BUGLVL(D_DURING) - printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n", - sizeof(struct arc_hardware), sizeof(struct arc_rfc1201), - sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap), - sizeof(struct archdr)); + if (BUGLVL(D_DURING)) + printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n", + sizeof(struct arc_hardware), sizeof(struct arc_rfc1201), + sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap), + sizeof(struct archdr)); return 0; } @@ -235,7 +235,7 @@ static void release_arcbuf(struct net_device *dev, int bufnum) lp->buf_queue[lp->first_free_buf++] = bufnum; lp->first_free_buf %= 5; - BUGLVL(D_DURING) { + if (BUGLVL(D_DURING)) { BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ", bufnum); for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) @@ -268,7 +268,7 @@ static int get_arcbuf(struct net_device *dev) } } - BUGLVL(D_DURING) { + if (BUGLVL(D_DURING)) { BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf); for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); @@ -356,7 +356,7 @@ int arcnet_open(struct net_device *dev) if (!try_module_get(lp->hw.owner)) return -ENODEV; - BUGLVL(D_PROTO) { + if (BUGLVL(D_PROTO)) { BUGMSG(D_PROTO, "protocol map (default is '%c'): ", arc_proto_default->suffix); for (count = 0; count < 256; count++) @@ -531,7 +531,8 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, BUGMSG(D_SKB_SIZE, "skb: transmitting %d bytes to %02X\n", skb->len, pkt->hard.dest); - BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, skb, "tx"); /* fits in one packet? */ if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) { @@ -609,7 +610,8 @@ static int go_tx(struct net_device *dev) if (lp->cur_tx != -1 || lp->next_tx == -1) return 0; - BUGLVL(D_TX) arcnet_dump_packet(dev, lp->next_tx, "go_tx", 0); + if (BUGLVL(D_TX)) + arcnet_dump_packet(dev, lp->next_tx, "go_tx", 0); lp->cur_tx = lp->next_tx; lp->next_tx = -1; @@ -822,7 +824,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) } /* now process the received packet, if any */ if (recbuf != -1) { - BUGLVL(D_RX) arcnet_dump_packet(dev, recbuf, "rx irq", 0); + if (BUGLVL(D_RX)) + arcnet_dump_packet(dev, recbuf, "rx irq", 0); arcnet_rx(dev, recbuf); release_arcbuf(dev, recbuf); @@ -938,7 +941,7 @@ static void arcnet_rx(struct net_device *dev, int bufnum) /* call the right receiver for the protocol */ if (arc_proto_map[soft->proto]->is_ip) { - BUGLVL(D_PROTO) { + if (BUGLVL(D_PROTO)) { struct ArcProto *oldp = arc_proto_map[lp->default_proto[pkt.hard.source]], *newp = arc_proto_map[soft->proto]; diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 8391324f684b..e7ec907f4680 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -84,7 +84,8 @@ static void rx(struct net_device *dev, int bufnum, + sizeof(int), length - sizeof(pkt->soft)); - BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, skb, "rx"); skb->protocol = cpu_to_be16(ETH_P_ARCNET); netif_rx(skb); @@ -190,7 +191,8 @@ static int ack_tx(struct net_device *dev, int acked) BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n", lp->outgoing.skb->protocol, acked); - BUGLVL(D_SKB) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx"); /* Now alloc a skb to send back up through the layers: */ ackskb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); @@ -216,7 +218,8 @@ static int ack_tx(struct net_device *dev, int acked) ackskb->protocol = cpu_to_be16(ETH_P_ARCNET); - BUGLVL(D_SKB) arcnet_dump_skb(dev, ackskb, "ack_tx_recv"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, ackskb, "ack_tx_recv"); netif_rx(ackskb); free_outskb: diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index 6e38a19d7210..af87c7482478 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -53,7 +53,8 @@ static int __init com20020isa_probe(struct net_device *dev) struct arcnet_local *lp = netdev_priv(dev); int err; - BUGLVL(D_NORMAL) printk(VERSION); + if (BUGLVL(D_NORMAL)) + printk(VERSION); ioaddr = dev->base_addr; if (!ioaddr) { diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 72334b59aa26..c8184de4480d 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -402,7 +402,8 @@ static struct pci_driver com20020pci_driver = { static int __init com20020pci_init(void) { - BUGLVL(D_NORMAL) printk(VERSION); + if (BUGLVL(D_NORMAL)) + printk(VERSION); return pci_register_driver(&com20020pci_driver); } diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 63697272f146..3170e8ebb7fa 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -365,7 +365,8 @@ MODULE_LICENSE("GPL"); static int __init com20020_module_init(void) { - BUGLVL(D_NORMAL) printk(VERSION); + if (BUGLVL(D_NORMAL)) + printk(VERSION); return 0; } diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 6ec36f9975ba..33a8531e90c7 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -145,8 +145,10 @@ static int __init com90io_probe(struct net_device *dev) int ioaddr = dev->base_addr, status; unsigned long airqmask; - BUGLVL(D_NORMAL) printk(VERSION); - BUGLVL(D_NORMAL) printk("E-mail me if you actually test this driver, please!\n"); + if (BUGLVL(D_NORMAL)) { + printk(VERSION); + printk("E-mail me if you actually test this driver, please!\n"); + } if (!ioaddr) { BUGMSG(D_NORMAL, "No autoprobe for IO mapped cards; you must specify the base address!\n"); diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 4781cd696dd1..b5e1c1904f13 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -133,7 +133,8 @@ static void __init com90xx_probe(void) return; } - BUGLVL(D_NORMAL) printk(VERSION); + if (BUGLVL(D_NORMAL)) + printk(VERSION); /* set up the arrays where we'll store the possible probe addresses */ numports = numshmems = 0; @@ -166,14 +167,16 @@ static void __init com90xx_probe(void) if (!request_region(*port, ARCNET_TOTAL_SIZE, "arcnet (90xx)")) { BUGMSG2(D_INIT_REASONS, "(request_region)\n"); BUGMSG2(D_INIT_REASONS, "S1: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; *port-- = ports[--numports]; continue; } if (ASTATUS() == 0xFF) { BUGMSG2(D_INIT_REASONS, "(empty)\n"); BUGMSG2(D_INIT_REASONS, "S1: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); *port-- = ports[--numports]; continue; @@ -182,7 +185,8 @@ static void __init com90xx_probe(void) BUGMSG2(D_INIT_REASONS, "\n"); BUGMSG2(D_INIT_REASONS, "S1: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; } BUGMSG2(D_INIT, "\n"); @@ -227,21 +231,24 @@ static void __init com90xx_probe(void) if (!request_mem_region(*p, MIRROR_SIZE, "arcnet (90xx)")) { BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n"); BUGMSG2(D_INIT_REASONS, "Stage 3: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; goto out; } base = ioremap(*p, MIRROR_SIZE); if (!base) { BUGMSG2(D_INIT_REASONS, "(ioremap)\n"); BUGMSG2(D_INIT_REASONS, "Stage 3: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; goto out1; } if (readb(base) != TESTvalue) { BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n", readb(base), TESTvalue); BUGMSG2(D_INIT_REASONS, "S3: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; goto out2; } /* By writing 0x42 to the TESTvalue location, we also make @@ -257,7 +264,8 @@ static void __init com90xx_probe(void) } BUGMSG2(D_INIT_REASONS, "\n"); BUGMSG2(D_INIT_REASONS, "S3: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; iomem[index] = base; continue; out2: @@ -319,7 +327,8 @@ static void __init com90xx_probe(void) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status); BUGMSG2(D_INIT_REASONS, "S5: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); *port-- = ports[--numports]; continue; @@ -330,7 +339,8 @@ static void __init com90xx_probe(void) BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n", status); BUGMSG2(D_INIT_REASONS, "S5: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); *port-- = ports[--numports]; continue; @@ -352,7 +362,8 @@ static void __init com90xx_probe(void) if (airq <= 0) { BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq); BUGMSG2(D_INIT_REASONS, "S5: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT_REASONS)) + numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); *port-- = ports[--numports]; continue; @@ -406,16 +417,20 @@ static void __init com90xx_probe(void) } if (openparen) { - BUGLVL(D_INIT) printk("no matching shmem)\n"); - BUGLVL(D_INIT_REASONS) printk("S5: "); - BUGLVL(D_INIT_REASONS) numprint = 0; + if (BUGLVL(D_INIT)) + printk("no matching shmem)\n"); + if (BUGLVL(D_INIT_REASONS)) { + printk("S5: "); + numprint = 0; + } } if (!found) release_region(*port, ARCNET_TOTAL_SIZE); *port-- = ports[--numports]; } - BUGLVL(D_INIT_REASONS) printk("\n"); + if (BUGLVL(D_INIT_REASONS)) + printk("\n"); /* Now put back TESTvalue on all leftover shmems. */ for (index = 0; index < numshmems; index++) { @@ -603,8 +618,8 @@ static int com90xx_reset(struct net_device *dev, int really_reset) ACOMMAND(CONFIGcmd | EXTconf); /* clean out all the memory to make debugging make more sense :) */ - BUGLVL(D_DURING) - memset_io(lp->mem_start, 0x42, 2048); + if (BUGLVL(D_DURING)) + memset_io(lp->mem_start, 0x42, 2048); /* done! return success. */ return 0; diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index e78b76535acc..824d71fcfd53 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -149,7 +149,8 @@ static void rx(struct net_device *dev, int bufnum, pkt->soft.raw + sizeof(pkt->soft), length - sizeof(pkt->soft)); - BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, skb, "rx"); skb->protocol = type_trans(skb, dev); netif_rx(skb); diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 4ebfbcbe5de3..d052976ebdfa 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -221,7 +221,8 @@ static void rx(struct net_device *dev, int bufnum, dev->stats.rx_crc_errors++; } } - BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, skb, "rx"); skb->protocol = type_trans(skb, dev); netif_rx(skb); @@ -353,7 +354,8 @@ static void rx(struct net_device *dev, int bufnum, skb->len, pkt->hard.source); BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n", skb->len, pkt->hard.source); - BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + if (BUGLVL(D_SKB)) + arcnet_dump_skb(dev, skb, "rx"); skb->protocol = type_trans(skb, dev); netif_rx(skb); -- cgit v1.2.3 From a34c0932c3b2f28542825ffc5280d562c49ad42d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:55 -0700 Subject: arcnet: Convert BUGMSG and BUGMSG2 to arc_prink and arc_cont These macros don't actually represent BUG uses but are more commonly used as logging macros, so use a more kernel style macro. Convert the BUGMSG from a netdev_ like use to actually use netdev_. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 16 +-- drivers/net/arcnet/arc-rimi.c | 24 +++-- drivers/net/arcnet/arcnet.c | 212 ++++++++++++++++++++------------------ drivers/net/arcnet/capmode.c | 35 ++++--- drivers/net/arcnet/com20020-isa.c | 15 +-- drivers/net/arcnet/com20020-pci.c | 2 +- drivers/net/arcnet/com20020.c | 64 ++++++------ drivers/net/arcnet/com90io.c | 43 ++++---- drivers/net/arcnet/com90xx.c | 119 ++++++++++----------- drivers/net/arcnet/rfc1051.c | 16 +-- drivers/net/arcnet/rfc1201.c | 104 ++++++++++--------- 11 files changed, 338 insertions(+), 312 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 998c8356e576..034c8988f987 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -89,7 +89,7 @@ static void rx(struct net_device *dev, int bufnum, struct archdr *pkt = pkthdr; int ofs; - BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length); + arc_printk(D_DURING, dev, "it's a raw packet (length=%d)\n", length); if (length > MTU) ofs = 512 - length; @@ -98,7 +98,7 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { - BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); + arc_printk(D_NORMAL, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } @@ -163,15 +163,15 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, struct arc_hardware *hard = &pkt->hard; int ofs; - BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", - lp->next_tx, lp->cur_tx, bufnum); + arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", + lp->next_tx, lp->cur_tx, bufnum); length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ if (length > XMTU) { /* should never happen! other people already check for this. */ - BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n", - length, XMTU); + arc_printk(D_NORMAL, dev, "Bug! prepare_tx with size %d (> %d)\n", + length, XMTU); length = XMTU; } if (length >= MinTU) { @@ -184,8 +184,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, hard->offset[0] = ofs = 256 - length; } - BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", - length, ofs); + arc_printk(D_DURING, dev, "prepare_tx: length=%d ofs=%d\n", + length, ofs); lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length); diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index cd47a1b3008c..25f84b7437f3 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -147,7 +147,7 @@ static int __init arcrimi_found(struct net_device *dev) p = ioremap(dev->mem_start, MIRROR_SIZE); if (!p) { release_mem_region(dev->mem_start, MIRROR_SIZE); - BUGMSG(D_NORMAL, "Can't ioremap\n"); + arc_printk(D_NORMAL, dev, "Can't ioremap\n"); return -ENODEV; } @@ -155,7 +155,7 @@ static int __init arcrimi_found(struct net_device *dev) if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (RIM I)", dev)) { iounmap(p); release_mem_region(dev->mem_start, MIRROR_SIZE); - BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); + arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq); return -ENODEV; } @@ -210,23 +210,24 @@ static int __init arcrimi_found(struct net_device *dev) if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)")) { - BUGMSG(D_NORMAL, "Card memory already allocated\n"); + arc_printk(D_NORMAL, dev, "Card memory already allocated\n"); goto err_free_irq; } lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1); if (!lp->mem_start) { - BUGMSG(D_NORMAL, "Can't remap device memory!\n"); + arc_printk(D_NORMAL, dev, "Can't remap device memory!\n"); goto err_release_mem; } /* get and check the station ID from offset 1 in shmem */ dev->dev_addr[0] = readb(lp->mem_start + 1); - BUGMSG(D_NORMAL, "ARCnet RIM I: station %02Xh found at IRQ %d, ShMem %lXh (%ld*%d bytes)\n", - dev->dev_addr[0], - dev->irq, dev->mem_start, - (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size); + arc_printk(D_NORMAL, dev, "ARCnet RIM I: station %02Xh found at IRQ %d, ShMem %lXh (%ld*%d bytes)\n", + dev->dev_addr[0], + dev->irq, dev->mem_start, + (dev->mem_end - dev->mem_start + 1) / mirror_size, + mirror_size); err = register_netdev(dev); if (err) @@ -255,7 +256,8 @@ static int arcrimi_reset(struct net_device *dev, int really_reset) struct arcnet_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->mem_start + 0x800; - BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS()); + arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n", + dev->name, ASTATUS()); if (really_reset) { writeb(TESTvalue, ioaddr - 0x800); /* fake reset */ @@ -301,7 +303,7 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset, struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; - TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count)); + TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset, @@ -310,7 +312,7 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; - TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); + TIME(dev, "memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); } static int node; diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 7a90b8a45a37..2aab7e2f7e4a 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -236,11 +236,11 @@ static void release_arcbuf(struct net_device *dev, int bufnum) lp->first_free_buf %= 5; if (BUGLVL(D_DURING)) { - BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ", - bufnum); + arc_printk(D_DURING, dev, "release_arcbuf: freed #%d; buffer queue is now: ", + bufnum); for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) - BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); - BUGMSG2(D_DURING, "\n"); + arc_cont(D_DURING, "#%d ", lp->buf_queue[i]); + arc_cont(D_DURING, "\n"); } } @@ -254,14 +254,14 @@ static int get_arcbuf(struct net_device *dev) if (!atomic_dec_and_test(&lp->buf_lock)) { /* already in this function */ - BUGMSG(D_NORMAL, "get_arcbuf: overlap (%d)!\n", - lp->buf_lock.counter); + arc_printk(D_NORMAL, dev, "get_arcbuf: overlap (%d)!\n", + lp->buf_lock.counter); } else { /* we can continue */ if (lp->next_buf >= 5) lp->next_buf -= 5; if (lp->next_buf == lp->first_free_buf) { - BUGMSG(D_NORMAL, "get_arcbuf: BUG: no buffers are available??\n"); + arc_printk(D_NORMAL, dev, "get_arcbuf: BUG: no buffers are available??\n"); } else { buf = lp->buf_queue[lp->next_buf++]; lp->next_buf %= 5; @@ -269,10 +269,11 @@ static int get_arcbuf(struct net_device *dev) } if (BUGLVL(D_DURING)) { - BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf); + arc_printk(D_DURING, dev, "get_arcbuf: got #%d; buffer queue is now: ", + buf); for (i = lp->next_buf; i != lp->first_free_buf; i = (i + 1) % 5) - BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]); - BUGMSG2(D_DURING, "\n"); + arc_cont(D_DURING, "#%d ", lp->buf_queue[i]); + arc_cont(D_DURING, "\n"); } atomic_inc(&lp->buf_lock); @@ -351,20 +352,20 @@ int arcnet_open(struct net_device *dev) struct arcnet_local *lp = netdev_priv(dev); int count, newmtu, error; - BUGMSG(D_INIT, "opened."); + arc_printk(D_INIT, dev, "opened."); if (!try_module_get(lp->hw.owner)) return -ENODEV; if (BUGLVL(D_PROTO)) { - BUGMSG(D_PROTO, "protocol map (default is '%c'): ", - arc_proto_default->suffix); + arc_printk(D_PROTO, dev, "protocol map (default is '%c'): ", + arc_proto_default->suffix); for (count = 0; count < 256; count++) - BUGMSG2(D_PROTO, "%c", arc_proto_map[count]->suffix); - BUGMSG2(D_PROTO, "\n"); + arc_cont(D_PROTO, "%c", arc_proto_map[count]->suffix); + arc_cont(D_PROTO, "\n"); } - BUGMSG(D_INIT, "arcnet_open: resetting card.\n"); + arc_printk(D_INIT, dev, "arcnet_open: resetting card.\n"); /* try to put the card in a defined state - if it fails the first * time, actually reset it. @@ -377,7 +378,7 @@ int arcnet_open(struct net_device *dev) if (newmtu < dev->mtu) dev->mtu = newmtu; - BUGMSG(D_INIT, "arcnet_open: mtu: %d.\n", dev->mtu); + arc_printk(D_INIT, dev, "arcnet_open: mtu: %d.\n", dev->mtu); /* autodetect the encapsulation for each host. */ memset(lp->default_proto, 0, sizeof(lp->default_proto)); @@ -408,27 +409,28 @@ int arcnet_open(struct net_device *dev) lp->hw.open(dev); if (dev->dev_addr[0] == 0) - BUGMSG(D_NORMAL, "WARNING! Station address 00 is reserved for broadcasts!\n"); + arc_printk(D_NORMAL, dev, "WARNING! Station address 00 is reserved for broadcasts!\n"); else if (dev->dev_addr[0] == 255) - BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse DOS networking programs!\n"); + arc_printk(D_NORMAL, dev, "WARNING! Station address FF may confuse DOS networking programs!\n"); - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (ASTATUS() & RESETflag) { - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", + __FILE__, __LINE__, __func__); ACOMMAND(CFLAGScmd | RESETclear); } - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); /* make sure we're ready to receive IRQ's. */ AINTMASK(0); udelay(1); /* give it time to set the mask before * we reset it again. (may not even be * necessary) */ - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->intmask = NORXflag | RECONflag; AINTMASK(lp->intmask); - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); netif_start_queue(dev); @@ -466,20 +468,21 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, uint8_t _daddr, proto_num; struct ArcProto *proto; - BUGMSG(D_DURING, - "create header from %d to %d; protocol %d (%Xh); size %u.\n", - saddr ? *(uint8_t *)saddr : -1, - daddr ? *(uint8_t *)daddr : -1, - type, type, len); + arc_printk(D_DURING, dev, + "create header from %d to %d; protocol %d (%Xh); size %u.\n", + saddr ? *(uint8_t *)saddr : -1, + daddr ? *(uint8_t *)daddr : -1, + type, type, len); if (skb->len != 0 && len != skb->len) - BUGMSG(D_NORMAL, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n", - skb->len, len); + arc_printk(D_NORMAL, dev, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n", + skb->len, len); /* Type is host order - ? */ if (type == ETH_P_ARCNET) { proto = arc_raw_proto; - BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n", proto->suffix); + arc_printk(D_DEBUG, dev, "arc_raw_proto used. proto='%c'\n", + proto->suffix); _daddr = daddr ? *(uint8_t *)daddr : 0; } else if (!daddr) { /* if the dest addr isn't provided, we can't choose an @@ -490,19 +493,19 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, *(uint16_t *)skb_push(skb, 2) = type; /* XXX: Why not use skb->mac_len? */ if (skb->network_header - skb->mac_header != 2) - BUGMSG(D_NORMAL, "arcnet_header: Yikes! diff (%d) is not 2!\n", - (int)(skb->network_header - skb->mac_header)); + arc_printk(D_NORMAL, dev, "arcnet_header: Yikes! diff (%u) is not 2!\n", + skb->network_header - skb->mac_header); return -2; /* return error -- can't transmit yet! */ } else { /* otherwise, we can just add the header as usual. */ _daddr = *(uint8_t *)daddr; proto_num = lp->default_proto[_daddr]; proto = arc_proto_map[proto_num]; - BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n", - proto_num, proto->suffix); + arc_printk(D_DURING, dev, "building header for %02Xh using protocol '%c'\n", + proto_num, proto->suffix); if (proto == &arc_proto_null && arc_bcast_proto != proto) { - BUGMSG(D_DURING, "actually, let's use '%c' instead.\n", - arc_bcast_proto->suffix); + arc_printk(D_DURING, dev, "actually, let's use '%c' instead.\n", + arc_bcast_proto->suffix); proto = arc_bcast_proto; } } @@ -521,22 +524,22 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, unsigned long flags; int freeskb, retval; - BUGMSG(D_DURING, - "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n", - ASTATUS(), lp->cur_tx, lp->next_tx, skb->len, skb->protocol); + arc_printk(D_DURING, dev, + "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n", + ASTATUS(), lp->cur_tx, lp->next_tx, skb->len, skb->protocol); pkt = (struct archdr *)skb->data; soft = &pkt->soft.rfc1201; proto = arc_proto_map[soft->proto]; - BUGMSG(D_SKB_SIZE, "skb: transmitting %d bytes to %02X\n", - skb->len, pkt->hard.dest); + arc_printk(D_SKB_SIZE, dev, "skb: transmitting %d bytes to %02X\n", + skb->len, pkt->hard.dest); if (BUGLVL(D_SKB)) arcnet_dump_skb(dev, skb, "tx"); /* fits in one packet? */ if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) { - BUGMSG(D_NORMAL, "fixme: packet too large: compensating badly!\n"); + arc_printk(D_NORMAL, dev, "fixme: packet too large: compensating badly!\n"); dev_kfree_skb(skb); return NETDEV_TX_OK; /* don't try again */ } @@ -569,9 +572,9 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, if (proto->continue_tx && proto->continue_tx(dev, txbuf)) { - BUGMSG(D_NORMAL, - "bug! continue_tx finished the first time! (proto='%c')\n", - proto->suffix); + arc_printk(D_NORMAL, dev, + "bug! continue_tx finished the first time! (proto='%c')\n", + proto->suffix); } } retval = NETDEV_TX_OK; @@ -581,14 +584,16 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, freeskb = 0; } - BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, ASTATUS()); + arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n", + __FILE__, __LINE__, __func__, ASTATUS()); /* make sure we didn't ignore a TX IRQ while we were in here */ AINTMASK(0); - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->intmask |= TXFREEflag | EXCNAKflag; AINTMASK(lp->intmask); - BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, ASTATUS()); + arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n", + __FILE__, __LINE__, __func__, ASTATUS()); spin_unlock_irqrestore(&lp->lock, flags); if (freeskb) @@ -604,8 +609,8 @@ static int go_tx(struct net_device *dev) { struct arcnet_local *lp = netdev_priv(dev); - BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n", - ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx); + arc_printk(D_DURING, dev, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n", + ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx); if (lp->cur_tx != -1 || lp->next_tx == -1) return 0; @@ -655,8 +660,8 @@ void arcnet_timeout(struct net_device *dev) spin_unlock_irqrestore(&lp->lock, flags); if (time_after(jiffies, lp->last_timeout + 10 * HZ)) { - BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n", - msg, status, lp->intmask, lp->lasttrans_dest); + arc_printk(D_EXTRA, dev, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n", + msg, status, lp->intmask, lp->lasttrans_dest); lp->last_timeout = jiffies; } @@ -675,9 +680,9 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) int recbuf, status, diagstatus, didsomething, boguscount; int retval = IRQ_NONE; - BUGMSG(D_DURING, "\n"); + arc_printk(D_DURING, dev, "\n"); - BUGMSG(D_DURING, "in arcnet_interrupt\n"); + arc_printk(D_DURING, dev, "in arcnet_interrupt\n"); lp = netdev_priv(dev); BUG_ON(!lp); @@ -695,16 +700,16 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) return retval; } - BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", - ASTATUS(), lp->intmask); + arc_printk(D_DURING, dev, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", + ASTATUS(), lp->intmask); boguscount = 5; do { status = ASTATUS(); diagstatus = (status >> 8) & 0xFF; - BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n", - __FILE__, __LINE__, __func__, status); + arc_printk(D_DEBUG, dev, "%s: %d: %s: status=%x\n", + __FILE__, __LINE__, __func__, status); didsomething = 0; /* RESET flag was enabled - card is resetting and if RX is @@ -714,7 +719,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) * Clear it out and start over. */ if (status & RESETflag) { - BUGMSG(D_NORMAL, "spurious reset (status=%Xh)\n", status); + arc_printk(D_NORMAL, dev, "spurious reset (status=%Xh)\n", + status); arcnet_close(dev); arcnet_open(dev); @@ -732,21 +738,21 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) recbuf = -1; if (status & lp->intmask & NORXflag) { recbuf = lp->cur_rx; - BUGMSG(D_DURING, "Buffer #%d: receive irq (status=%Xh)\n", - recbuf, status); + arc_printk(D_DURING, dev, "Buffer #%d: receive irq (status=%Xh)\n", + recbuf, status); lp->cur_rx = get_arcbuf(dev); if (lp->cur_rx != -1) { - BUGMSG(D_DURING, "enabling receive to buffer #%d\n", - lp->cur_rx); + arc_printk(D_DURING, dev, "enabling receive to buffer #%d\n", + lp->cur_rx); ACOMMAND(RXcmd | (lp->cur_rx << 3) | RXbcasts); } didsomething++; } if ((diagstatus & EXCNAKflag)) { - BUGMSG(D_DURING, "EXCNAK IRQ (diagstat=%Xh)\n", - diagstatus); + arc_printk(D_DURING, dev, "EXCNAK IRQ (diagstat=%Xh)\n", + diagstatus); ACOMMAND(NOTXcmd); /* disable transmit */ lp->excnak_pending = 1; @@ -760,20 +766,22 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if ((status & lp->intmask & TXFREEflag) || lp->timed_out) { lp->intmask &= ~(TXFREEflag | EXCNAKflag); - BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status); + arc_printk(D_DURING, dev, "TX IRQ (stat=%Xh)\n", status); if (lp->cur_tx != -1 && !lp->timed_out) { if (!(status & TXACKflag)) { if (lp->lasttrans_dest != 0) { - BUGMSG(D_EXTRA, - "transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n", - status, lp->lasttrans_dest); + arc_printk(D_EXTRA, dev, + "transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n", + status, + lp->lasttrans_dest); dev->stats.tx_errors++; dev->stats.tx_carrier_errors++; } else { - BUGMSG(D_DURING, - "broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n", - status, lp->lasttrans_dest); + arc_printk(D_DURING, dev, + "broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n", + status, + lp->lasttrans_dest); } } @@ -836,29 +844,29 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) ACOMMAND(CFLAGScmd | CONFIGclear); dev->stats.tx_carrier_errors++; - BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n", - status); + arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n", + status); /* MYRECON bit is at bit 7 of diagstatus */ if (diagstatus & 0x80) - BUGMSG(D_RECON, "Put out that recon myself\n"); + arc_printk(D_RECON, dev, "Put out that recon myself\n"); /* is the RECON info empty or old? */ if (!lp->first_recon || !lp->last_recon || time_after(jiffies, lp->last_recon + HZ * 10)) { if (lp->network_down) - BUGMSG(D_NORMAL, "reconfiguration detected: cabling restored?\n"); + arc_printk(D_NORMAL, dev, "reconfiguration detected: cabling restored?\n"); lp->first_recon = lp->last_recon = jiffies; lp->num_recons = lp->network_down = 0; - BUGMSG(D_DURING, "recon: clearing counters.\n"); + arc_printk(D_DURING, dev, "recon: clearing counters.\n"); } else { /* add to current RECON counter */ lp->last_recon = jiffies; lp->num_recons++; - BUGMSG(D_DURING, "recon: counter=%d, time=%lds, net=%d\n", - lp->num_recons, - (lp->last_recon - lp->first_recon) / HZ, - lp->network_down); + arc_printk(D_DURING, dev, "recon: counter=%d, time=%lds, net=%d\n", + lp->num_recons, + (lp->last_recon - lp->first_recon) / HZ, + lp->network_down); /* if network is marked up; * and first_recon and last_recon are 60+ apart; @@ -870,7 +878,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) (lp->last_recon - lp->first_recon) <= HZ * 60 && lp->num_recons >= RECON_THRESHOLD) { lp->network_down = 1; - BUGMSG(D_NORMAL, "many reconfigurations detected: cabling problem?\n"); + arc_printk(D_NORMAL, dev, "many reconfigurations detected: cabling problem?\n"); } else if (!lp->network_down && lp->last_recon - lp->first_recon > HZ * 60) { /* reset counters if we've gone for over a minute. */ @@ -881,20 +889,20 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) } else if (lp->network_down && time_after(jiffies, lp->last_recon + HZ * 10)) { if (lp->network_down) - BUGMSG(D_NORMAL, "cabling restored?\n"); + arc_printk(D_NORMAL, dev, "cabling restored?\n"); lp->first_recon = lp->last_recon = 0; lp->num_recons = lp->network_down = 0; - BUGMSG(D_DURING, "not recon: clearing counters anyway.\n"); + arc_printk(D_DURING, dev, "not recon: clearing counters anyway.\n"); } if (didsomething) retval |= IRQ_HANDLED; } while (--boguscount && didsomething); - BUGMSG(D_DURING, "arcnet_interrupt complete (status=%Xh, count=%d)\n", - ASTATUS(), boguscount); - BUGMSG(D_DURING, "\n"); + arc_printk(D_DURING, dev, "arcnet_interrupt complete (status=%Xh, count=%d)\n", + ASTATUS(), boguscount); + arc_printk(D_DURING, dev, "\n"); AINTMASK(0); udelay(1); @@ -933,8 +941,8 @@ static void arcnet_rx(struct net_device *dev, int bufnum) lp->hw.copy_from_card(dev, bufnum, ofs, soft, length); } - BUGMSG(D_DURING, "Buffer #%d: received packet from %02Xh to %02Xh (%d+4 bytes)\n", - bufnum, pkt.hard.source, pkt.hard.dest, length); + arc_printk(D_DURING, dev, "Buffer #%d: received packet from %02Xh to %02Xh (%d+4 bytes)\n", + bufnum, pkt.hard.source, pkt.hard.dest, length); dev->stats.rx_packets++; dev->stats.rx_bytes += length + ARC_HDR_SIZE; @@ -947,10 +955,10 @@ static void arcnet_rx(struct net_device *dev, int bufnum) *newp = arc_proto_map[soft->proto]; if (oldp != newp) { - BUGMSG(D_PROTO, - "got protocol %02Xh; encap for host %02Xh is now '%c' (was '%c')\n", - soft->proto, pkt.hard.source, - newp->suffix, oldp->suffix); + arc_printk(D_PROTO, dev, + "got protocol %02Xh; encap for host %02Xh is now '%c' (was '%c')\n", + soft->proto, pkt.hard.source, + newp->suffix, oldp->suffix); } } @@ -967,9 +975,9 @@ static void arcnet_rx(struct net_device *dev, int bufnum) static void null_rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) { - BUGMSG(D_PROTO, - "rx: don't know how to deal with proto %02Xh from host %02Xh.\n", - pkthdr->soft.rfc1201.proto, pkthdr->hard.source); + arc_printk(D_PROTO, dev, + "rx: don't know how to deal with proto %02Xh from host %02Xh.\n", + pkthdr->soft.rfc1201.proto, pkthdr->hard.source); } static int null_build_header(struct sk_buff *skb, struct net_device *dev, @@ -977,9 +985,9 @@ static int null_build_header(struct sk_buff *skb, struct net_device *dev, { struct arcnet_local *lp = netdev_priv(dev); - BUGMSG(D_PROTO, - "tx: can't build header for encap %02Xh; load a protocol driver.\n", - lp->default_proto[daddr]); + arc_printk(D_PROTO, dev, + "tx: can't build header for encap %02Xh; load a protocol driver.\n", + lp->default_proto[daddr]); /* always fails */ return 0; @@ -992,7 +1000,7 @@ static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, struct arcnet_local *lp = netdev_priv(dev); struct arc_hardware newpkt; - BUGMSG(D_PROTO, "tx: no encap for this host; load a protocol driver.\n"); + arc_printk(D_PROTO, dev, "tx: no encap for this host; load a protocol driver.\n"); /* send a packet to myself -- will never get received, of course */ newpkt.source = newpkt.dest = dev->dev_addr[0]; diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index e7ec907f4680..d62d1accf4b6 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -47,7 +47,8 @@ static void rx(struct net_device *dev, int bufnum, char *pktbuf, *pkthdrbuf; int ofs; - BUGMSG(D_DURING, "it's a raw(cap) packet (length=%d)\n", length); + arc_printk(D_DURING, dev, "it's a raw(cap) packet (length=%d)\n", + length); if (length >= MinTU) ofs = 512 - length; @@ -56,7 +57,7 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE + sizeof(int), GFP_ATOMIC); if (skb == NULL) { - BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); + arc_printk(D_NORMAL, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } @@ -102,8 +103,8 @@ static int build_header(struct sk_buff *skb, int hdr_size = ARC_HDR_SIZE; struct archdr *pkt = (struct archdr *)skb_push(skb, hdr_size); - BUGMSG(D_PROTO, "Preparing header for cap packet %x.\n", - *((int *)&pkt->soft.cap.cookie[0])); + arc_printk(D_PROTO, dev, "Preparing header for cap packet %x.\n", + *((int *)&pkt->soft.cap.cookie[0])); /* Set the source hardware address. * @@ -140,16 +141,16 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, /* And neither is the cookie field */ length -= sizeof(int); - BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", - lp->next_tx, lp->cur_tx, bufnum); + arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", + lp->next_tx, lp->cur_tx, bufnum); - BUGMSG(D_PROTO, "Sending for cap packet %x.\n", - *((int *)&pkt->soft.cap.cookie[0])); + arc_printk(D_PROTO, dev, "Sending for cap packet %x.\n", + *((int *)&pkt->soft.cap.cookie[0])); if (length > XMTU) { /* should never happen! other people already check for this. */ - BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n", - length, XMTU); + arc_printk(D_NORMAL, dev, "Bug! prepare_tx with size %d (> %d)\n", + length, XMTU); length = XMTU; } if (length > MinTU) { @@ -162,8 +163,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, hard->offset[0] = ofs = 256 - length; } - BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", - length, ofs); + arc_printk(D_DURING, dev, "prepare_tx: length=%d ofs=%d\n", + length, ofs); /* Copy the arcnet-header + the protocol byte down: */ lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); @@ -188,8 +189,8 @@ static int ack_tx(struct net_device *dev, int acked) struct archdr *ackpkt; int length = sizeof(struct arc_cap); - BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n", - lp->outgoing.skb->protocol, acked); + arc_printk(D_DURING, dev, "capmode: ack_tx: protocol: %x: result: %d\n", + lp->outgoing.skb->protocol, acked); if (BUGLVL(D_SKB)) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx"); @@ -197,7 +198,7 @@ static int ack_tx(struct net_device *dev, int acked) /* Now alloc a skb to send back up through the layers: */ ackskb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (ackskb == NULL) { - BUGMSG(D_NORMAL, "Memory squeeze, can't acknowledge.\n"); + arc_printk(D_NORMAL, dev, "Memory squeeze, can't acknowledge\n"); goto free_outskb; } @@ -213,8 +214,8 @@ static int ack_tx(struct net_device *dev, int acked) ackpkt->soft.cap.proto = 0; /* using protocol 0 for acknowledge */ ackpkt->soft.cap.mes.ack = acked; - BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n", - *((int *)&ackpkt->soft.cap.cookie[0])); + arc_printk(D_PROTO, dev, "Ackknowledge for cap packet %x.\n", + *((int *)&ackpkt->soft.cap.cookie[0])); ackskb->protocol = cpu_to_be16(ETH_P_ARCNET); diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index af87c7482478..c3748f7c5081 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -58,16 +58,16 @@ static int __init com20020isa_probe(struct net_device *dev) ioaddr = dev->base_addr; if (!ioaddr) { - BUGMSG(D_NORMAL, "No autoprobe (yet) for IO mapped cards; you must specify the base address!\n"); + arc_printk(D_NORMAL, dev, "No autoprobe (yet) for IO mapped cards; you must specify the base address!\n"); return -ENODEV; } if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (COM20020)")) { - BUGMSG(D_NORMAL, "IO region %xh-%xh already allocated.\n", - ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); + arc_printk(D_NORMAL, dev, "IO region %xh-%xh already allocated.\n", + ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); return -ENXIO; } if (ASTATUS() == 0xFF) { - BUGMSG(D_NORMAL, "IO address %x empty\n", ioaddr); + arc_printk(D_NORMAL, dev, "IO address %x empty\n", ioaddr); err = -ENODEV; goto out; } @@ -81,7 +81,8 @@ static int __init com20020isa_probe(struct net_device *dev) * card has just reset and the NORXflag is on until * we tell it to start receiving. */ - BUGMSG(D_INIT_REASONS, "intmask was %02Xh\n", inb(_INTMASK)); + arc_printk(D_INIT_REASONS, dev, "intmask was %02Xh\n", + inb(_INTMASK)); outb(0, _INTMASK); airqmask = probe_irq_on(); outb(NORXflag, _INTMASK); @@ -90,14 +91,14 @@ static int __init com20020isa_probe(struct net_device *dev) dev->irq = probe_irq_off(airqmask); if ((int)dev->irq <= 0) { - BUGMSG(D_INIT_REASONS, "Autoprobe IRQ failed first time\n"); + arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed first time\n"); airqmask = probe_irq_on(); outb(NORXflag, _INTMASK); udelay(5); outb(0, _INTMASK); dev->irq = probe_irq_off(airqmask); if ((int)dev->irq <= 0) { - BUGMSG(D_NORMAL, "Autoprobe IRQ failed.\n"); + arc_printk(D_NORMAL, dev, "Autoprobe IRQ failed.\n"); err = -ENODEV; goto out; } diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index c8184de4480d..0d0cc6a9c618 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -99,7 +99,7 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i lp = netdev_priv(dev); - BUGMSG(D_NORMAL, "%s Controls\n", ci->name); + arc_printk(D_NORMAL, dev, "%s Controls\n", ci->name); ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset; r = devm_request_region(&pdev->dev, ioaddr, cm->size, diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 3170e8ebb7fa..b0b8a0be08e5 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -68,7 +68,7 @@ static void com20020_copy_from_card(struct net_device *dev, int bufnum, outb(ofs & 0xff, _ADDR_LO); /* copy the data */ - TIME("insb", count, insb(_MEMDATA, buf, count)); + TIME(dev, "insb", count, insb(_MEMDATA, buf, count)); } static void com20020_copy_to_card(struct net_device *dev, int bufnum, @@ -81,7 +81,7 @@ static void com20020_copy_to_card(struct net_device *dev, int bufnum, outb(ofs & 0xff, _ADDR_LO); /* copy the data */ - TIME("outsb", count, outsb(_MEMDATA, buf, count)); + TIME(dev, "outsb", count, outsb(_MEMDATA, buf, count)); } /* Reset the card and check some basic stuff during the detection stage. */ @@ -120,10 +120,10 @@ int com20020_check(struct net_device *dev) status = ASTATUS(); if ((status & 0x99) != (NORXflag | TXFREEflag | RESETflag)) { - BUGMSG(D_NORMAL, "status invalid (%Xh).\n", status); + arc_printk(D_NORMAL, dev, "status invalid (%Xh).\n", status); return -ENODEV; } - BUGMSG(D_INIT_REASONS, "status after reset: %X\n", status); + arc_printk(D_INIT_REASONS, dev, "status after reset: %X\n", status); /* Enable TX */ outb(0x39, _CONFIG); @@ -132,16 +132,16 @@ int com20020_check(struct net_device *dev) ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); status = ASTATUS(); - BUGMSG(D_INIT_REASONS, "status after reset acknowledged: %X\n", - status); + arc_printk(D_INIT_REASONS, dev, "status after reset acknowledged: %X\n", + status); /* Read first location of memory */ outb(0 | RDDATAflag | AUTOINCflag, _ADDR_HI); outb(0, _ADDR_LO); if ((status = inb(_MEMDATA)) != TESTvalue) { - BUGMSG(D_NORMAL, "Signature byte not found (%02Xh != D1h).\n", - status); + arc_printk(D_NORMAL, dev, "Signature byte not found (%02Xh != D1h).\n", + status); return -ENODEV; } return 0; @@ -213,24 +213,25 @@ int com20020_found(struct net_device *dev, int shared) /* reserve the irq */ if (request_irq(dev->irq, arcnet_interrupt, shared, "arcnet (COM20020)", dev)) { - BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); + arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq); return -ENODEV; } dev->base_addr = ioaddr; - BUGMSG(D_NORMAL, "%s: station %02Xh found at %03lXh, IRQ %d.\n", - lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq); + arc_printk(D_NORMAL, dev, "%s: station %02Xh found at %03lXh, IRQ %d.\n", + lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq); if (lp->backplane) - BUGMSG(D_NORMAL, "Using backplane mode.\n"); + arc_printk(D_NORMAL, dev, "Using backplane mode.\n"); if (lp->timeout != 3) - BUGMSG(D_NORMAL, "Using extended timeout value of %d.\n", lp->timeout); + arc_printk(D_NORMAL, dev, "Using extended timeout value of %d\n", + lp->timeout); - BUGMSG(D_NORMAL, "Using CKP %d - data rate %s.\n", - lp->setup >> 1, - clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]); + arc_printk(D_NORMAL, dev, "Using CKP %d - data rate %s\n", + lp->setup >> 1, + clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]); if (register_netdev(dev)) { free_irq(dev->irq, dev); @@ -252,16 +253,16 @@ static int com20020_reset(struct net_device *dev, int really_reset) u_int ioaddr = dev->base_addr; u_char inbyte; - BUGMSG(D_DEBUG, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n", - __FILE__, __LINE__, __func__, dev, lp, dev->name); - BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", - dev->name, ASTATUS()); + arc_printk(D_DEBUG, dev, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n", + __FILE__, __LINE__, __func__, dev, lp, dev->name); + arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n", + dev->name, ASTATUS()); - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2); /* power-up defaults */ SETCONF; - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (really_reset) { /* reset the card */ @@ -269,22 +270,23 @@ static int com20020_reset(struct net_device *dev, int really_reset) mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */ } /* clear flags & end reset */ - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); /* verify that the ARCnet signature byte is present */ - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); com20020_copy_from_card(dev, 0, 0, &inbyte, 1); - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (inbyte != TESTvalue) { - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); - BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", + __FILE__, __LINE__, __func__); + arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ ACOMMAND(CONFIGcmd | EXTconf); - BUGMSG(D_DEBUG, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); /* done! return success. */ return 0; @@ -294,7 +296,7 @@ static void com20020_setmask(struct net_device *dev, int mask) { u_int ioaddr = dev->base_addr; - BUGMSG(D_DURING, "Setting mask to %x at %x\n", mask, ioaddr); + arc_printk(D_DURING, dev, "Setting mask to %x at %x\n", mask, ioaddr); AINTMASK(mask); } @@ -336,7 +338,7 @@ static void com20020_set_mc_list(struct net_device *dev) if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { /* Enable promiscuous mode */ if (!(lp->setup & PROMISCset)) - BUGMSG(D_NORMAL, "Setting promiscuous flag...\n"); + arc_printk(D_NORMAL, dev, "Setting promiscuous flag...\n"); SET_SUBADR(SUB_SETUP1); lp->setup |= PROMISCset; outb(lp->setup, _XREG); @@ -344,7 +346,7 @@ static void com20020_set_mc_list(struct net_device *dev) /* Disable promiscuous mode, use normal mode */ { if ((lp->setup & PROMISCset)) - BUGMSG(D_NORMAL, "Resetting promiscuous flag...\n"); + arc_printk(D_NORMAL, dev, "Resetting promiscuous flag...\n"); SET_SUBADR(SUB_SETUP1); lp->setup &= ~PROMISCset; outb(lp->setup, _XREG); diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 33a8531e90c7..ec2db8527862 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -151,16 +151,17 @@ static int __init com90io_probe(struct net_device *dev) } if (!ioaddr) { - BUGMSG(D_NORMAL, "No autoprobe for IO mapped cards; you must specify the base address!\n"); + arc_printk(D_NORMAL, dev, "No autoprobe for IO mapped cards; you must specify the base address!\n"); return -ENODEV; } if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) { - BUGMSG(D_INIT_REASONS, "IO request_region %x-%x failed.\n", - ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); + arc_printk(D_INIT_REASONS, dev, "IO request_region %x-%x failed\n", + ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); return -ENXIO; } if (ASTATUS() == 0xFF) { - BUGMSG(D_INIT_REASONS, "IO address %x empty\n", ioaddr); + arc_printk(D_INIT_REASONS, dev, "IO address %x empty\n", + ioaddr); goto err_out; } inb(_RESET); @@ -169,19 +170,22 @@ static int __init com90io_probe(struct net_device *dev) status = ASTATUS(); if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { - BUGMSG(D_INIT_REASONS, "Status invalid (%Xh).\n", status); + arc_printk(D_INIT_REASONS, dev, "Status invalid (%Xh)\n", + status); goto err_out; } - BUGMSG(D_INIT_REASONS, "Status after reset: %X\n", status); + arc_printk(D_INIT_REASONS, dev, "Status after reset: %X\n", status); ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); - BUGMSG(D_INIT_REASONS, "Status after reset acknowledged: %X\n", status); + arc_printk(D_INIT_REASONS, dev, "Status after reset acknowledged: %X\n", + status); status = ASTATUS(); if (status & RESETflag) { - BUGMSG(D_INIT_REASONS, "Eternal reset (status=%Xh)\n", status); + arc_printk(D_INIT_REASONS, dev, "Eternal reset (status=%Xh)\n", + status); goto err_out; } outb((0x16 | IOMAPflag) & ~ENABLE16flag, _CONFIG); @@ -192,8 +196,8 @@ static int __init com90io_probe(struct net_device *dev) outb(0, _ADDR_LO); if ((status = inb(_MEMDATA)) != 0xd1) { - BUGMSG(D_INIT_REASONS, "Signature byte not found (%Xh instead).\n", - status); + arc_printk(D_INIT_REASONS, dev, "Signature byte not found (%Xh instead).\n", + status); goto err_out; } if (!dev->irq) { @@ -209,7 +213,7 @@ static int __init com90io_probe(struct net_device *dev) dev->irq = probe_irq_off(airqmask); if ((int)dev->irq <= 0) { - BUGMSG(D_INIT_REASONS, "Autoprobe IRQ failed\n"); + arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed\n"); goto err_out; } } @@ -232,7 +236,7 @@ static int __init com90io_found(struct net_device *dev) /* Reserve the irq */ if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (COM90xx-IO)", dev)) { - BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); + arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq); return -ENODEV; } /* Reserve the I/O region */ @@ -266,8 +270,8 @@ static int __init com90io_found(struct net_device *dev) return err; } - BUGMSG(D_NORMAL, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n", - dev->dev_addr[0], dev->base_addr, dev->irq); + arc_printk(D_NORMAL, dev, "COM90IO: station %02Xh found at %03lXh, IRQ %d.\n", + dev->dev_addr[0], dev->base_addr, dev->irq); return 0; } @@ -284,7 +288,8 @@ static int com90io_reset(struct net_device *dev, int really_reset) struct arcnet_local *lp = netdev_priv(dev); short ioaddr = dev->base_addr; - BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS()); + arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n", + dev->name, ASTATUS()); if (really_reset) { /* reset the card */ @@ -300,7 +305,7 @@ static int com90io_reset(struct net_device *dev, int really_reset) /* verify that the ARCnet signature byte is present */ if (get_buffer_byte(dev, 0) != TESTvalue) { - BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); + arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ @@ -334,13 +339,15 @@ static void com90io_setmask(struct net_device *dev, int mask) static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { - TIME("put_whole_buffer", count, put_whole_buffer(dev, bufnum * 512 + offset, count, buf)); + TIME(dev, "put_whole_buffer", count, + put_whole_buffer(dev, bufnum * 512 + offset, count, buf)); } static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, void *buf, int count) { - TIME("get_whole_buffer", count, get_whole_buffer(dev, bufnum * 512 + offset, count, buf)); + TIME(dev, "get_whole_buffer", count, + get_whole_buffer(dev, bufnum * 512 + offset, count, buf)); } static int io; /* use the insmod io= irq= shmem= options */ diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index b5e1c1904f13..12534a3cb4ce 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -157,24 +157,24 @@ static void __init com90xx_probe(void) numprint++; numprint %= 8; if (!numprint) { - BUGMSG2(D_INIT, "\n"); - BUGMSG2(D_INIT, "S1: "); + arc_cont(D_INIT, "\n"); + arc_cont(D_INIT, "S1: "); } - BUGMSG2(D_INIT, "%Xh ", *port); + arc_cont(D_INIT, "%Xh ", *port); ioaddr = *port; if (!request_region(*port, ARCNET_TOTAL_SIZE, "arcnet (90xx)")) { - BUGMSG2(D_INIT_REASONS, "(request_region)\n"); - BUGMSG2(D_INIT_REASONS, "S1: "); + arc_cont(D_INIT_REASONS, "(request_region)\n"); + arc_cont(D_INIT_REASONS, "S1: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; *port-- = ports[--numports]; continue; } if (ASTATUS() == 0xFF) { - BUGMSG2(D_INIT_REASONS, "(empty)\n"); - BUGMSG2(D_INIT_REASONS, "S1: "); + arc_cont(D_INIT_REASONS, "(empty)\n"); + arc_cont(D_INIT_REASONS, "S1: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); @@ -183,15 +183,15 @@ static void __init com90xx_probe(void) } inb(_RESET); /* begin resetting card */ - BUGMSG2(D_INIT_REASONS, "\n"); - BUGMSG2(D_INIT_REASONS, "S1: "); + arc_cont(D_INIT_REASONS, "\n"); + arc_cont(D_INIT_REASONS, "S1: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; } - BUGMSG2(D_INIT, "\n"); + arc_cont(D_INIT, "\n"); if (!numports) { - BUGMSG2(D_NORMAL, "S1: No ARCnet cards found.\n"); + arc_cont(D_NORMAL, "S1: No ARCnet cards found.\n"); kfree(shmems); kfree(iomem); return; @@ -205,12 +205,12 @@ static void __init com90xx_probe(void) numprint++; numprint %= 8; if (!numprint) { - BUGMSG2(D_INIT, "\n"); - BUGMSG2(D_INIT, "S2: "); + arc_cont(D_INIT, "\n"); + arc_cont(D_INIT, "S2: "); } - BUGMSG2(D_INIT, "%Xh ", *port); + arc_cont(D_INIT, "%Xh ", *port); } - BUGMSG2(D_INIT, "\n"); + arc_cont(D_INIT, "\n"); mdelay(RESETtime); /* Stage 3: abandon any shmem addresses that don't have the signature @@ -223,30 +223,30 @@ static void __init com90xx_probe(void) numprint++; numprint %= 8; if (!numprint) { - BUGMSG2(D_INIT, "\n"); - BUGMSG2(D_INIT, "S3: "); + arc_cont(D_INIT, "\n"); + arc_cont(D_INIT, "S3: "); } - BUGMSG2(D_INIT, "%lXh ", *p); + arc_cont(D_INIT, "%lXh ", *p); if (!request_mem_region(*p, MIRROR_SIZE, "arcnet (90xx)")) { - BUGMSG2(D_INIT_REASONS, "(request_mem_region)\n"); - BUGMSG2(D_INIT_REASONS, "Stage 3: "); + arc_cont(D_INIT_REASONS, "(request_mem_region)\n"); + arc_cont(D_INIT_REASONS, "Stage 3: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; goto out; } base = ioremap(*p, MIRROR_SIZE); if (!base) { - BUGMSG2(D_INIT_REASONS, "(ioremap)\n"); - BUGMSG2(D_INIT_REASONS, "Stage 3: "); + arc_cont(D_INIT_REASONS, "(ioremap)\n"); + arc_cont(D_INIT_REASONS, "Stage 3: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; goto out1; } if (readb(base) != TESTvalue) { - BUGMSG2(D_INIT_REASONS, "(%02Xh != %02Xh)\n", - readb(base), TESTvalue); - BUGMSG2(D_INIT_REASONS, "S3: "); + arc_cont(D_INIT_REASONS, "(%02Xh != %02Xh)\n", + readb(base), TESTvalue); + arc_cont(D_INIT_REASONS, "S3: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; goto out2; @@ -258,12 +258,12 @@ static void __init com90xx_probe(void) */ writeb(0x42, base); if (readb(base) != 0x42) { - BUGMSG2(D_INIT_REASONS, "(read only)\n"); - BUGMSG2(D_INIT_REASONS, "S3: "); + arc_cont(D_INIT_REASONS, "(read only)\n"); + arc_cont(D_INIT_REASONS, "S3: "); goto out2; } - BUGMSG2(D_INIT_REASONS, "\n"); - BUGMSG2(D_INIT_REASONS, "S3: "); + arc_cont(D_INIT_REASONS, "\n"); + arc_cont(D_INIT_REASONS, "S3: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; iomem[index] = base; @@ -276,10 +276,10 @@ static void __init com90xx_probe(void) *p-- = shmems[--numshmems]; index--; } - BUGMSG2(D_INIT, "\n"); + arc_cont(D_INIT, "\n"); if (!numshmems) { - BUGMSG2(D_NORMAL, "S3: No ARCnet cards found.\n"); + arc_cont(D_NORMAL, "S3: No ARCnet cards found.\n"); for (port = &ports[0]; port < ports + numports; port++) release_region(*port, ARCNET_TOTAL_SIZE); kfree(shmems); @@ -294,12 +294,12 @@ static void __init com90xx_probe(void) numprint++; numprint %= 8; if (!numprint) { - BUGMSG2(D_INIT, "\n"); - BUGMSG2(D_INIT, "S4: "); + arc_cont(D_INIT, "\n"); + arc_cont(D_INIT, "S4: "); } - BUGMSG2(D_INIT, "%lXh ", *p); + arc_cont(D_INIT, "%lXh ", *p); } - BUGMSG2(D_INIT, "\n"); + arc_cont(D_INIT, "\n"); /* Stage 5: for any ports that have the correct status, can disable * the RESET flag, and (if no irq is given) generate an autoirq, @@ -315,18 +315,18 @@ static void __init com90xx_probe(void) numprint++; numprint %= 8; if (!numprint) { - BUGMSG2(D_INIT, "\n"); - BUGMSG2(D_INIT, "S5: "); + arc_cont(D_INIT, "\n"); + arc_cont(D_INIT, "S5: "); } - BUGMSG2(D_INIT, "%Xh ", *port); + arc_cont(D_INIT, "%Xh ", *port); ioaddr = *port; status = ASTATUS(); if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { - BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status); - BUGMSG2(D_INIT_REASONS, "S5: "); + arc_cont(D_INIT_REASONS, "(status=%Xh)\n", status); + arc_cont(D_INIT_REASONS, "S5: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); @@ -336,9 +336,9 @@ static void __init com90xx_probe(void) ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); status = ASTATUS(); if (status & RESETflag) { - BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n", - status); - BUGMSG2(D_INIT_REASONS, "S5: "); + arc_cont(D_INIT_REASONS, " (eternal reset, status=%Xh)\n", + status); + arc_cont(D_INIT_REASONS, "S5: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); @@ -360,8 +360,8 @@ static void __init com90xx_probe(void) airq = probe_irq_off(airqmask); if (airq <= 0) { - BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq); - BUGMSG2(D_INIT_REASONS, "S5: "); + arc_cont(D_INIT_REASONS, "(airq=%d)\n", airq); + arc_cont(D_INIT_REASONS, "S5: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; release_region(*port, ARCNET_TOTAL_SIZE); @@ -372,7 +372,7 @@ static void __init com90xx_probe(void) airq = irq; } - BUGMSG2(D_INIT, "(%d,", airq); + arc_cont(D_INIT, "(%d,", airq); openparen = 1; /* Everything seems okay. But which shmem, if any, puts @@ -399,7 +399,7 @@ static void __init com90xx_probe(void) void __iomem *base = iomem[index]; if (readb(base) == TESTvalue) { /* found one */ - BUGMSG2(D_INIT, "%lXh)\n", *p); + arc_cont(D_INIT, "%lXh)\n", *p); openparen = 0; /* register the card */ @@ -412,7 +412,7 @@ static void __init com90xx_probe(void) iomem[index] = iomem[numshmems]; break; /* go to the next I/O port */ } else { - BUGMSG2(D_INIT_REASONS, "%Xh-", readb(base)); + arc_cont(D_INIT_REASONS, "%Xh-", readb(base)); } } @@ -476,7 +476,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem /* allocate struct net_device */ dev = alloc_arcdev(device); if (!dev) { - BUGMSG2(D_NORMAL, "com90xx: Can't allocate device!\n"); + arc_cont(D_NORMAL, "com90xx: Can't allocate device!\n"); iounmap(p); release_mem_region(shmem, MIRROR_SIZE); return -ENOMEM; @@ -515,7 +515,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem /* reserve the irq */ if (request_irq(airq, arcnet_interrupt, 0, "arcnet (90xx)", dev)) { - BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", airq); + arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", airq); goto err_release_mem; } dev->irq = airq; @@ -531,7 +531,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem lp->hw.copy_from_card = com90xx_copy_from_card; lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1); if (!lp->mem_start) { - BUGMSG(D_NORMAL, "Can't remap device memory!\n"); + arc_printk(D_NORMAL, dev, "Can't remap device memory!\n"); goto err_free_irq; } @@ -540,10 +540,11 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem dev->base_addr = ioaddr; - BUGMSG(D_NORMAL, "COM90xx station %02Xh found at %03lXh, IRQ %d, ShMem %lXh (%ld*%xh).\n", - dev->dev_addr[0], - dev->base_addr, dev->irq, dev->mem_start, - (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size); + arc_printk(D_NORMAL, dev, "COM90xx station %02Xh found at %03lXh, IRQ %d, ShMem %lXh (%ld*%xh).\n", + dev->dev_addr[0], + dev->base_addr, dev->irq, dev->mem_start, + (dev->mem_end - dev->mem_start + 1) / mirror_size, + mirror_size); if (register_netdev(dev)) goto err_unmap; @@ -595,7 +596,7 @@ static int com90xx_reset(struct net_device *dev, int really_reset) struct arcnet_local *lp = netdev_priv(dev); short ioaddr = dev->base_addr; - BUGMSG(D_INIT, "Resetting (status=%02Xh)\n", ASTATUS()); + arc_printk(D_INIT, dev, "Resetting (status=%02Xh)\n", ASTATUS()); if (really_reset) { /* reset the card */ @@ -611,7 +612,7 @@ static int com90xx_reset(struct net_device *dev, int really_reset) /* verify that the ARCnet signature byte is present */ if (readb(lp->mem_start) != TESTvalue) { if (really_reset) - BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); + arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ @@ -631,7 +632,7 @@ static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; - TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count)); + TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset, @@ -640,7 +641,7 @@ static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offse struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; - TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); + TIME(dev, "memcpy_fromio", count, memcpy_fromio(buf, memaddr, count)); } MODULE_LICENSE("GPL"); diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index 824d71fcfd53..47c7d1a4ef4c 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -124,7 +124,7 @@ static void rx(struct net_device *dev, int bufnum, struct archdr *pkt = pkthdr; int ofs; - BUGMSG(D_DURING, "it's a raw packet (length=%d)\n", length); + arc_printk(D_DURING, dev, "it's a raw packet (length=%d)\n", length); if (length >= MinTU) ofs = 512 - length; @@ -133,7 +133,7 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { - BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); + arc_printk(D_NORMAL, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } @@ -173,8 +173,8 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, soft->proto = ARC_P_ARP_RFC1051; break; default: - BUGMSG(D_NORMAL, "RFC1051: I don't understand protocol %d (%Xh)\n", - type, type); + arc_printk(D_NORMAL, dev, "RFC1051: I don't understand protocol %d (%Xh)\n", + type, type); dev->stats.tx_errors++; dev->stats.tx_aborted_errors++; return 0; @@ -210,15 +210,15 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, struct arc_hardware *hard = &pkt->hard; int ofs; - BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", - lp->next_tx, lp->cur_tx, bufnum); + arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", + lp->next_tx, lp->cur_tx, bufnum); length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ if (length > XMTU) { /* should never happen! other people already check for this. */ - BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n", - length, XMTU); + arc_printk(D_NORMAL, dev, "Bug! prepare_tx with size %d (> %d)\n", + length, XMTU); length = XMTU; } if (length > MinTU) { diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index d052976ebdfa..97af7d92c020 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -136,7 +136,8 @@ static void rx(struct net_device *dev, int bufnum, int saddr = pkt->hard.source, ofs; struct Incoming *in = &lp->rfc1201.incoming[saddr]; - BUGMSG(D_DURING, "it's an RFC1201 packet (length=%d)\n", length); + arc_printk(D_DURING, dev, "it's an RFC1201 packet (length=%d)\n", + length); if (length >= MinTU) ofs = 512 - length; @@ -145,10 +146,10 @@ static void rx(struct net_device *dev, int bufnum, if (soft->split_flag == 0xFF) { /* Exception Packet */ if (length >= 4 + RFC1201_HDR_SIZE) { - BUGMSG(D_DURING, "compensating for exception packet\n"); + arc_printk(D_DURING, dev, "compensating for exception packet\n"); } else { - BUGMSG(D_EXTRA, "short RFC1201 exception packet from %02Xh", - saddr); + arc_printk(D_EXTRA, dev, "short RFC1201 exception packet from %02Xh", + saddr); return; } @@ -159,12 +160,13 @@ static void rx(struct net_device *dev, int bufnum, soft, sizeof(pkt->soft)); } if (!soft->split_flag) { /* not split */ - BUGMSG(D_RX, "incoming is not split (splitflag=%d)\n", - soft->split_flag); + arc_printk(D_RX, dev, "incoming is not split (splitflag=%d)\n", + soft->split_flag); if (in->skb) { /* already assembling one! */ - BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", - in->sequence, soft->split_flag, soft->sequence); + arc_printk(D_EXTRA, dev, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", + in->sequence, soft->split_flag, + soft->sequence); lp->rfc1201.aborted_seq = soft->sequence; dev_kfree_skb_irq(in->skb); dev->stats.rx_errors++; @@ -175,7 +177,7 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { - BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); + arc_printk(D_NORMAL, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } @@ -205,18 +207,18 @@ static void rx(struct net_device *dev, int bufnum, uint8_t *cptr = (uint8_t *)arp + sizeof(struct arphdr); if (!*cptr) { /* is saddr = 00? */ - BUGMSG(D_EXTRA, - "ARP source address was 00h, set to %02Xh.\n", - saddr); + arc_printk(D_EXTRA, dev, + "ARP source address was 00h, set to %02Xh\n", + saddr); dev->stats.rx_crc_errors++; *cptr = saddr; } else { - BUGMSG(D_DURING, "ARP source address (%Xh) is fine.\n", - *cptr); + arc_printk(D_DURING, dev, "ARP source address (%Xh) is fine.\n", + *cptr); } } else { - BUGMSG(D_NORMAL, "funny-shaped ARP packet. (%Xh, %Xh)\n", - arp->ar_hln, arp->ar_pln); + arc_printk(D_NORMAL, dev, "funny-shaped ARP packet. (%Xh, %Xh)\n", + arp->ar_hln, arp->ar_pln); dev->stats.rx_errors++; dev->stats.rx_crc_errors++; } @@ -245,13 +247,13 @@ static void rx(struct net_device *dev, int bufnum, * other way to be reliable. */ - BUGMSG(D_RX, "packet is split (splitflag=%d, seq=%d)\n", - soft->split_flag, in->sequence); + arc_printk(D_RX, dev, "packet is split (splitflag=%d, seq=%d)\n", + soft->split_flag, in->sequence); if (in->skb && in->sequence != soft->sequence) { - BUGMSG(D_EXTRA, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n", - saddr, in->sequence, soft->sequence, - soft->split_flag); + arc_printk(D_EXTRA, dev, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n", + saddr, in->sequence, soft->sequence, + soft->split_flag); dev_kfree_skb_irq(in->skb); in->skb = NULL; dev->stats.rx_errors++; @@ -259,12 +261,12 @@ static void rx(struct net_device *dev, int bufnum, in->lastpacket = in->numpackets = 0; } if (soft->split_flag & 1) { /* first packet in split */ - BUGMSG(D_RX, "brand new splitpacket (splitflag=%d)\n", - soft->split_flag); + arc_printk(D_RX, dev, "brand new splitpacket (splitflag=%d)\n", + soft->split_flag); if (in->skb) { /* already assembling one! */ - BUGMSG(D_EXTRA, "aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n", - in->sequence, soft->split_flag, - soft->sequence); + arc_printk(D_EXTRA, dev, "aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n", + in->sequence, soft->split_flag, + soft->sequence); dev->stats.rx_errors++; dev->stats.rx_missed_errors++; dev_kfree_skb_irq(in->skb); @@ -274,8 +276,8 @@ static void rx(struct net_device *dev, int bufnum, in->lastpacket = 1; if (in->numpackets > 16) { - BUGMSG(D_EXTRA, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n", - soft->split_flag); + arc_printk(D_EXTRA, dev, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n", + soft->split_flag); lp->rfc1201.aborted_seq = soft->sequence; dev->stats.rx_errors++; dev->stats.rx_length_errors++; @@ -284,7 +286,7 @@ static void rx(struct net_device *dev, int bufnum, in->skb = skb = alloc_skb(508 * in->numpackets + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { - BUGMSG(D_NORMAL, "(split) memory squeeze, dropping packet.\n"); + arc_printk(D_NORMAL, dev, "(split) memory squeeze, dropping packet.\n"); lp->rfc1201.aborted_seq = soft->sequence; dev->stats.rx_dropped++; return; @@ -305,9 +307,10 @@ static void rx(struct net_device *dev, int bufnum, */ if (!in->skb) { if (lp->rfc1201.aborted_seq != soft->sequence) { - BUGMSG(D_EXTRA, "can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n", - soft->split_flag, soft->sequence, - lp->rfc1201.aborted_seq); + arc_printk(D_EXTRA, dev, "can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n", + soft->split_flag, + soft->sequence, + lp->rfc1201.aborted_seq); dev->stats.rx_errors++; dev->stats.rx_missed_errors++; } @@ -317,15 +320,16 @@ static void rx(struct net_device *dev, int bufnum, if (packetnum != in->lastpacket) { /* not the right flag! */ /* harmless duplicate? ignore. */ if (packetnum <= in->lastpacket - 1) { - BUGMSG(D_EXTRA, "duplicate splitpacket ignored! (splitflag=%d)\n", - soft->split_flag); + arc_printk(D_EXTRA, dev, "duplicate splitpacket ignored! (splitflag=%d)\n", + soft->split_flag); dev->stats.rx_errors++; dev->stats.rx_frame_errors++; return; } /* "bad" duplicate, kill reassembly */ - BUGMSG(D_EXTRA, "out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n", - in->sequence, soft->split_flag, soft->sequence); + arc_printk(D_EXTRA, dev, "out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n", + in->sequence, soft->split_flag, + soft->sequence); lp->rfc1201.aborted_seq = soft->sequence; dev_kfree_skb_irq(in->skb); in->skb = NULL; @@ -350,10 +354,10 @@ static void rx(struct net_device *dev, int bufnum, in->skb = NULL; in->lastpacket = in->numpackets = 0; - BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (unsplit)\n", - skb->len, pkt->hard.source); - BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n", - skb->len, pkt->hard.source); + arc_printk(D_SKB_SIZE, dev, "skb: received %d bytes from %02X (unsplit)\n", + skb->len, pkt->hard.source); + arc_printk(D_SKB_SIZE, dev, "skb: received %d bytes from %02X (split)\n", + skb->len, pkt->hard.source); if (BUGLVL(D_SKB)) arcnet_dump_skb(dev, skb, "rx"); @@ -395,8 +399,8 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, soft->proto = ARC_P_ATALK; break; default: - BUGMSG(D_NORMAL, "RFC1201: I don't understand protocol %d (%Xh)\n", - type, type); + arc_printk(D_NORMAL, dev, "RFC1201: I don't understand protocol %d (%Xh)\n", + type, type); dev->stats.tx_errors++; dev->stats.tx_aborted_errors++; return 0; @@ -469,8 +473,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, const int maxsegsize = XMTU - RFC1201_HDR_SIZE; struct Outgoing *out; - BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", - lp->next_tx, lp->cur_tx, bufnum); + arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", + lp->next_tx, lp->cur_tx, bufnum); length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ pkt->soft.rfc1201.split_flag = 0; @@ -484,9 +488,9 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, out->numsegs = (out->dataleft + maxsegsize - 1) / maxsegsize; out->segnum = 0; - BUGMSG(D_DURING, "rfc1201 prep_tx: ready for %d-segment split (%d bytes, seq=%d)\n", - out->numsegs, out->length, - pkt->soft.rfc1201.sequence); + arc_printk(D_DURING, dev, "rfc1201 prep_tx: ready for %d-segment split (%d bytes, seq=%d)\n", + out->numsegs, out->length, + pkt->soft.rfc1201.sequence); return 0; /* not done */ } @@ -505,9 +509,9 @@ static int continue_tx(struct net_device *dev, int bufnum) int maxsegsize = XMTU - RFC1201_HDR_SIZE; int seglen; - BUGMSG(D_DURING, - "rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n", - out->segnum, out->numsegs, soft->sequence); + arc_printk(D_DURING, dev, + "rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n", + out->segnum, out->numsegs, soft->sequence); /* the "new" soft header comes right before the data chunk */ newsoft = (struct arc_rfc1201 *) -- cgit v1.2.3 From 05a24b234b9dda3720208b74503f2cf1d05774ee Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:56 -0700 Subject: arcnet: Convert printk to pr_ Use the more current logging style. Remove #define VERSION, use pr_info normally. Add pr_fmt with "arcnet:" prefixes and KBUILD_MODNAME. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 6 +++--- drivers/net/arcnet/arc-rimi.c | 21 +++++++++++---------- drivers/net/arcnet/arcnet.c | 25 ++++++++----------------- drivers/net/arcnet/capmode.c | 6 +++--- drivers/net/arcnet/com20020-isa.c | 9 +++++---- drivers/net/arcnet/com20020-pci.c | 9 +++++---- drivers/net/arcnet/com20020.c | 7 ++++--- drivers/net/arcnet/com20020_cs.c | 5 +++-- drivers/net/arcnet/com90io.c | 11 ++++++----- drivers/net/arcnet/com90xx.c | 17 +++++++++-------- drivers/net/arcnet/rfc1051.c | 7 ++++--- drivers/net/arcnet/rfc1201.c | 6 ++++-- 12 files changed, 65 insertions(+), 64 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 034c8988f987..e4a27029e1c0 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -24,6 +24,8 @@ * ********************** */ +#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt + #include #include #include @@ -33,8 +35,6 @@ #include #include -#define VERSION "arcnet: raw mode (`r') encapsulation support loaded.\n" - static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); static int build_header(struct sk_buff *skb, struct net_device *dev, @@ -56,7 +56,7 @@ static int __init arcnet_raw_init(void) { int count; - printk(VERSION); + pr_info("%s\n", "raw mode (`r') encapsulation support loaded"); for (count = 0; count < 256; count++) if (arc_proto_map[count] == arc_proto_default) diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 25f84b7437f3..7360214e3d3f 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -24,6 +24,9 @@ * * ********************** */ + +#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt + #include #include #include @@ -36,8 +39,6 @@ #include #include -#define VERSION "arcnet: RIM I (entirely mem-mapped) support\n" - /* Internal function declarations */ static int arcrimi_probe(struct net_device *dev); @@ -83,20 +84,20 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse static int __init arcrimi_probe(struct net_device *dev) { if (BUGLVL(D_NORMAL)) { - printk(VERSION); - printk("E-mail me if you actually test the RIM I driver, please!\n"); - printk("Given: node %02Xh, shmem %lXh, irq %d\n", - dev->dev_addr[0], dev->mem_start, dev->irq); + pr_info("%s\n", "RIM I (entirely mem-mapped) support"); + pr_info("E-mail me if you actually test the RIM I driver, please!\n"); + pr_info("Given: node %02Xh, shmem %lXh, irq %d\n", + dev->dev_addr[0], dev->mem_start, dev->irq); } if (dev->mem_start <= 0 || dev->irq <= 0) { if (BUGLVL(D_NORMAL)) - printk("No autoprobe for RIM I; you must specify the shmem and irq!\n"); + pr_err("No autoprobe for RIM I; you must specify the shmem and irq!\n"); return -ENODEV; } if (dev->dev_addr[0] == 0) { if (BUGLVL(D_NORMAL)) - printk("You need to specify your card's station ID!\n"); + pr_err("You need to specify your card's station ID!\n"); return -ENODEV; } /* Grab the memory region at mem_start for MIRROR_SIZE bytes. @@ -106,7 +107,7 @@ static int __init arcrimi_probe(struct net_device *dev) */ if (!request_mem_region(dev->mem_start, MIRROR_SIZE, "arcnet (90xx)")) { if (BUGLVL(D_NORMAL)) - printk("Card memory already allocated\n"); + pr_notice("Card memory already allocated\n"); return -ENODEV; } return arcrimi_found(dev); @@ -375,7 +376,7 @@ static int __init arcrimi_setup(char *s) return 1; switch (ints[0]) { default: /* ERROR */ - printk("arcrimi: Too many arguments.\n"); + pr_err("Too many arguments\n"); case 3: /* Node ID */ node = ints[3]; case 2: /* IRQ */ diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 2aab7e2f7e4a..2be8ab66d067 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -41,7 +41,7 @@ * */ -#define VERSION "arcnet: v3.94 BETA 2007/02/08 - by Avery Pennarun et al.\n" +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include @@ -114,18 +114,7 @@ static int __init arcnet_init(void) arcnet_debug = debug; - printk("arcnet loaded.\n"); - -#ifdef ALPHA_WARNING - if (BUGLVL(D_EXTRA)) { - printk("arcnet: ***\n" - "arcnet: * Read arcnet.txt for important release notes!\n" - "arcnet: *\n" - "arcnet: * This is an ALPHA version! (Last stable release: v3.02) E-mail\n" - "arcnet: * me if you have any questions, comments, or bug reports.\n" - "arcnet: ***\n"); - } -#endif + pr_info("arcnet loaded\n"); /* initialize the protocol map */ arc_raw_proto = arc_proto_default = arc_bcast_proto = &arc_proto_null; @@ -133,10 +122,12 @@ static int __init arcnet_init(void) arc_proto_map[count] = arc_proto_default; if (BUGLVL(D_DURING)) - printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n", - sizeof(struct arc_hardware), sizeof(struct arc_rfc1201), - sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap), - sizeof(struct archdr)); + pr_info("struct sizes: %Zd %Zd %Zd %Zd %Zd\n", + sizeof(struct arc_hardware), + sizeof(struct arc_rfc1201), + sizeof(struct arc_rfc1051), + sizeof(struct arc_eth_encap), + sizeof(struct archdr)); return 0; } diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index d62d1accf4b6..92b553e70d5c 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -26,6 +26,8 @@ * ********************** */ +#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt + #include #include #include @@ -35,8 +37,6 @@ #include #include -#define VERSION "arcnet: cap mode (`c') encapsulation support loaded.\n" - /* packet receiver */ static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) @@ -259,7 +259,7 @@ static void arcnet_cap_init(void) static int __init capmode_module_init(void) { - printk(VERSION); + pr_info("%s\n", "cap mode (`c') encapsulation support loaded"); arcnet_cap_init(); return 0; } diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index c3748f7c5081..f3b2222bcada 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -25,6 +25,9 @@ * * ********************** */ + +#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt + #include #include #include @@ -41,8 +44,6 @@ #include -#define VERSION "arcnet: COM20020 ISA support (by David Woodhouse et al.)\n" - /* We cannot (yet) probe for an IO mapped card, although we can check that * it's where we were told it was, and even do autoirq. */ @@ -54,7 +55,7 @@ static int __init com20020isa_probe(struct net_device *dev) int err; if (BUGLVL(D_NORMAL)) - printk(VERSION); + pr_info("%s\n", "COM20020 ISA support (by David Woodhouse et al.)"); ioaddr = dev->base_addr; if (!ioaddr) { @@ -193,7 +194,7 @@ static int __init com20020isa_setup(char *s) switch (ints[0]) { default: /* ERROR */ - printk("com90xx: Too many arguments.\n"); + pr_info("Too many arguments\n"); case 6: /* Timeout */ timeout = ints[6]; case 5: /* CKP value */ diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 0d0cc6a9c618..7247addf46de 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -26,6 +26,9 @@ * * ********************** */ + +#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt + #include #include #include @@ -42,8 +45,6 @@ #include -#define VERSION "arcnet: COM20020 PCI support\n" - /* Module parameters */ static int node; @@ -105,7 +106,7 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i r = devm_request_region(&pdev->dev, ioaddr, cm->size, "com20020-pci"); if (!r) { - pr_err("IO region %xh-%xh already allocated.\n", + pr_err("IO region %xh-%xh already allocated\n", ioaddr, ioaddr + cm->size - 1); ret = -EBUSY; goto out_port; @@ -403,7 +404,7 @@ static struct pci_driver com20020pci_driver = { static int __init com20020pci_init(void) { if (BUGLVL(D_NORMAL)) - printk(VERSION); + pr_info("%s\n", "COM20020 PCI support"); return pci_register_driver(&com20020pci_driver); } diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index b0b8a0be08e5..e813fc619ac9 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -25,6 +25,9 @@ * * ********************** */ + +#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt + #include #include #include @@ -39,8 +42,6 @@ #include -#define VERSION "arcnet: COM20020 chipset support (by David Woodhouse et al.)\n" - static char *clockrates[] = { "XXXXXXX", "XXXXXXXX", "XXXXXX", "2.5 Mb/s", "1.25Mb/s", "625 Kb/s", "312.5 Kb/s", @@ -368,7 +369,7 @@ MODULE_LICENSE("GPL"); static int __init com20020_module_init(void) { if (BUGLVL(D_NORMAL)) - printk(VERSION); + pr_info("%s\n", "COM20020 chipset support (by David Woodhouse et al.)\n"); return 0; } diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c index 13fe53864383..854169489b68 100644 --- a/drivers/net/arcnet/com20020_cs.c +++ b/drivers/net/arcnet/com20020_cs.c @@ -31,6 +31,9 @@ * * ********************** */ + +#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt + #include #include #include @@ -47,8 +50,6 @@ #include -#define VERSION "arcnet: COM20020 PCMCIA support loaded.\n" - static void regdump(struct net_device *dev) { #ifdef DEBUG diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index ec2db8527862..32abaa8d0dc4 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -25,6 +25,9 @@ * * ********************** */ + +#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt + #include #include #include @@ -37,8 +40,6 @@ #include #include -#define VERSION "arcnet: COM90xx IO-mapped mode support (by David Woodhouse et el.)\n" - /* Internal function declarations */ static int com90io_found(struct net_device *dev); @@ -146,8 +147,8 @@ static int __init com90io_probe(struct net_device *dev) unsigned long airqmask; if (BUGLVL(D_NORMAL)) { - printk(VERSION); - printk("E-mail me if you actually test this driver, please!\n"); + pr_info("%s\n", "COM90xx IO-mapped mode support (by David Woodhouse et el.)"); + pr_info("E-mail me if you actually test this driver, please!\n"); } if (!ioaddr) { @@ -369,7 +370,7 @@ static int __init com90io_setup(char *s) return 0; switch (ints[0]) { default: /* ERROR */ - printk("com90io: Too many arguments.\n"); + pr_err("Too many arguments\n"); case 2: /* IRQ */ irq = ints[2]; case 1: /* IO address */ diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 12534a3cb4ce..50c346b5d907 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -24,6 +24,9 @@ * * ********************** */ + +#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt + #include #include #include @@ -35,8 +38,6 @@ #include #include -#define VERSION "arcnet: COM90xx chipset support\n" - /* Define this to speed up the autoprobe by assuming if only one io port and * shmem are left in the list at Stage 5, they must correspond to each * other. @@ -134,7 +135,7 @@ static void __init com90xx_probe(void) } if (BUGLVL(D_NORMAL)) - printk(VERSION); + pr_info("%s\n", "COM90xx chipset support"); /* set up the arrays where we'll store the possible probe addresses */ numports = numshmems = 0; @@ -418,9 +419,9 @@ static void __init com90xx_probe(void) if (openparen) { if (BUGLVL(D_INIT)) - printk("no matching shmem)\n"); + pr_cont("no matching shmem)\n"); if (BUGLVL(D_INIT_REASONS)) { - printk("S5: "); + pr_cont("S5: "); numprint = 0; } } @@ -430,7 +431,7 @@ static void __init com90xx_probe(void) } if (BUGLVL(D_INIT_REASONS)) - printk("\n"); + pr_cont("\n"); /* Now put back TESTvalue on all leftover shmems. */ for (index = 0; index < numshmems; index++) { @@ -685,13 +686,13 @@ static int __init com90xx_setup(char *s) s = get_options(s, 8, ints); if (!ints[0] && !*s) { - printk("com90xx: Disabled.\n"); + pr_notice("Disabled\n"); return 1; } switch (ints[0]) { default: /* ERROR */ - printk("com90xx: Too many arguments.\n"); + pr_err("Too many arguments\n"); case 3: /* Mem address */ shmem = ints[3]; case 2: /* IRQ */ diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index 47c7d1a4ef4c..d5a0f907ac82 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -23,6 +23,9 @@ * * ********************** */ + +#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt + #include #include #include @@ -32,8 +35,6 @@ #include #include -#define VERSION "arcnet: RFC1051 \"simple standard\" (`s') encapsulation support loaded.\n" - static __be16 type_trans(struct sk_buff *skb, struct net_device *dev); static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); @@ -55,7 +56,7 @@ static struct ArcProto rfc1051_proto = { static int __init arcnet_rfc1051_init(void) { - printk(VERSION); + pr_info("%s\n", "RFC1051 \"simple standard\" (`s') encapsulation support loaded"); arc_proto_map[ARC_P_IP_RFC1051] = arc_proto_map[ARC_P_ARP_RFC1051] diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 97af7d92c020..3dae14166120 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -23,6 +23,9 @@ * * ********************** */ + +#define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt + #include #include #include @@ -32,7 +35,6 @@ #include MODULE_LICENSE("GPL"); -#define VERSION "arcnet: RFC1201 \"standard\" (`a') encapsulation support loaded.\n" static __be16 type_trans(struct sk_buff *skb, struct net_device *dev); static void rx(struct net_device *dev, int bufnum, @@ -56,7 +58,7 @@ static struct ArcProto rfc1201_proto = { static int __init arcnet_rfc1201_init(void) { - printk(VERSION); + pr_info("%s\n", "RFC1201 \"standard\" (`a') encapsulation support loaded"); arc_proto_map[ARC_P_IP] = arc_proto_map[ARC_P_IPV6] -- cgit v1.2.3 From 811eafc02e16996674848d7d057909624fb0cc31 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:57 -0700 Subject: arcnet: Move EXPORT_SYMBOL after declarations Use the normal kernel style for EXPORT_SYMBOL. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arcnet.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 2be8ab66d067..a9535ec9c236 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -68,8 +68,17 @@ static void arcnet_rx(struct net_device *dev, int bufnum); * arc_proto_default instead. It also must not be NULL; if you would like * to set it to NULL, set it to &arc_proto_null instead. */ -struct ArcProto *arc_proto_map[256], *arc_proto_default, - *arc_bcast_proto, *arc_raw_proto; +struct ArcProto *arc_proto_map[256]; +EXPORT_SYMBOL(arc_proto_map); + +struct ArcProto *arc_proto_default; +EXPORT_SYMBOL(arc_proto_default); + +struct ArcProto *arc_bcast_proto; +EXPORT_SYMBOL(arc_bcast_proto); + +struct ArcProto *arc_raw_proto; +EXPORT_SYMBOL(arc_raw_proto); static struct ArcProto arc_proto_null = { .suffix = '?', @@ -84,19 +93,7 @@ static struct ArcProto arc_proto_null = { /* Exported function prototypes */ int arcnet_debug = ARCNET_DEBUG; - -EXPORT_SYMBOL(arc_proto_map); -EXPORT_SYMBOL(arc_proto_default); -EXPORT_SYMBOL(arc_bcast_proto); -EXPORT_SYMBOL(arc_raw_proto); -EXPORT_SYMBOL(arcnet_unregister_proto); EXPORT_SYMBOL(arcnet_debug); -EXPORT_SYMBOL(alloc_arcdev); -EXPORT_SYMBOL(arcnet_interrupt); -EXPORT_SYMBOL(arcnet_open); -EXPORT_SYMBOL(arcnet_close); -EXPORT_SYMBOL(arcnet_send_packet); -EXPORT_SYMBOL(arcnet_timeout); /* Internal function prototypes */ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, @@ -151,7 +148,6 @@ void arcnet_dump_skb(struct net_device *dev, print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len, true); } - EXPORT_SYMBOL(arcnet_dump_skb); #endif @@ -211,6 +207,7 @@ void arcnet_unregister_proto(struct ArcProto *proto) arc_proto_map[count] = arc_proto_default; } } +EXPORT_SYMBOL(arcnet_unregister_proto); /* Add a buffer to the queue. Only the interrupt handler is allowed to do * this, unless interrupts are disabled. @@ -330,6 +327,7 @@ struct net_device *alloc_arcdev(const char *name) return dev; } +EXPORT_SYMBOL(alloc_arcdev); /* Open/initialize the board. This is called sometime after booting when * the 'ifconfig' program is run. @@ -431,6 +429,7 @@ int arcnet_open(struct net_device *dev) module_put(lp->hw.owner); return error; } +EXPORT_SYMBOL(arcnet_open); /* The inverse routine to arcnet_open - shuts down the card. */ int arcnet_close(struct net_device *dev) @@ -450,6 +449,7 @@ int arcnet_close(struct net_device *dev) module_put(lp->hw.owner); return 0; } +EXPORT_SYMBOL(arcnet_close); static int arcnet_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, const void *daddr, @@ -592,6 +592,7 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, return retval; /* no need to try again */ } +EXPORT_SYMBOL(arcnet_send_packet); /* Actually start transmitting a packet that was loaded into a buffer * by prepare_tx. This should _only_ be called by the interrupt handler. @@ -659,6 +660,7 @@ void arcnet_timeout(struct net_device *dev) if (lp->cur_tx == -1) netif_wake_queue(dev); } +EXPORT_SYMBOL(arcnet_timeout); /* The typical workload of the driver: Handle the network interface * interrupts. Establish which device needs attention, and call the correct @@ -902,6 +904,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) spin_unlock(&lp->lock); return retval; } +EXPORT_SYMBOL(arcnet_interrupt); /* This is a generic packet receiver that calls arcnet??_rx depending on the * protocol ID found. -- cgit v1.2.3 From 5628d98fc5e99e29f2a480d4a7b1faba94a0d422 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:58 -0700 Subject: arcnet: Remove unnecessary OOM messages Alloc failures have generic stack dumps so these are redundant. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 1 - drivers/net/arcnet/capmode.c | 5 +---- drivers/net/arcnet/com20020-pci.c | 4 +--- drivers/net/arcnet/rfc1051.c | 1 - drivers/net/arcnet/rfc1201.c | 1 - 5 files changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index e4a27029e1c0..7fc5b0420d62 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -98,7 +98,6 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { - arc_printk(D_NORMAL, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 92b553e70d5c..de80d9e0e53f 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -57,7 +57,6 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE + sizeof(int), GFP_ATOMIC); if (skb == NULL) { - arc_printk(D_NORMAL, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } @@ -197,10 +196,8 @@ static int ack_tx(struct net_device *dev, int acked) /* Now alloc a skb to send back up through the layers: */ ackskb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); - if (ackskb == NULL) { - arc_printk(D_NORMAL, dev, "Memory squeeze, can't acknowledge\n"); + if (ackskb == NULL) goto free_outskb; - } skb_put(ackskb, length + ARC_HDR_SIZE); ackskb->dev = dev; diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 7247addf46de..fc6809b43f8f 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -142,10 +142,8 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *i card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev), GFP_KERNEL); - if (!card) { - pr_err("%s out of memory!\n", __func__); + if (!card) return -ENOMEM; - } card->index = i; card->pci_priv = priv; diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index d5a0f907ac82..7e7eda5b0232 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -134,7 +134,6 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { - arc_printk(D_NORMAL, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 3dae14166120..9040a8be155c 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -179,7 +179,6 @@ static void rx(struct net_device *dev, int bufnum, skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); if (skb == NULL) { - arc_printk(D_NORMAL, dev, "Memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } -- cgit v1.2.3 From 97464eddf9fdbe02abfc44676949e07708cf557f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:05:59 -0700 Subject: arcnet: Remove assignments from ifs Move the assignment above the if like general kernel style. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/com20020-isa.c | 4 +++- drivers/net/arcnet/com20020.c | 3 ++- drivers/net/arcnet/com90io.c | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index f3b2222bcada..352500b8d875 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -107,7 +107,9 @@ static int __init com20020isa_probe(struct net_device *dev) } lp->card_name = "ISA COM20020"; - if ((err = com20020_found(dev, 0)) != 0) + + err = com20020_found(dev, 0); + if (err != 0) goto out; return 0; diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index e813fc619ac9..bea386222149 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -140,7 +140,8 @@ int com20020_check(struct net_device *dev) outb(0 | RDDATAflag | AUTOINCflag, _ADDR_HI); outb(0, _ADDR_LO); - if ((status = inb(_MEMDATA)) != TESTvalue) { + status = inb(_MEMDATA); + if (status != TESTvalue) { arc_printk(D_NORMAL, dev, "Signature byte not found (%02Xh != D1h).\n", status); return -ENODEV; diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 32abaa8d0dc4..11bc589aa8d1 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -196,7 +196,8 @@ static int __init com90io_probe(struct net_device *dev) outb(AUTOINCflag, _ADDR_HI); outb(0, _ADDR_LO); - if ((status = inb(_MEMDATA)) != 0xd1) { + status = inb(_MEMDATA); + if (status != 0xd1) { arc_printk(D_INIT_REASONS, dev, "Signature byte not found (%Xh instead).\n", status); goto err_out; -- cgit v1.2.3 From d8101e7bec352b7b6a154ec2e428d01bddb7e5b4 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:00 -0700 Subject: arcnet: Remove pointer comparisons to NULL Use direct tests of pointer instead. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 2 +- drivers/net/arcnet/capmode.c | 4 ++-- drivers/net/arcnet/rfc1051.c | 2 +- drivers/net/arcnet/rfc1201.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 7fc5b0420d62..40035ee8cb40 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -97,7 +97,7 @@ static void rx(struct net_device *dev, int bufnum, ofs = 256 - length; skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); - if (skb == NULL) { + if (!skb) { dev->stats.rx_dropped++; return; } diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index de80d9e0e53f..a898647ab05d 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -56,7 +56,7 @@ static void rx(struct net_device *dev, int bufnum, ofs = 256 - length; skb = alloc_skb(length + ARC_HDR_SIZE + sizeof(int), GFP_ATOMIC); - if (skb == NULL) { + if (!skb) { dev->stats.rx_dropped++; return; } @@ -196,7 +196,7 @@ static int ack_tx(struct net_device *dev, int acked) /* Now alloc a skb to send back up through the layers: */ ackskb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); - if (ackskb == NULL) + if (!ackskb) goto free_outskb; skb_put(ackskb, length + ARC_HDR_SIZE); diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index 7e7eda5b0232..b76e458b19e0 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -133,7 +133,7 @@ static void rx(struct net_device *dev, int bufnum, ofs = 256 - length; skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); - if (skb == NULL) { + if (!skb) { dev->stats.rx_dropped++; return; } diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 9040a8be155c..1d777c1e8383 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -178,7 +178,7 @@ static void rx(struct net_device *dev, int bufnum, in->sequence = soft->sequence; skb = alloc_skb(length + ARC_HDR_SIZE, GFP_ATOMIC); - if (skb == NULL) { + if (!skb) { dev->stats.rx_dropped++; return; } @@ -286,7 +286,7 @@ static void rx(struct net_device *dev, int bufnum, } in->skb = skb = alloc_skb(508 * in->numpackets + ARC_HDR_SIZE, GFP_ATOMIC); - if (skb == NULL) { + if (!skb) { arc_printk(D_NORMAL, dev, "(split) memory squeeze, dropping packet.\n"); lp->rfc1201.aborted_seq = soft->sequence; dev->stats.rx_dropped++; -- cgit v1.2.3 From d6d7d3ed56e3bfe7fd34108dbe23f0610e3d8621 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:02 -0700 Subject: arcnet: Wrap some long lines Just neatening. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 3 ++- drivers/net/arcnet/arc-rimi.c | 11 ++++++----- drivers/net/arcnet/arcnet.c | 10 +++++++--- drivers/net/arcnet/capmode.c | 3 ++- drivers/net/arcnet/com20020-pci.c | 3 ++- drivers/net/arcnet/com20020.c | 14 ++++++++------ drivers/net/arcnet/com90io.c | 31 +++++++++++++++++++------------ drivers/net/arcnet/com90xx.c | 28 +++++++++++++++++----------- drivers/net/arcnet/rfc1051.c | 3 ++- drivers/net/arcnet/rfc1201.c | 15 ++++++++++----- 10 files changed, 75 insertions(+), 46 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 40035ee8cb40..59b3083c19f9 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -165,7 +165,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", lp->next_tx, lp->cur_tx, bufnum); - length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ + /* hard header is not included in packet length */ + length -= ARC_HDR_SIZE; if (length > XMTU) { /* should never happen! other people already check for this. */ diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 7360214e3d3f..8fa5eb43f308 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -49,8 +49,8 @@ static void arcrimi_setmask(struct net_device *dev, int mask); static int arcrimi_reset(struct net_device *dev, int really_reset); static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count); -static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count); +static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count); /* Handy defines for ARCnet specific stuff */ @@ -215,7 +215,8 @@ static int __init arcrimi_found(struct net_device *dev) goto err_free_irq; } - lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1); + lp->mem_start = ioremap(dev->mem_start, + dev->mem_end - dev->mem_start + 1); if (!lp->mem_start) { arc_printk(D_NORMAL, dev, "Can't remap device memory!\n"); goto err_release_mem; @@ -307,8 +308,8 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset, TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } -static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count) +static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count) { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset; diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index a9535ec9c236..00074e781353 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -759,7 +759,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if ((status & lp->intmask & TXFREEflag) || lp->timed_out) { lp->intmask &= ~(TXFREEflag | EXCNAKflag); - arc_printk(D_DURING, dev, "TX IRQ (stat=%Xh)\n", status); + arc_printk(D_DURING, dev, "TX IRQ (stat=%Xh)\n", + status); if (lp->cur_tx != -1 && !lp->timed_out) { if (!(status & TXACKflag)) { @@ -804,7 +805,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) go_tx(dev); /* continue a split packet, if any */ - if (lp->outgoing.proto && lp->outgoing.proto->continue_tx) { + if (lp->outgoing.proto && + lp->outgoing.proto->continue_tx) { int txbuf = get_arcbuf(dev); if (txbuf != -1) { @@ -874,7 +876,9 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) arc_printk(D_NORMAL, dev, "many reconfigurations detected: cabling problem?\n"); } else if (!lp->network_down && lp->last_recon - lp->first_recon > HZ * 60) { - /* reset counters if we've gone for over a minute. */ + /* reset counters if we've gone for + * over a minute. + */ lp->first_recon = lp->last_recon; lp->num_recons = 1; } diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index a898647ab05d..46a76dcc21aa 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -222,7 +222,8 @@ static int ack_tx(struct net_device *dev, int acked) free_outskb: dev_kfree_skb_irq(lp->outgoing.skb); - lp->outgoing.proto = NULL; /* We are always finished when in this protocol */ + lp->outgoing.proto = NULL; + /* We are always finished when in this protocol */ return 0; } diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index fc6809b43f8f..a28887dfcc9e 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -64,7 +64,8 @@ MODULE_LICENSE("GPL"); static void com20020pci_remove(struct pci_dev *pdev); -static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +static int com20020pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) { struct com20020_pci_card_info *ci; struct net_device *dev; diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index bea386222149..00f910cf7b81 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -192,8 +192,9 @@ int com20020_found(struct net_device *dev, int shared) lp->hw.copy_from_card = com20020_copy_from_card; lp->hw.close = com20020_close; + /* FIXME: do this some other way! */ if (!dev->dev_addr[0]) - dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN * 8); /* FIXME: do this some other way! */ + dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN * 8); SET_SUBADR(SUB_SETUP1); outb(lp->setup, _XREG); @@ -269,7 +270,8 @@ static int com20020_reset(struct net_device *dev, int really_reset) if (really_reset) { /* reset the card */ ARCRESET; - mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */ + mdelay(RESETtime * 2); + /* COM20020 seems to be slower sometimes */ } /* clear flags & end reset */ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); @@ -338,15 +340,15 @@ static void com20020_set_mc_list(struct net_device *dev) struct arcnet_local *lp = netdev_priv(dev); int ioaddr = dev->base_addr; - if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { /* Enable promiscuous mode */ + if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { + /* Enable promiscuous mode */ if (!(lp->setup & PROMISCset)) arc_printk(D_NORMAL, dev, "Setting promiscuous flag...\n"); SET_SUBADR(SUB_SETUP1); lp->setup |= PROMISCset; outb(lp->setup, _XREG); - } else + } else { /* Disable promiscuous mode, use normal mode */ - { if ((lp->setup & PROMISCset)) arc_printk(D_NORMAL, dev, "Resetting promiscuous flag...\n"); SET_SUBADR(SUB_SETUP1); @@ -370,7 +372,7 @@ MODULE_LICENSE("GPL"); static int __init com20020_module_init(void) { if (BUGLVL(D_NORMAL)) - pr_info("%s\n", "COM20020 chipset support (by David Woodhouse et al.)\n"); + pr_info("%s\n", "COM20020 chipset support (by David Woodhouse et al.)"); return 0; } diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 11bc589aa8d1..9e779a53035d 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -49,8 +49,8 @@ static void com90io_setmask(struct net_device *dev, int mask); static int com90io_reset(struct net_device *dev, int really_reset); static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count); -static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count); +static void com90io_copy_from_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count); /* Handy defines for ARCnet specific stuff */ @@ -96,7 +96,8 @@ static u_char get_buffer_byte(struct net_device *dev, unsigned offset) } #ifdef ONE_AT_A_TIME_TX -static void put_buffer_byte(struct net_device *dev, unsigned offset, u_char datum) +static void put_buffer_byte(struct net_device *dev, unsigned offset, + u_char datum) { int ioaddr = dev->base_addr; @@ -108,7 +109,8 @@ static void put_buffer_byte(struct net_device *dev, unsigned offset, u_char datu #endif -static void get_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest) +static void get_whole_buffer(struct net_device *dev, unsigned offset, + unsigned length, char *dest) { int ioaddr = dev->base_addr; @@ -123,7 +125,8 @@ static void get_whole_buffer(struct net_device *dev, unsigned offset, unsigned l #endif } -static void put_whole_buffer(struct net_device *dev, unsigned offset, unsigned length, char *dest) +static void put_whole_buffer(struct net_device *dev, unsigned offset, + unsigned length, char *dest) { int ioaddr = dev->base_addr; @@ -237,12 +240,14 @@ static int __init com90io_found(struct net_device *dev) int err; /* Reserve the irq */ - if (request_irq(dev->irq, arcnet_interrupt, 0, "arcnet (COM90xx-IO)", dev)) { + if (request_irq(dev->irq, arcnet_interrupt, 0, + "arcnet (COM90xx-IO)", dev)) { arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq); return -ENODEV; } /* Reserve the I/O region */ - if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) { + if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, + "arcnet (COM90xx-IO)")) { free_irq(dev->irq, dev); return -EBUSY; } @@ -338,15 +343,15 @@ static void com90io_setmask(struct net_device *dev, int mask) AINTMASK(mask); } -static void com90io_copy_to_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count) +static void com90io_copy_to_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count) { TIME(dev, "put_whole_buffer", count, put_whole_buffer(dev, bufnum * 512 + offset, count, buf)); } -static void com90io_copy_from_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count) +static void com90io_copy_from_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count) { TIME(dev, "get_whole_buffer", count, get_whole_buffer(dev, bufnum * 512 + offset, count, buf)); @@ -418,7 +423,9 @@ static void __exit com90io_exit(void) unregister_netdev(dev); - /* Set the thing back to MMAP mode, in case the old driver is loaded later */ + /* In case the old driver is loaded later, + * set the thing back to MMAP mode + */ outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG); free_irq(dev->irq, dev); diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 50c346b5d907..62100acfb6a7 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -60,8 +60,8 @@ static void com90xx_setmask(struct net_device *dev, int mask); static int com90xx_reset(struct net_device *dev, int really_reset); static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, void *buf, int count); -static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count); +static void com90xx_copy_from_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count); /* Known ARCnet cards */ @@ -165,7 +165,8 @@ static void __init com90xx_probe(void) ioaddr = *port; - if (!request_region(*port, ARCNET_TOTAL_SIZE, "arcnet (90xx)")) { + if (!request_region(*port, ARCNET_TOTAL_SIZE, + "arcnet (90xx)")) { arc_cont(D_INIT_REASONS, "(request_region)\n"); arc_cont(D_INIT_REASONS, "S1: "); if (BUGLVL(D_INIT_REASONS)) @@ -467,7 +468,8 @@ static int check_mirror(unsigned long addr, size_t size) /* Set up the struct net_device associated with this card. Called after * probing succeeds. */ -static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem *p) +static int __init com90xx_found(int ioaddr, int airq, u_long shmem, + void __iomem *p) { struct net_device *dev = NULL; struct arcnet_local *lp; @@ -511,7 +513,9 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem iounmap(p); release_mem_region(shmem, MIRROR_SIZE); - if (!request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)")) + if (!request_mem_region(dev->mem_start, + dev->mem_end - dev->mem_start + 1, + "arcnet (90xx)")) goto err_free_dev; /* reserve the irq */ @@ -530,7 +534,8 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem lp->hw.owner = THIS_MODULE; lp->hw.copy_to_card = com90xx_copy_to_card; lp->hw.copy_from_card = com90xx_copy_from_card; - lp->mem_start = ioremap(dev->mem_start, dev->mem_end - dev->mem_start + 1); + lp->mem_start = ioremap(dev->mem_start, + dev->mem_end - dev->mem_start + 1); if (!lp->mem_start) { arc_printk(D_NORMAL, dev, "Can't remap device memory!\n"); goto err_free_irq; @@ -627,8 +632,8 @@ static int com90xx_reset(struct net_device *dev, int really_reset) return 0; } -static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count) +static void com90xx_copy_to_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count) { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; @@ -636,8 +641,8 @@ static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset, TIME(dev, "memcpy_toio", count, memcpy_toio(memaddr, buf, count)); } -static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset, - void *buf, int count) +static void com90xx_copy_from_card(struct net_device *dev, int bufnum, + int offset, void *buf, int count) { struct arcnet_local *lp = netdev_priv(dev); void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset; @@ -671,7 +676,8 @@ static void __exit com90xx_exit(void) free_irq(dev->irq, dev); iounmap(lp->mem_start); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); - release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); + release_mem_region(dev->mem_start, + dev->mem_end - dev->mem_start + 1); free_netdev(dev); } } diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index b76e458b19e0..691bee5bcd42 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -213,7 +213,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", lp->next_tx, lp->cur_tx, bufnum); - length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ + /* hard header is not included in packet length */ + length -= ARC_HDR_SIZE; if (length > XMTU) { /* should never happen! other people already check for this. */ diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index 1d777c1e8383..aaa1966593aa 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -188,11 +188,14 @@ static void rx(struct net_device *dev, int bufnum, pkt = (struct archdr *)skb->data; soft = &pkt->soft.rfc1201; - /* up to sizeof(pkt->soft) has already been copied from the card */ + /* up to sizeof(pkt->soft) has already + * been copied from the card + */ memcpy(pkt, pkthdr, sizeof(struct archdr)); if (length > sizeof(pkt->soft)) - lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft), - pkt->soft.raw + sizeof(pkt->soft), + lp->hw.copy_from_card(dev, bufnum, + ofs + sizeof(pkt->soft), + pkt->soft.raw + sizeof(pkt->soft), length - sizeof(pkt->soft)); /* ARP packets have problems when sent from some DOS systems: @@ -318,7 +321,8 @@ static void rx(struct net_device *dev, int bufnum, return; } in->lastpacket++; - if (packetnum != in->lastpacket) { /* not the right flag! */ + /* if not the right flag */ + if (packetnum != in->lastpacket) { /* harmless duplicate? ignore. */ if (packetnum <= in->lastpacket - 1) { arc_printk(D_EXTRA, dev, "duplicate splitpacket ignored! (splitflag=%d)\n", @@ -477,7 +481,8 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, arc_printk(D_DURING, dev, "prepare_tx: txbufs=%d/%d/%d\n", lp->next_tx, lp->cur_tx, bufnum); - length -= ARC_HDR_SIZE; /* hard header is not included in packet length */ + /* hard header is not included in packet length */ + length -= ARC_HDR_SIZE; pkt->soft.rfc1201.split_flag = 0; /* need to do a split packet? */ -- cgit v1.2.3 From 26c6d281688e8bb8154fa78c60e551d024f5d0b8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:03 -0700 Subject: arcnet: Move files out of include/linux These #include files don't need to be in the include/linux directory as they can be local to drivers/net/arcnet/ Move them and update the #include statements. Update the MAINTAINERS file pattern by deleting arcdevice from the NETWORKING block as arcnet is currently unmaintained. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 3 +- drivers/net/arcnet/arc-rimi.c | 3 +- drivers/net/arcnet/arcdevice.h | 346 ++++++++++++++++++++++++++++++++++++++ drivers/net/arcnet/arcnet.c | 3 +- drivers/net/arcnet/capmode.c | 3 +- drivers/net/arcnet/com20020-isa.c | 6 +- drivers/net/arcnet/com20020-pci.c | 6 +- drivers/net/arcnet/com20020.c | 6 +- drivers/net/arcnet/com20020.h | 145 ++++++++++++++++ drivers/net/arcnet/com20020_cs.c | 7 +- drivers/net/arcnet/com90io.c | 3 +- drivers/net/arcnet/com90xx.c | 3 +- drivers/net/arcnet/rfc1051.c | 3 +- drivers/net/arcnet/rfc1201.c | 3 +- 14 files changed, 519 insertions(+), 21 deletions(-) create mode 100644 drivers/net/arcnet/arcdevice.h create mode 100644 drivers/net/arcnet/com20020.h (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 59b3083c19f9..35a747a7329e 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -33,7 +33,8 @@ #include #include #include -#include + +#include "arcdevice.h" static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 8fa5eb43f308..37406fffc001 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -37,7 +37,8 @@ #include #include #include -#include + +#include "arcdevice.h" /* Internal function declarations */ diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h new file mode 100644 index 000000000000..9ca135d0f114 --- /dev/null +++ b/drivers/net/arcnet/arcdevice.h @@ -0,0 +1,346 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. NET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions used by the ARCnet driver. + * + * Authors: Avery Pennarun and David Woodhouse + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ +#ifndef _LINUX_ARCDEVICE_H +#define _LINUX_ARCDEVICE_H + +#include +#include + +#ifdef __KERNEL__ +#include + +/* + * RECON_THRESHOLD is the maximum number of RECON messages to receive + * within one minute before printing a "cabling problem" warning. The + * default value should be fine. + * + * After that, a "cabling restored" message will be printed on the next IRQ + * if no RECON messages have been received for 10 seconds. + * + * Do not define RECON_THRESHOLD at all if you want to disable this feature. + */ +#define RECON_THRESHOLD 30 + +/* + * Define this to the minimum "timeout" value. If a transmit takes longer + * than TX_TIMEOUT jiffies, Linux will abort the TX and retry. On a large + * network, or one with heavy network traffic, this timeout may need to be + * increased. The larger it is, though, the longer it will be between + * necessary transmits - don't set this too high. + */ +#define TX_TIMEOUT (HZ * 200 / 1000) + +/* Display warnings about the driver being an ALPHA version. */ +#undef ALPHA_WARNING + +/* + * Debugging bitflags: each option can be enabled individually. + * + * Note: only debug flags included in the ARCNET_DEBUG_MAX define will + * actually be available. GCC will (at least, GCC 2.7.0 will) notice + * lines using a BUGLVL not in ARCNET_DEBUG_MAX and automatically optimize + * them out. + */ +#define D_NORMAL 1 /* important operational info */ +#define D_EXTRA 2 /* useful, but non-vital information */ +#define D_INIT 4 /* show init/probe messages */ +#define D_INIT_REASONS 8 /* show reasons for discarding probes */ +#define D_RECON 32 /* print a message whenever token is lost */ +#define D_PROTO 64 /* debug auto-protocol support */ +/* debug levels below give LOTS of output during normal operation! */ +#define D_DURING 128 /* trace operations (including irq's) */ +#define D_TX 256 /* show tx packets */ +#define D_RX 512 /* show rx packets */ +#define D_SKB 1024 /* show skb's */ +#define D_SKB_SIZE 2048 /* show skb sizes */ +#define D_TIMING 4096 /* show time needed to copy buffers to card */ +#define D_DEBUG 8192 /* Very detailed debug line for line */ + +#ifndef ARCNET_DEBUG_MAX +#define ARCNET_DEBUG_MAX (127) /* change to ~0 if you want detailed debugging */ +#endif + +#ifndef ARCNET_DEBUG +#define ARCNET_DEBUG (D_NORMAL | D_EXTRA) +#endif +extern int arcnet_debug; + +#define BUGLVL(x) ((x) & ARCNET_DEBUG_MAX & arcnet_debug) + +/* macros to simplify debug checking */ +#define arc_printk(x, dev, fmt, ...) \ +do { \ + if (BUGLVL(x)) { \ + if ((x) == D_NORMAL) \ + netdev_warn(dev, fmt, ##__VA_ARGS__); \ + else if ((x) < D_DURING) \ + netdev_info(dev, fmt, ##__VA_ARGS__); \ + else \ + netdev_dbg(dev, fmt, ##__VA_ARGS__); \ + } \ +} while (0) + +#define arc_cont(x, fmt, ...) \ +do { \ + if (BUGLVL(x)) \ + pr_cont(fmt, ##__VA_ARGS__); \ +} while (0) + +/* see how long a function call takes to run, expressed in CPU cycles */ +#define TIME(dev, name, bytes, call) \ +do { \ + if (BUGLVL(D_TIMING)) { \ + unsigned long _x, _y; \ + _x = get_cycles(); \ + call; \ + _y = get_cycles(); \ + arc_printk(D_TIMING, dev, \ + "%s: %d bytes in %lu cycles == %lu Kbytes/100Mcycle\n", \ + name, bytes, _y - _x, \ + 100000000 / 1024 * bytes / (_y - _x + 1)); \ + } else { \ + call; \ + } \ +} while (0) + +/* + * Time needed to reset the card - in ms (milliseconds). This works on my + * SMC PC100. I can't find a reference that tells me just how long I + * should wait. + */ +#define RESETtime (300) + +/* + * These are the max/min lengths of packet payload, not including the + * arc_hardware header, but definitely including the soft header. + * + * Note: packet sizes 254, 255, 256 are impossible because of the way + * ARCnet registers work That's why RFC1201 defines "exception" packets. + * In non-RFC1201 protocols, we have to just tack some extra bytes on the + * end. + */ +#define MTU 253 /* normal packet max size */ +#define MinTU 257 /* extended packet min size */ +#define XMTU 508 /* extended packet max size */ + +/* status/interrupt mask bit fields */ +#define TXFREEflag 0x01 /* transmitter available */ +#define TXACKflag 0x02 /* transmitted msg. ackd */ +#define RECONflag 0x04 /* network reconfigured */ +#define TESTflag 0x08 /* test flag */ +#define EXCNAKflag 0x08 /* excesive nak flag */ +#define RESETflag 0x10 /* power-on-reset */ +#define RES1flag 0x20 /* reserved - usually set by jumper */ +#define RES2flag 0x40 /* reserved - usually set by jumper */ +#define NORXflag 0x80 /* receiver inhibited */ + +/* Flags used for IO-mapped memory operations */ +#define AUTOINCflag 0x40 /* Increase location with each access */ +#define IOMAPflag 0x02 /* (for 90xx) Use IO mapped memory, not mmap */ +#define ENABLE16flag 0x80 /* (for 90xx) Enable 16-bit mode */ + +/* in the command register, the following bits have these meanings: + * 0-2 command + * 3-4 page number (for enable rcv/xmt command) + * 7 receive broadcasts + */ +#define NOTXcmd 0x01 /* disable transmitter */ +#define NORXcmd 0x02 /* disable receiver */ +#define TXcmd 0x03 /* enable transmitter */ +#define RXcmd 0x04 /* enable receiver */ +#define CONFIGcmd 0x05 /* define configuration */ +#define CFLAGScmd 0x06 /* clear flags */ +#define TESTcmd 0x07 /* load test flags */ + +/* flags for "clear flags" command */ +#define RESETclear 0x08 /* power-on-reset */ +#define CONFIGclear 0x10 /* system reconfigured */ + +#define EXCNAKclear 0x0E /* Clear and acknowledge the excive nak bit */ + +/* flags for "load test flags" command */ +#define TESTload 0x08 /* test flag (diagnostic) */ + +/* byte deposited into first address of buffers on reset */ +#define TESTvalue 0321 /* that's octal for 0xD1 :) */ + +/* for "enable receiver" command */ +#define RXbcasts 0x80 /* receive broadcasts */ + +/* flags for "define configuration" command */ +#define NORMALconf 0x00 /* 1-249 byte packets */ +#define EXTconf 0x08 /* 250-504 byte packets */ + +/* card feature flags, set during auto-detection. + * (currently only used by com20020pci) + */ +#define ARC_IS_5MBIT 1 /* card default speed is 5MBit */ +#define ARC_CAN_10MBIT 2 /* card uses COM20022, supporting 10MBit, + but default is 2.5MBit. */ + +/* information needed to define an encapsulation driver */ +struct ArcProto { + char suffix; /* a for RFC1201, e for ether-encap, etc. */ + int mtu; /* largest possible packet */ + int is_ip; /* This is a ip plugin - not a raw thing */ + + void (*rx)(struct net_device *dev, int bufnum, + struct archdr *pkthdr, int length); + int (*build_header)(struct sk_buff *skb, struct net_device *dev, + unsigned short ethproto, uint8_t daddr); + + /* these functions return '1' if the skb can now be freed */ + int (*prepare_tx)(struct net_device *dev, struct archdr *pkt, + int length, int bufnum); + int (*continue_tx)(struct net_device *dev, int bufnum); + int (*ack_tx)(struct net_device *dev, int acked); +}; + +extern struct ArcProto *arc_proto_map[256], *arc_proto_default, + *arc_bcast_proto, *arc_raw_proto; + +/* + * "Incoming" is information needed for each address that could be sending + * to us. Mostly for partially-received split packets. + */ +struct Incoming { + struct sk_buff *skb; /* packet data buffer */ + __be16 sequence; /* sequence number of assembly */ + uint8_t lastpacket, /* number of last packet (from 1) */ + numpackets; /* number of packets in split */ +}; + +/* only needed for RFC1201 */ +struct Outgoing { + struct ArcProto *proto; /* protocol driver that owns this: + * if NULL, no packet is pending. + */ + struct sk_buff *skb; /* buffer from upper levels */ + struct archdr *pkt; /* a pointer into the skb */ + uint16_t length, /* bytes total */ + dataleft, /* bytes left */ + segnum, /* segment being sent */ + numsegs; /* number of segments */ +}; + +struct arcnet_local { + uint8_t config, /* current value of CONFIG register */ + timeout, /* Extended timeout for COM20020 */ + backplane, /* Backplane flag for COM20020 */ + clockp, /* COM20020 clock divider */ + clockm, /* COM20020 clock multiplier flag */ + setup, /* Contents of setup1 register */ + setup2, /* Contents of setup2 register */ + intmask; /* current value of INTMASK register */ + uint8_t default_proto[256]; /* default encap to use for each host */ + int cur_tx, /* buffer used by current transmit, or -1 */ + next_tx, /* buffer where a packet is ready to send */ + cur_rx; /* current receive buffer */ + int lastload_dest, /* can last loaded packet be acked? */ + lasttrans_dest; /* can last TX'd packet be acked? */ + int timed_out; /* need to process TX timeout and drop packet */ + unsigned long last_timeout; /* time of last reported timeout */ + char *card_name; /* card ident string */ + int card_flags; /* special card features */ + + /* On preemtive and SMB a lock is needed */ + spinlock_t lock; + + /* + * Buffer management: an ARCnet card has 4 x 512-byte buffers, each of + * which can be used for either sending or receiving. The new dynamic + * buffer management routines use a simple circular queue of available + * buffers, and take them as they're needed. This way, we simplify + * situations in which we (for example) want to pre-load a transmit + * buffer, or start receiving while we copy a received packet to + * memory. + * + * The rules: only the interrupt handler is allowed to _add_ buffers to + * the queue; thus, this doesn't require a lock. Both the interrupt + * handler and the transmit function will want to _remove_ buffers, so + * we need to handle the situation where they try to do it at the same + * time. + * + * If next_buf == first_free_buf, the queue is empty. Since there are + * only four possible buffers, the queue should never be full. + */ + atomic_t buf_lock; + int buf_queue[5]; + int next_buf, first_free_buf; + + /* network "reconfiguration" handling */ + unsigned long first_recon; /* time of "first" RECON message to count */ + unsigned long last_recon; /* time of most recent RECON */ + int num_recons; /* number of RECONs between first and last. */ + int network_down; /* do we think the network is down? */ + + int excnak_pending; /* We just got an excesive nak interrupt */ + + struct { + uint16_t sequence; /* sequence number (incs with each packet) */ + __be16 aborted_seq; + + struct Incoming incoming[256]; /* one from each address */ + } rfc1201; + + /* really only used by rfc1201, but we'll pretend it's not */ + struct Outgoing outgoing; /* packet currently being sent */ + + /* hardware-specific functions */ + struct { + struct module *owner; + void (*command)(struct net_device *dev, int cmd); + int (*status)(struct net_device *dev); + void (*intmask)(struct net_device *dev, int mask); + int (*reset)(struct net_device *dev, int really_reset); + void (*open)(struct net_device *dev); + void (*close)(struct net_device *dev); + + void (*copy_to_card)(struct net_device *dev, int bufnum, + int offset, void *buf, int count); + void (*copy_from_card)(struct net_device *dev, int bufnum, + int offset, void *buf, int count); + } hw; + + void __iomem *mem_start; /* pointer to ioremap'ed MMIO */ +}; + +#define ARCRESET(x) (lp->hw.reset(dev, (x))) +#define ACOMMAND(x) (lp->hw.command(dev, (x))) +#define ASTATUS() (lp->hw.status(dev)) +#define AINTMASK(x) (lp->hw.intmask(dev, (x))) + +#if ARCNET_DEBUG_MAX & D_SKB +void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); +#else +static inline +void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc) +{ +} +#endif + +void arcnet_unregister_proto(struct ArcProto *proto); +irqreturn_t arcnet_interrupt(int irq, void *dev_id); +struct net_device *alloc_arcdev(const char *name); + +int arcnet_open(struct net_device *dev); +int arcnet_close(struct net_device *dev); +netdev_tx_t arcnet_send_packet(struct sk_buff *skb, + struct net_device *dev); +void arcnet_timeout(struct net_device *dev); + +#endif /* __KERNEL__ */ +#endif /* _LINUX_ARCDEVICE_H */ diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 00074e781353..c8423ee24e71 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -50,9 +50,10 @@ #include #include #include -#include #include +#include "arcdevice.h" + /* "do nothing" functions for protocol drivers */ static void null_rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 46a76dcc21aa..2f2d0d94a80d 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -35,7 +35,8 @@ #include #include #include -#include + +#include "arcdevice.h" /* packet receiver */ static void rx(struct net_device *dev, int bufnum, diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index 352500b8d875..ab5202b506a6 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -39,11 +39,11 @@ #include #include #include -#include -#include - #include +#include "arcdevice.h" +#include "com20020.h" + /* We cannot (yet) probe for an IO mapped card, although we can check that * it's where we were told it was, and even do autoirq. */ diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index a28887dfcc9e..1a75a6982031 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -39,12 +39,12 @@ #include #include #include -#include -#include #include - #include +#include "arcdevice.h" +#include "com20020.h" + /* Module parameters */ static int node; diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 00f910cf7b81..f46e22093c54 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -37,11 +37,11 @@ #include #include #include -#include -#include - #include +#include "arcdevice.h" +#include "com20020.h" + static char *clockrates[] = { "XXXXXXX", "XXXXXXXX", "XXXXXX", "2.5 Mb/s", "1.25Mb/s", "625 Kb/s", "312.5 Kb/s", diff --git a/drivers/net/arcnet/com20020.h b/drivers/net/arcnet/com20020.h new file mode 100644 index 000000000000..85898995b234 --- /dev/null +++ b/drivers/net/arcnet/com20020.h @@ -0,0 +1,145 @@ +/* + * Linux ARCnet driver - COM20020 chipset support - function declarations + * + * Written 1997 by David Woodhouse. + * Written 1994-1999 by Avery Pennarun. + * Derived from skeleton.c by Donald Becker. + * + * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) + * for sponsoring the further development of this driver. + * + * ********************** + * + * The original copyright of skeleton.c was as follows: + * + * skeleton.c Written 1993 by Donald Becker. + * Copyright 1993 United States Government as represented by the + * Director, National Security Agency. This software may only be used + * and distributed according to the terms of the GNU General Public License as + * modified by SRC, incorporated herein by reference. + * + * ********************** + * + * For more details, see drivers/net/arcnet.c + * + * ********************** + */ +#ifndef __COM20020_H +#define __COM20020_H + +int com20020_check(struct net_device *dev); +int com20020_found(struct net_device *dev, int shared); +extern const struct net_device_ops com20020_netdev_ops; + +/* The number of low I/O ports used by the card. */ +#define ARCNET_TOTAL_SIZE 8 + +/* various register addresses */ +#ifdef CONFIG_SA1100_CT6001 +#define BUS_ALIGN 2 /* 8 bit device on a 16 bit bus - needs padding */ +#else +#define BUS_ALIGN 1 +#endif + +#define PLX_PCI_MAX_CARDS 2 + +struct com20020_pci_channel_map { + u32 bar; + u32 offset; + u32 size; /* 0x00 - auto, e.g. length of entire bar */ +}; + +struct com20020_pci_card_info { + const char *name; + int devcount; + + struct com20020_pci_channel_map chan_map_tbl[PLX_PCI_MAX_CARDS]; + + unsigned int flags; +}; + +struct com20020_priv { + struct com20020_pci_card_info *ci; + struct list_head list_dev; +}; + +struct com20020_dev { + struct list_head list; + struct net_device *dev; + + struct com20020_priv *pci_priv; + int index; +}; + +#define _INTMASK (ioaddr+BUS_ALIGN*0) /* writable */ +#define _STATUS (ioaddr+BUS_ALIGN*0) /* readable */ +#define _COMMAND (ioaddr+BUS_ALIGN*1) /* standard arcnet commands */ +#define _DIAGSTAT (ioaddr+BUS_ALIGN*1) /* diagnostic status register */ +#define _ADDR_HI (ioaddr+BUS_ALIGN*2) /* control registers for IO-mapped memory */ +#define _ADDR_LO (ioaddr+BUS_ALIGN*3) +#define _MEMDATA (ioaddr+BUS_ALIGN*4) /* data port for IO-mapped memory */ +#define _SUBADR (ioaddr+BUS_ALIGN*5) /* the extended port _XREG refers to */ +#define _CONFIG (ioaddr+BUS_ALIGN*6) /* configuration register */ +#define _XREG (ioaddr+BUS_ALIGN*7) /* extra registers (indexed by _CONFIG + or _SUBADR) */ + +/* in the ADDR_HI register */ +#define RDDATAflag 0x80 /* next access is a read (not a write) */ + +/* in the DIAGSTAT register */ +#define NEWNXTIDflag 0x02 /* ID to which token is passed has changed */ + +/* in the CONFIG register */ +#define RESETcfg 0x80 /* put card in reset state */ +#define TXENcfg 0x20 /* enable TX */ + +/* in SETUP register */ +#define PROMISCset 0x10 /* enable RCV_ALL */ +#define P1MODE 0x80 /* enable P1-MODE for Backplane */ +#define SLOWARB 0x01 /* enable Slow Arbitration for >=5Mbps */ + +/* COM2002x */ +#define SUB_TENTATIVE 0 /* tentative node ID */ +#define SUB_NODE 1 /* node ID */ +#define SUB_SETUP1 2 /* various options */ +#define SUB_TEST 3 /* test/diag register */ + +/* COM20022 only */ +#define SUB_SETUP2 4 /* sundry options */ +#define SUB_BUSCTL 5 /* bus control options */ +#define SUB_DMACOUNT 6 /* DMA count options */ + +#define SET_SUBADR(x) do { \ + if ((x) < 4) \ + { \ + lp->config = (lp->config & ~0x03) | (x); \ + SETCONF; \ + } \ + else \ + { \ + outb(x, _SUBADR); \ + } \ +} while (0) + +#undef ARCRESET +#undef ASTATUS +#undef ACOMMAND +#undef AINTMASK + +#define ARCRESET { outb(lp->config | 0x80, _CONFIG); \ + udelay(5); \ + outb(lp->config , _CONFIG); \ + } +#define ARCRESET0 { outb(0x18 | 0x80, _CONFIG); \ + udelay(5); \ + outb(0x18 , _CONFIG); \ + } + +#define ASTATUS() inb(_STATUS) +#define ADIAGSTATUS() inb(_DIAGSTAT) +#define ACOMMAND(cmd) outb((cmd),_COMMAND) +#define AINTMASK(msk) outb((msk),_INTMASK) + +#define SETCONF outb(lp->config, _CONFIG) + +#endif /* __COM20020_H */ diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c index 854169489b68..5fdde6946427 100644 --- a/drivers/net/arcnet/com20020_cs.c +++ b/drivers/net/arcnet/com20020_cs.c @@ -42,13 +42,12 @@ #include #include #include -#include -#include - +#include #include #include -#include +#include "arcdevice.h" +#include "com20020.h" static void regdump(struct net_device *dev) { diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 9e779a53035d..ce15d1911048 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -38,7 +38,8 @@ #include #include #include -#include + +#include "arcdevice.h" /* Internal function declarations */ diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 62100acfb6a7..b672795acaa7 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -36,7 +36,8 @@ #include #include #include -#include + +#include "arcdevice.h" /* Define this to speed up the autoprobe by assuming if only one io port and * shmem are left in the list at Stage 5, they must correspond to each diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index 691bee5bcd42..4b1a75469cb1 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -33,7 +33,8 @@ #include #include #include -#include + +#include "arcdevice.h" static __be16 type_trans(struct sk_buff *skb, struct net_device *dev); static void rx(struct net_device *dev, int bufnum, diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index aaa1966593aa..566da5ecdc9d 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -32,7 +32,8 @@ #include #include #include -#include + +#include "arcdevice.h" MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 4e299b922c44d242ac855805aee94d938b06944f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:04 -0700 Subject: arcnet: Make a char * array const char * const Might as well be specific about the use of this array. Add a commment questioning the indexing too. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/com20020.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index f46e22093c54..ddd64bb87b58 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -42,10 +42,10 @@ #include "arcdevice.h" #include "com20020.h" -static char *clockrates[] = { - "XXXXXXX", "XXXXXXXX", "XXXXXX", - "2.5 Mb/s", "1.25Mb/s", "625 Kb/s", "312.5 Kb/s", - "156.25 Kb/s", "Reserved", "Reserved", "Reserved" +static const char * const clockrates[] = { + "XXXXXXX", "XXXXXXXX", "XXXXXX", "2.5 Mb/s", + "1.25Mb/s", "625 Kb/s", "312.5 Kb/s", "156.25 Kb/s", + "Reserved", "Reserved", "Reserved" }; static void com20020_command(struct net_device *dev, int command); @@ -234,7 +234,12 @@ int com20020_found(struct net_device *dev, int shared) arc_printk(D_NORMAL, dev, "Using CKP %d - data rate %s\n", lp->setup >> 1, - clockrates[3 - ((lp->setup2 & 0xF0) >> 4) + ((lp->setup & 0x0F) >> 1)]); + clockrates[3 - + ((lp->setup2 & 0xF0) >> 4) + + ((lp->setup & 0x0F) >> 1)]); + /* The clockrates array index looks very fragile. + * It seems like it could have negative indexing. + */ if (register_netdev(dev)) { free_irq(dev->irq, dev); -- cgit v1.2.3 From e5fcfc1f8d3cfaf432a93d39df3e5d7718c58848 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:05 -0700 Subject: arcnet: Add arcnet_ macros arcnet uses an I/O scheme which can align I/O addresses to word boundaries on different architectures. Add arcnet specific macros which can hide this alignment calculation. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arcdevice.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h index 9ca135d0f114..95e7ed6781c3 100644 --- a/drivers/net/arcnet/arcdevice.h +++ b/drivers/net/arcnet/arcdevice.h @@ -342,5 +342,30 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, struct net_device *dev); void arcnet_timeout(struct net_device *dev); +/* I/O equivalents */ + +/* addr and offset allow register like names to define the actual IO address. + * A configuration option multiplies the offset for alignment. + */ +#define arcnet_inb(addr, offset) \ + inb((addr) + (offset)) +#define arcnet_outb(value, addr, offset) \ + outb(value, (addr) + (offset)) + +#define arcnet_insb(addr, offset, buffer, count) \ + insb((addr) + (offset), buffer, count) +#define arcnet_outsb(addr, offset, buffer, count) \ + outsb((addr) + (offset), buffer, count) + +#define arcnet_inw(addr, offset) \ + inw((addr) + (offset)) +#define arcnet_outw(value, addr, offset) \ + outw(value, (addr) + (offset)) + +#define arcnet_insw(addr, offset, buffer, count) \ + insw((addr) + (offset), buffer, count) +#define arcnet_outsw(addr, offset, buffer, count) \ + outsw((addr) + (offset), buffer, count) + #endif /* __KERNEL__ */ #endif /* _LINUX_ARCDEVICE_H */ -- cgit v1.2.3 From 0fec65130b9f11a73d74f47025491f97f82ba070 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:06 -0700 Subject: arcnet: com20020: Use arcnet_ routines Simplify and make consistent the current uses of inb/outb by using the newly introduced arcnet_ equivalents. o Add new #defines for register offsets There is an register offset, 8, that is unnamed and used as-is. o Remove old #defines that included the ioaddr o Remove obfuscating macros by expanding them in-place where appropriate o Create static inline com20020_set_subaddress for the SET_SUBADR macro There is an unused arcnet config entry CONFIGSA100_CT6001 which added a special #define BUS_ALIGN which was introduced but never used in fullhist git tree commit 22cfce4b82b0 ("[ARCNET]: Fixes.") in Nov 2004 for Linux v2.6.10. This BUS_ALIGN #define tries to allow 8 bit devices to work on a 16 bit bus by aligning addresses to 16 bit boundaries. Move this currently unused CONFIG_SA1100_CT6001 BUS_ALIGN macro from com20020.h to arcdevice.h. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arcdevice.h | 22 +++++--- drivers/net/arcnet/com20020-isa.c | 14 +++--- drivers/net/arcnet/com20020-pci.c | 6 +-- drivers/net/arcnet/com20020.c | 103 +++++++++++++++++++++----------------- drivers/net/arcnet/com20020.h | 74 +++++++++------------------ drivers/net/arcnet/com20020_cs.c | 17 ++++--- 6 files changed, 114 insertions(+), 122 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h index 95e7ed6781c3..4afa32b5e9f1 100644 --- a/drivers/net/arcnet/arcdevice.h +++ b/drivers/net/arcnet/arcdevice.h @@ -344,28 +344,34 @@ void arcnet_timeout(struct net_device *dev); /* I/O equivalents */ +#ifdef CONFIG_SA1100_CT6001 +#define BUS_ALIGN 2 /* 8 bit device on a 16 bit bus - needs padding */ +#else +#define BUS_ALIGN 1 +#endif + /* addr and offset allow register like names to define the actual IO address. * A configuration option multiplies the offset for alignment. */ #define arcnet_inb(addr, offset) \ - inb((addr) + (offset)) + inb((addr) + BUS_ALIGN * (offset)) #define arcnet_outb(value, addr, offset) \ - outb(value, (addr) + (offset)) + outb(value, (addr) + BUS_ALIGN * (offset)) #define arcnet_insb(addr, offset, buffer, count) \ - insb((addr) + (offset), buffer, count) + insb((addr) + BUS_ALIGN * (offset), buffer, count) #define arcnet_outsb(addr, offset, buffer, count) \ - outsb((addr) + (offset), buffer, count) + outsb((addr) + BUS_ALIGN * (offset), buffer, count) #define arcnet_inw(addr, offset) \ - inw((addr) + (offset)) + inw((addr) + BUS_ALIGN * (offset)) #define arcnet_outw(value, addr, offset) \ - outw(value, (addr) + (offset)) + outw(value, (addr) + BUS_ALIGN * (offset)) #define arcnet_insw(addr, offset, buffer, count) \ - insw((addr) + (offset), buffer, count) + insw((addr) + BUS_ALIGN * (offset), buffer, count) #define arcnet_outsw(addr, offset, buffer, count) \ - outsw((addr) + (offset), buffer, count) + outsw((addr) + BUS_ALIGN * (offset), buffer, count) #endif /* __KERNEL__ */ #endif /* _LINUX_ARCDEVICE_H */ diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index ab5202b506a6..b9e9931353b2 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -67,7 +67,7 @@ static int __init com20020isa_probe(struct net_device *dev) ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); return -ENXIO; } - if (ASTATUS() == 0xFF) { + if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) { arc_printk(D_NORMAL, dev, "IO address %x empty\n", ioaddr); err = -ENODEV; goto out; @@ -83,20 +83,20 @@ static int __init com20020isa_probe(struct net_device *dev) * we tell it to start receiving. */ arc_printk(D_INIT_REASONS, dev, "intmask was %02Xh\n", - inb(_INTMASK)); - outb(0, _INTMASK); + arcnet_inb(ioaddr, COM20020_REG_R_STATUS)); + arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK); airqmask = probe_irq_on(); - outb(NORXflag, _INTMASK); + arcnet_outb(NORXflag, ioaddr, COM20020_REG_W_INTMASK); udelay(1); - outb(0, _INTMASK); + arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK); dev->irq = probe_irq_off(airqmask); if ((int)dev->irq <= 0) { arc_printk(D_INIT_REASONS, dev, "Autoprobe IRQ failed first time\n"); airqmask = probe_irq_on(); - outb(NORXflag, _INTMASK); + arcnet_outb(NORXflag, ioaddr, COM20020_REG_W_INTMASK); udelay(5); - outb(0, _INTMASK); + arcnet_outb(0, ioaddr, COM20020_REG_W_INTMASK); dev->irq = probe_irq_off(airqmask); if ((int)dev->irq <= 0) { arc_printk(D_NORMAL, dev, "Autoprobe IRQ failed.\n"); diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 1a75a6982031..9b8212663320 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -117,8 +117,8 @@ static int com20020pci_probe(struct pci_dev *pdev, * ARCNET controller needs * this access to detect bustype */ - outb(0x00, ioaddr + 1); - inb(ioaddr + 1); + arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND); + arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT); dev->base_addr = ioaddr; dev->dev_addr[0] = node; @@ -131,7 +131,7 @@ static int com20020pci_probe(struct pci_dev *pdev, lp->timeout = timeout; lp->hw.owner = THIS_MODULE; - if (ASTATUS() == 0xFF) { + if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) { pr_err("IO address %Xh is empty!\n", ioaddr); ret = -EIO; goto out_port; diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index ddd64bb87b58..d4162750a354 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -65,11 +65,13 @@ static void com20020_copy_from_card(struct net_device *dev, int bufnum, int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset; /* set up the address register */ - outb((ofs >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI); - outb(ofs & 0xff, _ADDR_LO); + arcnet_outb((ofs >> 8) | RDDATAflag | AUTOINCflag, + ioaddr, COM20020_REG_W_ADDR_HI); + arcnet_outb(ofs & 0xff, ioaddr, COM20020_REG_W_ADDR_LO); /* copy the data */ - TIME(dev, "insb", count, insb(_MEMDATA, buf, count)); + TIME(dev, "insb", count, + arcnet_insb(ioaddr, COM20020_REG_RW_MEMDATA, buf, count)); } static void com20020_copy_to_card(struct net_device *dev, int bufnum, @@ -78,11 +80,12 @@ static void com20020_copy_to_card(struct net_device *dev, int bufnum, int ioaddr = dev->base_addr, ofs = 512 * bufnum + offset; /* set up the address register */ - outb((ofs >> 8) | AUTOINCflag, _ADDR_HI); - outb(ofs & 0xff, _ADDR_LO); + arcnet_outb((ofs >> 8) | AUTOINCflag, ioaddr, COM20020_REG_W_ADDR_HI); + arcnet_outb(ofs & 0xff, ioaddr, COM20020_REG_W_ADDR_LO); /* copy the data */ - TIME(dev, "outsb", count, outsb(_MEMDATA, buf, count)); + TIME(dev, "outsb", count, + arcnet_outsb(ioaddr, COM20020_REG_RW_MEMDATA, buf, count)); } /* Reset the card and check some basic stuff during the detection stage. */ @@ -91,7 +94,9 @@ int com20020_check(struct net_device *dev) int ioaddr = dev->base_addr, status; struct arcnet_local *lp = netdev_priv(dev); - ARCRESET0; + arcnet_outb(0x18 | 0x80, ioaddr, COM20020_REG_W_CONFIG); + udelay(5); + arcnet_outb(0x18 , ioaddr, COM20020_REG_W_CONFIG); mdelay(RESETtime); lp->setup = lp->clockm ? 0 : (lp->clockp << 1); @@ -101,24 +106,24 @@ int com20020_check(struct net_device *dev) /* Enable P1Mode for backplane mode */ lp->setup = lp->setup | P1MODE; - SET_SUBADR(SUB_SETUP1); - outb(lp->setup, _XREG); + com20020_set_subaddress(lp, ioaddr, SUB_SETUP1); + arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG); if (lp->clockm != 0) { - SET_SUBADR(SUB_SETUP2); - outb(lp->setup2, _XREG); + com20020_set_subaddress(lp, ioaddr, SUB_SETUP2); + arcnet_outb(lp->setup2, ioaddr, COM20020_REG_W_XREG); /* must now write the magic "restart operation" command */ mdelay(1); - outb(0x18, _COMMAND); + arcnet_outb(0x18, ioaddr, COM20020_REG_W_COMMAND); } lp->config = 0x21 | (lp->timeout << 3) | (lp->backplane << 2); /* set node ID to 0x42 (but transmitter is disabled, so it's okay) */ - SETCONF; - outb(0x42, ioaddr + BUS_ALIGN * 7); + arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); + arcnet_outb(0x42, ioaddr, COM20020_REG_W_XREG); - status = ASTATUS(); + status = arcnet_inb(ioaddr, COM20020_REG_R_STATUS); if ((status & 0x99) != (NORXflag | TXFREEflag | RESETflag)) { arc_printk(D_NORMAL, dev, "status invalid (%Xh).\n", status); @@ -127,20 +132,21 @@ int com20020_check(struct net_device *dev) arc_printk(D_INIT_REASONS, dev, "status after reset: %X\n", status); /* Enable TX */ - outb(0x39, _CONFIG); - outb(inb(ioaddr + BUS_ALIGN * 8), ioaddr + BUS_ALIGN * 7); + arcnet_outb(0x39, ioaddr, COM20020_REG_W_CONFIG); + arcnet_outb(arcnet_inb(ioaddr, 8), ioaddr, COM20020_REG_W_XREG); - ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); - - status = ASTATUS(); + arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear, + ioaddr, COM20020_REG_W_COMMAND); + status = arcnet_inb(ioaddr, COM20020_REG_R_STATUS); arc_printk(D_INIT_REASONS, dev, "status after reset acknowledged: %X\n", status); /* Read first location of memory */ - outb(0 | RDDATAflag | AUTOINCflag, _ADDR_HI); - outb(0, _ADDR_LO); + arcnet_outb(0 | RDDATAflag | AUTOINCflag, + ioaddr, COM20020_REG_W_ADDR_HI); + arcnet_outb(0, ioaddr, COM20020_REG_W_ADDR_LO); - status = inb(_MEMDATA); + status = arcnet_inb(ioaddr, COM20020_REG_RW_MEMDATA); if (status != TESTvalue) { arc_printk(D_NORMAL, dev, "Signature byte not found (%02Xh != D1h).\n", status); @@ -156,8 +162,8 @@ static int com20020_set_hwaddr(struct net_device *dev, void *addr) struct sockaddr *hwaddr = addr; memcpy(dev->dev_addr, hwaddr->sa_data, 1); - SET_SUBADR(SUB_NODE); - outb(dev->dev_addr[0], _XREG); + com20020_set_subaddress(lp, ioaddr, SUB_NODE); + arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG); return 0; } @@ -194,24 +200,24 @@ int com20020_found(struct net_device *dev, int shared) /* FIXME: do this some other way! */ if (!dev->dev_addr[0]) - dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN * 8); + dev->dev_addr[0] = arcnet_inb(ioaddr, 8); - SET_SUBADR(SUB_SETUP1); - outb(lp->setup, _XREG); + com20020_set_subaddress(lp, ioaddr, SUB_SETUP1); + arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG); if (lp->card_flags & ARC_CAN_10MBIT) { - SET_SUBADR(SUB_SETUP2); - outb(lp->setup2, _XREG); + com20020_set_subaddress(lp, ioaddr, SUB_SETUP2); + arcnet_outb(lp->setup2, ioaddr, COM20020_REG_W_XREG); /* must now write the magic "restart operation" command */ mdelay(1); - outb(0x18, _COMMAND); + arcnet_outb(0x18, ioaddr, COM20020_REG_W_COMMAND); } lp->config = 0x20 | (lp->timeout << 3) | (lp->backplane << 2) | 1; /* Default 0x38 + register: Node ID */ - SETCONF; - outb(dev->dev_addr[0], _XREG); + arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); + arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG); /* reserve the irq */ if (request_irq(dev->irq, arcnet_interrupt, shared, @@ -264,23 +270,26 @@ static int com20020_reset(struct net_device *dev, int really_reset) arc_printk(D_DEBUG, dev, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n", __FILE__, __LINE__, __func__, dev, lp, dev->name); arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n", - dev->name, ASTATUS()); + dev->name, arcnet_inb(ioaddr, COM20020_REG_R_STATUS)); arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2); /* power-up defaults */ - SETCONF; + arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); if (really_reset) { /* reset the card */ - ARCRESET; + arcnet_outb(lp->config | 0x80, ioaddr, COM20020_REG_W_CONFIG); + udelay(5); + arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */ } /* clear flags & end reset */ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); - ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); + arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear, + ioaddr, COM20020_REG_W_COMMAND); /* verify that the ARCnet signature byte is present */ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); @@ -294,7 +303,8 @@ static int com20020_reset(struct net_device *dev, int really_reset) return 1; } /* enable extended (512-byte) packets */ - ACOMMAND(CONFIGcmd | EXTconf); + arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM20020_REG_W_COMMAND); + arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); /* done! return success. */ @@ -306,21 +316,22 @@ static void com20020_setmask(struct net_device *dev, int mask) u_int ioaddr = dev->base_addr; arc_printk(D_DURING, dev, "Setting mask to %x at %x\n", mask, ioaddr); - AINTMASK(mask); + arcnet_outb(mask, ioaddr, COM20020_REG_W_INTMASK); } static void com20020_command(struct net_device *dev, int cmd) { u_int ioaddr = dev->base_addr; - ACOMMAND(cmd); + arcnet_outb(cmd, ioaddr, COM20020_REG_W_COMMAND); } static int com20020_status(struct net_device *dev) { u_int ioaddr = dev->base_addr; - return ASTATUS() + (ADIAGSTATUS() << 8); + return arcnet_inb(ioaddr, COM20020_REG_R_STATUS) + + (arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT) << 8); } static void com20020_close(struct net_device *dev) @@ -330,7 +341,7 @@ static void com20020_close(struct net_device *dev) /* disable transmitter */ lp->config &= ~TXENcfg; - SETCONF; + arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); } /* Set or clear the multicast filter for this adaptor. @@ -349,16 +360,16 @@ static void com20020_set_mc_list(struct net_device *dev) /* Enable promiscuous mode */ if (!(lp->setup & PROMISCset)) arc_printk(D_NORMAL, dev, "Setting promiscuous flag...\n"); - SET_SUBADR(SUB_SETUP1); + com20020_set_subaddress(lp, ioaddr, SUB_SETUP1); lp->setup |= PROMISCset; - outb(lp->setup, _XREG); + arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG); } else { /* Disable promiscuous mode, use normal mode */ if ((lp->setup & PROMISCset)) arc_printk(D_NORMAL, dev, "Resetting promiscuous flag...\n"); - SET_SUBADR(SUB_SETUP1); + com20020_set_subaddress(lp, ioaddr, SUB_SETUP1); lp->setup &= ~PROMISCset; - outb(lp->setup, _XREG); + arcnet_outb(lp->setup, ioaddr, COM20020_REG_W_XREG); } } diff --git a/drivers/net/arcnet/com20020.h b/drivers/net/arcnet/com20020.h index 85898995b234..ffb19464b607 100644 --- a/drivers/net/arcnet/com20020.h +++ b/drivers/net/arcnet/com20020.h @@ -1,6 +1,6 @@ /* * Linux ARCnet driver - COM20020 chipset support - function declarations - * + * * Written 1997 by David Woodhouse. * Written 1994-1999 by Avery Pennarun. * Derived from skeleton.c by Donald Becker. @@ -34,13 +34,6 @@ extern const struct net_device_ops com20020_netdev_ops; /* The number of low I/O ports used by the card. */ #define ARCNET_TOTAL_SIZE 8 -/* various register addresses */ -#ifdef CONFIG_SA1100_CT6001 -#define BUS_ALIGN 2 /* 8 bit device on a 16 bit bus - needs padding */ -#else -#define BUS_ALIGN 1 -#endif - #define PLX_PCI_MAX_CARDS 2 struct com20020_pci_channel_map { @@ -71,17 +64,18 @@ struct com20020_dev { int index; }; -#define _INTMASK (ioaddr+BUS_ALIGN*0) /* writable */ -#define _STATUS (ioaddr+BUS_ALIGN*0) /* readable */ -#define _COMMAND (ioaddr+BUS_ALIGN*1) /* standard arcnet commands */ -#define _DIAGSTAT (ioaddr+BUS_ALIGN*1) /* diagnostic status register */ -#define _ADDR_HI (ioaddr+BUS_ALIGN*2) /* control registers for IO-mapped memory */ -#define _ADDR_LO (ioaddr+BUS_ALIGN*3) -#define _MEMDATA (ioaddr+BUS_ALIGN*4) /* data port for IO-mapped memory */ -#define _SUBADR (ioaddr+BUS_ALIGN*5) /* the extended port _XREG refers to */ -#define _CONFIG (ioaddr+BUS_ALIGN*6) /* configuration register */ -#define _XREG (ioaddr+BUS_ALIGN*7) /* extra registers (indexed by _CONFIG - or _SUBADR) */ +#define COM20020_REG_W_INTMASK 0 /* writable */ +#define COM20020_REG_R_STATUS 0 /* readable */ +#define COM20020_REG_W_COMMAND 1 /* standard arcnet commands */ +#define COM20020_REG_R_DIAGSTAT 1 /* diagnostic status */ +#define COM20020_REG_W_ADDR_HI 2 /* control for IO-mapped memory */ +#define COM20020_REG_W_ADDR_LO 3 +#define COM20020_REG_RW_MEMDATA 4 /* data port for IO-mapped memory */ +#define COM20020_REG_W_SUBADR 5 /* the extended port _XREG refers to */ +#define COM20020_REG_W_CONFIG 6 /* configuration */ +#define COM20020_REG_W_XREG 7 /* extra + * (indexed by _CONFIG or _SUBADDR) + */ /* in the ADDR_HI register */ #define RDDATAflag 0x80 /* next access is a read (not a write) */ @@ -109,37 +103,15 @@ struct com20020_dev { #define SUB_BUSCTL 5 /* bus control options */ #define SUB_DMACOUNT 6 /* DMA count options */ -#define SET_SUBADR(x) do { \ - if ((x) < 4) \ - { \ - lp->config = (lp->config & ~0x03) | (x); \ - SETCONF; \ - } \ - else \ - { \ - outb(x, _SUBADR); \ - } \ -} while (0) - -#undef ARCRESET -#undef ASTATUS -#undef ACOMMAND -#undef AINTMASK - -#define ARCRESET { outb(lp->config | 0x80, _CONFIG); \ - udelay(5); \ - outb(lp->config , _CONFIG); \ - } -#define ARCRESET0 { outb(0x18 | 0x80, _CONFIG); \ - udelay(5); \ - outb(0x18 , _CONFIG); \ - } - -#define ASTATUS() inb(_STATUS) -#define ADIAGSTATUS() inb(_DIAGSTAT) -#define ACOMMAND(cmd) outb((cmd),_COMMAND) -#define AINTMASK(msk) outb((msk),_INTMASK) - -#define SETCONF outb(lp->config, _CONFIG) +static inline void com20020_set_subaddress(struct arcnet_local *lp, + int ioaddr, int val) +{ + if (val < 4) { + lp->config = (lp->config & ~0x03) | val; + arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); + } else { + arcnet_outb(val, ioaddr, COM20020_REG_W_SUBADR); + } +} #endif /* __COM20020_H */ diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c index 5fdde6946427..cf607ffcf358 100644 --- a/drivers/net/arcnet/com20020_cs.c +++ b/drivers/net/arcnet/com20020_cs.c @@ -56,25 +56,26 @@ static void regdump(struct net_device *dev) int count; netdev_dbg(dev, "register dump:\n"); - for (count = ioaddr; count < ioaddr + 16; count++) { + for (count = 0; count < 16; count++) { if (!(count % 16)) - pr_cont("%04X:", count); - pr_cont(" %02X", inb(count)); + pr_cont("%04X:", ioaddr + count); + pr_cont(" %02X", arcnet_inb(ioaddr, count)); } pr_cont("\n"); netdev_dbg(dev, "buffer0 dump:\n"); /* set up the address register */ count = 0; - outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI); - outb(count & 0xff, _ADDR_LO); + arcnet_outb((count >> 8) | RDDATAflag | AUTOINCflag, + ioaddr, com20020_REG_W_ADDR_HI); + arcnet_outb(count & 0xff, ioaddr, COM20020_REG_W_ADDR_LO); for (count = 0; count < 256 + 32; count++) { if (!(count % 16)) pr_cont("%04X:", count); /* copy the data */ - pr_cont(" %02X", inb(_MEMDATA)); + pr_cont(" %02X", arcnet_inb(ioaddr, COM20020_REG_RW_MEMDATA)); } pr_cont("\n"); #endif @@ -292,7 +293,9 @@ static int com20020_resume(struct pcmcia_device *link) int ioaddr = dev->base_addr; struct arcnet_local *lp = netdev_priv(dev); - ARCRESET; + arcnet_outb(lp->config | 0x80, ioaddr, COM20020_REG_W_CONFIG); + udelay(5); + arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); } return 0; -- cgit v1.2.3 From f0b9c27c0c933a6545ea57d4edbc56a4db435c84 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:07 -0700 Subject: arcnet: com90io: Use arcnet_ routines Simplify and make consistent the current uses of inb/outb by using the newly introduced arcnet_ equivalents. o Add new #defines for register offsets o Remove old #defines that included the ioaddr o Remove obfuscating macros by expanding them in-place where appropriate Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/com90io.c | 101 ++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 53 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index ce15d1911048..7e084f148fa0 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -59,23 +59,14 @@ static void com90io_copy_from_card(struct net_device *dev, int bufnum, #define ARCNET_TOTAL_SIZE 16 /* COM 9026 controller chip --> ARCnet register addresses */ -#define _INTMASK (ioaddr + 0) /* writable */ -#define _STATUS (ioaddr + 0) /* readable */ -#define _COMMAND (ioaddr + 1) /* writable, returns random vals on read (?) */ -#define _RESET (ioaddr + 8) /* software reset (on read) */ -#define _MEMDATA (ioaddr + 12) /* Data port for IO-mapped memory */ -#define _ADDR_HI (ioaddr + 15) /* Control registers for said */ -#define _ADDR_LO (ioaddr + 14) -#define _CONFIG (ioaddr + 2) /* Configuration register */ - -#undef ASTATUS -#undef ACOMMAND -#undef AINTMASK - -#define ASTATUS() inb(_STATUS) -#define ACOMMAND(cmd) outb((cmd), _COMMAND) -#define AINTMASK(msk) outb((msk), _INTMASK) -#define SETCONF() outb((lp->config), _CONFIG) +#define COM9026_REG_W_INTMASK 0 /* writable */ +#define COM9026_REG_R_STATUS 0 /* readable */ +#define COM9026_REG_W_COMMAND 1 /* writable, returns random vals on read (?) */ +#define COM9026_REG_RW_CONFIG 2 /* Configuration register */ +#define COM9026_REG_R_RESET 8 /* software reset (on read) */ +#define COM9026_REG_RW_MEMDATA 12 /* Data port for IO-mapped memory */ +#define COM9026_REG_W_ADDR_LO 14 /* Control registers for said */ +#define COM9026_REG_W_ADDR_HI 15 /**************************************************************************** * * @@ -90,10 +81,10 @@ static u_char get_buffer_byte(struct net_device *dev, unsigned offset) { int ioaddr = dev->base_addr; - outb(offset >> 8, _ADDR_HI); - outb(offset & 0xff, _ADDR_LO); + arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI); + arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO); - return inb(_MEMDATA); + return arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA); } #ifdef ONE_AT_A_TIME_TX @@ -102,10 +93,10 @@ static void put_buffer_byte(struct net_device *dev, unsigned offset, { int ioaddr = dev->base_addr; - outb(offset >> 8, _ADDR_HI); - outb(offset & 0xff, _ADDR_LO); + arcnet_outb(offset >> 8, ioaddr, COM9026_REG_W_ADDR_HI); + arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO); - outb(datum, _MEMDATA); + arcnet_outb(datum, ioaddr, COM9026_REG_RW_MEMDATA); } #endif @@ -115,14 +106,14 @@ static void get_whole_buffer(struct net_device *dev, unsigned offset, { int ioaddr = dev->base_addr; - outb((offset >> 8) | AUTOINCflag, _ADDR_HI); - outb(offset & 0xff, _ADDR_LO); + arcnet_outb((offset >> 8) | AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI); + arcnet_outb(offset & 0xff, ioaddr, COM9026_REG_W_ADDR_LO); while (length--) #ifdef ONE_AT_A_TIME_RX *(dest++) = get_buffer_byte(dev, offset++); #else - *(dest++) = inb(_MEMDATA); + *(dest++) = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA); #endif } @@ -131,14 +122,14 @@ static void put_whole_buffer(struct net_device *dev, unsigned offset, { int ioaddr = dev->base_addr; - outb((offset >> 8) | AUTOINCflag, _ADDR_HI); - outb(offset & 0xff, _ADDR_LO); + arcnet_outb((offset >> 8) | AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI); + arcnet_outb(offset & 0xff, ioaddr,COM9026_REG_W_ADDR_LO); while (length--) #ifdef ONE_AT_A_TIME_TX put_buffer_byte(dev, offset++, *(dest++)); #else - outb(*(dest++), _MEMDATA); + arcnet_outb(*(dest++), ioaddr, COM9026_REG_RW_MEMDATA); #endif } @@ -164,15 +155,15 @@ static int __init com90io_probe(struct net_device *dev) ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); return -ENXIO; } - if (ASTATUS() == 0xFF) { + if (arcnet_inb(ioaddr, COM9026_REG_R_STATUS) == 0xFF) { arc_printk(D_INIT_REASONS, dev, "IO address %x empty\n", ioaddr); goto err_out; } - inb(_RESET); + arcnet_inb(ioaddr, COM9026_REG_R_RESET); mdelay(RESETtime); - status = ASTATUS(); + status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS); if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { arc_printk(D_INIT_REASONS, dev, "Status invalid (%Xh)\n", @@ -181,26 +172,28 @@ static int __init com90io_probe(struct net_device *dev) } arc_printk(D_INIT_REASONS, dev, "Status after reset: %X\n", status); - ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); + arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear, + ioaddr, COM9026_REG_W_COMMAND); arc_printk(D_INIT_REASONS, dev, "Status after reset acknowledged: %X\n", status); - status = ASTATUS(); + status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS); if (status & RESETflag) { arc_printk(D_INIT_REASONS, dev, "Eternal reset (status=%Xh)\n", status); goto err_out; } - outb((0x16 | IOMAPflag) & ~ENABLE16flag, _CONFIG); + arcnet_outb((0x16 | IOMAPflag) & ~ENABLE16flag, + ioaddr, COM9026_REG_RW_CONFIG); /* Read first loc'n of memory */ - outb(AUTOINCflag, _ADDR_HI); - outb(0, _ADDR_LO); + arcnet_outb(AUTOINCflag, ioaddr, COM9026_REG_W_ADDR_HI); + arcnet_outb(0, ioaddr, COM9026_REG_W_ADDR_LO); - status = inb(_MEMDATA); + status = arcnet_inb(ioaddr, COM9026_REG_RW_MEMDATA); if (status != 0xd1) { arc_printk(D_INIT_REASONS, dev, "Signature byte not found (%Xh instead).\n", status); @@ -213,9 +206,9 @@ static int __init com90io_probe(struct net_device *dev) */ airqmask = probe_irq_on(); - outb(NORXflag, _INTMASK); + arcnet_outb(NORXflag, ioaddr, COM9026_REG_W_INTMASK); udelay(1); - outb(0, _INTMASK); + arcnet_outb(0, ioaddr, COM9026_REG_W_INTMASK); dev->irq = probe_irq_off(airqmask); if ((int)dev->irq <= 0) { @@ -264,7 +257,7 @@ static int __init com90io_found(struct net_device *dev) lp->hw.copy_from_card = com90io_copy_from_card; lp->config = (0x16 | IOMAPflag) & ~ENABLE16flag; - SETCONF(); + arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG); /* get and check the station ID from offset 1 in shmem */ @@ -272,7 +265,8 @@ static int __init com90io_found(struct net_device *dev) err = register_netdev(dev); if (err) { - outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG); + arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) & ~IOMAPflag, + ioaddr, COM9026_REG_RW_CONFIG); free_irq(dev->irq, dev); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); return err; @@ -297,19 +291,20 @@ static int com90io_reset(struct net_device *dev, int really_reset) short ioaddr = dev->base_addr; arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n", - dev->name, ASTATUS()); + dev->name, arcnet_inb(ioaddr, COM9026_REG_R_STATUS)); if (really_reset) { /* reset the card */ - inb(_RESET); + arcnet_inb(ioaddr, COM9026_REG_R_RESET); mdelay(RESETtime); } /* Set the thing to IO-mapped, 8-bit mode */ lp->config = (0x1C | IOMAPflag) & ~ENABLE16flag; - SETCONF(); + arcnet_outb(lp->config, ioaddr, COM9026_REG_RW_CONFIG); - ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */ - ACOMMAND(CFLAGScmd | CONFIGclear); + arcnet_outb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND); + /* clear flags & end reset */ + arcnet_outb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND); /* verify that the ARCnet signature byte is present */ if (get_buffer_byte(dev, 0) != TESTvalue) { @@ -317,8 +312,7 @@ static int com90io_reset(struct net_device *dev, int really_reset) return 1; } /* enable extended (512-byte) packets */ - ACOMMAND(CONFIGcmd | EXTconf); - + arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND); /* done! return success. */ return 0; } @@ -327,21 +321,21 @@ static void com90io_command(struct net_device *dev, int cmd) { short ioaddr = dev->base_addr; - ACOMMAND(cmd); + arcnet_outb(cmd, ioaddr, COM9026_REG_W_COMMAND); } static int com90io_status(struct net_device *dev) { short ioaddr = dev->base_addr; - return ASTATUS(); + return arcnet_inb(ioaddr, COM9026_REG_R_STATUS); } static void com90io_setmask(struct net_device *dev, int mask) { short ioaddr = dev->base_addr; - AINTMASK(mask); + arcnet_outb(mask, ioaddr, COM9026_REG_W_INTMASK); } static void com90io_copy_to_card(struct net_device *dev, int bufnum, @@ -427,7 +421,8 @@ static void __exit com90io_exit(void) /* In case the old driver is loaded later, * set the thing back to MMAP mode */ - outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG); + arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) & ~IOMAPflag, + ioaddr, COM9026_REG_RW_CONFIG); free_irq(dev->irq, dev); release_region(dev->base_addr, ARCNET_TOTAL_SIZE); -- cgit v1.2.3 From 09dfbcd5d178f8e03b5a29c9f3411687ec388c91 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:08 -0700 Subject: arcnet: com90xx: Use arcnet_ routines Simplify and make consistent the current uses of inb/outb by using the newly introduced arcnet_ equivalents. o Add new #defines for register offsets o Remove old #defines that included the ioaddr o Remove obfuscating macros by expanding them in-place where appropriate Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/com90xx.c | 67 ++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 34 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index b672795acaa7..f1cfeb0e1343 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -79,22 +79,14 @@ static int numcards; #define MIRROR_SIZE (BUFFER_SIZE * 4) /* COM 9026 controller chip --> ARCnet register addresses */ -#define _INTMASK (ioaddr + 0) /* writable */ -#define _STATUS (ioaddr + 0) /* readable */ -#define _COMMAND (ioaddr + 1) /* writable, returns random vals on read (?) */ -#define _CONFIG (ioaddr + 2) /* Configuration register */ -#define _RESET (ioaddr + 8) /* software reset (on read) */ -#define _MEMDATA (ioaddr + 12) /* Data port for IO-mapped memory */ -#define _ADDR_HI (ioaddr + 15) /* Control registers for said */ -#define _ADDR_LO (ioaddr + 14) - -#undef ASTATUS -#undef ACOMMAND -#undef AINTMASK - -#define ASTATUS() inb(_STATUS) -#define ACOMMAND(cmd) outb((cmd), _COMMAND) -#define AINTMASK(msk) outb((msk), _INTMASK) +#define COM9026_REG_W_INTMASK 0 /* writable */ +#define COM9026_REG_R_STATUS 0 /* readable */ +#define COM9026_REG_W_COMMAND 1 /* writable, returns random vals on read (?) */ +#define COM9026_REG_RW_CONFIG 2 /* Configuration register */ +#define COM9026_REG_R_RESET 8 /* software reset (on read) */ +#define COM9026_REG_RW_MEMDATA 12 /* Data port for IO-mapped memory */ +#define COM9026_REG_W_ADDR_LO 14 /* Control registers for said */ +#define COM9026_REG_W_ADDR_HI 15 static int com90xx_skip_probe __initdata = 0; @@ -175,7 +167,7 @@ static void __init com90xx_probe(void) *port-- = ports[--numports]; continue; } - if (ASTATUS() == 0xFF) { + if (arcnet_inb(ioaddr, COM9026_REG_R_STATUS) == 0xFF) { arc_cont(D_INIT_REASONS, "(empty)\n"); arc_cont(D_INIT_REASONS, "S1: "); if (BUGLVL(D_INIT_REASONS)) @@ -184,7 +176,8 @@ static void __init com90xx_probe(void) *port-- = ports[--numports]; continue; } - inb(_RESET); /* begin resetting card */ + /* begin resetting card */ + arcnet_inb(ioaddr, COM9026_REG_R_RESET); arc_cont(D_INIT_REASONS, "\n"); arc_cont(D_INIT_REASONS, "S1: "); @@ -324,7 +317,7 @@ static void __init com90xx_probe(void) arc_cont(D_INIT, "%Xh ", *port); ioaddr = *port; - status = ASTATUS(); + status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS); if ((status & 0x9D) != (NORXflag | RECONflag | TXFREEflag | RESETflag)) { @@ -336,8 +329,9 @@ static void __init com90xx_probe(void) *port-- = ports[--numports]; continue; } - ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); - status = ASTATUS(); + arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear, + ioaddr, COM9026_REG_W_COMMAND); + status = arcnet_inb(ioaddr, COM9026_REG_R_STATUS); if (status & RESETflag) { arc_cont(D_INIT_REASONS, " (eternal reset, status=%Xh)\n", status); @@ -357,9 +351,9 @@ static void __init com90xx_probe(void) * we tell it to start receiving. */ airqmask = probe_irq_on(); - AINTMASK(NORXflag); + arcnet_outb(NORXflag, ioaddr, COM9026_REG_W_INTMASK); udelay(1); - AINTMASK(0); + arcnet_outb(0, ioaddr, COM9026_REG_W_INTMASK); airq = probe_irq_off(airqmask); if (airq <= 0) { @@ -386,14 +380,14 @@ static void __init com90xx_probe(void) */ #ifdef FAST_PROBE if (numports > 1 || numshmems > 1) { - inb(_RESET); + arcnet_inb(ioaddr, COM9026_REG_R_RESET); mdelay(RESETtime); } else { /* just one shmem and port, assume they match */ writeb(TESTvalue, iomem[0]); } #else - inb(_RESET); + arcnet_inb(ioaddr, COM9026_REG_R_RESET); mdelay(RESETtime); #endif @@ -574,21 +568,21 @@ static void com90xx_command(struct net_device *dev, int cmd) { short ioaddr = dev->base_addr; - ACOMMAND(cmd); + arcnet_outb(cmd, ioaddr, COM9026_REG_W_COMMAND); } static int com90xx_status(struct net_device *dev) { short ioaddr = dev->base_addr; - return ASTATUS(); + return arcnet_inb(ioaddr, COM9026_REG_R_STATUS); } static void com90xx_setmask(struct net_device *dev, int mask) { short ioaddr = dev->base_addr; - AINTMASK(mask); + arcnet_outb(mask, ioaddr, COM9026_REG_W_INTMASK); } /* Do a hardware reset on the card, and set up necessary registers. @@ -603,18 +597,23 @@ static int com90xx_reset(struct net_device *dev, int really_reset) struct arcnet_local *lp = netdev_priv(dev); short ioaddr = dev->base_addr; - arc_printk(D_INIT, dev, "Resetting (status=%02Xh)\n", ASTATUS()); + arc_printk(D_INIT, dev, "Resetting (status=%02Xh)\n", + arcnet_inb(ioaddr, COM9026_REG_R_STATUS)); if (really_reset) { /* reset the card */ - inb(_RESET); + arcnet_inb(ioaddr, COM9026_REG_R_RESET); mdelay(RESETtime); } - ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */ - ACOMMAND(CFLAGScmd | CONFIGclear); + /* clear flags & end reset */ + arcnet_outb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND); + arcnet_outb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND); +#if 0 /* don't do this until we verify that it doesn't hurt older cards! */ - /* outb(inb(_CONFIG) | ENABLE16flag, _CONFIG); */ + arcnet_outb(arcnet_inb(ioaddr, COM9026_REG_RW_CONFIG) | ENABLE16flag, + ioaddr, COM9026_REG_RW_CONFIG); +#endif /* verify that the ARCnet signature byte is present */ if (readb(lp->mem_start) != TESTvalue) { @@ -623,7 +622,7 @@ static int com90xx_reset(struct net_device *dev, int really_reset) return 1; } /* enable extended (512-byte) packets */ - ACOMMAND(CONFIGcmd | EXTconf); + arcnet_outb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND); /* clean out all the memory to make debugging make more sense :) */ if (BUGLVL(D_DURING)) -- cgit v1.2.3 From 9c76aa55110a48c0db1eab4c998a5b94d9f0f852 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:09 -0700 Subject: arcnet: arcdevice.h: Add arcnet_readb and arcnet_writeb Use the same indirection as the other arcnet_ macros. Neither of these new macros add the BUS_ALIGN use for 8 bit devices on 16 bit busses. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arcdevice.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h index 4afa32b5e9f1..a05a77de0917 100644 --- a/drivers/net/arcnet/arcdevice.h +++ b/drivers/net/arcnet/arcdevice.h @@ -373,5 +373,10 @@ void arcnet_timeout(struct net_device *dev); #define arcnet_outsw(addr, offset, buffer, count) \ outsw((addr) + BUS_ALIGN * (offset), buffer, count) +#define arcnet_readb(addr, offset) \ + readb((addr) + (offset)) +#define arcnet_writeb(value, addr, offset) \ + writeb(value, (addr) + (offset)) + #endif /* __KERNEL__ */ #endif /* _LINUX_ARCDEVICE_H */ -- cgit v1.2.3 From 4e2f9f1b1ff68e86871594f7321c851c4a147ea4 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:10 -0700 Subject: arcnet: arc-rimi: Use arcnet_ routines Simplify and make consistent the current uses of readb/writeb by using the newly introduced arcnet_ equivalents. o Add new #defines for register offsets o Remove old #defines that included the ioaddr o Remove obfuscating macros by expanding them in-place where appropriate Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rimi.c | 55 ++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 30 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 37406fffc001..4c35a7eb7dde 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -60,23 +60,16 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, #define MIRROR_SIZE (BUFFER_SIZE * 4) /* COM 9026 controller chip --> ARCnet register addresses */ -#define _INTMASK (ioaddr + 0) /* writable */ -#define _STATUS (ioaddr + 0) /* readable */ -#define _COMMAND (ioaddr + 1) /* writable, returns random vals on read (?) */ -#define _RESET (ioaddr + 8) /* software reset (on read) */ -#define _MEMDATA (ioaddr + 12) /* Data port for IO-mapped memory */ -#define _ADDR_HI (ioaddr + 15) /* Control registers for said */ -#define _ADDR_LO (ioaddr + 14) -#define _CONFIG (ioaddr + 2) /* Configuration register */ - -#undef ASTATUS -#undef ACOMMAND -#undef AINTMASK - -#define ASTATUS() readb(_STATUS) -#define ACOMMAND(cmd) writeb((cmd), _COMMAND) -#define AINTMASK(msk) writeb((msk), _INTMASK) -#define SETCONF() writeb(lp->config, _CONFIG) +#define COM9026_REG_W_INTMASK 0 /* writable */ +#define COM9026_REG_R_STATUS 0 /* readable */ +#define COM9026_REG_W_COMMAND 1 /* writable, returns random vals on read (?) */ +#define COM9026_REG_RW_CONFIG 2 /* Configuration register */ +#define COM9026_REG_R_RESET 8 /* software reset (on read) */ +#define COM9026_REG_RW_MEMDATA 12 /* Data port for IO-mapped memory */ +#define COM9026_REG_W_ADDR_LO 14 /* Control registers for said */ +#define COM9026_REG_W_ADDR_HI 15 + +#define COM9026_REG_R_STATION 1 /* Station ID */ /* We cannot probe for a RIM I card; one reason is I don't know how to reset * them. In fact, we can't even get their node ID automatically. So, we @@ -124,7 +117,7 @@ static int check_mirror(unsigned long addr, size_t size) p = ioremap(addr, size); if (p) { - if (readb(p) == TESTvalue) + if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue) res = 1; else res = 0; @@ -162,8 +155,9 @@ static int __init arcrimi_found(struct net_device *dev) } shmem = dev->mem_start; - writeb(TESTvalue, p); - writeb(dev->dev_addr[0], p + 1); /* actually the node ID */ + arcnet_writeb(TESTvalue, p, COM9026_REG_W_INTMASK); + arcnet_writeb(TESTvalue, p, COM9026_REG_W_COMMAND); + /* actually the station/node ID */ /* find the real shared memory start/end points, including mirrors */ @@ -172,7 +166,7 @@ static int __init arcrimi_found(struct net_device *dev) * 2k (or there are no mirrors at all) but on some, it's 4k. */ mirror_size = MIRROR_SIZE; - if (readb(p) == TESTvalue && + if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue && check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 && check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1) mirror_size = 2 * MIRROR_SIZE; @@ -224,7 +218,7 @@ static int __init arcrimi_found(struct net_device *dev) } /* get and check the station ID from offset 1 in shmem */ - dev->dev_addr[0] = readb(lp->mem_start + 1); + dev->dev_addr[0] = arcnet_readb(lp->mem_start, COM9026_REG_R_STATION); arc_printk(D_NORMAL, dev, "ARCnet RIM I: station %02Xh found at IRQ %d, ShMem %lXh (%ld*%d bytes)\n", dev->dev_addr[0], @@ -260,17 +254,18 @@ static int arcrimi_reset(struct net_device *dev, int really_reset) void __iomem *ioaddr = lp->mem_start + 0x800; arc_printk(D_INIT, dev, "Resetting %s (status=%02Xh)\n", - dev->name, ASTATUS()); + dev->name, arcnet_readb(ioaddr, COM9026_REG_R_STATUS)); if (really_reset) { - writeb(TESTvalue, ioaddr - 0x800); /* fake reset */ + arcnet_writeb(TESTvalue, ioaddr, -0x800); /* fake reset */ return 0; } - ACOMMAND(CFLAGScmd | RESETclear); /* clear flags & end reset */ - ACOMMAND(CFLAGScmd | CONFIGclear); + /* clear flags & end reset */ + arcnet_writeb(CFLAGScmd | RESETclear, ioaddr, COM9026_REG_W_COMMAND); + arcnet_writeb(CFLAGScmd | CONFIGclear, ioaddr, COM9026_REG_W_COMMAND); /* enable extended (512-byte) packets */ - ACOMMAND(CONFIGcmd | EXTconf); + arcnet_writeb(CONFIGcmd | EXTconf, ioaddr, COM9026_REG_W_COMMAND); /* done! return success. */ return 0; @@ -281,7 +276,7 @@ static void arcrimi_setmask(struct net_device *dev, int mask) struct arcnet_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->mem_start + 0x800; - AINTMASK(mask); + arcnet_writeb(mask, ioaddr, COM9026_REG_W_INTMASK); } static int arcrimi_status(struct net_device *dev) @@ -289,7 +284,7 @@ static int arcrimi_status(struct net_device *dev) struct arcnet_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->mem_start + 0x800; - return ASTATUS(); + return arcnet_readb(ioaddr, COM9026_REG_R_STATUS); } static void arcrimi_command(struct net_device *dev, int cmd) @@ -297,7 +292,7 @@ static void arcrimi_command(struct net_device *dev, int cmd) struct arcnet_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->mem_start + 0x800; - ACOMMAND(cmd); + arcnet_writeb(cmd, ioaddr, COM9026_REG_W_COMMAND); } static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset, -- cgit v1.2.3 From a11a5442d108357d44d34407ce2ed9d77ab424a0 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:11 -0700 Subject: arcnet: com90xx: Use arcnet_readb/writeb routines Simplify and make consistent the current uses of readb/writeb by using the newly introduced arcnet_ equivalents. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/com90xx.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index f1cfeb0e1343..a97d086a8f51 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -88,6 +88,8 @@ static int numcards; #define COM9026_REG_W_ADDR_LO 14 /* Control registers for said */ #define COM9026_REG_W_ADDR_HI 15 +#define COM9026_REG_R_STATION 1 /* Station ID */ + static int com90xx_skip_probe __initdata = 0; /* Module parameters */ @@ -239,9 +241,10 @@ static void __init com90xx_probe(void) numprint = 0; goto out1; } - if (readb(base) != TESTvalue) { + if (arcnet_readb(base, COM9026_REG_R_STATUS) != TESTvalue) { arc_cont(D_INIT_REASONS, "(%02Xh != %02Xh)\n", - readb(base), TESTvalue); + arcnet_readb(base, COM9026_REG_R_STATUS), + TESTvalue); arc_cont(D_INIT_REASONS, "S3: "); if (BUGLVL(D_INIT_REASONS)) numprint = 0; @@ -252,8 +255,8 @@ static void __init com90xx_probe(void) * in another pass through this loop, they will be discarded * because *cptr != TESTvalue. */ - writeb(0x42, base); - if (readb(base) != 0x42) { + arcnet_writeb(0x42, base, COM9026_REG_W_INTMASK); + if (arcnet_readb(base, COM9026_REG_R_STATUS) != 0x42) { arc_cont(D_INIT_REASONS, "(read only)\n"); arc_cont(D_INIT_REASONS, "S3: "); goto out2; @@ -384,7 +387,8 @@ static void __init com90xx_probe(void) mdelay(RESETtime); } else { /* just one shmem and port, assume they match */ - writeb(TESTvalue, iomem[0]); + arcnet_writeb(TESTvalue, iomem[0], + COM9026_REG_W_INTMASK); } #else arcnet_inb(ioaddr, COM9026_REG_R_RESET); @@ -395,7 +399,7 @@ static void __init com90xx_probe(void) u_long ptr = shmems[index]; void __iomem *base = iomem[index]; - if (readb(base) == TESTvalue) { /* found one */ + if (arcnet_readb(base, COM9026_REG_R_STATUS) == TESTvalue) { /* found one */ arc_cont(D_INIT, "%lXh)\n", *p); openparen = 0; @@ -409,7 +413,8 @@ static void __init com90xx_probe(void) iomem[index] = iomem[numshmems]; break; /* go to the next I/O port */ } else { - arc_cont(D_INIT_REASONS, "%Xh-", readb(base)); + arc_cont(D_INIT_REASONS, "%Xh-", + arcnet_readb(base, COM9026_REG_R_STATUS)); } } @@ -431,7 +436,7 @@ static void __init com90xx_probe(void) /* Now put back TESTvalue on all leftover shmems. */ for (index = 0; index < numshmems; index++) { - writeb(TESTvalue, iomem[index]); + arcnet_writeb(TESTvalue, iomem[index], COM9026_REG_W_INTMASK); iounmap(iomem[index]); release_mem_region(shmems[index], MIRROR_SIZE); } @@ -449,7 +454,7 @@ static int check_mirror(unsigned long addr, size_t size) p = ioremap(addr, size); if (p) { - if (readb(p) == TESTvalue) + if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue) res = 1; else res = 0; @@ -487,7 +492,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, * 2k (or there are no mirrors at all) but on some, it's 4k. */ mirror_size = MIRROR_SIZE; - if (readb(p) == TESTvalue && + if (arcnet_readb(p, COM9026_REG_R_STATUS) == TESTvalue && check_mirror(shmem - MIRROR_SIZE, MIRROR_SIZE) == 0 && check_mirror(shmem - 2 * MIRROR_SIZE, MIRROR_SIZE) == 1) mirror_size = 2 * MIRROR_SIZE; @@ -537,7 +542,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, } /* get and check the station ID from offset 1 in shmem */ - dev->dev_addr[0] = readb(lp->mem_start + 1); + dev->dev_addr[0] = arcnet_readb(lp->mem_start, COM9026_REG_R_STATION); dev->base_addr = ioaddr; @@ -616,7 +621,7 @@ static int com90xx_reset(struct net_device *dev, int really_reset) #endif /* verify that the ARCnet signature byte is present */ - if (readb(lp->mem_start) != TESTvalue) { + if (arcnet_readb(lp->mem_start, COM9026_REG_R_STATUS) != TESTvalue) { if (really_reset) arc_printk(D_NORMAL, dev, "reset failed: TESTvalue not present.\n"); return 1; -- cgit v1.2.3 From e15b03625ce1aa5ca4ab782e034af7d5b56e1b19 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:12 -0700 Subject: arcnet: Remove function pointer macro indirections It's clearer to use function pointer calls directly instead of the macro indirections of ARCRESET, ACOMMAND, ASTATUS, and AINTMASK. Remove the now unused macros too. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arcdevice.h | 5 ---- drivers/net/arcnet/arcnet.c | 64 +++++++++++++++++++++--------------------- 2 files changed, 32 insertions(+), 37 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h index a05a77de0917..257748594cdb 100644 --- a/drivers/net/arcnet/arcdevice.h +++ b/drivers/net/arcnet/arcdevice.h @@ -318,11 +318,6 @@ struct arcnet_local { void __iomem *mem_start; /* pointer to ioremap'ed MMIO */ }; -#define ARCRESET(x) (lp->hw.reset(dev, (x))) -#define ACOMMAND(x) (lp->hw.command(dev, (x))) -#define ASTATUS() (lp->hw.status(dev)) -#define AINTMASK(x) (lp->hw.intmask(dev, (x))) - #if ARCNET_DEBUG_MAX & D_SKB void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); #else diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index c8423ee24e71..bcfdd9123e4f 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -361,7 +361,7 @@ int arcnet_open(struct net_device *dev) * time, actually reset it. */ error = -ENODEV; - if (ARCRESET(0) && ARCRESET(1)) + if (lp->hw.reset(dev, 0) && lp->hw.reset(dev, 1)) goto out_module_put; newmtu = choose_mtu(); @@ -404,22 +404,22 @@ int arcnet_open(struct net_device *dev) arc_printk(D_NORMAL, dev, "WARNING! Station address FF may confuse DOS networking programs!\n"); arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); - if (ASTATUS() & RESETflag) { + if (lp->hw.status(dev) & RESETflag) { arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); - ACOMMAND(CFLAGScmd | RESETclear); + lp->hw.command(dev, CFLAGScmd | RESETclear); } arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); /* make sure we're ready to receive IRQ's. */ - AINTMASK(0); + lp->hw.intmask(dev, 0); udelay(1); /* give it time to set the mask before * we reset it again. (may not even be * necessary) */ arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->intmask = NORXflag | RECONflag; - AINTMASK(lp->intmask); + lp->hw.intmask(dev, lp->intmask); arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); netif_start_queue(dev); @@ -440,9 +440,9 @@ int arcnet_close(struct net_device *dev) netif_stop_queue(dev); /* flush TX and disable RX */ - AINTMASK(0); - ACOMMAND(NOTXcmd); /* stop transmit */ - ACOMMAND(NORXcmd); /* disable receive */ + lp->hw.intmask(dev, 0); + lp->hw.command(dev, NOTXcmd); /* stop transmit */ + lp->hw.command(dev, NORXcmd); /* disable receive */ mdelay(1); /* shut down the card */ @@ -518,7 +518,7 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, arc_printk(D_DURING, dev, "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n", - ASTATUS(), lp->cur_tx, lp->next_tx, skb->len, skb->protocol); + lp->hw.status(dev), lp->cur_tx, lp->next_tx, skb->len, skb->protocol); pkt = (struct archdr *)skb->data; soft = &pkt->soft.rfc1201; @@ -540,7 +540,7 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, netif_stop_queue(dev); spin_lock_irqsave(&lp->lock, flags); - AINTMASK(0); + lp->hw.intmask(dev, 0); if (lp->next_tx == -1) txbuf = get_arcbuf(dev); else @@ -577,15 +577,15 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, } arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n", - __FILE__, __LINE__, __func__, ASTATUS()); + __FILE__, __LINE__, __func__, lp->hw.status(dev)); /* make sure we didn't ignore a TX IRQ while we were in here */ - AINTMASK(0); + lp->hw.intmask(dev, 0); arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); lp->intmask |= TXFREEflag | EXCNAKflag; - AINTMASK(lp->intmask); + lp->hw.intmask(dev, lp->intmask); arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n", - __FILE__, __LINE__, __func__, ASTATUS()); + __FILE__, __LINE__, __func__, lp->hw.status(dev)); spin_unlock_irqrestore(&lp->lock, flags); if (freeskb) @@ -603,7 +603,7 @@ static int go_tx(struct net_device *dev) struct arcnet_local *lp = netdev_priv(dev); arc_printk(D_DURING, dev, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n", - ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx); + lp->hw.status(dev), lp->intmask, lp->next_tx, lp->cur_tx); if (lp->cur_tx != -1 || lp->next_tx == -1) return 0; @@ -615,7 +615,7 @@ static int go_tx(struct net_device *dev) lp->next_tx = -1; /* start sending */ - ACOMMAND(TXcmd | (lp->cur_tx << 3)); + lp->hw.command(dev, TXcmd | (lp->cur_tx << 3)); dev->stats.tx_packets++; lp->lasttrans_dest = lp->lastload_dest; @@ -631,7 +631,7 @@ void arcnet_timeout(struct net_device *dev) { unsigned long flags; struct arcnet_local *lp = netdev_priv(dev); - int status = ASTATUS(); + int status = lp->hw.status(dev); char *msg; spin_lock_irqsave(&lp->lock, flags); @@ -641,14 +641,14 @@ void arcnet_timeout(struct net_device *dev) msg = ""; dev->stats.tx_aborted_errors++; lp->timed_out = 1; - ACOMMAND(NOTXcmd | (lp->cur_tx << 3)); + lp->hw.command(dev, NOTXcmd | (lp->cur_tx << 3)); } dev->stats.tx_errors++; /* make sure we didn't miss a TX or a EXC NAK IRQ */ - AINTMASK(0); + lp->hw.intmask(dev, 0); lp->intmask |= TXFREEflag | EXCNAKflag; - AINTMASK(lp->intmask); + lp->hw.intmask(dev, lp->intmask); spin_unlock_irqrestore(&lp->lock, flags); @@ -687,19 +687,19 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) * clear it right away (but nothing else). */ if (!netif_running(dev)) { - if (ASTATUS() & RESETflag) - ACOMMAND(CFLAGScmd | RESETclear); - AINTMASK(0); + if (lp->hw.status(dev) & RESETflag) + lp->hw.command(dev, CFLAGScmd | RESETclear); + lp->hw.intmask(dev, 0); spin_unlock(&lp->lock); return retval; } arc_printk(D_DURING, dev, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", - ASTATUS(), lp->intmask); + lp->hw.status(dev), lp->intmask); boguscount = 5; do { - status = ASTATUS(); + status = lp->hw.status(dev); diagstatus = (status >> 8) & 0xFF; arc_printk(D_DEBUG, dev, "%s: %d: %s: status=%x\n", @@ -739,7 +739,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) if (lp->cur_rx != -1) { arc_printk(D_DURING, dev, "enabling receive to buffer #%d\n", lp->cur_rx); - ACOMMAND(RXcmd | (lp->cur_rx << 3) | RXbcasts); + lp->hw.command(dev, RXcmd | (lp->cur_rx << 3) | RXbcasts); } didsomething++; } @@ -748,10 +748,10 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) arc_printk(D_DURING, dev, "EXCNAK IRQ (diagstat=%Xh)\n", diagstatus); - ACOMMAND(NOTXcmd); /* disable transmit */ + lp->hw.command(dev, NOTXcmd); /* disable transmit */ lp->excnak_pending = 1; - ACOMMAND(EXCNAKclear); + lp->hw.command(dev, EXCNAKclear); lp->intmask &= ~(EXCNAKflag); didsomething++; } @@ -837,7 +837,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) didsomething++; } if (status & lp->intmask & RECONflag) { - ACOMMAND(CFLAGScmd | CONFIGclear); + lp->hw.command(dev, CFLAGScmd | CONFIGclear); dev->stats.tx_carrier_errors++; arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n", @@ -899,12 +899,12 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) } while (--boguscount && didsomething); arc_printk(D_DURING, dev, "arcnet_interrupt complete (status=%Xh, count=%d)\n", - ASTATUS(), boguscount); + lp->hw.status(dev), boguscount); arc_printk(D_DURING, dev, "\n"); - AINTMASK(0); + lp->hw.intmask(dev, 0); udelay(1); - AINTMASK(lp->intmask); + lp->hw.intmask(dev, lp->intmask); spin_unlock(&lp->lock); return retval; -- cgit v1.2.3 From 8e0f295ea5e712ca30db08a4e3c496e914ee7fef Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:13 -0700 Subject: arcnet: Add com9026.h to standardize COM9026_REG_ Deduplicate the COM9026 registers. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rimi.c | 13 +------------ drivers/net/arcnet/arcnet.c | 1 + drivers/net/arcnet/com9026.h | 17 +++++++++++++++++ drivers/net/arcnet/com90io.c | 11 +---------- drivers/net/arcnet/com90xx.c | 13 +------------ 5 files changed, 21 insertions(+), 34 deletions(-) create mode 100644 drivers/net/arcnet/com9026.h (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 4c35a7eb7dde..a07e24970be4 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -39,6 +39,7 @@ #include #include "arcdevice.h" +#include "com9026.h" /* Internal function declarations */ @@ -59,18 +60,6 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, #define BUFFER_SIZE (512) #define MIRROR_SIZE (BUFFER_SIZE * 4) -/* COM 9026 controller chip --> ARCnet register addresses */ -#define COM9026_REG_W_INTMASK 0 /* writable */ -#define COM9026_REG_R_STATUS 0 /* readable */ -#define COM9026_REG_W_COMMAND 1 /* writable, returns random vals on read (?) */ -#define COM9026_REG_RW_CONFIG 2 /* Configuration register */ -#define COM9026_REG_R_RESET 8 /* software reset (on read) */ -#define COM9026_REG_RW_MEMDATA 12 /* Data port for IO-mapped memory */ -#define COM9026_REG_W_ADDR_LO 14 /* Control registers for said */ -#define COM9026_REG_W_ADDR_HI 15 - -#define COM9026_REG_R_STATION 1 /* Station ID */ - /* We cannot probe for a RIM I card; one reason is I don't know how to reset * them. In fact, we can't even get their node ID automatically. So, we * need to be passed a specific shmem address, IRQ, and node ID. diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index bcfdd9123e4f..2158e985a0e7 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -53,6 +53,7 @@ #include #include "arcdevice.h" +#include "com9026.h" /* "do nothing" functions for protocol drivers */ static void null_rx(struct net_device *dev, int bufnum, diff --git a/drivers/net/arcnet/com9026.h b/drivers/net/arcnet/com9026.h new file mode 100644 index 000000000000..efcaf6707214 --- /dev/null +++ b/drivers/net/arcnet/com9026.h @@ -0,0 +1,17 @@ +#ifndef __COM9026_H +#define __COM9026_H + +/* COM 9026 controller chip --> ARCnet register addresses */ + +#define COM9026_REG_W_INTMASK 0 /* writable */ +#define COM9026_REG_R_STATUS 0 /* readable */ +#define COM9026_REG_W_COMMAND 1 /* writable, returns random vals on read (?) */ +#define COM9026_REG_RW_CONFIG 2 /* Configuration register */ +#define COM9026_REG_R_RESET 8 /* software reset (on read) */ +#define COM9026_REG_RW_MEMDATA 12 /* Data port for IO-mapped memory */ +#define COM9026_REG_W_ADDR_LO 14 /* Control registers for said */ +#define COM9026_REG_W_ADDR_HI 15 + +#define COM9026_REG_R_STATION 1 /* Station ID */ + +#endif diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 7e084f148fa0..b57863df5bf5 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -40,6 +40,7 @@ #include #include "arcdevice.h" +#include "com9026.h" /* Internal function declarations */ @@ -58,16 +59,6 @@ static void com90io_copy_from_card(struct net_device *dev, int bufnum, /* The number of low I/O ports used by the card. */ #define ARCNET_TOTAL_SIZE 16 -/* COM 9026 controller chip --> ARCnet register addresses */ -#define COM9026_REG_W_INTMASK 0 /* writable */ -#define COM9026_REG_R_STATUS 0 /* readable */ -#define COM9026_REG_W_COMMAND 1 /* writable, returns random vals on read (?) */ -#define COM9026_REG_RW_CONFIG 2 /* Configuration register */ -#define COM9026_REG_R_RESET 8 /* software reset (on read) */ -#define COM9026_REG_RW_MEMDATA 12 /* Data port for IO-mapped memory */ -#define COM9026_REG_W_ADDR_LO 14 /* Control registers for said */ -#define COM9026_REG_W_ADDR_HI 15 - /**************************************************************************** * * * IO-mapped operation routines * diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index a97d086a8f51..0d9b45ff1bb2 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -38,6 +38,7 @@ #include #include "arcdevice.h" +#include "com9026.h" /* Define this to speed up the autoprobe by assuming if only one io port and * shmem are left in the list at Stage 5, they must correspond to each @@ -78,18 +79,6 @@ static int numcards; #define BUFFER_SIZE (512) #define MIRROR_SIZE (BUFFER_SIZE * 4) -/* COM 9026 controller chip --> ARCnet register addresses */ -#define COM9026_REG_W_INTMASK 0 /* writable */ -#define COM9026_REG_R_STATUS 0 /* readable */ -#define COM9026_REG_W_COMMAND 1 /* writable, returns random vals on read (?) */ -#define COM9026_REG_RW_CONFIG 2 /* Configuration register */ -#define COM9026_REG_R_RESET 8 /* software reset (on read) */ -#define COM9026_REG_RW_MEMDATA 12 /* Data port for IO-mapped memory */ -#define COM9026_REG_W_ADDR_LO 14 /* Control registers for said */ -#define COM9026_REG_W_ADDR_HI 15 - -#define COM9026_REG_R_STATION 1 /* Station ID */ - static int com90xx_skip_probe __initdata = 0; /* Module parameters */ -- cgit v1.2.3 From 4b0dad83c53b4a6a29be47dc3acc8623be36e7dd Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 5 May 2015 10:06:14 -0700 Subject: arcnet: Remove unused arcnet_w macros The word length macros are unused. Remove them. Signed-off-by: Joe Perches Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arcdevice.h | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h index 257748594cdb..4c1c44c85b08 100644 --- a/drivers/net/arcnet/arcdevice.h +++ b/drivers/net/arcnet/arcdevice.h @@ -358,16 +358,6 @@ void arcnet_timeout(struct net_device *dev); #define arcnet_outsb(addr, offset, buffer, count) \ outsb((addr) + BUS_ALIGN * (offset), buffer, count) -#define arcnet_inw(addr, offset) \ - inw((addr) + BUS_ALIGN * (offset)) -#define arcnet_outw(value, addr, offset) \ - outw(value, (addr) + BUS_ALIGN * (offset)) - -#define arcnet_insw(addr, offset, buffer, count) \ - insw((addr) + BUS_ALIGN * (offset), buffer, count) -#define arcnet_outsw(addr, offset, buffer, count) \ - outsw((addr) + BUS_ALIGN * (offset), buffer, count) - #define arcnet_readb(addr, offset) \ readb((addr) + (offset)) #define arcnet_writeb(value, addr, offset) \ -- cgit v1.2.3 From 54a84c61823e2069da2c7ad91518ff7625129ce5 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Fri, 20 Mar 2015 15:22:02 +0100 Subject: arcnet: reformat structs to C99 format This patch changes the macro definitions to match the C99 formating. This improves the readability. Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/capmode.c | 14 ++++++-------- drivers/net/arcnet/com20020-pci.c | 35 +++++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 2f2d0d94a80d..8297e004dc26 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -230,14 +230,12 @@ free_outskb: } static struct ArcProto capmode_proto = { - 'r', - XMTU, - 0, - rx, - build_header, - prepare_tx, - NULL, - ack_tx + .suffix = 'r', + .mtu = XMTU, + .rx = rx, + .build_header = build_header, + .prepare_tx = prepare_tx, + .ack_tx = ack_tx }; static void arcnet_cap_init(void) diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 9b8212663320..a12bf83be750 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -188,7 +188,11 @@ static struct com20020_pci_card_info card_info_10mbit = { .name = "ARC-PCI", .devcount = 1, .chan_map_tbl = { - { 2, 0x00, 0x08 }, + { + .bar = 2, + .offset = 0x00, + .size = 0x08, + }, }, .flags = ARC_CAN_10MBIT, }; @@ -197,7 +201,11 @@ static struct com20020_pci_card_info card_info_5mbit = { .name = "ARC-PCI", .devcount = 1, .chan_map_tbl = { - { 2, 0x00, 0x08 }, + { + .bar = 2, + .offset = 0x00, + .size = 0x08, + }, }, .flags = ARC_IS_5MBIT, }; @@ -207,7 +215,11 @@ static struct com20020_pci_card_info card_info_sohard = { .devcount = 1, /* SOHARD needs PCI base addr 4 */ .chan_map_tbl = { - {4, 0x00, 0x08}, + { + .bar = 4, + .offset = 0x00, + .size = 0x08 + }, }, .flags = ARC_CAN_10MBIT, }; @@ -216,7 +228,11 @@ static struct com20020_pci_card_info card_info_eae_arc1 = { .name = "EAE PLX-PCI ARC1", .devcount = 1, .chan_map_tbl = { - { 2, 0x00, 0x08 }, + { + .bar = 2, + .offset = 0x00, + .size = 0x08, + }, }, .flags = ARC_CAN_10MBIT, }; @@ -225,8 +241,15 @@ static struct com20020_pci_card_info card_info_eae_ma1 = { .name = "EAE PLX-PCI MA1", .devcount = 2, .chan_map_tbl = { - { 2, 0x00, 0x08 }, - { 2, 0x08, 0x08 } + { + .bar = 2, + .offset = 0x00, + .size = 0x08, + }, { + .bar = 2, + .offset = 0x08, + .size = 0x08, + } }, .flags = ARC_CAN_10MBIT, }; -- cgit v1.2.3 From 84286f191a01f198ccfc15759d01320e3847accd Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 15 Apr 2015 11:43:57 +0200 Subject: arcnet: com20020: replace magic numbers with readable macros This patch replaces all magic numbers in the driver with proper named macros. For the case of XTOcfg and STARTIOcmd it introduces the new macros. Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arcdevice.h | 1 + drivers/net/arcnet/com20020.c | 17 +++++++++-------- drivers/net/arcnet/com20020.h | 1 + 3 files changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h index 4c1c44c85b08..d7fdea11e694 100644 --- a/drivers/net/arcnet/arcdevice.h +++ b/drivers/net/arcnet/arcdevice.h @@ -164,6 +164,7 @@ do { \ #define CONFIGcmd 0x05 /* define configuration */ #define CFLAGScmd 0x06 /* clear flags */ #define TESTcmd 0x07 /* load test flags */ +#define STARTIOcmd 0x18 /* start internal operation */ /* flags for "clear flags" command */ #define RESETclear 0x08 /* power-on-reset */ diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index d4162750a354..c82f323a8c2b 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -94,9 +94,9 @@ int com20020_check(struct net_device *dev) int ioaddr = dev->base_addr, status; struct arcnet_local *lp = netdev_priv(dev); - arcnet_outb(0x18 | 0x80, ioaddr, COM20020_REG_W_CONFIG); + arcnet_outb(XTOcfg(3) | RESETcfg, ioaddr, COM20020_REG_W_CONFIG); udelay(5); - arcnet_outb(0x18 , ioaddr, COM20020_REG_W_CONFIG); + arcnet_outb(XTOcfg(3), ioaddr, COM20020_REG_W_CONFIG); mdelay(RESETtime); lp->setup = lp->clockm ? 0 : (lp->clockp << 1); @@ -115,10 +115,10 @@ int com20020_check(struct net_device *dev) /* must now write the magic "restart operation" command */ mdelay(1); - arcnet_outb(0x18, ioaddr, COM20020_REG_W_COMMAND); + arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND); } - lp->config = 0x21 | (lp->timeout << 3) | (lp->backplane << 2); + lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE; /* set node ID to 0x42 (but transmitter is disabled, so it's okay) */ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); arcnet_outb(0x42, ioaddr, COM20020_REG_W_XREG); @@ -132,7 +132,8 @@ int com20020_check(struct net_device *dev) arc_printk(D_INIT_REASONS, dev, "status after reset: %X\n", status); /* Enable TX */ - arcnet_outb(0x39, ioaddr, COM20020_REG_W_CONFIG); + lp->config |= TXENcfg; + arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); arcnet_outb(arcnet_inb(ioaddr, 8), ioaddr, COM20020_REG_W_XREG); arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear, @@ -211,10 +212,10 @@ int com20020_found(struct net_device *dev, int shared) /* must now write the magic "restart operation" command */ mdelay(1); - arcnet_outb(0x18, ioaddr, COM20020_REG_W_COMMAND); + arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND); } - lp->config = 0x20 | (lp->timeout << 3) | (lp->backplane << 2) | 1; + lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE; /* Default 0x38 + register: Node ID */ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG); @@ -280,7 +281,7 @@ static int com20020_reset(struct net_device *dev, int really_reset) if (really_reset) { /* reset the card */ - arcnet_outb(lp->config | 0x80, ioaddr, COM20020_REG_W_CONFIG); + arcnet_outb(lp->config | RESETcfg, ioaddr, COM20020_REG_W_CONFIG); udelay(5); arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); mdelay(RESETtime * 2); diff --git a/drivers/net/arcnet/com20020.h b/drivers/net/arcnet/com20020.h index ffb19464b607..22a460f39fb9 100644 --- a/drivers/net/arcnet/com20020.h +++ b/drivers/net/arcnet/com20020.h @@ -86,6 +86,7 @@ struct com20020_dev { /* in the CONFIG register */ #define RESETcfg 0x80 /* put card in reset state */ #define TXENcfg 0x20 /* enable TX */ +#define XTOcfg(x) ((x) << 3) /* extended timeout */ /* in SETUP register */ #define PROMISCset 0x10 /* enable RCV_ALL */ -- cgit v1.2.3 From abc23ec927f217f1cc698e36d300ef80e935e805 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 22 Apr 2015 11:11:58 +0200 Subject: arcnet: arc-rawmode: reorder module functions This patch moves the module_init and module_exit patches to the end of the file. It also replaces the printk with pr_info. Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arc-rawmode.c | 84 ++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 46 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 35a747a7329e..d78f30186642 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -33,54 +33,8 @@ #include #include #include - #include "arcdevice.h" -static void rx(struct net_device *dev, int bufnum, - struct archdr *pkthdr, int length); -static int build_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, uint8_t daddr); -static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, - int bufnum); - -static struct ArcProto rawmode_proto = { - .suffix = 'r', - .mtu = XMTU, - .rx = rx, - .build_header = build_header, - .prepare_tx = prepare_tx, - .continue_tx = NULL, - .ack_tx = NULL -}; - -static int __init arcnet_raw_init(void) -{ - int count; - - pr_info("%s\n", "raw mode (`r') encapsulation support loaded"); - - for (count = 0; count < 256; count++) - if (arc_proto_map[count] == arc_proto_default) - arc_proto_map[count] = &rawmode_proto; - - /* for raw mode, we only set the bcast proto if there's no better one */ - if (arc_bcast_proto == arc_proto_default) - arc_bcast_proto = &rawmode_proto; - - arc_proto_default = &rawmode_proto; - return 0; -} - -static void __exit arcnet_raw_exit(void) -{ - arcnet_unregister_proto(&rawmode_proto); -} - -module_init(arcnet_raw_init); -module_exit(arcnet_raw_exit); - -MODULE_LICENSE("GPL"); - /* packet receiver */ static void rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length) @@ -195,3 +149,41 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, return 1; /* done */ } + +static struct ArcProto rawmode_proto = { + .suffix = 'r', + .mtu = XMTU, + .rx = rx, + .build_header = build_header, + .prepare_tx = prepare_tx, + .continue_tx = NULL, + .ack_tx = NULL +}; + +static int __init arcnet_raw_init(void) +{ + int count; + + pr_info("raw mode (`r') encapsulation support loaded\n"); + + for (count = 0; count < 256; count++) + if (arc_proto_map[count] == arc_proto_default) + arc_proto_map[count] = &rawmode_proto; + + /* for raw mode, we only set the bcast proto if there's no better one */ + if (arc_bcast_proto == arc_proto_default) + arc_bcast_proto = &rawmode_proto; + + arc_proto_default = &rawmode_proto; + return 0; +} + +static void __exit arcnet_raw_exit(void) +{ + arcnet_unregister_proto(&rawmode_proto); +} + +module_init(arcnet_raw_init); +module_exit(arcnet_raw_exit); + +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 834c952a1177721f2c0e779e3ca856b79ce27310 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 22 Apr 2015 11:47:43 +0200 Subject: arcnet: capmode: remove extra function This patch cleans the capmode protocol module. It removes the obsolete function arcnet_cap_init and replaces printk with pr_info. Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/capmode.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 8297e004dc26..2056878fb087 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -238,10 +238,12 @@ static struct ArcProto capmode_proto = { .ack_tx = ack_tx }; -static void arcnet_cap_init(void) +static int __init capmode_module_init(void) { int count; + pr_info("cap mode (`c') encapsulation support loaded\n"); + for (count = 1; count <= 8; count++) if (arc_proto_map[count] == arc_proto_default) arc_proto_map[count] = &capmode_proto; @@ -252,12 +254,7 @@ static void arcnet_cap_init(void) arc_proto_default = &capmode_proto; arc_raw_proto = &capmode_proto; -} -static int __init capmode_module_init(void) -{ - pr_info("%s\n", "cap mode (`c') encapsulation support loaded"); - arcnet_cap_init(); return 0; } -- cgit v1.2.3 From a471be41f2bfe4ee3a4b38b0e5af17d0abfd3aa6 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 23 Sep 2015 08:39:14 -0700 Subject: rocker: track when FDB entry is touched. The entry is touched once when created, and touched again for each update. The touched time is used to calculate FDB entry age. Signed-off-by: Scott Feldman Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 34ac41ac9e61..e517e9c355fa 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -152,6 +152,7 @@ struct rocker_fdb_tbl_entry { struct hlist_node entry; u32 key_crc32; /* key */ bool learned; + unsigned long touched; struct rocker_fdb_tbl_key { u32 pport; u8 addr[ETH_ALEN]; @@ -3629,6 +3630,7 @@ static int rocker_port_fdb(struct rocker_port *rocker_port, return -ENOMEM; fdb->learned = (flags & ROCKER_OP_FLAG_LEARNED); + fdb->touched = jiffies; fdb->key.pport = rocker_port->pport; ether_addr_copy(fdb->key.addr, addr); fdb->key.vlan_id = vlan_id; @@ -3638,13 +3640,17 @@ static int rocker_port_fdb(struct rocker_port *rocker_port, found = rocker_fdb_tbl_find(rocker, fdb); - if (removing && found) { - rocker_port_kfree(trans, fdb); - if (trans != SWITCHDEV_TRANS_PREPARE) - hash_del(&found->entry); - } else if (!removing && !found) { + if (found) { + found->touched = jiffies; + if (removing) { + rocker_port_kfree(trans, fdb); + if (trans != SWITCHDEV_TRANS_PREPARE) + hash_del(&found->entry); + } + } else if (!removing) { if (trans != SWITCHDEV_TRANS_PREPARE) - hash_add(rocker->fdb_tbl, &fdb->entry, fdb->key_crc32); + hash_add(rocker->fdb_tbl, &fdb->entry, + fdb->key_crc32); } spin_unlock_irqrestore(&rocker->fdb_tbl_lock, lock_flags); -- cgit v1.2.3 From 4c660496c95af93f3461c06d46fd33c0719625db Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 23 Sep 2015 08:39:15 -0700 Subject: rocker: store rocker_port in fdb key rather than pport We'll need more info from rocker_port than just pport when we age out fdb entries, so store rocker_port rather than pport in each fdb entry. Signed-off-by: Scott Feldman Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index e517e9c355fa..f55ed2c2d20f 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -154,7 +154,7 @@ struct rocker_fdb_tbl_entry { bool learned; unsigned long touched; struct rocker_fdb_tbl_key { - u32 pport; + struct rocker_port *rocker_port; u8 addr[ETH_ALEN]; __be16 vlan_id; } key; @@ -3631,7 +3631,7 @@ static int rocker_port_fdb(struct rocker_port *rocker_port, fdb->learned = (flags & ROCKER_OP_FLAG_LEARNED); fdb->touched = jiffies; - fdb->key.pport = rocker_port->pport; + fdb->key.rocker_port = rocker_port; ether_addr_copy(fdb->key.addr, addr); fdb->key.vlan_id = vlan_id; fdb->key_crc32 = crc32(~0, &fdb->key, sizeof(fdb->key)); @@ -3686,7 +3686,7 @@ static int rocker_port_fdb_flush(struct rocker_port *rocker_port, spin_lock_irqsave(&rocker->fdb_tbl_lock, lock_flags); hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) { - if (found->key.pport != rocker_port->pport) + if (found->key.rocker_port != rocker_port) continue; if (!found->learned) continue; @@ -4553,7 +4553,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, spin_lock_irqsave(&rocker->fdb_tbl_lock, lock_flags); hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) { - if (found->key.pport != rocker_port->pport) + if (found->key.rocker_port != rocker_port) continue; fdb->addr = found->key.addr; fdb->ndm_state = NUD_REACHABLE; -- cgit v1.2.3 From e7335703e33e7787333872a31e0f4491f9d76cac Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 23 Sep 2015 08:39:17 -0700 Subject: rocker: adding port ageing_time for ageing out FDB entries Follow-up patcheset will allow user to change ageing_time, but for now just hard-code it to a fixed value (the same value used as the default for the bridge driver). Signed-off-by: Scott Feldman Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index f55ed2c2d20f..be8bb04b7355 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -221,6 +221,7 @@ struct rocker_port { __be16 internal_vlan_id; int stp_state; u32 brport_flags; + unsigned long ageing_time; bool ctrls[ROCKER_CTRL_MAX]; unsigned long vlan_bitmap[ROCKER_VLAN_BITMAP_LEN]; struct napi_struct napi_tx; @@ -4975,6 +4976,7 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number) rocker_port->port_number = port_number; rocker_port->pport = port_number + 1; rocker_port->brport_flags = BR_LEARNING | BR_LEARNING_SYNC; + rocker_port->ageing_time = BR_DEFAULT_AGEING_TIME; INIT_LIST_HEAD(&rocker_port->trans_mem); rocker_port_dev_addr_init(rocker_port); -- cgit v1.2.3 From 52fe3e2d51d27c0e68b2bea29dea0b64af2c665e Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Wed, 23 Sep 2015 08:39:18 -0700 Subject: rocker: add FDB cleanup timer Add a timer to each rocker switch to do FDB entry cleanup by ageing out expired entries. The timer scheduling algo is copied from the bridge driver, for the most part, to keep the firing of the timer to a minimum. Signed-off-by: Scott Feldman Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index be8bb04b7355..32c5429ea5fe 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -248,6 +248,7 @@ struct rocker { u64 flow_tbl_next_cookie; DECLARE_HASHTABLE(group_tbl, 16); spinlock_t group_tbl_lock; /* for group tbl accesses */ + struct timer_list fdb_cleanup_timer; DECLARE_HASHTABLE(fdb_tbl, 16); spinlock_t fdb_tbl_lock; /* for fdb tbl accesses */ unsigned long internal_vlan_bitmap[ROCKER_INTERNAL_VLAN_BITMAP_LEN]; @@ -3706,6 +3707,41 @@ err_out: return err; } +static void rocker_fdb_cleanup(unsigned long data) +{ + struct rocker *rocker = (struct rocker *)data; + struct rocker_port *rocker_port; + struct rocker_fdb_tbl_entry *entry; + struct hlist_node *tmp; + unsigned long next_timer = jiffies + BR_MIN_AGEING_TIME; + unsigned long expires; + unsigned long lock_flags; + int flags = ROCKER_OP_FLAG_NOWAIT | ROCKER_OP_FLAG_REMOVE | + ROCKER_OP_FLAG_LEARNED; + int bkt; + + spin_lock_irqsave(&rocker->fdb_tbl_lock, lock_flags); + + hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, entry, entry) { + if (!entry->learned) + continue; + rocker_port = entry->key.rocker_port; + expires = entry->touched + rocker_port->ageing_time; + if (time_before_eq(expires, jiffies)) { + rocker_port_fdb_learn(rocker_port, SWITCHDEV_TRANS_NONE, + flags, entry->key.addr, + entry->key.vlan_id); + hash_del(&entry->entry); + } else if (time_before(expires, next_timer)) { + next_timer = expires; + } + } + + spin_unlock_irqrestore(&rocker->fdb_tbl_lock, lock_flags); + + mod_timer(&rocker->fdb_cleanup_timer, round_jiffies_up(next_timer)); +} + static int rocker_port_router_mac(struct rocker_port *rocker_port, enum switchdev_trans trans, int flags, __be16 vlan_id) @@ -5191,6 +5227,10 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_init_tbls; } + setup_timer(&rocker->fdb_cleanup_timer, rocker_fdb_cleanup, + (unsigned long) rocker); + mod_timer(&rocker->fdb_cleanup_timer, jiffies); + err = rocker_probe_ports(rocker); if (err) { dev_err(&pdev->dev, "failed to probe ports\n"); @@ -5203,6 +5243,7 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; err_probe_ports: + del_timer_sync(&rocker->fdb_cleanup_timer); rocker_free_tbls(rocker); err_init_tbls: free_irq(rocker_msix_vector(rocker, ROCKER_MSIX_VEC_EVENT), rocker); @@ -5230,6 +5271,7 @@ static void rocker_remove(struct pci_dev *pdev) { struct rocker *rocker = pci_get_drvdata(pdev); + del_timer_sync(&rocker->fdb_cleanup_timer); rocker_free_tbls(rocker); rocker_write32(rocker, CONTROL, ROCKER_CONTROL_RESET); rocker_remove_ports(rocker); -- cgit v1.2.3 From b6bd9b5448a9362e3ca33b21f1461baa5500520f Mon Sep 17 00:00:00 2001 From: Shrikrishna Khare Date: Mon, 21 Sep 2015 20:01:29 -0700 Subject: Driver: Vmxnet3: Extend register dump support Signed-off-by: Shrikrishna Khare Signed-off-by: Bhavesh Davda Acked-by: Srividya Murali Signed-off-by: David S. Miller --- drivers/net/vmxnet3/vmxnet3_ethtool.c | 118 ++++++++++++++++++++++++++-------- drivers/net/vmxnet3/vmxnet3_int.h | 4 +- 2 files changed, 92 insertions(+), 30 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index c1d0e7a9da04..a681569ae0b5 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -183,16 +183,22 @@ vmxnet3_get_sset_count(struct net_device *netdev, int sset) } -/* Should be multiple of 4 */ -#define NUM_TX_REGS 8 -#define NUM_RX_REGS 12 - +/* This is a version 2 of the vmxnet3 ethtool_regs which goes hand in hand with + * the version 2 of the vmxnet3 support for ethtool(8) --register-dump. + * Therefore, if any registers are added, removed or modified, then a version + * bump and a corresponding change in the vmxnet3 support for ethtool(8) + * --register-dump would be required. + */ static int vmxnet3_get_regs_len(struct net_device *netdev) { struct vmxnet3_adapter *adapter = netdev_priv(netdev); - return (adapter->num_tx_queues * NUM_TX_REGS * sizeof(u32) + - adapter->num_rx_queues * NUM_RX_REGS * sizeof(u32)); + + return ((9 /* BAR1 registers */ + + (1 + adapter->intr.num_intrs) + + (1 + adapter->num_tx_queues * 17 /* Tx queue registers */) + + (1 + adapter->num_rx_queues * 23 /* Rx queue registers */)) * + sizeof(u32)); } @@ -342,6 +348,12 @@ vmxnet3_get_ethtool_stats(struct net_device *netdev, } +/* This is a version 2 of the vmxnet3 ethtool_regs which goes hand in hand with + * the version 2 of the vmxnet3 support for ethtool(8) --register-dump. + * Therefore, if any registers are added, removed or modified, then a version + * bump and a corresponding change in the vmxnet3 support for ethtool(8) + * --register-dump would be required. + */ static void vmxnet3_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) { @@ -351,40 +363,90 @@ vmxnet3_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) memset(p, 0, vmxnet3_get_regs_len(netdev)); - regs->version = 1; + regs->version = 2; /* Update vmxnet3_get_regs_len if we want to dump more registers */ - /* make each ring use multiple of 16 bytes */ - for (i = 0; i < adapter->num_tx_queues; i++) { - buf[j++] = adapter->tx_queue[i].tx_ring.next2fill; - buf[j++] = adapter->tx_queue[i].tx_ring.next2comp; - buf[j++] = adapter->tx_queue[i].tx_ring.gen; - buf[j++] = 0; + buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_VRRS); + buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_UVRS); + buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_DSAL); + buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_DSAH); + buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD); + buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_MACL); + buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_MACH); + buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_ICR); + buf[j++] = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_ECR); + + buf[j++] = adapter->intr.num_intrs; + for (i = 0; i < adapter->intr.num_intrs; i++) { + buf[j++] = VMXNET3_READ_BAR0_REG(adapter, VMXNET3_REG_IMR + + i * VMXNET3_REG_ALIGN); + } - buf[j++] = adapter->tx_queue[i].comp_ring.next2proc; - buf[j++] = adapter->tx_queue[i].comp_ring.gen; - buf[j++] = adapter->tx_queue[i].stopped; - buf[j++] = 0; + buf[j++] = adapter->num_tx_queues; + for (i = 0; i < adapter->num_tx_queues; i++) { + struct vmxnet3_tx_queue *tq = &adapter->tx_queue[i]; + + buf[j++] = VMXNET3_READ_BAR0_REG(adapter, VMXNET3_REG_TXPROD + + i * VMXNET3_REG_ALIGN); + + buf[j++] = VMXNET3_GET_ADDR_LO(tq->tx_ring.basePA); + buf[j++] = VMXNET3_GET_ADDR_HI(tq->tx_ring.basePA); + buf[j++] = tq->tx_ring.size; + buf[j++] = tq->tx_ring.next2fill; + buf[j++] = tq->tx_ring.next2comp; + buf[j++] = tq->tx_ring.gen; + + buf[j++] = VMXNET3_GET_ADDR_LO(tq->data_ring.basePA); + buf[j++] = VMXNET3_GET_ADDR_HI(tq->data_ring.basePA); + buf[j++] = tq->data_ring.size; + /* transmit data ring buffer size */ + buf[j++] = VMXNET3_HDR_COPY_SIZE; + + buf[j++] = VMXNET3_GET_ADDR_LO(tq->comp_ring.basePA); + buf[j++] = VMXNET3_GET_ADDR_HI(tq->comp_ring.basePA); + buf[j++] = tq->comp_ring.size; + buf[j++] = tq->comp_ring.next2proc; + buf[j++] = tq->comp_ring.gen; + + buf[j++] = tq->stopped; } + buf[j++] = adapter->num_rx_queues; for (i = 0; i < adapter->num_rx_queues; i++) { - buf[j++] = adapter->rx_queue[i].rx_ring[0].next2fill; - buf[j++] = adapter->rx_queue[i].rx_ring[0].next2comp; - buf[j++] = adapter->rx_queue[i].rx_ring[0].gen; + struct vmxnet3_rx_queue *rq = &adapter->rx_queue[i]; + + buf[j++] = VMXNET3_READ_BAR0_REG(adapter, VMXNET3_REG_RXPROD + + i * VMXNET3_REG_ALIGN); + buf[j++] = VMXNET3_READ_BAR0_REG(adapter, VMXNET3_REG_RXPROD2 + + i * VMXNET3_REG_ALIGN); + + buf[j++] = VMXNET3_GET_ADDR_LO(rq->rx_ring[0].basePA); + buf[j++] = VMXNET3_GET_ADDR_HI(rq->rx_ring[0].basePA); + buf[j++] = rq->rx_ring[0].size; + buf[j++] = rq->rx_ring[0].next2fill; + buf[j++] = rq->rx_ring[0].next2comp; + buf[j++] = rq->rx_ring[0].gen; + + buf[j++] = VMXNET3_GET_ADDR_LO(rq->rx_ring[1].basePA); + buf[j++] = VMXNET3_GET_ADDR_HI(rq->rx_ring[1].basePA); + buf[j++] = rq->rx_ring[1].size; + buf[j++] = rq->rx_ring[1].next2fill; + buf[j++] = rq->rx_ring[1].next2comp; + buf[j++] = rq->rx_ring[1].gen; + + /* receive data ring */ buf[j++] = 0; - - buf[j++] = adapter->rx_queue[i].rx_ring[1].next2fill; - buf[j++] = adapter->rx_queue[i].rx_ring[1].next2comp; - buf[j++] = adapter->rx_queue[i].rx_ring[1].gen; buf[j++] = 0; - - buf[j++] = adapter->rx_queue[i].comp_ring.next2proc; - buf[j++] = adapter->rx_queue[i].comp_ring.gen; buf[j++] = 0; buf[j++] = 0; - } + buf[j++] = VMXNET3_GET_ADDR_LO(rq->comp_ring.basePA); + buf[j++] = VMXNET3_GET_ADDR_HI(rq->comp_ring.basePA); + buf[j++] = rq->comp_ring.size; + buf[j++] = rq->comp_ring.next2proc; + buf[j++] = rq->comp_ring.gen; + } } diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index 2652245631d1..3f859a55c035 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -69,10 +69,10 @@ /* * Version numbers */ -#define VMXNET3_DRIVER_VERSION_STRING "1.4.2.0-k" +#define VMXNET3_DRIVER_VERSION_STRING "1.4.3.0-k" /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ -#define VMXNET3_DRIVER_VERSION_NUM 0x01040200 +#define VMXNET3_DRIVER_VERSION_NUM 0x01040300 #if defined(CONFIG_PCI_MSI) /* RSS only makes sense if MSI-X is supported. */ -- cgit v1.2.3 From 1bb6aa56bb388ac4f7dba226aa55142fa8c65361 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 22 Sep 2015 10:57:04 +0200 Subject: net: davinci_emac: Add support for fixed-link PHY In case the DaVinci Emac is directly connected to a non-mdio PHY/device, it should be possible to provide a fixed link configuration in the DT. Signed-off-by: Neil Armstrong Tested-by: Tony Lindgren Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/davinci_emac.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 39a54b27db66..33bd3b902304 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1861,8 +1861,12 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv) pdata->no_bd_ram = of_property_read_bool(np, "ti,davinci-no-bd-ram"); priv->phy_node = of_parse_phandle(np, "phy-handle", 0); - if (!priv->phy_node) - pdata->phy_id = NULL; + if (!priv->phy_node) { + if (!of_phy_is_fixed_link(np)) + pdata->phy_id = NULL; + else if (of_phy_register_fixed_link(np) >= 0) + priv->phy_node = of_node_get(np); + } auxdata = pdev->dev.platform_data; if (auxdata) { -- cgit v1.2.3 From 06e60e5912c0373b15143cc52e4a11fafeaafff3 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Tue, 22 Sep 2015 14:27:16 +0300 Subject: net/ethoc: support big-endian register layout Signed-off-by: Max Filippov Signed-off-by: David S. Miller --- drivers/net/ethernet/ethoc.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index a2c96fd88393..ff665493ca97 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -201,6 +201,7 @@ struct ethoc { void __iomem *membase; int dma_alloc; resource_size_t io_region_size; + bool big_endian; unsigned int num_bd; unsigned int num_tx; @@ -236,12 +237,18 @@ struct ethoc_bd { static inline u32 ethoc_read(struct ethoc *dev, loff_t offset) { - return ioread32(dev->iobase + offset); + if (dev->big_endian) + return ioread32be(dev->iobase + offset); + else + return ioread32(dev->iobase + offset); } static inline void ethoc_write(struct ethoc *dev, loff_t offset, u32 data) { - iowrite32(data, dev->iobase + offset); + if (dev->big_endian) + iowrite32be(data, dev->iobase + offset); + else + iowrite32(data, dev->iobase + offset); } static inline void ethoc_read_bd(struct ethoc *dev, int index, @@ -1106,6 +1113,9 @@ static int ethoc_probe(struct platform_device *pdev) priv->dma_alloc = buffer_size; } + priv->big_endian = pdata ? pdata->big_endian : + of_device_is_big_endian(pdev->dev.of_node); + /* calculate the number of TX/RX buffers, maximum 128 supported */ num_bd = min_t(unsigned int, 128, (netdev->mem_end - netdev->mem_start + 1) / ETHOC_BUFSIZ); -- cgit v1.2.3 From 6ee8c9a70d65ee37251465348501a067138050d7 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:18:17 -0700 Subject: ixgbe: Clear I2C destination location Clear the destination location for I2C data initially so that the received data will not be affected by previous attempts. This could have returned wrong data in certain retry sequences. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 315f0597fbc0..88ade175185a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -2026,6 +2026,7 @@ static s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data) s32 i; bool bit = false; + *data = 0; for (i = 7; i >= 0; i--) { ixgbe_clock_in_i2c_bit(hw, &bit); *data |= bit << i; -- cgit v1.2.3 From 56f6ed1ce13b0cb85ae9537f839df7c4ba1f5369 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:18:22 -0700 Subject: ixgbe: Allow reduced delays during SFP detection Reduce the number of retries during PHY detection. This reduces pauses when no SFP is present. Once an SFP is detected, the normal retry count will be used. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c | 18 ++++++++++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h | 2 ++ 2 files changed, 20 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 88ade175185a..7a7ee9d84ac8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -1730,6 +1730,21 @@ s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset, eeprom_data); } +/** + * ixgbe_is_sfp_probe - Returns true if SFP is being detected + * @hw: pointer to hardware structure + * @offset: eeprom offset to be read + * @addr: I2C address to be read + */ +static bool ixgbe_is_sfp_probe(struct ixgbe_hw *hw, u8 offset, u8 addr) +{ + if (addr == IXGBE_I2C_EEPROM_DEV_ADDR && + offset == IXGBE_SFF_IDENTIFIER && + hw->phy.sfp_type == ixgbe_sfp_type_not_present) + return true; + return false; +} + /** * ixgbe_read_i2c_byte_generic_int - Reads 8 bit word over I2C * @hw: pointer to hardware structure @@ -1749,6 +1764,9 @@ static s32 ixgbe_read_i2c_byte_generic_int(struct ixgbe_hw *hw, u8 byte_offset, u32 swfw_mask = hw->phy.phy_semaphore_mask; bool nack = true; + if (ixgbe_is_sfp_probe(hw, byte_offset, dev_addr)) + max_retry = IXGBE_SFP_DETECT_RETRIES; + *data = 0; do { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h index 4c06484fdebc..0769b40399ea 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h @@ -109,6 +109,8 @@ #define IXGBE_I2C_T_SU_STO 4 #define IXGBE_I2C_T_BUF 5 +#define IXGBE_SFP_DETECT_RETRIES 2 + #define IXGBE_TN_LASI_STATUS_REG 0x9005 #define IXGBE_TN_LASI_STATUS_TEMP_ALARM 0x0008 -- cgit v1.2.3 From 6d373a1bbb99bdfb9ce820aec9ae5f2e02c8891f Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:18:28 -0700 Subject: ixgbe: Add X550EM_x dual-speed SFP+ support This patch adds X550EM_x SFP+ dual-speed support. 82599 fiber link code was moved from ixgbe_82599.c to ixgbe_common.c for use by X550EM. SFP MAC link code is added to x550EM. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c | 192 +++------------------- drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 210 ++++++++++++++++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_common.h | 5 + drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h | 3 + drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 2 + drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 18 ++ 6 files changed, 263 insertions(+), 167 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 85156fb53b62..a39afcf03e2c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -44,9 +44,8 @@ static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); -static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, - ixgbe_link_speed speed, - bool autoneg_wait_to_complete); +static void +ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *, ixgbe_link_speed); static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, ixgbe_link_speed speed, bool autoneg_wait_to_complete); @@ -109,6 +108,9 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) if (hw->phy.multispeed_fiber) { /* Set up dual speed SFP+ support */ mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber; + mac->ops.setup_mac_link = ixgbe_setup_mac_link_82599; + mac->ops.set_rate_select_speed = + ixgbe_set_hard_rate_select_speed; } else { if ((mac->ops.get_media_type(hw) == ixgbe_media_type_backplane) && @@ -646,176 +648,32 @@ static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) } /** - * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed - * @hw: pointer to hardware structure - * @speed: new link speed - * @autoneg_wait_to_complete: true when waiting for completion is needed + * ixgbe_set_hard_rate_select_speed - Set module link speed + * @hw: pointer to hardware structure + * @speed: link speed to set * - * Set the link speed in the AUTOC register and restarts link. - **/ -static s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, - ixgbe_link_speed speed, - bool autoneg_wait_to_complete) + * Set module link speed via RS0/RS1 rate select pins. + */ +static void +ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw, ixgbe_link_speed speed) { - s32 status = 0; - ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; - ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; - u32 speedcnt = 0; u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); - u32 i = 0; - bool link_up = false; - bool autoneg = false; - /* Mask off requested but non-supported speeds */ - status = hw->mac.ops.get_link_capabilities(hw, &link_speed, - &autoneg); - if (status != 0) - return status; - - speed &= link_speed; - - /* - * Try each speed one by one, highest priority first. We do this in - * software because 10gb fiber doesn't support speed autonegotiation. - */ - if (speed & IXGBE_LINK_SPEED_10GB_FULL) { - speedcnt++; - highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; - - /* If we already have link at this speed, just jump out */ - status = hw->mac.ops.check_link(hw, &link_speed, &link_up, - false); - if (status != 0) - return status; - - if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up) - goto out; - - /* Set the module link speed */ - switch (hw->phy.media_type) { - case ixgbe_media_type_fiber: - esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5); - IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); - IXGBE_WRITE_FLUSH(hw); - break; - case ixgbe_media_type_fiber_qsfp: - /* QSFP module automatically detects MAC link speed */ - break; - default: - hw_dbg(hw, "Unexpected media type.\n"); - break; - } - - /* Allow module to change analog characteristics (1G->10G) */ - msleep(40); - - status = ixgbe_setup_mac_link_82599(hw, - IXGBE_LINK_SPEED_10GB_FULL, - autoneg_wait_to_complete); - if (status != 0) - return status; - - /* Flap the tx laser if it has not already been done */ - if (hw->mac.ops.flap_tx_laser) - hw->mac.ops.flap_tx_laser(hw); - - /* - * Wait for the controller to acquire link. Per IEEE 802.3ap, - * Section 73.10.2, we may have to wait up to 500ms if KR is - * attempted. 82599 uses the same timing for 10g SFI. - */ - for (i = 0; i < 5; i++) { - /* Wait for the link partner to also set speed */ - msleep(100); - - /* If we have link, just jump out */ - status = hw->mac.ops.check_link(hw, &link_speed, - &link_up, false); - if (status != 0) - return status; - - if (link_up) - goto out; - } - } - - if (speed & IXGBE_LINK_SPEED_1GB_FULL) { - speedcnt++; - if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) - highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; - - /* If we already have link at this speed, just jump out */ - status = hw->mac.ops.check_link(hw, &link_speed, &link_up, - false); - if (status != 0) - return status; - - if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up) - goto out; - - /* Set the module link speed */ - switch (hw->phy.media_type) { - case ixgbe_media_type_fiber: - esdp_reg &= ~IXGBE_ESDP_SDP5; - esdp_reg |= IXGBE_ESDP_SDP5_DIR; - IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); - IXGBE_WRITE_FLUSH(hw); - break; - case ixgbe_media_type_fiber_qsfp: - /* QSFP module automatically detects MAC link speed */ - break; - default: - hw_dbg(hw, "Unexpected media type.\n"); - break; - } - - /* Allow module to change analog characteristics (10G->1G) */ - msleep(40); - - status = ixgbe_setup_mac_link_82599(hw, - IXGBE_LINK_SPEED_1GB_FULL, - autoneg_wait_to_complete); - if (status != 0) - return status; - - /* Flap the tx laser if it has not already been done */ - if (hw->mac.ops.flap_tx_laser) - hw->mac.ops.flap_tx_laser(hw); - - /* Wait for the link partner to also set speed */ - msleep(100); - - /* If we have link, just jump out */ - status = hw->mac.ops.check_link(hw, &link_speed, &link_up, - false); - if (status != 0) - return status; - - if (link_up) - goto out; + switch (speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5); + break; + case IXGBE_LINK_SPEED_1GB_FULL: + esdp_reg &= ~IXGBE_ESDP_SDP5; + esdp_reg |= IXGBE_ESDP_SDP5_DIR; + break; + default: + hw_dbg(hw, "Invalid fixed module speed\n"); + return; } - /* - * We didn't get link. Configure back to the highest speed we tried, - * (if there was more than one). We call ourselves back with just the - * single highest speed that the user requested. - */ - if (speedcnt > 1) - status = ixgbe_setup_mac_link_multispeed_fiber(hw, - highest_link_speed, - autoneg_wait_to_complete); - -out: - /* Set autoneg_advertised value based on input link speed */ - hw->phy.autoneg_advertised = 0; - - if (speed & IXGBE_LINK_SPEED_10GB_FULL) - hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; - - if (speed & IXGBE_LINK_SPEED_1GB_FULL) - hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; - - return status; + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); + IXGBE_WRITE_FLUSH(hw); } /** diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 3f56a8080118..2cd0c3a48a8d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -3920,3 +3920,213 @@ bool ixgbe_mng_present(struct ixgbe_hw *hw) fwsm &= IXGBE_FWSM_MODE_MASK; return fwsm == IXGBE_FWSM_FW_MODE_PT; } + +/** + * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed + * @hw: pointer to hardware structure + * @speed: new link speed + * @autoneg_wait_to_complete: true when waiting for completion is needed + * + * Set the link speed in the MAC and/or PHY register and restarts link. + */ +s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, + ixgbe_link_speed speed, + bool autoneg_wait_to_complete) +{ + ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; + ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; + s32 status = 0; + u32 speedcnt = 0; + u32 i = 0; + bool autoneg, link_up = false; + + /* Mask off requested but non-supported speeds */ + status = hw->mac.ops.get_link_capabilities(hw, &link_speed, &autoneg); + if (status) + return status; + + speed &= link_speed; + + /* Try each speed one by one, highest priority first. We do this in + * software because 10Gb fiber doesn't support speed autonegotiation. + */ + if (speed & IXGBE_LINK_SPEED_10GB_FULL) { + speedcnt++; + highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; + + /* If we already have link at this speed, just jump out */ + status = hw->mac.ops.check_link(hw, &link_speed, &link_up, + false); + if (status) + return status; + + if (link_speed == IXGBE_LINK_SPEED_10GB_FULL && link_up) + goto out; + + /* Set the module link speed */ + switch (hw->phy.media_type) { + case ixgbe_media_type_fiber: + hw->mac.ops.set_rate_select_speed(hw, + IXGBE_LINK_SPEED_10GB_FULL); + break; + case ixgbe_media_type_fiber_qsfp: + /* QSFP module automatically detects MAC link speed */ + break; + default: + hw_dbg(hw, "Unexpected media type\n"); + break; + } + + /* Allow module to change analog characteristics (1G->10G) */ + msleep(40); + + status = hw->mac.ops.setup_mac_link(hw, + IXGBE_LINK_SPEED_10GB_FULL, + autoneg_wait_to_complete); + if (status) + return status; + + /* Flap the Tx laser if it has not already been done */ + if (hw->mac.ops.flap_tx_laser) + hw->mac.ops.flap_tx_laser(hw); + + /* Wait for the controller to acquire link. Per IEEE 802.3ap, + * Section 73.10.2, we may have to wait up to 500ms if KR is + * attempted. 82599 uses the same timing for 10g SFI. + */ + for (i = 0; i < 5; i++) { + /* Wait for the link partner to also set speed */ + msleep(100); + + /* If we have link, just jump out */ + status = hw->mac.ops.check_link(hw, &link_speed, + &link_up, false); + if (status) + return status; + + if (link_up) + goto out; + } + } + + if (speed & IXGBE_LINK_SPEED_1GB_FULL) { + speedcnt++; + if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) + highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; + + /* If we already have link at this speed, just jump out */ + status = hw->mac.ops.check_link(hw, &link_speed, &link_up, + false); + if (status) + return status; + + if (link_speed == IXGBE_LINK_SPEED_1GB_FULL && link_up) + goto out; + + /* Set the module link speed */ + switch (hw->phy.media_type) { + case ixgbe_media_type_fiber: + hw->mac.ops.set_rate_select_speed(hw, + IXGBE_LINK_SPEED_1GB_FULL); + break; + case ixgbe_media_type_fiber_qsfp: + /* QSFP module automatically detects link speed */ + break; + default: + hw_dbg(hw, "Unexpected media type\n"); + break; + } + + /* Allow module to change analog characteristics (10G->1G) */ + msleep(40); + + status = hw->mac.ops.setup_mac_link(hw, + IXGBE_LINK_SPEED_1GB_FULL, + autoneg_wait_to_complete); + if (status) + return status; + + /* Flap the Tx laser if it has not already been done */ + if (hw->mac.ops.flap_tx_laser) + hw->mac.ops.flap_tx_laser(hw); + + /* Wait for the link partner to also set speed */ + msleep(100); + + /* If we have link, just jump out */ + status = hw->mac.ops.check_link(hw, &link_speed, &link_up, + false); + if (status) + return status; + + if (link_up) + goto out; + } + + /* We didn't get link. Configure back to the highest speed we tried, + * (if there was more than one). We call ourselves back with just the + * single highest speed that the user requested. + */ + if (speedcnt > 1) + status = ixgbe_setup_mac_link_multispeed_fiber(hw, + highest_link_speed, + autoneg_wait_to_complete); + +out: + /* Set autoneg_advertised value based on input link speed */ + hw->phy.autoneg_advertised = 0; + + if (speed & IXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; + + if (speed & IXGBE_LINK_SPEED_1GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; + + return status; +} + +/** + * ixgbe_set_soft_rate_select_speed - Set module link speed + * @hw: pointer to hardware structure + * @speed: link speed to set + * + * Set module link speed via the soft rate select. + */ +void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, + ixgbe_link_speed speed) +{ + s32 status; + u8 rs, eeprom_data; + + switch (speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + /* one bit mask same as setting on */ + rs = IXGBE_SFF_SOFT_RS_SELECT_10G; + break; + case IXGBE_LINK_SPEED_1GB_FULL: + rs = IXGBE_SFF_SOFT_RS_SELECT_1G; + break; + default: + hw_dbg(hw, "Invalid fixed module speed\n"); + return; + } + + /* Set RS0 */ + status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, + IXGBE_I2C_EEPROM_DEV_ADDR2, + &eeprom_data); + if (status) { + hw_dbg(hw, "Failed to read Rx Rate Select RS0\n"); + return; + } + + eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; + + status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, + IXGBE_I2C_EEPROM_DEV_ADDR2, + eeprom_data); + if (status) { + hw_dbg(hw, "Failed to write Rx Rate Select RS0\n"); + return; + } +} diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h index 2f779f35dc4f..a0044e4a8b90 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h @@ -135,6 +135,11 @@ s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw); s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw); void ixgbe_disable_rx_generic(struct ixgbe_hw *hw); void ixgbe_enable_rx_generic(struct ixgbe_hw *hw); +s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, + ixgbe_link_speed speed, + bool autoneg_wait_to_complete); +void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, + ixgbe_link_speed speed); #define IXGBE_FAILED_READ_REG 0xffffffffU #define IXGBE_FAILED_READ_CFG_DWORD 0xffffffffU diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h index 0769b40399ea..824a2636aa9a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h @@ -66,6 +66,9 @@ #define IXGBE_SFF_1GBASET_CAPABLE 0x8 #define IXGBE_SFF_10GBASESR_CAPABLE 0x10 #define IXGBE_SFF_10GBASELR_CAPABLE 0x20 +#define IXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 +#define IXGBE_SFF_SOFT_RS_SELECT_10G 0x8 +#define IXGBE_SFF_SOFT_RS_SELECT_1G 0x0 #define IXGBE_SFF_ADDRESSING_MODE 0x4 #define IXGBE_SFF_QSFP_DA_ACTIVE_CABLE 0x1 #define IXGBE_SFF_QSFP_DA_PASSIVE_CABLE 0x8 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 3be743b4f6ba..deef530348a0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -3256,9 +3256,11 @@ struct ixgbe_mac_operations { void (*flap_tx_laser)(struct ixgbe_hw *); void (*stop_link_on_d3)(struct ixgbe_hw *); s32 (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool); + s32 (*setup_mac_link)(struct ixgbe_hw *, ixgbe_link_speed, bool); s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool); s32 (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *, bool *); + void (*set_rate_select_speed)(struct ixgbe_hw *, ixgbe_link_speed); /* Packet Buffer Manipulation */ void (*set_rxpba)(struct ixgbe_hw *, int, u32, int); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 2a1dca6e8d44..c6ae72bc92a0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -909,6 +909,20 @@ static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) return status; } +/** + * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. + * @hw: pointer to hardware structure + * + * Configures the extern PHY and the integrated KR PHY for SFP support. + */ +static s32 +ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, + ixgbe_link_speed speed, + __always_unused bool autoneg_wait_to_complete) +{ + return ixgbe_setup_ixfi_x550em(hw, &speed); +} + /** * ixgbe_setup_mac_link_t_X550em - Sets the auto advertised link speed * @hw: pointer to hardware structure @@ -1003,6 +1017,10 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) mac->ops.disable_tx_laser = NULL; mac->ops.enable_tx_laser = NULL; mac->ops.flap_tx_laser = NULL; + mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; + mac->ops.setup_mac_link = ixgbe_setup_mac_link_sfp_x550em; + mac->ops.set_rate_select_speed = + ixgbe_set_soft_rate_select_speed; break; case ixgbe_media_type_copper: mac->ops.setup_link = ixgbe_setup_mac_link_t_X550em; -- cgit v1.2.3 From e23f33367882450c66f7de8805b98ce7665a7ba9 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:18:33 -0700 Subject: ixgbe: Fix 1G and 10G link stability for X550EM_x SFP+ Configures the CS4227 correctly for both 1G and 10G operation, by moving the code to ixgbe_setup_mac_link_sfp_x550em(). It needs to be in this function because we need both the module type and the speed, and this is the only function in the init flow that knows the speed. In contrast, ixgbe_setup_sfp_modules_X550em() does not know the speed, so we can't do anything useful here. This is a fundamental difference from the previous flow, and is due to the way the CS4227 is implemented. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h | 7 +- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 127 +++++++++++++++++--------- 2 files changed, 90 insertions(+), 44 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h index 824a2636aa9a..85e142cf01a8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h @@ -81,7 +81,12 @@ #define IXGBE_I2C_EEPROM_STATUS_FAIL 0x2 #define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3 #define IXGBE_CS4227 0xBE /* CS4227 address */ -#define IXGBE_CS4227_SPARE24_LSB 0x12B0 /* Reg to program EDC */ +#define IXGBE_CS4227_LINE_SPARE22_MSB 0x12AD /* Reg to set speed */ +#define IXGBE_CS4227_LINE_SPARE24_LSB 0x12B0 /* Reg to set EDC */ +#define IXGBE_CS4227_HOST_SPARE22_MSB 0x1AAD /* Reg to set speed */ +#define IXGBE_CS4227_HOST_SPARE24_LSB 0x1AB0 /* Reg to program EDC */ +#define IXGBE_CS4227_SPEED_1G 0x8000 +#define IXGBE_CS4227_SPEED_10G 0 #define IXGBE_CS4227_EDC_MODE_CX1 0x0002 #define IXGBE_CS4227_EDC_MODE_SR 0x0004 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index c6ae72bc92a0..970dc6a78e14 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -909,6 +909,40 @@ static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed) return status; } +/** + * ixgbe_supported_sfp_modules_X550em - Check if SFP module type is supported + * @hw: pointer to hardware structure + * @linear: true if SFP module is linear + */ +static s32 ixgbe_supported_sfp_modules_X550em(struct ixgbe_hw *hw, bool *linear) +{ + switch (hw->phy.sfp_type) { + case ixgbe_sfp_type_not_present: + return IXGBE_ERR_SFP_NOT_PRESENT; + case ixgbe_sfp_type_da_cu_core0: + case ixgbe_sfp_type_da_cu_core1: + *linear = true; + break; + case ixgbe_sfp_type_srlr_core0: + case ixgbe_sfp_type_srlr_core1: + case ixgbe_sfp_type_da_act_lmt_core0: + case ixgbe_sfp_type_da_act_lmt_core1: + case ixgbe_sfp_type_1g_sx_core0: + case ixgbe_sfp_type_1g_sx_core1: + case ixgbe_sfp_type_1g_lx_core0: + case ixgbe_sfp_type_1g_lx_core1: + *linear = false; + break; + case ixgbe_sfp_type_unknown: + case ixgbe_sfp_type_1g_cu_core0: + case ixgbe_sfp_type_1g_cu_core1: + default: + return IXGBE_ERR_SFP_NOT_SUPPORTED; + } + + return 0; +} + /** * ixgbe_setup_mac_link_sfp_x550em - Configure the KR PHY for SFP. * @hw: pointer to hardware structure @@ -920,7 +954,49 @@ ixgbe_setup_mac_link_sfp_x550em(struct ixgbe_hw *hw, ixgbe_link_speed speed, __always_unused bool autoneg_wait_to_complete) { - return ixgbe_setup_ixfi_x550em(hw, &speed); + s32 status; + u16 slice, value; + bool setup_linear = false; + + /* Check if SFP module is supported and linear */ + status = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear); + + /* If no SFP module present, then return success. Return success since + * there is no reason to configure CS4227 and SFP not present error is + * not accepted in the setup MAC link flow. + */ + if (status == IXGBE_ERR_SFP_NOT_PRESENT) + return 0; + + if (status) + return status; + + /* Configure CS4227 LINE side to 10G SR. */ + slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12); + value = IXGBE_CS4227_SPEED_10G; + status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, slice, + value); + + /* Configure CS4227 for HOST connection rate then type. */ + slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12); + value = speed & IXGBE_LINK_SPEED_10GB_FULL ? + IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G; + status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, slice, + value); + + slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12); + if (setup_linear) + value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1; + else + value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1; + status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227, slice, + value); + + /* If internal link mode is XFI, then setup XFI internal link. */ + if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) + status = ixgbe_setup_ixfi_x550em(hw, &speed); + + return status; } /** @@ -1036,53 +1112,18 @@ static void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw) */ static s32 ixgbe_setup_sfp_modules_X550em(struct ixgbe_hw *hw) { - bool setup_linear; - u16 reg_slice, edc_mode; - s32 ret_val; + s32 status; + bool linear; - switch (hw->phy.sfp_type) { - case ixgbe_sfp_type_unknown: - return 0; - case ixgbe_sfp_type_not_present: - return IXGBE_ERR_SFP_NOT_PRESENT; - case ixgbe_sfp_type_da_cu_core0: - case ixgbe_sfp_type_da_cu_core1: - setup_linear = true; - break; - case ixgbe_sfp_type_srlr_core0: - case ixgbe_sfp_type_srlr_core1: - case ixgbe_sfp_type_da_act_lmt_core0: - case ixgbe_sfp_type_da_act_lmt_core1: - case ixgbe_sfp_type_1g_sx_core0: - case ixgbe_sfp_type_1g_sx_core1: - setup_linear = false; - break; - default: - return IXGBE_ERR_SFP_NOT_SUPPORTED; - } + /* Check if SFP module is supported */ + status = ixgbe_supported_sfp_modules_X550em(hw, &linear); + if (status) + return status; ixgbe_init_mac_link_ops_X550em(hw); hw->phy.ops.reset = NULL; - /* The CS4227 slice address is the base address + the port-pair reg - * offset. I.e. Slice 0 = 0x12B0 and slice 1 = 0x22B0. - */ - reg_slice = IXGBE_CS4227_SPARE24_LSB + (hw->bus.lan_id << 12); - - if (setup_linear) - edc_mode = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1; - else - edc_mode = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1; - - /* Configure CS4227 for connection type. */ - ret_val = hw->phy.ops.write_i2c_combined(hw, IXGBE_CS4227, reg_slice, - edc_mode); - - if (ret_val) - ret_val = hw->phy.ops.write_i2c_combined(hw, 0x80, reg_slice, - edc_mode); - - return ret_val; + return 0; } /** ixgbe_get_link_capabilities_x550em - Determines link capabilities -- cgit v1.2.3 From 542b6eecf4c3640f15a84ff89525131d421e7c8c Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:18:38 -0700 Subject: ixgbe: Add logic to reset CS4227 when needed On some hardware platforms, the CS4227 does not initialize properly. Detect those cases and reset it appropriately. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h | 15 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 279 +++++++++++++++++++++++++- 2 files changed, 293 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h index 85e142cf01a8..5abd66c84d00 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h @@ -81,14 +81,29 @@ #define IXGBE_I2C_EEPROM_STATUS_FAIL 0x2 #define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3 #define IXGBE_CS4227 0xBE /* CS4227 address */ +#define IXGBE_CS4227_SCRATCH 2 +#define IXGBE_CS4227_RESET_PENDING 0x1357 +#define IXGBE_CS4227_RESET_COMPLETE 0x5AA5 +#define IXGBE_CS4227_RETRIES 15 +#define IXGBE_CS4227_EFUSE_STATUS 0x0181 #define IXGBE_CS4227_LINE_SPARE22_MSB 0x12AD /* Reg to set speed */ #define IXGBE_CS4227_LINE_SPARE24_LSB 0x12B0 /* Reg to set EDC */ #define IXGBE_CS4227_HOST_SPARE22_MSB 0x1AAD /* Reg to set speed */ #define IXGBE_CS4227_HOST_SPARE24_LSB 0x1AB0 /* Reg to program EDC */ +#define IXGBE_CS4227_EEPROM_STATUS 0x5001 +#define IXGBE_CS4227_EEPROM_LOAD_OK 0x0001 #define IXGBE_CS4227_SPEED_1G 0x8000 #define IXGBE_CS4227_SPEED_10G 0 #define IXGBE_CS4227_EDC_MODE_CX1 0x0002 #define IXGBE_CS4227_EDC_MODE_SR 0x0004 +#define IXGBE_CS4227_EDC_MODE_DIAG 0x0008 +#define IXGBE_CS4227_RESET_HOLD 500 /* microseconds */ +#define IXGBE_CS4227_RESET_DELAY 500 /* milliseconds */ +#define IXGBE_CS4227_CHECK_DELAY 30 /* milliseconds */ +#define IXGBE_PE 0xE0 /* Port expander addr */ +#define IXGBE_PE_OUTPUT 1 /* Output reg offset */ +#define IXGBE_PE_CONFIG 3 /* Config reg offset */ +#define IXGBE_PE_BIT1 (1 << 1) /* Flow control defines */ #define IXGBE_TAF_SYM_PAUSE 0x400 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 970dc6a78e14..5048b90165d7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -56,6 +56,283 @@ static void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw) IXGBE_WRITE_FLUSH(hw); } +/** + * ixgbe_read_cs4227 - Read CS4227 register + * @hw: pointer to hardware structure + * @reg: register number to write + * @value: pointer to receive value read + * + * Returns status code + */ +static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value) +{ + return hw->phy.ops.read_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, + value); +} + +/** + * ixgbe_write_cs4227 - Write CS4227 register + * @hw: pointer to hardware structure + * @reg: register number to write + * @value: value to write to register + * + * Returns status code + */ +static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value) +{ + return hw->phy.ops.write_i2c_combined_unlocked(hw, IXGBE_CS4227, reg, + value); +} + +/** + * ixgbe_check_cs4227_reg - Perform diag on a CS4227 register + * @hw: pointer to hardware structure + * @reg: the register to check + * + * Performs a diagnostic on a register in the CS4227 chip. Returns an error + * if it is not operating correctly. + * This function assumes that the caller has acquired the proper semaphore. + */ +static s32 ixgbe_check_cs4227_reg(struct ixgbe_hw *hw, u16 reg) +{ + s32 status; + u32 retry; + u16 reg_val; + + reg_val = (IXGBE_CS4227_EDC_MODE_DIAG << 1) | 1; + status = ixgbe_write_cs4227(hw, reg, reg_val); + if (status) + return status; + for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { + msleep(IXGBE_CS4227_CHECK_DELAY); + reg_val = 0xFFFF; + ixgbe_read_cs4227(hw, reg, ®_val); + if (!reg_val) + break; + } + if (reg_val) { + hw_err(hw, "CS4227 reg 0x%04X failed diagnostic\n", reg); + return status; + } + + return 0; +} + +/** + * ixgbe_get_cs4227_status - Return CS4227 status + * @hw: pointer to hardware structure + * + * Performs a diagnostic on the CS4227 chip. Returns an error if it is + * not operating correctly. + * This function assumes that the caller has acquired the proper semaphore. + */ +static s32 ixgbe_get_cs4227_status(struct ixgbe_hw *hw) +{ + s32 status; + u16 value = 0; + + /* Exit if the diagnostic has already been performed. */ + status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); + if (status) + return status; + if (value == IXGBE_CS4227_RESET_COMPLETE) + return 0; + + /* Check port 0. */ + status = ixgbe_check_cs4227_reg(hw, IXGBE_CS4227_LINE_SPARE24_LSB); + if (status) + return status; + + status = ixgbe_check_cs4227_reg(hw, IXGBE_CS4227_HOST_SPARE24_LSB); + if (status) + return status; + + /* Check port 1. */ + status = ixgbe_check_cs4227_reg(hw, IXGBE_CS4227_LINE_SPARE24_LSB + + (1 << 12)); + if (status) + return status; + + return ixgbe_check_cs4227_reg(hw, IXGBE_CS4227_HOST_SPARE24_LSB + + (1 << 12)); +} + +/** + * ixgbe_read_pe - Read register from port expander + * @hw: pointer to hardware structure + * @reg: register number to read + * @value: pointer to receive read value + * + * Returns status code + */ +static s32 ixgbe_read_pe(struct ixgbe_hw *hw, u8 reg, u8 *value) +{ + s32 status; + + status = ixgbe_read_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, value); + if (status) + hw_err(hw, "port expander access failed with %d\n", status); + return status; +} + +/** + * ixgbe_write_pe - Write register to port expander + * @hw: pointer to hardware structure + * @reg: register number to write + * @value: value to write + * + * Returns status code + */ +static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) +{ + s32 status; + + status = ixgbe_write_i2c_byte_generic_unlocked(hw, reg, IXGBE_PE, + value); + if (status) + hw_err(hw, "port expander access failed with %d\n", status); + return status; +} + +/** + * ixgbe_reset_cs4227 - Reset CS4227 using port expander + * @hw: pointer to hardware structure + * + * Returns error code + */ +static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) +{ + s32 status; + u32 retry; + u16 value; + u8 reg; + + /* Trigger hard reset. */ + status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); + if (status) + return status; + reg |= IXGBE_PE_BIT1; + status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); + if (status) + return status; + + status = ixgbe_read_pe(hw, IXGBE_PE_CONFIG, ®); + if (status) + return status; + reg &= ~IXGBE_PE_BIT1; + status = ixgbe_write_pe(hw, IXGBE_PE_CONFIG, reg); + if (status) + return status; + + status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); + if (status) + return status; + reg &= ~IXGBE_PE_BIT1; + status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); + if (status) + return status; + + usleep_range(IXGBE_CS4227_RESET_HOLD, IXGBE_CS4227_RESET_HOLD + 100); + + status = ixgbe_read_pe(hw, IXGBE_PE_OUTPUT, ®); + if (status) + return status; + reg |= IXGBE_PE_BIT1; + status = ixgbe_write_pe(hw, IXGBE_PE_OUTPUT, reg); + if (status) + return status; + + /* Wait for the reset to complete. */ + msleep(IXGBE_CS4227_RESET_DELAY); + for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { + status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EFUSE_STATUS, + &value); + if (!status && value == IXGBE_CS4227_EEPROM_LOAD_OK) + break; + msleep(IXGBE_CS4227_CHECK_DELAY); + } + if (retry == IXGBE_CS4227_RETRIES) { + hw_err(hw, "CS4227 reset did not complete\n"); + return IXGBE_ERR_PHY; + } + + status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value); + if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) { + hw_err(hw, "CS4227 EEPROM did not load successfully\n"); + return IXGBE_ERR_PHY; + } + + return 0; +} + +/** + * ixgbe_check_cs4227 - Check CS4227 and reset as needed + * @hw: pointer to hardware structure + */ +static void ixgbe_check_cs4227(struct ixgbe_hw *hw) +{ + u32 swfw_mask = hw->phy.phy_semaphore_mask; + s32 status; + u16 value; + u8 retry; + + for (retry = 0; retry < IXGBE_CS4227_RETRIES; retry++) { + status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); + if (status) { + hw_err(hw, "semaphore failed with %d\n", status); + msleep(IXGBE_CS4227_CHECK_DELAY); + continue; + } + + /* Get status of reset flow. */ + status = ixgbe_read_cs4227(hw, IXGBE_CS4227_SCRATCH, &value); + if (!status && value == IXGBE_CS4227_RESET_COMPLETE) + goto out; + + if (status || value != IXGBE_CS4227_RESET_PENDING) + break; + + /* Reset is pending. Wait and check again. */ + hw->mac.ops.release_swfw_sync(hw, swfw_mask); + msleep(IXGBE_CS4227_CHECK_DELAY); + } + + /* Reset the CS4227. */ + status = ixgbe_reset_cs4227(hw); + if (status) { + hw_err(hw, "CS4227 reset failed: %d", status); + goto out; + } + + /* Reset takes so long, temporarily release semaphore in case the + * other driver instance is waiting for the reset indication. + */ + ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, + IXGBE_CS4227_RESET_PENDING); + hw->mac.ops.release_swfw_sync(hw, swfw_mask); + usleep_range(10000, 12000); + status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); + if (status) { + hw_err(hw, "semaphore failed with %d", status); + return; + } + + /* Is the CS4227 working correctly? */ + status = ixgbe_get_cs4227_status(hw); + if (status) { + hw_err(hw, "CS4227 status failed: %d", status); + goto out; + } + + /* Record completion for next time. */ + status = ixgbe_write_cs4227(hw, IXGBE_CS4227_SCRATCH, + IXGBE_CS4227_RESET_COMPLETE); + +out: + hw->mac.ops.release_swfw_sync(hw, swfw_mask); + msleep(hw->eeprom.semaphore_delay); +} + /** ixgbe_identify_phy_x550em - Get PHY type based on device id * @hw: pointer to hardware structure * @@ -68,7 +345,7 @@ static s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw) /* set up for CS4227 usage */ hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM; ixgbe_setup_mux_ctl(hw); - + ixgbe_check_cs4227(hw); return ixgbe_identify_module_generic(hw); case IXGBE_DEV_ID_X550EM_X_KX4: hw->phy.type = ixgbe_phy_x550em_kx4; -- cgit v1.2.3 From 69eec0c2fa8781a6abae96af1f11069e1965cbfe Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:18:43 -0700 Subject: ixgbe: Allow SFP+ on more than 82598 and 82599 Since SFP+ can be used with some X550 devices, permit them to be detected. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c index 7a7ee9d84ac8..fb8673d63806 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c @@ -1230,7 +1230,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) hw->phy.sfp_type = ixgbe_sfp_type_lr; else hw->phy.sfp_type = ixgbe_sfp_type_unknown; - } else if (hw->mac.type == ixgbe_mac_82599EB) { + } else { if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = -- cgit v1.2.3 From 58e7cd24d474c87763387f606e403012f562760b Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:18:48 -0700 Subject: ixgbe: Limit SFP polling rate Reduce the frequency of polling for SFP modules. Because the service task sometimes runs at high rates, we can poll for SFPs too often. When an SFP is not present, the I2C timeouts that result are very costly. So, prevent SFP polling from being done more than once every two seconds. To reduce latency, the poll time is cleared in a couple of cases to permit the next service task execution to poll the SFP module. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 2 ++ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 8 ++++++++ 2 files changed, 10 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index a699c991ad2c..dda0f678339a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -594,6 +594,7 @@ struct ixgbe_mac_addr { /* default to trying for four seconds */ #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ) +#define IXGBE_SFP_POLL_JIFFIES (2 * HZ) /* SFP poll every 2 seconds */ /* board specific private data structure */ struct ixgbe_adapter { @@ -707,6 +708,7 @@ struct ixgbe_adapter { u32 link_speed; bool link_up; + unsigned long sfp_poll_time; unsigned long link_check_timeout; struct timer_list service_timer; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 369204c18832..9986be5b84ca 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2509,6 +2509,7 @@ static void ixgbe_check_sfp_event(struct ixgbe_adapter *adapter, u32 eicr) IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); if (!test_bit(__IXGBE_DOWN, &adapter->state)) { adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET; + adapter->sfp_poll_time = 0; ixgbe_service_event_schedule(adapter); } } @@ -4804,6 +4805,7 @@ static void ixgbe_sfp_link_config(struct ixgbe_adapter *adapter) adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP; adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET; + adapter->sfp_poll_time = 0; } /** @@ -6709,10 +6711,16 @@ static void ixgbe_sfp_detection_subtask(struct ixgbe_adapter *adapter) !(adapter->flags2 & IXGBE_FLAG2_SFP_NEEDS_RESET)) return; + if (adapter->sfp_poll_time && + time_after(adapter->sfp_poll_time, jiffies)) + return; /* If not yet time to poll for SFP */ + /* someone else is in init, wait until next service event */ if (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state)) return; + adapter->sfp_poll_time = jiffies + IXGBE_SFP_POLL_JIFFIES - 1; + err = hw->phy.ops.identify_sfp(hw); if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) goto sfp_out; -- cgit v1.2.3 From 449e21a92411ba35bfa68b4464aa7dbd1f705d28 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:18:53 -0700 Subject: ixgbe: Add I2C bus mux support Take control of an I2C mux that selects which SFP is attached to the I2C bus. The control of the mux is captured in the taking and releasing of the related semaphore. Because only port 1 can control the mux, port 1 always leaves the mux set to select port 0. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c | 97 +++++++++++++++++---------- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 63 ++++++++++++++++- 3 files changed, 122 insertions(+), 39 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index deef530348a0..998cfb915ad7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -1949,6 +1949,7 @@ enum { #define IXGBE_GSSR_SW_MNG_SM 0x0400 #define IXGBE_GSSR_SHARED_I2C_SM 0x1806 /* Wait for both phys & I2Cs */ #define IXGBE_GSSR_I2C_MASK 0x1800 +#define IXGBE_GSSR_NVM_PHY_MASK 0xF /* FW Status register bitmask */ #define IXGBE_FWSTS_FWRI 0x00000200 /* Firmware Reset Indication */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c index 4e758435ece8..ccf853f7b73e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c @@ -567,19 +567,25 @@ static s32 ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw) **/ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask) { - u32 swfw_sync; - u32 swmask = mask; - u32 fwmask = mask << 5; - u32 hwmask = 0; + u32 swmask = mask & IXGBE_GSSR_NVM_PHY_MASK; + u32 swi2c_mask = mask & IXGBE_GSSR_I2C_MASK; + u32 fwmask = swmask << 5; u32 timeout = 200; + u32 hwmask = 0; + u32 swfw_sync; u32 i; - if (swmask == IXGBE_GSSR_EEP_SM) + if (swmask & IXGBE_GSSR_EEP_SM) hwmask = IXGBE_GSSR_FLASH_SM; + /* SW only mask does not have FW bit pair */ + if (mask & IXGBE_GSSR_SW_MNG_SM) + swmask |= IXGBE_GSSR_SW_MNG_SM; + + swmask |= swi2c_mask; + fwmask |= swi2c_mask << 2; for (i = 0; i < timeout; i++) { - /* - * SW NVM semaphore bit is used for access to all + /* SW NVM semaphore bit is used for access to all * SW_FW_SYNC bits (not just NVM) */ if (ixgbe_get_swfw_sync_semaphore(hw)) @@ -590,39 +596,56 @@ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask) swfw_sync |= swmask; IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC(hw), swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); - break; - } else { - /* - * Firmware currently using resource (fwmask), - * hardware currently using resource (hwmask), - * or other software thread currently using - * resource (swmask) - */ - ixgbe_release_swfw_sync_semaphore(hw); - usleep_range(5000, 10000); + usleep_range(5000, 6000); + return 0; } + /* Firmware currently using resource (fwmask), hardware + * currently using resource (hwmask), or other software + * thread currently using resource (swmask) + */ + ixgbe_release_swfw_sync_semaphore(hw); + usleep_range(5000, 10000); } - /* - * If the resource is not released by the FW/HW the SW can assume that - * the FW/HW malfunctions. In that case the SW should sets the - * SW bit(s) of the requested resource(s) while ignoring the - * corresponding FW/HW bits in the SW_FW_SYNC register. - */ - if (i >= timeout) { - swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw)); - if (swfw_sync & (fwmask | hwmask)) { - if (ixgbe_get_swfw_sync_semaphore(hw)) - return IXGBE_ERR_SWFW_SYNC; + /* Failed to get SW only semaphore */ + if (swmask == IXGBE_GSSR_SW_MNG_SM) { + hw_dbg(hw, "Failed to get SW only semaphore\n"); + return IXGBE_ERR_SWFW_SYNC; + } - swfw_sync |= swmask; - IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC(hw), swfw_sync); - ixgbe_release_swfw_sync_semaphore(hw); - } + /* If the resource is not released by the FW/HW the SW can assume that + * the FW/HW malfunctions. In that case the SW should set the SW bit(s) + * of the requested resource(s) while ignoring the corresponding FW/HW + * bits in the SW_FW_SYNC register. + */ + if (ixgbe_get_swfw_sync_semaphore(hw)) + return IXGBE_ERR_SWFW_SYNC; + swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw)); + if (swfw_sync & (fwmask | hwmask)) { + swfw_sync |= swmask; + IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC(hw), swfw_sync); + ixgbe_release_swfw_sync_semaphore(hw); + usleep_range(5000, 6000); + return 0; + } + /* If the resource is not released by other SW the SW can assume that + * the other SW malfunctions. In that case the SW should clear all SW + * flags that it does not own and then repeat the whole process once + * again. + */ + if (swfw_sync & swmask) { + u32 rmask = IXGBE_GSSR_EEP_SM | IXGBE_GSSR_PHY0_SM | + IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_MAC_CSR_SM; + + if (swi2c_mask) + rmask |= IXGBE_GSSR_I2C_MASK; + ixgbe_release_swfw_sync_X540(hw, rmask); + ixgbe_release_swfw_sync_semaphore(hw); + return IXGBE_ERR_SWFW_SYNC; } + ixgbe_release_swfw_sync_semaphore(hw); - usleep_range(5000, 10000); - return 0; + return IXGBE_ERR_SWFW_SYNC; } /** @@ -635,9 +658,11 @@ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask) **/ void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask) { + u32 swmask = mask & (IXGBE_GSSR_NVM_PHY_MASK | IXGBE_GSSR_SW_MNG_SM); u32 swfw_sync; - u32 swmask = mask; + if (mask & IXGBE_GSSR_I2C_MASK) + swmask |= mask & IXGBE_GSSR_I2C_MASK; ixgbe_get_swfw_sync_semaphore(hw); swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw)); @@ -645,7 +670,7 @@ void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask) IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC(hw), swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); - usleep_range(5000, 10000); + usleep_range(5000, 6000); } /** diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 5048b90165d7..ed7b2899affe 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -2263,6 +2263,62 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, IXGBE_WRITE_REG(hw, IXGBE_PFFLPH, (u32)(pfflp >> 32)); } +/** + * ixgbe_set_mux - Set mux for port 1 access with CS4227 + * @hw: pointer to hardware structure + * @state: set mux if 1, clear if 0 + */ +static void ixgbe_set_mux(struct ixgbe_hw *hw, u8 state) +{ + u32 esdp; + + if (!hw->bus.lan_id) + return; + esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + if (state) + esdp |= IXGBE_ESDP_SDP1; + else + esdp &= ~IXGBE_ESDP_SDP1; + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); + IXGBE_WRITE_FLUSH(hw); +} + +/** + * ixgbe_acquire_swfw_sync_X550em - Acquire SWFW semaphore + * @hw: pointer to hardware structure + * @mask: Mask to specify which semaphore to acquire + * + * Acquires the SWFW semaphore and sets the I2C MUX + */ +static s32 ixgbe_acquire_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) +{ + s32 status; + + status = ixgbe_acquire_swfw_sync_X540(hw, mask); + if (status) + return status; + + if (mask & IXGBE_GSSR_I2C_MASK) + ixgbe_set_mux(hw, 1); + + return 0; +} + +/** + * ixgbe_release_swfw_sync_X550em - Release SWFW semaphore + * @hw: pointer to hardware structure + * @mask: Mask to specify which semaphore to release + * + * Releases the SWFW semaphore and sets the I2C MUX + */ +static void ixgbe_release_swfw_sync_X550em(struct ixgbe_hw *hw, u32 mask) +{ + if (mask & IXGBE_GSSR_I2C_MASK) + ixgbe_set_mux(hw, 0); + + ixgbe_release_swfw_sync_X540(hw, mask); +} + #define X550_COMMON_MAC \ .init_hw = &ixgbe_init_hw_generic, \ .start_hw = &ixgbe_start_hw_X540, \ @@ -2300,8 +2356,6 @@ static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw, &ixgbe_set_source_address_pruning_X550, \ .set_ethertype_anti_spoofing = \ &ixgbe_set_ethertype_anti_spoofing_X550, \ - .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, \ - .release_swfw_sync = &ixgbe_release_swfw_sync_X540, \ .disable_rx_buff = &ixgbe_disable_rx_buff_generic, \ .enable_rx_buff = &ixgbe_enable_rx_buff_generic, \ .get_thermal_sensor_data = NULL, \ @@ -2321,6 +2375,8 @@ static struct ixgbe_mac_operations mac_ops_X550 = { .get_link_capabilities = &ixgbe_get_copper_link_capabilities_generic, .get_bus_info = &ixgbe_get_bus_info_generic, .setup_sfp = NULL, + .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540, + .release_swfw_sync = &ixgbe_release_swfw_sync_X540, }; static struct ixgbe_mac_operations mac_ops_X550EM_x = { @@ -2333,7 +2389,8 @@ static struct ixgbe_mac_operations mac_ops_X550EM_x = { .get_link_capabilities = &ixgbe_get_link_capabilities_X550em, .get_bus_info = &ixgbe_get_bus_info_X550em, .setup_sfp = ixgbe_setup_sfp_modules_X550em, - + .acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X550em, + .release_swfw_sync = &ixgbe_release_swfw_sync_X550em, }; #define X550_COMMON_EEP \ -- cgit v1.2.3 From 5967fe225686bcae17352de172573964a15b17d5 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:18:59 -0700 Subject: ixgbe: Correct error path in semaphore handling The timeout path is supposed to release the semaphore, so do that. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c index ccf853f7b73e..c1d4584f6469 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c @@ -711,6 +711,11 @@ static s32 ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw) usleep_range(50, 100); } + /* Release semaphores and return error if SW NVM semaphore + * was not granted because we do not have access to the EEPROM + */ + hw_dbg(hw, "REGSMP Software NVM semaphore not granted\n"); + ixgbe_release_swfw_sync_semaphore(hw); return IXGBE_ERR_EEPROM; } -- cgit v1.2.3 From 052a1a724338bbf4721f8b4d7de8486701fc37cb Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:19:04 -0700 Subject: ixgbe: Correct setting of RDRXCTL register for X550* devices Setting the X550* RDRXCTL register should fall through into X540 and 82599, not 82598. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 9986be5b84ca..a10728c32f65 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3789,8 +3789,6 @@ static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter) u32 rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL); switch (hw->mac.type) { - case ixgbe_mac_X550: - case ixgbe_mac_X550EM_x: case ixgbe_mac_82598EB: /* * For VMDq support of different descriptor types or @@ -3804,6 +3802,8 @@ static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter) */ rdrxctl |= IXGBE_RDRXCTL_MVMEN; break; + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: case ixgbe_mac_82599EB: case ixgbe_mac_X540: /* Disable RSC for ACK packets */ -- cgit v1.2.3 From f961ddae164a5288a62146aae191da7bc1ecedb4 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:19:09 -0700 Subject: ixgbe: Add small packet padding support for X550 This patch sets RDRXCTL.PSP when the driver is in SRIOV mode which enables padding of small packets. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 +++ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index a10728c32f65..81cbca4e6df5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3804,6 +3804,9 @@ static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter) break; case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + if (adapter->num_vfs) + rdrxctl |= IXGBE_RDRXCTL_PSP; + /* fall through for older HW */ case ixgbe_mac_82599EB: case ixgbe_mac_X540: /* Disable RSC for ACK packets */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 998cfb915ad7..939c90c4ff39 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -1193,6 +1193,7 @@ struct ixgbe_thermal_sensor_data { /* RDRXCTL Bit Masks */ #define IXGBE_RDRXCTL_RDMTS_1_2 0x00000000 /* Rx Desc Min Threshold Size */ #define IXGBE_RDRXCTL_CRCSTRIP 0x00000002 /* CRC Strip */ +#define IXGBE_RDRXCTL_PSP 0x00000004 /* Pad small packet */ #define IXGBE_RDRXCTL_MVMEN 0x00000020 #define IXGBE_RDRXCTL_DMAIDONE 0x00000008 /* DMA init cycle done */ #define IXGBE_RDRXCTL_AGGDIS 0x00010000 /* Aggregation disable */ -- cgit v1.2.3 From 7fc151035487916b266257c2e7b8b6cb2a5cd04f Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:19:14 -0700 Subject: ixgbe: Update ixgbe_disable_pcie_master flow for X550* This patch skips the PCI transactions pending check in ixgbe_disable_pcie_master. This is done to addresses a known HW issue where the PCI transactions pending bit sticks high when there are pending transactions. HW engineering instructed to workaround this issue by wait and then continue with our reset flow. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 2cd0c3a48a8d..b620d7a6631e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -2476,6 +2476,9 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw) hw_dbg(hw, "GIO Master Disable bit didn't clear - requesting resets\n"); hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; + if (hw->mac.type >= ixgbe_mac_X550) + return 0; + /* * Before proceeding, make sure that the PCIe block does not have * transactions pending. -- cgit v1.2.3 From 018d7146eee1942f27675bdabf9b43586bfaef72 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:19:19 -0700 Subject: ixgbe: Add new X550EM SFP+ device ID Add new device ID for X550EM device with SFPs. Signed-off-by: Mark Rustad Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 81cbca4e6df5..28b85943d4f7 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -137,6 +137,7 @@ static const struct pci_device_id ixgbe_pci_tbl[] = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KX4), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_KR), board_X550EM_x}, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_10G_T), board_X550EM_x}, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_SFP), board_X550EM_x}, /* required last entry */ {0, } }; -- cgit v1.2.3 From 9de7605ea2389d5ab86d6fbb3f1a11b87665a35c Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:27:41 -0700 Subject: ixgbe: Correct several flaws with with DCA setup This change does two things. First, it makes it so that we always set the relaxed ordering bits related to the DCA registers even if DCA is not enabled. Second, it moves the configuration out of the ixgbe_down function and into the ixgbe_configure function before enabling the Rx and Tx rings. This ensures that DCA is configured correctly before starting to process packets. Thanks to Alex Duyck for this fix. CC: Alex Duyck Signed-off-by: Mark Rustad Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 40 +++++++++++++++++---------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 28b85943d4f7..97cded35dee3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1245,9 +1245,12 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter, int cpu) { struct ixgbe_hw *hw = &adapter->hw; - u32 txctrl = dca3_get_tag(tx_ring->dev, cpu); + u32 txctrl = 0; u16 reg_offset; + if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) + txctrl = dca3_get_tag(tx_ring->dev, cpu); + switch (hw->mac.type) { case ixgbe_mac_82598EB: reg_offset = IXGBE_DCA_TXCTRL(tx_ring->reg_idx); @@ -1279,9 +1282,11 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, int cpu) { struct ixgbe_hw *hw = &adapter->hw; - u32 rxctrl = dca3_get_tag(rx_ring->dev, cpu); + u32 rxctrl = 0; u8 reg_idx = rx_ring->reg_idx; + if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) + rxctrl = dca3_get_tag(rx_ring->dev, cpu); switch (hw->mac.type) { case ixgbe_mac_82599EB: @@ -1298,6 +1303,7 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, * which will cause the DCA tag to be cleared. */ rxctrl |= IXGBE_DCA_RXCTRL_DESC_RRO_EN | + IXGBE_DCA_RXCTRL_DATA_DCA_EN | IXGBE_DCA_RXCTRL_DESC_DCA_EN; IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(reg_idx), rxctrl); @@ -1327,11 +1333,13 @@ static void ixgbe_setup_dca(struct ixgbe_adapter *adapter) { int i; - if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED)) - return; - /* always use CB2 mode, difference is masked in the CB driver */ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2); + if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) + IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, + IXGBE_DCA_CTRL_DCA_MODE_CB2); + else + IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, + IXGBE_DCA_CTRL_DCA_DISABLE); for (i = 0; i < adapter->num_q_vectors; i++) { adapter->q_vector[i]->cpu = -1; @@ -1354,7 +1362,8 @@ static int __ixgbe_notify_dca(struct device *dev, void *data) break; if (dca_add_requester(dev) == 0) { adapter->flags |= IXGBE_FLAG_DCA_ENABLED; - ixgbe_setup_dca(adapter); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, + IXGBE_DCA_CTRL_DCA_MODE_CB2); break; } /* Fall Through since DCA is disabled. */ @@ -1362,7 +1371,8 @@ static int __ixgbe_notify_dca(struct device *dev, void *data) if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { dca_remove_requester(dev); adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 1); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, + IXGBE_DCA_CTRL_DCA_DISABLE); } break; } @@ -4783,6 +4793,12 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter) break; } +#ifdef CONFIG_IXGBE_DCA + /* configure DCA */ + if (adapter->flags & IXGBE_FLAG_DCA_CAPABLE) + ixgbe_setup_dca(adapter); +#endif /* CONFIG_IXGBE_DCA */ + #ifdef IXGBE_FCOE /* configure FCoE L2 filters, redirection table, and Rx control */ ixgbe_configure_fcoe(adapter); @@ -5243,11 +5259,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter) ixgbe_clean_all_tx_rings(adapter); ixgbe_clean_all_rx_rings(adapter); - -#ifdef CONFIG_IXGBE_DCA - /* since we reset the hardware DCA settings were cleared */ - ixgbe_setup_dca(adapter); -#endif } /** @@ -9036,7 +9047,8 @@ static void ixgbe_remove(struct pci_dev *pdev) if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED; dca_remove_requester(&pdev->dev); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 1); + IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, + IXGBE_DCA_CTRL_DCA_DISABLE); } #endif -- cgit v1.2.3 From 3507a9b8c9d1684b5095c97f587ee46184e590da Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:27:46 -0700 Subject: ixgbe: Only clear adapter_stopped if ixgbe_setup_fc succeeded A logic error here results in the adapter_stopped flag only being cleared when ixgbe_setup_fc returns an error. Correct the logic. Signed-off-by: Mark Rustad Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index b620d7a6631e..98e1ddde3104 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -297,13 +297,13 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw) /* Setup flow control */ ret_val = ixgbe_setup_fc(hw); - if (!ret_val) - return 0; + if (ret_val) + return ret_val; /* Clear adapter stopped flag */ hw->adapter_stopped = false; - return ret_val; + return 0; } /** -- cgit v1.2.3 From bc1fc64fd2d9093496e5b04c6d94d26bfa629c9c Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:27:51 -0700 Subject: ixgbe: Fix FCRTH value in VM-to-VM loopback mode The 82599 and X540 datasheets require that FCRTH be "set" for Tx switching (VM-to-VM loopback) but it did not previously specify what the value should be set to. It has now been determined that the correct value is RXPBSIZE - (24*1024). This setting is also required for later devices. Signed-off-by: Mark Rustad Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_common.c | 7 ++++--- drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c | 8 +++++++- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 98e1ddde3104..ce61b36b94f1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -2164,10 +2164,11 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw) /* * In order to prevent Tx hangs when the internal Tx * switch is enabled we must set the high water mark - * to the maximum FCRTH value. This allows the Tx - * switch to function even under heavy Rx workloads. + * to the Rx packet buffer size - 24KB. This allows + * the Tx switch to function even under heavy Rx + * workloads. */ - fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32; + fcrth = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576; } IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c index 3b932fe64ab6..23277ab153b6 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82599.c @@ -259,7 +259,13 @@ s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en, u8 *prio_tc) fcrtl = (hw->fc.low_water[i] << 10) | IXGBE_FCRTL_XONE; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), fcrtl); } else { - reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 32; + /* In order to prevent Tx hangs when the internal Tx + * switch is enabled we must set the high water mark + * to the Rx packet buffer size - 24KB. This allows + * the Tx switch to function even under heavy Rx + * workloads. + */ + reg = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i)) - 24576; IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), 0); } -- cgit v1.2.3 From c5846ba44500293d290eb2a31bd344565f237ad3 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Sat, 8 Aug 2015 16:27:56 -0700 Subject: ixgbe: X540 thermal warning interrupt not a GPI The X540 thermal interrupt (IXGBE_EIMS_TS) is not an SDP, so it doesn't need to be enabled in ixgbe_setup_gpie(). In fact the value is simply not for the GPIE register at all. Signed-off-by: Mark Rustad Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 97cded35dee3..9b70595b3f22 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -4916,9 +4916,6 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter) case ixgbe_mac_82599EB: gpie |= IXGBE_SDP0_GPIEN_8259X; break; - case ixgbe_mac_X540: - gpie |= IXGBE_EIMS_TS; - break; default: break; } -- cgit v1.2.3 From 21dd560162d4bbf98cc81b303bfa19740ae5b964 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Tue, 11 Aug 2015 13:11:58 -0700 Subject: ixgbe: Advance version to 4.2.1 With the addition of X550em_x SFP+ support, the driver is now functionally equivalent to what will be the 4.2.1 driver when released, so change the version to match. Signed-off-by: Mark Rustad Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 9b70595b3f22..191003901adb 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -79,7 +79,7 @@ char ixgbe_default_device_descr[] = static char ixgbe_default_device_descr[] = "Intel(R) 10 Gigabit Network Connection"; #endif -#define DRV_VERSION "4.0.1-k" +#define DRV_VERSION "4.2.1-k" const char ixgbe_driver_version[] = DRV_VERSION; static const char ixgbe_copyright[] = "Copyright (c) 1999-2015 Intel Corporation."; -- cgit v1.2.3 From eb24d061f4b80338672b7d38ee6331896f0a7710 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Thu, 24 Sep 2015 19:40:33 +0200 Subject: mrf24j40: remove trailing semicolon This patch removes a trailing semicolon which was introduced by commit d3f1bc3 ("mrf24j40: add cca mode support") and reported by kbuild test robot. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/mrf24j40.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 2770df11f883..aca0fb3cccbf 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -1239,7 +1239,7 @@ static void mrf24j40_phy_setup(struct mrf24j40 *devrec) devrec->hw->phy->supported.min_maxbe = 5; devrec->hw->phy->supported.max_maxbe = 5; - devrec->hw->phy->cca.mode = NL802154_CCA_CARRIER;; + devrec->hw->phy->cca.mode = NL802154_CCA_CARRIER; devrec->hw->phy->supported.cca_modes = BIT(NL802154_CCA_ENERGY) | BIT(NL802154_CCA_CARRIER) | BIT(NL802154_CCA_ENERGY_CARRIER); -- cgit v1.2.3 From 92c14d9b5ee86fd6cf136c01b6a87353522aebdd Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 22 Sep 2015 18:56:43 +0200 Subject: genetlink: simplify genl_notify The genl_notify function has too many arguments for no real reason - all callers use genl_info to get them anyway. Just pass the genl_info down to genl_notify. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/wireless/mac80211_hwsim.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 520bef80747f..66c963dbc3fd 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2190,9 +2190,8 @@ static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb, struct genl_info *info) { if (info) - genl_notify(&hwsim_genl_family, mcast_skb, - genl_info_net(info), info->snd_portid, - HWSIM_MCGRP_CONFIG, info->nlhdr, GFP_KERNEL); + genl_notify(&hwsim_genl_family, mcast_skb, info, + HWSIM_MCGRP_CONFIG, GFP_KERNEL); else genlmsg_multicast(&hwsim_genl_family, mcast_skb, 0, HWSIM_MCGRP_CONFIG, GFP_KERNEL); -- cgit v1.2.3 From 38cf595b195552276e1cf1826434e05782de4be8 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 22 Sep 2015 18:57:13 +0200 Subject: ipv6: remove unused neigh parameter from ndisc functions Since commit 12fd84f4383b1 ("ipv6: Remove unused neigh argument for icmp6_dst_alloc() and its callers."), the neigh parameter of ndisc_send_na and ndisc_send_ns is unused. CC: YOSHIFUJI Hideaki Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/usb/cdc_mbim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index efc18e05af0a..bbde9884ab8a 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c @@ -342,7 +342,7 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci) in6_dev_put(in6_dev); /* ipv6_stub != NULL if in6_dev_get returned an inet6_dev */ - ipv6_stub->ndisc_send_na(netdev, NULL, &iph->saddr, &msg->target, + ipv6_stub->ndisc_send_na(netdev, &iph->saddr, &msg->target, is_router /* router */, true /* solicited */, false /* override */, -- cgit v1.2.3 From e734a42f046104f798195042e5a4d4b357f0b3fb Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 23 Sep 2015 09:20:02 +0200 Subject: net: ll_temac: Use of_property_read_u32 instead of open-coding it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use of_property_read_u32 to read the "clock-frequency" property instead of using of_get_property with return value checks. Signed-off-by: Tobias Klauser Reviewed-by: Sören Brinkmann Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/ll_temac_mdio.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/xilinx/ll_temac_mdio.c b/drivers/net/ethernet/xilinx/ll_temac_mdio.c index 8cf9d4f56bb2..415de1eaf641 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_mdio.c +++ b/drivers/net/ethernet/xilinx/ll_temac_mdio.c @@ -59,16 +59,15 @@ static int temac_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val) int temac_mdio_setup(struct temac_local *lp, struct device_node *np) { struct mii_bus *bus; - const u32 *bus_hz; + u32 bus_hz; int clk_div; - int rc, size; + int rc; struct resource res; /* Calculate a reasonable divisor for the clock rate */ clk_div = 0x3f; /* worst-case default setting */ - bus_hz = of_get_property(np, "clock-frequency", &size); - if (bus_hz && size >= sizeof(*bus_hz)) { - clk_div = (*bus_hz) / (2500 * 1000 * 2) - 1; + if (of_property_read_u32(np, "clock-frequency", &bus_hz) == 0) { + clk_div = bus_hz / (2500 * 1000 * 2) - 1; if (clk_div < 1) clk_div = 1; if (clk_div > 0x3f) -- cgit v1.2.3 From 729bf329c79684327a55c33cdf21222543a1e5f1 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 23 Sep 2015 09:20:55 +0200 Subject: net: axinet: Use of_property_read_u32 instead of open-coding it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use of_property_read_u32 instead of of_get_property with return value checks and endianness conversion. Signed-off-by: Tobias Klauser Reviewed-by: Sören Brinkmann Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c index 2a5a16834c01..507bbb0355c2 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c @@ -129,7 +129,6 @@ int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np) { int ret; u32 clk_div, host_clock; - u32 *property_p; struct mii_bus *bus; struct resource res; struct device_node *np1; @@ -168,8 +167,7 @@ int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np) clk_div = DEFAULT_CLOCK_DIVISOR; goto issue; } - property_p = (u32 *) of_get_property(np1, "clock-frequency", NULL); - if (!property_p) { + if (of_property_read_u32(np1, "clock-frequency", &host_clock)) { netdev_warn(lp->ndev, "clock-frequency property not found.\n"); netdev_warn(lp->ndev, "Setting MDIO clock divisor to default %d\n", @@ -179,7 +177,6 @@ int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np) goto issue; } - host_clock = be32_to_cpup(property_p); clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1; /* If there is any remainder from the division of * fHOST / (MAX_MDIO_FREQ * 2), then we need to add -- cgit v1.2.3 From 69f5df491e0becb75d2d795add7481a35218d657 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 24 Sep 2015 10:02:40 +0200 Subject: switchdev: rename "trans" to "trans_ph". This is temporary, name "trans" will be used for something else and "trans_ph" will eventually disappear. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 382 +++++++++++++++++------------------ 1 file changed, 191 insertions(+), 191 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 32c5429ea5fe..cf03b077311e 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -343,7 +343,7 @@ static bool rocker_port_is_ovsed(const struct rocker_port *rocker_port) #define ROCKER_OP_FLAG_REFRESH BIT(3) static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, size_t size) { struct list_head *elem = NULL; @@ -359,7 +359,7 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port, * memory used in the commit phase. */ - switch (trans) { + switch (trans_ph) { case SWITCHDEV_TRANS_PREPARE: elem = kzalloc(size + sizeof(*elem), gfp_flags); if (!elem) @@ -384,20 +384,20 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port, } static void *rocker_port_kzalloc(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, size_t size) { - return __rocker_port_mem_alloc(rocker_port, trans, flags, size); + return __rocker_port_mem_alloc(rocker_port, trans_ph, flags, size); } static void *rocker_port_kcalloc(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, size_t n, size_t size) { - return __rocker_port_mem_alloc(rocker_port, trans, flags, n * size); + return __rocker_port_mem_alloc(rocker_port, trans_ph, flags, n * size); } -static void rocker_port_kfree(enum switchdev_trans trans, const void *mem) +static void rocker_port_kfree(enum switchdev_trans_ph trans_ph, const void *mem) { struct list_head *elem; @@ -406,7 +406,7 @@ static void rocker_port_kfree(enum switchdev_trans trans, const void *mem) * commit phase. */ - if (trans == SWITCHDEV_TRANS_PREPARE) + if (trans_ph == SWITCHDEV_TRANS_PREPARE) return; elem = (struct list_head *)mem - 1; @@ -433,22 +433,22 @@ static void rocker_wait_init(struct rocker_wait *wait) } static struct rocker_wait *rocker_wait_create(struct rocker_port *rocker_port, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, int flags) { struct rocker_wait *wait; - wait = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*wait)); + wait = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*wait)); if (!wait) return NULL; rocker_wait_init(wait); return wait; } -static void rocker_wait_destroy(enum switchdev_trans trans, +static void rocker_wait_destroy(enum switchdev_trans_ph trans_ph, struct rocker_wait *wait) { - rocker_port_kfree(trans, wait); + rocker_port_kfree(trans_ph, wait); } static bool rocker_wait_event_timeout(struct rocker_wait *wait, @@ -1466,7 +1466,7 @@ static int rocker_event_link_change(const struct rocker *rocker, } static int rocker_port_fdb(struct rocker_port *rocker_port, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, const unsigned char *addr, __be16 vlan_id, int flags); @@ -1585,7 +1585,7 @@ typedef int (*rocker_cmd_proc_cb_t)(const struct rocker_port *rocker_port, void *priv); static int rocker_cmd_exec(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, rocker_cmd_prep_cb_t prepare, void *prepare_priv, rocker_cmd_proc_cb_t process, void *process_priv) { @@ -1596,7 +1596,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port, unsigned long lock_flags; int err; - wait = rocker_wait_create(rocker_port, trans, flags); + wait = rocker_wait_create(rocker_port, trans_ph, flags); if (!wait) return -ENOMEM; wait->nowait = nowait; @@ -1618,7 +1618,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port, rocker_desc_cookie_ptr_set(desc_info, wait); - if (trans != SWITCHDEV_TRANS_PREPARE) + if (trans_ph != SWITCHDEV_TRANS_PREPARE) rocker_desc_head_set(rocker, &rocker->cmd_ring, desc_info); spin_unlock_irqrestore(&rocker->cmd_ring_lock, lock_flags); @@ -1626,7 +1626,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port, if (nowait) return 0; - if (trans != SWITCHDEV_TRANS_PREPARE) + if (trans_ph != SWITCHDEV_TRANS_PREPARE) if (!rocker_wait_event_timeout(wait, HZ / 10)) return -EIO; @@ -1639,7 +1639,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port, rocker_desc_gen_clear(desc_info); out: - rocker_wait_destroy(trans, wait); + rocker_wait_destroy(trans_ph, wait); return err; } @@ -1918,9 +1918,9 @@ static int rocker_cmd_set_port_settings_mtu(struct rocker_port *rocker_port, } static int rocker_port_set_learning(struct rocker_port *rocker_port, - enum switchdev_trans trans) + enum switchdev_trans_ph trans_ph) { - return rocker_cmd_exec(rocker_port, trans, 0, + return rocker_cmd_exec(rocker_port, trans_ph, 0, rocker_cmd_set_port_learning_prep, NULL, NULL, NULL); } @@ -2436,7 +2436,7 @@ rocker_flow_tbl_find(const struct rocker *rocker, } static int rocker_flow_tbl_add(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, struct rocker_flow_tbl_entry *match) { struct rocker *rocker = rocker_port->rocker; @@ -2452,9 +2452,9 @@ static int rocker_flow_tbl_add(struct rocker_port *rocker_port, if (found) { match->cookie = found->cookie; - if (trans != SWITCHDEV_TRANS_PREPARE) + if (trans_ph != SWITCHDEV_TRANS_PREPARE) hash_del(&found->entry); - rocker_port_kfree(trans, found); + rocker_port_kfree(trans_ph, found); found = match; found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_MOD; } else { @@ -2463,17 +2463,17 @@ static int rocker_flow_tbl_add(struct rocker_port *rocker_port, found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_ADD; } - if (trans != SWITCHDEV_TRANS_PREPARE) + if (trans_ph != SWITCHDEV_TRANS_PREPARE) hash_add(rocker->flow_tbl, &found->entry, found->key_crc32); spin_unlock_irqrestore(&rocker->flow_tbl_lock, lock_flags); - return rocker_cmd_exec(rocker_port, trans, flags, + return rocker_cmd_exec(rocker_port, trans_ph, flags, rocker_cmd_flow_tbl_add, found, NULL, NULL); } static int rocker_flow_tbl_del(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, struct rocker_flow_tbl_entry *match) { struct rocker *rocker = rocker_port->rocker; @@ -2489,43 +2489,43 @@ static int rocker_flow_tbl_del(struct rocker_port *rocker_port, found = rocker_flow_tbl_find(rocker, match); if (found) { - if (trans != SWITCHDEV_TRANS_PREPARE) + if (trans_ph != SWITCHDEV_TRANS_PREPARE) hash_del(&found->entry); found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_DEL; } spin_unlock_irqrestore(&rocker->flow_tbl_lock, lock_flags); - rocker_port_kfree(trans, match); + rocker_port_kfree(trans_ph, match); if (found) { - err = rocker_cmd_exec(rocker_port, trans, flags, + err = rocker_cmd_exec(rocker_port, trans_ph, flags, rocker_cmd_flow_tbl_del, found, NULL, NULL); - rocker_port_kfree(trans, found); + rocker_port_kfree(trans_ph, found); } return err; } static int rocker_flow_tbl_do(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, struct rocker_flow_tbl_entry *entry) { if (flags & ROCKER_OP_FLAG_REMOVE) - return rocker_flow_tbl_del(rocker_port, trans, flags, entry); + return rocker_flow_tbl_del(rocker_port, trans_ph, flags, entry); else - return rocker_flow_tbl_add(rocker_port, trans, flags, entry); + return rocker_flow_tbl_add(rocker_port, trans_ph, flags, entry); } static int rocker_flow_tbl_ig_port(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, u32 in_pport, u32 in_pport_mask, enum rocker_of_dpa_table_id goto_tbl) { struct rocker_flow_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2535,11 +2535,11 @@ static int rocker_flow_tbl_ig_port(struct rocker_port *rocker_port, entry->key.ig_port.in_pport_mask = in_pport_mask; entry->key.ig_port.goto_tbl = goto_tbl; - return rocker_flow_tbl_do(rocker_port, trans, flags, entry); + return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry); } static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, u32 in_pport, __be16 vlan_id, __be16 vlan_id_mask, enum rocker_of_dpa_table_id goto_tbl, @@ -2547,7 +2547,7 @@ static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port, { struct rocker_flow_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2561,11 +2561,11 @@ static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port, entry->key.vlan.untagged = untagged; entry->key.vlan.new_vlan_id = new_vlan_id; - return rocker_flow_tbl_do(rocker_port, trans, flags, entry); + return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry); } static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, u32 in_pport, u32 in_pport_mask, __be16 eth_type, const u8 *eth_dst, const u8 *eth_dst_mask, __be16 vlan_id, @@ -2574,7 +2574,7 @@ static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port, { struct rocker_flow_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2598,11 +2598,11 @@ static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port, entry->key.term_mac.vlan_id_mask = vlan_id_mask; entry->key.term_mac.copy_to_cpu = copy_to_cpu; - return rocker_flow_tbl_do(rocker_port, trans, flags, entry); + return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry); } static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, const u8 *eth_dst, const u8 *eth_dst_mask, __be16 vlan_id, u32 tunnel_id, enum rocker_of_dpa_table_id goto_tbl, @@ -2614,7 +2614,7 @@ static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port, bool dflt = !eth_dst || (eth_dst && eth_dst_mask); bool wild = false; - entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2652,11 +2652,11 @@ static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port, entry->key.bridge.group_id = group_id; entry->key.bridge.copy_to_cpu = copy_to_cpu; - return rocker_flow_tbl_do(rocker_port, trans, flags, entry); + return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry); } static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, __be16 eth_type, __be32 dst, __be32 dst_mask, u32 priority, enum rocker_of_dpa_table_id goto_tbl, @@ -2664,7 +2664,7 @@ static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port, { struct rocker_flow_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2678,11 +2678,11 @@ static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port, entry->key_len = offsetof(struct rocker_flow_tbl_key, ucast_routing.group_id); - return rocker_flow_tbl_do(rocker_port, trans, flags, entry); + return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry); } static int rocker_flow_tbl_acl(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, u32 in_pport, u32 in_pport_mask, const u8 *eth_src, const u8 *eth_src_mask, const u8 *eth_dst, const u8 *eth_dst_mask, @@ -2694,7 +2694,7 @@ static int rocker_flow_tbl_acl(struct rocker_port *rocker_port, u32 priority; struct rocker_flow_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2729,7 +2729,7 @@ static int rocker_flow_tbl_acl(struct rocker_port *rocker_port, entry->key.acl.ip_tos_mask = ip_tos_mask; entry->key.acl.group_id = group_id; - return rocker_flow_tbl_do(rocker_port, trans, flags, entry); + return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry); } static struct rocker_group_tbl_entry * @@ -2747,22 +2747,22 @@ rocker_group_tbl_find(const struct rocker *rocker, return NULL; } -static void rocker_group_tbl_entry_free(enum switchdev_trans trans, +static void rocker_group_tbl_entry_free(enum switchdev_trans_ph trans_ph, struct rocker_group_tbl_entry *entry) { switch (ROCKER_GROUP_TYPE_GET(entry->group_id)) { case ROCKER_OF_DPA_GROUP_TYPE_L2_FLOOD: case ROCKER_OF_DPA_GROUP_TYPE_L2_MCAST: - rocker_port_kfree(trans, entry->group_ids); + rocker_port_kfree(trans_ph, entry->group_ids); break; default: break; } - rocker_port_kfree(trans, entry); + rocker_port_kfree(trans_ph, entry); } static int rocker_group_tbl_add(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, struct rocker_group_tbl_entry *match) { struct rocker *rocker = rocker_port->rocker; @@ -2774,9 +2774,9 @@ static int rocker_group_tbl_add(struct rocker_port *rocker_port, found = rocker_group_tbl_find(rocker, match); if (found) { - if (trans != SWITCHDEV_TRANS_PREPARE) + if (trans_ph != SWITCHDEV_TRANS_PREPARE) hash_del(&found->entry); - rocker_group_tbl_entry_free(trans, found); + rocker_group_tbl_entry_free(trans_ph, found); found = match; found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_MOD; } else { @@ -2784,17 +2784,17 @@ static int rocker_group_tbl_add(struct rocker_port *rocker_port, found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_ADD; } - if (trans != SWITCHDEV_TRANS_PREPARE) + if (trans_ph != SWITCHDEV_TRANS_PREPARE) hash_add(rocker->group_tbl, &found->entry, found->group_id); spin_unlock_irqrestore(&rocker->group_tbl_lock, lock_flags); - return rocker_cmd_exec(rocker_port, trans, flags, + return rocker_cmd_exec(rocker_port, trans_ph, flags, rocker_cmd_group_tbl_add, found, NULL, NULL); } static int rocker_group_tbl_del(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, struct rocker_group_tbl_entry *match) { struct rocker *rocker = rocker_port->rocker; @@ -2807,95 +2807,95 @@ static int rocker_group_tbl_del(struct rocker_port *rocker_port, found = rocker_group_tbl_find(rocker, match); if (found) { - if (trans != SWITCHDEV_TRANS_PREPARE) + if (trans_ph != SWITCHDEV_TRANS_PREPARE) hash_del(&found->entry); found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_DEL; } spin_unlock_irqrestore(&rocker->group_tbl_lock, lock_flags); - rocker_group_tbl_entry_free(trans, match); + rocker_group_tbl_entry_free(trans_ph, match); if (found) { - err = rocker_cmd_exec(rocker_port, trans, flags, + err = rocker_cmd_exec(rocker_port, trans_ph, flags, rocker_cmd_group_tbl_del, found, NULL, NULL); - rocker_group_tbl_entry_free(trans, found); + rocker_group_tbl_entry_free(trans_ph, found); } return err; } static int rocker_group_tbl_do(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, struct rocker_group_tbl_entry *entry) { if (flags & ROCKER_OP_FLAG_REMOVE) - return rocker_group_tbl_del(rocker_port, trans, flags, entry); + return rocker_group_tbl_del(rocker_port, trans_ph, flags, entry); else - return rocker_group_tbl_add(rocker_port, trans, flags, entry); + return rocker_group_tbl_add(rocker_port, trans_ph, flags, entry); } static int rocker_group_l2_interface(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, __be16 vlan_id, u32 out_pport, int pop_vlan) { struct rocker_group_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); if (!entry) return -ENOMEM; entry->group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport); entry->l2_interface.pop_vlan = pop_vlan; - return rocker_group_tbl_do(rocker_port, trans, flags, entry); + return rocker_group_tbl_do(rocker_port, trans_ph, flags, entry); } static int rocker_group_l2_fan_out(struct rocker_port *rocker_port, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, int flags, u8 group_count, const u32 *group_ids, u32 group_id) { struct rocker_group_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); if (!entry) return -ENOMEM; entry->group_id = group_id; entry->group_count = group_count; - entry->group_ids = rocker_port_kcalloc(rocker_port, trans, flags, + entry->group_ids = rocker_port_kcalloc(rocker_port, trans_ph, flags, group_count, sizeof(u32)); if (!entry->group_ids) { - rocker_port_kfree(trans, entry); + rocker_port_kfree(trans_ph, entry); return -ENOMEM; } memcpy(entry->group_ids, group_ids, group_count * sizeof(u32)); - return rocker_group_tbl_do(rocker_port, trans, flags, entry); + return rocker_group_tbl_do(rocker_port, trans_ph, flags, entry); } static int rocker_group_l2_flood(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, __be16 vlan_id, u8 group_count, const u32 *group_ids, u32 group_id) { - return rocker_group_l2_fan_out(rocker_port, trans, flags, + return rocker_group_l2_fan_out(rocker_port, trans_ph, flags, group_count, group_ids, group_id); } static int rocker_group_l3_unicast(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, u32 index, const u8 *src_mac, const u8 *dst_mac, __be16 vlan_id, bool ttl_check, u32 pport) { struct rocker_group_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2908,7 +2908,7 @@ static int rocker_group_l3_unicast(struct rocker_port *rocker_port, entry->l3_unicast.ttl_check = ttl_check; entry->l3_unicast.group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, pport); - return rocker_group_tbl_do(rocker_port, trans, flags, entry); + return rocker_group_tbl_do(rocker_port, trans_ph, flags, entry); } static struct rocker_neigh_tbl_entry * @@ -2925,43 +2925,43 @@ rocker_neigh_tbl_find(const struct rocker *rocker, __be32 ip_addr) } static void _rocker_neigh_add(struct rocker *rocker, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, struct rocker_neigh_tbl_entry *entry) { - if (trans != SWITCHDEV_TRANS_COMMIT) + if (trans_ph != SWITCHDEV_TRANS_COMMIT) entry->index = rocker->neigh_tbl_next_index++; - if (trans == SWITCHDEV_TRANS_PREPARE) + if (trans_ph == SWITCHDEV_TRANS_PREPARE) return; entry->ref_count++; hash_add(rocker->neigh_tbl, &entry->entry, be32_to_cpu(entry->ip_addr)); } -static void _rocker_neigh_del(enum switchdev_trans trans, +static void _rocker_neigh_del(enum switchdev_trans_ph trans_ph, struct rocker_neigh_tbl_entry *entry) { - if (trans == SWITCHDEV_TRANS_PREPARE) + if (trans_ph == SWITCHDEV_TRANS_PREPARE) return; if (--entry->ref_count == 0) { hash_del(&entry->entry); - rocker_port_kfree(trans, entry); + rocker_port_kfree(trans_ph, entry); } } static void _rocker_neigh_update(struct rocker_neigh_tbl_entry *entry, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, const u8 *eth_dst, bool ttl_check) { if (eth_dst) { ether_addr_copy(entry->eth_dst, eth_dst); entry->ttl_check = ttl_check; - } else if (trans != SWITCHDEV_TRANS_PREPARE) { + } else if (trans_ph != SWITCHDEV_TRANS_PREPARE) { entry->ref_count++; } } static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, int flags, __be32 ip_addr, const u8 *eth_dst) { struct rocker *rocker = rocker_port->rocker; @@ -2978,7 +2978,7 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port, bool removing; int err = 0; - entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2995,12 +2995,12 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port, entry->dev = rocker_port->dev; ether_addr_copy(entry->eth_dst, eth_dst); entry->ttl_check = true; - _rocker_neigh_add(rocker, trans, entry); + _rocker_neigh_add(rocker, trans_ph, entry); } else if (removing) { memcpy(entry, found, sizeof(*entry)); - _rocker_neigh_del(trans, found); + _rocker_neigh_del(trans_ph, found); } else if (updating) { - _rocker_neigh_update(found, trans, eth_dst, true); + _rocker_neigh_update(found, trans_ph, eth_dst, true); memcpy(entry, found, sizeof(*entry)); } else { err = -ENOENT; @@ -3017,7 +3017,7 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port, * other routes' nexthops. */ - err = rocker_group_l3_unicast(rocker_port, trans, flags, + err = rocker_group_l3_unicast(rocker_port, trans_ph, flags, entry->index, rocker_port->dev->dev_addr, entry->eth_dst, @@ -3033,7 +3033,7 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port, if (adding || removing) { group_id = ROCKER_GROUP_L3_UNICAST(entry->index); - err = rocker_flow_tbl_ucast4_routing(rocker_port, trans, + err = rocker_flow_tbl_ucast4_routing(rocker_port, trans_ph, eth_type, ip_addr, inet_make_mask(32), priority, goto_tbl, @@ -3047,13 +3047,13 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port, err_out: if (!adding) - rocker_port_kfree(trans, entry); + rocker_port_kfree(trans_ph, entry); return err; } static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port, - enum switchdev_trans trans, __be32 ip_addr) + enum switchdev_trans_ph trans_ph, __be32 ip_addr) { struct net_device *dev = rocker_port->dev; struct neighbour *n = __ipv4_neigh_lookup(dev, (__force u32)ip_addr); @@ -3071,7 +3071,7 @@ static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port, */ if (n->nud_state & NUD_VALID) - err = rocker_port_ipv4_neigh(rocker_port, trans, 0, + err = rocker_port_ipv4_neigh(rocker_port, trans_ph, 0, ip_addr, n->ha); else neigh_event_send(n, NULL); @@ -3081,7 +3081,7 @@ static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port, } static int rocker_port_ipv4_nh(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, __be32 ip_addr, u32 *index) { struct rocker *rocker = rocker_port->rocker; @@ -3094,7 +3094,7 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port, bool resolved = true; int err = 0; - entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -3111,13 +3111,13 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port, if (adding) { entry->ip_addr = ip_addr; entry->dev = rocker_port->dev; - _rocker_neigh_add(rocker, trans, entry); + _rocker_neigh_add(rocker, trans_ph, entry); *index = entry->index; resolved = false; } else if (removing) { - _rocker_neigh_del(trans, found); + _rocker_neigh_del(trans_ph, found); } else if (updating) { - _rocker_neigh_update(found, trans, NULL, false); + _rocker_neigh_update(found, trans_ph, NULL, false); resolved = !is_zero_ether_addr(found->eth_dst); } else { err = -ENOENT; @@ -3126,7 +3126,7 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port, spin_unlock_irqrestore(&rocker->neigh_tbl_lock, lock_flags); if (!adding) - rocker_port_kfree(trans, entry); + rocker_port_kfree(trans_ph, entry); if (err) return err; @@ -3134,13 +3134,13 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port, /* Resolved means neigh ip_addr is resolved to neigh mac. */ if (!resolved) - err = rocker_port_ipv4_resolve(rocker_port, trans, ip_addr); + err = rocker_port_ipv4_resolve(rocker_port, trans_ph, ip_addr); return err; } static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, int flags, __be16 vlan_id) { struct rocker_port *p; @@ -3151,7 +3151,7 @@ static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port, int err = 0; int i; - group_ids = rocker_port_kcalloc(rocker_port, trans, flags, + group_ids = rocker_port_kcalloc(rocker_port, trans_ph, flags, rocker->port_count, sizeof(u32)); if (!group_ids) return -ENOMEM; @@ -3177,19 +3177,19 @@ static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port, if (group_count == 0) goto no_ports_in_vlan; - err = rocker_group_l2_flood(rocker_port, trans, flags, vlan_id, + err = rocker_group_l2_flood(rocker_port, trans_ph, flags, vlan_id, group_count, group_ids, group_id); if (err) netdev_err(rocker_port->dev, "Error (%d) port VLAN l2 flood group\n", err); no_ports_in_vlan: - rocker_port_kfree(trans, group_ids); + rocker_port_kfree(trans_ph, group_ids); return err; } static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, __be16 vlan_id, bool pop_vlan) { const struct rocker *rocker = rocker_port->rocker; @@ -3207,7 +3207,7 @@ static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port, if (rocker_port->stp_state == BR_STATE_LEARNING || rocker_port->stp_state == BR_STATE_FORWARDING) { out_pport = rocker_port->pport; - err = rocker_group_l2_interface(rocker_port, trans, flags, + err = rocker_group_l2_interface(rocker_port, trans_ph, flags, vlan_id, out_pport, pop_vlan); if (err) { netdev_err(rocker_port->dev, @@ -3232,7 +3232,7 @@ static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port, return 0; out_pport = 0; - err = rocker_group_l2_interface(rocker_port, trans, flags, + err = rocker_group_l2_interface(rocker_port, trans_ph, flags, vlan_id, out_pport, pop_vlan); if (err) { netdev_err(rocker_port->dev, @@ -3295,7 +3295,7 @@ static struct rocker_ctrl { }; static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, const struct rocker_ctrl *ctrl, __be16 vlan_id) { u32 in_pport = rocker_port->pport; @@ -3311,7 +3311,7 @@ static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port, u32 group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport); int err; - err = rocker_flow_tbl_acl(rocker_port, trans, flags, + err = rocker_flow_tbl_acl(rocker_port, trans_ph, flags, in_pport, in_pport_mask, eth_src, eth_src_mask, ctrl->eth_dst, ctrl->eth_dst_mask, @@ -3328,7 +3328,7 @@ static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port, } static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, const struct rocker_ctrl *ctrl, __be16 vlan_id) { @@ -3341,7 +3341,7 @@ static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port, if (!rocker_port_is_bridged(rocker_port)) return 0; - err = rocker_flow_tbl_bridge(rocker_port, trans, flags, + err = rocker_flow_tbl_bridge(rocker_port, trans_ph, flags, ctrl->eth_dst, ctrl->eth_dst_mask, vlan_id, tunnel_id, goto_tbl, group_id, ctrl->copy_to_cpu); @@ -3353,7 +3353,7 @@ static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port, } static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, const struct rocker_ctrl *ctrl, __be16 vlan_id) { u32 in_pport_mask = 0xffffffff; @@ -3363,7 +3363,7 @@ static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port, if (ntohs(vlan_id) == 0) vlan_id = rocker_port->internal_vlan_id; - err = rocker_flow_tbl_term_mac(rocker_port, trans, + err = rocker_flow_tbl_term_mac(rocker_port, trans_ph, rocker_port->pport, in_pport_mask, ctrl->eth_type, ctrl->eth_dst, ctrl->eth_dst_mask, vlan_id, @@ -3377,25 +3377,25 @@ static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port, } static int rocker_port_ctrl_vlan(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, const struct rocker_ctrl *ctrl, __be16 vlan_id) { if (ctrl->acl) - return rocker_port_ctrl_vlan_acl(rocker_port, trans, flags, + return rocker_port_ctrl_vlan_acl(rocker_port, trans_ph, flags, ctrl, vlan_id); if (ctrl->bridge) - return rocker_port_ctrl_vlan_bridge(rocker_port, trans, flags, + return rocker_port_ctrl_vlan_bridge(rocker_port, trans_ph, flags, ctrl, vlan_id); if (ctrl->term) - return rocker_port_ctrl_vlan_term(rocker_port, trans, flags, + return rocker_port_ctrl_vlan_term(rocker_port, trans_ph, flags, ctrl, vlan_id); return -EOPNOTSUPP; } static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, __be16 vlan_id) { int err = 0; @@ -3403,7 +3403,7 @@ static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port, for (i = 0; i < ROCKER_CTRL_MAX; i++) { if (rocker_port->ctrls[i]) { - err = rocker_port_ctrl_vlan(rocker_port, trans, flags, + err = rocker_port_ctrl_vlan(rocker_port, trans_ph, flags, &rocker_ctrls[i], vlan_id); if (err) return err; @@ -3414,7 +3414,7 @@ static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port, } static int rocker_port_ctrl(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, const struct rocker_ctrl *ctrl) { u16 vid; @@ -3423,7 +3423,7 @@ static int rocker_port_ctrl(struct rocker_port *rocker_port, for (vid = 1; vid < VLAN_N_VID; vid++) { if (!test_bit(vid, rocker_port->vlan_bitmap)) continue; - err = rocker_port_ctrl_vlan(rocker_port, trans, flags, + err = rocker_port_ctrl_vlan(rocker_port, trans_ph, flags, ctrl, htons(vid)); if (err) break; @@ -3433,7 +3433,7 @@ static int rocker_port_ctrl(struct rocker_port *rocker_port, } static int rocker_port_vlan(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, u16 vid) + enum switchdev_trans_ph trans_ph, int flags, u16 vid) { enum rocker_of_dpa_table_id goto_tbl = ROCKER_OF_DPA_TABLE_ID_TERMINATION_MAC; @@ -3457,7 +3457,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port, change_bit(ntohs(internal_vlan_id), rocker_port->vlan_bitmap); if (adding) { - err = rocker_port_ctrl_vlan_add(rocker_port, trans, flags, + err = rocker_port_ctrl_vlan_add(rocker_port, trans_ph, flags, internal_vlan_id); if (err) { netdev_err(rocker_port->dev, @@ -3466,7 +3466,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port, } } - err = rocker_port_vlan_l2_groups(rocker_port, trans, flags, + err = rocker_port_vlan_l2_groups(rocker_port, trans_ph, flags, internal_vlan_id, untagged); if (err) { netdev_err(rocker_port->dev, @@ -3474,7 +3474,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port, goto err_out; } - err = rocker_port_vlan_flood_group(rocker_port, trans, flags, + err = rocker_port_vlan_flood_group(rocker_port, trans_ph, flags, internal_vlan_id); if (err) { netdev_err(rocker_port->dev, @@ -3482,7 +3482,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port, goto err_out; } - err = rocker_flow_tbl_vlan(rocker_port, trans, flags, + err = rocker_flow_tbl_vlan(rocker_port, trans_ph, flags, in_pport, vlan_id, vlan_id_mask, goto_tbl, untagged, internal_vlan_id); if (err) @@ -3490,14 +3490,14 @@ static int rocker_port_vlan(struct rocker_port *rocker_port, "Error (%d) port VLAN table\n", err); err_out: - if (trans == SWITCHDEV_TRANS_PREPARE) + if (trans_ph == SWITCHDEV_TRANS_PREPARE) change_bit(ntohs(internal_vlan_id), rocker_port->vlan_bitmap); return err; } static int rocker_port_ig_tbl(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags) + enum switchdev_trans_ph trans_ph, int flags) { enum rocker_of_dpa_table_id goto_tbl; u32 in_pport; @@ -3512,7 +3512,7 @@ static int rocker_port_ig_tbl(struct rocker_port *rocker_port, in_pport_mask = 0xffff0000; goto_tbl = ROCKER_OF_DPA_TABLE_ID_VLAN; - err = rocker_flow_tbl_ig_port(rocker_port, trans, flags, + err = rocker_flow_tbl_ig_port(rocker_port, trans_ph, flags, in_pport, in_pport_mask, goto_tbl); if (err) @@ -3525,7 +3525,7 @@ static int rocker_port_ig_tbl(struct rocker_port *rocker_port, struct rocker_fdb_learn_work { struct work_struct work; struct rocker_port *rocker_port; - enum switchdev_trans trans; + enum switchdev_trans_ph trans_ph; int flags; u8 addr[ETH_ALEN]; u16 vid; @@ -3549,11 +3549,11 @@ static void rocker_port_fdb_learn_work(struct work_struct *work) call_switchdev_notifiers(SWITCHDEV_FDB_ADD, lw->rocker_port->dev, &info.info); - rocker_port_kfree(lw->trans, work); + rocker_port_kfree(lw->trans_ph, work); } static int rocker_port_fdb_learn(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, const u8 *addr, __be16 vlan_id) { struct rocker_fdb_learn_work *lw; @@ -3570,7 +3570,7 @@ static int rocker_port_fdb_learn(struct rocker_port *rocker_port, group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport); if (!(flags & ROCKER_OP_FLAG_REFRESH)) { - err = rocker_flow_tbl_bridge(rocker_port, trans, flags, addr, + err = rocker_flow_tbl_bridge(rocker_port, trans_ph, flags, addr, NULL, vlan_id, tunnel_id, goto_tbl, group_id, copy_to_cpu); if (err) @@ -3583,20 +3583,20 @@ static int rocker_port_fdb_learn(struct rocker_port *rocker_port, if (!rocker_port_is_bridged(rocker_port)) return 0; - lw = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*lw)); + lw = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*lw)); if (!lw) return -ENOMEM; INIT_WORK(&lw->work, rocker_port_fdb_learn_work); lw->rocker_port = rocker_port; - lw->trans = trans; + lw->trans_ph = trans_ph; lw->flags = flags; ether_addr_copy(lw->addr, addr); lw->vid = rocker_port_vlan_to_vid(rocker_port, vlan_id); - if (trans == SWITCHDEV_TRANS_PREPARE) - rocker_port_kfree(trans, lw); + if (trans_ph == SWITCHDEV_TRANS_PREPARE) + rocker_port_kfree(trans_ph, lw); else schedule_work(&lw->work); @@ -3617,7 +3617,7 @@ rocker_fdb_tbl_find(const struct rocker *rocker, } static int rocker_port_fdb(struct rocker_port *rocker_port, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, const unsigned char *addr, __be16 vlan_id, int flags) { @@ -3627,7 +3627,7 @@ static int rocker_port_fdb(struct rocker_port *rocker_port, bool removing = (flags & ROCKER_OP_FLAG_REMOVE); unsigned long lock_flags; - fdb = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*fdb)); + fdb = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*fdb)); if (!fdb) return -ENOMEM; @@ -3645,12 +3645,12 @@ static int rocker_port_fdb(struct rocker_port *rocker_port, if (found) { found->touched = jiffies; if (removing) { - rocker_port_kfree(trans, fdb); - if (trans != SWITCHDEV_TRANS_PREPARE) + rocker_port_kfree(trans_ph, fdb); + if (trans_ph != SWITCHDEV_TRANS_PREPARE) hash_del(&found->entry); } } else if (!removing) { - if (trans != SWITCHDEV_TRANS_PREPARE) + if (trans_ph != SWITCHDEV_TRANS_PREPARE) hash_add(rocker->fdb_tbl, &fdb->entry, fdb->key_crc32); } @@ -3659,18 +3659,18 @@ static int rocker_port_fdb(struct rocker_port *rocker_port, /* Check if adding and already exists, or removing and can't find */ if (!found != !removing) { - rocker_port_kfree(trans, fdb); + rocker_port_kfree(trans_ph, fdb); if (!found && removing) return 0; /* Refreshing existing to update aging timers */ flags |= ROCKER_OP_FLAG_REFRESH; } - return rocker_port_fdb_learn(rocker_port, trans, flags, addr, vlan_id); + return rocker_port_fdb_learn(rocker_port, trans_ph, flags, addr, vlan_id); } static int rocker_port_fdb_flush(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags) + enum switchdev_trans_ph trans_ph, int flags) { struct rocker *rocker = rocker_port->rocker; struct rocker_fdb_tbl_entry *found; @@ -3692,12 +3692,12 @@ static int rocker_port_fdb_flush(struct rocker_port *rocker_port, continue; if (!found->learned) continue; - err = rocker_port_fdb_learn(rocker_port, trans, flags, + err = rocker_port_fdb_learn(rocker_port, trans_ph, flags, found->key.addr, found->key.vlan_id); if (err) goto err_out; - if (trans != SWITCHDEV_TRANS_PREPARE) + if (trans_ph != SWITCHDEV_TRANS_PREPARE) hash_del(&found->entry); } @@ -3743,7 +3743,7 @@ static void rocker_fdb_cleanup(unsigned long data) } static int rocker_port_router_mac(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, __be16 vlan_id) { u32 in_pport_mask = 0xffffffff; @@ -3757,7 +3757,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port, vlan_id = rocker_port->internal_vlan_id; eth_type = htons(ETH_P_IP); - err = rocker_flow_tbl_term_mac(rocker_port, trans, + err = rocker_flow_tbl_term_mac(rocker_port, trans_ph, rocker_port->pport, in_pport_mask, eth_type, rocker_port->dev->dev_addr, dst_mac_mask, vlan_id, vlan_id_mask, @@ -3766,7 +3766,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port, return err; eth_type = htons(ETH_P_IPV6); - err = rocker_flow_tbl_term_mac(rocker_port, trans, + err = rocker_flow_tbl_term_mac(rocker_port, trans_ph, rocker_port->pport, in_pport_mask, eth_type, rocker_port->dev->dev_addr, dst_mac_mask, vlan_id, vlan_id_mask, @@ -3776,7 +3776,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port, } static int rocker_port_fwding(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags) + enum switchdev_trans_ph trans_ph, int flags) { bool pop_vlan; u32 out_pport; @@ -3801,7 +3801,7 @@ static int rocker_port_fwding(struct rocker_port *rocker_port, continue; vlan_id = htons(vid); pop_vlan = rocker_vlan_id_is_internal(vlan_id); - err = rocker_group_l2_interface(rocker_port, trans, flags, + err = rocker_group_l2_interface(rocker_port, trans_ph, flags, vlan_id, out_pport, pop_vlan); if (err) { netdev_err(rocker_port->dev, @@ -3815,7 +3815,7 @@ static int rocker_port_fwding(struct rocker_port *rocker_port, } static int rocker_port_stp_update(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags, + enum switchdev_trans_ph trans_ph, int flags, u8 state) { bool want[ROCKER_CTRL_MAX] = { 0, }; @@ -3824,7 +3824,7 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port, int err; int i; - if (trans == SWITCHDEV_TRANS_PREPARE) { + if (trans_ph == SWITCHDEV_TRANS_PREPARE) { memcpy(prev_ctrls, rocker_port->ctrls, sizeof(prev_ctrls)); prev_state = rocker_port->stp_state; } @@ -3861,7 +3861,7 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port, if (want[i] != rocker_port->ctrls[i]) { int ctrl_flags = flags | (want[i] ? 0 : ROCKER_OP_FLAG_REMOVE); - err = rocker_port_ctrl(rocker_port, trans, ctrl_flags, + err = rocker_port_ctrl(rocker_port, trans_ph, ctrl_flags, &rocker_ctrls[i]); if (err) goto err_out; @@ -3869,14 +3869,14 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port, } } - err = rocker_port_fdb_flush(rocker_port, trans, flags); + err = rocker_port_fdb_flush(rocker_port, trans_ph, flags); if (err) goto err_out; - err = rocker_port_fwding(rocker_port, trans, flags); + err = rocker_port_fwding(rocker_port, trans_ph, flags); err_out: - if (trans == SWITCHDEV_TRANS_PREPARE) { + if (trans_ph == SWITCHDEV_TRANS_PREPARE) { memcpy(rocker_port->ctrls, prev_ctrls, sizeof(prev_ctrls)); rocker_port->stp_state = prev_state; } @@ -3885,26 +3885,26 @@ err_out: } static int rocker_port_fwd_enable(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags) + enum switchdev_trans_ph trans_ph, int flags) { if (rocker_port_is_bridged(rocker_port)) /* bridge STP will enable port */ return 0; /* port is not bridged, so simulate going to FORWARDING state */ - return rocker_port_stp_update(rocker_port, trans, flags, + return rocker_port_stp_update(rocker_port, trans_ph, flags, BR_STATE_FORWARDING); } static int rocker_port_fwd_disable(struct rocker_port *rocker_port, - enum switchdev_trans trans, int flags) + enum switchdev_trans_ph trans_ph, int flags) { if (rocker_port_is_bridged(rocker_port)) /* bridge STP will disable port */ return 0; /* port is not bridged, so simulate going to DISABLED state */ - return rocker_port_stp_update(rocker_port, trans, flags, + return rocker_port_stp_update(rocker_port, trans_ph, flags, BR_STATE_DISABLED); } @@ -3995,7 +3995,7 @@ not_found: } static int rocker_port_fib_ipv4(struct rocker_port *rocker_port, - enum switchdev_trans trans, __be32 dst, + enum switchdev_trans_ph trans_ph, __be32 dst, int dst_len, const struct fib_info *fi, u32 tb_id, int flags) { @@ -4019,7 +4019,7 @@ static int rocker_port_fib_ipv4(struct rocker_port *rocker_port, has_gw = !!nh->nh_gw; if (has_gw && nh_on_port) { - err = rocker_port_ipv4_nh(rocker_port, trans, flags, + err = rocker_port_ipv4_nh(rocker_port, trans_ph, flags, nh->nh_gw, &index); if (err) return err; @@ -4030,7 +4030,7 @@ static int rocker_port_fib_ipv4(struct rocker_port *rocker_port, group_id = ROCKER_GROUP_L2_INTERFACE(internal_vlan_id, 0); } - err = rocker_flow_tbl_ucast4_routing(rocker_port, trans, eth_type, dst, + err = rocker_flow_tbl_ucast4_routing(rocker_port, trans_ph, eth_type, dst, dst_mask, priority, goto_tbl, group_id, flags); if (err) @@ -4365,7 +4365,7 @@ static void rocker_port_trans_abort(const struct rocker_port *rocker_port) } static int rocker_port_brport_flags_set(struct rocker_port *rocker_port, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, unsigned long brport_flags) { unsigned long orig_flags; @@ -4374,9 +4374,9 @@ static int rocker_port_brport_flags_set(struct rocker_port *rocker_port, orig_flags = rocker_port->brport_flags; rocker_port->brport_flags = brport_flags; if ((orig_flags ^ rocker_port->brport_flags) & BR_LEARNING) - err = rocker_port_set_learning(rocker_port, trans); + err = rocker_port_set_learning(rocker_port, trans_ph); - if (trans == SWITCHDEV_TRANS_PREPARE) + if (trans_ph == SWITCHDEV_TRANS_PREPARE) rocker_port->brport_flags = orig_flags; return err; @@ -4388,7 +4388,7 @@ static int rocker_port_attr_set(struct net_device *dev, struct rocker_port *rocker_port = netdev_priv(dev); int err = 0; - switch (attr->trans) { + switch (attr->trans_ph) { case SWITCHDEV_TRANS_PREPARE: BUG_ON(!list_empty(&rocker_port->trans_mem)); break; @@ -4401,12 +4401,12 @@ static int rocker_port_attr_set(struct net_device *dev, switch (attr->id) { case SWITCHDEV_ATTR_PORT_STP_STATE: - err = rocker_port_stp_update(rocker_port, attr->trans, + err = rocker_port_stp_update(rocker_port, attr->trans_ph, ROCKER_OP_FLAG_NOWAIT, attr->u.stp_state); break; case SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS: - err = rocker_port_brport_flags_set(rocker_port, attr->trans, + err = rocker_port_brport_flags_set(rocker_port, attr->trans_ph, attr->u.brport_flags); break; default: @@ -4418,33 +4418,33 @@ static int rocker_port_attr_set(struct net_device *dev, } static int rocker_port_vlan_add(struct rocker_port *rocker_port, - enum switchdev_trans trans, u16 vid, u16 flags) + enum switchdev_trans_ph trans_ph, u16 vid, u16 flags) { int err; /* XXX deal with flags for PVID and untagged */ - err = rocker_port_vlan(rocker_port, trans, 0, vid); + err = rocker_port_vlan(rocker_port, trans_ph, 0, vid); if (err) return err; - err = rocker_port_router_mac(rocker_port, trans, 0, htons(vid)); + err = rocker_port_router_mac(rocker_port, trans_ph, 0, htons(vid)); if (err) - rocker_port_vlan(rocker_port, trans, + rocker_port_vlan(rocker_port, trans_ph, ROCKER_OP_FLAG_REMOVE, vid); return err; } static int rocker_port_vlans_add(struct rocker_port *rocker_port, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, const struct switchdev_obj_vlan *vlan) { u16 vid; int err; for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { - err = rocker_port_vlan_add(rocker_port, trans, + err = rocker_port_vlan_add(rocker_port, trans_ph, vid, vlan->flags); if (err) return err; @@ -4454,7 +4454,7 @@ static int rocker_port_vlans_add(struct rocker_port *rocker_port, } static int rocker_port_fdb_add(struct rocker_port *rocker_port, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, const struct switchdev_obj_fdb *fdb) { __be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL); @@ -4463,7 +4463,7 @@ static int rocker_port_fdb_add(struct rocker_port *rocker_port, if (!rocker_port_is_bridged(rocker_port)) return -EINVAL; - return rocker_port_fdb(rocker_port, trans, fdb->addr, vlan_id, flags); + return rocker_port_fdb(rocker_port, trans_ph, fdb->addr, vlan_id, flags); } static int rocker_port_obj_add(struct net_device *dev, @@ -4473,7 +4473,7 @@ static int rocker_port_obj_add(struct net_device *dev, const struct switchdev_obj_ipv4_fib *fib4; int err = 0; - switch (obj->trans) { + switch (obj->trans_ph) { case SWITCHDEV_TRANS_PREPARE: BUG_ON(!list_empty(&rocker_port->trans_mem)); break; @@ -4486,17 +4486,17 @@ static int rocker_port_obj_add(struct net_device *dev, switch (obj->id) { case SWITCHDEV_OBJ_PORT_VLAN: - err = rocker_port_vlans_add(rocker_port, obj->trans, + err = rocker_port_vlans_add(rocker_port, obj->trans_ph, &obj->u.vlan); break; case SWITCHDEV_OBJ_IPV4_FIB: fib4 = &obj->u.ipv4_fib; - err = rocker_port_fib_ipv4(rocker_port, obj->trans, + err = rocker_port_fib_ipv4(rocker_port, obj->trans_ph, htonl(fib4->dst), fib4->dst_len, fib4->fi, fib4->tb_id, 0); break; case SWITCHDEV_OBJ_PORT_FDB: - err = rocker_port_fdb_add(rocker_port, obj->trans, &obj->u.fdb); + err = rocker_port_fdb_add(rocker_port, obj->trans_ph, &obj->u.fdb); break; default: err = -EOPNOTSUPP; @@ -4536,7 +4536,7 @@ static int rocker_port_vlans_del(struct rocker_port *rocker_port, } static int rocker_port_fdb_del(struct rocker_port *rocker_port, - enum switchdev_trans trans, + enum switchdev_trans_ph trans_ph, const struct switchdev_obj_fdb *fdb) { __be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL); @@ -4545,7 +4545,7 @@ static int rocker_port_fdb_del(struct rocker_port *rocker_port, if (!rocker_port_is_bridged(rocker_port)) return -EINVAL; - return rocker_port_fdb(rocker_port, trans, fdb->addr, vlan_id, flags); + return rocker_port_fdb(rocker_port, trans_ph, fdb->addr, vlan_id, flags); } static int rocker_port_obj_del(struct net_device *dev, @@ -4567,7 +4567,7 @@ static int rocker_port_obj_del(struct net_device *dev, ROCKER_OP_FLAG_REMOVE); break; case SWITCHDEV_OBJ_PORT_FDB: - err = rocker_port_fdb_del(rocker_port, obj->trans, &obj->u.fdb); + err = rocker_port_fdb_del(rocker_port, obj->trans_ph, &obj->u.fdb); break; default: err = -EOPNOTSUPP; -- cgit v1.2.3 From 7ea6eb3f56f45cf4babae8b9a7421868e5005f17 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 24 Sep 2015 10:02:41 +0200 Subject: switchdev: introduce transaction item queue for attr_set and obj_add Now, the memory allocation in prepare/commit state is done separatelly in each driver (rocker). Introduce the similar mechanism in generic switchdev code, in form of queue. That can be used not only for memory allocations, but also for different items. Abort item destruction is handled as well. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index cf03b077311e..dcc6f3fd13c9 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4383,7 +4383,8 @@ static int rocker_port_brport_flags_set(struct rocker_port *rocker_port, } static int rocker_port_attr_set(struct net_device *dev, - struct switchdev_attr *attr) + struct switchdev_attr *attr, + struct switchdev_trans *trans) { struct rocker_port *rocker_port = netdev_priv(dev); int err = 0; @@ -4467,7 +4468,8 @@ static int rocker_port_fdb_add(struct rocker_port *rocker_port, } static int rocker_port_obj_add(struct net_device *dev, - struct switchdev_obj *obj) + struct switchdev_obj *obj, + struct switchdev_trans *trans) { struct rocker_port *rocker_port = netdev_priv(dev); const struct switchdev_obj_ipv4_fib *fib4; -- cgit v1.2.3 From f8db83486e316ff50f97961a82b614985645508e Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 24 Sep 2015 10:02:42 +0200 Subject: switchdev: move transaction phase enum under transaction structure Before it disappears completely, move transaction phase enum under transaction structure and make attr/obj structures a bit cleaner. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index dcc6f3fd13c9..c348f86d9b8d 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4389,7 +4389,7 @@ static int rocker_port_attr_set(struct net_device *dev, struct rocker_port *rocker_port = netdev_priv(dev); int err = 0; - switch (attr->trans_ph) { + switch (trans->ph) { case SWITCHDEV_TRANS_PREPARE: BUG_ON(!list_empty(&rocker_port->trans_mem)); break; @@ -4402,12 +4402,12 @@ static int rocker_port_attr_set(struct net_device *dev, switch (attr->id) { case SWITCHDEV_ATTR_PORT_STP_STATE: - err = rocker_port_stp_update(rocker_port, attr->trans_ph, + err = rocker_port_stp_update(rocker_port, trans->ph, ROCKER_OP_FLAG_NOWAIT, attr->u.stp_state); break; case SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS: - err = rocker_port_brport_flags_set(rocker_port, attr->trans_ph, + err = rocker_port_brport_flags_set(rocker_port, trans->ph, attr->u.brport_flags); break; default: @@ -4475,7 +4475,7 @@ static int rocker_port_obj_add(struct net_device *dev, const struct switchdev_obj_ipv4_fib *fib4; int err = 0; - switch (obj->trans_ph) { + switch (trans->ph) { case SWITCHDEV_TRANS_PREPARE: BUG_ON(!list_empty(&rocker_port->trans_mem)); break; @@ -4488,17 +4488,17 @@ static int rocker_port_obj_add(struct net_device *dev, switch (obj->id) { case SWITCHDEV_OBJ_PORT_VLAN: - err = rocker_port_vlans_add(rocker_port, obj->trans_ph, + err = rocker_port_vlans_add(rocker_port, trans->ph, &obj->u.vlan); break; case SWITCHDEV_OBJ_IPV4_FIB: fib4 = &obj->u.ipv4_fib; - err = rocker_port_fib_ipv4(rocker_port, obj->trans_ph, + err = rocker_port_fib_ipv4(rocker_port, trans->ph, htonl(fib4->dst), fib4->dst_len, fib4->fi, fib4->tb_id, 0); break; case SWITCHDEV_OBJ_PORT_FDB: - err = rocker_port_fdb_add(rocker_port, obj->trans_ph, &obj->u.fdb); + err = rocker_port_fdb_add(rocker_port, trans->ph, &obj->u.fdb); break; default: err = -EOPNOTSUPP; @@ -4569,7 +4569,8 @@ static int rocker_port_obj_del(struct net_device *dev, ROCKER_OP_FLAG_REMOVE); break; case SWITCHDEV_OBJ_PORT_FDB: - err = rocker_port_fdb_del(rocker_port, obj->trans_ph, &obj->u.fdb); + err = rocker_port_fdb_del(rocker_port, SWITCHDEV_TRANS_NONE, + &obj->u.fdb); break; default: err = -EOPNOTSUPP; -- cgit v1.2.3 From 76c6f945cc8ec92918ab5459eaa0958dedbfbcfe Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 24 Sep 2015 10:02:44 +0200 Subject: rocker: push struct switchdev_trans down through rocker code There will be needed to have switchdev_trans available down in the call chain, so propagate it instead of trans phase enum. This enum will be removed anyway. Also, use prepare/commit phase check helpers to get information about current phase of transaction. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 462 +++++++++++++++++------------------ 1 file changed, 225 insertions(+), 237 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index c348f86d9b8d..102b37d95d85 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -343,7 +343,7 @@ static bool rocker_port_is_ovsed(const struct rocker_port *rocker_port) #define ROCKER_OP_FLAG_REFRESH BIT(3) static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, size_t size) { struct list_head *elem = NULL; @@ -359,45 +359,39 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port, * memory used in the commit phase. */ - switch (trans_ph) { - case SWITCHDEV_TRANS_PREPARE: + if (!trans) { + elem = kzalloc(size + sizeof(*elem), gfp_flags); + if (elem) + INIT_LIST_HEAD(elem); + } else if (switchdev_trans_ph_prepare(trans)) { elem = kzalloc(size + sizeof(*elem), gfp_flags); if (!elem) return NULL; list_add_tail(elem, &rocker_port->trans_mem); - break; - case SWITCHDEV_TRANS_COMMIT: + } else { BUG_ON(list_empty(&rocker_port->trans_mem)); elem = rocker_port->trans_mem.next; list_del_init(elem); - break; - case SWITCHDEV_TRANS_NONE: - elem = kzalloc(size + sizeof(*elem), gfp_flags); - if (elem) - INIT_LIST_HEAD(elem); - break; - default: - break; } return elem ? elem + 1 : NULL; } static void *rocker_port_kzalloc(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, size_t size) { - return __rocker_port_mem_alloc(rocker_port, trans_ph, flags, size); + return __rocker_port_mem_alloc(rocker_port, trans, flags, size); } static void *rocker_port_kcalloc(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, size_t n, size_t size) { - return __rocker_port_mem_alloc(rocker_port, trans_ph, flags, n * size); + return __rocker_port_mem_alloc(rocker_port, trans, flags, n * size); } -static void rocker_port_kfree(enum switchdev_trans_ph trans_ph, const void *mem) +static void rocker_port_kfree(struct switchdev_trans *trans, const void *mem) { struct list_head *elem; @@ -406,7 +400,7 @@ static void rocker_port_kfree(enum switchdev_trans_ph trans_ph, const void *mem) * commit phase. */ - if (trans_ph == SWITCHDEV_TRANS_PREPARE) + if (switchdev_trans_ph_prepare(trans)) return; elem = (struct list_head *)mem - 1; @@ -433,22 +427,22 @@ static void rocker_wait_init(struct rocker_wait *wait) } static struct rocker_wait *rocker_wait_create(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, int flags) { struct rocker_wait *wait; - wait = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*wait)); + wait = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*wait)); if (!wait) return NULL; rocker_wait_init(wait); return wait; } -static void rocker_wait_destroy(enum switchdev_trans_ph trans_ph, +static void rocker_wait_destroy(struct switchdev_trans *trans, struct rocker_wait *wait) { - rocker_port_kfree(trans_ph, wait); + rocker_port_kfree(trans, wait); } static bool rocker_wait_event_timeout(struct rocker_wait *wait, @@ -1411,7 +1405,7 @@ static irqreturn_t rocker_cmd_irq_handler(int irq, void *dev_id) wait = rocker_desc_cookie_ptr_get(desc_info); if (wait->nowait) { rocker_desc_gen_clear(desc_info); - rocker_wait_destroy(SWITCHDEV_TRANS_NONE, wait); + rocker_wait_destroy(NULL, wait); } else { rocker_wait_wake_up(wait); } @@ -1466,7 +1460,7 @@ static int rocker_event_link_change(const struct rocker *rocker, } static int rocker_port_fdb(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, const unsigned char *addr, __be16 vlan_id, int flags); @@ -1499,8 +1493,7 @@ static int rocker_event_mac_vlan_seen(const struct rocker *rocker, rocker_port->stp_state != BR_STATE_FORWARDING) return 0; - return rocker_port_fdb(rocker_port, SWITCHDEV_TRANS_NONE, - addr, vlan_id, flags); + return rocker_port_fdb(rocker_port, NULL, addr, vlan_id, flags); } static int rocker_event_process(const struct rocker *rocker, @@ -1585,7 +1578,7 @@ typedef int (*rocker_cmd_proc_cb_t)(const struct rocker_port *rocker_port, void *priv); static int rocker_cmd_exec(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, rocker_cmd_prep_cb_t prepare, void *prepare_priv, rocker_cmd_proc_cb_t process, void *process_priv) { @@ -1596,7 +1589,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port, unsigned long lock_flags; int err; - wait = rocker_wait_create(rocker_port, trans_ph, flags); + wait = rocker_wait_create(rocker_port, trans, flags); if (!wait) return -ENOMEM; wait->nowait = nowait; @@ -1618,7 +1611,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port, rocker_desc_cookie_ptr_set(desc_info, wait); - if (trans_ph != SWITCHDEV_TRANS_PREPARE) + if (!switchdev_trans_ph_prepare(trans)) rocker_desc_head_set(rocker, &rocker->cmd_ring, desc_info); spin_unlock_irqrestore(&rocker->cmd_ring_lock, lock_flags); @@ -1626,7 +1619,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port, if (nowait) return 0; - if (trans_ph != SWITCHDEV_TRANS_PREPARE) + if (!switchdev_trans_ph_prepare(trans)) if (!rocker_wait_event_timeout(wait, HZ / 10)) return -EIO; @@ -1639,7 +1632,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port, rocker_desc_gen_clear(desc_info); out: - rocker_wait_destroy(trans_ph, wait); + rocker_wait_destroy(trans, wait); return err; } @@ -1878,7 +1871,7 @@ rocker_cmd_set_port_learning_prep(const struct rocker_port *rocker_port, static int rocker_cmd_get_port_settings_ethtool(struct rocker_port *rocker_port, struct ethtool_cmd *ecmd) { - return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0, + return rocker_cmd_exec(rocker_port, NULL, 0, rocker_cmd_get_port_settings_prep, NULL, rocker_cmd_get_port_settings_ethtool_proc, ecmd); @@ -1887,7 +1880,7 @@ static int rocker_cmd_get_port_settings_ethtool(struct rocker_port *rocker_port, static int rocker_cmd_get_port_settings_macaddr(struct rocker_port *rocker_port, unsigned char *macaddr) { - return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0, + return rocker_cmd_exec(rocker_port, NULL, 0, rocker_cmd_get_port_settings_prep, NULL, rocker_cmd_get_port_settings_macaddr_proc, macaddr); @@ -1896,7 +1889,7 @@ static int rocker_cmd_get_port_settings_macaddr(struct rocker_port *rocker_port, static int rocker_cmd_set_port_settings_ethtool(struct rocker_port *rocker_port, struct ethtool_cmd *ecmd) { - return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0, + return rocker_cmd_exec(rocker_port, NULL, 0, rocker_cmd_set_port_settings_ethtool_prep, ecmd, NULL, NULL); } @@ -1904,7 +1897,7 @@ static int rocker_cmd_set_port_settings_ethtool(struct rocker_port *rocker_port, static int rocker_cmd_set_port_settings_macaddr(struct rocker_port *rocker_port, unsigned char *macaddr) { - return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0, + return rocker_cmd_exec(rocker_port, NULL, 0, rocker_cmd_set_port_settings_macaddr_prep, macaddr, NULL, NULL); } @@ -1912,15 +1905,15 @@ static int rocker_cmd_set_port_settings_macaddr(struct rocker_port *rocker_port, static int rocker_cmd_set_port_settings_mtu(struct rocker_port *rocker_port, int mtu) { - return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0, + return rocker_cmd_exec(rocker_port, NULL, 0, rocker_cmd_set_port_settings_mtu_prep, &mtu, NULL, NULL); } static int rocker_port_set_learning(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph) + struct switchdev_trans *trans) { - return rocker_cmd_exec(rocker_port, trans_ph, 0, + return rocker_cmd_exec(rocker_port, trans, 0, rocker_cmd_set_port_learning_prep, NULL, NULL, NULL); } @@ -2436,7 +2429,7 @@ rocker_flow_tbl_find(const struct rocker *rocker, } static int rocker_flow_tbl_add(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, struct rocker_flow_tbl_entry *match) { struct rocker *rocker = rocker_port->rocker; @@ -2452,9 +2445,9 @@ static int rocker_flow_tbl_add(struct rocker_port *rocker_port, if (found) { match->cookie = found->cookie; - if (trans_ph != SWITCHDEV_TRANS_PREPARE) + if (!switchdev_trans_ph_prepare(trans)) hash_del(&found->entry); - rocker_port_kfree(trans_ph, found); + rocker_port_kfree(trans, found); found = match; found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_MOD; } else { @@ -2463,17 +2456,17 @@ static int rocker_flow_tbl_add(struct rocker_port *rocker_port, found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_ADD; } - if (trans_ph != SWITCHDEV_TRANS_PREPARE) + if (!switchdev_trans_ph_prepare(trans)) hash_add(rocker->flow_tbl, &found->entry, found->key_crc32); spin_unlock_irqrestore(&rocker->flow_tbl_lock, lock_flags); - return rocker_cmd_exec(rocker_port, trans_ph, flags, + return rocker_cmd_exec(rocker_port, trans, flags, rocker_cmd_flow_tbl_add, found, NULL, NULL); } static int rocker_flow_tbl_del(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, struct rocker_flow_tbl_entry *match) { struct rocker *rocker = rocker_port->rocker; @@ -2489,43 +2482,43 @@ static int rocker_flow_tbl_del(struct rocker_port *rocker_port, found = rocker_flow_tbl_find(rocker, match); if (found) { - if (trans_ph != SWITCHDEV_TRANS_PREPARE) + if (!switchdev_trans_ph_prepare(trans)) hash_del(&found->entry); found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_DEL; } spin_unlock_irqrestore(&rocker->flow_tbl_lock, lock_flags); - rocker_port_kfree(trans_ph, match); + rocker_port_kfree(trans, match); if (found) { - err = rocker_cmd_exec(rocker_port, trans_ph, flags, + err = rocker_cmd_exec(rocker_port, trans, flags, rocker_cmd_flow_tbl_del, found, NULL, NULL); - rocker_port_kfree(trans_ph, found); + rocker_port_kfree(trans, found); } return err; } static int rocker_flow_tbl_do(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, struct rocker_flow_tbl_entry *entry) { if (flags & ROCKER_OP_FLAG_REMOVE) - return rocker_flow_tbl_del(rocker_port, trans_ph, flags, entry); + return rocker_flow_tbl_del(rocker_port, trans, flags, entry); else - return rocker_flow_tbl_add(rocker_port, trans_ph, flags, entry); + return rocker_flow_tbl_add(rocker_port, trans, flags, entry); } static int rocker_flow_tbl_ig_port(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, u32 in_pport, u32 in_pport_mask, enum rocker_of_dpa_table_id goto_tbl) { struct rocker_flow_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2535,11 +2528,11 @@ static int rocker_flow_tbl_ig_port(struct rocker_port *rocker_port, entry->key.ig_port.in_pport_mask = in_pport_mask; entry->key.ig_port.goto_tbl = goto_tbl; - return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry); + return rocker_flow_tbl_do(rocker_port, trans, flags, entry); } static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, u32 in_pport, __be16 vlan_id, __be16 vlan_id_mask, enum rocker_of_dpa_table_id goto_tbl, @@ -2547,7 +2540,7 @@ static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port, { struct rocker_flow_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2561,11 +2554,11 @@ static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port, entry->key.vlan.untagged = untagged; entry->key.vlan.new_vlan_id = new_vlan_id; - return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry); + return rocker_flow_tbl_do(rocker_port, trans, flags, entry); } static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, u32 in_pport, u32 in_pport_mask, __be16 eth_type, const u8 *eth_dst, const u8 *eth_dst_mask, __be16 vlan_id, @@ -2574,7 +2567,7 @@ static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port, { struct rocker_flow_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2598,11 +2591,11 @@ static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port, entry->key.term_mac.vlan_id_mask = vlan_id_mask; entry->key.term_mac.copy_to_cpu = copy_to_cpu; - return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry); + return rocker_flow_tbl_do(rocker_port, trans, flags, entry); } static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, const u8 *eth_dst, const u8 *eth_dst_mask, __be16 vlan_id, u32 tunnel_id, enum rocker_of_dpa_table_id goto_tbl, @@ -2614,7 +2607,7 @@ static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port, bool dflt = !eth_dst || (eth_dst && eth_dst_mask); bool wild = false; - entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2652,11 +2645,11 @@ static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port, entry->key.bridge.group_id = group_id; entry->key.bridge.copy_to_cpu = copy_to_cpu; - return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry); + return rocker_flow_tbl_do(rocker_port, trans, flags, entry); } static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, __be16 eth_type, __be32 dst, __be32 dst_mask, u32 priority, enum rocker_of_dpa_table_id goto_tbl, @@ -2664,7 +2657,7 @@ static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port, { struct rocker_flow_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2678,11 +2671,11 @@ static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port, entry->key_len = offsetof(struct rocker_flow_tbl_key, ucast_routing.group_id); - return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry); + return rocker_flow_tbl_do(rocker_port, trans, flags, entry); } static int rocker_flow_tbl_acl(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, u32 in_pport, u32 in_pport_mask, const u8 *eth_src, const u8 *eth_src_mask, const u8 *eth_dst, const u8 *eth_dst_mask, @@ -2694,7 +2687,7 @@ static int rocker_flow_tbl_acl(struct rocker_port *rocker_port, u32 priority; struct rocker_flow_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2729,7 +2722,7 @@ static int rocker_flow_tbl_acl(struct rocker_port *rocker_port, entry->key.acl.ip_tos_mask = ip_tos_mask; entry->key.acl.group_id = group_id; - return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry); + return rocker_flow_tbl_do(rocker_port, trans, flags, entry); } static struct rocker_group_tbl_entry * @@ -2747,22 +2740,22 @@ rocker_group_tbl_find(const struct rocker *rocker, return NULL; } -static void rocker_group_tbl_entry_free(enum switchdev_trans_ph trans_ph, +static void rocker_group_tbl_entry_free(struct switchdev_trans *trans, struct rocker_group_tbl_entry *entry) { switch (ROCKER_GROUP_TYPE_GET(entry->group_id)) { case ROCKER_OF_DPA_GROUP_TYPE_L2_FLOOD: case ROCKER_OF_DPA_GROUP_TYPE_L2_MCAST: - rocker_port_kfree(trans_ph, entry->group_ids); + rocker_port_kfree(trans, entry->group_ids); break; default: break; } - rocker_port_kfree(trans_ph, entry); + rocker_port_kfree(trans, entry); } static int rocker_group_tbl_add(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, struct rocker_group_tbl_entry *match) { struct rocker *rocker = rocker_port->rocker; @@ -2774,9 +2767,9 @@ static int rocker_group_tbl_add(struct rocker_port *rocker_port, found = rocker_group_tbl_find(rocker, match); if (found) { - if (trans_ph != SWITCHDEV_TRANS_PREPARE) + if (!switchdev_trans_ph_prepare(trans)) hash_del(&found->entry); - rocker_group_tbl_entry_free(trans_ph, found); + rocker_group_tbl_entry_free(trans, found); found = match; found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_MOD; } else { @@ -2784,17 +2777,17 @@ static int rocker_group_tbl_add(struct rocker_port *rocker_port, found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_ADD; } - if (trans_ph != SWITCHDEV_TRANS_PREPARE) + if (!switchdev_trans_ph_prepare(trans)) hash_add(rocker->group_tbl, &found->entry, found->group_id); spin_unlock_irqrestore(&rocker->group_tbl_lock, lock_flags); - return rocker_cmd_exec(rocker_port, trans_ph, flags, + return rocker_cmd_exec(rocker_port, trans, flags, rocker_cmd_group_tbl_add, found, NULL, NULL); } static int rocker_group_tbl_del(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, struct rocker_group_tbl_entry *match) { struct rocker *rocker = rocker_port->rocker; @@ -2807,95 +2800,95 @@ static int rocker_group_tbl_del(struct rocker_port *rocker_port, found = rocker_group_tbl_find(rocker, match); if (found) { - if (trans_ph != SWITCHDEV_TRANS_PREPARE) + if (!switchdev_trans_ph_prepare(trans)) hash_del(&found->entry); found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_DEL; } spin_unlock_irqrestore(&rocker->group_tbl_lock, lock_flags); - rocker_group_tbl_entry_free(trans_ph, match); + rocker_group_tbl_entry_free(trans, match); if (found) { - err = rocker_cmd_exec(rocker_port, trans_ph, flags, + err = rocker_cmd_exec(rocker_port, trans, flags, rocker_cmd_group_tbl_del, found, NULL, NULL); - rocker_group_tbl_entry_free(trans_ph, found); + rocker_group_tbl_entry_free(trans, found); } return err; } static int rocker_group_tbl_do(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, struct rocker_group_tbl_entry *entry) { if (flags & ROCKER_OP_FLAG_REMOVE) - return rocker_group_tbl_del(rocker_port, trans_ph, flags, entry); + return rocker_group_tbl_del(rocker_port, trans, flags, entry); else - return rocker_group_tbl_add(rocker_port, trans_ph, flags, entry); + return rocker_group_tbl_add(rocker_port, trans, flags, entry); } static int rocker_group_l2_interface(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, __be16 vlan_id, u32 out_pport, int pop_vlan) { struct rocker_group_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); if (!entry) return -ENOMEM; entry->group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport); entry->l2_interface.pop_vlan = pop_vlan; - return rocker_group_tbl_do(rocker_port, trans_ph, flags, entry); + return rocker_group_tbl_do(rocker_port, trans, flags, entry); } static int rocker_group_l2_fan_out(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, int flags, u8 group_count, const u32 *group_ids, u32 group_id) { struct rocker_group_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); if (!entry) return -ENOMEM; entry->group_id = group_id; entry->group_count = group_count; - entry->group_ids = rocker_port_kcalloc(rocker_port, trans_ph, flags, + entry->group_ids = rocker_port_kcalloc(rocker_port, trans, flags, group_count, sizeof(u32)); if (!entry->group_ids) { - rocker_port_kfree(trans_ph, entry); + rocker_port_kfree(trans, entry); return -ENOMEM; } memcpy(entry->group_ids, group_ids, group_count * sizeof(u32)); - return rocker_group_tbl_do(rocker_port, trans_ph, flags, entry); + return rocker_group_tbl_do(rocker_port, trans, flags, entry); } static int rocker_group_l2_flood(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, __be16 vlan_id, u8 group_count, const u32 *group_ids, u32 group_id) { - return rocker_group_l2_fan_out(rocker_port, trans_ph, flags, + return rocker_group_l2_fan_out(rocker_port, trans, flags, group_count, group_ids, group_id); } static int rocker_group_l3_unicast(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, u32 index, const u8 *src_mac, const u8 *dst_mac, __be16 vlan_id, bool ttl_check, u32 pport) { struct rocker_group_tbl_entry *entry; - entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2908,7 +2901,7 @@ static int rocker_group_l3_unicast(struct rocker_port *rocker_port, entry->l3_unicast.ttl_check = ttl_check; entry->l3_unicast.group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, pport); - return rocker_group_tbl_do(rocker_port, trans_ph, flags, entry); + return rocker_group_tbl_do(rocker_port, trans, flags, entry); } static struct rocker_neigh_tbl_entry * @@ -2925,43 +2918,43 @@ rocker_neigh_tbl_find(const struct rocker *rocker, __be32 ip_addr) } static void _rocker_neigh_add(struct rocker *rocker, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, struct rocker_neigh_tbl_entry *entry) { - if (trans_ph != SWITCHDEV_TRANS_COMMIT) + if (!switchdev_trans_ph_commit(trans)) entry->index = rocker->neigh_tbl_next_index++; - if (trans_ph == SWITCHDEV_TRANS_PREPARE) + if (switchdev_trans_ph_prepare(trans)) return; entry->ref_count++; hash_add(rocker->neigh_tbl, &entry->entry, be32_to_cpu(entry->ip_addr)); } -static void _rocker_neigh_del(enum switchdev_trans_ph trans_ph, +static void _rocker_neigh_del(struct switchdev_trans *trans, struct rocker_neigh_tbl_entry *entry) { - if (trans_ph == SWITCHDEV_TRANS_PREPARE) + if (switchdev_trans_ph_prepare(trans)) return; if (--entry->ref_count == 0) { hash_del(&entry->entry); - rocker_port_kfree(trans_ph, entry); + rocker_port_kfree(trans, entry); } } static void _rocker_neigh_update(struct rocker_neigh_tbl_entry *entry, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, const u8 *eth_dst, bool ttl_check) { if (eth_dst) { ether_addr_copy(entry->eth_dst, eth_dst); entry->ttl_check = ttl_check; - } else if (trans_ph != SWITCHDEV_TRANS_PREPARE) { + } else if (!switchdev_trans_ph_prepare(trans)) { entry->ref_count++; } } static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, int flags, __be32 ip_addr, const u8 *eth_dst) { struct rocker *rocker = rocker_port->rocker; @@ -2978,7 +2971,7 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port, bool removing; int err = 0; - entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -2995,12 +2988,12 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port, entry->dev = rocker_port->dev; ether_addr_copy(entry->eth_dst, eth_dst); entry->ttl_check = true; - _rocker_neigh_add(rocker, trans_ph, entry); + _rocker_neigh_add(rocker, trans, entry); } else if (removing) { memcpy(entry, found, sizeof(*entry)); - _rocker_neigh_del(trans_ph, found); + _rocker_neigh_del(trans, found); } else if (updating) { - _rocker_neigh_update(found, trans_ph, eth_dst, true); + _rocker_neigh_update(found, trans, eth_dst, true); memcpy(entry, found, sizeof(*entry)); } else { err = -ENOENT; @@ -3017,7 +3010,7 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port, * other routes' nexthops. */ - err = rocker_group_l3_unicast(rocker_port, trans_ph, flags, + err = rocker_group_l3_unicast(rocker_port, trans, flags, entry->index, rocker_port->dev->dev_addr, entry->eth_dst, @@ -3033,7 +3026,7 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port, if (adding || removing) { group_id = ROCKER_GROUP_L3_UNICAST(entry->index); - err = rocker_flow_tbl_ucast4_routing(rocker_port, trans_ph, + err = rocker_flow_tbl_ucast4_routing(rocker_port, trans, eth_type, ip_addr, inet_make_mask(32), priority, goto_tbl, @@ -3047,13 +3040,14 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port, err_out: if (!adding) - rocker_port_kfree(trans_ph, entry); + rocker_port_kfree(trans, entry); return err; } static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, __be32 ip_addr) + struct switchdev_trans *trans, + __be32 ip_addr) { struct net_device *dev = rocker_port->dev; struct neighbour *n = __ipv4_neigh_lookup(dev, (__force u32)ip_addr); @@ -3071,7 +3065,7 @@ static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port, */ if (n->nud_state & NUD_VALID) - err = rocker_port_ipv4_neigh(rocker_port, trans_ph, 0, + err = rocker_port_ipv4_neigh(rocker_port, trans, 0, ip_addr, n->ha); else neigh_event_send(n, NULL); @@ -3081,7 +3075,7 @@ static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port, } static int rocker_port_ipv4_nh(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, __be32 ip_addr, u32 *index) { struct rocker *rocker = rocker_port->rocker; @@ -3094,7 +3088,7 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port, bool resolved = true; int err = 0; - entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry)); + entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry)); if (!entry) return -ENOMEM; @@ -3111,13 +3105,13 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port, if (adding) { entry->ip_addr = ip_addr; entry->dev = rocker_port->dev; - _rocker_neigh_add(rocker, trans_ph, entry); + _rocker_neigh_add(rocker, trans, entry); *index = entry->index; resolved = false; } else if (removing) { - _rocker_neigh_del(trans_ph, found); + _rocker_neigh_del(trans, found); } else if (updating) { - _rocker_neigh_update(found, trans_ph, NULL, false); + _rocker_neigh_update(found, trans, NULL, false); resolved = !is_zero_ether_addr(found->eth_dst); } else { err = -ENOENT; @@ -3126,7 +3120,7 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port, spin_unlock_irqrestore(&rocker->neigh_tbl_lock, lock_flags); if (!adding) - rocker_port_kfree(trans_ph, entry); + rocker_port_kfree(trans, entry); if (err) return err; @@ -3134,13 +3128,13 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port, /* Resolved means neigh ip_addr is resolved to neigh mac. */ if (!resolved) - err = rocker_port_ipv4_resolve(rocker_port, trans_ph, ip_addr); + err = rocker_port_ipv4_resolve(rocker_port, trans, ip_addr); return err; } static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, int flags, __be16 vlan_id) { struct rocker_port *p; @@ -3151,7 +3145,7 @@ static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port, int err = 0; int i; - group_ids = rocker_port_kcalloc(rocker_port, trans_ph, flags, + group_ids = rocker_port_kcalloc(rocker_port, trans, flags, rocker->port_count, sizeof(u32)); if (!group_ids) return -ENOMEM; @@ -3177,19 +3171,19 @@ static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port, if (group_count == 0) goto no_ports_in_vlan; - err = rocker_group_l2_flood(rocker_port, trans_ph, flags, vlan_id, + err = rocker_group_l2_flood(rocker_port, trans, flags, vlan_id, group_count, group_ids, group_id); if (err) netdev_err(rocker_port->dev, "Error (%d) port VLAN l2 flood group\n", err); no_ports_in_vlan: - rocker_port_kfree(trans_ph, group_ids); + rocker_port_kfree(trans, group_ids); return err; } static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, __be16 vlan_id, bool pop_vlan) { const struct rocker *rocker = rocker_port->rocker; @@ -3207,7 +3201,7 @@ static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port, if (rocker_port->stp_state == BR_STATE_LEARNING || rocker_port->stp_state == BR_STATE_FORWARDING) { out_pport = rocker_port->pport; - err = rocker_group_l2_interface(rocker_port, trans_ph, flags, + err = rocker_group_l2_interface(rocker_port, trans, flags, vlan_id, out_pport, pop_vlan); if (err) { netdev_err(rocker_port->dev, @@ -3232,7 +3226,7 @@ static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port, return 0; out_pport = 0; - err = rocker_group_l2_interface(rocker_port, trans_ph, flags, + err = rocker_group_l2_interface(rocker_port, trans, flags, vlan_id, out_pport, pop_vlan); if (err) { netdev_err(rocker_port->dev, @@ -3295,7 +3289,7 @@ static struct rocker_ctrl { }; static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, const struct rocker_ctrl *ctrl, __be16 vlan_id) { u32 in_pport = rocker_port->pport; @@ -3311,7 +3305,7 @@ static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port, u32 group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport); int err; - err = rocker_flow_tbl_acl(rocker_port, trans_ph, flags, + err = rocker_flow_tbl_acl(rocker_port, trans, flags, in_pport, in_pport_mask, eth_src, eth_src_mask, ctrl->eth_dst, ctrl->eth_dst_mask, @@ -3328,7 +3322,8 @@ static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port, } static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, + int flags, const struct rocker_ctrl *ctrl, __be16 vlan_id) { @@ -3341,7 +3336,7 @@ static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port, if (!rocker_port_is_bridged(rocker_port)) return 0; - err = rocker_flow_tbl_bridge(rocker_port, trans_ph, flags, + err = rocker_flow_tbl_bridge(rocker_port, trans, flags, ctrl->eth_dst, ctrl->eth_dst_mask, vlan_id, tunnel_id, goto_tbl, group_id, ctrl->copy_to_cpu); @@ -3353,7 +3348,7 @@ static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port, } static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, const struct rocker_ctrl *ctrl, __be16 vlan_id) { u32 in_pport_mask = 0xffffffff; @@ -3363,7 +3358,7 @@ static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port, if (ntohs(vlan_id) == 0) vlan_id = rocker_port->internal_vlan_id; - err = rocker_flow_tbl_term_mac(rocker_port, trans_ph, + err = rocker_flow_tbl_term_mac(rocker_port, trans, rocker_port->pport, in_pport_mask, ctrl->eth_type, ctrl->eth_dst, ctrl->eth_dst_mask, vlan_id, @@ -3377,25 +3372,25 @@ static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port, } static int rocker_port_ctrl_vlan(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, const struct rocker_ctrl *ctrl, __be16 vlan_id) { if (ctrl->acl) - return rocker_port_ctrl_vlan_acl(rocker_port, trans_ph, flags, + return rocker_port_ctrl_vlan_acl(rocker_port, trans, flags, ctrl, vlan_id); if (ctrl->bridge) - return rocker_port_ctrl_vlan_bridge(rocker_port, trans_ph, flags, + return rocker_port_ctrl_vlan_bridge(rocker_port, trans, flags, ctrl, vlan_id); if (ctrl->term) - return rocker_port_ctrl_vlan_term(rocker_port, trans_ph, flags, + return rocker_port_ctrl_vlan_term(rocker_port, trans, flags, ctrl, vlan_id); return -EOPNOTSUPP; } static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, __be16 vlan_id) { int err = 0; @@ -3403,7 +3398,7 @@ static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port, for (i = 0; i < ROCKER_CTRL_MAX; i++) { if (rocker_port->ctrls[i]) { - err = rocker_port_ctrl_vlan(rocker_port, trans_ph, flags, + err = rocker_port_ctrl_vlan(rocker_port, trans, flags, &rocker_ctrls[i], vlan_id); if (err) return err; @@ -3414,7 +3409,7 @@ static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port, } static int rocker_port_ctrl(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, const struct rocker_ctrl *ctrl) { u16 vid; @@ -3423,7 +3418,7 @@ static int rocker_port_ctrl(struct rocker_port *rocker_port, for (vid = 1; vid < VLAN_N_VID; vid++) { if (!test_bit(vid, rocker_port->vlan_bitmap)) continue; - err = rocker_port_ctrl_vlan(rocker_port, trans_ph, flags, + err = rocker_port_ctrl_vlan(rocker_port, trans, flags, ctrl, htons(vid)); if (err) break; @@ -3433,7 +3428,7 @@ static int rocker_port_ctrl(struct rocker_port *rocker_port, } static int rocker_port_vlan(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, u16 vid) + struct switchdev_trans *trans, int flags, u16 vid) { enum rocker_of_dpa_table_id goto_tbl = ROCKER_OF_DPA_TABLE_ID_TERMINATION_MAC; @@ -3457,7 +3452,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port, change_bit(ntohs(internal_vlan_id), rocker_port->vlan_bitmap); if (adding) { - err = rocker_port_ctrl_vlan_add(rocker_port, trans_ph, flags, + err = rocker_port_ctrl_vlan_add(rocker_port, trans, flags, internal_vlan_id); if (err) { netdev_err(rocker_port->dev, @@ -3466,7 +3461,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port, } } - err = rocker_port_vlan_l2_groups(rocker_port, trans_ph, flags, + err = rocker_port_vlan_l2_groups(rocker_port, trans, flags, internal_vlan_id, untagged); if (err) { netdev_err(rocker_port->dev, @@ -3474,7 +3469,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port, goto err_out; } - err = rocker_port_vlan_flood_group(rocker_port, trans_ph, flags, + err = rocker_port_vlan_flood_group(rocker_port, trans, flags, internal_vlan_id); if (err) { netdev_err(rocker_port->dev, @@ -3482,7 +3477,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port, goto err_out; } - err = rocker_flow_tbl_vlan(rocker_port, trans_ph, flags, + err = rocker_flow_tbl_vlan(rocker_port, trans, flags, in_pport, vlan_id, vlan_id_mask, goto_tbl, untagged, internal_vlan_id); if (err) @@ -3490,14 +3485,14 @@ static int rocker_port_vlan(struct rocker_port *rocker_port, "Error (%d) port VLAN table\n", err); err_out: - if (trans_ph == SWITCHDEV_TRANS_PREPARE) + if (switchdev_trans_ph_prepare(trans)) change_bit(ntohs(internal_vlan_id), rocker_port->vlan_bitmap); return err; } static int rocker_port_ig_tbl(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags) + struct switchdev_trans *trans, int flags) { enum rocker_of_dpa_table_id goto_tbl; u32 in_pport; @@ -3512,7 +3507,7 @@ static int rocker_port_ig_tbl(struct rocker_port *rocker_port, in_pport_mask = 0xffff0000; goto_tbl = ROCKER_OF_DPA_TABLE_ID_VLAN; - err = rocker_flow_tbl_ig_port(rocker_port, trans_ph, flags, + err = rocker_flow_tbl_ig_port(rocker_port, trans, flags, in_pport, in_pport_mask, goto_tbl); if (err) @@ -3525,7 +3520,7 @@ static int rocker_port_ig_tbl(struct rocker_port *rocker_port, struct rocker_fdb_learn_work { struct work_struct work; struct rocker_port *rocker_port; - enum switchdev_trans_ph trans_ph; + struct switchdev_trans *trans; int flags; u8 addr[ETH_ALEN]; u16 vid; @@ -3549,11 +3544,11 @@ static void rocker_port_fdb_learn_work(struct work_struct *work) call_switchdev_notifiers(SWITCHDEV_FDB_ADD, lw->rocker_port->dev, &info.info); - rocker_port_kfree(lw->trans_ph, work); + rocker_port_kfree(lw->trans, work); } static int rocker_port_fdb_learn(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, const u8 *addr, __be16 vlan_id) { struct rocker_fdb_learn_work *lw; @@ -3570,7 +3565,7 @@ static int rocker_port_fdb_learn(struct rocker_port *rocker_port, group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport); if (!(flags & ROCKER_OP_FLAG_REFRESH)) { - err = rocker_flow_tbl_bridge(rocker_port, trans_ph, flags, addr, + err = rocker_flow_tbl_bridge(rocker_port, trans, flags, addr, NULL, vlan_id, tunnel_id, goto_tbl, group_id, copy_to_cpu); if (err) @@ -3583,20 +3578,20 @@ static int rocker_port_fdb_learn(struct rocker_port *rocker_port, if (!rocker_port_is_bridged(rocker_port)) return 0; - lw = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*lw)); + lw = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*lw)); if (!lw) return -ENOMEM; INIT_WORK(&lw->work, rocker_port_fdb_learn_work); lw->rocker_port = rocker_port; - lw->trans_ph = trans_ph; + lw->trans = trans; lw->flags = flags; ether_addr_copy(lw->addr, addr); lw->vid = rocker_port_vlan_to_vid(rocker_port, vlan_id); - if (trans_ph == SWITCHDEV_TRANS_PREPARE) - rocker_port_kfree(trans_ph, lw); + if (switchdev_trans_ph_prepare(trans)) + rocker_port_kfree(trans, lw); else schedule_work(&lw->work); @@ -3617,7 +3612,7 @@ rocker_fdb_tbl_find(const struct rocker *rocker, } static int rocker_port_fdb(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, const unsigned char *addr, __be16 vlan_id, int flags) { @@ -3627,7 +3622,7 @@ static int rocker_port_fdb(struct rocker_port *rocker_port, bool removing = (flags & ROCKER_OP_FLAG_REMOVE); unsigned long lock_flags; - fdb = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*fdb)); + fdb = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*fdb)); if (!fdb) return -ENOMEM; @@ -3645,12 +3640,12 @@ static int rocker_port_fdb(struct rocker_port *rocker_port, if (found) { found->touched = jiffies; if (removing) { - rocker_port_kfree(trans_ph, fdb); - if (trans_ph != SWITCHDEV_TRANS_PREPARE) + rocker_port_kfree(trans, fdb); + if (!switchdev_trans_ph_prepare(trans)) hash_del(&found->entry); } } else if (!removing) { - if (trans_ph != SWITCHDEV_TRANS_PREPARE) + if (!switchdev_trans_ph_prepare(trans)) hash_add(rocker->fdb_tbl, &fdb->entry, fdb->key_crc32); } @@ -3659,18 +3654,18 @@ static int rocker_port_fdb(struct rocker_port *rocker_port, /* Check if adding and already exists, or removing and can't find */ if (!found != !removing) { - rocker_port_kfree(trans_ph, fdb); + rocker_port_kfree(trans, fdb); if (!found && removing) return 0; /* Refreshing existing to update aging timers */ flags |= ROCKER_OP_FLAG_REFRESH; } - return rocker_port_fdb_learn(rocker_port, trans_ph, flags, addr, vlan_id); + return rocker_port_fdb_learn(rocker_port, trans, flags, addr, vlan_id); } static int rocker_port_fdb_flush(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags) + struct switchdev_trans *trans, int flags) { struct rocker *rocker = rocker_port->rocker; struct rocker_fdb_tbl_entry *found; @@ -3692,12 +3687,12 @@ static int rocker_port_fdb_flush(struct rocker_port *rocker_port, continue; if (!found->learned) continue; - err = rocker_port_fdb_learn(rocker_port, trans_ph, flags, + err = rocker_port_fdb_learn(rocker_port, trans, flags, found->key.addr, found->key.vlan_id); if (err) goto err_out; - if (trans_ph != SWITCHDEV_TRANS_PREPARE) + if (!switchdev_trans_ph_prepare(trans)) hash_del(&found->entry); } @@ -3728,7 +3723,7 @@ static void rocker_fdb_cleanup(unsigned long data) rocker_port = entry->key.rocker_port; expires = entry->touched + rocker_port->ageing_time; if (time_before_eq(expires, jiffies)) { - rocker_port_fdb_learn(rocker_port, SWITCHDEV_TRANS_NONE, + rocker_port_fdb_learn(rocker_port, NULL, flags, entry->key.addr, entry->key.vlan_id); hash_del(&entry->entry); @@ -3743,7 +3738,7 @@ static void rocker_fdb_cleanup(unsigned long data) } static int rocker_port_router_mac(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, __be16 vlan_id) { u32 in_pport_mask = 0xffffffff; @@ -3757,7 +3752,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port, vlan_id = rocker_port->internal_vlan_id; eth_type = htons(ETH_P_IP); - err = rocker_flow_tbl_term_mac(rocker_port, trans_ph, + err = rocker_flow_tbl_term_mac(rocker_port, trans, rocker_port->pport, in_pport_mask, eth_type, rocker_port->dev->dev_addr, dst_mac_mask, vlan_id, vlan_id_mask, @@ -3766,7 +3761,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port, return err; eth_type = htons(ETH_P_IPV6); - err = rocker_flow_tbl_term_mac(rocker_port, trans_ph, + err = rocker_flow_tbl_term_mac(rocker_port, trans, rocker_port->pport, in_pport_mask, eth_type, rocker_port->dev->dev_addr, dst_mac_mask, vlan_id, vlan_id_mask, @@ -3776,7 +3771,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port, } static int rocker_port_fwding(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags) + struct switchdev_trans *trans, int flags) { bool pop_vlan; u32 out_pport; @@ -3801,7 +3796,7 @@ static int rocker_port_fwding(struct rocker_port *rocker_port, continue; vlan_id = htons(vid); pop_vlan = rocker_vlan_id_is_internal(vlan_id); - err = rocker_group_l2_interface(rocker_port, trans_ph, flags, + err = rocker_group_l2_interface(rocker_port, trans, flags, vlan_id, out_pport, pop_vlan); if (err) { netdev_err(rocker_port->dev, @@ -3815,16 +3810,16 @@ static int rocker_port_fwding(struct rocker_port *rocker_port, } static int rocker_port_stp_update(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags, + struct switchdev_trans *trans, int flags, u8 state) { bool want[ROCKER_CTRL_MAX] = { 0, }; bool prev_ctrls[ROCKER_CTRL_MAX]; - u8 prev_state; + u8 uninitialized_var(prev_state); int err; int i; - if (trans_ph == SWITCHDEV_TRANS_PREPARE) { + if (switchdev_trans_ph_prepare(trans)) { memcpy(prev_ctrls, rocker_port->ctrls, sizeof(prev_ctrls)); prev_state = rocker_port->stp_state; } @@ -3861,7 +3856,7 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port, if (want[i] != rocker_port->ctrls[i]) { int ctrl_flags = flags | (want[i] ? 0 : ROCKER_OP_FLAG_REMOVE); - err = rocker_port_ctrl(rocker_port, trans_ph, ctrl_flags, + err = rocker_port_ctrl(rocker_port, trans, ctrl_flags, &rocker_ctrls[i]); if (err) goto err_out; @@ -3869,14 +3864,14 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port, } } - err = rocker_port_fdb_flush(rocker_port, trans_ph, flags); + err = rocker_port_fdb_flush(rocker_port, trans, flags); if (err) goto err_out; - err = rocker_port_fwding(rocker_port, trans_ph, flags); + err = rocker_port_fwding(rocker_port, trans, flags); err_out: - if (trans_ph == SWITCHDEV_TRANS_PREPARE) { + if (switchdev_trans_ph_prepare(trans)) { memcpy(rocker_port->ctrls, prev_ctrls, sizeof(prev_ctrls)); rocker_port->stp_state = prev_state; } @@ -3885,26 +3880,26 @@ err_out: } static int rocker_port_fwd_enable(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags) + struct switchdev_trans *trans, int flags) { if (rocker_port_is_bridged(rocker_port)) /* bridge STP will enable port */ return 0; /* port is not bridged, so simulate going to FORWARDING state */ - return rocker_port_stp_update(rocker_port, trans_ph, flags, + return rocker_port_stp_update(rocker_port, trans, flags, BR_STATE_FORWARDING); } static int rocker_port_fwd_disable(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, int flags) + struct switchdev_trans *trans, int flags) { if (rocker_port_is_bridged(rocker_port)) /* bridge STP will disable port */ return 0; /* port is not bridged, so simulate going to DISABLED state */ - return rocker_port_stp_update(rocker_port, trans_ph, flags, + return rocker_port_stp_update(rocker_port, trans, flags, BR_STATE_DISABLED); } @@ -3995,7 +3990,7 @@ not_found: } static int rocker_port_fib_ipv4(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, __be32 dst, + struct switchdev_trans *trans, __be32 dst, int dst_len, const struct fib_info *fi, u32 tb_id, int flags) { @@ -4019,7 +4014,7 @@ static int rocker_port_fib_ipv4(struct rocker_port *rocker_port, has_gw = !!nh->nh_gw; if (has_gw && nh_on_port) { - err = rocker_port_ipv4_nh(rocker_port, trans_ph, flags, + err = rocker_port_ipv4_nh(rocker_port, trans, flags, nh->nh_gw, &index); if (err) return err; @@ -4030,7 +4025,7 @@ static int rocker_port_fib_ipv4(struct rocker_port *rocker_port, group_id = ROCKER_GROUP_L2_INTERFACE(internal_vlan_id, 0); } - err = rocker_flow_tbl_ucast4_routing(rocker_port, trans_ph, eth_type, dst, + err = rocker_flow_tbl_ucast4_routing(rocker_port, trans, eth_type, dst, dst_mask, priority, goto_tbl, group_id, flags); if (err) @@ -4069,7 +4064,7 @@ static int rocker_port_open(struct net_device *dev) goto err_request_rx_irq; } - err = rocker_port_fwd_enable(rocker_port, SWITCHDEV_TRANS_NONE, 0); + err = rocker_port_fwd_enable(rocker_port, NULL, 0); if (err) goto err_fwd_enable; @@ -4097,7 +4092,7 @@ static int rocker_port_stop(struct net_device *dev) rocker_port_set_enable(rocker_port, false); napi_disable(&rocker_port->napi_rx); napi_disable(&rocker_port->napi_tx); - rocker_port_fwd_disable(rocker_port, SWITCHDEV_TRANS_NONE, + rocker_port_fwd_disable(rocker_port, NULL, ROCKER_OP_FLAG_NOWAIT); free_irq(rocker_msix_rx_vector(rocker_port), rocker_port); free_irq(rocker_msix_tx_vector(rocker_port), rocker_port); @@ -4283,7 +4278,7 @@ static int rocker_port_get_phys_port_name(struct net_device *dev, struct port_name name = { .buf = buf, .len = len }; int err; - err = rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0, + err = rocker_cmd_exec(rocker_port, NULL, 0, rocker_cmd_get_port_settings_prep, NULL, rocker_cmd_get_port_settings_phys_name_proc, &name); @@ -4308,7 +4303,7 @@ static void rocker_port_neigh_destroy(struct neighbour *n) int flags = ROCKER_OP_FLAG_REMOVE | ROCKER_OP_FLAG_NOWAIT; __be32 ip_addr = *(__be32 *)n->primary_key; - rocker_port_ipv4_neigh(rocker_port, SWITCHDEV_TRANS_NONE, + rocker_port_ipv4_neigh(rocker_port, NULL, flags, ip_addr, n->ha); } @@ -4365,7 +4360,7 @@ static void rocker_port_trans_abort(const struct rocker_port *rocker_port) } static int rocker_port_brport_flags_set(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, unsigned long brport_flags) { unsigned long orig_flags; @@ -4374,9 +4369,9 @@ static int rocker_port_brport_flags_set(struct rocker_port *rocker_port, orig_flags = rocker_port->brport_flags; rocker_port->brport_flags = brport_flags; if ((orig_flags ^ rocker_port->brport_flags) & BR_LEARNING) - err = rocker_port_set_learning(rocker_port, trans_ph); + err = rocker_port_set_learning(rocker_port, trans); - if (trans_ph == SWITCHDEV_TRANS_PREPARE) + if (switchdev_trans_ph_prepare(trans)) rocker_port->brport_flags = orig_flags; return err; @@ -4402,12 +4397,12 @@ static int rocker_port_attr_set(struct net_device *dev, switch (attr->id) { case SWITCHDEV_ATTR_PORT_STP_STATE: - err = rocker_port_stp_update(rocker_port, trans->ph, + err = rocker_port_stp_update(rocker_port, trans, ROCKER_OP_FLAG_NOWAIT, attr->u.stp_state); break; case SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS: - err = rocker_port_brport_flags_set(rocker_port, trans->ph, + err = rocker_port_brport_flags_set(rocker_port, trans, attr->u.brport_flags); break; default: @@ -4419,33 +4414,34 @@ static int rocker_port_attr_set(struct net_device *dev, } static int rocker_port_vlan_add(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, u16 vid, u16 flags) + struct switchdev_trans *trans, + u16 vid, u16 flags) { int err; /* XXX deal with flags for PVID and untagged */ - err = rocker_port_vlan(rocker_port, trans_ph, 0, vid); + err = rocker_port_vlan(rocker_port, trans, 0, vid); if (err) return err; - err = rocker_port_router_mac(rocker_port, trans_ph, 0, htons(vid)); + err = rocker_port_router_mac(rocker_port, trans, 0, htons(vid)); if (err) - rocker_port_vlan(rocker_port, trans_ph, + rocker_port_vlan(rocker_port, trans, ROCKER_OP_FLAG_REMOVE, vid); return err; } static int rocker_port_vlans_add(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, const struct switchdev_obj_vlan *vlan) { u16 vid; int err; for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { - err = rocker_port_vlan_add(rocker_port, trans_ph, + err = rocker_port_vlan_add(rocker_port, trans, vid, vlan->flags); if (err) return err; @@ -4455,7 +4451,7 @@ static int rocker_port_vlans_add(struct rocker_port *rocker_port, } static int rocker_port_fdb_add(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, const struct switchdev_obj_fdb *fdb) { __be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL); @@ -4464,7 +4460,7 @@ static int rocker_port_fdb_add(struct rocker_port *rocker_port, if (!rocker_port_is_bridged(rocker_port)) return -EINVAL; - return rocker_port_fdb(rocker_port, trans_ph, fdb->addr, vlan_id, flags); + return rocker_port_fdb(rocker_port, trans, fdb->addr, vlan_id, flags); } static int rocker_port_obj_add(struct net_device *dev, @@ -4488,17 +4484,17 @@ static int rocker_port_obj_add(struct net_device *dev, switch (obj->id) { case SWITCHDEV_OBJ_PORT_VLAN: - err = rocker_port_vlans_add(rocker_port, trans->ph, + err = rocker_port_vlans_add(rocker_port, trans, &obj->u.vlan); break; case SWITCHDEV_OBJ_IPV4_FIB: fib4 = &obj->u.ipv4_fib; - err = rocker_port_fib_ipv4(rocker_port, trans->ph, + err = rocker_port_fib_ipv4(rocker_port, trans, htonl(fib4->dst), fib4->dst_len, fib4->fi, fib4->tb_id, 0); break; case SWITCHDEV_OBJ_PORT_FDB: - err = rocker_port_fdb_add(rocker_port, trans->ph, &obj->u.fdb); + err = rocker_port_fdb_add(rocker_port, trans, &obj->u.fdb); break; default: err = -EOPNOTSUPP; @@ -4513,12 +4509,12 @@ static int rocker_port_vlan_del(struct rocker_port *rocker_port, { int err; - err = rocker_port_router_mac(rocker_port, SWITCHDEV_TRANS_NONE, + err = rocker_port_router_mac(rocker_port, NULL, ROCKER_OP_FLAG_REMOVE, htons(vid)); if (err) return err; - return rocker_port_vlan(rocker_port, SWITCHDEV_TRANS_NONE, + return rocker_port_vlan(rocker_port, NULL, ROCKER_OP_FLAG_REMOVE, vid); } @@ -4538,7 +4534,7 @@ static int rocker_port_vlans_del(struct rocker_port *rocker_port, } static int rocker_port_fdb_del(struct rocker_port *rocker_port, - enum switchdev_trans_ph trans_ph, + struct switchdev_trans *trans, const struct switchdev_obj_fdb *fdb) { __be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL); @@ -4547,7 +4543,7 @@ static int rocker_port_fdb_del(struct rocker_port *rocker_port, if (!rocker_port_is_bridged(rocker_port)) return -EINVAL; - return rocker_port_fdb(rocker_port, trans_ph, fdb->addr, vlan_id, flags); + return rocker_port_fdb(rocker_port, trans, fdb->addr, vlan_id, flags); } static int rocker_port_obj_del(struct net_device *dev, @@ -4563,14 +4559,13 @@ static int rocker_port_obj_del(struct net_device *dev, break; case SWITCHDEV_OBJ_IPV4_FIB: fib4 = &obj->u.ipv4_fib; - err = rocker_port_fib_ipv4(rocker_port, SWITCHDEV_TRANS_NONE, + err = rocker_port_fib_ipv4(rocker_port, NULL, htonl(fib4->dst), fib4->dst_len, fib4->fi, fib4->tb_id, ROCKER_OP_FLAG_REMOVE); break; case SWITCHDEV_OBJ_PORT_FDB: - err = rocker_port_fdb_del(rocker_port, SWITCHDEV_TRANS_NONE, - &obj->u.fdb); + err = rocker_port_fdb_del(rocker_port, NULL, &obj->u.fdb); break; default: err = -EOPNOTSUPP; @@ -4784,7 +4779,7 @@ rocker_cmd_get_port_stats_ethtool_proc(const struct rocker_port *rocker_port, static int rocker_cmd_get_port_stats_ethtool(struct rocker_port *rocker_port, void *priv) { - return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0, + return rocker_cmd_exec(rocker_port, NULL, 0, rocker_cmd_get_port_stats_prep, NULL, rocker_cmd_get_port_stats_ethtool_proc, priv); @@ -4976,8 +4971,7 @@ static void rocker_remove_ports(const struct rocker *rocker) rocker_port = rocker->ports[i]; if (!rocker_port) continue; - rocker_port_ig_tbl(rocker_port, SWITCHDEV_TRANS_NONE, - ROCKER_OP_FLAG_REMOVE); + rocker_port_ig_tbl(rocker_port, NULL, ROCKER_OP_FLAG_REMOVE); unregister_netdev(rocker_port->dev); free_netdev(rocker_port->dev); } @@ -5039,9 +5033,9 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number) switchdev_port_fwd_mark_set(rocker_port->dev, NULL, false); - rocker_port_set_learning(rocker_port, SWITCHDEV_TRANS_NONE); + rocker_port_set_learning(rocker_port, NULL); - err = rocker_port_ig_tbl(rocker_port, SWITCHDEV_TRANS_NONE, 0); + err = rocker_port_ig_tbl(rocker_port, NULL, 0); if (err) { netdev_err(rocker_port->dev, "install ig port table failed\n"); goto err_port_ig_tbl; @@ -5050,8 +5044,7 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number) rocker_port->internal_vlan_id = rocker_port_internal_vlan_id_get(rocker_port, dev->ifindex); - err = rocker_port_vlan_add(rocker_port, SWITCHDEV_TRANS_NONE, - untagged_vid, 0); + err = rocker_port_vlan_add(rocker_port, NULL, untagged_vid, 0); if (err) { netdev_err(rocker_port->dev, "install untagged VLAN failed\n"); goto err_untagged_vlan; @@ -5060,8 +5053,7 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number) return 0; err_untagged_vlan: - rocker_port_ig_tbl(rocker_port, SWITCHDEV_TRANS_NONE, - ROCKER_OP_FLAG_REMOVE); + rocker_port_ig_tbl(rocker_port, NULL, ROCKER_OP_FLAG_REMOVE); err_port_ig_tbl: rocker->ports[port_number] = NULL; unregister_netdev(dev); @@ -5328,8 +5320,7 @@ static int rocker_port_bridge_join(struct rocker_port *rocker_port, rocker_port->bridge_dev = bridge; switchdev_port_fwd_mark_set(rocker_port->dev, bridge, true); - return rocker_port_vlan_add(rocker_port, SWITCHDEV_TRANS_NONE, - untagged_vid, 0); + return rocker_port_vlan_add(rocker_port, NULL, untagged_vid, 0); } static int rocker_port_bridge_leave(struct rocker_port *rocker_port) @@ -5351,14 +5342,12 @@ static int rocker_port_bridge_leave(struct rocker_port *rocker_port) false); rocker_port->bridge_dev = NULL; - err = rocker_port_vlan_add(rocker_port, SWITCHDEV_TRANS_NONE, - untagged_vid, 0); + err = rocker_port_vlan_add(rocker_port, NULL, untagged_vid, 0); if (err) return err; if (rocker_port->dev->flags & IFF_UP) - err = rocker_port_fwd_enable(rocker_port, - SWITCHDEV_TRANS_NONE, 0); + err = rocker_port_fwd_enable(rocker_port, NULL, 0); return err; } @@ -5371,10 +5360,10 @@ static int rocker_port_ovs_changed(struct rocker_port *rocker_port, rocker_port->bridge_dev = master; - err = rocker_port_fwd_disable(rocker_port, SWITCHDEV_TRANS_NONE, 0); + err = rocker_port_fwd_disable(rocker_port, NULL, 0); if (err) return err; - err = rocker_port_fwd_enable(rocker_port, SWITCHDEV_TRANS_NONE, 0); + err = rocker_port_fwd_enable(rocker_port, NULL, 0); return err; } @@ -5452,8 +5441,7 @@ static int rocker_neigh_update(struct net_device *dev, struct neighbour *n) ROCKER_OP_FLAG_NOWAIT; __be32 ip_addr = *(__be32 *)n->primary_key; - return rocker_port_ipv4_neigh(rocker_port, SWITCHDEV_TRANS_NONE, - flags, ip_addr, n->ha); + return rocker_port_ipv4_neigh(rocker_port, NULL, flags, ip_addr, n->ha); } static int rocker_netevent_event(struct notifier_block *unused, -- cgit v1.2.3 From ac3dbc68a4a74e74f4604207d01456d075394a64 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 24 Sep 2015 10:02:45 +0200 Subject: rocker: use switchdev transaction queue for allocated memory Benefit from previously introduced transaction item queue infrastructure and remove rocker specific transaction memory management. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 53 +++++------------------------------- 1 file changed, 7 insertions(+), 46 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 102b37d95d85..d3f663262184 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -228,7 +228,6 @@ struct rocker_port { struct napi_struct napi_rx; struct rocker_dma_ring_info tx_ring; struct rocker_dma_ring_info rx_ring; - struct list_head trans_mem; }; struct rocker { @@ -346,13 +345,13 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port, struct switchdev_trans *trans, int flags, size_t size) { - struct list_head *elem = NULL; + struct switchdev_trans_item *elem = NULL; gfp_t gfp_flags = (flags & ROCKER_OP_FLAG_NOWAIT) ? GFP_ATOMIC : GFP_KERNEL; /* If in transaction prepare phase, allocate the memory - * and enqueue it on a per-port list. If in transaction - * commit phase, dequeue the memory from the per-port list + * and enqueue it on a transaction. If in transaction + * commit phase, dequeue the memory from the transaction * rather than re-allocating the memory. The idea is the * driver code paths for prepare and commit are identical * so the memory allocated in the prepare phase is the @@ -361,17 +360,13 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port, if (!trans) { elem = kzalloc(size + sizeof(*elem), gfp_flags); - if (elem) - INIT_LIST_HEAD(elem); } else if (switchdev_trans_ph_prepare(trans)) { elem = kzalloc(size + sizeof(*elem), gfp_flags); if (!elem) return NULL; - list_add_tail(elem, &rocker_port->trans_mem); + switchdev_trans_item_enqueue(trans, elem, kfree, elem); } else { - BUG_ON(list_empty(&rocker_port->trans_mem)); - elem = rocker_port->trans_mem.next; - list_del_init(elem); + elem = switchdev_trans_item_dequeue(trans); } return elem ? elem + 1 : NULL; @@ -393,7 +388,7 @@ static void *rocker_port_kcalloc(struct rocker_port *rocker_port, static void rocker_port_kfree(struct switchdev_trans *trans, const void *mem) { - struct list_head *elem; + struct switchdev_trans_item *elem; /* Frees are ignored if in transaction prepare phase. The * memory remains on the per-port list until freed in the @@ -403,8 +398,7 @@ static void rocker_port_kfree(struct switchdev_trans *trans, const void *mem) if (switchdev_trans_ph_prepare(trans)) return; - elem = (struct list_head *)mem - 1; - BUG_ON(!list_empty(elem)); + elem = (struct switchdev_trans_item *) mem - 1; kfree(elem); } @@ -4349,16 +4343,6 @@ static int rocker_port_attr_get(struct net_device *dev, return 0; } -static void rocker_port_trans_abort(const struct rocker_port *rocker_port) -{ - struct list_head *mem, *tmp; - - list_for_each_safe(mem, tmp, &rocker_port->trans_mem) { - list_del(mem); - kfree(mem); - } -} - static int rocker_port_brport_flags_set(struct rocker_port *rocker_port, struct switchdev_trans *trans, unsigned long brport_flags) @@ -4384,17 +4368,6 @@ static int rocker_port_attr_set(struct net_device *dev, struct rocker_port *rocker_port = netdev_priv(dev); int err = 0; - switch (trans->ph) { - case SWITCHDEV_TRANS_PREPARE: - BUG_ON(!list_empty(&rocker_port->trans_mem)); - break; - case SWITCHDEV_TRANS_ABORT: - rocker_port_trans_abort(rocker_port); - return 0; - default: - break; - } - switch (attr->id) { case SWITCHDEV_ATTR_PORT_STP_STATE: err = rocker_port_stp_update(rocker_port, trans, @@ -4471,17 +4444,6 @@ static int rocker_port_obj_add(struct net_device *dev, const struct switchdev_obj_ipv4_fib *fib4; int err = 0; - switch (trans->ph) { - case SWITCHDEV_TRANS_PREPARE: - BUG_ON(!list_empty(&rocker_port->trans_mem)); - break; - case SWITCHDEV_TRANS_ABORT: - rocker_port_trans_abort(rocker_port); - return 0; - default: - break; - } - switch (obj->id) { case SWITCHDEV_OBJ_PORT_VLAN: err = rocker_port_vlans_add(rocker_port, trans, @@ -5010,7 +4972,6 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number) rocker_port->pport = port_number + 1; rocker_port->brport_flags = BR_LEARNING | BR_LEARNING_SYNC; rocker_port->ageing_time = BR_DEFAULT_AGEING_TIME; - INIT_LIST_HEAD(&rocker_port->trans_mem); rocker_port_dev_addr_init(rocker_port); dev->netdev_ops = &rocker_port_netdev_ops; -- cgit v1.2.3 From 029cd0370241641eb70235d205aa0b90c84dce44 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 24 Sep 2015 16:59:46 +0200 Subject: ath9k: declare required extra tx headroom ath9k inserts padding between the 802.11 header and the data area (to align it). Since it didn't declare this extra required headroom, this led to some nasty issues like randomly dropped packets in some setups. Cc: stable@vger.kernel.org Signed-off-by: Felix Fietkau Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/init.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 57f95f2dca5b..90eb75012e4f 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -880,6 +880,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->max_rate_tries = 10; hw->sta_data_size = sizeof(struct ath_node); hw->vif_data_size = sizeof(struct ath_vif); + hw->extra_tx_headroom = 4; hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1; hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1; -- cgit v1.2.3 From 910367e374b97fad6ae31f74198ca537e2f3cfe5 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 31 Aug 2015 10:55:05 +0200 Subject: rt2800usb: add usb ID 1b75:3070 for Airlive WT-2000USB Brand: Airlive (Ovislink Corp.) Name: Turbo-G USB Adaptor Model: WT-2000USB USB ID: 1b75:3070 Reported-and-tested-by: Michael Coates Signed-off-by: Stanislaw Gruszka Signed-off-by: Kalle Valo --- drivers/net/wireless/rt2x00/rt2800usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 5932306084fd..bf9afbf46c1b 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1114,6 +1114,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0db0, 0x871c) }, { USB_DEVICE(0x0db0, 0x899a) }, /* Ovislink */ + { USB_DEVICE(0x1b75, 0x3070) }, { USB_DEVICE(0x1b75, 0x3071) }, { USB_DEVICE(0x1b75, 0x3072) }, { USB_DEVICE(0x1b75, 0xa200) }, -- cgit v1.2.3 From c6ea46c6d3df06599daddbf3311744f3130e186c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 9 Sep 2015 07:16:42 +0200 Subject: b43: probe bcma core (device) rev 0x15 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenWrt user reported b43 doesn't probe wireless core on SoC BCM5356A1: [ 0.000000] bcma: bus0: Found chip with id 0x5356, rev 0x01 and package 0x04 it is because this chip uses different 802.11 core revison than others: [ 0.000000] bcma: bus0: Core 1 found: IEEE 802.11 (manuf 0x4BF, id 0x812, rev 0x15, class 0x0) Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/b43/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 28490702124a..71d3e9adbf3c 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -120,6 +120,7 @@ MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if over #ifdef CONFIG_B43_BCMA static const struct bcma_device_id b43_bcma_tbl[] = { BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS), + BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x15, BCMA_ANY_CLASS), BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS), BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS), BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1C, BCMA_ANY_CLASS), -- cgit v1.2.3 From 76d164f582150fd0259ec0fcbc485470bcd8033e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 17 Sep 2015 14:29:07 +0300 Subject: ath10k: fix DMA related firmware crashes on multiple devices Some platforms really don't like DMA bursts of 256 bytes, and this causes the firmware to crash when sending beacons. Also, changing this based on the firmware version does not seem to make much sense, so use 128 bytes for all versions. Cc: stable@vger.kernel.org Signed-off-by: Felix Fietkau Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/hw.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 23afcda2de96..678d72af4a9d 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -337,7 +337,7 @@ enum ath10k_hw_rate_cck { #define TARGET_10X_MAX_FRAG_ENTRIES 0 /* 10.2 parameters */ -#define TARGET_10_2_DMA_BURST_SIZE 1 +#define TARGET_10_2_DMA_BURST_SIZE 0 /* Target specific defines for WMI-TLV firmware */ #define TARGET_TLV_NUM_VDEVS 4 @@ -391,7 +391,7 @@ enum ath10k_hw_rate_cck { #define TARGET_10_4_TX_DBG_LOG_SIZE 1024 #define TARGET_10_4_NUM_WDS_ENTRIES 32 -#define TARGET_10_4_DMA_BURST_SIZE 1 +#define TARGET_10_4_DMA_BURST_SIZE 0 #define TARGET_10_4_MAC_AGGR_DELIM 0 #define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1 #define TARGET_10_4_VOW_CONFIG 0 -- cgit v1.2.3 From 5a58f227790faded5a3ef6075f3ddd65093e0f86 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 23 Sep 2015 09:46:09 +0100 Subject: 8139cp: Enable offload features by default I fixed TSO. Hardware checksum and scatter/gather also appear to be working correctly both on real hardware and in QEMU's emulation. Let's enable them by default and see if anyone screams... Signed-off-by: David Woodhouse Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/8139cp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index 686334f4588d..e5173f33428b 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -1983,12 +1983,12 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) dev->ethtool_ops = &cp_ethtool_ops; dev->watchdog_timeo = TX_TIMEOUT; - dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; + dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; if (pci_using_dac) dev->features |= NETIF_F_HIGHDMA; - /* disabled by default until verified */ dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | -- cgit v1.2.3 From 8b7a7048220f86547db31de0abe1ea6dd2cfa892 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 24 Sep 2015 11:38:22 +0100 Subject: 8139cp: Fix GSO MSS handling When fixing the TSO support I noticed we just mask ->gso_size with the MSSMask value and don't care about the consequences. Provide a .ndo_features_check() method which drops the NETIF_F_TSO feature for any skb which would exceed the maximum, and thus forces it to be segmented by software. Then we can stop the masking in cp_start_xmit(), and just WARN if the maximum is exceeded, which should now never happen. Finally, Francois Romieu noticed that we didn't even have the right value for MSSMask anyway; it should be 0x7ff (11 bits) not 0xfff. Signed-off-by: David Woodhouse Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/8139cp.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index e5173f33428b..deae10d7426d 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -175,7 +175,7 @@ enum { LastFrag = (1 << 28), /* Final segment of a packet */ LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ MSSShift = 16, /* MSS value position */ - MSSMask = 0xfff, /* MSS value: 11 bits */ + MSSMask = 0x7ff, /* MSS value: 11 bits */ TxError = (1 << 23), /* Tx error summary */ RxError = (1 << 20), /* Rx error summary */ IPCS = (1 << 18), /* Calculate IP checksum */ @@ -754,10 +754,16 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; mss = skb_shinfo(skb)->gso_size; + if (mss > MSSMask) { + WARN_ONCE(1, "Net bug: GSO size %d too large for 8139CP\n", + mss); + goto out_dma_error; + } + opts2 = cpu_to_le32(cp_tx_vlan_tag(skb)); opts1 = DescOwn; if (mss) - opts1 |= LargeSend | ((mss & MSSMask) << MSSShift); + opts1 |= LargeSend | (mss << MSSShift); else if (skb->ip_summed == CHECKSUM_PARTIAL) { const struct iphdr *ip = ip_hdr(skb); if (ip->protocol == IPPROTO_TCP) @@ -1852,6 +1858,15 @@ static void cp_set_d3_state (struct cp_private *cp) pci_set_power_state (cp->pdev, PCI_D3hot); } +static netdev_features_t cp_features_check(struct sk_buff *skb, + struct net_device *dev, + netdev_features_t features) +{ + if (skb_shinfo(skb)->gso_size > MSSMask) + features &= ~NETIF_F_TSO; + + return vlan_features_check(skb, features); +} static const struct net_device_ops cp_netdev_ops = { .ndo_open = cp_open, .ndo_stop = cp_close, @@ -1864,6 +1879,7 @@ static const struct net_device_ops cp_netdev_ops = { .ndo_tx_timeout = cp_tx_timeout, .ndo_set_features = cp_set_features, .ndo_change_mtu = cp_change_mtu, + .ndo_features_check = cp_features_check, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = cp_poll_controller, -- cgit v1.2.3 From 205f356d165033443793a97a668a203a79a8723a Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Thu, 24 Sep 2015 13:50:01 +0200 Subject: vxlan: make vxlan_sock_add and vxlan_sock_release complementary Make vxlan_sock_add both alloc the socket and attach it to vxlan_dev. Let vxlan_sock_release accept vxlan_dev as its parameter instead of vxlan_sock. This makes vxlan_sock_add and vxlan_sock release complementary. It reduces code duplication in the next patch. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 53 +++++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index bbac1d35ed4e..a86613011977 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -75,8 +75,7 @@ static struct rtnl_link_ops vxlan_link_ops; static const u8 all_zeros_mac[ETH_ALEN]; -static struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, - bool no_share, u32 flags); +static int vxlan_sock_add(struct vxlan_dev *vxlan); /* per-network namespace private data for this module */ struct vxlan_net { @@ -1022,8 +1021,9 @@ static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev) return false; } -static void vxlan_sock_release(struct vxlan_sock *vs) +static void vxlan_sock_release(struct vxlan_dev *vxlan) { + struct vxlan_sock *vs = vxlan->vn_sock; struct sock *sk = vs->sock->sk; struct net *net = sock_net(sk); struct vxlan_net *vn = net_generic(net, vxlan_net_id); @@ -2244,22 +2244,18 @@ static void vxlan_uninit(struct net_device *dev) static int vxlan_open(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); - struct vxlan_sock *vs; - int ret = 0; - - vs = vxlan_sock_add(vxlan->net, vxlan->cfg.dst_port, - vxlan->cfg.no_share, vxlan->flags); - if (IS_ERR(vs)) - return PTR_ERR(vs); + int ret; - vxlan_vs_add_dev(vs, vxlan); + ret = vxlan_sock_add(vxlan); + if (ret < 0) + return ret; if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) { ret = vxlan_igmp_join(vxlan); if (ret == -EADDRINUSE) ret = 0; if (ret) { - vxlan_sock_release(vs); + vxlan_sock_release(vxlan); return ret; } } @@ -2294,7 +2290,6 @@ static int vxlan_stop(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); - struct vxlan_sock *vs = vxlan->vn_sock; int ret = 0; if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) && @@ -2304,7 +2299,7 @@ static int vxlan_stop(struct net_device *dev) del_timer_sync(&vxlan->age_timer); vxlan_flush(vxlan); - vxlan_sock_release(vs); + vxlan_sock_release(vxlan); return ret; } @@ -2592,27 +2587,29 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, return vs; } -static struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, - bool no_share, u32 flags) +static int vxlan_sock_add(struct vxlan_dev *vxlan) { - struct vxlan_net *vn = net_generic(net, vxlan_net_id); - struct vxlan_sock *vs; - bool ipv6 = flags & VXLAN_F_IPV6; + struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); + struct vxlan_sock *vs = NULL; + bool ipv6 = vxlan->flags & VXLAN_F_IPV6; - if (!no_share) { + if (!vxlan->cfg.no_share) { spin_lock(&vn->sock_lock); - vs = vxlan_find_sock(net, ipv6 ? AF_INET6 : AF_INET, port, - flags); - if (vs) { - if (!atomic_add_unless(&vs->refcnt, 1, 0)) - vs = ERR_PTR(-EBUSY); + vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET, + vxlan->cfg.dst_port, vxlan->flags); + if (vs && !atomic_add_unless(&vs->refcnt, 1, 0)) { spin_unlock(&vn->sock_lock); - return vs; + return -EBUSY; } spin_unlock(&vn->sock_lock); } - - return vxlan_socket_create(net, port, flags); + if (!vs) + vs = vxlan_socket_create(vxlan->net, vxlan->cfg.dst_port, + vxlan->flags); + if (IS_ERR(vs)) + return PTR_ERR(vs); + vxlan_vs_add_dev(vs, vxlan); + return 0; } static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, -- cgit v1.2.3 From b1be00a6c39fda2ec380e168d7bcf96fb8c9da42 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Thu, 24 Sep 2015 13:50:02 +0200 Subject: vxlan: support both IPv4 and IPv6 sockets in a single vxlan device For metadata based vxlan interface, open both IPv4 and IPv6 socket. This is much more user friendly: it's not necessary to create two vxlan interfaces and pay attention to using the right one in routing rules. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 128 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 90 insertions(+), 38 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index a86613011977..ce704df7681b 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -993,19 +993,30 @@ static bool vxlan_snoop(struct net_device *dev, static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev) { struct vxlan_dev *vxlan; + unsigned short family = dev->default_dst.remote_ip.sa.sa_family; /* The vxlan_sock is only used by dev, leaving group has * no effect on other vxlan devices. */ - if (atomic_read(&dev->vn_sock->refcnt) == 1) + if (family == AF_INET && dev->vn4_sock && + atomic_read(&dev->vn4_sock->refcnt) == 1) return false; +#if IS_ENABLED(CONFIG_IPV6) + if (family == AF_INET6 && dev->vn6_sock && + atomic_read(&dev->vn6_sock->refcnt) == 1) + return false; +#endif list_for_each_entry(vxlan, &vn->vxlan_list, next) { if (!netif_running(vxlan->dev) || vxlan == dev) continue; - if (vxlan->vn_sock != dev->vn_sock) + if (family == AF_INET && vxlan->vn4_sock != dev->vn4_sock) continue; +#if IS_ENABLED(CONFIG_IPV6) + if (family == AF_INET6 && vxlan->vn6_sock != dev->vn6_sock) + continue; +#endif if (!vxlan_addr_equal(&vxlan->default_dst.remote_ip, &dev->default_dst.remote_ip)) @@ -1021,16 +1032,16 @@ static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev) return false; } -static void vxlan_sock_release(struct vxlan_dev *vxlan) +static void __vxlan_sock_release(struct vxlan_sock *vs) { - struct vxlan_sock *vs = vxlan->vn_sock; - struct sock *sk = vs->sock->sk; - struct net *net = sock_net(sk); - struct vxlan_net *vn = net_generic(net, vxlan_net_id); + struct vxlan_net *vn; + if (!vs) + return; if (!atomic_dec_and_test(&vs->refcnt)) return; + vn = net_generic(sock_net(vs->sock->sk), vxlan_net_id); spin_lock(&vn->sock_lock); hlist_del_rcu(&vs->hlist); vxlan_notify_del_rx_port(vs); @@ -1039,32 +1050,43 @@ static void vxlan_sock_release(struct vxlan_dev *vxlan) queue_work(vxlan_wq, &vs->del_work); } +static void vxlan_sock_release(struct vxlan_dev *vxlan) +{ + __vxlan_sock_release(vxlan->vn4_sock); +#if IS_ENABLED(CONFIG_IPV6) + __vxlan_sock_release(vxlan->vn6_sock); +#endif +} + /* Update multicast group membership when first VNI on * multicast address is brought up */ static int vxlan_igmp_join(struct vxlan_dev *vxlan) { - struct vxlan_sock *vs = vxlan->vn_sock; - struct sock *sk = vs->sock->sk; + struct sock *sk; union vxlan_addr *ip = &vxlan->default_dst.remote_ip; int ifindex = vxlan->default_dst.remote_ifindex; int ret = -EINVAL; - lock_sock(sk); if (ip->sa.sa_family == AF_INET) { struct ip_mreqn mreq = { .imr_multiaddr.s_addr = ip->sin.sin_addr.s_addr, .imr_ifindex = ifindex, }; + sk = vxlan->vn4_sock->sock->sk; + lock_sock(sk); ret = ip_mc_join_group(sk, &mreq); + release_sock(sk); #if IS_ENABLED(CONFIG_IPV6) } else { + sk = vxlan->vn6_sock->sock->sk; + lock_sock(sk); ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex, &ip->sin6.sin6_addr); + release_sock(sk); #endif } - release_sock(sk); return ret; } @@ -1072,27 +1094,30 @@ static int vxlan_igmp_join(struct vxlan_dev *vxlan) /* Inverse of vxlan_igmp_join when last VNI is brought down */ static int vxlan_igmp_leave(struct vxlan_dev *vxlan) { - struct vxlan_sock *vs = vxlan->vn_sock; - struct sock *sk = vs->sock->sk; + struct sock *sk; union vxlan_addr *ip = &vxlan->default_dst.remote_ip; int ifindex = vxlan->default_dst.remote_ifindex; int ret = -EINVAL; - lock_sock(sk); if (ip->sa.sa_family == AF_INET) { struct ip_mreqn mreq = { .imr_multiaddr.s_addr = ip->sin.sin_addr.s_addr, .imr_ifindex = ifindex, }; + sk = vxlan->vn4_sock->sock->sk; + lock_sock(sk); ret = ip_mc_leave_group(sk, &mreq); + release_sock(sk); #if IS_ENABLED(CONFIG_IPV6) } else { + sk = vxlan->vn6_sock->sock->sk; + lock_sock(sk); ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex, &ip->sin6.sin6_addr); + release_sock(sk); #endif } - release_sock(sk); return ret; } @@ -1873,8 +1898,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, { struct ip_tunnel_info *info; struct vxlan_dev *vxlan = netdev_priv(dev); - struct sock *sk = vxlan->vn_sock->sock->sk; - unsigned short family = vxlan_get_sk_family(vxlan->vn_sock); + struct sock *sk; struct rtable *rt = NULL; const struct iphdr *old_iph; struct flowi4 fl4; @@ -1901,13 +1925,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dev->name); goto drop; } - if (family != ip_tunnel_info_af(info)) - goto drop; - dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; vni = be64_to_cpu(info->key.tun_id); - remote_ip.sa.sa_family = family; - if (family == AF_INET) + remote_ip.sa.sa_family = ip_tunnel_info_af(info); + if (remote_ip.sa.sa_family == AF_INET) remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst; else remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst; @@ -1952,6 +1973,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, } if (dst->sa.sa_family == AF_INET) { + if (!vxlan->vn4_sock) + goto drop; + sk = vxlan->vn4_sock->sock->sk; + if (info && (info->key.tun_flags & TUNNEL_DONT_FRAGMENT)) df = htons(IP_DF); @@ -2013,6 +2038,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, struct flowi6 fl6; u32 rt6i_flags; + if (!vxlan->vn6_sock) + goto drop; + sk = vxlan->vn6_sock->sock->sk; + memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_oif = rdst ? rdst->remote_ifindex : 0; fl6.daddr = dst->sin6.sin6_addr; @@ -2204,7 +2233,6 @@ static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan) struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); __u32 vni = vxlan->default_dst.remote_vni; - vxlan->vn_sock = vs; spin_lock(&vn->sock_lock); hlist_add_head_rcu(&vxlan->hlist, vni_head(vs, vni)); spin_unlock(&vn->sock_lock); @@ -2535,14 +2563,13 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6, } /* Create new listen socket if needed */ -static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, - u32 flags) +static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6, + __be16 port, u32 flags) { struct vxlan_net *vn = net_generic(net, vxlan_net_id); struct vxlan_sock *vs; struct socket *sock; unsigned int h; - bool ipv6 = !!(flags & VXLAN_F_IPV6); struct udp_tunnel_sock_cfg tunnel_cfg; vs = kzalloc(sizeof(*vs), GFP_KERNEL); @@ -2587,11 +2614,10 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, return vs; } -static int vxlan_sock_add(struct vxlan_dev *vxlan) +static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6) { struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); struct vxlan_sock *vs = NULL; - bool ipv6 = vxlan->flags & VXLAN_F_IPV6; if (!vxlan->cfg.no_share) { spin_lock(&vn->sock_lock); @@ -2604,20 +2630,46 @@ static int vxlan_sock_add(struct vxlan_dev *vxlan) spin_unlock(&vn->sock_lock); } if (!vs) - vs = vxlan_socket_create(vxlan->net, vxlan->cfg.dst_port, - vxlan->flags); + vs = vxlan_socket_create(vxlan->net, ipv6, + vxlan->cfg.dst_port, vxlan->flags); if (IS_ERR(vs)) return PTR_ERR(vs); +#if IS_ENABLED(CONFIG_IPV6) + if (ipv6) + vxlan->vn6_sock = vs; + else +#endif + vxlan->vn4_sock = vs; vxlan_vs_add_dev(vs, vxlan); return 0; } +static int vxlan_sock_add(struct vxlan_dev *vxlan) +{ + bool ipv6 = vxlan->flags & VXLAN_F_IPV6; + bool metadata = vxlan->flags & VXLAN_F_COLLECT_METADATA; + int ret = 0; + + vxlan->vn4_sock = NULL; +#if IS_ENABLED(CONFIG_IPV6) + vxlan->vn6_sock = NULL; + if (ipv6 || metadata) + ret = __vxlan_sock_add(vxlan, true); +#endif + if (!ret && (!ipv6 || metadata)) + ret = __vxlan_sock_add(vxlan, false); + if (ret < 0) + vxlan_sock_release(vxlan); + return ret; +} + static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, struct vxlan_config *conf) { struct vxlan_net *vn = net_generic(src_net, vxlan_net_id); struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_rdst *dst = &vxlan->default_dst; + unsigned short needed_headroom = ETH_HLEN; int err; bool use_ipv6 = false; __be16 default_port = vxlan->cfg.dst_port; @@ -2637,6 +2689,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, if (!IS_ENABLED(CONFIG_IPV6)) return -EPFNOSUPPORT; use_ipv6 = true; + vxlan->flags |= VXLAN_F_IPV6; } if (conf->remote_ifindex) { @@ -2657,22 +2710,21 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, pr_info("IPv6 is disabled via sysctl\n"); return -EPERM; } - vxlan->flags |= VXLAN_F_IPV6; } #endif if (!conf->mtu) dev->mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); - dev->needed_headroom = lowerdev->hard_header_len + - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); - } else if (use_ipv6) { - vxlan->flags |= VXLAN_F_IPV6; - dev->needed_headroom = ETH_HLEN + VXLAN6_HEADROOM; - } else { - dev->needed_headroom = ETH_HLEN + VXLAN_HEADROOM; + needed_headroom = lowerdev->hard_header_len; } + if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA) + needed_headroom += VXLAN6_HEADROOM; + else + needed_headroom += VXLAN_HEADROOM; + dev->needed_headroom = needed_headroom; + memcpy(&vxlan->cfg, conf, sizeof(*conf)); if (!vxlan->cfg.dst_port) vxlan->cfg.dst_port = default_port; -- cgit v1.2.3 From b0b252278082787eec54098556566d4d68b8126c Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Thu, 17 Sep 2015 14:29:07 +0300 Subject: ath: fix incorrect PPB on JAPAN chirp radar The number of pulses per burst on Japan chirp radar is between 1 and 3. The previous value, 20, is representing number of bursts, but since current DFS detector is using pulse detection other than bursts, use the pulse number for correct radar detection. Also using the highest number helps to avoid false detection. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/dfs_pattern_detector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c index 656ce42b339a..5aa053ab8467 100644 --- a/drivers/net/wireless/ath/dfs_pattern_detector.c +++ b/drivers/net/wireless/ath/dfs_pattern_detector.c @@ -121,7 +121,7 @@ static const struct radar_detector_specs jp_radar_ref_types[] = { JP_PATTERN(4, 0, 5, 150, 230, 1, 23, 50, false), JP_PATTERN(5, 6, 10, 200, 500, 1, 16, 50, false), JP_PATTERN(6, 11, 20, 200, 500, 1, 12, 50, false), - JP_PATTERN(7, 50, 100, 1000, 2000, 1, 20, 50, false), + JP_PATTERN(7, 50, 100, 1000, 2000, 1, 3, 50, false), JP_PATTERN(5, 0, 1, 333, 333, 1, 9, 50, false), }; -- cgit v1.2.3 From 44acedb00b6d4b56ddab04362ccfa133b0d3b013 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Thu, 17 Sep 2015 14:29:08 +0300 Subject: ath: use PRI value given by spec for fixed PRI PRI value is used as divider when DFS detector analyzes candidate radar pulses. If PRI deviation is big from its origin PRI, DFS detector could miss valid radar reports since HW often misses detecting radar pulses and causes long interval value of pulses. For instance from practical results, if runtime PRI is calculated as 1431 for fixed PRI value of 1428 and delta timestamp logs 15719, the modular remainder will be 1409 and the delta between the remainder and runtime PRI is 22 that is bigger than PRI tolerance which is 16. As a result this radar report will be ignored even though it's valid. By using spec defined PRI for fixed PRI, we can correct this error. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/dfs_pattern_detector.c | 6 ------ drivers/net/wireless/ath/dfs_pattern_detector.h | 5 +++++ drivers/net/wireless/ath/dfs_pri_detector.c | 6 +++++- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c index 5aa053ab8467..9d687121b2bf 100644 --- a/drivers/net/wireless/ath/dfs_pattern_detector.c +++ b/drivers/net/wireless/ath/dfs_pattern_detector.c @@ -21,12 +21,6 @@ #include "dfs_pri_detector.h" #include "ath.h" -/* - * tolerated deviation of radar time stamp in usecs on both sides - * TODO: this might need to be HW-dependent - */ -#define PRI_TOLERANCE 16 - /** * struct radar_types - contains array of patterns defined for one DFS domain * @domain: DFS regulatory domain diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.h b/drivers/net/wireless/ath/dfs_pattern_detector.h index 25a43d632f90..92be3530e9b5 100644 --- a/drivers/net/wireless/ath/dfs_pattern_detector.h +++ b/drivers/net/wireless/ath/dfs_pattern_detector.h @@ -21,6 +21,11 @@ #include #include +/* tolerated deviation of radar time stamp in usecs on both sides + * TODO: this might need to be HW-dependent + */ +#define PRI_TOLERANCE 16 + /** * struct ath_dfs_pool_stats - DFS Statistics for global pools */ diff --git a/drivers/net/wireless/ath/dfs_pri_detector.c b/drivers/net/wireless/ath/dfs_pri_detector.c index cc5c592fc4c0..05b0464c6b92 100644 --- a/drivers/net/wireless/ath/dfs_pri_detector.c +++ b/drivers/net/wireless/ath/dfs_pri_detector.c @@ -25,6 +25,9 @@ struct ath_dfs_pool_stats global_dfs_pool_stats = {}; #define DFS_POOL_STAT_INC(c) (global_dfs_pool_stats.c++) #define DFS_POOL_STAT_DEC(c) (global_dfs_pool_stats.c--) +#define GET_PRI_TO_USE(MIN, MAX, RUNTIME) \ + (MIN + PRI_TOLERANCE == MAX - PRI_TOLERANCE ? \ + MIN + PRI_TOLERANCE : RUNTIME) /** * struct pulse_elem - elements in pulse queue @@ -243,7 +246,8 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde, ps.count_falses = 0; ps.first_ts = p->ts; ps.last_ts = ts; - ps.pri = ts - p->ts; + ps.pri = GET_PRI_TO_USE(pde->rs->pri_min, + pde->rs->pri_max, ts - p->ts); ps.dur = ps.pri * (pde->rs->ppb - 1) + 2 * pde->rs->max_pri_tolerance; -- cgit v1.2.3 From bd4a41e6dee43b5b00876e37d42abffa298d63fe Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Wed, 16 Sep 2015 13:19:00 +0530 Subject: ath10k: fix ldpc param for fixed rate ldpc is not configured for fixed rates. This blocks auto rate vs fixed rate performance comparison. Since firmware is considering ldpc vdev param for fixed rate selection, it has to be configured to enable ldpc for fixed rates. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index bb4416186b2b..3f6c1c42a70f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -5957,7 +5957,7 @@ ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar, } static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif, - u8 rate, u8 nss, u8 sgi) + u8 rate, u8 nss, u8 sgi, u8 ldpc) { struct ath10k *ar = arvif->ar; u32 vdev_param; @@ -5990,6 +5990,13 @@ static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif, return ret; } + vdev_param = ar->wmi.vdev_param->ldpc; + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, ldpc); + if (ret) { + ath10k_warn(ar, "failed to set ldpc param %d: %d\n", ldpc, ret); + return ret; + } + return 0; } @@ -6053,6 +6060,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, u8 rate; u8 nss; u8 sgi; + u8 ldpc; int single_nss; int ret; @@ -6062,6 +6070,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, band = def.chan->band; ht_mcs_mask = mask->control[band].ht_mcs; vht_mcs_mask = mask->control[band].vht_mcs; + ldpc = !!(ar->ht_cap_info & WMI_HT_CAP_LDPC); sgi = mask->control[band].gi; if (sgi == NL80211_TXRATE_FORCE_LGI) @@ -6100,7 +6109,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); - ret = ath10k_mac_set_fixed_rate_params(arvif, rate, nss, sgi); + ret = ath10k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc); if (ret) { ath10k_warn(ar, "failed to set fixed rate params on vdev %i: %d\n", arvif->vdev_id, ret); -- cgit v1.2.3 From b8402d827fbb288f4ecee585e151bab5a81b3c58 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Thu, 17 Sep 2015 08:17:33 +0200 Subject: ath10k: fix MSI-X registering for qca99x0 In case of qca99x0 and MSI-X supported/enabled we failed during interrupts registering with message: ath10k_pci 0000:04:00.0: failed to request MSI-X ce irq 50: -22 Issue/fix was reproduced/tested using Dell Latitude E6430 laptop. Signed-off-by: Janusz Dziedzic Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/hw.h | 10 ---------- drivers/net/wireless/ath/ath10k/pci.c | 18 +++++------------- 2 files changed, 5 insertions(+), 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 23afcda2de96..bc421a5c5356 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -413,16 +413,6 @@ enum ath10k_hw_rate_cck { /* Number of Copy Engines supported */ #define CE_COUNT ar->hw_values->ce_count -/* - * Total number of PCIe MSI interrupts requested for all interrupt sources. - * PCIe standard forces this to be a power of 2. - * Some Host OS's limit MSI requests that can be granted to 8 - * so for now we abide by this limit and avoid requesting more - * than that. - */ -#define MSI_NUM_REQUEST_LOG2 3 -#define MSI_NUM_REQUEST (1<num_msi_intrs = MSI_NUM_REQUEST; + ar_pci->num_msi_intrs = MSI_ASSIGN_CE_MAX + 1; ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs, ar_pci->num_msi_intrs); if (ret > 0) @@ -2705,18 +2702,13 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar) switch (ar_pci->num_msi_intrs) { case 0: ath10k_pci_deinit_irq_legacy(ar); - return 0; - case 1: - /* fall-through */ - case MSI_NUM_REQUEST: - pci_disable_msi(ar_pci->pdev); - return 0; + break; default: pci_disable_msi(ar_pci->pdev); + break; } - ath10k_warn(ar, "unknown irq configuration upon deinit\n"); - return -EINVAL; + return 0; } static int ath10k_pci_wait_for_target_init(struct ath10k *ar) -- cgit v1.2.3 From 1e6d6f8c1b07a5874444c3a403eb24427e8b39d3 Mon Sep 17 00:00:00 2001 From: Kiran Patil Date: Thu, 24 Sep 2015 15:43:02 -0400 Subject: i40e: Move i40e_get_head into header file i40e_get_head needs to be called in multiple files in a further patch, prepare by moving the function into a header file. Signed-off-by: Kiran Patil Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 13 ------------- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 738aca68f665..9a800f99ec13 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -600,19 +600,6 @@ void i40e_free_tx_resources(struct i40e_ring *tx_ring) } } -/** - * i40e_get_head - Retrieve head from head writeback - * @tx_ring: tx ring to fetch head of - * - * Returns value of Tx ring head based on value stored - * in head write-back location - **/ -static inline u32 i40e_get_head(struct i40e_ring *tx_ring) -{ - void *head = (struct i40e_tx_desc *)tx_ring->desc + tx_ring->count; - - return le32_to_cpu(*(volatile __le32 *)head); -} /** * i40e_get_tx_pending - how many tx descriptors not processed diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index f1385a1989fa..51487ef9eda3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -326,4 +326,18 @@ int i40e_xmit_descriptor_count(struct sk_buff *skb, struct i40e_ring *tx_ring); int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, struct i40e_ring *tx_ring, u32 *flags); #endif + +/** + * i40e_get_head - Retrieve head from head writeback + * @tx_ring: tx ring to fetch head of + * + * Returns value of Tx ring head based on value stored + * in head write-back location + **/ +static inline u32 i40e_get_head(struct i40e_ring *tx_ring) +{ + void *head = (struct i40e_tx_desc *)tx_ring->desc + tx_ring->count; + + return le32_to_cpu(*(volatile __le32 *)head); +} #endif /* _I40E_TXRX_H_ */ -- cgit v1.2.3 From b03a8c1f4c0c6f95f5addaf4a13dd3aa118c3c1a Mon Sep 17 00:00:00 2001 From: Kiran Patil Date: Thu, 24 Sep 2015 18:13:15 -0400 Subject: i40e/i40evf: refactor tx timeout logic This patch modifies the driver timeout logic by issuing a writeback request via a software interrupt to the hardware the first time the driver detects a hang. The driver was too aggressive in resetting a hung queue, so back that off by removing logic to down the netdevice after too many hangs, and move the function to the service task. Change-ID: Ife100b9d124cd08cbdb81ab659008c1b9abbedea Signed-off-by: Kiran Patil Signed-off-by: Shannon Nelson Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 - drivers/net/ethernet/intel/i40e/i40e_main.c | 272 +++++++++++++++----------- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 75 +------ drivers/net/ethernet/intel/i40e/i40e_txrx.h | 10 +- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 94 +-------- drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 8 - 6 files changed, 173 insertions(+), 287 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index e7462793d48d..4797269d1200 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -243,7 +243,6 @@ struct i40e_pf { struct pci_dev *pdev; struct i40e_hw hw; unsigned long state; - unsigned long link_check_timeout; struct msix_entry *msix_entries; bool fc_autoneg_status; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 530d8b6739f9..c246dca5de71 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -299,25 +299,69 @@ static void i40e_tx_timeout(struct net_device *netdev) struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_vsi *vsi = np->vsi; struct i40e_pf *pf = vsi->back; + struct i40e_ring *tx_ring = NULL; + unsigned int i, hung_queue = 0; + u32 head, val; pf->tx_timeout_count++; + /* find the stopped queue the same way the stack does */ + for (i = 0; i < netdev->num_tx_queues; i++) { + struct netdev_queue *q; + unsigned long trans_start; + + q = netdev_get_tx_queue(netdev, i); + trans_start = q->trans_start ? : netdev->trans_start; + if (netif_xmit_stopped(q) && + time_after(jiffies, + (trans_start + netdev->watchdog_timeo))) { + hung_queue = i; + break; + } + } + + if (i == netdev->num_tx_queues) { + netdev_info(netdev, "tx_timeout: no netdev hung queue found\n"); + } else { + /* now that we have an index, find the tx_ring struct */ + for (i = 0; i < vsi->num_queue_pairs; i++) { + if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) { + if (hung_queue == + vsi->tx_rings[i]->queue_index) { + tx_ring = vsi->tx_rings[i]; + break; + } + } + } + } + if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ*20))) - pf->tx_timeout_recovery_level = 1; + pf->tx_timeout_recovery_level = 1; /* reset after some time */ + else if (time_before(jiffies, + (pf->tx_timeout_last_recovery + netdev->watchdog_timeo))) + return; /* don't do any new action before the next timeout */ + + if (tx_ring) { + head = i40e_get_head(tx_ring); + /* Read interrupt register */ + if (pf->flags & I40E_FLAG_MSIX_ENABLED) + val = rd32(&pf->hw, + I40E_PFINT_DYN_CTLN(tx_ring->q_vector->v_idx + + tx_ring->vsi->base_vector - 1)); + else + val = rd32(&pf->hw, I40E_PFINT_DYN_CTL0); + + netdev_info(netdev, "tx_timeout: VSI_seid: %d, Q %d, NTC: 0x%x, HWB: 0x%x, NTU: 0x%x, TAIL: 0x%x, INT: 0x%x\n", + vsi->seid, hung_queue, tx_ring->next_to_clean, + head, tx_ring->next_to_use, + readl(tx_ring->tail), val); + } + pf->tx_timeout_last_recovery = jiffies; - netdev_info(netdev, "tx_timeout recovery level %d\n", - pf->tx_timeout_recovery_level); + netdev_info(netdev, "tx_timeout recovery level %d, hung_queue %d\n", + pf->tx_timeout_recovery_level, hung_queue); switch (pf->tx_timeout_recovery_level) { - case 0: - /* disable and re-enable queues for the VSI */ - if (in_interrupt()) { - set_bit(__I40E_REINIT_REQUESTED, &pf->state); - set_bit(__I40E_REINIT_REQUESTED, &vsi->state); - } else { - i40e_vsi_reinit_locked(vsi); - } - break; case 1: set_bit(__I40E_PF_RESET_REQUESTED, &pf->state); break; @@ -329,10 +373,9 @@ static void i40e_tx_timeout(struct net_device *netdev) break; default: netdev_err(netdev, "tx_timeout recovery unsuccessful\n"); - set_bit(__I40E_DOWN_REQUESTED, &pf->state); - set_bit(__I40E_DOWN_REQUESTED, &vsi->state); break; } + i40e_service_event_schedule(pf); pf->tx_timeout_recovery_level++; } @@ -754,7 +797,6 @@ static void i40e_update_link_xoff_rx(struct i40e_pf *pf) struct i40e_hw_port_stats *nsd = &pf->stats; struct i40e_hw *hw = &pf->hw; u64 xoff = 0; - u16 i, v; if ((hw->fc.current_mode != I40E_FC_FULL) && (hw->fc.current_mode != I40E_FC_RX_PAUSE)) @@ -769,18 +811,6 @@ static void i40e_update_link_xoff_rx(struct i40e_pf *pf) if (!(nsd->link_xoff_rx - xoff)) return; - /* Clear the __I40E_HANG_CHECK_ARMED bit for all Tx rings */ - for (v = 0; v < pf->num_alloc_vsi; v++) { - struct i40e_vsi *vsi = pf->vsi[v]; - - if (!vsi || !vsi->tx_rings[0]) - continue; - - for (i = 0; i < vsi->num_queue_pairs; i++) { - struct i40e_ring *ring = vsi->tx_rings[i]; - clear_bit(__I40E_HANG_CHECK_ARMED, &ring->state); - } - } } /** @@ -796,7 +826,7 @@ static void i40e_update_prio_xoff_rx(struct i40e_pf *pf) bool xoff[I40E_MAX_TRAFFIC_CLASS] = {false}; struct i40e_dcbx_config *dcb_cfg; struct i40e_hw *hw = &pf->hw; - u16 i, v; + u16 i; u8 tc; dcb_cfg = &hw->local_dcbx_config; @@ -821,23 +851,6 @@ static void i40e_update_prio_xoff_rx(struct i40e_pf *pf) tc = dcb_cfg->etscfg.prioritytable[i]; xoff[tc] = true; } - - /* Clear the __I40E_HANG_CHECK_ARMED bit for Tx rings */ - for (v = 0; v < pf->num_alloc_vsi; v++) { - struct i40e_vsi *vsi = pf->vsi[v]; - - if (!vsi || !vsi->tx_rings[0]) - continue; - - for (i = 0; i < vsi->num_queue_pairs; i++) { - struct i40e_ring *ring = vsi->tx_rings[i]; - - tc = ring->dcb_tc; - if (xoff[tc]) - clear_bit(__I40E_HANG_CHECK_ARMED, - &ring->state); - } - } } /** @@ -2609,8 +2622,6 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring) wr32(hw, I40E_QTX_CTL(pf_q), qtx_ctl); i40e_flush(hw); - clear_bit(__I40E_HANG_CHECK_ARMED, &ring->state); - /* cache tail off for easier writes later */ ring->tail = hw->hw_addr + I40E_QTX_TAIL(pf_q); @@ -4145,6 +4156,108 @@ static int i40e_pf_wait_txq_disabled(struct i40e_pf *pf) } #endif + +/** + * i40e_detect_recover_hung_queue - Function to detect and recover hung_queue + * @q_idx: TX queue number + * @vsi: Pointer to VSI struct + * + * This function checks specified queue for given VSI. Detects hung condition. + * Sets hung bit since it is two step process. Before next run of service task + * if napi_poll runs, it reset 'hung' bit for respective q_vector. If not, + * hung condition remain unchanged and during subsequent run, this function + * issues SW interrupt to recover from hung condition. + **/ +static void i40e_detect_recover_hung_queue(int q_idx, struct i40e_vsi *vsi) +{ + struct i40e_ring *tx_ring = NULL; + struct i40e_pf *pf; + u32 head, val, tx_pending; + int i; + + pf = vsi->back; + + /* now that we have an index, find the tx_ring struct */ + for (i = 0; i < vsi->num_queue_pairs; i++) { + if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) { + if (q_idx == vsi->tx_rings[i]->queue_index) { + tx_ring = vsi->tx_rings[i]; + break; + } + } + } + + if (!tx_ring) + return; + + /* Read interrupt register */ + if (pf->flags & I40E_FLAG_MSIX_ENABLED) + val = rd32(&pf->hw, + I40E_PFINT_DYN_CTLN(tx_ring->q_vector->v_idx + + tx_ring->vsi->base_vector - 1)); + else + val = rd32(&pf->hw, I40E_PFINT_DYN_CTL0); + + head = i40e_get_head(tx_ring); + + tx_pending = i40e_get_tx_pending(tx_ring); + + /* Interrupts are disabled and TX pending is non-zero, + * trigger the SW interrupt (don't wait). Worst case + * there will be one extra interrupt which may result + * into not cleaning any queues because queues are cleaned. + */ + if (tx_pending && (!(val & I40E_PFINT_DYN_CTLN_INTENA_MASK))) + i40e_force_wb(vsi, tx_ring->q_vector); +} + +/** + * i40e_detect_recover_hung - Function to detect and recover hung_queues + * @pf: pointer to PF struct + * + * LAN VSI has netdev and netdev has TX queues. This function is to check + * each of those TX queues if they are hung, trigger recovery by issuing + * SW interrupt. + **/ +static void i40e_detect_recover_hung(struct i40e_pf *pf) +{ + struct net_device *netdev; + struct i40e_vsi *vsi; + int i; + + /* Only for LAN VSI */ + vsi = pf->vsi[pf->lan_vsi]; + + if (!vsi) + return; + + /* Make sure, VSI state is not DOWN/RECOVERY_PENDING */ + if (test_bit(__I40E_DOWN, &vsi->back->state) || + test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state)) + return; + + /* Make sure type is MAIN VSI */ + if (vsi->type != I40E_VSI_MAIN) + return; + + netdev = vsi->netdev; + if (!netdev) + return; + + /* Bail out if netif_carrier is not OK */ + if (!netif_carrier_ok(netdev)) + return; + + /* Go thru' TX queues for netdev */ + for (i = 0; i < netdev->num_tx_queues; i++) { + struct netdev_queue *q; + + q = netdev_get_tx_queue(netdev, i); + if (q) + i40e_detect_recover_hung_queue(i, vsi); + } +} + /** * i40e_get_iscsi_tc_map - Return TC map for iSCSI APP * @pf: pointer to PF @@ -5758,68 +5871,6 @@ static void i40e_link_event(struct i40e_pf *pf) i40e_ptp_set_increment(pf); } -/** - * i40e_check_hang_subtask - Check for hung queues and dropped interrupts - * @pf: board private structure - * - * Set the per-queue flags to request a check for stuck queues in the irq - * clean functions, then force interrupts to be sure the irq clean is called. - **/ -static void i40e_check_hang_subtask(struct i40e_pf *pf) -{ - int i, v; - - /* If we're down or resetting, just bail */ - if (test_bit(__I40E_DOWN, &pf->state) || - test_bit(__I40E_CONFIG_BUSY, &pf->state)) - return; - - /* for each VSI/netdev - * for each Tx queue - * set the check flag - * for each q_vector - * force an interrupt - */ - for (v = 0; v < pf->num_alloc_vsi; v++) { - struct i40e_vsi *vsi = pf->vsi[v]; - int armed = 0; - - if (!pf->vsi[v] || - test_bit(__I40E_DOWN, &vsi->state) || - (vsi->netdev && !netif_carrier_ok(vsi->netdev))) - continue; - - for (i = 0; i < vsi->num_queue_pairs; i++) { - set_check_for_tx_hang(vsi->tx_rings[i]); - if (test_bit(__I40E_HANG_CHECK_ARMED, - &vsi->tx_rings[i]->state)) - armed++; - } - - if (armed) { - if (!(pf->flags & I40E_FLAG_MSIX_ENABLED)) { - wr32(&vsi->back->hw, I40E_PFINT_DYN_CTL0, - (I40E_PFINT_DYN_CTL0_INTENA_MASK | - I40E_PFINT_DYN_CTL0_SWINT_TRIG_MASK | - I40E_PFINT_DYN_CTL0_ITR_INDX_MASK | - I40E_PFINT_DYN_CTL0_SW_ITR_INDX_ENA_MASK | - I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK)); - } else { - u16 vec = vsi->base_vector - 1; - u32 val = (I40E_PFINT_DYN_CTLN_INTENA_MASK | - I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK | - I40E_PFINT_DYN_CTLN_ITR_INDX_MASK | - I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK | - I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK); - for (i = 0; i < vsi->num_q_vectors; i++, vec++) - wr32(&vsi->back->hw, - I40E_PFINT_DYN_CTLN(vec), val); - } - i40e_flush(&vsi->back->hw); - } - } -} - /** * i40e_watchdog_subtask - periodic checks not using event driven response * @pf: board private structure @@ -5839,7 +5890,6 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf) return; pf->service_timer_previous = jiffies; - i40e_check_hang_subtask(pf); i40e_link_event(pf); /* Update the stats for active netdevs so the network stack @@ -6807,6 +6857,7 @@ static void i40e_service_task(struct work_struct *work) return; } + i40e_detect_recover_hung(pf); i40e_reset_subtask(pf); i40e_handle_mdd_event(pf); i40e_vc_process_vflr_event(pf); @@ -10101,7 +10152,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) INIT_WORK(&pf->service_task, i40e_service_task); clear_bit(__I40E_SERVICE_SCHED, &pf->state); pf->flags |= I40E_FLAG_NEED_LINK_UPDATE; - pf->link_check_timeout = jiffies; /* WoL defaults to disabled */ pf->wol_en = false; diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 9a800f99ec13..4f9ff894d7c5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -600,7 +600,6 @@ void i40e_free_tx_resources(struct i40e_ring *tx_ring) } } - /** * i40e_get_tx_pending - how many tx descriptors not processed * @tx_ring: the ring of descriptors @@ -608,7 +607,7 @@ void i40e_free_tx_resources(struct i40e_ring *tx_ring) * Since there is no access to the ring head register * in XL710, we need to use our local copies **/ -static u32 i40e_get_tx_pending(struct i40e_ring *ring) +u32 i40e_get_tx_pending(struct i40e_ring *ring) { u32 head, tail; @@ -622,50 +621,6 @@ static u32 i40e_get_tx_pending(struct i40e_ring *ring) return 0; } -/** - * i40e_check_tx_hang - Is there a hang in the Tx queue - * @tx_ring: the ring of descriptors - **/ -static bool i40e_check_tx_hang(struct i40e_ring *tx_ring) -{ - u32 tx_done = tx_ring->stats.packets; - u32 tx_done_old = tx_ring->tx_stats.tx_done_old; - u32 tx_pending = i40e_get_tx_pending(tx_ring); - struct i40e_pf *pf = tx_ring->vsi->back; - bool ret = false; - - clear_check_for_tx_hang(tx_ring); - - /* Check for a hung queue, but be thorough. This verifies - * that a transmit has been completed since the previous - * check AND there is at least one packet pending. The - * ARMED bit is set to indicate a potential hang. The - * bit is cleared if a pause frame is received to remove - * false hang detection due to PFC or 802.3x frames. By - * requiring this to fail twice we avoid races with - * PFC clearing the ARMED bit and conditions where we - * run the check_tx_hang logic with a transmit completion - * pending but without time to complete it yet. - */ - if ((tx_done_old == tx_done) && tx_pending) { - /* make sure it is true for two checks in a row */ - ret = test_and_set_bit(__I40E_HANG_CHECK_ARMED, - &tx_ring->state); - } else if (tx_done_old == tx_done && - (tx_pending < I40E_MIN_DESC_PENDING) && (tx_pending > 0)) { - if (I40E_DEBUG_FLOW & pf->hw.debug_mask) - dev_info(tx_ring->dev, "HW needs some more descs to do a cacheline flush. tx_pending %d, queue %d", - tx_pending, tx_ring->queue_index); - pf->tx_sluggish_count++; - } else { - /* update completed stats and disarm the hang check */ - tx_ring->tx_stats.tx_done_old = tx_done; - clear_bit(__I40E_HANG_CHECK_ARMED, &tx_ring->state); - } - - return ret; -} - #define WB_STRIDE 0x3 /** @@ -783,32 +738,6 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) else tx_ring->arm_wb = false; - if (check_for_tx_hang(tx_ring) && i40e_check_tx_hang(tx_ring)) { - /* schedule immediate reset if we believe we hung */ - dev_info(tx_ring->dev, "Detected Tx Unit Hang\n" - " VSI <%d>\n" - " Tx Queue <%d>\n" - " next_to_use <%x>\n" - " next_to_clean <%x>\n", - tx_ring->vsi->seid, - tx_ring->queue_index, - tx_ring->next_to_use, i); - - netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); - - dev_info(tx_ring->dev, - "tx hang detected on queue %d, reset requested\n", - tx_ring->queue_index); - - /* do not fire the reset immediately, wait for the stack to - * decide we are truly stuck, also prevents every queue from - * simultaneously requesting a reset - */ - - /* the adapter is about to reset, no point in enabling polling */ - budget = 1; - } - netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index), total_packets, total_bytes); @@ -838,7 +767,7 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) * @q_vector: the vector on which to force writeback * **/ -static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector) +void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector) { u16 flags = q_vector->tx.ring[0].flags; diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 51487ef9eda3..977cb5b46115 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -199,8 +199,6 @@ struct i40e_rx_queue_stats { enum i40e_ring_state_t { __I40E_TX_FDIR_INIT_DONE, __I40E_TX_XPS_INIT_DONE, - __I40E_TX_DETECT_HANG, - __I40E_HANG_CHECK_ARMED, __I40E_RX_PS_ENABLED, __I40E_RX_16BYTE_DESC_ENABLED, }; @@ -211,12 +209,6 @@ enum i40e_ring_state_t { set_bit(__I40E_RX_PS_ENABLED, &(ring)->state) #define clear_ring_ps_enabled(ring) \ clear_bit(__I40E_RX_PS_ENABLED, &(ring)->state) -#define check_for_tx_hang(ring) \ - test_bit(__I40E_TX_DETECT_HANG, &(ring)->state) -#define set_check_for_tx_hang(ring) \ - set_bit(__I40E_TX_DETECT_HANG, &(ring)->state) -#define clear_check_for_tx_hang(ring) \ - clear_bit(__I40E_TX_DETECT_HANG, &(ring)->state) #define ring_is_16byte_desc_enabled(ring) \ test_bit(__I40E_RX_16BYTE_DESC_ENABLED, &(ring)->state) #define set_ring_16byte_desc_enabled(ring) \ @@ -326,6 +318,8 @@ int i40e_xmit_descriptor_count(struct sk_buff *skb, struct i40e_ring *tx_ring); int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, struct i40e_ring *tx_ring, u32 *flags); #endif +void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector); +u32 i40e_get_tx_pending(struct i40e_ring *ring); /** * i40e_get_head - Retrieve head from head writeback diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 7e91d825c760..830979380466 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -140,65 +140,6 @@ static inline u32 i40e_get_head(struct i40e_ring *tx_ring) return le32_to_cpu(*(volatile __le32 *)head); } -/** - * i40e_get_tx_pending - how many tx descriptors not processed - * @tx_ring: the ring of descriptors - * - * Since there is no access to the ring head register - * in XL710, we need to use our local copies - **/ -static u32 i40e_get_tx_pending(struct i40e_ring *ring) -{ - u32 head, tail; - - head = i40e_get_head(ring); - tail = readl(ring->tail); - - if (head != tail) - return (head < tail) ? - tail - head : (tail + ring->count - head); - - return 0; -} - -/** - * i40e_check_tx_hang - Is there a hang in the Tx queue - * @tx_ring: the ring of descriptors - **/ -static bool i40e_check_tx_hang(struct i40e_ring *tx_ring) -{ - u32 tx_done = tx_ring->stats.packets; - u32 tx_done_old = tx_ring->tx_stats.tx_done_old; - u32 tx_pending = i40e_get_tx_pending(tx_ring); - bool ret = false; - - clear_check_for_tx_hang(tx_ring); - - /* Check for a hung queue, but be thorough. This verifies - * that a transmit has been completed since the previous - * check AND there is at least one packet pending. The - * ARMED bit is set to indicate a potential hang. The - * bit is cleared if a pause frame is received to remove - * false hang detection due to PFC or 802.3x frames. By - * requiring this to fail twice we avoid races with - * PFC clearing the ARMED bit and conditions where we - * run the check_tx_hang logic with a transmit completion - * pending but without time to complete it yet. - */ - if ((tx_done_old == tx_done) && tx_pending) { - /* make sure it is true for two checks in a row */ - ret = test_and_set_bit(__I40E_HANG_CHECK_ARMED, - &tx_ring->state); - } else if (tx_done_old == tx_done && - (tx_pending < I40E_MIN_DESC_PENDING) && (tx_pending > 0)) { - /* update completed stats and disarm the hang check */ - tx_ring->tx_stats.tx_done_old = tx_done; - clear_bit(__I40E_HANG_CHECK_ARMED, &tx_ring->state); - } - - return ret; -} - #define WB_STRIDE 0x3 /** @@ -304,6 +245,10 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) tx_ring->q_vector->tx.total_bytes += total_bytes; tx_ring->q_vector->tx.total_packets += total_packets; + /* check to see if there are any non-cache aligned descriptors + * waiting to be written back, and kick the hardware to force + * them to be written back in case of napi polling + */ if (budget && !((i & WB_STRIDE) == WB_STRIDE) && !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && @@ -312,29 +257,6 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) else tx_ring->arm_wb = false; - if (check_for_tx_hang(tx_ring) && i40e_check_tx_hang(tx_ring)) { - /* schedule immediate reset if we believe we hung */ - dev_info(tx_ring->dev, "Detected Tx Unit Hang\n" - " VSI <%d>\n" - " Tx Queue <%d>\n" - " next_to_use <%x>\n" - " next_to_clean <%x>\n", - tx_ring->vsi->seid, - tx_ring->queue_index, - tx_ring->next_to_use, i); - - netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); - - dev_info(tx_ring->dev, - "tx hang detected on queue %d, resetting adapter\n", - tx_ring->queue_index); - - tx_ring->netdev->netdev_ops->ndo_tx_timeout(tx_ring->netdev); - - /* the adapter is about to reset, no point in enabling stuff */ - return true; - } - netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index), total_packets, total_bytes); @@ -355,16 +277,16 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) } } - return budget > 0; + return !!budget; } /** - * i40e_force_wb -Arm hardware to do a wb on noncache aligned descriptors + * i40evf_force_wb -Arm hardware to do a wb on noncache aligned descriptors * @vsi: the VSI we care about * @q_vector: the vector on which to force writeback * **/ -static void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector) +static void i40evf_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector) { u16 flags = q_vector->tx.ring[0].flags; @@ -1385,7 +1307,7 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget) /* If work not completed, return budget and polling will return */ if (!clean_complete) { if (arm_wb) - i40e_force_wb(vsi, q_vector); + i40evf_force_wb(vsi, q_vector); return budget; } diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index 9a30f5d8c089..d5cb7aca87b4 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -198,8 +198,6 @@ struct i40e_rx_queue_stats { enum i40e_ring_state_t { __I40E_TX_FDIR_INIT_DONE, __I40E_TX_XPS_INIT_DONE, - __I40E_TX_DETECT_HANG, - __I40E_HANG_CHECK_ARMED, __I40E_RX_PS_ENABLED, __I40E_RX_16BYTE_DESC_ENABLED, }; @@ -210,12 +208,6 @@ enum i40e_ring_state_t { set_bit(__I40E_RX_PS_ENABLED, &(ring)->state) #define clear_ring_ps_enabled(ring) \ clear_bit(__I40E_RX_PS_ENABLED, &(ring)->state) -#define check_for_tx_hang(ring) \ - test_bit(__I40E_TX_DETECT_HANG, &(ring)->state) -#define set_check_for_tx_hang(ring) \ - set_bit(__I40E_TX_DETECT_HANG, &(ring)->state) -#define clear_check_for_tx_hang(ring) \ - clear_bit(__I40E_TX_DETECT_HANG, &(ring)->state) #define ring_is_16byte_desc_enabled(ring) \ test_bit(__I40E_RX_16BYTE_DESC_ENABLED, &(ring)->state) #define set_ring_16byte_desc_enabled(ring) \ -- cgit v1.2.3 From c1d1791dc8b2a13c316a4e163552804361a786a4 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Fri, 25 Sep 2015 19:26:04 +0000 Subject: i40e: add GRE tunnel type to csum encoding Make sure the Tx checksum encoder knows about GRE protocol and sets the descriptor flag appropriately. Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 4f9ff894d7c5..d699fc941a77 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2240,6 +2240,9 @@ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, l4_tunnel = I40E_TXD_CTX_UDP_TUNNELING; *tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL; break; + case IPPROTO_GRE: + l4_tunnel = I40E_TXD_CTX_GRE_TUNNELING; + break; default: return; } -- cgit v1.2.3 From 5804474311912c1b80601a1afee052e8df962cd4 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Date: Fri, 25 Sep 2015 18:26:13 -0700 Subject: i40e: Fix RS bit update in Tx path and disable force WB workaround This patch fixes the issue of forcing WB too often causing us to not benefit from NAPI. Without this patch we were forcing WB/arming interrupt too often taking away the benefits of NAPI and causing a performance impact. With this patch we disable force WB in the clean routine for X710 and XL710 adapters. X722 adapters do not enable interrupt to force a WB and benefit from WB_ON_ITR and hence force WB is left enabled for those adapters. For XL710 and X710 adapters if we have less than 4 packets pending a software Interrupt triggered from service task will force a WB. This patch also changes the conditions for setting RS bit as described in code comments. This optimizes when the HW does a tail bump and when it does a WB. It also optimizes when we do a wmb. Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 129 ++++++++++++++++++---------- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 2 + 2 files changed, 87 insertions(+), 44 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index d699fc941a77..3ce4900c0c43 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -726,17 +726,22 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) tx_ring->q_vector->tx.total_bytes += total_bytes; tx_ring->q_vector->tx.total_packets += total_packets; - /* check to see if there are any non-cache aligned descriptors - * waiting to be written back, and kick the hardware to force - * them to be written back in case of napi polling - */ - if (budget && - !((i & WB_STRIDE) == WB_STRIDE) && - !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && - (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) - tx_ring->arm_wb = true; - else - tx_ring->arm_wb = false; + if (tx_ring->flags & I40E_TXR_FLAGS_WB_ON_ITR) { + unsigned int j = 0; + + /* check to see if there are < 4 descriptors + * waiting to be written back, then kick the hardware to force + * them to be written back in case we stay in NAPI. + * In this mode on X722 we do not enable Interrupt. + */ + j = i40e_get_tx_pending(tx_ring); + + if (budget && + ((j / (WB_STRIDE + 1)) == 0) && (j != 0) && + !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && + (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) + tx_ring->arm_wb = true; + } netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index), @@ -2500,6 +2505,9 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, u32 td_tag = 0; dma_addr_t dma; u16 gso_segs; + u16 desc_count = 0; + bool tail_bump = true; + bool do_rs = false; if (tx_flags & I40E_TX_FLAGS_HW_VLAN) { td_cmd |= I40E_TX_DESC_CMD_IL2TAG1; @@ -2540,6 +2548,8 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_desc++; i++; + desc_count++; + if (i == tx_ring->count) { tx_desc = I40E_TX_DESC(tx_ring, 0); i = 0; @@ -2559,6 +2569,8 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_desc++; i++; + desc_count++; + if (i == tx_ring->count) { tx_desc = I40E_TX_DESC(tx_ring, 0); i = 0; @@ -2573,34 +2585,6 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_bi = &tx_ring->tx_bi[i]; } - /* Place RS bit on last descriptor of any packet that spans across the - * 4th descriptor (WB_STRIDE aka 0x3) in a 64B cacheline. - */ - if (((i & WB_STRIDE) != WB_STRIDE) && - (first <= &tx_ring->tx_bi[i]) && - (first >= &tx_ring->tx_bi[i & ~WB_STRIDE])) { - tx_desc->cmd_type_offset_bsz = - build_ctob(td_cmd, td_offset, size, td_tag) | - cpu_to_le64((u64)I40E_TX_DESC_CMD_EOP << - I40E_TXD_QW1_CMD_SHIFT); - } else { - tx_desc->cmd_type_offset_bsz = - build_ctob(td_cmd, td_offset, size, td_tag) | - cpu_to_le64((u64)I40E_TXD_CMD << - I40E_TXD_QW1_CMD_SHIFT); - } - - netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev, - tx_ring->queue_index), - first->bytecount); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - /* set next_to_watch value indicating a packet is present */ first->next_to_watch = tx_desc; @@ -2610,15 +2594,72 @@ static inline void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb, tx_ring->next_to_use = i; + netdev_tx_sent_queue(netdev_get_tx_queue(tx_ring->netdev, + tx_ring->queue_index), + first->bytecount); i40e_maybe_stop_tx(tx_ring, DESC_NEEDED); + + /* Algorithm to optimize tail and RS bit setting: + * if xmit_more is supported + * if xmit_more is true + * do not update tail and do not mark RS bit. + * if xmit_more is false and last xmit_more was false + * if every packet spanned less than 4 desc + * then set RS bit on 4th packet and update tail + * on every packet + * else + * update tail and set RS bit on every packet. + * if xmit_more is false and last_xmit_more was true + * update tail and set RS bit. + * + * Optimization: wmb to be issued only in case of tail update. + * Also optimize the Descriptor WB path for RS bit with the same + * algorithm. + * + * Note: If there are less than 4 packets + * pending and interrupts were disabled the service task will + * trigger a force WB. + */ + if (skb->xmit_more && + !netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev, + tx_ring->queue_index))) { + tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET; + tail_bump = false; + } else if (!skb->xmit_more && + !netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev, + tx_ring->queue_index)) && + (!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) && + (tx_ring->packet_stride < WB_STRIDE) && + (desc_count < WB_STRIDE)) { + tx_ring->packet_stride++; + } else { + tx_ring->packet_stride = 0; + tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET; + do_rs = true; + } + if (do_rs) + tx_ring->packet_stride = 0; + + tx_desc->cmd_type_offset_bsz = + build_ctob(td_cmd, td_offset, size, td_tag) | + cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD : + I40E_TX_DESC_CMD_EOP) << + I40E_TXD_QW1_CMD_SHIFT); + /* notify HW of packet */ - if (!skb->xmit_more || - netif_xmit_stopped(netdev_get_tx_queue(tx_ring->netdev, - tx_ring->queue_index))) - writel(i, tx_ring->tail); - else + if (!tail_bump) prefetchw(tx_desc + 1); + if (tail_bump) { + /* Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + writel(i, tx_ring->tail); + } + return; dma_error: diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 977cb5b46115..a3978c2b5fc9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -256,10 +256,12 @@ struct i40e_ring { bool ring_active; /* is ring online or not */ bool arm_wb; /* do something to arm write back */ + u8 packet_stride; u16 flags; #define I40E_TXR_FLAGS_WB_ON_ITR BIT(0) #define I40E_TXR_FLAGS_OUTER_UDP_CSUM BIT(1) +#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2) /* stats structs */ struct i40e_queue_stats stats; -- cgit v1.2.3 From 30e2561b95295258890b4e0366ce867e04d34a97 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Date: Mon, 28 Sep 2015 13:37:12 -0700 Subject: i40e: Fix for recursive RTNL lock during PROMISC change The sync_vsi_filters function can be called directly under RTNL or through the timer subtask without one. This was causing a deadlock. If sync_vsi_filters is called from a thread which held the lock, and in another thread the PROMISC setting got changed we would be executing the PROMISC change in the thread which already held the lock alongside the other filter update. The PROMISC change requires a reset if we are on a VEB, which requires it to be called under RTNL. Earlier the driver would call reset for PROMISC change without checking if we were already under RTNL and would try to grab it causing a deadlock. This patch changes the flow to see if we are already under RTNL before trying to grab it. Signed-off-by: Anjali Singhai Jain Signed-off-by: Kiran Patil Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 +- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_main.c | 19 ++++++++++++------- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 8 ++++---- 4 files changed, 19 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 4797269d1200..c64d18d4cb2d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -666,7 +666,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, bool is_vf, bool is_netdev); void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan, bool is_vf, bool is_netdev); -int i40e_sync_vsi_filters(struct i40e_vsi *vsi); +int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl); struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, u16 uplink, u32 param1); int i40e_vsi_release(struct i40e_vsi *vsi); diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index d7c15d17faa6..508efb034e87 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1146,7 +1146,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, } f = i40e_add_filter(vsi, ma, vlan, false, false); - ret = i40e_sync_vsi_filters(vsi); + ret = i40e_sync_vsi_filters(vsi, true); if (f && !ret) dev_info(&pf->pdev->dev, "add macaddr: %pM vlan=%d added to VSI %d\n", @@ -1183,7 +1183,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, } i40e_del_filter(vsi, ma, vlan, false, false); - ret = i40e_sync_vsi_filters(vsi); + ret = i40e_sync_vsi_filters(vsi, true); if (!ret) dev_info(&pf->pdev->dev, "del macaddr: %pM vlan=%d removed from VSI %d\n", diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index c246dca5de71..52e58f304b21 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1527,7 +1527,7 @@ static int i40e_set_mac(struct net_device *netdev, void *p) f->is_laa = true; } - i40e_sync_vsi_filters(vsi); + i40e_sync_vsi_filters(vsi, false); ether_addr_copy(netdev->dev_addr, addr->sa_data); return 0; @@ -1764,12 +1764,13 @@ static void i40e_set_rx_mode(struct net_device *netdev) /** * i40e_sync_vsi_filters - Update the VSI filter list to the HW * @vsi: ptr to the VSI + * @grab_rtnl: whether RTNL needs to be grabbed * * Push any outstanding VSI filter changes through the AdminQ. * * Returns 0 or error value **/ -int i40e_sync_vsi_filters(struct i40e_vsi *vsi) +int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) { struct i40e_mac_filter *f, *ftmp; bool promisc_forced_on = false; @@ -1958,7 +1959,11 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) */ if (pf->cur_promisc != cur_promisc) { pf->cur_promisc = cur_promisc; - i40e_do_reset_safe(pf, + if (grab_rtnl) + i40e_do_reset_safe(pf, + BIT(__I40E_PF_RESET_REQUESTED)); + else + i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED)); } } else { @@ -2009,7 +2014,7 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf) for (v = 0; v < pf->num_alloc_vsi; v++) { if (pf->vsi[v] && (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED)) - i40e_sync_vsi_filters(pf->vsi[v]); + i40e_sync_vsi_filters(pf->vsi[v], true); } } @@ -2216,7 +2221,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state)) return 0; - return i40e_sync_vsi_filters(vsi); + return i40e_sync_vsi_filters(vsi, false); } /** @@ -2288,7 +2293,7 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state)) return 0; - return i40e_sync_vsi_filters(vsi); + return i40e_sync_vsi_filters(vsi, false); } /** @@ -8821,7 +8826,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi) list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) i40e_del_filter(vsi, f->macaddr, f->vlan, f->is_vf, f->is_netdev); - i40e_sync_vsi_filters(vsi); + i40e_sync_vsi_filters(vsi, false); i40e_vsi_delete(vsi); i40e_vsi_free_q_vectors(vsi); diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index d99c116032f3..eacce9389962 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -561,7 +561,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) } /* program mac filter */ - ret = i40e_sync_vsi_filters(vsi); + ret = i40e_sync_vsi_filters(vsi, false); if (ret) dev_err(&pf->pdev->dev, "Unable to program ucast filters\n"); @@ -1605,7 +1605,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) } /* program the updated filter list */ - if (i40e_sync_vsi_filters(vsi)) + if (i40e_sync_vsi_filters(vsi, false)) dev_err(&pf->pdev->dev, "Unable to program VF MAC filters\n"); error_param: @@ -1656,7 +1656,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) I40E_VLAN_ANY, true, false); /* program the updated filter list */ - if (i40e_sync_vsi_filters(vsi)) + if (i40e_sync_vsi_filters(vsi, false)) dev_err(&pf->pdev->dev, "Unable to program VF MAC filters\n"); error_param: @@ -2062,7 +2062,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) dev_info(&pf->pdev->dev, "Setting MAC %pM on VF %d\n", mac, vf_id); /* program mac filter */ - if (i40e_sync_vsi_filters(vsi)) { + if (i40e_sync_vsi_filters(vsi, false)) { dev_err(&pf->pdev->dev, "Unable to program ucast filters\n"); ret = -EIO; goto error_param; -- cgit v1.2.3 From cbfe360a1541a32e9e28f8f8ac925d2b7979d767 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Thu, 17 Sep 2015 14:46:10 +0200 Subject: igb: assume MSI-X interrupts during initialization In igb_sw_init() the sequence of calls was changed from igb_init_queue_configuration() igb_init_interrupt_scheme() igb_probe_vfs() to igb_probe_vfs() igb_init_queue_configuration() igb_init_interrupt_scheme() This results in adapter->flags not having the IGB_FLAG_HAS_MSIX bit set during igb_probe_vfs()->igb_enable_sriov(). Therefore SR-IOV does not get enabled properly and we run into a NULL pointer if the max_vfs module parameter is specified (adapter->vf_data does not get allocated, crash on accessing the structure). [ 7.419348] BUG: unable to handle kernel NULL pointer dereference at 0000000000000048 [ 7.419367] IP: [] igb_reset+0xe6/0x5d0 [igb] [ 7.419370] PGD 0 [ 7.419373] Oops: 0002 [#1] SMP [ 7.419381] Modules linked in: ahci(+) libahci igb(+) i40e(+) vxlan ip6_udp_tunnel udp_tunnel megaraid_sas(+) ixgbe(+) mdio [ 7.419385] CPU: 0 PID: 4 Comm: kworker/0:0 Not tainted 4.2.0+ #153 [ 7.419387] Hardware name: Dell Inc. PowerEdge R720/0C4Y3R, BIOS 1.6.0 03/07/2013 [...] [ 7.419431] Call Trace: [ 7.419442] [] igb_probe+0x8b6/0x1340 [igb] [ 7.419447] [] local_pci_probe+0x45/0xa0 Prevent this by setting the IGB_FLAG_HAS_MSIX bit before calling igb_probe_vfs(). The real interrupt capabilities will be checked during igb_init_interrupt_scheme() so this is safe to do. Signed-off-by: Stefan Assmann Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/igb/igb_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index e174fbbdba40..ba019fc87fd1 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2986,6 +2986,9 @@ static int igb_sw_init(struct igb_adapter *adapter) } #endif /* CONFIG_PCI_IOV */ + /* Assume MSI-X interrupts, will be checked during IRQ allocation */ + adapter->flags |= IGB_FLAG_HAS_MSIX; + igb_probe_vfs(adapter); igb_init_queue_configuration(adapter); -- cgit v1.2.3 From 343b29f308d0a9c12579feec9d244ffc53ae99c3 Mon Sep 17 00:00:00 2001 From: Achiad Shochat Date: Fri, 25 Sep 2015 10:49:09 +0300 Subject: net/mlx5e: Priv state flag not rolled-back upon netdev open error The private mlx5 state flag that indicates that the netdev is opened is set at the beginning of the netdev open flow. In case an error occured later in the mlx5 netdev open flow, this flag was not cleared, remaining set although the actual set is closed. Signed-off-by: Achiad Shochat Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 59874d666cff..bb801a9bbd42 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1367,13 +1367,13 @@ int mlx5e_open_locked(struct net_device *netdev) err = mlx5e_set_dev_port_mtu(netdev); if (err) - return err; + goto err_clear_state_opened_flag; err = mlx5e_open_channels(priv); if (err) { netdev_err(netdev, "%s: mlx5e_open_channels failed, %d\n", __func__, err); - return err; + goto err_clear_state_opened_flag; } mlx5e_update_carrier(priv); @@ -1382,6 +1382,10 @@ int mlx5e_open_locked(struct net_device *netdev) schedule_delayed_work(&priv->update_stats_work, 0); return 0; + +err_clear_state_opened_flag: + clear_bit(MLX5E_STATE_OPENED, &priv->state); + return err; } static int mlx5e_open(struct net_device *netdev) -- cgit v1.2.3 From 97909302f9739c4c5664bc6fc19237ec19d53c02 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Fri, 25 Sep 2015 10:49:10 +0300 Subject: net/mlx5_core: Fix struct type in the DESTROY_TIR/TIS device commands Used the output mailbox format for input mailbox. Signed-off-by: Saeed Mahameed Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/transobj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/transobj.c b/drivers/net/ethernet/mellanox/mlx5/core/transobj.c index b4c87c7b0cf0..d7068f54e800 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/transobj.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/transobj.c @@ -177,7 +177,7 @@ int mlx5_core_modify_tir(struct mlx5_core_dev *dev, u32 tirn, u32 *in, void mlx5_core_destroy_tir(struct mlx5_core_dev *dev, u32 tirn) { - u32 in[MLX5_ST_SZ_DW(destroy_tir_out)]; + u32 in[MLX5_ST_SZ_DW(destroy_tir_in)]; u32 out[MLX5_ST_SZ_DW(destroy_tir_out)]; memset(in, 0, sizeof(in)); @@ -206,7 +206,7 @@ int mlx5_core_create_tis(struct mlx5_core_dev *dev, u32 *in, int inlen, void mlx5_core_destroy_tis(struct mlx5_core_dev *dev, u32 tisn) { - u32 in[MLX5_ST_SZ_DW(destroy_tis_out)]; + u32 in[MLX5_ST_SZ_DW(destroy_tis_in)]; u32 out[MLX5_ST_SZ_DW(destroy_tis_out)]; memset(in, 0, sizeof(in)); -- cgit v1.2.3 From 6c3dbd2d722a6010010ad99a6890a56178385bb8 Mon Sep 17 00:00:00 2001 From: Achiad Shochat Date: Fri, 25 Sep 2015 10:49:11 +0300 Subject: net/mlx5_core: Remove redundant "err" variable usage Cosmetic change. Do not use the an err variable just to assign and return it. Signed-off-by: Achiad Shochat Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/port.c | 35 ++++++++------------------ 1 file changed, 11 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index 821caaab9bfb..ae302614e74b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -90,16 +90,13 @@ int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps) { struct mlx5_reg_pcap in; struct mlx5_reg_pcap out; - int err; memset(&in, 0, sizeof(in)); in.caps_127_96 = cpu_to_be32(caps); in.port_num = port_num; - err = mlx5_core_access_reg(dev, &in, sizeof(in), &out, - sizeof(out), MLX5_REG_PCAP, 0, 1); - - return err; + return mlx5_core_access_reg(dev, &in, sizeof(in), &out, + sizeof(out), MLX5_REG_PCAP, 0, 1); } EXPORT_SYMBOL_GPL(mlx5_set_port_caps); @@ -107,16 +104,13 @@ int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys, int ptys_size, int proto_mask, u8 local_port) { u32 in[MLX5_ST_SZ_DW(ptys_reg)]; - int err; memset(in, 0, sizeof(in)); MLX5_SET(ptys_reg, in, local_port, local_port); MLX5_SET(ptys_reg, in, proto_mask, proto_mask); - err = mlx5_core_access_reg(dev, in, sizeof(in), ptys, - ptys_size, MLX5_REG_PTYS, 0, 0); - - return err; + return mlx5_core_access_reg(dev, in, sizeof(in), ptys, + ptys_size, MLX5_REG_PTYS, 0, 0); } EXPORT_SYMBOL_GPL(mlx5_query_port_ptys); @@ -199,7 +193,6 @@ int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin, { u32 in[MLX5_ST_SZ_DW(ptys_reg)]; u32 out[MLX5_ST_SZ_DW(ptys_reg)]; - int err; memset(in, 0, sizeof(in)); @@ -210,9 +203,8 @@ int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin, else MLX5_SET(ptys_reg, in, ib_proto_admin, proto_admin); - err = mlx5_core_access_reg(dev, in, sizeof(in), out, - sizeof(out), MLX5_REG_PTYS, 0, 1); - return err; + return mlx5_core_access_reg(dev, in, sizeof(in), out, + sizeof(out), MLX5_REG_PTYS, 0, 1); } EXPORT_SYMBOL_GPL(mlx5_set_port_proto); @@ -250,7 +242,7 @@ int mlx5_query_port_admin_status(struct mlx5_core_dev *dev, return err; *status = MLX5_GET(paos_reg, out, admin_status); - return err; + return 0; } EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status); @@ -308,15 +300,12 @@ static int mlx5_query_port_pvlc(struct mlx5_core_dev *dev, u32 *pvlc, int pvlc_size, u8 local_port) { u32 in[MLX5_ST_SZ_DW(pvlc_reg)]; - int err; memset(in, 0, sizeof(in)); MLX5_SET(ptys_reg, in, local_port, local_port); - err = mlx5_core_access_reg(dev, in, sizeof(in), pvlc, - pvlc_size, MLX5_REG_PVLC, 0, 0); - - return err; + return mlx5_core_access_reg(dev, in, sizeof(in), pvlc, + pvlc_size, MLX5_REG_PVLC, 0, 0); } int mlx5_query_port_vl_hw_cap(struct mlx5_core_dev *dev, @@ -339,16 +328,14 @@ int mlx5_set_port_pause(struct mlx5_core_dev *dev, u32 rx_pause, u32 tx_pause) { u32 in[MLX5_ST_SZ_DW(pfcc_reg)]; u32 out[MLX5_ST_SZ_DW(pfcc_reg)]; - int err; memset(in, 0, sizeof(in)); MLX5_SET(pfcc_reg, in, local_port, 1); MLX5_SET(pfcc_reg, in, pptx, tx_pause); MLX5_SET(pfcc_reg, in, pprx, rx_pause); - err = mlx5_core_access_reg(dev, in, sizeof(in), out, - sizeof(out), MLX5_REG_PFCC, 0, 1); - return err; + return mlx5_core_access_reg(dev, in, sizeof(in), out, + sizeof(out), MLX5_REG_PFCC, 0, 1); } EXPORT_SYMBOL_GPL(mlx5_set_port_pause); -- cgit v1.2.3 From be87544de8df2b1eb34bcb5e32691287d96f9ec4 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Fri, 25 Sep 2015 10:49:12 +0300 Subject: net/mlx5_core: Fix async commands return code In case of async command completion, the error code returned should take into account the command completion status. Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 75ff58dc1ff5..c3516598de9e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -1136,6 +1136,7 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector) mlx5_free_cmd_msg(dev, ent->out); free_msg(dev, ent->in); + err = err ? err : ent->status; free_cmd(ent); callback(err, context); } else { -- cgit v1.2.3 From a8ffe63e60dde2f2f05fa92dad48f6106d62f9a3 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Fri, 25 Sep 2015 10:49:13 +0300 Subject: net/mlx5_core: Fix notification of page supplement error Some errors did not result with notifying firmware that the page request could not be fulfilled. Fix this and put the notification logic into a separate function. Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/pagealloc.c | 63 +++++++++++++--------- 1 file changed, 37 insertions(+), 26 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index 8a64542abc16..76432a510ac2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c @@ -275,12 +275,36 @@ out_alloc: return err; } + +static void page_notify_fail(struct mlx5_core_dev *dev, u16 func_id) +{ + struct mlx5_manage_pages_inbox *in; + struct mlx5_manage_pages_outbox out; + int err; + + in = kzalloc(sizeof(*in), GFP_KERNEL); + if (!in) + return; + + memset(&out, 0, sizeof(out)); + in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES); + in->hdr.opmod = cpu_to_be16(MLX5_PAGES_CANT_GIVE); + in->func_id = cpu_to_be16(func_id); + err = mlx5_cmd_exec(dev, in, sizeof(*in), &out, sizeof(out)); + if (!err) + err = mlx5_cmd_status_to_err(&out.hdr); + + if (err) + mlx5_core_warn(dev, "page notify failed\n"); + + kfree(in); +} + static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages, int notify_fail) { struct mlx5_manage_pages_inbox *in; struct mlx5_manage_pages_outbox out; - struct mlx5_manage_pages_inbox *nin; int inlen; u64 addr; int err; @@ -289,8 +313,9 @@ static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages, inlen = sizeof(*in) + npages * sizeof(in->pas[0]); in = mlx5_vzalloc(inlen); if (!in) { + err = -ENOMEM; mlx5_core_warn(dev, "vzalloc failed %d\n", inlen); - return -ENOMEM; + goto out_free; } memset(&out, 0, sizeof(out)); @@ -316,43 +341,29 @@ retry: if (err) { mlx5_core_warn(dev, "func_id 0x%x, npages %d, err %d\n", func_id, npages, err); - goto out_alloc; + goto out_4k; } dev->priv.fw_pages += npages; - if (out.hdr.status) { - err = mlx5_cmd_status_to_err(&out.hdr); - if (err) { - mlx5_core_warn(dev, "func_id 0x%x, npages %d, status %d\n", - func_id, npages, out.hdr.status); - goto out_alloc; - } + err = mlx5_cmd_status_to_err(&out.hdr); + if (err) { + mlx5_core_warn(dev, "func_id 0x%x, npages %d, status %d\n", + func_id, npages, out.hdr.status); + goto out_4k; } mlx5_core_dbg(dev, "err %d\n", err); - goto out_free; - -out_alloc: - if (notify_fail) { - nin = kzalloc(sizeof(*nin), GFP_KERNEL); - if (!nin) { - mlx5_core_warn(dev, "allocation failed\n"); - goto out_4k; - } - memset(&out, 0, sizeof(out)); - nin->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_MANAGE_PAGES); - nin->hdr.opmod = cpu_to_be16(MLX5_PAGES_CANT_GIVE); - if (mlx5_cmd_exec(dev, nin, sizeof(*nin), &out, sizeof(out))) - mlx5_core_warn(dev, "page notify failed\n"); - kfree(nin); - } + kvfree(in); + return 0; out_4k: for (i--; i >= 0; i--) free_4k(dev, be64_to_cpu(in->pas[i])); out_free: kvfree(in); + if (notify_fail) + page_notify_fail(dev, func_id); return err; } -- cgit v1.2.3 From a31208b1e11df334d443ec8cace7636150bb8ce2 Mon Sep 17 00:00:00 2001 From: Majd Dibbiny Date: Fri, 25 Sep 2015 10:49:14 +0300 Subject: net/mlx5_core: New init and exit flow for mlx5_core In the new flow, we separate the pci initialization and teardown from the initialization and teardown of the other resources. init_one calls mlx5_pci_init that handles the pci resources initialization. It then calls mlx5_load_one to initialize the remainder of the resources. When removing a device, remove_one is invoked. However, now remove_one calls mlx5_unload_one to free all the resources except the pci resources. When mlx5_unload_one returns, mlx5_pci_close is called to free the pci resources. The above separation will allow us to implement the pci error handlers and suspend and resume callbacks. Signed-off-by: Majd Dibbiny Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 1 + drivers/net/ethernet/mellanox/mlx5/core/cq.c | 1 + drivers/net/ethernet/mellanox/mlx5/core/eq.c | 1 + drivers/net/ethernet/mellanox/mlx5/core/main.c | 341 ++++++++++++++----------- drivers/net/ethernet/mellanox/mlx5/core/mr.c | 1 + drivers/net/ethernet/mellanox/mlx5/core/qp.c | 1 + drivers/net/ethernet/mellanox/mlx5/core/srq.c | 1 + 7 files changed, 194 insertions(+), 153 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index c3516598de9e..84838c2f528f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -1364,6 +1364,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev) int err; int i; + memset(cmd, 0, sizeof(*cmd)); cmd_if_rev = cmdif_rev(dev); if (cmd_if_rev != CMD_IF_REV) { dev_err(&dev->pdev->dev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cq.c b/drivers/net/ethernet/mellanox/mlx5/core/cq.c index 04ab7e445eae..b51e42d6fbec 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cq.c @@ -242,6 +242,7 @@ int mlx5_init_cq_table(struct mlx5_core_dev *dev) struct mlx5_cq_table *table = &dev->priv.cq_table; int err; + memset(table, 0, sizeof(*table)); spin_lock_init(&table->lock); INIT_RADIX_TREE(&table->tree, GFP_ATOMIC); err = mlx5_cq_debugfs_init(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index a40b96d4c662..1f01fe8fde42 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -346,6 +346,7 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx, int inlen; eq->nent = roundup_pow_of_two(nent + MLX5_NUM_SPARE_EQE); + eq->cons_index = 0; err = mlx5_buf_alloc(dev, eq->nent * MLX5_EQE_SIZE, &eq->buf); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 03aabdd79abe..7718f6ac6214 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -672,12 +672,126 @@ static void unmap_bf_area(struct mlx5_core_dev *dev) io_mapping_free(dev->priv.bf_mapping); } -static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev) +static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv) +{ + struct mlx5_device_context *dev_ctx; + struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv); + + dev_ctx = kmalloc(sizeof(*dev_ctx), GFP_KERNEL); + if (!dev_ctx) + return; + + dev_ctx->intf = intf; + dev_ctx->context = intf->add(dev); + + if (dev_ctx->context) { + spin_lock_irq(&priv->ctx_lock); + list_add_tail(&dev_ctx->list, &priv->ctx_list); + spin_unlock_irq(&priv->ctx_lock); + } else { + kfree(dev_ctx); + } +} + +static void mlx5_remove_device(struct mlx5_interface *intf, struct mlx5_priv *priv) +{ + struct mlx5_device_context *dev_ctx; + struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv); + + list_for_each_entry(dev_ctx, &priv->ctx_list, list) + if (dev_ctx->intf == intf) { + spin_lock_irq(&priv->ctx_lock); + list_del(&dev_ctx->list); + spin_unlock_irq(&priv->ctx_lock); + + intf->remove(dev, dev_ctx->context); + kfree(dev_ctx); + return; + } +} + +static int mlx5_register_device(struct mlx5_core_dev *dev) { struct mlx5_priv *priv = &dev->priv; - int err; + struct mlx5_interface *intf; + + mutex_lock(&intf_mutex); + list_add_tail(&priv->dev_list, &dev_list); + list_for_each_entry(intf, &intf_list, list) + mlx5_add_device(intf, priv); + mutex_unlock(&intf_mutex); + + return 0; +} + +static void mlx5_unregister_device(struct mlx5_core_dev *dev) +{ + struct mlx5_priv *priv = &dev->priv; + struct mlx5_interface *intf; + + mutex_lock(&intf_mutex); + list_for_each_entry(intf, &intf_list, list) + mlx5_remove_device(intf, priv); + list_del(&priv->dev_list); + mutex_unlock(&intf_mutex); +} + +int mlx5_register_interface(struct mlx5_interface *intf) +{ + struct mlx5_priv *priv; + + if (!intf->add || !intf->remove) + return -EINVAL; + + mutex_lock(&intf_mutex); + list_add_tail(&intf->list, &intf_list); + list_for_each_entry(priv, &dev_list, dev_list) + mlx5_add_device(intf, priv); + mutex_unlock(&intf_mutex); + + return 0; +} +EXPORT_SYMBOL(mlx5_register_interface); + +void mlx5_unregister_interface(struct mlx5_interface *intf) +{ + struct mlx5_priv *priv; + + mutex_lock(&intf_mutex); + list_for_each_entry(priv, &dev_list, dev_list) + mlx5_remove_device(intf, priv); + list_del(&intf->list); + mutex_unlock(&intf_mutex); +} +EXPORT_SYMBOL(mlx5_unregister_interface); + +void *mlx5_get_protocol_dev(struct mlx5_core_dev *mdev, int protocol) +{ + struct mlx5_priv *priv = &mdev->priv; + struct mlx5_device_context *dev_ctx; + unsigned long flags; + void *result = NULL; + + spin_lock_irqsave(&priv->ctx_lock, flags); + + list_for_each_entry(dev_ctx, &mdev->priv.ctx_list, list) + if ((dev_ctx->intf->protocol == protocol) && + dev_ctx->intf->get_dev) { + result = dev_ctx->intf->get_dev(dev_ctx->context); + break; + } + + spin_unlock_irqrestore(&priv->ctx_lock, flags); + + return result; +} +EXPORT_SYMBOL(mlx5_get_protocol_dev); + +static int mlx5_pci_init(struct mlx5_core_dev *dev, struct mlx5_priv *priv) +{ + struct pci_dev *pdev = dev->pdev; + int err = 0; - dev->pdev = pdev; pci_set_drvdata(dev->pdev, dev); strncpy(priv->name, dev_name(&pdev->dev), MLX5_MAX_NAME_LEN); priv->name[MLX5_MAX_NAME_LEN - 1] = 0; @@ -721,13 +835,42 @@ static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev) dev_err(&pdev->dev, "Failed mapping initialization segment, aborting\n"); goto err_clr_master; } + + return 0; + +err_clr_master: + pci_clear_master(dev->pdev); + release_bar(dev->pdev); +err_disable: + pci_disable_device(dev->pdev); + +err_dbg: + debugfs_remove(priv->dbg_root); + return err; +} + +static void mlx5_pci_close(struct mlx5_core_dev *dev, struct mlx5_priv *priv) +{ + iounmap(dev->iseg); + pci_clear_master(dev->pdev); + release_bar(dev->pdev); + pci_disable_device(dev->pdev); + debugfs_remove(priv->dbg_root); +} + +#define MLX5_IB_MOD "mlx5_ib" +static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) +{ + struct pci_dev *pdev = dev->pdev; + int err; + dev_info(&pdev->dev, "firmware version: %d.%d.%d\n", fw_rev_maj(dev), fw_rev_min(dev), fw_rev_sub(dev)); err = mlx5_cmd_init(dev); if (err) { dev_err(&pdev->dev, "Failed initializing command interface, aborting\n"); - goto err_unmap; + return err; } mlx5_pagealloc_init(dev); @@ -842,8 +985,25 @@ static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev) mlx5_init_srq_table(dev); mlx5_init_mr_table(dev); + err = mlx5_register_device(dev); + if (err) { + dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err); + goto err_reg_dev; + } + + err = request_module_nowait(MLX5_IB_MOD); + if (err) + pr_info("failed request module on %s\n", MLX5_IB_MOD); + return 0; +err_reg_dev: + mlx5_cleanup_mr_table(dev); + mlx5_cleanup_srq_table(dev); + mlx5_cleanup_qp_table(dev); + mlx5_cleanup_cq_table(dev); + mlx5_irq_clear_affinity_hints(dev); + err_unmap_bf_area: unmap_bf_area(dev); @@ -881,25 +1041,14 @@ err_pagealloc_cleanup: mlx5_pagealloc_cleanup(dev); mlx5_cmd_cleanup(dev); -err_unmap: - iounmap(dev->iseg); - -err_clr_master: - pci_clear_master(dev->pdev); - release_bar(dev->pdev); - -err_disable: - pci_disable_device(dev->pdev); - -err_dbg: - debugfs_remove(priv->dbg_root); return err; } -static void mlx5_dev_cleanup(struct mlx5_core_dev *dev) +static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) { - struct mlx5_priv *priv = &dev->priv; + mlx5_unregister_device(dev); + mlx5_cleanup_mr_table(dev); mlx5_cleanup_srq_table(dev); mlx5_cleanup_qp_table(dev); mlx5_cleanup_cq_table(dev); @@ -913,134 +1062,16 @@ static void mlx5_dev_cleanup(struct mlx5_core_dev *dev) mlx5_stop_health_poll(dev); if (mlx5_cmd_teardown_hca(dev)) { dev_err(&dev->pdev->dev, "tear_down_hca failed, skip cleanup\n"); - return; + return 1; } mlx5_pagealloc_stop(dev); mlx5_reclaim_startup_pages(dev); mlx5_core_disable_hca(dev); mlx5_pagealloc_cleanup(dev); mlx5_cmd_cleanup(dev); - iounmap(dev->iseg); - pci_clear_master(dev->pdev); - release_bar(dev->pdev); - pci_disable_device(dev->pdev); - debugfs_remove(priv->dbg_root); -} - -static void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv) -{ - struct mlx5_device_context *dev_ctx; - struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv); - - dev_ctx = kmalloc(sizeof(*dev_ctx), GFP_KERNEL); - if (!dev_ctx) { - pr_warn("mlx5_add_device: alloc context failed\n"); - return; - } - - dev_ctx->intf = intf; - dev_ctx->context = intf->add(dev); - - if (dev_ctx->context) { - spin_lock_irq(&priv->ctx_lock); - list_add_tail(&dev_ctx->list, &priv->ctx_list); - spin_unlock_irq(&priv->ctx_lock); - } else { - kfree(dev_ctx); - } -} - -static void mlx5_remove_device(struct mlx5_interface *intf, struct mlx5_priv *priv) -{ - struct mlx5_device_context *dev_ctx; - struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv); - - list_for_each_entry(dev_ctx, &priv->ctx_list, list) - if (dev_ctx->intf == intf) { - spin_lock_irq(&priv->ctx_lock); - list_del(&dev_ctx->list); - spin_unlock_irq(&priv->ctx_lock); - - intf->remove(dev, dev_ctx->context); - kfree(dev_ctx); - return; - } -} -static int mlx5_register_device(struct mlx5_core_dev *dev) -{ - struct mlx5_priv *priv = &dev->priv; - struct mlx5_interface *intf; - - mutex_lock(&intf_mutex); - list_add_tail(&priv->dev_list, &dev_list); - list_for_each_entry(intf, &intf_list, list) - mlx5_add_device(intf, priv); - mutex_unlock(&intf_mutex); return 0; } -static void mlx5_unregister_device(struct mlx5_core_dev *dev) -{ - struct mlx5_priv *priv = &dev->priv; - struct mlx5_interface *intf; - - mutex_lock(&intf_mutex); - list_for_each_entry(intf, &intf_list, list) - mlx5_remove_device(intf, priv); - list_del(&priv->dev_list); - mutex_unlock(&intf_mutex); -} - -int mlx5_register_interface(struct mlx5_interface *intf) -{ - struct mlx5_priv *priv; - - if (!intf->add || !intf->remove) - return -EINVAL; - - mutex_lock(&intf_mutex); - list_add_tail(&intf->list, &intf_list); - list_for_each_entry(priv, &dev_list, dev_list) - mlx5_add_device(intf, priv); - mutex_unlock(&intf_mutex); - - return 0; -} -EXPORT_SYMBOL(mlx5_register_interface); - -void mlx5_unregister_interface(struct mlx5_interface *intf) -{ - struct mlx5_priv *priv; - - mutex_lock(&intf_mutex); - list_for_each_entry(priv, &dev_list, dev_list) - mlx5_remove_device(intf, priv); - list_del(&intf->list); - mutex_unlock(&intf_mutex); -} -EXPORT_SYMBOL(mlx5_unregister_interface); - -void *mlx5_get_protocol_dev(struct mlx5_core_dev *mdev, int protocol) -{ - struct mlx5_priv *priv = &mdev->priv; - struct mlx5_device_context *dev_ctx; - unsigned long flags; - void *result = NULL; - - spin_lock_irqsave(&priv->ctx_lock, flags); - - list_for_each_entry(dev_ctx, &mdev->priv.ctx_list, list) - if ((dev_ctx->intf->protocol == protocol) && - dev_ctx->intf->get_dev) { - result = dev_ctx->intf->get_dev(dev_ctx->context); - break; - } - - spin_unlock_irqrestore(&priv->ctx_lock, flags); - - return result; -} -EXPORT_SYMBOL(mlx5_get_protocol_dev); static void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event, unsigned long param) @@ -1064,7 +1095,6 @@ struct mlx5_core_event_handler { void *data); }; -#define MLX5_IB_MOD "mlx5_ib" static int init_one(struct pci_dev *pdev, const struct pci_device_id *id) @@ -1088,40 +1118,45 @@ static int init_one(struct pci_dev *pdev, prof_sel = MLX5_DEFAULT_PROF; } dev->profile = &profile[prof_sel]; + dev->pdev = pdev; dev->event = mlx5_core_event; INIT_LIST_HEAD(&priv->ctx_list); spin_lock_init(&priv->ctx_lock); - err = mlx5_dev_init(dev, pdev); + err = mlx5_pci_init(dev, priv); if (err) { - dev_err(&pdev->dev, "mlx5_dev_init failed %d\n", err); - goto out; + dev_err(&pdev->dev, "mlx5_pci_init failed with error code %d\n", err); + goto clean_dev; } - err = mlx5_register_device(dev); + err = mlx5_load_one(dev, priv); if (err) { - dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err); - goto out_init; + dev_err(&pdev->dev, "mlx5_load_one failed with error code %d\n", err); + goto close_pci; } - err = request_module_nowait(MLX5_IB_MOD); - if (err) - pr_info("failed request module on %s\n", MLX5_IB_MOD); - return 0; -out_init: - mlx5_dev_cleanup(dev); -out: +close_pci: + mlx5_pci_close(dev, priv); +clean_dev: + pci_set_drvdata(pdev, NULL); kfree(dev); + return err; } + static void remove_one(struct pci_dev *pdev) { struct mlx5_core_dev *dev = pci_get_drvdata(pdev); + struct mlx5_priv *priv = &dev->priv; - mlx5_unregister_device(dev); - mlx5_dev_cleanup(dev); + if (mlx5_unload_one(dev, priv)) { + dev_err(&dev->pdev->dev, "mlx5_unload_one failed\n"); + return; + } + mlx5_pci_close(dev, priv); + pci_set_drvdata(pdev, NULL); kfree(dev); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mr.c b/drivers/net/ethernet/mellanox/mlx5/core/mr.c index 1adb300dd850..6fa22b51e460 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mr.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/mr.c @@ -40,6 +40,7 @@ void mlx5_init_mr_table(struct mlx5_core_dev *dev) { struct mlx5_mr_table *table = &dev->priv.mr_table; + memset(table, 0, sizeof(*table)); rwlock_init(&table->lock); INIT_RADIX_TREE(&table->tree, GFP_ATOMIC); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c index 8b494b562263..30e2ba3f5f16 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/qp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c @@ -345,6 +345,7 @@ void mlx5_init_qp_table(struct mlx5_core_dev *dev) { struct mlx5_qp_table *table = &dev->priv.qp_table; + memset(table, 0, sizeof(*table)); spin_lock_init(&table->lock); INIT_RADIX_TREE(&table->tree, GFP_ATOMIC); mlx5_qp_debugfs_init(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/srq.c b/drivers/net/ethernet/mellanox/mlx5/core/srq.c index c48f504ccbeb..ffada801976b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/srq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/srq.c @@ -531,6 +531,7 @@ void mlx5_init_srq_table(struct mlx5_core_dev *dev) { struct mlx5_srq_table *table = &dev->priv.srq_table; + memset(table, 0, sizeof(*table)); spin_lock_init(&table->lock); INIT_RADIX_TREE(&table->tree, GFP_ATOMIC); } -- cgit v1.2.3 From 78ccb25861d76a8fc5c678d762180e6918834200 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Fri, 25 Sep 2015 10:49:15 +0300 Subject: net/mlx5_core: Fix wrong name in struct The name refers to syndrome so uset ext_synd instread of ext_sync. Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/health.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 292d76f2a904..6e69de00cea8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -130,7 +130,7 @@ static void print_health_info(struct mlx5_core_dev *dev) pr_info("hw_id 0x%08x\n", read_be32(&h->hw_id)); pr_info("irisc_index %d\n", readb(&h->irisc_index)); pr_info("synd 0x%x: %s\n", readb(&h->synd), hsynd_str(readb(&h->synd))); - pr_info("ext_sync 0x%04x\n", read_be16(&h->ext_sync)); + pr_info("ext_sync 0x%04x\n", read_be16(&h->ext_synd)); } static void poll_health(unsigned long data) -- cgit v1.2.3 From 171bb2c560f45c0427ca3776a4c8f4e26e559400 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Fri, 25 Sep 2015 10:49:16 +0300 Subject: net/mlx5_core: Update health syndromes Update new health monitored syndromes and their descriptions. Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/health.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 6e69de00cea8..1277c427242a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -46,12 +46,15 @@ enum { enum { MLX5_HEALTH_SYNDR_FW_ERR = 0x1, MLX5_HEALTH_SYNDR_IRISC_ERR = 0x7, + MLX5_HEALTH_SYNDR_HW_UNRECOVERABLE_ERR = 0x8, MLX5_HEALTH_SYNDR_CRC_ERR = 0x9, MLX5_HEALTH_SYNDR_FETCH_PCI_ERR = 0xa, MLX5_HEALTH_SYNDR_HW_FTL_ERR = 0xb, MLX5_HEALTH_SYNDR_ASYNC_EQ_OVERRUN_ERR = 0xc, MLX5_HEALTH_SYNDR_EQ_ERR = 0xd, + MLX5_HEALTH_SYNDR_EQ_INV = 0xe, MLX5_HEALTH_SYNDR_FFSER_ERR = 0xf, + MLX5_HEALTH_SYNDR_HIGH_TEMP = 0x10 }; static DEFINE_SPINLOCK(health_lock); @@ -88,6 +91,8 @@ static const char *hsynd_str(u8 synd) return "firmware internal error"; case MLX5_HEALTH_SYNDR_IRISC_ERR: return "irisc not responding"; + case MLX5_HEALTH_SYNDR_HW_UNRECOVERABLE_ERR: + return "unrecoverable hardware error"; case MLX5_HEALTH_SYNDR_CRC_ERR: return "firmware CRC error"; case MLX5_HEALTH_SYNDR_FETCH_PCI_ERR: @@ -98,8 +103,12 @@ static const char *hsynd_str(u8 synd) return "async EQ buffer overrun"; case MLX5_HEALTH_SYNDR_EQ_ERR: return "EQ error"; + case MLX5_HEALTH_SYNDR_EQ_INV: + return "Invalid EQ refrenced"; case MLX5_HEALTH_SYNDR_FFSER_ERR: return "FFSER error"; + case MLX5_HEALTH_SYNDR_HIGH_TEMP: + return "High temprature"; default: return "unrecognized error"; } -- cgit v1.2.3 From 49d28b5642444d82bd23b9333785480d265420d1 Mon Sep 17 00:00:00 2001 From: "Woojung.Huh@microchip.com" Date: Fri, 25 Sep 2015 21:13:48 +0000 Subject: lan78xx: Return 0 when lan78xx_suspend() has no error. lan78xx_suspend() may return non-zero from lan78xx_write_reg() in some scenario. Fix to return 0 when lan78xx_suspend() has no error. Signed-off-by: Woojung Huh Signed-off-by: David S. Miller --- drivers/net/usb/lan78xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index d2a5f3f88b13..226668ead0d8 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -3204,7 +3204,6 @@ int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) int ret; int event; - ret = 0; event = message.event; if (!dev->suspend_count++) { @@ -3286,6 +3285,7 @@ int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) } } + ret = 0; out: return ret; } -- cgit v1.2.3 From 5b40f709a1b3100a1a9dbd824303c68757f2e25e Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 25 Sep 2015 18:31:32 -0300 Subject: net: fec: Remove unneeded FEATURES_NEED_QUIESCE definition There is no need to have FEATURES_NEED_QUIESCE defined as we can simply use NETIF_F_RXCSUM instead as done in other parts of the driver. Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index dd4ca39d5d8f..501e1438d153 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3070,7 +3070,6 @@ static void fec_poll_controller(struct net_device *dev) } #endif -#define FEATURES_NEED_QUIESCE NETIF_F_RXCSUM static inline void fec_enet_set_netdev_features(struct net_device *netdev, netdev_features_t features) { @@ -3094,7 +3093,7 @@ static int fec_set_features(struct net_device *netdev, struct fec_enet_private *fep = netdev_priv(netdev); netdev_features_t changed = features ^ netdev->features; - if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) { + if (netif_running(netdev) && changed & NETIF_F_RXCSUM) { napi_disable(&fep->napi); netif_tx_lock_bh(netdev); fec_stop(netdev); -- cgit v1.2.3 From be01891e4606bc6aaa2b12fbade1aca8eb467a16 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 26 Sep 2015 20:49:18 +0200 Subject: net: irda: pxaficp_ir: use sched_clock() for time management Instead of using directly the OS timer through direct register access, use the standard sched_clock(), which will end up in OSCR reading anyway. This is a first step for direct access register removal and machine specific code removal from this driver. This commit changes the behavior, as previously the minimum turnaround time was counted in 76ns steps, while with this patch it is counted in microsecond steps. The strictly equal formula would have been : while ((sched_clock() - si->last_clk) * 76 < mtt) Signed-off-by: Robert Jarzmik Signed-off-by: David S. Miller --- drivers/net/irda/pxaficp_ir.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index 100454662e4b..6a81d3d1b312 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -29,7 +29,6 @@ #include #include -#include #include #define FICP __REG(0x40800000) /* Start of FICP area */ @@ -102,7 +101,7 @@ struct pxa_irda { int speed; int newspeed; - unsigned long last_oscr; + unsigned long long last_clk; unsigned char *dma_rx_buff; unsigned char *dma_tx_buff; @@ -292,7 +291,7 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) } lsr = STLSR; } - si->last_oscr = readl_relaxed(OSCR); + si->last_clk = sched_clock(); break; case 0x04: /* Received Data Available */ @@ -303,7 +302,7 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) dev->stats.rx_bytes++; async_unwrap_char(dev, &dev->stats, &si->rx_buff, STRBR); } while (STLSR & LSR_DR); - si->last_oscr = readl_relaxed(OSCR); + si->last_clk = sched_clock(); break; case 0x02: /* Transmit FIFO Data Request */ @@ -319,7 +318,7 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) /* We need to ensure that the transmitter has finished. */ while ((STLSR & LSR_TEMT) == 0) cpu_relax(); - si->last_oscr = readl_relaxed(OSCR); + si->last_clk = sched_clock(); /* * Ok, we've finished transmitting. Now enable @@ -373,7 +372,7 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data) while (ICSR1 & ICSR1_TBY) cpu_relax(); - si->last_oscr = readl_relaxed(OSCR); + si->last_clk = sched_clock(); /* * HACK: It looks like the TBY bit is dropped too soon. @@ -473,8 +472,8 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) /* stop RX DMA */ DCSR(si->rxdma) &= ~DCSR_RUN; - si->last_oscr = readl_relaxed(OSCR); icsr0 = ICSR0; + si->last_clk = sched_clock(); if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) { if (icsr0 & ICSR0_FRE) { @@ -549,7 +548,7 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) skb_copy_from_linear_data(skb, si->dma_tx_buff, skb->len); if (mtt) - while ((unsigned)(readl_relaxed(OSCR) - si->last_oscr)/4 < mtt) + while ((sched_clock() - si->last_clk) * 1000 < mtt) cpu_relax(); /* stop RX DMA, disable FICP */ -- cgit v1.2.3 From 89fa57244aa170bb344cdb5be35afdeefc219fbd Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 26 Sep 2015 20:49:19 +0200 Subject: net: irda: pxaficp_ir: convert to readl and writel Convert the pxa IRDA driver to readl and writel primitives, and remove another set of direct registers access. This leaves only the DMA registers access, which will be dealt with dmaengine conversion. Signed-off-by: Robert Jarzmik Tested-by: Petr Cvek Signed-off-by: David S. Miller --- drivers/net/irda/pxaficp_ir.c | 210 +++++++++++++++++++++++++----------------- 1 file changed, 126 insertions(+), 84 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index 6a81d3d1b312..05a668216a0f 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -29,15 +29,16 @@ #include #include +#undef __REG +#define __REG(x) ((x) & 0xffff) #include -#define FICP __REG(0x40800000) /* Start of FICP area */ -#define ICCR0 __REG(0x40800000) /* ICP Control Register 0 */ -#define ICCR1 __REG(0x40800004) /* ICP Control Register 1 */ -#define ICCR2 __REG(0x40800008) /* ICP Control Register 2 */ -#define ICDR __REG(0x4080000c) /* ICP Data Register */ -#define ICSR0 __REG(0x40800014) /* ICP Status Register 0 */ -#define ICSR1 __REG(0x40800018) /* ICP Status Register 1 */ +#define ICCR0 0x0000 /* ICP Control Register 0 */ +#define ICCR1 0x0004 /* ICP Control Register 1 */ +#define ICCR2 0x0008 /* ICP Control Register 2 */ +#define ICDR 0x000c /* ICP Data Register */ +#define ICSR0 0x0014 /* ICP Status Register 0 */ +#define ICSR1 0x0018 /* ICP Status Register 1 */ #define ICCR0_AME (1 << 7) /* Address match enable */ #define ICCR0_TIE (1 << 6) /* Transmit FIFO interrupt enable */ @@ -55,9 +56,7 @@ #define ICCR2_TRIG_16 (1 << 0) /* >= 16 bytes */ #define ICCR2_TRIG_32 (2 << 0) /* >= 32 bytes */ -#ifdef CONFIG_PXA27x #define ICSR0_EOC (1 << 6) /* DMA End of Descriptor Chain */ -#endif #define ICSR0_FRE (1 << 5) /* Framing error */ #define ICSR0_RFS (1 << 4) /* Receive FIFO service request */ #define ICSR0_TFS (1 << 3) /* Transnit FIFO service request */ @@ -98,11 +97,50 @@ IrSR_RCVEIR_UART_MODE | \ IrSR_XMITIR_IR_MODE) +/* macros for registers read/write */ +#define ficp_writel(irda, val, off) \ + do { \ + dev_vdbg(irda->dev, \ + "%s():%d ficp_writel(0x%x, %s)\n", \ + __func__, __LINE__, (val), #off); \ + writel_relaxed((val), (irda)->irda_base + (off)); \ + } while (0) + +#define ficp_readl(irda, off) \ + ({ \ + unsigned int _v; \ + _v = readl_relaxed((irda)->irda_base + (off)); \ + dev_vdbg(irda->dev, \ + "%s():%d ficp_readl(%s): 0x%x\n", \ + __func__, __LINE__, #off, _v); \ + _v; \ + }) + +#define stuart_writel(irda, val, off) \ + do { \ + dev_vdbg(irda->dev, \ + "%s():%d stuart_writel(0x%x, %s)\n", \ + __func__, __LINE__, (val), #off); \ + writel_relaxed((val), (irda)->stuart_base + (off)); \ + } while (0) + +#define stuart_readl(irda, off) \ + ({ \ + unsigned int _v; \ + _v = readl_relaxed((irda)->stuart_base + (off)); \ + dev_vdbg(irda->dev, \ + "%s():%d stuart_readl(%s): 0x%x\n", \ + __func__, __LINE__, #off, _v); \ + _v; \ + }) + struct pxa_irda { int speed; int newspeed; unsigned long long last_clk; + void __iomem *stuart_base; + void __iomem *irda_base; unsigned char *dma_rx_buff; unsigned char *dma_tx_buff; dma_addr_t dma_rx_buff_phy; @@ -153,7 +191,7 @@ static inline void pxa_irda_enable_sirclk(struct pxa_irda *si) inline static void pxa_irda_fir_dma_rx_start(struct pxa_irda *si) { DCSR(si->rxdma) = DCSR_NODESC; - DSADR(si->rxdma) = __PREG(ICDR); + DSADR(si->rxdma) = (unsigned long)si->irda_base + ICDR; DTADR(si->rxdma) = si->dma_rx_buff_phy; DCMD(si->rxdma) = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_WIDTH1 | DCMD_BURST32 | IRDA_FRAME_SIZE_LIMIT; DCSR(si->rxdma) |= DCSR_RUN; @@ -163,7 +201,7 @@ inline static void pxa_irda_fir_dma_tx_start(struct pxa_irda *si) { DCSR(si->txdma) = DCSR_NODESC; DSADR(si->txdma) = si->dma_tx_buff_phy; - DTADR(si->txdma) = __PREG(ICDR); + DTADR(si->txdma) = (unsigned long)si->irda_base + ICDR; DCMD(si->txdma) = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_ENDIRQEN | DCMD_WIDTH1 | DCMD_BURST32 | si->dma_tx_buff_len; DCSR(si->txdma) |= DCSR_RUN; } @@ -206,7 +244,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) /* stop RX DMA */ DCSR(si->rxdma) &= ~DCSR_RUN; /* disable FICP */ - ICCR0 = 0; + ficp_writel(si, 0, ICCR0); pxa_irda_disable_clk(si); /* set board transceiver to SIR mode */ @@ -217,17 +255,19 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) } /* disable STUART first */ - STIER = 0; + stuart_writel(si, 0, STIER); /* access DLL & DLH */ - STLCR |= LCR_DLAB; - STDLL = divisor & 0xff; - STDLH = divisor >> 8; - STLCR &= ~LCR_DLAB; + stuart_writel(si, stuart_readl(si, STLCR) | LCR_DLAB, STLCR); + stuart_writel(si, divisor & 0xff, STDLL); + stuart_writel(si, divisor >> 8, STDLH); + stuart_writel(si, stuart_readl(si, STLCR) & ~LCR_DLAB, STLCR); si->speed = speed; - STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6; - STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE; + stuart_writel(si, IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6, + STISR); + stuart_writel(si, IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE, + STIER); local_irq_restore(flags); break; @@ -236,12 +276,12 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) local_irq_save(flags); /* disable STUART */ - STIER = 0; - STISR = 0; + stuart_writel(si, 0, STIER); + stuart_writel(si, 0, STISR); pxa_irda_disable_clk(si); /* disable FICP first */ - ICCR0 = 0; + ficp_writel(si, 0, ICCR0); /* set board transceiver to FIR mode */ pxa_irda_set_mode(si, IR_FIRMODE); @@ -251,7 +291,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) si->speed = speed; pxa_irda_fir_dma_rx_start(si); - ICCR0 = ICCR0_ITR | ICCR0_RXE; + ficp_writel(si, ICCR0_ITR | ICCR0_RXE, ICCR0); local_irq_restore(flags); break; @@ -270,13 +310,13 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) struct pxa_irda *si = netdev_priv(dev); int iir, lsr, data; - iir = STIIR; + iir = stuart_readl(si, STIIR); switch (iir & 0x0F) { case 0x06: /* Receiver Line Status */ - lsr = STLSR; + lsr = stuart_readl(si, STLSR); while (lsr & LSR_FIFOE) { - data = STRBR; + data = stuart_readl(si, STRBR); if (lsr & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) { printk(KERN_DEBUG "pxa_ir: sir receiving error\n"); dev->stats.rx_errors++; @@ -289,7 +329,7 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) async_unwrap_char(dev, &dev->stats, &si->rx_buff, data); } - lsr = STLSR; + lsr = stuart_readl(si, STLSR); } si->last_clk = sched_clock(); break; @@ -300,14 +340,16 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) case 0x0C: /* Character Timeout Indication */ do { dev->stats.rx_bytes++; - async_unwrap_char(dev, &dev->stats, &si->rx_buff, STRBR); - } while (STLSR & LSR_DR); + async_unwrap_char(dev, &dev->stats, &si->rx_buff, + stuart_readl(si, STRBR)); + } while (stuart_readl(si, STLSR) & LSR_DR); si->last_clk = sched_clock(); break; case 0x02: /* Transmit FIFO Data Request */ - while ((si->tx_buff.len) && (STLSR & LSR_TDRQ)) { - STTHR = *si->tx_buff.data++; + while ((si->tx_buff.len) && + (stuart_readl(si, STLSR) & LSR_TDRQ)) { + stuart_writel(si, *si->tx_buff.data++, STTHR); si->tx_buff.len -= 1; } @@ -316,7 +358,7 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) dev->stats.tx_bytes += si->tx_buff.data - si->tx_buff.head; /* We need to ensure that the transmitter has finished. */ - while ((STLSR & LSR_TEMT) == 0) + while ((stuart_readl(si, STLSR) & LSR_TEMT) == 0) cpu_relax(); si->last_clk = sched_clock(); @@ -330,9 +372,11 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) si->newspeed = 0; } else { /* enable IR Receiver, disable IR Transmitter */ - STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6; + stuart_writel(si, IrSR_IR_RECEIVE_ON | + IrSR_XMODE_PULSE_1_6, STISR); /* enable STUART and receive interrupts */ - STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE; + stuart_writel(si, IER_UUE | IER_RLSE | + IER_RAVIE | IER_RTIOE, STIER); } /* I'm hungry! */ netif_wake_queue(dev); @@ -370,7 +414,7 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data) dev->stats.tx_errors++; } - while (ICSR1 & ICSR1_TBY) + while (ficp_readl(si, ICSR1) & ICSR1_TBY) cpu_relax(); si->last_clk = sched_clock(); @@ -386,11 +430,11 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data) } else { int i = 64; - ICCR0 = 0; + ficp_writel(si, 0, ICCR0); pxa_irda_fir_dma_rx_start(si); - while ((ICSR1 & ICSR1_RNE) && i--) - (void)ICDR; - ICCR0 = ICCR0_ITR | ICCR0_RXE; + while ((ficp_readl(si, ICSR1) & ICSR1_RNE) && i--) + ficp_readl(si, ICDR); + ficp_writel(si, ICCR0_ITR | ICCR0_RXE, ICCR0); if (i < 0) printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n"); @@ -408,9 +452,9 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, in do { /* Read Status, and then Data. */ - stat = ICSR1; + stat = ficp_readl(si, ICSR1); rmb(); - data = ICDR; + data = ficp_readl(si, ICDR); if (stat & (ICSR1_CRE | ICSR1_ROR)) { dev->stats.rx_errors++; @@ -428,7 +472,7 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, in /* If we hit the end of frame, there's no point in continuing. */ if (stat & ICSR1_EOF) break; - } while (ICSR0 & ICSR0_EIF); + } while (ficp_readl(si, ICSR0) & ICSR0_EIF); if (stat & ICSR1_EOF) { /* end of frame. */ @@ -472,8 +516,8 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) /* stop RX DMA */ DCSR(si->rxdma) &= ~DCSR_RUN; - icsr0 = ICSR0; si->last_clk = sched_clock(); + icsr0 = ficp_readl(si, ICSR0); if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) { if (icsr0 & ICSR0_FRE) { @@ -483,7 +527,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) printk(KERN_DEBUG "pxa_ir: fir receive abort\n"); dev->stats.rx_errors++; } - ICSR0 = icsr0 & (ICSR0_FRE | ICSR0_RAB); + ficp_writel(si, icsr0 & (ICSR0_FRE | ICSR0_RAB), ICSR0); } if (icsr0 & ICSR0_EIF) { @@ -491,11 +535,11 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) pxa_irda_fir_irq_eif(si, dev, icsr0); } - ICCR0 = 0; + ficp_writel(si, 0, ICCR0); pxa_irda_fir_dma_rx_start(si); - while ((ICSR1 & ICSR1_RNE) && i--) - (void)ICDR; - ICCR0 = ICCR0_ITR | ICCR0_RXE; + while ((ficp_readl(si, ICSR1) & ICSR1_RNE) && i--) + ficp_readl(si, ICDR); + ficp_writel(si, ICCR0_ITR | ICCR0_RXE, ICCR0); if (i < 0) printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n"); @@ -536,11 +580,12 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize); /* Disable STUART interrupts and switch to transmit mode. */ - STIER = 0; - STISR = IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6; + stuart_writel(si, 0, STIER); + stuart_writel(si, IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6, + STISR); /* enable STUART and transmit interrupts */ - STIER = IER_UUE | IER_TIE; + stuart_writel(si, IER_UUE | IER_TIE, STIER); } else { unsigned long mtt = irda_get_mtt(skb); @@ -553,10 +598,10 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) /* stop RX DMA, disable FICP */ DCSR(si->rxdma) &= ~DCSR_RUN; - ICCR0 = 0; + ficp_writel(si, 0, ICCR0); pxa_irda_fir_dma_tx_start(si); - ICCR0 = ICCR0_ITR | ICCR0_TXE; + ficp_writel(si, ICCR0_ITR | ICCR0_TXE, ICCR0); } dev_kfree_skb(skb); @@ -612,18 +657,18 @@ static int pxa_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd) static void pxa_irda_startup(struct pxa_irda *si) { /* Disable STUART interrupts */ - STIER = 0; + stuart_writel(si, 0, STIER); /* enable STUART interrupt to the processor */ - STMCR = MCR_OUT2; + stuart_writel(si, MCR_OUT2, STMCR); /* configure SIR frame format: StartBit - Data 7 ... Data 0 - Stop Bit */ - STLCR = LCR_WLS0 | LCR_WLS1; + stuart_writel(si, LCR_WLS0 | LCR_WLS1, STLCR); /* enable FIFO, we use FIFO to improve performance */ - STFCR = FCR_TRFIFOE | FCR_ITL_32; + stuart_writel(si, FCR_TRFIFOE | FCR_ITL_32, STFCR); /* disable FICP */ - ICCR0 = 0; + ficp_writel(si, 0, ICCR0); /* configure FICP ICCR2 */ - ICCR2 = ICCR2_TXP | ICCR2_TRIG_32; + ficp_writel(si, ICCR2_TXP | ICCR2_TRIG_32, ICCR2); /* configure DMAC */ DRCMR(17) = si->rxdma | DRCMR_MAPVLD; @@ -643,15 +688,15 @@ static void pxa_irda_shutdown(struct pxa_irda *si) local_irq_save(flags); /* disable STUART and interrupt */ - STIER = 0; + stuart_writel(si, 0, STIER); /* disable STUART SIR mode */ - STISR = 0; + stuart_writel(si, 0, STISR); /* disable DMA */ DCSR(si->txdma) &= ~DCSR_RUN; DCSR(si->rxdma) &= ~DCSR_RUN; /* disable FICP */ - ICCR0 = 0; + ficp_writel(si, 0, ICCR0); /* disable the STUART or FICP clocks */ pxa_irda_disable_clk(si); @@ -829,25 +874,33 @@ static const struct net_device_ops pxa_irda_netdev_ops = { static int pxa_irda_probe(struct platform_device *pdev) { struct net_device *dev; + struct resource *res; struct pxa_irda *si; + void __iomem *ficp, *stuart; unsigned int baudrate_mask; int err; if (!pdev->dev.platform_data) return -ENODEV; - err = request_mem_region(__PREG(STUART), 0x24, "IrDA") ? 0 : -EBUSY; - if (err) - goto err_mem_1; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + ficp = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(ficp)) { + dev_err(&pdev->dev, "resource ficp not defined\n"); + return PTR_ERR(ficp); + } - err = request_mem_region(__PREG(FICP), 0x1c, "IrDA") ? 0 : -EBUSY; - if (err) - goto err_mem_2; + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + stuart = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(stuart)) { + dev_err(&pdev->dev, "resource stuart not defined\n"); + return PTR_ERR(stuart); + } dev = alloc_irdadev(sizeof(struct pxa_irda)); if (!dev) { err = -ENOMEM; - goto err_mem_3; + goto err_mem_1; } SET_NETDEV_DEV(dev, &pdev->dev); @@ -855,11 +908,13 @@ static int pxa_irda_probe(struct platform_device *pdev) si->dev = &pdev->dev; si->pdata = pdev->dev.platform_data; + si->irda_base = ficp; + si->stuart_base = stuart; si->uart_irq = platform_get_irq(pdev, 0); si->icp_irq = platform_get_irq(pdev, 1); - si->sir_clk = clk_get(&pdev->dev, "UARTCLK"); - si->fir_clk = clk_get(&pdev->dev, "FICPCLK"); + si->sir_clk = devm_clk_get(&pdev->dev, "UARTCLK"); + si->fir_clk = devm_clk_get(&pdev->dev, "FICPCLK"); if (IS_ERR(si->sir_clk) || IS_ERR(si->fir_clk)) { err = PTR_ERR(IS_ERR(si->sir_clk) ? si->sir_clk : si->fir_clk); goto err_mem_4; @@ -924,15 +979,7 @@ err_startup: err_mem_5: kfree(si->rx_buff.head); err_mem_4: - if (si->sir_clk && !IS_ERR(si->sir_clk)) - clk_put(si->sir_clk); - if (si->fir_clk && !IS_ERR(si->fir_clk)) - clk_put(si->fir_clk); free_netdev(dev); -err_mem_3: - release_mem_region(__PREG(FICP), 0x1c); -err_mem_2: - release_mem_region(__PREG(STUART), 0x24); } err_mem_1: return err; @@ -951,14 +998,9 @@ static int pxa_irda_remove(struct platform_device *_dev) si->pdata->shutdown(si->dev); kfree(si->tx_buff.head); kfree(si->rx_buff.head); - clk_put(si->fir_clk); - clk_put(si->sir_clk); free_netdev(dev); } - release_mem_region(__PREG(STUART), 0x24); - release_mem_region(__PREG(FICP), 0x1c); - return 0; } -- cgit v1.2.3 From 1273bc573ab13b9c76053fe0403dca7d8acffa78 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 26 Sep 2015 20:49:20 +0200 Subject: net: irda: pxaficp_ir: dmaengine conversion Convert pxaficp_ir to dmaengine. As pxa architecture is shifting from raw DMA registers access to pxa_dma dmaengine driver, convert this driver to dmaengine. Signed-off-by: Robert Jarzmik Tested-by: Petr Cvek Signed-off-by: David S. Miller --- drivers/net/irda/pxaficp_ir.c | 149 +++++++++++++++++++++++++++++------------- 1 file changed, 102 insertions(+), 47 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index 05a668216a0f..6e8f616be48e 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c @@ -19,6 +19,9 @@ #include #include #include +#include +#include +#include #include #include @@ -27,7 +30,6 @@ #include #include -#include #include #undef __REG #define __REG(x) ((x) & 0xffff) @@ -146,8 +148,12 @@ struct pxa_irda { dma_addr_t dma_rx_buff_phy; dma_addr_t dma_tx_buff_phy; unsigned int dma_tx_buff_len; - int txdma; - int rxdma; + struct dma_chan *txdma; + struct dma_chan *rxdma; + dma_cookie_t rx_cookie; + dma_cookie_t tx_cookie; + int drcmr_rx; + int drcmr_tx; int uart_irq; int icp_irq; @@ -165,6 +171,8 @@ struct pxa_irda { struct clk *cur_clk; }; +static int pxa_irda_set_speed(struct pxa_irda *si, int speed); + static inline void pxa_irda_disable_clk(struct pxa_irda *si) { if (si->cur_clk) @@ -188,22 +196,41 @@ static inline void pxa_irda_enable_sirclk(struct pxa_irda *si) #define IS_FIR(si) ((si)->speed >= 4000000) #define IRDA_FRAME_SIZE_LIMIT 2047 +static void pxa_irda_fir_dma_rx_irq(void *data); +static void pxa_irda_fir_dma_tx_irq(void *data); + inline static void pxa_irda_fir_dma_rx_start(struct pxa_irda *si) { - DCSR(si->rxdma) = DCSR_NODESC; - DSADR(si->rxdma) = (unsigned long)si->irda_base + ICDR; - DTADR(si->rxdma) = si->dma_rx_buff_phy; - DCMD(si->rxdma) = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_WIDTH1 | DCMD_BURST32 | IRDA_FRAME_SIZE_LIMIT; - DCSR(si->rxdma) |= DCSR_RUN; + struct dma_async_tx_descriptor *tx; + + tx = dmaengine_prep_slave_single(si->rxdma, si->dma_rx_buff_phy, + IRDA_FRAME_SIZE_LIMIT, DMA_FROM_DEVICE, + DMA_PREP_INTERRUPT); + if (!tx) { + dev_err(si->dev, "prep_slave_sg() failed\n"); + return; + } + tx->callback = pxa_irda_fir_dma_rx_irq; + tx->callback_param = si; + si->rx_cookie = dmaengine_submit(tx); + dma_async_issue_pending(si->rxdma); } inline static void pxa_irda_fir_dma_tx_start(struct pxa_irda *si) { - DCSR(si->txdma) = DCSR_NODESC; - DSADR(si->txdma) = si->dma_tx_buff_phy; - DTADR(si->txdma) = (unsigned long)si->irda_base + ICDR; - DCMD(si->txdma) = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_ENDIRQEN | DCMD_WIDTH1 | DCMD_BURST32 | si->dma_tx_buff_len; - DCSR(si->txdma) |= DCSR_RUN; + struct dma_async_tx_descriptor *tx; + + tx = dmaengine_prep_slave_single(si->txdma, si->dma_tx_buff_phy, + si->dma_tx_buff_len, DMA_TO_DEVICE, + DMA_PREP_INTERRUPT); + if (!tx) { + dev_err(si->dev, "prep_slave_sg() failed\n"); + return; + } + tx->callback = pxa_irda_fir_dma_tx_irq; + tx->callback_param = si; + si->tx_cookie = dmaengine_submit(tx); + dma_async_issue_pending(si->rxdma); } /* @@ -242,7 +269,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) if (IS_FIR(si)) { /* stop RX DMA */ - DCSR(si->rxdma) &= ~DCSR_RUN; + dmaengine_terminate_all(si->rxdma); /* disable FICP */ ficp_writel(si, 0, ICCR0); pxa_irda_disable_clk(si); @@ -388,30 +415,27 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) } /* FIR Receive DMA interrupt handler */ -static void pxa_irda_fir_dma_rx_irq(int channel, void *data) +static void pxa_irda_fir_dma_rx_irq(void *data) { - int dcsr = DCSR(channel); - - DCSR(channel) = dcsr & ~DCSR_RUN; + struct net_device *dev = data; + struct pxa_irda *si = netdev_priv(dev); - printk(KERN_DEBUG "pxa_ir: fir rx dma bus error %#x\n", dcsr); + dmaengine_terminate_all(si->rxdma); + netdev_dbg(dev, "pxa_ir: fir rx dma bus error\n"); } /* FIR Transmit DMA interrupt handler */ -static void pxa_irda_fir_dma_tx_irq(int channel, void *data) +static void pxa_irda_fir_dma_tx_irq(void *data) { struct net_device *dev = data; struct pxa_irda *si = netdev_priv(dev); - int dcsr; - - dcsr = DCSR(channel); - DCSR(channel) = dcsr & ~DCSR_RUN; - if (dcsr & DCSR_ENDINTR) { + dmaengine_terminate_all(si->txdma); + if (dmaengine_tx_status(si->txdma, si->tx_cookie, NULL) == DMA_ERROR) { + dev->stats.tx_errors++; + } else { dev->stats.tx_packets++; dev->stats.tx_bytes += si->dma_tx_buff_len; - } else { - dev->stats.tx_errors++; } while (ficp_readl(si, ICSR1) & ICSR1_TBY) @@ -446,9 +470,12 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data) static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, int icsr0) { unsigned int len, stat, data; + struct dma_tx_state state; /* Get the current data position. */ - len = DTADR(si->rxdma) - si->dma_rx_buff_phy; + + dmaengine_tx_status(si->rxdma, si->rx_cookie, &state); + len = IRDA_FRAME_SIZE_LIMIT - state.residue; do { /* Read Status, and then Data. */ @@ -515,7 +542,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) int icsr0, i = 64; /* stop RX DMA */ - DCSR(si->rxdma) &= ~DCSR_RUN; + dmaengine_terminate_all(si->rxdma); si->last_clk = sched_clock(); icsr0 = ficp_readl(si, ICSR0); @@ -597,7 +624,7 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) cpu_relax(); /* stop RX DMA, disable FICP */ - DCSR(si->rxdma) &= ~DCSR_RUN; + dmaengine_terminate_all(si->rxdma); ficp_writel(si, 0, ICCR0); pxa_irda_fir_dma_tx_start(si); @@ -670,10 +697,6 @@ static void pxa_irda_startup(struct pxa_irda *si) /* configure FICP ICCR2 */ ficp_writel(si, ICCR2_TXP | ICCR2_TRIG_32, ICCR2); - /* configure DMAC */ - DRCMR(17) = si->rxdma | DRCMR_MAPVLD; - DRCMR(18) = si->txdma | DRCMR_MAPVLD; - /* force SIR reinitialization */ si->speed = 4000000; pxa_irda_set_speed(si, 9600); @@ -693,17 +716,14 @@ static void pxa_irda_shutdown(struct pxa_irda *si) stuart_writel(si, 0, STISR); /* disable DMA */ - DCSR(si->txdma) &= ~DCSR_RUN; - DCSR(si->rxdma) &= ~DCSR_RUN; + dmaengine_terminate_all(si->rxdma); + dmaengine_terminate_all(si->txdma); /* disable FICP */ ficp_writel(si, 0, ICCR0); /* disable the STUART or FICP clocks */ pxa_irda_disable_clk(si); - DRCMR(17) = 0; - DRCMR(18) = 0; - local_irq_restore(flags); /* power off board transceiver */ @@ -715,6 +735,9 @@ static void pxa_irda_shutdown(struct pxa_irda *si) static int pxa_irda_start(struct net_device *dev) { struct pxa_irda *si = netdev_priv(dev); + dma_cap_mask_t mask; + struct dma_slave_config config; + struct pxad_param param; int err; si->speed = 9600; @@ -734,14 +757,37 @@ static int pxa_irda_start(struct net_device *dev) disable_irq(si->icp_irq); err = -EBUSY; - si->rxdma = pxa_request_dma("FICP_RX",DMA_PRIO_LOW, pxa_irda_fir_dma_rx_irq, dev); - if (si->rxdma < 0) + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + param.prio = PXAD_PRIO_LOWEST; + + memset(&config, 0, sizeof(config)); + config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + config.src_addr = (dma_addr_t)si->irda_base + ICDR; + config.dst_addr = (dma_addr_t)si->irda_base + ICDR; + config.src_maxburst = 32; + config.dst_maxburst = 32; + + param.drcmr = si->drcmr_rx; + si->rxdma = dma_request_slave_channel_compat(mask, pxad_filter_fn, + ¶m, &dev->dev, "rx"); + if (!si->rxdma) goto err_rx_dma; - si->txdma = pxa_request_dma("FICP_TX",DMA_PRIO_LOW, pxa_irda_fir_dma_tx_irq, dev); - if (si->txdma < 0) + param.drcmr = si->drcmr_tx; + si->txdma = dma_request_slave_channel_compat(mask, pxad_filter_fn, + ¶m, &dev->dev, "tx"); + if (!si->txdma) goto err_tx_dma; + err = dmaengine_slave_config(si->rxdma, &config); + if (err) + goto err_dma_rx_buff; + err = dmaengine_slave_config(si->txdma, &config); + if (err) + goto err_dma_rx_buff; + err = -ENOMEM; si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, &si->dma_rx_buff_phy, GFP_KERNEL); @@ -781,9 +827,9 @@ err_irlap: err_dma_tx_buff: dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy); err_dma_rx_buff: - pxa_free_dma(si->txdma); + dma_release_channel(si->txdma); err_tx_dma: - pxa_free_dma(si->rxdma); + dma_release_channel(si->rxdma); err_rx_dma: free_irq(si->icp_irq, dev); err_irq2: @@ -810,8 +856,10 @@ static int pxa_irda_stop(struct net_device *dev) free_irq(si->uart_irq, dev); free_irq(si->icp_irq, dev); - pxa_free_dma(si->rxdma); - pxa_free_dma(si->txdma); + dmaengine_terminate_all(si->rxdma); + dmaengine_terminate_all(si->txdma); + dma_release_channel(si->rxdma); + dma_release_channel(si->txdma); if (si->dma_rx_buff) dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy); @@ -920,6 +968,13 @@ static int pxa_irda_probe(struct platform_device *pdev) goto err_mem_4; } + res = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (res) + si->drcmr_rx = res->start; + res = platform_get_resource(pdev, IORESOURCE_DMA, 1); + if (res) + si->drcmr_tx = res->start; + /* * Initialise the SIR buffers */ -- cgit v1.2.3 From e4600d69ffc7c0ce9759532e2c10056bf1c0a1a7 Mon Sep 17 00:00:00 2001 From: huangdaode Date: Sun, 27 Sep 2015 15:22:44 +0800 Subject: net: Fix Hisilicon Network Subsystem Support Compilation This patch fixes the compilation error with arm allmodconfig, this error generated due to unavailability of readq() on 32-bit platform which was found during net-next daily compilation. In the same time, fix all the hns drivers compilation warnings. Signed-off-by: huangdaode Signed-off-by: zhaungyuzeng Signed-off-by: kenneth Lee Signed-off-by: yankejian Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 2 +- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h | 4 ++-- drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 6 ++---- drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 2 +- drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c | 1 + drivers/net/ethernet/hisilicon/hns/hns_enet.c | 17 ----------------- 6 files changed, 7 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index a8bd27b7f439..95bf42aae24c 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -86,7 +86,7 @@ int hns_mac_get_sfp_prsnt(struct hns_mac_cb *mac_cb, int *sfp_prsnt) if (!mac_cb->cpld_vaddr) return -ENODEV; - *sfp_prsnt = !dsaf_read_b((u64)mac_cb->cpld_vaddr + *sfp_prsnt = !dsaf_read_b((u8 *)mac_cb->cpld_vaddr + MAC_SFP_PORT_OFFSET); return 0; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index e0417c09ba79..315b07ecd291 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -43,7 +43,7 @@ struct hns_mac_cb; #define DSAF_DUMP_REGS_NUM 504 #define DSAF_STATIC_NUM 28 -#define DSAF_STATS_READ(p, offset) (*((u64 *)((u64)(p) + (offset)))) +#define DSAF_STATS_READ(p, offset) (*((u64 *)((u8 *)(p) + (offset)))) enum hal_dsaf_mode { HRD_DSAF_NO_DSAF_MODE = 0x0, @@ -302,7 +302,7 @@ struct dsaf_device { static inline void *hns_dsaf_dev_priv(const struct dsaf_device *dsaf_dev) { - return (void *)((u64)dsaf_dev + sizeof(*dsaf_dev)); + return (void *)((u8 *)dsaf_dev + sizeof(*dsaf_dev)); } struct dsaf_drv_tbl_tcam_key { diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index 50f3427709d9..05ea244d999c 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -192,8 +192,7 @@ static void hns_rcb_ring_init(struct ring_pair_cb *ring_pair, int ring_type) dsaf_write_dev(q, RCB_RING_RX_RING_BASEADDR_L_REG, (u32)dma); dsaf_write_dev(q, RCB_RING_RX_RING_BASEADDR_H_REG, - (u32)(dma >> 32)); - + (u32)((dma >> 31) >> 1)); dsaf_write_dev(q, RCB_RING_RX_RING_BD_LEN_REG, bd_size_type); dsaf_write_dev(q, RCB_RING_RX_RING_BD_NUM_REG, @@ -204,8 +203,7 @@ static void hns_rcb_ring_init(struct ring_pair_cb *ring_pair, int ring_type) dsaf_write_dev(q, RCB_RING_TX_RING_BASEADDR_L_REG, (u32)dma); dsaf_write_dev(q, RCB_RING_TX_RING_BASEADDR_H_REG, - (u32)(dma >> 32)); - + (u32)((dma >> 31) >> 1)); dsaf_write_dev(q, RCB_RING_TX_RING_BD_LEN_REG, bd_size_type); dsaf_write_dev(q, RCB_RING_TX_RING_BD_NUM_REG, diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index 6fc58ba01f87..b475e1bf2e6f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -967,6 +967,6 @@ static inline u32 dsaf_get_reg_field(void *base, u32 reg, u32 mask, u32 shift) readb((__iomem unsigned char *)(addr)) #define hns_mac_reg_read64(drv, offset) \ - readq((__iomem void *)(((u64)(drv)->io_base + 0xc00 + (offset)))) + readq((__iomem void *)(((u8 *)(drv)->io_base + 0xc00 + (offset)))) #endif /* _DSAF_REG_H */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c index fe7fa1d6852b..dab5ecf382a0 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c @@ -7,6 +7,7 @@ * (at your option) any later version. */ +#include #include #include "hns_dsaf_main.h" #include "hns_dsaf_mac.h" diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 0713ced120b6..ce7f2e0e3fd1 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -31,8 +31,6 @@ #define NIC_TX_CLEAN_MAX_NUM 256 #define NIC_RX_CLEAN_MAX_NUM 64 -#define RCB_ERR_PRINT_CYCLE 1000 - #define RCB_IRQ_NOT_INITED 0 #define RCB_IRQ_INITED 1 @@ -434,21 +432,12 @@ out_bnum_err: if (unlikely((!desc->rx.pkt_len) || hnae_get_bit(bnum_flag, HNS_RXD_DROP_B))) { - if (!(ring->stats.err_pkt_len % RCB_ERR_PRINT_CYCLE)) - netdev_dbg(ndev, - "pkt_len(%u),drop(%u),%#llx,%#llx\n", - le16_to_cpu(desc->rx.pkt_len), - hnae_get_bit(bnum_flag, HNS_RXD_DROP_B), - ((u64 *)desc)[0], ((u64 *)desc)[1]); ring->stats.err_pkt_len++; dev_kfree_skb_any(skb); return -EFAULT; } if (unlikely(hnae_get_bit(bnum_flag, HNS_RXD_L2E_B))) { - if (!(ring->stats.l2_err % RCB_ERR_PRINT_CYCLE)) - netdev_dbg(ndev, "L2 check err,%#llx,%#llx\n", - ((u64 *)desc)[0], ((u64 *)desc)[1]); ring->stats.l2_err++; dev_kfree_skb_any(skb); return -EFAULT; @@ -459,12 +448,6 @@ out_bnum_err: if (unlikely(hnae_get_bit(bnum_flag, HNS_RXD_L3E_B) || hnae_get_bit(bnum_flag, HNS_RXD_L4E_B))) { - if (!(ring->stats.l3l4_csum_err % RCB_ERR_PRINT_CYCLE)) - netdev_dbg(ndev, - "check err(%#x),%#llx,%#llx\n", - hnae_get_bit(bnum_flag, HNS_RXD_L3E_B) | - hnae_get_bit(bnum_flag, HNS_RXD_L4E_B), - ((u64 *)desc)[0], ((u64 *)desc)[1]); ring->stats.l3l4_csum_err++; return 0; } -- cgit v1.2.3 From 5e2a5ebc3f94027d0f2ffd33d3f3adbc856775d3 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Mon, 28 Sep 2015 10:26:53 +0530 Subject: cxgb4: Add HW timesptamp support for RX Adds support for ethtool get time stamp ioctl, which is used by tcpdump to get the supported time stamp types eg: tcpdump -i eth5 -J Time stamp types for eth5 (use option -j to set): host (Host) adapter_unsynced (Adapter, not synced with system time) Adds support for adapter unsynced mode, by adding SIOCSHWTSTAMP support in driver. Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 4 +++ drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 15 +++++++++ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 24 +++++++++++++++ drivers/net/ethernet/chelsio/cxgb4/sge.c | 36 ++++++++++++++++++++-- drivers/net/ethernet/chelsio/cxgb4/t4_hw.h | 5 +++ 5 files changed, 81 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index fa0c7b54ec7a..634e50c8c5ef 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -47,6 +47,7 @@ #include #include #include +#include #include #include "cxgb4_uld.h" @@ -478,6 +479,8 @@ struct port_info { #ifdef CONFIG_CHELSIO_T4_FCOE struct cxgb_fcoe fcoe; #endif /* CONFIG_CHELSIO_T4_FCOE */ + bool rxtstamp; /* Enable TS */ + struct hwtstamp_config tstamp_config; }; struct dentry; @@ -517,6 +520,7 @@ struct sge_fl { /* SGE free-buffer queue state */ /* A packet gather list */ struct pkt_gl { + u64 sgetstamp; /* SGE Time Stamp for Ingress Packet */ struct page_frag frags[MAX_SKB_FRAGS]; void *va; /* virtual address of first byte */ unsigned int nfrags; /* # of fragments */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c index 5eedb98ff581..02e4e028a647 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c @@ -961,6 +961,20 @@ static int set_flash(struct net_device *netdev, struct ethtool_flash *ef) return ret; } +static int get_ts_info(struct net_device *dev, struct ethtool_ts_info *ts_info) +{ + ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE; + + ts_info->so_timestamping |= SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + + ts_info->phc_index = -1; + + return 0; +} + static u32 get_rss_table_size(struct net_device *dev) { const struct port_info *pi = netdev_priv(dev); @@ -1095,6 +1109,7 @@ static const struct ethtool_ops cxgb_ethtool_ops = { .get_rxfh = get_rss_table, .set_rxfh = set_rss_table, .flash_device = set_flash, + .get_ts_info = get_ts_info }; void cxgb4_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index f5dcde27e402..0b7570ddbe1a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -2959,6 +2959,30 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd) ret = t4_mdio_wr(pi->adapter, mbox, prtad, devad, data->reg_num, data->val_in); break; + case SIOCGHWTSTAMP: + return copy_to_user(req->ifr_data, &pi->tstamp_config, + sizeof(pi->tstamp_config)) ? + -EFAULT : 0; + case SIOCSHWTSTAMP: + if (copy_from_user(&pi->tstamp_config, req->ifr_data, + sizeof(pi->tstamp_config))) + return -EFAULT; + + switch (pi->tstamp_config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + pi->rxtstamp = false; + break; + case HWTSTAMP_FILTER_ALL: + pi->rxtstamp = true; + break; + default: + pi->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; + return -ERANGE; + } + + return copy_to_user(req->ifr_data, &pi->tstamp_config, + sizeof(pi->tstamp_config)) ? + -EFAULT : 0; default: return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 9162746d7729..b7b93e7a643d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -1820,11 +1820,34 @@ static noinline int handle_trace_pkt(struct adapter *adap, return 0; } +/** + * cxgb4_sgetim_to_hwtstamp - convert sge time stamp to hw time stamp + * @adap: the adapter + * @hwtstamps: time stamp structure to update + * @sgetstamp: 60bit iqe timestamp + * + * Every ingress queue entry has the 60-bit timestamp, convert that timestamp + * which is in Core Clock ticks into ktime_t and assign it + **/ +static void cxgb4_sgetim_to_hwtstamp(struct adapter *adap, + struct skb_shared_hwtstamps *hwtstamps, + u64 sgetstamp) +{ + u64 ns; + u64 tmp = (sgetstamp * 1000 * 1000 + adap->params.vpd.cclk / 2); + + ns = div_u64(tmp, adap->params.vpd.cclk); + + memset(hwtstamps, 0, sizeof(*hwtstamps)); + hwtstamps->hwtstamp = ns_to_ktime(ns); +} + static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl, const struct cpl_rx_pkt *pkt) { struct adapter *adapter = rxq->rspq.adap; struct sge *s = &adapter->sge; + struct port_info *pi; int ret; struct sk_buff *skb; @@ -1842,6 +1865,10 @@ static void do_gro(struct sge_eth_rxq *rxq, const struct pkt_gl *gl, skb->ip_summed = CHECKSUM_UNNECESSARY; skb_record_rx_queue(skb, rxq->rspq.idx); skb_mark_napi_id(skb, &rxq->rspq.napi); + pi = netdev_priv(skb->dev); + if (pi->rxtstamp) + cxgb4_sgetim_to_hwtstamp(adapter, skb_hwtstamps(skb), + gl->sgetstamp); if (rxq->rspq.netdev->features & NETIF_F_RXHASH) skb_set_hash(skb, (__force u32)pkt->rsshdr.hash_val, PKT_HASH_TYPE_L3); @@ -1877,9 +1904,7 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, struct sge *s = &q->adap->sge; int cpl_trace_pkt = is_t4(q->adap->params.chip) ? CPL_TRACE_PKT : CPL_TRACE_PKT_T5; -#ifdef CONFIG_CHELSIO_T4_FCOE struct port_info *pi; -#endif if (unlikely(*(u8 *)rsp == cpl_trace_pkt)) return handle_trace_pkt(q->adap, si); @@ -1910,6 +1935,10 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, rxq->stats.pkts++; + pi = netdev_priv(skb->dev); + if (pi->rxtstamp) + cxgb4_sgetim_to_hwtstamp(q->adap, skb_hwtstamps(skb), + si->sgetstamp); if (csum_ok && (pkt->l2info & htonl(RXF_UDP_F | RXF_TCP_F))) { if (!pkt->ip_frag) { skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -1926,7 +1955,6 @@ int t4_ethrx_handler(struct sge_rspq *q, const __be64 *rsp, #define CPL_RX_PKT_FLAGS (RXF_PSH_F | RXF_SYN_F | RXF_UDP_F | \ RXF_TCP_F | RXF_IP_F | RXF_IP6_F | RXF_LRO_F) - pi = netdev_priv(skb->dev); if (!(pkt->l2info & cpu_to_be32(CPL_RX_PKT_FLAGS))) { if ((pkt->l2info & cpu_to_be32(RXF_FCOE_F)) && (pi->fcoe.flags & CXGB_FCOE_ENABLED)) { @@ -2067,6 +2095,8 @@ static int process_responses(struct sge_rspq *q, int budget) unmap_rx_buf(q->adap, &rxq->fl); } + si.sgetstamp = SGE_TIMESTAMP_G( + be64_to_cpu(rc->last_flit)); /* * Last buffer remains mapped so explicitly make it * coherent for CPU access. diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h index 640369df8b3a..13708fde1668 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h @@ -263,4 +263,9 @@ enum { #undef FLASH_START #undef FLASH_MAX_SIZE +#define SGE_TIMESTAMP_S 0 +#define SGE_TIMESTAMP_M 0xfffffffffffffffULL +#define SGE_TIMESTAMP_V(x) ((__u64)(x) << SGE_TIMESTAMP_S) +#define SGE_TIMESTAMP_G(x) (((__u64)(x) >> SGE_TIMESTAMP_S) & SGE_TIMESTAMP_M) + #endif /* __T4_HW_H */ -- cgit v1.2.3 From 75effb03ee8e4c9d4bbc909118ce5444b047dfde Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Aug 2015 22:14:53 +0200 Subject: brcmfmac: consolidate ifp lookup in driver core In rx path the firmware provide an interface index which is used to map to a struct brcmf_if instance. However, this involves some trick that is done in two places. This is changed by having driver core providing brcmf_get_ifp() function. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/bcdc.c | 25 ++++++++++-------------- drivers/net/wireless/brcm80211/brcmfmac/core.c | 19 ++++++++++++++++++ drivers/net/wireless/brcm80211/brcmfmac/core.h | 2 +- drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | 12 ++---------- 4 files changed, 32 insertions(+), 26 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c index 8e0e91c4a0b1..83aa6a00aa35 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c @@ -276,6 +276,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, struct sk_buff *pktbuf) { struct brcmf_proto_bcdc_header *h; + struct brcmf_if *ifp; brcmf_dbg(BCDC, "Enter\n"); @@ -289,30 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, trace_brcmf_bcdchdr(pktbuf->data); h = (struct brcmf_proto_bcdc_header *)(pktbuf->data); - *ifidx = BCDC_GET_IF_IDX(h); - if (*ifidx >= BRCMF_MAX_IFS) { - brcmf_err("rx data ifnum out of range (%d)\n", *ifidx); + ifp = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h)); + if (IS_ERR_OR_NULL(ifp)) { + brcmf_dbg(INFO, "no matching ifp found\n"); return -EBADE; } - /* The ifidx is the idx to map to matching netdev/ifp. When receiving - * events this is easy because it contains the bssidx which maps - * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. - * bssidx 1 is used for p2p0 and no data can be received or - * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 - */ - if (*ifidx) - (*ifidx)++; - if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) != BCDC_PROTO_VER) { brcmf_err("%s: non-BCDC packet received, flags 0x%x\n", - brcmf_ifname(drvr, *ifidx), h->flags); + brcmf_ifname(drvr, ifp->ifidx), h->flags); return -EBADE; } if (h->flags & BCDC_FLAG_SUM_GOOD) { brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n", - brcmf_ifname(drvr, *ifidx), h->flags); + brcmf_ifname(drvr, ifp->ifidx), h->flags); pktbuf->ip_summed = CHECKSUM_UNNECESSARY; } @@ -320,12 +312,15 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, skb_pull(pktbuf, BCDC_HEADER_LEN); if (do_fws) - brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); + brcmf_fws_hdrpull(drvr, ifp->ifidx, h->data_offset << 2, + pktbuf); else skb_pull(pktbuf, h->data_offset << 2); if (pktbuf->len == 0) return -ENODATA; + + *ifidx = ifp->ifidx; return 0; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index fe9d3fbf5fe2..1747d59ef4c7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -83,6 +83,25 @@ char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) return ""; } +struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx) +{ + if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { + brcmf_err("ifidx %d out of range\n", ifidx); + return ERR_PTR(-ERANGE); + } + + /* The ifidx is the idx to map to matching netdev/ifp. When receiving + * events this is easy because it contains the bssidx which maps + * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. + * bssidx 1 is used for p2p0 and no data can be received or + * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 + */ + if (ifidx) + ifidx++; + + return drvr->iflist[ifidx]; +} + static void _brcmf_set_multicast_list(struct work_struct *work) { struct brcmf_if *ifp; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h index 746304121cdb..1dc5b9684a9d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h @@ -202,7 +202,7 @@ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp); /* Return pointer to interface name */ char *brcmf_ifname(struct brcmf_pub *drvr, int idx); - +struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx); int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, char *name, u8 *mac_addr); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c index 7b2136c9badb..1271d1d86ec9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c @@ -1081,16 +1081,8 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf *msgbuf, struct sk_buff *skb, { struct brcmf_if *ifp; - /* The ifidx is the idx to map to matching netdev/ifp. When receiving - * events this is easy because it contains the bssidx which maps - * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. - * bssidx 1 is used for p2p0 and no data can be received or - * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 - */ - if (ifidx) - (ifidx)++; - ifp = msgbuf->drvr->iflist[ifidx]; - if (!ifp || !ifp->ndev) { + ifp = brcmf_get_ifp(msgbuf->drvr, ifidx); + if (IS_ERR_OR_NULL(ifp) || !ifp->ndev) { brcmf_err("Received pkt for invalid ifidx %d\n", ifidx); brcmu_pkt_buf_free_skb(skb); return; -- cgit v1.2.3 From 796cfb65e3ed01a9b08e3a0b93e34120c54bbbd2 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Aug 2015 22:14:54 +0200 Subject: brcmfmac: make brcmf_proto_hdrpull() return struct brcmf_if instance Avoid spreading the ifidx in the driver, but have it return the struct brcmf_if instance. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/bcdc.c | 18 +++++++++--------- drivers/net/wireless/brcm80211/brcmfmac/core.c | 14 ++++++-------- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 11 ++++++----- drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | 4 ++-- drivers/net/wireless/brcm80211/brcmfmac/proto.h | 18 ++++++++++++++---- 5 files changed, 37 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c index 83aa6a00aa35..aa5ed651625d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c @@ -272,11 +272,11 @@ brcmf_proto_bcdc_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, } static int -brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, - struct sk_buff *pktbuf) +brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, + struct sk_buff *pktbuf, struct brcmf_if **ifp) { struct brcmf_proto_bcdc_header *h; - struct brcmf_if *ifp; + struct brcmf_if *tmp_if; brcmf_dbg(BCDC, "Enter\n"); @@ -290,21 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, trace_brcmf_bcdchdr(pktbuf->data); h = (struct brcmf_proto_bcdc_header *)(pktbuf->data); - ifp = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h)); - if (IS_ERR_OR_NULL(ifp)) { + tmp_if = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h)); + if (!tmp_if) { brcmf_dbg(INFO, "no matching ifp found\n"); return -EBADE; } if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) != BCDC_PROTO_VER) { brcmf_err("%s: non-BCDC packet received, flags 0x%x\n", - brcmf_ifname(drvr, ifp->ifidx), h->flags); + brcmf_ifname(drvr, tmp_if->ifidx), h->flags); return -EBADE; } if (h->flags & BCDC_FLAG_SUM_GOOD) { brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n", - brcmf_ifname(drvr, ifp->ifidx), h->flags); + brcmf_ifname(drvr, tmp_if->ifidx), h->flags); pktbuf->ip_summed = CHECKSUM_UNNECESSARY; } @@ -312,7 +312,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, skb_pull(pktbuf, BCDC_HEADER_LEN); if (do_fws) - brcmf_fws_hdrpull(drvr, ifp->ifidx, h->data_offset << 2, + brcmf_fws_hdrpull(drvr, tmp_if->ifidx, h->data_offset << 2, pktbuf); else skb_pull(pktbuf, h->data_offset << 2); @@ -320,7 +320,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, if (pktbuf->len == 0) return -ENODATA; - *ifidx = ifp->ifidx; + *ifp = tmp_if; return 0; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 1747d59ef4c7..1f65ce867b16 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -87,7 +87,7 @@ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx) { if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { brcmf_err("ifidx %d out of range\n", ifidx); - return ERR_PTR(-ERANGE); + return NULL; } /* The ifidx is the idx to map to matching netdev/ifp. When receiving @@ -539,17 +539,15 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb) struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; struct brcmf_skb_reorder_data *rd; - u8 ifidx; int ret; brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb); /* process and remove protocol-specific header */ - ret = brcmf_proto_hdrpull(drvr, true, &ifidx, skb); - ifp = drvr->iflist[ifidx]; + ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp); if (ret || !ifp || !ifp->ndev) { - if ((ret != -ENODATA) && ifp) + if (ret != -ENODATA && ifp) ifp->stats.rx_errors++; brcmu_pkt_buf_free_skb(skb); return; @@ -592,17 +590,17 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; - u8 ifidx; + struct brcmf_if *ifp; /* await txstatus signal for firmware if active */ if (brcmf_fws_fc_active(drvr->fws)) { if (!success) brcmf_fws_bustxfail(drvr->fws, txp); } else { - if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp)) + if (brcmf_proto_hdrpull(drvr, false, txp, &ifp)) brcmu_pkt_buf_free_skb(txp); else - brcmf_txfinalize(drvr, txp, ifidx, success); + brcmf_txfinalize(drvr, txp, ifp->ifidx, success); } } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 5017eaa4af45..fd438739a91e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1448,7 +1448,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, struct sk_buff *skb; struct brcmf_skbuff_cb *skcb; struct brcmf_fws_mac_descriptor *entry = NULL; - u8 ifidx; + struct brcmf_if *ifp; brcmf_dbg(DATA, "flags %d\n", flags); @@ -1497,15 +1497,16 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, } brcmf_fws_macdesc_return_req_credit(skb); - if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) { + ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp); + if (ret) { brcmu_pkt_buf_free_skb(skb); return -EINVAL; } if (!remove_from_hanger) - ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx, + ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx, genbit, seq); if (remove_from_hanger || ret) - brcmf_txfinalize(fws->drvr, skb, ifidx, true); + brcmf_txfinalize(fws->drvr, skb, ifp->ifidx, true); return 0; } @@ -1848,7 +1849,7 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo, entry->transit_count--; if (entry->suppressed) entry->suppr_transit_count--; - brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); + (void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL); goto rollback; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c index 1271d1d86ec9..d582f6993574 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c @@ -522,7 +522,7 @@ static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx, static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws, - u8 *ifidx, struct sk_buff *skb) + struct sk_buff *skb, struct brcmf_if **ifp) { return -ENODEV; } @@ -1082,7 +1082,7 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf *msgbuf, struct sk_buff *skb, struct brcmf_if *ifp; ifp = brcmf_get_ifp(msgbuf->drvr, ifidx); - if (IS_ERR_OR_NULL(ifp) || !ifp->ndev) { + if (!ifp || !ifp->ndev) { brcmf_err("Received pkt for invalid ifidx %d\n", ifidx); brcmu_pkt_buf_free_skb(skb); return; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/brcm80211/brcmfmac/proto.h index 971172ff686c..d55119d36755 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/proto.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.h @@ -24,8 +24,8 @@ enum proto_addr_mode { struct brcmf_proto { - int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, - struct sk_buff *skb); + int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, + struct sk_buff *skb, struct brcmf_if **ifp); int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, uint len); int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, @@ -46,9 +46,19 @@ int brcmf_proto_attach(struct brcmf_pub *drvr); void brcmf_proto_detach(struct brcmf_pub *drvr); static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, - u8 *ifidx, struct sk_buff *skb) + struct sk_buff *skb, + struct brcmf_if **ifp) { - return drvr->proto->hdrpull(drvr, do_fws, ifidx, skb); + struct brcmf_if *tmp = NULL; + + /* assure protocol is always called with + * non-null initialized pointer. + */ + if (ifp) + *ifp = NULL; + else + ifp = &tmp; + return drvr->proto->hdrpull(drvr, do_fws, skb, ifp); } static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, uint len) -- cgit v1.2.3 From ee6e3a3414a48425211f9292b8bfc4524c666c41 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Aug 2015 22:14:55 +0200 Subject: brcmfmac: change parameters for brcmf_remove_interface() Just pass the interface to be removed, ie. the struct brcmf_if instance. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 2 +- drivers/net/wireless/brcm80211/brcmfmac/core.c | 13 +++++++------ drivers/net/wireless/brcm80211/brcmfmac/core.h | 2 +- drivers/net/wireless/brcm80211/brcmfmac/fweh.c | 2 +- drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index a293275c1b0b..0c29bf61bb82 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -4983,7 +4983,7 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg, brcmf_dbg(CONN, "AP mode link down\n"); complete(&cfg->vif_disabled); if (ifp->vif->mbss) - brcmf_remove_interface(ifp->drvr, ifp->bssidx); + brcmf_remove_interface(ifp); return 0; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 1f65ce867b16..157f0d7be350 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -887,12 +887,13 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) } } -void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx) +void brcmf_remove_interface(struct brcmf_if *ifp) { - if (drvr->iflist[bssidx]) { - brcmf_fws_del_interface(drvr->iflist[bssidx]); - brcmf_del_if(drvr, bssidx); - } + if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp)) + return; + + brcmf_fws_del_interface(ifp); + brcmf_del_if(ifp->drvr, ifp->bssidx); } int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr) @@ -1122,7 +1123,7 @@ void brcmf_detach(struct device *dev) /* make sure primary interface removed last */ for (i = BRCMF_MAX_IFS-1; i > -1; i--) - brcmf_remove_interface(drvr, i); + brcmf_remove_interface(drvr->iflist[i]); brcmf_cfg80211_detach(drvr->config); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h index 1dc5b9684a9d..eb0c177be1db 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h @@ -206,7 +206,7 @@ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx); int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, char *name, u8 *mac_addr); -void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx); +void brcmf_remove_interface(struct brcmf_if *ifp); int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); void brcmf_txflowblock_if(struct brcmf_if *ifp, enum brcmf_netif_stop_reason reason, bool state); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index ec62492ffa69..4d4cc2cd7668 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -222,7 +222,7 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); if (ifp && ifevent->action == BRCMF_E_IF_DEL) - brcmf_remove_interface(drvr, ifevent->bssidx); + brcmf_remove_interface(ifp); } /** diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index a9ba775a24c1..6a70c068fbc5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -2140,7 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p, { cfg80211_unregister_wdev(&vif->wdev); p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; - brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx); + brcmf_remove_interface(vif->ifp); brcmf_free_vif(vif); } -- cgit v1.2.3 From 1c626cf472fce757a69a4c70f038867907b5b808 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Aug 2015 22:14:56 +0200 Subject: brcmfmac: only call brcmf_cfg80211_detach() when attach was successful In brcmf_bus_start() the function brcmf_cfg80211_attach() is called which may fail. If this happens we should not call brcmf_cfg80211_detach() in the failure path as it will result in NULL pointer dereference: brcmf_fweh_activate_events: Set event_msgs error (-5) brcmf_bus_start: failed: -5 brcmf_sdio_firmware_callback: dongle is not responding BUG: unable to handle kernel NULL pointer dereference at 0000000000000068 IP: [] kernfs_find_ns+0x18/0xd0 PGD 0 Oops: 0000 [#1] SMP Modules linked in: brcmfmac(O) brcmutil(O) cfg80211 auth_rpcgss CPU: 1 PID: 45 Comm: kworker/1:1 Tainted: G O Hardware name: Dell Inc. Latitude E6410/07XJP9, BIOS A07 02/15/2011 Workqueue: events request_firmware_work_func task: ffff880036c09ac0 ti: ffff880036dd4000 task.ti: ffff880036dd4000 RIP: 0010:[] [] kernfs_find_ns+0x18/0xd0 RSP: 0018:ffff880036dd7a28 EFLAGS: 00010246 RAX: ffff880036c09ac0 RBX: 0000000000000000 RCX: 000000007fffffff RDX: 0000000000000000 RSI: ffffffff816578b9 RDI: 0000000000000000 RBP: ffff880036dd7a48 R08: 0000000000000000 R09: ffff880036c0b340 R10: 00000000000002ec R11: ffff880036dd7b08 R12: ffffffff816578b9 R13: 0000000000000000 R14: ffffffff816578b9 R15: ffff8800c6c87000 FS: 0000000000000000(0000) GS:ffff88012bc40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000068 CR3: 0000000001a0b000 CR4: 00000000000006e0 Stack: 0000000000000000 ffffffff816578b9 0000000000000000 ffff8800c0d003c8 ffff880036dd7a78 ffffffff811e8ff5 0000000ffffffff1 ffffffff81a9b060 ffff8800c789f880 ffff8800c0d00000 ffff880036dd7a98 ffffffff811ebe0d Call Trace: [] kernfs_find_and_get_ns+0x35/0x60 [] sysfs_unmerge_group+0x1d/0x60 [] dpm_sysfs_remove+0x22/0x60 [] device_del+0x49/0x240 [] rfkill_unregister+0x58/0xc0 [] wiphy_unregister+0xab/0x2f0 [cfg80211] [] brcmf_cfg80211_detach+0x23/0x50 [brcmfmac] [] brcmf_detach+0x86/0xe0 [brcmfmac] [] brcmf_sdio_remove+0x48/0x120 [brcmfmac] [] brcmf_sdiod_remove+0x29/0xd0 [brcmfmac] [] brcmf_ops_sdio_remove+0xb1/0x110 [brcmfmac] [] sdio_bus_remove+0x37/0x100 [mmc_core] [] __device_release_driver+0x96/0x130 [] device_release_driver+0x23/0x30 [] brcmf_sdio_firmware_callback+0x2a8/0x5d0 [brcmfmac] [] brcmf_fw_request_nvram_done+0x15f/0x5e0 [brcmfmac] [] ? devres_add+0x3f/0x50 [] ? usermodehelper_read_unlock+0x15/0x20 [] ? platform_match+0x70/0xa0 [] request_firmware_work_func+0x30/0x60 [] process_one_work+0x14c/0x3d0 [] worker_thread+0x11a/0x450 [] ? process_one_work+0x3d0/0x3d0 [] kthread+0xd2/0xf0 [] ? kthread_create_on_node+0x180/0x180 [] ret_from_fork+0x3f/0x70 [] ? kthread_create_on_node+0x180/0x180 Code: e9 40 fe ff ff 48 89 d8 eb 87 66 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 89 e5 41 56 49 89 f6 41 55 49 89 d5 31 d2 41 54 53 <0f> b7 47 68 48 8b 5f 48 66 c1 e8 05 83 e0 01 4d 85 ed 0f b6 c8 RIP [] kernfs_find_ns+0x18/0xd0 RSP CR2: 0000000000000068 ---[ end trace 87d6ec0d3fe46740 ]--- Reported-by: Daniel (Deognyoun) Kim Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 157f0d7be350..126081acda1e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -1049,7 +1049,10 @@ int brcmf_bus_start(struct device *dev) fail: if (ret < 0) { brcmf_err("failed: %d\n", ret); - brcmf_cfg80211_detach(drvr->config); + if (drvr->config) { + brcmf_cfg80211_detach(drvr->config); + drvr->config = NULL; + } if (drvr->fws) { brcmf_fws_del_interface(ifp); brcmf_fws_deinit(drvr); -- cgit v1.2.3 From ddddfed2f9d8422fd5bb5080aa95e478832c0130 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Aug 2015 22:14:57 +0200 Subject: brcmfmac: correct detection of p2pdev interface event The p2pdev interface is setup in firmware resulting in a interface event. This event has role and no-if flag. When role is p2p client and no-if flag is set it indicates that this is the p2pdev interface. This info is used in handling the event and adding interface in the driver. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/core.c | 8 ++++---- drivers/net/wireless/brcm80211/brcmfmac/core.h | 2 +- drivers/net/wireless/brcm80211/brcmfmac/fweh.c | 15 +++++++-------- 3 files changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 126081acda1e..b9ed0ed32204 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -795,7 +795,7 @@ fail: } struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, - char *name, u8 *mac_addr) + bool is_p2pdev, char *name, u8 *mac_addr) { struct brcmf_if *ifp; struct net_device *ndev; @@ -821,7 +821,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, } } - if (!brcmf_p2p_enable && bssidx == 1) { + if (!brcmf_p2p_enable && is_p2pdev) { /* this is P2P_DEVICE interface */ brcmf_dbg(INFO, "allocate non-netdev interface\n"); ifp = kzalloc(sizeof(*ifp), GFP_KERNEL); @@ -999,12 +999,12 @@ int brcmf_bus_start(struct device *dev) brcmf_dbg(TRACE, "\n"); /* add primary networking interface */ - ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL); + ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL); if (IS_ERR(ifp)) return PTR_ERR(ifp); if (brcmf_p2p_enable) - p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL); + p2p_ifp = brcmf_add_if(drvr, 1, 0, false, "p2p%d", NULL); else p2p_ifp = NULL; if (IS_ERR(p2p_ifp)) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h index eb0c177be1db..5fb9f4be7de0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h @@ -205,7 +205,7 @@ char *brcmf_ifname(struct brcmf_pub *drvr, int idx); struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx); int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, - char *name, u8 *mac_addr); + bool is_p2pdev, char *name, u8 *mac_addr); void brcmf_remove_interface(struct brcmf_if *ifp); int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); void brcmf_txflowblock_if(struct brcmf_if *ifp, diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index 4d4cc2cd7668..1afaf97aebf7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -179,6 +179,7 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, { struct brcmf_if_event *ifevent = data; struct brcmf_if *ifp; + bool is_p2pdev; int err = 0; brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n", @@ -186,18 +187,16 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, ifevent->flags, ifevent->role); /* The P2P Device interface event must not be ignored - * contrary to what firmware tells us. The only way to - * distinguish the P2P Device is by looking at the ifidx - * and bssidx received. + * contrary to what firmware tells us. */ - if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) && - (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { + is_p2pdev = (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) && + ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT; + if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { brcmf_dbg(EVENT, "event can be ignored\n"); return; } if (ifevent->ifidx >= BRCMF_MAX_IFS) { - brcmf_err("invalid interface index: %u\n", - ifevent->ifidx); + brcmf_err("invalid interface index: %u\n", ifevent->ifidx); return; } @@ -207,7 +206,7 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname, emsg->addr); ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx, - emsg->ifname, emsg->addr); + is_p2pdev, emsg->ifname, emsg->addr); if (IS_ERR(ifp)) return; brcmf_fws_add_interface(ifp); -- cgit v1.2.3 From 46f3b6ee483898095906023e1ba3af2bddc38af9 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Aug 2015 22:14:58 +0200 Subject: brcmfmac: use brcmf_get_ifp() to map ifidx to struct brcmf_if instance The knowledge on how to map the interface index to a struct brcmf_if instance is in brcmf_get_ifp() so use that function when only the interface index is known instead of accessing brcmf_pub::iflist directly. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/btcoex.c | 4 ++-- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 2 +- drivers/net/wireless/brcm80211/brcmfmac/feature.c | 2 +- drivers/net/wireless/brcm80211/brcmfmac/flowring.c | 2 +- drivers/net/wireless/brcm80211/brcmfmac/fweh.c | 2 +- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 12 +++++++----- 6 files changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c index 0445163991b7..4e33f96b3dd1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c @@ -149,7 +149,7 @@ static s32 brcmf_btcoex_params_read(struct brcmf_if *ifp, u32 addr, u32 *data) static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci, bool trump_sco) { - struct brcmf_if *ifp = btci->cfg->pub->iflist[0]; + struct brcmf_if *ifp = brcmf_get_ifp(btci->cfg->pub, 0); if (trump_sco && !btci->saved_regs_part2) { /* this should reduce eSCO agressive @@ -468,7 +468,7 @@ int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif, { struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy); struct brcmf_btcoex_info *btci = cfg->btcoex; - struct brcmf_if *ifp = cfg->pub->iflist[0]; + struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); switch (mode) { case BRCMF_BTCOEX_DISABLED: diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 0c29bf61bb82..cee9ff46626e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -6213,7 +6213,7 @@ static void brcmf_free_wiphy(struct wiphy *wiphy) struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, struct device *busdev) { - struct net_device *ndev = drvr->iflist[0]->ndev; + struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev; struct brcmf_cfg80211_info *cfg; struct wiphy *wiphy; struct brcmf_cfg80211_vif *vif; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c index 1e94e94e01dc..7c2135faaf82 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c @@ -121,7 +121,7 @@ static void brcmf_feat_iovar_int_set(struct brcmf_if *ifp, void brcmf_feat_attach(struct brcmf_pub *drvr) { - struct brcmf_if *ifp = drvr->iflist[0]; + struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan"); brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn"); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c index 8d1ab4ab5be8..2ca783fa50cf 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c @@ -221,7 +221,7 @@ static void brcmf_flowring_block(struct brcmf_flowring *flow, u8 flowid, bus_if = dev_get_drvdata(flow->dev); drvr = bus_if->drvr; - ifp = drvr->iflist[ifidx]; + ifp = brcmf_get_ifp(drvr, ifidx); brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW, blocked); spin_unlock_irqrestore(&flow->block_lock, flags); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index 1afaf97aebf7..3330f30be8ef 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -334,7 +334,7 @@ void brcmf_fweh_attach(struct brcmf_pub *drvr) void brcmf_fweh_detach(struct brcmf_pub *drvr) { struct brcmf_fweh_info *fweh = &drvr->fweh; - struct brcmf_if *ifp = drvr->iflist[0]; + struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); s8 eventmask[BRCMF_EVENTING_MASK_LEN]; if (ifp) { diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index fd438739a91e..0c80c858462f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -972,7 +972,7 @@ static void brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq, u8 if_id) { - struct brcmf_if *ifp = fws->drvr->iflist[!if_id ? 0 : if_id + 1]; + struct brcmf_if *ifp = brcmf_get_ifp(fws->drvr, if_id); if (WARN_ON(!ifp)) return; @@ -2118,6 +2118,7 @@ static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data) int brcmf_fws_init(struct brcmf_pub *drvr) { struct brcmf_fws_info *fws; + struct brcmf_if *ifp; u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS; int rc; u32 mode; @@ -2177,21 +2178,22 @@ int brcmf_fws_init(struct brcmf_pub *drvr) * continue. Set mode back to none indicating not enabled. */ fws->fw_signals = true; - if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) { + ifp = brcmf_get_ifp(drvr, 0); + if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) { brcmf_err("failed to set bdcv2 tlv signaling\n"); fws->fcmode = BRCMF_FWS_FCMODE_NONE; fws->fw_signals = false; } - if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1)) + if (brcmf_fil_iovar_int_set(ifp, "ampdu_hostreorder", 1)) brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n"); /* Enable seq number reuse, if supported */ - if (brcmf_fil_iovar_int_get(drvr->iflist[0], "wlfc_mode", &mode) == 0) { + if (brcmf_fil_iovar_int_get(ifp, "wlfc_mode", &mode) == 0) { if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) { mode = 0; BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1); - if (brcmf_fil_iovar_int_set(drvr->iflist[0], + if (brcmf_fil_iovar_int_set(ifp, "wlfc_mode", mode) == 0) { BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1); } -- cgit v1.2.3 From 054e68add65972af20dbf0848e25c80828c5cd60 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Aug 2015 22:14:59 +0200 Subject: brcmfmac: pass struct brcmf_if instance in brcmf_txfinalize() Most call sites of brcmf_txfinalize already have struct brcmf_if instance so pass that to brcmf_txfinalize() as the function needs it anyway. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/core.c | 12 +++--------- drivers/net/wireless/brcm80211/brcmfmac/core.h | 3 +-- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 11 ++++++----- drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | 6 +++++- 4 files changed, 15 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index b9ed0ed32204..cd0bffe282c6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -560,17 +560,11 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb) brcmf_netif_rx(ifp, skb); } -void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, - bool success) +void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success) { - struct brcmf_if *ifp; struct ethhdr *eh; u16 type; - ifp = drvr->iflist[ifidx]; - if (!ifp) - goto done; - eh = (struct ethhdr *)(txp->data); type = ntohs(eh->h_proto); @@ -582,7 +576,7 @@ void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, if (!success) ifp->stats.tx_errors++; -done: + brcmu_pkt_buf_free_skb(txp); } @@ -600,7 +594,7 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) if (brcmf_proto_hdrpull(drvr, false, txp, &ifp)) brcmu_pkt_buf_free_skb(txp); else - brcmf_txfinalize(drvr, txp, ifp->ifidx, success); + brcmf_txfinalize(ifp, txp, success); } } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h index 5fb9f4be7de0..576e7ac2d668 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h @@ -210,8 +210,7 @@ void brcmf_remove_interface(struct brcmf_if *ifp); int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); void brcmf_txflowblock_if(struct brcmf_if *ifp, enum brcmf_netif_stop_reason reason, bool state); -void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, - bool success); +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); /* Sets dongle media info (drv_version, mac address). */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 0c80c858462f..dc4844c301ac 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1506,7 +1506,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx, genbit, seq); if (remove_from_hanger || ret) - brcmf_txfinalize(fws->drvr, skb, ifp->ifidx, true); + brcmf_txfinalize(ifp, skb, true); return 0; } @@ -1905,7 +1905,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) if (fws->avoid_queueing) { rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb); if (rc < 0) - brcmf_txfinalize(drvr, skb, ifp->ifidx, false); + brcmf_txfinalize(ifp, skb, false); return rc; } @@ -1929,7 +1929,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) brcmf_fws_schedule_deq(fws); } else { brcmf_err("drop skb: no hanger slot\n"); - brcmf_txfinalize(drvr, skb, ifp->ifidx, false); + brcmf_txfinalize(ifp, skb, false); rc = -ENOMEM; } brcmf_fws_unlock(fws); @@ -2009,8 +2009,9 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) ret = brcmf_proto_txdata(drvr, ifidx, 0, skb); brcmf_fws_lock(fws); if (ret < 0) - brcmf_txfinalize(drvr, skb, ifidx, - false); + brcmf_txfinalize(brcmf_get_ifp(drvr, + ifidx), + skb, false); if (fws->bus_flow_blocked) break; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c index d582f6993574..7eff9de6885b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c @@ -873,7 +873,11 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf) commonring = msgbuf->flowrings[flowid]; atomic_dec(&commonring->outstanding_tx); - brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true); + /* Hante: i believe this was a bug as tx_status->msg.ifidx was used + * in brcmf_txfinalize as index in drvr->iflist. Can you confirm/deny? + */ + brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx), + skb, true); } -- cgit v1.2.3 From 291da87b69109924e6ee526606a783668d2232e0 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Aug 2015 22:15:00 +0200 Subject: brcmfmac: add mapping for interface index to bsscfg index Because the P2P Device interface in firmware uses the same interface index as the primary interface we use the bsscfg index as index in the struct brcmf_pub::iflist. However, in the data path we get the interface index and not the bsscfg index. So we need a mapping of interface index to bsscfg index, which can be determined upon handle adding the interface. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/core.c | 22 +++++++++++++--------- drivers/net/wireless/brcm80211/brcmfmac/core.h | 1 + 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index cd0bffe282c6..5d81b74efb66 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -85,21 +85,20 @@ char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx) { + struct brcmf_if *ifp; + s32 bssidx; + if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { brcmf_err("ifidx %d out of range\n", ifidx); return NULL; } - /* The ifidx is the idx to map to matching netdev/ifp. When receiving - * events this is easy because it contains the bssidx which maps - * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. - * bssidx 1 is used for p2p0 and no data can be received or - * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 - */ - if (ifidx) - ifidx++; + ifp = NULL; + bssidx = drvr->if2bss[ifidx]; + if (bssidx >= 0) + ifp = drvr->iflist[bssidx]; - return drvr->iflist[ifidx]; + return ifp; } static void _brcmf_set_multicast_list(struct work_struct *work) @@ -831,6 +830,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, ifp = netdev_priv(ndev); ifp->ndev = ndev; + /* store mapping ifidx to bssidx */ + drvr->if2bss[ifidx] = bssidx; } ifp->drvr = drvr; @@ -855,6 +856,7 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) struct brcmf_if *ifp; ifp = drvr->iflist[bssidx]; + drvr->if2bss[ifp->ifidx] = -1; drvr->iflist[bssidx] = NULL; if (!ifp) { brcmf_err("Null interface, idx=%d\n", bssidx); @@ -862,6 +864,7 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) } brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx); if (ifp->ndev) { + drvr->if2bss[ifp->ifidx] = -1; if (bssidx == 0) { if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { rtnl_lock(); @@ -926,6 +929,7 @@ int brcmf_attach(struct device *dev) if (!drvr) return -ENOMEM; + memset(drvr->if2bss, 0xFF, sizeof(drvr->if2bss)); mutex_init(&drvr->proto_block); /* Link to bus module */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h index 576e7ac2d668..d81ff95acab5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h @@ -122,6 +122,7 @@ struct brcmf_pub { struct mac_address addresses[BRCMF_MAX_IFS]; struct brcmf_if *iflist[BRCMF_MAX_IFS]; + s32 if2bss[BRCMF_MAX_IFS]; struct mutex proto_block; unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; -- cgit v1.2.3 From 9d6c1dc4f9136227b39faf98ae46d0228fe1fa19 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Aug 2015 22:15:01 +0200 Subject: brcmfmac: add dedicated debug level for firmware console logging Both PCIe and SDIO devices have the possibility to log the firmware console output in kernel log. For PCIe it is logged when PCIE debug level is enabled. For SDIO it is logged when user specifies a non-zero console interval through debugfs. This patch tries to make it a bit more consistent. The firmware console output is only logged when FWCON debug level is enabled. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Pontus Fuchs Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/debug.h | 3 +++ drivers/net/wireless/brcm80211/brcmfmac/pcie.c | 7 +++++-- drivers/net/wireless/brcm80211/brcmfmac/sdio.c | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/brcm80211/brcmfmac/debug.h index eb0b8c47479d..48648ca44ba8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h @@ -37,6 +37,7 @@ #define BRCMF_SDIO_VAL 0x00020000 #define BRCMF_MSGBUF_VAL 0x00040000 #define BRCMF_PCIE_VAL 0x00080000 +#define BRCMF_FWCON_VAL 0x00100000 /* set default print format */ #undef pr_fmt @@ -78,6 +79,7 @@ do { \ #define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) #define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL) +#define BRCMF_FWCON_ON() (brcmf_msg_level & BRCMF_FWCON_VAL) #else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */ @@ -90,6 +92,7 @@ do { \ #define BRCMF_GLOM_ON() 0 #define BRCMF_EVENT_ON() 0 #define BRCMF_FIL_ON() 0 +#define BRCMF_FWCON_ON() 0 #endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index 3a98c4306d1d..e75d04e89ac2 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c @@ -644,7 +644,7 @@ static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo) addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET; console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr); - brcmf_dbg(PCIE, "Console: base %x, buf %x, size %d\n", + brcmf_dbg(FWCON, "Console: base %x, buf %x, size %d\n", console->base_addr, console->buf_addr, console->bufsize); } @@ -656,6 +656,9 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo) u8 ch; u32 newidx; + if (!BRCMF_FWCON_ON()) + return; + console = &devinfo->shared.console; addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET; newidx = brcmf_pcie_read_tcm32(devinfo, addr); @@ -677,7 +680,7 @@ static void brcmf_pcie_bus_console_read(struct brcmf_pciedev_info *devinfo) } if (ch == '\n') { console->log_str[console->log_idx] = 0; - brcmf_dbg(PCIE, "CONSOLE: %s", console->log_str); + pr_debug("CONSOLE: %s", console->log_str); console->log_idx = 0; } } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index f990e3d0e696..e41bf441410b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c @@ -123,6 +123,7 @@ struct rte_console { #define BRCMF_FIRSTREAD (1 << 6) +#define BRCMF_CONSOLE 10 /* watchdog interval to poll console */ /* SBSDIO_DEVICE_CTL */ @@ -3204,6 +3205,8 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus) if (IS_ERR_OR_NULL(dentry)) return; + bus->console_interval = BRCMF_CONSOLE; + brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read); brcmf_debugfs_add_entry(drvr, "counters", brcmf_debugfs_sdio_count_read); @@ -3613,7 +3616,7 @@ static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) } #ifdef DEBUG /* Poll for console output periodically */ - if (bus->sdiodev->state == BRCMF_SDIOD_DATA && + if (bus->sdiodev->state == BRCMF_SDIOD_DATA && BRCMF_FWCON_ON() && bus->console_interval != 0) { bus->console.count += BRCMF_WD_POLL_MS; if (bus->console.count >= bus->console_interval) { -- cgit v1.2.3 From 03cca20a6ee15b25487b4992eda2c3bf08d1f1c1 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Aug 2015 22:15:02 +0200 Subject: brcmfmac: remove ifidx parameter from brcmf_fws_txstatus_suppressed() The brcmf_fws_txstatus_suppressed() function prototype specifies an ifidx parameter which is not used within the function implementation. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index dc4844c301ac..ed124867a0f4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1398,7 +1398,7 @@ done: } static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, - struct sk_buff *skb, u8 ifidx, + struct sk_buff *skb, u32 genbit, u16 seq) { struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; @@ -1503,7 +1503,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, return -EINVAL; } if (!remove_from_hanger) - ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx, + ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit, seq); if (remove_from_hanger || ret) brcmf_txfinalize(ifp, skb, true); -- cgit v1.2.3 From c67d41ba6ff3a4be9aecb9df202e05e149832df5 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Aug 2015 22:15:03 +0200 Subject: brcmfmac: change prototype for brcmf_fws_hdrpull() Instead of passing ifidx and drvr just pass struct brcmf_if pointer which holds both parameters. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/bcdc.c | 3 +-- drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 23 ++++++++++------------ drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h | 3 +-- 3 files changed, 12 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c index aa5ed651625d..288c84e7c56b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c @@ -312,8 +312,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, skb_pull(pktbuf, BCDC_HEADER_LEN); if (do_fws) - brcmf_fws_hdrpull(drvr, tmp_if->ifidx, h->data_offset << 2, - pktbuf); + brcmf_fws_hdrpull(tmp_if, h->data_offset << 2, pktbuf); else skb_pull(pktbuf, h->data_offset << 2); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index ed124867a0f4..086cac3f86d6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c @@ -1616,11 +1616,10 @@ static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp, return 0; } -int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, - struct sk_buff *skb) +void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb) { struct brcmf_skb_reorder_data *rd; - struct brcmf_fws_info *fws = drvr->fws; + struct brcmf_fws_info *fws = ifp->drvr->fws; u8 *signal_data; s16 data_len; u8 type; @@ -1630,20 +1629,20 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, s32 err; brcmf_dbg(HDRS, "enter: ifidx %d, skblen %u, sig %d\n", - ifidx, skb->len, signal_len); + ifp->ifidx, skb->len, siglen); - WARN_ON(signal_len > skb->len); + WARN_ON(siglen > skb->len); - if (!signal_len) - return 0; + if (!siglen) + return; /* if flow control disabled, skip to packet data and leave */ if ((!fws) || (!fws->fw_signals)) { - skb_pull(skb, signal_len); - return 0; + skb_pull(skb, siglen); + return; } fws->stats.header_pulls++; - data_len = signal_len; + data_len = siglen; signal_data = skb->data; status = BRCMF_FWS_RET_OK_NOSCHEDULE; @@ -1731,14 +1730,12 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, /* signalling processing result does * not affect the actual ethernet packet. */ - skb_pull(skb, signal_len); + skb_pull(skb, siglen); /* this may be a signal-only packet */ if (skb->len == 0) fws->stats.header_only_pkt++; - - return 0; } static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h index 9fc860910bd8..a36bac17eafd 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h @@ -21,8 +21,7 @@ int brcmf_fws_init(struct brcmf_pub *drvr); void brcmf_fws_deinit(struct brcmf_pub *drvr); bool brcmf_fws_fc_active(struct brcmf_fws_info *fws); -int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, - struct sk_buff *skb); +void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb); int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb); void brcmf_fws_reset_interface(struct brcmf_if *ifp); -- cgit v1.2.3 From 95ef12394a4d002c7ed3bcbed224f3391792a02b Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 26 Aug 2015 22:15:04 +0200 Subject: brcmfmac: introduce brcmf_net_detach() function In case of error during brcmf_bus_start() the network interfaces were freed using free_netdev(). However, the interfaces may have additional memory allocated which is not freed. The netdev has destructor set to brcmf_cfg80211_free_netdev() which frees the additional memory if allocated and call free_netdev(). The brcmf_net_detach() either calls brcmf_cfg80211_free_netdev() directly or uses unregister_netdev() when struct net_device::reg_state indicates the netdev was registered. Reported-by: Daniel (Deognyoun) Kim Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 3 ++- drivers/net/wireless/brcm80211/brcmfmac/core.c | 21 +++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index cee9ff46626e..600098dd197c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -4747,7 +4747,8 @@ void brcmf_cfg80211_free_netdev(struct net_device *ndev) ifp = netdev_priv(ndev); vif = ifp->vif; - brcmf_free_vif(vif); + if (vif) + brcmf_free_vif(vif); free_netdev(ndev); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 5d81b74efb66..17658b59c36c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -718,8 +718,6 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) } brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); - - ndev->destructor = brcmf_cfg80211_free_netdev; return 0; fail: @@ -729,6 +727,14 @@ fail: return -EBADE; } +static void brcmf_net_detach(struct net_device *ndev) +{ + if (ndev->reg_state == NETREG_REGISTERED) + unregister_netdev(ndev); + else + brcmf_cfg80211_free_netdev(ndev); +} + static int brcmf_net_p2p_open(struct net_device *ndev) { brcmf_dbg(TRACE, "Enter\n"); @@ -805,8 +811,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, ifp->ndev->name); if (ifidx) { netif_stop_queue(ifp->ndev); - unregister_netdev(ifp->ndev); - free_netdev(ifp->ndev); + brcmf_net_detach(ifp->ndev); drvr->iflist[bssidx] = NULL; } else { brcmf_err("ignore IF event\n"); @@ -828,6 +833,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, if (!ndev) return ERR_PTR(-ENOMEM); + ndev->destructor = brcmf_cfg80211_free_netdev; ifp = netdev_priv(ndev); ifp->ndev = ndev; /* store mapping ifidx to bssidx */ @@ -879,8 +885,7 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) cancel_work_sync(&ifp->setmacaddr_work); cancel_work_sync(&ifp->multicast_work); } - /* unregister will take care of freeing it */ - unregister_netdev(ifp->ndev); + brcmf_net_detach(ifp->ndev); } } @@ -1056,11 +1061,11 @@ fail: brcmf_fws_deinit(drvr); } if (drvr->iflist[0]) { - free_netdev(ifp->ndev); + brcmf_net_detach(ifp->ndev); drvr->iflist[0] = NULL; } if (p2p_ifp) { - free_netdev(p2p_ifp->ndev); + brcmf_net_detach(p2p_ifp->ndev); drvr->iflist[1] = NULL; } return ret; -- cgit v1.2.3 From 07fe2e38c7fd19dc6a5468d0661fc75586ce9ca4 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 27 Aug 2015 16:14:06 +0200 Subject: brcmfmac: Reset PCIE devices after recognition. When PCIE type devices are being FW reloaded without being properly reset then the device ends up in a locked state, requiring the device to be completely powered down. This patch adds a reset through watchdog at the moment the device (cores) has been recognized. This will solve warm reboot issues. Cc: Rafal Milecki Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/chip.c | 18 +++++++ drivers/net/wireless/brcm80211/brcmfmac/chip.h | 1 + drivers/net/wireless/brcm80211/brcmfmac/pcie.c | 66 ++++++++++++++++++-------- 3 files changed, 64 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index 288f8314f208..e3b8e235620e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c @@ -101,6 +101,9 @@ /* ARM Cortex M3 core, ID 0x82a */ #define BCM4329_CORE_ARM_BASE 0x18002000 +/* Max possibly supported memory size (limited by IO mapped memory) */ +#define BRCMF_CHIP_MAX_MEMSIZE (4 * 1024 * 1024) + #define CORE_SB(base, field) \ (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) #define SBCOREREV(sbidh) \ @@ -687,6 +690,12 @@ static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) brcmf_err("RAM size is undetermined\n"); return -ENOMEM; } + + if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) { + brcmf_err("RAM size is incorrect\n"); + return -ENOMEM; + } + return 0; } @@ -899,6 +908,15 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) /* assure chip is passive for core access */ brcmf_chip_set_passive(&ci->pub); + + /* Call bus specific reset function now. Cores have been determined + * but further access may require a chip specific reset at this point. + */ + if (ci->ops->reset) { + ci->ops->reset(ci->ctx, &ci->pub); + brcmf_chip_set_passive(&ci->pub); + } + return brcmf_chip_get_raminfo(ci); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/brcm80211/brcmfmac/chip.h index 60dcb38fc77a..f6b5feea23d2 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h @@ -73,6 +73,7 @@ struct brcmf_buscore_ops { u32 (*read32)(void *ctx, u32 addr); void (*write32)(void *ctx, u32 addr, u32 value); int (*prepare)(void *ctx); + int (*reset)(void *ctx, struct brcmf_chip *chip); int (*setup)(void *ctx, struct brcmf_chip *chip); void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec); }; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index e75d04e89ac2..255d49a5b0a3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c @@ -74,6 +74,8 @@ enum brcmf_pcie_state { #define BRCMF_PCIE_REG_INTMASK 0x94 #define BRCMF_PCIE_REG_SBMBX 0x98 +#define BRCMF_PCIE_REG_LINK_STATUS_CTRL 0xBC + #define BRCMF_PCIE_PCIE2REG_INTMASK 0x24 #define BRCMF_PCIE_PCIE2REG_MAILBOXINT 0x48 #define BRCMF_PCIE_PCIE2REG_MAILBOXMASK 0x4C @@ -466,6 +468,7 @@ brcmf_pcie_select_core(struct brcmf_pciedev_info *devinfo, u16 coreid) static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo) { + struct brcmf_core *core; u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD, BRCMF_PCIE_CFGREG_PM_CSR, BRCMF_PCIE_CFGREG_MSI_CAP, @@ -484,32 +487,38 @@ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo) if (!devinfo->ci) return; + /* Disable ASPM */ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, - BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL); - lsc = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA); + pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL, + &lsc); val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB); - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, val); + pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL, + val); + /* Watchdog reset */ brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON); WRITECC32(devinfo, watchdog, 4); msleep(100); + /* Restore ASPM */ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, - BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL); - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, lsc); - - brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); - for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) { - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, - cfg_offset[i]); - val = brcmf_pcie_read_reg32(devinfo, - BRCMF_PCIE_PCIE2REG_CONFIGDATA); - brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n", - cfg_offset[i], val); - brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, - val); + pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL, + lsc); + + core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2); + if (core->rev <= 13) { + for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) { + brcmf_pcie_write_reg32(devinfo, + BRCMF_PCIE_PCIE2REG_CONFIGADDR, + cfg_offset[i]); + val = brcmf_pcie_read_reg32(devinfo, + BRCMF_PCIE_PCIE2REG_CONFIGDATA); + brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n", + cfg_offset[i], val); + brcmf_pcie_write_reg32(devinfo, + BRCMF_PCIE_PCIE2REG_CONFIGDATA, + val); + } } } @@ -519,8 +528,6 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo) u32 config; brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); - if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) - brcmf_pcie_reset_device(devinfo); /* 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); @@ -1636,6 +1643,23 @@ static int brcmf_pcie_buscoreprep(void *ctx) } +static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip) +{ + struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; + u32 val; + + devinfo->ci = chip; + brcmf_pcie_reset_device(devinfo); + + val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT); + if (val != 0xffffffff) + brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, + val); + + return 0; +} + + static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip, u32 rstvec) { @@ -1647,6 +1671,7 @@ static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip, static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { .prepare = brcmf_pcie_buscoreprep, + .reset = brcmf_pcie_buscore_reset, .activate = brcmf_pcie_buscore_activate, .read32 = brcmf_pcie_buscore_read32, .write32 = brcmf_pcie_buscore_write32, @@ -1814,7 +1839,6 @@ brcmf_pcie_remove(struct pci_dev *pdev) brcmf_pcie_intr_disable(devinfo); brcmf_detach(&pdev->dev); - brcmf_pcie_reset_device(devinfo); kfree(bus->bus_priv.pcie); kfree(bus->msgbuf->flowrings); -- cgit v1.2.3 From 36925e52c5ac9d10a553d1339e13a61bfbdd4ba4 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 31 Aug 2015 10:46:45 -0700 Subject: mwifiex: Make mwifiex_dbg a function, reduce object size The mwifiex_dbg macro has two tests that could be consolidated into a function reducing overall object size ~10KB (~4%). So convert the macro into a function. $ size drivers/net/wireless/mwifiex/built-in.o* (x86-64 defconfig) text data bss dec hex filename 233102 8628 4809 246539 3c30b drivers/net/wireless/mwifiex/built-in.o.new 243949 8628 4809 257386 3ed6a drivers/net/wireless/mwifiex/built-in.o.old Signed-off-by: Joe Perches Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/main.c | 20 ++++++++++++++++++++ drivers/net/wireless/mwifiex/main.h | 17 ++++++++--------- 2 files changed, 28 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 278dc94eaecb..4fa8ca33937d 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -1447,6 +1447,26 @@ exit_sem_err: } EXPORT_SYMBOL_GPL(mwifiex_remove_card); +void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + if (!adapter->dev || !(adapter->debug_mask & mask)) + return; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + dev_info(adapter->dev, "%pV", &vaf); + + va_end(args); +} +EXPORT_SYMBOL_GPL(_mwifiex_dbg); + /* * This function initializes the module. * diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 6b9512140e7a..966632147079 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -48,6 +48,9 @@ extern const char driver_version[]; +struct mwifiex_adapter; +struct mwifiex_private; + enum { MWIFIEX_ASYNC_CMD, MWIFIEX_SYNC_CMD @@ -180,12 +183,11 @@ enum MWIFIEX_DEBUG_LEVEL { MWIFIEX_DBG_FATAL | \ MWIFIEX_DBG_ERROR) -#define mwifiex_dbg(adapter, dbg_mask, fmt, args...) \ -do { \ - if ((adapter)->debug_mask & MWIFIEX_DBG_##dbg_mask) \ - if ((adapter)->dev) \ - dev_info((adapter)->dev, fmt, ## args); \ -} while (0) +__printf(3, 4) +void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask, + const char *fmt, ...); +#define mwifiex_dbg(adapter, mask, fmt, ...) \ + _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__) #define DEBUG_DUMP_DATA_MAX_LEN 128 #define mwifiex_dbg_dump(adapter, dbg_mask, str, buf, len) \ @@ -506,9 +508,6 @@ enum mwifiex_iface_work_flags { MWIFIEX_IFACE_WORK_CARD_RESET, }; -struct mwifiex_adapter; -struct mwifiex_private; - struct mwifiex_private { struct mwifiex_adapter *adapter; u8 bss_type; -- cgit v1.2.3 From 61d36370e24bb5d8f83481aa6f76fc05385c75c9 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Tue, 1 Sep 2015 10:56:09 +0800 Subject: ath9k: enable hw manual peak calibration for QCA9561 This patch fix https://lists.openwrt.org/pipermail/openwrt-devel/ 2015-August/034979.html. As the peak detect calibration is set incorrectly. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 174442beb952..0c391997a2f7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -1249,7 +1249,8 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0); - if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) { + if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || + AR_SREV_9561(ah)) { if (is_2g) REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, @@ -1640,7 +1641,8 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, skip_tx_iqcal: if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { - if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) { + if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah) || + AR_SREV_9561(ah)) { for (i = 0; i < AR9300_MAX_CHAINS; i++) { if (!(ah->rxchainmask & (1 << i))) continue; -- cgit v1.2.3 From 76ea6fdbeb2540ea8a06189b519175ee5616ab56 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Wed, 2 Sep 2015 16:56:42 -0700 Subject: net/wireless/wl18xx: Add missing MODULE_FIRMWARE Fixes the output of 'modinfo --field firmware'. Signed-off-by: Geoff Levand Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wl18xx/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index abbf054fb6da..50cce42089a5 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -2115,3 +2115,4 @@ MODULE_PARM_DESC(num_rx_desc_param, MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Luciano Coelho "); MODULE_FIRMWARE(WL18XX_FW_NAME); +MODULE_FIRMWARE(WL18XX_CONF_FILE_NAME); -- cgit v1.2.3 From c452d944bee09c8c2529d965f10999d80991402a Mon Sep 17 00:00:00 2001 From: Hiroaki KAWAI Date: Thu, 10 Sep 2015 18:04:45 +0000 Subject: carl9170: fix bad rssi reading Fix rssi calculation error which was introduced in otus to ar9170 porting. Signed-off-by: Hiroaki KAWAI Acked-by: Christian Lamparter Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/carl9170/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index 924135b8e575..d66533cbc38a 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -453,7 +453,7 @@ static void carl9170_rx_phy_status(struct ar9170 *ar, /* post-process RSSI */ for (i = 0; i < 7; i++) if (phy->rssi[i] & 0x80) - phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f; + phy->rssi[i] = ((~phy->rssi[i] & 0x7f) + 1) & 0x7f; /* TODO: we could do something with phy_errors */ status->signal = ar->noise[0] + phy->rssi_combined; -- cgit v1.2.3 From 862a336c8302695cbac6d8d752ee9a2429487478 Mon Sep 17 00:00:00 2001 From: Jan Kaisrlik Date: Thu, 17 Sep 2015 14:03:46 +0200 Subject: ath9k: Add support for OCB mode The patch adds support for "outside the context of a BSS"(OCB) mode to ath9k driver and extends debugfs files by OCB ralated information. This patch was tested on AR9380-AL1A cards. Signed-off-by: Jan Kaisrlik Cc: Michal Sojka Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/debug.c | 4 ++-- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 3 ++- drivers/net/wireless/ath/ath9k/hw.c | 1 + drivers/net/wireless/ath/ath9k/init.c | 3 ++- drivers/net/wireless/ath/ath9k/main.c | 8 +++++++- drivers/net/wireless/ath/ath9k/recv.c | 2 +- 7 files changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index c85c47978e1e..b42f4a963ef4 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -635,6 +635,7 @@ struct ath9k_vif_iter_data { int nstations; /* number of station vifs */ int nwds; /* number of WDS vifs */ int nadhocs; /* number of adhoc vifs */ + int nocbs; /* number of OCB vifs */ struct ieee80211_vif *primary_sta; }; diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index da32c8faad94..6de64cface3c 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -741,8 +741,8 @@ static int read_file_misc(struct seq_file *file, void *data) i++, (int)(ctx->assigned), iter_data.naps, iter_data.nstations, iter_data.nmeshes, iter_data.nwds); - seq_printf(file, " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n", - iter_data.nadhocs, sc->cur_chan->nvifs, + seq_printf(file, " ADHOC: %i OCB: %i TOTAL: %hi BEACON-VIF: %hi\n", + iter_data.nadhocs, iter_data.nocbs, sc->cur_chan->nvifs, sc->nbcnvifs); } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index efe77db96570..8647ab77c019 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -740,7 +740,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_MESH_POINT); + BIT(NL80211_IFTYPE_MESH_POINT) | + BIT(NL80211_IFTYPE_OCB); hw->wiphy->iface_combinations = &if_comb; hw->wiphy->n_iface_combinations = 1; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 1dd0339de372..bdfff4641931 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1241,6 +1241,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) break; } /* fall through */ + case NL80211_IFTYPE_OCB: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_AP: set |= AR_STA_ID1_STA_AP; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 57f95f2dca5b..5d532c7b813f 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -855,7 +855,8 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT) | - BIT(NL80211_IFTYPE_WDS); + BIT(NL80211_IFTYPE_WDS) | + BIT(NL80211_IFTYPE_OCB); if (ath9k_is_chanctx_enabled()) hw->wiphy->interface_modes |= diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c27143ba9ffb..56abb9ddae67 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -938,6 +938,9 @@ static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data, if (avp->assoc && !iter_data->primary_sta) iter_data->primary_sta = vif; break; + case NL80211_IFTYPE_OCB: + iter_data->nocbs++; + break; case NL80211_IFTYPE_ADHOC: iter_data->nadhocs++; if (vif->bss_conf.enable_beacon) @@ -1111,6 +1114,8 @@ void ath9k_calculate_summary_state(struct ath_softc *sc, if (iter_data.nmeshes) ah->opmode = NL80211_IFTYPE_MESH_POINT; + else if (iter_data.nocbs) + ah->opmode = NL80211_IFTYPE_OCB; else if (iter_data.nwds) ah->opmode = NL80211_IFTYPE_AP; else if (iter_data.nadhocs) @@ -1760,7 +1765,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, ath9k_calculate_summary_state(sc, avp->chanctx); } - if (changed & BSS_CHANGED_IBSS) { + if ((changed & BSS_CHANGED_IBSS) || + (changed & BSS_CHANGED_OCB)) { memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); common->curaid = bss_conf->aid; ath9k_hw_write_associd(sc->sc_ah); diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index d3189daf9996..994daf6c6297 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -403,7 +403,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) (sc->cur_chan->nvifs <= 1) && !(sc->cur_chan->rxfilter & FIF_BCN_PRBRESP_PROMISC)) rfilt |= ATH9K_RX_FILTER_MYBEACON; - else + else if (sc->sc_ah->opmode != NL80211_IFTYPE_OCB) rfilt |= ATH9K_RX_FILTER_BEACON; if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || -- cgit v1.2.3 From 32677b25849f627aba27235f4cbf65663a0cc1a6 Mon Sep 17 00:00:00 2001 From: Guodong Xu Date: Fri, 18 Sep 2015 20:37:27 +0800 Subject: wlcore: align reg_ch_conf_last[] to 64bit Align fields reg_ch_conf_last and reg_ch_conf_pending of struct wl1271{} to 64bit. Without this, on 64bit ARM, wlcore_set_pending_regdomain_ch() fails at the point it calls set_bit(ch_bit_idx, (long*)wl->reg_ch_conf_pending); Here is the error message while doing iw wlan0 scan or connect: [ 10.666857] wlcore: IRQ work [ 10.670046] wlcore: intr: 0x40 (fw_rx_counter = 1, drv_rx_counter = 0, tx_results_counter = 0) [ 10.678697] wlcore: WL1271_ACX_INTR_DATA [ 10.682810] Unhandled fault: alignment fault (0x96000021) at 0xffffffc037a817f4 [ 10.690139] Internal error: : 96000021 [#1] PREEMPT SMP [ 10.695366] Modules linked in: [ 10.698437] CPU: 3 PID: 894 Comm: irq/60-wl18xx Tainted: G W 4.2.0-rc6-linaro-hikey #2 [ 10.707501] Hardware name: HiKey Development Board (DT) [ 10.712733] task: ffffffc03a9d1680 ti: ffffffc039e18000 task.ti: ffffffc039e18000 [ 10.720239] PC is at set_bit+0x14/0x30 [ 10.724002] LR is at wlcore_set_pending_regdomain_ch+0x40/0x4c Signed-off-by: Guodong Xu Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wlcore/wlcore.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index a1b6040e6491..906be6aa4eb6 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -318,7 +318,7 @@ struct wl1271 { bool watchdog_recovery; /* Reg domain last configuration */ - u32 reg_ch_conf_last[2]; + u32 reg_ch_conf_last[2] __aligned(8); /* Reg domain pending configuration */ u32 reg_ch_conf_pending[2]; -- cgit v1.2.3 From 65405c51bb2e9d2a348f5402443e31f82411aabb Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Fri, 18 Sep 2015 06:32:03 -0700 Subject: mwifiex: fix typo in del_virtual_intf() function Interface counters should be incremented in add_virtual_intf() and decremented in del_virtual_intf() function. This patch corrects it. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/cfg80211.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index ff63cb5632eb..d8143409da60 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -2859,14 +2859,14 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_ADHOC: - adapter->curr_iface_comb.sta_intf++; + adapter->curr_iface_comb.sta_intf--; break; case NL80211_IFTYPE_AP: - adapter->curr_iface_comb.uap_intf++; + adapter->curr_iface_comb.uap_intf--; break; case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_GO: - adapter->curr_iface_comb.p2p_intf++; + adapter->curr_iface_comb.p2p_intf--; break; default: mwifiex_dbg(adapter, ERROR, -- cgit v1.2.3 From 0a252abb6ad75260353a28c08b904c2c9d258d2c Mon Sep 17 00:00:00 2001 From: Zhaoyang Liu Date: Fri, 18 Sep 2015 06:32:04 -0700 Subject: mwifiex: update amsdu tx packet time stamp This patch fixes the issue of delay time in A-MSDU tx packet. In generated new A-MSDU packet, the time stamp is initialized to zero. Choose the time of first MSDU packet as aggregated packet's time. Signed-off-by: Zhaoyang Liu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/11n_aggr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index f7c717253a66..6cb0d33b0636 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -202,6 +202,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT; skb_aggr->priority = skb_src->priority; + skb_aggr->tstamp = skb_src->tstamp; do_gettimeofday(&tv); skb_aggr->tstamp = timeval_to_ktime(tv); -- cgit v1.2.3 From e3ad3d5b6ab2a9876773fe99d9d1866d3c1744ae Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Fri, 18 Sep 2015 06:32:05 -0700 Subject: mwifiex: minor corrections in multiport aggregation code This patch includes below changes 1) Check if multiport aggregation feature flag while doing rx length validation check. 2) Reset buffer size variables when buffers are freed. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/sdio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 5d05c6fe6429..d35210caa94b 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -1606,8 +1606,9 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) (rx_len + MWIFIEX_SDIO_BLOCK_SIZE - 1) / MWIFIEX_SDIO_BLOCK_SIZE; if (rx_len <= INTF_HEADER_LEN || - (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > - card->mpa_rx.buf_size) { + (card->mpa_rx.enabled && + ((rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > + card->mpa_rx.buf_size))) { mwifiex_dbg(adapter, ERROR, "invalid rx_len=%d\n", rx_len); @@ -1925,6 +1926,8 @@ error: if (ret) { kfree(card->mpa_tx.buf); kfree(card->mpa_rx.buf); + card->mpa_tx.buf_size = 0; + card->mpa_rx.buf_size = 0; } return ret; -- cgit v1.2.3 From 9a9053c3420fcc5779319e4ea267c6dcbf8d7c04 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Fri, 18 Sep 2015 06:32:06 -0700 Subject: mwifiex: fix driver init failure under memory pressure 64k Tx and Rx buffers are allocated during driver initialization for SDIO level data aggregations. When host is under memory pressure situation, kzalloc() request for 64k may fail. We will try allocating 32k buffers and disable our rx single port aggreagation feature in this situation. If the allocation still fails, we will disable our sdio multport aggregation feature as well. In this way, we will transmit and receive packets one by one, thus reduce the demand for big memory. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/main.h | 2 ++ drivers/net/wireless/mwifiex/sdio.c | 22 ++++++++++++++++------ drivers/net/wireless/mwifiex/sta_cmd.c | 3 ++- 3 files changed, 20 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 966632147079..2c2004e991e0 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -860,6 +860,8 @@ struct mwifiex_adapter { u8 more_task_flag; u16 tx_buf_size; u16 curr_tx_buf_size; + /* sdio single port rx aggregation capability */ + bool host_disable_sdio_rx_aggr; bool sdio_rx_aggr_enable; u16 sdio_rx_block_size; u32 ioport; diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index d35210caa94b..78a8474e1a3d 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -2058,16 +2058,26 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) ret = mwifiex_alloc_sdio_mpa_buffers(adapter, card->mp_tx_agg_buf_size, card->mp_rx_agg_buf_size); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "failed to alloc sdio mp-a buffers\n"); - kfree(card->mp_regs); - return -1; + + /* Allocate 32k MPA Tx/Rx buffers if 64k memory allocation fails */ + if (ret && (card->mp_tx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX || + card->mp_rx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX)) { + /* Disable rx single port aggregation */ + adapter->host_disable_sdio_rx_aggr = true; + + ret = mwifiex_alloc_sdio_mpa_buffers + (adapter, MWIFIEX_MP_AGGR_BUF_SIZE_32K, + MWIFIEX_MP_AGGR_BUF_SIZE_32K); + if (ret) { + /* Disable multi port aggregation */ + card->mpa_tx.enabled = 0; + card->mpa_rx.enabled = 0; + } } adapter->auto_tdls = card->can_auto_tdls; adapter->ext_scan = card->can_ext_scan; - return ret; + return 0; } /* diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index a49a80dd773e..504b321301ec 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -2125,7 +2125,8 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) /** Set SDIO Single Port RX Aggr Info */ if (priv->adapter->iface_type == MWIFIEX_SDIO && - ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info)) { + ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info) && + !priv->adapter->host_disable_sdio_rx_aggr) { sdio_sp_rx_aggr_enable = true; ret = mwifiex_send_cmd(priv, HostCmd_CMD_SDIO_SP_RX_AGGR_CFG, -- cgit v1.2.3 From 02421dd3f6af1b6becb6d9a690a2b70c73c03a7a Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Fri, 18 Sep 2015 06:32:07 -0700 Subject: mwifiex: NULL check for cfg80211_inform_bss() cfg80211_inform_bss would return null in some cases, such as memory allocation failure. This patch adds sanity check for this case, to avoid possible issues when above corner case is hit. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/cfg80211.c | 6 ++++-- drivers/net/wireless/mwifiex/scan.c | 20 ++++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index d8143409da60..30cbafbd17c6 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1994,8 +1994,10 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) CFG80211_BSS_FTYPE_UNKNOWN, bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, 0, ie_buf, ie_len, 0, GFP_KERNEL); - cfg80211_put_bss(priv->wdev.wiphy, bss); - memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); + if (bss) { + cfg80211_put_bss(priv->wdev.wiphy, bss); + ether_addr_copy(priv->cfg_bssid, bss_info.bssid); + } return 0; } diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 5847863a2d6b..3675730fc3b5 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1839,14 +1839,18 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, bssid, timestamp, cap_info_bitmap, beacon_period, ie_buf, ie_len, rssi, GFP_KERNEL); - bss_priv = (struct mwifiex_bss_priv *)bss->priv; - bss_priv->band = band; - bss_priv->fw_tsf = fw_tsf; - if (priv->media_connected && - !memcmp(bssid, priv->curr_bss_params.bss_descriptor - .mac_address, ETH_ALEN)) - mwifiex_update_curr_bss_params(priv, bss); - cfg80211_put_bss(priv->wdev.wiphy, bss); + if (bss) { + bss_priv = (struct mwifiex_bss_priv *)bss->priv; + bss_priv->band = band; + bss_priv->fw_tsf = fw_tsf; + if (priv->media_connected && + !memcmp(bssid, priv->curr_bss_params. + bss_descriptor.mac_address, + ETH_ALEN)) + mwifiex_update_curr_bss_params(priv, + bss); + cfg80211_put_bss(priv->wdev.wiphy, bss); + } if ((chan->flags & IEEE80211_CHAN_RADAR) || (chan->flags & IEEE80211_CHAN_NO_IR)) { -- cgit v1.2.3 From 2c3da961268ff7f4a6c958fee081c58aef2e5c1d Mon Sep 17 00:00:00 2001 From: Aniket Nagarnaik Date: Fri, 18 Sep 2015 06:32:08 -0700 Subject: mwifiex: don't always include ht/vht info in tdls confirm frame Current TDLS implementation always includes ht/vht information in tdls setup confirm frame which causes teardown by legacy peer station after TDLS handshake. We will inclue ht/vht capabilities in tdls setup confirm frame only if peer station supports it to fix this problem. Signed-off-by: Aniket Nagarnaik Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/tdls.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c index b3e163de9899..9275f9c3f869 100644 --- a/drivers/net/wireless/mwifiex/tdls.c +++ b/drivers/net/wireless/mwifiex/tdls.c @@ -204,6 +204,12 @@ mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, const u8 *mac, return -1; } + if (!(le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info))) { + mwifiex_dbg(priv->adapter, WARN, + "TDLS peer doesn't support ht capabilities\n"); + return 0; + } + pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2); *pos++ = WLAN_EID_HT_OPERATION; *pos++ = sizeof(struct ieee80211_ht_operation); @@ -252,6 +258,12 @@ static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv, return -1; } + if (!(le32_to_cpu(sta_ptr->tdls_cap.vhtcap.vht_cap_info))) { + mwifiex_dbg(adapter, WARN, + "TDLS peer doesn't support vht capabilities\n"); + return 0; + } + if (!mwifiex_is_bss_in_11ac_mode(priv)) { if (sta_ptr->tdls_cap.extcap.ext_capab[7] & WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) { -- cgit v1.2.3 From 17e524b1b60f4390d24a51d9524d1648cf5d1447 Mon Sep 17 00:00:00 2001 From: Aniket Nagarnaik Date: Fri, 18 Sep 2015 06:32:09 -0700 Subject: mwifiex: fix NULL pointer dereference during hidden SSID scan This NULL pointer dereference is observed during suspend resume stress test. All pending commands are cancelled when system goes into suspend state. There a corner case in which host may receive response for last scan command after this and try to trigger extra active scan for hidden SSIDs. The issue is fixed by adding a NULL check to skip that extra scan. Fixes: 2375fa2b36feaf34 (mwifiex: fix unable to connect hidden SSID..) Cc: [v4.2+] Signed-off-by: Aniket Nagarnaik Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 3675730fc3b5..c20017ced566 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1893,7 +1893,7 @@ mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv) u8 id = 0; struct mwifiex_user_scan_cfg *user_scan_cfg; - if (adapter->active_scan_triggered) { + if (adapter->active_scan_triggered || !priv->scan_request) { adapter->active_scan_triggered = false; return 0; } -- cgit v1.2.3 From 14d9c11c91a606fed65eaae2455423a23bb4ae59 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 18 Sep 2015 06:32:10 -0700 Subject: mwifiex: avoid memsetting PCIe event buffer Preallocated PCIe buffer is being reused for all PCIe interface events. Physical address of the buffer is shared with firmware so that it can perform DMA on it. As event length is specified in the header, there should not be a problem if the buffer gets overwritten. We will save some cycles by avoiding memset everytime while submitting the buffer to firmware. Fixes: 2728cecdc7d6bf3d21(mwifiex: corrections in PCIe event skb) Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/pcie.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 408b68460716..21192b6f9c64 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -1815,7 +1815,6 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, if (!card->evt_buf_list[rdptr]) { skb_push(skb, INTF_HEADER_LEN); skb_put(skb, MAX_EVENT_SIZE - skb->len); - memset(skb->data, 0, MAX_EVENT_SIZE); if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE, PCI_DMA_FROMDEVICE)) -- cgit v1.2.3 From 70c5ad7e20c1426d14f6e722da0972b2c9163db7 Mon Sep 17 00:00:00 2001 From: Zhaoyang Liu Date: Fri, 18 Sep 2015 06:32:11 -0700 Subject: mwifiex: correct paused tx data packet counter This patch fixes observed issues while updating counter for number of paused data packets in wmm queue when trying to delete packet or delete station entry. Signed-off-by: Zhaoyang Liu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/uap_txrx.c | 10 +++++++--- drivers/net/wireless/mwifiex/wmm.c | 9 +++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index 87667418af5f..74d5d7238633 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -31,7 +31,8 @@ */ static bool mwifiex_uap_del_tx_pkts_in_ralist(struct mwifiex_private *priv, - struct list_head *ra_list_head) + struct list_head *ra_list_head, + int tid) { struct mwifiex_ra_list_tbl *ra_list; struct sk_buff *skb, *tmp; @@ -49,7 +50,10 @@ mwifiex_uap_del_tx_pkts_in_ralist(struct mwifiex_private *priv, __skb_unlink(skb, &ra_list->skb_head); mwifiex_write_data_complete(adapter, skb, 0, -1); - atomic_dec(&priv->wmm.tx_pkts_queued); + if (ra_list->tx_paused) + priv->wmm.pkts_paused[tid]--; + else + atomic_dec(&priv->wmm.tx_pkts_queued); pkt_deleted = true; } if ((atomic_read(&adapter->pending_bridged_pkts) <= @@ -77,7 +81,7 @@ static void mwifiex_uap_cleanup_tx_queues(struct mwifiex_private *priv) if (priv->del_list_idx == MAX_NUM_TID) priv->del_list_idx = 0; ra_list = &priv->wmm.tid_tbl_ptr[priv->del_list_idx].ra_list; - if (mwifiex_uap_del_tx_pkts_in_ralist(priv, ra_list)) { + if (mwifiex_uap_del_tx_pkts_in_ralist(priv, ra_list, i)) { priv->del_list_idx++; break; } diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 173d3663c2e0..8e30fb34c9a1 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -160,7 +160,6 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra) ra_list->tdls_link = false; ra_list->ba_status = BA_SETUP_NONE; ra_list->amsdu_in_ampdu = false; - ra_list->tx_paused = false; if (!mwifiex_queuing_ra_based(priv)) { if (mwifiex_is_tdls_link_setup (mwifiex_get_tdls_link_status(priv, ra))) { @@ -173,6 +172,8 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra) } else { spin_lock_irqsave(&priv->sta_list_spinlock, flags); node = mwifiex_get_sta_entry(priv, ra); + if (node) + ra_list->tx_paused = node->tx_pause; ra_list->is_11n_enabled = mwifiex_is_sta_11n_enabled(priv, node); if (ra_list->is_11n_enabled) @@ -737,7 +738,11 @@ mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, const u8 *ra_addr) if (!ra_list) continue; mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list); - atomic_sub(ra_list->total_pkt_count, &priv->wmm.tx_pkts_queued); + if (ra_list->tx_paused) + priv->wmm.pkts_paused[i] -= ra_list->total_pkt_count; + else + atomic_sub(ra_list->total_pkt_count, + &priv->wmm.tx_pkts_queued); list_del(&ra_list->list); kfree(ra_list); } -- cgit v1.2.3 From 17090beec26ea5bd064c67e2707151722d9d88d6 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 18 Sep 2015 06:32:12 -0700 Subject: mwifiex: Suppress -ENOSR error for data traffic on USB We have preallocated buffer pool for Tx data. During high data traffic, all buffers are submitted to USB and driver needs to wait until one of the buffers get available for next Tx packet. "data: -ENOSR is returned" errors is expected in this case. Let's lower the priority of this message. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 8b1e5b5d47fe..98f097d7361d 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -130,7 +130,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, switch (ret) { case -ENOSR: - mwifiex_dbg(adapter, ERROR, "data: -ENOSR is returned\n"); + mwifiex_dbg(adapter, DATA, "data: -ENOSR is returned\n"); break; case -EBUSY: if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && -- cgit v1.2.3 From d22871db0172eba2bba2e7ff8373f682c9b001cd Mon Sep 17 00:00:00 2001 From: Zhaoyang Liu Date: Fri, 18 Sep 2015 06:32:13 -0700 Subject: mwifiex: fix tx data_sent issue for usb interface This patch fix missing tx data_sent flag update for usb interface. Except USB interface, data_sent flag has been updated in specific file such as sdio.c and pcie.c. So only USB interface type need check when TX data completed. Signed-off-by: Zhaoyang Liu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/11n_aggr.c | 4 ++-- drivers/net/wireless/mwifiex/sta_tx.c | 6 +++++- drivers/net/wireless/mwifiex/txrx.c | 8 ++++---- drivers/net/wireless/mwifiex/wmm.c | 4 ++-- 4 files changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 6cb0d33b0636..ce22cc83b178 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -300,7 +300,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); break; case -1: - if (adapter->iface_type != MWIFIEX_PCIE) + if (adapter->iface_type == MWIFIEX_USB) adapter->data_sent = false; mwifiex_dbg(adapter, ERROR, "%s: host_to_card failed: %#x\n", __func__, ret); @@ -308,7 +308,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, mwifiex_write_data_complete(adapter, skb_aggr, 1, ret); return 0; case -EINPROGRESS: - if (adapter->iface_type != MWIFIEX_PCIE) + if (adapter->iface_type == MWIFIEX_USB) adapter->data_sent = false; break; case 0: diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 355ac5904fac..7a4d5f46d87d 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -174,6 +174,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) local_tx_pd->bss_type = priv->bss_type; if (adapter->iface_type == MWIFIEX_USB) { + adapter->data_sent = true; ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, skb, NULL); } else { @@ -191,7 +192,8 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) adapter->dbg.num_tx_host_to_card_failure++; break; case -1: - adapter->data_sent = false; + if (adapter->iface_type == MWIFIEX_USB) + adapter->data_sent = false; dev_kfree_skb_any(skb); mwifiex_dbg(adapter, ERROR, "%s: host_to_card failed: ret=%d\n", @@ -206,6 +208,8 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) adapter->tx_lock_flag = true; break; case -EINPROGRESS: + if (adapter->iface_type == MWIFIEX_USB) + adapter->data_sent = false; adapter->tx_lock_flag = true; break; default: diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 98f097d7361d..6ef030a61a94 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -142,7 +142,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); break; case -1: - if (adapter->iface_type != MWIFIEX_PCIE) + if (adapter->iface_type == MWIFIEX_USB) adapter->data_sent = false; mwifiex_dbg(adapter, ERROR, "mwifiex_write_data_async failed: 0x%X\n", @@ -151,7 +151,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, mwifiex_write_data_complete(adapter, skb, 0, ret); break; case -EINPROGRESS: - if (adapter->iface_type != MWIFIEX_PCIE) + if (adapter->iface_type == MWIFIEX_USB) adapter->data_sent = false; break; case 0: @@ -222,7 +222,7 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter, mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); break; case -1: - if (adapter->iface_type != MWIFIEX_PCIE) + if (adapter->iface_type == MWIFIEX_USB) adapter->data_sent = false; mwifiex_dbg(adapter, ERROR, "mwifiex_write_data_async failed: 0x%X\n", ret); @@ -230,7 +230,7 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter, mwifiex_write_data_complete(adapter, skb, 0, ret); break; case -EINPROGRESS: - if (adapter->iface_type != MWIFIEX_PCIE) + if (adapter->iface_type == MWIFIEX_USB) adapter->data_sent = false; break; case 0: diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 8e30fb34c9a1..8a3f59e15c7c 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -1356,14 +1356,14 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, ra_list_flags); break; case -1: - if (adapter->iface_type != MWIFIEX_PCIE) + if (adapter->iface_type == MWIFIEX_USB) adapter->data_sent = false; mwifiex_dbg(adapter, ERROR, "host_to_card failed: %#x\n", ret); adapter->dbg.num_tx_host_to_card_failure++; mwifiex_write_data_complete(adapter, skb, 0, ret); break; case -EINPROGRESS: - if (adapter->iface_type != MWIFIEX_PCIE) + if (adapter->iface_type == MWIFIEX_USB) adapter->data_sent = false; break; case 0: -- cgit v1.2.3 From d941444321f6b84bdd36d8d24eef10171c9ab981 Mon Sep 17 00:00:00 2001 From: Zhaoyang Liu Date: Fri, 18 Sep 2015 06:32:14 -0700 Subject: mwifiex: move usb specific data_sent update to usb.c This patch move data_sent flag update to usb.c file. >From now all data_sent update cases only happened in specific file: sdio.c, usb.c, pcie.c. Outside ot these files, it is only allowed to check the value of data_ent. Signed-off-by: Zhaoyang Liu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/11n_aggr.c | 5 ----- drivers/net/wireless/mwifiex/sta_tx.c | 5 ----- drivers/net/wireless/mwifiex/txrx.c | 13 ------------- drivers/net/wireless/mwifiex/usb.c | 7 ++++++- drivers/net/wireless/mwifiex/wmm.c | 5 ----- 5 files changed, 6 insertions(+), 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index ce22cc83b178..46221c2d0f90 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -259,7 +259,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, } if (adapter->iface_type == MWIFIEX_USB) { - adapter->data_sent = true; ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, skb_aggr, NULL); } else { @@ -300,16 +299,12 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); break; case -1: - if (adapter->iface_type == MWIFIEX_USB) - adapter->data_sent = false; mwifiex_dbg(adapter, ERROR, "%s: host_to_card failed: %#x\n", __func__, ret); adapter->dbg.num_tx_host_to_card_failure++; mwifiex_write_data_complete(adapter, skb_aggr, 1, ret); return 0; case -EINPROGRESS: - if (adapter->iface_type == MWIFIEX_USB) - adapter->data_sent = false; break; case 0: mwifiex_write_data_complete(adapter, skb_aggr, 1, ret); diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 7a4d5f46d87d..877ad06336a9 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -174,7 +174,6 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) local_tx_pd->bss_type = priv->bss_type; if (adapter->iface_type == MWIFIEX_USB) { - adapter->data_sent = true; ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, skb, NULL); } else { @@ -192,8 +191,6 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) adapter->dbg.num_tx_host_to_card_failure++; break; case -1: - if (adapter->iface_type == MWIFIEX_USB) - adapter->data_sent = false; dev_kfree_skb_any(skb); mwifiex_dbg(adapter, ERROR, "%s: host_to_card failed: ret=%d\n", @@ -208,8 +205,6 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) adapter->tx_lock_flag = true; break; case -EINPROGRESS: - if (adapter->iface_type == MWIFIEX_USB) - adapter->data_sent = false; adapter->tx_lock_flag = true; break; default: diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 6ef030a61a94..90f4915aea58 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -115,7 +115,6 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) local_tx_pd = (struct txpd *)(head_ptr + hroom); if (adapter->iface_type == MWIFIEX_USB) { - adapter->data_sent = true; ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, skb, NULL); @@ -142,8 +141,6 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); break; case -1: - if (adapter->iface_type == MWIFIEX_USB) - adapter->data_sent = false; mwifiex_dbg(adapter, ERROR, "mwifiex_write_data_async failed: 0x%X\n", ret); @@ -151,8 +148,6 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, mwifiex_write_data_complete(adapter, skb, 0, ret); break; case -EINPROGRESS: - if (adapter->iface_type == MWIFIEX_USB) - adapter->data_sent = false; break; case 0: mwifiex_write_data_complete(adapter, skb, 0, ret); @@ -193,7 +188,6 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter, } if (adapter->iface_type == MWIFIEX_USB) { - adapter->data_sent = true; ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, skb, NULL); @@ -222,16 +216,12 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter, mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); break; case -1: - if (adapter->iface_type == MWIFIEX_USB) - adapter->data_sent = false; mwifiex_dbg(adapter, ERROR, "mwifiex_write_data_async failed: 0x%X\n", ret); adapter->dbg.num_tx_host_to_card_failure++; mwifiex_write_data_complete(adapter, skb, 0, ret); break; case -EINPROGRESS: - if (adapter->iface_type == MWIFIEX_USB) - adapter->data_sent = false; break; case 0: mwifiex_write_data_complete(adapter, skb, 0, ret); @@ -306,9 +296,6 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, if (!priv) goto done; - if (adapter->iface_type == MWIFIEX_USB) - adapter->data_sent = false; - mwifiex_set_trans_start(priv->netdev); if (!status) { priv->stats.tx_packets++; diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 5e789b2e06ea..01438a4e1732 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -277,6 +277,7 @@ static void mwifiex_usb_tx_complete(struct urb *urb) mwifiex_dbg(adapter, DATA, "%s: DATA\n", __func__); atomic_dec(&card->tx_data_urb_pending); + adapter->data_sent = false; mwifiex_write_data_complete(adapter, context->skb, 0, urb->status ? -1 : 0); } @@ -759,6 +760,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, if (ep == card->tx_data_ep && atomic_read(&card->tx_data_urb_pending) >= MWIFIEX_TX_DATA_URB) { + adapter->data_sent = true; return -EBUSY; } @@ -795,6 +797,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, atomic_dec(&card->tx_cmd_urb_pending); } else { atomic_dec(&card->tx_data_urb_pending); + adapter->data_sent = false; if (card->tx_data_ix) card->tx_data_ix--; else @@ -805,8 +808,10 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, } else { if (ep == card->tx_data_ep && atomic_read(&card->tx_data_urb_pending) == - MWIFIEX_TX_DATA_URB) + MWIFIEX_TX_DATA_URB) { + adapter->data_sent = true; return -ENOSR; + } } return -EINPROGRESS; diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 8a3f59e15c7c..4f303f388647 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -1326,7 +1326,6 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); if (adapter->iface_type == MWIFIEX_USB) { - adapter->data_sent = true; ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, skb, NULL); } else { @@ -1356,15 +1355,11 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, ra_list_flags); break; case -1: - if (adapter->iface_type == MWIFIEX_USB) - adapter->data_sent = false; mwifiex_dbg(adapter, ERROR, "host_to_card failed: %#x\n", ret); adapter->dbg.num_tx_host_to_card_failure++; mwifiex_write_data_complete(adapter, skb, 0, ret); break; case -EINPROGRESS: - if (adapter->iface_type == MWIFIEX_USB) - adapter->data_sent = false; break; case 0: mwifiex_write_data_complete(adapter, skb, 0, ret); -- cgit v1.2.3 From 2b0f997db43f01370503d88b5fbec9a350a7955f Mon Sep 17 00:00:00 2001 From: Zhaoyang Liu Date: Fri, 18 Sep 2015 06:32:15 -0700 Subject: mwifiex: add usb multi channel event process support This patch add multi channel event process for USB multi tx data endpoints. Driver receives firmware multi channel event only in case that new connection is setup or interface is disconnect. Different BSS interface need update used usb endpoint. Signed-off-by: Zhaoyang Liu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/fw.h | 18 +++++++++ drivers/net/wireless/mwifiex/init.c | 1 + drivers/net/wireless/mwifiex/main.h | 2 + drivers/net/wireless/mwifiex/sta_event.c | 69 +++++++++++++++++++++++++++----- drivers/net/wireless/mwifiex/usb.c | 2 + 5 files changed, 82 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 3ec2ac82e394..0e6f029458d5 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -104,6 +104,7 @@ enum KEY_TYPE_ID { enum mwifiex_usb_ep { MWIFIEX_USB_EP_CMD_EVENT = 1, MWIFIEX_USB_EP_DATA = 2, + MWIFIEX_USB_EP_DATA_CH2 = 3, }; enum MWIFIEX_802_11_PRIVACY_FILTER { @@ -173,6 +174,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154) #define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156) #define TLV_TYPE_MULTI_CHAN_INFO (PROPRIETARY_TLV_BASE_ID + 183) +#define TLV_TYPE_MC_GROUP_INFO (PROPRIETARY_TLV_BASE_ID + 184) #define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194) #define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197) #define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199) @@ -1984,6 +1986,22 @@ struct mwifiex_ie_types_multi_chan_info { u8 tlv_buffer[0]; } __packed; +struct mwifiex_ie_types_mc_group_info { + struct mwifiex_ie_types_header header; + u8 chan_group_id; + u8 chan_buf_weight; + u8 band_config; + u8 chan_num; + u32 chan_time; + u32 reserved; + union { + u8 sdio_func_num; + u8 usb_ep_num; + } hid_num; + u8 intf_num; + u8 bss_type_numlist[0]; +} __packed; + struct meas_rpt_map { u8 rssi:3; u8 unmeasured:1; diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 5d3ae63baea4..de74a7773fb6 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -78,6 +78,7 @@ int mwifiex_init_priv(struct mwifiex_private *priv) priv->media_connected = false; eth_broadcast_addr(priv->curr_addr); priv->port_open = false; + priv->usb_port = MWIFIEX_USB_EP_DATA; priv->pkt_tx_ctrl = 0; priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; priv->data_rate = 0; /* Initially indicate the rate as auto */ diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 2c2004e991e0..9772a186f480 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -519,6 +519,7 @@ struct mwifiex_private { u8 curr_addr[ETH_ALEN]; u8 media_connected; u8 port_open; + u8 usb_port; u32 num_tx_timeout; /* track consecutive timeout */ u8 tx_timeout_cnt; @@ -989,6 +990,7 @@ struct mwifiex_adapter { u8 coex_rx_win_size; bool drcs_enabled; u8 active_scan_triggered; + bool usb_mc_status; }; void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 3d18c585e543..67920899afeb 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -313,25 +313,74 @@ void mwifiex_process_multi_chan_event(struct mwifiex_private *priv, struct sk_buff *event_skb) { struct mwifiex_ie_types_multi_chan_info *chan_info; - u16 status; + struct mwifiex_ie_types_mc_group_info *grp_info; + struct mwifiex_adapter *adapter = priv->adapter; + struct mwifiex_ie_types_header *tlv; + u16 tlv_buf_left, tlv_type, tlv_len; + int intf_num, bss_type, bss_num, i; + struct mwifiex_private *intf_priv; + tlv_buf_left = event_skb->len - sizeof(u32); chan_info = (void *)event_skb->data + sizeof(u32); - if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO) { - mwifiex_dbg(priv->adapter, ERROR, + if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO || + tlv_buf_left < sizeof(struct mwifiex_ie_types_multi_chan_info)) { + mwifiex_dbg(adapter, ERROR, "unknown TLV in chan_info event\n"); return; } - status = le16_to_cpu(chan_info->status); + adapter->usb_mc_status = le16_to_cpu(chan_info->status); + mwifiex_dbg(adapter, EVENT, "multi chan operation %s\n", + adapter->usb_mc_status ? "started" : "over"); - if (status) { - mwifiex_dbg(priv->adapter, EVENT, - "multi-channel operation started\n"); - } else { - mwifiex_dbg(priv->adapter, EVENT, - "multi-channel operation over\n"); + tlv_buf_left -= sizeof(struct mwifiex_ie_types_multi_chan_info); + tlv = (struct mwifiex_ie_types_header *)chan_info->tlv_buffer; + + while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) { + tlv_type = le16_to_cpu(tlv->type); + tlv_len = le16_to_cpu(tlv->len); + if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) > + tlv_buf_left) { + mwifiex_dbg(adapter, ERROR, "wrong tlv: tlvLen=%d,\t" + "tlvBufLeft=%d\n", tlv_len, tlv_buf_left); + break; + } + if (tlv_type != TLV_TYPE_MC_GROUP_INFO) { + mwifiex_dbg(adapter, ERROR, "wrong tlv type: 0x%x\n", + tlv_type); + break; + } + + grp_info = (struct mwifiex_ie_types_mc_group_info *)tlv; + intf_num = grp_info->intf_num; + for (i = 0; i < intf_num; i++) { + bss_type = grp_info->bss_type_numlist[i] >> 4; + bss_num = grp_info->bss_type_numlist[i] & BSS_NUM_MASK; + intf_priv = mwifiex_get_priv_by_id(adapter, bss_num, + bss_type); + if (!intf_priv) { + mwifiex_dbg(adapter, ERROR, + "Invalid bss_type bss_num\t" + "in multi channel event\n"); + continue; + } + if (adapter->iface_type == MWIFIEX_USB) { + u8 ep; + + ep = grp_info->hid_num.usb_ep_num; + if (ep == MWIFIEX_USB_EP_DATA || + ep == MWIFIEX_USB_EP_DATA_CH2) + intf_priv->usb_port = ep; + } + } + + tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) + + tlv_len; + tlv = (void *)((u8 *)tlv + tlv_len + + sizeof(struct mwifiex_ie_types_header)); } + } void mwifiex_process_tx_pause_event(struct mwifiex_private *priv, diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 01438a4e1732..54c9b4517700 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -858,6 +858,8 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) break; } + adapter->usb_mc_status = false; + return 0; } -- cgit v1.2.3 From 308fe29ef24394e4db66d80c7a23e3e5640aca74 Mon Sep 17 00:00:00 2001 From: Zhaoyang Liu Date: Fri, 18 Sep 2015 06:32:16 -0700 Subject: mwifiex: add usb tx data multi endpoints support This patch add support for USB interface to TX data with different endpoint. And previous TX information are saved in new designed structure. Signed-off-by: Zhaoyang Liu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/main.c | 6 +- drivers/net/wireless/mwifiex/usb.c | 124 ++++++++++++++++++++++++------------ drivers/net/wireless/mwifiex/usb.h | 13 ++-- 3 files changed, 97 insertions(+), 46 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 4fa8ca33937d..4b2110d711bf 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -963,8 +963,10 @@ void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter) cardp = (struct usb_card_rec *)adapter->card; p += sprintf(p, "tx_cmd_urb_pending = %d\n", atomic_read(&cardp->tx_cmd_urb_pending)); - p += sprintf(p, "tx_data_urb_pending = %d\n", - atomic_read(&cardp->tx_data_urb_pending)); + p += sprintf(p, "tx_data_urb_pending_port_0 = %d\n", + atomic_read(&cardp->port[0].tx_data_urb_pending)); + p += sprintf(p, "tx_data_urb_pending_port_1 = %d\n", + atomic_read(&cardp->port[1].tx_data_urb_pending)); p += sprintf(p, "rx_cmd_urb_pending = %d\n", atomic_read(&cardp->rx_cmd_urb_pending)); p += sprintf(p, "rx_data_urb_pending = %d\n", diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 54c9b4517700..df7e7df54a12 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -264,6 +264,8 @@ static void mwifiex_usb_tx_complete(struct urb *urb) struct urb_context *context = (struct urb_context *)(urb->context); struct mwifiex_adapter *adapter = context->adapter; struct usb_card_rec *card = adapter->card; + struct usb_tx_data_port *port; + int i; mwifiex_dbg(adapter, INFO, "%s: status: %d\n", __func__, urb->status); @@ -276,7 +278,13 @@ static void mwifiex_usb_tx_complete(struct urb *urb) } else { mwifiex_dbg(adapter, DATA, "%s: DATA\n", __func__); - atomic_dec(&card->tx_data_urb_pending); + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { + port = &card->port[i]; + if (context->ep == port->tx_data_ep) { + atomic_dec(&port->tx_data_urb_pending); + break; + } + } adapter->data_sent = false; mwifiex_write_data_complete(adapter, context->skb, 0, urb->status ? -1 : 0); @@ -328,7 +336,8 @@ static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size) static void mwifiex_usb_free(struct usb_card_rec *card) { - int i; + struct usb_tx_data_port *port; + int i, j; if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb) usb_kill_urb(card->rx_cmd.urb); @@ -346,9 +355,12 @@ static void mwifiex_usb_free(struct usb_card_rec *card) card->rx_data_list[i].urb = NULL; } - for (i = 0; i < MWIFIEX_TX_DATA_URB; i++) { - usb_free_urb(card->tx_data_list[i].urb); - card->tx_data_list[i].urb = NULL; + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { + port = &card->port[i]; + for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) { + usb_free_urb(port->tx_data_list[j].urb); + port->tx_data_list[j].urb = NULL; + } } usb_free_urb(card->tx_cmd.urb); @@ -438,8 +450,18 @@ static int mwifiex_usb_probe(struct usb_interface *intf, pr_debug("info: bulk OUT: max pkt size: %d, addr: %d\n", le16_to_cpu(epd->wMaxPacketSize), epd->bEndpointAddress); - card->tx_data_ep = usb_endpoint_num(epd); - atomic_set(&card->tx_data_urb_pending, 0); + card->port[0].tx_data_ep = usb_endpoint_num(epd); + atomic_set(&card->port[0].tx_data_urb_pending, 0); + } + if (usb_endpoint_dir_out(epd) && + usb_endpoint_num(epd) == MWIFIEX_USB_EP_DATA_CH2 && + usb_endpoint_xfer_bulk(epd)) { + pr_debug("info: bulk OUT chan2:\t" + "max pkt size: %d, addr: %d\n", + le16_to_cpu(epd->wMaxPacketSize), + epd->bEndpointAddress); + card->port[1].tx_data_ep = usb_endpoint_num(epd); + atomic_set(&card->port[1].tx_data_urb_pending, 0); } if (usb_endpoint_dir_out(epd) && usb_endpoint_num(epd) == MWIFIEX_USB_EP_CMD_EVENT && @@ -481,7 +503,8 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message) { struct usb_card_rec *card = usb_get_intfdata(intf); struct mwifiex_adapter *adapter; - int i; + struct usb_tx_data_port *port; + int i, j; if (!card || !card->adapter) { pr_err("%s: card or card->adapter is NULL\n", __func__); @@ -512,9 +535,13 @@ static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message) if (card->rx_data_list[i].urb) usb_kill_urb(card->rx_data_list[i].urb); - for (i = 0; i < MWIFIEX_TX_DATA_URB; i++) - if (card->tx_data_list[i].urb) - usb_kill_urb(card->tx_data_list[i].urb); + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { + port = &card->port[i]; + for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) { + if (port->tx_data_list[j].urb) + usb_kill_urb(port->tx_data_list[j].urb); + } + } if (card->tx_cmd.urb) usb_kill_urb(card->tx_cmd.urb); @@ -626,7 +653,8 @@ static struct usb_driver mwifiex_usb_driver = { static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter) { struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; - int i; + struct usb_tx_data_port *port; + int i, j; card->tx_cmd.adapter = adapter; card->tx_cmd.ep = card->tx_cmd_ep; @@ -638,17 +666,21 @@ static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter) return -ENOMEM; } - card->tx_data_ix = 0; - - for (i = 0; i < MWIFIEX_TX_DATA_URB; i++) { - card->tx_data_list[i].adapter = adapter; - card->tx_data_list[i].ep = card->tx_data_ep; - - card->tx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL); - if (!card->tx_data_list[i].urb) { - mwifiex_dbg(adapter, ERROR, - "tx_data_list[] urb allocation failed\n"); - return -ENOMEM; + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { + port = &card->port[i]; + if (!port->tx_data_ep) + continue; + port->tx_data_ix = 0; + for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) { + port->tx_data_list[j].adapter = adapter; + port->tx_data_list[j].ep = port->tx_data_ep; + port->tx_data_list[j].urb = + usb_alloc_urb(0, GFP_KERNEL); + if (!port->tx_data_list[j].urb) { + mwifiex_dbg(adapter, ERROR, + "urb allocation failed\n"); + return -ENOMEM; + } } } @@ -743,9 +775,11 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, struct mwifiex_tx_param *tx_param) { struct usb_card_rec *card = adapter->card; - struct urb_context *context; + struct urb_context *context = NULL; + struct usb_tx_data_port *port = NULL; u8 *data = (u8 *)skb->data; struct urb *tx_urb; + int idx; if (adapter->is_suspended) { mwifiex_dbg(adapter, ERROR, @@ -758,20 +792,30 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, return -1; } - if (ep == card->tx_data_ep && - atomic_read(&card->tx_data_urb_pending) >= MWIFIEX_TX_DATA_URB) { - adapter->data_sent = true; - return -EBUSY; - } - mwifiex_dbg(adapter, INFO, "%s: ep=%d\n", __func__, ep); if (ep == card->tx_cmd_ep) { context = &card->tx_cmd; } else { - if (card->tx_data_ix >= MWIFIEX_TX_DATA_URB) - card->tx_data_ix = 0; - context = &card->tx_data_list[card->tx_data_ix++]; + for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) { + if (ep == card->port[idx].tx_data_ep) { + port = &card->port[idx]; + if (atomic_read(&port->tx_data_urb_pending) + >= MWIFIEX_TX_DATA_URB) { + adapter->data_sent = true; + return -EBUSY; + } + if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB) + port->tx_data_ix = 0; + context = + &port->tx_data_list[port->tx_data_ix++]; + break; + } + } + if (!port) { + mwifiex_dbg(adapter, ERROR, "Wrong usb tx data port\n"); + return -1; + } } context->adapter = adapter; @@ -788,7 +832,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, if (ep == card->tx_cmd_ep) atomic_inc(&card->tx_cmd_urb_pending); else - atomic_inc(&card->tx_data_urb_pending); + atomic_inc(&port->tx_data_urb_pending); if (usb_submit_urb(tx_urb, GFP_ATOMIC)) { mwifiex_dbg(adapter, ERROR, @@ -796,18 +840,18 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, if (ep == card->tx_cmd_ep) { atomic_dec(&card->tx_cmd_urb_pending); } else { - atomic_dec(&card->tx_data_urb_pending); + atomic_dec(&port->tx_data_urb_pending); adapter->data_sent = false; - if (card->tx_data_ix) - card->tx_data_ix--; + if (port->tx_data_ix) + port->tx_data_ix--; else - card->tx_data_ix = MWIFIEX_TX_DATA_URB; + port->tx_data_ix = MWIFIEX_TX_DATA_URB; } return -1; } else { - if (ep == card->tx_data_ep && - atomic_read(&card->tx_data_urb_pending) == + if (ep != card->tx_cmd_ep && + atomic_read(&port->tx_data_urb_pending) == MWIFIEX_TX_DATA_URB) { adapter->data_sent = true; return -ENOSR; diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h index f0051f8c8981..0a756f2de717 100644 --- a/drivers/net/wireless/mwifiex/usb.h +++ b/drivers/net/wireless/mwifiex/usb.h @@ -40,6 +40,7 @@ #define USB8XXX_FW_READY 2 #define USB8XXX_FW_MAX_RETRY 3 +#define MWIFIEX_TX_DATA_PORT 2 #define MWIFIEX_TX_DATA_URB 6 #define MWIFIEX_RX_DATA_URB 6 #define MWIFIEX_USB_TIMEOUT 100 @@ -64,6 +65,13 @@ struct urb_context { u8 ep; }; +struct usb_tx_data_port { + u8 tx_data_ep; + atomic_t tx_data_urb_pending; + int tx_data_ix; + struct urb_context tx_data_list[MWIFIEX_TX_DATA_URB]; +}; + struct usb_card_rec { struct mwifiex_adapter *adapter; struct usb_device *udev; @@ -75,14 +83,11 @@ struct usb_card_rec { u8 usb_boot_state; u8 rx_data_ep; atomic_t rx_data_urb_pending; - u8 tx_data_ep; u8 tx_cmd_ep; - atomic_t tx_data_urb_pending; atomic_t tx_cmd_urb_pending; int bulk_out_maxpktsize; struct urb_context tx_cmd; - int tx_data_ix; - struct urb_context tx_data_list[MWIFIEX_TX_DATA_URB]; + struct usb_tx_data_port port[MWIFIEX_TX_DATA_PORT]; }; struct fw_header { -- cgit v1.2.3 From 7e4e5d2cd0817b91eb07c7abe297012bf76616ea Mon Sep 17 00:00:00 2001 From: Zhaoyang Liu Date: Fri, 18 Sep 2015 06:32:17 -0700 Subject: mwifiex: add usb multi endpoints resync support This patch add support for usb multi endpoints resync. Once multi channel event is received from firmware, update usb_mc_setp flag to block TX data until setup is over. And available data endpoint will be attached to BSS interface. Signed-off-by: Zhaoyang Liu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/main.c | 54 +++++++++++++++++++++++++--- drivers/net/wireless/mwifiex/main.h | 3 ++ drivers/net/wireless/mwifiex/sta_cmdresp.c | 11 ++++++ drivers/net/wireless/mwifiex/sta_event.c | 5 +++ drivers/net/wireless/mwifiex/usb.c | 56 ++++++++++++++++++++++++++++++ drivers/net/wireless/mwifiex/usb.h | 2 ++ 6 files changed, 127 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 4b2110d711bf..6e3faa74389c 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -294,9 +294,15 @@ process_start: /* We have tried to wakeup the card already */ if (adapter->pm_wakeup_fw_try) break; - if (adapter->ps_state != PS_STATE_AWAKE || - adapter->tx_lock_flag) + if (adapter->ps_state != PS_STATE_AWAKE) break; + if (adapter->tx_lock_flag) { + if (adapter->iface_type == MWIFIEX_USB) { + if (!adapter->usb_mc_setup) + break; + } else + break; + } if ((!adapter->scan_chan_gap_enabled && adapter->scan_processing) || adapter->data_sent || @@ -345,11 +351,18 @@ process_start: */ if ((adapter->ps_state == PS_STATE_SLEEP) || (adapter->ps_state == PS_STATE_PRE_SLEEP) || - (adapter->ps_state == PS_STATE_SLEEP_CFM) || - adapter->tx_lock_flag){ + (adapter->ps_state == PS_STATE_SLEEP_CFM)) { continue; } + if (adapter->tx_lock_flag) { + if (adapter->iface_type == MWIFIEX_USB) { + if (!adapter->usb_mc_setup) + continue; + } else + continue; + } + if (!adapter->cmd_sent && !adapter->curr_cmd && mwifiex_is_send_cmd_allowed (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) { @@ -359,6 +372,13 @@ process_start: } } + /** If USB Multi channel setup ongoing, + * wait for ready to tx data. + */ + if (adapter->iface_type == MWIFIEX_USB && + adapter->usb_mc_setup) + continue; + if ((adapter->scan_chan_gap_enabled || !adapter->scan_processing) && !adapter->data_sent && @@ -928,6 +948,32 @@ mwifiex_tx_timeout(struct net_device *dev) } } +void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter) +{ + struct usb_card_rec *card = adapter->card; + struct mwifiex_private *priv; + u16 tx_buf_size; + int i, ret; + + card->mc_resync_flag = true; + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { + if (atomic_read(&card->port[i].tx_data_urb_pending)) { + mwifiex_dbg(adapter, WARN, "pending data urb in sys\n"); + return; + } + } + + card->mc_resync_flag = false; + tx_buf_size = 0xffff; + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, + HostCmd_ACT_GEN_SET, 0, &tx_buf_size, false); + if (ret) + mwifiex_dbg(adapter, ERROR, + "send reconfig tx buf size cmd err\n"); +} +EXPORT_SYMBOL_GPL(mwifiex_multi_chan_resync); + void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter) { void *p; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 9772a186f480..88130028cd89 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -816,6 +816,7 @@ struct mwifiex_if_ops { void (*iface_work)(struct work_struct *work); void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter); void (*deaggr_pkt)(struct mwifiex_adapter *, struct sk_buff *); + void (*multi_port_resync)(struct mwifiex_adapter *); }; struct mwifiex_adapter { @@ -991,6 +992,7 @@ struct mwifiex_adapter { bool drcs_enabled; u8 active_scan_triggered; bool usb_mc_status; + bool usb_mc_setup; }; void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); @@ -1564,6 +1566,7 @@ void mwifiex_process_tx_pause_event(struct mwifiex_private *priv, struct sk_buff *event); void mwifiex_process_multi_chan_event(struct mwifiex_private *priv, struct sk_buff *event_skb); +void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter); #ifdef CONFIG_DEBUG_FS void mwifiex_debugfs_init(void); diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 87b69d8ad120..d0961635c7b3 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -1128,6 +1128,17 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, ret = mwifiex_ret_11n_addba_resp(priv, resp); break; case HostCmd_CMD_RECONFIGURE_TX_BUFF: + if (0xffff == (u16)le16_to_cpu(resp->params.tx_buf.buff_size)) { + if (adapter->iface_type == MWIFIEX_USB && + adapter->usb_mc_setup) { + if (adapter->if_ops.multi_port_resync) + adapter->if_ops. + multi_port_resync(adapter); + adapter->usb_mc_setup = false; + adapter->tx_lock_flag = false; + } + break; + } adapter->tx_buf_size = (u16) le16_to_cpu(resp->params. tx_buf.buff_size); adapter->tx_buf_size = (adapter->tx_buf_size diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 67920899afeb..c333b2492451 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -381,6 +381,11 @@ void mwifiex_process_multi_chan_event(struct mwifiex_private *priv, sizeof(struct mwifiex_ie_types_header)); } + if (adapter->iface_type == MWIFIEX_USB) { + adapter->tx_lock_flag = true; + adapter->usb_mc_setup = true; + mwifiex_multi_chan_resync(adapter); + } } void mwifiex_process_tx_pause_event(struct mwifiex_private *priv, diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index df7e7df54a12..78ad857f20ea 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -290,6 +290,9 @@ static void mwifiex_usb_tx_complete(struct urb *urb) urb->status ? -1 : 0); } + if (card->mc_resync_flag) + mwifiex_multi_chan_resync(adapter); + mwifiex_queue_main_work(adapter); return; @@ -671,6 +674,10 @@ static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter) if (!port->tx_data_ep) continue; port->tx_data_ix = 0; + if (port->tx_data_ep == MWIFIEX_USB_EP_DATA) + port->block_status = false; + else + port->block_status = true; for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) { port->tx_data_list[j].adapter = adapter; port->tx_data_list[j].ep = port->tx_data_ep; @@ -769,6 +776,53 @@ static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf, return ret; } +static void mwifiex_usb_port_resync(struct mwifiex_adapter *adapter) +{ + struct usb_card_rec *card = adapter->card; + u8 active_port = MWIFIEX_USB_EP_DATA; + struct mwifiex_private *priv = NULL; + int i; + + if (adapter->usb_mc_status) { + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + if (!priv) + continue; + if ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP && + !priv->bss_started) || + (priv->bss_role == MWIFIEX_BSS_ROLE_STA && + !priv->media_connected)) + priv->usb_port = MWIFIEX_USB_EP_DATA; + } + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) + card->port[i].block_status = false; + } else { + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + if (!priv) + continue; + if ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP && + priv->bss_started) || + (priv->bss_role == MWIFIEX_BSS_ROLE_STA && + priv->media_connected)) { + active_port = priv->usb_port; + break; + } + } + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + if (priv) + priv->usb_port = active_port; + } + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { + if (active_port == card->port[i].tx_data_ep) + card->port[i].block_status = false; + else + card->port[i].block_status = true; + } + } +} + /* This function write a command/data packet to card. */ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, struct sk_buff *skb, @@ -903,6 +957,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) } adapter->usb_mc_status = false; + adapter->usb_mc_setup = false; return 0; } @@ -1133,6 +1188,7 @@ static struct mwifiex_if_ops usb_ops = { .event_complete = mwifiex_usb_cmd_event_complete, .host_to_card = mwifiex_usb_host_to_card, .submit_rem_rx_urbs = mwifiex_usb_submit_rem_rx_urbs, + .multi_port_resync = mwifiex_usb_port_resync, }; /* This function initializes the USB driver module. diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h index 0a756f2de717..bab10ee41923 100644 --- a/drivers/net/wireless/mwifiex/usb.h +++ b/drivers/net/wireless/mwifiex/usb.h @@ -67,6 +67,7 @@ struct urb_context { struct usb_tx_data_port { u8 tx_data_ep; + u8 block_status; atomic_t tx_data_urb_pending; int tx_data_ix; struct urb_context tx_data_list[MWIFIEX_TX_DATA_URB]; @@ -87,6 +88,7 @@ struct usb_card_rec { atomic_t tx_cmd_urb_pending; int bulk_out_maxpktsize; struct urb_context tx_cmd; + u8 mc_resync_flag; struct usb_tx_data_port port[MWIFIEX_TX_DATA_PORT]; }; -- cgit v1.2.3 From 735ab6bfc03878e6b41feb1f14da750a951854ad Mon Sep 17 00:00:00 2001 From: Zhaoyang Liu Date: Fri, 18 Sep 2015 06:32:18 -0700 Subject: mwifiex: complete usb tx data with multi endpoints This patch do the work to TX data with specific USB endpoint. At the same time, update data_sent flag according to multi port status. And is_port_ready API is added for BSS interface to check if current used usb data endpoint is available or not. Signed-off-by: Zhaoyang Liu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/11n_aggr.c | 2 +- drivers/net/wireless/mwifiex/main.h | 1 + drivers/net/wireless/mwifiex/sta_event.c | 4 ++- drivers/net/wireless/mwifiex/sta_tx.c | 6 +++- drivers/net/wireless/mwifiex/txrx.c | 4 +-- drivers/net/wireless/mwifiex/uap_event.c | 4 ++- drivers/net/wireless/mwifiex/usb.c | 47 ++++++++++++++++++++++++++++---- drivers/net/wireless/mwifiex/wmm.c | 38 +++++++++++++++++++++++--- 8 files changed, 90 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 46221c2d0f90..2c5ffa13f7b5 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -259,7 +259,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, } if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, + ret = adapter->if_ops.host_to_card(adapter, priv->usb_port, skb_aggr, NULL); } else { if (skb_src) diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 88130028cd89..3959f1c97f4e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -817,6 +817,7 @@ struct mwifiex_if_ops { void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter); void (*deaggr_pkt)(struct mwifiex_adapter *, struct sk_buff *); void (*multi_port_resync)(struct mwifiex_adapter *); + bool (*is_port_ready)(struct mwifiex_private *); }; struct mwifiex_adapter { diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index c333b2492451..ff3ee9dfbbd5 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -616,7 +616,9 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) adapter->tx_lock_flag = false; if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { if (mwifiex_check_last_packet_indication(priv)) { - if (adapter->data_sent) { + if (adapter->data_sent || + (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv))) { adapter->ps_state = PS_STATE_AWAKE; adapter->pm_wakeup_card_req = false; adapter->pm_wakeup_fw_try = false; diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 877ad06336a9..f6683ea6bd5d 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -153,6 +153,10 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) if (adapter->data_sent) return -1; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + return -1; + skb = dev_alloc_skb(data_len); if (!skb) return -1; @@ -174,7 +178,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) local_tx_pd->bss_type = priv->bss_type; if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, + ret = adapter->if_ops.host_to_card(adapter, priv->usb_port, skb, NULL); } else { skb_push(skb, INTF_HEADER_LEN); diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 90f4915aea58..bf6182b646a5 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -116,7 +116,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, local_tx_pd = (struct txpd *)(head_ptr + hroom); if (adapter->iface_type == MWIFIEX_USB) { ret = adapter->if_ops.host_to_card(adapter, - MWIFIEX_USB_EP_DATA, + priv->usb_port, skb, NULL); } else { ret = adapter->if_ops.host_to_card(adapter, @@ -189,7 +189,7 @@ static int mwifiex_host_to_card(struct mwifiex_adapter *adapter, if (adapter->iface_type == MWIFIEX_USB) { ret = adapter->if_ops.host_to_card(adapter, - MWIFIEX_USB_EP_DATA, + priv->usb_port, skb, NULL); } else { ret = adapter->if_ops.host_to_card(adapter, diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 46c972a650a4..078834cf1251 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -269,7 +269,9 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) adapter->tx_lock_flag = false; if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { if (mwifiex_check_last_packet_indication(priv)) { - if (adapter->data_sent) { + if (adapter->data_sent || + (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv))) { adapter->ps_state = PS_STATE_AWAKE; adapter->pm_wakeup_card_req = false; adapter->pm_wakeup_fw_try = false; diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 78ad857f20ea..9f5356ef0531 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -282,6 +282,7 @@ static void mwifiex_usb_tx_complete(struct urb *urb) port = &card->port[i]; if (context->ep == port->tx_data_ep) { atomic_dec(&port->tx_data_urb_pending); + port->block_status = false; break; } } @@ -823,6 +824,31 @@ static void mwifiex_usb_port_resync(struct mwifiex_adapter *adapter) } } +static bool mwifiex_usb_is_port_ready(struct mwifiex_private *priv) +{ + struct usb_card_rec *card = priv->adapter->card; + int idx; + + for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) { + if (priv->usb_port == card->port[idx].tx_data_ep) + return !card->port[idx].block_status; + } + + return false; +} + +static inline u8 mwifiex_usb_data_sent(struct mwifiex_adapter *adapter) +{ + struct usb_card_rec *card = adapter->card; + int i; + + for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) + if (!card->port[i].block_status) + return false; + + return true; +} + /* This function write a command/data packet to card. */ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, struct sk_buff *skb, @@ -833,7 +859,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, struct usb_tx_data_port *port = NULL; u8 *data = (u8 *)skb->data; struct urb *tx_urb; - int idx; + int idx, ret; if (adapter->is_suspended) { mwifiex_dbg(adapter, ERROR, @@ -856,8 +882,9 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, port = &card->port[idx]; if (atomic_read(&port->tx_data_urb_pending) >= MWIFIEX_TX_DATA_URB) { - adapter->data_sent = true; - return -EBUSY; + port->block_status = true; + ret = -EBUSY; + goto done; } if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB) port->tx_data_ix = 0; @@ -895,7 +922,7 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, atomic_dec(&card->tx_cmd_urb_pending); } else { atomic_dec(&port->tx_data_urb_pending); - adapter->data_sent = false; + port->block_status = false; if (port->tx_data_ix) port->tx_data_ix--; else @@ -907,12 +934,19 @@ static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, if (ep != card->tx_cmd_ep && atomic_read(&port->tx_data_urb_pending) == MWIFIEX_TX_DATA_URB) { - adapter->data_sent = true; - return -ENOSR; + port->block_status = true; + ret = -ENOSR; + goto done; } } return -EINPROGRESS; + +done: + if (ep != card->tx_cmd_ep) + adapter->data_sent = mwifiex_usb_data_sent(adapter); + + return ret; } /* This function register usb device and initialize parameter. */ @@ -1189,6 +1223,7 @@ static struct mwifiex_if_ops usb_ops = { .host_to_card = mwifiex_usb_host_to_card, .submit_rem_rx_urbs = mwifiex_usb_submit_rem_rx_urbs, .multi_port_resync = mwifiex_usb_port_resync, + .is_port_ready = mwifiex_usb_is_port_ready, }; /* This function initializes the USB driver module. diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 4f303f388647..7bbdfe4872e4 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -452,7 +452,21 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter) { - return atomic_read(&adapter->bypass_tx_pending) ? false : true; + struct mwifiex_private *priv; + int i; + + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + if (!priv) + continue; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + continue; + if (!skb_queue_empty(&priv->bypass_txq)) + return false; + } + + return true; } /* @@ -466,9 +480,14 @@ mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) for (i = 0; i < adapter->priv_num; ++i) { priv = adapter->priv[i]; - if (priv && !priv->port_open) + if (!priv) + continue; + if (!priv->port_open) + continue; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) continue; - if (priv && atomic_read(&priv->wmm.tx_pkts_queued)) + if (atomic_read(&priv->wmm.tx_pkts_queued)) return false; } @@ -1091,6 +1110,10 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0)) continue; + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv_tmp)) + continue; + /* iterate over the WMM queues of the BSS */ hqp = &priv_tmp->wmm.highest_queued_prio; for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) { @@ -1326,7 +1349,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, + ret = adapter->if_ops.host_to_card(adapter, priv->usb_port, skb, NULL); } else { tx_param.next_pkt_len = @@ -1467,6 +1490,13 @@ void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter) for (i = 0; i < adapter->priv_num; ++i) { priv = adapter->priv[i]; + if (!priv) + continue; + + if (adapter->if_ops.is_port_ready && + !adapter->if_ops.is_port_ready(priv)) + continue; + if (skb_queue_empty(&priv->bypass_txq)) continue; -- cgit v1.2.3 From 2b5d348ee786dd875b3aa8536a97ff6f6421d018 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:04 +0200 Subject: brcmfmac: Fix exception handling. In some exception situations the ifp->vif was not properly assigned which could result in crash. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 600098dd197c..da24bf0d43f6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -6332,6 +6332,7 @@ wiphy_unreg_out: priv_out: wl_deinit_priv(cfg); brcmf_free_vif(vif); + ifp->vif = NULL; wiphy_out: brcmf_free_wiphy(wiphy); return NULL; -- cgit v1.2.3 From e3c92cb2eea395c9fbec7ceb678626565cbac0fe Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:05 +0200 Subject: brcmfmac: Add support for the BCM4350 PCIE device. This patch adds support fo the BRCM4350 2x2 11ac PCIE device. Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/chip.c | 1 + drivers/net/wireless/brcm80211/brcmfmac/pcie.c | 9 +++++++++ drivers/net/wireless/brcm80211/include/brcm_hw_ids.h | 2 ++ 3 files changed, 12 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index e3b8e235620e..ff0c7c620c4e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c @@ -647,6 +647,7 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) return 0x198000; case BRCM_CC_4335_CHIP_ID: case BRCM_CC_4339_CHIP_ID: + case BRCM_CC_4350_CHIP_ID: case BRCM_CC_4354_CHIP_ID: case BRCM_CC_4356_CHIP_ID: case BRCM_CC_43567_CHIP_ID: diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index 255d49a5b0a3..451022e4cdea 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c @@ -47,6 +47,8 @@ enum brcmf_pcie_state { #define BRCMF_PCIE_43602_FW_NAME "brcm/brcmfmac43602-pcie.bin" #define BRCMF_PCIE_43602_NVRAM_NAME "brcm/brcmfmac43602-pcie.txt" +#define BRCMF_PCIE_4350_FW_NAME "brcm/brcmfmac4350-pcie.bin" +#define BRCMF_PCIE_4350_NVRAM_NAME "brcm/brcmfmac4350-pcie.txt" #define BRCMF_PCIE_4356_FW_NAME "brcm/brcmfmac4356-pcie.bin" #define BRCMF_PCIE_4356_NVRAM_NAME "brcm/brcmfmac4356-pcie.txt" #define BRCMF_PCIE_43570_FW_NAME "brcm/brcmfmac43570-pcie.bin" @@ -194,6 +196,8 @@ enum brcmf_pcie_state { MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME); MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4350_FW_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4350_NVRAM_NAME); MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME); MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME); MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME); @@ -1418,6 +1422,10 @@ static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo) fw_name = BRCMF_PCIE_43602_FW_NAME; nvram_name = BRCMF_PCIE_43602_NVRAM_NAME; break; + case BRCM_CC_4350_CHIP_ID: + fw_name = BRCMF_PCIE_4350_FW_NAME; + nvram_name = BRCMF_PCIE_4350_NVRAM_NAME; + break; case BRCM_CC_4356_CHIP_ID: fw_name = BRCMF_PCIE_4356_FW_NAME; nvram_name = BRCMF_PCIE_4356_NVRAM_NAME; @@ -1956,6 +1964,7 @@ cleanup: PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 } static struct pci_device_id brcmf_pcie_devid_table[] = { + BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID), diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index 7a6daa37dc6b..8278376aee40 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h @@ -39,6 +39,7 @@ #define BRCM_CC_4339_CHIP_ID 0x4339 #define BRCM_CC_43430_CHIP_ID 43430 #define BRCM_CC_4345_CHIP_ID 0x4345 +#define BRCM_CC_4350_CHIP_ID 0x4350 #define BRCM_CC_4354_CHIP_ID 0x4354 #define BRCM_CC_4356_CHIP_ID 0x4356 #define BRCM_CC_43566_CHIP_ID 43566 @@ -56,6 +57,7 @@ #define BRCM_USB_BCMFW_DEVICE_ID 0x0bdc /* PCIE Device IDs */ +#define BRCM_PCIE_4350_DEVICE_ID 0x43a3 #define BRCM_PCIE_4354_DEVICE_ID 0x43df #define BRCM_PCIE_4356_DEVICE_ID 0x43ec #define BRCM_PCIE_43567_DEVICE_ID 0x43d3 -- cgit v1.2.3 From 60dc35ef9ffdf8810b98cc09abb02378023818c2 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:06 +0200 Subject: brcmfmac: Fix set and get tx-power functions. Implementation of tx-power (get and set) related functions are still assuming mW interface. This is wrong as functions use dbm (or mbm) nowadays. As a result a tx power configuration could result in wrong power configuration. Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 137 ++++----------------- 1 file changed, 26 insertions(+), 111 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index da24bf0d43f6..0a97e61025fb 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -236,89 +236,6 @@ static int brcmf_roamoff; module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR); MODULE_PARM_DESC(roamoff, "do not use internal roaming engine"); -/* Quarter dBm units to mW - * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 - * Table is offset so the last entry is largest mW value that fits in - * a u16. - */ - -#define QDBM_OFFSET 153 /* Offset for first entry */ -#define QDBM_TABLE_LEN 40 /* Table size */ - -/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. - * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 - */ -#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ - -/* Largest mW value that will round down to the last table entry, - * QDBM_OFFSET + QDBM_TABLE_LEN-1. - * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + - * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. - */ -#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ - -static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { -/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ -/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, -/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, -/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, -/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, -/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 -}; - -static u16 brcmf_qdbm_to_mw(u8 qdbm) -{ - uint factor = 1; - int idx = qdbm - QDBM_OFFSET; - - if (idx >= QDBM_TABLE_LEN) - /* clamp to max u16 mW value */ - return 0xFFFF; - - /* scale the qdBm index up to the range of the table 0-40 - * where an offset of 40 qdBm equals a factor of 10 mW. - */ - while (idx < 0) { - idx += 40; - factor *= 10; - } - - /* return the mW value scaled down to the correct factor of 10, - * adding in factor/2 to get proper rounding. - */ - return (nqdBm_to_mW_map[idx] + factor / 2) / factor; -} - -static u8 brcmf_mw_to_qdbm(u16 mw) -{ - u8 qdbm; - int offset; - uint mw_uint = mw; - uint boundary; - - /* handle boundary case */ - if (mw_uint <= 1) - return 0; - - offset = QDBM_OFFSET; - - /* move mw into the range of the table */ - while (mw_uint < QDBM_TABLE_LOW_BOUND) { - mw_uint *= 10; - offset -= 40; - } - - for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) { - boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] - - nqdBm_to_mW_map[qdbm]) / 2; - if (mw_uint < boundary) - break; - } - - qdbm += (u8) offset; - - return qdbm; -} static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, struct cfg80211_chan_def *ch) @@ -2017,16 +1934,14 @@ static s32 brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, enum nl80211_tx_power_setting type, s32 mbm) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct net_device *ndev = cfg_to_ndev(cfg); struct brcmf_if *ifp = netdev_priv(ndev); - u16 txpwrmw; - s32 err = 0; - s32 disable = 0; - s32 dbm = MBM_TO_DBM(mbm); + s32 err; + s32 disable; + u32 qdbm = 127; - brcmf_dbg(TRACE, "Enter\n"); + brcmf_dbg(TRACE, "Enter %d %d\n", type, mbm); if (!check_vif_up(ifp->vif)) return -EIO; @@ -2035,12 +1950,20 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, break; case NL80211_TX_POWER_LIMITED: case NL80211_TX_POWER_FIXED: - if (dbm < 0) { + if (mbm < 0) { brcmf_err("TX_POWER_FIXED - dbm is negative\n"); err = -EINVAL; goto done; } + qdbm = MBM_TO_DBM(4 * mbm); + if (qdbm > 127) + qdbm = 127; + qdbm |= WL_TXPWR_OVERRIDE; break; + default: + brcmf_err("Unsupported type %d\n", type); + err = -EINVAL; + goto done; } /* Make sure radio is off or on as far as software is concerned */ disable = WL_RADIO_SW_DISABLE << 16; @@ -2048,52 +1971,44 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, if (err) brcmf_err("WLC_SET_RADIO error (%d)\n", err); - if (dbm > 0xffff) - txpwrmw = 0xffff; - else - txpwrmw = (u16) dbm; - err = brcmf_fil_iovar_int_set(ifp, "qtxpower", - (s32)brcmf_mw_to_qdbm(txpwrmw)); + err = brcmf_fil_iovar_int_set(ifp, "qtxpower", qdbm); if (err) brcmf_err("qtxpower error (%d)\n", err); - cfg->conf->tx_power = dbm; done: - brcmf_dbg(TRACE, "Exit\n"); + brcmf_dbg(TRACE, "Exit %d (qdbm)\n", qdbm & ~WL_TXPWR_OVERRIDE); return err; } -static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, - struct wireless_dev *wdev, - s32 *dbm) +static s32 +brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, + s32 *dbm) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); - s32 txpwrdbm; - u8 result; - s32 err = 0; + struct net_device *ndev = cfg_to_ndev(cfg); + struct brcmf_if *ifp = netdev_priv(ndev); + s32 qdbm = 0; + s32 err; brcmf_dbg(TRACE, "Enter\n"); if (!check_vif_up(ifp->vif)) return -EIO; - err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &txpwrdbm); + err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &qdbm); if (err) { brcmf_err("error (%d)\n", err); goto done; } - - result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE); - *dbm = (s32) brcmf_qdbm_to_mw(result); + *dbm = (qdbm & ~WL_TXPWR_OVERRIDE) / 4; done: - brcmf_dbg(TRACE, "Exit\n"); + brcmf_dbg(TRACE, "Exit (0x%x %d)\n", qdbm, *dbm); return err; } static s32 brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, - u8 key_idx, bool unicast, bool multicast) + u8 key_idx, bool unicast, bool multicast) { struct brcmf_if *ifp = netdev_priv(ndev); u32 index; -- cgit v1.2.3 From 6ea696eb4e2646e8f2440e2090f3d165a21ff02f Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:07 +0200 Subject: brcmfmac: Only assign primary netdev to if2bss array. The if2bss allows for translation of ifidx to bssidx which has a 1:n relation. Therefor only the first (primary) netdev should be assigned in this array. This fixes the p2pon=1 module param usage. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/core.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 17658b59c36c..571c3054da58 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -53,6 +53,8 @@ MODULE_LICENSE("Dual BSD/GPL"); #define BRCMF_RXREORDER_EXPIDX_VALID 0x08 #define BRCMF_RXREORDER_NEW_HOLE 0x10 +#define BRCMF_BSSIDX_INVALID -1 + /* Error bits */ int brcmf_msg_level; module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR); @@ -837,7 +839,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, ifp = netdev_priv(ndev); ifp->ndev = ndev; /* store mapping ifidx to bssidx */ - drvr->if2bss[ifidx] = bssidx; + if (drvr->if2bss[ifidx] == BRCMF_BSSIDX_INVALID) + drvr->if2bss[ifidx] = bssidx; } ifp->drvr = drvr; @@ -862,15 +865,15 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) struct brcmf_if *ifp; ifp = drvr->iflist[bssidx]; - drvr->if2bss[ifp->ifidx] = -1; drvr->iflist[bssidx] = NULL; if (!ifp) { brcmf_err("Null interface, idx=%d\n", bssidx); return; } brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx); + if (drvr->if2bss[ifp->ifidx] == bssidx) + drvr->if2bss[ifp->ifidx] = BRCMF_BSSIDX_INVALID; if (ifp->ndev) { - drvr->if2bss[ifp->ifidx] = -1; if (bssidx == 0) { if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { rtnl_lock(); @@ -926,6 +929,7 @@ int brcmf_attach(struct device *dev) { struct brcmf_pub *drvr = NULL; int ret = 0; + int i; brcmf_dbg(TRACE, "Enter\n"); @@ -934,7 +938,9 @@ int brcmf_attach(struct device *dev) if (!drvr) return -ENOMEM; - memset(drvr->if2bss, 0xFF, sizeof(drvr->if2bss)); + for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++) + drvr->if2bss[i] = BRCMF_BSSIDX_INVALID; + mutex_init(&drvr->proto_block); /* Link to bus module */ -- cgit v1.2.3 From ae7c03f68ee24e51f3ded9265715405df72812ba Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:08 +0200 Subject: brcmfmac: Inform p2p module about p2pon through API When the p2pon module param is used then p2p attach will initialize p2p device iface in the firmware, but it is doing that by checking data. It is cleaner to pass the p2pon information to p2p by API. This information is also needed for other patch. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 5 +++-- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h | 3 ++- drivers/net/wireless/brcm80211/brcmfmac/core.c | 3 ++- drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 12 ++++++++---- drivers/net/wireless/brcm80211/brcmfmac/p2p.h | 4 +++- 5 files changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 0a97e61025fb..3e1c8fcf57cb 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -6127,7 +6127,8 @@ static void brcmf_free_wiphy(struct wiphy *wiphy) } struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, - struct device *busdev) + struct device *busdev, + bool p2pdev_forced) { struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev; struct brcmf_cfg80211_info *cfg; @@ -6219,7 +6220,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; } - err = brcmf_p2p_attach(cfg); + err = brcmf_p2p_attach(cfg, p2pdev_forced); if (err) { brcmf_err("P2P initilisation failed (%d)\n", err); goto wiphy_unreg_out; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h index d9e6d01b2b69..3f5e5505d329 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h @@ -469,7 +469,8 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg) } struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, - struct device *busdev); + struct device *busdev, + bool p2pdev_forced); void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); s32 brcmf_cfg80211_up(struct net_device *ndev); s32 brcmf_cfg80211_down(struct net_device *ndev); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 571c3054da58..3b169f526a80 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -1044,7 +1044,8 @@ int brcmf_bus_start(struct device *dev) brcmf_fws_add_interface(ifp); - drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev); + drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev, + brcmf_p2p_enable); if (drvr->config == NULL) { ret = -ENOMEM; goto fail; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 6a70c068fbc5..1e09cd2429f3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -2336,7 +2336,7 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev) * * @cfg: driver private data for cfg80211 interface. */ -s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) +s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced) { struct brcmf_if *pri_ifp; struct brcmf_if *p2p_ifp; @@ -2351,11 +2351,15 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) drvr = cfg->pub; - pri_ifp = drvr->iflist[0]; - p2p_ifp = drvr->iflist[1]; - + pri_ifp = brcmf_get_ifp(drvr, 0); p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif; + if (p2pdev_forced) { + p2p_ifp = drvr->iflist[1]; + } else { + p2p_ifp = NULL; + p2p->p2pdev_dynamically = true; + } if (p2p_ifp) { p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE, false); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h index 872f382d9e49..d82287decf77 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h @@ -124,6 +124,7 @@ struct afx_hdl { * @wait_next_af: thread synchronizing struct. * @gon_req_action: about to send go negotiation requets frame. * @block_gon_req_tx: drop tx go negotiation requets frame. + * @p2pdev_dynamically: is p2p device if created by module param or supplicant. */ struct brcmf_p2p_info { struct brcmf_cfg80211_info *cfg; @@ -144,9 +145,10 @@ struct brcmf_p2p_info { struct completion wait_next_af; bool gon_req_action; bool block_gon_req_tx; + bool p2pdev_dynamically; }; -s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg); +s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced); void brcmf_p2p_detach(struct brcmf_p2p_info *p2p); struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, unsigned char name_assign_type, -- cgit v1.2.3 From 9f64df940cfe734156ec434807611e014278b359 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:09 +0200 Subject: brcmfmac: Fix bug in flowring management. The hash index stored in the flowrings is of type u16 but gets stored in u8. This can result in incorrect indexing and possibly result in crashes. This patch fixes the type. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/flowring.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.h b/drivers/net/wireless/brcm80211/brcmfmac/flowring.h index 5551861a44bc..95fd1c9675d1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.h @@ -34,7 +34,7 @@ enum ring_status { }; struct brcmf_flowring_ring { - u8 hash_id; + u16 hash_id; bool blocked; enum ring_status status; struct sk_buff_head skblist; -- cgit v1.2.3 From 43e55a2a1cf05afcc4b9d4fc214ccb4a53447cb1 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:10 +0200 Subject: brcmfmac: Make p2pon module param always available. p2pon module param is currently under define BRCMDBG. Though it is a needed option for older versions of the wpa_supplicant which do not support the P2P_DEVICE interface. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 3b169f526a80..031283a39d60 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -62,10 +62,8 @@ MODULE_PARM_DESC(debug, "level of debug output"); /* P2P0 enable */ static int brcmf_p2p_enable; -#ifdef CONFIG_BRCMDBG module_param_named(p2pon, brcmf_p2p_enable, int, 0); -MODULE_PARM_DESC(p2pon, "enable p2p management functionality"); -#endif +MODULE_PARM_DESC(p2pon, "enable legacy p2p management functionality"); char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) { -- cgit v1.2.3 From 178e9ef9b6c619b1b3de354f21692a0ad1071116 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:11 +0200 Subject: brcmfmac: Workaround in change vif for wpa_supplicant support. Different wpa_supplicants have different behavior and expectations regarding the change_virtual_intf behavior. This patch implements a workaround for the different versions and possible brcmfmac configuration. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 43 ++++++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 3e1c8fcf57cb..891f4ed8c5e3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -777,6 +777,37 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, s32 err = 0; brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type); + + /* WAR: There are a number of p2p interface related problems which + * need to be handled initially (before doing the validate). + * wpa_supplicant tends to do iface changes on p2p device/client/go + * which are not always possible/allowed. However we need to return + * OK otherwise the wpa_supplicant wont start. The situation differs + * on configuration and setup (p2pon=1 module param). The first check + * is to see if the request is a change to station for p2p iface. + */ + if ((type == NL80211_IFTYPE_STATION) && + ((vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) || + (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) || + (vif->wdev.iftype == NL80211_IFTYPE_P2P_DEVICE))) { + brcmf_dbg(TRACE, "Ignoring cmd for p2p if\n"); + /* Now depending on whether module param p2pon=1 was used the + * response needs to be either 0 or EOPNOTSUPP. The reason is + * that if p2pon=1 is used, but a newer supplicant is used then + * we should return an error, as this combination wont work. + * In other situations 0 is returned and supplicant will start + * normally. It will give a trace in cfg80211, but it is the + * only way to get it working. Unfortunately this will result + * in situation where we wont support new supplicant in + * combination with module param p2pon=1, but that is the way + * it is. If the user tries this then unloading of driver might + * fail/lock. + */ + if (cfg->p2p.p2pdev_dynamically) + return -EOPNOTSUPP; + else + return 0; + } err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type); if (err) { brcmf_err("iface validation failed: err=%d\n", err); @@ -792,18 +823,6 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, infra = 0; break; case NL80211_IFTYPE_STATION: - /* Ignore change for p2p IF. Unclear why supplicant does this */ - if ((vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) || - (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { - brcmf_dbg(TRACE, "Ignoring cmd for p2p if\n"); - /* WAR: It is unexpected to get a change of VIF for P2P - * IF, but it happens. The request can not be handled - * but returning EPERM causes a crash. Returning 0 - * without setting ieee80211_ptr->iftype causes trace - * (WARN_ON) but it works with wpa_supplicant - */ - return 0; - } infra = 1; break; case NL80211_IFTYPE_AP: -- cgit v1.2.3 From 9831bcb987df4aff6a1d85975f1dda4c654f298d Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:12 +0200 Subject: brcmfmac: Deleting of p2p device is leaking memory. When a p2p device gets deleted, the memory for the vif is not being released. This is solved by reorganizing the cleanup path and properly freeing the memory. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/core.c | 13 ++++++++- drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 38 +++++++++++++------------- drivers/net/wireless/brcm80211/brcmfmac/p2p.h | 1 + 3 files changed, 32 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 031283a39d60..8c2a280f0c98 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -887,6 +887,16 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) cancel_work_sync(&ifp->multicast_work); } brcmf_net_detach(ifp->ndev); + } else { + /* Only p2p device interfaces which get dynamically created + * end up here. In this case the p2p module should be informed + * about the removal of the interface within the firmware. If + * not then p2p commands towards the firmware will cause some + * serious troublesome side effects. The p2p module will clean + * up the ifp if needed. + */ + brcmf_p2p_ifp_removed(ifp); + kfree(ifp); } } @@ -894,7 +904,8 @@ void brcmf_remove_interface(struct brcmf_if *ifp) { if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp)) return; - + brcmf_dbg(TRACE, "Enter, bssidx=%d, ifidx=%d\n", ifp->bssidx, + ifp->ifidx); brcmf_fws_del_interface(ifp); brcmf_del_if(ifp->drvr, ifp->bssidx); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 1e09cd2429f3..83027dcc4aae 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -2130,20 +2130,6 @@ fail: return ERR_PTR(err); } -/** - * brcmf_p2p_delete_p2pdev() - delete P2P_DEVICE virtual interface. - * - * @vif: virtual interface object to delete. - */ -static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p, - struct brcmf_cfg80211_vif *vif) -{ - cfg80211_unregister_wdev(&vif->wdev); - p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; - brcmf_remove_interface(vif->ifp); - brcmf_free_vif(vif); -} - /** * brcmf_p2p_add_vif() - create a new P2P virtual interface. * @@ -2267,9 +2253,11 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) break; case NL80211_IFTYPE_P2P_DEVICE: + if (!p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif) + return 0; brcmf_p2p_cancel_remain_on_channel(vif->ifp); brcmf_p2p_deinit_discovery(p2p); - brcmf_p2p_delete_p2pdev(p2p, vif); + brcmf_remove_interface(vif->ifp); return 0; default: return -ENOTSUPP; @@ -2301,6 +2289,21 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) return err; } +void brcmf_p2p_ifp_removed(struct brcmf_if *ifp) +{ + struct brcmf_cfg80211_info *cfg; + struct brcmf_cfg80211_vif *vif; + + brcmf_dbg(INFO, "P2P: device interface removed\n"); + vif = ifp->vif; + cfg = wdev_to_cfg(&vif->wdev); + cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; + rtnl_lock(); + cfg80211_unregister_wdev(&vif->wdev); + rtnl_unlock(); + brcmf_free_vif(vif); +} + int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); @@ -2425,10 +2428,7 @@ void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) if (vif != NULL) { brcmf_p2p_cancel_remain_on_channel(vif->ifp); brcmf_p2p_deinit_discovery(p2p); - /* remove discovery interface */ - rtnl_lock(); - brcmf_p2p_delete_p2pdev(p2p, vif); - rtnl_unlock(); + brcmf_remove_interface(vif->ifp); } /* just set it all to zero */ memset(p2p, 0, sizeof(*p2p)); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h index d82287decf77..5d49059021a9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.h @@ -157,6 +157,7 @@ struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev); int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, enum brcmf_fil_p2p_if_types if_type); +void brcmf_p2p_ifp_removed(struct brcmf_if *ifp); int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev); void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev); int brcmf_p2p_scan_prep(struct wiphy *wiphy, -- cgit v1.2.3 From d1bb34c128f59c30b75b96ef60f5f00cdbe9ca0e Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:13 +0200 Subject: brcmfmac: Only handle p2p_stop_device if vif is valid In some situations it is possible that vif has been removed while cfg80211 invokes the p2p_stop_device handler. This will result in crash. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 83027dcc4aae..76e477109e6d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -2327,11 +2327,17 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev) struct brcmf_cfg80211_vif *vif; vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); - mutex_lock(&cfg->usr_sync); - (void)brcmf_p2p_deinit_discovery(p2p); - brcmf_abort_scanning(cfg); - clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); - mutex_unlock(&cfg->usr_sync); + /* This call can be result of the unregister_wdev call. In that case + * we dont want to do anything anymore. Just return. The config vif + * will have been cleared at this point. + */ + if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif == vif) { + mutex_lock(&cfg->usr_sync); + (void)brcmf_p2p_deinit_discovery(p2p); + brcmf_abort_scanning(cfg); + clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); + mutex_unlock(&cfg->usr_sync); + } } /** -- cgit v1.2.3 From 35a3cbcc49b5422fbfe7d655952888a3d29b45ed Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:14 +0200 Subject: brcmfmac: Fix p2p bug for older firmwares. Some devices with older firmwares are reporting new p2p device interface with the wrong type. Accept this type to get p2p working for these devices. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/fweh.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index 3330f30be8ef..dc34d3a69b27 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -186,11 +186,13 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, ifevent->action, ifevent->ifidx, ifevent->bssidx, ifevent->flags, ifevent->role); - /* The P2P Device interface event must not be ignored - * contrary to what firmware tells us. + /* The P2P Device interface event must not be ignored contrary to what + * firmware tells us. Older firmware uses p2p noif, with sta role. + * This should be accepted. */ - is_p2pdev = (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) && - ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT; + is_p2pdev = ((ifevent->flags & BRCMF_E_IF_FLAG_NOIF) && + (ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT || + ifevent->role == BRCMF_E_IF_ROLE_STA)); if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { brcmf_dbg(EVENT, "event can be ignored\n"); return; -- cgit v1.2.3 From 8268c2011d255b547a9093977e728af5cf16d69e Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:15 +0200 Subject: brcmfmac: Add module parameter to disable features. For debugging purpose it is very handy to be able to disable features. It has happened a few times that new features turned out not always being properly detected for all devices/firmwares. Making it possible to disable the feature with a module parameter will make testing/debugging easier. Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/feature.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c index 7c2135faaf82..44bb30636690 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c @@ -15,6 +15,7 @@ */ #include +#include #include #include "core.h" @@ -23,6 +24,12 @@ #include "fwil.h" #include "feature.h" + +/* Module param feature_disable (global for all devices) */ +static int brcmf_feature_disable; +module_param_named(feature_disable, brcmf_feature_disable, int, 0); +MODULE_PARM_DESC(feature_disable, "Disable features"); + /* * expand feature list to array of feature strings. */ @@ -131,6 +138,12 @@ void brcmf_feat_attach(struct brcmf_pub *drvr) brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0); brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p"); + if (brcmf_feature_disable) { + brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n", + ifp->drvr->feat_flags, brcmf_feature_disable); + ifp->drvr->feat_flags &= ~brcmf_feature_disable; + } + /* set chip related quirks */ switch (drvr->bus_if->chip) { case BRCM_CC_43236_CHIP_ID: -- cgit v1.2.3 From a2044d91d9d25a0e9e2abb43ca90cceee032f6ee Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:16 +0200 Subject: brcmfmac: Fix race condition bug when deleting p2p interface. When p2p device interface gets deleted by deinitialising discovery it will result in an event which removes the interface, but that is also done by delete p2p interface code. This results in race condition which sometimes results in lockup/crash. With this patch the delete device interface will wait for the event (with timeout) removing the possible race condition. Also on the stop device call from cfg80211 the deinitialisation of the discovery device should be avoided as it can result in a similar situation. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 76e477109e6d..fda726c8e7ab 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -2241,6 +2241,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) brcmf_dbg(TRACE, "delete P2P vif\n"); vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); + brcmf_cfg80211_arm_vif_event(cfg, vif); switch (vif->wdev.iftype) { case NL80211_IFTYPE_P2P_CLIENT: if (test_bit(BRCMF_VIF_STATUS_DISCONNECTING, &vif->sme_state)) @@ -2257,8 +2258,6 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) return 0; brcmf_p2p_cancel_remain_on_channel(vif->ifp); brcmf_p2p_deinit_discovery(p2p); - brcmf_remove_interface(vif->ifp); - return 0; default: return -ENOTSUPP; } @@ -2270,10 +2269,11 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) wait_for_completion_timeout(&cfg->vif_disabled, msecs_to_jiffies(500)); - brcmf_vif_clear_mgmt_ies(vif); - - brcmf_cfg80211_arm_vif_event(cfg, vif); - err = brcmf_p2p_release_p2p_if(vif); + err = 0; + if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE) { + brcmf_vif_clear_mgmt_ies(vif); + err = brcmf_p2p_release_p2p_if(vif); + } if (!err) { /* wait for firmware event */ err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL, @@ -2283,8 +2283,12 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) else err = 0; } + if (err) + brcmf_remove_interface(vif->ifp); + brcmf_cfg80211_arm_vif_event(cfg, NULL); - p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL; + if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE) + p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL; return err; } @@ -2333,7 +2337,9 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev) */ if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif == vif) { mutex_lock(&cfg->usr_sync); - (void)brcmf_p2p_deinit_discovery(p2p); + /* Set the discovery state to SCAN */ + (void)brcmf_p2p_set_discover_state(vif->ifp, + WL_P2P_DISC_ST_SCAN, 0, 0); brcmf_abort_scanning(cfg); clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); mutex_unlock(&cfg->usr_sync); -- cgit v1.2.3 From 55acca90da52b85299c033354e51ddaa7b73e019 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:17 +0200 Subject: brcmfmac: Add support for the BCM4365 and BCM4366 PCIE devices. This patch adds support for the BCM4365 and BCM4366 11ac Wave2 PCIE devices. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/chip.c | 110 +++++++++++++++++++-- drivers/net/wireless/brcm80211/brcmfmac/pcie.c | 22 +++++ .../net/wireless/brcm80211/include/brcm_hw_ids.h | 9 ++ 3 files changed, 131 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index ff0c7c620c4e..ffc3ace24903 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c @@ -208,6 +208,7 @@ struct sbsocramregs { }; #define SOCRAMREGOFFS(_f) offsetof(struct sbsocramregs, _f) +#define SYSMEMREGOFFS(_f) offsetof(struct sbsocramregs, _f) #define ARMCR4_CAP (0x04) #define ARMCR4_BANKIDX (0x40) @@ -516,6 +517,9 @@ static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) case BCMA_CORE_ARM_CR4: cpu_found = true; break; + case BCMA_CORE_ARM_CA7: + cpu_found = true; + break; default: break; } @@ -614,6 +618,29 @@ static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize, } } +/** Return the SYS MEM size */ +static u32 brcmf_chip_sysmem_ramsize(struct brcmf_core_priv *sysmem) +{ + u32 memsize = 0; + u32 coreinfo; + u32 idx; + u32 nb; + u32 banksize; + + if (!brcmf_chip_iscoreup(&sysmem->pub)) + brcmf_chip_resetcore(&sysmem->pub, 0, 0, 0); + + coreinfo = brcmf_chip_core_read32(sysmem, SYSMEMREGOFFS(coreinfo)); + nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; + + for (idx = 0; idx < nb; idx++) { + brcmf_chip_socram_banksize(sysmem, idx, &banksize); + memsize += banksize; + } + + return memsize; +} + /** Return the TCM-RAM size of the ARMCR4 core. */ static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4) { @@ -656,6 +683,9 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) case BRCM_CC_4358_CHIP_ID: case BRCM_CC_43602_CHIP_ID: return 0x180000; + case BRCM_CC_4365_CHIP_ID: + case BRCM_CC_4366_CHIP_ID: + return 0x200000; default: brcmf_err("unknown chip: %s\n", ci->pub.name); break; @@ -678,10 +708,28 @@ static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) return -EINVAL; } } else { - mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_INTERNAL_MEM); - mem_core = container_of(mem, struct brcmf_core_priv, pub); - brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize, - &ci->pub.srsize); + mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_SYS_MEM); + if (mem) { + mem_core = container_of(mem, struct brcmf_core_priv, + pub); + ci->pub.ramsize = brcmf_chip_sysmem_ramsize(mem_core); + ci->pub.rambase = brcmf_chip_tcm_rambase(ci); + if (!ci->pub.rambase) { + brcmf_err("RAM base not provided with ARM CA7 core\n"); + return -EINVAL; + } + } else { + mem = brcmf_chip_get_core(&ci->pub, + BCMA_CORE_INTERNAL_MEM); + if (!mem) { + brcmf_err("No memory cores found\n"); + return -ENOMEM; + } + mem_core = container_of(mem, struct brcmf_core_priv, + pub); + brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize, + &ci->pub.srsize); + } } brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n", ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize, @@ -924,7 +972,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id) { struct brcmf_core *core; - struct brcmf_core_priv *cr4; + struct brcmf_core_priv *cpu; u32 val; @@ -937,10 +985,11 @@ static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id) brcmf_chip_coredisable(core, 0, 0); break; case BCMA_CORE_ARM_CR4: - cr4 = container_of(core, struct brcmf_core_priv, pub); + case BCMA_CORE_ARM_CA7: + cpu = container_of(core, struct brcmf_core_priv, pub); /* clear all IOCTL bits except HALT bit */ - val = chip->ops->read32(chip->ctx, cr4->wrapbase + BCMA_IOCTL); + val = chip->ops->read32(chip->ctx, cpu->wrapbase + BCMA_IOCTL); val &= ARMCR4_BCMA_IOCTL_CPUHALT; brcmf_chip_resetcore(core, val, ARMCR4_BCMA_IOCTL_CPUHALT, ARMCR4_BCMA_IOCTL_CPUHALT); @@ -1162,6 +1211,33 @@ static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec) return true; } +static inline void +brcmf_chip_ca7_set_passive(struct brcmf_chip_priv *chip) +{ + struct brcmf_core *core; + + brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CA7); + + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); + brcmf_chip_resetcore(core, D11_BCMA_IOCTL_PHYRESET | + D11_BCMA_IOCTL_PHYCLOCKEN, + D11_BCMA_IOCTL_PHYCLOCKEN, + D11_BCMA_IOCTL_PHYCLOCKEN); +} + +static bool brcmf_chip_ca7_set_active(struct brcmf_chip_priv *chip, u32 rstvec) +{ + struct brcmf_core *core; + + chip->ops->activate(chip->ctx, &chip->pub, rstvec); + + /* restore ARM */ + core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CA7); + brcmf_chip_resetcore(core, ARMCR4_BCMA_IOCTL_CPUHALT, 0, 0); + + return true; +} + void brcmf_chip_set_passive(struct brcmf_chip *pub) { struct brcmf_chip_priv *chip; @@ -1175,8 +1251,16 @@ void brcmf_chip_set_passive(struct brcmf_chip *pub) brcmf_chip_cr4_set_passive(chip); return; } - - brcmf_chip_cm3_set_passive(chip); + arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7); + if (arm) { + brcmf_chip_ca7_set_passive(chip); + return; + } + arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3); + if (arm) { + brcmf_chip_cm3_set_passive(chip); + return; + } } bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec) @@ -1190,8 +1274,14 @@ bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec) arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); if (arm) return brcmf_chip_cr4_set_active(chip, rstvec); + arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CA7); + if (arm) + return brcmf_chip_ca7_set_active(chip, rstvec); + arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CM3); + if (arm) + return brcmf_chip_cm3_set_active(chip); - return brcmf_chip_cm3_set_active(chip); + return false; } bool brcmf_chip_sr_capable(struct brcmf_chip *pub) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index 451022e4cdea..30baf352e234 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c @@ -55,6 +55,10 @@ enum brcmf_pcie_state { #define BRCMF_PCIE_43570_NVRAM_NAME "brcm/brcmfmac43570-pcie.txt" #define BRCMF_PCIE_4358_FW_NAME "brcm/brcmfmac4358-pcie.bin" #define BRCMF_PCIE_4358_NVRAM_NAME "brcm/brcmfmac4358-pcie.txt" +#define BRCMF_PCIE_4365_FW_NAME "brcm/brcmfmac4365b-pcie.bin" +#define BRCMF_PCIE_4365_NVRAM_NAME "brcm/brcmfmac4365b-pcie.txt" +#define BRCMF_PCIE_4366_FW_NAME "brcm/brcmfmac4366b-pcie.bin" +#define BRCMF_PCIE_4366_NVRAM_NAME "brcm/brcmfmac4366b-pcie.txt" #define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */ @@ -204,6 +208,10 @@ MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME); MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME); MODULE_FIRMWARE(BRCMF_PCIE_4358_FW_NAME); MODULE_FIRMWARE(BRCMF_PCIE_4358_NVRAM_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4365_FW_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4365_NVRAM_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4366_FW_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4366_NVRAM_NAME); struct brcmf_pcie_console { @@ -1440,6 +1448,14 @@ static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo) fw_name = BRCMF_PCIE_4358_FW_NAME; nvram_name = BRCMF_PCIE_4358_NVRAM_NAME; break; + case BRCM_CC_4365_CHIP_ID: + fw_name = BRCMF_PCIE_4365_FW_NAME; + nvram_name = BRCMF_PCIE_4365_NVRAM_NAME; + break; + case BRCM_CC_4366_CHIP_ID: + fw_name = BRCMF_PCIE_4366_FW_NAME; + nvram_name = BRCMF_PCIE_4366_NVRAM_NAME; + break; default: brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip); return -ENODEV; @@ -1973,6 +1989,12 @@ static struct pci_device_id brcmf_pcie_devid_table[] = { BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID), { /* end: all zeroes */ } }; diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index 8278376aee40..d823734a4713 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h @@ -48,6 +48,8 @@ #define BRCM_CC_43570_CHIP_ID 43570 #define BRCM_CC_4358_CHIP_ID 0x4358 #define BRCM_CC_43602_CHIP_ID 43602 +#define BRCM_CC_4365_CHIP_ID 0x4365 +#define BRCM_CC_4366_CHIP_ID 0x4366 /* USB Device IDs */ #define BRCM_USB_43143_DEVICE_ID 0xbd1e @@ -67,6 +69,13 @@ #define BRCM_PCIE_43602_2G_DEVICE_ID 0x43bb #define BRCM_PCIE_43602_5G_DEVICE_ID 0x43bc #define BRCM_PCIE_43602_RAW_DEVICE_ID 43602 +#define BRCM_PCIE_4365_DEVICE_ID 0x43ca +#define BRCM_PCIE_4365_2G_DEVICE_ID 0x43cb +#define BRCM_PCIE_4365_5G_DEVICE_ID 0x43cc +#define BRCM_PCIE_4366_DEVICE_ID 0x43c3 +#define BRCM_PCIE_4366_2G_DEVICE_ID 0x43c4 +#define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5 + /* brcmsmac IDs */ #define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ -- cgit v1.2.3 From cb8dc71f516a98908de7de9be381ef9b571742e2 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:18 +0200 Subject: brcmfmac: Fix TDLS setup by properly handling p2p noif. There is a workaround needed for p2p device setup which breaks tdls functionality. This patch fixes that by properly signalling fweh that p2p device setup is ongoing. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/fweh.c | 17 +++++++++++++++-- drivers/net/wireless/brcm80211/brcmfmac/fweh.h | 3 +++ drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 8 +++++++- 3 files changed, 25 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index dc34d3a69b27..81542e064741 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -188,11 +188,13 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, /* The P2P Device interface event must not be ignored contrary to what * firmware tells us. Older firmware uses p2p noif, with sta role. - * This should be accepted. + * This should be accepted when p2pdev_setup is ongoing. TDLS setup will + * use the same ifevent and should be ignored. */ is_p2pdev = ((ifevent->flags & BRCMF_E_IF_FLAG_NOIF) && (ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT || - ifevent->role == BRCMF_E_IF_ROLE_STA)); + ((ifevent->role == BRCMF_E_IF_ROLE_STA) && + (drvr->fweh.p2pdev_setup_ongoing)))); if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { brcmf_dbg(EVENT, "event can be ignored\n"); return; @@ -315,6 +317,17 @@ event_free: } } +/** + * brcmf_fweh_p2pdev_setup() - P2P device setup ongoing (or not). + * + * @ifp: ifp on which setup is taking place or finished. + * @ongoing: p2p device setup in progress (or not). + */ +void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing) +{ + ifp->drvr->fweh.p2pdev_setup_ongoing = ongoing; +} + /** * brcmf_fweh_attach() - initialize firmware event handling. * diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h index 1326898d608e..d9a942842382 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h @@ -230,12 +230,14 @@ typedef int (*brcmf_fweh_handler_t)(struct brcmf_if *ifp, /** * struct brcmf_fweh_info - firmware event handling information. * + * @p2pdev_setup_ongoing: P2P device creation in progress. * @event_work: event worker. * @evt_q_lock: lock for event queue protection. * @event_q: event queue. * @evt_handler: registered event handlers. */ struct brcmf_fweh_info { + bool p2pdev_setup_ongoing; struct work_struct event_work; spinlock_t evt_q_lock; struct list_head event_q; @@ -255,6 +257,7 @@ void brcmf_fweh_unregister(struct brcmf_pub *drvr, int brcmf_fweh_activate_events(struct brcmf_if *ifp); void brcmf_fweh_process_event(struct brcmf_pub *drvr, struct brcmf_event *event_packet); +void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing); static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, struct sk_buff *skb) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index fda726c8e7ab..37a8c352e077 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -2084,11 +2084,13 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); brcmf_cfg80211_arm_vif_event(p2p->cfg, p2p_vif); + brcmf_fweh_p2pdev_setup(pri_ifp, true); /* Initialize P2P Discovery in the firmware */ err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); if (err < 0) { brcmf_err("set p2p_disc error\n"); + brcmf_fweh_p2pdev_setup(pri_ifp, false); brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); goto fail; } @@ -2097,6 +2099,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p, err = brcmf_cfg80211_wait_vif_event_timeout(p2p->cfg, BRCMF_E_IF_ADD, msecs_to_jiffies(1500)); brcmf_cfg80211_arm_vif_event(p2p->cfg, NULL); + brcmf_fweh_p2pdev_setup(pri_ifp, false); if (!err) { brcmf_err("timeout occurred\n"); err = -EIO; @@ -2396,6 +2399,8 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced) memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); + brcmf_fweh_p2pdev_setup(pri_ifp, true); + /* Initialize P2P Discovery in the firmware */ err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); if (err < 0) { @@ -2422,8 +2427,9 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced) INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); init_completion(&p2p->afx_hdl.act_frm_scan); init_completion(&p2p->wait_next_af); - } exit: + brcmf_fweh_p2pdev_setup(pri_ifp, false); + } return err; } -- cgit v1.2.3 From 29b93c0e3c3891e3ba6e38a71997bdad8a2aa457 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Fri, 18 Sep 2015 22:08:19 +0200 Subject: brcmfmac: Accept events when TDLS is used in combination with p2p. TDLS events are mapped back to primary interface but when p2p is in use then this fails because the check was incorrect by checking bsscfg number. Which can be different when a p2p device has been created. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/fweh.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index 81542e064741..383d6faf426b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -300,8 +300,7 @@ static void brcmf_fweh_event_worker(struct work_struct *work) goto event_free; } - if ((event->code == BRCMF_E_TDLS_PEER_EVENT) && - (emsg.bsscfgidx == 1)) + if (event->code == BRCMF_E_TDLS_PEER_EVENT) ifp = drvr->iflist[0]; else ifp = drvr->iflist[emsg.bsscfgidx]; -- cgit v1.2.3 From a32be01772525eba2001be23a570d9e31c58273d Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 19 Sep 2015 12:47:20 +0200 Subject: brcmfmac: include linux/atomic.h brcmfmac uses atomic_or() and other atomic_* functions, but does not include linux/atomic.h. This file gets included by some other header file so this normally does not cause problems. Signed-off-by: Hauke Mehrtens Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/sdio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index e41bf441410b..7f574f26cdef 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include -- cgit v1.2.3 From 4a0f2ea79797642341020eae5918871db94fc769 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Mon, 21 Sep 2015 15:44:24 +0200 Subject: airo: fix IW_AUTH_ALG_OPEN_SYSTEM IW_AUTH_ALG_OPEN_SYSTEM is ambiguous in set_auth for WEP as wpa_supplicant uses it for both no encryption and WEP open system. Cache the last mode set (only of these two) and use it here. This allows wpa_supplicant to work with unencrypted APs. Signed-off-by: Ondrej Zary Signed-off-by: Kalle Valo --- drivers/net/wireless/airo.c | 59 +++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index d0c97c220026..67001a86f240 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1237,6 +1237,7 @@ struct airo_info { int wep_capable; int max_wep_idx; + int last_auth; /* WPA-related stuff */ unsigned int bssListFirst; @@ -3786,6 +3787,16 @@ badrx: } } +static inline void set_auth_type(struct airo_info *local, int auth_type) +{ + local->config.authType = auth_type; + /* Cache the last auth type used (of AUTH_OPEN and AUTH_ENCRYPT). + * Used by airo_set_auth() + */ + if (auth_type == AUTH_OPEN || auth_type == AUTH_ENCRYPT) + local->last_auth = auth_type; +} + static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) { Cmd cmd; @@ -3862,7 +3873,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) "level scale"); } ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS; - ai->config.authType = AUTH_OPEN; + set_auth_type(ai, AUTH_OPEN); ai->config.modulation = MOD_CCK; if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) && @@ -4880,13 +4891,13 @@ static void proc_config_on_close(struct inode *inode, struct file *file) line += 5; switch( line[0] ) { case 's': - ai->config.authType = AUTH_SHAREDKEY; + set_auth_type(ai, AUTH_SHAREDKEY); break; case 'e': - ai->config.authType = AUTH_ENCRYPT; + set_auth_type(ai, AUTH_ENCRYPT); break; default: - ai->config.authType = AUTH_OPEN; + set_auth_type(ai, AUTH_OPEN); break; } set_bit (FLAG_COMMIT, &ai->flags); @@ -6368,9 +6379,8 @@ static int airo_set_encode(struct net_device *dev, * should be enabled (user may turn it off later) * This is also how "iwconfig ethX key on" works */ if((index == current_index) && (key.len > 0) && - (local->config.authType == AUTH_OPEN)) { - local->config.authType = AUTH_ENCRYPT; - } + (local->config.authType == AUTH_OPEN)) + set_auth_type(local, AUTH_ENCRYPT); } else { /* Do we want to just set the transmit key index ? */ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; @@ -6389,12 +6399,12 @@ static int airo_set_encode(struct net_device *dev, } } /* Read the flags */ - if(dwrq->flags & IW_ENCODE_DISABLED) - local->config.authType = AUTH_OPEN; // disable encryption + if (dwrq->flags & IW_ENCODE_DISABLED) + set_auth_type(local, AUTH_OPEN); /* disable encryption */ if(dwrq->flags & IW_ENCODE_RESTRICTED) - local->config.authType = AUTH_SHAREDKEY; // Only Both - if(dwrq->flags & IW_ENCODE_OPEN) - local->config.authType = AUTH_ENCRYPT; // Only Wep + set_auth_type(local, AUTH_SHAREDKEY); /* Only Both */ + if (dwrq->flags & IW_ENCODE_OPEN) + set_auth_type(local, AUTH_ENCRYPT); /* Only Wep */ /* Commit the changes to flags if needed */ if (local->config.authType != currentAuthType) set_bit (FLAG_COMMIT, &local->flags); @@ -6549,12 +6559,12 @@ static int airo_set_encodeext(struct net_device *dev, } /* Read the flags */ - if(encoding->flags & IW_ENCODE_DISABLED) - local->config.authType = AUTH_OPEN; // disable encryption + if (encoding->flags & IW_ENCODE_DISABLED) + set_auth_type(local, AUTH_OPEN); /* disable encryption */ if(encoding->flags & IW_ENCODE_RESTRICTED) - local->config.authType = AUTH_SHAREDKEY; // Only Both - if(encoding->flags & IW_ENCODE_OPEN) - local->config.authType = AUTH_ENCRYPT; // Only Wep + set_auth_type(local, AUTH_SHAREDKEY); /* Only Both */ + if (encoding->flags & IW_ENCODE_OPEN) + set_auth_type(local, AUTH_ENCRYPT); /* Commit the changes to flags if needed */ if (local->config.authType != currentAuthType) set_bit (FLAG_COMMIT, &local->flags); @@ -6659,9 +6669,9 @@ static int airo_set_auth(struct net_device *dev, if (param->value) { /* Only change auth type if unencrypted */ if (currentAuthType == AUTH_OPEN) - local->config.authType = AUTH_ENCRYPT; + set_auth_type(local, AUTH_ENCRYPT); } else { - local->config.authType = AUTH_OPEN; + set_auth_type(local, AUTH_OPEN); } /* Commit the changes to flags if needed */ @@ -6670,13 +6680,14 @@ static int airo_set_auth(struct net_device *dev, break; case IW_AUTH_80211_AUTH_ALG: { - /* FIXME: What about AUTH_OPEN? This API seems to - * disallow setting our auth to AUTH_OPEN. - */ if (param->value & IW_AUTH_ALG_SHARED_KEY) { - local->config.authType = AUTH_SHAREDKEY; + set_auth_type(local, AUTH_SHAREDKEY); } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { - local->config.authType = AUTH_ENCRYPT; + /* We don't know here if WEP open system or + * unencrypted mode was requested - so use the + * last mode (of these two) used last time + */ + set_auth_type(local, local->last_auth); } else return -EINVAL; -- cgit v1.2.3 From 2b8fa9e870b7dd4ea30a0c72e3a134533552278f Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Mon, 21 Sep 2015 15:44:25 +0200 Subject: airo: Implement netif_carrier_on/off Add calls to netif_carrier_on and netif_carrier_off Signed-off-by: Ondrej Zary Signed-off-by: Kalle Valo --- drivers/net/wireless/airo.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 67001a86f240..8ae838d96a9e 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -3267,6 +3267,7 @@ static void airo_handle_link(struct airo_info *ai) wake_up_interruptible(&ai->thr_wait); } else airo_send_event(ai->dev); + netif_carrier_on(ai->dev); } else if (!scan_forceloss) { if (auto_wep && !ai->expires) { ai->expires = RUN_AT(3*HZ); @@ -3277,6 +3278,9 @@ static void airo_handle_link(struct airo_info *ai) eth_zero_addr(wrqu.ap_addr.sa_data); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(ai->dev, SIOCGIWAP, &wrqu, NULL); + netif_carrier_off(ai->dev); + } else { + netif_carrier_off(ai->dev); } } @@ -3613,6 +3617,7 @@ static void disable_MAC( struct airo_info *ai, int lock ) { return; if (test_bit(FLAG_ENABLED, &ai->flags)) { + netif_carrier_off(ai->dev); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = MAC_DISABLE; // disable in case already enabled issuecommand(ai, &cmd, &rsp); -- cgit v1.2.3 From 1f9c6e1bc1ba5f8a10fcd6e99d170954d7c6d382 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 21 Sep 2015 19:19:53 +0300 Subject: mwifiex: fix mwifiex_rdeeprom_read() There were several bugs here. 1) The done label was in the wrong place so we didn't copy any information out when there was no command given. 2) We were using PAGE_SIZE as the size of the buffer instead of "PAGE_SIZE - pos". 3) snprintf() returns the number of characters that would have been printed if there were enough space. If there was not enough space (and we had fixed the memory corruption bug #2) then it would result in an information leak when we do simple_read_from_buffer(). I've changed it to use scnprintf() instead. I also removed the initialization at the start of the function, because I thought it made the code a little more clear. Fixes: 5e6e3a92b9a4 ('wireless: mwifiex: initial commit for Marvell mwifiex driver') Signed-off-by: Dan Carpenter Acked-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/debugfs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index 5a0636d43a1b..5583856fc5c4 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -731,7 +731,7 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, (struct mwifiex_private *) file->private_data; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *) addr; - int pos = 0, ret = 0, i; + int pos, ret, i; u8 value[MAX_EEPROM_DATA]; if (!buf) @@ -739,7 +739,7 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, if (saved_offset == -1) { /* No command has been given */ - pos += snprintf(buf, PAGE_SIZE, "0"); + pos = snprintf(buf, PAGE_SIZE, "0"); goto done; } @@ -748,17 +748,17 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, (u16) saved_bytes, value); if (ret) { ret = -EINVAL; - goto done; + goto out_free; } - pos += snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes); + pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes); for (i = 0; i < saved_bytes; i++) - pos += snprintf(buf + strlen(buf), PAGE_SIZE, "%d ", value[i]); - - ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); + pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]); done: + ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); +out_free: free_page(addr); return ret; } -- cgit v1.2.3 From bf69a3b60e4d892f8c1d7a6b18cf84aaa7acd43f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 12 Aug 2015 15:59:42 +0530 Subject: drivers: net: Drop unlikely before IS_ERR(_OR_NULL) IS_ERR(_OR_NULL) already contain an 'unlikely' compiler flag and there is no need to do that again from its callers. Drop it. Acked-by: Murali Karicheri Signed-off-by: Viresh Kumar Signed-off-by: Jiri Kosina --- drivers/net/ethernet/ti/netcp_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 9749dfd78c43..734a6c435840 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -1016,7 +1016,7 @@ netcp_tx_map_skb(struct sk_buff *skb, struct netcp_intf *netcp) } desc = knav_pool_desc_get(netcp->tx_pool); - if (unlikely(IS_ERR_OR_NULL(desc))) { + if (IS_ERR_OR_NULL(desc)) { dev_err(netcp->ndev_dev, "out of TX desc\n"); dma_unmap_single(dev, dma_addr, pkt_len, DMA_TO_DEVICE); return NULL; @@ -1049,7 +1049,7 @@ netcp_tx_map_skb(struct sk_buff *skb, struct netcp_intf *netcp) } ndesc = knav_pool_desc_get(netcp->tx_pool); - if (unlikely(IS_ERR_OR_NULL(ndesc))) { + if (IS_ERR_OR_NULL(ndesc)) { dev_err(netcp->ndev_dev, "out of TX desc for frags\n"); dma_unmap_page(dev, dma_addr, buf_len, DMA_TO_DEVICE); goto free_descs; -- cgit v1.2.3 From 2502d0ef272da7058ef303b849a2c8dc324c2e2e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 25 Sep 2015 18:09:35 +0200 Subject: net: mvneta: Fix CPU_MAP registers initialisation The CPU_MAP register is duplicated for each CPUs at different addresses, each instance being at a different address. However, the code so far was using CONFIG_NR_CPUS to initialise the CPU_MAP registers for each registers, while the SoCs embed at most 4 CPUs. This is especially an issue with multi_v7_defconfig, where CONFIG_NR_CPUS is currently set to 16, resulting in writes to registers that are not CPU_MAP. Fixes: c5aff18204da ("net: mvneta: driver for Marvell Armada 370/XP network unit") Signed-off-by: Maxime Ripard Cc: # v3.8+ Signed-off-by: Gregory CLEMENT Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 514df76fc70f..8c6f307457d3 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -949,7 +949,7 @@ static void mvneta_defaults_set(struct mvneta_port *pp) /* Set CPU queue access map - all CPUs have access to all RX * queues and to all TX queues */ - for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) + for_each_present_cpu(cpu) mvreg_write(pp, MVNETA_CPU_MAP(cpu), (MVNETA_CPU_RXQ_ACCESS_ALL_MASK | MVNETA_CPU_TXQ_ACCESS_ALL_MASK)); -- cgit v1.2.3 From 12bb03b436dad56692e9a103ed26156156bef5d2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 25 Sep 2015 18:09:36 +0200 Subject: net: mvneta: Handle per-cpu interrupts Now that our interrupt controller is allowing us to use per-CPU interrupts, actually use it in the mvneta driver. This involves obviously reworking the driver to have a CPU-local NAPI structure, and report for incoming packet using that structure. Signed-off-by: Maxime Ripard Signed-off-by: Gregory CLEMENT Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 91 ++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 8c6f307457d3..d0b710afffd6 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -285,7 +285,21 @@ struct mvneta_pcpu_stats { u64 tx_bytes; }; +struct mvneta_pcpu_port { + /* Pointer to the shared port */ + struct mvneta_port *pp; + + /* Pointer to the CPU-local NAPI struct */ + struct napi_struct napi; + + /* Cause of the previous interrupt */ + u32 cause_rx_tx; +}; + struct mvneta_port { + struct mvneta_pcpu_port __percpu *ports; + struct mvneta_pcpu_stats __percpu *stats; + int pkt_size; unsigned int frag_size; void __iomem *base; @@ -293,15 +307,11 @@ struct mvneta_port { struct mvneta_tx_queue *txqs; struct net_device *dev; - u32 cause_rx_tx; - struct napi_struct napi; - /* Core clock */ struct clk *clk; u8 mcast_count[256]; u16 tx_ring_size; u16 rx_ring_size; - struct mvneta_pcpu_stats *stats; struct mii_bus *mii_bus; struct phy_device *phy_dev; @@ -1461,6 +1471,7 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp, static int mvneta_rx(struct mvneta_port *pp, int rx_todo, struct mvneta_rx_queue *rxq) { + struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports); struct net_device *dev = pp->dev; int rx_done; u32 rcvd_pkts = 0; @@ -1515,7 +1526,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, skb->protocol = eth_type_trans(skb, dev); mvneta_rx_csum(pp, rx_status, skb); - napi_gro_receive(&pp->napi, skb); + napi_gro_receive(&port->napi, skb); rcvd_pkts++; rcvd_bytes += rx_bytes; @@ -1550,7 +1561,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo, mvneta_rx_csum(pp, rx_status, skb); - napi_gro_receive(&pp->napi, skb); + napi_gro_receive(&port->napi, skb); } if (rcvd_pkts) { @@ -2061,12 +2072,11 @@ static void mvneta_set_rx_mode(struct net_device *dev) /* Interrupt handling - the callback for request_irq() */ static irqreturn_t mvneta_isr(int irq, void *dev_id) { - struct mvneta_port *pp = (struct mvneta_port *)dev_id; + struct mvneta_pcpu_port *port = (struct mvneta_pcpu_port *)dev_id; - /* Mask all interrupts */ - mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); + disable_percpu_irq(port->pp->dev->irq); - napi_schedule(&pp->napi); + napi_schedule(&port->napi); return IRQ_HANDLED; } @@ -2104,11 +2114,11 @@ static int mvneta_poll(struct napi_struct *napi, int budget) { int rx_done = 0; u32 cause_rx_tx; - unsigned long flags; struct mvneta_port *pp = netdev_priv(napi->dev); + struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports); if (!netif_running(pp->dev)) { - napi_complete(napi); + napi_complete(&port->napi); return rx_done; } @@ -2135,7 +2145,7 @@ static int mvneta_poll(struct napi_struct *napi, int budget) /* For the case where the last mvneta_poll did not process all * RX packets */ - cause_rx_tx |= pp->cause_rx_tx; + cause_rx_tx |= port->cause_rx_tx; if (rxq_number > 1) { while ((cause_rx_tx & MVNETA_RX_INTR_MASK_ALL) && (budget > 0)) { int count; @@ -2166,16 +2176,11 @@ static int mvneta_poll(struct napi_struct *napi, int budget) if (budget > 0) { cause_rx_tx = 0; - napi_complete(napi); - local_irq_save(flags); - mvreg_write(pp, MVNETA_INTR_NEW_MASK, - MVNETA_RX_INTR_MASK(rxq_number) | - MVNETA_TX_INTR_MASK(txq_number) | - MVNETA_MISCINTR_INTR_MASK); - local_irq_restore(flags); + napi_complete(&port->napi); + enable_percpu_irq(pp->dev->irq, 0); } - pp->cause_rx_tx = cause_rx_tx; + port->cause_rx_tx = cause_rx_tx; return rx_done; } @@ -2424,6 +2429,8 @@ static int mvneta_setup_txqs(struct mvneta_port *pp) static void mvneta_start_dev(struct mvneta_port *pp) { + unsigned int cpu; + mvneta_max_rx_size_set(pp, pp->pkt_size); mvneta_txq_max_tx_size_set(pp, pp->pkt_size); @@ -2431,7 +2438,11 @@ static void mvneta_start_dev(struct mvneta_port *pp) mvneta_port_enable(pp); /* Enable polling on the port */ - napi_enable(&pp->napi); + for_each_present_cpu(cpu) { + struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); + + napi_enable(&port->napi); + } /* Unmask interrupts */ mvreg_write(pp, MVNETA_INTR_NEW_MASK, @@ -2449,9 +2460,15 @@ static void mvneta_start_dev(struct mvneta_port *pp) static void mvneta_stop_dev(struct mvneta_port *pp) { + unsigned int cpu; + phy_stop(pp->phy_dev); - napi_disable(&pp->napi); + for_each_present_cpu(cpu) { + struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); + + napi_disable(&port->napi); + } netif_carrier_off(pp->dev); @@ -2709,8 +2726,8 @@ static int mvneta_open(struct net_device *dev) goto err_cleanup_rxqs; /* Connect to port interrupt line */ - ret = request_irq(pp->dev->irq, mvneta_isr, 0, - MVNETA_DRIVER_NAME, pp); + ret = request_percpu_irq(pp->dev->irq, mvneta_isr, + MVNETA_DRIVER_NAME, pp->ports); if (ret) { netdev_err(pp->dev, "cannot request irq %d\n", pp->dev->irq); goto err_cleanup_txqs; @@ -2730,7 +2747,7 @@ static int mvneta_open(struct net_device *dev) return 0; err_free_irq: - free_irq(pp->dev->irq, pp); + free_percpu_irq(pp->dev->irq, pp->ports); err_cleanup_txqs: mvneta_cleanup_txqs(pp); err_cleanup_rxqs: @@ -2745,7 +2762,7 @@ static int mvneta_stop(struct net_device *dev) mvneta_stop_dev(pp); mvneta_mdio_remove(pp); - free_irq(dev->irq, pp); + free_percpu_irq(dev->irq, pp->ports); mvneta_cleanup_rxqs(pp); mvneta_cleanup_txqs(pp); @@ -3032,6 +3049,7 @@ static int mvneta_probe(struct platform_device *pdev) const char *managed; int phy_mode; int err; + int cpu; /* Our multiqueue support is not complete, so for now, only * allow the usage of the first RX queue @@ -3107,11 +3125,18 @@ static int mvneta_probe(struct platform_device *pdev) goto err_clk; } + /* Alloc per-cpu port structure */ + pp->ports = alloc_percpu(struct mvneta_pcpu_port); + if (!pp->ports) { + err = -ENOMEM; + goto err_clk; + } + /* Alloc per-cpu stats */ pp->stats = netdev_alloc_pcpu_stats(struct mvneta_pcpu_stats); if (!pp->stats) { err = -ENOMEM; - goto err_clk; + goto err_free_ports; } dt_mac_addr = of_get_mac_address(dn); @@ -3152,7 +3177,12 @@ static int mvneta_probe(struct platform_device *pdev) if (dram_target_info) mvneta_conf_mbus_windows(pp, dram_target_info); - netif_napi_add(dev, &pp->napi, mvneta_poll, NAPI_POLL_WEIGHT); + for_each_present_cpu(cpu) { + struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); + + netif_napi_add(dev, &port->napi, mvneta_poll, NAPI_POLL_WEIGHT); + port->pp = pp; + } dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; dev->hw_features |= dev->features; @@ -3183,6 +3213,8 @@ static int mvneta_probe(struct platform_device *pdev) err_free_stats: free_percpu(pp->stats); +err_free_ports: + free_percpu(pp->ports); err_clk: clk_disable_unprepare(pp->clk); err_put_phy_node: @@ -3202,6 +3234,7 @@ static int mvneta_remove(struct platform_device *pdev) unregister_netdev(dev); clk_disable_unprepare(pp->clk); + free_percpu(pp->ports); free_percpu(pp->stats); irq_dispose_mapping(dev->irq); of_node_put(pp->phy_node); -- cgit v1.2.3 From d893665728f3cc79f7719df50c4345d200bb293c Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 25 Sep 2015 18:09:37 +0200 Subject: net: mvneta: Allow different queues The mvneta driver allows to change the default RX queue trough the rxq_def kernel parameter. However, the current code doesn't allow to have any value but 0. It is actively checked for in the driver's probe because the drivers makes a number of assumption and takes a number of shortcuts in order to just use that RX queue. Remove these limitations in order to be able to specify any available queue. Signed-off-by: Maxime Ripard Signed-off-by: Gregory CLEMENT Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 80 +++++------------------------------ 1 file changed, 11 insertions(+), 69 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index d0b710afffd6..0702beb60031 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -478,7 +478,7 @@ struct mvneta_rx_queue { /* The hardware supports eight (8) rx queues, but we are only allowing * the first one to be used. Therefore, let's just allocate one queue. */ -static int rxq_number = 1; +static int rxq_number = 8; static int txq_number = 8; static int rxq_def; @@ -766,14 +766,7 @@ static void mvneta_port_up(struct mvneta_port *pp) mvreg_write(pp, MVNETA_TXQ_CMD, q_map); /* Enable all initialized RXQs. */ - q_map = 0; - for (queue = 0; queue < rxq_number; queue++) { - struct mvneta_rx_queue *rxq = &pp->rxqs[queue]; - if (rxq->descs != NULL) - q_map |= (1 << queue); - } - - mvreg_write(pp, MVNETA_RXQ_CMD, q_map); + mvreg_write(pp, MVNETA_RXQ_CMD, BIT(rxq_def)); } /* Stop the Ethernet port activity */ @@ -1436,17 +1429,6 @@ static u32 mvneta_skb_tx_csum(struct mvneta_port *pp, struct sk_buff *skb) return MVNETA_TX_L4_CSUM_NOT; } -/* Returns rx queue pointer (find last set bit) according to causeRxTx - * value - */ -static struct mvneta_rx_queue *mvneta_rx_policy(struct mvneta_port *pp, - u32 cause) -{ - int queue = fls(cause >> 8) - 1; - - return (queue < 0 || queue >= rxq_number) ? NULL : &pp->rxqs[queue]; -} - /* Drop packets received by the RXQ and free buffers */ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp, struct mvneta_rx_queue *rxq) @@ -2146,33 +2128,8 @@ static int mvneta_poll(struct napi_struct *napi, int budget) * RX packets */ cause_rx_tx |= port->cause_rx_tx; - if (rxq_number > 1) { - while ((cause_rx_tx & MVNETA_RX_INTR_MASK_ALL) && (budget > 0)) { - int count; - struct mvneta_rx_queue *rxq; - /* get rx queue number from cause_rx_tx */ - rxq = mvneta_rx_policy(pp, cause_rx_tx); - if (!rxq) - break; - - /* process the packet in that rx queue */ - count = mvneta_rx(pp, budget, rxq); - rx_done += count; - budget -= count; - if (budget > 0) { - /* set off the rx bit of the - * corresponding bit in the cause rx - * tx register, so that next iteration - * will find the next rx queue where - * packets are received on - */ - cause_rx_tx &= ~((1 << rxq->id) << 8); - } - } - } else { - rx_done = mvneta_rx(pp, budget, &pp->rxqs[rxq_def]); - budget -= rx_done; - } + rx_done = mvneta_rx(pp, budget, &pp->rxqs[rxq_def]); + budget -= rx_done; if (budget > 0) { cause_rx_tx = 0; @@ -2384,26 +2341,19 @@ static void mvneta_cleanup_txqs(struct mvneta_port *pp) /* Cleanup all Rx queues */ static void mvneta_cleanup_rxqs(struct mvneta_port *pp) { - int queue; - - for (queue = 0; queue < rxq_number; queue++) - mvneta_rxq_deinit(pp, &pp->rxqs[queue]); + mvneta_rxq_deinit(pp, &pp->rxqs[rxq_def]); } /* Init all Rx queues */ static int mvneta_setup_rxqs(struct mvneta_port *pp) { - int queue; - - for (queue = 0; queue < rxq_number; queue++) { - int err = mvneta_rxq_init(pp, &pp->rxqs[queue]); - if (err) { - netdev_err(pp->dev, "%s: can't create rxq=%d\n", - __func__, queue); - mvneta_cleanup_rxqs(pp); - return err; - } + int err = mvneta_rxq_init(pp, &pp->rxqs[rxq_def]); + if (err) { + netdev_err(pp->dev, "%s: can't create rxq=%d\n", + __func__, rxq_def); + mvneta_cleanup_rxqs(pp); + return err; } return 0; @@ -3051,14 +3001,6 @@ static int mvneta_probe(struct platform_device *pdev) int err; int cpu; - /* Our multiqueue support is not complete, so for now, only - * allow the usage of the first RX queue - */ - if (rxq_def != 0) { - dev_err(&pdev->dev, "Invalid rxq_def argument: %d\n", rxq_def); - return -EINVAL; - } - dev = alloc_etherdev_mqs(sizeof(struct mvneta_port), txq_number, rxq_number); if (!dev) return -ENOMEM; -- cgit v1.2.3 From f864288544802ae68b20da293e1b861230852dba Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 25 Sep 2015 18:09:38 +0200 Subject: net: mvneta: Statically assign queues to CPUs Since the switch to per-CPU interrupts, we lost the ability to set which CPU was going to receive our RX interrupt, which was now only the CPU on which the mvneta_open function was run. We can now assign our queues to their respective CPUs, and make sure only this CPU is going to handle our traffic. This also paves the road to be able to change that at runtime, and later on to support RSS. [gregory.clement@free-electrons.com]: hardened the CPU hotplug support. Signed-off-by: Maxime Ripard Signed-off-by: Gregory CLEMENT Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 143 +++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 0702beb60031..dd6fe942acf9 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -32,6 +32,7 @@ #include #include #include +#include /* Registers */ #define MVNETA_RXQ_CONFIG_REG(q) (0x1400 + ((q) << 2)) @@ -306,6 +307,7 @@ struct mvneta_port { struct mvneta_rx_queue *rxqs; struct mvneta_tx_queue *txqs; struct net_device *dev; + struct notifier_block cpu_notifier; /* Core clock */ struct clk *clk; @@ -2057,7 +2059,6 @@ static irqreturn_t mvneta_isr(int irq, void *dev_id) struct mvneta_pcpu_port *port = (struct mvneta_pcpu_port *)dev_id; disable_percpu_irq(port->pp->dev->irq); - napi_schedule(&port->napi); return IRQ_HANDLED; @@ -2658,6 +2659,125 @@ static void mvneta_mdio_remove(struct mvneta_port *pp) pp->phy_dev = NULL; } +static void mvneta_percpu_enable(void *arg) +{ + struct mvneta_port *pp = arg; + + enable_percpu_irq(pp->dev->irq, IRQ_TYPE_NONE); +} + +static void mvneta_percpu_disable(void *arg) +{ + struct mvneta_port *pp = arg; + + disable_percpu_irq(pp->dev->irq); +} + +static void mvneta_percpu_elect(struct mvneta_port *pp) +{ + int online_cpu_idx, cpu, i = 0; + + online_cpu_idx = rxq_def % num_online_cpus(); + + for_each_online_cpu(cpu) { + if (i == online_cpu_idx) + /* Enable per-CPU interrupt on the one CPU we + * just elected + */ + smp_call_function_single(cpu, mvneta_percpu_enable, + pp, true); + else + /* Disable per-CPU interrupt on all the other CPU */ + smp_call_function_single(cpu, mvneta_percpu_disable, + pp, true); + i++; + } +}; + +static int mvneta_percpu_notifier(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + struct mvneta_port *pp = container_of(nfb, struct mvneta_port, + cpu_notifier); + int cpu = (unsigned long)hcpu, other_cpu; + struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); + + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + netif_tx_stop_all_queues(pp->dev); + + /* We have to synchronise on tha napi of each CPU + * except the one just being waked up + */ + for_each_online_cpu(other_cpu) { + if (other_cpu != cpu) { + struct mvneta_pcpu_port *other_port = + per_cpu_ptr(pp->ports, other_cpu); + + napi_synchronize(&other_port->napi); + } + } + + /* Mask all ethernet port interrupts */ + mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); + mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); + mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); + napi_enable(&port->napi); + + /* Enable per-CPU interrupt on the one CPU we care + * about. + */ + mvneta_percpu_elect(pp); + + /* Unmask all ethernet port interrupts */ + mvreg_write(pp, MVNETA_INTR_NEW_MASK, + MVNETA_RX_INTR_MASK(rxq_number) | + MVNETA_TX_INTR_MASK(txq_number) | + MVNETA_MISCINTR_INTR_MASK); + mvreg_write(pp, MVNETA_INTR_MISC_MASK, + MVNETA_CAUSE_PHY_STATUS_CHANGE | + MVNETA_CAUSE_LINK_CHANGE | + MVNETA_CAUSE_PSC_SYNC_CHANGE); + netif_tx_start_all_queues(pp->dev); + break; + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + netif_tx_stop_all_queues(pp->dev); + /* Mask all ethernet port interrupts */ + mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); + mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); + mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); + + napi_synchronize(&port->napi); + napi_disable(&port->napi); + /* Disable per-CPU interrupts on the CPU that is + * brought down. + */ + smp_call_function_single(cpu, mvneta_percpu_disable, + pp, true); + + break; + case CPU_DEAD: + case CPU_DEAD_FROZEN: + /* Check if a new CPU must be elected now this on is down */ + mvneta_percpu_elect(pp); + /* Unmask all ethernet port interrupts */ + mvreg_write(pp, MVNETA_INTR_NEW_MASK, + MVNETA_RX_INTR_MASK(rxq_number) | + MVNETA_TX_INTR_MASK(txq_number) | + MVNETA_MISCINTR_INTR_MASK); + mvreg_write(pp, MVNETA_INTR_MISC_MASK, + MVNETA_CAUSE_PHY_STATUS_CHANGE | + MVNETA_CAUSE_LINK_CHANGE | + MVNETA_CAUSE_PSC_SYNC_CHANGE); + netif_tx_start_all_queues(pp->dev); + break; + } + + return NOTIFY_OK; +} + static int mvneta_open(struct net_device *dev) { struct mvneta_port *pp = netdev_priv(dev); @@ -2683,6 +2803,22 @@ static int mvneta_open(struct net_device *dev) goto err_cleanup_txqs; } + /* Even though the documentation says that request_percpu_irq + * doesn't enable the interrupts automatically, it actually + * does so on the local CPU. + * + * Make sure it's disabled. + */ + mvneta_percpu_disable(pp); + + /* Elect a CPU to handle our RX queue interrupt */ + mvneta_percpu_elect(pp); + + /* Register a CPU notifier to handle the case where our CPU + * might be taken offline. + */ + register_cpu_notifier(&pp->cpu_notifier); + /* In default link is down */ netif_carrier_off(pp->dev); @@ -2709,9 +2845,13 @@ err_cleanup_rxqs: static int mvneta_stop(struct net_device *dev) { struct mvneta_port *pp = netdev_priv(dev); + int cpu; mvneta_stop_dev(pp); mvneta_mdio_remove(pp); + unregister_cpu_notifier(&pp->cpu_notifier); + for_each_present_cpu(cpu) + smp_call_function_single(cpu, mvneta_percpu_disable, pp, true); free_percpu_irq(dev->irq, pp->ports); mvneta_cleanup_rxqs(pp); mvneta_cleanup_txqs(pp); @@ -3051,6 +3191,7 @@ static int mvneta_probe(struct platform_device *pdev) err = of_property_read_string(dn, "managed", &managed); pp->use_inband_status = (err == 0 && strcmp(managed, "in-band-status") == 0); + pp->cpu_notifier.notifier_call = mvneta_percpu_notifier; pp->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(pp->clk)) { -- cgit v1.2.3 From 0f50c10d2683fd2b8a3908c779c5f29bcb3c2174 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Mon, 28 Sep 2015 17:51:51 +0100 Subject: RESEND: [PATCH v3 net-next] sky2: use random address if EEPROM is bad On some embedded systems the EEPROM does not contain a valid MAC address. In that case it is better to fallback to a generated mac address and let init scripts fix the value later. Reported-by: Liviu Dudau Signed-off-by: Stephen Hemminger [Changed handcoded setup to use eth_hw_addr_random() and to save new address into HW] Signed-off-by: Liviu Dudau Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/sky2.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index d9f4498832a1..5606a043063e 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -4819,6 +4819,18 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port, memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN); + /* if the address is invalid, use a random value */ + if (!is_valid_ether_addr(dev->dev_addr)) { + struct sockaddr sa = { AF_UNSPEC }; + + netdev_warn(dev, + "Invalid MAC address, defaulting to random\n"); + eth_hw_addr_random(dev); + memcpy(sa.sa_data, dev->dev_addr, ETH_ALEN); + if (sky2_set_mac_address(dev, &sa)) + netdev_warn(dev, "Failed to set MAC address.\n"); + } + return dev; } -- cgit v1.2.3 From 007979eaf94d1c888d8c7cf8a5250c2c6c9bd98e Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 29 Sep 2015 20:07:10 -0700 Subject: net: Rename IFF_VRF_MASTER to IFF_L3MDEV_MASTER Rename IFF_VRF_MASTER to IFF_L3MDEV_MASTER and update the name of the netif_is_vrf and netif_index_is_vrf macros. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 4ecb3a3e516a..2d7418e0b908 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -438,7 +438,7 @@ out_fail: static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev) { - if (netif_is_vrf(port_dev) || vrf_is_slave(port_dev)) + if (netif_is_l3_master(port_dev) || vrf_is_slave(port_dev)) return -EINVAL; return do_vrf_add_slave(dev, port_dev); @@ -591,7 +591,7 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev, vrf->tb_id = nla_get_u32(data[IFLA_VRF_TABLE]); - dev->priv_flags |= IFF_VRF_MASTER; + dev->priv_flags |= IFF_L3MDEV_MASTER; err = -ENOMEM; vrf_ptr = kmalloc(sizeof(*dev->vrf_ptr), GFP_KERNEL); @@ -657,7 +657,7 @@ static int vrf_device_event(struct notifier_block *unused, struct net_vrf_dev *vrf_ptr = rtnl_dereference(dev->vrf_ptr); struct net_device *vrf_dev; - if (!vrf_ptr || netif_is_vrf(dev)) + if (!vrf_ptr || netif_is_l3_master(dev)) goto out; vrf_dev = netdev_master_upper_dev_get(dev); -- cgit v1.2.3 From ee15ee5d94f5837260e7fa539ffd1b50952079c4 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 29 Sep 2015 20:07:12 -0700 Subject: net: Add support for l3mdev ops to VRF driver Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/Kconfig | 1 + drivers/net/vrf.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d18eb607bee6..b9ebd0d18a52 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -299,6 +299,7 @@ config NLMON config NET_VRF tristate "Virtual Routing and Forwarding (Lite)" depends on IP_MULTIPLE_TABLES && IPV6_MULTIPLE_TABLES + depends on NET_L3_MASTER_DEV ---help--- This option enables the support for mapping interfaces into VRF's. The support enables VRF devices. diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 2d7418e0b908..72f1892ebad0 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -35,6 +35,7 @@ #include #include #include +#include #define DRV_NAME "vrf" #define DRV_VERSION "1.0" @@ -529,6 +530,33 @@ static const struct net_device_ops vrf_netdev_ops = { .ndo_del_slave = vrf_del_slave, }; +static u32 vrf_fib_table(const struct net_device *dev) +{ + struct net_vrf *vrf = netdev_priv(dev); + + return vrf->tb_id; +} + +static struct rtable *vrf_get_rtable(const struct net_device *dev, + const struct flowi4 *fl4) +{ + struct rtable *rth = NULL; + + if (!(fl4->flowi4_flags & FLOWI_FLAG_VRFSRC)) { + struct net_vrf *vrf = netdev_priv(dev); + + rth = vrf->rth; + atomic_inc(&rth->dst.__refcnt); + } + + return rth; +} + +static const struct l3mdev_ops vrf_l3mdev_ops = { + .l3mdev_fib_table = vrf_fib_table, + .l3mdev_get_rtable = vrf_get_rtable, +}; + static void vrf_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -546,6 +574,7 @@ static void vrf_setup(struct net_device *dev) /* Initialize the device structure. */ dev->netdev_ops = &vrf_netdev_ops; + dev->l3mdev_ops = &vrf_l3mdev_ops; dev->ethtool_ops = &vrf_ethtool_ops; dev->destructor = free_netdev; -- cgit v1.2.3 From 93a7e7e837af6846052481da974320c19ab82e5c Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 29 Sep 2015 20:07:16 -0700 Subject: net: Remove the now unused vrf_ptr Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 72f1892ebad0..df872f4efb0d 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -396,18 +396,15 @@ static void __vrf_insert_slave(struct slave_queue *queue, struct slave *slave) static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev) { - struct net_vrf_dev *vrf_ptr = kmalloc(sizeof(*vrf_ptr), GFP_KERNEL); struct slave *slave = kzalloc(sizeof(*slave), GFP_KERNEL); struct net_vrf *vrf = netdev_priv(dev); struct slave_queue *queue = &vrf->queue; int ret = -ENOMEM; - if (!slave || !vrf_ptr) + if (!slave) goto out_fail; slave->dev = port_dev; - vrf_ptr->ifindex = dev->ifindex; - vrf_ptr->tb_id = vrf->tb_id; /* register the packet handler for slave ports */ ret = netdev_rx_handler_register(port_dev, vrf_handle_frame, dev); @@ -424,7 +421,6 @@ static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev) port_dev->flags |= IFF_SLAVE; __vrf_insert_slave(queue, slave); - rcu_assign_pointer(port_dev->vrf_ptr, vrf_ptr); cycle_netdev(port_dev); return 0; @@ -432,7 +428,6 @@ static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev) out_unregister: netdev_rx_handler_unregister(port_dev); out_fail: - kfree(vrf_ptr); kfree(slave); return ret; } @@ -448,21 +443,15 @@ static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev) /* inverse of do_vrf_add_slave */ static int do_vrf_del_slave(struct net_device *dev, struct net_device *port_dev) { - struct net_vrf_dev *vrf_ptr = rtnl_dereference(port_dev->vrf_ptr); struct net_vrf *vrf = netdev_priv(dev); struct slave_queue *queue = &vrf->queue; struct slave *slave; - RCU_INIT_POINTER(port_dev->vrf_ptr, NULL); - netdev_upper_dev_unlink(port_dev, dev); port_dev->flags &= ~IFF_SLAVE; netdev_rx_handler_unregister(port_dev); - /* after netdev_rx_handler_unregister for synchronize_rcu */ - kfree(vrf_ptr); - cycle_netdev(port_dev); slave = __vrf_find_slave_dev(queue, port_dev); @@ -601,10 +590,6 @@ static int vrf_validate(struct nlattr *tb[], struct nlattr *data[]) static void vrf_dellink(struct net_device *dev, struct list_head *head) { - struct net_vrf_dev *vrf_ptr = rtnl_dereference(dev->vrf_ptr); - - RCU_INIT_POINTER(dev->vrf_ptr, NULL); - kfree_rcu(vrf_ptr, rcu); unregister_netdevice_queue(dev, head); } @@ -612,7 +597,6 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { struct net_vrf *vrf = netdev_priv(dev); - struct net_vrf_dev *vrf_ptr; int err; if (!data || !data[IFLA_VRF_TABLE]) @@ -622,24 +606,13 @@ static int vrf_newlink(struct net *src_net, struct net_device *dev, dev->priv_flags |= IFF_L3MDEV_MASTER; - err = -ENOMEM; - vrf_ptr = kmalloc(sizeof(*dev->vrf_ptr), GFP_KERNEL); - if (!vrf_ptr) - goto out_fail; - - vrf_ptr->ifindex = dev->ifindex; - vrf_ptr->tb_id = vrf->tb_id; - err = register_netdevice(dev); if (err < 0) goto out_fail; - rcu_assign_pointer(dev->vrf_ptr, vrf_ptr); - return 0; out_fail: - kfree(vrf_ptr); free_netdev(dev); return err; } @@ -683,10 +656,9 @@ static int vrf_device_event(struct notifier_block *unused, /* only care about unregister events to drop slave references */ if (event == NETDEV_UNREGISTER) { - struct net_vrf_dev *vrf_ptr = rtnl_dereference(dev->vrf_ptr); struct net_device *vrf_dev; - if (!vrf_ptr || netif_is_l3_master(dev)) + if (netif_is_l3_master(dev)) goto out; vrf_dev = netdev_master_upper_dev_get(dev); -- cgit v1.2.3 From ec539514e56284b21c47468f23f7d01ff882f51b Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 29 Sep 2015 20:07:17 -0700 Subject: net: Remove vrf header file Move remaining structs to VRF driver and delete the vrf header file. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index df872f4efb0d..64f2ab663ffe 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #define DRV_NAME "vrf" @@ -45,6 +44,21 @@ #define vrf_master_get_rcu(dev) \ ((struct net_device *)rcu_dereference(dev->rx_handler_data)) +struct slave { + struct list_head list; + struct net_device *dev; +}; + +struct slave_queue { + struct list_head all_slaves; +}; + +struct net_vrf { + struct slave_queue queue; + struct rtable *rth; + u32 tb_id; +}; + struct pcpu_dstats { u64 tx_pkts; u64 tx_bytes; -- cgit v1.2.3 From 4905287138f60e86198620c72b570d3d265a71ea Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Tue, 29 Sep 2015 01:53:48 +0200 Subject: dsa: mv88e6xxx: Fix unsigned/signed issue commit dea870242a9c ("dsa: mv88e6xxx: Allow speed/duplex of port to be configured") leads to the following static checker warning: drivers/net/dsa/mv88e6xxx.c:585 mv88e6xxx_adjust_link() warn: unsigned 'ret' is never less than zero. drivers/net/dsa/mv88e6xxx.c 573 void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, 574 struct phy_device *phydev) 575 { 576 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 577 u32 ret, reg; 578 579 if (!phy_is_pseudo_fixed_link(phydev)) 580 return; 581 582 mutex_lock(&ps->smi_mutex); 583 584 ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL); 585 if (ret < 0) Make ret an int, which is the return type for _mv88e6xxx_reg_read() Reported-by: Dan Carpenter Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 8e9d172543a0..b3849267ae7a 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -574,7 +574,8 @@ void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phydev) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - u32 ret, reg; + u32 reg; + int ret; if (!phy_is_pseudo_fixed_link(phydev)) return; -- cgit v1.2.3 From 3a3a7f3b7fbd3c2f2ca2f2bf76363a1abbd5ba94 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 29 Sep 2015 10:24:02 +0200 Subject: net: mac8390: Allow modular build The modular driver supports only one card, just like the built-in driver. Note that this limitation is a problem which affects all Nubus card drivers, because they have to do all their own bus matching, because Nubus still lacks the necessary driver model support. Suggested-by: Finn Thain Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/ethernet/8390/Kconfig | 2 +- drivers/net/ethernet/8390/mac8390.c | 32 ++++++++++---------------------- 2 files changed, 11 insertions(+), 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig index edf72258ab1d..29c3075bfb05 100644 --- a/drivers/net/ethernet/8390/Kconfig +++ b/drivers/net/ethernet/8390/Kconfig @@ -64,7 +64,7 @@ config ARM_ETHERH should say Y to this option if you wish to use it with Linux. config MAC8390 - bool "Macintosh NS 8390 based ethernet cards" + tristate "Macintosh NS 8390 based ethernet cards" depends on MAC select CRC32 ---help--- diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c index 65cf60f6718c..b9283901136e 100644 --- a/drivers/net/ethernet/8390/mac8390.c +++ b/drivers/net/ethernet/8390/mac8390.c @@ -454,34 +454,22 @@ MODULE_AUTHOR("David Huggins-Daines and others"); MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver"); MODULE_LICENSE("GPL"); -/* overkill, of course */ -static struct net_device *dev_mac8390[15]; -int init_module(void) +static struct net_device *dev_mac8390; + +int __init init_module(void) { - int i; - for (i = 0; i < 15; i++) { - struct net_device *dev = mac8390_probe(-1); - if (IS_ERR(dev)) - break; - dev_mac890[i] = dev; - } - if (!i) { - pr_notice("No useable cards found, driver NOT installed.\n"); - return -ENODEV; + dev_mac8390 = mac8390_probe(-1); + if (IS_ERR(dev_mac8390)) { + pr_warn("mac8390: No card found\n"); + return PTR_ERR(dev_mac8390); } return 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { - int i; - for (i = 0; i < 15; i++) { - struct net_device *dev = dev_mac890[i]; - if (dev) { - unregister_netdev(dev); - free_netdev(dev); - } - } + unregister_netdev(dev_mac8390); + free_netdev(dev_mac8390); } #endif /* MODULE */ -- cgit v1.2.3 From 93a82ca2f3c642becc3d824ba79be98084f76519 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 29 Sep 2015 10:24:03 +0200 Subject: net: 7990: Export lance_poll() to modules If CONFIG_HPLANCE=m and CONFIG_NET_POLL_CONTROLLER=y: ERROR: "lance_poll" [drivers/net/ethernet/amd/hplance.ko] undefined! Add the missing export to fix this. Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/7990.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/7990.c b/drivers/net/ethernet/amd/7990.c index 98a10d555b79..66d0b73c39c0 100644 --- a/drivers/net/ethernet/amd/7990.c +++ b/drivers/net/ethernet/amd/7990.c @@ -661,6 +661,7 @@ void lance_poll(struct net_device *dev) spin_unlock(&lp->devlock); lance_interrupt(dev->irq, dev); } +EXPORT_SYMBOL_GPL(lance_poll); #endif MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 18785040b088c0d90713606b57a8b1bd4834ec04 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 29 Sep 2015 10:24:04 +0200 Subject: net: hplance: Allow modular build Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig index afc62ea804fc..0038709fd317 100644 --- a/drivers/net/ethernet/amd/Kconfig +++ b/drivers/net/ethernet/amd/Kconfig @@ -100,7 +100,7 @@ config DECLANCE DEPCA series. (This chipset is better known via the NE2100 cards.) config HPLANCE - bool "HP on-board LANCE support" + tristate "HP on-board LANCE support" depends on DIO select CRC32 ---help--- -- cgit v1.2.3 From 6153348f5e0cc6e162918c20e05534981aa5504c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 29 Sep 2015 10:24:06 +0200 Subject: net: macmace: Allow modular build Signed-off-by: Geert Uytterhoeven Signed-off-by: David S. Miller --- drivers/net/ethernet/apple/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/apple/Kconfig b/drivers/net/ethernet/apple/Kconfig index d19a41b0c6d2..31071297896c 100644 --- a/drivers/net/ethernet/apple/Kconfig +++ b/drivers/net/ethernet/apple/Kconfig @@ -51,7 +51,7 @@ config BMAC will be called bmac. config MACMACE - bool "Macintosh (AV) onboard MACE ethernet" + tristate "Macintosh (AV) onboard MACE ethernet" depends on MAC select CRC32 ---help--- -- cgit v1.2.3 From 03d5fb18626aff95426a380aef0d1c6904cac7c9 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Tue, 29 Sep 2015 12:07:15 -0400 Subject: net: switchdev: remove dev from switchdev_obj cb The net_device associated to a dump operation does not have to be passed to the callback. switchdev stores it in a superset struct, if needed. Also some drivers (such as DSA drivers) may not have easy access to it. This will simplify pushing the callback function down to the drivers. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index d3f663262184..78fd443f2ea1 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4556,7 +4556,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, fdb->ndm_state = NUD_REACHABLE; fdb->vid = rocker_port_vlan_to_vid(rocker_port, found->key.vlan_id); - err = obj->cb(rocker_port->dev, obj); + err = obj->cb(obj); if (err) break; } @@ -4579,7 +4579,7 @@ static int rocker_port_vlan_dump(const struct rocker_port *rocker_port, if (rocker_vlan_id_is_internal(htons(vid))) vlan->flags |= BRIDGE_VLAN_INFO_PVID; vlan->vid_begin = vlan->vid_end = vid; - err = obj->cb(rocker_port->dev, obj); + err = obj->cb(obj); if (err) break; } -- cgit v1.2.3 From 25f07adc473f05f850efc9414b9da3374563015f Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Tue, 29 Sep 2015 12:07:16 -0400 Subject: net: switchdev: pass callback to dump operation Similar to the notifier_call callback of a notifier_block, change the function signature of switchdev dump operation to: int switchdev_port_obj_dump(struct net_device *dev, enum switchdev_obj_id id, void *obj, int (*cb)(void *obj)); This allows the caller to pass and expect back a specific switchdev_obj_* structure instead of the generic switchdev_obj one. Drivers implementation of dump operation can now expect this specific structure and call the callback with it. Drivers have been changed accordingly. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 78fd443f2ea1..107adb6aee81 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4538,10 +4538,10 @@ static int rocker_port_obj_del(struct net_device *dev, } static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, - struct switchdev_obj *obj) + struct switchdev_obj_fdb *fdb, + int (*cb)(void *obj)) { struct rocker *rocker = rocker_port->rocker; - struct switchdev_obj_fdb *fdb = &obj->u.fdb; struct rocker_fdb_tbl_entry *found; struct hlist_node *tmp; unsigned long lock_flags; @@ -4556,7 +4556,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, fdb->ndm_state = NUD_REACHABLE; fdb->vid = rocker_port_vlan_to_vid(rocker_port, found->key.vlan_id); - err = obj->cb(obj); + err = cb(fdb); if (err) break; } @@ -4566,9 +4566,9 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, } static int rocker_port_vlan_dump(const struct rocker_port *rocker_port, - struct switchdev_obj *obj) + struct switchdev_obj_vlan *vlan, + int (*cb)(void *obj)) { - struct switchdev_obj_vlan *vlan = &obj->u.vlan; u16 vid; int err = 0; @@ -4579,7 +4579,7 @@ static int rocker_port_vlan_dump(const struct rocker_port *rocker_port, if (rocker_vlan_id_is_internal(htons(vid))) vlan->flags |= BRIDGE_VLAN_INFO_PVID; vlan->vid_begin = vlan->vid_end = vid; - err = obj->cb(obj); + err = cb(vlan); if (err) break; } @@ -4588,17 +4588,18 @@ static int rocker_port_vlan_dump(const struct rocker_port *rocker_port, } static int rocker_port_obj_dump(struct net_device *dev, - struct switchdev_obj *obj) + enum switchdev_obj_id id, void *obj, + int (*cb)(void *obj)) { const struct rocker_port *rocker_port = netdev_priv(dev); int err = 0; - switch (obj->id) { + switch (id) { case SWITCHDEV_OBJ_PORT_FDB: - err = rocker_port_fdb_dump(rocker_port, obj); + err = rocker_port_fdb_dump(rocker_port, obj, cb); break; case SWITCHDEV_OBJ_PORT_VLAN: - err = rocker_port_vlan_dump(rocker_port, obj); + err = rocker_port_vlan_dump(rocker_port, obj, cb); break; default: err = -EOPNOTSUPP; -- cgit v1.2.3 From ab06900230181b5a717b1e1a39c44e96f6292e71 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Tue, 29 Sep 2015 12:07:17 -0400 Subject: net: switchdev: abstract object in add/del ops Similar to the notifier_call callback of a notifier_block, change the function signature of switchdev add and del operations to: int switchdev_port_obj_add/del(struct net_device *dev, enum switchdev_obj_id id, void *obj); This allows the caller to pass a specific switchdev_obj_* structure instead of the generic switchdev_obj one. Drivers implementation of these operations and switchdev have been changed accordingly. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 107adb6aee81..9773f5b65296 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4437,26 +4437,25 @@ static int rocker_port_fdb_add(struct rocker_port *rocker_port, } static int rocker_port_obj_add(struct net_device *dev, - struct switchdev_obj *obj, + enum switchdev_obj_id id, const void *obj, struct switchdev_trans *trans) { struct rocker_port *rocker_port = netdev_priv(dev); const struct switchdev_obj_ipv4_fib *fib4; int err = 0; - switch (obj->id) { + switch (id) { case SWITCHDEV_OBJ_PORT_VLAN: - err = rocker_port_vlans_add(rocker_port, trans, - &obj->u.vlan); + err = rocker_port_vlans_add(rocker_port, trans, obj); break; case SWITCHDEV_OBJ_IPV4_FIB: - fib4 = &obj->u.ipv4_fib; + fib4 = obj; err = rocker_port_fib_ipv4(rocker_port, trans, htonl(fib4->dst), fib4->dst_len, fib4->fi, fib4->tb_id, 0); break; case SWITCHDEV_OBJ_PORT_FDB: - err = rocker_port_fdb_add(rocker_port, trans, &obj->u.fdb); + err = rocker_port_fdb_add(rocker_port, trans, obj); break; default: err = -EOPNOTSUPP; @@ -4509,25 +4508,25 @@ static int rocker_port_fdb_del(struct rocker_port *rocker_port, } static int rocker_port_obj_del(struct net_device *dev, - struct switchdev_obj *obj) + enum switchdev_obj_id id, const void *obj) { struct rocker_port *rocker_port = netdev_priv(dev); const struct switchdev_obj_ipv4_fib *fib4; int err = 0; - switch (obj->id) { + switch (id) { case SWITCHDEV_OBJ_PORT_VLAN: - err = rocker_port_vlans_del(rocker_port, &obj->u.vlan); + err = rocker_port_vlans_del(rocker_port, obj); break; case SWITCHDEV_OBJ_IPV4_FIB: - fib4 = &obj->u.ipv4_fib; + fib4 = obj; err = rocker_port_fib_ipv4(rocker_port, NULL, htonl(fib4->dst), fib4->dst_len, fib4->fi, fib4->tb_id, ROCKER_OP_FLAG_REMOVE); break; case SWITCHDEV_OBJ_PORT_FDB: - err = rocker_port_fdb_del(rocker_port, NULL, &obj->u.fdb); + err = rocker_port_fdb_del(rocker_port, NULL, obj); break; default: err = -EOPNOTSUPP; -- cgit v1.2.3 From 7253054e5d05233063c48f57ac02283bd35753d8 Mon Sep 17 00:00:00 2001 From: Stephane Grosjean Date: Wed, 30 Sep 2015 12:42:35 +0200 Subject: can: peak_pci: add unused device id. in devices table While new PEAK_PCIE_OEM_ID has been defined since 3.17, no corresponding entry has been added in the peak_pci_tbl[] of the peak_pci CAN driver. This patch enables now users of the PCAN-PCI Express OEM card to run the peak_pci driver too. Signed-off-by: Stephane Grosjean Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/peak_pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index e5fac368068a..131026fbc2d7 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -87,6 +87,7 @@ static const struct pci_device_id peak_pci_tbl[] = { {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PEAK_PCI_VENDOR_ID, PEAK_PCIE_OEM_ID, PCI_ANY_ID, PCI_ANY_ID,}, #ifdef CONFIG_CAN_PEAK_PCIEC {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, -- cgit v1.2.3 From f2a1c3680c1d9e2a1f9e68ce13f1130e587d28cf Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Tue, 7 Jul 2015 18:53:38 +0300 Subject: i40evf: missing rtnl_unlock in i40evf_resume() Signed-off-by: Vasily Averin Tested-by: Andrews Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 5fc820412fca..49fa71c69128 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2510,6 +2510,7 @@ static int i40evf_resume(struct pci_dev *pdev) rtnl_lock(); err = i40evf_set_interrupt_capability(adapter); if (err) { + rtnl_unlock(); dev_err(&pdev->dev, "Cannot enable MSI-X interrupts.\n"); return err; } -- cgit v1.2.3 From 4c4935a964e29da61390122f0a5c9f36e8ae081d Mon Sep 17 00:00:00 2001 From: Vasily Averin Date: Wed, 8 Jul 2015 15:04:26 +0300 Subject: i40e: rtnl_lock called twice in i40e_pci_error_resume() Signed-off-by: Vasily Averin Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 52e58f304b21..613da5143f7f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10537,7 +10537,7 @@ static void i40e_pci_error_resume(struct pci_dev *pdev) rtnl_lock(); i40e_handle_reset_warning(pf); - rtnl_lock(); + rtnl_unlock(); } /** -- cgit v1.2.3 From 1fa89a4b3b0b646ee9cb04eb890a3398eae0dc85 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 23 Jul 2015 16:54:30 -0400 Subject: i40e/i40evf: fix up type clash in i40e_aq_rc_to_posix conversion The error code sent into i40e_aq_rc_to_posix() are signed values, so we really need to treat them as such. Change-ID: I3d1ae0ee9ae0b1b6f5fc424f8b8cc58b0ea93203 Reported-by: Helin Zhang Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.h | 9 ++++++--- drivers/net/ethernet/intel/i40evf/i40e_adminq.h | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h index b67b34c35533..ca81b0b9db97 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h @@ -109,9 +109,10 @@ struct i40e_adminq_info { /** * i40e_aq_rc_to_posix - convert errors to user-land codes - * aq_rc: AdminQ error code to convert + * aq_ret: AdminQ handler error code can override aq_rc + * aq_rc: AdminQ firmware error code to convert **/ -static inline int i40e_aq_rc_to_posix(u32 aq_ret, u16 aq_rc) +static inline int i40e_aq_rc_to_posix(int aq_ret, int aq_rc) { int aq_to_posix[] = { 0, /* I40E_AQ_RC_OK */ @@ -143,8 +144,10 @@ static inline int i40e_aq_rc_to_posix(u32 aq_ret, u16 aq_rc) if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT) return -EAGAIN; - if (aq_rc >= ARRAY_SIZE(aq_to_posix)) + if (aq_rc >= (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0])) || + aq_rc < 0) return -ERANGE; + return aq_to_posix[aq_rc]; } diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h index 547b79b81ffe..e62e951cf208 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h @@ -109,9 +109,10 @@ struct i40e_adminq_info { /** * i40e_aq_rc_to_posix - convert errors to user-land codes - * aq_rc: AdminQ error code to convert + * aq_ret: AdminQ handler error code can override aq_rc + * aq_rc: AdminQ firmware error code to convert **/ -static inline int i40e_aq_rc_to_posix(u32 aq_ret, u16 aq_rc) +static inline int i40e_aq_rc_to_posix(int aq_ret, int aq_rc) { int aq_to_posix[] = { 0, /* I40E_AQ_RC_OK */ @@ -143,8 +144,10 @@ static inline int i40e_aq_rc_to_posix(u32 aq_ret, u16 aq_rc) if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT) return -EAGAIN; - if (aq_rc >= ARRAY_SIZE(aq_to_posix)) + if (aq_rc >= (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0])) || + aq_rc < 0) return -ERANGE; + return aq_to_posix[aq_rc]; } -- cgit v1.2.3 From d9b68f8aba0ae3f9ab6c5dec4ae1052b7e26c53c Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Thu, 23 Jul 2015 16:54:31 -0400 Subject: i40e: Fix a port VLAN configuration bug If a port VLAN is set for a given virtual function (VF) before the VF driver is loaded then a configuration error results in which the port VLAN is ignored when the VF driver is subsequently loaded. This causes the VF's MAC/VLAN filters to not use the correct VLAN filter. This patch ensures that the port VLAN filter is considered at the right time during configuration of the VF's MAC/VLAN filters. Change-ID: I28f404cbc21a4c6d70a7980b87c77f13f06685a4 Signed-off-by: Greg Rose Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 613da5143f7f..dce7d85116cf 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1269,7 +1269,7 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi) * so we have to go through all the list in order to make sure */ list_for_each_entry(f, &vsi->mac_filter_list, list) { - if (f->vlan >= 0) + if (f->vlan >= 0 || vsi->info.pvid) return true; } -- cgit v1.2.3 From 17351401fec6df1e6032054cd3c2ea03ad917a92 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 23 Jul 2015 16:54:32 -0400 Subject: i40e: fixup padding issue in get_cee_dcb_cfg_v1_resp The struct i40e_aqc_get_cee_dcb_cfg_v1_resp was originally defined with word boundary layout issues, which most compilers deal with by silently adding padding, making the actual struct larger than designed. This patch adds an extra byte in fields reserved3 and reserved4 to directly acknowledge that padding. Because the struct doesn't actually change in size or layout, this doesn't constitute a change in the API. Change-ID: I53fa4741b73fa255621232a85fba000b0e223015 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 95d23bfbcbf1..b840fabe3997 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -2074,6 +2074,15 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_start); #define I40E_AQC_CEE_ISCSI_STATUS_MASK (0x7 << I40E_AQC_CEE_ISCSI_STATUS_SHIFT) #define I40E_AQC_CEE_FIP_STATUS_SHIFT 0x10 #define I40E_AQC_CEE_FIP_STATUS_MASK (0x7 << I40E_AQC_CEE_FIP_STATUS_SHIFT) + +/* struct i40e_aqc_get_cee_dcb_cfg_v1_resp was originally defined with + * word boundary layout issues, which the Linux compilers silently deal + * with by adding padding, making the actual struct larger than designed. + * However, the FW compiler for the NIC is less lenient and complains + * about the struct. Hence, the struct defined here has an extra byte in + * fields reserved3 and reserved4 to directly acknowledge that padding, + * and the new length is used in the length check macro. + */ struct i40e_aqc_get_cee_dcb_cfg_v1_resp { u8 reserved1; u8 oper_num_tc; @@ -2081,9 +2090,9 @@ struct i40e_aqc_get_cee_dcb_cfg_v1_resp { u8 reserved2; u8 oper_tc_bw[8]; u8 oper_pfc_en; - u8 reserved3; + u8 reserved3[2]; __le16 oper_app_prio; - u8 reserved4; + u8 reserved4[2]; __le16 tlv_status; }; -- cgit v1.2.3 From 0deda86836e489fe43a33e8d899319bd0ed985a4 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 23 Jul 2015 16:54:34 -0400 Subject: i40e/i40evf: fix Tx hang workaround code The arm writeback (arm_wb) code is used for kicking the Tx ring to make sure any pending work is completed even if interrupts are disabled. It was running when it didn't need to, and not clearing the ring->arm_wb state after it was set. This caused Tx hangs to still occur occasionally when there really was no hang. Fix this by resetting the variable right after it was used. Change-ID: I7bf75d552ba9c4bd203d40615213861a24bb5594 Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 1 + drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 3ce4900c0c43..47dba9b0299b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1842,6 +1842,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) i40e_for_each_ring(ring, q_vector->tx) { clean_complete &= i40e_clean_tx_irq(ring, vsi->work_limit); arm_wb |= ring->arm_wb; + ring->arm_wb = false; } /* We attempt to distribute budget to each Rx queue fairly, but don't diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 830979380466..aaee89fd6526 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -254,8 +254,6 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) tx_ring->arm_wb = true; - else - tx_ring->arm_wb = false; netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index), @@ -1288,6 +1286,7 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget) i40e_for_each_ring(ring, q_vector->tx) { clean_complete &= i40e_clean_tx_irq(ring, vsi->work_limit); arm_wb |= ring->arm_wb; + ring->arm_wb = false; } /* We attempt to distribute budget to each Rx queue fairly, but don't -- cgit v1.2.3 From d8201e200a7474d391fd24ca811b0375e6694387 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 23 Jul 2015 16:54:35 -0400 Subject: i40e: count drops in netstat interface The i40e rx_dropped counter was not showing up in netstat -i. Add the right counter to be updated with the stats. Change-ID: I4dd552e9995836099184f9d9a08e90edb591155f Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index dce7d85116cf..3a3d49cebd92 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -474,6 +474,7 @@ static struct rtnl_link_stats64 *i40e_get_netdev_stats_struct( stats->tx_errors = vsi_stats->tx_errors; stats->tx_dropped = vsi_stats->tx_dropped; stats->rx_errors = vsi_stats->rx_errors; + stats->rx_dropped = vsi_stats->rx_dropped; stats->rx_crc_errors = vsi_stats->rx_crc_errors; stats->rx_length_errors = vsi_stats->rx_length_errors; -- cgit v1.2.3 From f7fc2f2eb11fe808df330df42a9429aa5b804388 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 23 Jul 2015 16:54:36 -0400 Subject: i40e: use QOS field consistently In i40e_ndo_set_vf_port_vlan, we were using the QOS value inconsistently, sometimes shifting it, sometimes not. Do the shift-and- or operation correctly, once, and use the result consistently everywhere in the function. Change-ID: I46f062f3edc90a8a017ecec9137f4d1ab0ab9e41 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index eacce9389962..b148694f8e11 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -2089,6 +2089,7 @@ error_param: int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos) { + u16 vlanprio = vlan_id | (qos << I40E_VLAN_PRIORITY_SHIFT); struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; struct i40e_vsi *vsi; @@ -2116,8 +2117,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, goto error_pvid; } - if (le16_to_cpu(vsi->info.pvid) == - (vlan_id | (qos << I40E_VLAN_PRIORITY_SHIFT))) + if (le16_to_cpu(vsi->info.pvid) == vlanprio) /* duplicate request, so just return success */ goto error_pvid; @@ -2141,7 +2141,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, * MAC addresses deleted. */ if ((!(vlan_id || qos) || - (vlan_id | qos) != le16_to_cpu(vsi->info.pvid)) && + vlanprio != le16_to_cpu(vsi->info.pvid)) && vsi->info.pvid) ret = i40e_vsi_add_vlan(vsi, I40E_VLAN_ANY); @@ -2156,8 +2156,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, } } if (vlan_id || qos) - ret = i40e_vsi_add_pvid(vsi, - vlan_id | (qos << I40E_VLAN_PRIORITY_SHIFT)); + ret = i40e_vsi_add_pvid(vsi, vlanprio); else i40e_vsi_remove_pvid(vsi); -- cgit v1.2.3 From 2ac8b675d9466b397f94aa1ead575d39b71b5055 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 23 Jul 2015 16:54:37 -0400 Subject: i40e: limit debugfs io ops Don't let the debugfs register read and write commands try to access outside of the ioremapped space. While we're at it, remove the use of a misleading constant. Change-ID: Ifce2893e232c65c7a76c23532c658f298218a81b Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 3 ++- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 12 ++++++------ drivers/net/ethernet/intel/i40e/i40e_main.c | 9 ++++----- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index c64d18d4cb2d..0044cb062f4f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -71,7 +71,6 @@ #define I40E_MAX_VEB 16 #define I40E_MAX_NUM_DESCRIPTORS 4096 -#define I40E_MAX_REGISTER 0x800000 #define I40E_MAX_CSR_SPACE (4 * 1024 * 1024 - 64 * 1024) #define I40E_DEFAULT_NUM_DESCRIPTORS 512 #define I40E_REQ_DESCRIPTOR_MULTIPLE 32 @@ -408,6 +407,8 @@ struct i40e_pf { /* These are only valid in NPAR modes */ u32 npar_max_bw; u32 npar_min_bw; + + u32 ioremap_len; }; struct i40e_mac_filter { diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 508efb034e87..ee96106d855e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1495,9 +1495,9 @@ static ssize_t i40e_dbg_command_write(struct file *filp, } /* check the range on address */ - if (address >= I40E_MAX_REGISTER) { - dev_info(&pf->pdev->dev, "read reg address 0x%08x too large\n", - address); + if (address > (pf->ioremap_len - sizeof(u32))) { + dev_info(&pf->pdev->dev, "read reg address 0x%08x too large, max=0x%08lx\n", + address, (pf->ioremap_len - sizeof(u32))); goto command_write_done; } @@ -1514,9 +1514,9 @@ static ssize_t i40e_dbg_command_write(struct file *filp, } /* check the range on address */ - if (address >= I40E_MAX_REGISTER) { - dev_info(&pf->pdev->dev, "write reg address 0x%08x too large\n", - address); + if (address > (pf->ioremap_len - sizeof(u32))) { + dev_info(&pf->pdev->dev, "write reg address 0x%08x too large, max=0x%08lx\n", + address, (pf->ioremap_len - sizeof(u32))); goto command_write_done; } wr32(&pf->hw, address, value); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 3a3d49cebd92..940744a7f936 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -9939,7 +9939,6 @@ static void i40e_print_features(struct i40e_pf *pf) static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct i40e_aq_get_phy_abilities_resp abilities; - unsigned long ioremap_len; struct i40e_pf *pf; struct i40e_hw *hw; static u16 pfs_found; @@ -9992,15 +9991,15 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw = &pf->hw; hw->back = pf; - ioremap_len = min_t(unsigned long, pci_resource_len(pdev, 0), - I40E_MAX_CSR_SPACE); + pf->ioremap_len = min_t(int, pci_resource_len(pdev, 0), + I40E_MAX_CSR_SPACE); - hw->hw_addr = ioremap(pci_resource_start(pdev, 0), ioremap_len); + hw->hw_addr = ioremap(pci_resource_start(pdev, 0), pf->ioremap_len); if (!hw->hw_addr) { err = -EIO; dev_info(&pdev->dev, "ioremap(0x%04x, 0x%04x) failed: 0x%x\n", (unsigned int)pci_resource_start(pdev, 0), - (unsigned int)pci_resource_len(pdev, 0), err); + pf->ioremap_len, err); goto err_ioremap; } hw->vendor_id = pdev->vendor; -- cgit v1.2.3 From 201991004da2c88e780ec58c93c960d0223c3687 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Thu, 23 Jul 2015 16:54:38 -0400 Subject: i40e: Remove useless message Remove a useless message that blathers on whenever a vxlan port is deleted. Change-ID: If63fb8cf38e56cf433b68e498f11389de51919ba Signed-off-by: Greg Rose Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 940744a7f936..032df6d0f454 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8175,9 +8175,6 @@ static void i40e_del_vxlan_port(struct net_device *netdev, pf->vxlan_ports[idx] = 0; pf->pending_vxlan_bitmap |= BIT_ULL(idx); pf->flags |= I40E_FLAG_VXLAN_FILTER_SYNC; - - dev_info(&pf->pdev->dev, "deleting vxlan port %d\n", - ntohs(port)); } else { netdev_warn(netdev, "vxlan port %d was not found, not deleting\n", ntohs(port)); -- cgit v1.2.3 From 48a3b512e8c0703884dd1b3afd85a295ecd36b5f Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 23 Jul 2015 16:54:39 -0400 Subject: i40e/i40evf: add new device id 1588 Add new device id and support for another 20Gb device. Change-ID: Ib1b61e5bb6201d84953f97cade39a6e3369c2cf2 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 2 ++ drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_common.c | 1 + drivers/net/ethernet/intel/i40evf/i40e_type.h | 1 + 6 files changed, 7 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 114dc6450183..80c354c6805d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -52,6 +52,7 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw) case I40E_DEV_ID_QSFP_C: case I40E_DEV_ID_10G_BASE_T: case I40E_DEV_ID_20G_KR2: + case I40E_DEV_ID_20G_KR2_A: hw->mac.type = I40E_MAC_XL710; break; case I40E_DEV_ID_SFP_X722: diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index e972b5ecbf0b..dd2b6208d91a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -437,6 +437,7 @@ static void i40e_get_settings_link_down(struct i40e_hw *hw, ecmd->advertising |= ADVERTISED_100baseT_Full; break; case I40E_DEV_ID_20G_KR2: + case I40E_DEV_ID_20G_KR2_A: /* backplane 20G */ ecmd->supported = SUPPORTED_20000baseKR2_Full; ecmd->advertising = ADVERTISED_20000baseKR2_Full; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 032df6d0f454..8952ab766992 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -79,6 +79,8 @@ static const struct pci_device_id i40e_pci_tbl[] = { {PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_1G_BASE_T_X722), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T_X722), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2_A), 0}, /* required last entry */ {0, } }; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index af4829065af6..c5b6a65f520f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -45,6 +45,7 @@ #define I40E_DEV_ID_QSFP_C 0x1585 #define I40E_DEV_ID_10G_BASE_T 0x1586 #define I40E_DEV_ID_20G_KR2 0x1587 +#define I40E_DEV_ID_20G_KR2_A 0x1588 #define I40E_DEV_ID_VF 0x154C #define I40E_DEV_ID_VF_HV 0x1571 #define I40E_DEV_ID_SFP_X722 0x37D0 diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c index d45d0ae6bd3b..1950db10a414 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_common.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c @@ -52,6 +52,7 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw) case I40E_DEV_ID_QSFP_C: case I40E_DEV_ID_10G_BASE_T: case I40E_DEV_ID_20G_KR2: + case I40E_DEV_ID_20G_KR2_A: hw->mac.type = I40E_MAC_XL710; break; case I40E_DEV_ID_SFP_X722: diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index ed7166693e5f..37bacc34fb84 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -45,6 +45,7 @@ #define I40E_DEV_ID_QSFP_C 0x1585 #define I40E_DEV_ID_10G_BASE_T 0x1586 #define I40E_DEV_ID_20G_KR2 0x1587 +#define I40E_DEV_ID_20G_KR2_A 0x1588 #define I40E_DEV_ID_VF 0x154C #define I40E_DEV_ID_VF_HV 0x1571 #define I40E_DEV_ID_SFP_X722 0x37D0 -- cgit v1.2.3 From d1a8d275340470b89fa3a3f7c47433caf1286336 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Thu, 23 Jul 2015 16:54:40 -0400 Subject: i40e: Strip VEB stats if they are disabled in HW Due to performance reasons, VEB stats have been disabled in the hw. This patch adds code to check for that condition before accumulating these stats. Change-ID: I7d805669476fedabb073790403703798ae5d878e Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 9 ++++++--- drivers/net/ethernet/intel/i40e/i40e_main.c | 13 +++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 0044cb062f4f..f6d97ad811bb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -325,6 +325,7 @@ struct i40e_pf { #define I40E_FLAG_OUTER_UDP_CSUM_CAPABLE BIT_ULL(33) #define I40E_FLAG_128_QP_RSS_CAPABLE BIT_ULL(34) #define I40E_FLAG_WB_ON_ITR_CAPABLE BIT_ULL(35) +#define I40E_FLAG_VEB_STATS_ENABLED BIT_ULL(37) #define I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE BIT_ULL(38) #define I40E_FLAG_VEB_MODE_ENABLED BIT_ULL(40) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index dd2b6208d91a..1345de2ef614 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1264,7 +1264,8 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset) if (vsi == pf->vsi[pf->lan_vsi] && pf->hw.partition_id == 1) { int len = I40E_PF_STATS_LEN(netdev); - if (pf->lan_veb != I40E_NO_VEB) + if ((pf->lan_veb != I40E_NO_VEB) && + (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)) len += I40E_VEB_STATS_TOTAL; return len; } else { @@ -1337,7 +1338,8 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id != 1) return; - if (pf->lan_veb != I40E_NO_VEB) { + if ((pf->lan_veb != I40E_NO_VEB) && + (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)) { struct i40e_veb *veb = pf->veb[pf->lan_veb]; for (j = 0; j < I40E_VEB_STATS_LEN; j++) { p = (char *)veb; @@ -1410,7 +1412,8 @@ static void i40e_get_strings(struct net_device *netdev, u32 stringset, if (vsi != pf->vsi[pf->lan_vsi] || pf->hw.partition_id != 1) return; - if (pf->lan_veb != I40E_NO_VEB) { + if ((pf->lan_veb != I40E_NO_VEB) && + (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)) { for (i = 0; i < I40E_VEB_STATS_LEN; i++) { snprintf(p, ETH_GSTRING_LEN, "veb.%s", i40e_gstrings_veb_stats[i].stat_string); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 8952ab766992..43e21bd0cec3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5907,10 +5907,12 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf) if (pf->vsi[i] && pf->vsi[i]->netdev) i40e_update_stats(pf->vsi[i]); - /* Update the stats for the active switching components */ - for (i = 0; i < I40E_MAX_VEB; i++) - if (pf->veb[i]) - i40e_update_veb_stats(pf->veb[i]); + if (pf->flags & I40E_FLAG_VEB_STATS_ENABLED) { + /* Update the stats for the active switching components */ + for (i = 0; i < I40E_MAX_VEB; i++) + if (pf->veb[i]) + i40e_update_veb_stats(pf->veb[i]); + } i40e_ptp_rx_hang(pf->vsi[pf->lan_vsi]); } @@ -7998,6 +8000,9 @@ static int i40e_sw_init(struct i40e_pf *pf) pf->lan_veb = I40E_NO_VEB; pf->lan_vsi = I40E_NO_VSI; + /* By default FW has this off for performance reasons */ + pf->flags &= ~I40E_FLAG_VEB_STATS_ENABLED; + /* set up queue assignment tracking */ size = sizeof(struct i40e_lump_tracking) + (sizeof(u16) * pf->hw.func_caps.num_tx_qp); -- cgit v1.2.3 From 7845548de7e4b49451f0eed77f690e579c428417 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 23 Jul 2015 16:54:41 -0400 Subject: i40e: refactor interrupt enable The interrupt enable function was always making the caller add the base_vector from the VSI struct which is already passed to the function. Just collapse the math into the helper function. Change-ID: I54ef33aa7ceebc3231c3cc48f7b39fd0c3ff5806 Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 10 ++++------ drivers/net/ethernet/intel/i40e/i40e_txrx.c | 6 ++---- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 43e21bd0cec3..c9a7dfa5e48d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3066,7 +3066,7 @@ void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf) /** * i40e_irq_dynamic_enable - Enable default interrupt generation settings * @vsi: pointer to a vsi - * @vector: enable a particular Hw Interrupt vector + * @vector: enable a particular Hw Interrupt vector, without base_vector **/ void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector) { @@ -3077,7 +3077,7 @@ void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector) val = I40E_PFINT_DYN_CTLN_INTENA_MASK | I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | (I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT); - wr32(hw, I40E_PFINT_DYN_CTLN(vector - 1), val); + wr32(hw, I40E_PFINT_DYN_CTLN(vector + vsi->base_vector - 1), val); /* skip the flush */ } @@ -3220,8 +3220,7 @@ static int i40e_vsi_enable_irq(struct i40e_vsi *vsi) int i; if (pf->flags & I40E_FLAG_MSIX_ENABLED) { - for (i = vsi->base_vector; - i < (vsi->num_q_vectors + vsi->base_vector); i++) + for (i = 0; i < vsi->num_q_vectors; i++) i40e_irq_dynamic_enable(vsi, i); } else { i40e_irq_dynamic_enable_icr0(pf); @@ -3453,8 +3452,7 @@ static bool i40e_clean_fdir_tx_irq(struct i40e_ring *tx_ring, int budget) tx_ring->next_to_clean = i; if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) { - i40e_irq_dynamic_enable(vsi, - tx_ring->q_vector->v_idx + vsi->base_vector); + i40e_irq_dynamic_enable(vsi, tx_ring->q_vector->v_idx); } return budget > 0; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 47dba9b0299b..5e1a7dcb3f57 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1783,8 +1783,7 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, if (!test_bit(__I40E_DOWN, &vsi->state)) wr32(hw, I40E_PFINT_DYN_CTLN(vector - 1), val); } else { - i40e_irq_dynamic_enable(vsi, - q_vector->v_idx + vsi->base_vector); + i40e_irq_dynamic_enable(vsi, q_vector->v_idx); } if (ITR_IS_DYNAMIC(vsi->tx_itr_setting)) { old_itr = q_vector->tx.itr; @@ -1806,8 +1805,7 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, wr32(hw, I40E_PFINT_DYN_CTLN(q_vector->v_idx + vsi->base_vector - 1), val); } else { - i40e_irq_dynamic_enable(vsi, - q_vector->v_idx + vsi->base_vector); + i40e_irq_dynamic_enable(vsi, q_vector->v_idx); } } -- cgit v1.2.3 From e908f81562b1367ac3ab3d156db3dcbbe07479f6 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 23 Jul 2015 16:54:42 -0400 Subject: i40e: warn on double free Down was requesting queue disables, but then exited immediately without waiting for the queues to actually disable. This could allow any function called after i40evf_down to run immediately, including i40evf_up, and causes a memory leak. This issue has been fixed in a recent refactor of the reset code, but add a couple WARN_ONs in the slow path to help us recognize if we reintroduce this issue or if we missed any cases. Change-ID: I27b6b5c9a79c1892f0ba453129f116bc32647dd0 Signed-off-by: Jesse Brandeburg Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 5e1a7dcb3f57..0d692ddfbc4f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -923,6 +923,8 @@ int i40e_setup_tx_descriptors(struct i40e_ring *tx_ring) if (!dev) return -ENOMEM; + /* warn if we are about to overwrite the pointer */ + WARN_ON(tx_ring->tx_bi); bi_size = sizeof(struct i40e_tx_buffer) * tx_ring->count; tx_ring->tx_bi = kzalloc(bi_size, GFP_KERNEL); if (!tx_ring->tx_bi) @@ -1083,6 +1085,8 @@ int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring) struct device *dev = rx_ring->dev; int bi_size; + /* warn if we are about to overwrite the pointer */ + WARN_ON(rx_ring->rx_bi); bi_size = sizeof(struct i40e_rx_buffer) * rx_ring->count; rx_ring->rx_bi = kzalloc(bi_size, GFP_KERNEL); if (!rx_ring->rx_bi) -- cgit v1.2.3 From 9b32b0b5dded7382c00595180bd5ce4f2f8c3d9b Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 13 Aug 2015 15:11:32 -0700 Subject: i40evf: tweak init timing This patch tweaks the init timing of the driver just a little bit to increase stability on load/unload and SR-IOV enable/disable cycles. First, run the init_task loop a little quicker in order to reduce overall init time. Second, stagger the start of the init task based on the device's PCIe function ID. This lessens the impact on the firmware when a whole bunch of VFs are initialized simultaneously, e.g. enabling SR-IOV without the VF driver blacklisted. For single VFs assigned to VMs this will have no effect as the function ID will always be 0. Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 49fa71c69128..76df6b2aa74a 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2300,8 +2300,7 @@ static void i40evf_init_task(struct work_struct *work) } return; restart: - schedule_delayed_work(&adapter->init_task, - msecs_to_jiffies(50)); + schedule_delayed_work(&adapter->init_task, msecs_to_jiffies(30)); return; err_register: @@ -2434,7 +2433,8 @@ static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) INIT_WORK(&adapter->adminq_task, i40evf_adminq_task); INIT_WORK(&adapter->watchdog_task, i40evf_watchdog_task); INIT_DELAYED_WORK(&adapter->init_task, i40evf_init_task); - schedule_delayed_work(&adapter->init_task, 10); + schedule_delayed_work(&adapter->init_task, + msecs_to_jiffies(5 * (pdev->devfn & 0x07))); return 0; -- cgit v1.2.3 From e88ae667ecccf104311ec1a34536bd1e8a0fe6f7 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 13 Aug 2015 18:54:26 -0700 Subject: i40e: fix kbuild warnings The 0day build infrastructure found some issues in i40e, this removes the warnings by adding a harmless cast to a dev_info. CC: kbuild-all@01.org Signed-off-by: Jesse Brandeburg Reported-by: kbuild test robot Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index ee96106d855e..9f9d8422096a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1497,7 +1497,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, /* check the range on address */ if (address > (pf->ioremap_len - sizeof(u32))) { dev_info(&pf->pdev->dev, "read reg address 0x%08x too large, max=0x%08lx\n", - address, (pf->ioremap_len - sizeof(u32))); + address, (unsigned long int)(pf->ioremap_len - sizeof(u32))); goto command_write_done; } @@ -1516,7 +1516,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, /* check the range on address */ if (address > (pf->ioremap_len - sizeof(u32))) { dev_info(&pf->pdev->dev, "write reg address 0x%08x too large, max=0x%08lx\n", - address, (pf->ioremap_len - sizeof(u32))); + address, (unsigned long int)(pf->ioremap_len - sizeof(u32))); goto command_write_done; } wr32(&pf->hw, address, value); -- cgit v1.2.3 From 9c70d7cebfec558e07a2ab0f2d5f5a80a821ecf5 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 13 Aug 2015 18:54:31 -0700 Subject: i40e: fix 32 bit build warnings Sparse found some issues with 32 bit compilation, which probably should at least work without warning. Not only that, but the code was wrong. Thanks sparse!! And thanks to the kbuild robot zero day testing for finding this issue. $ make ARCH=i386 M=drivers/net/ethernet/intel/i40e C=2 CF="-D__CHECK_ENDIAN__" CHECK drivers/net/ethernet/intel/i40e/i40e_main.c include/linux/etherdevice.h:79:32: warning: restricted __be16 degrades to integer drivers/net/ethernet/intel/i40e/i40e_main.c:7565:17: warning: shift too big (32) for type unsigned long drivers/net/ethernet/intel/i40e/i40e_main.c:7565:17: warning: shift too big (42) for type unsigned long drivers/net/ethernet/intel/i40e/i40e_main.c:7565:17: warning: shift too big (39) for type unsigned long drivers/net/ethernet/intel/i40e/i40e_main.c:7565:17: warning: shift too big (40) for type unsigned long CC: kbuild-all@01.org Signed-off-by: Jesse Brandeburg Reported-by: kbuild test robot Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 5 ----- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 12 ++++++------ 2 files changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 80c354c6805d..683371763293 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -442,9 +442,6 @@ static i40e_status i40e_aq_get_set_rss_lut(struct i40e_hw *hw, I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT) & I40E_AQC_SET_RSS_LUT_TABLE_TYPE_MASK)); - cmd_resp->addr_high = cpu_to_le32(high_16_bits((u64)lut)); - cmd_resp->addr_low = cpu_to_le32(lower_32_bits((u64)lut)); - status = i40e_asq_send_command(hw, &desc, lut, lut_size, NULL); return status; @@ -519,8 +516,6 @@ static i40e_status i40e_aq_get_set_rss_key(struct i40e_hw *hw, I40E_AQC_SET_RSS_KEY_VSI_ID_SHIFT) & I40E_AQC_SET_RSS_KEY_VSI_ID_MASK)); cmd_resp->vsi_id |= cpu_to_le16((u16)I40E_AQC_SET_RSS_KEY_VSI_VALID); - cmd_resp->addr_high = cpu_to_le32(high_16_bits((u64)key)); - cmd_resp->addr_low = cpu_to_le32(lower_32_bits((u64)key)); status = i40e_asq_send_command(hw, &desc, key, key_size, NULL); diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index a3978c2b5fc9..7c9975c983d9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -79,12 +79,12 @@ enum i40e_dyn_idx_t { BIT_ULL(I40E_FILTER_PCTYPE_L2_PAYLOAD)) #define I40E_DEFAULT_RSS_HENA_EXPANDED (I40E_DEFAULT_RSS_HENA | \ - BIT(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \ - BIT(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \ - BIT(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \ - BIT(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \ - BIT(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \ - BIT(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP)) + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \ + BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \ + BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \ + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \ + BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \ + BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP)) #define i40e_pf_get_default_rss_hena(pf) \ (((pf)->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) ? \ -- cgit v1.2.3 From ade1bdffe90e59cd257cb9bd4f5abe4de5f14911 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 28 Sep 2015 22:21:31 +0200 Subject: ntp/pps: use y2038 safe types in pps_event_time The pps_event_time uses two 'timespec' structures internally, which suffer from the y2038 problem. The uses of this structure are fairly self-contained in the pps code, so this replaces them all at once. Unfortunately, this includes the sfc ethernet driver aside from the pps subsystem, so we change that one as well. Both touch the same data structure, and there probably is no good way to split the patch into smaller units. Acked-by: Richard Cochran Acked-by: David S. Miller Reviewed-by: Thomas Gleixner Signed-off-by: Arnd Bergmann Signed-off-by: John Stultz --- drivers/net/ethernet/sfc/ptp.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index ad62615a93dc..fe849dbf9f80 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -646,28 +646,28 @@ static void efx_ptp_send_times(struct efx_nic *efx, struct pps_event_time *last_time) { struct pps_event_time now; - struct timespec limit; + struct timespec64 limit; struct efx_ptp_data *ptp = efx->ptp_data; - struct timespec start; + struct timespec64 start; int *mc_running = ptp->start.addr; pps_get_ts(&now); start = now.ts_real; limit = now.ts_real; - timespec_add_ns(&limit, SYNCHRONISE_PERIOD_NS); + timespec64_add_ns(&limit, SYNCHRONISE_PERIOD_NS); /* Write host time for specified period or until MC is done */ - while ((timespec_compare(&now.ts_real, &limit) < 0) && + while ((timespec64_compare(&now.ts_real, &limit) < 0) && ACCESS_ONCE(*mc_running)) { - struct timespec update_time; + struct timespec64 update_time; unsigned int host_time; /* Don't update continuously to avoid saturating the PCIe bus */ update_time = now.ts_real; - timespec_add_ns(&update_time, SYNCHRONISATION_GRANULARITY_NS); + timespec64_add_ns(&update_time, SYNCHRONISATION_GRANULARITY_NS); do { pps_get_ts(&now); - } while ((timespec_compare(&now.ts_real, &update_time) < 0) && + } while ((timespec64_compare(&now.ts_real, &update_time) < 0) && ACCESS_ONCE(*mc_running)); /* Synchronise NIC with single word of time only */ @@ -723,7 +723,7 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), struct efx_ptp_data *ptp = efx->ptp_data; u32 last_sec; u32 start_sec; - struct timespec delta; + struct timespec64 delta; ktime_t mc_time; if (number_readings == 0) -- cgit v1.2.3 From 090e2edb4171dae4872c4eaae972dd3ccf96d4a8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 28 Sep 2015 22:21:32 +0200 Subject: net: sfc: avoid using timespec The sfc driver internally uses a time format based on 32-bit (unsigned) seconds and 32-bit nanoseconds. This means it will overflow in 2106, but the value we pass into it is a signed 32-bit tv_sec that already overflows in 2038 to a negative value. This patch changes the logic to use the lower 32 bits of the timespec64 tv_sec in efx_ptp_ns_to_s_ns, which will have the correct value beyond the overflow. While this does not change any of the register values, it lets us keep using the driver after we deprecate the use of the timespec type in the kernel. In the efx_ptp_process_times function, the change to use timespec64 is similar, in that the tv_sec portion is ignored anyway and we only care about the nanosecond portion that remains unchanged. Acked-by: Richard Cochran Acked-by: David S. Miller Reviewed-by: Thomas Gleixner Signed-off-by: Arnd Bergmann Signed-off-by: John Stultz --- drivers/net/ethernet/sfc/ptp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index fe849dbf9f80..c771e0af4e06 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -401,8 +401,8 @@ size_t efx_ptp_update_stats(struct efx_nic *efx, u64 *stats) /* For Siena platforms NIC time is s and ns */ static void efx_ptp_ns_to_s_ns(s64 ns, u32 *nic_major, u32 *nic_minor) { - struct timespec ts = ns_to_timespec(ns); - *nic_major = ts.tv_sec; + struct timespec64 ts = ns_to_timespec64(ns); + *nic_major = (u32)ts.tv_sec; *nic_minor = ts.tv_nsec; } @@ -431,8 +431,8 @@ static ktime_t efx_ptp_s_ns_to_ktime_correction(u32 nic_major, u32 nic_minor, */ static void efx_ptp_ns_to_s27(s64 ns, u32 *nic_major, u32 *nic_minor) { - struct timespec ts = ns_to_timespec(ns); - u32 maj = ts.tv_sec; + struct timespec64 ts = ns_to_timespec64(ns); + u32 maj = (u32)ts.tv_sec; u32 min = (u32)(((u64)ts.tv_nsec * NS_TO_S27_MULT + (1ULL << (NS_TO_S27_SHIFT - 1))) >> NS_TO_S27_SHIFT); @@ -737,14 +737,14 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), */ for (i = 0; i < number_readings; i++) { s32 window, corrected; - struct timespec wait; + struct timespec64 wait; efx_ptp_read_timeset( MCDI_ARRAY_STRUCT_PTR(synch_buf, PTP_OUT_SYNCHRONIZE_TIMESET, i), &ptp->timeset[i]); - wait = ktime_to_timespec( + wait = ktime_to_timespec64( ptp->nic_to_kernel_time(0, ptp->timeset[i].wait, 0)); window = ptp->timeset[i].window; corrected = window - wait.tv_nsec; @@ -803,7 +803,7 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf), ptp->timeset[last_good].minor, 0); /* Calculate delay from NIC top of second to last_time */ - delta.tv_nsec += ktime_to_timespec(mc_time).tv_nsec; + delta.tv_nsec += ktime_to_timespec64(mc_time).tv_nsec; /* Set PPS timestamp to match NIC top of second */ ptp->host_time_pps = *last_time; -- cgit v1.2.3 From 54328e64047a54b8fc2362c2e1f0fa16c90f739f Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 2 Oct 2015 11:44:30 -0500 Subject: rtlwifi: rtl8821ae: Fix system lockups on boot In commit 1277fa2ab2f9 ("rtlwifi: Remove the clear interrupt routine from all drivers"), the code that cleared all interrupt enable bits before setting them was removed for all PCI drivers. This fixed an issue that caused TX to be blocked for 3-5 seconds. On some RTL8821AE units, this change causes soft lockups to occur on boot. For that reason, the portion of the earlier commit that applied to rtl8821ae is reverted. Kernels 4.1 and newer are affected. See http://marc.info/?l=linux-wireless&m=144373370103285&w=2 and https://bugzilla.opensuse.org/show_bug.cgi?id=944978 for two cases where this regression affected user systems. Note that this bug does not appear on any of the developer's setups. For those users whose systems are affected by the TX blockage, but do not lock up on boot, a module parameter is added to disable the interrupt clear Fixes: 1277fa2ab2f9 ("rtlwifi: Remove the clear interrupt routine from all drivers") Signed-off-by: Larry Finger Cc: Stable [V4.1+] Signed-off-by: Kalle Valo --- drivers/net/wireless/rtlwifi/pci.h | 2 ++ drivers/net/wireless/rtlwifi/rtl8821ae/hw.c | 17 +++++++++++++++++ drivers/net/wireless/rtlwifi/rtl8821ae/sw.c | 5 +++++ drivers/net/wireless/rtlwifi/wifi.h | 3 +++ 4 files changed, 27 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index d4567d12e07e..5da6703942d9 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h @@ -247,6 +247,8 @@ struct rtl_pci { /* MSI support */ bool msi_support; bool using_msi; + /* interrupt clear before set */ + bool int_clear; }; struct mp_adapter { diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c index b7f18e2155eb..6e9418ed90c2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c @@ -2253,11 +2253,28 @@ void rtl8821ae_set_qos(struct ieee80211_hw *hw, int aci) } } +static void rtl8821ae_clear_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 tmp = rtl_read_dword(rtlpriv, REG_HISR); + + rtl_write_dword(rtlpriv, REG_HISR, tmp); + + tmp = rtl_read_dword(rtlpriv, REG_HISRE); + rtl_write_dword(rtlpriv, REG_HISRE, tmp); + + tmp = rtl_read_dword(rtlpriv, REG_HSISR); + rtl_write_dword(rtlpriv, REG_HSISR, tmp); +} + void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + if (!rtlpci->int_clear) + rtl8821ae_clear_interrupt(hw);/*clear it here first*/ + rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); rtlpci->irq_enabled = true; diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c index a4988121e1ab..8ee141a55bc5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c @@ -96,6 +96,7 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw) rtl8821ae_bt_reg_init(hw); rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; + rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear; rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); rtlpriv->dm.dm_initialgain_enable = 1; @@ -167,6 +168,7 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; + rtlpci->msi_support = rtlpriv->cfg->mod_params->int_clear; if (rtlpriv->cfg->mod_params->disable_watchdog) pr_info("watchdog disabled\n"); rtlpriv->psc.reg_fwctrl_lps = 3; @@ -308,6 +310,7 @@ static struct rtl_mod_params rtl8821ae_mod_params = { .swctrl_lps = false, .fwctrl_lps = true, .msi_support = true, + .int_clear = true, .debug = DBG_EMERG, .disable_watchdog = 0, }; @@ -437,6 +440,7 @@ module_param_named(fwlps, rtl8821ae_mod_params.fwctrl_lps, bool, 0444); module_param_named(msi, rtl8821ae_mod_params.msi_support, bool, 0444); module_param_named(disable_watchdog, rtl8821ae_mod_params.disable_watchdog, bool, 0444); +module_param_named(int_clear, rtl8821ae_mod_params.int_clear, bool, 0444); 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"); @@ -444,6 +448,7 @@ 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(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n"); +MODULE_PARM_DESC(int_clear, "Set to 1 to disable interrupt clear before set (default 0)\n"); static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index b90ca618b123..4544752a2ba8 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -2249,6 +2249,9 @@ struct rtl_mod_params { /* default 0: 1 means disable */ bool disable_watchdog; + + /* default 0: 1 means do not disable interrupts */ + bool int_clear; }; struct rtl_hal_usbint_cfg { -- cgit v1.2.3 From 57d80838dae55c1bc6ca629e471c84100513079a Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Oct 2015 11:03:41 +0200 Subject: switchdev: rename SWITCHDEV_OBJ_* enum values to SWITCHDEV_OBJ_ID_* Suggested-by: Vivien Didelot Signed-off-by: Jiri Pirko Acked-by: Scott Feldman Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 9773f5b65296..9b2e8bed8f83 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4445,16 +4445,16 @@ static int rocker_port_obj_add(struct net_device *dev, int err = 0; switch (id) { - case SWITCHDEV_OBJ_PORT_VLAN: + case SWITCHDEV_OBJ_ID_PORT_VLAN: err = rocker_port_vlans_add(rocker_port, trans, obj); break; - case SWITCHDEV_OBJ_IPV4_FIB: + case SWITCHDEV_OBJ_ID_IPV4_FIB: fib4 = obj; err = rocker_port_fib_ipv4(rocker_port, trans, htonl(fib4->dst), fib4->dst_len, fib4->fi, fib4->tb_id, 0); break; - case SWITCHDEV_OBJ_PORT_FDB: + case SWITCHDEV_OBJ_ID_PORT_FDB: err = rocker_port_fdb_add(rocker_port, trans, obj); break; default: @@ -4515,17 +4515,17 @@ static int rocker_port_obj_del(struct net_device *dev, int err = 0; switch (id) { - case SWITCHDEV_OBJ_PORT_VLAN: + case SWITCHDEV_OBJ_ID_PORT_VLAN: err = rocker_port_vlans_del(rocker_port, obj); break; - case SWITCHDEV_OBJ_IPV4_FIB: + case SWITCHDEV_OBJ_ID_IPV4_FIB: fib4 = obj; err = rocker_port_fib_ipv4(rocker_port, NULL, htonl(fib4->dst), fib4->dst_len, fib4->fi, fib4->tb_id, ROCKER_OP_FLAG_REMOVE); break; - case SWITCHDEV_OBJ_PORT_FDB: + case SWITCHDEV_OBJ_ID_PORT_FDB: err = rocker_port_fdb_del(rocker_port, NULL, obj); break; default: @@ -4594,10 +4594,10 @@ static int rocker_port_obj_dump(struct net_device *dev, int err = 0; switch (id) { - case SWITCHDEV_OBJ_PORT_FDB: + case SWITCHDEV_OBJ_ID_PORT_FDB: err = rocker_port_fdb_dump(rocker_port, obj, cb); break; - case SWITCHDEV_OBJ_PORT_VLAN: + case SWITCHDEV_OBJ_ID_PORT_VLAN: err = rocker_port_vlan_dump(rocker_port, obj, cb); break; default: -- cgit v1.2.3 From 1f86839874a50c9ee2009567d2f312b1e1949e24 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Oct 2015 11:03:42 +0200 Subject: switchdev: rename SWITCHDEV_ATTR_* enum values to SWITCHDEV_ATTR_ID_* To be aligned with obj. Signed-off-by: Jiri Pirko Acked-by: Scott Feldman Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 2 +- drivers/net/ethernet/rocker/rocker.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 3e52ee93438c..d448431bbc83 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -868,7 +868,7 @@ static int mlxsw_sx_port_attr_get(struct net_device *dev, struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; switch (attr->id) { - case SWITCHDEV_ATTR_PORT_PARENT_ID: + case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: attr->u.ppid.id_len = sizeof(mlxsw_sx->hw_id); memcpy(&attr->u.ppid.id, &mlxsw_sx->hw_id, attr->u.ppid.id_len); break; diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 9b2e8bed8f83..4540ca63a434 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4329,11 +4329,11 @@ static int rocker_port_attr_get(struct net_device *dev, const struct rocker *rocker = rocker_port->rocker; switch (attr->id) { - case SWITCHDEV_ATTR_PORT_PARENT_ID: + case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: attr->u.ppid.id_len = sizeof(rocker->hw.id); memcpy(&attr->u.ppid.id, &rocker->hw.id, attr->u.ppid.id_len); break; - case SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS: + case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: attr->u.brport_flags = rocker_port->brport_flags; break; default: @@ -4369,12 +4369,12 @@ static int rocker_port_attr_set(struct net_device *dev, int err = 0; switch (attr->id) { - case SWITCHDEV_ATTR_PORT_STP_STATE: + case SWITCHDEV_ATTR_ID_PORT_STP_STATE: err = rocker_port_stp_update(rocker_port, trans, ROCKER_OP_FLAG_NOWAIT, attr->u.stp_state); break; - case SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS: + case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: err = rocker_port_brport_flags_set(rocker_port, trans, attr->u.brport_flags); break; -- cgit v1.2.3 From 8f24f3095dcedaa4eb4719eee2bed738fe2ce4a0 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Oct 2015 11:03:43 +0200 Subject: switchdev: rename switchdev_obj_vlan to switchdev_obj_port_vlan Make the struct name in sync with object id name. Suggested-by: Vivien Didelot Signed-off-by: Jiri Pirko Acked-by: Scott Feldman Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 4540ca63a434..d75fc4b3baa9 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4408,7 +4408,7 @@ static int rocker_port_vlan_add(struct rocker_port *rocker_port, static int rocker_port_vlans_add(struct rocker_port *rocker_port, struct switchdev_trans *trans, - const struct switchdev_obj_vlan *vlan) + const struct switchdev_obj_port_vlan *vlan) { u16 vid; int err; @@ -4480,7 +4480,7 @@ static int rocker_port_vlan_del(struct rocker_port *rocker_port, } static int rocker_port_vlans_del(struct rocker_port *rocker_port, - const struct switchdev_obj_vlan *vlan) + const struct switchdev_obj_port_vlan *vlan) { u16 vid; int err; @@ -4565,7 +4565,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, } static int rocker_port_vlan_dump(const struct rocker_port *rocker_port, - struct switchdev_obj_vlan *vlan, + struct switchdev_obj_port_vlan *vlan, int (*cb)(void *obj)) { u16 vid; -- cgit v1.2.3 From 52ba57cfdc4c90da3bf996dfbe0c5feb731eb477 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Oct 2015 11:03:44 +0200 Subject: switchdev: rename switchdev_obj_fdb to switchdev_obj_port_fdb Make the struct name in sync with object id name. Suggested-by: Vivien Didelot Signed-off-by: Jiri Pirko Acked-by: Scott Feldman Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index d75fc4b3baa9..875f9b5b78a2 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4425,7 +4425,7 @@ static int rocker_port_vlans_add(struct rocker_port *rocker_port, static int rocker_port_fdb_add(struct rocker_port *rocker_port, struct switchdev_trans *trans, - const struct switchdev_obj_fdb *fdb) + const struct switchdev_obj_port_fdb *fdb) { __be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL); int flags = 0; @@ -4496,7 +4496,7 @@ static int rocker_port_vlans_del(struct rocker_port *rocker_port, static int rocker_port_fdb_del(struct rocker_port *rocker_port, struct switchdev_trans *trans, - const struct switchdev_obj_fdb *fdb) + const struct switchdev_obj_port_fdb *fdb) { __be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL); int flags = ROCKER_OP_FLAG_NOWAIT | ROCKER_OP_FLAG_REMOVE; @@ -4537,7 +4537,7 @@ static int rocker_port_obj_del(struct net_device *dev, } static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, - struct switchdev_obj_fdb *fdb, + struct switchdev_obj_port_fdb *fdb, int (*cb)(void *obj)) { struct rocker *rocker = rocker_port->rocker; -- cgit v1.2.3 From 648b4a995a057187ddd77cdb181e6a0b24ab2959 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Oct 2015 11:03:45 +0200 Subject: switchdev: bring back switchdev_obj and use it as a generic object param Replace "void *obj" with a generic structure. Introduce couple of helpers along that. Signed-off-by: Jiri Pirko Acked-by: Scott Feldman Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 41 ++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 875f9b5b78a2..2a577e5b8ca5 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4437,7 +4437,8 @@ static int rocker_port_fdb_add(struct rocker_port *rocker_port, } static int rocker_port_obj_add(struct net_device *dev, - enum switchdev_obj_id id, const void *obj, + enum switchdev_obj_id id, + const struct switchdev_obj *obj, struct switchdev_trans *trans) { struct rocker_port *rocker_port = netdev_priv(dev); @@ -4446,16 +4447,18 @@ static int rocker_port_obj_add(struct net_device *dev, switch (id) { case SWITCHDEV_OBJ_ID_PORT_VLAN: - err = rocker_port_vlans_add(rocker_port, trans, obj); + err = rocker_port_vlans_add(rocker_port, trans, + SWITCHDEV_OBJ_PORT_VLAN(obj)); break; case SWITCHDEV_OBJ_ID_IPV4_FIB: - fib4 = obj; + fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj); err = rocker_port_fib_ipv4(rocker_port, trans, htonl(fib4->dst), fib4->dst_len, fib4->fi, fib4->tb_id, 0); break; case SWITCHDEV_OBJ_ID_PORT_FDB: - err = rocker_port_fdb_add(rocker_port, trans, obj); + err = rocker_port_fdb_add(rocker_port, trans, + SWITCHDEV_OBJ_PORT_FDB(obj)); break; default: err = -EOPNOTSUPP; @@ -4508,7 +4511,8 @@ static int rocker_port_fdb_del(struct rocker_port *rocker_port, } static int rocker_port_obj_del(struct net_device *dev, - enum switchdev_obj_id id, const void *obj) + enum switchdev_obj_id id, + const struct switchdev_obj *obj) { struct rocker_port *rocker_port = netdev_priv(dev); const struct switchdev_obj_ipv4_fib *fib4; @@ -4516,17 +4520,19 @@ static int rocker_port_obj_del(struct net_device *dev, switch (id) { case SWITCHDEV_OBJ_ID_PORT_VLAN: - err = rocker_port_vlans_del(rocker_port, obj); + err = rocker_port_vlans_del(rocker_port, + SWITCHDEV_OBJ_PORT_VLAN(obj)); break; case SWITCHDEV_OBJ_ID_IPV4_FIB: - fib4 = obj; + fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj); err = rocker_port_fib_ipv4(rocker_port, NULL, htonl(fib4->dst), fib4->dst_len, fib4->fi, fib4->tb_id, ROCKER_OP_FLAG_REMOVE); break; case SWITCHDEV_OBJ_ID_PORT_FDB: - err = rocker_port_fdb_del(rocker_port, NULL, obj); + err = rocker_port_fdb_del(rocker_port, NULL, + SWITCHDEV_OBJ_PORT_FDB(obj)); break; default: err = -EOPNOTSUPP; @@ -4538,7 +4544,7 @@ static int rocker_port_obj_del(struct net_device *dev, static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, struct switchdev_obj_port_fdb *fdb, - int (*cb)(void *obj)) + switchdev_obj_dump_cb_t *cb) { struct rocker *rocker = rocker_port->rocker; struct rocker_fdb_tbl_entry *found; @@ -4555,7 +4561,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, fdb->ndm_state = NUD_REACHABLE; fdb->vid = rocker_port_vlan_to_vid(rocker_port, found->key.vlan_id); - err = cb(fdb); + err = cb(&fdb->obj); if (err) break; } @@ -4566,7 +4572,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, static int rocker_port_vlan_dump(const struct rocker_port *rocker_port, struct switchdev_obj_port_vlan *vlan, - int (*cb)(void *obj)) + switchdev_obj_dump_cb_t *cb) { u16 vid; int err = 0; @@ -4578,7 +4584,7 @@ static int rocker_port_vlan_dump(const struct rocker_port *rocker_port, if (rocker_vlan_id_is_internal(htons(vid))) vlan->flags |= BRIDGE_VLAN_INFO_PVID; vlan->vid_begin = vlan->vid_end = vid; - err = cb(vlan); + err = cb(&vlan->obj); if (err) break; } @@ -4587,18 +4593,21 @@ static int rocker_port_vlan_dump(const struct rocker_port *rocker_port, } static int rocker_port_obj_dump(struct net_device *dev, - enum switchdev_obj_id id, void *obj, - int (*cb)(void *obj)) + enum switchdev_obj_id id, + struct switchdev_obj *obj, + switchdev_obj_dump_cb_t *cb) { const struct rocker_port *rocker_port = netdev_priv(dev); int err = 0; switch (id) { case SWITCHDEV_OBJ_ID_PORT_FDB: - err = rocker_port_fdb_dump(rocker_port, obj, cb); + err = rocker_port_fdb_dump(rocker_port, + SWITCHDEV_OBJ_PORT_FDB(obj), cb); break; case SWITCHDEV_OBJ_ID_PORT_VLAN: - err = rocker_port_vlan_dump(rocker_port, obj, cb); + err = rocker_port_vlan_dump(rocker_port, + SWITCHDEV_OBJ_PORT_VLAN(obj), cb); break; default: err = -EOPNOTSUPP; -- cgit v1.2.3 From 9e8f4a548ab4710002c23c94c4b1bbde91b5e335 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 1 Oct 2015 11:03:46 +0200 Subject: switchdev: push object ID back to object structure Suggested-by: Scott Feldman Signed-off-by: Jiri Pirko Acked-by: Scott Feldman Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 2a577e5b8ca5..cf91ffc6c987 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4437,7 +4437,6 @@ static int rocker_port_fdb_add(struct rocker_port *rocker_port, } static int rocker_port_obj_add(struct net_device *dev, - enum switchdev_obj_id id, const struct switchdev_obj *obj, struct switchdev_trans *trans) { @@ -4445,7 +4444,7 @@ static int rocker_port_obj_add(struct net_device *dev, const struct switchdev_obj_ipv4_fib *fib4; int err = 0; - switch (id) { + switch (obj->id) { case SWITCHDEV_OBJ_ID_PORT_VLAN: err = rocker_port_vlans_add(rocker_port, trans, SWITCHDEV_OBJ_PORT_VLAN(obj)); @@ -4511,14 +4510,13 @@ static int rocker_port_fdb_del(struct rocker_port *rocker_port, } static int rocker_port_obj_del(struct net_device *dev, - enum switchdev_obj_id id, const struct switchdev_obj *obj) { struct rocker_port *rocker_port = netdev_priv(dev); const struct switchdev_obj_ipv4_fib *fib4; int err = 0; - switch (id) { + switch (obj->id) { case SWITCHDEV_OBJ_ID_PORT_VLAN: err = rocker_port_vlans_del(rocker_port, SWITCHDEV_OBJ_PORT_VLAN(obj)); @@ -4593,14 +4591,13 @@ static int rocker_port_vlan_dump(const struct rocker_port *rocker_port, } static int rocker_port_obj_dump(struct net_device *dev, - enum switchdev_obj_id id, struct switchdev_obj *obj, switchdev_obj_dump_cb_t *cb) { const struct rocker_port *rocker_port = netdev_priv(dev); int err = 0; - switch (id) { + switch (obj->id) { case SWITCHDEV_OBJ_ID_PORT_FDB: err = rocker_port_fdb_dump(rocker_port, SWITCHDEV_OBJ_PORT_FDB(obj), cb); -- cgit v1.2.3 From f3a6bd393c2c5d0e6b16624ba99a1c5fa07bdb0b Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 30 Sep 2015 15:15:52 +0900 Subject: phylib: Add phy_set_max_speed helper Add a helper to allow ethernet drivers to limit the speed of a phy (that they are attached to). This mainly involves factoring out the business-end of of_set_phy_supported() and exporting a new symbol. This code seems to be open coded in several places, in several different variants. It is is envisaged that this will be used in situations where setting the "max-speed" property in DT is not appropriate, e.g. because the maximum speed is not a property of the phy hardware. Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 59 ++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index f761288abe66..383389146099 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1239,6 +1239,44 @@ static int gen10g_resume(struct phy_device *phydev) return 0; } +static int __set_phy_supported(struct phy_device *phydev, u32 max_speed) +{ + /* The default values for phydev->supported are provided by the PHY + * driver "features" member, we want to reset to sane defaults first + * before supporting higher speeds. + */ + phydev->supported &= PHY_DEFAULT_FEATURES; + + switch (max_speed) { + default: + return -ENOTSUPP; + case SPEED_1000: + phydev->supported |= PHY_1000BT_FEATURES; + /* fall through */ + case SPEED_100: + phydev->supported |= PHY_100BT_FEATURES; + /* fall through */ + case SPEED_10: + phydev->supported |= PHY_10BT_FEATURES; + } + + return 0; +} + +int phy_set_max_speed(struct phy_device *phydev, u32 max_speed) +{ + int err; + + err = __set_phy_supported(phydev, max_speed); + if (err) + return err; + + phydev->advertising = phydev->supported; + + return 0; +} +EXPORT_SYMBOL(phy_set_max_speed); + static void of_set_phy_supported(struct phy_device *phydev) { struct device_node *node = phydev->dev.of_node; @@ -1250,25 +1288,8 @@ static void of_set_phy_supported(struct phy_device *phydev) if (!node) return; - if (!of_property_read_u32(node, "max-speed", &max_speed)) { - /* The default values for phydev->supported are provided by the PHY - * driver "features" member, we want to reset to sane defaults fist - * before supporting higher speeds. - */ - phydev->supported &= PHY_DEFAULT_FEATURES; - - switch (max_speed) { - default: - return; - - case SPEED_1000: - phydev->supported |= PHY_1000BT_FEATURES; - case SPEED_100: - phydev->supported |= PHY_100BT_FEATURES; - case SPEED_10: - phydev->supported |= PHY_10BT_FEATURES; - } - } + if (!of_property_read_u32(node, "max-speed", &max_speed)) + __set_phy_supported(phydev, max_speed); } /** -- cgit v1.2.3 From e2dbb33ad9545de6859747b92556a74a81bed8f5 Mon Sep 17 00:00:00 2001 From: Kazuya Mizuguchi Date: Wed, 30 Sep 2015 15:15:53 +0900 Subject: ravb: Provide dev parameter to DMA API This patch is in preparation for using this driver on arm64 where the implementation of __dma_alloc_coherent fails if a device parameter is not provided. Signed-off-by: Kazuya Mizuguchi Signed-off-by: Yoshihiro Shimoda Signed-off-by: Masaru Nagai [horms: squashed into a single patch] Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb_main.c | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 450899e9cea2..4ca093d033f8 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -201,7 +201,7 @@ static void ravb_ring_free(struct net_device *ndev, int q) if (priv->rx_ring[q]) { ring_size = sizeof(struct ravb_ex_rx_desc) * (priv->num_rx_ring[q] + 1); - dma_free_coherent(NULL, ring_size, priv->rx_ring[q], + dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q], priv->rx_desc_dma[q]); priv->rx_ring[q] = NULL; } @@ -209,7 +209,7 @@ static void ravb_ring_free(struct net_device *ndev, int q) if (priv->tx_ring[q]) { ring_size = sizeof(struct ravb_tx_desc) * (priv->num_tx_ring[q] * NUM_TX_DESC + 1); - dma_free_coherent(NULL, ring_size, priv->tx_ring[q], + dma_free_coherent(ndev->dev.parent, ring_size, priv->tx_ring[q], priv->tx_desc_dma[q]); priv->tx_ring[q] = NULL; } @@ -240,13 +240,13 @@ static void ravb_ring_format(struct net_device *ndev, int q) rx_desc = &priv->rx_ring[q][i]; /* The size of the buffer should be on 16-byte boundary. */ rx_desc->ds_cc = cpu_to_le16(ALIGN(PKT_BUF_SZ, 16)); - dma_addr = dma_map_single(&ndev->dev, priv->rx_skb[q][i]->data, + dma_addr = dma_map_single(ndev->dev.parent, priv->rx_skb[q][i]->data, ALIGN(PKT_BUF_SZ, 16), DMA_FROM_DEVICE); /* We just set the data size to 0 for a failed mapping which * should prevent DMA from happening... */ - if (dma_mapping_error(&ndev->dev, dma_addr)) + if (dma_mapping_error(ndev->dev.parent, dma_addr)) rx_desc->ds_cc = cpu_to_le16(0); rx_desc->dptr = cpu_to_le32(dma_addr); rx_desc->die_dt = DT_FEMPTY; @@ -309,7 +309,7 @@ static int ravb_ring_init(struct net_device *ndev, int q) /* Allocate all RX descriptors. */ ring_size = sizeof(struct ravb_ex_rx_desc) * (priv->num_rx_ring[q] + 1); - priv->rx_ring[q] = dma_alloc_coherent(NULL, ring_size, + priv->rx_ring[q] = dma_alloc_coherent(ndev->dev.parent, ring_size, &priv->rx_desc_dma[q], GFP_KERNEL); if (!priv->rx_ring[q]) @@ -320,7 +320,7 @@ static int ravb_ring_init(struct net_device *ndev, int q) /* Allocate all TX descriptors. */ ring_size = sizeof(struct ravb_tx_desc) * (priv->num_tx_ring[q] * NUM_TX_DESC + 1); - priv->tx_ring[q] = dma_alloc_coherent(NULL, ring_size, + priv->tx_ring[q] = dma_alloc_coherent(ndev->dev.parent, ring_size, &priv->tx_desc_dma[q], GFP_KERNEL); if (!priv->tx_ring[q]) @@ -443,7 +443,7 @@ static int ravb_tx_free(struct net_device *ndev, int q) size = le16_to_cpu(desc->ds_tagl) & TX_DS; /* Free the original skb. */ if (priv->tx_skb[q][entry / NUM_TX_DESC]) { - dma_unmap_single(&ndev->dev, le32_to_cpu(desc->dptr), + dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr), size, DMA_TO_DEVICE); /* Last packet descriptor? */ if (entry % NUM_TX_DESC == NUM_TX_DESC - 1) { @@ -546,7 +546,7 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q) skb = priv->rx_skb[q][entry]; priv->rx_skb[q][entry] = NULL; - dma_unmap_single(&ndev->dev, le32_to_cpu(desc->dptr), + dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr), ALIGN(PKT_BUF_SZ, 16), DMA_FROM_DEVICE); get_ts &= (q == RAVB_NC) ? @@ -586,14 +586,14 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q) if (!skb) break; /* Better luck next round. */ ravb_set_buffer_align(skb); - dma_addr = dma_map_single(&ndev->dev, skb->data, + dma_addr = dma_map_single(ndev->dev.parent, skb->data, le16_to_cpu(desc->ds_cc), DMA_FROM_DEVICE); skb_checksum_none_assert(skb); /* We just set the data size to 0 for a failed mapping * which should prevent DMA from happening... */ - if (dma_mapping_error(&ndev->dev, dma_addr)) + if (dma_mapping_error(ndev->dev.parent, dma_addr)) desc->ds_cc = cpu_to_le16(0); desc->dptr = cpu_to_le32(dma_addr); priv->rx_skb[q][entry] = skb; @@ -1300,8 +1300,8 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) entry / NUM_TX_DESC * DPTR_ALIGN; len = PTR_ALIGN(skb->data, DPTR_ALIGN) - skb->data; memcpy(buffer, skb->data, len); - dma_addr = dma_map_single(&ndev->dev, buffer, len, DMA_TO_DEVICE); - if (dma_mapping_error(&ndev->dev, dma_addr)) + dma_addr = dma_map_single(ndev->dev.parent, buffer, len, DMA_TO_DEVICE); + if (dma_mapping_error(ndev->dev.parent, dma_addr)) goto drop; desc = &priv->tx_ring[q][entry]; @@ -1310,8 +1310,8 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) buffer = skb->data + len; len = skb->len - len; - dma_addr = dma_map_single(&ndev->dev, buffer, len, DMA_TO_DEVICE); - if (dma_mapping_error(&ndev->dev, dma_addr)) + dma_addr = dma_map_single(ndev->dev.parent, buffer, len, DMA_TO_DEVICE); + if (dma_mapping_error(ndev->dev.parent, dma_addr)) goto unmap; desc++; @@ -1323,7 +1323,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) ts_skb = kmalloc(sizeof(*ts_skb), GFP_ATOMIC); if (!ts_skb) { desc--; - dma_unmap_single(&ndev->dev, dma_addr, len, + dma_unmap_single(ndev->dev.parent, dma_addr, len, DMA_TO_DEVICE); goto unmap; } @@ -1358,7 +1358,7 @@ exit: return NETDEV_TX_OK; unmap: - dma_unmap_single(&ndev->dev, le32_to_cpu(desc->dptr), + dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr), le16_to_cpu(desc->ds_tagl), DMA_TO_DEVICE); drop: dev_kfree_skb_any(skb); @@ -1708,7 +1708,7 @@ static int ravb_probe(struct platform_device *pdev) /* Allocate descriptor base address table */ priv->desc_bat_size = sizeof(struct ravb_desc) * DBAT_ENTRY_NUM; - priv->desc_bat = dma_alloc_coherent(NULL, priv->desc_bat_size, + priv->desc_bat = dma_alloc_coherent(ndev->dev.parent, priv->desc_bat_size, &priv->desc_bat_dma, GFP_KERNEL); if (!priv->desc_bat) { dev_err(&ndev->dev, @@ -1763,7 +1763,7 @@ out_napi_del: netif_napi_del(&priv->napi[RAVB_BE]); ravb_mdio_release(priv); out_dma_free: - dma_free_coherent(NULL, priv->desc_bat_size, priv->desc_bat, + dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, priv->desc_bat_dma); out_release: if (ndev) @@ -1779,7 +1779,7 @@ static int ravb_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct ravb_private *priv = netdev_priv(ndev); - dma_free_coherent(NULL, priv->desc_bat_size, priv->desc_bat, + dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, priv->desc_bat_dma); /* Set reset mode */ ravb_write(ndev, CCC_OPC_RESET, CCC); -- cgit v1.2.3 From 22d4df8ff3a3cc7251671d129a7185c66a929ddc Mon Sep 17 00:00:00 2001 From: Kazuya Mizuguchi Date: Wed, 30 Sep 2015 15:15:55 +0900 Subject: ravb: Add support for r8a7795 SoC This patch supports the r8a7795 SoC by: - Using two interrupts + One for E-MAC + One for everything else + Both can be handled by the existing common interrupt handler, which affords a simpler update to support the new SoC. In future some consideration may be given to implementing multiple interrupt handlers - Limiting the phy speed to 100Mbit/s for the new SoC; at this time it is not clear how this restriction may be lifted but I hope it will be possible as more information comes to light Signed-off-by: Kazuya Mizuguchi [horms: reworked] Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb.h | 7 ++++ drivers/net/ethernet/renesas/ravb_main.c | 63 ++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h index a157aaaaff6a..0623fff932e4 100644 --- a/drivers/net/ethernet/renesas/ravb.h +++ b/drivers/net/ethernet/renesas/ravb.h @@ -766,6 +766,11 @@ struct ravb_ptp { struct ravb_ptp_perout perout[N_PER_OUT]; }; +enum ravb_chip_id { + RCAR_GEN2, + RCAR_GEN3, +}; + struct ravb_private { struct net_device *ndev; struct platform_device *pdev; @@ -806,6 +811,8 @@ struct ravb_private { int msg_enable; int speed; int duplex; + int emac_irq; + enum ravb_chip_id chip_id; unsigned no_avb_link:1; unsigned avb_link_active_low:1; diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 4ca093d033f8..8cc5ec5ed19a 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -889,6 +889,22 @@ static int ravb_phy_init(struct net_device *ndev) return -ENOENT; } + /* This driver only support 10/100Mbit speeds on Gen3 + * at this time. + */ + if (priv->chip_id == RCAR_GEN3) { + int err; + + err = phy_set_max_speed(phydev, SPEED_100); + if (err) { + netdev_err(ndev, "failed to limit PHY to 100Mbit/s\n"); + phy_disconnect(phydev); + return err; + } + + netdev_info(ndev, "limited PHY to 100Mbit/s\n"); + } + netdev_info(ndev, "attached PHY %d (IRQ %d) to driver %s\n", phydev->addr, phydev->irq, phydev->drv->name); @@ -1197,6 +1213,15 @@ static int ravb_open(struct net_device *ndev) goto out_napi_off; } + if (priv->chip_id == RCAR_GEN3) { + error = request_irq(priv->emac_irq, ravb_interrupt, + IRQF_SHARED, ndev->name, ndev); + if (error) { + netdev_err(ndev, "cannot request IRQ\n"); + goto out_free_irq; + } + } + /* Device init */ error = ravb_dmac_init(ndev); if (error) @@ -1220,6 +1245,7 @@ out_ptp_stop: ravb_ptp_stop(ndev); out_free_irq: free_irq(ndev->irq, ndev); + free_irq(priv->emac_irq, ndev); out_napi_off: napi_disable(&priv->napi[RAVB_NC]); napi_disable(&priv->napi[RAVB_BE]); @@ -1625,10 +1651,20 @@ static int ravb_mdio_release(struct ravb_private *priv) return 0; } +static const struct of_device_id ravb_match_table[] = { + { .compatible = "renesas,etheravb-r8a7790", .data = (void *)RCAR_GEN2 }, + { .compatible = "renesas,etheravb-r8a7794", .data = (void *)RCAR_GEN2 }, + { .compatible = "renesas,etheravb-r8a7795", .data = (void *)RCAR_GEN3 }, + { } +}; +MODULE_DEVICE_TABLE(of, ravb_match_table); + static int ravb_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; struct ravb_private *priv; + enum ravb_chip_id chip_id; struct net_device *ndev; int error, irq, q; struct resource *res; @@ -1657,7 +1693,14 @@ static int ravb_probe(struct platform_device *pdev) /* The Ether-specific entries in the device structure. */ ndev->base_addr = res->start; ndev->dma = -1; - irq = platform_get_irq(pdev, 0); + + match = of_match_device(of_match_ptr(ravb_match_table), &pdev->dev); + chip_id = (enum ravb_chip_id)match->data; + + if (chip_id == RCAR_GEN3) + irq = platform_get_irq_byname(pdev, "ch22"); + else + irq = platform_get_irq(pdev, 0); if (irq < 0) { error = irq; goto out_release; @@ -1688,6 +1731,17 @@ static int ravb_probe(struct platform_device *pdev) priv->avb_link_active_low = of_property_read_bool(np, "renesas,ether-link-active-low"); + if (chip_id == RCAR_GEN3) { + irq = platform_get_irq_byname(pdev, "ch24"); + if (irq < 0) { + error = irq; + goto out_release; + } + priv->emac_irq = irq; + } + + priv->chip_id = chip_id; + /* Set function */ ndev->netdev_ops = &ravb_netdev_ops; ndev->ethtool_ops = &ravb_ethtool_ops; @@ -1818,13 +1872,6 @@ static const struct dev_pm_ops ravb_dev_pm_ops = { #define RAVB_PM_OPS NULL #endif -static const struct of_device_id ravb_match_table[] = { - { .compatible = "renesas,etheravb-r8a7790" }, - { .compatible = "renesas,etheravb-r8a7794" }, - { } -}; -MODULE_DEVICE_TABLE(of, ravb_match_table); - static struct platform_driver ravb_driver = { .probe = ravb_probe, .remove = ravb_remove, -- cgit v1.2.3 From 8dc5562e4e2b8255d2ea5d472a7fa25d5aa20da4 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 17 Aug 2015 11:19:02 +0800 Subject: i40e: Use numa_mem_id() to better support memoryless node Function i40e_clean_rx_irq() tries to reuse memory pages allocated from the nearest node. To better support memoryless node, use numa_mem_id() instead of numa_node_id() to get the nearest node with memory. This change should only affect performance. Signed-off-by: Jiang Liu Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 0d692ddfbc4f..85e61b004f2c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1443,7 +1443,7 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget) unsigned int total_rx_bytes = 0, total_rx_packets = 0; u16 rx_packet_len, rx_header_len, rx_sph, rx_hbo; u16 cleaned_count = I40E_DESC_UNUSED(rx_ring); - const int current_node = numa_node_id(); + const int current_node = numa_mem_id(); struct i40e_vsi *vsi = rx_ring->vsi; u16 i = rx_ring->next_to_clean; union i40e_rx_desc *rx_desc; -- cgit v1.2.3 From 27ca2753500537b8f3f3aba43558d68e2e8439a1 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Mon, 17 Aug 2015 11:19:03 +0800 Subject: i40evf: Use numa_mem_id() to better support memoryless node Function i40e_clean_rx_irq() tries to reuse memory pages allocated from the nearest node. To better support memoryless node, use numa_mem_id() instead of numa_node_id() to get the nearest node with memory. This change should only affect performance. Signed-off-by: Jiang Liu Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index aaee89fd6526..0e1a4d6e4e6e 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -917,7 +917,7 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget) unsigned int total_rx_bytes = 0, total_rx_packets = 0; u16 rx_packet_len, rx_header_len, rx_sph, rx_hbo; u16 cleaned_count = I40E_DESC_UNUSED(rx_ring); - const int current_node = numa_node_id(); + const int current_node = numa_mem_id(); struct i40e_vsi *vsi = rx_ring->vsi; u16 i = rx_ring->next_to_clean; union i40e_rx_desc *rx_desc; -- cgit v1.2.3 From 126b63d9d3aa99a90381ed168a885989dd33cf15 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Date: Mon, 24 Aug 2015 13:26:53 -0700 Subject: i40e: Fix a memory leak in X722 rss config path In any case free the memory allocated before exiting. Reported-by: Dan Carpenter Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 4345fc58dc00..5646ee885db2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7625,7 +7625,7 @@ static int i40e_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed) "Cannot set RSS key, err %s aq_err %s\n", i40e_stat_str(&pf->hw, ret), i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); - return ret; + goto config_rss_aq_out; } if (vsi->type == I40E_VSI_MAIN) @@ -7639,6 +7639,8 @@ static int i40e_config_rss_aq(struct i40e_vsi *vsi, const u8 *seed) i40e_stat_str(&pf->hw, ret), i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); +config_rss_aq_out: + kfree(rss_lut); return ret; } -- cgit v1.2.3 From 24408e7ae677cea4e44ce6869a1b803820839471 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Mon, 28 Sep 2015 14:12:38 -0400 Subject: i40e/i40evf: grab the AQ spinlocks before clearing registers Make sure we have the spinlocks before we clear the ARQ and ASQ management registers. Also, widen the locked portion and make a sanity check earlier in the send function to be sure we're working with safe register values. Change-ID: I34b56044b33461ed780f3d2de8d62826cdf933f9 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 45 +++++++++++++------------ drivers/net/ethernet/intel/i40evf/i40e_adminq.c | 45 +++++++++++++------------ 2 files changed, 46 insertions(+), 44 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index e59ffb2e7b4c..34a64e05c55c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -482,8 +482,12 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw) { i40e_status ret_code = 0; - if (hw->aq.asq.count == 0) - return I40E_ERR_NOT_READY; + mutex_lock(&hw->aq.asq_mutex); + + if (hw->aq.asq.count == 0) { + ret_code = I40E_ERR_NOT_READY; + goto shutdown_asq_out; + } /* Stop firmware AdminQ processing */ wr32(hw, hw->aq.asq.head, 0); @@ -492,16 +496,13 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw) wr32(hw, hw->aq.asq.bal, 0); wr32(hw, hw->aq.asq.bah, 0); - /* make sure lock is available */ - mutex_lock(&hw->aq.asq_mutex); - hw->aq.asq.count = 0; /* to indicate uninitialized queue */ /* free ring buffers */ i40e_free_asq_bufs(hw); +shutdown_asq_out: mutex_unlock(&hw->aq.asq_mutex); - return ret_code; } @@ -515,8 +516,12 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw) { i40e_status ret_code = 0; - if (hw->aq.arq.count == 0) - return I40E_ERR_NOT_READY; + mutex_lock(&hw->aq.arq_mutex); + + if (hw->aq.arq.count == 0) { + ret_code = I40E_ERR_NOT_READY; + goto shutdown_arq_out; + } /* Stop firmware AdminQ processing */ wr32(hw, hw->aq.arq.head, 0); @@ -525,16 +530,13 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw) wr32(hw, hw->aq.arq.bal, 0); wr32(hw, hw->aq.arq.bah, 0); - /* make sure lock is available */ - mutex_lock(&hw->aq.arq_mutex); - hw->aq.arq.count = 0; /* to indicate uninitialized queue */ /* free ring buffers */ i40e_free_arq_bufs(hw); +shutdown_arq_out: mutex_unlock(&hw->aq.arq_mutex); - return ret_code; } @@ -745,19 +747,21 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, u16 retval = 0; u32 val = 0; - val = rd32(hw, hw->aq.asq.head); - if (val >= hw->aq.num_asq_entries) { + mutex_lock(&hw->aq.asq_mutex); + + if (hw->aq.asq.count == 0) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, - "AQTX: head overrun at %d\n", val); + "AQTX: Admin queue not initialized.\n"); status = I40E_ERR_QUEUE_EMPTY; - goto asq_send_command_exit; + goto asq_send_command_error; } - if (hw->aq.asq.count == 0) { + val = rd32(hw, hw->aq.asq.head); + if (val >= hw->aq.num_asq_entries) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, - "AQTX: Admin queue not initialized.\n"); + "AQTX: head overrun at %d\n", val); status = I40E_ERR_QUEUE_EMPTY; - goto asq_send_command_exit; + goto asq_send_command_error; } details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use); @@ -782,8 +786,6 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, desc->flags &= ~cpu_to_le16(details->flags_dis); desc->flags |= cpu_to_le16(details->flags_ena); - mutex_lock(&hw->aq.asq_mutex); - if (buff_size > hw->aq.asq_buf_size) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, @@ -907,7 +909,6 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, asq_send_command_error: mutex_unlock(&hw->aq.asq_mutex); -asq_send_command_exit: return status; } diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c index 5026773a7c26..c7f59e002cb6 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c @@ -469,8 +469,12 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw) { i40e_status ret_code = 0; - if (hw->aq.asq.count == 0) - return I40E_ERR_NOT_READY; + mutex_lock(&hw->aq.asq_mutex); + + if (hw->aq.asq.count == 0) { + ret_code = I40E_ERR_NOT_READY; + goto shutdown_asq_out; + } /* Stop firmware AdminQ processing */ wr32(hw, hw->aq.asq.head, 0); @@ -479,16 +483,13 @@ static i40e_status i40e_shutdown_asq(struct i40e_hw *hw) wr32(hw, hw->aq.asq.bal, 0); wr32(hw, hw->aq.asq.bah, 0); - /* make sure lock is available */ - mutex_lock(&hw->aq.asq_mutex); - hw->aq.asq.count = 0; /* to indicate uninitialized queue */ /* free ring buffers */ i40e_free_asq_bufs(hw); +shutdown_asq_out: mutex_unlock(&hw->aq.asq_mutex); - return ret_code; } @@ -502,8 +503,12 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw) { i40e_status ret_code = 0; - if (hw->aq.arq.count == 0) - return I40E_ERR_NOT_READY; + mutex_lock(&hw->aq.arq_mutex); + + if (hw->aq.arq.count == 0) { + ret_code = I40E_ERR_NOT_READY; + goto shutdown_arq_out; + } /* Stop firmware AdminQ processing */ wr32(hw, hw->aq.arq.head, 0); @@ -512,16 +517,13 @@ static i40e_status i40e_shutdown_arq(struct i40e_hw *hw) wr32(hw, hw->aq.arq.bal, 0); wr32(hw, hw->aq.arq.bah, 0); - /* make sure lock is available */ - mutex_lock(&hw->aq.arq_mutex); - hw->aq.arq.count = 0; /* to indicate uninitialized queue */ /* free ring buffers */ i40e_free_arq_bufs(hw); +shutdown_arq_out: mutex_unlock(&hw->aq.arq_mutex); - return ret_code; } @@ -685,19 +687,21 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw, u16 retval = 0; u32 val = 0; - val = rd32(hw, hw->aq.asq.head); - if (val >= hw->aq.num_asq_entries) { + mutex_lock(&hw->aq.asq_mutex); + + if (hw->aq.asq.count == 0) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, - "AQTX: head overrun at %d\n", val); + "AQTX: Admin queue not initialized.\n"); status = I40E_ERR_QUEUE_EMPTY; - goto asq_send_command_exit; + goto asq_send_command_error; } - if (hw->aq.asq.count == 0) { + val = rd32(hw, hw->aq.asq.head); + if (val >= hw->aq.num_asq_entries) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, - "AQTX: Admin queue not initialized.\n"); + "AQTX: head overrun at %d\n", val); status = I40E_ERR_QUEUE_EMPTY; - goto asq_send_command_exit; + goto asq_send_command_error; } details = I40E_ADMINQ_DETAILS(hw->aq.asq, hw->aq.asq.next_to_use); @@ -722,8 +726,6 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw, desc->flags &= ~cpu_to_le16(details->flags_dis); desc->flags |= cpu_to_le16(details->flags_ena); - mutex_lock(&hw->aq.asq_mutex); - if (buff_size > hw->aq.asq_buf_size) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, @@ -848,7 +850,6 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw, asq_send_command_error: mutex_unlock(&hw->aq.asq_mutex); -asq_send_command_exit: return status; } -- cgit v1.2.3 From 8552d85442dd814d733f67592627ea55f7cbfb01 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Mon, 31 Aug 2015 19:54:51 -0400 Subject: i40evf: don't blow away MAC address Under certain circumstances, we can get an extra VF_RESOURCES message from the PF driver at runtime. When this happens, we need to parse it because our VSI may have changed out from underneath us, and that will affect our relationship with the PF driver. However, parsing the resources message also blows away our current MAC address in the hardware struct, usually with all zeros. When this happens, the next time the interface is opened, it will have no MAC address and will a) not work and b) complain. Fix this issue by restoring the current MAC address from the netdev struct after we parse the resource message. Change-ID: I6cd1b624fc20432f81dc901166c8de195b8e0e65 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index d4eb1a5e7d42..fbf2a1c86c1c 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -756,6 +756,8 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, sizeof(struct i40e_virtchnl_vsi_resource); memcpy(adapter->vf_res, msg, min(msglen, len)); i40e_vf_parse_hw_config(&adapter->hw, adapter->vf_res); + /* restore current mac address */ + ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr); i40evf_process_config(adapter); } break; -- cgit v1.2.3 From 621a5f7ad9cd1ce7933f1d302067cbd58354173c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sat, 26 Sep 2015 15:04:07 -0700 Subject: debugfs: Pass bool pointer to debugfs_create_bool() Its a bit odd that debugfs_create_bool() takes 'u32 *' as an argument, when all it needs is a boolean pointer. It would be better to update this API to make it accept 'bool *' instead, as that will make it more consistent and often more convenient. Over that bool takes just a byte. That required updates to all user sites as well, in the same commit updating the API. regmap core was also using debugfs_{read|write}_file_bool(), directly and variable types were updated for that to be bool as well. Signed-off-by: Viresh Kumar Acked-by: Mark Brown Acked-by: Charles Keepax Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 4 ++-- drivers/net/wireless/ath/ath10k/core.h | 2 +- drivers/net/wireless/ath/ath5k/ath5k.h | 2 +- drivers/net/wireless/ath/ath9k/hw.c | 2 +- drivers/net/wireless/ath/ath9k/hw.h | 4 ++-- drivers/net/wireless/b43/debugfs.c | 18 +++++++++--------- drivers/net/wireless/b43/debugfs.h | 2 +- drivers/net/wireless/b43legacy/debugfs.c | 10 +++++----- drivers/net/wireless/b43legacy/debugfs.h | 2 +- drivers/net/wireless/iwlegacy/common.h | 6 +++--- drivers/net/wireless/iwlwifi/mvm/mvm.h | 6 +++--- 11 files changed, 29 insertions(+), 29 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index fa0c7b54ec7a..5384f999c24b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -767,8 +767,8 @@ struct adapter { bool tid_release_task_busy; struct dentry *debugfs_root; - u32 use_bd; /* Use SGE Back Door intfc for reading SGE Contexts */ - u32 trace_rss; /* 1 implies that different RSS flit per filter is + bool use_bd; /* Use SGE Back Door intfc for reading SGE Contexts */ + bool trace_rss; /* 1 implies that different RSS flit per filter is * used per filter else if 0 default RSS flit is * used for all 4 filters. */ diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 12542144fe12..b6a08177b6ee 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -680,7 +680,7 @@ struct ath10k { bool monitor_started; unsigned int filter_flags; unsigned long dev_flags; - u32 dfs_block_radar_events; + bool dfs_block_radar_events; /* protected by conf_mutex */ bool radar_enabled; diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index fa6e89e5c421..ba12f7f4061d 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1367,7 +1367,7 @@ struct ath5k_hw { u8 ah_retry_long; u8 ah_retry_short; - u32 ah_use_32khz_clock; + bool ah_use_32khz_clock; u8 ah_coverage_class; bool ah_ack_bitrate_high; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 1dd0339de372..8823fadada89 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -385,7 +385,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah) ah->config.dma_beacon_response_time = 1; ah->config.sw_beacon_response_time = 6; - ah->config.cwm_ignore_extcca = 0; + ah->config.cwm_ignore_extcca = false; ah->config.analog_shiftreg = 1; ah->config.rx_intr_mitigation = true; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e8454db17634..52971b48ab6a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -332,14 +332,14 @@ enum ath9k_hw_hang_checks { struct ath9k_ops_config { int dma_beacon_response_time; int sw_beacon_response_time; - u32 cwm_ignore_extcca; + bool cwm_ignore_extcca; u32 pcie_waen; u8 analog_shiftreg; u32 ofdm_trig_low; u32 ofdm_trig_high; u32 cck_trig_high; u32 cck_trig_low; - u32 enable_paprd; + bool enable_paprd; int serialize_regmode; bool rx_intr_mitigation; bool tx_intr_mitigation; diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index e807bd930647..b4bcd94aff6c 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c @@ -676,15 +676,15 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev) e->dyn_debug_dentries[id] = d; \ } while (0) - add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, 0); - add_dyn_dbg("debug_dmaoverflow", B43_DBG_DMAOVERFLOW, 0); - add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, 0); - add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0); - add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); - add_dyn_dbg("debug_lo", B43_DBG_LO, 0); - add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); - add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0); - add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, 0); + add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, false); + add_dyn_dbg("debug_dmaoverflow", B43_DBG_DMAOVERFLOW, false); + add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, false); + add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, false); + add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, false); + add_dyn_dbg("debug_lo", B43_DBG_LO, false); + add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, false); + add_dyn_dbg("debug_keys", B43_DBG_KEYS, false); + add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, false); #undef add_dyn_dbg } diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index 50517b801cb4..d05377745011 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h @@ -68,7 +68,7 @@ struct b43_dfsentry { u32 shm32read_addr_next; /* Enabled/Disabled list for the dynamic debugging features. */ - u32 dyn_debug[__B43_NR_DYNDBG]; + bool dyn_debug[__B43_NR_DYNDBG]; /* Dentries for the dynamic debugging entries. */ struct dentry *dyn_debug_dentries[__B43_NR_DYNDBG]; }; diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c index 1965edb765a2..090910ea259e 100644 --- a/drivers/net/wireless/b43legacy/debugfs.c +++ b/drivers/net/wireless/b43legacy/debugfs.c @@ -369,11 +369,11 @@ static void b43legacy_add_dynamic_debug(struct b43legacy_wldev *dev) e->dyn_debug_dentries[id] = d; \ } while (0) - add_dyn_dbg("debug_xmitpower", B43legacy_DBG_XMITPOWER, 0); - add_dyn_dbg("debug_dmaoverflow", B43legacy_DBG_DMAOVERFLOW, 0); - add_dyn_dbg("debug_dmaverbose", B43legacy_DBG_DMAVERBOSE, 0); - add_dyn_dbg("debug_pwork_fast", B43legacy_DBG_PWORK_FAST, 0); - add_dyn_dbg("debug_pwork_stop", B43legacy_DBG_PWORK_STOP, 0); + add_dyn_dbg("debug_xmitpower", B43legacy_DBG_XMITPOWER, false); + add_dyn_dbg("debug_dmaoverflow", B43legacy_DBG_DMAOVERFLOW, false); + add_dyn_dbg("debug_dmaverbose", B43legacy_DBG_DMAVERBOSE, false); + add_dyn_dbg("debug_pwork_fast", B43legacy_DBG_PWORK_FAST, false); + add_dyn_dbg("debug_pwork_stop", B43legacy_DBG_PWORK_STOP, false); #undef add_dyn_dbg } diff --git a/drivers/net/wireless/b43legacy/debugfs.h b/drivers/net/wireless/b43legacy/debugfs.h index ae3b0d0fa849..9ee32158b947 100644 --- a/drivers/net/wireless/b43legacy/debugfs.h +++ b/drivers/net/wireless/b43legacy/debugfs.h @@ -47,7 +47,7 @@ struct b43legacy_dfsentry { struct b43legacy_txstatus_log txstatlog; /* Enabled/Disabled list for the dynamic debugging features. */ - u32 dyn_debug[__B43legacy_NR_DYNDBG]; + bool dyn_debug[__B43legacy_NR_DYNDBG]; /* Dentries for the dynamic debugging entries. */ struct dentry *dyn_debug_dentries[__B43legacy_NR_DYNDBG]; }; diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 5b972798bdff..ce52cf114fde 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1425,9 +1425,9 @@ struct il_priv { #endif /* CONFIG_IWLEGACY_DEBUGFS */ struct work_struct txpower_work; - u32 disable_sens_cal; - u32 disable_chain_noise_cal; - u32 disable_tx_power_cal; + bool disable_sens_cal; + bool disable_chain_noise_cal; + bool disable_tx_power_cal; struct work_struct run_time_calib_work; struct timer_list stats_periodic; struct timer_list watchdog; diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index b95a07ec9e36..72e8a03a5293 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -649,7 +649,7 @@ struct iwl_mvm { const struct iwl_fw_bcast_filter *bcast_filters; #ifdef CONFIG_IWLWIFI_DEBUGFS struct { - u32 override; /* u32 for debugfs_create_bool */ + bool override; struct iwl_bcast_filter_cmd cmd; } dbgfs_bcast_filtering; #endif @@ -673,7 +673,7 @@ struct iwl_mvm { bool disable_power_off; bool disable_power_off_d3; - u32 scan_iter_notif_enabled; /* must be u32 for debugfs_create_bool */ + bool scan_iter_notif_enabled; struct debugfs_blob_wrapper nvm_hw_blob; struct debugfs_blob_wrapper nvm_sw_blob; @@ -729,7 +729,7 @@ struct iwl_mvm { int n_nd_channels; bool net_detect; #ifdef CONFIG_IWLWIFI_DEBUGFS - u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */ + bool d3_wake_sysassert; bool d3_test_active; bool store_d3_resume_sram; void *d3_resume_sram; -- cgit v1.2.3 From 09eef3307e6d55afbdc4cebc8aeacbbb0a7337f6 Mon Sep 17 00:00:00 2001 From: Aviya Erenfeld Date: Tue, 1 Sep 2015 19:34:38 +0300 Subject: iwlwifi: mvm: move DTS command and notification to new group Move the DTS measurement command and notification from short command header to the new PHY command group for firmware supporting the extended command headers. Signed-off-by: Aviya Erenfeld Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/fw-api.h | 10 ++++++++++ drivers/net/wireless/iwlwifi/mvm/ops.c | 2 ++ drivers/net/wireless/iwlwifi/mvm/tt.c | 14 ++++++++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 5e4014a87222..44ff6849b7a5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h @@ -268,6 +268,16 @@ enum { REPLY_MAX = 0xff, }; +enum iwl_phy_ops_subcmd_ids { + CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0, + DTS_MEASUREMENT_NOTIF_WIDE = 0xFF, +}; + +/* command groups */ +enum { + PHY_OPS_GROUP = 0x4, +}; + /** * struct iwl_cmd_response - generic response struct for most commands * @status: status of the command asked, changes for each one diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 3f6428c260de..23825ff8c270 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -257,6 +257,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { RX_HANDLER(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION, iwl_mvm_power_uapsd_misbehaving_ap_notif, false), RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif, true), + RX_HANDLER_GRP(PHY_OPS_GROUP, DTS_MEASUREMENT_NOTIF_WIDE, + iwl_mvm_temp_notif, true), RX_HANDLER(TDLS_CHANNEL_SWITCH_NOTIFICATION, iwl_mvm_rx_tdls_notif, true), diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index fe7145c2c98a..58b762f1e0b5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c @@ -176,17 +176,27 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm) struct iwl_dts_measurement_cmd cmd = { .flags = cpu_to_le32(DTS_TRIGGER_CMD_FLAGS_TEMP), }; + u32 cmdid; - return iwl_mvm_send_cmd_pdu(mvm, CMD_DTS_MEASUREMENT_TRIGGER, 0, + if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR)) + cmdid = iwl_cmd_id(CMD_DTS_MEASUREMENT_TRIGGER_WIDE, + PHY_OPS_GROUP, 0); + else + cmdid = CMD_DTS_MEASUREMENT_TRIGGER; + return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(cmd), &cmd); } int iwl_mvm_get_temp(struct iwl_mvm *mvm) { struct iwl_notification_wait wait_temp_notif; - static const u16 temp_notif[] = { DTS_MEASUREMENT_NOTIFICATION }; + static u16 temp_notif[] = { WIDE_ID(PHY_OPS_GROUP, + DTS_MEASUREMENT_NOTIF_WIDE) }; int ret, temp; + if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR)) + temp_notif[0] = DTS_MEASUREMENT_NOTIFICATION; + lockdep_assert_held(&mvm->mutex); iwl_init_notification_wait(&mvm->notif_wait, &wait_temp_notif, -- cgit v1.2.3 From bb35dc14182c16e9646f6323cce25f3cfe3ba593 Mon Sep 17 00:00:00 2001 From: Moshe Harel Date: Sun, 6 Sep 2015 16:50:33 +0300 Subject: iwlwifi: nvm: force 1x1 antenna in Series 8000 This is a workaround to an OTP bug. In Series 8000 1x1, the OTP 0xA052 defines 2x2 antenna configuration. This workaround overrides the decision based on HW id and MIMO disabled bit which is correct in the OTP and set to disabled. Signed-off-by: Moshe Harel Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 15 ++++++++++++++- drivers/net/wireless/iwlwifi/iwl-nvm-parse.h | 2 +- drivers/net/wireless/iwlwifi/mvm/nvm.c | 3 ++- 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 3b8e85e51002..d82984912e04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -580,13 +580,15 @@ static void iwl_set_hw_address_family_8000(struct device *dev, IWL_ERR_DEV(dev, "mac address is not found\n"); } +#define IWL_4165_DEVICE_ID 0x5501 + struct iwl_nvm_data * iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_hw, const __le16 *nvm_sw, const __le16 *nvm_calib, const __le16 *regulatory, const __le16 *mac_override, const __le16 *phy_sku, u8 tx_chains, u8 rx_chains, bool lar_fw_supported, - u32 mac_addr0, u32 mac_addr1) + u32 mac_addr0, u32 mac_addr1, u32 hw_id) { struct iwl_nvm_data *data; u32 sku; @@ -625,6 +627,17 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, (sku & NVM_SKU_CAP_11AC_ENABLE); data->sku_cap_mimo_disabled = sku & NVM_SKU_CAP_MIMO_DISABLE; + /* + * OTP 0x52 bug work around + * define antenna 1x1 according to MIMO disabled + */ + if (hw_id == IWL_4165_DEVICE_ID && data->sku_cap_mimo_disabled) { + data->valid_tx_ant = ANT_B; + data->valid_rx_ant = ANT_B; + tx_chains = ANT_B; + rx_chains = ANT_B; + } + data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw); if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h index 822ba52e0e5a..9f44d8188c5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.h @@ -79,7 +79,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_calib, const __le16 *regulatory, const __le16 *mac_override, const __le16 *phy_sku, u8 tx_chains, u8 rx_chains, bool lar_fw_supported, - u32 mac_addr0, u32 mac_addr1); + u32 mac_addr0, u32 mac_addr1, u32 hw_id); /** * iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 328187da7541..0b3ffd5e0f3b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c @@ -316,7 +316,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, regulatory, mac_override, phy_sku, mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant, - lar_enabled, mac_addr0, mac_addr1); + lar_enabled, mac_addr0, mac_addr1, + mvm->trans->hw_id); } #define MAX_NVM_FILE_LEN 16384 -- cgit v1.2.3 From a6449126518d908f0d706cce85c9bf243342b7b0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 1 Sep 2015 14:15:17 +0200 Subject: iwlwifi: mvm: correct skip-over-DTIM implementation The formula used in D0i3 should also be used in D3, instead of the hardcoded value. Additionally, the formula is actually wrong - if the calculation yields 0 then 1 should be used instead of disabling entirely. Also need to add 1 since the firmware needs 3 to skip 2, etc. To make all this clearer, centralize the calculation into a single function. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/power.c | 74 ++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 4645877882a6..21a858dfcc26 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * * 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 @@ -33,6 +34,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -306,13 +308,50 @@ static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif) return radar_detect; } +static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct iwl_mac_power_cmd *cmd, + bool host_awake) +{ + int dtimper = vif->bss_conf.dtim_period ?: 1; + int skip; + + /* disable, in case we're supposed to override */ + cmd->skip_dtim_periods = 0; + cmd->flags &= ~cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); + + if (iwl_mvm_power_is_radar(vif)) + return; + + if (dtimper >= 10) + return; + + /* TODO: check that multicast wake lock is off */ + + if (host_awake) { + if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP) + return; + skip = 2; + } else { + int dtimper_tu = dtimper * vif->bss_conf.beacon_int; + + if (WARN_ON(!dtimper_tu)) + return; + /* configure skip over dtim up to 306TU - 314 msec */ + skip = max_t(u8, 1, 306 / dtimper_tu); + } + + /* the firmware really expects "look at every X DTIMs", so add 1 */ + cmd->skip_dtim_periods = 1 + skip; + cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); +} + static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_mac_power_cmd *cmd) { int dtimper, bi; int keep_alive; - bool radar_detect = false; struct iwl_mvm_vif *mvmvif __maybe_unused = iwl_mvm_vif_from_mac80211(vif); @@ -350,16 +389,8 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD; } - /* Check if radar detection is required on current channel */ - radar_detect = iwl_mvm_power_is_radar(vif); - - /* Check skip over DTIM conditions */ - if (!radar_detect && (dtimper < 10) && - (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP || - mvm->cur_ucode == IWL_UCODE_WOWLAN)) { - cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); - cmd->skip_dtim_periods = 3; - } + iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, + mvm->cur_ucode != IWL_UCODE_WOWLAN); if (mvm->cur_ucode != IWL_UCODE_WOWLAN) { cmd->rx_data_timeout = @@ -964,24 +995,11 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, return 0; iwl_mvm_power_build_cmd(mvm, vif, &cmd); - if (enable) { - /* configure skip over dtim up to 306TU - 314 msec */ - int dtimper = vif->bss_conf.dtim_period ?: 1; - int dtimper_tu = dtimper * vif->bss_conf.beacon_int; - bool radar_detect = iwl_mvm_power_is_radar(vif); - if (WARN_ON(!dtimper_tu)) - return 0; - - /* Check skip over DTIM conditions */ - /* TODO: check that multicast wake lock is off */ - if (!radar_detect && (dtimper < 10)) { - cmd.skip_dtim_periods = 306 / dtimper_tu; - if (cmd.skip_dtim_periods) - cmd.flags |= cpu_to_le16( - POWER_FLAGS_SKIP_OVER_DTIM_MSK); - } - } + /* when enabling D0i3, override the skip-over-dtim configuration */ + if (enable) + iwl_mvm_power_config_skip_dtim(mvm, vif, &cmd, false); + iwl_mvm_power_log(mvm, &cmd); #ifdef CONFIG_IWLWIFI_DEBUGFS memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd)); -- cgit v1.2.3 From acf9de3dfb2c9c00d94c3d614980006947ed2b7f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 4 Sep 2015 20:54:35 +0200 Subject: iwlwifi: enable tracing by default Tracing, if disabled at runtime, has very low overhead with great returns on debugging. It therefore makes sense to have it enabled by default (if the kernel enables EVENT_TRACING). Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index aba095761ac6..6e949df399d6 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -142,6 +142,7 @@ config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE config IWLWIFI_DEVICE_TRACING bool "iwlwifi device access tracing" depends on EVENT_TRACING + default y help Say Y here to trace all commands, including TX frames and IO accesses, sent to the device. If you say yes, iwlwifi will -- cgit v1.2.3 From 69191afef3c889992de643af7c318c9a8a1750c0 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Tue, 1 Sep 2015 18:50:22 +0300 Subject: iwlwifi: mvm: fix default disabled aggs in sta For the ADD_STA command, when the flag for aggregation disabling is set, there is a bitmap indicated what TIDs are disabling aggregations and what aren't. Currently, by default, all TIDs allow for aggregations since the value we begin with is 0. Change this default value to 0xffff so all TIDs don't allow aggregations until explicitly turned on. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/sta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index fe2f53850d36..18ca030d28b2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -292,7 +292,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, /* HW restart, don't assume the memory has been zeroed */ atomic_set(&mvm->pending_frames[sta_id], 0); - mvm_sta->tid_disable_agg = 0; + mvm_sta->tid_disable_agg = 0xffff; /* No aggs at first */ mvm_sta->tfd_queue_msk = 0; /* allocate new queues for a TDLS station */ -- cgit v1.2.3 From f82c83397beac5c829bfcb3ea6bb4bfdbac79209 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Thu, 10 Sep 2015 12:54:38 +0300 Subject: iwlwifi: mvm: Correctly update MAC context on add/del station Commit "iwlwifi: mvm: don't ask beacons when AP vif and no assoc sta" directly called iwl_mvm_mac_ctxt_cmd_ap() to update the MAC context when adding/removing a station. However, this ignores the case that the vif is actually a P2P GO. Fix this by calling iwl_mvm_mac_ctxt_changed() that handles P2P GO case as well. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 6 +++--- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 2 +- drivers/net/wireless/iwlwifi/mvm/mvm.h | 4 ---- drivers/net/wireless/iwlwifi/mvm/sta.c | 2 +- 4 files changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 5af0090ffb6e..361565076eaf 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -1126,9 +1126,9 @@ static void iwl_mvm_mac_ctxt_cmd_fill_ap(struct iwl_mvm *mvm, ctxt_ap->beacon_template = cpu_to_le32(mvmvif->id); } -int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - u32 action) +static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + u32 action) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mac_ctx_cmd cmd = {}; diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 4c497fe99878..d7275a5f7f00 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -2616,7 +2616,7 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, if (mvm_sta->vif->type == NL80211_IFTYPE_AP) { mvmvif->ap_assoc_sta_count--; - iwl_mvm_mac_ctxt_cmd_ap(mvm, vif, FW_CTXT_ACTION_MODIFY); + iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); } mutex_unlock(&mvm->mutex); diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index cf1f5140127a..5e027363baf0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -1129,10 +1129,6 @@ void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif); unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, struct ieee80211_vif *exclude_vif); -int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - u32 action); - /* Bindings */ int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 18ca030d28b2..4967990bfc46 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -277,7 +277,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, if (vif->type == NL80211_IFTYPE_AP) { mvmvif->ap_assoc_sta_count++; - iwl_mvm_mac_ctxt_cmd_ap(mvm, vif, FW_CTXT_ACTION_MODIFY); + iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); } spin_lock_init(&mvm_sta->lock); -- cgit v1.2.3 From bb7436093717d3ccaeaf28438be763b30a794ad8 Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Sat, 12 Sep 2015 12:04:51 +0200 Subject: iwlwifi: mvm: fix tof.h header guard Commit ce7929186a39 ("iwlwifi: mvm: add basic Time of Flight (802.11mc FTM) support") created drivers/net/wireless/iwlwifi/mvm/tof.h with a broken header guard: #ifndef __tof #define __tof_h__ ... #endif /* __tof_h__ */ Use __tof_h__ in the first line. Signed-off-by: Nicolas Iooss Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/tof.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/tof.h b/drivers/net/wireless/iwlwifi/mvm/tof.h index 50ae8adaaa6e..9beebc33cb8d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tof.h +++ b/drivers/net/wireless/iwlwifi/mvm/tof.h @@ -60,7 +60,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ -#ifndef __tof +#ifndef __tof_h__ #define __tof_h__ #include "fw-api-tof.h" -- cgit v1.2.3 From e6740165b8f7f06d8caee0fceab3fb9d790a6fed Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Wed, 30 Sep 2015 11:45:33 +0200 Subject: ppp: don't override sk->sk_state in pppoe_flush_dev() Since commit 2b018d57ff18 ("pppoe: drop PPPOX_ZOMBIEs in pppoe_release"), pppoe_release() calls dev_put(po->pppoe_dev) if sk is in the PPPOX_ZOMBIE state. But pppoe_flush_dev() can set sk->sk_state to PPPOX_ZOMBIE _and_ reset po->pppoe_dev to NULL. This leads to the following oops: [ 570.140800] BUG: unable to handle kernel NULL pointer dereference at 00000000000004e0 [ 570.142931] IP: [] pppoe_release+0x50/0x101 [pppoe] [ 570.144601] PGD 3d119067 PUD 3dbc1067 PMD 0 [ 570.144601] Oops: 0000 [#1] SMP [ 570.144601] Modules linked in: l2tp_ppp l2tp_netlink l2tp_core ip6_udp_tunnel udp_tunnel pppoe pppox ppp_generic slhc loop crc32c_intel ghash_clmulni_intel jitterentropy_rng sha256_generic hmac drbg ansi_cprng aesni_intel aes_x86_64 ablk_helper cryptd lrw gf128mul glue_helper acpi_cpufreq evdev serio_raw processor button ext4 crc16 mbcache jbd2 virtio_net virtio_blk virtio_pci virtio_ring virtio [ 570.144601] CPU: 1 PID: 15738 Comm: ppp-apitest Not tainted 4.2.0 #1 [ 570.144601] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Debian-1.8.2-1 04/01/2014 [ 570.144601] task: ffff88003d30d600 ti: ffff880036b60000 task.ti: ffff880036b60000 [ 570.144601] RIP: 0010:[] [] pppoe_release+0x50/0x101 [pppoe] [ 570.144601] RSP: 0018:ffff880036b63e08 EFLAGS: 00010202 [ 570.144601] RAX: 0000000000000000 RBX: ffff880034340000 RCX: 0000000000000206 [ 570.144601] RDX: 0000000000000006 RSI: ffff88003d30dd20 RDI: ffff88003d30dd20 [ 570.144601] RBP: ffff880036b63e28 R08: 0000000000000001 R09: 0000000000000000 [ 570.144601] R10: 00007ffee9b50420 R11: ffff880034340078 R12: ffff8800387ec780 [ 570.144601] R13: ffff8800387ec7b0 R14: ffff88003e222aa0 R15: ffff8800387ec7b0 [ 570.144601] FS: 00007f5672f48700(0000) GS:ffff88003fc80000(0000) knlGS:0000000000000000 [ 570.144601] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 570.144601] CR2: 00000000000004e0 CR3: 0000000037f7e000 CR4: 00000000000406a0 [ 570.144601] Stack: [ 570.144601] ffffffffa018f240 ffff8800387ec780 ffffffffa018f240 ffff8800387ec7b0 [ 570.144601] ffff880036b63e48 ffffffff812caabe ffff880039e4e000 0000000000000008 [ 570.144601] ffff880036b63e58 ffffffff812cabad ffff880036b63ea8 ffffffff811347f5 [ 570.144601] Call Trace: [ 570.144601] [] sock_release+0x1a/0x75 [ 570.144601] [] sock_close+0xd/0x11 [ 570.144601] [] __fput+0xff/0x1a5 [ 570.144601] [] ____fput+0x9/0xb [ 570.144601] [] task_work_run+0x66/0x90 [ 570.144601] [] prepare_exit_to_usermode+0x8c/0xa7 [ 570.144601] [] syscall_return_slowpath+0x16d/0x19b [ 570.144601] [] int_ret_from_sys_call+0x25/0x9f [ 570.144601] Code: 48 8b 83 c8 01 00 00 a8 01 74 12 48 89 df e8 8b 27 14 e1 b8 f7 ff ff ff e9 b7 00 00 00 8a 43 12 a8 0b 74 1c 48 8b 83 a8 04 00 00 <48> 8b 80 e0 04 00 00 65 ff 08 48 c7 83 a8 04 00 00 00 00 00 00 [ 570.144601] RIP [] pppoe_release+0x50/0x101 [pppoe] [ 570.144601] RSP [ 570.144601] CR2: 00000000000004e0 [ 570.200518] ---[ end trace 46956baf17349563 ]--- pppoe_flush_dev() has no reason to override sk->sk_state with PPPOX_ZOMBIE. pppox_unbind_sock() already sets sk->sk_state to PPPOX_DEAD, which is the correct state given that sk is unbound and po->pppoe_dev is NULL. Fixes: 2b018d57ff18 ("pppoe: drop PPPOX_ZOMBIEs in pppoe_release") Tested-by: Oleksii Berezhniak Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller --- drivers/net/ppp/pppoe.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index 3837ae344f63..2ed75060da50 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -313,7 +313,6 @@ static void pppoe_flush_dev(struct net_device *dev) if (po->pppoe_dev == dev && sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { pppox_unbind_sock(sk); - sk->sk_state = PPPOX_ZOMBIE; sk->sk_state_change(sk); po->pppoe_dev = NULL; dev_put(dev); -- cgit v1.2.3 From 9dc80a74313d2741e053a650942818a86f234fc9 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 30 Sep 2015 03:48:50 -0700 Subject: amd-xgbe: fix potential memory leak in xgbe-debugfs Added kfree() to avoid the memory leak when debugfs_create_dir() fails. Signed-off-by: Geliang Tang Acked-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c index 2c063b60db4b..66137ffea3f8 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c @@ -330,6 +330,7 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata) pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL); if (!pdata->xgbe_debugfs) { netdev_err(pdata->netdev, "debugfs_create_dir failed\n"); + kfree(buf); return; } -- cgit v1.2.3 From be7ccdc36ba4815ca71b0ac6df898237a912b3ac Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 30 Sep 2015 13:26:31 +0200 Subject: net: fec: avoid timespec use The fec_ptp_enable_pps uses an open-coded implementation of ns_to_timespec, which will be removed eventually as it is not y2038-safe on 32-bit architectures. Two more instances of the same code in this file were already converted to use the safe ns_to_timespec64 in commit 6630514fcee ("ptp: fec: use helpers for converting ns to timespec"), this changes the last one as well. The seconds portion here is actually unused and we could just remove the timespec variable, but using ns_to_timespec64 can still be better as the implementation can be hand-optimized in the future. Signed-off-by: Arnd Bergmann Cc: Richard Cochran Cc: Fugang Duan Cc: Luwei Zhou Cc: Frank Li Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_ptp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 1543cf0e8ef6..f9e74461bdc0 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -112,9 +112,8 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) unsigned long flags; u32 val, tempval; int inc; - struct timespec ts; + struct timespec64 ts; u64 ns; - u32 remainder; val = 0; if (!(fep->hwts_tx_en || fep->hwts_rx_en)) { @@ -163,8 +162,7 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) tempval = readl(fep->hwp + FEC_ATIME); /* Convert the ptp local counter to 1588 timestamp */ ns = timecounter_cyc2time(&fep->tc, tempval); - ts.tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder); - ts.tv_nsec = remainder; + ts = ns_to_timespec64(ns); /* The tempval is less than 3 seconds, and so val is less than * 4 seconds. No overflow for 32bit calculation. -- cgit v1.2.3 From 0a6241551d20e982dba8fc6c88b0a021456ea7b4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 30 Sep 2015 13:26:32 +0200 Subject: net: stmmac: avoid using timespec We want to deprecate the use of 'struct timespec' on 32-bit architectures, as it is will overflow in 2038. The stmmac driver uses it to read the current time, and can simply be changed to use ktime_get_real_ts64() instead. Because of hardware limitations, there is still an overflow in year 2106, which we cannot really avoid, but this documents the overflow. Signed-off-by: Arnd Bergmann Cc: Giuseppe Cavallaro Cc: Richard Cochran Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 934143e1193b..64d8aa4e0cad 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -424,7 +424,7 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) { struct stmmac_priv *priv = netdev_priv(dev); struct hwtstamp_config config; - struct timespec now; + struct timespec64 now; u64 temp = 0; u32 ptp_v2 = 0; u32 tstamp_all = 0; @@ -621,8 +621,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) priv->default_addend); /* initialize system time */ - getnstimeofday(&now); - priv->hw->ptp->init_systime(priv->ioaddr, now.tv_sec, + ktime_get_real_ts64(&now); + + /* lower 32 bits of tv_sec are safe until y2106 */ + priv->hw->ptp->init_systime(priv->ioaddr, (u32)now.tv_sec, now.tv_nsec); } -- cgit v1.2.3 From 40c9b0796d46523fffb93e46ed8c691456146743 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 30 Sep 2015 13:26:33 +0200 Subject: net: igb: avoid using timespec We want to deprecate the use of 'struct timespec' on 32-bit architectures, as it is will overflow in 2038. The igb driver uses it to read the current time, and can simply be changed to use ktime_get_real_ts64() instead. Because of hardware limitations, there is still an overflow in year 2106, which we cannot really avoid, but this documents the overflow. Signed-off-by: Arnd Bergmann Cc: Jeff Kirsher Cc: intel-wired-lan@lists.osuosl.org Reviewed-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/igb/igb.h | 4 ++-- drivers/net/ethernet/intel/igb/igb_main.c | 15 ++++++++------- drivers/net/ethernet/intel/igb/igb_ptp.c | 8 ++++---- 3 files changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index 212d668dabb3..1a2f1cc44b28 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -444,8 +444,8 @@ struct igb_adapter { struct ptp_pin_desc sdp_config[IGB_N_SDP]; struct { - struct timespec start; - struct timespec period; + struct timespec64 start; + struct timespec64 period; } perout[IGB_N_PEROUT]; char fw_version[32]; diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index ba019fc87fd1..7e6267503790 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -5392,7 +5392,7 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct ptp_clock_event event; - struct timespec ts; + struct timespec64 ts; u32 ack = 0, tsauxc, sec, nsec, tsicr = rd32(E1000_TSICR); if (tsicr & TSINTR_SYS_WRAP) { @@ -5412,10 +5412,11 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) if (tsicr & TSINTR_TT0) { spin_lock(&adapter->tmreg_lock); - ts = timespec_add(adapter->perout[0].start, - adapter->perout[0].period); + ts = timespec64_add(adapter->perout[0].start, + adapter->perout[0].period); + /* u32 conversion of tv_sec is safe until y2106 */ wr32(E1000_TRGTTIML0, ts.tv_nsec); - wr32(E1000_TRGTTIMH0, ts.tv_sec); + wr32(E1000_TRGTTIMH0, (u32)ts.tv_sec); tsauxc = rd32(E1000_TSAUXC); tsauxc |= TSAUXC_EN_TT0; wr32(E1000_TSAUXC, tsauxc); @@ -5426,10 +5427,10 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) if (tsicr & TSINTR_TT1) { spin_lock(&adapter->tmreg_lock); - ts = timespec_add(adapter->perout[1].start, - adapter->perout[1].period); + ts = timespec64_add(adapter->perout[1].start, + adapter->perout[1].period); wr32(E1000_TRGTTIML1, ts.tv_nsec); - wr32(E1000_TRGTTIMH1, ts.tv_sec); + wr32(E1000_TRGTTIMH1, (u32)ts.tv_sec); tsauxc = rd32(E1000_TSAUXC); tsauxc |= TSAUXC_EN_TT1; wr32(E1000_TSAUXC, tsauxc); diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 5982f28d521a..c44df87c38de 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -143,7 +143,7 @@ static void igb_ptp_write_i210(struct igb_adapter *adapter, * sub-nanosecond resolution. */ wr32(E1000_SYSTIML, ts->tv_nsec); - wr32(E1000_SYSTIMH, ts->tv_sec); + wr32(E1000_SYSTIMH, (u32)ts->tv_sec); } /** @@ -479,7 +479,7 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, struct e1000_hw *hw = &igb->hw; u32 tsauxc, tsim, tsauxc_mask, tsim_mask, trgttiml, trgttimh, freqout; unsigned long flags; - struct timespec ts; + struct timespec64 ts; int use_freq = 0, pin = -1; s64 ns; @@ -523,14 +523,14 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, } ts.tv_sec = rq->perout.period.sec; ts.tv_nsec = rq->perout.period.nsec; - ns = timespec_to_ns(&ts); + ns = timespec64_to_ns(&ts); ns = ns >> 1; if (on && ns <= 70000000LL) { if (ns < 8LL) return -EINVAL; use_freq = 1; } - ts = ns_to_timespec(ns); + ts = ns_to_timespec64(ns); if (rq->perout.index == 1) { if (use_freq) { tsauxc_mask = TSAUXC_EN_CLK1 | TSAUXC_ST1; -- cgit v1.2.3 From e253fb74d66428597bd272b2614e8564b882b14c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 30 Sep 2015 13:26:34 +0200 Subject: mwifiex: use ktime_get_real for timestamping The mwifiex_11n_aggregate_pkt() function creates a ktime_t from a timeval returned by do_gettimeofday, which is slow and causes an overflow in 2038 on 32-bit architectures. This solves both problems by using the appropriate ktime_get_real() function. Signed-off-by: Arnd Bergmann Cc: Amitkumar Karwar Cc: Nishant Sarmukadam Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/wireless/mwifiex/11n_aggr.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index f7c717253a66..78853c51774d 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -173,7 +173,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, int pad = 0, aggr_num = 0, ret; struct mwifiex_tx_param tx_param; struct txpd *ptx_pd = NULL; - struct timeval tv; int headroom = adapter->iface_type == MWIFIEX_USB ? 0 : INTF_HEADER_LEN; skb_src = skb_peek(&pra_list->skb_head); @@ -203,8 +202,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT; skb_aggr->priority = skb_src->priority; - do_gettimeofday(&tv); - skb_aggr->tstamp = timeval_to_ktime(tv); + skb_aggr->tstamp = ktime_get_real(); do { /* Check if AMSDU can accommodate this MSDU */ -- cgit v1.2.3 From 52f4f91893955c359885d022b2142e2326f020a1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 30 Sep 2015 13:26:35 +0200 Subject: mwifiex: avoid gettimeofday in ba_threshold setting mwifiex_get_random_ba_threshold() uses a complex homegrown implementation to generate a pseudo-random number from the current time as returned from do_gettimeofday(). This currently requires two 32-bit divisions plus a couple of other computations that are eventually discarded as only eight bits of the microsecond portion are used at all. We could replace this with a call to get_random_bytes(), but that might drain the entropy pool too fast if this is called for each packet. Instead, this patch converts it to use ktime_get_ns(), which is a bit faster than do_gettimeofday(), and then uses a similar algorithm as before, but in a way that takes both the nanosecond and second portion into account for slightly-more-but-still-not-very-random pseudorandom number. Signed-off-by: Arnd Bergmann Cc: Amitkumar Karwar Cc: Nishant Sarmukadam Cc: Kalle Valo Cc: linux-wireless@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/wireless/mwifiex/wmm.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 173d3663c2e0..878d358063dc 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -117,22 +117,15 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra) */ static u8 mwifiex_get_random_ba_threshold(void) { - u32 sec, usec; - struct timeval ba_tstamp; - u8 ba_threshold; - + u64 ns; /* setup ba_packet_threshold here random number between * [BA_SETUP_PACKET_OFFSET, * BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1] */ + ns = ktime_get_ns(); + ns += (ns >> 32) + (ns >> 16); - do_gettimeofday(&ba_tstamp); - sec = (ba_tstamp.tv_sec & 0xFFFF) + (ba_tstamp.tv_sec >> 16); - usec = (ba_tstamp.tv_usec & 0xFFFF) + (ba_tstamp.tv_usec >> 16); - ba_threshold = (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD) - + BA_SETUP_PACKET_OFFSET; - - return ba_threshold; + return ((u8)ns % BA_SETUP_MAX_PACKET_THRESHOLD) + BA_SETUP_PACKET_OFFSET; } /* -- cgit v1.2.3 From 3947d78a547845fa5a129a39ce0abac2352f7a3a Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Wed, 30 Sep 2015 08:52:38 -0500 Subject: amd-xgbe: Remove an unneeded semicolon on a switch statement Remove an unneeded semicolon at the end of a switch statement block. Reported-by: kbuild test robot Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index a4473d8ff4fa..553e251fcc95 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -2224,7 +2224,7 @@ static u64 xgbe_mmc_read(struct xgbe_prv_data *pdata, unsigned int reg_lo) default: read_hi = false; - }; + } val = XGMAC_IOREAD(pdata, reg_lo); -- cgit v1.2.3 From 47f2e6c27553d9a164bb0067f4c1f9bbba388c2e Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Wed, 30 Sep 2015 08:52:45 -0500 Subject: amd-xgbe: Use proper DT / ACPI precedence checking Device tree presence takes precedence over ACPI in the device_* APIs. The amd-xgbe driver should follow the same precedence. Update the check on whether to use DT / ACPI to follow this. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index e83bd76abce6..7dd893331785 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -371,7 +371,7 @@ static int xgbe_probe(struct platform_device *pdev) set_bit(XGBE_DOWN, &pdata->dev_state); /* Check if we should use ACPI or DT */ - pdata->use_acpi = (!pdata->adev || acpi_disabled) ? 0 : 1; + pdata->use_acpi = dev->of_node ? 0 : 1; phy_pdev = xgbe_get_phy_pdev(pdata); if (!phy_pdev) { -- cgit v1.2.3 From 349fb2d7008caa752919e394fb202545b5f72c67 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Wed, 30 Sep 2015 08:52:51 -0500 Subject: amd-xgbe: Add ethtool support for setting the msglevel Provide the ethtool functions to support getting and setting the msglevel for the driver. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c index 59e090e95c0e..29db64b08d52 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c @@ -388,6 +388,20 @@ static void xgbe_get_drvinfo(struct net_device *netdev, drvinfo->n_stats = XGBE_STATS_COUNT; } +static u32 xgbe_get_msglevel(struct net_device *netdev) +{ + struct xgbe_prv_data *pdata = netdev_priv(netdev); + + return pdata->msg_enable; +} + +static void xgbe_set_msglevel(struct net_device *netdev, u32 msglevel) +{ + struct xgbe_prv_data *pdata = netdev_priv(netdev); + + pdata->msg_enable = msglevel; +} + static int xgbe_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec) { @@ -594,6 +608,8 @@ static const struct ethtool_ops xgbe_ethtool_ops = { .get_settings = xgbe_get_settings, .set_settings = xgbe_set_settings, .get_drvinfo = xgbe_get_drvinfo, + .get_msglevel = xgbe_get_msglevel, + .set_msglevel = xgbe_set_msglevel, .get_link = ethtool_op_get_link, .get_coalesce = xgbe_get_coalesce, .set_coalesce = xgbe_set_coalesce, -- cgit v1.2.3 From e5dd8b81107881f8928378a38f6e47aa2da62c37 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Wed, 30 Sep 2015 08:52:57 -0500 Subject: amd-xgbe: Add ethtool error and debug messages Add error and dynamic debug messages to various ethtool functions in the driver while also removing the DBGPR debug print calls. Also, change the message level for some error messages from alert to err. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 89 ++++++++++++---------------- 1 file changed, 37 insertions(+), 52 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c index 29db64b08d52..95b63730aa58 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c @@ -187,8 +187,6 @@ static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data) { int i; - DBGPR("-->%s\n", __func__); - switch (stringset) { case ETH_SS_STATS: for (i = 0; i < XGBE_STATS_COUNT; i++) { @@ -198,8 +196,6 @@ static void xgbe_get_strings(struct net_device *netdev, u32 stringset, u8 *data) } break; } - - DBGPR("<--%s\n", __func__); } static void xgbe_get_ethtool_stats(struct net_device *netdev, @@ -209,23 +205,17 @@ static void xgbe_get_ethtool_stats(struct net_device *netdev, u8 *stat; int i; - DBGPR("-->%s\n", __func__); - pdata->hw_if.read_mmc_stats(pdata); for (i = 0; i < XGBE_STATS_COUNT; i++) { stat = (u8 *)pdata + xgbe_gstring_stats[i].stat_offset; *data++ = *(u64 *)stat; } - - DBGPR("<--%s\n", __func__); } static int xgbe_get_sset_count(struct net_device *netdev, int stringset) { int ret; - DBGPR("-->%s\n", __func__); - switch (stringset) { case ETH_SS_STATS: ret = XGBE_STATS_COUNT; @@ -235,8 +225,6 @@ static int xgbe_get_sset_count(struct net_device *netdev, int stringset) ret = -EOPNOTSUPP; } - DBGPR("<--%s\n", __func__); - return ret; } @@ -245,13 +233,9 @@ static void xgbe_get_pauseparam(struct net_device *netdev, { struct xgbe_prv_data *pdata = netdev_priv(netdev); - DBGPR("-->xgbe_get_pauseparam\n"); - pause->autoneg = pdata->phy.pause_autoneg; pause->tx_pause = pdata->phy.tx_pause; pause->rx_pause = pdata->phy.rx_pause; - - DBGPR("<--xgbe_get_pauseparam\n"); } static int xgbe_set_pauseparam(struct net_device *netdev, @@ -260,13 +244,11 @@ static int xgbe_set_pauseparam(struct net_device *netdev, struct xgbe_prv_data *pdata = netdev_priv(netdev); int ret = 0; - DBGPR("-->xgbe_set_pauseparam\n"); - - DBGPR(" autoneg = %d, tx_pause = %d, rx_pause = %d\n", - pause->autoneg, pause->tx_pause, pause->rx_pause); - - if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) + if (pause->autoneg && (pdata->phy.autoneg != AUTONEG_ENABLE)) { + netdev_err(netdev, + "autoneg disabled, pause autoneg not avialable\n"); return -EINVAL; + } pdata->phy.pause_autoneg = pause->autoneg; pdata->phy.tx_pause = pause->tx_pause; @@ -286,8 +268,6 @@ static int xgbe_set_pauseparam(struct net_device *netdev, if (netif_running(netdev)) ret = pdata->phy_if.phy_config_aneg(pdata); - DBGPR("<--xgbe_set_pauseparam\n"); - return ret; } @@ -296,8 +276,6 @@ static int xgbe_get_settings(struct net_device *netdev, { struct xgbe_prv_data *pdata = netdev_priv(netdev); - DBGPR("-->xgbe_get_settings\n"); - cmd->phy_address = pdata->phy.address; cmd->supported = pdata->phy.supported; @@ -311,8 +289,6 @@ static int xgbe_get_settings(struct net_device *netdev, cmd->port = PORT_NONE; cmd->transceiver = XCVR_INTERNAL; - DBGPR("<--xgbe_get_settings\n"); - return 0; } @@ -323,16 +299,20 @@ static int xgbe_set_settings(struct net_device *netdev, u32 speed; int ret; - DBGPR("-->xgbe_set_settings\n"); - speed = ethtool_cmd_speed(cmd); - if (cmd->phy_address != pdata->phy.address) + if (cmd->phy_address != pdata->phy.address) { + netdev_err(netdev, "invalid phy address %hhu\n", + cmd->phy_address); return -EINVAL; + } if ((cmd->autoneg != AUTONEG_ENABLE) && - (cmd->autoneg != AUTONEG_DISABLE)) + (cmd->autoneg != AUTONEG_DISABLE)) { + netdev_err(netdev, "unsupported autoneg %hhu\n", + cmd->autoneg); return -EINVAL; + } if (cmd->autoneg == AUTONEG_DISABLE) { switch (speed) { @@ -341,16 +321,27 @@ static int xgbe_set_settings(struct net_device *netdev, case SPEED_1000: break; default: + netdev_err(netdev, "unsupported speed %u\n", speed); return -EINVAL; } - if (cmd->duplex != DUPLEX_FULL) + if (cmd->duplex != DUPLEX_FULL) { + netdev_err(netdev, "unsupported duplex %hhu\n", + cmd->duplex); return -EINVAL; + } } + netif_dbg(pdata, link, netdev, + "requested advertisement %#x, phy supported %#x\n", + cmd->advertising, pdata->phy.supported); + cmd->advertising &= pdata->phy.supported; - if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising) + if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising) { + netdev_err(netdev, + "unsupported requested advertisement\n"); return -EINVAL; + } ret = 0; pdata->phy.autoneg = cmd->autoneg; @@ -366,8 +357,6 @@ static int xgbe_set_settings(struct net_device *netdev, if (netif_running(netdev)) ret = pdata->phy_if.phy_config_aneg(pdata); - DBGPR("<--xgbe_set_settings\n"); - return ret; } @@ -407,8 +396,6 @@ static int xgbe_get_coalesce(struct net_device *netdev, { struct xgbe_prv_data *pdata = netdev_priv(netdev); - DBGPR("-->xgbe_get_coalesce\n"); - memset(ec, 0, sizeof(struct ethtool_coalesce)); ec->rx_coalesce_usecs = pdata->rx_usecs; @@ -416,8 +403,6 @@ static int xgbe_get_coalesce(struct net_device *netdev, ec->tx_max_coalesced_frames = pdata->tx_frames; - DBGPR("<--xgbe_get_coalesce\n"); - return 0; } @@ -429,8 +414,6 @@ static int xgbe_set_coalesce(struct net_device *netdev, unsigned int rx_frames, rx_riwt, rx_usecs; unsigned int tx_frames; - DBGPR("-->xgbe_set_coalesce\n"); - /* Check for not supported parameters */ if ((ec->rx_coalesce_usecs_irq) || (ec->rx_max_coalesced_frames_irq) || @@ -450,8 +433,10 @@ static int xgbe_set_coalesce(struct net_device *netdev, (ec->rx_max_coalesced_frames_high) || (ec->tx_coalesce_usecs_high) || (ec->tx_max_coalesced_frames_high) || - (ec->rate_sample_interval)) + (ec->rate_sample_interval)) { + netdev_err(netdev, "unsupported coalescing parameter\n"); return -EOPNOTSUPP; + } rx_riwt = hw_if->usec_to_riwt(pdata, ec->rx_coalesce_usecs); rx_usecs = ec->rx_coalesce_usecs; @@ -463,13 +448,13 @@ static int xgbe_set_coalesce(struct net_device *netdev, /* Check the bounds of values for Rx */ if (rx_riwt > XGMAC_MAX_DMA_RIWT) { - netdev_alert(netdev, "rx-usec is limited to %d usecs\n", - hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT)); + netdev_err(netdev, "rx-usec is limited to %d usecs\n", + hw_if->riwt_to_usec(pdata, XGMAC_MAX_DMA_RIWT)); return -EINVAL; } if (rx_frames > pdata->rx_desc_count) { - netdev_alert(netdev, "rx-frames is limited to %d frames\n", - pdata->rx_desc_count); + netdev_err(netdev, "rx-frames is limited to %d frames\n", + pdata->rx_desc_count); return -EINVAL; } @@ -477,8 +462,8 @@ static int xgbe_set_coalesce(struct net_device *netdev, /* Check the bounds of values for Tx */ if (tx_frames > pdata->tx_desc_count) { - netdev_alert(netdev, "tx-frames is limited to %d frames\n", - pdata->tx_desc_count); + netdev_err(netdev, "tx-frames is limited to %d frames\n", + pdata->tx_desc_count); return -EINVAL; } @@ -490,8 +475,6 @@ static int xgbe_set_coalesce(struct net_device *netdev, pdata->tx_frames = tx_frames; hw_if->config_tx_coalesce(pdata); - DBGPR("<--xgbe_set_coalesce\n"); - return 0; } @@ -553,8 +536,10 @@ static int xgbe_set_rxfh(struct net_device *netdev, const u32 *indir, struct xgbe_hw_if *hw_if = &pdata->hw_if; unsigned int ret; - if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) + if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) { + netdev_err(netdev, "unsupported hash function\n"); return -EOPNOTSUPP; + } if (indir) { ret = hw_if->set_rss_lookup_table(pdata, indir); -- cgit v1.2.3 From 9c439e4b730f0d519821527afd697e6af99a67ab Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Wed, 30 Sep 2015 08:53:03 -0500 Subject: amd-xgbe: Simplify calculation and setting of queue fifos The calculation of the Tx and Rx fifo sizes can be calculated rather than hardcoded in a switch statement. Additionally, the per-queue fifo sizes can be calculated rather than hardcoded using if/else if statements that can possibly underutilize the available fifo area. Change the code to calculate the fifo sizes and the per-queue fifo sizes to simplify the code and make best use of the available fifo. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 81 ++++++-------------------------- drivers/net/ethernet/amd/xgbe/xgbe.h | 16 ------- 2 files changed, 14 insertions(+), 83 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 553e251fcc95..45512242baea 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -1940,84 +1940,31 @@ static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata) static unsigned int xgbe_calculate_per_queue_fifo(unsigned int fifo_size, unsigned int queue_count) { - unsigned int q_fifo_size = 0; - enum xgbe_mtl_fifo_size p_fifo = XGMAC_MTL_FIFO_SIZE_256; + unsigned int q_fifo_size; + unsigned int p_fifo; - /* Calculate Tx/Rx fifo share per queue */ - switch (fifo_size) { - case 0: - q_fifo_size = XGBE_FIFO_SIZE_B(128); - break; - case 1: - q_fifo_size = XGBE_FIFO_SIZE_B(256); - break; - case 2: - q_fifo_size = XGBE_FIFO_SIZE_B(512); - break; - case 3: - q_fifo_size = XGBE_FIFO_SIZE_KB(1); - break; - case 4: - q_fifo_size = XGBE_FIFO_SIZE_KB(2); - break; - case 5: - q_fifo_size = XGBE_FIFO_SIZE_KB(4); - break; - case 6: - q_fifo_size = XGBE_FIFO_SIZE_KB(8); - break; - case 7: - q_fifo_size = XGBE_FIFO_SIZE_KB(16); - break; - case 8: - q_fifo_size = XGBE_FIFO_SIZE_KB(32); - break; - case 9: - q_fifo_size = XGBE_FIFO_SIZE_KB(64); - break; - case 10: - q_fifo_size = XGBE_FIFO_SIZE_KB(128); - break; - case 11: - q_fifo_size = XGBE_FIFO_SIZE_KB(256); - break; - } + /* Calculate the configured fifo size */ + q_fifo_size = 1 << (fifo_size + 7); - /* The configured value is not the actual amount of fifo RAM */ + /* The configured value may not be the actual amount of fifo RAM */ q_fifo_size = min_t(unsigned int, XGBE_FIFO_MAX, q_fifo_size); q_fifo_size = q_fifo_size / queue_count; - /* Set the queue fifo size programmable value */ - if (q_fifo_size >= XGBE_FIFO_SIZE_KB(256)) - p_fifo = XGMAC_MTL_FIFO_SIZE_256K; - else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(128)) - p_fifo = XGMAC_MTL_FIFO_SIZE_128K; - else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(64)) - p_fifo = XGMAC_MTL_FIFO_SIZE_64K; - else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(32)) - p_fifo = XGMAC_MTL_FIFO_SIZE_32K; - else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(16)) - p_fifo = XGMAC_MTL_FIFO_SIZE_16K; - else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(8)) - p_fifo = XGMAC_MTL_FIFO_SIZE_8K; - else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(4)) - p_fifo = XGMAC_MTL_FIFO_SIZE_4K; - else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(2)) - p_fifo = XGMAC_MTL_FIFO_SIZE_2K; - else if (q_fifo_size >= XGBE_FIFO_SIZE_KB(1)) - p_fifo = XGMAC_MTL_FIFO_SIZE_1K; - else if (q_fifo_size >= XGBE_FIFO_SIZE_B(512)) - p_fifo = XGMAC_MTL_FIFO_SIZE_512; - else if (q_fifo_size >= XGBE_FIFO_SIZE_B(256)) - p_fifo = XGMAC_MTL_FIFO_SIZE_256; + /* Each increment in the queue fifo size represents 256 bytes of + * fifo, with 0 representing 256 bytes. Distribute the fifo equally + * between the queues. + */ + p_fifo = q_fifo_size / 256; + if (p_fifo) + p_fifo--; return p_fifo; } static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata) { - enum xgbe_mtl_fifo_size fifo_size; + unsigned int fifo_size; unsigned int i; fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.tx_fifo_size, @@ -2033,7 +1980,7 @@ static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata) static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata) { - enum xgbe_mtl_fifo_size fifo_size; + unsigned int fifo_size; unsigned int i; fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.rx_fifo_size, diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 8c9d01ef730d..5f9a1ab1e387 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -209,8 +209,6 @@ #define XGMAC_IOCTL_CONTEXT 2 #define XGBE_FIFO_MAX 81920 -#define XGBE_FIFO_SIZE_B(x) (x) -#define XGBE_FIFO_SIZE_KB(x) (x * 1024) #define XGBE_TC_MIN_QUANTUM 10 @@ -483,20 +481,6 @@ enum xgbe_int_state { XGMAC_INT_STATE_RESTORE, }; -enum xgbe_mtl_fifo_size { - XGMAC_MTL_FIFO_SIZE_256 = 0x00, - XGMAC_MTL_FIFO_SIZE_512 = 0x01, - XGMAC_MTL_FIFO_SIZE_1K = 0x03, - XGMAC_MTL_FIFO_SIZE_2K = 0x07, - XGMAC_MTL_FIFO_SIZE_4K = 0x0f, - XGMAC_MTL_FIFO_SIZE_8K = 0x1f, - XGMAC_MTL_FIFO_SIZE_16K = 0x3f, - XGMAC_MTL_FIFO_SIZE_32K = 0x7f, - XGMAC_MTL_FIFO_SIZE_64K = 0xff, - XGMAC_MTL_FIFO_SIZE_128K = 0x1ff, - XGMAC_MTL_FIFO_SIZE_256K = 0x3ff, -}; - enum xgbe_speed { XGBE_SPEED_1000 = 0, XGBE_SPEED_2500, -- cgit v1.2.3 From 72c9ac4e1f4faf1f4e7252319ab8af2517891ae5 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Wed, 30 Sep 2015 08:53:10 -0500 Subject: amd-xgbe: Add receive buffer unavailable statistic Add a statistic that tracks how many times an interrupt is generated for a receive buffer not being available to the hardware which prevents the hardware from being able to DMA the received data. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 3 +++ drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 1 + drivers/net/ethernet/amd/xgbe/xgbe.h | 1 + 3 files changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index aae9d5ecd182..24212d256a01 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -360,6 +360,9 @@ static irqreturn_t xgbe_isr(int irq, void *data) } } + if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RBU)) + pdata->ext_stats.rx_buffer_unavailable++; + /* Restart the device on a Fatal Bus Error */ if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, FBE)) schedule_work(&pdata->restart_work); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c index 95b63730aa58..204fb3afb182 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c @@ -179,6 +179,7 @@ static const struct xgbe_stats xgbe_gstring_stats[] = { XGMAC_MMC_STAT("rx_watchdog_errors", rxwatchdogerror), XGMAC_MMC_STAT("rx_pause_frames", rxpauseframes), XGMAC_EXT_STAT("rx_split_header_packets", rx_split_header_packets), + XGMAC_EXT_STAT("rx_buffer_unavailable", rx_buffer_unavailable), }; #define XGBE_STATS_COUNT ARRAY_SIZE(xgbe_gstring_stats) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 5f9a1ab1e387..a5f5a7869609 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -582,6 +582,7 @@ struct xgbe_mmc_stats { struct xgbe_ext_stats { u64 tx_tso_packets; u64 rx_split_header_packets; + u64 rx_buffer_unavailable; }; struct xgbe_hw_if { -- cgit v1.2.3 From afb43e8a0af18fa959e9ef09abfa969c3c83f4ef Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Wed, 30 Sep 2015 08:53:16 -0500 Subject: amd-xgbe: Use device workqueue instead of system workqueue The driver creates, flushes and destroys a device workqueue but queues work to the system workqueue. Switch from using the system workqueue to the device workqueue. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 24212d256a01..14bad8c44c87 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -365,7 +365,7 @@ static irqreturn_t xgbe_isr(int irq, void *data) /* Restart the device on a Fatal Bus Error */ if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, FBE)) - schedule_work(&pdata->restart_work); + queue_work(pdata->dev_workqueue, &pdata->restart_work); /* Clear all interrupt signals */ XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_ch_isr); @@ -387,7 +387,8 @@ static irqreturn_t xgbe_isr(int irq, void *data) /* Read Tx Timestamp to clear interrupt */ pdata->tx_tstamp = hw_if->get_tx_tstamp(pdata); - schedule_work(&pdata->tx_tstamp_work); + queue_work(pdata->dev_workqueue, + &pdata->tx_tstamp_work); } } } @@ -453,7 +454,7 @@ static void xgbe_service_timer(unsigned long data) { struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data; - schedule_work(&pdata->service_work); + queue_work(pdata->dev_workqueue, &pdata->service_work); mod_timer(&pdata->service_timer, jiffies + HZ); } @@ -894,7 +895,7 @@ static int xgbe_start(struct xgbe_prv_data *pdata) netif_tx_start_all_queues(netdev); xgbe_start_timers(pdata); - schedule_work(&pdata->service_work); + queue_work(pdata->dev_workqueue, &pdata->service_work); DBGPR("<--xgbe_start\n"); @@ -1536,7 +1537,7 @@ static void xgbe_tx_timeout(struct net_device *netdev) struct xgbe_prv_data *pdata = netdev_priv(netdev); netdev_warn(netdev, "tx timeout, device restarting\n"); - schedule_work(&pdata->restart_work); + queue_work(pdata->dev_workqueue, &pdata->restart_work); } static struct rtnl_link_stats64 *xgbe_get_stats64(struct net_device *netdev, -- cgit v1.2.3 From 50789845cfc37d5331b56e1a566ddc95aeac0a7d Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Wed, 30 Sep 2015 08:53:22 -0500 Subject: amd-xgbe: Remove the XGBE_LINK state bit The XGBE_LINK bit is used just to determine whether to call the netif_carrier_on/off functions. Rather than define and use this bit, just call the functions. The netif_carrier_ok function can be used in place of checking the XGBE_LINK bit in the future. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 16 ++++------------ drivers/net/ethernet/amd/xgbe/xgbe.h | 1 - 2 files changed, 4 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index 9088c3a35a20..446058081866 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -1115,8 +1115,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata) unsigned int reg, link_aneg; if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) { - if (test_and_clear_bit(XGBE_LINK, &pdata->dev_state)) - netif_carrier_off(pdata->netdev); + netif_carrier_off(pdata->netdev); pdata->phy.link = 0; goto adjust_link; @@ -1142,10 +1141,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata) if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) clear_bit(XGBE_LINK_INIT, &pdata->dev_state); - if (!test_bit(XGBE_LINK, &pdata->dev_state)) { - set_bit(XGBE_LINK, &pdata->dev_state); - netif_carrier_on(pdata->netdev); - } + netif_carrier_on(pdata->netdev); } else { if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) { xgbe_check_link_timeout(pdata); @@ -1156,10 +1152,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata) xgbe_phy_status_aneg(pdata); - if (test_bit(XGBE_LINK, &pdata->dev_state)) { - clear_bit(XGBE_LINK, &pdata->dev_state); - netif_carrier_off(pdata->netdev); - } + netif_carrier_off(pdata->netdev); } adjust_link: @@ -1179,8 +1172,7 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata) devm_free_irq(pdata->dev, pdata->an_irq, pdata); pdata->phy.link = 0; - if (test_and_clear_bit(XGBE_LINK, &pdata->dev_state)) - netif_carrier_off(pdata->netdev); + netif_carrier_off(pdata->netdev); xgbe_phy_adjust_link(pdata); } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index a5f5a7869609..e234b9970318 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -459,7 +459,6 @@ struct xgbe_channel { enum xgbe_state { XGBE_DOWN, - XGBE_LINK, XGBE_LINK_INIT, XGBE_LINK_ERR, }; -- cgit v1.2.3 From f6194bcf03e40bc6b6094f11289d87b605fb326d Mon Sep 17 00:00:00 2001 From: "David B. Robins" Date: Wed, 30 Sep 2015 16:20:04 -0400 Subject: net: usb: asix: Fix crash on skb alloc failure If asix_rx_fixup_internal() fails to allocate rx->ax_skb, it will return but not clear rx->size. rx points to driver private data. A later call assumes that nonzero size means ax_skb was allocated and passes a null ax_skb to skb_put. Changed allocation failure return to clear size first. Found testing board with AX88772B devices. Signed-off-by: David B. Robins Signed-off-by: David S. Miller --- drivers/net/usb/asix_common.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 75d6f26729a3..079069a060a6 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -91,8 +91,10 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, } rx->ax_skb = netdev_alloc_skb_ip_align(dev->net, rx->size); - if (!rx->ax_skb) + if (!rx->ax_skb) { + rx->size = 0; return 0; + } } if (rx->size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) { -- cgit v1.2.3 From 33a8316d9cda4368e7cb477fff36c9ee35d4164e Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Thu, 1 Oct 2015 00:37:43 +0300 Subject: net: lpc_eth: fix warnings caused by enabling unprepared clock If common clock framework is configured, the driver generates warnings, which are fixed by this change: WARNING: CPU: 0 PID: 1 at linux/drivers/clk/clk.c:727 clk_core_enable+0x2c/0xa4() Modules linked in: CPU: 0 PID: 1 Comm: swapper Not tainted 4.3.0-rc2+ #141 Hardware name: LPC32XX SoC (Flattened Device Tree) Backtrace: [<>] (dump_backtrace) from [<>] (show_stack+0x18/0x1c) [<>] (show_stack) from [<>] (dump_stack+0x20/0x28) [<>] (dump_stack) from [<>] (warn_slowpath_common+0x90/0xb8) [<>] (warn_slowpath_common) from [<>] (warn_slowpath_null+0x24/0x2c) [<>] (warn_slowpath_null) from [<>] (clk_core_enable+0x2c/0xa4) [<>] (clk_core_enable) from [<>] (clk_enable+0x24/0x38) [<>] (clk_enable) from [<>] (lpc_eth_drv_probe+0xfc/0x99c) [<>] (lpc_eth_drv_probe) from [<>] (platform_drv_probe+0x50/0xa0) [<>] (platform_drv_probe) from [<>] (driver_probe_device+0x18c/0x408) [<>] (driver_probe_device) from [<>] (__driver_attach+0x70/0x94) [<>] (__driver_attach) from [<>] (bus_for_each_dev+0x74/0x98) [<>] (bus_for_each_dev) from [<>] (driver_attach+0x20/0x28) [<>] (driver_attach) from [<>] (bus_add_driver+0x11c/0x248) [<>] (bus_add_driver) from [<>] (driver_register+0xa4/0xe8) [<>] (driver_register) from [<>] (__platform_driver_register+0x50/0x64) [<>] (__platform_driver_register) from [<>] (lpc_eth_driver_init+0x18/0x20) [<>] (lpc_eth_driver_init) from [<>] (do_one_initcall+0x11c/0x1dc) [<>] (do_one_initcall) from [<>] (kernel_init_freeable+0x10c/0x1d4) [<>] (kernel_init_freeable) from [<>] (kernel_init+0x10/0xec) [<>] (kernel_init) from [<>] (ret_from_fork+0x14/0x24) Signed-off-by: Vladimir Zapolskiy Signed-off-by: David S. Miller --- drivers/net/ethernet/nxp/lpc_eth.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 66fd868152e5..b159ef8303cc 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -476,13 +476,12 @@ static void __lpc_get_mac(struct netdata_local *pldat, u8 *mac) mac[5] = tmp >> 8; } -static void __lpc_eth_clock_enable(struct netdata_local *pldat, - bool enable) +static void __lpc_eth_clock_enable(struct netdata_local *pldat, bool enable) { if (enable) - clk_enable(pldat->clk); + clk_prepare_enable(pldat->clk); else - clk_disable(pldat->clk); + clk_disable_unprepare(pldat->clk); } static void __lpc_params_setup(struct netdata_local *pldat) @@ -1494,7 +1493,7 @@ err_out_free_irq: err_out_iounmap: iounmap(pldat->net_base); err_out_disable_clocks: - clk_disable(pldat->clk); + clk_disable_unprepare(pldat->clk); clk_put(pldat->clk); err_out_free_dev: free_netdev(ndev); @@ -1519,7 +1518,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev) iounmap(pldat->net_base); mdiobus_unregister(pldat->mii_bus); mdiobus_free(pldat->mii_bus); - clk_disable(pldat->clk); + clk_disable_unprepare(pldat->clk); clk_put(pldat->clk); free_netdev(ndev); @@ -1540,7 +1539,7 @@ static int lpc_eth_drv_suspend(struct platform_device *pdev, if (netif_running(ndev)) { netif_device_detach(ndev); __lpc_eth_shutdown(pldat); - clk_disable(pldat->clk); + clk_disable_unprepare(pldat->clk); /* * Reset again now clock is disable to be sure -- cgit v1.2.3 From 6645d5e441db9121793421d477255f4242b3dbf3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 15 Sep 2015 09:58:53 +0200 Subject: iwlwifi: mvm: fix D3 CCMP TX PN assignment When going into/coming out of D3, the TX PN must be programmed into and restored from the firmware respectively. The restore was broken due to my previous commit to move PN assignment into the driver. Sending the PN to the firmware still worked since we now use the counter that's shared with mac80211, but accessing it through the mac80211 API makes no sense now. Fix this by reading/writing the counter directly. This actually simplifies the code since we don't need to round-trip through the key_seq structure. Fixes: ca8c0f4bede6 ("iwlwifi: mvm: move TX PN assignment for CCMP to the driver") Cc: [4.1+] Reported-by: Luca Coelho Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/d3.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 04264e417c1c..9578b9d663dc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -274,18 +274,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, break; case WLAN_CIPHER_SUITE_CCMP: if (sta) { - u8 *pn = seq.ccmp.pn; + u64 pn64; aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc; aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc; - ieee80211_get_key_tx_seq(key, &seq); - aes_tx_sc->pn = cpu_to_le64((u64)pn[5] | - ((u64)pn[4] << 8) | - ((u64)pn[3] << 16) | - ((u64)pn[2] << 24) | - ((u64)pn[1] << 32) | - ((u64)pn[0] << 40)); + pn64 = atomic64_read(&key->tx_pn); + aes_tx_sc->pn = cpu_to_le64(pn64); } else { aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc; } @@ -1453,15 +1448,15 @@ static void iwl_mvm_d3_update_gtks(struct ieee80211_hw *hw, switch (key->cipher) { case WLAN_CIPHER_SUITE_CCMP: - iwl_mvm_aes_sc_to_seq(&sc->aes.tsc, &seq); iwl_mvm_set_aes_rx_seq(sc->aes.unicast_rsc, key); + atomic64_set(&key->tx_pn, le64_to_cpu(sc->aes.tsc.pn)); break; case WLAN_CIPHER_SUITE_TKIP: iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq); iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key); + ieee80211_set_key_tx_seq(key, &seq); break; } - ieee80211_set_key_tx_seq(key, &seq); /* that's it for this key */ return; -- cgit v1.2.3 From 8119c018000bcc2d56e74f5459b7ff1902f96ff8 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Thu, 1 Oct 2015 13:48:45 +0530 Subject: cxgb4 : Update T4/T5/T6 register ranges Update T4/T5/T6 adapter register ranges so that it doesn't read non existent registers when dumped using ethtool Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 1464 +++++++++++++++++++++------- 1 file changed, 1134 insertions(+), 330 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 44806253c178..dc6ce31a8320 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -699,50 +699,107 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) { static const unsigned int t4_reg_ranges[] = { 0x1008, 0x1108, - 0x1180, 0x11b4, + 0x1180, 0x1184, + 0x1190, 0x1194, + 0x11a0, 0x11a4, + 0x11b0, 0x11b4, 0x11fc, 0x123c, 0x1300, 0x173c, 0x1800, 0x18fc, - 0x3000, 0x305c, - 0x3068, 0x30d8, - 0x30e0, 0x5924, - 0x5960, 0x59d4, - 0x5a00, 0x5af8, + 0x3000, 0x30d8, + 0x30e0, 0x30e4, + 0x30ec, 0x5910, + 0x5920, 0x5924, + 0x5960, 0x5960, + 0x5968, 0x5968, + 0x5970, 0x5970, + 0x5978, 0x5978, + 0x5980, 0x5980, + 0x5988, 0x5988, + 0x5990, 0x5990, + 0x5998, 0x5998, + 0x59a0, 0x59d4, + 0x5a00, 0x5ae0, + 0x5ae8, 0x5ae8, + 0x5af0, 0x5af0, + 0x5af8, 0x5af8, 0x6000, 0x6098, 0x6100, 0x6150, 0x6200, 0x6208, 0x6240, 0x6248, - 0x6280, 0x6338, + 0x6280, 0x62b0, + 0x62c0, 0x6338, 0x6370, 0x638c, 0x6400, 0x643c, 0x6500, 0x6524, - 0x6a00, 0x6a38, - 0x6a60, 0x6a78, - 0x6b00, 0x6b84, - 0x6bf0, 0x6c84, - 0x6cf0, 0x6d84, - 0x6df0, 0x6e84, - 0x6ef0, 0x6f84, - 0x6ff0, 0x7084, - 0x70f0, 0x7184, - 0x71f0, 0x7284, - 0x72f0, 0x7384, - 0x73f0, 0x7450, + 0x6a00, 0x6a04, + 0x6a14, 0x6a38, + 0x6a60, 0x6a70, + 0x6a78, 0x6a78, + 0x6b00, 0x6b0c, + 0x6b1c, 0x6b84, + 0x6bf0, 0x6bf8, + 0x6c00, 0x6c0c, + 0x6c1c, 0x6c84, + 0x6cf0, 0x6cf8, + 0x6d00, 0x6d0c, + 0x6d1c, 0x6d84, + 0x6df0, 0x6df8, + 0x6e00, 0x6e0c, + 0x6e1c, 0x6e84, + 0x6ef0, 0x6ef8, + 0x6f00, 0x6f0c, + 0x6f1c, 0x6f84, + 0x6ff0, 0x6ff8, + 0x7000, 0x700c, + 0x701c, 0x7084, + 0x70f0, 0x70f8, + 0x7100, 0x710c, + 0x711c, 0x7184, + 0x71f0, 0x71f8, + 0x7200, 0x720c, + 0x721c, 0x7284, + 0x72f0, 0x72f8, + 0x7300, 0x730c, + 0x731c, 0x7384, + 0x73f0, 0x73f8, + 0x7400, 0x7450, 0x7500, 0x7530, - 0x7600, 0x761c, + 0x7600, 0x760c, + 0x7614, 0x761c, 0x7680, 0x76cc, 0x7700, 0x7798, 0x77c0, 0x77fc, 0x7900, 0x79fc, - 0x7b00, 0x7c38, - 0x7d00, 0x7efc, - 0x8dc0, 0x8e1c, + 0x7b00, 0x7b58, + 0x7b60, 0x7b84, + 0x7b8c, 0x7c38, + 0x7d00, 0x7d38, + 0x7d40, 0x7d80, + 0x7d8c, 0x7ddc, + 0x7de4, 0x7e04, + 0x7e10, 0x7e1c, + 0x7e24, 0x7e38, + 0x7e40, 0x7e44, + 0x7e4c, 0x7e78, + 0x7e80, 0x7ea4, + 0x7eac, 0x7edc, + 0x7ee8, 0x7efc, + 0x8dc0, 0x8e04, + 0x8e10, 0x8e1c, 0x8e30, 0x8e78, - 0x8ea0, 0x8f6c, - 0x8fc0, 0x9074, + 0x8ea0, 0x8eb8, + 0x8ec0, 0x8f6c, + 0x8fc0, 0x9008, + 0x9010, 0x9058, + 0x9060, 0x9060, + 0x9068, 0x9074, 0x90fc, 0x90fc, - 0x9400, 0x9458, - 0x9600, 0x96bc, + 0x9400, 0x9408, + 0x9410, 0x9458, + 0x9600, 0x9600, + 0x9608, 0x9638, + 0x9640, 0x96bc, 0x9800, 0x9808, 0x9820, 0x983c, 0x9850, 0x9864, @@ -754,23 +811,42 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x9e80, 0x9eec, 0x9f00, 0x9f6c, 0x9f80, 0x9fec, - 0xd004, 0xd03c, + 0xd004, 0xd004, + 0xd010, 0xd03c, 0xdfc0, 0xdfe0, 0xe000, 0xea7c, - 0xf000, 0x11110, - 0x11118, 0x11190, + 0xf000, 0x11190, 0x19040, 0x1906c, 0x19078, 0x19080, - 0x1908c, 0x19124, - 0x19150, 0x191b0, + 0x1908c, 0x190e4, + 0x190f0, 0x190f8, + 0x19100, 0x19110, + 0x19120, 0x19124, + 0x19150, 0x19194, + 0x1919c, 0x191b0, 0x191d0, 0x191e8, 0x19238, 0x1924c, - 0x193f8, 0x19474, - 0x19490, 0x194f8, - 0x19800, 0x19f4c, - 0x1a000, 0x1a06c, - 0x1a0b0, 0x1a120, - 0x1a128, 0x1a138, + 0x193f8, 0x1943c, + 0x1944c, 0x19474, + 0x19490, 0x194e0, + 0x194f0, 0x194f8, + 0x19800, 0x19c08, + 0x19c10, 0x19c90, + 0x19ca0, 0x19ce4, + 0x19cf0, 0x19d40, + 0x19d50, 0x19d94, + 0x19da0, 0x19de8, + 0x19df0, 0x19e40, + 0x19e50, 0x19e90, + 0x19ea0, 0x19f4c, + 0x1a000, 0x1a004, + 0x1a010, 0x1a06c, + 0x1a0b0, 0x1a0e4, + 0x1a0ec, 0x1a0f4, + 0x1a100, 0x1a108, + 0x1a114, 0x1a120, + 0x1a128, 0x1a130, + 0x1a138, 0x1a138, 0x1a190, 0x1a1c4, 0x1a1fc, 0x1a1fc, 0x1e040, 0x1e04c, @@ -823,9 +899,12 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x1ffc0, 0x1ffc8, 0x20000, 0x2002c, 0x20100, 0x2013c, - 0x20190, 0x201c8, + 0x20190, 0x201a0, + 0x201a8, 0x201b8, + 0x201c4, 0x201c8, 0x20200, 0x20318, - 0x20400, 0x20528, + 0x20400, 0x204b4, + 0x204c0, 0x20528, 0x20540, 0x20614, 0x21000, 0x21040, 0x2104c, 0x21060, @@ -834,22 +913,62 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x21270, 0x21284, 0x212fc, 0x21388, 0x21400, 0x21404, - 0x21500, 0x21518, - 0x2152c, 0x2153c, + 0x21500, 0x21500, + 0x21510, 0x21518, + 0x2152c, 0x21530, + 0x2153c, 0x2153c, 0x21550, 0x21554, 0x21600, 0x21600, - 0x21608, 0x21628, - 0x21630, 0x2163c, + 0x21608, 0x2161c, + 0x21624, 0x21628, + 0x21630, 0x21634, + 0x2163c, 0x2163c, 0x21700, 0x2171c, 0x21780, 0x2178c, - 0x21800, 0x21c38, - 0x21c80, 0x21d7c, + 0x21800, 0x21818, + 0x21820, 0x21828, + 0x21830, 0x21848, + 0x21850, 0x21854, + 0x21860, 0x21868, + 0x21870, 0x21870, + 0x21878, 0x21898, + 0x218a0, 0x218a8, + 0x218b0, 0x218c8, + 0x218d0, 0x218d4, + 0x218e0, 0x218e8, + 0x218f0, 0x218f0, + 0x218f8, 0x21a18, + 0x21a20, 0x21a28, + 0x21a30, 0x21a48, + 0x21a50, 0x21a54, + 0x21a60, 0x21a68, + 0x21a70, 0x21a70, + 0x21a78, 0x21a98, + 0x21aa0, 0x21aa8, + 0x21ab0, 0x21ac8, + 0x21ad0, 0x21ad4, + 0x21ae0, 0x21ae8, + 0x21af0, 0x21af0, + 0x21af8, 0x21c18, + 0x21c20, 0x21c20, + 0x21c28, 0x21c30, + 0x21c38, 0x21c38, + 0x21c80, 0x21c98, + 0x21ca0, 0x21ca8, + 0x21cb0, 0x21cc8, + 0x21cd0, 0x21cd4, + 0x21ce0, 0x21ce8, + 0x21cf0, 0x21cf0, + 0x21cf8, 0x21d7c, 0x21e00, 0x21e04, 0x22000, 0x2202c, 0x22100, 0x2213c, - 0x22190, 0x221c8, + 0x22190, 0x221a0, + 0x221a8, 0x221b8, + 0x221c4, 0x221c8, 0x22200, 0x22318, - 0x22400, 0x22528, + 0x22400, 0x224b4, + 0x224c0, 0x22528, 0x22540, 0x22614, 0x23000, 0x23040, 0x2304c, 0x23060, @@ -858,22 +977,62 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x23270, 0x23284, 0x232fc, 0x23388, 0x23400, 0x23404, - 0x23500, 0x23518, - 0x2352c, 0x2353c, + 0x23500, 0x23500, + 0x23510, 0x23518, + 0x2352c, 0x23530, + 0x2353c, 0x2353c, 0x23550, 0x23554, 0x23600, 0x23600, - 0x23608, 0x23628, - 0x23630, 0x2363c, + 0x23608, 0x2361c, + 0x23624, 0x23628, + 0x23630, 0x23634, + 0x2363c, 0x2363c, 0x23700, 0x2371c, 0x23780, 0x2378c, - 0x23800, 0x23c38, - 0x23c80, 0x23d7c, + 0x23800, 0x23818, + 0x23820, 0x23828, + 0x23830, 0x23848, + 0x23850, 0x23854, + 0x23860, 0x23868, + 0x23870, 0x23870, + 0x23878, 0x23898, + 0x238a0, 0x238a8, + 0x238b0, 0x238c8, + 0x238d0, 0x238d4, + 0x238e0, 0x238e8, + 0x238f0, 0x238f0, + 0x238f8, 0x23a18, + 0x23a20, 0x23a28, + 0x23a30, 0x23a48, + 0x23a50, 0x23a54, + 0x23a60, 0x23a68, + 0x23a70, 0x23a70, + 0x23a78, 0x23a98, + 0x23aa0, 0x23aa8, + 0x23ab0, 0x23ac8, + 0x23ad0, 0x23ad4, + 0x23ae0, 0x23ae8, + 0x23af0, 0x23af0, + 0x23af8, 0x23c18, + 0x23c20, 0x23c20, + 0x23c28, 0x23c30, + 0x23c38, 0x23c38, + 0x23c80, 0x23c98, + 0x23ca0, 0x23ca8, + 0x23cb0, 0x23cc8, + 0x23cd0, 0x23cd4, + 0x23ce0, 0x23ce8, + 0x23cf0, 0x23cf0, + 0x23cf8, 0x23d7c, 0x23e00, 0x23e04, 0x24000, 0x2402c, 0x24100, 0x2413c, - 0x24190, 0x241c8, + 0x24190, 0x241a0, + 0x241a8, 0x241b8, + 0x241c4, 0x241c8, 0x24200, 0x24318, - 0x24400, 0x24528, + 0x24400, 0x244b4, + 0x244c0, 0x24528, 0x24540, 0x24614, 0x25000, 0x25040, 0x2504c, 0x25060, @@ -882,22 +1041,62 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x25270, 0x25284, 0x252fc, 0x25388, 0x25400, 0x25404, - 0x25500, 0x25518, - 0x2552c, 0x2553c, + 0x25500, 0x25500, + 0x25510, 0x25518, + 0x2552c, 0x25530, + 0x2553c, 0x2553c, 0x25550, 0x25554, 0x25600, 0x25600, - 0x25608, 0x25628, - 0x25630, 0x2563c, + 0x25608, 0x2561c, + 0x25624, 0x25628, + 0x25630, 0x25634, + 0x2563c, 0x2563c, 0x25700, 0x2571c, 0x25780, 0x2578c, - 0x25800, 0x25c38, - 0x25c80, 0x25d7c, + 0x25800, 0x25818, + 0x25820, 0x25828, + 0x25830, 0x25848, + 0x25850, 0x25854, + 0x25860, 0x25868, + 0x25870, 0x25870, + 0x25878, 0x25898, + 0x258a0, 0x258a8, + 0x258b0, 0x258c8, + 0x258d0, 0x258d4, + 0x258e0, 0x258e8, + 0x258f0, 0x258f0, + 0x258f8, 0x25a18, + 0x25a20, 0x25a28, + 0x25a30, 0x25a48, + 0x25a50, 0x25a54, + 0x25a60, 0x25a68, + 0x25a70, 0x25a70, + 0x25a78, 0x25a98, + 0x25aa0, 0x25aa8, + 0x25ab0, 0x25ac8, + 0x25ad0, 0x25ad4, + 0x25ae0, 0x25ae8, + 0x25af0, 0x25af0, + 0x25af8, 0x25c18, + 0x25c20, 0x25c20, + 0x25c28, 0x25c30, + 0x25c38, 0x25c38, + 0x25c80, 0x25c98, + 0x25ca0, 0x25ca8, + 0x25cb0, 0x25cc8, + 0x25cd0, 0x25cd4, + 0x25ce0, 0x25ce8, + 0x25cf0, 0x25cf0, + 0x25cf8, 0x25d7c, 0x25e00, 0x25e04, 0x26000, 0x2602c, 0x26100, 0x2613c, - 0x26190, 0x261c8, + 0x26190, 0x261a0, + 0x261a8, 0x261b8, + 0x261c4, 0x261c8, 0x26200, 0x26318, - 0x26400, 0x26528, + 0x26400, 0x264b4, + 0x264c0, 0x26528, 0x26540, 0x26614, 0x27000, 0x27040, 0x2704c, 0x27060, @@ -906,51 +1105,120 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x27270, 0x27284, 0x272fc, 0x27388, 0x27400, 0x27404, - 0x27500, 0x27518, - 0x2752c, 0x2753c, + 0x27500, 0x27500, + 0x27510, 0x27518, + 0x2752c, 0x27530, + 0x2753c, 0x2753c, 0x27550, 0x27554, 0x27600, 0x27600, - 0x27608, 0x27628, - 0x27630, 0x2763c, + 0x27608, 0x2761c, + 0x27624, 0x27628, + 0x27630, 0x27634, + 0x2763c, 0x2763c, 0x27700, 0x2771c, 0x27780, 0x2778c, - 0x27800, 0x27c38, - 0x27c80, 0x27d7c, + 0x27800, 0x27818, + 0x27820, 0x27828, + 0x27830, 0x27848, + 0x27850, 0x27854, + 0x27860, 0x27868, + 0x27870, 0x27870, + 0x27878, 0x27898, + 0x278a0, 0x278a8, + 0x278b0, 0x278c8, + 0x278d0, 0x278d4, + 0x278e0, 0x278e8, + 0x278f0, 0x278f0, + 0x278f8, 0x27a18, + 0x27a20, 0x27a28, + 0x27a30, 0x27a48, + 0x27a50, 0x27a54, + 0x27a60, 0x27a68, + 0x27a70, 0x27a70, + 0x27a78, 0x27a98, + 0x27aa0, 0x27aa8, + 0x27ab0, 0x27ac8, + 0x27ad0, 0x27ad4, + 0x27ae0, 0x27ae8, + 0x27af0, 0x27af0, + 0x27af8, 0x27c18, + 0x27c20, 0x27c20, + 0x27c28, 0x27c30, + 0x27c38, 0x27c38, + 0x27c80, 0x27c98, + 0x27ca0, 0x27ca8, + 0x27cb0, 0x27cc8, + 0x27cd0, 0x27cd4, + 0x27ce0, 0x27ce8, + 0x27cf0, 0x27cf0, + 0x27cf8, 0x27d7c, 0x27e00, 0x27e04, }; static const unsigned int t5_reg_ranges[] = { - 0x1008, 0x1148, - 0x1180, 0x11b4, + 0x1008, 0x10c0, + 0x10cc, 0x10f8, + 0x1100, 0x1100, + 0x110c, 0x1148, + 0x1180, 0x1184, + 0x1190, 0x1194, + 0x11a0, 0x11a4, + 0x11b0, 0x11b4, 0x11fc, 0x123c, 0x1280, 0x173c, 0x1800, 0x18fc, 0x3000, 0x3028, - 0x3068, 0x30d8, + 0x3060, 0x30b0, + 0x30b8, 0x30d8, 0x30e0, 0x30fc, 0x3140, 0x357c, 0x35a8, 0x35cc, 0x35ec, 0x35ec, 0x3600, 0x5624, - 0x56cc, 0x575c, + 0x56cc, 0x56ec, + 0x56f4, 0x5720, + 0x5728, 0x575c, 0x580c, 0x5814, - 0x5890, 0x58bc, - 0x5940, 0x59dc, + 0x5890, 0x589c, + 0x58a4, 0x58ac, + 0x58b8, 0x58bc, + 0x5940, 0x59c8, + 0x59d0, 0x59dc, 0x59fc, 0x5a18, - 0x5a60, 0x5a9c, + 0x5a60, 0x5a70, + 0x5a80, 0x5a9c, 0x5b94, 0x5bfc, - 0x6000, 0x6040, - 0x6058, 0x614c, + 0x6000, 0x6020, + 0x6028, 0x6040, + 0x6058, 0x609c, + 0x60a8, 0x614c, 0x7700, 0x7798, 0x77c0, 0x78fc, - 0x7b00, 0x7c54, - 0x7d00, 0x7efc, + 0x7b00, 0x7b58, + 0x7b60, 0x7b84, + 0x7b8c, 0x7c54, + 0x7d00, 0x7d38, + 0x7d40, 0x7d80, + 0x7d8c, 0x7ddc, + 0x7de4, 0x7e04, + 0x7e10, 0x7e1c, + 0x7e24, 0x7e38, + 0x7e40, 0x7e44, + 0x7e4c, 0x7e78, + 0x7e80, 0x7edc, + 0x7ee8, 0x7efc, 0x8dc0, 0x8de0, - 0x8df8, 0x8e84, + 0x8df8, 0x8e04, + 0x8e10, 0x8e84, 0x8ea0, 0x8f84, - 0x8fc0, 0x90f8, - 0x9400, 0x9470, - 0x9600, 0x96f4, + 0x8fc0, 0x9058, + 0x9060, 0x9060, + 0x9068, 0x90f8, + 0x9400, 0x9408, + 0x9410, 0x9470, + 0x9600, 0x9600, + 0x9608, 0x9638, + 0x9640, 0x96f4, 0x9800, 0x9808, 0x9820, 0x983c, 0x9850, 0x9864, @@ -962,103 +1230,143 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x9e80, 0x9eec, 0x9f00, 0x9f6c, 0x9f80, 0xa020, - 0xd004, 0xd03c, + 0xd004, 0xd004, + 0xd010, 0xd03c, 0xdfc0, 0xdfe0, - 0xe000, 0x11088, - 0x1109c, 0x11110, - 0x11118, 0x1117c, + 0xe000, 0x1106c, + 0x11074, 0x11088, + 0x1109c, 0x1117c, 0x11190, 0x11204, 0x19040, 0x1906c, 0x19078, 0x19080, - 0x1908c, 0x19124, - 0x19150, 0x191b0, + 0x1908c, 0x190e8, + 0x190f0, 0x190f8, + 0x19100, 0x19110, + 0x19120, 0x19124, + 0x19150, 0x19194, + 0x1919c, 0x191b0, 0x191d0, 0x191e8, 0x19238, 0x19290, - 0x193f8, 0x19474, + 0x193f8, 0x19428, + 0x19430, 0x19444, + 0x1944c, 0x1946c, + 0x19474, 0x19474, 0x19490, 0x194cc, 0x194f0, 0x194f8, - 0x19c00, 0x19c60, - 0x19c94, 0x19e10, - 0x19e50, 0x19f34, + 0x19c00, 0x19c08, + 0x19c10, 0x19c60, + 0x19c94, 0x19ce4, + 0x19cf0, 0x19d40, + 0x19d50, 0x19d94, + 0x19da0, 0x19de8, + 0x19df0, 0x19e10, + 0x19e50, 0x19e90, + 0x19ea0, 0x19f24, + 0x19f34, 0x19f34, 0x19f40, 0x19f50, - 0x19f90, 0x19fe4, - 0x1a000, 0x1a06c, - 0x1a0b0, 0x1a120, - 0x1a128, 0x1a138, + 0x19f90, 0x19fb4, + 0x19fc4, 0x19fe4, + 0x1a000, 0x1a004, + 0x1a010, 0x1a06c, + 0x1a0b0, 0x1a0e4, + 0x1a0ec, 0x1a0f8, + 0x1a100, 0x1a108, + 0x1a114, 0x1a120, + 0x1a128, 0x1a130, + 0x1a138, 0x1a138, 0x1a190, 0x1a1c4, 0x1a1fc, 0x1a1fc, 0x1e008, 0x1e00c, - 0x1e040, 0x1e04c, + 0x1e040, 0x1e044, + 0x1e04c, 0x1e04c, 0x1e284, 0x1e290, 0x1e2c0, 0x1e2c0, 0x1e2e0, 0x1e2e0, 0x1e300, 0x1e384, 0x1e3c0, 0x1e3c8, 0x1e408, 0x1e40c, - 0x1e440, 0x1e44c, + 0x1e440, 0x1e444, + 0x1e44c, 0x1e44c, 0x1e684, 0x1e690, 0x1e6c0, 0x1e6c0, 0x1e6e0, 0x1e6e0, 0x1e700, 0x1e784, 0x1e7c0, 0x1e7c8, 0x1e808, 0x1e80c, - 0x1e840, 0x1e84c, + 0x1e840, 0x1e844, + 0x1e84c, 0x1e84c, 0x1ea84, 0x1ea90, 0x1eac0, 0x1eac0, 0x1eae0, 0x1eae0, 0x1eb00, 0x1eb84, 0x1ebc0, 0x1ebc8, 0x1ec08, 0x1ec0c, - 0x1ec40, 0x1ec4c, + 0x1ec40, 0x1ec44, + 0x1ec4c, 0x1ec4c, 0x1ee84, 0x1ee90, 0x1eec0, 0x1eec0, 0x1eee0, 0x1eee0, 0x1ef00, 0x1ef84, 0x1efc0, 0x1efc8, 0x1f008, 0x1f00c, - 0x1f040, 0x1f04c, + 0x1f040, 0x1f044, + 0x1f04c, 0x1f04c, 0x1f284, 0x1f290, 0x1f2c0, 0x1f2c0, 0x1f2e0, 0x1f2e0, 0x1f300, 0x1f384, 0x1f3c0, 0x1f3c8, 0x1f408, 0x1f40c, - 0x1f440, 0x1f44c, + 0x1f440, 0x1f444, + 0x1f44c, 0x1f44c, 0x1f684, 0x1f690, 0x1f6c0, 0x1f6c0, 0x1f6e0, 0x1f6e0, 0x1f700, 0x1f784, 0x1f7c0, 0x1f7c8, 0x1f808, 0x1f80c, - 0x1f840, 0x1f84c, + 0x1f840, 0x1f844, + 0x1f84c, 0x1f84c, 0x1fa84, 0x1fa90, 0x1fac0, 0x1fac0, 0x1fae0, 0x1fae0, 0x1fb00, 0x1fb84, 0x1fbc0, 0x1fbc8, 0x1fc08, 0x1fc0c, - 0x1fc40, 0x1fc4c, + 0x1fc40, 0x1fc44, + 0x1fc4c, 0x1fc4c, 0x1fe84, 0x1fe90, 0x1fec0, 0x1fec0, 0x1fee0, 0x1fee0, 0x1ff00, 0x1ff84, 0x1ffc0, 0x1ffc8, 0x30000, 0x30030, + 0x30038, 0x30038, + 0x30040, 0x30040, 0x30100, 0x30144, - 0x30190, 0x301d0, + 0x30190, 0x301a0, + 0x301a8, 0x301b8, + 0x301c4, 0x301c8, + 0x301d0, 0x301d0, 0x30200, 0x30318, - 0x30400, 0x3052c, + 0x30400, 0x304b4, + 0x304c0, 0x3052c, 0x30540, 0x3061c, - 0x30800, 0x30834, + 0x30800, 0x30828, + 0x30834, 0x30834, 0x308c0, 0x30908, 0x30910, 0x309ac, - 0x30a00, 0x30a2c, + 0x30a00, 0x30a14, + 0x30a1c, 0x30a2c, 0x30a44, 0x30a50, - 0x30a74, 0x30c24, + 0x30a74, 0x30a74, + 0x30a7c, 0x30afc, + 0x30b08, 0x30c24, 0x30d00, 0x30d00, 0x30d08, 0x30d14, 0x30d1c, 0x30d20, - 0x30d3c, 0x30d50, + 0x30d3c, 0x30d3c, + 0x30d48, 0x30d50, 0x31200, 0x3120c, 0x31220, 0x31220, 0x31240, 0x31240, @@ -1078,27 +1386,65 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x322c8, 0x322fc, 0x32600, 0x32630, 0x32a00, 0x32abc, - 0x32b00, 0x32b70, - 0x33000, 0x33048, - 0x33060, 0x3309c, - 0x330f0, 0x33148, - 0x33160, 0x3319c, - 0x331f0, 0x332e4, - 0x332f8, 0x333e4, - 0x333f8, 0x33448, - 0x33460, 0x3349c, - 0x334f0, 0x33548, - 0x33560, 0x3359c, - 0x335f0, 0x336e4, - 0x336f8, 0x337e4, + 0x32b00, 0x32b10, + 0x32b20, 0x32b30, + 0x32b40, 0x32b50, + 0x32b60, 0x32b70, + 0x33000, 0x33028, + 0x33030, 0x33048, + 0x33060, 0x33068, + 0x33070, 0x3309c, + 0x330f0, 0x33128, + 0x33130, 0x33148, + 0x33160, 0x33168, + 0x33170, 0x3319c, + 0x331f0, 0x33238, + 0x33240, 0x33240, + 0x33248, 0x33250, + 0x3325c, 0x33264, + 0x33270, 0x332b8, + 0x332c0, 0x332e4, + 0x332f8, 0x33338, + 0x33340, 0x33340, + 0x33348, 0x33350, + 0x3335c, 0x33364, + 0x33370, 0x333b8, + 0x333c0, 0x333e4, + 0x333f8, 0x33428, + 0x33430, 0x33448, + 0x33460, 0x33468, + 0x33470, 0x3349c, + 0x334f0, 0x33528, + 0x33530, 0x33548, + 0x33560, 0x33568, + 0x33570, 0x3359c, + 0x335f0, 0x33638, + 0x33640, 0x33640, + 0x33648, 0x33650, + 0x3365c, 0x33664, + 0x33670, 0x336b8, + 0x336c0, 0x336e4, + 0x336f8, 0x33738, + 0x33740, 0x33740, + 0x33748, 0x33750, + 0x3375c, 0x33764, + 0x33770, 0x337b8, + 0x337c0, 0x337e4, 0x337f8, 0x337fc, 0x33814, 0x33814, 0x3382c, 0x3382c, 0x33880, 0x3388c, 0x338e8, 0x338ec, - 0x33900, 0x33948, - 0x33960, 0x3399c, - 0x339f0, 0x33ae4, + 0x33900, 0x33928, + 0x33930, 0x33948, + 0x33960, 0x33968, + 0x33970, 0x3399c, + 0x339f0, 0x33a38, + 0x33a40, 0x33a40, + 0x33a48, 0x33a50, + 0x33a5c, 0x33a64, + 0x33a70, 0x33ab8, + 0x33ac0, 0x33ae4, 0x33af8, 0x33b10, 0x33b28, 0x33b28, 0x33b3c, 0x33b50, @@ -1107,21 +1453,32 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x33c3c, 0x33c50, 0x33cf0, 0x33cfc, 0x34000, 0x34030, + 0x34038, 0x34038, + 0x34040, 0x34040, 0x34100, 0x34144, - 0x34190, 0x341d0, + 0x34190, 0x341a0, + 0x341a8, 0x341b8, + 0x341c4, 0x341c8, + 0x341d0, 0x341d0, 0x34200, 0x34318, - 0x34400, 0x3452c, + 0x34400, 0x344b4, + 0x344c0, 0x3452c, 0x34540, 0x3461c, - 0x34800, 0x34834, + 0x34800, 0x34828, + 0x34834, 0x34834, 0x348c0, 0x34908, 0x34910, 0x349ac, - 0x34a00, 0x34a2c, + 0x34a00, 0x34a14, + 0x34a1c, 0x34a2c, 0x34a44, 0x34a50, - 0x34a74, 0x34c24, + 0x34a74, 0x34a74, + 0x34a7c, 0x34afc, + 0x34b08, 0x34c24, 0x34d00, 0x34d00, 0x34d08, 0x34d14, 0x34d1c, 0x34d20, - 0x34d3c, 0x34d50, + 0x34d3c, 0x34d3c, + 0x34d48, 0x34d50, 0x35200, 0x3520c, 0x35220, 0x35220, 0x35240, 0x35240, @@ -1141,27 +1498,65 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x362c8, 0x362fc, 0x36600, 0x36630, 0x36a00, 0x36abc, - 0x36b00, 0x36b70, - 0x37000, 0x37048, - 0x37060, 0x3709c, - 0x370f0, 0x37148, - 0x37160, 0x3719c, - 0x371f0, 0x372e4, - 0x372f8, 0x373e4, - 0x373f8, 0x37448, - 0x37460, 0x3749c, - 0x374f0, 0x37548, - 0x37560, 0x3759c, - 0x375f0, 0x376e4, - 0x376f8, 0x377e4, + 0x36b00, 0x36b10, + 0x36b20, 0x36b30, + 0x36b40, 0x36b50, + 0x36b60, 0x36b70, + 0x37000, 0x37028, + 0x37030, 0x37048, + 0x37060, 0x37068, + 0x37070, 0x3709c, + 0x370f0, 0x37128, + 0x37130, 0x37148, + 0x37160, 0x37168, + 0x37170, 0x3719c, + 0x371f0, 0x37238, + 0x37240, 0x37240, + 0x37248, 0x37250, + 0x3725c, 0x37264, + 0x37270, 0x372b8, + 0x372c0, 0x372e4, + 0x372f8, 0x37338, + 0x37340, 0x37340, + 0x37348, 0x37350, + 0x3735c, 0x37364, + 0x37370, 0x373b8, + 0x373c0, 0x373e4, + 0x373f8, 0x37428, + 0x37430, 0x37448, + 0x37460, 0x37468, + 0x37470, 0x3749c, + 0x374f0, 0x37528, + 0x37530, 0x37548, + 0x37560, 0x37568, + 0x37570, 0x3759c, + 0x375f0, 0x37638, + 0x37640, 0x37640, + 0x37648, 0x37650, + 0x3765c, 0x37664, + 0x37670, 0x376b8, + 0x376c0, 0x376e4, + 0x376f8, 0x37738, + 0x37740, 0x37740, + 0x37748, 0x37750, + 0x3775c, 0x37764, + 0x37770, 0x377b8, + 0x377c0, 0x377e4, 0x377f8, 0x377fc, 0x37814, 0x37814, 0x3782c, 0x3782c, 0x37880, 0x3788c, 0x378e8, 0x378ec, - 0x37900, 0x37948, - 0x37960, 0x3799c, - 0x379f0, 0x37ae4, + 0x37900, 0x37928, + 0x37930, 0x37948, + 0x37960, 0x37968, + 0x37970, 0x3799c, + 0x379f0, 0x37a38, + 0x37a40, 0x37a40, + 0x37a48, 0x37a50, + 0x37a5c, 0x37a64, + 0x37a70, 0x37ab8, + 0x37ac0, 0x37ae4, 0x37af8, 0x37b10, 0x37b28, 0x37b28, 0x37b3c, 0x37b50, @@ -1170,21 +1565,32 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x37c3c, 0x37c50, 0x37cf0, 0x37cfc, 0x38000, 0x38030, + 0x38038, 0x38038, + 0x38040, 0x38040, 0x38100, 0x38144, - 0x38190, 0x381d0, + 0x38190, 0x381a0, + 0x381a8, 0x381b8, + 0x381c4, 0x381c8, + 0x381d0, 0x381d0, 0x38200, 0x38318, - 0x38400, 0x3852c, + 0x38400, 0x384b4, + 0x384c0, 0x3852c, 0x38540, 0x3861c, - 0x38800, 0x38834, + 0x38800, 0x38828, + 0x38834, 0x38834, 0x388c0, 0x38908, 0x38910, 0x389ac, - 0x38a00, 0x38a2c, + 0x38a00, 0x38a14, + 0x38a1c, 0x38a2c, 0x38a44, 0x38a50, - 0x38a74, 0x38c24, + 0x38a74, 0x38a74, + 0x38a7c, 0x38afc, + 0x38b08, 0x38c24, 0x38d00, 0x38d00, 0x38d08, 0x38d14, 0x38d1c, 0x38d20, - 0x38d3c, 0x38d50, + 0x38d3c, 0x38d3c, + 0x38d48, 0x38d50, 0x39200, 0x3920c, 0x39220, 0x39220, 0x39240, 0x39240, @@ -1204,27 +1610,65 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x3a2c8, 0x3a2fc, 0x3a600, 0x3a630, 0x3aa00, 0x3aabc, - 0x3ab00, 0x3ab70, - 0x3b000, 0x3b048, - 0x3b060, 0x3b09c, - 0x3b0f0, 0x3b148, - 0x3b160, 0x3b19c, - 0x3b1f0, 0x3b2e4, - 0x3b2f8, 0x3b3e4, - 0x3b3f8, 0x3b448, - 0x3b460, 0x3b49c, - 0x3b4f0, 0x3b548, - 0x3b560, 0x3b59c, - 0x3b5f0, 0x3b6e4, - 0x3b6f8, 0x3b7e4, + 0x3ab00, 0x3ab10, + 0x3ab20, 0x3ab30, + 0x3ab40, 0x3ab50, + 0x3ab60, 0x3ab70, + 0x3b000, 0x3b028, + 0x3b030, 0x3b048, + 0x3b060, 0x3b068, + 0x3b070, 0x3b09c, + 0x3b0f0, 0x3b128, + 0x3b130, 0x3b148, + 0x3b160, 0x3b168, + 0x3b170, 0x3b19c, + 0x3b1f0, 0x3b238, + 0x3b240, 0x3b240, + 0x3b248, 0x3b250, + 0x3b25c, 0x3b264, + 0x3b270, 0x3b2b8, + 0x3b2c0, 0x3b2e4, + 0x3b2f8, 0x3b338, + 0x3b340, 0x3b340, + 0x3b348, 0x3b350, + 0x3b35c, 0x3b364, + 0x3b370, 0x3b3b8, + 0x3b3c0, 0x3b3e4, + 0x3b3f8, 0x3b428, + 0x3b430, 0x3b448, + 0x3b460, 0x3b468, + 0x3b470, 0x3b49c, + 0x3b4f0, 0x3b528, + 0x3b530, 0x3b548, + 0x3b560, 0x3b568, + 0x3b570, 0x3b59c, + 0x3b5f0, 0x3b638, + 0x3b640, 0x3b640, + 0x3b648, 0x3b650, + 0x3b65c, 0x3b664, + 0x3b670, 0x3b6b8, + 0x3b6c0, 0x3b6e4, + 0x3b6f8, 0x3b738, + 0x3b740, 0x3b740, + 0x3b748, 0x3b750, + 0x3b75c, 0x3b764, + 0x3b770, 0x3b7b8, + 0x3b7c0, 0x3b7e4, 0x3b7f8, 0x3b7fc, 0x3b814, 0x3b814, 0x3b82c, 0x3b82c, 0x3b880, 0x3b88c, 0x3b8e8, 0x3b8ec, - 0x3b900, 0x3b948, - 0x3b960, 0x3b99c, - 0x3b9f0, 0x3bae4, + 0x3b900, 0x3b928, + 0x3b930, 0x3b948, + 0x3b960, 0x3b968, + 0x3b970, 0x3b99c, + 0x3b9f0, 0x3ba38, + 0x3ba40, 0x3ba40, + 0x3ba48, 0x3ba50, + 0x3ba5c, 0x3ba64, + 0x3ba70, 0x3bab8, + 0x3bac0, 0x3bae4, 0x3baf8, 0x3bb10, 0x3bb28, 0x3bb28, 0x3bb3c, 0x3bb50, @@ -1233,21 +1677,32 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x3bc3c, 0x3bc50, 0x3bcf0, 0x3bcfc, 0x3c000, 0x3c030, + 0x3c038, 0x3c038, + 0x3c040, 0x3c040, 0x3c100, 0x3c144, - 0x3c190, 0x3c1d0, + 0x3c190, 0x3c1a0, + 0x3c1a8, 0x3c1b8, + 0x3c1c4, 0x3c1c8, + 0x3c1d0, 0x3c1d0, 0x3c200, 0x3c318, - 0x3c400, 0x3c52c, + 0x3c400, 0x3c4b4, + 0x3c4c0, 0x3c52c, 0x3c540, 0x3c61c, - 0x3c800, 0x3c834, + 0x3c800, 0x3c828, + 0x3c834, 0x3c834, 0x3c8c0, 0x3c908, 0x3c910, 0x3c9ac, - 0x3ca00, 0x3ca2c, + 0x3ca00, 0x3ca14, + 0x3ca1c, 0x3ca2c, 0x3ca44, 0x3ca50, - 0x3ca74, 0x3cc24, + 0x3ca74, 0x3ca74, + 0x3ca7c, 0x3cafc, + 0x3cb08, 0x3cc24, 0x3cd00, 0x3cd00, 0x3cd08, 0x3cd14, 0x3cd1c, 0x3cd20, - 0x3cd3c, 0x3cd50, + 0x3cd3c, 0x3cd3c, + 0x3cd48, 0x3cd50, 0x3d200, 0x3d20c, 0x3d220, 0x3d220, 0x3d240, 0x3d240, @@ -1267,27 +1722,65 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x3e2c8, 0x3e2fc, 0x3e600, 0x3e630, 0x3ea00, 0x3eabc, - 0x3eb00, 0x3eb70, - 0x3f000, 0x3f048, - 0x3f060, 0x3f09c, - 0x3f0f0, 0x3f148, - 0x3f160, 0x3f19c, - 0x3f1f0, 0x3f2e4, - 0x3f2f8, 0x3f3e4, - 0x3f3f8, 0x3f448, - 0x3f460, 0x3f49c, - 0x3f4f0, 0x3f548, - 0x3f560, 0x3f59c, - 0x3f5f0, 0x3f6e4, - 0x3f6f8, 0x3f7e4, + 0x3eb00, 0x3eb10, + 0x3eb20, 0x3eb30, + 0x3eb40, 0x3eb50, + 0x3eb60, 0x3eb70, + 0x3f000, 0x3f028, + 0x3f030, 0x3f048, + 0x3f060, 0x3f068, + 0x3f070, 0x3f09c, + 0x3f0f0, 0x3f128, + 0x3f130, 0x3f148, + 0x3f160, 0x3f168, + 0x3f170, 0x3f19c, + 0x3f1f0, 0x3f238, + 0x3f240, 0x3f240, + 0x3f248, 0x3f250, + 0x3f25c, 0x3f264, + 0x3f270, 0x3f2b8, + 0x3f2c0, 0x3f2e4, + 0x3f2f8, 0x3f338, + 0x3f340, 0x3f340, + 0x3f348, 0x3f350, + 0x3f35c, 0x3f364, + 0x3f370, 0x3f3b8, + 0x3f3c0, 0x3f3e4, + 0x3f3f8, 0x3f428, + 0x3f430, 0x3f448, + 0x3f460, 0x3f468, + 0x3f470, 0x3f49c, + 0x3f4f0, 0x3f528, + 0x3f530, 0x3f548, + 0x3f560, 0x3f568, + 0x3f570, 0x3f59c, + 0x3f5f0, 0x3f638, + 0x3f640, 0x3f640, + 0x3f648, 0x3f650, + 0x3f65c, 0x3f664, + 0x3f670, 0x3f6b8, + 0x3f6c0, 0x3f6e4, + 0x3f6f8, 0x3f738, + 0x3f740, 0x3f740, + 0x3f748, 0x3f750, + 0x3f75c, 0x3f764, + 0x3f770, 0x3f7b8, + 0x3f7c0, 0x3f7e4, 0x3f7f8, 0x3f7fc, 0x3f814, 0x3f814, 0x3f82c, 0x3f82c, 0x3f880, 0x3f88c, 0x3f8e8, 0x3f8ec, - 0x3f900, 0x3f948, - 0x3f960, 0x3f99c, - 0x3f9f0, 0x3fae4, + 0x3f900, 0x3f928, + 0x3f930, 0x3f948, + 0x3f960, 0x3f968, + 0x3f970, 0x3f99c, + 0x3f9f0, 0x3fa38, + 0x3fa40, 0x3fa40, + 0x3fa48, 0x3fa50, + 0x3fa5c, 0x3fa64, + 0x3fa70, 0x3fab8, + 0x3fac0, 0x3fae4, 0x3faf8, 0x3fb10, 0x3fb28, 0x3fb28, 0x3fb3c, 0x3fb50, @@ -1296,108 +1789,224 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x3fc3c, 0x3fc50, 0x3fcf0, 0x3fcfc, 0x40000, 0x4000c, - 0x40040, 0x40068, - 0x4007c, 0x40144, + 0x40040, 0x40050, + 0x40060, 0x40068, + 0x4007c, 0x4008c, + 0x40094, 0x400b0, + 0x400c0, 0x40144, 0x40180, 0x4018c, - 0x40200, 0x40298, - 0x402ac, 0x4033c, + 0x40200, 0x40254, + 0x40260, 0x40264, + 0x40270, 0x40288, + 0x40290, 0x40298, + 0x402ac, 0x402c8, + 0x402d0, 0x402e0, + 0x402f0, 0x402f0, + 0x40300, 0x4033c, 0x403f8, 0x403fc, 0x41304, 0x413c4, - 0x41400, 0x4141c, + 0x41400, 0x4140c, + 0x41414, 0x4141c, 0x41480, 0x414d0, - 0x44000, 0x44078, - 0x440c0, 0x44278, - 0x442c0, 0x44478, - 0x444c0, 0x44678, - 0x446c0, 0x44878, - 0x448c0, 0x449fc, - 0x45000, 0x45068, + 0x44000, 0x44054, + 0x4405c, 0x44078, + 0x440c0, 0x44174, + 0x44180, 0x441ac, + 0x441b4, 0x441b8, + 0x441c0, 0x44254, + 0x4425c, 0x44278, + 0x442c0, 0x44374, + 0x44380, 0x443ac, + 0x443b4, 0x443b8, + 0x443c0, 0x44454, + 0x4445c, 0x44478, + 0x444c0, 0x44574, + 0x44580, 0x445ac, + 0x445b4, 0x445b8, + 0x445c0, 0x44654, + 0x4465c, 0x44678, + 0x446c0, 0x44774, + 0x44780, 0x447ac, + 0x447b4, 0x447b8, + 0x447c0, 0x44854, + 0x4485c, 0x44878, + 0x448c0, 0x44974, + 0x44980, 0x449ac, + 0x449b4, 0x449b8, + 0x449c0, 0x449fc, + 0x45000, 0x45004, + 0x45010, 0x45030, + 0x45040, 0x45060, + 0x45068, 0x45068, 0x45080, 0x45084, 0x450a0, 0x450b0, - 0x45200, 0x45268, + 0x45200, 0x45204, + 0x45210, 0x45230, + 0x45240, 0x45260, + 0x45268, 0x45268, 0x45280, 0x45284, 0x452a0, 0x452b0, 0x460c0, 0x460e4, - 0x47000, 0x4708c, + 0x47000, 0x4703c, + 0x47044, 0x4708c, 0x47200, 0x47250, - 0x47400, 0x47420, + 0x47400, 0x47408, + 0x47414, 0x47420, 0x47600, 0x47618, 0x47800, 0x47814, 0x48000, 0x4800c, - 0x48040, 0x48068, - 0x4807c, 0x48144, + 0x48040, 0x48050, + 0x48060, 0x48068, + 0x4807c, 0x4808c, + 0x48094, 0x480b0, + 0x480c0, 0x48144, 0x48180, 0x4818c, - 0x48200, 0x48298, - 0x482ac, 0x4833c, + 0x48200, 0x48254, + 0x48260, 0x48264, + 0x48270, 0x48288, + 0x48290, 0x48298, + 0x482ac, 0x482c8, + 0x482d0, 0x482e0, + 0x482f0, 0x482f0, + 0x48300, 0x4833c, 0x483f8, 0x483fc, 0x49304, 0x493c4, - 0x49400, 0x4941c, + 0x49400, 0x4940c, + 0x49414, 0x4941c, 0x49480, 0x494d0, - 0x4c000, 0x4c078, - 0x4c0c0, 0x4c278, - 0x4c2c0, 0x4c478, - 0x4c4c0, 0x4c678, - 0x4c6c0, 0x4c878, - 0x4c8c0, 0x4c9fc, - 0x4d000, 0x4d068, + 0x4c000, 0x4c054, + 0x4c05c, 0x4c078, + 0x4c0c0, 0x4c174, + 0x4c180, 0x4c1ac, + 0x4c1b4, 0x4c1b8, + 0x4c1c0, 0x4c254, + 0x4c25c, 0x4c278, + 0x4c2c0, 0x4c374, + 0x4c380, 0x4c3ac, + 0x4c3b4, 0x4c3b8, + 0x4c3c0, 0x4c454, + 0x4c45c, 0x4c478, + 0x4c4c0, 0x4c574, + 0x4c580, 0x4c5ac, + 0x4c5b4, 0x4c5b8, + 0x4c5c0, 0x4c654, + 0x4c65c, 0x4c678, + 0x4c6c0, 0x4c774, + 0x4c780, 0x4c7ac, + 0x4c7b4, 0x4c7b8, + 0x4c7c0, 0x4c854, + 0x4c85c, 0x4c878, + 0x4c8c0, 0x4c974, + 0x4c980, 0x4c9ac, + 0x4c9b4, 0x4c9b8, + 0x4c9c0, 0x4c9fc, + 0x4d000, 0x4d004, + 0x4d010, 0x4d030, + 0x4d040, 0x4d060, + 0x4d068, 0x4d068, 0x4d080, 0x4d084, 0x4d0a0, 0x4d0b0, - 0x4d200, 0x4d268, + 0x4d200, 0x4d204, + 0x4d210, 0x4d230, + 0x4d240, 0x4d260, + 0x4d268, 0x4d268, 0x4d280, 0x4d284, 0x4d2a0, 0x4d2b0, 0x4e0c0, 0x4e0e4, - 0x4f000, 0x4f08c, + 0x4f000, 0x4f03c, + 0x4f044, 0x4f08c, 0x4f200, 0x4f250, - 0x4f400, 0x4f420, + 0x4f400, 0x4f408, + 0x4f414, 0x4f420, 0x4f600, 0x4f618, 0x4f800, 0x4f814, - 0x50000, 0x500cc, + 0x50000, 0x50084, + 0x50090, 0x500cc, 0x50400, 0x50400, - 0x50800, 0x508cc, + 0x50800, 0x50884, + 0x50890, 0x508cc, 0x50c00, 0x50c00, 0x51000, 0x5101c, 0x51300, 0x51308, }; static const unsigned int t6_reg_ranges[] = { - 0x1008, 0x1124, - 0x1138, 0x114c, - 0x1180, 0x11b4, + 0x1008, 0x101c, + 0x1024, 0x10a8, + 0x10b4, 0x10f8, + 0x1100, 0x1114, + 0x111c, 0x112c, + 0x1138, 0x113c, + 0x1144, 0x114c, + 0x1180, 0x1184, + 0x1190, 0x1194, + 0x11a0, 0x11a4, + 0x11b0, 0x11b4, 0x11fc, 0x1254, 0x1280, 0x133c, 0x1800, 0x18fc, 0x3000, 0x302c, - 0x3060, 0x30d8, + 0x3060, 0x30b0, + 0x30b8, 0x30d8, 0x30e0, 0x30fc, 0x3140, 0x357c, 0x35a8, 0x35cc, 0x35ec, 0x35ec, 0x3600, 0x5624, - 0x56cc, 0x575c, + 0x56cc, 0x56ec, + 0x56f4, 0x5720, + 0x5728, 0x575c, 0x580c, 0x5814, - 0x5890, 0x58bc, + 0x5890, 0x589c, + 0x58a4, 0x58ac, + 0x58b8, 0x58bc, 0x5940, 0x595c, 0x5980, 0x598c, - 0x59b0, 0x59dc, + 0x59b0, 0x59c8, + 0x59d0, 0x59dc, 0x59fc, 0x5a18, 0x5a60, 0x5a6c, - 0x5a80, 0x5a9c, + 0x5a80, 0x5a8c, + 0x5a94, 0x5a9c, 0x5b94, 0x5bfc, - 0x5c10, 0x5ec0, + 0x5c10, 0x5e48, + 0x5e50, 0x5e94, + 0x5ea0, 0x5eb0, + 0x5ec0, 0x5ec0, 0x5ec8, 0x5ecc, - 0x6000, 0x6040, - 0x6058, 0x619c, + 0x6000, 0x6020, + 0x6028, 0x6040, + 0x6058, 0x609c, + 0x60a8, 0x619c, 0x7700, 0x7798, 0x77c0, 0x7880, 0x78cc, 0x78fc, - 0x7b00, 0x7c54, - 0x7d00, 0x7efc, + 0x7b00, 0x7b58, + 0x7b60, 0x7b84, + 0x7b8c, 0x7c54, + 0x7d00, 0x7d38, + 0x7d40, 0x7d84, + 0x7d8c, 0x7ddc, + 0x7de4, 0x7e04, + 0x7e10, 0x7e1c, + 0x7e24, 0x7e38, + 0x7e40, 0x7e44, + 0x7e4c, 0x7e78, + 0x7e80, 0x7edc, + 0x7ee8, 0x7efc, 0x8dc0, 0x8de4, - 0x8df8, 0x8e84, + 0x8df8, 0x8e04, + 0x8e10, 0x8e84, 0x8ea0, 0x8f88, - 0x8fb8, 0x9124, + 0x8fb8, 0x9058, + 0x9060, 0x9060, + 0x9068, 0x90f8, + 0x9100, 0x9124, 0x9400, 0x9470, - 0x9600, 0x971c, + 0x9600, 0x9600, + 0x9608, 0x9638, + 0x9640, 0x9704, + 0x9710, 0x971c, 0x9800, 0x9808, 0x9820, 0x983c, 0x9850, 0x9864, @@ -1411,109 +2020,170 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x9f80, 0xa020, 0xd004, 0xd03c, 0xd100, 0xd118, - 0xd200, 0xd31c, + 0xd200, 0xd214, + 0xd220, 0xd234, + 0xd240, 0xd254, + 0xd260, 0xd274, + 0xd280, 0xd294, + 0xd2a0, 0xd2b4, + 0xd2c0, 0xd2d4, + 0xd2e0, 0xd2f4, + 0xd300, 0xd31c, 0xdfc0, 0xdfe0, 0xe000, 0xf008, 0x11000, 0x11014, - 0x11048, 0x1117c, - 0x11190, 0x11270, + 0x11048, 0x1106c, + 0x11074, 0x11088, + 0x11098, 0x11120, + 0x1112c, 0x1117c, + 0x11190, 0x112e0, 0x11300, 0x1130c, 0x12000, 0x1206c, 0x19040, 0x1906c, 0x19078, 0x19080, - 0x1908c, 0x19124, - 0x19150, 0x191b0, + 0x1908c, 0x190e8, + 0x190f0, 0x190f8, + 0x19100, 0x19110, + 0x19120, 0x19124, + 0x19150, 0x19194, + 0x1919c, 0x191b0, 0x191d0, 0x191e8, - 0x19238, 0x192bc, - 0x193f8, 0x19474, + 0x19238, 0x192b0, + 0x192bc, 0x192bc, + 0x19348, 0x1934c, + 0x193f8, 0x19418, + 0x19420, 0x19428, + 0x19430, 0x19444, + 0x1944c, 0x1946c, + 0x19474, 0x19474, 0x19490, 0x194cc, 0x194f0, 0x194f8, - 0x19c00, 0x19c80, - 0x19c94, 0x19cbc, - 0x19ce4, 0x19d28, + 0x19c00, 0x19c48, + 0x19c50, 0x19c80, + 0x19c94, 0x19c98, + 0x19ca0, 0x19cbc, + 0x19ce4, 0x19ce4, + 0x19cf0, 0x19cf8, + 0x19d00, 0x19d28, 0x19d50, 0x19d78, - 0x19d94, 0x19dc8, + 0x19d94, 0x19d98, + 0x19da0, 0x19dc8, 0x19df0, 0x19e10, 0x19e50, 0x19e6c, - 0x19ea0, 0x19f34, + 0x19ea0, 0x19ebc, + 0x19ec4, 0x19ef4, + 0x19f04, 0x19f2c, + 0x19f34, 0x19f34, 0x19f40, 0x19f50, 0x19f90, 0x19fac, - 0x19fc4, 0x19fe4, - 0x1a000, 0x1a06c, - 0x1a0b0, 0x1a120, - 0x1a128, 0x1a138, + 0x19fc4, 0x19fc8, + 0x19fd0, 0x19fe4, + 0x1a000, 0x1a004, + 0x1a010, 0x1a06c, + 0x1a0b0, 0x1a0e4, + 0x1a0ec, 0x1a0f8, + 0x1a100, 0x1a108, + 0x1a114, 0x1a120, + 0x1a128, 0x1a130, + 0x1a138, 0x1a138, 0x1a190, 0x1a1c4, 0x1a1fc, 0x1a1fc, 0x1e008, 0x1e00c, - 0x1e040, 0x1e04c, + 0x1e040, 0x1e044, + 0x1e04c, 0x1e04c, 0x1e284, 0x1e290, 0x1e2c0, 0x1e2c0, 0x1e2e0, 0x1e2e0, 0x1e300, 0x1e384, 0x1e3c0, 0x1e3c8, 0x1e408, 0x1e40c, - 0x1e440, 0x1e44c, + 0x1e440, 0x1e444, + 0x1e44c, 0x1e44c, 0x1e684, 0x1e690, 0x1e6c0, 0x1e6c0, 0x1e6e0, 0x1e6e0, 0x1e700, 0x1e784, 0x1e7c0, 0x1e7c8, 0x1e808, 0x1e80c, - 0x1e840, 0x1e84c, + 0x1e840, 0x1e844, + 0x1e84c, 0x1e84c, 0x1ea84, 0x1ea90, 0x1eac0, 0x1eac0, 0x1eae0, 0x1eae0, 0x1eb00, 0x1eb84, 0x1ebc0, 0x1ebc8, 0x1ec08, 0x1ec0c, - 0x1ec40, 0x1ec4c, + 0x1ec40, 0x1ec44, + 0x1ec4c, 0x1ec4c, 0x1ee84, 0x1ee90, 0x1eec0, 0x1eec0, 0x1eee0, 0x1eee0, 0x1ef00, 0x1ef84, 0x1efc0, 0x1efc8, 0x1f008, 0x1f00c, - 0x1f040, 0x1f04c, + 0x1f040, 0x1f044, + 0x1f04c, 0x1f04c, 0x1f284, 0x1f290, 0x1f2c0, 0x1f2c0, 0x1f2e0, 0x1f2e0, 0x1f300, 0x1f384, 0x1f3c0, 0x1f3c8, 0x1f408, 0x1f40c, - 0x1f440, 0x1f44c, + 0x1f440, 0x1f444, + 0x1f44c, 0x1f44c, 0x1f684, 0x1f690, 0x1f6c0, 0x1f6c0, 0x1f6e0, 0x1f6e0, 0x1f700, 0x1f784, 0x1f7c0, 0x1f7c8, 0x1f808, 0x1f80c, - 0x1f840, 0x1f84c, + 0x1f840, 0x1f844, + 0x1f84c, 0x1f84c, 0x1fa84, 0x1fa90, 0x1fac0, 0x1fac0, 0x1fae0, 0x1fae0, 0x1fb00, 0x1fb84, 0x1fbc0, 0x1fbc8, 0x1fc08, 0x1fc0c, - 0x1fc40, 0x1fc4c, + 0x1fc40, 0x1fc44, + 0x1fc4c, 0x1fc4c, 0x1fe84, 0x1fe90, 0x1fec0, 0x1fec0, 0x1fee0, 0x1fee0, 0x1ff00, 0x1ff84, 0x1ffc0, 0x1ffc8, - 0x30000, 0x30070, - 0x30100, 0x301d0, + 0x30000, 0x30030, + 0x30038, 0x30038, + 0x30040, 0x30040, + 0x30048, 0x30048, + 0x30050, 0x30050, + 0x3005c, 0x30060, + 0x30068, 0x30068, + 0x30070, 0x30070, + 0x30100, 0x30168, + 0x30190, 0x301a0, + 0x301a8, 0x301b8, + 0x301c4, 0x301c8, + 0x301d0, 0x301d0, 0x30200, 0x30320, - 0x30400, 0x3052c, + 0x30400, 0x304b4, + 0x304c0, 0x3052c, 0x30540, 0x3061c, - 0x30800, 0x30890, + 0x30800, 0x308a0, 0x308c0, 0x30908, 0x30910, 0x309b8, 0x30a00, 0x30a04, - 0x30a0c, 0x30a2c, + 0x30a0c, 0x30a14, + 0x30a1c, 0x30a2c, 0x30a44, 0x30a50, - 0x30a74, 0x30c24, - 0x30d00, 0x30d3c, - 0x30d44, 0x30d7c, + 0x30a74, 0x30a74, + 0x30a7c, 0x30afc, + 0x30b08, 0x30c24, + 0x30d00, 0x30d14, + 0x30d1c, 0x30d3c, + 0x30d44, 0x30d4c, + 0x30d54, 0x30d74, + 0x30d7c, 0x30d7c, 0x30de0, 0x30de0, 0x30e00, 0x30ed4, 0x30f00, 0x30fa4, @@ -1542,7 +2212,8 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x31bb0, 0x31bb4, 0x31bc8, 0x31bd4, 0x32140, 0x3218c, - 0x321f0, 0x32200, + 0x321f0, 0x321f4, + 0x32200, 0x32200, 0x32218, 0x32218, 0x32400, 0x32400, 0x32408, 0x3241c, @@ -1551,46 +2222,108 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x326a8, 0x326a8, 0x326ec, 0x326ec, 0x32a00, 0x32abc, - 0x32b00, 0x32b78, + 0x32b00, 0x32b38, + 0x32b40, 0x32b58, + 0x32b60, 0x32b78, 0x32c00, 0x32c00, 0x32c08, 0x32c3c, 0x32e00, 0x32e2c, 0x32f00, 0x32f2c, - 0x33000, 0x330ac, - 0x330c0, 0x331ac, - 0x331c0, 0x332c4, - 0x332e4, 0x333c4, - 0x333e4, 0x334ac, - 0x334c0, 0x335ac, - 0x335c0, 0x336c4, - 0x336e4, 0x337c4, + 0x33000, 0x3302c, + 0x33034, 0x33050, + 0x33058, 0x33058, + 0x33060, 0x3308c, + 0x3309c, 0x330ac, + 0x330c0, 0x330c0, + 0x330c8, 0x330d0, + 0x330d8, 0x330e0, + 0x330ec, 0x3312c, + 0x33134, 0x33150, + 0x33158, 0x33158, + 0x33160, 0x3318c, + 0x3319c, 0x331ac, + 0x331c0, 0x331c0, + 0x331c8, 0x331d0, + 0x331d8, 0x331e0, + 0x331ec, 0x33290, + 0x33298, 0x332c4, + 0x332e4, 0x33390, + 0x33398, 0x333c4, + 0x333e4, 0x3342c, + 0x33434, 0x33450, + 0x33458, 0x33458, + 0x33460, 0x3348c, + 0x3349c, 0x334ac, + 0x334c0, 0x334c0, + 0x334c8, 0x334d0, + 0x334d8, 0x334e0, + 0x334ec, 0x3352c, + 0x33534, 0x33550, + 0x33558, 0x33558, + 0x33560, 0x3358c, + 0x3359c, 0x335ac, + 0x335c0, 0x335c0, + 0x335c8, 0x335d0, + 0x335d8, 0x335e0, + 0x335ec, 0x33690, + 0x33698, 0x336c4, + 0x336e4, 0x33790, + 0x33798, 0x337c4, 0x337e4, 0x337fc, 0x33814, 0x33814, 0x33854, 0x33868, 0x33880, 0x3388c, 0x338c0, 0x338d0, 0x338e8, 0x338ec, - 0x33900, 0x339ac, - 0x339c0, 0x33ac4, + 0x33900, 0x3392c, + 0x33934, 0x33950, + 0x33958, 0x33958, + 0x33960, 0x3398c, + 0x3399c, 0x339ac, + 0x339c0, 0x339c0, + 0x339c8, 0x339d0, + 0x339d8, 0x339e0, + 0x339ec, 0x33a90, + 0x33a98, 0x33ac4, 0x33ae4, 0x33b10, - 0x33b24, 0x33b50, + 0x33b24, 0x33b28, + 0x33b38, 0x33b50, 0x33bf0, 0x33c10, - 0x33c24, 0x33c50, + 0x33c24, 0x33c28, + 0x33c38, 0x33c50, 0x33cf0, 0x33cfc, - 0x34000, 0x34070, - 0x34100, 0x341d0, + 0x34000, 0x34030, + 0x34038, 0x34038, + 0x34040, 0x34040, + 0x34048, 0x34048, + 0x34050, 0x34050, + 0x3405c, 0x34060, + 0x34068, 0x34068, + 0x34070, 0x34070, + 0x34100, 0x34168, + 0x34190, 0x341a0, + 0x341a8, 0x341b8, + 0x341c4, 0x341c8, + 0x341d0, 0x341d0, 0x34200, 0x34320, - 0x34400, 0x3452c, + 0x34400, 0x344b4, + 0x344c0, 0x3452c, 0x34540, 0x3461c, - 0x34800, 0x34890, + 0x34800, 0x348a0, 0x348c0, 0x34908, 0x34910, 0x349b8, 0x34a00, 0x34a04, - 0x34a0c, 0x34a2c, + 0x34a0c, 0x34a14, + 0x34a1c, 0x34a2c, 0x34a44, 0x34a50, - 0x34a74, 0x34c24, - 0x34d00, 0x34d3c, - 0x34d44, 0x34d7c, + 0x34a74, 0x34a74, + 0x34a7c, 0x34afc, + 0x34b08, 0x34c24, + 0x34d00, 0x34d14, + 0x34d1c, 0x34d3c, + 0x34d44, 0x34d4c, + 0x34d54, 0x34d74, + 0x34d7c, 0x34d7c, 0x34de0, 0x34de0, 0x34e00, 0x34ed4, 0x34f00, 0x34fa4, @@ -1619,7 +2352,8 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x35bb0, 0x35bb4, 0x35bc8, 0x35bd4, 0x36140, 0x3618c, - 0x361f0, 0x36200, + 0x361f0, 0x361f4, + 0x36200, 0x36200, 0x36218, 0x36218, 0x36400, 0x36400, 0x36408, 0x3641c, @@ -1628,31 +2362,75 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x366a8, 0x366a8, 0x366ec, 0x366ec, 0x36a00, 0x36abc, - 0x36b00, 0x36b78, + 0x36b00, 0x36b38, + 0x36b40, 0x36b58, + 0x36b60, 0x36b78, 0x36c00, 0x36c00, 0x36c08, 0x36c3c, 0x36e00, 0x36e2c, 0x36f00, 0x36f2c, - 0x37000, 0x370ac, - 0x370c0, 0x371ac, - 0x371c0, 0x372c4, - 0x372e4, 0x373c4, - 0x373e4, 0x374ac, - 0x374c0, 0x375ac, - 0x375c0, 0x376c4, - 0x376e4, 0x377c4, + 0x37000, 0x3702c, + 0x37034, 0x37050, + 0x37058, 0x37058, + 0x37060, 0x3708c, + 0x3709c, 0x370ac, + 0x370c0, 0x370c0, + 0x370c8, 0x370d0, + 0x370d8, 0x370e0, + 0x370ec, 0x3712c, + 0x37134, 0x37150, + 0x37158, 0x37158, + 0x37160, 0x3718c, + 0x3719c, 0x371ac, + 0x371c0, 0x371c0, + 0x371c8, 0x371d0, + 0x371d8, 0x371e0, + 0x371ec, 0x37290, + 0x37298, 0x372c4, + 0x372e4, 0x37390, + 0x37398, 0x373c4, + 0x373e4, 0x3742c, + 0x37434, 0x37450, + 0x37458, 0x37458, + 0x37460, 0x3748c, + 0x3749c, 0x374ac, + 0x374c0, 0x374c0, + 0x374c8, 0x374d0, + 0x374d8, 0x374e0, + 0x374ec, 0x3752c, + 0x37534, 0x37550, + 0x37558, 0x37558, + 0x37560, 0x3758c, + 0x3759c, 0x375ac, + 0x375c0, 0x375c0, + 0x375c8, 0x375d0, + 0x375d8, 0x375e0, + 0x375ec, 0x37690, + 0x37698, 0x376c4, + 0x376e4, 0x37790, + 0x37798, 0x377c4, 0x377e4, 0x377fc, 0x37814, 0x37814, 0x37854, 0x37868, 0x37880, 0x3788c, 0x378c0, 0x378d0, 0x378e8, 0x378ec, - 0x37900, 0x379ac, - 0x379c0, 0x37ac4, + 0x37900, 0x3792c, + 0x37934, 0x37950, + 0x37958, 0x37958, + 0x37960, 0x3798c, + 0x3799c, 0x379ac, + 0x379c0, 0x379c0, + 0x379c8, 0x379d0, + 0x379d8, 0x379e0, + 0x379ec, 0x37a90, + 0x37a98, 0x37ac4, 0x37ae4, 0x37b10, - 0x37b24, 0x37b50, + 0x37b24, 0x37b28, + 0x37b38, 0x37b50, 0x37bf0, 0x37c10, - 0x37c24, 0x37c50, + 0x37c24, 0x37c28, + 0x37c38, 0x37c50, 0x37cf0, 0x37cfc, 0x40040, 0x40040, 0x40080, 0x40084, @@ -1664,36 +2442,62 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x40280, 0x40280, 0x40304, 0x40304, 0x40330, 0x4033c, - 0x41304, 0x413dc, - 0x41400, 0x4141c, + 0x41304, 0x413c8, + 0x413d0, 0x413dc, + 0x413f0, 0x413f0, + 0x41400, 0x4140c, + 0x41414, 0x4141c, 0x41480, 0x414d0, 0x44000, 0x4407c, - 0x440c0, 0x4427c, - 0x442c0, 0x4447c, - 0x444c0, 0x4467c, - 0x446c0, 0x4487c, - 0x448c0, 0x44a7c, - 0x44ac0, 0x44c7c, - 0x44cc0, 0x44e7c, - 0x44ec0, 0x4507c, - 0x450c0, 0x451fc, - 0x45800, 0x45868, + 0x440c0, 0x441ac, + 0x441b4, 0x4427c, + 0x442c0, 0x443ac, + 0x443b4, 0x4447c, + 0x444c0, 0x445ac, + 0x445b4, 0x4467c, + 0x446c0, 0x447ac, + 0x447b4, 0x4487c, + 0x448c0, 0x449ac, + 0x449b4, 0x44a7c, + 0x44ac0, 0x44bac, + 0x44bb4, 0x44c7c, + 0x44cc0, 0x44dac, + 0x44db4, 0x44e7c, + 0x44ec0, 0x44fac, + 0x44fb4, 0x4507c, + 0x450c0, 0x451ac, + 0x451b4, 0x451fc, + 0x45800, 0x45804, + 0x45810, 0x45830, + 0x45840, 0x45860, + 0x45868, 0x45868, 0x45880, 0x45884, 0x458a0, 0x458b0, - 0x45a00, 0x45a68, + 0x45a00, 0x45a04, + 0x45a10, 0x45a30, + 0x45a40, 0x45a60, + 0x45a68, 0x45a68, 0x45a80, 0x45a84, 0x45aa0, 0x45ab0, 0x460c0, 0x460e4, - 0x47000, 0x4708c, + 0x47000, 0x4703c, + 0x47044, 0x4708c, 0x47200, 0x47250, - 0x47400, 0x47420, + 0x47400, 0x47408, + 0x47414, 0x47420, 0x47600, 0x47618, - 0x47800, 0x4782c, - 0x50000, 0x500cc, + 0x47800, 0x47814, + 0x47820, 0x4782c, + 0x50000, 0x50084, + 0x50090, 0x500cc, + 0x50300, 0x50384, 0x50400, 0x50400, - 0x50800, 0x508cc, + 0x50800, 0x50884, + 0x50890, 0x508cc, + 0x50b00, 0x50b84, 0x50c00, 0x50c00, - 0x51000, 0x510b0, + 0x51000, 0x51020, + 0x51028, 0x510b0, 0x51300, 0x51324, }; -- cgit v1.2.3 From b3695540ba5d8cf032f30533d53786b31af271f5 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Thu, 1 Oct 2015 13:48:46 +0530 Subject: cxgb4: For T4, don't read the Firmware Mailbox Control register T4 doesn't have the Shadow copy of the register which we can read without side effect. So don't read mbox control register for T4 adapter Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c index 0a87a3247464..b4ace1940497 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c @@ -1128,18 +1128,26 @@ static const struct file_operations devlog_fops = { static int mbox_show(struct seq_file *seq, void *v) { static const char * const owner[] = { "none", "FW", "driver", - "unknown" }; + "unknown", "" }; int i; unsigned int mbox = (uintptr_t)seq->private & 7; struct adapter *adap = seq->private - mbox; void __iomem *addr = adap->regs + PF_REG(mbox, CIM_PF_MAILBOX_DATA_A); - unsigned int ctrl_reg = (is_t4(adap->params.chip) - ? CIM_PF_MAILBOX_CTRL_A - : CIM_PF_MAILBOX_CTRL_SHADOW_COPY_A); - void __iomem *ctrl = adap->regs + PF_REG(mbox, ctrl_reg); - i = MBOWNER_G(readl(ctrl)); + /* For T4 we don't have a shadow copy of the Mailbox Control register. + * And since reading that real register causes a side effect of + * granting ownership, we're best of simply not reading it at all. + */ + if (is_t4(adap->params.chip)) { + i = 4; /* index of "" */ + } else { + unsigned int ctrl_reg = CIM_PF_MAILBOX_CTRL_SHADOW_COPY_A; + void __iomem *ctrl = adap->regs + PF_REG(mbox, ctrl_reg); + + i = MBOWNER_G(readl(ctrl)); + } + seq_printf(seq, "mailbox owned by %s\n\n", owner[i]); for (i = 0; i < MBOX_LEN; i += 8) -- cgit v1.2.3 From da4976e17bff3bb7538090c36750b9875da67b5e Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Thu, 1 Oct 2015 13:48:47 +0530 Subject: cxgb4: Adds a new Device Log Facility FW_DEVLOG_FACILITY_CF The firmware team added a new Device Log Facility FW_DEVLOG_FACILITY_CF, but the driver has been decoding Device Log messages with that Facility as "(NULL)", fixing it. Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c index b4ace1940497..4269944c5db5 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c @@ -940,6 +940,7 @@ static const char * const devlog_level_strings[] = { static const char * const devlog_facility_strings[] = { [FW_DEVLOG_FACILITY_CORE] = "CORE", + [FW_DEVLOG_FACILITY_CF] = "CF", [FW_DEVLOG_FACILITY_SCHED] = "SCHED", [FW_DEVLOG_FACILITY_TIMER] = "TIMER", [FW_DEVLOG_FACILITY_RES] = "RES", -- cgit v1.2.3 From 85412255ef4fcccf52e0408d61cf8a75828a6800 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Thu, 1 Oct 2015 13:48:48 +0530 Subject: cxgb4: Report correct link speed for unsupported ones When we get garbage from the firmware with weird Port Speeds, etc. we should emit a warning regarding unsupported speeds rather than use the bogus default of "10Mbps" which isn't even an option in the firmware Port Information message Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 0b7570ddbe1a..9f1f5b2aacf7 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -275,7 +275,7 @@ static void link_report(struct net_device *dev) else { static const char *fc[] = { "no", "Rx", "Tx", "Tx/Rx" }; - const char *s = "10Mbps"; + const char *s; const struct port_info *p = netdev_priv(dev); switch (p->link_cfg.speed) { @@ -291,6 +291,10 @@ static void link_report(struct net_device *dev) case 40000: s = "40Gbps"; break; + default: + pr_info("%s: unsupported speed: %d\n", + dev->name, p->link_cfg.speed); + return; } netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s, -- cgit v1.2.3 From 5bd166872d8f99f156fac191299d24f828bb2348 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 15 Sep 2015 14:36:09 +0200 Subject: iwlwifi: dvm: fix D3 firmware PN programming The code to send the RX PN data (for each TID) to the firmware has a devastating bug: it overwrites the data for TID 0 with all the TID data, leaving the remaining TIDs zeroed. This will allow replays to actually be accepted by the firmware, which could allow waking up the system. Cc: [3.1+] Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/dvm/lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index ab45819c1fbb..e18629a16fb0 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c @@ -1020,7 +1020,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw, u8 *pn = seq.ccmp.pn; ieee80211_get_key_rx_seq(key, i, &seq); - aes_sc->pn = cpu_to_le64( + aes_sc[i].pn = cpu_to_le64( (u64)pn[5] | ((u64)pn[4] << 8) | ((u64)pn[3] << 16) | -- cgit v1.2.3 From 2cf5eb3ab7bb7f2e3a70edcef236cd62c87db030 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 15 Sep 2015 14:36:09 +0200 Subject: iwlwifi: mvm: fix D3 firmware PN programming The code to send the RX PN data (for each TID) to the firmware has a devastating bug: it overwrites the data for TID 0 with all the TID data, leaving the remaining TIDs zeroed. This will allow replays to actually be accepted by the firmware, which could allow waking up the system. Cc: [3.1+] Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/d3.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 9578b9d663dc..576187611e61 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c @@ -293,12 +293,12 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, u8 *pn = seq.ccmp.pn; ieee80211_get_key_rx_seq(key, i, &seq); - aes_sc->pn = cpu_to_le64((u64)pn[5] | - ((u64)pn[4] << 8) | - ((u64)pn[3] << 16) | - ((u64)pn[2] << 24) | - ((u64)pn[1] << 32) | - ((u64)pn[0] << 40)); + aes_sc[i].pn = cpu_to_le64((u64)pn[5] | + ((u64)pn[4] << 8) | + ((u64)pn[3] << 16) | + ((u64)pn[2] << 24) | + ((u64)pn[1] << 32) | + ((u64)pn[0] << 40)); } data->use_rsc_tsc = true; break; -- cgit v1.2.3 From cc809237e1f215141165f221ad729803d88bcbbe Mon Sep 17 00:00:00 2001 From: Govindarajulu Varadarajan <_govind@gmx.com> Date: Thu, 1 Oct 2015 14:18:46 +0530 Subject: enic: handle spurious error interrupt Some of the enic adaptors are know to generate spurious interrupts. When error interrupt is generated, driver just resets the device. This patch resets the device only when an error is occurred. Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com> Signed-off-by: David S. Miller --- drivers/net/ethernet/cisco/enic/enic_main.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 3352d027ab89..0b5442986507 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -178,13 +178,15 @@ static int enic_wq_service(struct vnic_dev *vdev, struct cq_desc *cq_desc, return 0; } -static void enic_log_q_error(struct enic *enic) +static bool enic_log_q_error(struct enic *enic) { unsigned int i; u32 error_status; + bool err = false; for (i = 0; i < enic->wq_count; i++) { error_status = vnic_wq_error_status(&enic->wq[i]); + err |= error_status; if (error_status) netdev_err(enic->netdev, "WQ[%d] error_status %d\n", i, error_status); @@ -192,10 +194,13 @@ static void enic_log_q_error(struct enic *enic) for (i = 0; i < enic->rq_count; i++) { error_status = vnic_rq_error_status(&enic->rq[i]); + err |= error_status; if (error_status) netdev_err(enic->netdev, "RQ[%d] error_status %d\n", i, error_status); } + + return err; } static void enic_msglvl_check(struct enic *enic) @@ -333,10 +338,9 @@ static irqreturn_t enic_isr_msix_err(int irq, void *data) vnic_intr_return_all_credits(&enic->intr[intr]); - enic_log_q_error(enic); - - /* schedule recovery from WQ/RQ error */ - schedule_work(&enic->reset); + if (enic_log_q_error(enic)) + /* schedule recovery from WQ/RQ error */ + schedule_work(&enic->reset); return IRQ_HANDLED; } -- cgit v1.2.3 From 937317c7c1097aa878a5000e3aab616eb5c590c0 Mon Sep 17 00:00:00 2001 From: Govindarajulu Varadarajan <_govind@gmx.com> Date: Thu, 1 Oct 2015 14:18:47 +0530 Subject: enic: do hang reset only in case of tx timeout The current code invokes hang reset in case of error interrupt. We should hang reset only in case of tx timeout. This because of the way hang reset is implemented in firmware. Hang reset takes more firmware resources than soft reset. Adaptor does not generate error interrupt in case of tx timeout. Hang reset only in case of tx timeout, in .ndo_tx_timeout. Do soft reset otherwise. Introduce deferred work, enic_tx_hang_reset, to do hang reset. Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com> Signed-off-by: David S. Miller --- drivers/net/ethernet/cisco/enic/enic.h | 1 + drivers/net/ethernet/cisco/enic/enic_main.c | 36 ++++++++++++++++++++++++++++- drivers/net/ethernet/cisco/enic/vnic_dev.c | 4 ++-- drivers/net/ethernet/cisco/enic/vnic_dev.h | 2 ++ 4 files changed, 40 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h index 8b53f7d4bebf..6401ba99457f 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -143,6 +143,7 @@ struct enic { struct vnic_dev *vdev; struct timer_list notify_timer; struct work_struct reset; + struct work_struct tx_hang_reset; struct work_struct change_mtu_work; struct msix_entry msix_entry[ENIC_INTR_MAX]; struct enic_msix_entry msix[ENIC_INTR_MAX]; diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 0b5442986507..0c22fd014378 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -808,7 +808,7 @@ static void enic_set_rx_mode(struct net_device *netdev) static void enic_tx_timeout(struct net_device *netdev) { struct enic *enic = netdev_priv(netdev); - schedule_work(&enic->reset); + schedule_work(&enic->tx_hang_reset); } static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) @@ -1928,6 +1928,19 @@ static int enic_dev_open(struct enic *enic) return err; } +static int enic_dev_soft_reset(struct enic *enic) +{ + int err; + + err = enic_dev_wait(enic->vdev, vnic_dev_soft_reset, + vnic_dev_soft_reset_done, 0); + if (err) + netdev_err(enic->netdev, "vNIC soft reset failed, err %d\n", + err); + + return err; +} + static int enic_dev_hang_reset(struct enic *enic) { int err; @@ -2063,6 +2076,26 @@ static void enic_reset(struct work_struct *work) rtnl_lock(); + spin_lock(&enic->enic_api_lock); + enic_stop(enic->netdev); + enic_dev_soft_reset(enic); + enic_reset_addr_lists(enic); + enic_init_vnic_resources(enic); + enic_set_rss_nic_cfg(enic); + enic_dev_set_ig_vlan_rewrite_mode(enic); + enic_open(enic->netdev); + spin_unlock(&enic->enic_api_lock); + call_netdevice_notifiers(NETDEV_REBOOT, enic->netdev); + + rtnl_unlock(); +} + +static void enic_tx_hang_reset(struct work_struct *work) +{ + struct enic *enic = container_of(work, struct enic, tx_hang_reset); + + rtnl_lock(); + spin_lock(&enic->enic_api_lock); enic_dev_hang_notify(enic); enic_stop(enic->netdev); @@ -2587,6 +2620,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) enic_set_rx_coal_setting(enic); INIT_WORK(&enic->reset, enic_reset); + INIT_WORK(&enic->tx_hang_reset, enic_tx_hang_reset); INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work); for (i = 0; i < enic->wq_count; i++) diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.c b/drivers/net/ethernet/cisco/enic/vnic_dev.c index a3badefaf360..1ffd1050860b 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_dev.c +++ b/drivers/net/ethernet/cisco/enic/vnic_dev.c @@ -659,14 +659,14 @@ int vnic_dev_open_done(struct vnic_dev *vdev, int *done) return 0; } -static int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg) +int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg) { u64 a0 = (u32)arg, a1 = 0; int wait = 1000; return vnic_dev_cmd(vdev, CMD_SOFT_RESET, &a0, &a1, wait); } -static int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done) +int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done) { u64 a0 = 0, a1 = 0; int wait = 1000; diff --git a/drivers/net/ethernet/cisco/enic/vnic_dev.h b/drivers/net/ethernet/cisco/enic/vnic_dev.h index b013b6a78e87..54156c484424 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_dev.h +++ b/drivers/net/ethernet/cisco/enic/vnic_dev.h @@ -155,7 +155,9 @@ int vnic_dev_deinit(struct vnic_dev *vdev); void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev); int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev); int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg); +int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg); int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done); +int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done); void vnic_dev_set_intr_mode(struct vnic_dev *vdev, enum vnic_dev_intr_mode intr_mode); enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev); -- cgit v1.2.3 From e9cb0327b26dd7ba43a3b7a05b4b62219decf42d Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Mon, 31 Aug 2015 11:08:27 +0300 Subject: iwlwifi: mvm: clear csa countdown when AP is stopped The csa_countdown flag was not cleared when the AP is stopped. As a result, if the AP was stopped after csa_countdown had started, all the folowing channel switch commands would fail. Fix that by clearing the csa_countdown flag when the AP is stopped. Cc: [3.17+] Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index aa8c2b7f23c7..7c2944a72470 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -2388,6 +2388,7 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); RCU_INIT_POINTER(mvm->csa_vif, NULL); + mvmvif->csa_countdown = false; } if (rcu_access_pointer(mvm->csa_tx_blocked_vif) == vif) { -- cgit v1.2.3 From b5a48134f8af08f5243328f8a0b05fc5ae7cf343 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 22 Sep 2015 10:47:27 +0200 Subject: iwlwifi: fix firmware filename for 3160 The MODULE_FIRMWARE() for 3160 should be using the 7260 version as it's done in the device configuration struct instead of referencing IWL3160_UCODE_API_OK which doesn't even exist. Cc: [3.8+] Reported-by: Hauke Mehrtens Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/iwl-7000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 6951aba620eb..3fb327d5a911 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -348,6 +348,6 @@ const struct iwl_cfg iwl7265d_n_cfg = { }; MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); -MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); +MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); -- cgit v1.2.3 From f08f625876476b6c4a87834dc86e3b927f4697d2 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 22 Sep 2015 09:44:39 +0300 Subject: iwlwifi: pci: add a few more PCI subvendor IDs for the 7265 series Add 3 new subdevice IDs for the 0x095A device ID and 2 for the 0x095B device ID. Cc: [3.13+] Reported-by: Jeremy Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/pcie/drv.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index b0825c402c73..644b58bc5226 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -414,6 +414,11 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x095A, 0x5590, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5F10, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095B, 0x5212, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095B, 0x520A, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x9000, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x9400, iwl7265_2ac_cfg)}, /* 8000 Series */ {IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)}, -- cgit v1.2.3 From 1a3fe0b2b6778b7866e2b3f5c9a299d5e9bbd89c Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Wed, 30 Sep 2015 11:19:55 +0300 Subject: iwlwifi: mvm: init card correctly on ctkill exit check During the CT-kill exit flow, the card is powered up and partially initialized to check if the temperature is already low enough. Unfortunately the init bails early because the CT-kill flag is set. Make the code bail early only for HW RF-kill, as was intended by the author. CT-kill is self-imposed and is not really RF-kill. Fixes: 31b8b343e019 ("iwlwifi: fix RFkill while calibrating") Cc: [3.18+] Signed-off-by: Arik Nemtsov Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/fw.c | 4 ++-- drivers/net/wireless/iwlwifi/mvm/mvm.h | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 4a0ce83315bd..5c7f7cc9ffcc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c @@ -703,7 +703,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) * abort after reading the nvm in case RF Kill is on, we will complete * the init seq later when RF kill will switch to off */ - if (iwl_mvm_is_radio_killed(mvm)) { + if (iwl_mvm_is_radio_hw_killed(mvm)) { IWL_DEBUG_RF_KILL(mvm, "jump over all phy activities due to RF kill\n"); iwl_remove_notification(&mvm->notif_wait, &calib_wait); @@ -736,7 +736,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait, MVM_UCODE_CALIB_TIMEOUT); - if (ret && iwl_mvm_is_radio_killed(mvm)) { + if (ret && iwl_mvm_is_radio_hw_killed(mvm)) { IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n"); ret = 1; } diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index b95a07ec9e36..c754051a4cea 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -860,6 +860,11 @@ static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status); } +static inline bool iwl_mvm_is_radio_hw_killed(struct iwl_mvm *mvm) +{ + return test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); +} + /* Must be called with rcu_read_lock() held and it can only be * released when mvmsta is not needed anymore. */ -- cgit v1.2.3 From 04fbfce7a222327b97ca165294ef19f0faa45960 Mon Sep 17 00:00:00 2001 From: Jon Ringle Date: Thu, 1 Oct 2015 07:43:21 -0400 Subject: net: Microchip encx24j600 driver This ethernet driver supports the Micorchip enc424j600/626j600 Ethernet controller over a SPI bus interface. This driver makes use of the regmap API to optimize access to registers by caching registers where possible. Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/39935b.pdf Signed-off-by: Jon Ringle Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/Kconfig | 9 + drivers/net/ethernet/microchip/Makefile | 1 + drivers/net/ethernet/microchip/encx24j600-regmap.c | 551 ++++++++++ drivers/net/ethernet/microchip/encx24j600.c | 1124 ++++++++++++++++++++ drivers/net/ethernet/microchip/encx24j600_hw.h | 437 ++++++++ 5 files changed, 2122 insertions(+) create mode 100644 drivers/net/ethernet/microchip/encx24j600-regmap.c create mode 100644 drivers/net/ethernet/microchip/encx24j600.c create mode 100644 drivers/net/ethernet/microchip/encx24j600_hw.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig index 3fd8ca6d4e7c..992b01462a8f 100644 --- a/drivers/net/ethernet/microchip/Kconfig +++ b/drivers/net/ethernet/microchip/Kconfig @@ -33,4 +33,13 @@ config ENC28J60_WRITEVERIFY Enable the verify after the buffer write useful for debugging purpose. If unsure, say N. +config ENCX24J600 + tristate "ENCX24J600 support" + depends on SPI + ---help--- + Support for the Microchip ENC424J600 ethernet chip. + + To compile this driver as a module, choose M here. The module will be + called enc424j600. + endif # NET_VENDOR_MICROCHIP diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile index 573d4292b9ea..ff78f621b59a 100644 --- a/drivers/net/ethernet/microchip/Makefile +++ b/drivers/net/ethernet/microchip/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_ENC28J60) += enc28j60.o +obj-$(CONFIG_ENCX24J600) += encx24j600.o encx24j600-regmap.o diff --git a/drivers/net/ethernet/microchip/encx24j600-regmap.c b/drivers/net/ethernet/microchip/encx24j600-regmap.c new file mode 100644 index 000000000000..f1d74e300b24 --- /dev/null +++ b/drivers/net/ethernet/microchip/encx24j600-regmap.c @@ -0,0 +1,551 @@ +/** + * Register map access API - ENCX24J600 support + * + * Copyright 2015 Gridpoint + * + * Author: Jon Ringle + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "encx24j600_hw.h" + +static inline bool is_bits_set(int value, int mask) +{ + return (value & mask) == mask; +} + +static int encx24j600_switch_bank(struct encx24j600_context *ctx, + int bank) +{ + int ret = 0; + + int bank_opcode = BANK_SELECT(bank); + ret = spi_write(ctx->spi, &bank_opcode, 1); + if (ret == 0) + ctx->bank = bank; + + return ret; +} + +static int encx24j600_cmdn(struct encx24j600_context *ctx, u8 opcode, + const void *buf, size_t len) +{ + struct spi_message m; + struct spi_transfer t[2] = { { .tx_buf = &opcode, .len = 1, }, + { .tx_buf = buf, .len = len }, }; + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + return spi_sync(ctx->spi, &m); +} + +static void regmap_lock_mutex(void *context) +{ + struct encx24j600_context *ctx = context; + mutex_lock(&ctx->mutex); +} + +static void regmap_unlock_mutex(void *context) +{ + struct encx24j600_context *ctx = context; + mutex_unlock(&ctx->mutex); +} + +static int regmap_encx24j600_sfr_read(void *context, u8 reg, u8 *val, + size_t len) +{ + struct encx24j600_context *ctx = context; + u8 banked_reg = reg & ADDR_MASK; + u8 bank = ((reg & BANK_MASK) >> BANK_SHIFT); + u8 cmd = RCRU; + int ret = 0; + int i = 0; + u8 tx_buf[2]; + + if (reg < 0x80) { + cmd = RCRCODE | banked_reg; + if ((banked_reg < 0x16) && (ctx->bank != bank)) + ret = encx24j600_switch_bank(ctx, bank); + if (unlikely(ret)) + return ret; + } else { + /* Translate registers that are more effecient using + * 3-byte SPI commands + */ + switch (reg) { + case EGPRDPT: + cmd = RGPRDPT; break; + case EGPWRPT: + cmd = RGPWRPT; break; + case ERXRDPT: + cmd = RRXRDPT; break; + case ERXWRPT: + cmd = RRXWRPT; break; + case EUDARDPT: + cmd = RUDARDPT; break; + case EUDAWRPT: + cmd = RUDAWRPT; break; + case EGPDATA: + case ERXDATA: + case EUDADATA: + default: + return -EINVAL; + } + } + + tx_buf[i++] = cmd; + if (cmd == RCRU) + tx_buf[i++] = reg; + + ret = spi_write_then_read(ctx->spi, tx_buf, i, val, len); + + return ret; +} + +static int regmap_encx24j600_sfr_update(struct encx24j600_context *ctx, + u8 reg, u8 *val, size_t len, + u8 unbanked_cmd, u8 banked_code) +{ + u8 banked_reg = reg & ADDR_MASK; + u8 bank = ((reg & BANK_MASK) >> BANK_SHIFT); + u8 cmd = unbanked_cmd; + struct spi_message m; + struct spi_transfer t[3] = { { .tx_buf = &cmd, .len = sizeof(cmd), }, + { .tx_buf = ®, .len = sizeof(reg), }, + { .tx_buf = val, .len = len }, }; + + if (reg < 0x80) { + int ret = 0; + cmd = banked_code | banked_reg; + if ((banked_reg < 0x16) && (ctx->bank != bank)) + ret = encx24j600_switch_bank(ctx, bank); + if (unlikely(ret)) + return ret; + } else { + /* Translate registers that are more effecient using + * 3-byte SPI commands + */ + switch (reg) { + case EGPRDPT: + cmd = WGPRDPT; break; + case EGPWRPT: + cmd = WGPWRPT; break; + case ERXRDPT: + cmd = WRXRDPT; break; + case ERXWRPT: + cmd = WRXWRPT; break; + case EUDARDPT: + cmd = WUDARDPT; break; + case EUDAWRPT: + cmd = WUDAWRPT; break; + case EGPDATA: + case ERXDATA: + case EUDADATA: + default: + return -EINVAL; + } + } + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + + if (cmd == unbanked_cmd) { + t[1].tx_buf = ® + spi_message_add_tail(&t[1], &m); + } + + spi_message_add_tail(&t[2], &m); + return spi_sync(ctx->spi, &m); +} + +static int regmap_encx24j600_sfr_write(void *context, u8 reg, u8 *val, + size_t len) +{ + struct encx24j600_context *ctx = context; + return regmap_encx24j600_sfr_update(ctx, reg, val, len, WCRU, WCRCODE); +} + +static int regmap_encx24j600_sfr_set_bits(struct encx24j600_context *ctx, + u8 reg, u8 val) +{ + return regmap_encx24j600_sfr_update(ctx, reg, &val, 1, BFSU, BFSCODE); +} + +static int regmap_encx24j600_sfr_clr_bits(struct encx24j600_context *ctx, + u8 reg, u8 val) +{ + return regmap_encx24j600_sfr_update(ctx, reg, &val, 1, BFCU, BFCCODE); +} + +static int regmap_encx24j600_reg_update_bits(void *context, unsigned int reg, + unsigned int mask, + unsigned int val, bool *change, + bool force_write) +{ + struct encx24j600_context *ctx = context; + + int ret = 0; + unsigned int set_mask = mask & val; + unsigned int clr_mask = mask & ~val; + + if (change) + *change = false; + + if ((reg >= 0x40 && reg < 0x6c) || reg >= 0x80) { + /* Must do read/modify/write cycles for + * MAC/MII regs or Unbanked SFR regs + */ + u16 tmp, orig; + + ret = regmap_encx24j600_sfr_read(context, reg, (u8 *)&orig, + sizeof(orig)); + if (ret != 0) + return ret; + + tmp = orig & ~mask; + tmp |= val & mask; + + if (force_write || (tmp != orig)) { + ret = regmap_encx24j600_sfr_write(context, reg, + (u8 *)&tmp, + sizeof(tmp)); + if (change) + *change = true; + } else if (change) { + *change = false; + } + + return ret; + } + + if (set_mask & 0xff) { + ret = regmap_encx24j600_sfr_set_bits(ctx, reg, set_mask); + if (ret == 0 && change) + *change = true; + } + set_mask = (set_mask & 0xff00) >> 8; + + if ((set_mask & 0xff) && (ret == 0)) { + ret = regmap_encx24j600_sfr_set_bits(ctx, reg + 1, set_mask); + if (ret == 0 && change) + *change = true; + } + + if ((clr_mask & 0xff) && (ret == 0)) { + ret = regmap_encx24j600_sfr_clr_bits(ctx, reg, clr_mask); + if (ret == 0 && change) + *change = true; + } + clr_mask = (clr_mask & 0xff00) >> 8; + + if ((clr_mask & 0xff) && (ret == 0)) { + ret = regmap_encx24j600_sfr_clr_bits(ctx, reg + 1, clr_mask); + if (ret == 0 && change) + *change = true; + } + + return ret; +} + +int regmap_encx24j600_spi_write(void *context, u8 reg, const u8 *data, + size_t count) +{ + struct encx24j600_context *ctx = context; + + if (reg < 0xc0) + return encx24j600_cmdn(ctx, reg, data, count); + else + /* SPI 1-byte command. Ignore data */ + return spi_write(ctx->spi, ®, 1); +} +EXPORT_SYMBOL_GPL(regmap_encx24j600_spi_write); + +int regmap_encx24j600_spi_read(void *context, u8 reg, u8 *data, size_t count) +{ + struct encx24j600_context *ctx = context; + + if (reg == RBSEL && count > 1) + count = 1; + + return spi_write_then_read(ctx->spi, ®, sizeof(reg), data, count); +} +EXPORT_SYMBOL_GPL(regmap_encx24j600_spi_read); + +static int regmap_encx24j600_write(void *context, const void *data, + size_t len) +{ + u8 *dout = (u8 *)data; + u8 reg = dout[0]; + ++dout; + --len; + + if (reg > 0xa0) + return regmap_encx24j600_spi_write(context, reg, dout, len); + + if (len > 2) + return -EINVAL; + + return regmap_encx24j600_sfr_write(context, reg, dout, len); +} + +static int regmap_encx24j600_read(void *context, + const void *reg_buf, size_t reg_size, + void *val, size_t val_size) +{ + u8 reg = *(const u8 *)reg_buf; + + if (reg_size != 1) { + pr_err("%s: reg=%02x reg_size=%zu\n", __func__, reg, reg_size); + return -EINVAL; + } + + if (reg > 0xa0) + return regmap_encx24j600_spi_read(context, reg, val, val_size); + + if (val_size > 2) { + pr_err("%s: reg=%02x val_size=%zu\n", __func__, reg, val_size); + return -EINVAL; + } + + return regmap_encx24j600_sfr_read(context, reg, val, val_size); +} + +static bool encx24j600_regmap_readable(struct device *dev, unsigned int reg) +{ + if ((reg < 0x36) || + ((reg >= 0x40) && (reg < 0x4c)) || + ((reg >= 0x52) && (reg < 0x56)) || + ((reg >= 0x60) && (reg < 0x66)) || + ((reg >= 0x68) && (reg < 0x80)) || + ((reg >= 0x86) && (reg < 0x92)) || + (reg == 0xc8)) + return true; + else + return false; +} + +static bool encx24j600_regmap_writeable(struct device *dev, unsigned int reg) +{ + if ((reg < 0x12) || + ((reg >= 0x14) && (reg < 0x1a)) || + ((reg >= 0x1c) && (reg < 0x36)) || + ((reg >= 0x40) && (reg < 0x4c)) || + ((reg >= 0x52) && (reg < 0x56)) || + ((reg >= 0x60) && (reg < 0x68)) || + ((reg >= 0x6c) && (reg < 0x80)) || + ((reg >= 0x86) && (reg < 0x92)) || + ((reg >= 0xc0) && (reg < 0xc8)) || + ((reg >= 0xca) && (reg < 0xf0))) + return true; + else + return false; +} + +static bool encx24j600_regmap_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ERXHEAD: + case EDMACS: + case ETXSTAT: + case ETXWIRE: + case ECON1: /* Can be modified via single byte cmds */ + case ECON2: /* Can be modified via single byte cmds */ + case ESTAT: + case EIR: /* Can be modified via single byte cmds */ + case MIRD: + case MISTAT: + return true; + default: + break; + } + + return false; +} + +static bool encx24j600_regmap_precious(struct device *dev, unsigned int reg) +{ + /* single byte cmds are precious */ + if (((reg >= 0xc0) && (reg < 0xc8)) || + ((reg >= 0xca) && (reg < 0xf0))) + return true; + else + return false; +} + +static int regmap_encx24j600_phy_reg_read(void *context, unsigned int reg, + unsigned int *val) +{ + struct encx24j600_context *ctx = context; + int ret; + unsigned int mistat; + + reg = MIREGADR_VAL | (reg & PHREG_MASK); + ret = regmap_write(ctx->regmap, MIREGADR, reg); + if (unlikely(ret)) + goto err_out; + + ret = regmap_write(ctx->regmap, MICMD, MIIRD); + if (unlikely(ret)) + goto err_out; + + usleep_range(26, 100); + while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) && + (mistat & BUSY)) + cpu_relax(); + + if (unlikely(ret)) + goto err_out; + + ret = regmap_write(ctx->regmap, MICMD, 0); + if (unlikely(ret)) + goto err_out; + + ret = regmap_read(ctx->regmap, MIRD, val); + +err_out: + if (ret) + pr_err("%s: error %d reading reg %02x\n", __func__, ret, + reg & PHREG_MASK); + + return ret; +} + +static int regmap_encx24j600_phy_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + struct encx24j600_context *ctx = context; + int ret; + unsigned int mistat; + + reg = MIREGADR_VAL | (reg & PHREG_MASK); + ret = regmap_write(ctx->regmap, MIREGADR, reg); + if (unlikely(ret)) + goto err_out; + + ret = regmap_write(ctx->regmap, MIWR, val); + if (unlikely(ret)) + goto err_out; + + usleep_range(26, 100); + while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) && + (mistat & BUSY)) + cpu_relax(); + +err_out: + if (ret) + pr_err("%s: error %d writing reg %02x=%04x\n", __func__, ret, + reg & PHREG_MASK, val); + + return ret; +} + +static bool encx24j600_phymap_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PHCON1: + case PHSTAT1: + case PHANA: + case PHANLPA: + case PHANE: + case PHCON2: + case PHSTAT2: + case PHSTAT3: + return true; + default: + return false; + } +} + +static bool encx24j600_phymap_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PHCON1: + case PHCON2: + case PHANA: + return true; + case PHSTAT1: + case PHSTAT2: + case PHSTAT3: + case PHANLPA: + case PHANE: + default: + return false; + } +} + +static bool encx24j600_phymap_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PHSTAT1: + case PHSTAT2: + case PHSTAT3: + case PHANLPA: + case PHANE: + case PHCON2: + return true; + default: + return false; + } +} + +static struct regmap_config regcfg = { + .name = "reg", + .reg_bits = 8, + .val_bits = 16, + .max_register = 0xee, + .reg_stride = 2, + .cache_type = REGCACHE_RBTREE, + .val_format_endian = REGMAP_ENDIAN_LITTLE, + .readable_reg = encx24j600_regmap_readable, + .writeable_reg = encx24j600_regmap_writeable, + .volatile_reg = encx24j600_regmap_volatile, + .precious_reg = encx24j600_regmap_precious, + .lock = regmap_lock_mutex, + .unlock = regmap_unlock_mutex, +}; + +static struct regmap_bus regmap_encx24j600 = { + .write = regmap_encx24j600_write, + .read = regmap_encx24j600_read, + .reg_update_bits = regmap_encx24j600_reg_update_bits, +}; + +static struct regmap_config phycfg = { + .name = "phy", + .reg_bits = 8, + .val_bits = 16, + .max_register = 0x1f, + .cache_type = REGCACHE_RBTREE, + .val_format_endian = REGMAP_ENDIAN_LITTLE, + .readable_reg = encx24j600_phymap_readable, + .writeable_reg = encx24j600_phymap_writeable, + .volatile_reg = encx24j600_phymap_volatile, +}; +static struct regmap_bus phymap_encx24j600 = { + .reg_write = regmap_encx24j600_phy_reg_write, + .reg_read = regmap_encx24j600_phy_reg_read, +}; + +void devm_regmap_init_encx24j600(struct device *dev, + struct encx24j600_context *ctx) +{ + mutex_init(&ctx->mutex); + regcfg.lock_arg = ctx; + ctx->regmap = devm_regmap_init(dev, ®map_encx24j600, ctx, ®cfg); + ctx->phymap = devm_regmap_init(dev, &phymap_encx24j600, ctx, &phycfg); +} +EXPORT_SYMBOL_GPL(devm_regmap_init_encx24j600); + +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c new file mode 100644 index 000000000000..1da37fddab42 --- /dev/null +++ b/drivers/net/ethernet/microchip/encx24j600.c @@ -0,0 +1,1124 @@ +/** + * Microchip ENCX24J600 ethernet driver + * + * Copyright (C) 2015 Gridpoint + * Author: Jon Ringle + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "encx24j600_hw.h" + +#define DRV_NAME "encx24j600" +#define DRV_VERSION "1.0" + +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) +static int debug = -1; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + +/* SRAM memory layout: + * + * 0x0000-0x05ff TX buffers 1.5KB (1*1536) reside in the GP area in SRAM + * 0x0600-0x5fff RX buffers 22.5KB (15*1536) reside in the RX area in SRAM + */ +#define ENC_TX_BUF_START 0x0000U +#define ENC_RX_BUF_START 0x0600U +#define ENC_RX_BUF_END 0x5fffU +#define ENC_SRAM_SIZE 0x6000U + +enum { + RXFILTER_NORMAL, + RXFILTER_MULTI, + RXFILTER_PROMISC +}; + +struct encx24j600_priv { + struct net_device *ndev; + struct mutex lock; /* device access lock */ + struct encx24j600_context ctx; + struct sk_buff *tx_skb; + struct task_struct *kworker_task; + struct kthread_worker kworker; + struct kthread_work tx_work; + struct kthread_work setrx_work; + u16 next_packet; + bool hw_enabled; + bool full_duplex; + bool autoneg; + u16 speed; + int rxfilter; + u32 msg_enable; +}; + +static void dump_packet(const char *msg, int len, const char *data) +{ + pr_debug(DRV_NAME ": %s - packet len:%d\n", msg, len); + print_hex_dump_bytes("pk data: ", DUMP_PREFIX_OFFSET, data, len); +} + +static void encx24j600_dump_rsv(struct encx24j600_priv *priv, const char *msg, + struct rsv *rsv) +{ + struct net_device *dev = priv->ndev; + + netdev_info(dev, "RX packet Len:%d\n", rsv->len); + netdev_dbg(dev, "%s - NextPk: 0x%04x\n", msg, + rsv->next_packet); + netdev_dbg(dev, "RxOK: %d, DribbleNibble: %d\n", + RSV_GETBIT(rsv->rxstat, RSV_RXOK), + RSV_GETBIT(rsv->rxstat, RSV_DRIBBLENIBBLE)); + netdev_dbg(dev, "CRCErr:%d, LenChkErr: %d, LenOutOfRange: %d\n", + RSV_GETBIT(rsv->rxstat, RSV_CRCERROR), + RSV_GETBIT(rsv->rxstat, RSV_LENCHECKERR), + RSV_GETBIT(rsv->rxstat, RSV_LENOUTOFRANGE)); + netdev_dbg(dev, "Multicast: %d, Broadcast: %d, LongDropEvent: %d, CarrierEvent: %d\n", + RSV_GETBIT(rsv->rxstat, RSV_RXMULTICAST), + RSV_GETBIT(rsv->rxstat, RSV_RXBROADCAST), + RSV_GETBIT(rsv->rxstat, RSV_RXLONGEVDROPEV), + RSV_GETBIT(rsv->rxstat, RSV_CARRIEREV)); + netdev_dbg(dev, "ControlFrame: %d, PauseFrame: %d, UnknownOp: %d, VLanTagFrame: %d\n", + RSV_GETBIT(rsv->rxstat, RSV_RXCONTROLFRAME), + RSV_GETBIT(rsv->rxstat, RSV_RXPAUSEFRAME), + RSV_GETBIT(rsv->rxstat, RSV_RXUNKNOWNOPCODE), + RSV_GETBIT(rsv->rxstat, RSV_RXTYPEVLAN)); +} + +static u16 encx24j600_read_reg(struct encx24j600_priv *priv, u8 reg) +{ + struct net_device *dev = priv->ndev; + unsigned int val = 0; + int ret = regmap_read(priv->ctx.regmap, reg, &val); + if (unlikely(ret)) + netif_err(priv, drv, dev, "%s: error %d reading reg %02x\n", + __func__, ret, reg); + return val; +} + +static void encx24j600_write_reg(struct encx24j600_priv *priv, u8 reg, u16 val) +{ + struct net_device *dev = priv->ndev; + int ret = regmap_write(priv->ctx.regmap, reg, val); + if (unlikely(ret)) + netif_err(priv, drv, dev, "%s: error %d writing reg %02x=%04x\n", + __func__, ret, reg, val); +} + +static void encx24j600_update_reg(struct encx24j600_priv *priv, u8 reg, + u16 mask, u16 val) +{ + struct net_device *dev = priv->ndev; + int ret = regmap_update_bits(priv->ctx.regmap, reg, mask, val); + if (unlikely(ret)) + netif_err(priv, drv, dev, "%s: error %d updating reg %02x=%04x~%04x\n", + __func__, ret, reg, val, mask); +} + +static u16 encx24j600_read_phy(struct encx24j600_priv *priv, u8 reg) +{ + struct net_device *dev = priv->ndev; + unsigned int val = 0; + int ret = regmap_read(priv->ctx.phymap, reg, &val); + if (unlikely(ret)) + netif_err(priv, drv, dev, "%s: error %d reading %02x\n", + __func__, ret, reg); + return val; +} + +static void encx24j600_write_phy(struct encx24j600_priv *priv, u8 reg, u16 val) +{ + struct net_device *dev = priv->ndev; + int ret = regmap_write(priv->ctx.phymap, reg, val); + if (unlikely(ret)) + netif_err(priv, drv, dev, "%s: error %d writing reg %02x=%04x\n", + __func__, ret, reg, val); +} + +static void encx24j600_clr_bits(struct encx24j600_priv *priv, u8 reg, u16 mask) +{ + encx24j600_update_reg(priv, reg, mask, 0); +} + +static void encx24j600_set_bits(struct encx24j600_priv *priv, u8 reg, u16 mask) +{ + encx24j600_update_reg(priv, reg, mask, mask); +} + +static void encx24j600_cmd(struct encx24j600_priv *priv, u8 cmd) +{ + struct net_device *dev = priv->ndev; + int ret = regmap_write(priv->ctx.regmap, cmd, 0); + if (unlikely(ret)) + netif_err(priv, drv, dev, "%s: error %d with cmd %02x\n", + __func__, ret, cmd); +} + +static int encx24j600_raw_read(struct encx24j600_priv *priv, u8 reg, u8 *data, + size_t count) +{ + int ret; + mutex_lock(&priv->ctx.mutex); + ret = regmap_encx24j600_spi_read(&priv->ctx, reg, data, count); + mutex_unlock(&priv->ctx.mutex); + + return ret; +} + +static int encx24j600_raw_write(struct encx24j600_priv *priv, u8 reg, + const u8 *data, size_t count) +{ + int ret; + mutex_lock(&priv->ctx.mutex); + ret = regmap_encx24j600_spi_write(&priv->ctx, reg, data, count); + mutex_unlock(&priv->ctx.mutex); + + return ret; +} + +static void encx24j600_update_phcon1(struct encx24j600_priv *priv) +{ + u16 phcon1 = encx24j600_read_phy(priv, PHCON1); + if (priv->autoneg == AUTONEG_ENABLE) { + phcon1 |= ANEN | RENEG; + } else { + phcon1 &= ~ANEN; + if (priv->speed == SPEED_100) + phcon1 |= SPD100; + else + phcon1 &= ~SPD100; + + if (priv->full_duplex) + phcon1 |= PFULDPX; + else + phcon1 &= ~PFULDPX; + } + encx24j600_write_phy(priv, PHCON1, phcon1); +} + +/* Waits for autonegotiation to complete. */ +static int encx24j600_wait_for_autoneg(struct encx24j600_priv *priv) +{ + struct net_device *dev = priv->ndev; + unsigned long timeout = jiffies + msecs_to_jiffies(2000); + u16 phstat1; + u16 estat; + int ret = 0; + + phstat1 = encx24j600_read_phy(priv, PHSTAT1); + while ((phstat1 & ANDONE) == 0) { + if (time_after(jiffies, timeout)) { + u16 phstat3; + + netif_notice(priv, drv, dev, "timeout waiting for autoneg done\n"); + + priv->autoneg = AUTONEG_DISABLE; + phstat3 = encx24j600_read_phy(priv, PHSTAT3); + priv->speed = (phstat3 & PHY3SPD100) + ? SPEED_100 : SPEED_10; + priv->full_duplex = (phstat3 & PHY3DPX) ? 1 : 0; + encx24j600_update_phcon1(priv); + netif_notice(priv, drv, dev, "Using parallel detection: %s/%s", + priv->speed == SPEED_100 ? "100" : "10", + priv->full_duplex ? "Full" : "Half"); + + return -ETIMEDOUT; + } + cpu_relax(); + phstat1 = encx24j600_read_phy(priv, PHSTAT1); + } + + estat = encx24j600_read_reg(priv, ESTAT); + if (estat & PHYDPX) { + encx24j600_set_bits(priv, MACON2, FULDPX); + encx24j600_write_reg(priv, MABBIPG, 0x15); + } else { + encx24j600_clr_bits(priv, MACON2, FULDPX); + encx24j600_write_reg(priv, MABBIPG, 0x12); + /* Max retransmittions attempt */ + encx24j600_write_reg(priv, MACLCON, 0x370f); + } + + return ret; +} + +/* Access the PHY to determine link status */ +static void encx24j600_check_link_status(struct encx24j600_priv *priv) +{ + struct net_device *dev = priv->ndev; + u16 estat; + + estat = encx24j600_read_reg(priv, ESTAT); + + if (estat & PHYLNK) { + if (priv->autoneg == AUTONEG_ENABLE) + encx24j600_wait_for_autoneg(priv); + + netif_carrier_on(dev); + netif_info(priv, ifup, dev, "link up\n"); + } else { + netif_info(priv, ifdown, dev, "link down\n"); + + /* Re-enable autoneg since we won't know what we might be + * connected to when the link is brought back up again. + */ + priv->autoneg = AUTONEG_ENABLE; + priv->full_duplex = true; + priv->speed = SPEED_100; + netif_carrier_off(dev); + } +} + +static void encx24j600_int_link_handler(struct encx24j600_priv *priv) +{ + struct net_device *dev = priv->ndev; + + netif_dbg(priv, intr, dev, "%s", __func__); + encx24j600_check_link_status(priv); + encx24j600_clr_bits(priv, EIR, LINKIF); +} + +static void encx24j600_tx_complete(struct encx24j600_priv *priv, bool err) +{ + struct net_device *dev = priv->ndev; + + mutex_lock(&priv->lock); + + if (err) + dev->stats.tx_errors++; + else + dev->stats.tx_packets++; + + dev->stats.tx_bytes += priv->tx_skb->len; + + encx24j600_clr_bits(priv, EIR, TXIF | TXABTIF); + + netif_dbg(priv, tx_done, dev, "TX Done%s\n", err ? ": Err" : ""); + + if (priv->tx_skb) { + dev_kfree_skb(priv->tx_skb); + priv->tx_skb = NULL; + } + + netif_wake_queue(dev); + + mutex_unlock(&priv->lock); +} + +static int encx24j600_receive_packet(struct encx24j600_priv *priv, + struct rsv *rsv) +{ + struct net_device *dev = priv->ndev; + struct sk_buff *skb = netdev_alloc_skb(dev, rsv->len + NET_IP_ALIGN); + if (!skb) { + pr_err_ratelimited("RX: OOM: packet dropped\n"); + dev->stats.rx_dropped++; + return -ENOMEM; + } + skb_reserve(skb, NET_IP_ALIGN); + encx24j600_raw_read(priv, RRXDATA, skb_put(skb, rsv->len), rsv->len); + + if (netif_msg_pktdata(priv)) + dump_packet("RX", skb->len, skb->data); + + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_COMPLETE; + + /* Maintain stats */ + dev->stats.rx_packets++; + dev->stats.rx_bytes += rsv->len; + priv->next_packet = rsv->next_packet; + + netif_rx(skb); + + return 0; +} + +static void encx24j600_rx_packets(struct encx24j600_priv *priv, u8 packet_count) +{ + struct net_device *dev = priv->ndev; + + while (packet_count--) { + struct rsv rsv; + u16 newrxtail; + + encx24j600_write_reg(priv, ERXRDPT, priv->next_packet); + encx24j600_raw_read(priv, RRXDATA, (u8 *)&rsv, sizeof(rsv)); + + if (netif_msg_rx_status(priv)) + encx24j600_dump_rsv(priv, __func__, &rsv); + + if (!RSV_GETBIT(rsv.rxstat, RSV_RXOK) || + (rsv.len > MAX_FRAMELEN)) { + netif_err(priv, rx_err, dev, "RX Error %04x\n", + rsv.rxstat); + dev->stats.rx_errors++; + + if (RSV_GETBIT(rsv.rxstat, RSV_CRCERROR)) + dev->stats.rx_crc_errors++; + if (RSV_GETBIT(rsv.rxstat, RSV_LENCHECKERR)) + dev->stats.rx_frame_errors++; + if (rsv.len > MAX_FRAMELEN) + dev->stats.rx_over_errors++; + } else { + encx24j600_receive_packet(priv, &rsv); + } + + newrxtail = priv->next_packet - 2; + if (newrxtail == ENC_RX_BUF_START) + newrxtail = SRAM_SIZE - 2; + + encx24j600_cmd(priv, SETPKTDEC); + encx24j600_write_reg(priv, ERXTAIL, newrxtail); + } +} + +static irqreturn_t encx24j600_isr(int irq, void *dev_id) +{ + struct encx24j600_priv *priv = dev_id; + struct net_device *dev = priv->ndev; + int eir; + + /* Clear interrupts */ + encx24j600_cmd(priv, CLREIE); + + eir = encx24j600_read_reg(priv, EIR); + + if (eir & LINKIF) + encx24j600_int_link_handler(priv); + + if (eir & TXIF) + encx24j600_tx_complete(priv, false); + + if (eir & TXABTIF) + encx24j600_tx_complete(priv, true); + + if (eir & RXABTIF) { + if (eir & PCFULIF) { + /* Packet counter is full */ + netif_err(priv, rx_err, dev, "Packet counter full\n"); + } + dev->stats.rx_dropped++; + encx24j600_clr_bits(priv, EIR, RXABTIF); + } + + if (eir & PKTIF) { + u8 packet_count; + + mutex_lock(&priv->lock); + + packet_count = encx24j600_read_reg(priv, ESTAT) & 0xff; + while (packet_count) { + encx24j600_rx_packets(priv, packet_count); + packet_count = encx24j600_read_reg(priv, ESTAT) & 0xff; + } + + mutex_unlock(&priv->lock); + } + + /* Enable interrupts */ + encx24j600_cmd(priv, SETEIE); + + return IRQ_HANDLED; +} + +static int encx24j600_soft_reset(struct encx24j600_priv *priv) +{ + int ret = 0; + int timeout; + u16 eudast; + + /* Write and verify a test value to EUDAST */ + regcache_cache_bypass(priv->ctx.regmap, true); + timeout = 10; + do { + encx24j600_write_reg(priv, EUDAST, EUDAST_TEST_VAL); + eudast = encx24j600_read_reg(priv, EUDAST); + usleep_range(25, 100); + } while ((eudast != EUDAST_TEST_VAL) && --timeout); + regcache_cache_bypass(priv->ctx.regmap, false); + + if (timeout == 0) { + ret = -ETIMEDOUT; + goto err_out; + } + + /* Wait for CLKRDY to become set */ + timeout = 10; + while (!(encx24j600_read_reg(priv, ESTAT) & CLKRDY) && --timeout) + usleep_range(25, 100); + + if (timeout == 0) { + ret = -ETIMEDOUT; + goto err_out; + } + + /* Issue a System Reset command */ + encx24j600_cmd(priv, SETETHRST); + usleep_range(25, 100); + + /* Confirm that EUDAST has 0000h after system reset */ + if (encx24j600_read_reg(priv, EUDAST) != 0) { + ret = -EINVAL; + goto err_out; + } + + /* Wait for PHY register and status bits to become available */ + usleep_range(256, 1000); + +err_out: + return ret; +} + +static int encx24j600_hw_reset(struct encx24j600_priv *priv) +{ + int ret; + + mutex_lock(&priv->lock); + ret = encx24j600_soft_reset(priv); + mutex_unlock(&priv->lock); + + return ret; +} + +static void encx24j600_reset_hw_tx(struct encx24j600_priv *priv) +{ + encx24j600_set_bits(priv, ECON2, TXRST); + encx24j600_clr_bits(priv, ECON2, TXRST); +} + +static void encx24j600_hw_init_tx(struct encx24j600_priv *priv) +{ + /* Reset TX */ + encx24j600_reset_hw_tx(priv); + + /* Clear the TXIF flag if were previously set */ + encx24j600_clr_bits(priv, EIR, TXIF | TXABTIF); + + /* Write the Tx Buffer pointer */ + encx24j600_write_reg(priv, EGPWRPT, ENC_TX_BUF_START); +} + +static void encx24j600_hw_init_rx(struct encx24j600_priv *priv) +{ + encx24j600_cmd(priv, DISABLERX); + + /* Set up RX packet start address in the SRAM */ + encx24j600_write_reg(priv, ERXST, ENC_RX_BUF_START); + + /* Preload the RX Data pointer to the beginning of the RX area */ + encx24j600_write_reg(priv, ERXRDPT, ENC_RX_BUF_START); + + priv->next_packet = ENC_RX_BUF_START; + + /* Set up RX end address in the SRAM */ + encx24j600_write_reg(priv, ERXTAIL, ENC_SRAM_SIZE - 2); + + /* Reset the user data pointers */ + encx24j600_write_reg(priv, EUDAST, ENC_SRAM_SIZE); + encx24j600_write_reg(priv, EUDAND, ENC_SRAM_SIZE + 1); + + /* Set Max Frame length */ + encx24j600_write_reg(priv, MAMXFL, MAX_FRAMELEN); +} + +static void encx24j600_dump_config(struct encx24j600_priv *priv, + const char *msg) +{ + pr_info(DRV_NAME ": %s\n", msg); + + /* CHIP configuration */ + pr_info(DRV_NAME " ECON1: %04X\n", encx24j600_read_reg(priv, ECON1)); + pr_info(DRV_NAME " ECON2: %04X\n", encx24j600_read_reg(priv, ECON2)); + pr_info(DRV_NAME " ERXFCON: %04X\n", encx24j600_read_reg(priv, + ERXFCON)); + pr_info(DRV_NAME " ESTAT: %04X\n", encx24j600_read_reg(priv, ESTAT)); + pr_info(DRV_NAME " EIR: %04X\n", encx24j600_read_reg(priv, EIR)); + pr_info(DRV_NAME " EIDLED: %04X\n", encx24j600_read_reg(priv, EIDLED)); + + /* MAC layer configuration */ + pr_info(DRV_NAME " MACON1: %04X\n", encx24j600_read_reg(priv, MACON1)); + pr_info(DRV_NAME " MACON2: %04X\n", encx24j600_read_reg(priv, MACON2)); + pr_info(DRV_NAME " MAIPG: %04X\n", encx24j600_read_reg(priv, MAIPG)); + pr_info(DRV_NAME " MACLCON: %04X\n", encx24j600_read_reg(priv, + MACLCON)); + pr_info(DRV_NAME " MABBIPG: %04X\n", encx24j600_read_reg(priv, + MABBIPG)); + + /* PHY configuation */ + pr_info(DRV_NAME " PHCON1: %04X\n", encx24j600_read_phy(priv, PHCON1)); + pr_info(DRV_NAME " PHCON2: %04X\n", encx24j600_read_phy(priv, PHCON2)); + pr_info(DRV_NAME " PHANA: %04X\n", encx24j600_read_phy(priv, PHANA)); + pr_info(DRV_NAME " PHANLPA: %04X\n", encx24j600_read_phy(priv, + PHANLPA)); + pr_info(DRV_NAME " PHANE: %04X\n", encx24j600_read_phy(priv, PHANE)); + pr_info(DRV_NAME " PHSTAT1: %04X\n", encx24j600_read_phy(priv, + PHSTAT1)); + pr_info(DRV_NAME " PHSTAT2: %04X\n", encx24j600_read_phy(priv, + PHSTAT2)); + pr_info(DRV_NAME " PHSTAT3: %04X\n", encx24j600_read_phy(priv, + PHSTAT3)); +} + +static void encx24j600_set_rxfilter_mode(struct encx24j600_priv *priv) +{ + switch (priv->rxfilter) { + case RXFILTER_PROMISC: + encx24j600_set_bits(priv, MACON1, PASSALL); + encx24j600_write_reg(priv, ERXFCON, UCEN | MCEN | NOTMEEN); + break; + case RXFILTER_MULTI: + encx24j600_clr_bits(priv, MACON1, PASSALL); + encx24j600_write_reg(priv, ERXFCON, UCEN | CRCEN | BCEN | MCEN); + break; + case RXFILTER_NORMAL: + default: + encx24j600_clr_bits(priv, MACON1, PASSALL); + encx24j600_write_reg(priv, ERXFCON, UCEN | CRCEN | BCEN); + break; + } +} + +static int encx24j600_hw_init(struct encx24j600_priv *priv) +{ + struct net_device *dev = priv->ndev; + int ret = 0; + u16 eidled; + u16 macon2; + + priv->hw_enabled = false; + + eidled = encx24j600_read_reg(priv, EIDLED); + if (((eidled & DEVID_MASK) >> DEVID_SHIFT) != ENCX24J600_DEV_ID) { + ret = -EINVAL; + goto err_out; + } + + netif_info(priv, drv, dev, "Silicon rev ID: 0x%02x\n", + (eidled & REVID_MASK) >> REVID_SHIFT); + + /* PHY Leds: link status, + * LEDA: Link + transmit/receive events + * LEDB: Link State + colision events + */ + encx24j600_update_reg(priv, EIDLED, 0xbc00, 0xbc00); + + /* Loopback disabled */ + encx24j600_write_reg(priv, MACON1, 0x9); + + /* interpacket gap value */ + encx24j600_write_reg(priv, MAIPG, 0x0c12); + + /* Write the auto negotiation pattern */ + encx24j600_write_phy(priv, PHANA, PHANA_DEFAULT); + + encx24j600_update_phcon1(priv); + encx24j600_check_link_status(priv); + + macon2 = MACON2_RSV1 | TXCRCEN | PADCFG0 | PADCFG2 | MACON2_DEFER; + if ((priv->autoneg == AUTONEG_DISABLE) && priv->full_duplex) + macon2 |= FULDPX; + + encx24j600_set_bits(priv, MACON2, macon2); + + priv->rxfilter = RXFILTER_NORMAL; + encx24j600_set_rxfilter_mode(priv); + + /* Program the Maximum frame length */ + encx24j600_write_reg(priv, MAMXFL, MAX_FRAMELEN); + + /* Init Tx pointers */ + encx24j600_hw_init_tx(priv); + + /* Init Rx pointers */ + encx24j600_hw_init_rx(priv); + + if (netif_msg_hw(priv)) + encx24j600_dump_config(priv, "Hw is initialized"); + +err_out: + return ret; +} + +static void encx24j600_hw_enable(struct encx24j600_priv *priv) +{ + /* Clear the interrupt flags in case was set */ + encx24j600_clr_bits(priv, EIR, (PCFULIF | RXABTIF | TXABTIF | TXIF | + PKTIF | LINKIF)); + + /* Enable the interrupts */ + encx24j600_write_reg(priv, EIE, (PCFULIE | RXABTIE | TXABTIE | TXIE | + PKTIE | LINKIE | INTIE)); + + /* Enable RX */ + encx24j600_cmd(priv, ENABLERX); + + priv->hw_enabled = true; +} + +static void encx24j600_hw_disable(struct encx24j600_priv *priv) +{ + /* Disable all interrupts */ + encx24j600_write_reg(priv, EIE, 0); + + /* Disable RX */ + encx24j600_cmd(priv, DISABLERX); + + priv->hw_enabled = false; +} + +static int encx24j600_setlink(struct net_device *dev, u8 autoneg, u16 speed, + u8 duplex) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + int ret = 0; + + if (!priv->hw_enabled) { + /* link is in low power mode now; duplex setting + * will take effect on next encx24j600_hw_init() + */ + if (speed == SPEED_10 || speed == SPEED_100) { + priv->autoneg = (autoneg == AUTONEG_ENABLE); + priv->full_duplex = (duplex == DUPLEX_FULL); + priv->speed = (speed == SPEED_100); + } else { + netif_warn(priv, link, dev, "unsupported link speed setting\n"); + /*speeds other than SPEED_10 and SPEED_100 */ + /*are not supported by chip */ + ret = -EOPNOTSUPP; + } + } else { + netif_warn(priv, link, dev, "Warning: hw must be disabled to set link mode\n"); + ret = -EBUSY; + } + return ret; +} + +static void encx24j600_hw_get_macaddr(struct encx24j600_priv *priv, + unsigned char *ethaddr) +{ + unsigned short val; + + val = encx24j600_read_reg(priv, MAADR1); + + ethaddr[0] = val & 0x00ff; + ethaddr[1] = (val & 0xff00) >> 8; + + val = encx24j600_read_reg(priv, MAADR2); + + ethaddr[2] = val & 0x00ffU; + ethaddr[3] = (val & 0xff00U) >> 8; + + val = encx24j600_read_reg(priv, MAADR3); + + ethaddr[4] = val & 0x00ffU; + ethaddr[5] = (val & 0xff00U) >> 8; +} + +/* Program the hardware MAC address from dev->dev_addr.*/ +static int encx24j600_set_hw_macaddr(struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + + if (priv->hw_enabled) { + netif_info(priv, drv, dev, "Hardware must be disabled to set Mac address\n"); + return -EBUSY; + } + + mutex_lock(&priv->lock); + + netif_info(priv, drv, dev, "%s: Setting MAC address to %pM\n", + dev->name, dev->dev_addr); + + encx24j600_write_reg(priv, MAADR3, (dev->dev_addr[4] | + dev->dev_addr[5] << 8)); + encx24j600_write_reg(priv, MAADR2, (dev->dev_addr[2] | + dev->dev_addr[3] << 8)); + encx24j600_write_reg(priv, MAADR1, (dev->dev_addr[0] | + dev->dev_addr[1] << 8)); + + mutex_unlock(&priv->lock); + + return 0; +} + +/* Store the new hardware address in dev->dev_addr, and update the MAC.*/ +static int encx24j600_set_mac_address(struct net_device *dev, void *addr) +{ + struct sockaddr *address = addr; + + if (netif_running(dev)) + return -EBUSY; + if (!is_valid_ether_addr(address->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, address->sa_data, dev->addr_len); + return encx24j600_set_hw_macaddr(dev); +} + +static int encx24j600_open(struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + + int ret = request_threaded_irq(priv->ctx.spi->irq, NULL, encx24j600_isr, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + DRV_NAME, priv); + if (unlikely(ret < 0)) { + netdev_err(dev, "request irq %d failed (ret = %d)\n", + priv->ctx.spi->irq, ret); + return ret; + } + + encx24j600_hw_disable(priv); + encx24j600_hw_init(priv); + encx24j600_hw_enable(priv); + netif_start_queue(dev); + + return 0; +} + +static int encx24j600_stop(struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + + netif_stop_queue(dev); + free_irq(priv->ctx.spi->irq, priv); + return 0; +} + +static void encx24j600_setrx_proc(struct kthread_work *ws) +{ + struct encx24j600_priv *priv = + container_of(ws, struct encx24j600_priv, setrx_work); + + mutex_lock(&priv->lock); + encx24j600_set_rxfilter_mode(priv); + mutex_unlock(&priv->lock); +} + +static void encx24j600_set_multicast_list(struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + int oldfilter = priv->rxfilter; + + if (dev->flags & IFF_PROMISC) { + netif_dbg(priv, link, dev, "promiscuous mode\n"); + priv->rxfilter = RXFILTER_PROMISC; + } else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) { + netif_dbg(priv, link, dev, "%smulticast mode\n", + (dev->flags & IFF_ALLMULTI) ? "all-" : ""); + priv->rxfilter = RXFILTER_MULTI; + } else { + netif_dbg(priv, link, dev, "normal mode\n"); + priv->rxfilter = RXFILTER_NORMAL; + } + + if (oldfilter != priv->rxfilter) + queue_kthread_work(&priv->kworker, &priv->setrx_work); +} + +static void encx24j600_hw_tx(struct encx24j600_priv *priv) +{ + struct net_device *dev = priv->ndev; + netif_info(priv, tx_queued, dev, "TX Packet Len:%d\n", + priv->tx_skb->len); + + if (netif_msg_pktdata(priv)) + dump_packet("TX", priv->tx_skb->len, priv->tx_skb->data); + + if (encx24j600_read_reg(priv, EIR) & TXABTIF) + /* Last transmition aborted due to error. Reset TX interface */ + encx24j600_reset_hw_tx(priv); + + /* Clear the TXIF flag if were previously set */ + encx24j600_clr_bits(priv, EIR, TXIF); + + /* Set the data pointer to the TX buffer address in the SRAM */ + encx24j600_write_reg(priv, EGPWRPT, ENC_TX_BUF_START); + + /* Copy the packet into the SRAM */ + encx24j600_raw_write(priv, WGPDATA, (u8 *)priv->tx_skb->data, + priv->tx_skb->len); + + /* Program the Tx buffer start pointer */ + encx24j600_write_reg(priv, ETXST, ENC_TX_BUF_START); + + /* Program the packet length */ + encx24j600_write_reg(priv, ETXLEN, priv->tx_skb->len); + + /* Start the transmission */ + encx24j600_cmd(priv, SETTXRTS); +} + +static void encx24j600_tx_proc(struct kthread_work *ws) +{ + struct encx24j600_priv *priv = + container_of(ws, struct encx24j600_priv, tx_work); + + mutex_lock(&priv->lock); + encx24j600_hw_tx(priv); + mutex_unlock(&priv->lock); +} + +static netdev_tx_t encx24j600_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + + netif_stop_queue(dev); + + /* save the timestamp */ + dev->trans_start = jiffies; + + /* Remember the skb for deferred processing */ + priv->tx_skb = skb; + + queue_kthread_work(&priv->kworker, &priv->tx_work); + + return NETDEV_TX_OK; +} + +/* Deal with a transmit timeout */ +static void encx24j600_tx_timeout(struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + + netif_err(priv, tx_err, dev, "TX timeout at %ld, latency %ld\n", + jiffies, jiffies - dev->trans_start); + + dev->stats.tx_errors++; + netif_wake_queue(dev); + return; +} + +static int encx24j600_get_regs_len(struct net_device *dev) +{ + return SFR_REG_COUNT; +} + +static void encx24j600_get_regs(struct net_device *dev, + struct ethtool_regs *regs, void *p) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + u16 *buff = p; + u8 reg; + + regs->version = 1; + mutex_lock(&priv->lock); + for (reg = 0; reg < SFR_REG_COUNT; reg += 2) { + unsigned int val = 0; + /* ignore errors for unreadable registers */ + regmap_read(priv->ctx.regmap, reg, &val); + buff[reg] = val & 0xffff; + } + mutex_unlock(&priv->lock); +} + +static void encx24j600_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + strlcpy(info->bus_info, dev_name(dev->dev.parent), + sizeof(info->bus_info)); +} + +static int encx24j600_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + + cmd->transceiver = XCVR_INTERNAL; + cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_TP; + + ethtool_cmd_speed_set(cmd, priv->speed); + cmd->duplex = priv->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + cmd->port = PORT_TP; + cmd->autoneg = priv->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; + + return 0; +} + +static int encx24j600_set_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + return encx24j600_setlink(dev, cmd->autoneg, + ethtool_cmd_speed(cmd), cmd->duplex); +} + +static u32 encx24j600_get_msglevel(struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + return priv->msg_enable; +} + +static void encx24j600_set_msglevel(struct net_device *dev, u32 val) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + priv->msg_enable = val; +} + +static const struct ethtool_ops encx24j600_ethtool_ops = { + .get_settings = encx24j600_get_settings, + .set_settings = encx24j600_set_settings, + .get_drvinfo = encx24j600_get_drvinfo, + .get_msglevel = encx24j600_get_msglevel, + .set_msglevel = encx24j600_set_msglevel, + .get_regs_len = encx24j600_get_regs_len, + .get_regs = encx24j600_get_regs, +}; + +static const struct net_device_ops encx24j600_netdev_ops = { + .ndo_open = encx24j600_open, + .ndo_stop = encx24j600_stop, + .ndo_start_xmit = encx24j600_tx, + .ndo_set_rx_mode = encx24j600_set_multicast_list, + .ndo_set_mac_address = encx24j600_set_mac_address, + .ndo_tx_timeout = encx24j600_tx_timeout, + .ndo_validate_addr = eth_validate_addr, +}; + +static int encx24j600_spi_probe(struct spi_device *spi) +{ + int ret; + + struct net_device *ndev; + struct encx24j600_priv *priv; + + ndev = alloc_etherdev(sizeof(struct encx24j600_priv)); + + if (!ndev) { + ret = -ENOMEM; + goto error_out; + } + + priv = netdev_priv(ndev); + spi_set_drvdata(spi, priv); + dev_set_drvdata(&spi->dev, priv); + SET_NETDEV_DEV(ndev, &spi->dev); + + priv->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); + priv->ndev = ndev; + + /* Default configuration PHY configuration */ + priv->full_duplex = true; + priv->autoneg = AUTONEG_ENABLE; + priv->speed = SPEED_100; + + priv->ctx.spi = spi; + devm_regmap_init_encx24j600(&spi->dev, &priv->ctx); + ndev->irq = spi->irq; + ndev->netdev_ops = &encx24j600_netdev_ops; + + mutex_init(&priv->lock); + + /* Reset device and check if it is connected */ + if (encx24j600_hw_reset(priv)) { + netif_err(priv, probe, ndev, + DRV_NAME ": Chip is not detected\n"); + ret = -EIO; + goto out_free; + } + + /* Initialize the device HW to the consistent state */ + if (encx24j600_hw_init(priv)) { + netif_err(priv, probe, ndev, + DRV_NAME ": HW initialization error\n"); + ret = -EIO; + goto out_free; + } + + init_kthread_worker(&priv->kworker); + init_kthread_work(&priv->tx_work, encx24j600_tx_proc); + init_kthread_work(&priv->setrx_work, encx24j600_setrx_proc); + + priv->kworker_task = kthread_run(kthread_worker_fn, &priv->kworker, + "encx24j600"); + + if (IS_ERR(priv->kworker_task)) { + ret = PTR_ERR(priv->kworker_task); + goto out_free; + } + + /* Get the MAC address from the chip */ + encx24j600_hw_get_macaddr(priv, ndev->dev_addr); + + ndev->ethtool_ops = &encx24j600_ethtool_ops; + + ret = register_netdev(ndev); + if (unlikely(ret)) { + netif_err(priv, probe, ndev, "Error %d initializing card encx24j600 card\n", + ret); + goto out_free; + } + + netif_info(priv, drv, priv->ndev, "MAC address %pM\n", ndev->dev_addr); + + return ret; + +out_free: + free_netdev(ndev); + +error_out: + return ret; +} + +static int encx24j600_spi_remove(struct spi_device *spi) +{ + struct encx24j600_priv *priv = dev_get_drvdata(&spi->dev); + + unregister_netdev(priv->ndev); + + free_netdev(priv->ndev); + + return 0; +} + +static const struct spi_device_id encx24j600_spi_id_table = { + .name = "encx24j600" +}; + +static struct spi_driver encx24j600_spi_net_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .bus = &spi_bus_type, + }, + .probe = encx24j600_spi_probe, + .remove = encx24j600_spi_remove, + .id_table = &encx24j600_spi_id_table, +}; + +static int __init encx24j600_init(void) +{ + return spi_register_driver(&encx24j600_spi_net_driver); +} +module_init(encx24j600_init); + +void encx24j600_exit(void) +{ + spi_unregister_driver(&encx24j600_spi_net_driver); +} +module_exit(encx24j600_exit); + +MODULE_DESCRIPTION(DRV_NAME " ethernet driver"); +MODULE_AUTHOR("Jon Ringle "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:" DRV_NAME); diff --git a/drivers/net/ethernet/microchip/encx24j600_hw.h b/drivers/net/ethernet/microchip/encx24j600_hw.h new file mode 100644 index 000000000000..4be73d5553f8 --- /dev/null +++ b/drivers/net/ethernet/microchip/encx24j600_hw.h @@ -0,0 +1,437 @@ +/** + * encx24j600_hw.h: Register definitions + * + */ + +#ifndef _ENCX24J600_HW_H +#define _ENCX24J600_HW_H + +struct encx24j600_context { + struct spi_device *spi; + struct regmap *regmap; + struct regmap *phymap; + struct mutex mutex; /* mutex to protect access to regmap */ + int bank; +}; + +void devm_regmap_init_encx24j600(struct device *dev, + struct encx24j600_context *ctx); + +/* Single-byte instructions */ +#define BANK_SELECT(bank) (0xC0 | ((bank & (BANK_MASK >> BANK_SHIFT)) << 1)) +#define B0SEL 0xC0 /* Bank 0 Select */ +#define B1SEL 0xC2 /* Bank 1 Select */ +#define B2SEL 0xC4 /* Bank 2 Select */ +#define B3SEL 0xC6 /* Bank 3 Select */ +#define SETETHRST 0xCA /* System Reset */ +#define FCDISABLE 0xE0 /* Flow Control Disable */ +#define FCSINGLE 0xE2 /* Flow Control Single */ +#define FCMULTIPLE 0xE4 /* Flow Control Multiple */ +#define FCCLEAR 0xE6 /* Flow Control Clear */ +#define SETPKTDEC 0xCC /* Decrement Packet Counter */ +#define DMASTOP 0xD2 /* DMA Stop */ +#define DMACKSUM 0xD8 /* DMA Start Checksum */ +#define DMACKSUMS 0xDA /* DMA Start Checksum with Seed */ +#define DMACOPY 0xDC /* DMA Start Copy */ +#define DMACOPYS 0xDE /* DMA Start Copy and Checksum with Seed */ +#define SETTXRTS 0xD4 /* Request Packet Transmission */ +#define ENABLERX 0xE8 /* Enable RX */ +#define DISABLERX 0xEA /* Disable RX */ +#define SETEIE 0xEC /* Enable Interrupts */ +#define CLREIE 0xEE /* Disable Interrupts */ + +/* Two byte instructions */ +#define RBSEL 0xC8 /* Read Bank Select */ + +/* Three byte instructions */ +#define WGPRDPT 0x60 /* Write EGPRDPT */ +#define RGPRDPT 0x62 /* Read EGPRDPT */ +#define WRXRDPT 0x64 /* Write ERXRDPT */ +#define RRXRDPT 0x66 /* Read ERXRDPT */ +#define WUDARDPT 0x68 /* Write EUDARDPT */ +#define RUDARDPT 0x6A /* Read EUDARDPT */ +#define WGPWRPT 0x6C /* Write EGPWRPT */ +#define RGPWRPT 0x6E /* Read EGPWRPT */ +#define WRXWRPT 0x70 /* Write ERXWRPT */ +#define RRXWRPT 0x72 /* Read ERXWRPT */ +#define WUDAWRPT 0x74 /* Write EUDAWRPT */ +#define RUDAWRPT 0x76 /* Read EUDAWRPT */ + +/* n byte instructions */ +#define RCRCODE 0x00 +#define WCRCODE 0x40 +#define BFSCODE 0x80 +#define BFCCODE 0xA0 +#define RCR(addr) (RCRCODE | (addr & ADDR_MASK)) /* Read Control Register */ +#define WCR(addr) (WCRCODE | (addr & ADDR_MASK)) /* Write Control Register */ +#define RCRU 0x20 /* Read Control Register Unbanked */ +#define WCRU 0x22 /* Write Control Register Unbanked */ +#define BFS(addr) (BFSCODE | (addr & ADDR_MASK)) /* Bit Field Set */ +#define BFC(addr) (BFCCODE | (addr & ADDR_MASK)) /* Bit Field Clear */ +#define BFSU 0x24 /* Bit Field Set Unbanked */ +#define BFCU 0x26 /* Bit Field Clear Unbanked */ +#define RGPDATA 0x28 /* Read EGPDATA */ +#define WGPDATA 0x2A /* Write EGPDATA */ +#define RRXDATA 0x2C /* Read ERXDATA */ +#define WRXDATA 0x2E /* Write ERXDATA */ +#define RUDADATA 0x30 /* Read EUDADATA */ +#define WUDADATA 0x32 /* Write EUDADATA */ + +#define SFR_REG_COUNT 0xA0 + +/* ENC424J600 Control Registers + * Control register definitions are a combination of address + * and bank number + * - Register address (bits 0-4) + * - Bank number (bits 5-6) + */ +#define ADDR_MASK 0x1F +#define BANK_MASK 0x60 +#define BANK_SHIFT 5 + +/* All-bank registers */ +#define EUDAST 0x16 +#define EUDAND 0x18 +#define ESTAT 0x1A +#define EIR 0x1C +#define ECON1 0x1E + +/* Bank 0 registers */ +#define ETXST (0x00 | 0x00) +#define ETXLEN (0x02 | 0x00) +#define ERXST (0x04 | 0x00) +#define ERXTAIL (0x06 | 0x00) +#define ERXHEAD (0x08 | 0x00) +#define EDMAST (0x0A | 0x00) +#define EDMALEN (0x0C | 0x00) +#define EDMADST (0x0E | 0x00) +#define EDMACS (0x10 | 0x00) +#define ETXSTAT (0x12 | 0x00) +#define ETXWIRE (0x14 | 0x00) + +/* Bank 1 registers */ +#define EHT1 (0x00 | 0x20) +#define EHT2 (0x02 | 0x20) +#define EHT3 (0x04 | 0x20) +#define EHT4 (0x06 | 0x20) +#define EPMM1 (0x08 | 0x20) +#define EPMM2 (0x0A | 0x20) +#define EPMM3 (0x0C | 0x20) +#define EPMM4 (0x0E | 0x20) +#define EPMCS (0x10 | 0x20) +#define EPMO (0x12 | 0x20) +#define ERXFCON (0x14 | 0x20) + +/* Bank 2 registers */ +#define MACON1 (0x00 | 0x40) +#define MACON2 (0x02 | 0x40) +#define MABBIPG (0x04 | 0x40) +#define MAIPG (0x06 | 0x40) +#define MACLCON (0x08 | 0x40) +#define MAMXFL (0x0A | 0x40) +#define MICMD (0x12 | 0x40) +#define MIREGADR (0x14 | 0x40) + +/* Bank 3 registers */ +#define MAADR3 (0x00 | 0x60) +#define MAADR2 (0x02 | 0x60) +#define MAADR1 (0x04 | 0x60) +#define MIWR (0x06 | 0x60) +#define MIRD (0x08 | 0x60) +#define MISTAT (0x0A | 0x60) +#define EPAUS (0x0C | 0x60) +#define ECON2 (0x0E | 0x60) +#define ERXWM (0x10 | 0x60) +#define EIE (0x12 | 0x60) +#define EIDLED (0x14 | 0x60) + +/* Unbanked registers */ +#define EGPDATA (0x00 | 0x80) +#define ERXDATA (0x02 | 0x80) +#define EUDADATA (0x04 | 0x80) +#define EGPRDPT (0x06 | 0x80) +#define EGPWRPT (0x08 | 0x80) +#define ERXRDPT (0x0A | 0x80) +#define ERXWRPT (0x0C | 0x80) +#define EUDARDPT (0x0E | 0x80) +#define EUDAWRPT (0x10 | 0x80) + + +/* Register bit definitions */ +/* ESTAT */ +#define INT (1 << 15) +#define FCIDLE (1 << 14) +#define RXBUSY (1 << 13) +#define CLKRDY (1 << 12) +#define PHYDPX (1 << 10) +#define PHYLNK (1 << 8) + +/* EIR */ +#define CRYPTEN (1 << 15) +#define MODEXIF (1 << 14) +#define HASHIF (1 << 13) +#define AESIF (1 << 12) +#define LINKIF (1 << 11) +#define PKTIF (1 << 6) +#define DMAIF (1 << 5) +#define TXIF (1 << 3) +#define TXABTIF (1 << 2) +#define RXABTIF (1 << 1) +#define PCFULIF (1 << 0) + +/* ECON1 */ +#define MODEXST (1 << 15) +#define HASHEN (1 << 14) +#define HASHOP (1 << 13) +#define HASHLST (1 << 12) +#define AESST (1 << 11) +#define AESOP1 (1 << 10) +#define AESOP0 (1 << 9) +#define PKTDEC (1 << 8) +#define FCOP1 (1 << 7) +#define FCOP0 (1 << 6) +#define DMAST (1 << 5) +#define DMACPY (1 << 4) +#define DMACSSD (1 << 3) +#define DMANOCS (1 << 2) +#define TXRTS (1 << 1) +#define RXEN (1 << 0) + +/* ETXSTAT */ +#define LATECOL (1 << 10) +#define MAXCOL (1 << 9) +#define EXDEFER (1 << 8) +#define ETXSTATL_DEFER (1 << 7) +#define CRCBAD (1 << 4) +#define COLCNT_MASK 0xF + +/* ERXFCON */ +#define HTEN (1 << 15) +#define MPEN (1 << 14) +#define NOTPM (1 << 12) +#define PMEN3 (1 << 11) +#define PMEN2 (1 << 10) +#define PMEN1 (1 << 9) +#define PMEN0 (1 << 8) +#define CRCEEN (1 << 7) +#define CRCEN (1 << 6) +#define RUNTEEN (1 << 5) +#define RUNTEN (1 << 4) +#define UCEN (1 << 3) +#define NOTMEEN (1 << 2) +#define MCEN (1 << 1) +#define BCEN (1 << 0) + +/* MACON1 */ +#define LOOPBK (1 << 4) +#define RXPAUS (1 << 2) +#define PASSALL (1 << 1) + +/* MACON2 */ +#define MACON2_DEFER (1 << 14) +#define BPEN (1 << 13) +#define NOBKOFF (1 << 12) +#define PADCFG2 (1 << 7) +#define PADCFG1 (1 << 6) +#define PADCFG0 (1 << 5) +#define TXCRCEN (1 << 4) +#define PHDREN (1 << 3) +#define HFRMEN (1 << 2) +#define MACON2_RSV1 (1 << 1) +#define FULDPX (1 << 0) + +/* MAIPG */ +/* value of the high byte is given by the reserved bits, + * value of the low byte is recomended setting of the + * IPG parameter. + */ +#define MAIPGH_VAL 0x0C +#define MAIPGL_VAL 0x12 + +/* MIREGADRH */ +#define MIREGADR_VAL (1 << 8) + +/* MIREGADRL */ +#define PHREG_MASK 0x1F + +/* MICMD */ +#define MIISCAN (1 << 1) +#define MIIRD (1 << 0) + +/* MISTAT */ +#define NVALID (1 << 2) +#define SCAN (1 << 1) +#define BUSY (1 << 0) + +/* ECON2 */ +#define ETHEN (1 << 15) +#define STRCH (1 << 14) +#define TXMAC (1 << 13) +#define SHA1MD5 (1 << 12) +#define COCON3 (1 << 11) +#define COCON2 (1 << 10) +#define COCON1 (1 << 9) +#define COCON0 (1 << 8) +#define AUTOFC (1 << 7) +#define TXRST (1 << 6) +#define RXRST (1 << 5) +#define ETHRST (1 << 4) +#define MODLEN1 (1 << 3) +#define MODLEN0 (1 << 2) +#define AESLEN1 (1 << 1) +#define AESLEN0 (1 << 0) + +/* EIE */ +#define INTIE (1 << 15) +#define MODEXIE (1 << 14) +#define HASHIE (1 << 13) +#define AESIE (1 << 12) +#define LINKIE (1 << 11) +#define PKTIE (1 << 6) +#define DMAIE (1 << 5) +#define TXIE (1 << 3) +#define TXABTIE (1 << 2) +#define RXABTIE (1 << 1) +#define PCFULIE (1 << 0) + +/* EIDLED */ +#define LACFG3 (1 << 15) +#define LACFG2 (1 << 14) +#define LACFG1 (1 << 13) +#define LACFG0 (1 << 12) +#define LBCFG3 (1 << 11) +#define LBCFG2 (1 << 10) +#define LBCFG1 (1 << 9) +#define LBCFG0 (1 << 8) +#define DEVID_SHIFT 5 +#define DEVID_MASK (0x7 << DEVID_SHIFT) +#define REVID_SHIFT 0 +#define REVID_MASK (0x1F << REVID_SHIFT) + +/* PHY registers */ +#define PHCON1 0x00 +#define PHSTAT1 0x01 +#define PHANA 0x04 +#define PHANLPA 0x05 +#define PHANE 0x06 +#define PHCON2 0x11 +#define PHSTAT2 0x1B +#define PHSTAT3 0x1F + +/* PHCON1 */ +#define PRST (1 << 15) +#define PLOOPBK (1 << 14) +#define SPD100 (1 << 13) +#define ANEN (1 << 12) +#define PSLEEP (1 << 11) +#define RENEG (1 << 9) +#define PFULDPX (1 << 8) + +/* PHSTAT1 */ +#define FULL100 (1 << 14) +#define HALF100 (1 << 13) +#define FULL10 (1 << 12) +#define HALF10 (1 << 11) +#define ANDONE (1 << 5) +#define LRFAULT (1 << 4) +#define ANABLE (1 << 3) +#define LLSTAT (1 << 2) +#define EXTREGS (1 << 0) + +/* PHSTAT2 */ +#define PLRITY (1 << 4) + +/* PHSTAT3 */ +#define PHY3SPD100 (1 << 3) +#define PHY3DPX (1 << 4) +#define SPDDPX_SHIFT 2 +#define SPDDPX_MASK (0x7 << SPDDPX_SHIFT) + +/* PHANA */ +/* Default value for PHY initialization*/ +#define PHANA_DEFAULT 0x05E1 + +/* PHANE */ +#define PDFLT (1 << 4) +#define LPARCD (1 << 1) +#define LPANABL (1 << 0) + +#define EUDAST_TEST_VAL 0x1234 + +#define TSV_SIZE 7 + +#define ENCX24J600_DEV_ID 0x1 + +/* Configuration */ + +/* Led is on when the link is present and driven low + * temporarily when packet is TX'd or RX'd + */ +#define LED_A_SETTINGS 0xC + +/* Led is on if the link is in 100 Mbps mode */ +#define LED_B_SETTINGS 0x8 + +/* maximum ethernet frame length + * Currently not used as a limit anywhere + * (we're using the "huge frame enable" feature of + * enc424j600). + */ +#define MAX_FRAMELEN 1518 + +/* Size in bytes of the receive buffer in enc424j600. + * Must be word aligned (even). + */ +#define RX_BUFFER_SIZE (15 * MAX_FRAMELEN) + +/* Start of the general purpose area in sram */ +#define SRAM_GP_START 0x0 + +/* SRAM size */ +#define SRAM_SIZE 0x6000 + +/* Start of the receive buffer */ +#define ERXST_VAL (SRAM_SIZE - RX_BUFFER_SIZE) + +#define RSV_RXLONGEVDROPEV 16 +#define RSV_CARRIEREV 18 +#define RSV_CRCERROR 20 +#define RSV_LENCHECKERR 21 +#define RSV_LENOUTOFRANGE 22 +#define RSV_RXOK 23 +#define RSV_RXMULTICAST 24 +#define RSV_RXBROADCAST 25 +#define RSV_DRIBBLENIBBLE 26 +#define RSV_RXCONTROLFRAME 27 +#define RSV_RXPAUSEFRAME 28 +#define RSV_RXUNKNOWNOPCODE 29 +#define RSV_RXTYPEVLAN 30 + +#define RSV_RUNTFILTERMATCH 31 +#define RSV_NOTMEFILTERMATCH 32 +#define RSV_HASHFILTERMATCH 33 +#define RSV_MAGICPKTFILTERMATCH 34 +#define RSV_PTRNMTCHFILTERMATCH 35 +#define RSV_UNICASTFILTERMATCH 36 + +#define RSV_SIZE 8 +#define RSV_BITMASK(x) (1 << ((x) - 16)) +#define RSV_GETBIT(x, y) (((x) & RSV_BITMASK(y)) ? 1 : 0) + +struct rsv { + u16 next_packet; + u16 len; + u32 rxstat; +}; + +/* Put RX buffer at 0 as suggested by the Errata datasheet */ + +#define RXSTART_INIT ERXST_VAL +#define RXEND_INIT 0x5FFF + +int regmap_encx24j600_spi_write(void *context, u8 reg, const u8 *data, + size_t count); +int regmap_encx24j600_spi_read(void *context, u8 reg, u8 *data, size_t count); + + +#endif -- cgit v1.2.3 From 9886ce2b9d4e5a8bb3d78d0f7eff3c0f1ed58d67 Mon Sep 17 00:00:00 2001 From: kbuild test robot Date: Thu, 1 Oct 2015 20:26:20 +0800 Subject: net: encx24j600_exit() can be static Signed-off-by: Fengguang Wu Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/encx24j600.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c index 1da37fddab42..afc008a75c0f 100644 --- a/drivers/net/ethernet/microchip/encx24j600.c +++ b/drivers/net/ethernet/microchip/encx24j600.c @@ -1112,7 +1112,7 @@ static int __init encx24j600_init(void) } module_init(encx24j600_init); -void encx24j600_exit(void) +static void encx24j600_exit(void) { spi_unregister_driver(&encx24j600_spi_net_driver); } -- cgit v1.2.3 From dbf73d4a8bb8f4e1d1f3edd3be825692279e2ef3 Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Wed, 30 Sep 2015 12:26:23 +0200 Subject: iwlwifi: mvm: flush fw_dump_wk when mvm fails to start FW dump may be triggered when running init ucode, for example due to a sysassert. In this case fw_dump_wk may run after mvm is freed, resulting in a kernel panic. Fix it by flushing the work. Fixes: 01b988a708af ("iwlwifi: mvm: allow to collect debug data when restart is disabled") Cc: [3.18+] Signed-off-by: Andrei Otcheretianski Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/ops.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index a37de3f410a0..f0cb092f980e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -590,6 +590,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, ieee80211_unregister_hw(mvm->hw); iwl_mvm_leds_exit(mvm); out_free: + flush_delayed_work(&mvm->fw_dump_wk); iwl_phy_db_free(mvm->phy_db); kfree(mvm->scan_cmd); if (!cfg->no_power_up_nic_in_init || !mvm->nvm_file_name) -- cgit v1.2.3 From fec31ffffa6e05845ab13908d0ac0d5a10816836 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 1 Oct 2015 18:25:42 -0700 Subject: i40e: fix offload of GRE tunnels The driver still was not offloading TSO on GRE tunnels because it forgot to set the GSO_GRE flag, causing lots of retransmits. This fixes generic GRE traffic (like a tunnel added like below) whereas before it would get 1Gb/s or less, now on a 10G adapter it gets 8.7Gb/s. ip ad ad 11.1.0.2/24 dev ens2f0 ip l set ens2f0 up ip link add gre2 type gretap remote 11.1.0.1 local 11.1.0.2 dev ens2f0 ip l set gre2 up ip ad ad 192.168.124.2/24 dev gre2 ping 192.168.124.1 netperf -H 192.168.124.1 Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 2fdf978ae6a5..dd44fafd8798 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8389,6 +8389,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_GRE | NETIF_F_TSO; netdev->features = NETIF_F_SG | @@ -8396,6 +8397,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) NETIF_F_SCTP_CSUM | NETIF_F_HIGHDMA | NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_GRE | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER | -- cgit v1.2.3 From 3e0fa50575dbc83e57ceee7c413ff9b4e09a9a80 Mon Sep 17 00:00:00 2001 From: Assaf Krauss Date: Wed, 16 Sep 2015 11:44:55 +0300 Subject: iwlwifi: mvm: Fix tof debugfs formats (dec vs. hex) Make some input formats more natural, e.g. bandwidth and periods are more natural in decimal than in hexadecimal. Signed-off-by: Assaf Krauss Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 40 ++++++++++++++------------ 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 334ae56e5d8b..15ab543f7156 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c @@ -913,11 +913,11 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, u8 *mac = ap.bssid; unsigned int i; - if (sscanf(data, "%u %hhd %hhx %hhx" + if (sscanf(data, "%u %hhd %hhd %hhd" "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx" - "%hhx %hhx %hx" - "%hhx %hhx %x" - "%hhx %hhx %hhx %hhx", + "%hhd %hhd %hd" + "%hhd %hhd %d" + "%hhx %hhd %hhd %hhd", &i, &ap.channel_num, &ap.bandwidth, &ap.ctrl_ch_position, mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5, @@ -994,16 +994,18 @@ static ssize_t iwl_dbgfs_tof_range_request_read(struct file *file, struct iwl_tof_range_req_ap_entry *ap = &cmd->ap[i]; pos += scnprintf(buf + pos, bufsz - pos, - "ap %.2d: channel_num=%hhx bw=%hhx" - " control=%hhx bssid=%pM type=%hhx" - " num_of_bursts=%hhx burst_period=%hx ftm=%hhx" - " retries=%hhx tsf_delta=%x location_req=%hhx " - " asap=%hhx enable=%hhx rssi=%hhx\n", + "ap %.2d: channel_num=%hhd bw=%hhd" + " control=%hhd bssid=%pM type=%hhd" + " num_of_bursts=%hhd burst_period=%hd ftm=%hhd" + " retries=%hhd tsf_delta=%d" + " tsf_delta_direction=%hhd location_req=0x%hhx " + " asap=%hhd enable=%hhd rssi=%hhd\n", i, ap->channel_num, ap->bandwidth, ap->ctrl_ch_position, ap->bssid, ap->measure_type, ap->num_of_bursts, ap->burst_period, ap->samples_per_burst, ap->retries_per_sample, ap->tsf_delta, + ap->tsf_delta_direction, ap->location_req, ap->asap_mode, ap->enable_dyn_ack, ap->rssi); } @@ -1099,18 +1101,18 @@ static ssize_t iwl_dbgfs_tof_range_req_ext_read(struct file *file, mutex_lock(&mvm->mutex); pos += scnprintf(buf + pos, bufsz - pos, - "tsf_timer_offset_msec = %hx\n", + "tsf_timer_offset_msec = %hd\n", cmd->tsf_timer_offset_msec); - pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhx\n", + pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhd\n", cmd->min_delta_ftm); pos += scnprintf(buf + pos, bufsz - pos, - "ftm_format_and_bw20M = %hhx\n", + "ftm_format_and_bw20M = %hhd\n", cmd->ftm_format_and_bw20M); pos += scnprintf(buf + pos, bufsz - pos, - "ftm_format_and_bw40M = %hhx\n", + "ftm_format_and_bw40M = %hhd\n", cmd->ftm_format_and_bw40M); pos += scnprintf(buf + pos, bufsz - pos, - "ftm_format_and_bw80M = %hhx\n", + "ftm_format_and_bw80M = %hhd\n", cmd->ftm_format_and_bw80M); mutex_unlock(&mvm->mutex); @@ -1205,11 +1207,11 @@ static ssize_t iwl_dbgfs_tof_range_response_read(struct file *file, struct iwl_tof_range_rsp_ap_entry_ntfy *ap = &cmd->ap[i]; pos += scnprintf(buf + pos, bufsz - pos, - "ap %.2d: bssid=%pM status=%hhx bw=%hhx" - " rtt=%x rtt_var=%x rtt_spread=%x" - " rssi=%hhx rssi_spread=%hhx" - " range=%x range_var=%x" - " time_stamp=%x\n", + "ap %.2d: bssid=%pM status=%hhd bw=%hhd" + " rtt=%d rtt_var=%d rtt_spread=%d" + " rssi=%hhd rssi_spread=%hhd" + " range=%d range_var=%d" + " time_stamp=%d\n", i, ap->bssid, ap->measure_status, ap->measure_bw, ap->rtt, ap->rtt_variance, ap->rtt_spread, -- cgit v1.2.3 From 9ef2b8befb5acf499ac60e2a18dfa3e41194ba6e Mon Sep 17 00:00:00 2001 From: Gregory Greenman Date: Mon, 20 Jul 2015 07:44:44 +0300 Subject: iwlwifi: mvm: ToF - fill bssid of responder configuration The command needs to have the AP interfaces BSSID (which corresponds to its address). Signed-off-by: Gregory Greenman Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/tof.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/tof.c b/drivers/net/wireless/iwlwifi/mvm/tof.c index 7ae0bd894c82..4007f1d421dd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tof.c +++ b/drivers/net/wireless/iwlwifi/mvm/tof.c @@ -185,6 +185,7 @@ int iwl_mvm_tof_responder_cmd(struct iwl_mvm *mvm, } cmd->sta_id = mvmvif->bcast_sta.sta_id; + memcpy(cmd->bssid, vif->addr, ETH_ALEN); return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_CMD, IWL_ALWAYS_LONG_GROUP, 0), 0, sizeof(*cmd), cmd); -- cgit v1.2.3 From 5ac15be8fa5193206f5c47172a63cf83bec91f66 Mon Sep 17 00:00:00 2001 From: Assaf Krauss Date: Wed, 16 Sep 2015 11:47:14 +0300 Subject: iwlwifi: mvm: Improve debugfs tof robustness Return a proper error when wrong parameters are passed to debugfs tof_range_request. Signed-off-by: Assaf Krauss Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 15ab543f7156..5dc1686100d2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c @@ -892,6 +892,7 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, goto out; } memcpy(mvm->tof_data.range_req.macaddr_template, mac, ETH_ALEN); + goto out; } data = iwl_dbgfs_is_match("macaddr_mask=", buf); @@ -903,11 +904,12 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, goto out; } memcpy(mvm->tof_data.range_req.macaddr_mask, mac, ETH_ALEN); + goto out; } data = iwl_dbgfs_is_match("ap=", buf); if (data) { - struct iwl_tof_range_req_ap_entry ap; + struct iwl_tof_range_req_ap_entry ap = {}; int size = sizeof(struct iwl_tof_range_req_ap_entry); u16 burst_period; u8 *mac = ap.bssid; @@ -944,12 +946,12 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, data = iwl_dbgfs_is_match("send_range_request=", buf); if (data) { ret = kstrtou32(data, 10, &value); - if (ret == 0 && value) { + if (ret == 0 && value) ret = iwl_mvm_tof_range_request_cmd(mvm, vif); - goto out; - } + goto out; } + ret = -EINVAL; out: mutex_unlock(&mvm->mutex); return ret ?: count; @@ -1073,12 +1075,12 @@ static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif, data = iwl_dbgfs_is_match("send_range_req_ext=", buf); if (data) { ret = kstrtou32(data, 10, &value); - if (ret == 0 && value) { + if (ret == 0 && value) ret = iwl_mvm_tof_range_request_ext_cmd(mvm, vif); - goto out; - } + goto out; } + ret = -EINVAL; out: mutex_unlock(&mvm->mutex); return ret ?: count; -- cgit v1.2.3 From 1939089300cb4709dec2b268db649adfdefdb7bc Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 3 Sep 2015 14:53:09 +0200 Subject: iwlwifi: mvm: remove PHY RX from handlers Treat PHY RX specially, since it's actually pretty frequent, doesn't need all the notication etc. code, and will have a different handler in future hardware. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/ops.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 23825ff8c270..1c38e457abbe 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -222,7 +222,6 @@ struct iwl_rx_handlers { * called from a worker with mvm->mutex held. */ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { - RX_HANDLER(REPLY_RX_PHY_CMD, iwl_mvm_rx_rx_phy_cmd, false), RX_HANDLER(TX_CMD, iwl_mvm_rx_tx_cmd, false), RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false), @@ -730,6 +729,9 @@ static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode, if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD)) { iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); return; + } else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD) { + iwl_mvm_rx_rx_phy_cmd(mvm, rxb); + return; } iwl_mvm_rx_check_trigger(mvm, pkt); -- cgit v1.2.3 From a190430c5eeaff1b3a0cfc05d3572650b3bd3beb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 22 May 2015 10:52:26 +0200 Subject: iwlwifi: op-mode API: add rx_rss method Upcoming hardware will have the ability to do L3 hashing for RSS, directing data packets (and perhaps some associated metadata and management notifications) to different MSI-X vectors. In this case, it makes no sense to go through the full RX dispatch since it's already known that only a subset of the possibilities can come in, requiring a new receive method. In addition this must know which queue the packet was received on. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/iwl-op-mode.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index b47fe9d6b97a..2a58d6833224 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h @@ -7,6 +7,7 @@ * * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * * 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 @@ -33,6 +34,7 @@ * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,7 +110,8 @@ struct iwl_cfg; * interact with it. The driver layer typically calls the start and stop * handlers, the transport layer calls the others. * - * All the handlers MUST be implemented + * All the handlers MUST be implemented, except @rx_rss which can be left + * out *iff* the opmode will never run on hardware with multi-queue capability. * * @start: start the op_mode. The transport layer is already allocated. * May sleep @@ -116,6 +119,10 @@ struct iwl_cfg; * May sleep * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the * HCMD this Rx responds to. Can't sleep. + * @rx_rss: data queue RX notification to the op_mode, for (data) notifications + * received on the RSS queue(s). The queue parameter indicates which of the + * RSS queues received this frame; it will always be non-zero. + * This method must not sleep. * @queue_full: notifies that a HW queue is full. * Must be atomic and called with BH disabled. * @queue_not_full: notifies that a HW queue is not full any more. @@ -146,6 +153,8 @@ struct iwl_op_mode_ops { void (*stop)(struct iwl_op_mode *op_mode); void (*rx)(struct iwl_op_mode *op_mode, struct napi_struct *napi, struct iwl_rx_cmd_buffer *rxb); + void (*rx_rss)(struct iwl_op_mode *op_mode, struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb, unsigned int queue); void (*queue_full)(struct iwl_op_mode *op_mode, int queue); void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue); bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); @@ -186,6 +195,14 @@ static inline void iwl_op_mode_rx(struct iwl_op_mode *op_mode, return op_mode->ops->rx(op_mode, napi, rxb); } +static inline void iwl_op_mode_rx_rss(struct iwl_op_mode *op_mode, + struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb, + unsigned int queue) +{ + op_mode->ops->rx_rss(op_mode, napi, rxb, queue); +} + static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode, int queue) { -- cgit v1.2.3 From 56882e6cab432508c79b350d7842af3abac9c7d3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 22 May 2015 11:33:12 +0200 Subject: iwlwifi: transport: track number of allocated queues As the transport will decide how many queues (and MSI-X vectors) to allocate, add a field to indicate that to the op-mode so it can size/allocate its own data structures appropriately. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/iwl-trans.c | 1 + drivers/net/wireless/iwlwifi/iwl-trans.h | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 9f8bcefc04c5..71610968c365 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -87,6 +87,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size, trans->cfg = cfg; trans->ops = ops; trans->dev_cmd_headroom = dev_cmd_headroom; + trans->num_rx_queues = 1; snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name), "iwl_cmd_pool:%s", dev_name(trans->dev)); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index c829c505e141..bb51b6f8002c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -386,6 +386,7 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r) #define IWL_MAX_HW_QUEUES 32 #define IWL_MAX_TID_COUNT 8 #define IWL_FRAME_LIMIT 64 +#define IWL_MAX_RX_HW_QUEUES 16 /** * enum iwl_wowlan_status - WoWLAN image/device status @@ -654,6 +655,8 @@ enum iwl_d0i3_mode { * @hw_id_str: a string with info about HW ID. Set during transport allocation. * @pm_support: set to true in start_hw if link pm is supported * @ltr_enabled: set to true if the LTR is enabled + * @num_rx_queues: number of RX queues allocated by the transport; + * the transport must set this before calling iwl_drv_start() * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. * The user should use iwl_trans_{alloc,free}_tx_cmd. * @dev_cmd_headroom: room needed for the transport's private use before the @@ -693,6 +696,8 @@ struct iwl_trans { bool pm_support; bool ltr_enabled; + u8 num_rx_queues; + /* The following fields are internal only */ struct kmem_cache *dev_cmd_pool; size_t dev_cmd_headroom; -- cgit v1.2.3 From 4ecafae9e56802575c3b0c45ecf3dedecd3fd9e3 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Tue, 14 Jul 2015 13:36:18 +0300 Subject: iwlwifi: mvm: support using multiple ACs on single HW queue "DQA" is shorthand for "dynamic queue allocation", with the idea of allocating queues per-RA/TID on-demand rather than using shared queues statically allocated per vif. The goal of this is to enable future features (like GO PM) and to improve performance measurements of TX traffic. When RA/TID streams can't be neatly sorted into different AC queues, DQA allows sharing queues for the same RA. This means that DQA allows different ACs may reach the same HW queue. Update the code to allow such queue sharing by having a mapping between the HW queue and the mac80211 queues using it (as this could be more than one queue). Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/fw.c | 8 +- drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 15 ++- drivers/net/wireless/iwlwifi/mvm/mvm.h | 40 +++++--- drivers/net/wireless/iwlwifi/mvm/ops.c | 51 ++++++---- drivers/net/wireless/iwlwifi/mvm/sta.c | 71 +++++++++----- drivers/net/wireless/iwlwifi/mvm/tx.c | 11 +-- drivers/net/wireless/iwlwifi/mvm/utils.c | 142 ++++++++++++++++++++++++---- 7 files changed, 249 insertions(+), 89 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 248b025b5c59..834641e250fb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c @@ -616,12 +616,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, * will be empty. */ - for (i = 0; i < IWL_MAX_HW_QUEUES; i++) { - if (i < mvm->first_agg_queue && i != IWL_MVM_CMD_QUEUE) - mvm->queue_to_mac80211[i] = i; - else - mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE; - } + memset(&mvm->queue_info, 0, sizeof(mvm->queue_info)); + mvm->queue_info[IWL_MVM_CMD_QUEUE].hw_queue_refcount = 1; for (i = 0; i < IEEE80211_MAX_QUEUES; i++) atomic_set(&mvm->mac80211_queue_stop_count[i], 0); diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 361565076eaf..d2a221da7c77 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -486,15 +486,17 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) switch (vif->type) { case NL80211_IFTYPE_P2P_DEVICE: iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, + IWL_MVM_OFFCHANNEL_QUEUE, IWL_MVM_TX_FIFO_VO, wdg_timeout); break; case NL80211_IFTYPE_AP: - iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, + iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, vif->cab_queue, IWL_MVM_TX_FIFO_MCAST, wdg_timeout); /* fall through */ default: for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac], + vif->hw_queue[ac], iwl_mvm_ac_to_tx_fifo[ac], wdg_timeout); break; @@ -511,14 +513,19 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif) switch (vif->type) { case NL80211_IFTYPE_P2P_DEVICE: - iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, 0); + iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, + IWL_MVM_OFFCHANNEL_QUEUE, IWL_MAX_TID_COUNT, + 0); break; case NL80211_IFTYPE_AP: - iwl_mvm_disable_txq(mvm, vif->cab_queue, 0); + iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue, + IWL_MAX_TID_COUNT, 0); /* fall through */ default: for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) - iwl_mvm_disable_txq(mvm, vif->hw_queue[ac], 0); + iwl_mvm_disable_txq(mvm, vif->hw_queue[ac], + vif->hw_queue[ac], + IWL_MAX_TID_COUNT, 0); } } diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 5e027363baf0..a7a961947d6c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -82,7 +82,6 @@ #include "constants.h" #include "tof.h" -#define IWL_INVALID_MAC80211_QUEUE 0xff #define IWL_MVM_MAX_ADDRESSES 5 /* RSSI offset for WkP */ #define IWL_RSSI_OFFSET 50 @@ -605,7 +604,14 @@ struct iwl_mvm { u64 on_time_scan; } radio_stats, accu_radio_stats; - u8 queue_to_mac80211[IWL_MAX_HW_QUEUES]; + struct { + /* Map to HW queue */ + u32 hw_queue_to_mac80211; + u8 hw_queue_refcount; + bool setup_reserved; + u16 tid_bitmap; /* Bitmap of the TIDs mapped to this queue */ + } queue_info[IWL_MAX_HW_QUEUES]; + spinlock_t queue_info_lock; /* For syncing queue mgmt operations */ atomic_t mac80211_queue_stop_count[IEEE80211_MAX_QUEUES]; const char *nvm_file_name; @@ -910,6 +916,12 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm) IWL_UCODE_TLV_CAPA_D0I3_SUPPORT); } +static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm) +{ + return fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_DQA_SUPPORT); +} + static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm) { bool nvm_lar = mvm->nvm_data->lar_enabled; @@ -1341,13 +1353,19 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) } /* hw scheduler queue config */ -void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, - const struct iwl_trans_txq_scd_cfg *cfg, +void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, + u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg, unsigned int wdg_timeout); -void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags); +/* + * 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_find_free_queue(struct iwl_mvm *mvm, u8 minq, u8 maxq); static inline -void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, +void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, u8 fifo, unsigned int wdg_timeout) { struct iwl_trans_txq_scd_cfg cfg = { @@ -1357,13 +1375,13 @@ void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, .frame_limit = IWL_FRAME_LIMIT, }; - iwl_mvm_enable_txq(mvm, queue, 0, &cfg, wdg_timeout); + iwl_mvm_enable_txq(mvm, queue, mac80211_queue, 0, &cfg, wdg_timeout); } static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, - int fifo, int sta_id, int tid, - int frame_limit, u16 ssn, - unsigned int wdg_timeout) + int mac80211_queue, int fifo, + int sta_id, int tid, int frame_limit, + u16 ssn, unsigned int wdg_timeout) { struct iwl_trans_txq_scd_cfg cfg = { .fifo = fifo, @@ -1373,7 +1391,7 @@ static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, .aggregate = true, }; - iwl_mvm_enable_txq(mvm, queue, ssn, &cfg, wdg_timeout); + iwl_mvm_enable_txq(mvm, queue, mac80211_queue, ssn, &cfg, wdg_timeout); } /* Thermal management and CT-kill */ diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 1c38e457abbe..0e8166fb31e9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -453,6 +453,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, INIT_LIST_HEAD(&mvm->aux_roc_te_list); INIT_LIST_HEAD(&mvm->async_handlers_list); spin_lock_init(&mvm->time_event_lock); + spin_lock_init(&mvm->queue_info_lock); INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk); INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk); @@ -775,37 +776,51 @@ static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode, static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) { struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); - int mq = mvm->queue_to_mac80211[queue]; + unsigned long mq; + int q; - if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE)) - return; + spin_lock_bh(&mvm->queue_info_lock); + mq = mvm->queue_info[queue].hw_queue_to_mac80211; + spin_unlock_bh(&mvm->queue_info_lock); - if (atomic_inc_return(&mvm->mac80211_queue_stop_count[mq]) > 1) { - IWL_DEBUG_TX_QUEUES(mvm, - "queue %d (mac80211 %d) already stopped\n", - queue, mq); + if (WARN_ON_ONCE(!mq)) return; - } - ieee80211_stop_queue(mvm->hw, mq); + for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { + if (atomic_inc_return(&mvm->mac80211_queue_stop_count[q]) > 1) { + IWL_DEBUG_TX_QUEUES(mvm, + "queue %d (mac80211 %d) already stopped\n", + queue, q); + continue; + } + + ieee80211_stop_queue(mvm->hw, q); + } } static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) { struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); - int mq = mvm->queue_to_mac80211[queue]; + unsigned long mq; + int q; - if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE)) - return; + spin_lock_bh(&mvm->queue_info_lock); + mq = mvm->queue_info[queue].hw_queue_to_mac80211; + spin_unlock_bh(&mvm->queue_info_lock); - if (atomic_dec_return(&mvm->mac80211_queue_stop_count[mq]) > 0) { - IWL_DEBUG_TX_QUEUES(mvm, - "queue %d (mac80211 %d) still stopped\n", - queue, mq); + if (WARN_ON_ONCE(!mq)) return; - } - ieee80211_wake_queue(mvm->hw, mq); + for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { + if (atomic_dec_return(&mvm->mac80211_queue_stop_count[q]) > 0) { + IWL_DEBUG_TX_QUEUES(mvm, + "queue %d (mac80211 %d) still stopped\n", + queue, q); + continue; + } + + ieee80211_wake_queue(mvm->hw, q); + } } void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 4967990bfc46..9bda6c99eff2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -234,6 +234,7 @@ static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm, /* Found a place for all queues - enable them */ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac], + mvmsta->hw_queue[ac], iwl_mvm_ac_to_tx_fifo[ac], wdg_timeout); mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]); } @@ -253,7 +254,7 @@ static void iwl_mvm_tdls_sta_deinit(struct iwl_mvm *mvm, /* disable the TDLS STA-specific queues */ sta_msk = mvmsta->tfd_queue_msk; for_each_set_bit(i, &sta_msk, sizeof(sta_msk) * BITS_PER_BYTE) - iwl_mvm_disable_txq(mvm, i, 0); + iwl_mvm_disable_txq(mvm, i, i, 0, 0); } int iwl_mvm_add_sta(struct iwl_mvm *mvm, @@ -472,7 +473,7 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk) unsigned long i, msk = mvm->tfd_drained[sta_id]; for_each_set_bit(i, &msk, sizeof(msk) * BITS_PER_BYTE) - iwl_mvm_disable_txq(mvm, i, 0); + iwl_mvm_disable_txq(mvm, i, i, 0, 0); mvm->tfd_drained[sta_id] = 0; IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n", @@ -651,7 +652,7 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) lockdep_assert_held(&mvm->mutex); /* Map Aux queue to fifo - needs to happen before adding Aux station */ - iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, + iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, mvm->aux_queue, IWL_MVM_TX_FIFO_MCAST, wdg_timeout); /* Allocate aux station and assign to it the aux queue */ @@ -923,6 +924,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_tid_data *tid_data; int txq_id; + int ret; if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) return -EINVAL; @@ -935,17 +937,6 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, lockdep_assert_held(&mvm->mutex); - for (txq_id = mvm->first_agg_queue; - txq_id <= mvm->last_agg_queue; txq_id++) - if (mvm->queue_to_mac80211[txq_id] == - IWL_INVALID_MAC80211_QUEUE) - break; - - if (txq_id > mvm->last_agg_queue) { - IWL_ERR(mvm, "Failed to allocate agg queue\n"); - return -EIO; - } - spin_lock_bh(&mvmsta->lock); /* possible race condition - we entered D0i3 while starting agg */ @@ -955,8 +946,18 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return -EIO; } - /* the new tx queue is still connected to the same mac80211 queue */ - mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_mac80211_ac[tid]]; + spin_lock_bh(&mvm->queue_info_lock); + + txq_id = iwl_mvm_find_free_queue(mvm, mvm->first_agg_queue, + mvm->last_agg_queue); + if (txq_id < 0) { + ret = txq_id; + spin_unlock_bh(&mvm->queue_info_lock); + IWL_ERR(mvm, "Failed to allocate agg queue\n"); + goto release_locks; + } + mvm->queue_info[txq_id].setup_reserved = true; + spin_unlock_bh(&mvm->queue_info_lock); tid_data = &mvmsta->tid_data[tid]; tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); @@ -975,9 +976,12 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, tid_data->state = IWL_EMPTYING_HW_QUEUE_ADDBA; } + ret = 0; + +release_locks: spin_unlock_bh(&mvmsta->lock); - return 0; + return ret; } int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, @@ -1005,13 +1009,19 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; - iwl_mvm_enable_agg_txq(mvm, queue, fifo, mvmsta->sta_id, tid, - buf_size, ssn, wdg_timeout); + iwl_mvm_enable_agg_txq(mvm, queue, + vif->hw_queue[tid_to_mac80211_ac[tid]], fifo, + mvmsta->sta_id, tid, buf_size, ssn, wdg_timeout); ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true); if (ret) return -EIO; + /* No need to mark as reserved */ + spin_lock_bh(&mvm->queue_info_lock); + mvm->queue_info[queue].setup_reserved = false; + spin_unlock_bh(&mvm->queue_info_lock); + /* * Even though in theory the peer could have different * aggregation reorder buffer sizes for different sessions, @@ -1056,6 +1066,11 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvmsta->agg_tids &= ~BIT(tid); + /* No need to mark as reserved anymore */ + spin_lock_bh(&mvm->queue_info_lock); + mvm->queue_info[txq_id].setup_reserved = false; + spin_unlock_bh(&mvm->queue_info_lock); + switch (tid_data->state) { case IWL_AGG_ON: tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); @@ -1073,14 +1088,15 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, tid_data->ssn = 0xffff; tid_data->state = IWL_AGG_OFF; - mvm->queue_to_mac80211[txq_id] = IWL_INVALID_MAC80211_QUEUE; spin_unlock_bh(&mvmsta->lock); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false); - iwl_mvm_disable_txq(mvm, txq_id, 0); + iwl_mvm_disable_txq(mvm, txq_id, + vif->hw_queue[tid_to_mac80211_ac[tid]], tid, + 0); return 0; case IWL_AGG_STARTING: case IWL_EMPTYING_HW_QUEUE_ADDBA: @@ -1091,7 +1107,6 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, /* No barriers since we are under mutex */ lockdep_assert_held(&mvm->mutex); - mvm->queue_to_mac80211[txq_id] = IWL_INVALID_MAC80211_QUEUE; ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); tid_data->state = IWL_AGG_OFF; @@ -1132,6 +1147,11 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvmsta->agg_tids &= ~BIT(tid); spin_unlock_bh(&mvmsta->lock); + /* No need to mark as reserved */ + spin_lock_bh(&mvm->queue_info_lock); + mvm->queue_info[txq_id].setup_reserved = false; + spin_unlock_bh(&mvm->queue_info_lock); + if (old_state >= IWL_AGG_ON) { iwl_mvm_drain_sta(mvm, mvmsta, true); if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true)) @@ -1142,12 +1162,11 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false); - iwl_mvm_disable_txq(mvm, tid_data->txq_id, 0); + iwl_mvm_disable_txq(mvm, tid_data->txq_id, + vif->hw_queue[tid_to_mac80211_ac[tid]], tid, + 0); } - mvm->queue_to_mac80211[tid_data->txq_id] = - IWL_INVALID_MAC80211_QUEUE; - return 0; } diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 6df5aada4f16..ff8b9bdef7e8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -560,15 +560,10 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm, IWL_DEBUG_TX_QUEUES(mvm, "Can continue DELBA flow ssn = next_recl = %d\n", tid_data->next_reclaimed); - iwl_mvm_disable_txq(mvm, tid_data->txq_id, CMD_ASYNC); + iwl_mvm_disable_txq(mvm, tid_data->txq_id, + vif->hw_queue[tid_to_mac80211_ac[tid]], tid, + CMD_ASYNC); tid_data->state = IWL_AGG_OFF; - /* - * we can't hold the mutex - but since we are after a sequence - * point (call to iwl_mvm_disable_txq(), so we don't even need - * a memory barrier. - */ - mvm->queue_to_mac80211[tid_data->txq_id] = - IWL_INVALID_MAC80211_QUEUE; ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); break; diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 06cba97418b3..ad0f16909e2e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright (C) 2015 Intel Deutschland GmbH * * 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 @@ -657,34 +658,143 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) if (mvm->support_umac_log) iwl_mvm_dump_umac_error_log(mvm); } -void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, - const struct iwl_trans_txq_scd_cfg *cfg, + +int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 minq, u8 maxq) +{ + int i; + + lockdep_assert_held(&mvm->queue_info_lock); + + for (i = minq; i <= maxq; i++) + if (mvm->queue_info[i].hw_queue_refcount == 0 && + !mvm->queue_info[i].setup_reserved) + return i; + + return -ENOSPC; +} + +void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, + u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg, unsigned int wdg_timeout) { - struct iwl_scd_txq_cfg_cmd cmd = { - .scd_queue = queue, - .enable = 1, - .window = cfg->frame_limit, - .sta_id = cfg->sta_id, - .ssn = cpu_to_le16(ssn), - .tx_fifo = cfg->fifo, - .aggregate = cfg->aggregate, - .tid = cfg->tid, - }; + bool enable_queue = true; + + spin_lock_bh(&mvm->queue_info_lock); + + /* Make sure this TID isn't already enabled */ + if (mvm->queue_info[queue].tid_bitmap & BIT(cfg->tid)) { + spin_unlock_bh(&mvm->queue_info_lock); + IWL_ERR(mvm, "Trying to enable TXQ with existing TID %d\n", + cfg->tid); + return; + } - 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), &cmd), - "Failed to configure queue %d on FIFO %d\n", queue, cfg->fifo); + /* Update mappings and refcounts */ + mvm->queue_info[queue].hw_queue_to_mac80211 |= BIT(mac80211_queue); + mvm->queue_info[queue].hw_queue_refcount++; + if (mvm->queue_info[queue].hw_queue_refcount > 1) + enable_queue = false; + mvm->queue_info[queue].tid_bitmap |= BIT(cfg->tid); + + IWL_DEBUG_TX_QUEUES(mvm, + "Enabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n", + queue, mvm->queue_info[queue].hw_queue_refcount, + mvm->queue_info[queue].hw_queue_to_mac80211); + + spin_unlock_bh(&mvm->queue_info_lock); + + /* Send the enabling command if we need to */ + if (enable_queue) { + struct iwl_scd_txq_cfg_cmd cmd = { + .scd_queue = queue, + .enable = 1, + .window = cfg->frame_limit, + .sta_id = cfg->sta_id, + .ssn = cpu_to_le16(ssn), + .tx_fifo = cfg->fifo, + .aggregate = cfg->aggregate, + .tid = cfg->tid, + }; + + 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), + &cmd), + "Failed to configure queue %d on FIFO %d\n", queue, + cfg->fifo); + } } -void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags) +void 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, .enable = 0, }; + bool remove_mac_queue = true; int ret; + spin_lock_bh(&mvm->queue_info_lock); + + if (WARN_ON(mvm->queue_info[queue].hw_queue_refcount == 0)) { + spin_unlock_bh(&mvm->queue_info_lock); + return; + } + + mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); + + /* + * If there is another TID with the same AC - don't remove the MAC queue + * from the mapping + */ + if (tid < IWL_MAX_TID_COUNT) { + unsigned long tid_bitmap = + mvm->queue_info[queue].tid_bitmap; + int ac = tid_to_mac80211_ac[tid]; + int i; + + for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT) { + if (tid_to_mac80211_ac[i] == ac) + remove_mac_queue = false; + } + } + + if (remove_mac_queue) + mvm->queue_info[queue].hw_queue_to_mac80211 &= + ~BIT(mac80211_queue); + mvm->queue_info[queue].hw_queue_refcount--; + + cmd.enable = mvm->queue_info[queue].hw_queue_refcount ? 1 : 0; + + IWL_DEBUG_TX_QUEUES(mvm, + "Disabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n", + queue, + mvm->queue_info[queue].hw_queue_refcount, + mvm->queue_info[queue].hw_queue_to_mac80211); + + /* If the queue is still enabled - nothing left to do in this func */ + if (cmd.enable) { + spin_unlock_bh(&mvm->queue_info_lock); + return; + } + + /* Make sure queue info is correct even though we overwrite it */ + WARN(mvm->queue_info[queue].hw_queue_refcount || + mvm->queue_info[queue].tid_bitmap || + mvm->queue_info[queue].hw_queue_to_mac80211, + "TXQ #%d info out-of-sync - refcount=%d, mac map=0x%x, tid=0x%x\n", + queue, mvm->queue_info[queue].hw_queue_refcount, + mvm->queue_info[queue].hw_queue_to_mac80211, + mvm->queue_info[queue].tid_bitmap); + + /* If we are here - the queue is freed and we can zero out these vals */ + mvm->queue_info[queue].hw_queue_refcount = 0; + mvm->queue_info[queue].tid_bitmap = 0; + mvm->queue_info[queue].hw_queue_to_mac80211 = 0; + + spin_unlock_bh(&mvm->queue_info_lock); + iwl_trans_txq_disable(mvm->trans, queue, false); ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, flags, sizeof(cmd), &cmd); -- cgit v1.2.3 From 5c1156efebc6b76b4a7daec844c19d2ce1d7bb03 Mon Sep 17 00:00:00 2001 From: Liad Kaufman Date: Wed, 22 Jul 2015 17:59:53 +0300 Subject: iwlwifi: mvm: support enabling a queue with a given ssn When enabling a queue, the default SSN is 0. Allow determining what that SSN should be, if required. This can happen, for example, if a queue gets reconfigured. Signed-off-by: Liad Kaufman Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 6 +++--- drivers/net/wireless/iwlwifi/mvm/mvm.h | 4 ++-- drivers/net/wireless/iwlwifi/mvm/sta.c | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index d2a221da7c77..9d36ba7295a5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -487,17 +487,17 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) case NL80211_IFTYPE_P2P_DEVICE: iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, IWL_MVM_OFFCHANNEL_QUEUE, - IWL_MVM_TX_FIFO_VO, wdg_timeout); + IWL_MVM_TX_FIFO_VO, 0, wdg_timeout); break; case NL80211_IFTYPE_AP: iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, vif->cab_queue, - IWL_MVM_TX_FIFO_MCAST, wdg_timeout); + IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout); /* fall through */ default: for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac], vif->hw_queue[ac], - iwl_mvm_ac_to_tx_fifo[ac], + iwl_mvm_ac_to_tx_fifo[ac], 0, wdg_timeout); break; } diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index a7a961947d6c..99182df47e8b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -1366,7 +1366,7 @@ int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 minq, u8 maxq); static inline void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, - u8 fifo, unsigned int wdg_timeout) + u8 fifo, u16 ssn, unsigned int wdg_timeout) { struct iwl_trans_txq_scd_cfg cfg = { .fifo = fifo, @@ -1375,7 +1375,7 @@ void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, .frame_limit = IWL_FRAME_LIMIT, }; - iwl_mvm_enable_txq(mvm, queue, mac80211_queue, 0, &cfg, wdg_timeout); + iwl_mvm_enable_txq(mvm, queue, mac80211_queue, ssn, &cfg, wdg_timeout); } static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 9bda6c99eff2..a9a3eb6a1f8a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -235,7 +235,8 @@ static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm, for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac], mvmsta->hw_queue[ac], - iwl_mvm_ac_to_tx_fifo[ac], wdg_timeout); + iwl_mvm_ac_to_tx_fifo[ac], 0, + wdg_timeout); mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]); } @@ -653,7 +654,7 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) /* Map Aux queue to fifo - needs to happen before adding Aux station */ iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, mvm->aux_queue, - IWL_MVM_TX_FIFO_MCAST, wdg_timeout); + IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout); /* Allocate aux station and assign to it the aux queue */ ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue), -- cgit v1.2.3 From ceef91c89480dd18bb3ac51e91280a233d0ca41f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 4 Sep 2015 11:27:25 +0200 Subject: iwlwifi: mvm: stop using DEVICE_POWER_FLAGS_CAM_MSK The firmware has always treated these two bits to mean that powersave is enabled when POWER_SAVE_ENA is set and CAM is clear; it doesn't use them in any non-combined way. Therefore, it's pointless to send it two bits, and the API should be cleaned up. Prepare the driver by removing the CAM bit and using only POWER_SAVE_ENA to indicate whether PS is enabled or not. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | 8 +------- drivers/net/wireless/iwlwifi/mvm/power.c | 6 +++--- 2 files changed, 4 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index 7005fa4be74a..c8f3e2536cbb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h @@ -192,16 +192,10 @@ struct iwl_powertable_cmd { /** * enum iwl_device_power_flags - masks for device power command flags * @DEVIC_POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off - * receiver and transmitter. '0' - does not allow. This flag should be - * always set to '1' unless one need to disable actual power down for debug - * purposes. - * @DEVICE_POWER_FLAGS_CAM_MSK: '1' CAM (Continuous Active Mode) is set, meaning - * that power management is disabled. '0' Power management is enabled, one - * of power schemes is applied. + * receiver and transmitter. '0' - does not allow. */ enum iwl_device_power_flags { DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), - DEVICE_POWER_FLAGS_CAM_MSK = BIT(13), }; /** diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 21a858dfcc26..723b537341c4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -471,14 +471,14 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, int iwl_mvm_power_update_device(struct iwl_mvm *mvm) { struct iwl_device_power_cmd cmd = { - .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK), + .flags = 0, }; if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) mvm->ps_disabled = true; - if (mvm->ps_disabled) - cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK); + if (!mvm->ps_disabled) + cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK); #ifdef CONFIG_IWLWIFI_DEBUGFS if ((mvm->cur_ucode == IWL_UCODE_WOWLAN) ? mvm->disable_power_off_d3 : -- cgit v1.2.3 From cc60c6e92907d7d1380353b46d7db9826a3622f2 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sat, 19 Sep 2015 23:37:45 +0300 Subject: iwlwifi: mvm: rs: improve rate debug messages Pretty print the rate full details to ease debugging. Signed-off-by: Eyal Shapira Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/rs.c | 60 +++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 5ae9c8aa868f..98f4d78598c5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -524,14 +524,56 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type) return lq_types[type]; } +static char *rs_pretty_rate(const struct rs_rate *rate) +{ + static char buf[40]; + static const char * const legacy_rates[] = { + [IWL_RATE_1M_INDEX] = "1M", + [IWL_RATE_2M_INDEX] = "2M", + [IWL_RATE_5M_INDEX] = "5.5M", + [IWL_RATE_11M_INDEX] = "11M", + [IWL_RATE_6M_INDEX] = "6M", + [IWL_RATE_9M_INDEX] = "9M", + [IWL_RATE_12M_INDEX] = "12M", + [IWL_RATE_18M_INDEX] = "18M", + [IWL_RATE_24M_INDEX] = "24M", + [IWL_RATE_36M_INDEX] = "36M", + [IWL_RATE_48M_INDEX] = "48M", + [IWL_RATE_54M_INDEX] = "54M", + }; + static const char *const ht_vht_rates[] = { + [IWL_RATE_MCS_0_INDEX] = "MCS0", + [IWL_RATE_MCS_1_INDEX] = "MCS1", + [IWL_RATE_MCS_2_INDEX] = "MCS2", + [IWL_RATE_MCS_3_INDEX] = "MCS3", + [IWL_RATE_MCS_4_INDEX] = "MCS4", + [IWL_RATE_MCS_5_INDEX] = "MCS5", + [IWL_RATE_MCS_6_INDEX] = "MCS6", + [IWL_RATE_MCS_7_INDEX] = "MCS7", + [IWL_RATE_MCS_8_INDEX] = "MCS8", + [IWL_RATE_MCS_9_INDEX] = "MCS9", + }; + const char *rate_str; + + if (is_type_legacy(rate->type)) + rate_str = legacy_rates[rate->index]; + else if (is_type_ht(rate->type) || is_type_vht(rate->type)) + rate_str = ht_vht_rates[rate->index]; + else + rate_str = "BAD_RATE"; + + sprintf(buf, "(%s|%s|%s)", rs_pretty_lq_type(rate->type), + rs_pretty_ant(rate->ant), rate_str); + return buf; +} + static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate, const char *prefix) { IWL_DEBUG_RATE(mvm, - "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d STBC: %d\n", - prefix, rs_pretty_lq_type(rate->type), - rate->index, rs_pretty_ant(rate->ant), - rate->bw, rate->sgi, rate->ldpc, rate->stbc); + "%s: %s BW: %d SGI: %d LDPC: %d STBC: %d\n", + prefix, rs_pretty_rate(rate), rate->bw, + rate->sgi, rate->ldpc, rate->stbc); } static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) @@ -2174,9 +2216,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, if ((fail_count < IWL_MVM_RS_RATE_MIN_FAILURE_TH) && (window->success_counter < IWL_MVM_RS_RATE_MIN_SUCCESS_TH)) { IWL_DEBUG_RATE(mvm, - "(%s: %d): Test Window: succ %d total %d\n", - rs_pretty_lq_type(rate->type), - index, window->success_counter, window->counter); + "%s: Test Window: succ %d total %d\n", + rs_pretty_rate(rate), + window->success_counter, window->counter); /* Can't calculate this yet; not enough history */ window->average_tpt = IWL_INVALID_VALUE; @@ -2253,8 +2295,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, high_tpt = tbl->win[high].average_tpt; IWL_DEBUG_RATE(mvm, - "(%s: %d): cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n", - rs_pretty_lq_type(rate->type), index, current_tpt, sr, + "%s: cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n", + rs_pretty_rate(rate), current_tpt, sr, low, high, low_tpt, high_tpt); scale_action = rs_get_rate_action(mvm, tbl, sr, low, high, -- cgit v1.2.3 From dfa1325a0865da0509f045ddc4c99b8653517f6b Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sat, 19 Sep 2015 23:46:32 +0300 Subject: iwlwifi: mvm: rs: remove overflowing debug message This message isn't very useful and creates clutter. Remove it. Signed-off-by: Eyal Shapira Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/rs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 98f4d78598c5..49cf3119d3e5 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -2584,7 +2584,6 @@ static struct rs_rate *rs_get_optimal_rate(struct iwl_mvm *mvm, } } - rs_dump_rate(mvm, rate, "OPTIMAL RATE"); return rate; } -- cgit v1.2.3 From 40ce5ed1e9d5c80819733c4fdc40a2b6c531d981 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sat, 19 Sep 2015 23:54:38 +0300 Subject: iwlwifi: mvm: rs: minor indentation fix Indentation was off a bit. Fix it. Signed-off-by: Eyal Shapira Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/rs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 49cf3119d3e5..2bf2a0895723 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -604,8 +604,8 @@ static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) } static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm, - struct iwl_lq_sta *lq_data, u8 tid, - struct ieee80211_sta *sta) + struct iwl_lq_sta *lq_data, u8 tid, + struct ieee80211_sta *sta) { int ret = -EAGAIN; -- cgit v1.2.3 From ed21a384bbd2b011289dd1b5cab7eebc7ebeda11 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Mon, 21 Sep 2015 20:03:22 +0300 Subject: iwlwifi: mvm: rs: fix success ratio comparison in rs_get_best_rate success_ratio is actually 128 * SR in percentage while IWL_MVM_RS_SR_NO_DECREASE is 85%. Fix this by using RS_PERCENT(). This bug caused the if branch to be always executed. This in turn led to always selecting a rate, following a column switch, in which the expected throughput would exceed the best expected current throughput. In some scenarios where the success ratio isn't >85% such a rate could be too aggressive leading us to avoid the new column. This has the potential of causing sub optimal performance. Reported-by: Moshe Harel Signed-off-by: Eyal Shapira Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/rs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 2bf2a0895723..435e1e40edb8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -1527,7 +1527,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, u32 target_tpt; int rate_idx; - if (success_ratio > IWL_MVM_RS_SR_NO_DECREASE) { + if (success_ratio >= RS_PERCENT(IWL_MVM_RS_SR_NO_DECREASE)) { target_tpt = 100 * expected_current_tpt; IWL_DEBUG_RATE(mvm, "SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n", @@ -1535,7 +1535,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, } else { target_tpt = lq_sta->last_tpt; IWL_DEBUG_RATE(mvm, - "SR %d not thag good. Find rate exceeding ACTUAL_TPT %d\n", + "SR %d not that good. Find rate exceeding ACTUAL_TPT %d\n", success_ratio, target_tpt); } -- cgit v1.2.3 From 5736b7eba362ee304335808325ad60e2249ac670 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 22 Sep 2015 10:51:17 +0200 Subject: iwlwifi: remove IWL3165_UCODE_API_OK and _MIN As the 3165 device uses the same firmware as 7265-D and currently all 7000 series (including 3160/3165) use the same API versions remove IWL3165_UCODE_API_OK and _MIN. We might have to put them back if firmware support ever splits, but in that case might also have to add a different MODULE_FIRMWARE statement. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/iwl-7000.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 5b25f367ef48..d561181f2cff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -73,11 +73,9 @@ /* Oldest version we won't warn about */ #define IWL7260_UCODE_API_OK 13 -#define IWL3165_UCODE_API_OK 13 /* Lowest firmware API version supported */ #define IWL7260_UCODE_API_MIN 13 -#define IWL3165_UCODE_API_MIN 13 /* NVM versions */ #define IWL7260_NVM_VERSION 0x0a1d @@ -269,11 +267,6 @@ const struct iwl_cfg iwl3165_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 3165", .fw_name_pre = IWL7265D_FW_PRE, IWL_DEVICE_7000, - /* sparse doens't like the re-assignment but it is safe */ -#ifndef __CHECKER__ - .ucode_api_ok = IWL3165_UCODE_API_OK, - .ucode_api_min = IWL3165_UCODE_API_MIN, -#endif .ht_params = &iwl7000_ht_params, .nvm_ver = IWL3165_NVM_VERSION, .nvm_calib_ver = IWL3165_TX_POWER_VERSION, -- cgit v1.2.3 From 7c0ebd7870ce212d370a97d3d8ff5129edcc2323 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 22 Sep 2015 12:28:42 +0200 Subject: iwlwifi: mvm: minor rx code cleanup Clean up variable initialisation slightly. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/rx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 0a6d47c5bfc8..5b58f5320e8d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c @@ -346,8 +346,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, /* This is fine since we don't support multiple AP interfaces */ sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL); if (sta) { - struct iwl_mvm_sta *mvmsta; - mvmsta = iwl_mvm_sta_from_mac80211(sta); + struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status); if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) && -- cgit v1.2.3 From 1191f646bb913feba4239a7ca45e5edb09324869 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sat, 19 Sep 2015 23:48:45 +0300 Subject: iwlwifi: mvm: rs: dynamically switch between 80MHz and 20MHz in some scenarios This is a tweak which has been shown to improve performance when moving away from the AP while working in 80Mhz. When RS decides to go down to 80MHz SISO MCS0 instead switch to 20MHz MCS4. Go back to 80MHz MCS1 if RS can sustain 20MHz MCS5. Signed-off-by: Eyal Shapira Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/constants.h | 1 + drivers/net/wireless/iwlwifi/mvm/rs.c | 47 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index b8ee3121fbd2..a3ca6db0f303 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h @@ -102,6 +102,7 @@ #define IWL_MVM_QUOTA_THRESHOLD 4 #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 #define IWL_MVM_RS_DISABLE_P2P_MIMO 0 +#define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1 #define IWL_MVM_TOF_IS_RESPONDER 0 #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2 diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 435e1e40edb8..34d98b26a215 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -1664,6 +1664,51 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm, iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); } +static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm, + struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, + enum rs_action scale_action) +{ + if (sta->bandwidth != IEEE80211_STA_RX_BW_80) + return false; + + if (!is_vht_siso(&tbl->rate)) + return false; + + if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_80) && + (tbl->rate.index == IWL_RATE_MCS_0_INDEX) && + (scale_action == RS_ACTION_DOWNSCALE)) { + tbl->rate.bw = RATE_MCS_CHAN_WIDTH_20; + tbl->rate.index = IWL_RATE_MCS_4_INDEX; + IWL_DEBUG_RATE(mvm, "Switch 80Mhz SISO MCS0 -> 20Mhz MCS4\n"); + goto tweaked; + } + + /* Go back to 80Mhz MCS1 only if we've established that 20Mhz MCS5 is + * sustainable, i.e. we're past the test window. We can't go back + * if MCS5 is just tested as this will happen always after switching + * to 20Mhz MCS4 because the rate stats are cleared. + */ + if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_20) && + (((tbl->rate.index == IWL_RATE_MCS_5_INDEX) && + (scale_action == RS_ACTION_STAY)) || + ((tbl->rate.index > IWL_RATE_MCS_5_INDEX) && + (scale_action == RS_ACTION_UPSCALE)))) { + tbl->rate.bw = RATE_MCS_CHAN_WIDTH_80; + tbl->rate.index = IWL_RATE_MCS_1_INDEX; + IWL_DEBUG_RATE(mvm, "Switch 20Mhz SISO MCS5 -> 80Mhz MCS1\n"); + goto tweaked; + } + + return false; + +tweaked: + rs_set_expected_tpt_table(lq_sta, tbl); + rs_rate_scale_clear_tbl_windows(mvm, tbl); + return true; +} + static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, struct iwl_lq_sta *lq_sta, struct ieee80211_sta *sta, @@ -2347,6 +2392,8 @@ lq_update: /* Replace uCode's rate table for the destination station. */ if (update_lq) { tbl->rate.index = index; + if (IWL_MVM_RS_80_20_FAR_RANGE_TWEAK) + rs_tweak_rate_tbl(mvm, sta, lq_sta, tbl, scale_action); rs_update_rate_tbl(mvm, sta, lq_sta, tbl); } -- cgit v1.2.3 From e6c21be665cab08325ee1f99e76497b5ffa924a9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 24 Sep 2015 22:15:02 +0200 Subject: iwlwifi: mvm: fix signedness warnings in ToF debugfs Using an int* instead of u32* as the kstrtou32() output argument obviously results in signedness warnings, change that. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 5dc1686100d2..398bef6f4f61 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c @@ -511,7 +511,8 @@ static ssize_t iwl_dbgfs_tof_enable_write(struct ieee80211_vif *vif, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; - int value, ret = -EINVAL; + u32 value; + int ret = -EINVAL; char *data; mutex_lock(&mvm->mutex); @@ -599,7 +600,8 @@ static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; - int value, ret = 0; + u32 value; + int ret = 0; char *data; mutex_lock(&mvm->mutex); @@ -822,7 +824,8 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; - int value, ret = 0; + u32 value; + int ret = 0; char *data; mutex_lock(&mvm->mutex); @@ -1023,7 +1026,8 @@ static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; - int value, ret = 0; + u32 value; + int ret = 0; char *data; mutex_lock(&mvm->mutex); @@ -1127,8 +1131,8 @@ static ssize_t iwl_dbgfs_tof_range_abort_write(struct ieee80211_vif *vif, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; - int value, ret = 0; - int abort_id; + u32 value; + int abort_id, ret = 0; char *data; mutex_lock(&mvm->mutex); -- cgit v1.2.3 From 91fac940896b345d10e503ed7e1f54f85b3b9318 Mon Sep 17 00:00:00 2001 From: Moshe Harel Date: Wed, 2 Sep 2015 12:45:12 +0300 Subject: iwlwifi: nvm: add nvm phy_sku section to debugfs The only NVM section not captured in debugfs. Signed-off-by: Moshe Harel Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 3 +++ drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 + drivers/net/wireless/iwlwifi/mvm/nvm.c | 4 ++++ 3 files changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 3b8481f34a18..9b4fbb8b483a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -1495,6 +1495,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) if (!debugfs_create_blob("nvm_prod", S_IRUSR, mvm->debugfs_dir, &mvm->nvm_prod_blob)) goto err; + if (!debugfs_create_blob("nvm_phy_sku", S_IRUSR, + mvm->debugfs_dir, &mvm->nvm_phy_sku_blob)) + goto err; /* * Create a symlink with mac80211. It will be removed when mac80211 diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 99182df47e8b..f4e22f5a29d1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -688,6 +688,7 @@ struct iwl_mvm { struct debugfs_blob_wrapper nvm_sw_blob; struct debugfs_blob_wrapper nvm_calib_blob; struct debugfs_blob_wrapper nvm_prod_blob; + struct debugfs_blob_wrapper nvm_phy_sku_blob; struct iwl_mvm_frame_stats drv_rx_stats; spinlock_t drv_stats_lock; diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 0b3ffd5e0f3b..4e4a680f274a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c @@ -564,6 +564,10 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic) mvm->nvm_prod_blob.data = temp; mvm->nvm_prod_blob.size = ret; break; + case NVM_SECTION_TYPE_PHY_SKU: + mvm->nvm_phy_sku_blob.data = temp; + mvm->nvm_phy_sku_blob.size = ret; + break; default: if (section == mvm->cfg->nvm_hw_section_num) { mvm->nvm_hw_blob.data = temp; -- cgit v1.2.3 From fe96cc73c9f405a0bdc90504048235dfd0384582 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 24 Sep 2015 22:19:43 +0200 Subject: iwlwifi: mvm: make threshold temperatures unsigned There's no need to have negative threshold temperatures, so make them unsigned to avoid signedness warnings in debugfs. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/iwl-config.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 939fa229c038..910970858f98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -223,13 +223,13 @@ struct iwl_tt_tx_backoff { * @support_tx_backoff: Support tx-backoff? */ struct iwl_tt_params { - s32 ct_kill_entry; - s32 ct_kill_exit; + u32 ct_kill_entry; + u32 ct_kill_exit; u32 ct_kill_duration; - s32 dynamic_smps_entry; - s32 dynamic_smps_exit; - s32 tx_protection_entry; - s32 tx_protection_exit; + u32 dynamic_smps_entry; + u32 dynamic_smps_exit; + u32 tx_protection_entry; + u32 tx_protection_exit; struct iwl_tt_tx_backoff tx_backoff[TT_TX_BACKOFF_SIZE]; bool support_ct_kill; bool support_dynamic_smps; -- cgit v1.2.3 From d3f555f493b037eb688adda6d8a682e9b69211ed Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 16 Sep 2015 12:21:32 +0200 Subject: iwlwifi: size firmware flags memory correctly Instead of relying on a hard-coded constant of a maximum of 64 API and capability bits, add a new enum value after the others that will then always track the number of used bits in the API/capabilities. We thus no longer need to maintain the maximum number, and on 32-bit platforms even (currently) reduce the number of bits kept in memory. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/iwl-drv.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-fw-file.h | 19 ++++++++++++++++--- drivers/net/wireless/iwlwifi/iwl-fw.h | 4 ++-- 3 files changed, 20 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index a86aa5bcee7d..463cadfbfccb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -450,7 +450,7 @@ static int iwl_set_ucode_api_flags(struct iwl_drv *drv, const u8 *data, u32 api_flags = le32_to_cpu(ucode_api->api_flags); int i; - if (api_index >= IWL_API_MAX_BITS / 32) { + if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_API, 32)) { IWL_ERR(drv, "api_index larger than supported by driver\n"); /* don't return an error so we can load FW that has more bits */ return 0; @@ -472,7 +472,7 @@ static int iwl_set_ucode_capabilities(struct iwl_drv *drv, const u8 *data, u32 api_flags = le32_to_cpu(ucode_capa->api_capa); int i; - if (api_index >= IWL_CAPABILITIES_MAX_BITS / 32) { + if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_CAPA, 32)) { IWL_ERR(drv, "api_index larger than supported by driver\n"); /* don't return an error so we can load FW that has more bits */ return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 352d245765e7..72ddd4a163e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h @@ -254,6 +254,8 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_api_t; * instead of 3. * @IWL_UCODE_TLV_API_TX_POWER_CHAIN: TX power API has larger command size * (command version 3) that supports per-chain limits + * + * @NUM_IWL_UCODE_TLV_API: number of bits used */ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_BT_COEX_SPLIT = (__force iwl_ucode_tlv_api_t)3, @@ -264,6 +266,12 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_NEW_VERSION = (__force iwl_ucode_tlv_api_t)20, IWL_UCODE_TLV_API_EXT_SCAN_PRIORITY = (__force iwl_ucode_tlv_api_t)24, IWL_UCODE_TLV_API_TX_POWER_CHAIN = (__force iwl_ucode_tlv_api_t)27, + + NUM_IWL_UCODE_TLV_API +#ifdef __CHECKER__ + /* sparse says it cannot increment the previous enum member */ + = 128 +#endif }; typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; @@ -298,6 +306,8 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * is supported. * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan + * + * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = (__force iwl_ucode_tlv_capa_t)0, @@ -320,6 +330,12 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, + + NUM_IWL_UCODE_TLV_CAPA +#ifdef __CHECKER__ + /* sparse says it cannot increment the previous enum member */ + = 128 +#endif }; /* The default calibrate table size if not specified by firmware file */ @@ -330,9 +346,6 @@ enum iwl_ucode_tlv_capa { /* The default max probe length if not specified by the firmware file */ #define IWL_DEFAULT_MAX_PROBE_LENGTH 200 -#define IWL_API_MAX_BITS 64 -#define IWL_CAPABILITIES_MAX_BITS 64 - /* * For 16.0 uCode and above, there is no differentiation between sections, * just an offset to the HW address. diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index 45e732150d28..84ec0cefb62a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h @@ -105,8 +105,8 @@ struct iwl_ucode_capabilities { u32 n_scan_channels; u32 standard_phy_calibration_size; u32 flags; - unsigned long _api[BITS_TO_LONGS(IWL_API_MAX_BITS)]; - unsigned long _capa[BITS_TO_LONGS(IWL_CAPABILITIES_MAX_BITS)]; + unsigned long _api[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_API)]; + unsigned long _capa[BITS_TO_LONGS(NUM_IWL_UCODE_TLV_CAPA)]; }; static inline bool -- cgit v1.2.3 From 0316d30ea3e66379cd30ed70a114bc282159bb4c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 22 May 2015 13:41:07 +0200 Subject: iwlwifi: mvm: add minimal multi-RXQ infrastructure Since the new multi-queue capability depends on a new firmware API, we can already add some code for it. If the new API is present, a new opmode ops struct is used that handles the new rx_rss method. For now, only restructure the RX handling to distinguish between the two. Future patches will convert the new infrastructure to actually use the new RX descriptor layout. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/iwlwifi/mvm/mvm.h | 6 ++ drivers/net/wireless/iwlwifi/mvm/ops.c | 104 ++++++++++++++++++++++++--------- 2 files changed, 83 insertions(+), 27 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index f4e22f5a29d1..0d3aff1b4bad 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -970,6 +970,12 @@ static inline bool iwl_mvm_is_csum_supported(struct iwl_mvm *mvm) IWL_UCODE_TLV_CAPA_CSUM_SUPPORT); } +static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm) +{ + /* firmware flag isn't defined yet */ + return false; +} + extern const u8 iwl_mvm_ac_to_tx_fifo[]; struct iwl_rate_info { diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 0e8166fb31e9..064c100e45fe 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -89,6 +89,7 @@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); MODULE_LICENSE("GPL"); static const struct iwl_op_mode_ops iwl_mvm_ops; +static const struct iwl_op_mode_ops iwl_mvm_ops_mq; struct iwl_mvm_mod_params iwlmvm_mod_params = { .power_scheme = IWL_POWER_SCHEME_BPS, @@ -424,7 +425,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size; op_mode = hw->priv; - op_mode->ops = &iwl_mvm_ops; mvm = IWL_OP_MODE_GET_MVM(op_mode); mvm->dev = trans->dev; @@ -433,6 +433,15 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, mvm->fw = fw; mvm->hw = hw; + if (iwl_mvm_has_new_rx_api(mvm)) { + op_mode->ops = &iwl_mvm_ops_mq; + } else { + op_mode->ops = &iwl_mvm_ops; + + if (WARN_ON(trans->num_rx_queues > 1)) + goto out_free; + } + mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0; mvm->aux_queue = 15; @@ -719,21 +728,11 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm, } } -static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode, - struct napi_struct *napi, - struct iwl_rx_cmd_buffer *rxb) +static void iwl_mvm_rx_common(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb, + struct iwl_rx_packet *pkt) { - struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); - u8 i; - - if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD)) { - iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); - return; - } else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD) { - iwl_mvm_rx_rx_phy_cmd(mvm, rxb); - return; - } + int i; iwl_mvm_rx_check_trigger(mvm, pkt); @@ -773,6 +772,36 @@ static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode, } } +static void iwl_mvm_rx(struct iwl_op_mode *op_mode, + struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + + if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD)) + iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); + else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD) + iwl_mvm_rx_rx_phy_cmd(mvm, rxb); + else + iwl_mvm_rx_common(mvm, rxb, pkt); +} + +static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode, + struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + + if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD)) + iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); + else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD) + iwl_mvm_rx_rx_phy_cmd(mvm, rxb); + else + iwl_mvm_rx_common(mvm, rxb, pkt); +} + static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) { struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); @@ -1366,17 +1395,38 @@ int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode) return _iwl_mvm_exit_d0i3(mvm); } +#define IWL_MVM_COMMON_OPS \ + /* these could be differentiated */ \ + .queue_full = iwl_mvm_stop_sw_queue, \ + .queue_not_full = iwl_mvm_wake_sw_queue, \ + .hw_rf_kill = iwl_mvm_set_hw_rfkill_state, \ + .free_skb = iwl_mvm_free_skb, \ + .nic_error = iwl_mvm_nic_error, \ + .cmd_queue_full = iwl_mvm_cmd_queue_full, \ + .nic_config = iwl_mvm_nic_config, \ + .enter_d0i3 = iwl_mvm_enter_d0i3, \ + .exit_d0i3 = iwl_mvm_exit_d0i3, \ + /* as we only register one, these MUST be common! */ \ + .start = iwl_op_mode_mvm_start, \ + .stop = iwl_op_mode_mvm_stop + static const struct iwl_op_mode_ops iwl_mvm_ops = { - .start = iwl_op_mode_mvm_start, - .stop = iwl_op_mode_mvm_stop, - .rx = iwl_mvm_rx_dispatch, - .queue_full = iwl_mvm_stop_sw_queue, - .queue_not_full = iwl_mvm_wake_sw_queue, - .hw_rf_kill = iwl_mvm_set_hw_rfkill_state, - .free_skb = iwl_mvm_free_skb, - .nic_error = iwl_mvm_nic_error, - .cmd_queue_full = iwl_mvm_cmd_queue_full, - .nic_config = iwl_mvm_nic_config, - .enter_d0i3 = iwl_mvm_enter_d0i3, - .exit_d0i3 = iwl_mvm_exit_d0i3, + IWL_MVM_COMMON_OPS, + .rx = iwl_mvm_rx, +}; + +static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode, + struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb, + unsigned int queue) +{ + struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + + iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); +} + +static const struct iwl_op_mode_ops iwl_mvm_ops_mq = { + IWL_MVM_COMMON_OPS, + .rx = iwl_mvm_rx_mq, + .rx_rss = iwl_mvm_rx_mq_rss, }; -- cgit v1.2.3 From 0a15afd2eaceceff5be4c8b7166f01c1a68e9642 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Thu, 1 Oct 2015 15:21:08 -0700 Subject: vrf: fix a kernel warning This fixes: tried to remove device ip6gre0 from (null) ------------[ cut here ]------------ kernel BUG at net/core/dev.c:5219! invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC CPU: 3 PID: 161 Comm: kworker/u8:2 Not tainted 4.3.0-rc2+ #1142 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 Workqueue: netns cleanup_net task: ffff8800d784a9c0 ti: ffff8800d74a4000 task.ti: ffff8800d74a4000 RIP: 0010:[] [] __netdev_adjacent_dev_remove+0x40/0xec RSP: 0018:ffff8800d74a7a98 EFLAGS: 00010282 RAX: 000000000000002a RBX: 0000000000000000 RCX: 0000000000000000 RDX: ffff88011adcf701 RSI: ffff88011adccbf8 RDI: ffff88011adccbf8 RBP: ffff8800d74a7ab8 R08: 0000000000000001 R09: 0000000000000000 R10: ffffffff81d190ff R11: 00000000ffffffff R12: ffff8800d599e7c0 R13: 0000000000000000 R14: ffff8800d599e890 R15: ffffffff82385e00 FS: 0000000000000000(0000) GS:ffff88011ac00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 00007ffd6f003000 CR3: 000000000220c000 CR4: 00000000000006e0 Stack: 0000000000000000 ffff8800d599e7c0 0000000000000b00 ffff8800d599e8a0 ffff8800d74a7ad8 ffffffff817f0861 0000000000000000 ffff8800d599e7c0 ffff8800d74a7af8 ffffffff817f088f 0000000000000000 ffff8800d599e7c0 Call Trace: [] __netdev_adjacent_dev_unlink+0x1e/0x35 [] __netdev_adjacent_dev_unlink_neighbour+0x17/0x41 [] netdev_upper_dev_unlink+0x6c/0x13d [] vrf_del_slave+0x26/0x7d [] vrf_device_event+0x2f/0x34 [] notifier_call_chain+0x75/0x9c [] raw_notifier_call_chain+0x14/0x16 [] call_netdevice_notifiers_info+0x52/0x59 [] call_netdevice_notifiers+0x13/0x15 [] rollback_registered_many+0x14f/0x24f [] unregister_netdevice_many+0x19/0x64 [] ip6gre_exit_net+0x163/0x177 [] ops_exit_list+0x44/0x55 [] cleanup_net+0x193/0x226 [] process_one_work+0x26c/0x4d8 [] ? process_one_work+0x170/0x4d8 [] worker_thread+0x1df/0x2c2 [] ? process_scheduled_works+0x2f/0x2f [] ? process_scheduled_works+0x2f/0x2f [] kthread+0xd4/0xdc [] ? trace_hardirqs_on_caller+0x17d/0x199 [] ? __kthread_parkme+0x83/0x83 [] ret_from_fork+0x3f/0x70 [] ? __kthread_parkme+0x83/0x83 Fixes: 93a7e7e837af ("net: Remove the now unused vrf_ptr") Cc: David Ahern Signed-off-by: Cong Wang Acked-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 64f2ab663ffe..474396353e7f 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -672,7 +672,7 @@ static int vrf_device_event(struct notifier_block *unused, if (event == NETDEV_UNREGISTER) { struct net_device *vrf_dev; - if (netif_is_l3_master(dev)) + if (!vrf_is_slave(dev) || netif_is_l3_master(dev)) goto out; vrf_dev = netdev_master_upper_dev_get(dev); -- cgit v1.2.3 From 7b0378f517fa1a32b5c8384248d2f8bf79c7c2ae Mon Sep 17 00:00:00 2001 From: Dean Jenkins Date: Fri, 2 Oct 2015 14:29:04 +0100 Subject: asix: Rename remaining and size for clarity The Data header synchronisation is easier to understand if the variables "remaining" and "size" are renamed. Therefore, the lifetime of the "remaining" variable exists outside of asix_rx_fixup_internal() and is used to indicate any remaining pending bytes of the Ethernet frame that need to be obtained from the next socket buffer. This allows an Ethernet frame to span across multiple socket buffers. "size" is now local to asix_rx_fixup_internal() and contains the size read from the Data header 32-bit word. Add "copy_length" to hold the number of the Ethernet frame bytes (maybe a part of a full frame) that are to be copied out of the socket buffer. Signed-off-by: Dean Jenkins Signed-off-by: Mark Craske Signed-off-by: David S. Miller --- drivers/net/usb/asix.h | 2 +- drivers/net/usb/asix_common.c | 41 +++++++++++++++++++++-------------------- 2 files changed, 22 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/asix.h b/drivers/net/usb/asix.h index 5d049d00c2d7..a2d3ea6efb20 100644 --- a/drivers/net/usb/asix.h +++ b/drivers/net/usb/asix.h @@ -168,7 +168,7 @@ struct asix_data { struct asix_rx_fixup_info { struct sk_buff *ax_skb; u32 header; - u16 size; + u16 remaining; bool split_head; }; diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 75d6f26729a3..2bd5bdda8c2e 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -54,12 +54,13 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, struct asix_rx_fixup_info *rx) { int offset = 0; + u16 size; while (offset + sizeof(u16) <= skb->len) { - u16 remaining = 0; + u16 copy_length; unsigned char *data; - if (!rx->size) { + if (!rx->remaining) { if ((skb->len - offset == sizeof(u16)) || rx->split_head) { if(!rx->split_head) { @@ -81,42 +82,42 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, offset += sizeof(u32); } - /* get the packet length */ - rx->size = (u16) (rx->header & 0x7ff); - if (rx->size != ((~rx->header >> 16) & 0x7ff)) { + /* take frame length from Data header 32-bit word */ + size = (u16)(rx->header & 0x7ff); + if (size != ((~rx->header >> 16) & 0x7ff)) { netdev_err(dev->net, "asix_rx_fixup() Bad Header Length 0x%x, offset %d\n", rx->header, offset); - rx->size = 0; return 0; } - rx->ax_skb = netdev_alloc_skb_ip_align(dev->net, - rx->size); + rx->ax_skb = netdev_alloc_skb_ip_align(dev->net, size); if (!rx->ax_skb) return 0; + rx->remaining = size; } - if (rx->size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) { + if (rx->remaining > dev->net->mtu + ETH_HLEN + VLAN_HLEN) { netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", - rx->size); + rx->remaining); kfree_skb(rx->ax_skb); rx->ax_skb = NULL; - rx->size = 0U; - + rx->remaining = 0; return 0; } - if (rx->size > skb->len - offset) { - remaining = rx->size - (skb->len - offset); - rx->size = skb->len - offset; + if (rx->remaining > skb->len - offset) { + copy_length = skb->len - offset; + rx->remaining -= copy_length; + } else { + copy_length = rx->remaining; + rx->remaining = 0; } - data = skb_put(rx->ax_skb, rx->size); - memcpy(data, skb->data + offset, rx->size); - if (!remaining) + data = skb_put(rx->ax_skb, copy_length); + memcpy(data, skb->data + offset, copy_length); + if (!rx->remaining) usbnet_skb_return(dev, rx->ax_skb); - offset += (rx->size + 1) & 0xfffe; - rx->size = remaining; + offset += (copy_length + 1) & 0xfffe; } if (skb->len != offset) { -- cgit v1.2.3 From 3bfc69abf802f56901ffd83bb66b7dd7644ddcc3 Mon Sep 17 00:00:00 2001 From: Dean Jenkins Date: Fri, 2 Oct 2015 14:29:05 +0100 Subject: asix: Tidy-up 32-bit header word synchronisation Tidy-up the Data header 32-bit word synchronisation logic in asix_rx_fixup_internal() by removing redundant logic tests. The code is looking at the following cases of the Data header 32-bit word that is present before each Ethernet frame: a) all 32 bits of the Data header word are in the URB socket buffer b) first 16 bits of the Data header word are at the end of the URB socket buffer c) last 16 bits of the Data header word are at the start of the URB socket buffer eg. split_head = true Note that the lifetime of rx->split_head exists outside of the function call and is accessed per processing of each URB. Therefore, split_head being true acts on the next URB to be processed. To check for b) the offset will be 16 bits (2 bytes) from the end of the buffer then indicate split_head is true. To check for c) split_head must be true because the first 16 bits have been found. To check for a) else c) Note that the || logic of the old code included the state (skb->len - offset == sizeof(u16) && rx->split_head) which is not possible because the split_head cannot be true whilst checking for b). This is because the split_head indicates that the first 16 bits have been found and that is not possible whilst checking for the first 16 bits. Therefore simplify the logic. Signed-off-by: Dean Jenkins Signed-off-by: Mark Craske Signed-off-by: David S. Miller --- drivers/net/usb/asix_common.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 2bd5bdda8c2e..89efd6ad9644 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -61,21 +61,19 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, unsigned char *data; if (!rx->remaining) { - if ((skb->len - offset == sizeof(u16)) || - rx->split_head) { - if(!rx->split_head) { - rx->header = get_unaligned_le16( - skb->data + offset); - rx->split_head = true; - offset += sizeof(u16); - break; - } else { - rx->header |= (get_unaligned_le16( - skb->data + offset) - << 16); - rx->split_head = false; - offset += sizeof(u16); - } + if (skb->len - offset == sizeof(u16)) { + rx->header = get_unaligned_le16( + skb->data + offset); + rx->split_head = true; + offset += sizeof(u16); + break; + } + + if (rx->split_head == true) { + rx->header |= (get_unaligned_le16( + skb->data + offset) << 16); + rx->split_head = false; + offset += sizeof(u16); } else { rx->header = get_unaligned_le32(skb->data + offset); -- cgit v1.2.3 From 9a5ccd8e039eef53336e45d01c7d8a1acbd36b47 Mon Sep 17 00:00:00 2001 From: Dean Jenkins Date: Fri, 2 Oct 2015 14:29:06 +0100 Subject: asix: Simplify asix_rx_fixup_internal() netdev alloc The code is checking that the Ethernet frame will fit into a netdev allocated socket buffer within the constraints of MTU size, Ethernet header length plus VLAN header length. The original code was checking rx->remaining each loop of the while loop that processes multiple Ethernet frames per URB and/or Ethernet frames that span across URBs. rx->remaining decreases per while loop so there is no point in potentially checking multiple times that the Ethernet frame (remaining part) will fit into the netdev socket buffer. The modification checks that the size of the Ethernet frame will fit the netdev socket buffer before allocating the netdev socket buffer. This avoids grabbing memory and then deciding that the Ethernet frame is too big and then freeing the memory. Signed-off-by: Dean Jenkins Signed-off-by: Mark Craske Signed-off-by: David S. Miller --- drivers/net/usb/asix_common.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 89efd6ad9644..6a8eddfea229 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -87,19 +87,17 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, rx->header, offset); return 0; } + if (size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) { + netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", + size); + return 0; + } + rx->ax_skb = netdev_alloc_skb_ip_align(dev->net, size); if (!rx->ax_skb) return 0; - rx->remaining = size; - } - if (rx->remaining > dev->net->mtu + ETH_HLEN + VLAN_HLEN) { - netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", - rx->remaining); - kfree_skb(rx->ax_skb); - rx->ax_skb = NULL; - rx->remaining = 0; - return 0; + rx->remaining = size; } if (rx->remaining > skb->len - offset) { -- cgit v1.2.3 From 3f30b158eba5c604b6e0870027eef5d19fc9271d Mon Sep 17 00:00:00 2001 From: Dean Jenkins Date: Fri, 2 Oct 2015 14:29:07 +0100 Subject: asix: On RX avoid creating bad Ethernet frames When RX Ethernet frames span multiple URB socket buffers, the data stream may suffer a discontinuity which will cause the current Ethernet frame in the netdev socket buffer to be incomplete. This frame needs to be discarded instead of appending unrelated data from the current URB socket buffer to the Ethernet frame in the netdev socket buffer. This avoids creating a corrupted Ethernet frame in the netdev socket buffer. A discontinuity can occur when the previous URB socket buffer held an incomplete Ethernet frame due to truncation or a URB socket buffer containing the end of the Ethernet frame was missing. Therefore, add a sanity test for when an Ethernet frame spans multiple URB socket buffers to check that the remaining bytes of the currently received Ethernet frame point to a good Data header 32-bit word of the next Ethernet frame. Upon error, reset the remaining bytes variable to zero and discard the current netdev socket buffer. Assume that the Data header is located at the start of the current socket buffer and attempt to process the next Ethernet frame from there. This avoids unnecessarily discarding a good URB socket buffer that contains a new Ethernet frame. Signed-off-by: Dean Jenkins Signed-off-by: Mark Craske Signed-off-by: David S. Miller --- drivers/net/usb/asix_common.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 6a8eddfea229..1e4768debcc9 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -56,6 +56,34 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, int offset = 0; u16 size; + /* When an Ethernet frame spans multiple URB socket buffers, + * do a sanity test for the Data header synchronisation. + * Attempt to detect the situation of the previous socket buffer having + * been truncated or a socket buffer was missing. These situations + * cause a discontinuity in the data stream and therefore need to avoid + * appending bad data to the end of the current netdev socket buffer. + * Also avoid unnecessarily discarding a good current netdev socket + * buffer. + */ + if (rx->remaining && (rx->remaining + sizeof(u32) <= skb->len)) { + offset = ((rx->remaining + 1) & 0xfffe) + sizeof(u32); + rx->header = get_unaligned_le32(skb->data + offset); + offset = 0; + + size = (u16)(rx->header & 0x7ff); + if (size != ((~rx->header >> 16) & 0x7ff)) { + netdev_err(dev->net, "asix_rx_fixup() Data Header synchronisation was lost, remaining %d\n", + rx->remaining); + kfree_skb(rx->ax_skb); + rx->ax_skb = NULL; + /* Discard the incomplete netdev Ethernet frame and + * assume the Data header is at the start of the current + * URB socket buffer. + */ + rx->remaining = 0; + } + } + while (offset + sizeof(u16) <= skb->len) { u16 copy_length; unsigned char *data; -- cgit v1.2.3 From 6a570814cd430fa5ef4f278e8046dcf12ee63f13 Mon Sep 17 00:00:00 2001 From: Dean Jenkins Date: Fri, 2 Oct 2015 14:29:08 +0100 Subject: asix: Continue processing URB if no RX netdev buffer Avoid a loss of synchronisation of the Ethernet Data header 32-bit word due to a failure to get a netdev socket buffer. The ASIX RX handling algorithm returned 0 upon a failure to get an allocation of a netdev socket buffer. This causes the URB processing to stop which potentially causes a loss of synchronisation with the Ethernet Data header 32-bit word. Therefore, subsequent processing of URBs may be rejected due to a loss of synchronisation. This may cause additional good Ethernet frames to be discarded along with outputting of synchronisation error messages. Implement a solution which checks whether a netdev socket buffer has been allocated before trying to copy the Ethernet frame into the netdev socket buffer. But continue to process the URB so that synchronisation is maintained. Therefore, only a single Ethernet frame is discarded when no netdev socket buffer is available. Signed-off-by: Dean Jenkins Signed-off-by: Mark Craske Signed-off-by: David S. Miller --- drivers/net/usb/asix_common.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index 1e4768debcc9..a186b0a12d50 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -74,12 +74,14 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, if (size != ((~rx->header >> 16) & 0x7ff)) { netdev_err(dev->net, "asix_rx_fixup() Data Header synchronisation was lost, remaining %d\n", rx->remaining); - kfree_skb(rx->ax_skb); - rx->ax_skb = NULL; - /* Discard the incomplete netdev Ethernet frame and - * assume the Data header is at the start of the current - * URB socket buffer. - */ + if (rx->ax_skb) { + kfree_skb(rx->ax_skb); + rx->ax_skb = NULL; + /* Discard the incomplete netdev Ethernet frame + * and assume the Data header is at the start of + * the current URB socket buffer. + */ + } rx->remaining = 0; } } @@ -121,9 +123,12 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, return 0; } + /* Sometimes may fail to get a netdev socket buffer but + * continue to process the URB socket buffer so that + * synchronisation of the Ethernet frame Data header + * word is maintained. + */ rx->ax_skb = netdev_alloc_skb_ip_align(dev->net, size); - if (!rx->ax_skb) - return 0; rx->remaining = size; } @@ -136,10 +141,12 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb, rx->remaining = 0; } - data = skb_put(rx->ax_skb, copy_length); - memcpy(data, skb->data + offset, copy_length); - if (!rx->remaining) - usbnet_skb_return(dev, rx->ax_skb); + if (rx->ax_skb) { + data = skb_put(rx->ax_skb, copy_length); + memcpy(data, skb->data + offset, copy_length); + if (!rx->remaining) + usbnet_skb_return(dev, rx->ax_skb); + } offset += (copy_length + 1) & 0xfffe; } -- cgit v1.2.3 From 855591d2f7d1ff7eb18b60ce2be494e3bfe27fb8 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Mon, 5 Oct 2015 10:51:03 -0500 Subject: amd-xgbe: Check for successful buffer allocation before use The kasprintf function can return NULL if the allocation fails. Check for successful allocation before attempting to use the returned buffer. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c index 66137ffea3f8..96f485ab612e 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c @@ -327,6 +327,9 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata) pdata->debugfs_xpcs_reg = 0; buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name); + if (!buf) + return; + pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL); if (!pdata->xgbe_debugfs) { netdev_err(pdata->netdev, "debugfs_create_dir failed\n"); -- cgit v1.2.3 From be62e92a5b2b5960b494fc81ce27611240016821 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 5 Oct 2015 17:56:34 +0300 Subject: ath10k: fix checkpatch warning about logical continuations checkpatch found: drivers/net/wireless/ath/ath9k/core.c:490: Logical continuations should be on the previous line Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 879625adc63a..87ad2e998a94 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -486,8 +486,8 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT, - ar->fw_features)) - && result != 0) { + ar->fw_features)) && + result != 0) { ath10k_err(ar, "otp calibration failed: %d", result); return -EINVAL; } -- cgit v1.2.3 From 617b0f4d4a69962e0e86604f889d6af9e8f4150d Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 5 Oct 2015 17:56:35 +0300 Subject: ath10k: indentation fixes checkpatch found: drivers/net/wireless/ath/ath10k/core.c:513: Alignment should match open parenthesis drivers/net/wireless/ath/ath10k/core.c:1266: code indent should use tabs where possible drivers/net/wireless/ath/ath10k/core.c:1267: code indent should use tabs where possible drivers/net/wireless/ath/ath10k/core.c:1268: code indent should use tabs where possible drivers/net/wireless/ath/ath10k/core.c:1269: code indent should use tabs where possible drivers/net/wireless/ath/ath10k/mac.c:4659: Alignment should match open parenthesis drivers/net/wireless/ath/ath10k/mac.c:6271: Alignment should match open parenthesis drivers/net/wireless/ath/ath10k/pci.c:2260: Alignment should match open parenthesis drivers/net/wireless/ath/ath10k/wmi.c:3510: Alignment should match open parenthesis Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 10 +++++----- drivers/net/wireless/ath/ath10k/mac.c | 6 +++--- drivers/net/wireless/ath/ath10k/pci.c | 2 +- drivers/net/wireless/ath/ath10k/wmi.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 87ad2e998a94..12fef599debe 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -510,7 +510,7 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) data_len = ar->firmware_len; mode_name = "normal"; ret = ath10k_swap_code_seg_configure(ar, - ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW); + ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW); if (ret) { ath10k_err(ar, "failed to configure fw code swap: %d\n", ret); @@ -1263,10 +1263,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) goto err; /* Some of of qca988x solutions are having global reset issue - * during target initialization. Bypassing PLL setting before - * downloading firmware and letting the SoC run on REF_CLK is - * fixing the problem. Corresponding firmware change is also needed - * to set the clock source once the target is initialized. + * during target initialization. Bypassing PLL setting before + * downloading firmware and letting the SoC run on REF_CLK is + * fixing the problem. Corresponding firmware change is also needed + * to set the clock source once the target is initialized. */ if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT, ar->fw_features)) { diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 3f6c1c42a70f..3106e3bfa515 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4656,7 +4656,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, info->use_cts_prot ? 1 : 0); if (ret) ath10k_warn(ar, "failed to set protection mode %d on vdev %i: %d\n", - info->use_cts_prot, arvif->vdev_id, ret); + info->use_cts_prot, arvif->vdev_id, ret); } if (changed & BSS_CHANGED_ERP_SLOT) { @@ -6268,8 +6268,8 @@ ath10k_mac_update_rx_channel(struct ath10k *ar, rcu_read_lock(); if (!ctx && ath10k_mac_num_chanctxs(ar) == 1) { ieee80211_iter_chan_contexts_atomic(ar->hw, - ath10k_mac_get_any_chandef_iter, - &def); + ath10k_mac_get_any_chandef_iter, + &def); if (vifs) def = &vifs[0].new_ctx->def; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 110fcad609b9..08cc4304001e 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -2257,7 +2257,7 @@ static int ath10k_pci_qca6174_chip_reset(struct ath10k *ar) ret = ath10k_pci_wait_for_target_init(ar); if (ret) { ath10k_warn(ar, "failed to wait for target after cold reset: %d\n", - ret); + ret); return ret; } diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 87d9de2aa8c5..0c7a233a223c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3507,7 +3507,7 @@ void ath10k_wmi_event_spectral_scan(struct ath10k *ar, tsf); if (res < 0) { ath10k_dbg(ar, ATH10K_DBG_WMI, "failed to process fft report: %d\n", - res); + res); return; } break; -- cgit v1.2.3 From b9e284e515af75e72043bb802cfb52cd9bd04450 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 5 Oct 2015 17:56:35 +0300 Subject: ath10k: brace style fixes drivers/net/wireless/ath/ath10k/htt_tx.c:457: braces {} are not necessary for single statement blocks drivers/net/wireless/ath/ath10k/htt_tx.c:545: braces {} are not necessary for single statement blocks drivers/net/wireless/ath/ath10k/mac.c:200: braces {} are not necessary for single statement blocks Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_tx.c | 8 ++++---- drivers/net/wireless/ath/ath10k/mac.c | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index eb5ba9bb8b4d..a31d508fc397 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -454,9 +454,9 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) spin_lock_bh(&htt->tx_lock); res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); spin_unlock_bh(&htt->tx_lock); - if (res < 0) { + if (res < 0) goto err_tx_dec; - } + msdu_id = res; txdesc = ath10k_htc_alloc_skb(ar, len); @@ -542,9 +542,9 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) spin_lock_bh(&htt->tx_lock); res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); spin_unlock_bh(&htt->tx_lock); - if (res < 0) { + if (res < 0) goto err_tx_dec; - } + msdu_id = res; prefetch_len = min(htt->prefetch_len, msdu->len); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 3106e3bfa515..cde0af81b6e7 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -197,9 +197,8 @@ static int ath10k_send_key(struct ath10k_vif *arvif, return -EOPNOTSUPP; } - if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { + if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - } if (cmd == DISABLE_KEY) { arg.key_cipher = WMI_CIPHER_NONE; -- cgit v1.2.3 From 92438a2cdb5d152d152ca7c449b033c255b977b4 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 5 Oct 2015 17:56:36 +0300 Subject: ath10k: remove void function return statements drivers/net/wireless/ath/ath10k/wmi.c:3023: void function return statements are not generally useful Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 0c7a233a223c..186b363c8b35 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3018,8 +3018,6 @@ static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, memcpy(skb_put(bcn, arvif->u.ap.noa_len), arvif->u.ap.noa_data, arvif->u.ap.noa_len); - - return; } static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb, -- cgit v1.2.3 From 9a14969fa1674d2215d6d9f171ed323bd3ebb39d Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 5 Oct 2015 17:56:36 +0300 Subject: ath10k: fix whitespace usage checkpatch found: drivers/net/wireless/ath/ath10k/core.c:574: Blank lines aren't necessary before a close brace '}' drivers/net/wireless/ath/ath10k/mac.c:4067: Missing a blank line after declarations drivers/net/wireless/ath/ath10k/mac.c:4083: Missing a blank line after declarations drivers/net/wireless/ath/ath10k/mac.c:4084: spaces required around that '>>=' (ctx:WxV) drivers/net/wireless/ath/ath10k/pci.c:1507: Missing a blank line after declarations Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 1 - drivers/net/wireless/ath/ath10k/mac.c | 4 +++- drivers/net/wireless/ath/ath10k/pci.c | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 12fef599debe..c295c919568b 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -570,7 +570,6 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) ar->firmware_len = 0; ar->cal_file = NULL; - } static int ath10k_fetch_cal_file(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index cde0af81b6e7..185651db71c0 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4064,6 +4064,7 @@ static u32 get_nss_from_chainmask(u16 chain_mask) static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar) { int nsts = ar->vht_cap_info; + nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; @@ -4080,8 +4081,9 @@ static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar) static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar) { int sound_dim = ar->vht_cap_info; + sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; - sound_dim >>=IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; + sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; /* If the sounding dimension is not advertised by the firmware, * let's use a default value of 1 diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 08cc4304001e..61df93e2e1c9 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1504,6 +1504,7 @@ static void ath10k_pci_irq_enable(struct ath10k *ar) static int ath10k_pci_hif_start(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n"); ath10k_pci_irq_enable(ar); -- cgit v1.2.3 From 2a995088c5aec38db6ffbac96c404f75c7dd9d2c Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 5 Oct 2015 17:56:37 +0300 Subject: ath10k: split an unnecessary long line from checkpatch: drivers/net/wireless/ath/ath10k/mac.c:1113: line over 90 characters Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 185651db71c0..803a708f2298 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1110,7 +1110,8 @@ static int ath10k_monitor_recalc(struct ath10k *ar) ret = ath10k_monitor_stop(ar); if (ret) - ath10k_warn(ar, "failed to stop disallowed monitor: %d\n", ret); + ath10k_warn(ar, "failed to stop disallowed monitor: %d\n", + ret); /* not serious */ } -- cgit v1.2.3 From 3b8fc902e33e65dd859c0f974c0097b177eeb695 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Mon, 5 Oct 2015 17:56:37 +0300 Subject: ath10k: add a_sle32_to_cpu() Copy a_sle32_to_cpu() from ath6kl so that we can easily handle signed __le32 values. This is needed in struct wmi_pdev_tpc_config_event. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 3e5a1591f772..1e8f55d29d2c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -73,6 +73,25 @@ struct wmi_cmd_hdr { #define HTC_PROTOCOL_VERSION 0x0002 #define WMI_PROTOCOL_VERSION 0x0002 +/* + * There is no signed version of __le32, so for a temporary solution come + * up with our own version. The idea is from fs/ntfs/types.h. + * + * Use a_ prefix so that it doesn't conflict if we get proper support to + * linux/types.h. + */ +typedef __s32 __bitwise a_sle32; + +static inline a_sle32 a_cpu_to_sle32(s32 val) +{ + return (__force a_sle32)cpu_to_le32(val); +} + +static inline s32 a_sle32_to_cpu(a_sle32 val) +{ + return le32_to_cpu((__force __le32)val); +} + enum wmi_service { WMI_SERVICE_BEACON_OFFLOAD = 0, WMI_SERVICE_SCAN_OFFLOAD, @@ -3657,7 +3676,7 @@ struct wmi_pdev_tpc_config_event { __le32 phy_mode; __le32 twice_antenna_reduction; __le32 twice_max_rd_power; - s32 twice_antenna_gain; + a_sle32 twice_antenna_gain; __le32 power_limit; __le32 rate_max; __le32 num_tx_chain; -- cgit v1.2.3 From 295426669cd68efc84657e6ee426499cfb54346e Mon Sep 17 00:00:00 2001 From: Maharaja Kennadyrajan Date: Mon, 5 Oct 2015 17:56:38 +0300 Subject: ath10k: implement debugfs interface for Transmit Power Control stats The Transmit Power Control (TPC) dump will show the power control values for each rate which makes it easier to debug calibration problems. Example usage: # cat /sys/kernel/debug/ieee80211/phy0/ath10k/tpc_stats TPC config for channel 5180 mode 10 CTL = 0x10 Reg. Domain = 58 Antenna Gain = 1 Reg. Max Antenna Gain = 0 Power Limit = 34 Reg. Max Power = 34 Num tx chains = 3 Num supported rates = 155 **********CDD POWER TABLE******* No. Preamble Rate_code tpc_valu1 tpc_value2 tpc_value3 0 CCK 0x40 0 0 0 1 CCk 0x41 0 0 0 [...] 154 HTCUP 0x 0 24 0 0 **********STBC POWER TABLE****** No. Preamble Rate_code tpc_valu1 tpc_value2 tpc_value3 0 CCK 0x40 0 0 0 [...] 154 HTCUP 0x 0 24 24 0 **********TXBF POWER TABLE****** is used to dump the tx power control stats. Signed-off-by: Maharaja Kennadyrajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 29 ++++ drivers/net/wireless/ath/ath10k/debug.c | 233 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/debug.h | 8 + drivers/net/wireless/ath/ath10k/wmi-ops.h | 19 +++ drivers/net/wireless/ath/ath10k/wmi.c | 270 +++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/wmi.h | 15 ++ 6 files changed, 573 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 04e040a06cb1..002de7113e63 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -250,6 +250,30 @@ struct ath10k_fw_stats { struct list_head peers; }; +#define ATH10K_TPC_TABLE_TYPE_FLAG 1 +#define ATH10K_TPC_PREAM_TABLE_END 0xFFFF + +struct ath10k_tpc_table { + u32 pream_idx[WMI_TPC_RATE_MAX]; + u8 rate_code[WMI_TPC_RATE_MAX]; + char tpc_value[WMI_TPC_RATE_MAX][WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE]; +}; + +struct ath10k_tpc_stats { + u32 reg_domain; + u32 chan_freq; + u32 phy_mode; + u32 twice_antenna_reduction; + u32 twice_max_rd_power; + s32 twice_antenna_gain; + u32 power_limit; + u32 num_tx_chain; + u32 ctl; + u32 rate_max; + u8 flag[WMI_TPC_FLAG]; + struct ath10k_tpc_table tpc_table[WMI_TPC_FLAG]; +}; + struct ath10k_dfs_stats { u32 phy_errors; u32 pulses_total; @@ -378,6 +402,11 @@ struct ath10k_debug { struct ath10k_dfs_stats dfs_stats; struct ath_dfs_pool_stats dfs_pool_stats; + /* used for tpc-dump storage, protected by data-lock */ + struct ath10k_tpc_stats *tpc_stats; + + struct completion tpc_complete; + /* protected by conf_mutex */ u32 fw_dbglog_mask; u32 fw_dbglog_level; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index bf033f46f8aa..f316efdbd6c3 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -1843,6 +1843,233 @@ static const struct file_operations fops_nf_cal_period = { .llseek = default_llseek, }; +#define ATH10K_TPC_CONFIG_BUF_SIZE (1024 * 1024) + +static int ath10k_debug_tpc_stats_request(struct ath10k *ar) +{ + int ret; + unsigned long time_left; + + lockdep_assert_held(&ar->conf_mutex); + + reinit_completion(&ar->debug.tpc_complete); + + ret = ath10k_wmi_pdev_get_tpc_config(ar, WMI_TPC_CONFIG_PARAM); + if (ret) { + ath10k_warn(ar, "failed to request tpc config: %d\n", ret); + return ret; + } + + time_left = wait_for_completion_timeout(&ar->debug.tpc_complete, + 1 * HZ); + if (time_left == 0) + return -ETIMEDOUT; + + return 0; +} + +void ath10k_debug_tpc_stats_process(struct ath10k *ar, + struct ath10k_tpc_stats *tpc_stats) +{ + spin_lock_bh(&ar->data_lock); + + kfree(ar->debug.tpc_stats); + ar->debug.tpc_stats = tpc_stats; + complete(&ar->debug.tpc_complete); + + spin_unlock_bh(&ar->data_lock); +} + +static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats, + unsigned int j, char *buf, unsigned int *len) +{ + unsigned int i, buf_len; + static const char table_str[][5] = { "CDD", + "STBC", + "TXBF" }; + static const char pream_str[][6] = { "CCK", + "OFDM", + "HT20", + "HT40", + "VHT20", + "VHT40", + "VHT80", + "HTCUP" }; + + buf_len = ATH10K_TPC_CONFIG_BUF_SIZE; + *len += scnprintf(buf + *len, buf_len - *len, + "********************************\n"); + *len += scnprintf(buf + *len, buf_len - *len, + "******************* %s POWER TABLE ****************\n", + table_str[j]); + *len += scnprintf(buf + *len, buf_len - *len, + "********************************\n"); + *len += scnprintf(buf + *len, buf_len - *len, + "No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3\n"); + + for (i = 0; i < tpc_stats->rate_max; i++) { + *len += scnprintf(buf + *len, buf_len - *len, + "%8d %s 0x%2x %s\n", i, + pream_str[tpc_stats->tpc_table[j].pream_idx[i]], + tpc_stats->tpc_table[j].rate_code[i], + tpc_stats->tpc_table[j].tpc_value[i]); + } + + *len += scnprintf(buf + *len, buf_len - *len, + "***********************************\n"); +} + +static void ath10k_tpc_stats_fill(struct ath10k *ar, + struct ath10k_tpc_stats *tpc_stats, + char *buf) +{ + unsigned int len, j, buf_len; + + len = 0; + buf_len = ATH10K_TPC_CONFIG_BUF_SIZE; + + spin_lock_bh(&ar->data_lock); + + if (!tpc_stats) { + ath10k_warn(ar, "failed to get tpc stats\n"); + goto unlock; + } + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, + "*************************************\n"); + len += scnprintf(buf + len, buf_len - len, + "TPC config for channel %4d mode %d\n", + tpc_stats->chan_freq, + tpc_stats->phy_mode); + len += scnprintf(buf + len, buf_len - len, + "*************************************\n"); + len += scnprintf(buf + len, buf_len - len, + "CTL = 0x%2x Reg. Domain = %2d\n", + tpc_stats->ctl, + tpc_stats->reg_domain); + len += scnprintf(buf + len, buf_len - len, + "Antenna Gain = %2d Reg. Max Antenna Gain = %2d\n", + tpc_stats->twice_antenna_gain, + tpc_stats->twice_antenna_reduction); + len += scnprintf(buf + len, buf_len - len, + "Power Limit = %2d Reg. Max Power = %2d\n", + tpc_stats->power_limit, + tpc_stats->twice_max_rd_power / 2); + len += scnprintf(buf + len, buf_len - len, + "Num tx chains = %2d Num supported rates = %2d\n", + tpc_stats->num_tx_chain, + tpc_stats->rate_max); + + for (j = 0; j < tpc_stats->num_tx_chain ; j++) { + switch (j) { + case WMI_TPC_TABLE_TYPE_CDD: + if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) { + len += scnprintf(buf + len, buf_len - len, + "CDD not supported\n"); + break; + } + + ath10k_tpc_stats_print(tpc_stats, j, buf, &len); + break; + case WMI_TPC_TABLE_TYPE_STBC: + if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) { + len += scnprintf(buf + len, buf_len - len, + "STBC not supported\n"); + break; + } + + ath10k_tpc_stats_print(tpc_stats, j, buf, &len); + break; + case WMI_TPC_TABLE_TYPE_TXBF: + if (tpc_stats->flag[j] == ATH10K_TPC_TABLE_TYPE_FLAG) { + len += scnprintf(buf + len, buf_len - len, + "TXBF not supported\n***************************\n"); + break; + } + + ath10k_tpc_stats_print(tpc_stats, j, buf, &len); + break; + default: + len += scnprintf(buf + len, buf_len - len, + "Invalid Type\n"); + break; + } + } + +unlock: + spin_unlock_bh(&ar->data_lock); + + if (len >= buf_len) + buf[len - 1] = 0; + else + buf[len] = 0; +} + +static int ath10k_tpc_stats_open(struct inode *inode, struct file *file) +{ + struct ath10k *ar = inode->i_private; + void *buf = NULL; + int ret; + + mutex_lock(&ar->conf_mutex); + + if (ar->state != ATH10K_STATE_ON) { + ret = -ENETDOWN; + goto err_unlock; + } + + buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE); + if (!buf) { + ret = -ENOMEM; + goto err_unlock; + } + + ret = ath10k_debug_tpc_stats_request(ar); + if (ret) { + ath10k_warn(ar, "failed to request tpc config stats: %d\n", + ret); + goto err_free; + } + + ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf); + file->private_data = buf; + + mutex_unlock(&ar->conf_mutex); + return 0; + +err_free: + vfree(buf); + +err_unlock: + mutex_unlock(&ar->conf_mutex); + return ret; +} + +static int ath10k_tpc_stats_release(struct inode *inode, struct file *file) +{ + vfree(file->private_data); + + return 0; +} + +static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + const char *buf = file->private_data; + unsigned int len = strlen(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_tpc_stats = { + .open = ath10k_tpc_stats_open, + .release = ath10k_tpc_stats_release, + .read = ath10k_tpc_stats_read, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + int ath10k_debug_start(struct ath10k *ar) { int ret; @@ -2111,6 +2338,8 @@ void ath10k_debug_destroy(struct ath10k *ar) ar->debug.fw_crash_data = NULL; ath10k_debug_fw_stats_reset(ar); + + kfree(ar->debug.tpc_stats); } int ath10k_debug_register(struct ath10k *ar) @@ -2127,6 +2356,7 @@ int ath10k_debug_register(struct ath10k *ar) INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork, ath10k_debug_htt_stats_dwork); + init_completion(&ar->debug.tpc_complete); init_completion(&ar->debug.fw_stats_complete); debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar, @@ -2195,6 +2425,9 @@ int ath10k_debug_register(struct ath10k *ar) debugfs_create_file("quiet_period", S_IRUGO | S_IWUSR, ar->debug.debugfs_phy, ar, &fops_quiet_period); + debugfs_create_file("tpc_stats", S_IRUSR, + ar->debug.debugfs_phy, ar, &fops_tpc_stats); + return 0; } diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 53bd6a19eab6..b07639e9b082 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -70,6 +70,8 @@ void ath10k_debug_destroy(struct ath10k *ar); int ath10k_debug_register(struct ath10k *ar); void ath10k_debug_unregister(struct ath10k *ar); void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb); +void ath10k_debug_tpc_stats_process(struct ath10k *ar, + struct ath10k_tpc_stats *tpc_stats); struct ath10k_fw_crash_data * ath10k_debug_get_new_fw_crash_data(struct ath10k *ar); @@ -117,6 +119,12 @@ static inline void ath10k_debug_fw_stats_process(struct ath10k *ar, { } +static inline void ath10k_debug_tpc_stats_process(struct ath10k *ar, + struct ath10k_tpc_stats *tpc_stats) +{ + kfree(tpc_stats); +} + static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len) { diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index 248ffc3d6620..d3bc6df861e4 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -177,6 +177,8 @@ struct wmi_ops { const struct wmi_tdls_peer_capab_arg *cap, const struct wmi_channel_arg *chan); struct sk_buff *(*gen_adaptive_qcs)(struct ath10k *ar, bool enable); + struct sk_buff *(*gen_pdev_get_tpc_config)(struct ath10k *ar, + u32 param); }; int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); @@ -1270,4 +1272,21 @@ ath10k_wmi_adaptive_qcs(struct ath10k *ar, bool enable) return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->adaptive_qcs_cmdid); } +static inline int +ath10k_wmi_pdev_get_tpc_config(struct ath10k *ar, u32 param) +{ + struct sk_buff *skb; + + if (!ar->wmi.ops->gen_pdev_get_tpc_config) + return -EOPNOTSUPP; + + skb = ar->wmi.ops->gen_pdev_get_tpc_config(ar, param); + + if (IS_ERR(skb)) + return PTR_ERR(skb); + + return ath10k_wmi_cmd_send(ar, skb, + ar->wmi.cmd->pdev_get_tpc_config_cmdid); +} + #endif diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 186b363c8b35..3eca5ffe9cdd 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3833,9 +3833,258 @@ void ath10k_wmi_event_dcs_interference(struct ath10k *ar, struct sk_buff *skb) ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_DCS_INTERFERENCE_EVENTID\n"); } +static u8 ath10k_tpc_config_get_rate(struct ath10k *ar, + struct wmi_pdev_tpc_config_event *ev, + u32 rate_idx, u32 num_chains, + u32 rate_code, u8 type) +{ + u8 tpc, num_streams, preamble, ch, stm_idx; + + num_streams = ATH10K_HW_NSS(rate_code); + preamble = ATH10K_HW_PREAMBLE(rate_code); + ch = num_chains - 1; + + tpc = min_t(u8, ev->rates_array[rate_idx], ev->max_reg_allow_pow[ch]); + + if (__le32_to_cpu(ev->num_tx_chain) <= 1) + goto out; + + if (preamble == WMI_RATE_PREAMBLE_CCK) + goto out; + + stm_idx = num_streams - 1; + if (num_chains <= num_streams) + goto out; + + switch (type) { + case WMI_TPC_TABLE_TYPE_STBC: + tpc = min_t(u8, tpc, + ev->max_reg_allow_pow_agstbc[ch - 1][stm_idx]); + break; + case WMI_TPC_TABLE_TYPE_TXBF: + tpc = min_t(u8, tpc, + ev->max_reg_allow_pow_agtxbf[ch - 1][stm_idx]); + break; + case WMI_TPC_TABLE_TYPE_CDD: + tpc = min_t(u8, tpc, + ev->max_reg_allow_pow_agcdd[ch - 1][stm_idx]); + break; + default: + ath10k_warn(ar, "unknown wmi tpc table type: %d\n", type); + tpc = 0; + break; + } + +out: + return tpc; +} + +static void ath10k_tpc_config_disp_tables(struct ath10k *ar, + struct wmi_pdev_tpc_config_event *ev, + struct ath10k_tpc_stats *tpc_stats, + u8 *rate_code, u16 *pream_table, u8 type) +{ + u32 i, j, pream_idx, flags; + u8 tpc[WMI_TPC_TX_N_CHAIN]; + char tpc_value[WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE]; + char buff[WMI_TPC_BUF_SIZE]; + + flags = __le32_to_cpu(ev->flags); + + switch (type) { + case WMI_TPC_TABLE_TYPE_CDD: + if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD)) { + ath10k_dbg(ar, ATH10K_DBG_WMI, "CDD not supported\n"); + tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG; + return; + } + break; + case WMI_TPC_TABLE_TYPE_STBC: + if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_STBC)) { + ath10k_dbg(ar, ATH10K_DBG_WMI, "STBC not supported\n"); + tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG; + return; + } + break; + case WMI_TPC_TABLE_TYPE_TXBF: + if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_TXBF)) { + ath10k_dbg(ar, ATH10K_DBG_WMI, "TXBF not supported\n"); + tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG; + return; + } + break; + default: + ath10k_dbg(ar, ATH10K_DBG_WMI, + "invalid table type in wmi tpc event: %d\n", type); + return; + } + + pream_idx = 0; + for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) { + memset(tpc_value, 0, sizeof(tpc_value)); + memset(buff, 0, sizeof(buff)); + if (i == pream_table[pream_idx]) + pream_idx++; + + for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) { + if (j >= __le32_to_cpu(ev->num_tx_chain)) + break; + + tpc[j] = ath10k_tpc_config_get_rate(ar, ev, i, j + 1, + rate_code[i], + type); + snprintf(buff, sizeof(buff), "%8d ", tpc[j]); + strncat(tpc_value, buff, strlen(buff)); + } + tpc_stats->tpc_table[type].pream_idx[i] = pream_idx; + tpc_stats->tpc_table[type].rate_code[i] = rate_code[i]; + memcpy(tpc_stats->tpc_table[type].tpc_value[i], + tpc_value, sizeof(tpc_value)); + } +} + void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) { - ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_TPC_CONFIG_EVENTID\n"); + u32 i, j, pream_idx, num_tx_chain; + u8 rate_code[WMI_TPC_RATE_MAX], rate_idx; + u16 pream_table[WMI_TPC_PREAM_TABLE_MAX]; + struct wmi_pdev_tpc_config_event *ev; + struct ath10k_tpc_stats *tpc_stats; + + ev = (struct wmi_pdev_tpc_config_event *)skb->data; + + tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC); + if (!tpc_stats) + return; + + /* Create the rate code table based on the chains supported */ + rate_idx = 0; + pream_idx = 0; + + /* Fill CCK rate code */ + for (i = 0; i < 4; i++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(i, 0, WMI_RATE_PREAMBLE_CCK); + rate_idx++; + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + /* Fill OFDM rate code */ + for (i = 0; i < 8; i++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(i, 0, WMI_RATE_PREAMBLE_OFDM); + rate_idx++; + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + num_tx_chain = __le32_to_cpu(ev->num_tx_chain); + + /* Fill HT20 rate code */ + for (i = 0; i < num_tx_chain; i++) { + for (j = 0; j < 8; j++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_HT); + rate_idx++; + } + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + /* Fill HT40 rate code */ + for (i = 0; i < num_tx_chain; i++) { + for (j = 0; j < 8; j++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_HT); + rate_idx++; + } + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + /* Fill VHT20 rate code */ + for (i = 0; i < __le32_to_cpu(ev->num_tx_chain); i++) { + for (j = 0; j < 10; j++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT); + rate_idx++; + } + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + /* Fill VHT40 rate code */ + for (i = 0; i < num_tx_chain; i++) { + for (j = 0; j < 10; j++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT); + rate_idx++; + } + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + /* Fill VHT80 rate code */ + for (i = 0; i < num_tx_chain; i++) { + for (j = 0; j < 10; j++) { + rate_code[rate_idx] = + ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT); + rate_idx++; + } + } + pream_table[pream_idx] = rate_idx; + pream_idx++; + + rate_code[rate_idx++] = + ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_CCK); + rate_code[rate_idx++] = + ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM); + rate_code[rate_idx++] = + ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_CCK); + rate_code[rate_idx++] = + ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM); + rate_code[rate_idx++] = + ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM); + + pream_table[pream_idx] = ATH10K_TPC_PREAM_TABLE_END; + + tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq); + tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode); + tpc_stats->ctl = __le32_to_cpu(ev->ctl); + tpc_stats->reg_domain = __le32_to_cpu(ev->reg_domain); + tpc_stats->twice_antenna_gain = a_sle32_to_cpu(ev->twice_antenna_gain); + tpc_stats->twice_antenna_reduction = + __le32_to_cpu(ev->twice_antenna_reduction); + tpc_stats->power_limit = __le32_to_cpu(ev->power_limit); + tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power); + tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain); + tpc_stats->rate_max = __le32_to_cpu(ev->rate_max); + + ath10k_tpc_config_disp_tables(ar, ev, tpc_stats, + rate_code, pream_table, + WMI_TPC_TABLE_TYPE_CDD); + ath10k_tpc_config_disp_tables(ar, ev, tpc_stats, + rate_code, pream_table, + WMI_TPC_TABLE_TYPE_STBC); + ath10k_tpc_config_disp_tables(ar, ev, tpc_stats, + rate_code, pream_table, + WMI_TPC_TABLE_TYPE_TXBF); + + ath10k_debug_tpc_stats_process(ar, tpc_stats); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi event tpc config channel %d mode %d ctl %d regd %d gain %d %d limit %d max_power %d tx_chanins %d rates %d\n", + __le32_to_cpu(ev->chan_freq), + __le32_to_cpu(ev->phy_mode), + __le32_to_cpu(ev->ctl), + __le32_to_cpu(ev->reg_domain), + a_sle32_to_cpu(ev->twice_antenna_gain), + __le32_to_cpu(ev->twice_antenna_reduction), + __le32_to_cpu(ev->power_limit), + __le32_to_cpu(ev->twice_max_rd_power) / 2, + __le32_to_cpu(ev->num_tx_chain), + __le32_to_cpu(ev->rate_max)); } void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb) @@ -6354,6 +6603,24 @@ ath10k_wmi_op_gen_delba_send(struct ath10k *ar, u32 vdev_id, const u8 *mac, return skb; } +static struct sk_buff * +ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config(struct ath10k *ar, u32 param) +{ + struct wmi_pdev_get_tpc_config_cmd *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); + if (!skb) + return ERR_PTR(-ENOMEM); + + cmd = (struct wmi_pdev_get_tpc_config_cmd *)skb->data; + cmd->param = __cpu_to_le32(param); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi pdev get tcp config param:%d\n", param); + return skb; +} + static const struct wmi_ops wmi_ops = { .rx = ath10k_wmi_op_rx, .map_svc = wmi_main_svc_map, @@ -6604,6 +6871,7 @@ static const struct wmi_ops wmi_10_2_4_ops = { .gen_addba_send = ath10k_wmi_op_gen_addba_send, .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 1e8f55d29d2c..4c373b27c1a6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -3661,8 +3661,18 @@ struct wmi_pdev_get_tpc_config_cmd { __le32 param; } __packed; +#define WMI_TPC_CONFIG_PARAM 1 #define WMI_TPC_RATE_MAX 160 #define WMI_TPC_TX_N_CHAIN 4 +#define WMI_TPC_PREAM_TABLE_MAX 10 +#define WMI_TPC_FLAG 3 +#define WMI_TPC_BUF_SIZE 10 + +enum wmi_tpc_table_type { + WMI_TPC_TABLE_TYPE_CDD = 0, + WMI_TPC_TABLE_TYPE_STBC = 1, + WMI_TPC_TABLE_TYPE_TXBF = 2, +}; enum wmi_tpc_config_event_flag { WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD = 0x1, @@ -4272,6 +4282,11 @@ enum wmi_rate_preamble { WMI_RATE_PREAMBLE_VHT, }; +#define ATH10K_HW_NSS(rate) (1 + (((rate) >> 4) & 0x3)) +#define ATH10K_HW_PREAMBLE(rate) (((rate) >> 6) & 0x3) +#define ATH10K_HW_RATECODE(rate, nss, preamble) \ + (((preamble) << 6) | ((nss) << 4) | (rate)) + /* Value to disable fixed rate setting */ #define WMI_FIXED_RATE_NONE (0xff) -- cgit v1.2.3 From bc27e8cddda69daa324318ffe3d2e1badad07775 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Mon, 5 Oct 2015 17:56:39 +0300 Subject: ath10k: use Rx decap mode configured when driver registered ath10k is using Native WiFi mode as default mode for both of Tx and Rx path, but it could be changed when driver registers with a module parameter for specific purpose such as mesh. The Rx decap mode sent to firmware during WMI initialization should use the same mode that driver configured at its registration stage in case of using raw mode, so that host driver receives MAC frame header containing necessary fields such as QoS and Mesh Control and uses them in right way to make data traffic work. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 3eca5ffe9cdd..063469b69d5f 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -5337,7 +5337,7 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar) config.rx_timeout_pri[2] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI); config.rx_timeout_pri[3] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_HI_PRI); - config.rx_decap_mode = __cpu_to_le32(TARGET_10_4_RX_DECAP_MODE); + config.rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode); config.scan_max_pending_req = __cpu_to_le32(TARGET_10_4_SCAN_MAX_REQS); config.bmiss_offload_max_vdev = __cpu_to_le32(TARGET_10_4_BMISS_OFFLOAD_MAX_VDEV); -- cgit v1.2.3 From 683b95e8071603b4e945cb26dcae0308457ec478 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Mon, 5 Oct 2015 17:56:40 +0300 Subject: ath10k: use pre-allocated DMA buffer in Tx ath10k driver is using dma_pool_alloc per packet and dma_pool_free in coresponding at Tx completion. Use of pre-allocated DMA buffer in Tx will improve saving CPU resource by 5% while it consumes about 56KB memory more as trade off. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 6 ++++- drivers/net/wireless/ath/ath10k/htt_tx.c | 43 +++++++++++++++++--------------- drivers/net/wireless/ath/ath10k/txrx.c | 5 ---- 3 files changed, 28 insertions(+), 26 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 5a8e4eae7a9c..db0a99b4e9d9 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1488,7 +1488,6 @@ struct ath10k_htt { int num_pending_mgmt_tx; struct idr pending_tx; wait_queue_head_t empty_tx_wq; - struct dma_pool *tx_pool; /* set if host-fw communication goes haywire * used to avoid further failures */ @@ -1509,6 +1508,11 @@ struct ath10k_htt { dma_addr_t paddr; struct htt_msdu_ext_desc *vaddr; } frag_desc; + + struct { + dma_addr_t paddr; + struct ath10k_htt_txbuf *vaddr; + } txbuf; }; #define RX_HTT_HDR_STATUS_LEN 64 diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index a31d508fc397..555174756eb1 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -108,9 +108,12 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) spin_lock_init(&htt->tx_lock); idr_init(&htt->pending_tx); - htt->tx_pool = dma_pool_create("ath10k htt tx pool", htt->ar->dev, - sizeof(struct ath10k_htt_txbuf), 4, 0); - if (!htt->tx_pool) { + size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf); + htt->txbuf.vaddr = dma_alloc_coherent(ar->dev, size, + &htt->txbuf.paddr, + GFP_DMA); + if (!htt->txbuf.vaddr) { + ath10k_err(ar, "failed to alloc tx buffer\n"); ret = -ENOMEM; goto free_idr_pending_tx; } @@ -125,14 +128,17 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) if (!htt->frag_desc.vaddr) { ath10k_warn(ar, "failed to alloc fragment desc memory\n"); ret = -ENOMEM; - goto free_tx_pool; + goto free_txbuf; } skip_frag_desc_alloc: return 0; -free_tx_pool: - dma_pool_destroy(htt->tx_pool); +free_txbuf: + size = htt->max_num_pending_tx * + sizeof(struct ath10k_htt_txbuf); + dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr, + htt->txbuf.paddr); free_idr_pending_tx: idr_destroy(&htt->pending_tx); return ret; @@ -160,7 +166,13 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt) idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); idr_destroy(&htt->pending_tx); - dma_pool_destroy(htt->tx_pool); + + if (htt->txbuf.vaddr) { + size = htt->max_num_pending_tx * + sizeof(struct ath10k_htt_txbuf); + dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr, + htt->txbuf.paddr); + } if (htt->frag_desc.vaddr) { size = htt->max_num_pending_tx * @@ -521,7 +533,6 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) int res; u8 flags0 = 0; u16 msdu_id, flags1 = 0; - dma_addr_t paddr = 0; u32 frags_paddr = 0; struct htt_msdu_ext_desc *ext_desc = NULL; bool limit_mgmt_desc = false; @@ -550,13 +561,9 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) prefetch_len = min(htt->prefetch_len, msdu->len); prefetch_len = roundup(prefetch_len, 4); - skb_cb->htt.txbuf = dma_pool_alloc(htt->tx_pool, GFP_ATOMIC, - &paddr); - if (!skb_cb->htt.txbuf) { - res = -ENOMEM; - goto err_free_msdu_id; - } - skb_cb->htt.txbuf_paddr = paddr; + skb_cb->htt.txbuf = &htt->txbuf.vaddr[msdu_id]; + skb_cb->htt.txbuf_paddr = htt->txbuf.paddr + + (sizeof(struct ath10k_htt_txbuf) * msdu_id); if ((ieee80211_is_action(hdr->frame_control) || ieee80211_is_deauth(hdr->frame_control) || @@ -574,7 +581,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) res = dma_mapping_error(dev, skb_cb->paddr); if (res) { res = -EIO; - goto err_free_txbuf; + goto err_free_msdu_id; } switch (skb_cb->txmode) { @@ -706,10 +713,6 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) err_unmap_msdu: dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); -err_free_txbuf: - dma_pool_free(htt->tx_pool, - skb_cb->htt.txbuf, - skb_cb->htt.txbuf_paddr); err_free_msdu_id: spin_lock_bh(&htt->tx_lock); ath10k_htt_tx_free_msdu_id(htt, msdu_id); diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index 7db7d501726b..6d1105ab4592 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c @@ -92,11 +92,6 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, skb_cb = ATH10K_SKB_CB(msdu); dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); - if (skb_cb->htt.txbuf) - dma_pool_free(htt->tx_pool, - skb_cb->htt.txbuf, - skb_cb->htt.txbuf_paddr); - ath10k_report_offchan_tx(htt->ar, msdu); info = IEEE80211_SKB_CB(msdu); -- cgit v1.2.3 From c664bc6d946d253077f3a5d5ca6769492de59e04 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 6 Oct 2015 06:25:29 -0700 Subject: Revert "net: encx24j600_exit() can be static" This reverts commit 9886ce2b9d4e5a8bb3d78d0f7eff3c0f1ed58d67. --- drivers/net/ethernet/microchip/encx24j600.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c index afc008a75c0f..1da37fddab42 100644 --- a/drivers/net/ethernet/microchip/encx24j600.c +++ b/drivers/net/ethernet/microchip/encx24j600.c @@ -1112,7 +1112,7 @@ static int __init encx24j600_init(void) } module_init(encx24j600_init); -static void encx24j600_exit(void) +void encx24j600_exit(void) { spi_unregister_driver(&encx24j600_spi_net_driver); } -- cgit v1.2.3 From 6a27a6c3be95d382cd158c5705c1840be291f28f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 6 Oct 2015 06:25:36 -0700 Subject: Revert "net: Microchip encx24j600 driver" This reverts commit 04fbfce7a222327b97ca165294ef19f0faa45960. --- drivers/net/ethernet/microchip/Kconfig | 9 - drivers/net/ethernet/microchip/Makefile | 1 - drivers/net/ethernet/microchip/encx24j600-regmap.c | 551 ---------- drivers/net/ethernet/microchip/encx24j600.c | 1124 -------------------- drivers/net/ethernet/microchip/encx24j600_hw.h | 437 -------- 5 files changed, 2122 deletions(-) delete mode 100644 drivers/net/ethernet/microchip/encx24j600-regmap.c delete mode 100644 drivers/net/ethernet/microchip/encx24j600.c delete mode 100644 drivers/net/ethernet/microchip/encx24j600_hw.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig index 992b01462a8f..3fd8ca6d4e7c 100644 --- a/drivers/net/ethernet/microchip/Kconfig +++ b/drivers/net/ethernet/microchip/Kconfig @@ -33,13 +33,4 @@ config ENC28J60_WRITEVERIFY Enable the verify after the buffer write useful for debugging purpose. If unsure, say N. -config ENCX24J600 - tristate "ENCX24J600 support" - depends on SPI - ---help--- - Support for the Microchip ENC424J600 ethernet chip. - - To compile this driver as a module, choose M here. The module will be - called enc424j600. - endif # NET_VENDOR_MICROCHIP diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile index ff78f621b59a..573d4292b9ea 100644 --- a/drivers/net/ethernet/microchip/Makefile +++ b/drivers/net/ethernet/microchip/Makefile @@ -3,4 +3,3 @@ # obj-$(CONFIG_ENC28J60) += enc28j60.o -obj-$(CONFIG_ENCX24J600) += encx24j600.o encx24j600-regmap.o diff --git a/drivers/net/ethernet/microchip/encx24j600-regmap.c b/drivers/net/ethernet/microchip/encx24j600-regmap.c deleted file mode 100644 index f1d74e300b24..000000000000 --- a/drivers/net/ethernet/microchip/encx24j600-regmap.c +++ /dev/null @@ -1,551 +0,0 @@ -/** - * Register map access API - ENCX24J600 support - * - * Copyright 2015 Gridpoint - * - * Author: Jon Ringle - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "encx24j600_hw.h" - -static inline bool is_bits_set(int value, int mask) -{ - return (value & mask) == mask; -} - -static int encx24j600_switch_bank(struct encx24j600_context *ctx, - int bank) -{ - int ret = 0; - - int bank_opcode = BANK_SELECT(bank); - ret = spi_write(ctx->spi, &bank_opcode, 1); - if (ret == 0) - ctx->bank = bank; - - return ret; -} - -static int encx24j600_cmdn(struct encx24j600_context *ctx, u8 opcode, - const void *buf, size_t len) -{ - struct spi_message m; - struct spi_transfer t[2] = { { .tx_buf = &opcode, .len = 1, }, - { .tx_buf = buf, .len = len }, }; - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - spi_message_add_tail(&t[1], &m); - - return spi_sync(ctx->spi, &m); -} - -static void regmap_lock_mutex(void *context) -{ - struct encx24j600_context *ctx = context; - mutex_lock(&ctx->mutex); -} - -static void regmap_unlock_mutex(void *context) -{ - struct encx24j600_context *ctx = context; - mutex_unlock(&ctx->mutex); -} - -static int regmap_encx24j600_sfr_read(void *context, u8 reg, u8 *val, - size_t len) -{ - struct encx24j600_context *ctx = context; - u8 banked_reg = reg & ADDR_MASK; - u8 bank = ((reg & BANK_MASK) >> BANK_SHIFT); - u8 cmd = RCRU; - int ret = 0; - int i = 0; - u8 tx_buf[2]; - - if (reg < 0x80) { - cmd = RCRCODE | banked_reg; - if ((banked_reg < 0x16) && (ctx->bank != bank)) - ret = encx24j600_switch_bank(ctx, bank); - if (unlikely(ret)) - return ret; - } else { - /* Translate registers that are more effecient using - * 3-byte SPI commands - */ - switch (reg) { - case EGPRDPT: - cmd = RGPRDPT; break; - case EGPWRPT: - cmd = RGPWRPT; break; - case ERXRDPT: - cmd = RRXRDPT; break; - case ERXWRPT: - cmd = RRXWRPT; break; - case EUDARDPT: - cmd = RUDARDPT; break; - case EUDAWRPT: - cmd = RUDAWRPT; break; - case EGPDATA: - case ERXDATA: - case EUDADATA: - default: - return -EINVAL; - } - } - - tx_buf[i++] = cmd; - if (cmd == RCRU) - tx_buf[i++] = reg; - - ret = spi_write_then_read(ctx->spi, tx_buf, i, val, len); - - return ret; -} - -static int regmap_encx24j600_sfr_update(struct encx24j600_context *ctx, - u8 reg, u8 *val, size_t len, - u8 unbanked_cmd, u8 banked_code) -{ - u8 banked_reg = reg & ADDR_MASK; - u8 bank = ((reg & BANK_MASK) >> BANK_SHIFT); - u8 cmd = unbanked_cmd; - struct spi_message m; - struct spi_transfer t[3] = { { .tx_buf = &cmd, .len = sizeof(cmd), }, - { .tx_buf = ®, .len = sizeof(reg), }, - { .tx_buf = val, .len = len }, }; - - if (reg < 0x80) { - int ret = 0; - cmd = banked_code | banked_reg; - if ((banked_reg < 0x16) && (ctx->bank != bank)) - ret = encx24j600_switch_bank(ctx, bank); - if (unlikely(ret)) - return ret; - } else { - /* Translate registers that are more effecient using - * 3-byte SPI commands - */ - switch (reg) { - case EGPRDPT: - cmd = WGPRDPT; break; - case EGPWRPT: - cmd = WGPWRPT; break; - case ERXRDPT: - cmd = WRXRDPT; break; - case ERXWRPT: - cmd = WRXWRPT; break; - case EUDARDPT: - cmd = WUDARDPT; break; - case EUDAWRPT: - cmd = WUDAWRPT; break; - case EGPDATA: - case ERXDATA: - case EUDADATA: - default: - return -EINVAL; - } - } - - spi_message_init(&m); - spi_message_add_tail(&t[0], &m); - - if (cmd == unbanked_cmd) { - t[1].tx_buf = ® - spi_message_add_tail(&t[1], &m); - } - - spi_message_add_tail(&t[2], &m); - return spi_sync(ctx->spi, &m); -} - -static int regmap_encx24j600_sfr_write(void *context, u8 reg, u8 *val, - size_t len) -{ - struct encx24j600_context *ctx = context; - return regmap_encx24j600_sfr_update(ctx, reg, val, len, WCRU, WCRCODE); -} - -static int regmap_encx24j600_sfr_set_bits(struct encx24j600_context *ctx, - u8 reg, u8 val) -{ - return regmap_encx24j600_sfr_update(ctx, reg, &val, 1, BFSU, BFSCODE); -} - -static int regmap_encx24j600_sfr_clr_bits(struct encx24j600_context *ctx, - u8 reg, u8 val) -{ - return regmap_encx24j600_sfr_update(ctx, reg, &val, 1, BFCU, BFCCODE); -} - -static int regmap_encx24j600_reg_update_bits(void *context, unsigned int reg, - unsigned int mask, - unsigned int val, bool *change, - bool force_write) -{ - struct encx24j600_context *ctx = context; - - int ret = 0; - unsigned int set_mask = mask & val; - unsigned int clr_mask = mask & ~val; - - if (change) - *change = false; - - if ((reg >= 0x40 && reg < 0x6c) || reg >= 0x80) { - /* Must do read/modify/write cycles for - * MAC/MII regs or Unbanked SFR regs - */ - u16 tmp, orig; - - ret = regmap_encx24j600_sfr_read(context, reg, (u8 *)&orig, - sizeof(orig)); - if (ret != 0) - return ret; - - tmp = orig & ~mask; - tmp |= val & mask; - - if (force_write || (tmp != orig)) { - ret = regmap_encx24j600_sfr_write(context, reg, - (u8 *)&tmp, - sizeof(tmp)); - if (change) - *change = true; - } else if (change) { - *change = false; - } - - return ret; - } - - if (set_mask & 0xff) { - ret = regmap_encx24j600_sfr_set_bits(ctx, reg, set_mask); - if (ret == 0 && change) - *change = true; - } - set_mask = (set_mask & 0xff00) >> 8; - - if ((set_mask & 0xff) && (ret == 0)) { - ret = regmap_encx24j600_sfr_set_bits(ctx, reg + 1, set_mask); - if (ret == 0 && change) - *change = true; - } - - if ((clr_mask & 0xff) && (ret == 0)) { - ret = regmap_encx24j600_sfr_clr_bits(ctx, reg, clr_mask); - if (ret == 0 && change) - *change = true; - } - clr_mask = (clr_mask & 0xff00) >> 8; - - if ((clr_mask & 0xff) && (ret == 0)) { - ret = regmap_encx24j600_sfr_clr_bits(ctx, reg + 1, clr_mask); - if (ret == 0 && change) - *change = true; - } - - return ret; -} - -int regmap_encx24j600_spi_write(void *context, u8 reg, const u8 *data, - size_t count) -{ - struct encx24j600_context *ctx = context; - - if (reg < 0xc0) - return encx24j600_cmdn(ctx, reg, data, count); - else - /* SPI 1-byte command. Ignore data */ - return spi_write(ctx->spi, ®, 1); -} -EXPORT_SYMBOL_GPL(regmap_encx24j600_spi_write); - -int regmap_encx24j600_spi_read(void *context, u8 reg, u8 *data, size_t count) -{ - struct encx24j600_context *ctx = context; - - if (reg == RBSEL && count > 1) - count = 1; - - return spi_write_then_read(ctx->spi, ®, sizeof(reg), data, count); -} -EXPORT_SYMBOL_GPL(regmap_encx24j600_spi_read); - -static int regmap_encx24j600_write(void *context, const void *data, - size_t len) -{ - u8 *dout = (u8 *)data; - u8 reg = dout[0]; - ++dout; - --len; - - if (reg > 0xa0) - return regmap_encx24j600_spi_write(context, reg, dout, len); - - if (len > 2) - return -EINVAL; - - return regmap_encx24j600_sfr_write(context, reg, dout, len); -} - -static int regmap_encx24j600_read(void *context, - const void *reg_buf, size_t reg_size, - void *val, size_t val_size) -{ - u8 reg = *(const u8 *)reg_buf; - - if (reg_size != 1) { - pr_err("%s: reg=%02x reg_size=%zu\n", __func__, reg, reg_size); - return -EINVAL; - } - - if (reg > 0xa0) - return regmap_encx24j600_spi_read(context, reg, val, val_size); - - if (val_size > 2) { - pr_err("%s: reg=%02x val_size=%zu\n", __func__, reg, val_size); - return -EINVAL; - } - - return regmap_encx24j600_sfr_read(context, reg, val, val_size); -} - -static bool encx24j600_regmap_readable(struct device *dev, unsigned int reg) -{ - if ((reg < 0x36) || - ((reg >= 0x40) && (reg < 0x4c)) || - ((reg >= 0x52) && (reg < 0x56)) || - ((reg >= 0x60) && (reg < 0x66)) || - ((reg >= 0x68) && (reg < 0x80)) || - ((reg >= 0x86) && (reg < 0x92)) || - (reg == 0xc8)) - return true; - else - return false; -} - -static bool encx24j600_regmap_writeable(struct device *dev, unsigned int reg) -{ - if ((reg < 0x12) || - ((reg >= 0x14) && (reg < 0x1a)) || - ((reg >= 0x1c) && (reg < 0x36)) || - ((reg >= 0x40) && (reg < 0x4c)) || - ((reg >= 0x52) && (reg < 0x56)) || - ((reg >= 0x60) && (reg < 0x68)) || - ((reg >= 0x6c) && (reg < 0x80)) || - ((reg >= 0x86) && (reg < 0x92)) || - ((reg >= 0xc0) && (reg < 0xc8)) || - ((reg >= 0xca) && (reg < 0xf0))) - return true; - else - return false; -} - -static bool encx24j600_regmap_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case ERXHEAD: - case EDMACS: - case ETXSTAT: - case ETXWIRE: - case ECON1: /* Can be modified via single byte cmds */ - case ECON2: /* Can be modified via single byte cmds */ - case ESTAT: - case EIR: /* Can be modified via single byte cmds */ - case MIRD: - case MISTAT: - return true; - default: - break; - } - - return false; -} - -static bool encx24j600_regmap_precious(struct device *dev, unsigned int reg) -{ - /* single byte cmds are precious */ - if (((reg >= 0xc0) && (reg < 0xc8)) || - ((reg >= 0xca) && (reg < 0xf0))) - return true; - else - return false; -} - -static int regmap_encx24j600_phy_reg_read(void *context, unsigned int reg, - unsigned int *val) -{ - struct encx24j600_context *ctx = context; - int ret; - unsigned int mistat; - - reg = MIREGADR_VAL | (reg & PHREG_MASK); - ret = regmap_write(ctx->regmap, MIREGADR, reg); - if (unlikely(ret)) - goto err_out; - - ret = regmap_write(ctx->regmap, MICMD, MIIRD); - if (unlikely(ret)) - goto err_out; - - usleep_range(26, 100); - while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) && - (mistat & BUSY)) - cpu_relax(); - - if (unlikely(ret)) - goto err_out; - - ret = regmap_write(ctx->regmap, MICMD, 0); - if (unlikely(ret)) - goto err_out; - - ret = regmap_read(ctx->regmap, MIRD, val); - -err_out: - if (ret) - pr_err("%s: error %d reading reg %02x\n", __func__, ret, - reg & PHREG_MASK); - - return ret; -} - -static int regmap_encx24j600_phy_reg_write(void *context, unsigned int reg, - unsigned int val) -{ - struct encx24j600_context *ctx = context; - int ret; - unsigned int mistat; - - reg = MIREGADR_VAL | (reg & PHREG_MASK); - ret = regmap_write(ctx->regmap, MIREGADR, reg); - if (unlikely(ret)) - goto err_out; - - ret = regmap_write(ctx->regmap, MIWR, val); - if (unlikely(ret)) - goto err_out; - - usleep_range(26, 100); - while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) && - (mistat & BUSY)) - cpu_relax(); - -err_out: - if (ret) - pr_err("%s: error %d writing reg %02x=%04x\n", __func__, ret, - reg & PHREG_MASK, val); - - return ret; -} - -static bool encx24j600_phymap_readable(struct device *dev, unsigned int reg) -{ - switch (reg) { - case PHCON1: - case PHSTAT1: - case PHANA: - case PHANLPA: - case PHANE: - case PHCON2: - case PHSTAT2: - case PHSTAT3: - return true; - default: - return false; - } -} - -static bool encx24j600_phymap_writeable(struct device *dev, unsigned int reg) -{ - switch (reg) { - case PHCON1: - case PHCON2: - case PHANA: - return true; - case PHSTAT1: - case PHSTAT2: - case PHSTAT3: - case PHANLPA: - case PHANE: - default: - return false; - } -} - -static bool encx24j600_phymap_volatile(struct device *dev, unsigned int reg) -{ - switch (reg) { - case PHSTAT1: - case PHSTAT2: - case PHSTAT3: - case PHANLPA: - case PHANE: - case PHCON2: - return true; - default: - return false; - } -} - -static struct regmap_config regcfg = { - .name = "reg", - .reg_bits = 8, - .val_bits = 16, - .max_register = 0xee, - .reg_stride = 2, - .cache_type = REGCACHE_RBTREE, - .val_format_endian = REGMAP_ENDIAN_LITTLE, - .readable_reg = encx24j600_regmap_readable, - .writeable_reg = encx24j600_regmap_writeable, - .volatile_reg = encx24j600_regmap_volatile, - .precious_reg = encx24j600_regmap_precious, - .lock = regmap_lock_mutex, - .unlock = regmap_unlock_mutex, -}; - -static struct regmap_bus regmap_encx24j600 = { - .write = regmap_encx24j600_write, - .read = regmap_encx24j600_read, - .reg_update_bits = regmap_encx24j600_reg_update_bits, -}; - -static struct regmap_config phycfg = { - .name = "phy", - .reg_bits = 8, - .val_bits = 16, - .max_register = 0x1f, - .cache_type = REGCACHE_RBTREE, - .val_format_endian = REGMAP_ENDIAN_LITTLE, - .readable_reg = encx24j600_phymap_readable, - .writeable_reg = encx24j600_phymap_writeable, - .volatile_reg = encx24j600_phymap_volatile, -}; -static struct regmap_bus phymap_encx24j600 = { - .reg_write = regmap_encx24j600_phy_reg_write, - .reg_read = regmap_encx24j600_phy_reg_read, -}; - -void devm_regmap_init_encx24j600(struct device *dev, - struct encx24j600_context *ctx) -{ - mutex_init(&ctx->mutex); - regcfg.lock_arg = ctx; - ctx->regmap = devm_regmap_init(dev, ®map_encx24j600, ctx, ®cfg); - ctx->phymap = devm_regmap_init(dev, &phymap_encx24j600, ctx, &phycfg); -} -EXPORT_SYMBOL_GPL(devm_regmap_init_encx24j600); - -MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c deleted file mode 100644 index 1da37fddab42..000000000000 --- a/drivers/net/ethernet/microchip/encx24j600.c +++ /dev/null @@ -1,1124 +0,0 @@ -/** - * Microchip ENCX24J600 ethernet driver - * - * Copyright (C) 2015 Gridpoint - * Author: Jon Ringle - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "encx24j600_hw.h" - -#define DRV_NAME "encx24j600" -#define DRV_VERSION "1.0" - -#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) -static int debug = -1; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); - -/* SRAM memory layout: - * - * 0x0000-0x05ff TX buffers 1.5KB (1*1536) reside in the GP area in SRAM - * 0x0600-0x5fff RX buffers 22.5KB (15*1536) reside in the RX area in SRAM - */ -#define ENC_TX_BUF_START 0x0000U -#define ENC_RX_BUF_START 0x0600U -#define ENC_RX_BUF_END 0x5fffU -#define ENC_SRAM_SIZE 0x6000U - -enum { - RXFILTER_NORMAL, - RXFILTER_MULTI, - RXFILTER_PROMISC -}; - -struct encx24j600_priv { - struct net_device *ndev; - struct mutex lock; /* device access lock */ - struct encx24j600_context ctx; - struct sk_buff *tx_skb; - struct task_struct *kworker_task; - struct kthread_worker kworker; - struct kthread_work tx_work; - struct kthread_work setrx_work; - u16 next_packet; - bool hw_enabled; - bool full_duplex; - bool autoneg; - u16 speed; - int rxfilter; - u32 msg_enable; -}; - -static void dump_packet(const char *msg, int len, const char *data) -{ - pr_debug(DRV_NAME ": %s - packet len:%d\n", msg, len); - print_hex_dump_bytes("pk data: ", DUMP_PREFIX_OFFSET, data, len); -} - -static void encx24j600_dump_rsv(struct encx24j600_priv *priv, const char *msg, - struct rsv *rsv) -{ - struct net_device *dev = priv->ndev; - - netdev_info(dev, "RX packet Len:%d\n", rsv->len); - netdev_dbg(dev, "%s - NextPk: 0x%04x\n", msg, - rsv->next_packet); - netdev_dbg(dev, "RxOK: %d, DribbleNibble: %d\n", - RSV_GETBIT(rsv->rxstat, RSV_RXOK), - RSV_GETBIT(rsv->rxstat, RSV_DRIBBLENIBBLE)); - netdev_dbg(dev, "CRCErr:%d, LenChkErr: %d, LenOutOfRange: %d\n", - RSV_GETBIT(rsv->rxstat, RSV_CRCERROR), - RSV_GETBIT(rsv->rxstat, RSV_LENCHECKERR), - RSV_GETBIT(rsv->rxstat, RSV_LENOUTOFRANGE)); - netdev_dbg(dev, "Multicast: %d, Broadcast: %d, LongDropEvent: %d, CarrierEvent: %d\n", - RSV_GETBIT(rsv->rxstat, RSV_RXMULTICAST), - RSV_GETBIT(rsv->rxstat, RSV_RXBROADCAST), - RSV_GETBIT(rsv->rxstat, RSV_RXLONGEVDROPEV), - RSV_GETBIT(rsv->rxstat, RSV_CARRIEREV)); - netdev_dbg(dev, "ControlFrame: %d, PauseFrame: %d, UnknownOp: %d, VLanTagFrame: %d\n", - RSV_GETBIT(rsv->rxstat, RSV_RXCONTROLFRAME), - RSV_GETBIT(rsv->rxstat, RSV_RXPAUSEFRAME), - RSV_GETBIT(rsv->rxstat, RSV_RXUNKNOWNOPCODE), - RSV_GETBIT(rsv->rxstat, RSV_RXTYPEVLAN)); -} - -static u16 encx24j600_read_reg(struct encx24j600_priv *priv, u8 reg) -{ - struct net_device *dev = priv->ndev; - unsigned int val = 0; - int ret = regmap_read(priv->ctx.regmap, reg, &val); - if (unlikely(ret)) - netif_err(priv, drv, dev, "%s: error %d reading reg %02x\n", - __func__, ret, reg); - return val; -} - -static void encx24j600_write_reg(struct encx24j600_priv *priv, u8 reg, u16 val) -{ - struct net_device *dev = priv->ndev; - int ret = regmap_write(priv->ctx.regmap, reg, val); - if (unlikely(ret)) - netif_err(priv, drv, dev, "%s: error %d writing reg %02x=%04x\n", - __func__, ret, reg, val); -} - -static void encx24j600_update_reg(struct encx24j600_priv *priv, u8 reg, - u16 mask, u16 val) -{ - struct net_device *dev = priv->ndev; - int ret = regmap_update_bits(priv->ctx.regmap, reg, mask, val); - if (unlikely(ret)) - netif_err(priv, drv, dev, "%s: error %d updating reg %02x=%04x~%04x\n", - __func__, ret, reg, val, mask); -} - -static u16 encx24j600_read_phy(struct encx24j600_priv *priv, u8 reg) -{ - struct net_device *dev = priv->ndev; - unsigned int val = 0; - int ret = regmap_read(priv->ctx.phymap, reg, &val); - if (unlikely(ret)) - netif_err(priv, drv, dev, "%s: error %d reading %02x\n", - __func__, ret, reg); - return val; -} - -static void encx24j600_write_phy(struct encx24j600_priv *priv, u8 reg, u16 val) -{ - struct net_device *dev = priv->ndev; - int ret = regmap_write(priv->ctx.phymap, reg, val); - if (unlikely(ret)) - netif_err(priv, drv, dev, "%s: error %d writing reg %02x=%04x\n", - __func__, ret, reg, val); -} - -static void encx24j600_clr_bits(struct encx24j600_priv *priv, u8 reg, u16 mask) -{ - encx24j600_update_reg(priv, reg, mask, 0); -} - -static void encx24j600_set_bits(struct encx24j600_priv *priv, u8 reg, u16 mask) -{ - encx24j600_update_reg(priv, reg, mask, mask); -} - -static void encx24j600_cmd(struct encx24j600_priv *priv, u8 cmd) -{ - struct net_device *dev = priv->ndev; - int ret = regmap_write(priv->ctx.regmap, cmd, 0); - if (unlikely(ret)) - netif_err(priv, drv, dev, "%s: error %d with cmd %02x\n", - __func__, ret, cmd); -} - -static int encx24j600_raw_read(struct encx24j600_priv *priv, u8 reg, u8 *data, - size_t count) -{ - int ret; - mutex_lock(&priv->ctx.mutex); - ret = regmap_encx24j600_spi_read(&priv->ctx, reg, data, count); - mutex_unlock(&priv->ctx.mutex); - - return ret; -} - -static int encx24j600_raw_write(struct encx24j600_priv *priv, u8 reg, - const u8 *data, size_t count) -{ - int ret; - mutex_lock(&priv->ctx.mutex); - ret = regmap_encx24j600_spi_write(&priv->ctx, reg, data, count); - mutex_unlock(&priv->ctx.mutex); - - return ret; -} - -static void encx24j600_update_phcon1(struct encx24j600_priv *priv) -{ - u16 phcon1 = encx24j600_read_phy(priv, PHCON1); - if (priv->autoneg == AUTONEG_ENABLE) { - phcon1 |= ANEN | RENEG; - } else { - phcon1 &= ~ANEN; - if (priv->speed == SPEED_100) - phcon1 |= SPD100; - else - phcon1 &= ~SPD100; - - if (priv->full_duplex) - phcon1 |= PFULDPX; - else - phcon1 &= ~PFULDPX; - } - encx24j600_write_phy(priv, PHCON1, phcon1); -} - -/* Waits for autonegotiation to complete. */ -static int encx24j600_wait_for_autoneg(struct encx24j600_priv *priv) -{ - struct net_device *dev = priv->ndev; - unsigned long timeout = jiffies + msecs_to_jiffies(2000); - u16 phstat1; - u16 estat; - int ret = 0; - - phstat1 = encx24j600_read_phy(priv, PHSTAT1); - while ((phstat1 & ANDONE) == 0) { - if (time_after(jiffies, timeout)) { - u16 phstat3; - - netif_notice(priv, drv, dev, "timeout waiting for autoneg done\n"); - - priv->autoneg = AUTONEG_DISABLE; - phstat3 = encx24j600_read_phy(priv, PHSTAT3); - priv->speed = (phstat3 & PHY3SPD100) - ? SPEED_100 : SPEED_10; - priv->full_duplex = (phstat3 & PHY3DPX) ? 1 : 0; - encx24j600_update_phcon1(priv); - netif_notice(priv, drv, dev, "Using parallel detection: %s/%s", - priv->speed == SPEED_100 ? "100" : "10", - priv->full_duplex ? "Full" : "Half"); - - return -ETIMEDOUT; - } - cpu_relax(); - phstat1 = encx24j600_read_phy(priv, PHSTAT1); - } - - estat = encx24j600_read_reg(priv, ESTAT); - if (estat & PHYDPX) { - encx24j600_set_bits(priv, MACON2, FULDPX); - encx24j600_write_reg(priv, MABBIPG, 0x15); - } else { - encx24j600_clr_bits(priv, MACON2, FULDPX); - encx24j600_write_reg(priv, MABBIPG, 0x12); - /* Max retransmittions attempt */ - encx24j600_write_reg(priv, MACLCON, 0x370f); - } - - return ret; -} - -/* Access the PHY to determine link status */ -static void encx24j600_check_link_status(struct encx24j600_priv *priv) -{ - struct net_device *dev = priv->ndev; - u16 estat; - - estat = encx24j600_read_reg(priv, ESTAT); - - if (estat & PHYLNK) { - if (priv->autoneg == AUTONEG_ENABLE) - encx24j600_wait_for_autoneg(priv); - - netif_carrier_on(dev); - netif_info(priv, ifup, dev, "link up\n"); - } else { - netif_info(priv, ifdown, dev, "link down\n"); - - /* Re-enable autoneg since we won't know what we might be - * connected to when the link is brought back up again. - */ - priv->autoneg = AUTONEG_ENABLE; - priv->full_duplex = true; - priv->speed = SPEED_100; - netif_carrier_off(dev); - } -} - -static void encx24j600_int_link_handler(struct encx24j600_priv *priv) -{ - struct net_device *dev = priv->ndev; - - netif_dbg(priv, intr, dev, "%s", __func__); - encx24j600_check_link_status(priv); - encx24j600_clr_bits(priv, EIR, LINKIF); -} - -static void encx24j600_tx_complete(struct encx24j600_priv *priv, bool err) -{ - struct net_device *dev = priv->ndev; - - mutex_lock(&priv->lock); - - if (err) - dev->stats.tx_errors++; - else - dev->stats.tx_packets++; - - dev->stats.tx_bytes += priv->tx_skb->len; - - encx24j600_clr_bits(priv, EIR, TXIF | TXABTIF); - - netif_dbg(priv, tx_done, dev, "TX Done%s\n", err ? ": Err" : ""); - - if (priv->tx_skb) { - dev_kfree_skb(priv->tx_skb); - priv->tx_skb = NULL; - } - - netif_wake_queue(dev); - - mutex_unlock(&priv->lock); -} - -static int encx24j600_receive_packet(struct encx24j600_priv *priv, - struct rsv *rsv) -{ - struct net_device *dev = priv->ndev; - struct sk_buff *skb = netdev_alloc_skb(dev, rsv->len + NET_IP_ALIGN); - if (!skb) { - pr_err_ratelimited("RX: OOM: packet dropped\n"); - dev->stats.rx_dropped++; - return -ENOMEM; - } - skb_reserve(skb, NET_IP_ALIGN); - encx24j600_raw_read(priv, RRXDATA, skb_put(skb, rsv->len), rsv->len); - - if (netif_msg_pktdata(priv)) - dump_packet("RX", skb->len, skb->data); - - skb->dev = dev; - skb->protocol = eth_type_trans(skb, dev); - skb->ip_summed = CHECKSUM_COMPLETE; - - /* Maintain stats */ - dev->stats.rx_packets++; - dev->stats.rx_bytes += rsv->len; - priv->next_packet = rsv->next_packet; - - netif_rx(skb); - - return 0; -} - -static void encx24j600_rx_packets(struct encx24j600_priv *priv, u8 packet_count) -{ - struct net_device *dev = priv->ndev; - - while (packet_count--) { - struct rsv rsv; - u16 newrxtail; - - encx24j600_write_reg(priv, ERXRDPT, priv->next_packet); - encx24j600_raw_read(priv, RRXDATA, (u8 *)&rsv, sizeof(rsv)); - - if (netif_msg_rx_status(priv)) - encx24j600_dump_rsv(priv, __func__, &rsv); - - if (!RSV_GETBIT(rsv.rxstat, RSV_RXOK) || - (rsv.len > MAX_FRAMELEN)) { - netif_err(priv, rx_err, dev, "RX Error %04x\n", - rsv.rxstat); - dev->stats.rx_errors++; - - if (RSV_GETBIT(rsv.rxstat, RSV_CRCERROR)) - dev->stats.rx_crc_errors++; - if (RSV_GETBIT(rsv.rxstat, RSV_LENCHECKERR)) - dev->stats.rx_frame_errors++; - if (rsv.len > MAX_FRAMELEN) - dev->stats.rx_over_errors++; - } else { - encx24j600_receive_packet(priv, &rsv); - } - - newrxtail = priv->next_packet - 2; - if (newrxtail == ENC_RX_BUF_START) - newrxtail = SRAM_SIZE - 2; - - encx24j600_cmd(priv, SETPKTDEC); - encx24j600_write_reg(priv, ERXTAIL, newrxtail); - } -} - -static irqreturn_t encx24j600_isr(int irq, void *dev_id) -{ - struct encx24j600_priv *priv = dev_id; - struct net_device *dev = priv->ndev; - int eir; - - /* Clear interrupts */ - encx24j600_cmd(priv, CLREIE); - - eir = encx24j600_read_reg(priv, EIR); - - if (eir & LINKIF) - encx24j600_int_link_handler(priv); - - if (eir & TXIF) - encx24j600_tx_complete(priv, false); - - if (eir & TXABTIF) - encx24j600_tx_complete(priv, true); - - if (eir & RXABTIF) { - if (eir & PCFULIF) { - /* Packet counter is full */ - netif_err(priv, rx_err, dev, "Packet counter full\n"); - } - dev->stats.rx_dropped++; - encx24j600_clr_bits(priv, EIR, RXABTIF); - } - - if (eir & PKTIF) { - u8 packet_count; - - mutex_lock(&priv->lock); - - packet_count = encx24j600_read_reg(priv, ESTAT) & 0xff; - while (packet_count) { - encx24j600_rx_packets(priv, packet_count); - packet_count = encx24j600_read_reg(priv, ESTAT) & 0xff; - } - - mutex_unlock(&priv->lock); - } - - /* Enable interrupts */ - encx24j600_cmd(priv, SETEIE); - - return IRQ_HANDLED; -} - -static int encx24j600_soft_reset(struct encx24j600_priv *priv) -{ - int ret = 0; - int timeout; - u16 eudast; - - /* Write and verify a test value to EUDAST */ - regcache_cache_bypass(priv->ctx.regmap, true); - timeout = 10; - do { - encx24j600_write_reg(priv, EUDAST, EUDAST_TEST_VAL); - eudast = encx24j600_read_reg(priv, EUDAST); - usleep_range(25, 100); - } while ((eudast != EUDAST_TEST_VAL) && --timeout); - regcache_cache_bypass(priv->ctx.regmap, false); - - if (timeout == 0) { - ret = -ETIMEDOUT; - goto err_out; - } - - /* Wait for CLKRDY to become set */ - timeout = 10; - while (!(encx24j600_read_reg(priv, ESTAT) & CLKRDY) && --timeout) - usleep_range(25, 100); - - if (timeout == 0) { - ret = -ETIMEDOUT; - goto err_out; - } - - /* Issue a System Reset command */ - encx24j600_cmd(priv, SETETHRST); - usleep_range(25, 100); - - /* Confirm that EUDAST has 0000h after system reset */ - if (encx24j600_read_reg(priv, EUDAST) != 0) { - ret = -EINVAL; - goto err_out; - } - - /* Wait for PHY register and status bits to become available */ - usleep_range(256, 1000); - -err_out: - return ret; -} - -static int encx24j600_hw_reset(struct encx24j600_priv *priv) -{ - int ret; - - mutex_lock(&priv->lock); - ret = encx24j600_soft_reset(priv); - mutex_unlock(&priv->lock); - - return ret; -} - -static void encx24j600_reset_hw_tx(struct encx24j600_priv *priv) -{ - encx24j600_set_bits(priv, ECON2, TXRST); - encx24j600_clr_bits(priv, ECON2, TXRST); -} - -static void encx24j600_hw_init_tx(struct encx24j600_priv *priv) -{ - /* Reset TX */ - encx24j600_reset_hw_tx(priv); - - /* Clear the TXIF flag if were previously set */ - encx24j600_clr_bits(priv, EIR, TXIF | TXABTIF); - - /* Write the Tx Buffer pointer */ - encx24j600_write_reg(priv, EGPWRPT, ENC_TX_BUF_START); -} - -static void encx24j600_hw_init_rx(struct encx24j600_priv *priv) -{ - encx24j600_cmd(priv, DISABLERX); - - /* Set up RX packet start address in the SRAM */ - encx24j600_write_reg(priv, ERXST, ENC_RX_BUF_START); - - /* Preload the RX Data pointer to the beginning of the RX area */ - encx24j600_write_reg(priv, ERXRDPT, ENC_RX_BUF_START); - - priv->next_packet = ENC_RX_BUF_START; - - /* Set up RX end address in the SRAM */ - encx24j600_write_reg(priv, ERXTAIL, ENC_SRAM_SIZE - 2); - - /* Reset the user data pointers */ - encx24j600_write_reg(priv, EUDAST, ENC_SRAM_SIZE); - encx24j600_write_reg(priv, EUDAND, ENC_SRAM_SIZE + 1); - - /* Set Max Frame length */ - encx24j600_write_reg(priv, MAMXFL, MAX_FRAMELEN); -} - -static void encx24j600_dump_config(struct encx24j600_priv *priv, - const char *msg) -{ - pr_info(DRV_NAME ": %s\n", msg); - - /* CHIP configuration */ - pr_info(DRV_NAME " ECON1: %04X\n", encx24j600_read_reg(priv, ECON1)); - pr_info(DRV_NAME " ECON2: %04X\n", encx24j600_read_reg(priv, ECON2)); - pr_info(DRV_NAME " ERXFCON: %04X\n", encx24j600_read_reg(priv, - ERXFCON)); - pr_info(DRV_NAME " ESTAT: %04X\n", encx24j600_read_reg(priv, ESTAT)); - pr_info(DRV_NAME " EIR: %04X\n", encx24j600_read_reg(priv, EIR)); - pr_info(DRV_NAME " EIDLED: %04X\n", encx24j600_read_reg(priv, EIDLED)); - - /* MAC layer configuration */ - pr_info(DRV_NAME " MACON1: %04X\n", encx24j600_read_reg(priv, MACON1)); - pr_info(DRV_NAME " MACON2: %04X\n", encx24j600_read_reg(priv, MACON2)); - pr_info(DRV_NAME " MAIPG: %04X\n", encx24j600_read_reg(priv, MAIPG)); - pr_info(DRV_NAME " MACLCON: %04X\n", encx24j600_read_reg(priv, - MACLCON)); - pr_info(DRV_NAME " MABBIPG: %04X\n", encx24j600_read_reg(priv, - MABBIPG)); - - /* PHY configuation */ - pr_info(DRV_NAME " PHCON1: %04X\n", encx24j600_read_phy(priv, PHCON1)); - pr_info(DRV_NAME " PHCON2: %04X\n", encx24j600_read_phy(priv, PHCON2)); - pr_info(DRV_NAME " PHANA: %04X\n", encx24j600_read_phy(priv, PHANA)); - pr_info(DRV_NAME " PHANLPA: %04X\n", encx24j600_read_phy(priv, - PHANLPA)); - pr_info(DRV_NAME " PHANE: %04X\n", encx24j600_read_phy(priv, PHANE)); - pr_info(DRV_NAME " PHSTAT1: %04X\n", encx24j600_read_phy(priv, - PHSTAT1)); - pr_info(DRV_NAME " PHSTAT2: %04X\n", encx24j600_read_phy(priv, - PHSTAT2)); - pr_info(DRV_NAME " PHSTAT3: %04X\n", encx24j600_read_phy(priv, - PHSTAT3)); -} - -static void encx24j600_set_rxfilter_mode(struct encx24j600_priv *priv) -{ - switch (priv->rxfilter) { - case RXFILTER_PROMISC: - encx24j600_set_bits(priv, MACON1, PASSALL); - encx24j600_write_reg(priv, ERXFCON, UCEN | MCEN | NOTMEEN); - break; - case RXFILTER_MULTI: - encx24j600_clr_bits(priv, MACON1, PASSALL); - encx24j600_write_reg(priv, ERXFCON, UCEN | CRCEN | BCEN | MCEN); - break; - case RXFILTER_NORMAL: - default: - encx24j600_clr_bits(priv, MACON1, PASSALL); - encx24j600_write_reg(priv, ERXFCON, UCEN | CRCEN | BCEN); - break; - } -} - -static int encx24j600_hw_init(struct encx24j600_priv *priv) -{ - struct net_device *dev = priv->ndev; - int ret = 0; - u16 eidled; - u16 macon2; - - priv->hw_enabled = false; - - eidled = encx24j600_read_reg(priv, EIDLED); - if (((eidled & DEVID_MASK) >> DEVID_SHIFT) != ENCX24J600_DEV_ID) { - ret = -EINVAL; - goto err_out; - } - - netif_info(priv, drv, dev, "Silicon rev ID: 0x%02x\n", - (eidled & REVID_MASK) >> REVID_SHIFT); - - /* PHY Leds: link status, - * LEDA: Link + transmit/receive events - * LEDB: Link State + colision events - */ - encx24j600_update_reg(priv, EIDLED, 0xbc00, 0xbc00); - - /* Loopback disabled */ - encx24j600_write_reg(priv, MACON1, 0x9); - - /* interpacket gap value */ - encx24j600_write_reg(priv, MAIPG, 0x0c12); - - /* Write the auto negotiation pattern */ - encx24j600_write_phy(priv, PHANA, PHANA_DEFAULT); - - encx24j600_update_phcon1(priv); - encx24j600_check_link_status(priv); - - macon2 = MACON2_RSV1 | TXCRCEN | PADCFG0 | PADCFG2 | MACON2_DEFER; - if ((priv->autoneg == AUTONEG_DISABLE) && priv->full_duplex) - macon2 |= FULDPX; - - encx24j600_set_bits(priv, MACON2, macon2); - - priv->rxfilter = RXFILTER_NORMAL; - encx24j600_set_rxfilter_mode(priv); - - /* Program the Maximum frame length */ - encx24j600_write_reg(priv, MAMXFL, MAX_FRAMELEN); - - /* Init Tx pointers */ - encx24j600_hw_init_tx(priv); - - /* Init Rx pointers */ - encx24j600_hw_init_rx(priv); - - if (netif_msg_hw(priv)) - encx24j600_dump_config(priv, "Hw is initialized"); - -err_out: - return ret; -} - -static void encx24j600_hw_enable(struct encx24j600_priv *priv) -{ - /* Clear the interrupt flags in case was set */ - encx24j600_clr_bits(priv, EIR, (PCFULIF | RXABTIF | TXABTIF | TXIF | - PKTIF | LINKIF)); - - /* Enable the interrupts */ - encx24j600_write_reg(priv, EIE, (PCFULIE | RXABTIE | TXABTIE | TXIE | - PKTIE | LINKIE | INTIE)); - - /* Enable RX */ - encx24j600_cmd(priv, ENABLERX); - - priv->hw_enabled = true; -} - -static void encx24j600_hw_disable(struct encx24j600_priv *priv) -{ - /* Disable all interrupts */ - encx24j600_write_reg(priv, EIE, 0); - - /* Disable RX */ - encx24j600_cmd(priv, DISABLERX); - - priv->hw_enabled = false; -} - -static int encx24j600_setlink(struct net_device *dev, u8 autoneg, u16 speed, - u8 duplex) -{ - struct encx24j600_priv *priv = netdev_priv(dev); - int ret = 0; - - if (!priv->hw_enabled) { - /* link is in low power mode now; duplex setting - * will take effect on next encx24j600_hw_init() - */ - if (speed == SPEED_10 || speed == SPEED_100) { - priv->autoneg = (autoneg == AUTONEG_ENABLE); - priv->full_duplex = (duplex == DUPLEX_FULL); - priv->speed = (speed == SPEED_100); - } else { - netif_warn(priv, link, dev, "unsupported link speed setting\n"); - /*speeds other than SPEED_10 and SPEED_100 */ - /*are not supported by chip */ - ret = -EOPNOTSUPP; - } - } else { - netif_warn(priv, link, dev, "Warning: hw must be disabled to set link mode\n"); - ret = -EBUSY; - } - return ret; -} - -static void encx24j600_hw_get_macaddr(struct encx24j600_priv *priv, - unsigned char *ethaddr) -{ - unsigned short val; - - val = encx24j600_read_reg(priv, MAADR1); - - ethaddr[0] = val & 0x00ff; - ethaddr[1] = (val & 0xff00) >> 8; - - val = encx24j600_read_reg(priv, MAADR2); - - ethaddr[2] = val & 0x00ffU; - ethaddr[3] = (val & 0xff00U) >> 8; - - val = encx24j600_read_reg(priv, MAADR3); - - ethaddr[4] = val & 0x00ffU; - ethaddr[5] = (val & 0xff00U) >> 8; -} - -/* Program the hardware MAC address from dev->dev_addr.*/ -static int encx24j600_set_hw_macaddr(struct net_device *dev) -{ - struct encx24j600_priv *priv = netdev_priv(dev); - - if (priv->hw_enabled) { - netif_info(priv, drv, dev, "Hardware must be disabled to set Mac address\n"); - return -EBUSY; - } - - mutex_lock(&priv->lock); - - netif_info(priv, drv, dev, "%s: Setting MAC address to %pM\n", - dev->name, dev->dev_addr); - - encx24j600_write_reg(priv, MAADR3, (dev->dev_addr[4] | - dev->dev_addr[5] << 8)); - encx24j600_write_reg(priv, MAADR2, (dev->dev_addr[2] | - dev->dev_addr[3] << 8)); - encx24j600_write_reg(priv, MAADR1, (dev->dev_addr[0] | - dev->dev_addr[1] << 8)); - - mutex_unlock(&priv->lock); - - return 0; -} - -/* Store the new hardware address in dev->dev_addr, and update the MAC.*/ -static int encx24j600_set_mac_address(struct net_device *dev, void *addr) -{ - struct sockaddr *address = addr; - - if (netif_running(dev)) - return -EBUSY; - if (!is_valid_ether_addr(address->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, address->sa_data, dev->addr_len); - return encx24j600_set_hw_macaddr(dev); -} - -static int encx24j600_open(struct net_device *dev) -{ - struct encx24j600_priv *priv = netdev_priv(dev); - - int ret = request_threaded_irq(priv->ctx.spi->irq, NULL, encx24j600_isr, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - DRV_NAME, priv); - if (unlikely(ret < 0)) { - netdev_err(dev, "request irq %d failed (ret = %d)\n", - priv->ctx.spi->irq, ret); - return ret; - } - - encx24j600_hw_disable(priv); - encx24j600_hw_init(priv); - encx24j600_hw_enable(priv); - netif_start_queue(dev); - - return 0; -} - -static int encx24j600_stop(struct net_device *dev) -{ - struct encx24j600_priv *priv = netdev_priv(dev); - - netif_stop_queue(dev); - free_irq(priv->ctx.spi->irq, priv); - return 0; -} - -static void encx24j600_setrx_proc(struct kthread_work *ws) -{ - struct encx24j600_priv *priv = - container_of(ws, struct encx24j600_priv, setrx_work); - - mutex_lock(&priv->lock); - encx24j600_set_rxfilter_mode(priv); - mutex_unlock(&priv->lock); -} - -static void encx24j600_set_multicast_list(struct net_device *dev) -{ - struct encx24j600_priv *priv = netdev_priv(dev); - int oldfilter = priv->rxfilter; - - if (dev->flags & IFF_PROMISC) { - netif_dbg(priv, link, dev, "promiscuous mode\n"); - priv->rxfilter = RXFILTER_PROMISC; - } else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) { - netif_dbg(priv, link, dev, "%smulticast mode\n", - (dev->flags & IFF_ALLMULTI) ? "all-" : ""); - priv->rxfilter = RXFILTER_MULTI; - } else { - netif_dbg(priv, link, dev, "normal mode\n"); - priv->rxfilter = RXFILTER_NORMAL; - } - - if (oldfilter != priv->rxfilter) - queue_kthread_work(&priv->kworker, &priv->setrx_work); -} - -static void encx24j600_hw_tx(struct encx24j600_priv *priv) -{ - struct net_device *dev = priv->ndev; - netif_info(priv, tx_queued, dev, "TX Packet Len:%d\n", - priv->tx_skb->len); - - if (netif_msg_pktdata(priv)) - dump_packet("TX", priv->tx_skb->len, priv->tx_skb->data); - - if (encx24j600_read_reg(priv, EIR) & TXABTIF) - /* Last transmition aborted due to error. Reset TX interface */ - encx24j600_reset_hw_tx(priv); - - /* Clear the TXIF flag if were previously set */ - encx24j600_clr_bits(priv, EIR, TXIF); - - /* Set the data pointer to the TX buffer address in the SRAM */ - encx24j600_write_reg(priv, EGPWRPT, ENC_TX_BUF_START); - - /* Copy the packet into the SRAM */ - encx24j600_raw_write(priv, WGPDATA, (u8 *)priv->tx_skb->data, - priv->tx_skb->len); - - /* Program the Tx buffer start pointer */ - encx24j600_write_reg(priv, ETXST, ENC_TX_BUF_START); - - /* Program the packet length */ - encx24j600_write_reg(priv, ETXLEN, priv->tx_skb->len); - - /* Start the transmission */ - encx24j600_cmd(priv, SETTXRTS); -} - -static void encx24j600_tx_proc(struct kthread_work *ws) -{ - struct encx24j600_priv *priv = - container_of(ws, struct encx24j600_priv, tx_work); - - mutex_lock(&priv->lock); - encx24j600_hw_tx(priv); - mutex_unlock(&priv->lock); -} - -static netdev_tx_t encx24j600_tx(struct sk_buff *skb, struct net_device *dev) -{ - struct encx24j600_priv *priv = netdev_priv(dev); - - netif_stop_queue(dev); - - /* save the timestamp */ - dev->trans_start = jiffies; - - /* Remember the skb for deferred processing */ - priv->tx_skb = skb; - - queue_kthread_work(&priv->kworker, &priv->tx_work); - - return NETDEV_TX_OK; -} - -/* Deal with a transmit timeout */ -static void encx24j600_tx_timeout(struct net_device *dev) -{ - struct encx24j600_priv *priv = netdev_priv(dev); - - netif_err(priv, tx_err, dev, "TX timeout at %ld, latency %ld\n", - jiffies, jiffies - dev->trans_start); - - dev->stats.tx_errors++; - netif_wake_queue(dev); - return; -} - -static int encx24j600_get_regs_len(struct net_device *dev) -{ - return SFR_REG_COUNT; -} - -static void encx24j600_get_regs(struct net_device *dev, - struct ethtool_regs *regs, void *p) -{ - struct encx24j600_priv *priv = netdev_priv(dev); - u16 *buff = p; - u8 reg; - - regs->version = 1; - mutex_lock(&priv->lock); - for (reg = 0; reg < SFR_REG_COUNT; reg += 2) { - unsigned int val = 0; - /* ignore errors for unreadable registers */ - regmap_read(priv->ctx.regmap, reg, &val); - buff[reg] = val & 0xffff; - } - mutex_unlock(&priv->lock); -} - -static void encx24j600_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); - strlcpy(info->version, DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, dev_name(dev->dev.parent), - sizeof(info->bus_info)); -} - -static int encx24j600_get_settings(struct net_device *dev, - struct ethtool_cmd *cmd) -{ - struct encx24j600_priv *priv = netdev_priv(dev); - - cmd->transceiver = XCVR_INTERNAL; - cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | SUPPORTED_TP; - - ethtool_cmd_speed_set(cmd, priv->speed); - cmd->duplex = priv->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; - cmd->port = PORT_TP; - cmd->autoneg = priv->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; - - return 0; -} - -static int encx24j600_set_settings(struct net_device *dev, - struct ethtool_cmd *cmd) -{ - return encx24j600_setlink(dev, cmd->autoneg, - ethtool_cmd_speed(cmd), cmd->duplex); -} - -static u32 encx24j600_get_msglevel(struct net_device *dev) -{ - struct encx24j600_priv *priv = netdev_priv(dev); - return priv->msg_enable; -} - -static void encx24j600_set_msglevel(struct net_device *dev, u32 val) -{ - struct encx24j600_priv *priv = netdev_priv(dev); - priv->msg_enable = val; -} - -static const struct ethtool_ops encx24j600_ethtool_ops = { - .get_settings = encx24j600_get_settings, - .set_settings = encx24j600_set_settings, - .get_drvinfo = encx24j600_get_drvinfo, - .get_msglevel = encx24j600_get_msglevel, - .set_msglevel = encx24j600_set_msglevel, - .get_regs_len = encx24j600_get_regs_len, - .get_regs = encx24j600_get_regs, -}; - -static const struct net_device_ops encx24j600_netdev_ops = { - .ndo_open = encx24j600_open, - .ndo_stop = encx24j600_stop, - .ndo_start_xmit = encx24j600_tx, - .ndo_set_rx_mode = encx24j600_set_multicast_list, - .ndo_set_mac_address = encx24j600_set_mac_address, - .ndo_tx_timeout = encx24j600_tx_timeout, - .ndo_validate_addr = eth_validate_addr, -}; - -static int encx24j600_spi_probe(struct spi_device *spi) -{ - int ret; - - struct net_device *ndev; - struct encx24j600_priv *priv; - - ndev = alloc_etherdev(sizeof(struct encx24j600_priv)); - - if (!ndev) { - ret = -ENOMEM; - goto error_out; - } - - priv = netdev_priv(ndev); - spi_set_drvdata(spi, priv); - dev_set_drvdata(&spi->dev, priv); - SET_NETDEV_DEV(ndev, &spi->dev); - - priv->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); - priv->ndev = ndev; - - /* Default configuration PHY configuration */ - priv->full_duplex = true; - priv->autoneg = AUTONEG_ENABLE; - priv->speed = SPEED_100; - - priv->ctx.spi = spi; - devm_regmap_init_encx24j600(&spi->dev, &priv->ctx); - ndev->irq = spi->irq; - ndev->netdev_ops = &encx24j600_netdev_ops; - - mutex_init(&priv->lock); - - /* Reset device and check if it is connected */ - if (encx24j600_hw_reset(priv)) { - netif_err(priv, probe, ndev, - DRV_NAME ": Chip is not detected\n"); - ret = -EIO; - goto out_free; - } - - /* Initialize the device HW to the consistent state */ - if (encx24j600_hw_init(priv)) { - netif_err(priv, probe, ndev, - DRV_NAME ": HW initialization error\n"); - ret = -EIO; - goto out_free; - } - - init_kthread_worker(&priv->kworker); - init_kthread_work(&priv->tx_work, encx24j600_tx_proc); - init_kthread_work(&priv->setrx_work, encx24j600_setrx_proc); - - priv->kworker_task = kthread_run(kthread_worker_fn, &priv->kworker, - "encx24j600"); - - if (IS_ERR(priv->kworker_task)) { - ret = PTR_ERR(priv->kworker_task); - goto out_free; - } - - /* Get the MAC address from the chip */ - encx24j600_hw_get_macaddr(priv, ndev->dev_addr); - - ndev->ethtool_ops = &encx24j600_ethtool_ops; - - ret = register_netdev(ndev); - if (unlikely(ret)) { - netif_err(priv, probe, ndev, "Error %d initializing card encx24j600 card\n", - ret); - goto out_free; - } - - netif_info(priv, drv, priv->ndev, "MAC address %pM\n", ndev->dev_addr); - - return ret; - -out_free: - free_netdev(ndev); - -error_out: - return ret; -} - -static int encx24j600_spi_remove(struct spi_device *spi) -{ - struct encx24j600_priv *priv = dev_get_drvdata(&spi->dev); - - unregister_netdev(priv->ndev); - - free_netdev(priv->ndev); - - return 0; -} - -static const struct spi_device_id encx24j600_spi_id_table = { - .name = "encx24j600" -}; - -static struct spi_driver encx24j600_spi_net_driver = { - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - .bus = &spi_bus_type, - }, - .probe = encx24j600_spi_probe, - .remove = encx24j600_spi_remove, - .id_table = &encx24j600_spi_id_table, -}; - -static int __init encx24j600_init(void) -{ - return spi_register_driver(&encx24j600_spi_net_driver); -} -module_init(encx24j600_init); - -void encx24j600_exit(void) -{ - spi_unregister_driver(&encx24j600_spi_net_driver); -} -module_exit(encx24j600_exit); - -MODULE_DESCRIPTION(DRV_NAME " ethernet driver"); -MODULE_AUTHOR("Jon Ringle "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:" DRV_NAME); diff --git a/drivers/net/ethernet/microchip/encx24j600_hw.h b/drivers/net/ethernet/microchip/encx24j600_hw.h deleted file mode 100644 index 4be73d5553f8..000000000000 --- a/drivers/net/ethernet/microchip/encx24j600_hw.h +++ /dev/null @@ -1,437 +0,0 @@ -/** - * encx24j600_hw.h: Register definitions - * - */ - -#ifndef _ENCX24J600_HW_H -#define _ENCX24J600_HW_H - -struct encx24j600_context { - struct spi_device *spi; - struct regmap *regmap; - struct regmap *phymap; - struct mutex mutex; /* mutex to protect access to regmap */ - int bank; -}; - -void devm_regmap_init_encx24j600(struct device *dev, - struct encx24j600_context *ctx); - -/* Single-byte instructions */ -#define BANK_SELECT(bank) (0xC0 | ((bank & (BANK_MASK >> BANK_SHIFT)) << 1)) -#define B0SEL 0xC0 /* Bank 0 Select */ -#define B1SEL 0xC2 /* Bank 1 Select */ -#define B2SEL 0xC4 /* Bank 2 Select */ -#define B3SEL 0xC6 /* Bank 3 Select */ -#define SETETHRST 0xCA /* System Reset */ -#define FCDISABLE 0xE0 /* Flow Control Disable */ -#define FCSINGLE 0xE2 /* Flow Control Single */ -#define FCMULTIPLE 0xE4 /* Flow Control Multiple */ -#define FCCLEAR 0xE6 /* Flow Control Clear */ -#define SETPKTDEC 0xCC /* Decrement Packet Counter */ -#define DMASTOP 0xD2 /* DMA Stop */ -#define DMACKSUM 0xD8 /* DMA Start Checksum */ -#define DMACKSUMS 0xDA /* DMA Start Checksum with Seed */ -#define DMACOPY 0xDC /* DMA Start Copy */ -#define DMACOPYS 0xDE /* DMA Start Copy and Checksum with Seed */ -#define SETTXRTS 0xD4 /* Request Packet Transmission */ -#define ENABLERX 0xE8 /* Enable RX */ -#define DISABLERX 0xEA /* Disable RX */ -#define SETEIE 0xEC /* Enable Interrupts */ -#define CLREIE 0xEE /* Disable Interrupts */ - -/* Two byte instructions */ -#define RBSEL 0xC8 /* Read Bank Select */ - -/* Three byte instructions */ -#define WGPRDPT 0x60 /* Write EGPRDPT */ -#define RGPRDPT 0x62 /* Read EGPRDPT */ -#define WRXRDPT 0x64 /* Write ERXRDPT */ -#define RRXRDPT 0x66 /* Read ERXRDPT */ -#define WUDARDPT 0x68 /* Write EUDARDPT */ -#define RUDARDPT 0x6A /* Read EUDARDPT */ -#define WGPWRPT 0x6C /* Write EGPWRPT */ -#define RGPWRPT 0x6E /* Read EGPWRPT */ -#define WRXWRPT 0x70 /* Write ERXWRPT */ -#define RRXWRPT 0x72 /* Read ERXWRPT */ -#define WUDAWRPT 0x74 /* Write EUDAWRPT */ -#define RUDAWRPT 0x76 /* Read EUDAWRPT */ - -/* n byte instructions */ -#define RCRCODE 0x00 -#define WCRCODE 0x40 -#define BFSCODE 0x80 -#define BFCCODE 0xA0 -#define RCR(addr) (RCRCODE | (addr & ADDR_MASK)) /* Read Control Register */ -#define WCR(addr) (WCRCODE | (addr & ADDR_MASK)) /* Write Control Register */ -#define RCRU 0x20 /* Read Control Register Unbanked */ -#define WCRU 0x22 /* Write Control Register Unbanked */ -#define BFS(addr) (BFSCODE | (addr & ADDR_MASK)) /* Bit Field Set */ -#define BFC(addr) (BFCCODE | (addr & ADDR_MASK)) /* Bit Field Clear */ -#define BFSU 0x24 /* Bit Field Set Unbanked */ -#define BFCU 0x26 /* Bit Field Clear Unbanked */ -#define RGPDATA 0x28 /* Read EGPDATA */ -#define WGPDATA 0x2A /* Write EGPDATA */ -#define RRXDATA 0x2C /* Read ERXDATA */ -#define WRXDATA 0x2E /* Write ERXDATA */ -#define RUDADATA 0x30 /* Read EUDADATA */ -#define WUDADATA 0x32 /* Write EUDADATA */ - -#define SFR_REG_COUNT 0xA0 - -/* ENC424J600 Control Registers - * Control register definitions are a combination of address - * and bank number - * - Register address (bits 0-4) - * - Bank number (bits 5-6) - */ -#define ADDR_MASK 0x1F -#define BANK_MASK 0x60 -#define BANK_SHIFT 5 - -/* All-bank registers */ -#define EUDAST 0x16 -#define EUDAND 0x18 -#define ESTAT 0x1A -#define EIR 0x1C -#define ECON1 0x1E - -/* Bank 0 registers */ -#define ETXST (0x00 | 0x00) -#define ETXLEN (0x02 | 0x00) -#define ERXST (0x04 | 0x00) -#define ERXTAIL (0x06 | 0x00) -#define ERXHEAD (0x08 | 0x00) -#define EDMAST (0x0A | 0x00) -#define EDMALEN (0x0C | 0x00) -#define EDMADST (0x0E | 0x00) -#define EDMACS (0x10 | 0x00) -#define ETXSTAT (0x12 | 0x00) -#define ETXWIRE (0x14 | 0x00) - -/* Bank 1 registers */ -#define EHT1 (0x00 | 0x20) -#define EHT2 (0x02 | 0x20) -#define EHT3 (0x04 | 0x20) -#define EHT4 (0x06 | 0x20) -#define EPMM1 (0x08 | 0x20) -#define EPMM2 (0x0A | 0x20) -#define EPMM3 (0x0C | 0x20) -#define EPMM4 (0x0E | 0x20) -#define EPMCS (0x10 | 0x20) -#define EPMO (0x12 | 0x20) -#define ERXFCON (0x14 | 0x20) - -/* Bank 2 registers */ -#define MACON1 (0x00 | 0x40) -#define MACON2 (0x02 | 0x40) -#define MABBIPG (0x04 | 0x40) -#define MAIPG (0x06 | 0x40) -#define MACLCON (0x08 | 0x40) -#define MAMXFL (0x0A | 0x40) -#define MICMD (0x12 | 0x40) -#define MIREGADR (0x14 | 0x40) - -/* Bank 3 registers */ -#define MAADR3 (0x00 | 0x60) -#define MAADR2 (0x02 | 0x60) -#define MAADR1 (0x04 | 0x60) -#define MIWR (0x06 | 0x60) -#define MIRD (0x08 | 0x60) -#define MISTAT (0x0A | 0x60) -#define EPAUS (0x0C | 0x60) -#define ECON2 (0x0E | 0x60) -#define ERXWM (0x10 | 0x60) -#define EIE (0x12 | 0x60) -#define EIDLED (0x14 | 0x60) - -/* Unbanked registers */ -#define EGPDATA (0x00 | 0x80) -#define ERXDATA (0x02 | 0x80) -#define EUDADATA (0x04 | 0x80) -#define EGPRDPT (0x06 | 0x80) -#define EGPWRPT (0x08 | 0x80) -#define ERXRDPT (0x0A | 0x80) -#define ERXWRPT (0x0C | 0x80) -#define EUDARDPT (0x0E | 0x80) -#define EUDAWRPT (0x10 | 0x80) - - -/* Register bit definitions */ -/* ESTAT */ -#define INT (1 << 15) -#define FCIDLE (1 << 14) -#define RXBUSY (1 << 13) -#define CLKRDY (1 << 12) -#define PHYDPX (1 << 10) -#define PHYLNK (1 << 8) - -/* EIR */ -#define CRYPTEN (1 << 15) -#define MODEXIF (1 << 14) -#define HASHIF (1 << 13) -#define AESIF (1 << 12) -#define LINKIF (1 << 11) -#define PKTIF (1 << 6) -#define DMAIF (1 << 5) -#define TXIF (1 << 3) -#define TXABTIF (1 << 2) -#define RXABTIF (1 << 1) -#define PCFULIF (1 << 0) - -/* ECON1 */ -#define MODEXST (1 << 15) -#define HASHEN (1 << 14) -#define HASHOP (1 << 13) -#define HASHLST (1 << 12) -#define AESST (1 << 11) -#define AESOP1 (1 << 10) -#define AESOP0 (1 << 9) -#define PKTDEC (1 << 8) -#define FCOP1 (1 << 7) -#define FCOP0 (1 << 6) -#define DMAST (1 << 5) -#define DMACPY (1 << 4) -#define DMACSSD (1 << 3) -#define DMANOCS (1 << 2) -#define TXRTS (1 << 1) -#define RXEN (1 << 0) - -/* ETXSTAT */ -#define LATECOL (1 << 10) -#define MAXCOL (1 << 9) -#define EXDEFER (1 << 8) -#define ETXSTATL_DEFER (1 << 7) -#define CRCBAD (1 << 4) -#define COLCNT_MASK 0xF - -/* ERXFCON */ -#define HTEN (1 << 15) -#define MPEN (1 << 14) -#define NOTPM (1 << 12) -#define PMEN3 (1 << 11) -#define PMEN2 (1 << 10) -#define PMEN1 (1 << 9) -#define PMEN0 (1 << 8) -#define CRCEEN (1 << 7) -#define CRCEN (1 << 6) -#define RUNTEEN (1 << 5) -#define RUNTEN (1 << 4) -#define UCEN (1 << 3) -#define NOTMEEN (1 << 2) -#define MCEN (1 << 1) -#define BCEN (1 << 0) - -/* MACON1 */ -#define LOOPBK (1 << 4) -#define RXPAUS (1 << 2) -#define PASSALL (1 << 1) - -/* MACON2 */ -#define MACON2_DEFER (1 << 14) -#define BPEN (1 << 13) -#define NOBKOFF (1 << 12) -#define PADCFG2 (1 << 7) -#define PADCFG1 (1 << 6) -#define PADCFG0 (1 << 5) -#define TXCRCEN (1 << 4) -#define PHDREN (1 << 3) -#define HFRMEN (1 << 2) -#define MACON2_RSV1 (1 << 1) -#define FULDPX (1 << 0) - -/* MAIPG */ -/* value of the high byte is given by the reserved bits, - * value of the low byte is recomended setting of the - * IPG parameter. - */ -#define MAIPGH_VAL 0x0C -#define MAIPGL_VAL 0x12 - -/* MIREGADRH */ -#define MIREGADR_VAL (1 << 8) - -/* MIREGADRL */ -#define PHREG_MASK 0x1F - -/* MICMD */ -#define MIISCAN (1 << 1) -#define MIIRD (1 << 0) - -/* MISTAT */ -#define NVALID (1 << 2) -#define SCAN (1 << 1) -#define BUSY (1 << 0) - -/* ECON2 */ -#define ETHEN (1 << 15) -#define STRCH (1 << 14) -#define TXMAC (1 << 13) -#define SHA1MD5 (1 << 12) -#define COCON3 (1 << 11) -#define COCON2 (1 << 10) -#define COCON1 (1 << 9) -#define COCON0 (1 << 8) -#define AUTOFC (1 << 7) -#define TXRST (1 << 6) -#define RXRST (1 << 5) -#define ETHRST (1 << 4) -#define MODLEN1 (1 << 3) -#define MODLEN0 (1 << 2) -#define AESLEN1 (1 << 1) -#define AESLEN0 (1 << 0) - -/* EIE */ -#define INTIE (1 << 15) -#define MODEXIE (1 << 14) -#define HASHIE (1 << 13) -#define AESIE (1 << 12) -#define LINKIE (1 << 11) -#define PKTIE (1 << 6) -#define DMAIE (1 << 5) -#define TXIE (1 << 3) -#define TXABTIE (1 << 2) -#define RXABTIE (1 << 1) -#define PCFULIE (1 << 0) - -/* EIDLED */ -#define LACFG3 (1 << 15) -#define LACFG2 (1 << 14) -#define LACFG1 (1 << 13) -#define LACFG0 (1 << 12) -#define LBCFG3 (1 << 11) -#define LBCFG2 (1 << 10) -#define LBCFG1 (1 << 9) -#define LBCFG0 (1 << 8) -#define DEVID_SHIFT 5 -#define DEVID_MASK (0x7 << DEVID_SHIFT) -#define REVID_SHIFT 0 -#define REVID_MASK (0x1F << REVID_SHIFT) - -/* PHY registers */ -#define PHCON1 0x00 -#define PHSTAT1 0x01 -#define PHANA 0x04 -#define PHANLPA 0x05 -#define PHANE 0x06 -#define PHCON2 0x11 -#define PHSTAT2 0x1B -#define PHSTAT3 0x1F - -/* PHCON1 */ -#define PRST (1 << 15) -#define PLOOPBK (1 << 14) -#define SPD100 (1 << 13) -#define ANEN (1 << 12) -#define PSLEEP (1 << 11) -#define RENEG (1 << 9) -#define PFULDPX (1 << 8) - -/* PHSTAT1 */ -#define FULL100 (1 << 14) -#define HALF100 (1 << 13) -#define FULL10 (1 << 12) -#define HALF10 (1 << 11) -#define ANDONE (1 << 5) -#define LRFAULT (1 << 4) -#define ANABLE (1 << 3) -#define LLSTAT (1 << 2) -#define EXTREGS (1 << 0) - -/* PHSTAT2 */ -#define PLRITY (1 << 4) - -/* PHSTAT3 */ -#define PHY3SPD100 (1 << 3) -#define PHY3DPX (1 << 4) -#define SPDDPX_SHIFT 2 -#define SPDDPX_MASK (0x7 << SPDDPX_SHIFT) - -/* PHANA */ -/* Default value for PHY initialization*/ -#define PHANA_DEFAULT 0x05E1 - -/* PHANE */ -#define PDFLT (1 << 4) -#define LPARCD (1 << 1) -#define LPANABL (1 << 0) - -#define EUDAST_TEST_VAL 0x1234 - -#define TSV_SIZE 7 - -#define ENCX24J600_DEV_ID 0x1 - -/* Configuration */ - -/* Led is on when the link is present and driven low - * temporarily when packet is TX'd or RX'd - */ -#define LED_A_SETTINGS 0xC - -/* Led is on if the link is in 100 Mbps mode */ -#define LED_B_SETTINGS 0x8 - -/* maximum ethernet frame length - * Currently not used as a limit anywhere - * (we're using the "huge frame enable" feature of - * enc424j600). - */ -#define MAX_FRAMELEN 1518 - -/* Size in bytes of the receive buffer in enc424j600. - * Must be word aligned (even). - */ -#define RX_BUFFER_SIZE (15 * MAX_FRAMELEN) - -/* Start of the general purpose area in sram */ -#define SRAM_GP_START 0x0 - -/* SRAM size */ -#define SRAM_SIZE 0x6000 - -/* Start of the receive buffer */ -#define ERXST_VAL (SRAM_SIZE - RX_BUFFER_SIZE) - -#define RSV_RXLONGEVDROPEV 16 -#define RSV_CARRIEREV 18 -#define RSV_CRCERROR 20 -#define RSV_LENCHECKERR 21 -#define RSV_LENOUTOFRANGE 22 -#define RSV_RXOK 23 -#define RSV_RXMULTICAST 24 -#define RSV_RXBROADCAST 25 -#define RSV_DRIBBLENIBBLE 26 -#define RSV_RXCONTROLFRAME 27 -#define RSV_RXPAUSEFRAME 28 -#define RSV_RXUNKNOWNOPCODE 29 -#define RSV_RXTYPEVLAN 30 - -#define RSV_RUNTFILTERMATCH 31 -#define RSV_NOTMEFILTERMATCH 32 -#define RSV_HASHFILTERMATCH 33 -#define RSV_MAGICPKTFILTERMATCH 34 -#define RSV_PTRNMTCHFILTERMATCH 35 -#define RSV_UNICASTFILTERMATCH 36 - -#define RSV_SIZE 8 -#define RSV_BITMASK(x) (1 << ((x) - 16)) -#define RSV_GETBIT(x, y) (((x) & RSV_BITMASK(y)) ? 1 : 0) - -struct rsv { - u16 next_packet; - u16 len; - u32 rxstat; -}; - -/* Put RX buffer at 0 as suggested by the Errata datasheet */ - -#define RXSTART_INIT ERXST_VAL -#define RXEND_INIT 0x5FFF - -int regmap_encx24j600_spi_write(void *context, u8 reg, const u8 *data, - size_t count); -int regmap_encx24j600_spi_read(void *context, u8 reg, u8 *data, size_t count); - - -#endif -- cgit v1.2.3 From 4bac50bace0377138fed2ac3627c1ad470ea1eca Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 3 Oct 2015 18:09:01 +0100 Subject: net: dsa: mv88e6xxx: remove link polling The link status is polled by the generic phy layer, there's no need to duplicate that polling with additional polling. This additional polling adds additional MDIO traffic, and races with the generic phy layer, resulting in missing or duplicated link status messages. Tested-by: Andrew Lunn Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6123_61_65.c | 1 - drivers/net/dsa/mv88e6131.c | 1 - drivers/net/dsa/mv88e6171.c | 1 - drivers/net/dsa/mv88e6352.c | 1 - drivers/net/dsa/mv88e6xxx.c | 67 --------------------------------------- drivers/net/dsa/mv88e6xxx.h | 1 - 6 files changed, 72 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c index 3de2a6d73fdc..4bcfd683bbea 100644 --- a/drivers/net/dsa/mv88e6123_61_65.c +++ b/drivers/net/dsa/mv88e6123_61_65.c @@ -125,7 +125,6 @@ struct dsa_switch_driver mv88e6123_61_65_switch_driver = { .set_addr = mv88e6xxx_set_addr_indirect, .phy_read = mv88e6xxx_phy_read, .phy_write = mv88e6xxx_phy_write, - .poll_link = mv88e6xxx_poll_link, .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index 3e8386529965..c73121c8f155 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -178,7 +178,6 @@ struct dsa_switch_driver mv88e6131_switch_driver = { .set_addr = mv88e6xxx_set_addr_direct, .phy_read = mv88e6131_phy_read, .phy_write = mv88e6131_phy_write, - .poll_link = mv88e6xxx_poll_link, .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index c2daaf087761..c95cfab56a4f 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -104,7 +104,6 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .set_addr = mv88e6xxx_set_addr_indirect, .phy_read = mv88e6xxx_phy_read_indirect, .phy_write = mv88e6xxx_phy_write_indirect, - .poll_link = mv88e6xxx_poll_link, .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 1f5129c105fb..37367060676f 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -324,7 +324,6 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .set_addr = mv88e6xxx_set_addr_indirect, .phy_read = mv88e6xxx_phy_read_indirect, .phy_write = mv88e6xxx_phy_write_indirect, - .poll_link = mv88e6xxx_poll_link, .get_strings = mv88e6xxx_get_strings, .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, .get_sset_count = mv88e6xxx_get_sset_count, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 932fb720be24..8e088e355834 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -388,73 +388,6 @@ int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr, } #endif -void mv88e6xxx_poll_link(struct dsa_switch *ds) -{ - int i; - - for (i = 0; i < DSA_MAX_PORTS; i++) { - struct net_device *dev; - int uninitialized_var(port_status); - int pcs_ctrl; - int link; - int speed; - int duplex; - int fc; - - dev = ds->ports[i]; - if (dev == NULL) - continue; - - pcs_ctrl = mv88e6xxx_reg_read(ds, REG_PORT(i), PORT_PCS_CTRL); - if (pcs_ctrl < 0 || pcs_ctrl & PORT_PCS_CTRL_FORCE_LINK) - continue; - - link = 0; - if (dev->flags & IFF_UP) { - port_status = mv88e6xxx_reg_read(ds, REG_PORT(i), - PORT_STATUS); - if (port_status < 0) - continue; - - link = !!(port_status & PORT_STATUS_LINK); - } - - if (!link) { - if (netif_carrier_ok(dev)) { - netdev_info(dev, "link down\n"); - netif_carrier_off(dev); - } - continue; - } - - switch (port_status & PORT_STATUS_SPEED_MASK) { - case PORT_STATUS_SPEED_10: - speed = 10; - break; - case PORT_STATUS_SPEED_100: - speed = 100; - break; - case PORT_STATUS_SPEED_1000: - speed = 1000; - break; - default: - speed = -1; - break; - } - duplex = (port_status & PORT_STATUS_DUPLEX) ? 1 : 0; - fc = (port_status & PORT_STATUS_PAUSE_EN) ? 1 : 0; - - if (!netif_carrier_ok(dev)) { - netdev_info(dev, - "link up, %d Mb/s, %s duplex, flow control %sabled\n", - speed, - duplex ? "full" : "half", - fc ? "en" : "dis"); - netif_carrier_on(dev); - } - } -} - static bool mv88e6xxx_6065_family(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 1cf3cf887902..d8ec48710b80 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -442,7 +442,6 @@ void mv88e6xxx_ppu_state_init(struct dsa_switch *ds); int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum); int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr, int regnum, u16 val); -void mv88e6xxx_poll_link(struct dsa_switch *ds); void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, uint8_t *data); void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data); -- cgit v1.2.3 From 90d2c056bd85bbb47104c52e08eecf8408163a54 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Sat, 3 Oct 2015 17:13:05 -0700 Subject: i40e/i40evf: set AQ count after memory allocation The standard way to check if the AQ is enabled is to look at the count field. So we should only set this field after we have successfully allocated memory. To do otherwise is to incite panic among the populace. Signed-off-by: Mitch Williams Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 4 ++-- drivers/net/ethernet/intel/i40evf/i40e_adminq.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 62488a67149d..c0e943aecd13 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -386,7 +386,6 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw) hw->aq.asq.next_to_use = 0; hw->aq.asq.next_to_clean = 0; - hw->aq.asq.count = hw->aq.num_asq_entries; /* allocate the ring memory */ ret_code = i40e_alloc_adminq_asq_ring(hw); @@ -404,6 +403,7 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw) goto init_adminq_free_rings; /* success! */ + hw->aq.asq.count = hw->aq.num_asq_entries; goto init_adminq_exit; init_adminq_free_rings: @@ -445,7 +445,6 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw) hw->aq.arq.next_to_use = 0; hw->aq.arq.next_to_clean = 0; - hw->aq.arq.count = hw->aq.num_arq_entries; /* allocate the ring memory */ ret_code = i40e_alloc_adminq_arq_ring(hw); @@ -463,6 +462,7 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw) goto init_adminq_free_rings; /* success! */ + hw->aq.arq.count = hw->aq.num_arq_entries; goto init_adminq_exit; init_adminq_free_rings: diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c index 929d47152bf2..a23ebfd5cd25 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c @@ -373,7 +373,6 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw) hw->aq.asq.next_to_use = 0; hw->aq.asq.next_to_clean = 0; - hw->aq.asq.count = hw->aq.num_asq_entries; /* allocate the ring memory */ ret_code = i40e_alloc_adminq_asq_ring(hw); @@ -391,6 +390,7 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw) goto init_adminq_free_rings; /* success! */ + hw->aq.asq.count = hw->aq.num_asq_entries; goto init_adminq_exit; init_adminq_free_rings: @@ -432,7 +432,6 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw) hw->aq.arq.next_to_use = 0; hw->aq.arq.next_to_clean = 0; - hw->aq.arq.count = hw->aq.num_arq_entries; /* allocate the ring memory */ ret_code = i40e_alloc_adminq_arq_ring(hw); @@ -450,6 +449,7 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw) goto init_adminq_free_rings; /* success! */ + hw->aq.arq.count = hw->aq.num_arq_entries; goto init_adminq_exit; init_adminq_free_rings: -- cgit v1.2.3 From 3e905b80b92146d8dd0bf2da3ade0944a3026597 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 5 Oct 2015 17:19:59 +0300 Subject: gianfar: Add WAKE_UCAST and "wake-on-filer" support This enables eTSEC's filer (Rx parser) and the FGPI Rx interrupt (Filer General Purpose Interrupt) as a wakeup source event. Upon entering suspend state, the eTSEC filer is given a rule to match incoming L2 unicast packets. A packet matching the rule will be enqueued in the Rx ring and a FGPI Rx interrupt will be asserted by the filer to wakeup the system. Other packet types will be dropped. On resume the filer table is restored to the content before entering suspend state. The set of rules from gfar_filer_config_wol() could be extended to implement other WoL capabilities as well. The "fsl,wake-on-filer" DT binding enables this capability on certain platforms that feature the necessary power management infrastructure, targeting mainly printing and imaging applications. (refer to Power Management section of the SoC Ref Man) Cc: Li Yang Cc: Zhao Chenhui Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 155 +++++++++++++++++++++-- drivers/net/ethernet/freescale/gianfar.h | 12 +- drivers/net/ethernet/freescale/gianfar_ethtool.c | 43 +++++-- 3 files changed, 186 insertions(+), 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 710715fcb23d..7f5389c3c0cf 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -907,6 +907,9 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) if (of_find_property(np, "fsl,magic-packet", NULL)) priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET; + if (of_get_property(np, "fsl,wake-on-filer", NULL)) + priv->device_flags |= FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER; + priv->phy_node = of_parse_phandle(np, "phy-handle", 0); /* In the case of a fixed PHY, the DT node associated @@ -1415,8 +1418,14 @@ static int gfar_probe(struct platform_device *ofdev) goto register_fail; } - device_set_wakeup_capable(&dev->dev, priv->device_flags & - FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); + if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) + priv->wol_supported |= GFAR_WOL_MAGIC; + + if ((priv->device_flags & FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER) && + priv->rx_filer_enable) + priv->wol_supported |= GFAR_WOL_FILER_UCAST; + + device_set_wakeup_capable(&ofdev->dev, priv->wol_supported); /* fill out IRQ number and name fields */ for (i = 0; i < priv->num_grps; i++) { @@ -1479,15 +1488,122 @@ static int gfar_remove(struct platform_device *ofdev) #ifdef CONFIG_PM +static void __gfar_filer_disable(struct gfar_private *priv) +{ + struct gfar __iomem *regs = priv->gfargrp[0].regs; + u32 temp; + + temp = gfar_read(®s->rctrl); + temp &= ~(RCTRL_FILREN | RCTRL_PRSDEP_INIT); + gfar_write(®s->rctrl, temp); +} + +static void __gfar_filer_enable(struct gfar_private *priv) +{ + struct gfar __iomem *regs = priv->gfargrp[0].regs; + u32 temp; + + temp = gfar_read(®s->rctrl); + temp |= RCTRL_FILREN | RCTRL_PRSDEP_INIT; + gfar_write(®s->rctrl, temp); +} + +/* Filer rules implementing wol capabilities */ +static void gfar_filer_config_wol(struct gfar_private *priv) +{ + unsigned int i; + u32 rqfcr; + + __gfar_filer_disable(priv); + + /* clear the filer table, reject any packet by default */ + rqfcr = RQFCR_RJE | RQFCR_CMP_MATCH; + for (i = 0; i <= MAX_FILER_IDX; i++) + gfar_write_filer(priv, i, rqfcr, 0); + + i = 0; + if (priv->wol_opts & GFAR_WOL_FILER_UCAST) { + /* unicast packet, accept it */ + struct net_device *ndev = priv->ndev; + /* get the default rx queue index */ + u8 qindex = (u8)priv->gfargrp[0].rx_queue->qindex; + u32 dest_mac_addr = (ndev->dev_addr[0] << 16) | + (ndev->dev_addr[1] << 8) | + ndev->dev_addr[2]; + + rqfcr = (qindex << 10) | RQFCR_AND | + RQFCR_CMP_EXACT | RQFCR_PID_DAH; + + gfar_write_filer(priv, i++, rqfcr, dest_mac_addr); + + dest_mac_addr = (ndev->dev_addr[3] << 16) | + (ndev->dev_addr[4] << 8) | + ndev->dev_addr[5]; + rqfcr = (qindex << 10) | RQFCR_GPI | + RQFCR_CMP_EXACT | RQFCR_PID_DAL; + gfar_write_filer(priv, i++, rqfcr, dest_mac_addr); + } + + __gfar_filer_enable(priv); +} + +static void gfar_filer_restore_table(struct gfar_private *priv) +{ + u32 rqfcr, rqfpr; + unsigned int i; + + __gfar_filer_disable(priv); + + for (i = 0; i <= MAX_FILER_IDX; i++) { + rqfcr = priv->ftp_rqfcr[i]; + rqfpr = priv->ftp_rqfpr[i]; + gfar_write_filer(priv, i, rqfcr, rqfpr); + } + + __gfar_filer_enable(priv); +} + +/* gfar_start() for Rx only and with the FGPI filer interrupt enabled */ +static void gfar_start_wol_filer(struct gfar_private *priv) +{ + struct gfar __iomem *regs = priv->gfargrp[0].regs; + u32 tempval; + int i = 0; + + /* Enable Rx hw queues */ + gfar_write(®s->rqueue, priv->rqueue); + + /* Initialize DMACTRL to have WWR and WOP */ + tempval = gfar_read(®s->dmactrl); + tempval |= DMACTRL_INIT_SETTINGS; + gfar_write(®s->dmactrl, tempval); + + /* Make sure we aren't stopped */ + tempval = gfar_read(®s->dmactrl); + tempval &= ~DMACTRL_GRS; + gfar_write(®s->dmactrl, tempval); + + for (i = 0; i < priv->num_grps; i++) { + regs = priv->gfargrp[i].regs; + /* Clear RHLT, so that the DMA starts polling now */ + gfar_write(®s->rstat, priv->gfargrp[i].rstat); + /* enable the Filer General Purpose Interrupt */ + gfar_write(®s->imask, IMASK_FGPI); + } + + /* Enable Rx DMA */ + tempval = gfar_read(®s->maccfg1); + tempval |= MACCFG1_RX_EN; + gfar_write(®s->maccfg1, tempval); +} + static int gfar_suspend(struct device *dev) { struct gfar_private *priv = dev_get_drvdata(dev); struct net_device *ndev = priv->ndev; struct gfar __iomem *regs = priv->gfargrp[0].regs; u32 tempval; - int magic_packet = priv->wol_en && - (priv->device_flags & - FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); + u16 wol = priv->wol_opts; if (!netif_running(ndev)) return 0; @@ -1499,7 +1615,7 @@ static int gfar_suspend(struct device *dev) gfar_halt(priv); - if (magic_packet) { + if (wol & GFAR_WOL_MAGIC) { /* Enable interrupt on Magic Packet */ gfar_write(®s->imask, IMASK_MAG); @@ -1513,6 +1629,10 @@ static int gfar_suspend(struct device *dev) tempval |= MACCFG1_RX_EN; gfar_write(®s->maccfg1, tempval); + } else if (wol & GFAR_WOL_FILER_UCAST) { + gfar_filer_config_wol(priv); + gfar_start_wol_filer(priv); + } else { phy_stop(priv->phydev); } @@ -1526,18 +1646,22 @@ static int gfar_resume(struct device *dev) struct net_device *ndev = priv->ndev; struct gfar __iomem *regs = priv->gfargrp[0].regs; u32 tempval; - int magic_packet = priv->wol_en && - (priv->device_flags & - FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); + u16 wol = priv->wol_opts; if (!netif_running(ndev)) return 0; - if (magic_packet) { + if (wol & GFAR_WOL_MAGIC) { /* Disable Magic Packet mode */ tempval = gfar_read(®s->maccfg2); tempval &= ~MACCFG2_MPEN; gfar_write(®s->maccfg2, tempval); + + } else if (wol & GFAR_WOL_FILER_UCAST) { + /* need to stop rx only, tx is already down */ + gfar_halt(priv); + gfar_filer_restore_table(priv); + } else { phy_start(priv->phydev); } @@ -1998,6 +2122,8 @@ static int register_grp_irqs(struct gfar_priv_grp *grp) gfar_irq(grp, RX)->irq); goto rx_irq_fail; } + enable_irq_wake(gfar_irq(grp, RX)->irq); + } else { err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt, 0, gfar_irq(grp, TX)->name, grp); @@ -2743,7 +2869,14 @@ irqreturn_t gfar_receive(int irq, void *grp_id) { struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id; unsigned long flags; - u32 imask; + u32 imask, ievent; + + ievent = gfar_read(&grp->regs->ievent); + + if (unlikely(ievent & IEVENT_FGPI)) { + gfar_write(&grp->regs->ievent, IEVENT_FGPI); + return IRQ_HANDLED; + } if (likely(napi_schedule_prep(&grp->napi_rx))) { spin_lock_irqsave(&grp->grplock, flags); diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index 8c1994856e93..f266b20f9ef5 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -340,6 +340,7 @@ extern const char gfar_driver_version[]; #define IEVENT_MAG 0x00000800 #define IEVENT_GRSC 0x00000100 #define IEVENT_RXF0 0x00000080 +#define IEVENT_FGPI 0x00000010 #define IEVENT_FIR 0x00000008 #define IEVENT_FIQ 0x00000004 #define IEVENT_DPE 0x00000002 @@ -372,6 +373,7 @@ extern const char gfar_driver_version[]; #define IMASK_MAG 0x00000800 #define IMASK_GRSC 0x00000100 #define IMASK_RXFEN0 0x00000080 +#define IMASK_FGPI 0x00000010 #define IMASK_FIR 0x00000008 #define IMASK_FIQ 0x00000004 #define IMASK_DPE 0x00000002 @@ -540,6 +542,9 @@ extern const char gfar_driver_version[]; #define GFAR_INT_NAME_MAX (IFNAMSIZ + 6) /* '_g#_xx' */ +#define GFAR_WOL_MAGIC 0x00000001 +#define GFAR_WOL_FILER_UCAST 0x00000002 + struct txbd8 { union { @@ -917,6 +922,7 @@ struct gfar { #define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200 #define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400 #define FSL_GIANFAR_DEV_HAS_TIMER 0x00000800 +#define FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER 0x00001000 #if (MAXGROUPS == 2) #define DEFAULT_MAPPING 0xAA @@ -1161,8 +1167,6 @@ struct gfar_private { extended_hash:1, bd_stash_en:1, rx_filer_enable:1, - /* Wake-on-LAN enabled */ - wol_en:1, /* Enable priorty based Tx scheduling in Hw */ prio_sched_en:1, /* Flow control flags */ @@ -1191,6 +1195,10 @@ struct gfar_private { u32 __iomem *hash_regs[16]; int hash_width; + /* wake-on-lan settings */ + u16 wol_opts; + u16 wol_supported; + /*Filer table*/ unsigned int ftp_rqfpr[MAX_FILER_IDX + 1]; unsigned int ftp_rqfcr[MAX_FILER_IDX + 1]; diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index 6bdc89179b72..fb7f8d67aef4 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -644,28 +644,49 @@ static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct gfar_private *priv = netdev_priv(dev); - if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) { - wol->supported = WAKE_MAGIC; - wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0; - } else { - wol->supported = wol->wolopts = 0; - } + wol->supported = 0; + wol->wolopts = 0; + + if (priv->wol_supported & GFAR_WOL_MAGIC) + wol->supported |= WAKE_MAGIC; + + if (priv->wol_supported & GFAR_WOL_FILER_UCAST) + wol->supported |= WAKE_UCAST; + + if (priv->wol_opts & GFAR_WOL_MAGIC) + wol->wolopts |= WAKE_MAGIC; + + if (priv->wol_opts & GFAR_WOL_FILER_UCAST) + wol->wolopts |= WAKE_UCAST; } static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct gfar_private *priv = netdev_priv(dev); + u16 wol_opts = 0; + int err; - if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) && - wol->wolopts != 0) + if (!priv->wol_supported && wol->wolopts) return -EINVAL; - if (wol->wolopts & ~WAKE_MAGIC) + if (wol->wolopts & ~(WAKE_MAGIC | WAKE_UCAST)) return -EINVAL; - device_set_wakeup_enable(&dev->dev, wol->wolopts & WAKE_MAGIC); + if (wol->wolopts & WAKE_MAGIC) { + wol_opts |= GFAR_WOL_MAGIC; + } else { + if (wol->wolopts & WAKE_UCAST) + wol_opts |= GFAR_WOL_FILER_UCAST; + } + + wol_opts &= priv->wol_supported; + priv->wol_opts = 0; + + err = device_set_wakeup_enable(priv->dev, wol_opts); + if (err) + return err; - priv->wol_en = !!device_may_wakeup(&dev->dev); + priv->wol_opts = wol_opts; return 0; } -- cgit v1.2.3 From 6e2895a8e3824eb5611c97a015a3b6d678b4503e Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 5 Oct 2015 08:51:23 -0700 Subject: net: Rename FLOWI_FLAG_VRFSRC to FLOWI_FLAG_L3MDEV_SRC Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 474396353e7f..4fd5af1acff0 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -208,7 +208,7 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb, .flowi4_oif = vrf_dev->ifindex, .flowi4_iif = LOOPBACK_IFINDEX, .flowi4_tos = RT_TOS(ip4h->tos), - .flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_VRFSRC | + .flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_L3MDEV_SRC | FLOWI_FLAG_SKIP_NH_OIF, .daddr = ip4h->daddr, }; @@ -545,7 +545,7 @@ static struct rtable *vrf_get_rtable(const struct net_device *dev, { struct rtable *rth = NULL; - if (!(fl4->flowi4_flags & FLOWI_FLAG_VRFSRC)) { + if (!(fl4->flowi4_flags & FLOWI_FLAG_L3MDEV_SRC)) { struct net_vrf *vrf = netdev_priv(dev); rth = vrf->rth; -- cgit v1.2.3 From fee6d4c777a125e56de9370db3b2bf359bf958d6 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 5 Oct 2015 08:51:24 -0700 Subject: net: Add netif_is_l3_slave IPv6 addrconf keys off of IFF_SLAVE so can not use it for L3 slave. Add a new private flag and add netif_is_l3_slave function for checking it. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 4fd5af1acff0..8713317eed86 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -39,8 +39,6 @@ #define DRV_NAME "vrf" #define DRV_VERSION "1.0" -#define vrf_is_slave(dev) ((dev)->flags & IFF_SLAVE) - #define vrf_master_get_rcu(dev) \ ((struct net_device *)rcu_dereference(dev->rx_handler_data)) @@ -433,7 +431,7 @@ static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev) if (ret < 0) goto out_unregister; - port_dev->flags |= IFF_SLAVE; + port_dev->priv_flags |= IFF_L3MDEV_SLAVE; __vrf_insert_slave(queue, slave); cycle_netdev(port_dev); @@ -448,7 +446,7 @@ out_fail: static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev) { - if (netif_is_l3_master(port_dev) || vrf_is_slave(port_dev)) + if (netif_is_l3_master(port_dev) || netif_is_l3_slave(port_dev)) return -EINVAL; return do_vrf_add_slave(dev, port_dev); @@ -462,7 +460,7 @@ static int do_vrf_del_slave(struct net_device *dev, struct net_device *port_dev) struct slave *slave; netdev_upper_dev_unlink(port_dev, dev); - port_dev->flags &= ~IFF_SLAVE; + port_dev->priv_flags &= ~IFF_L3MDEV_SLAVE; netdev_rx_handler_unregister(port_dev); @@ -672,7 +670,7 @@ static int vrf_device_event(struct notifier_block *unused, if (event == NETDEV_UNREGISTER) { struct net_device *vrf_dev; - if (!vrf_is_slave(dev) || netif_is_l3_master(dev)) + if (!netif_is_l3_slave(dev)) goto out; vrf_dev = netdev_master_upper_dev_get(dev); -- cgit v1.2.3 From 8cbb512c923d5f695ff6265b2b741b1718e3b444 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 5 Oct 2015 08:51:26 -0700 Subject: net: Add source address lookup op for VRF Add operation to l3mdev to lookup source address for a given flow. Add support for the operation to VRF driver and convert existing IPv4 hooks to use the new lookup. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 8713317eed86..64499766e00f 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -36,6 +36,9 @@ #include #include +#define RT_FL_TOS(oldflp4) \ + ((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)) + #define DRV_NAME "vrf" #define DRV_VERSION "1.0" @@ -553,9 +556,41 @@ static struct rtable *vrf_get_rtable(const struct net_device *dev, return rth; } +/* called under rcu_read_lock */ +static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4) +{ + struct fib_result res = { .tclassid = 0 }; + struct net *net = dev_net(dev); + u32 orig_tos = fl4->flowi4_tos; + u8 flags = fl4->flowi4_flags; + u8 scope = fl4->flowi4_scope; + u8 tos = RT_FL_TOS(fl4); + + if (unlikely(!fl4->daddr)) + return; + + fl4->flowi4_flags |= FLOWI_FLAG_SKIP_NH_OIF; + fl4->flowi4_iif = LOOPBACK_IFINDEX; + fl4->flowi4_tos = tos & IPTOS_RT_MASK; + fl4->flowi4_scope = ((tos & RTO_ONLINK) ? + RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); + + if (!fib_lookup(net, fl4, &res, 0)) { + if (res.type == RTN_LOCAL) + fl4->saddr = res.fi->fib_prefsrc ? : fl4->daddr; + else + fib_select_path(net, &res, fl4, -1); + } + + fl4->flowi4_flags = flags; + fl4->flowi4_tos = orig_tos; + fl4->flowi4_scope = scope; +} + static const struct l3mdev_ops vrf_l3mdev_ops = { .l3mdev_fib_table = vrf_fib_table, .l3mdev_get_rtable = vrf_get_rtable, + .l3mdev_get_saddr = vrf_get_saddr, }; static void vrf_get_drvinfo(struct net_device *dev, -- cgit v1.2.3 From 22e05bd6f7949d3e638c9f4697a2198a19fff312 Mon Sep 17 00:00:00 2001 From: Paul M Stillwell Jr Date: Wed, 26 Aug 2015 15:14:07 -0400 Subject: i40e: Increase the amount of time we wait for reset to be done In some rare cases the reset can take longer to complete so increase the amount of time we wait. Change-ID: Ib5628ec54b526a811ee33d1214fe763226406671 Signed-off-by: Paul M Stillwell Jr Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 683371763293..1e81f4e3b205 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1256,7 +1256,7 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw) grst_del = (rd32(hw, I40E_GLGEN_RSTCTL) & I40E_GLGEN_RSTCTL_GRSTDEL_MASK) >> I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT; - for (cnt = 0; cnt < grst_del + 2; cnt++) { + for (cnt = 0; cnt < grst_del + 10; cnt++) { reg = rd32(hw, I40E_GLGEN_RSTAT); if (!(reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK)) break; -- cgit v1.2.3 From 1d5109d18757d8d6450905275bf362819781368c Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 26 Aug 2015 15:14:08 -0400 Subject: i40e: enable WoL operation if config bit show WoL capable The driver was disabling Wake-on-LAN by default and waiting for the user to expressly turn it on. This patch has the driver turning on WoL from the start if enabled in the hardware config, which matches the behavior of our other drivers. Change-ID: I43faedb907f8ba4d1a61b72a7c86072b97af12b1 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 5646ee885db2..7fc5e2c28cdb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -9947,6 +9947,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct i40e_pf *pf; struct i40e_hw *hw; static u16 pfs_found; + u16 wol_nvm_bits; u16 link_status; int err = 0; u32 len; @@ -10163,8 +10164,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) clear_bit(__I40E_SERVICE_SCHED, &pf->state); pf->flags |= I40E_FLAG_NEED_LINK_UPDATE; - /* WoL defaults to disabled */ - pf->wol_en = false; + /* NVM bit on means WoL disabled for the port */ + i40e_read_nvm_word(hw, I40E_SR_NVM_WAKE_ON_LAN, &wol_nvm_bits); + if ((1 << hw->port) & wol_nvm_bits || hw->partition_id != 1) + pf->wol_en = false; + else + pf->wol_en = true; device_set_wakeup_enable(&pf->pdev->dev, pf->wol_en); /* set up the main switch operations */ -- cgit v1.2.3 From 0325fca7577c5157da2cdf064fc3e8d38242e47c Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 26 Aug 2015 15:14:09 -0400 Subject: i40e: stop VF rings Explicitly stop the rings belonging to each VF when disabling SR-IOV. Even though the VFs were gone, and the associated VSIs were removed, the rings were not stopped, and in some circumstances the hardware would continue to access the memory formerly used by the rings, causing memory corruption or DMAR errors, both of which would lead to general malaise of the kernel. To relieve this condition, explicitly stop all the rings associated with each VF before releasing its resources. Change-ID: I78c05d562c66e7b594b7e48d67860f49b3e5b6ec Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index b148694f8e11..0545e3f80e7a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -872,6 +872,11 @@ void i40e_free_vfs(struct i40e_pf *pf) i40e_vsi_control_rings(pf->vsi[pf->vf[i].lan_vsi_idx], false); + for (i = 0; i < pf->num_alloc_vfs; i++) + if (test_bit(I40E_VF_STAT_INIT, &pf->vf[i].vf_states)) + i40e_vsi_control_rings(pf->vsi[pf->vf[i].lan_vsi_idx], + false); + /* Disable IOV before freeing resources. This lets any VF drivers * running in the host get themselves cleaned up before we yank * the carpet out from underneath their feet. -- cgit v1.2.3 From bc5166b908aaa126d524b84c767323b75c17bdee Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 26 Aug 2015 15:14:10 -0400 Subject: i40e/i40evf: add driver support for new device ids Early addition of new a device id. Change-ID: I61a8c8556fdf4f5714be4e4089689e374f30293c Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + drivers/net/ethernet/intel/i40e/i40e_type.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_common.c | 1 + drivers/net/ethernet/intel/i40evf/i40e_type.h | 1 + 6 files changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 1e81f4e3b205..7a70abcafbbb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -51,6 +51,7 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw) case I40E_DEV_ID_QSFP_B: case I40E_DEV_ID_QSFP_C: case I40E_DEV_ID_10G_BASE_T: + case I40E_DEV_ID_10G_BASE_T4: case I40E_DEV_ID_20G_KR2: case I40E_DEV_ID_20G_KR2_A: hw->mac.type = I40E_MAC_XL710; diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 1345de2ef614..928bd5abbaed 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -425,6 +425,7 @@ static void i40e_get_settings_link_down(struct i40e_hw *hw, ecmd->advertising = ADVERTISED_10000baseKR_Full; break; case I40E_DEV_ID_10G_BASE_T: + case I40E_DEV_ID_10G_BASE_T4: ecmd->supported = SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 7fc5e2c28cdb..19eb14d488c5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -75,6 +75,7 @@ static const struct pci_device_id i40e_pci_tbl[] = { {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_B), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_C), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_X722), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_1G_BASE_T_X722), 0}, diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index c5b6a65f520f..34720e07f990 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -46,6 +46,7 @@ #define I40E_DEV_ID_10G_BASE_T 0x1586 #define I40E_DEV_ID_20G_KR2 0x1587 #define I40E_DEV_ID_20G_KR2_A 0x1588 +#define I40E_DEV_ID_10G_BASE_T4 0x1589 #define I40E_DEV_ID_VF 0x154C #define I40E_DEV_ID_VF_HV 0x1571 #define I40E_DEV_ID_SFP_X722 0x37D0 diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c index 1950db10a414..96e48ee8ab38 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_common.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c @@ -51,6 +51,7 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw) case I40E_DEV_ID_QSFP_B: case I40E_DEV_ID_QSFP_C: case I40E_DEV_ID_10G_BASE_T: + case I40E_DEV_ID_10G_BASE_T4: case I40E_DEV_ID_20G_KR2: case I40E_DEV_ID_20G_KR2_A: hw->mac.type = I40E_MAC_XL710; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 37bacc34fb84..bbb388660aa7 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -46,6 +46,7 @@ #define I40E_DEV_ID_10G_BASE_T 0x1586 #define I40E_DEV_ID_20G_KR2 0x1587 #define I40E_DEV_ID_20G_KR2_A 0x1588 +#define I40E_DEV_ID_10G_BASE_T4 0x1589 #define I40E_DEV_ID_VF 0x154C #define I40E_DEV_ID_VF_HV 0x1571 #define I40E_DEV_ID_SFP_X722 0x37D0 -- cgit v1.2.3 From df08fd4dbcc95cbc5a35745b6a77a9df0dc5776f Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 26 Aug 2015 15:14:11 -0400 Subject: i40e/i40evf: fix a potential type compare issue Rework an if expression to assure there is no type compare problem between a size and a possible negative number. Change-ID: I4921fcc96abfcf69490efce020a9e4007f251c99 Reported-by: Helin Zhang Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.h | 3 +-- drivers/net/ethernet/intel/i40evf/i40e_adminq.h | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.h b/drivers/net/ethernet/intel/i40e/i40e_adminq.h index ca81b0b9db97..12fbbddea299 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.h @@ -144,8 +144,7 @@ static inline int i40e_aq_rc_to_posix(int aq_ret, int aq_rc) if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT) return -EAGAIN; - if (aq_rc >= (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0])) || - aq_rc < 0) + if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0])))) return -ERANGE; return aq_to_posix[aq_rc]; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h index e62e951cf208..a3eae5d9a2bd 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.h @@ -144,8 +144,7 @@ static inline int i40e_aq_rc_to_posix(int aq_ret, int aq_rc) if (aq_ret == I40E_ERR_ADMIN_QUEUE_TIMEOUT) return -EAGAIN; - if (aq_rc >= (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0])) || - aq_rc < 0) + if (!((u32)aq_rc < (sizeof(aq_to_posix) / sizeof((aq_to_posix)[0])))) return -ERANGE; return aq_to_posix[aq_rc]; -- cgit v1.2.3 From 725821f340184fcdd35dbd369c5058eec8a30fcb Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 26 Aug 2015 15:14:12 -0400 Subject: i40e: fix bad CEE status shift value Fix a shift value that was wrong, ending up with a bad bitmask. Also add a blank line between two sets of #defines for better readability. Change-ID: I3e41fa2a2ab904d3a4e6cbf13972ab0036a10601 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index b840fabe3997..785b3dbd22ca 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -2062,6 +2062,7 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_start); #define I40E_AQC_CEE_APP_ISCSI_MASK (0x7 << I40E_AQC_CEE_APP_ISCSI_SHIFT) #define I40E_AQC_CEE_APP_FIP_SHIFT 0x8 #define I40E_AQC_CEE_APP_FIP_MASK (0x7 << I40E_AQC_CEE_APP_FIP_SHIFT) + #define I40E_AQC_CEE_PG_STATUS_SHIFT 0x0 #define I40E_AQC_CEE_PG_STATUS_MASK (0x7 << I40E_AQC_CEE_PG_STATUS_SHIFT) #define I40E_AQC_CEE_PFC_STATUS_SHIFT 0x3 @@ -2070,7 +2071,7 @@ I40E_CHECK_CMD_LENGTH(i40e_aqc_lldp_start); #define I40E_AQC_CEE_APP_STATUS_MASK (0x7 << I40E_AQC_CEE_APP_STATUS_SHIFT) #define I40E_AQC_CEE_FCOE_STATUS_SHIFT 0x8 #define I40E_AQC_CEE_FCOE_STATUS_MASK (0x7 << I40E_AQC_CEE_FCOE_STATUS_SHIFT) -#define I40E_AQC_CEE_ISCSI_STATUS_SHIFT 0xA +#define I40E_AQC_CEE_ISCSI_STATUS_SHIFT 0xB #define I40E_AQC_CEE_ISCSI_STATUS_MASK (0x7 << I40E_AQC_CEE_ISCSI_STATUS_SHIFT) #define I40E_AQC_CEE_FIP_STATUS_SHIFT 0x10 #define I40E_AQC_CEE_FIP_STATUS_MASK (0x7 << I40E_AQC_CEE_FIP_STATUS_SHIFT) -- cgit v1.2.3 From 21364bcfc7810894114ab18f5335745e374cc2ea Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 26 Aug 2015 15:14:13 -0400 Subject: i40e: make i40e_init_pf_fcoe to void i40e_init_pf_fcoe() didn't return anything except 0, it prints enough error info already, and no driver logic depends on the return value, so this can be void. Change-ID: Ie6afad849857d87a7064c42c3cce14c74c2f29d8 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 +- drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 10 ++++------ drivers/net/ethernet/intel/i40e/i40e_main.c | 8 ++------ 3 files changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index f6d97ad811bb..44837ecd82f5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -740,7 +740,7 @@ int i40e_fcoe_vsi_init(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt); u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf); void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi); void i40e_fcoe_vsi_setup(struct i40e_pf *pf); -int i40e_init_pf_fcoe(struct i40e_pf *pf); +void i40e_init_pf_fcoe(struct i40e_pf *pf); int i40e_fcoe_setup_ddp_resources(struct i40e_vsi *vsi); void i40e_fcoe_free_ddp_resources(struct i40e_vsi *vsi); int i40e_fcoe_handle_offload(struct i40e_ring *rx_ring, diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index 5ea75dd537d6..2398d9bd08d8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -272,10 +272,8 @@ out: /** * i40e_fcoe_sw_init - sets up the HW for FCoE * @pf: pointer to PF - * - * Returns 0 if FCoE is supported otherwise the error code **/ -int i40e_init_pf_fcoe(struct i40e_pf *pf) +void i40e_init_pf_fcoe(struct i40e_pf *pf) { struct i40e_hw *hw = &pf->hw; u32 val; @@ -287,13 +285,13 @@ int i40e_init_pf_fcoe(struct i40e_pf *pf) if (!pf->hw.func_caps.fcoe) { dev_info(&pf->pdev->dev, "FCoE capability is disabled\n"); - return 0; + return; } if (!pf->hw.func_caps.dcb) { dev_warn(&pf->pdev->dev, "Hardware is not DCB capable not enabling FCoE.\n"); - return 0; + return; } /* enable FCoE hash filter */ @@ -326,7 +324,7 @@ int i40e_init_pf_fcoe(struct i40e_pf *pf) wr32(hw, I40E_GLFCOE_RCTL, val); dev_info(&pf->pdev->dev, "FCoE is supported.\n"); - return 0; + return; } /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 19eb14d488c5..0ef6a153b134 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6573,9 +6573,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) } #endif /* CONFIG_I40E_DCB */ #ifdef I40E_FCOE - ret = i40e_init_pf_fcoe(pf); - if (ret) - dev_info(&pf->pdev->dev, "init_pf_fcoe failed: %d\n", ret); + i40e_init_pf_fcoe(pf); #endif /* do basic switch setup */ @@ -7976,9 +7974,7 @@ static int i40e_sw_init(struct i40e_pf *pf) } #ifdef I40E_FCOE - err = i40e_init_pf_fcoe(pf); - if (err) - dev_info(&pf->pdev->dev, "init_pf_fcoe failed: %d\n", err); + i40e_init_pf_fcoe(pf); #endif /* I40E_FCOE */ #ifdef CONFIG_PCI_IOV -- cgit v1.2.3 From 9e1c26e35030aa56057a69514acb17da5e81eb16 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 26 Aug 2015 15:14:14 -0400 Subject: i40e/i40evf: assure clean asq status report There was a possibility where the asq_last_status could get through without update and thus report a previous error. I don't think we've actually seen this happen, but this patch will help make sure it doesn't. Change-ID: I9e33927052a5ee6ea21f80b66d4c4b76c2760b17 Signed-off-by: Shannon Nelson Signed-off-by: Christopher Pau Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 2 ++ drivers/net/ethernet/intel/i40evf/i40e_adminq.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 34a64e05c55c..287cb8def7cd 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -756,6 +756,8 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, goto asq_send_command_error; } + hw->aq.asq_last_status = I40E_AQ_RC_OK; + val = rd32(hw, hw->aq.asq.head); if (val >= hw->aq.num_asq_entries) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c index c7f59e002cb6..c5cf886cdd08 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c @@ -696,6 +696,8 @@ i40e_status i40evf_asq_send_command(struct i40e_hw *hw, goto asq_send_command_error; } + hw->aq.asq_last_status = I40E_AQ_RC_OK; + val = rd32(hw, hw->aq.asq.head); if (val >= hw->aq.num_asq_entries) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, -- cgit v1.2.3 From fba52e21e5cad1347255d0d3600f7e4df6e69435 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Wed, 26 Aug 2015 15:14:15 -0400 Subject: i40e: Fix for truncated interrupt name This patch extends the size of the text available for the interrupt names. Without this patch, all the descriptive data available for the Flow Director interrupts is truncated. Change-ID: I2ac458f23ac3b4ea8f1edf73edc283b1d3704c7f Signed-off-by: Carolyn Wyborny Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 44837ecd82f5..a54577af4884 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -97,7 +97,7 @@ #define I40E_MAX_USER_PRIORITY 8 #define I40E_DEFAULT_MSG_ENABLE 4 #define I40E_QUEUE_WAIT_RETRY_LIMIT 10 -#define I40E_INT_NAME_STR_LEN (IFNAMSIZ + 9) +#define I40E_INT_NAME_STR_LEN (IFNAMSIZ + 16) /* Ethtool Private Flags */ #define I40E_PRIV_FLAGS_NPAR_FLAG BIT(0) -- cgit v1.2.3 From 0002e1189b594d462c7a93417f5ac8bbc22bd768 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Wed, 26 Aug 2015 15:14:16 -0400 Subject: i40e: Never let speed get set to 0 in get_settings In ethtool, there is a possibility of speed getting set to 0 if advertise is set to 0 (which it is when autoneg is disabled). We never want this to happen as the firmware will actually attempt to set the speed to 0 sending link down, so add an extra check to make sure this doesn't happen. Change-ID: I62e0eeee2cbf043d8e6f5c9c9f0b92794e877f01 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 928bd5abbaed..930369c4882b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -666,6 +666,13 @@ static int i40e_set_settings(struct net_device *netdev, advertise & ADVERTISED_40000baseLR4_Full) config.link_speed |= I40E_LINK_SPEED_40GB; + /* If speed didn't get set, set it to what it currently is. + * This is needed because if advertise is 0 (as it is when autoneg + * is disabled) then speed won't get set. + */ + if (!config.link_speed) + config.link_speed = abilities.link_speed; + if (change || (abilities.link_speed != config.link_speed)) { /* copy over the rest of the abilities */ config.phy_type = abilities.phy_type; -- cgit v1.2.3 From fb43201f150300fa2c0215f00418eda9143cdab1 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 26 Aug 2015 15:14:17 -0400 Subject: i40e/i40evf: give up the __func__ During early development, we added the function name to all of the error strings to make debugging simpler. Now that we've released the driver, our users should have more comprehensible error messages. So tear the roof off and give up the __func__. Ow. Change-ID: I7e1766252c7a032b9af6520da6aff536bdfd533c Signed-off-by: Shannon Nelson Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c | 5 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 40 ++++++--------- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 9 ++-- .../net/ethernet/intel/i40evf/i40evf_virtchnl.c | 59 ++++++++++------------ 4 files changed, 47 insertions(+), 66 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c index 1c51f736a8d0..dbadad74e1c0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c @@ -240,9 +240,8 @@ static void i40e_dcbnl_del_app(struct i40e_pf *pf, if (pf->vsi[v] && pf->vsi[v]->netdev) { err = i40e_dcbnl_vsi_del_app(pf->vsi[v], app); if (err) - dev_info(&pf->pdev->dev, "%s: Failed deleting app for VSI seid=%d err=%d sel=%d proto=0x%x prio=%d\n", - __func__, pf->vsi[v]->seid, - err, app->selector, + dev_info(&pf->pdev->dev, "Failed deleting app for VSI seid=%d err=%d sel=%d proto=0x%x prio=%d\n", + pf->vsi[v]->seid, err, app->selector, app->protocolid, app->priority); } } diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 0ef6a153b134..1fa1ebab9e92 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3156,8 +3156,7 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename) q_vector); if (err) { dev_info(&pf->pdev->dev, - "%s: request_irq failed, error: %d\n", - __func__, err); + "MSIX request_irq failed, error: %d\n", err); goto free_queue_irqs; } /* assign the mask for this irq */ @@ -3681,9 +3680,8 @@ static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable) ret = i40e_pf_txq_wait(pf, pf_q, enable); if (ret) { dev_info(&pf->pdev->dev, - "%s: VSI seid %d Tx ring %d %sable timeout\n", - __func__, vsi->seid, pf_q, - (enable ? "en" : "dis")); + "VSI seid %d Tx ring %d %sable timeout\n", + vsi->seid, pf_q, (enable ? "en" : "dis")); break; } } @@ -3759,9 +3757,8 @@ static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable) ret = i40e_pf_rxq_wait(pf, pf_q, enable); if (ret) { dev_info(&pf->pdev->dev, - "%s: VSI seid %d Rx ring %d %sable timeout\n", - __func__, vsi->seid, pf_q, - (enable ? "en" : "dis")); + "VSI seid %d Rx ring %d %sable timeout\n", + vsi->seid, pf_q, (enable ? "en" : "dis")); break; } } @@ -4056,8 +4053,7 @@ static void i40e_quiesce_vsi(struct i40e_vsi *vsi) if ((test_bit(__I40E_PORT_TX_SUSPENDED, &vsi->back->state)) && vsi->type == I40E_VSI_FCOE) { dev_dbg(&vsi->back->pdev->dev, - "%s: VSI seid %d skipping FCoE VSI disable\n", - __func__, vsi->seid); + "VSI seid %d skipping FCoE VSI disable\n", vsi->seid); return; } @@ -4131,8 +4127,8 @@ static int i40e_vsi_wait_txq_disabled(struct i40e_vsi *vsi) ret = i40e_pf_txq_wait(pf, pf_q, false); if (ret) { dev_info(&pf->pdev->dev, - "%s: VSI seid %d Tx ring %d disable timeout\n", - __func__, vsi->seid, pf_q); + "VSI seid %d Tx ring %d disable timeout\n", + vsi->seid, pf_q); return ret; } } @@ -5423,8 +5419,7 @@ bool i40e_dcb_need_reconfig(struct i40e_pf *pf, dev_dbg(&pf->pdev->dev, "APP Table change detected.\n"); } - dev_dbg(&pf->pdev->dev, "%s: need_reconfig=%d\n", __func__, - need_reconfig); + dev_dbg(&pf->pdev->dev, "dcb need_reconfig=%d\n", need_reconfig); return need_reconfig; } @@ -5451,16 +5446,14 @@ static int i40e_handle_lldp_event(struct i40e_pf *pf, /* Ignore if event is not for Nearest Bridge */ type = ((mib->type >> I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT) & I40E_AQ_LLDP_BRIDGE_TYPE_MASK); - dev_dbg(&pf->pdev->dev, - "%s: LLDP event mib bridge type 0x%x\n", __func__, type); + dev_dbg(&pf->pdev->dev, "LLDP event mib bridge type 0x%x\n", type); if (type != I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE) return ret; /* Check MIB Type and return if event for Remote MIB update */ type = mib->type & I40E_AQ_LLDP_MIB_TYPE_MASK; dev_dbg(&pf->pdev->dev, - "%s: LLDP event mib type %s\n", __func__, - type ? "remote" : "local"); + "LLDP event mib type %s\n", type ? "remote" : "local"); if (type == I40E_AQ_LLDP_MIB_REMOTE) { /* Update the remote cached instance and return */ ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE, @@ -9054,8 +9047,7 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, if (veb) { if (vsi->seid != pf->vsi[pf->lan_vsi]->seid) { dev_info(&vsi->back->pdev->dev, - "%s: New VSI creation error, uplink seid of LAN VSI expected.\n", - __func__); + "New VSI creation error, uplink seid of LAN VSI expected.\n"); return NULL; } /* We come up by default in VEPA mode if SRIOV is not @@ -10498,7 +10490,7 @@ static pci_ers_result_t i40e_pci_error_slot_reset(struct pci_dev *pdev) int err; u32 reg; - dev_info(&pdev->dev, "%s\n", __func__); + dev_dbg(&pdev->dev, "%s\n", __func__); if (pci_enable_device_mem(pdev)) { dev_info(&pdev->dev, "Cannot re-enable PCI device after reset.\n"); @@ -10538,7 +10530,7 @@ static void i40e_pci_error_resume(struct pci_dev *pdev) { struct i40e_pf *pf = pci_get_drvdata(pdev); - dev_info(&pdev->dev, "%s\n", __func__); + dev_dbg(&pdev->dev, "%s\n", __func__); if (test_bit(__I40E_SUSPENDED, &pf->state)) return; @@ -10630,9 +10622,7 @@ static int i40e_resume(struct pci_dev *pdev) err = pci_enable_device_mem(pdev); if (err) { - dev_err(&pdev->dev, - "%s: Cannot enable PCI device from suspend\n", - __func__); + dev_err(&pdev->dev, "Cannot enable PCI device from suspend\n"); return err; } pci_set_master(pdev); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 76df6b2aa74a..f3a61c49ee32 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -489,8 +489,7 @@ i40evf_request_traffic_irqs(struct i40evf_adapter *adapter, char *basename) q_vector); if (err) { dev_info(&adapter->pdev->dev, - "%s: request_irq failed, error: %d\n", - __func__, err); + "Request_irq failed, error: %d\n", err); goto free_queue_irqs; } /* assign the mask for this irq */ @@ -1853,8 +1852,7 @@ static int i40evf_setup_all_tx_resources(struct i40evf_adapter *adapter) if (!err) continue; dev_err(&adapter->pdev->dev, - "%s: Allocation for Tx Queue %u failed\n", - __func__, i); + "Allocation for Tx Queue %u failed\n", i); break; } @@ -1881,8 +1879,7 @@ static int i40evf_setup_all_rx_resources(struct i40evf_adapter *adapter) if (!err) continue; dev_err(&adapter->pdev->dev, - "%s: Allocation for Rx Queue %u failed\n", - __func__, i); + "Allocation for Rx Queue %u failed\n", i); break; } return err; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index fbf2a1c86c1c..4f056efecba4 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -234,8 +234,8 @@ void i40evf_configure_queues(struct i40evf_adapter *adapter) if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ - dev_err(&adapter->pdev->dev, "%s: command %d pending\n", - __func__, adapter->current_op); + dev_err(&adapter->pdev->dev, "Cannot configure queues, command %d pending\n", + adapter->current_op); return; } adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES; @@ -288,8 +288,8 @@ void i40evf_enable_queues(struct i40evf_adapter *adapter) if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ - dev_err(&adapter->pdev->dev, "%s: command %d pending\n", - __func__, adapter->current_op); + dev_err(&adapter->pdev->dev, "Cannot enable queues, command %d pending\n", + adapter->current_op); return; } adapter->current_op = I40E_VIRTCHNL_OP_ENABLE_QUEUES; @@ -313,8 +313,8 @@ void i40evf_disable_queues(struct i40evf_adapter *adapter) if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ - dev_err(&adapter->pdev->dev, "%s: command %d pending\n", - __func__, adapter->current_op); + dev_err(&adapter->pdev->dev, "Cannot disable queues, command %d pending\n", + adapter->current_op); return; } adapter->current_op = I40E_VIRTCHNL_OP_DISABLE_QUEUES; @@ -341,8 +341,8 @@ void i40evf_map_queues(struct i40evf_adapter *adapter) if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ - dev_err(&adapter->pdev->dev, "%s: command %d pending\n", - __func__, adapter->current_op); + dev_err(&adapter->pdev->dev, "Cannot map queues to vectors, command %d pending\n", + adapter->current_op); return; } adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP; @@ -393,8 +393,8 @@ void i40evf_add_ether_addrs(struct i40evf_adapter *adapter) if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ - dev_err(&adapter->pdev->dev, "%s: command %d pending\n", - __func__, adapter->current_op); + dev_err(&adapter->pdev->dev, "Cannot add filters, command %d pending\n", + adapter->current_op); return; } list_for_each_entry(f, &adapter->mac_filter_list, list) { @@ -410,8 +410,7 @@ void i40evf_add_ether_addrs(struct i40evf_adapter *adapter) len = sizeof(struct i40e_virtchnl_ether_addr_list) + (count * sizeof(struct i40e_virtchnl_ether_addr)); if (len > I40EVF_MAX_AQ_BUF_SIZE) { - dev_warn(&adapter->pdev->dev, "%s: Too many MAC address changes in one request\n", - __func__); + dev_warn(&adapter->pdev->dev, "Too many add MAC changes in one request\n"); count = (I40EVF_MAX_AQ_BUF_SIZE - sizeof(struct i40e_virtchnl_ether_addr_list)) / sizeof(struct i40e_virtchnl_ether_addr); @@ -453,8 +452,8 @@ void i40evf_del_ether_addrs(struct i40evf_adapter *adapter) if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ - dev_err(&adapter->pdev->dev, "%s: command %d pending\n", - __func__, adapter->current_op); + dev_err(&adapter->pdev->dev, "Cannot remove filters, command %d pending\n", + adapter->current_op); return; } list_for_each_entry(f, &adapter->mac_filter_list, list) { @@ -470,8 +469,7 @@ void i40evf_del_ether_addrs(struct i40evf_adapter *adapter) len = sizeof(struct i40e_virtchnl_ether_addr_list) + (count * sizeof(struct i40e_virtchnl_ether_addr)); if (len > I40EVF_MAX_AQ_BUF_SIZE) { - dev_warn(&adapter->pdev->dev, "%s: Too many MAC address changes in one request\n", - __func__); + dev_warn(&adapter->pdev->dev, "Too many delete MAC changes in one request\n"); count = (I40EVF_MAX_AQ_BUF_SIZE - sizeof(struct i40e_virtchnl_ether_addr_list)) / sizeof(struct i40e_virtchnl_ether_addr); @@ -513,8 +511,8 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter) if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ - dev_err(&adapter->pdev->dev, "%s: command %d pending\n", - __func__, adapter->current_op); + dev_err(&adapter->pdev->dev, "Cannot add VLANs, command %d pending\n", + adapter->current_op); return; } @@ -531,8 +529,7 @@ void i40evf_add_vlans(struct i40evf_adapter *adapter) len = sizeof(struct i40e_virtchnl_vlan_filter_list) + (count * sizeof(u16)); if (len > I40EVF_MAX_AQ_BUF_SIZE) { - dev_warn(&adapter->pdev->dev, "%s: Too many VLAN changes in one request\n", - __func__); + dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n"); count = (I40EVF_MAX_AQ_BUF_SIZE - sizeof(struct i40e_virtchnl_vlan_filter_list)) / sizeof(u16); @@ -572,8 +569,8 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter) if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ - dev_err(&adapter->pdev->dev, "%s: command %d pending\n", - __func__, adapter->current_op); + dev_err(&adapter->pdev->dev, "Cannot remove VLANs, command %d pending\n", + adapter->current_op); return; } @@ -590,8 +587,7 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter) len = sizeof(struct i40e_virtchnl_vlan_filter_list) + (count * sizeof(u16)); if (len > I40EVF_MAX_AQ_BUF_SIZE) { - dev_warn(&adapter->pdev->dev, "%s: Too many VLAN changes in one request\n", - __func__); + dev_warn(&adapter->pdev->dev, "Too many delete VLAN changes in one request\n"); count = (I40EVF_MAX_AQ_BUF_SIZE - sizeof(struct i40e_virtchnl_vlan_filter_list)) / sizeof(u16); @@ -629,8 +625,8 @@ void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags) if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ - dev_err(&adapter->pdev->dev, "%s: command %d pending\n", - __func__, adapter->current_op); + dev_err(&adapter->pdev->dev, "Cannot set promiscuous mode, command %d pending\n", + adapter->current_op); return; } adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE; @@ -720,17 +716,16 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, } break; default: - dev_err(&adapter->pdev->dev, - "%s: Unknown event %d from pf\n", - __func__, vpe->event); + dev_err(&adapter->pdev->dev, "Unknown event %d from PF\n", + vpe->event); break; } return; } if (v_retval) { - dev_err(&adapter->pdev->dev, "%s: PF returned error %d (%s) to our request %d\n", - __func__, v_retval, - i40evf_stat_str(&adapter->hw, v_retval), v_opcode); + dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n", + v_retval, i40evf_stat_str(&adapter->hw, v_retval), + v_opcode); } switch (v_opcode) { case I40E_VIRTCHNL_OP_GET_STATS: { -- cgit v1.2.3 From dd38c583aea07c508caeaf979c64e267584ee067 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 26 Aug 2015 15:14:18 -0400 Subject: i40e: add little endian conversion for checksum The checksum is not correct on big endian machines so add code to swap it correctly. Change-ID: Ic92b886d172a2cbe49f5d7eee1bc78e447023c7b Signed-off-by: Jesse Brandeburg Signed-off-by: Paul M Stillwell Jr Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index d0288ad4e9b2..2142e1004a2f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -547,11 +547,13 @@ i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw) { i40e_status ret_code = 0; u16 checksum; + __le16 le_sum; ret_code = i40e_calc_nvm_checksum(hw, &checksum); + le_sum = cpu_to_le16(checksum); if (!ret_code) ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD, - 1, &checksum, true); + 1, &le_sum, true); return ret_code; } -- cgit v1.2.3 From a72a5abcb37beac163704efba6a3d33ebca4d90a Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 26 Aug 2015 15:14:19 -0400 Subject: i40e: fix bug in return from get_link_status and avoid spurious link messages Previously, the driver could call this function and have only true/false returned, but false could mean multiple things like failure to read or link was down. This change allows the caller to get all return values in the call chain bubbled back to the source, which keeps information about failures from being lost. Also, in some unlikely scenarios, the firmware can become slow to respond to admin queue (AQ) queries for link state. Should the AQ time out, the driver can detect the state and avoid a link change when there may have been none. Change-ID: Ib2ac38407b7880750fb891b392fa77457fe6c21c Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 15 ++++++++------- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 11 ++++++++++- drivers/net/ethernet/intel/i40e/i40e_main.c | 12 ++++++++++-- drivers/net/ethernet/intel/i40e/i40e_prototype.h | 2 +- 4 files changed, 29 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 7a70abcafbbb..2839ea53234d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -2235,27 +2235,28 @@ i40e_status i40e_aq_send_driver_version(struct i40e_hw *hw, /** * i40e_get_link_status - get status of the HW network link * @hw: pointer to the hw struct + * @link_up: pointer to bool (true/false = linkup/linkdown) * - * Returns true if link is up, false if link is down. + * Variable link_up true if link is up, false if link is down. + * The variable link_up is invalid if returned value of status != 0 * * Side effect: LinkStatusEvent reporting becomes enabled **/ -bool i40e_get_link_status(struct i40e_hw *hw) +i40e_status i40e_get_link_status(struct i40e_hw *hw, bool *link_up) { i40e_status status = 0; - bool link_status = false; if (hw->phy.get_link_info) { status = i40e_aq_get_link_info(hw, true, NULL, NULL); if (status) - goto i40e_get_link_status_exit; + i40e_debug(hw, I40E_DEBUG_LINK, "get link failed: status %d\n", + status); } - link_status = hw->phy.link_info.link_info & I40E_AQ_LINK_UP; + *link_up = hw->phy.link_info.link_info & I40E_AQ_LINK_UP; -i40e_get_link_status_exit: - return link_status; + return status; } /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 930369c4882b..1fa38f6e0e19 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1516,9 +1516,18 @@ static int i40e_link_test(struct net_device *netdev, u64 *data) { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; + i40e_status status; + bool link_up = false; netif_info(pf, hw, netdev, "link test\n"); - if (i40e_get_link_status(&pf->hw)) + status = i40e_get_link_status(&pf->hw, &link_up); + if (status) { + netif_err(pf, drv, netdev, "link query timed out, please retry test\n"); + *data = 1; + return *data; + } + + if (link_up) *data = 0; else *data = 1; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 1fa1ebab9e92..f205e18a8530 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5836,15 +5836,23 @@ static void i40e_veb_link_event(struct i40e_veb *veb, bool link_up) **/ static void i40e_link_event(struct i40e_pf *pf) { - bool new_link, old_link; struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi]; u8 new_link_speed, old_link_speed; + i40e_status status; + bool new_link, old_link; /* set this to force the get_link_status call to refresh state */ pf->hw.phy.get_link_info = true; old_link = (pf->hw.phy.link_info_old.link_info & I40E_AQ_LINK_UP); - new_link = i40e_get_link_status(&pf->hw); + + status = i40e_get_link_status(&pf->hw, &new_link); + if (status) { + dev_dbg(&pf->pdev->dev, "couldn't get link state, status: %d\n", + status); + return; + } + old_link_speed = pf->hw.phy.link_info_old.link_speed; new_link_speed = pf->hw.phy.link_info.link_speed; diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index dcb72a8ee8e5..e51e1567837c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -258,7 +258,7 @@ i40e_status i40e_init_shared_code(struct i40e_hw *hw); i40e_status i40e_pf_reset(struct i40e_hw *hw); void i40e_clear_hw(struct i40e_hw *hw); void i40e_clear_pxe_mode(struct i40e_hw *hw); -bool i40e_get_link_status(struct i40e_hw *hw); +i40e_status i40e_get_link_status(struct i40e_hw *hw, bool *link_up); i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr); i40e_status i40e_read_bw_from_alt_ram(struct i40e_hw *hw, u32 *max_bw, u32 *min_bw, bool *min_valid, -- cgit v1.2.3 From 2f41f3358672dfda67c1e254f1e823d98e6a3099 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 26 Aug 2015 15:14:20 -0400 Subject: i40e/i40evf: fix unicast mac address add When using something like "ip maddr add ..." to add another unicast mac address to the netdev, the mac address comes into the set_rx_mode handler in the multicast list whether it is a unicast or multicast address. This was confusing the code when it was trying to search for addresses that needed to be deleted from the VSI, because it was looking for the VSI unicast address in the netdev unicast list. The result was that a new unicast address would get added to the VSI list and then immediately removed, and would never actually make it down into the hardware. This patch removes the separation from unicast and multicast in the search for filters to be deleted. It also simplifies the logic a little with a jump to the bottom of the loop when an address is found. Now it doesn't matter which netdev list the address is hiding in, we'll check them all. Change-ID: Ie3685a92427ae7d2212bf948919ce295bc7a874c Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 41 +++++++++------------- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 45 ++++++++++++------------- 2 files changed, 38 insertions(+), 48 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index f205e18a8530..84f9dd91f354 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1726,36 +1726,27 @@ static void i40e_set_rx_mode(struct net_device *netdev) /* remove filter if not in netdev list */ list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { - bool found = false; if (!f->is_netdev) continue; - if (is_multicast_ether_addr(f->macaddr)) { - netdev_for_each_mc_addr(mca, netdev) { - if (ether_addr_equal(mca->addr, f->macaddr)) { - found = true; - break; - } - } - } else { - netdev_for_each_uc_addr(uca, netdev) { - if (ether_addr_equal(uca->addr, f->macaddr)) { - found = true; - break; - } - } + netdev_for_each_mc_addr(mca, netdev) + if (ether_addr_equal(mca->addr, f->macaddr)) + goto bottom_of_search_loop; - for_each_dev_addr(netdev, ha) { - if (ether_addr_equal(ha->addr, f->macaddr)) { - found = true; - break; - } - } - } - if (!found) - i40e_del_filter( - vsi, f->macaddr, I40E_VLAN_ANY, false, true); + netdev_for_each_uc_addr(uca, netdev) + if (ether_addr_equal(uca->addr, f->macaddr)) + goto bottom_of_search_loop; + + for_each_dev_addr(netdev, ha) + if (ether_addr_equal(ha->addr, f->macaddr)) + goto bottom_of_search_loop; + + /* f->macaddr wasn't found in uc, mc, or ha list so delete it */ + i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY, false, true); + +bottom_of_search_loop: + continue; } /* check for other flag changes */ diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index f3a61c49ee32..cc78fdfd5fa0 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -855,6 +855,7 @@ static void i40evf_set_rx_mode(struct net_device *netdev) struct i40evf_mac_filter *f, *ftmp; struct netdev_hw_addr *uca; struct netdev_hw_addr *mca; + struct netdev_hw_addr *ha; int count = 50; /* add addr if not already in the filter list */ @@ -876,29 +877,27 @@ static void i40evf_set_rx_mode(struct net_device *netdev) } /* remove filter if not in netdev list */ list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) { - bool found = false; - - if (is_multicast_ether_addr(f->macaddr)) { - netdev_for_each_mc_addr(mca, netdev) { - if (ether_addr_equal(mca->addr, f->macaddr)) { - found = true; - break; - } - } - } else { - netdev_for_each_uc_addr(uca, netdev) { - if (ether_addr_equal(uca->addr, f->macaddr)) { - found = true; - break; - } - } - if (ether_addr_equal(f->macaddr, adapter->hw.mac.addr)) - found = true; - } - if (!found) { - f->remove = true; - adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER; - } + netdev_for_each_mc_addr(mca, netdev) + if (ether_addr_equal(mca->addr, f->macaddr)) + goto bottom_of_search_loop; + + netdev_for_each_uc_addr(uca, netdev) + if (ether_addr_equal(uca->addr, f->macaddr)) + goto bottom_of_search_loop; + + for_each_dev_addr(netdev, ha) + if (ether_addr_equal(ha->addr, f->macaddr)) + goto bottom_of_search_loop; + + if (ether_addr_equal(f->macaddr, adapter->hw.mac.addr)) + goto bottom_of_search_loop; + + /* f->macaddr wasn't found in uc, mc, or ha list so delete it */ + f->remove = true; + adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER; + +bottom_of_search_loop: + continue; } clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section); } -- cgit v1.2.3 From 2fc3d7152ae9562c15c30ed4a766ba05a3db8200 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Thu, 27 Aug 2015 11:42:29 -0400 Subject: i40e/i40evf: Add a stat to keep track of linearization count Keep track of how many times we ask the stack to linearize the skb because the HW cannot handle skbs with more than 8 frags per segment/single packet. Change-ID: If455452060963a769bbe6112cba952e79e944b52 Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 5 ++++- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 5 +++-- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 5 +++-- drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 1 + 7 files changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index a54577af4884..681bd5d37960 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -475,6 +475,7 @@ struct i40e_vsi { #endif u32 tx_restart; u32 tx_busy; + u64 tx_linearize; u32 rx_buf_failed; u32 rx_page_failed; diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 1fa38f6e0e19..ffa943164b42 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -87,6 +87,7 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = { I40E_VSI_STAT("rx_broadcast", eth_stats.rx_broadcast), I40E_VSI_STAT("tx_broadcast", eth_stats.tx_broadcast), I40E_VSI_STAT("rx_unknown_protocol", eth_stats.rx_unknown_protocol), + I40E_VSI_STAT("tx_linearize", tx_linearize), }; static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi, diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 84f9dd91f354..fb4b34db1ff5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -879,6 +879,7 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi) u32 rx_page, rx_buf; u64 bytes, packets; unsigned int start; + u64 tx_linearize; u64 rx_p, rx_b; u64 tx_p, tx_b; u16 q; @@ -897,7 +898,7 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi) */ rx_b = rx_p = 0; tx_b = tx_p = 0; - tx_restart = tx_busy = 0; + tx_restart = tx_busy = tx_linearize = 0; rx_page = 0; rx_buf = 0; rcu_read_lock(); @@ -914,6 +915,7 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi) tx_p += packets; tx_restart += p->tx_stats.restart_queue; tx_busy += p->tx_stats.tx_busy; + tx_linearize += p->tx_stats.tx_linearize; /* Rx queue is part of the same block as Tx queue */ p = &p[1]; @@ -930,6 +932,7 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi) rcu_read_unlock(); vsi->tx_restart = tx_restart; vsi->tx_busy = tx_busy; + vsi->tx_linearize = tx_linearize; vsi->rx_page_failed = rx_page; vsi->rx_buf_failed = rx_buf; diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 85e61b004f2c..889ed10f588b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2771,10 +2771,11 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, if (tsyn) tx_flags |= I40E_TX_FLAGS_TSYN; - if (i40e_chk_linearize(skb, tx_flags)) + if (i40e_chk_linearize(skb, tx_flags)) { if (skb_linearize(skb)) goto out_drop; - + tx_ring->tx_stats.tx_linearize++; + } skb_tx_timestamp(skb); /* always enable CRC insertion offload */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 7c9975c983d9..ac3fb3a6f42d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -188,6 +188,7 @@ struct i40e_tx_queue_stats { u64 restart_queue; u64 tx_busy; u64 tx_done_old; + u64 tx_linearize; }; struct i40e_rx_queue_stats { diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 0e1a4d6e4e6e..3b102f209a96 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1927,10 +1927,11 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, else if (tso) tx_flags |= I40E_TX_FLAGS_TSO; - if (i40e_chk_linearize(skb, tx_flags)) + if (i40e_chk_linearize(skb, tx_flags)) { if (skb_linearize(skb)) goto out_drop; - + tx_ring->tx_stats.tx_linearize++; + } skb_tx_timestamp(skb); /* always enable CRC insertion offload */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index d5cb7aca87b4..93b90f7e8e86 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -187,6 +187,7 @@ struct i40e_tx_queue_stats { u64 restart_queue; u64 tx_busy; u64 tx_done_old; + u64 tx_linearize; }; struct i40e_rx_queue_stats { -- cgit v1.2.3 From 2642f02528b6e9c1e904f6e3ec902d8a2deb7af5 Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Thu, 27 Aug 2015 11:42:30 -0400 Subject: i40e: Additional checks for CEE APP priority validity The firmware has added additional status information to allow software to determine if the APP priority for FCoE/iSCSI/FIP is valid or not in CEE DCBX mode. This patch adds to support those additional checks and will only add applications to the software table that have oper and sync bits set without any error. Change-ID: I0a76c52427dadf97d4dba4538a3068d05e4eb56b Signed-off-by: Neerav Parikh Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_dcb.c | 48 ++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c index 90de46aef557..9aee35d284fa 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c @@ -531,37 +531,55 @@ static void i40e_cee_to_dcb_config( dcbcfg->pfc.pfcenable = cee_cfg->oper_pfc_en; dcbcfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS; - status = (tlv_status & I40E_AQC_CEE_APP_STATUS_MASK) >> - I40E_AQC_CEE_APP_STATUS_SHIFT; + i = 0; + status = (tlv_status & I40E_AQC_CEE_FCOE_STATUS_MASK) >> + I40E_AQC_CEE_FCOE_STATUS_SHIFT; err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; - /* Add APPs if Error is False and Oper/Sync is True */ + /* Add FCoE APP if Error is False and Oper/Sync is True */ if (!err && sync && oper) { - /* CEE operating configuration supports FCoE/iSCSI/FIP only */ - dcbcfg->numapps = I40E_CEE_OPER_MAX_APPS; - /* FCoE APP */ - dcbcfg->app[0].priority = + dcbcfg->app[i].priority = (app_prio & I40E_AQC_CEE_APP_FCOE_MASK) >> I40E_AQC_CEE_APP_FCOE_SHIFT; - dcbcfg->app[0].selector = I40E_APP_SEL_ETHTYPE; - dcbcfg->app[0].protocolid = I40E_APP_PROTOID_FCOE; + dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE; + dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FCOE; + i++; + } + status = (tlv_status & I40E_AQC_CEE_ISCSI_STATUS_MASK) >> + I40E_AQC_CEE_ISCSI_STATUS_SHIFT; + err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; + sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; + oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; + /* Add iSCSI APP if Error is False and Oper/Sync is True */ + if (!err && sync && oper) { /* iSCSI APP */ - dcbcfg->app[1].priority = + dcbcfg->app[i].priority = (app_prio & I40E_AQC_CEE_APP_ISCSI_MASK) >> I40E_AQC_CEE_APP_ISCSI_SHIFT; - dcbcfg->app[1].selector = I40E_APP_SEL_TCPIP; - dcbcfg->app[1].protocolid = I40E_APP_PROTOID_ISCSI; + dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP; + dcbcfg->app[i].protocolid = I40E_APP_PROTOID_ISCSI; + i++; + } + status = (tlv_status & I40E_AQC_CEE_FIP_STATUS_MASK) >> + I40E_AQC_CEE_FIP_STATUS_SHIFT; + err = (status & I40E_TLV_STATUS_ERR) ? 1 : 0; + sync = (status & I40E_TLV_STATUS_SYNC) ? 1 : 0; + oper = (status & I40E_TLV_STATUS_OPER) ? 1 : 0; + /* Add FIP APP if Error is False and Oper/Sync is True */ + if (!err && sync && oper) { /* FIP APP */ - dcbcfg->app[2].priority = + dcbcfg->app[i].priority = (app_prio & I40E_AQC_CEE_APP_FIP_MASK) >> I40E_AQC_CEE_APP_FIP_SHIFT; - dcbcfg->app[2].selector = I40E_APP_SEL_ETHTYPE; - dcbcfg->app[2].protocolid = I40E_APP_PROTOID_FIP; + dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE; + dcbcfg->app[i].protocolid = I40E_APP_PROTOID_FIP; + i++; } + dcbcfg->numapps = i; } /** -- cgit v1.2.3 From 313ed2d52052ad8dab9a6182cde55a832873cbea Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 27 Aug 2015 11:42:31 -0400 Subject: i40evf: propagate interrupt allocation failure Lower level functions are properly reporting errors, and higher-level functions are correctly responding to errors, but the errors aren't actually getting through. Typically, the middle-manager function seems to want to shield its boss from any bad news. This change fixes a panic if the driver is unable to enable MSI-X or is unable to acquire enough vectors. Change-ID: Ifd5787ce92519a5d97e4b465902db930d97b71a1 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index cc78fdfd5fa0..0d18446cc5ad 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1163,7 +1163,7 @@ static int i40evf_set_interrupt_capability(struct i40evf_adapter *adapter) for (vector = 0; vector < v_budget; vector++) adapter->msix_entries[vector].entry = vector; - i40evf_acquire_msix_vectors(adapter, v_budget); + err = i40evf_acquire_msix_vectors(adapter, v_budget); out: adapter->netdev->real_num_tx_queues = pairs; -- cgit v1.2.3 From 7fd0ac66c2de5767e234fea6436d28dce210da80 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 27 Aug 2015 11:42:32 -0400 Subject: i40e/i40evf: remove unused opcode This opcode is not required. VFs that program RSS through the firmware do it by interacting directly with the firmware, and do not need to use the virtual channel for this functionality. Change-ID: Iaf17d2600e28ff1b6be8653f2fe9df1facd23b0e Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl.h | 1 - drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h index 0f8d4156f8b1..95d0f8c5d484 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h @@ -81,7 +81,6 @@ enum i40e_virtchnl_ops { I40E_VIRTCHNL_OP_GET_STATS = 15, I40E_VIRTCHNL_OP_FCOE = 16, I40E_VIRTCHNL_OP_EVENT = 17, - I40E_VIRTCHNL_OP_CONFIG_RSS = 18, }; /* Virtual channel message descriptor. This overlays the admin queue diff --git a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h index e6db20e8a395..cadda642c98c 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h @@ -81,7 +81,6 @@ enum i40e_virtchnl_ops { I40E_VIRTCHNL_OP_GET_STATS = 15, I40E_VIRTCHNL_OP_FCOE = 16, I40E_VIRTCHNL_OP_EVENT = 17, - I40E_VIRTCHNL_OP_CONFIG_RSS = 18, }; /* Virtual channel message descriptor. This overlays the admin queue -- cgit v1.2.3 From 4ebdfba73c09d8568d891bae87c40fad43dd7f41 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 7 Oct 2015 16:48:36 -0500 Subject: dst: Pass a sk into .local_out For consistency with the other similar methods in the kernel pass a struct sock into the dst_ops .local_out method. Simplifying the socket passing case is needed a prequel to passing a struct net reference into .local_out. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/vrf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 64499766e00f..1039eb5f6c2a 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -74,9 +74,9 @@ static struct dst_entry *vrf_ip_check(struct dst_entry *dst, u32 cookie) return dst; } -static int vrf_ip_local_out(struct sk_buff *skb) +static int vrf_ip_local_out(struct sock *sk, struct sk_buff *skb) { - return ip_local_out(skb); + return ip_local_out_sk(sk, skb); } static unsigned int vrf_v4_mtu(const struct dst_entry *dst) -- cgit v1.2.3 From e2cb77db089796f163092326ca25512845df7a3a Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 7 Oct 2015 16:48:38 -0500 Subject: ipv4: Merge ip_local_out and ip_local_out_sk It is confusing and silly hiding a parameter so modify all of the callers to pass in the appropriate socket or skb->sk if no socket is known. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_core.c | 2 +- drivers/net/ppp/pptp.c | 2 +- drivers/net/vrf.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 207f62e8de9a..c75ad39c752f 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -364,7 +364,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb) } skb_dst_drop(skb); skb_dst_set(skb, &rt->dst); - err = ip_local_out(skb); + err = ip_local_out(skb->sk, skb); if (unlikely(net_xmit_eval(err))) dev->stats.tx_errors++; else diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 686f37daa262..6bef7be10671 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -282,7 +282,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) ip_select_ident(sock_net(sk), skb, NULL); ip_send_check(iph); - ip_local_out(skb); + ip_local_out(skb->sk, skb); return 1; tx_error: diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 1039eb5f6c2a..231f9d85d4eb 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -76,7 +76,7 @@ static struct dst_entry *vrf_ip_check(struct dst_entry *dst, u32 cookie) static int vrf_ip_local_out(struct sock *sk, struct sk_buff *skb) { - return ip_local_out_sk(sk, skb); + return ip_local_out(sk, skb); } static unsigned int vrf_v4_mtu(const struct dst_entry *dst) @@ -222,7 +222,7 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb, RT_SCOPE_LINK); } - ret = ip_local_out(skb); + ret = ip_local_out(skb->sk, skb); if (unlikely(net_xmit_eval(ret))) vrf_dev->stats.tx_errors++; else -- cgit v1.2.3 From 792883303cdb3a7edd16017d7aba53926189ef41 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 7 Oct 2015 16:48:40 -0500 Subject: ipv6: Merge ip6_local_out and ip6_local_out_sk Stop hidding the sk parameter with an inline helper function and make all of the callers pass it, so that it is clear what the function is doing. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index c75ad39c752f..75dcf36c0366 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -401,7 +401,7 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb) } skb_dst_drop(skb); skb_dst_set(skb, dst); - err = ip6_local_out(skb); + err = ip6_local_out(skb->sk, skb); if (unlikely(net_xmit_eval(err))) dev->stats.tx_errors++; else -- cgit v1.2.3 From a7093fefa543afad2bf292bba163800e81a4ba33 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 7 Oct 2015 16:48:43 -0500 Subject: ppp: Cache net in pptp_xmit Compute net and store it in a variable in pptp_xmit, so that the value can be reused the next time it is needed. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/ppp/pptp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 6bef7be10671..5243ab6ed4d4 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -169,6 +169,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) { struct sock *sk = (struct sock *) chan->private; struct pppox_sock *po = pppox_sk(sk); + struct net *net = sock_net(sk); struct pptp_opt *opt = &po->proto.pptp; struct pptp_gre_header *hdr; unsigned int header_len = sizeof(*hdr); @@ -187,7 +188,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) if (sk_pppox(po)->sk_state & PPPOX_DEAD) goto tx_error; - rt = ip_route_output_ports(sock_net(sk), &fl4, NULL, + rt = ip_route_output_ports(net, &fl4, NULL, opt->dst_addr.sin_addr.s_addr, opt->src_addr.sin_addr.s_addr, 0, 0, IPPROTO_GRE, @@ -279,7 +280,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) nf_reset(skb); skb->ip_summed = CHECKSUM_NONE; - ip_select_ident(sock_net(sk), skb, NULL); + ip_select_ident(net, skb, NULL); ip_send_check(iph); ip_local_out(skb->sk, skb); -- cgit v1.2.3 From 57c4bf859cad9d6c4f73d8c98a95e00f156301e0 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 7 Oct 2015 16:48:44 -0500 Subject: ipvlan: Cache net in ipvlan_process_v4_outbound and ipvlan_process_v6_outbound Compute net once in ipvlan_process_v4_outbound and ipvlan_process_v6_outbound and store it in a variable so that net does not need to be recomputed next time it is used. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 75dcf36c0366..976f30b291f6 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -344,6 +344,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb) { const struct iphdr *ip4h = ip_hdr(skb); struct net_device *dev = skb->dev; + struct net *net = dev_net(dev); struct rtable *rt; int err, ret = NET_XMIT_DROP; struct flowi4 fl4 = { @@ -354,7 +355,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb) .saddr = ip4h->saddr, }; - rt = ip_route_output_flow(dev_net(dev), &fl4, NULL); + rt = ip_route_output_flow(net, &fl4, NULL); if (IS_ERR(rt)) goto err; @@ -381,6 +382,7 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb) { const struct ipv6hdr *ip6h = ipv6_hdr(skb); struct net_device *dev = skb->dev; + struct net *net = dev_net(dev); struct dst_entry *dst; int err, ret = NET_XMIT_DROP; struct flowi6 fl6 = { @@ -393,7 +395,7 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb) .flowi6_proto = ip6h->nexthdr, }; - dst = ip6_route_output(dev_net(dev), NULL, &fl6); + dst = ip6_route_output(net, NULL, &fl6); if (dst->error) { ret = dst->error; dst_release(dst); -- cgit v1.2.3 From cf91a99daa4651d0c1f52b8c3d813fd44b43cada Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 7 Oct 2015 16:48:45 -0500 Subject: ipv4, ipv6: Pass net into __ip_local_out and __ip6_local_out Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/vrf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 231f9d85d4eb..b27dc11cd3f2 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -74,7 +74,7 @@ static struct dst_entry *vrf_ip_check(struct dst_entry *dst, u32 cookie) return dst; } -static int vrf_ip_local_out(struct sock *sk, struct sk_buff *skb) +static int vrf_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb) { return ip_local_out(sk, skb); } -- cgit v1.2.3 From 33224b16ffccb49cf798317670389e0bfba0024c Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 7 Oct 2015 16:48:46 -0500 Subject: ipv4, ipv6: Pass net into ip_local_out and ip6_local_out Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_core.c | 4 ++-- drivers/net/ppp/pptp.c | 2 +- drivers/net/vrf.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 976f30b291f6..24f8dbcf854f 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -365,7 +365,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb) } skb_dst_drop(skb); skb_dst_set(skb, &rt->dst); - err = ip_local_out(skb->sk, skb); + err = ip_local_out(net, skb->sk, skb); if (unlikely(net_xmit_eval(err))) dev->stats.tx_errors++; else @@ -403,7 +403,7 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb) } skb_dst_drop(skb); skb_dst_set(skb, dst); - err = ip6_local_out(skb->sk, skb); + err = ip6_local_out(net, skb->sk, skb); if (unlikely(net_xmit_eval(err))) dev->stats.tx_errors++; else diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 5243ab6ed4d4..fc69e41d0950 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -283,7 +283,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) ip_select_ident(net, skb, NULL); ip_send_check(iph); - ip_local_out(skb->sk, skb); + ip_local_out(net, skb->sk, skb); return 1; tx_error: diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index b27dc11cd3f2..21bb7deb6d58 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -76,7 +76,7 @@ static struct dst_entry *vrf_ip_check(struct dst_entry *dst, u32 cookie) static int vrf_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb) { - return ip_local_out(sk, skb); + return ip_local_out(net, sk, skb); } static unsigned int vrf_v4_mtu(const struct dst_entry *dst) @@ -222,7 +222,7 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb, RT_SCOPE_LINK); } - ret = ip_local_out(skb->sk, skb); + ret = ip_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb); if (unlikely(net_xmit_eval(ret))) vrf_dev->stats.tx_errors++; else -- cgit v1.2.3 From ede2059dbaf9c6557a49d466c8c7778343b208ff Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 7 Oct 2015 16:48:47 -0500 Subject: dst: Pass net into dst->output The network namespace is already passed into dst_output pass it into dst->output lwt->output and friends. Signed-off-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- drivers/net/vrf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 21bb7deb6d58..191579aeab16 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -312,10 +312,9 @@ err: return ret; } -static int vrf_output(struct sock *sk, struct sk_buff *skb) +static int vrf_output(struct net *net, struct sock *sk, struct sk_buff *skb) { struct net_device *dev = skb_dst(skb)->dev; - struct net *net = dev_net(dev); IP_UPD_PO_STATS(net, IPSTATS_MIB_OUT, skb->len); -- cgit v1.2.3 From ddc24ae1fd6ae2638365b0b824750b5b2ef13ca5 Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Tue, 6 Oct 2015 12:25:47 -0700 Subject: net: phy: Broadcom iProc MDIO bus driver This patch adds support for the Broadcom iProc MDIO bus interface. The MDIO interface can be found in the Broadcom iProc family Soc's. The MDIO bus is accessed using a combination of command and data registers. This MDIO driver provides access to the Etherent GPHY's connected to the MDIO bus. Signed-off-by: Arun Parameswaran Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 9 ++ drivers/net/phy/Makefile | 1 + drivers/net/phy/mdio-bcm-iproc.c | 213 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 drivers/net/phy/mdio-bcm-iproc.c (limited to 'drivers/net') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index c5ad98ace5d0..b57f6c280cad 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -225,6 +225,15 @@ config MDIO_BCM_UNIMAC This hardware can be found in the Broadcom GENET Ethernet MAC controllers as well as some Broadcom Ethernet switches such as the Starfighter 2 switches. + +config MDIO_BCM_IPROC + tristate "Broadcom iProc MDIO bus controller" + depends on ARCH_BCM_IPROC || COMPILE_TEST + depends on HAS_IOMEM && OF_MDIO + help + This module provides a driver for the MDIO busses found in the + Broadcom iProc SoC's. + endif # PHYLIB config MICREL_KS8995MA diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 87f079c4b2c7..f4e6eb9b2363 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -38,3 +38,4 @@ obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o obj-$(CONFIG_MICROCHIP_PHY) += microchip.o +obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o diff --git a/drivers/net/phy/mdio-bcm-iproc.c b/drivers/net/phy/mdio-bcm-iproc.c new file mode 100644 index 000000000000..c0b4e65267af --- /dev/null +++ b/drivers/net/phy/mdio-bcm-iproc.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IPROC_GPHY_MDCDIV 0x1a + +#define MII_CTRL_OFFSET 0x000 + +#define MII_CTRL_DIV_SHIFT 0 +#define MII_CTRL_PRE_SHIFT 7 +#define MII_CTRL_BUSY_SHIFT 8 + +#define MII_DATA_OFFSET 0x004 +#define MII_DATA_MASK 0xffff +#define MII_DATA_TA_SHIFT 16 +#define MII_DATA_TA_VAL 2 +#define MII_DATA_RA_SHIFT 18 +#define MII_DATA_PA_SHIFT 23 +#define MII_DATA_OP_SHIFT 28 +#define MII_DATA_OP_WRITE 1 +#define MII_DATA_OP_READ 2 +#define MII_DATA_SB_SHIFT 30 + +struct iproc_mdio_priv { + struct mii_bus *mii_bus; + void __iomem *base; +}; + +static inline int iproc_mdio_wait_for_idle(void __iomem *base) +{ + u32 val; + unsigned int timeout = 1000; /* loop for 1s */ + + do { + val = readl(base + MII_CTRL_OFFSET); + if ((val & BIT(MII_CTRL_BUSY_SHIFT)) == 0) + return 0; + + usleep_range(1000, 2000); + } while (timeout--); + + return -ETIMEDOUT; +} + +static inline void iproc_mdio_config_clk(void __iomem *base) +{ + u32 val; + + val = (IPROC_GPHY_MDCDIV << MII_CTRL_DIV_SHIFT) | + BIT(MII_CTRL_PRE_SHIFT); + writel(val, base + MII_CTRL_OFFSET); +} + +static int iproc_mdio_read(struct mii_bus *bus, int phy_id, int reg) +{ + struct iproc_mdio_priv *priv = bus->priv; + u32 cmd; + int rc; + + rc = iproc_mdio_wait_for_idle(priv->base); + if (rc) + return rc; + + iproc_mdio_config_clk(priv->base); + + /* Prepare the read operation */ + cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) | + (reg << MII_DATA_RA_SHIFT) | + (phy_id << MII_DATA_PA_SHIFT) | + BIT(MII_DATA_SB_SHIFT) | + (MII_DATA_OP_READ << MII_DATA_OP_SHIFT); + + writel(cmd, priv->base + MII_DATA_OFFSET); + + rc = iproc_mdio_wait_for_idle(priv->base); + if (rc) + return rc; + + cmd = readl(priv->base + MII_DATA_OFFSET) & MII_DATA_MASK; + + return cmd; +} + +static int iproc_mdio_write(struct mii_bus *bus, int phy_id, + int reg, u16 val) +{ + struct iproc_mdio_priv *priv = bus->priv; + u32 cmd; + int rc; + + rc = iproc_mdio_wait_for_idle(priv->base); + if (rc) + return rc; + + iproc_mdio_config_clk(priv->base); + + /* Prepare the write operation */ + cmd = (MII_DATA_TA_VAL << MII_DATA_TA_SHIFT) | + (reg << MII_DATA_RA_SHIFT) | + (phy_id << MII_DATA_PA_SHIFT) | + BIT(MII_DATA_SB_SHIFT) | + (MII_DATA_OP_WRITE << MII_DATA_OP_SHIFT) | + ((u32)(val) & MII_DATA_MASK); + + writel(cmd, priv->base + MII_DATA_OFFSET); + + rc = iproc_mdio_wait_for_idle(priv->base); + if (rc) + return rc; + + return 0; +} + +static int iproc_mdio_probe(struct platform_device *pdev) +{ + struct iproc_mdio_priv *priv; + struct mii_bus *bus; + struct resource *res; + int rc; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->base)) { + dev_err(&pdev->dev, "failed to ioremap register\n"); + return PTR_ERR(priv->base); + } + + priv->mii_bus = mdiobus_alloc(); + if (!priv->mii_bus) { + dev_err(&pdev->dev, "MDIO bus alloc failed\n"); + return -ENOMEM; + } + + bus = priv->mii_bus; + bus->priv = priv; + bus->name = "iProc MDIO bus"; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", pdev->name, pdev->id); + bus->parent = &pdev->dev; + bus->read = iproc_mdio_read; + bus->write = iproc_mdio_write; + + rc = of_mdiobus_register(bus, pdev->dev.of_node); + if (rc) { + dev_err(&pdev->dev, "MDIO bus registration failed\n"); + goto err_iproc_mdio; + } + + platform_set_drvdata(pdev, priv); + + dev_info(&pdev->dev, "Broadcom iProc MDIO bus at 0x%p\n", priv->base); + + return 0; + +err_iproc_mdio: + mdiobus_free(bus); + return rc; +} + +static int iproc_mdio_remove(struct platform_device *pdev) +{ + struct iproc_mdio_priv *priv = platform_get_drvdata(pdev); + + mdiobus_unregister(priv->mii_bus); + mdiobus_free(priv->mii_bus); + + return 0; +} + +static const struct of_device_id iproc_mdio_of_match[] = { + { .compatible = "brcm,iproc-mdio", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, iproc_mdio_of_match); + +static struct platform_driver iproc_mdio_driver = { + .driver = { + .name = "iproc-mdio", + .of_match_table = iproc_mdio_of_match, + }, + .probe = iproc_mdio_probe, + .remove = iproc_mdio_remove, +}; + +module_platform_driver(iproc_mdio_driver); + +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("Broadcom iProc MDIO bus controller"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:iproc-mdio"); -- cgit v1.2.3 From a1cba5613edf50c2a213fa90c30aa10500b241b7 Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Tue, 6 Oct 2015 12:25:48 -0700 Subject: net: phy: Add Broadcom phy library for common interfaces This patch adds the Broadcom phy library to consolidate common interfaces shared by Broadcom phy's. Moved the common interfaces to the 'bcm-phy-lib.c' and updated the Broadcom PHY drivers to use the new APIs. Signed-off-by: Arun Parameswaran Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 6 ++ drivers/net/phy/Makefile | 1 + drivers/net/phy/bcm-phy-lib.c | 208 ++++++++++++++++++++++++++++++++++++++++++ drivers/net/phy/bcm-phy-lib.h | 37 ++++++++ drivers/net/phy/bcm63xx.c | 38 +------- drivers/net/phy/bcm7xxx.c | 127 ++++++-------------------- drivers/net/phy/broadcom.c | 149 +++++++++--------------------- 7 files changed, 329 insertions(+), 237 deletions(-) create mode 100644 drivers/net/phy/bcm-phy-lib.c create mode 100644 drivers/net/phy/bcm-phy-lib.h (limited to 'drivers/net') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index b57f6c280cad..606fdc924768 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -69,8 +69,12 @@ config SMSC_PHY ---help--- Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs +config BCM_NET_PHYLIB + tristate + config BROADCOM_PHY tristate "Drivers for Broadcom PHYs" + select BCM_NET_PHYLIB ---help--- Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464, BCM5481 and BCM5482 PHYs. @@ -78,11 +82,13 @@ config BROADCOM_PHY config BCM63XX_PHY tristate "Drivers for Broadcom 63xx SOCs internal PHY" depends on BCM63XX + select BCM_NET_PHYLIB ---help--- Currently supports the 6348 and 6358 PHYs. config BCM7XXX_PHY tristate "Drivers for Broadcom 7xxx SOCs internal PHYs" + select BCM_NET_PHYLIB ---help--- Currently supports the BCM7366, BCM7439, BCM7445, and 40nm and 65nm generation of BCM7xxx Set Top Box SoCs. diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index f4e6eb9b2363..6932475a1a8a 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_SMSC_PHY) += smsc.o obj-$(CONFIG_TERANETICS_PHY) += teranetics.o obj-$(CONFIG_VITESSE_PHY) += vitesse.o +obj-$(CONFIG_BCM_NET_PHYLIB) += bcm-phy-lib.o obj-$(CONFIG_BROADCOM_PHY) += broadcom.o obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c new file mode 100644 index 000000000000..dd79ea6ba023 --- /dev/null +++ b/drivers/net/phy/bcm-phy-lib.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "bcm-phy-lib.h" +#include +#include +#include +#include + +#define MII_BCM_CHANNEL_WIDTH 0x2000 +#define BCM_CL45VEN_EEE_ADV 0x3c + +int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val) +{ + int rc; + + rc = phy_write(phydev, MII_BCM54XX_EXP_SEL, reg); + if (rc < 0) + return rc; + + return phy_write(phydev, MII_BCM54XX_EXP_DATA, val); +} +EXPORT_SYMBOL_GPL(bcm_phy_write_exp); + +int bcm_phy_read_exp(struct phy_device *phydev, u16 reg) +{ + int val; + + val = phy_write(phydev, MII_BCM54XX_EXP_SEL, reg); + if (val < 0) + return val; + + val = phy_read(phydev, MII_BCM54XX_EXP_DATA); + + /* Restore default value. It's O.K. if this write fails. */ + phy_write(phydev, MII_BCM54XX_EXP_SEL, 0); + + return val; +} +EXPORT_SYMBOL_GPL(bcm_phy_read_exp); + +int bcm_phy_write_misc(struct phy_device *phydev, + u16 reg, u16 chl, u16 val) +{ + int rc; + int tmp; + + rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, + MII_BCM54XX_AUXCTL_SHDWSEL_MISC); + if (rc < 0) + return rc; + + tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL); + tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA; + rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp); + if (rc < 0) + return rc; + + tmp = (chl * MII_BCM_CHANNEL_WIDTH) | reg; + rc = bcm_phy_write_exp(phydev, tmp, val); + + return rc; +} +EXPORT_SYMBOL_GPL(bcm_phy_write_misc); + +int bcm_phy_read_misc(struct phy_device *phydev, + u16 reg, u16 chl) +{ + int rc; + int tmp; + + rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, + MII_BCM54XX_AUXCTL_SHDWSEL_MISC); + if (rc < 0) + return rc; + + tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL); + tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA; + rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp); + if (rc < 0) + return rc; + + tmp = (chl * MII_BCM_CHANNEL_WIDTH) | reg; + rc = bcm_phy_read_exp(phydev, tmp); + + return rc; +} +EXPORT_SYMBOL_GPL(bcm_phy_read_misc); + +int bcm_phy_ack_intr(struct phy_device *phydev) +{ + int reg; + + /* Clear pending interrupts. */ + reg = phy_read(phydev, MII_BCM54XX_ISR); + if (reg < 0) + return reg; + + return 0; +} +EXPORT_SYMBOL_GPL(bcm_phy_ack_intr); + +int bcm_phy_config_intr(struct phy_device *phydev) +{ + int reg; + + reg = phy_read(phydev, MII_BCM54XX_ECR); + if (reg < 0) + return reg; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + reg &= ~MII_BCM54XX_ECR_IM; + else + reg |= MII_BCM54XX_ECR_IM; + + return phy_write(phydev, MII_BCM54XX_ECR, reg); +} +EXPORT_SYMBOL_GPL(bcm_phy_config_intr); + +int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow) +{ + phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow)); + return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD)); +} +EXPORT_SYMBOL_GPL(bcm_phy_read_shadow); + +int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow, + u16 val) +{ + return phy_write(phydev, MII_BCM54XX_SHD, + MII_BCM54XX_SHD_WRITE | + MII_BCM54XX_SHD_VAL(shadow) | + MII_BCM54XX_SHD_DATA(val)); +} +EXPORT_SYMBOL_GPL(bcm_phy_write_shadow); + +int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down) +{ + int val; + + if (dll_pwr_down) { + val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3); + if (val < 0) + return val; + + val |= BCM54XX_SHD_SCR3_DLLAPD_DIS; + bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val); + } + + val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD); + if (val < 0) + return val; + + /* Clear APD bits */ + val &= BCM_APD_CLR_MASK; + + if (phydev->autoneg == AUTONEG_ENABLE) + val |= BCM54XX_SHD_APD_EN; + else + val |= BCM_NO_ANEG_APD_EN; + + /* Enable energy detect single link pulse for easy wakeup */ + val |= BCM_APD_SINGLELP_EN; + + /* Enable Auto Power-Down (APD) for the PHY */ + return bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val); +} +EXPORT_SYMBOL_GPL(bcm_phy_enable_apd); + +int bcm_phy_enable_eee(struct phy_device *phydev) +{ + int val; + + /* Enable EEE at PHY level */ + val = phy_read_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL, + MDIO_MMD_AN, phydev->addr); + if (val < 0) + return val; + + val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X; + + phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL, + MDIO_MMD_AN, phydev->addr, (u32)val); + + /* Advertise EEE */ + val = phy_read_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV, + MDIO_MMD_AN, phydev->addr); + if (val < 0) + return val; + + val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T); + + phy_write_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV, + MDIO_MMD_AN, phydev->addr, (u32)val); + + return 0; +} +EXPORT_SYMBOL_GPL(bcm_phy_enable_eee); diff --git a/drivers/net/phy/bcm-phy-lib.h b/drivers/net/phy/bcm-phy-lib.h new file mode 100644 index 000000000000..b2091c88b44d --- /dev/null +++ b/drivers/net/phy/bcm-phy-lib.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _LINUX_BCM_PHY_LIB_H +#define _LINUX_BCM_PHY_LIB_H + +#include + +int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val); +int bcm_phy_read_exp(struct phy_device *phydev, u16 reg); + +int bcm_phy_write_misc(struct phy_device *phydev, + u16 reg, u16 chl, u16 value); +int bcm_phy_read_misc(struct phy_device *phydev, + u16 reg, u16 chl); + +int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow, + u16 val); +int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow); + +int bcm_phy_ack_intr(struct phy_device *phydev); +int bcm_phy_config_intr(struct phy_device *phydev); + +int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down); + +int bcm_phy_enable_eee(struct phy_device *phydev); +#endif /* _LINUX_BCM_PHY_LIB_H */ diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c index 830ec31f952f..86b28052bf06 100644 --- a/drivers/net/phy/bcm63xx.c +++ b/drivers/net/phy/bcm63xx.c @@ -6,6 +6,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#include "bcm-phy-lib.h" #include #include @@ -42,35 +43,6 @@ static int bcm63xx_config_init(struct phy_device *phydev) return phy_write(phydev, MII_BCM63XX_IR, reg); } -static int bcm63xx_ack_interrupt(struct phy_device *phydev) -{ - int reg; - - /* Clear pending interrupts. */ - reg = phy_read(phydev, MII_BCM63XX_IR); - if (reg < 0) - return reg; - - return 0; -} - -static int bcm63xx_config_intr(struct phy_device *phydev) -{ - int reg, err; - - reg = phy_read(phydev, MII_BCM63XX_IR); - if (reg < 0) - return reg; - - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) - reg &= ~MII_BCM63XX_IR_GMASK; - else - reg |= MII_BCM63XX_IR_GMASK; - - err = phy_write(phydev, MII_BCM63XX_IR, reg); - return err; -} - static struct phy_driver bcm63xx_driver[] = { { .phy_id = 0x00406000, @@ -82,8 +54,8 @@ static struct phy_driver bcm63xx_driver[] = { .config_init = bcm63xx_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .ack_interrupt = bcm63xx_ack_interrupt, - .config_intr = bcm63xx_config_intr, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, }, { /* same phy as above, with just a different OUI */ @@ -95,8 +67,8 @@ static struct phy_driver bcm63xx_driver[] = { .config_init = bcm63xx_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .ack_interrupt = bcm63xx_ack_interrupt, - .config_intr = bcm63xx_config_intr, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, } }; diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index 6b701b3ded74..efa31a655eb1 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -12,12 +12,12 @@ #include #include #include +#include "bcm-phy-lib.h" #include #include #include /* Broadcom BCM7xxx internal PHY registers */ -#define MII_BCM7XXX_CHANNEL_WIDTH 0x2000 /* 40nm only register definitions */ #define MII_BCM7XXX_100TX_AUX_CTL 0x10 @@ -48,37 +48,13 @@ #define CORE_EXPB0 0xb0 -static void phy_write_exp(struct phy_device *phydev, - u16 reg, u16 value) -{ - phy_write(phydev, MII_BCM54XX_EXP_SEL, MII_BCM54XX_EXP_SEL_ER | reg); - phy_write(phydev, MII_BCM54XX_EXP_DATA, value); -} - -static void phy_write_misc(struct phy_device *phydev, - u16 reg, u16 chl, u16 value) -{ - int tmp; - - phy_write(phydev, MII_BCM54XX_AUX_CTL, MII_BCM54XX_AUXCTL_SHDWSEL_MISC); - - tmp = phy_read(phydev, MII_BCM54XX_AUX_CTL); - tmp |= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA; - phy_write(phydev, MII_BCM54XX_AUX_CTL, tmp); - - tmp = (chl * MII_BCM7XXX_CHANNEL_WIDTH) | reg; - phy_write(phydev, MII_BCM54XX_EXP_SEL, tmp); - - phy_write(phydev, MII_BCM54XX_EXP_DATA, value); -} - static void r_rc_cal_reset(struct phy_device *phydev) { /* Reset R_CAL/RC_CAL Engine */ - phy_write_exp(phydev, 0x00b0, 0x0010); + bcm_phy_write_exp(phydev, 0x00b0, 0x0010); /* Disable Reset R_AL/RC_CAL Engine */ - phy_write_exp(phydev, 0x00b0, 0x0000); + bcm_phy_write_exp(phydev, 0x00b0, 0x0000); } static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) @@ -86,18 +62,18 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) /* Increase VCO range to prevent unlocking problem of PLL at low * temp */ - phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048); + bcm_phy_write_misc(phydev, PLL_PLLCTRL_1, 0x0048); /* Change Ki to 011 */ - phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b); + bcm_phy_write_misc(phydev, PLL_PLLCTRL_2, 0x021b); /* Disable loading of TVCO buffer to bandgap, set bandgap trim * to 111 */ - phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20); + bcm_phy_write_misc(phydev, PLL_PLLCTRL_4, 0x0e20); /* Adjust bias current trim by -3 */ - phy_write_misc(phydev, DSP_TAP10, 0x690b); + bcm_phy_write_misc(phydev, DSP_TAP10, 0x690b); /* Switch to CORE_BASE1E */ phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0xd); @@ -105,19 +81,19 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) r_rc_cal_reset(phydev); /* write AFE_RXCONFIG_0 */ - phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19); + bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb19); /* write AFE_RXCONFIG_1 */ - phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f); + bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9a3f); /* write AFE_RX_LP_COUNTER */ - phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0); + bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0); /* write AFE_HPF_TRIM_OTHERS */ - phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b); + bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x000b); /* write AFTE_TX_CONFIG */ - phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800); + bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x0800); return 0; } @@ -125,36 +101,36 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev) { /* AFE_RXCONFIG_0 */ - phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15); + bcm_phy_write_misc(phydev, AFE_RXCONFIG_0, 0xeb15); /* AFE_RXCONFIG_1 */ - phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f); + bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f); /* AFE_RXCONFIG_2, set rCal offset for HT=0 code and LT=-2 code */ - phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003); + bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0x2003); /* AFE_RX_LP_COUNTER, set RX bandwidth to maximum */ - phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0); + bcm_phy_write_misc(phydev, AFE_RX_LP_COUNTER, 0x7fc0); /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */ - phy_write_misc(phydev, AFE_TX_CONFIG, 0x431); + bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431); /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */ - phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da); + bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da); /* AFE_VDAC_OTHERS_0, set 1000BT Cidac=010 for all ports */ - phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020); + bcm_phy_write_misc(phydev, AFE_VDAC_OTHERS_0, 0xa020); /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal * offset for HT=0 code */ - phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3); + bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3); /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */ phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010); /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */ - phy_write_misc(phydev, DSP_TAP10, 0x011b); + bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b); /* Reset R_CAL/RC_CAL engine */ r_rc_cal_reset(phydev); @@ -165,24 +141,24 @@ static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev) static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev) { /* AFE_RXCONFIG_1, provide more margin for INL/DNL measurement */ - phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f); + bcm_phy_write_misc(phydev, AFE_RXCONFIG_1, 0x9b2f); /* AFE_TX_CONFIG, set 100BT Cfeed=011 to improve rise/fall time */ - phy_write_misc(phydev, AFE_TX_CONFIG, 0x431); + bcm_phy_write_misc(phydev, AFE_TX_CONFIG, 0x431); /* AFE_VDCA_ICTRL_0, set Iq=1101 instead of 0111 for AB symmetry */ - phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da); + bcm_phy_write_misc(phydev, AFE_VDCA_ICTRL_0, 0xa7da); /* AFE_HPF_TRIM_OTHERS, set 100Tx/10BT to -4.5% swing and set rCal * offset for HT=0 code */ - phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3); + bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3); /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */ phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010); /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */ - phy_write_misc(phydev, DSP_TAP10, 0x011b); + bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b); /* Reset R_CAL/RC_CAL engine */ r_rc_cal_reset(phydev); @@ -190,53 +166,6 @@ static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev) return 0; } -static int bcm7xxx_apd_enable(struct phy_device *phydev) -{ - int val; - - /* Enable powering down of the DLL during auto-power down */ - val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3); - if (val < 0) - return val; - - val |= BCM54XX_SHD_SCR3_DLLAPD_DIS; - bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val); - - /* Enable auto-power down */ - val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD); - if (val < 0) - return val; - - val |= BCM54XX_SHD_APD_EN; - return bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val); -} - -static int bcm7xxx_eee_enable(struct phy_device *phydev) -{ - int val; - - val = phy_read_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL, - MDIO_MMD_AN, phydev->addr); - if (val < 0) - return val; - - /* Enable general EEE feature at the PHY level */ - val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X; - - phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL, - MDIO_MMD_AN, phydev->addr, val); - - /* Advertise supported modes */ - val = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV, - MDIO_MMD_AN, phydev->addr); - - val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T); - phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV, - MDIO_MMD_AN, phydev->addr, val); - - return 0; -} - static int bcm7xxx_28nm_config_init(struct phy_device *phydev) { u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags); @@ -273,11 +202,11 @@ static int bcm7xxx_28nm_config_init(struct phy_device *phydev) if (ret) return ret; - ret = bcm7xxx_eee_enable(phydev); + ret = bcm_phy_enable_eee(phydev); if (ret) return ret; - return bcm7xxx_apd_enable(phydev); + return bcm_phy_enable_apd(phydev, true); } static int bcm7xxx_28nm_resume(struct phy_device *phydev) diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 9c71295f2fef..07a6119121c3 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -14,6 +14,7 @@ * 2 of the License, or (at your option) any later version. */ +#include "bcm-phy-lib.h" #include #include #include @@ -29,39 +30,6 @@ MODULE_DESCRIPTION("Broadcom PHY driver"); MODULE_AUTHOR("Maciej W. Rozycki"); MODULE_LICENSE("GPL"); -/* Indirect register access functions for the Expansion Registers */ -static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum) -{ - int val; - - val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum); - if (val < 0) - return val; - - val = phy_read(phydev, MII_BCM54XX_EXP_DATA); - - /* Restore default value. It's O.K. if this write fails. */ - phy_write(phydev, MII_BCM54XX_EXP_SEL, 0); - - return val; -} - -static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val) -{ - int ret; - - ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum); - if (ret < 0) - return ret; - - ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val); - - /* Restore default value. It's O.K. if this write fails. */ - phy_write(phydev, MII_BCM54XX_EXP_SEL, 0); - - return ret; -} - static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val) { return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val); @@ -72,28 +40,28 @@ static int bcm50610_a0_workaround(struct phy_device *phydev) { int err; - err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0, + err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0, MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN | MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF); if (err < 0) return err; - err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3, - MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ); + err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3, + MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ); if (err < 0) return err; - err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, + err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, MII_BCM54XX_EXP_EXP75_VDACCTRL); if (err < 0) return err; - err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96, + err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96, MII_BCM54XX_EXP_EXP96_MYST); if (err < 0) return err; - err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97, + err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97, MII_BCM54XX_EXP_EXP97_MYST); return err; @@ -114,7 +82,7 @@ static int bcm54xx_phydsp_config(struct phy_device *phydev) if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) { /* Clear bit 9 to fix a phy interop issue. */ - err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08, + err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08, MII_BCM54XX_EXP_EXP08_RJCT_2MHZ); if (err < 0) goto error; @@ -129,12 +97,12 @@ static int bcm54xx_phydsp_config(struct phy_device *phydev) if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) { int val; - val = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75); + val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75); if (val < 0) goto error; val |= MII_BCM54XX_EXP_EXP75_CM_OSC; - err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, val); + err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val); } error: @@ -159,7 +127,7 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M) return; - val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3); + val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3); if (val < 0) return; @@ -190,9 +158,9 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) val |= BCM54XX_SHD_SCR3_TRDDAPD; if (orig != val) - bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val); + bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val); - val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD); + val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD); if (val < 0) return; @@ -204,7 +172,7 @@ static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) val &= ~BCM54XX_SHD_APD_EN; if (orig != val) - bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val); + bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val); } static int bcm54xx_config_init(struct phy_device *phydev) @@ -232,7 +200,7 @@ static int bcm54xx_config_init(struct phy_device *phydev) if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) - bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0); + bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0); if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) || (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) || @@ -254,8 +222,8 @@ static int bcm5482_config_init(struct phy_device *phydev) /* * Enable secondary SerDes and its use as an LED source */ - reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD); - bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD, + reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_SSD); + bcm_phy_write_shadow(phydev, BCM5482_SHD_SSD, reg | BCM5482_SHD_SSD_LEDM | BCM5482_SHD_SSD_EN); @@ -264,10 +232,10 @@ static int bcm5482_config_init(struct phy_device *phydev) * Enable SGMII slave mode and auto-detection */ reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD; - err = bcm54xx_exp_read(phydev, reg); + err = bcm_phy_read_exp(phydev, reg); if (err < 0) return err; - err = bcm54xx_exp_write(phydev, reg, err | + err = bcm_phy_write_exp(phydev, reg, err | BCM5482_SSD_SGMII_SLAVE_EN | BCM5482_SSD_SGMII_SLAVE_AD); if (err < 0) @@ -277,10 +245,10 @@ static int bcm5482_config_init(struct phy_device *phydev) * Disable secondary SerDes powerdown */ reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD; - err = bcm54xx_exp_read(phydev, reg); + err = bcm_phy_read_exp(phydev, reg); if (err < 0) return err; - err = bcm54xx_exp_write(phydev, reg, + err = bcm_phy_write_exp(phydev, reg, err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN); if (err < 0) return err; @@ -288,15 +256,15 @@ static int bcm5482_config_init(struct phy_device *phydev) /* * Select 1000BASE-X register set (primary SerDes) */ - reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE); - bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE, + reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE); + bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE, reg | BCM5482_SHD_MODE_1000BX); /* * LED1=ACTIVITYLED, LED3=LINKSPD[2] * (Use LED1 as secondary SerDes ACTIVITY LED) */ - bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1, + bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) | BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2)); @@ -334,35 +302,6 @@ static int bcm5482_read_status(struct phy_device *phydev) return err; } -static int bcm54xx_ack_interrupt(struct phy_device *phydev) -{ - int reg; - - /* Clear pending interrupts. */ - reg = phy_read(phydev, MII_BCM54XX_ISR); - if (reg < 0) - return reg; - - return 0; -} - -static int bcm54xx_config_intr(struct phy_device *phydev) -{ - int reg, err; - - reg = phy_read(phydev, MII_BCM54XX_ECR); - if (reg < 0) - return reg; - - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) - reg &= ~MII_BCM54XX_ECR_IM; - else - reg |= MII_BCM54XX_ECR_IM; - - err = phy_write(phydev, MII_BCM54XX_ECR, reg); - return err; -} - static int bcm5481_config_aneg(struct phy_device *phydev) { int ret; @@ -519,8 +458,8 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .ack_interrupt = bcm54xx_ack_interrupt, - .config_intr = bcm54xx_config_intr, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, }, { .phy_id = PHY_ID_BCM5421, @@ -532,8 +471,8 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .ack_interrupt = bcm54xx_ack_interrupt, - .config_intr = bcm54xx_config_intr, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, }, { .phy_id = PHY_ID_BCM5461, @@ -545,8 +484,8 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .ack_interrupt = bcm54xx_ack_interrupt, - .config_intr = bcm54xx_config_intr, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, }, { .phy_id = PHY_ID_BCM54616S, @@ -558,8 +497,8 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .ack_interrupt = bcm54xx_ack_interrupt, - .config_intr = bcm54xx_config_intr, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, }, { .phy_id = PHY_ID_BCM5464, @@ -571,8 +510,8 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .ack_interrupt = bcm54xx_ack_interrupt, - .config_intr = bcm54xx_config_intr, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, }, { .phy_id = PHY_ID_BCM5481, @@ -584,8 +523,8 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_aneg = bcm5481_config_aneg, .read_status = genphy_read_status, - .ack_interrupt = bcm54xx_ack_interrupt, - .config_intr = bcm54xx_config_intr, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, }, { .phy_id = PHY_ID_BCM5482, @@ -597,8 +536,8 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm5482_config_init, .config_aneg = genphy_config_aneg, .read_status = bcm5482_read_status, - .ack_interrupt = bcm54xx_ack_interrupt, - .config_intr = bcm54xx_config_intr, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, }, { .phy_id = PHY_ID_BCM50610, @@ -610,8 +549,8 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .ack_interrupt = bcm54xx_ack_interrupt, - .config_intr = bcm54xx_config_intr, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, }, { .phy_id = PHY_ID_BCM50610M, @@ -623,8 +562,8 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .ack_interrupt = bcm54xx_ack_interrupt, - .config_intr = bcm54xx_config_intr, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, }, { .phy_id = PHY_ID_BCM57780, @@ -636,8 +575,8 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, - .ack_interrupt = bcm54xx_ack_interrupt, - .config_intr = bcm54xx_config_intr, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, .driver = { .owner = THIS_MODULE }, }, { .phy_id = PHY_ID_BCMAC131, -- cgit v1.2.3 From 8e185d6997bb67068f0ca8f062a50caa2608cf1b Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Tue, 6 Oct 2015 12:25:49 -0700 Subject: net: phy: Broadcom Cygnus internal Etherent PHY driver Add support for the Broadcom Cygnus SoCs internal PHY's. The PHYs are 1000M/100M/10M capable with support for 'EEE' and 'APD' (Auto Power Down). This driver supports the following Broadcom Cygnus SoCs: - BCM583XX (BCM58300, BCM58302, BCM58303, BCM58305) - BCM113XX (BCM11300, BCM11320, BCM11350, BCM11360) The PHY's on these SoC's require some workarounds for stable operation, both during configuration time and during suspend/resume. This driver handles the application of the workarounds. Signed-off-by: Arun Parameswaran Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 13 ++++ drivers/net/phy/Makefile | 1 + drivers/net/phy/bcm-cygnus.c | 158 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 drivers/net/phy/bcm-cygnus.c (limited to 'drivers/net') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 606fdc924768..9d097ae54fb2 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -79,6 +79,19 @@ config BROADCOM_PHY Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464, BCM5481 and BCM5482 PHYs. +config BCM_CYGNUS_PHY + tristate "Drivers for Broadcom Cygnus SoC internal PHY" + depends on ARCH_BCM_CYGNUS || COMPILE_TEST + depends on MDIO_BCM_IPROC + select BCM_NET_PHYLIB + ---help--- + This PHY driver is for the 1G internal PHYs of the Broadcom + Cygnus Family SoC. + + Currently supports internal PHY's used in the BCM11300, + BCM11320, BCM11350, BCM11360, BCM58300, BCM58302, + BCM58303 & BCM58305 Broadcom Cygnus SoCs. + config BCM63XX_PHY tristate "Drivers for Broadcom 63xx SOCs internal PHY" depends on BCM63XX diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 6932475a1a8a..7655d47ad8d8 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_BROADCOM_PHY) += broadcom.o obj-$(CONFIG_BCM63XX_PHY) += bcm63xx.o obj-$(CONFIG_BCM7XXX_PHY) += bcm7xxx.o obj-$(CONFIG_BCM87XX_PHY) += bcm87xx.o +obj-$(CONFIG_BCM_CYGNUS_PHY) += bcm-cygnus.o obj-$(CONFIG_ICPLUS_PHY) += icplus.o obj-$(CONFIG_REALTEK_PHY) += realtek.o obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o diff --git a/drivers/net/phy/bcm-cygnus.c b/drivers/net/phy/bcm-cygnus.c new file mode 100644 index 000000000000..49bbc6826883 --- /dev/null +++ b/drivers/net/phy/bcm-cygnus.c @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* Broadcom Cygnus SoC internal transceivers support. */ +#include "bcm-phy-lib.h" +#include +#include +#include +#include + +/* Broadcom Cygnus Phy specific registers */ +#define MII_BCM_CYGNUS_AFE_VDAC_ICTRL_0 0x91E5 /* VDAL Control register */ + +static int bcm_cygnus_afe_config(struct phy_device *phydev) +{ + int rc; + + /* ensure smdspclk is enabled */ + rc = phy_write(phydev, MII_BCM54XX_AUX_CTL, 0x0c30); + if (rc < 0) + return rc; + + /* AFE_VDAC_ICTRL_0 bit 7:4 Iq=1100 for 1g 10bt, normal modes */ + rc = bcm_phy_write_misc(phydev, 0x39, 0x01, 0xA7C8); + if (rc < 0) + return rc; + + /* AFE_HPF_TRIM_OTHERS bit11=1, short cascode enable for all modes*/ + rc = bcm_phy_write_misc(phydev, 0x3A, 0x00, 0x0803); + if (rc < 0) + return rc; + + /* AFE_TX_CONFIG_1 bit 7:4 Iq=1100 for test modes */ + rc = bcm_phy_write_misc(phydev, 0x3A, 0x01, 0xA740); + if (rc < 0) + return rc; + + /* AFE TEMPSEN_OTHERS rcal_HT, rcal_LT 10000 */ + rc = bcm_phy_write_misc(phydev, 0x3A, 0x03, 0x8400); + if (rc < 0) + return rc; + + /* AFE_FUTURE_RSV bit 2:0 rccal <2:0>=100 */ + rc = bcm_phy_write_misc(phydev, 0x3B, 0x00, 0x0004); + if (rc < 0) + return rc; + + /* Adjust bias current trim to overcome digital offSet */ + rc = phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x02); + if (rc < 0) + return rc; + + /* make rcal=100, since rdb default is 000 */ + rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB1, 0x10); + if (rc < 0) + return rc; + + /* CORE_EXPB0, Reset R_CAL/RC_CAL Engine */ + rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB0, 0x10); + if (rc < 0) + return rc; + + /* CORE_EXPB0, Disable Reset R_CAL/RC_CAL Engine */ + rc = bcm_phy_write_exp(phydev, MII_BRCM_CORE_EXPB0, 0x00); + + return 0; +} + +static int bcm_cygnus_config_init(struct phy_device *phydev) +{ + int reg, rc; + + reg = phy_read(phydev, MII_BCM54XX_ECR); + if (reg < 0) + return reg; + + /* Mask interrupts globally. */ + reg |= MII_BCM54XX_ECR_IM; + rc = phy_write(phydev, MII_BCM54XX_ECR, reg); + if (rc) + return rc; + + /* Unmask events of interest */ + reg = ~(MII_BCM54XX_INT_DUPLEX | + MII_BCM54XX_INT_SPEED | + MII_BCM54XX_INT_LINK); + rc = phy_write(phydev, MII_BCM54XX_IMR, reg); + if (rc) + return rc; + + /* Apply AFE settings for the PHY */ + rc = bcm_cygnus_afe_config(phydev); + if (rc) + return rc; + + /* Advertise EEE */ + rc = bcm_phy_enable_eee(phydev); + if (rc) + return rc; + + /* Enable APD */ + return bcm_phy_enable_apd(phydev, false); +} + +static int bcm_cygnus_resume(struct phy_device *phydev) +{ + int rc; + + genphy_resume(phydev); + + /* Re-initialize the PHY to apply AFE work-arounds and + * configurations when coming out of suspend. + */ + rc = bcm_cygnus_config_init(phydev); + if (rc) + return rc; + + /* restart auto negotiation with the new settings */ + return genphy_config_aneg(phydev); +} + +static struct phy_driver bcm_cygnus_phy_driver[] = { +{ + .phy_id = PHY_ID_BCM_CYGNUS, + .phy_id_mask = 0xfffffff0, + .name = "Broadcom Cygnus PHY", + .features = PHY_GBIT_FEATURES | + SUPPORTED_Pause | SUPPORTED_Asym_Pause, + .config_init = bcm_cygnus_config_init, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .ack_interrupt = bcm_phy_ack_intr, + .config_intr = bcm_phy_config_intr, + .suspend = genphy_suspend, + .resume = bcm_cygnus_resume, +} }; + +static struct mdio_device_id __maybe_unused bcm_cygnus_phy_tbl[] = { + { PHY_ID_BCM_CYGNUS, 0xfffffff0, }, + { } +}; +MODULE_DEVICE_TABLE(mdio, bcm_cygnus_phy_tbl); + +module_phy_driver(bcm_cygnus_phy_driver); + +MODULE_DESCRIPTION("Broadcom Cygnus internal PHY driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Broadcom Corporation"); -- cgit v1.2.3 From 9200c27a1cc7ac719e4c43411e5a170144ba0ac5 Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Tue, 6 Oct 2015 12:25:50 -0700 Subject: net: phy: bcm7xxx: Modified to use global core register defines Modified the bcm7xxx phy driver to remove local core register defines and use the common ones from "include/linux/brcmphy.h" Signed-off-by: Arun Parameswaran Signed-off-by: David S. Miller --- drivers/net/phy/bcm7xxx.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index efa31a655eb1..03d4809a9126 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -25,7 +25,6 @@ #define MII_BCM7XXX_100TX_DISC 0x14 #define MII_BCM7XXX_AUX_MODE 0x1d #define MII_BCM7XX_64CLK_MDIO BIT(12) -#define MII_BCM7XXX_CORE_BASE1E 0x1e #define MII_BCM7XXX_TEST 0x1f #define MII_BCM7XXX_SHD_MODE_2 BIT(2) @@ -46,8 +45,6 @@ #define AFE_VDAC_OTHERS_0 MISC_ADDR(0x39, 3) #define AFE_HPF_TRIM_OTHERS MISC_ADDR(0x3a, 0) -#define CORE_EXPB0 0xb0 - static void r_rc_cal_reset(struct phy_device *phydev) { /* Reset R_CAL/RC_CAL Engine */ @@ -76,7 +73,7 @@ static int bcm7xxx_28nm_b0_afe_config_init(struct phy_device *phydev) bcm_phy_write_misc(phydev, DSP_TAP10, 0x690b); /* Switch to CORE_BASE1E */ - phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0xd); + phy_write(phydev, MII_BRCM_CORE_BASE1E, 0xd); r_rc_cal_reset(phydev); @@ -127,7 +124,7 @@ static int bcm7xxx_28nm_d0_afe_config_init(struct phy_device *phydev) bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3); /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */ - phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010); + phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010); /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */ bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b); @@ -155,7 +152,7 @@ static int bcm7xxx_28nm_e0_plus_afe_config_init(struct phy_device *phydev) bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x00e3); /* CORE_BASE1E, force trim to overwrite and set I_ext trim to 0000 */ - phy_write(phydev, MII_BCM7XXX_CORE_BASE1E, 0x0010); + phy_write(phydev, MII_BRCM_CORE_BASE1E, 0x0010); /* DSP_TAP10, adjust bias current trim (+0% swing, +0 tick) */ bcm_phy_write_misc(phydev, DSP_TAP10, 0x011b); -- cgit v1.2.3 From d70e53262f5cfc0b88a211ef9cbd1ca5256f4a6b Mon Sep 17 00:00:00 2001 From: Jon Ringle Date: Tue, 6 Oct 2015 16:37:46 -0400 Subject: net: Microchip encx24j600 driver This ethernet driver supports the Micorchip enc424j600/626j600 Ethernet controller over a SPI bus interface. This driver makes use of the regmap API to optimize access to registers by caching registers where possible. Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/39935b.pdf Signed-off-by: Jon Ringle Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/Kconfig | 9 + drivers/net/ethernet/microchip/Makefile | 1 + drivers/net/ethernet/microchip/encx24j600-regmap.c | 513 +++++++++ drivers/net/ethernet/microchip/encx24j600.c | 1127 ++++++++++++++++++++ drivers/net/ethernet/microchip/encx24j600_hw.h | 437 ++++++++ 5 files changed, 2087 insertions(+) create mode 100644 drivers/net/ethernet/microchip/encx24j600-regmap.c create mode 100644 drivers/net/ethernet/microchip/encx24j600.c create mode 100644 drivers/net/ethernet/microchip/encx24j600_hw.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig index 3fd8ca6d4e7c..992b01462a8f 100644 --- a/drivers/net/ethernet/microchip/Kconfig +++ b/drivers/net/ethernet/microchip/Kconfig @@ -33,4 +33,13 @@ config ENC28J60_WRITEVERIFY Enable the verify after the buffer write useful for debugging purpose. If unsure, say N. +config ENCX24J600 + tristate "ENCX24J600 support" + depends on SPI + ---help--- + Support for the Microchip ENC424J600 ethernet chip. + + To compile this driver as a module, choose M here. The module will be + called enc424j600. + endif # NET_VENDOR_MICROCHIP diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile index 573d4292b9ea..ff78f621b59a 100644 --- a/drivers/net/ethernet/microchip/Makefile +++ b/drivers/net/ethernet/microchip/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_ENC28J60) += enc28j60.o +obj-$(CONFIG_ENCX24J600) += encx24j600.o encx24j600-regmap.o diff --git a/drivers/net/ethernet/microchip/encx24j600-regmap.c b/drivers/net/ethernet/microchip/encx24j600-regmap.c new file mode 100644 index 000000000000..f3bb9055a292 --- /dev/null +++ b/drivers/net/ethernet/microchip/encx24j600-regmap.c @@ -0,0 +1,513 @@ +/** + * Register map access API - ENCX24J600 support + * + * Copyright 2015 Gridpoint + * + * Author: Jon Ringle + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "encx24j600_hw.h" + +static inline bool is_bits_set(int value, int mask) +{ + return (value & mask) == mask; +} + +static int encx24j600_switch_bank(struct encx24j600_context *ctx, + int bank) +{ + int ret = 0; + + int bank_opcode = BANK_SELECT(bank); + ret = spi_write(ctx->spi, &bank_opcode, 1); + if (ret == 0) + ctx->bank = bank; + + return ret; +} + +static int encx24j600_cmdn(struct encx24j600_context *ctx, u8 opcode, + const void *buf, size_t len) +{ + struct spi_message m; + struct spi_transfer t[2] = { { .tx_buf = &opcode, .len = 1, }, + { .tx_buf = buf, .len = len }, }; + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + spi_message_add_tail(&t[1], &m); + + return spi_sync(ctx->spi, &m); +} + +static void regmap_lock_mutex(void *context) +{ + struct encx24j600_context *ctx = context; + mutex_lock(&ctx->mutex); +} + +static void regmap_unlock_mutex(void *context) +{ + struct encx24j600_context *ctx = context; + mutex_unlock(&ctx->mutex); +} + +static int regmap_encx24j600_sfr_read(void *context, u8 reg, u8 *val, + size_t len) +{ + struct encx24j600_context *ctx = context; + u8 banked_reg = reg & ADDR_MASK; + u8 bank = ((reg & BANK_MASK) >> BANK_SHIFT); + u8 cmd = RCRU; + int ret = 0; + int i = 0; + u8 tx_buf[2]; + + if (reg < 0x80) { + cmd = RCRCODE | banked_reg; + if ((banked_reg < 0x16) && (ctx->bank != bank)) + ret = encx24j600_switch_bank(ctx, bank); + if (unlikely(ret)) + return ret; + } else { + /* Translate registers that are more effecient using + * 3-byte SPI commands + */ + switch (reg) { + case EGPRDPT: + cmd = RGPRDPT; break; + case EGPWRPT: + cmd = RGPWRPT; break; + case ERXRDPT: + cmd = RRXRDPT; break; + case ERXWRPT: + cmd = RRXWRPT; break; + case EUDARDPT: + cmd = RUDARDPT; break; + case EUDAWRPT: + cmd = RUDAWRPT; break; + case EGPDATA: + case ERXDATA: + case EUDADATA: + default: + return -EINVAL; + } + } + + tx_buf[i++] = cmd; + if (cmd == RCRU) + tx_buf[i++] = reg; + + ret = spi_write_then_read(ctx->spi, tx_buf, i, val, len); + + return ret; +} + +static int regmap_encx24j600_sfr_update(struct encx24j600_context *ctx, + u8 reg, u8 *val, size_t len, + u8 unbanked_cmd, u8 banked_code) +{ + u8 banked_reg = reg & ADDR_MASK; + u8 bank = ((reg & BANK_MASK) >> BANK_SHIFT); + u8 cmd = unbanked_cmd; + struct spi_message m; + struct spi_transfer t[3] = { { .tx_buf = &cmd, .len = sizeof(cmd), }, + { .tx_buf = ®, .len = sizeof(reg), }, + { .tx_buf = val, .len = len }, }; + + if (reg < 0x80) { + int ret = 0; + cmd = banked_code | banked_reg; + if ((banked_reg < 0x16) && (ctx->bank != bank)) + ret = encx24j600_switch_bank(ctx, bank); + if (unlikely(ret)) + return ret; + } else { + /* Translate registers that are more effecient using + * 3-byte SPI commands + */ + switch (reg) { + case EGPRDPT: + cmd = WGPRDPT; break; + case EGPWRPT: + cmd = WGPWRPT; break; + case ERXRDPT: + cmd = WRXRDPT; break; + case ERXWRPT: + cmd = WRXWRPT; break; + case EUDARDPT: + cmd = WUDARDPT; break; + case EUDAWRPT: + cmd = WUDAWRPT; break; + case EGPDATA: + case ERXDATA: + case EUDADATA: + default: + return -EINVAL; + } + } + + spi_message_init(&m); + spi_message_add_tail(&t[0], &m); + + if (cmd == unbanked_cmd) { + t[1].tx_buf = ® + spi_message_add_tail(&t[1], &m); + } + + spi_message_add_tail(&t[2], &m); + return spi_sync(ctx->spi, &m); +} + +static int regmap_encx24j600_sfr_write(void *context, u8 reg, u8 *val, + size_t len) +{ + struct encx24j600_context *ctx = context; + return regmap_encx24j600_sfr_update(ctx, reg, val, len, WCRU, WCRCODE); +} + +static int regmap_encx24j600_sfr_set_bits(struct encx24j600_context *ctx, + u8 reg, u8 val) +{ + return regmap_encx24j600_sfr_update(ctx, reg, &val, 1, BFSU, BFSCODE); +} + +static int regmap_encx24j600_sfr_clr_bits(struct encx24j600_context *ctx, + u8 reg, u8 val) +{ + return regmap_encx24j600_sfr_update(ctx, reg, &val, 1, BFCU, BFCCODE); +} + +static int regmap_encx24j600_reg_update_bits(void *context, unsigned int reg, + unsigned int mask, + unsigned int val) +{ + struct encx24j600_context *ctx = context; + + int ret = 0; + unsigned int set_mask = mask & val; + unsigned int clr_mask = mask & ~val; + + if ((reg >= 0x40 && reg < 0x6c) || reg >= 0x80) + return -EINVAL; + + if (set_mask & 0xff) + ret = regmap_encx24j600_sfr_set_bits(ctx, reg, set_mask); + + set_mask = (set_mask & 0xff00) >> 8; + + if ((set_mask & 0xff) && (ret == 0)) + ret = regmap_encx24j600_sfr_set_bits(ctx, reg + 1, set_mask); + + if ((clr_mask & 0xff) && (ret == 0)) + ret = regmap_encx24j600_sfr_clr_bits(ctx, reg, clr_mask); + + clr_mask = (clr_mask & 0xff00) >> 8; + + if ((clr_mask & 0xff) && (ret == 0)) + ret = regmap_encx24j600_sfr_clr_bits(ctx, reg + 1, clr_mask); + + return ret; +} + +int regmap_encx24j600_spi_write(void *context, u8 reg, const u8 *data, + size_t count) +{ + struct encx24j600_context *ctx = context; + + if (reg < 0xc0) + return encx24j600_cmdn(ctx, reg, data, count); + else + /* SPI 1-byte command. Ignore data */ + return spi_write(ctx->spi, ®, 1); +} +EXPORT_SYMBOL_GPL(regmap_encx24j600_spi_write); + +int regmap_encx24j600_spi_read(void *context, u8 reg, u8 *data, size_t count) +{ + struct encx24j600_context *ctx = context; + + if (reg == RBSEL && count > 1) + count = 1; + + return spi_write_then_read(ctx->spi, ®, sizeof(reg), data, count); +} +EXPORT_SYMBOL_GPL(regmap_encx24j600_spi_read); + +static int regmap_encx24j600_write(void *context, const void *data, + size_t len) +{ + u8 *dout = (u8 *)data; + u8 reg = dout[0]; + ++dout; + --len; + + if (reg > 0xa0) + return regmap_encx24j600_spi_write(context, reg, dout, len); + + if (len > 2) + return -EINVAL; + + return regmap_encx24j600_sfr_write(context, reg, dout, len); +} + +static int regmap_encx24j600_read(void *context, + const void *reg_buf, size_t reg_size, + void *val, size_t val_size) +{ + u8 reg = *(const u8 *)reg_buf; + + if (reg_size != 1) { + pr_err("%s: reg=%02x reg_size=%zu\n", __func__, reg, reg_size); + return -EINVAL; + } + + if (reg > 0xa0) + return regmap_encx24j600_spi_read(context, reg, val, val_size); + + if (val_size > 2) { + pr_err("%s: reg=%02x val_size=%zu\n", __func__, reg, val_size); + return -EINVAL; + } + + return regmap_encx24j600_sfr_read(context, reg, val, val_size); +} + +static bool encx24j600_regmap_readable(struct device *dev, unsigned int reg) +{ + if ((reg < 0x36) || + ((reg >= 0x40) && (reg < 0x4c)) || + ((reg >= 0x52) && (reg < 0x56)) || + ((reg >= 0x60) && (reg < 0x66)) || + ((reg >= 0x68) && (reg < 0x80)) || + ((reg >= 0x86) && (reg < 0x92)) || + (reg == 0xc8)) + return true; + else + return false; +} + +static bool encx24j600_regmap_writeable(struct device *dev, unsigned int reg) +{ + if ((reg < 0x12) || + ((reg >= 0x14) && (reg < 0x1a)) || + ((reg >= 0x1c) && (reg < 0x36)) || + ((reg >= 0x40) && (reg < 0x4c)) || + ((reg >= 0x52) && (reg < 0x56)) || + ((reg >= 0x60) && (reg < 0x68)) || + ((reg >= 0x6c) && (reg < 0x80)) || + ((reg >= 0x86) && (reg < 0x92)) || + ((reg >= 0xc0) && (reg < 0xc8)) || + ((reg >= 0xca) && (reg < 0xf0))) + return true; + else + return false; +} + +static bool encx24j600_regmap_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ERXHEAD: + case EDMACS: + case ETXSTAT: + case ETXWIRE: + case ECON1: /* Can be modified via single byte cmds */ + case ECON2: /* Can be modified via single byte cmds */ + case ESTAT: + case EIR: /* Can be modified via single byte cmds */ + case MIRD: + case MISTAT: + return true; + default: + break; + } + + return false; +} + +static bool encx24j600_regmap_precious(struct device *dev, unsigned int reg) +{ + /* single byte cmds are precious */ + if (((reg >= 0xc0) && (reg < 0xc8)) || + ((reg >= 0xca) && (reg < 0xf0))) + return true; + else + return false; +} + +static int regmap_encx24j600_phy_reg_read(void *context, unsigned int reg, + unsigned int *val) +{ + struct encx24j600_context *ctx = context; + int ret; + unsigned int mistat; + + reg = MIREGADR_VAL | (reg & PHREG_MASK); + ret = regmap_write(ctx->regmap, MIREGADR, reg); + if (unlikely(ret)) + goto err_out; + + ret = regmap_write(ctx->regmap, MICMD, MIIRD); + if (unlikely(ret)) + goto err_out; + + usleep_range(26, 100); + while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) && + (mistat & BUSY)) + cpu_relax(); + + if (unlikely(ret)) + goto err_out; + + ret = regmap_write(ctx->regmap, MICMD, 0); + if (unlikely(ret)) + goto err_out; + + ret = regmap_read(ctx->regmap, MIRD, val); + +err_out: + if (ret) + pr_err("%s: error %d reading reg %02x\n", __func__, ret, + reg & PHREG_MASK); + + return ret; +} + +static int regmap_encx24j600_phy_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + struct encx24j600_context *ctx = context; + int ret; + unsigned int mistat; + + reg = MIREGADR_VAL | (reg & PHREG_MASK); + ret = regmap_write(ctx->regmap, MIREGADR, reg); + if (unlikely(ret)) + goto err_out; + + ret = regmap_write(ctx->regmap, MIWR, val); + if (unlikely(ret)) + goto err_out; + + usleep_range(26, 100); + while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) && + (mistat & BUSY)) + cpu_relax(); + +err_out: + if (ret) + pr_err("%s: error %d writing reg %02x=%04x\n", __func__, ret, + reg & PHREG_MASK, val); + + return ret; +} + +static bool encx24j600_phymap_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PHCON1: + case PHSTAT1: + case PHANA: + case PHANLPA: + case PHANE: + case PHCON2: + case PHSTAT2: + case PHSTAT3: + return true; + default: + return false; + } +} + +static bool encx24j600_phymap_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PHCON1: + case PHCON2: + case PHANA: + return true; + case PHSTAT1: + case PHSTAT2: + case PHSTAT3: + case PHANLPA: + case PHANE: + default: + return false; + } +} + +static bool encx24j600_phymap_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case PHSTAT1: + case PHSTAT2: + case PHSTAT3: + case PHANLPA: + case PHANE: + case PHCON2: + return true; + default: + return false; + } +} + +static struct regmap_config regcfg = { + .name = "reg", + .reg_bits = 8, + .val_bits = 16, + .max_register = 0xee, + .reg_stride = 2, + .cache_type = REGCACHE_RBTREE, + .val_format_endian = REGMAP_ENDIAN_LITTLE, + .readable_reg = encx24j600_regmap_readable, + .writeable_reg = encx24j600_regmap_writeable, + .volatile_reg = encx24j600_regmap_volatile, + .precious_reg = encx24j600_regmap_precious, + .lock = regmap_lock_mutex, + .unlock = regmap_unlock_mutex, +}; + +static struct regmap_bus regmap_encx24j600 = { + .write = regmap_encx24j600_write, + .read = regmap_encx24j600_read, + .reg_update_bits = regmap_encx24j600_reg_update_bits, +}; + +static struct regmap_config phycfg = { + .name = "phy", + .reg_bits = 8, + .val_bits = 16, + .max_register = 0x1f, + .cache_type = REGCACHE_RBTREE, + .val_format_endian = REGMAP_ENDIAN_LITTLE, + .readable_reg = encx24j600_phymap_readable, + .writeable_reg = encx24j600_phymap_writeable, + .volatile_reg = encx24j600_phymap_volatile, +}; +static struct regmap_bus phymap_encx24j600 = { + .reg_write = regmap_encx24j600_phy_reg_write, + .reg_read = regmap_encx24j600_phy_reg_read, +}; + +void devm_regmap_init_encx24j600(struct device *dev, + struct encx24j600_context *ctx) +{ + mutex_init(&ctx->mutex); + regcfg.lock_arg = ctx; + ctx->regmap = devm_regmap_init(dev, ®map_encx24j600, ctx, ®cfg); + ctx->phymap = devm_regmap_init(dev, &phymap_encx24j600, ctx, &phycfg); +} +EXPORT_SYMBOL_GPL(devm_regmap_init_encx24j600); + +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c new file mode 100644 index 000000000000..e1329d9c2acc --- /dev/null +++ b/drivers/net/ethernet/microchip/encx24j600.c @@ -0,0 +1,1127 @@ +/** + * Microchip ENCX24J600 ethernet driver + * + * Copyright (C) 2015 Gridpoint + * Author: Jon Ringle + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "encx24j600_hw.h" + +#define DRV_NAME "encx24j600" +#define DRV_VERSION "1.0" + +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) +static int debug = -1; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + +/* SRAM memory layout: + * + * 0x0000-0x05ff TX buffers 1.5KB (1*1536) reside in the GP area in SRAM + * 0x0600-0x5fff RX buffers 22.5KB (15*1536) reside in the RX area in SRAM + */ +#define ENC_TX_BUF_START 0x0000U +#define ENC_RX_BUF_START 0x0600U +#define ENC_RX_BUF_END 0x5fffU +#define ENC_SRAM_SIZE 0x6000U + +enum { + RXFILTER_NORMAL, + RXFILTER_MULTI, + RXFILTER_PROMISC +}; + +struct encx24j600_priv { + struct net_device *ndev; + struct mutex lock; /* device access lock */ + struct encx24j600_context ctx; + struct sk_buff *tx_skb; + struct task_struct *kworker_task; + struct kthread_worker kworker; + struct kthread_work tx_work; + struct kthread_work setrx_work; + u16 next_packet; + bool hw_enabled; + bool full_duplex; + bool autoneg; + u16 speed; + int rxfilter; + u32 msg_enable; +}; + +static void dump_packet(const char *msg, int len, const char *data) +{ + pr_debug(DRV_NAME ": %s - packet len:%d\n", msg, len); + print_hex_dump_bytes("pk data: ", DUMP_PREFIX_OFFSET, data, len); +} + +static void encx24j600_dump_rsv(struct encx24j600_priv *priv, const char *msg, + struct rsv *rsv) +{ + struct net_device *dev = priv->ndev; + + netdev_info(dev, "RX packet Len:%d\n", rsv->len); + netdev_dbg(dev, "%s - NextPk: 0x%04x\n", msg, + rsv->next_packet); + netdev_dbg(dev, "RxOK: %d, DribbleNibble: %d\n", + RSV_GETBIT(rsv->rxstat, RSV_RXOK), + RSV_GETBIT(rsv->rxstat, RSV_DRIBBLENIBBLE)); + netdev_dbg(dev, "CRCErr:%d, LenChkErr: %d, LenOutOfRange: %d\n", + RSV_GETBIT(rsv->rxstat, RSV_CRCERROR), + RSV_GETBIT(rsv->rxstat, RSV_LENCHECKERR), + RSV_GETBIT(rsv->rxstat, RSV_LENOUTOFRANGE)); + netdev_dbg(dev, "Multicast: %d, Broadcast: %d, LongDropEvent: %d, CarrierEvent: %d\n", + RSV_GETBIT(rsv->rxstat, RSV_RXMULTICAST), + RSV_GETBIT(rsv->rxstat, RSV_RXBROADCAST), + RSV_GETBIT(rsv->rxstat, RSV_RXLONGEVDROPEV), + RSV_GETBIT(rsv->rxstat, RSV_CARRIEREV)); + netdev_dbg(dev, "ControlFrame: %d, PauseFrame: %d, UnknownOp: %d, VLanTagFrame: %d\n", + RSV_GETBIT(rsv->rxstat, RSV_RXCONTROLFRAME), + RSV_GETBIT(rsv->rxstat, RSV_RXPAUSEFRAME), + RSV_GETBIT(rsv->rxstat, RSV_RXUNKNOWNOPCODE), + RSV_GETBIT(rsv->rxstat, RSV_RXTYPEVLAN)); +} + +static u16 encx24j600_read_reg(struct encx24j600_priv *priv, u8 reg) +{ + struct net_device *dev = priv->ndev; + unsigned int val = 0; + int ret = regmap_read(priv->ctx.regmap, reg, &val); + if (unlikely(ret)) + netif_err(priv, drv, dev, "%s: error %d reading reg %02x\n", + __func__, ret, reg); + return val; +} + +static void encx24j600_write_reg(struct encx24j600_priv *priv, u8 reg, u16 val) +{ + struct net_device *dev = priv->ndev; + int ret = regmap_write(priv->ctx.regmap, reg, val); + if (unlikely(ret)) + netif_err(priv, drv, dev, "%s: error %d writing reg %02x=%04x\n", + __func__, ret, reg, val); +} + +static void encx24j600_update_reg(struct encx24j600_priv *priv, u8 reg, + u16 mask, u16 val) +{ + struct net_device *dev = priv->ndev; + int ret = regmap_update_bits(priv->ctx.regmap, reg, mask, val); + if (unlikely(ret)) + netif_err(priv, drv, dev, "%s: error %d updating reg %02x=%04x~%04x\n", + __func__, ret, reg, val, mask); +} + +static u16 encx24j600_read_phy(struct encx24j600_priv *priv, u8 reg) +{ + struct net_device *dev = priv->ndev; + unsigned int val = 0; + int ret = regmap_read(priv->ctx.phymap, reg, &val); + if (unlikely(ret)) + netif_err(priv, drv, dev, "%s: error %d reading %02x\n", + __func__, ret, reg); + return val; +} + +static void encx24j600_write_phy(struct encx24j600_priv *priv, u8 reg, u16 val) +{ + struct net_device *dev = priv->ndev; + int ret = regmap_write(priv->ctx.phymap, reg, val); + if (unlikely(ret)) + netif_err(priv, drv, dev, "%s: error %d writing reg %02x=%04x\n", + __func__, ret, reg, val); +} + +static void encx24j600_clr_bits(struct encx24j600_priv *priv, u8 reg, u16 mask) +{ + encx24j600_update_reg(priv, reg, mask, 0); +} + +static void encx24j600_set_bits(struct encx24j600_priv *priv, u8 reg, u16 mask) +{ + encx24j600_update_reg(priv, reg, mask, mask); +} + +static void encx24j600_cmd(struct encx24j600_priv *priv, u8 cmd) +{ + struct net_device *dev = priv->ndev; + int ret = regmap_write(priv->ctx.regmap, cmd, 0); + if (unlikely(ret)) + netif_err(priv, drv, dev, "%s: error %d with cmd %02x\n", + __func__, ret, cmd); +} + +static int encx24j600_raw_read(struct encx24j600_priv *priv, u8 reg, u8 *data, + size_t count) +{ + int ret; + mutex_lock(&priv->ctx.mutex); + ret = regmap_encx24j600_spi_read(&priv->ctx, reg, data, count); + mutex_unlock(&priv->ctx.mutex); + + return ret; +} + +static int encx24j600_raw_write(struct encx24j600_priv *priv, u8 reg, + const u8 *data, size_t count) +{ + int ret; + mutex_lock(&priv->ctx.mutex); + ret = regmap_encx24j600_spi_write(&priv->ctx, reg, data, count); + mutex_unlock(&priv->ctx.mutex); + + return ret; +} + +static void encx24j600_update_phcon1(struct encx24j600_priv *priv) +{ + u16 phcon1 = encx24j600_read_phy(priv, PHCON1); + if (priv->autoneg == AUTONEG_ENABLE) { + phcon1 |= ANEN | RENEG; + } else { + phcon1 &= ~ANEN; + if (priv->speed == SPEED_100) + phcon1 |= SPD100; + else + phcon1 &= ~SPD100; + + if (priv->full_duplex) + phcon1 |= PFULDPX; + else + phcon1 &= ~PFULDPX; + } + encx24j600_write_phy(priv, PHCON1, phcon1); +} + +/* Waits for autonegotiation to complete. */ +static int encx24j600_wait_for_autoneg(struct encx24j600_priv *priv) +{ + struct net_device *dev = priv->ndev; + unsigned long timeout = jiffies + msecs_to_jiffies(2000); + u16 phstat1; + u16 estat; + int ret = 0; + + phstat1 = encx24j600_read_phy(priv, PHSTAT1); + while ((phstat1 & ANDONE) == 0) { + if (time_after(jiffies, timeout)) { + u16 phstat3; + + netif_notice(priv, drv, dev, "timeout waiting for autoneg done\n"); + + priv->autoneg = AUTONEG_DISABLE; + phstat3 = encx24j600_read_phy(priv, PHSTAT3); + priv->speed = (phstat3 & PHY3SPD100) + ? SPEED_100 : SPEED_10; + priv->full_duplex = (phstat3 & PHY3DPX) ? 1 : 0; + encx24j600_update_phcon1(priv); + netif_notice(priv, drv, dev, "Using parallel detection: %s/%s", + priv->speed == SPEED_100 ? "100" : "10", + priv->full_duplex ? "Full" : "Half"); + + return -ETIMEDOUT; + } + cpu_relax(); + phstat1 = encx24j600_read_phy(priv, PHSTAT1); + } + + estat = encx24j600_read_reg(priv, ESTAT); + if (estat & PHYDPX) { + encx24j600_set_bits(priv, MACON2, FULDPX); + encx24j600_write_reg(priv, MABBIPG, 0x15); + } else { + encx24j600_clr_bits(priv, MACON2, FULDPX); + encx24j600_write_reg(priv, MABBIPG, 0x12); + /* Max retransmittions attempt */ + encx24j600_write_reg(priv, MACLCON, 0x370f); + } + + return ret; +} + +/* Access the PHY to determine link status */ +static void encx24j600_check_link_status(struct encx24j600_priv *priv) +{ + struct net_device *dev = priv->ndev; + u16 estat; + + estat = encx24j600_read_reg(priv, ESTAT); + + if (estat & PHYLNK) { + if (priv->autoneg == AUTONEG_ENABLE) + encx24j600_wait_for_autoneg(priv); + + netif_carrier_on(dev); + netif_info(priv, ifup, dev, "link up\n"); + } else { + netif_info(priv, ifdown, dev, "link down\n"); + + /* Re-enable autoneg since we won't know what we might be + * connected to when the link is brought back up again. + */ + priv->autoneg = AUTONEG_ENABLE; + priv->full_duplex = true; + priv->speed = SPEED_100; + netif_carrier_off(dev); + } +} + +static void encx24j600_int_link_handler(struct encx24j600_priv *priv) +{ + struct net_device *dev = priv->ndev; + + netif_dbg(priv, intr, dev, "%s", __func__); + encx24j600_check_link_status(priv); + encx24j600_clr_bits(priv, EIR, LINKIF); +} + +static void encx24j600_tx_complete(struct encx24j600_priv *priv, bool err) +{ + struct net_device *dev = priv->ndev; + + if (!priv->tx_skb) { + BUG(); + return; + } + + mutex_lock(&priv->lock); + + if (err) + dev->stats.tx_errors++; + else + dev->stats.tx_packets++; + + dev->stats.tx_bytes += priv->tx_skb->len; + + encx24j600_clr_bits(priv, EIR, TXIF | TXABTIF); + + netif_dbg(priv, tx_done, dev, "TX Done%s\n", err ? ": Err" : ""); + + dev_kfree_skb(priv->tx_skb); + priv->tx_skb = NULL; + + netif_wake_queue(dev); + + mutex_unlock(&priv->lock); +} + +static int encx24j600_receive_packet(struct encx24j600_priv *priv, + struct rsv *rsv) +{ + struct net_device *dev = priv->ndev; + struct sk_buff *skb = netdev_alloc_skb(dev, rsv->len + NET_IP_ALIGN); + if (!skb) { + pr_err_ratelimited("RX: OOM: packet dropped\n"); + dev->stats.rx_dropped++; + return -ENOMEM; + } + skb_reserve(skb, NET_IP_ALIGN); + encx24j600_raw_read(priv, RRXDATA, skb_put(skb, rsv->len), rsv->len); + + if (netif_msg_pktdata(priv)) + dump_packet("RX", skb->len, skb->data); + + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + skb->ip_summed = CHECKSUM_COMPLETE; + + /* Maintain stats */ + dev->stats.rx_packets++; + dev->stats.rx_bytes += rsv->len; + priv->next_packet = rsv->next_packet; + + netif_rx(skb); + + return 0; +} + +static void encx24j600_rx_packets(struct encx24j600_priv *priv, u8 packet_count) +{ + struct net_device *dev = priv->ndev; + + while (packet_count--) { + struct rsv rsv; + u16 newrxtail; + + encx24j600_write_reg(priv, ERXRDPT, priv->next_packet); + encx24j600_raw_read(priv, RRXDATA, (u8 *)&rsv, sizeof(rsv)); + + if (netif_msg_rx_status(priv)) + encx24j600_dump_rsv(priv, __func__, &rsv); + + if (!RSV_GETBIT(rsv.rxstat, RSV_RXOK) || + (rsv.len > MAX_FRAMELEN)) { + netif_err(priv, rx_err, dev, "RX Error %04x\n", + rsv.rxstat); + dev->stats.rx_errors++; + + if (RSV_GETBIT(rsv.rxstat, RSV_CRCERROR)) + dev->stats.rx_crc_errors++; + if (RSV_GETBIT(rsv.rxstat, RSV_LENCHECKERR)) + dev->stats.rx_frame_errors++; + if (rsv.len > MAX_FRAMELEN) + dev->stats.rx_over_errors++; + } else { + encx24j600_receive_packet(priv, &rsv); + } + + newrxtail = priv->next_packet - 2; + if (newrxtail == ENC_RX_BUF_START) + newrxtail = SRAM_SIZE - 2; + + encx24j600_cmd(priv, SETPKTDEC); + encx24j600_write_reg(priv, ERXTAIL, newrxtail); + } +} + +static irqreturn_t encx24j600_isr(int irq, void *dev_id) +{ + struct encx24j600_priv *priv = dev_id; + struct net_device *dev = priv->ndev; + int eir; + + /* Clear interrupts */ + encx24j600_cmd(priv, CLREIE); + + eir = encx24j600_read_reg(priv, EIR); + + if (eir & LINKIF) + encx24j600_int_link_handler(priv); + + if (eir & TXIF) + encx24j600_tx_complete(priv, false); + + if (eir & TXABTIF) + encx24j600_tx_complete(priv, true); + + if (eir & RXABTIF) { + if (eir & PCFULIF) { + /* Packet counter is full */ + netif_err(priv, rx_err, dev, "Packet counter full\n"); + } + dev->stats.rx_dropped++; + encx24j600_clr_bits(priv, EIR, RXABTIF); + } + + if (eir & PKTIF) { + u8 packet_count; + + mutex_lock(&priv->lock); + + packet_count = encx24j600_read_reg(priv, ESTAT) & 0xff; + while (packet_count) { + encx24j600_rx_packets(priv, packet_count); + packet_count = encx24j600_read_reg(priv, ESTAT) & 0xff; + } + + mutex_unlock(&priv->lock); + } + + /* Enable interrupts */ + encx24j600_cmd(priv, SETEIE); + + return IRQ_HANDLED; +} + +static int encx24j600_soft_reset(struct encx24j600_priv *priv) +{ + int ret = 0; + int timeout; + u16 eudast; + + /* Write and verify a test value to EUDAST */ + regcache_cache_bypass(priv->ctx.regmap, true); + timeout = 10; + do { + encx24j600_write_reg(priv, EUDAST, EUDAST_TEST_VAL); + eudast = encx24j600_read_reg(priv, EUDAST); + usleep_range(25, 100); + } while ((eudast != EUDAST_TEST_VAL) && --timeout); + regcache_cache_bypass(priv->ctx.regmap, false); + + if (timeout == 0) { + ret = -ETIMEDOUT; + goto err_out; + } + + /* Wait for CLKRDY to become set */ + timeout = 10; + while (!(encx24j600_read_reg(priv, ESTAT) & CLKRDY) && --timeout) + usleep_range(25, 100); + + if (timeout == 0) { + ret = -ETIMEDOUT; + goto err_out; + } + + /* Issue a System Reset command */ + encx24j600_cmd(priv, SETETHRST); + usleep_range(25, 100); + + /* Confirm that EUDAST has 0000h after system reset */ + if (encx24j600_read_reg(priv, EUDAST) != 0) { + ret = -EINVAL; + goto err_out; + } + + /* Wait for PHY register and status bits to become available */ + usleep_range(256, 1000); + +err_out: + return ret; +} + +static int encx24j600_hw_reset(struct encx24j600_priv *priv) +{ + int ret; + + mutex_lock(&priv->lock); + ret = encx24j600_soft_reset(priv); + mutex_unlock(&priv->lock); + + return ret; +} + +static void encx24j600_reset_hw_tx(struct encx24j600_priv *priv) +{ + encx24j600_set_bits(priv, ECON2, TXRST); + encx24j600_clr_bits(priv, ECON2, TXRST); +} + +static void encx24j600_hw_init_tx(struct encx24j600_priv *priv) +{ + /* Reset TX */ + encx24j600_reset_hw_tx(priv); + + /* Clear the TXIF flag if were previously set */ + encx24j600_clr_bits(priv, EIR, TXIF | TXABTIF); + + /* Write the Tx Buffer pointer */ + encx24j600_write_reg(priv, EGPWRPT, ENC_TX_BUF_START); +} + +static void encx24j600_hw_init_rx(struct encx24j600_priv *priv) +{ + encx24j600_cmd(priv, DISABLERX); + + /* Set up RX packet start address in the SRAM */ + encx24j600_write_reg(priv, ERXST, ENC_RX_BUF_START); + + /* Preload the RX Data pointer to the beginning of the RX area */ + encx24j600_write_reg(priv, ERXRDPT, ENC_RX_BUF_START); + + priv->next_packet = ENC_RX_BUF_START; + + /* Set up RX end address in the SRAM */ + encx24j600_write_reg(priv, ERXTAIL, ENC_SRAM_SIZE - 2); + + /* Reset the user data pointers */ + encx24j600_write_reg(priv, EUDAST, ENC_SRAM_SIZE); + encx24j600_write_reg(priv, EUDAND, ENC_SRAM_SIZE + 1); + + /* Set Max Frame length */ + encx24j600_write_reg(priv, MAMXFL, MAX_FRAMELEN); +} + +static void encx24j600_dump_config(struct encx24j600_priv *priv, + const char *msg) +{ + pr_info(DRV_NAME ": %s\n", msg); + + /* CHIP configuration */ + pr_info(DRV_NAME " ECON1: %04X\n", encx24j600_read_reg(priv, ECON1)); + pr_info(DRV_NAME " ECON2: %04X\n", encx24j600_read_reg(priv, ECON2)); + pr_info(DRV_NAME " ERXFCON: %04X\n", encx24j600_read_reg(priv, + ERXFCON)); + pr_info(DRV_NAME " ESTAT: %04X\n", encx24j600_read_reg(priv, ESTAT)); + pr_info(DRV_NAME " EIR: %04X\n", encx24j600_read_reg(priv, EIR)); + pr_info(DRV_NAME " EIDLED: %04X\n", encx24j600_read_reg(priv, EIDLED)); + + /* MAC layer configuration */ + pr_info(DRV_NAME " MACON1: %04X\n", encx24j600_read_reg(priv, MACON1)); + pr_info(DRV_NAME " MACON2: %04X\n", encx24j600_read_reg(priv, MACON2)); + pr_info(DRV_NAME " MAIPG: %04X\n", encx24j600_read_reg(priv, MAIPG)); + pr_info(DRV_NAME " MACLCON: %04X\n", encx24j600_read_reg(priv, + MACLCON)); + pr_info(DRV_NAME " MABBIPG: %04X\n", encx24j600_read_reg(priv, + MABBIPG)); + + /* PHY configuation */ + pr_info(DRV_NAME " PHCON1: %04X\n", encx24j600_read_phy(priv, PHCON1)); + pr_info(DRV_NAME " PHCON2: %04X\n", encx24j600_read_phy(priv, PHCON2)); + pr_info(DRV_NAME " PHANA: %04X\n", encx24j600_read_phy(priv, PHANA)); + pr_info(DRV_NAME " PHANLPA: %04X\n", encx24j600_read_phy(priv, + PHANLPA)); + pr_info(DRV_NAME " PHANE: %04X\n", encx24j600_read_phy(priv, PHANE)); + pr_info(DRV_NAME " PHSTAT1: %04X\n", encx24j600_read_phy(priv, + PHSTAT1)); + pr_info(DRV_NAME " PHSTAT2: %04X\n", encx24j600_read_phy(priv, + PHSTAT2)); + pr_info(DRV_NAME " PHSTAT3: %04X\n", encx24j600_read_phy(priv, + PHSTAT3)); +} + +static void encx24j600_set_rxfilter_mode(struct encx24j600_priv *priv) +{ + switch (priv->rxfilter) { + case RXFILTER_PROMISC: + encx24j600_set_bits(priv, MACON1, PASSALL); + encx24j600_write_reg(priv, ERXFCON, UCEN | MCEN | NOTMEEN); + break; + case RXFILTER_MULTI: + encx24j600_clr_bits(priv, MACON1, PASSALL); + encx24j600_write_reg(priv, ERXFCON, UCEN | CRCEN | BCEN | MCEN); + break; + case RXFILTER_NORMAL: + default: + encx24j600_clr_bits(priv, MACON1, PASSALL); + encx24j600_write_reg(priv, ERXFCON, UCEN | CRCEN | BCEN); + break; + } +} + +static int encx24j600_hw_init(struct encx24j600_priv *priv) +{ + struct net_device *dev = priv->ndev; + int ret = 0; + u16 eidled; + u16 macon2; + + priv->hw_enabled = false; + + eidled = encx24j600_read_reg(priv, EIDLED); + if (((eidled & DEVID_MASK) >> DEVID_SHIFT) != ENCX24J600_DEV_ID) { + ret = -EINVAL; + goto err_out; + } + + netif_info(priv, drv, dev, "Silicon rev ID: 0x%02x\n", + (eidled & REVID_MASK) >> REVID_SHIFT); + + /* PHY Leds: link status, + * LEDA: Link + transmit/receive events + * LEDB: Link State + colision events + */ + encx24j600_update_reg(priv, EIDLED, 0xbc00, 0xbc00); + + /* Loopback disabled */ + encx24j600_write_reg(priv, MACON1, 0x9); + + /* interpacket gap value */ + encx24j600_write_reg(priv, MAIPG, 0x0c12); + + /* Write the auto negotiation pattern */ + encx24j600_write_phy(priv, PHANA, PHANA_DEFAULT); + + encx24j600_update_phcon1(priv); + encx24j600_check_link_status(priv); + + macon2 = MACON2_RSV1 | TXCRCEN | PADCFG0 | PADCFG2 | MACON2_DEFER; + if ((priv->autoneg == AUTONEG_DISABLE) && priv->full_duplex) + macon2 |= FULDPX; + + encx24j600_set_bits(priv, MACON2, macon2); + + priv->rxfilter = RXFILTER_NORMAL; + encx24j600_set_rxfilter_mode(priv); + + /* Program the Maximum frame length */ + encx24j600_write_reg(priv, MAMXFL, MAX_FRAMELEN); + + /* Init Tx pointers */ + encx24j600_hw_init_tx(priv); + + /* Init Rx pointers */ + encx24j600_hw_init_rx(priv); + + if (netif_msg_hw(priv)) + encx24j600_dump_config(priv, "Hw is initialized"); + +err_out: + return ret; +} + +static void encx24j600_hw_enable(struct encx24j600_priv *priv) +{ + /* Clear the interrupt flags in case was set */ + encx24j600_clr_bits(priv, EIR, (PCFULIF | RXABTIF | TXABTIF | TXIF | + PKTIF | LINKIF)); + + /* Enable the interrupts */ + encx24j600_write_reg(priv, EIE, (PCFULIE | RXABTIE | TXABTIE | TXIE | + PKTIE | LINKIE | INTIE)); + + /* Enable RX */ + encx24j600_cmd(priv, ENABLERX); + + priv->hw_enabled = true; +} + +static void encx24j600_hw_disable(struct encx24j600_priv *priv) +{ + /* Disable all interrupts */ + encx24j600_write_reg(priv, EIE, 0); + + /* Disable RX */ + encx24j600_cmd(priv, DISABLERX); + + priv->hw_enabled = false; +} + +static int encx24j600_setlink(struct net_device *dev, u8 autoneg, u16 speed, + u8 duplex) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + int ret = 0; + + if (!priv->hw_enabled) { + /* link is in low power mode now; duplex setting + * will take effect on next encx24j600_hw_init() + */ + if (speed == SPEED_10 || speed == SPEED_100) { + priv->autoneg = (autoneg == AUTONEG_ENABLE); + priv->full_duplex = (duplex == DUPLEX_FULL); + priv->speed = (speed == SPEED_100); + } else { + netif_warn(priv, link, dev, "unsupported link speed setting\n"); + /*speeds other than SPEED_10 and SPEED_100 */ + /*are not supported by chip */ + ret = -EOPNOTSUPP; + } + } else { + netif_warn(priv, link, dev, "Warning: hw must be disabled to set link mode\n"); + ret = -EBUSY; + } + return ret; +} + +static void encx24j600_hw_get_macaddr(struct encx24j600_priv *priv, + unsigned char *ethaddr) +{ + unsigned short val; + + val = encx24j600_read_reg(priv, MAADR1); + + ethaddr[0] = val & 0x00ff; + ethaddr[1] = (val & 0xff00) >> 8; + + val = encx24j600_read_reg(priv, MAADR2); + + ethaddr[2] = val & 0x00ffU; + ethaddr[3] = (val & 0xff00U) >> 8; + + val = encx24j600_read_reg(priv, MAADR3); + + ethaddr[4] = val & 0x00ffU; + ethaddr[5] = (val & 0xff00U) >> 8; +} + +/* Program the hardware MAC address from dev->dev_addr.*/ +static int encx24j600_set_hw_macaddr(struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + + if (priv->hw_enabled) { + netif_info(priv, drv, dev, "Hardware must be disabled to set Mac address\n"); + return -EBUSY; + } + + mutex_lock(&priv->lock); + + netif_info(priv, drv, dev, "%s: Setting MAC address to %pM\n", + dev->name, dev->dev_addr); + + encx24j600_write_reg(priv, MAADR3, (dev->dev_addr[4] | + dev->dev_addr[5] << 8)); + encx24j600_write_reg(priv, MAADR2, (dev->dev_addr[2] | + dev->dev_addr[3] << 8)); + encx24j600_write_reg(priv, MAADR1, (dev->dev_addr[0] | + dev->dev_addr[1] << 8)); + + mutex_unlock(&priv->lock); + + return 0; +} + +/* Store the new hardware address in dev->dev_addr, and update the MAC.*/ +static int encx24j600_set_mac_address(struct net_device *dev, void *addr) +{ + struct sockaddr *address = addr; + + if (netif_running(dev)) + return -EBUSY; + if (!is_valid_ether_addr(address->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, address->sa_data, dev->addr_len); + return encx24j600_set_hw_macaddr(dev); +} + +static int encx24j600_open(struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + + int ret = request_threaded_irq(priv->ctx.spi->irq, NULL, encx24j600_isr, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + DRV_NAME, priv); + if (unlikely(ret < 0)) { + netdev_err(dev, "request irq %d failed (ret = %d)\n", + priv->ctx.spi->irq, ret); + return ret; + } + + encx24j600_hw_disable(priv); + encx24j600_hw_init(priv); + encx24j600_hw_enable(priv); + netif_start_queue(dev); + + return 0; +} + +static int encx24j600_stop(struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + + netif_stop_queue(dev); + free_irq(priv->ctx.spi->irq, priv); + return 0; +} + +static void encx24j600_setrx_proc(struct kthread_work *ws) +{ + struct encx24j600_priv *priv = + container_of(ws, struct encx24j600_priv, setrx_work); + + mutex_lock(&priv->lock); + encx24j600_set_rxfilter_mode(priv); + mutex_unlock(&priv->lock); +} + +static void encx24j600_set_multicast_list(struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + int oldfilter = priv->rxfilter; + + if (dev->flags & IFF_PROMISC) { + netif_dbg(priv, link, dev, "promiscuous mode\n"); + priv->rxfilter = RXFILTER_PROMISC; + } else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) { + netif_dbg(priv, link, dev, "%smulticast mode\n", + (dev->flags & IFF_ALLMULTI) ? "all-" : ""); + priv->rxfilter = RXFILTER_MULTI; + } else { + netif_dbg(priv, link, dev, "normal mode\n"); + priv->rxfilter = RXFILTER_NORMAL; + } + + if (oldfilter != priv->rxfilter) + queue_kthread_work(&priv->kworker, &priv->setrx_work); +} + +static void encx24j600_hw_tx(struct encx24j600_priv *priv) +{ + struct net_device *dev = priv->ndev; + netif_info(priv, tx_queued, dev, "TX Packet Len:%d\n", + priv->tx_skb->len); + + if (netif_msg_pktdata(priv)) + dump_packet("TX", priv->tx_skb->len, priv->tx_skb->data); + + if (encx24j600_read_reg(priv, EIR) & TXABTIF) + /* Last transmition aborted due to error. Reset TX interface */ + encx24j600_reset_hw_tx(priv); + + /* Clear the TXIF flag if were previously set */ + encx24j600_clr_bits(priv, EIR, TXIF); + + /* Set the data pointer to the TX buffer address in the SRAM */ + encx24j600_write_reg(priv, EGPWRPT, ENC_TX_BUF_START); + + /* Copy the packet into the SRAM */ + encx24j600_raw_write(priv, WGPDATA, (u8 *)priv->tx_skb->data, + priv->tx_skb->len); + + /* Program the Tx buffer start pointer */ + encx24j600_write_reg(priv, ETXST, ENC_TX_BUF_START); + + /* Program the packet length */ + encx24j600_write_reg(priv, ETXLEN, priv->tx_skb->len); + + /* Start the transmission */ + encx24j600_cmd(priv, SETTXRTS); +} + +static void encx24j600_tx_proc(struct kthread_work *ws) +{ + struct encx24j600_priv *priv = + container_of(ws, struct encx24j600_priv, tx_work); + + mutex_lock(&priv->lock); + encx24j600_hw_tx(priv); + mutex_unlock(&priv->lock); +} + +static netdev_tx_t encx24j600_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + + netif_stop_queue(dev); + + /* save the timestamp */ + dev->trans_start = jiffies; + + /* Remember the skb for deferred processing */ + priv->tx_skb = skb; + + queue_kthread_work(&priv->kworker, &priv->tx_work); + + return NETDEV_TX_OK; +} + +/* Deal with a transmit timeout */ +static void encx24j600_tx_timeout(struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + + netif_err(priv, tx_err, dev, "TX timeout at %ld, latency %ld\n", + jiffies, jiffies - dev->trans_start); + + dev->stats.tx_errors++; + netif_wake_queue(dev); + return; +} + +static int encx24j600_get_regs_len(struct net_device *dev) +{ + return SFR_REG_COUNT; +} + +static void encx24j600_get_regs(struct net_device *dev, + struct ethtool_regs *regs, void *p) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + u16 *buff = p; + u8 reg; + + regs->version = 1; + mutex_lock(&priv->lock); + for (reg = 0; reg < SFR_REG_COUNT; reg += 2) { + unsigned int val = 0; + /* ignore errors for unreadable registers */ + regmap_read(priv->ctx.regmap, reg, &val); + buff[reg] = val & 0xffff; + } + mutex_unlock(&priv->lock); +} + +static void encx24j600_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_VERSION, sizeof(info->version)); + strlcpy(info->bus_info, dev_name(dev->dev.parent), + sizeof(info->bus_info)); +} + +static int encx24j600_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + + cmd->transceiver = XCVR_INTERNAL; + cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | + SUPPORTED_Autoneg | SUPPORTED_TP; + + ethtool_cmd_speed_set(cmd, priv->speed); + cmd->duplex = priv->full_duplex ? DUPLEX_FULL : DUPLEX_HALF; + cmd->port = PORT_TP; + cmd->autoneg = priv->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; + + return 0; +} + +static int encx24j600_set_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + return encx24j600_setlink(dev, cmd->autoneg, + ethtool_cmd_speed(cmd), cmd->duplex); +} + +static u32 encx24j600_get_msglevel(struct net_device *dev) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + return priv->msg_enable; +} + +static void encx24j600_set_msglevel(struct net_device *dev, u32 val) +{ + struct encx24j600_priv *priv = netdev_priv(dev); + priv->msg_enable = val; +} + +static const struct ethtool_ops encx24j600_ethtool_ops = { + .get_settings = encx24j600_get_settings, + .set_settings = encx24j600_set_settings, + .get_drvinfo = encx24j600_get_drvinfo, + .get_msglevel = encx24j600_get_msglevel, + .set_msglevel = encx24j600_set_msglevel, + .get_regs_len = encx24j600_get_regs_len, + .get_regs = encx24j600_get_regs, +}; + +static const struct net_device_ops encx24j600_netdev_ops = { + .ndo_open = encx24j600_open, + .ndo_stop = encx24j600_stop, + .ndo_start_xmit = encx24j600_tx, + .ndo_set_rx_mode = encx24j600_set_multicast_list, + .ndo_set_mac_address = encx24j600_set_mac_address, + .ndo_tx_timeout = encx24j600_tx_timeout, + .ndo_validate_addr = eth_validate_addr, +}; + +static int encx24j600_spi_probe(struct spi_device *spi) +{ + int ret; + + struct net_device *ndev; + struct encx24j600_priv *priv; + + ndev = alloc_etherdev(sizeof(struct encx24j600_priv)); + + if (!ndev) { + ret = -ENOMEM; + goto error_out; + } + + priv = netdev_priv(ndev); + spi_set_drvdata(spi, priv); + dev_set_drvdata(&spi->dev, priv); + SET_NETDEV_DEV(ndev, &spi->dev); + + priv->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); + priv->ndev = ndev; + + /* Default configuration PHY configuration */ + priv->full_duplex = true; + priv->autoneg = AUTONEG_ENABLE; + priv->speed = SPEED_100; + + priv->ctx.spi = spi; + devm_regmap_init_encx24j600(&spi->dev, &priv->ctx); + ndev->irq = spi->irq; + ndev->netdev_ops = &encx24j600_netdev_ops; + + mutex_init(&priv->lock); + + /* Reset device and check if it is connected */ + if (encx24j600_hw_reset(priv)) { + netif_err(priv, probe, ndev, + DRV_NAME ": Chip is not detected\n"); + ret = -EIO; + goto out_free; + } + + /* Initialize the device HW to the consistent state */ + if (encx24j600_hw_init(priv)) { + netif_err(priv, probe, ndev, + DRV_NAME ": HW initialization error\n"); + ret = -EIO; + goto out_free; + } + + init_kthread_worker(&priv->kworker); + init_kthread_work(&priv->tx_work, encx24j600_tx_proc); + init_kthread_work(&priv->setrx_work, encx24j600_setrx_proc); + + priv->kworker_task = kthread_run(kthread_worker_fn, &priv->kworker, + "encx24j600"); + + if (IS_ERR(priv->kworker_task)) { + ret = PTR_ERR(priv->kworker_task); + goto out_free; + } + + /* Get the MAC address from the chip */ + encx24j600_hw_get_macaddr(priv, ndev->dev_addr); + + ndev->ethtool_ops = &encx24j600_ethtool_ops; + + ret = register_netdev(ndev); + if (unlikely(ret)) { + netif_err(priv, probe, ndev, "Error %d initializing card encx24j600 card\n", + ret); + goto out_free; + } + + netif_info(priv, drv, priv->ndev, "MAC address %pM\n", ndev->dev_addr); + + return ret; + +out_free: + free_netdev(ndev); + +error_out: + return ret; +} + +static int encx24j600_spi_remove(struct spi_device *spi) +{ + struct encx24j600_priv *priv = dev_get_drvdata(&spi->dev); + + unregister_netdev(priv->ndev); + + free_netdev(priv->ndev); + + return 0; +} + +static const struct spi_device_id encx24j600_spi_id_table = { + .name = "encx24j600" +}; + +static struct spi_driver encx24j600_spi_net_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .bus = &spi_bus_type, + }, + .probe = encx24j600_spi_probe, + .remove = encx24j600_spi_remove, + .id_table = &encx24j600_spi_id_table, +}; + +static int __init encx24j600_init(void) +{ + return spi_register_driver(&encx24j600_spi_net_driver); +} +module_init(encx24j600_init); + +static void encx24j600_exit(void) +{ + spi_unregister_driver(&encx24j600_spi_net_driver); +} +module_exit(encx24j600_exit); + +MODULE_DESCRIPTION(DRV_NAME " ethernet driver"); +MODULE_AUTHOR("Jon Ringle "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:" DRV_NAME); diff --git a/drivers/net/ethernet/microchip/encx24j600_hw.h b/drivers/net/ethernet/microchip/encx24j600_hw.h new file mode 100644 index 000000000000..4be73d5553f8 --- /dev/null +++ b/drivers/net/ethernet/microchip/encx24j600_hw.h @@ -0,0 +1,437 @@ +/** + * encx24j600_hw.h: Register definitions + * + */ + +#ifndef _ENCX24J600_HW_H +#define _ENCX24J600_HW_H + +struct encx24j600_context { + struct spi_device *spi; + struct regmap *regmap; + struct regmap *phymap; + struct mutex mutex; /* mutex to protect access to regmap */ + int bank; +}; + +void devm_regmap_init_encx24j600(struct device *dev, + struct encx24j600_context *ctx); + +/* Single-byte instructions */ +#define BANK_SELECT(bank) (0xC0 | ((bank & (BANK_MASK >> BANK_SHIFT)) << 1)) +#define B0SEL 0xC0 /* Bank 0 Select */ +#define B1SEL 0xC2 /* Bank 1 Select */ +#define B2SEL 0xC4 /* Bank 2 Select */ +#define B3SEL 0xC6 /* Bank 3 Select */ +#define SETETHRST 0xCA /* System Reset */ +#define FCDISABLE 0xE0 /* Flow Control Disable */ +#define FCSINGLE 0xE2 /* Flow Control Single */ +#define FCMULTIPLE 0xE4 /* Flow Control Multiple */ +#define FCCLEAR 0xE6 /* Flow Control Clear */ +#define SETPKTDEC 0xCC /* Decrement Packet Counter */ +#define DMASTOP 0xD2 /* DMA Stop */ +#define DMACKSUM 0xD8 /* DMA Start Checksum */ +#define DMACKSUMS 0xDA /* DMA Start Checksum with Seed */ +#define DMACOPY 0xDC /* DMA Start Copy */ +#define DMACOPYS 0xDE /* DMA Start Copy and Checksum with Seed */ +#define SETTXRTS 0xD4 /* Request Packet Transmission */ +#define ENABLERX 0xE8 /* Enable RX */ +#define DISABLERX 0xEA /* Disable RX */ +#define SETEIE 0xEC /* Enable Interrupts */ +#define CLREIE 0xEE /* Disable Interrupts */ + +/* Two byte instructions */ +#define RBSEL 0xC8 /* Read Bank Select */ + +/* Three byte instructions */ +#define WGPRDPT 0x60 /* Write EGPRDPT */ +#define RGPRDPT 0x62 /* Read EGPRDPT */ +#define WRXRDPT 0x64 /* Write ERXRDPT */ +#define RRXRDPT 0x66 /* Read ERXRDPT */ +#define WUDARDPT 0x68 /* Write EUDARDPT */ +#define RUDARDPT 0x6A /* Read EUDARDPT */ +#define WGPWRPT 0x6C /* Write EGPWRPT */ +#define RGPWRPT 0x6E /* Read EGPWRPT */ +#define WRXWRPT 0x70 /* Write ERXWRPT */ +#define RRXWRPT 0x72 /* Read ERXWRPT */ +#define WUDAWRPT 0x74 /* Write EUDAWRPT */ +#define RUDAWRPT 0x76 /* Read EUDAWRPT */ + +/* n byte instructions */ +#define RCRCODE 0x00 +#define WCRCODE 0x40 +#define BFSCODE 0x80 +#define BFCCODE 0xA0 +#define RCR(addr) (RCRCODE | (addr & ADDR_MASK)) /* Read Control Register */ +#define WCR(addr) (WCRCODE | (addr & ADDR_MASK)) /* Write Control Register */ +#define RCRU 0x20 /* Read Control Register Unbanked */ +#define WCRU 0x22 /* Write Control Register Unbanked */ +#define BFS(addr) (BFSCODE | (addr & ADDR_MASK)) /* Bit Field Set */ +#define BFC(addr) (BFCCODE | (addr & ADDR_MASK)) /* Bit Field Clear */ +#define BFSU 0x24 /* Bit Field Set Unbanked */ +#define BFCU 0x26 /* Bit Field Clear Unbanked */ +#define RGPDATA 0x28 /* Read EGPDATA */ +#define WGPDATA 0x2A /* Write EGPDATA */ +#define RRXDATA 0x2C /* Read ERXDATA */ +#define WRXDATA 0x2E /* Write ERXDATA */ +#define RUDADATA 0x30 /* Read EUDADATA */ +#define WUDADATA 0x32 /* Write EUDADATA */ + +#define SFR_REG_COUNT 0xA0 + +/* ENC424J600 Control Registers + * Control register definitions are a combination of address + * and bank number + * - Register address (bits 0-4) + * - Bank number (bits 5-6) + */ +#define ADDR_MASK 0x1F +#define BANK_MASK 0x60 +#define BANK_SHIFT 5 + +/* All-bank registers */ +#define EUDAST 0x16 +#define EUDAND 0x18 +#define ESTAT 0x1A +#define EIR 0x1C +#define ECON1 0x1E + +/* Bank 0 registers */ +#define ETXST (0x00 | 0x00) +#define ETXLEN (0x02 | 0x00) +#define ERXST (0x04 | 0x00) +#define ERXTAIL (0x06 | 0x00) +#define ERXHEAD (0x08 | 0x00) +#define EDMAST (0x0A | 0x00) +#define EDMALEN (0x0C | 0x00) +#define EDMADST (0x0E | 0x00) +#define EDMACS (0x10 | 0x00) +#define ETXSTAT (0x12 | 0x00) +#define ETXWIRE (0x14 | 0x00) + +/* Bank 1 registers */ +#define EHT1 (0x00 | 0x20) +#define EHT2 (0x02 | 0x20) +#define EHT3 (0x04 | 0x20) +#define EHT4 (0x06 | 0x20) +#define EPMM1 (0x08 | 0x20) +#define EPMM2 (0x0A | 0x20) +#define EPMM3 (0x0C | 0x20) +#define EPMM4 (0x0E | 0x20) +#define EPMCS (0x10 | 0x20) +#define EPMO (0x12 | 0x20) +#define ERXFCON (0x14 | 0x20) + +/* Bank 2 registers */ +#define MACON1 (0x00 | 0x40) +#define MACON2 (0x02 | 0x40) +#define MABBIPG (0x04 | 0x40) +#define MAIPG (0x06 | 0x40) +#define MACLCON (0x08 | 0x40) +#define MAMXFL (0x0A | 0x40) +#define MICMD (0x12 | 0x40) +#define MIREGADR (0x14 | 0x40) + +/* Bank 3 registers */ +#define MAADR3 (0x00 | 0x60) +#define MAADR2 (0x02 | 0x60) +#define MAADR1 (0x04 | 0x60) +#define MIWR (0x06 | 0x60) +#define MIRD (0x08 | 0x60) +#define MISTAT (0x0A | 0x60) +#define EPAUS (0x0C | 0x60) +#define ECON2 (0x0E | 0x60) +#define ERXWM (0x10 | 0x60) +#define EIE (0x12 | 0x60) +#define EIDLED (0x14 | 0x60) + +/* Unbanked registers */ +#define EGPDATA (0x00 | 0x80) +#define ERXDATA (0x02 | 0x80) +#define EUDADATA (0x04 | 0x80) +#define EGPRDPT (0x06 | 0x80) +#define EGPWRPT (0x08 | 0x80) +#define ERXRDPT (0x0A | 0x80) +#define ERXWRPT (0x0C | 0x80) +#define EUDARDPT (0x0E | 0x80) +#define EUDAWRPT (0x10 | 0x80) + + +/* Register bit definitions */ +/* ESTAT */ +#define INT (1 << 15) +#define FCIDLE (1 << 14) +#define RXBUSY (1 << 13) +#define CLKRDY (1 << 12) +#define PHYDPX (1 << 10) +#define PHYLNK (1 << 8) + +/* EIR */ +#define CRYPTEN (1 << 15) +#define MODEXIF (1 << 14) +#define HASHIF (1 << 13) +#define AESIF (1 << 12) +#define LINKIF (1 << 11) +#define PKTIF (1 << 6) +#define DMAIF (1 << 5) +#define TXIF (1 << 3) +#define TXABTIF (1 << 2) +#define RXABTIF (1 << 1) +#define PCFULIF (1 << 0) + +/* ECON1 */ +#define MODEXST (1 << 15) +#define HASHEN (1 << 14) +#define HASHOP (1 << 13) +#define HASHLST (1 << 12) +#define AESST (1 << 11) +#define AESOP1 (1 << 10) +#define AESOP0 (1 << 9) +#define PKTDEC (1 << 8) +#define FCOP1 (1 << 7) +#define FCOP0 (1 << 6) +#define DMAST (1 << 5) +#define DMACPY (1 << 4) +#define DMACSSD (1 << 3) +#define DMANOCS (1 << 2) +#define TXRTS (1 << 1) +#define RXEN (1 << 0) + +/* ETXSTAT */ +#define LATECOL (1 << 10) +#define MAXCOL (1 << 9) +#define EXDEFER (1 << 8) +#define ETXSTATL_DEFER (1 << 7) +#define CRCBAD (1 << 4) +#define COLCNT_MASK 0xF + +/* ERXFCON */ +#define HTEN (1 << 15) +#define MPEN (1 << 14) +#define NOTPM (1 << 12) +#define PMEN3 (1 << 11) +#define PMEN2 (1 << 10) +#define PMEN1 (1 << 9) +#define PMEN0 (1 << 8) +#define CRCEEN (1 << 7) +#define CRCEN (1 << 6) +#define RUNTEEN (1 << 5) +#define RUNTEN (1 << 4) +#define UCEN (1 << 3) +#define NOTMEEN (1 << 2) +#define MCEN (1 << 1) +#define BCEN (1 << 0) + +/* MACON1 */ +#define LOOPBK (1 << 4) +#define RXPAUS (1 << 2) +#define PASSALL (1 << 1) + +/* MACON2 */ +#define MACON2_DEFER (1 << 14) +#define BPEN (1 << 13) +#define NOBKOFF (1 << 12) +#define PADCFG2 (1 << 7) +#define PADCFG1 (1 << 6) +#define PADCFG0 (1 << 5) +#define TXCRCEN (1 << 4) +#define PHDREN (1 << 3) +#define HFRMEN (1 << 2) +#define MACON2_RSV1 (1 << 1) +#define FULDPX (1 << 0) + +/* MAIPG */ +/* value of the high byte is given by the reserved bits, + * value of the low byte is recomended setting of the + * IPG parameter. + */ +#define MAIPGH_VAL 0x0C +#define MAIPGL_VAL 0x12 + +/* MIREGADRH */ +#define MIREGADR_VAL (1 << 8) + +/* MIREGADRL */ +#define PHREG_MASK 0x1F + +/* MICMD */ +#define MIISCAN (1 << 1) +#define MIIRD (1 << 0) + +/* MISTAT */ +#define NVALID (1 << 2) +#define SCAN (1 << 1) +#define BUSY (1 << 0) + +/* ECON2 */ +#define ETHEN (1 << 15) +#define STRCH (1 << 14) +#define TXMAC (1 << 13) +#define SHA1MD5 (1 << 12) +#define COCON3 (1 << 11) +#define COCON2 (1 << 10) +#define COCON1 (1 << 9) +#define COCON0 (1 << 8) +#define AUTOFC (1 << 7) +#define TXRST (1 << 6) +#define RXRST (1 << 5) +#define ETHRST (1 << 4) +#define MODLEN1 (1 << 3) +#define MODLEN0 (1 << 2) +#define AESLEN1 (1 << 1) +#define AESLEN0 (1 << 0) + +/* EIE */ +#define INTIE (1 << 15) +#define MODEXIE (1 << 14) +#define HASHIE (1 << 13) +#define AESIE (1 << 12) +#define LINKIE (1 << 11) +#define PKTIE (1 << 6) +#define DMAIE (1 << 5) +#define TXIE (1 << 3) +#define TXABTIE (1 << 2) +#define RXABTIE (1 << 1) +#define PCFULIE (1 << 0) + +/* EIDLED */ +#define LACFG3 (1 << 15) +#define LACFG2 (1 << 14) +#define LACFG1 (1 << 13) +#define LACFG0 (1 << 12) +#define LBCFG3 (1 << 11) +#define LBCFG2 (1 << 10) +#define LBCFG1 (1 << 9) +#define LBCFG0 (1 << 8) +#define DEVID_SHIFT 5 +#define DEVID_MASK (0x7 << DEVID_SHIFT) +#define REVID_SHIFT 0 +#define REVID_MASK (0x1F << REVID_SHIFT) + +/* PHY registers */ +#define PHCON1 0x00 +#define PHSTAT1 0x01 +#define PHANA 0x04 +#define PHANLPA 0x05 +#define PHANE 0x06 +#define PHCON2 0x11 +#define PHSTAT2 0x1B +#define PHSTAT3 0x1F + +/* PHCON1 */ +#define PRST (1 << 15) +#define PLOOPBK (1 << 14) +#define SPD100 (1 << 13) +#define ANEN (1 << 12) +#define PSLEEP (1 << 11) +#define RENEG (1 << 9) +#define PFULDPX (1 << 8) + +/* PHSTAT1 */ +#define FULL100 (1 << 14) +#define HALF100 (1 << 13) +#define FULL10 (1 << 12) +#define HALF10 (1 << 11) +#define ANDONE (1 << 5) +#define LRFAULT (1 << 4) +#define ANABLE (1 << 3) +#define LLSTAT (1 << 2) +#define EXTREGS (1 << 0) + +/* PHSTAT2 */ +#define PLRITY (1 << 4) + +/* PHSTAT3 */ +#define PHY3SPD100 (1 << 3) +#define PHY3DPX (1 << 4) +#define SPDDPX_SHIFT 2 +#define SPDDPX_MASK (0x7 << SPDDPX_SHIFT) + +/* PHANA */ +/* Default value for PHY initialization*/ +#define PHANA_DEFAULT 0x05E1 + +/* PHANE */ +#define PDFLT (1 << 4) +#define LPARCD (1 << 1) +#define LPANABL (1 << 0) + +#define EUDAST_TEST_VAL 0x1234 + +#define TSV_SIZE 7 + +#define ENCX24J600_DEV_ID 0x1 + +/* Configuration */ + +/* Led is on when the link is present and driven low + * temporarily when packet is TX'd or RX'd + */ +#define LED_A_SETTINGS 0xC + +/* Led is on if the link is in 100 Mbps mode */ +#define LED_B_SETTINGS 0x8 + +/* maximum ethernet frame length + * Currently not used as a limit anywhere + * (we're using the "huge frame enable" feature of + * enc424j600). + */ +#define MAX_FRAMELEN 1518 + +/* Size in bytes of the receive buffer in enc424j600. + * Must be word aligned (even). + */ +#define RX_BUFFER_SIZE (15 * MAX_FRAMELEN) + +/* Start of the general purpose area in sram */ +#define SRAM_GP_START 0x0 + +/* SRAM size */ +#define SRAM_SIZE 0x6000 + +/* Start of the receive buffer */ +#define ERXST_VAL (SRAM_SIZE - RX_BUFFER_SIZE) + +#define RSV_RXLONGEVDROPEV 16 +#define RSV_CARRIEREV 18 +#define RSV_CRCERROR 20 +#define RSV_LENCHECKERR 21 +#define RSV_LENOUTOFRANGE 22 +#define RSV_RXOK 23 +#define RSV_RXMULTICAST 24 +#define RSV_RXBROADCAST 25 +#define RSV_DRIBBLENIBBLE 26 +#define RSV_RXCONTROLFRAME 27 +#define RSV_RXPAUSEFRAME 28 +#define RSV_RXUNKNOWNOPCODE 29 +#define RSV_RXTYPEVLAN 30 + +#define RSV_RUNTFILTERMATCH 31 +#define RSV_NOTMEFILTERMATCH 32 +#define RSV_HASHFILTERMATCH 33 +#define RSV_MAGICPKTFILTERMATCH 34 +#define RSV_PTRNMTCHFILTERMATCH 35 +#define RSV_UNICASTFILTERMATCH 36 + +#define RSV_SIZE 8 +#define RSV_BITMASK(x) (1 << ((x) - 16)) +#define RSV_GETBIT(x, y) (((x) & RSV_BITMASK(y)) ? 1 : 0) + +struct rsv { + u16 next_packet; + u16 len; + u32 rxstat; +}; + +/* Put RX buffer at 0 as suggested by the Errata datasheet */ + +#define RXSTART_INIT ERXST_VAL +#define RXEND_INIT 0x5FFF + +int regmap_encx24j600_spi_write(void *context, u8 reg, const u8 *data, + size_t count); +int regmap_encx24j600_spi_read(void *context, u8 reg, u8 *data, size_t count); + + +#endif -- cgit v1.2.3 From dfdd7230c5a2d9d675b4e7d6e111a8ead13cfb11 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 6 Oct 2015 23:53:57 +0200 Subject: net: hns: fix 32-bit build warning The recently added hns driver causes a build warning in ARM allmodconfig builds: drivers/net/ethernet/hisilicon/hns/hnae.c: In function 'handles_show': drivers/net/ethernet/hisilicon/hns/hnae.c:452:13: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] j, (u64)h->qs[i]->io_base); ^ This removes the pointless cast and prints the pointer address using the "%p" format string in all three locations. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hnae.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c index 0a0a9e80dcd7..f52e99acf463 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.c +++ b/drivers/net/ethernet/hisilicon/hns/hnae.c @@ -448,12 +448,12 @@ static ssize_t handles_show(struct device *dev, s += sprintf(buf + s, "handle %d (eport_id=%u from %s):\n", i++, h->eport_id, h->dev->name); for (j = 0; j < h->q_num; j++) { - s += sprintf(buf + s, "\tqueue[%d] on 0x%llx\n", - j, (u64)h->qs[i]->io_base); -#define HANDEL_TX_MSG "\t\ttx_ring on 0x%llx:%u,%u,%u,%u,%u,%llu,%llu\n" + s += sprintf(buf + s, "\tqueue[%d] on %p\n", + j, h->qs[i]->io_base); +#define HANDEL_TX_MSG "\t\ttx_ring on %p:%u,%u,%u,%u,%u,%llu,%llu\n" s += sprintf(buf + s, HANDEL_TX_MSG, - (u64)h->qs[i]->tx_ring.io_base, + h->qs[i]->tx_ring.io_base, h->qs[i]->tx_ring.buf_size, h->qs[i]->tx_ring.desc_num, h->qs[i]->tx_ring.max_desc_num_per_pkt, @@ -462,8 +462,8 @@ static ssize_t handles_show(struct device *dev, h->qs[i]->tx_ring.stats.sw_err_cnt, h->qs[i]->tx_ring.stats.io_err_cnt); s += sprintf(buf + s, - "\t\trx_ring on 0x%llx:%u,%u,%llu,%llu,%llu\n", - (u64)h->qs[i]->rx_ring.io_base, + "\t\trx_ring on %p:%u,%u,%llu,%llu,%llu\n", + h->qs[i]->rx_ring.io_base, h->qs[i]->rx_ring.buf_size, h->qs[i]->rx_ring.desc_num, h->qs[i]->rx_ring.stats.sw_err_cnt, -- cgit v1.2.3 From bcb9db49bb9da895ee809bfb2718d664dfb3ee2f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 7 Oct 2015 08:58:34 +0200 Subject: mlxsw: fix warnings for big-endian 32-bit dma_addr_t The recently added mlxsw driver produces warnings in ARM allmodconfig: drivers/net/ethernet/mellanox/mlxsw/pci.c: In function 'mlxsw_pci_cmd_exec': drivers/net/ethernet/mellanox/mlxsw/pci.c:1585:59: warning: right shift count >= width of type [-Wshift-count-overflow] linux/byteorder/big_endian.h:38:51: note: in definition of macro '__cpu_to_be32' drivers/net/ethernet/mellanox/mlxsw/pci.c:76:2: note: in expansion of macro 'iowrite32be' This uses upper_32_bits() to extract the bits while avoiding that warning. Signed-off-by: Arnd Bergmann Acked-by: Jiri Pirko Fixes: eda6500a987a "mlxsw: Add PCI bus implementation" Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/pci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 462cea31ecbb..cef866c37648 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1582,11 +1582,11 @@ static int mlxsw_pci_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod, if (in_mbox) memcpy(mlxsw_pci->cmd.in_mbox.buf, in_mbox, in_mbox_size); - mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_HI, in_mapaddr >> 32); - mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_LO, in_mapaddr); + mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_HI, upper_32_bits(in_mapaddr)); + mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_LO, lower_32_bits(in_mapaddr)); - mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_HI, out_mapaddr >> 32); - mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_LO, out_mapaddr); + mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_HI, upper_32_bits(out_mapaddr)); + mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_LO, lower_32_bits(out_mapaddr)); mlxsw_pci_write32(mlxsw_pci, CIR_IN_MODIFIER, in_mod); mlxsw_pci_write32(mlxsw_pci, CIR_TOKEN, 0); -- cgit v1.2.3 From 9d3a6386c8238bfacf57ee9dac68ec4b40b302fe Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 7 Oct 2015 10:26:38 +0200 Subject: net: mdio-octeon: Drop obsolete Kconfig advice "Y" was the right answer for MDIO_OCTEON when this option was only available on CAVIUM_OCTEON_SOC. But now that the option is visible on all (64-bit) systems, this piece of advice no longer makes sense. This helper module is selected automatically by drivers which need it anyway. Signed-off-by: Jean Delvare Fixes: a6d6786452 ("net: mdio-octeon: Modify driver to work on both ThunderX and Octeon") Cc: Florian Fainelli Cc: Sunil Goutham Cc: Radha Mohan Chintakuntla Cc: David Daney Cc: David S. Miller Acked-by: David Daney Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index c5ad98ace5d0..11e3975485c1 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -168,8 +168,6 @@ config MDIO_OCTEON busses. It is required by the Octeon and ThunderX ethernet device drivers. - If in doubt, say Y. - config MDIO_SUN4I tristate "Allwinner sun4i MDIO interface support" depends on ARCH_SUNXI -- cgit v1.2.3 From 85121d6ee6973f98789bf7343f7f636c01e2de19 Mon Sep 17 00:00:00 2001 From: Carol L Soto Date: Wed, 7 Oct 2015 12:31:46 -0400 Subject: net/mlx4: Remove shared_ports variable at mlx4_enable_msi_x If we get MAX_MSIX interrupts would like to have each receive ring with his own msix interrupt line. Do not need the shared_ports variable at mlx4_enable_msix Fixes: 9293267a3e2a ('net/mlx4_core: Capping number of requested MSIXs to MAX_MSIX') Signed-off-by: Carol L Soto Acked-by: Matan Barak Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/main.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 006757f80988..cc3a9897574c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -2669,14 +2669,11 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) if (msi_x) { int nreq = dev->caps.num_ports * num_online_cpus() + 1; - bool shared_ports = false; nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, nreq); - if (nreq > MAX_MSIX) { + if (nreq > MAX_MSIX) nreq = MAX_MSIX; - shared_ports = true; - } entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); if (!entries) @@ -2699,9 +2696,6 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) bitmap_zero(priv->eq_table.eq[MLX4_EQ_ASYNC].actv_ports.ports, dev->caps.num_ports); - if (MLX4_IS_LEGACY_EQ_MODE(dev->caps)) - shared_ports = true; - for (i = 0; i < dev->caps.num_comp_vectors + 1; i++) { if (i == MLX4_EQ_ASYNC) continue; @@ -2709,7 +2703,7 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) priv->eq_table.eq[i].irq = entries[i + 1 - !!(i > MLX4_EQ_ASYNC)].vector; - if (shared_ports) { + if (MLX4_IS_LEGACY_EQ_MODE(dev->caps)) { bitmap_fill(priv->eq_table.eq[i].actv_ports.ports, dev->caps.num_ports); /* We don't set affinity hint when there -- cgit v1.2.3 From 1e8efb42cf32982d68c1ceab3e3dc15a05157632 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 27 Aug 2015 11:42:33 -0400 Subject: i40e: fix erroneous WARN_ON The driver was issuing a WARN_ON during ring size changes because the code was cloning the rx_ring struct but not zeroing out the pointers before allocating new memory. Zero out the pointers in the cloned copy before allocating new memory for them. In this case the code was correctly avoiding memory leaks but still triggering the warning. Change-ID: I186dd493948e9b7254ab0593d4aad8b68808918d Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index ffa943164b42..ef471fc7ffcc 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1176,6 +1176,11 @@ static int i40e_set_ringparam(struct net_device *netdev, /* clone ring and setup updated count */ tx_rings[i] = *vsi->tx_rings[i]; tx_rings[i].count = new_tx_count; + /* the desc and bi pointers will be reallocated in the + * setup call + */ + tx_rings[i].desc = NULL; + tx_rings[i].rx_bi = NULL; err = i40e_setup_tx_descriptors(&tx_rings[i]); if (err) { while (i) { @@ -1206,6 +1211,11 @@ static int i40e_set_ringparam(struct net_device *netdev, /* clone ring and setup updated count */ rx_rings[i] = *vsi->rx_rings[i]; rx_rings[i].count = new_rx_count; + /* the desc and bi pointers will be reallocated in the + * setup call + */ + rx_rings[i].desc = NULL; + rx_rings[i].rx_bi = NULL; err = i40e_setup_rx_descriptors(&rx_rings[i]); if (err) { while (i) { -- cgit v1.2.3 From 02d109be3ddc9768c1c38709218648d0c48a4ea9 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 27 Aug 2015 11:42:34 -0400 Subject: i40e: inline interrupt enable The interrupt enable function can be inlined by moving it to the header file, which decreases the function call overhead for a frequently called function. Change-ID: I3214cc99593725768642680e7b8ce7e9bba7e44d Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 19 ++++++++++++++++++- drivers/net/ethernet/intel/i40e/i40e_main.c | 18 ------------------ 2 files changed, 18 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 681bd5d37960..7a3c93972356 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -702,7 +702,24 @@ static inline void i40e_dbg_pf_exit(struct i40e_pf *pf) {} static inline void i40e_dbg_init(void) {} static inline void i40e_dbg_exit(void) {} #endif /* CONFIG_DEBUG_FS*/ -void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector); +/** + * i40e_irq_dynamic_enable - Enable default interrupt generation settings + * @vsi: pointer to a vsi + * @vector: enable a particular Hw Interrupt vector, without base_vector + **/ +static inline void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector) +{ + struct i40e_pf *pf = vsi->back; + struct i40e_hw *hw = &pf->hw; + u32 val; + + val = I40E_PFINT_DYN_CTLN_INTENA_MASK | + I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | + (I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT); + wr32(hw, I40E_PFINT_DYN_CTLN(vector + vsi->base_vector - 1), val); + /* skip the flush */ +} + void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector); void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf); void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index fb4b34db1ff5..2c5921483dc8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3059,24 +3059,6 @@ void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf) i40e_flush(hw); } -/** - * i40e_irq_dynamic_enable - Enable default interrupt generation settings - * @vsi: pointer to a vsi - * @vector: enable a particular Hw Interrupt vector, without base_vector - **/ -void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector) -{ - struct i40e_pf *pf = vsi->back; - struct i40e_hw *hw = &pf->hw; - u32 val; - - val = I40E_PFINT_DYN_CTLN_INTENA_MASK | - I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | - (I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT); - wr32(hw, I40E_PFINT_DYN_CTLN(vector + vsi->base_vector - 1), val); - /* skip the flush */ -} - /** * i40e_irq_dynamic_disable - Disable default interrupt generation settings * @vsi: pointer to a vsi -- cgit v1.2.3 From 96c8d0738aff3ecf3e8b3253fb286685e35d93e6 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 27 Aug 2015 11:42:35 -0400 Subject: i40e: add more verbose error messages Under certain circumstances, the device may not have enough resources to enable all of the VFs that it advertises in config space. Although the number of supported VFs is reported upon driver init, it is not obvious when this is different from the number reported in config space. To eliminate this confusion, add an error message explaining the problem. Additionally, move the 'Allocating VFs' message down below the error checks so as to prevent further confusion. Change-ID: I45b7efca53a7aebf7777be33a8bc9d615ae48ea1 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 0545e3f80e7a..fac8a02ab74e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -998,17 +998,19 @@ static int i40e_pci_sriov_enable(struct pci_dev *pdev, int num_vfs) goto err_out; } - dev_info(&pdev->dev, "Allocating %d VFs.\n", num_vfs); if (pre_existing_vfs && pre_existing_vfs != num_vfs) i40e_free_vfs(pf); else if (pre_existing_vfs && pre_existing_vfs == num_vfs) goto out; if (num_vfs > pf->num_req_vfs) { + dev_warn(&pdev->dev, "Unable to enable %d VFs. Limited to %d VFs due to device resource constraints.\n", + num_vfs, pf->num_req_vfs); err = -EPERM; goto err_out; } + dev_info(&pdev->dev, "Allocating %d VFs.\n", num_vfs); err = i40e_alloc_vfs(pf, num_vfs); if (err) { dev_warn(&pdev->dev, "Failed to enable SR-IOV: %d\n", err); -- cgit v1.2.3 From 909b2d16c41f3a56ff67342073ae5f2569d58084 Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Thu, 27 Aug 2015 11:42:36 -0400 Subject: i40e: Add parsing for CEE DCBX TLVs This patch adds parsing for CEE DCBX TLVs from the LLDP MIB. While the driver gets the DCB CEE operational configuration from Firmware using the "Get CEE DCBX Oper Config" AQ command there is a need to get the CEE DesiredCfg Tx by firmware and DCB configuration Rx from peer; for debug and other application purposes. Change-ID: I9140edf1a25a2852c7eff805d81e5eff6266178d Signed-off-by: Neerav Parikh Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_dcb.c | 179 +++++++++++++++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_dcb.h | 39 +++++++ 2 files changed, 218 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c index 9aee35d284fa..89e60e3b74c6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c @@ -291,6 +291,182 @@ static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv, } } +/** + * i40e_parse_cee_pgcfg_tlv + * @tlv: CEE DCBX PG CFG TLV + * @dcbcfg: Local store to update ETS CFG data + * + * Parses CEE DCBX PG CFG TLV + **/ +static void i40e_parse_cee_pgcfg_tlv(struct i40e_cee_feat_tlv *tlv, + struct i40e_dcbx_config *dcbcfg) +{ + struct i40e_dcb_ets_config *etscfg; + u8 *buf = tlv->tlvinfo; + u16 offset = 0; + u8 priority; + int i; + + etscfg = &dcbcfg->etscfg; + + if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK) + etscfg->willing = 1; + + etscfg->cbs = 0; + /* Priority Group Table (4 octets) + * Octets:| 1 | 2 | 3 | 4 | + * ----------------------------------------- + * |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7| + * ----------------------------------------- + * Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0| + * ----------------------------------------- + */ + for (i = 0; i < 4; i++) { + priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_1_MASK) >> + I40E_CEE_PGID_PRIO_1_SHIFT); + etscfg->prioritytable[i * 2] = priority; + priority = (u8)((buf[offset] & I40E_CEE_PGID_PRIO_0_MASK) >> + I40E_CEE_PGID_PRIO_0_SHIFT); + etscfg->prioritytable[i * 2 + 1] = priority; + offset++; + } + + /* PG Percentage Table (8 octets) + * Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | + * --------------------------------- + * |pg0|pg1|pg2|pg3|pg4|pg5|pg6|pg7| + * --------------------------------- + */ + for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) + etscfg->tcbwtable[i] = buf[offset++]; + + /* Number of TCs supported (1 octet) */ + etscfg->maxtcs = buf[offset]; +} + +/** + * i40e_parse_cee_pfccfg_tlv + * @tlv: CEE DCBX PFC CFG TLV + * @dcbcfg: Local store to update PFC CFG data + * + * Parses CEE DCBX PFC CFG TLV + **/ +static void i40e_parse_cee_pfccfg_tlv(struct i40e_cee_feat_tlv *tlv, + struct i40e_dcbx_config *dcbcfg) +{ + u8 *buf = tlv->tlvinfo; + + if (tlv->en_will_err & I40E_CEE_FEAT_TLV_WILLING_MASK) + dcbcfg->pfc.willing = 1; + + /* ------------------------ + * | PFC Enable | PFC TCs | + * ------------------------ + * | 1 octet | 1 octet | + */ + dcbcfg->pfc.pfcenable = buf[0]; + dcbcfg->pfc.pfccap = buf[1]; +} + +/** + * i40e_parse_cee_app_tlv + * @tlv: CEE DCBX APP TLV + * @dcbcfg: Local store to update APP PRIO data + * + * Parses CEE DCBX APP PRIO TLV + **/ +static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv, + struct i40e_dcbx_config *dcbcfg) +{ + u16 length, typelength, offset = 0; + struct i40e_cee_app_prio *app; + u8 i, up; + + typelength = ntohs(tlv->hdr.typelen); + length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> + I40E_LLDP_TLV_LEN_SHIFT); + + dcbcfg->numapps = length / sizeof(*app); + if (!dcbcfg->numapps) + return; + + for (i = 0; i < dcbcfg->numapps; i++) { + app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset); + for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) { + if (app->prio_map & (1 << up)) + break; + } + dcbcfg->app[i].priority = up; + /* Get Selector from lower 2 bits */ + dcbcfg->app[i].selector = (app->upper_oui_sel & + I40E_CEE_APP_SELECTOR_MASK); + dcbcfg->app[i].protocolid = ntohs(app->protocol); + /* Move to next app */ + offset += sizeof(*app); + } +} + +/** + * i40e_parse_cee_tlv + * @tlv: CEE DCBX TLV + * @dcbcfg: Local store to update DCBX config data + * + * Get the TLV subtype and send it to parsing function + * based on the subtype value + **/ +static void i40e_parse_cee_tlv(struct i40e_lldp_org_tlv *tlv, + struct i40e_dcbx_config *dcbcfg) +{ + u16 len, tlvlen, sublen, typelength; + struct i40e_cee_feat_tlv *sub_tlv; + u8 subtype, feat_tlv_count = 0; + u32 ouisubtype; + + ouisubtype = ntohl(tlv->ouisubtype); + subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >> + I40E_LLDP_TLV_SUBTYPE_SHIFT); + /* Return if not CEE DCBX */ + if (subtype != I40E_CEE_DCBX_TYPE) + return; + + typelength = ntohs(tlv->typelength); + tlvlen = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> + I40E_LLDP_TLV_LEN_SHIFT); + len = sizeof(tlv->typelength) + sizeof(ouisubtype) + + sizeof(struct i40e_cee_ctrl_tlv); + /* Return if no CEE DCBX Feature TLVs */ + if (tlvlen <= len) + return; + + sub_tlv = (struct i40e_cee_feat_tlv *)((char *)tlv + len); + while (feat_tlv_count < I40E_CEE_MAX_FEAT_TYPE) { + typelength = ntohs(sub_tlv->hdr.typelen); + sublen = (u16)((typelength & + I40E_LLDP_TLV_LEN_MASK) >> + I40E_LLDP_TLV_LEN_SHIFT); + subtype = (u8)((typelength & I40E_LLDP_TLV_TYPE_MASK) >> + I40E_LLDP_TLV_TYPE_SHIFT); + switch (subtype) { + case I40E_CEE_SUBTYPE_PG_CFG: + i40e_parse_cee_pgcfg_tlv(sub_tlv, dcbcfg); + break; + case I40E_CEE_SUBTYPE_PFC_CFG: + i40e_parse_cee_pfccfg_tlv(sub_tlv, dcbcfg); + break; + case I40E_CEE_SUBTYPE_APP_PRI: + i40e_parse_cee_app_tlv(sub_tlv, dcbcfg); + break; + default: + return; /* Invalid Sub-type return */ + } + feat_tlv_count++; + /* Move to next sub TLV */ + sub_tlv = (struct i40e_cee_feat_tlv *)((char *)sub_tlv + + sizeof(sub_tlv->hdr.typelen) + + sublen); + } +} + /** * i40e_parse_org_tlv * @tlv: Organization specific TLV @@ -312,6 +488,9 @@ static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv, case I40E_IEEE_8021QAZ_OUI: i40e_parse_ieee_tlv(tlv, dcbcfg); break; + case I40E_CEE_DCBX_OUI: + i40e_parse_cee_tlv(tlv, dcbcfg); + break; default: break; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.h b/drivers/net/ethernet/intel/i40e/i40e_dcb.h index 50fc894a4cde..92d01042c1f6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.h +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.h @@ -44,6 +44,15 @@ #define I40E_IEEE_SUBTYPE_PFC_CFG 11 #define I40E_IEEE_SUBTYPE_APP_PRI 12 +#define I40E_CEE_DCBX_OUI 0x001b21 +#define I40E_CEE_DCBX_TYPE 2 + +#define I40E_CEE_SUBTYPE_CTRL 1 +#define I40E_CEE_SUBTYPE_PG_CFG 2 +#define I40E_CEE_SUBTYPE_PFC_CFG 3 +#define I40E_CEE_SUBTYPE_APP_PRI 4 + +#define I40E_CEE_MAX_FEAT_TYPE 3 /* Defines for LLDP TLV header */ #define I40E_LLDP_TLV_LEN_SHIFT 0 #define I40E_LLDP_TLV_LEN_MASK (0x01FF << I40E_LLDP_TLV_LEN_SHIFT) @@ -98,6 +107,36 @@ struct i40e_lldp_org_tlv { __be32 ouisubtype; u8 tlvinfo[1]; }; + +struct i40e_cee_tlv_hdr { + __be16 typelen; + u8 operver; + u8 maxver; +}; + +struct i40e_cee_ctrl_tlv { + struct i40e_cee_tlv_hdr hdr; + __be32 seqno; + __be32 ackno; +}; + +struct i40e_cee_feat_tlv { + struct i40e_cee_tlv_hdr hdr; + u8 en_will_err; /* Bits: |En|Will|Err|Reserved(5)| */ +#define I40E_CEE_FEAT_TLV_ENABLE_MASK 0x80 +#define I40E_CEE_FEAT_TLV_WILLING_MASK 0x40 +#define I40E_CEE_FEAT_TLV_ERR_MASK 0x20 + u8 subtype; + u8 tlvinfo[1]; +}; + +struct i40e_cee_app_prio { + __be16 protocol; + u8 upper_oui_sel; /* Bits: |Upper OUI(6)|Selector(2)| */ +#define I40E_CEE_APP_SELECTOR_MASK 0x03 + __be16 lower_oui; + u8 prio_map; +}; #pragma pack() i40e_status i40e_get_dcbx_status(struct i40e_hw *hw, -- cgit v1.2.3 From 1a9375eb7f987e9338c17504dd2b358b688b32d8 Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Thu, 27 Aug 2015 11:42:37 -0400 Subject: i40e/i40evf: Store CEE DCBX DesiredCfg and RemoteCfg This patch adds capability to query and store the CEE DCBX DesiredCfg and RemoteCfg data from the LLDP MIB. Added new member "desired_dcbx_config" in the i40e_hw data structure to hold CEE only DesiredCfg data. Change-ID: I19c550369594384eaff4cc63e690ca740231195d Signed-off-by: Neerav Parikh Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_dcb.c | 44 ++++++++++++++++++++++----- drivers/net/ethernet/intel/i40e/i40e_type.h | 5 +-- drivers/net/ethernet/intel/i40evf/i40e_type.h | 5 +-- 3 files changed, 42 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c index 89e60e3b74c6..fbec7d787f9d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c @@ -761,6 +761,36 @@ static void i40e_cee_to_dcb_config( dcbcfg->numapps = i; } +/** + * i40e_get_ieee_dcb_config + * @hw: pointer to the hw struct + * + * Get IEEE mode DCB configuration from the Firmware + **/ +static i40e_status i40e_get_ieee_dcb_config(struct i40e_hw *hw) +{ + i40e_status ret = 0; + + /* IEEE mode */ + hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE; + /* Get Local DCB Config */ + ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0, + &hw->local_dcbx_config); + if (ret) + goto out; + + /* Get Remote DCB Config */ + ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE, + I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE, + &hw->remote_dcbx_config); + /* Don't treat ENOENT as an error for Remote MIBs */ + if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) + ret = 0; + +out: + return ret; +} + /** * i40e_get_dcb_config * @hw: pointer to the hw struct @@ -776,7 +806,7 @@ i40e_status i40e_get_dcb_config(struct i40e_hw *hw) /* If Firmware version < v4.33 IEEE only */ if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || (hw->aq.fw_maj_ver < 4)) - goto ieee; + return i40e_get_ieee_dcb_config(hw); /* If Firmware version == v4.33 use old CEE struct */ if ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33)) { @@ -805,16 +835,14 @@ i40e_status i40e_get_dcb_config(struct i40e_hw *hw) /* CEE mode not enabled try querying IEEE data */ if (hw->aq.asq_last_status == I40E_AQ_RC_ENOENT) - goto ieee; - else + return i40e_get_ieee_dcb_config(hw); + + if (ret) goto out; -ieee: - /* IEEE mode */ - hw->local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE; - /* Get Local DCB Config */ + /* Get CEE DCB Desired Config */ ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0, - &hw->local_dcbx_config); + &hw->desired_dcbx_config); if (ret) goto out; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 34720e07f990..1c0bedbb4132 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -510,8 +510,9 @@ struct i40e_hw { u16 dcbx_status; /* DCBX info */ - struct i40e_dcbx_config local_dcbx_config; - struct i40e_dcbx_config remote_dcbx_config; + struct i40e_dcbx_config local_dcbx_config; /* Oper/Local Cfg */ + struct i40e_dcbx_config remote_dcbx_config; /* Peer Cfg */ + struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */ /* debug mask */ u32 debug_mask; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index bbb388660aa7..4b5528d4ae3d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -504,8 +504,9 @@ struct i40e_hw { u16 dcbx_status; /* DCBX info */ - struct i40e_dcbx_config local_dcbx_config; - struct i40e_dcbx_config remote_dcbx_config; + struct i40e_dcbx_config local_dcbx_config; /* Oper/Local Cfg */ + struct i40e_dcbx_config remote_dcbx_config; /* Peer Cfg */ + struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */ /* debug mask */ u32 debug_mask; -- cgit v1.2.3 From 3487b6c30c0dd2204dc31e14330097dff02d9a58 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Thu, 27 Aug 2015 11:42:38 -0400 Subject: i40e: Fix for extra Flow Director filter in table after error This patch fixes a problem where the PF's fdir filter table would have an entry that the hw was unable to add. This notification happens in the hot path, so instead of trying to fix it then, we note the location in the failure case and delete it during regular fdir subtask callback. Without this patch, a case can occur where an invalid entry gets replayed and a valid one is not. Change-ID: I67831c183b5d0309876de807cc434809b74c9cb7 Signed-off-by: Carolyn Wyborny Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 14 ++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 7a3c93972356..a662e3961951 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -410,6 +410,7 @@ struct i40e_pf { u32 npar_min_bw; u32 ioremap_len; + u32 fd_inv; }; struct i40e_mac_filter { diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 2c5921483dc8..949535684fa9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5614,7 +5614,9 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf) **/ void i40e_fdir_check_and_reenable(struct i40e_pf *pf) { + struct i40e_fdir_filter *filter; u32 fcnt_prog, fcnt_avail; + struct hlist_node *node; if (test_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state)) return; @@ -5643,6 +5645,18 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf) dev_info(&pf->pdev->dev, "ATR is being enabled since we have space in the table now\n"); } } + + /* if hw had a problem adding a filter, delete it */ + if (pf->fd_inv > 0) { + hlist_for_each_entry_safe(filter, node, + &pf->fdir_filter_list, fdir_node) { + if (filter->fd_id == pf->fd_inv) { + hlist_del(&filter->fdir_node); + kfree(filter); + pf->fdir_pf_active_filters--; + } + } + } } #define I40E_MIN_FD_FLUSH_INTERVAL 10 diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 889ed10f588b..8ab7ab1623f2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -465,10 +465,11 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring, I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT; if (error == BIT(I40E_RX_PROG_STATUS_DESC_FD_TBL_FULL_SHIFT)) { + pf->fd_inv = le32_to_cpu(rx_desc->wb.qword0.hi_dword.fd_id); if ((rx_desc->wb.qword0.hi_dword.fd_id != 0) || (I40E_DEBUG_FD & pf->hw.debug_mask)) dev_warn(&pdev->dev, "ntuple filter loc = %d, could not be added\n", - rx_desc->wb.qword0.hi_dword.fd_id); + pf->fd_inv); /* Check if the programming error is for ATR. * If so, auto disable ATR and set a state for -- cgit v1.2.3 From c156f856ad8ba4f71bcdb2c92ba1a9effaa29ac1 Mon Sep 17 00:00:00 2001 From: Matt Jared Date: Thu, 27 Aug 2015 11:42:39 -0400 Subject: i40e: Fix multiple link up messages This patch addresses an issue where multiple link up messages can be logged resulting from aq link status timing when link properties are changed (fc, speed, etc.); solved by using a single function to handle status printing and adding a mechanism to track whether link state (up or down) has actually changed. Change-ID: Ied6ed6e49dc397c77d992adc0bc9ed3767152b9d Signed-off-by: Matt Jared Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 ++ drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_main.c | 5 ++++- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index a662e3961951..0c73404fdca6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -537,6 +537,7 @@ struct i40e_vsi { u16 idx; /* index in pf->vsi[] */ u16 veb_idx; /* index of VEB parent */ struct kobject *kobj; /* sysfs object */ + bool current_isup; /* Sync 'link up' logging */ /* VSI specific handlers */ irqreturn_t (*irq_handler)(int irq, void *data); @@ -791,4 +792,5 @@ int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi); i40e_status i40e_get_npar_bw_setting(struct i40e_pf *pf); i40e_status i40e_set_npar_bw_setting(struct i40e_pf *pf); i40e_status i40e_commit_npar_bw_setting(struct i40e_pf *pf); +void i40e_print_link_message(struct i40e_vsi *vsi, bool isup); #endif /* _I40E_H_ */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index ef471fc7ffcc..f2b4f8b8d754 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -690,7 +690,7 @@ static int i40e_set_settings(struct net_device *netdev, /* Tell the OS link is going down, the link will go * back up when fw says it is ready asynchronously */ - netdev_info(netdev, "PHY settings change requested, NIC Link is going down.\n"); + i40e_print_link_message(vsi, false); netif_carrier_off(netdev); netif_tx_stop_all_queues(netdev); } @@ -834,7 +834,7 @@ static int i40e_set_pauseparam(struct net_device *netdev, /* Tell the OS link is going down, the link will go back up when fw * says it is ready asynchronously */ - netdev_info(netdev, "Flow control settings change requested, NIC Link is going down.\n"); + i40e_print_link_message(vsi, false); netif_carrier_off(netdev); netif_tx_stop_all_queues(netdev); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 949535684fa9..e05e6aaa4cc1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -4837,11 +4837,14 @@ out: * i40e_print_link_message - print link up or down * @vsi: the VSI for which link needs a message */ -static void i40e_print_link_message(struct i40e_vsi *vsi, bool isup) +void i40e_print_link_message(struct i40e_vsi *vsi, bool isup) { char speed[SPEED_SIZE] = "Unknown"; char fc[FC_SIZE] = "RX/TX"; + if (vsi->current_isup == isup) + return; + vsi->current_isup = isup; if (!isup) { netdev_info(vsi->netdev, "NIC Link is Down\n"); return; -- cgit v1.2.3 From 9ac77266379d070c6d140ad44f86a99936497eeb Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 27 Aug 2015 11:42:40 -0400 Subject: i40e: add switch for link polling There's been some need for controlling the periodic link polling for debugging link issues. This patch enables switching it off and on through an ethtool private flag. The link poll remains on by default, but can be turned off with ethtool --set-priv-flags p261p1 LinkPolling off and later turned back on with ethtool --set-priv-flags p261p1 LinkPolling on To check the current status, use ethtool --show-priv-flags p261p1 Change-ID: I32e4ab654ff3eec90a06cf144899971b82d71c40 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 ++ drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 26 ++++++++++++++++++++++++-- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 +++- 3 files changed, 29 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 0c73404fdca6..f26dcb23ebf9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -101,6 +101,7 @@ /* Ethtool Private Flags */ #define I40E_PRIV_FLAGS_NPAR_FLAG BIT(0) +#define I40E_PRIV_FLAGS_LINKPOLL_FLAG BIT(1) #define I40E_NVM_VERSION_LO_SHIFT 0 #define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT) @@ -327,6 +328,7 @@ struct i40e_pf { #define I40E_FLAG_WB_ON_ITR_CAPABLE BIT_ULL(35) #define I40E_FLAG_VEB_STATS_ENABLED BIT_ULL(37) #define I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE BIT_ULL(38) +#define I40E_FLAG_LINK_POLLING_ENABLED BIT_ULL(39) #define I40E_FLAG_VEB_MODE_ENABLED BIT_ULL(40) /* tracks features that get auto disabled by errors */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index f2b4f8b8d754..5a726f2624e0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -230,10 +230,10 @@ static const char i40e_gstrings_test[][ETH_GSTRING_LEN] = { static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = { "NPAR", + "LinkPolling", }; -#define I40E_PRIV_FLAGS_STR_LEN \ - (sizeof(i40e_priv_flags_strings) / ETH_GSTRING_LEN) +#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings) /** * i40e_partition_setting_complaint - generic complaint for MFP restriction @@ -2636,10 +2636,31 @@ static u32 i40e_get_priv_flags(struct net_device *dev) ret_flags |= pf->hw.func_caps.npar_enable ? I40E_PRIV_FLAGS_NPAR_FLAG : 0; + ret_flags |= pf->flags & I40E_FLAG_LINK_POLLING_ENABLED ? + I40E_PRIV_FLAGS_LINKPOLL_FLAG : 0; return ret_flags; } +/** + * i40e_set_priv_flags - set private flags + * @dev: network interface device structure + * @flags: bit flags to be set + **/ +static int i40e_set_priv_flags(struct net_device *dev, u32 flags) +{ + struct i40e_netdev_priv *np = netdev_priv(dev); + struct i40e_vsi *vsi = np->vsi; + struct i40e_pf *pf = vsi->back; + + if (flags & I40E_PRIV_FLAGS_LINKPOLL_FLAG) + pf->flags |= I40E_FLAG_LINK_POLLING_ENABLED; + else + pf->flags &= ~I40E_FLAG_LINK_POLLING_ENABLED; + + return 0; +} + static const struct ethtool_ops i40e_ethtool_ops = { .get_settings = i40e_get_settings, .set_settings = i40e_set_settings, @@ -2676,6 +2697,7 @@ static const struct ethtool_ops i40e_ethtool_ops = { .set_channels = i40e_set_channels, .get_ts_info = i40e_get_ts_info, .get_priv_flags = i40e_get_priv_flags, + .set_priv_flags = i40e_set_priv_flags, }; void i40e_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index e05e6aaa4cc1..23a7b40c764c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5892,7 +5892,8 @@ static void i40e_watchdog_subtask(struct i40e_pf *pf) return; pf->service_timer_previous = jiffies; - i40e_link_event(pf); + if (pf->flags & I40E_FLAG_LINK_POLLING_ENABLED) + i40e_link_event(pf); /* Update the stats for active netdevs so the network stack * can look at updated numbers whenever it cares to @@ -7908,6 +7909,7 @@ static int i40e_sw_init(struct i40e_pf *pf) /* Set default capability flags */ pf->flags = I40E_FLAG_RX_CSUM_ENABLED | I40E_FLAG_MSI_ENABLED | + I40E_FLAG_LINK_POLLING_ENABLED | I40E_FLAG_MSIX_ENABLED; if (iommu_present(&pci_bus_type)) -- cgit v1.2.3 From 66486cd71723b2b41b36759159b551230ab8763d Mon Sep 17 00:00:00 2001 From: Serey Kong Date: Thu, 27 Aug 2015 11:42:41 -0400 Subject: i40e/i40evf: Explicitly assign enum index for VSI type Ran into an issue where PF's VSI type list was different from VF's, which was resulted in different enum index. The VSI type list can be different depending on what build flag is used for PF and VF. The change is to explicitly assign enum index for each VSI type so that PF and VF always reference to the same VSI type event if the enum lists are different. Change-ID: I8c0e5fdb515f324f7964df863a458073cf467e57 Signed-off-by: Serey Kong Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_type.h | 16 ++++++++-------- drivers/net/ethernet/intel/i40evf/i40e_type.h | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 1c0bedbb4132..d1ec5a4326cf 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -160,14 +160,14 @@ enum i40e_set_fc_aq_failures { }; enum i40e_vsi_type { - I40E_VSI_MAIN = 0, - I40E_VSI_VMDQ1, - I40E_VSI_VMDQ2, - I40E_VSI_CTRL, - I40E_VSI_FCOE, - I40E_VSI_MIRROR, - I40E_VSI_SRIOV, - I40E_VSI_FDIR, + I40E_VSI_MAIN = 0, + I40E_VSI_VMDQ1 = 1, + I40E_VSI_VMDQ2 = 2, + I40E_VSI_CTRL = 3, + I40E_VSI_FCOE = 4, + I40E_VSI_MIRROR = 5, + I40E_VSI_SRIOV = 6, + I40E_VSI_FDIR = 7, I40E_VSI_TYPE_UNKNOWN }; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 4b5528d4ae3d..a59b60ffd0ce 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -160,14 +160,14 @@ enum i40e_set_fc_aq_failures { }; enum i40e_vsi_type { - I40E_VSI_MAIN = 0, - I40E_VSI_VMDQ1, - I40E_VSI_VMDQ2, - I40E_VSI_CTRL, - I40E_VSI_FCOE, - I40E_VSI_MIRROR, - I40E_VSI_SRIOV, - I40E_VSI_FDIR, + I40E_VSI_MAIN = 0, + I40E_VSI_VMDQ1 = 1, + I40E_VSI_VMDQ2 = 2, + I40E_VSI_CTRL = 3, + I40E_VSI_FCOE = 4, + I40E_VSI_MIRROR = 5, + I40E_VSI_SRIOV = 6, + I40E_VSI_FDIR = 7, I40E_VSI_TYPE_UNKNOWN }; -- cgit v1.2.3 From 95e5613f75ac93d0547b7d2077030a5fe11af21e Mon Sep 17 00:00:00 2001 From: Greg Bowers Date: Fri, 28 Aug 2015 17:55:52 -0400 Subject: i40e: Support FW CEE DCB UP to TC map nibble swap Changes parsing of AQ command Get CEE DCBX OPER CFG (0x0A07). Change is required because FW creates the oper_prio_tc nibbles reversed from those in the CEE Priority Group sub-TLV. Change-ID: I7d9d8641bb430d30e286fc3fac909866ef8a0de8 Signed-off-by: Greg Bowers Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_dcb.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c index fbec7d787f9d..6fa07ef1651d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c @@ -681,15 +681,18 @@ static void i40e_cee_to_dcb_config( /* CEE PG data to ETS config */ dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; + /* Note that the FW creates the oper_prio_tc nibbles reversed + * from those in the CEE Priority Group sub-TLV. + */ for (i = 0; i < 4; i++) { - tc = (u8)((cee_cfg->oper_prio_tc[i] & - I40E_CEE_PGID_PRIO_1_MASK) >> - I40E_CEE_PGID_PRIO_1_SHIFT); - dcbcfg->etscfg.prioritytable[i*2] = tc; tc = (u8)((cee_cfg->oper_prio_tc[i] & I40E_CEE_PGID_PRIO_0_MASK) >> I40E_CEE_PGID_PRIO_0_SHIFT); - dcbcfg->etscfg.prioritytable[i*2 + 1] = tc; + dcbcfg->etscfg.prioritytable[i * 2] = tc; + tc = (u8)((cee_cfg->oper_prio_tc[i] & + I40E_CEE_PGID_PRIO_1_MASK) >> + I40E_CEE_PGID_PRIO_1_SHIFT); + dcbcfg->etscfg.prioritytable[i * 2 + 1] = tc; } for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) -- cgit v1.2.3 From ee5c1e92dd01d372b8e054b5a7e1cc19a1d32815 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 28 Aug 2015 17:55:53 -0400 Subject: i40evf: detect reset more reliably Using VFGEN_RSTAT to detect a VF reset is an endeavor that is fraught with peril. It's entirely too easy to miss a reset because none of the bits are sticky. By the time the VF driver reads the register, the reset may have been processed and cleaned up by the PF driver, leaving the register in the same state that it was before the reset. Instead, detect a reset with the VF_ARQLEN register. When the VF is reset, the enable bit in this register is cleared, and it stays cleared until the VF driver processes the reset and re-enables the admin queue. Because we now deal with multiple registers in the reset and watchdog tasks, rename the rstat_val variable to reg_val. Change-ID: Id1df17045c0992e607da0162d31807f7fc20d199 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 36 +++++++++++-------------- 1 file changed, 16 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 0d18446cc5ad..664fde68b537 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1419,16 +1419,16 @@ static void i40evf_watchdog_task(struct work_struct *work) struct i40evf_adapter, watchdog_task); struct i40e_hw *hw = &adapter->hw; - uint32_t rstat_val; + u32 reg_val; if (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section)) goto restart_watchdog; if (adapter->flags & I40EVF_FLAG_PF_COMMS_FAILED) { - rstat_val = rd32(hw, I40E_VFGEN_RSTAT) & - I40E_VFGEN_RSTAT_VFR_STATE_MASK; - if ((rstat_val == I40E_VFR_VFACTIVE) || - (rstat_val == I40E_VFR_COMPLETED)) { + reg_val = rd32(hw, I40E_VFGEN_RSTAT) & + I40E_VFGEN_RSTAT_VFR_STATE_MASK; + if ((reg_val == I40E_VFR_VFACTIVE) || + (reg_val == I40E_VFR_COMPLETED)) { /* A chance for redemption! */ dev_err(&adapter->pdev->dev, "Hardware came out of reset. Attempting reinit.\n"); adapter->state = __I40EVF_STARTUP; @@ -1453,11 +1453,8 @@ static void i40evf_watchdog_task(struct work_struct *work) goto watchdog_done; /* check for reset */ - rstat_val = rd32(hw, I40E_VFGEN_RSTAT) & - I40E_VFGEN_RSTAT_VFR_STATE_MASK; - if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING) && - (rstat_val != I40E_VFR_VFACTIVE) && - (rstat_val != I40E_VFR_COMPLETED)) { + reg_val = rd32(hw, I40E_VF_ARQLEN1) & I40E_VF_ARQLEN1_ARQENABLE_MASK; + if (!(adapter->flags & I40EVF_FLAG_RESET_PENDING) && !reg_val) { adapter->state = __I40EVF_RESETTING; adapter->flags |= I40EVF_FLAG_RESET_PENDING; dev_err(&adapter->pdev->dev, "Hardware reset detected\n"); @@ -1572,7 +1569,7 @@ static void i40evf_reset_task(struct work_struct *work) struct net_device *netdev = adapter->netdev; struct i40e_hw *hw = &adapter->hw; struct i40evf_mac_filter *f; - uint32_t rstat_val; + u32 reg_val; int i = 0, err; while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, @@ -1593,12 +1590,11 @@ static void i40evf_reset_task(struct work_struct *work) /* poll until we see the reset actually happen */ for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) { - rstat_val = rd32(hw, I40E_VFGEN_RSTAT) & - I40E_VFGEN_RSTAT_VFR_STATE_MASK; - if ((rstat_val != I40E_VFR_VFACTIVE) && - (rstat_val != I40E_VFR_COMPLETED)) + reg_val = rd32(hw, I40E_VF_ARQLEN1) & + I40E_VF_ARQLEN1_ARQENABLE_MASK; + if (!reg_val) break; - usleep_range(500, 1000); + usleep_range(5000, 10000); } if (i == I40EVF_RESET_WAIT_COUNT) { dev_info(&adapter->pdev->dev, "Never saw reset\n"); @@ -1607,9 +1603,9 @@ static void i40evf_reset_task(struct work_struct *work) /* wait until the reset is complete and the PF is responding to us */ for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) { - rstat_val = rd32(hw, I40E_VFGEN_RSTAT) & - I40E_VFGEN_RSTAT_VFR_STATE_MASK; - if (rstat_val == I40E_VFR_VFACTIVE) + reg_val = rd32(hw, I40E_VFGEN_RSTAT) & + I40E_VFGEN_RSTAT_VFR_STATE_MASK; + if (reg_val == I40E_VFR_VFACTIVE) break; msleep(I40EVF_RESET_WAIT_MS); } @@ -1621,7 +1617,7 @@ static void i40evf_reset_task(struct work_struct *work) /* reset never finished */ dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n", - rstat_val); + reg_val); adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED; if (netif_running(adapter->netdev)) { -- cgit v1.2.3 From 6995b36c0fc3dd97c1d641f9630d19db2cadf44f Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 28 Aug 2015 17:55:54 -0400 Subject: i40e/i40evf: clean up some code Add missings spaces after declarations, remove another __func__ use, remove uncessary braces, remove unneeded breaks, and useless returns, and generally fix up some code. Change-ID: Ie715d6b64976c50e1c21531685fe0a2bd38c4244 Signed-off-by: Jesse Brandeburg Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 3 +- drivers/net/ethernet/intel/i40e/i40e_common.c | 9 +- drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c | 1 + drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 124 ++++++++++++--------- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 3 +- drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 1 - drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c | 3 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 38 ++++--- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 3 +- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 6 +- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 + drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 13 ++- drivers/net/ethernet/intel/i40evf/i40e_adminq.c | 3 +- drivers/net/ethernet/intel/i40evf/i40e_common.c | 8 +- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 6 +- drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 1 + drivers/net/ethernet/intel/i40evf/i40evf.h | 4 - 17 files changed, 124 insertions(+), 103 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index 287cb8def7cd..fa2e916b23da 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -683,8 +683,7 @@ static u16 i40e_clean_asq(struct i40e_hw *hw) details = I40E_ADMINQ_DETAILS(*asq, ntc); while (rd32(hw, hw->aq.asq.head) != ntc) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, - "%s: ntc %d head %d.\n", __func__, ntc, - rd32(hw, hw->aq.asq.head)); + "ntc %d head %d.\n", ntc, rd32(hw, hw->aq.asq.head)); if (details->callback) { I40E_ADMINQ_CALLBACK cb_func = diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 2839ea53234d..2d012d9c22ad 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1035,7 +1035,7 @@ i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr) status = i40e_aq_mac_address_read(hw, &flags, &addrs, NULL); if (flags & I40E_AQC_LAN_ADDR_VALID) - memcpy(mac_addr, &addrs.pf_lan_mac, sizeof(addrs.pf_lan_mac)); + ether_addr_copy(mac_addr, addrs.pf_lan_mac); return status; } @@ -1058,7 +1058,7 @@ i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr) return status; if (flags & I40E_AQC_PORT_ADDR_VALID) - memcpy(mac_addr, &addrs.port_mac, sizeof(addrs.port_mac)); + ether_addr_copy(mac_addr, addrs.port_mac); else status = I40E_ERR_INVALID_MAC_ADDR; @@ -1116,7 +1116,7 @@ i40e_status i40e_get_san_mac_addr(struct i40e_hw *hw, u8 *mac_addr) return status; if (flags & I40E_AQC_SAN_ADDR_VALID) - memcpy(mac_addr, &addrs.pf_san_mac, sizeof(addrs.pf_san_mac)); + ether_addr_copy(mac_addr, addrs.pf_san_mac); else status = I40E_ERR_INVALID_MAC_ADDR; @@ -2363,6 +2363,7 @@ i40e_status i40e_aq_get_veb_parameters(struct i40e_hw *hw, *vebs_free = le16_to_cpu(cmd_resp->vebs_free); if (floating) { u16 flags = le16_to_cpu(cmd_resp->veb_flags); + if (flags & I40E_AQC_ADD_VEB_FLOATING) *floating = true; else @@ -3777,7 +3778,7 @@ i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw, } if (mac_addr) - memcpy(cmd->mac, mac_addr, ETH_ALEN); + ether_addr_copy(cmd->mac, mac_addr); cmd->etype = cpu_to_le16(ethtype); cmd->flags = cpu_to_le16(flags); diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c index dbadad74e1c0..7c42d1340de6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c @@ -236,6 +236,7 @@ static void i40e_dcbnl_del_app(struct i40e_pf *pf, struct i40e_dcb_app_priority_table *app) { int v, err; + for (v = 0; v < pf->num_alloc_vsi; v++) { if (pf->vsi[v] && pf->vsi[v]->netdev) { err = i40e_dcbnl_vsi_del_app(pf->vsi[v], app); diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index 9f9d8422096a..c1dd2483e262 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -404,82 +404,82 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) nstat = i40e_get_vsi_stats_struct(vsi); dev_info(&pf->pdev->dev, " net_stats: rx_packets = %lu, rx_bytes = %lu, rx_errors = %lu, rx_dropped = %lu\n", - (long unsigned int)nstat->rx_packets, - (long unsigned int)nstat->rx_bytes, - (long unsigned int)nstat->rx_errors, - (long unsigned int)nstat->rx_dropped); + (unsigned long int)nstat->rx_packets, + (unsigned long int)nstat->rx_bytes, + (unsigned long int)nstat->rx_errors, + (unsigned long int)nstat->rx_dropped); dev_info(&pf->pdev->dev, " net_stats: tx_packets = %lu, tx_bytes = %lu, tx_errors = %lu, tx_dropped = %lu\n", - (long unsigned int)nstat->tx_packets, - (long unsigned int)nstat->tx_bytes, - (long unsigned int)nstat->tx_errors, - (long unsigned int)nstat->tx_dropped); + (unsigned long int)nstat->tx_packets, + (unsigned long int)nstat->tx_bytes, + (unsigned long int)nstat->tx_errors, + (unsigned long int)nstat->tx_dropped); dev_info(&pf->pdev->dev, " net_stats: multicast = %lu, collisions = %lu\n", - (long unsigned int)nstat->multicast, - (long unsigned int)nstat->collisions); + (unsigned long int)nstat->multicast, + (unsigned long int)nstat->collisions); dev_info(&pf->pdev->dev, " net_stats: rx_length_errors = %lu, rx_over_errors = %lu, rx_crc_errors = %lu\n", - (long unsigned int)nstat->rx_length_errors, - (long unsigned int)nstat->rx_over_errors, - (long unsigned int)nstat->rx_crc_errors); + (unsigned long int)nstat->rx_length_errors, + (unsigned long int)nstat->rx_over_errors, + (unsigned long int)nstat->rx_crc_errors); dev_info(&pf->pdev->dev, " net_stats: rx_frame_errors = %lu, rx_fifo_errors = %lu, rx_missed_errors = %lu\n", - (long unsigned int)nstat->rx_frame_errors, - (long unsigned int)nstat->rx_fifo_errors, - (long unsigned int)nstat->rx_missed_errors); + (unsigned long int)nstat->rx_frame_errors, + (unsigned long int)nstat->rx_fifo_errors, + (unsigned long int)nstat->rx_missed_errors); dev_info(&pf->pdev->dev, " net_stats: tx_aborted_errors = %lu, tx_carrier_errors = %lu, tx_fifo_errors = %lu\n", - (long unsigned int)nstat->tx_aborted_errors, - (long unsigned int)nstat->tx_carrier_errors, - (long unsigned int)nstat->tx_fifo_errors); + (unsigned long int)nstat->tx_aborted_errors, + (unsigned long int)nstat->tx_carrier_errors, + (unsigned long int)nstat->tx_fifo_errors); dev_info(&pf->pdev->dev, " net_stats: tx_heartbeat_errors = %lu, tx_window_errors = %lu\n", - (long unsigned int)nstat->tx_heartbeat_errors, - (long unsigned int)nstat->tx_window_errors); + (unsigned long int)nstat->tx_heartbeat_errors, + (unsigned long int)nstat->tx_window_errors); dev_info(&pf->pdev->dev, " net_stats: rx_compressed = %lu, tx_compressed = %lu\n", - (long unsigned int)nstat->rx_compressed, - (long unsigned int)nstat->tx_compressed); + (unsigned long int)nstat->rx_compressed, + (unsigned long int)nstat->tx_compressed); dev_info(&pf->pdev->dev, " net_stats_offsets: rx_packets = %lu, rx_bytes = %lu, rx_errors = %lu, rx_dropped = %lu\n", - (long unsigned int)vsi->net_stats_offsets.rx_packets, - (long unsigned int)vsi->net_stats_offsets.rx_bytes, - (long unsigned int)vsi->net_stats_offsets.rx_errors, - (long unsigned int)vsi->net_stats_offsets.rx_dropped); + (unsigned long int)vsi->net_stats_offsets.rx_packets, + (unsigned long int)vsi->net_stats_offsets.rx_bytes, + (unsigned long int)vsi->net_stats_offsets.rx_errors, + (unsigned long int)vsi->net_stats_offsets.rx_dropped); dev_info(&pf->pdev->dev, " net_stats_offsets: tx_packets = %lu, tx_bytes = %lu, tx_errors = %lu, tx_dropped = %lu\n", - (long unsigned int)vsi->net_stats_offsets.tx_packets, - (long unsigned int)vsi->net_stats_offsets.tx_bytes, - (long unsigned int)vsi->net_stats_offsets.tx_errors, - (long unsigned int)vsi->net_stats_offsets.tx_dropped); + (unsigned long int)vsi->net_stats_offsets.tx_packets, + (unsigned long int)vsi->net_stats_offsets.tx_bytes, + (unsigned long int)vsi->net_stats_offsets.tx_errors, + (unsigned long int)vsi->net_stats_offsets.tx_dropped); dev_info(&pf->pdev->dev, " net_stats_offsets: multicast = %lu, collisions = %lu\n", - (long unsigned int)vsi->net_stats_offsets.multicast, - (long unsigned int)vsi->net_stats_offsets.collisions); + (unsigned long int)vsi->net_stats_offsets.multicast, + (unsigned long int)vsi->net_stats_offsets.collisions); dev_info(&pf->pdev->dev, " net_stats_offsets: rx_length_errors = %lu, rx_over_errors = %lu, rx_crc_errors = %lu\n", - (long unsigned int)vsi->net_stats_offsets.rx_length_errors, - (long unsigned int)vsi->net_stats_offsets.rx_over_errors, - (long unsigned int)vsi->net_stats_offsets.rx_crc_errors); + (unsigned long int)vsi->net_stats_offsets.rx_length_errors, + (unsigned long int)vsi->net_stats_offsets.rx_over_errors, + (unsigned long int)vsi->net_stats_offsets.rx_crc_errors); dev_info(&pf->pdev->dev, " net_stats_offsets: rx_frame_errors = %lu, rx_fifo_errors = %lu, rx_missed_errors = %lu\n", - (long unsigned int)vsi->net_stats_offsets.rx_frame_errors, - (long unsigned int)vsi->net_stats_offsets.rx_fifo_errors, - (long unsigned int)vsi->net_stats_offsets.rx_missed_errors); + (unsigned long int)vsi->net_stats_offsets.rx_frame_errors, + (unsigned long int)vsi->net_stats_offsets.rx_fifo_errors, + (unsigned long int)vsi->net_stats_offsets.rx_missed_errors); dev_info(&pf->pdev->dev, " net_stats_offsets: tx_aborted_errors = %lu, tx_carrier_errors = %lu, tx_fifo_errors = %lu\n", - (long unsigned int)vsi->net_stats_offsets.tx_aborted_errors, - (long unsigned int)vsi->net_stats_offsets.tx_carrier_errors, - (long unsigned int)vsi->net_stats_offsets.tx_fifo_errors); + (unsigned long int)vsi->net_stats_offsets.tx_aborted_errors, + (unsigned long int)vsi->net_stats_offsets.tx_carrier_errors, + (unsigned long int)vsi->net_stats_offsets.tx_fifo_errors); dev_info(&pf->pdev->dev, " net_stats_offsets: tx_heartbeat_errors = %lu, tx_window_errors = %lu\n", - (long unsigned int)vsi->net_stats_offsets.tx_heartbeat_errors, - (long unsigned int)vsi->net_stats_offsets.tx_window_errors); + (unsigned long int)vsi->net_stats_offsets.tx_heartbeat_errors, + (unsigned long int)vsi->net_stats_offsets.tx_window_errors); dev_info(&pf->pdev->dev, " net_stats_offsets: rx_compressed = %lu, tx_compressed = %lu\n", - (long unsigned int)vsi->net_stats_offsets.rx_compressed, - (long unsigned int)vsi->net_stats_offsets.tx_compressed); + (unsigned long int)vsi->net_stats_offsets.rx_compressed, + (unsigned long int)vsi->net_stats_offsets.tx_compressed); dev_info(&pf->pdev->dev, " tx_restart = %d, tx_busy = %d, rx_buf_failed = %d, rx_page_failed = %d\n", vsi->tx_restart, vsi->tx_busy, @@ -487,6 +487,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) rcu_read_lock(); for (i = 0; i < vsi->num_queue_pairs; i++) { struct i40e_ring *rx_ring = ACCESS_ONCE(vsi->rx_rings[i]); + if (!rx_ring) continue; @@ -527,7 +528,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) dev_info(&pf->pdev->dev, " rx_rings[%i]: size = %i, dma = 0x%08lx\n", i, rx_ring->size, - (long unsigned int)rx_ring->dma); + (unsigned long int)rx_ring->dma); dev_info(&pf->pdev->dev, " rx_rings[%i]: vsi = %p, q_vector = %p\n", i, rx_ring->vsi, @@ -535,6 +536,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) } for (i = 0; i < vsi->num_queue_pairs; i++) { struct i40e_ring *tx_ring = ACCESS_ONCE(vsi->tx_rings[i]); + if (!tx_ring) continue; @@ -573,7 +575,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) dev_info(&pf->pdev->dev, " tx_rings[%i]: size = %i, dma = 0x%08lx\n", i, tx_ring->size, - (long unsigned int)tx_ring->dma); + (unsigned long int)tx_ring->dma); dev_info(&pf->pdev->dev, " tx_rings[%i]: vsi = %p, q_vector = %p\n", i, tx_ring->vsi, @@ -743,6 +745,7 @@ static void i40e_dbg_dump_aq_desc(struct i40e_pf *pf) ring = &(hw->aq.asq); for (i = 0; i < ring->count; i++) { struct i40e_aq_desc *d = I40E_ADMINQ_DESC(*ring, i); + dev_info(&pf->pdev->dev, " at[%02d] flags=0x%04x op=0x%04x dlen=0x%04x ret=0x%04x cookie_h=0x%08x cookie_l=0x%08x\n", i, d->flags, d->opcode, d->datalen, d->retval, @@ -755,6 +758,7 @@ static void i40e_dbg_dump_aq_desc(struct i40e_pf *pf) ring = &(hw->aq.arq); for (i = 0; i < ring->count; i++) { struct i40e_aq_desc *d = I40E_ADMINQ_DESC(*ring, i); + dev_info(&pf->pdev->dev, " ar[%02d] flags=0x%04x op=0x%04x dlen=0x%04x ret=0x%04x cookie_h=0x%08x cookie_l=0x%08x\n", i, d->flags, d->opcode, d->datalen, d->retval, @@ -1038,7 +1042,13 @@ static ssize_t i40e_dbg_command_write(struct file *filp, dev_info(&pf->pdev->dev, "'%s' failed\n", cmd_buf); } else if (strncmp(cmd_buf, "del vsi", 7) == 0) { - sscanf(&cmd_buf[7], "%i", &vsi_seid); + cnt = sscanf(&cmd_buf[7], "%i", &vsi_seid); + if (cnt != 1) { + dev_info(&pf->pdev->dev, + "del vsi: bad command string, cnt=%d\n", + cnt); + goto command_write_done; + } vsi = i40e_dbg_find_vsi(pf, vsi_seid); if (!vsi) { dev_info(&pf->pdev->dev, "del VSI %d: seid not found\n", @@ -1488,6 +1498,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, } else if (strncmp(cmd_buf, "read", 4) == 0) { u32 address; u32 value; + cnt = sscanf(&cmd_buf[4], "%i", &address); if (cnt != 1) { dev_info(&pf->pdev->dev, "read \n"); @@ -1507,6 +1518,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, } else if (strncmp(cmd_buf, "write", 5) == 0) { u32 address, value; + cnt = sscanf(&cmd_buf[5], "%i %i", &address, &value); if (cnt != 2) { dev_info(&pf->pdev->dev, "write \n"); @@ -1528,6 +1540,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, cnt = sscanf(&cmd_buf[15], "%i", &vsi_seid); if (cnt == 0) { int i; + for (i = 0; i < pf->num_alloc_vsi; i++) i40e_vsi_reset_stats(pf->vsi[i]); dev_info(&pf->pdev->dev, "vsi clear stats called for all vsi's\n"); @@ -1726,8 +1739,9 @@ static ssize_t i40e_dbg_command_write(struct file *filp, packet_len, I40E_FDIR_MAX_RAW_PACKET_SIZE); for (i = 0; i < packet_len; i++) { - sscanf(&asc_packet[j], "%2hhx ", - &raw_packet[i]); + cnt = sscanf(&asc_packet[j], "%2hhx ", &raw_packet[i]); + if (!cnt) + break; j += 3; } dev_info(&pf->pdev->dev, "FD raw packet dump\n"); @@ -1755,6 +1769,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, } else if (strncmp(cmd_buf, "lldp", 4) == 0) { if (strncmp(&cmd_buf[5], "stop", 4) == 0) { int ret; + ret = i40e_aq_stop_lldp(&pf->hw, false, NULL); if (ret) { dev_info(&pf->pdev->dev, @@ -1779,6 +1794,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, #endif /* CONFIG_I40E_DCB */ } else if (strncmp(&cmd_buf[5], "start", 5) == 0) { int ret; + ret = i40e_aq_add_rem_control_packet_filter(&pf->hw, pf->hw.mac.addr, I40E_ETH_P_LLDP, 0, @@ -1807,6 +1823,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, u16 llen, rlen; int ret; u8 *buff; + buff = kzalloc(I40E_LLDPDU_SIZE, GFP_KERNEL); if (!buff) goto command_write_done; @@ -1833,6 +1850,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, u16 llen, rlen; int ret; u8 *buff; + buff = kzalloc(I40E_LLDPDU_SIZE, GFP_KERNEL); if (!buff) goto command_write_done; @@ -1858,6 +1876,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, buff = NULL; } else if (strncmp(&cmd_buf[5], "event on", 8) == 0) { int ret; + ret = i40e_aq_cfg_lldp_mib_change_event(&pf->hw, true, NULL); if (ret) { @@ -1868,6 +1887,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp, } } else if (strncmp(&cmd_buf[5], "event off", 9) == 0) { int ret; + ret = i40e_aq_cfg_lldp_mib_change_event(&pf->hw, false, NULL); if (ret) { @@ -2105,6 +2125,7 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp, } } else if (strncmp(i40e_dbg_netdev_ops_buf, "change_mtu", 10) == 0) { int mtu; + cnt = sscanf(&i40e_dbg_netdev_ops_buf[11], "%i %i", &vsi_seid, &mtu); if (cnt != 2) { @@ -2220,7 +2241,6 @@ void i40e_dbg_pf_init(struct i40e_pf *pf) create_failed: dev_info(dev, "debugfs dir/file for %s failed\n", name); debugfs_remove_recursive(pf->i40e_dbg_pf); - return; } /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 5a726f2624e0..148f61461076 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1360,6 +1360,7 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, if ((pf->lan_veb != I40E_NO_VEB) && (pf->flags & I40E_FLAG_VEB_STATS_ENABLED)) { struct i40e_veb *veb = pf->veb[pf->lan_veb]; + for (j = 0; j < I40E_VEB_STATS_LEN; j++) { p = (char *)veb; p += i40e_gstrings_veb_stats[j].stat_offset; @@ -1607,7 +1608,7 @@ static inline bool i40e_active_vfs(struct i40e_pf *pf) int i; for (i = 0; i < pf->num_alloc_vfs; i++) - if (vfs[i].vf_states & I40E_VF_STAT_ACTIVE) + if (test_bit(I40E_VF_STAT_ACTIVE, &vfs[i].vf_states)) return true; return false; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index 2398d9bd08d8..eaedc1f4c257 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -324,7 +324,6 @@ void i40e_init_pf_fcoe(struct i40e_pf *pf) wr32(hw, I40E_GLFCOE_RCTL, val); dev_info(&pf->pdev->dev, "FCoE is supported.\n"); - return; } /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c index fa371a2a40c6..79ae7beeafe5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c +++ b/drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c @@ -431,9 +431,8 @@ exit_sd_error: pd_idx1 = max(pd_idx, ((j - 1) * I40E_HMC_MAX_BP_COUNT)); pd_lmt1 = min(pd_lmt, (j * I40E_HMC_MAX_BP_COUNT)); - for (i = pd_idx1; i < pd_lmt1; i++) { + for (i = pd_idx1; i < pd_lmt1; i++) i40e_remove_pd_bp(hw, info->hmc_info, i); - } i40e_remove_pd_page(hw, info->hmc_info, (j - 1)); break; case I40E_SD_TYPE_DIRECT: diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 23a7b40c764c..12b90fa45d87 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -216,10 +216,10 @@ static int i40e_get_lump(struct i40e_pf *pf, struct i40e_lump_tracking *pile, ret = i; pile->search_hint = i + j; break; - } else { - /* not enough, so skip over it and continue looking */ - i += j; } + + /* not enough, so skip over it and continue looking */ + i += j; } return ret; @@ -503,11 +503,11 @@ void i40e_vsi_reset_stats(struct i40e_vsi *vsi) memset(&vsi->eth_stats_offsets, 0, sizeof(vsi->eth_stats_offsets)); if (vsi->rx_rings && vsi->rx_rings[0]) { for (i = 0; i < vsi->num_queue_pairs; i++) { - memset(&vsi->rx_rings[i]->stats, 0 , + memset(&vsi->rx_rings[i]->stats, 0, sizeof(vsi->rx_rings[i]->stats)); - memset(&vsi->rx_rings[i]->rx_stats, 0 , + memset(&vsi->rx_rings[i]->rx_stats, 0, sizeof(vsi->rx_rings[i]->rx_stats)); - memset(&vsi->tx_rings[i]->stats, 0 , + memset(&vsi->tx_rings[i]->stats, 0, sizeof(vsi->tx_rings[i]->stats)); memset(&vsi->tx_rings[i]->tx_stats, 0, sizeof(vsi->tx_rings[i]->tx_stats)); @@ -843,6 +843,7 @@ static void i40e_update_prio_xoff_rx(struct i40e_pf *pf) for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) { u64 prio_xoff = nsd->priority_xoff_rx[i]; + i40e_stat_update32(hw, I40E_GLPRT_PXOFFRXC(hw->port, i), pf->stat_offsets_loaded, &osd->priority_xoff_rx[i], @@ -1439,6 +1440,7 @@ void i40e_del_filter(struct i40e_vsi *vsi, } else { /* make sure we don't remove a filter in use by VF or netdev */ int min_f = 0; + min_f += (f->is_vf ? 1 : 0); min_f += (f->is_netdev ? 1 : 0); @@ -1497,6 +1499,7 @@ static int i40e_set_mac(struct net_device *netdev, void *p) if (vsi->type == I40E_VSI_MAIN) { i40e_status ret; + ret = i40e_aq_mac_address_write(&vsi->back->hw, I40E_AQC_WRITE_TYPE_LAA_WOL, addr->sa_data, NULL); @@ -1932,6 +1935,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) /* check for changes in promiscuous modes */ if (changed_flags & IFF_ALLMULTI) { bool cur_multipromisc; + cur_multipromisc = !!(vsi->current_netdev_flags & IFF_ALLMULTI); ret = i40e_aq_set_vsi_multicast_promiscuous(&vsi->back->hw, vsi->seid, @@ -1946,6 +1950,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) } if ((changed_flags & IFF_PROMISC) || promisc_forced_on) { bool cur_promisc; + cur_promisc = (!!(vsi->current_netdev_flags & IFF_PROMISC) || test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state)); @@ -3259,6 +3264,7 @@ static irqreturn_t i40e_intr(int irq, void *data) /* temporarily disable queue cause for NAPI processing */ u32 qval = rd32(hw, I40E_QINT_RQCTL(0)); + qval &= ~I40E_QINT_RQCTL_CAUSE_ENA_MASK; wr32(hw, I40E_QINT_RQCTL(0), qval); @@ -3428,9 +3434,9 @@ static bool i40e_clean_fdir_tx_irq(struct i40e_ring *tx_ring, int budget) i += tx_ring->count; tx_ring->next_to_clean = i; - if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) { + if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) i40e_irq_dynamic_enable(vsi, tx_ring->q_vector->v_idx); - } + return budget > 0; } @@ -4034,11 +4040,10 @@ static void i40e_quiesce_vsi(struct i40e_vsi *vsi) } set_bit(__I40E_NEEDS_RESTART, &vsi->state); - if (vsi->netdev && netif_running(vsi->netdev)) { + if (vsi->netdev && netif_running(vsi->netdev)) vsi->netdev->netdev_ops->ndo_stop(vsi->netdev); - } else { + else i40e_vsi_close(vsi); - } } /** @@ -5313,15 +5318,13 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags) "VSI reinit requested\n"); for (v = 0; v < pf->num_alloc_vsi; v++) { struct i40e_vsi *vsi = pf->vsi[v]; + if (vsi != NULL && test_bit(__I40E_REINIT_REQUESTED, &vsi->state)) { i40e_vsi_reinit_locked(pf->vsi[v]); clear_bit(__I40E_REINIT_REQUESTED, &vsi->state); } } - - /* no further action needed, so return now */ - return; } else if (reset_flags & BIT_ULL(__I40E_DOWN_REQUESTED)) { int v; @@ -5329,6 +5332,7 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags) dev_info(&pf->pdev->dev, "VSI down requested\n"); for (v = 0; v < pf->num_alloc_vsi; v++) { struct i40e_vsi *vsi = pf->vsi[v]; + if (vsi != NULL && test_bit(__I40E_DOWN_REQUESTED, &vsi->state)) { set_bit(__I40E_DOWN, &vsi->state); @@ -5336,13 +5340,9 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags) clear_bit(__I40E_DOWN_REQUESTED, &vsi->state); } } - - /* no further action needed, so return now */ - return; } else { dev_info(&pf->pdev->dev, "bad reset request 0x%08x\n", reset_flags); - return; } } @@ -6286,6 +6286,7 @@ static int i40e_reconstitute_veb(struct i40e_veb *veb) if (pf->vsi[v]->veb_idx == veb->idx) { struct i40e_vsi *vsi = pf->vsi[v]; + vsi->uplink_seid = veb->seid; ret = i40e_add_vsi(vsi); if (ret) { @@ -9700,6 +9701,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) } else { /* force a reset of TC and queue layout configurations */ u8 enabled_tc = pf->vsi[pf->lan_vsi]->tc_config.enabled_tc; + pf->vsi[pf->lan_vsi]->tc_config.enabled_tc = 0; pf->vsi[pf->lan_vsi]->seid = pf->main_vsi_seid; i40e_vsi_config_tc(pf->vsi[pf->lan_vsi], enabled_tc); diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index 8c40d6ea15fd..552c84e2e05d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -618,9 +618,8 @@ static long i40e_ptp_create_clock(struct i40e_pf *pf) /* Attempt to register the clock before enabling the hardware. */ pf->ptp_clock = ptp_clock_register(&pf->ptp_caps, &pf->pdev->dev); - if (IS_ERR(pf->ptp_clock)) { + if (IS_ERR(pf->ptp_clock)) return PTR_ERR(pf->ptp_clock); - } /* clear the hwtstamp settings here during clock create, instead of * during regular init, so that we can maintain settings across a diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 8ab7ab1623f2..01e5ece8046d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1522,6 +1522,7 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget) cleaned_count++; if (rx_hbo || rx_sph) { int len; + if (rx_hbo) len = I40E_RX_HDR_SIZE; else @@ -1707,9 +1708,6 @@ static int i40e_clean_rx_irq_1buf(struct i40e_ring *rx_ring, int budget) /* ERR_MASK will only have valid bits if EOP set */ if (unlikely(rx_error & BIT(I40E_RX_DESC_ERROR_RXE_SHIFT))) { dev_kfree_skb_any(skb); - /* TODO: shouldn't we increment a counter indicating the - * drop? - */ continue; } @@ -2081,6 +2079,7 @@ static inline int i40e_tx_prepare_vlan_flags(struct sk_buff *skb, /* else if it is a SW VLAN, check the next protocol and store the tag */ } else if (protocol == htons(ETH_P_8021Q)) { struct vlan_hdr *vhdr, _vhdr; + vhdr = skb_header_pointer(skb, ETH_HLEN, sizeof(_vhdr), &_vhdr); if (!vhdr) return -EINVAL; @@ -2740,6 +2739,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, u8 hdr_len = 0; int tsyn; int tso; + if (0 == i40e_xmit_descriptor_count(skb, tx_ring)) return NETDEV_TX_BUSY; diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index ac3fb3a6f42d..75cecfa6e338 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -165,6 +165,7 @@ struct i40e_tx_buffer { }; unsigned int bytecount; unsigned short gso_segs; + DEFINE_DMA_UNMAP_ADDR(dma); DEFINE_DMA_UNMAP_LEN(len); u32 tx_flags; diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index fac8a02ab74e..678623fcd213 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -536,6 +536,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) } if (type == I40E_VSI_SRIOV) { u8 brdcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + vf->lan_vsi_idx = vsi->idx; vf->lan_vsi_id = vsi->id; /* If the port VLAN has been configured and then the @@ -605,6 +606,7 @@ static void i40e_enable_vf_mappings(struct i40e_vf *vf) /* map PF queues to VF queues */ for (j = 0; j < pf->vsi[vf->lan_vsi_idx]->alloc_queue_pairs; j++) { u16 qid = i40e_vc_get_pf_queue_id(vf, vf->lan_vsi_id, j); + reg = (qid & I40E_VPLAN_QTABLE_QINDEX_MASK); wr32(hw, I40E_VPLAN_QTABLE(total_queue_pairs, vf->vf_id), reg); total_queue_pairs++; @@ -991,7 +993,7 @@ static int i40e_pci_sriov_enable(struct pci_dev *pdev, int num_vfs) int pre_existing_vfs = pci_num_vf(pdev); int err = 0; - if (pf->state & __I40E_TESTING) { + if (test_bit(__I40E_TESTING, &pf->state)) { dev_warn(&pdev->dev, "Cannot enable SR-IOV virtual functions while the device is undergoing diagnostic testing\n"); err = -EPERM; @@ -1210,8 +1212,8 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) vfres->vsi_res[i].vsi_type = I40E_VSI_SRIOV; vfres->vsi_res[i].num_queue_pairs = pf->vsi[vf->lan_vsi_idx]->alloc_queue_pairs; - memcpy(vfres->vsi_res[i].default_mac_addr, - vf->default_lan_addr.addr, ETH_ALEN); + ether_addr_copy(vfres->vsi_res[i].default_mac_addr, + vf->default_lan_addr.addr); i++; } set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states); @@ -1715,6 +1717,7 @@ static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) for (i = 0; i < vfl->num_elements; i++) { /* add new VLAN filter */ int ret = i40e_vsi_add_vlan(vsi, vfl->vlan_id[i]); + if (ret) dev_err(&pf->pdev->dev, "Unable to add VF vlan filter %d, error %d\n", @@ -1766,6 +1769,7 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) for (i = 0; i < vfl->num_elements; i++) { int ret = i40e_vsi_kill_vlan(vsi, vfl->vlan_id[i]); + if (ret) dev_err(&pf->pdev->dev, "Unable to delete VF vlan filter %d, error %d\n", @@ -1877,7 +1881,6 @@ static int i40e_vc_validate_vf_msg(struct i40e_vf *vf, u32 v_opcode, case I40E_VIRTCHNL_OP_UNKNOWN: default: return -EPERM; - break; } /* few more checks */ if ((valid_len != msglen) || (err_msg_format)) { @@ -2316,7 +2319,7 @@ int i40e_ndo_get_vf_config(struct net_device *netdev, ivi->vf = vf_id; - memcpy(&ivi->mac, vf->default_lan_addr.addr, ETH_ALEN); + ether_addr_copy(ivi->mac, vf->default_lan_addr.addr); ivi->max_tx_rate = vf->tx_rate; ivi->min_tx_rate = 0; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c index c5cf886cdd08..3eba36913c1d 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq.c @@ -622,8 +622,7 @@ static u16 i40e_clean_asq(struct i40e_hw *hw) details = I40E_ADMINQ_DETAILS(*asq, ntc); while (rd32(hw, hw->aq.asq.head) != ntc) { i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE, - "%s: ntc %d head %d.\n", __func__, ntc, - rd32(hw, hw->aq.asq.head)); + "ntc %d head %d.\n", ntc, rd32(hw, hw->aq.asq.head)); if (details->callback) { I40E_ADMINQ_CALLBACK cb_func = diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c index 96e48ee8ab38..b98b642b897a 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_common.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c @@ -992,10 +992,10 @@ void i40e_vf_parse_hw_config(struct i40e_hw *hw, I40E_VIRTCHNL_VF_OFFLOAD_FCOE) ? 1 : 0; for (i = 0; i < msg->num_vsis; i++) { if (vsi_res->vsi_type == I40E_VSI_SRIOV) { - memcpy(hw->mac.perm_addr, vsi_res->default_mac_addr, - ETH_ALEN); - memcpy(hw->mac.addr, vsi_res->default_mac_addr, - ETH_ALEN); + ether_addr_copy(hw->mac.perm_addr, + vsi_res->default_mac_addr); + ether_addr_copy(hw->mac.addr, + vsi_res->default_mac_addr); } vsi_res++; } diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 3b102f209a96..0e71eb4633d5 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -987,6 +987,7 @@ static int i40e_clean_rx_irq_ps(struct i40e_ring *rx_ring, int budget) cleaned_count++; if (rx_hbo || rx_sph) { int len; + if (rx_hbo) len = I40E_RX_HDR_SIZE; else @@ -1160,9 +1161,6 @@ static int i40e_clean_rx_irq_1buf(struct i40e_ring *rx_ring, int budget) /* ERR_MASK will only have valid bits if EOP set */ if (unlikely(rx_error & BIT(I40E_RX_DESC_ERROR_RXE_SHIFT))) { dev_kfree_skb_any(skb); - /* TODO: shouldn't we increment a counter indicating the - * drop? - */ continue; } @@ -1358,6 +1356,7 @@ static inline int i40evf_tx_prepare_vlan_flags(struct sk_buff *skb, /* else if it is a SW VLAN, check the next protocol and store the tag */ } else if (protocol == htons(ETH_P_8021Q)) { struct vlan_hdr *vhdr, _vhdr; + vhdr = skb_header_pointer(skb, ETH_HLEN, sizeof(_vhdr), &_vhdr); if (!vhdr) return -EINVAL; @@ -1900,6 +1899,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb, u32 td_cmd = 0; u8 hdr_len = 0; int tso; + if (0 == i40evf_xmit_descriptor_count(skb, tx_ring)) return NETDEV_TX_BUSY; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index 93b90f7e8e86..0c13ece00366 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -164,6 +164,7 @@ struct i40e_tx_buffer { }; unsigned int bytecount; unsigned short gso_segs; + DEFINE_DMA_UNMAP_ADDR(dma); DEFINE_DMA_UNMAP_LEN(len); u32 tx_flags; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index 3817cbbf45e6..27dc3fe144a8 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -48,10 +48,6 @@ #define DEFAULT_DEBUG_LEVEL_SHIFT 3 #define PFX "i40evf: " -#define DPRINTK(nlevel, klevel, fmt, args...) \ - ((void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \ - printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \ - __func__ , ## args))) /* dummy struct to make common code less painful */ struct i40e_vsi { -- cgit v1.2.3 From a5fdaf342aa2fa6679dcb87dad2f78f1309de29e Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 28 Aug 2015 17:55:56 -0400 Subject: i40e: refactor code to remove indent I found a code indent that was avoidable because a whole function is inside an if block, reverse the if and move the code back a tab. Change-ID: I9989c8750ee61678fbf96a3b0fd7bf7cc7ef300a Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 82 +++++++++++++++-------------- 1 file changed, 42 insertions(+), 40 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 12b90fa45d87..c46d8140e8fa 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5679,49 +5679,51 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf) if (!(pf->flags & (I40E_FLAG_FD_SB_ENABLED | I40E_FLAG_FD_ATR_ENABLED))) return; - if (time_after(jiffies, pf->fd_flush_timestamp + - (I40E_MIN_FD_FLUSH_INTERVAL * HZ))) { - /* If the flush is happening too quick and we have mostly - * SB rules we should not re-enable ATR for some time. - */ - min_flush_time = pf->fd_flush_timestamp - + (I40E_MIN_FD_FLUSH_SB_ATR_UNSTABLE * HZ); - fd_room = pf->fdir_pf_filter_count - pf->fdir_pf_active_filters; + if (!time_after(jiffies, pf->fd_flush_timestamp + + (I40E_MIN_FD_FLUSH_INTERVAL * HZ))) + return; - if (!(time_after(jiffies, min_flush_time)) && - (fd_room < I40E_FDIR_BUFFER_HEAD_ROOM_FOR_ATR)) { - if (I40E_DEBUG_FD & pf->hw.debug_mask) - dev_info(&pf->pdev->dev, "ATR disabled, not enough FD filter space.\n"); - disable_atr = true; - } + /* If the flush is happening too quick and we have mostly SB rules we + * should not re-enable ATR for some time. + */ + min_flush_time = pf->fd_flush_timestamp + + (I40E_MIN_FD_FLUSH_SB_ATR_UNSTABLE * HZ); + fd_room = pf->fdir_pf_filter_count - pf->fdir_pf_active_filters; - pf->fd_flush_timestamp = jiffies; - pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED; - /* flush all filters */ - wr32(&pf->hw, I40E_PFQF_CTL_1, - I40E_PFQF_CTL_1_CLEARFDTABLE_MASK); - i40e_flush(&pf->hw); - pf->fd_flush_cnt++; - pf->fd_add_err = 0; - do { - /* Check FD flush status every 5-6msec */ - usleep_range(5000, 6000); - reg = rd32(&pf->hw, I40E_PFQF_CTL_1); - if (!(reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK)) - break; - } while (flush_wait_retry--); - if (reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK) { - dev_warn(&pf->pdev->dev, "FD table did not flush, needs more time\n"); - } else { - /* replay sideband filters */ - i40e_fdir_filter_restore(pf->vsi[pf->lan_vsi]); - if (!disable_atr) - pf->flags |= I40E_FLAG_FD_ATR_ENABLED; - clear_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state); - if (I40E_DEBUG_FD & pf->hw.debug_mask) - dev_info(&pf->pdev->dev, "FD Filter table flushed and FD-SB replayed.\n"); - } + if (!(time_after(jiffies, min_flush_time)) && + (fd_room < I40E_FDIR_BUFFER_HEAD_ROOM_FOR_ATR)) { + if (I40E_DEBUG_FD & pf->hw.debug_mask) + dev_info(&pf->pdev->dev, "ATR disabled, not enough FD filter space.\n"); + disable_atr = true; + } + + pf->fd_flush_timestamp = jiffies; + pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED; + /* flush all filters */ + wr32(&pf->hw, I40E_PFQF_CTL_1, + I40E_PFQF_CTL_1_CLEARFDTABLE_MASK); + i40e_flush(&pf->hw); + pf->fd_flush_cnt++; + pf->fd_add_err = 0; + do { + /* Check FD flush status every 5-6msec */ + usleep_range(5000, 6000); + reg = rd32(&pf->hw, I40E_PFQF_CTL_1); + if (!(reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK)) + break; + } while (flush_wait_retry--); + if (reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK) { + dev_warn(&pf->pdev->dev, "FD table did not flush, needs more time\n"); + } else { + /* replay sideband filters */ + i40e_fdir_filter_restore(pf->vsi[pf->lan_vsi]); + if (!disable_atr) + pf->flags |= I40E_FLAG_FD_ATR_ENABLED; + clear_bit(__I40E_FD_FLUSH_REQUESTED, &pf->state); + if (I40E_DEBUG_FD & pf->hw.debug_mask) + dev_info(&pf->pdev->dev, "FD Filter table flushed and FD-SB replayed.\n"); } + } /** -- cgit v1.2.3 From 8ed995ff6bb9c5436db64b3653a0c62a0cd18f08 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 28 Aug 2015 17:55:57 -0400 Subject: i40evf: use capabilities flags properly Use the capabilities passed to us by the PF driver to control VF driver behavior. In the process, clean up the VLAN add/remove code so it's not a horrible morass of ifdefs. Change-ID: I1050eaf12b658a26fea6813047c9964163c70a73 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 664fde68b537..1f999305c406 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -730,6 +730,8 @@ static int i40evf_vlan_rx_add_vid(struct net_device *netdev, { struct i40evf_adapter *adapter = netdev_priv(netdev); + if (!VLAN_ALLOWED(adapter)) + return -EIO; if (i40evf_add_vlan(adapter, vid) == NULL) return -ENOMEM; return 0; @@ -745,8 +747,11 @@ static int i40evf_vlan_rx_kill_vid(struct net_device *netdev, { struct i40evf_adapter *adapter = netdev_priv(netdev); - i40evf_del_vlan(adapter, vid); - return 0; + if (VLAN_ALLOWED(adapter)) { + i40evf_del_vlan(adapter, vid); + return 0; + } + return -EIO; } /** -- cgit v1.2.3 From f578f5f453abf09e8cb4c3aaf1e0c3bdf8125493 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Fri, 28 Aug 2015 17:55:58 -0400 Subject: i40e/i40evf: pass QOS handle to VF The VF really doesn't care about the QOS handle but it will in the future. Since the VF only uses TC0, send it that handle. On the VF side, save the handle and use it to populate the QOS params when we call into the client interface. Change-ID: I76f41b070baeaa09b19383e9168bc677837e0761 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 6 ++++-- drivers/net/ethernet/intel/i40evf/i40evf.h | 1 + drivers/net/ethernet/intel/i40evf/i40evf_main.c | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 678623fcd213..ee747dc5d617 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1210,8 +1210,10 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) if (vf->lan_vsi_idx) { vfres->vsi_res[i].vsi_id = vf->lan_vsi_id; vfres->vsi_res[i].vsi_type = I40E_VSI_SRIOV; - vfres->vsi_res[i].num_queue_pairs = - pf->vsi[vf->lan_vsi_idx]->alloc_queue_pairs; + vfres->vsi_res[i].num_queue_pairs = vsi->alloc_queue_pairs; + /* VFs only use TC 0 */ + vfres->vsi_res[i].qset_handle + = le16_to_cpu(vsi->info.qs_handle[0]); ether_addr_copy(vfres->vsi_res[i].default_mac_addr, vf->default_lan_addr.addr); i++; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index 27dc3fe144a8..e7a223ea6c25 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -66,6 +66,7 @@ struct i40e_vsi { */ u16 rx_itr_setting; u16 tx_itr_setting; + u16 qs_handle; }; /* How many Rx Buffers do we bundle into one write to the hardware ? */ diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 1f999305c406..c00e4959f026 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2115,6 +2115,7 @@ int i40evf_process_config(struct i40evf_adapter *adapter) adapter->vsi.tx_itr_setting = (I40E_ITR_DYNAMIC | ITR_REG_TO_USEC(I40E_ITR_TX_DEF)); adapter->vsi.netdev = adapter->netdev; + adapter->vsi.qs_handle = adapter->vsi_res->qset_handle; return 0; } -- cgit v1.2.3 From ce6fcb3f2467902b48e59d1c866c5b4c9f6136eb Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 28 Aug 2015 17:55:59 -0400 Subject: i40e: print neato new features To help users and developers know what compile options and hardware features are enabled at compile time, print VxLAN is available. Change-ID: I3162f3b7678dc725a597f964217920eb218b480b Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index c46d8140e8fa..a484f2265524 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -9914,6 +9914,9 @@ static void i40e_print_features(struct i40e_pf *pf) } if (pf->flags & I40E_FLAG_DCB_CAPABLE) buf += sprintf(buf, "DCB "); +#if IS_ENABLED(CONFIG_VXLAN) + buf += sprintf(buf, "VxLAN "); +#endif if (pf->flags & I40E_FLAG_PTP) buf += sprintf(buf, "PTP "); #ifdef I40E_FCOE -- cgit v1.2.3 From 39b91b8144e028cbe383548f76c1f8cdb7977532 Mon Sep 17 00:00:00 2001 From: Maharaja Kennadyrajan Date: Tue, 6 Oct 2015 15:19:28 +0300 Subject: ath10k: increase pci wakeup timeout to 30 ms It is noticed that pci wakeup time is exceeding current timeout (10ms) randomly which is tested on QCA988x. So, the wake up time is increased to 30 ms and added debug prints to log total timeout. Signed-off-by: Maharaja Kennadyrajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 6 +++++- drivers/net/wireless/ath/ath10k/pci.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 61df93e2e1c9..7af39118b1f4 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -452,8 +452,12 @@ static int ath10k_pci_wake_wait(struct ath10k *ar) int curr_delay = 5; while (tot_delay < PCIE_WAKE_TIMEOUT) { - if (ath10k_pci_is_awake(ar)) + if (ath10k_pci_is_awake(ar)) { + if (tot_delay > PCIE_WAKE_LATE_US) + ath10k_warn(ar, "device wakeup took %d ms which is unusally long, otherwise it works normally.\n", + tot_delay / 1000); return 0; + } udelay(curr_delay); tot_delay += curr_delay; diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 8d364fb8f743..54af2d7fbe7b 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -230,7 +230,8 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) #define ATH10K_PCI_RX_POST_RETRY_MS 50 #define ATH_PCI_RESET_WAIT_MAX 10 /* ms */ -#define PCIE_WAKE_TIMEOUT 10000 /* 10ms */ +#define PCIE_WAKE_TIMEOUT 30000 /* 30ms */ +#define PCIE_WAKE_LATE_US 10000 /* 10ms */ #define BAR_NUM 0 -- cgit v1.2.3 From ab4e3db043589204041c00272f751d05b4e52c50 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 6 Oct 2015 15:19:33 +0300 Subject: ath10k: optimize ce_lock on post rx buffer processing After processing received packets from copy engine, host will allocate new buffer and queue them back to copy engine ring for further packet reception. On post rx processing path, skb allocation and dma mapping are unnecessarily handled within ce_lock. This is affecting peak throughput and also causing more CPU consumption. Optimize this by acquiring ce_lock only when accessing copy engine ring and moving skb allocation out of ce_lock. In AP148 platform with QCA99x0 in conducted environment, UDP uplink peak throughput is improved from ~1320 Mbps to ~1450 Mbps and TCP uplink peak throughput is increased from ~1240 Mbps (70% host CPU load) to ~1300 Mbps (71% CPU load). Similarly ~40Mbps improvement is observed in downlink path. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 2 +- drivers/net/wireless/ath/ath10k/pci.c | 27 ++++++++------------------- 2 files changed, 9 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index cf28fbebaedc..8d7ab1ccc005 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -413,7 +413,7 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) lockdep_assert_held(&ar_pci->ce_lock); if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0) - return -EIO; + return -ENOSPC; desc->addr = __cpu_to_le32(paddr); desc->nbytes = 0; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 7af39118b1f4..4401779af253 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -686,8 +686,6 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe) dma_addr_t paddr; int ret; - lockdep_assert_held(&ar_pci->ce_lock); - skb = dev_alloc_skb(pipe->buf_sz); if (!skb) return -ENOMEM; @@ -705,9 +703,10 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe) ATH10K_SKB_RXCB(skb)->paddr = paddr; + spin_lock_bh(&ar_pci->ce_lock); ret = __ath10k_ce_rx_post_buf(ce_pipe, skb, paddr); + spin_unlock_bh(&ar_pci->ce_lock); if (ret) { - ath10k_warn(ar, "failed to post pci rx buf: %d\n", ret); dma_unmap_single(ar->dev, paddr, skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); dev_kfree_skb_any(skb); @@ -717,25 +716,27 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe) return 0; } -static void __ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) +static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) { struct ath10k *ar = pipe->hif_ce_state; struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_ce_pipe *ce_pipe = pipe->ce_hdl; int ret, num; - lockdep_assert_held(&ar_pci->ce_lock); - if (pipe->buf_sz == 0) return; if (!ce_pipe->dest_ring) return; + spin_lock_bh(&ar_pci->ce_lock); num = __ath10k_ce_rx_num_free_bufs(ce_pipe); + spin_unlock_bh(&ar_pci->ce_lock); while (num--) { ret = __ath10k_pci_rx_post_buf(pipe); if (ret) { + if (ret == -ENOSPC) + break; ath10k_warn(ar, "failed to post pci rx buf: %d\n", ret); mod_timer(&ar_pci->rx_post_retry, jiffies + ATH10K_PCI_RX_POST_RETRY_MS); @@ -744,25 +745,13 @@ static void __ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) } } -static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) -{ - struct ath10k *ar = pipe->hif_ce_state; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - - spin_lock_bh(&ar_pci->ce_lock); - __ath10k_pci_rx_post_pipe(pipe); - spin_unlock_bh(&ar_pci->ce_lock); -} - static void ath10k_pci_rx_post(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int i; - spin_lock_bh(&ar_pci->ce_lock); for (i = 0; i < CE_COUNT; i++) - __ath10k_pci_rx_post_pipe(&ar_pci->pipe_info[i]); - spin_unlock_bh(&ar_pci->ce_lock); + ath10k_pci_rx_post_pipe(&ar_pci->pipe_info[i]); } static void ath10k_pci_rx_replenish_retry(unsigned long ptr) -- cgit v1.2.3 From 72f8cef5d1155209561b01e092ce1a04ad50c4cb Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Tue, 6 Oct 2015 15:19:34 +0300 Subject: ath10k: use station's current operating mode from assoc request The current number of spatial streams used by the client is advertised as a separate IE in assoc request. Use this information to set the NSS operating mode. Fixes: 45c9abc059fa ("ath10k: implement more versatile set_bitrate_mask"). Signed-off-by: Vivek Natarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 803a708f2298..6bfaead35298 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -2084,7 +2084,8 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, enum ieee80211_band band; const u8 *ht_mcs_mask; const u16 *vht_mcs_mask; - int i, n, max_nss; + int i, n; + u8 max_nss; u32 stbc; lockdep_assert_held(&ar->conf_mutex); @@ -2169,7 +2170,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, arg->peer_ht_rates.rates[i] = i; } else { arg->peer_ht_rates.num_rates = n; - arg->peer_num_spatial_streams = max_nss; + arg->peer_num_spatial_streams = min(sta->rx_nss, max_nss); } ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n", -- cgit v1.2.3 From 5a813da0068dbe46b77897c955b4059c7ffee4d8 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 4 Oct 2015 10:23:18 +0300 Subject: wil6210: fix warning in system power management code Fix compilation warning where CONFIG_PM defined while CONFIG_PM_SLEEP is not defined Report follows: tree: git://github.com/kvalo/ath pending head: 941145fc5e5afbb120271e5dfaf37213ddb55807 commit: df596be39294d9712e5d568063a48448031e0a9f [37/39] wil6210: system power management config: xtensa-allyesconfig (attached as .config) reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross git checkout df596be39294d9712e5d568063a48448031e0a9f # save the attached .config to linux build tree make.cross ARCH=xtensa All warnings (new ones prefixed by >>): >> drivers/net/wireless/ath/wil6210/pcie_bus.c:264:12: warning: 'wil6210_suspend' defined but not used [-Wunused-function] static int wil6210_suspend(struct device *dev, bool is_runtime) ^ >> drivers/net/wireless/ath/wil6210/pcie_bus.c:291:12: warning: 'wil6210_resume' defined but not used [-Wunused-function] static int wil6210_resume(struct device *dev, bool is_runtime) ^ Reported-by: kbuild test robot Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/pcie_bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index feff1ef10fb3..1a3142c332e1 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -260,6 +260,7 @@ static const struct pci_device_id wil6210_pcie_ids[] = { MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); #ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int wil6210_suspend(struct device *dev, bool is_runtime) { @@ -307,7 +308,6 @@ static int wil6210_resume(struct device *dev, bool is_runtime) return rc; } -#ifdef CONFIG_PM_SLEEP static int wil6210_pm_suspend(struct device *dev) { return wil6210_suspend(dev, false); -- cgit v1.2.3 From 3b282bc6095f77908cb83427d93f0764e8419fdb Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 4 Oct 2015 10:23:19 +0300 Subject: wil6210: Add proper handling for invalid frames on Rx On Rx, when invalid frame is received and dropped, reaping of next frames from Rx ring is stopped. This stops NAPI polling and re-enables the Rx interrupt. However, in cases where no more frames received, interrupt will not be triggered and rest of Rx frames will not be processed. Skip bad frames and continue to reap Rx packets when such frames are encountered, and add statistics for such frames for debug. Signed-off-by: Hamad Kadmany Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/debugfs.c | 6 ++++++ drivers/net/wireless/ath/wil6210/txrx.c | 20 +++++++++++++------- drivers/net/wireless/ath/wil6210/wil6210.h | 3 +++ 3 files changed, 22 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index d1a1e160ef31..97bc186f9728 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1373,6 +1373,12 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) } } spin_unlock_bh(&p->tid_rx_lock); + seq_printf(s, + "Rx invalid frame: non-data %lu, short %lu, large %lu\n", + p->stats.rx_non_data_frame, + p->stats.rx_short_frame, + p->stats.rx_large_frame); + seq_puts(s, "Rx/MCS:"); for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs); mcs++) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 6229110d558a..8ba271f685f4 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -379,14 +379,16 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, u16 dmalen; u8 ftype; int cid; - int i = (int)vring->swhead; + int i; struct wil_net_stats *stats; BUILD_BUG_ON(sizeof(struct vring_rx_desc) > sizeof(skb->cb)); +again: if (unlikely(wil_vring_is_empty(vring))) return NULL; + i = (int)vring->swhead; _d = &vring->va[i].rx; if (unlikely(!(_d->dma.status & RX_DMA_STATUS_DU))) { /* it is not error, we just reached end of Rx done area */ @@ -398,7 +400,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, wil_vring_advance_head(vring, 1); if (!skb) { wil_err(wil, "No Rx skb at [%d]\n", i); - return NULL; + goto again; } d = wil_skb_rxdesc(skb); *d = *_d; @@ -412,10 +414,14 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); + cid = wil_rxdesc_cid(d); + stats = &wil->sta[cid].stats; + if (unlikely(dmalen > sz)) { wil_err(wil, "Rx size too large: %d bytes!\n", dmalen); + stats->rx_large_frame++; kfree_skb(skb); - return NULL; + goto again; } skb_trim(skb, dmalen); @@ -424,8 +430,6 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb_headlen(skb), false); - cid = wil_rxdesc_cid(d); - stats = &wil->sta[cid].stats; stats->last_mcs_rx = wil_rxdesc_mcs(d); if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs)) stats->rx_per_mcs[stats->last_mcs_rx]++; @@ -446,15 +450,17 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, if (unlikely(ftype != IEEE80211_FTYPE_DATA)) { wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype); /* TODO: process it */ + stats->rx_non_data_frame++; kfree_skb(skb); - return NULL; + goto again; } if (unlikely(skb->len < ETH_HLEN + snaplen)) { wil_err(wil, "Short frame, len = %d\n", skb->len); /* TODO: process it (i.e. BAR) */ + stats->rx_short_frame++; kfree_skb(skb); - return NULL; + goto again; } /* L4 IDENT is on when HW calculated checksum, check status diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index dd4ea926b8e3..e405bef10433 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -465,6 +465,9 @@ struct wil_net_stats { unsigned long tx_bytes; unsigned long tx_errors; unsigned long rx_dropped; + unsigned long rx_non_data_frame; + unsigned long rx_short_frame; + unsigned long rx_large_frame; u16 last_mcs_rx; u64 rx_per_mcs[WIL_MCS_MAX + 1]; }; -- cgit v1.2.3 From bf2f67343eedc276b8441f91d8daaef4f3ed11d0 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 4 Oct 2015 10:23:20 +0300 Subject: wil6210: log firmware crash information Print firmware and ucode assert codes when firmware crashed. Signed-off-by: Lior David Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/interrupt.c | 7 ++++++- drivers/net/wireless/ath/wil6210/wil6210.h | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index a371f036d054..f651994fee5e 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -347,7 +347,12 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) wil6210_mask_irq_misc(wil); if (isr & ISR_MISC_FW_ERROR) { - wil_err(wil, "Firmware error detected\n"); + u32 fw_assert_code = wil_r(wil, RGF_FW_ASSERT_CODE); + u32 ucode_assert_code = wil_r(wil, RGF_UCODE_ASSERT_CODE); + + wil_err(wil, + "Firmware error detected, assert codes FW 0x%08x, UCODE 0x%08x\n", + fw_assert_code, ucode_assert_code); clear_bit(wil_status_fwready, wil->status); /* * do not clear @isr here - we do 2-nd part in thread diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index e405bef10433..525ce2cbec64 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -246,6 +246,10 @@ struct RGF_ICR { #define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */ #define JTAG_DEV_ID_SPARROW_B0 (0x2632072f) +/* crash codes for FW/Ucode stored here */ +#define RGF_FW_ASSERT_CODE (0x91f020) +#define RGF_UCODE_ASSERT_CODE (0x91f028) + enum { HW_VER_UNKNOWN, HW_VER_SPARROW_B0, /* JTAG_DEV_ID_SPARROW_B0 */ -- cgit v1.2.3 From 6cc6c468381e369e6450257645cf65c67f9f4a1b Mon Sep 17 00:00:00 2001 From: Vladimir Shulman Date: Sun, 4 Oct 2015 10:23:21 +0300 Subject: wil6210: pmc logger bug fix When allocating pmc descriptor, the structure is initially created on stack and later copied to the physical ring (device) memory. The descriptor structure must be initialized to zero to avoid garbage configuration, which may result in pmc mechanism malfunctioning. Signed-off-by: Vladimir Shulman Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/pmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c index 8a8cdc61b25b..5ca0307a3274 100644 --- a/drivers/net/wireless/ath/wil6210/pmc.c +++ b/drivers/net/wireless/ath/wil6210/pmc.c @@ -110,7 +110,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, */ for (i = 0; i < num_descriptors; i++) { struct vring_tx_desc *_d = &pmc->pring_va[i]; - struct vring_tx_desc dd, *d = ⅆ + struct vring_tx_desc dd = {}, *d = ⅆ int j = 0; pmc->descriptors[i].va = dma_alloc_coherent(dev, -- cgit v1.2.3 From 68682b4108f1254a34e40f516f9ab1f49b4754fc Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 4 Oct 2015 10:23:22 +0300 Subject: wil6210: treat broadcast bssid as "disconnect all" Hostapd request disconnect for broadcast bssid when it wants to disconnect all stations from the AP. Detect this and really disconnect all connected stations. Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 2fb04c51da53..de6e3c279f97 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -203,11 +203,13 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, * - disconnect single STA, already disconnected * - disconnect all * - * For "disconnect all", there are 2 options: + * For "disconnect all", there are 3 options: * - bssid == NULL + * - bssid is broadcast address (ff:ff:ff:ff:ff:ff) * - bssid is our MAC address */ - if (bssid && memcmp(ndev->dev_addr, bssid, ETH_ALEN)) { + if (bssid && !is_broadcast_ether_addr(bssid) && + !ether_addr_equal_unaligned(ndev->dev_addr, bssid)) { cid = wil_find_cid(wil, bssid); wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n", bssid, cid, reason_code); -- cgit v1.2.3 From a8313341c4a83d5da18aad07501119da649d58dc Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 4 Oct 2015 10:23:23 +0300 Subject: wil6210: support BAR (BlockAck Req) BAR frames delivered to the host via Rx path; whole BAR frame get delivered. Advance sequence in the reorder buffer and release old frames, as per IEEE802.11 spec. Firmware will reply to BAR, driver responsibility is only reorder buffer management. Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/rx_reorder.c | 26 +++++++++++++++++ drivers/net/wireless/ath/wil6210/txrx.c | 40 +++++++++++++++++++++++---- drivers/net/wireless/ath/wil6210/txrx.h | 7 +++++ 3 files changed, 67 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 9238c1ac23dd..e3d1be82f314 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -205,6 +205,32 @@ out: spin_unlock(&sta->tid_rx_lock); } +/* process BAR frame, called in NAPI context */ +void wil_rx_bar(struct wil6210_priv *wil, u8 cid, u8 tid, u16 seq) +{ + struct wil_sta_info *sta = &wil->sta[cid]; + struct wil_tid_ampdu_rx *r; + + spin_lock(&sta->tid_rx_lock); + + r = sta->tid_rx[tid]; + if (!r) { + wil_err(wil, "BAR for non-existing CID %d TID %d\n", cid, tid); + goto out; + } + if (seq_less(seq, r->head_seq_num)) { + wil_err(wil, "BAR Seq 0x%03x preceding head 0x%03x\n", + seq, r->head_seq_num); + goto out; + } + wil_dbg_txrx(wil, "BAR: CID %d TID %d Seq 0x%03x head 0x%03x\n", + cid, tid, seq, r->head_seq_num); + wil_release_reorder_frames(wil, r, seq); + +out: + spin_unlock(&sta->tid_rx_lock); +} + struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, int size, u16 ssn) { diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 8ba271f685f4..c530c795f4ab 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -358,6 +358,13 @@ static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, } } +/* similar to ieee80211_ version, but FC contain only 1-st byte */ +static inline int wil_is_back_req(u8 fc) +{ + return (fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ); +} + /** * reap 1 frame from @swhead * @@ -411,7 +418,7 @@ again: trace_wil6210_rx(i, d); wil_dbg_txrx(wil, "Rx[%3d] : %d bytes\n", i, dmalen); - wil_hex_dump_txrx("Rx ", DUMP_PREFIX_NONE, 32, 4, + wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4, (const void *)d, sizeof(*d), false); cid = wil_rxdesc_cid(d); @@ -441,23 +448,44 @@ again: /* no extra checks if in sniffer mode */ if (ndev->type != ARPHRD_ETHER) return skb; - /* - * Non-data frames may be delivered through Rx DMA channel (ex: BAR) + /* Non-data frames may be delivered through Rx DMA channel (ex: BAR) * Driver should recognize it by frame type, that is found * in Rx descriptor. If type is not data, it is 802.11 frame as is */ ftype = wil_rxdesc_ftype(d) << 2; if (unlikely(ftype != IEEE80211_FTYPE_DATA)) { - wil_dbg_txrx(wil, "Non-data frame ftype 0x%08x\n", ftype); - /* TODO: process it */ + u8 fc1 = wil_rxdesc_fc1(d); + int mid = wil_rxdesc_mid(d); + int tid = wil_rxdesc_tid(d); + u16 seq = wil_rxdesc_seq(d); + + wil_dbg_txrx(wil, + "Non-data frame FC[7:0] 0x%02x MID %d CID %d TID %d Seq 0x%03x\n", + fc1, mid, cid, tid, seq); stats->rx_non_data_frame++; + if (wil_is_back_req(fc1)) { + wil_dbg_txrx(wil, + "BAR: MID %d CID %d TID %d Seq 0x%03x\n", + mid, cid, tid, seq); + wil_rx_bar(wil, cid, tid, seq); + } else { + /* print again all info. One can enable only this + * without overhead for printing every Rx frame + */ + wil_dbg_txrx(wil, + "Unhandled non-data frame FC[7:0] 0x%02x MID %d CID %d TID %d Seq 0x%03x\n", + fc1, mid, cid, tid, seq); + wil_hex_dump_txrx("RxD ", DUMP_PREFIX_NONE, 32, 4, + (const void *)d, sizeof(*d), false); + wil_hex_dump_txrx("Rx ", DUMP_PREFIX_OFFSET, 16, 1, + skb->data, skb_headlen(skb), false); + } kfree_skb(skb); goto again; } if (unlikely(skb->len < ETH_HLEN + snaplen)) { wil_err(wil, "Short frame, len = %d\n", skb->len); - /* TODO: process it (i.e. BAR) */ stats->rx_short_frame++; kfree_skb(skb); goto again; diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index 82a8f9a030e7..ee7c7b4b9a17 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h @@ -464,6 +464,12 @@ static inline int wil_rxdesc_subtype(struct vring_rx_desc *d) return WIL_GET_BITS(d->mac.d0, 12, 15); } +/* 1-st byte (with frame type/subtype) of FC field */ +static inline u8 wil_rxdesc_fc1(struct vring_rx_desc *d) +{ + return (u8)(WIL_GET_BITS(d->mac.d0, 10, 15) << 2); +} + static inline int wil_rxdesc_seq(struct vring_rx_desc *d) { return WIL_GET_BITS(d->mac.d0, 16, 27); @@ -501,6 +507,7 @@ static inline struct vring_rx_desc *wil_skb_rxdesc(struct sk_buff *skb) void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev); void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb); +void wil_rx_bar(struct wil6210_priv *wil, u8 cid, u8 tid, u16 seq); struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, int size, u16 ssn); void wil_tid_ampdu_rx_free(struct wil6210_priv *wil, -- cgit v1.2.3 From 4765332df9222b9172ce2e5172f1e8e8ffc6d554 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 4 Oct 2015 10:23:24 +0300 Subject: wil6210: capture all frames in sniffer mode For the sniffer (monitor) mode, capture either control only or both control and data PHY. It used to be control only or data only PHY due to firmware issues with configuration for PHY auto-detection; but now it is resolved. Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 2f35d4c51f34..61121892c6ca 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1120,7 +1120,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP); cmd.sniffer_cfg.phy_support = cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL) - ? WMI_SNIFFER_CP : WMI_SNIFFER_DP); + ? WMI_SNIFFER_CP : WMI_SNIFFER_BOTH_PHYS); } else { /* Initialize offload (in non-sniffer mode). * Linux IP stack always calculates IP checksum -- cgit v1.2.3 From a3dcbae2476f2c32e8f123dd833d789f7f494711 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 4 Oct 2015 10:23:25 +0300 Subject: wil6210: ratelimit Tx error message Situations observed when IP stack schedules lots of frames for Tx while no connection (connection lost, for example). In this case, dmesg bloated with error message "FW not connected", printed for every frame. Ratelimit this error message to avoid dmesg pollution. Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index c530c795f4ab..0f8b6877497e 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -1667,7 +1667,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) goto drop; } if (unlikely(!test_bit(wil_status_fwconnected, wil->status))) { - wil_err(wil, "FW not connected\n"); + wil_err_ratelimited(wil, "FW not connected\n"); goto drop; } if (unlikely(wil->wdev->iftype == NL80211_IFTYPE_MONITOR)) { -- cgit v1.2.3 From 7dc47258a00d026ba1268133687b3b1940e36e58 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 4 Oct 2015 10:23:26 +0300 Subject: wil6210: dump firmware memory when firmware crashes When firmware crashes, just before firmware recovery, dump the firmware memory to a devcoredump device. The resulting dump can be read from user space to be used in offline crash analysis. Signed-off-by: Lior David Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/Kconfig | 1 + drivers/net/wireless/ath/wil6210/Makefile | 1 + drivers/net/wireless/ath/wil6210/interrupt.c | 3 +- drivers/net/wireless/ath/wil6210/wil6210.h | 2 + drivers/net/wireless/ath/wil6210/wil_crash_dump.c | 115 ++++++++++++++++++++++ 5 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 drivers/net/wireless/ath/wil6210/wil_crash_dump.c (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig index ce8c0381825e..6dfedc8bd6a3 100644 --- a/drivers/net/wireless/ath/wil6210/Kconfig +++ b/drivers/net/wireless/ath/wil6210/Kconfig @@ -1,5 +1,6 @@ config WIL6210 tristate "Wilocity 60g WiFi card wil6210 support" + select WANT_DEV_COREDUMP depends on CFG80211 depends on PCI default n diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile index 64b432625fbb..fdf63d5fe82b 100644 --- a/drivers/net/wireless/ath/wil6210/Makefile +++ b/drivers/net/wireless/ath/wil6210/Makefile @@ -17,6 +17,7 @@ wil6210-y += pmc.o wil6210-$(CONFIG_WIL6210_TRACING) += trace.o wil6210-y += wil_platform.o wil6210-y += ethtool.o +wil6210-y += wil_crash_dump.o # for tracing framework to find trace.h CFLAGS_trace.o := -I$(src) diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index f651994fee5e..06fc46f85c85 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2015 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 @@ -391,6 +391,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr); if (isr & ISR_MISC_FW_ERROR) { + wil_fw_core_dump(wil); wil_notify_fw_error(wil); isr &= ~ISR_MISC_FW_ERROR; wil_fw_error_recovery(wil); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 525ce2cbec64..9a90a58cbc85 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -827,4 +827,6 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime); int wil_suspend(struct wil6210_priv *wil, bool is_runtime); int wil_resume(struct wil6210_priv *wil, bool is_runtime); +void wil_fw_core_dump(struct wil6210_priv *wil); + #endif /* __WIL6210_H__ */ diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c new file mode 100644 index 000000000000..7e70934990ae --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2015 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "wil6210.h" +#include + +static int wil_fw_get_crash_dump_bounds(struct wil6210_priv *wil, + u32 *out_dump_size, u32 *out_host_min) +{ + int i; + const struct fw_map *map; + u32 host_min, host_max, tmp_max; + + if (!out_dump_size) + return -EINVAL; + + /* calculate the total size of the unpacked crash dump */ + BUILD_BUG_ON(ARRAY_SIZE(fw_mapping) == 0); + map = &fw_mapping[0]; + host_min = map->host; + host_max = map->host + (map->to - map->from); + + for (i = 1; i < ARRAY_SIZE(fw_mapping); i++) { + map = &fw_mapping[i]; + + if (map->host < host_min) + host_min = map->host; + + tmp_max = map->host + (map->to - map->from); + if (tmp_max > host_max) + host_max = tmp_max; + } + + *out_dump_size = host_max - host_min; + if (out_host_min) + *out_host_min = host_min; + + return 0; +} + +static int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, + u32 size) +{ + int i; + const struct fw_map *map; + void *data; + 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__); + return -EINVAL; + } + + if (dump_size > size) { + wil_err(wil, "%s: not enough space for dump. Need %d have %d\n", + __func__, dump_size, size); + return -EINVAL; + } + + /* copy to crash dump area */ + for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { + map = &fw_mapping[i]; + + data = (void * __force)wil->csr + HOSTADDR(map->host); + 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_memcpy_fromio_32((void * __force)(dest + offset), + (const void __iomem * __force)data, len); + } + + return 0; +} + +void wil_fw_core_dump(struct wil6210_priv *wil) +{ + void *fw_dump_data; + 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__); + return; + } + + fw_dump_data = vzalloc(fw_dump_size); + if (!fw_dump_data) + return; + + if (wil_fw_copy_crash_dump(wil, fw_dump_data, fw_dump_size)) { + vfree(fw_dump_data); + return; + } + /* fw_dump_data will be free in device coredump release function + * 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); +} -- cgit v1.2.3 From f13e0630826f961732f3192282a6c249bb6208c1 Mon Sep 17 00:00:00 2001 From: Hamad Kadmany Date: Sun, 4 Oct 2015 10:23:27 +0300 Subject: wil6210: Do no schedule firmware recovery during reset flow During reset flow, ignore firmware errors detected prior to the actual hardware reset as the recovery flow would make additional unnecessary reset. Signed-off-by: Hamad Kadmany Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/main.c | 8 ++++++++ drivers/net/wireless/ath/wil6210/wil6210.h | 1 + 2 files changed, 9 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index de6e3c279f97..aade16b126c4 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -767,6 +767,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) if (wil->hw_version == HW_VER_UNKNOWN) return -ENODEV; + set_bit(wil_status_resetting, wil->status); + cancel_work_sync(&wil->disconnect_worker); wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); wil_bcast_fini(wil); @@ -853,6 +855,12 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) void wil_fw_error_recovery(struct wil6210_priv *wil) { wil_dbg_misc(wil, "starting fw error recovery\n"); + + if (test_bit(wil_status_resetting, wil->status)) { + wil_info(wil, "Reset already in progress\n"); + return; + } + wil->recovery_state = fw_recovery_pending; schedule_work(&wil->fw_error_worker); } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 9a90a58cbc85..f619bf234353 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -409,6 +409,7 @@ enum { /* for wil6210_priv.status */ wil_status_reset_done, wil_status_irqen, /* FIXME: interrupts enabled - for debug */ wil_status_napi_en, /* NAPI enabled protected by wil->mutex */ + wil_status_resetting, /* reset in progress */ wil_status_last /* keep last */ }; -- cgit v1.2.3 From 101d1f7fbf7dbb881f808c0fdc23124051ac5da6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 7 Sep 2015 14:49:05 +0100 Subject: ath6kl: remove redundant null pointer check on send_pkt The check for send_pkt being NULL is redundant before the call to htc_reclaim_txctrl_buf, therefore it should be removed. This was detected by static analysis by cppcheck. Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/htc_mbox.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index e481f14b9878..fffb65b3e652 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c @@ -1085,9 +1085,7 @@ static int htc_setup_tx_complete(struct htc_target *target) send_pkt->completion = NULL; ath6kl_htc_tx_prep_pkt(send_pkt, 0, 0, 0); status = ath6kl_htc_tx_issue(target, send_pkt); - - if (send_pkt != NULL) - htc_reclaim_txctrl_buf(target, send_pkt); + htc_reclaim_txctrl_buf(target, send_pkt); return status; } -- cgit v1.2.3 From 706452b06866f950febb91e582c1d06c03ca85ee Mon Sep 17 00:00:00 2001 From: Zefir Kurtisi Date: Tue, 29 Sep 2015 12:29:49 +0200 Subject: ath: fix DFS timestamp wraparound reset condition The DFS pattern detector ought to reset the detector lines when a pulse is added with lower time stamp than the previous (which indicates a TSF restart). This did not work so far and is fixed with this patch. The modification does not change detection performance within the driver, since it only ensures early reset (which is later performed by the PRI detectors anyway). It is relevant for synthetic tests and statistical evaluations, where millions of pulse patterns are processed and an early reset helps reducing load. Signed-off-by: Zefir Kurtisi Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/dfs_pattern_detector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c index 9d687121b2bf..2303ef96299d 100644 --- a/drivers/net/wireless/ath/dfs_pattern_detector.c +++ b/drivers/net/wireless/ath/dfs_pattern_detector.c @@ -284,10 +284,10 @@ dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event) if (cd == NULL) return false; - dpd->last_pulse_ts = event->ts; /* reset detector on time stamp wraparound, caused by TSF reset */ if (event->ts < dpd->last_pulse_ts) dpd_reset(dpd); + dpd->last_pulse_ts = event->ts; /* do type individual pattern matching */ for (i = 0; i < dpd->num_radar_types; i++) { -- cgit v1.2.3 From bffb7db279abe86949dabc7e63b6c2500f472a92 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Mon, 5 Oct 2015 20:46:12 +0800 Subject: ath6kl: drop unlikely behind WARN_ON() WARN_ON() already contain an unlikely compiler flag. Drop it. Signed-off-by: Geliang Tang Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index a511ef3614b9..fe38fc40de0f 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2217,7 +2217,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) /* enter / leave wow suspend on first vif always */ first_vif = ath6kl_vif_first(ar); - if (WARN_ON(unlikely(!first_vif)) || + if (WARN_ON(!first_vif) || !ath6kl_cfg80211_ready(first_vif)) return -EIO; @@ -2297,7 +2297,7 @@ static int ath6kl_wow_resume(struct ath6kl *ar) int ret; vif = ath6kl_vif_first(ar); - if (WARN_ON(unlikely(!vif)) || + if (WARN_ON(!vif) || !ath6kl_cfg80211_ready(vif)) return -EIO; -- cgit v1.2.3 From 5a7883989b1c57513bb4067ca4b42c96d449d1a5 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 8 Oct 2015 17:13:57 +0300 Subject: net/mlx5_core: Improve mlx5 messages Improve the messages printed by the mlx5 macros to include the device string. In addition, prefix names used by the macros with two underscores to avoid possible name collisions. Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 566a70488db1..30c0be721b08 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -43,25 +43,25 @@ extern int mlx5_core_debug_mask; -#define mlx5_core_dbg(dev, format, ...) \ - pr_debug("%s:%s:%d:(pid %d): " format, \ - (dev)->priv.name, __func__, __LINE__, current->pid, \ +#define mlx5_core_dbg(__dev, format, ...) \ + dev_dbg(&(__dev)->pdev->dev, "%s:%s:%d:(pid %d): " format, \ + (__dev)->priv.name, __func__, __LINE__, current->pid, \ ##__VA_ARGS__) -#define mlx5_core_dbg_mask(dev, mask, format, ...) \ +#define mlx5_core_dbg_mask(__dev, mask, format, ...) \ do { \ if ((mask) & mlx5_core_debug_mask) \ - mlx5_core_dbg(dev, format, ##__VA_ARGS__); \ + mlx5_core_dbg(__dev, format, ##__VA_ARGS__); \ } while (0) -#define mlx5_core_err(dev, format, ...) \ - pr_err("%s:%s:%d:(pid %d): " format, \ - (dev)->priv.name, __func__, __LINE__, current->pid, \ +#define mlx5_core_err(__dev, format, ...) \ + dev_err(&(__dev)->pdev->dev, "%s:%s:%d:(pid %d): " format, \ + (__dev)->priv.name, __func__, __LINE__, current->pid, \ ##__VA_ARGS__) -#define mlx5_core_warn(dev, format, ...) \ - pr_warn("%s:%s:%d:(pid %d): " format, \ - (dev)->priv.name, __func__, __LINE__, current->pid, \ +#define mlx5_core_warn(__dev, format, ...) \ + dev_warn(&(__dev)->pdev->dev, "%s:%s:%d:(pid %d): " format, \ + (__dev)->priv.name, __func__, __LINE__, current->pid, \ ##__VA_ARGS__) enum { -- cgit v1.2.3 From 020446e01eebc9dbe7eda038e570ab9c7ab13586 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 8 Oct 2015 17:13:58 +0300 Subject: net/mlx5_core: Prepare cmd interface to system errors handling In preparation to handling system errors at the mlx5_core level, change the interface of cmd_work_handler to accept a 64 bit argument for the vector. This allows to encode a flag that signifies when the handler is called as a result of a driver logic that wishes to terminate commands that the hardware may not be able to terminate. Such command completions are detected at the handler and proper return status is encoded. To be able to terminate page handler commands, we make sure to set the corresponding bit in the bitmask. Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 84838c2f528f..c3e54b7e8780 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -254,6 +254,10 @@ static void dump_buf(void *buf, int size, int data_only, int offset) pr_debug("\n"); } +enum { + MLX5_DRIVER_STATUS_ABORTED = 0xfe, +}; + const char *mlx5_command_str(int command) { switch (command) { @@ -473,6 +477,7 @@ static void cmd_work_handler(struct work_struct *work) struct mlx5_core_dev *dev = container_of(cmd, struct mlx5_core_dev, cmd); struct mlx5_cmd_layout *lay; struct semaphore *sem; + unsigned long flags; sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem; down(sem); @@ -485,6 +490,9 @@ static void cmd_work_handler(struct work_struct *work) } } else { ent->idx = cmd->max_reg_cmds; + spin_lock_irqsave(&cmd->alloc_lock, flags); + clear_bit(ent->idx, &cmd->bitmask); + spin_unlock_irqrestore(&cmd->alloc_lock, flags); } ent->token = alloc_token(cmd); @@ -1081,7 +1089,7 @@ static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg) } } -void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector) +void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec) { struct mlx5_cmd *cmd = &dev->cmd; struct mlx5_cmd_work_ent *ent; @@ -1092,7 +1100,10 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector) s64 ds; struct mlx5_cmd_stats *stats; unsigned long flags; + unsigned long vector; + /* there can be at most 32 command queues */ + vector = vec & 0xffffffff; for (i = 0; i < (1 << cmd->log_sz); i++) { if (test_bit(i, &vector)) { struct semaphore *sem; @@ -1110,11 +1121,16 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, unsigned long vector) ent->ret = verify_signature(ent); else ent->ret = 0; - ent->status = ent->lay->status_own >> 1; + if (vec & MLX5_TRIGGERED_CMD_COMP) + ent->status = MLX5_DRIVER_STATUS_ABORTED; + else + ent->status = ent->lay->status_own >> 1; + mlx5_core_dbg(dev, "command completed. ret 0x%x, delivery status %s(0x%x)\n", ent->ret, deliv_status_to_str(ent->status), ent->status); } free_ent(cmd, ent->idx); + if (ent->callback) { ds = ent->ts2 - ent->ts1; if (ent->op < ARRAY_SIZE(cmd->stats)) { -- cgit v1.2.3 From 0144a95e2ad53a40c62148f44fb0c1f9d2a0d1e9 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 8 Oct 2015 17:13:59 +0300 Subject: net/mlx5_core: Use accessor functions to read from device memory Use ioread function to read health buffer data. In addition, print the firmware version as a string for readability and also use dev_err to have the device string to be printed. Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/health.c | 35 +++++++++++++++--------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 1277c427242a..8770968fff35 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -114,32 +114,41 @@ static const char *hsynd_str(u8 synd) } } -static u16 read_be16(__be16 __iomem *p) +static u16 get_maj(u32 fw) { - return swab16(readl((__force u16 __iomem *) p)); + return fw >> 28; } -static u32 read_be32(__be32 __iomem *p) +static u16 get_min(u32 fw) { - return swab32(readl((__force u32 __iomem *) p)); + return fw >> 16 & 0xfff; +} + +static u16 get_sub(u32 fw) +{ + return fw & 0xffff; } static void print_health_info(struct mlx5_core_dev *dev) { struct mlx5_core_health *health = &dev->priv.health; struct health_buffer __iomem *h = health->health; + char fw_str[18]; + u32 fw; int i; for (i = 0; i < ARRAY_SIZE(h->assert_var); i++) - pr_info("assert_var[%d] 0x%08x\n", i, read_be32(h->assert_var + i)); - - pr_info("assert_exit_ptr 0x%08x\n", read_be32(&h->assert_exit_ptr)); - pr_info("assert_callra 0x%08x\n", read_be32(&h->assert_callra)); - pr_info("fw_ver 0x%08x\n", read_be32(&h->fw_ver)); - pr_info("hw_id 0x%08x\n", read_be32(&h->hw_id)); - pr_info("irisc_index %d\n", readb(&h->irisc_index)); - pr_info("synd 0x%x: %s\n", readb(&h->synd), hsynd_str(readb(&h->synd))); - pr_info("ext_sync 0x%04x\n", read_be16(&h->ext_synd)); + dev_err(&dev->pdev->dev, "assert_var[%d] 0x%08x\n", i, ioread32be(h->assert_var + i)); + + dev_err(&dev->pdev->dev, "assert_exit_ptr 0x%08x\n", ioread32be(&h->assert_exit_ptr)); + dev_err(&dev->pdev->dev, "assert_callra 0x%08x\n", ioread32be(&h->assert_callra)); + fw = ioread32be(&h->fw_ver); + sprintf(fw_str, "%d.%d.%d", get_maj(fw), get_min(fw), get_sub(fw)); + dev_err(&dev->pdev->dev, "fw_ver %s\n", fw_str); + dev_err(&dev->pdev->dev, "hw_id 0x%08x\n", ioread32be(&h->hw_id)); + dev_err(&dev->pdev->dev, "irisc_index %d\n", ioread8(&h->irisc_index)); + dev_err(&dev->pdev->dev, "synd 0x%x: %s\n", ioread8(&h->synd), hsynd_str(ioread8(&h->synd))); + dev_err(&dev->pdev->dev, "ext_synd 0x%04x\n", ioread16be(&h->ext_synd)); } static void poll_health(unsigned long data) -- cgit v1.2.3 From ac6ea6e81a80172612e0c9ef93720f371b198918 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 8 Oct 2015 17:14:00 +0300 Subject: net/mlx5_core: Use private health thread for each device Use a single threaded work queue for each device in the system instead of using one thread for any device. This is required so we can concurrently process system error handling for all the devices that need that. Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/health.c | 63 +++++++++++------------- drivers/net/ethernet/mellanox/mlx5/core/main.c | 37 +++++++------- 2 files changed, 48 insertions(+), 52 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 8770968fff35..9b81e1ceb8de 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -57,31 +57,16 @@ enum { MLX5_HEALTH_SYNDR_HIGH_TEMP = 0x10 }; -static DEFINE_SPINLOCK(health_lock); -static LIST_HEAD(health_list); -static struct work_struct health_work; - static void health_care(struct work_struct *work) { - struct mlx5_core_health *health, *n; + struct mlx5_core_health *health; struct mlx5_core_dev *dev; struct mlx5_priv *priv; - LIST_HEAD(tlist); - - spin_lock_irq(&health_lock); - list_splice_init(&health_list, &tlist); - - spin_unlock_irq(&health_lock); - list_for_each_entry_safe(health, n, &tlist, list) { - priv = container_of(health, struct mlx5_priv, health); - dev = container_of(priv, struct mlx5_core_dev, priv); - mlx5_core_warn(dev, "handling bad device here\n"); - /* nothing yet */ - spin_lock_irq(&health_lock); - list_del_init(&health->list); - spin_unlock_irq(&health_lock); - } + health = container_of(work, struct mlx5_core_health, work); + priv = container_of(health, struct mlx5_priv, health); + dev = container_of(priv, struct mlx5_core_dev, priv); + mlx5_core_warn(dev, "handling bad device here\n"); } static const char *hsynd_str(u8 synd) @@ -168,11 +153,7 @@ static void poll_health(unsigned long data) if (health->miss_counter == MAX_MISSES) { mlx5_core_err(dev, "device's health compromised\n"); print_health_info(dev); - spin_lock_irq(&health_lock); - list_add_tail(&health->list, &health_list); - spin_unlock_irq(&health_lock); - - queue_work(mlx5_core_wq, &health_work); + queue_work(health->wq, &health->work); } else { get_random_bytes(&next, sizeof(next)); next %= HZ; @@ -185,7 +166,6 @@ void mlx5_start_health_poll(struct mlx5_core_dev *dev) { struct mlx5_core_health *health = &dev->priv.health; - INIT_LIST_HEAD(&health->list); init_timer(&health->timer); health->health = &dev->iseg->health; health->health_counter = &dev->iseg->health_counter; @@ -201,18 +181,33 @@ void mlx5_stop_health_poll(struct mlx5_core_dev *dev) struct mlx5_core_health *health = &dev->priv.health; del_timer_sync(&health->timer); - - spin_lock_irq(&health_lock); - if (!list_empty(&health->list)) - list_del_init(&health->list); - spin_unlock_irq(&health_lock); } -void mlx5_health_cleanup(void) +void mlx5_health_cleanup(struct mlx5_core_dev *dev) { + struct mlx5_core_health *health = &dev->priv.health; + + destroy_workqueue(health->wq); } -void __init mlx5_health_init(void) +int mlx5_health_init(struct mlx5_core_dev *dev) { - INIT_WORK(&health_work, health_care); + struct mlx5_core_health *health; + char *name; + + health = &dev->priv.health; + name = kmalloc(64, GFP_KERNEL); + if (!name) + return -ENOMEM; + + strcpy(name, "mlx5_health"); + strcat(name, dev_name(&dev->pdev->dev)); + health->wq = create_singlethread_workqueue(name); + kfree(name); + if (!health->wq) + return -ENOMEM; + + INIT_WORK(&health->work, health_care); + + return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 7718f6ac6214..b6edc58766ad 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -62,7 +62,6 @@ static int prof_sel = MLX5_DEFAULT_PROF; module_param_named(prof_sel, prof_sel, int, 0444); MODULE_PARM_DESC(prof_sel, "profile selector. Valid range 0 - 2"); -struct workqueue_struct *mlx5_core_wq; static LIST_HEAD(intf_list); static LIST_HEAD(dev_list); static DEFINE_MUTEX(intf_mutex); @@ -1046,6 +1045,7 @@ err_pagealloc_cleanup: static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) { + int err; mlx5_unregister_device(dev); mlx5_cleanup_mr_table(dev); @@ -1060,9 +1060,10 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) mlx5_eq_cleanup(dev); mlx5_disable_msix(dev); mlx5_stop_health_poll(dev); - if (mlx5_cmd_teardown_hca(dev)) { + err = mlx5_cmd_teardown_hca(dev); + if (err) { dev_err(&dev->pdev->dev, "tear_down_hca failed, skip cleanup\n"); - return 1; + goto out; } mlx5_pagealloc_stop(dev); mlx5_reclaim_startup_pages(dev); @@ -1070,11 +1071,12 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) mlx5_pagealloc_cleanup(dev); mlx5_cmd_cleanup(dev); - return 0; +out: + return err; } static void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event, - unsigned long param) + unsigned long param) { struct mlx5_priv *priv = &dev->priv; struct mlx5_device_context *dev_ctx; @@ -1129,14 +1131,22 @@ static int init_one(struct pci_dev *pdev, goto clean_dev; } + err = mlx5_health_init(dev); + if (err) { + dev_err(&pdev->dev, "mlx5_health_init failed with error code %d\n", err); + goto close_pci; + } + err = mlx5_load_one(dev, priv); if (err) { dev_err(&pdev->dev, "mlx5_load_one failed with error code %d\n", err); - goto close_pci; + goto clean_health; } return 0; +clean_health: + mlx5_health_cleanup(dev); close_pci: mlx5_pci_close(dev, priv); clean_dev: @@ -1153,8 +1163,10 @@ static void remove_one(struct pci_dev *pdev) if (mlx5_unload_one(dev, priv)) { dev_err(&dev->pdev->dev, "mlx5_unload_one failed\n"); + mlx5_health_cleanup(dev); return; } + mlx5_health_cleanup(dev); mlx5_pci_close(dev, priv); pci_set_drvdata(pdev, NULL); kfree(dev); @@ -1184,16 +1196,10 @@ static int __init init(void) int err; mlx5_register_debugfs(); - mlx5_core_wq = create_singlethread_workqueue("mlx5_core_wq"); - if (!mlx5_core_wq) { - err = -ENOMEM; - goto err_debug; - } - mlx5_health_init(); err = pci_register_driver(&mlx5_core_driver); if (err) - goto err_health; + goto err_debug; #ifdef CONFIG_MLX5_CORE_EN mlx5e_init(); @@ -1201,9 +1207,6 @@ static int __init init(void) return 0; -err_health: - mlx5_health_cleanup(); - destroy_workqueue(mlx5_core_wq); err_debug: mlx5_unregister_debugfs(); return err; @@ -1215,8 +1218,6 @@ static void __exit cleanup(void) mlx5e_cleanup(); #endif pci_unregister_driver(&mlx5_core_driver); - mlx5_health_cleanup(); - destroy_workqueue(mlx5_core_wq); mlx5_unregister_debugfs(); } -- cgit v1.2.3 From ba4b87aedd7123df4e4cfd1ca4dcfe8a6d756511 Mon Sep 17 00:00:00 2001 From: Ido Shamay Date: Thu, 8 Oct 2015 17:14:01 +0300 Subject: net/mlx4_en: Add steering rules after RSS creation Changed the receive control flow in a way that steering rules are added only when the RSS object is already in RTR/RTS mode. Some optimization features, which are enabled by the device firmware, require this condition in order to be effective. Signed-off-by: Ido Shamay Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 144 ++++++++++++++----------- 1 file changed, 80 insertions(+), 64 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 4726122ea76b..597d8923c8e1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -573,10 +573,8 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv) { struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_dev *dev = mdev->dev; - struct mlx4_mac_entry *entry; int index = 0; int err = 0; - u64 reg_id = 0; int *qpn = &priv->base_qpn; u64 mac = mlx4_mac_to_u64(priv->dev->dev_addr); @@ -600,44 +598,11 @@ static int mlx4_en_get_qp(struct mlx4_en_priv *priv) en_dbg(DRV, priv, "Reserved qp %d\n", *qpn); if (err) { en_err(priv, "Failed to reserve qp for mac registration\n"); - goto qp_err; - } - - err = mlx4_en_uc_steer_add(priv, priv->dev->dev_addr, qpn, ®_id); - if (err) - goto steer_err; - - err = mlx4_en_tunnel_steer_add(priv, priv->dev->dev_addr, *qpn, - &priv->tunnel_reg_id); - if (err) - goto tunnel_err; - - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { - err = -ENOMEM; - goto alloc_err; + mlx4_unregister_mac(dev, priv->port, mac); + return err; } - memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac)); - memcpy(priv->current_mac, entry->mac, sizeof(priv->current_mac)); - entry->reg_id = reg_id; - - hlist_add_head_rcu(&entry->hlist, - &priv->mac_hash[entry->mac[MLX4_EN_MAC_HASH_IDX]]); return 0; - -alloc_err: - if (priv->tunnel_reg_id) - mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id); -tunnel_err: - mlx4_en_uc_steer_release(priv, priv->dev->dev_addr, *qpn, reg_id); - -steer_err: - mlx4_qp_release_range(dev, *qpn, 1); - -qp_err: - mlx4_unregister_mac(dev, priv->port, mac); - return err; } static void mlx4_en_put_qp(struct mlx4_en_priv *priv) @@ -645,39 +610,13 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv) struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_dev *dev = mdev->dev; int qpn = priv->base_qpn; - u64 mac; if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) { - mac = mlx4_mac_to_u64(priv->dev->dev_addr); + u64 mac = mlx4_mac_to_u64(priv->dev->dev_addr); en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n", priv->dev->dev_addr); mlx4_unregister_mac(dev, priv->port, mac); } else { - struct mlx4_mac_entry *entry; - struct hlist_node *tmp; - struct hlist_head *bucket; - unsigned int i; - - for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) { - bucket = &priv->mac_hash[i]; - hlist_for_each_entry_safe(entry, tmp, bucket, hlist) { - mac = mlx4_mac_to_u64(entry->mac); - en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n", - entry->mac); - mlx4_en_uc_steer_release(priv, entry->mac, - qpn, entry->reg_id); - - mlx4_unregister_mac(dev, priv->port, mac); - hlist_del_rcu(&entry->hlist); - kfree_rcu(entry, rcu); - } - } - - if (priv->tunnel_reg_id) { - mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id); - priv->tunnel_reg_id = 0; - } - en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n", priv->port, qpn); mlx4_qp_release_range(dev, qpn, 1); @@ -1283,6 +1222,75 @@ static void mlx4_en_netpoll(struct net_device *dev) } #endif +static int mlx4_en_set_rss_steer_rules(struct mlx4_en_priv *priv) +{ + u64 reg_id; + int err = 0; + int *qpn = &priv->base_qpn; + struct mlx4_mac_entry *entry; + + err = mlx4_en_uc_steer_add(priv, priv->dev->dev_addr, qpn, ®_id); + if (err) + return err; + + err = mlx4_en_tunnel_steer_add(priv, priv->dev->dev_addr, *qpn, + &priv->tunnel_reg_id); + if (err) + goto tunnel_err; + + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) { + err = -ENOMEM; + goto alloc_err; + } + + memcpy(entry->mac, priv->dev->dev_addr, sizeof(entry->mac)); + memcpy(priv->current_mac, entry->mac, sizeof(priv->current_mac)); + entry->reg_id = reg_id; + hlist_add_head_rcu(&entry->hlist, + &priv->mac_hash[entry->mac[MLX4_EN_MAC_HASH_IDX]]); + + return 0; + +alloc_err: + if (priv->tunnel_reg_id) + mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id); + +tunnel_err: + mlx4_en_uc_steer_release(priv, priv->dev->dev_addr, *qpn, reg_id); + return err; +} + +static void mlx4_en_delete_rss_steer_rules(struct mlx4_en_priv *priv) +{ + u64 mac; + unsigned int i; + int qpn = priv->base_qpn; + struct hlist_head *bucket; + struct hlist_node *tmp; + struct mlx4_mac_entry *entry; + + for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) { + bucket = &priv->mac_hash[i]; + hlist_for_each_entry_safe(entry, tmp, bucket, hlist) { + mac = mlx4_mac_to_u64(entry->mac); + en_dbg(DRV, priv, "Registering MAC:%pM for deleting\n", + entry->mac); + mlx4_en_uc_steer_release(priv, entry->mac, + qpn, entry->reg_id); + + mlx4_unregister_mac(priv->mdev->dev, priv->port, mac); + hlist_del_rcu(&entry->hlist); + kfree_rcu(entry, rcu); + } + } + + if (priv->tunnel_reg_id) { + mlx4_flow_detach(priv->mdev->dev, priv->tunnel_reg_id); + priv->tunnel_reg_id = 0; + } +} + static void mlx4_en_tx_timeout(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); @@ -1684,6 +1692,11 @@ int mlx4_en_start_port(struct net_device *dev) goto tx_err; } + /* Set Unicast and VXLAN steering rules */ + if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0 && + mlx4_en_set_rss_steer_rules(priv)) + mlx4_warn(mdev, "Failed setting steering rules\n"); + /* Attach rx QP to bradcast address */ eth_broadcast_addr(&mc_list[10]); mc_list[5] = priv->port; /* needed for B0 steering support */ @@ -1831,6 +1844,9 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) for (i = 0; i < priv->tx_ring_num; i++) mlx4_en_free_tx_buf(dev, priv->tx_ring[i]); + if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0) + mlx4_en_delete_rss_steer_rules(priv); + /* Free RSS qps */ mlx4_en_release_rss_steer(priv); -- cgit v1.2.3 From a5b3c56ef792009f6aff54ba93bd86ceca3e5bfc Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Thu, 8 Oct 2015 17:14:02 +0300 Subject: net/mlx4_core: Fix mailbox leak in error flow when performing update qp The procedure mlx4_update_qp leaks mailboxes in its error-flow, fix that. Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/qp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index 20268634a9ab..3311f35d08e0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -422,15 +422,15 @@ int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn, u64 qp_mask = 0; int err = 0; + if (!attr || (attr & ~MLX4_UPDATE_QP_SUPPORTED_ATTRS)) + return -EINVAL; + mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) return PTR_ERR(mailbox); cmd = (struct mlx4_update_qp_context *)mailbox->buf; - if (!attr || (attr & ~MLX4_UPDATE_QP_SUPPORTED_ATTRS)) - return -EINVAL; - if (attr & MLX4_UPDATE_QP_SMAC) { pri_addr_path_mask |= 1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX; cmd->qp_context.pri_path.grh_mylmc = params->smac_index; -- cgit v1.2.3 From 95e196337a3bd1a1678e794064d8097600c277de Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Thu, 8 Oct 2015 17:14:03 +0300 Subject: net/mlx4_core: Fix resource tracker error flow in add_res_range The 'for' loop when undoing rb-tree insertions and list-adds in the error flow in add_res_range had errors, fix them. Signed-off-by: Saeed Mahameed Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 731423ca575d..ac4b99ab1f85 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -1238,8 +1238,10 @@ static int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count, return 0; undo: - for (--i; i >= base; --i) + for (--i; i >= 0; --i) { rb_erase(&res_arr[i]->node, root); + list_del_init(&res_arr[i]->list); + } spin_unlock_irq(mlx4_tlock(dev)); -- cgit v1.2.3 From 820d39f3c497df6c8e040b8dcc7c19eeaa312701 Mon Sep 17 00:00:00 2001 From: Carol L Soto Date: Thu, 8 Oct 2015 15:26:15 +0300 Subject: net/mlx4_core: Avoid failing the interrupts test Test interrupts fails if not all completion vectors called request_irq. This case happens if only mlx4_en is loaded and we have more completion vectors than rx rings. Fixes: c66fa19c405a ('net/mlx4: Add EQ pool') Signed-off-by: Carol L Soto Acked-by: Matan Barak Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/eq.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 8e81e53c370e..c34488479365 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -1364,6 +1364,10 @@ int mlx4_test_interrupts(struct mlx4_dev *dev) * and performing a NOP command */ for(i = 0; !err && (i < dev->caps.num_comp_vectors); ++i) { + /* Make sure request_irq was called */ + if (!priv->eq_table.eq[i].have_irq) + continue; + /* Temporary use polling for command completions */ mlx4_cmd_use_polling(dev); -- cgit v1.2.3 From 13b7938883ea6e70e7e23f30dece6f79d7a2961d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 8 Oct 2015 15:26:17 +0300 Subject: net/mlx5: Fix typo in mlx5_query_port_pvlc We used the wrong register name for querying the PVLC register Fixes: a124d13ef59e ('net/mlx5_core: Add more query port helpers') Signed-off-by: Jiri Pirko Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index 821caaab9bfb..3b9480fa3403 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -311,7 +311,7 @@ static int mlx5_query_port_pvlc(struct mlx5_core_dev *dev, u32 *pvlc, int err; memset(in, 0, sizeof(in)); - MLX5_SET(ptys_reg, in, local_port, local_port); + MLX5_SET(pvlc_reg, in, local_port, local_port); err = mlx5_core_access_reg(dev, in, sizeof(in), pvlc, pvlc_size, MLX5_REG_PVLC, 0, 0); -- cgit v1.2.3 From c07543431e9f3d126d083808efa0e76461d8833b Mon Sep 17 00:00:00 2001 From: Achiad Shochat Date: Thu, 8 Oct 2015 15:26:18 +0300 Subject: net/mlx5e: Disable VLAN filter in promiscuous mode When the device was set to promiscuous mode, we didn't disable VLAN filtering, which is wrong behaviour, fix that. Now when the device is set to promiscuous mode RX packets sent over any VLAN (or no VLAN tag at all) will be accepted. Signed-off-by: Achiad Shochat Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c b/drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c index e71563ce05d1..22d603f78273 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c @@ -598,6 +598,8 @@ void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv) return; priv->vlan.filter_disabled = false; + if (priv->netdev->flags & IFF_PROMISC) + return; mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0); } @@ -607,6 +609,8 @@ void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv) return; priv->vlan.filter_disabled = true; + if (priv->netdev->flags & IFF_PROMISC) + return; mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0); } @@ -717,8 +721,12 @@ void mlx5e_set_rx_mode_work(struct work_struct *work) bool enable_broadcast = !ea->broadcast_enabled && broadcast_enabled; bool disable_broadcast = ea->broadcast_enabled && !broadcast_enabled; - if (enable_promisc) + if (enable_promisc) { mlx5e_add_eth_addr_rule(priv, &ea->promisc, MLX5E_PROMISC); + if (!priv->vlan.filter_disabled) + mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, + 0); + } if (enable_allmulti) mlx5e_add_eth_addr_rule(priv, &ea->allmulti, MLX5E_ALLMULTI); if (enable_broadcast) @@ -730,8 +738,12 @@ void mlx5e_set_rx_mode_work(struct work_struct *work) mlx5e_del_eth_addr_from_flow_table(priv, &ea->broadcast); if (disable_allmulti) mlx5e_del_eth_addr_from_flow_table(priv, &ea->allmulti); - if (disable_promisc) + if (disable_promisc) { + if (!priv->vlan.filter_disabled) + mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, + 0); mlx5e_del_eth_addr_from_flow_table(priv, &ea->promisc); + } ea->promisc_enabled = promisc_enabled; ea->allmulti_enabled = allmulti_enabled; -- cgit v1.2.3 From b3c8ec35a93d61fde15eefde2d54ecf2f5950f68 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 7 Oct 2015 17:27:46 -0400 Subject: drivers/net/ethernet: make ti/cpsw-phy-sel.c explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/net/ethernet/ti/Kconfig:config TI_CPSW_PHY_SEL drivers/net/ethernet/ti/Kconfig: bool "TI CPSW Switch Phy sel Support" ...meaning that it currently is not being built as a module by anyone. Lets remove the couple traces of modularity so that when reading the driver there is no doubt it is builtin-only. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE tag etc. since all that information was (or is now) contained at the top of the file in the comments. Cc: "David S. Miller" Cc: Varka Bhadram Cc: netdev@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw-phy-sel.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/cpsw-phy-sel.c b/drivers/net/ethernet/ti/cpsw-phy-sel.c index 0ea78326cc21..e9cc61e1ec74 100644 --- a/drivers/net/ethernet/ti/cpsw-phy-sel.c +++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c @@ -2,6 +2,8 @@ * * Copyright (C) 2013 Texas Instruments * + * Module Author: Mugunthan V N + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. @@ -13,7 +15,7 @@ */ #include -#include +#include #include #include #include @@ -173,7 +175,6 @@ static const struct of_device_id cpsw_phy_sel_id_table[] = { }, {} }; -MODULE_DEVICE_TABLE(of, cpsw_phy_sel_id_table); static int cpsw_phy_sel_probe(struct platform_device *pdev) { @@ -214,7 +215,4 @@ static struct platform_driver cpsw_phy_sel_driver = { .of_match_table = cpsw_phy_sel_id_table, }, }; - -module_platform_driver(cpsw_phy_sel_driver); -MODULE_AUTHOR("Mugunthan V N "); -MODULE_LICENSE("GPL v2"); +builtin_platform_driver(cpsw_phy_sel_driver); -- cgit v1.2.3 From 21d11bd6f0f15c9c782d1f09557bb71f582a3f53 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Thu, 8 Oct 2015 10:08:23 +0530 Subject: cxgb4: Enhance driver to update FW, when FW is too old t4_check_fw_version() can return several error codes (-EINVAL, -EBUSY, -EAGAIN). The present code sets the adapter state to UNINIT only if its an EFAULT. In all the error cases set the adapter to uninitialized state. In t4_check_fw_version() if call to t4_get_fw_version() fails, repeat the operation a few times before returning failure. Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 2 +- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 9f1f5b2aacf7..c29227ee9ee8 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -3698,7 +3698,7 @@ static int adap_init0(struct adapter *adap) t4_get_tp_version(adap, &adap->params.tp_vers); ret = t4_check_fw_version(adap); /* If firmware is too old (not supported by driver) force an update. */ - if (ret == -EFAULT) + if (ret) state = DEV_STATE_UNINIT; if ((adap->flags & MASTER_PF) && state != DEV_STATE_INIT) { struct fw_info *fw_info; diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index dc6ce31a8320..cf61a5869c6e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -2981,11 +2981,15 @@ int t4_get_exprom_version(struct adapter *adap, u32 *vers) */ int t4_check_fw_version(struct adapter *adap) { - int ret, major, minor, micro; + int i, ret, major, minor, micro; int exp_major, exp_minor, exp_micro; unsigned int chip_version = CHELSIO_CHIP_VERSION(adap->params.chip); ret = t4_get_fw_version(adap, &adap->params.fw_vers); + /* Try multiple times before returning error */ + for (i = 0; (ret == -EBUSY || ret == -EAGAIN) && i < 3; i++) + ret = t4_get_fw_version(adap, &adap->params.fw_vers); + if (ret) return ret; -- cgit v1.2.3 From 8fae307c8fe9789ff1f4161dcb2db0d689069448 Mon Sep 17 00:00:00 2001 From: wangweidong Date: Thu, 8 Oct 2015 18:03:47 +0800 Subject: BNX2: fix a Null Pointer for stats_blk we have two processes to do: P1#: ifconfig eth0 down; which will call bnx2_close, then will , and set Null to stats_blk P2#: ifconfig eth0; which will call bnx2_get_stats64, it will use stats_blk. In one case: --P1#-- --P2#-- stats_blk(no null) bnx2_free_mem ->bp->stats_blk = NULL GET_64BIT_NET_STATS then it will cause 'NULL Pointer' Problem. it is as well with 'ethtool -S ethx'. Allocate the statistics block at probe time so that this problem is impossible Signed-off-by: Wang Weidong Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2.c | 79 ++++++++++++++++++++++++------------ drivers/net/ethernet/broadcom/bnx2.h | 1 + 2 files changed, 53 insertions(+), 27 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 2b66ef3d8217..62590641897d 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -812,6 +812,46 @@ bnx2_alloc_rx_mem(struct bnx2 *bp) return 0; } +static void +bnx2_free_stats_blk(struct net_device *dev) +{ + struct bnx2 *bp = netdev_priv(dev); + + if (bp->status_blk) { + dma_free_coherent(&bp->pdev->dev, bp->status_stats_size, + bp->status_blk, + bp->status_blk_mapping); + bp->status_blk = NULL; + bp->stats_blk = NULL; + } +} + +static int +bnx2_alloc_stats_blk(struct net_device *dev) +{ + int status_blk_size; + void *status_blk; + struct bnx2 *bp = netdev_priv(dev); + + /* Combine status and statistics blocks into one allocation. */ + status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block)); + if (bp->flags & BNX2_FLAG_MSIX_CAP) + status_blk_size = L1_CACHE_ALIGN(BNX2_MAX_MSIX_HW_VEC * + BNX2_SBLK_MSIX_ALIGN_SIZE); + bp->status_stats_size = status_blk_size + + sizeof(struct statistics_block); + status_blk = dma_zalloc_coherent(&bp->pdev->dev, bp->status_stats_size, + &bp->status_blk_mapping, GFP_KERNEL); + if (status_blk == NULL) + return -ENOMEM; + + bp->status_blk = status_blk; + bp->stats_blk = status_blk + status_blk_size; + bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size; + + return 0; +} + static void bnx2_free_mem(struct bnx2 *bp) { @@ -829,37 +869,19 @@ bnx2_free_mem(struct bnx2 *bp) bp->ctx_blk[i] = NULL; } } - if (bnapi->status_blk.msi) { - dma_free_coherent(&bp->pdev->dev, bp->status_stats_size, - bnapi->status_blk.msi, - bp->status_blk_mapping); + + if (bnapi->status_blk.msi) bnapi->status_blk.msi = NULL; - bp->stats_blk = NULL; - } } static int bnx2_alloc_mem(struct bnx2 *bp) { - int i, status_blk_size, err; + int i, err; struct bnx2_napi *bnapi; - void *status_blk; - - /* Combine status and statistics blocks into one allocation. */ - status_blk_size = L1_CACHE_ALIGN(sizeof(struct status_block)); - if (bp->flags & BNX2_FLAG_MSIX_CAP) - status_blk_size = L1_CACHE_ALIGN(BNX2_MAX_MSIX_HW_VEC * - BNX2_SBLK_MSIX_ALIGN_SIZE); - bp->status_stats_size = status_blk_size + - sizeof(struct statistics_block); - - status_blk = dma_zalloc_coherent(&bp->pdev->dev, bp->status_stats_size, - &bp->status_blk_mapping, GFP_KERNEL); - if (status_blk == NULL) - goto alloc_mem_err; bnapi = &bp->bnx2_napi[0]; - bnapi->status_blk.msi = status_blk; + bnapi->status_blk.msi = bp->status_blk; bnapi->hw_tx_cons_ptr = &bnapi->status_blk.msi->status_tx_quick_consumer_index0; bnapi->hw_rx_cons_ptr = @@ -870,7 +892,7 @@ bnx2_alloc_mem(struct bnx2 *bp) bnapi = &bp->bnx2_napi[i]; - sblk = (status_blk + BNX2_SBLK_MSIX_ALIGN_SIZE * i); + sblk = (bp->status_blk + BNX2_SBLK_MSIX_ALIGN_SIZE * i); bnapi->status_blk.msix = sblk; bnapi->hw_tx_cons_ptr = &sblk->status_tx_quick_consumer_index; @@ -880,10 +902,6 @@ bnx2_alloc_mem(struct bnx2 *bp) } } - bp->stats_blk = status_blk + status_blk_size; - - bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size; - if (BNX2_CHIP(bp) == BNX2_CHIP_5709) { bp->ctx_pages = 0x2000 / BNX2_PAGE_SIZE; if (bp->ctx_pages == 0) @@ -8330,6 +8348,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->phy_addr = 1; + /* allocate stats_blk */ + rc = bnx2_alloc_stats_blk(dev); + if (rc) + goto err_out_unmap; + /* Disable WOL support if we are running on a SERDES chip. */ if (BNX2_CHIP(bp) == BNX2_CHIP_5709) bnx2_get_5709_media(bp); @@ -8586,6 +8609,7 @@ error: pci_release_regions(pdev); pci_disable_device(pdev); err_free: + bnx2_free_stats_blk(dev); free_netdev(dev); return rc; } @@ -8603,6 +8627,7 @@ bnx2_remove_one(struct pci_dev *pdev) pci_iounmap(bp->pdev, bp->regview); + bnx2_free_stats_blk(dev); kfree(bp->temp_stats_blk); if (bp->flags & BNX2_FLAG_AER_ENABLED) { diff --git a/drivers/net/ethernet/broadcom/bnx2.h b/drivers/net/ethernet/broadcom/bnx2.h index f92f76c44756..380234d72b95 100644 --- a/drivers/net/ethernet/broadcom/bnx2.h +++ b/drivers/net/ethernet/broadcom/bnx2.h @@ -6928,6 +6928,7 @@ struct bnx2 { dma_addr_t status_blk_mapping; + void *status_blk; struct statistics_block *stats_blk; struct statistics_block *temp_stats_blk; dma_addr_t stats_blk_mapping; -- cgit v1.2.3 From 4b0c2541cbf223abd38b235146e30a3d207d3bfe Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Thu, 8 Oct 2015 15:17:37 +0200 Subject: mlxsw: switchx2: changing order of exit fallbacks Fixes: 31557f0f9755 ("mlxsw: Introduce Mellanox SwitchX-2 ASIC support") Signed-off-by: Elad Raz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 3e52ee93438c..62cbbd1ada8d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1069,9 +1069,9 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port) return 0; err_register_netdev: -err_port_admin_status_set: err_port_mac_learning_mode_set: err_port_stp_state_set: +err_port_admin_status_set: err_port_mtu_set: err_port_speed_set: err_port_swid_set: -- cgit v1.2.3 From bee1f753bfcb19660d8ad713b9dd3939630854b6 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Thu, 8 Oct 2015 15:17:38 +0200 Subject: mlxsw: Fix bug in __mlxsw_item_bit_array_offset When calculating the shift needed in order to access a bit array element in a byte, we should multiply the index by the element size and not assume it is fixed at 2-bits. Fixes: 93c1edb27f9e ("mlxsw: Introduce Mellanox switch driver core") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/item.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/item.h b/drivers/net/ethernet/mellanox/mlxsw/item.h index ffd55d030ce2..36fb1cec53c9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/item.h +++ b/drivers/net/ethernet/mellanox/mlxsw/item.h @@ -187,6 +187,7 @@ __mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift) { u16 max_index, be_index; u16 offset; /* byte offset inside the array */ + u8 in_byte_index; BUG_ON(index && !item->element_size); if (item->offset % sizeof(u32) != 0 || @@ -199,7 +200,8 @@ __mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift) max_index = (item->size.bytes << 3) / item->element_size - 1; be_index = max_index - index; offset = be_index * item->element_size >> 3; - *shift = index % (BITS_PER_BYTE / item->element_size) << 1; + in_byte_index = index % (BITS_PER_BYTE / item->element_size); + *shift = in_byte_index * item->element_size; return item->offset + offset; } -- cgit v1.2.3 From f9468e8dc87e31f807fae04aae70380a461b95c6 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Thu, 8 Oct 2015 16:19:01 +0300 Subject: bnx2x: Prevent UDP 4-tuple configurations on older adapters Configuring 4-tuple RSS hsahing for UDP [E.g., by using `ethtool -N rx-flow-hash udp4 sdfn'] on a 57710/57711 adapter would cause it to assert as HW does not support such a configuration. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index aeb7ce64452e..be628bd9fb18 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -3351,6 +3351,13 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info) udp_rss_requested = 0; else return -EINVAL; + + if (CHIP_IS_E1x(bp) && udp_rss_requested) { + DP(BNX2X_MSG_ETHTOOL, + "57710, 57711 boards don't support RSS according to UDP 4-tuple\n"); + return -EINVAL; + } + if ((info->flow_type == UDP_V4_FLOW) && (bp->rss_conf_obj.udp_rss_v4 != udp_rss_requested)) { bp->rss_conf_obj.udp_rss_v4 = udp_rss_requested; -- cgit v1.2.3 From 6e86ac120e144154d345ebb5839d50b6f713149b Mon Sep 17 00:00:00 2001 From: Jon Ringle Date: Thu, 8 Oct 2015 11:10:19 -0400 Subject: net: encx24j600: Fix typos in Kconfig Signed-off-by: Jon Ringle Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig index 992b01462a8f..36a09d94b368 100644 --- a/drivers/net/ethernet/microchip/Kconfig +++ b/drivers/net/ethernet/microchip/Kconfig @@ -37,9 +37,9 @@ config ENCX24J600 tristate "ENCX24J600 support" depends on SPI ---help--- - Support for the Microchip ENC424J600 ethernet chip. + Support for the Microchip ENC424J600/624J600 ethernet chip. To compile this driver as a module, choose M here. The module will be - called enc424j600. + called encx24j600. endif # NET_VENDOR_MICROCHIP -- cgit v1.2.3 From 146a32067b3fde1424d737d7fb333eb0951e6419 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 8 Oct 2015 11:35:12 -0400 Subject: net: dsa: add port_fdb_prepare Push the prepare phase for FDB operations down to the DSA drivers, with a new port_fdb_prepare function. Currently only mv88e6xxx is affected. Signed-off-by: Vivien Didelot Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6171.c | 1 + drivers/net/dsa/mv88e6352.c | 1 + drivers/net/dsa/mv88e6xxx.c | 10 ++++++++++ drivers/net/dsa/mv88e6xxx.h | 3 +++ 4 files changed, 15 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index c95cfab56a4f..ca3330aec740 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -121,6 +121,7 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .port_vlan_add = mv88e6xxx_port_vlan_add, .port_vlan_del = mv88e6xxx_port_vlan_del, .vlan_getnext = mv88e6xxx_vlan_getnext, + .port_fdb_prepare = mv88e6xxx_port_fdb_prepare, .port_fdb_add = mv88e6xxx_port_fdb_add, .port_fdb_del = mv88e6xxx_port_fdb_del, .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 37367060676f..078a358c1b83 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -348,6 +348,7 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .port_vlan_add = mv88e6xxx_port_vlan_add, .port_vlan_del = mv88e6xxx_port_vlan_del, .vlan_getnext = mv88e6xxx_vlan_getnext, + .port_fdb_prepare = mv88e6xxx_port_fdb_prepare, .port_fdb_add = mv88e6xxx_port_fdb_add, .port_fdb_del = mv88e6xxx_port_fdb_del, .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 8e088e355834..0da865171798 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1841,6 +1841,16 @@ static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port, return _mv88e6xxx_atu_load(ds, &entry); } +int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_fdb *fdb, + struct switchdev_trans *trans) +{ + /* We don't need any dynamic resource from the kernel (yet), + * so skip the prepare phase. + */ + return 0; +} + int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid) { diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index d8ec48710b80..304286924642 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -474,6 +474,9 @@ int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid, int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid); int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid, unsigned long *ports, unsigned long *untagged); +int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_fdb *fdb, + struct switchdev_trans *trans); int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid); int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, -- cgit v1.2.3 From 1f36faf26943f5f5fc1d1a7be6ce252d2ff25e1a Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 8 Oct 2015 11:35:13 -0400 Subject: net: dsa: push prepare phase in port_fdb_add Now that the prepare phase is pushed down to the DSA drivers, propagate it to the port_fdb_add function. Signed-off-by: Vivien Didelot Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 8 +++++--- drivers/net/dsa/mv88e6xxx.h | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 0da865171798..644fffc6b98b 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "mv88e6xxx.h" /* MDIO bus access can be nested in the case of PHYs connected to the @@ -1852,16 +1853,17 @@ int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port, } int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, - const unsigned char *addr, u16 vid) + const struct switchdev_obj_port_fdb *fdb, + struct switchdev_trans *trans) { - int state = is_multicast_ether_addr(addr) ? + int state = is_multicast_ether_addr(fdb->addr) ? GLOBAL_ATU_DATA_STATE_MC_STATIC : GLOBAL_ATU_DATA_STATE_UC_STATIC; struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_port_fdb_load(ds, port, addr, vid, state); + ret = _mv88e6xxx_port_fdb_load(ds, port, fdb->addr, fdb->vid, state); mutex_unlock(&ps->smi_mutex); return ret; diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 304286924642..86a94dc0d86e 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -478,7 +478,8 @@ int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port, const struct switchdev_obj_port_fdb *fdb, struct switchdev_trans *trans); int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, - const unsigned char *addr, u16 vid); + const struct switchdev_obj_port_fdb *fdb, + struct switchdev_trans *trans); int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid); int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, -- cgit v1.2.3 From 8057b3e7a1cfb4da61717ba609e1ea642bb82f9b Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 8 Oct 2015 11:35:14 -0400 Subject: net: dsa: use switchdev obj in port_fdb_del For consistency with the FDB add operation, propagate the switchdev_obj_port_fdb structure in the DSA drivers. Signed-off-by: Vivien Didelot Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 4 ++-- drivers/net/dsa/mv88e6xxx.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 644fffc6b98b..87b405e4f9f6 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1870,13 +1870,13 @@ int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, } int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, - const unsigned char *addr, u16 vid) + const struct switchdev_obj_port_fdb *fdb) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_port_fdb_load(ds, port, addr, vid, + ret = _mv88e6xxx_port_fdb_load(ds, port, fdb->addr, fdb->vid, GLOBAL_ATU_DATA_STATE_UNUSED); mutex_unlock(&ps->smi_mutex); diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 86a94dc0d86e..8325c11b9be2 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -481,7 +481,7 @@ int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, const struct switchdev_obj_port_fdb *fdb, struct switchdev_trans *trans); int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, - const unsigned char *addr, u16 vid); + const struct switchdev_obj_port_fdb *fdb); int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, unsigned char *addr, u16 *vid, bool *is_static); int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg); -- cgit v1.2.3 From d0cf57f9dddb50ea404bf747a3c6b22b29f82b9a Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 8 Oct 2015 19:23:20 -0700 Subject: rocker: handle setting bridge ageing_time The FDB cleanup timer will get rescheduled to re-evaluate FDB entries based on new ageing_time. Signed-off-by: Scott Feldman Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index cf91ffc6c987..eafa907965ec 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4361,6 +4361,18 @@ static int rocker_port_brport_flags_set(struct rocker_port *rocker_port, return err; } +static int rocker_port_bridge_ageing_time(struct rocker_port *rocker_port, + struct switchdev_trans *trans, + u32 ageing_time) +{ + if (!switchdev_trans_ph_prepare(trans)) { + rocker_port->ageing_time = clock_t_to_jiffies(ageing_time); + mod_timer(&rocker_port->rocker->fdb_cleanup_timer, jiffies); + } + + return 0; +} + static int rocker_port_attr_set(struct net_device *dev, struct switchdev_attr *attr, struct switchdev_trans *trans) @@ -4378,6 +4390,10 @@ static int rocker_port_attr_set(struct net_device *dev, err = rocker_port_brport_flags_set(rocker_port, trans, attr->u.brport_flags); break; + case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: + err = rocker_port_bridge_ageing_time(rocker_port, trans, + attr->u.ageing_time); + break; default: err = -EOPNOTSUPP; break; -- cgit v1.2.3 From c577e59ed7f55be398a2a730447a7f37d72eaa57 Mon Sep 17 00:00:00 2001 From: Daniel Pieczko Date: Fri, 9 Oct 2015 10:40:35 +0100 Subject: sfc: fully reset if MC_REBOOT event received without warm_boot_count increment On EF10, MC_CMD_VPORT_RECONFIGURE can cause a CODE_MC_REBOOT event to be sent to a function without incrementing the (adapter-wide) warm_boot_count. In this case, the reboot is not detected by the loop on efx_mcdi_poll_reboot(), so prepare for recovery from an MC reboot anyway. When this codepath is run, the MC has always just rebooted, so this recovery is valid. The loop on efx_mcdi_poll_reboot() is still required for other MC reboot cases, so that actions in response to an MC reboot are performed, such as clearing locally calculated statistics. Siena NICs are unaffected by this change as the above scenario does not apply. Signed-off-by: Shradha Shah Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/ef10.c | 30 +++++++++++++++++++----------- drivers/net/ethernet/sfc/mcdi.c | 13 ++++++++++++- drivers/net/ethernet/sfc/net_driver.h | 1 + 3 files changed, 32 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index ff649ebef637..78b7b7bcae37 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1604,6 +1604,22 @@ efx_ef10_mcdi_read_response(struct efx_nic *efx, efx_dword_t *outbuf, memcpy(outbuf, pdu + offset, outlen); } +static void efx_ef10_mcdi_reboot_detected(struct efx_nic *efx) +{ + struct efx_ef10_nic_data *nic_data = efx->nic_data; + + /* All our allocations have been reset */ + efx_ef10_reset_mc_allocations(efx); + + /* The datapath firmware might have been changed */ + nic_data->must_check_datapath_caps = true; + + /* MAC statistics have been cleared on the NIC; clear the local + * statistic that we update with efx_update_diff_stat(). + */ + nic_data->stats[EF10_STAT_port_rx_bad_bytes] = 0; +} + static int efx_ef10_mcdi_poll_reboot(struct efx_nic *efx) { struct efx_ef10_nic_data *nic_data = efx->nic_data; @@ -1623,17 +1639,7 @@ static int efx_ef10_mcdi_poll_reboot(struct efx_nic *efx) return 0; nic_data->warm_boot_count = rc; - - /* All our allocations have been reset */ - efx_ef10_reset_mc_allocations(efx); - - /* The datapath firmware might have been changed */ - nic_data->must_check_datapath_caps = true; - - /* MAC statistics have been cleared on the NIC; clear the local - * statistic that we update with efx_update_diff_stat(). - */ - nic_data->stats[EF10_STAT_port_rx_bad_bytes] = 0; + efx_ef10_mcdi_reboot_detected(efx); return -EIO; } @@ -4670,6 +4676,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { .mcdi_poll_response = efx_ef10_mcdi_poll_response, .mcdi_read_response = efx_ef10_mcdi_read_response, .mcdi_poll_reboot = efx_ef10_mcdi_poll_reboot, + .mcdi_reboot_detected = efx_ef10_mcdi_reboot_detected, .irq_enable_master = efx_port_dummy_op_void, .irq_test_generate = efx_ef10_irq_test_generate, .irq_disable_non_ev = efx_port_dummy_op_void, @@ -4774,6 +4781,7 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .mcdi_poll_response = efx_ef10_mcdi_poll_response, .mcdi_read_response = efx_ef10_mcdi_read_response, .mcdi_poll_reboot = efx_ef10_mcdi_poll_reboot, + .mcdi_reboot_detected = efx_ef10_mcdi_reboot_detected, .irq_enable_master = efx_port_dummy_op_void, .irq_test_generate = efx_ef10_irq_test_generate, .irq_disable_non_ev = efx_port_dummy_op_void, diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 98d172b04f71..d3f307e5c070 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -1028,10 +1028,21 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc) /* Consume the status word since efx_mcdi_rpc_finish() won't */ for (count = 0; count < MCDI_STATUS_DELAY_COUNT; ++count) { - if (efx_mcdi_poll_reboot(efx)) + rc = efx_mcdi_poll_reboot(efx); + if (rc) break; udelay(MCDI_STATUS_DELAY_US); } + + /* On EF10, a CODE_MC_REBOOT event can be received without the + * reboot detection in efx_mcdi_poll_reboot() being triggered. + * If zero was returned from the final call to + * efx_mcdi_poll_reboot(), the MC reboot wasn't noticed but the + * MC has definitely rebooted so prepare for the reset. + */ + if (!rc && efx->type->mcdi_reboot_detected) + efx->type->mcdi_reboot_detected(efx); + mcdi->new_epoch = true; /* Nobody was waiting for an MCDI request, so trigger a reset */ diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index c530e1c4cb4f..ad56231743a6 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -1277,6 +1277,7 @@ struct efx_nic_type { void (*mcdi_read_response)(struct efx_nic *efx, efx_dword_t *pdu, size_t pdu_offset, size_t pdu_len); int (*mcdi_poll_reboot)(struct efx_nic *efx); + void (*mcdi_reboot_detected)(struct efx_nic *efx); void (*irq_enable_master)(struct efx_nic *efx); void (*irq_test_generate)(struct efx_nic *efx); void (*irq_disable_non_ev)(struct efx_nic *efx); -- cgit v1.2.3 From 0fa28877b26641cca56b607ccec1fcbda7ae09c6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 9 Oct 2015 14:53:54 +0200 Subject: net: HNS: fix MDIO dependencies The newly introduced HNS_MDIO Kconfig symbol selects 'MDIO', but that is the wrong symbol as the code used by this driver is provided by PHYLIB rather than the MDIO driver. Also, there is no need to make this driver user selectable, because it is already selected by all drivers that need it. This changes the Kconfig file to select the correct library, and to make the option silent. Signed-off-by: Arnd Bergmann Fixes: 5b904d39406 ("net: add Hisilicon Network Subsystem MDIO support") Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig index 165b5a8aa2ea..8d12b587809e 100644 --- a/drivers/net/ethernet/hisilicon/Kconfig +++ b/drivers/net/ethernet/hisilicon/Kconfig @@ -24,7 +24,6 @@ config HIX5HD2_GMAC config HIP04_ETH tristate "HISILICON P04 Ethernet support" - select PHYLIB select MARVELL_PHY select MFD_SYSCON select HNS_MDIO @@ -33,8 +32,8 @@ config HIP04_ETH want to use the internal ethernet then you should answer Y to this. config HNS_MDIO - tristate "Hisilicon HNS MDIO device Support" - select MDIO + tristate + select PHYLIB ---help--- This selects the HNS MDIO support. It is needed by HNS_DSAF to access the PHY -- cgit v1.2.3 From 3703ebe4035044dea3749fcdd1c0849937147959 Mon Sep 17 00:00:00 2001 From: wangweidong Date: Tue, 13 Oct 2015 10:05:19 +0800 Subject: BNX2: free temp_stats_blk on error path In bnx2_init_board, missing free temp_stats_blk on error path when some operations do failed. Just add the 'kfree' operation. Signed-off-by: Wang Weidong Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 62590641897d..8fc3f3c137f8 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -8476,6 +8476,8 @@ err_out_disable: pci_disable_device(pdev); err_out: + kfree(bp->temp_stats_blk); + return rc; } -- cgit v1.2.3 From 19bcf9f203c82c2028f5a0881b1f0690e3207190 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 9 Oct 2015 13:44:54 -0500 Subject: ipv4: Pass struct net into ip_defrag and ip_check_defrag The function ip_defrag is called on both the input and the output paths of the networking stack. In particular conntrack when it is tracking outbound packets from the local machine calls ip_defrag. So add a struct net parameter and stop making ip_defrag guess which network namespace it needs to defragment packets in. Signed-off-by: "Eric W. Biederman" Acked-by: Pablo Neira Ayuso Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 47da43595ac2..86f6c6292c27 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -412,7 +412,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) port = macvlan_port_get_rcu(skb->dev); if (is_multicast_ether_addr(eth->h_dest)) { - skb = ip_check_defrag(skb, IP_DEFRAG_MACVLAN); + skb = ip_check_defrag(dev_net(skb->dev), skb, IP_DEFRAG_MACVLAN); if (!skb) return RX_HANDLER_CONSUMED; eth = eth_hdr(skb); -- cgit v1.2.3 From 5fcd2d8be43664f1b6a5add3d21a367411add9d4 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 9 Oct 2015 15:42:21 -0700 Subject: tun: use sk_fullsock() before reading sk->sk_tsflags timewait or request sockets are small and do not contain sk->sk_tsflags Without this fix, we might read garbage, and crash later in __skb_complete_tx_timestamp() -> sock_queue_err_skb() (These pseudo sockets do not have an error queue either) Fixes: ca6fb0651883 ("tcp: attach SYNACK messages to request sockets instead of listener") Signed-off-by: Eric Dumazet Cc: Willem de Bruijn Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/tun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 976aa9704297..b1878faea397 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -858,7 +858,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) goto drop; - if (skb->sk) { + if (skb->sk && sk_fullsock(skb->sk)) { sock_tx_timestamp(skb->sk, &skb_shinfo(skb)->tx_flags); sw_tx_timestamp(skb); } -- cgit v1.2.3 From 99dcc7dfb1960d5e2f1577ff3aad69dfeb6e9787 Mon Sep 17 00:00:00 2001 From: huangdaode Date: Sat, 10 Oct 2015 17:20:38 +0800 Subject: net: hns: fix the unknown phy_nterface_t type error This patch fix the building error reported by Jiri Pirko drivers/net/ethernet/hisilicon/hns/hnae.h:465:2: error: unknown type name 'phy_interface_t' phy_interface_t phy_if; ^ the full build log is on https://lists.01.org/pipermail/kbuild-all. Signed-off-by: huangdaode Signed-off-by: yankejian Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hnae.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index 5edd8cdc2485..d4a1eb1b8e54 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #define HNAE_DRIVER_VERSION "1.3.0" -- cgit v1.2.3 From 3b06d277957c7af705a9c0cdda4b371759efb717 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Mon, 12 Oct 2015 09:51:34 +0300 Subject: cfg80211: Add multiple scan plans for scheduled scan Add the option to configure multiple 'scan plans' for scheduled scan. Each 'scan plan' defines the number of scan cycles and the interval between scans. The scan plans are executed in the order they were configured. The last scan plan will always run infinitely and thus defines only the interval between scans. The maximum number of scan plans supported by the device and the maximum number of iterations in a single scan plan are advertised to userspace so it can configure the scan plans appropriately. When scheduled scan results are received there is no way to know which scan plan is being currently executed, so there is no way to know when the next scan iteration will start. This is not a problem, however. The scan start timestamp is only used for flushing old scan results, and there is no difference between flushing all results received until the end of the previous iteration or the start of the current one, since no results will be received in between. Signed-off-by: Avraham Stern Signed-off-by: Luca Coelho Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 +- drivers/net/wireless/iwlwifi/mvm/ops.c | 1 + drivers/net/wireless/iwlwifi/mvm/scan.c | 4 ++-- drivers/net/wireless/ti/wl12xx/scan.c | 3 ++- drivers/net/wireless/ti/wl18xx/scan.c | 8 +++++--- 5 files changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index a511ef3614b9..3fda750db2a9 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -3312,7 +3312,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, } /* fw uses seconds, also make sure that it's >0 */ - interval = max_t(u16, 1, request->interval / 1000); + interval = max_t(u16, 1, request->scan_plans[0].interval); ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, interval, interval, diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 064c100e45fe..f0728b784edb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -629,6 +629,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) kfree(mvm->d3_resume_sram); if (mvm->nd_config) { kfree(mvm->nd_config->match_sets); + kfree(mvm->nd_config->scan_plans); kfree(mvm->nd_config); mvm->nd_config = NULL; } diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 4a1f9af63bf0..cee4f267ca66 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -1271,12 +1271,12 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); - if (req->interval > U16_MAX) { + if (req->scan_plans[0].interval > U16_MAX) { IWL_DEBUG_SCAN(mvm, "interval value is > 16-bits, set to max possible\n"); params.interval = U16_MAX; } else { - params.interval = req->interval / MSEC_PER_SEC; + params.interval = req->scan_plans[0].interval; } /* In theory, LMAC scans can handle a 32-bit delay, but since diff --git a/drivers/net/wireless/ti/wl12xx/scan.c b/drivers/net/wireless/ti/wl12xx/scan.c index 7c355fff2c5e..ebed13af9852 100644 --- a/drivers/net/wireless/ti/wl12xx/scan.c +++ b/drivers/net/wireless/ti/wl12xx/scan.c @@ -350,7 +350,8 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, cfg->bss_type = SCAN_BSS_TYPE_ANY; /* currently NL80211 supports only a single interval */ for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++) - cfg->intervals[i] = cpu_to_le32(req->interval); + cfg->intervals[i] = cpu_to_le32(req->scan_plans[0].interval * + MSEC_PER_SEC); cfg->ssid_len = 0; ret = wlcore_scan_sched_scan_ssid_list(wl, wlvif, req); diff --git a/drivers/net/wireless/ti/wl18xx/scan.c b/drivers/net/wireless/ti/wl18xx/scan.c index c938c494c785..bc15aa2c3efa 100644 --- a/drivers/net/wireless/ti/wl18xx/scan.c +++ b/drivers/net/wireless/ti/wl18xx/scan.c @@ -228,13 +228,15 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl, wl18xx_adjust_channels(cmd, cmd_channels); if (c->num_short_intervals && c->long_interval && - c->long_interval > req->interval) { - cmd->short_cycles_msec = cpu_to_le16(req->interval); + c->long_interval > req->scan_plans[0].interval * MSEC_PER_SEC) { + cmd->short_cycles_msec = + cpu_to_le16(req->scan_plans[0].interval * MSEC_PER_SEC); cmd->long_cycles_msec = cpu_to_le16(c->long_interval); cmd->short_cycles_count = c->num_short_intervals; } else { cmd->short_cycles_msec = 0; - cmd->long_cycles_msec = cpu_to_le16(req->interval); + cmd->long_cycles_msec = + cpu_to_le16(req->scan_plans[0].interval * MSEC_PER_SEC); cmd->short_cycles_count = 0; } wl1271_debug(DEBUG_SCAN, "short_interval: %d, long_interval: %d, num_short: %d", -- cgit v1.2.3 From 571f2c11b343cd6997f35a21f6caa0f78e87fc84 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 11 Oct 2015 13:48:05 +0200 Subject: qlcnic: constify qlcnic_mbx_ops structure The only instance of a qlcnic_mbx_ops structure is never modified. Thus the declaration of the structure and all references to the structure type can be made const. In the definition of the qlcnic_mailbox structure, the ops field is no longer lined up with the other fields. This was left as is, to avoid a lot of trivial changes on the other lines. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Acked-by: Sony Chacko Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 2 +- drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index d6696cfa11d2..46bbea8e023c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -1092,7 +1092,7 @@ struct qlcnic_filter_hash { struct qlcnic_mailbox { struct workqueue_struct *work_q; struct qlcnic_adapter *adapter; - struct qlcnic_mbx_ops *ops; + const struct qlcnic_mbx_ops *ops; struct work_struct work; struct completion completion; struct list_head cmd_q; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 9f0bdd993955..37a731be7d39 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -4048,7 +4048,7 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work) struct qlcnic_mailbox *mbx = container_of(work, struct qlcnic_mailbox, work); struct qlcnic_adapter *adapter = mbx->adapter; - struct qlcnic_mbx_ops *mbx_ops = mbx->ops; + const struct qlcnic_mbx_ops *mbx_ops = mbx->ops; struct device *dev = &adapter->pdev->dev; atomic_t *rsp_status = &mbx->rsp_status; struct list_head *head = &mbx->cmd_q; @@ -4098,7 +4098,7 @@ static void qlcnic_83xx_mailbox_worker(struct work_struct *work) } } -static struct qlcnic_mbx_ops qlcnic_83xx_mbx_ops = { +static const struct qlcnic_mbx_ops qlcnic_83xx_mbx_ops = { .enqueue_cmd = qlcnic_83xx_enqueue_mbx_cmd, .dequeue_cmd = qlcnic_83xx_dequeue_mbx_cmd, .decode_resp = qlcnic_83xx_decode_mbx_rsp, -- cgit v1.2.3 From ede8098d0fef46ae48e59fcf7088149ca424d959 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 11 Oct 2015 18:08:35 -0400 Subject: net: dsa: mv88e6xxx: bridges do not need an FID With 88E6352 and similar switch chips, each port has a map to restrict which output port this input port can egress frames to. The current driver code implements hardware bridging using this feature, and assigns to a bridge group the FID of its first member. Now that 802.1Q is fully implemented in this driver, a Linux bridge which is a simple untagged VLAN, already gets its own FID. This patch gets rid of the per-bridge FID and explicits the usage of the port based VLAN map feature. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 141 ++++++++++---------------------------------- drivers/net/dsa/mv88e6xxx.h | 1 - 2 files changed, 32 insertions(+), 110 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 87b405e4f9f6..8d62bb344d43 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1046,11 +1046,6 @@ static int _mv88e6xxx_atu_flush(struct dsa_switch *ds, u16 fid, bool static_too) return _mv88e6xxx_atu_flush_move(ds, &entry, static_too); } -static int _mv88e6xxx_flush_fid(struct dsa_switch *ds, int fid) -{ - return _mv88e6xxx_atu_flush(ds, fid, false); -} - static int _mv88e6xxx_atu_move(struct dsa_switch *ds, u16 fid, int from_port, int to_port, bool static_too) { @@ -1112,130 +1107,56 @@ abort: return ret; } -/* Must be called with smi lock held */ -static int _mv88e6xxx_update_port_config(struct dsa_switch *ds, int port) +static int _mv88e6xxx_port_vlan_map_set(struct dsa_switch *ds, int port, + u16 output_ports) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - u8 fid = ps->fid[port]; - u16 reg = fid << 12; - - if (dsa_is_cpu_port(ds, port)) - reg |= ds->phys_port_mask; - else - reg |= (ps->bridge_mask[fid] | - (1 << dsa_upstream_port(ds))) & ~(1 << port); - - return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN, reg); -} - -/* Must be called with smi lock held */ -static int _mv88e6xxx_update_bridge_config(struct dsa_switch *ds, int fid) -{ - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int port; - u32 mask; - int ret; + const u16 mask = (1 << ps->num_ports) - 1; + int reg; - mask = ds->phys_port_mask; - while (mask) { - port = __ffs(mask); - mask &= ~(1 << port); - if (ps->fid[port] != fid) - continue; + reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_BASE_VLAN); + if (reg < 0) + return reg; - ret = _mv88e6xxx_update_port_config(ds, port); - if (ret) - return ret; - } + reg &= ~mask; + reg |= output_ports & mask; - return _mv88e6xxx_flush_fid(ds, fid); + return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN, reg); } /* Bridge handling functions */ -int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) +static int mv88e6xxx_map_bridge(struct dsa_switch *ds, u16 members) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int ret = 0; - u32 nmask; - int fid; - - /* If the bridge group is not empty, join that group. - * Otherwise create a new group. - */ - fid = ps->fid[port]; - nmask = br_port_mask & ~(1 << port); - if (nmask) - fid = ps->fid[__ffs(nmask)]; - - nmask = ps->bridge_mask[fid] | (1 << port); - if (nmask != br_port_mask) { - netdev_err(ds->ports[port], - "join: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n", - fid, br_port_mask, nmask); - return -EINVAL; - } + const unsigned long output = members | BIT(dsa_upstream_port(ds)); + int port, err = 0; mutex_lock(&ps->smi_mutex); - ps->bridge_mask[fid] = br_port_mask; + for_each_set_bit(port, &output, ps->num_ports) { + if (dsa_is_cpu_port(ds, port)) + continue; - if (fid != ps->fid[port]) { - clear_bit(ps->fid[port], ps->fid_bitmap); - ps->fid[port] = fid; - ret = _mv88e6xxx_update_bridge_config(ds, fid); + err = _mv88e6xxx_port_vlan_map_set(ds, port, output & ~port); + if (err) + break; } mutex_unlock(&ps->smi_mutex); - return ret; + return err; } -int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) -{ - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - u8 fid, newfid; - int ret; - - fid = ps->fid[port]; - if (ps->bridge_mask[fid] != br_port_mask) { - netdev_err(ds->ports[port], - "leave: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n", - fid, br_port_mask, ps->bridge_mask[fid]); - return -EINVAL; - } - - /* If the port was the last port of a bridge, we are done. - * Otherwise assign a new fid to the port, and fix up - * the bridge configuration. - */ - if (br_port_mask == (1 << port)) - return 0; - - mutex_lock(&ps->smi_mutex); - - newfid = find_next_zero_bit(ps->fid_bitmap, VLAN_N_VID, 1); - if (unlikely(newfid > ps->num_ports)) { - netdev_err(ds->ports[port], "all first %d FIDs are used\n", - ps->num_ports); - ret = -ENOSPC; - goto unlock; - } - - ps->fid[port] = newfid; - set_bit(newfid, ps->fid_bitmap); - ps->bridge_mask[fid] &= ~(1 << port); - ps->bridge_mask[newfid] = 1 << port; - - ret = _mv88e6xxx_update_bridge_config(ds, fid); - if (!ret) - ret = _mv88e6xxx_update_bridge_config(ds, newfid); - -unlock: - mutex_unlock(&ps->smi_mutex); +int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) +{ + return mv88e6xxx_map_bridge(ds, br_port_mask); +} - return ret; +int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) +{ + return mv88e6xxx_map_bridge(ds, br_port_mask & ~port); } int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state) @@ -2231,10 +2152,12 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) ps->fid[port] = fid; set_bit(fid, ps->fid_bitmap); - if (!dsa_is_cpu_port(ds, port)) - ps->bridge_mask[fid] = 1 << port; + if (dsa_is_cpu_port(ds, port)) + reg = BIT(ps->num_ports) - 1; + else + reg = BIT(dsa_upstream_port(ds)); - ret = _mv88e6xxx_update_port_config(ds, port); + ret = _mv88e6xxx_port_vlan_map_set(ds, port, reg & ~port); if (ret) goto abort; diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 8325c11b9be2..10387c2e999c 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -406,7 +406,6 @@ struct mv88e6xxx_priv_state { DECLARE_BITMAP(fid_bitmap, VLAN_N_VID); /* FIDs 1 to 4095 available */ u16 fid[DSA_MAX_PORTS]; /* per (non-bridged) port FID */ - u16 bridge_mask[DSA_MAX_PORTS]; /* br groups (indexed by FID) */ unsigned long port_state_update_mask; u8 port_state[DSA_MAX_PORTS]; -- cgit v1.2.3 From f02bdffca29bc41e440ac67ffd47b56834d3bf85 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 11 Oct 2015 18:08:36 -0400 Subject: net: dsa: mv88e6xxx: do not support per-port FID Since we configure a switch chip through a Linux bridge, and a bridge is implemented as a VLAN, there is no need for per-port FID anymore. This patch gets rid of this and simplifies the driver code since we can now directly map all 4095 FIDs available to all VLANs. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 69 ++++++++------------------------------------- drivers/net/dsa/mv88e6xxx.h | 5 ---- 2 files changed, 11 insertions(+), 63 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 8d62bb344d43..b2b99f8ef29b 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1468,6 +1468,7 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid, struct mv88e6xxx_vtu_stu_entry vlan = { .valid = true, .vid = vid, + .fid = vid, /* We use one FID per VLAN */ }; int i; @@ -1501,22 +1502,10 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid, return err; } - /* Non-bridged ports and bridge groups use FIDs from 1 to - * num_ports; VLANs use FIDs from num_ports+1 to 4095. - */ - vlan.fid = find_next_zero_bit(ps->fid_bitmap, VLAN_N_VID, - ps->num_ports + 1); - if (unlikely(vlan.fid == VLAN_N_VID)) { - pr_err("no more FID available for VLAN %d\n", vid); - return -ENOSPC; - } - /* Clear all MAC addresses from the new database */ err = _mv88e6xxx_atu_flush(ds, vlan.fid, true); if (err) return err; - - set_bit(vlan.fid, ps->fid_bitmap); } *entry = vlan; @@ -1556,7 +1545,6 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_vtu_stu_entry vlan; - bool keep = false; int i, err; mutex_lock(&ps->smi_mutex); @@ -1574,28 +1562,22 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) vlan.data[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER; /* keep the VLAN unless all ports are excluded */ + vlan.valid = false; for (i = 0; i < ps->num_ports; ++i) { if (dsa_is_cpu_port(ds, i)) continue; if (vlan.data[i] != GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) { - keep = true; + vlan.valid = true; break; } } - vlan.valid = keep; err = _mv88e6xxx_vtu_loadpurge(ds, &vlan); if (err) goto unlock; err = _mv88e6xxx_atu_remove(ds, vlan.fid, port, false); - if (err) - goto unlock; - - if (!keep) - clear_bit(vlan.fid, ps->fid_bitmap); - unlock: mutex_unlock(&ps->smi_mutex); @@ -1722,37 +1704,13 @@ static int _mv88e6xxx_atu_load(struct dsa_switch *ds, return _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_LOAD_DB); } -static int _mv88e6xxx_port_vid_to_fid(struct dsa_switch *ds, int port, u16 vid) -{ - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - struct mv88e6xxx_vtu_stu_entry vlan; - int err; - - if (vid == 0) - return ps->fid[port]; - - err = _mv88e6xxx_port_vtu_getnext(ds, port, vid - 1, &vlan); - if (err) - return err; - - if (vlan.vid == vid) - return vlan.fid; - - return -ENOENT; -} - static int _mv88e6xxx_port_fdb_load(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, u8 state) { struct mv88e6xxx_atu_entry entry = { 0 }; - int ret; - - ret = _mv88e6xxx_port_vid_to_fid(ds, port, vid); - if (ret < 0) - return ret; - entry.fid = ret; + entry.fid = vid; /* We use one FID per VLAN */ entry.state = state; ether_addr_copy(entry.mac, addr); if (state != GLOBAL_ATU_DATA_STATE_UNUSED) { @@ -1767,6 +1725,10 @@ int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port, const struct switchdev_obj_port_fdb *fdb, struct switchdev_trans *trans) { + /* We don't use per-port FDB */ + if (fdb->vid == 0) + return -EOPNOTSUPP; + /* We don't need any dynamic resource from the kernel (yet), * so skip the prepare phase. */ @@ -1864,16 +1826,11 @@ int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_atu_entry next; - u16 fid; + u16 fid = *vid; /* We use one FID per VLAN */ int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_port_vid_to_fid(ds, port, *vid); - if (ret < 0) - goto unlock; - fid = ret; - do { if (is_broadcast_ether_addr(addr)) { struct mv88e6xxx_vtu_stu_entry vtu; @@ -1924,7 +1881,7 @@ static void mv88e6xxx_bridge_work(struct work_struct *work) static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int ret, fid; + int ret; u16 reg; mutex_lock(&ps->smi_mutex); @@ -2143,15 +2100,11 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) if (ret) goto abort; - /* Port based VLAN map: give each port its own address + /* Port based VLAN map: do not give each port its own address * database, allow the CPU port to talk to each of the 'real' * ports, and allow each of the 'real' ports to only talk to * the upstream port. */ - fid = port + 1; - ps->fid[port] = fid; - set_bit(fid, ps->fid_bitmap); - if (dsa_is_cpu_port(ds, port)) reg = BIT(ps->num_ports) - 1; else diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 10387c2e999c..9b6104b94ce4 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -402,11 +402,6 @@ struct mv88e6xxx_priv_state { int id; /* switch product id */ int num_ports; /* number of switch ports */ - /* hw bridging */ - - DECLARE_BITMAP(fid_bitmap, VLAN_N_VID); /* FIDs 1 to 4095 available */ - u16 fid[DSA_MAX_PORTS]; /* per (non-bridged) port FID */ - unsigned long port_state_update_mask; u8 port_state[DSA_MAX_PORTS]; -- cgit v1.2.3 From 5fe7f68016ff9dcb59632071f9abf30296bbad3c Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 11 Oct 2015 18:08:38 -0400 Subject: net: dsa: mv88e6xxx: fix hardware bridging Playing with the VLAN map of every port to implement "hardware bridging" in the 88E6352 driver was a hack until full 802.1Q was supported. Indeed with 802.1Q port mode "Disabled" or "Fallback", this feature is used to restrict which output ports an input port can egress frames to. A Linux bridge is an untagged VLAN. With full 802.1Q support, we don't need this hack anymore and can use the "Secure" strict 802.1Q port mode. With this mode, the port-based VLAN map still needs to be configured, but all the logic is VTU-centric. This means that the switch only cares about rules described in its hardware VLAN table, which is exactly what Linux bridge expects and what we want. Note also that the hardware bridging was broken with the previous flexible "Fallback" 802.1Q port mode. Here's an example: Port0 and Port1 belong to the same bridge. If Port0 sends crafted tagged frames with VID 200 to Port1, Port1 receives it. Even if Port1 is in hardware VLAN 200, but not Port0, Port1 will still receive it, because Fallback mode doesn't care about invalid VID or non-member source port. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6171.c | 2 -- drivers/net/dsa/mv88e6352.c | 2 -- drivers/net/dsa/mv88e6xxx.c | 47 +++------------------------------------------ drivers/net/dsa/mv88e6xxx.h | 2 -- 4 files changed, 3 insertions(+), 50 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index ca3330aec740..dfca352e78e3 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -113,8 +113,6 @@ struct dsa_switch_driver mv88e6171_switch_driver = { #endif .get_regs_len = mv88e6xxx_get_regs_len, .get_regs = mv88e6xxx_get_regs, - .port_join_bridge = mv88e6xxx_join_bridge, - .port_leave_bridge = mv88e6xxx_leave_bridge, .port_stp_update = mv88e6xxx_port_stp_update, .port_pvid_get = mv88e6xxx_port_pvid_get, .port_pvid_set = mv88e6xxx_port_pvid_set, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 078a358c1b83..796fdcbe3c6e 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -340,8 +340,6 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .set_eeprom = mv88e6352_set_eeprom, .get_regs_len = mv88e6xxx_get_regs_len, .get_regs = mv88e6xxx_get_regs, - .port_join_bridge = mv88e6xxx_join_bridge, - .port_leave_bridge = mv88e6xxx_leave_bridge, .port_stp_update = mv88e6xxx_port_stp_update, .port_pvid_get = mv88e6xxx_port_pvid_get, .port_pvid_set = mv88e6xxx_port_pvid_set, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index b2b99f8ef29b..4591240eb795 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1124,41 +1124,6 @@ static int _mv88e6xxx_port_vlan_map_set(struct dsa_switch *ds, int port, return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_BASE_VLAN, reg); } -/* Bridge handling functions */ - -static int mv88e6xxx_map_bridge(struct dsa_switch *ds, u16 members) -{ - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - const unsigned long output = members | BIT(dsa_upstream_port(ds)); - int port, err = 0; - - mutex_lock(&ps->smi_mutex); - - for_each_set_bit(port, &output, ps->num_ports) { - if (dsa_is_cpu_port(ds, port)) - continue; - - err = _mv88e6xxx_port_vlan_map_set(ds, port, output & ~port); - if (err) - break; - } - - mutex_unlock(&ps->smi_mutex); - - return err; -} - - -int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) -{ - return mv88e6xxx_map_bridge(ds, br_port_mask); -} - -int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask) -{ - return mv88e6xxx_map_bridge(ds, br_port_mask & ~port); -} - int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); @@ -2007,7 +1972,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) reg |= PORT_CONTROL_2_FORWARD_UNKNOWN; } - reg |= PORT_CONTROL_2_8021Q_FALLBACK; + reg |= PORT_CONTROL_2_8021Q_SECURE; if (reg) { ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), @@ -2101,15 +2066,9 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) goto abort; /* Port based VLAN map: do not give each port its own address - * database, allow the CPU port to talk to each of the 'real' - * ports, and allow each of the 'real' ports to only talk to - * the upstream port. + * database, and allow every port to egress frames on all other ports. */ - if (dsa_is_cpu_port(ds, port)) - reg = BIT(ps->num_ports) - 1; - else - reg = BIT(dsa_upstream_port(ds)); - + reg = BIT(ps->num_ports) - 1; /* all ports */ ret = _mv88e6xxx_port_vlan_map_set(ds, port, reg & ~port); if (ret) goto abort; diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 9b6104b94ce4..4ba69f339bfe 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -458,8 +458,6 @@ int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum, int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e); int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, struct phy_device *phydev, struct ethtool_eee *e); -int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask); -int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask); int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state); int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *vid); int mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 vid); -- cgit v1.2.3 From 3dd03e52a410818c0818924c2ba27a43725f5e94 Mon Sep 17 00:00:00 2001 From: Gerlando Falauto Date: Mon, 12 Oct 2015 09:18:40 +0200 Subject: net/fsl_pq_mdio: check TBI address for consistency with mapped range When configuring the MDIO subsystem it is also necessary to configure the TBI register. Make sure the TBI is contained within the mapped register range in order to: a) make sure the address is computed correctly b) make users aware that we're actually accessing that register In case of error, print a message but continue anyway. Signed-off-by: Gerlando Falauto Cc: Timur Tabi Cc: David S. Miller Cc: Kumar Gala Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fsl_pq_mdio.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 3c40f6b99224..5333d0afceba 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -445,6 +445,16 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev) tbipa = data->get_tbipa(priv->map); + /* + * Add consistency check to make sure TBI is contained + * within the mapped range (not because we would get a + * segfault, rather to catch bugs in computing TBI + * address). Print error message but continue anyway. + */ + if ((void *)tbipa > priv->map + resource_size(&res) - 4) + dev_err(&pdev->dev, "invalid register map (should be at least 0x%04x to contain TBI address)\n", + ((void *)tbipa - priv->map) + 4); + iowrite32be(be32_to_cpup(prop), tbipa); } } -- cgit v1.2.3 From 3bb35ac4978977cf414893ee721f442039c4b8a4 Mon Sep 17 00:00:00 2001 From: Gerlando Falauto Date: Mon, 12 Oct 2015 09:18:41 +0200 Subject: net/fsl_pq_mdio: fix computed address for the TBI register commit afae5ad78b342f401c28b0bb1adb3cd494cb125a "net/fsl_pq_mdio: streamline probing of MDIO nodes" added support for different types of MDIO devices: 1) Gianfar MDIO nodes that only map the MII registers 2) Gianfar MDIO nodes that map the full MDIO register set 3) eTSEC2 MDIO nodes (which map the full MDIO register set) 4) QE MDIO nodes (which map only the MII registers) However, the implementation for types 1 and 4 would mistakenly assume a mapping of the full MDIO register set, thereby computing the address for the TBI register starting from the containing structure. The TBI register would therefore be accessed at a wrong (much bigger) address, not giving the expected result at all. This patch restores the correct behavior we had prior to the above one. The consequences of this bug are apparent when trying to access a PHY with the same address as the value contained in the initial value of the TBI register (normally 0); in that case you'll get answers from the internal TBI device (even though MDIO/MDC pins are actually *also* toggling on the physical bus!). Beware that you also need to add a fake tbi node to your device tree with an unused address. Notice how this fix is related to commit 220669495bf8b68130a8218607147c7b74c28d2b "powerpc: Add TBI PHY node to first MDIO bus" which fixed the behavior in kernel 3.3, which was later broken by the above commit on kernel 3.7. Signed-off-by: Gerlando Falauto Cc: Timur Tabi Cc: David S. Miller Cc: Kumar Gala Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fsl_pq_mdio.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 5333d0afceba..55c36230e176 100644 --- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -198,17 +198,28 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus) #if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) /* + * Return the TBIPA address, starting from the address + * of the mapped GFAR MDIO registers (struct gfar) * This is mildly evil, but so is our hardware for doing this. * Also, we have to cast back to struct gfar because of * definition weirdness done in gianfar.h. */ -static uint32_t __iomem *get_gfar_tbipa(void __iomem *p) +static uint32_t __iomem *get_gfar_tbipa_from_mdio(void __iomem *p) { struct gfar __iomem *enet_regs = p; return &enet_regs->tbipa; } +/* + * Return the TBIPA address, starting from the address + * of the mapped GFAR MII registers (gfar_mii_regs[] within struct gfar) + */ +static uint32_t __iomem *get_gfar_tbipa_from_mii(void __iomem *p) +{ + return get_gfar_tbipa_from_mdio(container_of(p, struct gfar, gfar_mii_regs)); +} + /* * Return the TBIPAR address for an eTSEC2 node */ @@ -220,11 +231,12 @@ static uint32_t __iomem *get_etsec_tbipa(void __iomem *p) #if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) /* - * Return the TBIPAR address for a QE MDIO node + * Return the TBIPAR address for a QE MDIO node, starting from the address + * of the mapped MII registers (struct fsl_pq_mii) */ static uint32_t __iomem *get_ucc_tbipa(void __iomem *p) { - struct fsl_pq_mdio __iomem *mdio = p; + struct fsl_pq_mdio __iomem *mdio = container_of(p, struct fsl_pq_mdio, mii); return &mdio->utbipar; } @@ -300,14 +312,14 @@ static const struct of_device_id fsl_pq_mdio_match[] = { .compatible = "fsl,gianfar-tbi", .data = &(struct fsl_pq_mdio_data) { .mii_offset = 0, - .get_tbipa = get_gfar_tbipa, + .get_tbipa = get_gfar_tbipa_from_mii, }, }, { .compatible = "fsl,gianfar-mdio", .data = &(struct fsl_pq_mdio_data) { .mii_offset = 0, - .get_tbipa = get_gfar_tbipa, + .get_tbipa = get_gfar_tbipa_from_mii, }, }, { @@ -315,7 +327,7 @@ static const struct of_device_id fsl_pq_mdio_match[] = { .compatible = "gianfar", .data = &(struct fsl_pq_mdio_data) { .mii_offset = offsetof(struct fsl_pq_mdio, mii), - .get_tbipa = get_gfar_tbipa, + .get_tbipa = get_gfar_tbipa_from_mdio, }, }, { -- cgit v1.2.3 From ae4a9d6a6362df4e4e492c297157498d299bdb68 Mon Sep 17 00:00:00 2001 From: Kalesh AP Date: Mon, 12 Oct 2015 03:47:17 -0400 Subject: be2net: fix BE3-R FW download compatibility check In the BE3 FW image, unlike Skyhawk's, the "asic_type_rev" field doesn't track the asic_rev of chip it is compatible with. When asic_type_rev is 0 the image is compatible only with pre-BE3-R chips (asic_rev < 0x10). Fix the current compatibility check to take care of this. We hit this issue when we try to flash old BE3 images (used prior to the release of BE3-R) on pre-BE3-R adapters. Fixes: a6e6ff6eee12f3e ("be2net: simplify UFI compatibility checking") Signed-off-by: Kalesh AP Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 7bf51a1a0a77..86eed4761806 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4999,7 +4999,15 @@ static bool be_check_ufi_compatibility(struct be_adapter *adapter, return false; } - return (fhdr->asic_type_rev >= adapter->asic_rev); + /* In BE3 FW images the "asic_type_rev" field doesn't track the + * asic_rev of the chips it is compatible with. + * When asic_type_rev is 0 the image is compatible only with + * pre-BE3-R chips (asic_rev < 0x10) + */ + if (BEx_chip(adapter) && fhdr->asic_type_rev == 0) + return adapter->asic_rev < 0x10; + else + return (fhdr->asic_type_rev >= adapter->asic_rev); } static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) -- cgit v1.2.3 From 0c8845679f3b8f030f3bafcdf226ed92545fa2a9 Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Mon, 12 Oct 2015 03:47:18 -0400 Subject: be2net: release mcc-lock in a failure case in be_cmd_notify_wait() The mcc/mbox lock is not being released when be_cmd_copy() returns an error. Signed-off-by: Suresh Reddy Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index eb323913cd39..9dc5ce11d996 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -851,8 +851,10 @@ static int be_cmd_notify_wait(struct be_adapter *adapter, return status; dest_wrb = be_cmd_copy(adapter, wrb); - if (!dest_wrb) - return -EBUSY; + if (!dest_wrb) { + status = -EBUSY; + goto unlock; + } if (use_mcc(adapter)) status = be_mcc_notify_wait(adapter); @@ -862,6 +864,7 @@ static int be_cmd_notify_wait(struct be_adapter *adapter, if (!status) memcpy(wrb, dest_wrb, sizeof(*wrb)); +unlock: be_cmd_unlock(adapter); return status; } -- cgit v1.2.3 From 8227e9901ded28d071f20313238e91e71d6bfdce Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Mon, 12 Oct 2015 03:47:19 -0400 Subject: be2net: pad skb to meet minimum TX pkt size in BE3 On BE3 chips in SRIOV configs, the TX path stalls when a packet less than 32B is received from the host. A workaround to pad such packets already exists for the Skyhawk and Lancer chips. Use the same workaround for BE3 chips too. Signed-off-by: Suresh Reddy Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 86eed4761806..821e0142fa2c 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1123,11 +1123,12 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, struct sk_buff *skb, struct be_wrb_params *wrb_params) { - /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or - * less may cause a transmit stall on that port. So the work-around is - * to pad short packets (<= 32 bytes) to a 36-byte length. + /* Lancer, SH and BE3 in SRIOV mode have a bug wherein + * packets that are 32b or less may cause a transmit stall + * on that port. The workaround is to pad such packets + * (len <= 32 bytes) to a minimum length of 36b. */ - if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) { + if (skb->len <= 32) { if (skb_put_padto(skb, 36)) return NULL; } -- cgit v1.2.3 From 72ef3a88fa8e225301aaea296ffc95407de21986 Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Mon, 12 Oct 2015 03:47:20 -0400 Subject: be2net: set pci_func_num while issuing GET_PROFILE_CONFIG cmd The FW requires the pf_num field in the cmd hdr to be set for it to return the specific function's descriptors in the GET_PROFILE_CONFIG cmd. If not set, the FW returns the descriptors of all the functions on the device. If the first descriptor is not what is being queried for, the driver will read wrong data. This patch fixes this issue by using the GET_CNTL_ATTRIB cmd to query the real pci_func_num of a function and then uses it in the GET_PROFILE_CONFIG cmd. Signed-off-by: Somnath Kotur Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 1 + drivers/net/ethernet/emulex/benet/be_cmds.c | 14 +++++++++++--- drivers/net/ethernet/emulex/benet/be_cmds.h | 10 ++++++++-- drivers/net/ethernet/emulex/benet/be_main.c | 9 +++++---- 4 files changed, 25 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 821540913343..d463563e1f70 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -592,6 +592,7 @@ struct be_adapter { int be_get_temp_freq; struct be_hwmon hwmon_info; u8 pf_number; + u8 pci_func_num; struct rss_info rss_info; /* Filters for packets that need to be sent to BMC */ u32 bmc_filt_mask; diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 9dc5ce11d996..790284de5a99 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -2890,6 +2890,7 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter) if (!status) { attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr); adapter->hba_port_num = attribs->hba_attribs.phy_port; + adapter->pci_func_num = attribs->pci_func_num; serial_num = attribs->hba_attribs.controller_serial_number; for (i = 0; i < CNTL_SERIAL_NUM_WORDS; i++) adapter->serial_num[i] = le32_to_cpu(serial_num[i]) & @@ -3712,7 +3713,6 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res) status = -EINVAL; goto err; } - adapter->pf_number = desc->pf_num; be_copy_nic_desc(res, desc); } @@ -3724,7 +3724,10 @@ err: return status; } -/* Will use MBOX only if MCCQ has not been created */ +/* Will use MBOX only if MCCQ has not been created + * non-zero domain => a PF is querying this on behalf of a VF + * zero domain => a PF or a VF is querying this for itself + */ int be_cmd_get_profile_config(struct be_adapter *adapter, struct be_resources *res, u8 query, u8 domain) { @@ -3751,10 +3754,15 @@ int be_cmd_get_profile_config(struct be_adapter *adapter, OPCODE_COMMON_GET_PROFILE_CONFIG, cmd.size, &wrb, &cmd); - req->hdr.domain = domain; if (!lancer_chip(adapter)) req->hdr.version = 1; req->type = ACTIVE_PROFILE_TYPE; + /* When a function is querying profile information relating to + * itself hdr.pf_number must be set to it's pci_func_num + 1 + */ + req->hdr.domain = domain; + if (domain == 0) + req->hdr.pf_num = adapter->pci_func_num + 1; /* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the * descriptors with all bits set to "1" for the fields which can be diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 7d178bdb112e..91155ea74f34 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -289,7 +289,9 @@ struct be_cmd_req_hdr { u32 timeout; /* dword 1 */ u32 request_length; /* dword 2 */ u8 version; /* dword 3 */ - u8 rsvd[3]; /* dword 3 */ + u8 rsvd1; /* dword 3 */ + u8 pf_num; /* dword 3 */ + u8 rsvd2; /* dword 3 */ }; #define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ @@ -1652,7 +1654,11 @@ struct mgmt_hba_attribs { struct mgmt_controller_attrib { struct mgmt_hba_attribs hba_attribs; - u32 rsvd0[10]; + u32 rsvd0[2]; + u16 rsvd1; + u8 pci_func_num; + u8 rsvd2; + u32 rsvd3[7]; } __packed; struct be_cmd_req_cntl_attribs { diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 821e0142fa2c..eb48a977f8da 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4206,10 +4206,6 @@ static int be_get_config(struct be_adapter *adapter) int status, level; u16 profile_id; - status = be_cmd_get_cntl_attributes(adapter); - if (status) - return status; - status = be_cmd_query_fw_cfg(adapter); if (status) return status; @@ -4408,6 +4404,11 @@ static int be_setup(struct be_adapter *adapter) if (!lancer_chip(adapter)) be_cmd_req_native_mode(adapter); + /* Need to invoke this cmd first to get the PCI Function Number */ + status = be_cmd_get_cntl_attributes(adapter); + if (status) + return status; + if (!BE2_chip(adapter) && be_physfn(adapter)) be_alloc_sriov_res(adapter); -- cgit v1.2.3 From 196e3735fa66c8340d6fff9ec81f6201ffc60b7d Mon Sep 17 00:00:00 2001 From: Kalesh AP Date: Mon, 12 Oct 2015 03:47:21 -0400 Subject: be2net: remove vlan promisc capability from VF's profile descriptors The commit 435452aa8847 ("Prevent VFs from enabling VLAN promiscuous mode") fixed the PF driver to not include the VLAN promisc capability while provisioning the interface for a VF. But the fix did not remove this capability from the profile descriptor of the VF. This causes the VF driver to request this capability when it tries to create it's interface at probe time. This could potentailly cause the VF probe to fail if the FW enforces strict checking of the flags based on what was provisoned by the PF. This strict checking is not being done by FW currently but will be fixed in a future version. This patch fixes this issue by updating the VF's profile descriptor so that they match the interface capability flags provisioned by the PF. Fixes: 435452aa8847 ("Prevent VFs from enabling VLAN promiscuous mode") Signed-off-by: Kalesh AP Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 790284de5a99..1795c935ff02 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1987,6 +1987,8 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) be_if_cap_flags(adapter)); } flags &= be_if_cap_flags(adapter); + if (!flags) + return -ENOTSUPP; return __be_cmd_rx_filter(adapter, flags, value); } @@ -3932,12 +3934,16 @@ static void be_fill_vf_res_template(struct be_adapter *adapter, vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS); } - - nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags); } else { num_vf_qs = 1; } + if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) { + nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT); + vf_if_cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS; + } + + nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags); nic_vft->rq_count = cpu_to_le16(num_vf_qs); nic_vft->txq_count = cpu_to_le16(num_vf_qs); nic_vft->rssq_count = cpu_to_le16(num_vf_qs); -- cgit v1.2.3 From 35402e31366349a32b505afdfe856aeeb8d939a0 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 12 Oct 2015 11:47:09 -0700 Subject: net: Add IPv6 support to VRF device Add support for IPv6 to VRF device driver. Implemenation parallels what has been done for IPv4. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/Kconfig | 4 +- drivers/net/vrf.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 275 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index b9ebd0d18a52..f184fb5bd110 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -298,8 +298,10 @@ config NLMON config NET_VRF tristate "Virtual Routing and Forwarding (Lite)" - depends on IP_MULTIPLE_TABLES && IPV6_MULTIPLE_TABLES + depends on IP_MULTIPLE_TABLES depends on NET_L3_MASTER_DEV + depends on IPV6 || IPV6=n + depends on IPV6_MULTIPLE_TABLES || IPV6=n ---help--- This option enables the support for mapping interfaces into VRF's. The support enables VRF devices. diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 191579aeab16..92fa3e1ea65c 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ struct slave_queue { struct net_vrf { struct slave_queue queue; struct rtable *rth; + struct rt6_info *rt6; u32 tb_id; }; @@ -104,12 +106,56 @@ static struct dst_ops vrf_dst_ops = { .default_advmss = vrf_default_advmss, }; +/* neighbor handling is done with actual device; do not want + * to flip skb->dev for those ndisc packets. This really fails + * for multiple next protocols (e.g., NEXTHDR_HOP). But it is + * a start. + */ +#if IS_ENABLED(CONFIG_IPV6) +static bool check_ipv6_frame(const struct sk_buff *skb) +{ + const struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb->data; + size_t hlen = sizeof(*ipv6h); + bool rc = true; + + if (skb->len < hlen) + goto out; + + if (ipv6h->nexthdr == NEXTHDR_ICMP) { + const struct icmp6hdr *icmph; + + if (skb->len < hlen + sizeof(*icmph)) + goto out; + + icmph = (struct icmp6hdr *)(skb->data + sizeof(*ipv6h)); + switch (icmph->icmp6_type) { + case NDISC_ROUTER_SOLICITATION: + case NDISC_ROUTER_ADVERTISEMENT: + case NDISC_NEIGHBOUR_SOLICITATION: + case NDISC_NEIGHBOUR_ADVERTISEMENT: + case NDISC_REDIRECT: + rc = false; + break; + } + } + +out: + return rc; +} +#else +static bool check_ipv6_frame(const struct sk_buff *skb) +{ + return false; +} +#endif + static bool is_ip_rx_frame(struct sk_buff *skb) { switch (skb->protocol) { case htons(ETH_P_IP): - case htons(ETH_P_IPV6): return true; + case htons(ETH_P_IPV6): + return check_ipv6_frame(skb); } return false; } @@ -169,12 +215,53 @@ static struct rtnl_link_stats64 *vrf_get_stats64(struct net_device *dev, return stats; } +#if IS_ENABLED(CONFIG_IPV6) +static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb, + struct net_device *dev) +{ + const struct ipv6hdr *iph = ipv6_hdr(skb); + struct net *net = dev_net(skb->dev); + struct flowi6 fl6 = { + /* needed to match OIF rule */ + .flowi6_oif = dev->ifindex, + .flowi6_iif = LOOPBACK_IFINDEX, + .daddr = iph->daddr, + .saddr = iph->saddr, + .flowlabel = ip6_flowinfo(iph), + .flowi6_mark = skb->mark, + .flowi6_proto = iph->nexthdr, + .flowi6_flags = FLOWI_FLAG_L3MDEV_SRC | FLOWI_FLAG_SKIP_NH_OIF, + }; + int ret = NET_XMIT_DROP; + struct dst_entry *dst; + struct dst_entry *dst_null = &net->ipv6.ip6_null_entry->dst; + + dst = ip6_route_output(net, NULL, &fl6); + if (dst == dst_null) + goto err; + + skb_dst_drop(skb); + skb_dst_set(skb, dst); + + ret = ip6_local_out(net, skb->sk, skb); + if (unlikely(net_xmit_eval(ret))) + dev->stats.tx_errors++; + else + ret = NET_XMIT_SUCCESS; + + return ret; +err: + vrf_tx_error(dev, skb); + return NET_XMIT_DROP; +} +#else static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb, struct net_device *dev) { vrf_tx_error(dev, skb); return NET_XMIT_DROP; } +#endif static int vrf_send_v4_prep(struct sk_buff *skb, struct flowi4 *fl4, struct net_device *vrf_dev) @@ -269,6 +356,157 @@ static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev) return ret; } +#if IS_ENABLED(CONFIG_IPV6) +static struct dst_entry *vrf_ip6_check(struct dst_entry *dst, u32 cookie) +{ + return dst; +} + +static struct dst_ops vrf_dst_ops6 = { + .family = AF_INET6, + .local_out = ip6_local_out, + .check = vrf_ip6_check, + .mtu = vrf_v4_mtu, + .destroy = vrf_dst_destroy, + .default_advmss = vrf_default_advmss, +}; + +static int init_dst_ops6_kmem_cachep(void) +{ + vrf_dst_ops6.kmem_cachep = kmem_cache_create("vrf_ip6_dst_cache", + sizeof(struct rt6_info), + 0, + SLAB_HWCACHE_ALIGN, + NULL); + + if (!vrf_dst_ops6.kmem_cachep) + return -ENOMEM; + + return 0; +} + +static void free_dst_ops6_kmem_cachep(void) +{ + kmem_cache_destroy(vrf_dst_ops6.kmem_cachep); +} + +static int vrf_input6(struct sk_buff *skb) +{ + skb->dev->stats.rx_errors++; + kfree_skb(skb); + return 0; +} + +/* modelled after ip6_finish_output2 */ +static int vrf_finish_output6(struct net *net, struct sock *sk, + struct sk_buff *skb) +{ + struct dst_entry *dst = skb_dst(skb); + struct net_device *dev = dst->dev; + struct neighbour *neigh; + struct in6_addr *nexthop; + int ret; + + skb->protocol = htons(ETH_P_IPV6); + skb->dev = dev; + + rcu_read_lock_bh(); + nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr); + neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop); + if (unlikely(!neigh)) + neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false); + if (!IS_ERR(neigh)) { + ret = dst_neigh_output(dst, neigh, skb); + rcu_read_unlock_bh(); + return ret; + } + rcu_read_unlock_bh(); + + IP6_INC_STATS(dev_net(dst->dev), + ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); + kfree_skb(skb); + return -EINVAL; +} + +/* modelled after ip6_output */ +static int vrf_output6(struct net *net, struct sock *sk, struct sk_buff *skb) +{ + return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, + net, sk, skb, NULL, skb_dst(skb)->dev, + vrf_finish_output6, + !(IP6CB(skb)->flags & IP6SKB_REROUTED)); +} + +static void vrf_rt6_destroy(struct net_vrf *vrf) +{ + dst_destroy(&vrf->rt6->dst); + free_percpu(vrf->rt6->rt6i_pcpu); + vrf->rt6 = NULL; +} + +static int vrf_rt6_create(struct net_device *dev) +{ + struct net_vrf *vrf = netdev_priv(dev); + struct dst_entry *dst; + struct rt6_info *rt6; + int cpu; + int rc = -ENOMEM; + + rt6 = dst_alloc(&vrf_dst_ops6, dev, 0, + DST_OBSOLETE_NONE, + (DST_HOST | DST_NOPOLICY | DST_NOXFRM)); + if (!rt6) + goto out; + + dst = &rt6->dst; + + rt6->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, GFP_KERNEL); + if (!rt6->rt6i_pcpu) { + dst_destroy(dst); + goto out; + } + for_each_possible_cpu(cpu) { + struct rt6_info **p = per_cpu_ptr(rt6->rt6i_pcpu, cpu); + *p = NULL; + } + + memset(dst + 1, 0, sizeof(*rt6) - sizeof(*dst)); + + INIT_LIST_HEAD(&rt6->rt6i_siblings); + INIT_LIST_HEAD(&rt6->rt6i_uncached); + + rt6->dst.input = vrf_input6; + rt6->dst.output = vrf_output6; + + rt6->rt6i_table = fib6_get_table(dev_net(dev), vrf->tb_id); + + atomic_set(&rt6->dst.__refcnt, 2); + + vrf->rt6 = rt6; + rc = 0; +out: + return rc; +} +#else +static int init_dst_ops6_kmem_cachep(void) +{ + return 0; +} + +static void free_dst_ops6_kmem_cachep(void) +{ +} + +static void vrf_rt6_destroy(struct net_vrf *vrf) +{ +} + +static int vrf_rt6_create(struct net_device *dev) +{ + return 0; +} +#endif + /* modelled after ip_finish_output2 */ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) { @@ -490,6 +728,7 @@ static void vrf_dev_uninit(struct net_device *dev) struct slave *slave, *next; vrf_rtable_destroy(vrf); + vrf_rt6_destroy(vrf); list_for_each_entry_safe(slave, next, head, list) vrf_del_slave(dev, slave->dev); @@ -513,10 +752,15 @@ static int vrf_dev_init(struct net_device *dev) if (!vrf->rth) goto out_stats; + if (vrf_rt6_create(dev) != 0) + goto out_rth; + dev->flags = IFF_MASTER | IFF_NOARP; return 0; +out_rth: + vrf_rtable_destroy(vrf); out_stats: free_percpu(dev->dstats); dev->dstats = NULL; @@ -586,10 +830,30 @@ static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4) fl4->flowi4_scope = scope; } +#if IS_ENABLED(CONFIG_IPV6) +static struct dst_entry *vrf_get_rt6_dst(const struct net_device *dev, + const struct flowi6 *fl6) +{ + struct rt6_info *rt = NULL; + + if (!(fl6->flowi6_flags & FLOWI_FLAG_L3MDEV_SRC)) { + struct net_vrf *vrf = netdev_priv(dev); + + rt = vrf->rt6; + atomic_inc(&rt->dst.__refcnt); + } + + return (struct dst_entry *)rt; +} +#endif + static const struct l3mdev_ops vrf_l3mdev_ops = { .l3mdev_fib_table = vrf_fib_table, .l3mdev_get_rtable = vrf_get_rtable, .l3mdev_get_saddr = vrf_get_saddr, +#if IS_ENABLED(CONFIG_IPV6) + .l3mdev_get_rt6_dst = vrf_get_rt6_dst, +#endif }; static void vrf_get_drvinfo(struct net_device *dev, @@ -731,6 +995,10 @@ static int __init vrf_init_module(void) if (!vrf_dst_ops.kmem_cachep) return -ENOMEM; + rc = init_dst_ops6_kmem_cachep(); + if (rc != 0) + goto error2; + register_netdevice_notifier(&vrf_notifier_block); rc = rtnl_link_register(&vrf_link_ops); @@ -741,6 +1009,8 @@ static int __init vrf_init_module(void) error: unregister_netdevice_notifier(&vrf_notifier_block); + free_dst_ops6_kmem_cachep(); +error2: kmem_cache_destroy(vrf_dst_ops.kmem_cachep); return rc; } @@ -750,6 +1020,7 @@ static void __exit vrf_cleanup_module(void) rtnl_link_unregister(&vrf_link_ops); unregister_netdevice_notifier(&vrf_notifier_block); kmem_cache_destroy(vrf_dst_ops.kmem_cachep); + free_dst_ops6_kmem_cachep(); } module_init(vrf_init_module); -- cgit v1.2.3 From 887e07be3fd2d056362a9f851f796580d7bca499 Mon Sep 17 00:00:00 2001 From: Gerhard Bertelsmann Date: Fri, 25 Sep 2015 18:58:38 +0200 Subject: can: sun4i: fix arbitration lost error reporting This patch fixes a bug in arbitration error reporting Reported-by: Dan Carpenter Signed-off-by: Gerhard Bertelsmann Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sun4i_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 10d8497635e8..67bdf6d62c76 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -601,7 +601,7 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status) stats->tx_errors++; if (likely(skb)) { cf->can_id |= CAN_ERR_LOSTARB; - cf->data[0] = (alc & 0x1f) >> 8; + cf->data[0] = (alc >> 8) & 0x1f; } } -- cgit v1.2.3 From 3c200db56441365d964b5a983de948821f5011b9 Mon Sep 17 00:00:00 2001 From: Gerhard Bertelsmann Date: Fri, 25 Sep 2015 18:58:39 +0200 Subject: can: sun4i: fix MODULE_DESCRIPTION This patch change description of the module. Signed-off-by: Gerhard Bertelsmann Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sun4i_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 67bdf6d62c76..d9a42c646783 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -854,4 +854,4 @@ module_platform_driver(sun4i_can_driver); MODULE_AUTHOR("Peter Chen "); MODULE_AUTHOR("Gerhard Bertelsmann "); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION(DRV_NAME "CAN driver for Allwinner SoCs (A10/A20)"); +MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20)"); -- cgit v1.2.3 From 42160a041db89807691b2a3fbf42e36a98b6019e Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 8 Oct 2015 16:56:07 +0200 Subject: can: at91: remove at91_can_data struct at91_can_data was used to pass a callback to the driver, allowing it to switch the transceiver on and off. As all at91 boards are now using DT, this is not used anymore, remove that structure. Signed-off-by: Alexandre Belloni Signed-off-by: Marc Kleine-Budde --- drivers/net/can/at91_can.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 945c0955a967..8b3275d7792a 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -8,15 +8,6 @@ * Public License ("GPL") version 2 as distributed in the 'COPYING' * file from the main directory of the linux kernel source. * - * - * Your platform definition file should specify something like: - * - * static struct at91_can_data ek_can_data = { - * transceiver_switch = sam9263ek_transceiver_switch, - * }; - * - * at91_add_device_can(&ek_can_data); - * */ #include @@ -33,7 +24,6 @@ #include #include #include -#include #include #include @@ -324,15 +314,6 @@ static inline u32 at91_can_id_to_reg_mid(canid_t can_id) return reg_mid; } -/* - * Swtich transceiver on or off - */ -static void at91_transceiver_switch(const struct at91_priv *priv, int on) -{ - if (priv->pdata && priv->pdata->transceiver_switch) - priv->pdata->transceiver_switch(on); -} - static void at91_setup_mailboxes(struct net_device *dev) { struct at91_priv *priv = netdev_priv(dev); @@ -416,7 +397,6 @@ static void at91_chip_start(struct net_device *dev) at91_set_bittiming(dev); at91_setup_mailboxes(dev); - at91_transceiver_switch(priv, 1); /* enable chip */ if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) @@ -444,7 +424,6 @@ static void at91_chip_stop(struct net_device *dev, enum can_state state) reg_mr = at91_read(priv, AT91_MR); at91_write(priv, AT91_MR, reg_mr & ~AT91_MR_CANEN); - at91_transceiver_switch(priv, 0); priv->can.state = state; } -- cgit v1.2.3 From ea9ed9cff47e7932925982c8fdaf2d4d1708884f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 3 Oct 2015 15:32:56 +0200 Subject: netconsole: use per-attribute show and store methods Note that the old code actually used the store_attributes method to do locking, this is moved into the individual methods. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/net/netconsole.c | 271 +++++++++++++++++++++++------------------------ 1 file changed, 132 insertions(+), 139 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 97f3acd44798..06ee6395117f 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -244,15 +244,6 @@ static void free_param_target(struct netconsole_target *nt) * /... */ -struct netconsole_target_attr { - struct configfs_attribute attr; - ssize_t (*show)(struct netconsole_target *nt, - char *buf); - ssize_t (*store)(struct netconsole_target *nt, - const char *buf, - size_t count); -}; - static struct netconsole_target *to_target(struct config_item *item) { return item ? @@ -264,58 +255,62 @@ static struct netconsole_target *to_target(struct config_item *item) * Attribute operations for netconsole_target. */ -static ssize_t show_enabled(struct netconsole_target *nt, char *buf) +static ssize_t enabled_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", nt->enabled); + return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->enabled); } -static ssize_t show_extended(struct netconsole_target *nt, char *buf) +static ssize_t extended_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", nt->extended); + return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->extended); } -static ssize_t show_dev_name(struct netconsole_target *nt, char *buf) +static ssize_t dev_name_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%s\n", nt->np.dev_name); + return snprintf(buf, PAGE_SIZE, "%s\n", to_target(item)->np.dev_name); } -static ssize_t show_local_port(struct netconsole_target *nt, char *buf) +static ssize_t local_port_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", nt->np.local_port); + return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->np.local_port); } -static ssize_t show_remote_port(struct netconsole_target *nt, char *buf) +static ssize_t remote_port_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", nt->np.remote_port); + return snprintf(buf, PAGE_SIZE, "%d\n", to_target(item)->np.remote_port); } -static ssize_t show_local_ip(struct netconsole_target *nt, char *buf) +static ssize_t local_ip_show(struct config_item *item, char *buf) { + struct netconsole_target *nt = to_target(item); + if (nt->np.ipv6) return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.local_ip.in6); else return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip); } -static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf) +static ssize_t remote_ip_show(struct config_item *item, char *buf) { + struct netconsole_target *nt = to_target(item); + if (nt->np.ipv6) return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.remote_ip.in6); else return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip); } -static ssize_t show_local_mac(struct netconsole_target *nt, char *buf) +static ssize_t local_mac_show(struct config_item *item, char *buf) { - struct net_device *dev = nt->np.dev; + struct net_device *dev = to_target(item)->np.dev; static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; return snprintf(buf, PAGE_SIZE, "%pM\n", dev ? dev->dev_addr : bcast); } -static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf) +static ssize_t remote_mac_show(struct config_item *item, char *buf) { - return snprintf(buf, PAGE_SIZE, "%pM\n", nt->np.remote_mac); + return snprintf(buf, PAGE_SIZE, "%pM\n", to_target(item)->np.remote_mac); } /* @@ -325,23 +320,26 @@ static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf) * would enable him to dynamically add new netpoll targets for new * network interfaces as and when they come up). */ -static ssize_t store_enabled(struct netconsole_target *nt, - const char *buf, - size_t count) +static ssize_t enabled_store(struct config_item *item, + const char *buf, size_t count) { + struct netconsole_target *nt = to_target(item); unsigned long flags; int enabled; int err; + mutex_lock(&dynamic_netconsole_mutex); err = kstrtoint(buf, 10, &enabled); if (err < 0) - return err; + goto out_unlock; + + err = -EINVAL; if (enabled < 0 || enabled > 1) - return -EINVAL; + goto out_unlock; if ((bool)enabled == nt->enabled) { pr_info("network logging has already %s\n", nt->enabled ? "started" : "stopped"); - return -EINVAL; + goto out_unlock; } if (enabled) { /* true */ @@ -358,7 +356,7 @@ static ssize_t store_enabled(struct netconsole_target *nt, err = netpoll_setup(&nt->np); if (err) - return err; + goto out_unlock; pr_info("netconsole: network logging started\n"); } else { /* false */ @@ -374,42 +372,56 @@ static ssize_t store_enabled(struct netconsole_target *nt, nt->enabled = enabled; + mutex_unlock(&dynamic_netconsole_mutex); return strnlen(buf, count); +out_unlock: + mutex_unlock(&dynamic_netconsole_mutex); + return err; } -static ssize_t store_extended(struct netconsole_target *nt, - const char *buf, - size_t count) +static ssize_t extended_store(struct config_item *item, const char *buf, + size_t count) { + struct netconsole_target *nt = to_target(item); int extended; int err; + mutex_lock(&dynamic_netconsole_mutex); if (nt->enabled) { pr_err("target (%s) is enabled, disable to update parameters\n", config_item_name(&nt->item)); - return -EINVAL; + err = -EINVAL; + goto out_unlock; } err = kstrtoint(buf, 10, &extended); if (err < 0) - return err; - if (extended < 0 || extended > 1) - return -EINVAL; + goto out_unlock; + if (extended < 0 || extended > 1) { + err = -EINVAL; + goto out_unlock; + } nt->extended = extended; + mutex_unlock(&dynamic_netconsole_mutex); return strnlen(buf, count); +out_unlock: + mutex_unlock(&dynamic_netconsole_mutex); + return err; } -static ssize_t store_dev_name(struct netconsole_target *nt, - const char *buf, - size_t count) +static ssize_t dev_name_store(struct config_item *item, const char *buf, + size_t count) { + struct netconsole_target *nt = to_target(item); size_t len; + mutex_lock(&dynamic_netconsole_mutex); if (nt->enabled) { pr_err("target (%s) is enabled, disable to update parameters\n", config_item_name(&nt->item)); + mutex_unlock(&dynamic_netconsole_mutex); return -EINVAL; } @@ -420,53 +432,66 @@ static ssize_t store_dev_name(struct netconsole_target *nt, if (nt->np.dev_name[len - 1] == '\n') nt->np.dev_name[len - 1] = '\0'; + mutex_unlock(&dynamic_netconsole_mutex); return strnlen(buf, count); } -static ssize_t store_local_port(struct netconsole_target *nt, - const char *buf, - size_t count) +static ssize_t local_port_store(struct config_item *item, const char *buf, + size_t count) { - int rv; + struct netconsole_target *nt = to_target(item); + int rv = -EINVAL; + mutex_lock(&dynamic_netconsole_mutex); if (nt->enabled) { pr_err("target (%s) is enabled, disable to update parameters\n", config_item_name(&nt->item)); - return -EINVAL; + goto out_unlock; } rv = kstrtou16(buf, 10, &nt->np.local_port); if (rv < 0) - return rv; + goto out_unlock; + mutex_unlock(&dynamic_netconsole_mutex); return strnlen(buf, count); +out_unlock: + mutex_unlock(&dynamic_netconsole_mutex); + return rv; } -static ssize_t store_remote_port(struct netconsole_target *nt, - const char *buf, - size_t count) +static ssize_t remote_port_store(struct config_item *item, + const char *buf, size_t count) { - int rv; + struct netconsole_target *nt = to_target(item); + int rv = -EINVAL; + mutex_lock(&dynamic_netconsole_mutex); if (nt->enabled) { pr_err("target (%s) is enabled, disable to update parameters\n", config_item_name(&nt->item)); - return -EINVAL; + goto out_unlock; } rv = kstrtou16(buf, 10, &nt->np.remote_port); if (rv < 0) - return rv; + goto out_unlock; + mutex_unlock(&dynamic_netconsole_mutex); return strnlen(buf, count); +out_unlock: + mutex_unlock(&dynamic_netconsole_mutex); + return rv; } -static ssize_t store_local_ip(struct netconsole_target *nt, - const char *buf, - size_t count) +static ssize_t local_ip_store(struct config_item *item, const char *buf, + size_t count) { + struct netconsole_target *nt = to_target(item); + + mutex_lock(&dynamic_netconsole_mutex); if (nt->enabled) { pr_err("target (%s) is enabled, disable to update parameters\n", config_item_name(&nt->item)); - return -EINVAL; + goto out_unlock; } if (strnchr(buf, count, ':')) { @@ -474,29 +499,35 @@ static ssize_t store_local_ip(struct netconsole_target *nt, if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) { if (*end && *end != '\n') { pr_err("invalid IPv6 address at: <%c>\n", *end); - return -EINVAL; + goto out_unlock; } nt->np.ipv6 = true; } else - return -EINVAL; + goto out_unlock; } else { if (!nt->np.ipv6) { nt->np.local_ip.ip = in_aton(buf); } else - return -EINVAL; + goto out_unlock; } + mutex_unlock(&dynamic_netconsole_mutex); return strnlen(buf, count); +out_unlock: + mutex_unlock(&dynamic_netconsole_mutex); + return -EINVAL; } -static ssize_t store_remote_ip(struct netconsole_target *nt, - const char *buf, - size_t count) +static ssize_t remote_ip_store(struct config_item *item, const char *buf, + size_t count) { + struct netconsole_target *nt = to_target(item); + + mutex_lock(&dynamic_netconsole_mutex); if (nt->enabled) { pr_err("target (%s) is enabled, disable to update parameters\n", config_item_name(&nt->item)); - return -EINVAL; + goto out_unlock; } if (strnchr(buf, count, ':')) { @@ -504,74 +535,71 @@ static ssize_t store_remote_ip(struct netconsole_target *nt, if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) { if (*end && *end != '\n') { pr_err("invalid IPv6 address at: <%c>\n", *end); - return -EINVAL; + goto out_unlock; } nt->np.ipv6 = true; } else - return -EINVAL; + goto out_unlock; } else { if (!nt->np.ipv6) { nt->np.remote_ip.ip = in_aton(buf); } else - return -EINVAL; + goto out_unlock; } + mutex_unlock(&dynamic_netconsole_mutex); return strnlen(buf, count); +out_unlock: + mutex_unlock(&dynamic_netconsole_mutex); + return -EINVAL; } -static ssize_t store_remote_mac(struct netconsole_target *nt, - const char *buf, - size_t count) +static ssize_t remote_mac_store(struct config_item *item, const char *buf, + size_t count) { + struct netconsole_target *nt = to_target(item); u8 remote_mac[ETH_ALEN]; + mutex_lock(&dynamic_netconsole_mutex); if (nt->enabled) { pr_err("target (%s) is enabled, disable to update parameters\n", config_item_name(&nt->item)); - return -EINVAL; + goto out_unlock; } if (!mac_pton(buf, remote_mac)) - return -EINVAL; + goto out_unlock; if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n') - return -EINVAL; + goto out_unlock; memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN); + mutex_unlock(&dynamic_netconsole_mutex); return strnlen(buf, count); +out_unlock: + mutex_unlock(&dynamic_netconsole_mutex); + return -EINVAL; } -/* - * Attribute definitions for netconsole_target. - */ - -#define NETCONSOLE_TARGET_ATTR_RO(_name) \ -static struct netconsole_target_attr netconsole_target_##_name = \ - __CONFIGFS_ATTR(_name, S_IRUGO, show_##_name, NULL) - -#define NETCONSOLE_TARGET_ATTR_RW(_name) \ -static struct netconsole_target_attr netconsole_target_##_name = \ - __CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, show_##_name, store_##_name) - -NETCONSOLE_TARGET_ATTR_RW(enabled); -NETCONSOLE_TARGET_ATTR_RW(extended); -NETCONSOLE_TARGET_ATTR_RW(dev_name); -NETCONSOLE_TARGET_ATTR_RW(local_port); -NETCONSOLE_TARGET_ATTR_RW(remote_port); -NETCONSOLE_TARGET_ATTR_RW(local_ip); -NETCONSOLE_TARGET_ATTR_RW(remote_ip); -NETCONSOLE_TARGET_ATTR_RO(local_mac); -NETCONSOLE_TARGET_ATTR_RW(remote_mac); +CONFIGFS_ATTR(, enabled); +CONFIGFS_ATTR(, extended); +CONFIGFS_ATTR(, dev_name); +CONFIGFS_ATTR(, local_port); +CONFIGFS_ATTR(, remote_port); +CONFIGFS_ATTR(, local_ip); +CONFIGFS_ATTR(, remote_ip); +CONFIGFS_ATTR_RO(, local_mac); +CONFIGFS_ATTR(, remote_mac); static struct configfs_attribute *netconsole_target_attrs[] = { - &netconsole_target_enabled.attr, - &netconsole_target_extended.attr, - &netconsole_target_dev_name.attr, - &netconsole_target_local_port.attr, - &netconsole_target_remote_port.attr, - &netconsole_target_local_ip.attr, - &netconsole_target_remote_ip.attr, - &netconsole_target_local_mac.attr, - &netconsole_target_remote_mac.attr, + &attr_enabled, + &attr_extended, + &attr_dev_name, + &attr_local_port, + &attr_remote_port, + &attr_local_ip, + &attr_remote_ip, + &attr_local_mac, + &attr_remote_mac, NULL, }; @@ -584,43 +612,8 @@ static void netconsole_target_release(struct config_item *item) kfree(to_target(item)); } -static ssize_t netconsole_target_attr_show(struct config_item *item, - struct configfs_attribute *attr, - char *buf) -{ - ssize_t ret = -EINVAL; - struct netconsole_target *nt = to_target(item); - struct netconsole_target_attr *na = - container_of(attr, struct netconsole_target_attr, attr); - - if (na->show) - ret = na->show(nt, buf); - - return ret; -} - -static ssize_t netconsole_target_attr_store(struct config_item *item, - struct configfs_attribute *attr, - const char *buf, - size_t count) -{ - ssize_t ret = -EINVAL; - struct netconsole_target *nt = to_target(item); - struct netconsole_target_attr *na = - container_of(attr, struct netconsole_target_attr, attr); - - mutex_lock(&dynamic_netconsole_mutex); - if (na->store) - ret = na->store(nt, buf, count); - mutex_unlock(&dynamic_netconsole_mutex); - - return ret; -} - static struct configfs_item_operations netconsole_target_item_ops = { .release = netconsole_target_release, - .show_attribute = netconsole_target_attr_show, - .store_attribute = netconsole_target_attr_store, }; static struct config_item_type netconsole_target_type = { -- cgit v1.2.3 From 0a51b343abfe2c0dbcbd9ec3c4b18bb8779fefa8 Mon Sep 17 00:00:00 2001 From: Manikanta Pubbisetty Date: Fri, 9 Oct 2015 11:55:58 +0300 Subject: ath10k: add board 2 API support QCA6174 needs different board files based on board type. To make it easier to distribute multiple board files and automatically choose correct board file create a simple TLV file format following the same principles as with FW IEs. The file is named board-2.bin and contain multiple board files. Each board file then can have multiple names. ath10k searches for file board-N.bin (where N is the interface version number for the board file, just like we for firmware files) in /lib/firmware/*, for example for qca99x0 it will try to find it here: /lib/firmware/ath10k/QCA99X0/hw2.0/board-2.bin If ath10k doesn't find board-2.bin then it will fallback to the old board.bin file. This patch adds a simple name scheme using pci device id which for now will be used by qca6174: bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x This removes the old method of having subsystem ids in ar->spec_board_id and using that in the board file name. Signed-off-by: Manikanta Pubbisetty [kvalo@qca.qualcomm.com: simplified the file format, rewrote commit log, other smaller changes] Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 249 +++++++++++++++++++++++++++----- drivers/net/wireless/ath/ath10k/core.h | 9 +- drivers/net/wireless/ath/ath10k/debug.c | 12 +- drivers/net/wireless/ath/ath10k/hw.h | 13 ++ drivers/net/wireless/ath/ath10k/pci.c | 16 +- 5 files changed, 250 insertions(+), 49 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index c295c919568b..99a4e145c9b6 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -541,11 +541,18 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) return ret; } -static void ath10k_core_free_firmware_files(struct ath10k *ar) +static void ath10k_core_free_board_files(struct ath10k *ar) { if (!IS_ERR(ar->board)) release_firmware(ar->board); + ar->board = NULL; + ar->board_data = NULL; + ar->board_len = 0; +} + +static void ath10k_core_free_firmware_files(struct ath10k *ar) +{ if (!IS_ERR(ar->otp)) release_firmware(ar->otp); @@ -557,10 +564,6 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) ath10k_swap_code_seg_release(ar); - ar->board = NULL; - ar->board_data = NULL; - ar->board_len = 0; - ar->otp = NULL; ar->otp_data = NULL; ar->otp_len = 0; @@ -591,68 +594,241 @@ static int ath10k_fetch_cal_file(struct ath10k *ar) return 0; } -static int ath10k_core_fetch_spec_board_file(struct ath10k *ar) +static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar) { - char filename[100]; - - scnprintf(filename, sizeof(filename), "board-%s-%s.bin", - ath10k_bus_str(ar->hif.bus), ar->spec_board_id); + if (!ar->hw_params.fw.board) { + ath10k_err(ar, "failed to find board file fw entry\n"); + return -EINVAL; + } - ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename); + ar->board = ath10k_fetch_fw_file(ar, + ar->hw_params.fw.dir, + ar->hw_params.fw.board); if (IS_ERR(ar->board)) return PTR_ERR(ar->board); ar->board_data = ar->board->data; ar->board_len = ar->board->size; - ar->spec_board_loaded = true; return 0; } -static int ath10k_core_fetch_generic_board_file(struct ath10k *ar) +static int ath10k_core_parse_bd_ie_board(struct ath10k *ar, + const void *buf, size_t buf_len, + const char *boardname) { - if (!ar->hw_params.fw.board) { - ath10k_err(ar, "failed to find board file fw entry\n"); - return -EINVAL; + const struct ath10k_fw_ie *hdr; + bool name_match_found; + int ret, board_ie_id; + size_t board_ie_len; + const void *board_ie_data; + + name_match_found = false; + + /* go through ATH10K_BD_IE_BOARD_ elements */ + while (buf_len > sizeof(struct ath10k_fw_ie)) { + hdr = buf; + board_ie_id = le32_to_cpu(hdr->id); + board_ie_len = le32_to_cpu(hdr->len); + board_ie_data = hdr->data; + + buf_len -= sizeof(*hdr); + buf += sizeof(*hdr); + + if (buf_len < ALIGN(board_ie_len, 4)) { + ath10k_err(ar, "invalid ATH10K_BD_IE_BOARD length: %zu < %zu\n", + buf_len, ALIGN(board_ie_len, 4)); + ret = -EINVAL; + goto out; + } + + switch (board_ie_id) { + case ATH10K_BD_IE_BOARD_NAME: + ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "board name", "", + board_ie_data, board_ie_len); + + if (board_ie_len != strlen(boardname)) + break; + + ret = memcmp(board_ie_data, boardname, strlen(boardname)); + if (ret) + break; + + name_match_found = true; + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "boot found match for name '%s'", + boardname); + break; + case ATH10K_BD_IE_BOARD_DATA: + if (!name_match_found) + /* no match found */ + break; + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "boot found board data for '%s'", + boardname); + + ar->board_data = board_ie_data; + ar->board_len = board_ie_len; + + ret = 0; + goto out; + default: + ath10k_warn(ar, "unknown ATH10K_BD_IE_BOARD found: %d\n", + board_ie_id); + break; + } + + /* jump over the padding */ + board_ie_len = ALIGN(board_ie_len, 4); + + buf_len -= board_ie_len; + buf += board_ie_len; } - ar->board = ath10k_fetch_fw_file(ar, - ar->hw_params.fw.dir, - ar->hw_params.fw.board); + /* no match found */ + ret = -ENOENT; + +out: + return ret; +} + +static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, + const char *boardname, + const char *filename) +{ + size_t len, magic_len, ie_len; + struct ath10k_fw_ie *hdr; + const u8 *data; + int ret, ie_id; + + ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename); if (IS_ERR(ar->board)) return PTR_ERR(ar->board); - ar->board_data = ar->board->data; - ar->board_len = ar->board->size; - ar->spec_board_loaded = false; + data = ar->board->data; + len = ar->board->size; + + /* magic has extra null byte padded */ + magic_len = strlen(ATH10K_BOARD_MAGIC) + 1; + if (len < magic_len) { + ath10k_err(ar, "failed to find magic value in %s/%s, file too short: %zu\n", + ar->hw_params.fw.dir, filename, len); + ret = -EINVAL; + goto err; + } + + if (memcmp(data, ATH10K_BOARD_MAGIC, magic_len)) { + ath10k_err(ar, "found invalid board magic\n"); + ret = -EINVAL; + goto err; + } + + /* magic is padded to 4 bytes */ + magic_len = ALIGN(magic_len, 4); + if (len < magic_len) { + ath10k_err(ar, "failed: %s/%s too small to contain board data, len: %zu\n", + ar->hw_params.fw.dir, filename, len); + ret = -EINVAL; + goto err; + } + + data += magic_len; + len -= magic_len; + + while (len > sizeof(struct ath10k_fw_ie)) { + hdr = (struct ath10k_fw_ie *)data; + ie_id = le32_to_cpu(hdr->id); + ie_len = le32_to_cpu(hdr->len); + + len -= sizeof(*hdr); + data = hdr->data; + + if (len < ALIGN(ie_len, 4)) { + ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n", + ie_id, ie_len, len); + ret = -EINVAL; + goto err; + } + + switch (ie_id) { + case ATH10K_BD_IE_BOARD: + ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, + boardname); + if (ret == -ENOENT) + /* no match found, continue */ + break; + else if (ret) + /* there was an error, bail out */ + goto err; + + /* board data found */ + goto out; + } + + /* jump over the padding */ + ie_len = ALIGN(ie_len, 4); + + len -= ie_len; + data += ie_len; + } + +out: + if (!ar->board_data || !ar->board_len) { + ath10k_err(ar, + "failed to fetch board data for %s from %s/%s\n", + ar->hw_params.fw.dir, boardname, filename); + ret = -ENODATA; + goto err; + } + + return 0; + +err: + ath10k_core_free_board_files(ar); + return ret; +} + +static int ath10k_core_create_board_name(struct ath10k *ar, char *name, + size_t name_len) +{ + scnprintf(name, name_len, + "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x", + ath10k_bus_str(ar->hif.bus), + ar->id.vendor, ar->id.device, + ar->id.subsystem_vendor, ar->id.subsystem_device); + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name); return 0; } static int ath10k_core_fetch_board_file(struct ath10k *ar) { + char boardname[100]; int ret; - if (strlen(ar->spec_board_id) > 0) { - ret = ath10k_core_fetch_spec_board_file(ar); - if (ret) { - ath10k_info(ar, "failed to load spec board file, falling back to generic: %d\n", - ret); - goto generic; - } - - ath10k_dbg(ar, ATH10K_DBG_BOOT, "found specific board file for %s\n", - ar->spec_board_id); - return 0; + ret = ath10k_core_create_board_name(ar, boardname, sizeof(boardname)); + if (ret) { + ath10k_err(ar, "failed to create board name: %d", ret); + return ret; } -generic: - ret = ath10k_core_fetch_generic_board_file(ar); + ar->bd_api = 2; + ret = ath10k_core_fetch_board_data_api_n(ar, boardname, + ATH10K_BOARD_API2_FILE); + if (!ret) + goto success; + + ar->bd_api = 1; + ret = ath10k_core_fetch_board_data_api_1(ar); if (ret) { - ath10k_err(ar, "failed to fetch generic board data: %d\n", ret); + ath10k_err(ar, "failed to fetch board data\n"); return ret; } +success: + ath10k_dbg(ar, ATH10K_DBG_BOOT, "using board api %d\n", ar->bd_api); return 0; } @@ -1626,6 +1802,7 @@ void ath10k_core_unregister(struct ath10k *ar) ath10k_testmode_destroy(ar); ath10k_core_free_firmware_files(ar); + ath10k_core_free_board_files(ar); ath10k_debug_unregister(ar); } diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 002de7113e63..af5c0d741659 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -676,10 +676,15 @@ struct ath10k { struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info; } swap; - char spec_board_id[100]; - bool spec_board_loaded; + struct { + u32 vendor; + u32 device; + u32 subsystem_vendor; + u32 subsystem_device; + } id; int fw_api; + int bd_api; enum ath10k_cal_mode cal_mode; struct { diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index f316efdbd6c3..7e8f6511b232 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -125,19 +125,21 @@ EXPORT_SYMBOL(ath10k_info); void ath10k_print_driver_info(struct ath10k *ar) { char fw_features[128] = {}; + char boardinfo[100]; ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features)); - ath10k_info(ar, "%s (0x%08x, 0x%08x%s%s%s) fw %s api %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n", + scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x", + ar->id.subsystem_vendor, ar->id.subsystem_device); + + ath10k_info(ar, "%s (0x%08x, 0x%08x %s) fw %s fwapi %d bdapi %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n", ar->hw_params.name, ar->target_version, ar->chip_id, - (strlen(ar->spec_board_id) > 0 ? ", " : ""), - ar->spec_board_id, - (strlen(ar->spec_board_id) > 0 && !ar->spec_board_loaded - ? " fallback" : ""), + boardinfo, ar->hw->wiphy->fw_version, ar->fw_api, + ar->bd_api, ar->htt.target_version_major, ar->htt.target_version_minor, ar->wmi.op_version, diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index bc421a5c5356..291df3d6d484 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -97,6 +97,9 @@ enum qca6174_chip_id_rev { /* includes also the null byte */ #define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K" +#define ATH10K_BOARD_MAGIC "QCA-ATH10K-BOARD" + +#define ATH10K_BOARD_API2_FILE "board-2.bin" #define REG_DUMP_COUNT_QCA988X 60 @@ -159,6 +162,16 @@ enum ath10k_fw_htt_op_version { ATH10K_FW_HTT_OP_VERSION_MAX, }; +enum ath10k_bd_ie_type { + /* contains sub IEs of enum ath10k_bd_ie_board_type */ + ATH10K_BD_IE_BOARD = 0, +}; + +enum ath10k_bd_ie_board_type { + ATH10K_BD_IE_BOARD_NAME = 0, + ATH10K_BD_IE_BOARD_DATA = 1, +}; + enum ath10k_hw_rev { ATH10K_HW_QCA988X, ATH10K_HW_QCA6174, diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 4401779af253..863117bd18ea 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -2918,7 +2918,9 @@ static int ath10k_pci_probe(struct pci_dev *pdev, return -ENOMEM; } - ath10k_dbg(ar, ATH10K_DBG_PCI, "pci probe\n"); + ath10k_dbg(ar, ATH10K_DBG_BOOT, "pci probe %04x:%04x %04x:%04x\n", + pdev->vendor, pdev->device, + pdev->subsystem_vendor, pdev->subsystem_device); ar_pci = ath10k_pci_priv(ar); ar_pci->pdev = pdev; @@ -2926,11 +2928,10 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar_pci->ar = ar; ar->dev_id = pci_dev->device; - if (pdev->subsystem_vendor || pdev->subsystem_device) - scnprintf(ar->spec_board_id, sizeof(ar->spec_board_id), - "%04x:%04x:%04x:%04x", - pdev->vendor, pdev->device, - pdev->subsystem_vendor, pdev->subsystem_device); + ar->id.vendor = pdev->vendor; + ar->id.device = pdev->device; + ar->id.subsystem_vendor = pdev->subsystem_vendor; + ar->id.subsystem_device = pdev->subsystem_device; spin_lock_init(&ar_pci->ce_lock); spin_lock_init(&ar_pci->ps_lock); @@ -3084,13 +3085,16 @@ MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API4_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API5_FILE); MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE); +MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_BOARD_API2_FILE); /* QCA6174 2.1 firmware files */ MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API4_FILE); MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API5_FILE); MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" QCA6174_HW_2_1_BOARD_DATA_FILE); +MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_BOARD_API2_FILE); /* QCA6174 3.1 firmware files */ MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE); MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API5_FILE); MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE); +MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_BOARD_API2_FILE); -- cgit v1.2.3 From db0984e51a187f5bbe41231af7e671cc12586346 Mon Sep 17 00:00:00 2001 From: Manikanta Pubbisetty Date: Fri, 9 Oct 2015 11:55:59 +0300 Subject: ath10k: select board data based on BMI chip id and board id QCA99X0 uses radio specific board names based on chip id and board id combinations. We get these IDs from the target using BMI after otp.bin has been started. This patch reorders the call to the function ath10k_core_fetch_board_file so that we have OTP binary before requesting for boardid-chipid. We get this OTP data after parsing firmware-N.bin. [kvalo@qca.qualcomm.com: try BMI_PARAM_GET_EEPROM_BOARD_ID with all boards and detect if command is not supported] Signed-off-by: Manikanta Pubbisetty Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/bmi.h | 10 +++++ drivers/net/wireless/ath/ath10k/core.c | 79 ++++++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath10k/core.h | 4 ++ drivers/net/wireless/ath/ath10k/debug.c | 8 +++- 4 files changed, 93 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h index df7c7616533b..7d3231acfb24 100644 --- a/drivers/net/wireless/ath/ath10k/bmi.h +++ b/drivers/net/wireless/ath/ath10k/bmi.h @@ -82,6 +82,16 @@ enum bmi_cmd_id { #define BMI_NVRAM_SEG_NAME_SZ 16 +#define BMI_PARAM_GET_EEPROM_BOARD_ID 0x10 + +#define ATH10K_BMI_BOARD_ID_FROM_OTP_MASK 0x7c00 +#define ATH10K_BMI_BOARD_ID_FROM_OTP_LSB 10 + +#define ATH10K_BMI_CHIP_ID_FROM_OTP_MASK 0x18000 +#define ATH10K_BMI_CHIP_ID_FROM_OTP_LSB 15 + +#define ATH10K_BMI_BOARD_ID_STATUS_MASK 0xff + struct bmi_cmd { __le32 id; /* enum bmi_cmd_id */ union { diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 99a4e145c9b6..13de3617d5ab 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -448,6 +448,56 @@ out: return ret; } +static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) +{ + u32 result, address; + u8 board_id, chip_id; + int ret; + + address = ar->hw_params.patch_load_addr; + + if (!ar->otp_data || !ar->otp_len) { + ath10k_warn(ar, + "failed to retrieve board id because of invalid otp\n"); + return -ENODATA; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "boot upload otp to 0x%x len %zd for board id\n", + address, ar->otp_len); + + ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len); + if (ret) { + ath10k_err(ar, "could not write otp for board id check: %d\n", + ret); + return ret; + } + + ret = ath10k_bmi_execute(ar, address, BMI_PARAM_GET_EEPROM_BOARD_ID, + &result); + if (ret) { + ath10k_err(ar, "could not execute otp for board id check: %d\n", + ret); + return ret; + } + + board_id = MS(result, ATH10K_BMI_BOARD_ID_FROM_OTP); + chip_id = MS(result, ATH10K_BMI_CHIP_ID_FROM_OTP); + + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "boot get otp board id result 0x%08x board_id %d chip_id %d\n", + result, board_id, chip_id); + + if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0) + return -EOPNOTSUPP; + + ar->id.bmi_ids_valid = true; + ar->id.bmi_board_id = board_id; + ar->id.bmi_chip_id = chip_id; + + return 0; +} + static int ath10k_download_and_run_otp(struct ath10k *ar) { u32 result, address = ar->hw_params.patch_load_addr; @@ -792,12 +842,22 @@ err: static int ath10k_core_create_board_name(struct ath10k *ar, char *name, size_t name_len) { + if (ar->id.bmi_ids_valid) { + scnprintf(name, name_len, + "bus=%s,bmi-chip-id=%d,bmi-board-id=%d", + ath10k_bus_str(ar->hif.bus), + ar->id.bmi_chip_id, + ar->id.bmi_board_id); + goto out; + } + scnprintf(name, name_len, "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x", ath10k_bus_str(ar->hif.bus), ar->id.vendor, ar->id.device, ar->id.subsystem_vendor, ar->id.subsystem_device); +out: ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name); return 0; @@ -1060,12 +1120,6 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) /* calibration file is optional, don't check for any errors */ ath10k_fetch_cal_file(ar); - ret = ath10k_core_fetch_board_file(ar); - if (ret) { - ath10k_err(ar, "failed to fetch board file: %d\n", ret); - return ret; - } - ar->fw_api = 5; ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); @@ -1675,6 +1729,19 @@ static int ath10k_core_probe_fw(struct ath10k *ar) goto err_power_down; } + ret = ath10k_core_get_board_id_from_otp(ar); + if (ret && ret != -EOPNOTSUPP) { + ath10k_err(ar, "failed to get board id from otp for qca99x0: %d\n", + ret); + return ret; + } + + ret = ath10k_core_fetch_board_file(ar); + if (ret) { + ath10k_err(ar, "failed to fetch board file: %d\n", ret); + goto err_free_firmware_files; + } + ret = ath10k_core_init_firmware_features(ar); if (ret) { ath10k_err(ar, "fatal problem with firmware features: %d\n", diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index af5c0d741659..7cc7cdd56c95 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -681,6 +681,10 @@ struct ath10k { u32 device; u32 subsystem_vendor; u32 subsystem_device; + + bool bmi_ids_valid; + u8 bmi_board_id; + u8 bmi_chip_id; } id; int fw_api; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 7e8f6511b232..eab71e2eb4d7 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -129,8 +129,12 @@ void ath10k_print_driver_info(struct ath10k *ar) ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features)); - scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x", - ar->id.subsystem_vendor, ar->id.subsystem_device); + if (ar->id.bmi_ids_valid) + scnprintf(boardinfo, sizeof(boardinfo), "bmi %d:%d", + ar->id.bmi_chip_id, ar->id.bmi_board_id); + else + scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x", + ar->id.subsystem_vendor, ar->id.subsystem_device); ath10k_info(ar, "%s (0x%08x, 0x%08x %s) fw %s fwapi %d bdapi %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n", ar->hw_params.name, -- cgit v1.2.3 From 83cfce87d91f06e37bd38f782f0714b406a95873 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Thu, 8 Oct 2015 16:03:03 +0530 Subject: ath10k: fix cleanup in ath10k_thermal_unregister First remove the 'cooling_device#n' syslink created for ath10k and then unregsiter from the thermal subsystem(cooling) Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/thermal.c b/drivers/net/wireless/ath/ath10k/thermal.c index 1a899d70dc5d..60fe562e3041 100644 --- a/drivers/net/wireless/ath/ath10k/thermal.c +++ b/drivers/net/wireless/ath/ath10k/thermal.c @@ -215,6 +215,6 @@ err_cooling_destroy: void ath10k_thermal_unregister(struct ath10k *ar) { - thermal_cooling_device_unregister(ar->thermal.cdev); sysfs_remove_link(&ar->dev->kobj, "cooling_device"); + thermal_cooling_device_unregister(ar->thermal.cdev); } -- cgit v1.2.3 From 0e339447cf2c8b5c742f9be8e2d73bc27b7ac9c4 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Thu, 8 Oct 2015 09:15:53 -0700 Subject: ath10k: cleanup ath10k_mac_register() error handling The logic in the error-handling path of ath10k_mac_register() is divergent from the logic in ath10k_mac_unregister(). Update the ath10k_mac_register() error handling logic to align with the ath10k_mac_unregister() logic. Signed-off-by: Jeff Johnson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 6bfaead35298..f00aafd2c768 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -7304,7 +7304,7 @@ int ath10k_mac_register(struct ath10k *ar) ath10k_reg_notifier); if (ret) { ath10k_err(ar, "failed to initialise regulatory: %i\n", ret); - goto err_free; + goto err_dfs_detector_exit; } ar->hw->wiphy->cipher_suites = cipher_suites; @@ -7313,7 +7313,7 @@ int ath10k_mac_register(struct ath10k *ar) ret = ieee80211_register_hw(ar->hw); if (ret) { ath10k_err(ar, "failed to register ieee80211: %d\n", ret); - goto err_free; + goto err_dfs_detector_exit; } if (!ath_is_world_regd(&ar->ath_common.regulatory)) { @@ -7327,10 +7327,16 @@ int ath10k_mac_register(struct ath10k *ar) err_unregister: ieee80211_unregister_hw(ar->hw); + +err_dfs_detector_exit: + if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) + ar->dfs_detector->exit(ar->dfs_detector); + err_free: kfree(ar->mac.sbands[IEEE80211_BAND_2GHZ].channels); kfree(ar->mac.sbands[IEEE80211_BAND_5GHZ].channels); + SET_IEEE80211_DEV(ar->hw, NULL); return ret; } -- cgit v1.2.3 From 1d55aa9c350b02a0c79d901518026e3af5d5b006 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Mon, 31 Aug 2015 19:54:41 -0400 Subject: i40e/i40evf: Add new link status defines Add the new Port link status bit and rename the link status to function link status. Change-ID: I71289327ae62638ce967b6ad40114caf998b6dab Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 4 +++- drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 785b3dbd22ca..02d52251ee7f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -1722,11 +1722,13 @@ struct i40e_aqc_get_link_status { u8 phy_type; /* i40e_aq_phy_type */ u8 link_speed; /* i40e_aq_link_speed */ u8 link_info; -#define I40E_AQ_LINK_UP 0x01 +#define I40E_AQ_LINK_UP 0x01 /* obsolete */ +#define I40E_AQ_LINK_UP_FUNCTION 0x01 #define I40E_AQ_LINK_FAULT 0x02 #define I40E_AQ_LINK_FAULT_TX 0x04 #define I40E_AQ_LINK_FAULT_RX 0x08 #define I40E_AQ_LINK_FAULT_REMOTE 0x10 +#define I40E_AQ_LINK_UP_PORT 0x20 #define I40E_AQ_MEDIA_AVAILABLE 0x40 #define I40E_AQ_SIGNAL_DETECT 0x80 u8 an_info; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index c8022092d369..fcb9ef34cc7a 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -1719,11 +1719,13 @@ struct i40e_aqc_get_link_status { u8 phy_type; /* i40e_aq_phy_type */ u8 link_speed; /* i40e_aq_link_speed */ u8 link_info; -#define I40E_AQ_LINK_UP 0x01 +#define I40E_AQ_LINK_UP 0x01 /* obsolete */ +#define I40E_AQ_LINK_UP_FUNCTION 0x01 #define I40E_AQ_LINK_FAULT 0x02 #define I40E_AQ_LINK_FAULT_TX 0x04 #define I40E_AQ_LINK_FAULT_RX 0x08 #define I40E_AQ_LINK_FAULT_REMOTE 0x10 +#define I40E_AQ_LINK_UP_PORT 0x20 #define I40E_AQ_MEDIA_AVAILABLE 0x40 #define I40E_AQ_SIGNAL_DETECT 0x80 u8 an_info; -- cgit v1.2.3 From 9f4ffc4426c4a4b6d4a84413e13efba6a72bf81d Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Mon, 31 Aug 2015 19:54:42 -0400 Subject: i40e: Make it clear a parameter is never used Flag the filter_mask parameter as __always_unused in the ndo_bridge_getlink function. Change-ID: Ifc1e99c7fb84bcbf81cf7b0ac891ad8ca956ffb2 Signed-off-by: Carolyn Wyborny Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index a484f2265524..d5d8b662ce9f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8336,7 +8336,8 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev, **/ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev, - u32 filter_mask, int nlflags) + u32 __always_unused filter_mask, + int nlflags) { struct i40e_netdev_priv *np = netdev_priv(dev); struct i40e_vsi *vsi = np->vsi; -- cgit v1.2.3 From ab252253e08c16de28ec0f6da0a7ff684a8fce98 Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Mon, 31 Aug 2015 19:54:43 -0400 Subject: i40e: Use BIT() macro for priority map parsing Replace one left over (1 << up) in the i40e_dcb.c file with the BIT() macro. Change-ID: I39492a400a2cee5ac566143a5b436cc478bea0db Signed-off-by: Neerav Parikh Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_dcb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c index 6fa07ef1651d..251a8416659b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c @@ -393,7 +393,7 @@ static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv, for (i = 0; i < dcbcfg->numapps; i++) { app = (struct i40e_cee_app_prio *)(tlv->tlvinfo + offset); for (up = 0; up < I40E_MAX_USER_PRIORITY; up++) { - if (app->prio_map & (1 << up)) + if (app->prio_map & BIT(up)) break; } dcbcfg->app[i].priority = up; -- cgit v1.2.3 From 14e52ee26bdfd6ad00075b66089b4b63fe36fff0 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Mon, 31 Aug 2015 19:54:44 -0400 Subject: i40evf: properly handle ndo_set_mac_address calls The driver was not correctly handling calls to its ndo_set_mac_address method. It did not properly check to see if the override would be allowed by the PF driver, and never removed the old address from its filter list. Add a new flag to the adapter struct which is set if the MAC address is assigned by the PF. Check this flag and don't allow the MAC address to be changed if it is set. Search for and properly remove the filter for the old MAC address when the new one is set. Change-ID: I817bf620c869c5a80e6a7eab65c9cbad1dc89799 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf.h | 1 + drivers/net/ethernet/intel/i40evf/i40evf_main.c | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index e7a223ea6c25..6f427113d621 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -220,6 +220,7 @@ struct i40evf_adapter { #define I40EVF_FLAG_RESET_NEEDED BIT(10) #define I40EVF_FLAG_WB_ON_ITR_CAPABLE BIT(11) #define I40EVF_FLAG_OUTER_UDP_CSUM_CAPABLE BIT(12) +#define I40EVF_FLAG_ADDR_SET_BY_PF BIT(13) /* duplicates for common code */ #define I40E_FLAG_FDIR_ATR_ENABLED 0 #define I40E_FLAG_DCB_ENABLED 0 diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index c00e4959f026..7ea7d2edb534 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -841,6 +841,15 @@ static int i40evf_set_mac(struct net_device *netdev, void *p) if (ether_addr_equal(netdev->dev_addr, addr->sa_data)) return 0; + if (adapter->flags & I40EVF_FLAG_ADDR_SET_BY_PF) + return -EPERM; + + f = i40evf_find_filter(adapter, hw->mac.addr); + if (f) { + f->remove = true; + adapter->aq_required |= I40EVF_FLAG_AQ_DEL_MAC_FILTER; + } + f = i40evf_add_filter(adapter, addr->sa_data); if (f) { ether_addr_copy(hw->mac.addr, addr->sa_data); @@ -2244,10 +2253,13 @@ static void i40evf_init_task(struct work_struct *work) if (!is_valid_ether_addr(adapter->hw.mac.addr)) { dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n", adapter->hw.mac.addr); - random_ether_addr(adapter->hw.mac.addr); + eth_hw_addr_random(netdev); + ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr); + } else { + adapter->flags |= I40EVF_FLAG_ADDR_SET_BY_PF; + ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr); + ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr); } - ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr); - ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr); init_timer(&adapter->watchdog_timer); adapter->watchdog_timer.function = &i40evf_watchdog_timer; -- cgit v1.2.3 From ac24382d41cc72541d5f8810336acf98a5e6d260 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Mon, 31 Aug 2015 19:54:45 -0400 Subject: i40e/i40evf: Add info to nvm info struct for OEM version data This patch adds a member to the nvm_info struct for oem_ver info to be output either by OID or ethtool. Change-ID: I1e5d513ae67622e2af17042924fdb4b5d6d85366 Signed-off-by: Carolyn Wyborny Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq.c | 9 ++++++++- drivers/net/ethernet/intel/i40e/i40e_type.h | 3 +++ drivers/net/ethernet/intel/i40evf/i40e_type.h | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c index fa2e916b23da..5c950e20f2ee 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c @@ -553,8 +553,9 @@ shutdown_arq_out: **/ i40e_status i40e_init_adminq(struct i40e_hw *hw) { - i40e_status ret_code; + u16 cfg_ptr, oem_hi, oem_lo; u16 eetrack_lo, eetrack_hi; + i40e_status ret_code; int retry = 0; /* verify input for valid configuration */ @@ -613,6 +614,12 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw) i40e_read_nvm_word(hw, I40E_SR_NVM_EETRACK_LO, &eetrack_lo); i40e_read_nvm_word(hw, I40E_SR_NVM_EETRACK_HI, &eetrack_hi); hw->nvm.eetrack = (eetrack_hi << 16) | eetrack_lo; + i40e_read_nvm_word(hw, I40E_SR_BOOT_CONFIG_PTR, &cfg_ptr); + i40e_read_nvm_word(hw, (cfg_ptr + I40E_NVM_OEM_VER_OFF), + &oem_hi); + i40e_read_nvm_word(hw, (cfg_ptr + (I40E_NVM_OEM_VER_OFF + 1)), + &oem_lo); + hw->nvm.oem_ver = ((u32)oem_hi << 16) | oem_lo; if (hw->aq.api_maj_ver > I40E_FW_API_VERSION_MAJOR) { ret_code = I40E_ERR_FIRMWARE_API_VERSION; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index d1ec5a4326cf..c8f7a5240d3c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -289,6 +289,7 @@ struct i40e_nvm_info { bool blank_nvm_mode; /* is NVM empty (no FW present)*/ u16 version; /* NVM package version */ u32 eetrack; /* NVM data version */ + u32 oem_ver; /* OEM version info */ }; /* definitions used in NVM update support */ @@ -1204,6 +1205,8 @@ struct i40e_hw_port_stats { #define I40E_SR_EMP_MODULE_PTR 0x0F #define I40E_SR_PBA_FLAGS 0x15 #define I40E_SR_PBA_BLOCK_PTR 0x16 +#define I40E_SR_BOOT_CONFIG_PTR 0x17 +#define I40E_NVM_OEM_VER_OFF 0x83 #define I40E_SR_NVM_DEV_STARTER_VERSION 0x18 #define I40E_SR_NVM_WAKE_ON_LAN 0x19 #define I40E_SR_ALTERNATE_SAN_MAC_ADDRESS_PTR 0x27 diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index a59b60ffd0ce..b3c65dd80dff 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -288,6 +288,7 @@ struct i40e_nvm_info { bool blank_nvm_mode; /* is NVM empty (no FW present)*/ u16 version; /* NVM package version */ u32 eetrack; /* NVM data version */ + u32 oem_ver; /* OEM version info */ }; /* definitions used in NVM update support */ @@ -1173,6 +1174,7 @@ struct i40e_hw_port_stats { /* Checksum and Shadow RAM pointers */ #define I40E_SR_NVM_CONTROL_WORD 0x00 #define I40E_SR_EMP_MODULE_PTR 0x0F +#define I40E_NVM_OEM_VER_OFF 0x83 #define I40E_SR_NVM_DEV_STARTER_VERSION 0x18 #define I40E_SR_NVM_WAKE_ON_LAN 0x19 #define I40E_SR_ALTERNATE_SAN_MAC_ADDRESS_PTR 0x27 -- cgit v1.2.3 From 41c3ae8b726e07e366fdb63e0e40a33528f1c3e4 Mon Sep 17 00:00:00 2001 From: Greg Bowers Date: Mon, 31 Aug 2015 19:54:46 -0400 Subject: i40e: Convert CEE App TLV selector to IEEE selector Changes the parsing of CEE App TLVs to fill in the App selector in struct i40e_dcbx_config with the IEEE App selector so the caller doesn't have to consider whether the App came from a CEE or IEEE DCBX negotiation. Change-ID: Ia7d9d664cde04d2ebcc9822fd22e4929c6edab3a Signed-off-by: Greg Bowers Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_dcb.c | 16 ++++++++++++---- drivers/net/ethernet/intel/i40e/i40e_type.h | 2 ++ 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c index 251a8416659b..2691277c0055 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c @@ -380,7 +380,7 @@ static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv, { u16 length, typelength, offset = 0; struct i40e_cee_app_prio *app; - u8 i, up; + u8 i, up, selector; typelength = ntohs(tlv->hdr.typelen); length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >> @@ -397,9 +397,17 @@ static void i40e_parse_cee_app_tlv(struct i40e_cee_feat_tlv *tlv, break; } dcbcfg->app[i].priority = up; - /* Get Selector from lower 2 bits */ - dcbcfg->app[i].selector = (app->upper_oui_sel & - I40E_CEE_APP_SELECTOR_MASK); + + /* Get Selector from lower 2 bits, and convert to IEEE */ + selector = (app->upper_oui_sel & I40E_CEE_APP_SELECTOR_MASK); + if (selector == I40E_CEE_APP_SEL_ETHTYPE) + dcbcfg->app[i].selector = I40E_APP_SEL_ETHTYPE; + else if (selector == I40E_CEE_APP_SEL_TCPIP) + dcbcfg->app[i].selector = I40E_APP_SEL_TCPIP; + else + /* Keep selector as it is for unknown types */ + dcbcfg->app[i].selector = selector; + dcbcfg->app[i].protocolid = ntohs(app->protocol); /* Move to next app */ offset += sizeof(*app); diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index c8f7a5240d3c..4ec3ffa904b1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -418,6 +418,8 @@ struct i40e_fc_info { #define I40E_APP_PROTOID_FIP 0x8914 #define I40E_APP_SEL_ETHTYPE 0x1 #define I40E_APP_SEL_TCPIP 0x2 +#define I40E_CEE_APP_SEL_ETHTYPE 0x0 +#define I40E_CEE_APP_SEL_TCPIP 0x1 /* CEE or IEEE 802.1Qaz ETS Configuration data */ struct i40e_dcb_ets_config { -- cgit v1.2.3 From e7e6cfce16e9184497716e004fc9e714a7411ad0 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Mon, 31 Aug 2015 19:54:47 -0400 Subject: i40e: remove redundant call This function call isn't needed here; the same function is already called by i40e_reset_vf. Change-ID: I96ccbf91b752965c9e28fe895d4c7d4c46e3ba44 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index ee747dc5d617..21022801a789 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -964,8 +964,6 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs) /* VF resources get allocated during reset */ i40e_reset_vf(&vfs[i], false); - /* enable VF vplan_qtable mappings */ - i40e_enable_vf_mappings(&vfs[i]); } pf->num_alloc_vfs = num_alloc_vfs; -- cgit v1.2.3 From 21be99ec4ed366e24d4735d230aa3086ff2bc6ed Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Mon, 31 Aug 2015 19:54:48 -0400 Subject: i40e: don't panic on VSI allocation failure In some circumstances, the firmware may fail to allocate a VSI for a VF. When this happens, the driver does not react well to the bad news and has a panic attack. To fix this problem, check the return value from i40e_alloc_vf_res and don't try to configure the device further if it failed. Additionally, explicitly clear the INIT bit when we free VF resources, so that this bit will be in the proper state in the failure case, and won't blow up elsewhere. Change-ID: I6a20ce2b59c3458fd832032e88fa28cd42500189 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 21022801a789..ae7548a5286e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -703,6 +703,7 @@ static void i40e_free_vf_res(struct i40e_vf *vf) */ vf->num_queue_pairs = 0; vf->vf_states = 0; + clear_bit(I40E_VF_STAT_INIT, &vf->vf_states); } /** @@ -841,11 +842,11 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr) complete_reset: /* reallocate VF resources to reset the VSI state */ i40e_free_vf_res(vf); - i40e_alloc_vf_res(vf); - i40e_enable_vf_mappings(vf); - set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states); - clear_bit(I40E_VF_STAT_DISABLED, &vf->vf_states); - + if (!i40e_alloc_vf_res(vf)) { + i40e_enable_vf_mappings(vf); + set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states); + clear_bit(I40E_VF_STAT_DISABLED, &vf->vf_states); + } /* tell the VF the reset is done */ wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE); i40e_flush(hw); -- cgit v1.2.3 From f0b44440148c257bb5b1872e8ff5d6591afc8f4f Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Mon, 31 Aug 2015 19:54:49 -0400 Subject: i40e: update fw version text string per previous product formats This patch moves the internal fw version and fw api version info to be output in probe. The nvm version, etrack and oem version info are now configured for output via ethtool -i. Change-ID: I05d490093a7137dbefcdef263d014d1e5c9e83d0 Signed-off-by: Carolyn Wyborny Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 10 ++++++---- drivers/net/ethernet/intel/i40e/i40e_main.c | 7 +++++++ 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index f26dcb23ebf9..cfe8f83b8144 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -107,6 +107,8 @@ #define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT) #define I40E_NVM_VERSION_HI_SHIFT 12 #define I40E_NVM_VERSION_HI_MASK (0xf << I40E_NVM_VERSION_HI_SHIFT) +#define I40E_OEM_VER_BUILD_MASK 0xff00 +#define I40E_OEM_VER_PATCH_MASK 0xff /* The values in here are decimal coded as hex as is the case in the NVM map*/ #define I40E_CURRENT_NVM_VERSION_HI 0x2 @@ -587,14 +589,14 @@ static inline char *i40e_fw_version_str(struct i40e_hw *hw) static char buf[32]; snprintf(buf, sizeof(buf), - "f%d.%d.%05d a%d.%d n%x.%02x e%x", - hw->aq.fw_maj_ver, hw->aq.fw_min_ver, hw->aq.fw_build, - hw->aq.api_maj_ver, hw->aq.api_min_ver, + "%x.%02x 0x%x %d.%d.%d", (hw->nvm.version & I40E_NVM_VERSION_HI_MASK) >> I40E_NVM_VERSION_HI_SHIFT, (hw->nvm.version & I40E_NVM_VERSION_LO_MASK) >> I40E_NVM_VERSION_LO_SHIFT, - (hw->nvm.eetrack & 0xffffff)); + hw->nvm.eetrack, (hw->nvm.oem_ver >> 24), + (hw->nvm.oem_ver & I40E_OEM_VER_BUILD_MASK) >> 8, + hw->nvm.oem_ver & I40E_OEM_VER_PATCH_MASK); return buf; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d5d8b662ce9f..45b32928cd89 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10064,6 +10064,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = i40e_init_adminq(hw); dev_info(&pdev->dev, "%s\n", i40e_fw_version_str(hw)); + + /* provide additional fw info, like api and ver */ + dev_info(&pdev->dev, "fw_version:%d.%d.%05d\n", + hw->aq.fw_maj_ver, hw->aq.fw_min_ver, hw->aq.fw_build); + dev_info(&pdev->dev, "fw api version:%d.%d\n", + hw->aq.api_maj_ver, hw->aq.api_min_ver); + if (err) { dev_info(&pdev->dev, "The driver for the device stopped because the NVM image is newer than expected. You must install the most recent version of the network driver.\n"); -- cgit v1.2.3 From d72c95ea422ab63c832a13c075cb73bc87a1276e Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Mon, 31 Aug 2015 19:54:50 -0400 Subject: i40e/i40evf: split device ids into a separate file Due to desires to write userland drivers, and other requests, without needing the rest of the include files, the device ids are pulled out into a standalone file. Change-ID: Ic0b047dbf9d4b0891892309c1f2079f56d9b60e8 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_devids.h | 55 +++++++++++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_type.h | 26 +----------- drivers/net/ethernet/intel/i40evf/i40e_devids.h | 55 +++++++++++++++++++++++++ drivers/net/ethernet/intel/i40evf/i40e_type.h | 26 +----------- 4 files changed, 112 insertions(+), 50 deletions(-) create mode 100644 drivers/net/ethernet/intel/i40e/i40e_devids.h create mode 100644 drivers/net/ethernet/intel/i40evf/i40e_devids.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_devids.h b/drivers/net/ethernet/intel/i40e/i40e_devids.h new file mode 100644 index 000000000000..c601ca4a610c --- /dev/null +++ b/drivers/net/ethernet/intel/i40e/i40e_devids.h @@ -0,0 +1,55 @@ +/******************************************************************************* + * + * Intel Ethernet Controller XL710 Family Linux Driver + * Copyright(c) 2013 - 2015 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * e1000-devel Mailing List + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + ******************************************************************************/ + +#ifndef _I40E_DEVIDS_H_ +#define _I40E_DEVIDS_H_ + +/* Device IDs */ +#define I40E_DEV_ID_SFP_XL710 0x1572 +#define I40E_DEV_ID_QEMU 0x1574 +#define I40E_DEV_ID_KX_A 0x157F +#define I40E_DEV_ID_KX_B 0x1580 +#define I40E_DEV_ID_KX_C 0x1581 +#define I40E_DEV_ID_QSFP_A 0x1583 +#define I40E_DEV_ID_QSFP_B 0x1584 +#define I40E_DEV_ID_QSFP_C 0x1585 +#define I40E_DEV_ID_10G_BASE_T 0x1586 +#define I40E_DEV_ID_20G_KR2 0x1587 +#define I40E_DEV_ID_20G_KR2_A 0x1588 +#define I40E_DEV_ID_10G_BASE_T4 0x1589 +#define I40E_DEV_ID_VF 0x154C +#define I40E_DEV_ID_VF_HV 0x1571 +#define I40E_DEV_ID_SFP_X722 0x37D0 +#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1 +#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2 +#define I40E_DEV_ID_X722_VF 0x37CD +#define I40E_DEV_ID_X722_VF_HV 0x37D9 + +#define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \ + (d) == I40E_DEV_ID_QSFP_B || \ + (d) == I40E_DEV_ID_QSFP_C) + +#endif /* _I40E_DEVIDS_H_ */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 4ec3ffa904b1..102d0c4ec83f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -33,31 +33,7 @@ #include "i40e_adminq.h" #include "i40e_hmc.h" #include "i40e_lan_hmc.h" - -/* Device IDs */ -#define I40E_DEV_ID_SFP_XL710 0x1572 -#define I40E_DEV_ID_QEMU 0x1574 -#define I40E_DEV_ID_KX_A 0x157F -#define I40E_DEV_ID_KX_B 0x1580 -#define I40E_DEV_ID_KX_C 0x1581 -#define I40E_DEV_ID_QSFP_A 0x1583 -#define I40E_DEV_ID_QSFP_B 0x1584 -#define I40E_DEV_ID_QSFP_C 0x1585 -#define I40E_DEV_ID_10G_BASE_T 0x1586 -#define I40E_DEV_ID_20G_KR2 0x1587 -#define I40E_DEV_ID_20G_KR2_A 0x1588 -#define I40E_DEV_ID_10G_BASE_T4 0x1589 -#define I40E_DEV_ID_VF 0x154C -#define I40E_DEV_ID_VF_HV 0x1571 -#define I40E_DEV_ID_SFP_X722 0x37D0 -#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1 -#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2 -#define I40E_DEV_ID_X722_VF 0x37CD -#define I40E_DEV_ID_X722_VF_HV 0x37D9 - -#define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \ - (d) == I40E_DEV_ID_QSFP_B || \ - (d) == I40E_DEV_ID_QSFP_C) +#include "i40e_devids.h" /* I40E_MASK is a macro used on 32 bit registers */ #define I40E_MASK(mask, shift) (mask << shift) diff --git a/drivers/net/ethernet/intel/i40evf/i40e_devids.h b/drivers/net/ethernet/intel/i40evf/i40e_devids.h new file mode 100644 index 000000000000..e6a39c9862e8 --- /dev/null +++ b/drivers/net/ethernet/intel/i40evf/i40e_devids.h @@ -0,0 +1,55 @@ +/******************************************************************************* + * + * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver + * Copyright(c) 2013 - 2015 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * e1000-devel Mailing List + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + ******************************************************************************/ + +#ifndef _I40E_DEVIDS_H_ +#define _I40E_DEVIDS_H_ + +/* Device IDs */ +#define I40E_DEV_ID_SFP_XL710 0x1572 +#define I40E_DEV_ID_QEMU 0x1574 +#define I40E_DEV_ID_KX_A 0x157F +#define I40E_DEV_ID_KX_B 0x1580 +#define I40E_DEV_ID_KX_C 0x1581 +#define I40E_DEV_ID_QSFP_A 0x1583 +#define I40E_DEV_ID_QSFP_B 0x1584 +#define I40E_DEV_ID_QSFP_C 0x1585 +#define I40E_DEV_ID_10G_BASE_T 0x1586 +#define I40E_DEV_ID_20G_KR2 0x1587 +#define I40E_DEV_ID_20G_KR2_A 0x1588 +#define I40E_DEV_ID_10G_BASE_T4 0x1589 +#define I40E_DEV_ID_VF 0x154C +#define I40E_DEV_ID_VF_HV 0x1571 +#define I40E_DEV_ID_SFP_X722 0x37D0 +#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1 +#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2 +#define I40E_DEV_ID_X722_VF 0x37CD +#define I40E_DEV_ID_X722_VF_HV 0x37D9 + +#define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \ + (d) == I40E_DEV_ID_QSFP_B || \ + (d) == I40E_DEV_ID_QSFP_C) + +#endif /* _I40E_DEVIDS_H_ */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index b3c65dd80dff..6dbace37431b 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -33,31 +33,7 @@ #include "i40e_adminq.h" #include "i40e_hmc.h" #include "i40e_lan_hmc.h" - -/* Device IDs */ -#define I40E_DEV_ID_SFP_XL710 0x1572 -#define I40E_DEV_ID_QEMU 0x1574 -#define I40E_DEV_ID_KX_A 0x157F -#define I40E_DEV_ID_KX_B 0x1580 -#define I40E_DEV_ID_KX_C 0x1581 -#define I40E_DEV_ID_QSFP_A 0x1583 -#define I40E_DEV_ID_QSFP_B 0x1584 -#define I40E_DEV_ID_QSFP_C 0x1585 -#define I40E_DEV_ID_10G_BASE_T 0x1586 -#define I40E_DEV_ID_20G_KR2 0x1587 -#define I40E_DEV_ID_20G_KR2_A 0x1588 -#define I40E_DEV_ID_10G_BASE_T4 0x1589 -#define I40E_DEV_ID_VF 0x154C -#define I40E_DEV_ID_VF_HV 0x1571 -#define I40E_DEV_ID_SFP_X722 0x37D0 -#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1 -#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2 -#define I40E_DEV_ID_X722_VF 0x37CD -#define I40E_DEV_ID_X722_VF_HV 0x37D9 - -#define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \ - (d) == I40E_DEV_ID_QSFP_B || \ - (d) == I40E_DEV_ID_QSFP_C) +#include "i40e_devids.h" /* I40E_MASK is a macro used on 32 bit registers */ #define I40E_MASK(mask, shift) (mask << shift) -- cgit v1.2.3 From 0a862b43acc6c5d38fd462baa9c76f9197907d73 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Mon, 31 Aug 2015 19:54:53 -0400 Subject: i40e/i40evf: Add module_types and update_link_info Add a module_types variable to the link_info struct to save the module information from get_phy_capabilities. This information can be used to determine which speeds the module supports. Also add a new function update_link_info which updates the module_types parameter and then calls get_link_info. This function should be called in place of get_link_info so that the module_types variable stays up-to-date with the rest of the link information. The EAS table does not reflect the values that are actually returned, so instead, basing these values on the Ethernet compliance codes specified in table 33 of SFF-8436 as these have been accurate. Use the new variable in ethtool to differentiate between a 10G/1G dual speed fiber module and a 10G only module. Change-ID: Ib7585cce321319c10ce15180054c41a6cbd41389 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 30 +++++++++++++++++++++--- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 16 +++++++++---- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_prototype.h | 1 + drivers/net/ethernet/intel/i40e/i40e_type.h | 18 ++++++++++++++ drivers/net/ethernet/intel/i40evf/i40e_type.h | 18 ++++++++++++++ 6 files changed, 76 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 2d012d9c22ad..ffd1cd0642f1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1717,14 +1717,14 @@ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures, *aq_failures |= I40E_SET_FC_AQ_FAIL_SET; } /* Update the link info */ - status = i40e_aq_get_link_info(hw, true, NULL, NULL); + status = i40e_update_link_info(hw); if (status) { /* Wait a little bit (on 40G cards it sometimes takes a really * long time for link to come back from the atomic reset) * and try once more */ msleep(1000); - status = i40e_aq_get_link_info(hw, true, NULL, NULL); + status = i40e_update_link_info(hw); } if (status) *aq_failures |= I40E_SET_FC_AQ_FAIL_UPDATE; @@ -2247,7 +2247,7 @@ i40e_status i40e_get_link_status(struct i40e_hw *hw, bool *link_up) i40e_status status = 0; if (hw->phy.get_link_info) { - status = i40e_aq_get_link_info(hw, true, NULL, NULL); + status = i40e_update_link_info(hw); if (status) i40e_debug(hw, I40E_DEBUG_LINK, "get link failed: status %d\n", @@ -2259,6 +2259,30 @@ i40e_status i40e_get_link_status(struct i40e_hw *hw, bool *link_up) return status; } +/** + * i40e_updatelink_status - update status of the HW network link + * @hw: pointer to the hw struct + **/ +i40e_status i40e_update_link_info(struct i40e_hw *hw) +{ + struct i40e_aq_get_phy_abilities_resp abilities; + i40e_status status = 0; + + status = i40e_aq_get_link_info(hw, true, NULL, NULL); + if (status) + return status; + + status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, + NULL); + if (status) + return status; + + memcpy(hw->phy.link_info.module_type, &abilities.module_type, + sizeof(hw->phy.link_info.module_type)); + + return status; +} + /** * i40e_aq_add_veb - Insert a VEB between the VSI and the MAC * @hw: pointer to the hw struct diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 148f61461076..46019e9c489e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -307,12 +307,18 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, case I40E_PHY_TYPE_10GBASE_LR: case I40E_PHY_TYPE_1000BASE_SX: case I40E_PHY_TYPE_1000BASE_LX: - ecmd->supported = SUPPORTED_10000baseT_Full | - SUPPORTED_1000baseT_Full; + ecmd->supported = SUPPORTED_10000baseT_Full; + if (hw_link_info->module_type[2] & + I40E_MODULE_TYPE_1000BASE_SX || + hw_link_info->module_type[2] & + I40E_MODULE_TYPE_1000BASE_LX) { + ecmd->supported |= SUPPORTED_1000baseT_Full; + if (hw_link_info->requested_speeds & + I40E_LINK_SPEED_1GB) + ecmd->advertising |= ADVERTISED_1000baseT_Full; + } if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) ecmd->advertising |= ADVERTISED_10000baseT_Full; - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) - ecmd->advertising |= ADVERTISED_1000baseT_Full; break; case I40E_PHY_TYPE_1000BASE_KX: ecmd->supported = SUPPORTED_Autoneg | @@ -704,7 +710,7 @@ static int i40e_set_settings(struct net_device *netdev, return -EAGAIN; } - status = i40e_aq_get_link_info(hw, true, NULL, NULL); + status = i40e_update_link_info(hw); if (status) netdev_info(netdev, "Updating link info failed with err %s aq_err %s\n", i40e_stat_str(hw, status), diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 45b32928cd89..dc80a5fbf389 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -9728,7 +9728,7 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) i40e_config_rss(pf); /* fill in link information and enable LSE reporting */ - i40e_aq_get_link_info(&pf->hw, true, NULL, NULL); + i40e_update_link_info(&pf->hw); i40e_link_event(pf); /* Initialize user-specific link properties */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index e51e1567837c..4454974b27e7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -259,6 +259,7 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw); void i40e_clear_hw(struct i40e_hw *hw); void i40e_clear_pxe_mode(struct i40e_hw *hw); i40e_status i40e_get_link_status(struct i40e_hw *hw, bool *link_up); +i40e_status i40e_update_link_info(struct i40e_hw *hw); i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr); i40e_status i40e_read_bw_from_alt_ram(struct i40e_hw *hw, u32 *max_bw, u32 *min_bw, bool *min_valid, diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 102d0c4ec83f..0a450ac27e8b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -167,6 +167,24 @@ struct i40e_link_status { bool crc_enable; u8 pacing; u8 requested_speeds; + u8 module_type[3]; + /* 1st byte: module identifier */ +#define I40E_MODULE_TYPE_SFP 0x03 +#define I40E_MODULE_TYPE_QSFP 0x0D + /* 2nd byte: ethernet compliance codes for 10/40G */ +#define I40E_MODULE_TYPE_40G_ACTIVE 0x01 +#define I40E_MODULE_TYPE_40G_LR4 0x02 +#define I40E_MODULE_TYPE_40G_SR4 0x04 +#define I40E_MODULE_TYPE_40G_CR4 0x08 +#define I40E_MODULE_TYPE_10G_BASE_SR 0x10 +#define I40E_MODULE_TYPE_10G_BASE_LR 0x20 +#define I40E_MODULE_TYPE_10G_BASE_LRM 0x40 +#define I40E_MODULE_TYPE_10G_BASE_ER 0x80 + /* 3rd byte: ethernet compliance codes for 1G */ +#define I40E_MODULE_TYPE_1000BASE_SX 0x01 +#define I40E_MODULE_TYPE_1000BASE_LX 0x02 +#define I40E_MODULE_TYPE_1000BASE_CX 0x04 +#define I40E_MODULE_TYPE_1000BASE_T 0x08 }; struct i40e_phy_info { diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 6dbace37431b..f3155e358235 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -167,6 +167,24 @@ struct i40e_link_status { bool crc_enable; u8 pacing; u8 requested_speeds; + u8 module_type[3]; + /* 1st byte: module identifier */ +#define I40E_MODULE_TYPE_SFP 0x03 +#define I40E_MODULE_TYPE_QSFP 0x0D + /* 2nd byte: ethernet compliance codes for 10/40G */ +#define I40E_MODULE_TYPE_40G_ACTIVE 0x01 +#define I40E_MODULE_TYPE_40G_LR4 0x02 +#define I40E_MODULE_TYPE_40G_SR4 0x04 +#define I40E_MODULE_TYPE_40G_CR4 0x08 +#define I40E_MODULE_TYPE_10G_BASE_SR 0x10 +#define I40E_MODULE_TYPE_10G_BASE_LR 0x20 +#define I40E_MODULE_TYPE_10G_BASE_LRM 0x40 +#define I40E_MODULE_TYPE_10G_BASE_ER 0x80 + /* 3rd byte: ethernet compliance codes for 1G */ +#define I40E_MODULE_TYPE_1000BASE_SX 0x01 +#define I40E_MODULE_TYPE_1000BASE_LX 0x02 +#define I40E_MODULE_TYPE_1000BASE_CX 0x04 +#define I40E_MODULE_TYPE_1000BASE_T 0x08 }; struct i40e_phy_info { -- cgit v1.2.3 From fc72dbce09989b268b20342473ddc8d77c8da350 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Tue, 1 Sep 2015 11:36:30 -0400 Subject: i40e/i40evf: Refactor PHY structure and add phy_capabilities enum Remove unused members in the PHY structure and add a new member to store all the capabilities the PHY has as reported by the FW. This information will help us determine what speeds the device is capable of when link is down. Also add an enum to decode the PHY types the NVM is capable of. Use the phy_types variable to determine what phy types are possible when link is down instead of device id as it will be more accurate. When on a backplane device, we do not support changing any settings, however we should display all the phy_types we are capable of so if we see a backplane dev ID set supported and advertised purely based on the phy_types variable. Change-ID: Ia75d560f1fcd30c54cbfb7458690c5867559a930 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 189 ++++++++++++++----------- drivers/net/ethernet/intel/i40e/i40e_main.c | 8 ++ drivers/net/ethernet/intel/i40e/i40e_type.h | 37 ++++- drivers/net/ethernet/intel/i40evf/i40e_type.h | 37 ++++- 4 files changed, 181 insertions(+), 90 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 46019e9c489e..831f97125c8f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -273,36 +273,12 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, case I40E_PHY_TYPE_40GBASE_AOC: ecmd->supported = SUPPORTED_40000baseCR4_Full; break; - case I40E_PHY_TYPE_40GBASE_KR4: - ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_40000baseKR4_Full; - ecmd->advertising = ADVERTISED_Autoneg | - ADVERTISED_40000baseKR4_Full; - break; case I40E_PHY_TYPE_40GBASE_SR4: ecmd->supported = SUPPORTED_40000baseSR4_Full; break; case I40E_PHY_TYPE_40GBASE_LR4: ecmd->supported = SUPPORTED_40000baseLR4_Full; break; - case I40E_PHY_TYPE_20GBASE_KR2: - ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_20000baseKR2_Full; - ecmd->advertising = ADVERTISED_Autoneg | - ADVERTISED_20000baseKR2_Full; - break; - case I40E_PHY_TYPE_10GBASE_KX4: - ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_10000baseKX4_Full; - ecmd->advertising = ADVERTISED_Autoneg | - ADVERTISED_10000baseKX4_Full; - break; - case I40E_PHY_TYPE_10GBASE_KR: - ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_10000baseKR_Full; - ecmd->advertising = ADVERTISED_Autoneg | - ADVERTISED_10000baseKR_Full; - break; case I40E_PHY_TYPE_10GBASE_SR: case I40E_PHY_TYPE_10GBASE_LR: case I40E_PHY_TYPE_1000BASE_SX: @@ -320,12 +296,6 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) ecmd->advertising |= ADVERTISED_10000baseT_Full; break; - case I40E_PHY_TYPE_1000BASE_KX: - ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_1000baseKX_Full; - ecmd->advertising = ADVERTISED_Autoneg | - ADVERTISED_1000baseKX_Full; - break; case I40E_PHY_TYPE_10GBASE_T: case I40E_PHY_TYPE_1000BASE_T: case I40E_PHY_TYPE_100BASE_TX: @@ -364,6 +334,15 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB) ecmd->advertising |= ADVERTISED_100baseT_Full; break; + /* Backplane is set based on supported phy types in get_settings + * so don't set anything here but don't warn either + */ + case I40E_PHY_TYPE_40GBASE_KR4: + case I40E_PHY_TYPE_20GBASE_KR2: + case I40E_PHY_TYPE_10GBASE_KR: + case I40E_PHY_TYPE_10GBASE_KX4: + case I40E_PHY_TYPE_1000BASE_KX: + break; default: /* if we got here and link is up something bad is afoot */ netdev_info(netdev, "WARNING: Link is up but PHY type 0x%x is not recognized.\n", @@ -403,64 +382,67 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, static void i40e_get_settings_link_down(struct i40e_hw *hw, struct ethtool_cmd *ecmd) { - struct i40e_link_status *hw_link_info = &hw->phy.link_info; + enum i40e_aq_capabilities_phy_type phy_types = hw->phy.phy_types; /* link is down and the driver needs to fall back on - * device ID to determine what kinds of info to display, - * it's mostly a guess that may change when link is up + * supported phy types to figure out what info to display */ - switch (hw->device_id) { - case I40E_DEV_ID_QSFP_A: - case I40E_DEV_ID_QSFP_B: - case I40E_DEV_ID_QSFP_C: - /* pluggable QSFP */ - ecmd->supported = SUPPORTED_40000baseSR4_Full | - SUPPORTED_40000baseCR4_Full | - SUPPORTED_40000baseLR4_Full; - ecmd->advertising = ADVERTISED_40000baseSR4_Full | - ADVERTISED_40000baseCR4_Full | - ADVERTISED_40000baseLR4_Full; - break; - case I40E_DEV_ID_KX_B: - /* backplane 40G */ - ecmd->supported = SUPPORTED_40000baseKR4_Full; - ecmd->advertising = ADVERTISED_40000baseKR4_Full; - break; - case I40E_DEV_ID_KX_C: - /* backplane 10G */ - ecmd->supported = SUPPORTED_10000baseKR_Full; - ecmd->advertising = ADVERTISED_10000baseKR_Full; - break; - case I40E_DEV_ID_10G_BASE_T: - case I40E_DEV_ID_10G_BASE_T4: - ecmd->supported = SUPPORTED_10000baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_100baseT_Full; - /* Figure out what has been requested */ - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) - ecmd->advertising |= ADVERTISED_10000baseT_Full; - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) - ecmd->advertising |= ADVERTISED_1000baseT_Full; - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB) - ecmd->advertising |= ADVERTISED_100baseT_Full; - break; - case I40E_DEV_ID_20G_KR2: - case I40E_DEV_ID_20G_KR2_A: - /* backplane 20G */ - ecmd->supported = SUPPORTED_20000baseKR2_Full; - ecmd->advertising = ADVERTISED_20000baseKR2_Full; - break; - default: - /* all the rest are 10G/1G */ - ecmd->supported = SUPPORTED_10000baseT_Full | - SUPPORTED_1000baseT_Full; - /* Figure out what has been requested */ - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) - ecmd->advertising |= ADVERTISED_10000baseT_Full; - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) - ecmd->advertising |= ADVERTISED_1000baseT_Full; - break; + ecmd->supported = 0x0; + ecmd->advertising = 0x0; + if (phy_types & I40E_CAP_PHY_TYPE_SGMII) { + ecmd->supported |= SUPPORTED_Autoneg | + SUPPORTED_1000baseT_Full | + SUPPORTED_100baseT_Full; + ecmd->advertising |= ADVERTISED_Autoneg | + ADVERTISED_1000baseT_Full | + ADVERTISED_100baseT_Full; + } + if (phy_types & I40E_CAP_PHY_TYPE_XAUI || + phy_types & I40E_CAP_PHY_TYPE_XFI || + phy_types & I40E_CAP_PHY_TYPE_SFI || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_AOC) + ecmd->supported |= SUPPORTED_10000baseT_Full; + if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_T || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_SR || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_LR) { + ecmd->supported |= SUPPORTED_Autoneg | + SUPPORTED_10000baseT_Full; + ecmd->advertising |= ADVERTISED_Autoneg | + ADVERTISED_10000baseT_Full; + } + if (phy_types & I40E_CAP_PHY_TYPE_XLAUI || + phy_types & I40E_CAP_PHY_TYPE_XLPPI || + phy_types & I40E_CAP_PHY_TYPE_40GBASE_AOC) + ecmd->supported |= SUPPORTED_40000baseCR4_Full; + if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_CR4_CU || + phy_types & I40E_CAP_PHY_TYPE_40GBASE_CR4) { + ecmd->supported |= SUPPORTED_Autoneg | + SUPPORTED_40000baseCR4_Full; + ecmd->advertising |= ADVERTISED_Autoneg | + ADVERTISED_40000baseCR4_Full; } + if (phy_types & I40E_CAP_PHY_TYPE_100BASE_TX) { + ecmd->supported |= SUPPORTED_Autoneg | + SUPPORTED_100baseT_Full; + ecmd->advertising |= ADVERTISED_Autoneg | + ADVERTISED_100baseT_Full; + } + if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_T || + phy_types & I40E_CAP_PHY_TYPE_1000BASE_SX || + phy_types & I40E_CAP_PHY_TYPE_1000BASE_LX || + phy_types & I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL) { + ecmd->supported |= SUPPORTED_Autoneg | + SUPPORTED_1000baseT_Full; + ecmd->advertising |= ADVERTISED_Autoneg | + ADVERTISED_1000baseT_Full; + } + if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_SR4) + ecmd->supported |= SUPPORTED_40000baseSR4_Full; + if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_LR4) + ecmd->supported |= SUPPORTED_40000baseLR4_Full; /* With no link speed and duplex are unknown */ ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); @@ -490,6 +472,37 @@ static int i40e_get_settings(struct net_device *netdev, /* Now set the settings that don't rely on link being up/down */ + /* For backplane, supported and advertised are only reliant on the + * phy types the NVM specifies are supported. + */ + if (hw->device_id == I40E_DEV_ID_KX_B || + hw->device_id == I40E_DEV_ID_KX_C || + hw->device_id == I40E_DEV_ID_20G_KR2 || + hw->device_id == I40E_DEV_ID_20G_KR2_A) { + ecmd->supported = SUPPORTED_Autoneg; + ecmd->advertising = ADVERTISED_Autoneg; + if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_40GBASE_KR4) { + ecmd->supported |= SUPPORTED_40000baseKR4_Full; + ecmd->advertising |= ADVERTISED_40000baseKR4_Full; + } + if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_20GBASE_KR2) { + ecmd->supported |= SUPPORTED_20000baseKR2_Full; + ecmd->advertising |= ADVERTISED_20000baseKR2_Full; + } + if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR) { + ecmd->supported |= SUPPORTED_10000baseKR_Full; + ecmd->advertising |= ADVERTISED_10000baseKR_Full; + } + if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4) { + ecmd->supported |= SUPPORTED_10000baseKX4_Full; + ecmd->advertising |= ADVERTISED_10000baseKX4_Full; + } + if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_1000BASE_KX) { + ecmd->supported |= SUPPORTED_1000baseKX_Full; + ecmd->advertising |= ADVERTISED_1000baseKX_Full; + } + } + /* Set autoneg settings */ ecmd->autoneg = ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ? AUTONEG_ENABLE : AUTONEG_DISABLE); @@ -589,6 +602,14 @@ static int i40e_set_settings(struct net_device *netdev, hw->phy.link_info.link_info & I40E_AQ_LINK_UP) return -EOPNOTSUPP; + if (hw->device_id == I40E_DEV_ID_KX_B || + hw->device_id == I40E_DEV_ID_KX_C || + hw->device_id == I40E_DEV_ID_20G_KR2 || + hw->device_id == I40E_DEV_ID_20G_KR2_A) { + netdev_info(netdev, "Changing settings is not supported on backplane.\n"); + return -EOPNOTSUPP; + } + /* get our own copy of the bits to check against */ memset(&safe_ecmd, 0, sizeof(struct ethtool_cmd)); i40e_get_settings(netdev, &safe_ecmd); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index dc80a5fbf389..7158ff2035b6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10338,6 +10338,14 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); pf->hw.phy.link_info.requested_speeds = abilities.link_speed; + /* get the supported phy types from the fw */ + err = i40e_aq_get_phy_capabilities(hw, false, true, &abilities, NULL); + if (err) + dev_dbg(&pf->pdev->dev, "get supported phy types ret = %s last_status = %s\n", + i40e_stat_str(&pf->hw, err), + i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); + pf->hw.phy.phy_types = le32_to_cpu(abilities.phy_type); + /* print a string summarizing features */ i40e_print_features(pf); diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 0a450ac27e8b..6f69576de59d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -187,14 +187,45 @@ struct i40e_link_status { #define I40E_MODULE_TYPE_1000BASE_T 0x08 }; +enum i40e_aq_capabilities_phy_type { + I40E_CAP_PHY_TYPE_SGMII = BIT(I40E_PHY_TYPE_SGMII), + I40E_CAP_PHY_TYPE_1000BASE_KX = BIT(I40E_PHY_TYPE_1000BASE_KX), + I40E_CAP_PHY_TYPE_10GBASE_KX4 = BIT(I40E_PHY_TYPE_10GBASE_KX4), + I40E_CAP_PHY_TYPE_10GBASE_KR = BIT(I40E_PHY_TYPE_10GBASE_KR), + I40E_CAP_PHY_TYPE_40GBASE_KR4 = BIT(I40E_PHY_TYPE_40GBASE_KR4), + I40E_CAP_PHY_TYPE_XAUI = BIT(I40E_PHY_TYPE_XAUI), + I40E_CAP_PHY_TYPE_XFI = BIT(I40E_PHY_TYPE_XFI), + I40E_CAP_PHY_TYPE_SFI = BIT(I40E_PHY_TYPE_SFI), + I40E_CAP_PHY_TYPE_XLAUI = BIT(I40E_PHY_TYPE_XLAUI), + I40E_CAP_PHY_TYPE_XLPPI = BIT(I40E_PHY_TYPE_XLPPI), + I40E_CAP_PHY_TYPE_40GBASE_CR4_CU = BIT(I40E_PHY_TYPE_40GBASE_CR4_CU), + I40E_CAP_PHY_TYPE_10GBASE_CR1_CU = BIT(I40E_PHY_TYPE_10GBASE_CR1_CU), + I40E_CAP_PHY_TYPE_10GBASE_AOC = BIT(I40E_PHY_TYPE_10GBASE_AOC), + I40E_CAP_PHY_TYPE_40GBASE_AOC = BIT(I40E_PHY_TYPE_40GBASE_AOC), + I40E_CAP_PHY_TYPE_100BASE_TX = BIT(I40E_PHY_TYPE_100BASE_TX), + I40E_CAP_PHY_TYPE_1000BASE_T = BIT(I40E_PHY_TYPE_1000BASE_T), + I40E_CAP_PHY_TYPE_10GBASE_T = BIT(I40E_PHY_TYPE_10GBASE_T), + I40E_CAP_PHY_TYPE_10GBASE_SR = BIT(I40E_PHY_TYPE_10GBASE_SR), + I40E_CAP_PHY_TYPE_10GBASE_LR = BIT(I40E_PHY_TYPE_10GBASE_LR), + I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU = BIT(I40E_PHY_TYPE_10GBASE_SFPP_CU), + I40E_CAP_PHY_TYPE_10GBASE_CR1 = BIT(I40E_PHY_TYPE_10GBASE_CR1), + I40E_CAP_PHY_TYPE_40GBASE_CR4 = BIT(I40E_PHY_TYPE_40GBASE_CR4), + I40E_CAP_PHY_TYPE_40GBASE_SR4 = BIT(I40E_PHY_TYPE_40GBASE_SR4), + I40E_CAP_PHY_TYPE_40GBASE_LR4 = BIT(I40E_PHY_TYPE_40GBASE_LR4), + I40E_CAP_PHY_TYPE_1000BASE_SX = BIT(I40E_PHY_TYPE_1000BASE_SX), + I40E_CAP_PHY_TYPE_1000BASE_LX = BIT(I40E_PHY_TYPE_1000BASE_LX), + I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL = + BIT(I40E_PHY_TYPE_1000BASE_T_OPTICAL), + I40E_CAP_PHY_TYPE_20GBASE_KR2 = BIT(I40E_PHY_TYPE_20GBASE_KR2) +}; + struct i40e_phy_info { struct i40e_link_status link_info; struct i40e_link_status link_info_old; - u32 autoneg_advertised; - u32 phy_id; - u32 module_type; bool get_link_info; enum i40e_media_type media_type; + /* all the phy types the NVM is capable of */ + enum i40e_aq_capabilities_phy_type phy_types; }; #define I40E_HW_CAP_MAX_GPIO 30 diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index f3155e358235..85af3b48effc 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -187,14 +187,45 @@ struct i40e_link_status { #define I40E_MODULE_TYPE_1000BASE_T 0x08 }; +enum i40e_aq_capabilities_phy_type { + I40E_CAP_PHY_TYPE_SGMII = BIT(I40E_PHY_TYPE_SGMII), + I40E_CAP_PHY_TYPE_1000BASE_KX = BIT(I40E_PHY_TYPE_1000BASE_KX), + I40E_CAP_PHY_TYPE_10GBASE_KX4 = BIT(I40E_PHY_TYPE_10GBASE_KX4), + I40E_CAP_PHY_TYPE_10GBASE_KR = BIT(I40E_PHY_TYPE_10GBASE_KR), + I40E_CAP_PHY_TYPE_40GBASE_KR4 = BIT(I40E_PHY_TYPE_40GBASE_KR4), + I40E_CAP_PHY_TYPE_XAUI = BIT(I40E_PHY_TYPE_XAUI), + I40E_CAP_PHY_TYPE_XFI = BIT(I40E_PHY_TYPE_XFI), + I40E_CAP_PHY_TYPE_SFI = BIT(I40E_PHY_TYPE_SFI), + I40E_CAP_PHY_TYPE_XLAUI = BIT(I40E_PHY_TYPE_XLAUI), + I40E_CAP_PHY_TYPE_XLPPI = BIT(I40E_PHY_TYPE_XLPPI), + I40E_CAP_PHY_TYPE_40GBASE_CR4_CU = BIT(I40E_PHY_TYPE_40GBASE_CR4_CU), + I40E_CAP_PHY_TYPE_10GBASE_CR1_CU = BIT(I40E_PHY_TYPE_10GBASE_CR1_CU), + I40E_CAP_PHY_TYPE_10GBASE_AOC = BIT(I40E_PHY_TYPE_10GBASE_AOC), + I40E_CAP_PHY_TYPE_40GBASE_AOC = BIT(I40E_PHY_TYPE_40GBASE_AOC), + I40E_CAP_PHY_TYPE_100BASE_TX = BIT(I40E_PHY_TYPE_100BASE_TX), + I40E_CAP_PHY_TYPE_1000BASE_T = BIT(I40E_PHY_TYPE_1000BASE_T), + I40E_CAP_PHY_TYPE_10GBASE_T = BIT(I40E_PHY_TYPE_10GBASE_T), + I40E_CAP_PHY_TYPE_10GBASE_SR = BIT(I40E_PHY_TYPE_10GBASE_SR), + I40E_CAP_PHY_TYPE_10GBASE_LR = BIT(I40E_PHY_TYPE_10GBASE_LR), + I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU = BIT(I40E_PHY_TYPE_10GBASE_SFPP_CU), + I40E_CAP_PHY_TYPE_10GBASE_CR1 = BIT(I40E_PHY_TYPE_10GBASE_CR1), + I40E_CAP_PHY_TYPE_40GBASE_CR4 = BIT(I40E_PHY_TYPE_40GBASE_CR4), + I40E_CAP_PHY_TYPE_40GBASE_SR4 = BIT(I40E_PHY_TYPE_40GBASE_SR4), + I40E_CAP_PHY_TYPE_40GBASE_LR4 = BIT(I40E_PHY_TYPE_40GBASE_LR4), + I40E_CAP_PHY_TYPE_1000BASE_SX = BIT(I40E_PHY_TYPE_1000BASE_SX), + I40E_CAP_PHY_TYPE_1000BASE_LX = BIT(I40E_PHY_TYPE_1000BASE_LX), + I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL = + BIT(I40E_PHY_TYPE_1000BASE_T_OPTICAL), + I40E_CAP_PHY_TYPE_20GBASE_KR2 = BIT(I40E_PHY_TYPE_20GBASE_KR2) +}; + struct i40e_phy_info { struct i40e_link_status link_info; struct i40e_link_status link_info_old; - u32 autoneg_advertised; - u32 phy_id; - u32 module_type; bool get_link_info; enum i40e_media_type media_type; + /* all the phy types the NVM is capable of */ + enum i40e_aq_capabilities_phy_type phy_types; }; #define I40E_HW_CAP_MAX_GPIO 30 -- cgit v1.2.3 From 06a24dd6c29a814a81595861c2cc681329c56bfc Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Mon, 31 Aug 2015 19:54:55 -0400 Subject: i40e/i40evf: Bump i40e version to 1.3.25 and i40evf to 1.3.17 Bump. Change-ID: If3cd42f6c1b9546beed60faf9c79faab35216f58 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 7158ff2035b6..f7281400bdd1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -39,7 +39,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 3 -#define DRV_VERSION_BUILD 21 +#define DRV_VERSION_BUILD 25 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 7ea7d2edb534..69767c0d9194 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -34,7 +34,7 @@ char i40evf_driver_name[] = "i40evf"; static const char i40evf_driver_string[] = "Intel(R) XL710/X710 Virtual Function Network Driver"; -#define DRV_VERSION "1.3.13" +#define DRV_VERSION "1.3.17" const char i40evf_driver_version[] = DRV_VERSION; static const char i40evf_copyright[] = "Copyright (c) 2013 - 2015 Intel Corporation."; -- cgit v1.2.3 From f079fa005aae08ee0e1bc32699874ff4f02e11c1 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 20 Aug 2015 15:31:20 -0700 Subject: ixgbe: add flow control ethertype to the anti-spoofing filter This patch makes sure that flow control packets initiated by the VF are dropped and reported as spoofed. Flow control packets can be used to limit the throughput or as DOS attack when generated from a VF. Flow control is not supported per VF hence any pause frames generated from a VF are considered malicious. Also cleaned up indentation and some redundant comments. Signed-off-by: Emil Tantilov Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 16 +++++++++++----- drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 4 ++++ 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 191003901adb..c4608f893f95 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3723,14 +3723,20 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter) hw->mac.ops.set_mac_anti_spoofing(hw, (adapter->num_vfs != 0), adapter->num_vfs); - /* Ensure LLDP is set for Ethertype Antispoofing if we will be + /* Ensure LLDP and FC is set for Ethertype Antispoofing if we will be * calling set_ethertype_anti_spoofing for each VF in loop below */ - if (hw->mac.ops.set_ethertype_anti_spoofing) + if (hw->mac.ops.set_ethertype_anti_spoofing) { IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_LLDP), - (IXGBE_ETQF_FILTER_EN | /* enable filter */ - IXGBE_ETQF_TX_ANTISPOOF | /* tx antispoof */ - IXGBE_ETH_P_LLDP)); /* LLDP eth type */ + (IXGBE_ETQF_FILTER_EN | + IXGBE_ETQF_TX_ANTISPOOF | + IXGBE_ETH_P_LLDP)); + + IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_FC), + (IXGBE_ETQF_FILTER_EN | + IXGBE_ETQF_TX_ANTISPOOF | + ETH_P_PAUSE)); + } /* For VFs that have spoof checking turned off */ for (i = 0; i < adapter->num_vfs; i++) { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 939c90c4ff39..995f03107eac 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -1752,6 +1752,9 @@ enum { * FCoE (0x8906): Filter 2 * 1588 (0x88f7): Filter 3 * FIP (0x8914): Filter 4 + * LLDP (0x88CC): Filter 5 + * LACP (0x8809): Filter 6 + * FC (0x8808): Filter 7 */ #define IXGBE_ETQF_FILTER_EAPOL 0 #define IXGBE_ETQF_FILTER_FCOE 2 @@ -1759,6 +1762,7 @@ enum { #define IXGBE_ETQF_FILTER_FIP 4 #define IXGBE_ETQF_FILTER_LLDP 5 #define IXGBE_ETQF_FILTER_LACP 6 +#define IXGBE_ETQF_FILTER_FC 7 /* VLAN Control Bit Masks */ #define IXGBE_VLNCTRL_VET 0x0000FFFF /* bits 0-15 */ -- cgit v1.2.3 From f6f19f8bb9afcd0e9970fe51b5affa3063af4499 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 24 Aug 2015 17:01:58 -0700 Subject: fm10k: use snprintf() instead of sprintf() to avoid buffer overflow Signed-off-by: Jacob Keller Signed-off-by: Bruce Allan Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c | 6 +++--- drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c b/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c index 08ecf43dffc7..5304bc1fbecd 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_debugfs.c @@ -176,7 +176,7 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector) return; /* Generate a folder for each q_vector */ - sprintf(name, "q_vector.%03d", q_vector->v_idx); + snprintf(name, sizeof(name), "q_vector.%03d", q_vector->v_idx); q_vector->dbg_q_vector = debugfs_create_dir(name, interface->dbg_intfc); if (!q_vector->dbg_q_vector) @@ -186,7 +186,7 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector) for (i = 0; i < q_vector->tx.count; i++) { struct fm10k_ring *ring = &q_vector->tx.ring[i]; - sprintf(name, "tx_ring.%03d", ring->queue_index); + snprintf(name, sizeof(name), "tx_ring.%03d", ring->queue_index); debugfs_create_file(name, 0600, q_vector->dbg_q_vector, ring, @@ -197,7 +197,7 @@ void fm10k_dbg_q_vector_init(struct fm10k_q_vector *q_vector) for (i = 0; i < q_vector->rx.count; i++) { struct fm10k_ring *ring = &q_vector->rx.ring[i]; - sprintf(name, "rx_ring.%03d", ring->queue_index); + snprintf(name, sizeof(name), "rx_ring.%03d", ring->queue_index); debugfs_create_file(name, 0600, q_vector->dbg_q_vector, ring, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index 4ef2fbd22911..447a5f8da42f 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -206,13 +206,13 @@ static void fm10k_get_stat_strings(struct net_device *dev, u8 *data) } for (i = 0; i < interface->hw.mac.max_queues; i++) { - sprintf(p, "tx_queue_%u_packets", i); + snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_packets", i); p += ETH_GSTRING_LEN; - sprintf(p, "tx_queue_%u_bytes", i); + snprintf(p, ETH_GSTRING_LEN, "tx_queue_%u_bytes", i); p += ETH_GSTRING_LEN; - sprintf(p, "rx_queue_%u_packets", i); + snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_packets", i); p += ETH_GSTRING_LEN; - sprintf(p, "rx_queue_%u_bytes", i); + snprintf(p, ETH_GSTRING_LEN, "rx_queue_%u_bytes", i); p += ETH_GSTRING_LEN; } } -- cgit v1.2.3 From b4a5127b03b7f0b06dcaf08a878ffc93ad53fa82 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 24 Aug 2015 17:02:00 -0700 Subject: fm10k: do not use enum as boolean Check for actual value NETREG_UNINITIALIZED in case it ever changes from the current value of zero. Signed-off-by: Jacob Keller Signed-off-by: Bruce Allan Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 2f47bfe6cc90..537d81a6d738 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -1905,7 +1905,7 @@ static void fm10k_init_reta(struct fm10k_intfc *interface) u32 reta, base; /* If the netdev is initialized we have to maintain table if possible */ - if (interface->netdev->reg_state) { + if (interface->netdev->reg_state != NETREG_UNINITIALIZED) { for (i = FM10K_RETA_SIZE; i--;) { reta = interface->reta[i]; if ((((reta << 24) >> 24) < rss_i) && -- cgit v1.2.3 From f1d2b4d338bf090296f67830025228872fd52513 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 7 Sep 2015 15:59:16 -0500 Subject: rtlwifi: rtl818x: Move drivers into new realtek directory Now that a new mac80211-based driver for Realtek devices has been submitted, it is time to reorganize the directories. Rather than having directories rtlwifi and rtl818x be in drivers/net/wireless/, they will now be in drivers/net/wireless/realtek/. This change simplifies the directory structure, but does not result in any configuration changes that are visable to the user. Signed-off-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/Kconfig | 6 +- drivers/net/wireless/Makefile | 4 +- drivers/net/wireless/realtek/Makefile | 8 + drivers/net/wireless/realtek/rtl818x/Kconfig | 88 + drivers/net/wireless/realtek/rtl818x/Makefile | 2 + .../net/wireless/realtek/rtl818x/rtl8180/Makefile | 5 + drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 1991 ++++++++ .../net/wireless/realtek/rtl818x/rtl8180/grf5101.c | 190 + .../net/wireless/realtek/rtl818x/rtl8180/grf5101.h | 28 + .../net/wireless/realtek/rtl818x/rtl8180/max2820.c | 168 + .../net/wireless/realtek/rtl818x/rtl8180/max2820.h | 28 + .../net/wireless/realtek/rtl818x/rtl8180/rtl8180.h | 185 + .../net/wireless/realtek/rtl818x/rtl8180/rtl8225.c | 770 ++++ .../net/wireless/realtek/rtl818x/rtl8180/rtl8225.h | 23 + .../wireless/realtek/rtl818x/rtl8180/rtl8225se.c | 475 ++ .../wireless/realtek/rtl818x/rtl8180/rtl8225se.h | 61 + .../net/wireless/realtek/rtl818x/rtl8180/sa2400.c | 228 + .../net/wireless/realtek/rtl818x/rtl8180/sa2400.h | 36 + .../net/wireless/realtek/rtl818x/rtl8187/Makefile | 5 + drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c | 1684 +++++++ .../net/wireless/realtek/rtl818x/rtl8187/leds.c | 245 + .../net/wireless/realtek/rtl818x/rtl8187/leds.h | 59 + .../net/wireless/realtek/rtl818x/rtl8187/rfkill.c | 64 + .../net/wireless/realtek/rtl818x/rtl8187/rfkill.h | 8 + .../net/wireless/realtek/rtl818x/rtl8187/rtl8187.h | 288 ++ .../net/wireless/realtek/rtl818x/rtl8187/rtl8225.c | 961 ++++ .../net/wireless/realtek/rtl818x/rtl8187/rtl8225.h | 44 + drivers/net/wireless/realtek/rtl818x/rtl818x.h | 405 ++ drivers/net/wireless/realtek/rtlwifi/Kconfig | 154 + drivers/net/wireless/realtek/rtlwifi/Makefile | 34 + drivers/net/wireless/realtek/rtlwifi/base.c | 2176 +++++++++ drivers/net/wireless/realtek/rtlwifi/base.h | 156 + .../wireless/realtek/rtlwifi/btcoexist/Makefile | 7 + .../realtek/rtlwifi/btcoexist/halbt_precomp.h | 81 + .../realtek/rtlwifi/btcoexist/halbtc8192e2ant.c | 3849 ++++++++++++++++ .../realtek/rtlwifi/btcoexist/halbtc8192e2ant.h | 185 + .../realtek/rtlwifi/btcoexist/halbtc8723b1ant.c | 3170 +++++++++++++ .../realtek/rtlwifi/btcoexist/halbtc8723b1ant.h | 184 + .../realtek/rtlwifi/btcoexist/halbtc8723b2ant.c | 3717 +++++++++++++++ .../realtek/rtlwifi/btcoexist/halbtc8723b2ant.h | 172 + .../realtek/rtlwifi/btcoexist/halbtc8821a1ant.c | 2970 ++++++++++++ .../realtek/rtlwifi/btcoexist/halbtc8821a1ant.h | 188 + .../realtek/rtlwifi/btcoexist/halbtc8821a2ant.c | 3879 ++++++++++++++++ .../realtek/rtlwifi/btcoexist/halbtc8821a2ant.h | 205 + .../realtek/rtlwifi/btcoexist/halbtcoutsrc.c | 987 ++++ .../realtek/rtlwifi/btcoexist/halbtcoutsrc.h | 545 +++ .../wireless/realtek/rtlwifi/btcoexist/rtl_btc.c | 231 + .../wireless/realtek/rtlwifi/btcoexist/rtl_btc.h | 54 + drivers/net/wireless/realtek/rtlwifi/cam.c | 347 ++ drivers/net/wireless/realtek/rtlwifi/cam.h | 50 + drivers/net/wireless/realtek/rtlwifi/core.c | 1924 ++++++++ drivers/net/wireless/realtek/rtlwifi/core.h | 86 + drivers/net/wireless/realtek/rtlwifi/debug.c | 50 + drivers/net/wireless/realtek/rtlwifi/debug.h | 241 + drivers/net/wireless/realtek/rtlwifi/efuse.c | 1245 +++++ drivers/net/wireless/realtek/rtlwifi/efuse.h | 113 + drivers/net/wireless/realtek/rtlwifi/pci.c | 2478 ++++++++++ drivers/net/wireless/realtek/rtlwifi/pci.h | 335 ++ drivers/net/wireless/realtek/rtlwifi/ps.c | 1004 ++++ drivers/net/wireless/realtek/rtlwifi/ps.h | 53 + drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h | 94 + drivers/net/wireless/realtek/rtlwifi/rc.c | 302 ++ drivers/net/wireless/realtek/rtlwifi/rc.h | 48 + drivers/net/wireless/realtek/rtlwifi/regd.c | 473 ++ drivers/net/wireless/realtek/rtlwifi/regd.h | 63 + .../wireless/realtek/rtlwifi/rtl8188ee/Makefile | 15 + .../net/wireless/realtek/rtlwifi/rtl8188ee/def.h | 269 ++ .../net/wireless/realtek/rtlwifi/rtl8188ee/dm.c | 1805 ++++++++ .../net/wireless/realtek/rtlwifi/rtl8188ee/dm.h | 286 ++ .../net/wireless/realtek/rtlwifi/rtl8188ee/fw.c | 815 ++++ .../net/wireless/realtek/rtlwifi/rtl8188ee/fw.h | 285 ++ .../net/wireless/realtek/rtlwifi/rtl8188ee/hw.c | 2599 +++++++++++ .../net/wireless/realtek/rtlwifi/rtl8188ee/hw.h | 66 + .../net/wireless/realtek/rtlwifi/rtl8188ee/led.c | 154 + .../net/wireless/realtek/rtlwifi/rtl8188ee/led.h | 34 + .../net/wireless/realtek/rtlwifi/rtl8188ee/phy.c | 2343 ++++++++++ .../net/wireless/realtek/rtlwifi/rtl8188ee/phy.h | 233 + .../wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c | 105 + .../wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h | 311 ++ .../net/wireless/realtek/rtlwifi/rtl8188ee/reg.h | 2271 +++++++++ .../net/wireless/realtek/rtlwifi/rtl8188ee/rf.c | 509 ++ .../net/wireless/realtek/rtlwifi/rtl8188ee/rf.h | 42 + .../net/wireless/realtek/rtlwifi/rtl8188ee/sw.c | 419 ++ .../net/wireless/realtek/rtlwifi/rtl8188ee/sw.h | 34 + .../net/wireless/realtek/rtlwifi/rtl8188ee/table.c | 639 +++ .../net/wireless/realtek/rtlwifi/rtl8188ee/table.h | 43 + .../net/wireless/realtek/rtlwifi/rtl8188ee/trx.c | 858 ++++ .../net/wireless/realtek/rtlwifi/rtl8188ee/trx.h | 796 ++++ .../net/wireless/realtek/rtlwifi/rtl8192c/Makefile | 9 + .../wireless/realtek/rtlwifi/rtl8192c/dm_common.c | 1778 +++++++ .../wireless/realtek/rtlwifi/rtl8192c/dm_common.h | 147 + .../wireless/realtek/rtlwifi/rtl8192c/fw_common.c | 867 ++++ .../wireless/realtek/rtlwifi/rtl8192c/fw_common.h | 101 + .../net/wireless/realtek/rtlwifi/rtl8192c/main.c | 40 + .../wireless/realtek/rtlwifi/rtl8192c/phy_common.c | 1659 +++++++ .../wireless/realtek/rtlwifi/rtl8192c/phy_common.h | 254 + .../wireless/realtek/rtlwifi/rtl8192ce/Makefile | 13 + .../net/wireless/realtek/rtlwifi/rtl8192ce/def.h | 197 + .../net/wireless/realtek/rtlwifi/rtl8192ce/dm.c | 110 + .../net/wireless/realtek/rtlwifi/rtl8192ce/dm.h | 86 + .../net/wireless/realtek/rtlwifi/rtl8192ce/hw.c | 2426 ++++++++++ .../net/wireless/realtek/rtlwifi/rtl8192ce/hw.h | 80 + .../net/wireless/realtek/rtlwifi/rtl8192ce/led.c | 151 + .../net/wireless/realtek/rtlwifi/rtl8192ce/led.h | 38 + .../net/wireless/realtek/rtlwifi/rtl8192ce/phy.c | 577 +++ .../net/wireless/realtek/rtlwifi/rtl8192ce/phy.h | 143 + .../net/wireless/realtek/rtlwifi/rtl8192ce/reg.h | 2057 +++++++++ .../net/wireless/realtek/rtlwifi/rtl8192ce/rf.c | 509 ++ .../net/wireless/realtek/rtlwifi/rtl8192ce/rf.h | 42 + .../net/wireless/realtek/rtlwifi/rtl8192ce/sw.c | 394 ++ .../net/wireless/realtek/rtlwifi/rtl8192ce/sw.h | 41 + .../net/wireless/realtek/rtlwifi/rtl8192ce/table.c | 1224 +++++ .../net/wireless/realtek/rtlwifi/rtl8192ce/table.h | 58 + .../net/wireless/realtek/rtlwifi/rtl8192ce/trx.c | 768 ++++ .../net/wireless/realtek/rtlwifi/rtl8192ce/trx.h | 732 +++ .../wireless/realtek/rtlwifi/rtl8192cu/Makefile | 14 + .../net/wireless/realtek/rtlwifi/rtl8192cu/def.h | 46 + .../net/wireless/realtek/rtlwifi/rtl8192cu/dm.c | 116 + .../net/wireless/realtek/rtlwifi/rtl8192cu/dm.h | 35 + .../net/wireless/realtek/rtlwifi/rtl8192cu/hw.c | 2323 ++++++++++ .../net/wireless/realtek/rtlwifi/rtl8192cu/hw.h | 113 + .../net/wireless/realtek/rtlwifi/rtl8192cu/led.c | 141 + .../net/wireless/realtek/rtlwifi/rtl8192cu/led.h | 37 + .../net/wireless/realtek/rtlwifi/rtl8192cu/mac.c | 827 ++++ .../net/wireless/realtek/rtlwifi/rtl8192cu/mac.h | 161 + .../net/wireless/realtek/rtlwifi/rtl8192cu/phy.c | 539 +++ .../net/wireless/realtek/rtlwifi/rtl8192cu/phy.h | 50 + .../net/wireless/realtek/rtlwifi/rtl8192cu/reg.h | 30 + .../net/wireless/realtek/rtlwifi/rtl8192cu/rf.c | 475 ++ .../net/wireless/realtek/rtlwifi/rtl8192cu/rf.h | 49 + .../net/wireless/realtek/rtlwifi/rtl8192cu/sw.c | 412 ++ .../net/wireless/realtek/rtlwifi/rtl8192cu/sw.h | 53 + .../net/wireless/realtek/rtlwifi/rtl8192cu/table.c | 1888 ++++++++ .../net/wireless/realtek/rtlwifi/rtl8192cu/table.h | 71 + .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.c | 686 +++ .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.h | 435 ++ .../wireless/realtek/rtlwifi/rtl8192de/Makefile | 14 + .../net/wireless/realtek/rtlwifi/rtl8192de/def.h | 232 + .../net/wireless/realtek/rtlwifi/rtl8192de/dm.c | 1316 ++++++ .../net/wireless/realtek/rtlwifi/rtl8192de/dm.h | 123 + .../net/wireless/realtek/rtlwifi/rtl8192de/fw.c | 763 +++ .../net/wireless/realtek/rtlwifi/rtl8192de/fw.h | 120 + .../net/wireless/realtek/rtlwifi/rtl8192de/hw.c | 2307 ++++++++++ .../net/wireless/realtek/rtlwifi/rtl8192de/hw.h | 65 + .../net/wireless/realtek/rtlwifi/rtl8192de/led.c | 159 + .../net/wireless/realtek/rtlwifi/rtl8192de/led.h | 38 + .../net/wireless/realtek/rtlwifi/rtl8192de/phy.c | 3609 +++++++++++++++ .../net/wireless/realtek/rtlwifi/rtl8192de/phy.h | 173 + .../net/wireless/realtek/rtlwifi/rtl8192de/reg.h | 1299 ++++++ .../net/wireless/realtek/rtlwifi/rtl8192de/rf.c | 623 +++ .../net/wireless/realtek/rtlwifi/rtl8192de/rf.h | 42 + .../net/wireless/realtek/rtlwifi/rtl8192de/sw.c | 419 ++ .../net/wireless/realtek/rtlwifi/rtl8192de/sw.h | 37 + .../net/wireless/realtek/rtlwifi/rtl8192de/table.c | 1690 +++++++ .../net/wireless/realtek/rtlwifi/rtl8192de/table.h | 57 + .../net/wireless/realtek/rtlwifi/rtl8192de/trx.c | 871 ++++ .../net/wireless/realtek/rtlwifi/rtl8192de/trx.h | 748 +++ .../wireless/realtek/rtlwifi/rtl8192ee/Makefile | 16 + .../net/wireless/realtek/rtlwifi/rtl8192ee/def.h | 101 + .../net/wireless/realtek/rtlwifi/rtl8192ee/dm.c | 1236 +++++ .../net/wireless/realtek/rtlwifi/rtl8192ee/dm.h | 251 + .../net/wireless/realtek/rtlwifi/rtl8192ee/fw.c | 902 ++++ .../net/wireless/realtek/rtlwifi/rtl8192ee/fw.h | 189 + .../net/wireless/realtek/rtlwifi/rtl8192ee/hw.c | 2666 +++++++++++ .../net/wireless/realtek/rtlwifi/rtl8192ee/hw.h | 62 + .../net/wireless/realtek/rtlwifi/rtl8192ee/led.c | 145 + .../net/wireless/realtek/rtlwifi/rtl8192ee/led.h | 34 + .../net/wireless/realtek/rtlwifi/rtl8192ee/phy.c | 3219 +++++++++++++ .../net/wireless/realtek/rtlwifi/rtl8192ee/phy.h | 153 + .../wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c | 112 + .../wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h | 340 ++ .../net/wireless/realtek/rtlwifi/rtl8192ee/reg.h | 2233 +++++++++ .../net/wireless/realtek/rtlwifi/rtl8192ee/rf.c | 152 + .../net/wireless/realtek/rtlwifi/rtl8192ee/rf.h | 35 + .../net/wireless/realtek/rtlwifi/rtl8192ee/sw.c | 398 ++ .../net/wireless/realtek/rtlwifi/rtl8192ee/sw.h | 33 + .../net/wireless/realtek/rtlwifi/rtl8192ee/table.c | 882 ++++ .../net/wireless/realtek/rtlwifi/rtl8192ee/table.h | 45 + .../net/wireless/realtek/rtlwifi/rtl8192ee/trx.c | 1129 +++++ .../net/wireless/realtek/rtlwifi/rtl8192ee/trx.h | 862 ++++ .../wireless/realtek/rtlwifi/rtl8192se/Makefile | 15 + .../net/wireless/realtek/rtlwifi/rtl8192se/def.h | 555 +++ .../net/wireless/realtek/rtlwifi/rtl8192se/dm.c | 742 +++ .../net/wireless/realtek/rtlwifi/rtl8192se/dm.h | 92 + .../net/wireless/realtek/rtlwifi/rtl8192se/fw.c | 652 +++ .../net/wireless/realtek/rtlwifi/rtl8192se/fw.h | 375 ++ .../net/wireless/realtek/rtlwifi/rtl8192se/hw.c | 2548 ++++++++++ .../net/wireless/realtek/rtlwifi/rtl8192se/hw.h | 78 + .../net/wireless/realtek/rtlwifi/rtl8192se/led.c | 151 + .../net/wireless/realtek/rtlwifi/rtl8192se/led.h | 37 + .../net/wireless/realtek/rtlwifi/rtl8192se/phy.c | 1658 +++++++ .../net/wireless/realtek/rtlwifi/rtl8192se/phy.h | 102 + .../net/wireless/realtek/rtlwifi/rtl8192se/reg.h | 1168 +++++ .../net/wireless/realtek/rtlwifi/rtl8192se/rf.c | 535 +++ .../net/wireless/realtek/rtlwifi/rtl8192se/rf.h | 43 + .../net/wireless/realtek/rtlwifi/rtl8192se/sw.c | 442 ++ .../net/wireless/realtek/rtlwifi/rtl8192se/sw.h | 36 + .../net/wireless/realtek/rtlwifi/rtl8192se/table.c | 634 +++ .../net/wireless/realtek/rtlwifi/rtl8192se/table.h | 49 + .../net/wireless/realtek/rtlwifi/rtl8192se/trx.c | 658 +++ .../net/wireless/realtek/rtlwifi/rtl8192se/trx.h | 48 + .../wireless/realtek/rtlwifi/rtl8723ae/Makefile | 18 + .../net/wireless/realtek/rtlwifi/rtl8723ae/btc.h | 36 + .../net/wireless/realtek/rtlwifi/rtl8723ae/def.h | 238 + .../net/wireless/realtek/rtlwifi/rtl8723ae/dm.c | 881 ++++ .../net/wireless/realtek/rtlwifi/rtl8723ae/dm.h | 136 + .../net/wireless/realtek/rtlwifi/rtl8723ae/fw.c | 603 +++ .../net/wireless/realtek/rtlwifi/rtl8723ae/fw.h | 66 + .../realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c | 537 +++ .../realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h | 158 + .../wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c | 1780 +++++++ .../wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h | 159 + .../net/wireless/realtek/rtlwifi/rtl8723ae/hw.c | 2482 ++++++++++ .../net/wireless/realtek/rtlwifi/rtl8723ae/hw.h | 67 + .../net/wireless/realtek/rtlwifi/rtl8723ae/led.c | 159 + .../net/wireless/realtek/rtlwifi/rtl8723ae/led.h | 34 + .../net/wireless/realtek/rtlwifi/rtl8723ae/phy.c | 1705 +++++++ .../net/wireless/realtek/rtlwifi/rtl8723ae/phy.h | 202 + .../wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c | 112 + .../wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h | 340 ++ .../net/wireless/realtek/rtlwifi/rtl8723ae/reg.h | 2120 +++++++++ .../net/wireless/realtek/rtlwifi/rtl8723ae/rf.c | 514 +++ .../net/wireless/realtek/rtlwifi/rtl8723ae/rf.h | 39 + .../net/wireless/realtek/rtlwifi/rtl8723ae/sw.c | 405 ++ .../net/wireless/realtek/rtlwifi/rtl8723ae/sw.h | 35 + .../net/wireless/realtek/rtlwifi/rtl8723ae/table.c | 732 +++ .../net/wireless/realtek/rtlwifi/rtl8723ae/table.h | 46 + .../net/wireless/realtek/rtlwifi/rtl8723ae/trx.c | 717 +++ .../net/wireless/realtek/rtlwifi/rtl8723ae/trx.h | 721 +++ .../wireless/realtek/rtlwifi/rtl8723be/Makefile | 16 + .../net/wireless/realtek/rtlwifi/rtl8723be/def.h | 92 + .../net/wireless/realtek/rtlwifi/rtl8723be/dm.c | 1298 ++++++ .../net/wireless/realtek/rtlwifi/rtl8723be/dm.h | 267 ++ .../net/wireless/realtek/rtlwifi/rtl8723be/fw.c | 640 +++ .../net/wireless/realtek/rtlwifi/rtl8723be/fw.h | 152 + .../net/wireless/realtek/rtlwifi/rtl8723be/hw.c | 2734 +++++++++++ .../net/wireless/realtek/rtlwifi/rtl8723be/hw.h | 63 + .../net/wireless/realtek/rtlwifi/rtl8723be/led.c | 153 + .../net/wireless/realtek/rtlwifi/rtl8723be/led.h | 35 + .../net/wireless/realtek/rtlwifi/rtl8723be/phy.c | 2730 +++++++++++ .../net/wireless/realtek/rtlwifi/rtl8723be/phy.h | 135 + .../wireless/realtek/rtlwifi/rtl8723be/pwrseq.c | 106 + .../wireless/realtek/rtlwifi/rtl8723be/pwrseq.h | 423 ++ .../net/wireless/realtek/rtlwifi/rtl8723be/reg.h | 2295 +++++++++ .../net/wireless/realtek/rtlwifi/rtl8723be/rf.c | 512 +++ .../net/wireless/realtek/rtlwifi/rtl8723be/rf.h | 42 + .../net/wireless/realtek/rtlwifi/rtl8723be/sw.c | 410 ++ .../net/wireless/realtek/rtlwifi/rtl8723be/sw.h | 35 + .../net/wireless/realtek/rtlwifi/rtl8723be/table.c | 577 +++ .../net/wireless/realtek/rtlwifi/rtl8723be/table.h | 43 + .../net/wireless/realtek/rtlwifi/rtl8723be/trx.c | 783 ++++ .../net/wireless/realtek/rtlwifi/rtl8723be/trx.h | 625 +++ .../wireless/realtek/rtlwifi/rtl8723com/Makefile | 9 + .../realtek/rtlwifi/rtl8723com/dm_common.c | 65 + .../realtek/rtlwifi/rtl8723com/dm_common.h | 33 + .../realtek/rtlwifi/rtl8723com/fw_common.c | 339 ++ .../realtek/rtlwifi/rtl8723com/fw_common.h | 100 + .../net/wireless/realtek/rtlwifi/rtl8723com/main.c | 33 + .../realtek/rtlwifi/rtl8723com/phy_common.c | 447 ++ .../realtek/rtlwifi/rtl8723com/phy_common.h | 89 + .../wireless/realtek/rtlwifi/rtl8821ae/Makefile | 16 + .../net/wireless/realtek/rtlwifi/rtl8821ae/def.h | 355 ++ .../net/wireless/realtek/rtlwifi/rtl8821ae/dm.c | 2988 ++++++++++++ .../net/wireless/realtek/rtlwifi/rtl8821ae/dm.h | 315 ++ .../net/wireless/realtek/rtlwifi/rtl8821ae/fw.c | 1857 ++++++++ .../net/wireless/realtek/rtlwifi/rtl8821ae/fw.h | 332 ++ .../net/wireless/realtek/rtlwifi/rtl8821ae/hw.c | 4199 +++++++++++++++++ .../net/wireless/realtek/rtlwifi/rtl8821ae/hw.h | 70 + .../net/wireless/realtek/rtlwifi/rtl8821ae/led.c | 237 + .../net/wireless/realtek/rtlwifi/rtl8821ae/led.h | 37 + .../net/wireless/realtek/rtlwifi/rtl8821ae/phy.c | 4858 ++++++++++++++++++++ .../net/wireless/realtek/rtlwifi/rtl8821ae/phy.h | 259 ++ .../wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c | 182 + .../wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h | 738 +++ .../net/wireless/realtek/rtlwifi/rtl8821ae/reg.h | 2465 ++++++++++ .../net/wireless/realtek/rtlwifi/rtl8821ae/rf.c | 465 ++ .../net/wireless/realtek/rtlwifi/rtl8821ae/rf.h | 42 + .../net/wireless/realtek/rtlwifi/rtl8821ae/sw.c | 458 ++ .../net/wireless/realtek/rtlwifi/rtl8821ae/sw.h | 34 + .../net/wireless/realtek/rtlwifi/rtl8821ae/table.c | 4572 ++++++++++++++++++ .../net/wireless/realtek/rtlwifi/rtl8821ae/table.h | 60 + .../net/wireless/realtek/rtlwifi/rtl8821ae/trx.c | 1024 +++++ .../net/wireless/realtek/rtlwifi/rtl8821ae/trx.h | 620 +++ drivers/net/wireless/realtek/rtlwifi/stats.c | 268 ++ drivers/net/wireless/realtek/rtlwifi/stats.h | 42 + drivers/net/wireless/realtek/rtlwifi/usb.c | 1188 +++++ drivers/net/wireless/realtek/rtlwifi/usb.h | 169 + drivers/net/wireless/realtek/rtlwifi/wifi.h | 3032 ++++++++++++ drivers/net/wireless/rtl818x/Kconfig | 88 - drivers/net/wireless/rtl818x/Makefile | 2 - drivers/net/wireless/rtl818x/rtl8180/Makefile | 5 - drivers/net/wireless/rtl818x/rtl8180/dev.c | 1991 -------- drivers/net/wireless/rtl818x/rtl8180/grf5101.c | 190 - drivers/net/wireless/rtl818x/rtl8180/grf5101.h | 28 - drivers/net/wireless/rtl818x/rtl8180/max2820.c | 168 - drivers/net/wireless/rtl818x/rtl8180/max2820.h | 28 - drivers/net/wireless/rtl818x/rtl8180/rtl8180.h | 185 - drivers/net/wireless/rtl818x/rtl8180/rtl8225.c | 770 ---- drivers/net/wireless/rtl818x/rtl8180/rtl8225.h | 23 - drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c | 475 -- drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h | 61 - drivers/net/wireless/rtl818x/rtl8180/sa2400.c | 228 - drivers/net/wireless/rtl818x/rtl8180/sa2400.h | 36 - drivers/net/wireless/rtl818x/rtl8187/Makefile | 5 - drivers/net/wireless/rtl818x/rtl8187/dev.c | 1684 ------- drivers/net/wireless/rtl818x/rtl8187/leds.c | 245 - drivers/net/wireless/rtl818x/rtl8187/leds.h | 59 - drivers/net/wireless/rtl818x/rtl8187/rfkill.c | 64 - drivers/net/wireless/rtl818x/rtl8187/rfkill.h | 8 - drivers/net/wireless/rtl818x/rtl8187/rtl8187.h | 288 -- drivers/net/wireless/rtl818x/rtl8187/rtl8225.c | 961 ---- drivers/net/wireless/rtl818x/rtl8187/rtl8225.h | 44 - drivers/net/wireless/rtl818x/rtl818x.h | 405 -- drivers/net/wireless/rtlwifi/Kconfig | 154 - drivers/net/wireless/rtlwifi/Makefile | 34 - drivers/net/wireless/rtlwifi/base.c | 2176 --------- drivers/net/wireless/rtlwifi/base.h | 156 - drivers/net/wireless/rtlwifi/btcoexist/Makefile | 7 - .../net/wireless/rtlwifi/btcoexist/halbt_precomp.h | 81 - .../wireless/rtlwifi/btcoexist/halbtc8192e2ant.c | 3849 ---------------- .../wireless/rtlwifi/btcoexist/halbtc8192e2ant.h | 185 - .../wireless/rtlwifi/btcoexist/halbtc8723b1ant.c | 3170 ------------- .../wireless/rtlwifi/btcoexist/halbtc8723b1ant.h | 184 - .../wireless/rtlwifi/btcoexist/halbtc8723b2ant.c | 3717 --------------- .../wireless/rtlwifi/btcoexist/halbtc8723b2ant.h | 172 - .../wireless/rtlwifi/btcoexist/halbtc8821a1ant.c | 2970 ------------ .../wireless/rtlwifi/btcoexist/halbtc8821a1ant.h | 188 - .../wireless/rtlwifi/btcoexist/halbtc8821a2ant.c | 3879 ---------------- .../wireless/rtlwifi/btcoexist/halbtc8821a2ant.h | 205 - .../net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c | 987 ---- .../net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h | 545 --- drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c | 231 - drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h | 54 - drivers/net/wireless/rtlwifi/cam.c | 347 -- drivers/net/wireless/rtlwifi/cam.h | 50 - drivers/net/wireless/rtlwifi/core.c | 1924 -------- drivers/net/wireless/rtlwifi/core.h | 86 - drivers/net/wireless/rtlwifi/debug.c | 50 - drivers/net/wireless/rtlwifi/debug.h | 241 - drivers/net/wireless/rtlwifi/efuse.c | 1245 ----- drivers/net/wireless/rtlwifi/efuse.h | 113 - drivers/net/wireless/rtlwifi/pci.c | 2478 ---------- drivers/net/wireless/rtlwifi/pci.h | 335 -- drivers/net/wireless/rtlwifi/ps.c | 1004 ---- drivers/net/wireless/rtlwifi/ps.h | 53 - drivers/net/wireless/rtlwifi/pwrseqcmd.h | 94 - drivers/net/wireless/rtlwifi/rc.c | 302 -- drivers/net/wireless/rtlwifi/rc.h | 48 - drivers/net/wireless/rtlwifi/regd.c | 473 -- drivers/net/wireless/rtlwifi/regd.h | 63 - drivers/net/wireless/rtlwifi/rtl8188ee/Makefile | 15 - drivers/net/wireless/rtlwifi/rtl8188ee/def.h | 269 -- drivers/net/wireless/rtlwifi/rtl8188ee/dm.c | 1805 -------- drivers/net/wireless/rtlwifi/rtl8188ee/dm.h | 286 -- drivers/net/wireless/rtlwifi/rtl8188ee/fw.c | 815 ---- drivers/net/wireless/rtlwifi/rtl8188ee/fw.h | 285 -- drivers/net/wireless/rtlwifi/rtl8188ee/hw.c | 2599 ----------- drivers/net/wireless/rtlwifi/rtl8188ee/hw.h | 66 - drivers/net/wireless/rtlwifi/rtl8188ee/led.c | 154 - drivers/net/wireless/rtlwifi/rtl8188ee/led.h | 34 - drivers/net/wireless/rtlwifi/rtl8188ee/phy.c | 2343 ---------- drivers/net/wireless/rtlwifi/rtl8188ee/phy.h | 233 - drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c | 105 - drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h | 311 -- drivers/net/wireless/rtlwifi/rtl8188ee/reg.h | 2271 --------- drivers/net/wireless/rtlwifi/rtl8188ee/rf.c | 509 -- drivers/net/wireless/rtlwifi/rtl8188ee/rf.h | 42 - drivers/net/wireless/rtlwifi/rtl8188ee/sw.c | 419 -- drivers/net/wireless/rtlwifi/rtl8188ee/sw.h | 34 - drivers/net/wireless/rtlwifi/rtl8188ee/table.c | 639 --- drivers/net/wireless/rtlwifi/rtl8188ee/table.h | 43 - drivers/net/wireless/rtlwifi/rtl8188ee/trx.c | 858 ---- drivers/net/wireless/rtlwifi/rtl8188ee/trx.h | 796 ---- drivers/net/wireless/rtlwifi/rtl8192c/Makefile | 9 - drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c | 1778 ------- drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h | 147 - drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 867 ---- drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h | 101 - drivers/net/wireless/rtlwifi/rtl8192c/main.c | 40 - drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c | 1659 ------- drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h | 254 - drivers/net/wireless/rtlwifi/rtl8192ce/Makefile | 13 - drivers/net/wireless/rtlwifi/rtl8192ce/def.h | 197 - drivers/net/wireless/rtlwifi/rtl8192ce/dm.c | 110 - drivers/net/wireless/rtlwifi/rtl8192ce/dm.h | 86 - drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | 2426 ---------- drivers/net/wireless/rtlwifi/rtl8192ce/hw.h | 80 - drivers/net/wireless/rtlwifi/rtl8192ce/led.c | 151 - drivers/net/wireless/rtlwifi/rtl8192ce/led.h | 38 - drivers/net/wireless/rtlwifi/rtl8192ce/phy.c | 577 --- drivers/net/wireless/rtlwifi/rtl8192ce/phy.h | 143 - drivers/net/wireless/rtlwifi/rtl8192ce/reg.h | 2057 --------- drivers/net/wireless/rtlwifi/rtl8192ce/rf.c | 509 -- drivers/net/wireless/rtlwifi/rtl8192ce/rf.h | 42 - drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 394 -- drivers/net/wireless/rtlwifi/rtl8192ce/sw.h | 41 - drivers/net/wireless/rtlwifi/rtl8192ce/table.c | 1224 ----- drivers/net/wireless/rtlwifi/rtl8192ce/table.h | 58 - drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | 768 ---- drivers/net/wireless/rtlwifi/rtl8192ce/trx.h | 732 --- drivers/net/wireless/rtlwifi/rtl8192cu/Makefile | 14 - drivers/net/wireless/rtlwifi/rtl8192cu/def.h | 46 - drivers/net/wireless/rtlwifi/rtl8192cu/dm.c | 116 - drivers/net/wireless/rtlwifi/rtl8192cu/dm.h | 35 - drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | 2323 ---------- drivers/net/wireless/rtlwifi/rtl8192cu/hw.h | 113 - drivers/net/wireless/rtlwifi/rtl8192cu/led.c | 141 - drivers/net/wireless/rtlwifi/rtl8192cu/led.h | 37 - drivers/net/wireless/rtlwifi/rtl8192cu/mac.c | 827 ---- drivers/net/wireless/rtlwifi/rtl8192cu/mac.h | 161 - drivers/net/wireless/rtlwifi/rtl8192cu/phy.c | 539 --- drivers/net/wireless/rtlwifi/rtl8192cu/phy.h | 50 - drivers/net/wireless/rtlwifi/rtl8192cu/reg.h | 30 - drivers/net/wireless/rtlwifi/rtl8192cu/rf.c | 475 -- drivers/net/wireless/rtlwifi/rtl8192cu/rf.h | 49 - drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 412 -- drivers/net/wireless/rtlwifi/rtl8192cu/sw.h | 53 - drivers/net/wireless/rtlwifi/rtl8192cu/table.c | 1888 -------- drivers/net/wireless/rtlwifi/rtl8192cu/table.h | 71 - drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 686 --- drivers/net/wireless/rtlwifi/rtl8192cu/trx.h | 435 -- drivers/net/wireless/rtlwifi/rtl8192de/Makefile | 14 - drivers/net/wireless/rtlwifi/rtl8192de/def.h | 232 - drivers/net/wireless/rtlwifi/rtl8192de/dm.c | 1316 ------ drivers/net/wireless/rtlwifi/rtl8192de/dm.h | 123 - drivers/net/wireless/rtlwifi/rtl8192de/fw.c | 763 --- drivers/net/wireless/rtlwifi/rtl8192de/fw.h | 120 - drivers/net/wireless/rtlwifi/rtl8192de/hw.c | 2307 ---------- drivers/net/wireless/rtlwifi/rtl8192de/hw.h | 65 - drivers/net/wireless/rtlwifi/rtl8192de/led.c | 159 - drivers/net/wireless/rtlwifi/rtl8192de/led.h | 38 - drivers/net/wireless/rtlwifi/rtl8192de/phy.c | 3609 --------------- drivers/net/wireless/rtlwifi/rtl8192de/phy.h | 173 - drivers/net/wireless/rtlwifi/rtl8192de/reg.h | 1299 ------ drivers/net/wireless/rtlwifi/rtl8192de/rf.c | 623 --- drivers/net/wireless/rtlwifi/rtl8192de/rf.h | 42 - drivers/net/wireless/rtlwifi/rtl8192de/sw.c | 419 -- drivers/net/wireless/rtlwifi/rtl8192de/sw.h | 37 - drivers/net/wireless/rtlwifi/rtl8192de/table.c | 1690 ------- drivers/net/wireless/rtlwifi/rtl8192de/table.h | 57 - drivers/net/wireless/rtlwifi/rtl8192de/trx.c | 871 ---- drivers/net/wireless/rtlwifi/rtl8192de/trx.h | 748 --- drivers/net/wireless/rtlwifi/rtl8192ee/Makefile | 16 - drivers/net/wireless/rtlwifi/rtl8192ee/def.h | 101 - drivers/net/wireless/rtlwifi/rtl8192ee/dm.c | 1236 ----- drivers/net/wireless/rtlwifi/rtl8192ee/dm.h | 251 - drivers/net/wireless/rtlwifi/rtl8192ee/fw.c | 902 ---- drivers/net/wireless/rtlwifi/rtl8192ee/fw.h | 189 - drivers/net/wireless/rtlwifi/rtl8192ee/hw.c | 2666 ----------- drivers/net/wireless/rtlwifi/rtl8192ee/hw.h | 62 - drivers/net/wireless/rtlwifi/rtl8192ee/led.c | 145 - drivers/net/wireless/rtlwifi/rtl8192ee/led.h | 34 - drivers/net/wireless/rtlwifi/rtl8192ee/phy.c | 3219 ------------- drivers/net/wireless/rtlwifi/rtl8192ee/phy.h | 153 - drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.c | 112 - drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.h | 340 -- drivers/net/wireless/rtlwifi/rtl8192ee/reg.h | 2233 --------- drivers/net/wireless/rtlwifi/rtl8192ee/rf.c | 152 - drivers/net/wireless/rtlwifi/rtl8192ee/rf.h | 35 - drivers/net/wireless/rtlwifi/rtl8192ee/sw.c | 398 -- drivers/net/wireless/rtlwifi/rtl8192ee/sw.h | 33 - drivers/net/wireless/rtlwifi/rtl8192ee/table.c | 882 ---- drivers/net/wireless/rtlwifi/rtl8192ee/table.h | 45 - drivers/net/wireless/rtlwifi/rtl8192ee/trx.c | 1129 ----- drivers/net/wireless/rtlwifi/rtl8192ee/trx.h | 862 ---- drivers/net/wireless/rtlwifi/rtl8192se/Makefile | 15 - drivers/net/wireless/rtlwifi/rtl8192se/def.h | 555 --- drivers/net/wireless/rtlwifi/rtl8192se/dm.c | 742 --- drivers/net/wireless/rtlwifi/rtl8192se/dm.h | 92 - drivers/net/wireless/rtlwifi/rtl8192se/fw.c | 652 --- drivers/net/wireless/rtlwifi/rtl8192se/fw.h | 375 -- drivers/net/wireless/rtlwifi/rtl8192se/hw.c | 2548 ---------- drivers/net/wireless/rtlwifi/rtl8192se/hw.h | 78 - drivers/net/wireless/rtlwifi/rtl8192se/led.c | 151 - drivers/net/wireless/rtlwifi/rtl8192se/led.h | 37 - drivers/net/wireless/rtlwifi/rtl8192se/phy.c | 1658 ------- drivers/net/wireless/rtlwifi/rtl8192se/phy.h | 102 - drivers/net/wireless/rtlwifi/rtl8192se/reg.h | 1168 ----- drivers/net/wireless/rtlwifi/rtl8192se/rf.c | 535 --- drivers/net/wireless/rtlwifi/rtl8192se/rf.h | 43 - drivers/net/wireless/rtlwifi/rtl8192se/sw.c | 442 -- drivers/net/wireless/rtlwifi/rtl8192se/sw.h | 36 - drivers/net/wireless/rtlwifi/rtl8192se/table.c | 634 --- drivers/net/wireless/rtlwifi/rtl8192se/table.h | 49 - drivers/net/wireless/rtlwifi/rtl8192se/trx.c | 658 --- drivers/net/wireless/rtlwifi/rtl8192se/trx.h | 48 - drivers/net/wireless/rtlwifi/rtl8723ae/Makefile | 18 - drivers/net/wireless/rtlwifi/rtl8723ae/btc.h | 36 - drivers/net/wireless/rtlwifi/rtl8723ae/def.h | 238 - drivers/net/wireless/rtlwifi/rtl8723ae/dm.c | 881 ---- drivers/net/wireless/rtlwifi/rtl8723ae/dm.h | 136 - drivers/net/wireless/rtlwifi/rtl8723ae/fw.c | 603 --- drivers/net/wireless/rtlwifi/rtl8723ae/fw.h | 66 - .../wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c | 537 --- .../wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h | 158 - drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c | 1780 ------- drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h | 159 - drivers/net/wireless/rtlwifi/rtl8723ae/hw.c | 2482 ---------- drivers/net/wireless/rtlwifi/rtl8723ae/hw.h | 67 - drivers/net/wireless/rtlwifi/rtl8723ae/led.c | 159 - drivers/net/wireless/rtlwifi/rtl8723ae/led.h | 34 - drivers/net/wireless/rtlwifi/rtl8723ae/phy.c | 1705 ------- drivers/net/wireless/rtlwifi/rtl8723ae/phy.h | 202 - drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c | 112 - drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h | 340 -- drivers/net/wireless/rtlwifi/rtl8723ae/reg.h | 2120 --------- drivers/net/wireless/rtlwifi/rtl8723ae/rf.c | 514 --- drivers/net/wireless/rtlwifi/rtl8723ae/rf.h | 39 - drivers/net/wireless/rtlwifi/rtl8723ae/sw.c | 405 -- drivers/net/wireless/rtlwifi/rtl8723ae/sw.h | 35 - drivers/net/wireless/rtlwifi/rtl8723ae/table.c | 732 --- drivers/net/wireless/rtlwifi/rtl8723ae/table.h | 46 - drivers/net/wireless/rtlwifi/rtl8723ae/trx.c | 717 --- drivers/net/wireless/rtlwifi/rtl8723ae/trx.h | 721 --- drivers/net/wireless/rtlwifi/rtl8723be/Makefile | 16 - drivers/net/wireless/rtlwifi/rtl8723be/def.h | 92 - drivers/net/wireless/rtlwifi/rtl8723be/dm.c | 1298 ------ drivers/net/wireless/rtlwifi/rtl8723be/dm.h | 267 -- drivers/net/wireless/rtlwifi/rtl8723be/fw.c | 640 --- drivers/net/wireless/rtlwifi/rtl8723be/fw.h | 152 - drivers/net/wireless/rtlwifi/rtl8723be/hw.c | 2734 ----------- drivers/net/wireless/rtlwifi/rtl8723be/hw.h | 63 - drivers/net/wireless/rtlwifi/rtl8723be/led.c | 153 - drivers/net/wireless/rtlwifi/rtl8723be/led.h | 35 - drivers/net/wireless/rtlwifi/rtl8723be/phy.c | 2730 ----------- drivers/net/wireless/rtlwifi/rtl8723be/phy.h | 135 - drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.c | 106 - drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.h | 423 -- drivers/net/wireless/rtlwifi/rtl8723be/reg.h | 2295 --------- drivers/net/wireless/rtlwifi/rtl8723be/rf.c | 512 --- drivers/net/wireless/rtlwifi/rtl8723be/rf.h | 42 - drivers/net/wireless/rtlwifi/rtl8723be/sw.c | 410 -- drivers/net/wireless/rtlwifi/rtl8723be/sw.h | 35 - drivers/net/wireless/rtlwifi/rtl8723be/table.c | 577 --- drivers/net/wireless/rtlwifi/rtl8723be/table.h | 43 - drivers/net/wireless/rtlwifi/rtl8723be/trx.c | 783 ---- drivers/net/wireless/rtlwifi/rtl8723be/trx.h | 625 --- drivers/net/wireless/rtlwifi/rtl8723com/Makefile | 9 - .../net/wireless/rtlwifi/rtl8723com/dm_common.c | 65 - .../net/wireless/rtlwifi/rtl8723com/dm_common.h | 33 - .../net/wireless/rtlwifi/rtl8723com/fw_common.c | 339 -- .../net/wireless/rtlwifi/rtl8723com/fw_common.h | 100 - drivers/net/wireless/rtlwifi/rtl8723com/main.c | 33 - .../net/wireless/rtlwifi/rtl8723com/phy_common.c | 447 -- .../net/wireless/rtlwifi/rtl8723com/phy_common.h | 89 - drivers/net/wireless/rtlwifi/rtl8821ae/Makefile | 16 - drivers/net/wireless/rtlwifi/rtl8821ae/def.h | 355 -- drivers/net/wireless/rtlwifi/rtl8821ae/dm.c | 2988 ------------ drivers/net/wireless/rtlwifi/rtl8821ae/dm.h | 315 -- drivers/net/wireless/rtlwifi/rtl8821ae/fw.c | 1857 -------- drivers/net/wireless/rtlwifi/rtl8821ae/fw.h | 332 -- drivers/net/wireless/rtlwifi/rtl8821ae/hw.c | 4199 ----------------- drivers/net/wireless/rtlwifi/rtl8821ae/hw.h | 70 - drivers/net/wireless/rtlwifi/rtl8821ae/led.c | 237 - drivers/net/wireless/rtlwifi/rtl8821ae/led.h | 37 - drivers/net/wireless/rtlwifi/rtl8821ae/phy.c | 4858 -------------------- drivers/net/wireless/rtlwifi/rtl8821ae/phy.h | 259 -- drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.c | 182 - drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.h | 738 --- drivers/net/wireless/rtlwifi/rtl8821ae/reg.h | 2465 ---------- drivers/net/wireless/rtlwifi/rtl8821ae/rf.c | 465 -- drivers/net/wireless/rtlwifi/rtl8821ae/rf.h | 42 - drivers/net/wireless/rtlwifi/rtl8821ae/sw.c | 458 -- drivers/net/wireless/rtlwifi/rtl8821ae/sw.h | 34 - drivers/net/wireless/rtlwifi/rtl8821ae/table.c | 4572 ------------------ drivers/net/wireless/rtlwifi/rtl8821ae/table.h | 60 - drivers/net/wireless/rtlwifi/rtl8821ae/trx.c | 1024 ----- drivers/net/wireless/rtlwifi/rtl8821ae/trx.h | 620 --- drivers/net/wireless/rtlwifi/stats.c | 268 -- drivers/net/wireless/rtlwifi/stats.h | 42 - drivers/net/wireless/rtlwifi/usb.c | 1188 ----- drivers/net/wireless/rtlwifi/usb.h | 169 - drivers/net/wireless/rtlwifi/wifi.h | 3032 ------------ 573 files changed, 179559 insertions(+), 179553 deletions(-) create mode 100644 drivers/net/wireless/realtek/Makefile create mode 100644 drivers/net/wireless/realtek/rtl818x/Kconfig create mode 100644 drivers/net/wireless/realtek/rtl818x/Makefile create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.c create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.h create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.c create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.h create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8180.h create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.c create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.h create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.h create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.c create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.h create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8187/leds.c create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8187/leds.h create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.c create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.h create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.h create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.h create mode 100644 drivers/net/wireless/realtek/rtl818x/rtl818x.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/Kconfig create mode 100644 drivers/net/wireless/realtek/rtlwifi/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/base.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/base.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/cam.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/cam.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/core.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/core.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/debug.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/debug.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/efuse.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/efuse.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/pci.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/pci.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/ps.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/ps.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rc.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rc.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/regd.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/regd.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192c/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723com/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/Makefile create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/stats.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/stats.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/usb.c create mode 100644 drivers/net/wireless/realtek/rtlwifi/usb.h create mode 100644 drivers/net/wireless/realtek/rtlwifi/wifi.h delete mode 100644 drivers/net/wireless/rtl818x/Kconfig delete mode 100644 drivers/net/wireless/rtl818x/Makefile delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/Makefile delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/dev.c delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/grf5101.c delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/grf5101.h delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/max2820.c delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/max2820.h delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/rtl8180.h delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/rtl8225.c delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/rtl8225.h delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/sa2400.c delete mode 100644 drivers/net/wireless/rtl818x/rtl8180/sa2400.h delete mode 100644 drivers/net/wireless/rtl818x/rtl8187/Makefile delete mode 100644 drivers/net/wireless/rtl818x/rtl8187/dev.c delete mode 100644 drivers/net/wireless/rtl818x/rtl8187/leds.c delete mode 100644 drivers/net/wireless/rtl818x/rtl8187/leds.h delete mode 100644 drivers/net/wireless/rtl818x/rtl8187/rfkill.c delete mode 100644 drivers/net/wireless/rtl818x/rtl8187/rfkill.h delete mode 100644 drivers/net/wireless/rtl818x/rtl8187/rtl8187.h delete mode 100644 drivers/net/wireless/rtl818x/rtl8187/rtl8225.c delete mode 100644 drivers/net/wireless/rtl818x/rtl8187/rtl8225.h delete mode 100644 drivers/net/wireless/rtl818x/rtl818x.h delete mode 100644 drivers/net/wireless/rtlwifi/Kconfig delete mode 100644 drivers/net/wireless/rtlwifi/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/base.c delete mode 100644 drivers/net/wireless/rtlwifi/base.h delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.h delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.c delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.h delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.c delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.c delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.h delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.c delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.h delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c delete mode 100644 drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h delete mode 100644 drivers/net/wireless/rtlwifi/cam.c delete mode 100644 drivers/net/wireless/rtlwifi/cam.h delete mode 100644 drivers/net/wireless/rtlwifi/core.c delete mode 100644 drivers/net/wireless/rtlwifi/core.h delete mode 100644 drivers/net/wireless/rtlwifi/debug.c delete mode 100644 drivers/net/wireless/rtlwifi/debug.h delete mode 100644 drivers/net/wireless/rtlwifi/efuse.c delete mode 100644 drivers/net/wireless/rtlwifi/efuse.h delete mode 100644 drivers/net/wireless/rtlwifi/pci.c delete mode 100644 drivers/net/wireless/rtlwifi/pci.h delete mode 100644 drivers/net/wireless/rtlwifi/ps.c delete mode 100644 drivers/net/wireless/rtlwifi/ps.h delete mode 100644 drivers/net/wireless/rtlwifi/pwrseqcmd.h delete mode 100644 drivers/net/wireless/rtlwifi/rc.c delete mode 100644 drivers/net/wireless/rtlwifi/rc.h delete mode 100644 drivers/net/wireless/rtlwifi/regd.c delete mode 100644 drivers/net/wireless/rtlwifi/regd.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/def.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/dm.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/dm.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/fw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/fw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/hw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/hw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/led.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/led.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/phy.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/phy.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/reg.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/rf.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/rf.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/sw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/sw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/table.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/table.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/trx.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8188ee/trx.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192c/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192c/main.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/def.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/dm.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/dm.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/hw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/hw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/led.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/led.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/phy.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/phy.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/reg.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/rf.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/rf.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/sw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/sw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/table.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/table.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/trx.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ce/trx.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/def.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/dm.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/dm.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/hw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/hw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/led.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/led.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/mac.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/mac.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/phy.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/phy.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/reg.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/rf.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/rf.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/sw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/sw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/table.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/table.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/trx.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192cu/trx.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/def.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/dm.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/dm.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/fw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/fw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/hw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/hw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/led.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/led.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/phy.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/phy.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/reg.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/rf.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/rf.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/sw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/sw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/table.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/table.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/trx.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192de/trx.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/def.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/dm.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/dm.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/fw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/fw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/hw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/hw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/led.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/led.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/phy.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/phy.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/reg.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/rf.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/rf.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/sw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/sw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/table.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/table.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/trx.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192ee/trx.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/def.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/dm.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/dm.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/fw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/fw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/hw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/hw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/led.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/led.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/phy.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/phy.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/reg.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/rf.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/rf.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/sw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/sw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/table.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/table.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/trx.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8192se/trx.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/btc.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/def.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/dm.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/dm.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/fw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/fw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/hw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/hw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/led.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/led.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/phy.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/phy.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/reg.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/rf.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/rf.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/sw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/sw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/table.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/table.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/trx.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723ae/trx.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/def.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/dm.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/dm.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/fw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/fw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/hw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/hw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/led.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/led.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/phy.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/phy.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/reg.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/rf.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/rf.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/sw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/sw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/table.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/table.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/trx.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723be/trx.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723com/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723com/dm_common.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723com/dm_common.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723com/fw_common.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723com/main.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723com/phy_common.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8723com/phy_common.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/Makefile delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/def.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/dm.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/dm.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/fw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/fw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/hw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/hw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/led.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/led.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/phy.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/phy.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/reg.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/rf.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/rf.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/sw.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/sw.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/table.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/table.h delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/trx.c delete mode 100644 drivers/net/wireless/rtlwifi/rtl8821ae/trx.h delete mode 100644 drivers/net/wireless/rtlwifi/stats.c delete mode 100644 drivers/net/wireless/rtlwifi/stats.h delete mode 100644 drivers/net/wireless/rtlwifi/usb.c delete mode 100644 drivers/net/wireless/rtlwifi/usb.h delete mode 100644 drivers/net/wireless/rtlwifi/wifi.h (limited to 'drivers/net') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index a63ab2e83105..91907c4b8bcf 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -214,8 +214,6 @@ config USB_NET_RNDIS_WLAN If you choose to build a module, it'll be called rndis_wlan. -source "drivers/net/wireless/rtl818x/Kconfig" - config ADM8211 tristate "ADMtek ADM8211 support" depends on MAC80211 && PCI @@ -243,6 +241,8 @@ config ADM8211 Thanks to Infineon-ADMtek for their support of this driver. +source "drivers/net/wireless/realtek/rtl818x/Kconfig" + config MAC80211_HWSIM tristate "Simulated radio testing tool for mac80211" depends on MAC80211 @@ -278,7 +278,7 @@ source "drivers/net/wireless/orinoco/Kconfig" source "drivers/net/wireless/p54/Kconfig" source "drivers/net/wireless/rt2x00/Kconfig" source "drivers/net/wireless/mediatek/Kconfig" -source "drivers/net/wireless/rtlwifi/Kconfig" +source "drivers/net/wireless/realtek/rtlwifi/Kconfig" source "drivers/net/wireless/ti/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" source "drivers/net/wireless/mwifiex/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 6b9e729dd8ac..740fdd353c5d 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -22,9 +22,7 @@ obj-$(CONFIG_HOSTAP) += hostap/ obj-$(CONFIG_B43) += b43/ obj-$(CONFIG_B43LEGACY) += b43legacy/ obj-$(CONFIG_ZD1211RW) += zd1211rw/ -obj-$(CONFIG_RTL8180) += rtl818x/ -obj-$(CONFIG_RTL8187) += rtl818x/ -obj-$(CONFIG_RTLWIFI) += rtlwifi/ +obj-$(CONFIG_WLAN) += realtek/ # 16-bit wireless PCMCIA client drivers obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o diff --git a/drivers/net/wireless/realtek/Makefile b/drivers/net/wireless/realtek/Makefile new file mode 100644 index 000000000000..3489b98979f8 --- /dev/null +++ b/drivers/net/wireless/realtek/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the Linux Wireless network device drivers for Realtek units +# + +obj-$(CONFIG_RTL8180) += rtl818x/ +obj-$(CONFIG_RTL8187) += rtl818x/ +obj-$(CONFIG_RTLWIFI) += rtlwifi/ + diff --git a/drivers/net/wireless/realtek/rtl818x/Kconfig b/drivers/net/wireless/realtek/rtl818x/Kconfig new file mode 100644 index 000000000000..1ce1d55f0010 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/Kconfig @@ -0,0 +1,88 @@ +# +# RTL818X Wireless LAN device configuration +# +config RTL8180 + tristate "Realtek 8180/8185/8187SE PCI support" + depends on MAC80211 && PCI + select EEPROM_93CX6 + ---help--- + This is a driver for RTL8180, RTL8185 and RTL8187SE based cards. + These are PCI based chips found in cards such as: + + (RTL8185 802.11g) + A-Link WL54PC + + (RTL8180 802.11b) + Belkin F5D6020 v3 + Belkin F5D6020 v3 + Dlink DWL-610 + Dlink DWL-510 + Netgear MA521 + Level-One WPC-0101 + Acer Aspire 1357 LMi + VCTnet PC-11B1 + Ovislink AirLive WL-1120PCM + Mentor WL-PCI + Linksys WPC11 v4 + TrendNET TEW-288PI + D-Link DWL-520 Rev D + Repotec RP-WP7126 + TP-Link TL-WN250/251 + Zonet ZEW1000 + Longshine LCS-8031-R + HomeLine HLW-PCC200 + GigaFast WF721-AEX + Planet WL-3553 + Encore ENLWI-PCI1-NT + TrendNET TEW-266PC + Gigabyte GN-WLMR101 + Siemens-fujitsu Amilo D1840W + Edimax EW-7126 + PheeNet WL-11PCIR + Tonze PC-2100T + Planet WL-8303 + Dlink DWL-650 v M1 + Edimax EW-7106 + Q-Tec 770WC + Topcom Skyr@cer 4011b + Roper FreeLan 802.11b (edition 2004) + Wistron Neweb Corp CB-200B + Pentagram HorNET + QTec 775WC + TwinMOS Booming B Series + Micronet SP906BB + Sweex LC700010 + Surecom EP-9428 + Safecom SWLCR-1100 + + Thanks to Realtek for their support! + +config RTL8187 + tristate "Realtek 8187 and 8187B USB support" + depends on MAC80211 && USB + select EEPROM_93CX6 + ---help--- + This is a driver for RTL8187 and RTL8187B based cards. + These are USB based chips found in devices such as: + + Netgear WG111v2 + Level 1 WNC-0301USB + Micronet SP907GK V5 + Encore ENUWI-G2 + Trendnet TEW-424UB + ASUS P5B Deluxe/P5K Premium motherboards + Toshiba Satellite Pro series of laptops + Asus Wireless Link + Linksys WUSB54GC-EU v2 + (v1 = rt73usb; v3 is rt2070-based, + use staging/rt3070 or try rt2800usb) + + Thanks to Realtek for their support! + +# If possible, automatically enable LEDs for RTL8187. + +config RTL8187_LEDS + bool + depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187) + default y + diff --git a/drivers/net/wireless/realtek/rtl818x/Makefile b/drivers/net/wireless/realtek/rtl818x/Makefile new file mode 100644 index 000000000000..997569076923 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_RTL8180) += rtl8180/ +obj-$(CONFIG_RTL8187) += rtl8187/ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile b/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile new file mode 100644 index 000000000000..2966681efaef --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/Makefile @@ -0,0 +1,5 @@ +rtl818x_pci-objs := dev.o rtl8225.o sa2400.o max2820.o grf5101.o rtl8225se.o + +obj-$(CONFIG_RTL8180) += rtl818x_pci.o + +ccflags-y += -Idrivers/net/wireless/realtek/rtl818x diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c new file mode 100644 index 000000000000..a43a16fde59d --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c @@ -0,0 +1,1991 @@ + +/* Linux device driver for RTL8180 / RTL8185 / RTL8187SE + * + * Copyright 2007 Michael Wu + * Copyright 2007,2014 Andrea Merello + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * + * Thanks to Realtek for their support! + * + ************************************************************************ + * + * The driver was extended to the RTL8187SE in 2014 by + * Andrea Merello + * + * based also on: + * - portions of rtl8187se Linux staging driver, Copyright Realtek corp. + * (available in drivers/staging/rtl8187se directory of Linux 3.14) + * - other GPL, unpublished (until now), Linux driver code, + * Copyright Larry Finger + * + * A huge thanks goes to Sara V. Nari who forgives me when I'm + * sitting in front of my laptop at evening, week-end, night... + * + * A special thanks goes to Antonio Cuni, who helped me with + * some python userspace stuff I used to debug RTL8187SE code, and who + * bought a laptop with an unsupported Wi-Fi card some years ago... + * + * Thanks to Larry Finger for writing some code for rtl8187se and for + * his suggestions. + * + * Thanks to Dan Carpenter for reviewing my initial patch and for his + * suggestions. + * + * Thanks to Bernhard Schiffner for his help in testing and for his + * suggestions. + * + ************************************************************************ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rtl8180.h" +#include "rtl8225.h" +#include "sa2400.h" +#include "max2820.h" +#include "grf5101.h" +#include "rtl8225se.h" + +MODULE_AUTHOR("Michael Wu "); +MODULE_AUTHOR("Andrea Merello "); +MODULE_DESCRIPTION("RTL8180 / RTL8185 / RTL8187SE PCI wireless driver"); +MODULE_LICENSE("GPL"); + +static const struct pci_device_id rtl8180_table[] = { + + /* rtl8187se */ + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8199) }, + + /* rtl8185 */ + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) }, + { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x700f) }, + { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x701f) }, + + /* rtl8180 */ + { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8180) }, + { PCI_DEVICE(0x1799, 0x6001) }, + { PCI_DEVICE(0x1799, 0x6020) }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x3300) }, + { PCI_DEVICE(0x1186, 0x3301) }, + { PCI_DEVICE(0x1432, 0x7106) }, + { } +}; + +MODULE_DEVICE_TABLE(pci, rtl8180_table); + +static const struct ieee80211_rate rtl818x_rates[] = { + { .bitrate = 10, .hw_value = 0, }, + { .bitrate = 20, .hw_value = 1, }, + { .bitrate = 55, .hw_value = 2, }, + { .bitrate = 110, .hw_value = 3, }, + { .bitrate = 60, .hw_value = 4, }, + { .bitrate = 90, .hw_value = 5, }, + { .bitrate = 120, .hw_value = 6, }, + { .bitrate = 180, .hw_value = 7, }, + { .bitrate = 240, .hw_value = 8, }, + { .bitrate = 360, .hw_value = 9, }, + { .bitrate = 480, .hw_value = 10, }, + { .bitrate = 540, .hw_value = 11, }, +}; + +static const struct ieee80211_channel rtl818x_channels[] = { + { .center_freq = 2412 }, + { .center_freq = 2417 }, + { .center_freq = 2422 }, + { .center_freq = 2427 }, + { .center_freq = 2432 }, + { .center_freq = 2437 }, + { .center_freq = 2442 }, + { .center_freq = 2447 }, + { .center_freq = 2452 }, + { .center_freq = 2457 }, + { .center_freq = 2462 }, + { .center_freq = 2467 }, + { .center_freq = 2472 }, + { .center_freq = 2484 }, +}; + +/* Queues for rtl8187se card + * + * name | reg | queue + * BC | 7 | 6 + * MG | 1 | 0 + * HI | 6 | 1 + * VO | 5 | 2 + * VI | 4 | 3 + * BE | 3 | 4 + * BK | 2 | 5 + * + * The complete map for DMA kick reg using use all queue is: + * static const int rtl8187se_queues_map[RTL8187SE_NR_TX_QUEUES] = + * {1, 6, 5, 4, 3, 2, 7}; + * + * .. but.. Because for mac80211 4 queues are enough for QoS we use this + * + * name | reg | queue + * BC | 7 | 4 <- currently not used yet + * MG | 1 | x <- Not used + * HI | 6 | x <- Not used + * VO | 5 | 0 <- used + * VI | 4 | 1 <- used + * BE | 3 | 2 <- used + * BK | 2 | 3 <- used + * + * Beacon queue could be used, but this is not finished yet. + * + * I thougth about using the other two queues but I decided not to do this: + * + * - I'm unsure whether the mac80211 will ever try to use more than 4 queues + * by itself. + * + * - I could route MGMT frames (currently sent over VO queue) to the MGMT + * queue but since mac80211 will do not know about it, I will probably gain + * some HW priority whenever the VO queue is not empty, but this gain is + * limited by the fact that I had to stop the mac80211 queue whenever one of + * the VO or MGMT queues is full, stopping also submitting of MGMT frame + * to the driver. + * + * - I don't know how to set in the HW the contention window params for MGMT + * and HI-prio queues. + */ + +static const int rtl8187se_queues_map[RTL8187SE_NR_TX_QUEUES] = {5, 4, 3, 2, 7}; + +/* Queues for rtl8180/rtl8185 cards + * + * name | reg | prio + * BC | 7 | 3 + * HI | 6 | 0 + * NO | 5 | 1 + * LO | 4 | 2 + * + * The complete map for DMA kick reg using all queue is: + * static const int rtl8180_queues_map[RTL8180_NR_TX_QUEUES] = {6, 5, 4, 7}; + * + * .. but .. Because the mac80211 needs at least 4 queues for QoS or + * otherwise QoS can't be done, we use just one. + * Beacon queue could be used, but this is not finished yet. + * Actual map is: + * + * name | reg | prio + * BC | 7 | 1 <- currently not used yet. + * HI | 6 | x <- not used + * NO | 5 | x <- not used + * LO | 4 | 0 <- used + */ + +static const int rtl8180_queues_map[RTL8180_NR_TX_QUEUES] = {4, 7}; + +/* LNA gain table for rtl8187se */ +static const u8 rtl8187se_lna_gain[4] = {02, 17, 29, 39}; + +void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) +{ + struct rtl8180_priv *priv = dev->priv; + int i = 10; + u32 buf; + + buf = (data << 8) | addr; + + rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->PHY[0], buf | 0x80); + while (i--) { + rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->PHY[0], buf); + if (rtl818x_ioread8(priv, &priv->map->PHY[2]) == (data & 0xFF)) + return; + } +} + +static void rtl8180_handle_rx(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + struct rtl818x_rx_cmd_desc *cmd_desc; + unsigned int count = 32; + u8 agc, sq; + s8 signal = 1; + dma_addr_t mapping; + + while (count--) { + void *entry = priv->rx_ring + priv->rx_idx * priv->rx_ring_sz; + struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; + u32 flags, flags2, flags3 = 0; + u64 tsft; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + struct rtl8187se_rx_desc *desc = entry; + + flags = le32_to_cpu(desc->flags); + /* if ownership flag is set, then we can trust the + * HW has written other fields. We must not trust + * other descriptor data read before we checked (read) + * the ownership flag + */ + rmb(); + flags3 = le32_to_cpu(desc->flags3); + flags2 = le32_to_cpu(desc->flags2); + tsft = le64_to_cpu(desc->tsft); + } else { + struct rtl8180_rx_desc *desc = entry; + + flags = le32_to_cpu(desc->flags); + /* same as above */ + rmb(); + flags2 = le32_to_cpu(desc->flags2); + tsft = le64_to_cpu(desc->tsft); + } + + if (flags & RTL818X_RX_DESC_FLAG_OWN) + return; + + if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | + RTL818X_RX_DESC_FLAG_FOF | + RTL818X_RX_DESC_FLAG_RX_ERR))) + goto done; + else { + struct ieee80211_rx_status rx_status = {0}; + struct sk_buff *new_skb = dev_alloc_skb(MAX_RX_SIZE); + + if (unlikely(!new_skb)) + goto done; + + mapping = pci_map_single(priv->pdev, + skb_tail_pointer(new_skb), + MAX_RX_SIZE, PCI_DMA_FROMDEVICE); + + if (pci_dma_mapping_error(priv->pdev, mapping)) { + kfree_skb(new_skb); + dev_err(&priv->pdev->dev, "RX DMA map error\n"); + + goto done; + } + + pci_unmap_single(priv->pdev, + *((dma_addr_t *)skb->cb), + MAX_RX_SIZE, PCI_DMA_FROMDEVICE); + skb_put(skb, flags & 0xFFF); + + rx_status.antenna = (flags2 >> 15) & 1; + rx_status.rate_idx = (flags >> 20) & 0xF; + agc = (flags2 >> 17) & 0x7F; + + switch (priv->chip_family) { + case RTL818X_CHIP_FAMILY_RTL8185: + if (rx_status.rate_idx > 3) + signal = -clamp_t(u8, agc, 25, 90) - 9; + else + signal = -clamp_t(u8, agc, 30, 95); + break; + case RTL818X_CHIP_FAMILY_RTL8180: + sq = flags2 & 0xff; + signal = priv->rf->calc_rssi(agc, sq); + break; + case RTL818X_CHIP_FAMILY_RTL8187SE: + /* OFDM measure reported by HW is signed, + * in 0.5dBm unit, with zero centered @ -41dBm + * input signal. + */ + if (rx_status.rate_idx > 3) { + signal = (s8)((flags3 >> 16) & 0xff); + signal = signal / 2 - 41; + } else { + int idx, bb; + + idx = (agc & 0x60) >> 5; + bb = (agc & 0x1F) * 2; + /* bias + BB gain + LNA gain */ + signal = 4 - bb - rtl8187se_lna_gain[idx]; + } + break; + } + rx_status.signal = signal; + rx_status.freq = dev->conf.chandef.chan->center_freq; + rx_status.band = dev->conf.chandef.chan->band; + rx_status.mactime = tsft; + rx_status.flag |= RX_FLAG_MACTIME_START; + if (flags & RTL818X_RX_DESC_FLAG_SPLCP) + rx_status.flag |= RX_FLAG_SHORTPRE; + if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) + rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; + + memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); + ieee80211_rx_irqsafe(dev, skb); + + skb = new_skb; + priv->rx_buf[priv->rx_idx] = skb; + *((dma_addr_t *) skb->cb) = mapping; + } + + done: + cmd_desc = entry; + cmd_desc->rx_buf = cpu_to_le32(*((dma_addr_t *)skb->cb)); + cmd_desc->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN | + MAX_RX_SIZE); + if (priv->rx_idx == 31) + cmd_desc->flags |= + cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); + priv->rx_idx = (priv->rx_idx + 1) % 32; + } +} + +static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) +{ + struct rtl8180_priv *priv = dev->priv; + struct rtl8180_tx_ring *ring = &priv->tx_ring[prio]; + + while (skb_queue_len(&ring->queue)) { + struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb; + struct ieee80211_tx_info *info; + u32 flags = le32_to_cpu(entry->flags); + + if (flags & RTL818X_TX_DESC_FLAG_OWN) + return; + + ring->idx = (ring->idx + 1) % ring->entries; + skb = __skb_dequeue(&ring->queue); + pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), + skb->len, PCI_DMA_TODEVICE); + + info = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(info); + + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && + (flags & RTL818X_TX_DESC_FLAG_TX_OK)) + info->flags |= IEEE80211_TX_STAT_ACK; + + info->status.rates[0].count = (flags & 0xFF) + 1; + + ieee80211_tx_status_irqsafe(dev, skb); + if (ring->entries - skb_queue_len(&ring->queue) == 2) + ieee80211_wake_queue(dev, prio); + } +} + +static irqreturn_t rtl8187se_interrupt(int irq, void *dev_id) +{ + struct ieee80211_hw *dev = dev_id; + struct rtl8180_priv *priv = dev->priv; + u32 reg; + unsigned long flags; + static int desc_err; + + spin_lock_irqsave(&priv->lock, flags); + /* Note: 32-bit interrupt status */ + reg = rtl818x_ioread32(priv, &priv->map->INT_STATUS_SE); + if (unlikely(reg == 0xFFFFFFFF)) { + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_HANDLED; + } + + rtl818x_iowrite32(priv, &priv->map->INT_STATUS_SE, reg); + + if (reg & IMR_TIMEOUT1) + rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); + + if (reg & (IMR_TBDOK | IMR_TBDER)) + rtl8180_handle_tx(dev, 4); + + if (reg & (IMR_TVODOK | IMR_TVODER)) + rtl8180_handle_tx(dev, 0); + + if (reg & (IMR_TVIDOK | IMR_TVIDER)) + rtl8180_handle_tx(dev, 1); + + if (reg & (IMR_TBEDOK | IMR_TBEDER)) + rtl8180_handle_tx(dev, 2); + + if (reg & (IMR_TBKDOK | IMR_TBKDER)) + rtl8180_handle_tx(dev, 3); + + if (reg & (IMR_ROK | IMR_RER | RTL818X_INT_SE_RX_DU | IMR_RQOSOK)) + rtl8180_handle_rx(dev); + /* The interface sometimes generates several RX DMA descriptor errors + * at startup. Do not report these. + */ + if ((reg & RTL818X_INT_SE_RX_DU) && desc_err++ > 2) + if (net_ratelimit()) + wiphy_err(dev->wiphy, "No RX DMA Descriptor avail\n"); + + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_HANDLED; +} + +static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) +{ + struct ieee80211_hw *dev = dev_id; + struct rtl8180_priv *priv = dev->priv; + u16 reg; + + spin_lock(&priv->lock); + reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); + if (unlikely(reg == 0xFFFF)) { + spin_unlock(&priv->lock); + return IRQ_HANDLED; + } + + rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); + + if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR)) + rtl8180_handle_tx(dev, 1); + + if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR)) + rtl8180_handle_tx(dev, 0); + + if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR)) + rtl8180_handle_rx(dev); + + spin_unlock(&priv->lock); + + return IRQ_HANDLED; +} + +static void rtl8180_tx(struct ieee80211_hw *dev, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct rtl8180_priv *priv = dev->priv; + struct rtl8180_tx_ring *ring; + struct rtl8180_tx_desc *entry; + unsigned long flags; + unsigned int idx, prio, hw_prio; + dma_addr_t mapping; + u32 tx_flags; + u8 rc_flags; + u16 plcp_len = 0; + __le16 rts_duration = 0; + /* do arithmetic and then convert to le16 */ + u16 frame_duration = 0; + + prio = skb_get_queue_mapping(skb); + ring = &priv->tx_ring[prio]; + + mapping = pci_map_single(priv->pdev, skb->data, + skb->len, PCI_DMA_TODEVICE); + + if (pci_dma_mapping_error(priv->pdev, mapping)) { + kfree_skb(skb); + dev_err(&priv->pdev->dev, "TX DMA mapping error\n"); + return; + } + + tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS | + RTL818X_TX_DESC_FLAG_LS | + (ieee80211_get_tx_rate(dev, info)->hw_value << 24) | + skb->len; + + if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) + tx_flags |= RTL818X_TX_DESC_FLAG_DMA | + RTL818X_TX_DESC_FLAG_NO_ENC; + + rc_flags = info->control.rates[0].flags; + + /* HW will perform RTS-CTS when only RTS flags is set. + * HW will perform CTS-to-self when both RTS and CTS flags are set. + * RTS rate and RTS duration will be used also for CTS-to-self. + */ + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { + tx_flags |= RTL818X_TX_DESC_FLAG_RTS; + tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; + rts_duration = ieee80211_rts_duration(dev, priv->vif, + skb->len, info); + } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + tx_flags |= RTL818X_TX_DESC_FLAG_RTS | RTL818X_TX_DESC_FLAG_CTS; + tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; + rts_duration = ieee80211_ctstoself_duration(dev, priv->vif, + skb->len, info); + } + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) { + unsigned int remainder; + + plcp_len = DIV_ROUND_UP(16 * (skb->len + 4), + (ieee80211_get_tx_rate(dev, info)->bitrate * 2) / 10); + remainder = (16 * (skb->len + 4)) % + ((ieee80211_get_tx_rate(dev, info)->bitrate * 2) / 10); + if (remainder <= 6) + plcp_len |= 1 << 15; + } + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + __le16 duration; + /* SIFS time (required by HW) is already included by + * ieee80211_generic_frame_duration + */ + duration = ieee80211_generic_frame_duration(dev, priv->vif, + IEEE80211_BAND_2GHZ, skb->len, + ieee80211_get_tx_rate(dev, info)); + + frame_duration = priv->ack_time + le16_to_cpu(duration); + } + + spin_lock_irqsave(&priv->lock, flags); + + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + priv->seqno += 0x10; + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(priv->seqno); + } + + idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; + entry = &ring->desc[idx]; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + entry->frame_duration = cpu_to_le16(frame_duration); + entry->frame_len_se = cpu_to_le16(skb->len); + + /* tpc polarity */ + entry->flags3 = cpu_to_le16(1<<4); + } else + entry->frame_len = cpu_to_le32(skb->len); + + entry->rts_duration = rts_duration; + entry->plcp_len = cpu_to_le16(plcp_len); + entry->tx_buf = cpu_to_le32(mapping); + + entry->retry_limit = info->control.rates[0].count - 1; + + /* We must be sure that tx_flags is written last because the HW + * looks at it to check if the rest of data is valid or not + */ + wmb(); + entry->flags = cpu_to_le32(tx_flags); + /* We must be sure this has been written before followings HW + * register write, because this write will made the HW attempts + * to DMA the just-written data + */ + wmb(); + + __skb_queue_tail(&ring->queue, skb); + if (ring->entries - skb_queue_len(&ring->queue) < 2) + ieee80211_stop_queue(dev, prio); + + spin_unlock_irqrestore(&priv->lock, flags); + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + /* just poll: rings are stopped with TPPollStop reg */ + hw_prio = rtl8187se_queues_map[prio]; + rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, + (1 << hw_prio)); + } else { + hw_prio = rtl8180_queues_map[prio]; + rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, + (1 << hw_prio) | /* ring to poll */ + (1<<1) | (1<<2));/* stopped rings */ + } +} + +static void rtl8180_set_anaparam3(struct rtl8180_priv *priv, u16 anaparam3) +{ + u8 reg; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + + rtl818x_iowrite16(priv, &priv->map->ANAPARAM3, anaparam3); + + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); +} + +void rtl8180_set_anaparam2(struct rtl8180_priv *priv, u32 anaparam2) +{ + u8 reg; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, anaparam2); + + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); +} + +void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam) +{ + u8 reg; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, anaparam); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); +} + +static void rtl8187se_mac_config(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + u8 reg; + + rtl818x_iowrite32(priv, REG_ADDR4(0x1F0), 0); + rtl818x_ioread32(priv, REG_ADDR4(0x1F0)); + rtl818x_iowrite32(priv, REG_ADDR4(0x1F4), 0); + rtl818x_ioread32(priv, REG_ADDR4(0x1F4)); + rtl818x_iowrite8(priv, REG_ADDR1(0x1F8), 0); + rtl818x_ioread8(priv, REG_ADDR1(0x1F8)); + /* Enable DA10 TX power saving */ + reg = rtl818x_ioread8(priv, &priv->map->PHY_PR); + rtl818x_iowrite8(priv, &priv->map->PHY_PR, reg | 0x04); + /* Power */ + rtl818x_iowrite16(priv, PI_DATA_REG, 0x1000); + rtl818x_iowrite16(priv, SI_DATA_REG, 0x1000); + /* AFE - default to power ON */ + rtl818x_iowrite16(priv, REG_ADDR2(0x370), 0x0560); + rtl818x_iowrite16(priv, REG_ADDR2(0x372), 0x0560); + rtl818x_iowrite16(priv, REG_ADDR2(0x374), 0x0DA4); + rtl818x_iowrite16(priv, REG_ADDR2(0x376), 0x0DA4); + rtl818x_iowrite16(priv, REG_ADDR2(0x378), 0x0560); + rtl818x_iowrite16(priv, REG_ADDR2(0x37A), 0x0560); + rtl818x_iowrite16(priv, REG_ADDR2(0x37C), 0x00EC); + rtl818x_iowrite16(priv, REG_ADDR2(0x37E), 0x00EC); + rtl818x_iowrite8(priv, REG_ADDR1(0x24E), 0x01); + /* unknown, needed for suspend to RAM resume */ + rtl818x_iowrite8(priv, REG_ADDR1(0x0A), 0x72); +} + +static void rtl8187se_set_antenna_config(struct ieee80211_hw *dev, u8 def_ant, + bool diversity) +{ + struct rtl8180_priv *priv = dev->priv; + + rtl8225_write_phy_cck(dev, 0x0C, 0x09); + if (diversity) { + if (def_ant == 1) { + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x00); + rtl8225_write_phy_cck(dev, 0x11, 0xBB); + rtl8225_write_phy_cck(dev, 0x01, 0xC7); + rtl8225_write_phy_ofdm(dev, 0x0D, 0x54); + rtl8225_write_phy_ofdm(dev, 0x18, 0xB2); + } else { /* main antenna */ + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); + rtl8225_write_phy_cck(dev, 0x11, 0x9B); + rtl8225_write_phy_cck(dev, 0x01, 0xC7); + rtl8225_write_phy_ofdm(dev, 0x0D, 0x5C); + rtl8225_write_phy_ofdm(dev, 0x18, 0xB2); + } + } else { /* disable antenna diversity */ + if (def_ant == 1) { + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x00); + rtl8225_write_phy_cck(dev, 0x11, 0xBB); + rtl8225_write_phy_cck(dev, 0x01, 0x47); + rtl8225_write_phy_ofdm(dev, 0x0D, 0x54); + rtl8225_write_phy_ofdm(dev, 0x18, 0x32); + } else { /* main antenna */ + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); + rtl8225_write_phy_cck(dev, 0x11, 0x9B); + rtl8225_write_phy_cck(dev, 0x01, 0x47); + rtl8225_write_phy_ofdm(dev, 0x0D, 0x5C); + rtl8225_write_phy_ofdm(dev, 0x18, 0x32); + } + } + /* priv->curr_ant = def_ant; */ +} + +static void rtl8180_int_enable(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + rtl818x_iowrite32(priv, &priv->map->IMR, + IMR_TBDER | IMR_TBDOK | + IMR_TVODER | IMR_TVODOK | + IMR_TVIDER | IMR_TVIDOK | + IMR_TBEDER | IMR_TBEDOK | + IMR_TBKDER | IMR_TBKDOK | + IMR_RDU | IMR_RER | + IMR_ROK | IMR_RQOSOK); + } else { + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); + } +} + +static void rtl8180_int_disable(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + rtl818x_iowrite32(priv, &priv->map->IMR, 0); + } else { + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); + } +} + +static void rtl8180_conf_basic_rates(struct ieee80211_hw *dev, + u32 basic_mask) +{ + struct rtl8180_priv *priv = dev->priv; + u16 reg; + u32 resp_mask; + u8 basic_max; + u8 resp_max, resp_min; + + resp_mask = basic_mask; + /* IEEE80211 says the response rate should be equal to the highest basic + * rate that is not faster than received frame. But it says also that if + * the basic rate set does not contains any rate for the current + * modulation class then mandatory rate set must be used for that + * modulation class. Eventually add OFDM mandatory rates.. + */ + if ((resp_mask & 0xf) == resp_mask) + resp_mask |= 0x150; /* 6, 12, 24Mbps */ + + switch (priv->chip_family) { + + case RTL818X_CHIP_FAMILY_RTL8180: + /* in 8180 this is NOT a BITMAP */ + basic_max = fls(basic_mask) - 1; + reg = rtl818x_ioread16(priv, &priv->map->BRSR); + reg &= ~3; + reg |= basic_max; + rtl818x_iowrite16(priv, &priv->map->BRSR, reg); + break; + + case RTL818X_CHIP_FAMILY_RTL8185: + resp_max = fls(resp_mask) - 1; + resp_min = ffs(resp_mask) - 1; + /* in 8185 this is a BITMAP */ + rtl818x_iowrite16(priv, &priv->map->BRSR, basic_mask); + rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (resp_max << 4) | + resp_min); + break; + + case RTL818X_CHIP_FAMILY_RTL8187SE: + /* in 8187se this is a BITMAP. BRSR reg actually sets + * response rates. + */ + rtl818x_iowrite16(priv, &priv->map->BRSR_8187SE, resp_mask); + break; + } +} + +static void rtl8180_config_cardbus(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + u16 reg16; + u8 reg8; + + reg8 = rtl818x_ioread8(priv, &priv->map->CONFIG3); + reg8 |= 1 << 1; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg8); + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + rtl818x_iowrite16(priv, FEMR_SE, 0xffff); + } else { + reg16 = rtl818x_ioread16(priv, &priv->map->FEMR); + reg16 |= (1 << 15) | (1 << 14) | (1 << 4); + rtl818x_iowrite16(priv, &priv->map->FEMR, reg16); + } + +} + +static int rtl8180_init_hw(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + u16 reg; + u32 reg32; + + rtl818x_iowrite8(priv, &priv->map->CMD, 0); + rtl818x_ioread8(priv, &priv->map->CMD); + msleep(10); + + /* reset */ + rtl8180_int_disable(dev); + rtl818x_ioread8(priv, &priv->map->CMD); + + reg = rtl818x_ioread8(priv, &priv->map->CMD); + reg &= (1 << 1); + reg |= RTL818X_CMD_RESET; + rtl818x_iowrite8(priv, &priv->map->CMD, RTL818X_CMD_RESET); + rtl818x_ioread8(priv, &priv->map->CMD); + msleep(200); + + /* check success of reset */ + if (rtl818x_ioread8(priv, &priv->map->CMD) & RTL818X_CMD_RESET) { + wiphy_err(dev->wiphy, "reset timeout!\n"); + return -ETIMEDOUT; + } + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD); + rtl818x_ioread8(priv, &priv->map->CMD); + msleep(200); + + if (rtl818x_ioread8(priv, &priv->map->CONFIG3) & (1 << 3)) { + rtl8180_config_cardbus(dev); + } + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_ENEDCA); + else + rtl818x_iowrite8(priv, &priv->map->MSR, 0); + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) + rtl8180_set_anaparam(priv, priv->anaparam); + + rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma); + /* mac80211 queue have higher prio for lower index. The last queue + * (that mac80211 is not aware of) is reserved for beacons (and have + * the highest priority on the NIC) + */ + if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8187SE) { + rtl818x_iowrite32(priv, &priv->map->TBDA, + priv->tx_ring[1].dma); + rtl818x_iowrite32(priv, &priv->map->TLPDA, + priv->tx_ring[0].dma); + } else { + rtl818x_iowrite32(priv, &priv->map->TBDA, + priv->tx_ring[4].dma); + rtl818x_iowrite32(priv, &priv->map->TVODA, + priv->tx_ring[0].dma); + rtl818x_iowrite32(priv, &priv->map->TVIDA, + priv->tx_ring[1].dma); + rtl818x_iowrite32(priv, &priv->map->TBEDA, + priv->tx_ring[2].dma); + rtl818x_iowrite32(priv, &priv->map->TBKDA, + priv->tx_ring[3].dma); + } + + /* TODO: necessary? specs indicate not */ + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG2); + rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg & ~(1 << 3)); + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) { + reg = rtl818x_ioread8(priv, &priv->map->CONFIG2); + rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg | (1 << 4)); + } + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + /* TODO: set CONFIG5 for calibrating AGC on rtl8180 + philips radio? */ + + /* TODO: turn off hw wep on rtl8180 */ + + rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); + + if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { + rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); + rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0); + } else { + rtl818x_iowrite8(priv, &priv->map->SECURITY, 0); + + rtl818x_iowrite8(priv, &priv->map->PHY_DELAY, 0x6); + rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, 0x4C); + } + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) { + /* TODO: set ClkRun enable? necessary? */ + reg = rtl818x_ioread8(priv, &priv->map->GP_ENABLE); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, reg & ~(1 << 6)); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | (1 << 2)); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + /* fix eccessive IFS after CTS-to-self */ + if (priv->map_pio) { + u8 reg; + + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1); + rtl818x_iowrite8(priv, REG_ADDR1(0xff), 0x35); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + } else + rtl818x_iowrite8(priv, REG_ADDR1(0x1ff), 0x35); + } + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + + /* the set auto rate fallback bitmask from 1M to 54 Mb/s */ + rtl818x_iowrite16(priv, ARFR, 0xFFF); + rtl818x_ioread16(priv, ARFR); + + /* stop unused queus (no dma alloc) */ + rtl818x_iowrite8(priv, &priv->map->TPPOLL_STOP, + RTL818x_TPPOLL_STOP_MG | RTL818x_TPPOLL_STOP_HI); + + rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0x00); + rtl818x_iowrite16(priv, &priv->map->TID_AC_MAP, 0xFA50); + + rtl818x_iowrite16(priv, &priv->map->INT_MIG, 0); + + /* some black magic here.. */ + rtl8187se_mac_config(dev); + + rtl818x_iowrite16(priv, RFSW_CTRL, 0x569A); + rtl818x_ioread16(priv, RFSW_CTRL); + + rtl8180_set_anaparam(priv, RTL8225SE_ANAPARAM_ON); + rtl8180_set_anaparam2(priv, RTL8225SE_ANAPARAM2_ON); + rtl8180_set_anaparam3(priv, RTL8225SE_ANAPARAM3); + + + rtl818x_iowrite8(priv, &priv->map->CONFIG5, + rtl818x_ioread8(priv, &priv->map->CONFIG5) & 0x7F); + + /*probably this switch led on */ + rtl818x_iowrite8(priv, &priv->map->PGSELECT, + rtl818x_ioread8(priv, &priv->map->PGSELECT) | 0x08); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1BFF); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488); + + rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x4003); + + /* the reference code mac hardcode table write + * this reg by doing byte-wide accesses. + * It does it just for lowest and highest byte.. + */ + reg32 = rtl818x_ioread32(priv, &priv->map->RF_PARA); + reg32 &= 0x00ffff00; + reg32 |= 0xb8000054; + rtl818x_iowrite32(priv, &priv->map->RF_PARA, reg32); + } else + /* stop unused queus (no dma alloc) */ + rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, + (1<<1) | (1<<2)); + + priv->rf->init(dev); + + /* default basic rates are 1,2 Mbps for rtl8180. 1,2,6,9,12,18,24 Mbps + * otherwise. bitmask 0x3 and 0x01f3 respectively. + * NOTE: currenty rtl8225 RF code changes basic rates, so we need to do + * this after rf init. + * TODO: try to find out whether RF code really needs to do this.. + */ + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) + rtl8180_conf_basic_rates(dev, 0x3); + else + rtl8180_conf_basic_rates(dev, 0x1f3); + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + rtl8187se_set_antenna_config(dev, + priv->antenna_diversity_default, + priv->antenna_diversity_en); + return 0; +} + +static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + struct rtl818x_rx_cmd_desc *entry; + int i; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + priv->rx_ring_sz = sizeof(struct rtl8187se_rx_desc); + else + priv->rx_ring_sz = sizeof(struct rtl8180_rx_desc); + + priv->rx_ring = pci_zalloc_consistent(priv->pdev, priv->rx_ring_sz * 32, + &priv->rx_ring_dma); + if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) { + wiphy_err(dev->wiphy, "Cannot allocate RX ring\n"); + return -ENOMEM; + } + + priv->rx_idx = 0; + + for (i = 0; i < 32; i++) { + struct sk_buff *skb = dev_alloc_skb(MAX_RX_SIZE); + dma_addr_t *mapping; + entry = priv->rx_ring + priv->rx_ring_sz*i; + if (!skb) { + wiphy_err(dev->wiphy, "Cannot allocate RX skb\n"); + return -ENOMEM; + } + priv->rx_buf[i] = skb; + mapping = (dma_addr_t *)skb->cb; + *mapping = pci_map_single(priv->pdev, skb_tail_pointer(skb), + MAX_RX_SIZE, PCI_DMA_FROMDEVICE); + + if (pci_dma_mapping_error(priv->pdev, *mapping)) { + kfree_skb(skb); + wiphy_err(dev->wiphy, "Cannot map DMA for RX skb\n"); + return -ENOMEM; + } + + entry->rx_buf = cpu_to_le32(*mapping); + entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN | + MAX_RX_SIZE); + } + entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); + return 0; +} + +static void rtl8180_free_rx_ring(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + int i; + + for (i = 0; i < 32; i++) { + struct sk_buff *skb = priv->rx_buf[i]; + if (!skb) + continue; + + pci_unmap_single(priv->pdev, + *((dma_addr_t *)skb->cb), + MAX_RX_SIZE, PCI_DMA_FROMDEVICE); + kfree_skb(skb); + } + + pci_free_consistent(priv->pdev, priv->rx_ring_sz * 32, + priv->rx_ring, priv->rx_ring_dma); + priv->rx_ring = NULL; +} + +static int rtl8180_init_tx_ring(struct ieee80211_hw *dev, + unsigned int prio, unsigned int entries) +{ + struct rtl8180_priv *priv = dev->priv; + struct rtl8180_tx_desc *ring; + dma_addr_t dma; + int i; + + ring = pci_zalloc_consistent(priv->pdev, sizeof(*ring) * entries, + &dma); + if (!ring || (unsigned long)ring & 0xFF) { + wiphy_err(dev->wiphy, "Cannot allocate TX ring (prio = %d)\n", + prio); + return -ENOMEM; + } + + priv->tx_ring[prio].desc = ring; + priv->tx_ring[prio].dma = dma; + priv->tx_ring[prio].idx = 0; + priv->tx_ring[prio].entries = entries; + skb_queue_head_init(&priv->tx_ring[prio].queue); + + for (i = 0; i < entries; i++) + ring[i].next_tx_desc = + cpu_to_le32((u32)dma + ((i + 1) % entries) * sizeof(*ring)); + + return 0; +} + +static void rtl8180_free_tx_ring(struct ieee80211_hw *dev, unsigned int prio) +{ + struct rtl8180_priv *priv = dev->priv; + struct rtl8180_tx_ring *ring = &priv->tx_ring[prio]; + + while (skb_queue_len(&ring->queue)) { + struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb = __skb_dequeue(&ring->queue); + + pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), + skb->len, PCI_DMA_TODEVICE); + kfree_skb(skb); + ring->idx = (ring->idx + 1) % ring->entries; + } + + pci_free_consistent(priv->pdev, sizeof(*ring->desc)*ring->entries, + ring->desc, ring->dma); + ring->desc = NULL; +} + +static int rtl8180_start(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + int ret, i; + u32 reg; + + ret = rtl8180_init_rx_ring(dev); + if (ret) + return ret; + + for (i = 0; i < (dev->queues + 1); i++) + if ((ret = rtl8180_init_tx_ring(dev, i, 16))) + goto err_free_rings; + + ret = rtl8180_init_hw(dev); + if (ret) + goto err_free_rings; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + ret = request_irq(priv->pdev->irq, rtl8187se_interrupt, + IRQF_SHARED, KBUILD_MODNAME, dev); + } else { + ret = request_irq(priv->pdev->irq, rtl8180_interrupt, + IRQF_SHARED, KBUILD_MODNAME, dev); + } + + if (ret) { + wiphy_err(dev->wiphy, "failed to register IRQ handler\n"); + goto err_free_rings; + } + + rtl8180_int_enable(dev); + + /* in rtl8187se at MAR regs offset there is the management + * TX descriptor DMA addres.. + */ + if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8187SE) { + rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); + rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); + } + + reg = RTL818X_RX_CONF_ONLYERLPKT | + RTL818X_RX_CONF_RX_AUTORESETPHY | + RTL818X_RX_CONF_MGMT | + RTL818X_RX_CONF_DATA | + (7 << 8 /* MAX RX DMA */) | + RTL818X_RX_CONF_BROADCAST | + RTL818X_RX_CONF_NICMAC; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) + reg |= RTL818X_RX_CONF_CSDM1 | RTL818X_RX_CONF_CSDM2; + else if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) { + reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE1) + ? RTL818X_RX_CONF_CSDM1 : 0; + reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE2) + ? RTL818X_RX_CONF_CSDM2 : 0; + } else { + reg &= ~(RTL818X_RX_CONF_CSDM1 | RTL818X_RX_CONF_CSDM2); + } + + priv->rx_conf = reg; + rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); + + if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { + reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); + + /* CW is not on per-packet basis. + * in rtl8185 the CW_VALUE reg is used. + * in rtl8187se the AC param regs are used. + */ + reg &= ~RTL818X_CW_CONF_PERPACKET_CW; + /* retry limit IS on per-packet basis. + * the short and long retry limit in TX_CONF + * reg are ignored + */ + reg |= RTL818X_CW_CONF_PERPACKET_RETRY; + rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); + + reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); + /* TX antenna and TX gain are not on per-packet basis. + * TX Antenna is selected by ANTSEL reg (RX in BB regs). + * TX gain is selected with CCK_TX_AGC and OFDM_TX_AGC regs + */ + reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN; + reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL; + reg |= RTL818X_TX_AGC_CTL_FEEDBACK_ANT; + rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); + + /* disable early TX */ + rtl818x_iowrite8(priv, (u8 __iomem *)priv->map + 0xec, 0x3f); + } + + reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); + reg |= (6 << 21 /* MAX TX DMA */) | + RTL818X_TX_CONF_NO_ICV; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + reg |= 1<<30; /* "duration procedure mode" */ + + if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) + reg &= ~RTL818X_TX_CONF_PROBE_DTS; + else + reg &= ~RTL818X_TX_CONF_HW_SEQNUM; + + reg &= ~RTL818X_TX_CONF_DISCW; + + /* different meaning, same value on both rtl8185 and rtl8180 */ + reg &= ~RTL818X_TX_CONF_SAT_HWPLCP; + + rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); + + reg = rtl818x_ioread8(priv, &priv->map->CMD); + reg |= RTL818X_CMD_RX_ENABLE; + reg |= RTL818X_CMD_TX_ENABLE; + rtl818x_iowrite8(priv, &priv->map->CMD, reg); + + return 0; + + err_free_rings: + rtl8180_free_rx_ring(dev); + for (i = 0; i < (dev->queues + 1); i++) + if (priv->tx_ring[i].desc) + rtl8180_free_tx_ring(dev, i); + + return ret; +} + +static void rtl8180_stop(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + u8 reg; + int i; + + rtl8180_int_disable(dev); + + reg = rtl818x_ioread8(priv, &priv->map->CMD); + reg &= ~RTL818X_CMD_TX_ENABLE; + reg &= ~RTL818X_CMD_RX_ENABLE; + rtl818x_iowrite8(priv, &priv->map->CMD, reg); + + priv->rf->stop(dev); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG4); + rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + free_irq(priv->pdev->irq, dev); + + rtl8180_free_rx_ring(dev); + for (i = 0; i < (dev->queues + 1); i++) + rtl8180_free_tx_ring(dev, i); +} + +static u64 rtl8180_get_tsf(struct ieee80211_hw *dev, + struct ieee80211_vif *vif) +{ + struct rtl8180_priv *priv = dev->priv; + + return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | + (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; +} + +static void rtl8180_beacon_work(struct work_struct *work) +{ + struct rtl8180_vif *vif_priv = + container_of(work, struct rtl8180_vif, beacon_work.work); + struct ieee80211_vif *vif = + container_of((void *)vif_priv, struct ieee80211_vif, drv_priv); + struct ieee80211_hw *dev = vif_priv->dev; + struct ieee80211_mgmt *mgmt; + struct sk_buff *skb; + + /* don't overflow the tx ring */ + if (ieee80211_queue_stopped(dev, 0)) + goto resched; + + /* grab a fresh beacon */ + skb = ieee80211_beacon_get(dev, vif); + if (!skb) + goto resched; + + /* + * update beacon timestamp w/ TSF value + * TODO: make hardware update beacon timestamp + */ + mgmt = (struct ieee80211_mgmt *)skb->data; + mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev, vif)); + + /* TODO: use actual beacon queue */ + skb_set_queue_mapping(skb, 0); + + rtl8180_tx(dev, NULL, skb); + +resched: + /* + * schedule next beacon + * TODO: use hardware support for beacon timing + */ + schedule_delayed_work(&vif_priv->beacon_work, + usecs_to_jiffies(1024 * vif->bss_conf.beacon_int)); +} + +static int rtl8180_add_interface(struct ieee80211_hw *dev, + struct ieee80211_vif *vif) +{ + struct rtl8180_priv *priv = dev->priv; + struct rtl8180_vif *vif_priv; + + /* + * We only support one active interface at a time. + */ + if (priv->vif) + return -EBUSY; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + break; + default: + return -EOPNOTSUPP; + } + + priv->vif = vif; + + /* Initialize driver private area */ + vif_priv = (struct rtl8180_vif *)&vif->drv_priv; + vif_priv->dev = dev; + INIT_DELAYED_WORK(&vif_priv->beacon_work, rtl8180_beacon_work); + vif_priv->enable_beacon = false; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], + le32_to_cpu(*(__le32 *)vif->addr)); + rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], + le16_to_cpu(*(__le16 *)(vif->addr + 4))); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + return 0; +} + +static void rtl8180_remove_interface(struct ieee80211_hw *dev, + struct ieee80211_vif *vif) +{ + struct rtl8180_priv *priv = dev->priv; + priv->vif = NULL; +} + +static int rtl8180_config(struct ieee80211_hw *dev, u32 changed) +{ + struct rtl8180_priv *priv = dev->priv; + struct ieee80211_conf *conf = &dev->conf; + + priv->rf->set_chan(dev, conf); + + return 0; +} + +static void rtl8187se_conf_ac_parm(struct ieee80211_hw *dev, u8 queue) +{ + const struct ieee80211_tx_queue_params *params; + struct rtl8180_priv *priv = dev->priv; + + /* hw value */ + u32 ac_param; + + u8 aifs; + u8 txop; + u8 cw_min, cw_max; + + params = &priv->queue_param[queue]; + + cw_min = fls(params->cw_min); + cw_max = fls(params->cw_max); + + aifs = 10 + params->aifs * priv->slot_time; + + /* TODO: check if txop HW is in us (mult by 32) */ + txop = params->txop; + + ac_param = txop << AC_PARAM_TXOP_LIMIT_SHIFT | + cw_max << AC_PARAM_ECW_MAX_SHIFT | + cw_min << AC_PARAM_ECW_MIN_SHIFT | + aifs << AC_PARAM_AIFS_SHIFT; + + switch (queue) { + case IEEE80211_AC_BK: + rtl818x_iowrite32(priv, &priv->map->AC_BK_PARAM, ac_param); + break; + case IEEE80211_AC_BE: + rtl818x_iowrite32(priv, &priv->map->AC_BE_PARAM, ac_param); + break; + case IEEE80211_AC_VI: + rtl818x_iowrite32(priv, &priv->map->AC_VI_PARAM, ac_param); + break; + case IEEE80211_AC_VO: + rtl818x_iowrite32(priv, &priv->map->AC_VO_PARAM, ac_param); + break; + } +} + +static int rtl8180_conf_tx(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct rtl8180_priv *priv = dev->priv; + u8 cw_min, cw_max; + + /* nothing to do ? */ + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) + return 0; + + cw_min = fls(params->cw_min); + cw_max = fls(params->cw_max); + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + priv->queue_param[queue] = *params; + rtl8187se_conf_ac_parm(dev, queue); + } else + rtl818x_iowrite8(priv, &priv->map->CW_VAL, + (cw_max << 4) | cw_min); + return 0; +} + +static void rtl8180_conf_erp(struct ieee80211_hw *dev, + struct ieee80211_bss_conf *info) +{ + struct rtl8180_priv *priv = dev->priv; + u8 sifs, difs; + int eifs; + u8 hw_eifs; + + /* TODO: should we do something ? */ + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) + return; + + /* I _hope_ this means 10uS for the HW. + * In reference code it is 0x22 for + * both rtl8187L and rtl8187SE + */ + sifs = 0x22; + + if (info->use_short_slot) + priv->slot_time = 9; + else + priv->slot_time = 20; + + /* 10 is SIFS time in uS */ + difs = 10 + 2 * priv->slot_time; + eifs = 10 + difs + priv->ack_time; + + /* HW should use 4uS units for EIFS (I'm sure for rtl8185)*/ + hw_eifs = DIV_ROUND_UP(eifs, 4); + + + rtl818x_iowrite8(priv, &priv->map->SLOT, priv->slot_time); + rtl818x_iowrite8(priv, &priv->map->SIFS, sifs); + rtl818x_iowrite8(priv, &priv->map->DIFS, difs); + + /* from reference code. set ack timeout reg = eifs reg */ + rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, hw_eifs); + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + rtl818x_iowrite8(priv, &priv->map->EIFS_8187SE, hw_eifs); + else if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) { + /* rtl8187/rtl8185 HW bug. After EIFS is elapsed, + * the HW still wait for DIFS. + * HW uses 4uS units for EIFS. + */ + hw_eifs = DIV_ROUND_UP(eifs - difs, 4); + + rtl818x_iowrite8(priv, &priv->map->EIFS, hw_eifs); + } +} + +static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + struct rtl8180_priv *priv = dev->priv; + struct rtl8180_vif *vif_priv; + int i; + u8 reg; + + vif_priv = (struct rtl8180_vif *)&vif->drv_priv; + + if (changed & BSS_CHANGED_BSSID) { + rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->BSSID[0], + le16_to_cpu(*(__le16 *)info->bssid)); + rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->BSSID[2], + le32_to_cpu(*(__le32 *)(info->bssid + 2))); + + if (is_valid_ether_addr(info->bssid)) { + if (vif->type == NL80211_IFTYPE_ADHOC) + reg = RTL818X_MSR_ADHOC; + else + reg = RTL818X_MSR_INFRA; + } else + reg = RTL818X_MSR_NO_LINK; + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + reg |= RTL818X_MSR_ENEDCA; + + rtl818x_iowrite8(priv, &priv->map->MSR, reg); + } + + if (changed & BSS_CHANGED_BASIC_RATES) + rtl8180_conf_basic_rates(dev, info->basic_rates); + + if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE)) { + + /* when preamble changes, acktime duration changes, and erp must + * be recalculated. ACK time is calculated at lowest rate. + * Since mac80211 include SIFS time we remove it (-10) + */ + priv->ack_time = + le16_to_cpu(ieee80211_generic_frame_duration(dev, + priv->vif, + IEEE80211_BAND_2GHZ, 10, + &priv->rates[0])) - 10; + + rtl8180_conf_erp(dev, info); + + /* mac80211 supplies aifs_n to driver and calls + * conf_tx callback whether aifs_n changes, NOT + * when aifs changes. + * Aifs should be recalculated if slot changes. + */ + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + for (i = 0; i < 4; i++) + rtl8187se_conf_ac_parm(dev, i); + } + } + + if (changed & BSS_CHANGED_BEACON_ENABLED) + vif_priv->enable_beacon = info->enable_beacon; + + if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON)) { + cancel_delayed_work_sync(&vif_priv->beacon_work); + if (vif_priv->enable_beacon) + schedule_work(&vif_priv->beacon_work.work); + } +} + +static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, + struct netdev_hw_addr_list *mc_list) +{ + return netdev_hw_addr_list_count(mc_list); +} + +static void rtl8180_configure_filter(struct ieee80211_hw *dev, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct rtl8180_priv *priv = dev->priv; + + if (changed_flags & FIF_FCSFAIL) + priv->rx_conf ^= RTL818X_RX_CONF_FCS; + if (changed_flags & FIF_CONTROL) + priv->rx_conf ^= RTL818X_RX_CONF_CTRL; + if (changed_flags & FIF_OTHER_BSS) + priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; + if (*total_flags & FIF_ALLMULTI || multicast > 0) + priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; + else + priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; + + *total_flags = 0; + + if (priv->rx_conf & RTL818X_RX_CONF_FCS) + *total_flags |= FIF_FCSFAIL; + if (priv->rx_conf & RTL818X_RX_CONF_CTRL) + *total_flags |= FIF_CONTROL; + if (priv->rx_conf & RTL818X_RX_CONF_MONITOR) + *total_flags |= FIF_OTHER_BSS; + if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) + *total_flags |= FIF_ALLMULTI; + + rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); +} + +static const struct ieee80211_ops rtl8180_ops = { + .tx = rtl8180_tx, + .start = rtl8180_start, + .stop = rtl8180_stop, + .add_interface = rtl8180_add_interface, + .remove_interface = rtl8180_remove_interface, + .config = rtl8180_config, + .bss_info_changed = rtl8180_bss_info_changed, + .conf_tx = rtl8180_conf_tx, + .prepare_multicast = rtl8180_prepare_multicast, + .configure_filter = rtl8180_configure_filter, + .get_tsf = rtl8180_get_tsf, +}; + +static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) +{ + struct rtl8180_priv *priv = eeprom->data; + u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + + eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE; + eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ; + eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK; + eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS; +} + +static void rtl8180_eeprom_register_write(struct eeprom_93cx6 *eeprom) +{ + struct rtl8180_priv *priv = eeprom->data; + u8 reg = 2 << 6; + + if (eeprom->reg_data_in) + reg |= RTL818X_EEPROM_CMD_WRITE; + if (eeprom->reg_data_out) + reg |= RTL818X_EEPROM_CMD_READ; + if (eeprom->reg_data_clock) + reg |= RTL818X_EEPROM_CMD_CK; + if (eeprom->reg_chip_select) + reg |= RTL818X_EEPROM_CMD_CS; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(10); +} + +static void rtl8180_eeprom_read(struct rtl8180_priv *priv) +{ + struct eeprom_93cx6 eeprom; + int eeprom_cck_table_adr; + u16 eeprom_val; + int i; + + eeprom.data = priv; + eeprom.register_read = rtl8180_eeprom_register_read; + eeprom.register_write = rtl8180_eeprom_register_write; + if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6)) + eeprom.width = PCI_EEPROM_WIDTH_93C66; + else + eeprom.width = PCI_EEPROM_WIDTH_93C46; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_PROGRAM); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(10); + + eeprom_93cx6_read(&eeprom, 0x06, &eeprom_val); + eeprom_val &= 0xFF; + priv->rf_type = eeprom_val; + + eeprom_93cx6_read(&eeprom, 0x17, &eeprom_val); + priv->csthreshold = eeprom_val >> 8; + + eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)priv->mac_addr, 3); + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + eeprom_cck_table_adr = 0x30; + else + eeprom_cck_table_adr = 0x10; + + /* CCK TX power */ + for (i = 0; i < 14; i += 2) { + u16 txpwr; + eeprom_93cx6_read(&eeprom, eeprom_cck_table_adr + (i >> 1), + &txpwr); + priv->channels[i].hw_value = txpwr & 0xFF; + priv->channels[i + 1].hw_value = txpwr >> 8; + } + + /* OFDM TX power */ + if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { + for (i = 0; i < 14; i += 2) { + u16 txpwr; + eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr); + priv->channels[i].hw_value |= (txpwr & 0xFF) << 8; + priv->channels[i + 1].hw_value |= txpwr & 0xFF00; + } + } + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) { + __le32 anaparam; + eeprom_93cx6_multiread(&eeprom, 0xD, (__le16 *)&anaparam, 2); + priv->anaparam = le32_to_cpu(anaparam); + eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam); + } + + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { + eeprom_93cx6_read(&eeprom, 0x3F, &eeprom_val); + priv->antenna_diversity_en = !!(eeprom_val & 0x100); + priv->antenna_diversity_default = (eeprom_val & 0xC00) == 0x400; + + eeprom_93cx6_read(&eeprom, 0x7C, &eeprom_val); + priv->xtal_out = eeprom_val & 0xF; + priv->xtal_in = (eeprom_val & 0xF0) >> 4; + priv->xtal_cal = !!(eeprom_val & 0x1000); + priv->thermal_meter_val = (eeprom_val & 0xF00) >> 8; + priv->thermal_meter_en = !!(eeprom_val & 0x2000); + } + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); +} + +static int rtl8180_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct ieee80211_hw *dev; + struct rtl8180_priv *priv; + unsigned long mem_addr, mem_len; + unsigned int io_addr, io_len; + int err; + const char *chip_name, *rf_name = NULL; + u32 reg; + + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR "%s (rtl8180): Cannot enable new PCI device\n", + pci_name(pdev)); + return err; + } + + err = pci_request_regions(pdev, KBUILD_MODNAME); + if (err) { + printk(KERN_ERR "%s (rtl8180): Cannot obtain PCI resources\n", + pci_name(pdev)); + return err; + } + + io_addr = pci_resource_start(pdev, 0); + io_len = pci_resource_len(pdev, 0); + mem_addr = pci_resource_start(pdev, 1); + mem_len = pci_resource_len(pdev, 1); + + if (mem_len < sizeof(struct rtl818x_csr) || + io_len < sizeof(struct rtl818x_csr)) { + printk(KERN_ERR "%s (rtl8180): Too short PCI resources\n", + pci_name(pdev)); + err = -ENOMEM; + goto err_free_reg; + } + + if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) || + (err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))) { + printk(KERN_ERR "%s (rtl8180): No suitable DMA available\n", + pci_name(pdev)); + goto err_free_reg; + } + + pci_set_master(pdev); + + dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8180_ops); + if (!dev) { + printk(KERN_ERR "%s (rtl8180): ieee80211 alloc failed\n", + pci_name(pdev)); + err = -ENOMEM; + goto err_free_reg; + } + + priv = dev->priv; + priv->pdev = pdev; + + dev->max_rates = 1; + SET_IEEE80211_DEV(dev, &pdev->dev); + pci_set_drvdata(pdev, dev); + + priv->map_pio = false; + priv->map = pci_iomap(pdev, 1, mem_len); + if (!priv->map) { + priv->map = pci_iomap(pdev, 0, io_len); + priv->map_pio = true; + } + + if (!priv->map) { + dev_err(&pdev->dev, "Cannot map device memory/PIO\n"); + err = -ENOMEM; + goto err_free_dev; + } + + BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels)); + BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates)); + + memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); + memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); + + priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); + priv->band.bitrates = priv->rates; + priv->band.n_bitrates = 4; + dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + + ieee80211_hw_set(dev, HOST_BROADCAST_PS_BUFFERING); + ieee80211_hw_set(dev, RX_INCLUDES_FCS); + + dev->vif_data_size = sizeof(struct rtl8180_vif); + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); + dev->max_signal = 65; + + reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); + reg &= RTL818X_TX_CONF_HWVER_MASK; + switch (reg) { + case RTL818X_TX_CONF_R8180_ABCD: + chip_name = "RTL8180"; + priv->chip_family = RTL818X_CHIP_FAMILY_RTL8180; + break; + + case RTL818X_TX_CONF_R8180_F: + chip_name = "RTL8180vF"; + priv->chip_family = RTL818X_CHIP_FAMILY_RTL8180; + break; + + case RTL818X_TX_CONF_R8185_ABC: + chip_name = "RTL8185"; + priv->chip_family = RTL818X_CHIP_FAMILY_RTL8185; + break; + + case RTL818X_TX_CONF_R8185_D: + chip_name = "RTL8185vD"; + priv->chip_family = RTL818X_CHIP_FAMILY_RTL8185; + break; + + case RTL818X_TX_CONF_RTL8187SE: + chip_name = "RTL8187SE"; + if (priv->map_pio) { + dev_err(&pdev->dev, + "MMIO failed. PIO not supported on RTL8187SE\n"); + err = -ENOMEM; + goto err_iounmap; + } + priv->chip_family = RTL818X_CHIP_FAMILY_RTL8187SE; + break; + + default: + printk(KERN_ERR "%s (rtl8180): Unknown chip! (0x%x)\n", + pci_name(pdev), reg >> 25); + err = -ENODEV; + goto err_iounmap; + } + + /* we declare to MAC80211 all the queues except for beacon queue + * that will be eventually handled by DRV. + * TX rings are arranged in such a way that lower is the IDX, + * higher is the priority, in order to achieve direct mapping + * with mac80211, however the beacon queue is an exception and it + * is mapped on the highst tx ring IDX. + */ + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + dev->queues = RTL8187SE_NR_TX_QUEUES - 1; + else + dev->queues = RTL8180_NR_TX_QUEUES - 1; + + if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { + priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); + pci_try_set_mwi(pdev); + } + + if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) + ieee80211_hw_set(dev, SIGNAL_DBM); + else + ieee80211_hw_set(dev, SIGNAL_UNSPEC); + + rtl8180_eeprom_read(priv); + + switch (priv->rf_type) { + case 1: rf_name = "Intersil"; + break; + case 2: rf_name = "RFMD"; + break; + case 3: priv->rf = &sa2400_rf_ops; + break; + case 4: priv->rf = &max2820_rf_ops; + break; + case 5: priv->rf = &grf5101_rf_ops; + break; + case 9: + if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) + priv->rf = rtl8187se_detect_rf(dev); + else + priv->rf = rtl8180_detect_rf(dev); + break; + case 10: + rf_name = "RTL8255"; + break; + default: + printk(KERN_ERR "%s (rtl8180): Unknown RF! (0x%x)\n", + pci_name(pdev), priv->rf_type); + err = -ENODEV; + goto err_iounmap; + } + + if (!priv->rf) { + printk(KERN_ERR "%s (rtl8180): %s RF frontend not supported!\n", + pci_name(pdev), rf_name); + err = -ENODEV; + goto err_iounmap; + } + + if (!is_valid_ether_addr(priv->mac_addr)) { + printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using" + " randomly generated MAC addr\n", pci_name(pdev)); + eth_random_addr(priv->mac_addr); + } + SET_IEEE80211_PERM_ADDR(dev, priv->mac_addr); + + spin_lock_init(&priv->lock); + + err = ieee80211_register_hw(dev); + if (err) { + printk(KERN_ERR "%s (rtl8180): Cannot register device\n", + pci_name(pdev)); + goto err_iounmap; + } + + wiphy_info(dev->wiphy, "hwaddr %pm, %s + %s\n", + priv->mac_addr, chip_name, priv->rf->name); + + return 0; + + err_iounmap: + pci_iounmap(pdev, priv->map); + + err_free_dev: + ieee80211_free_hw(dev); + + err_free_reg: + pci_release_regions(pdev); + pci_disable_device(pdev); + return err; +} + +static void rtl8180_remove(struct pci_dev *pdev) +{ + struct ieee80211_hw *dev = pci_get_drvdata(pdev); + struct rtl8180_priv *priv; + + if (!dev) + return; + + ieee80211_unregister_hw(dev); + + priv = dev->priv; + + pci_iounmap(pdev, priv->map); + pci_release_regions(pdev); + pci_disable_device(pdev); + ieee80211_free_hw(dev); +} + +#ifdef CONFIG_PM +static int rtl8180_suspend(struct pci_dev *pdev, pm_message_t state) +{ + pci_save_state(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; +} + +static int rtl8180_resume(struct pci_dev *pdev) +{ + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + return 0; +} + +#endif /* CONFIG_PM */ + +static struct pci_driver rtl8180_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl8180_table, + .probe = rtl8180_probe, + .remove = rtl8180_remove, +#ifdef CONFIG_PM + .suspend = rtl8180_suspend, + .resume = rtl8180_resume, +#endif /* CONFIG_PM */ +}; + +module_pci_driver(rtl8180_driver); diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.c new file mode 100644 index 000000000000..b1bfee738937 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.c @@ -0,0 +1,190 @@ + +/* + * Radio tuning for GCT GRF5101 on RTL8180 + * + * Copyright 2007 Andrea Merello + * + * Code from the BSD driver and the rtl8181 project have been + * very useful to understand certain things + * + * I want to thanks the Authors of such projects and the Ndiswrapper + * project Authors. + * + * A special Big Thanks also is for all people who donated me cards, + * making possible the creation of the original rtl8180 driver + * from which this code is derived! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include "rtl8180.h" +#include "grf5101.h" + +static const int grf5101_encode[] = { + 0x0, 0x8, 0x4, 0xC, + 0x2, 0xA, 0x6, 0xE, + 0x1, 0x9, 0x5, 0xD, + 0x3, 0xB, 0x7, 0xF +}; + +static void write_grf5101(struct ieee80211_hw *dev, u8 addr, u32 data) +{ + struct rtl8180_priv *priv = dev->priv; + u32 phy_config; + + phy_config = grf5101_encode[(data >> 8) & 0xF]; + phy_config |= grf5101_encode[(data >> 4) & 0xF] << 4; + phy_config |= grf5101_encode[data & 0xF] << 8; + phy_config |= grf5101_encode[(addr >> 1) & 0xF] << 12; + phy_config |= (addr & 1) << 16; + phy_config |= grf5101_encode[(data & 0xf000) >> 12] << 24; + + /* MAC will bang bits to the chip */ + phy_config |= 0x90000000; + + rtl818x_iowrite32(priv, + (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config); + + msleep(3); +} + +static void grf5101_write_phy_antenna(struct ieee80211_hw *dev, short chan) +{ + struct rtl8180_priv *priv = dev->priv; + u8 ant = GRF5101_ANTENNA; + + if (priv->rfparam & RF_PARAM_ANTBDEFAULT) + ant |= BB_ANTENNA_B; + + if (chan == 14) + ant |= BB_ANTATTEN_CHAN14; + + rtl8180_write_phy(dev, 0x10, ant); +} + +static u8 grf5101_rf_calc_rssi(u8 agc, u8 sq) +{ + if (agc > 60) + return 65; + + /* TODO(?): just return agc (or agc + 5) to avoid mult / div */ + return 65 * agc / 60; +} + +static void grf5101_rf_set_channel(struct ieee80211_hw *dev, + struct ieee80211_conf *conf) +{ + struct rtl8180_priv *priv = dev->priv; + int channel = + ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); + u32 txpw = priv->channels[channel - 1].hw_value & 0xFF; + u32 chan = channel - 1; + + /* set TX power */ + write_grf5101(dev, 0x15, 0x0); + write_grf5101(dev, 0x06, txpw); + write_grf5101(dev, 0x15, 0x10); + write_grf5101(dev, 0x15, 0x0); + + /* set frequency */ + write_grf5101(dev, 0x07, 0x0); + write_grf5101(dev, 0x0B, chan); + write_grf5101(dev, 0x07, 0x1000); + + grf5101_write_phy_antenna(dev, channel); +} + +static void grf5101_rf_stop(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + u32 anaparam; + + anaparam = priv->anaparam; + anaparam &= 0x000fffff; + anaparam |= 0x3f900000; + rtl8180_set_anaparam(priv, anaparam); + + write_grf5101(dev, 0x07, 0x0); + write_grf5101(dev, 0x1f, 0x45); + write_grf5101(dev, 0x1f, 0x5); + write_grf5101(dev, 0x00, 0x8e4); +} + +static void grf5101_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + + rtl8180_set_anaparam(priv, priv->anaparam); + + write_grf5101(dev, 0x1f, 0x0); + write_grf5101(dev, 0x1f, 0x0); + write_grf5101(dev, 0x1f, 0x40); + write_grf5101(dev, 0x1f, 0x60); + write_grf5101(dev, 0x1f, 0x61); + write_grf5101(dev, 0x1f, 0x61); + write_grf5101(dev, 0x00, 0xae4); + write_grf5101(dev, 0x1f, 0x1); + write_grf5101(dev, 0x1f, 0x41); + write_grf5101(dev, 0x1f, 0x61); + + write_grf5101(dev, 0x01, 0x1a23); + write_grf5101(dev, 0x02, 0x4971); + write_grf5101(dev, 0x03, 0x41de); + write_grf5101(dev, 0x04, 0x2d80); + write_grf5101(dev, 0x05, 0x68ff); /* 0x61ff original value */ + write_grf5101(dev, 0x06, 0x0); + write_grf5101(dev, 0x07, 0x0); + write_grf5101(dev, 0x08, 0x7533); + write_grf5101(dev, 0x09, 0xc401); + write_grf5101(dev, 0x0a, 0x0); + write_grf5101(dev, 0x0c, 0x1c7); + write_grf5101(dev, 0x0d, 0x29d3); + write_grf5101(dev, 0x0e, 0x2e8); + write_grf5101(dev, 0x10, 0x192); + write_grf5101(dev, 0x11, 0x248); + write_grf5101(dev, 0x12, 0x0); + write_grf5101(dev, 0x13, 0x20c4); + write_grf5101(dev, 0x14, 0xf4fc); + write_grf5101(dev, 0x15, 0x0); + write_grf5101(dev, 0x16, 0x1500); + + write_grf5101(dev, 0x07, 0x1000); + + /* baseband configuration */ + rtl8180_write_phy(dev, 0, 0xa8); + rtl8180_write_phy(dev, 3, 0x0); + rtl8180_write_phy(dev, 4, 0xc0); + rtl8180_write_phy(dev, 5, 0x90); + rtl8180_write_phy(dev, 6, 0x1e); + rtl8180_write_phy(dev, 7, 0x64); + + grf5101_write_phy_antenna(dev, 1); + + rtl8180_write_phy(dev, 0x11, 0x88); + + if (rtl818x_ioread8(priv, &priv->map->CONFIG2) & + RTL818X_CONFIG2_ANTENNA_DIV) + rtl8180_write_phy(dev, 0x12, 0xc0); /* enable ant diversity */ + else + rtl8180_write_phy(dev, 0x12, 0x40); /* disable ant diversity */ + + rtl8180_write_phy(dev, 0x13, 0x90 | priv->csthreshold); + + rtl8180_write_phy(dev, 0x19, 0x0); + rtl8180_write_phy(dev, 0x1a, 0xa0); + rtl8180_write_phy(dev, 0x1b, 0x44); +} + +const struct rtl818x_rf_ops grf5101_rf_ops = { + .name = "GCT", + .init = grf5101_rf_init, + .stop = grf5101_rf_stop, + .set_chan = grf5101_rf_set_channel, + .calc_rssi = grf5101_rf_calc_rssi, +}; diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.h new file mode 100644 index 000000000000..4d80a2785123 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/grf5101.h @@ -0,0 +1,28 @@ +#ifndef RTL8180_GRF5101_H +#define RTL8180_GRF5101_H + +/* + * Radio tuning for GCT GRF5101 on RTL8180 + * + * Copyright 2007 Andrea Merello + * + * Code from the BSD driver and the rtl8181 project have been + * very useful to understand certain things + * + * I want to thanks the Authors of such projects and the Ndiswrapper + * project Authors. + * + * A special Big Thanks also is for all people who donated me cards, + * making possible the creation of the original rtl8180 driver + * from which this code is derived! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define GRF5101_ANTENNA 0xA3 + +extern const struct rtl818x_rf_ops grf5101_rf_ops; + +#endif /* RTL8180_GRF5101_H */ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.c new file mode 100644 index 000000000000..eebf23976524 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.c @@ -0,0 +1,168 @@ +/* + * Radio tuning for Maxim max2820 on RTL8180 + * + * Copyright 2007 Andrea Merello + * + * Code from the BSD driver and the rtl8181 project have been + * very useful to understand certain things + * + * I want to thanks the Authors of such projects and the Ndiswrapper + * project Authors. + * + * A special Big Thanks also is for all people who donated me cards, + * making possible the creation of the original rtl8180 driver + * from which this code is derived! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include "rtl8180.h" +#include "max2820.h" + +static const u32 max2820_chan[] = { + 12, /* CH 1 */ + 17, + 22, + 27, + 32, + 37, + 42, + 47, + 52, + 57, + 62, + 67, + 72, + 84, /* CH 14 */ +}; + +static void write_max2820(struct ieee80211_hw *dev, u8 addr, u32 data) +{ + struct rtl8180_priv *priv = dev->priv; + u32 phy_config; + + phy_config = 0x90 + (data & 0xf); + phy_config <<= 16; + phy_config += addr; + phy_config <<= 8; + phy_config += (data >> 4) & 0xff; + + rtl818x_iowrite32(priv, + (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config); + + msleep(1); +} + +static void max2820_write_phy_antenna(struct ieee80211_hw *dev, short chan) +{ + struct rtl8180_priv *priv = dev->priv; + u8 ant; + + ant = MAXIM_ANTENNA; + if (priv->rfparam & RF_PARAM_ANTBDEFAULT) + ant |= BB_ANTENNA_B; + if (chan == 14) + ant |= BB_ANTATTEN_CHAN14; + + rtl8180_write_phy(dev, 0x10, ant); +} + +static u8 max2820_rf_calc_rssi(u8 agc, u8 sq) +{ + bool odd; + + odd = !!(agc & 1); + + agc >>= 1; + if (odd) + agc += 76; + else + agc += 66; + + /* TODO: change addends above to avoid mult / div below */ + return 65 * agc / 100; +} + +static void max2820_rf_set_channel(struct ieee80211_hw *dev, + struct ieee80211_conf *conf) +{ + struct rtl8180_priv *priv = dev->priv; + int channel = conf ? + ieee80211_frequency_to_channel(conf->chandef.chan->center_freq) : 1; + unsigned int chan_idx = channel - 1; + u32 txpw = priv->channels[chan_idx].hw_value & 0xFF; + u32 chan = max2820_chan[chan_idx]; + + /* While philips SA2400 drive the PA bias from + * sa2400, for MAXIM we do this directly from BB */ + rtl8180_write_phy(dev, 3, txpw); + + max2820_write_phy_antenna(dev, channel); + write_max2820(dev, 3, chan); +} + +static void max2820_rf_stop(struct ieee80211_hw *dev) +{ + rtl8180_write_phy(dev, 3, 0x8); + write_max2820(dev, 1, 0); +} + + +static void max2820_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + + /* MAXIM from netbsd driver */ + write_max2820(dev, 0, 0x007); /* test mode as indicated in datasheet */ + write_max2820(dev, 1, 0x01e); /* enable register */ + write_max2820(dev, 2, 0x001); /* synt register */ + + max2820_rf_set_channel(dev, NULL); + + write_max2820(dev, 4, 0x313); /* rx register */ + + /* PA is driven directly by the BB, we keep the MAXIM bias + * at the highest value in case that setting it to lower + * values may introduce some further attenuation somewhere.. + */ + write_max2820(dev, 5, 0x00f); + + /* baseband configuration */ + rtl8180_write_phy(dev, 0, 0x88); /* sys1 */ + rtl8180_write_phy(dev, 3, 0x08); /* txagc */ + rtl8180_write_phy(dev, 4, 0xf8); /* lnadet */ + rtl8180_write_phy(dev, 5, 0x90); /* ifagcinit */ + rtl8180_write_phy(dev, 6, 0x1a); /* ifagclimit */ + rtl8180_write_phy(dev, 7, 0x64); /* ifagcdet */ + + max2820_write_phy_antenna(dev, 1); + + rtl8180_write_phy(dev, 0x11, 0x88); /* trl */ + + if (rtl818x_ioread8(priv, &priv->map->CONFIG2) & + RTL818X_CONFIG2_ANTENNA_DIV) + rtl8180_write_phy(dev, 0x12, 0xc7); + else + rtl8180_write_phy(dev, 0x12, 0x47); + + rtl8180_write_phy(dev, 0x13, 0x9b); + + rtl8180_write_phy(dev, 0x19, 0x0); /* CHESTLIM */ + rtl8180_write_phy(dev, 0x1a, 0x9f); /* CHSQLIM */ + + max2820_rf_set_channel(dev, NULL); +} + +const struct rtl818x_rf_ops max2820_rf_ops = { + .name = "Maxim", + .init = max2820_rf_init, + .stop = max2820_rf_stop, + .set_chan = max2820_rf_set_channel, + .calc_rssi = max2820_rf_calc_rssi, +}; diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.h new file mode 100644 index 000000000000..8e982b72b690 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/max2820.h @@ -0,0 +1,28 @@ +#ifndef RTL8180_MAX2820_H +#define RTL8180_MAX2820_H + +/* + * Radio tuning for Maxim max2820 on RTL8180 + * + * Copyright 2007 Andrea Merello + * + * Code from the BSD driver and the rtl8181 project have been + * very useful to understand certain things + * + * I want to thanks the Authors of such projects and the Ndiswrapper + * project Authors. + * + * A special Big Thanks also is for all people who donated me cards, + * making possible the creation of the original rtl8180 driver + * from which this code is derived! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define MAXIM_ANTENNA 0xb3 + +extern const struct rtl818x_rf_ops max2820_rf_ops; + +#endif /* RTL8180_MAX2820_H */ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8180.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8180.h new file mode 100644 index 000000000000..e8243a44d6b6 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8180.h @@ -0,0 +1,185 @@ +#ifndef RTL8180_H +#define RTL8180_H + +#include "rtl818x.h" + +#define MAX_RX_SIZE IEEE80211_MAX_RTS_THRESHOLD + +#define RF_PARAM_ANALOGPHY (1 << 0) +#define RF_PARAM_ANTBDEFAULT (1 << 1) +#define RF_PARAM_CARRIERSENSE1 (1 << 2) +#define RF_PARAM_CARRIERSENSE2 (1 << 3) + +#define BB_ANTATTEN_CHAN14 0x0C +#define BB_ANTENNA_B 0x40 + +#define BB_HOST_BANG (1 << 30) +#define BB_HOST_BANG_EN (1 << 2) +#define BB_HOST_BANG_CLK (1 << 1) +#define BB_HOST_BANG_DATA 1 + +#define ANAPARAM_TXDACOFF_SHIFT 27 +#define ANAPARAM_PWR0_SHIFT 28 +#define ANAPARAM_PWR0_MASK (0x07 << ANAPARAM_PWR0_SHIFT) +#define ANAPARAM_PWR1_SHIFT 20 +#define ANAPARAM_PWR1_MASK (0x7F << ANAPARAM_PWR1_SHIFT) + +/* rtl8180/rtl8185 have 3 queue + beacon queue. + * mac80211 can use just one, + beacon = 2 tot. + */ +#define RTL8180_NR_TX_QUEUES 2 + +/* rtl8187SE have 6 queues + beacon queues + * mac80211 can use 4 QoS data queue, + beacon = 5 tot + */ +#define RTL8187SE_NR_TX_QUEUES 5 + +/* for array static allocation, it is the max of above */ +#define RTL818X_NR_TX_QUEUES 5 + +struct rtl8180_tx_desc { + __le32 flags; + __le16 rts_duration; + __le16 plcp_len; + __le32 tx_buf; + union{ + __le32 frame_len; + struct { + __le16 frame_len_se; + __le16 frame_duration; + } __packed; + } __packed; + __le32 next_tx_desc; + u8 cw; + u8 retry_limit; + u8 agc; + u8 flags2; + /* rsvd for 8180/8185. + * valid for 8187se but we dont use it + */ + u32 reserved; + /* all rsvd for 8180/8185 */ + __le16 flags3; + __le16 frag_qsize; +} __packed; + +struct rtl818x_rx_cmd_desc { + __le32 flags; + u32 reserved; + __le32 rx_buf; +} __packed; + +struct rtl8180_rx_desc { + __le32 flags; + __le32 flags2; + __le64 tsft; + +} __packed; + +struct rtl8187se_rx_desc { + __le32 flags; + __le64 tsft; + __le32 flags2; + __le32 flags3; + u32 reserved[3]; +} __packed; + +struct rtl8180_tx_ring { + struct rtl8180_tx_desc *desc; + dma_addr_t dma; + unsigned int idx; + unsigned int entries; + struct sk_buff_head queue; +}; + +struct rtl8180_vif { + struct ieee80211_hw *dev; + + /* beaconing */ + struct delayed_work beacon_work; + bool enable_beacon; +}; + +struct rtl8180_priv { + /* common between rtl818x drivers */ + struct rtl818x_csr __iomem *map; + const struct rtl818x_rf_ops *rf; + struct ieee80211_vif *vif; + + /* rtl8180 driver specific */ + bool map_pio; + spinlock_t lock; + void *rx_ring; + u8 rx_ring_sz; + dma_addr_t rx_ring_dma; + unsigned int rx_idx; + struct sk_buff *rx_buf[32]; + struct rtl8180_tx_ring tx_ring[RTL818X_NR_TX_QUEUES]; + struct ieee80211_channel channels[14]; + struct ieee80211_rate rates[12]; + struct ieee80211_supported_band band; + struct ieee80211_tx_queue_params queue_param[4]; + struct pci_dev *pdev; + u32 rx_conf; + u8 slot_time; + u16 ack_time; + + enum { + RTL818X_CHIP_FAMILY_RTL8180, + RTL818X_CHIP_FAMILY_RTL8185, + RTL818X_CHIP_FAMILY_RTL8187SE, + } chip_family; + u32 anaparam; + u16 rfparam; + u8 csthreshold; + u8 mac_addr[ETH_ALEN]; + u8 rf_type; + u8 xtal_out; + u8 xtal_in; + u8 xtal_cal; + u8 thermal_meter_val; + u8 thermal_meter_en; + u8 antenna_diversity_en; + u8 antenna_diversity_default; + /* sequence # */ + u16 seqno; +}; + +void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); +void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam); +void rtl8180_set_anaparam2(struct rtl8180_priv *priv, u32 anaparam2); + +static inline u8 rtl818x_ioread8(struct rtl8180_priv *priv, u8 __iomem *addr) +{ + return ioread8(addr); +} + +static inline u16 rtl818x_ioread16(struct rtl8180_priv *priv, __le16 __iomem *addr) +{ + return ioread16(addr); +} + +static inline u32 rtl818x_ioread32(struct rtl8180_priv *priv, __le32 __iomem *addr) +{ + return ioread32(addr); +} + +static inline void rtl818x_iowrite8(struct rtl8180_priv *priv, + u8 __iomem *addr, u8 val) +{ + iowrite8(val, addr); +} + +static inline void rtl818x_iowrite16(struct rtl8180_priv *priv, + __le16 __iomem *addr, u16 val) +{ + iowrite16(val, addr); +} + +static inline void rtl818x_iowrite32(struct rtl8180_priv *priv, + __le32 __iomem *addr, u32 val) +{ + iowrite32(val, addr); +} + +#endif /* RTL8180_H */ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.c new file mode 100644 index 000000000000..9bda5bc78eda --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.c @@ -0,0 +1,770 @@ + +/* + * Radio tuning for RTL8225 on RTL8180 + * + * Copyright 2007 Michael Wu + * Copyright 2007 Andrea Merello + * + * Based on the r8180 driver, which is: + * Copyright 2005 Andrea Merello , et al. + * + * Thanks to Realtek for their support! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include "rtl8180.h" +#include "rtl8225.h" + +static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data) +{ + struct rtl8180_priv *priv = dev->priv; + u16 reg80, reg84, reg82; + u32 bangdata; + int i; + + bangdata = (data << 4) | (addr & 0xf); + + reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3; + reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7); + + reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7 | 0x400); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(10); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(10); + + for (i = 15; i >= 0; i--) { + u16 reg = reg80; + + if (bangdata & (1 << i)) + reg |= 1; + + if (i & 1) + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); + + if (!(i & 1)) + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); + } + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(10); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x400); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); +} + +static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr) +{ + struct rtl8180_priv *priv = dev->priv; + u16 reg80, reg82, reg84, out; + int i; + + reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput); + reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); + reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect) | 0x400; + + reg80 &= ~0xF; + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(4); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(5); + + for (i = 4; i >= 0; i--) { + u16 reg = reg80 | ((addr >> i) & 1); + + if (!(i & 1)) { + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(1); + } + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg | (1 << 1)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg | (1 << 1)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(2); + + if (i & 1) { + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(1); + } + } + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x000E); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x040E); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 1)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(2); + + out = 0; + for (i = 11; i >= 0; i--) { + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(1); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 1)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 1)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 1)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(2); + + if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1)) + out |= 1 << i; + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(2); + } + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 2)); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + udelay(2); + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0); + + return out; +} + +static const u16 rtl8225bcd_rxgain[] = { + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, + 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, + 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, + 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, + 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, + 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, + 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, + 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, + 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, + 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, + 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, + 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb +}; + +static const u8 rtl8225_agc[] = { + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, + 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, + 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, + 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, + 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, + 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, + 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, + 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, + 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, + 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, + 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 +}; + +static const u8 rtl8225_gain[] = { + 0x23, 0x88, 0x7c, 0xa5, /* -82dbm */ + 0x23, 0x88, 0x7c, 0xb5, /* -82dbm */ + 0x23, 0x88, 0x7c, 0xc5, /* -82dbm */ + 0x33, 0x80, 0x79, 0xc5, /* -78dbm */ + 0x43, 0x78, 0x76, 0xc5, /* -74dbm */ + 0x53, 0x60, 0x73, 0xc5, /* -70dbm */ + 0x63, 0x58, 0x70, 0xc5, /* -66dbm */ +}; + +static const u8 rtl8225_threshold[] = { + 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd +}; + +static const u8 rtl8225_tx_gain_cck_ofdm[] = { + 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e +}; + +static const u8 rtl8225_tx_power_cck[] = { + 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, + 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, + 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, + 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, + 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, + 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 +}; + +static const u8 rtl8225_tx_power_cck_ch14[] = { + 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 rtl8225_tx_power_ofdm[] = { + 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 +}; + +static const u32 rtl8225_chan[] = { + 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c, + 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72 +}; + +static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) +{ + struct rtl8180_priv *priv = dev->priv; + u8 cck_power, ofdm_power; + const u8 *tmp; + u32 reg; + int i; + + cck_power = priv->channels[channel - 1].hw_value & 0xFF; + ofdm_power = priv->channels[channel - 1].hw_value >> 8; + + cck_power = min(cck_power, (u8)35); + ofdm_power = min(ofdm_power, (u8)35); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, + rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1); + + if (channel == 14) + tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8]; + else + tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8]; + + for (i = 0; i < 8; i++) + rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); + + msleep(1); /* FIXME: optional? */ + + /* TODO: use set_anaparam2 dev.c_func*/ + /* anaparam2 on */ + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, + rtl8225_tx_gain_cck_ofdm[ofdm_power/6] >> 1); + + tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6]; + + rtl8225_write_phy_ofdm(dev, 5, *tmp); + rtl8225_write_phy_ofdm(dev, 7, *tmp); + + msleep(1); +} + +static void rtl8225_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + int i; + + rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON); + + /* host_pci_init */ + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + msleep(200); /* FIXME: ehh?? */ + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6)); + + rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008); + + /* TODO: check if we need really to change BRSR to do RF config */ + rtl818x_ioread16(priv, &priv->map->BRSR); + rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); + rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + rtl8225_write(dev, 0x0, 0x067); + rtl8225_write(dev, 0x1, 0xFE0); + rtl8225_write(dev, 0x2, 0x44D); + rtl8225_write(dev, 0x3, 0x441); + rtl8225_write(dev, 0x4, 0x8BE); + rtl8225_write(dev, 0x5, 0xBF0); /* TODO: minipci */ + rtl8225_write(dev, 0x6, 0xAE6); + rtl8225_write(dev, 0x7, rtl8225_chan[0]); + rtl8225_write(dev, 0x8, 0x01F); + rtl8225_write(dev, 0x9, 0x334); + rtl8225_write(dev, 0xA, 0xFD4); + rtl8225_write(dev, 0xB, 0x391); + rtl8225_write(dev, 0xC, 0x050); + rtl8225_write(dev, 0xD, 0x6DB); + rtl8225_write(dev, 0xE, 0x029); + rtl8225_write(dev, 0xF, 0x914); msleep(1); + + rtl8225_write(dev, 0x2, 0xC4D); msleep(100); + + rtl8225_write(dev, 0x0, 0x127); + + for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) { + rtl8225_write(dev, 0x1, i + 1); + rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]); + } + + rtl8225_write(dev, 0x0, 0x027); + rtl8225_write(dev, 0x0, 0x22F); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); + + for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { + rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); + msleep(1); + rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); + msleep(1); + } + + msleep(1); + + rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x06, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x08, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x11, 0x03); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1); + + rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1); + rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1); + rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1); + rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1); + rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1); + rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1); + rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1); + rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1); + rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1); + rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1); + rtl8225_write_phy_cck(dev, 0x13, 0xd0); + rtl8225_write_phy_cck(dev, 0x19, 0x00); + rtl8225_write_phy_cck(dev, 0x1a, 0xa0); + rtl8225_write_phy_cck(dev, 0x1b, 0x08); + rtl8225_write_phy_cck(dev, 0x40, 0x86); + rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1); + rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1); + rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1); + rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1); + rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1); + rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1); + rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1); + rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1); + rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1); + rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1); + rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1); + rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1); + + rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); msleep(1); + + rtl8225_rf_set_tx_power(dev, 1); + + /* RX antenna default to A */ + rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */ + rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */ + + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ + msleep(1); + rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); + + rtl8225_write(dev, 0x0c, 0x50); + /* set OFDM initial gain */ + rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[4 * 4]); + rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[4 * 4 + 1]); + rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[4 * 4 + 2]); + rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[4 * 4 + 3]); + /* set CCK threshold */ + rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[0]); +} + +static const u8 rtl8225z2_tx_power_cck_ch14[] = { + 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 rtl8225z2_tx_power_cck_B[] = { + 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04 +}; + +static const u8 rtl8225z2_tx_power_cck_A[] = { + 0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04 +}; + +static const u8 rtl8225z2_tx_power_cck[] = { + 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 +}; + +static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) +{ + struct rtl8180_priv *priv = dev->priv; + u8 cck_power, ofdm_power; + const u8 *tmp; + int i; + + cck_power = priv->channels[channel - 1].hw_value & 0xFF; + ofdm_power = priv->channels[channel - 1].hw_value >> 8; + + if (channel == 14) + tmp = rtl8225z2_tx_power_cck_ch14; + else if (cck_power == 12) + tmp = rtl8225z2_tx_power_cck_B; + else if (cck_power == 13) + tmp = rtl8225z2_tx_power_cck_A; + else + tmp = rtl8225z2_tx_power_cck; + + for (i = 0; i < 8; i++) + rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); + + cck_power = min(cck_power, (u8)35); + if (cck_power == 13 || cck_power == 14) + cck_power = 12; + if (cck_power >= 15) + cck_power -= 2; + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, cck_power); + rtl818x_ioread8(priv, &priv->map->TX_GAIN_CCK); + msleep(1); + + ofdm_power = min(ofdm_power, (u8)35); + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, ofdm_power); + + rtl8225_write_phy_ofdm(dev, 2, 0x62); + rtl8225_write_phy_ofdm(dev, 5, 0x00); + rtl8225_write_phy_ofdm(dev, 6, 0x40); + rtl8225_write_phy_ofdm(dev, 7, 0x00); + rtl8225_write_phy_ofdm(dev, 8, 0x40); + + msleep(1); +} + +static const u16 rtl8225z2_rxgain[] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009, + 0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141, + 0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183, + 0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244, + 0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288, + 0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345, + 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389, + 0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393, + 0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, + 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9, + 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, + 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb +}; + +static void rtl8225z2_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + int i; + + rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON); + + /* host_pci_init */ + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + msleep(200); /* FIXME: ehh?? */ + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6)); + + rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00088008); + + /* TODO: check if we need really to change BRSR to do RF config */ + rtl818x_ioread16(priv, &priv->map->BRSR); + rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); + rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); + + rtl8225_write(dev, 0x0, 0x0B7); msleep(1); + rtl8225_write(dev, 0x1, 0xEE0); msleep(1); + rtl8225_write(dev, 0x2, 0x44D); msleep(1); + rtl8225_write(dev, 0x3, 0x441); msleep(1); + rtl8225_write(dev, 0x4, 0x8C3); msleep(1); + rtl8225_write(dev, 0x5, 0xC72); msleep(1); + rtl8225_write(dev, 0x6, 0x0E6); msleep(1); + rtl8225_write(dev, 0x7, 0x82A); msleep(1); + rtl8225_write(dev, 0x8, 0x03F); msleep(1); + rtl8225_write(dev, 0x9, 0x335); msleep(1); + rtl8225_write(dev, 0xa, 0x9D4); msleep(1); + rtl8225_write(dev, 0xb, 0x7BB); msleep(1); + rtl8225_write(dev, 0xc, 0x850); msleep(1); + rtl8225_write(dev, 0xd, 0xCDF); msleep(1); + rtl8225_write(dev, 0xe, 0x02B); msleep(1); + rtl8225_write(dev, 0xf, 0x114); msleep(100); + + if (!(rtl8225_read(dev, 6) & (1 << 7))) { + rtl8225_write(dev, 0x02, 0x0C4D); + msleep(200); + rtl8225_write(dev, 0x02, 0x044D); + msleep(100); + /* TODO: readd calibration failure message when the calibration + check works */ + } + + rtl8225_write(dev, 0x0, 0x1B7); + rtl8225_write(dev, 0x3, 0x002); + rtl8225_write(dev, 0x5, 0x004); + + for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { + rtl8225_write(dev, 0x1, i + 1); + rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); + } + + rtl8225_write(dev, 0x0, 0x0B7); msleep(100); + rtl8225_write(dev, 0x2, 0xC4D); + + msleep(200); + rtl8225_write(dev, 0x2, 0x44D); + msleep(100); + + rtl8225_write(dev, 0x00, 0x2BF); + rtl8225_write(dev, 0xFF, 0xFFFF); + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); + + for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { + rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); + msleep(1); + rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); + msleep(1); + } + + msleep(1); + + rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0d, 0x43); + rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1b, 0x11); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1e, 0xb3); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); /* FIXME: not needed? */ + rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1); + + rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1); + rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1); + rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1); + rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1); + rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1); + rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1); + rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1); + rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1); + rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1); + rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1); + rtl8225_write_phy_cck(dev, 0x13, 0xd0); + rtl8225_write_phy_cck(dev, 0x19, 0x00); + rtl8225_write_phy_cck(dev, 0x1a, 0xa0); + rtl8225_write_phy_cck(dev, 0x1b, 0x08); + rtl8225_write_phy_cck(dev, 0x40, 0x86); + rtl8225_write_phy_cck(dev, 0x41, 0x8a); msleep(1); + rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1); + rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1); + rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1); + rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1); + rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1); + rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1); + rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1); + rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1); + rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1); + rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1); + rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1); + + rtl818x_iowrite8(priv, (u8 __iomem *)((void __iomem *)priv->map + 0x5B), 0x0D); msleep(1); + + rtl8225z2_rf_set_tx_power(dev, 1); + + /* RX antenna default to A */ + rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */ + rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */ + + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ + msleep(1); + rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); +} + +static void rtl8225_rf_stop(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + u8 reg; + + rtl8225_write(dev, 0x4, 0x1f); msleep(1); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); +} + +static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, + struct ieee80211_conf *conf) +{ + struct rtl8180_priv *priv = dev->priv; + int chan = + ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); + + if (priv->rf->init == rtl8225_rf_init) + rtl8225_rf_set_tx_power(dev, chan); + else + rtl8225z2_rf_set_tx_power(dev, chan); + + rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); + msleep(10); +} + +static const struct rtl818x_rf_ops rtl8225_ops = { + .name = "rtl8225", + .init = rtl8225_rf_init, + .stop = rtl8225_rf_stop, + .set_chan = rtl8225_rf_set_channel, +}; + +static const struct rtl818x_rf_ops rtl8225z2_ops = { + .name = "rtl8225z2", + .init = rtl8225z2_rf_init, + .stop = rtl8225_rf_stop, + .set_chan = rtl8225_rf_set_channel, +}; + +const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + u16 reg8, reg9; + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); + rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + msleep(100); + + rtl8225_write(dev, 0, 0x1B7); + + reg8 = rtl8225_read(dev, 8); + reg9 = rtl8225_read(dev, 9); + + rtl8225_write(dev, 0, 0x0B7); + + if (reg8 != 0x588 || reg9 != 0x700) + return &rtl8225_ops; + + return &rtl8225z2_ops; +} diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.h new file mode 100644 index 000000000000..310013a2d726 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225.h @@ -0,0 +1,23 @@ +#ifndef RTL8180_RTL8225_H +#define RTL8180_RTL8225_H + +#define RTL8225_ANAPARAM_ON 0xa0000b59 +#define RTL8225_ANAPARAM2_ON 0x860dec11 +#define RTL8225_ANAPARAM_OFF 0xa00beb59 +#define RTL8225_ANAPARAM2_OFF 0x840dec11 + +const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *); + +static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev, + u8 addr, u8 data) +{ + rtl8180_write_phy(dev, addr, data); +} + +static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev, + u8 addr, u8 data) +{ + rtl8180_write_phy(dev, addr, data | 0x10000); +} + +#endif /* RTL8180_RTL8225_H */ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c new file mode 100644 index 000000000000..fde89866fa8d --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.c @@ -0,0 +1,475 @@ + +/* Radio tuning for RTL8225 on RTL8187SE + * + * Copyright 2009 Larry Finger + * Copyright 2014 Andrea Merello + * + * Based on the r8180 and Realtek r8187se drivers, which are: + * Copyright 2004-2005 Andrea Merello , et al. + * + * Also based on the rtl8187 driver, which is: + * Copyright 2007 Michael Wu + * Copyright 2007 Andrea Merello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +#include "rtl8180.h" +#include "rtl8225se.h" + +#define PFX "rtl8225 (se) " + +static const u32 RF_GAIN_TABLE[] = { + 0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6, + 0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057, + 0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3, + 0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3, + 0x0183, 0x0163, 0x0143, 0x0123, 0x0103 +}; + +static const u8 cck_ofdm_gain_settings[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, +}; + +static const u8 rtl8225se_tx_gain_cck_ofdm[] = { + 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e +}; + +static const u8 rtl8225se_tx_power_cck[] = { + 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, + 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, + 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, + 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, + 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, + 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 +}; + +static const u8 rtl8225se_tx_power_cck_ch14[] = { + 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 rtl8225se_tx_power_ofdm[] = { + 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 +}; + +static const u32 rtl8225se_chan[] = { + 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, + 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A, +}; + +static const u8 rtl8225sez2_tx_power_cck_ch14[] = { + 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 rtl8225sez2_tx_power_cck_B[] = { + 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04 +}; + +static const u8 rtl8225sez2_tx_power_cck_A[] = { + 0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04 +}; + +static const u8 rtl8225sez2_tx_power_cck[] = { + 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 +}; + +static const u8 ZEBRA_AGC[] = { + 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, + 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, + 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, + 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, + 0x48, 0x47, 0x46, 0x45, 0x44, 0x29, 0x28, 0x27, + 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07, + 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16, + 0x17, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1a, 0x1b, + 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, + 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, + 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24, + 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, + 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F +}; + +static const u8 OFDM_CONFIG[] = { + 0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, + 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26, + 0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB, + 0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00, + 0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00, + 0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e, + 0xD8, 0x3C, 0x7B, 0x10, 0x10 +}; + +static void rtl8187se_three_wire_io(struct ieee80211_hw *dev, u8 *data, + u8 len, bool write) +{ + struct rtl8180_priv *priv = dev->priv; + int i; + u8 tmp; + + do { + for (i = 0; i < 5; i++) { + tmp = rtl818x_ioread8(priv, SW_3W_CMD1); + if (!(tmp & 0x3)) + break; + udelay(10); + } + if (i == 5) + wiphy_err(dev->wiphy, PFX + "CmdReg: 0x%x RE/WE bits aren't clear\n", tmp); + + tmp = rtl818x_ioread8(priv, &priv->map->rf_sw_config) | 0x02; + rtl818x_iowrite8(priv, &priv->map->rf_sw_config, tmp); + + tmp = rtl818x_ioread8(priv, REG_ADDR1(0x84)) & 0xF7; + rtl818x_iowrite8(priv, REG_ADDR1(0x84), tmp); + if (write) { + if (len == 16) { + rtl818x_iowrite16(priv, SW_3W_DB0, + *(u16 *)data); + } else if (len == 64) { + rtl818x_iowrite32(priv, SW_3W_DB0_4, + *((u32 *)data)); + rtl818x_iowrite32(priv, SW_3W_DB1_4, + *((u32 *)(data + 4))); + } else + wiphy_err(dev->wiphy, PFX + "Unimplemented length\n"); + } else { + rtl818x_iowrite16(priv, SW_3W_DB0, *(u16 *)data); + } + if (write) + tmp = 2; + else + tmp = 1; + rtl818x_iowrite8(priv, SW_3W_CMD1, tmp); + for (i = 0; i < 5; i++) { + tmp = rtl818x_ioread8(priv, SW_3W_CMD1); + if (!(tmp & 0x3)) + break; + udelay(10); + } + rtl818x_iowrite8(priv, SW_3W_CMD1, 0); + if (!write) { + *((u16 *)data) = rtl818x_ioread16(priv, SI_DATA_REG); + *((u16 *)data) &= 0x0FFF; + } + } while (0); +} + +static u32 rtl8187se_rf_readreg(struct ieee80211_hw *dev, u8 addr) +{ + u32 dataread = addr & 0x0F; + rtl8187se_three_wire_io(dev, (u8 *)&dataread, 16, 0); + return dataread; +} + +static void rtl8187se_rf_writereg(struct ieee80211_hw *dev, u8 addr, u32 data) +{ + u32 outdata = (data << 4) | (u32)(addr & 0x0F); + rtl8187se_three_wire_io(dev, (u8 *)&outdata, 16, 1); +} + + +static void rtl8225se_write_zebra_agc(struct ieee80211_hw *dev) +{ + int i; + + for (i = 0; i < 128; i++) { + rtl8225se_write_phy_ofdm(dev, 0xF, ZEBRA_AGC[i]); + rtl8225se_write_phy_ofdm(dev, 0xE, i+0x80); + rtl8225se_write_phy_ofdm(dev, 0xE, 0); + } +} + +static void rtl8187se_write_ofdm_config(struct ieee80211_hw *dev) +{ + /* write OFDM_CONFIG table */ + int i; + + for (i = 0; i < 60; i++) + rtl8225se_write_phy_ofdm(dev, i, OFDM_CONFIG[i]); + +} + +static void rtl8225sez2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) +{ + struct rtl8180_priv *priv = dev->priv; + u8 cck_power, ofdm_power; + + cck_power = priv->channels[channel - 1].hw_value & 0xFF; + if (cck_power > 35) + cck_power = 35; + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, + cck_ofdm_gain_settings[cck_power]); + + usleep_range(1000, 5000); + ofdm_power = priv->channels[channel - 1].hw_value >> 8; + if (ofdm_power > 35) + ofdm_power = 35; + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, + cck_ofdm_gain_settings[ofdm_power]); + if (ofdm_power < 12) { + rtl8225se_write_phy_ofdm(dev, 7, 0x5C); + rtl8225se_write_phy_ofdm(dev, 9, 0x5C); + } + if (ofdm_power < 18) { + rtl8225se_write_phy_ofdm(dev, 7, 0x54); + rtl8225se_write_phy_ofdm(dev, 9, 0x54); + } else { + rtl8225se_write_phy_ofdm(dev, 7, 0x50); + rtl8225se_write_phy_ofdm(dev, 9, 0x50); + } + + usleep_range(1000, 5000); +} + +static void rtl8187se_write_rf_gain(struct ieee80211_hw *dev) +{ + int i; + + for (i = 0; i <= 36; i++) { + rtl8187se_rf_writereg(dev, 0x01, i); mdelay(1); + rtl8187se_rf_writereg(dev, 0x02, RF_GAIN_TABLE[i]); mdelay(1); + } +} + +static void rtl8187se_write_initial_gain(struct ieee80211_hw *dev, + int init_gain) +{ + switch (init_gain) { + default: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x26); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1); + break; + case 2: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1); + break; + case 3: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1); + break; + case 4: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1); + break; + case 5: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1); + break; + case 6: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1); + break; + case 7: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0xA6); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1); + break; + case 8: + rtl8225se_write_phy_ofdm(dev, 0x17, 0x66); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x24, 0xB6); mdelay(1); + rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1); + break; + } +} + +void rtl8225se_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + u32 rf23, rf24; + u8 d_cut = 0; + u8 tmp; + + /* Page 1 */ + rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1); + rf23 = rtl8187se_rf_readreg(dev, 0x08); mdelay(1); + rf24 = rtl8187se_rf_readreg(dev, 0x09); mdelay(1); + if (rf23 == 0x0818 && rf24 == 0x070C) + d_cut = 1; + + wiphy_info(dev->wiphy, "RTL8225-SE version %s\n", + d_cut ? "D" : "not-D"); + + /* Page 0: reg 0 - 15 */ + rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1); + rtl8187se_rf_writereg(dev, 0x01, 0x06E0); mdelay(1); + rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1); + rtl8187se_rf_writereg(dev, 0x03, 0x07F1); mdelay(1); + rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(1); + rtl8187se_rf_writereg(dev, 0x05, 0x0C72); mdelay(1); + rtl8187se_rf_writereg(dev, 0x06, 0x0AE6); mdelay(1); + rtl8187se_rf_writereg(dev, 0x07, 0x00CA); mdelay(1); + rtl8187se_rf_writereg(dev, 0x08, 0x0E1C); mdelay(1); + rtl8187se_rf_writereg(dev, 0x09, 0x02F0); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0A, 0x09D0); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0B, 0x01BA); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0C, 0x0640); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0E, 0x0020); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0F, 0x0990); mdelay(1); + /* page 1: reg 16-30 */ + rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1); + rtl8187se_rf_writereg(dev, 0x03, 0x0806); mdelay(1); + rtl8187se_rf_writereg(dev, 0x04, 0x03A7); mdelay(1); + rtl8187se_rf_writereg(dev, 0x05, 0x059B); mdelay(1); + rtl8187se_rf_writereg(dev, 0x06, 0x0081); mdelay(1); + rtl8187se_rf_writereg(dev, 0x07, 0x01A0); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0B, 0x0418); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0C, 0x0FBE); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(1); + if (d_cut) + rtl8187se_rf_writereg(dev, 0x0E, 0x0807); + else + rtl8187se_rf_writereg(dev, 0x0E, 0x0806); + mdelay(1); + rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC); mdelay(1); + rtl8187se_rf_writereg(dev, 0x00, 0x01D7); mdelay(1); + rtl8187se_rf_writereg(dev, 0x03, 0x0E00); mdelay(1); + rtl8187se_rf_writereg(dev, 0x04, 0x0E50); mdelay(1); + + rtl8187se_write_rf_gain(dev); + + rtl8187se_rf_writereg(dev, 0x05, 0x0203); mdelay(1); + rtl8187se_rf_writereg(dev, 0x06, 0x0200); mdelay(1); + rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11); + rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(11); + rtl8187se_rf_writereg(dev, 0x00, 0x0037); mdelay(11); + rtl8187se_rf_writereg(dev, 0x04, 0x0160); mdelay(11); + rtl8187se_rf_writereg(dev, 0x07, 0x0080); mdelay(11); + rtl8187se_rf_writereg(dev, 0x02, 0x088D); mdelay(221); + rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11); + rtl8187se_rf_writereg(dev, 0x07, 0x0000); mdelay(1); + rtl8187se_rf_writereg(dev, 0x07, 0x0180); mdelay(1); + rtl8187se_rf_writereg(dev, 0x07, 0x0220); mdelay(1); + rtl8187se_rf_writereg(dev, 0x07, 0x03E0); mdelay(1); + rtl8187se_rf_writereg(dev, 0x06, 0x00C1); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1); + if (priv->xtal_cal) { + tmp = (priv->xtal_in << 4) | (priv->xtal_out << 1) | + (1 << 11) | (1 << 9); + rtl8187se_rf_writereg(dev, 0x0F, tmp); + wiphy_info(dev->wiphy, "Xtal cal\n"); + mdelay(1); + } else { + wiphy_info(dev->wiphy, "NO Xtal cal\n"); + rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC); + mdelay(1); + } + /* page 0 */ + rtl8187se_rf_writereg(dev, 0x00, 0x00BF); mdelay(1); + rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1); + rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1); + rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(31); + rtl8187se_rf_writereg(dev, 0x00, 0x0197); mdelay(1); + rtl8187se_rf_writereg(dev, 0x05, 0x05AB); mdelay(1); + + rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1); + rtl8187se_rf_writereg(dev, 0x01, 0x0000); mdelay(1); + rtl8187se_rf_writereg(dev, 0x02, 0x0000); mdelay(1); + /* power save parameters */ + /* TODO: move to dev.c */ + rtl818x_iowrite8(priv, REG_ADDR1(0x024E), + rtl818x_ioread8(priv, REG_ADDR1(0x24E)) & 0x9F); + rtl8225se_write_phy_cck(dev, 0x00, 0xC8); + rtl8225se_write_phy_cck(dev, 0x06, 0x1C); + rtl8225se_write_phy_cck(dev, 0x10, 0x78); + rtl8225se_write_phy_cck(dev, 0x2E, 0xD0); + rtl8225se_write_phy_cck(dev, 0x2F, 0x06); + rtl8225se_write_phy_cck(dev, 0x01, 0x46); + + /* power control */ + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x10); + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x1B); + + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); + rtl8225se_write_phy_ofdm(dev, 0x00, 0x12); + + rtl8225se_write_zebra_agc(dev); + + rtl8225se_write_phy_ofdm(dev, 0x10, 0x00); + + rtl8187se_write_ofdm_config(dev); + + /* turn on RF */ + rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500); + rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500); + /* turn on RF again */ + rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500); + rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500); + /* turn on BB */ + rtl8225se_write_phy_ofdm(dev, 0x10, 0x40); + rtl8225se_write_phy_ofdm(dev, 0x12, 0x40); + + rtl8187se_write_initial_gain(dev, 4); +} + +void rtl8225se_rf_stop(struct ieee80211_hw *dev) +{ + /* checked for 8187se */ + struct rtl8180_priv *priv = dev->priv; + + /* turn off BB RXIQ matrix to cut off rx signal */ + rtl8225se_write_phy_ofdm(dev, 0x10, 0x00); + rtl8225se_write_phy_ofdm(dev, 0x12, 0x00); + /* turn off RF */ + rtl8187se_rf_writereg(dev, 0x04, 0x0000); + rtl8187se_rf_writereg(dev, 0x00, 0x0000); + + usleep_range(1000, 5000); + /* turn off A/D and D/A */ + rtl8180_set_anaparam(priv, RTL8225SE_ANAPARAM_OFF); + rtl8180_set_anaparam2(priv, RTL8225SE_ANAPARAM2_OFF); +} + +void rtl8225se_rf_set_channel(struct ieee80211_hw *dev, + struct ieee80211_conf *conf) +{ + int chan = + ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); + + rtl8225sez2_rf_set_tx_power(dev, chan); + rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]); + if ((rtl8187se_rf_readreg(dev, 0x7) & 0x0F80) != + rtl8225se_chan[chan - 1]) + rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]); + usleep_range(10000, 20000); +} + +static const struct rtl818x_rf_ops rtl8225se_ops = { + .name = "rtl8225-se", + .init = rtl8225se_rf_init, + .stop = rtl8225se_rf_stop, + .set_chan = rtl8225se_rf_set_channel, +}; + +const struct rtl818x_rf_ops *rtl8187se_detect_rf(struct ieee80211_hw *dev) +{ + return &rtl8225se_ops; +} diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.h new file mode 100644 index 000000000000..229400264088 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/rtl8225se.h @@ -0,0 +1,61 @@ + +/* Definitions for RTL8187SE hardware + * + * Copyright 2009 Larry Finger + * Copyright 2014 Andrea Merello + * + * Based on the r8180 and Realtek r8187se drivers, which are: + * Copyright 2004-2005 Andrea Merello , et al. + * + * Also based on the rtl8187 driver, which is: + * Copyright 2007 Michael Wu + * Copyright 2007 Andrea Merello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef RTL8187SE_RTL8225_H +#define RTL8187SE_RTL8225_H + +#define RTL8225SE_ANAPARAM_ON 0xb0054d00 +#define RTL8225SE_ANAPARAM2_ON 0x000004c6 + +/* all off except PLL */ +#define RTL8225SE_ANAPARAM_OFF 0xb0054dec +/* all on including PLL */ +#define RTL8225SE_ANAPARAM_OFF2 0xb0054dfc + +#define RTL8225SE_ANAPARAM2_OFF 0x00ff04c6 + +#define RTL8225SE_ANAPARAM3 0x10 + +enum rtl8187se_power_state { + RTL8187SE_POWER_ON, + RTL8187SE_POWER_OFF, + RTL8187SE_POWER_SLEEP +}; + +static inline void rtl8225se_write_phy_ofdm(struct ieee80211_hw *dev, + u8 addr, u8 data) +{ + rtl8180_write_phy(dev, addr, data); +} + +static inline void rtl8225se_write_phy_cck(struct ieee80211_hw *dev, + u8 addr, u8 data) +{ + rtl8180_write_phy(dev, addr, data | 0x10000); +} + + +const struct rtl818x_rf_ops *rtl8187se_detect_rf(struct ieee80211_hw *); +void rtl8225se_rf_stop(struct ieee80211_hw *dev); +void rtl8225se_rf_set_channel(struct ieee80211_hw *dev, + struct ieee80211_conf *conf); +void rtl8225se_rf_conf_erp(struct ieee80211_hw *dev, + struct ieee80211_bss_conf *info); +void rtl8225se_rf_init(struct ieee80211_hw *dev); + +#endif /* RTL8187SE_RTL8225_H */ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.c new file mode 100644 index 000000000000..959b049827de --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.c @@ -0,0 +1,228 @@ + +/* + * Radio tuning for Philips SA2400 on RTL8180 + * + * Copyright 2007 Andrea Merello + * + * Code from the BSD driver and the rtl8181 project have been + * very useful to understand certain things + * + * I want to thanks the Authors of such projects and the Ndiswrapper + * project Authors. + * + * A special Big Thanks also is for all people who donated me cards, + * making possible the creation of the original rtl8180 driver + * from which this code is derived! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include "rtl8180.h" +#include "sa2400.h" + +static const u32 sa2400_chan[] = { + 0x00096c, /* ch1 */ + 0x080970, + 0x100974, + 0x180978, + 0x000980, + 0x080984, + 0x100988, + 0x18098c, + 0x000994, + 0x080998, + 0x10099c, + 0x1809a0, + 0x0009a8, + 0x0009b4, /* ch 14 */ +}; + +static void write_sa2400(struct ieee80211_hw *dev, u8 addr, u32 data) +{ + struct rtl8180_priv *priv = dev->priv; + u32 phy_config; + + /* MAC will bang bits to the sa2400. sw 3-wire is NOT used */ + phy_config = 0xb0000000; + + phy_config |= ((u32)(addr & 0xf)) << 24; + phy_config |= data & 0xffffff; + + rtl818x_iowrite32(priv, + (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config); + + msleep(3); +} + +static void sa2400_write_phy_antenna(struct ieee80211_hw *dev, short chan) +{ + struct rtl8180_priv *priv = dev->priv; + u8 ant = SA2400_ANTENNA; + + if (priv->rfparam & RF_PARAM_ANTBDEFAULT) + ant |= BB_ANTENNA_B; + + if (chan == 14) + ant |= BB_ANTATTEN_CHAN14; + + rtl8180_write_phy(dev, 0x10, ant); + +} + +static u8 sa2400_rf_rssi_map[] = { + 0x64, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, + 0x5d, 0x5c, 0x5b, 0x5a, 0x57, 0x54, 0x52, 0x50, + 0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x41, 0x3f, + 0x3c, 0x3a, 0x37, 0x36, 0x36, 0x1c, 0x1c, 0x1b, + 0x1b, 0x1a, 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, + 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, + 0x13, 0x12, 0x12, 0x11, 0x11, 0x10, 0x10, 0x0f, + 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, + 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07, + 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02, +}; + +static u8 sa2400_rf_calc_rssi(u8 agc, u8 sq) +{ + if (sq == 0x80) + return 1; + + if (sq > 78) + return 32; + + /* TODO: recalc sa2400_rf_rssi_map to avoid mult / div */ + return 65 * sa2400_rf_rssi_map[sq] / 100; +} + +static void sa2400_rf_set_channel(struct ieee80211_hw *dev, + struct ieee80211_conf *conf) +{ + struct rtl8180_priv *priv = dev->priv; + int channel = + ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); + u32 txpw = priv->channels[channel - 1].hw_value & 0xFF; + u32 chan = sa2400_chan[channel - 1]; + + write_sa2400(dev, 7, txpw); + + sa2400_write_phy_antenna(dev, channel); + + write_sa2400(dev, 0, chan); + write_sa2400(dev, 1, 0xbb50); + write_sa2400(dev, 2, 0x80); + write_sa2400(dev, 3, 0); +} + +static void sa2400_rf_stop(struct ieee80211_hw *dev) +{ + write_sa2400(dev, 4, 0); +} + +static void sa2400_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8180_priv *priv = dev->priv; + u32 anaparam, txconf; + u8 firdac; + int analogphy = priv->rfparam & RF_PARAM_ANALOGPHY; + + anaparam = priv->anaparam; + anaparam &= ~(1 << ANAPARAM_TXDACOFF_SHIFT); + anaparam &= ~ANAPARAM_PWR1_MASK; + anaparam &= ~ANAPARAM_PWR0_MASK; + + if (analogphy) { + anaparam |= SA2400_ANA_ANAPARAM_PWR1_ON << ANAPARAM_PWR1_SHIFT; + firdac = 0; + } else { + anaparam |= (SA2400_DIG_ANAPARAM_PWR1_ON << ANAPARAM_PWR1_SHIFT); + anaparam |= (SA2400_ANAPARAM_PWR0_ON << ANAPARAM_PWR0_SHIFT); + firdac = 1 << SA2400_REG4_FIRDAC_SHIFT; + } + + rtl8180_set_anaparam(priv, anaparam); + + write_sa2400(dev, 0, sa2400_chan[0]); + write_sa2400(dev, 1, 0xbb50); + write_sa2400(dev, 2, 0x80); + write_sa2400(dev, 3, 0); + write_sa2400(dev, 4, 0x19340 | firdac); + write_sa2400(dev, 5, 0x1dfb | (SA2400_MAX_SENS - 54) << 15); + write_sa2400(dev, 4, 0x19348 | firdac); /* calibrate VCO */ + + if (!analogphy) + write_sa2400(dev, 4, 0x1938c); /*???*/ + + write_sa2400(dev, 4, 0x19340 | firdac); + + write_sa2400(dev, 0, sa2400_chan[0]); + write_sa2400(dev, 1, 0xbb50); + write_sa2400(dev, 2, 0x80); + write_sa2400(dev, 3, 0); + write_sa2400(dev, 4, 0x19344 | firdac); /* calibrate filter */ + + /* new from rtl8180 embedded driver (rtl8181 project) */ + write_sa2400(dev, 6, 0x13ff | (1 << 23)); /* MANRX */ + write_sa2400(dev, 8, 0); /* VCO */ + + if (analogphy) { + rtl8180_set_anaparam(priv, anaparam | + (1 << ANAPARAM_TXDACOFF_SHIFT)); + + txconf = rtl818x_ioread32(priv, &priv->map->TX_CONF); + rtl818x_iowrite32(priv, &priv->map->TX_CONF, + txconf | RTL818X_TX_CONF_LOOPBACK_CONT); + + write_sa2400(dev, 4, 0x19341); /* calibrates DC */ + + /* a 5us sleep is required here, + * we rely on the 3ms delay introduced in write_sa2400 */ + write_sa2400(dev, 4, 0x19345); + + /* a 20us sleep is required here, + * we rely on the 3ms delay introduced in write_sa2400 */ + + rtl818x_iowrite32(priv, &priv->map->TX_CONF, txconf); + + rtl8180_set_anaparam(priv, anaparam); + } + /* end new code */ + + write_sa2400(dev, 4, 0x19341 | firdac); /* RTX MODE */ + + /* baseband configuration */ + rtl8180_write_phy(dev, 0, 0x98); + rtl8180_write_phy(dev, 3, 0x38); + rtl8180_write_phy(dev, 4, 0xe0); + rtl8180_write_phy(dev, 5, 0x90); + rtl8180_write_phy(dev, 6, 0x1a); + rtl8180_write_phy(dev, 7, 0x64); + + sa2400_write_phy_antenna(dev, 1); + + rtl8180_write_phy(dev, 0x11, 0x80); + + if (rtl818x_ioread8(priv, &priv->map->CONFIG2) & + RTL818X_CONFIG2_ANTENNA_DIV) + rtl8180_write_phy(dev, 0x12, 0xc7); /* enable ant diversity */ + else + rtl8180_write_phy(dev, 0x12, 0x47); /* disable ant diversity */ + + rtl8180_write_phy(dev, 0x13, 0x90 | priv->csthreshold); + + rtl8180_write_phy(dev, 0x19, 0x0); + rtl8180_write_phy(dev, 0x1a, 0xa0); +} + +const struct rtl818x_rf_ops sa2400_rf_ops = { + .name = "Philips", + .init = sa2400_rf_init, + .stop = sa2400_rf_stop, + .set_chan = sa2400_rf_set_channel, + .calc_rssi = sa2400_rf_calc_rssi, +}; diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.h b/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.h new file mode 100644 index 000000000000..fb0093f35148 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/sa2400.h @@ -0,0 +1,36 @@ +#ifndef RTL8180_SA2400_H +#define RTL8180_SA2400_H + +/* + * Radio tuning for Philips SA2400 on RTL8180 + * + * Copyright 2007 Andrea Merello + * + * Code from the BSD driver and the rtl8181 project have been + * very useful to understand certain things + * + * I want to thanks the Authors of such projects and the Ndiswrapper + * project Authors. + * + * A special Big Thanks also is for all people who donated me cards, + * making possible the creation of the original rtl8180 driver + * from which this code is derived! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define SA2400_ANTENNA 0x91 +#define SA2400_DIG_ANAPARAM_PWR1_ON 0x8 +#define SA2400_ANA_ANAPARAM_PWR1_ON 0x28 +#define SA2400_ANAPARAM_PWR0_ON 0x3 + +/* RX sensitivity in dbm */ +#define SA2400_MAX_SENS 85 + +#define SA2400_REG4_FIRDAC_SHIFT 7 + +extern const struct rtl818x_rf_ops sa2400_rf_ops; + +#endif /* RTL8180_SA2400_H */ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile b/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile new file mode 100644 index 000000000000..ff074912a095 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/Makefile @@ -0,0 +1,5 @@ +rtl8187-objs := dev.o rtl8225.o leds.o rfkill.o + +obj-$(CONFIG_RTL8187) += rtl8187.o + +ccflags-y += -Idrivers/net/wireless/realtek/rtl818x diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c new file mode 100644 index 000000000000..b7f72f9c7988 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c @@ -0,0 +1,1684 @@ +/* + * Linux device driver for RTL8187 + * + * Copyright 2007 Michael Wu + * Copyright 2007 Andrea Merello + * + * Based on the r8187 driver, which is: + * Copyright 2005 Andrea Merello , et al. + * + * The driver was extended to the RTL8187B in 2008 by: + * Herton Ronaldo Krzesinski + * Hin-Tak Leung + * Larry Finger + * + * Magic delays and register offsets below are taken from the original + * r8187 driver sources. Thanks to Realtek for their support! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "rtl8187.h" +#include "rtl8225.h" +#ifdef CONFIG_RTL8187_LEDS +#include "leds.h" +#endif +#include "rfkill.h" + +MODULE_AUTHOR("Michael Wu "); +MODULE_AUTHOR("Andrea Merello "); +MODULE_AUTHOR("Herton Ronaldo Krzesinski "); +MODULE_AUTHOR("Hin-Tak Leung "); +MODULE_AUTHOR("Larry Finger "); +MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); +MODULE_LICENSE("GPL"); + +static struct usb_device_id rtl8187_table[] = { + /* Asus */ + {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, + /* Belkin */ + {USB_DEVICE(0x050d, 0x705e), .driver_info = DEVICE_RTL8187B}, + /* Realtek */ + {USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187}, + {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, + {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, + {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B}, + /* Surecom */ + {USB_DEVICE(0x0769, 0x11F2), .driver_info = DEVICE_RTL8187}, + /* Logitech */ + {USB_DEVICE(0x0789, 0x010C), .driver_info = DEVICE_RTL8187}, + /* Netgear */ + {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, + {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, + {USB_DEVICE(0x0846, 0x4260), .driver_info = DEVICE_RTL8187B}, + /* HP */ + {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, + /* Sitecom */ + {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, + {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, + {USB_DEVICE(0x0df6, 0x0029), .driver_info = DEVICE_RTL8187B}, + /* Sphairon Access Systems GmbH */ + {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187}, + /* Dick Smith Electronics */ + {USB_DEVICE(0x1371, 0x9401), .driver_info = DEVICE_RTL8187}, + /* Abocom */ + {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, + /* Qcom */ + {USB_DEVICE(0x18E8, 0x6232), .driver_info = DEVICE_RTL8187}, + /* AirLive */ + {USB_DEVICE(0x1b75, 0x8187), .driver_info = DEVICE_RTL8187}, + /* Linksys */ + {USB_DEVICE(0x1737, 0x0073), .driver_info = DEVICE_RTL8187B}, + {} +}; + +MODULE_DEVICE_TABLE(usb, rtl8187_table); + +static const struct ieee80211_rate rtl818x_rates[] = { + { .bitrate = 10, .hw_value = 0, }, + { .bitrate = 20, .hw_value = 1, }, + { .bitrate = 55, .hw_value = 2, }, + { .bitrate = 110, .hw_value = 3, }, + { .bitrate = 60, .hw_value = 4, }, + { .bitrate = 90, .hw_value = 5, }, + { .bitrate = 120, .hw_value = 6, }, + { .bitrate = 180, .hw_value = 7, }, + { .bitrate = 240, .hw_value = 8, }, + { .bitrate = 360, .hw_value = 9, }, + { .bitrate = 480, .hw_value = 10, }, + { .bitrate = 540, .hw_value = 11, }, +}; + +static const struct ieee80211_channel rtl818x_channels[] = { + { .center_freq = 2412 }, + { .center_freq = 2417 }, + { .center_freq = 2422 }, + { .center_freq = 2427 }, + { .center_freq = 2432 }, + { .center_freq = 2437 }, + { .center_freq = 2442 }, + { .center_freq = 2447 }, + { .center_freq = 2452 }, + { .center_freq = 2457 }, + { .center_freq = 2462 }, + { .center_freq = 2467 }, + { .center_freq = 2472 }, + { .center_freq = 2484 }, +}; + +static void rtl8187_iowrite_async_cb(struct urb *urb) +{ + kfree(urb->context); +} + +static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr, + void *data, u16 len) +{ + struct usb_ctrlrequest *dr; + struct urb *urb; + struct rtl8187_async_write_data { + u8 data[4]; + struct usb_ctrlrequest dr; + } *buf; + int rc; + + buf = kmalloc(sizeof(*buf), GFP_ATOMIC); + if (!buf) + return; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + kfree(buf); + return; + } + + dr = &buf->dr; + + dr->bRequestType = RTL8187_REQT_WRITE; + dr->bRequest = RTL8187_REQ_SET_REG; + dr->wValue = addr; + dr->wIndex = 0; + dr->wLength = cpu_to_le16(len); + + memcpy(buf, data, len); + + usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0), + (unsigned char *)dr, buf, len, + rtl8187_iowrite_async_cb, buf); + usb_anchor_urb(urb, &priv->anchored); + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc < 0) { + kfree(buf); + usb_unanchor_urb(urb); + } + usb_free_urb(urb); +} + +static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv, + __le32 *addr, u32 val) +{ + __le32 buf = cpu_to_le32(val); + + rtl8187_iowrite_async(priv, cpu_to_le16((unsigned long)addr), + &buf, sizeof(buf)); +} + +void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) +{ + struct rtl8187_priv *priv = dev->priv; + + data <<= 8; + data |= addr | 0x80; + + rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF); + rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF); + rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF); + rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF); +} + +static void rtl8187_tx_cb(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *)urb->context; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hw *hw = info->rate_driver_data[0]; + struct rtl8187_priv *priv = hw->priv; + + skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : + sizeof(struct rtl8187_tx_hdr)); + ieee80211_tx_info_clear_status(info); + + if (!(urb->status) && !(info->flags & IEEE80211_TX_CTL_NO_ACK)) { + if (priv->is_rtl8187b) { + skb_queue_tail(&priv->b_tx_status.queue, skb); + + /* queue is "full", discard last items */ + while (skb_queue_len(&priv->b_tx_status.queue) > 5) { + struct sk_buff *old_skb; + + dev_dbg(&priv->udev->dev, + "transmit status queue full\n"); + + old_skb = skb_dequeue(&priv->b_tx_status.queue); + ieee80211_tx_status_irqsafe(hw, old_skb); + } + return; + } else { + info->flags |= IEEE80211_TX_STAT_ACK; + } + } + if (priv->is_rtl8187b) + ieee80211_tx_status_irqsafe(hw, skb); + else { + /* Retry information for the RTI8187 is only available by + * reading a register in the device. We are in interrupt mode + * here, thus queue the skb and finish on a work queue. */ + skb_queue_tail(&priv->b_tx_status.queue, skb); + ieee80211_queue_delayed_work(hw, &priv->work, 0); + } +} + +static void rtl8187_tx(struct ieee80211_hw *dev, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct rtl8187_priv *priv = dev->priv; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_hdr *tx_hdr = (struct ieee80211_hdr *)(skb->data); + unsigned int ep; + void *buf; + struct urb *urb; + __le16 rts_dur = 0; + u32 flags; + int rc; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + kfree_skb(skb); + return; + } + + flags = skb->len; + flags |= RTL818X_TX_DESC_FLAG_NO_ENC; + + flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24; + if (ieee80211_has_morefrags(tx_hdr->frame_control)) + flags |= RTL818X_TX_DESC_FLAG_MOREFRAG; + + /* HW will perform RTS-CTS when only RTS flags is set. + * HW will perform CTS-to-self when both RTS and CTS flags are set. + * RTS rate and RTS duration will be used also for CTS-to-self. + */ + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { + flags |= RTL818X_TX_DESC_FLAG_RTS; + flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; + rts_dur = ieee80211_rts_duration(dev, priv->vif, + skb->len, info); + } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { + flags |= RTL818X_TX_DESC_FLAG_RTS | RTL818X_TX_DESC_FLAG_CTS; + flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; + rts_dur = ieee80211_ctstoself_duration(dev, priv->vif, + skb->len, info); + } + + if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + priv->seqno += 0x10; + tx_hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + tx_hdr->seq_ctrl |= cpu_to_le16(priv->seqno); + } + + if (!priv->is_rtl8187b) { + struct rtl8187_tx_hdr *hdr = + (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); + hdr->flags = cpu_to_le32(flags); + hdr->len = 0; + hdr->rts_duration = rts_dur; + hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); + buf = hdr; + + ep = 2; + } else { + /* fc needs to be calculated before skb_push() */ + unsigned int epmap[4] = { 6, 7, 5, 4 }; + u16 fc = le16_to_cpu(tx_hdr->frame_control); + + struct rtl8187b_tx_hdr *hdr = + (struct rtl8187b_tx_hdr *)skb_push(skb, sizeof(*hdr)); + struct ieee80211_rate *txrate = + ieee80211_get_tx_rate(dev, info); + memset(hdr, 0, sizeof(*hdr)); + hdr->flags = cpu_to_le32(flags); + hdr->rts_duration = rts_dur; + hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); + hdr->tx_duration = + ieee80211_generic_frame_duration(dev, priv->vif, + info->band, + skb->len, txrate); + buf = hdr; + + if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) + ep = 12; + else + ep = epmap[skb_get_queue_mapping(skb)]; + } + + info->rate_driver_data[0] = dev; + info->rate_driver_data[1] = urb; + + usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep), + buf, skb->len, rtl8187_tx_cb, skb); + urb->transfer_flags |= URB_ZERO_PACKET; + usb_anchor_urb(urb, &priv->anchored); + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc < 0) { + usb_unanchor_urb(urb); + kfree_skb(skb); + } + usb_free_urb(urb); +} + +static void rtl8187_rx_cb(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *)urb->context; + struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb; + struct ieee80211_hw *dev = info->dev; + struct rtl8187_priv *priv = dev->priv; + struct ieee80211_rx_status rx_status = { 0 }; + int rate, signal; + u32 flags; + unsigned long f; + + spin_lock_irqsave(&priv->rx_queue.lock, f); + __skb_unlink(skb, &priv->rx_queue); + spin_unlock_irqrestore(&priv->rx_queue.lock, f); + skb_put(skb, urb->actual_length); + + if (unlikely(urb->status)) { + dev_kfree_skb_irq(skb); + return; + } + + if (!priv->is_rtl8187b) { + struct rtl8187_rx_hdr *hdr = + (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); + flags = le32_to_cpu(hdr->flags); + /* As with the RTL8187B below, the AGC is used to calculate + * signal strength. In this case, the scaling + * constants are derived from the output of p54usb. + */ + signal = -4 - ((27 * hdr->agc) >> 6); + rx_status.antenna = (hdr->signal >> 7) & 1; + rx_status.mactime = le64_to_cpu(hdr->mac_time); + } else { + struct rtl8187b_rx_hdr *hdr = + (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); + /* The Realtek datasheet for the RTL8187B shows that the RX + * header contains the following quantities: signal quality, + * RSSI, AGC, the received power in dB, and the measured SNR. + * In testing, none of these quantities show qualitative + * agreement with AP signal strength, except for the AGC, + * which is inversely proportional to the strength of the + * signal. In the following, the signal strength + * is derived from the AGC. The arbitrary scaling constants + * are chosen to make the results close to the values obtained + * for a BCM4312 using b43 as the driver. The noise is ignored + * for now. + */ + flags = le32_to_cpu(hdr->flags); + signal = 14 - hdr->agc / 2; + rx_status.antenna = (hdr->rssi >> 7) & 1; + rx_status.mactime = le64_to_cpu(hdr->mac_time); + } + + rx_status.signal = signal; + priv->signal = signal; + rate = (flags >> 20) & 0xF; + skb_trim(skb, flags & 0x0FFF); + rx_status.rate_idx = rate; + rx_status.freq = dev->conf.chandef.chan->center_freq; + rx_status.band = dev->conf.chandef.chan->band; + rx_status.flag |= RX_FLAG_MACTIME_START; + if (flags & RTL818X_RX_DESC_FLAG_SPLCP) + rx_status.flag |= RX_FLAG_SHORTPRE; + if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) + rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; + memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); + ieee80211_rx_irqsafe(dev, skb); + + skb = dev_alloc_skb(RTL8187_MAX_RX); + if (unlikely(!skb)) { + /* TODO check rx queue length and refill *somewhere* */ + return; + } + + info = (struct rtl8187_rx_info *)skb->cb; + info->urb = urb; + info->dev = dev; + urb->transfer_buffer = skb_tail_pointer(skb); + urb->context = skb; + skb_queue_tail(&priv->rx_queue, skb); + + usb_anchor_urb(urb, &priv->anchored); + if (usb_submit_urb(urb, GFP_ATOMIC)) { + usb_unanchor_urb(urb); + skb_unlink(skb, &priv->rx_queue); + dev_kfree_skb_irq(skb); + } +} + +static int rtl8187_init_urbs(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + struct urb *entry = NULL; + struct sk_buff *skb; + struct rtl8187_rx_info *info; + int ret = 0; + + while (skb_queue_len(&priv->rx_queue) < 32) { + skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL); + if (!skb) { + ret = -ENOMEM; + goto err; + } + entry = usb_alloc_urb(0, GFP_KERNEL); + if (!entry) { + ret = -ENOMEM; + goto err; + } + usb_fill_bulk_urb(entry, priv->udev, + usb_rcvbulkpipe(priv->udev, + priv->is_rtl8187b ? 3 : 1), + skb_tail_pointer(skb), + RTL8187_MAX_RX, rtl8187_rx_cb, skb); + info = (struct rtl8187_rx_info *)skb->cb; + info->urb = entry; + info->dev = dev; + skb_queue_tail(&priv->rx_queue, skb); + usb_anchor_urb(entry, &priv->anchored); + ret = usb_submit_urb(entry, GFP_KERNEL); + usb_put_urb(entry); + if (ret) { + skb_unlink(skb, &priv->rx_queue); + usb_unanchor_urb(entry); + goto err; + } + } + return ret; + +err: + kfree_skb(skb); + usb_kill_anchored_urbs(&priv->anchored); + return ret; +} + +static void rtl8187b_status_cb(struct urb *urb) +{ + struct ieee80211_hw *hw = (struct ieee80211_hw *)urb->context; + struct rtl8187_priv *priv = hw->priv; + u64 val; + unsigned int cmd_type; + + if (unlikely(urb->status)) + return; + + /* + * Read from status buffer: + * + * bits [30:31] = cmd type: + * - 0 indicates tx beacon interrupt + * - 1 indicates tx close descriptor + * + * In the case of tx beacon interrupt: + * [0:9] = Last Beacon CW + * [10:29] = reserved + * [30:31] = 00b + * [32:63] = Last Beacon TSF + * + * If it's tx close descriptor: + * [0:7] = Packet Retry Count + * [8:14] = RTS Retry Count + * [15] = TOK + * [16:27] = Sequence No + * [28] = LS + * [29] = FS + * [30:31] = 01b + * [32:47] = unused (reserved?) + * [48:63] = MAC Used Time + */ + val = le64_to_cpu(priv->b_tx_status.buf); + + cmd_type = (val >> 30) & 0x3; + if (cmd_type == 1) { + unsigned int pkt_rc, seq_no; + bool tok; + struct sk_buff *skb; + struct ieee80211_hdr *ieee80211hdr; + unsigned long flags; + + pkt_rc = val & 0xFF; + tok = val & (1 << 15); + seq_no = (val >> 16) & 0xFFF; + + spin_lock_irqsave(&priv->b_tx_status.queue.lock, flags); + skb_queue_reverse_walk(&priv->b_tx_status.queue, skb) { + ieee80211hdr = (struct ieee80211_hdr *)skb->data; + + /* + * While testing, it was discovered that the seq_no + * doesn't actually contains the sequence number. + * Instead of returning just the 12 bits of sequence + * number, hardware is returning entire sequence control + * (fragment number plus sequence number) in a 12 bit + * only field overflowing after some time. As a + * workaround, just consider the lower bits, and expect + * it's unlikely we wrongly ack some sent data + */ + if ((le16_to_cpu(ieee80211hdr->seq_ctrl) + & 0xFFF) == seq_no) + break; + } + if (skb != (struct sk_buff *) &priv->b_tx_status.queue) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + + __skb_unlink(skb, &priv->b_tx_status.queue); + if (tok) + info->flags |= IEEE80211_TX_STAT_ACK; + info->status.rates[0].count = pkt_rc + 1; + + ieee80211_tx_status_irqsafe(hw, skb); + } + spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags); + } + + usb_anchor_urb(urb, &priv->anchored); + if (usb_submit_urb(urb, GFP_ATOMIC)) + usb_unanchor_urb(urb); +} + +static int rtl8187b_init_status_urb(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + struct urb *entry; + int ret = 0; + + entry = usb_alloc_urb(0, GFP_KERNEL); + if (!entry) + return -ENOMEM; + + usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9), + &priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf), + rtl8187b_status_cb, dev); + + usb_anchor_urb(entry, &priv->anchored); + ret = usb_submit_urb(entry, GFP_KERNEL); + if (ret) + usb_unanchor_urb(entry); + usb_free_urb(entry); + + return ret; +} + +static void rtl8187_set_anaparam(struct rtl8187_priv *priv, bool rfon) +{ + u32 anaparam, anaparam2; + u8 anaparam3, reg; + + if (!priv->is_rtl8187b) { + if (rfon) { + anaparam = RTL8187_RTL8225_ANAPARAM_ON; + anaparam2 = RTL8187_RTL8225_ANAPARAM2_ON; + } else { + anaparam = RTL8187_RTL8225_ANAPARAM_OFF; + anaparam2 = RTL8187_RTL8225_ANAPARAM2_OFF; + } + } else { + if (rfon) { + anaparam = RTL8187B_RTL8225_ANAPARAM_ON; + anaparam2 = RTL8187B_RTL8225_ANAPARAM2_ON; + anaparam3 = RTL8187B_RTL8225_ANAPARAM3_ON; + } else { + anaparam = RTL8187B_RTL8225_ANAPARAM_OFF; + anaparam2 = RTL8187B_RTL8225_ANAPARAM2_OFF; + anaparam3 = RTL8187B_RTL8225_ANAPARAM3_OFF; + } + } + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + reg |= RTL818X_CONFIG3_ANAPARAM_WRITE; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, anaparam); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, anaparam2); + if (priv->is_rtl8187b) + rtl818x_iowrite8(priv, &priv->map->ANAPARAM3A, anaparam3); + reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); +} + +static int rtl8187_cmd_reset(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + u8 reg; + int i; + + reg = rtl818x_ioread8(priv, &priv->map->CMD); + reg &= (1 << 1); + reg |= RTL818X_CMD_RESET; + rtl818x_iowrite8(priv, &priv->map->CMD, reg); + + i = 10; + do { + msleep(2); + if (!(rtl818x_ioread8(priv, &priv->map->CMD) & + RTL818X_CMD_RESET)) + break; + } while (--i); + + if (!i) { + wiphy_err(dev->wiphy, "Reset timeout!\n"); + return -ETIMEDOUT; + } + + /* reload registers from eeprom */ + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD); + + i = 10; + do { + msleep(4); + if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) & + RTL818X_EEPROM_CMD_CONFIG)) + break; + } while (--i); + + if (!i) { + wiphy_err(dev->wiphy, "eeprom reset timeout!\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int rtl8187_init_hw(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + u8 reg; + int res; + + /* reset */ + rtl8187_set_anaparam(priv, true); + + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); + + msleep(200); + rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10); + rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11); + rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00); + msleep(200); + + res = rtl8187_cmd_reset(dev); + if (res) + return res; + + rtl8187_set_anaparam(priv, true); + + /* setup card */ + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0); + rtl818x_iowrite8(priv, &priv->map->GPIO0, 0); + + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8)); + rtl818x_iowrite8(priv, &priv->map->GPIO0, 1); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + + rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); + reg &= 0x3F; + reg |= 0x80; + rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); + rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); + rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0); + + // TODO: set RESP_RATE and BRSR properly + rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0); + rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); + + /* host_usb_init */ + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0); + rtl818x_iowrite8(priv, &priv->map->GPIO0, 0); + reg = rtl818x_ioread8(priv, (u8 *)0xFE53); + rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7)); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8)); + rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x20); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80); + msleep(100); + + rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008); + rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); + rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7); + msleep(100); + + priv->rf->init(dev); + + rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~1; + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1); + rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10); + rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80); + rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + + return 0; +} + +static const u8 rtl8187b_reg_table[][3] = { + {0xF0, 0x32, 0}, {0xF1, 0x32, 0}, {0xF2, 0x00, 0}, {0xF3, 0x00, 0}, + {0xF4, 0x32, 0}, {0xF5, 0x43, 0}, {0xF6, 0x00, 0}, {0xF7, 0x00, 0}, + {0xF8, 0x46, 0}, {0xF9, 0xA4, 0}, {0xFA, 0x00, 0}, {0xFB, 0x00, 0}, + {0xFC, 0x96, 0}, {0xFD, 0xA4, 0}, {0xFE, 0x00, 0}, {0xFF, 0x00, 0}, + + {0x58, 0x4B, 1}, {0x59, 0x00, 1}, {0x5A, 0x4B, 1}, {0x5B, 0x00, 1}, + {0x60, 0x4B, 1}, {0x61, 0x09, 1}, {0x62, 0x4B, 1}, {0x63, 0x09, 1}, + {0xCE, 0x0F, 1}, {0xCF, 0x00, 1}, {0xF0, 0x4E, 1}, {0xF1, 0x01, 1}, + {0xF2, 0x02, 1}, {0xF3, 0x03, 1}, {0xF4, 0x04, 1}, {0xF5, 0x05, 1}, + {0xF6, 0x06, 1}, {0xF7, 0x07, 1}, {0xF8, 0x08, 1}, + + {0x4E, 0x00, 2}, {0x0C, 0x04, 2}, {0x21, 0x61, 2}, {0x22, 0x68, 2}, + {0x23, 0x6F, 2}, {0x24, 0x76, 2}, {0x25, 0x7D, 2}, {0x26, 0x84, 2}, + {0x27, 0x8D, 2}, {0x4D, 0x08, 2}, {0x50, 0x05, 2}, {0x51, 0xF5, 2}, + {0x52, 0x04, 2}, {0x53, 0xA0, 2}, {0x54, 0x1F, 2}, {0x55, 0x23, 2}, + {0x56, 0x45, 2}, {0x57, 0x67, 2}, {0x58, 0x08, 2}, {0x59, 0x08, 2}, + {0x5A, 0x08, 2}, {0x5B, 0x08, 2}, {0x60, 0x08, 2}, {0x61, 0x08, 2}, + {0x62, 0x08, 2}, {0x63, 0x08, 2}, {0x64, 0xCF, 2}, + + {0x5B, 0x40, 0}, {0x84, 0x88, 0}, {0x85, 0x24, 0}, {0x88, 0x54, 0}, + {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, + {0x95, 0x12, 0}, {0x96, 0x00, 0}, {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, + {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, + {0xEE, 0x00, 0}, {0x4C, 0x00, 2}, + + {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, {0x8E, 0x08, 0}, + {0x8F, 0x00, 0} +}; + +static int rtl8187b_init_hw(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + int res, i; + u8 reg; + + rtl8187_set_anaparam(priv, true); + + /* Reset PLL sequence on 8187B. Realtek note: reduces power + * consumption about 30 mA */ + rtl818x_iowrite8(priv, (u8 *)0xFF61, 0x10); + reg = rtl818x_ioread8(priv, (u8 *)0xFF62); + rtl818x_iowrite8(priv, (u8 *)0xFF62, reg & ~(1 << 5)); + rtl818x_iowrite8(priv, (u8 *)0xFF62, reg | (1 << 5)); + + res = rtl8187_cmd_reset(dev); + if (res) + return res; + + rtl8187_set_anaparam(priv, true); + + /* BRSR (Basic Rate Set Register) on 8187B looks to be the same as + * RESP_RATE on 8187L in Realtek sources: each bit should be each + * one of the 12 rates, all are enabled */ + rtl818x_iowrite16(priv, (__le16 *)0xFF34, 0x0FFF); + + reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); + reg |= RTL818X_CW_CONF_PERPACKET_RETRY; + rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); + + /* Auto Rate Fallback Register (ARFR): 1M-54M setting */ + rtl818x_iowrite16_idx(priv, (__le16 *)0xFFE0, 0x0FFF, 1); + rtl818x_iowrite8_idx(priv, (u8 *)0xFFE2, 0x00, 1); + + rtl818x_iowrite16_idx(priv, (__le16 *)0xFFD4, 0xFFFF, 1); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); + rtl818x_iowrite8(priv, &priv->map->CONFIG1, (reg & 0x3F) | 0x80); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); + + rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); + for (i = 0; i < ARRAY_SIZE(rtl8187b_reg_table); i++) { + rtl818x_iowrite8_idx(priv, + (u8 *)(uintptr_t) + (rtl8187b_reg_table[i][0] | 0xFF00), + rtl8187b_reg_table[i][1], + rtl8187b_reg_table[i][2]); + } + + rtl818x_iowrite16(priv, &priv->map->TID_AC_MAP, 0xFA50); + rtl818x_iowrite16(priv, &priv->map->INT_MIG, 0); + + rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF0, 0, 1); + rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF4, 0, 1); + rtl818x_iowrite8_idx(priv, (u8 *)0xFFF8, 0, 1); + + rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00004001); + + /* RFSW_CTRL register */ + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x569A, 2); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); + msleep(100); + + priv->rf->init(dev); + + reg = RTL818X_CMD_TX_ENABLE | RTL818X_CMD_RX_ENABLE; + rtl818x_iowrite8(priv, &priv->map->CMD, reg); + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); + + rtl818x_iowrite8(priv, (u8 *)0xFE41, 0xF4); + rtl818x_iowrite8(priv, (u8 *)0xFE40, 0x00); + rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x00); + rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x01); + rtl818x_iowrite8(priv, (u8 *)0xFE40, 0x0F); + rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x00); + rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x01); + + reg = rtl818x_ioread8(priv, (u8 *)0xFFDB); + rtl818x_iowrite8(priv, (u8 *)0xFFDB, reg | (1 << 2)); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x59FA, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF74, 0x59D2, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF76, 0x59D2, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF78, 0x19FA, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF7A, 0x19FA, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF7C, 0x00D0, 3); + rtl818x_iowrite8(priv, (u8 *)0xFF61, 0); + rtl818x_iowrite8_idx(priv, (u8 *)0xFF80, 0x0F, 1); + rtl818x_iowrite8_idx(priv, (u8 *)0xFF83, 0x03, 1); + rtl818x_iowrite8(priv, (u8 *)0xFFDA, 0x10); + rtl818x_iowrite8_idx(priv, (u8 *)0xFF4D, 0x08, 2); + + rtl818x_iowrite32(priv, &priv->map->HSSI_PARA, 0x0600321B); + + rtl818x_iowrite16_idx(priv, (__le16 *)0xFFEC, 0x0800, 1); + + priv->slot_time = 0x9; + priv->aifsn[0] = 2; /* AIFSN[AC_VO] */ + priv->aifsn[1] = 2; /* AIFSN[AC_VI] */ + priv->aifsn[2] = 7; /* AIFSN[AC_BK] */ + priv->aifsn[3] = 3; /* AIFSN[AC_BE] */ + rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0); + + /* ENEDCA flag must always be set, transmit issues? */ + rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_ENEDCA); + + return 0; +} + +static void rtl8187_work(struct work_struct *work) +{ + /* The RTL8187 returns the retry count through register 0xFFFA. In + * addition, it appears to be a cumulative retry count, not the + * value for the current TX packet. When multiple TX entries are + * waiting in the queue, the retry count will be the total for all. + * The "error" may matter for purposes of rate setting, but there is + * no other choice with this hardware. + */ + struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, + work.work); + struct ieee80211_tx_info *info; + struct ieee80211_hw *dev = priv->dev; + static u16 retry; + u16 tmp; + u16 avg_retry; + int length; + + mutex_lock(&priv->conf_mutex); + tmp = rtl818x_ioread16(priv, (__le16 *)0xFFFA); + length = skb_queue_len(&priv->b_tx_status.queue); + if (unlikely(!length)) + length = 1; + if (unlikely(tmp < retry)) + tmp = retry; + avg_retry = (tmp - retry) / length; + while (skb_queue_len(&priv->b_tx_status.queue) > 0) { + struct sk_buff *old_skb; + + old_skb = skb_dequeue(&priv->b_tx_status.queue); + info = IEEE80211_SKB_CB(old_skb); + info->status.rates[0].count = avg_retry + 1; + if (info->status.rates[0].count > RETRY_COUNT) + info->flags &= ~IEEE80211_TX_STAT_ACK; + ieee80211_tx_status_irqsafe(dev, old_skb); + } + retry = tmp; + mutex_unlock(&priv->conf_mutex); +} + +static int rtl8187_start(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + u32 reg; + int ret; + + mutex_lock(&priv->conf_mutex); + + ret = (!priv->is_rtl8187b) ? rtl8187_init_hw(dev) : + rtl8187b_init_hw(dev); + if (ret) + goto rtl8187_start_exit; + + init_usb_anchor(&priv->anchored); + priv->dev = dev; + + if (priv->is_rtl8187b) { + reg = RTL818X_RX_CONF_MGMT | + RTL818X_RX_CONF_DATA | + RTL818X_RX_CONF_BROADCAST | + RTL818X_RX_CONF_NICMAC | + RTL818X_RX_CONF_BSSID | + (7 << 13 /* RX FIFO threshold NONE */) | + (7 << 10 /* MAX RX DMA */) | + RTL818X_RX_CONF_RX_AUTORESETPHY | + RTL818X_RX_CONF_ONLYERLPKT | + RTL818X_RX_CONF_MULTICAST; + priv->rx_conf = reg; + rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); + + reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); + reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN; + reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL; + reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT; + rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); + + rtl818x_iowrite32(priv, &priv->map->TX_CONF, + RTL818X_TX_CONF_HW_SEQNUM | + RTL818X_TX_CONF_DISREQQSIZE | + (RETRY_COUNT << 8 /* short retry limit */) | + (RETRY_COUNT << 0 /* long retry limit */) | + (7 << 21 /* MAX TX DMA */)); + ret = rtl8187_init_urbs(dev); + if (ret) + goto rtl8187_start_exit; + ret = rtl8187b_init_status_urb(dev); + if (ret) + usb_kill_anchored_urbs(&priv->anchored); + goto rtl8187_start_exit; + } + + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); + + rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); + rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); + + ret = rtl8187_init_urbs(dev); + if (ret) + goto rtl8187_start_exit; + + reg = RTL818X_RX_CONF_ONLYERLPKT | + RTL818X_RX_CONF_RX_AUTORESETPHY | + RTL818X_RX_CONF_BSSID | + RTL818X_RX_CONF_MGMT | + RTL818X_RX_CONF_DATA | + (7 << 13 /* RX FIFO threshold NONE */) | + (7 << 10 /* MAX RX DMA */) | + RTL818X_RX_CONF_BROADCAST | + RTL818X_RX_CONF_NICMAC; + + priv->rx_conf = reg; + rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); + + reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); + reg &= ~RTL818X_CW_CONF_PERPACKET_CW; + reg |= RTL818X_CW_CONF_PERPACKET_RETRY; + rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); + + reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); + reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN; + reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL; + reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT; + rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); + + reg = RTL818X_TX_CONF_CW_MIN | + (7 << 21 /* MAX TX DMA */) | + RTL818X_TX_CONF_NO_ICV; + rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); + + reg = rtl818x_ioread8(priv, &priv->map->CMD); + reg |= RTL818X_CMD_TX_ENABLE; + reg |= RTL818X_CMD_RX_ENABLE; + rtl818x_iowrite8(priv, &priv->map->CMD, reg); + INIT_DELAYED_WORK(&priv->work, rtl8187_work); + +rtl8187_start_exit: + mutex_unlock(&priv->conf_mutex); + return ret; +} + +static void rtl8187_stop(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + struct sk_buff *skb; + u32 reg; + + mutex_lock(&priv->conf_mutex); + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); + + reg = rtl818x_ioread8(priv, &priv->map->CMD); + reg &= ~RTL818X_CMD_TX_ENABLE; + reg &= ~RTL818X_CMD_RX_ENABLE; + rtl818x_iowrite8(priv, &priv->map->CMD, reg); + + priv->rf->stop(dev); + rtl8187_set_anaparam(priv, false); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG4); + rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + while ((skb = skb_dequeue(&priv->b_tx_status.queue))) + dev_kfree_skb_any(skb); + + usb_kill_anchored_urbs(&priv->anchored); + mutex_unlock(&priv->conf_mutex); + + if (!priv->is_rtl8187b) + cancel_delayed_work_sync(&priv->work); +} + +static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif) +{ + struct rtl8187_priv *priv = dev->priv; + + return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | + (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; +} + + +static void rtl8187_beacon_work(struct work_struct *work) +{ + struct rtl8187_vif *vif_priv = + container_of(work, struct rtl8187_vif, beacon_work.work); + struct ieee80211_vif *vif = + container_of((void *)vif_priv, struct ieee80211_vif, drv_priv); + struct ieee80211_hw *dev = vif_priv->dev; + struct ieee80211_mgmt *mgmt; + struct sk_buff *skb; + + /* don't overflow the tx ring */ + if (ieee80211_queue_stopped(dev, 0)) + goto resched; + + /* grab a fresh beacon */ + skb = ieee80211_beacon_get(dev, vif); + if (!skb) + goto resched; + + /* + * update beacon timestamp w/ TSF value + * TODO: make hardware update beacon timestamp + */ + mgmt = (struct ieee80211_mgmt *)skb->data; + mgmt->u.beacon.timestamp = cpu_to_le64(rtl8187_get_tsf(dev, vif)); + + /* TODO: use actual beacon queue */ + skb_set_queue_mapping(skb, 0); + + rtl8187_tx(dev, NULL, skb); + +resched: + /* + * schedule next beacon + * TODO: use hardware support for beacon timing + */ + schedule_delayed_work(&vif_priv->beacon_work, + usecs_to_jiffies(1024 * vif->bss_conf.beacon_int)); +} + + +static int rtl8187_add_interface(struct ieee80211_hw *dev, + struct ieee80211_vif *vif) +{ + struct rtl8187_priv *priv = dev->priv; + struct rtl8187_vif *vif_priv; + int i; + int ret = -EOPNOTSUPP; + + mutex_lock(&priv->conf_mutex); + if (priv->vif) + goto exit; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_ADHOC: + break; + default: + goto exit; + } + + ret = 0; + priv->vif = vif; + + /* Initialize driver private area */ + vif_priv = (struct rtl8187_vif *)&vif->drv_priv; + vif_priv->dev = dev; + INIT_DELAYED_WORK(&vif_priv->beacon_work, rtl8187_beacon_work); + vif_priv->enable_beacon = false; + + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + for (i = 0; i < ETH_ALEN; i++) + rtl818x_iowrite8(priv, &priv->map->MAC[i], + ((u8 *)vif->addr)[i]); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + +exit: + mutex_unlock(&priv->conf_mutex); + return ret; +} + +static void rtl8187_remove_interface(struct ieee80211_hw *dev, + struct ieee80211_vif *vif) +{ + struct rtl8187_priv *priv = dev->priv; + mutex_lock(&priv->conf_mutex); + priv->vif = NULL; + mutex_unlock(&priv->conf_mutex); +} + +static int rtl8187_config(struct ieee80211_hw *dev, u32 changed) +{ + struct rtl8187_priv *priv = dev->priv; + struct ieee80211_conf *conf = &dev->conf; + u32 reg; + + mutex_lock(&priv->conf_mutex); + reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); + /* Enable TX loopback on MAC level to avoid TX during channel + * changes, as this has be seen to causes problems and the + * card will stop work until next reset + */ + rtl818x_iowrite32(priv, &priv->map->TX_CONF, + reg | RTL818X_TX_CONF_LOOPBACK_MAC); + priv->rf->set_chan(dev, conf); + msleep(10); + rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); + + rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); + rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100); + rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); + rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100); + mutex_unlock(&priv->conf_mutex); + return 0; +} + +/* + * With 8187B, AC_*_PARAM clashes with FEMR definition in struct rtl818x_csr for + * example. Thus we have to use raw values for AC_*_PARAM register addresses. + */ +static __le32 *rtl8187b_ac_addr[4] = { + (__le32 *) 0xFFF0, /* AC_VO */ + (__le32 *) 0xFFF4, /* AC_VI */ + (__le32 *) 0xFFFC, /* AC_BK */ + (__le32 *) 0xFFF8, /* AC_BE */ +}; + +#define SIFS_TIME 0xa + +static void rtl8187_conf_erp(struct rtl8187_priv *priv, bool use_short_slot, + bool use_short_preamble) +{ + if (priv->is_rtl8187b) { + u8 difs, eifs; + u16 ack_timeout; + int queue; + + if (use_short_slot) { + priv->slot_time = 0x9; + difs = 0x1c; + eifs = 0x53; + } else { + priv->slot_time = 0x14; + difs = 0x32; + eifs = 0x5b; + } + rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); + rtl818x_iowrite8(priv, &priv->map->SLOT, priv->slot_time); + rtl818x_iowrite8(priv, &priv->map->DIFS, difs); + + /* + * BRSR+1 on 8187B is in fact EIFS register + * Value in units of 4 us + */ + rtl818x_iowrite8(priv, (u8 *)&priv->map->BRSR + 1, eifs); + + /* + * For 8187B, CARRIER_SENSE_COUNTER is in fact ack timeout + * register. In units of 4 us like eifs register + * ack_timeout = ack duration + plcp + difs + preamble + */ + ack_timeout = 112 + 48 + difs; + if (use_short_preamble) + ack_timeout += 72; + else + ack_timeout += 144; + rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, + DIV_ROUND_UP(ack_timeout, 4)); + + for (queue = 0; queue < 4; queue++) + rtl818x_iowrite8(priv, (u8 *) rtl8187b_ac_addr[queue], + priv->aifsn[queue] * priv->slot_time + + SIFS_TIME); + } else { + rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); + if (use_short_slot) { + rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); + rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); + rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); + } else { + rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); + rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); + rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); + } + } +} + +static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + struct rtl8187_priv *priv = dev->priv; + struct rtl8187_vif *vif_priv; + int i; + u8 reg; + + vif_priv = (struct rtl8187_vif *)&vif->drv_priv; + + if (changed & BSS_CHANGED_BSSID) { + mutex_lock(&priv->conf_mutex); + for (i = 0; i < ETH_ALEN; i++) + rtl818x_iowrite8(priv, &priv->map->BSSID[i], + info->bssid[i]); + + if (priv->is_rtl8187b) + reg = RTL818X_MSR_ENEDCA; + else + reg = 0; + + if (is_valid_ether_addr(info->bssid)) { + if (vif->type == NL80211_IFTYPE_ADHOC) + reg |= RTL818X_MSR_ADHOC; + else + reg |= RTL818X_MSR_INFRA; + } + else + reg |= RTL818X_MSR_NO_LINK; + + rtl818x_iowrite8(priv, &priv->map->MSR, reg); + + mutex_unlock(&priv->conf_mutex); + } + + if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE)) + rtl8187_conf_erp(priv, info->use_short_slot, + info->use_short_preamble); + + if (changed & BSS_CHANGED_BEACON_ENABLED) + vif_priv->enable_beacon = info->enable_beacon; + + if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON)) { + cancel_delayed_work_sync(&vif_priv->beacon_work); + if (vif_priv->enable_beacon) + schedule_work(&vif_priv->beacon_work.work); + } + +} + +static u64 rtl8187_prepare_multicast(struct ieee80211_hw *dev, + struct netdev_hw_addr_list *mc_list) +{ + return netdev_hw_addr_list_count(mc_list); +} + +static void rtl8187_configure_filter(struct ieee80211_hw *dev, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct rtl8187_priv *priv = dev->priv; + + if (changed_flags & FIF_FCSFAIL) + priv->rx_conf ^= RTL818X_RX_CONF_FCS; + if (changed_flags & FIF_CONTROL) + priv->rx_conf ^= RTL818X_RX_CONF_CTRL; + if (changed_flags & FIF_OTHER_BSS) + priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; + if (*total_flags & FIF_ALLMULTI || multicast > 0) + priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; + else + priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; + + *total_flags = 0; + + if (priv->rx_conf & RTL818X_RX_CONF_FCS) + *total_flags |= FIF_FCSFAIL; + if (priv->rx_conf & RTL818X_RX_CONF_CTRL) + *total_flags |= FIF_CONTROL; + if (priv->rx_conf & RTL818X_RX_CONF_MONITOR) + *total_flags |= FIF_OTHER_BSS; + if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) + *total_flags |= FIF_ALLMULTI; + + rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf); +} + +static int rtl8187_conf_tx(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, u16 queue, + const struct ieee80211_tx_queue_params *params) +{ + struct rtl8187_priv *priv = dev->priv; + u8 cw_min, cw_max; + + if (queue > 3) + return -EINVAL; + + cw_min = fls(params->cw_min); + cw_max = fls(params->cw_max); + + if (priv->is_rtl8187b) { + priv->aifsn[queue] = params->aifs; + + /* + * This is the structure of AC_*_PARAM registers in 8187B: + * - TXOP limit field, bit offset = 16 + * - ECWmax, bit offset = 12 + * - ECWmin, bit offset = 8 + * - AIFS, bit offset = 0 + */ + rtl818x_iowrite32(priv, rtl8187b_ac_addr[queue], + (params->txop << 16) | (cw_max << 12) | + (cw_min << 8) | (params->aifs * + priv->slot_time + SIFS_TIME)); + } else { + if (queue != 0) + return -EINVAL; + + rtl818x_iowrite8(priv, &priv->map->CW_VAL, + cw_min | (cw_max << 4)); + } + return 0; +} + + +static const struct ieee80211_ops rtl8187_ops = { + .tx = rtl8187_tx, + .start = rtl8187_start, + .stop = rtl8187_stop, + .add_interface = rtl8187_add_interface, + .remove_interface = rtl8187_remove_interface, + .config = rtl8187_config, + .bss_info_changed = rtl8187_bss_info_changed, + .prepare_multicast = rtl8187_prepare_multicast, + .configure_filter = rtl8187_configure_filter, + .conf_tx = rtl8187_conf_tx, + .rfkill_poll = rtl8187_rfkill_poll, + .get_tsf = rtl8187_get_tsf, +}; + +static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) +{ + struct ieee80211_hw *dev = eeprom->data; + struct rtl8187_priv *priv = dev->priv; + u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); + + eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE; + eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ; + eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK; + eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS; +} + +static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom) +{ + struct ieee80211_hw *dev = eeprom->data; + struct rtl8187_priv *priv = dev->priv; + u8 reg = RTL818X_EEPROM_CMD_PROGRAM; + + if (eeprom->reg_data_in) + reg |= RTL818X_EEPROM_CMD_WRITE; + if (eeprom->reg_data_out) + reg |= RTL818X_EEPROM_CMD_READ; + if (eeprom->reg_data_clock) + reg |= RTL818X_EEPROM_CMD_CK; + if (eeprom->reg_chip_select) + reg |= RTL818X_EEPROM_CMD_CS; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg); + udelay(10); +} + +static int rtl8187_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct ieee80211_hw *dev; + struct rtl8187_priv *priv; + struct eeprom_93cx6 eeprom; + struct ieee80211_channel *channel; + const char *chip_name; + u16 txpwr, reg; + u16 product_id = le16_to_cpu(udev->descriptor.idProduct); + int err, i; + u8 mac_addr[ETH_ALEN]; + + dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops); + if (!dev) { + printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n"); + return -ENOMEM; + } + + priv = dev->priv; + priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B); + + /* allocate "DMA aware" buffer for register accesses */ + priv->io_dmabuf = kmalloc(sizeof(*priv->io_dmabuf), GFP_KERNEL); + if (!priv->io_dmabuf) { + err = -ENOMEM; + goto err_free_dev; + } + mutex_init(&priv->io_mutex); + + SET_IEEE80211_DEV(dev, &intf->dev); + usb_set_intfdata(intf, dev); + priv->udev = udev; + + usb_get_dev(udev); + + skb_queue_head_init(&priv->rx_queue); + + BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels)); + BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates)); + + memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); + memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); + priv->map = (struct rtl818x_csr *)0xFF00; + + priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); + priv->band.bitrates = priv->rates; + priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); + dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + + + ieee80211_hw_set(dev, RX_INCLUDES_FCS); + ieee80211_hw_set(dev, HOST_BROADCAST_PS_BUFFERING); + ieee80211_hw_set(dev, SIGNAL_DBM); + /* Initialize rate-control variables */ + dev->max_rates = 1; + dev->max_rate_tries = RETRY_COUNT; + + eeprom.data = dev; + eeprom.register_read = rtl8187_eeprom_register_read; + eeprom.register_write = rtl8187_eeprom_register_write; + if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6)) + eeprom.width = PCI_EEPROM_WIDTH_93C66; + else + eeprom.width = PCI_EEPROM_WIDTH_93C46; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + udelay(10); + + eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR, + (__le16 __force *)mac_addr, 3); + if (!is_valid_ether_addr(mac_addr)) { + printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly " + "generated MAC address\n"); + eth_random_addr(mac_addr); + } + SET_IEEE80211_PERM_ADDR(dev, mac_addr); + + channel = priv->channels; + for (i = 0; i < 3; i++) { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i, + &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; + } + for (i = 0; i < 2; i++) { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i, + &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; + } + + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE, + &priv->txpwr_base); + + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~1; + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1); + /* 0 means asic B-cut, we should use SW 3 wire + * bit-by-bit banging for radio. 1 means we can use + * USB specific request to write radio registers */ + priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3; + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + if (!priv->is_rtl8187b) { + u32 reg32; + reg32 = rtl818x_ioread32(priv, &priv->map->TX_CONF); + reg32 &= RTL818X_TX_CONF_HWVER_MASK; + switch (reg32) { + case RTL818X_TX_CONF_R8187vD_B: + /* Some RTL8187B devices have a USB ID of 0x8187 + * detect them here */ + chip_name = "RTL8187BvB(early)"; + priv->is_rtl8187b = 1; + priv->hw_rev = RTL8187BvB; + break; + case RTL818X_TX_CONF_R8187vD: + chip_name = "RTL8187vD"; + break; + default: + chip_name = "RTL8187vB (default)"; + } + } else { + /* + * Force USB request to write radio registers for 8187B, Realtek + * only uses it in their sources + */ + /*if (priv->asic_rev == 0) { + printk(KERN_WARNING "rtl8187: Forcing use of USB " + "requests to write to radio registers\n"); + priv->asic_rev = 1; + }*/ + switch (rtl818x_ioread8(priv, (u8 *)0xFFE1)) { + case RTL818X_R8187B_B: + chip_name = "RTL8187BvB"; + priv->hw_rev = RTL8187BvB; + break; + case RTL818X_R8187B_D: + chip_name = "RTL8187BvD"; + priv->hw_rev = RTL8187BvD; + break; + case RTL818X_R8187B_E: + chip_name = "RTL8187BvE"; + priv->hw_rev = RTL8187BvE; + break; + default: + chip_name = "RTL8187BvB (default)"; + priv->hw_rev = RTL8187BvB; + } + } + + if (!priv->is_rtl8187b) { + for (i = 0; i < 2; i++) { + eeprom_93cx6_read(&eeprom, + RTL8187_EEPROM_TXPWR_CHAN_6 + i, + &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; + } + } else { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6, + &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + + eeprom_93cx6_read(&eeprom, 0x0A, &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + + eeprom_93cx6_read(&eeprom, 0x1C, &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; + } + /* Handle the differing rfkill GPIO bit in different models */ + priv->rfkill_mask = RFKILL_MASK_8187_89_97; + if (product_id == 0x8197 || product_id == 0x8198) { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_SELECT_GPIO, ®); + if (reg & 0xFF00) + priv->rfkill_mask = RFKILL_MASK_8198; + } + dev->vif_data_size = sizeof(struct rtl8187_vif); + dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) ; + + if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) + printk(KERN_INFO "rtl8187: inconsistency between id with OEM" + " info!\n"); + + priv->rf = rtl8187_detect_rf(dev); + dev->extra_tx_headroom = (!priv->is_rtl8187b) ? + sizeof(struct rtl8187_tx_hdr) : + sizeof(struct rtl8187b_tx_hdr); + if (!priv->is_rtl8187b) + dev->queues = 1; + else + dev->queues = 4; + + err = ieee80211_register_hw(dev); + if (err) { + printk(KERN_ERR "rtl8187: Cannot register device\n"); + goto err_free_dmabuf; + } + mutex_init(&priv->conf_mutex); + skb_queue_head_init(&priv->b_tx_status.queue); + + wiphy_info(dev->wiphy, "hwaddr %pM, %s V%d + %s, rfkill mask %d\n", + mac_addr, chip_name, priv->asic_rev, priv->rf->name, + priv->rfkill_mask); + +#ifdef CONFIG_RTL8187_LEDS + eeprom_93cx6_read(&eeprom, 0x3F, ®); + reg &= 0xFF; + rtl8187_leds_init(dev, reg); +#endif + rtl8187_rfkill_init(dev); + + return 0; + + err_free_dmabuf: + kfree(priv->io_dmabuf); + usb_set_intfdata(intf, NULL); + usb_put_dev(udev); + err_free_dev: + ieee80211_free_hw(dev); + return err; +} + +static void rtl8187_disconnect(struct usb_interface *intf) +{ + struct ieee80211_hw *dev = usb_get_intfdata(intf); + struct rtl8187_priv *priv; + + if (!dev) + return; + +#ifdef CONFIG_RTL8187_LEDS + rtl8187_leds_exit(dev); +#endif + rtl8187_rfkill_exit(dev); + ieee80211_unregister_hw(dev); + + priv = dev->priv; + usb_reset_device(priv->udev); + usb_put_dev(interface_to_usbdev(intf)); + kfree(priv->io_dmabuf); + ieee80211_free_hw(dev); +} + +static struct usb_driver rtl8187_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl8187_table, + .probe = rtl8187_probe, + .disconnect = rtl8187_disconnect, + .disable_hub_initiated_lpm = 1, +}; + +module_usb_driver(rtl8187_driver); diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.c new file mode 100644 index 000000000000..c2d5b495c179 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.c @@ -0,0 +1,245 @@ +/* + * Linux LED driver for RTL8187 + * + * Copyright 2009 Larry Finger + * + * Based on the LED handling in the r8187 driver, which is: + * Copyright (c) Realtek Semiconductor Corp. All rights reserved. + * + * Thanks to Realtek for their support! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifdef CONFIG_RTL8187_LEDS + +#include +#include +#include + +#include "rtl8187.h" +#include "leds.h" + +static void led_turn_on(struct work_struct *work) +{ + /* As this routine does read/write operations on the hardware, it must + * be run from a work queue. + */ + u8 reg; + struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, + led_on.work); + struct rtl8187_led *led = &priv->led_tx; + + /* Don't change the LED, when the device is down. */ + if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) + return ; + + /* Skip if the LED is not registered. */ + if (!led->dev) + return; + mutex_lock(&priv->conf_mutex); + switch (led->ledpin) { + case LED_PIN_GPIO0: + rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x00); + break; + case LED_PIN_LED0: + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 4); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + break; + case LED_PIN_LED1: + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 5); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + break; + case LED_PIN_HW: + default: + break; + } + mutex_unlock(&priv->conf_mutex); +} + +static void led_turn_off(struct work_struct *work) +{ + /* As this routine does read/write operations on the hardware, it must + * be run from a work queue. + */ + u8 reg; + struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, + led_off.work); + struct rtl8187_led *led = &priv->led_tx; + + /* Don't change the LED, when the device is down. */ + if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) + return ; + + /* Skip if the LED is not registered. */ + if (!led->dev) + return; + mutex_lock(&priv->conf_mutex); + switch (led->ledpin) { + case LED_PIN_GPIO0: + rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01); + rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x01); + break; + case LED_PIN_LED0: + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 4); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + break; + case LED_PIN_LED1: + reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 5); + rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); + break; + case LED_PIN_HW: + default: + break; + } + mutex_unlock(&priv->conf_mutex); +} + +/* Callback from the LED subsystem. */ +static void rtl8187_led_brightness_set(struct led_classdev *led_dev, + enum led_brightness brightness) +{ + struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led, + led_dev); + struct ieee80211_hw *hw = led->dev; + struct rtl8187_priv *priv; + static bool radio_on; + + if (!hw) + return; + priv = hw->priv; + if (led->is_radio) { + if (brightness == LED_FULL) { + ieee80211_queue_delayed_work(hw, &priv->led_on, 0); + radio_on = true; + } else if (radio_on) { + radio_on = false; + cancel_delayed_work(&priv->led_on); + ieee80211_queue_delayed_work(hw, &priv->led_off, 0); + } + } else if (radio_on) { + if (brightness == LED_OFF) { + ieee80211_queue_delayed_work(hw, &priv->led_off, 0); + /* The LED is off for 1/20 sec - it just blinks. */ + ieee80211_queue_delayed_work(hw, &priv->led_on, + HZ / 20); + } else + ieee80211_queue_delayed_work(hw, &priv->led_on, 0); + } +} + +static int rtl8187_register_led(struct ieee80211_hw *dev, + struct rtl8187_led *led, const char *name, + const char *default_trigger, u8 ledpin, + bool is_radio) +{ + int err; + struct rtl8187_priv *priv = dev->priv; + + if (led->dev) + return -EEXIST; + if (!default_trigger) + return -EINVAL; + led->dev = dev; + led->ledpin = ledpin; + led->is_radio = is_radio; + strncpy(led->name, name, sizeof(led->name)); + + led->led_dev.name = led->name; + led->led_dev.default_trigger = default_trigger; + led->led_dev.brightness_set = rtl8187_led_brightness_set; + + err = led_classdev_register(&priv->udev->dev, &led->led_dev); + if (err) { + printk(KERN_INFO "LEDs: Failed to register %s\n", name); + led->dev = NULL; + return err; + } + return 0; +} + +static void rtl8187_unregister_led(struct rtl8187_led *led) +{ + struct ieee80211_hw *hw = led->dev; + struct rtl8187_priv *priv = hw->priv; + + led_classdev_unregister(&led->led_dev); + flush_delayed_work(&priv->led_off); + led->dev = NULL; +} + +void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid) +{ + struct rtl8187_priv *priv = dev->priv; + char name[RTL8187_LED_MAX_NAME_LEN + 1]; + u8 ledpin; + int err; + + /* According to the vendor driver, the LED operation depends on the + * customer ID encoded in the EEPROM + */ + printk(KERN_INFO "rtl8187: Customer ID is 0x%02X\n", custid); + switch (custid) { + case EEPROM_CID_RSVD0: + case EEPROM_CID_RSVD1: + case EEPROM_CID_SERCOMM_PS: + case EEPROM_CID_QMI: + case EEPROM_CID_DELL: + case EEPROM_CID_TOSHIBA: + ledpin = LED_PIN_GPIO0; + break; + case EEPROM_CID_ALPHA0: + ledpin = LED_PIN_LED0; + break; + case EEPROM_CID_HW: + ledpin = LED_PIN_HW; + break; + default: + ledpin = LED_PIN_GPIO0; + } + + INIT_DELAYED_WORK(&priv->led_on, led_turn_on); + INIT_DELAYED_WORK(&priv->led_off, led_turn_off); + + snprintf(name, sizeof(name), + "rtl8187-%s::radio", wiphy_name(dev->wiphy)); + err = rtl8187_register_led(dev, &priv->led_radio, name, + ieee80211_get_radio_led_name(dev), ledpin, true); + if (err) + return; + + snprintf(name, sizeof(name), + "rtl8187-%s::tx", wiphy_name(dev->wiphy)); + err = rtl8187_register_led(dev, &priv->led_tx, name, + ieee80211_get_tx_led_name(dev), ledpin, false); + if (err) + goto err_tx; + + snprintf(name, sizeof(name), + "rtl8187-%s::rx", wiphy_name(dev->wiphy)); + err = rtl8187_register_led(dev, &priv->led_rx, name, + ieee80211_get_rx_led_name(dev), ledpin, false); + if (!err) + return; + + /* registration of RX LED failed - unregister */ + rtl8187_unregister_led(&priv->led_tx); +err_tx: + rtl8187_unregister_led(&priv->led_radio); +} + +void rtl8187_leds_exit(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + + rtl8187_unregister_led(&priv->led_radio); + rtl8187_unregister_led(&priv->led_rx); + rtl8187_unregister_led(&priv->led_tx); + cancel_delayed_work_sync(&priv->led_off); + cancel_delayed_work_sync(&priv->led_on); +} +#endif /* def CONFIG_RTL8187_LEDS */ + diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.h b/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.h new file mode 100644 index 000000000000..d743c96d4a20 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/leds.h @@ -0,0 +1,59 @@ +/* + * Definitions for RTL8187 leds + * + * Copyright 2009 Larry Finger + * + * Based on the LED handling in the r8187 driver, which is: + * Copyright (c) Realtek Semiconductor Corp. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef RTL8187_LED_H +#define RTL8187_LED_H + +#ifdef CONFIG_RTL8187_LEDS + +#define RTL8187_LED_MAX_NAME_LEN 21 + +#include +#include + +enum { + LED_PIN_LED0, + LED_PIN_LED1, + LED_PIN_GPIO0, + LED_PIN_HW +}; + +enum { + EEPROM_CID_RSVD0 = 0x00, + EEPROM_CID_RSVD1 = 0xFF, + EEPROM_CID_ALPHA0 = 0x01, + EEPROM_CID_SERCOMM_PS = 0x02, + EEPROM_CID_HW = 0x03, + EEPROM_CID_TOSHIBA = 0x04, + EEPROM_CID_QMI = 0x07, + EEPROM_CID_DELL = 0x08 +}; + +struct rtl8187_led { + struct ieee80211_hw *dev; + /* The LED class device */ + struct led_classdev led_dev; + /* The pin/method used to control the led */ + u8 ledpin; + /* The unique name string for this LED device. */ + char name[RTL8187_LED_MAX_NAME_LEN + 1]; + /* If the LED is radio or tx/rx */ + bool is_radio; +}; + +void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); +void rtl8187_leds_exit(struct ieee80211_hw *dev); + +#endif /* def CONFIG_RTL8187_LEDS */ + +#endif /* RTL8187_LED_H */ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.c new file mode 100644 index 000000000000..34116719974a --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.c @@ -0,0 +1,64 @@ +/* + * Linux RFKILL support for RTL8187 + * + * Copyright (c) 2009 Herton Ronaldo Krzesinski + * + * Based on the RFKILL handling in the r8187 driver, which is: + * Copyright (c) Realtek Semiconductor Corp. All rights reserved. + * + * Thanks to Realtek for their support! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include "rtl8187.h" +#include "rfkill.h" + +static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv) +{ + u8 gpio; + + gpio = rtl818x_ioread8(priv, &priv->map->GPIO0); + rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~priv->rfkill_mask); + gpio = rtl818x_ioread8(priv, &priv->map->GPIO1); + + return gpio & priv->rfkill_mask; +} + +void rtl8187_rfkill_init(struct ieee80211_hw *hw) +{ + struct rtl8187_priv *priv = hw->priv; + + priv->rfkill_off = rtl8187_is_radio_enabled(priv); + printk(KERN_INFO "rtl8187: wireless switch is %s\n", + priv->rfkill_off ? "on" : "off"); + wiphy_rfkill_set_hw_state(hw->wiphy, !priv->rfkill_off); + wiphy_rfkill_start_polling(hw->wiphy); +} + +void rtl8187_rfkill_poll(struct ieee80211_hw *hw) +{ + bool enabled; + struct rtl8187_priv *priv = hw->priv; + + mutex_lock(&priv->conf_mutex); + enabled = rtl8187_is_radio_enabled(priv); + if (unlikely(enabled != priv->rfkill_off)) { + priv->rfkill_off = enabled; + printk(KERN_INFO "rtl8187: wireless radio switch turned %s\n", + enabled ? "on" : "off"); + wiphy_rfkill_set_hw_state(hw->wiphy, !enabled); + } + mutex_unlock(&priv->conf_mutex); +} + +void rtl8187_rfkill_exit(struct ieee80211_hw *hw) +{ + wiphy_rfkill_stop_polling(hw->wiphy); +} diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.h b/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.h new file mode 100644 index 000000000000..e12575e96d11 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rfkill.h @@ -0,0 +1,8 @@ +#ifndef RTL8187_RFKILL_H +#define RTL8187_RFKILL_H + +void rtl8187_rfkill_init(struct ieee80211_hw *hw); +void rtl8187_rfkill_poll(struct ieee80211_hw *hw); +void rtl8187_rfkill_exit(struct ieee80211_hw *hw); + +#endif /* RTL8187_RFKILL_H */ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.h new file mode 100644 index 000000000000..a6ad79f61bf9 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8187.h @@ -0,0 +1,288 @@ +/* + * Definitions for RTL8187 hardware + * + * Copyright 2007 Michael Wu + * Copyright 2007 Andrea Merello + * + * Based on the r8187 driver, which is: + * Copyright 2005 Andrea Merello , et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef RTL8187_H +#define RTL8187_H + +#include + +#include "rtl818x.h" +#include "leds.h" + +#define RTL8187_EEPROM_TXPWR_BASE 0x05 +#define RTL8187_EEPROM_MAC_ADDR 0x07 +#define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */ +#define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */ +#define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */ +#define RTL8187_EEPROM_SELECT_GPIO 0x3B + +#define RTL8187_REQT_READ 0xC0 +#define RTL8187_REQT_WRITE 0x40 +#define RTL8187_REQ_GET_REG 0x05 +#define RTL8187_REQ_SET_REG 0x05 + +#define RTL8187_MAX_RX 0x9C4 + +#define RFKILL_MASK_8187_89_97 0x2 +#define RFKILL_MASK_8198 0x4 + +#define RETRY_COUNT 7 + +struct rtl8187_rx_info { + struct urb *urb; + struct ieee80211_hw *dev; +}; + +struct rtl8187_rx_hdr { + __le32 flags; + u8 noise; + u8 signal; + u8 agc; + u8 reserved; + __le64 mac_time; +} __packed; + +struct rtl8187b_rx_hdr { + __le32 flags; + __le64 mac_time; + u8 sq; + u8 rssi; + u8 agc; + u8 flags2; + __le16 snr_long2end; + s8 pwdb_g12; + u8 fot; +} __packed; + +/* {rtl8187,rtl8187b}_tx_info is in skb */ + +struct rtl8187_tx_hdr { + __le32 flags; + __le16 rts_duration; + __le16 len; + __le32 retry; +} __packed; + +struct rtl8187b_tx_hdr { + __le32 flags; + __le16 rts_duration; + __le16 len; + __le32 unused_1; + __le16 unused_2; + __le16 tx_duration; + __le32 unused_3; + __le32 retry; + __le32 unused_4[2]; +} __packed; + +enum { + DEVICE_RTL8187, + DEVICE_RTL8187B +}; + +struct rtl8187_vif { + struct ieee80211_hw *dev; + + /* beaconing */ + struct delayed_work beacon_work; + bool enable_beacon; +}; + +struct rtl8187_priv { + /* common between rtl818x drivers */ + struct rtl818x_csr *map; + const struct rtl818x_rf_ops *rf; + struct ieee80211_vif *vif; + + /* The mutex protects the TX loopback state. + * Any attempt to set channels concurrently locks the device. + */ + struct mutex conf_mutex; + + /* rtl8187 specific */ + struct ieee80211_channel channels[14]; + struct ieee80211_rate rates[12]; + struct ieee80211_supported_band band; + struct usb_device *udev; + u32 rx_conf; + struct usb_anchor anchored; + struct delayed_work work; + struct ieee80211_hw *dev; +#ifdef CONFIG_RTL8187_LEDS + struct rtl8187_led led_radio; + struct rtl8187_led led_tx; + struct rtl8187_led led_rx; + struct delayed_work led_on; + struct delayed_work led_off; +#endif + u16 txpwr_base; + u8 asic_rev; + u8 is_rtl8187b; + enum { + RTL8187BvB, + RTL8187BvD, + RTL8187BvE + } hw_rev; + struct sk_buff_head rx_queue; + u8 signal; + u8 noise; + u8 slot_time; + u8 aifsn[4]; + u8 rfkill_mask; + struct { + union { + __le64 buf; + u8 dummy1[L1_CACHE_BYTES]; + } ____cacheline_aligned; + struct sk_buff_head queue; + } b_tx_status; /* This queue is used by both -b and non-b devices */ + struct mutex io_mutex; + union { + u8 bits8; + __le16 bits16; + __le32 bits32; + u8 dummy2[L1_CACHE_BYTES]; + } *io_dmabuf ____cacheline_aligned; + bool rfkill_off; + u16 seqno; +}; + +void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); + +static inline u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv, + u8 *addr, u8 idx) +{ + u8 val; + + mutex_lock(&priv->io_mutex); + usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), + RTL8187_REQ_GET_REG, RTL8187_REQT_READ, + (unsigned long)addr, idx & 0x03, + &priv->io_dmabuf->bits8, sizeof(val), HZ / 2); + + val = priv->io_dmabuf->bits8; + mutex_unlock(&priv->io_mutex); + + return val; +} + +static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr) +{ + return rtl818x_ioread8_idx(priv, addr, 0); +} + +static inline u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv, + __le16 *addr, u8 idx) +{ + __le16 val; + + mutex_lock(&priv->io_mutex); + usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), + RTL8187_REQ_GET_REG, RTL8187_REQT_READ, + (unsigned long)addr, idx & 0x03, + &priv->io_dmabuf->bits16, sizeof(val), HZ / 2); + + val = priv->io_dmabuf->bits16; + mutex_unlock(&priv->io_mutex); + + return le16_to_cpu(val); +} + +static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr) +{ + return rtl818x_ioread16_idx(priv, addr, 0); +} + +static inline u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv, + __le32 *addr, u8 idx) +{ + __le32 val; + + mutex_lock(&priv->io_mutex); + usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), + RTL8187_REQ_GET_REG, RTL8187_REQT_READ, + (unsigned long)addr, idx & 0x03, + &priv->io_dmabuf->bits32, sizeof(val), HZ / 2); + + val = priv->io_dmabuf->bits32; + mutex_unlock(&priv->io_mutex); + + return le32_to_cpu(val); +} + +static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr) +{ + return rtl818x_ioread32_idx(priv, addr, 0); +} + +static inline void rtl818x_iowrite8_idx(struct rtl8187_priv *priv, + u8 *addr, u8 val, u8 idx) +{ + mutex_lock(&priv->io_mutex); + + priv->io_dmabuf->bits8 = val; + usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), + RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, + (unsigned long)addr, idx & 0x03, + &priv->io_dmabuf->bits8, sizeof(val), HZ / 2); + + mutex_unlock(&priv->io_mutex); +} + +static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, u8 *addr, u8 val) +{ + rtl818x_iowrite8_idx(priv, addr, val, 0); +} + +static inline void rtl818x_iowrite16_idx(struct rtl8187_priv *priv, + __le16 *addr, u16 val, u8 idx) +{ + mutex_lock(&priv->io_mutex); + + priv->io_dmabuf->bits16 = cpu_to_le16(val); + usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), + RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, + (unsigned long)addr, idx & 0x03, + &priv->io_dmabuf->bits16, sizeof(val), HZ / 2); + + mutex_unlock(&priv->io_mutex); +} + +static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, __le16 *addr, + u16 val) +{ + rtl818x_iowrite16_idx(priv, addr, val, 0); +} + +static inline void rtl818x_iowrite32_idx(struct rtl8187_priv *priv, + __le32 *addr, u32 val, u8 idx) +{ + mutex_lock(&priv->io_mutex); + + priv->io_dmabuf->bits32 = cpu_to_le32(val); + usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), + RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, + (unsigned long)addr, idx & 0x03, + &priv->io_dmabuf->bits32, sizeof(val), HZ / 2); + + mutex_unlock(&priv->io_mutex); +} + +static inline void rtl818x_iowrite32(struct rtl8187_priv *priv, __le32 *addr, + u32 val) +{ + rtl818x_iowrite32_idx(priv, addr, val, 0); +} + +#endif /* RTL8187_H */ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c new file mode 100644 index 000000000000..5ecf18ed67b8 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c @@ -0,0 +1,961 @@ +/* + * Radio tuning for RTL8225 on RTL8187 + * + * Copyright 2007 Michael Wu + * Copyright 2007 Andrea Merello + * + * Based on the r8187 driver, which is: + * Copyright 2005 Andrea Merello , et al. + * + * Magic delays, register offsets, and phy value tables below are + * taken from the original r8187 driver sources. Thanks to Realtek + * for their support! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +#include "rtl8187.h" +#include "rtl8225.h" + +static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data) +{ + struct rtl8187_priv *priv = dev->priv; + u16 reg80, reg84, reg82; + u32 bangdata; + int i; + + bangdata = (data << 4) | (addr & 0xf); + + reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3; + reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7); + + reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7); + udelay(10); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); + udelay(10); + + for (i = 15; i >= 0; i--) { + u16 reg = reg80 | (bangdata & (1 << i)) >> i; + + if (i & 1) + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); + + if (!(i & 1)) + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); + } + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + udelay(10); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); +} + +static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data) +{ + struct rtl8187_priv *priv = dev->priv; + u16 reg80, reg82, reg84; + + reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput); + reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); + reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); + + reg80 &= ~(0x3 << 2); + reg84 &= ~0xF; + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007); + udelay(10); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + udelay(2); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); + udelay(10); + + mutex_lock(&priv->io_mutex); + + priv->io_dmabuf->bits16 = data; + usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), + RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, + addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data), + HZ / 2); + + mutex_unlock(&priv->io_mutex); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + udelay(10); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); +} + +static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data) +{ + struct rtl8187_priv *priv = dev->priv; + + if (priv->asic_rev) + rtl8225_write_8051(dev, addr, cpu_to_le16(data)); + else + rtl8225_write_bitbang(dev, addr, data); +} + +static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr) +{ + struct rtl8187_priv *priv = dev->priv; + u16 reg80, reg82, reg84, out; + int i; + + reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput); + reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); + reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); + + reg80 &= ~0xF; + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); + udelay(4); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); + udelay(5); + + for (i = 4; i >= 0; i--) { + u16 reg = reg80 | ((addr >> i) & 1); + + if (!(i & 1)) { + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); + udelay(1); + } + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg | (1 << 1)); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg | (1 << 1)); + udelay(2); + + if (i & 1) { + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); + udelay(1); + } + } + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 1)); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3)); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3)); + udelay(2); + + out = 0; + for (i = 11; i >= 0; i--) { + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3)); + udelay(1); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 1)); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 1)); + udelay(2); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 1)); + udelay(2); + + if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1)) + out |= 1 << i; + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3)); + udelay(2); + } + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, + reg80 | (1 << 3) | (1 << 2)); + udelay(2); + + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0); + + return out; +} + +static const u16 rtl8225bcd_rxgain[] = { + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, + 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, + 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, + 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, + 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, + 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, + 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, + 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, + 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, + 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, + 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, + 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb +}; + +static const u8 rtl8225_agc[] = { + 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, + 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, + 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, + 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, + 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, + 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, + 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, + 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, + 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, + 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, + 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, + 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 +}; + +static const u8 rtl8225_gain[] = { + 0x23, 0x88, 0x7c, 0xa5, /* -82dBm */ + 0x23, 0x88, 0x7c, 0xb5, /* -82dBm */ + 0x23, 0x88, 0x7c, 0xc5, /* -82dBm */ + 0x33, 0x80, 0x79, 0xc5, /* -78dBm */ + 0x43, 0x78, 0x76, 0xc5, /* -74dBm */ + 0x53, 0x60, 0x73, 0xc5, /* -70dBm */ + 0x63, 0x58, 0x70, 0xc5, /* -66dBm */ +}; + +static const u8 rtl8225_threshold[] = { + 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd +}; + +static const u8 rtl8225_tx_gain_cck_ofdm[] = { + 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e +}; + +static const u8 rtl8225_tx_power_cck[] = { + 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, + 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, + 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, + 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, + 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, + 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 +}; + +static const u8 rtl8225_tx_power_cck_ch14[] = { + 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 rtl8225_tx_power_ofdm[] = { + 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 +}; + +static const u32 rtl8225_chan[] = { + 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c, + 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72 +}; + +static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) +{ + struct rtl8187_priv *priv = dev->priv; + u8 cck_power, ofdm_power; + const u8 *tmp; + u32 reg; + int i; + + cck_power = priv->channels[channel - 1].hw_value & 0xF; + ofdm_power = priv->channels[channel - 1].hw_value >> 4; + + cck_power = min(cck_power, (u8)11); + if (ofdm_power > (u8)15) + ofdm_power = 25; + else + ofdm_power += 10; + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, + rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1); + + if (channel == 14) + tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8]; + else + tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8]; + + for (i = 0; i < 8; i++) + rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); + + msleep(1); // FIXME: optional? + + /* anaparam2 on */ + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, + RTL8187_RTL8225_ANAPARAM2_ON); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + rtl8225_write_phy_ofdm(dev, 2, 0x42); + rtl8225_write_phy_ofdm(dev, 6, 0x00); + rtl8225_write_phy_ofdm(dev, 8, 0x00); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, + rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1); + + tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6]; + + rtl8225_write_phy_ofdm(dev, 5, *tmp); + rtl8225_write_phy_ofdm(dev, 7, *tmp); + + msleep(1); +} + +static void rtl8225_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + int i; + + rtl8225_write(dev, 0x0, 0x067); + rtl8225_write(dev, 0x1, 0xFE0); + rtl8225_write(dev, 0x2, 0x44D); + rtl8225_write(dev, 0x3, 0x441); + rtl8225_write(dev, 0x4, 0x486); + rtl8225_write(dev, 0x5, 0xBC0); + rtl8225_write(dev, 0x6, 0xAE6); + rtl8225_write(dev, 0x7, 0x82A); + rtl8225_write(dev, 0x8, 0x01F); + rtl8225_write(dev, 0x9, 0x334); + rtl8225_write(dev, 0xA, 0xFD4); + rtl8225_write(dev, 0xB, 0x391); + rtl8225_write(dev, 0xC, 0x050); + rtl8225_write(dev, 0xD, 0x6DB); + rtl8225_write(dev, 0xE, 0x029); + rtl8225_write(dev, 0xF, 0x914); msleep(100); + + rtl8225_write(dev, 0x2, 0xC4D); msleep(200); + rtl8225_write(dev, 0x2, 0x44D); msleep(200); + + if (!(rtl8225_read(dev, 6) & (1 << 7))) { + rtl8225_write(dev, 0x02, 0x0c4d); + msleep(200); + rtl8225_write(dev, 0x02, 0x044d); + msleep(100); + if (!(rtl8225_read(dev, 6) & (1 << 7))) + wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n", + rtl8225_read(dev, 6)); + } + + rtl8225_write(dev, 0x0, 0x127); + + for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) { + rtl8225_write(dev, 0x1, i + 1); + rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]); + } + + rtl8225_write(dev, 0x0, 0x027); + rtl8225_write(dev, 0x0, 0x22F); + + for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { + rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); + rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); + } + + msleep(1); + + rtl8225_write_phy_ofdm(dev, 0x00, 0x01); + rtl8225_write_phy_ofdm(dev, 0x01, 0x02); + rtl8225_write_phy_ofdm(dev, 0x02, 0x42); + rtl8225_write_phy_ofdm(dev, 0x03, 0x00); + rtl8225_write_phy_ofdm(dev, 0x04, 0x00); + rtl8225_write_phy_ofdm(dev, 0x05, 0x00); + rtl8225_write_phy_ofdm(dev, 0x06, 0x40); + rtl8225_write_phy_ofdm(dev, 0x07, 0x00); + rtl8225_write_phy_ofdm(dev, 0x08, 0x40); + rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); + rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); + rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); + rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); + rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); + rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); + rtl8225_write_phy_ofdm(dev, 0x10, 0x84); + rtl8225_write_phy_ofdm(dev, 0x11, 0x06); + rtl8225_write_phy_ofdm(dev, 0x12, 0x20); + rtl8225_write_phy_ofdm(dev, 0x13, 0x20); + rtl8225_write_phy_ofdm(dev, 0x14, 0x00); + rtl8225_write_phy_ofdm(dev, 0x15, 0x40); + rtl8225_write_phy_ofdm(dev, 0x16, 0x00); + rtl8225_write_phy_ofdm(dev, 0x17, 0x40); + rtl8225_write_phy_ofdm(dev, 0x18, 0xef); + rtl8225_write_phy_ofdm(dev, 0x19, 0x19); + rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); + rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); + rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); + rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); + rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); + rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); + rtl8225_write_phy_ofdm(dev, 0x21, 0x27); + rtl8225_write_phy_ofdm(dev, 0x22, 0x16); + rtl8225_write_phy_ofdm(dev, 0x24, 0x46); + rtl8225_write_phy_ofdm(dev, 0x25, 0x20); + rtl8225_write_phy_ofdm(dev, 0x26, 0x90); + rtl8225_write_phy_ofdm(dev, 0x27, 0x88); + + rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]); + rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]); + rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]); + rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]); + + rtl8225_write_phy_cck(dev, 0x00, 0x98); + rtl8225_write_phy_cck(dev, 0x03, 0x20); + rtl8225_write_phy_cck(dev, 0x04, 0x7e); + rtl8225_write_phy_cck(dev, 0x05, 0x12); + rtl8225_write_phy_cck(dev, 0x06, 0xfc); + rtl8225_write_phy_cck(dev, 0x07, 0x78); + rtl8225_write_phy_cck(dev, 0x08, 0x2e); + rtl8225_write_phy_cck(dev, 0x10, 0x9b); + rtl8225_write_phy_cck(dev, 0x11, 0x88); + rtl8225_write_phy_cck(dev, 0x12, 0x47); + rtl8225_write_phy_cck(dev, 0x13, 0xd0); + rtl8225_write_phy_cck(dev, 0x19, 0x00); + rtl8225_write_phy_cck(dev, 0x1a, 0xa0); + rtl8225_write_phy_cck(dev, 0x1b, 0x08); + rtl8225_write_phy_cck(dev, 0x40, 0x86); + rtl8225_write_phy_cck(dev, 0x41, 0x8d); + rtl8225_write_phy_cck(dev, 0x42, 0x15); + rtl8225_write_phy_cck(dev, 0x43, 0x18); + rtl8225_write_phy_cck(dev, 0x44, 0x1f); + rtl8225_write_phy_cck(dev, 0x45, 0x1e); + rtl8225_write_phy_cck(dev, 0x46, 0x1a); + rtl8225_write_phy_cck(dev, 0x47, 0x15); + rtl8225_write_phy_cck(dev, 0x48, 0x10); + rtl8225_write_phy_cck(dev, 0x49, 0x0a); + rtl8225_write_phy_cck(dev, 0x4a, 0x05); + rtl8225_write_phy_cck(dev, 0x4b, 0x02); + rtl8225_write_phy_cck(dev, 0x4c, 0x05); + + rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); + + rtl8225_rf_set_tx_power(dev, 1); + + /* RX antenna default to A */ + rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */ + rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */ + + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ + msleep(1); + rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002); + + /* set sensitivity */ + rtl8225_write(dev, 0x0c, 0x50); + rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]); + rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]); + rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]); + rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]); + rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]); +} + +static const u8 rtl8225z2_agc[] = { + 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f, + 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37, + 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f, + 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07, + 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, + 0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 +}; +static const u8 rtl8225z2_ofdm[] = { + 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, + 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26, + 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3, + 0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f, + 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00, + 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e, + 0x6d, 0x3c, 0xfb, 0x07 +}; + +static const u8 rtl8225z2_tx_power_cck_ch14[] = { + 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 rtl8225z2_tx_power_cck[] = { + 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04, + 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03, + 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03, + 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 +}; + +static const u8 rtl8225z2_tx_power_ofdm[] = { + 0x42, 0x00, 0x40, 0x00, 0x40 +}; + +static const u8 rtl8225z2_tx_gain_cck_ofdm[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, + 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23 +}; + +static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) +{ + struct rtl8187_priv *priv = dev->priv; + u8 cck_power, ofdm_power; + const u8 *tmp; + u32 reg; + int i; + + cck_power = priv->channels[channel - 1].hw_value & 0xF; + ofdm_power = priv->channels[channel - 1].hw_value >> 4; + + cck_power = min(cck_power, (u8)15); + cck_power += priv->txpwr_base & 0xF; + cck_power = min(cck_power, (u8)35); + + if (ofdm_power > (u8)15) + ofdm_power = 25; + else + ofdm_power += 10; + ofdm_power += priv->txpwr_base >> 4; + ofdm_power = min(ofdm_power, (u8)35); + + if (channel == 14) + tmp = rtl8225z2_tx_power_cck_ch14; + else + tmp = rtl8225z2_tx_power_cck; + + for (i = 0; i < 8; i++) + rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, + rtl8225z2_tx_gain_cck_ofdm[cck_power]); + msleep(1); + + /* anaparam2 on */ + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, + RTL8187_RTL8225_ANAPARAM2_ON); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + + rtl8225_write_phy_ofdm(dev, 2, 0x42); + rtl8225_write_phy_ofdm(dev, 5, 0x00); + rtl8225_write_phy_ofdm(dev, 6, 0x40); + rtl8225_write_phy_ofdm(dev, 7, 0x00); + rtl8225_write_phy_ofdm(dev, 8, 0x40); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, + rtl8225z2_tx_gain_cck_ofdm[ofdm_power]); + msleep(1); +} + +static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel) +{ + struct rtl8187_priv *priv = dev->priv; + u8 cck_power, ofdm_power; + const u8 *tmp; + int i; + + cck_power = priv->channels[channel - 1].hw_value & 0xF; + ofdm_power = priv->channels[channel - 1].hw_value >> 4; + + if (cck_power > 15) + cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22; + else + cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7; + cck_power += priv->txpwr_base & 0xF; + cck_power = min(cck_power, (u8)35); + + if (ofdm_power > 15) + ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25; + else + ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10; + ofdm_power += (priv->txpwr_base >> 4) & 0xF; + ofdm_power = min(ofdm_power, (u8)35); + + if (channel == 14) + tmp = rtl8225z2_tx_power_cck_ch14; + else + tmp = rtl8225z2_tx_power_cck; + + if (priv->hw_rev == RTL8187BvB) { + if (cck_power <= 6) + ; /* do nothing */ + else if (cck_power <= 11) + tmp += 8; + else + tmp += 16; + } else { + if (cck_power <= 5) + ; /* do nothing */ + else if (cck_power <= 11) + tmp += 8; + else if (cck_power <= 17) + tmp += 16; + else + tmp += 24; + } + + for (i = 0; i < 8; i++) + rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, + rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1); + msleep(1); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, + rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1); + if (priv->hw_rev == RTL8187BvB) { + if (ofdm_power <= 11) { + rtl8225_write_phy_ofdm(dev, 0x87, 0x60); + rtl8225_write_phy_ofdm(dev, 0x89, 0x60); + } else { + rtl8225_write_phy_ofdm(dev, 0x87, 0x5c); + rtl8225_write_phy_ofdm(dev, 0x89, 0x5c); + } + } else { + if (ofdm_power <= 11) { + rtl8225_write_phy_ofdm(dev, 0x87, 0x5c); + rtl8225_write_phy_ofdm(dev, 0x89, 0x5c); + } else if (ofdm_power <= 17) { + rtl8225_write_phy_ofdm(dev, 0x87, 0x54); + rtl8225_write_phy_ofdm(dev, 0x89, 0x54); + } else { + rtl8225_write_phy_ofdm(dev, 0x87, 0x50); + rtl8225_write_phy_ofdm(dev, 0x89, 0x50); + } + } + msleep(1); +} + +static const u16 rtl8225z2_rxgain[] = { + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, + 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, + 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, + 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, + 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, + 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, + 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, + 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, + 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, + 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, + 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, + 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb +}; + +static const u8 rtl8225z2_gain_bg[] = { + 0x23, 0x15, 0xa5, /* -82-1dBm */ + 0x23, 0x15, 0xb5, /* -82-2dBm */ + 0x23, 0x15, 0xc5, /* -82-3dBm */ + 0x33, 0x15, 0xc5, /* -78dBm */ + 0x43, 0x15, 0xc5, /* -74dBm */ + 0x53, 0x15, 0xc5, /* -70dBm */ + 0x63, 0x15, 0xc5 /* -66dBm */ +}; + +static void rtl8225z2_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + int i; + + rtl8225_write(dev, 0x0, 0x2BF); + rtl8225_write(dev, 0x1, 0xEE0); + rtl8225_write(dev, 0x2, 0x44D); + rtl8225_write(dev, 0x3, 0x441); + rtl8225_write(dev, 0x4, 0x8C3); + rtl8225_write(dev, 0x5, 0xC72); + rtl8225_write(dev, 0x6, 0x0E6); + rtl8225_write(dev, 0x7, 0x82A); + rtl8225_write(dev, 0x8, 0x03F); + rtl8225_write(dev, 0x9, 0x335); + rtl8225_write(dev, 0xa, 0x9D4); + rtl8225_write(dev, 0xb, 0x7BB); + rtl8225_write(dev, 0xc, 0x850); + rtl8225_write(dev, 0xd, 0xCDF); + rtl8225_write(dev, 0xe, 0x02B); + rtl8225_write(dev, 0xf, 0x114); + msleep(100); + + rtl8225_write(dev, 0x0, 0x1B7); + + for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { + rtl8225_write(dev, 0x1, i + 1); + rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); + } + + rtl8225_write(dev, 0x3, 0x080); + rtl8225_write(dev, 0x5, 0x004); + rtl8225_write(dev, 0x0, 0x0B7); + rtl8225_write(dev, 0x2, 0xc4D); + + msleep(200); + rtl8225_write(dev, 0x2, 0x44D); + msleep(100); + + if (!(rtl8225_read(dev, 6) & (1 << 7))) { + rtl8225_write(dev, 0x02, 0x0C4D); + msleep(200); + rtl8225_write(dev, 0x02, 0x044D); + msleep(100); + if (!(rtl8225_read(dev, 6) & (1 << 7))) + wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n", + rtl8225_read(dev, 6)); + } + + msleep(200); + + rtl8225_write(dev, 0x0, 0x2BF); + + for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { + rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); + rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); + } + + msleep(1); + + rtl8225_write_phy_ofdm(dev, 0x00, 0x01); + rtl8225_write_phy_ofdm(dev, 0x01, 0x02); + rtl8225_write_phy_ofdm(dev, 0x02, 0x42); + rtl8225_write_phy_ofdm(dev, 0x03, 0x00); + rtl8225_write_phy_ofdm(dev, 0x04, 0x00); + rtl8225_write_phy_ofdm(dev, 0x05, 0x00); + rtl8225_write_phy_ofdm(dev, 0x06, 0x40); + rtl8225_write_phy_ofdm(dev, 0x07, 0x00); + rtl8225_write_phy_ofdm(dev, 0x08, 0x40); + rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); + rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); + rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); + rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); + rtl8225_write_phy_ofdm(dev, 0x0d, 0x43); + rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); + rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); + rtl8225_write_phy_ofdm(dev, 0x10, 0x84); + rtl8225_write_phy_ofdm(dev, 0x11, 0x07); + rtl8225_write_phy_ofdm(dev, 0x12, 0x20); + rtl8225_write_phy_ofdm(dev, 0x13, 0x20); + rtl8225_write_phy_ofdm(dev, 0x14, 0x00); + rtl8225_write_phy_ofdm(dev, 0x15, 0x40); + rtl8225_write_phy_ofdm(dev, 0x16, 0x00); + rtl8225_write_phy_ofdm(dev, 0x17, 0x40); + rtl8225_write_phy_ofdm(dev, 0x18, 0xef); + rtl8225_write_phy_ofdm(dev, 0x19, 0x19); + rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); + rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); + rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); + rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); + rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); + rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); + rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); + rtl8225_write_phy_ofdm(dev, 0x21, 0x17); + rtl8225_write_phy_ofdm(dev, 0x22, 0x16); + rtl8225_write_phy_ofdm(dev, 0x23, 0x80); + rtl8225_write_phy_ofdm(dev, 0x24, 0x46); + rtl8225_write_phy_ofdm(dev, 0x25, 0x00); + rtl8225_write_phy_ofdm(dev, 0x26, 0x90); + rtl8225_write_phy_ofdm(dev, 0x27, 0x88); + + rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]); + rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]); + rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]); + rtl8225_write_phy_ofdm(dev, 0x21, 0x37); + + rtl8225_write_phy_cck(dev, 0x00, 0x98); + rtl8225_write_phy_cck(dev, 0x03, 0x20); + rtl8225_write_phy_cck(dev, 0x04, 0x7e); + rtl8225_write_phy_cck(dev, 0x05, 0x12); + rtl8225_write_phy_cck(dev, 0x06, 0xfc); + rtl8225_write_phy_cck(dev, 0x07, 0x78); + rtl8225_write_phy_cck(dev, 0x08, 0x2e); + rtl8225_write_phy_cck(dev, 0x10, 0x9b); + rtl8225_write_phy_cck(dev, 0x11, 0x88); + rtl8225_write_phy_cck(dev, 0x12, 0x47); + rtl8225_write_phy_cck(dev, 0x13, 0xd0); + rtl8225_write_phy_cck(dev, 0x19, 0x00); + rtl8225_write_phy_cck(dev, 0x1a, 0xa0); + rtl8225_write_phy_cck(dev, 0x1b, 0x08); + rtl8225_write_phy_cck(dev, 0x40, 0x86); + rtl8225_write_phy_cck(dev, 0x41, 0x8d); + rtl8225_write_phy_cck(dev, 0x42, 0x15); + rtl8225_write_phy_cck(dev, 0x43, 0x18); + rtl8225_write_phy_cck(dev, 0x44, 0x36); + rtl8225_write_phy_cck(dev, 0x45, 0x35); + rtl8225_write_phy_cck(dev, 0x46, 0x2e); + rtl8225_write_phy_cck(dev, 0x47, 0x25); + rtl8225_write_phy_cck(dev, 0x48, 0x1c); + rtl8225_write_phy_cck(dev, 0x49, 0x12); + rtl8225_write_phy_cck(dev, 0x4a, 0x09); + rtl8225_write_phy_cck(dev, 0x4b, 0x04); + rtl8225_write_phy_cck(dev, 0x4c, 0x05); + + rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1); + + rtl8225z2_rf_set_tx_power(dev, 1); + + /* RX antenna default to A */ + rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */ + rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */ + + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ + msleep(1); + rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002); +} + +static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + int i; + + rtl8225_write(dev, 0x0, 0x0B7); + rtl8225_write(dev, 0x1, 0xEE0); + rtl8225_write(dev, 0x2, 0x44D); + rtl8225_write(dev, 0x3, 0x441); + rtl8225_write(dev, 0x4, 0x8C3); + rtl8225_write(dev, 0x5, 0xC72); + rtl8225_write(dev, 0x6, 0x0E6); + rtl8225_write(dev, 0x7, 0x82A); + rtl8225_write(dev, 0x8, 0x03F); + rtl8225_write(dev, 0x9, 0x335); + rtl8225_write(dev, 0xa, 0x9D4); + rtl8225_write(dev, 0xb, 0x7BB); + rtl8225_write(dev, 0xc, 0x850); + rtl8225_write(dev, 0xd, 0xCDF); + rtl8225_write(dev, 0xe, 0x02B); + rtl8225_write(dev, 0xf, 0x114); + + rtl8225_write(dev, 0x0, 0x1B7); + + for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { + rtl8225_write(dev, 0x1, i + 1); + rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); + } + + rtl8225_write(dev, 0x3, 0x080); + rtl8225_write(dev, 0x5, 0x004); + rtl8225_write(dev, 0x0, 0x0B7); + + rtl8225_write(dev, 0x2, 0xC4D); + + rtl8225_write(dev, 0x2, 0x44D); + rtl8225_write(dev, 0x0, 0x2BF); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03); + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07); + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); + + rtl8225_write_phy_ofdm(dev, 0x80, 0x12); + for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) { + rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]); + rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i); + rtl8225_write_phy_ofdm(dev, 0xE, 0); + } + rtl8225_write_phy_ofdm(dev, 0x80, 0x10); + + for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++) + rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]); + + rtl8225_write_phy_ofdm(dev, 0x97, 0x46); + rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); + rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); + rtl8225_write_phy_cck(dev, 0xc1, 0x88); +} + +static void rtl8225_rf_stop(struct ieee80211_hw *dev) +{ + rtl8225_write(dev, 0x4, 0x1f); +} + +static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, + struct ieee80211_conf *conf) +{ + struct rtl8187_priv *priv = dev->priv; + int chan = + ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); + + if (priv->rf->init == rtl8225_rf_init) + rtl8225_rf_set_tx_power(dev, chan); + else if (priv->rf->init == rtl8225z2_rf_init) + rtl8225z2_rf_set_tx_power(dev, chan); + else + rtl8225z2_b_rf_set_tx_power(dev, chan); + + rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); + msleep(10); +} + +static const struct rtl818x_rf_ops rtl8225_ops = { + .name = "rtl8225", + .init = rtl8225_rf_init, + .stop = rtl8225_rf_stop, + .set_chan = rtl8225_rf_set_channel +}; + +static const struct rtl818x_rf_ops rtl8225z2_ops = { + .name = "rtl8225z2", + .init = rtl8225z2_rf_init, + .stop = rtl8225_rf_stop, + .set_chan = rtl8225_rf_set_channel +}; + +static const struct rtl818x_rf_ops rtl8225z2_b_ops = { + .name = "rtl8225z2", + .init = rtl8225z2_b_rf_init, + .stop = rtl8225_rf_stop, + .set_chan = rtl8225_rf_set_channel +}; + +const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev) +{ + u16 reg8, reg9; + struct rtl8187_priv *priv = dev->priv; + + if (!priv->is_rtl8187b) { + rtl8225_write(dev, 0, 0x1B7); + + reg8 = rtl8225_read(dev, 8); + reg9 = rtl8225_read(dev, 9); + + rtl8225_write(dev, 0, 0x0B7); + + if (reg8 != 0x588 || reg9 != 0x700) + return &rtl8225_ops; + + return &rtl8225z2_ops; + } else + return &rtl8225z2_b_ops; +} diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.h b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.h new file mode 100644 index 000000000000..141afb09a5b4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.h @@ -0,0 +1,44 @@ +/* + * Radio tuning definitions for RTL8225 on RTL8187 + * + * Copyright 2007 Michael Wu + * Copyright 2007 Andrea Merello + * + * Based on the r8187 driver, which is: + * Copyright 2005 Andrea Merello , et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef RTL8187_RTL8225_H +#define RTL8187_RTL8225_H + +#define RTL8187_RTL8225_ANAPARAM_ON 0xa0000a59 +#define RTL8187_RTL8225_ANAPARAM2_ON 0x860c7312 +#define RTL8187_RTL8225_ANAPARAM_OFF 0xa00beb59 +#define RTL8187_RTL8225_ANAPARAM2_OFF 0x840dec11 + +#define RTL8187B_RTL8225_ANAPARAM_ON 0x45090658 +#define RTL8187B_RTL8225_ANAPARAM2_ON 0x727f3f52 +#define RTL8187B_RTL8225_ANAPARAM3_ON 0x00 +#define RTL8187B_RTL8225_ANAPARAM_OFF 0x55480658 +#define RTL8187B_RTL8225_ANAPARAM2_OFF 0x72003f50 +#define RTL8187B_RTL8225_ANAPARAM3_OFF 0x00 + +const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *); + +static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev, + u8 addr, u32 data) +{ + rtl8187_write_phy(dev, addr, data); +} + +static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev, + u8 addr, u32 data) +{ + rtl8187_write_phy(dev, addr, data | 0x10000); +} + +#endif /* RTL8187_RTL8225_H */ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl818x.h b/drivers/net/wireless/realtek/rtl818x/rtl818x.h new file mode 100644 index 000000000000..7abef95d278b --- /dev/null +++ b/drivers/net/wireless/realtek/rtl818x/rtl818x.h @@ -0,0 +1,405 @@ +/* + * Definitions for RTL818x hardware + * + * Copyright 2007 Michael Wu + * Copyright 2007 Andrea Merello + * + * Based on the r8187 driver, which is: + * Copyright 2005 Andrea Merello , et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef RTL818X_H +#define RTL818X_H + +struct rtl818x_csr { + + u8 MAC[6]; + u8 reserved_0[2]; + + union { + __le32 MAR[2]; /* 0x8 */ + + struct{ /* rtl8187se */ + u8 rf_sw_config; /* 0x8 */ + u8 reserved_01[3]; + __le32 TMGDA; /* 0xc */ + } __packed; + } __packed; + + union { /* 0x10 */ + struct { + u8 RX_FIFO_COUNT; + u8 reserved_1; + u8 TX_FIFO_COUNT; + u8 BQREQ; + } __packed; + + __le32 TBKDA; /* for 8187se */ + } __packed; + + __le32 TBEDA; /* 0x14 - for rtl8187se */ + + __le32 TSFT[2]; + + union { /* 0x20 */ + __le32 TLPDA; + __le32 TVIDA; /* for 8187se */ + } __packed; + + union { /* 0x24 */ + __le32 TNPDA; + __le32 TVODA; /* for 8187se */ + } __packed; + + /* hi pri ring for all cards */ + __le32 THPDA; /* 0x28 */ + + union { /* 0x2c */ + struct { + u8 reserved_2a; + u8 EIFS_8187SE; + } __packed; + + __le16 BRSR; + } __packed; + + u8 BSSID[6]; /* 0x2e */ + + union { /* 0x34 */ + struct { + u8 RESP_RATE; + u8 EIFS; + } __packed; + __le16 BRSR_8187SE; + } __packed; + + u8 reserved_3[1]; /* 0x36 */ + u8 CMD; /* 0x37 */ +#define RTL818X_CMD_TX_ENABLE (1 << 2) +#define RTL818X_CMD_RX_ENABLE (1 << 3) +#define RTL818X_CMD_RESET (1 << 4) + u8 reserved_4[4]; /* 0x38 */ + union { + struct { + __le16 INT_MASK; + __le16 INT_STATUS; + } __packed; + + __le32 INT_STATUS_SE; /* 0x3c */ + } __packed; +/* status bits for rtl8187 and rtl8180/8185 */ +#define RTL818X_INT_RX_OK (1 << 0) +#define RTL818X_INT_RX_ERR (1 << 1) +#define RTL818X_INT_TXL_OK (1 << 2) +#define RTL818X_INT_TXL_ERR (1 << 3) +#define RTL818X_INT_RX_DU (1 << 4) +#define RTL818X_INT_RX_FO (1 << 5) +#define RTL818X_INT_TXN_OK (1 << 6) +#define RTL818X_INT_TXN_ERR (1 << 7) +#define RTL818X_INT_TXH_OK (1 << 8) +#define RTL818X_INT_TXH_ERR (1 << 9) +#define RTL818X_INT_TXB_OK (1 << 10) +#define RTL818X_INT_TXB_ERR (1 << 11) +#define RTL818X_INT_ATIM (1 << 12) +#define RTL818X_INT_BEACON (1 << 13) +#define RTL818X_INT_TIME_OUT (1 << 14) +#define RTL818X_INT_TX_FO (1 << 15) +/* status bits for rtl8187se */ +#define RTL818X_INT_SE_TIMER3 (1 << 0) +#define RTL818X_INT_SE_TIMER2 (1 << 1) +#define RTL818X_INT_SE_RQ0SOR (1 << 2) +#define RTL818X_INT_SE_TXBED_OK (1 << 3) +#define RTL818X_INT_SE_TXBED_ERR (1 << 4) +#define RTL818X_INT_SE_TXBE_OK (1 << 5) +#define RTL818X_INT_SE_TXBE_ERR (1 << 6) +#define RTL818X_INT_SE_RX_OK (1 << 7) +#define RTL818X_INT_SE_RX_ERR (1 << 8) +#define RTL818X_INT_SE_TXL_OK (1 << 9) +#define RTL818X_INT_SE_TXL_ERR (1 << 10) +#define RTL818X_INT_SE_RX_DU (1 << 11) +#define RTL818X_INT_SE_RX_FIFO (1 << 12) +#define RTL818X_INT_SE_TXN_OK (1 << 13) +#define RTL818X_INT_SE_TXN_ERR (1 << 14) +#define RTL818X_INT_SE_TXH_OK (1 << 15) +#define RTL818X_INT_SE_TXH_ERR (1 << 16) +#define RTL818X_INT_SE_TXB_OK (1 << 17) +#define RTL818X_INT_SE_TXB_ERR (1 << 18) +#define RTL818X_INT_SE_ATIM_TO (1 << 19) +#define RTL818X_INT_SE_BK_TO (1 << 20) +#define RTL818X_INT_SE_TIMER1 (1 << 21) +#define RTL818X_INT_SE_TX_FIFO (1 << 22) +#define RTL818X_INT_SE_WAKEUP (1 << 23) +#define RTL818X_INT_SE_BK_DMA (1 << 24) +#define RTL818X_INT_SE_TMGD_OK (1 << 30) + __le32 TX_CONF; /* 0x40 */ +#define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17) +#define RTL818X_TX_CONF_LOOPBACK_CONT (3 << 17) +#define RTL818X_TX_CONF_NO_ICV (1 << 19) +#define RTL818X_TX_CONF_DISCW (1 << 20) +#define RTL818X_TX_CONF_SAT_HWPLCP (1 << 24) +#define RTL818X_TX_CONF_R8180_ABCD (2 << 25) +#define RTL818X_TX_CONF_R8180_F (3 << 25) +#define RTL818X_TX_CONF_R8185_ABC (4 << 25) +#define RTL818X_TX_CONF_R8185_D (5 << 25) +#define RTL818X_TX_CONF_R8187vD (5 << 25) +#define RTL818X_TX_CONF_R8187vD_B (6 << 25) +#define RTL818X_TX_CONF_RTL8187SE (6 << 25) +#define RTL818X_TX_CONF_HWVER_MASK (7 << 25) +#define RTL818X_TX_CONF_DISREQQSIZE (1 << 28) +#define RTL818X_TX_CONF_PROBE_DTS (1 << 29) +#define RTL818X_TX_CONF_HW_SEQNUM (1 << 30) +#define RTL818X_TX_CONF_CW_MIN (1 << 31) + __le32 RX_CONF; +#define RTL818X_RX_CONF_MONITOR (1 << 0) +#define RTL818X_RX_CONF_NICMAC (1 << 1) +#define RTL818X_RX_CONF_MULTICAST (1 << 2) +#define RTL818X_RX_CONF_BROADCAST (1 << 3) +#define RTL818X_RX_CONF_FCS (1 << 5) +#define RTL818X_RX_CONF_DATA (1 << 18) +#define RTL818X_RX_CONF_CTRL (1 << 19) +#define RTL818X_RX_CONF_MGMT (1 << 20) +#define RTL818X_RX_CONF_ADDR3 (1 << 21) +#define RTL818X_RX_CONF_PM (1 << 22) +#define RTL818X_RX_CONF_BSSID (1 << 23) +#define RTL818X_RX_CONF_RX_AUTORESETPHY (1 << 28) +#define RTL818X_RX_CONF_CSDM1 (1 << 29) +#define RTL818X_RX_CONF_CSDM2 (1 << 30) +#define RTL818X_RX_CONF_ONLYERLPKT (1 << 31) + __le32 INT_TIMEOUT; + __le32 TBDA; + u8 EEPROM_CMD; +#define RTL818X_EEPROM_CMD_READ (1 << 0) +#define RTL818X_EEPROM_CMD_WRITE (1 << 1) +#define RTL818X_EEPROM_CMD_CK (1 << 2) +#define RTL818X_EEPROM_CMD_CS (1 << 3) +#define RTL818X_EEPROM_CMD_NORMAL (0 << 6) +#define RTL818X_EEPROM_CMD_LOAD (1 << 6) +#define RTL818X_EEPROM_CMD_PROGRAM (2 << 6) +#define RTL818X_EEPROM_CMD_CONFIG (3 << 6) + u8 CONFIG0; + u8 CONFIG1; + u8 CONFIG2; +#define RTL818X_CONFIG2_ANTENNA_DIV (1 << 6) + __le32 ANAPARAM; + u8 MSR; +#define RTL818X_MSR_NO_LINK (0 << 2) +#define RTL818X_MSR_ADHOC (1 << 2) +#define RTL818X_MSR_INFRA (2 << 2) +#define RTL818X_MSR_MASTER (3 << 2) +#define RTL818X_MSR_ENEDCA (4 << 2) + u8 CONFIG3; +#define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6) +#define RTL818X_CONFIG3_GNT_SELECT (1 << 7) + u8 CONFIG4; +#define RTL818X_CONFIG4_POWEROFF (1 << 6) +#define RTL818X_CONFIG4_VCOOFF (1 << 7) + u8 TESTR; + u8 reserved_9[2]; + u8 PGSELECT; + u8 SECURITY; + __le32 ANAPARAM2; + u8 reserved_10[8]; + __le32 IMR; /* 0x6c - Interrupt mask reg for 8187se */ +#define IMR_TMGDOK ((1 << 30)) +#define IMR_DOT11HINT ((1 << 25)) /* 802.11h Measurement Interrupt */ +#define IMR_BCNDMAINT ((1 << 24)) /* Beacon DMA Interrupt */ +#define IMR_WAKEINT ((1 << 23)) /* Wake Up Interrupt */ +#define IMR_TXFOVW ((1 << 22)) /* Tx FIFO Overflow */ +#define IMR_TIMEOUT1 ((1 << 21)) /* Time Out Interrupt 1 */ +#define IMR_BCNINT ((1 << 20)) /* Beacon Time out */ +#define IMR_ATIMINT ((1 << 19)) /* ATIM Time Out */ +#define IMR_TBDER ((1 << 18)) /* Tx Beacon Descriptor Error */ +#define IMR_TBDOK ((1 << 17)) /* Tx Beacon Descriptor OK */ +#define IMR_THPDER ((1 << 16)) /* Tx High Priority Descriptor Error */ +#define IMR_THPDOK ((1 << 15)) /* Tx High Priority Descriptor OK */ +#define IMR_TVODER ((1 << 14)) /* Tx AC_VO Descriptor Error Int */ +#define IMR_TVODOK ((1 << 13)) /* Tx AC_VO Descriptor OK Interrupt */ +#define IMR_FOVW ((1 << 12)) /* Rx FIFO Overflow Interrupt */ +#define IMR_RDU ((1 << 11)) /* Rx Descriptor Unavailable */ +#define IMR_TVIDER ((1 << 10)) /* Tx AC_VI Descriptor Error */ +#define IMR_TVIDOK ((1 << 9)) /* Tx AC_VI Descriptor OK Interrupt */ +#define IMR_RER ((1 << 8)) /* Rx Error Interrupt */ +#define IMR_ROK ((1 << 7)) /* Receive OK Interrupt */ +#define IMR_TBEDER ((1 << 6)) /* Tx AC_BE Descriptor Error */ +#define IMR_TBEDOK ((1 << 5)) /* Tx AC_BE Descriptor OK */ +#define IMR_TBKDER ((1 << 4)) /* Tx AC_BK Descriptor Error */ +#define IMR_TBKDOK ((1 << 3)) /* Tx AC_BK Descriptor OK */ +#define IMR_RQOSOK ((1 << 2)) /* Rx QoS OK Interrupt */ +#define IMR_TIMEOUT2 ((1 << 1)) /* Time Out Interrupt 2 */ +#define IMR_TIMEOUT3 ((1 << 0)) /* Time Out Interrupt 3 */ + __le16 BEACON_INTERVAL; /* 0x70 */ + __le16 ATIM_WND; /* 0x72 */ + __le16 BEACON_INTERVAL_TIME; /* 0x74 */ + __le16 ATIMTR_INTERVAL; /* 0x76 */ + u8 PHY_DELAY; /* 0x78 */ + u8 CARRIER_SENSE_COUNTER; /* 0x79 */ + u8 reserved_11[2]; /* 0x7a */ + u8 PHY[4]; /* 0x7c */ + __le16 RFPinsOutput; /* 0x80 */ + __le16 RFPinsEnable; /* 0x82 */ + __le16 RFPinsSelect; /* 0x84 */ + __le16 RFPinsInput; /* 0x86 */ + __le32 RF_PARA; /* 0x88 */ + __le32 RF_TIMING; /* 0x8c */ + u8 GP_ENABLE; /* 0x90 */ + u8 GPIO0; /* 0x91 */ + u8 GPIO1; /* 0x92 */ + u8 TPPOLL_STOP; /* 0x93 - rtl8187se only */ +#define RTL818x_TPPOLL_STOP_BQ (1 << 7) +#define RTL818x_TPPOLL_STOP_VI (1 << 4) +#define RTL818x_TPPOLL_STOP_VO (1 << 5) +#define RTL818x_TPPOLL_STOP_BE (1 << 3) +#define RTL818x_TPPOLL_STOP_BK (1 << 2) +#define RTL818x_TPPOLL_STOP_MG (1 << 1) +#define RTL818x_TPPOLL_STOP_HI (1 << 6) + + __le32 HSSI_PARA; /* 0x94 */ + u8 reserved_13[4]; /* 0x98 */ + u8 TX_AGC_CTL; /* 0x9c */ +#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN (1 << 0) +#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL (1 << 1) +#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT (1 << 2) + u8 TX_GAIN_CCK; + u8 TX_GAIN_OFDM; + u8 TX_ANTENNA; + u8 reserved_14[16]; + u8 WPA_CONF; + u8 reserved_15[3]; + u8 SIFS; + u8 DIFS; + u8 SLOT; + u8 reserved_16[5]; + u8 CW_CONF; +#define RTL818X_CW_CONF_PERPACKET_CW (1 << 0) +#define RTL818X_CW_CONF_PERPACKET_RETRY (1 << 1) + u8 CW_VAL; + u8 RATE_FALLBACK; +#define RTL818X_RATE_FALLBACK_ENABLE (1 << 7) + u8 ACM_CONTROL; + u8 reserved_17[24]; + u8 CONFIG5; + u8 TX_DMA_POLLING; + u8 PHY_PR; + u8 reserved_18; + __le16 CWR; + u8 RETRY_CTR; + u8 reserved_19[3]; + __le16 INT_MIG; +/* RTL818X_R8187B_*: magic numbers from ioregisters */ +#define RTL818X_R8187B_B 0 +#define RTL818X_R8187B_D 1 +#define RTL818X_R8187B_E 2 + __le32 RDSAR; + __le16 TID_AC_MAP; + u8 reserved_20[4]; + union { + __le16 ANAPARAM3; /* 0xee */ + u8 ANAPARAM3A; /* for rtl8187 */ + }; + +#define AC_PARAM_TXOP_LIMIT_SHIFT 16 +#define AC_PARAM_ECW_MAX_SHIFT 12 +#define AC_PARAM_ECW_MIN_SHIFT 8 +#define AC_PARAM_AIFS_SHIFT 0 + + __le32 AC_VO_PARAM; /* 0xf0 */ + + union { /* 0xf4 */ + __le32 AC_VI_PARAM; + __le16 FEMR; + } __packed; + + union{ /* 0xf8 */ + __le32 AC_BE_PARAM; /* rtl8187se */ + struct{ + u8 reserved_21[2]; + __le16 TALLY_CNT; /* 0xfa */ + } __packed; + } __packed; + + union { + u8 TALLY_SEL; /* 0xfc */ + __le32 AC_BK_PARAM; + + } __packed; + +} __packed; + +/* These are addresses with NON-standard usage. + * They have offsets very far from this struct. + * I don't like to introduce a ton of "reserved".. + * They are for RTL8187SE + */ +#define REG_ADDR1(addr) ((u8 __iomem *)priv->map + (addr)) +#define REG_ADDR2(addr) ((__le16 __iomem *)priv->map + ((addr) >> 1)) +#define REG_ADDR4(addr) ((__le32 __iomem *)priv->map + ((addr) >> 2)) + +#define FEMR_SE REG_ADDR2(0x1D4) +#define ARFR REG_ADDR2(0x1E0) +#define RFSW_CTRL REG_ADDR2(0x272) +#define SW_3W_DB0 REG_ADDR2(0x274) +#define SW_3W_DB0_4 REG_ADDR4(0x274) +#define SW_3W_DB1 REG_ADDR2(0x278) +#define SW_3W_DB1_4 REG_ADDR4(0x278) +#define SW_3W_CMD1 REG_ADDR1(0x27D) +#define PI_DATA_REG REG_ADDR2(0x360) +#define SI_DATA_REG REG_ADDR2(0x362) + +struct rtl818x_rf_ops { + char *name; + void (*init)(struct ieee80211_hw *); + void (*stop)(struct ieee80211_hw *); + void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *); + u8 (*calc_rssi)(u8 agc, u8 sq); +}; + +/** + * enum rtl818x_tx_desc_flags - Tx/Rx flags are common between RTL818X chips + * + * @RTL818X_TX_DESC_FLAG_NO_ENC: Disable hardware based encryption. + * @RTL818X_TX_DESC_FLAG_TX_OK: TX frame was ACKed. + * @RTL818X_TX_DESC_FLAG_SPLCP: Use short preamble. + * @RTL818X_TX_DESC_FLAG_MOREFRAG: More fragments follow. + * @RTL818X_TX_DESC_FLAG_CTS: Use CTS-to-self protection. + * @RTL818X_TX_DESC_FLAG_RTS: Use RTS/CTS protection. + * @RTL818X_TX_DESC_FLAG_LS: Last segment of the frame. + * @RTL818X_TX_DESC_FLAG_FS: First segment of the frame. + */ +enum rtl818x_tx_desc_flags { + RTL818X_TX_DESC_FLAG_NO_ENC = (1 << 15), + RTL818X_TX_DESC_FLAG_TX_OK = (1 << 15), + RTL818X_TX_DESC_FLAG_SPLCP = (1 << 16), + RTL818X_TX_DESC_FLAG_RX_UNDER = (1 << 16), + RTL818X_TX_DESC_FLAG_MOREFRAG = (1 << 17), + RTL818X_TX_DESC_FLAG_CTS = (1 << 18), + RTL818X_TX_DESC_FLAG_RTS = (1 << 23), + RTL818X_TX_DESC_FLAG_LS = (1 << 28), + RTL818X_TX_DESC_FLAG_FS = (1 << 29), + RTL818X_TX_DESC_FLAG_DMA = (1 << 30), + RTL818X_TX_DESC_FLAG_OWN = (1 << 31) +}; + +enum rtl818x_rx_desc_flags { + RTL818X_RX_DESC_FLAG_ICV_ERR = (1 << 12), + RTL818X_RX_DESC_FLAG_CRC32_ERR = (1 << 13), + RTL818X_RX_DESC_FLAG_PM = (1 << 14), + RTL818X_RX_DESC_FLAG_RX_ERR = (1 << 15), + RTL818X_RX_DESC_FLAG_BCAST = (1 << 16), + RTL818X_RX_DESC_FLAG_PAM = (1 << 17), + RTL818X_RX_DESC_FLAG_MCAST = (1 << 18), + RTL818X_RX_DESC_FLAG_QOS = (1 << 19), /* RTL8187(B) only */ + RTL818X_RX_DESC_FLAG_TRSW = (1 << 24), /* RTL8187(B) only */ + RTL818X_RX_DESC_FLAG_SPLCP = (1 << 25), + RTL818X_RX_DESC_FLAG_FOF = (1 << 26), + RTL818X_RX_DESC_FLAG_DMA_FAIL = (1 << 27), + RTL818X_RX_DESC_FLAG_LS = (1 << 28), + RTL818X_RX_DESC_FLAG_FS = (1 << 29), + RTL818X_RX_DESC_FLAG_EOR = (1 << 30), + RTL818X_RX_DESC_FLAG_OWN = (1 << 31) +}; + +#endif /* RTL818X_H */ diff --git a/drivers/net/wireless/realtek/rtlwifi/Kconfig b/drivers/net/wireless/realtek/rtlwifi/Kconfig new file mode 100644 index 000000000000..73067cac289c --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/Kconfig @@ -0,0 +1,154 @@ +menuconfig RTL_CARDS + tristate "Realtek rtlwifi family of devices" + depends on MAC80211 && (PCI || USB) + default y + ---help--- + This option will enable support for the Realtek mac80211-based + wireless drivers. Drivers rtl8192ce, rtl8192cu, rtl8192se, rtl8192de, + rtl8723ae, rtl8723be, rtl8188ee, rtl8192ee, and rtl8821ae share + some common code. + +if RTL_CARDS + +config RTL8192CE + tristate "Realtek RTL8192CE/RTL8188CE Wireless Network Adapter" + depends on PCI + select RTL8192C_COMMON + select RTLWIFI + select RTLWIFI_PCI + ---help--- + This is the driver for Realtek RTL8192CE/RTL8188CE 802.11n PCIe + wireless network adapters. + + If you choose to build it as a module, it will be called rtl8192ce + +config RTL8192SE + tristate "Realtek RTL8192SE/RTL8191SE PCIe Wireless Network Adapter" + depends on PCI + select RTLWIFI + select RTLWIFI_PCI + ---help--- + This is the driver for Realtek RTL8192SE/RTL8191SE 802.11n PCIe + wireless network adapters. + + If you choose to build it as a module, it will be called rtl8192se + +config RTL8192DE + tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter" + depends on PCI + select RTLWIFI + select RTLWIFI_PCI + ---help--- + This is the driver for Realtek RTL8192DE/RTL8188DE 802.11n PCIe + wireless network adapters. + + If you choose to build it as a module, it will be called rtl8192de + +config RTL8723AE + tristate "Realtek RTL8723AE PCIe Wireless Network Adapter" + depends on PCI + select RTLWIFI + select RTLWIFI_PCI + select RTL8723_COMMON + select RTLBTCOEXIST + ---help--- + This is the driver for Realtek RTL8723AE 802.11n PCIe + wireless network adapters. + + If you choose to build it as a module, it will be called rtl8723ae + +config RTL8723BE + tristate "Realtek RTL8723BE PCIe Wireless Network Adapter" + depends on PCI + select RTLWIFI + select RTLWIFI_PCI + select RTL8723_COMMON + select RTLBTCOEXIST + ---help--- + This is the driver for Realtek RTL8723BE 802.11n PCIe + wireless network adapters. + + If you choose to build it as a module, it will be called rtl8723be + +config RTL8188EE + tristate "Realtek RTL8188EE Wireless Network Adapter" + depends on PCI + select RTLWIFI + select RTLWIFI_PCI + ---help--- + This is the driver for Realtek RTL8188EE 802.11n PCIe + wireless network adapters. + + If you choose to build it as a module, it will be called rtl8188ee + +config RTL8192EE + tristate "Realtek RTL8192EE Wireless Network Adapter" + depends on PCI + select RTLWIFI + select RTLWIFI_PCI + select RTLBTCOEXIST + ---help--- + This is the driver for Realtek RTL8192EE 802.11n PCIe + wireless network adapters. + + If you choose to build it as a module, it will be called rtl8192ee + +config RTL8821AE + tristate "Realtek RTL8821AE/RTL8812AE Wireless Network Adapter" + depends on PCI + select RTLWIFI + select RTLWIFI_PCI + select RTLBTCOEXIST + ---help--- + This is the driver for Realtek RTL8821AE/RTL8812AE 802.11ac PCIe + wireless network adapters. + + If you choose to build it as a module, it will be called rtl8821ae + +config RTL8192CU + tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter" + depends on USB + select RTLWIFI + select RTLWIFI_USB + select RTL8192C_COMMON + ---help--- + This is the driver for Realtek RTL8192CU/RTL8188CU 802.11n USB + wireless network adapters. + + If you choose to build it as a module, it will be called rtl8192cu + +config RTLWIFI + tristate + select FW_LOADER + +config RTLWIFI_PCI + tristate + +config RTLWIFI_USB + tristate + +config RTLWIFI_DEBUG + bool "Debugging output for rtlwifi driver family" + depends on RTLWIFI + default y + ---help--- + To use the module option that sets the dynamic-debugging level for, + the front-end driver, this parameter must be "Y". For memory-limited + systems, choose "N". If in doubt, choose "Y". + +config RTL8192C_COMMON + tristate + depends on RTL8192CE || RTL8192CU + default y + +config RTL8723_COMMON + tristate + depends on RTL8723AE || RTL8723BE + default y + +config RTLBTCOEXIST + tristate + depends on RTL8723AE || RTL8723BE || RTL8821AE || RTL8192EE + default y + +endif diff --git a/drivers/net/wireless/realtek/rtlwifi/Makefile b/drivers/net/wireless/realtek/rtlwifi/Makefile new file mode 100644 index 000000000000..ad6d3c52ec57 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/Makefile @@ -0,0 +1,34 @@ +obj-$(CONFIG_RTLWIFI) += rtlwifi.o +rtlwifi-objs := \ + base.o \ + cam.o \ + core.o \ + debug.o \ + efuse.o \ + ps.o \ + rc.o \ + regd.o \ + stats.o + +rtl8192c_common-objs += \ + +obj-$(CONFIG_RTLWIFI_PCI) += rtl_pci.o +rtl_pci-objs := pci.o + +obj-$(CONFIG_RTLWIFI_USB) += rtl_usb.o +rtl_usb-objs := usb.o + +obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c/ +obj-$(CONFIG_RTL8192CE) += rtl8192ce/ +obj-$(CONFIG_RTL8192CU) += rtl8192cu/ +obj-$(CONFIG_RTL8192SE) += rtl8192se/ +obj-$(CONFIG_RTL8192DE) += rtl8192de/ +obj-$(CONFIG_RTL8723AE) += rtl8723ae/ +obj-$(CONFIG_RTL8723BE) += rtl8723be/ +obj-$(CONFIG_RTL8188EE) += rtl8188ee/ +obj-$(CONFIG_RTLBTCOEXIST) += btcoexist/ +obj-$(CONFIG_RTL8723_COMMON) += rtl8723com/ +obj-$(CONFIG_RTL8821AE) += rtl8821ae/ +obj-$(CONFIG_RTL8192EE) += rtl8192ee/ + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c new file mode 100644 index 000000000000..0517a4f2d3f2 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -0,0 +1,2176 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "wifi.h" +#include "rc.h" +#include "base.h" +#include "efuse.h" +#include "cam.h" +#include "ps.h" +#include "regd.h" +#include "pci.h" +#include +#include +#include + +/* + *NOTICE!!!: This file will be very big, we should + *keep it clear under following roles: + * + *This file include following parts, so, if you add new + *functions into this file, please check which part it + *should includes. or check if you should add new part + *for this file: + * + *1) mac80211 init functions + *2) tx information functions + *3) functions called by core.c + *4) wq & timer callback functions + *5) frame process functions + *6) IOT functions + *7) sysfs functions + *8) vif functions + *9) ... + */ + +/********************************************************* + * + * mac80211 init functions + * + *********************************************************/ +static struct ieee80211_channel rtl_channeltable_2g[] = { + {.center_freq = 2412, .hw_value = 1,}, + {.center_freq = 2417, .hw_value = 2,}, + {.center_freq = 2422, .hw_value = 3,}, + {.center_freq = 2427, .hw_value = 4,}, + {.center_freq = 2432, .hw_value = 5,}, + {.center_freq = 2437, .hw_value = 6,}, + {.center_freq = 2442, .hw_value = 7,}, + {.center_freq = 2447, .hw_value = 8,}, + {.center_freq = 2452, .hw_value = 9,}, + {.center_freq = 2457, .hw_value = 10,}, + {.center_freq = 2462, .hw_value = 11,}, + {.center_freq = 2467, .hw_value = 12,}, + {.center_freq = 2472, .hw_value = 13,}, + {.center_freq = 2484, .hw_value = 14,}, +}; + +static struct ieee80211_channel rtl_channeltable_5g[] = { + {.center_freq = 5180, .hw_value = 36,}, + {.center_freq = 5200, .hw_value = 40,}, + {.center_freq = 5220, .hw_value = 44,}, + {.center_freq = 5240, .hw_value = 48,}, + {.center_freq = 5260, .hw_value = 52,}, + {.center_freq = 5280, .hw_value = 56,}, + {.center_freq = 5300, .hw_value = 60,}, + {.center_freq = 5320, .hw_value = 64,}, + {.center_freq = 5500, .hw_value = 100,}, + {.center_freq = 5520, .hw_value = 104,}, + {.center_freq = 5540, .hw_value = 108,}, + {.center_freq = 5560, .hw_value = 112,}, + {.center_freq = 5580, .hw_value = 116,}, + {.center_freq = 5600, .hw_value = 120,}, + {.center_freq = 5620, .hw_value = 124,}, + {.center_freq = 5640, .hw_value = 128,}, + {.center_freq = 5660, .hw_value = 132,}, + {.center_freq = 5680, .hw_value = 136,}, + {.center_freq = 5700, .hw_value = 140,}, + {.center_freq = 5745, .hw_value = 149,}, + {.center_freq = 5765, .hw_value = 153,}, + {.center_freq = 5785, .hw_value = 157,}, + {.center_freq = 5805, .hw_value = 161,}, + {.center_freq = 5825, .hw_value = 165,}, +}; + +static struct ieee80211_rate rtl_ratetable_2g[] = { + {.bitrate = 10, .hw_value = 0x00,}, + {.bitrate = 20, .hw_value = 0x01,}, + {.bitrate = 55, .hw_value = 0x02,}, + {.bitrate = 110, .hw_value = 0x03,}, + {.bitrate = 60, .hw_value = 0x04,}, + {.bitrate = 90, .hw_value = 0x05,}, + {.bitrate = 120, .hw_value = 0x06,}, + {.bitrate = 180, .hw_value = 0x07,}, + {.bitrate = 240, .hw_value = 0x08,}, + {.bitrate = 360, .hw_value = 0x09,}, + {.bitrate = 480, .hw_value = 0x0a,}, + {.bitrate = 540, .hw_value = 0x0b,}, +}; + +static struct ieee80211_rate rtl_ratetable_5g[] = { + {.bitrate = 60, .hw_value = 0x04,}, + {.bitrate = 90, .hw_value = 0x05,}, + {.bitrate = 120, .hw_value = 0x06,}, + {.bitrate = 180, .hw_value = 0x07,}, + {.bitrate = 240, .hw_value = 0x08,}, + {.bitrate = 360, .hw_value = 0x09,}, + {.bitrate = 480, .hw_value = 0x0a,}, + {.bitrate = 540, .hw_value = 0x0b,}, +}; + +static const struct ieee80211_supported_band rtl_band_2ghz = { + .band = IEEE80211_BAND_2GHZ, + + .channels = rtl_channeltable_2g, + .n_channels = ARRAY_SIZE(rtl_channeltable_2g), + + .bitrates = rtl_ratetable_2g, + .n_bitrates = ARRAY_SIZE(rtl_ratetable_2g), + + .ht_cap = {0}, +}; + +static struct ieee80211_supported_band rtl_band_5ghz = { + .band = IEEE80211_BAND_5GHZ, + + .channels = rtl_channeltable_5g, + .n_channels = ARRAY_SIZE(rtl_channeltable_5g), + + .bitrates = rtl_ratetable_5g, + .n_bitrates = ARRAY_SIZE(rtl_ratetable_5g), + + .ht_cap = {0}, +}; + +static const u8 tid_to_ac[] = { + 2, /* IEEE80211_AC_BE */ + 3, /* IEEE80211_AC_BK */ + 3, /* IEEE80211_AC_BK */ + 2, /* IEEE80211_AC_BE */ + 1, /* IEEE80211_AC_VI */ + 1, /* IEEE80211_AC_VI */ + 0, /* IEEE80211_AC_VO */ + 0, /* IEEE80211_AC_VO */ +}; + +u8 rtl_tid_to_ac(u8 tid) +{ + return tid_to_ac[tid]; +} +EXPORT_SYMBOL_GPL(rtl_tid_to_ac); + +static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, + struct ieee80211_sta_ht_cap *ht_cap) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + ht_cap->ht_supported = true; + ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU; + + if (rtlpriv->rtlhal.disable_amsdu_8k) + ht_cap->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; + + /* + *Maximum length of AMPDU that the STA can receive. + *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) + */ + ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + + /*Minimum MPDU start spacing , */ + ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; + + ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; + + /*hw->wiphy->bands[IEEE80211_BAND_2GHZ] + *base on ant_num + *rx_mask: RX mask + *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7 + *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15 + *if rx_ant >= 3 rx_mask[2]= 0xff; + *if BW_40 rx_mask[4]= 0x01; + *highest supported RX rate + */ + if (rtlpriv->dm.supp_phymode_switch) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + "Support phy mode switch\n"); + + ht_cap->mcs.rx_mask[0] = 0xFF; + ht_cap->mcs.rx_mask[1] = 0xFF; + ht_cap->mcs.rx_mask[4] = 0x01; + + ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); + } else { + if (get_rf_type(rtlphy) == RF_1T2R || + get_rf_type(rtlphy) == RF_2T2R) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "1T2R or 2T2R\n"); + ht_cap->mcs.rx_mask[0] = 0xFF; + ht_cap->mcs.rx_mask[1] = 0xFF; + ht_cap->mcs.rx_mask[4] = 0x01; + + ht_cap->mcs.rx_highest = + cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); + } else if (get_rf_type(rtlphy) == RF_1T1R) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n"); + + ht_cap->mcs.rx_mask[0] = 0xFF; + ht_cap->mcs.rx_mask[1] = 0x00; + ht_cap->mcs.rx_mask[4] = 0x01; + + ht_cap->mcs.rx_highest = + cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); + } + } +} + +static void _rtl_init_hw_vht_capab(struct ieee80211_hw *hw, + struct ieee80211_sta_vht_cap *vht_cap) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + u16 mcs_map; + + vht_cap->vht_supported = true; + vht_cap->cap = + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 | + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | + IEEE80211_VHT_CAP_SHORT_GI_80 | + IEEE80211_VHT_CAP_TXSTBC | + IEEE80211_VHT_CAP_RXSTBC_1 | + IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | + IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | + IEEE80211_VHT_CAP_HTC_VHT | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | + IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | + IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | + 0; + + mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | + IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; + + vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); + vht_cap->vht_mcs.rx_highest = + cpu_to_le16(MAX_BIT_RATE_SHORT_GI_2NSS_80MHZ_MCS9); + vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); + vht_cap->vht_mcs.tx_highest = + cpu_to_le16(MAX_BIT_RATE_SHORT_GI_2NSS_80MHZ_MCS9); + } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + u16 mcs_map; + + vht_cap->vht_supported = true; + vht_cap->cap = + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 | + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | + IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | + IEEE80211_VHT_CAP_SHORT_GI_80 | + IEEE80211_VHT_CAP_TXSTBC | + IEEE80211_VHT_CAP_RXSTBC_1 | + IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | + IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | + IEEE80211_VHT_CAP_HTC_VHT | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | + IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | + IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | + 0; + + mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | + IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; + + vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); + vht_cap->vht_mcs.rx_highest = + cpu_to_le16(MAX_BIT_RATE_SHORT_GI_1NSS_80MHZ_MCS9); + vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); + vht_cap->vht_mcs.tx_highest = + cpu_to_le16(MAX_BIT_RATE_SHORT_GI_1NSS_80MHZ_MCS9); + } +} + +static void _rtl_init_mac80211(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct ieee80211_supported_band *sband; + + if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && + rtlhal->bandset == BAND_ON_BOTH) { + /* 1: 2.4 G bands */ + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); + + /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] + * to default value(1T1R) */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, + sizeof(struct ieee80211_supported_band)); + + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + + /* 2: 5 G bands */ + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); + + /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] + * to default value(1T1R) */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, + sizeof(struct ieee80211_supported_band)); + + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + + _rtl_init_hw_vht_capab(hw, &sband->vht_cap); + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; + } else { + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); + + /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] + * to default value(1T1R) */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), + &rtl_band_2ghz, + sizeof(struct ieee80211_supported_band)); + + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + } else if (rtlhal->current_bandtype == BAND_ON_5G) { + /* <1> use mac->bands as mem for hw->wiphy->bands */ + sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); + + /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] + * to default value(1T1R) */ + memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), + &rtl_band_5ghz, + sizeof(struct ieee80211_supported_band)); + + /* <3> init ht cap base on ant_num */ + _rtl_init_hw_ht_capab(hw, &sband->ht_cap); + + _rtl_init_hw_vht_capab(hw, &sband->vht_cap); + /* <4> set mac->sband to wiphy->sband */ + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Err BAND %d\n", + rtlhal->current_bandtype); + } + } + /* <5> set hw caps */ + ieee80211_hw_set(hw, SIGNAL_DBM); + ieee80211_hw_set(hw, RX_INCLUDES_FCS); + ieee80211_hw_set(hw, AMPDU_AGGREGATION); + ieee80211_hw_set(hw, CONNECTION_MONITOR); + ieee80211_hw_set(hw, MFP_CAPABLE); + ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); + + /* swlps or hwlps has been set in diff chip in init_sw_vars */ + if (rtlpriv->psc.swctrl_lps) { + ieee80211_hw_set(hw, SUPPORTS_PS); + ieee80211_hw_set(hw, PS_NULLFUNC_STACK); + } + hw->wiphy->interface_modes = + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_MESH_POINT) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO); + hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + + hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + + hw->wiphy->rts_threshold = 2347; + + hw->queues = AC_MAX; + hw->extra_tx_headroom = RTL_TX_HEADER_SIZE; + + /* TODO: Correct this value for our hw */ + /* TODO: define these hard code value */ + hw->max_listen_interval = 10; + hw->max_rate_tries = 4; + /* hw->max_rates = 1; */ + hw->sta_data_size = sizeof(struct rtl_sta_info); + +/* wowlan is not supported by kernel if CONFIG_PM is not defined */ +#ifdef CONFIG_PM + if (rtlpriv->psc.wo_wlan_mode) { + if (rtlpriv->psc.wo_wlan_mode & WAKE_ON_MAGIC_PACKET) + rtlpriv->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; + if (rtlpriv->psc.wo_wlan_mode & WAKE_ON_PATTERN_MATCH) { + rtlpriv->wowlan.n_patterns = + MAX_SUPPORT_WOL_PATTERN_NUM; + rtlpriv->wowlan.pattern_min_len = MIN_WOL_PATTERN_SIZE; + rtlpriv->wowlan.pattern_max_len = MAX_WOL_PATTERN_SIZE; + } + hw->wiphy->wowlan = &rtlpriv->wowlan; + } +#endif + + /* <6> mac address */ + if (is_valid_ether_addr(rtlefuse->dev_addr)) { + SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr); + } else { + u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; + get_random_bytes((rtlmac1 + (ETH_ALEN - 1)), 1); + SET_IEEE80211_PERM_ADDR(hw, rtlmac1); + } +} + +static void _rtl_init_deferred_work(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* <1> timer */ + setup_timer(&rtlpriv->works.watchdog_timer, + rtl_watch_dog_timer_callback, (unsigned long)hw); + setup_timer(&rtlpriv->works.dualmac_easyconcurrent_retrytimer, + rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw); + /* <2> work queue */ + rtlpriv->works.hw = hw; + rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name); + INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq, + (void *)rtl_watchdog_wq_callback); + INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, + (void *)rtl_ips_nic_off_wq_callback); + INIT_DELAYED_WORK(&rtlpriv->works.ps_work, + (void *)rtl_swlps_wq_callback); + INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, + (void *)rtl_swlps_rfon_wq_callback); + INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq, + (void *)rtl_fwevt_wq_callback); + +} + +void rtl_deinit_deferred_work(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + del_timer_sync(&rtlpriv->works.watchdog_timer); + + cancel_delayed_work(&rtlpriv->works.watchdog_wq); + cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); + cancel_delayed_work(&rtlpriv->works.ps_work); + cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); + cancel_delayed_work(&rtlpriv->works.fwevt_wq); +} +EXPORT_SYMBOL_GPL(rtl_deinit_deferred_work); + +void rtl_init_rfkill(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + bool radio_state; + bool blocked; + u8 valid = 0; + + /*set init state to on */ + rtlpriv->rfkill.rfkill_state = true; + wiphy_rfkill_set_hw_state(hw->wiphy, 0); + + radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); + + if (valid) { + pr_info("rtlwifi: wireless switch is %s\n", + rtlpriv->rfkill.rfkill_state ? "on" : "off"); + + rtlpriv->rfkill.rfkill_state = radio_state; + + blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1; + wiphy_rfkill_set_hw_state(hw->wiphy, blocked); + } + + wiphy_rfkill_start_polling(hw->wiphy); +} +EXPORT_SYMBOL(rtl_init_rfkill); + +void rtl_deinit_rfkill(struct ieee80211_hw *hw) +{ + wiphy_rfkill_stop_polling(hw->wiphy); +} +EXPORT_SYMBOL_GPL(rtl_deinit_rfkill); + +int rtl_init_core(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); + + /* <1> init mac80211 */ + _rtl_init_mac80211(hw); + rtlmac->hw = hw; + + /* <2> rate control register */ + hw->rate_control_algorithm = "rtl_rc"; + + /* + * <3> init CRDA must come after init + * mac80211 hw in _rtl_init_mac80211. + */ + if (rtl_regd_init(hw, rtl_reg_notifier)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "REGD init failed\n"); + return 1; + } + + /* <4> locks */ + mutex_init(&rtlpriv->locks.conf_mutex); + spin_lock_init(&rtlpriv->locks.ips_lock); + spin_lock_init(&rtlpriv->locks.irq_th_lock); + spin_lock_init(&rtlpriv->locks.h2c_lock); + spin_lock_init(&rtlpriv->locks.rf_ps_lock); + spin_lock_init(&rtlpriv->locks.rf_lock); + spin_lock_init(&rtlpriv->locks.waitq_lock); + spin_lock_init(&rtlpriv->locks.entry_list_lock); + spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); + spin_lock_init(&rtlpriv->locks.check_sendpkt_lock); + spin_lock_init(&rtlpriv->locks.fw_ps_lock); + spin_lock_init(&rtlpriv->locks.lps_lock); + spin_lock_init(&rtlpriv->locks.iqk_lock); + /* <5> init list */ + INIT_LIST_HEAD(&rtlpriv->entry_list); + + rtlmac->link_state = MAC80211_NOLINK; + + /* <6> init deferred work */ + _rtl_init_deferred_work(hw); + + return 0; +} +EXPORT_SYMBOL_GPL(rtl_init_core); + +void rtl_deinit_core(struct ieee80211_hw *hw) +{ +} +EXPORT_SYMBOL_GPL(rtl_deinit_core); + +void rtl_init_rx_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); +} +EXPORT_SYMBOL_GPL(rtl_init_rx_config); + +/********************************************************* + * + * tx information functions + * + *********************************************************/ +static void _rtl_qurey_shortpreamble_mode(struct ieee80211_hw *hw, + struct rtl_tcb_desc *tcb_desc, + struct ieee80211_tx_info *info) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 rate_flag = info->control.rates[0].flags; + + tcb_desc->use_shortpreamble = false; + + /* 1M can only use Long Preamble. 11B spec */ + if (tcb_desc->hw_rate == rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]) + return; + else if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) + tcb_desc->use_shortpreamble = true; + + return; +} + +static void _rtl_query_shortgi(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct rtl_tcb_desc *tcb_desc, + struct ieee80211_tx_info *info) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 rate_flag = info->control.rates[0].flags; + u8 sgi_40 = 0, sgi_20 = 0, bw_40 = 0; + u8 sgi_80 = 0, bw_80 = 0; + tcb_desc->use_shortgi = false; + + if (sta == NULL) + return; + + sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; + sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; + sgi_80 = sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80; + + if ((!sta->ht_cap.ht_supported) && (!sta->vht_cap.vht_supported)) + return; + + if (!sgi_40 && !sgi_20) + return; + + if (mac->opmode == NL80211_IFTYPE_STATION) { + bw_40 = mac->bw_40; + bw_80 = mac->bw_80; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; + bw_80 = sta->vht_cap.vht_supported; + } + + if (bw_80) { + if (sgi_80) + tcb_desc->use_shortgi = true; + else + tcb_desc->use_shortgi = false; + } else { + if (bw_40 && sgi_40) + tcb_desc->use_shortgi = true; + else if (!bw_40 && sgi_20) + tcb_desc->use_shortgi = true; + } + + if (!(rate_flag & IEEE80211_TX_RC_SHORT_GI)) + tcb_desc->use_shortgi = false; +} + +static void _rtl_query_protection_mode(struct ieee80211_hw *hw, + struct rtl_tcb_desc *tcb_desc, + struct ieee80211_tx_info *info) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 rate_flag = info->control.rates[0].flags; + + /* Common Settings */ + tcb_desc->rts_stbc = false; + tcb_desc->cts_enable = false; + tcb_desc->rts_sc = 0; + tcb_desc->rts_bw = false; + tcb_desc->rts_use_shortpreamble = false; + tcb_desc->rts_use_shortgi = false; + + if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT) { + /* Use CTS-to-SELF in protection mode. */ + tcb_desc->rts_enable = true; + tcb_desc->cts_enable = true; + tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; + } else if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) { + /* Use RTS-CTS in protection mode. */ + tcb_desc->rts_enable = true; + tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; + } +} + +static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct rtl_tcb_desc *tcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u8 ratr_index = 7; + + if (sta) { + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + ratr_index = sta_entry->ratr_index; + } + if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { + if (mac->opmode == NL80211_IFTYPE_STATION) { + tcb_desc->ratr_index = 0; + } else if (mac->opmode == NL80211_IFTYPE_ADHOC || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + if (tcb_desc->multicast || tcb_desc->broadcast) { + tcb_desc->hw_rate = + rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; + tcb_desc->use_driver_rate = 1; + tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; + } else { + tcb_desc->ratr_index = ratr_index; + } + } else if (mac->opmode == NL80211_IFTYPE_AP) { + tcb_desc->ratr_index = ratr_index; + } + } + + if (rtlpriv->dm.useramask) { + tcb_desc->ratr_index = ratr_index; + /* TODO we will differentiate adhoc and station future */ + if (mac->opmode == NL80211_IFTYPE_STATION || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + tcb_desc->mac_id = 0; + + if (mac->mode == WIRELESS_MODE_AC_5G) + tcb_desc->ratr_index = + RATR_INX_WIRELESS_AC_5N; + else if (mac->mode == WIRELESS_MODE_AC_24G) + tcb_desc->ratr_index = + RATR_INX_WIRELESS_AC_24N; + else if (mac->mode == WIRELESS_MODE_N_24G) + tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB; + else if (mac->mode == WIRELESS_MODE_N_5G) + tcb_desc->ratr_index = RATR_INX_WIRELESS_NG; + else if (mac->mode & WIRELESS_MODE_G) + tcb_desc->ratr_index = RATR_INX_WIRELESS_GB; + else if (mac->mode & WIRELESS_MODE_B) + tcb_desc->ratr_index = RATR_INX_WIRELESS_B; + else if (mac->mode & WIRELESS_MODE_A) + tcb_desc->ratr_index = RATR_INX_WIRELESS_G; + + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (NULL != sta) { + if (sta->aid > 0) + tcb_desc->mac_id = sta->aid + 1; + else + tcb_desc->mac_id = 1; + } else { + tcb_desc->mac_id = 0; + } + } + } +} + +static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct rtl_tcb_desc *tcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + tcb_desc->packet_bw = false; + if (!sta) + return; + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + if (!(sta->ht_cap.ht_supported) || + !(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + return; + } else if (mac->opmode == NL80211_IFTYPE_STATION) { + if (!mac->bw_40 || !(sta->ht_cap.ht_supported)) + return; + } + if (tcb_desc->multicast || tcb_desc->broadcast) + return; + + /*use legency rate, shall use 20MHz */ + if (tcb_desc->hw_rate <= rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]) + return; + + tcb_desc->packet_bw = HT_CHANNEL_WIDTH_20_40; + + if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE || + rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8821AE) { + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + if (!(sta->vht_cap.vht_supported)) + return; + } else if (mac->opmode == NL80211_IFTYPE_STATION) { + if (!mac->bw_80 || + !(sta->vht_cap.vht_supported)) + return; + } + if (tcb_desc->hw_rate <= + rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15]) + return; + tcb_desc->packet_bw = HT_CHANNEL_WIDTH_80; + } +} + +static u8 _rtl_get_vht_highest_n_rate(struct ieee80211_hw *hw, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u8 hw_rate; + u16 tx_mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.tx_mcs_map); + + if ((get_rf_type(rtlphy) == RF_2T2R) && + (tx_mcs_map & 0x000c) != 0x000c) { + if ((tx_mcs_map & 0x000c) >> 2 == + IEEE80211_VHT_MCS_SUPPORT_0_7) + hw_rate = + rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS7]; + else if ((tx_mcs_map & 0x000c) >> 2 == + IEEE80211_VHT_MCS_SUPPORT_0_8) + hw_rate = + rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS9]; + else + hw_rate = + rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS9]; + } else { + if ((tx_mcs_map & 0x0003) == + IEEE80211_VHT_MCS_SUPPORT_0_7) + hw_rate = + rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS7]; + else if ((tx_mcs_map & 0x0003) == + IEEE80211_VHT_MCS_SUPPORT_0_8) + hw_rate = + rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS9]; + else + hw_rate = + rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS9]; + } + + return hw_rate; +} + +static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 hw_rate; + + if ((get_rf_type(rtlphy) == RF_2T2R) && + (sta->ht_cap.mcs.rx_mask[1] != 0)) + hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15]; + else + hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS7]; + + return hw_rate; +} + +/* mac80211's rate_idx is like this: + * + * 2.4G band:rx_status->band == IEEE80211_BAND_2GHZ + * + * B/G rate: + * (rx_status->flag & RX_FLAG_HT) = 0, + * DESC_RATE1M-->DESC_RATE54M ==> idx is 0-->11, + * + * N rate: + * (rx_status->flag & RX_FLAG_HT) = 1, + * DESC_RATEMCS0-->DESC_RATEMCS15 ==> idx is 0-->15 + * + * 5G band:rx_status->band == IEEE80211_BAND_5GHZ + * A rate: + * (rx_status->flag & RX_FLAG_HT) = 0, + * DESC_RATE6M-->DESC_RATE54M ==> idx is 0-->7, + * + * N rate: + * (rx_status->flag & RX_FLAG_HT) = 1, + * DESC_RATEMCS0-->DESC_RATEMCS15 ==> idx is 0-->15 + * + * VHT rates: + * DESC_RATEVHT1SS_MCS0-->DESC_RATEVHT1SS_MCS9 ==> idx is 0-->9 + * DESC_RATEVHT2SS_MCS0-->DESC_RATEVHT2SS_MCS9 ==> idx is 0-->9 + */ +int rtlwifi_rate_mapping(struct ieee80211_hw *hw, bool isht, bool isvht, + u8 desc_rate) +{ + int rate_idx; + + if (isvht) { + switch (desc_rate) { + case DESC_RATEVHT1SS_MCS0: + rate_idx = 0; + break; + case DESC_RATEVHT1SS_MCS1: + rate_idx = 1; + break; + case DESC_RATEVHT1SS_MCS2: + rate_idx = 2; + break; + case DESC_RATEVHT1SS_MCS3: + rate_idx = 3; + break; + case DESC_RATEVHT1SS_MCS4: + rate_idx = 4; + break; + case DESC_RATEVHT1SS_MCS5: + rate_idx = 5; + break; + case DESC_RATEVHT1SS_MCS6: + rate_idx = 6; + break; + case DESC_RATEVHT1SS_MCS7: + rate_idx = 7; + break; + case DESC_RATEVHT1SS_MCS8: + rate_idx = 8; + break; + case DESC_RATEVHT1SS_MCS9: + rate_idx = 9; + break; + case DESC_RATEVHT2SS_MCS0: + rate_idx = 0; + break; + case DESC_RATEVHT2SS_MCS1: + rate_idx = 1; + break; + case DESC_RATEVHT2SS_MCS2: + rate_idx = 2; + break; + case DESC_RATEVHT2SS_MCS3: + rate_idx = 3; + break; + case DESC_RATEVHT2SS_MCS4: + rate_idx = 4; + break; + case DESC_RATEVHT2SS_MCS5: + rate_idx = 5; + break; + case DESC_RATEVHT2SS_MCS6: + rate_idx = 6; + break; + case DESC_RATEVHT2SS_MCS7: + rate_idx = 7; + break; + case DESC_RATEVHT2SS_MCS8: + rate_idx = 8; + break; + case DESC_RATEVHT2SS_MCS9: + rate_idx = 9; + break; + default: + rate_idx = 0; + break; + } + return rate_idx; + } + if (false == isht) { + if (IEEE80211_BAND_2GHZ == hw->conf.chandef.chan->band) { + switch (desc_rate) { + case DESC_RATE1M: + rate_idx = 0; + break; + case DESC_RATE2M: + rate_idx = 1; + break; + case DESC_RATE5_5M: + rate_idx = 2; + break; + case DESC_RATE11M: + rate_idx = 3; + break; + case DESC_RATE6M: + rate_idx = 4; + break; + case DESC_RATE9M: + rate_idx = 5; + break; + case DESC_RATE12M: + rate_idx = 6; + break; + case DESC_RATE18M: + rate_idx = 7; + break; + case DESC_RATE24M: + rate_idx = 8; + break; + case DESC_RATE36M: + rate_idx = 9; + break; + case DESC_RATE48M: + rate_idx = 10; + break; + case DESC_RATE54M: + rate_idx = 11; + break; + default: + rate_idx = 0; + break; + } + } else { + switch (desc_rate) { + case DESC_RATE6M: + rate_idx = 0; + break; + case DESC_RATE9M: + rate_idx = 1; + break; + case DESC_RATE12M: + rate_idx = 2; + break; + case DESC_RATE18M: + rate_idx = 3; + break; + case DESC_RATE24M: + rate_idx = 4; + break; + case DESC_RATE36M: + rate_idx = 5; + break; + case DESC_RATE48M: + rate_idx = 6; + break; + case DESC_RATE54M: + rate_idx = 7; + break; + default: + rate_idx = 0; + break; + } + } + } else { + switch (desc_rate) { + case DESC_RATEMCS0: + rate_idx = 0; + break; + case DESC_RATEMCS1: + rate_idx = 1; + break; + case DESC_RATEMCS2: + rate_idx = 2; + break; + case DESC_RATEMCS3: + rate_idx = 3; + break; + case DESC_RATEMCS4: + rate_idx = 4; + break; + case DESC_RATEMCS5: + rate_idx = 5; + break; + case DESC_RATEMCS6: + rate_idx = 6; + break; + case DESC_RATEMCS7: + rate_idx = 7; + break; + case DESC_RATEMCS8: + rate_idx = 8; + break; + case DESC_RATEMCS9: + rate_idx = 9; + break; + case DESC_RATEMCS10: + rate_idx = 10; + break; + case DESC_RATEMCS11: + rate_idx = 11; + break; + case DESC_RATEMCS12: + rate_idx = 12; + break; + case DESC_RATEMCS13: + rate_idx = 13; + break; + case DESC_RATEMCS14: + rate_idx = 14; + break; + case DESC_RATEMCS15: + rate_idx = 15; + break; + default: + rate_idx = 0; + break; + } + } + return rate_idx; +} +EXPORT_SYMBOL(rtlwifi_rate_mapping); + +void rtl_get_tcb_desc(struct ieee80211_hw *hw, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); + struct ieee80211_rate *txrate; + __le16 fc = rtl_get_fc(skb); + + txrate = ieee80211_get_tx_rate(hw, info); + if (txrate) + tcb_desc->hw_rate = txrate->hw_value; + + if (ieee80211_is_data(fc)) { + /* + *we set data rate INX 0 + *in rtl_rc.c if skb is special data or + *mgt which need low data rate. + */ + + /* + *So tcb_desc->hw_rate is just used for + *special data and mgt frames + */ + if (info->control.rates[0].idx == 0 || + ieee80211_is_nullfunc(fc)) { + tcb_desc->use_driver_rate = true; + tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; + + tcb_desc->disable_ratefallback = 1; + } else { + /* + *because hw will nerver use hw_rate + *when tcb_desc->use_driver_rate = false + *so we never set highest N rate here, + *and N rate will all be controlled by FW + *when tcb_desc->use_driver_rate = false + */ + if (sta && sta->vht_cap.vht_supported) { + tcb_desc->hw_rate = + _rtl_get_vht_highest_n_rate(hw, sta); + } else { + if (sta && (sta->ht_cap.ht_supported)) { + tcb_desc->hw_rate = + _rtl_get_highest_n_rate(hw, sta); + } else { + if (rtlmac->mode == WIRELESS_MODE_B) { + tcb_desc->hw_rate = + rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; + } else { + tcb_desc->hw_rate = + rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; + } + } + } + } + + if (is_multicast_ether_addr(ieee80211_get_DA(hdr))) + tcb_desc->multicast = 1; + else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr))) + tcb_desc->broadcast = 1; + + _rtl_txrate_selectmode(hw, sta, tcb_desc); + _rtl_query_bandwidth_mode(hw, sta, tcb_desc); + _rtl_qurey_shortpreamble_mode(hw, tcb_desc, info); + _rtl_query_shortgi(hw, sta, tcb_desc, info); + _rtl_query_protection_mode(hw, tcb_desc, info); + } else { + tcb_desc->use_driver_rate = true; + tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; + tcb_desc->disable_ratefallback = 1; + tcb_desc->mac_id = 0; + tcb_desc->packet_bw = false; + } +} +EXPORT_SYMBOL(rtl_get_tcb_desc); + +bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + __le16 fc = rtl_get_fc(skb); + + if (rtlpriv->dm.supp_phymode_switch && + mac->link_state < MAC80211_LINKED && + (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) { + if (rtlpriv->cfg->ops->chk_switch_dmdp) + rtlpriv->cfg->ops->chk_switch_dmdp(hw); + } + if (ieee80211_is_auth(fc)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n"); + rtl_ips_nic_on(hw); + + mac->link_state = MAC80211_LINKING; + /* Dul mac */ + rtlpriv->phy.need_iqk = true; + + } + + return true; +} +EXPORT_SYMBOL_GPL(rtl_tx_mgmt_proc); + +struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, u8 *sa, + u8 *bssid, u16 tid); + +static void process_agg_start(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u16 tid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_rx_status rx_status = { 0 }; + struct sk_buff *skb_delba = NULL; + + skb_delba = rtl_make_del_ba(hw, hdr->addr2, hdr->addr3, tid); + if (skb_delba) { + rx_status.freq = hw->conf.chandef.chan->center_freq; + rx_status.band = hw->conf.chandef.chan->band; + rx_status.flag |= RX_FLAG_DECRYPTED; + rx_status.flag |= RX_FLAG_MACTIME_START; + rx_status.rate_idx = 0; + rx_status.signal = 50 + 10; + memcpy(IEEE80211_SKB_RXCB(skb_delba), + &rx_status, sizeof(rx_status)); + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, + "fake del\n", + skb_delba->data, + skb_delba->len); + ieee80211_rx_irqsafe(hw, skb_delba); + } +} + +bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); + struct rtl_priv *rtlpriv = rtl_priv(hw); + __le16 fc = rtl_get_fc(skb); + u8 *act = (u8 *)(((u8 *)skb->data + MAC80211_3ADDR_LEN)); + u8 category; + + if (!ieee80211_is_action(fc)) + return true; + + category = *act; + act++; + switch (category) { + case ACT_CAT_BA: + switch (*act) { + case ACT_ADDBAREQ: + if (mac->act_scanning) + return false; + + RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, + "%s ACT_ADDBAREQ From :%pM\n", + is_tx ? "Tx" : "Rx", hdr->addr2); + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "req\n", + skb->data, skb->len); + if (!is_tx) { + struct ieee80211_sta *sta = NULL; + struct rtl_sta_info *sta_entry = NULL; + struct rtl_tid_data *tid_data; + struct ieee80211_mgmt *mgmt = (void *)skb->data; + u16 capab = 0, tid = 0; + + rcu_read_lock(); + sta = rtl_find_sta(hw, hdr->addr3); + if (sta == NULL) { + RT_TRACE(rtlpriv, COMP_SEND | COMP_RECV, + DBG_DMESG, "sta is NULL\n"); + rcu_read_unlock(); + return true; + } + + sta_entry = + (struct rtl_sta_info *)sta->drv_priv; + if (!sta_entry) { + rcu_read_unlock(); + return true; + } + capab = + le16_to_cpu(mgmt->u.action.u.addba_req.capab); + tid = (capab & + IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; + tid_data = &sta_entry->tids[tid]; + if (tid_data->agg.rx_agg_state == + RTL_RX_AGG_START) + process_agg_start(hw, hdr, tid); + rcu_read_unlock(); + } + break; + case ACT_ADDBARSP: + RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, + "%s ACT_ADDBARSP From :%pM\n", + is_tx ? "Tx" : "Rx", hdr->addr2); + break; + case ACT_DELBA: + RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, + "ACT_ADDBADEL From :%pM\n", hdr->addr2); + break; + } + break; + default: + break; + } + + return true; +} +EXPORT_SYMBOL_GPL(rtl_action_proc); + +static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc) +{ + rtlpriv->ra.is_special_data = true; + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_special_packet_notify( + rtlpriv, 1); + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); + ppsc->last_delaylps_stamp_jiffies = jiffies; +} + +/*should call before software enc*/ +u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx, + bool is_enc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + __le16 fc = rtl_get_fc(skb); + u16 ether_type; + u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); + u8 encrypt_header_len = 0; + u8 offset; + const struct iphdr *ip; + + if (!ieee80211_is_data(fc)) + goto end; + + switch (rtlpriv->sec.pairwise_enc_algorithm) { + case WEP40_ENCRYPTION: + case WEP104_ENCRYPTION: + encrypt_header_len = 4;/*WEP_IV_LEN*/ + break; + case TKIP_ENCRYPTION: + encrypt_header_len = 8;/*TKIP_IV_LEN*/ + break; + case AESCCMP_ENCRYPTION: + encrypt_header_len = 8;/*CCMP_HDR_LEN;*/ + break; + default: + break; + } + + offset = mac_hdr_len + SNAP_SIZE; + if (is_enc) + offset += encrypt_header_len; + ether_type = be16_to_cpup((__be16 *)(skb->data + offset)); + + if (ETH_P_IP == ether_type) { + ip = (struct iphdr *)((u8 *)skb->data + offset + + PROTOC_TYPE_SIZE); + if (IPPROTO_UDP == ip->protocol) { + struct udphdr *udp = (struct udphdr *)((u8 *)ip + + (ip->ihl << 2)); + if (((((u8 *)udp)[1] == 68) && + (((u8 *)udp)[3] == 67)) || + ((((u8 *)udp)[1] == 67) && + (((u8 *)udp)[3] == 68))) { + /* 68 : UDP BOOTP client + * 67 : UDP BOOTP server + */ + RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), + DBG_DMESG, "dhcp %s !!\n", + (is_tx) ? "Tx" : "Rx"); + + if (is_tx) + setup_arp_tx(rtlpriv, ppsc); + return true; + } + } + } else if (ETH_P_ARP == ether_type) { + if (is_tx) + setup_arp_tx(rtlpriv, ppsc); + + return true; + } else if (ETH_P_PAE == ether_type) { + RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, + "802.1X %s EAPOL pkt!!\n", (is_tx) ? "Tx" : "Rx"); + + if (is_tx) { + rtlpriv->ra.is_special_data = true; + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); + ppsc->last_delaylps_stamp_jiffies = jiffies; + } + + return true; + } else if (ETH_P_IPV6 == ether_type) { + /* TODO: Handle any IPv6 cases that need special handling. + * For now, always return false + */ + goto end; + } + +end: + rtlpriv->ra.is_special_data = false; + return false; +} +EXPORT_SYMBOL_GPL(rtl_is_special_data); + +/********************************************************* + * + * functions called by core.c + * + *********************************************************/ +int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, u16 tid, u16 *ssn) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_tid_data *tid_data; + struct rtl_sta_info *sta_entry = NULL; + + if (sta == NULL) + return -EINVAL; + + if (unlikely(tid >= MAX_TID_COUNT)) + return -EINVAL; + + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + if (!sta_entry) + return -ENXIO; + tid_data = &sta_entry->tids[tid]; + + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, + "on ra = %pM tid = %d seq:%d\n", sta->addr, tid, + tid_data->seq_number); + + *ssn = tid_data->seq_number; + tid_data->agg.agg_state = RTL_AGG_START; + + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + return 0; +} + +int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, u16 tid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_tid_data *tid_data; + struct rtl_sta_info *sta_entry = NULL; + + if (sta == NULL) + return -EINVAL; + + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, + "on ra = %pM tid = %d\n", sta->addr, tid); + + if (unlikely(tid >= MAX_TID_COUNT)) + return -EINVAL; + + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + tid_data = &sta_entry->tids[tid]; + sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP; + + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + return 0; +} + +int rtl_rx_agg_start(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_tid_data *tid_data; + struct rtl_sta_info *sta_entry = NULL; + + if (sta == NULL) + return -EINVAL; + + if (unlikely(tid >= MAX_TID_COUNT)) + return -EINVAL; + + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + if (!sta_entry) + return -ENXIO; + tid_data = &sta_entry->tids[tid]; + + RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG, + "on ra = %pM tid = %d seq:%d\n", sta->addr, tid, + tid_data->seq_number); + + tid_data->agg.rx_agg_state = RTL_RX_AGG_START; + return 0; +} + +int rtl_rx_agg_stop(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_sta_info *sta_entry = NULL; + + if (sta == NULL) + return -EINVAL; + + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, + "on ra = %pM tid = %d\n", sta->addr, tid); + + if (unlikely(tid >= MAX_TID_COUNT)) + return -EINVAL; + + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + sta_entry->tids[tid].agg.rx_agg_state = RTL_RX_AGG_STOP; + + return 0; +} +int rtl_tx_agg_oper(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_sta_info *sta_entry = NULL; + + if (sta == NULL) + return -EINVAL; + + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, + "on ra = %pM tid = %d\n", sta->addr, tid); + + if (unlikely(tid >= MAX_TID_COUNT)) + return -EINVAL; + + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL; + + return 0; +} + +/********************************************************* + * + * wq & timer callback functions + * + *********************************************************/ +/* this function is used for roaming */ +void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + + if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) + return; + + if (rtlpriv->mac80211.link_state < MAC80211_LINKED) + return; + + /* check if this really is a beacon */ + if (!ieee80211_is_beacon(hdr->frame_control) && + !ieee80211_is_probe_resp(hdr->frame_control)) + return; + + /* min. beacon length + FCS_LEN */ + if (skb->len <= 40 + FCS_LEN) + return; + + /* and only beacons from the associated BSSID, please */ + if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid)) + return; + + rtlpriv->link_info.bcn_rx_inperiod++; +} +EXPORT_SYMBOL_GPL(rtl_beacon_statistic); + +void rtl_watchdog_wq_callback(void *data) +{ + struct rtl_works *rtlworks = container_of_dwork_rtl(data, + struct rtl_works, + watchdog_wq); + struct ieee80211_hw *hw = rtlworks->hw; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + bool busytraffic = false; + bool tx_busy_traffic = false; + bool rx_busy_traffic = false; + bool higher_busytraffic = false; + bool higher_busyrxtraffic = false; + u8 idx, tid; + u32 rx_cnt_inp4eriod = 0; + u32 tx_cnt_inp4eriod = 0; + u32 aver_rx_cnt_inperiod = 0; + u32 aver_tx_cnt_inperiod = 0; + u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; + u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; + + if (is_hal_stop(rtlhal)) + return; + + /* <1> Determine if action frame is allowed */ + if (mac->link_state > MAC80211_NOLINK) { + if (mac->cnt_after_linked < 20) + mac->cnt_after_linked++; + } else { + mac->cnt_after_linked = 0; + } + + /* <2> to check if traffic busy, if + * busytraffic we don't change channel + */ + if (mac->link_state >= MAC80211_LINKED) { + + /* (1) get aver_rx_cnt_inperiod & aver_tx_cnt_inperiod */ + for (idx = 0; idx <= 2; idx++) { + rtlpriv->link_info.num_rx_in4period[idx] = + rtlpriv->link_info.num_rx_in4period[idx + 1]; + rtlpriv->link_info.num_tx_in4period[idx] = + rtlpriv->link_info.num_tx_in4period[idx + 1]; + } + rtlpriv->link_info.num_rx_in4period[3] = + rtlpriv->link_info.num_rx_inperiod; + rtlpriv->link_info.num_tx_in4period[3] = + rtlpriv->link_info.num_tx_inperiod; + for (idx = 0; idx <= 3; idx++) { + rx_cnt_inp4eriod += + rtlpriv->link_info.num_rx_in4period[idx]; + tx_cnt_inp4eriod += + rtlpriv->link_info.num_tx_in4period[idx]; + } + aver_rx_cnt_inperiod = rx_cnt_inp4eriod / 4; + aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; + + /* (2) check traffic busy */ + if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) { + busytraffic = true; + if (aver_rx_cnt_inperiod > aver_tx_cnt_inperiod) + rx_busy_traffic = true; + else + tx_busy_traffic = false; + } + + /* Higher Tx/Rx data. */ + if (aver_rx_cnt_inperiod > 4000 || + aver_tx_cnt_inperiod > 4000) { + higher_busytraffic = true; + + /* Extremely high Rx data. */ + if (aver_rx_cnt_inperiod > 5000) + higher_busyrxtraffic = true; + } + + /* check every tid's tx traffic */ + for (tid = 0; tid <= 7; tid++) { + for (idx = 0; idx <= 2; idx++) + rtlpriv->link_info.tidtx_in4period[tid][idx] = + rtlpriv->link_info.tidtx_in4period[tid] + [idx + 1]; + rtlpriv->link_info.tidtx_in4period[tid][3] = + rtlpriv->link_info.tidtx_inperiod[tid]; + + for (idx = 0; idx <= 3; idx++) + tidtx_inp4eriod[tid] += + rtlpriv->link_info.tidtx_in4period[tid][idx]; + aver_tidtx_inperiod[tid] = tidtx_inp4eriod[tid] / 4; + if (aver_tidtx_inperiod[tid] > 5000) + rtlpriv->link_info.higher_busytxtraffic[tid] = + true; + else + rtlpriv->link_info.higher_busytxtraffic[tid] = + false; + } + + if (((rtlpriv->link_info.num_rx_inperiod + + rtlpriv->link_info.num_tx_inperiod) > 8) || + (rtlpriv->link_info.num_rx_inperiod > 2)) + rtl_lps_enter(hw); + else + rtl_lps_leave(hw); + } + + rtlpriv->link_info.num_rx_inperiod = 0; + rtlpriv->link_info.num_tx_inperiod = 0; + for (tid = 0; tid <= 7; tid++) + rtlpriv->link_info.tidtx_inperiod[tid] = 0; + + rtlpriv->link_info.busytraffic = busytraffic; + rtlpriv->link_info.higher_busytraffic = higher_busytraffic; + rtlpriv->link_info.rx_busy_traffic = rx_busy_traffic; + rtlpriv->link_info.tx_busy_traffic = tx_busy_traffic; + rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; + + /* <3> DM */ + if (!rtlpriv->cfg->mod_params->disable_watchdog) + rtlpriv->cfg->ops->dm_watchdog(hw); + + /* <4> roaming */ + if (mac->link_state == MAC80211_LINKED && + mac->opmode == NL80211_IFTYPE_STATION) { + if ((rtlpriv->link_info.bcn_rx_inperiod + + rtlpriv->link_info.num_rx_inperiod) == 0) { + rtlpriv->link_info.roam_times++; + RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, + "AP off for %d s\n", + (rtlpriv->link_info.roam_times * 2)); + + /* if we can't recv beacon for 10s, + * we should reconnect this AP + */ + if (rtlpriv->link_info.roam_times >= 5) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "AP off, try to reconnect now\n"); + rtlpriv->link_info.roam_times = 0; + ieee80211_connection_loss( + rtlpriv->mac80211.vif); + } + } else { + rtlpriv->link_info.roam_times = 0; + } + } + + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_periodical(rtlpriv); + + rtlpriv->link_info.bcn_rx_inperiod = 0; +} + +void rtl_watch_dog_timer_callback(unsigned long data) +{ + struct ieee80211_hw *hw = (struct ieee80211_hw *)data; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + queue_delayed_work(rtlpriv->works.rtl_wq, + &rtlpriv->works.watchdog_wq, 0); + + mod_timer(&rtlpriv->works.watchdog_timer, + jiffies + MSECS(RTL_WATCH_DOG_TIME)); +} +void rtl_fwevt_wq_callback(void *data) +{ + struct rtl_works *rtlworks = + container_of_dwork_rtl(data, struct rtl_works, fwevt_wq); + struct ieee80211_hw *hw = rtlworks->hw; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->cfg->ops->c2h_command_handle(hw); +} +void rtl_easy_concurrent_retrytimer_callback(unsigned long data) +{ + struct ieee80211_hw *hw = (struct ieee80211_hw *)data; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_priv *buddy_priv = rtlpriv->buddy_priv; + + if (buddy_priv == NULL) + return; + + rtlpriv->cfg->ops->dualmac_easy_concurrent(hw); +} +/********************************************************* + * + * frame process functions + * + *********************************************************/ +u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie) +{ + struct ieee80211_mgmt *mgmt = (void *)data; + u8 *pos, *end; + + pos = (u8 *)mgmt->u.beacon.variable; + end = data + len; + while (pos < end) { + if (pos + 2 + pos[1] > end) + return NULL; + + if (pos[0] == ie) + return pos; + + pos += 2 + pos[1]; + } + return NULL; +} + +/* when we use 2 rx ants we send IEEE80211_SMPS_OFF */ +/* when we use 1 rx ant we send IEEE80211_SMPS_STATIC */ +static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, + enum ieee80211_smps_mode smps, + u8 *da, u8 *bssid) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct sk_buff *skb; + struct ieee80211_mgmt *action_frame; + + /* 27 = header + category + action + smps mode */ + skb = dev_alloc_skb(27 + hw->extra_tx_headroom); + if (!skb) + return NULL; + + skb_reserve(skb, hw->extra_tx_headroom); + action_frame = (void *)skb_put(skb, 27); + memset(action_frame, 0, 27); + memcpy(action_frame->da, da, ETH_ALEN); + memcpy(action_frame->sa, rtlefuse->dev_addr, ETH_ALEN); + memcpy(action_frame->bssid, bssid, ETH_ALEN); + action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); + action_frame->u.action.category = WLAN_CATEGORY_HT; + action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS; + switch (smps) { + case IEEE80211_SMPS_AUTOMATIC:/* 0 */ + case IEEE80211_SMPS_NUM_MODES:/* 4 */ + WARN_ON(1); + /* Here will get a 'MISSING_BREAK' in Coverity Test, just ignore it. + * According to Kernel Code, here is right. + */ + case IEEE80211_SMPS_OFF:/* 1 */ /*MIMO_PS_NOLIMIT*/ + action_frame->u.action.u.ht_smps.smps_control = + WLAN_HT_SMPS_CONTROL_DISABLED;/* 0 */ + break; + case IEEE80211_SMPS_STATIC:/* 2 */ /*MIMO_PS_STATIC*/ + action_frame->u.action.u.ht_smps.smps_control = + WLAN_HT_SMPS_CONTROL_STATIC;/* 1 */ + break; + case IEEE80211_SMPS_DYNAMIC:/* 3 */ /*MIMO_PS_DYNAMIC*/ + action_frame->u.action.u.ht_smps.smps_control = + WLAN_HT_SMPS_CONTROL_DYNAMIC;/* 3 */ + break; + } + + return skb; +} + +int rtl_send_smps_action(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + enum ieee80211_smps_mode smps) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct sk_buff *skb = NULL; + struct rtl_tcb_desc tcb_desc; + u8 bssid[ETH_ALEN] = {0}; + + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + + if (rtlpriv->mac80211.act_scanning) + goto err_free; + + if (!sta) + goto err_free; + + if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) + goto err_free; + + if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) + goto err_free; + + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) + memcpy(bssid, rtlpriv->efuse.dev_addr, ETH_ALEN); + else + memcpy(bssid, rtlpriv->mac80211.bssid, ETH_ALEN); + + skb = rtl_make_smps_action(hw, smps, sta->addr, bssid); + /* this is a type = mgmt * stype = action frame */ + if (skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct rtl_sta_info *sta_entry = + (struct rtl_sta_info *) sta->drv_priv; + sta_entry->mimo_ps = smps; + /* rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); */ + + info->control.rates[0].idx = 0; + info->band = hw->conf.chandef.chan->band; + rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc); + } + return 1; + +err_free: + return 0; +} +EXPORT_SYMBOL(rtl_send_smps_action); + +void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + enum io_type iotype; + + if (!is_hal_stop(rtlhal)) { + switch (operation) { + case SCAN_OPT_BACKUP: + iotype = IO_CMD_PAUSE_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_IO_CMD, + (u8 *)&iotype); + break; + case SCAN_OPT_RESTORE: + iotype = IO_CMD_RESUME_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_IO_CMD, + (u8 *)&iotype); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Unknown Scan Backup operation.\n"); + break; + } + } +} +EXPORT_SYMBOL(rtl_phy_scan_operation_backup); + +/* because mac80211 have issues when can receive del ba + * so here we just make a fake del_ba if we receive a ba_req + * but rx_agg was opened to let mac80211 release some ba + * related resources, so please this del_ba for tx + */ +struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, + u8 *sa, u8 *bssid, u16 tid) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct sk_buff *skb; + struct ieee80211_mgmt *action_frame; + u16 params; + + /* 27 = header + category + action + smps mode */ + skb = dev_alloc_skb(34 + hw->extra_tx_headroom); + if (!skb) + return NULL; + + skb_reserve(skb, hw->extra_tx_headroom); + action_frame = (void *)skb_put(skb, 34); + memset(action_frame, 0, 34); + memcpy(action_frame->sa, sa, ETH_ALEN); + memcpy(action_frame->da, rtlefuse->dev_addr, ETH_ALEN); + memcpy(action_frame->bssid, bssid, ETH_ALEN); + action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); + action_frame->u.action.category = WLAN_CATEGORY_BACK; + action_frame->u.action.u.delba.action_code = WLAN_ACTION_DELBA; + params = (u16)(1 << 11); /* bit 11 initiator */ + params |= (u16)(tid << 12); /* bit 15:12 TID number */ + + action_frame->u.action.u.delba.params = cpu_to_le16(params); + action_frame->u.action.u.delba.reason_code = + cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); + + return skb; +} + +/********************************************************* + * + * IOT functions + * + *********************************************************/ +static bool rtl_chk_vendor_ouisub(struct ieee80211_hw *hw, + struct octet_string vendor_ie) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool matched = false; + static u8 athcap_1[] = { 0x00, 0x03, 0x7F }; + static u8 athcap_2[] = { 0x00, 0x13, 0x74 }; + static u8 broadcap_1[] = { 0x00, 0x10, 0x18 }; + static u8 broadcap_2[] = { 0x00, 0x0a, 0xf7 }; + static u8 broadcap_3[] = { 0x00, 0x05, 0xb5 }; + static u8 racap[] = { 0x00, 0x0c, 0x43 }; + static u8 ciscocap[] = { 0x00, 0x40, 0x96 }; + static u8 marvcap[] = { 0x00, 0x50, 0x43 }; + + if (memcmp(vendor_ie.octet, athcap_1, 3) == 0 || + memcmp(vendor_ie.octet, athcap_2, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_ATH; + matched = true; + } else if (memcmp(vendor_ie.octet, broadcap_1, 3) == 0 || + memcmp(vendor_ie.octet, broadcap_2, 3) == 0 || + memcmp(vendor_ie.octet, broadcap_3, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_BROAD; + matched = true; + } else if (memcmp(vendor_ie.octet, racap, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_RAL; + matched = true; + } else if (memcmp(vendor_ie.octet, ciscocap, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_CISCO; + matched = true; + } else if (memcmp(vendor_ie.octet, marvcap, 3) == 0) { + rtlpriv->mac80211.vendor = PEER_MARV; + matched = true; + } + + return matched; +} + +static bool rtl_find_221_ie(struct ieee80211_hw *hw, u8 *data, + unsigned int len) +{ + struct ieee80211_mgmt *mgmt = (void *)data; + struct octet_string vendor_ie; + u8 *pos, *end; + + pos = (u8 *)mgmt->u.beacon.variable; + end = data + len; + while (pos < end) { + if (pos[0] == 221) { + vendor_ie.length = pos[1]; + vendor_ie.octet = &pos[2]; + if (rtl_chk_vendor_ouisub(hw, vendor_ie)) + return true; + } + + if (pos + 2 + pos[1] > end) + return false; + + pos += 2 + pos[1]; + } + return false; +} + +void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct ieee80211_hdr *hdr = (void *)data; + u32 vendor = PEER_UNKNOWN; + + static u8 ap3_1[3] = { 0x00, 0x14, 0xbf }; + static u8 ap3_2[3] = { 0x00, 0x1a, 0x70 }; + static u8 ap3_3[3] = { 0x00, 0x1d, 0x7e }; + static u8 ap4_1[3] = { 0x00, 0x90, 0xcc }; + static u8 ap4_2[3] = { 0x00, 0x0e, 0x2e }; + static u8 ap4_3[3] = { 0x00, 0x18, 0x02 }; + static u8 ap4_4[3] = { 0x00, 0x17, 0x3f }; + static u8 ap4_5[3] = { 0x00, 0x1c, 0xdf }; + static u8 ap5_1[3] = { 0x00, 0x1c, 0xf0 }; + static u8 ap5_2[3] = { 0x00, 0x21, 0x91 }; + static u8 ap5_3[3] = { 0x00, 0x24, 0x01 }; + static u8 ap5_4[3] = { 0x00, 0x15, 0xe9 }; + static u8 ap5_5[3] = { 0x00, 0x17, 0x9A }; + static u8 ap5_6[3] = { 0x00, 0x18, 0xE7 }; + static u8 ap6_1[3] = { 0x00, 0x17, 0x94 }; + static u8 ap7_1[3] = { 0x00, 0x14, 0xa4 }; + + if (mac->opmode != NL80211_IFTYPE_STATION) + return; + + if (mac->link_state == MAC80211_NOLINK) { + mac->vendor = PEER_UNKNOWN; + return; + } + + if (mac->cnt_after_linked > 2) + return; + + /* check if this really is a beacon */ + if (!ieee80211_is_beacon(hdr->frame_control)) + return; + + /* min. beacon length + FCS_LEN */ + if (len <= 40 + FCS_LEN) + return; + + /* and only beacons from the associated BSSID, please */ + if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid)) + return; + + if (rtl_find_221_ie(hw, data, len)) + vendor = mac->vendor; + + if ((memcmp(mac->bssid, ap5_1, 3) == 0) || + (memcmp(mac->bssid, ap5_2, 3) == 0) || + (memcmp(mac->bssid, ap5_3, 3) == 0) || + (memcmp(mac->bssid, ap5_4, 3) == 0) || + (memcmp(mac->bssid, ap5_5, 3) == 0) || + (memcmp(mac->bssid, ap5_6, 3) == 0) || + vendor == PEER_ATH) { + vendor = PEER_ATH; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ath find\n"); + } else if ((memcmp(mac->bssid, ap4_4, 3) == 0) || + (memcmp(mac->bssid, ap4_5, 3) == 0) || + (memcmp(mac->bssid, ap4_1, 3) == 0) || + (memcmp(mac->bssid, ap4_2, 3) == 0) || + (memcmp(mac->bssid, ap4_3, 3) == 0) || + vendor == PEER_RAL) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ral find\n"); + vendor = PEER_RAL; + } else if (memcmp(mac->bssid, ap6_1, 3) == 0 || + vendor == PEER_CISCO) { + vendor = PEER_CISCO; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>cisco find\n"); + } else if ((memcmp(mac->bssid, ap3_1, 3) == 0) || + (memcmp(mac->bssid, ap3_2, 3) == 0) || + (memcmp(mac->bssid, ap3_3, 3) == 0) || + vendor == PEER_BROAD) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>broad find\n"); + vendor = PEER_BROAD; + } else if (memcmp(mac->bssid, ap7_1, 3) == 0 || + vendor == PEER_MARV) { + vendor = PEER_MARV; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>marv find\n"); + } + + mac->vendor = vendor; +} +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 "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); + +struct rtl_global_var rtl_global_var = {}; +EXPORT_SYMBOL_GPL(rtl_global_var); + +static int __init rtl_core_module_init(void) +{ + if (rtl_rate_control_register()) + pr_err("rtl: Unable to register rtl_rc, use default RC !!\n"); + + /* init some global vars */ + INIT_LIST_HEAD(&rtl_global_var.glb_priv_list); + spin_lock_init(&rtl_global_var.glb_list_lock); + + return 0; +} + +static void __exit rtl_core_module_exit(void) +{ + /*RC*/ + rtl_rate_control_unregister(); +} + +module_init(rtl_core_module_init); +module_exit(rtl_core_module_exit); diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h new file mode 100644 index 000000000000..74233d601a90 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/base.h @@ -0,0 +1,156 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL_BASE_H__ +#define __RTL_BASE_H__ + +enum ap_peer { + PEER_UNKNOWN = 0, + PEER_RTL = 1, + PEER_RTL_92SE = 2, + PEER_BROAD = 3, + PEER_RAL = 4, + PEER_ATH = 5, + PEER_CISCO = 6, + PEER_MARV = 7, + PEER_AIRGO = 9, + PEER_MAX = 10, +}; + +#define RTL_DUMMY_OFFSET 0 +#define RTL_DUMMY_UNIT 8 +#define RTL_TX_DUMMY_SIZE (RTL_DUMMY_OFFSET * RTL_DUMMY_UNIT) +#define RTL_TX_DESC_SIZE 32 +#define RTL_TX_HEADER_SIZE (RTL_TX_DESC_SIZE + RTL_TX_DUMMY_SIZE) + +#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */ +#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */ + +#define MAX_BIT_RATE_SHORT_GI_2NSS_80MHZ_MCS9 867 /* Mbps */ +#define MAX_BIT_RATE_SHORT_GI_2NSS_80MHZ_MCS7 650 /* Mbps */ +#define MAX_BIT_RATE_LONG_GI_2NSS_80MHZ_MCS9 780 /* Mbps */ +#define MAX_BIT_RATE_LONG_GI_2NSS_80MHZ_MCS7 585 /* Mbps */ + +#define MAX_BIT_RATE_SHORT_GI_1NSS_80MHZ_MCS9 434 /* Mbps */ +#define MAX_BIT_RATE_SHORT_GI_1NSS_80MHZ_MCS7 325 /* Mbps */ +#define MAX_BIT_RATE_LONG_GI_1NSS_80MHZ_MCS9 390 /* Mbps */ +#define MAX_BIT_RATE_LONG_GI_1NSS_80MHZ_MCS7 293 /* Mbps */ + +#define FRAME_OFFSET_FRAME_CONTROL 0 +#define FRAME_OFFSET_DURATION 2 +#define FRAME_OFFSET_ADDRESS1 4 +#define FRAME_OFFSET_ADDRESS2 10 +#define FRAME_OFFSET_ADDRESS3 16 +#define FRAME_OFFSET_SEQUENCE 22 +#define FRAME_OFFSET_ADDRESS4 24 + +#define SET_80211_HDR_FRAME_CONTROL(_hdr, _val) \ + WRITEEF2BYTE(_hdr, _val) +#define SET_80211_HDR_TYPE_AND_SUBTYPE(_hdr, _val) \ + WRITEEF1BYTE(_hdr, _val) +#define SET_80211_HDR_PWR_MGNT(_hdr, _val) \ + SET_BITS_TO_LE_2BYTE(_hdr, 12, 1, _val) +#define SET_80211_HDR_TO_DS(_hdr, _val) \ + SET_BITS_TO_LE_2BYTE(_hdr, 8, 1, _val) + +#define SET_80211_PS_POLL_AID(_hdr, _val) \ + (*(u16 *)((u8 *)(_hdr) + 2) = _val) +#define SET_80211_PS_POLL_BSSID(_hdr, _val) \ + ether_addr_copy(((u8 *)(_hdr)) + 4, (u8 *)(_val)) +#define SET_80211_PS_POLL_TA(_hdr, _val) \ + ether_addr_copy(((u8 *)(_hdr))+10, (u8 *)(_val)) + +#define SET_80211_HDR_DURATION(_hdr, _val) \ + (*(u16 *)((u8 *)(_hdr) + FRAME_OFFSET_DURATION) = le16_to_cpu(_val)) +#define SET_80211_HDR_ADDRESS1(_hdr, _val) \ + CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8 *)(_val)) +#define SET_80211_HDR_ADDRESS2(_hdr, _val) \ + CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS2, (u8 *)(_val)) +#define SET_80211_HDR_ADDRESS3(_hdr, _val) \ + CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val)) +#define SET_80211_HDR_FRAGMENT_SEQUENCE(_hdr, _val) \ + WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_SEQUENCE, _val) + +#define SET_BEACON_PROBE_RSP_TIME_STAMP_LOW(__phdr, __val) \ + WRITEEF4BYTE(((u8 *)(__phdr)) + 24, __val) +#define SET_BEACON_PROBE_RSP_TIME_STAMP_HIGH(__phdr, __val) \ + WRITEEF4BYTE(((u8 *)(__phdr)) + 28, __val) +#define SET_BEACON_PROBE_RSP_BEACON_INTERVAL(__phdr, __val) \ + WRITEEF2BYTE(((u8 *)(__phdr)) + 32, __val) +#define GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) \ + READEF2BYTE(((u8 *)(__phdr)) + 34) +#define SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ + WRITEEF2BYTE(((u8 *)(__phdr)) + 34, __val) +#define MASK_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ + SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, \ + (GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) & (~(__val)))) + +int rtl_init_core(struct ieee80211_hw *hw); +void rtl_deinit_core(struct ieee80211_hw *hw); +void rtl_init_rx_config(struct ieee80211_hw *hw); +void rtl_init_rfkill(struct ieee80211_hw *hw); +void rtl_deinit_rfkill(struct ieee80211_hw *hw); + +void rtl_watch_dog_timer_callback(unsigned long data); +void rtl_deinit_deferred_work(struct ieee80211_hw *hw); + +bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); +int rtlwifi_rate_mapping(struct ieee80211_hw *hw, bool isht, + bool isvht, u8 desc_rate); +bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); +u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx, + bool is_enc); + +void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb); +int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, u16 tid, u16 *ssn); +int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, u16 tid); +int rtl_tx_agg_oper(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tid); +int rtl_rx_agg_start(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tid); +int rtl_rx_agg_stop(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u16 tid); +void rtl_watchdog_wq_callback(void *data); +void rtl_fwevt_wq_callback(void *data); + +void rtl_get_tcb_desc(struct ieee80211_hw *hw, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); + +int rtl_send_smps_action(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + enum ieee80211_smps_mode smps); +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); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/Makefile b/drivers/net/wireless/realtek/rtlwifi/btcoexist/Makefile new file mode 100644 index 000000000000..47ceecfcb7dc --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/Makefile @@ -0,0 +1,7 @@ +btcoexist-objs := halbtc8723b2ant.o \ + halbtcoutsrc.o \ + rtl_btc.o + +obj-$(CONFIG_RTLBTCOEXIST) += btcoexist.o + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h new file mode 100644 index 000000000000..39b9a3309cfd --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbt_precomp.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * Larry Finger + * + ******************************************************************************/ + +#ifndef __HALBT_PRECOMP_H__ +#define __HALBT_PRECOMP_H__ +/************************************************************* + * include files + *************************************************************/ +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../regd.h" +#include "../cam.h" +#include "../ps.h" +#include "../pci.h" + +#include "halbtcoutsrc.h" + +#include "halbtc8192e2ant.h" +#include "halbtc8723b1ant.h" +#include "halbtc8723b2ant.h" +#include "halbtc8821a2ant.h" +#include "halbtc8821a1ant.h" + +#define GetDefaultAdapter(padapter) padapter + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#endif /* __HALBT_PRECOMP_H__ */ diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c new file mode 100644 index 000000000000..53261d6f8578 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c @@ -0,0 +1,3849 @@ +/****************************************************************************** + * + * Copyright(c) 2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +/************************************************************** + * Description: + * + * This file is for RTL8192E Co-exist mechanism + * + * History + * 2012/11/15 Cosa first check in. + * + **************************************************************/ + +/************************************************************** + * include files + **************************************************************/ +#include "halbt_precomp.h" +/************************************************************** + * Global variables, these are static variables + **************************************************************/ +static struct coex_dm_8192e_2ant glcoex_dm_8192e_2ant; +static struct coex_dm_8192e_2ant *coex_dm = &glcoex_dm_8192e_2ant; +static struct coex_sta_8192e_2ant glcoex_sta_8192e_2ant; +static struct coex_sta_8192e_2ant *coex_sta = &glcoex_sta_8192e_2ant; + +static const char *const GLBtInfoSrc8192e2Ant[] = { + "BT Info[wifi fw]", + "BT Info[bt rsp]", + "BT Info[bt auto report]", +}; + +static u32 glcoex_ver_date_8192e_2ant = 20130902; +static u32 glcoex_ver_8192e_2ant = 0x34; + +/************************************************************** + * local function proto type if needed + **************************************************************/ +/************************************************************** + * local function start with halbtc8192e2ant_ + **************************************************************/ +static u8 halbtc8192e2ant_btrssi_state(u8 level_num, u8 rssi_thresh, + u8 rssi_thresh1) +{ + int btrssi = 0; + u8 btrssi_state = coex_sta->pre_bt_rssi_state; + + btrssi = coex_sta->bt_rssi; + + if (level_num == 2) { + if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || + (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi pre state = LOW\n"); + if (btrssi >= (rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { + btrssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi state switch to High\n"); + } else { + btrssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi state stay at Low\n"); + } + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi pre state = HIGH\n"); + if (btrssi < rssi_thresh) { + btrssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi state switch to Low\n"); + } else { + btrssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi state stay at High\n"); + } + } + } else if (level_num == 3) { + if (rssi_thresh > rssi_thresh1) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi thresh error!!\n"); + return coex_sta->pre_bt_rssi_state; + } + + if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || + (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi pre state = LOW\n"); + if (btrssi >= (rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { + btrssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi state switch to Medium\n"); + } else { + btrssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi state stay at Low\n"); + } + } else if ((coex_sta->pre_bt_rssi_state == + BTC_RSSI_STATE_MEDIUM) || + (coex_sta->pre_bt_rssi_state == + BTC_RSSI_STATE_STAY_MEDIUM)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi pre state = MEDIUM\n"); + if (btrssi >= (rssi_thresh1 + + BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { + btrssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi state switch to High\n"); + } else if (btrssi < rssi_thresh) { + btrssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi state switch to Low\n"); + } else { + btrssi_state = BTC_RSSI_STATE_STAY_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi state stay at Medium\n"); + } + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi pre state = HIGH\n"); + if (btrssi < rssi_thresh1) { + btrssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi state switch to Medium\n"); + } else { + btrssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "BT Rssi state stay at High\n"); + } + } + } + + coex_sta->pre_bt_rssi_state = btrssi_state; + + return btrssi_state; +} + +static u8 halbtc8192e2ant_wifirssi_state(struct btc_coexist *btcoexist, + u8 index, u8 level_num, u8 rssi_thresh, + u8 rssi_thresh1) +{ + int wifirssi = 0; + u8 wifirssi_state = coex_sta->pre_wifi_rssi_state[index]; + + btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifirssi); + + if (level_num == 2) { + if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_LOW) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_LOW)) { + if (wifirssi >= (rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { + wifirssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "wifi RSSI state switch to High\n"); + } else { + wifirssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "wifi RSSI state stay at Low\n"); + } + } else { + if (wifirssi < rssi_thresh) { + wifirssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "wifi RSSI state switch to Low\n"); + } else { + wifirssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "wifi RSSI state stay at High\n"); + } + } + } else if (level_num == 3) { + if (rssi_thresh > rssi_thresh1) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, + "wifi RSSI thresh error!!\n"); + return coex_sta->pre_wifi_rssi_state[index]; + } + + if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_LOW) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_LOW)) { + if (wifirssi >= (rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { + wifirssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "wifi RSSI state switch to Medium\n"); + } else { + wifirssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "wifi RSSI state stay at Low\n"); + } + } else if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_MEDIUM) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_MEDIUM)) { + if (wifirssi >= (rssi_thresh1 + + BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { + wifirssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "wifi RSSI state switch to High\n"); + } else if (wifirssi < rssi_thresh) { + wifirssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "wifi RSSI state switch to Low\n"); + } else { + wifirssi_state = BTC_RSSI_STATE_STAY_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "wifi RSSI state stay at Medium\n"); + } + } else { + if (wifirssi < rssi_thresh1) { + wifirssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "wifi RSSI state switch to Medium\n"); + } else { + wifirssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "wifi RSSI state stay at High\n"); + } + } + } + + coex_sta->pre_wifi_rssi_state[index] = wifirssi_state; + + return wifirssi_state; +} + +static void btc8192e2ant_monitor_bt_enable_dis(struct btc_coexist *btcoexist) +{ + static bool pre_bt_disabled; + static u32 bt_disable_cnt; + bool bt_active = true, bt_disabled = false; + + /* This function check if bt is disabled */ + + if (coex_sta->high_priority_tx == 0 && + coex_sta->high_priority_rx == 0 && + coex_sta->low_priority_tx == 0 && + coex_sta->low_priority_rx == 0) + bt_active = false; + + if (coex_sta->high_priority_tx == 0xffff && + coex_sta->high_priority_rx == 0xffff && + coex_sta->low_priority_tx == 0xffff && + coex_sta->low_priority_rx == 0xffff) + bt_active = false; + + if (bt_active) { + bt_disable_cnt = 0; + bt_disabled = false; + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, + &bt_disabled); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], BT is enabled !!\n"); + } else { + bt_disable_cnt++; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], bt all counters = 0, %d times!!\n", + bt_disable_cnt); + if (bt_disable_cnt >= 2) { + bt_disabled = true; + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, + &bt_disabled); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], BT is disabled !!\n"); + } + } + if (pre_bt_disabled != bt_disabled) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], BT is from %s to %s!!\n", + (pre_bt_disabled ? "disabled" : "enabled"), + (bt_disabled ? "disabled" : "enabled")); + pre_bt_disabled = bt_disabled; + } +} + +static u32 halbtc8192e2ant_decidera_mask(struct btc_coexist *btcoexist, + u8 sstype, u32 ra_masktype) +{ + u32 disra_mask = 0x0; + + switch (ra_masktype) { + case 0: /* normal mode */ + if (sstype == 2) + disra_mask = 0x0; /* enable 2ss */ + else + disra_mask = 0xfff00000;/* disable 2ss */ + break; + case 1: /* disable cck 1/2 */ + if (sstype == 2) + disra_mask = 0x00000003;/* enable 2ss */ + else + disra_mask = 0xfff00003;/* disable 2ss */ + break; + case 2: /* disable cck 1/2/5.5, ofdm 6/9/12/18/24, mcs 0/1/2/3/4 */ + if (sstype == 2) + disra_mask = 0x0001f1f7;/* enable 2ss */ + else + disra_mask = 0xfff1f1f7;/* disable 2ss */ + break; + default: + break; + } + + return disra_mask; +} + +static void halbtc8192e2ant_Updatera_mask(struct btc_coexist *btcoexist, + bool force_exec, u32 dis_ratemask) +{ + coex_dm->curra_mask = dis_ratemask; + + if (force_exec || (coex_dm->prera_mask != coex_dm->curra_mask)) + btcoexist->btc_set(btcoexist, BTC_SET_ACT_UPDATE_ra_mask, + &coex_dm->curra_mask); + coex_dm->prera_mask = coex_dm->curra_mask; +} + +static void btc8192e2ant_autorate_fallback_retry(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + bool wifi_under_bmode = false; + + coex_dm->cur_arfrtype = type; + + if (force_exec || (coex_dm->pre_arfrtype != coex_dm->cur_arfrtype)) { + switch (coex_dm->cur_arfrtype) { + case 0: /* normal mode */ + btcoexist->btc_write_4byte(btcoexist, 0x430, + coex_dm->backup_arfr_cnt1); + btcoexist->btc_write_4byte(btcoexist, 0x434, + coex_dm->backup_arfr_cnt2); + break; + case 1: + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_UNDER_B_MODE, + &wifi_under_bmode); + if (wifi_under_bmode) { + btcoexist->btc_write_4byte(btcoexist, 0x430, + 0x0); + btcoexist->btc_write_4byte(btcoexist, 0x434, + 0x01010101); + } else { + btcoexist->btc_write_4byte(btcoexist, 0x430, + 0x0); + btcoexist->btc_write_4byte(btcoexist, 0x434, + 0x04030201); + } + break; + default: + break; + } + } + + coex_dm->pre_arfrtype = coex_dm->cur_arfrtype; +} + +static void halbtc8192e2ant_retrylimit(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + coex_dm->cur_retrylimit_type = type; + + if (force_exec || (coex_dm->pre_retrylimit_type != + coex_dm->cur_retrylimit_type)) { + switch (coex_dm->cur_retrylimit_type) { + case 0: /* normal mode */ + btcoexist->btc_write_2byte(btcoexist, 0x42a, + coex_dm->backup_retrylimit); + break; + case 1: /* retry limit = 8 */ + btcoexist->btc_write_2byte(btcoexist, 0x42a, + 0x0808); + break; + default: + break; + } + } + + coex_dm->pre_retrylimit_type = coex_dm->cur_retrylimit_type; +} + +static void halbtc8192e2ant_ampdu_maxtime(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + coex_dm->cur_ampdutime_type = type; + + if (force_exec || (coex_dm->pre_ampdutime_type != + coex_dm->cur_ampdutime_type)) { + switch (coex_dm->cur_ampdutime_type) { + case 0: /* normal mode */ + btcoexist->btc_write_1byte(btcoexist, 0x456, + coex_dm->backup_ampdu_maxtime); + break; + case 1: /* AMPDU timw = 0x38 * 32us */ + btcoexist->btc_write_1byte(btcoexist, 0x456, 0x38); + break; + default: + break; + } + } + + coex_dm->pre_ampdutime_type = coex_dm->cur_ampdutime_type; +} + +static void halbtc8192e2ant_limited_tx(struct btc_coexist *btcoexist, + bool force_exec, u8 ra_masktype, + u8 arfr_type, u8 retrylimit_type, + u8 ampdutime_type) +{ + u32 disra_mask = 0x0; + + coex_dm->curra_masktype = ra_masktype; + disra_mask = halbtc8192e2ant_decidera_mask(btcoexist, + coex_dm->cur_sstype, + ra_masktype); + halbtc8192e2ant_Updatera_mask(btcoexist, force_exec, disra_mask); +btc8192e2ant_autorate_fallback_retry(btcoexist, force_exec, arfr_type); + halbtc8192e2ant_retrylimit(btcoexist, force_exec, retrylimit_type); + halbtc8192e2ant_ampdu_maxtime(btcoexist, force_exec, ampdutime_type); +} + +static void halbtc8192e2ant_limited_rx(struct btc_coexist *btcoexist, + bool force_exec, bool rej_ap_agg_pkt, + bool bt_ctrl_agg_buf_size, + u8 agg_buf_size) +{ + bool reject_rx_agg = rej_ap_agg_pkt; + bool bt_ctrl_rx_agg_size = bt_ctrl_agg_buf_size; + u8 rx_agg_size = agg_buf_size; + + /********************************************* + * Rx Aggregation related setting + *********************************************/ + btcoexist->btc_set(btcoexist, BTC_SET_BL_TO_REJ_AP_AGG_PKT, + &reject_rx_agg); + /* decide BT control aggregation buf size or not */ + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_CTRL_AGG_SIZE, + &bt_ctrl_rx_agg_size); + /* aggregation buf size, only work + * when BT control Rx aggregation size. + */ + btcoexist->btc_set(btcoexist, BTC_SET_U1_AGG_BUF_SIZE, &rx_agg_size); + /* real update aggregation setting */ + btcoexist->btc_set(btcoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL); +} + +static void halbtc8192e2ant_monitor_bt_ctr(struct btc_coexist *btcoexist) +{ + u32 reg_hp_txrx, reg_lp_txrx, u32tmp; + u32 reg_hp_tx = 0, reg_hp_rx = 0, reg_lp_tx = 0, reg_lp_rx = 0; + + reg_hp_txrx = 0x770; + reg_lp_txrx = 0x774; + + u32tmp = btcoexist->btc_read_4byte(btcoexist, reg_hp_txrx); + reg_hp_tx = u32tmp & MASKLWORD; + reg_hp_rx = (u32tmp & MASKHWORD)>>16; + + u32tmp = btcoexist->btc_read_4byte(btcoexist, reg_lp_txrx); + reg_lp_tx = u32tmp & MASKLWORD; + reg_lp_rx = (u32tmp & MASKHWORD)>>16; + + coex_sta->high_priority_tx = reg_hp_tx; + coex_sta->high_priority_rx = reg_hp_rx; + coex_sta->low_priority_tx = reg_lp_tx; + coex_sta->low_priority_rx = reg_lp_rx; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex] High Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", + reg_hp_txrx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex] Low Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", + reg_lp_txrx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); + + /* reset counter */ + btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); +} + +static void halbtc8192e2ant_querybt_info(struct btc_coexist *btcoexist) +{ + u8 h2c_parameter[1] = {0}; + + coex_sta->c2h_bt_info_req_sent = true; + + h2c_parameter[0] |= BIT0; /* trigger */ + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", + h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); +} + +static void halbtc8192e2ant_update_btlink_info(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool bt_hson = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hson); + + bt_link_info->bt_link_exist = coex_sta->bt_link_exist; + bt_link_info->sco_exist = coex_sta->sco_exist; + bt_link_info->a2dp_exist = coex_sta->a2dp_exist; + bt_link_info->pan_exist = coex_sta->pan_exist; + bt_link_info->hid_exist = coex_sta->hid_exist; + + /* work around for HS mode. */ + if (bt_hson) { + bt_link_info->pan_exist = true; + bt_link_info->bt_link_exist = true; + } + + /* check if Sco only */ + if (bt_link_info->sco_exist && + !bt_link_info->a2dp_exist && + !bt_link_info->pan_exist && + !bt_link_info->hid_exist) + bt_link_info->sco_only = true; + else + bt_link_info->sco_only = false; + + /* check if A2dp only */ + if (!bt_link_info->sco_exist && + bt_link_info->a2dp_exist && + !bt_link_info->pan_exist && + !bt_link_info->hid_exist) + bt_link_info->a2dp_only = true; + else + bt_link_info->a2dp_only = false; + + /* check if Pan only */ + if (!bt_link_info->sco_exist && + !bt_link_info->a2dp_exist && + bt_link_info->pan_exist && + !bt_link_info->hid_exist) + bt_link_info->pan_only = true; + else + bt_link_info->pan_only = false; + + /* check if Hid only */ + if (!bt_link_info->sco_exist && + !bt_link_info->a2dp_exist && + !bt_link_info->pan_exist && + bt_link_info->hid_exist) + bt_link_info->hid_only = true; + else + bt_link_info->hid_only = false; +} + +static u8 halbtc8192e2ant_action_algorithm(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + struct btc_stack_info *stack_info = &btcoexist->stack_info; + bool bt_hson = false; + u8 algorithm = BT_8192E_2ANT_COEX_ALGO_UNDEFINED; + u8 numdiffprofile = 0; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hson); + + if (!bt_link_info->bt_link_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "No BT link exists!!!\n"); + return algorithm; + } + + if (bt_link_info->sco_exist) + numdiffprofile++; + if (bt_link_info->hid_exist) + numdiffprofile++; + if (bt_link_info->pan_exist) + numdiffprofile++; + if (bt_link_info->a2dp_exist) + numdiffprofile++; + + if (numdiffprofile == 1) { + if (bt_link_info->sco_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "SCO only\n"); + algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; + } else { + if (bt_link_info->hid_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "HID only\n"); + algorithm = BT_8192E_2ANT_COEX_ALGO_HID; + } else if (bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "A2DP only\n"); + algorithm = BT_8192E_2ANT_COEX_ALGO_A2DP; + } else if (bt_link_info->pan_exist) { + if (bt_hson) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "PAN(HS) only\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_PANHS; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "PAN(EDR) only\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_PANEDR; + } + } + } + } else if (numdiffprofile == 2) { + if (bt_link_info->sco_exist) { + if (bt_link_info->hid_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "SCO + HID\n"); + algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; + } else if (bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "SCO + A2DP ==> SCO\n"); + algorithm = BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; + } else if (bt_link_info->pan_exist) { + if (bt_hson) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "SCO + PAN(HS)\n"); + algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "SCO + PAN(EDR)\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_SCO_PAN; + } + } + } else { + if (bt_link_info->hid_exist && + bt_link_info->a2dp_exist) { + if (stack_info->num_of_hid >= 2) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "HID*2 + A2DP\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_HID_A2DP_PANEDR; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "HID + A2DP\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_HID_A2DP; + } + } else if (bt_link_info->hid_exist && + bt_link_info->pan_exist) { + if (bt_hson) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "HID + PAN(HS)\n"); + algorithm = BT_8192E_2ANT_COEX_ALGO_HID; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "HID + PAN(EDR)\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; + } + } else if (bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hson) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "A2DP + PAN(HS)\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_A2DP_PANHS; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "A2DP + PAN(EDR)\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_PANEDR_A2DP; + } + } + } + } else if (numdiffprofile == 3) { + if (bt_link_info->sco_exist) { + if (bt_link_info->hid_exist && + bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "SCO + HID + A2DP ==> HID\n"); + algorithm = BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; + } else if (bt_link_info->hid_exist && + bt_link_info->pan_exist) { + if (bt_hson) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "SCO + HID + PAN(HS)\n"); + algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "SCO + HID + PAN(EDR)\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_SCO_PAN; + } + } else if (bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hson) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "SCO + A2DP + PAN(HS)\n"); + algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "SCO + A2DP + PAN(EDR)\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; + } + } + } else { + if (bt_link_info->hid_exist && + bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hson) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "HID + A2DP + PAN(HS)\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_HID_A2DP; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "HID + A2DP + PAN(EDR)\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_HID_A2DP_PANEDR; + } + } + } + } else if (numdiffprofile >= 3) { + if (bt_link_info->sco_exist) { + if (bt_link_info->hid_exist && + bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hson) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "ErrorSCO+HID+A2DP+PAN(HS)\n"); + + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "SCO+HID+A2DP+PAN(EDR)\n"); + algorithm = + BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; + } + } + } + } + + return algorithm; +} + +static void halbtc8192e2ant_setfw_dac_swinglevel(struct btc_coexist *btcoexist, + u8 dac_swinglvl) +{ + u8 h2c_parameter[1] = {0}; + + /* There are several type of dacswing + * 0x18/ 0x10/ 0xc/ 0x8/ 0x4/ 0x6 + */ + h2c_parameter[0] = dac_swinglvl; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], Set Dac Swing Level = 0x%x\n", dac_swinglvl); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x64 = 0x%x\n", h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x64, 1, h2c_parameter); +} + +static void halbtc8192e2ant_set_fwdec_btpwr(struct btc_coexist *btcoexist, + u8 dec_btpwr_lvl) +{ + u8 h2c_parameter[1] = {0}; + + h2c_parameter[0] = dec_btpwr_lvl; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex] decrease Bt Power level = %d, FW write 0x62 = 0x%x\n", + dec_btpwr_lvl, h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x62, 1, h2c_parameter); +} + +static void halbtc8192e2ant_dec_btpwr(struct btc_coexist *btcoexist, + bool force_exec, u8 dec_btpwr_lvl) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s Dec BT power level = %d\n", + (force_exec ? "force to" : ""), dec_btpwr_lvl); + coex_dm->cur_dec_bt_pwr = dec_btpwr_lvl; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], preBtDecPwrLvl=%d, curBtDecPwrLvl=%d\n", + coex_dm->pre_dec_bt_pwr, coex_dm->cur_dec_bt_pwr); + } + halbtc8192e2ant_set_fwdec_btpwr(btcoexist, coex_dm->cur_dec_bt_pwr); + + coex_dm->pre_dec_bt_pwr = coex_dm->cur_dec_bt_pwr; +} + +static void halbtc8192e2ant_set_bt_autoreport(struct btc_coexist *btcoexist, + bool enable_autoreport) +{ + u8 h2c_parameter[1] = {0}; + + h2c_parameter[0] = 0; + + if (enable_autoreport) + h2c_parameter[0] |= BIT0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], BT FW auto report : %s, FW write 0x68 = 0x%x\n", + (enable_autoreport ? "Enabled!!" : "Disabled!!"), + h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter); +} + +static void halbtc8192e2ant_bt_autoreport(struct btc_coexist *btcoexist, + bool force_exec, + bool enable_autoreport) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s BT Auto report = %s\n", + (force_exec ? "force to" : ""), + ((enable_autoreport) ? "Enabled" : "Disabled")); + coex_dm->cur_bt_auto_report = enable_autoreport; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex] bPreBtAutoReport=%d, bCurBtAutoReport=%d\n", + coex_dm->pre_bt_auto_report, + coex_dm->cur_bt_auto_report); + + if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report) + return; + } + halbtc8192e2ant_set_bt_autoreport(btcoexist, + coex_dm->cur_bt_auto_report); + + coex_dm->pre_bt_auto_report = coex_dm->cur_bt_auto_report; +} + +static void halbtc8192e2ant_fw_dac_swinglvl(struct btc_coexist *btcoexist, + bool force_exec, u8 fw_dac_swinglvl) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s set FW Dac Swing level = %d\n", + (force_exec ? "force to" : ""), fw_dac_swinglvl); + coex_dm->cur_fw_dac_swing_lvl = fw_dac_swinglvl; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex] preFwDacSwingLvl=%d, curFwDacSwingLvl=%d\n", + coex_dm->pre_fw_dac_swing_lvl, + coex_dm->cur_fw_dac_swing_lvl); + + if (coex_dm->pre_fw_dac_swing_lvl == + coex_dm->cur_fw_dac_swing_lvl) + return; + } + + halbtc8192e2ant_setfw_dac_swinglevel(btcoexist, + coex_dm->cur_fw_dac_swing_lvl); + + coex_dm->pre_fw_dac_swing_lvl = coex_dm->cur_fw_dac_swing_lvl; +} + +static void btc8192e2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, + bool rx_rf_shrink_on) +{ + if (rx_rf_shrink_on) { + /* Shrink RF Rx LPF corner */ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Shrink RF Rx LPF corner!!\n"); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, + 0xfffff, 0xffffc); + } else { + /* Resume RF Rx LPF corner + * After initialized, we can use coex_dm->btRf0x1eBackup + */ + if (btcoexist->initilized) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Resume RF Rx LPF corner!!\n"); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, + 0xfffff, + coex_dm->bt_rf0x1e_backup); + } + } +} + +static void halbtc8192e2ant_rf_shrink(struct btc_coexist *btcoexist, + bool force_exec, bool rx_rf_shrink_on) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s turn Rx RF Shrink = %s\n", + (force_exec ? "force to" : ""), + ((rx_rf_shrink_on) ? "ON" : "OFF")); + coex_dm->cur_rf_rx_lpf_shrink = rx_rf_shrink_on; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex]bPreRfRxLpfShrink=%d,bCurRfRxLpfShrink=%d\n", + coex_dm->pre_rf_rx_lpf_shrink, + coex_dm->cur_rf_rx_lpf_shrink); + + if (coex_dm->pre_rf_rx_lpf_shrink == + coex_dm->cur_rf_rx_lpf_shrink) + return; + } + btc8192e2ant_set_sw_rf_rx_lpf_corner(btcoexist, + coex_dm->cur_rf_rx_lpf_shrink); + + coex_dm->pre_rf_rx_lpf_shrink = coex_dm->cur_rf_rx_lpf_shrink; +} + +static void halbtc8192e2ant_set_dac_swingreg(struct btc_coexist *btcoexist, + u32 level) +{ + u8 val = (u8)level; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Write SwDacSwing = 0x%x\n", level); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x883, 0x3e, val); +} + +static void btc8192e2ant_setsw_full_swing(struct btc_coexist *btcoexist, + bool sw_dac_swingon, + u32 sw_dac_swinglvl) +{ + if (sw_dac_swingon) + halbtc8192e2ant_set_dac_swingreg(btcoexist, sw_dac_swinglvl); + else + halbtc8192e2ant_set_dac_swingreg(btcoexist, 0x18); +} + +static void halbtc8192e2ant_DacSwing(struct btc_coexist *btcoexist, + bool force_exec, bool dac_swingon, + u32 dac_swinglvl) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s turn DacSwing=%s, dac_swinglvl = 0x%x\n", + (force_exec ? "force to" : ""), + ((dac_swingon) ? "ON" : "OFF"), dac_swinglvl); + coex_dm->cur_dac_swing_on = dac_swingon; + coex_dm->cur_dac_swing_lvl = dac_swinglvl; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], bPreDacSwingOn=%d, preDacSwingLvl = 0x%x, ", + coex_dm->pre_dac_swing_on, + coex_dm->pre_dac_swing_lvl); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "bCurDacSwingOn=%d, curDacSwingLvl = 0x%x\n", + coex_dm->cur_dac_swing_on, + coex_dm->cur_dac_swing_lvl); + + if ((coex_dm->pre_dac_swing_on == coex_dm->cur_dac_swing_on) && + (coex_dm->pre_dac_swing_lvl == coex_dm->cur_dac_swing_lvl)) + return; + } + mdelay(30); + btc8192e2ant_setsw_full_swing(btcoexist, dac_swingon, dac_swinglvl); + + coex_dm->pre_dac_swing_on = coex_dm->cur_dac_swing_on; + coex_dm->pre_dac_swing_lvl = coex_dm->cur_dac_swing_lvl; +} + +static void halbtc8192e2ant_set_agc_table(struct btc_coexist *btcoexist, + bool agc_table_en) +{ + /* BB AGC Gain Table */ + if (agc_table_en) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], BB Agc Table On!\n"); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x0a1A0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x091B0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x081C0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x071D0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x061E0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x051F0001); + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], BB Agc Table Off!\n"); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xaa1A0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa91B0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa81C0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa71D0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa61E0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa51F0001); + } +} + +static void halbtc8192e2ant_AgcTable(struct btc_coexist *btcoexist, + bool force_exec, bool agc_table_en) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s %s Agc Table\n", + (force_exec ? "force to" : ""), + ((agc_table_en) ? "Enable" : "Disable")); + coex_dm->cur_agc_table_en = agc_table_en; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], bPreAgcTableEn=%d, bCurAgcTableEn=%d\n", + coex_dm->pre_agc_table_en, coex_dm->cur_agc_table_en); + + if (coex_dm->pre_agc_table_en == coex_dm->cur_agc_table_en) + return; + } + halbtc8192e2ant_set_agc_table(btcoexist, agc_table_en); + + coex_dm->pre_agc_table_en = coex_dm->cur_agc_table_en; +} + +static void halbtc8192e2ant_set_coex_table(struct btc_coexist *btcoexist, + u32 val0x6c0, u32 val0x6c4, + u32 val0x6c8, u8 val0x6cc) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); + btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); + btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); + btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); + btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); +} + +static void halbtc8192e2ant_coex_table(struct btc_coexist *btcoexist, + bool force_exec, + u32 val0x6c0, u32 val0x6c4, + u32 val0x6c8, u8 val0x6cc) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, ", + (force_exec ? "force to" : ""), val0x6c0); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", + val0x6c4, val0x6c8, val0x6cc); + coex_dm->cur_val0x6c0 = val0x6c0; + coex_dm->cur_val0x6c4 = val0x6c4; + coex_dm->cur_val0x6c8 = val0x6c8; + coex_dm->cur_val0x6cc = val0x6cc; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], preVal0x6c0 = 0x%x, preVal0x6c4 = 0x%x, ", + coex_dm->pre_val0x6c0, coex_dm->pre_val0x6c4); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "preVal0x6c8 = 0x%x, preVal0x6cc = 0x%x !!\n", + coex_dm->pre_val0x6c8, coex_dm->pre_val0x6cc); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], curVal0x6c0 = 0x%x, curVal0x6c4 = 0x%x,\n", + coex_dm->cur_val0x6c0, coex_dm->cur_val0x6c4); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "curVal0x6c8 = 0x%x, curVal0x6cc = 0x%x !!\n", + coex_dm->cur_val0x6c8, coex_dm->cur_val0x6cc); + + if ((coex_dm->pre_val0x6c0 == coex_dm->cur_val0x6c0) && + (coex_dm->pre_val0x6c4 == coex_dm->cur_val0x6c4) && + (coex_dm->pre_val0x6c8 == coex_dm->cur_val0x6c8) && + (coex_dm->pre_val0x6cc == coex_dm->cur_val0x6cc)) + return; + } + halbtc8192e2ant_set_coex_table(btcoexist, val0x6c0, val0x6c4, + val0x6c8, val0x6cc); + + coex_dm->pre_val0x6c0 = coex_dm->cur_val0x6c0; + coex_dm->pre_val0x6c4 = coex_dm->cur_val0x6c4; + coex_dm->pre_val0x6c8 = coex_dm->cur_val0x6c8; + coex_dm->pre_val0x6cc = coex_dm->cur_val0x6cc; +} + +static void btc8192e2ant_coex_tbl_w_type(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + switch (type) { + case 0: + halbtc8192e2ant_coex_table(btcoexist, force_exec, 0x55555555, + 0x5a5a5a5a, 0xffffff, 0x3); + break; + case 1: + halbtc8192e2ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a, + 0x5a5a5a5a, 0xffffff, 0x3); + break; + case 2: + halbtc8192e2ant_coex_table(btcoexist, force_exec, 0x55555555, + 0x5ffb5ffb, 0xffffff, 0x3); + break; + case 3: + halbtc8192e2ant_coex_table(btcoexist, force_exec, 0xdfffdfff, + 0x5fdb5fdb, 0xffffff, 0x3); + break; + case 4: + halbtc8192e2ant_coex_table(btcoexist, force_exec, 0xdfffdfff, + 0x5ffb5ffb, 0xffffff, 0x3); + break; + default: + break; + } +} + +static void halbtc8192e2ant_set_fw_ignore_wlanact(struct btc_coexist *btcoexist, + bool enable) +{ + u8 h2c_parameter[1] = {0}; + + if (enable) + h2c_parameter[0] |= BIT0; /* function enable */ + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex]set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", + h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); +} + +static void halbtc8192e2ant_IgnoreWlanAct(struct btc_coexist *btcoexist, + bool force_exec, bool enable) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s turn Ignore WlanAct %s\n", + (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); + coex_dm->cur_ignore_wlan_act = enable; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], bPreIgnoreWlanAct = %d ", + coex_dm->pre_ignore_wlan_act); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "bCurIgnoreWlanAct = %d!!\n", + coex_dm->cur_ignore_wlan_act); + + if (coex_dm->pre_ignore_wlan_act == + coex_dm->cur_ignore_wlan_act) + return; + } + halbtc8192e2ant_set_fw_ignore_wlanact(btcoexist, enable); + + coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; +} + +static void halbtc8192e2ant_SetFwPstdma(struct btc_coexist *btcoexist, u8 byte1, + u8 byte2, u8 byte3, u8 byte4, u8 byte5) +{ + u8 h2c_parameter[5] = {0}; + + h2c_parameter[0] = byte1; + h2c_parameter[1] = byte2; + h2c_parameter[2] = byte3; + h2c_parameter[3] = byte4; + h2c_parameter[4] = byte5; + + coex_dm->ps_tdma_para[0] = byte1; + coex_dm->ps_tdma_para[1] = byte2; + coex_dm->ps_tdma_para[2] = byte3; + coex_dm->ps_tdma_para[3] = byte4; + coex_dm->ps_tdma_para[4] = byte5; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x60(5bytes) = 0x%x%08x\n", + h2c_parameter[0], + h2c_parameter[1] << 24 | h2c_parameter[2] << 16 | + h2c_parameter[3] << 8 | h2c_parameter[4]); + + btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); +} + +static void btc8192e2ant_sw_mec1(struct btc_coexist *btcoexist, + bool shrink_rx_lpf, bool low_penalty_ra, + bool limited_dig, bool btlan_constrain) +{ + halbtc8192e2ant_rf_shrink(btcoexist, NORMAL_EXEC, shrink_rx_lpf); +} + +static void btc8192e2ant_sw_mec2(struct btc_coexist *btcoexist, + bool agc_table_shift, bool adc_backoff, + bool sw_dac_swing, u32 dac_swinglvl) +{ + halbtc8192e2ant_AgcTable(btcoexist, NORMAL_EXEC, agc_table_shift); + halbtc8192e2ant_DacSwing(btcoexist, NORMAL_EXEC, sw_dac_swing, + dac_swinglvl); +} + +static void halbtc8192e2ant_ps_tdma(struct btc_coexist *btcoexist, + bool force_exec, bool turn_on, u8 type) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s turn %s PS TDMA, type=%d\n", + (force_exec ? "force to" : ""), + (turn_on ? "ON" : "OFF"), type); + coex_dm->cur_ps_tdma_on = turn_on; + coex_dm->cur_ps_tdma = type; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], bPrePsTdmaOn = %d, bCurPsTdmaOn = %d!!\n", + coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], prePsTdma = %d, curPsTdma = %d!!\n", + coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma); + + if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && + (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) + return; + } + if (turn_on) { + switch (type) { + case 1: + default: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0xe1, 0x90); + break; + case 2: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x12, + 0x12, 0xe1, 0x90); + break; + case 3: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1c, + 0x3, 0xf1, 0x90); + break; + case 4: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x10, + 0x3, 0xf1, 0x90); + break; + case 5: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0x60, 0x90); + break; + case 6: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x12, + 0x12, 0x60, 0x90); + break; + case 7: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1c, + 0x3, 0x70, 0x90); + break; + case 8: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xa3, 0x10, + 0x3, 0x70, 0x90); + break; + case 9: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0xe1, 0x10); + break; + case 10: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x12, + 0x12, 0xe1, 0x10); + break; + case 11: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1c, + 0x3, 0xf1, 0x10); + break; + case 12: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x10, + 0x3, 0xf1, 0x10); + break; + case 13: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0xe0, 0x10); + break; + case 14: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x12, + 0x12, 0xe0, 0x10); + break; + case 15: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1c, + 0x3, 0xf0, 0x10); + break; + case 16: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x12, + 0x3, 0xf0, 0x10); + break; + case 17: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0x61, 0x20, + 0x03, 0x10, 0x10); + break; + case 18: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x5, + 0x5, 0xe1, 0x90); + break; + case 19: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x25, + 0x25, 0xe1, 0x90); + break; + case 20: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x25, + 0x25, 0x60, 0x90); + break; + case 21: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x15, + 0x03, 0x70, 0x90); + break; + case 71: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0xe1, 0x90); + break; + } + } else { + /* disable PS tdma */ + switch (type) { + default: + case 0: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0x8, 0x0, 0x0, + 0x0, 0x0); + btcoexist->btc_write_1byte(btcoexist, 0x92c, 0x4); + break; + case 1: + halbtc8192e2ant_SetFwPstdma(btcoexist, 0x0, 0x0, 0x0, + 0x8, 0x0); + mdelay(5); + btcoexist->btc_write_1byte(btcoexist, 0x92c, 0x20); + break; + } + } + + /* update pre state */ + coex_dm->pre_ps_tdma_on = coex_dm->cur_ps_tdma_on; + coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; +} + +static void halbtc8192e2ant_set_switch_sstype(struct btc_coexist *btcoexist, + u8 sstype) +{ + u8 mimops = BTC_MIMO_PS_DYNAMIC; + u32 disra_mask = 0x0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], REAL set SS Type = %d\n", sstype); + + disra_mask = halbtc8192e2ant_decidera_mask(btcoexist, sstype, + coex_dm->curra_masktype); + halbtc8192e2ant_Updatera_mask(btcoexist, FORCE_EXEC, disra_mask); + + if (sstype == 1) { + halbtc8192e2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 1); + /* switch ofdm path */ + btcoexist->btc_write_1byte(btcoexist, 0xc04, 0x11); + btcoexist->btc_write_1byte(btcoexist, 0xd04, 0x1); + btcoexist->btc_write_4byte(btcoexist, 0x90c, 0x81111111); + /* switch cck patch */ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0xe77, 0x4, 0x1); + btcoexist->btc_write_1byte(btcoexist, 0xa07, 0x81); + mimops = BTC_MIMO_PS_STATIC; + } else if (sstype == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0); + btcoexist->btc_write_1byte(btcoexist, 0xc04, 0x33); + btcoexist->btc_write_1byte(btcoexist, 0xd04, 0x3); + btcoexist->btc_write_4byte(btcoexist, 0x90c, 0x81121313); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0xe77, 0x4, 0x0); + btcoexist->btc_write_1byte(btcoexist, 0xa07, 0x41); + mimops = BTC_MIMO_PS_DYNAMIC; + } + /* set rx 1ss or 2ss */ + btcoexist->btc_set(btcoexist, BTC_SET_ACT_SEND_MIMO_PS, &mimops); +} + +static void halbtc8192e2ant_switch_sstype(struct btc_coexist *btcoexist, + bool force_exec, u8 new_sstype) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], %s Switch SS Type = %d\n", + (force_exec ? "force to" : ""), new_sstype); + coex_dm->cur_sstype = new_sstype; + + if (!force_exec) { + if (coex_dm->pre_sstype == coex_dm->cur_sstype) + return; + } + halbtc8192e2ant_set_switch_sstype(btcoexist, coex_dm->cur_sstype); + + coex_dm->pre_sstype = coex_dm->cur_sstype; +} + +static void halbtc8192e2ant_coex_alloff(struct btc_coexist *btcoexist) +{ + /* fw all off */ + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + + /* sw all off */ + btc8192e2ant_sw_mec1(btcoexist, false, false, false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, false, 0x18); + + /* hw all off */ + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 0); +} + +static void halbtc8192e2ant_init_coex_dm(struct btc_coexist *btcoexist) +{ + /* force to reset coex mechanism */ + + halbtc8192e2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 1); + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, FORCE_EXEC, 6); + halbtc8192e2ant_dec_btpwr(btcoexist, FORCE_EXEC, 0); + + btc8192e2ant_coex_tbl_w_type(btcoexist, FORCE_EXEC, 0); + halbtc8192e2ant_switch_sstype(btcoexist, FORCE_EXEC, 2); + + btc8192e2ant_sw_mec1(btcoexist, false, false, false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, false, 0x18); +} + +static void halbtc8192e2ant_action_bt_inquiry(struct btc_coexist *btcoexist) +{ + bool low_pwr_disable = true; + + btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); + + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 2); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + + btc8192e2ant_sw_mec1(btcoexist, false, false, false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, false, 0x18); +} + +static bool halbtc8192e2ant_is_common_action(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool common = false, wifi_connected = false, wifi_busy = false; + bool bt_hson = false, low_pwr_disable = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hson); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + + if (bt_link_info->sco_exist || bt_link_info->hid_exist) + halbtc8192e2ant_limited_tx(btcoexist, NORMAL_EXEC, 1, 0, 0, 0); + else + halbtc8192e2ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); + + if (!wifi_connected) { + low_pwr_disable = false; + btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi non-connected idle!!\n"); + + if ((BT_8192E_2ANT_BT_STATUS_NON_CONNECTED_IDLE == + coex_dm->bt_status) || + (BT_8192E_2ANT_BT_STATUS_CONNECTED_IDLE == + coex_dm->bt_status)) { + halbtc8192e2ant_switch_sstype(btcoexist, + NORMAL_EXEC, 2); + btc8192e2ant_coex_tbl_w_type(btcoexist, + NORMAL_EXEC, 1); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 0); + } else { + halbtc8192e2ant_switch_sstype(btcoexist, + NORMAL_EXEC, 1); + btc8192e2ant_coex_tbl_w_type(btcoexist, + NORMAL_EXEC, 0); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 1); + } + + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + + btc8192e2ant_sw_mec1(btcoexist, false, false, false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, false, 0x18); + + common = true; + } else { + if (BT_8192E_2ANT_BT_STATUS_NON_CONNECTED_IDLE == + coex_dm->bt_status) { + low_pwr_disable = false; + btcoexist->btc_set(btcoexist, + BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Wifi connected + BT non connected-idle!!\n"); + + halbtc8192e2ant_switch_sstype(btcoexist, + NORMAL_EXEC, 2); + btc8192e2ant_coex_tbl_w_type(btcoexist, + NORMAL_EXEC, 1); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 0); + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, + NORMAL_EXEC, 6); + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + + btc8192e2ant_sw_mec1(btcoexist, false, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + + common = true; + } else if (BT_8192E_2ANT_BT_STATUS_CONNECTED_IDLE == + coex_dm->bt_status) { + low_pwr_disable = true; + btcoexist->btc_set(btcoexist, + BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + if (bt_hson) + return false; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Wifi connected + BT connected-idle!!\n"); + + halbtc8192e2ant_switch_sstype(btcoexist, + NORMAL_EXEC, 2); + btc8192e2ant_coex_tbl_w_type(btcoexist, + NORMAL_EXEC, 1); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 0); + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, + NORMAL_EXEC, 6); + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + + btc8192e2ant_sw_mec1(btcoexist, true, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + + common = true; + } else { + low_pwr_disable = true; + btcoexist->btc_set(btcoexist, + BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + if (wifi_busy) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Wifi Connected-Busy + BT Busy!!\n"); + common = false; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Wifi Connected-Idle + BT Busy!!\n"); + + halbtc8192e2ant_switch_sstype(btcoexist, + NORMAL_EXEC, 1); + btc8192e2ant_coex_tbl_w_type(btcoexist, + NORMAL_EXEC, 2); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 21); + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, + NORMAL_EXEC, 6); + halbtc8192e2ant_dec_btpwr(btcoexist, + NORMAL_EXEC, 0); + btc8192e2ant_sw_mec1(btcoexist, false, + false, false, false); + btc8192e2ant_sw_mec2(btcoexist, false, + false, false, 0x18); + common = true; + } + } + } + return common; +} + +static void btc8192e_int1(struct btc_coexist *btcoexist, bool tx_pause, + int result) +{ + if (tx_pause) { + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); + + if (coex_dm->cur_ps_tdma == 71) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + coex_dm->tdma_adj_type = 5; + } else if (coex_dm->cur_ps_tdma == 1) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + coex_dm->tdma_adj_type = 5; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 4) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } + if (coex_dm->cur_ps_tdma == 9) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 13); + coex_dm->tdma_adj_type = 13; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 12) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + + if (result == -1) { + if (coex_dm->cur_ps_tdma == 5) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } else if (coex_dm->cur_ps_tdma == 13) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 8) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + coex_dm->tdma_adj_type = 5; + } else if (coex_dm->cur_ps_tdma == 16) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 13); + coex_dm->tdma_adj_type = 13; + } + } + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); + if (coex_dm->cur_ps_tdma == 5) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 71); + coex_dm->tdma_adj_type = 71; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 8) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } + if (coex_dm->cur_ps_tdma == 13) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 16) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + + if (result == -1) { + if (coex_dm->cur_ps_tdma == 71) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 1); + coex_dm->tdma_adj_type = 1; + } else if (coex_dm->cur_ps_tdma == 1) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } else if (coex_dm->cur_ps_tdma == 9) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 4) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 1); + coex_dm->tdma_adj_type = 1; + } else if (coex_dm->cur_ps_tdma == 1) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 71); + coex_dm->tdma_adj_type = 71; + } else if (coex_dm->cur_ps_tdma == 12) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } + } + } +} + +static void btc8192e_int2(struct btc_coexist *btcoexist, bool tx_pause, + int result) +{ + if (tx_pause) { + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); + if (coex_dm->cur_ps_tdma == 1) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 4) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } + if (coex_dm->cur_ps_tdma == 9) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 12) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + if (result == -1) { + if (coex_dm->cur_ps_tdma == 5) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } else if (coex_dm->cur_ps_tdma == 13) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 8) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 16) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } + } + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); + if (coex_dm->cur_ps_tdma == 5) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 8) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } + if (coex_dm->cur_ps_tdma == 13) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 16) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + if (result == -1) { + if (coex_dm->cur_ps_tdma == 1) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } else if (coex_dm->cur_ps_tdma == 9) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 4) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 12) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } + } + } +} + +static void btc8192e_int3(struct btc_coexist *btcoexist, bool tx_pause, + int result) +{ + if (tx_pause) { + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); + if (coex_dm->cur_ps_tdma == 1) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 4) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } + if (coex_dm->cur_ps_tdma == 9) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 12) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + if (result == -1) { + if (coex_dm->cur_ps_tdma == 5) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } else if (coex_dm->cur_ps_tdma == 13) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 8) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 16) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } + } + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); + if (coex_dm->cur_ps_tdma == 5) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 8) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } + if (coex_dm->cur_ps_tdma == 13) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 16) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + if (result == -1) { + if (coex_dm->cur_ps_tdma == 1) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } else if (coex_dm->cur_ps_tdma == 9) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 4) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 12) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } + } + } +} + +static void halbtc8192e2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, + bool sco_hid, bool tx_pause, + u8 max_interval) +{ + static int up, dn, m, n, wait_cnt; + /* 0: no change, +1: increase WiFi duration, + * -1: decrease WiFi duration + */ + int result; + u8 retry_cnt = 0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], TdmaDurationAdjust()\n"); + + if (!coex_dm->auto_tdma_adjust) { + coex_dm->auto_tdma_adjust = true; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], first run TdmaDurationAdjust()!!\n"); + if (sco_hid) { + if (tx_pause) { + if (max_interval == 1) { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 13); + coex_dm->tdma_adj_type = 13; + } else if (max_interval == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (max_interval == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } + } else { + if (max_interval == 1) { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (max_interval == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (max_interval == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } + } + } else { + if (tx_pause) { + if (max_interval == 1) { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 5); + coex_dm->tdma_adj_type = 5; + } else if (max_interval == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (max_interval == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } + } else { + if (max_interval == 1) { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 1); + coex_dm->tdma_adj_type = 1; + } else if (max_interval == 2) { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (max_interval == 3) { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else { + halbtc8192e2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } + } + } + + up = 0; + dn = 0; + m = 1; + n = 3; + result = 0; + wait_cnt = 0; + } else { + /* accquire the BT TRx retry count from BT_Info byte2 */ + retry_cnt = coex_sta->bt_retry_cnt; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], retry_cnt = %d\n", retry_cnt); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], up=%d, dn=%d, m=%d, n=%d, wait_cnt=%d\n", + up, dn, m, n, wait_cnt); + result = 0; + wait_cnt++; + /* no retry in the last 2-second duration */ + if (retry_cnt == 0) { + up++; + dn--; + + if (dn <= 0) + dn = 0; + + if (up >= n) { + wait_cnt = 0; + n = 3; + up = 0; + dn = 0; + result = 1; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex]Increase wifi duration!!\n"); + } + } else if (retry_cnt <= 3) { + up--; + dn++; + + if (up <= 0) + up = 0; + + if (dn == 2) { + if (wait_cnt <= 2) + m++; + else + m = 1; + + if (m >= 20) + m = 20; + + n = 3 * m; + up = 0; + dn = 0; + wait_cnt = 0; + result = -1; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "Reduce wifi duration for retry<3\n"); + } + } else { + if (wait_cnt == 1) + m++; + else + m = 1; + + if (m >= 20) + m = 20; + + n = 3*m; + up = 0; + dn = 0; + wait_cnt = 0; + result = -1; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "Decrease wifi duration for retryCounter>3!!\n"); + } + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], max Interval = %d\n", max_interval); + if (max_interval == 1) + btc8192e_int1(btcoexist, tx_pause, result); + else if (max_interval == 2) + btc8192e_int2(btcoexist, tx_pause, result); + else if (max_interval == 3) + btc8192e_int3(btcoexist, tx_pause, result); + } + + /* if current PsTdma not match with + * the recorded one (when scan, dhcp...), + * then we have to adjust it back to the previous record one. + */ + if (coex_dm->cur_ps_tdma != coex_dm->tdma_adj_type) { + bool scan = false, link = false, roam = false; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], PsTdma type dismatch!!!, "); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "curPsTdma=%d, recordPsTdma=%d\n", + coex_dm->cur_ps_tdma, coex_dm->tdma_adj_type); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); + + if (!scan && !link && !roam) + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, + coex_dm->tdma_adj_type); + else + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n"); + } +} + +/* SCO only or SCO+PAN(HS) */ +static void halbtc8192e2ant_action_sco(struct btc_coexist *btcoexist) +{ + u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_STAY_LOW; + u32 wifi_bw; + + wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); + + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); + halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); + + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 4); + + btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); + + if ((btrssi_state == BTC_RSSI_STATE_LOW) || + (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13); + } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || + (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9); + } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || + (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9); + } + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, true, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x6); + } else { + btc8192e2ant_sw_mec1(btcoexist, true, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x6); + } + } else { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, false, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x6); + } else { + btc8192e2ant_sw_mec1(btcoexist, false, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x6); + } + } +} + +static void halbtc8192e2ant_action_sco_pan(struct btc_coexist *btcoexist) +{ + u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_STAY_LOW; + u32 wifi_bw; + + wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); + + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); + halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); + + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 4); + + btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); + + if ((btrssi_state == BTC_RSSI_STATE_LOW) || + (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14); + } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || + (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 10); + } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || + (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 10); + } + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, true, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x6); + } else { + btc8192e2ant_sw_mec1(btcoexist, true, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x6); + } + } else { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, false, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x6); + } else { + btc8192e2ant_sw_mec1(btcoexist, false, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x6); + } + } +} + +static void halbtc8192e2ant_action_hid(struct btc_coexist *btcoexist) +{ + u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; + u32 wifi_bw; + + wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); + btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); + + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); + halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); + + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 3); + + if ((btrssi_state == BTC_RSSI_STATE_LOW) || + (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13); + } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || + (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9); + } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || + (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9); + } + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, true, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, true, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, false, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, false, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } +} + +/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */ +static void halbtc8192e2ant_action_a2dp(struct btc_coexist *btcoexist) +{ + u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; + u32 wifi_bw; + bool long_dist = false; + + wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); + btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); + + if ((btrssi_state == BTC_RSSI_STATE_LOW || + btrssi_state == BTC_RSSI_STATE_STAY_LOW) && + (wifirssi_state == BTC_RSSI_STATE_LOW || + wifirssi_state == BTC_RSSI_STATE_STAY_LOW)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], A2dp, wifi/bt rssi both LOW!!\n"); + long_dist = true; + } + if (long_dist) { + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 2); + halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, true, + 0x4); + } else { + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); + halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, + 0x8); + } + + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + + if (long_dist) + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 0); + else + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 2); + + if (long_dist) { + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 17); + coex_dm->auto_tdma_adjust = false; + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + } else { + if ((btrssi_state == BTC_RSSI_STATE_LOW) || + (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { + halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, + true, 1); + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || + (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { + halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, + false, 1); + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); + } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || + (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, + false, 1); + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); + } + } + + /* sw mechanism */ + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, true, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, true, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, false, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, false, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void halbtc8192e2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) +{ + u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; + u32 wifi_bw; + + wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); + btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); + + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); + halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); + + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 2); + + if ((btrssi_state == BTC_RSSI_STATE_LOW) || + (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { + halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, true, 2); + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || + (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { + halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, + false, 2); + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); + } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || + (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, + false, 2); + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); + } + + /* sw mechanism */ + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, true, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + true, 0x6); + } else { + btc8192e2ant_sw_mec1(btcoexist, true, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + true, 0x6); + } + } else { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, false, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + true, 0x6); + } else { + btc8192e2ant_sw_mec1(btcoexist, false, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + true, 0x6); + } + } +} + +static void halbtc8192e2ant_action_pan_edr(struct btc_coexist *btcoexist) +{ + u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; + u32 wifi_bw; + + wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); + btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); + + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); + halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); + + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 2); + + if ((btrssi_state == BTC_RSSI_STATE_LOW) || + (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); + } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || + (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 1); + } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || + (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 1); + } + + /* sw mechanism */ + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, true, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, true, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, false, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, false, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } +} + +/* PAN(HS) only */ +static void halbtc8192e2ant_action_pan_hs(struct btc_coexist *btcoexist) +{ + u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; + u32 wifi_bw; + + wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); + btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); + + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); + halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); + + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 2); + + if ((btrssi_state == BTC_RSSI_STATE_LOW) || + (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || + (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); + } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || + (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); + } + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, true, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, true, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, false, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, false, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } +} + +/* PAN(EDR)+A2DP */ +static void halbtc8192e2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) +{ + u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; + u32 wifi_bw; + + wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); + btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); + + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); + halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); + + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 2); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if ((btrssi_state == BTC_RSSI_STATE_LOW) || + (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, true, 3); + } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || + (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); + halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, + false, 3); + } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || + (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); + halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, + false, 3); + } + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, true, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, true, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, false, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, false, false, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void halbtc8192e2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) +{ + u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; + u32 wifi_bw; + + wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); + btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); + halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); + + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 3); + + if ((btrssi_state == BTC_RSSI_STATE_LOW) || + (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14); + } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || + (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || + (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); + halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + } + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, true, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, true, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, false, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, false, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } +} + +/* HID+A2DP+PAN(EDR) */ +static void btc8192e2ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) +{ + u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; + u32 wifi_bw; + + wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); + btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); + + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); + halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); + + halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 3); + + if ((btrssi_state == BTC_RSSI_STATE_LOW) || + (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + halbtc8192e2ant_tdma_duration_adjust(btcoexist, true, true, 3); + } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || + (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); + halbtc8192e2ant_tdma_duration_adjust(btcoexist, true, false, 3); + } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || + (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); + halbtc8192e2ant_tdma_duration_adjust(btcoexist, true, false, 3); + } + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, true, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, true, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, false, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, false, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void halbtc8192e2ant_action_hid_a2dp(struct btc_coexist *btcoexist) +{ + u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; + u32 wifi_bw; + + wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); + btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); + + halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); + halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 3); + + if ((btrssi_state == BTC_RSSI_STATE_LOW) || + (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); + halbtc8192e2ant_tdma_duration_adjust(btcoexist, true, true, 2); + } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || + (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); + halbtc8192e2ant_tdma_duration_adjust(btcoexist, true, false, 2); + } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || + (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); + halbtc8192e2ant_tdma_duration_adjust(btcoexist, true, false, 2); + } + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, true, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, true, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || + (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8192e2ant_sw_mec1(btcoexist, false, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, true, false, + false, 0x18); + } else { + btc8192e2ant_sw_mec1(btcoexist, false, true, + false, false); + btc8192e2ant_sw_mec2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void halbtc8192e2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) +{ + u8 algorithm = 0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], RunCoexistMechanism()===>\n"); + + if (btcoexist->manual_control) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], return for Manual CTRL <===\n"); + return; + } + + if (coex_sta->under_ips) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], wifi is under IPS !!!\n"); + return; + } + + algorithm = halbtc8192e2ant_action_algorithm(btcoexist); + if (coex_sta->c2h_bt_inquiry_page && + (BT_8192E_2ANT_COEX_ALGO_PANHS != algorithm)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT is under inquiry/page scan !!\n"); + halbtc8192e2ant_action_bt_inquiry(btcoexist); + return; + } + + coex_dm->cur_algorithm = algorithm; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Algorithm = %d\n", coex_dm->cur_algorithm); + + if (halbtc8192e2ant_is_common_action(btcoexist)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant common.\n"); + coex_dm->auto_tdma_adjust = false; + } else { + if (coex_dm->cur_algorithm != coex_dm->pre_algorithm) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex] preAlgorithm=%d, curAlgorithm=%d\n", + coex_dm->pre_algorithm, + coex_dm->cur_algorithm); + coex_dm->auto_tdma_adjust = false; + } + switch (coex_dm->cur_algorithm) { + case BT_8192E_2ANT_COEX_ALGO_SCO: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Action 2-Ant, algorithm = SCO.\n"); + halbtc8192e2ant_action_sco(btcoexist); + break; + case BT_8192E_2ANT_COEX_ALGO_SCO_PAN: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Action 2-Ant, algorithm = SCO+PAN(EDR).\n"); + halbtc8192e2ant_action_sco_pan(btcoexist); + break; + case BT_8192E_2ANT_COEX_ALGO_HID: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Action 2-Ant, algorithm = HID.\n"); + halbtc8192e2ant_action_hid(btcoexist); + break; + case BT_8192E_2ANT_COEX_ALGO_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Action 2-Ant, algorithm = A2DP.\n"); + halbtc8192e2ant_action_a2dp(btcoexist); + break; + case BT_8192E_2ANT_COEX_ALGO_A2DP_PANHS: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Action 2-Ant, algorithm = A2DP+PAN(HS).\n"); + halbtc8192e2ant_action_a2dp_pan_hs(btcoexist); + break; + case BT_8192E_2ANT_COEX_ALGO_PANEDR: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Action 2-Ant, algorithm = PAN(EDR).\n"); + halbtc8192e2ant_action_pan_edr(btcoexist); + break; + case BT_8192E_2ANT_COEX_ALGO_PANHS: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Action 2-Ant, algorithm = HS mode.\n"); + halbtc8192e2ant_action_pan_hs(btcoexist); + break; + case BT_8192E_2ANT_COEX_ALGO_PANEDR_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Action 2-Ant, algorithm = PAN+A2DP.\n"); + halbtc8192e2ant_action_pan_edr_a2dp(btcoexist); + break; + case BT_8192E_2ANT_COEX_ALGO_PANEDR_HID: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Action 2-Ant, algorithm = PAN(EDR)+HID.\n"); + halbtc8192e2ant_action_pan_edr_hid(btcoexist); + break; + case BT_8192E_2ANT_COEX_ALGO_HID_A2DP_PANEDR: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Action 2-Ant, algorithm = HID+A2DP+PAN.\n"); + btc8192e2ant_action_hid_a2dp_pan_edr(btcoexist); + break; + case BT_8192E_2ANT_COEX_ALGO_HID_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Action 2-Ant, algorithm = HID+A2DP.\n"); + halbtc8192e2ant_action_hid_a2dp(btcoexist); + break; + default: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "Action 2-Ant, algorithm = unknown!!\n"); + /* halbtc8192e2ant_coex_alloff(btcoexist); */ + break; + } + coex_dm->pre_algorithm = coex_dm->cur_algorithm; + } +} + +static void halbtc8192e2ant_init_hwconfig(struct btc_coexist *btcoexist, + bool backup) +{ + u16 u16tmp = 0; + u8 u8tmp = 0; + + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], 2Ant Init HW Config!!\n"); + + if (backup) { + /* backup rf 0x1e value */ + coex_dm->bt_rf0x1e_backup = + btcoexist->btc_get_rf_reg(btcoexist, BTC_RF_A, + 0x1e, 0xfffff); + + coex_dm->backup_arfr_cnt1 = btcoexist->btc_read_4byte(btcoexist, + 0x430); + coex_dm->backup_arfr_cnt2 = btcoexist->btc_read_4byte(btcoexist, + 0x434); + coex_dm->backup_retrylimit = btcoexist->btc_read_2byte( + btcoexist, + 0x42a); + coex_dm->backup_ampdu_maxtime = btcoexist->btc_read_1byte( + btcoexist, + 0x456); + } + + /* antenna sw ctrl to bt */ + btcoexist->btc_write_1byte(btcoexist, 0x4f, 0x6); + btcoexist->btc_write_1byte(btcoexist, 0x944, 0x24); + btcoexist->btc_write_4byte(btcoexist, 0x930, 0x700700); + btcoexist->btc_write_1byte(btcoexist, 0x92c, 0x20); + if (btcoexist->chip_interface == BTC_INTF_USB) + btcoexist->btc_write_4byte(btcoexist, 0x64, 0x30430004); + else + btcoexist->btc_write_4byte(btcoexist, 0x64, 0x30030004); + + btc8192e2ant_coex_tbl_w_type(btcoexist, FORCE_EXEC, 0); + + /* antenna switch control parameter */ + btcoexist->btc_write_4byte(btcoexist, 0x858, 0x55555555); + + /* coex parameters */ + btcoexist->btc_write_1byte(btcoexist, 0x778, 0x3); + /* 0x790[5:0] = 0x5 */ + u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x790); + u8tmp &= 0xc0; + u8tmp |= 0x5; + btcoexist->btc_write_1byte(btcoexist, 0x790, u8tmp); + + /* enable counter statistics */ + btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4); + + /* enable PTA */ + btcoexist->btc_write_1byte(btcoexist, 0x40, 0x20); + /* enable mailbox interface */ + u16tmp = btcoexist->btc_read_2byte(btcoexist, 0x40); + u16tmp |= BIT9; + btcoexist->btc_write_2byte(btcoexist, 0x40, u16tmp); + + /* enable PTA I2C mailbox */ + u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x101); + u8tmp |= BIT4; + btcoexist->btc_write_1byte(btcoexist, 0x101, u8tmp); + + /* enable bt clock when wifi is disabled. */ + u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x93); + u8tmp |= BIT0; + btcoexist->btc_write_1byte(btcoexist, 0x93, u8tmp); + /* enable bt clock when suspend. */ + u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x7); + u8tmp |= BIT0; + btcoexist->btc_write_1byte(btcoexist, 0x7, u8tmp); +} + +/************************************************************* + * work around function start with wa_halbtc8192e2ant_ + *************************************************************/ + +/************************************************************ + * extern function start with EXhalbtc8192e2ant_ + ************************************************************/ + +void ex_halbtc8192e2ant_init_hwconfig(struct btc_coexist *btcoexist) +{ + halbtc8192e2ant_init_hwconfig(btcoexist, true); +} + +void ex_halbtc8192e2ant_init_coex_dm(struct btc_coexist *btcoexist) +{ + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], Coex Mechanism Init!!\n"); + halbtc8192e2ant_init_coex_dm(btcoexist); +} + +void ex_halbtc8192e2ant_display_coex_info(struct btc_coexist *btcoexist) +{ + struct btc_board_info *board_info = &btcoexist->board_info; + struct btc_stack_info *stack_info = &btcoexist->stack_info; + struct rtl_priv *rtlpriv = btcoexist->adapter; + u8 u8tmp[4], i, bt_info_ext, ps_tdma_case = 0; + u16 u16tmp[4]; + u32 u32tmp[4]; + bool roam = false, scan = false, link = false, wifi_under_5g = false; + bool bt_hson = false, wifi_busy = false; + int wifirssi = 0, bt_hs_rssi = 0; + u32 wifi_bw, wifi_traffic_dir; + u8 wifi_dot11_chnl, wifi_hs_chnl; + u32 fw_ver = 0, bt_patch_ver = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n ============[BT Coexist info]============"); + + if (btcoexist->manual_control) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n ===========[Under Manual Control]==========="); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n =========================================="); + } + + if (!board_info->bt_exist) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n BT not exists !!!"); + return; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d/ %d ", "Ant PG number/ Ant mechanism:", + board_info->pg_ant_num, board_info->btdm_ant_num); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s / %d", + "BT stack/ hci ext ver", + ((stack_info->profile_notified) ? "Yes" : "No"), + stack_info->hci_version); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d_%d/ 0x%x/ 0x%x(%d)", + "CoexVer/ FwVer/ PatchVer", + glcoex_ver_date_8192e_2ant, glcoex_ver_8192e_2ant, + fw_ver, bt_patch_ver, bt_patch_ver); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hson); + btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_DOT11_CHNL, + &wifi_dot11_chnl); + btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_HS_CHNL, &wifi_hs_chnl); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d / %d(%d)", + "Dot11 channel / HsMode(HsChnl)", + wifi_dot11_chnl, bt_hson, wifi_hs_chnl); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %02x %02x %02x ", + "H2C Wifi inform bt chnl Info", coex_dm->wifi_chnl_info[0], + coex_dm->wifi_chnl_info[1], coex_dm->wifi_chnl_info[2]); + + btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifirssi); + btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", + "Wifi rssi/ HS rssi", wifirssi, bt_hs_rssi); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d ", + "Wifi link/ roam/ scan", link, roam, scan); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, + &wifi_traffic_dir); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s / %s/ %s ", + "Wifi status", (wifi_under_5g ? "5G" : "2.4G"), + ((BTC_WIFI_BW_LEGACY == wifi_bw) ? "Legacy" : + (((BTC_WIFI_BW_HT40 == wifi_bw) ? "HT40" : "HT20"))), + ((!wifi_busy) ? "idle" : + ((BTC_WIFI_TRAFFIC_TX == wifi_traffic_dir) ? + "uplink" : "downlink"))); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = [%s/ %d/ %d] ", + "BT [status/ rssi/ retryCnt]", + ((btcoexist->bt_info.bt_disabled) ? ("disabled") : + ((coex_sta->c2h_bt_inquiry_page) ? + ("inquiry/page scan") : + ((BT_8192E_2ANT_BT_STATUS_NON_CONNECTED_IDLE == + coex_dm->bt_status) ? "non-connected idle" : + ((BT_8192E_2ANT_BT_STATUS_CONNECTED_IDLE == + coex_dm->bt_status) ? "connected-idle" : "busy")))), + coex_sta->bt_rssi, coex_sta->bt_retry_cnt); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d / %d / %d / %d", + "SCO/HID/PAN/A2DP", stack_info->sco_exist, + stack_info->hid_exist, stack_info->pan_exist, + stack_info->a2dp_exist); + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_BT_LINK_INFO); + + bt_info_ext = coex_sta->bt_info_ext; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s", + "BT Info A2DP rate", + (bt_info_ext&BIT0) ? "Basic rate" : "EDR rate"); + + for (i = 0; i < BT_INFO_SRC_8192E_2ANT_MAX; i++) { + if (coex_sta->bt_info_c2h_cnt[i]) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %02x %02x %02x %02x ", + GLBtInfoSrc8192e2Ant[i], + coex_sta->bt_info_c2h[i][0], + coex_sta->bt_info_c2h[i][1], + coex_sta->bt_info_c2h[i][2], + coex_sta->bt_info_c2h[i][3]); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "%02x %02x %02x(%d)", + coex_sta->bt_info_c2h[i][4], + coex_sta->bt_info_c2h[i][5], + coex_sta->bt_info_c2h[i][6], + coex_sta->bt_info_c2h_cnt[i]); + } + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s/%s", + "PS state, IPS/LPS", + ((coex_sta->under_ips ? "IPS ON" : "IPS OFF")), + ((coex_sta->under_lps ? "LPS ON" : "LPS OFF"))); + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x ", "SS Type", + coex_dm->cur_sstype); + + /* Sw mechanism */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", + "============[Sw mechanism]============"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d ", + "SM1[ShRf/ LpRA/ LimDig]", coex_dm->cur_rf_rx_lpf_shrink, + coex_dm->cur_low_penalty_ra, coex_dm->limited_dig); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d(0x%x) ", + "SM2[AgcT/ AdcB/ SwDacSwing(lvl)]", + coex_dm->cur_agc_table_en, coex_dm->cur_adc_back_off, + coex_dm->cur_dac_swing_on, coex_dm->cur_dac_swing_lvl); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x ", "Rate Mask", + btcoexist->bt_info.ra_mask); + + /* Fw mechanism */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", + "============[Fw mechanism]============"); + + ps_tdma_case = coex_dm->cur_ps_tdma; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", + "PS TDMA", coex_dm->ps_tdma_para[0], + coex_dm->ps_tdma_para[1], coex_dm->ps_tdma_para[2], + coex_dm->ps_tdma_para[3], coex_dm->ps_tdma_para[4], + ps_tdma_case, coex_dm->auto_tdma_adjust); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d ", + "DecBtPwr/ IgnWlanAct", + coex_dm->cur_dec_bt_pwr, coex_dm->cur_ignore_wlan_act); + + /* Hw setting */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", + "============[Hw setting]============"); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x", + "RF-A, 0x1e initVal", coex_dm->bt_rf0x1e_backup); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", + "backup ARFR1/ARFR2/RL/AMaxTime", coex_dm->backup_arfr_cnt1, + coex_dm->backup_arfr_cnt2, coex_dm->backup_retrylimit, + coex_dm->backup_ampdu_maxtime); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x430); + u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x434); + u16tmp[0] = btcoexist->btc_read_2byte(btcoexist, 0x42a); + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x456); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", + "0x430/0x434/0x42a/0x456", + u32tmp[0], u32tmp[1], u16tmp[0], u8tmp[0]); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc04); + u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0xd04); + u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x90c); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "0xc04/ 0xd04/ 0x90c", u32tmp[0], u32tmp[1], u32tmp[2]); + + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x778); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x", "0x778", + u8tmp[0]); + + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x92c); + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x930); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "0x92c/ 0x930", (u8tmp[0]), u32tmp[0]); + + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x40); + u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x4f); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "0x40/ 0x4f", u8tmp[0], u8tmp[1]); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x550); + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x522); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "0x550(bcn ctrl)/0x522", u32tmp[0], u8tmp[0]); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc50); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x", "0xc50(dig)", + u32tmp[0]); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6c0); + u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x6c4); + u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x6c8); + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x6cc); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", + "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)", + u32tmp[0], u32tmp[1], u32tmp[2], u8tmp[0]); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", + "0x770(hp rx[31:16]/tx[15:0])", + coex_sta->high_priority_rx, coex_sta->high_priority_tx); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", + "0x774(lp rx[31:16]/tx[15:0])", + coex_sta->low_priority_rx, coex_sta->low_priority_tx); +#if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 1) + halbtc8192e2ant_monitor_bt_ctr(btcoexist); +#endif + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS); +} + +void ex_halbtc8192e2ant_ips_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (BTC_IPS_ENTER == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], IPS ENTER notify\n"); + coex_sta->under_ips = true; + halbtc8192e2ant_coex_alloff(btcoexist); + } else if (BTC_IPS_LEAVE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], IPS LEAVE notify\n"); + coex_sta->under_ips = false; + } +} + +void ex_halbtc8192e2ant_lps_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (BTC_LPS_ENABLE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], LPS ENABLE notify\n"); + coex_sta->under_lps = true; + } else if (BTC_LPS_DISABLE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], LPS DISABLE notify\n"); + coex_sta->under_lps = false; + } +} + +void ex_halbtc8192e2ant_scan_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (BTC_SCAN_START == type) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], SCAN START notify\n"); + else if (BTC_SCAN_FINISH == type) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], SCAN FINISH notify\n"); +} + +void ex_halbtc8192e2ant_connect_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (BTC_ASSOCIATE_START == type) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], CONNECT START notify\n"); + else if (BTC_ASSOCIATE_FINISH == type) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], CONNECT FINISH notify\n"); +} + +void ex_halbtc8192e2ant_media_status_notify(struct btc_coexist *btcoexist, + u8 type) +{ + u8 h2c_parameter[3] = {0}; + u32 wifi_bw; + u8 wifi_center_chnl; + + if (btcoexist->manual_control || + btcoexist->stop_coex_dm || + btcoexist->bt_info.bt_disabled) + return; + + if (BTC_MEDIA_CONNECT == type) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], MEDIA connect notify\n"); + else + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], MEDIA disconnect notify\n"); + + /* only 2.4G we need to inform bt the chnl mask */ + btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, + &wifi_center_chnl); + if ((BTC_MEDIA_CONNECT == type) && + (wifi_center_chnl <= 14)) { + h2c_parameter[0] = 0x1; + h2c_parameter[1] = wifi_center_chnl; + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) + h2c_parameter[2] = 0x30; + else + h2c_parameter[2] = 0x20; + } + + coex_dm->wifi_chnl_info[0] = h2c_parameter[0]; + coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; + coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x66 = 0x%x\n", + h2c_parameter[0] << 16 | h2c_parameter[1] << 8 | + h2c_parameter[2]); + + btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); +} + +void ex_halbtc8192e2ant_special_packet_notify(struct btc_coexist *btcoexist, + u8 type) +{ + if (type == BTC_PACKET_DHCP) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], DHCP Packet notify\n"); +} + +void ex_halbtc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist, + u8 *tmp_buf, u8 length) +{ + u8 bt_info = 0; + u8 i, rsp_source = 0; + bool bt_busy = false, limited_dig = false; + bool wifi_connected = false; + + coex_sta->c2h_bt_info_req_sent = false; + + rsp_source = tmp_buf[0] & 0xf; + if (rsp_source >= BT_INFO_SRC_8192E_2ANT_MAX) + rsp_source = BT_INFO_SRC_8192E_2ANT_WIFI_FW; + coex_sta->bt_info_c2h_cnt[rsp_source]++; + + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], Bt info[%d], length=%d, hex data = [", + rsp_source, length); + for (i = 0; i < length; i++) { + coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i]; + if (i == 1) + bt_info = tmp_buf[i]; + if (i == length-1) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "0x%02x]\n", tmp_buf[i]); + else + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "0x%02x, ", tmp_buf[i]); + } + + if (BT_INFO_SRC_8192E_2ANT_WIFI_FW != rsp_source) { + coex_sta->bt_retry_cnt = /* [3:0] */ + coex_sta->bt_info_c2h[rsp_source][2] & 0xf; + + coex_sta->bt_rssi = + coex_sta->bt_info_c2h[rsp_source][3] * 2 + 10; + + coex_sta->bt_info_ext = + coex_sta->bt_info_c2h[rsp_source][4]; + + /* Here we need to resend some wifi info to BT + * because bt is reset and loss of the info. + */ + if ((coex_sta->bt_info_ext & BIT1)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "bit1, send wifi BW&Chnl to BT!!\n"); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + if (wifi_connected) + ex_halbtc8192e2ant_media_status_notify( + btcoexist, + BTC_MEDIA_CONNECT); + else + ex_halbtc8192e2ant_media_status_notify( + btcoexist, + BTC_MEDIA_DISCONNECT); + } + + if ((coex_sta->bt_info_ext & BIT3)) { + if (!btcoexist->manual_control && + !btcoexist->stop_coex_dm) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "bit3, BT NOT ignore Wlan active!\n"); + halbtc8192e2ant_IgnoreWlanAct(btcoexist, + FORCE_EXEC, + false); + } + } else { + /* BT already NOT ignore Wlan active, + * do nothing here. + */ + } + +#if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 0) + if ((coex_sta->bt_info_ext & BIT4)) { + /* BT auto report already enabled, do nothing */ + } else { + halbtc8192e2ant_bt_autoreport(btcoexist, FORCE_EXEC, + true); + } +#endif + } + + /* check BIT2 first ==> check if bt is under inquiry or page scan */ + if (bt_info & BT_INFO_8192E_2ANT_B_INQ_PAGE) + coex_sta->c2h_bt_inquiry_page = true; + else + coex_sta->c2h_bt_inquiry_page = false; + + /* set link exist status */ + if (!(bt_info&BT_INFO_8192E_2ANT_B_CONNECTION)) { + coex_sta->bt_link_exist = false; + coex_sta->pan_exist = false; + coex_sta->a2dp_exist = false; + coex_sta->hid_exist = false; + coex_sta->sco_exist = false; + } else {/* connection exists */ + coex_sta->bt_link_exist = true; + if (bt_info & BT_INFO_8192E_2ANT_B_FTP) + coex_sta->pan_exist = true; + else + coex_sta->pan_exist = false; + if (bt_info & BT_INFO_8192E_2ANT_B_A2DP) + coex_sta->a2dp_exist = true; + else + coex_sta->a2dp_exist = false; + if (bt_info & BT_INFO_8192E_2ANT_B_HID) + coex_sta->hid_exist = true; + else + coex_sta->hid_exist = false; + if (bt_info & BT_INFO_8192E_2ANT_B_SCO_ESCO) + coex_sta->sco_exist = true; + else + coex_sta->sco_exist = false; + } + + halbtc8192e2ant_update_btlink_info(btcoexist); + + if (!(bt_info&BT_INFO_8192E_2ANT_B_CONNECTION)) { + coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_NON_CONNECTED_IDLE; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Non-Connected idle!!!\n"); + } else if (bt_info == BT_INFO_8192E_2ANT_B_CONNECTION) { + coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_CONNECTED_IDLE; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], bt_infoNotify(), BT Connected-idle!!!\n"); + } else if ((bt_info&BT_INFO_8192E_2ANT_B_SCO_ESCO) || + (bt_info&BT_INFO_8192E_2ANT_B_SCO_BUSY)) { + coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_SCO_BUSY; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], bt_infoNotify(), BT SCO busy!!!\n"); + } else if (bt_info&BT_INFO_8192E_2ANT_B_ACL_BUSY) { + coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_ACL_BUSY; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], bt_infoNotify(), BT ACL busy!!!\n"); + } else { + coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_MAX; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex]bt_infoNotify(), BT Non-Defined state!!!\n"); + } + + if ((BT_8192E_2ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || + (BT_8192E_2ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || + (BT_8192E_2ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) { + bt_busy = true; + limited_dig = true; + } else { + bt_busy = false; + limited_dig = false; + } + + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy); + + coex_dm->limited_dig = limited_dig; + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_LIMITED_DIG, &limited_dig); + + halbtc8192e2ant_run_coexist_mechanism(btcoexist); +} + +void ex_halbtc8192e2ant_stack_operation_notify(struct btc_coexist *btcoexist, + u8 type) +{ +} + +void ex_halbtc8192e2ant_halt_notify(struct btc_coexist *btcoexist) +{ + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "[BTCoex], Halt notify\n"); + + halbtc8192e2ant_IgnoreWlanAct(btcoexist, FORCE_EXEC, true); + ex_halbtc8192e2ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT); +} + +void ex_halbtc8192e2ant_periodical(struct btc_coexist *btcoexist) +{ + static u8 dis_ver_info_cnt; + u32 fw_ver = 0, bt_patch_ver = 0; + struct btc_board_info *board_info = &btcoexist->board_info; + struct btc_stack_info *stack_info = &btcoexist->stack_info; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "=======================Periodical=======================\n"); + if (dis_ver_info_cnt <= 5) { + dis_ver_info_cnt += 1; + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "************************************************\n"); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", + board_info->pg_ant_num, board_info->btdm_ant_num, + board_info->btdm_ant_pos); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "BT stack/ hci ext ver = %s / %d\n", + ((stack_info->profile_notified) ? "Yes" : "No"), + stack_info->hci_version); + btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, + &bt_patch_ver); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", + glcoex_ver_date_8192e_2ant, glcoex_ver_8192e_2ant, + fw_ver, bt_patch_ver, bt_patch_ver); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "************************************************\n"); + } + +#if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 0) + halbtc8192e2ant_querybt_info(btcoexist); + halbtc8192e2ant_monitor_bt_ctr(btcoexist); + btc8192e2ant_monitor_bt_enable_dis(btcoexist); +#else + if (halbtc8192e2ant_iswifi_status_changed(btcoexist) || + coex_dm->auto_tdma_adjust) + halbtc8192e2ant_run_coexist_mechanism(btcoexist); +#endif +} diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h new file mode 100644 index 000000000000..75e1f7d0db06 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.h @@ -0,0 +1,185 @@ +/****************************************************************************** + * + * Copyright(c) 2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +/***************************************************************** + * The following is for 8192E 2Ant BT Co-exist definition + *****************************************************************/ +#define BT_AUTO_REPORT_ONLY_8192E_2ANT 0 + +#define BT_INFO_8192E_2ANT_B_FTP BIT7 +#define BT_INFO_8192E_2ANT_B_A2DP BIT6 +#define BT_INFO_8192E_2ANT_B_HID BIT5 +#define BT_INFO_8192E_2ANT_B_SCO_BUSY BIT4 +#define BT_INFO_8192E_2ANT_B_ACL_BUSY BIT3 +#define BT_INFO_8192E_2ANT_B_INQ_PAGE BIT2 +#define BT_INFO_8192E_2ANT_B_SCO_ESCO BIT1 +#define BT_INFO_8192E_2ANT_B_CONNECTION BIT0 + +#define BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT 2 + +enum bt_info_src_8192e_2ant { + BT_INFO_SRC_8192E_2ANT_WIFI_FW = 0x0, + BT_INFO_SRC_8192E_2ANT_BT_RSP = 0x1, + BT_INFO_SRC_8192E_2ANT_BT_ACTIVE_SEND = 0x2, + BT_INFO_SRC_8192E_2ANT_MAX +}; + +enum bt_8192e_2ant_bt_status { + BT_8192E_2ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0, + BT_8192E_2ANT_BT_STATUS_CONNECTED_IDLE = 0x1, + BT_8192E_2ANT_BT_STATUS_INQ_PAGE = 0x2, + BT_8192E_2ANT_BT_STATUS_ACL_BUSY = 0x3, + BT_8192E_2ANT_BT_STATUS_SCO_BUSY = 0x4, + BT_8192E_2ANT_BT_STATUS_ACL_SCO_BUSY = 0x5, + BT_8192E_2ANT_BT_STATUS_MAX +}; + +enum bt_8192e_2ant_coex_algo { + BT_8192E_2ANT_COEX_ALGO_UNDEFINED = 0x0, + BT_8192E_2ANT_COEX_ALGO_SCO = 0x1, + BT_8192E_2ANT_COEX_ALGO_SCO_PAN = 0x2, + BT_8192E_2ANT_COEX_ALGO_HID = 0x3, + BT_8192E_2ANT_COEX_ALGO_A2DP = 0x4, + BT_8192E_2ANT_COEX_ALGO_A2DP_PANHS = 0x5, + BT_8192E_2ANT_COEX_ALGO_PANEDR = 0x6, + BT_8192E_2ANT_COEX_ALGO_PANHS = 0x7, + BT_8192E_2ANT_COEX_ALGO_PANEDR_A2DP = 0x8, + BT_8192E_2ANT_COEX_ALGO_PANEDR_HID = 0x9, + BT_8192E_2ANT_COEX_ALGO_HID_A2DP_PANEDR = 0xa, + BT_8192E_2ANT_COEX_ALGO_HID_A2DP = 0xb, + BT_8192E_2ANT_COEX_ALGO_MAX = 0xc +}; + +struct coex_dm_8192e_2ant { + /* fw mechanism */ + u8 pre_dec_bt_pwr; + u8 cur_dec_bt_pwr; + u8 pre_fw_dac_swing_lvl; + u8 cur_fw_dac_swing_lvl; + bool cur_ignore_wlan_act; + bool pre_ignore_wlan_act; + u8 pre_ps_tdma; + u8 cur_ps_tdma; + u8 ps_tdma_para[5]; + u8 tdma_adj_type; + bool reset_tdma_adjust; + bool auto_tdma_adjust; + bool pre_ps_tdma_on; + bool cur_ps_tdma_on; + bool pre_bt_auto_report; + bool cur_bt_auto_report; + + /* sw mechanism */ + bool pre_rf_rx_lpf_shrink; + bool cur_rf_rx_lpf_shrink; + u32 bt_rf0x1e_backup; + bool pre_low_penalty_ra; + bool cur_low_penalty_ra; + bool pre_dac_swing_on; + u32 pre_dac_swing_lvl; + bool cur_dac_swing_on; + u32 cur_dac_swing_lvl; + bool pre_adc_back_off; + bool cur_adc_back_off; + bool pre_agc_table_en; + bool cur_agc_table_en; + u32 pre_val0x6c0; + u32 cur_val0x6c0; + u32 pre_val0x6c4; + u32 cur_val0x6c4; + u32 pre_val0x6c8; + u32 cur_val0x6c8; + u8 pre_val0x6cc; + u8 cur_val0x6cc; + bool limited_dig; + + u32 backup_arfr_cnt1; /* Auto Rate Fallback Retry cnt */ + u32 backup_arfr_cnt2; /* Auto Rate Fallback Retry cnt */ + u16 backup_retrylimit; + u8 backup_ampdu_maxtime; + + /* algorithm related */ + u8 pre_algorithm; + u8 cur_algorithm; + u8 bt_status; + u8 wifi_chnl_info[3]; + + u8 pre_sstype; + u8 cur_sstype; + + u32 prera_mask; + u32 curra_mask; + u8 curra_masktype; + u8 pre_arfrtype; + u8 cur_arfrtype; + u8 pre_retrylimit_type; + u8 cur_retrylimit_type; + u8 pre_ampdutime_type; + u8 cur_ampdutime_type; +}; + +struct coex_sta_8192e_2ant { + bool bt_link_exist; + bool sco_exist; + bool a2dp_exist; + bool hid_exist; + bool pan_exist; + + bool under_lps; + bool under_ips; + u32 high_priority_tx; + u32 high_priority_rx; + u32 low_priority_tx; + u32 low_priority_rx; + u8 bt_rssi; + u8 pre_bt_rssi_state; + u8 pre_wifi_rssi_state[4]; + bool c2h_bt_info_req_sent; + u8 bt_info_c2h[BT_INFO_SRC_8192E_2ANT_MAX][10]; + u32 bt_info_c2h_cnt[BT_INFO_SRC_8192E_2ANT_MAX]; + bool c2h_bt_inquiry_page; + u8 bt_retry_cnt; + u8 bt_info_ext; +}; + +/**************************************************************** + * The following is interface which will notify coex module. + ****************************************************************/ +void ex_halbtc8192e2ant_init_hwconfig(struct btc_coexist *btcoexist); +void ex_halbtc8192e2ant_init_coex_dm(struct btc_coexist *btcoexist); +void ex_halbtc8192e2ant_ips_notify(struct btc_coexist *btcoexist, u8 type); +void ex_halbtc8192e2ant_lps_notify(struct btc_coexist *btcoexist, u8 type); +void ex_halbtc8192e2ant_scan_notify(struct btc_coexist *btcoexist, u8 type); +void ex_halbtc8192e2ant_connect_notify(struct btc_coexist *btcoexist, u8 type); +void ex_halbtc8192e2ant_media_status_notify(struct btc_coexist *btcoexist, + u8 type); +void ex_halbtc8192e2ant_special_packet_notify(struct btc_coexist *btcoexist, + u8 type); +void ex_halbtc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist, + u8 *tmpbuf, u8 length); +void ex_halbtc8192e2ant_stack_operation_notify(struct btc_coexist *btcoexist, + u8 type); +void ex_halbtc8192e2ant_halt_notify(struct btc_coexist *btcoexist); +void ex_halbtc8192e2ant_periodical(struct btc_coexist *btcoexist); +void ex_halbtc8192e2ant_display_coex_info(struct btc_coexist *btcoexist); diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c new file mode 100644 index 000000000000..c4acd403e5f6 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c @@ -0,0 +1,3170 @@ +/****************************************************************************** + * + * Copyright(c) 2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +/*************************************************************** + * Description: + * + * This file is for RTL8723B Co-exist mechanism + * + * History + * 2012/11/15 Cosa first check in. + * + ***************************************************************/ + +/*************************************************************** + * include files + ***************************************************************/ +#include "halbt_precomp.h" +/*************************************************************** + * Global variables, these are static variables + ***************************************************************/ +static struct coex_dm_8723b_1ant glcoex_dm_8723b_1ant; +static struct coex_dm_8723b_1ant *coex_dm = &glcoex_dm_8723b_1ant; +static struct coex_sta_8723b_1ant glcoex_sta_8723b_1ant; +static struct coex_sta_8723b_1ant *coex_sta = &glcoex_sta_8723b_1ant; + +static const char *const GLBtInfoSrc8723b1Ant[] = { + "BT Info[wifi fw]", + "BT Info[bt rsp]", + "BT Info[bt auto report]", +}; + +static u32 glcoex_ver_date_8723b_1ant = 20130918; +static u32 glcoex_ver_8723b_1ant = 0x47; + +/*************************************************************** + * local function proto type if needed + ***************************************************************/ +/*************************************************************** + * local function start with halbtc8723b1ant_ + ***************************************************************/ +static u8 halbtc8723b1ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, + u8 rssi_thresh1) +{ + s32 bt_rssi = 0; + u8 bt_rssi_state = coex_sta->pre_bt_rssi_state; + + bt_rssi = coex_sta->bt_rssi; + + if (level_num == 2) { + if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || + (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { + if (bt_rssi >= rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { + bt_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); + } + } else { + if (bt_rssi < rssi_thresh) { + bt_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); + } + } + } else if (level_num == 3) { + if (rssi_thresh > rssi_thresh1) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi thresh error!!\n"); + return coex_sta->pre_bt_rssi_state; + } + + if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || + (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { + if (bt_rssi >= rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { + bt_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); + } + } else if ((coex_sta->pre_bt_rssi_state == + BTC_RSSI_STATE_MEDIUM) || + (coex_sta->pre_bt_rssi_state == + BTC_RSSI_STATE_STAY_MEDIUM)) { + if (bt_rssi >= rssi_thresh1 + + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { + bt_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); + } else if (bt_rssi < rssi_thresh) { + bt_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Medium\n"); + } + } else { + if (bt_rssi < rssi_thresh1) { + bt_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); + } + } + } + + coex_sta->pre_bt_rssi_state = bt_rssi_state; + + return bt_rssi_state; +} + +static u8 halbtc8723b1ant_wifi_rssi_state(struct btc_coexist *btcoexist, + u8 index, u8 level_num, + u8 rssi_thresh, u8 rssi_thresh1) +{ + s32 wifi_rssi = 0; + u8 wifi_rssi_state = coex_sta->pre_wifi_rssi_state[index]; + + btcoexist->btc_get(btcoexist, + BTC_GET_S4_WIFI_RSSI, &wifi_rssi); + + if (level_num == 2) { + if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_LOW) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_LOW)) { + if (wifi_rssi >= rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { + wifi_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); + } + } else { + if (wifi_rssi < rssi_thresh) { + wifi_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); + } + } + } else if (level_num == 3) { + if (rssi_thresh > rssi_thresh1) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI thresh error!!\n"); + return coex_sta->pre_wifi_rssi_state[index]; + } + + if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_LOW) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_LOW)) { + if (wifi_rssi >= rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { + wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); + } + } else if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_MEDIUM) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_MEDIUM)) { + if (wifi_rssi >= rssi_thresh1 + + BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { + wifi_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); + } else if (wifi_rssi < rssi_thresh) { + wifi_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Medium\n"); + } + } else { + if (wifi_rssi < rssi_thresh1) { + wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); + } + } + } + + coex_sta->pre_wifi_rssi_state[index] = wifi_rssi_state; + + return wifi_rssi_state; +} + +static void halbtc8723b1ant_updatera_mask(struct btc_coexist *btcoexist, + bool force_exec, u32 dis_rate_mask) +{ + coex_dm->curra_mask = dis_rate_mask; + + if (force_exec || (coex_dm->prera_mask != coex_dm->curra_mask)) + btcoexist->btc_set(btcoexist, BTC_SET_ACT_UPDATE_ra_mask, + &coex_dm->curra_mask); + + coex_dm->prera_mask = coex_dm->curra_mask; +} + +static void btc8723b1ant_auto_rate_fb_retry(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + bool wifi_under_bmode = false; + + coex_dm->cur_arfr_type = type; + + if (force_exec || (coex_dm->pre_arfr_type != coex_dm->cur_arfr_type)) { + switch (coex_dm->cur_arfr_type) { + case 0: /* normal mode */ + btcoexist->btc_write_4byte(btcoexist, 0x430, + coex_dm->backup_arfr_cnt1); + btcoexist->btc_write_4byte(btcoexist, 0x434, + coex_dm->backup_arfr_cnt2); + break; + case 1: + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_UNDER_B_MODE, + &wifi_under_bmode); + if (wifi_under_bmode) { + btcoexist->btc_write_4byte(btcoexist, + 0x430, 0x0); + btcoexist->btc_write_4byte(btcoexist, + 0x434, 0x01010101); + } else { + btcoexist->btc_write_4byte(btcoexist, + 0x430, 0x0); + btcoexist->btc_write_4byte(btcoexist, + 0x434, 0x04030201); + } + break; + default: + break; + } + } + + coex_dm->pre_arfr_type = coex_dm->cur_arfr_type; +} + +static void halbtc8723b1ant_retry_limit(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + coex_dm->cur_retry_limit_type = type; + + if (force_exec || (coex_dm->pre_retry_limit_type != + coex_dm->cur_retry_limit_type)) { + switch (coex_dm->cur_retry_limit_type) { + case 0: /* normal mode */ + btcoexist->btc_write_2byte(btcoexist, 0x42a, + coex_dm->backup_retry_limit); + break; + case 1: /* retry limit = 8 */ + btcoexist->btc_write_2byte(btcoexist, 0x42a, 0x0808); + break; + default: + break; + } + } + + coex_dm->pre_retry_limit_type = coex_dm->cur_retry_limit_type; +} + +static void halbtc8723b1ant_ampdu_maxtime(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + coex_dm->cur_ampdu_time_type = type; + + if (force_exec || (coex_dm->pre_ampdu_time_type != + coex_dm->cur_ampdu_time_type)) { + switch (coex_dm->cur_ampdu_time_type) { + case 0: /* normal mode */ + btcoexist->btc_write_1byte(btcoexist, 0x456, + coex_dm->backup_ampdu_max_time); + break; + case 1: /* AMPDU timw = 0x38 * 32us */ + btcoexist->btc_write_1byte(btcoexist, + 0x456, 0x38); + break; + default: + break; + } + } + + coex_dm->pre_ampdu_time_type = coex_dm->cur_ampdu_time_type; +} + +static void halbtc8723b1ant_limited_tx(struct btc_coexist *btcoexist, + bool force_exec, u8 ra_masktype, + u8 arfr_type, u8 retry_limit_type, + u8 ampdu_time_type) +{ + switch (ra_masktype) { + case 0: /* normal mode */ + halbtc8723b1ant_updatera_mask(btcoexist, force_exec, 0x0); + break; + case 1: /* disable cck 1/2 */ + halbtc8723b1ant_updatera_mask(btcoexist, force_exec, + 0x00000003); + break; + /* disable cck 1/2/5.5, ofdm 6/9/12/18/24, mcs 0/1/2/3/4*/ + case 2: + halbtc8723b1ant_updatera_mask(btcoexist, force_exec, + 0x0001f1f7); + break; + default: + break; + } + + btc8723b1ant_auto_rate_fb_retry(btcoexist, force_exec, arfr_type); + halbtc8723b1ant_retry_limit(btcoexist, force_exec, retry_limit_type); + halbtc8723b1ant_ampdu_maxtime(btcoexist, force_exec, ampdu_time_type); +} + +static void halbtc8723b1ant_limited_rx(struct btc_coexist *btcoexist, + bool force_exec, bool rej_ap_agg_pkt, + bool bt_ctrl_agg_buf_size, + u8 agg_buf_size) +{ + bool reject_rx_agg = rej_ap_agg_pkt; + bool bt_ctrl_rx_agg_size = bt_ctrl_agg_buf_size; + u8 rxaggsize = agg_buf_size; + + /********************************************** + * Rx Aggregation related setting + **********************************************/ + btcoexist->btc_set(btcoexist, BTC_SET_BL_TO_REJ_AP_AGG_PKT, + &reject_rx_agg); + /* decide BT control aggregation buf size or not */ + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_CTRL_AGG_SIZE, + &bt_ctrl_rx_agg_size); + /* aggregation buf size, only work + * when BT control Rx aggregation size. + */ + btcoexist->btc_set(btcoexist, BTC_SET_U1_AGG_BUF_SIZE, &rxaggsize); + /* real update aggregation setting */ + btcoexist->btc_set(btcoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL); +} + +static void halbtc8723b1ant_monitor_bt_ctr(struct btc_coexist *btcoexist) +{ + u32 reg_hp_txrx, reg_lp_txrx, u32tmp; + u32 reg_hp_tx = 0, reg_hp_rx = 0; + u32 reg_lp_tx = 0, reg_lp_rx = 0; + + reg_hp_txrx = 0x770; + reg_lp_txrx = 0x774; + + u32tmp = btcoexist->btc_read_4byte(btcoexist, reg_hp_txrx); + reg_hp_tx = u32tmp & MASKLWORD; + reg_hp_rx = (u32tmp & MASKHWORD) >> 16; + + u32tmp = btcoexist->btc_read_4byte(btcoexist, reg_lp_txrx); + reg_lp_tx = u32tmp & MASKLWORD; + reg_lp_rx = (u32tmp & MASKHWORD) >> 16; + + coex_sta->high_priority_tx = reg_hp_tx; + coex_sta->high_priority_rx = reg_hp_rx; + coex_sta->low_priority_tx = reg_lp_tx; + coex_sta->low_priority_rx = reg_lp_rx; + + /* reset counter */ + btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); +} + +static void halbtc8723b1ant_query_bt_info(struct btc_coexist *btcoexist) +{ + u8 h2c_parameter[1] = {0}; + + coex_sta->c2h_bt_info_req_sent = true; + + h2c_parameter[0] |= BIT0; /* trigger*/ + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", + h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); +} + +static bool btc8723b1ant_is_wifi_status_changed(struct btc_coexist *btcoexist) +{ + static bool pre_wifi_busy; + static bool pre_under_4way, pre_bt_hs_on; + bool wifi_busy = false, under_4way = false, bt_hs_on = false; + bool wifi_connected = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, + &under_4way); + + if (wifi_connected) { + if (wifi_busy != pre_wifi_busy) { + pre_wifi_busy = wifi_busy; + return true; + } + if (under_4way != pre_under_4way) { + pre_under_4way = under_4way; + return true; + } + if (bt_hs_on != pre_bt_hs_on) { + pre_bt_hs_on = bt_hs_on; + return true; + } + } + + return false; +} + +static void halbtc8723b1ant_update_bt_link_info(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool bt_hs_on = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + + bt_link_info->bt_link_exist = coex_sta->bt_link_exist; + bt_link_info->sco_exist = coex_sta->sco_exist; + bt_link_info->a2dp_exist = coex_sta->a2dp_exist; + bt_link_info->pan_exist = coex_sta->pan_exist; + bt_link_info->hid_exist = coex_sta->hid_exist; + + /* work around for HS mode. */ + if (bt_hs_on) { + bt_link_info->pan_exist = true; + bt_link_info->bt_link_exist = true; + } + + /* check if Sco only */ + if (bt_link_info->sco_exist && !bt_link_info->a2dp_exist && + !bt_link_info->pan_exist && !bt_link_info->hid_exist) + bt_link_info->sco_only = true; + else + bt_link_info->sco_only = false; + + /* check if A2dp only */ + if (!bt_link_info->sco_exist && bt_link_info->a2dp_exist && + !bt_link_info->pan_exist && !bt_link_info->hid_exist) + bt_link_info->a2dp_only = true; + else + bt_link_info->a2dp_only = false; + + /* check if Pan only */ + if (!bt_link_info->sco_exist && !bt_link_info->a2dp_exist && + bt_link_info->pan_exist && !bt_link_info->hid_exist) + bt_link_info->pan_only = true; + else + bt_link_info->pan_only = false; + + /* check if Hid only */ + if (!bt_link_info->sco_exist && !bt_link_info->a2dp_exist && + !bt_link_info->pan_exist && bt_link_info->hid_exist) + bt_link_info->hid_only = true; + else + bt_link_info->hid_only = false; +} + +static u8 halbtc8723b1ant_action_algorithm(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool bt_hs_on = false; + u8 algorithm = BT_8723B_1ANT_COEX_ALGO_UNDEFINED; + u8 numdiffprofile = 0; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + + if (!bt_link_info->bt_link_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], No BT link exists!!!\n"); + return algorithm; + } + + if (bt_link_info->sco_exist) + numdiffprofile++; + if (bt_link_info->hid_exist) + numdiffprofile++; + if (bt_link_info->pan_exist) + numdiffprofile++; + if (bt_link_info->a2dp_exist) + numdiffprofile++; + + if (numdiffprofile == 1) { + if (bt_link_info->sco_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO only\n"); + algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; + } else { + if (bt_link_info->hid_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = HID only\n"); + algorithm = BT_8723B_1ANT_COEX_ALGO_HID; + } else if (bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = A2DP only\n"); + algorithm = BT_8723B_1ANT_COEX_ALGO_A2DP; + } else if (bt_link_info->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = PAN(HS) only\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_PANHS; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = PAN(EDR) only\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_PANEDR; + } + } + } + } else if (numdiffprofile == 2) { + if (bt_link_info->sco_exist) { + if (bt_link_info->hid_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID\n"); + algorithm = BT_8723B_1ANT_COEX_ALGO_HID; + } else if (bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + A2DP ==> SCO\n"); + algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; + } else if (bt_link_info->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + PAN(HS)\n"); + algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + PAN(EDR)\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; + } + } + } else { + if (bt_link_info->hid_exist && + bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = HID + A2DP\n"); + algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP; + } else if (bt_link_info->hid_exist && + bt_link_info->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = HID + PAN(HS)\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_HID_A2DP; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = HID + PAN(EDR)\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; + } + } else if (bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = A2DP + PAN(HS)\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = A2DP + PAN(EDR)\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP; + } + } + } + } else if (numdiffprofile == 3) { + if (bt_link_info->sco_exist) { + if (bt_link_info->hid_exist && + bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + A2DP ==> HID\n"); + algorithm = BT_8723B_1ANT_COEX_ALGO_HID; + } else if (bt_link_info->hid_exist && + bt_link_info->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + PAN(HS)\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_HID_A2DP; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + PAN(EDR)\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; + } + } else if (bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + A2DP + PAN(HS)\n"); + algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + A2DP + PAN(EDR) ==> HID\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; + } + } + } else { + if (bt_link_info->hid_exist && + bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = HID + A2DP + PAN(HS)\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_HID_A2DP; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = HID + A2DP + PAN(EDR)\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR; + } + } + } + } else if (numdiffprofile >= 3) { + if (bt_link_info->sco_exist) { + if (bt_link_info->hid_exist && + bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Error!!! BT Profile = SCO + HID + A2DP + PAN(HS)\n"); + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); + algorithm = + BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; + } + } + } + } + + return algorithm; +} + +static void btc8723b1ant_set_sw_pen_tx_rate_adapt(struct btc_coexist *btcoexist, + bool low_penalty_ra) +{ + u8 h2c_parameter[6] = {0}; + + h2c_parameter[0] = 0x6; /* opCode, 0x6= Retry_Penalty */ + + if (low_penalty_ra) { + h2c_parameter[1] |= BIT0; + /*normal rate except MCS7/6/5, OFDM54/48/36 */ + h2c_parameter[2] = 0x00; + h2c_parameter[3] = 0xf7; /*MCS7 or OFDM54 */ + h2c_parameter[4] = 0xf8; /*MCS6 or OFDM48 */ + h2c_parameter[5] = 0xf9; /*MCS5 or OFDM36 */ + } + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], set WiFi Low-Penalty Retry: %s", + (low_penalty_ra ? "ON!!" : "OFF!!")); + + btcoexist->btc_fill_h2c(btcoexist, 0x69, 6, h2c_parameter); +} + +static void halbtc8723b1ant_low_penalty_ra(struct btc_coexist *btcoexist, + bool force_exec, bool low_penalty_ra) +{ + coex_dm->cur_low_penalty_ra = low_penalty_ra; + + if (!force_exec) { + if (coex_dm->pre_low_penalty_ra == coex_dm->cur_low_penalty_ra) + return; + } + btc8723b1ant_set_sw_pen_tx_rate_adapt(btcoexist, + coex_dm->cur_low_penalty_ra); + + coex_dm->pre_low_penalty_ra = coex_dm->cur_low_penalty_ra; +} + +static void halbtc8723b1ant_set_coex_table(struct btc_coexist *btcoexist, + u32 val0x6c0, u32 val0x6c4, + u32 val0x6c8, u8 val0x6cc) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); + btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); + btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); + btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); + btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); +} + +static void halbtc8723b1ant_coex_table(struct btc_coexist *btcoexist, + bool force_exec, u32 val0x6c0, + u32 val0x6c4, u32 val0x6c8, + u8 val0x6cc) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6cc = 0x%x\n", + (force_exec ? "force to" : ""), + val0x6c0, val0x6c4, val0x6cc); + coex_dm->cur_val0x6c0 = val0x6c0; + coex_dm->cur_val0x6c4 = val0x6c4; + coex_dm->cur_val0x6c8 = val0x6c8; + coex_dm->cur_val0x6cc = val0x6cc; + + if (!force_exec) { + if ((coex_dm->pre_val0x6c0 == coex_dm->cur_val0x6c0) && + (coex_dm->pre_val0x6c4 == coex_dm->cur_val0x6c4) && + (coex_dm->pre_val0x6c8 == coex_dm->cur_val0x6c8) && + (coex_dm->pre_val0x6cc == coex_dm->cur_val0x6cc)) + return; + } + halbtc8723b1ant_set_coex_table(btcoexist, val0x6c0, val0x6c4, + val0x6c8, val0x6cc); + + coex_dm->pre_val0x6c0 = coex_dm->cur_val0x6c0; + coex_dm->pre_val0x6c4 = coex_dm->cur_val0x6c4; + coex_dm->pre_val0x6c8 = coex_dm->cur_val0x6c8; + coex_dm->pre_val0x6cc = coex_dm->cur_val0x6cc; +} + +static void halbtc8723b1ant_coex_table_with_type(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + switch (type) { + case 0: + halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555, + 0x55555555, 0xffffff, 0x3); + break; + case 1: + halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555, + 0x5a5a5a5a, 0xffffff, 0x3); + break; + case 2: + halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a, + 0x5a5a5a5a, 0xffffff, 0x3); + break; + case 3: + halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555, + 0xaaaaaaaa, 0xffffff, 0x3); + break; + case 4: + halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555, + 0x5aaa5aaa, 0xffffff, 0x3); + break; + case 5: + halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a, + 0xaaaa5a5a, 0xffffff, 0x3); + break; + case 6: + halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555, + 0xaaaa5a5a, 0xffffff, 0x3); + break; + case 7: + halbtc8723b1ant_coex_table(btcoexist, force_exec, 0xaaaaaaaa, + 0xaaaaaaaa, 0xffffff, 0x3); + break; + default: + break; + } +} + +static void halbtc8723b1ant_SetFwIgnoreWlanAct(struct btc_coexist *btcoexist, + bool enable) +{ + u8 h2c_parameter[1] = {0}; + + if (enable) + h2c_parameter[0] |= BIT0; /* function enable */ + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", + h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); +} + +static void halbtc8723b1ant_ignore_wlan_act(struct btc_coexist *btcoexist, + bool force_exec, bool enable) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s turn Ignore WlanAct %s\n", + (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); + coex_dm->cur_ignore_wlan_act = enable; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], bPreIgnoreWlanAct = %d, bCurIgnoreWlanAct = %d!!\n", + coex_dm->pre_ignore_wlan_act, + coex_dm->cur_ignore_wlan_act); + + if (coex_dm->pre_ignore_wlan_act == + coex_dm->cur_ignore_wlan_act) + return; + } + halbtc8723b1ant_SetFwIgnoreWlanAct(btcoexist, enable); + + coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; +} + +static void halbtc8723b1ant_set_fw_ps_tdma(struct btc_coexist *btcoexist, + u8 byte1, u8 byte2, u8 byte3, + u8 byte4, u8 byte5) +{ + u8 h2c_parameter[5] = {0}; + u8 real_byte1 = byte1, real_byte5 = byte5; + bool ap_enable = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, + &ap_enable); + + if (ap_enable) { + if ((byte1 & BIT4) && !(byte1 & BIT5)) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], FW for 1Ant AP mode\n"); + real_byte1 &= ~BIT4; + real_byte1 |= BIT5; + + real_byte5 |= BIT5; + real_byte5 &= ~BIT6; + } + } + + h2c_parameter[0] = real_byte1; + h2c_parameter[1] = byte2; + h2c_parameter[2] = byte3; + h2c_parameter[3] = byte4; + h2c_parameter[4] = real_byte5; + + coex_dm->ps_tdma_para[0] = real_byte1; + coex_dm->ps_tdma_para[1] = byte2; + coex_dm->ps_tdma_para[2] = byte3; + coex_dm->ps_tdma_para[3] = byte4; + coex_dm->ps_tdma_para[4] = real_byte5; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], PS-TDMA H2C cmd =0x%x%08x\n", + h2c_parameter[0], + h2c_parameter[1] << 24 | + h2c_parameter[2] << 16 | + h2c_parameter[3] << 8 | + h2c_parameter[4]); + + btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); +} + +static void halbtc8723b1ant_set_lps_rpwm(struct btc_coexist *btcoexist, + u8 lps_val, u8 rpwm_val) +{ + u8 lps = lps_val; + u8 rpwm = rpwm_val; + + btcoexist->btc_set(btcoexist, BTC_SET_U1_LPS_VAL, &lps); + btcoexist->btc_set(btcoexist, BTC_SET_U1_RPWM_VAL, &rpwm); +} + +static void halbtc8723b1ant_LpsRpwm(struct btc_coexist *btcoexist, + bool force_exec, + u8 lps_val, u8 rpwm_val) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s set lps/rpwm = 0x%x/0x%x\n", + (force_exec ? "force to" : ""), lps_val, rpwm_val); + coex_dm->cur_lps = lps_val; + coex_dm->cur_rpwm = rpwm_val; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], LPS-RxBeaconMode = 0x%x , LPS-RPWM = 0x%x!!\n", + coex_dm->cur_lps, coex_dm->cur_rpwm); + + if ((coex_dm->pre_lps == coex_dm->cur_lps) && + (coex_dm->pre_rpwm == coex_dm->cur_rpwm)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], LPS-RPWM_Last = 0x%x , LPS-RPWM_Now = 0x%x!!\n", + coex_dm->pre_rpwm, coex_dm->cur_rpwm); + + return; + } + } + halbtc8723b1ant_set_lps_rpwm(btcoexist, lps_val, rpwm_val); + + coex_dm->pre_lps = coex_dm->cur_lps; + coex_dm->pre_rpwm = coex_dm->cur_rpwm; +} + +static void halbtc8723b1ant_sw_mechanism(struct btc_coexist *btcoexist, + bool low_penalty_ra) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], SM[LpRA] = %d\n", low_penalty_ra); + + halbtc8723b1ant_low_penalty_ra(btcoexist, NORMAL_EXEC, low_penalty_ra); +} + +static void halbtc8723b1ant_SetAntPath(struct btc_coexist *btcoexist, + u8 ant_pos_type, bool init_hw_cfg, + bool wifi_off) +{ + struct btc_board_info *board_info = &btcoexist->board_info; + u32 fw_ver = 0, u32tmp = 0; + bool pg_ext_switch = false; + bool use_ext_switch = false; + u8 h2c_parameter[2] = {0}; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_EXT_SWITCH, &pg_ext_switch); + /* [31:16] = fw ver, [15:0] = fw sub ver */ + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); + + if ((fw_ver < 0xc0000) || pg_ext_switch) + use_ext_switch = true; + + if (init_hw_cfg) { + /*BT select s0/s1 is controlled by WiFi */ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67, 0x20, 0x1); + + /*Force GNT_BT to Normal */ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x0); + } else if (wifi_off) { + /*Force GNT_BT to High */ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x3); + /*BT select s0/s1 is controlled by BT */ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67, 0x20, 0x0); + + /* 0x4c[24:23] = 00, Set Antenna control by BT_RFE_CTRL + * BT Vendor 0xac = 0xf002 + */ + u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); + u32tmp &= ~BIT23; + u32tmp &= ~BIT24; + btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp); + } + + if (use_ext_switch) { + if (init_hw_cfg) { + /* 0x4c[23] = 0, 0x4c[24] = 1 + * Antenna control by WL/BT + */ + u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); + u32tmp &= ~BIT23; + u32tmp |= BIT24; + btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp); + + if (board_info->btdm_ant_pos == + BTC_ANTENNA_AT_MAIN_PORT) { + /* Main Ant to BT for IPS case 0x4c[23] = 1 */ + btcoexist->btc_write_1byte_bitmask(btcoexist, + 0x64, 0x1, + 0x1); + + /*tell firmware "no antenna inverse"*/ + h2c_parameter[0] = 0; + h2c_parameter[1] = 1; /*ext switch type*/ + btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, + h2c_parameter); + } else { + /*Aux Ant to BT for IPS case 0x4c[23] = 1 */ + btcoexist->btc_write_1byte_bitmask(btcoexist, + 0x64, 0x1, + 0x0); + + /*tell firmware "antenna inverse"*/ + h2c_parameter[0] = 1; + h2c_parameter[1] = 1; /*ext switch type*/ + btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, + h2c_parameter); + } + } + + /* fixed internal switch first*/ + /* fixed internal switch S1->WiFi, S0->BT*/ + if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) + btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0); + else/* fixed internal switch S0->WiFi, S1->BT*/ + btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280); + + /* ext switch setting */ + switch (ant_pos_type) { + case BTC_ANT_PATH_WIFI: + if (board_info->btdm_ant_pos == + BTC_ANTENNA_AT_MAIN_PORT) + btcoexist->btc_write_1byte_bitmask(btcoexist, + 0x92c, 0x3, + 0x1); + else + btcoexist->btc_write_1byte_bitmask(btcoexist, + 0x92c, 0x3, + 0x2); + break; + case BTC_ANT_PATH_BT: + if (board_info->btdm_ant_pos == + BTC_ANTENNA_AT_MAIN_PORT) + btcoexist->btc_write_1byte_bitmask(btcoexist, + 0x92c, 0x3, + 0x2); + else + btcoexist->btc_write_1byte_bitmask(btcoexist, + 0x92c, 0x3, + 0x1); + break; + default: + case BTC_ANT_PATH_PTA: + if (board_info->btdm_ant_pos == + BTC_ANTENNA_AT_MAIN_PORT) + btcoexist->btc_write_1byte_bitmask(btcoexist, + 0x92c, 0x3, + 0x1); + else + btcoexist->btc_write_1byte_bitmask(btcoexist, + 0x92c, 0x3, + 0x2); + break; + } + + } else { + if (init_hw_cfg) { + /* 0x4c[23] = 1, 0x4c[24] = 0 Antenna control by 0x64*/ + u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); + u32tmp |= BIT23; + u32tmp &= ~BIT24; + btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp); + + if (board_info->btdm_ant_pos == + BTC_ANTENNA_AT_MAIN_PORT) { + /*Main Ant to WiFi for IPS case 0x4c[23] = 1*/ + btcoexist->btc_write_1byte_bitmask(btcoexist, + 0x64, 0x1, + 0x0); + + /*tell firmware "no antenna inverse"*/ + h2c_parameter[0] = 0; + h2c_parameter[1] = 0; /*internal switch type*/ + btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, + h2c_parameter); + } else { + /*Aux Ant to BT for IPS case 0x4c[23] = 1*/ + btcoexist->btc_write_1byte_bitmask(btcoexist, + 0x64, 0x1, + 0x1); + + /*tell firmware "antenna inverse"*/ + h2c_parameter[0] = 1; + h2c_parameter[1] = 0; /*internal switch type*/ + btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, + h2c_parameter); + } + } + + /* fixed external switch first*/ + /*Main->WiFi, Aux->BT*/ + if (board_info->btdm_ant_pos == + BTC_ANTENNA_AT_MAIN_PORT) + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x92c, + 0x3, 0x1); + else/*Main->BT, Aux->WiFi */ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x92c, + 0x3, 0x2); + + /* internal switch setting*/ + switch (ant_pos_type) { + case BTC_ANT_PATH_WIFI: + if (board_info->btdm_ant_pos == + BTC_ANTENNA_AT_MAIN_PORT) + btcoexist->btc_write_2byte(btcoexist, 0x948, + 0x0); + else + btcoexist->btc_write_2byte(btcoexist, 0x948, + 0x280); + break; + case BTC_ANT_PATH_BT: + if (board_info->btdm_ant_pos == + BTC_ANTENNA_AT_MAIN_PORT) + btcoexist->btc_write_2byte(btcoexist, 0x948, + 0x280); + else + btcoexist->btc_write_2byte(btcoexist, 0x948, + 0x0); + break; + default: + case BTC_ANT_PATH_PTA: + if (board_info->btdm_ant_pos == + BTC_ANTENNA_AT_MAIN_PORT) + btcoexist->btc_write_2byte(btcoexist, 0x948, + 0x200); + else + btcoexist->btc_write_2byte(btcoexist, 0x948, + 0x80); + break; + } + } +} + +static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist, + bool force_exec, bool turn_on, u8 type) +{ + bool wifi_busy = false; + u8 rssi_adjust_val = 0; + + coex_dm->cur_ps_tdma_on = turn_on; + coex_dm->cur_ps_tdma = type; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + + if (!force_exec) { + if (coex_dm->cur_ps_tdma_on) + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], ******** TDMA(on, %d) *********\n", + coex_dm->cur_ps_tdma); + else + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], ******** TDMA(off, %d) ********\n", + coex_dm->cur_ps_tdma); + + if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && + (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) + return; + } + if (turn_on) { + switch (type) { + default: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x1a, + 0x1a, 0x0, 0x50); + break; + case 1: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x3a, + 0x03, 0x10, 0x50); + + rssi_adjust_val = 11; + break; + case 2: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x2b, + 0x03, 0x10, 0x50); + rssi_adjust_val = 14; + break; + case 3: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x1d, + 0x1d, 0x0, 0x52); + break; + case 4: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x15, + 0x3, 0x14, 0x0); + rssi_adjust_val = 17; + break; + case 5: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x15, + 0x3, 0x11, 0x10); + break; + case 6: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x20, + 0x3, 0x11, 0x13); + break; + case 7: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xc, + 0x5, 0x0, 0x0); + break; + case 8: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x25, + 0x3, 0x10, 0x0); + break; + case 9: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x21, + 0x3, 0x10, 0x50); + rssi_adjust_val = 18; + break; + case 10: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xa, + 0xa, 0x0, 0x40); + break; + case 11: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x15, + 0x03, 0x10, 0x50); + rssi_adjust_val = 20; + break; + case 12: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x0a, + 0x0a, 0x0, 0x50); + break; + case 13: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x15, + 0x15, 0x0, 0x50); + break; + case 14: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x21, + 0x3, 0x10, 0x52); + break; + case 15: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xa, + 0x3, 0x8, 0x0); + break; + case 16: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x15, + 0x3, 0x10, 0x0); + rssi_adjust_val = 18; + break; + case 18: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x25, + 0x3, 0x10, 0x0); + rssi_adjust_val = 14; + break; + case 20: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x35, + 0x03, 0x11, 0x10); + break; + case 21: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x25, + 0x03, 0x11, 0x11); + break; + case 22: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x25, + 0x03, 0x11, 0x10); + break; + case 23: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x25, + 0x3, 0x31, 0x18); + rssi_adjust_val = 22; + break; + case 24: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x15, + 0x3, 0x31, 0x18); + rssi_adjust_val = 22; + break; + case 25: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0xa, + 0x3, 0x31, 0x18); + rssi_adjust_val = 22; + break; + case 26: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0xa, + 0x3, 0x31, 0x18); + rssi_adjust_val = 22; + break; + case 27: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x25, + 0x3, 0x31, 0x98); + rssi_adjust_val = 22; + break; + case 28: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x69, 0x25, + 0x3, 0x31, 0x0); + break; + case 29: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xab, 0x1a, + 0x1a, 0x1, 0x10); + break; + case 30: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x14, + 0x3, 0x10, 0x50); + break; + case 31: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xd3, 0x1a, + 0x1a, 0, 0x58); + break; + case 32: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0xa, + 0x3, 0x10, 0x0); + break; + case 33: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xa3, 0x25, + 0x3, 0x30, 0x90); + break; + case 34: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x53, 0x1a, + 0x1a, 0x0, 0x10); + break; + case 35: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x63, 0x1a, + 0x1a, 0x0, 0x10); + break; + case 36: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xd3, 0x12, + 0x3, 0x14, 0x50); + break; + /* SoftAP only with no sta associated,BT disable , + * TDMA mode for power saving + * here softap mode screen off will cost 70-80mA for phone + */ + case 40: + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x23, 0x18, + 0x00, 0x10, 0x24); + break; + } + } else { + switch (type) { + case 8: /*PTA Control */ + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x8, 0x0, + 0x0, 0x0, 0x0); + halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_PTA, + false, false); + break; + case 0: + default: /*Software control, Antenna at BT side */ + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0, + 0x0, 0x0, 0x0); + halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_BT, + false, false); + break; + case 9: /*Software control, Antenna at WiFi side */ + halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0, + 0x0, 0x0, 0x0); + halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_WIFI, + false, false); + break; + } + } + rssi_adjust_val = 0; + btcoexist->btc_set(btcoexist, + BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE, + &rssi_adjust_val); + + /* update pre state */ + coex_dm->pre_ps_tdma_on = coex_dm->cur_ps_tdma_on; + coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; +} + +static bool halbtc8723b1ant_is_common_action(struct btc_coexist *btcoexist) +{ + bool commom = false, wifi_connected = false; + bool wifi_busy = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + + if (!wifi_connected && + BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == coex_dm->bt_status) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi non connected-idle + BT non connected-idle!!\n"); + halbtc8723b1ant_sw_mechanism(btcoexist, false); + commom = true; + } else if (wifi_connected && + (BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == + coex_dm->bt_status)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi connected + BT non connected-idle!!\n"); + halbtc8723b1ant_sw_mechanism(btcoexist, false); + commom = true; + } else if (!wifi_connected && + (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == + coex_dm->bt_status)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi non connected-idle + BT connected-idle!!\n"); + halbtc8723b1ant_sw_mechanism(btcoexist, false); + commom = true; + } else if (wifi_connected && + (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == + coex_dm->bt_status)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi connected + BT connected-idle!!\n"); + halbtc8723b1ant_sw_mechanism(btcoexist, false); + commom = true; + } else if (!wifi_connected && + (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE != + coex_dm->bt_status)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + ("[BTCoex], Wifi non connected-idle + BT Busy!!\n")); + halbtc8723b1ant_sw_mechanism(btcoexist, false); + commom = true; + } else { + if (wifi_busy) + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi Connected-Busy + BT Busy!!\n"); + else + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi Connected-Idle + BT Busy!!\n"); + + commom = false; + } + + return commom; +} + +static void btc8723b1ant_tdma_dur_adj_for_acl(struct btc_coexist *btcoexist, + u8 wifi_status) +{ + static s32 up, dn, m, n, wait_count; + /* 0: no change, +1: increase WiFi duration, + * -1: decrease WiFi duration + */ + s32 result; + u8 retry_count = 0, bt_info_ext; + bool wifi_busy = false; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], TdmaDurationAdjustForAcl()\n"); + + if (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY == wifi_status) + wifi_busy = true; + else + wifi_busy = false; + + if ((BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN == + wifi_status) || + (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN == wifi_status) || + (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT == wifi_status)) { + if (coex_dm->cur_ps_tdma != 1 && coex_dm->cur_ps_tdma != 2 && + coex_dm->cur_ps_tdma != 3 && coex_dm->cur_ps_tdma != 9) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + + up = 0; + dn = 0; + m = 1; + n = 3; + result = 0; + wait_count = 0; + } + return; + } + + if (!coex_dm->auto_tdma_adjust) { + coex_dm->auto_tdma_adjust = true; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], first run TdmaDurationAdjust()!!\n"); + + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); + coex_dm->tdma_adj_type = 2; + + up = 0; + dn = 0; + m = 1; + n = 3; + result = 0; + wait_count = 0; + } else { + /*accquire the BT TRx retry count from BT_Info byte2 */ + retry_count = coex_sta->bt_retry_cnt; + bt_info_ext = coex_sta->bt_info_ext; + result = 0; + wait_count++; + /* no retry in the last 2-second duration */ + if (retry_count == 0) { + up++; + dn--; + + if (dn <= 0) + dn = 0; + + if (up >= n) { + wait_count = 0; + n = 3; + up = 0; + dn = 0; + result = 1; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], Increase wifi duration!!\n"); + } + } else if (retry_count <= 3) { + up--; + dn++; + + if (up <= 0) + up = 0; + + if (dn == 2) { + if (wait_count <= 2) + m++; + else + m = 1; + + if (m >= 20) + m = 20; + + n = 3 * m; + up = 0; + dn = 0; + wait_count = 0; + result = -1; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retryCounter<3!!\n"); + } + } else { + if (wait_count == 1) + m++; + else + m = 1; + + if (m >= 20) + m = 20; + + n = 3 * m; + up = 0; + dn = 0; + wait_count = 0; + result = -1; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retryCounter>3!!\n"); + } + + if (result == -1) { + if ((BT_INFO_8723B_1ANT_A2DP_BASIC_RATE(bt_info_ext)) && + ((coex_dm->cur_ps_tdma == 1) || + (coex_dm->cur_ps_tdma == 2))) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (coex_dm->cur_ps_tdma == 1) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (coex_dm->cur_ps_tdma == 9) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } + } else if (result == 1) { + if ((BT_INFO_8723B_1ANT_A2DP_BASIC_RATE(bt_info_ext)) && + ((coex_dm->cur_ps_tdma == 1) || + (coex_dm->cur_ps_tdma == 2))) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (coex_dm->cur_ps_tdma == 9) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 1); + coex_dm->tdma_adj_type = 1; + } + } else { /*no change */ + /*if busy / idle change */ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex],********* TDMA(on, %d) ********\n", + coex_dm->cur_ps_tdma); + } + + if (coex_dm->cur_ps_tdma != 1 && coex_dm->cur_ps_tdma != 2 && + coex_dm->cur_ps_tdma != 9 && coex_dm->cur_ps_tdma != 11) { + /* recover to previous adjust type */ + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, + coex_dm->tdma_adj_type); + } + } +} + +static void btc8723b1ant_pstdmachkpwrsave(struct btc_coexist *btcoexist, + bool new_ps_state) +{ + u8 lps_mode = 0x0; + + btcoexist->btc_get(btcoexist, BTC_GET_U1_LPS_MODE, &lps_mode); + + if (lps_mode) { /* already under LPS state */ + if (new_ps_state) { + /* keep state under LPS, do nothing. */ + } else { + /* will leave LPS state, turn off psTdma first */ + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 0); + } + } else { /* NO PS state */ + if (new_ps_state) { + /* will enter LPS state, turn off psTdma first */ + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 0); + } else { + /* keep state under NO PS state, do nothing. */ + } + } +} + +static void halbtc8723b1ant_power_save_state(struct btc_coexist *btcoexist, + u8 ps_type, u8 lps_val, + u8 rpwm_val) +{ + bool low_pwr_disable = false; + + switch (ps_type) { + case BTC_PS_WIFI_NATIVE: + /* recover to original 32k low power setting */ + low_pwr_disable = false; + btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + btcoexist->btc_set(btcoexist, BTC_SET_ACT_NORMAL_LPS, NULL); + break; + case BTC_PS_LPS_ON: + btc8723b1ant_pstdmachkpwrsave(btcoexist, true); + halbtc8723b1ant_LpsRpwm(btcoexist, NORMAL_EXEC, lps_val, + rpwm_val); + /* when coex force to enter LPS, do not enter 32k low power. */ + low_pwr_disable = true; + btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + /* power save must executed before psTdma. */ + btcoexist->btc_set(btcoexist, BTC_SET_ACT_ENTER_LPS, NULL); + break; + case BTC_PS_LPS_OFF: + btc8723b1ant_pstdmachkpwrsave(btcoexist, false); + btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS, NULL); + break; + default: + break; + } +} + +/*************************************************** + * + * Software Coex Mechanism start + * + ***************************************************/ +/* SCO only or SCO+PAN(HS) */ +static void halbtc8723b1ant_action_sco(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_sw_mechanism(btcoexist, true); +} + +static void halbtc8723b1ant_action_hid(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_sw_mechanism(btcoexist, true); +} + +/*A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */ +static void halbtc8723b1ant_action_a2dp(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_sw_mechanism(btcoexist, false); +} + +static void halbtc8723b1ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_sw_mechanism(btcoexist, false); +} + +static void halbtc8723b1ant_action_pan_edr(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_sw_mechanism(btcoexist, false); +} + +/* PAN(HS) only */ +static void halbtc8723b1ant_action_pan_hs(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_sw_mechanism(btcoexist, false); +} + +/*PAN(EDR)+A2DP */ +static void halbtc8723b1ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_sw_mechanism(btcoexist, false); +} + +static void halbtc8723b1ant_action_pan_edr_hid(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_sw_mechanism(btcoexist, true); +} + +/* HID+A2DP+PAN(EDR) */ +static void btc8723b1ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_sw_mechanism(btcoexist, true); +} + +static void halbtc8723b1ant_action_hid_a2dp(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_sw_mechanism(btcoexist, true); +} + +/***************************************************** + * + * Non-Software Coex Mechanism start + * + *****************************************************/ +static void halbtc8723b1ant_action_wifi_multiport(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); +} + +static void halbtc8723b1ant_action_hs(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); +} + +static void halbtc8723b1ant_action_bt_inquiry(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool wifi_connected = false, ap_enable = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, + &ap_enable); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + + if (!wifi_connected) { + halbtc8723b1ant_power_save_state(btcoexist, + BTC_PS_WIFI_NATIVE, 0x0, 0x0); + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); + } else if (bt_link_info->sco_exist || bt_link_info->hid_only) { + /* SCO/HID-only busy */ + halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + } else { + if (ap_enable) + halbtc8723b1ant_power_save_state(btcoexist, + BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + else + halbtc8723b1ant_power_save_state(btcoexist, + BTC_PS_LPS_ON, + 0x50, 0x4); + + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 30); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + } +} + +static void btc8723b1ant_act_bt_sco_hid_only_busy(struct btc_coexist *btcoexist, + u8 wifi_status) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool wifi_connected = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + + /* tdma and coex table */ + + if (bt_link_info->sco_exist) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); + } else { /* HID */ + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 6); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5); + } +} + +static void halbtc8723b1ant_action_wifi_connected_bt_acl_busy( + struct btc_coexist *btcoexist, + u8 wifi_status) +{ + u8 bt_rssi_state; + + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + + bt_rssi_state = halbtc8723b1ant_bt_rssi_state(2, 28, 0); + + if (bt_link_info->hid_only) { /*HID */ + btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist, wifi_status); + coex_dm->auto_tdma_adjust = false; + return; + } else if (bt_link_info->a2dp_only) { /*A2DP */ + if (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE == wifi_status) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 8); + halbtc8723b1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 2); + coex_dm->auto_tdma_adjust = false; + } else if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b1ant_tdma_dur_adj_for_acl(btcoexist, + wifi_status); + halbtc8723b1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 1); + } else { /*for low BT RSSI */ + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + halbtc8723b1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 1); + coex_dm->auto_tdma_adjust = false; + } + } else if (bt_link_info->hid_exist && + bt_link_info->a2dp_exist) { /*HID+A2DP */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->auto_tdma_adjust = false; + } else { /*for low BT RSSI*/ + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->auto_tdma_adjust = false; + } + + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 6); + /*PAN(OPP,FTP), HID+PAN(OPP,FTP) */ + } else if (bt_link_info->pan_only || + (bt_link_info->hid_exist && bt_link_info->pan_exist)) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 6); + coex_dm->auto_tdma_adjust = false; + /*A2DP+PAN(OPP,FTP), HID+A2DP+PAN(OPP,FTP)*/ + } else if ((bt_link_info->a2dp_exist && bt_link_info->pan_exist) || + (bt_link_info->hid_exist && bt_link_info->a2dp_exist && + bt_link_info->pan_exist)) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + coex_dm->auto_tdma_adjust = false; + } else { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + coex_dm->auto_tdma_adjust = false; + } +} + +static void btc8723b1ant_action_wifi_not_conn(struct btc_coexist *btcoexist) +{ + /* power save state */ + halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + + /* tdma and coex table */ + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0); +} + +static void btc8723b1ant_action_wifi_not_conn_scan(struct btc_coexist *btcoex) +{ + struct btc_bt_link_info *bt_link_info = &btcoex->bt_link_info; + + halbtc8723b1ant_power_save_state(btcoex, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + + /* tdma and coex table */ + if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { + if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) { + halbtc8723b1ant_ps_tdma(btcoex, NORMAL_EXEC, + true, 22); + halbtc8723b1ant_coex_table_with_type(btcoex, + NORMAL_EXEC, 1); + } else if (bt_link_info->pan_only) { + halbtc8723b1ant_ps_tdma(btcoex, NORMAL_EXEC, + true, 20); + halbtc8723b1ant_coex_table_with_type(btcoex, + NORMAL_EXEC, 2); + } else { + halbtc8723b1ant_ps_tdma(btcoex, NORMAL_EXEC, + true, 20); + halbtc8723b1ant_coex_table_with_type(btcoex, + NORMAL_EXEC, 1); + } + } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || + (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == + coex_dm->bt_status)){ + btc8723b1ant_act_bt_sco_hid_only_busy(btcoex, + BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN); + } else { + halbtc8723b1ant_ps_tdma(btcoex, NORMAL_EXEC, false, 8); + halbtc8723b1ant_coex_table_with_type(btcoex, NORMAL_EXEC, 2); + } +} + +static void btc8723b1ant_act_wifi_not_conn_asso_auth(struct btc_coexist *btcoex) +{ + struct btc_bt_link_info *bt_link_info = &btcoex->bt_link_info; + + halbtc8723b1ant_power_save_state(btcoex, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + + if ((BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == coex_dm->bt_status) || + (bt_link_info->sco_exist) || (bt_link_info->hid_only) || + (bt_link_info->a2dp_only) || (bt_link_info->pan_only)) { + halbtc8723b1ant_ps_tdma(btcoex, NORMAL_EXEC, false, 8); + halbtc8723b1ant_coex_table_with_type(btcoex, NORMAL_EXEC, 7); + } else { + halbtc8723b1ant_ps_tdma(btcoex, NORMAL_EXEC, true, 20); + halbtc8723b1ant_coex_table_with_type(btcoex, NORMAL_EXEC, 1); + } +} + +static void btc8723b1ant_action_wifi_conn_scan(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + + halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + + /* tdma and coex table */ + if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { + if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 22); + halbtc8723b1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 1); + } else if (bt_link_info->pan_only) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 20); + halbtc8723b1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 2); + } else { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 20); + halbtc8723b1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 1); + } + } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || + (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == + coex_dm->bt_status)) { + btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist, + BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN); + } else { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); + } +} + +static void halbtc8723b1ant_action_wifi_connected_special_packet( + struct btc_coexist *btcoexist) +{ + bool hs_connecting = false; + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_CONNECTING, &hs_connecting); + + halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + + /* tdma and coex table */ + if ((BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == coex_dm->bt_status) || + (bt_link_info->sco_exist) || (bt_link_info->hid_only) || + (bt_link_info->a2dp_only) || (bt_link_info->pan_only)) { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7); + } else { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + } +} + +static void halbtc8723b1ant_action_wifi_connected(struct btc_coexist *btcoexist) +{ + bool wifi_busy = false; + bool scan = false, link = false, roam = false; + bool under_4way = false, ap_enable = false; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], CoexForWifiConnect()===>\n"); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, + &under_4way); + if (under_4way) { + halbtc8723b1ant_action_wifi_connected_special_packet(btcoexist); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], CoexForWifiConnect(), return for wifi is under 4way<===\n"); + return; + } + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); + + if (scan || link || roam) { + if (scan) + btc8723b1ant_action_wifi_conn_scan(btcoexist); + else + halbtc8723b1ant_action_wifi_connected_special_packet( + btcoexist); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n"); + return; + } + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, + &ap_enable); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + /* power save state */ + if (!ap_enable && + BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status && + !btcoexist->bt_link_info.hid_only) { + if (!wifi_busy && btcoexist->bt_link_info.a2dp_only) + halbtc8723b1ant_power_save_state(btcoexist, + BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + else + halbtc8723b1ant_power_save_state(btcoexist, + BTC_PS_LPS_ON, + 0x50, 0x4); + } else { + halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + } + /* tdma and coex table */ + if (!wifi_busy) { + if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { + halbtc8723b1ant_action_wifi_connected_bt_acl_busy(btcoexist, + BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE); + } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY == + coex_dm->bt_status) || + (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == + coex_dm->bt_status)) { + btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist, + BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE); + } else { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 8); + halbtc8723b1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 2); + } + } else { + if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { + halbtc8723b1ant_action_wifi_connected_bt_acl_busy(btcoexist, + BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY); + } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY == + coex_dm->bt_status) || + (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == + coex_dm->bt_status)) { + btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist, + BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY); + } else { + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 8); + halbtc8723b1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 2); + } + } +} + +static void btc8723b1ant_run_sw_coex_mech(struct btc_coexist *btcoexist) +{ + u8 algorithm = 0; + + algorithm = halbtc8723b1ant_action_algorithm(btcoexist); + coex_dm->cur_algorithm = algorithm; + + if (!halbtc8723b1ant_is_common_action(btcoexist)) { + switch (coex_dm->cur_algorithm) { + case BT_8723B_1ANT_COEX_ALGO_SCO: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = SCO.\n"); + halbtc8723b1ant_action_sco(btcoexist); + break; + case BT_8723B_1ANT_COEX_ALGO_HID: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = HID.\n"); + halbtc8723b1ant_action_hid(btcoexist); + break; + case BT_8723B_1ANT_COEX_ALGO_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = A2DP.\n"); + halbtc8723b1ant_action_a2dp(btcoexist); + break; + case BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = A2DP+PAN(HS).\n"); + halbtc8723b1ant_action_a2dp_pan_hs(btcoexist); + break; + case BT_8723B_1ANT_COEX_ALGO_PANEDR: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = PAN(EDR).\n"); + halbtc8723b1ant_action_pan_edr(btcoexist); + break; + case BT_8723B_1ANT_COEX_ALGO_PANHS: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = HS mode.\n"); + halbtc8723b1ant_action_pan_hs(btcoexist); + break; + case BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = PAN+A2DP.\n"); + halbtc8723b1ant_action_pan_edr_a2dp(btcoexist); + break; + case BT_8723B_1ANT_COEX_ALGO_PANEDR_HID: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = PAN(EDR)+HID.\n"); + halbtc8723b1ant_action_pan_edr_hid(btcoexist); + break; + case BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = HID+A2DP+PAN.\n"); + btc8723b1ant_action_hid_a2dp_pan_edr(btcoexist); + break; + case BT_8723B_1ANT_COEX_ALGO_HID_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = HID+A2DP.\n"); + halbtc8723b1ant_action_hid_a2dp(btcoexist); + break; + default: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = coexist All Off!!\n"); + break; + } + coex_dm->pre_algorithm = coex_dm->cur_algorithm; + } +} + +static void halbtc8723b1ant_run_coexist_mechanism(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool wifi_connected = false, bt_hs_on = false; + bool increase_scan_dev_num = false; + bool bt_ctrl_agg_buf_size = false; + u8 agg_buf_size = 5; + u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH; + u32 wifi_link_status = 0; + u32 num_of_wifi_link = 0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], RunCoexistMechanism()===>\n"); + + if (btcoexist->manual_control) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n"); + return; + } + + if (btcoexist->stop_coex_dm) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), return for Stop Coex DM <===\n"); + return; + } + + if (coex_sta->under_ips) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], wifi is under IPS !!!\n"); + return; + } + + if ((BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || + (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || + (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) { + increase_scan_dev_num = true; + } + + btcoexist->btc_set(btcoexist, BTC_SET_BL_INC_SCAN_DEV_NUM, + &increase_scan_dev_num); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS, + &wifi_link_status); + num_of_wifi_link = wifi_link_status >> 16; + if (num_of_wifi_link >= 2) { + halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); + halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false, + bt_ctrl_agg_buf_size, + agg_buf_size); + halbtc8723b1ant_action_wifi_multiport(btcoexist); + return; + } + + if (!bt_link_info->sco_exist && !bt_link_info->hid_exist) { + halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); + } else { + if (wifi_connected) { + wifi_rssi_state = + halbtc8723b1ant_wifi_rssi_state(btcoexist, + 1, 2, 30, 0); + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8723b1ant_limited_tx(btcoexist, + NORMAL_EXEC, + 1, 1, 1, 1); + } else { + halbtc8723b1ant_limited_tx(btcoexist, + NORMAL_EXEC, + 1, 1, 1, 1); + } + } else { + halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, + 0, 0, 0, 0); + } + } + + if (bt_link_info->sco_exist) { + bt_ctrl_agg_buf_size = true; + agg_buf_size = 0x3; + } else if (bt_link_info->hid_exist) { + bt_ctrl_agg_buf_size = true; + agg_buf_size = 0x5; + } else if (bt_link_info->a2dp_exist || bt_link_info->pan_exist) { + bt_ctrl_agg_buf_size = true; + agg_buf_size = 0x8; + } + halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false, + bt_ctrl_agg_buf_size, agg_buf_size); + + btc8723b1ant_run_sw_coex_mech(btcoexist); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + + if (coex_sta->c2h_bt_inquiry_page) { + halbtc8723b1ant_action_bt_inquiry(btcoexist); + return; + } else if (bt_hs_on) { + halbtc8723b1ant_action_hs(btcoexist); + return; + } + + if (!wifi_connected) { + bool scan = false, link = false, roam = false; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], wifi is non connected-idle !!!\n"); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); + + if (scan || link || roam) { + if (scan) + btc8723b1ant_action_wifi_not_conn_scan( + btcoexist); + else + btc8723b1ant_act_wifi_not_conn_asso_auth( + btcoexist); + } else { + btc8723b1ant_action_wifi_not_conn(btcoexist); + } + } else { /* wifi LPS/Busy */ + halbtc8723b1ant_action_wifi_connected(btcoexist); + } +} + +static void halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist) +{ + /* sw all off */ + halbtc8723b1ant_sw_mechanism(btcoexist, false); + + halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8); + halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0); +} + +static void halbtc8723b1ant_init_hw_config(struct btc_coexist *btcoexist, + bool backup) +{ + u32 u32tmp = 0; + u8 u8tmp = 0; + u32 cnt_bt_cal_chk = 0; + + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], 1Ant Init HW Config!!\n"); + + if (backup) {/* backup rf 0x1e value */ + coex_dm->backup_arfr_cnt1 = + btcoexist->btc_read_4byte(btcoexist, 0x430); + coex_dm->backup_arfr_cnt2 = + btcoexist->btc_read_4byte(btcoexist, 0x434); + coex_dm->backup_retry_limit = + btcoexist->btc_read_2byte(btcoexist, 0x42a); + coex_dm->backup_ampdu_max_time = + btcoexist->btc_read_1byte(btcoexist, 0x456); + } + + /* WiFi goto standby while GNT_BT 0-->1 */ + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x780); + /* BT goto standby while GNT_BT 1-->0 */ + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x2, 0xfffff, 0x500); + + btcoexist->btc_write_1byte(btcoexist, 0x974, 0xff); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x944, 0x3, 0x3); + btcoexist->btc_write_1byte(btcoexist, 0x930, 0x77); + + /* BT calibration check */ + while (cnt_bt_cal_chk <= 20) { + u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x49d); + cnt_bt_cal_chk++; + if (u32tmp & BIT0) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], ########### BT calibration(cnt=%d) ###########\n", + cnt_bt_cal_chk); + mdelay(50); + } else { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], ********** BT NOT calibration (cnt=%d)**********\n", + cnt_bt_cal_chk); + break; + } + } + + /* 0x790[5:0] = 0x5 */ + u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x790); + u8tmp &= 0xc0; + u8tmp |= 0x5; + btcoexist->btc_write_1byte(btcoexist, 0x790, u8tmp); + + /* Enable counter statistics */ + /*0x76e[3] =1, WLAN_Act control by PTA */ + btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); + btcoexist->btc_write_1byte(btcoexist, 0x778, 0x1); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1); + + /*Antenna config */ + halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_PTA, true, false); + /* PTA parameter */ + halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0); +} + +static void halbtc8723b1ant_wifi_off_hw_cfg(struct btc_coexist *btcoexist) +{ + /* set wlan_act to low */ + btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4); +} + +/************************************************************** + * work around function start with wa_halbtc8723b1ant_ + **************************************************************/ +/************************************************************** + * extern function start with EXhalbtc8723b1ant_ + **************************************************************/ + +void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist) +{ + halbtc8723b1ant_init_hw_config(btcoexist, true); +} + +void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist) +{ + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], Coex Mechanism Init!!\n"); + + btcoexist->stop_coex_dm = false; + + halbtc8723b1ant_init_coex_dm(btcoexist); + + halbtc8723b1ant_query_bt_info(btcoexist); +} + +void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist) +{ + struct btc_board_info *board_info = &btcoexist->board_info; + struct btc_stack_info *stack_info = &btcoexist->stack_info; + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + struct rtl_priv *rtlpriv = btcoexist->adapter; + u8 u8tmp[4], i, bt_info_ext, pstdmacase = 0; + u16 u16tmp[4]; + u32 u32tmp[4]; + bool roam = false, scan = false; + bool link = false, wifi_under_5g = false; + bool bt_hs_on = false, wifi_busy = false; + s32 wifi_rssi = 0, bt_hs_rssi = 0; + u32 wifi_bw, wifi_traffic_dir, fa_ofdm, fa_cck, wifi_link_status; + u8 wifi_dot11_chnl, wifi_hs_chnl; + u32 fw_ver = 0, bt_patch_ver = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n ============[BT Coexist info]============"); + + if (btcoexist->manual_control) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n ============[Under Manual Control]=========="); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n =========================================="); + } + if (btcoexist->stop_coex_dm) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n ============[Coex is STOPPED]============"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n =========================================="); + } + + if (!board_info->bt_exist) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n BT not exists !!!"); + return; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d", + "Ant PG Num/ Ant Mech/ Ant Pos:", + board_info->pg_ant_num, board_info->btdm_ant_num, + board_info->btdm_ant_pos); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s / %d", + "BT stack/ hci ext ver", + ((stack_info->profile_notified) ? "Yes" : "No"), + stack_info->hci_version); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d_%x/ 0x%x/ 0x%x(%d)", + "CoexVer/ FwVer/ PatchVer", + glcoex_ver_date_8723b_1ant, glcoex_ver_8723b_1ant, + fw_ver, bt_patch_ver, bt_patch_ver); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_DOT11_CHNL, + &wifi_dot11_chnl); + btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_HS_CHNL, &wifi_hs_chnl); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d / %d(%d)", + "Dot11 channel / HsChnl(HsMode)", + wifi_dot11_chnl, wifi_hs_chnl, bt_hs_on); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %02x %02x %02x ", + "H2C Wifi inform bt chnl Info", + coex_dm->wifi_chnl_info[0], coex_dm->wifi_chnl_info[1], + coex_dm->wifi_chnl_info[2]); + + btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); + btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", + "Wifi rssi/ HS rssi", wifi_rssi, bt_hs_rssi); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d ", + "Wifi link/ roam/ scan", link, roam, scan); + + btcoexist->btc_get(btcoexist , BTC_GET_BL_WIFI_UNDER_5G, + &wifi_under_5g); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, + &wifi_traffic_dir); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s / %s/ %s ", + "Wifi status", (wifi_under_5g ? "5G" : "2.4G"), + ((BTC_WIFI_BW_LEGACY == wifi_bw) ? "Legacy" : + (((BTC_WIFI_BW_HT40 == wifi_bw) ? "HT40" : "HT20"))), + ((!wifi_busy) ? "idle" : + ((BTC_WIFI_TRAFFIC_TX == wifi_traffic_dir) ? + "uplink" : "downlink"))); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS, + &wifi_link_status); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d/ %d/ %d", + "sta/vwifi/hs/p2pGo/p2pGc", + ((wifi_link_status & WIFI_STA_CONNECTED) ? 1 : 0), + ((wifi_link_status & WIFI_AP_CONNECTED) ? 1 : 0), + ((wifi_link_status & WIFI_HS_CONNECTED) ? 1 : 0), + ((wifi_link_status & WIFI_P2P_GO_CONNECTED) ? 1 : 0), + ((wifi_link_status & WIFI_P2P_GC_CONNECTED) ? 1 : 0)); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = [%s/ %d/ %d] ", + "BT [status/ rssi/ retryCnt]", + ((btcoexist->bt_info.bt_disabled) ? ("disabled") : + ((coex_sta->c2h_bt_inquiry_page) ? ("inquiry/page scan") : + ((BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == + coex_dm->bt_status) ? + "non-connected idle" : + ((BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == + coex_dm->bt_status) ? + "connected-idle" : "busy")))), + coex_sta->bt_rssi, coex_sta->bt_retry_cnt); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d / %d / %d / %d", + "SCO/HID/PAN/A2DP", bt_link_info->sco_exist, + bt_link_info->hid_exist, bt_link_info->pan_exist, + bt_link_info->a2dp_exist); + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_BT_LINK_INFO); + + bt_info_ext = coex_sta->bt_info_ext; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s", + "BT Info A2DP rate", + (bt_info_ext & BIT0) ? "Basic rate" : "EDR rate"); + + for (i = 0; i < BT_INFO_SRC_8723B_1ANT_MAX; i++) { + if (coex_sta->bt_info_c2h_cnt[i]) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)", + GLBtInfoSrc8723b1Ant[i], + coex_sta->bt_info_c2h[i][0], + coex_sta->bt_info_c2h[i][1], + coex_sta->bt_info_c2h[i][2], + coex_sta->bt_info_c2h[i][3], + coex_sta->bt_info_c2h[i][4], + coex_sta->bt_info_c2h[i][5], + coex_sta->bt_info_c2h[i][6], + coex_sta->bt_info_c2h_cnt[i]); + } + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %s/%s, (0x%x/0x%x)", + "PS state, IPS/LPS, (lps/rpwm)", + ((coex_sta->under_ips ? "IPS ON" : "IPS OFF")), + ((coex_sta->under_lps ? "LPS ON" : "LPS OFF")), + btcoexist->bt_info.lps_val, + btcoexist->bt_info.rpwm_val); + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD); + + if (!btcoexist->manual_control) { + /* Sw mechanism */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", + "============[Sw mechanism]============"); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/", + "SM[LowPenaltyRA]", coex_dm->cur_low_penalty_ra); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s/ %s/ %d ", + "DelBA/ BtCtrlAgg/ AggSize", + (btcoexist->bt_info.reject_agg_pkt ? "Yes" : "No"), + (btcoexist->bt_info.bt_ctrl_buf_size ? "Yes" : "No"), + btcoexist->bt_info.agg_buf_size); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x ", + "Rate Mask", btcoexist->bt_info.ra_mask); + + /* Fw mechanism */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", + "============[Fw mechanism]============"); + + pstdmacase = coex_dm->cur_ps_tdma; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", + "PS TDMA", coex_dm->ps_tdma_para[0], + coex_dm->ps_tdma_para[1], coex_dm->ps_tdma_para[2], + coex_dm->ps_tdma_para[3], coex_dm->ps_tdma_para[4], + pstdmacase, coex_dm->auto_tdma_adjust); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d ", + "IgnWlanAct", coex_dm->cur_ignore_wlan_act); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x ", + "Latest error condition(should be 0)", + coex_dm->error_condition); + } + + /* Hw setting */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", + "============[Hw setting]============"); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", + "backup ARFR1/ARFR2/RL/AMaxTime", coex_dm->backup_arfr_cnt1, + coex_dm->backup_arfr_cnt2, coex_dm->backup_retry_limit, + coex_dm->backup_ampdu_max_time); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x430); + u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x434); + u16tmp[0] = btcoexist->btc_read_2byte(btcoexist, 0x42a); + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x456); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", + "0x430/0x434/0x42a/0x456", + u32tmp[0], u32tmp[1], u16tmp[0], u8tmp[0]); + + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x778); + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6cc); + u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x880); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "0x778/0x6cc/0x880[29:25]", u8tmp[0], u32tmp[0], + (u32tmp[1] & 0x3e000000) >> 25); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x948); + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x67); + u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x765); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "0x948/ 0x67[5] / 0x765", + u32tmp[0], ((u8tmp[0] & 0x20) >> 5), u8tmp[1]); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x92c); + u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x930); + u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x944); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "0x92c[1:0]/ 0x930[7:0]/0x944[1:0]", + u32tmp[0] & 0x3, u32tmp[1] & 0xff, u32tmp[2] & 0x3); + + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x39); + u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x40); + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x4c); + u8tmp[2] = btcoexist->btc_read_1byte(btcoexist, 0x64); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", + "0x38[11]/0x40/0x4c[24:23]/0x64[0]", + ((u8tmp[0] & 0x8)>>3), u8tmp[1], + ((u32tmp[0] & 0x01800000) >> 23), u8tmp[2] & 0x1); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x550); + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x522); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "0x550(bcn ctrl)/0x522", u32tmp[0], u8tmp[0]); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc50); + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x49c); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "0xc50(dig)/0x49c(null-drop)", u32tmp[0] & 0xff, u8tmp[0]); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xda0); + u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0xda4); + u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0xda8); + u32tmp[3] = btcoexist->btc_read_4byte(btcoexist, 0xcf0); + + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xa5b); + u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xa5c); + + fa_ofdm = ((u32tmp[0] & 0xffff0000) >> 16) + + ((u32tmp[1] & 0xffff0000) >> 16) + + (u32tmp[1] & 0xffff) + + (u32tmp[2] & 0xffff) + + ((u32tmp[3] & 0xffff0000) >> 16) + + (u32tmp[3] & 0xffff); + fa_cck = (u8tmp[0] << 8) + u8tmp[1]; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "OFDM-CCA/OFDM-FA/CCK-FA", + u32tmp[0] & 0xffff, fa_ofdm, fa_cck); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6c0); + u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x6c4); + u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x6c8); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "0x6c0/0x6c4/0x6c8(coexTable)", + u32tmp[0], u32tmp[1], u32tmp[2]); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", + "0x770(high-pri rx/tx)", coex_sta->high_priority_rx, + coex_sta->high_priority_tx); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", + "0x774(low-pri rx/tx)", coex_sta->low_priority_rx, + coex_sta->low_priority_tx); +#if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 1) + halbtc8723b1ant_monitor_bt_ctr(btcoexist); +#endif + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS); +} + +void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (btcoexist->manual_control || btcoexist->stop_coex_dm) + return; + + if (BTC_IPS_ENTER == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], IPS ENTER notify\n"); + coex_sta->under_ips = true; + + halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_BT, + false, true); + /* set PTA control */ + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0); + halbtc8723b1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 0); + halbtc8723b1ant_wifi_off_hw_cfg(btcoexist); + } else if (BTC_IPS_LEAVE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], IPS LEAVE notify\n"); + coex_sta->under_ips = false; + + halbtc8723b1ant_init_hw_config(btcoexist, false); + halbtc8723b1ant_init_coex_dm(btcoexist); + halbtc8723b1ant_query_bt_info(btcoexist); + } +} + +void ex_halbtc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (btcoexist->manual_control || btcoexist->stop_coex_dm) + return; + + if (BTC_LPS_ENABLE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], LPS ENABLE notify\n"); + coex_sta->under_lps = true; + } else if (BTC_LPS_DISABLE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], LPS DISABLE notify\n"); + coex_sta->under_lps = false; + } +} + +void ex_halbtc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type) +{ + bool wifi_connected = false, bt_hs_on = false; + u32 wifi_link_status = 0; + u32 num_of_wifi_link = 0; + bool bt_ctrl_agg_buf_size = false; + u8 agg_buf_size = 5; + + if (btcoexist->manual_control || btcoexist->stop_coex_dm || + btcoexist->bt_info.bt_disabled) + return; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + + halbtc8723b1ant_query_bt_info(btcoexist); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS, + &wifi_link_status); + num_of_wifi_link = wifi_link_status >> 16; + if (num_of_wifi_link >= 2) { + halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); + halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false, + bt_ctrl_agg_buf_size, agg_buf_size); + halbtc8723b1ant_action_wifi_multiport(btcoexist); + return; + } + + if (coex_sta->c2h_bt_inquiry_page) { + halbtc8723b1ant_action_bt_inquiry(btcoexist); + return; + } else if (bt_hs_on) { + halbtc8723b1ant_action_hs(btcoexist); + return; + } + + if (BTC_SCAN_START == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], SCAN START notify\n"); + if (!wifi_connected) /* non-connected scan */ + btc8723b1ant_action_wifi_not_conn_scan(btcoexist); + else /* wifi is connected */ + btc8723b1ant_action_wifi_conn_scan(btcoexist); + } else if (BTC_SCAN_FINISH == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], SCAN FINISH notify\n"); + if (!wifi_connected) /* non-connected scan */ + btc8723b1ant_action_wifi_not_conn(btcoexist); + else + halbtc8723b1ant_action_wifi_connected(btcoexist); + } +} + +void ex_halbtc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type) +{ + bool wifi_connected = false, bt_hs_on = false; + u32 wifi_link_status = 0; + u32 num_of_wifi_link = 0; + bool bt_ctrl_agg_buf_size = false; + u8 agg_buf_size = 5; + + if (btcoexist->manual_control || btcoexist->stop_coex_dm || + btcoexist->bt_info.bt_disabled) + return; + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS, + &wifi_link_status); + num_of_wifi_link = wifi_link_status>>16; + if (num_of_wifi_link >= 2) { + halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); + halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false, + bt_ctrl_agg_buf_size, agg_buf_size); + halbtc8723b1ant_action_wifi_multiport(btcoexist); + return; + } + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + if (coex_sta->c2h_bt_inquiry_page) { + halbtc8723b1ant_action_bt_inquiry(btcoexist); + return; + } else if (bt_hs_on) { + halbtc8723b1ant_action_hs(btcoexist); + return; + } + + if (BTC_ASSOCIATE_START == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], CONNECT START notify\n"); + btc8723b1ant_act_wifi_not_conn_asso_auth(btcoexist); + } else if (BTC_ASSOCIATE_FINISH == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], CONNECT FINISH notify\n"); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + if (!wifi_connected) /* non-connected scan */ + btc8723b1ant_action_wifi_not_conn(btcoexist); + else + halbtc8723b1ant_action_wifi_connected(btcoexist); + } +} + +void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist, + u8 type) +{ + u8 h2c_parameter[3] = {0}; + u32 wifi_bw; + u8 wifiCentralChnl; + + if (btcoexist->manual_control || btcoexist->stop_coex_dm || + btcoexist->bt_info.bt_disabled) + return; + + if (BTC_MEDIA_CONNECT == type) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], MEDIA connect notify\n"); + else + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], MEDIA disconnect notify\n"); + + /* only 2.4G we need to inform bt the chnl mask */ + btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, + &wifiCentralChnl); + + if ((BTC_MEDIA_CONNECT == type) && + (wifiCentralChnl <= 14)) { + h2c_parameter[0] = 0x0; + h2c_parameter[1] = wifiCentralChnl; + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) + h2c_parameter[2] = 0x30; + else + h2c_parameter[2] = 0x20; + } + + coex_dm->wifi_chnl_info[0] = h2c_parameter[0]; + coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; + coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x66 = 0x%x\n", + h2c_parameter[0] << 16 | h2c_parameter[1] << 8 | + h2c_parameter[2]); + + btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); +} + +void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist, + u8 type) +{ + bool bt_hs_on = false; + u32 wifi_link_status = 0; + u32 num_of_wifi_link = 0; + bool bt_ctrl_agg_buf_size = false; + u8 agg_buf_size = 5; + + if (btcoexist->manual_control || btcoexist->stop_coex_dm || + btcoexist->bt_info.bt_disabled) + return; + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS, + &wifi_link_status); + num_of_wifi_link = wifi_link_status >> 16; + if (num_of_wifi_link >= 2) { + halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); + halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false, + bt_ctrl_agg_buf_size, agg_buf_size); + halbtc8723b1ant_action_wifi_multiport(btcoexist); + return; + } + + coex_sta->special_pkt_period_cnt = 0; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + if (coex_sta->c2h_bt_inquiry_page) { + halbtc8723b1ant_action_bt_inquiry(btcoexist); + return; + } else if (bt_hs_on) { + halbtc8723b1ant_action_hs(btcoexist); + return; + } + + if (BTC_PACKET_DHCP == type || + BTC_PACKET_EAPOL == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], special Packet(%d) notify\n", type); + halbtc8723b1ant_action_wifi_connected_special_packet(btcoexist); + } +} + +void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist, + u8 *tmp_buf, u8 length) +{ + u8 bt_info = 0; + u8 i, rsp_source = 0; + bool wifi_connected = false; + bool bt_busy = false; + + coex_sta->c2h_bt_info_req_sent = false; + + rsp_source = tmp_buf[0] & 0xf; + if (rsp_source >= BT_INFO_SRC_8723B_1ANT_MAX) + rsp_source = BT_INFO_SRC_8723B_1ANT_WIFI_FW; + coex_sta->bt_info_c2h_cnt[rsp_source]++; + + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], Bt info[%d], length=%d, hex data = [", + rsp_source, length); + for (i = 0; i < length; i++) { + coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i]; + if (i == 1) + bt_info = tmp_buf[i]; + if (i == length - 1) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "0x%02x]\n", tmp_buf[i]); + else + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "0x%02x, ", tmp_buf[i]); + } + + if (BT_INFO_SRC_8723B_1ANT_WIFI_FW != rsp_source) { + coex_sta->bt_retry_cnt = /* [3:0] */ + coex_sta->bt_info_c2h[rsp_source][2] & 0xf; + + coex_sta->bt_rssi = + coex_sta->bt_info_c2h[rsp_source][3] * 2 + 10; + + coex_sta->bt_info_ext = + coex_sta->bt_info_c2h[rsp_source][4]; + + /* Here we need to resend some wifi info to BT + * because bt is reset and loss of the info. + */ + if (coex_sta->bt_info_ext & BIT1) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n"); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + if (wifi_connected) + ex_halbtc8723b1ant_media_status_notify(btcoexist, + BTC_MEDIA_CONNECT); + else + ex_halbtc8723b1ant_media_status_notify(btcoexist, + BTC_MEDIA_DISCONNECT); + } + + if (coex_sta->bt_info_ext & BIT3) { + if (!btcoexist->manual_control && + !btcoexist->stop_coex_dm) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT ext info bit3 check, set BT NOT ignore Wlan active!!\n"); + halbtc8723b1ant_ignore_wlan_act(btcoexist, + FORCE_EXEC, + false); + } + } else { + /* BT already NOT ignore Wlan active, do nothing here.*/ + } +#if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 0) + if (coex_sta->bt_info_ext & BIT4) { + /* BT auto report already enabled, do nothing */ + } else { + halbtc8723b1ant_bt_auto_report(btcoexist, FORCE_EXEC, + true); + } +#endif + } + + /* check BIT2 first ==> check if bt is under inquiry or page scan */ + if (bt_info & BT_INFO_8723B_1ANT_B_INQ_PAGE) + coex_sta->c2h_bt_inquiry_page = true; + else + coex_sta->c2h_bt_inquiry_page = false; + + /* set link exist status */ + if (!(bt_info & BT_INFO_8723B_1ANT_B_CONNECTION)) { + coex_sta->bt_link_exist = false; + coex_sta->pan_exist = false; + coex_sta->a2dp_exist = false; + coex_sta->hid_exist = false; + coex_sta->sco_exist = false; + } else { /* connection exists */ + coex_sta->bt_link_exist = true; + if (bt_info & BT_INFO_8723B_1ANT_B_FTP) + coex_sta->pan_exist = true; + else + coex_sta->pan_exist = false; + if (bt_info & BT_INFO_8723B_1ANT_B_A2DP) + coex_sta->a2dp_exist = true; + else + coex_sta->a2dp_exist = false; + if (bt_info & BT_INFO_8723B_1ANT_B_HID) + coex_sta->hid_exist = true; + else + coex_sta->hid_exist = false; + if (bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO) + coex_sta->sco_exist = true; + else + coex_sta->sco_exist = false; + } + + halbtc8723b1ant_update_bt_link_info(btcoexist); + + if (!(bt_info&BT_INFO_8723B_1ANT_B_CONNECTION)) { + coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Non-Connected idle!\n"); + /* connection exists but no busy */ + } else if (bt_info == BT_INFO_8723B_1ANT_B_CONNECTION) { + coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"); + } else if ((bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO) || + (bt_info & BT_INFO_8723B_1ANT_B_SCO_BUSY)) { + coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_SCO_BUSY; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"); + } else if (bt_info & BT_INFO_8723B_1ANT_B_ACL_BUSY) { + if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY != coex_dm->bt_status) + coex_dm->auto_tdma_adjust = false; + + coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_ACL_BUSY; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"); + } else { + coex_dm->bt_status = + BT_8723B_1ANT_BT_STATUS_MAX; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Non-Defined state!!\n"); + } + + if ((BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || + (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || + (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) + bt_busy = true; + else + bt_busy = false; + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy); + + halbtc8723b1ant_run_coexist_mechanism(btcoexist); +} + +void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist) +{ + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "[BTCoex], Halt notify\n"); + + btcoexist->stop_coex_dm = true; + + halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_BT, false, true); + + halbtc8723b1ant_wifi_off_hw_cfg(btcoexist); + halbtc8723b1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); + + halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0); + + ex_halbtc8723b1ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT); +} + +void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state) +{ + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "[BTCoex], Pnp notify\n"); + + if (BTC_WIFI_PNP_SLEEP == pnp_state) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], Pnp notify to SLEEP\n"); + btcoexist->stop_coex_dm = true; + halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_BT, false, + true); + halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0); + halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); + halbtc8723b1ant_wifi_off_hw_cfg(btcoexist); + } else if (BTC_WIFI_PNP_WAKE_UP == pnp_state) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], Pnp notify to WAKE UP\n"); + btcoexist->stop_coex_dm = false; + halbtc8723b1ant_init_hw_config(btcoexist, false); + halbtc8723b1ant_init_coex_dm(btcoexist); + halbtc8723b1ant_query_bt_info(btcoexist); + } +} + +void ex_halbtc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], *****************Coex DM Reset****************\n"); + + halbtc8723b1ant_init_hw_config(btcoexist, false); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x2, 0xfffff, 0x0); + halbtc8723b1ant_init_coex_dm(btcoexist); +} + +void ex_halbtc8723b1ant_periodical(struct btc_coexist *btcoexist) +{ + struct btc_board_info *board_info = &btcoexist->board_info; + struct btc_stack_info *stack_info = &btcoexist->stack_info; + static u8 dis_ver_info_cnt; + u32 fw_ver = 0, bt_patch_ver = 0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], ==========================Periodical===========================\n"); + + if (dis_ver_info_cnt <= 5) { + dis_ver_info_cnt += 1; + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], ****************************************************************\n"); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", + board_info->pg_ant_num, board_info->btdm_ant_num, + board_info->btdm_ant_pos); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], BT stack/ hci ext ver = %s / %d\n", + ((stack_info->profile_notified) ? "Yes" : "No"), + stack_info->hci_version); + btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, + &bt_patch_ver); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", + glcoex_ver_date_8723b_1ant, + glcoex_ver_8723b_1ant, fw_ver, + bt_patch_ver, bt_patch_ver); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], ****************************************************************\n"); + } + +#if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 0) + halbtc8723b1ant_query_bt_info(btcoexist); + halbtc8723b1ant_monitor_bt_ctr(btcoexist); + halbtc8723b1ant_monitor_bt_enable_disable(btcoexist); +#else + if (btc8723b1ant_is_wifi_status_changed(btcoexist) || + coex_dm->auto_tdma_adjust) { + halbtc8723b1ant_run_coexist_mechanism(btcoexist); + } + + coex_sta->special_pkt_period_cnt++; +#endif +} diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h new file mode 100644 index 000000000000..75f8094b7a34 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.h @@ -0,0 +1,184 @@ +/****************************************************************************** + * + * Copyright(c) 2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +/********************************************************************** + * The following is for 8723B 1ANT BT Co-exist definition + **********************************************************************/ +#define BT_AUTO_REPORT_ONLY_8723B_1ANT 1 + +#define BT_INFO_8723B_1ANT_B_FTP BIT7 +#define BT_INFO_8723B_1ANT_B_A2DP BIT6 +#define BT_INFO_8723B_1ANT_B_HID BIT5 +#define BT_INFO_8723B_1ANT_B_SCO_BUSY BIT4 +#define BT_INFO_8723B_1ANT_B_ACL_BUSY BIT3 +#define BT_INFO_8723B_1ANT_B_INQ_PAGE BIT2 +#define BT_INFO_8723B_1ANT_B_SCO_ESCO BIT1 +#define BT_INFO_8723B_1ANT_B_CONNECTION BIT0 + +#define BT_INFO_8723B_1ANT_A2DP_BASIC_RATE(_BT_INFO_EXT_) \ + (((_BT_INFO_EXT_&BIT0)) ? true : false) + +#define BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT 2 + +enum _BT_INFO_SRC_8723B_1ANT { + BT_INFO_SRC_8723B_1ANT_WIFI_FW = 0x0, + BT_INFO_SRC_8723B_1ANT_BT_RSP = 0x1, + BT_INFO_SRC_8723B_1ANT_BT_ACTIVE_SEND = 0x2, + BT_INFO_SRC_8723B_1ANT_MAX +}; + +enum _BT_8723B_1ANT_BT_STATUS { + BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0, + BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE = 0x1, + BT_8723B_1ANT_BT_STATUS_INQ_PAGE = 0x2, + BT_8723B_1ANT_BT_STATUS_ACL_BUSY = 0x3, + BT_8723B_1ANT_BT_STATUS_SCO_BUSY = 0x4, + BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY = 0x5, + BT_8723B_1ANT_BT_STATUS_MAX +}; + +enum _BT_8723B_1ANT_WIFI_STATUS { + BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_IDLE = 0x0, + BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN = 0x1, + BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN = 0x2, + BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT = 0x3, + BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE = 0x4, + BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY = 0x5, + BT_8723B_1ANT_WIFI_STATUS_MAX +}; + +enum _BT_8723B_1ANT_COEX_ALGO { + BT_8723B_1ANT_COEX_ALGO_UNDEFINED = 0x0, + BT_8723B_1ANT_COEX_ALGO_SCO = 0x1, + BT_8723B_1ANT_COEX_ALGO_HID = 0x2, + BT_8723B_1ANT_COEX_ALGO_A2DP = 0x3, + BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS = 0x4, + BT_8723B_1ANT_COEX_ALGO_PANEDR = 0x5, + BT_8723B_1ANT_COEX_ALGO_PANHS = 0x6, + BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP = 0x7, + BT_8723B_1ANT_COEX_ALGO_PANEDR_HID = 0x8, + BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x9, + BT_8723B_1ANT_COEX_ALGO_HID_A2DP = 0xa, + BT_8723B_1ANT_COEX_ALGO_MAX = 0xb, +}; + +struct coex_dm_8723b_1ant { + /* fw mechanism */ + bool cur_ignore_wlan_act; + bool pre_ignore_wlan_act; + u8 pre_ps_tdma; + u8 cur_ps_tdma; + u8 ps_tdma_para[5]; + u8 tdma_adj_type; + bool auto_tdma_adjust; + bool pre_ps_tdma_on; + bool cur_ps_tdma_on; + bool pre_bt_auto_report; + bool cur_bt_auto_report; + u8 pre_lps; + u8 cur_lps; + u8 pre_rpwm; + u8 cur_rpwm; + + /* sw mechanism */ + bool pre_low_penalty_ra; + bool cur_low_penalty_ra; + u32 pre_val0x6c0; + u32 cur_val0x6c0; + u32 pre_val0x6c4; + u32 cur_val0x6c4; + u32 pre_val0x6c8; + u32 cur_val0x6c8; + u8 pre_val0x6cc; + u8 cur_val0x6cc; + bool limited_dig; + + u32 backup_arfr_cnt1; /* Auto Rate Fallback Retry cnt */ + u32 backup_arfr_cnt2; /* Auto Rate Fallback Retry cnt */ + u16 backup_retry_limit; + u8 backup_ampdu_max_time; + + /* algorithm related */ + u8 pre_algorithm; + u8 cur_algorithm; + u8 bt_status; + u8 wifi_chnl_info[3]; + + u32 prera_mask; + u32 curra_mask; + u8 pre_arfr_type; + u8 cur_arfr_type; + u8 pre_retry_limit_type; + u8 cur_retry_limit_type; + u8 pre_ampdu_time_type; + u8 cur_ampdu_time_type; + + u8 error_condition; +}; + +struct coex_sta_8723b_1ant { + bool bt_link_exist; + bool sco_exist; + bool a2dp_exist; + bool hid_exist; + bool pan_exist; + + bool under_lps; + bool under_ips; + u32 special_pkt_period_cnt; + u32 high_priority_tx; + u32 high_priority_rx; + u32 low_priority_tx; + u32 low_priority_rx; + u8 bt_rssi; + u8 pre_bt_rssi_state; + u8 pre_wifi_rssi_state[4]; + bool c2h_bt_info_req_sent; + u8 bt_info_c2h[BT_INFO_SRC_8723B_1ANT_MAX][10]; + u32 bt_info_c2h_cnt[BT_INFO_SRC_8723B_1ANT_MAX]; + bool c2h_bt_inquiry_page; + u8 bt_retry_cnt; + u8 bt_info_ext; +}; + +/************************************************************************* + * The following is interface which will notify coex module. + *************************************************************************/ +void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist); +void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist); +void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type); +void ex_halbtc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type); +void ex_halbtc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type); +void ex_halbtc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type); +void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist, + u8 type); +void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist, + u8 type); +void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist, + u8 *tmpbuf, u8 length); +void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist); +void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate); +void ex_halbtc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist); +void ex_halbtc8723b1ant_periodical(struct btc_coexist *btcoexist); +void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist); diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c new file mode 100644 index 000000000000..f2b9d11adc9e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c @@ -0,0 +1,3717 @@ +/****************************************************************************** + * + * Copyright(c) 2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +/*************************************************************** + * Description: + * + * This file is for RTL8723B Co-exist mechanism + * + * History + * 2012/11/15 Cosa first check in. + * + **************************************************************/ +/************************************************************** + * include files + **************************************************************/ +#include "halbt_precomp.h" +/************************************************************** + * Global variables, these are static variables + **************************************************************/ +static struct coex_dm_8723b_2ant glcoex_dm_8723b_2ant; +static struct coex_dm_8723b_2ant *coex_dm = &glcoex_dm_8723b_2ant; +static struct coex_sta_8723b_2ant glcoex_sta_8723b_2ant; +static struct coex_sta_8723b_2ant *coex_sta = &glcoex_sta_8723b_2ant; + +static const char *const glbt_info_src_8723b_2ant[] = { + "BT Info[wifi fw]", + "BT Info[bt rsp]", + "BT Info[bt auto report]", +}; + +static u32 glcoex_ver_date_8723b_2ant = 20131113; +static u32 glcoex_ver_8723b_2ant = 0x3f; + +/************************************************************** + * local function proto type if needed + **************************************************************/ +/************************************************************** + * local function start with btc8723b2ant_ + **************************************************************/ +static u8 btc8723b2ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, + u8 rssi_thresh1) +{ + s32 bt_rssi = 0; + u8 bt_rssi_state = coex_sta->pre_bt_rssi_state; + + bt_rssi = coex_sta->bt_rssi; + + if (level_num == 2) { + if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || + (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { + if (bt_rssi >= rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { + bt_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state " + "switch to High\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state " + "stay at Low\n"); + } + } else { + if (bt_rssi < rssi_thresh) { + bt_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state " + "switch to Low\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state " + "stay at High\n"); + } + } + } else if (level_num == 3) { + if (rssi_thresh > rssi_thresh1) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi thresh error!!\n"); + return coex_sta->pre_bt_rssi_state; + } + + if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || + (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { + if (bt_rssi >= rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { + bt_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state " + "switch to Medium\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state " + "stay at Low\n"); + } + } else if ((coex_sta->pre_bt_rssi_state == + BTC_RSSI_STATE_MEDIUM) || + (coex_sta->pre_bt_rssi_state == + BTC_RSSI_STATE_STAY_MEDIUM)) { + if (bt_rssi >= rssi_thresh1 + + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { + bt_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state " + "switch to High\n"); + } else if (bt_rssi < rssi_thresh) { + bt_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state " + "switch to Low\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state " + "stay at Medium\n"); + } + } else { + if (bt_rssi < rssi_thresh1) { + bt_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state " + "switch to Medium\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state " + "stay at High\n"); + } + } + } + + coex_sta->pre_bt_rssi_state = bt_rssi_state; + + return bt_rssi_state; +} + +static u8 btc8723b2ant_wifi_rssi_state(struct btc_coexist *btcoexist, + u8 index, u8 level_num, + u8 rssi_thresh, u8 rssi_thresh1) +{ + s32 wifi_rssi = 0; + u8 wifi_rssi_state = coex_sta->pre_wifi_rssi_state[index]; + + btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); + + if (level_num == 2) { + if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_LOW) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_LOW)) { + if (wifi_rssi >= rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { + wifi_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state " + "switch to High\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state " + "stay at Low\n"); + } + } else { + if (wifi_rssi < rssi_thresh) { + wifi_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state " + "switch to Low\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state " + "stay at High\n"); + } + } + } else if (level_num == 3) { + if (rssi_thresh > rssi_thresh1) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI thresh error!!\n"); + return coex_sta->pre_wifi_rssi_state[index]; + } + + if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_LOW) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_LOW)) { + if (wifi_rssi >= rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { + wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state " + "switch to Medium\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state " + "stay at Low\n"); + } + } else if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_MEDIUM) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_MEDIUM)) { + if (wifi_rssi >= rssi_thresh1 + + BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { + wifi_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state " + "switch to High\n"); + } else if (wifi_rssi < rssi_thresh) { + wifi_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state " + "switch to Low\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state " + "stay at Medium\n"); + } + } else { + if (wifi_rssi < rssi_thresh1) { + wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state " + "switch to Medium\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state " + "stay at High\n"); + } + } + } + + coex_sta->pre_wifi_rssi_state[index] = wifi_rssi_state; + + return wifi_rssi_state; +} + +static void btc8723b2ant_monitor_bt_ctr(struct btc_coexist *btcoexist) +{ + u32 reg_hp_txrx, reg_lp_txrx, u32tmp; + u32 reg_hp_tx = 0, reg_hp_rx = 0; + u32 reg_lp_tx = 0, reg_lp_rx = 0; + + reg_hp_txrx = 0x770; + reg_lp_txrx = 0x774; + + u32tmp = btcoexist->btc_read_4byte(btcoexist, reg_hp_txrx); + reg_hp_tx = u32tmp & MASKLWORD; + reg_hp_rx = (u32tmp & MASKHWORD) >> 16; + + u32tmp = btcoexist->btc_read_4byte(btcoexist, reg_lp_txrx); + reg_lp_tx = u32tmp & MASKLWORD; + reg_lp_rx = (u32tmp & MASKHWORD) >> 16; + + coex_sta->high_priority_tx = reg_hp_tx; + coex_sta->high_priority_rx = reg_hp_rx; + coex_sta->low_priority_tx = reg_lp_tx; + coex_sta->low_priority_rx = reg_lp_rx; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], High Priority Tx/Rx(reg 0x%x)=0x%x(%d)/0x%x(%d)\n", + reg_hp_txrx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], Low Priority Tx/Rx(reg 0x%x)=0x%x(%d)/0x%x(%d)\n", + reg_lp_txrx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); + + /* reset counter */ + btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); +} + +static void btc8723b2ant_query_bt_info(struct btc_coexist *btcoexist) +{ + u8 h2c_parameter[1] = {0}; + + coex_sta->c2h_bt_info_req_sent = true; + + h2c_parameter[0] |= BIT0; /* trigger */ + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", + h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); +} + +static bool btc8723b2ant_is_wifi_status_changed(struct btc_coexist *btcoexist) +{ + static bool pre_wifi_busy; + static bool pre_under_4way; + static bool pre_bt_hs_on; + bool wifi_busy = false, under_4way = false, bt_hs_on = false; + bool wifi_connected = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, + &under_4way); + + if (wifi_connected) { + if (wifi_busy != pre_wifi_busy) { + pre_wifi_busy = wifi_busy; + return true; + } + + if (under_4way != pre_under_4way) { + pre_under_4way = under_4way; + return true; + } + + if (bt_hs_on != pre_bt_hs_on) { + pre_bt_hs_on = bt_hs_on; + return true; + } + } + + return false; +} + +static void btc8723b2ant_update_bt_link_info(struct btc_coexist *btcoexist) +{ + /*struct btc_stack_info *stack_info = &btcoexist->stack_info;*/ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool bt_hs_on = false; + +#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 1) /* profile from bt patch */ + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + + bt_link_info->bt_link_exist = coex_sta->bt_link_exist; + bt_link_info->sco_exist = coex_sta->sco_exist; + bt_link_info->a2dp_exist = coex_sta->a2dp_exist; + bt_link_info->pan_exist = coex_sta->pan_exist; + bt_link_info->hid_exist = coex_sta->hid_exist; + + /* work around for HS mode. */ + if (bt_hs_on) { + bt_link_info->pan_exist = true; + bt_link_info->bt_link_exist = true; + } +#else /* profile from bt stack */ + bt_link_info->bt_link_exist = stack_info->bt_link_exist; + bt_link_info->sco_exist = stack_info->sco_exist; + bt_link_info->a2dp_exist = stack_info->a2dp_exist; + bt_link_info->pan_exist = stack_info->pan_exist; + bt_link_info->hid_exist = stack_info->hid_exist; + + /*for win-8 stack HID report error*/ + if (!stack_info->hid_exist) + stack_info->hid_exist = coex_sta->hid_exist; + /*sync BTInfo with BT firmware and stack*/ + /* when stack HID report error, here we use the info from bt fw.*/ + if (!stack_info->bt_link_exist) + stack_info->bt_link_exist = coex_sta->bt_link_exist; +#endif + /* check if Sco only */ + if (bt_link_info->sco_exist && !bt_link_info->a2dp_exist && + !bt_link_info->pan_exist && !bt_link_info->hid_exist) + bt_link_info->sco_only = true; + else + bt_link_info->sco_only = false; + + /* check if A2dp only */ + if (!bt_link_info->sco_exist && bt_link_info->a2dp_exist && + !bt_link_info->pan_exist && !bt_link_info->hid_exist) + bt_link_info->a2dp_only = true; + else + bt_link_info->a2dp_only = false; + + /* check if Pan only */ + if (!bt_link_info->sco_exist && !bt_link_info->a2dp_exist && + bt_link_info->pan_exist && !bt_link_info->hid_exist) + bt_link_info->pan_only = true; + else + bt_link_info->pan_only = false; + + /* check if Hid only */ + if (!bt_link_info->sco_exist && !bt_link_info->a2dp_exist && + !bt_link_info->pan_exist && bt_link_info->hid_exist) + bt_link_info->hid_only = true; + else + bt_link_info->hid_only = false; +} + +static u8 btc8723b2ant_action_algorithm(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool bt_hs_on = false; + u8 algorithm = BT_8723B_2ANT_COEX_ALGO_UNDEFINED; + u8 num_of_diff_profile = 0; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + + if (!bt_link_info->bt_link_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], No BT link exists!!!\n"); + return algorithm; + } + + if (bt_link_info->sco_exist) + num_of_diff_profile++; + if (bt_link_info->hid_exist) + num_of_diff_profile++; + if (bt_link_info->pan_exist) + num_of_diff_profile++; + if (bt_link_info->a2dp_exist) + num_of_diff_profile++; + + if (num_of_diff_profile == 1) { + if (bt_link_info->sco_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO only\n"); + algorithm = BT_8723B_2ANT_COEX_ALGO_SCO; + } else { + if (bt_link_info->hid_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], HID only\n"); + algorithm = BT_8723B_2ANT_COEX_ALGO_HID; + } else if (bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], A2DP only\n"); + algorithm = BT_8723B_2ANT_COEX_ALGO_A2DP; + } else if (bt_link_info->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], PAN(HS) only\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_PANHS; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], PAN(EDR) only\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_PANEDR; + } + } + } + } else if (num_of_diff_profile == 2) { + if (bt_link_info->sco_exist) { + if (bt_link_info->hid_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + HID\n"); + algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; + } else if (bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + A2DP ==> SCO\n"); + algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; + } else if (bt_link_info->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + PAN(HS)\n"); + algorithm = BT_8723B_2ANT_COEX_ALGO_SCO; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + PAN(EDR)\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; + } + } + } else { + if (bt_link_info->hid_exist && + bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], HID + A2DP\n"); + algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP; + } else if (bt_link_info->hid_exist && + bt_link_info->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], HID + PAN(HS)\n"); + algorithm = BT_8723B_2ANT_COEX_ALGO_HID; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], HID + PAN(EDR)\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; + } + } else if (bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], A2DP + PAN(HS)\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex],A2DP + PAN(EDR)\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP; + } + } + } + } else if (num_of_diff_profile == 3) { + if (bt_link_info->sco_exist) { + if (bt_link_info->hid_exist && + bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + HID + A2DP" + " ==> HID\n"); + algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; + } else if (bt_link_info->hid_exist && + bt_link_info->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + HID + " + "PAN(HS)\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + HID + " + "PAN(EDR)\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; + } + } else if (bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + A2DP + " + "PAN(HS)\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + A2DP + " + "PAN(EDR) ==> HID\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; + } + } + } else { + if (bt_link_info->hid_exist && + bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], HID + A2DP + " + "PAN(HS)\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_HID_A2DP; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], HID + A2DP + " + "PAN(EDR)\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR; + } + } + } + } else if (num_of_diff_profile >= 3) { + if (bt_link_info->sco_exist) { + if (bt_link_info->hid_exist && + bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Error!!! SCO + HID" + " + A2DP + PAN(HS)\n"); + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + HID + A2DP +" + " PAN(EDR)==>PAN(EDR)+HID\n"); + algorithm = + BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; + } + } + } + } + return algorithm; +} + +static bool btc8723b_need_dec_pwr(struct btc_coexist *btcoexist) +{ + bool ret = false; + bool bt_hs_on = false, wifi_connected = false; + s32 bt_hs_rssi = 0; + u8 bt_rssi_state; + + if (!btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on)) + return false; + if (!btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected)) + return false; + if (!btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi)) + return false; + + bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); + + if (wifi_connected) { + if (bt_hs_on) { + if (bt_hs_rssi > 37) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], Need to decrease bt " + "power for HS mode!!\n"); + ret = true; + } + } else { + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], Need to decrease bt " + "power for Wifi is connected!!\n"); + ret = true; + } + } + } + + return ret; +} + +static void btc8723b2ant_set_fw_dac_swing_level(struct btc_coexist *btcoexist, + u8 dac_swing_lvl) +{ + u8 h2c_parameter[1] = {0}; + + /* There are several type of dacswing + * 0x18/ 0x10/ 0xc/ 0x8/ 0x4/ 0x6 + */ + h2c_parameter[0] = dac_swing_lvl; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], Set Dac Swing Level=0x%x\n", dac_swing_lvl); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x64=0x%x\n", h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x64, 1, h2c_parameter); +} + +static void btc8723b2ant_set_fw_dec_bt_pwr(struct btc_coexist *btcoexist, + bool dec_bt_pwr) +{ + u8 h2c_parameter[1] = {0}; + + h2c_parameter[0] = 0; + + if (dec_bt_pwr) + h2c_parameter[0] |= BIT1; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], decrease Bt Power : %s, FW write 0x62=0x%x\n", + (dec_bt_pwr ? "Yes!!" : "No!!"), h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x62, 1, h2c_parameter); +} + +static void btc8723b2ant_dec_bt_pwr(struct btc_coexist *btcoexist, + bool force_exec, bool dec_bt_pwr) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s Dec BT power = %s\n", + (force_exec ? "force to" : ""), (dec_bt_pwr ? "ON" : "OFF")); + coex_dm->cur_dec_bt_pwr = dec_bt_pwr; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], bPreDecBtPwr=%d, bCurDecBtPwr=%d\n", + coex_dm->pre_dec_bt_pwr, coex_dm->cur_dec_bt_pwr); + + if (coex_dm->pre_dec_bt_pwr == coex_dm->cur_dec_bt_pwr) + return; + } + btc8723b2ant_set_fw_dec_bt_pwr(btcoexist, coex_dm->cur_dec_bt_pwr); + + coex_dm->pre_dec_bt_pwr = coex_dm->cur_dec_bt_pwr; +} + +static void btc8723b2ant_fw_dac_swing_lvl(struct btc_coexist *btcoexist, + bool force_exec, u8 fw_dac_swing_lvl) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s set FW Dac Swing level = %d\n", + (force_exec ? "force to" : ""), fw_dac_swing_lvl); + coex_dm->cur_fw_dac_swing_lvl = fw_dac_swing_lvl; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], preFwDacSwingLvl=%d, " + "curFwDacSwingLvl=%d\n", + coex_dm->pre_fw_dac_swing_lvl, + coex_dm->cur_fw_dac_swing_lvl); + + if (coex_dm->pre_fw_dac_swing_lvl == + coex_dm->cur_fw_dac_swing_lvl) + return; + } + + btc8723b2ant_set_fw_dac_swing_level(btcoexist, + coex_dm->cur_fw_dac_swing_lvl); + coex_dm->pre_fw_dac_swing_lvl = coex_dm->cur_fw_dac_swing_lvl; +} + +static void btc8723b2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, + bool rx_rf_shrink_on) +{ + if (rx_rf_shrink_on) { + /* Shrink RF Rx LPF corner */ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Shrink RF Rx LPF corner!!\n"); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, + 0xfffff, 0xffffc); + } else { + /* Resume RF Rx LPF corner */ + /* After initialized, we can use coex_dm->btRf0x1eBackup */ + if (btcoexist->initilized) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Resume RF Rx LPF corner!!\n"); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, + 0xfffff, + coex_dm->bt_rf0x1e_backup); + } + } +} + +static void btc8723b2ant_rf_shrink(struct btc_coexist *btcoexist, + bool force_exec, bool rx_rf_shrink_on) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s turn Rx RF Shrink = %s\n", + (force_exec ? "force to" : ""), (rx_rf_shrink_on ? + "ON" : "OFF")); + coex_dm->cur_rf_rx_lpf_shrink = rx_rf_shrink_on; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], bPreRfRxLpfShrink=%d, " + "bCurRfRxLpfShrink=%d\n", + coex_dm->pre_rf_rx_lpf_shrink, + coex_dm->cur_rf_rx_lpf_shrink); + + if (coex_dm->pre_rf_rx_lpf_shrink == + coex_dm->cur_rf_rx_lpf_shrink) + return; + } + btc8723b2ant_set_sw_rf_rx_lpf_corner(btcoexist, + coex_dm->cur_rf_rx_lpf_shrink); + + coex_dm->pre_rf_rx_lpf_shrink = coex_dm->cur_rf_rx_lpf_shrink; +} + +static void btc8723b_set_penalty_txrate(struct btc_coexist *btcoexist, + bool low_penalty_ra) +{ + u8 h2c_parameter[6] = {0}; + + h2c_parameter[0] = 0x6; /* opCode, 0x6= Retry_Penalty*/ + + if (low_penalty_ra) { + h2c_parameter[1] |= BIT0; + /*normal rate except MCS7/6/5, OFDM54/48/36*/ + h2c_parameter[2] = 0x00; + h2c_parameter[3] = 0xf7; /*MCS7 or OFDM54*/ + h2c_parameter[4] = 0xf8; /*MCS6 or OFDM48*/ + h2c_parameter[5] = 0xf9; /*MCS5 or OFDM36*/ + } + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], set WiFi Low-Penalty Retry: %s", + (low_penalty_ra ? "ON!!" : "OFF!!")); + + btcoexist->btc_fill_h2c(btcoexist, 0x69, 6, h2c_parameter); +} + +static void btc8723b2ant_low_penalty_ra(struct btc_coexist *btcoexist, + bool force_exec, bool low_penalty_ra) +{ + /*return; */ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s turn LowPenaltyRA = %s\n", + (force_exec ? "force to" : ""), (low_penalty_ra ? + "ON" : "OFF")); + coex_dm->cur_low_penalty_ra = low_penalty_ra; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], bPreLowPenaltyRa=%d, " + "bCurLowPenaltyRa=%d\n", + coex_dm->pre_low_penalty_ra, + coex_dm->cur_low_penalty_ra); + + if (coex_dm->pre_low_penalty_ra == coex_dm->cur_low_penalty_ra) + return; + } + btc8723b_set_penalty_txrate(btcoexist, coex_dm->cur_low_penalty_ra); + + coex_dm->pre_low_penalty_ra = coex_dm->cur_low_penalty_ra; +} + +static void btc8723b2ant_set_dac_swing_reg(struct btc_coexist *btcoexist, + u32 level) +{ + u8 val = (u8) level; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Write SwDacSwing = 0x%x\n", level); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x883, 0x3e, val); +} + +static void btc8723b2ant_set_sw_fulltime_dac_swing(struct btc_coexist *btcoex, + bool sw_dac_swing_on, + u32 sw_dac_swing_lvl) +{ + if (sw_dac_swing_on) + btc8723b2ant_set_dac_swing_reg(btcoex, sw_dac_swing_lvl); + else + btc8723b2ant_set_dac_swing_reg(btcoex, 0x18); +} + +static void btc8723b2ant_dac_swing(struct btc_coexist *btcoexist, + bool force_exec, bool dac_swing_on, + u32 dac_swing_lvl) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s turn DacSwing=%s, dac_swing_lvl=0x%x\n", + (force_exec ? "force to" : ""), + (dac_swing_on ? "ON" : "OFF"), dac_swing_lvl); + coex_dm->cur_dac_swing_on = dac_swing_on; + coex_dm->cur_dac_swing_lvl = dac_swing_lvl; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], bPreDacSwingOn=%d, preDacSwingLvl=0x%x," + " bCurDacSwingOn=%d, curDacSwingLvl=0x%x\n", + coex_dm->pre_dac_swing_on, coex_dm->pre_dac_swing_lvl, + coex_dm->cur_dac_swing_on, + coex_dm->cur_dac_swing_lvl); + + if ((coex_dm->pre_dac_swing_on == coex_dm->cur_dac_swing_on) && + (coex_dm->pre_dac_swing_lvl == coex_dm->cur_dac_swing_lvl)) + return; + } + mdelay(30); + btc8723b2ant_set_sw_fulltime_dac_swing(btcoexist, dac_swing_on, + dac_swing_lvl); + + coex_dm->pre_dac_swing_on = coex_dm->cur_dac_swing_on; + coex_dm->pre_dac_swing_lvl = coex_dm->cur_dac_swing_lvl; +} + +static void btc8723b2ant_set_agc_table(struct btc_coexist *btcoexist, + bool agc_table_en) +{ + u8 rssi_adjust_val = 0; + + /* BB AGC Gain Table */ + if (agc_table_en) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], BB Agc Table On!\n"); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6e1A0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6d1B0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6c1C0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6b1D0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6a1E0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x691F0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x68200001); + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], BB Agc Table Off!\n"); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xaa1A0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa91B0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa81C0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa71D0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa61E0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa51F0001); + btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa4200001); + } + + /* RF Gain */ + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0xef, 0xfffff, 0x02000); + if (agc_table_en) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Agc Table On!\n"); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x3b, + 0xfffff, 0x38fff); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x3b, + 0xfffff, 0x38ffe); + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Agc Table Off!\n"); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x3b, + 0xfffff, 0x380c3); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x3b, + 0xfffff, 0x28ce6); + } + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0xef, 0xfffff, 0x0); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0xed, 0xfffff, 0x1); + + if (agc_table_en) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Agc Table On!\n"); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x40, + 0xfffff, 0x38fff); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x40, + 0xfffff, 0x38ffe); + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Agc Table Off!\n"); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x40, + 0xfffff, 0x380c3); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x40, + 0xfffff, 0x28ce6); + } + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0xed, 0xfffff, 0x0); + + /* set rssiAdjustVal for wifi module. */ + if (agc_table_en) + rssi_adjust_val = 8; + btcoexist->btc_set(btcoexist, BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON, + &rssi_adjust_val); +} + +static void btc8723b2ant_agc_table(struct btc_coexist *btcoexist, + bool force_exec, bool agc_table_en) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s %s Agc Table\n", + (force_exec ? "force to" : ""), + (agc_table_en ? "Enable" : "Disable")); + coex_dm->cur_agc_table_en = agc_table_en; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], bPreAgcTableEn=%d, bCurAgcTableEn=%d\n", + coex_dm->pre_agc_table_en, coex_dm->cur_agc_table_en); + + if (coex_dm->pre_agc_table_en == coex_dm->cur_agc_table_en) + return; + } + btc8723b2ant_set_agc_table(btcoexist, agc_table_en); + + coex_dm->pre_agc_table_en = coex_dm->cur_agc_table_en; +} + +static void btc8723b2ant_set_coex_table(struct btc_coexist *btcoexist, + u32 val0x6c0, u32 val0x6c4, + u32 val0x6c8, u8 val0x6cc) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c0=0x%x\n", val0x6c0); + btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c4=0x%x\n", val0x6c4); + btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c8=0x%x\n", val0x6c8); + btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6cc=0x%x\n", val0x6cc); + btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); +} + +static void btc8723b2ant_coex_table(struct btc_coexist *btcoexist, + bool force_exec, u32 val0x6c0, + u32 val0x6c4, u32 val0x6c8, + u8 val0x6cc) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s write Coex Table 0x6c0=0x%x," + " 0x6c4=0x%x, 0x6c8=0x%x, 0x6cc=0x%x\n", + (force_exec ? "force to" : ""), val0x6c0, + val0x6c4, val0x6c8, val0x6cc); + coex_dm->cur_val0x6c0 = val0x6c0; + coex_dm->cur_val0x6c4 = val0x6c4; + coex_dm->cur_val0x6c8 = val0x6c8; + coex_dm->cur_val0x6cc = val0x6cc; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], preVal0x6c0=0x%x, " + "preVal0x6c4=0x%x, preVal0x6c8=0x%x, " + "preVal0x6cc=0x%x !!\n", + coex_dm->pre_val0x6c0, coex_dm->pre_val0x6c4, + coex_dm->pre_val0x6c8, coex_dm->pre_val0x6cc); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], curVal0x6c0=0x%x, " + "curVal0x6c4=0x%x, curVal0x6c8=0x%x, " + "curVal0x6cc=0x%x !!\n", + coex_dm->cur_val0x6c0, coex_dm->cur_val0x6c4, + coex_dm->cur_val0x6c8, coex_dm->cur_val0x6cc); + + if ((coex_dm->pre_val0x6c0 == coex_dm->cur_val0x6c0) && + (coex_dm->pre_val0x6c4 == coex_dm->cur_val0x6c4) && + (coex_dm->pre_val0x6c8 == coex_dm->cur_val0x6c8) && + (coex_dm->pre_val0x6cc == coex_dm->cur_val0x6cc)) + return; + } + btc8723b2ant_set_coex_table(btcoexist, val0x6c0, val0x6c4, + val0x6c8, val0x6cc); + + coex_dm->pre_val0x6c0 = coex_dm->cur_val0x6c0; + coex_dm->pre_val0x6c4 = coex_dm->cur_val0x6c4; + coex_dm->pre_val0x6c8 = coex_dm->cur_val0x6c8; + coex_dm->pre_val0x6cc = coex_dm->cur_val0x6cc; +} + +static void btc8723b_coex_tbl_type(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + switch (type) { + case 0: + btc8723b2ant_coex_table(btcoexist, force_exec, 0x55555555, + 0x55555555, 0xffff, 0x3); + break; + case 1: + btc8723b2ant_coex_table(btcoexist, force_exec, 0x55555555, + 0x5afa5afa, 0xffff, 0x3); + break; + case 2: + btc8723b2ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a, + 0x5a5a5a5a, 0xffff, 0x3); + break; + case 3: + btc8723b2ant_coex_table(btcoexist, force_exec, 0xaaaaaaaa, + 0xaaaaaaaa, 0xffff, 0x3); + break; + case 4: + btc8723b2ant_coex_table(btcoexist, force_exec, 0xffffffff, + 0xffffffff, 0xffff, 0x3); + break; + case 5: + btc8723b2ant_coex_table(btcoexist, force_exec, 0x5fff5fff, + 0x5fff5fff, 0xffff, 0x3); + break; + case 6: + btc8723b2ant_coex_table(btcoexist, force_exec, 0x55ff55ff, + 0x5a5a5a5a, 0xffff, 0x3); + break; + case 7: + btc8723b2ant_coex_table(btcoexist, force_exec, 0x55ff55ff, + 0x5afa5afa, 0xffff, 0x3); + break; + case 8: + btc8723b2ant_coex_table(btcoexist, force_exec, 0x5aea5aea, + 0x5aea5aea, 0xffff, 0x3); + break; + case 9: + btc8723b2ant_coex_table(btcoexist, force_exec, 0x55ff55ff, + 0x5aea5aea, 0xffff, 0x3); + break; + case 10: + btc8723b2ant_coex_table(btcoexist, force_exec, 0x55ff55ff, + 0x5aff5aff, 0xffff, 0x3); + break; + case 11: + btc8723b2ant_coex_table(btcoexist, force_exec, 0x55ff55ff, + 0x5a5f5a5f, 0xffff, 0x3); + break; + case 12: + btc8723b2ant_coex_table(btcoexist, force_exec, 0x55ff55ff, + 0x5f5f5f5f, 0xffff, 0x3); + break; + default: + break; + } +} + +static void btc8723b2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, + bool enable) +{ + u8 h2c_parameter[1] = {0}; + + if (enable) + h2c_parameter[0] |= BIT0;/* function enable*/ + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], set FW for BT Ignore Wlan_Act, " + "FW write 0x63=0x%x\n", h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); +} + +static void btc8723b2ant_ignore_wlan_act(struct btc_coexist *btcoexist, + bool force_exec, bool enable) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s turn Ignore WlanAct %s\n", + (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); + coex_dm->cur_ignore_wlan_act = enable; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], bPreIgnoreWlanAct = %d, " + "bCurIgnoreWlanAct = %d!!\n", + coex_dm->pre_ignore_wlan_act, + coex_dm->cur_ignore_wlan_act); + + if (coex_dm->pre_ignore_wlan_act == + coex_dm->cur_ignore_wlan_act) + return; + } + btc8723b2ant_set_fw_ignore_wlan_act(btcoexist, enable); + + coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; +} + +static void btc8723b2ant_set_fw_ps_tdma(struct btc_coexist *btcoexist, u8 byte1, + u8 byte2, u8 byte3, u8 byte4, u8 byte5) +{ + u8 h2c_parameter[5]; + + h2c_parameter[0] = byte1; + h2c_parameter[1] = byte2; + h2c_parameter[2] = byte3; + h2c_parameter[3] = byte4; + h2c_parameter[4] = byte5; + + coex_dm->ps_tdma_para[0] = byte1; + coex_dm->ps_tdma_para[1] = byte2; + coex_dm->ps_tdma_para[2] = byte3; + coex_dm->ps_tdma_para[3] = byte4; + coex_dm->ps_tdma_para[4] = byte5; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x60(5bytes)=0x%x%08x\n", + h2c_parameter[0], + h2c_parameter[1] << 24 | h2c_parameter[2] << 16 | + h2c_parameter[3] << 8 | h2c_parameter[4]); + + btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); +} + +static void btc8723b2ant_sw_mechanism1(struct btc_coexist *btcoexist, + bool shrink_rx_lpf, bool low_penalty_ra, + bool limited_dig, bool bt_lna_constrain) +{ + btc8723b2ant_rf_shrink(btcoexist, NORMAL_EXEC, shrink_rx_lpf); + btc8723b2ant_low_penalty_ra(btcoexist, NORMAL_EXEC, low_penalty_ra); +} + +static void btc8723b2ant_sw_mechanism2(struct btc_coexist *btcoexist, + bool agc_table_shift, bool adc_backoff, + bool sw_dac_swing, u32 dac_swing_lvl) +{ + btc8723b2ant_agc_table(btcoexist, NORMAL_EXEC, agc_table_shift); + btc8723b2ant_dac_swing(btcoexist, NORMAL_EXEC, sw_dac_swing, + dac_swing_lvl); +} + +static void btc8723b2ant_set_ant_path(struct btc_coexist *btcoexist, + u8 antpos_type, bool init_hwcfg, + bool wifi_off) +{ + struct btc_board_info *board_info = &btcoexist->board_info; + u32 fw_ver = 0, u32tmp = 0; + bool pg_ext_switch = false; + bool use_ext_switch = false; + u8 h2c_parameter[2] = {0}; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_EXT_SWITCH, &pg_ext_switch); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); + + if ((fw_ver < 0xc0000) || pg_ext_switch) + use_ext_switch = true; + + if (init_hwcfg) { + /* 0x4c[23] = 0, 0x4c[24] = 1 Antenna control by WL/BT */ + u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); + u32tmp &= ~BIT23; + u32tmp |= BIT24; + btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp); + + btcoexist->btc_write_1byte(btcoexist, 0x974, 0xff); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x944, 0x3, 0x3); + btcoexist->btc_write_1byte(btcoexist, 0x930, 0x77); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67, 0x20, 0x1); + + /* Force GNT_BT to low */ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x0); + btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0); + + if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) { + /* tell firmware "no antenna inverse" */ + h2c_parameter[0] = 0; + h2c_parameter[1] = 1; /* ext switch type */ + btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, + h2c_parameter); + } else { + /* tell firmware "antenna inverse" */ + h2c_parameter[0] = 1; + h2c_parameter[1] = 1; /* ext switch type */ + btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, + h2c_parameter); + } + } + + /* ext switch setting */ + if (use_ext_switch) { + /* fixed internal switch S1->WiFi, S0->BT */ + btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0); + switch (antpos_type) { + case BTC_ANT_WIFI_AT_MAIN: + /* ext switch main at wifi */ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x92c, + 0x3, 0x1); + break; + case BTC_ANT_WIFI_AT_AUX: + /* ext switch aux at wifi */ + btcoexist->btc_write_1byte_bitmask(btcoexist, + 0x92c, 0x3, 0x2); + break; + } + } else { /* internal switch */ + /* fixed ext switch */ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x92c, 0x3, 0x1); + switch (antpos_type) { + case BTC_ANT_WIFI_AT_MAIN: + /* fixed internal switch S1->WiFi, S0->BT */ + btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0); + break; + case BTC_ANT_WIFI_AT_AUX: + /* fixed internal switch S0->WiFi, S1->BT */ + btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280); + break; + } + } +} + +static void btc8723b2ant_ps_tdma(struct btc_coexist *btcoexist, bool force_exec, + bool turn_on, u8 type) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s turn %s PS TDMA, type=%d\n", + (force_exec ? "force to" : ""), + (turn_on ? "ON" : "OFF"), type); + coex_dm->cur_ps_tdma_on = turn_on; + coex_dm->cur_ps_tdma = type; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], bPrePsTdmaOn = %d, bCurPsTdmaOn = %d!!\n", + coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], prePsTdma = %d, curPsTdma = %d!!\n", + coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma); + + if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && + (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) + return; + } + if (turn_on) { + switch (type) { + case 1: + default: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0xe1, 0x90); + break; + case 2: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x12, + 0x12, 0xe1, 0x90); + break; + case 3: + /* This call breaks BT when wireless is active - + * comment it out for now until a better fix is found: + * btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1c, + * 0x3, 0xf1, 0x90); + */ + break; + case 4: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x10, + 0x03, 0xf1, 0x90); + break; + case 5: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0x60, 0x90); + break; + case 6: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x12, + 0x12, 0x60, 0x90); + break; + case 7: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1c, + 0x3, 0x70, 0x90); + break; + case 8: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xa3, 0x10, + 0x3, 0x70, 0x90); + break; + case 9: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0xe1, 0x90); + break; + case 10: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x12, + 0x12, 0xe1, 0x90); + break; + case 11: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0xa, + 0xa, 0xe1, 0x90); + break; + case 12: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x5, + 0x5, 0xe1, 0x90); + break; + case 13: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0x60, 0x90); + break; + case 14: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x12, + 0x12, 0x60, 0x90); + break; + case 15: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0xa, + 0xa, 0x60, 0x90); + break; + case 16: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x5, + 0x5, 0x60, 0x90); + break; + case 17: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xa3, 0x2f, + 0x2f, 0x60, 0x90); + break; + case 18: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x5, + 0x5, 0xe1, 0x90); + break; + case 19: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x25, + 0x25, 0xe1, 0x90); + break; + case 20: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x25, + 0x25, 0x60, 0x90); + break; + case 21: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x15, + 0x03, 0x70, 0x90); + break; + case 71: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0xe1, 0x90); + break; + } + } else { + /* disable PS tdma */ + switch (type) { + case 0: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0, 0x0, + 0x40, 0x0); + break; + case 1: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0, 0x0, + 0x48, 0x0); + break; + default: + btc8723b2ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0, 0x0, + 0x40, 0x0); + break; + } + } + + /* update pre state */ + coex_dm->pre_ps_tdma_on = coex_dm->cur_ps_tdma_on; + coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; +} + +static void btc8723b2ant_coex_alloff(struct btc_coexist *btcoexist) +{ + /* fw all off */ + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + /* sw all off */ + btc8723b2ant_sw_mechanism1(btcoexist, false, false, false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, false, 0x18); + + /* hw all off */ + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 0); +} + +static void btc8723b2ant_init_coex_dm(struct btc_coexist *btcoexist) +{ + /* force to reset coex mechanism*/ + + btc8723b2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 1); + btc8723b2ant_fw_dac_swing_lvl(btcoexist, FORCE_EXEC, 6); + btc8723b2ant_dec_bt_pwr(btcoexist, FORCE_EXEC, false); + + btc8723b2ant_sw_mechanism1(btcoexist, false, false, false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, false, 0x18); +} + +static void btc8723b2ant_action_bt_inquiry(struct btc_coexist *btcoexist) +{ + bool wifi_connected = false; + bool low_pwr_disable = true; + + btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + + if (wifi_connected) { + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); + } else { + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 0); + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + } + btc8723b2ant_fw_dac_swing_lvl(btcoexist, FORCE_EXEC, 6); + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btc8723b2ant_sw_mechanism1(btcoexist, false, false, false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, false, 0x18); + + coex_dm->need_recover_0x948 = true; + coex_dm->backup_0x948 = btcoexist->btc_read_2byte(btcoexist, 0x948); + + btc8723b2ant_set_ant_path(btcoexist, BTC_ANT_WIFI_AT_AUX, + false, false); +} + +static bool btc8723b2ant_is_common_action(struct btc_coexist *btcoexist) +{ + bool common = false, wifi_connected = false; + bool wifi_busy = false; + bool bt_hs_on = false, low_pwr_disable = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + + if (!wifi_connected) { + low_pwr_disable = false; + btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi non-connected idle!!\n"); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, + 0x0); + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 0); + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btc8723b2ant_sw_mechanism1(btcoexist, false, false, false, + false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, false, + 0x18); + + common = true; + } else { + if (BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE == + coex_dm->bt_status) { + low_pwr_disable = false; + btcoexist->btc_set(btcoexist, + BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi connected + " + "BT non connected-idle!!\n"); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, + 0xfffff, 0x0); + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 0); + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, + 0xb); + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, + false); + + btc8723b2ant_sw_mechanism1(btcoexist, false, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + + common = true; + } else if (BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE == + coex_dm->bt_status) { + low_pwr_disable = true; + btcoexist->btc_set(btcoexist, + BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + if (bt_hs_on) + return false; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi connected + " + "BT connected-idle!!\n"); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, + 0xfffff, 0x0); + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 0); + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, + 0xb); + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, + false); + + btc8723b2ant_sw_mechanism1(btcoexist, true, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + + common = true; + } else { + low_pwr_disable = true; + btcoexist->btc_set(btcoexist, + BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + if (wifi_busy) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi Connected-Busy + " + "BT Busy!!\n"); + common = false; + } else { + if (bt_hs_on) + return false; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi Connected-Idle + " + "BT Busy!!\n"); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, + 0x1, 0xfffff, 0x0); + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, + 7); + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 21); + btc8723b2ant_fw_dac_swing_lvl(btcoexist, + NORMAL_EXEC, + 0xb); + if (btc8723b_need_dec_pwr(btcoexist)) + btc8723b2ant_dec_bt_pwr(btcoexist, + NORMAL_EXEC, + true); + else + btc8723b2ant_dec_bt_pwr(btcoexist, + NORMAL_EXEC, + false); + btc8723b2ant_sw_mechanism1(btcoexist, false, + false, false, + false); + btc8723b2ant_sw_mechanism2(btcoexist, false, + false, false, + 0x18); + common = true; + } + } + } + + return common; +} + +static void set_tdma_int1(struct btc_coexist *btcoexist, bool tx_pause, + s32 result) +{ + /* Set PS TDMA for max interval == 1 */ + if (tx_pause) { + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); + + if (coex_dm->cur_ps_tdma == 71) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + coex_dm->tdma_adj_type = 5; + } else if (coex_dm->cur_ps_tdma == 1) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + coex_dm->tdma_adj_type = 5; + } else if (coex_dm->cur_ps_tdma == 2) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 3) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 4) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } + + if (coex_dm->cur_ps_tdma == 9) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 13); + coex_dm->tdma_adj_type = 13; + } else if (coex_dm->cur_ps_tdma == 10) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 11) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 12) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + + if (result == -1) { + if (coex_dm->cur_ps_tdma == 5) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 6) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } else if (coex_dm->cur_ps_tdma == 13) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 14) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 8) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 6) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + coex_dm->tdma_adj_type = 5; + } else if (coex_dm->cur_ps_tdma == 16) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 14) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 13); + coex_dm->tdma_adj_type = 13; + } + } + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); + if (coex_dm->cur_ps_tdma == 5) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 71); + coex_dm->tdma_adj_type = 71; + } else if (coex_dm->cur_ps_tdma == 6) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 7) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 8) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 4); + coex_dm->tdma_adj_type = 4; + } + + if (coex_dm->cur_ps_tdma == 13) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9); + coex_dm->tdma_adj_type = 9; + } else if (coex_dm->cur_ps_tdma == 14) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 15) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 16) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 12); + coex_dm->tdma_adj_type = 12; + } + + if (result == -1) { + if (coex_dm->cur_ps_tdma == 71) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 1); + coex_dm->tdma_adj_type = 1; + } else if (coex_dm->cur_ps_tdma == 1) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } else if (coex_dm->cur_ps_tdma == 9) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 10) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 4) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 1); + coex_dm->tdma_adj_type = 1; + } else if (coex_dm->cur_ps_tdma == 1) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 71); + coex_dm->tdma_adj_type = 71; + } else if (coex_dm->cur_ps_tdma == 12) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 10) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } + } + } +} + +static void set_tdma_int2(struct btc_coexist *btcoexist, bool tx_pause, + s32 result) +{ + /* Set PS TDMA for max interval == 2 */ + if (tx_pause) { + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); + if (coex_dm->cur_ps_tdma == 1) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 2) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 3) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 4) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 8); + coex_dm->tdma_adj_type = 8; + } + if (coex_dm->cur_ps_tdma == 9) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 10) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 11) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 12) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 16); + coex_dm->tdma_adj_type = 16; + } + if (result == -1) { + if (coex_dm->cur_ps_tdma == 5) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 6) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } else if (coex_dm->cur_ps_tdma == 13) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 14) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 8) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 6) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 16) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 14) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } + } + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); + if (coex_dm->cur_ps_tdma == 5) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 6) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 7) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 8) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 4); + coex_dm->tdma_adj_type = 4; + } + if (coex_dm->cur_ps_tdma == 13) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 14) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 15) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 16) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 12); + coex_dm->tdma_adj_type = 12; + } + if (result == -1) { + if (coex_dm->cur_ps_tdma == 1) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } else if (coex_dm->cur_ps_tdma == 9) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 10) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 4) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 12) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 10) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } + } + } +} + +static void set_tdma_int3(struct btc_coexist *btcoexist, bool tx_pause, + s32 result) +{ + /* Set PS TDMA for max interval == 3 */ + if (tx_pause) { + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); + if (coex_dm->cur_ps_tdma == 1) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 2) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 3) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 4) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 8); + coex_dm->tdma_adj_type = 8; + } + if (coex_dm->cur_ps_tdma == 9) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 10) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 11) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 12) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 16); + coex_dm->tdma_adj_type = 16; + } + if (result == -1) { + if (coex_dm->cur_ps_tdma == 5) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 6) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } else if (coex_dm->cur_ps_tdma == 13) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 14) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 8) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 6) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 16) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 14) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } + } + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); + if (coex_dm->cur_ps_tdma == 5) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 6) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 7) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 8) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 4); + coex_dm->tdma_adj_type = 4; + } + if (coex_dm->cur_ps_tdma == 13) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 14) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 15) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 16) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 12); + coex_dm->tdma_adj_type = 12; + } + if (result == -1) { + if (coex_dm->cur_ps_tdma == 1) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 2) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } else if (coex_dm->cur_ps_tdma == 9) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 10) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 4) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 2) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 12) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 10) { + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } + } + } +} + +static void btc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, + bool sco_hid, bool tx_pause, + u8 max_interval) +{ + static s32 up, dn, m, n, wait_count; + /*0: no change, +1: increase WiFi duration, -1: decrease WiFi duration*/ + s32 result; + u8 retry_count = 0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], TdmaDurationAdjust()\n"); + + if (!coex_dm->auto_tdma_adjust) { + coex_dm->auto_tdma_adjust = true; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], first run TdmaDurationAdjust()!!\n"); + if (sco_hid) { + if (tx_pause) { + if (max_interval == 1) { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 13); + coex_dm->tdma_adj_type = 13; + } else if (max_interval == 2) { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (max_interval == 3) { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } + } else { + if (max_interval == 1) { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (max_interval == 2) { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (max_interval == 3) { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } + } + } else { + if (tx_pause) { + if (max_interval == 1) { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 5); + coex_dm->tdma_adj_type = 5; + } else if (max_interval == 2) { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (max_interval == 3) { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } + } else { + if (max_interval == 1) { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 1); + coex_dm->tdma_adj_type = 1; + } else if (max_interval == 2) { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (max_interval == 3) { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else { + btc8723b2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } + } + } + + up = 0; + dn = 0; + m = 1; + n = 3; + result = 0; + wait_count = 0; + } else { + /*accquire the BT TRx retry count from BT_Info byte2*/ + retry_count = coex_sta->bt_retry_cnt; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], retry_count = %d\n", retry_count); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], up=%d, dn=%d, m=%d, n=%d, wait_count=%d\n", + up, dn, m, n, wait_count); + result = 0; + wait_count++; + /* no retry in the last 2-second duration*/ + if (retry_count == 0) { + up++; + dn--; + + if (dn <= 0) + dn = 0; + + if (up >= n) { + wait_count = 0; + n = 3; + up = 0; + dn = 0; + result = 1; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], Increase wifi " + "duration!!\n"); + } /* <=3 retry in the last 2-second duration*/ + } else if (retry_count <= 3) { + up--; + dn++; + + if (up <= 0) + up = 0; + + if (dn == 2) { + if (wait_count <= 2) + m++; + else + m = 1; + + if (m >= 20) + m = 20; + + n = 3 * m; + up = 0; + dn = 0; + wait_count = 0; + result = -1; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration " + "for retry_counter<3!!\n"); + } + } else { + if (wait_count == 1) + m++; + else + m = 1; + + if (m >= 20) + m = 20; + + n = 3 * m; + up = 0; + dn = 0; + wait_count = 0; + result = -1; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration " + "for retry_counter>3!!\n"); + } + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], max Interval = %d\n", max_interval); + if (max_interval == 1) + set_tdma_int1(btcoexist, tx_pause, result); + else if (max_interval == 2) + set_tdma_int2(btcoexist, tx_pause, result); + else if (max_interval == 3) + set_tdma_int3(btcoexist, tx_pause, result); + } + + /*if current PsTdma not match with the recorded one (when scan, dhcp..), + *then we have to adjust it back to the previous recorded one. + */ + if (coex_dm->cur_ps_tdma != coex_dm->tdma_adj_type) { + bool scan = false, link = false, roam = false; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], PsTdma type dismatch!!!, " + "curPsTdma=%d, recordPsTdma=%d\n", + coex_dm->cur_ps_tdma, coex_dm->tdma_adj_type); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); + + if (!scan && !link && !roam) + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, + coex_dm->tdma_adj_type); + else + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], roaming/link/scan is under" + " progress, will adjust next time!!!\n"); + } +} + +/* SCO only or SCO+PAN(HS) */ +static void btc8723b2ant_action_sco(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); + + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 4); + + if (btc8723b_need_dec_pwr(btcoexist)) + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + /*for SCO quality at 11b/g mode*/ + if (BTC_WIFI_BW_LEGACY == wifi_bw) + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 2); + else /*for SCO quality & wifi performance balance at 11n mode*/ + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 8); + + /*for voice quality */ + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0); + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, true, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + true, 0x4); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, true, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + true, 0x4); + } + } else { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, false, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + true, 0x4); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, false, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + true, 0x4); + } + } +} + +static void btc8723b2ant_action_hid(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); + + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if (btc8723b_need_dec_pwr(btcoexist)) + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (BTC_WIFI_BW_LEGACY == wifi_bw) /*/for HID at 11b/g mode*/ + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); + else /*for HID quality & wifi performance balance at 11n mode*/ + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 9); + + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9); + else + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13); + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, true, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, true, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, false, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, false, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } +} + +/*A2DP only / PAN(EDR) only/ A2DP+PAN(HS)*/ +static void btc8723b2ant_action_a2dp(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state; + u32 wifi_bw; + u8 ap_num = 0; + + wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + wifi_rssi_state1 = btc8723b2ant_wifi_rssi_state(btcoexist, + 1, 2, 40, 0); + bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); + + btcoexist->btc_get(btcoexist, BTC_GET_U1_AP_NUM, &ap_num); + + /* define the office environment */ + /* driver don't know AP num in Linux, so we will never enter this if */ + if (ap_num >= 10 && BTC_RSSI_HIGH(wifi_rssi_state1)) { + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, + 0x0); + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 0); + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + + /* sw mechanism */ + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) { + btc8723b2ant_sw_mechanism1(btcoexist, true, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + true, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, false, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + true, 0x18); + } + return; + } + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); + + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if (btc8723b_need_dec_pwr(btcoexist)) + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); + + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) + btc8723b2ant_tdma_duration_adjust(btcoexist, false, + false, 1); + else + btc8723b2ant_tdma_duration_adjust(btcoexist, false, true, 1); + + /* sw mechanism */ + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, true, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, true, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, false, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, false, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void btc8723b2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); + + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if (btc8723b_need_dec_pwr(btcoexist)) + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); + + btc8723b2ant_tdma_duration_adjust(btcoexist, false, true, 2); + + /* sw mechanism */ + btcoexist->btc_get(btcoexist, + BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, true, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, true, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, false, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, false, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void btc8723b2ant_action_pan_edr(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); + + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if (btc8723b_need_dec_pwr(btcoexist)) + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 10); + + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 1); + else + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); + + /* sw mechanism */ + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, true, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, true, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, false, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, false, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } +} + +/*PAN(HS) only*/ +static void btc8723b2ant_action_pan_hs(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); + + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); + + btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, true, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, true, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, false, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, false, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } +} + +/*PAN(EDR)+A2DP*/ +static void btc8723b2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); + + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if (btc8723b_need_dec_pwr(btcoexist)) + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 12); + if (BTC_WIFI_BW_HT40 == wifi_bw) + btc8723b2ant_tdma_duration_adjust(btcoexist, false, + true, 3); + else + btc8723b2ant_tdma_duration_adjust(btcoexist, false, + false, 3); + } else { + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); + btc8723b2ant_tdma_duration_adjust(btcoexist, false, true, 3); + } + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, true, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, true, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, false, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, false, false, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void btc8723b2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (btc8723b_need_dec_pwr(btcoexist)) + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + if (BTC_WIFI_BW_HT40 == wifi_bw) { + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, + 3); + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 11); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, + 0xfffff, 0x780); + } else { + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, + 6); + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, + 0xfffff, 0x0); + } + btc8723b2ant_tdma_duration_adjust(btcoexist, true, false, 2); + } else { + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 11); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, + 0x0); + btc8723b2ant_tdma_duration_adjust(btcoexist, true, true, 2); + } + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, true, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, true, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, false, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, false, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } +} + +/* HID+A2DP+PAN(EDR) */ +static void btc8723b2ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); + + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if (btc8723b_need_dec_pwr(btcoexist)) + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); + + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + if (BTC_WIFI_BW_HT40 == wifi_bw) + btc8723b2ant_tdma_duration_adjust(btcoexist, true, + true, 2); + else + btc8723b2ant_tdma_duration_adjust(btcoexist, true, + false, 3); + } else { + btc8723b2ant_tdma_duration_adjust(btcoexist, true, true, 3); + } + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, true, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, true, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, false, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, false, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void btc8723b2ant_action_hid_a2dp(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); + + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); + + btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if (btc8723b_need_dec_pwr(btcoexist)) + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); + + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) + btc8723b2ant_tdma_duration_adjust(btcoexist, true, false, 2); + else + btc8723b2ant_tdma_duration_adjust(btcoexist, true, true, 2); + + /* sw mechanism */ + if (BTC_WIFI_BW_HT40 == wifi_bw) { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, true, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, true, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } else { + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8723b2ant_sw_mechanism1(btcoexist, false, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, true, false, + false, 0x18); + } else { + btc8723b2ant_sw_mechanism1(btcoexist, false, true, + false, false); + btc8723b2ant_sw_mechanism2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void btc8723b2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) +{ + u8 algorithm = 0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], RunCoexistMechanism()===>\n"); + + if (btcoexist->manual_control) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), " + "return for Manual CTRL <===\n"); + return; + } + + if (coex_sta->under_ips) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], wifi is under IPS !!!\n"); + return; + } + + algorithm = btc8723b2ant_action_algorithm(btcoexist); + if (coex_sta->c2h_bt_inquiry_page && + (BT_8723B_2ANT_COEX_ALGO_PANHS != algorithm)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT is under inquiry/page scan !!\n"); + btc8723b2ant_action_bt_inquiry(btcoexist); + return; + } else { + if (coex_dm->need_recover_0x948) { + coex_dm->need_recover_0x948 = false; + btcoexist->btc_write_2byte(btcoexist, 0x948, + coex_dm->backup_0x948); + } + } + + coex_dm->cur_algorithm = algorithm; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, "[BTCoex], Algorithm = %d\n", + coex_dm->cur_algorithm); + + if (btc8723b2ant_is_common_action(btcoexist)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant common.\n"); + coex_dm->auto_tdma_adjust = false; + } else { + if (coex_dm->cur_algorithm != coex_dm->pre_algorithm) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], preAlgorithm=%d, " + "curAlgorithm=%d\n", coex_dm->pre_algorithm, + coex_dm->cur_algorithm); + coex_dm->auto_tdma_adjust = false; + } + switch (coex_dm->cur_algorithm) { + case BT_8723B_2ANT_COEX_ALGO_SCO: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = SCO.\n"); + btc8723b2ant_action_sco(btcoexist); + break; + case BT_8723B_2ANT_COEX_ALGO_HID: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HID.\n"); + btc8723b2ant_action_hid(btcoexist); + break; + case BT_8723B_2ANT_COEX_ALGO_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, " + "algorithm = A2DP.\n"); + btc8723b2ant_action_a2dp(btcoexist); + break; + case BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, " + "algorithm = A2DP+PAN(HS).\n"); + btc8723b2ant_action_a2dp_pan_hs(btcoexist); + break; + case BT_8723B_2ANT_COEX_ALGO_PANEDR: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, " + "algorithm = PAN(EDR).\n"); + btc8723b2ant_action_pan_edr(btcoexist); + break; + case BT_8723B_2ANT_COEX_ALGO_PANHS: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, " + "algorithm = HS mode.\n"); + btc8723b2ant_action_pan_hs(btcoexist); + break; + case BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, " + "algorithm = PAN+A2DP.\n"); + btc8723b2ant_action_pan_edr_a2dp(btcoexist); + break; + case BT_8723B_2ANT_COEX_ALGO_PANEDR_HID: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, " + "algorithm = PAN(EDR)+HID.\n"); + btc8723b2ant_action_pan_edr_hid(btcoexist); + break; + case BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, " + "algorithm = HID+A2DP+PAN.\n"); + btc8723b2ant_action_hid_a2dp_pan_edr(btcoexist); + break; + case BT_8723B_2ANT_COEX_ALGO_HID_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, " + "algorithm = HID+A2DP.\n"); + btc8723b2ant_action_hid_a2dp(btcoexist); + break; + default: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, " + "algorithm = coexist All Off!!\n"); + btc8723b2ant_coex_alloff(btcoexist); + break; + } + coex_dm->pre_algorithm = coex_dm->cur_algorithm; + } +} + +static void btc8723b2ant_wifioff_hwcfg(struct btc_coexist *btcoexist) +{ + /* set wlan_act to low */ + btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4); + /* Force GNT_BT to High */ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x3); + /* BT select s0/s1 is controlled by BT */ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67, 0x20, 0x0); +} + +/********************************************************************* + * work around function start with wa_btc8723b2ant_ + *********************************************************************/ +/********************************************************************* + * extern function start with EXbtc8723b2ant_ + *********************************************************************/ +void ex_btc8723b2ant_init_hwconfig(struct btc_coexist *btcoexist) +{ + u8 u8tmp = 0; + + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], 2Ant Init HW Config!!\n"); + coex_dm->bt_rf0x1e_backup = + btcoexist->btc_get_rf_reg(btcoexist, BTC_RF_A, 0x1e, 0xfffff); + + /* 0x790[5:0] = 0x5 */ + u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x790); + u8tmp &= 0xc0; + u8tmp |= 0x5; + btcoexist->btc_write_1byte(btcoexist, 0x790, u8tmp); + + /*Antenna config */ + btc8723b2ant_set_ant_path(btcoexist, BTC_ANT_WIFI_AT_MAIN, + true, false); + /* PTA parameter */ + btc8723b_coex_tbl_type(btcoexist, FORCE_EXEC, 0); + + /* Enable counter statistics */ + /*0x76e[3] =1, WLAN_Act control by PTA*/ + btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); + btcoexist->btc_write_1byte(btcoexist, 0x778, 0x3); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1); +} + +void ex_btc8723b2ant_init_coex_dm(struct btc_coexist *btcoexist) +{ + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], Coex Mechanism Init!!\n"); + btc8723b2ant_init_coex_dm(btcoexist); +} + +void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist) +{ + struct btc_board_info *board_info = &btcoexist->board_info; + struct btc_stack_info *stack_info = &btcoexist->stack_info; + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + struct rtl_priv *rtlpriv = btcoexist->adapter; + u8 u8tmp[4], i, bt_info_ext, ps_tdma_case = 0; + u32 u32tmp[4]; + bool roam = false, scan = false; + bool link = false, wifi_under_5g = false; + bool bt_hs_on = false, wifi_busy = false; + s32 wifi_rssi = 0, bt_hs_rssi = 0; + u32 wifi_bw, wifi_traffic_dir, fa_ofdm, fa_cck; + u8 wifi_dot11_chnl, wifi_hs_chnl; + u32 fw_ver = 0, bt_patch_ver = 0; + u8 ap_num = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n ============[BT Coexist info]============"); + + if (btcoexist->manual_control) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n ==========[Under Manual Control]============"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n =========================================="); + } + + if (!board_info->bt_exist) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n BT not exists !!!"); + return; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d ", + "Ant PG number/ Ant mechanism:", + board_info->pg_ant_num, board_info->btdm_ant_num); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s / %d", + "BT stack/ hci ext ver", + ((stack_info->profile_notified) ? "Yes" : "No"), + stack_info->hci_version); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d_%x/ 0x%x/ 0x%x(%d)", + "CoexVer/ FwVer/ PatchVer", + glcoex_ver_date_8723b_2ant, glcoex_ver_8723b_2ant, + fw_ver, bt_patch_ver, bt_patch_ver); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_DOT11_CHNL, + &wifi_dot11_chnl); + btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_HS_CHNL, &wifi_hs_chnl); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d / %d(%d)", + "Dot11 channel / HsChnl(HsMode)", + wifi_dot11_chnl, wifi_hs_chnl, bt_hs_on); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %02x %02x %02x ", + "H2C Wifi inform bt chnl Info", coex_dm->wifi_chnl_info[0], + coex_dm->wifi_chnl_info[1], coex_dm->wifi_chnl_info[2]); + + btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); + btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi); + btcoexist->btc_get(btcoexist, BTC_GET_U1_AP_NUM, &ap_num); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d", + "Wifi rssi/ HS rssi/ AP#", wifi_rssi, bt_hs_rssi, ap_num); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d ", + "Wifi link/ roam/ scan", link, roam, scan); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, + &wifi_traffic_dir); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s / %s/ %s ", + "Wifi status", (wifi_under_5g ? "5G" : "2.4G"), + ((BTC_WIFI_BW_LEGACY == wifi_bw) ? "Legacy" : + (((BTC_WIFI_BW_HT40 == wifi_bw) ? "HT40" : "HT20"))), + ((!wifi_busy) ? "idle" : + ((BTC_WIFI_TRAFFIC_TX == wifi_traffic_dir) ? + "uplink" : "downlink"))); + + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d / %d / %d / %d", + "SCO/HID/PAN/A2DP", + bt_link_info->sco_exist, bt_link_info->hid_exist, + bt_link_info->pan_exist, bt_link_info->a2dp_exist); + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_BT_LINK_INFO); + + bt_info_ext = coex_sta->bt_info_ext; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s", + "BT Info A2DP rate", + (bt_info_ext&BIT0) ? "Basic rate" : "EDR rate"); + + for (i = 0; i < BT_INFO_SRC_8723B_2ANT_MAX; i++) { + if (coex_sta->bt_info_c2h_cnt[i]) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %02x %02x %02x " + "%02x %02x %02x %02x(%d)", + glbt_info_src_8723b_2ant[i], + coex_sta->bt_info_c2h[i][0], + coex_sta->bt_info_c2h[i][1], + coex_sta->bt_info_c2h[i][2], + coex_sta->bt_info_c2h[i][3], + coex_sta->bt_info_c2h[i][4], + coex_sta->bt_info_c2h[i][5], + coex_sta->bt_info_c2h[i][6], + coex_sta->bt_info_c2h_cnt[i]); + } + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s/%s", + "PS state, IPS/LPS", + ((coex_sta->under_ips ? "IPS ON" : "IPS OFF")), + ((coex_sta->under_lps ? "LPS ON" : "LPS OFF"))); + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD); + + /* Sw mechanism */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s", "============[Sw mechanism]============"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d ", + "SM1[ShRf/ LpRA/ LimDig]", coex_dm->cur_rf_rx_lpf_shrink, + coex_dm->cur_low_penalty_ra, coex_dm->limited_dig); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d(0x%x) ", + "SM2[AgcT/ AdcB/ SwDacSwing(lvl)]", + coex_dm->cur_agc_table_en, coex_dm->cur_adc_back_off, + coex_dm->cur_dac_swing_on, coex_dm->cur_dac_swing_lvl); + + /* Fw mechanism */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", + "============[Fw mechanism]============"); + + ps_tdma_case = coex_dm->cur_ps_tdma; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", + "PS TDMA", coex_dm->ps_tdma_para[0], + coex_dm->ps_tdma_para[1], coex_dm->ps_tdma_para[2], + coex_dm->ps_tdma_para[3], coex_dm->ps_tdma_para[4], + ps_tdma_case, coex_dm->auto_tdma_adjust); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d ", + "DecBtPwr/ IgnWlanAct", coex_dm->cur_dec_bt_pwr, + coex_dm->cur_ignore_wlan_act); + + /* Hw setting */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", + "============[Hw setting]============"); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x", + "RF-A, 0x1e initVal", coex_dm->bt_rf0x1e_backup); + + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x778); + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x880); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "0x778/0x880[29:25]", u8tmp[0], + (u32tmp[0]&0x3e000000) >> 25); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x948); + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x67); + u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x765); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "0x948/ 0x67[5] / 0x765", + u32tmp[0], ((u8tmp[0]&0x20) >> 5), u8tmp[1]); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x92c); + u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x930); + u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x944); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "0x92c[1:0]/ 0x930[7:0]/0x944[1:0]", + u32tmp[0]&0x3, u32tmp[1]&0xff, u32tmp[2]&0x3); + + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x39); + u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x40); + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x4c); + u8tmp[2] = btcoexist->btc_read_1byte(btcoexist, 0x64); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", + "0x38[11]/0x40/0x4c[24:23]/0x64[0]", + ((u8tmp[0] & 0x8)>>3), u8tmp[1], + ((u32tmp[0]&0x01800000)>>23), u8tmp[2]&0x1); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x550); + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x522); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "0x550(bcn ctrl)/0x522", u32tmp[0], u8tmp[0]); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc50); + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x49c); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "0xc50(dig)/0x49c(null-drop)", u32tmp[0]&0xff, u8tmp[0]); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xda0); + u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0xda4); + u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0xda8); + u32tmp[3] = btcoexist->btc_read_4byte(btcoexist, 0xcf0); + + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xa5b); + u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xa5c); + + fa_ofdm = ((u32tmp[0]&0xffff0000) >> 16) + + ((u32tmp[1]&0xffff0000) >> 16) + + (u32tmp[1] & 0xffff) + + (u32tmp[2] & 0xffff) + + ((u32tmp[3]&0xffff0000) >> 16) + + (u32tmp[3] & 0xffff); + fa_cck = (u8tmp[0] << 8) + u8tmp[1]; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "OFDM-CCA/OFDM-FA/CCK-FA", + u32tmp[0]&0xffff, fa_ofdm, fa_cck); + + u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6c0); + u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x6c4); + u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x6c8); + u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x6cc); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", + "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)", + u32tmp[0], u32tmp[1], u32tmp[2], u8tmp[0]); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", + "0x770(high-pri rx/tx)", + coex_sta->high_priority_rx, coex_sta->high_priority_tx); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", + "0x774(low-pri rx/tx)", coex_sta->low_priority_rx, + coex_sta->low_priority_tx); +#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 1) + btc8723b2ant_monitor_bt_ctr(btcoexist); +#endif + btcoexist->btc_disp_dbg_msg(btcoexist, + BTC_DBG_DISP_COEX_STATISTICS); +} + +void ex_btc8723b2ant_ips_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (BTC_IPS_ENTER == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], IPS ENTER notify\n"); + coex_sta->under_ips = true; + btc8723b2ant_wifioff_hwcfg(btcoexist); + btc8723b2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); + btc8723b2ant_coex_alloff(btcoexist); + } else if (BTC_IPS_LEAVE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], IPS LEAVE notify\n"); + coex_sta->under_ips = false; + ex_btc8723b2ant_init_hwconfig(btcoexist); + btc8723b2ant_init_coex_dm(btcoexist); + btc8723b2ant_query_bt_info(btcoexist); + } +} + +void ex_btc8723b2ant_lps_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (BTC_LPS_ENABLE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], LPS ENABLE notify\n"); + coex_sta->under_lps = true; + } else if (BTC_LPS_DISABLE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], LPS DISABLE notify\n"); + coex_sta->under_lps = false; + } +} + +void ex_btc8723b2ant_scan_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (BTC_SCAN_START == type) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], SCAN START notify\n"); + else if (BTC_SCAN_FINISH == type) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], SCAN FINISH notify\n"); +} + +void ex_btc8723b2ant_connect_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (BTC_ASSOCIATE_START == type) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], CONNECT START notify\n"); + else if (BTC_ASSOCIATE_FINISH == type) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], CONNECT FINISH notify\n"); +} + +void ex_btc8723b2ant_media_status_notify(struct btc_coexist *btcoexist, + u8 type) +{ + u8 h2c_parameter[3] = {0}; + u32 wifi_bw; + u8 wifi_central_chnl; + + if (BTC_MEDIA_CONNECT == type) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], MEDIA connect notify\n"); + else + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], MEDIA disconnect notify\n"); + + /* only 2.4G we need to inform bt the chnl mask */ + btcoexist->btc_get(btcoexist, + BTC_GET_U1_WIFI_CENTRAL_CHNL, &wifi_central_chnl); + if ((BTC_MEDIA_CONNECT == type) && + (wifi_central_chnl <= 14)) { + h2c_parameter[0] = 0x1; + h2c_parameter[1] = wifi_central_chnl; + btcoexist->btc_get(btcoexist, + BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) + h2c_parameter[2] = 0x30; + else + h2c_parameter[2] = 0x20; + } + + coex_dm->wifi_chnl_info[0] = h2c_parameter[0]; + coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; + coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x66=0x%x\n", + h2c_parameter[0] << 16 | h2c_parameter[1] << 8 | + h2c_parameter[2]); + + btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); +} + +void ex_btc8723b2ant_special_packet_notify(struct btc_coexist *btcoexist, + u8 type) +{ + if (type == BTC_PACKET_DHCP) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], DHCP Packet notify\n"); +} + +void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist, + u8 *tmpbuf, u8 length) +{ + u8 bt_info = 0; + u8 i, rsp_source = 0; + bool bt_busy = false, limited_dig = false; + bool wifi_connected = false; + + coex_sta->c2h_bt_info_req_sent = false; + + rsp_source = tmpbuf[0]&0xf; + if (rsp_source >= BT_INFO_SRC_8723B_2ANT_MAX) + rsp_source = BT_INFO_SRC_8723B_2ANT_WIFI_FW; + coex_sta->bt_info_c2h_cnt[rsp_source]++; + + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], Bt info[%d], length=%d, hex data=[", + rsp_source, length); + for (i = 0; i < length; i++) { + coex_sta->bt_info_c2h[rsp_source][i] = tmpbuf[i]; + if (i == 1) + bt_info = tmpbuf[i]; + if (i == length-1) + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "0x%02x]\n", tmpbuf[i]); + else + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "0x%02x, ", tmpbuf[i]); + } + + if (btcoexist->manual_control) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), " + "return for Manual CTRL<===\n"); + return; + } + + if (BT_INFO_SRC_8723B_2ANT_WIFI_FW != rsp_source) { + coex_sta->bt_retry_cnt = /* [3:0]*/ + coex_sta->bt_info_c2h[rsp_source][2] & 0xf; + + coex_sta->bt_rssi = + coex_sta->bt_info_c2h[rsp_source][3] * 2 + 10; + + coex_sta->bt_info_ext = + coex_sta->bt_info_c2h[rsp_source][4]; + + /* Here we need to resend some wifi info to BT + because bt is reset and loss of the info. + */ + if ((coex_sta->bt_info_ext & BIT1)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT ext info bit1 check," + " send wifi BW&Chnl to BT!!\n"); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + if (wifi_connected) + ex_btc8723b2ant_media_status_notify( + btcoexist, + BTC_MEDIA_CONNECT); + else + ex_btc8723b2ant_media_status_notify( + btcoexist, + BTC_MEDIA_DISCONNECT); + } + + if ((coex_sta->bt_info_ext & BIT3)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT ext info bit3 check, " + "set BT NOT to ignore Wlan active!!\n"); + btc8723b2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, + false); + } else { + /* BT already NOT ignore Wlan active, do nothing here.*/ + } +#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 0) + if ((coex_sta->bt_info_ext & BIT4)) { + /* BT auto report already enabled, do nothing*/ + } else { + btc8723b2ant_bt_auto_report(btcoexist, FORCE_EXEC, + true); + } +#endif + } + + /* check BIT2 first ==> check if bt is under inquiry or page scan*/ + if (bt_info & BT_INFO_8723B_2ANT_B_INQ_PAGE) + coex_sta->c2h_bt_inquiry_page = true; + else + coex_sta->c2h_bt_inquiry_page = false; + + /* set link exist status*/ + if (!(bt_info & BT_INFO_8723B_2ANT_B_CONNECTION)) { + coex_sta->bt_link_exist = false; + coex_sta->pan_exist = false; + coex_sta->a2dp_exist = false; + coex_sta->hid_exist = false; + coex_sta->sco_exist = false; + } else { /* connection exists */ + coex_sta->bt_link_exist = true; + if (bt_info & BT_INFO_8723B_2ANT_B_FTP) + coex_sta->pan_exist = true; + else + coex_sta->pan_exist = false; + if (bt_info & BT_INFO_8723B_2ANT_B_A2DP) + coex_sta->a2dp_exist = true; + else + coex_sta->a2dp_exist = false; + if (bt_info & BT_INFO_8723B_2ANT_B_HID) + coex_sta->hid_exist = true; + else + coex_sta->hid_exist = false; + if (bt_info & BT_INFO_8723B_2ANT_B_SCO_ESCO) + coex_sta->sco_exist = true; + else + coex_sta->sco_exist = false; + } + + btc8723b2ant_update_bt_link_info(btcoexist); + + if (!(bt_info & BT_INFO_8723B_2ANT_B_CONNECTION)) { + coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), " + "BT Non-Connected idle!!!\n"); + /* connection exists but no busy */ + } else if (bt_info == BT_INFO_8723B_2ANT_B_CONNECTION) { + coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"); + } else if ((bt_info & BT_INFO_8723B_2ANT_B_SCO_ESCO) || + (bt_info & BT_INFO_8723B_2ANT_B_SCO_BUSY)) { + coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_SCO_BUSY; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"); + } else if (bt_info&BT_INFO_8723B_2ANT_B_ACL_BUSY) { + coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_ACL_BUSY; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"); + } else { + coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_MAX; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), " + "BT Non-Defined state!!!\n"); + } + + if ((BT_8723B_2ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || + (BT_8723B_2ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || + (BT_8723B_2ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) { + bt_busy = true; + limited_dig = true; + } else { + bt_busy = false; + limited_dig = false; + } + + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy); + + coex_dm->limited_dig = limited_dig; + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_LIMITED_DIG, &limited_dig); + + btc8723b2ant_run_coexist_mechanism(btcoexist); +} + +void ex_btc8723b2ant_halt_notify(struct btc_coexist *btcoexist) +{ + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "[BTCoex], Halt notify\n"); + + btc8723b2ant_wifioff_hwcfg(btcoexist); + btc8723b2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); + ex_btc8723b2ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT); +} + +void ex_btc8723b2ant_periodical(struct btc_coexist *btcoexist) +{ + struct btc_board_info *board_info = &btcoexist->board_info; + struct btc_stack_info *stack_info = &btcoexist->stack_info; + static u8 dis_ver_info_cnt; + u32 fw_ver = 0, bt_patch_ver = 0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], ==========================" + "Periodical===========================\n"); + + if (dis_ver_info_cnt <= 5) { + dis_ver_info_cnt += 1; + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], ****************************" + "************************************\n"); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], Ant PG Num/ Ant Mech/ " + "Ant Pos = %d/ %d/ %d\n", board_info->pg_ant_num, + board_info->btdm_ant_num, board_info->btdm_ant_pos); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], BT stack/ hci ext ver = %s / %d\n", + ((stack_info->profile_notified) ? "Yes" : "No"), + stack_info->hci_version); + btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, + &bt_patch_ver); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], CoexVer/ fw_ver/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", + glcoex_ver_date_8723b_2ant, glcoex_ver_8723b_2ant, + fw_ver, bt_patch_ver, bt_patch_ver); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], *****************************" + "***********************************\n"); + } + +#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 0) + btc8723b2ant_query_bt_info(btcoexist); + btc8723b2ant_monitor_bt_ctr(btcoexist); + btc8723b2ant_monitor_bt_enable_disable(btcoexist); +#else + if (btc8723b2ant_is_wifi_status_changed(btcoexist) || + coex_dm->auto_tdma_adjust) + btc8723b2ant_run_coexist_mechanism(btcoexist); +#endif +} diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h new file mode 100644 index 000000000000..567f354caf95 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.h @@ -0,0 +1,172 @@ +/****************************************************************************** + * + * Copyright(c) 2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef _HAL8723B_2_ANT +#define _HAL8723B_2_ANT + +/************************************************************************ + * The following is for 8723B 2Ant BT Co-exist definition + ************************************************************************/ +#define BT_AUTO_REPORT_ONLY_8723B_2ANT 1 + +#define BT_INFO_8723B_2ANT_B_FTP BIT7 +#define BT_INFO_8723B_2ANT_B_A2DP BIT6 +#define BT_INFO_8723B_2ANT_B_HID BIT5 +#define BT_INFO_8723B_2ANT_B_SCO_BUSY BIT4 +#define BT_INFO_8723B_2ANT_B_ACL_BUSY BIT3 +#define BT_INFO_8723B_2ANT_B_INQ_PAGE BIT2 +#define BT_INFO_8723B_2ANT_B_SCO_ESCO BIT1 +#define BT_INFO_8723B_2ANT_B_CONNECTION BIT0 + +#define BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT 2 + +enum BT_INFO_SRC_8723B_2ANT { + BT_INFO_SRC_8723B_2ANT_WIFI_FW = 0x0, + BT_INFO_SRC_8723B_2ANT_BT_RSP = 0x1, + BT_INFO_SRC_8723B_2ANT_BT_ACTIVE_SEND = 0x2, + BT_INFO_SRC_8723B_2ANT_MAX +}; + +enum BT_8723B_2ANT_BT_STATUS { + BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0, + BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE = 0x1, + BT_8723B_2ANT_BT_STATUS_INQ_PAGE = 0x2, + BT_8723B_2ANT_BT_STATUS_ACL_BUSY = 0x3, + BT_8723B_2ANT_BT_STATUS_SCO_BUSY = 0x4, + BT_8723B_2ANT_BT_STATUS_ACL_SCO_BUSY = 0x5, + BT_8723B_2ANT_BT_STATUS_MAX +}; + +enum BT_8723B_2ANT_COEX_ALGO { + BT_8723B_2ANT_COEX_ALGO_UNDEFINED = 0x0, + BT_8723B_2ANT_COEX_ALGO_SCO = 0x1, + BT_8723B_2ANT_COEX_ALGO_HID = 0x2, + BT_8723B_2ANT_COEX_ALGO_A2DP = 0x3, + BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS = 0x4, + BT_8723B_2ANT_COEX_ALGO_PANEDR = 0x5, + BT_8723B_2ANT_COEX_ALGO_PANHS = 0x6, + BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP = 0x7, + BT_8723B_2ANT_COEX_ALGO_PANEDR_HID = 0x8, + BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x9, + BT_8723B_2ANT_COEX_ALGO_HID_A2DP = 0xa, + BT_8723B_2ANT_COEX_ALGO_MAX = 0xb, +}; + +struct coex_dm_8723b_2ant { + /* fw mechanism */ + bool pre_dec_bt_pwr; + bool cur_dec_bt_pwr; + u8 pre_fw_dac_swing_lvl; + u8 cur_fw_dac_swing_lvl; + bool cur_ignore_wlan_act; + bool pre_ignore_wlan_act; + u8 pre_ps_tdma; + u8 cur_ps_tdma; + u8 ps_tdma_para[5]; + u8 tdma_adj_type; + bool reset_tdma_adjust; + bool auto_tdma_adjust; + bool pre_ps_tdma_on; + bool cur_ps_tdma_on; + bool pre_bt_auto_report; + bool cur_bt_auto_report; + + /* sw mechanism */ + bool pre_rf_rx_lpf_shrink; + bool cur_rf_rx_lpf_shrink; + u32 bt_rf0x1e_backup; + bool pre_low_penalty_ra; + bool cur_low_penalty_ra; + bool pre_dac_swing_on; + u32 pre_dac_swing_lvl; + bool cur_dac_swing_on; + u32 cur_dac_swing_lvl; + bool pre_adc_back_off; + bool cur_adc_back_off; + bool pre_agc_table_en; + bool cur_agc_table_en; + u32 pre_val0x6c0; + u32 cur_val0x6c0; + u32 pre_val0x6c4; + u32 cur_val0x6c4; + u32 pre_val0x6c8; + u32 cur_val0x6c8; + u8 pre_val0x6cc; + u8 cur_val0x6cc; + bool limited_dig; + + /* algorithm related */ + u8 pre_algorithm; + u8 cur_algorithm; + u8 bt_status; + u8 wifi_chnl_info[3]; + + bool need_recover_0x948; + u16 backup_0x948; +}; + +struct coex_sta_8723b_2ant { + bool bt_link_exist; + bool sco_exist; + bool a2dp_exist; + bool hid_exist; + bool pan_exist; + + bool under_lps; + bool under_ips; + u32 high_priority_tx; + u32 high_priority_rx; + u32 low_priority_tx; + u32 low_priority_rx; + u8 bt_rssi; + u8 pre_bt_rssi_state; + u8 pre_wifi_rssi_state[4]; + bool c2h_bt_info_req_sent; + u8 bt_info_c2h[BT_INFO_SRC_8723B_2ANT_MAX][10]; + u32 bt_info_c2h_cnt[BT_INFO_SRC_8723B_2ANT_MAX]; + bool c2h_bt_inquiry_page; + u8 bt_retry_cnt; + u8 bt_info_ext; +}; + +/********************************************************************* + * The following is interface which will notify coex module. + *********************************************************************/ +void ex_btc8723b2ant_init_hwconfig(struct btc_coexist *btcoexist); +void ex_btc8723b2ant_init_coex_dm(struct btc_coexist *btcoexist); +void ex_btc8723b2ant_ips_notify(struct btc_coexist *btcoexist, u8 type); +void ex_btc8723b2ant_lps_notify(struct btc_coexist *btcoexist, u8 type); +void ex_btc8723b2ant_scan_notify(struct btc_coexist *btcoexist, u8 type); +void ex_btc8723b2ant_connect_notify(struct btc_coexist *btcoexist, u8 type); +void ex_btc8723b2ant_media_status_notify(struct btc_coexist *btcoexist, + u8 type); +void ex_btc8723b2ant_special_packet_notify(struct btc_coexist *btcoexist, + u8 type); +void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist, + u8 *tmpbuf, u8 length); +void ex_btc8723b2ant_halt_notify(struct btc_coexist *btcoexist); +void ex_btc8723b2ant_periodical(struct btc_coexist *btcoexist); +void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c new file mode 100644 index 000000000000..b72e5377bdbc --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c @@ -0,0 +1,2970 @@ +/****************************************************************************** + * + * Copyright(c) 2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +/*============================================================ + * Description: + * + * This file is for RTL8821A Co-exist mechanism + * + * History + * 2012/11/15 Cosa first check in. + * + *============================================================ +*/ +/*============================================================ + * include files + *============================================================ + */ +#include "halbt_precomp.h" +/*============================================================ + * Global variables, these are static variables + *============================================================ + */ +static struct coex_dm_8821a_1ant glcoex_dm_8821a_1ant; +static struct coex_dm_8821a_1ant *coex_dm = &glcoex_dm_8821a_1ant; +static struct coex_sta_8821a_1ant glcoex_sta_8821a_1ant; +static struct coex_sta_8821a_1ant *coex_sta = &glcoex_sta_8821a_1ant; + +static const char *const glbt_info_src_8821a_1ant[] = { + "BT Info[wifi fw]", + "BT Info[bt rsp]", + "BT Info[bt auto report]", +}; + +static u32 glcoex_ver_date_8821a_1ant = 20130816; +static u32 glcoex_ver_8821a_1ant = 0x41; + +/*============================================================ + * local function proto type if needed + * + * local function start with halbtc8821a1ant_ + *============================================================ + */ +static u8 halbtc8821a1ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, + u8 rssi_thresh1) +{ + long bt_rssi = 0; + u8 bt_rssi_state = coex_sta->pre_bt_rssi_state; + + bt_rssi = coex_sta->bt_rssi; + + if (level_num == 2) { + if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || + (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { + if (bt_rssi >= (rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { + bt_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); + } + } else { + if (bt_rssi < rssi_thresh) { + bt_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); + } + } + } else if (level_num == 3) { + if (rssi_thresh > rssi_thresh1) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi thresh error!!\n"); + return coex_sta->pre_bt_rssi_state; + } + + if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || + (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { + if (bt_rssi >= (rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { + bt_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); + } + } else if ((coex_sta->pre_bt_rssi_state == + BTC_RSSI_STATE_MEDIUM) || + (coex_sta->pre_bt_rssi_state == + BTC_RSSI_STATE_STAY_MEDIUM)) { + if (bt_rssi >= (rssi_thresh1 + + BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { + bt_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); + } else if (bt_rssi < rssi_thresh) { + bt_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Medium\n"); + } + } else { + if (bt_rssi < rssi_thresh1) { + bt_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); + } + } + } + coex_sta->pre_bt_rssi_state = bt_rssi_state; + + return bt_rssi_state; +} + +static u8 halbtc8821a1ant_WifiRssiState(struct btc_coexist *btcoexist, + u8 index, u8 level_num, u8 rssi_thresh, + u8 rssi_thresh1) +{ + long wifi_rssi = 0; + u8 wifi_rssi_state = coex_sta->pre_wifi_rssi_state[index]; + + btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); + + if (level_num == 2) { + if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_LOW) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_LOW)) { + if (wifi_rssi >= + (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { + wifi_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); + } + } else { + if (wifi_rssi < rssi_thresh) { + wifi_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); + } + } + } else if (level_num == 3) { + if (rssi_thresh > rssi_thresh1) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI thresh error!!\n"); + return coex_sta->pre_wifi_rssi_state[index]; + } + + if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_LOW) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_LOW)) { + if (wifi_rssi >= + (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { + wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); + } + } else if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_MEDIUM) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_MEDIUM)) { + if (wifi_rssi >= + (rssi_thresh1 + + BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { + wifi_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); + } else if (wifi_rssi < rssi_thresh) { + wifi_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Medium\n"); + } + } else { + if (wifi_rssi < rssi_thresh1) { + wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); + } + } + } + coex_sta->pre_wifi_rssi_state[index] = wifi_rssi_state; + + return wifi_rssi_state; +} + +static void halbtc8821a1ant_update_ra_mask(struct btc_coexist *btcoexist, + bool force_exec, u32 dis_rate_mask) +{ + coex_dm->cur_ra_mask = dis_rate_mask; + + if (force_exec || + (coex_dm->pre_ra_mask != coex_dm->cur_ra_mask)) { + btcoexist->btc_set(btcoexist, BTC_SET_ACT_UPDATE_ra_mask, + &coex_dm->cur_ra_mask); + } + coex_dm->pre_ra_mask = coex_dm->cur_ra_mask; +} + +static void btc8821a1ant_auto_rate_fb_retry(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + bool wifi_under_b_mode = false; + + coex_dm->cur_arfr_type = type; + + if (force_exec || + (coex_dm->pre_arfr_type != coex_dm->cur_arfr_type)) { + switch (coex_dm->cur_arfr_type) { + case 0: /* normal mode*/ + btcoexist->btc_write_4byte(btcoexist, 0x430, + coex_dm->backup_arfr_cnt1); + btcoexist->btc_write_4byte(btcoexist, 0x434, + coex_dm->backup_arfr_cnt2); + break; + case 1: + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_UNDER_B_MODE, + &wifi_under_b_mode); + if (wifi_under_b_mode) { + btcoexist->btc_write_4byte(btcoexist, 0x430, + 0x0); + btcoexist->btc_write_4byte(btcoexist, 0x434, + 0x01010101); + } else { + btcoexist->btc_write_4byte(btcoexist, 0x430, + 0x0); + btcoexist->btc_write_4byte(btcoexist, 0x434, + 0x04030201); + } + break; + default: + break; + } + } + + coex_dm->pre_arfr_type = coex_dm->cur_arfr_type; +} + +static void halbtc8821a1ant_retry_limit(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + coex_dm->cur_retry_limit_type = type; + + if (force_exec || + (coex_dm->pre_retry_limit_type != coex_dm->cur_retry_limit_type)) { + switch (coex_dm->cur_retry_limit_type) { + case 0: /* normal mode*/ + btcoexist->btc_write_2byte(btcoexist, 0x42a, + coex_dm->backup_retry_limit); + break; + case 1: /* retry limit = 8*/ + btcoexist->btc_write_2byte(btcoexist, 0x42a, 0x0808); + break; + default: + break; + } + } + coex_dm->pre_retry_limit_type = coex_dm->cur_retry_limit_type; +} + +static void halbtc8821a1ant_ampdu_max_time(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + coex_dm->cur_ampdu_time_type = type; + + if (force_exec || + (coex_dm->pre_ampdu_time_type != coex_dm->cur_ampdu_time_type)) { + switch (coex_dm->cur_ampdu_time_type) { + case 0: /* normal mode*/ + btcoexist->btc_write_1byte(btcoexist, 0x456, + coex_dm->backup_ampdu_max_time); + break; + case 1: /* AMPDU timw = 0x38 * 32us*/ + btcoexist->btc_write_1byte(btcoexist, 0x456, 0x38); + break; + default: + break; + } + } + + coex_dm->pre_ampdu_time_type = coex_dm->cur_ampdu_time_type; +} + +static void halbtc8821a1ant_limited_tx(struct btc_coexist *btcoexist, + bool force_exec, u8 ra_mask_type, + u8 arfr_type, u8 retry_limit_type, + u8 ampdu_time_type) +{ + switch (ra_mask_type) { + case 0: /* normal mode*/ + halbtc8821a1ant_update_ra_mask(btcoexist, force_exec, 0x0); + break; + case 1: /* disable cck 1/2*/ + halbtc8821a1ant_update_ra_mask(btcoexist, force_exec, + 0x00000003); + break; + case 2: /* disable cck 1/2/5.5, ofdm 6/9/12/18/24, mcs 0/1/2/3/4*/ + halbtc8821a1ant_update_ra_mask(btcoexist, force_exec, + 0x0001f1f7); + break; + default: + break; + } + + btc8821a1ant_auto_rate_fb_retry(btcoexist, force_exec, arfr_type); + halbtc8821a1ant_retry_limit(btcoexist, force_exec, retry_limit_type); + halbtc8821a1ant_ampdu_max_time(btcoexist, force_exec, ampdu_time_type); +} + +static void halbtc8821a1ant_limited_rx(struct btc_coexist *btcoexist, + bool force_exec, bool rej_ap_agg_pkt, + bool bt_ctrl_agg_buf_size, + u8 agg_buf_size) +{ + bool reject_rx_agg = rej_ap_agg_pkt; + bool bt_ctrl_rx_agg_size = bt_ctrl_agg_buf_size; + u8 rx_agg_size = agg_buf_size; + + /*============================================*/ + /* Rx Aggregation related setting*/ + /*============================================*/ + btcoexist->btc_set(btcoexist, + BTC_SET_BL_TO_REJ_AP_AGG_PKT, &reject_rx_agg); + /* decide BT control aggregation buf size or not*/ + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_CTRL_AGG_SIZE, + &bt_ctrl_rx_agg_size); + /* aggregation buf size, only work when BT control Rx agg size.*/ + btcoexist->btc_set(btcoexist, BTC_SET_U1_AGG_BUF_SIZE, &rx_agg_size); + /* real update aggregation setting*/ + btcoexist->btc_set(btcoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL); +} + +static void halbtc8821a1ant_monitor_bt_ctr(struct btc_coexist *btcoexist) +{ + u32 reg_hp_tx_rx, reg_lp_tx_rx, u4_tmp; + u32 reg_hp_tx = 0, reg_hp_rx = 0, reg_lp_tx = 0, reg_lp_rx = 0; + + reg_hp_tx_rx = 0x770; + reg_lp_tx_rx = 0x774; + + u4_tmp = btcoexist->btc_read_4byte(btcoexist, reg_hp_tx_rx); + reg_hp_tx = u4_tmp & MASKLWORD; + reg_hp_rx = (u4_tmp & MASKHWORD)>>16; + + u4_tmp = btcoexist->btc_read_4byte(btcoexist, reg_lp_tx_rx); + reg_lp_tx = u4_tmp & MASKLWORD; + reg_lp_rx = (u4_tmp & MASKHWORD)>>16; + + coex_sta->high_priority_tx = reg_hp_tx; + coex_sta->high_priority_rx = reg_hp_rx; + coex_sta->low_priority_tx = reg_lp_tx; + coex_sta->low_priority_rx = reg_lp_rx; + + /* reset counter*/ + btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); +} + +static void halbtc8821a1ant_query_bt_info(struct btc_coexist *btcoexist) +{ + u8 h2c_parameter[1] = {0}; + + coex_sta->c2h_bt_info_req_sent = true; + + h2c_parameter[0] |= BIT0; /* trigger*/ + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", + h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); +} + +static void halbtc8821a1ant_update_bt_link_info(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool bt_hs_on = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + + bt_link_info->bt_link_exist = coex_sta->bt_link_exist; + bt_link_info->sco_exist = coex_sta->sco_exist; + bt_link_info->a2dp_exist = coex_sta->a2dp_exist; + bt_link_info->pan_exist = coex_sta->pan_exist; + bt_link_info->hid_exist = coex_sta->hid_exist; + + /* work around for HS mode.*/ + if (bt_hs_on) { + bt_link_info->pan_exist = true; + bt_link_info->bt_link_exist = true; + } + + /* check if Sco only*/ + if (bt_link_info->sco_exist && + !bt_link_info->a2dp_exist && + !bt_link_info->pan_exist && + !bt_link_info->hid_exist) + bt_link_info->sco_only = true; + else + bt_link_info->sco_only = false; + + /* check if A2dp only*/ + if (!bt_link_info->sco_exist && + bt_link_info->a2dp_exist && + !bt_link_info->pan_exist && + !bt_link_info->hid_exist) + bt_link_info->a2dp_only = true; + else + bt_link_info->a2dp_only = false; + + /* check if Pan only*/ + if (!bt_link_info->sco_exist && + !bt_link_info->a2dp_exist && + bt_link_info->pan_exist && + !bt_link_info->hid_exist) + bt_link_info->pan_only = true; + else + bt_link_info->pan_only = false; + + /* check if Hid only*/ + if (!bt_link_info->sco_exist && + !bt_link_info->a2dp_exist && + !bt_link_info->pan_exist && + bt_link_info->hid_exist) + bt_link_info->hid_only = true; + else + bt_link_info->hid_only = false; +} + +static u8 halbtc8821a1ant_action_algorithm(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool bt_hs_on = false; + u8 algorithm = BT_8821A_1ANT_COEX_ALGO_UNDEFINED; + u8 num_of_diff_profile = 0; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + + if (!bt_link_info->bt_link_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], No BT link exists!!!\n"); + return algorithm; + } + + if (bt_link_info->sco_exist) + num_of_diff_profile++; + if (bt_link_info->hid_exist) + num_of_diff_profile++; + if (bt_link_info->pan_exist) + num_of_diff_profile++; + if (bt_link_info->a2dp_exist) + num_of_diff_profile++; + + if (num_of_diff_profile == 1) { + if (bt_link_info->sco_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO only\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_SCO; + } else { + if (bt_link_info->hid_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = HID only\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_HID; + } else if (bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = A2DP only\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_A2DP; + } else if (bt_link_info->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = PAN(HS) only\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_PANHS; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = PAN(EDR) only\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR; + } + } + } + } else if (num_of_diff_profile == 2) { + if (bt_link_info->sco_exist) { + if (bt_link_info->hid_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_HID; + } else if (bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + A2DP ==> SCO\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_SCO; + } else if (bt_link_info->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + PAN(HS)\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_SCO; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + PAN(EDR)\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; + } + } + } else { + if (bt_link_info->hid_exist && + bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = HID + A2DP\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP; + } else if (bt_link_info->hid_exist && + bt_link_info->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = HID + PAN(HS)\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = HID + PAN(EDR)\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; + } + } else if (bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = A2DP + PAN(HS)\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_A2DP_PANHS; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = A2DP + PAN(EDR)\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_A2DP; + } + } + } + } else if (num_of_diff_profile == 3) { + if (bt_link_info->sco_exist) { + if (bt_link_info->hid_exist && + bt_link_info->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + A2DP ==> HID\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_HID; + } else if (bt_link_info->hid_exist && + bt_link_info->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + PAN(HS)\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + PAN(EDR)\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; + } + } else if (bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + A2DP + PAN(HS)\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_SCO; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + A2DP + PAN(EDR) ==> HID\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; + } + } + } else { + if (bt_link_info->hid_exist && + bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = HID + A2DP + PAN(HS)\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = HID + A2DP + PAN(EDR)\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP_PANEDR; + } + } + } + } else if (num_of_diff_profile >= 3) { + if (bt_link_info->sco_exist) { + if (bt_link_info->hid_exist && + bt_link_info->pan_exist && + bt_link_info->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Error!!! BT Profile = SCO + HID + A2DP + PAN(HS)\n"); + + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT Profile = SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); + algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; + } + } + } + } + return algorithm; +} + +static void halbtc8821a1ant_set_bt_auto_report(struct btc_coexist *btcoexist, + bool enable_auto_report) +{ + u8 h2c_parameter[1] = {0}; + + h2c_parameter[0] = 0; + + if (enable_auto_report) + h2c_parameter[0] |= BIT0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], BT FW auto report : %s, FW write 0x68 = 0x%x\n", + (enable_auto_report ? "Enabled!!" : "Disabled!!"), + h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter); +} + +static void halbtc8821a1ant_bt_auto_report(struct btc_coexist *btcoexist, + bool force_exec, + bool enable_auto_report) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW, "[BTCoex], %s BT Auto report = %s\n", + (force_exec ? "force to" : ""), ((enable_auto_report) ? + "Enabled" : "Disabled")); + coex_dm->cur_bt_auto_report = enable_auto_report; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_bt_auto_report = %d, cur_bt_auto_report = %d\n", + coex_dm->pre_bt_auto_report, + coex_dm->cur_bt_auto_report); + + if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report) + return; + } + halbtc8821a1ant_set_bt_auto_report(btcoexist, coex_dm->cur_bt_auto_report); + + coex_dm->pre_bt_auto_report = coex_dm->cur_bt_auto_report; +} + +static void btc8821a1ant_set_sw_pen_tx_rate(struct btc_coexist *btcoexist, + bool low_penalty_ra) +{ + u8 h2c_parameter[6] = {0}; + + h2c_parameter[0] = 0x6; /* opCode, 0x6= Retry_Penalty*/ + + if (low_penalty_ra) { + h2c_parameter[1] |= BIT0; + /*normal rate except MCS7/6/5, OFDM54/48/36*/ + h2c_parameter[2] = 0x00; + h2c_parameter[3] = 0xf7; /*MCS7 or OFDM54*/ + h2c_parameter[4] = 0xf8; /*MCS6 or OFDM48*/ + h2c_parameter[5] = 0xf9; /*MCS5 or OFDM36*/ + } + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], set WiFi Low-Penalty Retry: %s", + (low_penalty_ra ? "ON!!" : "OFF!!")); + + btcoexist->btc_fill_h2c(btcoexist, 0x69, 6, h2c_parameter); +} + +static void halbtc8821a1ant_low_penalty_ra(struct btc_coexist *btcoexist, + bool force_exec, bool low_penalty_ra) +{ + coex_dm->cur_low_penalty_ra = low_penalty_ra; + + if (!force_exec) { + if (coex_dm->pre_low_penalty_ra == coex_dm->cur_low_penalty_ra) + return; + } + btc8821a1ant_set_sw_pen_tx_rate(btcoexist, coex_dm->cur_low_penalty_ra); + + coex_dm->pre_low_penalty_ra = coex_dm->cur_low_penalty_ra; +} + +static void halbtc8821a1ant_set_coex_table(struct btc_coexist *btcoexist, + u32 val0x6c0, u32 val0x6c4, + u32 val0x6c8, u8 val0x6cc) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); + btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); + btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); + btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); + btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); +} + +static void halbtc8821a1ant_coex_table(struct btc_coexist *btcoexist, + bool force_exec, u32 val0x6c0, + u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", + (force_exec ? "force to" : ""), val0x6c0, val0x6c4, + val0x6c8, val0x6cc); + coex_dm->cur_val_0x6c0 = val0x6c0; + coex_dm->cur_val_0x6c4 = val0x6c4; + coex_dm->cur_val_0x6c8 = val0x6c8; + coex_dm->cur_val_0x6cc = val0x6cc; + + if (!force_exec) { + if ((coex_dm->pre_val_0x6c0 == coex_dm->cur_val_0x6c0) && + (coex_dm->pre_val_0x6c4 == coex_dm->cur_val_0x6c4) && + (coex_dm->pre_val_0x6c8 == coex_dm->cur_val_0x6c8) && + (coex_dm->pre_val_0x6cc == coex_dm->cur_val_0x6cc)) + return; + } + halbtc8821a1ant_set_coex_table(btcoexist, val0x6c0, val0x6c4, + val0x6c8, val0x6cc); + + coex_dm->pre_val_0x6c0 = coex_dm->cur_val_0x6c0; + coex_dm->pre_val_0x6c4 = coex_dm->cur_val_0x6c4; + coex_dm->pre_val_0x6c8 = coex_dm->cur_val_0x6c8; + coex_dm->pre_val_0x6cc = coex_dm->cur_val_0x6cc; +} + +static void halbtc8821a1ant_coex_table_with_type(struct btc_coexist *btcoexist, + bool force_exec, u8 type) +{ + switch (type) { + case 0: + halbtc8821a1ant_coex_table(btcoexist, force_exec, 0x55555555, + 0x55555555, 0xffffff, 0x3); + break; + case 1: + halbtc8821a1ant_coex_table(btcoexist, force_exec, + 0x55555555, 0x5a5a5a5a, + 0xffffff, 0x3); + break; + case 2: + halbtc8821a1ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a, + 0x5a5a5a5a, 0xffffff, 0x3); + break; + case 3: + halbtc8821a1ant_coex_table(btcoexist, force_exec, 0x55555555, + 0xaaaaaaaa, 0xffffff, 0x3); + break; + case 4: + halbtc8821a1ant_coex_table(btcoexist, force_exec, 0xffffffff, + 0xffffffff, 0xffffff, 0x3); + break; + case 5: + halbtc8821a1ant_coex_table(btcoexist, force_exec, 0x5fff5fff, + 0x5fff5fff, 0xffffff, 0x3); + break; + case 6: + halbtc8821a1ant_coex_table(btcoexist, force_exec, 0x55ff55ff, + 0x5a5a5a5a, 0xffffff, 0x3); + break; + case 7: + halbtc8821a1ant_coex_table(btcoexist, force_exec, 0x5afa5afa, + 0x5afa5afa, 0xffffff, 0x3); + break; + default: + break; + } +} + +static void btc8821a1ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, + bool enable) +{ + u8 h2c_parameter[1] = {0}; + + if (enable) + h2c_parameter[0] |= BIT0; /* function enable*/ + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", + h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); +} + +static void halbtc8821a1ant_ignore_wlan_act(struct btc_coexist *btcoexist, + bool force_exec, bool enable) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s turn Ignore WlanAct %s\n", + (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); + coex_dm->cur_ignore_wlan_act = enable; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_ignore_wlan_act = %d, cur_ignore_wlan_act = %d!!\n", + coex_dm->pre_ignore_wlan_act, + coex_dm->cur_ignore_wlan_act); + + if (coex_dm->pre_ignore_wlan_act == + coex_dm->cur_ignore_wlan_act) + return; + } + btc8821a1ant_set_fw_ignore_wlan_act(btcoexist, enable); + + coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; +} + +static void halbtc8821a1ant_set_fw_pstdma(struct btc_coexist *btcoexist, + u8 byte1, u8 byte2, u8 byte3, + u8 byte4, u8 byte5) +{ + u8 h2c_parameter[5] = {0}; + + h2c_parameter[0] = byte1; + h2c_parameter[1] = byte2; + h2c_parameter[2] = byte3; + h2c_parameter[3] = byte4; + h2c_parameter[4] = byte5; + + coex_dm->ps_tdma_para[0] = byte1; + coex_dm->ps_tdma_para[1] = byte2; + coex_dm->ps_tdma_para[2] = byte3; + coex_dm->ps_tdma_para[3] = byte4; + coex_dm->ps_tdma_para[4] = byte5; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], PS-TDMA H2C cmd =0x%x%08x\n", + h2c_parameter[0], + h2c_parameter[1]<<24 | + h2c_parameter[2]<<16 | + h2c_parameter[3]<<8 | + h2c_parameter[4]); + btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); +} + +static void halbtc8821a1ant_set_lps_rpwm(struct btc_coexist *btcoexist, + u8 lps_val, u8 rpwm_val) +{ + u8 lps = lps_val; + u8 rpwm = rpwm_val; + + btcoexist->btc_set(btcoexist, BTC_SET_U1_LPS_VAL, &lps); + btcoexist->btc_set(btcoexist, BTC_SET_U1_RPWM_VAL, &rpwm); +} + +static void halbtc8821a1ant_lps_rpwm(struct btc_coexist *btcoexist, + bool force_exec, u8 lps_val, u8 rpwm_val) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s set lps/rpwm = 0x%x/0x%x\n", + (force_exec ? "force to" : ""), lps_val, rpwm_val); + coex_dm->cur_lps = lps_val; + coex_dm->cur_rpwm = rpwm_val; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], LPS-RxBeaconMode = 0x%x, LPS-RPWM = 0x%x!!\n", + coex_dm->cur_lps, coex_dm->cur_rpwm); + + if ((coex_dm->pre_lps == coex_dm->cur_lps) && + (coex_dm->pre_rpwm == coex_dm->cur_rpwm)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], LPS-RPWM_Last = 0x%x, LPS-RPWM_Now = 0x%x!!\n", + coex_dm->pre_rpwm, coex_dm->cur_rpwm); + + return; + } + } + halbtc8821a1ant_set_lps_rpwm(btcoexist, lps_val, rpwm_val); + + coex_dm->pre_lps = coex_dm->cur_lps; + coex_dm->pre_rpwm = coex_dm->cur_rpwm; +} + +static void halbtc8821a1ant_sw_mechanism(struct btc_coexist *btcoexist, + bool low_penalty_ra) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], SM[LpRA] = %d\n", low_penalty_ra); + + halbtc8821a1ant_low_penalty_ra(btcoexist, NORMAL_EXEC, low_penalty_ra); +} + +static void halbtc8821a1ant_set_ant_path(struct btc_coexist *btcoexist, + u8 ant_pos_type, bool init_hw_cfg, + bool wifi_off) +{ + struct btc_board_info *board_info = &btcoexist->board_info; + u32 u4_tmp = 0; + u8 h2c_parameter[2] = {0}; + + if (init_hw_cfg) { + /* 0x4c[23] = 0, 0x4c[24] = 1 Antenna control by WL/BT*/ + u4_tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); + u4_tmp &= ~BIT23; + u4_tmp |= BIT24; + btcoexist->btc_write_4byte(btcoexist, 0x4c, u4_tmp); + + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x975, 0x3, 0x3); + btcoexist->btc_write_1byte(btcoexist, 0xcb4, 0x77); + + if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) { + /*tell firmware "antenna inverse" ==> + * WRONG firmware antenna control code.==>need fw to fix + */ + h2c_parameter[0] = 1; + h2c_parameter[1] = 1; + btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, + h2c_parameter); + /*Main Ant to BT for IPS case 0x4c[23] = 1*/ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x64, + 0x1, 0x1); + } else { + /*tell firmware "no antenna inverse" ==> + * WRONG firmware antenna control code.==>need fw to fix + */ + h2c_parameter[0] = 0; + h2c_parameter[1] = 1; + btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, + h2c_parameter); + /*Aux Ant to BT for IPS case 0x4c[23] = 1*/ + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x64, + 0x1, 0x0); + } + } else if (wifi_off) { + /* 0x4c[24:23] = 00, Set Antenna control + * by BT_RFE_CTRL BT Vendor 0xac = 0xf002 + */ + u4_tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); + u4_tmp &= ~BIT23; + u4_tmp &= ~BIT24; + btcoexist->btc_write_4byte(btcoexist, 0x4c, u4_tmp); + } + + /* ext switch setting*/ + switch (ant_pos_type) { + case BTC_ANT_PATH_WIFI: + if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) + btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, + 0x30, 0x1); + else + btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, + 0x30, 0x2); + break; + case BTC_ANT_PATH_BT: + if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) + btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, + 0x30, 0x2); + else + btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, + 0x30, 0x1); + break; + default: + case BTC_ANT_PATH_PTA: + if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) + btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, + 0x30, 0x1); + else + btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, + 0x30, 0x2); + break; + } +} + +static void halbtc8821a1ant_ps_tdma(struct btc_coexist *btcoexist, + bool force_exec, bool turn_on, u8 type) +{ + u8 rssi_adjust_val = 0; + + coex_dm->cur_ps_tdma_on = turn_on; + coex_dm->cur_ps_tdma = type; + + if (!force_exec) { + if (coex_dm->cur_ps_tdma_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], ********** TDMA(on, %d) **********\n", + coex_dm->cur_ps_tdma); + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], ********** TDMA(off, %d) **********\n", + coex_dm->cur_ps_tdma); + } + if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && + (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) + return; + } + if (turn_on) { + switch (type) { + default: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x1a, + 0x1a, 0x0, 0x50); + break; + case 1: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x3a, + 0x03, 0x10, 0x50); + rssi_adjust_val = 11; + break; + case 2: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x2b, + 0x03, 0x10, 0x50); + rssi_adjust_val = 14; + break; + case 3: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x1d, + 0x1d, 0x0, 0x10); + break; + case 4: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x93, 0x15, + 0x3, 0x14, 0x0); + rssi_adjust_val = 17; + break; + case 5: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x61, 0x15, + 0x3, 0x11, 0x10); + break; + case 6: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x13, 0xa, + 0x3, 0x0, 0x0); + break; + case 7: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x13, 0xc, + 0x5, 0x0, 0x0); + break; + case 8: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x93, 0x25, + 0x3, 0x10, 0x0); + break; + case 9: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x21, + 0x3, 0x10, 0x50); + rssi_adjust_val = 18; + break; + case 10: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x13, 0xa, + 0xa, 0x0, 0x40); + break; + case 11: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x14, + 0x03, 0x10, 0x10); + rssi_adjust_val = 20; + break; + case 12: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x0a, + 0x0a, 0x0, 0x50); + break; + case 13: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x18, + 0x18, 0x0, 0x10); + break; + case 14: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x21, + 0x3, 0x10, 0x10); + break; + case 15: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x13, 0xa, + 0x3, 0x8, 0x0); + break; + case 16: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x93, 0x15, + 0x3, 0x10, 0x0); + rssi_adjust_val = 18; + break; + case 18: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x93, 0x25, + 0x3, 0x10, 0x0); + rssi_adjust_val = 14; + break; + case 20: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x61, 0x35, + 0x03, 0x11, 0x10); + break; + case 21: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x61, 0x15, + 0x03, 0x11, 0x10); + break; + case 22: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x61, 0x25, + 0x03, 0x11, 0x10); + break; + case 23: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xe3, 0x25, + 0x3, 0x31, 0x18); + rssi_adjust_val = 22; + break; + case 24: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xe3, 0x15, + 0x3, 0x31, 0x18); + rssi_adjust_val = 22; + break; + case 25: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xe3, 0xa, + 0x3, 0x31, 0x18); + rssi_adjust_val = 22; + break; + case 26: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xe3, 0xa, + 0x3, 0x31, 0x18); + rssi_adjust_val = 22; + break; + case 27: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xe3, 0x25, + 0x3, 0x31, 0x98); + rssi_adjust_val = 22; + break; + case 28: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x69, 0x25, + 0x3, 0x31, 0x0); + break; + case 29: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xab, 0x1a, + 0x1a, 0x1, 0x10); + break; + case 30: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x14, + 0x3, 0x10, 0x50); + break; + case 31: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xd3, 0x1a, + 0x1a, 0, 0x58); + break; + case 32: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x61, 0xa, + 0x3, 0x10, 0x0); + break; + case 33: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xa3, 0x25, + 0x3, 0x30, 0x90); + break; + case 34: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x53, 0x1a, + 0x1a, 0x0, 0x10); + break; + case 35: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x63, 0x1a, + 0x1a, 0x0, 0x10); + break; + case 36: + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xd3, 0x12, + 0x3, 0x14, 0x50); + break; + } + } else { + /* disable PS tdma*/ + switch (type) { + case 8: /*PTA Control*/ + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x8, 0x0, 0x0, + 0x0, 0x0); + halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA, + false, false); + break; + case 0: + default: /*Software control, Antenna at BT side*/ + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x0, 0x0, 0x0, + 0x0, 0x0); + halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, + false, false); + break; + case 9: /*Software control, Antenna at WiFi side*/ + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x0, 0x0, 0x0, + 0x0, 0x0); + halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_WIFI, + false, false); + break; + case 10: /* under 5G*/ + halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x0, 0x0, 0x0, + 0x8, 0x0); + halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, + false, false); + break; + } + } + rssi_adjust_val = 0; + btcoexist->btc_set(btcoexist, + BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE, &rssi_adjust_val); + + /* update pre state*/ + coex_dm->pre_ps_tdma_on = coex_dm->cur_ps_tdma_on; + coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; +} + +static bool halbtc8821a1ant_is_common_action(struct btc_coexist *btcoexist) +{ + bool common = false, wifi_connected = false, wifi_busy = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + + if (!wifi_connected && + BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE == + coex_dm->bt_status) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi non connected-idle + BT non connected-idle!!\n"); + halbtc8821a1ant_sw_mechanism(btcoexist, false); + + common = true; + } else if (wifi_connected && + (BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE == + coex_dm->bt_status)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi connected + BT non connected-idle!!\n"); + halbtc8821a1ant_sw_mechanism(btcoexist, false); + + common = true; + } else if (!wifi_connected && + (BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE == + coex_dm->bt_status)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi non connected-idle + BT connected-idle!!\n"); + halbtc8821a1ant_sw_mechanism(btcoexist, false); + + common = true; + } else if (wifi_connected && + (BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE == + coex_dm->bt_status)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi connected + BT connected-idle!!\n"); + halbtc8821a1ant_sw_mechanism(btcoexist, false); + + common = true; + } else if (!wifi_connected && + (BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE != + coex_dm->bt_status)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi non connected-idle + BT Busy!!\n"); + halbtc8821a1ant_sw_mechanism(btcoexist, false); + + common = true; + } else { + if (wifi_busy) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi Connected-Busy + BT Busy!!\n"); + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi Connected-Idle + BT Busy!!\n"); + } + + common = false; + } + + return common; +} + +static void btc8821a1ant_tdma_dur_adj(struct btc_coexist *btcoexist, + u8 wifi_status) +{ + static long up, dn, m, n, wait_count; + /*0: no change, +1: increase WiFi duration, -1: decrease WiFi duration*/ + long result; + u8 retry_count = 0, bt_info_ext; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], TdmaDurationAdjustForAcl()\n"); + + if ((BT_8821A_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN == + wifi_status) || + (BT_8821A_1ANT_WIFI_STATUS_CONNECTED_SCAN == + wifi_status) || + (BT_8821A_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT == + wifi_status)) { + if (coex_dm->cur_ps_tdma != 1 && + coex_dm->cur_ps_tdma != 2 && + coex_dm->cur_ps_tdma != 3 && + coex_dm->cur_ps_tdma != 9) { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + + up = 0; + dn = 0; + m = 1; + n = 3; + result = 0; + wait_count = 0; + } + return; + } + + if (!coex_dm->auto_tdma_adjust) { + coex_dm->auto_tdma_adjust = true; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], first run TdmaDurationAdjust()!!\n"); + + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); + coex_dm->tdma_adj_type = 2; + /*============*/ + up = 0; + dn = 0; + m = 1; + n = 3; + result = 0; + wait_count = 0; + } else { + /*accquire the BT TRx retry count from BT_Info byte2*/ + retry_count = coex_sta->bt_retry_cnt; + bt_info_ext = coex_sta->bt_info_ext; + result = 0; + wait_count++; + + if (retry_count == 0) { + /* no retry in the last 2-second duration*/ + up++; + dn--; + + if (dn <= 0) + dn = 0; + + if (up >= n) { + /* if (retry count == 0) for 2*n seconds , + * make WiFi duration wider + */ + wait_count = 0; + n = 3; + up = 0; + dn = 0; + result = 1; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], Increase wifi duration!!\n"); + } + } else if (retry_count <= 3) { + /* <=3 retry in the last 2-second duration*/ + up--; + dn++; + + if (up <= 0) + up = 0; + + if (dn == 2) { + /* if retry count< 3 for 2*2 seconds, + * shrink wifi duration + */ + if (wait_count <= 2) + m++; /* avoid bounce in two levels */ + else + m = 1; + + if (m >= 20) { + /* m max value is 20, max time is 120 s, + * recheck if adjust WiFi duration. + */ + m = 20; + } + n = 3*m; + up = 0; + dn = 0; + wait_count = 0; + result = -1; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retryCounter<3!!\n"); + } + } else { + /* retry count > 3, if retry count > 3 happens once, + * shrink WiFi duration + */ + if (wait_count == 1) + m++; /* avoid bounce in two levels */ + else + m = 1; + /* m max value is 20, max time is 120 second, + * recheck if adjust WiFi duration. + */ + if (m >= 20) + m = 20; + + n = 3*m; + up = 0; + dn = 0; + wait_count = 0; + result = -1; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retryCounter>3!!\n"); + } + + if (result == -1) { + if ((BT_INFO_8821A_1ANT_A2DP_BASIC_RATE(bt_info_ext)) && + ((coex_dm->cur_ps_tdma == 1) || + (coex_dm->cur_ps_tdma == 2))) { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (coex_dm->cur_ps_tdma == 1) { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (coex_dm->cur_ps_tdma == 9) { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } + } else if (result == 1) { + if ((BT_INFO_8821A_1ANT_A2DP_BASIC_RATE(bt_info_ext)) && + ((coex_dm->cur_ps_tdma == 1) || + (coex_dm->cur_ps_tdma == 2))) { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (coex_dm->cur_ps_tdma == 9) { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 1); + coex_dm->tdma_adj_type = 1; + } + } else { + /*no change*/ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], ********** TDMA(on, %d) **********\n", + coex_dm->cur_ps_tdma); + } + + if (coex_dm->cur_ps_tdma != 1 && + coex_dm->cur_ps_tdma != 2 && + coex_dm->cur_ps_tdma != 9 && + coex_dm->cur_ps_tdma != 11) { + /* recover to previous adjust type*/ + halbtc8821a1ant_ps_tdma(btcoexist, + NORMAL_EXEC, true, + coex_dm->tdma_adj_type); + } + } +} + +static void btc8821a1ant_ps_tdma_check_for_pwr_save(struct btc_coexist *btcoex, + bool new_ps_state) +{ + u8 lps_mode = 0x0; + + btcoex->btc_get(btcoex, BTC_GET_U1_LPS_MODE, &lps_mode); + + if (lps_mode) { + /* already under LPS state*/ + if (new_ps_state) { + /* keep state under LPS, do nothing.*/ + } else { + /* will leave LPS state, turn off psTdma first*/ + halbtc8821a1ant_ps_tdma(btcoex, NORMAL_EXEC, false, 0); + } + } else { + /* NO PS state*/ + if (new_ps_state) { + /* will enter LPS state, turn off psTdma first*/ + halbtc8821a1ant_ps_tdma(btcoex, NORMAL_EXEC, false, 0); + } else { + /* keep state under NO PS state, do nothing.*/ + } + } +} + +static void halbtc8821a1ant_power_save_state(struct btc_coexist *btcoexist, + u8 ps_type, u8 lps_val, + u8 rpwm_val) +{ + bool low_pwr_disable = false; + + switch (ps_type) { + case BTC_PS_WIFI_NATIVE: + /* recover to original 32k low power setting*/ + low_pwr_disable = false; + btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + btcoexist->btc_set(btcoexist, BTC_SET_ACT_NORMAL_LPS, NULL); + break; + case BTC_PS_LPS_ON: + btc8821a1ant_ps_tdma_check_for_pwr_save(btcoexist, + true); + halbtc8821a1ant_lps_rpwm(btcoexist, + NORMAL_EXEC, lps_val, rpwm_val); + /* when coex force to enter LPS, do not enter 32k low power.*/ + low_pwr_disable = true; + btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + /* power save must executed before psTdma.*/ + btcoexist->btc_set(btcoexist, BTC_SET_ACT_ENTER_LPS, NULL); + break; + case BTC_PS_LPS_OFF: + btc8821a1ant_ps_tdma_check_for_pwr_save(btcoexist, false); + btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS, NULL); + break; + default: + break; + } +} + +static void halbtc8821a1ant_coex_under_5g(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + halbtc8821a1ant_ignore_wlan_act(btcoexist, NORMAL_EXEC, true); + + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 10); + + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0); + + halbtc8821a1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); + + halbtc8821a1ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 5); +} + +static void halbtc8821a1ant_action_wifi_only(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0); + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 9); +} + +static void btc8821a1ant_mon_bt_en_dis(struct btc_coexist *btcoexist) +{ + static bool pre_bt_disabled; + static u32 bt_disable_cnt; + bool bt_active = true, bt_disabled = false; + + /* This function check if bt is disabled*/ + + if (coex_sta->high_priority_tx == 0 && + coex_sta->high_priority_rx == 0 && + coex_sta->low_priority_tx == 0 && + coex_sta->low_priority_rx == 0) { + bt_active = false; + } + if (coex_sta->high_priority_tx == 0xffff && + coex_sta->high_priority_rx == 0xffff && + coex_sta->low_priority_tx == 0xffff && + coex_sta->low_priority_rx == 0xffff) { + bt_active = false; + } + if (bt_active) { + bt_disable_cnt = 0; + bt_disabled = false; + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, + &bt_disabled); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], BT is enabled !!\n"); + } else { + bt_disable_cnt++; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], bt all counters = 0, %d times!!\n", + bt_disable_cnt); + if (bt_disable_cnt >= 2) { + bt_disabled = true; + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, + &bt_disabled); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], BT is disabled !!\n"); + halbtc8821a1ant_action_wifi_only(btcoexist); + } + } + if (pre_bt_disabled != bt_disabled) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], BT is from %s to %s!!\n", + (pre_bt_disabled ? "disabled" : "enabled"), + (bt_disabled ? "disabled" : "enabled")); + pre_bt_disabled = bt_disabled; + if (bt_disabled) { + btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS, + NULL); + btcoexist->btc_set(btcoexist, BTC_SET_ACT_NORMAL_LPS, + NULL); + } + } +} + +/*=============================================*/ +/**/ +/* Software Coex Mechanism start*/ +/**/ +/*=============================================*/ + +/* SCO only or SCO+PAN(HS)*/ +static void halbtc8821a1ant_action_sco(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_sw_mechanism(btcoexist, true); +} + +static void halbtc8821a1ant_action_hid(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_sw_mechanism(btcoexist, true); +} + +/*A2DP only / PAN(EDR) only/ A2DP+PAN(HS)*/ +static void halbtc8821a1ant_action_a2dp(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_sw_mechanism(btcoexist, false); +} + +static void halbtc8821a1ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_sw_mechanism(btcoexist, false); +} + +static void halbtc8821a1ant_action_pan_edr(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_sw_mechanism(btcoexist, false); +} + +/*PAN(HS) only*/ +static void halbtc8821a1ant_action_pan_hs(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_sw_mechanism(btcoexist, false); +} + +/*PAN(EDR)+A2DP*/ +static void halbtc8821a1ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_sw_mechanism(btcoexist, false); +} + +static void halbtc8821a1ant_action_pan_edr_hid(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_sw_mechanism(btcoexist, true); +} + +/* HID+A2DP+PAN(EDR)*/ +static void btc8821a1ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_sw_mechanism(btcoexist, true); +} + +static void halbtc8821a1ant_action_hid_a2dp(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_sw_mechanism(btcoexist, true); +} + +/*=============================================*/ +/**/ +/* Non-Software Coex Mechanism start*/ +/**/ +/*=============================================*/ + +static void halbtc8821a1ant_action_hs(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); + halbtc8821a1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 2); +} + +static void halbtc8821a1ant_action_bt_inquiry(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool wifi_connected = false; + + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); + + if (!wifi_connected) { + halbtc8821a1ant_power_save_state(btcoexist, + BTC_PS_WIFI_NATIVE, 0x0, 0x0); + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + } else if ((bt_link_info->sco_exist) || + (bt_link_info->hid_only)) { + /* SCO/HID-only busy*/ + halbtc8821a1ant_power_save_state(btcoexist, + BTC_PS_WIFI_NATIVE, 0x0, 0x0); + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32); + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + } else { + halbtc8821a1ant_power_save_state(btcoexist, BTC_PS_LPS_ON, + 0x50, 0x4); + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 30); + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + } +} + +static void btc8821a1ant_act_bt_sco_hid_only_busy(struct btc_coexist *btcoexist, + u8 wifi_status) { + /* tdma and coex table*/ + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); + + if (BT_8821A_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN == + wifi_status) + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + else + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); +} + +static void btc8821a1ant_act_wifi_con_bt_acl_busy(struct btc_coexist *btcoexist, + u8 wifi_status) +{ + u8 bt_rssi_state; + + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + + bt_rssi_state = halbtc8821a1ant_bt_rssi_state(2, 28, 0); + + if (bt_link_info->hid_only) { + /*HID*/ + btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist, + wifi_status); + coex_dm->auto_tdma_adjust = false; + return; + } else if (bt_link_info->a2dp_only) { + /*A2DP*/ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a1ant_tdma_dur_adj(btcoexist, wifi_status); + } else { + /*for low BT RSSI*/ + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->auto_tdma_adjust = false; + } + + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + } else if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) { + /*HID+A2DP*/ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->auto_tdma_adjust = false; + } else { + /*for low BT RSSI*/ + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->auto_tdma_adjust = false; + } + + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + } else if ((bt_link_info->pan_only) || + (bt_link_info->hid_exist && bt_link_info->pan_exist)) { + /*PAN(OPP, FTP), HID+PAN(OPP, FTP)*/ + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + coex_dm->auto_tdma_adjust = false; + } else if (((bt_link_info->a2dp_exist) && (bt_link_info->pan_exist)) || + (bt_link_info->hid_exist && bt_link_info->a2dp_exist && + bt_link_info->pan_exist)) { + /*A2DP+PAN(OPP, FTP), HID+A2DP+PAN(OPP, FTP)*/ + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13); + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + coex_dm->auto_tdma_adjust = false; + } else { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + coex_dm->auto_tdma_adjust = false; + } +} + +static void halbtc8821a1ant_action_wifi_not_connected( + struct btc_coexist *btcoexist) +{ + /* power save state*/ + halbtc8821a1ant_power_save_state(btcoexist, + BTC_PS_WIFI_NATIVE, 0x0, 0x0); + + /* tdma and coex table*/ + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0); +} + +static void btc8821a1ant_act_wifi_not_conn_scan(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_power_save_state(btcoexist, + BTC_PS_WIFI_NATIVE, 0x0, 0x0); + + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 22); + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); +} + +static void halbtc8821a1ant_action_wifi_connected_scan( + struct btc_coexist *btcoexist) { + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + + /* power save state*/ + halbtc8821a1ant_power_save_state(btcoexist, + BTC_PS_WIFI_NATIVE, 0x0, 0x0); + + /* tdma and coex table*/ + if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { + if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 22); + halbtc8821a1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 1); + } else { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20); + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + } + } else if ((BT_8821A_1ANT_BT_STATUS_SCO_BUSY == + coex_dm->bt_status) || + (BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY == + coex_dm->bt_status)) { + btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist, + BT_8821A_1ANT_WIFI_STATUS_CONNECTED_SCAN); + } else { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20); + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + } +} + +static void btc8821a1ant_act_wifi_conn_sp_pkt(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool hs_connecting = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_CONNECTING, &hs_connecting); + + halbtc8821a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + + /* tdma and coex table*/ + if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { + if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 22); + halbtc8821a1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 1); + } else { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 20); + halbtc8821a1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 1); + } + } else { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20); + halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); + } +} + +static void halbtc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist) +{ + bool wifi_busy = false; + bool scan = false, link = false, roam = false; + bool under_4way = false; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], CoexForWifiConnect()===>\n"); + + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_4_WAY_PROGRESS, &under_4way); + if (under_4way) { + btc8821a1ant_act_wifi_conn_sp_pkt(btcoexist); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], CoexForWifiConnect(), return for wifi is under 4way<===\n"); + return; + } + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); + if (scan || link || roam) { + halbtc8821a1ant_action_wifi_connected_scan(btcoexist); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n"); + return; + } + + /* power save state*/ + if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == + coex_dm->bt_status && !btcoexist->bt_link_info.hid_only) + halbtc8821a1ant_power_save_state(btcoexist, + BTC_PS_LPS_ON, 0x50, 0x4); + else + halbtc8821a1ant_power_save_state(btcoexist, + BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + + /* tdma and coex table*/ + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + if (!wifi_busy) { + if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { + btc8821a1ant_act_wifi_con_bt_acl_busy(btcoexist, + BT_8821A_1ANT_WIFI_STATUS_CONNECTED_IDLE); + } else if ((BT_8821A_1ANT_BT_STATUS_SCO_BUSY == + coex_dm->bt_status) || + (BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY == + coex_dm->bt_status)) { + btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist, + BT_8821A_1ANT_WIFI_STATUS_CONNECTED_IDLE); + } else { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + halbtc8821a1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 2); + } + } else { + if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { + btc8821a1ant_act_wifi_con_bt_acl_busy(btcoexist, + BT_8821A_1ANT_WIFI_STATUS_CONNECTED_BUSY); + } else if ((BT_8821A_1ANT_BT_STATUS_SCO_BUSY == + coex_dm->bt_status) || + (BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY == + coex_dm->bt_status)) { + btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist, + BT_8821A_1ANT_WIFI_STATUS_CONNECTED_BUSY); + } else { + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + halbtc8821a1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 2); + } + } +} + +static void btc8821a1ant_run_sw_coex_mech(struct btc_coexist *btcoexist) +{ + u8 algorithm = 0; + + algorithm = halbtc8821a1ant_action_algorithm(btcoexist); + coex_dm->cur_algorithm = algorithm; + + if (!halbtc8821a1ant_is_common_action(btcoexist)) { + switch (coex_dm->cur_algorithm) { + case BT_8821A_1ANT_COEX_ALGO_SCO: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = SCO.\n"); + halbtc8821a1ant_action_sco(btcoexist); + break; + case BT_8821A_1ANT_COEX_ALGO_HID: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = HID.\n"); + halbtc8821a1ant_action_hid(btcoexist); + break; + case BT_8821A_1ANT_COEX_ALGO_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = A2DP.\n"); + halbtc8821a1ant_action_a2dp(btcoexist); + break; + case BT_8821A_1ANT_COEX_ALGO_A2DP_PANHS: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = A2DP+PAN(HS).\n"); + halbtc8821a1ant_action_a2dp_pan_hs(btcoexist); + break; + case BT_8821A_1ANT_COEX_ALGO_PANEDR: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = PAN(EDR).\n"); + halbtc8821a1ant_action_pan_edr(btcoexist); + break; + case BT_8821A_1ANT_COEX_ALGO_PANHS: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = HS mode.\n"); + halbtc8821a1ant_action_pan_hs(btcoexist); + break; + case BT_8821A_1ANT_COEX_ALGO_PANEDR_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = PAN+A2DP.\n"); + halbtc8821a1ant_action_pan_edr_a2dp(btcoexist); + break; + case BT_8821A_1ANT_COEX_ALGO_PANEDR_HID: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = PAN(EDR)+HID.\n"); + halbtc8821a1ant_action_pan_edr_hid(btcoexist); + break; + case BT_8821A_1ANT_COEX_ALGO_HID_A2DP_PANEDR: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = HID+A2DP+PAN.\n"); + btc8821a1ant_action_hid_a2dp_pan_edr(btcoexist); + break; + case BT_8821A_1ANT_COEX_ALGO_HID_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = HID+A2DP.\n"); + halbtc8821a1ant_action_hid_a2dp(btcoexist); + break; + default: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action algorithm = coexist All Off!!\n"); + /*halbtc8821a1ant_coex_all_off(btcoexist);*/ + break; + } + coex_dm->pre_algorithm = coex_dm->cur_algorithm; + } +} + +static void halbtc8821a1ant_run_coexist_mechanism(struct btc_coexist *btcoexist) +{ + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + bool wifi_connected = false, bt_hs_on = false; + bool increase_scan_dev_num = false; + bool bt_ctrl_agg_buf_size = false; + u8 agg_buf_size = 5; + u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH; + bool wifi_under_5g = false; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], RunCoexistMechanism()===>\n"); + + if (btcoexist->manual_control) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n"); + return; + } + + if (btcoexist->stop_coex_dm) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), return for Stop Coex DM <===\n"); + return; + } + + if (coex_sta->under_ips) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], wifi is under IPS !!!\n"); + return; + } + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); + if (wifi_under_5g) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), return for 5G <===\n"); + halbtc8821a1ant_coex_under_5g(btcoexist); + return; + } + + if ((BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || + (BT_8821A_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || + (BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) + increase_scan_dev_num = true; + + btcoexist->btc_set(btcoexist, BTC_SET_BL_INC_SCAN_DEV_NUM, + &increase_scan_dev_num); + + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); + + if (!bt_link_info->sco_exist && !bt_link_info->hid_exist) { + halbtc8821a1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); + } else { + if (wifi_connected) { + wifi_rssi_state = + halbtc8821a1ant_WifiRssiState(btcoexist, 1, 2, + 30, 0); + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a1ant_limited_tx(btcoexist, + NORMAL_EXEC, 1, 1, + 1, 1); + } else { + halbtc8821a1ant_limited_tx(btcoexist, + NORMAL_EXEC, 1, 1, + 1, 1); + } + } else { + halbtc8821a1ant_limited_tx(btcoexist, NORMAL_EXEC, + 0, 0, 0, 0); + } + } + + if (bt_link_info->sco_exist) { + bt_ctrl_agg_buf_size = true; + agg_buf_size = 0x3; + } else if (bt_link_info->hid_exist) { + bt_ctrl_agg_buf_size = true; + agg_buf_size = 0x5; + } else if (bt_link_info->a2dp_exist || bt_link_info->pan_exist) { + bt_ctrl_agg_buf_size = true; + agg_buf_size = 0x8; + } + halbtc8821a1ant_limited_rx(btcoexist, NORMAL_EXEC, false, + bt_ctrl_agg_buf_size, agg_buf_size); + + btc8821a1ant_run_sw_coex_mech(btcoexist); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + if (coex_sta->c2h_bt_inquiry_page) { + halbtc8821a1ant_action_bt_inquiry(btcoexist); + return; + } else if (bt_hs_on) { + halbtc8821a1ant_action_hs(btcoexist); + return; + } + + if (!wifi_connected) { + bool scan = false, link = false, roam = false; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], wifi is non connected-idle !!!\n"); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); + + if (scan || link || roam) + btc8821a1ant_act_wifi_not_conn_scan(btcoexist); + else + halbtc8821a1ant_action_wifi_not_connected(btcoexist); + } else { + /* wifi LPS/Busy*/ + halbtc8821a1ant_action_wifi_connected(btcoexist); + } +} + +static void halbtc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist) +{ + /* force to reset coex mechanism*/ + /* sw all off*/ + halbtc8821a1ant_sw_mechanism(btcoexist, false); + + halbtc8821a1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8); + halbtc8821a1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0); +} + +static void halbtc8821a1ant_init_hw_config(struct btc_coexist *btcoexist, + bool back_up) +{ + u8 u1_tmp = 0; + bool wifi_under_5g = false; + + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], 1Ant Init HW Config!!\n"); + + if (back_up) { + coex_dm->backup_arfr_cnt1 = btcoexist->btc_read_4byte(btcoexist, + 0x430); + coex_dm->backup_arfr_cnt2 = btcoexist->btc_read_4byte(btcoexist, + 0x434); + coex_dm->backup_retry_limit = + btcoexist->btc_read_2byte(btcoexist, 0x42a); + coex_dm->backup_ampdu_max_time = + btcoexist->btc_read_1byte(btcoexist, 0x456); + } + + /* 0x790[5:0] = 0x5*/ + u1_tmp = btcoexist->btc_read_1byte(btcoexist, 0x790); + u1_tmp &= 0xc0; + u1_tmp |= 0x5; + btcoexist->btc_write_1byte(btcoexist, 0x790, u1_tmp); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); + + /*Antenna config*/ + if (wifi_under_5g) + halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, + true, false); + else + halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA, + true, false); + /* PTA parameter*/ + halbtc8821a1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0); + + /* Enable counter statistics*/ + /*0x76e[3] =1, WLAN_Act control by PTA*/ + btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); + btcoexist->btc_write_1byte(btcoexist, 0x778, 0x3); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1); +} + +/*============================================================*/ +/* work around function start with wa_halbtc8821a1ant_*/ +/*============================================================*/ +/*============================================================*/ +/* extern function start with EXhalbtc8821a1ant_*/ +/*============================================================*/ +void ex_halbtc8821a1ant_init_hwconfig(struct btc_coexist *btcoexist) +{ + halbtc8821a1ant_init_hw_config(btcoexist, true); +} + +void ex_halbtc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist) +{ + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], Coex Mechanism Init!!\n"); + + btcoexist->stop_coex_dm = false; + + halbtc8821a1ant_init_coex_dm(btcoexist); + + halbtc8821a1ant_query_bt_info(btcoexist); +} + +void ex_halbtc8821a1ant_display_coex_info(struct btc_coexist *btcoexist) +{ + struct btc_board_info *board_info = &btcoexist->board_info; + struct btc_stack_info *stack_info = &btcoexist->stack_info; + struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; + struct rtl_priv *rtlpriv = btcoexist->adapter; + u8 u1_tmp[4], i, bt_info_ext, ps_tdma_case = 0; + u16 u2_tmp[4]; + u32 u4_tmp[4]; + bool roam = false, scan = false, link = false, wifi_under_5g = false; + bool bt_hs_on = false, wifi_busy = false; + long wifi_rssi = 0, bt_hs_rssi = 0; + u32 wifi_bw, wifi_traffic_dir; + u8 wifi_dot11_chnl, wifi_hs_chnl; + u32 fw_ver = 0, bt_patch_ver = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n ============[BT Coexist info]============"); + + if (btcoexist->manual_control) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n ============[Under Manual Control]============"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n =========================================="); + } + if (btcoexist->stop_coex_dm) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n ============[Coex is STOPPED]============"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n =========================================="); + } + + if (!board_info->bt_exist) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n BT not exists !!!"); + return; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d/ %d/ %d", + "Ant PG Num/ Ant Mech/ Ant Pos:", + board_info->pg_ant_num, + board_info->btdm_ant_num, + board_info->btdm_ant_pos); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", + ((stack_info->profile_notified) ? "Yes" : "No"), + stack_info->hci_version); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, + &bt_patch_ver); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d_%x/ 0x%x/ 0x%x(%d)", + "CoexVer/ FwVer/ PatchVer", + glcoex_ver_date_8821a_1ant, + glcoex_ver_8821a_1ant, + fw_ver, bt_patch_ver, + bt_patch_ver); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, + &bt_hs_on); + btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_DOT11_CHNL, + &wifi_dot11_chnl); + btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_HS_CHNL, + &wifi_hs_chnl); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d / %d(%d)", + "Dot11 channel / HsChnl(HsMode)", + wifi_dot11_chnl, wifi_hs_chnl, bt_hs_on); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %02x %02x %02x ", + "H2C Wifi inform bt chnl Info", + coex_dm->wifi_chnl_info[0], coex_dm->wifi_chnl_info[1], + coex_dm->wifi_chnl_info[2]); + + btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); + btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d/ %d", "Wifi rssi/ HS rssi", + (int)wifi_rssi, (int)bt_hs_rssi); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d/ %d/ %d ", "Wifi link/ roam/ scan", + link, roam, scan); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, + &wifi_under_5g); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, + &wifi_bw); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, + &wifi_busy); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, + &wifi_traffic_dir); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %s / %s/ %s ", "Wifi status", + (wifi_under_5g ? "5G" : "2.4G"), + ((BTC_WIFI_BW_LEGACY == wifi_bw) ? "Legacy" : + (((BTC_WIFI_BW_HT40 == wifi_bw) ? "HT40" : "HT20"))), + ((!wifi_busy) ? "idle" : + ((BTC_WIFI_TRAFFIC_TX == wifi_traffic_dir) ? + "uplink" : "downlink"))); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = [%s/ %d/ %d] ", "BT [status/ rssi/ retryCnt]", + ((btcoexist->bt_info.bt_disabled) ? ("disabled") : + ((coex_sta->c2h_bt_inquiry_page) ? ("inquiry/page scan") : + ((BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE == + coex_dm->bt_status) ? + "non-connected idle" : + ((BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE == + coex_dm->bt_status) ? + "connected-idle" : "busy")))), + coex_sta->bt_rssi, coex_sta->bt_retry_cnt); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP", + bt_link_info->sco_exist, + bt_link_info->hid_exist, + bt_link_info->pan_exist, + bt_link_info->a2dp_exist); + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_BT_LINK_INFO); + + bt_info_ext = coex_sta->bt_info_ext; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %s", + "BT Info A2DP rate", + (bt_info_ext&BIT0) ? + "Basic rate" : "EDR rate"); + + for (i = 0; i < BT_INFO_SRC_8821A_1ANT_MAX; i++) { + if (coex_sta->bt_info_c2h_cnt[i]) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)", + glbt_info_src_8821a_1ant[i], + coex_sta->bt_info_c2h[i][0], + coex_sta->bt_info_c2h[i][1], + coex_sta->bt_info_c2h[i][2], + coex_sta->bt_info_c2h[i][3], + coex_sta->bt_info_c2h[i][4], + coex_sta->bt_info_c2h[i][5], + coex_sta->bt_info_c2h[i][6], + coex_sta->bt_info_c2h_cnt[i]); + } + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %s/%s, (0x%x/0x%x)", + "PS state, IPS/LPS, (lps/rpwm)", + ((coex_sta->under_ips ? "IPS ON" : "IPS OFF")), + ((coex_sta->under_Lps ? "LPS ON" : "LPS OFF")), + btcoexist->bt_info.lps_val, + btcoexist->bt_info.rpwm_val); + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD); + + if (!btcoexist->manual_control) { + /* Sw mechanism*/ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s", "============[Sw mechanism]============"); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d", "SM[LowPenaltyRA]", + coex_dm->cur_low_penalty_ra); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %s/ %s/ %d ", + "DelBA/ BtCtrlAgg/ AggSize", + (btcoexist->bt_info.reject_agg_pkt ? "Yes" : "No"), + (btcoexist->bt_info.bt_ctrl_buf_size ? "Yes" : "No"), + btcoexist->bt_info.agg_buf_size); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x ", "Rate Mask", + btcoexist->bt_info.ra_mask); + + /* Fw mechanism*/ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", + "============[Fw mechanism]============"); + + ps_tdma_case = coex_dm->cur_ps_tdma; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", + "PS TDMA", + coex_dm->ps_tdma_para[0], + coex_dm->ps_tdma_para[1], + coex_dm->ps_tdma_para[2], + coex_dm->ps_tdma_para[3], + coex_dm->ps_tdma_para[4], + ps_tdma_case, + coex_dm->auto_tdma_adjust); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x ", + "Latest error condition(should be 0)", + coex_dm->error_condition); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d ", "IgnWlanAct", + coex_dm->cur_ignore_wlan_act); + } + + /* Hw setting*/ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s", "============[Hw setting]============"); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", + "backup ARFR1/ARFR2/RL/AMaxTime", + coex_dm->backup_arfr_cnt1, + coex_dm->backup_arfr_cnt2, + coex_dm->backup_retry_limit, + coex_dm->backup_ampdu_max_time); + + u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x430); + u4_tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x434); + u2_tmp[0] = btcoexist->btc_read_2byte(btcoexist, 0x42a); + u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x456); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", + "0x430/0x434/0x42a/0x456", + u4_tmp[0], u4_tmp[1], u2_tmp[0], u1_tmp[0]); + + u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x778); + u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc58); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x/ 0x%x", "0x778/ 0xc58[29:25]", + u1_tmp[0], (u4_tmp[0]&0x3e000000) >> 25); + + u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x8db); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x", "0x8db[6:5]", + ((u1_tmp[0]&0x60)>>5)); + + u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x975); + u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xcb4); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "0xcb4[29:28]/0xcb4[7:0]/0x974[9:8]", + (u4_tmp[0] & 0x30000000)>>28, + u4_tmp[0] & 0xff, + u1_tmp[0] & 0x3); + + u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x40); + u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x4c); + u1_tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x64); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "0x40/0x4c[24:23]/0x64[0]", + u1_tmp[0], ((u4_tmp[0]&0x01800000)>>23), u1_tmp[1]&0x1); + + u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x550); + u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x522); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x/ 0x%x", "0x550(bcn ctrl)/0x522", + u4_tmp[0], u1_tmp[0]); + + u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc50); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x", "0xc50(dig)", + u4_tmp[0]&0xff); + + u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xf48); + u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xa5d); + u1_tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xa5c); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x/ 0x%x", "OFDM-FA/ CCK-FA", + u4_tmp[0], (u1_tmp[0]<<8) + u1_tmp[1]); + + u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6c0); + u4_tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x6c4); + u4_tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x6c8); + u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x6cc); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", + "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)", + u4_tmp[0], u4_tmp[1], u4_tmp[2], u1_tmp[0]); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d/ %d", "0x770(high-pri rx/tx)", + coex_sta->high_priority_rx, coex_sta->high_priority_tx); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d/ %d", "0x774(low-pri rx/tx)", + coex_sta->low_priority_rx, coex_sta->low_priority_tx); +#if (BT_AUTO_REPORT_ONLY_8821A_1ANT == 1) + halbtc8821a1ant_monitor_bt_ctr(btcoexist); +#endif + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS); +} + +void ex_halbtc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (btcoexist->manual_control || btcoexist->stop_coex_dm) + return; + + if (BTC_IPS_ENTER == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], IPS ENTER notify\n"); + coex_sta->under_ips = true; + halbtc8821a1ant_set_ant_path(btcoexist, + BTC_ANT_PATH_BT, false, true); + /*set PTA control*/ + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); + halbtc8821a1ant_coex_table_with_type(btcoexist, + NORMAL_EXEC, 0); + } else if (BTC_IPS_LEAVE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], IPS LEAVE notify\n"); + coex_sta->under_ips = false; + + halbtc8821a1ant_run_coexist_mechanism(btcoexist); + } +} + +void ex_halbtc8821a1ant_lps_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (btcoexist->manual_control || btcoexist->stop_coex_dm) + return; + + if (BTC_LPS_ENABLE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], LPS ENABLE notify\n"); + coex_sta->under_Lps = true; + } else if (BTC_LPS_DISABLE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], LPS DISABLE notify\n"); + coex_sta->under_Lps = false; + } +} + +void ex_halbtc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type) +{ + bool wifi_connected = false, bt_hs_on = false; + + if (btcoexist->manual_control || + btcoexist->stop_coex_dm || + btcoexist->bt_info.bt_disabled) + return; + + btcoexist->btc_get(btcoexist, + BTC_GET_BL_HS_OPERATION, &bt_hs_on); + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); + + halbtc8821a1ant_query_bt_info(btcoexist); + + if (coex_sta->c2h_bt_inquiry_page) { + halbtc8821a1ant_action_bt_inquiry(btcoexist); + return; + } else if (bt_hs_on) { + halbtc8821a1ant_action_hs(btcoexist); + return; + } + + if (BTC_SCAN_START == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], SCAN START notify\n"); + if (!wifi_connected) { + /* non-connected scan*/ + btc8821a1ant_act_wifi_not_conn_scan(btcoexist); + } else { + /* wifi is connected*/ + halbtc8821a1ant_action_wifi_connected_scan(btcoexist); + } + } else if (BTC_SCAN_FINISH == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], SCAN FINISH notify\n"); + if (!wifi_connected) { + /* non-connected scan*/ + halbtc8821a1ant_action_wifi_not_connected(btcoexist); + } else { + halbtc8821a1ant_action_wifi_connected(btcoexist); + } + } +} + +void ex_halbtc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type) +{ + bool wifi_connected = false, bt_hs_on = false; + + if (btcoexist->manual_control || + btcoexist->stop_coex_dm || + btcoexist->bt_info.bt_disabled) + return; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + if (coex_sta->c2h_bt_inquiry_page) { + halbtc8821a1ant_action_bt_inquiry(btcoexist); + return; + } else if (bt_hs_on) { + halbtc8821a1ant_action_hs(btcoexist); + return; + } + + if (BTC_ASSOCIATE_START == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], CONNECT START notify\n"); + btc8821a1ant_act_wifi_not_conn_scan(btcoexist); + } else if (BTC_ASSOCIATE_FINISH == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], CONNECT FINISH notify\n"); + + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); + if (!wifi_connected) { + /* non-connected scan*/ + halbtc8821a1ant_action_wifi_not_connected(btcoexist); + } else { + halbtc8821a1ant_action_wifi_connected(btcoexist); + } + } +} + +void ex_halbtc8821a1ant_media_status_notify(struct btc_coexist *btcoexist, + u8 type) +{ + u8 h2c_parameter[3] = {0}; + u32 wifi_bw; + u8 wifi_central_chnl; + + if (btcoexist->manual_control || + btcoexist->stop_coex_dm || + btcoexist->bt_info.bt_disabled) + return; + + if (BTC_MEDIA_CONNECT == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], MEDIA connect notify\n"); + } else { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], MEDIA disconnect notify\n"); + } + + /* only 2.4G we need to inform bt the chnl mask*/ + btcoexist->btc_get(btcoexist, + BTC_GET_U1_WIFI_CENTRAL_CHNL, + &wifi_central_chnl); + if ((BTC_MEDIA_CONNECT == type) && + (wifi_central_chnl <= 14)) { + /*h2c_parameter[0] = 0x1;*/ + h2c_parameter[0] = 0x0; + h2c_parameter[1] = wifi_central_chnl; + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) + h2c_parameter[2] = 0x30; + else + h2c_parameter[2] = 0x20; + } + + coex_dm->wifi_chnl_info[0] = h2c_parameter[0]; + coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; + coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x66 = 0x%x\n", + h2c_parameter[0]<<16|h2c_parameter[1]<<8|h2c_parameter[2]); + + btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); +} + +void ex_halbtc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist, + u8 type) +{ + bool bt_hs_on = false; + + if (btcoexist->manual_control || + btcoexist->stop_coex_dm || + btcoexist->bt_info.bt_disabled) + return; + + coex_sta->special_pkt_period_cnt = 0; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + if (coex_sta->c2h_bt_inquiry_page) { + halbtc8821a1ant_action_bt_inquiry(btcoexist); + return; + } else if (bt_hs_on) { + halbtc8821a1ant_action_hs(btcoexist); + return; + } + + if (BTC_PACKET_DHCP == type || + BTC_PACKET_EAPOL == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], special Packet(%d) notify\n", type); + btc8821a1ant_act_wifi_conn_sp_pkt(btcoexist); + } +} + +void ex_halbtc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist, + u8 *tmp_buf, u8 length) +{ + u8 bt_info = 0; + u8 i, rsp_source = 0; + bool wifi_connected = false; + bool bt_busy = false; + bool wifi_under_5g = false; + + coex_sta->c2h_bt_info_req_sent = false; + + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); + + rsp_source = tmp_buf[0]&0xf; + if (rsp_source >= BT_INFO_SRC_8821A_1ANT_MAX) + rsp_source = BT_INFO_SRC_8821A_1ANT_WIFI_FW; + coex_sta->bt_info_c2h_cnt[rsp_source]++; + + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], Bt info[%d], length = %d, hex data = [", + rsp_source, length); + for (i = 0; i < length; i++) { + coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i]; + if (i == 1) + bt_info = tmp_buf[i]; + if (i == length-1) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "0x%02x]\n", tmp_buf[i]); + } else { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "0x%02x, ", tmp_buf[i]); + } + } + + if (BT_INFO_SRC_8821A_1ANT_WIFI_FW != rsp_source) { + coex_sta->bt_retry_cnt = /* [3:0]*/ + coex_sta->bt_info_c2h[rsp_source][2]&0xf; + + coex_sta->bt_rssi = + coex_sta->bt_info_c2h[rsp_source][3]*2+10; + + coex_sta->bt_info_ext = + coex_sta->bt_info_c2h[rsp_source][4]; + + /* Here we need to resend some wifi info to BT*/ + /* because bt is reset and loss of the info.*/ + if (coex_sta->bt_info_ext & BIT1) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n"); + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + if (wifi_connected) { + ex_halbtc8821a1ant_media_status_notify(btcoexist, + BTC_MEDIA_CONNECT); + } else { + ex_halbtc8821a1ant_media_status_notify(btcoexist, + BTC_MEDIA_DISCONNECT); + } + } + + if ((coex_sta->bt_info_ext & BIT3) && !wifi_under_5g) { + if (!btcoexist->manual_control && + !btcoexist->stop_coex_dm) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n"); + halbtc8821a1ant_ignore_wlan_act(btcoexist, + FORCE_EXEC, + false); + } + } +#if (BT_AUTO_REPORT_ONLY_8821A_1ANT == 0) + if (!(coex_sta->bt_info_ext & BIT4)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT ext info bit4 check, set BT to enable Auto Report!!\n"); + halbtc8821a1ant_bt_auto_report(btcoexist, + FORCE_EXEC, true); + } +#endif + } + + /* check BIT2 first ==> check if bt is under inquiry or page scan*/ + if (bt_info & BT_INFO_8821A_1ANT_B_INQ_PAGE) + coex_sta->c2h_bt_inquiry_page = true; + else + coex_sta->c2h_bt_inquiry_page = false; + + /* set link exist status*/ + if (!(bt_info&BT_INFO_8821A_1ANT_B_CONNECTION)) { + coex_sta->bt_link_exist = false; + coex_sta->pan_exist = false; + coex_sta->a2dp_exist = false; + coex_sta->hid_exist = false; + coex_sta->sco_exist = false; + } else { + /* connection exists*/ + coex_sta->bt_link_exist = true; + if (bt_info & BT_INFO_8821A_1ANT_B_FTP) + coex_sta->pan_exist = true; + else + coex_sta->pan_exist = false; + if (bt_info & BT_INFO_8821A_1ANT_B_A2DP) + coex_sta->a2dp_exist = true; + else + coex_sta->a2dp_exist = false; + if (bt_info & BT_INFO_8821A_1ANT_B_HID) + coex_sta->hid_exist = true; + else + coex_sta->hid_exist = false; + if (bt_info & BT_INFO_8821A_1ANT_B_SCO_ESCO) + coex_sta->sco_exist = true; + else + coex_sta->sco_exist = false; + } + + halbtc8821a1ant_update_bt_link_info(btcoexist); + + if (!(bt_info&BT_INFO_8821A_1ANT_B_CONNECTION)) { + coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Non-Connected idle!!!\n"); + } else if (bt_info == BT_INFO_8821A_1ANT_B_CONNECTION) { + /* connection exists but no busy*/ + coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"); + } else if ((bt_info&BT_INFO_8821A_1ANT_B_SCO_ESCO) || + (bt_info&BT_INFO_8821A_1ANT_B_SCO_BUSY)) { + coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_SCO_BUSY; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"); + } else if (bt_info&BT_INFO_8821A_1ANT_B_ACL_BUSY) { + if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY != coex_dm->bt_status) + coex_dm->auto_tdma_adjust = false; + coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_ACL_BUSY; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"); + } else { + coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_MAX; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BtInfoNotify(), BT Non-Defined state!!!\n"); + } + + if ((BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || + (BT_8821A_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || + (BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) + bt_busy = true; + else + bt_busy = false; + btcoexist->btc_set(btcoexist, + BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy); + + halbtc8821a1ant_run_coexist_mechanism(btcoexist); +} + +void ex_halbtc8821a1ant_halt_notify(struct btc_coexist *btcoexist) +{ + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], Halt notify\n"); + + btcoexist->stop_coex_dm = true; + + halbtc8821a1ant_set_ant_path(btcoexist, + BTC_ANT_PATH_BT, false, true); + halbtc8821a1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); + + halbtc8821a1ant_power_save_state(btcoexist, + BTC_PS_WIFI_NATIVE, 0x0, 0x0); + halbtc8821a1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0); + + ex_halbtc8821a1ant_media_status_notify(btcoexist, + BTC_MEDIA_DISCONNECT); +} + +void ex_halbtc8821a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state) +{ + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], Pnp notify\n"); + + if (BTC_WIFI_PNP_SLEEP == pnp_state) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], Pnp notify to SLEEP\n"); + btcoexist->stop_coex_dm = true; + halbtc8821a1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); + halbtc8821a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, + 0x0, 0x0); + halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 9); + } else if (BTC_WIFI_PNP_WAKE_UP == pnp_state) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], Pnp notify to WAKE UP\n"); + btcoexist->stop_coex_dm = false; + halbtc8821a1ant_init_hw_config(btcoexist, false); + halbtc8821a1ant_init_coex_dm(btcoexist); + halbtc8821a1ant_query_bt_info(btcoexist); + } +} + +void +ex_halbtc8821a1ant_periodical( + struct btc_coexist *btcoexist) { + static u8 dis_ver_info_cnt; + u32 fw_ver = 0, bt_patch_ver = 0; + struct btc_board_info *board_info = &btcoexist->board_info; + struct btc_stack_info *stack_info = &btcoexist->stack_info; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], ==========================Periodical===========================\n"); + + if (dis_ver_info_cnt <= 5) { + dis_ver_info_cnt += 1; + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], ****************************************************************\n"); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", + board_info->pg_ant_num, + board_info->btdm_ant_num, + board_info->btdm_ant_pos); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], BT stack/ hci ext ver = %s / %d\n", + ((stack_info->profile_notified) ? "Yes" : "No"), + stack_info->hci_version); + btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, + &bt_patch_ver); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", + glcoex_ver_date_8821a_1ant, + glcoex_ver_8821a_1ant, + fw_ver, bt_patch_ver, + bt_patch_ver); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], ****************************************************************\n"); + } + +#if (BT_AUTO_REPORT_ONLY_8821A_1ANT == 0) + halbtc8821a1ant_query_bt_info(btcoexist); + halbtc8821a1ant_monitor_bt_ctr(btcoexist); + btc8821a1ant_mon_bt_en_dis(btcoexist); +#else + if (halbtc8821a1ant_Is_wifi_status_changed(btcoexist) || + coex_dm->auto_tdma_adjust) { + if (coex_sta->special_pkt_period_cnt > 2) + halbtc8821a1ant_run_coexist_mechanism(btcoexist); + } + + coex_sta->special_pkt_period_cnt++; +#endif +} diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h new file mode 100644 index 000000000000..20e904890fc2 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.h @@ -0,0 +1,188 @@ +/****************************************************************************** + * + * Copyright(c) 2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +/*=========================================== + * The following is for 8821A 1ANT BT Co-exist definition + *=========================================== + */ +#define BT_AUTO_REPORT_ONLY_8821A_1ANT 0 + +#define BT_INFO_8821A_1ANT_B_FTP BIT7 +#define BT_INFO_8821A_1ANT_B_A2DP BIT6 +#define BT_INFO_8821A_1ANT_B_HID BIT5 +#define BT_INFO_8821A_1ANT_B_SCO_BUSY BIT4 +#define BT_INFO_8821A_1ANT_B_ACL_BUSY BIT3 +#define BT_INFO_8821A_1ANT_B_INQ_PAGE BIT2 +#define BT_INFO_8821A_1ANT_B_SCO_ESCO BIT1 +#define BT_INFO_8821A_1ANT_B_CONNECTION BIT0 + +#define BT_INFO_8821A_1ANT_A2DP_BASIC_RATE(_BT_INFO_EXT_) \ + (((_BT_INFO_EXT_&BIT0)) ? true : false) + +#define BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT 2 + +enum _BT_INFO_SRC_8821A_1ANT { + BT_INFO_SRC_8821A_1ANT_WIFI_FW = 0x0, + BT_INFO_SRC_8821A_1ANT_BT_RSP = 0x1, + BT_INFO_SRC_8821A_1ANT_BT_ACTIVE_SEND = 0x2, + BT_INFO_SRC_8821A_1ANT_MAX +}; + +enum _BT_8821A_1ANT_BT_STATUS { + BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0, + BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE = 0x1, + BT_8821A_1ANT_BT_STATUS_INQ_PAGE = 0x2, + BT_8821A_1ANT_BT_STATUS_ACL_BUSY = 0x3, + BT_8821A_1ANT_BT_STATUS_SCO_BUSY = 0x4, + BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY = 0x5, + BT_8821A_1ANT_BT_STATUS_MAX +}; + +enum _BT_8821A_1ANT_WIFI_STATUS { + BT_8821A_1ANT_WIFI_STATUS_NON_CONNECTED_IDLE = 0x0, + BT_8821A_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN = 0x1, + BT_8821A_1ANT_WIFI_STATUS_CONNECTED_SCAN = 0x2, + BT_8821A_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT = 0x3, + BT_8821A_1ANT_WIFI_STATUS_CONNECTED_IDLE = 0x4, + BT_8821A_1ANT_WIFI_STATUS_CONNECTED_BUSY = 0x5, + BT_8821A_1ANT_WIFI_STATUS_MAX +}; + +enum BT_8821A_1ANT_COEX_ALGO { + BT_8821A_1ANT_COEX_ALGO_UNDEFINED = 0x0, + BT_8821A_1ANT_COEX_ALGO_SCO = 0x1, + BT_8821A_1ANT_COEX_ALGO_HID = 0x2, + BT_8821A_1ANT_COEX_ALGO_A2DP = 0x3, + BT_8821A_1ANT_COEX_ALGO_A2DP_PANHS = 0x4, + BT_8821A_1ANT_COEX_ALGO_PANEDR = 0x5, + BT_8821A_1ANT_COEX_ALGO_PANHS = 0x6, + BT_8821A_1ANT_COEX_ALGO_PANEDR_A2DP = 0x7, + BT_8821A_1ANT_COEX_ALGO_PANEDR_HID = 0x8, + BT_8821A_1ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x9, + BT_8821A_1ANT_COEX_ALGO_HID_A2DP = 0xa, + BT_8821A_1ANT_COEX_ALGO_MAX = 0xb, +}; + +struct coex_dm_8821a_1ant { + /* fw mechanism */ + bool cur_ignore_wlan_act; + bool pre_ignore_wlan_act; + u8 pre_ps_tdma; + u8 cur_ps_tdma; + u8 ps_tdma_para[5]; + u8 tdma_adj_type; + bool auto_tdma_adjust; + bool pre_ps_tdma_on; + bool cur_ps_tdma_on; + bool pre_bt_auto_report; + bool cur_bt_auto_report; + u8 pre_lps; + u8 cur_lps; + u8 pre_rpwm; + u8 cur_rpwm; + + /* sw mechanism */ + bool pre_low_penalty_ra; + bool cur_low_penalty_ra; + u32 pre_val_0x6c0; + u32 cur_val_0x6c0; + u32 pre_val_0x6c4; + u32 cur_val_0x6c4; + u32 pre_val_0x6c8; + u32 cur_val_0x6c8; + u8 pre_val_0x6cc; + u8 cur_val_0x6cc; + /* Auto Rate Fallback Retry cnt */ + u32 backup_arfr_cnt1; + /* Auto Rate Fallback Retry cnt */ + u32 backup_arfr_cnt2; + u16 backup_retry_limit; + u8 backup_ampdu_max_time; + + /* algorithm related */ + u8 pre_algorithm; + u8 cur_algorithm; + u8 bt_status; + u8 wifi_chnl_info[3]; + + u32 pre_ra_mask; + u32 cur_ra_mask; + u8 pre_arfr_type; + u8 cur_arfr_type; + u8 pre_retry_limit_type; + u8 cur_retry_limit_type; + u8 pre_ampdu_time_type; + u8 cur_ampdu_time_type; + + u8 error_condition; +}; + +struct coex_sta_8821a_1ant { + bool bt_link_exist; + bool sco_exist; + bool a2dp_exist; + bool hid_exist; + bool pan_exist; + + bool under_Lps; + bool under_ips; + u32 special_pkt_period_cnt; + u32 high_priority_tx; + u32 high_priority_rx; + u32 low_priority_tx; + u32 low_priority_rx; + u8 bt_rssi; + u8 pre_bt_rssi_state; + u8 pre_wifi_rssi_state[4]; + bool c2h_bt_info_req_sent; + u8 bt_info_c2h[BT_INFO_SRC_8821A_1ANT_MAX][10]; + u32 bt_info_c2h_cnt[BT_INFO_SRC_8821A_1ANT_MAX]; + bool c2h_bt_inquiry_page; + u8 bt_retry_cnt; + u8 bt_info_ext; +}; + +/*=========================================== + * The following is interface which will notify coex module. + *=========================================== + */ +void ex_halbtc8821a1ant_init_hwconfig(struct btc_coexist *btcoexist); +void ex_halbtc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist); +void ex_halbtc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type); +void ex_halbtc8821a1ant_lps_notify(struct btc_coexist *btcoexist, u8 type); +void ex_halbtc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type); +void ex_halbtc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type); +void ex_halbtc8821a1ant_media_status_notify(struct btc_coexist *btcoexist, + u8 type); +void ex_halbtc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist, + u8 type); +void ex_halbtc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist, + u8 *tmpbuf, u8 length); +void ex_halbtc8821a1ant_halt_notify(struct btc_coexist *btcoexist); +void ex_halbtc8821a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate); +void ex_halbtc8821a1ant_periodical(struct btc_coexist *btcoexist); +void ex_halbtc8821a1ant_display_coex_info(struct btc_coexist *btcoexist); +void ex_halbtc8821a1ant_dbg_control(struct btc_coexist *btcoexist, u8 op_code, + u8 op_len, u8 *data); diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c new file mode 100644 index 000000000000..cf819f02ed23 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c @@ -0,0 +1,3879 @@ +/****************************************************************************** + * + * Copyright(c) 2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +/*============================================================ + * Description: + * + * This file is for RTL8821A Co-exist mechanism + * + * History + * 2012/08/22 Cosa first check in. + * 2012/11/14 Cosa Revise for 8821A 2Ant out sourcing. + * + *============================================================ + */ + +/*============================================================ + * include files + *============================================================ +*/ +#include "halbt_precomp.h" +/*============================================================ + * Global variables, these are static variables + *============================================================ + */ +static struct coex_dm_8821a_2ant glcoex_dm_8821a_2ant; +static struct coex_dm_8821a_2ant *coex_dm = &glcoex_dm_8821a_2ant; +static struct coex_sta_8821a_2ant glcoex_sta_8821a_2ant; +static struct coex_sta_8821a_2ant *coex_sta = &glcoex_sta_8821a_2ant; + +static const char *const glbt_info_src_8821a_2ant[] = { + "BT Info[wifi fw]", + "BT Info[bt rsp]", + "BT Info[bt auto report]", +}; + +static u32 glcoex_ver_date_8821a_2ant = 20130618; +static u32 glcoex_ver_8821a_2ant = 0x5050; + +/*============================================================ + * local function proto type if needed + *============================================================ + *============================================================ + * local function start with halbtc8821a2ant_ + *============================================================ + */ +static u8 halbtc8821a2ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, + u8 rssi_thresh1) +{ + long bt_rssi = 0; + u8 bt_rssi_state = coex_sta->pre_bt_rssi_state; + + bt_rssi = coex_sta->bt_rssi; + + if (level_num == 2) { + if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || + (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { + long tmp = rssi_thresh + + BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT; + if (bt_rssi >= tmp) { + bt_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); + } + } else { + if (bt_rssi < rssi_thresh) { + bt_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); + } + } + } else if (level_num == 3) { + if (rssi_thresh > rssi_thresh1) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi thresh error!!\n"); + return coex_sta->pre_bt_rssi_state; + } + + if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || + (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { + if (bt_rssi >= + (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { + bt_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Low\n"); + } + } else if ((coex_sta->pre_bt_rssi_state == + BTC_RSSI_STATE_MEDIUM) || + (coex_sta->pre_bt_rssi_state == + BTC_RSSI_STATE_STAY_MEDIUM)) { + if (bt_rssi >= + (rssi_thresh1 + + BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { + bt_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to High\n"); + } else if (bt_rssi < rssi_thresh) { + bt_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Low\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at Medium\n"); + } + } else { + if (bt_rssi < rssi_thresh1) { + bt_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state switch to Medium\n"); + } else { + bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, + "[BTCoex], BT Rssi state stay at High\n"); + } + } + } + + coex_sta->pre_bt_rssi_state = bt_rssi_state; + + return bt_rssi_state; +} + +static u8 halbtc8821a2ant_wifi_rssi_state(struct btc_coexist *btcoexist, + u8 index, u8 level_num, + u8 rssi_thresh, u8 rssi_thresh1) +{ + long wifi_rssi = 0; + u8 wifi_rssi_state = coex_sta->pre_wifi_rssi_state[index]; + + btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); + + if (level_num == 2) { + if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_LOW) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_LOW)) { + if (wifi_rssi >= + (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { + wifi_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); + } + } else { + if (wifi_rssi < rssi_thresh) { + wifi_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); + } + } + } else if (level_num == 3) { + if (rssi_thresh > rssi_thresh1) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI thresh error!!\n"); + return coex_sta->pre_wifi_rssi_state[index]; + } + + if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_LOW) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_LOW)) { + if (wifi_rssi >= + (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { + wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Low\n"); + } + } else if ((coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_MEDIUM) || + (coex_sta->pre_wifi_rssi_state[index] == + BTC_RSSI_STATE_STAY_MEDIUM)) { + if (wifi_rssi >= (rssi_thresh1 + + BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { + wifi_rssi_state = BTC_RSSI_STATE_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to High\n"); + } else if (wifi_rssi < rssi_thresh) { + wifi_rssi_state = BTC_RSSI_STATE_LOW; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Low\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at Medium\n"); + } + } else { + if (wifi_rssi < rssi_thresh1) { + wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state switch to Medium\n"); + } else { + wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_WIFI_RSSI_STATE, + "[BTCoex], wifi RSSI state stay at High\n"); + } + } + } + coex_sta->pre_wifi_rssi_state[index] = wifi_rssi_state; + + return wifi_rssi_state; +} + +static void btc8821a2ant_mon_bt_en_dis(struct btc_coexist *btcoexist) +{ + static bool pre_bt_disabled; + static u32 bt_disable_cnt; + bool bt_active = true, bt_disabled = false; + + /* This function check if bt is disabled*/ + + if (coex_sta->high_priority_tx == 0 && + coex_sta->high_priority_rx == 0 && + coex_sta->low_priority_tx == 0 && + coex_sta->low_priority_rx == 0) + bt_active = false; + if (coex_sta->high_priority_tx == 0xffff && + coex_sta->high_priority_rx == 0xffff && + coex_sta->low_priority_tx == 0xffff && + coex_sta->low_priority_rx == 0xffff) + bt_active = false; + if (bt_active) { + bt_disable_cnt = 0; + bt_disabled = false; + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, + &bt_disabled); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], BT is enabled !!\n"); + } else { + bt_disable_cnt++; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], bt all counters = 0, %d times!!\n", + bt_disable_cnt); + if (bt_disable_cnt >= 2) { + bt_disabled = true; + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, + &bt_disabled); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], BT is disabled !!\n"); + } + } + if (pre_bt_disabled != bt_disabled) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], BT is from %s to %s!!\n", + (pre_bt_disabled ? "disabled" : "enabled"), + (bt_disabled ? "disabled" : "enabled")); + pre_bt_disabled = bt_disabled; + } +} + +static void halbtc8821a2ant_monitor_bt_ctr(struct btc_coexist *btcoexist) +{ + u32 reg_hp_txrx, reg_lp_txrx, u4tmp; + u32 reg_hp_tx = 0, reg_hp_rx = 0, reg_lp_tx = 0, reg_lp_rx = 0; + + reg_hp_txrx = 0x770; + reg_lp_txrx = 0x774; + + u4tmp = btcoexist->btc_read_4byte(btcoexist, reg_hp_txrx); + reg_hp_tx = u4tmp & MASKLWORD; + reg_hp_rx = (u4tmp & MASKHWORD)>>16; + + u4tmp = btcoexist->btc_read_4byte(btcoexist, reg_lp_txrx); + reg_lp_tx = u4tmp & MASKLWORD; + reg_lp_rx = (u4tmp & MASKHWORD)>>16; + + coex_sta->high_priority_tx = reg_hp_tx; + coex_sta->high_priority_rx = reg_hp_rx; + coex_sta->low_priority_tx = reg_lp_tx; + coex_sta->low_priority_rx = reg_lp_rx; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], High Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", + reg_hp_txrx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, + "[BTCoex], Low Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", + reg_lp_txrx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); + + /* reset counter */ + btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); +} + +static void halbtc8821a2ant_query_bt_info(struct btc_coexist *btcoexist) +{ + u8 h2c_parameter[1] = {0}; + + coex_sta->c2h_bt_info_req_sent = true; + + h2c_parameter[0] |= BIT0; /* trigger */ + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", + h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); +} + +static u8 halbtc8821a2ant_action_algorithm(struct btc_coexist *btcoexist) +{ + struct btc_stack_info *stack_info = &btcoexist->stack_info; + bool bt_hs_on = false; + u8 algorithm = BT_8821A_2ANT_COEX_ALGO_UNDEFINED; + u8 num_of_diff_profile = 0; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + + /*for win-8 stack HID report error*/ + /* sync BTInfo with BT firmware and stack */ + if (!stack_info->hid_exist) + stack_info->hid_exist = coex_sta->hid_exist; + /* when stack HID report error, here we use the info from bt fw. */ + if (!stack_info->bt_link_exist) + stack_info->bt_link_exist = coex_sta->bt_link_exist; + + if (!coex_sta->bt_link_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], No profile exists!!!\n"); + return algorithm; + } + + if (coex_sta->sco_exist) + num_of_diff_profile++; + if (coex_sta->hid_exist) + num_of_diff_profile++; + if (coex_sta->pan_exist) + num_of_diff_profile++; + if (coex_sta->a2dp_exist) + num_of_diff_profile++; + + if (num_of_diff_profile == 1) { + if (coex_sta->sco_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO only\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_SCO; + } else { + if (coex_sta->hid_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], HID only\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_HID; + } else if (coex_sta->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], A2DP only\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_A2DP; + } else if (coex_sta->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], PAN(HS) only\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANHS; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], PAN(EDR) only\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR; + } + } + } + } else if (num_of_diff_profile == 2) { + if (coex_sta->sco_exist) { + if (coex_sta->hid_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + HID\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; + } else if (coex_sta->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + A2DP ==> SCO\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; + } else if (coex_sta->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + PAN(HS)\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_SCO; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + PAN(EDR)\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; + } + } + } else { + if (coex_sta->hid_exist && + coex_sta->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], HID + A2DP\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_HID_A2DP; + } else if (coex_sta->hid_exist && + coex_sta->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], HID + PAN(HS)\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_HID; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], HID + PAN(EDR)\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; + } + } else if (coex_sta->pan_exist && + coex_sta->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], A2DP + PAN(HS)\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_A2DP_PANHS; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], A2DP + PAN(EDR)\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_A2DP; + } + } + } + } else if (num_of_diff_profile == 3) { + if (coex_sta->sco_exist) { + if (coex_sta->hid_exist && + coex_sta->a2dp_exist) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + HID + A2DP ==> HID\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; + } else if (coex_sta->hid_exist && + coex_sta->pan_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + HID + PAN(HS)\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + HID + PAN(EDR)\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; + } + } else if (coex_sta->pan_exist && + coex_sta->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + A2DP + PAN(HS)\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + A2DP + PAN(EDR) ==> HID\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; + } + } + } else { + if (coex_sta->hid_exist && + coex_sta->pan_exist && + coex_sta->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], HID + A2DP + PAN(HS)\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_HID_A2DP; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], HID + A2DP + PAN(EDR)\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_HID_A2DP_PANEDR; + } + } + } + } else if (num_of_diff_profile >= 3) { + if (coex_sta->sco_exist) { + if (coex_sta->hid_exist && + coex_sta->pan_exist && + coex_sta->a2dp_exist) { + if (bt_hs_on) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Error!!! SCO + HID + A2DP + PAN(HS)\n"); + + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); + algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; + } + } + } + } + return algorithm; +} + +static bool halbtc8821a2ant_need_to_dec_bt_pwr(struct btc_coexist *btcoexist) +{ + bool ret = false; + bool bt_hs_on = false, wifi_connected = false; + long bt_hs_rssi = 0; + u8 bt_rssi_state; + + if (!btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on)) + return false; + if (!btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected)) + return false; + if (!btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi)) + return false; + + bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); + + if (wifi_connected) { + if (bt_hs_on) { + if (bt_hs_rssi > 37) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], Need to decrease bt power for HS mode!!\n"); + ret = true; + } + } else { + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], Need to decrease bt power for Wifi is connected!!\n"); + ret = true; + } + } + } + return ret; +} + +static void btc8821a2ant_set_fw_dac_swing_lev(struct btc_coexist *btcoexist, + u8 dac_swing_lvl) +{ + u8 h2c_parameter[1] = {0}; + + /* There are several type of dacswing + * 0x18/ 0x10/ 0xc/ 0x8/ 0x4/ 0x6 + */ + h2c_parameter[0] = dac_swing_lvl; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], Set Dac Swing Level = 0x%x\n", dac_swing_lvl); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x64 = 0x%x\n", h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x64, 1, h2c_parameter); +} + +static void halbtc8821a2ant_set_fw_dec_bt_pwr(struct btc_coexist *btcoexist, + bool dec_bt_pwr) +{ + u8 h2c_parameter[1] = {0}; + + h2c_parameter[0] = 0; + + if (dec_bt_pwr) + h2c_parameter[0] |= BIT1; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], decrease Bt Power : %s, FW write 0x62 = 0x%x\n", + (dec_bt_pwr ? "Yes!!" : "No!!"), h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x62, 1, h2c_parameter); +} + +static void halbtc8821a2ant_dec_bt_pwr(struct btc_coexist *btcoexist, + bool force_exec, bool dec_bt_pwr) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s Dec BT power = %s\n", + (force_exec ? "force to" : ""), + ((dec_bt_pwr) ? "ON" : "OFF")); + coex_dm->cur_dec_bt_pwr = dec_bt_pwr; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_dec_bt_pwr = %d, cur_dec_bt_pwr = %d\n", + coex_dm->pre_dec_bt_pwr, coex_dm->cur_dec_bt_pwr); + + if (coex_dm->pre_dec_bt_pwr == coex_dm->cur_dec_bt_pwr) + return; + } + halbtc8821a2ant_set_fw_dec_bt_pwr(btcoexist, coex_dm->cur_dec_bt_pwr); + + coex_dm->pre_dec_bt_pwr = coex_dm->cur_dec_bt_pwr; +} + +static void btc8821a2ant_set_fw_bt_lna_constr(struct btc_coexist *btcoexist, + bool bt_lna_cons_on) +{ + u8 h2c_parameter[2] = {0}; + + h2c_parameter[0] = 0x3; /* opCode, 0x3 = BT_SET_LNA_CONSTRAIN */ + + if (bt_lna_cons_on) + h2c_parameter[1] |= BIT0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], set BT LNA Constrain: %s, FW write 0x69 = 0x%x\n", + (bt_lna_cons_on ? "ON!!" : "OFF!!"), + h2c_parameter[0]<<8|h2c_parameter[1]); + + btcoexist->btc_fill_h2c(btcoexist, 0x69, 2, h2c_parameter); +} + +static void btc8821a2_set_bt_lna_const(struct btc_coexist *btcoexist, + bool force_exec, bool bt_lna_cons_on) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s BT Constrain = %s\n", + (force_exec ? "force" : ""), + ((bt_lna_cons_on) ? "ON" : "OFF")); + coex_dm->cur_bt_lna_constrain = bt_lna_cons_on; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_bt_lna_constrain = %d,cur_bt_lna_constrain = %d\n", + coex_dm->pre_bt_lna_constrain, + coex_dm->cur_bt_lna_constrain); + + if (coex_dm->pre_bt_lna_constrain == + coex_dm->cur_bt_lna_constrain) + return; + } + btc8821a2ant_set_fw_bt_lna_constr(btcoexist, + coex_dm->cur_bt_lna_constrain); + + coex_dm->pre_bt_lna_constrain = coex_dm->cur_bt_lna_constrain; +} + +static void halbtc8821a2ant_set_fw_bt_psd_mode(struct btc_coexist *btcoexist, + u8 bt_psd_mode) +{ + u8 h2c_parameter[2] = {0}; + + h2c_parameter[0] = 0x2; /* opCode, 0x2 = BT_SET_PSD_MODE */ + + h2c_parameter[1] = bt_psd_mode; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], set BT PSD mode = 0x%x, FW write 0x69 = 0x%x\n", + h2c_parameter[1], + h2c_parameter[0]<<8|h2c_parameter[1]); + + btcoexist->btc_fill_h2c(btcoexist, 0x69, 2, h2c_parameter); +} + +static void halbtc8821a2ant_set_bt_psd_mode(struct btc_coexist *btcoexist, + bool force_exec, u8 bt_psd_mode) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s BT PSD mode = 0x%x\n", + (force_exec ? "force" : ""), bt_psd_mode); + coex_dm->cur_bt_psd_mode = bt_psd_mode; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_bt_psd_mode = 0x%x, cur_bt_psd_mode = 0x%x\n", + coex_dm->pre_bt_psd_mode, coex_dm->cur_bt_psd_mode); + + if (coex_dm->pre_bt_psd_mode == coex_dm->cur_bt_psd_mode) + return; + } + halbtc8821a2ant_set_fw_bt_psd_mode(btcoexist, + coex_dm->cur_bt_psd_mode); + + coex_dm->pre_bt_psd_mode = coex_dm->cur_bt_psd_mode; +} + +static void halbtc8821a2ant_set_bt_auto_report(struct btc_coexist *btcoexist, + bool enable_auto_report) +{ + u8 h2c_parameter[1] = {0}; + + h2c_parameter[0] = 0; + + if (enable_auto_report) + h2c_parameter[0] |= BIT0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], BT FW auto report : %s, FW write 0x68 = 0x%x\n", + (enable_auto_report ? "Enabled!!" : "Disabled!!"), + h2c_parameter[0]); + + btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter); +} + +static void halbtc8821a2ant_bt_auto_report(struct btc_coexist *btcoexist, + bool force_exec, + bool enable_auto_report) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s BT Auto report = %s\n", + (force_exec ? "force to" : ""), + ((enable_auto_report) ? "Enabled" : "Disabled")); + coex_dm->cur_bt_auto_report = enable_auto_report; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_bt_auto_report = %d, cur_bt_auto_report = %d\n", + coex_dm->pre_bt_auto_report, + coex_dm->cur_bt_auto_report); + + if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report) + return; + } + halbtc8821a2ant_set_bt_auto_report(btcoexist, + coex_dm->cur_bt_auto_report); + + coex_dm->pre_bt_auto_report = coex_dm->cur_bt_auto_report; +} + +static void halbtc8821a2ant_fw_dac_swing_lvl(struct btc_coexist *btcoexist, + bool force_exec, + u8 fw_dac_swing_lvl) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s set FW Dac Swing level = %d\n", + (force_exec ? "force to" : ""), fw_dac_swing_lvl); + coex_dm->cur_fw_dac_swing_lvl = fw_dac_swing_lvl; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_fw_dac_swing_lvl = %d, cur_fw_dac_swing_lvl = %d\n", + coex_dm->pre_fw_dac_swing_lvl, + coex_dm->cur_fw_dac_swing_lvl); + + if (coex_dm->pre_fw_dac_swing_lvl == + coex_dm->cur_fw_dac_swing_lvl) + return; + } + + btc8821a2ant_set_fw_dac_swing_lev(btcoexist, + coex_dm->cur_fw_dac_swing_lvl); + + coex_dm->pre_fw_dac_swing_lvl = coex_dm->cur_fw_dac_swing_lvl; +} + +static void btc8821a2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, + bool rx_rf_shrink_on) +{ + if (rx_rf_shrink_on) { + /* Shrink RF Rx LPF corner */ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Shrink RF Rx LPF corner!!\n"); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, + 0xfffff, 0xffffc); + } else { + /* Resume RF Rx LPF corner + * After initialized, we can use coex_dm->bt_rf0x1e_backup + */ + if (btcoexist->initilized) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Resume RF Rx LPF corner!!\n"); + btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, + 0x1e, 0xfffff, + coex_dm->bt_rf0x1e_backup); + } + } +} + +static void halbtc8821a2ant_RfShrink(struct btc_coexist *btcoexist, + bool force_exec, bool rx_rf_shrink_on) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s turn Rx RF Shrink = %s\n", + (force_exec ? "force to" : ""), + ((rx_rf_shrink_on) ? "ON" : "OFF")); + coex_dm->cur_rf_rx_lpf_shrink = rx_rf_shrink_on; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], pre_rf_rx_lpf_shrink = %d, cur_rf_rx_lpf_shrink = %d\n", + coex_dm->pre_rf_rx_lpf_shrink, + coex_dm->cur_rf_rx_lpf_shrink); + + if (coex_dm->pre_rf_rx_lpf_shrink == + coex_dm->cur_rf_rx_lpf_shrink) + return; + } + btc8821a2ant_set_sw_rf_rx_lpf_corner(btcoexist, + coex_dm->cur_rf_rx_lpf_shrink); + + coex_dm->pre_rf_rx_lpf_shrink = coex_dm->cur_rf_rx_lpf_shrink; +} + +static void btc8821a2ant_SetSwPenTxRateAdapt(struct btc_coexist *btcoexist, + bool low_penalty_ra) +{ + u8 h2c_parameter[6] = {0}; + + h2c_parameter[0] = 0x6; /* opCode, 0x6 = Retry_Penalty */ + + if (low_penalty_ra) { + h2c_parameter[1] |= BIT0; + /*normal rate except MCS7/6/5, OFDM54/48/36 */ + h2c_parameter[2] = 0x00; + /*MCS7 or OFDM54 */ + h2c_parameter[3] = 0xf7; + /*MCS6 or OFDM48 */ + h2c_parameter[4] = 0xf8; + /*MCS5 or OFDM36 */ + h2c_parameter[5] = 0xf9; + } + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], set WiFi Low-Penalty Retry: %s", + (low_penalty_ra ? "ON!!" : "OFF!!")); + + btcoexist->btc_fill_h2c(btcoexist, 0x69, 6, h2c_parameter); +} + +static void halbtc8821a2ant_low_penalty_ra(struct btc_coexist *btcoexist, + bool force_exec, bool low_penalty_ra) +{ + /*return;*/ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s turn LowPenaltyRA = %s\n", + (force_exec ? "force to" : ""), + ((low_penalty_ra) ? "ON" : "OFF")); + coex_dm->cur_low_penalty_ra = low_penalty_ra; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], pre_low_penalty_ra = %d, cur_low_penalty_ra = %d\n", + coex_dm->pre_low_penalty_ra, + coex_dm->cur_low_penalty_ra); + + if (coex_dm->pre_low_penalty_ra == coex_dm->cur_low_penalty_ra) + return; + } + btc8821a2ant_SetSwPenTxRateAdapt(btcoexist, + coex_dm->cur_low_penalty_ra); + + coex_dm->pre_low_penalty_ra = coex_dm->cur_low_penalty_ra; +} + +static void halbtc8821a2ant_set_dac_swing_reg(struct btc_coexist *btcoexist, + u32 level) +{ + u8 val = (u8)level; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], Write SwDacSwing = 0x%x\n", level); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0xc5b, 0x3e, val); +} + +static void btc8821a2ant_set_sw_full_dac_swing(struct btc_coexist *btcoexist, + bool sw_dac_swing_on, + u32 sw_dac_swing_lvl) +{ + if (sw_dac_swing_on) + halbtc8821a2ant_set_dac_swing_reg(btcoexist, sw_dac_swing_lvl); + else + halbtc8821a2ant_set_dac_swing_reg(btcoexist, 0x18); +} + +static void halbtc8821a2ant_dac_swing(struct btc_coexist *btcoexist, + bool force_exec, bool dac_swing_on, + u32 dac_swing_lvl) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s turn DacSwing = %s, dac_swing_lvl = 0x%x\n", + (force_exec ? "force to" : ""), + ((dac_swing_on) ? "ON" : "OFF"), + dac_swing_lvl); + coex_dm->cur_dac_swing_on = dac_swing_on; + coex_dm->cur_dac_swing_lvl = dac_swing_lvl; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], pre_dac_swing_on = %d, pre_dac_swing_lvl = 0x%x, cur_dac_swing_on = %d, cur_dac_swing_lvl = 0x%x\n", + coex_dm->pre_dac_swing_on, + coex_dm->pre_dac_swing_lvl, + coex_dm->cur_dac_swing_on, + coex_dm->cur_dac_swing_lvl); + + if ((coex_dm->pre_dac_swing_on == coex_dm->cur_dac_swing_on) && + (coex_dm->pre_dac_swing_lvl == + coex_dm->cur_dac_swing_lvl)) + return; + } + mdelay(30); + btc8821a2ant_set_sw_full_dac_swing(btcoexist, dac_swing_on, + dac_swing_lvl); + + coex_dm->pre_dac_swing_on = coex_dm->cur_dac_swing_on; + coex_dm->pre_dac_swing_lvl = coex_dm->cur_dac_swing_lvl; +} + +static void halbtc8821a2ant_set_adc_back_off(struct btc_coexist *btcoexist, + bool adc_back_off) +{ + if (adc_back_off) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], BB BackOff Level On!\n"); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x8db, 0x60, 0x3); + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], BB BackOff Level Off!\n"); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x8db, 0x60, 0x1); + } +} + +static void halbtc8821a2ant_adc_back_off(struct btc_coexist *btcoexist, + bool force_exec, bool adc_back_off) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s turn AdcBackOff = %s\n", + (force_exec ? "force to" : ""), + ((adc_back_off) ? "ON" : "OFF")); + coex_dm->cur_adc_back_off = adc_back_off; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], pre_adc_back_off = %d, cur_adc_back_off = %d\n", + coex_dm->pre_adc_back_off, coex_dm->cur_adc_back_off); + + if (coex_dm->pre_adc_back_off == coex_dm->cur_adc_back_off) + return; + } + halbtc8821a2ant_set_adc_back_off(btcoexist, coex_dm->cur_adc_back_off); + + coex_dm->pre_adc_back_off = coex_dm->cur_adc_back_off; +} + +static void halbtc8821a2ant_set_coex_table(struct btc_coexist *btcoexist, + u32 val0x6c0, u32 val0x6c4, + u32 val0x6c8, u8 val0x6cc) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); + btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); + btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); + btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, + "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); + btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); +} + +static void halbtc8821a2ant_coex_table(struct btc_coexist *btcoexist, + bool force_exec, u32 val0x6c0, + u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, + "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", + (force_exec ? "force to" : ""), + val0x6c0, val0x6c4, val0x6c8, val0x6cc); + coex_dm->cur_val0x6c0 = val0x6c0; + coex_dm->cur_val0x6c4 = val0x6c4; + coex_dm->cur_val0x6c8 = val0x6c8; + coex_dm->cur_val0x6cc = val0x6cc; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], pre_val0x6c0 = 0x%x, pre_val0x6c4 = 0x%x, pre_val0x6c8 = 0x%x, pre_val0x6cc = 0x%x !!\n", + coex_dm->pre_val0x6c0, + coex_dm->pre_val0x6c4, + coex_dm->pre_val0x6c8, + coex_dm->pre_val0x6cc); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, + "[BTCoex], cur_val0x6c0 = 0x%x, cur_val0x6c4 = 0x%x, cur_val0x6c8 = 0x%x, cur_val0x6cc = 0x%x !!\n", + coex_dm->cur_val0x6c0, + coex_dm->cur_val0x6c4, + coex_dm->cur_val0x6c8, + coex_dm->cur_val0x6cc); + + if ((coex_dm->pre_val0x6c0 == coex_dm->cur_val0x6c0) && + (coex_dm->pre_val0x6c4 == coex_dm->cur_val0x6c4) && + (coex_dm->pre_val0x6c8 == coex_dm->cur_val0x6c8) && + (coex_dm->pre_val0x6cc == coex_dm->cur_val0x6cc)) + return; + } + halbtc8821a2ant_set_coex_table(btcoexist, val0x6c0, val0x6c4, val0x6c8, + val0x6cc); + + coex_dm->pre_val0x6c0 = coex_dm->cur_val0x6c0; + coex_dm->pre_val0x6c4 = coex_dm->cur_val0x6c4; + coex_dm->pre_val0x6c8 = coex_dm->cur_val0x6c8; + coex_dm->pre_val0x6cc = coex_dm->cur_val0x6cc; +} + +static void halbtc8821a2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoex, + bool enable) +{ + u8 h2c_parameter[1] = {0}; + + if (enable) + h2c_parameter[0] |= BIT0;/* function enable */ + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", + h2c_parameter[0]); + + btcoex->btc_fill_h2c(btcoex, 0x63, 1, h2c_parameter); +} + +static void halbtc8821a2ant_ignore_wlan_act(struct btc_coexist *btcoexist, + bool force_exec, bool enable) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s turn Ignore WlanAct %s\n", + (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); + coex_dm->cur_ignore_wlan_act = enable; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_ignore_wlan_act = %d, cur_ignore_wlan_act = %d!!\n", + coex_dm->pre_ignore_wlan_act, + coex_dm->cur_ignore_wlan_act); + + if (coex_dm->pre_ignore_wlan_act == + coex_dm->cur_ignore_wlan_act) + return; + } + halbtc8821a2ant_set_fw_ignore_wlan_act(btcoexist, enable); + + coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; +} + +static void halbtc8821a2ant_set_fw_pstdma(struct btc_coexist *btcoexist, + u8 byte1, u8 byte2, u8 byte3, + u8 byte4, u8 byte5) +{ + u8 h2c_parameter[5]; + + h2c_parameter[0] = byte1; + h2c_parameter[1] = byte2; + h2c_parameter[2] = byte3; + h2c_parameter[3] = byte4; + h2c_parameter[4] = byte5; + + coex_dm->ps_tdma_para[0] = byte1; + coex_dm->ps_tdma_para[1] = byte2; + coex_dm->ps_tdma_para[2] = byte3; + coex_dm->ps_tdma_para[3] = byte4; + coex_dm->ps_tdma_para[4] = byte5; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x60(5bytes) = 0x%x%08x\n", + h2c_parameter[0], + h2c_parameter[1]<<24| + h2c_parameter[2]<<16| + h2c_parameter[3]<<8| + h2c_parameter[4]); + + btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); +} + +static void btc8821a2ant_sw_mech1(struct btc_coexist *btcoexist, + bool shrink_rx_lpf, + bool low_penalty_ra, bool limited_dig, + bool bt_lna_constrain) +{ + u32 wifi_bw; + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (BTC_WIFI_BW_HT40 != wifi_bw) { + /*only shrink RF Rx LPF for HT40*/ + if (shrink_rx_lpf) + shrink_rx_lpf = false; + } + + halbtc8821a2ant_RfShrink(btcoexist, NORMAL_EXEC, shrink_rx_lpf); + halbtc8821a2ant_low_penalty_ra(btcoexist, + NORMAL_EXEC, low_penalty_ra); + + /* no limited DIG + * btc8821a2_set_bt_lna_const(btcoexist, + NORMAL_EXEC, bBTLNAConstrain); + */ +} + +static void btc8821a2ant_sw_mech2(struct btc_coexist *btcoexist, + bool agc_table_shift, + bool adc_back_off, bool sw_dac_swing, + u32 dac_swing_lvl) +{ + /* halbtc8821a2ant_AgcTable(btcoexist, NORMAL_EXEC, bAGCTableShift); */ + halbtc8821a2ant_adc_back_off(btcoexist, NORMAL_EXEC, adc_back_off); + halbtc8821a2ant_dac_swing(btcoexist, NORMAL_EXEC, sw_dac_swing, + sw_dac_swing); +} + +static void halbtc8821a2ant_set_ant_path(struct btc_coexist *btcoexist, + u8 ant_pos_type, bool init_hw_cfg, + bool wifi_off) +{ + struct btc_board_info *board_info = &btcoexist->board_info; + u32 u4tmp = 0; + u8 h2c_parameter[2] = {0}; + + if (init_hw_cfg) { + /* 0x4c[23] = 0, 0x4c[24] = 1 Antenna control by WL/BT */ + u4tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); + u4tmp &= ~BIT23; + u4tmp |= BIT24; + btcoexist->btc_write_4byte(btcoexist, 0x4c, u4tmp); + + btcoexist->btc_write_4byte(btcoexist, 0x974, 0x3ff); + btcoexist->btc_write_1byte(btcoexist, 0xcb4, 0x77); + + if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) { + /* tell firmware "antenna inverse" ==> + * WRONG firmware antenna control code. + * ==>need fw to fix + */ + h2c_parameter[0] = 1; + h2c_parameter[1] = 1; + btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, + h2c_parameter); + } else { + /* tell firmware "no antenna inverse" + * ==> WRONG firmware antenna control code. + * ==>need fw to fix + */ + h2c_parameter[0] = 0; + h2c_parameter[1] = 1; + btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, + h2c_parameter); + } + } + + /* ext switch setting */ + switch (ant_pos_type) { + case BTC_ANT_WIFI_AT_MAIN: + btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, 0x30, 0x1); + break; + case BTC_ANT_WIFI_AT_AUX: + btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, 0x30, 0x2); + break; + } +} + +static void halbtc8821a2ant_ps_tdma(struct btc_coexist *btcoexist, + bool force_exec, bool turn_on, u8 type) +{ + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], %s turn %s PS TDMA, type = %d\n", + (force_exec ? "force to" : ""), (turn_on ? "ON" : "OFF"), + type); + coex_dm->cur_ps_tdma_on = turn_on; + coex_dm->cur_ps_tdma = type; + + if (!force_exec) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_ps_tdma_on = %d, cur_ps_tdma_on = %d!!\n", + coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], pre_ps_tdma = %d, cur_ps_tdma = %d!!\n", + coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma); + + if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && + (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) + return; + } + if (turn_on) { + switch (type) { + case 1: + default: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0xe1, 0x90); + break; + case 2: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x12, + 0x12, 0xe1, 0x90); + break; + case 3: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1c, + 0x3, 0xf1, 0x90); + break; + case 4: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x10, + 0x03, 0xf1, 0x90); + break; + case 5: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0x60, 0x90); + break; + case 6: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x12, + 0x12, 0x60, 0x90); + break; + case 7: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1c, + 0x3, 0x70, 0x90); + break; + case 8: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xa3, 0x10, + 0x3, 0x70, 0x90); + break; + case 9: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0xe1, 0x90); + break; + case 10: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x12, + 0x12, 0xe1, 0x90); + break; + case 11: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0xa, + 0xa, 0xe1, 0x90); + break; + case 12: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x5, + 0x5, 0xe1, 0x90); + break; + case 13: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0x60, 0x90); + break; + case 14: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, + 0x12, 0x12, 0x60, 0x90); + break; + case 15: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0xa, + 0xa, 0x60, 0x90); + break; + case 16: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x5, + 0x5, 0x60, 0x90); + break; + case 17: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xa3, 0x2f, + 0x2f, 0x60, 0x90); + break; + case 18: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x5, + 0x5, 0xe1, 0x90); + break; + case 19: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x25, + 0x25, 0xe1, 0x90); + break; + case 20: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x25, + 0x25, 0x60, 0x90); + break; + case 21: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x15, + 0x03, 0x70, 0x90); + break; + case 71: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a, + 0x1a, 0xe1, 0x90); + break; + } + } else { + /* disable PS tdma */ + switch (type) { + case 0: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0x0, 0x0, 0x0, + 0x40, 0x0); + break; + case 1: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0x0, 0x0, 0x0, + 0x48, 0x0); + break; + default: + halbtc8821a2ant_set_fw_pstdma(btcoexist, 0x0, 0x0, 0x0, + 0x40, 0x0); + break; + } + } + + /* update pre state */ + coex_dm->pre_ps_tdma_on = coex_dm->cur_ps_tdma_on; + coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; +} + +static void halbtc8821a2ant_coex_all_off(struct btc_coexist *btcoexist) +{ + /* fw all off */ + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + /* sw all off */ + btc8821a2ant_sw_mech1(btcoexist, false, false, false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, false, 0x18); + + /* hw all off */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, + 0x55555555, 0x55555555, 0xffff, 0x3); +} + +static void halbtc8821a2ant_coex_under_5g(struct btc_coexist *btcoexist) +{ + halbtc8821a2ant_coex_all_off(btcoexist); +} + +static void halbtc8821a2ant_init_coex_dm(struct btc_coexist *btcoexist) +{ + /* force to reset coex mechanism */ + halbtc8821a2ant_coex_table(btcoexist, FORCE_EXEC, 0x55555555, + 0x55555555, 0xffff, 0x3); + + halbtc8821a2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 1); + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, FORCE_EXEC, 6); + halbtc8821a2ant_dec_bt_pwr(btcoexist, FORCE_EXEC, false); + + btc8821a2ant_sw_mech1(btcoexist, false, false, false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, false, 0x18); +} + +static void halbtc8821a2ant_bt_inquiry_page(struct btc_coexist *btcoexist) +{ + bool low_pwr_disable = true; + + btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5afa5afa, 0xffff, 0x3); + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); +} + +static bool halbtc8821a2ant_is_common_action(struct btc_coexist *btcoexist) +{ + bool common = false, wifi_connected = false, wifi_busy = false; + bool low_pwr_disable = false; + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, + &wifi_connected); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); + + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5afa5afa, 0xffff, 0x3); + + if (!wifi_connected && + BT_8821A_2ANT_BT_STATUS_IDLE == coex_dm->bt_status) { + low_pwr_disable = false; + btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi IPS + BT IPS!!\n"); + + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btc8821a2ant_sw_mech1(btcoexist, false, false, false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, false, 0x18); + + common = true; + } else if (wifi_connected && + (BT_8821A_2ANT_BT_STATUS_IDLE == coex_dm->bt_status)) { + low_pwr_disable = false; + btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + if (wifi_busy) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi Busy + BT IPS!!\n"); + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 1); + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi LPS + BT IPS!!\n"); + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 1); + } + + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btc8821a2ant_sw_mech1(btcoexist, false, false, false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, false, 0x18); + + common = true; + } else if (!wifi_connected && + (BT_8821A_2ANT_BT_STATUS_CON_IDLE == coex_dm->bt_status)) { + low_pwr_disable = true; + btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi IPS + BT LPS!!\n"); + + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btc8821a2ant_sw_mech1(btcoexist, false, false, false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, false, 0x18); + common = true; + } else if (wifi_connected && + (BT_8821A_2ANT_BT_STATUS_CON_IDLE == coex_dm->bt_status)) { + low_pwr_disable = true; + btcoexist->btc_set(btcoexist, + BTC_SET_ACT_DISABLE_LOW_POWER, &low_pwr_disable); + + if (wifi_busy) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi Busy + BT LPS!!\n"); + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 1); + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi LPS + BT LPS!!\n"); + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 1); + } + + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btc8821a2ant_sw_mech1(btcoexist, true, true, true, true); + btc8821a2ant_sw_mech2(btcoexist, false, false, false, 0x18); + + common = true; + } else if (!wifi_connected && + (BT_8821A_2ANT_BT_STATUS_NON_IDLE == + coex_dm->bt_status)) { + low_pwr_disable = false; + btcoexist->btc_set(btcoexist, + BTC_SET_ACT_DISABLE_LOW_POWER, &low_pwr_disable); + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi IPS + BT Busy!!\n"); + + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btc8821a2ant_sw_mech1(btcoexist, false, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + + common = true; + } else { + low_pwr_disable = true; + btcoexist->btc_set(btcoexist, + BTC_SET_ACT_DISABLE_LOW_POWER, + &low_pwr_disable); + + if (wifi_busy) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi Busy + BT Busy!!\n"); + common = false; + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Wifi LPS + BT Busy!!\n"); + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, true, 21); + + if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) + halbtc8821a2ant_dec_bt_pwr(btcoexist, + NORMAL_EXEC, true); + else + halbtc8821a2ant_dec_bt_pwr(btcoexist, + NORMAL_EXEC, false); + + common = true; + } + btc8821a2ant_sw_mech1(btcoexist, true, true, true, true); + } + return common; +} + +static void btc8821a2_int1(struct btc_coexist *btcoexist, bool tx_pause, + int result) +{ + if (tx_pause) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); + + if (coex_dm->cur_ps_tdma == 71) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + coex_dm->tdma_adj_type = 5; + } else if (coex_dm->cur_ps_tdma == 1) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + coex_dm->tdma_adj_type = 5; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 4) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } + if (coex_dm->cur_ps_tdma == 9) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 13); + coex_dm->tdma_adj_type = 13; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 12) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + + if (result == -1) { + if (coex_dm->cur_ps_tdma == 5) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } else if (coex_dm->cur_ps_tdma == 13) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 8) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + coex_dm->tdma_adj_type = 5; + } else if (coex_dm->cur_ps_tdma == 16) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 13); + coex_dm->tdma_adj_type = 13; + } + } + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); + if (coex_dm->cur_ps_tdma == 5) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 71); + coex_dm->tdma_adj_type = 71; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 8) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } + if (coex_dm->cur_ps_tdma == 13) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 16) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + + if (result == -1) { + if (coex_dm->cur_ps_tdma == 71) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 1); + coex_dm->tdma_adj_type = 1; + } else if (coex_dm->cur_ps_tdma == 1) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } else if (coex_dm->cur_ps_tdma == 9) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 4) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 1); + coex_dm->tdma_adj_type = 1; + } else if (coex_dm->cur_ps_tdma == 1) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 71); + coex_dm->tdma_adj_type = 71; + } else if (coex_dm->cur_ps_tdma == 12) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } + } + } +} + +static void btc8821a2_int2(struct btc_coexist *btcoexist, bool tx_pause, + int result) +{ + if (tx_pause) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); + if (coex_dm->cur_ps_tdma == 1) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 4) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } + if (coex_dm->cur_ps_tdma == 9) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 12) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + if (result == -1) { + if (coex_dm->cur_ps_tdma == 5) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } else if (coex_dm->cur_ps_tdma == 13) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 8) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (coex_dm->cur_ps_tdma == 16) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } + } + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); + if (coex_dm->cur_ps_tdma == 5) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 8) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } + if (coex_dm->cur_ps_tdma == 13) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 16) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + if (result == -1) { + if (coex_dm->cur_ps_tdma == 1) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } else if (coex_dm->cur_ps_tdma == 9) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 4) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (coex_dm->cur_ps_tdma == 12) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } + } + } +} + +static void btc8821a2_int3(struct btc_coexist *btcoexist, bool tx_pause, + int result) +{ + if (tx_pause) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 1\n"); + if (coex_dm->cur_ps_tdma == 1) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 4) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } + if (coex_dm->cur_ps_tdma == 9) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 12) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + if (result == -1) { + if (coex_dm->cur_ps_tdma == 5) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 8); + coex_dm->tdma_adj_type = 8; + } else if (coex_dm->cur_ps_tdma == 13) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 16); + coex_dm->tdma_adj_type = 16; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 8) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else if (coex_dm->cur_ps_tdma == 16) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } + } + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], TxPause = 0\n"); + if (coex_dm->cur_ps_tdma == 5) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 6) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 7) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 8) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } + if (coex_dm->cur_ps_tdma == 13) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 14) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 15) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 16) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + if (result == -1) { + if (coex_dm->cur_ps_tdma == 1) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 4); + coex_dm->tdma_adj_type = 4; + } else if (coex_dm->cur_ps_tdma == 9) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 12); + coex_dm->tdma_adj_type = 12; + } + } else if (result == 1) { + if (coex_dm->cur_ps_tdma == 4) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else if (coex_dm->cur_ps_tdma == 12) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 11) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else if (coex_dm->cur_ps_tdma == 10) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } + } + } +} + +static void btc8821a2ant_tdma_dur_adj(struct btc_coexist *btcoexist, + bool sco_hid, bool tx_pause, + u8 max_interval) +{ + static long up, dn, m, n, wait_count; + /* 0: no change, +1: increase WiFi duration, + * -1: decrease WiFi duration + */ + int result; + u8 retry_count = 0; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, + "[BTCoex], TdmaDurationAdjust()\n"); + + if (coex_dm->reset_tdma_adjust) { + coex_dm->reset_tdma_adjust = false; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], first run TdmaDurationAdjust()!!\n"); + if (sco_hid) { + if (tx_pause) { + if (max_interval == 1) { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 13); + coex_dm->tdma_adj_type = 13; + } else if (max_interval == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 14); + coex_dm->tdma_adj_type = 14; + } else if (max_interval == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } else { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 15); + coex_dm->tdma_adj_type = 15; + } + } else { + if (max_interval == 1) { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 9); + coex_dm->tdma_adj_type = 9; + } else if (max_interval == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 10); + coex_dm->tdma_adj_type = 10; + } else if (max_interval == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } else { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 11); + coex_dm->tdma_adj_type = 11; + } + } + } else { + if (tx_pause) { + if (max_interval == 1) { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 5); + coex_dm->tdma_adj_type = 5; + } else if (max_interval == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 6); + coex_dm->tdma_adj_type = 6; + } else if (max_interval == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } else { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 7); + coex_dm->tdma_adj_type = 7; + } + } else { + if (max_interval == 1) { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 1); + coex_dm->tdma_adj_type = 1; + } else if (max_interval == 2) { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 2); + coex_dm->tdma_adj_type = 2; + } else if (max_interval == 3) { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } else { + halbtc8821a2ant_ps_tdma(btcoexist, + NORMAL_EXEC, + true, 3); + coex_dm->tdma_adj_type = 3; + } + } + } + + up = 0; + dn = 0; + m = 1; + n = 3; + result = 0; + wait_count = 0; + } else { + /* accquire the BT TRx retry count from BT_Info byte2 */ + retry_count = coex_sta->bt_retry_cnt; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], retry_count = %d\n", retry_count); + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], up = %d, dn = %d, m = %d, n = %d, wait_count = %d\n", + (int)up, (int)dn, (int)m, (int)n, (int)wait_count); + result = 0; + wait_count++; + + if (retry_count == 0) { + /* no retry in the last 2-second duration */ + up++; + dn--; + + if (dn <= 0) + dn = 0; + + if (up >= n) { + /* if (retry count == 0) for 2*n seconds, + * make WiFi duration wider + */ + wait_count = 0; + n = 3; + up = 0; + dn = 0; + result = 1; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], Increase wifi duration!!\n"); + } + } else if (retry_count <= 3) { + /* <=3 retry in the last 2-second duration */ + up--; + dn++; + + if (up <= 0) + up = 0; + + if (dn == 2) { + /* if retry count< 3 for 2*2 seconds, + * shrink wifi duration + */ + if (wait_count <= 2) + m++; /* avoid bounce in two levels */ + else + m = 1; + /* m max value is 20, max time is 120 second, + * recheck if adjust WiFi duration. + */ + if (m >= 20) + m = 20; + + n = 3*m; + up = 0; + dn = 0; + wait_count = 0; + result = -1; + BTC_PRINT(BTC_MSG_ALGORITHM, + ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retryCounter<3!!\n"); + } + } else { + /* retry count > 3, if retry count > 3 happens once, + * shrink WiFi duration + */ + if (wait_count == 1) + m++; /* avoid bounce in two levels */ + else + m = 1; + /* m max value is 20, max time is 120 second, + * recheck if adjust WiFi duration. + */ + if (m >= 20) + m = 20; + + n = 3*m; + up = 0; + dn = 0; + wait_count = 0; + result = -1; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], Decrease wifi duration for retryCounter>3!!\n"); + } + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], max Interval = %d\n", max_interval); + if (max_interval == 1) + btc8821a2_int1(btcoexist, tx_pause, result); + else if (max_interval == 2) + btc8821a2_int2(btcoexist, tx_pause, result); + else if (max_interval == 3) + btc8821a2_int3(btcoexist, tx_pause, result); + } + + /* if current PsTdma not match with the recorded one + * (when scan, dhcp...), then we have to adjust it back to + * the previous recorded one. + */ + if (coex_dm->cur_ps_tdma != coex_dm->tdma_adj_type) { + bool scan = false, link = false, roam = false; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], PsTdma type dismatch!!!, cur_ps_tdma = %d, recordPsTdma = %d\n", + coex_dm->cur_ps_tdma, coex_dm->tdma_adj_type); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); + + if (!scan && !link && !roam) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, + coex_dm->tdma_adj_type); + } else { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, + "[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n"); + } + } + + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 0x6); +} + +/* SCO only or SCO+PAN(HS)*/ +static void halbtc8821a2ant_action_sco(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, + 15, 0); + bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); + + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 4); + + if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (BTC_WIFI_BW_LEGACY == wifi_bw) { + /* for SCO quality at 11b/g mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, + 0x5a5a5a5a, 0x5a5a5a5a, 0xffff, 0x3); + } else { + /* for SCO quality & wifi performance balance at 11n mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, + 0x5aea5aea, 0x5aea5aea, 0xffff, 0x3); + } + + if (BTC_WIFI_BW_HT40 == wifi_bw) { + /* fw mechanism + * halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); + */ + + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 0); /*for voice quality*/ + } else { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 0); /*for voice quality*/ + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, true, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, true, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } else { + /* fw mechanism + * halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); + */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 0); /*for voice quality*/ + } else { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 0); /*for voice quality*/ + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, false, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, false, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void halbtc8821a2ant_action_hid(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); + + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (BTC_WIFI_BW_LEGACY == wifi_bw) { + /* for HID at 11b/g mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5a5a5a5a, 0xffff, 0x3); + } else { + /* for HID quality & wifi performance balance at 11n mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5aea5aea, 0xffff, 0x3); + } + + if (BTC_WIFI_BW_HT40 == wifi_bw) { + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + } else { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 13); + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, true, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, true, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } else { + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 9); + } else { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 13); + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, false, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, false, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } +} + +/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */ +static void halbtc8821a2ant_action_a2dp(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, + 15, 0); + bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); + + /* fw dac swing is called in btc8821a2ant_tdma_dur_adj() + * halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + */ + + if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (BTC_WIFI_BW_HT40 == wifi_bw) { + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_tdma_dur_adj(btcoexist, false, false, 1); + } else { + btc8821a2ant_tdma_dur_adj(btcoexist, false, true, 1); + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, true, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, true, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } else { + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_tdma_dur_adj(btcoexist, false, false, 1); + } else { + btc8821a2ant_tdma_dur_adj(btcoexist, false, true, 1); + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, false, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, false, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void halbtc8821a2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state, bt_info_ext; + u32 wifi_bw; + + bt_info_ext = coex_sta->bt_info_ext; + wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, + 15, 0); + bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); + + /*fw dac swing is called in btc8821a2ant_tdma_dur_adj() + *halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + */ + + if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (BTC_WIFI_BW_HT40 == wifi_bw) { + /* fw mechanism */ + if (bt_info_ext&BIT0) { + /*a2dp basic rate*/ + btc8821a2ant_tdma_dur_adj(btcoexist, false, true, 2); + } else { + /*a2dp edr rate*/ + btc8821a2ant_tdma_dur_adj(btcoexist, false, true, 1); + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, true, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, true, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } else { + /* fw mechanism */ + if (bt_info_ext&BIT0) { + /* a2dp basic rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, false, true, 2); + } else { + /* a2dp edr rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, false, true, 1); + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, false, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, false, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void halbtc8821a2ant_action_pan_edr(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, + 15, 0); + bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); + + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (BTC_WIFI_BW_LEGACY == wifi_bw) { + /* for HID at 11b/g mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5aff5aff, 0xffff, 0x3); + } else { + /* for HID quality & wifi performance balance at 11n mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5aff5aff, 0xffff, 0x3); + } + + if (BTC_WIFI_BW_HT40 == wifi_bw) { + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 1); + } else { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, true, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, true, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } else { + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 1); + } else { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 5); + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, false, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, false, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } +} + +/* PAN(HS) only */ +static void halbtc8821a2ant_action_pan_hs(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); + + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (BTC_WIFI_BW_HT40 == wifi_bw) { + /* fw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, + true); + } else { + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, + false); + } + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, true, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, true, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } else { + /* fw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a2ant_dec_bt_pwr(btcoexist, + NORMAL_EXEC, true); + } else { + halbtc8821a2ant_dec_bt_pwr(btcoexist, + NORMAL_EXEC, false); + } + + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 1); + } else { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + false, 1); + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, false, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, false, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } +} + +/* PAN(EDR)+A2DP */ +static void halbtc8821a2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state, bt_info_ext; + u32 wifi_bw; + + bt_info_ext = coex_sta->bt_info_ext; + wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, + 15, 0); + bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); + + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (BTC_WIFI_BW_LEGACY == wifi_bw) { + /* for HID at 11b/g mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5afa5afa, 0xffff, 0x3); + } else { + /* for HID quality & wifi performance balance at 11n mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5afa5afa, 0xffff, 0x3); + } + + if (BTC_WIFI_BW_HT40 == wifi_bw) { + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + if (bt_info_ext&BIT0) { + /* a2dp basic rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, false, + false, 3); + } else { + /* a2dp edr rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, false, + false, 3); + } + } else { + if (bt_info_ext&BIT0) { + /* a2dp basic rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, false, + true, 3); + } else { + /* a2dp edr rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, false, + true, 3); + } + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, true, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, true, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + }; + } else { + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + if (bt_info_ext&BIT0) { + /* a2dp basic rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, false, + false, 3); + } else { + /* a2dp edr rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, false, + false, 3); + } + } else { + if (bt_info_ext&BIT0) { + /* a2dp basic rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, false, + true, 3); + } else { + /* a2dp edr rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, false, + true, 3); + } + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, false, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, false, false, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void halbtc8821a2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state; + u32 wifi_bw; + + wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, + 15, 0); + bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); + + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (BTC_WIFI_BW_LEGACY == wifi_bw) { + /* for HID at 11b/g mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5a5f5a5f, 0xffff, 0x3); + } else { + /* for HID quality & wifi performance balance at 11n mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5a5f5a5f, 0xffff, 0x3); + } + + if (BTC_WIFI_BW_HT40 == wifi_bw) { + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 3); + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + } else { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, true, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, true, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } else { + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 10); + } else { + halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, + true, 14); + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, false, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, false, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } +} + +/* HID+A2DP+PAN(EDR) */ +static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state, bt_info_ext; + u32 wifi_bw; + + bt_info_ext = coex_sta->bt_info_ext; + wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, + 0, 2, 15, 0); + bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); + + halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); + + if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (BTC_WIFI_BW_LEGACY == wifi_bw) { + /* for HID at 11b/g mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5a5a5a5a, 0xffff, 0x3); + } else { + /* for HID quality & wifi performance balance at 11n mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5a5a5a5a, 0xffff, 0x3); + } + + if (BTC_WIFI_BW_HT40 == wifi_bw) { + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + if (bt_info_ext&BIT0) { + /* a2dp basic rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, true, + true, 3); + } else { + /* a2dp edr rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, true, + true, 3); + } + } else { + if (bt_info_ext&BIT0) { + /* a2dp basic rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, true, + true, 3); + } else { + /* a2dp edr rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, true, + true, 3); + } + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, true, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, true, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } else { + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + if (bt_info_ext&BIT0) { + /* a2dp basic rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, true, + false, 3); + } else { + /* a2dp edr rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, true, + false, 3); + } + } else { + if (bt_info_ext&BIT0) { + /* a2dp basic rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, true, + true, 3); + } else { + /* a2dp edr rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, true, + true, 3); + } + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, false, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, false, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void halbtc8821a2ant_action_hid_a2dp(struct btc_coexist *btcoexist) +{ + u8 wifi_rssi_state, bt_rssi_state, bt_info_ext; + u32 wifi_bw; + + bt_info_ext = coex_sta->bt_info_ext; + wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, + 15, 0); + bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); + + if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); + else + halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + + if (BTC_WIFI_BW_LEGACY == wifi_bw) { + /* for HID at 11b/g mode */ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5f5b5f5b, 0xffffff, 0x3); + } else { + /*for HID quality & wifi performance balance at 11n mode*/ + halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, + 0x5f5b5f5b, 0xffffff, 0x3); + } + + if (BTC_WIFI_BW_HT40 == wifi_bw) { + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + if (bt_info_ext&BIT0) { + /* a2dp basic rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, + true, true, 2); + } else { + /* a2dp edr rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, + true, true, 2); + } + } else { + if (bt_info_ext&BIT0) { + /* a2dp basic rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, + true, true, 2); + } else { + /* a2dp edr rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, + true, true, 2); + } + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, true, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, true, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } else { + /* fw mechanism */ + if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || + (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + if (bt_info_ext&BIT0) { + /* a2dp basic rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, + true, true, 2); + + } else { + /* a2dp edr rate */ + btc8821a2ant_tdma_dur_adj(btcoexist, + true, true, 2); + } + } else { + if (bt_info_ext&BIT0) { + /*a2dp basic rate*/ + btc8821a2ant_tdma_dur_adj(btcoexist, + true, true, 2); + } else { + /*a2dp edr rate*/ + btc8821a2ant_tdma_dur_adj(btcoexist, + true, true, 2); + } + } + + /* sw mechanism */ + if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || + (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { + btc8821a2ant_sw_mech1(btcoexist, false, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, true, false, + false, 0x18); + } else { + btc8821a2ant_sw_mech1(btcoexist, false, true, + false, false); + btc8821a2ant_sw_mech2(btcoexist, false, false, + false, 0x18); + } + } +} + +static void halbtc8821a2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) +{ + bool wifi_under_5g = false; + u8 algorithm = 0; + + if (btcoexist->manual_control) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Manual control!!!\n"); + return; + } + + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); + + if (wifi_under_5g) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], RunCoexistMechanism(), run 5G coex setting!!<===\n"); + halbtc8821a2ant_coex_under_5g(btcoexist); + return; + } + + algorithm = halbtc8821a2ant_action_algorithm(btcoexist); + if (coex_sta->c2h_bt_inquiry_page && + (BT_8821A_2ANT_COEX_ALGO_PANHS != algorithm)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], BT is under inquiry/page scan !!\n"); + halbtc8821a2ant_bt_inquiry_page(btcoexist); + return; + } + + coex_dm->cur_algorithm = algorithm; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Algorithm = %d\n", coex_dm->cur_algorithm); + + if (halbtc8821a2ant_is_common_action(btcoexist)) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant common.\n"); + coex_dm->reset_tdma_adjust = true; + } else { + if (coex_dm->cur_algorithm != coex_dm->pre_algorithm) { + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], pre_algorithm = %d, cur_algorithm = %d\n", + coex_dm->pre_algorithm, coex_dm->cur_algorithm); + coex_dm->reset_tdma_adjust = true; + } + switch (coex_dm->cur_algorithm) { + case BT_8821A_2ANT_COEX_ALGO_SCO: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = SCO.\n"); + halbtc8821a2ant_action_sco(btcoexist); + break; + case BT_8821A_2ANT_COEX_ALGO_HID: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HID.\n"); + halbtc8821a2ant_action_hid(btcoexist); + break; + case BT_8821A_2ANT_COEX_ALGO_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = A2DP.\n"); + halbtc8821a2ant_action_a2dp(btcoexist); + break; + case BT_8821A_2ANT_COEX_ALGO_A2DP_PANHS: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = A2DP+PAN(HS).\n"); + halbtc8821a2ant_action_a2dp_pan_hs(btcoexist); + break; + case BT_8821A_2ANT_COEX_ALGO_PANEDR: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = PAN(EDR).\n"); + halbtc8821a2ant_action_pan_edr(btcoexist); + break; + case BT_8821A_2ANT_COEX_ALGO_PANHS: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HS mode.\n"); + halbtc8821a2ant_action_pan_hs(btcoexist); + break; + case BT_8821A_2ANT_COEX_ALGO_PANEDR_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = PAN+A2DP.\n"); + halbtc8821a2ant_action_pan_edr_a2dp(btcoexist); + break; + case BT_8821A_2ANT_COEX_ALGO_PANEDR_HID: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = PAN(EDR)+HID.\n"); + halbtc8821a2ant_action_pan_edr_hid(btcoexist); + break; + case BT_8821A_2ANT_COEX_ALGO_HID_A2DP_PANEDR: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HID+A2DP+PAN.\n"); + btc8821a2ant_act_hid_a2dp_pan_edr(btcoexist); + break; + case BT_8821A_2ANT_COEX_ALGO_HID_A2DP: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = HID+A2DP.\n"); + halbtc8821a2ant_action_hid_a2dp(btcoexist); + break; + default: + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], Action 2-Ant, algorithm = coexist All Off!!\n"); + halbtc8821a2ant_coex_all_off(btcoexist); + break; + } + coex_dm->pre_algorithm = coex_dm->cur_algorithm; + } +} + +/*============================================================ + *work around function start with wa_halbtc8821a2ant_ + *============================================================ + *============================================================ + * extern function start with EXhalbtc8821a2ant_ + *============================================================ + */ +void ex_halbtc8821a2ant_init_hwconfig(struct btc_coexist *btcoexist) +{ + u8 u1tmp = 0; + + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], 2Ant Init HW Config!!\n"); + + /* backup rf 0x1e value */ + coex_dm->bt_rf0x1e_backup = + btcoexist->btc_get_rf_reg(btcoexist, BTC_RF_A, 0x1e, 0xfffff); + + /* 0x790[5:0] = 0x5 */ + u1tmp = btcoexist->btc_read_1byte(btcoexist, 0x790); + u1tmp &= 0xc0; + u1tmp |= 0x5; + btcoexist->btc_write_1byte(btcoexist, 0x790, u1tmp); + + /*Antenna config */ + halbtc8821a2ant_set_ant_path(btcoexist, + BTC_ANT_WIFI_AT_MAIN, true, false); + + /* PTA parameter */ + halbtc8821a2ant_coex_table(btcoexist, + FORCE_EXEC, 0x55555555, 0x55555555, + 0xffff, 0x3); + + /* Enable counter statistics */ + /*0x76e[3] = 1, WLAN_Act control by PTA*/ + btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); + btcoexist->btc_write_1byte(btcoexist, 0x778, 0x3); + btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1); +} + +void +ex_halbtc8821a2ant_init_coex_dm( + struct btc_coexist *btcoexist + ) +{ + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], Coex Mechanism Init!!\n"); + + halbtc8821a2ant_init_coex_dm(btcoexist); +} + +void +ex_halbtc8821a2ant_display_coex_info( + struct btc_coexist *btcoexist + ) +{ + struct btc_board_info *board_info = &btcoexist->board_info; + struct btc_stack_info *stack_info = &btcoexist->stack_info; + struct rtl_priv *rtlpriv = btcoexist->adapter; + u8 u1tmp[4], i, bt_info_ext, ps_tdma_case = 0; + u32 u4tmp[4]; + bool roam = false, scan = false, link = false, wifi_under_5g = false; + bool bt_hs_on = false, wifi_busy = false; + long wifi_rssi = 0, bt_hs_rssi = 0; + u32 wifi_bw, wifi_traffic_dir; + u8 wifi_dot_11_chnl, wifi_hs_chnl; + u32 fw_ver = 0, bt_patch_ver = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n ============[BT Coexist info]============"); + + if (!board_info->bt_exist) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n BT not exists !!!"); + return; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d/ %d ", "Ant PG number/ Ant mechanism:", + board_info->pg_ant_num, board_info->btdm_ant_num); + + if (btcoexist->manual_control) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s", "[Action Manual control]!!"); + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", + ((stack_info->profile_notified) ? "Yes" : "No"), + stack_info->hci_version); + + btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d_%d/ 0x%x/ 0x%x(%d)", + "CoexVer/ FwVer/ PatchVer", + glcoex_ver_date_8821a_2ant, glcoex_ver_8821a_2ant, + fw_ver, bt_patch_ver, bt_patch_ver); + + btcoexist->btc_get(btcoexist, + BTC_GET_BL_HS_OPERATION, &bt_hs_on); + btcoexist->btc_get(btcoexist, + BTC_GET_U1_WIFI_DOT11_CHNL, &wifi_dot_11_chnl); + btcoexist->btc_get(btcoexist, + BTC_GET_U1_WIFI_HS_CHNL, &wifi_hs_chnl); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d / %d(%d)", + "Dot11 channel / HsMode(HsChnl)", + wifi_dot_11_chnl, bt_hs_on, wifi_hs_chnl); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %02x %02x %02x ", + "H2C Wifi inform bt chnl Info", + coex_dm->wifi_chnl_info[0], coex_dm->wifi_chnl_info[1], + coex_dm->wifi_chnl_info[2]); + + btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); + btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %ld/ %ld", "Wifi rssi/ HS rssi", + wifi_rssi, bt_hs_rssi); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d/ %d/ %d ", "Wifi link/ roam/ scan", + link, roam, scan); + + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); + btcoexist->btc_get(btcoexist, + BTC_GET_U4_WIFI_BW, &wifi_bw); + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_BUSY, &wifi_busy); + btcoexist->btc_get(btcoexist, + BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, &wifi_traffic_dir); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %s / %s/ %s ", "Wifi status", + (wifi_under_5g ? "5G" : "2.4G"), + ((BTC_WIFI_BW_LEGACY == wifi_bw) ? "Legacy" : + (((BTC_WIFI_BW_HT40 == wifi_bw) ? "HT40" : "HT20"))), + ((!wifi_busy) ? "idle" : + ((BTC_WIFI_TRAFFIC_TX == wifi_traffic_dir) ? + "uplink" : "downlink"))); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = [%s/ %d/ %d] ", "BT [status/ rssi/ retryCnt]", + ((coex_sta->c2h_bt_inquiry_page) ? ("inquiry/page scan") : + ((BT_8821A_2ANT_BT_STATUS_IDLE == coex_dm->bt_status) + ? "idle" : ((BT_8821A_2ANT_BT_STATUS_CON_IDLE == + coex_dm->bt_status) ? "connected-idle" : "busy"))), + coex_sta->bt_rssi, coex_sta->bt_retry_cnt); + + if (stack_info->profile_notified) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP", + stack_info->sco_exist, stack_info->hid_exist, + stack_info->pan_exist, stack_info->a2dp_exist); + + btcoexist->btc_disp_dbg_msg(btcoexist, + BTC_DBG_DISP_BT_LINK_INFO); + } + + bt_info_ext = coex_sta->bt_info_ext; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s", + "BT Info A2DP rate", + (bt_info_ext&BIT0) ? "Basic rate" : "EDR rate"); + + for (i = 0; i < BT_INFO_SRC_8821A_2ANT_MAX; i++) { + if (coex_sta->bt_info_c2h_cnt[i]) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)", + glbt_info_src_8821a_2ant[i], + coex_sta->bt_info_c2h[i][0], + coex_sta->bt_info_c2h[i][1], + coex_sta->bt_info_c2h[i][2], + coex_sta->bt_info_c2h[i][3], + coex_sta->bt_info_c2h[i][4], + coex_sta->bt_info_c2h[i][5], + coex_sta->bt_info_c2h[i][6], + coex_sta->bt_info_c2h_cnt[i]); + } + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s/%s", + "PS state, IPS/LPS", + ((coex_sta->under_ips ? "IPS ON" : "IPS OFF")), + ((coex_sta->under_lps ? "LPS ON" : "LPS OFF"))); + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD); + + /* Sw mechanism*/ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", + "============[Sw mechanism]============"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d/ %d/ %d/ %d ", + "SM1[ShRf/ LpRA/ LimDig/ btLna]", + coex_dm->cur_rf_rx_lpf_shrink, coex_dm->cur_low_penalty_ra, + coex_dm->limited_dig, coex_dm->cur_bt_lna_constrain); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d/ %d/ %d(0x%x) ", + "SM2[AgcT/ AdcB/ SwDacSwing(lvl)]", + coex_dm->cur_agc_table_en, coex_dm->cur_adc_back_off, + coex_dm->cur_dac_swing_on, coex_dm->cur_dac_swing_lvl); + + /* Fw mechanism*/ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", + "============[Fw mechanism]============"); + + if (!btcoexist->manual_control) { + ps_tdma_case = coex_dm->cur_ps_tdma; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %02x %02x %02x %02x %02x case-%d", + "PS TDMA", + coex_dm->ps_tdma_para[0], coex_dm->ps_tdma_para[1], + coex_dm->ps_tdma_para[2], coex_dm->ps_tdma_para[3], + coex_dm->ps_tdma_para[4], ps_tdma_case); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = %d/ %d ", "DecBtPwr/ IgnWlanAct", + coex_dm->cur_dec_bt_pwr, + coex_dm->cur_ignore_wlan_act); + } + + /* Hw setting*/ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s", "============[Hw setting]============"); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "\r\n %-35s = 0x%x", "RF-A, 0x1e initVal", + coex_dm->bt_rf0x1e_backup); + + u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x778); + u1tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x6cc); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x ", + "0x778 (W_Act)/ 0x6cc (CoTab Sel)", + u1tmp[0], u1tmp[1]); + + u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x8db); + u1tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xc5b); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "0x8db(ADC)/0xc5b[29:25](DAC)", + ((u1tmp[0]&0x60)>>5), ((u1tmp[1]&0x3e)>>1)); + + u4tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xcb4); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "0xcb4[7:0](ctrl)/ 0xcb4[29:28](val)", + u4tmp[0]&0xff, ((u4tmp[0]&0x30000000)>>28)); + + u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x40); + u4tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x4c); + u4tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x974); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "0x40/ 0x4c[24:23]/ 0x974", + u1tmp[0], ((u4tmp[0]&0x01800000)>>23), u4tmp[1]); + + u4tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x550); + u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x522); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "0x550(bcn ctrl)/0x522", + u4tmp[0], u1tmp[0]); + + u4tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc50); + u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xa0a); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "0xc50(DIG)/0xa0a(CCK-TH)", + u4tmp[0], u1tmp[0]); + + u4tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xf48); + u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xa5b); + u1tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xa5c); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", + "OFDM-FA/ CCK-FA", + u4tmp[0], (u1tmp[0]<<8) + u1tmp[1]); + + u4tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6c0); + u4tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x6c4); + u4tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x6c8); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", + "0x6c0/0x6c4/0x6c8", + u4tmp[0], u4tmp[1], u4tmp[2]); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", + "0x770 (hi-pri Rx/Tx)", + coex_sta->high_priority_rx, coex_sta->high_priority_tx); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", + "0x774(low-pri Rx/Tx)", + coex_sta->low_priority_rx, coex_sta->low_priority_tx); + + /* Tx mgnt queue hang or not, 0x41b should = 0xf, ex: 0xd ==>hang*/ + u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x41b); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x", + "0x41b (mgntQ hang chk == 0xf)", + u1tmp[0]); + + btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS); +} + +void ex_halbtc8821a2ant_ips_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (BTC_IPS_ENTER == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], IPS ENTER notify\n"); + coex_sta->under_ips = true; + halbtc8821a2ant_coex_all_off(btcoexist); + } else if (BTC_IPS_LEAVE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], IPS LEAVE notify\n"); + coex_sta->under_ips = false; + /*halbtc8821a2ant_init_coex_dm(btcoexist);*/ + } +} + +void ex_halbtc8821a2ant_lps_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (BTC_LPS_ENABLE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], LPS ENABLE notify\n"); + coex_sta->under_lps = true; + } else if (BTC_LPS_DISABLE == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], LPS DISABLE notify\n"); + coex_sta->under_lps = false; + } +} + +void ex_halbtc8821a2ant_scan_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (BTC_SCAN_START == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], SCAN START notify\n"); + } else if (BTC_SCAN_FINISH == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], SCAN FINISH notify\n"); + } +} + +void ex_halbtc8821a2ant_connect_notify(struct btc_coexist *btcoexist, u8 type) +{ + if (BTC_ASSOCIATE_START == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], CONNECT START notify\n"); + } else if (BTC_ASSOCIATE_FINISH == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], CONNECT FINISH notify\n"); + } +} + +void ex_halbtc8821a2ant_media_status_notify(struct btc_coexist *btcoexist, + u8 type) +{ + u8 h2c_parameter[3] = {0}; + u32 wifi_bw; + u8 wifi_central_chnl; + + if (BTC_MEDIA_CONNECT == type) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], MEDIA connect notify\n"); + } else { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], MEDIA disconnect notify\n"); + } + + /* only 2.4G we need to inform bt the chnl mask*/ + btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, + &wifi_central_chnl); + if ((BTC_MEDIA_CONNECT == type) && + (wifi_central_chnl <= 14)) { + h2c_parameter[0] = 0x1; + h2c_parameter[1] = wifi_central_chnl; + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); + if (BTC_WIFI_BW_HT40 == wifi_bw) + h2c_parameter[2] = 0x30; + else + h2c_parameter[2] = 0x20; + } + + coex_dm->wifi_chnl_info[0] = h2c_parameter[0]; + coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; + coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, + "[BTCoex], FW write 0x66 = 0x%x\n", + h2c_parameter[0]<<16|h2c_parameter[1]<<8|h2c_parameter[2]); + + btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); +} + +void ex_halbtc8821a2ant_special_packet_notify(struct btc_coexist *btcoexist, + u8 type) { + if (type == BTC_PACKET_DHCP) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], DHCP Packet notify\n"); + } +} + +void ex_halbtc8821a2ant_bt_info_notify(struct btc_coexist *btcoexist, + u8 *tmp_buf, u8 length) +{ + u8 bt_info = 0; + u8 i, rsp_source = 0; + static u32 set_bt_lna_cnt, set_bt_psd_mode; + bool bt_busy = false, limited_dig = false; + bool wifi_connected = false, bt_hs_on = false; + + coex_sta->c2h_bt_info_req_sent = false; + + rsp_source = tmp_buf[0]&0xf; + if (rsp_source >= BT_INFO_SRC_8821A_2ANT_MAX) + rsp_source = BT_INFO_SRC_8821A_2ANT_WIFI_FW; + coex_sta->bt_info_c2h_cnt[rsp_source]++; + + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], Bt info[%d], length = %d, hex data = [", + rsp_source, length); + for (i = 0; i < length; i++) { + coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i]; + if (i == 1) + bt_info = tmp_buf[i]; + if (i == length-1) { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "0x%02x]\n", tmp_buf[i]); + } else { + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "0x%02x, ", tmp_buf[i]); + } + } + + if (BT_INFO_SRC_8821A_2ANT_WIFI_FW != rsp_source) { + coex_sta->bt_retry_cnt = /* [3:0]*/ + coex_sta->bt_info_c2h[rsp_source][2]&0xf; + + coex_sta->bt_rssi = + coex_sta->bt_info_c2h[rsp_source][3]*2+10; + + coex_sta->bt_info_ext = + coex_sta->bt_info_c2h[rsp_source][4]; + + /* Here we need to resend some wifi info to BT*/ + /* because bt is reset and loss of the info.*/ + if ((coex_sta->bt_info_ext & BIT1)) { + btcoexist->btc_get(btcoexist, + BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); + if (wifi_connected) { + ex_halbtc8821a2ant_media_status_notify(btcoexist, + BTC_MEDIA_CONNECT); + } else { + ex_halbtc8821a2ant_media_status_notify(btcoexist, + BTC_MEDIA_DISCONNECT); + } + + set_bt_psd_mode = 0; + } + if (set_bt_psd_mode <= 3) { + halbtc8821a2ant_set_bt_psd_mode(btcoexist, FORCE_EXEC, + 0x0); /*fix CH-BW mode*/ + set_bt_psd_mode++; + } + + if (coex_dm->cur_bt_lna_constrain) { + if (!(coex_sta->bt_info_ext & BIT2)) { + if (set_bt_lna_cnt <= 3) { + btc8821a2_set_bt_lna_const(btcoexist, + FORCE_EXEC, + true); + set_bt_lna_cnt++; + } + } + } else { + set_bt_lna_cnt = 0; + } + + if ((coex_sta->bt_info_ext & BIT3)) { + halbtc8821a2ant_ignore_wlan_act(btcoexist, + FORCE_EXEC, false); + } else { + /* BT already NOT ignore Wlan active, do nothing here.*/ + } + + if ((coex_sta->bt_info_ext & BIT4)) { + /* BT auto report already enabled, do nothing*/ + } else { + halbtc8821a2ant_bt_auto_report(btcoexist, + FORCE_EXEC, true); + } + } + + btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); + /* check BIT2 first ==> check if bt is under inquiry or page scan*/ + if (bt_info & BT_INFO_8821A_2ANT_B_INQ_PAGE) { + coex_sta->c2h_bt_inquiry_page = true; + coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_NON_IDLE; + } else { + coex_sta->c2h_bt_inquiry_page = false; + if (bt_info == 0x1) { + /* connection exists but not busy*/ + coex_sta->bt_link_exist = true; + coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_CON_IDLE; + } else if (bt_info & BT_INFO_8821A_2ANT_B_CONNECTION) { + /* connection exists and some link is busy*/ + coex_sta->bt_link_exist = true; + if (bt_info & BT_INFO_8821A_2ANT_B_FTP) + coex_sta->pan_exist = true; + else + coex_sta->pan_exist = false; + if (bt_info & BT_INFO_8821A_2ANT_B_A2DP) + coex_sta->a2dp_exist = true; + else + coex_sta->a2dp_exist = false; + if (bt_info & BT_INFO_8821A_2ANT_B_HID) + coex_sta->hid_exist = true; + else + coex_sta->hid_exist = false; + if (bt_info & BT_INFO_8821A_2ANT_B_SCO_ESCO) + coex_sta->sco_exist = true; + else + coex_sta->sco_exist = false; + coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_NON_IDLE; + } else { + coex_sta->bt_link_exist = false; + coex_sta->pan_exist = false; + coex_sta->a2dp_exist = false; + coex_sta->hid_exist = false; + coex_sta->sco_exist = false; + coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_IDLE; + } + + if (bt_hs_on) + coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_NON_IDLE; + } + + if (BT_8821A_2ANT_BT_STATUS_NON_IDLE == coex_dm->bt_status) + bt_busy = true; + else + bt_busy = false; + btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy); + + if (BT_8821A_2ANT_BT_STATUS_IDLE != coex_dm->bt_status) + limited_dig = true; + else + limited_dig = false; + coex_dm->limited_dig = limited_dig; + btcoexist->btc_set(btcoexist, + BTC_SET_BL_BT_LIMITED_DIG, &limited_dig); + + halbtc8821a2ant_run_coexist_mechanism(btcoexist); +} + +void ex_halbtc8821a2ant_halt_notify(struct btc_coexist *btcoexist) +{ + BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, + "[BTCoex], Halt notify\n"); + + halbtc8821a2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); + ex_halbtc8821a2ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT); +} + +void ex_halbtc8821a2ant_periodical(struct btc_coexist *btcoexist) +{ + static u8 dis_ver_info_cnt; + u32 fw_ver = 0, bt_patch_ver = 0; + struct btc_board_info *board_info = &btcoexist->board_info; + struct btc_stack_info *stack_info = &btcoexist->stack_info; + + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "[BTCoex], ==========================Periodical===========================\n"); + + if (dis_ver_info_cnt <= 5) { + dis_ver_info_cnt += 1; + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], ****************************************************************\n"); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", + board_info->pg_ant_num, + board_info->btdm_ant_num, + board_info->btdm_ant_pos); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], BT stack/ hci ext ver = %s / %d\n", + ((stack_info->profile_notified) ? "Yes" : "No"), + stack_info->hci_version); + btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, + &bt_patch_ver); + btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", + glcoex_ver_date_8821a_2ant, glcoex_ver_8821a_2ant, + fw_ver, bt_patch_ver, bt_patch_ver); + BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, + "[BTCoex], ****************************************************************\n"); + } + + halbtc8821a2ant_query_bt_info(btcoexist); + halbtc8821a2ant_monitor_bt_ctr(btcoexist); + btc8821a2ant_mon_bt_en_dis(btcoexist); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h new file mode 100644 index 000000000000..b4cf1f53d510 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.h @@ -0,0 +1,205 @@ +/****************************************************************************** + * + * Copyright(c) 2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +/*=========================================== + * The following is for 8821A 2Ant BT Co-exist definition + *=========================================== +*/ +#define BT_INFO_8821A_2ANT_B_FTP BIT7 +#define BT_INFO_8821A_2ANT_B_A2DP BIT6 +#define BT_INFO_8821A_2ANT_B_HID BIT5 +#define BT_INFO_8821A_2ANT_B_SCO_BUSY BIT4 +#define BT_INFO_8821A_2ANT_B_ACL_BUSY BIT3 +#define BT_INFO_8821A_2ANT_B_INQ_PAGE BIT2 +#define BT_INFO_8821A_2ANT_B_SCO_ESCO BIT1 +#define BT_INFO_8821A_2ANT_B_CONNECTION BIT0 + +#define BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT 2 + +enum _BT_INFO_SRC_8821A_2ANT { + BT_INFO_SRC_8821A_2ANT_WIFI_FW = 0x0, + BT_INFO_SRC_8821A_2ANT_BT_RSP = 0x1, + BT_INFO_SRC_8821A_2ANT_BT_ACTIVE_SEND = 0x2, + BT_INFO_SRC_8821A_2ANT_MAX +}; + +enum _BT_8821A_2ANT_BT_STATUS { + BT_8821A_2ANT_BT_STATUS_IDLE = 0x0, + BT_8821A_2ANT_BT_STATUS_CON_IDLE = 0x1, + BT_8821A_2ANT_BT_STATUS_NON_IDLE = 0x2, + BT_8821A_2ANT_BT_STATUS_MAX +}; + +enum _BT_8821A_2ANT_COEX_ALGO { + BT_8821A_2ANT_COEX_ALGO_UNDEFINED = 0x0, + BT_8821A_2ANT_COEX_ALGO_SCO = 0x1, + BT_8821A_2ANT_COEX_ALGO_HID = 0x2, + BT_8821A_2ANT_COEX_ALGO_A2DP = 0x3, + BT_8821A_2ANT_COEX_ALGO_A2DP_PANHS = 0x4, + BT_8821A_2ANT_COEX_ALGO_PANEDR = 0x5, + BT_8821A_2ANT_COEX_ALGO_PANHS = 0x6, + BT_8821A_2ANT_COEX_ALGO_PANEDR_A2DP = 0x7, + BT_8821A_2ANT_COEX_ALGO_PANEDR_HID = 0x8, + BT_8821A_2ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x9, + BT_8821A_2ANT_COEX_ALGO_HID_A2DP = 0xa, + BT_8821A_2ANT_COEX_ALGO_MAX = 0xb, +}; + +struct coex_dm_8821a_2ant { + /* fw mechanism */ + bool pre_dec_bt_pwr; + bool cur_dec_bt_pwr; + bool pre_bt_lna_constrain; + bool cur_bt_lna_constrain; + u8 pre_bt_psd_mode; + u8 cur_bt_psd_mode; + u8 pre_fw_dac_swing_lvl; + u8 cur_fw_dac_swing_lvl; + bool cur_ignore_wlan_act; + bool pre_ignore_wlan_act; + u8 pre_ps_tdma; + u8 cur_ps_tdma; + u8 ps_tdma_para[5]; + u8 tdma_adj_type; + bool reset_tdma_adjust; + bool pre_ps_tdma_on; + bool cur_ps_tdma_on; + bool pre_bt_auto_report; + bool cur_bt_auto_report; + + /* sw mechanism */ + bool pre_rf_rx_lpf_shrink; + bool cur_rf_rx_lpf_shrink; + u32 bt_rf0x1e_backup; + bool pre_low_penalty_ra; + bool cur_low_penalty_ra; + bool pre_dac_swing_on; + u32 pre_dac_swing_lvl; + bool cur_dac_swing_on; + u32 cur_dac_swing_lvl; + bool pre_adc_back_off; + bool cur_adc_back_off; + bool pre_agc_table_en; + bool cur_agc_table_en; + u32 pre_val0x6c0; + u32 cur_val0x6c0; + u32 pre_val0x6c4; + u32 cur_val0x6c4; + u32 pre_val0x6c8; + u32 cur_val0x6c8; + u8 pre_val0x6cc; + u8 cur_val0x6cc; + bool limited_dig; + + /* algorithm related */ + u8 pre_algorithm; + u8 cur_algorithm; + u8 bt_status; + u8 wifi_chnl_info[3]; +}; + +struct coex_sta_8821a_2ant { + bool bt_link_exist; + bool sco_exist; + bool a2dp_exist; + bool hid_exist; + bool pan_exist; + bool under_lps; + bool under_ips; + u32 high_priority_tx; + u32 high_priority_rx; + u32 low_priority_tx; + u32 low_priority_rx; + u8 bt_rssi; + u8 pre_bt_rssi_state; + u8 pre_wifi_rssi_state[4]; + bool c2h_bt_info_req_sent; + u8 bt_info_c2h[BT_INFO_SRC_8821A_2ANT_MAX][10]; + u32 bt_info_c2h_cnt[BT_INFO_SRC_8821A_2ANT_MAX]; + bool c2h_bt_inquiry_page; + u8 bt_retry_cnt; + u8 bt_info_ext; +}; + +/*=========================================== + * The following is interface which will notify coex module. + *=========================================== + */ +void +ex_halbtc8821a2ant_init_hwconfig( + struct btc_coexist *btcoexist + ); +void +ex_halbtc8821a2ant_init_coex_dm( + struct btc_coexist *btcoexist + ); +void +ex_halbtc8821a2ant_ips_notify( + struct btc_coexist *btcoexist, + u8 type + ); +void +ex_halbtc8821a2ant_lps_notify( + struct btc_coexist *btcoexist, + u8 type + ); +void +ex_halbtc8821a2ant_scan_notify( + struct btc_coexist *btcoexist, + u8 type + ); +void +ex_halbtc8821a2ant_connect_notify( + struct btc_coexist *btcoexist, + u8 type + ); +void +ex_halbtc8821a2ant_media_status_notify( + struct btc_coexist *btcoexist, + u8 type + ); +void +ex_halbtc8821a2ant_special_packet_notify( + struct btc_coexist *btcoexist, + u8 type + ); +void +ex_halbtc8821a2ant_bt_info_notify( + struct btc_coexist *btcoexist, + u8 *tmp_buf, + u8 length + ); +void +ex_halbtc8821a2ant_halt_notify( + struct btc_coexist *btcoexist + ); +void +ex_halbtc8821a2ant_periodical( + struct btc_coexist *btcoexist + ); +void +ex_halbtc8821a2ant_display_coex_info( + struct btc_coexist *btcoexist + ); diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c new file mode 100644 index 000000000000..b2791c893417 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c @@ -0,0 +1,987 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + ******************************************************************************/ + +#include "halbt_precomp.h" + +/*********************************************** + * Global variables + ***********************************************/ + +struct btc_coexist gl_bt_coexist; + +u32 btc_dbg_type[BTC_MSG_MAX]; + +/*************************************************** + * Debug related function + ***************************************************/ +static bool halbtc_is_bt_coexist_available(struct btc_coexist *btcoexist) +{ + if (!btcoexist->binded || NULL == btcoexist->adapter) + return false; + + return true; +} + +static bool halbtc_is_wifi_busy(struct rtl_priv *rtlpriv) +{ + if (rtlpriv->link_info.busytraffic) + return true; + else + return false; +} + +static void halbtc_dbg_init(void) +{ + u8 i; + + for (i = 0; i < BTC_MSG_MAX; i++) + btc_dbg_type[i] = 0; + + btc_dbg_type[BTC_MSG_INTERFACE] = +/* INTF_INIT | */ +/* INTF_NOTIFY | */ + 0; + + btc_dbg_type[BTC_MSG_ALGORITHM] = +/* ALGO_BT_RSSI_STATE | */ +/* ALGO_WIFI_RSSI_STATE | */ +/* ALGO_BT_MONITOR | */ +/* ALGO_TRACE | */ +/* ALGO_TRACE_FW | */ +/* ALGO_TRACE_FW_DETAIL | */ +/* ALGO_TRACE_FW_EXEC | */ +/* ALGO_TRACE_SW | */ +/* ALGO_TRACE_SW_DETAIL | */ +/* ALGO_TRACE_SW_EXEC | */ + 0; +} + +static bool halbtc_is_bt40(struct rtl_priv *adapter) +{ + struct rtl_priv *rtlpriv = adapter; + struct rtl_phy *rtlphy = &(rtlpriv->phy); + bool is_ht40 = true; + enum ht_channel_width bw = rtlphy->current_chan_bw; + + if (bw == HT_CHANNEL_WIDTH_20) + is_ht40 = false; + else if (bw == HT_CHANNEL_WIDTH_20_40) + is_ht40 = true; + + return is_ht40; +} + +static bool halbtc_legacy(struct rtl_priv *adapter) +{ + struct rtl_priv *rtlpriv = adapter; + struct rtl_mac *mac = rtl_mac(rtlpriv); + + bool is_legacy = false; + + if ((mac->mode == WIRELESS_MODE_B) || (mac->mode == WIRELESS_MODE_G)) + is_legacy = true; + + return is_legacy; +} + +bool halbtc_is_wifi_uplink(struct rtl_priv *adapter) +{ + struct rtl_priv *rtlpriv = adapter; + + if (rtlpriv->link_info.tx_busy_traffic) + return true; + else + return false; +} + +static u32 halbtc_get_wifi_bw(struct btc_coexist *btcoexist) +{ + struct rtl_priv *rtlpriv = + (struct rtl_priv *)btcoexist->adapter; + u32 wifi_bw = BTC_WIFI_BW_HT20; + + if (halbtc_is_bt40(rtlpriv)) { + wifi_bw = BTC_WIFI_BW_HT40; + } else { + if (halbtc_legacy(rtlpriv)) + wifi_bw = BTC_WIFI_BW_LEGACY; + else + wifi_bw = BTC_WIFI_BW_HT20; + } + return wifi_bw; +} + +static u8 halbtc_get_wifi_central_chnl(struct btc_coexist *btcoexist) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u8 chnl = 1; + + if (rtlphy->current_channel != 0) + chnl = rtlphy->current_channel; + BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, + "static halbtc_get_wifi_central_chnl:%d\n", chnl); + return chnl; +} + +static void halbtc_leave_lps(struct btc_coexist *btcoexist) +{ + struct rtl_priv *rtlpriv; + struct rtl_ps_ctl *ppsc; + bool ap_enable = false; + + rtlpriv = btcoexist->adapter; + ppsc = rtl_psc(rtlpriv); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, + &ap_enable); + + if (ap_enable) { + pr_info("halbtc_leave_lps()<--dont leave lps under AP mode\n"); + return; + } + + btcoexist->bt_info.bt_ctrl_lps = true; + btcoexist->bt_info.bt_lps_on = false; +} + +static void halbtc_enter_lps(struct btc_coexist *btcoexist) +{ + struct rtl_priv *rtlpriv; + struct rtl_ps_ctl *ppsc; + bool ap_enable = false; + + rtlpriv = btcoexist->adapter; + ppsc = rtl_psc(rtlpriv); + + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, + &ap_enable); + + if (ap_enable) { + pr_info("halbtc_enter_lps()<--dont enter lps under AP mode\n"); + return; + } + + btcoexist->bt_info.bt_ctrl_lps = true; + btcoexist->bt_info.bt_lps_on = false; +} + +static void halbtc_normal_lps(struct btc_coexist *btcoexist) +{ + if (btcoexist->bt_info.bt_ctrl_lps) { + btcoexist->bt_info.bt_lps_on = false; + btcoexist->bt_info.bt_ctrl_lps = false; + } +} + +static void halbtc_leave_low_power(void) +{ +} + +static void halbtc_nomal_low_power(void) +{ +} + +static void halbtc_disable_low_power(void) +{ +} + +static void halbtc_aggregation_check(void) +{ +} + +static u32 halbtc_get_bt_patch_version(struct btc_coexist *btcoexist) +{ + return 0; +} + +static s32 halbtc_get_wifi_rssi(struct rtl_priv *adapter) +{ + struct rtl_priv *rtlpriv = adapter; + s32 undec_sm_pwdb = 0; + + if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; + else /* associated entry pwdb */ + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; + return undec_sm_pwdb; +} + +static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)void_btcoexist; + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtlpriv); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + bool *bool_tmp = (bool *)out_buf; + int *s32_tmp = (int *)out_buf; + u32 *u32_tmp = (u32 *)out_buf; + u8 *u8_tmp = (u8 *)out_buf; + bool tmp = false; + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return false; + + switch (get_type) { + case BTC_GET_BL_HS_OPERATION: + *bool_tmp = false; + break; + case BTC_GET_BL_HS_CONNECTING: + *bool_tmp = false; + break; + case BTC_GET_BL_WIFI_CONNECTED: + if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) + tmp = true; + *bool_tmp = tmp; + break; + case BTC_GET_BL_WIFI_BUSY: + if (halbtc_is_wifi_busy(rtlpriv)) + *bool_tmp = true; + else + *bool_tmp = false; + break; + case BTC_GET_BL_WIFI_SCAN: + if (mac->act_scanning) + *bool_tmp = true; + else + *bool_tmp = false; + break; + case BTC_GET_BL_WIFI_LINK: + if (mac->link_state == MAC80211_LINKING) + *bool_tmp = true; + else + *bool_tmp = false; + break; + case BTC_GET_BL_WIFI_ROAM: /*TODO*/ + if (mac->link_state == MAC80211_LINKING) + *bool_tmp = true; + else + *bool_tmp = false; + break; + case BTC_GET_BL_WIFI_4_WAY_PROGRESS: /*TODO*/ + *bool_tmp = false; + + break; + case BTC_GET_BL_WIFI_UNDER_5G: + *bool_tmp = false; /*TODO*/ + + case BTC_GET_BL_WIFI_DHCP: /*TODO*/ + break; + case BTC_GET_BL_WIFI_SOFTAP_IDLE: + *bool_tmp = true; + break; + case BTC_GET_BL_WIFI_SOFTAP_LINKING: + *bool_tmp = false; + break; + case BTC_GET_BL_WIFI_IN_EARLY_SUSPEND: + *bool_tmp = false; + break; + case BTC_GET_BL_WIFI_AP_MODE_ENABLE: + *bool_tmp = false; + break; + case BTC_GET_BL_WIFI_ENABLE_ENCRYPTION: + if (NO_ENCRYPTION == rtlpriv->sec.pairwise_enc_algorithm) + *bool_tmp = false; + else + *bool_tmp = true; + break; + case BTC_GET_BL_WIFI_UNDER_B_MODE: + *bool_tmp = false; /*TODO*/ + break; + case BTC_GET_BL_EXT_SWITCH: + *bool_tmp = false; + break; + case BTC_GET_S4_WIFI_RSSI: + *s32_tmp = halbtc_get_wifi_rssi(rtlpriv); + break; + case BTC_GET_S4_HS_RSSI: /*TODO*/ + *s32_tmp = halbtc_get_wifi_rssi(rtlpriv); + break; + case BTC_GET_U4_WIFI_BW: + *u32_tmp = halbtc_get_wifi_bw(btcoexist); + break; + case BTC_GET_U4_WIFI_TRAFFIC_DIRECTION: + if (halbtc_is_wifi_uplink(rtlpriv)) + *u32_tmp = BTC_WIFI_TRAFFIC_TX; + else + *u32_tmp = BTC_WIFI_TRAFFIC_RX; + break; + case BTC_GET_U4_WIFI_FW_VER: + *u32_tmp = rtlhal->fw_version; + break; + case BTC_GET_U4_BT_PATCH_VER: + *u32_tmp = halbtc_get_bt_patch_version(btcoexist); + break; + case BTC_GET_U1_WIFI_DOT11_CHNL: + *u8_tmp = rtlphy->current_channel; + break; + case BTC_GET_U1_WIFI_CENTRAL_CHNL: + *u8_tmp = halbtc_get_wifi_central_chnl(btcoexist); + break; + case BTC_GET_U1_WIFI_HS_CHNL: + *u8_tmp = 1;/*BT_OperateChnl(rtlpriv);*/ + break; + case BTC_GET_U1_MAC_PHY_MODE: + *u8_tmp = BTC_MP_UNKNOWN; + break; + + /************* 1Ant **************/ + case BTC_GET_U1_LPS_MODE: + *u8_tmp = btcoexist->pwr_mode_val[0]; + break; + + default: + break; + } + + return true; +} + +static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)void_btcoexist; + bool *bool_tmp = (bool *)in_buf; + u8 *u8_tmp = (u8 *)in_buf; + u32 *u32_tmp = (u32 *)in_buf; + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return false; + + switch (set_type) { + /* set some bool type variables. */ + case BTC_SET_BL_BT_DISABLE: + btcoexist->bt_info.bt_disabled = *bool_tmp; + break; + case BTC_SET_BL_BT_TRAFFIC_BUSY: + btcoexist->bt_info.bt_busy = *bool_tmp; + break; + case BTC_SET_BL_BT_LIMITED_DIG: + btcoexist->bt_info.limited_dig = *bool_tmp; + break; + case BTC_SET_BL_FORCE_TO_ROAM: + btcoexist->bt_info.force_to_roam = *bool_tmp; + break; + case BTC_SET_BL_TO_REJ_AP_AGG_PKT: + btcoexist->bt_info.reject_agg_pkt = *bool_tmp; + break; + case BTC_SET_BL_BT_CTRL_AGG_SIZE: + btcoexist->bt_info.bt_ctrl_buf_size = *bool_tmp; + break; + case BTC_SET_BL_INC_SCAN_DEV_NUM: + btcoexist->bt_info.increase_scan_dev_num = *bool_tmp; + break; + /* set some u1Byte type variables. */ + case BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON: + btcoexist->bt_info.rssi_adjust_for_agc_table_on = *u8_tmp; + break; + case BTC_SET_U1_AGG_BUF_SIZE: + btcoexist->bt_info.agg_buf_size = *u8_tmp; + break; + /* the following are some action which will be triggered */ + case BTC_SET_ACT_GET_BT_RSSI: + /*BTHCI_SendGetBtRssiEvent(rtlpriv);*/ + break; + case BTC_SET_ACT_AGGREGATE_CTRL: + halbtc_aggregation_check(); + break; + + /* 1Ant */ + case BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE: + btcoexist->bt_info.rssi_adjust_for_1ant_coex_type = *u8_tmp; + break; + case BTC_SET_UI_SCAN_SIG_COMPENSATION: + /* rtlpriv->mlmepriv.scan_compensation = *u8_tmp; */ + break; + case BTC_SET_U1_1ANT_LPS: + btcoexist->bt_info.lps_val = *u8_tmp; + break; + case BTC_SET_U1_1ANT_RPWM: + btcoexist->bt_info.rpwm_val = *u8_tmp; + break; + /* the following are some action which will be triggered */ + case BTC_SET_ACT_LEAVE_LPS: + halbtc_leave_lps(btcoexist); + break; + case BTC_SET_ACT_ENTER_LPS: + halbtc_enter_lps(btcoexist); + break; + case BTC_SET_ACT_NORMAL_LPS: + halbtc_normal_lps(btcoexist); + break; + case BTC_SET_ACT_DISABLE_LOW_POWER: + halbtc_disable_low_power(); + break; + case BTC_SET_ACT_UPDATE_ra_mask: + btcoexist->bt_info.ra_mask = *u32_tmp; + break; + case BTC_SET_ACT_SEND_MIMO_PS: + break; + case BTC_SET_ACT_INC_FORCE_EXEC_PWR_CMD_CNT: + btcoexist->bt_info.force_exec_pwr_cmd_cnt++; + break; + case BTC_SET_ACT_CTRL_BT_INFO: /*wait for 8812/8821*/ + break; + case BTC_SET_ACT_CTRL_BT_COEX: + break; + default: + break; + } + + return true; +} + +static void halbtc_display_coex_statistics(struct btc_coexist *btcoexist) +{ +} + +static void halbtc_display_bt_link_info(struct btc_coexist *btcoexist) +{ +} + +static void halbtc_display_bt_fw_info(struct btc_coexist *btcoexist) +{ +} + +static void halbtc_display_fw_pwr_mode_cmd(struct btc_coexist *btcoexist) +{ +} + +/************************************************************ + * IO related function + ************************************************************/ +static u8 halbtc_read_1byte(void *bt_context, u32 reg_addr) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; + struct rtl_priv *rtlpriv = btcoexist->adapter; + + return rtl_read_byte(rtlpriv, reg_addr); +} + +static u16 halbtc_read_2byte(void *bt_context, u32 reg_addr) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; + struct rtl_priv *rtlpriv = btcoexist->adapter; + + return rtl_read_word(rtlpriv, reg_addr); +} + +static u32 halbtc_read_4byte(void *bt_context, u32 reg_addr) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; + struct rtl_priv *rtlpriv = btcoexist->adapter; + + return rtl_read_dword(rtlpriv, reg_addr); +} + +static void halbtc_write_1byte(void *bt_context, u32 reg_addr, u32 data) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; + struct rtl_priv *rtlpriv = btcoexist->adapter; + + rtl_write_byte(rtlpriv, reg_addr, data); +} + +static void halbtc_bitmask_write_1byte(void *bt_context, u32 reg_addr, + u32 bit_mask, u8 data) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; + struct rtl_priv *rtlpriv = btcoexist->adapter; + u8 original_value, bit_shift = 0; + u8 i; + + if (bit_mask != MASKDWORD) {/*if not "double word" write*/ + original_value = rtl_read_byte(rtlpriv, reg_addr); + for (i = 0; i <= 7; i++) { + if ((bit_mask>>i) & 0x1) + break; + } + bit_shift = i; + data = (original_value & (~bit_mask)) | + ((data << bit_shift) & bit_mask); + } + rtl_write_byte(rtlpriv, reg_addr, data); +} + +static void halbtc_write_2byte(void *bt_context, u32 reg_addr, u16 data) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; + struct rtl_priv *rtlpriv = btcoexist->adapter; + + rtl_write_word(rtlpriv, reg_addr, data); +} + +static void halbtc_write_4byte(void *bt_context, u32 reg_addr, u32 data) +{ + struct btc_coexist *btcoexist = + (struct btc_coexist *)bt_context; + struct rtl_priv *rtlpriv = btcoexist->adapter; + + rtl_write_dword(rtlpriv, reg_addr, data); +} + +static void halbtc_set_bbreg(void *bt_context, u32 reg_addr, u32 bit_mask, + u32 data) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; + struct rtl_priv *rtlpriv = btcoexist->adapter; + + rtl_set_bbreg(rtlpriv->mac80211.hw, reg_addr, bit_mask, data); +} + +static u32 halbtc_get_bbreg(void *bt_context, u32 reg_addr, u32 bit_mask) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; + struct rtl_priv *rtlpriv = btcoexist->adapter; + + return rtl_get_bbreg(rtlpriv->mac80211.hw, reg_addr, bit_mask); +} + +static void halbtc_set_rfreg(void *bt_context, u8 rf_path, u32 reg_addr, + u32 bit_mask, u32 data) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; + struct rtl_priv *rtlpriv = btcoexist->adapter; + + rtl_set_rfreg(rtlpriv->mac80211.hw, rf_path, reg_addr, bit_mask, data); +} + +static u32 halbtc_get_rfreg(void *bt_context, u8 rf_path, u32 reg_addr, + u32 bit_mask) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; + struct rtl_priv *rtlpriv = btcoexist->adapter; + + return rtl_get_rfreg(rtlpriv->mac80211.hw, rf_path, reg_addr, bit_mask); +} + +static void halbtc_fill_h2c_cmd(void *bt_context, u8 element_id, + u32 cmd_len, u8 *cmd_buf) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; + struct rtl_priv *rtlpriv = btcoexist->adapter; + + rtlpriv->cfg->ops->fill_h2c_cmd(rtlpriv->mac80211.hw, element_id, + cmd_len, cmd_buf); +} + +static void halbtc_display_dbg_msg(void *bt_context, u8 disp_type) +{ + struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; + switch (disp_type) { + case BTC_DBG_DISP_COEX_STATISTICS: + halbtc_display_coex_statistics(btcoexist); + break; + case BTC_DBG_DISP_BT_LINK_INFO: + halbtc_display_bt_link_info(btcoexist); + break; + case BTC_DBG_DISP_BT_FW_VER: + halbtc_display_bt_fw_info(btcoexist); + break; + case BTC_DBG_DISP_FW_PWR_MODE_CMD: + halbtc_display_fw_pwr_mode_cmd(btcoexist); + break; + default: + break; + } +} + +/***************************************************************** + * Extern functions called by other module + *****************************************************************/ +bool exhalbtc_initlize_variables(struct rtl_priv *adapter) +{ + struct btc_coexist *btcoexist = &gl_bt_coexist; + + btcoexist->statistics.cnt_bind++; + + halbtc_dbg_init(); + + if (btcoexist->binded) + return false; + else + btcoexist->binded = true; + + btcoexist->chip_interface = BTC_INTF_UNKNOWN; + + if (NULL == btcoexist->adapter) + btcoexist->adapter = adapter; + + btcoexist->stack_info.profile_notified = false; + + btcoexist->btc_read_1byte = halbtc_read_1byte; + btcoexist->btc_write_1byte = halbtc_write_1byte; + btcoexist->btc_write_1byte_bitmask = halbtc_bitmask_write_1byte; + btcoexist->btc_read_2byte = halbtc_read_2byte; + btcoexist->btc_write_2byte = halbtc_write_2byte; + btcoexist->btc_read_4byte = halbtc_read_4byte; + btcoexist->btc_write_4byte = halbtc_write_4byte; + + btcoexist->btc_set_bb_reg = halbtc_set_bbreg; + btcoexist->btc_get_bb_reg = halbtc_get_bbreg; + + btcoexist->btc_set_rf_reg = halbtc_set_rfreg; + btcoexist->btc_get_rf_reg = halbtc_get_rfreg; + + btcoexist->btc_fill_h2c = halbtc_fill_h2c_cmd; + btcoexist->btc_disp_dbg_msg = halbtc_display_dbg_msg; + + btcoexist->btc_get = halbtc_get; + btcoexist->btc_set = halbtc_set; + + btcoexist->bt_info.bt_ctrl_buf_size = false; + btcoexist->bt_info.agg_buf_size = 5; + + btcoexist->bt_info.increase_scan_dev_num = false; + return true; +} + +void exhalbtc_init_hw_config(struct btc_coexist *btcoexist) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + + btcoexist->statistics.cnt_init_hw_config++; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) + ex_btc8723b2ant_init_hwconfig(btcoexist); +} + +void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + + btcoexist->statistics.cnt_init_coex_dm++; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) + ex_btc8723b2ant_init_coex_dm(btcoexist); + + btcoexist->initilized = true; +} + +void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 ips_type; + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + btcoexist->statistics.cnt_ips_notify++; + if (btcoexist->manual_control) + return; + + if (ERFOFF == type) + ips_type = BTC_IPS_ENTER; + else + ips_type = BTC_IPS_LEAVE; + + halbtc_leave_low_power(); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) + ex_btc8723b2ant_ips_notify(btcoexist, ips_type); + + halbtc_nomal_low_power(); +} + +void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 lps_type; + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + btcoexist->statistics.cnt_lps_notify++; + if (btcoexist->manual_control) + return; + + if (EACTIVE == type) + lps_type = BTC_LPS_DISABLE; + else + lps_type = BTC_LPS_ENABLE; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) + ex_btc8723b2ant_lps_notify(btcoexist, lps_type); +} + +void exhalbtc_scan_notify(struct btc_coexist *btcoexist, u8 type) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 scan_type; + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + btcoexist->statistics.cnt_scan_notify++; + if (btcoexist->manual_control) + return; + + if (type) + scan_type = BTC_SCAN_START; + else + scan_type = BTC_SCAN_FINISH; + + halbtc_leave_low_power(); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) + ex_btc8723b2ant_scan_notify(btcoexist, scan_type); + + halbtc_nomal_low_power(); +} + +void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 asso_type; + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + btcoexist->statistics.cnt_connect_notify++; + if (btcoexist->manual_control) + return; + + if (action) + asso_type = BTC_ASSOCIATE_START; + else + asso_type = BTC_ASSOCIATE_FINISH; + + halbtc_leave_low_power(); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) + ex_btc8723b2ant_connect_notify(btcoexist, asso_type); +} + +void exhalbtc_mediastatus_notify(struct btc_coexist *btcoexist, + enum rt_media_status media_status) +{ + u8 status; + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + btcoexist->statistics.cnt_media_status_notify++; + if (btcoexist->manual_control) + return; + + if (RT_MEDIA_CONNECT == media_status) + status = BTC_MEDIA_CONNECT; + else + status = BTC_MEDIA_DISCONNECT; + + halbtc_leave_low_power(); + + halbtc_nomal_low_power(); +} + +void exhalbtc_special_packet_notify(struct btc_coexist *btcoexist, u8 pkt_type) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 packet_type; + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + btcoexist->statistics.cnt_special_packet_notify++; + if (btcoexist->manual_control) + return; + + packet_type = BTC_PACKET_DHCP; + + halbtc_leave_low_power(); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) + ex_btc8723b2ant_special_packet_notify(btcoexist, + packet_type); + + halbtc_nomal_low_power(); +} + +void exhalbtc_bt_info_notify(struct btc_coexist *btcoexist, + u8 *tmp_buf, u8 length) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + btcoexist->statistics.cnt_bt_info_notify++; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) + ex_btc8723b2ant_bt_info_notify(btcoexist, tmp_buf, length); +} + +void exhalbtc_stack_operation_notify(struct btc_coexist *btcoexist, u8 type) +{ + u8 stack_op_type; + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + btcoexist->statistics.cnt_stack_operation_notify++; + if (btcoexist->manual_control) + return; + + stack_op_type = BTC_STACK_OP_NONE; + + halbtc_leave_low_power(); + + halbtc_nomal_low_power(); +} + +void exhalbtc_halt_notify(struct btc_coexist *btcoexist) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) + ex_btc8723b2ant_halt_notify(btcoexist); +} + +void exhalbtc_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state) +{ + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; +} + +void exhalbtc_periodical(struct btc_coexist *btcoexist) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + btcoexist->statistics.cnt_periodical++; + + halbtc_leave_low_power(); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) + ex_btc8723b2ant_periodical(btcoexist); + + halbtc_nomal_low_power(); +} + +void exhalbtc_dbg_control(struct btc_coexist *btcoexist, + u8 code, u8 len, u8 *data) +{ + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + btcoexist->statistics.cnt_dbg_ctrl++; +} + +void exhalbtc_stack_update_profile_info(void) +{ +} + +void exhalbtc_update_min_bt_rssi(char bt_rssi) +{ + struct btc_coexist *btcoexist = &gl_bt_coexist; + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + + btcoexist->stack_info.min_bt_rssi = bt_rssi; +} + +void exhalbtc_set_hci_version(u16 hci_version) +{ + struct btc_coexist *btcoexist = &gl_bt_coexist; + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + + btcoexist->stack_info.hci_version = hci_version; +} + +void exhalbtc_set_bt_patch_version(u16 bt_hci_version, u16 bt_patch_version) +{ + struct btc_coexist *btcoexist = &gl_bt_coexist; + + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + + btcoexist->bt_info.bt_real_fw_ver = bt_patch_version; + btcoexist->bt_info.bt_hci_ver = bt_hci_version; +} + +void exhalbtc_set_bt_exist(bool bt_exist) +{ + gl_bt_coexist.board_info.bt_exist = bt_exist; +} + +void exhalbtc_set_chip_type(u8 chip_type) +{ + switch (chip_type) { + default: + case BT_2WIRE: + case BT_ISSC_3WIRE: + case BT_ACCEL: + case BT_RTL8756: + gl_bt_coexist.board_info.bt_chip_type = BTC_CHIP_UNDEF; + break; + case BT_CSR_BC4: + gl_bt_coexist.board_info.bt_chip_type = BTC_CHIP_CSR_BC4; + break; + case BT_CSR_BC8: + gl_bt_coexist.board_info.bt_chip_type = BTC_CHIP_CSR_BC8; + break; + case BT_RTL8723A: + gl_bt_coexist.board_info.bt_chip_type = BTC_CHIP_RTL8723A; + break; + case BT_RTL8821A: + gl_bt_coexist.board_info.bt_chip_type = BTC_CHIP_RTL8821; + break; + case BT_RTL8723B: + gl_bt_coexist.board_info.bt_chip_type = BTC_CHIP_RTL8723B; + break; + } +} + +void exhalbtc_set_ant_num(u8 type, u8 ant_num) +{ + if (BT_COEX_ANT_TYPE_PG == type) { + gl_bt_coexist.board_info.pg_ant_num = ant_num; + gl_bt_coexist.board_info.btdm_ant_num = ant_num; + } else if (BT_COEX_ANT_TYPE_ANTDIV == type) { + gl_bt_coexist.board_info.btdm_ant_num = ant_num; + } +} + +void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + if (!halbtc_is_bt_coexist_available(btcoexist)) + return; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) + ex_btc8723b2ant_display_coex_info(btcoexist); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h new file mode 100644 index 000000000000..0a903ea179ef --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h @@ -0,0 +1,545 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __HALBTC_OUT_SRC_H__ +#define __HALBTC_OUT_SRC_H__ + +#include "../wifi.h" + +#define NORMAL_EXEC false +#define FORCE_EXEC true + +#define BTC_RF_A RF90_PATH_A +#define BTC_RF_B RF90_PATH_B +#define BTC_RF_C RF90_PATH_C +#define BTC_RF_D RF90_PATH_D + +#define BTC_SMSP SINGLEMAC_SINGLEPHY +#define BTC_DMDP DUALMAC_DUALPHY +#define BTC_DMSP DUALMAC_SINGLEPHY +#define BTC_MP_UNKNOWN 0xff + +#define IN +#define OUT + +#define BT_TMP_BUF_SIZE 100 + +#define BT_COEX_ANT_TYPE_PG 0 +#define BT_COEX_ANT_TYPE_ANTDIV 1 +#define BT_COEX_ANT_TYPE_DETECTED 2 + +#define BTC_MIMO_PS_STATIC 0 +#define BTC_MIMO_PS_DYNAMIC 1 + +#define BTC_RATE_DISABLE 0 +#define BTC_RATE_ENABLE 1 + +/* single Antenna definition */ +#define BTC_ANT_PATH_WIFI 0 +#define BTC_ANT_PATH_BT 1 +#define BTC_ANT_PATH_PTA 2 +/* dual Antenna definition */ +#define BTC_ANT_WIFI_AT_MAIN 0 +#define BTC_ANT_WIFI_AT_AUX 1 +/* coupler Antenna definition */ +#define BTC_ANT_WIFI_AT_CPL_MAIN 0 +#define BTC_ANT_WIFI_AT_CPL_AUX 1 + +enum btc_chip_interface { + BTC_INTF_UNKNOWN = 0, + BTC_INTF_PCI = 1, + BTC_INTF_USB = 2, + BTC_INTF_SDIO = 3, + BTC_INTF_GSPI = 4, + BTC_INTF_MAX +}; + +enum btc_chip_type { + BTC_CHIP_UNDEF = 0, + BTC_CHIP_CSR_BC4 = 1, + BTC_CHIP_CSR_BC8 = 2, + BTC_CHIP_RTL8723A = 3, + BTC_CHIP_RTL8821 = 4, + BTC_CHIP_RTL8723B = 5, + BTC_CHIP_MAX +}; + +enum btc_msg_type { + BTC_MSG_INTERFACE = 0x0, + BTC_MSG_ALGORITHM = 0x1, + BTC_MSG_MAX +}; + +extern u32 btc_dbg_type[]; + +/* following is for BTC_MSG_INTERFACE */ +#define INTF_INIT BIT0 +#define INTF_NOTIFY BIT2 + +/* following is for BTC_ALGORITHM */ +#define ALGO_BT_RSSI_STATE BIT0 +#define ALGO_WIFI_RSSI_STATE BIT1 +#define ALGO_BT_MONITOR BIT2 +#define ALGO_TRACE BIT3 +#define ALGO_TRACE_FW BIT4 +#define ALGO_TRACE_FW_DETAIL BIT5 +#define ALGO_TRACE_FW_EXEC BIT6 +#define ALGO_TRACE_SW BIT7 +#define ALGO_TRACE_SW_DETAIL BIT8 +#define ALGO_TRACE_SW_EXEC BIT9 + +/* following is for wifi link status */ +#define WIFI_STA_CONNECTED BIT0 +#define WIFI_AP_CONNECTED BIT1 +#define WIFI_HS_CONNECTED BIT2 +#define WIFI_P2P_GO_CONNECTED BIT3 +#define WIFI_P2P_GC_CONNECTED BIT4 + +#define BTC_PRINT(dbgtype, dbgflag, printstr, ...) \ + do { \ + if (unlikely(btc_dbg_type[dbgtype] & dbgflag)) {\ + printk(printstr, ##__VA_ARGS__); \ + } \ + } while (0) + +#define BTC_RSSI_HIGH(_rssi_) \ + ((_rssi_ == BTC_RSSI_STATE_HIGH || \ + _rssi_ == BTC_RSSI_STATE_STAY_HIGH) ? true : false) +#define BTC_RSSI_MEDIUM(_rssi_) \ + ((_rssi_ == BTC_RSSI_STATE_MEDIUM || \ + _rssi_ == BTC_RSSI_STATE_STAY_MEDIUM) ? true : false) +#define BTC_RSSI_LOW(_rssi_) \ + ((_rssi_ == BTC_RSSI_STATE_LOW || \ + _rssi_ == BTC_RSSI_STATE_STAY_LOW) ? true : false) + +enum btc_power_save_type { + BTC_PS_WIFI_NATIVE = 0, + BTC_PS_LPS_ON = 1, + BTC_PS_LPS_OFF = 2, + BTC_PS_LPS_MAX +}; + +struct btc_board_info { + /* The following is some board information */ + u8 bt_chip_type; + u8 pg_ant_num; /* pg ant number */ + u8 btdm_ant_num; /* ant number for btdm */ + u8 btdm_ant_pos; + bool bt_exist; +}; + +enum btc_dbg_opcode { + BTC_DBG_SET_COEX_NORMAL = 0x0, + BTC_DBG_SET_COEX_WIFI_ONLY = 0x1, + BTC_DBG_SET_COEX_BT_ONLY = 0x2, + BTC_DBG_MAX +}; + +enum btc_rssi_state { + BTC_RSSI_STATE_HIGH = 0x0, + BTC_RSSI_STATE_MEDIUM = 0x1, + BTC_RSSI_STATE_LOW = 0x2, + BTC_RSSI_STATE_STAY_HIGH = 0x3, + BTC_RSSI_STATE_STAY_MEDIUM = 0x4, + BTC_RSSI_STATE_STAY_LOW = 0x5, + BTC_RSSI_MAX +}; + +enum btc_wifi_role { + BTC_ROLE_STATION = 0x0, + BTC_ROLE_AP = 0x1, + BTC_ROLE_IBSS = 0x2, + BTC_ROLE_HS_MODE = 0x3, + BTC_ROLE_MAX +}; + +enum btc_wifi_bw_mode { + BTC_WIFI_BW_LEGACY = 0x0, + BTC_WIFI_BW_HT20 = 0x1, + BTC_WIFI_BW_HT40 = 0x2, + BTC_WIFI_BW_MAX +}; + +enum btc_wifi_traffic_dir { + BTC_WIFI_TRAFFIC_TX = 0x0, + BTC_WIFI_TRAFFIC_RX = 0x1, + BTC_WIFI_TRAFFIC_MAX +}; + +enum btc_wifi_pnp { + BTC_WIFI_PNP_WAKE_UP = 0x0, + BTC_WIFI_PNP_SLEEP = 0x1, + BTC_WIFI_PNP_MAX +}; + +enum btc_get_type { + /* type bool */ + BTC_GET_BL_HS_OPERATION, + BTC_GET_BL_HS_CONNECTING, + BTC_GET_BL_WIFI_CONNECTED, + BTC_GET_BL_WIFI_BUSY, + BTC_GET_BL_WIFI_SCAN, + BTC_GET_BL_WIFI_LINK, + BTC_GET_BL_WIFI_DHCP, + BTC_GET_BL_WIFI_SOFTAP_IDLE, + BTC_GET_BL_WIFI_SOFTAP_LINKING, + BTC_GET_BL_WIFI_IN_EARLY_SUSPEND, + BTC_GET_BL_WIFI_ROAM, + BTC_GET_BL_WIFI_4_WAY_PROGRESS, + BTC_GET_BL_WIFI_UNDER_5G, + BTC_GET_BL_WIFI_AP_MODE_ENABLE, + BTC_GET_BL_WIFI_ENABLE_ENCRYPTION, + BTC_GET_BL_WIFI_UNDER_B_MODE, + BTC_GET_BL_EXT_SWITCH, + + /* type s4Byte */ + BTC_GET_S4_WIFI_RSSI, + BTC_GET_S4_HS_RSSI, + + /* type u32 */ + BTC_GET_U4_WIFI_BW, + BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, + BTC_GET_U4_WIFI_FW_VER, + BTC_GET_U4_WIFI_LINK_STATUS, + BTC_GET_U4_BT_PATCH_VER, + + /* type u1Byte */ + BTC_GET_U1_WIFI_DOT11_CHNL, + BTC_GET_U1_WIFI_CENTRAL_CHNL, + BTC_GET_U1_WIFI_HS_CHNL, + BTC_GET_U1_MAC_PHY_MODE, + BTC_GET_U1_AP_NUM, + + /* for 1Ant */ + BTC_GET_U1_LPS_MODE, + BTC_GET_BL_BT_SCO_BUSY, + + /* for test mode */ + BTC_GET_DRIVER_TEST_CFG, + BTC_GET_MAX +}; + +enum btc_set_type { + /* type bool */ + BTC_SET_BL_BT_DISABLE, + BTC_SET_BL_BT_TRAFFIC_BUSY, + BTC_SET_BL_BT_LIMITED_DIG, + BTC_SET_BL_FORCE_TO_ROAM, + BTC_SET_BL_TO_REJ_AP_AGG_PKT, + BTC_SET_BL_BT_CTRL_AGG_SIZE, + BTC_SET_BL_INC_SCAN_DEV_NUM, + + /* type u1Byte */ + BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON, + BTC_SET_UI_SCAN_SIG_COMPENSATION, + BTC_SET_U1_AGG_BUF_SIZE, + + /* type trigger some action */ + BTC_SET_ACT_GET_BT_RSSI, + BTC_SET_ACT_AGGREGATE_CTRL, + + /********* for 1Ant **********/ + /* type bool */ + BTC_SET_BL_BT_SCO_BUSY, + /* type u1Byte */ + BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE, + BTC_SET_U1_LPS_VAL, + BTC_SET_U1_RPWM_VAL, + BTC_SET_U1_1ANT_LPS, + BTC_SET_U1_1ANT_RPWM, + /* type trigger some action */ + BTC_SET_ACT_LEAVE_LPS, + BTC_SET_ACT_ENTER_LPS, + BTC_SET_ACT_NORMAL_LPS, + BTC_SET_ACT_INC_FORCE_EXEC_PWR_CMD_CNT, + BTC_SET_ACT_DISABLE_LOW_POWER, + BTC_SET_ACT_UPDATE_ra_mask, + BTC_SET_ACT_SEND_MIMO_PS, + /* BT Coex related */ + BTC_SET_ACT_CTRL_BT_INFO, + BTC_SET_ACT_CTRL_BT_COEX, + /***************************/ + BTC_SET_MAX +}; + +enum btc_dbg_disp_type { + BTC_DBG_DISP_COEX_STATISTICS = 0x0, + BTC_DBG_DISP_BT_LINK_INFO = 0x1, + BTC_DBG_DISP_BT_FW_VER = 0x2, + BTC_DBG_DISP_FW_PWR_MODE_CMD = 0x3, + BTC_DBG_DISP_MAX +}; + +enum btc_notify_type_ips { + BTC_IPS_LEAVE = 0x0, + BTC_IPS_ENTER = 0x1, + BTC_IPS_MAX +}; + +enum btc_notify_type_lps { + BTC_LPS_DISABLE = 0x0, + BTC_LPS_ENABLE = 0x1, + BTC_LPS_MAX +}; + +enum btc_notify_type_scan { + BTC_SCAN_FINISH = 0x0, + BTC_SCAN_START = 0x1, + BTC_SCAN_MAX +}; + +enum btc_notify_type_associate { + BTC_ASSOCIATE_FINISH = 0x0, + BTC_ASSOCIATE_START = 0x1, + BTC_ASSOCIATE_MAX +}; + +enum btc_notify_type_media_status { + BTC_MEDIA_DISCONNECT = 0x0, + BTC_MEDIA_CONNECT = 0x1, + BTC_MEDIA_MAX +}; + +enum btc_notify_type_special_packet { + BTC_PACKET_UNKNOWN = 0x0, + BTC_PACKET_DHCP = 0x1, + BTC_PACKET_ARP = 0x2, + BTC_PACKET_EAPOL = 0x3, + BTC_PACKET_MAX +}; + +enum hci_ext_bt_operation { + HCI_BT_OP_NONE = 0x0, + HCI_BT_OP_INQUIRY_START = 0x1, + HCI_BT_OP_INQUIRY_FINISH = 0x2, + HCI_BT_OP_PAGING_START = 0x3, + HCI_BT_OP_PAGING_SUCCESS = 0x4, + HCI_BT_OP_PAGING_UNSUCCESS = 0x5, + HCI_BT_OP_PAIRING_START = 0x6, + HCI_BT_OP_PAIRING_FINISH = 0x7, + HCI_BT_OP_BT_DEV_ENABLE = 0x8, + HCI_BT_OP_BT_DEV_DISABLE = 0x9, + HCI_BT_OP_MAX +}; + +enum btc_notify_type_stack_operation { + BTC_STACK_OP_NONE = 0x0, + BTC_STACK_OP_INQ_PAGE_PAIR_START = 0x1, + BTC_STACK_OP_INQ_PAGE_PAIR_FINISH = 0x2, + BTC_STACK_OP_MAX +}; + +typedef u8 (*bfp_btc_r1)(void *btc_context, u32 reg_addr); + +typedef u16 (*bfp_btc_r2)(void *btc_context, u32 reg_addr); + +typedef u32 (*bfp_btc_r4)(void *btc_context, u32 reg_addr); + +typedef void (*bfp_btc_w1)(void *btc_context, u32 reg_addr, u32 data); + +typedef void (*bfp_btc_w1_bit_mak)(void *btc_context, u32 reg_addr, + u32 bit_mask, u8 data1b); + +typedef void (*bfp_btc_w2)(void *btc_context, u32 reg_addr, u16 data); + +typedef void (*bfp_btc_w4)(void *btc_context, u32 reg_addr, u32 data); + +typedef void (*bfp_btc_wr_1byte_bit_mask)(void *btc_context, u32 reg_addr, + u8 bit_mask, u8 data); + +typedef void (*bfp_btc_set_bb_reg)(void *btc_context, u32 reg_addr, + u32 bit_mask, u32 data); + +typedef u32 (*bfp_btc_get_bb_reg)(void *btc_context, u32 reg_addr, + u32 bit_mask); + +typedef void (*bfp_btc_set_rf_reg)(void *btc_context, u8 rf_path, u32 reg_addr, + u32 bit_mask, u32 data); + +typedef u32 (*bfp_btc_get_rf_reg)(void *btc_context, u8 rf_path, + u32 reg_addr, u32 bit_mask); + +typedef void (*bfp_btc_fill_h2c)(void *btc_context, u8 element_id, + u32 cmd_len, u8 *cmd_buffer); + +typedef bool (*bfp_btc_get)(void *btcoexist, u8 get_type, void *out_buf); + +typedef bool (*bfp_btc_set)(void *btcoexist, u8 set_type, void *in_buf); + +typedef void (*bfp_btc_disp_dbg_msg)(void *btcoexist, u8 disp_type); + +struct btc_bt_info { + bool bt_disabled; + u8 rssi_adjust_for_agc_table_on; + u8 rssi_adjust_for_1ant_coex_type; + bool bt_busy; + u8 agg_buf_size; + bool limited_dig; + bool reject_agg_pkt; + bool bt_ctrl_buf_size; + bool increase_scan_dev_num; + u16 bt_hci_ver; + u16 bt_real_fw_ver; + u8 bt_fw_ver; + + bool bt_disable_low_pwr; + + /* the following is for 1Ant solution */ + bool bt_ctrl_lps; + bool bt_pwr_save_mode; + bool bt_lps_on; + bool force_to_roam; + u8 force_exec_pwr_cmd_cnt; + u8 lps_val; + u8 rpwm_val; + u32 ra_mask; +}; + +struct btc_stack_info { + bool profile_notified; + u16 hci_version; /* stack hci version */ + u8 num_of_link; + bool bt_link_exist; + bool sco_exist; + bool acl_exist; + bool a2dp_exist; + bool hid_exist; + u8 num_of_hid; + bool pan_exist; + bool unknown_acl_exist; + char min_bt_rssi; +}; + +struct btc_statistics { + u32 cnt_bind; + u32 cnt_init_hw_config; + u32 cnt_init_coex_dm; + u32 cnt_ips_notify; + u32 cnt_lps_notify; + u32 cnt_scan_notify; + u32 cnt_connect_notify; + u32 cnt_media_status_notify; + u32 cnt_special_packet_notify; + u32 cnt_bt_info_notify; + u32 cnt_periodical; + u32 cnt_coex_dm_switch; + u32 cnt_stack_operation_notify; + u32 cnt_dbg_ctrl; +}; + +struct btc_bt_link_info { + bool bt_link_exist; + bool sco_exist; + bool sco_only; + bool a2dp_exist; + bool a2dp_only; + bool hid_exist; + bool hid_only; + bool pan_exist; + bool pan_only; +}; + +enum btc_antenna_pos { + BTC_ANTENNA_AT_MAIN_PORT = 0x1, + BTC_ANTENNA_AT_AUX_PORT = 0x2, +}; + +struct btc_coexist { + /* make sure only one adapter can bind the data context */ + bool binded; + /* default adapter */ + void *adapter; + struct btc_board_info board_info; + /* some bt info referenced by non-bt module */ + struct btc_bt_info bt_info; + struct btc_stack_info stack_info; + enum btc_chip_interface chip_interface; + struct btc_bt_link_info bt_link_info; + + bool initilized; + bool stop_coex_dm; + bool manual_control; + struct btc_statistics statistics; + u8 pwr_mode_val[10]; + + /* function pointers - io related */ + bfp_btc_r1 btc_read_1byte; + bfp_btc_w1 btc_write_1byte; + bfp_btc_w1_bit_mak btc_write_1byte_bitmask; + bfp_btc_r2 btc_read_2byte; + bfp_btc_w2 btc_write_2byte; + bfp_btc_r4 btc_read_4byte; + bfp_btc_w4 btc_write_4byte; + + bfp_btc_set_bb_reg btc_set_bb_reg; + bfp_btc_get_bb_reg btc_get_bb_reg; + + bfp_btc_set_rf_reg btc_set_rf_reg; + bfp_btc_get_rf_reg btc_get_rf_reg; + + bfp_btc_fill_h2c btc_fill_h2c; + + bfp_btc_disp_dbg_msg btc_disp_dbg_msg; + + bfp_btc_get btc_get; + bfp_btc_set btc_set; +}; + +bool halbtc_is_wifi_uplink(struct rtl_priv *adapter); + +extern struct btc_coexist gl_bt_coexist; + +bool exhalbtc_initlize_variables(struct rtl_priv *adapter); +void exhalbtc_init_hw_config(struct btc_coexist *btcoexist); +void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist); +void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type); +void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type); +void exhalbtc_scan_notify(struct btc_coexist *btcoexist, u8 type); +void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action); +void exhalbtc_mediastatus_notify(struct btc_coexist *btcoexist, + enum rt_media_status media_status); +void exhalbtc_special_packet_notify(struct btc_coexist *btcoexist, u8 pkt_type); +void exhalbtc_bt_info_notify(struct btc_coexist *btcoexist, u8 *tmp_buf, + u8 length); +void exhalbtc_stack_operation_notify(struct btc_coexist *btcoexist, u8 type); +void exhalbtc_halt_notify(struct btc_coexist *btcoexist); +void exhalbtc_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state); +void exhalbtc_coex_dm_switch(struct btc_coexist *btcoexist); +void exhalbtc_periodical(struct btc_coexist *btcoexist); +void exhalbtc_dbg_control(struct btc_coexist *btcoexist, u8 code, u8 len, + u8 *data); +void exhalbtc_stack_update_profile_info(void); +void exhalbtc_set_hci_version(u16 hci_version); +void exhalbtc_set_bt_patch_version(u16 bt_hci_version, u16 bt_patch_version); +void exhalbtc_update_min_bt_rssi(char bt_rssi); +void exhalbtc_set_bt_exist(bool bt_exist); +void exhalbtc_set_chip_type(u8 chip_type); +void exhalbtc_set_ant_num(u8 type, u8 ant_num); +void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist); +void exhalbtc_signal_compensation(struct btc_coexist *btcoexist, + u8 *rssi_wifi, u8 *rssi_bt); +void exhalbtc_lps_leave(struct btc_coexist *btcoexist); +void exhalbtc_low_wifi_traffic_notify(struct btc_coexist *btcoexist); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c new file mode 100644 index 000000000000..b9b0cb7af8ea --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c @@ -0,0 +1,231 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#include "../wifi.h" +#include +#include + +#include "rtl_btc.h" +#include "halbt_precomp.h" + +static struct rtl_btc_ops rtl_btc_operation = { + .btc_init_variables = rtl_btc_init_variables, + .btc_init_hal_vars = rtl_btc_init_hal_vars, + .btc_init_hw_config = rtl_btc_init_hw_config, + .btc_ips_notify = rtl_btc_ips_notify, + .btc_lps_notify = rtl_btc_lps_notify, + .btc_scan_notify = rtl_btc_scan_notify, + .btc_connect_notify = rtl_btc_connect_notify, + .btc_mediastatus_notify = rtl_btc_mediastatus_notify, + .btc_periodical = rtl_btc_periodical, + .btc_halt_notify = rtl_btc_halt_notify, + .btc_btinfo_notify = rtl_btc_btinfo_notify, + .btc_is_limited_dig = rtl_btc_is_limited_dig, + .btc_is_disable_edca_turbo = rtl_btc_is_disable_edca_turbo, + .btc_is_bt_disabled = rtl_btc_is_bt_disabled, + .btc_special_packet_notify = rtl_btc_special_packet_notify, +}; + +void rtl_btc_init_variables(struct rtl_priv *rtlpriv) +{ + exhalbtc_initlize_variables(rtlpriv); +} + +void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv) +{ + u8 ant_num; + u8 bt_exist; + u8 bt_type; + + ant_num = rtl_get_hwpg_ant_num(rtlpriv); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "%s, antNum is %d\n", __func__, ant_num); + + bt_exist = rtl_get_hwpg_bt_exist(rtlpriv); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "%s, bt_exist is %d\n", __func__, bt_exist); + exhalbtc_set_bt_exist(bt_exist); + + bt_type = rtl_get_hwpg_bt_type(rtlpriv); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%s, bt_type is %d\n", + __func__, bt_type); + exhalbtc_set_chip_type(bt_type); + + exhalbtc_set_ant_num(BT_COEX_ANT_TYPE_PG, ant_num); +} + +void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv) +{ + exhalbtc_init_hw_config(&gl_bt_coexist); + exhalbtc_init_coex_dm(&gl_bt_coexist); +} + +void rtl_btc_ips_notify(struct rtl_priv *rtlpriv, u8 type) +{ + exhalbtc_ips_notify(&gl_bt_coexist, type); +} + +void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type) +{ + exhalbtc_lps_notify(&gl_bt_coexist, type); +} + +void rtl_btc_scan_notify(struct rtl_priv *rtlpriv, u8 scantype) +{ + exhalbtc_scan_notify(&gl_bt_coexist, scantype); +} + +void rtl_btc_connect_notify(struct rtl_priv *rtlpriv, u8 action) +{ + exhalbtc_connect_notify(&gl_bt_coexist, action); +} + +void rtl_btc_mediastatus_notify(struct rtl_priv *rtlpriv, + enum rt_media_status mstatus) +{ + exhalbtc_mediastatus_notify(&gl_bt_coexist, mstatus); +} + +void rtl_btc_periodical(struct rtl_priv *rtlpriv) +{ + /*rtl_bt_dm_monitor();*/ + exhalbtc_periodical(&gl_bt_coexist); +} + +void rtl_btc_halt_notify(void) +{ + exhalbtc_halt_notify(&gl_bt_coexist); +} + +void rtl_btc_btinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length) +{ + exhalbtc_bt_info_notify(&gl_bt_coexist, tmp_buf, length); +} + +bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv) +{ + return gl_bt_coexist.bt_info.limited_dig; +} + +bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv) +{ + bool bt_change_edca = false; + u32 cur_edca_val; + u32 edca_bt_hs_uplink = 0x5ea42b, edca_bt_hs_downlink = 0x5ea42b; + u32 edca_hs; + u32 edca_addr = 0x504; + + cur_edca_val = rtl_read_dword(rtlpriv, edca_addr); + if (halbtc_is_wifi_uplink(rtlpriv)) { + if (cur_edca_val != edca_bt_hs_uplink) { + edca_hs = edca_bt_hs_uplink; + bt_change_edca = true; + } + } else { + if (cur_edca_val != edca_bt_hs_downlink) { + edca_hs = edca_bt_hs_downlink; + bt_change_edca = true; + } + } + + if (bt_change_edca) + rtl_write_dword(rtlpriv, edca_addr, edca_hs); + + return true; +} + +bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv) +{ + /* It seems 'bt_disabled' is never be initialized or set. */ + if (gl_bt_coexist.bt_info.bt_disabled) + return true; + else + return false; +} + +void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type) +{ + return exhalbtc_special_packet_notify(&gl_bt_coexist, pkt_type); +} + +struct rtl_btc_ops *rtl_btc_get_ops_pointer(void) +{ + return &rtl_btc_operation; +} +EXPORT_SYMBOL(rtl_btc_get_ops_pointer); + +u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv) +{ + u8 num; + + if (rtlpriv->btcoexist.btc_info.ant_num == ANT_X2) + num = 2; + else + num = 1; + + return num; +} + +enum rt_media_status mgnt_link_status_query(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + enum rt_media_status m_status = RT_MEDIA_DISCONNECT; + + u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0; + + if (bibss || rtlpriv->mac80211.link_state >= MAC80211_LINKED) + m_status = RT_MEDIA_CONNECT; + + return m_status; +} + +u8 rtl_get_hwpg_bt_exist(struct rtl_priv *rtlpriv) +{ + return rtlpriv->btcoexist.btc_info.btcoexist; +} + +u8 rtl_get_hwpg_bt_type(struct rtl_priv *rtlpriv) +{ + return rtlpriv->btcoexist.btc_info.bt_type; +} + +MODULE_AUTHOR("Page He "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); + +static int __init rtl_btcoexist_module_init(void) +{ + return 0; +} + +static void __exit rtl_btcoexist_module_exit(void) +{ + return; +} + +module_init(rtl_btcoexist_module_init); +module_exit(rtl_btcoexist_module_exit); diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h new file mode 100644 index 000000000000..ccd5a0f91e3b --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL_BTC_H__ +#define __RTL_BTC_H__ + +#include "halbt_precomp.h" + +void rtl_btc_init_variables(struct rtl_priv *rtlpriv); +void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv); +void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv); +void rtl_btc_ips_notify(struct rtl_priv *rtlpriv, u8 type); +void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type); +void rtl_btc_scan_notify(struct rtl_priv *rtlpriv, u8 scantype); +void rtl_btc_connect_notify(struct rtl_priv *rtlpriv, u8 action); +void rtl_btc_mediastatus_notify(struct rtl_priv *rtlpriv, + enum rt_media_status mstatus); +void rtl_btc_periodical(struct rtl_priv *rtlpriv); +void rtl_btc_halt_notify(void); +void rtl_btc_btinfo_notify(struct rtl_priv *rtlpriv, u8 *tmpbuf, u8 length); +bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv); +bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv); +bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv); +void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type); + +struct rtl_btc_ops *rtl_btc_get_ops_pointer(void); + +u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv); +u8 rtl_get_hwpg_bt_exist(struct rtl_priv *rtlpriv); +u8 rtl_get_hwpg_bt_type(struct rtl_priv *rtlpriv); +enum rt_media_status mgnt_link_status_query(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/cam.c b/drivers/net/wireless/realtek/rtlwifi/cam.c new file mode 100644 index 000000000000..8fe8b4cfae6c --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/cam.c @@ -0,0 +1,347 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#include "wifi.h" +#include "cam.h" +#include + +void rtl_cam_reset_sec_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->sec.use_defaultkey = false; + rtlpriv->sec.pairwise_enc_algorithm = NO_ENCRYPTION; + rtlpriv->sec.group_enc_algorithm = NO_ENCRYPTION; + memset(rtlpriv->sec.key_buf, 0, KEY_BUF_SIZE * MAX_KEY_LEN); + memset(rtlpriv->sec.key_len, 0, KEY_BUF_SIZE); + rtlpriv->sec.pairwise_key = NULL; +} + +static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, + u8 *mac_addr, u8 *key_cont_128, u16 us_config) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + u32 target_command; + u32 target_content = 0; + u8 entry_i; + + RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_DMESG, "Key content :", + key_cont_128, 16); + + for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { + target_command = entry_i + CAM_CONTENT_COUNT * entry_no; + target_command = target_command | BIT(31) | BIT(16); + + if (entry_i == 0) { + target_content = (u32) (*(mac_addr + 0)) << 16 | + (u32) (*(mac_addr + 1)) << 24 | (u32) us_config; + + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], + target_content); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], + target_command); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "WRITE %x: %x\n", + rtlpriv->cfg->maps[WCAMI], target_content); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "The Key ID is %d\n", entry_no); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "WRITE %x: %x\n", + rtlpriv->cfg->maps[RWCAM], target_command); + + } else if (entry_i == 1) { + + target_content = (u32) (*(mac_addr + 5)) << 24 | + (u32) (*(mac_addr + 4)) << 16 | + (u32) (*(mac_addr + 3)) << 8 | + (u32) (*(mac_addr + 2)); + + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], + target_content); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], + target_command); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "WRITE A4: %x\n", target_content); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "WRITE A0: %x\n", target_command); + + } else { + + target_content = + (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 3)) << + 24 | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 2)) + << 16 | + (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 1)) << 8 + | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 0)); + + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], + target_content); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], + target_command); + udelay(100); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "WRITE A4: %x\n", target_content); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "WRITE A0: %x\n", target_command); + } + } + + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "after set key, usconfig:%x\n", us_config); +} + +u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, + u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg, + u32 ul_default_key, u8 *key_content) +{ + u32 us_config; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n", + ul_entry_idx, ul_key_id, ul_enc_alg, + ul_default_key, mac_addr); + + if (ul_key_id == TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "ulKeyId exceed!\n"); + return 0; + } + + if (ul_default_key == 1) + us_config = CFG_VALID | ((u16) (ul_enc_alg) << 2); + else + us_config = CFG_VALID | ((ul_enc_alg) << 2) | ul_key_id; + + rtl_cam_program_entry(hw, ul_entry_idx, mac_addr, + (u8 *)key_content, us_config); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "end\n"); + + return 1; + +} +EXPORT_SYMBOL(rtl_cam_add_one_entry); + +int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, + u8 *mac_addr, u32 ul_key_id) +{ + u32 ul_command; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "key_idx:%d\n", ul_key_id); + + ul_command = ul_key_id * CAM_CONTENT_COUNT; + ul_command = ul_command | BIT(31) | BIT(16); + + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 0); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "rtl_cam_delete_one_entry(): WRITE A4: %x\n", 0); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "rtl_cam_delete_one_entry(): WRITE A0: %x\n", ul_command); + + return 0; + +} +EXPORT_SYMBOL(rtl_cam_delete_one_entry); + +void rtl_cam_reset_all_entry(struct ieee80211_hw *hw) +{ + u32 ul_command; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + ul_command = BIT(31) | BIT(30); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); +} +EXPORT_SYMBOL(rtl_cam_reset_all_entry); + +void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + u32 ul_command; + u32 ul_content; + u32 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; + + switch (rtlpriv->sec.pairwise_enc_algorithm) { + case WEP40_ENCRYPTION: + ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP40]; + break; + case WEP104_ENCRYPTION: + ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP104]; + break; + case TKIP_ENCRYPTION: + ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_TKIP]; + break; + case AESCCMP_ENCRYPTION: + ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; + break; + default: + ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; + } + + ul_content = (uc_index & 3) | ((u16) (ul_enc_algo) << 2); + + ul_content |= BIT(15); + ul_command = CAM_CONTENT_COUNT * uc_index; + ul_command = ul_command | BIT(31) | BIT(16); + + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "rtl_cam_mark_invalid(): WRITE A4: %x\n", ul_content); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "rtl_cam_mark_invalid(): WRITE A0: %x\n", ul_command); +} +EXPORT_SYMBOL(rtl_cam_mark_invalid); + +void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + u32 ul_command; + u32 ul_content; + u32 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; + u8 entry_i; + + switch (rtlpriv->sec.pairwise_enc_algorithm) { + case WEP40_ENCRYPTION: + ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP40]; + break; + case WEP104_ENCRYPTION: + ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP104]; + break; + case TKIP_ENCRYPTION: + ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_TKIP]; + break; + case AESCCMP_ENCRYPTION: + ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; + break; + default: + ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; + } + + for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { + + if (entry_i == 0) { + ul_content = + (uc_index & 0x03) | ((u16) (ul_encalgo) << 2); + ul_content |= BIT(15); + + } else { + ul_content = 0; + } + + ul_command = CAM_CONTENT_COUNT * uc_index + entry_i; + ul_command = ul_command | BIT(31) | BIT(16); + + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "rtl_cam_empty_entry(): WRITE A4: %x\n", + ul_content); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "rtl_cam_empty_entry(): WRITE A0: %x\n", + ul_command); + } + +} +EXPORT_SYMBOL(rtl_cam_empty_entry); + +u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> 4; + u8 entry_idx = 0; + u8 i, *addr; + + if (NULL == sta_addr) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + "sta_addr is NULL.\n"); + return TOTAL_CAM_ENTRY; + } + /* Does STA already exist? */ + for (i = 4; i < TOTAL_CAM_ENTRY; i++) { + addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; + if (ether_addr_equal_unaligned(addr, sta_addr)) + return i; + } + /* Get a free CAM entry. */ + for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY; entry_idx++) { + if ((bitmap & BIT(0)) == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + "-----hwsec_cam_bitmap: 0x%x entry_idx=%d\n", + rtlpriv->sec.hwsec_cam_bitmap, entry_idx); + rtlpriv->sec.hwsec_cam_bitmap |= BIT(0) << entry_idx; + memcpy(rtlpriv->sec.hwsec_cam_sta_addr[entry_idx], + sta_addr, ETH_ALEN); + return entry_idx; + } + bitmap = bitmap >> 1; + } + return TOTAL_CAM_ENTRY; +} +EXPORT_SYMBOL(rtl_cam_get_free_entry); + +void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 bitmap; + u8 i, *addr; + + if (NULL == sta_addr) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + "sta_addr is NULL.\n"); + return; + } + + if (is_zero_ether_addr(sta_addr)) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + "sta_addr is %pM\n", sta_addr); + return; + } + /* Does STA already exist? */ + for (i = 4; i < TOTAL_CAM_ENTRY; i++) { + addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; + bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> i; + if (((bitmap & BIT(0)) == BIT(0)) && + (ether_addr_equal_unaligned(addr, sta_addr))) { + /* Remove from HW Security CAM */ + eth_zero_addr(rtlpriv->sec.hwsec_cam_sta_addr[i]); + rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "&&&&&&&&&del entry %d\n", i); + } + } + return; +} +EXPORT_SYMBOL(rtl_cam_del_entry); diff --git a/drivers/net/wireless/realtek/rtlwifi/cam.h b/drivers/net/wireless/realtek/rtlwifi/cam.h new file mode 100644 index 000000000000..e2e647d511c1 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/cam.h @@ -0,0 +1,50 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL_CAM_H_ +#define __RTL_CAM_H_ + +#define CAM_CONTENT_COUNT 8 + +#define CFG_VALID BIT(15) + +#define PAIRWISE_KEYIDX 0 +#define CAM_PAIRWISE_KEY_POSITION 4 + +#define CAM_CONFIG_NO_USEDK 0 + +void rtl_cam_reset_all_entry(struct ieee80211_hw *hw); +u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, + u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg, + u32 ul_default_key, u8 *key_content); +int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, + u32 ul_key_id); +void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index); +void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index); +void rtl_cam_reset_sec_info(struct ieee80211_hw *hw); +u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr); +void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c new file mode 100644 index 000000000000..c925a4dff599 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -0,0 +1,1924 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "wifi.h" +#include "core.h" +#include "cam.h" +#include "base.h" +#include "ps.h" +#include "pwrseqcmd.h" + +#include "btcoexist/rtl_btc.h" +#include +#include +#include + +void rtl_addr_delay(u32 addr) +{ + if (addr == 0xfe) + mdelay(50); + else if (addr == 0xfd) + mdelay(5); + else if (addr == 0xfc) + mdelay(1); + else if (addr == 0xfb) + udelay(50); + else if (addr == 0xfa) + udelay(5); + else if (addr == 0xf9) + udelay(1); +} +EXPORT_SYMBOL(rtl_addr_delay); + +void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr, + u32 mask, u32 data) +{ + if (addr == 0xfe) { + mdelay(50); + } else if (addr == 0xfd) { + mdelay(5); + } else if (addr == 0xfc) { + mdelay(1); + } else if (addr == 0xfb) { + udelay(50); + } else if (addr == 0xfa) { + udelay(5); + } else if (addr == 0xf9) { + udelay(1); + } else { + rtl_set_rfreg(hw, rfpath, addr, mask, data); + udelay(1); + } +} +EXPORT_SYMBOL(rtl_rfreg_delay); + +void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data) +{ + if (addr == 0xfe) { + mdelay(50); + } else if (addr == 0xfd) { + mdelay(5); + } else if (addr == 0xfc) { + mdelay(1); + } else if (addr == 0xfb) { + udelay(50); + } else if (addr == 0xfa) { + udelay(5); + } else if (addr == 0xf9) { + udelay(1); + } else { + rtl_set_bbreg(hw, addr, MASKDWORD, data); + udelay(1); + } +} +EXPORT_SYMBOL(rtl_bb_delay); + +static void rtl_fw_do_work(const struct firmware *firmware, void *context, + bool is_wow) +{ + struct ieee80211_hw *hw = context; + struct rtl_priv *rtlpriv = rtl_priv(hw); + int err; + + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "Firmware callback routine entered!\n"); + complete(&rtlpriv->firmware_loading_complete); + if (!firmware) { + if (rtlpriv->cfg->alt_fw_name) { + err = request_firmware(&firmware, + rtlpriv->cfg->alt_fw_name, + rtlpriv->io.dev); + pr_info("Loading alternative firmware %s\n", + rtlpriv->cfg->alt_fw_name); + if (!err) + goto found_alt; + } + pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name); + rtlpriv->max_fw_size = 0; + return; + } +found_alt: + if (firmware->size > rtlpriv->max_fw_size) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Firmware is too big!\n"); + release_firmware(firmware); + return; + } + if (!is_wow) { + memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, + firmware->size); + rtlpriv->rtlhal.fwsize = firmware->size; + } else { + memcpy(rtlpriv->rtlhal.wowlan_firmware, firmware->data, + firmware->size); + rtlpriv->rtlhal.wowlan_fwsize = firmware->size; + } + rtlpriv->rtlhal.fwsize = firmware->size; + release_firmware(firmware); +} + +void rtl_fw_cb(const struct firmware *firmware, void *context) +{ + rtl_fw_do_work(firmware, context, false); +} +EXPORT_SYMBOL(rtl_fw_cb); + +void rtl_wowlan_fw_cb(const struct firmware *firmware, void *context) +{ + rtl_fw_do_work(firmware, context, true); +} +EXPORT_SYMBOL(rtl_wowlan_fw_cb); + +/*mutex for start & stop is must here. */ +static int rtl_op_start(struct ieee80211_hw *hw) +{ + int err = 0; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (!is_hal_stop(rtlhal)) + return 0; + if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) + return 0; + mutex_lock(&rtlpriv->locks.conf_mutex); + err = rtlpriv->intf_ops->adapter_start(hw); + if (!err) + rtl_watch_dog_timer_callback((unsigned long)hw); + mutex_unlock(&rtlpriv->locks.conf_mutex); + return err; +} + +static void rtl_op_stop(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool support_remote_wakeup = false; + + if (is_hal_stop(rtlhal)) + return; + + rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, + (u8 *)(&support_remote_wakeup)); + /* here is must, because adhoc do stop and start, + * but stop with RFOFF may cause something wrong, + * like adhoc TP + */ + if (unlikely(ppsc->rfpwr_state == ERFOFF)) + rtl_ips_nic_on(hw); + + mutex_lock(&rtlpriv->locks.conf_mutex); + /* if wowlan supported, DON'T clear connected info */ + if (!(support_remote_wakeup && + rtlhal->enter_pnp_sleep)) { + mac->link_state = MAC80211_NOLINK; + eth_zero_addr(mac->bssid); + mac->vendor = PEER_UNKNOWN; + + /* reset sec info */ + rtl_cam_reset_sec_info(hw); + + rtl_deinit_deferred_work(hw); + } + rtlpriv->intf_ops->adapter_stop(hw); + + mutex_unlock(&rtlpriv->locks.conf_mutex); +} + +static void rtl_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_tcb_desc tcb_desc; + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + + if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) + goto err_free; + + if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) + goto err_free; + + if (!rtlpriv->intf_ops->waitq_insert(hw, control->sta, skb)) + rtlpriv->intf_ops->adapter_tx(hw, control->sta, skb, &tcb_desc); + return; + +err_free: + dev_kfree_skb_any(skb); +} + +static int rtl_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + int err = 0; + + if (mac->vif) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "vif has been set!! mac->vif = 0x%p\n", mac->vif); + return -EOPNOTSUPP; + } + + vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; + + rtl_ips_nic_on(hw); + + mutex_lock(&rtlpriv->locks.conf_mutex); + switch (ieee80211_vif_type_p2p(vif)) { + case NL80211_IFTYPE_P2P_CLIENT: + mac->p2p = P2P_ROLE_CLIENT; + /*fall through*/ + case NL80211_IFTYPE_STATION: + if (mac->beacon_enabled == 1) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "NL80211_IFTYPE_STATION\n"); + mac->beacon_enabled = 0; + rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, + rtlpriv->cfg->maps[RTL_IBSS_INT_MASKS]); + } + break; + case NL80211_IFTYPE_ADHOC: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "NL80211_IFTYPE_ADHOC\n"); + + mac->link_state = MAC80211_LINKED; + rtlpriv->cfg->ops->set_bcn_reg(hw); + if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) + mac->basic_rates = 0xfff; + else + mac->basic_rates = 0xff0; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, + (u8 *)(&mac->basic_rates)); + + break; + case NL80211_IFTYPE_P2P_GO: + mac->p2p = P2P_ROLE_GO; + /*fall through*/ + case NL80211_IFTYPE_AP: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "NL80211_IFTYPE_AP\n"); + + mac->link_state = MAC80211_LINKED; + rtlpriv->cfg->ops->set_bcn_reg(hw); + if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) + mac->basic_rates = 0xfff; + else + mac->basic_rates = 0xff0; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, + (u8 *)(&mac->basic_rates)); + break; + case NL80211_IFTYPE_MESH_POINT: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "NL80211_IFTYPE_MESH_POINT\n"); + + mac->link_state = MAC80211_LINKED; + rtlpriv->cfg->ops->set_bcn_reg(hw); + if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) + mac->basic_rates = 0xfff; + else + mac->basic_rates = 0xff0; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, + (u8 *)(&mac->basic_rates)); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "operation mode %d is not support!\n", vif->type); + err = -EOPNOTSUPP; + goto out; + } + + if (mac->p2p) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "p2p role %x\n", vif->type); + mac->basic_rates = 0xff0;/*disable cck rate for p2p*/ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, + (u8 *)(&mac->basic_rates)); + } + mac->vif = vif; + mac->opmode = vif->type; + rtlpriv->cfg->ops->set_network_type(hw, vif->type); + memcpy(mac->mac_addr, vif->addr, ETH_ALEN); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); + +out: + mutex_unlock(&rtlpriv->locks.conf_mutex); + return err; +} + +static void rtl_op_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + mutex_lock(&rtlpriv->locks.conf_mutex); + + /* Free beacon resources */ + if ((vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_ADHOC) || + (vif->type == NL80211_IFTYPE_MESH_POINT)) { + if (mac->beacon_enabled == 1) { + mac->beacon_enabled = 0; + rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, + rtlpriv->cfg->maps[RTL_IBSS_INT_MASKS]); + } + } + + /* + *Note: We assume NL80211_IFTYPE_UNSPECIFIED as + *NO LINK for our hardware. + */ + mac->p2p = 0; + mac->vif = NULL; + mac->link_state = MAC80211_NOLINK; + eth_zero_addr(mac->bssid); + mac->vendor = PEER_UNKNOWN; + mac->opmode = NL80211_IFTYPE_UNSPECIFIED; + rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); + + mutex_unlock(&rtlpriv->locks.conf_mutex); +} +static int rtl_op_change_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum nl80211_iftype new_type, bool p2p) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int ret; + rtl_op_remove_interface(hw, vif); + + vif->type = new_type; + vif->p2p = p2p; + ret = rtl_op_add_interface(hw, vif); + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "p2p %x\n", p2p); + return ret; +} + +#ifdef CONFIG_PM +static u16 crc16_ccitt(u8 data, u16 crc) +{ + u8 shift_in, data_bit, crc_bit11, crc_bit4, crc_bit15; + u8 i; + u16 result; + + for (i = 0; i < 8; i++) { + crc_bit15 = ((crc & BIT(15)) ? 1 : 0); + data_bit = (data & (BIT(0) << i) ? 1 : 0); + shift_in = crc_bit15 ^ data_bit; + + result = crc << 1; + if (shift_in == 0) + result &= (~BIT(0)); + else + result |= BIT(0); + + crc_bit11 = ((crc & BIT(11)) ? 1 : 0) ^ shift_in; + if (crc_bit11 == 0) + result &= (~BIT(12)); + else + result |= BIT(12); + + crc_bit4 = ((crc & BIT(4)) ? 1 : 0) ^ shift_in; + if (crc_bit4 == 0) + result &= (~BIT(5)); + else + result |= BIT(5); + + crc = result; + } + + return crc; +} + +static u16 _calculate_wol_pattern_crc(u8 *pattern, u16 len) +{ + u16 crc = 0xffff; + u32 i; + + for (i = 0; i < len; i++) + crc = crc16_ccitt(pattern[i], crc); + + crc = ~crc; + + return crc; +} + +static void _rtl_add_wowlan_patterns(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wow) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = &rtlpriv->mac80211; + struct cfg80211_pkt_pattern *patterns = wow->patterns; + struct rtl_wow_pattern rtl_pattern; + const u8 *pattern_os, *mask_os; + u8 mask[MAX_WOL_BIT_MASK_SIZE] = {0}; + u8 content[MAX_WOL_PATTERN_SIZE] = {0}; + u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 multicast_addr1[2] = {0x33, 0x33}; + u8 multicast_addr2[3] = {0x01, 0x00, 0x5e}; + u8 i, mask_len; + u16 j, len; + + for (i = 0; i < wow->n_patterns; i++) { + memset(&rtl_pattern, 0, sizeof(struct rtl_wow_pattern)); + memset(mask, 0, MAX_WOL_BIT_MASK_SIZE); + if (patterns[i].pattern_len > MAX_WOL_PATTERN_SIZE) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_WARNING, + "Pattern[%d] is too long\n", i); + continue; + } + pattern_os = patterns[i].pattern; + mask_len = DIV_ROUND_UP(patterns[i].pattern_len, 8); + mask_os = patterns[i].mask; + RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, + "pattern content\n", pattern_os, + patterns[i].pattern_len); + RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, + "mask content\n", mask_os, mask_len); + /* 1. unicast? multicast? or broadcast? */ + if (memcmp(pattern_os, broadcast_addr, 6) == 0) + rtl_pattern.type = BROADCAST_PATTERN; + else if (memcmp(pattern_os, multicast_addr1, 2) == 0 || + memcmp(pattern_os, multicast_addr2, 3) == 0) + rtl_pattern.type = MULTICAST_PATTERN; + else if (memcmp(pattern_os, mac->mac_addr, 6) == 0) + rtl_pattern.type = UNICAST_PATTERN; + else + rtl_pattern.type = UNKNOWN_TYPE; + + /* 2. translate mask_from_os to mask_for_hw */ + +/****************************************************************************** + * pattern from OS uses 'ethenet frame', like this: + + | 6 | 6 | 2 | 20 | Variable | 4 | + |--------+--------+------+-----------+------------+-----| + | 802.3 Mac Header | IP Header | TCP Packet | FCS | + | DA | SA | Type | + + * BUT, packet catched by our HW is in '802.11 frame', begin from LLC, + + | 24 or 30 | 6 | 2 | 20 | Variable | 4 | + |-------------------+--------+------+-----------+------------+-----| + | 802.11 MAC Header | LLC | IP Header | TCP Packet | FCS | + | Others | Tpye | + + * Therefore, we need translate mask_from_OS to mask_to_hw. + * We should left-shift mask by 6 bits, then set the new bit[0~5] = 0, + * because new mask[0~5] means 'SA', but our HW packet begins from LLC, + * bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match. + ******************************************************************************/ + + /* Shift 6 bits */ + for (j = 0; j < mask_len - 1; j++) { + mask[j] = mask_os[j] >> 6; + mask[j] |= (mask_os[j + 1] & 0x3F) << 2; + } + mask[j] = (mask_os[j] >> 6) & 0x3F; + /* Set bit 0-5 to zero */ + mask[0] &= 0xC0; + + RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, + "mask to hw\n", mask, mask_len); + for (j = 0; j < (MAX_WOL_BIT_MASK_SIZE + 1) / 4; j++) { + rtl_pattern.mask[j] = mask[j * 4]; + rtl_pattern.mask[j] |= (mask[j * 4 + 1] << 8); + rtl_pattern.mask[j] |= (mask[j * 4 + 2] << 16); + rtl_pattern.mask[j] |= (mask[j * 4 + 3] << 24); + } + + /* To get the wake up pattern from the mask. + * We do not count first 12 bits which means + * DA[6] and SA[6] in the pattern to match HW design. + */ + len = 0; + for (j = 12; j < patterns[i].pattern_len; j++) { + if ((mask_os[j / 8] >> (j % 8)) & 0x01) { + content[len] = pattern_os[j]; + len++; + } + } + + RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, + "pattern to hw\n", content, len); + /* 3. calculate crc */ + rtl_pattern.crc = _calculate_wol_pattern_crc(content, len); + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "CRC_Remainder = 0x%x", rtl_pattern.crc); + + /* 4. write crc & mask_for_hw to hw */ + rtlpriv->cfg->ops->add_wowlan_pattern(hw, &rtl_pattern, i); + } + rtl_write_byte(rtlpriv, 0x698, wow->n_patterns); +} + +static int rtl_op_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wow) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct timeval ts; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n"); + if (WARN_ON(!wow)) + return -EINVAL; + + /* to resolve s4 can not wake up*/ + do_gettimeofday(&ts); + rtlhal->last_suspend_sec = ts.tv_sec; + + if ((ppsc->wo_wlan_mode & WAKE_ON_PATTERN_MATCH) && wow->n_patterns) + _rtl_add_wowlan_patterns(hw, wow); + + rtlhal->driver_is_goingto_unload = true; + rtlhal->enter_pnp_sleep = true; + + rtl_lps_leave(hw); + rtl_op_stop(hw); + device_set_wakeup_enable(wiphy_dev(hw->wiphy), true); + return 0; +} + +static int rtl_op_resume(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct timeval ts; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n"); + rtlhal->driver_is_goingto_unload = false; + rtlhal->enter_pnp_sleep = false; + rtlhal->wake_from_pnp_sleep = true; + + /* to resovle s4 can not wake up*/ + do_gettimeofday(&ts); + if (ts.tv_sec - rtlhal->last_suspend_sec < 5) + return -1; + + rtl_op_start(hw); + device_set_wakeup_enable(wiphy_dev(hw->wiphy), false); + ieee80211_resume_disconnect(mac->vif); + rtlhal->wake_from_pnp_sleep = false; + return 0; +} +#endif + +static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct ieee80211_conf *conf = &hw->conf; + + if (mac->skip_scan) + return 1; + + mutex_lock(&rtlpriv->locks.conf_mutex); + if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /* BIT(2)*/ + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "IEEE80211_CONF_CHANGE_LISTEN_INTERVAL\n"); + } + + /*For IPS */ + if (changed & IEEE80211_CONF_CHANGE_IDLE) { + if (hw->conf.flags & IEEE80211_CONF_IDLE) + rtl_ips_nic_off(hw); + else + rtl_ips_nic_on(hw); + } else { + /* + *although rfoff may not cause by ips, but we will + *check the reason in set_rf_power_state function + */ + if (unlikely(ppsc->rfpwr_state == ERFOFF)) + rtl_ips_nic_on(hw); + } + + /*For LPS */ + if (changed & IEEE80211_CONF_CHANGE_PS) { + cancel_delayed_work(&rtlpriv->works.ps_work); + cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); + if (conf->flags & IEEE80211_CONF_PS) { + rtlpriv->psc.sw_ps_enabled = true; + /* sleep here is must, or we may recv the beacon and + * cause mac80211 into wrong ps state, this will cause + * power save nullfunc send fail, and further cause + * pkt loss, So sleep must quickly but not immediatly + * because that will cause nullfunc send by mac80211 + * fail, and cause pkt loss, we have tested that 5mA + * is worked very well */ + if (!rtlpriv->psc.multi_buffered) + queue_delayed_work(rtlpriv->works.rtl_wq, + &rtlpriv->works.ps_work, + MSECS(5)); + } else { + rtl_swlps_rf_awake(hw); + rtlpriv->psc.sw_ps_enabled = false; + } + } + + if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n", + hw->conf.long_frame_max_tx_count); + mac->retry_long = hw->conf.long_frame_max_tx_count; + mac->retry_short = hw->conf.long_frame_max_tx_count; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT, + (u8 *)(&hw->conf.long_frame_max_tx_count)); + } + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL && + !rtlpriv->proximity.proxim_on) { + struct ieee80211_channel *channel = hw->conf.chandef.chan; + enum nl80211_chan_width width = hw->conf.chandef.width; + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; + u8 wide_chan = (u8) channel->hw_value; + + /* channel_type is for 20&40M */ + if (width < NL80211_CHAN_WIDTH_80) + channel_type = + cfg80211_get_chandef_type(&hw->conf.chandef); + if (mac->act_scanning) + mac->n_channels++; + + if (rtlpriv->dm.supp_phymode_switch && + mac->link_state < MAC80211_LINKED && + !mac->act_scanning) { + if (rtlpriv->cfg->ops->chk_switch_dmdp) + rtlpriv->cfg->ops->chk_switch_dmdp(hw); + } + + /* + *because we should back channel to + *current_network.chan in in scanning, + *So if set_chan == current_network.chan + *we should set it. + *because mac80211 tell us wrong bw40 + *info for cisco1253 bw20, so we modify + *it here based on UPPER & LOWER + */ + + if (width >= NL80211_CHAN_WIDTH_80) { + if (width == NL80211_CHAN_WIDTH_80) { + u32 center = hw->conf.chandef.center_freq1; + u32 primary = + (u32)hw->conf.chandef.chan->center_freq; + + rtlphy->current_chan_bw = + HT_CHANNEL_WIDTH_80; + mac->bw_80 = true; + mac->bw_40 = true; + if (center > primary) { + mac->cur_80_prime_sc = + PRIME_CHNL_OFFSET_LOWER; + if (center - primary == 10) { + mac->cur_40_prime_sc = + PRIME_CHNL_OFFSET_UPPER; + + wide_chan += 2; + } else if (center - primary == 30) { + mac->cur_40_prime_sc = + PRIME_CHNL_OFFSET_LOWER; + + wide_chan += 6; + } + } else { + mac->cur_80_prime_sc = + PRIME_CHNL_OFFSET_UPPER; + if (primary - center == 10) { + mac->cur_40_prime_sc = + PRIME_CHNL_OFFSET_LOWER; + + wide_chan -= 2; + } else if (primary - center == 30) { + mac->cur_40_prime_sc = + PRIME_CHNL_OFFSET_UPPER; + + wide_chan -= 6; + } + } + } + } else { + switch (channel_type) { + case NL80211_CHAN_HT20: + case NL80211_CHAN_NO_HT: + /* SC */ + mac->cur_40_prime_sc = + PRIME_CHNL_OFFSET_DONT_CARE; + rtlphy->current_chan_bw = + HT_CHANNEL_WIDTH_20; + mac->bw_40 = false; + mac->bw_80 = false; + break; + case NL80211_CHAN_HT40MINUS: + /* SC */ + mac->cur_40_prime_sc = + PRIME_CHNL_OFFSET_UPPER; + rtlphy->current_chan_bw = + HT_CHANNEL_WIDTH_20_40; + mac->bw_40 = true; + mac->bw_80 = false; + + /*wide channel */ + wide_chan -= 2; + + break; + case NL80211_CHAN_HT40PLUS: + /* SC */ + mac->cur_40_prime_sc = + PRIME_CHNL_OFFSET_LOWER; + rtlphy->current_chan_bw = + HT_CHANNEL_WIDTH_20_40; + mac->bw_40 = true; + mac->bw_80 = false; + + /*wide channel */ + wide_chan += 2; + + break; + default: + mac->bw_40 = false; + mac->bw_80 = false; + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + } + + if (wide_chan <= 0) + wide_chan = 1; + + /* In scanning, when before we offchannel we may send a ps=1 + * null to AP, and then we may send a ps = 0 null to AP quickly, + * but first null may have caused AP to put lots of packet to + * hw tx buffer. These packets must be tx'd before we go off + * channel so we must delay more time to let AP flush these + * packets before going offchannel, or dis-association or + * delete BA will be caused by AP + */ + if (rtlpriv->mac80211.offchan_delay) { + rtlpriv->mac80211.offchan_delay = false; + mdelay(50); + } + + rtlphy->current_channel = wide_chan; + + rtlpriv->cfg->ops->switch_channel(hw); + rtlpriv->cfg->ops->set_channel_access(hw); + rtlpriv->cfg->ops->set_bw_mode(hw, channel_type); + } + + mutex_unlock(&rtlpriv->locks.conf_mutex); + + return 0; +} + +static void rtl_op_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *new_flags, u64 multicast) +{ + bool update_rcr = false; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + *new_flags &= RTL_SUPPORTED_FILTERS; + if (0 == changed_flags) + return; + + /*TODO: we disable broadcase now, so enable here */ + if (changed_flags & FIF_ALLMULTI) { + if (*new_flags & FIF_ALLMULTI) { + mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AM] | + rtlpriv->cfg->maps[MAC_RCR_AB]; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "Enable receive multicast frame\n"); + } else { + mac->rx_conf &= ~(rtlpriv->cfg->maps[MAC_RCR_AM] | + rtlpriv->cfg->maps[MAC_RCR_AB]); + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "Disable receive multicast frame\n"); + } + update_rcr = true; + } + + if (changed_flags & FIF_FCSFAIL) { + if (*new_flags & FIF_FCSFAIL) { + mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACRC32]; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "Enable receive FCS error frame\n"); + } else { + mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACRC32]; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "Disable receive FCS error frame\n"); + } + if (!update_rcr) + update_rcr = true; + } + + /* if ssid not set to hw don't check bssid + * here just used for linked scanning, & linked + * and nolink check bssid is set in set network_type + */ + if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && + (mac->link_state >= MAC80211_LINKED)) { + if (mac->opmode != NL80211_IFTYPE_AP && + mac->opmode != NL80211_IFTYPE_MESH_POINT) { + if (*new_flags & FIF_BCN_PRBRESP_PROMISC) + rtlpriv->cfg->ops->set_chk_bssid(hw, false); + else + rtlpriv->cfg->ops->set_chk_bssid(hw, true); + if (update_rcr) + update_rcr = false; + } + } + + if (changed_flags & FIF_CONTROL) { + if (*new_flags & FIF_CONTROL) { + mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF]; + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "Enable receive control frame.\n"); + } else { + mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF]; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "Disable receive control frame.\n"); + } + if (!update_rcr) + update_rcr = true; + } + + if (changed_flags & FIF_OTHER_BSS) { + if (*new_flags & FIF_OTHER_BSS) { + mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AAP]; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "Enable receive other BSS's frame.\n"); + } else { + mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_AAP]; + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "Disable receive other BSS's frame.\n"); + } + if (!update_rcr) + update_rcr = true; + } + + if (update_rcr) + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, + (u8 *)(&mac->rx_conf)); +} +static int rtl_op_sta_add(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_sta_info *sta_entry; + + if (sta) { + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + spin_lock_bh(&rtlpriv->locks.entry_list_lock); + list_add_tail(&sta_entry->list, &rtlpriv->entry_list); + spin_unlock_bh(&rtlpriv->locks.entry_list_lock); + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + sta_entry->wireless_mode = WIRELESS_MODE_G; + if (sta->supp_rates[0] <= 0xf) + sta_entry->wireless_mode = WIRELESS_MODE_B; + if (sta->ht_cap.ht_supported) + sta_entry->wireless_mode = WIRELESS_MODE_N_24G; + + if (vif->type == NL80211_IFTYPE_ADHOC) + sta_entry->wireless_mode = WIRELESS_MODE_G; + } else if (rtlhal->current_bandtype == BAND_ON_5G) { + sta_entry->wireless_mode = WIRELESS_MODE_A; + if (sta->ht_cap.ht_supported) + sta_entry->wireless_mode = WIRELESS_MODE_N_5G; + if (sta->vht_cap.vht_supported) + sta_entry->wireless_mode = WIRELESS_MODE_AC_5G; + + if (vif->type == NL80211_IFTYPE_ADHOC) + sta_entry->wireless_mode = WIRELESS_MODE_A; + } + /*disable cck rate for p2p*/ + if (mac->p2p) + sta->supp_rates[0] &= 0xfffffff0; + + memcpy(sta_entry->mac_addr, sta->addr, ETH_ALEN); + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + "Add sta addr is %pM\n", sta->addr); + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); + } + + return 0; +} + +static int rtl_op_sta_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_sta_info *sta_entry; + if (sta) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + "Remove sta addr is %pM\n", sta->addr); + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + sta_entry->wireless_mode = 0; + sta_entry->ratr_index = 0; + spin_lock_bh(&rtlpriv->locks.entry_list_lock); + list_del(&sta_entry->list); + spin_unlock_bh(&rtlpriv->locks.entry_list_lock); + } + return 0; +} +static int _rtl_get_hal_qnum(u16 queue) +{ + int qnum; + + switch (queue) { + case 0: + qnum = AC3_VO; + break; + case 1: + qnum = AC2_VI; + break; + case 2: + qnum = AC0_BE; + break; + case 3: + qnum = AC1_BK; + break; + default: + qnum = AC0_BE; + break; + } + return qnum; +} + +/* + *for mac80211 VO = 0, VI = 1, BE = 2, BK = 3 + *for rtl819x BE = 0, BK = 1, VI = 2, VO = 3 + */ +static int rtl_op_conf_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u16 queue, + const struct ieee80211_tx_queue_params *param) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + int aci; + + if (queue >= AC_MAX) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "queue number %d is incorrect!\n", queue); + return -EINVAL; + } + + aci = _rtl_get_hal_qnum(queue); + mac->ac[aci].aifs = param->aifs; + mac->ac[aci].cw_min = cpu_to_le16(param->cw_min); + mac->ac[aci].cw_max = cpu_to_le16(param->cw_max); + mac->ac[aci].tx_op = cpu_to_le16(param->txop); + memcpy(&mac->edca_param[aci], param, sizeof(*param)); + rtlpriv->cfg->ops->set_qos(hw, aci); + return 0; +} + +static void send_beacon_frame(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct sk_buff *skb = ieee80211_beacon_get(hw, vif); + struct rtl_tcb_desc tcb_desc; + + if (skb) { + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + rtlpriv->intf_ops->adapter_tx(hw, NULL, skb, &tcb_desc); + } +} + +static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changed) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + mutex_lock(&rtlpriv->locks.conf_mutex); + if ((vif->type == NL80211_IFTYPE_ADHOC) || + (vif->type == NL80211_IFTYPE_AP) || + (vif->type == NL80211_IFTYPE_MESH_POINT)) { + if ((changed & BSS_CHANGED_BEACON) || + (changed & BSS_CHANGED_BEACON_ENABLED && + bss_conf->enable_beacon)) { + if (mac->beacon_enabled == 0) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + "BSS_CHANGED_BEACON_ENABLED\n"); + + /*start hw beacon interrupt. */ + /*rtlpriv->cfg->ops->set_bcn_reg(hw); */ + mac->beacon_enabled = 1; + rtlpriv->cfg->ops->update_interrupt_mask(hw, + rtlpriv->cfg->maps + [RTL_IBSS_INT_MASKS], 0); + + if (rtlpriv->cfg->ops->linked_set_reg) + rtlpriv->cfg->ops->linked_set_reg(hw); + send_beacon_frame(hw, vif); + } + } + if ((changed & BSS_CHANGED_BEACON_ENABLED && + !bss_conf->enable_beacon)) { + if (mac->beacon_enabled == 1) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + "ADHOC DISABLE BEACON\n"); + + mac->beacon_enabled = 0; + rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, + rtlpriv->cfg->maps + [RTL_IBSS_INT_MASKS]); + } + } + if (changed & BSS_CHANGED_BEACON_INT) { + RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE, + "BSS_CHANGED_BEACON_INT\n"); + mac->beacon_interval = bss_conf->beacon_int; + rtlpriv->cfg->ops->set_bcn_intv(hw); + } + } + + /*TODO: reference to enum ieee80211_bss_change */ + if (changed & BSS_CHANGED_ASSOC) { + u8 mstatus; + if (bss_conf->assoc) { + struct ieee80211_sta *sta = NULL; + u8 keep_alive = 10; + + mstatus = RT_MEDIA_CONNECT; + /* we should reset all sec info & cam + * before set cam after linked, we should not + * reset in disassoc, that will cause tkip->wep + * fail because some flag will be wrong */ + /* reset sec info */ + rtl_cam_reset_sec_info(hw); + /* reset cam to fix wep fail issue + * when change from wpa to wep */ + rtl_cam_reset_all_entry(hw); + + mac->link_state = MAC80211_LINKED; + mac->cnt_after_linked = 0; + mac->assoc_id = bss_conf->aid; + memcpy(mac->bssid, bss_conf->bssid, ETH_ALEN); + + if (rtlpriv->cfg->ops->linked_set_reg) + rtlpriv->cfg->ops->linked_set_reg(hw); + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid); + if (!sta) { + rcu_read_unlock(); + goto out; + } + RT_TRACE(rtlpriv, COMP_EASY_CONCURRENT, DBG_LOUD, + "send PS STATIC frame\n"); + if (rtlpriv->dm.supp_phymode_switch) { + if (sta->ht_cap.ht_supported) + rtl_send_smps_action(hw, sta, + IEEE80211_SMPS_STATIC); + } + + if (rtlhal->current_bandtype == BAND_ON_5G) { + mac->mode = WIRELESS_MODE_A; + } else { + if (sta->supp_rates[0] <= 0xf) + mac->mode = WIRELESS_MODE_B; + else + mac->mode = WIRELESS_MODE_G; + } + + if (sta->ht_cap.ht_supported) { + if (rtlhal->current_bandtype == BAND_ON_2_4G) + mac->mode = WIRELESS_MODE_N_24G; + else + mac->mode = WIRELESS_MODE_N_5G; + } + + if (sta->vht_cap.vht_supported) { + if (rtlhal->current_bandtype == BAND_ON_5G) + mac->mode = WIRELESS_MODE_AC_5G; + else + mac->mode = WIRELESS_MODE_AC_24G; + } + + if (vif->type == NL80211_IFTYPE_STATION && sta) + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); + rcu_read_unlock(); + + /* to avoid AP Disassociation caused by inactivity */ + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_KEEP_ALIVE, + (u8 *)(&keep_alive)); + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + "BSS_CHANGED_ASSOC\n"); + } else { + mstatus = RT_MEDIA_DISCONNECT; + + if (mac->link_state == MAC80211_LINKED) { + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); + } + if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE) + rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); + mac->link_state = MAC80211_NOLINK; + eth_zero_addr(mac->bssid); + mac->vendor = PEER_UNKNOWN; + mac->mode = 0; + + if (rtlpriv->dm.supp_phymode_switch) { + if (rtlpriv->cfg->ops->chk_switch_dmdp) + rtlpriv->cfg->ops->chk_switch_dmdp(hw); + } + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + "BSS_CHANGED_UN_ASSOC\n"); + } + rtlpriv->cfg->ops->set_network_type(hw, vif->type); + /* For FW LPS: + * To tell firmware we have connected or disconnected + */ + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_JOINBSSRPT, + (u8 *)(&mstatus)); + ppsc->report_linked = (mstatus == RT_MEDIA_CONNECT) ? + true : false; + + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_mediastatus_notify( + rtlpriv, mstatus); + } + + if (changed & BSS_CHANGED_ERP_CTS_PROT) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + "BSS_CHANGED_ERP_CTS_PROT\n"); + mac->use_cts_protect = bss_conf->use_cts_prot; + } + + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, + "BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n", + bss_conf->use_short_preamble); + + mac->short_preamble = bss_conf->use_short_preamble; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACK_PREAMBLE, + (u8 *)(&mac->short_preamble)); + } + + if (changed & BSS_CHANGED_ERP_SLOT) { + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + "BSS_CHANGED_ERP_SLOT\n"); + + if (bss_conf->use_short_slot) + mac->slot_time = RTL_SLOT_TIME_9; + else + mac->slot_time = RTL_SLOT_TIME_20; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, + (u8 *)(&mac->slot_time)); + } + + if (changed & BSS_CHANGED_HT) { + struct ieee80211_sta *sta = NULL; + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + "BSS_CHANGED_HT\n"); + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid); + if (sta) { + if (sta->ht_cap.ampdu_density > + mac->current_ampdu_density) + mac->current_ampdu_density = + sta->ht_cap.ampdu_density; + if (sta->ht_cap.ampdu_factor < + mac->current_ampdu_factor) + mac->current_ampdu_factor = + sta->ht_cap.ampdu_factor; + } + rcu_read_unlock(); + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY, + (u8 *)(&mac->max_mss_density)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_FACTOR, + &mac->current_ampdu_factor); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_MIN_SPACE, + &mac->current_ampdu_density); + } + + if (changed & BSS_CHANGED_BSSID) { + u32 basic_rates; + struct ieee80211_sta *sta = NULL; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID, + (u8 *)bss_conf->bssid); + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, + "bssid: %pM\n", bss_conf->bssid); + + mac->vendor = PEER_UNKNOWN; + memcpy(mac->bssid, bss_conf->bssid, ETH_ALEN); + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid); + if (!sta) { + rcu_read_unlock(); + goto out; + } + + if (rtlhal->current_bandtype == BAND_ON_5G) { + mac->mode = WIRELESS_MODE_A; + } else { + if (sta->supp_rates[0] <= 0xf) + mac->mode = WIRELESS_MODE_B; + else + mac->mode = WIRELESS_MODE_G; + } + + if (sta->ht_cap.ht_supported) { + if (rtlhal->current_bandtype == BAND_ON_2_4G) + mac->mode = WIRELESS_MODE_N_24G; + else + mac->mode = WIRELESS_MODE_N_5G; + } + + if (sta->vht_cap.vht_supported) { + if (rtlhal->current_bandtype == BAND_ON_5G) + mac->mode = WIRELESS_MODE_AC_5G; + else + mac->mode = WIRELESS_MODE_AC_24G; + } + + /* just station need it, because ibss & ap mode will + * set in sta_add, and will be NULL here */ + if (vif->type == NL80211_IFTYPE_STATION) { + struct rtl_sta_info *sta_entry; + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + sta_entry->wireless_mode = mac->mode; + } + + if (sta->ht_cap.ht_supported) { + mac->ht_enable = true; + + /* + * for cisco 1252 bw20 it's wrong + * if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { + * mac->bw_40 = true; + * } + * */ + } + + if (sta->vht_cap.vht_supported) + mac->vht_enable = true; + + if (changed & BSS_CHANGED_BASIC_RATES) { + /* for 5G must << RATE_6M_INDEX = 4, + * because 5G have no cck rate*/ + if (rtlhal->current_bandtype == BAND_ON_5G) + basic_rates = sta->supp_rates[1] << 4; + else + basic_rates = sta->supp_rates[0]; + + mac->basic_rates = basic_rates; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, + (u8 *)(&basic_rates)); + } + rcu_read_unlock(); + } +out: + mutex_unlock(&rtlpriv->locks.conf_mutex); +} + +static u64 rtl_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u64 tsf; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *)(&tsf)); + return tsf; +} + +static void rtl_op_set_tsf(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u64 tsf) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0; + + mac->tsf = tsf; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *)(&bibss)); +} + +static void rtl_op_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp = 0; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_DUAL_TSF_RST, (u8 *)(&tmp)); +} + +static void rtl_op_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd cmd, + struct ieee80211_sta *sta) +{ + switch (cmd) { + case STA_NOTIFY_SLEEP: + break; + case STA_NOTIFY_AWAKE: + break; + default: + break; + } +} + +static int rtl_op_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, + u8 buf_size, bool amsdu) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (action) { + case IEEE80211_AMPDU_TX_START: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + "IEEE80211_AMPDU_TX_START: TID:%d\n", tid); + return rtl_tx_agg_start(hw, vif, sta, tid, ssn); + case IEEE80211_AMPDU_TX_STOP_CONT: + case IEEE80211_AMPDU_TX_STOP_FLUSH: + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid); + return rtl_tx_agg_stop(hw, vif, sta, tid); + case IEEE80211_AMPDU_TX_OPERATIONAL: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid); + rtl_tx_agg_oper(hw, sta, tid); + break; + case IEEE80211_AMPDU_RX_START: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + "IEEE80211_AMPDU_RX_START:TID:%d\n", tid); + return rtl_rx_agg_start(hw, sta, tid); + case IEEE80211_AMPDU_RX_STOP: + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, + "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid); + return rtl_rx_agg_stop(hw, sta, tid); + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "IEEE80211_AMPDU_ERR!!!!:\n"); + return -EOPNOTSUPP; + } + return 0; +} + +static void rtl_op_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *mac_addr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); + mac->act_scanning = true; + if (rtlpriv->link_info.higher_busytraffic) { + mac->skip_scan = true; + return; + } + + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_scan_notify(rtlpriv, 1); + + if (rtlpriv->dm.supp_phymode_switch) { + if (rtlpriv->cfg->ops->chk_switch_dmdp) + rtlpriv->cfg->ops->chk_switch_dmdp(hw); + } + + if (mac->link_state == MAC80211_LINKED) { + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); + mac->link_state = MAC80211_LINKED_SCANNING; + } else { + rtl_ips_nic_on(hw); + } + + /* Dul mac */ + rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; + + rtlpriv->cfg->ops->led_control(hw, LED_CTL_SITE_SURVEY); + rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP_BAND0); +} + +static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); + mac->act_scanning = false; + mac->skip_scan = false; + if (rtlpriv->link_info.higher_busytraffic) + return; + + /* p2p will use 1/6/11 to scan */ + if (mac->n_channels == 3) + mac->p2p_in_use = true; + else + mac->p2p_in_use = false; + mac->n_channels = 0; + /* Dul mac */ + rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; + + if (mac->link_state == MAC80211_LINKED_SCANNING) { + mac->link_state = MAC80211_LINKED; + if (mac->opmode == NL80211_IFTYPE_STATION) { + /* fix fwlps issue */ + rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); + } + } + + rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_scan_notify(rtlpriv, 0); +} + +static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 key_type = NO_ENCRYPTION; + u8 key_idx; + bool group_key = false; + bool wep_only = false; + int err = 0; + u8 mac_addr[ETH_ALEN]; + u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "not open hw encryption\n"); + return -ENOSPC; /*User disabled HW-crypto */ + } + /* To support IBSS, use sw-crypto for GTK */ + if (((vif->type == NL80211_IFTYPE_ADHOC) || + (vif->type == NL80211_IFTYPE_MESH_POINT)) && + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -ENOSPC; + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "%s hardware based encryption for keyidx: %d, mac: %pM\n", + cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, + sta ? sta->addr : bcast_addr); + rtlpriv->sec.being_setkey = true; + rtl_ips_nic_on(hw); + mutex_lock(&rtlpriv->locks.conf_mutex); + /* <1> get encryption alg */ + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + key_type = WEP40_ENCRYPTION; + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP40\n"); + break; + case WLAN_CIPHER_SUITE_WEP104: + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP104\n"); + key_type = WEP104_ENCRYPTION; + break; + case WLAN_CIPHER_SUITE_TKIP: + key_type = TKIP_ENCRYPTION; + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:TKIP\n"); + break; + case WLAN_CIPHER_SUITE_CCMP: + key_type = AESCCMP_ENCRYPTION; + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n"); + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + /* HW don't support CMAC encryption, + * use software CMAC encryption + */ + key_type = AESCMAC_ENCRYPTION; + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n"); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "HW don't support CMAC encrypiton, use software CMAC encrypiton\n"); + err = -EOPNOTSUPP; + goto out_unlock; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "alg_err:%x!!!!:\n", key->cipher); + goto out_unlock; + } + if (key_type == WEP40_ENCRYPTION || + key_type == WEP104_ENCRYPTION || + vif->type == NL80211_IFTYPE_ADHOC) + rtlpriv->sec.use_defaultkey = true; + + /* <2> get key_idx */ + key_idx = (u8) (key->keyidx); + if (key_idx > 3) + goto out_unlock; + /* <3> if pairwise key enable_hw_sec */ + group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE); + + /* wep always be group key, but there are two conditions: + * 1) wep only: is just for wep enc, in this condition + * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION + * will be true & enable_hw_sec will be set when wep + * ke setting. + * 2) wep(group) + AES(pairwise): some AP like cisco + * may use it, in this condition enable_hw_sec will not + * be set when wep key setting */ + /* we must reset sec_info after lingked before set key, + * or some flag will be wrong*/ + if (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT) { + if (!group_key || key_type == WEP40_ENCRYPTION || + key_type == WEP104_ENCRYPTION) { + if (group_key) + wep_only = true; + rtlpriv->cfg->ops->enable_hw_sec(hw); + } + } else { + if ((!group_key) || (vif->type == NL80211_IFTYPE_ADHOC) || + rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { + if (rtlpriv->sec.pairwise_enc_algorithm == + NO_ENCRYPTION && + (key_type == WEP40_ENCRYPTION || + key_type == WEP104_ENCRYPTION)) + wep_only = true; + rtlpriv->sec.pairwise_enc_algorithm = key_type; + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1 TKIP:2 AES:4 WEP104:5)\n", + key_type); + rtlpriv->cfg->ops->enable_hw_sec(hw); + } + } + /* <4> set key based on cmd */ + switch (cmd) { + case SET_KEY: + if (wep_only) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set WEP(group/pairwise) key\n"); + /* Pairwise key with an assigned MAC address. */ + rtlpriv->sec.pairwise_enc_algorithm = key_type; + rtlpriv->sec.group_enc_algorithm = key_type; + /*set local buf about wep key. */ + memcpy(rtlpriv->sec.key_buf[key_idx], + key->key, key->keylen); + rtlpriv->sec.key_len[key_idx] = key->keylen; + eth_zero_addr(mac_addr); + } else if (group_key) { /* group key */ + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set group key\n"); + /* group key */ + rtlpriv->sec.group_enc_algorithm = key_type; + /*set local buf about group key. */ + memcpy(rtlpriv->sec.key_buf[key_idx], + key->key, key->keylen); + rtlpriv->sec.key_len[key_idx] = key->keylen; + memcpy(mac_addr, bcast_addr, ETH_ALEN); + } else { /* pairwise key */ + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set pairwise key\n"); + if (!sta) { + RT_ASSERT(false, + "pairwise key without mac_addr\n"); + + err = -EOPNOTSUPP; + goto out_unlock; + } + /* Pairwise key with an assigned MAC address. */ + rtlpriv->sec.pairwise_enc_algorithm = key_type; + /*set local buf about pairwise key. */ + memcpy(rtlpriv->sec.key_buf[PAIRWISE_KEYIDX], + key->key, key->keylen); + rtlpriv->sec.key_len[PAIRWISE_KEYIDX] = key->keylen; + rtlpriv->sec.pairwise_key = + rtlpriv->sec.key_buf[PAIRWISE_KEYIDX]; + memcpy(mac_addr, sta->addr, ETH_ALEN); + } + rtlpriv->cfg->ops->set_key(hw, key_idx, mac_addr, + group_key, key_type, wep_only, + false); + /* <5> tell mac80211 do something: */ + /*must use sw generate IV, or can not work !!!!. */ + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + key->hw_key_idx = key_idx; + if (key_type == TKIP_ENCRYPTION) + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + /*use software CCMP encryption for management frames (MFP) */ + if (key_type == AESCCMP_ENCRYPTION) + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; + break; + case DISABLE_KEY: + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "disable key delete one entry\n"); + /*set local buf about wep key. */ + if (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_MESH_POINT) { + if (sta) + rtl_cam_del_entry(hw, sta->addr); + } + memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen); + rtlpriv->sec.key_len[key_idx] = 0; + eth_zero_addr(mac_addr); + /* + *mac80211 will delete entrys one by one, + *so don't use rtl_cam_reset_all_entry + *or clear all entry here. + */ + rtl_cam_delete_one_entry(hw, mac_addr, key_idx); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "cmd_err:%x!!!!:\n", cmd); + } +out_unlock: + mutex_unlock(&rtlpriv->locks.conf_mutex); + rtlpriv->sec.being_setkey = false; + return err; +} + +static void rtl_op_rfkill_poll(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + bool radio_state; + bool blocked; + u8 valid = 0; + + if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) + return; + + mutex_lock(&rtlpriv->locks.conf_mutex); + + /*if Radio On return true here */ + radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); + + if (valid) { + if (unlikely(radio_state != rtlpriv->rfkill.rfkill_state)) { + rtlpriv->rfkill.rfkill_state = radio_state; + + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "wireless radio switch turned %s\n", + radio_state ? "on" : "off"); + + blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1; + wiphy_rfkill_set_hw_state(hw->wiphy, blocked); + } + } + + mutex_unlock(&rtlpriv->locks.conf_mutex); +} + +/* this function is called by mac80211 to flush tx buffer + * before switch channle or power save, or tx buffer packet + * maybe send after offchannel or rf sleep, this may cause + * dis-association by AP */ +static void rtl_op_flush(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u32 queues, + bool drop) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->intf_ops->flush) + rtlpriv->intf_ops->flush(hw, queues, drop); +} + +/* Description: + * This routine deals with the Power Configuration CMD + * parsing for RTL8723/RTL8188E Series IC. + * Assumption: + * We should follow specific format that was released from HW SD. + */ +bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version, + u8 faversion, u8 interface_type, + struct wlan_pwr_cfg pwrcfgcmd[]) +{ + struct wlan_pwr_cfg cfg_cmd = {0}; + bool polling_bit = false; + u32 ary_idx = 0; + u8 value = 0; + u32 offset = 0; + u32 polling_count = 0; + u32 max_polling_cnt = 5000; + + do { + cfg_cmd = pwrcfgcmd[ary_idx]; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "rtl_hal_pwrseqcmdparsing(): offset(%#x),cut_msk(%#x), famsk(%#x), interface_msk(%#x), base(%#x), cmd(%#x), msk(%#x), value(%#x)\n", + GET_PWR_CFG_OFFSET(cfg_cmd), + GET_PWR_CFG_CUT_MASK(cfg_cmd), + GET_PWR_CFG_FAB_MASK(cfg_cmd), + GET_PWR_CFG_INTF_MASK(cfg_cmd), + GET_PWR_CFG_BASE(cfg_cmd), GET_PWR_CFG_CMD(cfg_cmd), + GET_PWR_CFG_MASK(cfg_cmd), GET_PWR_CFG_VALUE(cfg_cmd)); + + if ((GET_PWR_CFG_FAB_MASK(cfg_cmd)&faversion) && + (GET_PWR_CFG_CUT_MASK(cfg_cmd)&cut_version) && + (GET_PWR_CFG_INTF_MASK(cfg_cmd)&interface_type)) { + switch (GET_PWR_CFG_CMD(cfg_cmd)) { + case PWR_CMD_READ: + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "rtl_hal_pwrseqcmdparsing(): PWR_CMD_READ\n"); + break; + case PWR_CMD_WRITE: + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "rtl_hal_pwrseqcmdparsing(): PWR_CMD_WRITE\n"); + offset = GET_PWR_CFG_OFFSET(cfg_cmd); + + /*Read the value from system register*/ + value = rtl_read_byte(rtlpriv, offset); + value &= (~(GET_PWR_CFG_MASK(cfg_cmd))); + value |= (GET_PWR_CFG_VALUE(cfg_cmd) & + GET_PWR_CFG_MASK(cfg_cmd)); + + /*Write the value back to sytem register*/ + rtl_write_byte(rtlpriv, offset, value); + break; + case PWR_CMD_POLLING: + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "rtl_hal_pwrseqcmdparsing(): PWR_CMD_POLLING\n"); + polling_bit = false; + offset = GET_PWR_CFG_OFFSET(cfg_cmd); + + do { + value = rtl_read_byte(rtlpriv, offset); + + value &= GET_PWR_CFG_MASK(cfg_cmd); + if (value == + (GET_PWR_CFG_VALUE(cfg_cmd) & + GET_PWR_CFG_MASK(cfg_cmd))) + polling_bit = true; + else + udelay(10); + + if (polling_count++ > max_polling_cnt) + return false; + } while (!polling_bit); + break; + case PWR_CMD_DELAY: + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "rtl_hal_pwrseqcmdparsing(): PWR_CMD_DELAY\n"); + if (GET_PWR_CFG_VALUE(cfg_cmd) == + PWRSEQ_DELAY_US) + udelay(GET_PWR_CFG_OFFSET(cfg_cmd)); + else + mdelay(GET_PWR_CFG_OFFSET(cfg_cmd)); + break; + case PWR_CMD_END: + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "rtl_hal_pwrseqcmdparsing(): PWR_CMD_END\n"); + return true; + default: + RT_ASSERT(false, + "rtl_hal_pwrseqcmdparsing(): Unknown CMD!!\n"); + break; + } + } + ary_idx++; + } while (1); + + return true; +} +EXPORT_SYMBOL(rtl_hal_pwrseqcmdparsing); + +bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + struct rtl_tx_desc *pdesc; + unsigned long flags; + struct sk_buff *pskb = NULL; + + ring = &rtlpci->tx_ring[BEACON_QUEUE]; + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + pskb = __skb_dequeue(&ring->queue); + if (pskb) + kfree_skb(pskb); + + /*this is wrong, fill_tx_cmddesc needs update*/ + pdesc = &ring->desc[0]; + + rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); + + __skb_queue_tail(&ring->queue, skb); + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + + rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); + + return true; +} +EXPORT_SYMBOL(rtl_cmd_send_packet); +const struct ieee80211_ops rtl_ops = { + .start = rtl_op_start, + .stop = rtl_op_stop, + .tx = rtl_op_tx, + .add_interface = rtl_op_add_interface, + .remove_interface = rtl_op_remove_interface, + .change_interface = rtl_op_change_interface, +#ifdef CONFIG_PM + .suspend = rtl_op_suspend, + .resume = rtl_op_resume, +#endif + .config = rtl_op_config, + .configure_filter = rtl_op_configure_filter, + .set_key = rtl_op_set_key, + .conf_tx = rtl_op_conf_tx, + .bss_info_changed = rtl_op_bss_info_changed, + .get_tsf = rtl_op_get_tsf, + .set_tsf = rtl_op_set_tsf, + .reset_tsf = rtl_op_reset_tsf, + .sta_notify = rtl_op_sta_notify, + .ampdu_action = rtl_op_ampdu_action, + .sw_scan_start = rtl_op_sw_scan_start, + .sw_scan_complete = rtl_op_sw_scan_complete, + .rfkill_poll = rtl_op_rfkill_poll, + .sta_add = rtl_op_sta_add, + .sta_remove = rtl_op_sta_remove, + .flush = rtl_op_flush, +}; +EXPORT_SYMBOL_GPL(rtl_ops); + +bool rtl_btc_status_false(void) +{ + return false; +} +EXPORT_SYMBOL_GPL(rtl_btc_status_false); + +void rtl_dm_diginit(struct ieee80211_hw *hw, u32 cur_igvalue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + dm_digtable->dig_enable_flag = true; + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; + dm_digtable->cur_igvalue = cur_igvalue; + dm_digtable->pre_igvalue = 0; + dm_digtable->cur_sta_cstate = DIG_STA_DISCONNECT; + dm_digtable->presta_cstate = DIG_STA_DISCONNECT; + dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT; + dm_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW; + dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; + dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; + dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; + dm_digtable->rx_gain_max = DM_DIG_MAX; + dm_digtable->rx_gain_min = DM_DIG_MIN; + dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; + dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; + dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; + dm_digtable->pre_cck_cca_thres = 0xff; + dm_digtable->cur_cck_cca_thres = 0x83; + dm_digtable->forbidden_igi = DM_DIG_MIN; + dm_digtable->large_fa_hit = 0; + dm_digtable->recover_cnt = 0; + dm_digtable->dig_min_0 = 0x25; + dm_digtable->dig_min_1 = 0x25; + dm_digtable->media_connect_0 = false; + dm_digtable->media_connect_1 = false; + rtlpriv->dm.dm_initialgain_enable = true; + dm_digtable->bt30_cur_igi = 0x32; + dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX; + dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_LOWRSSI; +} +EXPORT_SYMBOL(rtl_dm_diginit); diff --git a/drivers/net/wireless/realtek/rtlwifi/core.h b/drivers/net/wireless/realtek/rtlwifi/core.h new file mode 100644 index 000000000000..782ac2fc4b28 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/core.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL_CORE_H__ +#define __RTL_CORE_H__ + +#define RTL_SUPPORTED_FILTERS \ + (FIF_ALLMULTI | FIF_CONTROL | \ + FIF_OTHER_BSS | \ + FIF_FCSFAIL | \ + FIF_BCN_PRBRESP_PROMISC) + +#define DM_DIG_THRESH_HIGH 40 +#define DM_DIG_THRESH_LOW 35 +#define DM_FALSEALARM_THRESH_LOW 400 +#define DM_FALSEALARM_THRESH_HIGH 1000 + +#define DM_DIG_MAX 0x3e +#define DM_DIG_MIN 0x1e +#define DM_DIG_MAX_AP 0x32 +#define DM_DIG_BACKOFF_MAX 12 +#define DM_DIG_BACKOFF_MIN -4 +#define DM_DIG_BACKOFF_DEFAULT 10 + +enum cck_packet_detection_threshold { + CCK_PD_STAGE_LOWRSSI = 0, + CCK_PD_STAGE_HIGHRSSI = 1, + CCK_FA_STAGE_LOW = 2, + CCK_FA_STAGE_HIGH = 3, + CCK_PD_STAGE_MAX = 4, +}; + +enum dm_dig_ext_port_alg_e { + DIG_EXT_PORT_STAGE_0 = 0, + DIG_EXT_PORT_STAGE_1 = 1, + DIG_EXT_PORT_STAGE_2 = 2, + DIG_EXT_PORT_STAGE_3 = 3, + DIG_EXT_PORT_STAGE_MAX = 4, +}; + +enum dm_dig_connect_e { + DIG_STA_DISCONNECT, + DIG_STA_CONNECT, + DIG_STA_BEFORE_CONNECT, + DIG_MULTISTA_DISCONNECT, + DIG_MULTISTA_CONNECT, + DIG_AP_DISCONNECT, + DIG_AP_CONNECT, + DIG_AP_ADD_STATION, + DIG_CONNECT_MAX +}; + +extern const struct ieee80211_ops rtl_ops; +void rtl_fw_cb(const struct firmware *firmware, void *context); +void rtl_wowlan_fw_cb(const struct firmware *firmware, void *context); +void rtl_addr_delay(u32 addr); +void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr, + u32 mask, u32 data); +void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data); +bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); +bool rtl_btc_status_false(void); +void rtl_dm_diginit(struct ieee80211_hw *hw, u32 cur_igval); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.c b/drivers/net/wireless/realtek/rtlwifi/debug.c new file mode 100644 index 000000000000..fd25abad2b9e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/debug.c @@ -0,0 +1,50 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + *****************************************************************************/ + +#include "wifi.h" + +#include + +void rtl_dbgp_flag_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 i; + + 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; + + + for (i = 0; i < DBGP_TYPE_MAX; i++) + rtlpriv->dbg.dbgp_type[i] = 0; + + /*Init Debug flag enable condition */ +} +EXPORT_SYMBOL_GPL(rtl_dbgp_flag_init); diff --git a/drivers/net/wireless/realtek/rtlwifi/debug.h b/drivers/net/wireless/realtek/rtlwifi/debug.h new file mode 100644 index 000000000000..fc794b3e9f4a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/debug.h @@ -0,0 +1,241 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + *****************************************************************************/ + +#ifndef __RTL_DEBUG_H__ +#define __RTL_DEBUG_H__ + +/*-------------------------------------------------------------- + Debug level +--------------------------------------------------------------*/ +/* + *Fatal bug. + *For example, Tx/Rx/IO locked up, + *memory access violation, + *resource allocation failed, + *unexpected HW behavior, HW BUG + *and so on. + */ +#define DBG_EMERG 0 + +/* + *Abnormal, rare, or unexpeted cases. + *For example, Packet/IO Ctl canceled, + *device suprisely unremoved and so on. + */ +#define DBG_WARNING 2 + +/* + *Normal case driver developer should + *open, we can see link status like + *assoc/AddBA/DHCP/adapter start and + *so on basic and useful infromations. + */ +#define DBG_DMESG 3 + +/* + *Normal case with useful information + *about current SW or HW state. + *For example, Tx/Rx descriptor to fill, + *Tx/Rx descriptor completed status, + *SW protocol state change, dynamic + *mechanism state change and so on. + */ +#define DBG_LOUD 4 + +/* + *Normal case with detail execution + *flow or information. + */ +#define DBG_TRACE 5 + +/*-------------------------------------------------------------- + Define the rt_trace components +--------------------------------------------------------------*/ +#define COMP_ERR BIT(0) +#define COMP_FW BIT(1) +#define COMP_INIT BIT(2) /*For init/deinit */ +#define COMP_RECV BIT(3) /*For Rx. */ +#define COMP_SEND BIT(4) /*For Tx. */ +#define COMP_MLME BIT(5) /*For MLME. */ +#define COMP_SCAN BIT(6) /*For Scan. */ +#define COMP_INTR BIT(7) /*For interrupt Related. */ +#define COMP_LED BIT(8) /*For LED. */ +#define COMP_SEC BIT(9) /*For sec. */ +#define COMP_BEACON BIT(10) /*For beacon. */ +#define COMP_RATE BIT(11) /*For rate. */ +#define COMP_RXDESC BIT(12) /*For rx desc. */ +#define COMP_DIG BIT(13) /*For DIG */ +#define COMP_TXAGC BIT(14) /*For Tx power */ +#define COMP_HIPWR BIT(15) /*For High Power Mechanism */ +#define COMP_POWER BIT(16) /*For lps/ips/aspm. */ +#define COMP_POWER_TRACKING BIT(17) /*For TX POWER TRACKING */ +#define COMP_BB_POWERSAVING BIT(18) +#define COMP_SWAS BIT(19) /*For SW Antenna Switch */ +#define COMP_RF BIT(20) /*For RF. */ +#define COMP_TURBO BIT(21) /*For EDCA TURBO. */ +#define COMP_RATR BIT(22) +#define COMP_CMD BIT(23) +#define COMP_EFUSE BIT(24) +#define COMP_QOS BIT(25) +#define COMP_MAC80211 BIT(26) +#define COMP_REGD BIT(27) +#define COMP_CHAN BIT(28) +#define COMP_USB BIT(29) +#define COMP_EASY_CONCURRENT COMP_USB /* reuse of this bit is OK */ +#define COMP_BT_COEXIST BIT(30) +#define COMP_IQK BIT(31) + +/*-------------------------------------------------------------- + Define the rt_print components +--------------------------------------------------------------*/ +/* Define EEPROM and EFUSE check module bit*/ +#define EEPROM_W BIT(0) +#define EFUSE_PG BIT(1) +#define EFUSE_READ_ALL BIT(2) + +/* Define init check for module bit*/ +#define INIT_EEPROM BIT(0) +#define INIT_TXPOWER BIT(1) +#define INIT_IQK BIT(2) +#define INIT_RF BIT(3) + +/* Define PHY-BB/RF/MAC check module bit */ +#define PHY_BBR BIT(0) +#define PHY_BBW BIT(1) +#define PHY_RFR BIT(2) +#define PHY_RFW BIT(3) +#define PHY_MACR BIT(4) +#define PHY_MACW BIT(5) +#define PHY_ALLR BIT(6) +#define PHY_ALLW BIT(7) +#define PHY_TXPWR BIT(8) +#define PHY_PWRDIFF BIT(9) + +/* Define Dynamic Mechanism check module bit --> FDM */ +#define WA_IOT BIT(0) +#define DM_PWDB BIT(1) +#define DM_MONITOR BIT(2) +#define DM_DIG BIT(3) +#define DM_EDCA_TURBO BIT(4) + +#define DM_PWDB BIT(1) + +enum dbgp_flag_e { + FQOS = 0, + FTX = 1, + FRX = 2, + FSEC = 3, + FMGNT = 4, + FMLME = 5, + FRESOURCE = 6, + FBEACON = 7, + FISR = 8, + FPHY = 9, + FMP = 10, + FEEPROM = 11, + FPWR = 12, + FDM = 13, + FDBGCtrl = 14, + FC2H = 15, + FBT = 16, + FINIT = 17, + FIOCTL = 18, + DBGP_TYPE_MAX +}; + +#ifdef CONFIG_RTLWIFI_DEBUG + +#define RT_ASSERT(_exp, fmt, ...) \ +do { \ + if (!(_exp)) { \ + printk(KERN_DEBUG KBUILD_MODNAME ":%s(): " fmt, \ + __func__, ##__VA_ARGS__); \ + } \ +} while (0) + +#define RT_TRACE(rtlpriv, comp, level, fmt, ...) \ +do { \ + if (unlikely(((comp) & rtlpriv->dbg.global_debugcomponents) && \ + ((level) <= rtlpriv->dbg.global_debuglevel))) { \ + printk(KERN_DEBUG KBUILD_MODNAME ":%s():<%lx-%x> " fmt, \ + __func__, in_interrupt(), in_atomic(), \ + ##__VA_ARGS__); \ + } \ +} while (0) + +#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) + +#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) + +#else + +struct rtl_priv; + +__printf(2, 3) +static inline void RT_ASSERT(int exp, const char *fmt, ...) +{ +} + +__printf(4, 5) +static inline void RT_TRACE(struct rtl_priv *rtlpriv, + int comp, int level, + const char *fmt, ...) +{ +} + +__printf(4, 5) +static inline void RTPRINT(struct rtl_priv *rtlpriv, + int dbgtype, int dbgflag, + const char *fmt, ...) +{ +} + +static inline void RT_PRINT_DATA(struct rtl_priv *rtlpriv, + int comp, int level, + const char *titlestring, + const void *hexdata, size_t hexdatalen) +{ +} + +#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 new file mode 100644 index 000000000000..0b4082c9272a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c @@ -0,0 +1,1245 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * Tmis 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 + * published by the Free Software Foundation. + * + * Tmis program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * Tme full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#include "wifi.h" +#include "efuse.h" +#include + +static const u8 MAX_PGPKT_SIZE = 9; +static const u8 PGPKT_DATA_SIZE = 8; +static const int EFUSE_MAX_SIZE = 512; + +static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { + {0, 0, 0, 2}, + {0, 1, 0, 2}, + {0, 2, 0, 2}, + {1, 0, 0, 1}, + {1, 0, 1, 1}, + {1, 1, 0, 1}, + {1, 1, 1, 3}, + {1, 3, 0, 17}, + {3, 3, 1, 48}, + {10, 0, 0, 6}, + {10, 3, 0, 1}, + {10, 3, 1, 1}, + {11, 0, 0, 28} +}; + +static void efuse_shadow_read_1byte(struct ieee80211_hw *hw, u16 offset, + u8 *value); +static void efuse_shadow_read_2byte(struct ieee80211_hw *hw, u16 offset, + u16 *value); +static void efuse_shadow_read_4byte(struct ieee80211_hw *hw, u16 offset, + u32 *value); +static void efuse_shadow_write_1byte(struct ieee80211_hw *hw, u16 offset, + u8 value); +static void efuse_shadow_write_2byte(struct ieee80211_hw *hw, u16 offset, + u16 value); +static void efuse_shadow_write_4byte(struct ieee80211_hw *hw, u16 offset, + u32 value); +static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, + u8 data); +static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse); +static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, + u8 *data); +static int efuse_pg_packet_write(struct ieee80211_hw *hw, u8 offset, + u8 word_en, u8 *data); +static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata, + u8 *targetdata); +static u8 enable_efuse_data_write(struct ieee80211_hw *hw, + u16 efuse_addr, u8 word_en, u8 *data); +static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, + u8 pwrstate); +static u16 efuse_get_current_size(struct ieee80211_hw *hw); +static u8 efuse_calculate_word_cnts(u8 word_en); + +void efuse_initialize(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bytetemp; + u8 temp; + + bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN] + 1); + temp = bytetemp | 0x20; + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN] + 1, temp); + + bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL] + 1); + temp = bytetemp & 0xFE; + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL] + 1, temp); + + bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3); + temp = bytetemp | 0x80; + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3, temp); + + rtl_write_byte(rtlpriv, 0x2F8, 0x3); + + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0x72); + +} + +u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 data; + u8 bytetemp; + u8 temp; + u32 k = 0; + const u32 efuse_len = + rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; + + if (address < efuse_len) { + temp = address & 0xFF; + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, + temp); + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 2); + temp = ((address >> 8) & 0x03) | (bytetemp & 0xFC); + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2, + temp); + + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3); + temp = bytetemp & 0x7F; + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, + temp); + + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3); + while (!(bytetemp & 0x80)) { + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg-> + maps[EFUSE_CTRL] + 3); + k++; + if (k == 1000) { + k = 0; + break; + } + } + data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); + return data; + } else + return 0xFF; + +} +EXPORT_SYMBOL(efuse_read_1byte); + +void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bytetemp; + u8 temp; + u32 k = 0; + const u32 efuse_len = + rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; + + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "Addr=%x Data =%x\n", + address, value); + + if (address < efuse_len) { + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], value); + + temp = address & 0xFF; + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, + temp); + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 2); + + temp = ((address >> 8) & 0x03) | (bytetemp & 0xFC); + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 2, temp); + + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3); + temp = bytetemp | 0x80; + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3, temp); + + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3); + + while (bytetemp & 0x80) { + bytetemp = rtl_read_byte(rtlpriv, + rtlpriv->cfg-> + maps[EFUSE_CTRL] + 3); + k++; + if (k == 100) { + k = 0; + break; + } + } + } + +} + +void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 value32; + u8 readbyte; + u16 retry; + + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, + (_offset & 0xff)); + readbyte = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2); + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2, + ((_offset >> 8) & 0x03) | (readbyte & 0xfc)); + + readbyte = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3); + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, + (readbyte & 0x7f)); + + retry = 0; + value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); + while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) { + value32 = rtl_read_dword(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL]); + retry++; + } + + udelay(50); + value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); + + *pbuf = (u8) (value32 & 0xff); +} +EXPORT_SYMBOL_GPL(read_efuse_byte); + +void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 *efuse_tbl; + u8 rtemp8[1]; + u16 efuse_addr = 0; + u8 offset, wren; + u8 u1temp = 0; + u16 i; + u16 j; + const u16 efuse_max_section = + rtlpriv->cfg->maps[EFUSE_MAX_SECTION_MAP]; + const u32 efuse_len = + rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; + u16 **efuse_word; + u16 efuse_utilized = 0; + u8 efuse_usage; + + if ((_offset + _size_byte) > rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]) { + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + "read_efuse(): Invalid offset(%#x) with read bytes(%#x)!!\n", + _offset, _size_byte); + return; + } + + /* allocate memory for efuse_tbl and efuse_word */ + efuse_tbl = kzalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE] * + sizeof(u8), GFP_ATOMIC); + if (!efuse_tbl) + return; + efuse_word = kzalloc(EFUSE_MAX_WORD_UNIT * sizeof(u16 *), GFP_ATOMIC); + if (!efuse_word) + goto out; + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { + efuse_word[i] = kzalloc(efuse_max_section * sizeof(u16), + GFP_ATOMIC); + if (!efuse_word[i]) + goto done; + } + + for (i = 0; i < efuse_max_section; i++) + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) + efuse_word[j][i] = 0xFFFF; + + read_efuse_byte(hw, efuse_addr, rtemp8); + if (*rtemp8 != 0xFF) { + efuse_utilized++; + RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, + "Addr=%d\n", efuse_addr); + efuse_addr++; + } + + while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { + /* Check PG header for section num. */ + if ((*rtemp8 & 0x1F) == 0x0F) {/* extended header */ + u1temp = ((*rtemp8 & 0xE0) >> 5); + read_efuse_byte(hw, efuse_addr, rtemp8); + + if ((*rtemp8 & 0x0F) == 0x0F) { + efuse_addr++; + read_efuse_byte(hw, efuse_addr, rtemp8); + + if (*rtemp8 != 0xFF && + (efuse_addr < efuse_len)) { + efuse_addr++; + } + continue; + } else { + offset = ((*rtemp8 & 0xF0) >> 1) | u1temp; + wren = (*rtemp8 & 0x0F); + efuse_addr++; + } + } else { + offset = ((*rtemp8 >> 4) & 0x0f); + wren = (*rtemp8 & 0x0f); + } + + if (offset < efuse_max_section) { + RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, + "offset-%d Worden=%x\n", offset, wren); + + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { + if (!(wren & 0x01)) { + RTPRINT(rtlpriv, FEEPROM, + EFUSE_READ_ALL, + "Addr=%d\n", efuse_addr); + + read_efuse_byte(hw, efuse_addr, rtemp8); + efuse_addr++; + efuse_utilized++; + efuse_word[i][offset] = + (*rtemp8 & 0xff); + + if (efuse_addr >= efuse_len) + break; + + RTPRINT(rtlpriv, FEEPROM, + EFUSE_READ_ALL, + "Addr=%d\n", efuse_addr); + + read_efuse_byte(hw, efuse_addr, rtemp8); + efuse_addr++; + efuse_utilized++; + efuse_word[i][offset] |= + (((u16)*rtemp8 << 8) & 0xff00); + + if (efuse_addr >= efuse_len) + break; + } + + wren >>= 1; + } + } + + RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, + "Addr=%d\n", efuse_addr); + read_efuse_byte(hw, efuse_addr, rtemp8); + if (*rtemp8 != 0xFF && (efuse_addr < efuse_len)) { + efuse_utilized++; + efuse_addr++; + } + } + + for (i = 0; i < efuse_max_section; i++) { + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { + efuse_tbl[(i * 8) + (j * 2)] = + (efuse_word[j][i] & 0xff); + efuse_tbl[(i * 8) + ((j * 2) + 1)] = + ((efuse_word[j][i] >> 8) & 0xff); + } + } + + for (i = 0; i < _size_byte; i++) + pbuf[i] = efuse_tbl[_offset + i]; + + rtlefuse->efuse_usedbytes = efuse_utilized; + efuse_usage = (u8) ((efuse_utilized * 100) / efuse_len); + rtlefuse->efuse_usedpercentage = efuse_usage; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_BYTES, + (u8 *)&efuse_utilized); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_USAGE, + &efuse_usage); +done: + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) + kfree(efuse_word[i]); + kfree(efuse_word); +out: + kfree(efuse_tbl); +} + +bool efuse_shadow_update_chk(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 section_idx, i, Base; + u16 words_need = 0, hdr_num = 0, totalbytes, efuse_used; + bool wordchanged, result = true; + + for (section_idx = 0; section_idx < 16; section_idx++) { + Base = section_idx * 8; + wordchanged = false; + + for (i = 0; i < 8; i = i + 2) { + if ((rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i] != + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i]) || + (rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i + 1] != + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i + + 1])) { + words_need++; + wordchanged = true; + } + } + + if (wordchanged) + hdr_num++; + } + + totalbytes = hdr_num + words_need * 2; + efuse_used = rtlefuse->efuse_usedbytes; + + if ((totalbytes + efuse_used) >= + (EFUSE_MAX_SIZE - rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) + result = false; + + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + "efuse_shadow_update_chk(): totalbytes(%#x), hdr_num(%#x), words_need(%#x), efuse_used(%d)\n", + totalbytes, hdr_num, words_need, efuse_used); + + return result; +} + +void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, + u16 offset, u32 *value) +{ + if (type == 1) + efuse_shadow_read_1byte(hw, offset, (u8 *)value); + else if (type == 2) + efuse_shadow_read_2byte(hw, offset, (u16 *)value); + else if (type == 4) + efuse_shadow_read_4byte(hw, offset, value); + +} +EXPORT_SYMBOL(efuse_shadow_read); + +void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, u16 offset, + u32 value) +{ + if (type == 1) + efuse_shadow_write_1byte(hw, offset, (u8) value); + else if (type == 2) + efuse_shadow_write_2byte(hw, offset, (u16) value); + else if (type == 4) + efuse_shadow_write_4byte(hw, offset, value); + +} + +bool efuse_shadow_update(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u16 i, offset, base; + u8 word_en = 0x0F; + u8 first_pg = false; + + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "\n"); + + if (!efuse_shadow_update_chk(hw)) { + efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); + memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], + &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); + + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + "efuse out of capacity!!\n"); + return false; + } + efuse_power_switch(hw, true, true); + + for (offset = 0; offset < 16; offset++) { + + word_en = 0x0F; + base = offset * 8; + + for (i = 0; i < 8; i++) { + if (first_pg) { + word_en &= ~(BIT(i / 2)); + + rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] = + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]; + } else { + + if (rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] != + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]) { + word_en &= ~(BIT(i / 2)); + + rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] = + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]; + } + } + } + + if (word_en != 0x0F) { + u8 tmpdata[8]; + memcpy(tmpdata, + &rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base], + 8); + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, + "U-efuse\n", tmpdata, 8); + + if (!efuse_pg_packet_write(hw, (u8) offset, word_en, + tmpdata)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "PG section(%#x) fail!!\n", offset); + break; + } + } + + } + + efuse_power_switch(hw, true, false); + efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); + + memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], + &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); + + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "\n"); + return true; +} + +void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + if (rtlefuse->autoload_failflag) + memset((&rtlefuse->efuse_map[EFUSE_INIT_MAP][0]), + 0xFF, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); + else + efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); + + memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], + &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); + +} +EXPORT_SYMBOL(rtl_efuse_shadow_map_update); + +void efuse_force_write_vendor_Id(struct ieee80211_hw *hw) +{ + u8 tmpdata[8] = { 0xFF, 0xFF, 0xEC, 0x10, 0xFF, 0xFF, 0xFF, 0xFF }; + + efuse_power_switch(hw, true, true); + + efuse_pg_packet_write(hw, 1, 0xD, tmpdata); + + efuse_power_switch(hw, true, false); + +} + +void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx) +{ +} + +static void efuse_shadow_read_1byte(struct ieee80211_hw *hw, + u16 offset, u8 *value) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset]; +} + +static void efuse_shadow_read_2byte(struct ieee80211_hw *hw, + u16 offset, u16 *value) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset]; + *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] << 8; + +} + +static void efuse_shadow_read_4byte(struct ieee80211_hw *hw, + u16 offset, u32 *value) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset]; + *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] << 8; + *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 2] << 16; + *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 3] << 24; +} + +static void efuse_shadow_write_1byte(struct ieee80211_hw *hw, + u16 offset, u8 value) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = value; +} + +static void efuse_shadow_write_2byte(struct ieee80211_hw *hw, + u16 offset, u16 value) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = value & 0x00FF; + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] = value >> 8; + +} + +static void efuse_shadow_write_4byte(struct ieee80211_hw *hw, + u16 offset, u32 value) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = + (u8) (value & 0x000000FF); + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] = + (u8) ((value >> 8) & 0x0000FF); + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 2] = + (u8) ((value >> 16) & 0x00FF); + rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 3] = + (u8) ((value >> 24) & 0xFF); + +} + +int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmpidx = 0; + int result; + + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, + (u8) (addr & 0xff)); + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2, + ((u8) ((addr >> 8) & 0x03)) | + (rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 2) & + 0xFC)); + + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0x72); + + while (!(0x80 & rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3)) + && (tmpidx < 100)) { + tmpidx++; + } + + if (tmpidx < 100) { + *data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); + result = true; + } else { + *data = 0xff; + result = false; + } + return result; +} +EXPORT_SYMBOL(efuse_one_byte_read); + +static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmpidx = 0; + + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + "Addr = %x Data=%x\n", addr, data); + + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 1, (u8) (addr & 0xff)); + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2, + (rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + + 2) & 0xFC) | (u8) ((addr >> 8) & 0x03)); + + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], data); + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0xF2); + + while ((0x80 & rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_CTRL] + 3)) + && (tmpidx < 100)) { + tmpidx++; + } + + if (tmpidx < 100) + return true; + return false; +} + +static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + efuse_power_switch(hw, false, true); + read_efuse(hw, 0, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], efuse); + efuse_power_switch(hw, false, false); +} + +static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, + u8 efuse_data, u8 offset, u8 *tmpdata, + u8 *readstate) +{ + bool dataempty = true; + u8 hoffset; + u8 tmpidx; + u8 hworden; + u8 word_cnts; + + hoffset = (efuse_data >> 4) & 0x0F; + hworden = efuse_data & 0x0F; + word_cnts = efuse_calculate_word_cnts(hworden); + + if (hoffset == offset) { + for (tmpidx = 0; tmpidx < word_cnts * 2; tmpidx++) { + if (efuse_one_byte_read(hw, *efuse_addr + 1 + tmpidx, + &efuse_data)) { + tmpdata[tmpidx] = efuse_data; + if (efuse_data != 0xff) + dataempty = false; + } + } + + if (!dataempty) { + *readstate = PG_STATE_DATA; + } else { + *efuse_addr = *efuse_addr + (word_cnts * 2) + 1; + *readstate = PG_STATE_HEADER; + } + + } else { + *efuse_addr = *efuse_addr + (word_cnts * 2) + 1; + *readstate = PG_STATE_HEADER; + } +} + +static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) +{ + u8 readstate = PG_STATE_HEADER; + + bool continual = true; + + u8 efuse_data, word_cnts = 0; + u16 efuse_addr = 0; + u8 tmpdata[8]; + + if (data == NULL) + return false; + if (offset > 15) + return false; + + memset(data, 0xff, PGPKT_DATA_SIZE * sizeof(u8)); + memset(tmpdata, 0xff, PGPKT_DATA_SIZE * sizeof(u8)); + + while (continual && (efuse_addr < EFUSE_MAX_SIZE)) { + if (readstate & PG_STATE_HEADER) { + if (efuse_one_byte_read(hw, efuse_addr, &efuse_data) + && (efuse_data != 0xFF)) + efuse_read_data_case1(hw, &efuse_addr, + efuse_data, offset, + tmpdata, &readstate); + else + continual = false; + } else if (readstate & PG_STATE_DATA) { + efuse_word_enable_data_read(0, tmpdata, data); + efuse_addr = efuse_addr + (word_cnts * 2) + 1; + readstate = PG_STATE_HEADER; + } + + } + + if ((data[0] == 0xff) && (data[1] == 0xff) && + (data[2] == 0xff) && (data[3] == 0xff) && + (data[4] == 0xff) && (data[5] == 0xff) && + (data[6] == 0xff) && (data[7] == 0xff)) + return false; + else + return true; + +} + +static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, + u8 efuse_data, u8 offset, + int *continual, u8 *write_state, + struct pgpkt_struct *target_pkt, + int *repeat_times, int *result, u8 word_en) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct pgpkt_struct tmp_pkt; + int dataempty = true; + u8 originaldata[8 * sizeof(u8)]; + u8 badworden = 0x0F; + u8 match_word_en, tmp_word_en; + u8 tmpindex; + u8 tmp_header = efuse_data; + u8 tmp_word_cnts; + + tmp_pkt.offset = (tmp_header >> 4) & 0x0F; + tmp_pkt.word_en = tmp_header & 0x0F; + tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en); + + if (tmp_pkt.offset != target_pkt->offset) { + *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; + *write_state = PG_STATE_HEADER; + } else { + for (tmpindex = 0; tmpindex < (tmp_word_cnts * 2); tmpindex++) { + if (efuse_one_byte_read(hw, + (*efuse_addr + 1 + tmpindex), + &efuse_data) && + (efuse_data != 0xFF)) + dataempty = false; + } + + if (!dataempty) { + *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; + *write_state = PG_STATE_HEADER; + } else { + match_word_en = 0x0F; + if (!((target_pkt->word_en & BIT(0)) | + (tmp_pkt.word_en & BIT(0)))) + match_word_en &= (~BIT(0)); + + if (!((target_pkt->word_en & BIT(1)) | + (tmp_pkt.word_en & BIT(1)))) + match_word_en &= (~BIT(1)); + + if (!((target_pkt->word_en & BIT(2)) | + (tmp_pkt.word_en & BIT(2)))) + match_word_en &= (~BIT(2)); + + if (!((target_pkt->word_en & BIT(3)) | + (tmp_pkt.word_en & BIT(3)))) + match_word_en &= (~BIT(3)); + + if ((match_word_en & 0x0F) != 0x0F) { + badworden = + enable_efuse_data_write(hw, + *efuse_addr + 1, + tmp_pkt.word_en, + target_pkt->data); + + if (0x0F != (badworden & 0x0F)) { + u8 reorg_offset = offset; + u8 reorg_worden = badworden; + efuse_pg_packet_write(hw, reorg_offset, + reorg_worden, + originaldata); + } + + tmp_word_en = 0x0F; + if ((target_pkt->word_en & BIT(0)) ^ + (match_word_en & BIT(0))) + tmp_word_en &= (~BIT(0)); + + if ((target_pkt->word_en & BIT(1)) ^ + (match_word_en & BIT(1))) + tmp_word_en &= (~BIT(1)); + + if ((target_pkt->word_en & BIT(2)) ^ + (match_word_en & BIT(2))) + tmp_word_en &= (~BIT(2)); + + if ((target_pkt->word_en & BIT(3)) ^ + (match_word_en & BIT(3))) + tmp_word_en &= (~BIT(3)); + + if ((tmp_word_en & 0x0F) != 0x0F) { + *efuse_addr = efuse_get_current_size(hw); + target_pkt->offset = offset; + target_pkt->word_en = tmp_word_en; + } else { + *continual = false; + } + *write_state = PG_STATE_HEADER; + *repeat_times += 1; + if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { + *continual = false; + *result = false; + } + } else { + *efuse_addr += (2 * tmp_word_cnts) + 1; + target_pkt->offset = offset; + target_pkt->word_en = word_en; + *write_state = PG_STATE_HEADER; + } + } + } + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse PG_STATE_HEADER-1\n"); +} + +static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, + int *continual, u8 *write_state, + struct pgpkt_struct target_pkt, + int *repeat_times, int *result) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct pgpkt_struct tmp_pkt; + u8 pg_header; + u8 tmp_header; + u8 originaldata[8 * sizeof(u8)]; + u8 tmp_word_cnts; + u8 badworden = 0x0F; + + pg_header = ((target_pkt.offset << 4) & 0xf0) | target_pkt.word_en; + efuse_one_byte_write(hw, *efuse_addr, pg_header); + efuse_one_byte_read(hw, *efuse_addr, &tmp_header); + + if (tmp_header == pg_header) { + *write_state = PG_STATE_DATA; + } else if (tmp_header == 0xFF) { + *write_state = PG_STATE_HEADER; + *repeat_times += 1; + if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { + *continual = false; + *result = false; + } + } else { + tmp_pkt.offset = (tmp_header >> 4) & 0x0F; + tmp_pkt.word_en = tmp_header & 0x0F; + + tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en); + + memset(originaldata, 0xff, 8 * sizeof(u8)); + + if (efuse_pg_packet_read(hw, tmp_pkt.offset, originaldata)) { + badworden = enable_efuse_data_write(hw, + *efuse_addr + 1, + tmp_pkt.word_en, + originaldata); + + if (0x0F != (badworden & 0x0F)) { + u8 reorg_offset = tmp_pkt.offset; + u8 reorg_worden = badworden; + efuse_pg_packet_write(hw, reorg_offset, + reorg_worden, + originaldata); + *efuse_addr = efuse_get_current_size(hw); + } else { + *efuse_addr = *efuse_addr + + (tmp_word_cnts * 2) + 1; + } + } else { + *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; + } + + *write_state = PG_STATE_HEADER; + *repeat_times += 1; + if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { + *continual = false; + *result = false; + } + + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, + "efuse PG_STATE_HEADER-2\n"); + } +} + +static int efuse_pg_packet_write(struct ieee80211_hw *hw, + u8 offset, u8 word_en, u8 *data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct pgpkt_struct target_pkt; + u8 write_state = PG_STATE_HEADER; + int continual = true, dataempty = true, result = true; + u16 efuse_addr = 0; + u8 efuse_data; + u8 target_word_cnts = 0; + u8 badworden = 0x0F; + static int repeat_times; + + if (efuse_get_current_size(hw) >= (EFUSE_MAX_SIZE - + rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) { + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, + "efuse_pg_packet_write error\n"); + return false; + } + + target_pkt.offset = offset; + target_pkt.word_en = word_en; + + memset(target_pkt.data, 0xFF, 8 * sizeof(u8)); + + efuse_word_enable_data_read(word_en, data, target_pkt.data); + target_word_cnts = efuse_calculate_word_cnts(target_pkt.word_en); + + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse Power ON\n"); + + while (continual && (efuse_addr < (EFUSE_MAX_SIZE - + rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) { + + if (write_state == PG_STATE_HEADER) { + dataempty = true; + badworden = 0x0F; + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, + "efuse PG_STATE_HEADER\n"); + + if (efuse_one_byte_read(hw, efuse_addr, &efuse_data) && + (efuse_data != 0xFF)) + efuse_write_data_case1(hw, &efuse_addr, + efuse_data, offset, + &continual, + &write_state, + &target_pkt, + &repeat_times, &result, + word_en); + else + efuse_write_data_case2(hw, &efuse_addr, + &continual, + &write_state, + target_pkt, + &repeat_times, + &result); + + } else if (write_state == PG_STATE_DATA) { + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, + "efuse PG_STATE_DATA\n"); + badworden = 0x0f; + badworden = + enable_efuse_data_write(hw, efuse_addr + 1, + target_pkt.word_en, + target_pkt.data); + + if ((badworden & 0x0F) == 0x0F) { + continual = false; + } else { + efuse_addr = + efuse_addr + (2 * target_word_cnts) + 1; + + target_pkt.offset = offset; + target_pkt.word_en = badworden; + target_word_cnts = + efuse_calculate_word_cnts(target_pkt. + word_en); + write_state = PG_STATE_HEADER; + repeat_times++; + if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { + continual = false; + result = false; + } + RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, + "efuse PG_STATE_HEADER-3\n"); + } + } + } + + if (efuse_addr >= (EFUSE_MAX_SIZE - + rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) { + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + "efuse_addr(%#x) Out of size!!\n", efuse_addr); + } + + return true; +} + +static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata, + u8 *targetdata) +{ + if (!(word_en & BIT(0))) { + targetdata[0] = sourdata[0]; + targetdata[1] = sourdata[1]; + } + + if (!(word_en & BIT(1))) { + targetdata[2] = sourdata[2]; + targetdata[3] = sourdata[3]; + } + + if (!(word_en & BIT(2))) { + targetdata[4] = sourdata[4]; + targetdata[5] = sourdata[5]; + } + + if (!(word_en & BIT(3))) { + targetdata[6] = sourdata[6]; + targetdata[7] = sourdata[7]; + } +} + +static u8 enable_efuse_data_write(struct ieee80211_hw *hw, + u16 efuse_addr, u8 word_en, u8 *data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 tmpaddr; + u16 start_addr = efuse_addr; + u8 badworden = 0x0F; + u8 tmpdata[8]; + + memset(tmpdata, 0xff, PGPKT_DATA_SIZE); + RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, + "word_en = %x efuse_addr=%x\n", word_en, efuse_addr); + + if (!(word_en & BIT(0))) { + tmpaddr = start_addr; + efuse_one_byte_write(hw, start_addr++, data[0]); + efuse_one_byte_write(hw, start_addr++, data[1]); + + efuse_one_byte_read(hw, tmpaddr, &tmpdata[0]); + efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[1]); + if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) + badworden &= (~BIT(0)); + } + + if (!(word_en & BIT(1))) { + tmpaddr = start_addr; + efuse_one_byte_write(hw, start_addr++, data[2]); + efuse_one_byte_write(hw, start_addr++, data[3]); + + efuse_one_byte_read(hw, tmpaddr, &tmpdata[2]); + efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[3]); + if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) + badworden &= (~BIT(1)); + } + + if (!(word_en & BIT(2))) { + tmpaddr = start_addr; + efuse_one_byte_write(hw, start_addr++, data[4]); + efuse_one_byte_write(hw, start_addr++, data[5]); + + efuse_one_byte_read(hw, tmpaddr, &tmpdata[4]); + efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[5]); + if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) + badworden &= (~BIT(2)); + } + + if (!(word_en & BIT(3))) { + tmpaddr = start_addr; + efuse_one_byte_write(hw, start_addr++, data[6]); + efuse_one_byte_write(hw, start_addr++, data[7]); + + efuse_one_byte_read(hw, tmpaddr, &tmpdata[6]); + efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[7]); + if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) + badworden &= (~BIT(3)); + } + + return badworden; +} + +static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tempval; + u16 tmpV16; + + if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) { + + if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192CE && + rtlhal->hw_type != HARDWARE_TYPE_RTL8192DE) { + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_ACCESS], 0x69); + } else { + tmpV16 = + rtl_read_word(rtlpriv, + rtlpriv->cfg->maps[SYS_ISO_CTRL]); + if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { + tmpV16 |= rtlpriv->cfg->maps[EFUSE_PWC_EV12V]; + rtl_write_word(rtlpriv, + rtlpriv->cfg->maps[SYS_ISO_CTRL], + tmpV16); + } + } + tmpV16 = rtl_read_word(rtlpriv, + rtlpriv->cfg->maps[SYS_FUNC_EN]); + if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_FEN_ELDR])) { + tmpV16 |= rtlpriv->cfg->maps[EFUSE_FEN_ELDR]; + rtl_write_word(rtlpriv, + rtlpriv->cfg->maps[SYS_FUNC_EN], tmpV16); + } + + tmpV16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_CLK]); + if ((!(tmpV16 & rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN])) || + (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_ANA8M]))) { + tmpV16 |= (rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN] | + rtlpriv->cfg->maps[EFUSE_ANA8M]); + rtl_write_word(rtlpriv, + rtlpriv->cfg->maps[SYS_CLK], tmpV16); + } + } + + if (pwrstate) { + if (write) { + tempval = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_TEST] + + 3); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + tempval &= ~(BIT(3) | BIT(4) | BIT(5) | BIT(6)); + tempval |= (VOLTAGE_V25 << 3); + } else if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) { + tempval &= 0x0F; + tempval |= (VOLTAGE_V25 << 4); + } + + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_TEST] + 3, + (tempval | 0x80)); + } + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK], + 0x03); + } + } else { + if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192CE && + rtlhal->hw_type != HARDWARE_TYPE_RTL8192DE) + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_ACCESS], 0); + + if (write) { + tempval = rtl_read_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_TEST] + + 3); + rtl_write_byte(rtlpriv, + rtlpriv->cfg->maps[EFUSE_TEST] + 3, + (tempval & 0x7F)); + } + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK], + 0x02); + } + } +} + +static u16 efuse_get_current_size(struct ieee80211_hw *hw) +{ + int continual = true; + u16 efuse_addr = 0; + u8 hoffset, hworden; + u8 efuse_data, word_cnts; + + while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) && + (efuse_addr < EFUSE_MAX_SIZE)) { + if (efuse_data != 0xFF) { + hoffset = (efuse_data >> 4) & 0x0F; + hworden = efuse_data & 0x0F; + word_cnts = efuse_calculate_word_cnts(hworden); + efuse_addr = efuse_addr + (word_cnts * 2) + 1; + } else { + continual = false; + } + } + + return efuse_addr; +} + +static u8 efuse_calculate_word_cnts(u8 word_en) +{ + u8 word_cnts = 0; + if (!(word_en & BIT(0))) + word_cnts++; + if (!(word_en & BIT(1))) + word_cnts++; + if (!(word_en & BIT(2))) + word_cnts++; + if (!(word_en & BIT(3))) + word_cnts++; + return word_cnts; +} + diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.h b/drivers/net/wireless/realtek/rtlwifi/efuse.h new file mode 100644 index 000000000000..be02e7894c61 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/efuse.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL_EFUSE_H_ +#define __RTL_EFUSE_H_ + +#define EFUSE_IC_ID_OFFSET 506 + +#define EFUSE_MAX_WORD_UNIT 4 + +#define EFUSE_INIT_MAP 0 +#define EFUSE_MODIFY_MAP 1 + +#define PG_STATE_HEADER 0x01 +#define PG_STATE_WORD_0 0x02 +#define PG_STATE_WORD_1 0x04 +#define PG_STATE_WORD_2 0x08 +#define PG_STATE_WORD_3 0x10 +#define PG_STATE_DATA 0x20 + +#define EFUSE_REPEAT_THRESHOLD_ 3 +#define EFUSE_ERROE_HANDLE 1 + +struct efuse_map { + u8 offset; + u8 word_start; + u8 byte_start; + u8 byte_cnts; +}; + +struct pgpkt_struct { + u8 offset; + u8 word_en; + u8 data[8]; +}; + +enum efuse_data_item { + EFUSE_CHIP_ID = 0, + EFUSE_LDO_SETTING, + EFUSE_CLK_SETTING, + EFUSE_SDIO_SETTING, + EFUSE_CCCR, + EFUSE_SDIO_MODE, + EFUSE_OCR, + EFUSE_F0CIS, + EFUSE_F1CIS, + EFUSE_MAC_ADDR, + EFUSE_EEPROM_VER, + EFUSE_CHAN_PLAN, + EFUSE_TXPW_TAB +}; + +enum { + VOLTAGE_V25 = 0x03, + LDOE25_SHIFT = 28, +}; + +struct efuse_priv { + u8 id[2]; + u8 ldo_setting[2]; + u8 clk_setting[2]; + u8 cccr; + u8 sdio_mode; + u8 ocr[3]; + u8 cis0[17]; + u8 cis1[48]; + u8 mac_addr[6]; + u8 eeprom_verno; + u8 channel_plan; + u8 tx_power_b[14]; + u8 tx_power_g[14]; +}; + +void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); +void efuse_initialize(struct ieee80211_hw *hw); +u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address); +int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data); +void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value); +void read_efuse(struct ieee80211_hw *hw, u16 _offset, + u16 _size_byte, u8 *pbuf); +void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, + u16 offset, u32 *value); +void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, + u16 offset, u32 value); +bool efuse_shadow_update(struct ieee80211_hw *hw); +bool efuse_shadow_update_chk(struct ieee80211_hw *hw); +void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw); +void efuse_force_write_vendor_Id(struct ieee80211_hw *hw); +void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c new file mode 100644 index 000000000000..f46c9d7f6528 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -0,0 +1,2478 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "wifi.h" +#include "core.h" +#include "pci.h" +#include "base.h" +#include "ps.h" +#include "efuse.h" +#include +#include +#include +#include + +MODULE_AUTHOR("lizhaoming "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("PCI basic driver for rtlwifi"); + +static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { + INTEL_VENDOR_ID, + ATI_VENDOR_ID, + AMD_VENDOR_ID, + SIS_VENDOR_ID +}; + +static const u8 ac_to_hwq[] = { + VO_QUEUE, + VI_QUEUE, + BE_QUEUE, + BK_QUEUE +}; + +static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + __le16 fc = rtl_get_fc(skb); + u8 queue_index = skb_get_queue_mapping(skb); + + if (unlikely(ieee80211_is_beacon(fc))) + return BEACON_QUEUE; + if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) + return MGNT_QUEUE; + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) + if (ieee80211_is_nullfunc(fc)) + return HIGH_QUEUE; + + return ac_to_hwq[queue_index]; +} + +/* Update PCI dependent default settings*/ +static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; + u8 init_aspm; + + ppsc->reg_rfps_level = 0; + ppsc->support_aspm = false; + + /*Update PCI ASPM setting */ + ppsc->const_amdpci_aspm = rtlpci->const_amdpci_aspm; + switch (rtlpci->const_pci_aspm) { + case 0: + /*No ASPM */ + break; + + case 1: + /*ASPM dynamically enabled/disable. */ + ppsc->reg_rfps_level |= RT_RF_LPS_LEVEL_ASPM; + break; + + case 2: + /*ASPM with Clock Req dynamically enabled/disable. */ + ppsc->reg_rfps_level |= (RT_RF_LPS_LEVEL_ASPM | + RT_RF_OFF_LEVL_CLK_REQ); + break; + + case 3: + /* + * Always enable ASPM and Clock Req + * from initialization to halt. + * */ + ppsc->reg_rfps_level &= ~(RT_RF_LPS_LEVEL_ASPM); + ppsc->reg_rfps_level |= (RT_RF_PS_LEVEL_ALWAYS_ASPM | + RT_RF_OFF_LEVL_CLK_REQ); + break; + + case 4: + /* + * Always enable ASPM without Clock Req + * from initialization to halt. + * */ + ppsc->reg_rfps_level &= ~(RT_RF_LPS_LEVEL_ASPM | + RT_RF_OFF_LEVL_CLK_REQ); + ppsc->reg_rfps_level |= RT_RF_PS_LEVEL_ALWAYS_ASPM; + break; + } + + ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_HALT_NIC; + + /*Update Radio OFF setting */ + switch (rtlpci->const_hwsw_rfoff_d3) { + case 1: + if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM) + ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_ASPM; + break; + + case 2: + if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM) + ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_ASPM; + ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_HALT_NIC; + break; + + case 3: + ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_PCI_D3; + break; + } + + /*Set HW definition to determine if it supports ASPM. */ + switch (rtlpci->const_support_pciaspm) { + case 0:{ + /*Not support ASPM. */ + bool support_aspm = false; + ppsc->support_aspm = support_aspm; + break; + } + case 1:{ + /*Support ASPM. */ + bool support_aspm = true; + bool support_backdoor = true; + ppsc->support_aspm = support_aspm; + + /*if (priv->oem_id == RT_CID_TOSHIBA && + !priv->ndis_adapter.amd_l1_patch) + support_backdoor = false; */ + + ppsc->support_backdoor = support_backdoor; + + break; + } + case 2: + /*ASPM value set by chipset. */ + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) { + bool support_aspm = true; + ppsc->support_aspm = support_aspm; + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + + /* toshiba aspm issue, toshiba will set aspm selfly + * so we should not set aspm in driver */ + pci_read_config_byte(rtlpci->pdev, 0x80, &init_aspm); + if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8192SE && + init_aspm == 0x43) + ppsc->support_aspm = false; +} + +static bool _rtl_pci_platform_switch_device_pci_aspm( + struct ieee80211_hw *hw, + u8 value) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) + value |= 0x40; + + pci_write_config_byte(rtlpci->pdev, 0x80, value); + + return false; +} + +/*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/ +static void _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + pci_write_config_byte(rtlpci->pdev, 0x81, value); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) + udelay(100); +} + +/*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/ +static void rtl_pci_disable_aspm(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; + u8 num4bytes = pcipriv->ndis_adapter.num4bytes; + /*Retrieve original configuration settings. */ + u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg; + u16 pcibridge_linkctrlreg = pcipriv->ndis_adapter. + pcibridge_linkctrlreg; + u16 aspmlevel = 0; + u8 tmp_u1b = 0; + + if (!ppsc->support_aspm) + return; + + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "PCI(Bridge) UNKNOWN\n"); + + return; + } + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) { + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ); + _rtl_pci_switch_clk_req(hw, 0x0); + } + + /*for promising device will in L0 state after an I/O. */ + pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b); + + /*Set corresponding value. */ + aspmlevel |= BIT(0) | BIT(1); + linkctrl_reg &= ~aspmlevel; + pcibridge_linkctrlreg &= ~(BIT(0) | BIT(1)); + + _rtl_pci_platform_switch_device_pci_aspm(hw, linkctrl_reg); + udelay(50); + + /*4 Disable Pci Bridge ASPM */ + pci_write_config_byte(rtlpci->pdev, (num4bytes << 2), + pcibridge_linkctrlreg); + + udelay(50); +} + +/* + *Enable RTL8192SE ASPM & Enable Pci Bridge ASPM for + *power saving We should follow the sequence to enable + *RTL8192SE first then enable Pci Bridge ASPM + *or the system will show bluescreen. + */ +static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; + u8 num4bytes = pcipriv->ndis_adapter.num4bytes; + u16 aspmlevel; + u8 u_pcibridge_aspmsetting; + u8 u_device_aspmsetting; + + if (!ppsc->support_aspm) + return; + + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "PCI(Bridge) UNKNOWN\n"); + return; + } + + /*4 Enable Pci Bridge ASPM */ + + u_pcibridge_aspmsetting = + pcipriv->ndis_adapter.pcibridge_linkctrlreg | + rtlpci->const_hostpci_aspm_setting; + + if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) + u_pcibridge_aspmsetting &= ~BIT(0); + + pci_write_config_byte(rtlpci->pdev, (num4bytes << 2), + u_pcibridge_aspmsetting); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "PlatformEnableASPM(): Write reg[%x] = %x\n", + (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10), + u_pcibridge_aspmsetting); + + udelay(50); + + /*Get ASPM level (with/without Clock Req) */ + aspmlevel = rtlpci->const_devicepci_aspm_setting; + u_device_aspmsetting = pcipriv->ndis_adapter.linkctrl_reg; + + /*_rtl_pci_platform_switch_device_pci_aspm(dev,*/ + /*(priv->ndis_adapter.linkctrl_reg | ASPMLevel)); */ + + u_device_aspmsetting |= aspmlevel; + + _rtl_pci_platform_switch_device_pci_aspm(hw, u_device_aspmsetting); + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) { + _rtl_pci_switch_clk_req(hw, (ppsc->reg_rfps_level & + RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ); + } + udelay(100); +} + +static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + bool status = false; + u8 offset_e0; + unsigned offset_e4; + + pci_write_config_byte(rtlpci->pdev, 0xe0, 0xa0); + + pci_read_config_byte(rtlpci->pdev, 0xe0, &offset_e0); + + if (offset_e0 == 0xA0) { + pci_read_config_dword(rtlpci->pdev, 0xe4, &offset_e4); + if (offset_e4 & BIT(23)) + status = true; + } + + return status; +} + +static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw, + struct rtl_priv **buddy_priv) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + bool find_buddy_priv = false; + struct rtl_priv *tpriv = NULL; + struct rtl_pci_priv *tpcipriv = NULL; + + if (!list_empty(&rtlpriv->glb_var->glb_priv_list)) { + list_for_each_entry(tpriv, &rtlpriv->glb_var->glb_priv_list, + list) { + if (tpriv) { + tpcipriv = (struct rtl_pci_priv *)tpriv->priv; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "pcipriv->ndis_adapter.funcnumber %x\n", + pcipriv->ndis_adapter.funcnumber); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "tpcipriv->ndis_adapter.funcnumber %x\n", + tpcipriv->ndis_adapter.funcnumber); + + if ((pcipriv->ndis_adapter.busnumber == + tpcipriv->ndis_adapter.busnumber) && + (pcipriv->ndis_adapter.devnumber == + tpcipriv->ndis_adapter.devnumber) && + (pcipriv->ndis_adapter.funcnumber != + tpcipriv->ndis_adapter.funcnumber)) { + find_buddy_priv = true; + break; + } + } + } + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "find_buddy_priv %d\n", find_buddy_priv); + + if (find_buddy_priv) + *buddy_priv = tpriv; + + return find_buddy_priv; +} + +static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); + u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset; + u8 linkctrl_reg; + u8 num4bbytes; + + num4bbytes = (capabilityoffset + 0x10) / 4; + + /*Read Link Control Register */ + pci_read_config_byte(rtlpci->pdev, (num4bbytes << 2), &linkctrl_reg); + + pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg; +} + +static void rtl_pci_parse_configuration(struct pci_dev *pdev, + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + + u8 tmp; + u16 linkctrl_reg; + + /*Link Control Register */ + pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &linkctrl_reg); + pcipriv->ndis_adapter.linkctrl_reg = (u8)linkctrl_reg; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Link Control Register =%x\n", + pcipriv->ndis_adapter.linkctrl_reg); + + pci_read_config_byte(pdev, 0x98, &tmp); + tmp |= BIT(4); + pci_write_config_byte(pdev, 0x98, tmp); + + tmp = 0x17; + pci_write_config_byte(pdev, 0x70f, tmp); +} + +static void rtl_pci_init_aspm(struct ieee80211_hw *hw) +{ + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + _rtl_pci_update_default_setting(hw); + + if (ppsc->reg_rfps_level & RT_RF_PS_LEVEL_ALWAYS_ASPM) { + /*Always enable ASPM & Clock Req. */ + rtl_pci_enable_aspm(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_PS_LEVEL_ALWAYS_ASPM); + } + +} + +static void _rtl_pci_io_handler_init(struct device *dev, + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->io.dev = dev; + + rtlpriv->io.write8_async = pci_write8_async; + rtlpriv->io.write16_async = pci_write16_async; + rtlpriv->io.write32_async = pci_write32_async; + + rtlpriv->io.read8_sync = pci_read8_sync; + rtlpriv->io.read16_sync = pci_read16_sync; + rtlpriv->io.read32_sync = pci_read32_sync; + +} + +static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, + struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct sk_buff *next_skb; + u8 additionlen = FCS_LEN; + + /* here open is 4, wep/tkip is 8, aes is 12*/ + if (info->control.hw_key) + additionlen += info->control.hw_key->icv_len; + + /* The most skb num is 6 */ + tcb_desc->empkt_num = 0; + spin_lock_bh(&rtlpriv->locks.waitq_lock); + skb_queue_walk(&rtlpriv->mac80211.skb_waitq[tid], next_skb) { + struct ieee80211_tx_info *next_info; + + next_info = IEEE80211_SKB_CB(next_skb); + if (next_info->flags & IEEE80211_TX_CTL_AMPDU) { + tcb_desc->empkt_len[tcb_desc->empkt_num] = + next_skb->len + additionlen; + tcb_desc->empkt_num++; + } else { + break; + } + + if (skb_queue_is_last(&rtlpriv->mac80211.skb_waitq[tid], + next_skb)) + break; + + if (tcb_desc->empkt_num >= rtlhal->max_earlymode_num) + break; + } + spin_unlock_bh(&rtlpriv->locks.waitq_lock); + + return true; +} + +/* just for early mode now */ +static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct sk_buff *skb = NULL; + struct ieee80211_tx_info *info = NULL; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + int tid; + + if (!rtlpriv->rtlhal.earlymode_enable) + return; + + if (rtlpriv->dm.supp_phymode_switch && + (rtlpriv->easy_concurrent_ctl.switch_in_process || + (rtlpriv->buddy_priv && + rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process))) + return; + /* we juse use em for BE/BK/VI/VO */ + for (tid = 7; tid >= 0; tid--) { + u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)]; + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; + while (!mac->act_scanning && + rtlpriv->psc.rfpwr_state == ERFON) { + struct rtl_tcb_desc tcb_desc; + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + + spin_lock_bh(&rtlpriv->locks.waitq_lock); + if (!skb_queue_empty(&mac->skb_waitq[tid]) && + (ring->entries - skb_queue_len(&ring->queue) > + rtlhal->max_earlymode_num)) { + skb = skb_dequeue(&mac->skb_waitq[tid]); + } else { + spin_unlock_bh(&rtlpriv->locks.waitq_lock); + break; + } + spin_unlock_bh(&rtlpriv->locks.waitq_lock); + + /* Some macaddr can't do early mode. like + * multicast/broadcast/no_qos data */ + info = IEEE80211_SKB_CB(skb); + if (info->flags & IEEE80211_TX_CTL_AMPDU) + _rtl_update_earlymode_info(hw, skb, + &tcb_desc, tid); + + rtlpriv->intf_ops->adapter_tx(hw, NULL, skb, &tcb_desc); + } + } +} + + +static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[prio]; + + while (skb_queue_len(&ring->queue)) { + struct sk_buff *skb; + struct ieee80211_tx_info *info; + __le16 fc; + u8 tid; + u8 *entry; + + if (rtlpriv->use_new_trx_flow) + entry = (u8 *)(&ring->buffer_desc[ring->idx]); + else + entry = (u8 *)(&ring->desc[ring->idx]); + + if (rtlpriv->cfg->ops->get_available_desc && + rtlpriv->cfg->ops->get_available_desc(hw, prio) <= 1) { + RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_DMESG, + "no available desc!\n"); + return; + } + + if (!rtlpriv->cfg->ops->is_tx_desc_closed(hw, prio, ring->idx)) + return; + ring->idx = (ring->idx + 1) % ring->entries; + + skb = __skb_dequeue(&ring->queue); + pci_unmap_single(rtlpci->pdev, + rtlpriv->cfg->ops-> + get_desc((u8 *)entry, true, + HW_DESC_TXBUFF_ADDR), + skb->len, PCI_DMA_TODEVICE); + + /* remove early mode header */ + if (rtlpriv->rtlhal.earlymode_enable) + skb_pull(skb, EM_HDR_LEN); + + RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_TRACE, + "new ring->idx:%d, free: skb_queue_len:%d, free: seq:%x\n", + ring->idx, + skb_queue_len(&ring->queue), + *(u16 *)(skb->data + 22)); + + if (prio == TXCMD_QUEUE) { + dev_kfree_skb(skb); + goto tx_status_ok; + + } + + /* for sw LPS, just after NULL skb send out, we can + * sure AP knows we are sleeping, we should not let + * rf sleep + */ + fc = rtl_get_fc(skb); + if (ieee80211_is_nullfunc(fc)) { + if (ieee80211_has_pm(fc)) { + rtlpriv->mac80211.offchan_delay = true; + rtlpriv->psc.state_inap = true; + } else { + rtlpriv->psc.state_inap = false; + } + } + if (ieee80211_is_action(fc)) { + struct ieee80211_mgmt *action_frame = + (struct ieee80211_mgmt *)skb->data; + if (action_frame->u.action.u.ht_smps.action == + WLAN_HT_ACTION_SMPS) { + dev_kfree_skb(skb); + goto tx_status_ok; + } + } + + /* update tid tx pkt num */ + tid = rtl_get_tid(skb); + if (tid <= 7) + rtlpriv->link_info.tidtx_inperiod[tid]++; + + info = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(info); + + info->flags |= IEEE80211_TX_STAT_ACK; + /*info->status.rates[0].count = 1; */ + + ieee80211_tx_status_irqsafe(hw, skb); + + if ((ring->entries - skb_queue_len(&ring->queue)) <= 4) { + + RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, + "more desc left, wake skb_queue@%d, ring->idx = %d, skb_queue_len = 0x%x\n", + prio, ring->idx, + skb_queue_len(&ring->queue)); + + ieee80211_wake_queue(hw, + skb_get_queue_mapping + (skb)); + } +tx_status_ok: + skb = NULL; + } + + if (((rtlpriv->link_info.num_rx_inperiod + + rtlpriv->link_info.num_tx_inperiod) > 8) || + (rtlpriv->link_info.num_rx_inperiod > 2)) { + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); + } +} + +static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw, + struct sk_buff *new_skb, u8 *entry, + int rxring_idx, int desc_idx) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 bufferaddress; + u8 tmp_one = 1; + struct sk_buff *skb; + + if (likely(new_skb)) { + skb = new_skb; + goto remap; + } + skb = dev_alloc_skb(rtlpci->rxbuffersize); + if (!skb) + return 0; + +remap: + /* just set skb->cb to mapping addr for pci_unmap_single use */ + *((dma_addr_t *)skb->cb) = + pci_map_single(rtlpci->pdev, skb_tail_pointer(skb), + rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); + bufferaddress = *((dma_addr_t *)skb->cb); + if (pci_dma_mapping_error(rtlpci->pdev, bufferaddress)) + return 0; + rtlpci->rx_ring[rxring_idx].rx_buf[desc_idx] = skb; + if (rtlpriv->use_new_trx_flow) { + rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false, + HW_DESC_RX_PREPARE, + (u8 *)&bufferaddress); + } else { + rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false, + HW_DESC_RXBUFF_ADDR, + (u8 *)&bufferaddress); + rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false, + HW_DESC_RXPKT_LEN, + (u8 *)&rtlpci->rxbuffersize); + rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false, + HW_DESC_RXOWN, + (u8 *)&tmp_one); + } + return 1; +} + +/* inorder to receive 8K AMSDU we have set skb to + * 9100bytes in init rx ring, but if this packet is + * not a AMSDU, this large packet will be sent to + * TCP/IP directly, this cause big packet ping fail + * like: "ping -s 65507", so here we will realloc skb + * based on the true size of packet, Mac80211 + * Probably will do it better, but does not yet. + * + * Some platform will fail when alloc skb sometimes. + * in this condition, we will send the old skb to + * mac80211 directly, this will not cause any other + * issues, but only this packet will be lost by TCP/IP + */ +static void _rtl_pci_rx_to_mac80211(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct ieee80211_rx_status rx_status) +{ + if (unlikely(!rtl_action_proc(hw, skb, false))) { + dev_kfree_skb_any(skb); + } else { + struct sk_buff *uskb = NULL; + u8 *pdata; + + uskb = dev_alloc_skb(skb->len + 128); + if (likely(uskb)) { + memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, + sizeof(rx_status)); + pdata = (u8 *)skb_put(uskb, skb->len); + memcpy(pdata, skb->data, skb->len); + dev_kfree_skb_any(skb); + ieee80211_rx_irqsafe(hw, uskb); + } else { + ieee80211_rx_irqsafe(hw, skb); + } + } +} + +/*hsisr interrupt handler*/ +static void _rtl_pci_hs_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[MAC_HSISR], + rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[MAC_HSISR]) | + rtlpci->sys_irq_mask); +} + +static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + int rxring_idx = RTL_PCI_RX_MPDU_QUEUE; + struct ieee80211_rx_status rx_status = { 0 }; + unsigned int count = rtlpci->rxringcount; + u8 own; + u8 tmp_one; + bool unicast = false; + u8 hw_queue = 0; + unsigned int rx_remained_cnt; + struct rtl_stats stats = { + .signal = 0, + .rate = 0, + }; + + /*RX NORMAL PKT */ + while (count--) { + struct ieee80211_hdr *hdr; + __le16 fc; + u16 len; + /*rx buffer descriptor */ + struct rtl_rx_buffer_desc *buffer_desc = NULL; + /*if use new trx flow, it means wifi info */ + struct rtl_rx_desc *pdesc = NULL; + /*rx pkt */ + struct sk_buff *skb = rtlpci->rx_ring[rxring_idx].rx_buf[ + rtlpci->rx_ring[rxring_idx].idx]; + struct sk_buff *new_skb; + + if (rtlpriv->use_new_trx_flow) { + rx_remained_cnt = + rtlpriv->cfg->ops->rx_desc_buff_remained_cnt(hw, + hw_queue); + if (rx_remained_cnt == 0) + return; + + } else { /* rx descriptor */ + pdesc = &rtlpci->rx_ring[rxring_idx].desc[ + rtlpci->rx_ring[rxring_idx].idx]; + + own = (u8)rtlpriv->cfg->ops->get_desc((u8 *)pdesc, + false, + HW_DESC_OWN); + if (own) /* wait data to be filled by hardware */ + return; + } + + /* Reaching this point means: data is filled already + * AAAAAAttention !!! + * We can NOT access 'skb' before 'pci_unmap_single' + */ + pci_unmap_single(rtlpci->pdev, *((dma_addr_t *)skb->cb), + rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); + + /* get a new skb - if fail, old one will be reused */ + new_skb = dev_alloc_skb(rtlpci->rxbuffersize); + if (unlikely(!new_skb)) + goto no_new; + if (rtlpriv->use_new_trx_flow) { + buffer_desc = + &rtlpci->rx_ring[rxring_idx].buffer_desc + [rtlpci->rx_ring[rxring_idx].idx]; + /*means rx wifi info*/ + pdesc = (struct rtl_rx_desc *)skb->data; + } + memset(&rx_status , 0 , sizeof(rx_status)); + rtlpriv->cfg->ops->query_rx_desc(hw, &stats, + &rx_status, (u8 *)pdesc, skb); + + if (rtlpriv->use_new_trx_flow) + rtlpriv->cfg->ops->rx_check_dma_ok(hw, + (u8 *)buffer_desc, + hw_queue); + + len = rtlpriv->cfg->ops->get_desc((u8 *)pdesc, false, + HW_DESC_RXPKT_LEN); + + if (skb->end - skb->tail > len) { + skb_put(skb, len); + if (rtlpriv->use_new_trx_flow) + skb_reserve(skb, stats.rx_drvinfo_size + + stats.rx_bufshift + 24); + else + skb_reserve(skb, stats.rx_drvinfo_size + + stats.rx_bufshift); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "skb->end - skb->tail = %d, len is %d\n", + skb->end - skb->tail, len); + dev_kfree_skb_any(skb); + goto new_trx_end; + } + /* handle command packet here */ + if (rtlpriv->cfg->ops->rx_command_packet && + rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) { + dev_kfree_skb_any(skb); + goto new_trx_end; + } + + /* + * NOTICE This can not be use for mac80211, + * this is done in mac80211 code, + * if done here sec DHCP will fail + * skb_trim(skb, skb->len - 4); + */ + + hdr = rtl_get_hdr(skb); + fc = rtl_get_fc(skb); + + if (!stats.crc && !stats.hwerror) { + memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, + sizeof(rx_status)); + + if (is_broadcast_ether_addr(hdr->addr1)) { + ;/*TODO*/ + } else if (is_multicast_ether_addr(hdr->addr1)) { + ;/*TODO*/ + } else { + unicast = true; + rtlpriv->stats.rxbytesunicast += skb->len; + } + rtl_is_special_data(hw, skb, false, true); + + if (ieee80211_is_data(fc)) { + rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); + if (unicast) + rtlpriv->link_info.num_rx_inperiod++; + } + /* static bcn for roaming */ + rtl_beacon_statistic(hw, skb); + rtl_p2p_info(hw, (void *)skb->data, skb->len); + /* for sw lps */ + rtl_swlps_beacon(hw, (void *)skb->data, skb->len); + rtl_recognize_peer(hw, (void *)skb->data, skb->len); + if ((rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) && + (rtlpriv->rtlhal.current_bandtype == + BAND_ON_2_4G) && + (ieee80211_is_beacon(fc) || + ieee80211_is_probe_resp(fc))) { + dev_kfree_skb_any(skb); + } else { + _rtl_pci_rx_to_mac80211(hw, skb, rx_status); + } + } else { + dev_kfree_skb_any(skb); + } +new_trx_end: + if (rtlpriv->use_new_trx_flow) { + rtlpci->rx_ring[hw_queue].next_rx_rp += 1; + rtlpci->rx_ring[hw_queue].next_rx_rp %= + RTL_PCI_MAX_RX_COUNT; + + rx_remained_cnt--; + rtl_write_word(rtlpriv, 0x3B4, + rtlpci->rx_ring[hw_queue].next_rx_rp); + } + if (((rtlpriv->link_info.num_rx_inperiod + + rtlpriv->link_info.num_tx_inperiod) > 8) || + (rtlpriv->link_info.num_rx_inperiod > 2)) { + rtlpriv->enter_ps = false; + schedule_work(&rtlpriv->works.lps_change_work); + } + skb = new_skb; +no_new: + if (rtlpriv->use_new_trx_flow) { + _rtl_pci_init_one_rxdesc(hw, skb, (u8 *)buffer_desc, + rxring_idx, + rtlpci->rx_ring[rxring_idx].idx); + } else { + _rtl_pci_init_one_rxdesc(hw, skb, (u8 *)pdesc, + rxring_idx, + rtlpci->rx_ring[rxring_idx].idx); + if (rtlpci->rx_ring[rxring_idx].idx == + rtlpci->rxringcount - 1) + rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, + false, + HW_DESC_RXERO, + (u8 *)&tmp_one); + } + rtlpci->rx_ring[rxring_idx].idx = + (rtlpci->rx_ring[rxring_idx].idx + 1) % + rtlpci->rxringcount; + } +} + +static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) +{ + struct ieee80211_hw *hw = dev_id; + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + unsigned long flags; + u32 inta = 0; + u32 intb = 0; + irqreturn_t ret = IRQ_HANDLED; + + if (rtlpci->irq_enabled == 0) + return ret; + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock , flags); + rtlpriv->cfg->ops->disable_interrupt(hw); + + /*read ISR: 4/8bytes */ + rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb); + + /*Shared IRQ or HW disappared */ + if (!inta || inta == 0xffff) + goto done; + + /*<1> beacon related */ + if (inta & rtlpriv->cfg->maps[RTL_IMR_TBDOK]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + "beacon ok interrupt!\n"); + } + + if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_TBDER])) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + "beacon err interrupt!\n"); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_BDOK]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, "beacon interrupt!\n"); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_BCNINT]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + "prepare beacon for interrupt!\n"); + tasklet_schedule(&rtlpriv->works.irq_prepare_bcn_tasklet); + } + + /*<2> Tx related */ + if (unlikely(intb & rtlpriv->cfg->maps[RTL_IMR_TXFOVW])) + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "IMR_TXFOVW!\n"); + + if (inta & rtlpriv->cfg->maps[RTL_IMR_MGNTDOK]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + "Manage ok interrupt!\n"); + _rtl_pci_tx_isr(hw, MGNT_QUEUE); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_HIGHDOK]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + "HIGH_QUEUE ok interrupt!\n"); + _rtl_pci_tx_isr(hw, HIGH_QUEUE); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_BKDOK]) { + rtlpriv->link_info.num_tx_inperiod++; + + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + "BK Tx OK interrupt!\n"); + _rtl_pci_tx_isr(hw, BK_QUEUE); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_BEDOK]) { + rtlpriv->link_info.num_tx_inperiod++; + + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + "BE TX OK interrupt!\n"); + _rtl_pci_tx_isr(hw, BE_QUEUE); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_VIDOK]) { + rtlpriv->link_info.num_tx_inperiod++; + + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + "VI TX OK interrupt!\n"); + _rtl_pci_tx_isr(hw, VI_QUEUE); + } + + if (inta & rtlpriv->cfg->maps[RTL_IMR_VODOK]) { + rtlpriv->link_info.num_tx_inperiod++; + + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + "Vo TX OK interrupt!\n"); + _rtl_pci_tx_isr(hw, VO_QUEUE); + } + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { + if (inta & rtlpriv->cfg->maps[RTL_IMR_COMDOK]) { + rtlpriv->link_info.num_tx_inperiod++; + + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + "CMD TX OK interrupt!\n"); + _rtl_pci_tx_isr(hw, TXCMD_QUEUE); + } + } + + /*<3> Rx related */ + if (inta & rtlpriv->cfg->maps[RTL_IMR_ROK]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, "Rx ok interrupt!\n"); + _rtl_pci_rx_interrupt(hw); + } + + if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RDU])) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "rx descriptor unavailable!\n"); + _rtl_pci_rx_interrupt(hw); + } + + if (unlikely(intb & rtlpriv->cfg->maps[RTL_IMR_RXFOVW])) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "rx overflow !\n"); + _rtl_pci_rx_interrupt(hw); + } + + /*<4> fw related*/ + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723AE) { + if (inta & rtlpriv->cfg->maps[RTL_IMR_C2HCMD]) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + "firmware interrupt!\n"); + queue_delayed_work(rtlpriv->works.rtl_wq, + &rtlpriv->works.fwevt_wq, 0); + } + } + + /*<5> hsisr related*/ + /* Only 8188EE & 8723BE Supported. + * If Other ICs Come in, System will corrupt, + * because maps[RTL_IMR_HSISR_IND] & maps[MAC_HSISR] + * are not initialized + */ + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8188EE || + rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) { + if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_HSISR_IND])) { + RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, + "hsisr interrupt!\n"); + _rtl_pci_hs_interrupt(hw); + } + } + + if (rtlpriv->rtlhal.earlymode_enable) + tasklet_schedule(&rtlpriv->works.irq_tasklet); + +done: + rtlpriv->cfg->ops->enable_interrupt(hw); + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + return ret; +} + +static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw) +{ + _rtl_pci_tx_chk_waitq(hw); +} + +static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl8192_tx_ring *ring = NULL; + struct ieee80211_hdr *hdr = NULL; + struct ieee80211_tx_info *info = NULL; + struct sk_buff *pskb = NULL; + struct rtl_tx_desc *pdesc = NULL; + struct rtl_tcb_desc tcb_desc; + /*This is for new trx flow*/ + struct rtl_tx_buffer_desc *pbuffer_desc = NULL; + u8 temp_one = 1; + u8 *entry; + + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + ring = &rtlpci->tx_ring[BEACON_QUEUE]; + pskb = __skb_dequeue(&ring->queue); + if (rtlpriv->use_new_trx_flow) + entry = (u8 *)(&ring->buffer_desc[ring->idx]); + else + entry = (u8 *)(&ring->desc[ring->idx]); + if (pskb) { + pci_unmap_single(rtlpci->pdev, + rtlpriv->cfg->ops->get_desc( + (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), + pskb->len, PCI_DMA_TODEVICE); + kfree_skb(pskb); + } + + /*NB: the beacon data buffer must be 32-bit aligned. */ + pskb = ieee80211_beacon_get(hw, mac->vif); + if (pskb == NULL) + return; + hdr = rtl_get_hdr(pskb); + info = IEEE80211_SKB_CB(pskb); + pdesc = &ring->desc[0]; + if (rtlpriv->use_new_trx_flow) + pbuffer_desc = &ring->buffer_desc[0]; + + rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, + (u8 *)pbuffer_desc, info, NULL, pskb, + BEACON_QUEUE, &tcb_desc); + + __skb_queue_tail(&ring->queue, pskb); + + if (rtlpriv->use_new_trx_flow) { + temp_one = 4; + rtlpriv->cfg->ops->set_desc(hw, (u8 *)pbuffer_desc, true, + HW_DESC_OWN, (u8 *)&temp_one); + } else { + rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN, + &temp_one); + } + return; +} + +static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 i; + u16 desc_num; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) + desc_num = TX_DESC_NUM_92E; + else + desc_num = RT_TXDESC_NUM; + + for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) + rtlpci->txringcount[i] = desc_num; + + /* + *we just alloc 2 desc for beacon queue, + *because we just need first desc in hw beacon. + */ + rtlpci->txringcount[BEACON_QUEUE] = 2; + + /*BE queue need more descriptor for performance + *consideration or, No more tx desc will happen, + *and may cause mac80211 mem leakage. + */ + if (!rtl_priv(hw)->use_new_trx_flow) + rtlpci->txringcount[BE_QUEUE] = RT_TXDESC_NUM_BE_QUEUE; + + rtlpci->rxbuffersize = 9100; /*2048/1024; */ + rtlpci->rxringcount = RTL_PCI_MAX_RX_COUNT; /*64; */ +} + +static void _rtl_pci_init_struct(struct ieee80211_hw *hw, + struct pci_dev *pdev) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + rtlpci->up_first_time = true; + rtlpci->being_init_adapter = false; + + rtlhal->hw = hw; + rtlpci->pdev = pdev; + + /*Tx/Rx related var */ + _rtl_pci_init_trx_var(hw); + + /*IBSS*/ mac->beacon_interval = 100; + + /*AMPDU*/ + mac->min_space_cfg = 0; + mac->max_mss_density = 0; + /*set sane AMPDU defaults */ + mac->current_ampdu_density = 7; + mac->current_ampdu_factor = 3; + + /*QOS*/ + rtlpci->acm_method = EACMWAY2_SW; + + /*task */ + tasklet_init(&rtlpriv->works.irq_tasklet, + (void (*)(unsigned long))_rtl_pci_irq_tasklet, + (unsigned long)hw); + tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, + (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, + (unsigned long)hw); + INIT_WORK(&rtlpriv->works.lps_change_work, + rtl_lps_change_work_callback); +} + +static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, + unsigned int prio, unsigned int entries) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_tx_buffer_desc *buffer_desc; + struct rtl_tx_desc *desc; + dma_addr_t buffer_desc_dma, desc_dma; + u32 nextdescaddress; + int i; + + /* alloc tx buffer desc for new trx flow*/ + if (rtlpriv->use_new_trx_flow) { + buffer_desc = + pci_zalloc_consistent(rtlpci->pdev, + sizeof(*buffer_desc) * entries, + &buffer_desc_dma); + + if (!buffer_desc || (unsigned long)buffer_desc & 0xFF) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Cannot allocate TX ring (prio = %d)\n", + prio); + return -ENOMEM; + } + + rtlpci->tx_ring[prio].buffer_desc = buffer_desc; + rtlpci->tx_ring[prio].buffer_desc_dma = buffer_desc_dma; + + rtlpci->tx_ring[prio].cur_tx_rp = 0; + rtlpci->tx_ring[prio].cur_tx_wp = 0; + rtlpci->tx_ring[prio].avl_desc = entries; + } + + /* alloc dma for this ring */ + desc = pci_zalloc_consistent(rtlpci->pdev, + sizeof(*desc) * entries, &desc_dma); + + if (!desc || (unsigned long)desc & 0xFF) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Cannot allocate TX ring (prio = %d)\n", prio); + return -ENOMEM; + } + + rtlpci->tx_ring[prio].desc = desc; + rtlpci->tx_ring[prio].dma = desc_dma; + + rtlpci->tx_ring[prio].idx = 0; + rtlpci->tx_ring[prio].entries = entries; + skb_queue_head_init(&rtlpci->tx_ring[prio].queue); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "queue:%d, ring_addr:%p\n", + prio, desc); + + /* init every desc in this ring */ + if (!rtlpriv->use_new_trx_flow) { + for (i = 0; i < entries; i++) { + nextdescaddress = (u32)desc_dma + + ((i + 1) % entries) * + sizeof(*desc); + + rtlpriv->cfg->ops->set_desc(hw, (u8 *)&desc[i], + true, + HW_DESC_TX_NEXTDESC_ADDR, + (u8 *)&nextdescaddress); + } + } + return 0; +} + +static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + int i; + + if (rtlpriv->use_new_trx_flow) { + struct rtl_rx_buffer_desc *entry = NULL; + /* alloc dma for this ring */ + rtlpci->rx_ring[rxring_idx].buffer_desc = + pci_zalloc_consistent(rtlpci->pdev, + sizeof(*rtlpci->rx_ring[rxring_idx]. + buffer_desc) * + rtlpci->rxringcount, + &rtlpci->rx_ring[rxring_idx].dma); + if (!rtlpci->rx_ring[rxring_idx].buffer_desc || + (ulong)rtlpci->rx_ring[rxring_idx].buffer_desc & 0xFF) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Cannot allocate RX ring\n"); + return -ENOMEM; + } + + /* init every desc in this ring */ + rtlpci->rx_ring[rxring_idx].idx = 0; + for (i = 0; i < rtlpci->rxringcount; i++) { + entry = &rtlpci->rx_ring[rxring_idx].buffer_desc[i]; + if (!_rtl_pci_init_one_rxdesc(hw, NULL, (u8 *)entry, + rxring_idx, i)) + return -ENOMEM; + } + } else { + struct rtl_rx_desc *entry = NULL; + u8 tmp_one = 1; + /* alloc dma for this ring */ + rtlpci->rx_ring[rxring_idx].desc = + pci_zalloc_consistent(rtlpci->pdev, + sizeof(*rtlpci->rx_ring[rxring_idx]. + desc) * rtlpci->rxringcount, + &rtlpci->rx_ring[rxring_idx].dma); + if (!rtlpci->rx_ring[rxring_idx].desc || + (unsigned long)rtlpci->rx_ring[rxring_idx].desc & 0xFF) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Cannot allocate RX ring\n"); + return -ENOMEM; + } + + /* init every desc in this ring */ + rtlpci->rx_ring[rxring_idx].idx = 0; + + for (i = 0; i < rtlpci->rxringcount; i++) { + entry = &rtlpci->rx_ring[rxring_idx].desc[i]; + if (!_rtl_pci_init_one_rxdesc(hw, NULL, (u8 *)entry, + rxring_idx, i)) + return -ENOMEM; + } + + rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false, + HW_DESC_RXERO, &tmp_one); + } + return 0; +} + +static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw, + unsigned int prio) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[prio]; + + /* free every desc in this ring */ + while (skb_queue_len(&ring->queue)) { + u8 *entry; + struct sk_buff *skb = __skb_dequeue(&ring->queue); + + if (rtlpriv->use_new_trx_flow) + entry = (u8 *)(&ring->buffer_desc[ring->idx]); + else + entry = (u8 *)(&ring->desc[ring->idx]); + + pci_unmap_single(rtlpci->pdev, + rtlpriv->cfg-> + ops->get_desc((u8 *)entry, true, + HW_DESC_TXBUFF_ADDR), + skb->len, PCI_DMA_TODEVICE); + kfree_skb(skb); + ring->idx = (ring->idx + 1) % ring->entries; + } + + /* free dma of this ring */ + pci_free_consistent(rtlpci->pdev, + sizeof(*ring->desc) * ring->entries, + ring->desc, ring->dma); + ring->desc = NULL; + if (rtlpriv->use_new_trx_flow) { + pci_free_consistent(rtlpci->pdev, + sizeof(*ring->buffer_desc) * ring->entries, + ring->buffer_desc, ring->buffer_desc_dma); + ring->buffer_desc = NULL; + } +} + +static void _rtl_pci_free_rx_ring(struct ieee80211_hw *hw, int rxring_idx) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + int i; + + /* free every desc in this ring */ + for (i = 0; i < rtlpci->rxringcount; i++) { + struct sk_buff *skb = rtlpci->rx_ring[rxring_idx].rx_buf[i]; + + if (!skb) + continue; + pci_unmap_single(rtlpci->pdev, *((dma_addr_t *)skb->cb), + rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); + kfree_skb(skb); + } + + /* free dma of this ring */ + if (rtlpriv->use_new_trx_flow) { + pci_free_consistent(rtlpci->pdev, + sizeof(*rtlpci->rx_ring[rxring_idx]. + buffer_desc) * rtlpci->rxringcount, + rtlpci->rx_ring[rxring_idx].buffer_desc, + rtlpci->rx_ring[rxring_idx].dma); + rtlpci->rx_ring[rxring_idx].buffer_desc = NULL; + } else { + pci_free_consistent(rtlpci->pdev, + sizeof(*rtlpci->rx_ring[rxring_idx].desc) * + rtlpci->rxringcount, + rtlpci->rx_ring[rxring_idx].desc, + rtlpci->rx_ring[rxring_idx].dma); + rtlpci->rx_ring[rxring_idx].desc = NULL; + } +} + +static int _rtl_pci_init_trx_ring(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + int ret; + int i, rxring_idx; + + /* rxring_idx 0:RX_MPDU_QUEUE + * rxring_idx 1:RX_CMD_QUEUE + */ + for (rxring_idx = 0; rxring_idx < RTL_PCI_MAX_RX_QUEUE; rxring_idx++) { + ret = _rtl_pci_init_rx_ring(hw, rxring_idx); + if (ret) + return ret; + } + + for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) { + ret = _rtl_pci_init_tx_ring(hw, i, + rtlpci->txringcount[i]); + if (ret) + goto err_free_rings; + } + + return 0; + +err_free_rings: + for (rxring_idx = 0; rxring_idx < RTL_PCI_MAX_RX_QUEUE; rxring_idx++) + _rtl_pci_free_rx_ring(hw, rxring_idx); + + for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) + if (rtlpci->tx_ring[i].desc || + rtlpci->tx_ring[i].buffer_desc) + _rtl_pci_free_tx_ring(hw, i); + + return 1; +} + +static int _rtl_pci_deinit_trx_ring(struct ieee80211_hw *hw) +{ + u32 i, rxring_idx; + + /*free rx rings */ + for (rxring_idx = 0; rxring_idx < RTL_PCI_MAX_RX_QUEUE; rxring_idx++) + _rtl_pci_free_rx_ring(hw, rxring_idx); + + /*free tx rings */ + for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) + _rtl_pci_free_tx_ring(hw, i); + + return 0; +} + +int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + int i, rxring_idx; + unsigned long flags; + u8 tmp_one = 1; + u32 bufferaddress; + /* rxring_idx 0:RX_MPDU_QUEUE */ + /* rxring_idx 1:RX_CMD_QUEUE */ + for (rxring_idx = 0; rxring_idx < RTL_PCI_MAX_RX_QUEUE; rxring_idx++) { + /* force the rx_ring[RX_MPDU_QUEUE/ + * RX_CMD_QUEUE].idx to the first one + *new trx flow, do nothing + */ + if (!rtlpriv->use_new_trx_flow && + rtlpci->rx_ring[rxring_idx].desc) { + struct rtl_rx_desc *entry = NULL; + + rtlpci->rx_ring[rxring_idx].idx = 0; + for (i = 0; i < rtlpci->rxringcount; i++) { + entry = &rtlpci->rx_ring[rxring_idx].desc[i]; + bufferaddress = + rtlpriv->cfg->ops->get_desc((u8 *)entry, + false , HW_DESC_RXBUFF_ADDR); + memset((u8 *)entry , 0 , + sizeof(*rtlpci->rx_ring + [rxring_idx].desc));/*clear one entry*/ + if (rtlpriv->use_new_trx_flow) { + rtlpriv->cfg->ops->set_desc(hw, + (u8 *)entry, false, + HW_DESC_RX_PREPARE, + (u8 *)&bufferaddress); + } else { + rtlpriv->cfg->ops->set_desc(hw, + (u8 *)entry, false, + HW_DESC_RXBUFF_ADDR, + (u8 *)&bufferaddress); + rtlpriv->cfg->ops->set_desc(hw, + (u8 *)entry, false, + HW_DESC_RXPKT_LEN, + (u8 *)&rtlpci->rxbuffersize); + rtlpriv->cfg->ops->set_desc(hw, + (u8 *)entry, false, + HW_DESC_RXOWN, + (u8 *)&tmp_one); + } + } + rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false, + HW_DESC_RXERO, (u8 *)&tmp_one); + } + rtlpci->rx_ring[rxring_idx].idx = 0; + } + + /* + *after reset, release previous pending packet, + *and force the tx idx to the first one + */ + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) { + if (rtlpci->tx_ring[i].desc || + rtlpci->tx_ring[i].buffer_desc) { + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[i]; + + while (skb_queue_len(&ring->queue)) { + u8 *entry; + struct sk_buff *skb = + __skb_dequeue(&ring->queue); + if (rtlpriv->use_new_trx_flow) + entry = (u8 *)(&ring->buffer_desc + [ring->idx]); + else + entry = (u8 *)(&ring->desc[ring->idx]); + + pci_unmap_single(rtlpci->pdev, + rtlpriv->cfg->ops-> + get_desc((u8 *) + entry, + true, + HW_DESC_TXBUFF_ADDR), + skb->len, PCI_DMA_TODEVICE); + kfree_skb(skb); + ring->idx = (ring->idx + 1) % ring->entries; + } + ring->idx = 0; + } + } + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + + return 0; +} + +static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_sta_info *sta_entry = NULL; + u8 tid = rtl_get_tid(skb); + __le16 fc = rtl_get_fc(skb); + + if (!sta) + return false; + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + + if (!rtlpriv->rtlhal.earlymode_enable) + return false; + if (ieee80211_is_nullfunc(fc)) + return false; + if (ieee80211_is_qos_nullfunc(fc)) + return false; + if (ieee80211_is_pspoll(fc)) + return false; + if (sta_entry->tids[tid].agg.agg_state != RTL_AGG_OPERATIONAL) + return false; + if (_rtl_mac_to_hwqueue(hw, skb) > VO_QUEUE) + return false; + if (tid > 7) + return false; + + /* maybe every tid should be checked */ + if (!rtlpriv->link_info.higher_busytxtraffic[tid]) + return false; + + spin_lock_bh(&rtlpriv->locks.waitq_lock); + skb_queue_tail(&rtlpriv->mac80211.skb_waitq[tid], skb); + spin_unlock_bh(&rtlpriv->locks.waitq_lock); + + return true; +} + +static int rtl_pci_tx(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb, + struct rtl_tcb_desc *ptcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_sta_info *sta_entry = NULL; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct rtl8192_tx_ring *ring; + struct rtl_tx_desc *pdesc; + struct rtl_tx_buffer_desc *ptx_bd_desc = NULL; + u16 idx; + u8 hw_queue = _rtl_mac_to_hwqueue(hw, skb); + unsigned long flags; + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); + __le16 fc = rtl_get_fc(skb); + u8 *pda_addr = hdr->addr1; + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + /*ssn */ + u8 tid = 0; + u16 seq_number = 0; + u8 own; + u8 temp_one = 1; + + if (ieee80211_is_mgmt(fc)) + rtl_tx_mgmt_proc(hw, skb); + + if (rtlpriv->psc.sw_ps_enabled) { + if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && + !ieee80211_has_pm(fc)) + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); + } + + rtl_action_proc(hw, skb, true); + + if (is_multicast_ether_addr(pda_addr)) + rtlpriv->stats.txbytesmulticast += skb->len; + else if (is_broadcast_ether_addr(pda_addr)) + rtlpriv->stats.txbytesbroadcast += skb->len; + else + rtlpriv->stats.txbytesunicast += skb->len; + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + ring = &rtlpci->tx_ring[hw_queue]; + if (hw_queue != BEACON_QUEUE) { + if (rtlpriv->use_new_trx_flow) + idx = ring->cur_tx_wp; + else + idx = (ring->idx + skb_queue_len(&ring->queue)) % + ring->entries; + } else { + idx = 0; + } + + pdesc = &ring->desc[idx]; + if (rtlpriv->use_new_trx_flow) { + ptx_bd_desc = &ring->buffer_desc[idx]; + } else { + own = (u8) rtlpriv->cfg->ops->get_desc((u8 *)pdesc, + true, HW_DESC_OWN); + + if ((own == 1) && (hw_queue != BEACON_QUEUE)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "No more TX desc@%d, ring->idx = %d, idx = %d, skb_queue_len = 0x%x\n", + hw_queue, ring->idx, idx, + skb_queue_len(&ring->queue)); + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, + flags); + return skb->len; + } + } + + if (rtlpriv->cfg->ops->get_available_desc && + rtlpriv->cfg->ops->get_available_desc(hw, hw_queue) == 0) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "get_available_desc fail\n"); + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, + flags); + return skb->len; + } + + if (ieee80211_is_data_qos(fc)) { + tid = rtl_get_tid(skb); + if (sta) { + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + seq_number = (le16_to_cpu(hdr->seq_ctrl) & + IEEE80211_SCTL_SEQ) >> 4; + seq_number += 1; + + if (!ieee80211_has_morefrags(hdr->frame_control)) + sta_entry->tids[tid].seq_number = seq_number; + } + } + + if (ieee80211_is_data(fc)) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); + + rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, + (u8 *)ptx_bd_desc, info, sta, skb, hw_queue, ptcb_desc); + + __skb_queue_tail(&ring->queue, skb); + + if (rtlpriv->use_new_trx_flow) { + rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, + HW_DESC_OWN, &hw_queue); + } else { + rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, + HW_DESC_OWN, &temp_one); + } + + if ((ring->entries - skb_queue_len(&ring->queue)) < 2 && + hw_queue != BEACON_QUEUE) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "less desc left, stop skb_queue@%d, ring->idx = %d, idx = %d, skb_queue_len = 0x%x\n", + hw_queue, ring->idx, idx, + skb_queue_len(&ring->queue)); + + ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); + } + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + + rtlpriv->cfg->ops->tx_polling(hw, hw_queue); + + return 0; +} + +static void rtl_pci_flush(struct ieee80211_hw *hw, u32 queues, bool drop) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 i = 0; + int queue_id; + struct rtl8192_tx_ring *ring; + + if (mac->skip_scan) + return; + + for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { + u32 queue_len; + + if (((queues >> queue_id) & 0x1) == 0) { + queue_id--; + continue; + } + ring = &pcipriv->dev.tx_ring[queue_id]; + queue_len = skb_queue_len(&ring->queue); + if (queue_len == 0 || queue_id == BEACON_QUEUE || + queue_id == TXCMD_QUEUE) { + queue_id--; + continue; + } else { + msleep(20); + i++; + } + + /* we just wait 1s for all queues */ + if (rtlpriv->psc.rfpwr_state == ERFOFF || + is_hal_stop(rtlhal) || i >= 200) + return; + } +} + +static void rtl_pci_deinit(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + _rtl_pci_deinit_trx_ring(hw); + + synchronize_irq(rtlpci->pdev->irq); + tasklet_kill(&rtlpriv->works.irq_tasklet); + cancel_work_sync(&rtlpriv->works.lps_change_work); + + flush_workqueue(rtlpriv->works.rtl_wq); + destroy_workqueue(rtlpriv->works.rtl_wq); + +} + +static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int err; + + _rtl_pci_init_struct(hw, pdev); + + err = _rtl_pci_init_trx_ring(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "tx ring initialization failed\n"); + return err; + } + + return 0; +} + +static int rtl_pci_start(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + int err; + + rtl_pci_reset_trx_ring(hw); + + rtlpci->driver_is_goingto_unload = false; + if (rtlpriv->cfg->ops->get_btc_status && + rtlpriv->cfg->ops->get_btc_status()) { + rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv); + rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv); + } + err = rtlpriv->cfg->ops->hw_init(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Failed to config hardware!\n"); + return err; + } + + rtlpriv->cfg->ops->enable_interrupt(hw); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "enable_interrupt OK\n"); + + rtl_init_rx_config(hw); + + /*should be after adapter start and interrupt enable. */ + set_hal_start(rtlhal); + + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + + rtlpci->up_first_time = false; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "rtl_pci_start OK\n"); + return 0; +} + +static void rtl_pci_stop(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + unsigned long flags; + u8 RFInProgressTimeOut = 0; + + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_halt_notify(); + + /* + *should be before disable interrupt&adapter + *and will do it immediately. + */ + set_hal_stop(rtlhal); + + rtlpci->driver_is_goingto_unload = true; + rtlpriv->cfg->ops->disable_interrupt(hw); + cancel_work_sync(&rtlpriv->works.lps_change_work); + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); + while (ppsc->rfchange_inprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); + if (RFInProgressTimeOut > 100) { + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); + break; + } + mdelay(1); + RFInProgressTimeOut++; + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); + } + ppsc->rfchange_inprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); + + rtlpriv->cfg->ops->hw_disable(hw); + /* some things are not needed if firmware not available */ + if (!rtlpriv->max_fw_size) + return; + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); + + rtl_pci_enable_aspm(hw); +} + +static bool _rtl_pci_find_adapter(struct pci_dev *pdev, + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct pci_dev *bridge_pdev = pdev->bus->self; + u16 venderid; + u16 deviceid; + u8 revisionid; + u16 irqline; + u8 tmp; + + pcipriv->ndis_adapter.pcibridge_vendor = PCI_BRIDGE_VENDOR_UNKNOWN; + venderid = pdev->vendor; + deviceid = pdev->device; + pci_read_config_byte(pdev, 0x8, &revisionid); + pci_read_config_word(pdev, 0x3C, &irqline); + + /* PCI ID 0x10ec:0x8192 occurs for both RTL8192E, which uses + * r8192e_pci, and RTL8192SE, which uses this driver. If the + * revision ID is RTL_PCI_REVISION_ID_8192PCIE (0x01), then + * the correct driver is r8192e_pci, thus this routine should + * return false. + */ + if (deviceid == RTL_PCI_8192SE_DID && + revisionid == RTL_PCI_REVISION_ID_8192PCIE) + return false; + + if (deviceid == RTL_PCI_8192_DID || + deviceid == RTL_PCI_0044_DID || + deviceid == RTL_PCI_0047_DID || + deviceid == RTL_PCI_8192SE_DID || + deviceid == RTL_PCI_8174_DID || + deviceid == RTL_PCI_8173_DID || + deviceid == RTL_PCI_8172_DID || + deviceid == RTL_PCI_8171_DID) { + switch (revisionid) { + case RTL_PCI_REVISION_ID_8192PCIE: + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "8192 PCI-E is found - vid/did=%x/%x\n", + venderid, deviceid); + rtlhal->hw_type = HARDWARE_TYPE_RTL8192E; + return false; + case RTL_PCI_REVISION_ID_8192SE: + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "8192SE is found - vid/did=%x/%x\n", + venderid, deviceid); + rtlhal->hw_type = HARDWARE_TYPE_RTL8192SE; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Err: Unknown device - vid/did=%x/%x\n", + venderid, deviceid); + rtlhal->hw_type = HARDWARE_TYPE_RTL8192SE; + break; + + } + } else if (deviceid == RTL_PCI_8723AE_DID) { + rtlhal->hw_type = HARDWARE_TYPE_RTL8723AE; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "8723AE PCI-E is found - " + "vid/did=%x/%x\n", venderid, deviceid); + } else if (deviceid == RTL_PCI_8192CET_DID || + deviceid == RTL_PCI_8192CE_DID || + deviceid == RTL_PCI_8191CE_DID || + deviceid == RTL_PCI_8188CE_DID) { + rtlhal->hw_type = HARDWARE_TYPE_RTL8192CE; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "8192C PCI-E is found - vid/did=%x/%x\n", + venderid, deviceid); + } else if (deviceid == RTL_PCI_8192DE_DID || + deviceid == RTL_PCI_8192DE_DID2) { + rtlhal->hw_type = HARDWARE_TYPE_RTL8192DE; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "8192D PCI-E is found - vid/did=%x/%x\n", + venderid, deviceid); + } else if (deviceid == RTL_PCI_8188EE_DID) { + rtlhal->hw_type = HARDWARE_TYPE_RTL8188EE; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Find adapter, Hardware type is 8188EE\n"); + } else if (deviceid == RTL_PCI_8723BE_DID) { + rtlhal->hw_type = HARDWARE_TYPE_RTL8723BE; + RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD, + "Find adapter, Hardware type is 8723BE\n"); + } else if (deviceid == RTL_PCI_8192EE_DID) { + rtlhal->hw_type = HARDWARE_TYPE_RTL8192EE; + RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD, + "Find adapter, Hardware type is 8192EE\n"); + } else if (deviceid == RTL_PCI_8821AE_DID) { + rtlhal->hw_type = HARDWARE_TYPE_RTL8821AE; + RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD, + "Find adapter, Hardware type is 8821AE\n"); + } else if (deviceid == RTL_PCI_8812AE_DID) { + rtlhal->hw_type = HARDWARE_TYPE_RTL8812AE; + RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD, + "Find adapter, Hardware type is 8812AE\n"); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Err: Unknown device - vid/did=%x/%x\n", + venderid, deviceid); + + rtlhal->hw_type = RTL_DEFAULT_HARDWARE_TYPE; + } + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) { + if (revisionid == 0 || revisionid == 1) { + if (revisionid == 0) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Find 92DE MAC0\n"); + rtlhal->interfaceindex = 0; + } else if (revisionid == 1) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Find 92DE MAC1\n"); + rtlhal->interfaceindex = 1; + } + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Unknown device - VendorID/DeviceID=%x/%x, Revision=%x\n", + venderid, deviceid, revisionid); + rtlhal->interfaceindex = 0; + } + } + + /* 92ee use new trx flow */ + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) + rtlpriv->use_new_trx_flow = true; + else + rtlpriv->use_new_trx_flow = false; + + /*find bus info */ + pcipriv->ndis_adapter.busnumber = pdev->bus->number; + pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); + pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn); + + /*find bridge info */ + pcipriv->ndis_adapter.pcibridge_vendor = PCI_BRIDGE_VENDOR_UNKNOWN; + /* some ARM have no bridge_pdev and will crash here + * so we should check if bridge_pdev is NULL + */ + if (bridge_pdev) { + /*find bridge info if available */ + pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor; + for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) { + if (bridge_pdev->vendor == pcibridge_vendors[tmp]) { + pcipriv->ndis_adapter.pcibridge_vendor = tmp; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Pci Bridge Vendor is found index: %d\n", + tmp); + break; + } + } + } + + if (pcipriv->ndis_adapter.pcibridge_vendor != + PCI_BRIDGE_VENDOR_UNKNOWN) { + pcipriv->ndis_adapter.pcibridge_busnum = + bridge_pdev->bus->number; + pcipriv->ndis_adapter.pcibridge_devnum = + PCI_SLOT(bridge_pdev->devfn); + pcipriv->ndis_adapter.pcibridge_funcnum = + PCI_FUNC(bridge_pdev->devfn); + pcipriv->ndis_adapter.pcibridge_pciehdr_offset = + pci_pcie_cap(bridge_pdev); + pcipriv->ndis_adapter.num4bytes = + (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10) / 4; + + rtl_pci_get_linkcontrol_field(hw); + + if (pcipriv->ndis_adapter.pcibridge_vendor == + PCI_BRIDGE_VENDOR_AMD) { + pcipriv->ndis_adapter.amd_l1_patch = + rtl_pci_get_amd_l1_patch(hw); + } + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "pcidev busnumber:devnumber:funcnumber:vendor:link_ctl %d:%d:%d:%x:%x\n", + pcipriv->ndis_adapter.busnumber, + pcipriv->ndis_adapter.devnumber, + pcipriv->ndis_adapter.funcnumber, + pdev->vendor, pcipriv->ndis_adapter.linkctrl_reg); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "pci_bridge busnumber:devnumber:funcnumber:vendor:pcie_cap:link_ctl_reg:amd %d:%d:%d:%x:%x:%x:%x\n", + pcipriv->ndis_adapter.pcibridge_busnum, + pcipriv->ndis_adapter.pcibridge_devnum, + pcipriv->ndis_adapter.pcibridge_funcnum, + pcibridge_vendors[pcipriv->ndis_adapter.pcibridge_vendor], + pcipriv->ndis_adapter.pcibridge_pciehdr_offset, + pcipriv->ndis_adapter.pcibridge_linkctrlreg, + pcipriv->ndis_adapter.amd_l1_patch); + + rtl_pci_parse_configuration(pdev, hw); + list_add_tail(&rtlpriv->list, &rtlpriv->glb_var->glb_priv_list); + + return true; +} + +static int rtl_pci_intr_mode_msi(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); + int ret; + + ret = pci_enable_msi(rtlpci->pdev); + if (ret < 0) + return ret; + + ret = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt, + IRQF_SHARED, KBUILD_MODNAME, hw); + if (ret < 0) { + pci_disable_msi(rtlpci->pdev); + return ret; + } + + rtlpci->using_msi = true; + + RT_TRACE(rtlpriv, COMP_INIT|COMP_INTR, DBG_DMESG, + "MSI Interrupt Mode!\n"); + return 0; +} + +static int rtl_pci_intr_mode_legacy(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); + int ret; + + ret = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt, + IRQF_SHARED, KBUILD_MODNAME, hw); + if (ret < 0) + return ret; + + rtlpci->using_msi = false; + RT_TRACE(rtlpriv, COMP_INIT|COMP_INTR, DBG_DMESG, + "Pin-based Interrupt Mode!\n"); + return 0; +} + +static int rtl_pci_intr_mode_decide(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); + int ret; + + if (rtlpci->msi_support) { + ret = rtl_pci_intr_mode_msi(hw); + if (ret < 0) + ret = rtl_pci_intr_mode_legacy(hw); + } else { + ret = rtl_pci_intr_mode_legacy(hw); + } + return ret; +} + +int rtl_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct ieee80211_hw *hw = NULL; + + struct rtl_priv *rtlpriv = NULL; + struct rtl_pci_priv *pcipriv = NULL; + struct rtl_pci *rtlpci; + unsigned long pmem_start, pmem_len, pmem_flags; + int err; + + err = pci_enable_device(pdev); + if (err) { + RT_ASSERT(false, "%s : Cannot enable new PCI device\n", + pci_name(pdev)); + return err; + } + + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { + if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { + RT_ASSERT(false, + "Unable to obtain 32bit DMA for consistent allocations\n"); + err = -ENOMEM; + goto fail1; + } + } + + pci_set_master(pdev); + + hw = ieee80211_alloc_hw(sizeof(struct rtl_pci_priv) + + sizeof(struct rtl_priv), &rtl_ops); + if (!hw) { + RT_ASSERT(false, + "%s : ieee80211 alloc failed\n", pci_name(pdev)); + err = -ENOMEM; + goto fail1; + } + + SET_IEEE80211_DEV(hw, &pdev->dev); + pci_set_drvdata(pdev, hw); + + rtlpriv = hw->priv; + rtlpriv->hw = hw; + pcipriv = (void *)rtlpriv->priv; + pcipriv->dev.pdev = pdev; + init_completion(&rtlpriv->firmware_loading_complete); + /*proximity init here*/ + rtlpriv->proximity.proxim_on = false; + + pcipriv = (void *)rtlpriv->priv; + pcipriv->dev.pdev = pdev; + + /* init cfg & intf_ops */ + rtlpriv->rtlhal.interface = INTF_PCI; + rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); + 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) { + RT_ASSERT(false, "Can't obtain PCI resources\n"); + goto fail1; + } + + pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); + pmem_len = pci_resource_len(pdev, rtlpriv->cfg->bar_id); + pmem_flags = pci_resource_flags(pdev, rtlpriv->cfg->bar_id); + + /*shared mem start */ + rtlpriv->io.pci_mem_start = + (unsigned long)pci_iomap(pdev, + rtlpriv->cfg->bar_id, pmem_len); + if (rtlpriv->io.pci_mem_start == 0) { + RT_ASSERT(false, "Can't map PCI mem\n"); + err = -ENOMEM; + goto fail2; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "mem mapped space: start: 0x%08lx len:%08lx flags:%08lx, after map:0x%08lx\n", + pmem_start, pmem_len, pmem_flags, + rtlpriv->io.pci_mem_start); + + /* Disable Clk Request */ + pci_write_config_byte(pdev, 0x81, 0); + /* leave D3 mode */ + pci_write_config_byte(pdev, 0x44, 0); + pci_write_config_byte(pdev, 0x04, 0x06); + pci_write_config_byte(pdev, 0x04, 0x07); + + /* find adapter */ + if (!_rtl_pci_find_adapter(pdev, hw)) { + err = -ENODEV; + goto fail3; + } + + /* Init IO handler */ + _rtl_pci_io_handler_init(&pdev->dev, hw); + + /*like read eeprom and so on */ + rtlpriv->cfg->ops->read_eeprom_info(hw); + + if (rtlpriv->cfg->ops->init_sw_vars(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n"); + err = -ENODEV; + goto fail3; + } + rtlpriv->cfg->ops->init_sw_leds(hw); + + /*aspm */ + rtl_pci_init_aspm(hw); + + /* Init mac80211 sw */ + err = rtl_init_core(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't allocate sw for mac80211\n"); + goto fail3; + } + + /* Init PCI sw */ + err = rtl_pci_init(hw, pdev); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Failed to init PCI\n"); + goto fail3; + } + + err = ieee80211_register_hw(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't register mac80211 hw.\n"); + err = -ENODEV; + goto fail3; + } + rtlpriv->mac80211.mac80211_registered = 1; + + err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "failed to create sysfs device attributes\n"); + goto fail3; + } + + /*init rfkill */ + rtl_init_rfkill(hw); /* Init PCI sw */ + + rtlpci = rtl_pcidev(pcipriv); + err = rtl_pci_intr_mode_decide(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "%s: failed to register IRQ handler\n", + wiphy_name(hw->wiphy)); + goto fail3; + } + rtlpci->irq_alloc = 1; + + set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); + return 0; + +fail3: + pci_set_drvdata(pdev, NULL); + rtl_deinit_core(hw); + + if (rtlpriv->io.pci_mem_start != 0) + pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); + +fail2: + pci_release_regions(pdev); + complete(&rtlpriv->firmware_loading_complete); + +fail1: + if (hw) + ieee80211_free_hw(hw); + pci_disable_device(pdev); + + return err; + +} +EXPORT_SYMBOL(rtl_pci_probe); + +void rtl_pci_disconnect(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); + struct rtl_mac *rtlmac = rtl_mac(rtlpriv); + + /* just in case driver is removed before firmware callback */ + 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); + rtlmac->mac80211_registered = 0; + } else { + rtl_deinit_deferred_work(hw); + rtlpriv->intf_ops->adapter_stop(hw); + } + rtlpriv->cfg->ops->disable_interrupt(hw); + + /*deinit rfkill */ + rtl_deinit_rfkill(hw); + + rtl_pci_deinit(hw); + rtl_deinit_core(hw); + rtlpriv->cfg->ops->deinit_sw_vars(hw); + + if (rtlpci->irq_alloc) { + synchronize_irq(rtlpci->pdev->irq); + free_irq(rtlpci->pdev->irq, hw); + rtlpci->irq_alloc = 0; + } + + if (rtlpci->using_msi) + pci_disable_msi(rtlpci->pdev); + + list_del(&rtlpriv->list); + if (rtlpriv->io.pci_mem_start != 0) { + pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); + pci_release_regions(pdev); + } + + pci_disable_device(pdev); + + rtl_pci_disable_aspm(hw); + + pci_set_drvdata(pdev, NULL); + + ieee80211_free_hw(hw); +} +EXPORT_SYMBOL(rtl_pci_disconnect); + +#ifdef CONFIG_PM_SLEEP +/*************************************** +kernel pci power state define: +PCI_D0 ((pci_power_t __force) 0) +PCI_D1 ((pci_power_t __force) 1) +PCI_D2 ((pci_power_t __force) 2) +PCI_D3hot ((pci_power_t __force) 3) +PCI_D3cold ((pci_power_t __force) 4) +PCI_UNKNOWN ((pci_power_t __force) 5) + +This function is called when system +goes into suspend state mac80211 will +call rtl_mac_stop() from the mac80211 +suspend function first, So there is +no need to call hw_disable here. +****************************************/ +int rtl_pci_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->cfg->ops->hw_suspend(hw); + rtl_deinit_rfkill(hw); + + return 0; +} +EXPORT_SYMBOL(rtl_pci_suspend); + +int rtl_pci_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->cfg->ops->hw_resume(hw); + rtl_init_rfkill(hw); + return 0; +} +EXPORT_SYMBOL(rtl_pci_resume); +#endif /* CONFIG_PM_SLEEP */ + +struct rtl_intf_ops rtl_pci_ops = { + .read_efuse_byte = read_efuse_byte, + .adapter_start = rtl_pci_start, + .adapter_stop = rtl_pci_stop, + .check_buddy_priv = rtl_pci_check_buddy_priv, + .adapter_tx = rtl_pci_tx, + .flush = rtl_pci_flush, + .reset_trx_ring = rtl_pci_reset_trx_ring, + .waitq_insert = rtl_pci_tx_chk_waitq_insert, + + .disable_aspm = rtl_pci_disable_aspm, + .enable_aspm = rtl_pci_enable_aspm, +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.h b/drivers/net/wireless/realtek/rtlwifi/pci.h new file mode 100644 index 000000000000..d4567d12e07e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/pci.h @@ -0,0 +1,335 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL_PCI_H__ +#define __RTL_PCI_H__ + +#include +/* +1: MSDU packet queue, +2: Rx Command Queue +*/ +#define RTL_PCI_RX_MPDU_QUEUE 0 +#define RTL_PCI_RX_CMD_QUEUE 1 +#define RTL_PCI_MAX_RX_QUEUE 2 + +#define RTL_PCI_MAX_RX_COUNT 512/*64*/ +#define RTL_PCI_MAX_TX_QUEUE_COUNT 9 + +#define RT_TXDESC_NUM 128 +#define TX_DESC_NUM_92E 512 +#define RT_TXDESC_NUM_BE_QUEUE 256 + +#define BK_QUEUE 0 +#define BE_QUEUE 1 +#define VI_QUEUE 2 +#define VO_QUEUE 3 +#define BEACON_QUEUE 4 +#define TXCMD_QUEUE 5 +#define MGNT_QUEUE 6 +#define HIGH_QUEUE 7 +#define HCCA_QUEUE 8 + +#define RTL_PCI_DEVICE(vend, dev, cfg) \ + .vendor = (vend), \ + .device = (dev), \ + .subvendor = PCI_ANY_ID, \ + .subdevice = PCI_ANY_ID,\ + .driver_data = (kernel_ulong_t)&(cfg) + +#define INTEL_VENDOR_ID 0x8086 +#define SIS_VENDOR_ID 0x1039 +#define ATI_VENDOR_ID 0x1002 +#define ATI_DEVICE_ID 0x7914 +#define AMD_VENDOR_ID 0x1022 + +#define PCI_MAX_BRIDGE_NUMBER 255 +#define PCI_MAX_DEVICES 32 +#define PCI_MAX_FUNCTION 8 + +#define PCI_CONF_ADDRESS 0x0CF8 /*PCI Configuration Space Address */ +#define PCI_CONF_DATA 0x0CFC /*PCI Configuration Space Data */ + +#define PCI_CLASS_BRIDGE_DEV 0x06 +#define PCI_SUBCLASS_BR_PCI_TO_PCI 0x04 +#define PCI_CAPABILITY_ID_PCI_EXPRESS 0x10 +#define PCI_CAP_ID_EXP 0x10 + +#define U1DONTCARE 0xFF +#define U2DONTCARE 0xFFFF +#define U4DONTCARE 0xFFFFFFFF + +#define RTL_PCI_8192_DID 0x8192 /*8192 PCI-E */ +#define RTL_PCI_8192SE_DID 0x8192 /*8192 SE */ +#define RTL_PCI_8174_DID 0x8174 /*8192 SE */ +#define RTL_PCI_8173_DID 0x8173 /*8191 SE Crab */ +#define RTL_PCI_8172_DID 0x8172 /*8191 SE RE */ +#define RTL_PCI_8171_DID 0x8171 /*8191 SE Unicron */ +#define RTL_PCI_8723AE_DID 0x8723 /*8723AE */ +#define RTL_PCI_0045_DID 0x0045 /*8190 PCI for Ceraga */ +#define RTL_PCI_0046_DID 0x0046 /*8190 Cardbus for Ceraga */ +#define RTL_PCI_0044_DID 0x0044 /*8192e PCIE for Ceraga */ +#define RTL_PCI_0047_DID 0x0047 /*8192e Express Card for Ceraga */ +#define RTL_PCI_700F_DID 0x700F +#define RTL_PCI_701F_DID 0x701F +#define RTL_PCI_DLINK_DID 0x3304 +#define RTL_PCI_8723AE_DID 0x8723 /*8723e */ +#define RTL_PCI_8192CET_DID 0x8191 /*8192ce */ +#define RTL_PCI_8192CE_DID 0x8178 /*8192ce */ +#define RTL_PCI_8191CE_DID 0x8177 /*8192ce */ +#define RTL_PCI_8188CE_DID 0x8176 /*8192ce */ +#define RTL_PCI_8192CU_DID 0x8191 /*8192ce */ +#define RTL_PCI_8192DE_DID 0x8193 /*8192de */ +#define RTL_PCI_8192DE_DID2 0x002B /*92DE*/ +#define RTL_PCI_8188EE_DID 0x8179 /*8188ee*/ +#define RTL_PCI_8723BE_DID 0xB723 /*8723be*/ +#define RTL_PCI_8192EE_DID 0x818B /*8192ee*/ +#define RTL_PCI_8821AE_DID 0x8821 /*8821ae*/ +#define RTL_PCI_8812AE_DID 0x8812 /*8812ae*/ + +/*8192 support 16 pages of IO registers*/ +#define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000 +#define RTL_MEM_MAPPED_IO_RANGE_8192PCIE 0x4000 +#define RTL_MEM_MAPPED_IO_RANGE_8192SE 0x4000 +#define RTL_MEM_MAPPED_IO_RANGE_8192CE 0x4000 +#define RTL_MEM_MAPPED_IO_RANGE_8192DE 0x4000 + +#define RTL_PCI_REVISION_ID_8190PCI 0x00 +#define RTL_PCI_REVISION_ID_8192PCIE 0x01 +#define RTL_PCI_REVISION_ID_8192SE 0x10 +#define RTL_PCI_REVISION_ID_8192CE 0x1 +#define RTL_PCI_REVISION_ID_8192DE 0x0 + +#define RTL_DEFAULT_HARDWARE_TYPE HARDWARE_TYPE_RTL8192CE + +enum pci_bridge_vendor { + PCI_BRIDGE_VENDOR_INTEL = 0x0, /*0b'0000,0001 */ + PCI_BRIDGE_VENDOR_ATI, /*0b'0000,0010*/ + PCI_BRIDGE_VENDOR_AMD, /*0b'0000,0100*/ + PCI_BRIDGE_VENDOR_SIS, /*0b'0000,1000*/ + PCI_BRIDGE_VENDOR_UNKNOWN, /*0b'0100,0000*/ + PCI_BRIDGE_VENDOR_MAX, +}; + +struct rtl_pci_capabilities_header { + u8 capability_id; + u8 next; +}; + +/* In new TRX flow, Buffer_desc is new concept + * But TX wifi info == TX descriptor in old flow + * RX wifi info == RX descriptor in old flow + */ +struct rtl_tx_buffer_desc { +#if (RTL8192EE_SEG_NUM == 2) + u32 dword[2*(DMA_IS_64BIT + 1)*8]; /*seg = 8*/ +#elif (RTL8192EE_SEG_NUM == 1) + u32 dword[2*(DMA_IS_64BIT + 1)*4]; /*seg = 4*/ +#elif (RTL8192EE_SEG_NUM == 0) + u32 dword[2*(DMA_IS_64BIT + 1)*2]; /*seg = 2*/ +#endif +} __packed; + +struct rtl_tx_desc { + u32 dword[16]; +} __packed; + +struct rtl_rx_buffer_desc { /*rx buffer desc*/ + u32 dword[2]; +} __packed; + +struct rtl_rx_desc { /*old: rx desc new: rx wifi info*/ + u32 dword[8]; +} __packed; + +struct rtl_tx_cmd_desc { + u32 dword[16]; +} __packed; + +struct rtl8192_tx_ring { + struct rtl_tx_desc *desc; + dma_addr_t dma; + unsigned int idx; + unsigned int entries; + struct sk_buff_head queue; + /*add for new trx flow*/ + struct rtl_tx_buffer_desc *buffer_desc; /*tx buffer descriptor*/ + dma_addr_t buffer_desc_dma; /*tx bufferd desc dma memory*/ + u16 avl_desc; /* available_desc_to_write */ + u16 cur_tx_wp; /* current_tx_write_point */ + u16 cur_tx_rp; /* current_tx_read_point */ +}; + +struct rtl8192_rx_ring { + struct rtl_rx_desc *desc; + dma_addr_t dma; + unsigned int idx; + struct sk_buff *rx_buf[RTL_PCI_MAX_RX_COUNT]; + /*add for new trx flow*/ + struct rtl_rx_buffer_desc *buffer_desc; /*rx buffer descriptor*/ + u16 next_rx_rp; /* next_rx_read_point */ +}; + +struct rtl_pci { + struct pci_dev *pdev; + bool irq_enabled; + + bool driver_is_goingto_unload; + bool up_first_time; + bool first_init; + bool being_init_adapter; + bool init_ready; + + /*Tx */ + struct rtl8192_tx_ring tx_ring[RTL_PCI_MAX_TX_QUEUE_COUNT]; + int txringcount[RTL_PCI_MAX_TX_QUEUE_COUNT]; + u32 transmit_config; + + /*Rx */ + struct rtl8192_rx_ring rx_ring[RTL_PCI_MAX_RX_QUEUE]; + int rxringcount; + u16 rxbuffersize; + u32 receive_config; + + /*irq */ + u8 irq_alloc; + u32 irq_mask[2]; + u32 sys_irq_mask; + + /*Bcn control register setting */ + u32 reg_bcn_ctrl_val; + + /*ASPM*/ u8 const_pci_aspm; + u8 const_amdpci_aspm; + u8 const_hwsw_rfoff_d3; + u8 const_support_pciaspm; + /*pci-e bridge */ + u8 const_hostpci_aspm_setting; + /*pci-e device */ + u8 const_devicepci_aspm_setting; + /*If it supports ASPM, Offset[560h] = 0x40, + otherwise Offset[560h] = 0x00. */ + bool support_aspm; + bool support_backdoor; + + /*QOS & EDCA */ + enum acm_method acm_method; + + u16 shortretry_limit; + u16 longretry_limit; + + /* MSI support */ + bool msi_support; + bool using_msi; +}; + +struct mp_adapter { + u8 linkctrl_reg; + + u8 busnumber; + u8 devnumber; + u8 funcnumber; + + u8 pcibridge_busnum; + u8 pcibridge_devnum; + u8 pcibridge_funcnum; + + u8 pcibridge_vendor; + u16 pcibridge_vendorid; + u16 pcibridge_deviceid; + + u8 num4bytes; + + u8 pcibridge_pciehdr_offset; + u8 pcibridge_linkctrlreg; + + bool amd_l1_patch; +}; + +struct rtl_pci_priv { + struct rtl_pci dev; + struct mp_adapter ndis_adapter; + struct rtl_led_ctl ledctl; + struct bt_coexist_info bt_coexist; +}; + +#define rtl_pcipriv(hw) (((struct rtl_pci_priv *)(rtl_priv(hw))->priv)) +#define rtl_pcidev(pcipriv) (&((pcipriv)->dev)) + +int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw); + +extern struct rtl_intf_ops rtl_pci_ops; + +int rtl_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id); +void rtl_pci_disconnect(struct pci_dev *pdev); +#ifdef CONFIG_PM_SLEEP +int rtl_pci_suspend(struct device *dev); +int rtl_pci_resume(struct device *dev); +#endif /* CONFIG_PM_SLEEP */ +static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr) +{ + return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr); +} + +static inline u16 pci_read16_sync(struct rtl_priv *rtlpriv, u32 addr) +{ + return readw((u8 __iomem *) rtlpriv->io.pci_mem_start + addr); +} + +static inline u32 pci_read32_sync(struct rtl_priv *rtlpriv, u32 addr) +{ + return readl((u8 __iomem *) rtlpriv->io.pci_mem_start + addr); +} + +static inline void pci_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val) +{ + writeb(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr); +} + +static inline void pci_write16_async(struct rtl_priv *rtlpriv, + u32 addr, u16 val) +{ + writew(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr); +} + +static inline void pci_write32_async(struct rtl_priv *rtlpriv, + u32 addr, u32 val) +{ + writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr); +} + +static inline u16 calc_fifo_space(u16 rp, u16 wp) +{ + if (rp <= wp) + return RTL_PCI_MAX_RX_COUNT - 1 + rp - wp; + return rp - wp - 1; +} + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.c b/drivers/net/wireless/realtek/rtlwifi/ps.c new file mode 100644 index 000000000000..b69321d45f04 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/ps.c @@ -0,0 +1,1004 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "wifi.h" +#include "base.h" +#include "ps.h" +#include +#include "btcoexist/rtl_btc.h" + +bool rtl_ps_enable_nic(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + /*<1> reset trx ring */ + if (rtlhal->interface == INTF_PCI) + rtlpriv->intf_ops->reset_trx_ring(hw); + + if (is_hal_stop(rtlhal)) + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Driver is already down!\n"); + + /*<2> Enable Adapter */ + if (rtlpriv->cfg->ops->hw_init(hw)) + return false; + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + + /*<3> Enable Interrupt */ + rtlpriv->cfg->ops->enable_interrupt(hw); + + /* */ + rtl_watch_dog_timer_callback((unsigned long)hw); + + return true; +} +EXPORT_SYMBOL(rtl_ps_enable_nic); + +bool rtl_ps_disable_nic(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /*<1> Stop all timer */ + rtl_deinit_deferred_work(hw); + + /*<2> Disable Interrupt */ + rtlpriv->cfg->ops->disable_interrupt(hw); + tasklet_kill(&rtlpriv->works.irq_tasklet); + + /*<3> Disable Adapter */ + rtlpriv->cfg->ops->hw_disable(hw); + + return true; +} +EXPORT_SYMBOL(rtl_ps_disable_nic); + +bool rtl_ps_set_rf_state(struct ieee80211_hw *hw, + enum rf_pwrstate state_toset, + u32 changesource, bool protect_or_not) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + enum rf_pwrstate rtstate; + bool actionallowed = false; + u16 rfwait_cnt = 0; + + if (protect_or_not) + goto no_protect; + + /*Only one thread can change + *the RF state at one time, and others + *should wait to be executed. + */ + while (true) { + spin_lock(&rtlpriv->locks.rf_ps_lock); + if (ppsc->rfchange_inprogress) { + spin_unlock(&rtlpriv->locks.rf_ps_lock); + + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "RF Change in progress! Wait to set..state_toset(%d).\n", + state_toset); + + /* Set RF after the previous action is done. */ + while (ppsc->rfchange_inprogress) { + rfwait_cnt++; + mdelay(1); + /*Wait too long, return false to avoid + *to be stuck here. + */ + if (rfwait_cnt > 100) + return false; + } + } else { + ppsc->rfchange_inprogress = true; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + break; + } + } + +no_protect: + rtstate = ppsc->rfpwr_state; + + switch (state_toset) { + case ERFON: + ppsc->rfoff_reason &= (~changesource); + + if ((changesource == RF_CHANGE_BY_HW) && + (ppsc->hwradiooff)) { + ppsc->hwradiooff = false; + } + + if (!ppsc->rfoff_reason) { + ppsc->rfoff_reason = 0; + actionallowed = true; + } + + break; + + case ERFOFF: + + if ((changesource == RF_CHANGE_BY_HW) && !ppsc->hwradiooff) { + ppsc->hwradiooff = true; + } + + ppsc->rfoff_reason |= changesource; + actionallowed = true; + break; + + case ERFSLEEP: + ppsc->rfoff_reason |= changesource; + actionallowed = true; + break; + + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + + if (actionallowed) + rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset); + + if (!protect_or_not) { + spin_lock(&rtlpriv->locks.rf_ps_lock); + ppsc->rfchange_inprogress = false; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } + + return actionallowed; +} +EXPORT_SYMBOL(rtl_ps_set_rf_state); + +static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + ppsc->swrf_processing = true; + + if (ppsc->inactive_pwrstate == ERFON && + rtlhal->interface == INTF_PCI) { + if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && + rtlhal->interface == INTF_PCI) { + rtlpriv->intf_ops->disable_aspm(hw); + RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + } + } + + rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, + RF_CHANGE_BY_IPS, false); + + if (ppsc->inactive_pwrstate == ERFOFF && + rtlhal->interface == INTF_PCI) { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && + !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { + rtlpriv->intf_ops->enable_aspm(hw); + RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + } + } + + ppsc->swrf_processing = false; +} + +void rtl_ips_nic_off_wq_callback(void *data) +{ + struct rtl_works *rtlworks = + container_of_dwork_rtl(data, struct rtl_works, ips_nic_off_wq); + struct ieee80211_hw *hw = rtlworks->hw; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + enum rf_pwrstate rtstate; + + if (mac->opmode != NL80211_IFTYPE_STATION) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "not station return\n"); + return; + } + + if (mac->p2p_in_use) + return; + + if (mac->link_state > MAC80211_NOLINK) + return; + + if (is_hal_stop(rtlhal)) + return; + + if (rtlpriv->sec.being_setkey) + return; + + if (rtlpriv->cfg->ops->bt_coex_off_before_lps) + rtlpriv->cfg->ops->bt_coex_off_before_lps(hw); + + if (ppsc->inactiveps) { + rtstate = ppsc->rfpwr_state; + + /* + *Do not enter IPS in the following conditions: + *(1) RF is already OFF or Sleep + *(2) swrf_processing (indicates the IPS is still under going) + *(3) Connectted (only disconnected can trigger IPS) + *(4) IBSS (send Beacon) + *(5) AP mode (send Beacon) + *(6) monitor mode (rcv packet) + */ + + if (rtstate == ERFON && + !ppsc->swrf_processing && + (mac->link_state == MAC80211_NOLINK) && + !mac->act_scanning) { + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "IPSEnter(): Turn off RF\n"); + + ppsc->inactive_pwrstate = ERFOFF; + ppsc->in_powersavemode = true; + + /* call before RF off */ + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_ips_notify(rtlpriv, + ppsc->inactive_pwrstate); + + /*rtl_pci_reset_trx_ring(hw); */ + _rtl_ps_inactive_ps(hw); + } + } +} + +void rtl_ips_nic_off(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* because when link with ap, mac80211 will ask us + * to disable nic quickly after scan before linking, + * this will cause link failed, so we delay 100ms here + */ + queue_delayed_work(rtlpriv->works.rtl_wq, + &rtlpriv->works.ips_nic_off_wq, MSECS(100)); +} + +/* NOTICE: any opmode should exc nic_on, or disable without + * nic_on may something wrong, like adhoc TP + */ +void rtl_ips_nic_on(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + enum rf_pwrstate rtstate; + + cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); + + spin_lock(&rtlpriv->locks.ips_lock); + if (ppsc->inactiveps) { + rtstate = ppsc->rfpwr_state; + + if (rtstate != ERFON && + !ppsc->swrf_processing && + ppsc->rfoff_reason <= RF_CHANGE_BY_IPS) { + + ppsc->inactive_pwrstate = ERFON; + ppsc->in_powersavemode = false; + _rtl_ps_inactive_ps(hw); + /* call after RF on */ + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_ips_notify(rtlpriv, + ppsc->inactive_pwrstate); + } + } + spin_unlock(&rtlpriv->locks.ips_lock); +} +EXPORT_SYMBOL_GPL(rtl_ips_nic_on); + +/*for FW LPS*/ + +/* + *Determine if we can set Fw into PS mode + *in current condition.Return TRUE if it + *can enter PS mode. + */ +static bool rtl_get_fwlps_doze(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u32 ps_timediff; + + ps_timediff = jiffies_to_msecs(jiffies - + ppsc->last_delaylps_stamp_jiffies); + + if (ps_timediff < 2000) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Delay enter Fw LPS for DHCP, ARP, or EAPOL exchanging state\n"); + return false; + } + + if (mac->link_state != MAC80211_LINKED) + return false; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) + return false; + + return true; +} + +/* Change current and default preamble mode.*/ +void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool enter_fwlps; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) + return; + + if (mac->link_state != MAC80211_LINKED) + return; + + if (ppsc->dot11_psmode == rt_psmode) + return; + + /* Update power save mode configured. */ + ppsc->dot11_psmode = rt_psmode; + + /* + * + *1. Enter PS mode + * Set RPWM to Fw to turn RF off and send H2C fw_pwrmode + * cmd to set Fw into PS mode. + *2. Leave PS mode + * Send H2C fw_pwrmode cmd to Fw to set Fw into Active + * mode and set RPWM to turn RF on. + */ + + if ((ppsc->fwctrl_lps) && ppsc->report_linked) { + if (ppsc->dot11_psmode == EACTIVE) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "FW LPS leave ps_mode:%x\n", + FW_PS_ACTIVE_MODE); + enter_fwlps = false; + ppsc->pwr_mode = FW_PS_ACTIVE_MODE; + ppsc->smart_ps = 0; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_LPS_ACTION, + (u8 *)(&enter_fwlps)); + if (ppsc->p2p_ps_info.opp_ps) + rtl_p2p_ps_cmd(hw , P2P_PS_ENABLE); + + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_lps_notify(rtlpriv, rt_psmode); + } else { + if (rtl_get_fwlps_doze(hw)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "FW LPS enter ps_mode:%x\n", + ppsc->fwctrl_psmode); + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_lps_notify(rtlpriv, rt_psmode); + enter_fwlps = true; + ppsc->pwr_mode = ppsc->fwctrl_psmode; + ppsc->smart_ps = 2; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_FW_LPS_ACTION, + (u8 *)(&enter_fwlps)); + + } else { + /* Reset the power save related parameters. */ + ppsc->dot11_psmode = EACTIVE; + } + } + } +} + +/*Enter the leisure power save mode.*/ +void rtl_lps_enter(struct ieee80211_hw *hw) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + unsigned long flag; + + if (!ppsc->fwctrl_lps) + return; + + if (rtlpriv->sec.being_setkey) + return; + + if (rtlpriv->link_info.busytraffic) + return; + + /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */ + if (mac->cnt_after_linked < 5) + return; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) + return; + + if (mac->link_state != MAC80211_LINKED) + return; + + spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); + + /* Idle for a while if we connect to AP a while ago. */ + if (mac->cnt_after_linked >= 2) { + if (ppsc->dot11_psmode == EACTIVE) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Enter 802.11 power save mode...\n"); + + rtl_lps_set_psmode(hw, EAUTOPS); + } + } + + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); +} +EXPORT_SYMBOL(rtl_lps_enter); + +/*Leave the leisure power save mode.*/ +void rtl_lps_leave(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + unsigned long flag; + + spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); + + if (ppsc->fwctrl_lps) { + if (ppsc->dot11_psmode != EACTIVE) { + + /*FIX ME */ + /*rtlpriv->cfg->ops->enable_interrupt(hw); */ + + if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && + RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && + rtlhal->interface == INTF_PCI) { + rtlpriv->intf_ops->disable_aspm(hw); + RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + } + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Busy Traffic,Leave 802.11 power save..\n"); + + rtl_lps_set_psmode(hw, EACTIVE); + } + } + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); +} +EXPORT_SYMBOL(rtl_lps_leave); + +/* For sw LPS*/ +void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct ieee80211_hdr *hdr = data; + struct ieee80211_tim_ie *tim_ie; + u8 *tim; + u8 tim_len; + bool u_buffed; + bool m_buffed; + + if (mac->opmode != NL80211_IFTYPE_STATION) + return; + + if (!rtlpriv->psc.swctrl_lps) + return; + + if (rtlpriv->mac80211.link_state != MAC80211_LINKED) + return; + + if (!rtlpriv->psc.sw_ps_enabled) + return; + + if (rtlpriv->psc.fwctrl_lps) + return; + + if (likely(!(hw->conf.flags & IEEE80211_CONF_PS))) + return; + + /* check if this really is a beacon */ + if (!ieee80211_is_beacon(hdr->frame_control)) + return; + + /* min. beacon length + FCS_LEN */ + if (len <= 40 + FCS_LEN) + return; + + /* and only beacons from the associated BSSID, please */ + if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid)) + return; + + rtlpriv->psc.last_beacon = jiffies; + + tim = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_TIM); + if (!tim) + return; + + if (tim[1] < sizeof(*tim_ie)) + return; + + tim_len = tim[1]; + tim_ie = (struct ieee80211_tim_ie *) &tim[2]; + + if (!WARN_ON_ONCE(!hw->conf.ps_dtim_period)) + rtlpriv->psc.dtim_counter = tim_ie->dtim_count; + + /* Check whenever the PHY can be turned off again. */ + + /* 1. What about buffered unicast traffic for our AID? */ + u_buffed = ieee80211_check_tim(tim_ie, tim_len, + rtlpriv->mac80211.assoc_id); + + /* 2. Maybe the AP wants to send multicast/broadcast data? */ + m_buffed = tim_ie->bitmap_ctrl & 0x01; + rtlpriv->psc.multi_buffered = m_buffed; + + /* unicast will process by mac80211 through + * set ~IEEE80211_CONF_PS, So we just check + * multicast frames here */ + if (!m_buffed) { + /* back to low-power land. and delay is + * prevent null power save frame tx fail */ + queue_delayed_work(rtlpriv->works.rtl_wq, + &rtlpriv->works.ps_work, MSECS(5)); + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "u_bufferd: %x, m_buffered: %x\n", u_buffed, m_buffed); + } +} +EXPORT_SYMBOL_GPL(rtl_swlps_beacon); + +void rtl_swlps_rf_awake(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + unsigned long flag; + + if (!rtlpriv->psc.swctrl_lps) + return; + if (mac->link_state != MAC80211_LINKED) + return; + + if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && + RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { + rtlpriv->intf_ops->disable_aspm(hw); + RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + } + + spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); + rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false); + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); +} + +void rtl_swlps_rfon_wq_callback(void *data) +{ + struct rtl_works *rtlworks = + container_of_dwork_rtl(data, struct rtl_works, ps_rfon_wq); + struct ieee80211_hw *hw = rtlworks->hw; + + rtl_swlps_rf_awake(hw); +} + +void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + unsigned long flag; + u8 sleep_intv; + + if (!rtlpriv->psc.sw_ps_enabled) + return; + + if ((rtlpriv->sec.being_setkey) || + (mac->opmode == NL80211_IFTYPE_ADHOC)) + return; + + /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */ + if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5)) + return; + + if (rtlpriv->link_info.busytraffic) + return; + + spin_lock(&rtlpriv->locks.rf_ps_lock); + if (rtlpriv->psc.rfchange_inprogress) { + spin_unlock(&rtlpriv->locks.rf_ps_lock); + return; + } + spin_unlock(&rtlpriv->locks.rf_ps_lock); + + spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); + rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS , false); + spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && + !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { + rtlpriv->intf_ops->enable_aspm(hw); + RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); + } + + /* here is power save alg, when this beacon is DTIM + * we will set sleep time to dtim_period * n; + * when this beacon is not DTIM, we will set sleep + * time to sleep_intv = rtlpriv->psc.dtim_counter or + * MAX_SW_LPS_SLEEP_INTV(default set to 5) */ + + if (rtlpriv->psc.dtim_counter == 0) { + if (hw->conf.ps_dtim_period == 1) + sleep_intv = hw->conf.ps_dtim_period * 2; + else + sleep_intv = hw->conf.ps_dtim_period; + } else { + sleep_intv = rtlpriv->psc.dtim_counter; + } + + if (sleep_intv > MAX_SW_LPS_SLEEP_INTV) + sleep_intv = MAX_SW_LPS_SLEEP_INTV; + + /* this print should always be dtim_conter = 0 & + * sleep = dtim_period, that meaons, we should + * awake before every dtim */ + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "dtim_counter:%x will sleep :%d beacon_intv\n", + rtlpriv->psc.dtim_counter, sleep_intv); + + /* we tested that 40ms is enough for sw & hw sw delay */ + queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq, + MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40)); +} + +void rtl_lps_change_work_callback(struct work_struct *work) +{ + struct rtl_works *rtlworks = + container_of(work, struct rtl_works, lps_change_work); + struct ieee80211_hw *hw = rtlworks->hw; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->enter_ps) + rtl_lps_enter(hw); + else + rtl_lps_leave(hw); +} +EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback); + +void rtl_swlps_wq_callback(void *data) +{ + struct rtl_works *rtlworks = container_of_dwork_rtl(data, + struct rtl_works, + ps_work); + struct ieee80211_hw *hw = rtlworks->hw; + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool ps = false; + + ps = (hw->conf.flags & IEEE80211_CONF_PS); + + /* we can sleep after ps null send ok */ + if (rtlpriv->psc.state_inap) { + rtl_swlps_rf_sleep(hw); + + if (rtlpriv->psc.state && !ps) { + rtlpriv->psc.sleep_ms = jiffies_to_msecs(jiffies - + rtlpriv->psc.last_action); + } + + if (ps) + rtlpriv->psc.last_slept = jiffies; + + rtlpriv->psc.last_action = jiffies; + rtlpriv->psc.state = ps; + } +} + +static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data, + unsigned int len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_mgmt *mgmt = data; + struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); + u8 *pos, *end, *ie; + u16 noa_len; + static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; + u8 noa_num, index , i, noa_index = 0; + bool find_p2p_ie = false , find_p2p_ps_ie = false; + pos = (u8 *)mgmt->u.beacon.variable; + end = data + len; + ie = NULL; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + return; + + if (pos[0] == 221 && pos[1] > 4) { + if (memcmp(&pos[2], p2p_oui_ie_type, 4) == 0) { + ie = pos + 2+4; + break; + } + } + pos += 2 + pos[1]; + } + + if (ie == NULL) + return; + find_p2p_ie = true; + /*to find noa ie*/ + while (ie + 1 < end) { + noa_len = READEF2BYTE((__le16 *)&ie[1]); + if (ie + 3 + ie[1] > end) + return; + + if (ie[0] == 12) { + find_p2p_ps_ie = true; + if ((noa_len - 2) % 13 != 0) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "P2P notice of absence: invalid length.%d\n", + noa_len); + return; + } else { + noa_num = (noa_len - 2) / 13; + } + noa_index = ie[3]; + if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == + P2P_PS_NONE || noa_index != p2pinfo->noa_index) { + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "update NOA ie.\n"); + p2pinfo->noa_index = noa_index; + p2pinfo->opp_ps = (ie[4] >> 7); + p2pinfo->ctwindow = ie[4] & 0x7F; + p2pinfo->noa_num = noa_num; + index = 5; + for (i = 0; i < noa_num; i++) { + p2pinfo->noa_count_type[i] = + READEF1BYTE(ie+index); + index += 1; + p2pinfo->noa_duration[i] = + READEF4BYTE((__le32 *)ie+index); + index += 4; + p2pinfo->noa_interval[i] = + READEF4BYTE((__le32 *)ie+index); + index += 4; + p2pinfo->noa_start_time[i] = + READEF4BYTE((__le32 *)ie+index); + index += 4; + } + + if (p2pinfo->opp_ps == 1) { + p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW; + /* Driver should wait LPS entering + * CTWindow + */ + if (rtlpriv->psc.fw_current_inpsmode) + rtl_p2p_ps_cmd(hw, + P2P_PS_ENABLE); + } else if (p2pinfo->noa_num > 0) { + p2pinfo->p2p_ps_mode = P2P_PS_NOA; + rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); + } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { + rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); + } + } + break; + } + ie += 3 + noa_len; + } + + if (find_p2p_ie == true) { + if ((p2pinfo->p2p_ps_mode > P2P_PS_NONE) && + (find_p2p_ps_ie == false)) + rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); + } +} + +static void rtl_p2p_action_ie(struct ieee80211_hw *hw, void *data, + unsigned int len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_mgmt *mgmt = data; + struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); + u8 noa_num, index , i , noa_index = 0; + u8 *pos, *end, *ie; + u16 noa_len; + static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; + + pos = (u8 *)&mgmt->u.action.category; + end = data + len; + ie = NULL; + + if (pos[0] == 0x7f) { + if (memcmp(&pos[1], p2p_oui_ie_type, 4) == 0) + ie = pos + 3+4; + } + + if (ie == NULL) + return; + + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "action frame find P2P IE.\n"); + /*to find noa ie*/ + while (ie + 1 < end) { + noa_len = READEF2BYTE((__le16 *)&ie[1]); + if (ie + 3 + ie[1] > end) + return; + + if (ie[0] == 12) { + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "find NOA IE.\n"); + RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_LOUD, "noa ie ", + ie, noa_len); + if ((noa_len - 2) % 13 != 0) { + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "P2P notice of absence: invalid length.%d\n", + noa_len); + return; + } else { + noa_num = (noa_len - 2) / 13; + } + noa_index = ie[3]; + if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == + P2P_PS_NONE || noa_index != p2pinfo->noa_index) { + p2pinfo->noa_index = noa_index; + p2pinfo->opp_ps = (ie[4] >> 7); + p2pinfo->ctwindow = ie[4] & 0x7F; + p2pinfo->noa_num = noa_num; + index = 5; + for (i = 0; i < noa_num; i++) { + p2pinfo->noa_count_type[i] = + READEF1BYTE(ie+index); + index += 1; + p2pinfo->noa_duration[i] = + READEF4BYTE((__le32 *)ie+index); + index += 4; + p2pinfo->noa_interval[i] = + READEF4BYTE((__le32 *)ie+index); + index += 4; + p2pinfo->noa_start_time[i] = + READEF4BYTE((__le32 *)ie+index); + index += 4; + } + + if (p2pinfo->opp_ps == 1) { + p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW; + /* Driver should wait LPS entering + * CTWindow + */ + if (rtlpriv->psc.fw_current_inpsmode) + rtl_p2p_ps_cmd(hw, + P2P_PS_ENABLE); + } else if (p2pinfo->noa_num > 0) { + p2pinfo->p2p_ps_mode = P2P_PS_NOA; + rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); + } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { + rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); + } + } + break; + } + ie += 3 + noa_len; + } +} + +void rtl_p2p_ps_cmd(struct ieee80211_hw *hw , u8 p2p_ps_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); + struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); + + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, " p2p state %x\n" , p2p_ps_state); + switch (p2p_ps_state) { + case P2P_PS_DISABLE: + p2pinfo->p2p_ps_state = p2p_ps_state; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, + &p2p_ps_state); + p2pinfo->noa_index = 0; + p2pinfo->ctwindow = 0; + p2pinfo->opp_ps = 0; + p2pinfo->noa_num = 0; + p2pinfo->p2p_ps_mode = P2P_PS_NONE; + if (rtlps->fw_current_inpsmode) { + if (rtlps->smart_ps == 0) { + rtlps->smart_ps = 2; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_PWRMODE, + &rtlps->pwr_mode); + } + + } + break; + case P2P_PS_ENABLE: + if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { + p2pinfo->p2p_ps_state = p2p_ps_state; + + if (p2pinfo->ctwindow > 0) { + if (rtlps->smart_ps != 0) { + rtlps->smart_ps = 0; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_PWRMODE, + &rtlps->pwr_mode); + } + } + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_P2P_PS_OFFLOAD, + &p2p_ps_state); + + } + break; + case P2P_PS_SCAN: + case P2P_PS_SCAN_DONE: + case P2P_PS_ALLSTASLEEP: + if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { + p2pinfo->p2p_ps_state = p2p_ps_state; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_P2P_PS_OFFLOAD, + &p2p_ps_state); + } + break; + default: + break; + } + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "ctwindow %x oppps %x\n", + p2pinfo->ctwindow , p2pinfo->opp_ps); + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "count %x duration %x index %x interval %x start time %x noa num %x\n", + p2pinfo->noa_count_type[0], + p2pinfo->noa_duration[0], + p2pinfo->noa_index, + p2pinfo->noa_interval[0], + p2pinfo->noa_start_time[0], + p2pinfo->noa_num); + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "end\n"); +} + +void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct ieee80211_hdr *hdr = data; + + if (!mac->p2p) + return; + if (mac->link_state != MAC80211_LINKED) + return; + /* min. beacon length + FCS_LEN */ + if (len <= 40 + FCS_LEN) + return; + + /* and only beacons from the associated BSSID, please */ + if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid)) + return; + + /* check if this really is a beacon */ + if (!(ieee80211_is_beacon(hdr->frame_control) || + ieee80211_is_probe_resp(hdr->frame_control) || + ieee80211_is_action(hdr->frame_control))) + return; + + if (ieee80211_is_action(hdr->frame_control)) + rtl_p2p_action_ie(hw , data , len - FCS_LEN); + else + rtl_p2p_noa_ie(hw , data , len - FCS_LEN); +} +EXPORT_SYMBOL_GPL(rtl_p2p_info); diff --git a/drivers/net/wireless/realtek/rtlwifi/ps.h b/drivers/net/wireless/realtek/rtlwifi/ps.h new file mode 100644 index 000000000000..29dfc514212d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/ps.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __REALTEK_RTL_PCI_PS_H__ +#define __REALTEK_RTL_PCI_PS_H__ + +#define MAX_SW_LPS_SLEEP_INTV 5 + +bool rtl_ps_set_rf_state(struct ieee80211_hw *hw, + enum rf_pwrstate state_toset, u32 changesource, + bool protect_or_not); +bool rtl_ps_enable_nic(struct ieee80211_hw *hw); +bool rtl_ps_disable_nic(struct ieee80211_hw *hw); +void rtl_ips_nic_off(struct ieee80211_hw *hw); +void rtl_ips_nic_on(struct ieee80211_hw *hw); +void rtl_ips_nic_off_wq_callback(void *data); +void rtl_lps_enter(struct ieee80211_hw *hw); +void rtl_lps_leave(struct ieee80211_hw *hw); + +void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode); + +void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len); +void rtl_swlps_wq_callback(void *data); +void rtl_swlps_rfon_wq_callback(void *data); +void rtl_swlps_rf_awake(struct ieee80211_hw *hw); +void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); +void rtl_p2p_ps_cmd(struct ieee80211_hw *hw , u8 p2p_ps_state); +void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len); +void rtl_lps_change_work_callback(struct work_struct *work); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h b/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h new file mode 100644 index 000000000000..17ce0cb2c35c --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/pwrseqcmd.h @@ -0,0 +1,94 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_PWRSEQCMD_H__ +#define __RTL8723E_PWRSEQCMD_H__ + +#include "wifi.h" +/*--------------------------------------------- + * 3 The value of cmd: 4 bits + *--------------------------------------------- + */ +#define PWR_CMD_READ 0x00 +#define PWR_CMD_WRITE 0x01 +#define PWR_CMD_POLLING 0x02 +#define PWR_CMD_DELAY 0x03 +#define PWR_CMD_END 0x04 + +/* define the base address of each block */ +#define PWR_BASEADDR_MAC 0x00 +#define PWR_BASEADDR_USB 0x01 +#define PWR_BASEADDR_PCIE 0x02 +#define PWR_BASEADDR_SDIO 0x03 + +#define PWR_INTF_SDIO_MSK BIT(0) +#define PWR_INTF_USB_MSK BIT(1) +#define PWR_INTF_PCI_MSK BIT(2) +#define PWR_INTF_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) + +#define PWR_FAB_TSMC_MSK BIT(0) +#define PWR_FAB_UMC_MSK BIT(1) +#define PWR_FAB_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) + +#define PWR_CUT_TESTCHIP_MSK BIT(0) +#define PWR_CUT_A_MSK BIT(1) +#define PWR_CUT_B_MSK BIT(2) +#define PWR_CUT_C_MSK BIT(3) +#define PWR_CUT_D_MSK BIT(4) +#define PWR_CUT_E_MSK BIT(5) +#define PWR_CUT_F_MSK BIT(6) +#define PWR_CUT_G_MSK BIT(7) +#define PWR_CUT_ALL_MSK 0xFF + +enum pwrseq_delay_unit { + PWRSEQ_DELAY_US, + PWRSEQ_DELAY_MS, +}; + +struct wlan_pwr_cfg { + u16 offset; + u8 cut_msk; + u8 fab_msk:4; + u8 interface_msk:4; + u8 base:4; + u8 cmd:4; + u8 msk; + u8 value; +}; + +#define GET_PWR_CFG_OFFSET(__PWR_CMD) (__PWR_CMD.offset) +#define GET_PWR_CFG_CUT_MASK(__PWR_CMD) (__PWR_CMD.cut_msk) +#define GET_PWR_CFG_FAB_MASK(__PWR_CMD) (__PWR_CMD.fab_msk) +#define GET_PWR_CFG_INTF_MASK(__PWR_CMD) (__PWR_CMD.interface_msk) +#define GET_PWR_CFG_BASE(__PWR_CMD) (__PWR_CMD.base) +#define GET_PWR_CFG_CMD(__PWR_CMD) (__PWR_CMD.cmd) +#define GET_PWR_CFG_MASK(__PWR_CMD) (__PWR_CMD.msk) +#define GET_PWR_CFG_VALUE(__PWR_CMD) (__PWR_CMD.value) + +bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version, + u8 fab_version, u8 interface_type, + struct wlan_pwr_cfg pwrcfgcmd[]); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rc.c b/drivers/net/wireless/realtek/rtlwifi/rc.c new file mode 100644 index 000000000000..74c14ce28238 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rc.c @@ -0,0 +1,302 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "wifi.h" +#include "base.h" +#include "rc.h" + +/* + *Finds the highest rate index we can use + *if skb is special data like DHCP/EAPOL, we set should + *it to lowest rate CCK_1M, otherwise we set rate to + *highest rate based on wireless mode used for iwconfig + *show Tx rate. + */ +static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, + struct ieee80211_sta *sta, + struct sk_buff *skb, bool not_data) +{ + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_sta_info *sta_entry = NULL; + u8 wireless_mode = 0; + + /* + *this rate is no use for true rate, firmware + *will control rate at all it just used for + *1.show in iwconfig in B/G mode + *2.in rtl_get_tcb_desc when we check rate is + * 1M we will not use FW rate but user rate. + */ + + if (sta) { + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + wireless_mode = sta_entry->wireless_mode; + } + + if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true, false) || + not_data) { + return 0; + } else { + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + if (wireless_mode == WIRELESS_MODE_B) { + return B_MODE_MAX_RIX; + } else if (wireless_mode == WIRELESS_MODE_G) { + return G_MODE_MAX_RIX; + } else if (wireless_mode == WIRELESS_MODE_N_24G) { + if (get_rf_type(rtlphy) != RF_2T2R) + return N_MODE_MCS7_RIX; + else + return N_MODE_MCS15_RIX; + } else if (wireless_mode == WIRELESS_MODE_AC_24G) { + return AC_MODE_MCS9_RIX; + } + return 0; + } else { + if (wireless_mode == WIRELESS_MODE_A) { + return A_MODE_MAX_RIX; + } else if (wireless_mode == WIRELESS_MODE_N_5G) { + if (get_rf_type(rtlphy) != RF_2T2R) + return N_MODE_MCS7_RIX; + else + return N_MODE_MCS15_RIX; + } else if (wireless_mode == WIRELESS_MODE_AC_5G) { + return AC_MODE_MCS9_RIX; + } + return 0; + } + } +} + +static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, + struct ieee80211_sta *sta, + struct ieee80211_tx_rate *rate, + struct ieee80211_tx_rate_control *txrc, + u8 tries, char rix, int rtsctsenable, + bool not_data) +{ + struct rtl_mac *mac = rtl_mac(rtlpriv); + struct rtl_sta_info *sta_entry = NULL; + u8 wireless_mode = 0; + u8 sgi_20 = 0, sgi_40 = 0, sgi_80 = 0; + + if (sta) { + sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; + sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; + sgi_80 = sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80; + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + wireless_mode = sta_entry->wireless_mode; + } + rate->count = tries; + rate->idx = rix >= 0x00 ? rix : 0x00; + if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE && + wireless_mode == WIRELESS_MODE_AC_5G) + rate->idx += 0x10;/*2NSS for 8812AE*/ + + if (!not_data) { + if (txrc->short_preamble) + rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta && (sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40)) + rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + if (sta && (sta->vht_cap.vht_supported)) + rate->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; + } else { + if (mac->bw_40) + rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; + if (mac->bw_80) + rate->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; + } + + if (sgi_20 || sgi_40 || sgi_80) + rate->flags |= IEEE80211_TX_RC_SHORT_GI; + if (sta && sta->ht_cap.ht_supported && + ((wireless_mode == WIRELESS_MODE_N_5G) || + (wireless_mode == WIRELESS_MODE_N_24G))) + rate->flags |= IEEE80211_TX_RC_MCS; + } +} + +static void rtl_get_rate(void *ppriv, struct ieee80211_sta *sta, + void *priv_sta, + struct ieee80211_tx_rate_control *txrc) +{ + struct rtl_priv *rtlpriv = ppriv; + struct sk_buff *skb = txrc->skb; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_rate *rates = tx_info->control.rates; + __le16 fc = rtl_get_fc(skb); + u8 try_per_rate, i, rix; + bool not_data = !ieee80211_is_data(fc); + + if (rate_control_send_low(sta, priv_sta, txrc)) + return; + + rix = _rtl_rc_get_highest_rix(rtlpriv, sta, skb, not_data); + try_per_rate = 1; + _rtl_rc_rate_set_series(rtlpriv, sta, &rates[0], txrc, + try_per_rate, rix, 1, not_data); + + if (!not_data) { + for (i = 1; i < 4; i++) + _rtl_rc_rate_set_series(rtlpriv, sta, &rates[i], + txrc, i, (rix - i), 1, + not_data); + } +} + +static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, + struct rtl_sta_info *sta_entry, u16 tid) +{ + struct rtl_mac *mac = rtl_mac(rtlpriv); + + if (mac->act_scanning) + return false; + + if (mac->opmode == NL80211_IFTYPE_STATION && + mac->cnt_after_linked < 3) + return false; + + if (sta_entry->tids[tid].agg.agg_state == RTL_AGG_STOP) + return true; + + return false; +} + +/*mac80211 Rate Control callbacks*/ +static void rtl_tx_status(void *ppriv, + struct ieee80211_supported_band *sband, + struct ieee80211_sta *sta, void *priv_sta, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = ppriv; + struct rtl_mac *mac = rtl_mac(rtlpriv); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); + __le16 fc = rtl_get_fc(skb); + struct rtl_sta_info *sta_entry; + + if (!priv_sta || !ieee80211_is_data(fc)) + return; + + if (rtl_is_special_data(mac->hw, skb, true, true)) + return; + + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) + return; + + if (sta) { + /* Check if aggregation has to be enabled for this tid */ + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + if ((sta->ht_cap.ht_supported) && + !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { + if (ieee80211_is_data_qos(fc)) { + u8 tid = rtl_get_tid(skb); + if (_rtl_tx_aggr_check(rtlpriv, sta_entry, + tid)) { + sta_entry->tids[tid].agg.agg_state = + RTL_AGG_PROGRESS; + ieee80211_start_tx_ba_session(sta, tid, + 5000); + } + } + } + } +} + +static void rtl_rate_init(void *ppriv, + struct ieee80211_supported_band *sband, + struct cfg80211_chan_def *chandef, + struct ieee80211_sta *sta, void *priv_sta) +{ +} + +static void rtl_rate_update(void *ppriv, + struct ieee80211_supported_band *sband, + struct cfg80211_chan_def *chandef, + struct ieee80211_sta *sta, void *priv_sta, + u32 changed) +{ +} + +static void *rtl_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + return rtlpriv; +} + +static void rtl_rate_free(void *rtlpriv) +{ + return; +} + +static void *rtl_rate_alloc_sta(void *ppriv, + struct ieee80211_sta *sta, gfp_t gfp) +{ + struct rtl_priv *rtlpriv = ppriv; + struct rtl_rate_priv *rate_priv; + + rate_priv = kzalloc(sizeof(struct rtl_rate_priv), gfp); + if (!rate_priv) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Unable to allocate private rc structure\n"); + return NULL; + } + + rtlpriv->rate_priv = rate_priv; + + return rate_priv; +} + +static void rtl_rate_free_sta(void *rtlpriv, + struct ieee80211_sta *sta, void *priv_sta) +{ + struct rtl_rate_priv *rate_priv = priv_sta; + kfree(rate_priv); +} + +static struct rate_control_ops rtl_rate_ops = { + .name = "rtl_rc", + .alloc = rtl_rate_alloc, + .free = rtl_rate_free, + .alloc_sta = rtl_rate_alloc_sta, + .free_sta = rtl_rate_free_sta, + .rate_init = rtl_rate_init, + .rate_update = rtl_rate_update, + .tx_status = rtl_tx_status, + .get_rate = rtl_get_rate, +}; + +int rtl_rate_control_register(void) +{ + return ieee80211_rate_control_register(&rtl_rate_ops); +} + +void rtl_rate_control_unregister(void) +{ + ieee80211_rate_control_unregister(&rtl_rate_ops); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rc.h b/drivers/net/wireless/realtek/rtlwifi/rc.h new file mode 100644 index 000000000000..f29643d60d6b --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rc.h @@ -0,0 +1,48 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL_RC_H__ +#define __RTL_RC_H__ + +#define B_MODE_MAX_RIX 3 +#define G_MODE_MAX_RIX 11 +#define A_MODE_MAX_RIX 7 + +/* in mac80211 mcs0-mcs15 is idx0-idx15*/ +#define N_MODE_MCS7_RIX 7 +#define N_MODE_MCS15_RIX 15 + +#define AC_MODE_MCS7_RIX 7 +#define AC_MODE_MCS8_RIX 8 +#define AC_MODE_MCS9_RIX 9 + +struct rtl_rate_priv { + u8 ht_cap; +}; + +int rtl_rate_control_register(void); +void rtl_rate_control_unregister(void); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c new file mode 100644 index 000000000000..a62bf0a65c32 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c @@ -0,0 +1,473 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "wifi.h" +#include "regd.h" + +static struct country_code_to_enum_rd allCountries[] = { + {COUNTRY_CODE_FCC, "US"}, + {COUNTRY_CODE_IC, "US"}, + {COUNTRY_CODE_ETSI, "EC"}, + {COUNTRY_CODE_SPAIN, "EC"}, + {COUNTRY_CODE_FRANCE, "EC"}, + {COUNTRY_CODE_MKK, "JP"}, + {COUNTRY_CODE_MKK1, "JP"}, + {COUNTRY_CODE_ISRAEL, "EC"}, + {COUNTRY_CODE_TELEC, "JP"}, + {COUNTRY_CODE_MIC, "JP"}, + {COUNTRY_CODE_GLOBAL_DOMAIN, "JP"}, + {COUNTRY_CODE_WORLD_WIDE_13, "EC"}, + {COUNTRY_CODE_TELEC_NETGEAR, "EC"}, + {COUNTRY_CODE_WORLD_WIDE_13_5G_ALL, "US"}, +}; + +/* + *Only these channels all allow active + *scan on all world regulatory domains + */ +#define RTL819x_2GHZ_CH01_11 \ + REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) + +/* + *We enable active scan on these a case + *by case basis by regulatory domain + */ +#define RTL819x_2GHZ_CH12_13 \ + REG_RULE(2467-10, 2472+10, 40, 0, 20,\ + NL80211_RRF_PASSIVE_SCAN) + +#define RTL819x_2GHZ_CH14 \ + REG_RULE(2484-10, 2484+10, 40, 0, 20, \ + NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_NO_OFDM) + + +/* 5G chan 36 - chan 64*/ +#define RTL819x_5GHZ_5150_5350 \ + REG_RULE(5150-10, 5350+10, 80, 0, 30, 0) +/* 5G chan 100 - chan 165*/ +#define RTL819x_5GHZ_5470_5850 \ + REG_RULE(5470-10, 5850+10, 80, 0, 30, 0) +/* 5G chan 149 - chan 165*/ +#define RTL819x_5GHZ_5725_5850 \ + REG_RULE(5725-10, 5850+10, 80, 0, 30, 0) + +#define RTL819x_5GHZ_ALL \ + (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850) + +static const struct ieee80211_regdomain rtl_regdom_11 = { + .n_reg_rules = 1, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_12_13 = { + .n_reg_rules = 2, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_no_midband = { + .n_reg_rules = 3, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_5GHZ_5150_5350, + RTL819x_5GHZ_5725_5850, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_60_64 = { + .n_reg_rules = 3, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + RTL819x_5GHZ_5725_5850, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_14_60_64 = { + .n_reg_rules = 4, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + RTL819x_2GHZ_CH14, + RTL819x_5GHZ_5725_5850, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_12_13_5g_all = { + .n_reg_rules = 4, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + RTL819x_5GHZ_5150_5350, + RTL819x_5GHZ_5470_5850, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_14 = { + .n_reg_rules = 3, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + RTL819x_2GHZ_CH14, + } +}; + +static bool _rtl_is_radar_freq(u16 center_freq) +{ + return center_freq >= 5260 && center_freq <= 5700; +} + +static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator) +{ + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + const struct ieee80211_reg_rule *reg_rule; + struct ieee80211_channel *ch; + unsigned int i; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + + if (!wiphy->bands[band]) + continue; + + sband = wiphy->bands[band]; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + if (_rtl_is_radar_freq(ch->center_freq) || + (ch->flags & IEEE80211_CHAN_RADAR)) + continue; + if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { + reg_rule = freq_reg_info(wiphy, + ch->center_freq); + if (IS_ERR(reg_rule)) + continue; + /* + *If 11d had a rule for this channel ensure + *we enable adhoc/beaconing if it allows us to + *use it. Note that we would have disabled it + *by applying our static world regdomain by + *default during init, prior to calling our + *regulatory_hint(). + */ + + if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) + ch->flags &= ~IEEE80211_CHAN_NO_IBSS; + if (!(reg_rule->flags & + NL80211_RRF_PASSIVE_SCAN)) + ch->flags &= + ~IEEE80211_CHAN_PASSIVE_SCAN; + } else { + if (ch->beacon_found) + ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_PASSIVE_SCAN); + } + } + } +} + +/* Allows active scan scan on Ch 12 and 13 */ +static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator + initiator) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + const struct ieee80211_reg_rule *reg_rule; + + if (!wiphy->bands[IEEE80211_BAND_2GHZ]) + return; + sband = wiphy->bands[IEEE80211_BAND_2GHZ]; + + /* + *If no country IE has been received always enable active scan + *on these channels. This is only done for specific regulatory SKUs + */ + if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { + ch = &sband->channels[11]; /* CH 12 */ + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + ch = &sband->channels[12]; /* CH 13 */ + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + return; + } + + /* + *If a country IE has been recieved check its rule for this + *channel first before enabling active scan. The passive scan + *would have been enforced by the initial processing of our + *custom regulatory domain. + */ + + ch = &sband->channels[11]; /* CH 12 */ + reg_rule = freq_reg_info(wiphy, ch->center_freq); + if (!IS_ERR(reg_rule)) { + if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + } + + ch = &sband->channels[12]; /* CH 13 */ + reg_rule = freq_reg_info(wiphy, ch->center_freq); + if (!IS_ERR(reg_rule)) { + if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) + ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; + } +} + +/* + *Always apply Radar/DFS rules on + *freq range 5260 MHz - 5700 MHz + */ +static void _rtl_reg_apply_radar_flags(struct wiphy *wiphy) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + unsigned int i; + + if (!wiphy->bands[IEEE80211_BAND_5GHZ]) + return; + + sband = wiphy->bands[IEEE80211_BAND_5GHZ]; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + if (!_rtl_is_radar_freq(ch->center_freq)) + continue; + + /* + *We always enable radar detection/DFS on this + *frequency range. Additionally we also apply on + *this frequency range: + *- If STA mode does not yet have DFS supports disable + * active scanning + *- If adhoc mode does not support DFS yet then disable + * adhoc in the frequency. + *- If AP mode does not yet support radar detection/DFS + *do not allow AP mode + */ + if (!(ch->flags & IEEE80211_CHAN_DISABLED)) + ch->flags |= IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_PASSIVE_SCAN; + } +} + +static void _rtl_reg_apply_world_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator, + struct rtl_regulatory *reg) +{ + _rtl_reg_apply_beaconing_flags(wiphy, initiator); + _rtl_reg_apply_active_scan_flags(wiphy, initiator); + return; +} + +static void _rtl_dump_channel_map(struct wiphy *wiphy) +{ + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + unsigned int i; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!wiphy->bands[band]) + continue; + sband = wiphy->bands[band]; + for (i = 0; i < sband->n_channels; i++) + ch = &sband->channels[i]; + } +} + +static int _rtl_reg_notifier_apply(struct wiphy *wiphy, + struct regulatory_request *request, + struct rtl_regulatory *reg) +{ + /* We always apply this */ + _rtl_reg_apply_radar_flags(wiphy); + + switch (request->initiator) { + case NL80211_REGDOM_SET_BY_DRIVER: + case NL80211_REGDOM_SET_BY_CORE: + case NL80211_REGDOM_SET_BY_USER: + break; + case NL80211_REGDOM_SET_BY_COUNTRY_IE: + _rtl_reg_apply_world_flags(wiphy, request->initiator, reg); + break; + } + + _rtl_dump_channel_map(wiphy); + + return 0; +} + +static const struct ieee80211_regdomain *_rtl_regdomain_select( + struct rtl_regulatory *reg) +{ + switch (reg->country_code) { + case COUNTRY_CODE_FCC: + return &rtl_regdom_no_midband; + case COUNTRY_CODE_IC: + return &rtl_regdom_11; + case COUNTRY_CODE_ETSI: + case COUNTRY_CODE_TELEC_NETGEAR: + return &rtl_regdom_60_64; + case COUNTRY_CODE_SPAIN: + case COUNTRY_CODE_FRANCE: + case COUNTRY_CODE_ISRAEL: + case COUNTRY_CODE_WORLD_WIDE_13: + return &rtl_regdom_12_13; + case COUNTRY_CODE_MKK: + case COUNTRY_CODE_MKK1: + case COUNTRY_CODE_TELEC: + case COUNTRY_CODE_MIC: + return &rtl_regdom_14_60_64; + case COUNTRY_CODE_GLOBAL_DOMAIN: + return &rtl_regdom_14; + case COUNTRY_CODE_WORLD_WIDE_13_5G_ALL: + return &rtl_regdom_12_13_5g_all; + default: + return &rtl_regdom_no_midband; + } +} + +static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg, + struct wiphy *wiphy, + void (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request * + request)) +{ + const struct ieee80211_regdomain *regd; + + wiphy->reg_notifier = reg_notifier; + + wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; + wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG; + wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS; + regd = _rtl_regdomain_select(reg); + wiphy_apply_custom_regulatory(wiphy, regd); + _rtl_reg_apply_radar_flags(wiphy); + _rtl_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); + return 0; +} + +static struct country_code_to_enum_rd *_rtl_regd_find_country(u16 countrycode) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(allCountries); i++) { + if (allCountries[i].countrycode == countrycode) + return &allCountries[i]; + } + return NULL; +} + +static u8 channel_plan_to_country_code(u8 channelplan) +{ + switch (channelplan) { + case 0x20: + case 0x21: + return COUNTRY_CODE_WORLD_WIDE_13; + case 0x22: + return COUNTRY_CODE_IC; + case 0x32: + return COUNTRY_CODE_TELEC_NETGEAR; + case 0x41: + return COUNTRY_CODE_GLOBAL_DOMAIN; + case 0x7f: + return COUNTRY_CODE_WORLD_WIDE_13_5G_ALL; + default: + return COUNTRY_CODE_MAX; /*Error*/ + } +} + +int rtl_regd_init(struct ieee80211_hw *hw, + void (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct wiphy *wiphy = hw->wiphy; + struct country_code_to_enum_rd *country = NULL; + + if (wiphy == NULL || &rtlpriv->regd == NULL) + return -EINVAL; + + /* init country_code from efuse channel plan */ + rtlpriv->regd.country_code = + channel_plan_to_country_code(rtlpriv->efuse.channel_plan); + + RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG, + "rtl: EEPROM regdomain: 0x%0x conuntry code: %d\n", + rtlpriv->efuse.channel_plan, rtlpriv->regd.country_code); + + if (rtlpriv->regd.country_code >= COUNTRY_CODE_MAX) { + RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG, + "rtl: EEPROM indicates invalid contry code, world wide 13 should be used\n"); + + rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13; + } + + country = _rtl_regd_find_country(rtlpriv->regd.country_code); + + if (country) { + rtlpriv->regd.alpha2[0] = country->iso_name[0]; + rtlpriv->regd.alpha2[1] = country->iso_name[1]; + } else { + rtlpriv->regd.alpha2[0] = '0'; + rtlpriv->regd.alpha2[1] = '0'; + } + + RT_TRACE(rtlpriv, COMP_REGD, DBG_TRACE, + "rtl: Country alpha2 being used: %c%c\n", + rtlpriv->regd.alpha2[0], rtlpriv->regd.alpha2[1]); + + _rtl_regd_init_wiphy(&rtlpriv->regd, wiphy, reg_notifier); + + return 0; +} + +void rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) +{ + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_REGD, DBG_LOUD, "\n"); + + _rtl_reg_notifier_apply(wiphy, request, &rtlpriv->regd); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.h b/drivers/net/wireless/realtek/rtlwifi/regd.h new file mode 100644 index 000000000000..f7f15bce35dd --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/regd.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL_REGD_H__ +#define __RTL_REGD_H__ + +/* for kernel 3.14 , both value are changed to IEEE80211_CHAN_NO_IR*/ +#define IEEE80211_CHAN_NO_IBSS IEEE80211_CHAN_NO_IR +#define IEEE80211_CHAN_PASSIVE_SCAN IEEE80211_CHAN_NO_IR + +struct country_code_to_enum_rd { + u16 countrycode; + const char *iso_name; +}; + +enum country_code_type_t { + COUNTRY_CODE_FCC = 0, + COUNTRY_CODE_IC = 1, + COUNTRY_CODE_ETSI = 2, + COUNTRY_CODE_SPAIN = 3, + COUNTRY_CODE_FRANCE = 4, + COUNTRY_CODE_MKK = 5, + COUNTRY_CODE_MKK1 = 6, + COUNTRY_CODE_ISRAEL = 7, + COUNTRY_CODE_TELEC = 8, + COUNTRY_CODE_MIC = 9, + COUNTRY_CODE_GLOBAL_DOMAIN = 10, + COUNTRY_CODE_WORLD_WIDE_13 = 11, + COUNTRY_CODE_TELEC_NETGEAR = 12, + COUNTRY_CODE_WORLD_WIDE_13_5G_ALL = 13, + + /*add new channel plan above this line */ + COUNTRY_CODE_MAX +}; + +int rtl_regd_init(struct ieee80211_hw *hw, + void (*reg_notifier) (struct wiphy *wiphy, + struct regulatory_request *request)); +void rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/Makefile new file mode 100644 index 000000000000..a85419a37651 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/Makefile @@ -0,0 +1,15 @@ +rtl8188ee-objs := \ + dm.o \ + fw.o \ + hw.o \ + led.o \ + phy.o \ + pwrseq.o \ + rf.o \ + sw.o \ + table.o \ + trx.o + +obj-$(CONFIG_RTL8188EE) += rtl8188ee.o + +ccflags-y += -Idrivers/net/wireless/rtlwifi -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h new file mode 100644 index 000000000000..0532b9852444 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/def.h @@ -0,0 +1,269 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_DEF_H__ +#define __RTL92C_DEF_H__ + +#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 +#define HAL_PRIME_CHNL_OFFSET_LOWER 1 +#define HAL_PRIME_CHNL_OFFSET_UPPER 2 + +#define RX_MPDU_QUEUE 0 +#define RX_CMD_QUEUE 1 + +#define C2H_RX_CMD_HDR_LEN 8 +#define GET_C2H_CMD_CMD_LEN(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 0, 16) +#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 16, 8) +#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 24, 7) +#define GET_C2H_CMD_CONTINUE(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 31, 1) +#define GET_C2H_CMD_CONTENT(__prxhdr) \ + ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) + +#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) +#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) +#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) + +#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) + +/* [15:12] IC version(CUT): A-cut=0, B-cut=1, C-cut=2, D-cut=3 + * [7] Manufacturer: TSMC=0, UMC=1 + * [6:4] RF type: 1T1R=0, 1T2R=1, 2T2R=2 + * [3] Chip type: TEST=0, NORMAL=1 + * [2:0] IC type: 81xxC=0, 8723=1, 92D=2 + */ +#define CHIP_8723 BIT(0) +#define CHIP_92D BIT(1) +#define NORMAL_CHIP BIT(3) +#define RF_TYPE_1T1R (~(BIT(4)|BIT(5)|BIT(6))) +#define RF_TYPE_1T2R BIT(4) +#define RF_TYPE_2T2R BIT(5) +#define CHIP_VENDOR_UMC BIT(7) +#define B_CUT_VERSION BIT(12) +#define C_CUT_VERSION BIT(13) +#define D_CUT_VERSION ((BIT(12)|BIT(13))) +#define E_CUT_VERSION BIT(14) + +/* MASK */ +#define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2)) +#define CHIP_TYPE_MASK BIT(3) +#define RF_TYPE_MASK (BIT(4)|BIT(5)|BIT(6)) +#define MANUFACTUER_MASK BIT(7) +#define ROM_VERSION_MASK (BIT(11)|BIT(10)|BIT(9)|BIT(8)) +#define CUT_VERSION_MASK (BIT(15)|BIT(14)|BIT(13)|BIT(12)) + +/* Get element */ +#define GET_CVID_IC_TYPE(version) ((version) & IC_TYPE_MASK) +#define GET_CVID_CHIP_TYPE(version) ((version) & CHIP_TYPE_MASK) +#define GET_CVID_RF_TYPE(version) ((version) & RF_TYPE_MASK) +#define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK) +#define GET_CVID_ROM_VERSION(version) ((version) & ROM_VERSION_MASK) +#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK) + +#define IS_81XXC(version) \ + ((GET_CVID_IC_TYPE(version) == 0) ? true : false) +#define IS_8723_SERIES(version) \ + ((GET_CVID_IC_TYPE(version) == CHIP_8723) ? true : false) +#define IS_92D(version) \ + ((GET_CVID_IC_TYPE(version) == CHIP_92D) ? true : false) + +#define IS_NORMAL_CHIP(version) \ + ((GET_CVID_CHIP_TYPE(version)) ? true : false) +#define IS_NORMAL_CHIP92D(version) \ + ((GET_CVID_CHIP_TYPE(version)) ? true : false) + +#define IS_1T1R(version) \ + ((GET_CVID_RF_TYPE(version)) ? false : true) +#define IS_1T2R(version) \ + ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R) ? true : false) +#define IS_2T2R(version) \ + ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R) ? true : false) +#define IS_CHIP_VENDOR_UMC(version) \ + ((GET_CVID_MANUFACTUER(version)) ? true : false) + +#define IS_92C_SERIAL(version) \ + ((IS_81XXC(version) && IS_2T2R(version)) ? true : false) +#define IS_81xxC_VENDOR_UMC_A_CUT(version) \ + (IS_81XXC(version) ? ((IS_CHIP_VENDOR_UMC(version)) ? \ + ((GET_CVID_CUT_VERSION(version)) ? false : true) : false) : false) +#define IS_81XXC_VENDOR_UMC_B_CUT(version) \ + (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \ + ((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true \ + : false) : false) : false) + +enum version_8188e { + VERSION_TEST_CHIP_88E = 0x00, + VERSION_NORMAL_CHIP_88E = 0x01, + VERSION_UNKNOWN = 0xFF, +}; + +enum rx_packet_type { + NORMAL_RX, + TX_REPORT1, + TX_REPORT2, + HIS_REPORT, +}; + +enum rtl819x_loopback_e { + RTL819X_NO_LOOPBACK = 0, + RTL819X_MAC_LOOPBACK = 1, + RTL819X_DMA_LOOPBACK = 2, + RTL819X_CCK_LOOPBACK = 3, +}; + +enum rf_optype { + RF_OP_BY_SW_3WIRE = 0, + RF_OP_BY_FW, + RF_OP_MAX +}; + +enum rf_power_state { + RF_ON, + RF_OFF, + RF_SLEEP, + RF_SHUT_DOWN, +}; + +enum power_save_mode { + POWER_SAVE_MODE_ACTIVE, + POWER_SAVE_MODE_SAVE, +}; + +enum power_polocy_config { + POWERCFG_MAX_POWER_SAVINGS, + POWERCFG_GLOBAL_POWER_SAVINGS, + POWERCFG_LOCAL_POWER_SAVINGS, + POWERCFG_LENOVO, +}; + +enum interface_select_pci { + INTF_SEL1_MINICARD = 0, + INTF_SEL0_PCIE = 1, + INTF_SEL2_RSV = 2, + INTF_SEL3_RSV = 3, +}; + +enum hal_fw_c2h_cmd_id { + HAL_FW_C2H_CMD_READ_MACREG = 0, + HAL_FW_C2H_CMD_READ_BBREG = 1, + HAL_FW_C2H_CMD_READ_RFREG = 2, + HAL_FW_C2H_CMD_READ_EEPROM = 3, + HAL_FW_C2H_CMD_READ_EFUSE = 4, + HAL_FW_C2H_CMD_READ_CAM = 5, + HAL_FW_C2H_CMD_GET_BASICRATE = 6, + HAL_FW_C2H_CMD_GET_DATARATE = 7, + HAL_FW_C2H_CMD_SURVEY = 8, + HAL_FW_C2H_CMD_SURVEYDONE = 9, + HAL_FW_C2H_CMD_JOINBSS = 10, + HAL_FW_C2H_CMD_ADDSTA = 11, + HAL_FW_C2H_CMD_DELSTA = 12, + HAL_FW_C2H_CMD_ATIMDONE = 13, + HAL_FW_C2H_CMD_TX_REPORT = 14, + HAL_FW_C2H_CMD_CCX_REPORT = 15, + HAL_FW_C2H_CMD_DTM_REPORT = 16, + HAL_FW_C2H_CMD_TX_RATE_STATISTICS = 17, + HAL_FW_C2H_CMD_C2HLBK = 18, + HAL_FW_C2H_CMD_C2HDBG = 19, + HAL_FW_C2H_CMD_C2HFEEDBACK = 20, + HAL_FW_C2H_CMD_MAX +}; + +enum rtl_desc_qsel { + QSLT_BK = 0x2, + QSLT_BE = 0x0, + QSLT_VI = 0x5, + QSLT_VO = 0x7, + QSLT_BEACON = 0x10, + QSLT_HIGH = 0x11, + QSLT_MGNT = 0x12, + QSLT_CMD = 0x13, +}; + +enum rtl_desc92c_rate { + DESC92C_RATE1M = 0x00, + DESC92C_RATE2M = 0x01, + DESC92C_RATE5_5M = 0x02, + DESC92C_RATE11M = 0x03, + + DESC92C_RATE6M = 0x04, + DESC92C_RATE9M = 0x05, + DESC92C_RATE12M = 0x06, + DESC92C_RATE18M = 0x07, + DESC92C_RATE24M = 0x08, + DESC92C_RATE36M = 0x09, + DESC92C_RATE48M = 0x0a, + DESC92C_RATE54M = 0x0b, + + DESC92C_RATEMCS0 = 0x0c, + DESC92C_RATEMCS1 = 0x0d, + DESC92C_RATEMCS2 = 0x0e, + DESC92C_RATEMCS3 = 0x0f, + DESC92C_RATEMCS4 = 0x10, + DESC92C_RATEMCS5 = 0x11, + DESC92C_RATEMCS6 = 0x12, + DESC92C_RATEMCS7 = 0x13, + DESC92C_RATEMCS8 = 0x14, + DESC92C_RATEMCS9 = 0x15, + DESC92C_RATEMCS10 = 0x16, + DESC92C_RATEMCS11 = 0x17, + DESC92C_RATEMCS12 = 0x18, + DESC92C_RATEMCS13 = 0x19, + DESC92C_RATEMCS14 = 0x1a, + DESC92C_RATEMCS15 = 0x1b, + DESC92C_RATEMCS15_SG = 0x1c, + DESC92C_RATEMCS32 = 0x20, +}; + +struct phy_sts_cck_8192s_t { + u8 adc_pwdb_X[4]; + u8 sq_rpt; + u8 cck_agc_rpt; +}; + +struct h2c_cmd_8192c { + u8 element_id; + u32 cmd_len; + u8 *p_cmdbuffer; +}; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c new file mode 100644 index 000000000000..ce4da9d79fbd --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c @@ -0,0 +1,1805 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../base.h" +#include "../pci.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "trx.h" + +static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { + 0x7f8001fe, /* 0, +6.0dB */ + 0x788001e2, /* 1, +5.5dB */ + 0x71c001c7, /* 2, +5.0dB */ + 0x6b8001ae, /* 3, +4.5dB */ + 0x65400195, /* 4, +4.0dB */ + 0x5fc0017f, /* 5, +3.5dB */ + 0x5a400169, /* 6, +3.0dB */ + 0x55400155, /* 7, +2.5dB */ + 0x50800142, /* 8, +2.0dB */ + 0x4c000130, /* 9, +1.5dB */ + 0x47c0011f, /* 10, +1.0dB */ + 0x43c0010f, /* 11, +0.5dB */ + 0x40000100, /* 12, +0dB */ + 0x3c8000f2, /* 13, -0.5dB */ + 0x390000e4, /* 14, -1.0dB */ + 0x35c000d7, /* 15, -1.5dB */ + 0x32c000cb, /* 16, -2.0dB */ + 0x300000c0, /* 17, -2.5dB */ + 0x2d4000b5, /* 18, -3.0dB */ + 0x2ac000ab, /* 19, -3.5dB */ + 0x288000a2, /* 20, -4.0dB */ + 0x26000098, /* 21, -4.5dB */ + 0x24000090, /* 22, -5.0dB */ + 0x22000088, /* 23, -5.5dB */ + 0x20000080, /* 24, -6.0dB */ + 0x1e400079, /* 25, -6.5dB */ + 0x1c800072, /* 26, -7.0dB */ + 0x1b00006c, /* 27. -7.5dB */ + 0x19800066, /* 28, -8.0dB */ + 0x18000060, /* 29, -8.5dB */ + 0x16c0005b, /* 30, -9.0dB */ + 0x15800056, /* 31, -9.5dB */ + 0x14400051, /* 32, -10.0dB */ + 0x1300004c, /* 33, -10.5dB */ + 0x12000048, /* 34, -11.0dB */ + 0x11000044, /* 35, -11.5dB */ + 0x10000040, /* 36, -12.0dB */ + 0x0f00003c, /* 37, -12.5dB */ + 0x0e400039, /* 38, -13.0dB */ + 0x0d800036, /* 39, -13.5dB */ + 0x0cc00033, /* 40, -14.0dB */ + 0x0c000030, /* 41, -14.5dB */ + 0x0b40002d, /* 42, -15.0dB */ +}; + +static const u8 cck_tbl_ch1_13[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ + {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ + {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ + {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ + {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ + {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ + {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ + {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ + {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ + {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ + {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB*/ + {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB*/ + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB*/ + {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB*/ + {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB*/ + {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB*/ + {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB*/ + {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB*/ + {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB*/ + {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB*/ + {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB*/ + {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB*/ + {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB*/ +}; + +static const u8 cck_tbl_ch14[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */ + {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */ + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */ + {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */ + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */ + {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */ + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */ + {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */ + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */ + {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */ + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */ + {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */ + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */ + {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */ + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */ + {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */ + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ + {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */ + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */ + {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */ + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB*/ + {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB*/ + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB*/ + {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB*/ + {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB*/ + {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB*/ + {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB*/ + {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB*/ + {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB*/ + {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB*/ + {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB*/ + {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB*/ + {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB*/ +}; + +#define CAL_SWING_OFF(_off, _dir, _size, _del) \ + do { \ + for (_off = 0; _off < _size; _off++) { \ + if (_del < thermal_threshold[_dir][_off]) { \ + if (_off != 0) \ + _off--; \ + break; \ + } \ + } \ + if (_off >= _size) \ + _off = _size - 1; \ + } while (0) + +static void rtl88e_set_iqk_matrix(struct ieee80211_hw *hw, + u8 ofdm_index, u8 rfpath, + long iqk_result_x, long iqk_result_y) +{ + long ele_a = 0, ele_d, ele_c = 0, value32; + + ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000)>>22; + + if (iqk_result_x != 0) { + if ((iqk_result_x & 0x00000200) != 0) + iqk_result_x = iqk_result_x | 0xFFFFFC00; + ele_a = ((iqk_result_x * ele_d)>>8)&0x000003FF; + + if ((iqk_result_y & 0x00000200) != 0) + iqk_result_y = iqk_result_y | 0xFFFFFC00; + ele_c = ((iqk_result_y * ele_d)>>8)&0x000003FF; + + switch (rfpath) { + case RF90_PATH_A: + value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a; + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD, value32); + value32 = (ele_c & 0x000003C0) >> 6; + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, + value32); + value32 = ((iqk_result_x * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), + value32); + break; + case RF90_PATH_B: + value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a; + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD, + value32); + value32 = (ele_c & 0x000003C0) >> 6; + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, value32); + value32 = ((iqk_result_x * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28), + value32); + break; + default: + break; + } + } else { + switch (rfpath) { + case RF90_PATH_A: + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD, ofdmswing_table[ofdm_index]); + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, + MASKH4BITS, 0x00); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(24), 0x00); + break; + case RF90_PATH_B: + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, + MASKDWORD, ofdmswing_table[ofdm_index]); + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, + MASKH4BITS, 0x00); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(28), 0x00); + break; + default: + break; + } + } +} + +void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw, + u8 type, u8 *pdirection, u32 *poutwrite_val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + u8 pwr_val = 0; + u8 cck_base = rtldm->swing_idx_cck_base; + u8 cck_val = rtldm->swing_idx_cck; + u8 ofdm_base = rtldm->swing_idx_ofdm_base[0]; + u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A]; + + if (type == 0) { + if (ofdm_val <= ofdm_base) { + *pdirection = 1; + pwr_val = ofdm_base - ofdm_val; + } else { + *pdirection = 2; + pwr_val = ofdm_base - ofdm_val; + } + } else if (type == 1) { + if (cck_val <= cck_base) { + *pdirection = 1; + pwr_val = cck_base - cck_val; + } else { + *pdirection = 2; + pwr_val = cck_val - cck_base; + } + } + + if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1)) + pwr_val = TXPWRTRACK_MAX_IDX; + + *poutwrite_val = pwr_val | (pwr_val << 8) | (pwr_val << 16) | + (pwr_val << 24); +} + +static void dm_tx_pwr_track_set_pwr(struct ieee80211_hw *hw, + enum pwr_track_control_method method, + u8 rfpath, u8 channel_mapped_index) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + + if (method == TXAGC) { + if (rtldm->swing_flag_ofdm || + rtldm->swing_flag_cck) { + rtl88e_phy_set_txpower_level(hw, + rtlphy->current_channel); + rtldm->swing_flag_ofdm = false; + rtldm->swing_flag_cck = false; + } + } else if (method == BBSWING) { + if (!rtldm->cck_inch14) { + rtl_write_byte(rtlpriv, 0xa22, + cck_tbl_ch1_13[rtldm->swing_idx_cck][0]); + rtl_write_byte(rtlpriv, 0xa23, + cck_tbl_ch1_13[rtldm->swing_idx_cck][1]); + rtl_write_byte(rtlpriv, 0xa24, + cck_tbl_ch1_13[rtldm->swing_idx_cck][2]); + rtl_write_byte(rtlpriv, 0xa25, + cck_tbl_ch1_13[rtldm->swing_idx_cck][3]); + rtl_write_byte(rtlpriv, 0xa26, + cck_tbl_ch1_13[rtldm->swing_idx_cck][4]); + rtl_write_byte(rtlpriv, 0xa27, + cck_tbl_ch1_13[rtldm->swing_idx_cck][5]); + rtl_write_byte(rtlpriv, 0xa28, + cck_tbl_ch1_13[rtldm->swing_idx_cck][6]); + rtl_write_byte(rtlpriv, 0xa29, + cck_tbl_ch1_13[rtldm->swing_idx_cck][7]); + } else { + rtl_write_byte(rtlpriv, 0xa22, + cck_tbl_ch14[rtldm->swing_idx_cck][0]); + rtl_write_byte(rtlpriv, 0xa23, + cck_tbl_ch14[rtldm->swing_idx_cck][1]); + rtl_write_byte(rtlpriv, 0xa24, + cck_tbl_ch14[rtldm->swing_idx_cck][2]); + rtl_write_byte(rtlpriv, 0xa25, + cck_tbl_ch14[rtldm->swing_idx_cck][3]); + rtl_write_byte(rtlpriv, 0xa26, + cck_tbl_ch14[rtldm->swing_idx_cck][4]); + rtl_write_byte(rtlpriv, 0xa27, + cck_tbl_ch14[rtldm->swing_idx_cck][5]); + rtl_write_byte(rtlpriv, 0xa28, + cck_tbl_ch14[rtldm->swing_idx_cck][6]); + rtl_write_byte(rtlpriv, 0xa29, + cck_tbl_ch14[rtldm->swing_idx_cck][7]); + } + + if (rfpath == RF90_PATH_A) { + rtl88e_set_iqk_matrix(hw, rtldm->swing_idx_ofdm[rfpath], + rfpath, rtlphy->iqk_matrix + [channel_mapped_index]. + value[0][0], + rtlphy->iqk_matrix + [channel_mapped_index]. + value[0][1]); + } else if (rfpath == RF90_PATH_B) { + rtl88e_set_iqk_matrix(hw, rtldm->swing_idx_ofdm[rfpath], + rfpath, rtlphy->iqk_matrix + [channel_mapped_index]. + value[0][4], + rtlphy->iqk_matrix + [channel_mapped_index]. + value[0][5]); + } + } else { + return; + } +} + +static u8 rtl88e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_dig = &rtlpriv->dm_digtable; + long rssi_val_min = 0; + + if ((dm_dig->curmultista_cstate == DIG_MULTISTA_CONNECT) && + (dm_dig->cur_sta_cstate == DIG_STA_CONNECT)) { + if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0) + rssi_val_min = + (rtlpriv->dm.entry_min_undec_sm_pwdb > + rtlpriv->dm.undec_sm_pwdb) ? + rtlpriv->dm.undec_sm_pwdb : + rtlpriv->dm.entry_min_undec_sm_pwdb; + else + rssi_val_min = rtlpriv->dm.undec_sm_pwdb; + } else if (dm_dig->cur_sta_cstate == DIG_STA_CONNECT || + dm_dig->cur_sta_cstate == DIG_STA_BEFORE_CONNECT) { + rssi_val_min = rtlpriv->dm.undec_sm_pwdb; + } else if (dm_dig->curmultista_cstate == + DIG_MULTISTA_CONNECT) { + rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb; + } + + return (u8)rssi_val_min; +} + +static void rtl88e_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) +{ + u32 ret_value; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt; + + rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1); + rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1); + + ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD); + falsealm_cnt->cnt_fast_fsync_fail = (ret_value&0xffff); + falsealm_cnt->cnt_sb_search_fail = ((ret_value&0xffff0000)>>16); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); + falsealm_cnt->cnt_ofdm_cca = (ret_value&0xffff); + falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); + falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); + falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); + falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); + falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_fast_fsync_fail + + falsealm_cnt->cnt_sb_search_fail; + + ret_value = rtl_get_bbreg(hw, REG_SC_CNT, MASKDWORD); + falsealm_cnt->cnt_bw_lsc = (ret_value & 0xffff); + falsealm_cnt->cnt_bw_usc = ((ret_value & 0xffff0000) >> 16); + + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(12), 1); + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1); + + ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); + falsealm_cnt->cnt_cck_fail = ret_value; + + ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3); + falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; + + ret_value = rtl_get_bbreg(hw, RCCK0_CCA_CNT, MASKDWORD); + falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) | + ((ret_value&0xFF00)>>8); + + falsealm_cnt->cnt_all = (falsealm_cnt->cnt_fast_fsync_fail + + falsealm_cnt->cnt_sb_search_fail + + falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_cck_fail); + falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca + + falsealm_cnt->cnt_cck_cca; + + rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 1); + rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 0); + rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 1); + rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 0); + rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0); + rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0); + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 0); + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 2); + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 0); + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 2); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", + falsealm_cnt->cnt_parity_fail, + falsealm_cnt->cnt_rate_illegal, + falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", + falsealm_cnt->cnt_ofdm_fail, + falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all); +} + +static void rtl88e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_dig = &rtlpriv->dm_digtable; + u8 cur_cck_cca_thresh; + + if (dm_dig->cur_sta_cstate == DIG_STA_CONNECT) { + dm_dig->rssi_val_min = rtl88e_dm_initial_gain_min_pwdb(hw); + if (dm_dig->rssi_val_min > 25) { + cur_cck_cca_thresh = 0xcd; + } else if ((dm_dig->rssi_val_min <= 25) && + (dm_dig->rssi_val_min > 10)) { + cur_cck_cca_thresh = 0x83; + } else { + if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) + cur_cck_cca_thresh = 0x83; + else + cur_cck_cca_thresh = 0x40; + } + + } else { + if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) + cur_cck_cca_thresh = 0x83; + else + cur_cck_cca_thresh = 0x40; + } + + if (dm_dig->cur_cck_cca_thres != cur_cck_cca_thresh) + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh); + + dm_dig->cur_cck_cca_thres = cur_cck_cca_thresh; + dm_dig->pre_cck_cca_thres = dm_dig->cur_cck_cca_thres; + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "CCK cca thresh hold =%x\n", dm_dig->cur_cck_cca_thres); +} + +static void rtl88e_dm_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct dig_t *dm_dig = &rtlpriv->dm_digtable; + u8 dig_dynamic_min, dig_maxofmin; + bool bfirstconnect; + u8 dm_dig_max, dm_dig_min; + u8 current_igi = dm_dig->cur_igvalue; + + if (rtlpriv->dm.dm_initialgain_enable == false) + return; + if (dm_dig->dig_enable_flag == false) + return; + if (mac->act_scanning == true) + return; + + if (mac->link_state >= MAC80211_LINKED) + dm_dig->cur_sta_cstate = DIG_STA_CONNECT; + else + dm_dig->cur_sta_cstate = DIG_STA_DISCONNECT; + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || + rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) + dm_dig->cur_sta_cstate = DIG_STA_DISCONNECT; + + dm_dig_max = DM_DIG_MAX; + dm_dig_min = DM_DIG_MIN; + dig_maxofmin = DM_DIG_MAX_AP; + dig_dynamic_min = dm_dig->dig_min_0; + bfirstconnect = ((mac->link_state >= MAC80211_LINKED) ? true : false) && + !dm_dig->media_connect_0; + + dm_dig->rssi_val_min = + rtl88e_dm_initial_gain_min_pwdb(hw); + + if (mac->link_state >= MAC80211_LINKED) { + if ((dm_dig->rssi_val_min + 20) > dm_dig_max) + dm_dig->rx_gain_max = dm_dig_max; + else if ((dm_dig->rssi_val_min + 20) < dm_dig_min) + dm_dig->rx_gain_max = dm_dig_min; + else + dm_dig->rx_gain_max = dm_dig->rssi_val_min + 20; + + if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) { + dig_dynamic_min = dm_dig->antdiv_rssi_max; + } else { + if (dm_dig->rssi_val_min < dm_dig_min) + dig_dynamic_min = dm_dig_min; + else if (dm_dig->rssi_val_min < dig_maxofmin) + dig_dynamic_min = dig_maxofmin; + else + dig_dynamic_min = dm_dig->rssi_val_min; + } + } else { + dm_dig->rx_gain_max = dm_dig_max; + dig_dynamic_min = dm_dig_min; + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n"); + } + + if (rtlpriv->falsealm_cnt.cnt_all > 10000) { + dm_dig->large_fa_hit++; + if (dm_dig->forbidden_igi < current_igi) { + dm_dig->forbidden_igi = current_igi; + dm_dig->large_fa_hit = 1; + } + + if (dm_dig->large_fa_hit >= 3) { + if ((dm_dig->forbidden_igi + 1) > + dm_dig->rx_gain_max) + dm_dig->rx_gain_min = + dm_dig->rx_gain_max; + else + dm_dig->rx_gain_min = + dm_dig->forbidden_igi + 1; + dm_dig->recover_cnt = 3600; + } + } else { + if (dm_dig->recover_cnt != 0) { + dm_dig->recover_cnt--; + } else { + if (dm_dig->large_fa_hit == 0) { + if ((dm_dig->forbidden_igi - 1) < + dig_dynamic_min) { + dm_dig->forbidden_igi = dig_dynamic_min; + dm_dig->rx_gain_min = dig_dynamic_min; + } else { + dm_dig->forbidden_igi--; + dm_dig->rx_gain_min = + dm_dig->forbidden_igi + 1; + } + } else if (dm_dig->large_fa_hit == 3) { + dm_dig->large_fa_hit = 0; + } + } + } + + if (dm_dig->cur_sta_cstate == DIG_STA_CONNECT) { + if (bfirstconnect) { + current_igi = dm_dig->rssi_val_min; + } else { + if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2) + current_igi += 2; + else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1) + current_igi++; + else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) + current_igi--; + } + } else { + if (rtlpriv->falsealm_cnt.cnt_all > 10000) + current_igi += 2; + else if (rtlpriv->falsealm_cnt.cnt_all > 8000) + current_igi++; + else if (rtlpriv->falsealm_cnt.cnt_all < 500) + current_igi--; + } + + if (current_igi > DM_DIG_FA_UPPER) + current_igi = DM_DIG_FA_UPPER; + else if (current_igi < DM_DIG_FA_LOWER) + current_igi = DM_DIG_FA_LOWER; + + if (rtlpriv->falsealm_cnt.cnt_all > 10000) + current_igi = DM_DIG_FA_UPPER; + + dm_dig->cur_igvalue = current_igi; + rtl88e_dm_write_dig(hw); + dm_dig->media_connect_0 = + ((mac->link_state >= MAC80211_LINKED) ? true : false); + dm_dig->dig_min_0 = dig_dynamic_min; + + rtl88e_dm_cck_packet_detection_thresh(hw); +} + +static void rtl88e_dm_init_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.dynamic_txpower_enable = false; + + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; +} + +static void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undec_sm_pwdb; + + if (!rtlpriv->dm.dynamic_txpower_enable) + return; + + if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "Not connected to any\n"); + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + undec_sm_pwdb = + rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Client PWDB = 0x%lx\n", + undec_sm_pwdb); + } else { + undec_sm_pwdb = + rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "STA Default Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + } else { + undec_sm_pwdb = + rtlpriv->dm.entry_min_undec_sm_pwdb; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Ext Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + + if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x0)\n"); + } else if ((undec_sm_pwdb < + (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && + (undec_sm_pwdb >= + TX_POWER_NEAR_FIELD_THRESH_LVL1)) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x10)\n"); + } else if (undec_sm_pwdb < + (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_NORMAL\n"); + } + + if ((rtlpriv->dm.dynamic_txhighpower_lvl != + rtlpriv->dm.last_dtp_lvl)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "PHY_SetTxPowerLevel8192S() Channel = %d\n", + rtlphy->current_channel); + rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel); + } + + rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; +} + +void rtl88e_dm_write_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_dig = &rtlpriv->dm_digtable; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "cur_igvalue = 0x%x, pre_igvalue = 0x%x, backoff_val = %d\n", + dm_dig->cur_igvalue, dm_dig->pre_igvalue, + dm_dig->back_val); + + if (dm_dig->cur_igvalue > 0x3f) + dm_dig->cur_igvalue = 0x3f; + if (dm_dig->pre_igvalue != dm_dig->cur_igvalue) { + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, + dm_dig->cur_igvalue); + + dm_dig->pre_igvalue = dm_dig->cur_igvalue; + } +} + +static void rtl88e_dm_pwdb_monitor(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_sta_info *drv_priv; + static u64 last_record_txok_cnt; + static u64 last_record_rxok_cnt; + long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff; + + if (rtlhal->oem_id == RT_CID_819X_HP) { + u64 cur_txok_cnt = 0; + u64 cur_rxok_cnt = 0; + cur_txok_cnt = rtlpriv->stats.txbytesunicast - + last_record_txok_cnt; + cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - + last_record_rxok_cnt; + last_record_txok_cnt = cur_txok_cnt; + last_record_rxok_cnt = cur_rxok_cnt; + + if (cur_rxok_cnt > (cur_txok_cnt * 6)) + rtl_write_dword(rtlpriv, REG_ARFR0, 0x8f015); + else + rtl_write_dword(rtlpriv, REG_ARFR0, 0xff015); + } + + /* AP & ADHOC & MESH */ + spin_lock_bh(&rtlpriv->locks.entry_list_lock); + list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { + if (drv_priv->rssi_stat.undec_sm_pwdb < + tmp_entry_min_pwdb) + tmp_entry_min_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; + if (drv_priv->rssi_stat.undec_sm_pwdb > + tmp_entry_max_pwdb) + tmp_entry_max_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; + } + spin_unlock_bh(&rtlpriv->locks.entry_list_lock); + + /* If associated entry is found */ + if (tmp_entry_max_pwdb != 0) { + rtlpriv->dm.entry_max_undec_sm_pwdb = tmp_entry_max_pwdb; + RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMaxPWDB = 0x%lx(%ld)\n", + tmp_entry_max_pwdb, tmp_entry_max_pwdb); + } else { + rtlpriv->dm.entry_max_undec_sm_pwdb = 0; + } + /* If associated entry is found */ + if (tmp_entry_min_pwdb != 0xff) { + rtlpriv->dm.entry_min_undec_sm_pwdb = tmp_entry_min_pwdb; + RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMinPWDB = 0x%lx(%ld)\n", + tmp_entry_min_pwdb, tmp_entry_min_pwdb); + } else { + rtlpriv->dm.entry_min_undec_sm_pwdb = 0; + } + /* Indicate Rx signal strength to FW. */ + if (rtlpriv->dm.useramask) { + u8 h2c_parameter[3] = { 0 }; + + h2c_parameter[2] = (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF); + h2c_parameter[0] = 0x20; + } else { + rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb); + } +} + +void rtl88e_dm_init_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.current_turbo_edca = false; + rtlpriv->dm.is_any_nonbepkts = false; + rtlpriv->dm.is_cur_rdlstate = false; +} + +static void rtl88e_dm_check_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + static u64 last_txok_cnt; + static u64 last_rxok_cnt; + static u32 last_bt_edca_ul; + static u32 last_bt_edca_dl; + u64 cur_txok_cnt = 0; + u64 cur_rxok_cnt = 0; + u32 edca_be_ul = 0x5ea42b; + u32 edca_be_dl = 0x5ea42b; + bool bt_change_edca = false; + + if ((last_bt_edca_ul != rtlpriv->btcoexist.bt_edca_ul) || + (last_bt_edca_dl != rtlpriv->btcoexist.bt_edca_dl)) { + rtlpriv->dm.current_turbo_edca = false; + last_bt_edca_ul = rtlpriv->btcoexist.bt_edca_ul; + last_bt_edca_dl = rtlpriv->btcoexist.bt_edca_dl; + } + + if (rtlpriv->btcoexist.bt_edca_ul != 0) { + edca_be_ul = rtlpriv->btcoexist.bt_edca_ul; + bt_change_edca = true; + } + + if (rtlpriv->btcoexist.bt_edca_dl != 0) { + edca_be_ul = rtlpriv->btcoexist.bt_edca_dl; + bt_change_edca = true; + } + + if (mac->link_state != MAC80211_LINKED) { + rtlpriv->dm.current_turbo_edca = false; + return; + } + if ((bt_change_edca) || + ((!rtlpriv->dm.is_any_nonbepkts) && + (!rtlpriv->dm.disable_framebursting))) { + + cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; + cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; + + if (cur_rxok_cnt > 4 * cur_txok_cnt) { + if (!rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + rtl_write_dword(rtlpriv, + REG_EDCA_BE_PARAM, + edca_be_dl); + rtlpriv->dm.is_cur_rdlstate = true; + } + } else { + if (rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + rtl_write_dword(rtlpriv, + REG_EDCA_BE_PARAM, + edca_be_ul); + rtlpriv->dm.is_cur_rdlstate = false; + } + } + rtlpriv->dm.current_turbo_edca = true; + } else { + if (rtlpriv->dm.current_turbo_edca) { + u8 tmp = AC0_BE; + + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AC_PARAM, + &tmp); + rtlpriv->dm.current_turbo_edca = false; + } + } + + rtlpriv->dm.is_any_nonbepkts = false; + last_txok_cnt = rtlpriv->stats.txbytesunicast; + last_rxok_cnt = rtlpriv->stats.rxbytesunicast; +} + +static void dm_txpower_track_cb_therm(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 thermalvalue = 0, delta, delta_lck, delta_iqk, offset; + u8 thermalvalue_avg_count = 0; + u32 thermalvalue_avg = 0; + long ele_d, temp_cck; + char ofdm_index[2], cck_index = 0, + ofdm_index_old[2] = {0, 0}, cck_index_old = 0; + int i = 0; + /*bool is2t = false;*/ + + u8 ofdm_min_index = 6, rf = 1; + /*u8 index_for_channel;*/ + enum _power_dec_inc {power_dec, power_inc}; + + /*0.1 the following TWO tables decide the + *final index of OFDM/CCK swing table + */ + char delta_swing_table_idx[2][15] = { + {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11}, + {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10} + }; + u8 thermal_threshold[2][15] = { + {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27}, + {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25} + }; + + /*Initilization (7 steps in total) */ + rtlpriv->dm.txpower_trackinginit = true; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "dm_txpower_track_cb_therm\n"); + + thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, + 0xfc00); + if (!thermalvalue) + return; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n", + thermalvalue, rtlpriv->dm.thermalvalue, + rtlefuse->eeprom_thermalmeter); + + /*1. Query OFDM Default Setting: Path A*/ + ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD) & + MASKOFDM_D; + for (i = 0; i < OFDM_TABLE_LENGTH; i++) { + if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { + ofdm_index_old[0] = (u8)i; + rtldm->swing_idx_ofdm_base[RF90_PATH_A] = (u8)i; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index = 0x%x\n", + ROFDM0_XATXIQIMBALANCE, + ele_d, ofdm_index_old[0]); + break; + } + } + + /*2.Query CCK default setting From 0xa24*/ + temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK; + for (i = 0; i < CCK_TABLE_LENGTH; i++) { + if (rtlpriv->dm.cck_inch14) { + if (memcmp(&temp_cck, &cck_tbl_ch14[i][2], 4) == 0) { + cck_index_old = (u8)i; + rtldm->swing_idx_cck_base = (u8)i; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, + DBG_LOUD, + "Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch 14 %d\n", + RCCK0_TXFILTER2, temp_cck, + cck_index_old, + rtlpriv->dm.cck_inch14); + break; + } + } else { + if (memcmp(&temp_cck, &cck_tbl_ch1_13[i][2], 4) == 0) { + cck_index_old = (u8)i; + rtldm->swing_idx_cck_base = (u8)i; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, + DBG_LOUD, + "Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch14 %d\n", + RCCK0_TXFILTER2, temp_cck, + cck_index_old, + rtlpriv->dm.cck_inch14); + break; + } + } + } + + /*3 Initialize ThermalValues of RFCalibrateInfo*/ + if (!rtldm->thermalvalue) { + rtlpriv->dm.thermalvalue = rtlefuse->eeprom_thermalmeter; + rtlpriv->dm.thermalvalue_lck = thermalvalue; + rtlpriv->dm.thermalvalue_iqk = thermalvalue; + for (i = 0; i < rf; i++) + rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; + rtlpriv->dm.cck_index = cck_index_old; + } + + /*4 Calculate average thermal meter*/ + rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue; + rtldm->thermalvalue_avg_index++; + if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_88E) + rtldm->thermalvalue_avg_index = 0; + + for (i = 0; i < AVG_THERMAL_NUM_88E; i++) { + if (rtldm->thermalvalue_avg[i]) { + thermalvalue_avg += rtldm->thermalvalue_avg[i]; + thermalvalue_avg_count++; + } + } + + if (thermalvalue_avg_count) + thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count); + + /* 5 Calculate delta, delta_LCK, delta_IQK.*/ + if (rtlhal->reloadtxpowerindex) { + delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? + (thermalvalue - rtlefuse->eeprom_thermalmeter) : + (rtlefuse->eeprom_thermalmeter - thermalvalue); + rtlhal->reloadtxpowerindex = false; + rtlpriv->dm.done_txpower = false; + } else if (rtlpriv->dm.done_txpower) { + delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? + (thermalvalue - rtlpriv->dm.thermalvalue) : + (rtlpriv->dm.thermalvalue - thermalvalue); + } else { + delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? + (thermalvalue - rtlefuse->eeprom_thermalmeter) : + (rtlefuse->eeprom_thermalmeter - thermalvalue); + } + delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? + (thermalvalue - rtlpriv->dm.thermalvalue_lck) : + (rtlpriv->dm.thermalvalue_lck - thermalvalue); + delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? + (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : + (rtlpriv->dm.thermalvalue_iqk - thermalvalue); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n", + thermalvalue, rtlpriv->dm.thermalvalue, + rtlefuse->eeprom_thermalmeter, delta, delta_lck, + delta_iqk); + /* 6 If necessary, do LCK.*/ + if (delta_lck >= 8) { + rtlpriv->dm.thermalvalue_lck = thermalvalue; + rtl88e_phy_lc_calibrate(hw); + } + + /* 7 If necessary, move the index of + * swing table to adjust Tx power. + */ + if (delta > 0 && rtlpriv->dm.txpower_track_control) { + delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? + (thermalvalue - rtlefuse->eeprom_thermalmeter) : + (rtlefuse->eeprom_thermalmeter - thermalvalue); + + /* 7.1 Get the final CCK_index and OFDM_index for each + * swing table. + */ + if (thermalvalue > rtlefuse->eeprom_thermalmeter) { + CAL_SWING_OFF(offset, power_inc, INDEX_MAPPING_NUM, + delta); + for (i = 0; i < rf; i++) + ofdm_index[i] = + rtldm->ofdm_index[i] + + delta_swing_table_idx[power_inc][offset]; + cck_index = rtldm->cck_index + + delta_swing_table_idx[power_inc][offset]; + } else { + CAL_SWING_OFF(offset, power_dec, INDEX_MAPPING_NUM, + delta); + for (i = 0; i < rf; i++) + ofdm_index[i] = + rtldm->ofdm_index[i] + + delta_swing_table_idx[power_dec][offset]; + cck_index = rtldm->cck_index + + delta_swing_table_idx[power_dec][offset]; + } + + /* 7.2 Handle boundary conditions of index.*/ + for (i = 0; i < rf; i++) { + if (ofdm_index[i] > OFDM_TABLE_SIZE-1) + ofdm_index[i] = OFDM_TABLE_SIZE-1; + else if (rtldm->ofdm_index[i] < ofdm_min_index) + ofdm_index[i] = ofdm_min_index; + } + + if (cck_index > CCK_TABLE_SIZE-1) + cck_index = CCK_TABLE_SIZE-1; + else if (cck_index < 0) + cck_index = 0; + + /*7.3Configure the Swing Table to adjust Tx Power.*/ + if (rtlpriv->dm.txpower_track_control) { + rtldm->done_txpower = true; + rtldm->swing_idx_ofdm[RF90_PATH_A] = + (u8)ofdm_index[RF90_PATH_A]; + rtldm->swing_idx_cck = cck_index; + if (rtldm->swing_idx_ofdm_cur != + rtldm->swing_idx_ofdm[0]) { + rtldm->swing_idx_ofdm_cur = + rtldm->swing_idx_ofdm[0]; + rtldm->swing_flag_ofdm = true; + } + + if (rtldm->swing_idx_cck_cur != rtldm->swing_idx_cck) { + rtldm->swing_idx_cck_cur = rtldm->swing_idx_cck; + rtldm->swing_flag_cck = true; + } + + dm_tx_pwr_track_set_pwr(hw, TXAGC, 0, 0); + } + } + + if (delta_iqk >= 8) { + rtlpriv->dm.thermalvalue_iqk = thermalvalue; + rtl88e_phy_iq_calibrate(hw, false); + } + + if (rtldm->txpower_track_control) + rtldm->thermalvalue = thermalvalue; + rtldm->txpowercount = 0; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n"); +} + +static void rtl88e_dm_init_txpower_tracking(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.txpower_tracking = true; + rtlpriv->dm.txpower_trackinginit = false; + rtlpriv->dm.txpowercount = 0; + rtlpriv->dm.txpower_track_control = true; + + rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] = 12; + rtlpriv->dm.swing_idx_ofdm_cur = 12; + rtlpriv->dm.swing_flag_ofdm = false; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "rtlpriv->dm.txpower_tracking = %d\n", + rtlpriv->dm.txpower_tracking); +} + +void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (!rtlpriv->dm.txpower_tracking) + return; + + if (!rtlpriv->dm.tm_trigger) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17)|BIT(16), + 0x03); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Trigger 88E Thermal Meter!!\n"); + rtlpriv->dm.tm_trigger = 1; + return; + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Schedule TxPowerTracking !!\n"); + dm_txpower_track_cb_therm(hw); + rtlpriv->dm.tm_trigger = 0; + } +} + +void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rate_adaptive *p_ra = &rtlpriv->ra; + + p_ra->ratr_state = DM_RATR_STA_INIT; + p_ra->pre_ratr_state = DM_RATR_STA_INIT; + + if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) + rtlpriv->dm.useramask = true; + else + rtlpriv->dm.useramask = false; +} + +static void rtl88e_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rate_adaptive *p_ra = &rtlpriv->ra; + u32 low_rssithresh_for_ra, high_rssithresh_for_ra; + struct ieee80211_sta *sta = NULL; + + if (is_hal_stop(rtlhal)) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "driver is going to unload\n"); + return; + } + + if (!rtlpriv->dm.useramask) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "driver does not control rate adaptive mask\n"); + return; + } + + if (mac->link_state == MAC80211_LINKED && + mac->opmode == NL80211_IFTYPE_STATION) { + switch (p_ra->pre_ratr_state) { + case DM_RATR_STA_HIGH: + high_rssithresh_for_ra = 50; + low_rssithresh_for_ra = 20; + break; + case DM_RATR_STA_MIDDLE: + high_rssithresh_for_ra = 55; + low_rssithresh_for_ra = 20; + break; + case DM_RATR_STA_LOW: + high_rssithresh_for_ra = 50; + low_rssithresh_for_ra = 25; + break; + default: + high_rssithresh_for_ra = 50; + low_rssithresh_for_ra = 20; + break; + } + + if (rtlpriv->dm.undec_sm_pwdb > + (long)high_rssithresh_for_ra) + p_ra->ratr_state = DM_RATR_STA_HIGH; + else if (rtlpriv->dm.undec_sm_pwdb > + (long)low_rssithresh_for_ra) + p_ra->ratr_state = DM_RATR_STA_MIDDLE; + else + p_ra->ratr_state = DM_RATR_STA_LOW; + + if (p_ra->pre_ratr_state != p_ra->ratr_state) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "RSSI = %ld\n", + rtlpriv->dm.undec_sm_pwdb); + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "RSSI_LEVEL = %d\n", p_ra->ratr_state); + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "PreState = %d, CurState = %d\n", + p_ra->pre_ratr_state, p_ra->ratr_state); + + rcu_read_lock(); + sta = rtl_find_sta(hw, mac->bssid); + if (sta) + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, + p_ra->ratr_state); + rcu_read_unlock(); + + p_ra->pre_ratr_state = p_ra->ratr_state; + } + } +} + +static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ps_t *dm_pstable = &rtlpriv->dm_pstable; + + dm_pstable->pre_ccastate = CCA_MAX; + dm_pstable->cur_ccasate = CCA_MAX; + dm_pstable->pre_rfstate = RF_MAX; + dm_pstable->cur_rfstate = RF_MAX; + dm_pstable->rssi_val_min = 0; +} + +static void rtl88e_dm_update_rx_idle_ant(struct ieee80211_hw *hw, + u8 ant) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct fast_ant_training *pfat_table = &rtldm->fat_table; + u32 default_ant, optional_ant; + + if (pfat_table->rx_idle_ant != ant) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "need to update rx idle ant\n"); + if (ant == MAIN_ANT) { + default_ant = + (pfat_table->rx_idle_ant == CG_TRX_HW_ANTDIV) ? + MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; + optional_ant = + (pfat_table->rx_idle_ant == CG_TRX_HW_ANTDIV) ? + AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; + } else { + default_ant = + (pfat_table->rx_idle_ant == CG_TRX_HW_ANTDIV) ? + AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; + optional_ant = + (pfat_table->rx_idle_ant == CG_TRX_HW_ANTDIV) ? + MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; + } + + if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) { + rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, + BIT(5) | BIT(4) | BIT(3), default_ant); + rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, + BIT(8) | BIT(7) | BIT(6), optional_ant); + rtl_set_bbreg(hw, DM_REG_ANTSEL_CTRL_11N, + BIT(14) | BIT(13) | BIT(12), + default_ant); + rtl_set_bbreg(hw, DM_REG_RESP_TX_11N, + BIT(6) | BIT(7), default_ant); + } else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) { + rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, + BIT(5) | BIT(4) | BIT(3), default_ant); + rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, + BIT(8) | BIT(7) | BIT(6), optional_ant); + } + } + pfat_table->rx_idle_ant = ant; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RxIdleAnt %s\n", + (ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT")); +} + +static void rtl88e_dm_update_tx_ant(struct ieee80211_hw *hw, + u8 ant, u32 mac_id) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct fast_ant_training *pfat_table = &rtldm->fat_table; + u8 target_ant; + + if (ant == MAIN_ANT) + target_ant = MAIN_ANT_CG_TRX; + else + target_ant = AUX_ANT_CG_TRX; + + pfat_table->antsel_a[mac_id] = target_ant & BIT(0); + pfat_table->antsel_b[mac_id] = (target_ant & BIT(1)) >> 1; + pfat_table->antsel_c[mac_id] = (target_ant & BIT(2)) >> 2; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "txfrominfo target ant %s\n", + (ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT")); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "antsel_tr_mux = 3'b%d%d%d\n", + pfat_table->antsel_c[mac_id], + pfat_table->antsel_b[mac_id], + pfat_table->antsel_a[mac_id]); +} + +static void rtl88e_dm_rx_hw_antena_div_init(struct ieee80211_hw *hw) +{ + u32 value32; + + /*MAC Setting*/ + value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD); + rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, + MASKDWORD, value32 | (BIT(23) | BIT(25))); + /*Pin Setting*/ + rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0); + rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0); + rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 1); + rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1); + /*OFDM Setting*/ + rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); + /*CCK Setting*/ + rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1); + rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); + rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT); + rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201); +} + +static void rtl88e_dm_trx_hw_antenna_div_init(struct ieee80211_hw *hw) +{ + u32 value32; + + /*MAC Setting*/ + value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD); + rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, + value32 | (BIT(23) | BIT(25))); + /*Pin Setting*/ + rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0); + rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0); + rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0); + rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1); + /*OFDM Setting*/ + rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); + /*CCK Setting*/ + rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1); + rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); + /*TX Setting*/ + rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 0); + rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT); + rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201); +} + +static void rtl88e_dm_fast_training_init(struct ieee80211_hw *hw) +{ + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct fast_ant_training *pfat_table = &rtldm->fat_table; + u32 ant_combination = 2; + u32 value32, i; + + for (i = 0; i < 6; i++) { + pfat_table->bssid[i] = 0; + pfat_table->ant_sum[i] = 0; + pfat_table->ant_cnt[i] = 0; + pfat_table->ant_ave[i] = 0; + } + pfat_table->train_idx = 0; + pfat_table->fat_state = FAT_NORMAL_STATE; + + /*MAC Setting*/ + value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD); + rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, + MASKDWORD, value32 | (BIT(23) | BIT(25))); + value32 = rtl_get_bbreg(hw, DM_REG_ANT_TRAIN_PARA2_11N, MASKDWORD); + rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_PARA2_11N, + MASKDWORD, value32 | (BIT(16) | BIT(17))); + rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_PARA2_11N, + MASKLWORD, 0); + rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_PARA1_11N, + MASKDWORD, 0); + + /*Pin Setting*/ + rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0); + rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0); + rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0); + rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1); + + /*OFDM Setting*/ + rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); + /*antenna mapping table*/ + rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE0, 1); + rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE1, 2); + + /*TX Setting*/ + rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 1); + rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, + BIT(5) | BIT(4) | BIT(3), 0); + rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, + BIT(8) | BIT(7) | BIT(6), 1); + rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, + BIT(2) | BIT(1) | BIT(0), (ant_combination - 1)); + + rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1); +} + +static void rtl88e_dm_antenna_div_init(struct ieee80211_hw *hw) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) + rtl88e_dm_rx_hw_antena_div_init(hw); + else if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) + rtl88e_dm_trx_hw_antenna_div_init(hw); + else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) + rtl88e_dm_fast_training_init(hw); + +} + +void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, + u8 *pdesc, u32 mac_id) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct fast_ant_training *pfat_table = &rtldm->fat_table; + + if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || + (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV)) { + SET_TX_DESC_ANTSEL_A(pdesc, pfat_table->antsel_a[mac_id]); + SET_TX_DESC_ANTSEL_B(pdesc, pfat_table->antsel_b[mac_id]); + SET_TX_DESC_ANTSEL_C(pdesc, pfat_table->antsel_c[mac_id]); + } +} + +void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw, + u8 antsel_tr_mux, u32 mac_id, + u32 rx_pwdb_all) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct fast_ant_training *pfat_table = &rtldm->fat_table; + + if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) { + if (antsel_tr_mux == MAIN_ANT_CG_TRX) { + pfat_table->main_ant_sum[mac_id] += rx_pwdb_all; + pfat_table->main_ant_cnt[mac_id]++; + } else { + pfat_table->aux_ant_sum[mac_id] += rx_pwdb_all; + pfat_table->aux_ant_cnt[mac_id]++; + } + } else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) { + if (antsel_tr_mux == MAIN_ANT_CGCS_RX) { + pfat_table->main_ant_sum[mac_id] += rx_pwdb_all; + pfat_table->main_ant_cnt[mac_id]++; + } else { + pfat_table->aux_ant_sum[mac_id] += rx_pwdb_all; + pfat_table->aux_ant_cnt[mac_id]++; + } + } +} + +static void rtl88e_dm_hw_ant_div(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct rtl_sta_info *drv_priv; + struct fast_ant_training *pfat_table = &rtldm->fat_table; + struct dig_t *dm_dig = &rtlpriv->dm_digtable; + u32 i, min_rssi = 0xff, ant_div_max_rssi = 0; + u32 max_rssi = 0, local_min_rssi, local_max_rssi; + u32 main_rssi, aux_rssi; + u8 rx_idle_ant = 0, target_ant = 7; + + /*for sta its self*/ + i = 0; + main_rssi = (pfat_table->main_ant_cnt[i] != 0) ? + (pfat_table->main_ant_sum[i] / pfat_table->main_ant_cnt[i]) : 0; + aux_rssi = (pfat_table->aux_ant_cnt[i] != 0) ? + (pfat_table->aux_ant_sum[i] / pfat_table->aux_ant_cnt[i]) : 0; + target_ant = (main_rssi == aux_rssi) ? + pfat_table->rx_idle_ant : ((main_rssi >= aux_rssi) ? + MAIN_ANT : AUX_ANT); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "main_ant_sum %d main_ant_cnt %d\n", + pfat_table->main_ant_sum[i], + pfat_table->main_ant_cnt[i]); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "aux_ant_sum %d aux_ant_cnt %d\n", + pfat_table->aux_ant_sum[i], pfat_table->aux_ant_cnt[i]); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "main_rssi %d aux_rssi%d\n", + main_rssi, aux_rssi); + local_max_rssi = (main_rssi > aux_rssi) ? main_rssi : aux_rssi; + if ((local_max_rssi > ant_div_max_rssi) && (local_max_rssi < 40)) + ant_div_max_rssi = local_max_rssi; + if (local_max_rssi > max_rssi) + max_rssi = local_max_rssi; + + if ((pfat_table->rx_idle_ant == MAIN_ANT) && (main_rssi == 0)) + main_rssi = aux_rssi; + else if ((pfat_table->rx_idle_ant == AUX_ANT) && (aux_rssi == 0)) + aux_rssi = main_rssi; + + local_min_rssi = (main_rssi > aux_rssi) ? aux_rssi : main_rssi; + if (local_min_rssi < min_rssi) { + min_rssi = local_min_rssi; + rx_idle_ant = target_ant; + } + if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) + rtl88e_dm_update_tx_ant(hw, target_ant, i); + + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || + rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) { + spin_lock_bh(&rtlpriv->locks.entry_list_lock); + list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { + i++; + main_rssi = (pfat_table->main_ant_cnt[i] != 0) ? + (pfat_table->main_ant_sum[i] / + pfat_table->main_ant_cnt[i]) : 0; + aux_rssi = (pfat_table->aux_ant_cnt[i] != 0) ? + (pfat_table->aux_ant_sum[i] / + pfat_table->aux_ant_cnt[i]) : 0; + target_ant = (main_rssi == aux_rssi) ? + pfat_table->rx_idle_ant : ((main_rssi >= + aux_rssi) ? MAIN_ANT : AUX_ANT); + + local_max_rssi = (main_rssi > aux_rssi) ? + main_rssi : aux_rssi; + if ((local_max_rssi > ant_div_max_rssi) && + (local_max_rssi < 40)) + ant_div_max_rssi = local_max_rssi; + if (local_max_rssi > max_rssi) + max_rssi = local_max_rssi; + + if ((pfat_table->rx_idle_ant == MAIN_ANT) && + (main_rssi == 0)) + main_rssi = aux_rssi; + else if ((pfat_table->rx_idle_ant == AUX_ANT) && + (aux_rssi == 0)) + aux_rssi = main_rssi; + + local_min_rssi = (main_rssi > aux_rssi) ? + aux_rssi : main_rssi; + if (local_min_rssi < min_rssi) { + min_rssi = local_min_rssi; + rx_idle_ant = target_ant; + } + if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) + rtl88e_dm_update_tx_ant(hw, target_ant, i); + } + spin_unlock_bh(&rtlpriv->locks.entry_list_lock); + } + + for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) { + pfat_table->main_ant_sum[i] = 0; + pfat_table->aux_ant_sum[i] = 0; + pfat_table->main_ant_cnt[i] = 0; + pfat_table->aux_ant_cnt[i] = 0; + } + + rtl88e_dm_update_rx_idle_ant(hw, rx_idle_ant); + + dm_dig->antdiv_rssi_max = ant_div_max_rssi; + dm_dig->rssi_max = max_rssi; +} + +static void rtl88e_set_next_mac_address_target(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct rtl_sta_info *drv_priv; + struct fast_ant_training *pfat_table = &rtldm->fat_table; + u32 value32, i, j = 0; + + if (mac->link_state >= MAC80211_LINKED) { + for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) { + if ((pfat_table->train_idx + 1) == ASSOCIATE_ENTRY_NUM) + pfat_table->train_idx = 0; + else + pfat_table->train_idx++; + + if (pfat_table->train_idx == 0) { + value32 = (mac->mac_addr[5] << 8) | + mac->mac_addr[4]; + rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_PARA2_11N, + MASKLWORD, value32); + + value32 = (mac->mac_addr[3] << 24) | + (mac->mac_addr[2] << 16) | + (mac->mac_addr[1] << 8) | + mac->mac_addr[0]; + rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_PARA1_11N, + MASKDWORD, value32); + break; + } + + if (rtlpriv->mac80211.opmode != + NL80211_IFTYPE_STATION) { + spin_lock_bh(&rtlpriv->locks.entry_list_lock); + list_for_each_entry(drv_priv, + &rtlpriv->entry_list, list) { + j++; + if (j != pfat_table->train_idx) + continue; + + value32 = (drv_priv->mac_addr[5] << 8) | + drv_priv->mac_addr[4]; + rtl_set_bbreg(hw, + DM_REG_ANT_TRAIN_PARA2_11N, + MASKLWORD, value32); + + value32 = (drv_priv->mac_addr[3] << 24) | + (drv_priv->mac_addr[2] << 16) | + (drv_priv->mac_addr[1] << 8) | + drv_priv->mac_addr[0]; + rtl_set_bbreg(hw, + DM_REG_ANT_TRAIN_PARA1_11N, + MASKDWORD, value32); + break; + } + spin_unlock_bh(&rtlpriv->locks.entry_list_lock); + /*find entry, break*/ + if (j == pfat_table->train_idx) + break; + } + } + } +} + +static void rtl88e_dm_fast_ant_training(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct fast_ant_training *pfat_table = &rtldm->fat_table; + u32 i, max_rssi = 0; + u8 target_ant = 2; + bool bpkt_filter_match = false; + + if (pfat_table->fat_state == FAT_TRAINING_STATE) { + for (i = 0; i < 7; i++) { + if (pfat_table->ant_cnt[i] == 0) { + pfat_table->ant_ave[i] = 0; + } else { + pfat_table->ant_ave[i] = + pfat_table->ant_sum[i] / + pfat_table->ant_cnt[i]; + bpkt_filter_match = true; + } + + if (pfat_table->ant_ave[i] > max_rssi) { + max_rssi = pfat_table->ant_ave[i]; + target_ant = (u8) i; + } + } + + if (bpkt_filter_match == false) { + rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, + BIT(16), 0); + rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0); + } else { + rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, + BIT(16), 0); + rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | + BIT(7) | BIT(6), target_ant); + rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, + BIT(21), 1); + + pfat_table->antsel_a[pfat_table->train_idx] = + target_ant & BIT(0); + pfat_table->antsel_b[pfat_table->train_idx] = + (target_ant & BIT(1)) >> 1; + pfat_table->antsel_c[pfat_table->train_idx] = + (target_ant & BIT(2)) >> 2; + + if (target_ant == 0) + rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0); + } + + for (i = 0; i < 7; i++) { + pfat_table->ant_sum[i] = 0; + pfat_table->ant_cnt[i] = 0; + } + + pfat_table->fat_state = FAT_NORMAL_STATE; + return; + } + + if (pfat_table->fat_state == FAT_NORMAL_STATE) { + rtl88e_set_next_mac_address_target(hw); + + pfat_table->fat_state = FAT_TRAINING_STATE; + rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, BIT(16), 1); + rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1); + + mod_timer(&rtlpriv->works.fast_antenna_training_timer, + jiffies + MSECS(RTL_WATCH_DOG_TIME)); + } +} + +void rtl88e_dm_fast_antenna_training_callback(unsigned long data) +{ + struct ieee80211_hw *hw = (struct ieee80211_hw *)data; + + rtl88e_dm_fast_ant_training(hw); +} + +static void rtl88e_dm_antenna_diversity(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct fast_ant_training *pfat_table = &rtldm->fat_table; + + if (mac->link_state < MAC80211_LINKED) { + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "No Link\n"); + if (pfat_table->becomelinked) { + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "need to turn off HW AntDiv\n"); + rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0); + rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N, + BIT(15), 0); + if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) + rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, + BIT(21), 0); + pfat_table->becomelinked = + (mac->link_state == MAC80211_LINKED) ? + true : false; + } + return; + } else { + if (!pfat_table->becomelinked) { + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Need to turn on HW AntDiv\n"); + rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1); + rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N, + BIT(15), 1); + if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) + rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, + BIT(21), 1); + pfat_table->becomelinked = + (mac->link_state >= MAC80211_LINKED) ? + true : false; + } + } + + if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || + (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)) + rtl88e_dm_hw_ant_div(hw); + else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) + rtl88e_dm_fast_ant_training(hw); +} + +void rtl88e_dm_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f); + + rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; + rtl_dm_diginit(hw, cur_igvalue); + rtl88e_dm_init_dynamic_txpower(hw); + rtl88e_dm_init_edca_turbo(hw); + rtl88e_dm_init_rate_adaptive_mask(hw); + rtl88e_dm_init_txpower_tracking(hw); + rtl92c_dm_init_dynamic_bb_powersaving(hw); + rtl88e_dm_antenna_div_init(hw); +} + +void rtl88e_dm_watchdog(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool fw_current_inpsmode = false; + bool fw_ps_awake = true; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inpsmode)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, + (u8 *)(&fw_ps_awake)); + if (ppsc->p2p_ps_info.p2p_ps_mode) + fw_ps_awake = false; + + if ((ppsc->rfpwr_state == ERFON) && + ((!fw_current_inpsmode) && fw_ps_awake) && + (!ppsc->rfchange_inprogress)) { + rtl88e_dm_pwdb_monitor(hw); + rtl88e_dm_dig(hw); + rtl88e_dm_false_alarm_counter_statistics(hw); + rtl92c_dm_dynamic_txpower(hw); + rtl88e_dm_check_txpower_tracking(hw); + rtl88e_dm_refresh_rate_adaptive_mask(hw); + rtl88e_dm_check_edca_turbo(hw); + rtl88e_dm_antenna_diversity(hw); + } +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h new file mode 100644 index 000000000000..071ccee69eae --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.h @@ -0,0 +1,286 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL88E_DM_H__ +#define __RTL88E_DM_H__ + +#define MAIN_ANT 0 +#define AUX_ANT 1 +#define MAIN_ANT_CG_TRX 1 +#define AUX_ANT_CG_TRX 0 +#define MAIN_ANT_CGCS_RX 0 +#define AUX_ANT_CGCS_RX 1 + +/*RF REG LIST*/ +#define DM_REG_RF_MODE_11N 0x00 +#define DM_REG_RF_0B_11N 0x0B +#define DM_REG_CHNBW_11N 0x18 +#define DM_REG_T_METER_11N 0x24 +#define DM_REG_RF_25_11N 0x25 +#define DM_REG_RF_26_11N 0x26 +#define DM_REG_RF_27_11N 0x27 +#define DM_REG_RF_2B_11N 0x2B +#define DM_REG_RF_2C_11N 0x2C +#define DM_REG_RXRF_A3_11N 0x3C +#define DM_REG_T_METER_92D_11N 0x42 +#define DM_REG_T_METER_88E_11N 0x42 + +/*BB REG LIST*/ +/*PAGE 8 */ +#define DM_REG_BB_CTRL_11N 0x800 +#define DM_REG_RF_PIN_11N 0x804 +#define DM_REG_PSD_CTRL_11N 0x808 +#define DM_REG_TX_ANT_CTRL_11N 0x80C +#define DM_REG_BB_PWR_SAV5_11N 0x818 +#define DM_REG_CCK_RPT_FORMAT_11N 0x824 +#define DM_REG_RX_DEFAULT_A_11N 0x858 +#define DM_REG_RX_DEFAULT_B_11N 0x85A +#define DM_REG_BB_PWR_SAV3_11N 0x85C +#define DM_REG_ANTSEL_CTRL_11N 0x860 +#define DM_REG_RX_ANT_CTRL_11N 0x864 +#define DM_REG_PIN_CTRL_11N 0x870 +#define DM_REG_BB_PWR_SAV1_11N 0x874 +#define DM_REG_ANTSEL_PATH_11N 0x878 +#define DM_REG_BB_3WIRE_11N 0x88C +#define DM_REG_SC_CNT_11N 0x8C4 +#define DM_REG_PSD_DATA_11N 0x8B4 +/*PAGE 9*/ +#define DM_REG_ANT_MAPPING1_11N 0x914 +#define DM_REG_ANT_MAPPING2_11N 0x918 +/*PAGE A*/ +#define DM_REG_CCK_ANTDIV_PARA1_11N 0xA00 +#define DM_REG_CCK_CCA_11N 0xA0A +#define DM_REG_CCK_ANTDIV_PARA2_11N 0xA0C +#define DM_REG_CCK_ANTDIV_PARA3_11N 0xA10 +#define DM_REG_CCK_ANTDIV_PARA4_11N 0xA14 +#define DM_REG_CCK_FILTER_PARA1_11N 0xA22 +#define DM_REG_CCK_FILTER_PARA2_11N 0xA23 +#define DM_REG_CCK_FILTER_PARA3_11N 0xA24 +#define DM_REG_CCK_FILTER_PARA4_11N 0xA25 +#define DM_REG_CCK_FILTER_PARA5_11N 0xA26 +#define DM_REG_CCK_FILTER_PARA6_11N 0xA27 +#define DM_REG_CCK_FILTER_PARA7_11N 0xA28 +#define DM_REG_CCK_FILTER_PARA8_11N 0xA29 +#define DM_REG_CCK_FA_RST_11N 0xA2C +#define DM_REG_CCK_FA_MSB_11N 0xA58 +#define DM_REG_CCK_FA_LSB_11N 0xA5C +#define DM_REG_CCK_CCA_CNT_11N 0xA60 +#define DM_REG_BB_PWR_SAV4_11N 0xA74 +/*PAGE B */ +#define DM_REG_LNA_SWITCH_11N 0xB2C +#define DM_REG_PATH_SWITCH_11N 0xB30 +#define DM_REG_RSSI_CTRL_11N 0xB38 +#define DM_REG_CONFIG_ANTA_11N 0xB68 +#define DM_REG_RSSI_BT_11N 0xB9C +/*PAGE C */ +#define DM_REG_OFDM_FA_HOLDC_11N 0xC00 +#define DM_REG_RX_PATH_11N 0xC04 +#define DM_REG_TRMUX_11N 0xC08 +#define DM_REG_OFDM_FA_RSTC_11N 0xC0C +#define DM_REG_RXIQI_MATRIX_11N 0xC14 +#define DM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C +#define DM_REG_IGI_A_11N 0xC50 +#define DM_REG_ANTDIV_PARA2_11N 0xC54 +#define DM_REG_IGI_B_11N 0xC58 +#define DM_REG_ANTDIV_PARA3_11N 0xC5C +#define DM_REG_BB_PWR_SAV2_11N 0xC70 +#define DM_REG_RX_OFF_11N 0xC7C +#define DM_REG_TXIQK_MATRIXA_11N 0xC80 +#define DM_REG_TXIQK_MATRIXB_11N 0xC88 +#define DM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 +#define DM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C +#define DM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 +#define DM_REG_ANTDIV_PARA1_11N 0xCA4 +#define DM_REG_OFDM_FA_TYPE1_11N 0xCF0 +/*PAGE D */ +#define DM_REG_OFDM_FA_RSTD_11N 0xD00 +#define DM_REG_OFDM_FA_TYPE2_11N 0xDA0 +#define DM_REG_OFDM_FA_TYPE3_11N 0xDA4 +#define DM_REG_OFDM_FA_TYPE4_11N 0xDA8 +/*PAGE E */ +#define DM_REG_TXAGC_A_6_18_11N 0xE00 +#define DM_REG_TXAGC_A_24_54_11N 0xE04 +#define DM_REG_TXAGC_A_1_MCS32_11N 0xE08 +#define DM_REG_TXAGC_A_MCS0_3_11N 0xE10 +#define DM_REG_TXAGC_A_MCS4_7_11N 0xE14 +#define DM_REG_TXAGC_A_MCS8_11_11N 0xE18 +#define DM_REG_TXAGC_A_MCS12_15_11N 0xE1C +#define DM_REG_FPGA0_IQK_11N 0xE28 +#define DM_REG_TXIQK_TONE_A_11N 0xE30 +#define DM_REG_RXIQK_TONE_A_11N 0xE34 +#define DM_REG_TXIQK_PI_A_11N 0xE38 +#define DM_REG_RXIQK_PI_A_11N 0xE3C +#define DM_REG_TXIQK_11N 0xE40 +#define DM_REG_RXIQK_11N 0xE44 +#define DM_REG_IQK_AGC_PTS_11N 0xE48 +#define DM_REG_IQK_AGC_RSP_11N 0xE4C +#define DM_REG_BLUETOOTH_11N 0xE6C +#define DM_REG_RX_WAIT_CCA_11N 0xE70 +#define DM_REG_TX_CCK_RFON_11N 0xE74 +#define DM_REG_TX_CCK_BBON_11N 0xE78 +#define DM_REG_OFDM_RFON_11N 0xE7C +#define DM_REG_OFDM_BBON_11N 0xE80 +#define DM_REG_TX2RX_11N 0xE84 +#define DM_REG_TX2TX_11N 0xE88 +#define DM_REG_RX_CCK_11N 0xE8C +#define DM_REG_RX_OFDM_11N 0xED0 +#define DM_REG_RX_WAIT_RIFS_11N 0xED4 +#define DM_REG_RX2RX_11N 0xED8 +#define DM_REG_STANDBY_11N 0xEDC +#define DM_REG_SLEEP_11N 0xEE0 +#define DM_REG_PMPD_ANAEN_11N 0xEEC + +/*MAC REG LIST*/ +#define DM_REG_BB_RST_11N 0x02 +#define DM_REG_ANTSEL_PIN_11N 0x4C +#define DM_REG_EARLY_MODE_11N 0x4D0 +#define DM_REG_RSSI_MONITOR_11N 0x4FE +#define DM_REG_EDCA_VO_11N 0x500 +#define DM_REG_EDCA_VI_11N 0x504 +#define DM_REG_EDCA_BE_11N 0x508 +#define DM_REG_EDCA_BK_11N 0x50C +#define DM_REG_TXPAUSE_11N 0x522 +#define DM_REG_RESP_TX_11N 0x6D8 +#define DM_REG_ANT_TRAIN_PARA1_11N 0x7b0 +#define DM_REG_ANT_TRAIN_PARA2_11N 0x7b4 + + +/*DIG Related*/ +#define DM_BIT_IGI_11N 0x0000007F + +#define HAL_DM_DIG_DISABLE BIT(0) +#define HAL_DM_HIPWR_DISABLE BIT(1) + +#define OFDM_TABLE_LENGTH 43 +#define CCK_TABLE_LENGTH 33 + +#define OFDM_TABLE_SIZE 43 +#define CCK_TABLE_SIZE 33 + +#define BW_AUTO_SWITCH_HIGH_LOW 25 +#define BW_AUTO_SWITCH_LOW_HIGH 30 + +#define DM_DIG_FA_UPPER 0x3e +#define DM_DIG_FA_LOWER 0x1e +#define DM_DIG_FA_TH0 0x200 +#define DM_DIG_FA_TH1 0x300 +#define DM_DIG_FA_TH2 0x400 + +#define RXPATHSELECTION_SS_TH_W 30 +#define RXPATHSELECTION_DIFF_TH 18 + +#define DM_RATR_STA_INIT 0 +#define DM_RATR_STA_HIGH 1 +#define DM_RATR_STA_MIDDLE 2 +#define DM_RATR_STA_LOW 3 + +#define CTS2SELF_THVAL 30 +#define REGC38_TH 20 + +#define WAIOTTHVAL 25 + +#define TXHIGHPWRLEVEL_NORMAL 0 +#define TXHIGHPWRLEVEL_LEVEL1 1 +#define TXHIGHPWRLEVEL_LEVEL2 2 +#define TXHIGHPWRLEVEL_BT1 3 +#define TXHIGHPWRLEVEL_BT2 4 + +#define DM_TYPE_BYFW 0 +#define DM_TYPE_BYDRIVER 1 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 +#define TXPWRTRACK_MAX_IDX 6 + +struct swat_t { + u8 failure_cnt; + u8 try_flag; + u8 stop_trying; + + long pre_rssi; + long trying_threshold; + u8 cur_antenna; + u8 pre_antenna; + +}; + +enum FAT_STATE { + FAT_NORMAL_STATE = 0, + FAT_TRAINING_STATE = 1, +}; + +enum tag_dynamic_init_gain_operation_type_definition { + DIG_TYPE_THRESH_HIGH = 0, + DIG_TYPE_THRESH_LOW = 1, + DIG_TYPE_BACKOFF = 2, + DIG_TYPE_RX_GAIN_MIN = 3, + DIG_TYPE_RX_GAIN_MAX = 4, + DIG_TYPE_ENABLE = 5, + DIG_TYPE_DISABLE = 6, + DIG_OP_TYPE_MAX +}; + +enum dm_1r_cca_e { + CCA_1R = 0, + CCA_2R = 1, + CCA_MAX = 2, +}; + +enum dm_rf_e { + RF_SAVE = 0, + RF_NORMAL = 1, + RF_MAX = 2, +}; + +enum dm_sw_ant_switch_e { + ANS_ANTENNA_B = 1, + ANS_ANTENNA_A = 2, + ANS_ANTENNA_MAX = 3, +}; + +enum pwr_track_control_method { + BBSWING, + TXAGC +}; + +void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, + u8 *pdesc, u32 mac_id); +void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw, + u8 antsel_tr_mux, u32 mac_id, + u32 rx_pwdb_all); +void rtl88e_dm_fast_antenna_training_callback(unsigned long data); +void rtl88e_dm_init(struct ieee80211_hw *hw); +void rtl88e_dm_watchdog(struct ieee80211_hw *hw); +void rtl88e_dm_write_dig(struct ieee80211_hw *hw); +void rtl88e_dm_init_edca_turbo(struct ieee80211_hw *hw); +void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw); +void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); +void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw, + u8 type, u8 *pdirection, u32 *poutwrite_val); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c new file mode 100644 index 000000000000..629125658b87 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.c @@ -0,0 +1,815 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "fw.h" + +static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp; + + if (enable) { + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04); + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); + rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); + } else { + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); + + rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00); + } +} + +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) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 *bufferptr = (u8 *)buffer; + u32 pagenums, remainsize; + u32 page, offset; + + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size); + + _rtl88e_fill_dummy(bufferptr, &size); + + pagenums = size / FW_8192C_PAGE_SIZE; + remainsize = size % FW_8192C_PAGE_SIZE; + + if (pagenums > 8) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Page numbers should not greater then 8\n"); + } + + for (page = 0; page < pagenums; page++) { + offset = page * FW_8192C_PAGE_SIZE; + _rtl88e_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); + } +} + +static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int err = -EIO; + u32 counter = 0; + u32 value32; + + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && + (!(value32 & FWDL_CHKSUM_RPT))); + + if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "chksum report faill ! REG_MCUFWDL:0x%08x .\n", + value32); + goto exit; + } + + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); + + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + value32 |= MCUFWDL_RDY; + value32 &= ~WINTINI_RDY; + rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); + + rtl88e_firmware_selfreset(hw); + counter = 0; + + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + if (value32 & WINTINI_RDY) { + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "Polling FW ready success!! REG_MCUFWDL:0x%08x.\n", + value32); + err = 0; + goto exit; + } + + udelay(FW_8192C_POLLING_DELAY); + + } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT); + + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32); + +exit: + return err; +} + +int rtl88e_download_fw(struct ieee80211_hw *hw, + bool buse_wake_on_wlan_fw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtlwifi_firmware_header *pfwheader; + u8 *pfwdata; + u32 fwsize; + int err; + enum version_8188e version = rtlhal->version; + + if (!rtlhal->pfirmware) + return 1; + + pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; + pfwdata = rtlhal->pfirmware; + fwsize = rtlhal->fwsize; + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "normal Firmware SIZE %d\n", fwsize); + + if (IS_FW_HEADER_EXIST(pfwheader)) { + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "Firmware Version(%d), Signature(%#x), Size(%d)\n", + pfwheader->version, pfwheader->signature, + (int)sizeof(struct rtlwifi_firmware_header)); + + pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); + fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); + } + + if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); + rtl88e_firmware_selfreset(hw); + } + _rtl88e_enable_fw_download(hw, true); + _rtl88e_write_fw(hw, version, pfwdata, fwsize); + _rtl88e_enable_fw_download(hw, false); + + err = _rtl88e_fw_free_to_go(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Firmware is not ready to run!\n"); + } else { + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "Firmware is ready to run!\n"); + } + + return 0; +} + +static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 val_hmetfr; + + val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); + if (((val_hmetfr >> boxnum) & BIT(0)) == 0) + return true; + return false; +} + +static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, + u8 *cmd_b) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 boxnum; + u16 box_reg = 0, box_extreg = 0; + u8 u1b_tmp; + bool isfw_read = false; + u8 buf_index = 0; + bool write_sucess = false; + u8 wait_h2c_limmit = 100; + u8 wait_writeh2c_limit = 100; + u8 boxcontent[4], boxextcontent[4]; + u32 h2c_waitcounter = 0; + unsigned long flag; + u8 idx; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); + + while (true) { + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + if (rtlhal->h2c_setinprogress) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C set in progress! Wait to set..element_id(%d).\n", + element_id); + + while (rtlhal->h2c_setinprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, + flag); + h2c_waitcounter++; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Wait 100 us (%d times)...\n", + h2c_waitcounter); + udelay(100); + + if (h2c_waitcounter > 1000) + return; + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, + flag); + } + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + } else { + rtlhal->h2c_setinprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + break; + } + } + + while (!write_sucess) { + wait_writeh2c_limit--; + if (wait_writeh2c_limit == 0) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Write H2C fail because no trigger for FW INT!\n"); + break; + } + + boxnum = rtlhal->last_hmeboxnum; + switch (boxnum) { + case 0: + box_reg = REG_HMEBOX_0; + box_extreg = REG_HMEBOX_EXT_0; + break; + case 1: + box_reg = REG_HMEBOX_1; + box_extreg = REG_HMEBOX_EXT_1; + break; + case 2: + box_reg = REG_HMEBOX_2; + box_extreg = REG_HMEBOX_EXT_2; + break; + case 3: + box_reg = REG_HMEBOX_3; + box_extreg = REG_HMEBOX_EXT_3; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); + while (!isfw_read) { + wait_h2c_limmit--; + if (wait_h2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Waiting too long for FW read clear HMEBox(%d)!\n", + boxnum); + break; + } + + udelay(10); + + isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); + u1b_tmp = rtl_read_byte(rtlpriv, 0x130); + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", + boxnum, u1b_tmp); + } + + if (!isfw_read) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", + boxnum); + break; + } + + memset(boxcontent, 0, sizeof(boxcontent)); + memset(boxextcontent, 0, sizeof(boxextcontent)); + boxcontent[0] = element_id; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Write element_id box_reg(%4x) = %2x\n", + box_reg, element_id); + + switch (cmd_len) { + case 1: + case 2: + case 3: + /*boxcontent[0] &= ~(BIT(7));*/ + memcpy((u8 *)(boxcontent) + 1, + cmd_b + buf_index, cmd_len); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 4: + case 5: + case 6: + case 7: + /*boxcontent[0] |= (BIT(7));*/ + memcpy((u8 *)(boxextcontent), + cmd_b + buf_index+3, cmd_len-3); + memcpy((u8 *)(boxcontent) + 1, + cmd_b + buf_index, 3); + + for (idx = 0; idx < 2; idx++) { + rtl_write_byte(rtlpriv, box_extreg + idx, + boxextcontent[idx]); + } + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + + write_sucess = true; + + rtlhal->last_hmeboxnum = boxnum + 1; + if (rtlhal->last_hmeboxnum == 4) + rtlhal->last_hmeboxnum = 0; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "pHalData->last_hmeboxnum = %d\n", + rtlhal->last_hmeboxnum); + } + + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + rtlhal->h2c_setinprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); +} + +void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, u8 *cmdbuffer) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 tmp_cmdbuf[2]; + + if (!rtlhal->fw_ready) { + RT_ASSERT(false, + "return H2C cmd because of Fw download fail!!!\n"); + return; + } + + memset(tmp_cmdbuf, 0, 8); + memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); + _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); + + return; +} + +void rtl88e_firmware_selfreset(struct ieee80211_hw *hw) +{ + u8 u1b_tmp; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2))); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "8051Reset88E(): 8051 reset success\n"); + +} + +void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 }; + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 rlbm, power_state = 0; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); + + SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); + rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM=2.*/ + SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); + SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, + (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1); + SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, + ppsc->reg_max_lps_awakeintvl); + SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); + if (mode == FW_PS_ACTIVE_MODE) + power_state |= FW_PWR_STATE_ACTIVE; + else + power_state |= FW_PWR_STATE_RF_OFF; + + SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", + u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH); + rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE, + H2C_88E_PWEMODE_LENGTH, u1_h2c_set_pwrmode); +} + +void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) +{ + u8 u1_joinbssrpt_parm[1] = { 0 }; + + SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); + + rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm); +} + +void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, + u8 ap_offload_enable) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 }; + + SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable); + SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid); + SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0); + + rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD, + H2C_88E_AP_OFFLOAD_LENGTH, u1_apoffload_parm); + +} + +#define BEACON_PG 0 /* ->1 */ +#define PSPOLL_PG 2 +#define NULL_PG 3 +#define PROBERSP_PG 4 /* ->5 */ + +#define TOTAL_RESERVED_PKT_LEN 768 + +static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { + /* page 0 beacon */ + 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, + 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, + 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, + 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, + 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, + 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, + 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 1 beacon */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 2 ps-poll */ + 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 3 null */ + 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 4 probe_resp */ + 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, + 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, + 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, + 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, + 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, + 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, + 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, + 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, + 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 5 probe_resp */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct sk_buff *skb = NULL; + u32 totalpacketlen; + bool rtstatus; + u8 u1rsvdpageloc[5] = { 0 }; + bool b_dlok = false; + u8 *beacon; + u8 *p_pspoll; + u8 *nullfunc; + u8 *p_probersp; + + /*--------------------------------------------------------- + * (1) beacon + *--------------------------------------------------------- + */ + beacon = &reserved_page_packet[BEACON_PG * 128]; + SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); + SET_80211_HDR_ADDRESS3(beacon, mac->bssid); + + /*------------------------------------------------------- + * (2) ps-poll + *-------------------------------------------------------- + */ + p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; + SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); + SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); + SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); + + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); + + /*-------------------------------------------------------- + * (3) null data + *--------------------------------------------------------- + */ + nullfunc = &reserved_page_packet[NULL_PG * 128]; + SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); + SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); + SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); + + /*--------------------------------------------------------- + * (4) probe response + *---------------------------------------------------------- + */ + p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; + SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); + SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); + SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); + + totalpacketlen = TOTAL_RESERVED_PKT_LEN; + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + &reserved_page_packet[0], totalpacketlen); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + u1rsvdpageloc, 3); + + skb = dev_alloc_skb(totalpacketlen); + memcpy(skb_put(skb, totalpacketlen), + &reserved_page_packet, totalpacketlen); + + rtstatus = rtl_cmd_send_packet(hw, skb); + + if (rtstatus) + b_dlok = true; + + if (b_dlok) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Set RSVD page location to Fw.\n"); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3); + rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE, + sizeof(u1rsvdpageloc), u1rsvdpageloc); + } else + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set RSVD page location to Fw FAIL!!!!!!.\n"); +} + +/*Should check FW support p2p or not.*/ +static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) +{ + u8 u1_ctwindow_period[1] = { ctwindow}; + + rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); + +} + +void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); + struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; + u8 i; + u16 ctwindow; + u32 start_time, tsf_low; + + switch (p2p_ps_state) { + case P2P_PS_DISABLE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); + memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); + break; + case P2P_PS_ENABLE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); + /* update CTWindow value. */ + if (p2pinfo->ctwindow > 0) { + p2p_ps_offload->ctwindow_en = 1; + ctwindow = p2pinfo->ctwindow; + rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow); + } + + /* hw only support 2 set of NoA */ + for (i = 0 ; i < p2pinfo->noa_num; i++) { + /* To control the register setting for which NOA*/ + rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); + if (i == 0) + p2p_ps_offload->noa0_en = 1; + else + p2p_ps_offload->noa1_en = 1; + + /* config P2P NoA Descriptor Register */ + rtl_write_dword(rtlpriv, 0x5E0, + p2pinfo->noa_duration[i]); + rtl_write_dword(rtlpriv, 0x5E4, + p2pinfo->noa_interval[i]); + + /*Get Current TSF value */ + tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + start_time = p2pinfo->noa_start_time[i]; + if (p2pinfo->noa_count_type[i] != 1) { + while (start_time <= (tsf_low+(50*1024))) { + start_time += p2pinfo->noa_interval[i]; + if (p2pinfo->noa_count_type[i] != 255) + p2pinfo->noa_count_type[i]--; + } + } + rtl_write_dword(rtlpriv, 0x5E8, start_time); + rtl_write_dword(rtlpriv, 0x5EC, + p2pinfo->noa_count_type[i]); + } + + if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { + /* rst p2p circuit */ + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); + + p2p_ps_offload->offload_en = 1; + + if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { + p2p_ps_offload->role = 1; + p2p_ps_offload->allstasleep = -1; + } else { + p2p_ps_offload->role = 0; + } + + p2p_ps_offload->discovery = 0; + } + break; + case P2P_PS_SCAN: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); + p2p_ps_offload->discovery = 1; + break; + case P2P_PS_SCAN_DONE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); + p2p_ps_offload->discovery = 0; + p2pinfo->p2p_ps_state = P2P_PS_ENABLE; + break; + default: + break; + } + + rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1, + (u8 *)p2p_ps_offload); + +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h new file mode 100644 index 000000000000..21bd4a5337ab --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/fw.h @@ -0,0 +1,285 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C__FW__H__ +#define __RTL92C__FW__H__ + +#define FW_8192C_SIZE 0x8000 +#define FW_8192C_START_ADDRESS 0x1000 +#define FW_8192C_END_ADDRESS 0x5FFF +#define FW_8192C_PAGE_SIZE 4096 +#define FW_8192C_POLLING_DELAY 5 +#define FW_8192C_POLLING_TIMEOUT_COUNT 3000 + +#define IS_FW_HEADER_EXIST(_pfwhdr) \ + ((le16_to_cpu(_pfwhdr->signature) & 0xFFFF) == 0x88E1) +#define USE_OLD_WOWLAN_DEBUG_FW 0 + +#define H2C_88E_RSVDPAGE_LOC_LEN 5 +#define H2C_88E_PWEMODE_LENGTH 5 +#define H2C_88E_JOINBSSRPT_LENGTH 1 +#define H2C_88E_AP_OFFLOAD_LENGTH 3 +#define H2C_88E_WOWLAN_LENGTH 3 +#define H2C_88E_KEEP_ALIVE_CTRL_LENGTH 3 +#if (USE_OLD_WOWLAN_DEBUG_FW == 0) +#define H2C_88E_REMOTE_WAKE_CTRL_LEN 1 +#else +#define H2C_88E_REMOTE_WAKE_CTRL_LEN 3 +#endif +#define H2C_88E_AOAC_GLOBAL_INFO_LEN 2 +#define H2C_88E_AOAC_RSVDPAGE_LOC_LEN 7 + +/* Fw PS state for RPWM. +*BIT[2:0] = HW state +*BIT[3] = Protocol PS state, +*1: register active state , 0: register sleep state +*BIT[4] = sub-state +*/ +#define FW_PS_GO_ON BIT(0) +#define FW_PS_TX_NULL BIT(1) +#define FW_PS_RF_ON BIT(2) +#define FW_PS_REGISTER_ACTIVE BIT(3) + +#define FW_PS_DPS BIT(0) +#define FW_PS_LCLK (FW_PS_DPS) +#define FW_PS_RF_OFF BIT(1) +#define FW_PS_ALL_ON BIT(2) +#define FW_PS_ST_ACTIVE BIT(3) +#define FW_PS_ISR_ENABLE BIT(4) +#define FW_PS_IMR_ENABLE BIT(5) + + +#define FW_PS_ACK BIT(6) +#define FW_PS_TOGGLE BIT(7) + + /* 88E RPWM value*/ + /* BIT[0] = 1: 32k, 0: 40M*/ +#define FW_PS_CLOCK_OFF BIT(0) /* 32k*/ +#define FW_PS_CLOCK_ON 0 /*40M*/ + +#define FW_PS_STATE_MASK (0x0F) +#define FW_PS_STATE_HW_MASK (0x07) +/*ISR_ENABLE, IMR_ENABLE, and PS mode should be inherited.*/ +#define FW_PS_STATE_INT_MASK (0x3F) + +#define FW_PS_STATE(x) (FW_PS_STATE_MASK & (x)) +#define FW_PS_STATE_HW(x) (FW_PS_STATE_HW_MASK & (x)) +#define FW_PS_STATE_INT(x) (FW_PS_STATE_INT_MASK & (x)) +#define FW_PS_ISR_VAL(x) ((x) & 0x70) +#define FW_PS_IMR_MASK(x) ((x) & 0xDF) +#define FW_PS_KEEP_IMR(x) ((x) & 0x20) + +#define FW_PS_STATE_S0 (FW_PS_DPS) +#define FW_PS_STATE_S1 (FW_PS_LCLK) +#define FW_PS_STATE_S2 (FW_PS_RF_OFF) +#define FW_PS_STATE_S3 (FW_PS_ALL_ON) +#define FW_PS_STATE_S4 ((FW_PS_ST_ACTIVE) | (FW_PS_ALL_ON)) +/* ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE))*/ +#define FW_PS_STATE_ALL_ON_88E (FW_PS_CLOCK_ON) +/* (FW_PS_RF_ON)*/ +#define FW_PS_STATE_RF_ON_88E (FW_PS_CLOCK_ON) +/* 0x0*/ +#define FW_PS_STATE_RF_OFF_88E (FW_PS_CLOCK_ON) +/* (FW_PS_STATE_RF_OFF)*/ +#define FW_PS_STATE_RF_OFF_LOW_PWR_88E (FW_PS_CLOCK_OFF) + +#define FW_PS_STATE_ALL_ON_92C (FW_PS_STATE_S4) +#define FW_PS_STATE_RF_ON_92C (FW_PS_STATE_S3) +#define FW_PS_STATE_RF_OFF_92C (FW_PS_STATE_S2) +#define FW_PS_STATE_RF_OFF_LOW_PWR_92C (FW_PS_STATE_S1) + +/* For 88E H2C PwrMode Cmd ID 5.*/ +#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) +#define FW_PWR_STATE_RF_OFF 0 + +#define FW_PS_IS_ACK(x) ((x) & FW_PS_ACK) +#define FW_PS_IS_CLK_ON(x) ((x) & (FW_PS_RF_OFF | FW_PS_ALL_ON)) +#define FW_PS_IS_RF_ON(x) ((x) & (FW_PS_ALL_ON)) +#define FW_PS_IS_ACTIVE(x) ((x) & (FW_PS_ST_ACTIVE)) +#define FW_PS_IS_CPWM_INT(x) ((x) & 0x40) + +#define FW_CLR_PS_STATE(x) ((x) = ((x) & (0xF0))) + +#define IS_IN_LOW_POWER_STATE_88E(fwpsstate) \ + (FW_PS_STATE(fwpsstate) == FW_PS_CLOCK_OFF) + +#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) +#define FW_PWR_STATE_RF_OFF 0 + +enum rtl8188e_h2c_cmd { + H2C_88E_RSVDPAGE = 0, + H2C_88E_JOINBSSRPT = 1, + H2C_88E_SCAN = 2, + H2C_88E_KEEP_ALIVE_CTRL = 3, + H2C_88E_DISCONNECT_DECISION = 4, +#if (USE_OLD_WOWLAN_DEBUG_FW == 1) + H2C_88E_WO_WLAN = 5, +#endif + H2C_88E_INIT_OFFLOAD = 6, +#if (USE_OLD_WOWLAN_DEBUG_FW == 1) + H2C_88E_REMOTE_WAKE_CTRL = 7, +#endif + H2C_88E_AP_OFFLOAD = 8, + H2C_88E_BCN_RSVDPAGE = 9, + H2C_88E_PROBERSP_RSVDPAGE = 10, + + H2C_88E_SETPWRMODE = 0x20, + H2C_88E_PS_TUNING_PARA = 0x21, + H2C_88E_PS_TUNING_PARA2 = 0x22, + H2C_88E_PS_LPS_PARA = 0x23, + H2C_88E_P2P_PS_OFFLOAD = 024, + +#if (USE_OLD_WOWLAN_DEBUG_FW == 0) + H2C_88E_WO_WLAN = 0x80, + H2C_88E_REMOTE_WAKE_CTRL = 0x81, + H2C_88E_AOAC_GLOBAL_INFO = 0x82, + H2C_88E_AOAC_RSVDPAGE = 0x83, +#endif + /*Not defined in new 88E H2C CMD Format*/ + H2C_88E_RA_MASK, + H2C_88E_SELECTIVE_SUSPEND_ROF_CMD, + H2C_88E_P2P_PS_MODE, + H2C_88E_PSD_RESULT, + /*Not defined CTW CMD for P2P yet*/ + H2C_88E_P2P_PS_CTW_CMD, + MAX_88E_H2CCMD +}; + +#define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) + +#define SET_88E_H2CCMD_WOWLAN_FUNC_ENABLE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) +#define SET_88E_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) +#define SET_88E_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value) +#define SET_88E_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value) +#define SET_88E_H2CCMD_WOWLAN_ALL_PKT_DROP(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 4, 1, __value) +#define SET_88E_H2CCMD_WOWLAN_GPIO_ACTIVE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 5, 1, __value) +#define SET_88E_H2CCMD_WOWLAN_REKEY_WAKE_UP(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 6, 1, __value) +#define SET_88E_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 7, 1, __value) +#define SET_88E_H2CCMD_WOWLAN_GPIONUM(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) +#define SET_88E_H2CCMD_WOWLAN_GPIO_DURATION(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) + + +#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_RLBM(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 4, __value) +#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 4, 4, __value) +#define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) +#define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) +#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value) +#define GET_88E_H2CCMD_PWRMODE_PARM_MODE(__cmd) \ + LE_BITS_TO_1BYTE(__cmd, 0, 8) + +#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) + +/* AP_OFFLOAD */ +#define SET_H2CCMD_AP_OFFLOAD_ON(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value) +#define SET_H2CCMD_AP_OFFLOAD_HIDDEN(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) +#define SET_H2CCMD_AP_OFFLOAD_DENYANY(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) +#define SET_H2CCMD_AP_OFFLOAD_WAKEUP_EVT_RPT(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) + +/* Keep Alive Control*/ +#define SET_88E_H2CCMD_KEEP_ALIVE_ENABLE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) +#define SET_88E_H2CCMD_KEEP_ALIVE_ACCPEPT_USER_DEFINED(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) +#define SET_88E_H2CCMD_KEEP_ALIVE_PERIOD(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) + +/*REMOTE_WAKE_CTRL */ +#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_EN(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) +#if (USE_OLD_WOWLAN_DEBUG_FW == 0) +#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) +#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_NDP_OFFLOAD_EN(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value) +#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value) +#else +#define SET_88E_H2_REM_WAKE_ENC_ALG(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) +#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_GROUP_ENC_ALG(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) +#endif + +/* GTK_OFFLOAD */ +#define SET_88E_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value) +#define SET_88E_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) + +/* AOAC_RSVDPAGE_LOC */ +#define SET_88E_H2CCMD_AOAC_RSVD_LOC_REM_WAKE_CTRL_INFO(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd), 0, 8, __value) +#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) +#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) +#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) +#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value) + +int rtl88e_download_fw(struct ieee80211_hw *hw, + bool buse_wake_on_wlan_fw); +void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *cmdbuffer); +void rtl88e_firmware_selfreset(struct ieee80211_hw *hw); +void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); +void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); +void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, + u8 ap_offload_enable); +void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); +void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c new file mode 100644 index 000000000000..8ee83b093c0d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.c @@ -0,0 +1,2599 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../regd.h" +#include "../cam.h" +#include "../ps.h" +#include "../pci.h" +#include "../pwrseqcmd.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "led.h" +#include "hw.h" +#include "pwrseq.h" + +#define LLT_CONFIG 5 + +static void _rtl88ee_set_bcn_ctrl_reg(struct ieee80211_hw *hw, + u8 set_bits, u8 clear_bits) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpci->reg_bcn_ctrl_val |= set_bits; + rtlpci->reg_bcn_ctrl_val &= ~clear_bits; + + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); +} + +static void _rtl88ee_stop_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl88ee_resume_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte |= BIT(0); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl88ee_enable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(1)); +} + +static void _rtl88ee_return_beacon_queue_skb(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; + unsigned long flags; + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + while (skb_queue_len(&ring->queue)) { + struct rtl_tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb = __skb_dequeue(&ring->queue); + + pci_unmap_single(rtlpci->pdev, + rtlpriv->cfg->ops->get_desc( + (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), + skb->len, PCI_DMA_TODEVICE); + kfree_skb(skb); + ring->idx = (ring->idx + 1) % ring->entries; + } + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); +} + +static void _rtl88ee_disable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl88ee_set_bcn_ctrl_reg(hw, BIT(1), 0); +} + +static void _rtl88ee_set_fw_clock_on(struct ieee80211_hw *hw, + u8 rpwm_val, bool b_need_turn_off_ckk) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool b_support_remote_wake_up; + u32 count = 0, isr_regaddr, content; + bool schedule_timer = b_need_turn_off_ckk; + rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, + (u8 *)(&b_support_remote_wake_up)); + + if (!rtlhal->fw_ready) + return; + if (!rtlpriv->psc.fw_current_inpsmode) + return; + + while (1) { + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + if (rtlhal->fw_clk_change_in_progress) { + while (rtlhal->fw_clk_change_in_progress) { + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + count++; + udelay(100); + if (count > 1000) + return; + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + } + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + } else { + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + break; + } + } + + if (IS_IN_LOW_POWER_STATE_88E(rtlhal->fw_ps_state)) { + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, &rpwm_val); + if (FW_PS_IS_ACK(rpwm_val)) { + isr_regaddr = REG_HISR; + content = rtl_read_dword(rtlpriv, isr_regaddr); + while (!(content & IMR_CPWM) && (count < 500)) { + udelay(50); + count++; + content = rtl_read_dword(rtlpriv, isr_regaddr); + } + + if (content & IMR_CPWM) { + rtl_write_word(rtlpriv, isr_regaddr, 0x0100); + rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_88E; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Receive CPWM INT!!! Set pHalData->FwPSState = %X\n", + rtlhal->fw_ps_state); + } + } + + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + if (schedule_timer) { + mod_timer(&rtlpriv->works.fw_clockoff_timer, + jiffies + MSECS(10)); + } + + } else { + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + } +} + +static void _rtl88ee_set_fw_clock_off(struct ieee80211_hw *hw, + u8 rpwm_val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + enum rf_pwrstate rtstate; + bool schedule_timer = false; + u8 queue; + + if (!rtlhal->fw_ready) + return; + if (!rtlpriv->psc.fw_current_inpsmode) + return; + if (!rtlhal->allow_sw_to_change_hwclc) + return; + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate)); + if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF) + return; + + for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) { + ring = &rtlpci->tx_ring[queue]; + if (skb_queue_len(&ring->queue)) { + schedule_timer = true; + break; + } + } + + if (schedule_timer) { + mod_timer(&rtlpriv->works.fw_clockoff_timer, + jiffies + MSECS(10)); + return; + } + + if (FW_PS_STATE(rtlhal->fw_ps_state) != + FW_PS_STATE_RF_OFF_LOW_PWR_88E) { + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + if (!rtlhal->fw_clk_change_in_progress) { + rtlhal->fw_clk_change_in_progress = true; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); + rtl_write_word(rtlpriv, REG_HISR, 0x0100); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + &rpwm_val); + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + } else { + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + mod_timer(&rtlpriv->works.fw_clockoff_timer, + jiffies + MSECS(10)); + } + } +} + +static void _rtl88ee_set_fw_ps_rf_on(struct ieee80211_hw *hw) +{ + u8 rpwm_val = 0; + + rpwm_val |= (FW_PS_STATE_RF_OFF_88E | FW_PS_ACK); + _rtl88ee_set_fw_clock_on(hw, rpwm_val, true); +} + +static void _rtl88ee_set_fw_ps_rf_off_low_power(struct ieee80211_hw *hw) +{ + u8 rpwm_val = 0; + rpwm_val |= FW_PS_STATE_RF_OFF_LOW_PWR_88E; + _rtl88ee_set_fw_clock_off(hw, rpwm_val); +} +void rtl88ee_fw_clk_off_timer_callback(unsigned long data) +{ + struct ieee80211_hw *hw = (struct ieee80211_hw *)data; + + _rtl88ee_set_fw_ps_rf_off_low_power(hw); +} + +static void _rtl88ee_fwlps_leave(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool fw_current_inps = false; + u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE; + + if (ppsc->low_power_enable) { + rpwm_val = (FW_PS_STATE_ALL_ON_88E|FW_PS_ACK);/* RF on */ + _rtl88ee_set_fw_clock_on(hw, rpwm_val, false); + rtlhal->allow_sw_to_change_hwclc = false; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + &fw_pwrmode); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + } else { + rpwm_val = FW_PS_STATE_ALL_ON_88E; /* RF on */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, &rpwm_val); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + &fw_pwrmode); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + } +} + +static void _rtl88ee_fwlps_enter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool fw_current_inps = true; + u8 rpwm_val; + + if (ppsc->low_power_enable) { + rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR_88E; /* RF off */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + &ppsc->fwctrl_psmode); + rtlhal->allow_sw_to_change_hwclc = true; + _rtl88ee_set_fw_clock_off(hw, rpwm_val); + } else { + rpwm_val = FW_PS_STATE_RF_OFF_88E; /* RF off */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + &ppsc->fwctrl_psmode); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, &rpwm_val); + } +} + +void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + switch (variable) { + case HW_VAR_RCR: + *((u32 *)(val)) = rtlpci->receive_config; + break; + case HW_VAR_RF_STATE: + *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; + break; + case HW_VAR_FWLPS_RF_ON:{ + enum rf_pwrstate rfstate; + u32 val_rcr; + + rtlpriv->cfg->ops->get_hw_reg(hw, + HW_VAR_RF_STATE, + (u8 *)(&rfstate)); + if (rfstate == ERFOFF) { + *((bool *)(val)) = true; + } else { + val_rcr = rtl_read_dword(rtlpriv, REG_RCR); + val_rcr &= 0x00070000; + if (val_rcr) + *((bool *)(val)) = false; + else + *((bool *)(val)) = true; + } + break; } + case HW_VAR_FW_PSMODE_STATUS: + *((bool *)(val)) = ppsc->fw_current_inpsmode; + break; + case HW_VAR_CORRECT_TSF:{ + u64 tsf; + u32 *ptsf_low = (u32 *)&tsf; + u32 *ptsf_high = ((u32 *)&tsf) + 1; + + *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); + *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + *((u64 *)(val)) = tsf; + break; } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process %x\n", variable); + break; + } +} + +void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 idx; + + switch (variable) { + case HW_VAR_ETHER_ADDR: + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_MACID + idx), + val[idx]); + } + break; + case HW_VAR_BASIC_RATE:{ + u16 b_rate_cfg = ((u16 *)val)[0]; + u8 rate_index = 0; + b_rate_cfg = b_rate_cfg & 0x15f; + b_rate_cfg |= 0x01; + rtl_write_byte(rtlpriv, REG_RRSR, b_rate_cfg & 0xff); + rtl_write_byte(rtlpriv, REG_RRSR + 1, + (b_rate_cfg >> 8) & 0xff); + while (b_rate_cfg > 0x1) { + b_rate_cfg = (b_rate_cfg >> 1); + rate_index++; + } + rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, + rate_index); + break; + } + case HW_VAR_BSSID: + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_BSSID + idx), + val[idx]); + } + break; + case HW_VAR_SIFS: + rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); + rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); + + rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); + rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); + + if (!mac->ht_enable) + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, + 0x0e0e); + else + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, + *((u16 *)val)); + break; + case HW_VAR_SLOT_TIME:{ + u8 e_aci; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "HW_VAR_SLOT_TIME %x\n", val[0]); + + rtl_write_byte(rtlpriv, REG_SLOT, val[0]); + + for (e_aci = 0; e_aci < AC_MAX; e_aci++) { + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + &e_aci); + } + break; + } + case HW_VAR_ACK_PREAMBLE:{ + u8 reg_tmp; + u8 short_preamble = (bool)*val; + reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL+2); + if (short_preamble) { + reg_tmp |= 0x02; + rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + + 2, reg_tmp); + } else { + reg_tmp |= 0xFD; + rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + + 2, reg_tmp); + } + break; } + case HW_VAR_WPA_CONFIG: + rtl_write_byte(rtlpriv, REG_SECCFG, *val); + break; + case HW_VAR_AMPDU_MIN_SPACE:{ + u8 min_spacing_to_set; + u8 sec_min_space; + + min_spacing_to_set = *val; + if (min_spacing_to_set <= 7) { + sec_min_space = 0; + + if (min_spacing_to_set < sec_min_space) + min_spacing_to_set = sec_min_space; + + mac->min_space_cfg = ((mac->min_space_cfg & + 0xf8) | + min_spacing_to_set); + + *val = min_spacing_to_set; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", + mac->min_space_cfg); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + } + break; } + case HW_VAR_SHORTGI_DENSITY:{ + u8 density_to_set; + + density_to_set = *val; + mac->min_space_cfg |= (density_to_set << 3); + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_SHORTGI_DENSITY: %#x\n", + mac->min_space_cfg); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + break; + } + case HW_VAR_AMPDU_FACTOR:{ + u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; + u8 factor_toset; + u8 *p_regtoset = NULL; + u8 index = 0; + + p_regtoset = regtoset_normal; + + factor_toset = *val; + if (factor_toset <= 3) { + factor_toset = (1 << (factor_toset + 2)); + if (factor_toset > 0xf) + factor_toset = 0xf; + + for (index = 0; index < 4; index++) { + if ((p_regtoset[index] & 0xf0) > + (factor_toset << 4)) + p_regtoset[index] = + (p_regtoset[index] & 0x0f) | + (factor_toset << 4); + + if ((p_regtoset[index] & 0x0f) > + factor_toset) + p_regtoset[index] = + (p_regtoset[index] & 0xf0) | + (factor_toset); + + rtl_write_byte(rtlpriv, + (REG_AGGLEN_LMT + index), + p_regtoset[index]); + + } + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_FACTOR: %#x\n", + factor_toset); + } + break; } + case HW_VAR_AC_PARAM:{ + u8 e_aci = *val; + rtl88e_dm_init_edca_turbo(hw); + + if (rtlpci->acm_method != EACMWAY2_SW) + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_ACM_CTRL, + &e_aci); + break; } + case HW_VAR_ACM_CTRL:{ + u8 e_aci = *val; + union aci_aifsn *p_aci_aifsn = + (union aci_aifsn *)(&(mac->ac[0].aifs)); + u8 acm = p_aci_aifsn->f.acm; + u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); + + acm_ctrl = acm_ctrl | + ((rtlpci->acm_method == 2) ? 0x0 : 0x1); + + if (acm) { + switch (e_aci) { + case AC0_BE: + acm_ctrl |= ACMHW_BEQEN; + break; + case AC2_VI: + acm_ctrl |= ACMHW_VIQEN; + break; + case AC3_VO: + acm_ctrl |= ACMHW_VOQEN; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", + acm); + break; + } + } else { + switch (e_aci) { + case AC0_BE: + acm_ctrl &= (~ACMHW_BEQEN); + break; + case AC2_VI: + acm_ctrl &= (~ACMHW_VIQEN); + break; + case AC3_VO: + acm_ctrl &= (~ACMHW_VOQEN); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + } + + RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, + "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", + acm_ctrl); + rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); + break; } + case HW_VAR_RCR: + rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); + rtlpci->receive_config = ((u32 *)(val))[0]; + break; + case HW_VAR_RETRY_LIMIT:{ + u8 retry_limit = *val; + + rtl_write_word(rtlpriv, REG_RL, + retry_limit << RETRY_LIMIT_SHORT_SHIFT | + retry_limit << RETRY_LIMIT_LONG_SHIFT); + break; } + case HW_VAR_DUAL_TSF_RST: + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); + break; + case HW_VAR_EFUSE_BYTES: + rtlefuse->efuse_usedbytes = *((u16 *)val); + break; + case HW_VAR_EFUSE_USAGE: + rtlefuse->efuse_usedpercentage = *val; + break; + case HW_VAR_IO_CMD: + rtl88e_phy_set_io_cmd(hw, (*(enum io_type *)val)); + break; + case HW_VAR_SET_RPWM:{ + u8 rpwm_val; + + rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); + udelay(1); + + if (rpwm_val & BIT(7)) { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, *val); + } else { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, *val | BIT(7)); + } + break; } + case HW_VAR_H2C_FW_PWRMODE: + rtl88e_set_fw_pwrmode_cmd(hw, *val); + break; + case HW_VAR_FW_PSMODE_STATUS: + ppsc->fw_current_inpsmode = *((bool *)val); + break; + case HW_VAR_RESUME_CLK_ON: + _rtl88ee_set_fw_ps_rf_on(hw); + break; + case HW_VAR_FW_LPS_ACTION:{ + bool enter_fwlps = *((bool *)val); + + if (enter_fwlps) + _rtl88ee_fwlps_enter(hw); + else + _rtl88ee_fwlps_leave(hw); + + break; } + case HW_VAR_H2C_FW_JOINBSSRPT:{ + u8 mstatus = *val; + u8 tmp_regcr, tmp_reg422, bcnvalid_reg; + u8 count = 0, dlbcn_count = 0; + bool b_recover = false; + + if (mstatus == RT_MEDIA_CONNECT) { + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, + NULL); + + tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, + (tmp_regcr | BIT(0))); + + _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); + _rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0); + + tmp_reg422 = + rtl_read_byte(rtlpriv, + REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, + tmp_reg422 & (~BIT(6))); + if (tmp_reg422 & BIT(6)) + b_recover = true; + + do { + bcnvalid_reg = rtl_read_byte(rtlpriv, + REG_TDECTRL+2); + rtl_write_byte(rtlpriv, REG_TDECTRL+2, + (bcnvalid_reg | BIT(0))); + _rtl88ee_return_beacon_queue_skb(hw); + + rtl88e_set_fw_rsvdpagepkt(hw, 0); + bcnvalid_reg = rtl_read_byte(rtlpriv, + REG_TDECTRL+2); + count = 0; + while (!(bcnvalid_reg & BIT(0)) && count < 20) { + count++; + udelay(10); + bcnvalid_reg = + rtl_read_byte(rtlpriv, REG_TDECTRL+2); + } + dlbcn_count++; + } while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5); + + if (bcnvalid_reg & BIT(0)) + rtl_write_byte(rtlpriv, REG_TDECTRL+2, BIT(0)); + + _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); + _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); + + if (b_recover) { + rtl_write_byte(rtlpriv, + REG_FWHW_TXQ_CTRL + 2, + tmp_reg422); + } + + rtl_write_byte(rtlpriv, REG_CR + 1, + (tmp_regcr & ~(BIT(0)))); + } + rtl88e_set_fw_joinbss_report_cmd(hw, (*(u8 *)val)); + break; } + case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: + rtl88e_set_p2p_ps_offload_cmd(hw, *val); + break; + case HW_VAR_AID:{ + u16 u2btmp; + + u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); + u2btmp &= 0xC000; + rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | + mac->assoc_id)); + break; } + case HW_VAR_CORRECT_TSF:{ + u8 btype_ibss = *val; + + if (btype_ibss) + _rtl88ee_stop_tx_beacon(hw); + + _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); + + rtl_write_dword(rtlpriv, REG_TSFTR, + (u32)(mac->tsf & 0xffffffff)); + rtl_write_dword(rtlpriv, REG_TSFTR + 4, + (u32)((mac->tsf >> 32) & 0xffffffff)); + + _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); + + if (btype_ibss) + _rtl88ee_resume_tx_beacon(hw); + break; } + case HW_VAR_KEEP_ALIVE: { + u8 array[2]; + + array[0] = 0xff; + array[1] = *((u8 *)val); + rtl88e_fill_h2c_cmd(hw, H2C_88E_KEEP_ALIVE_CTRL, + 2, array); + break; } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process %x\n", variable); + break; + } +} + +static bool _rtl88ee_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool status = true; + long count = 0; + u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | + _LLT_OP(_LLT_WRITE_ACCESS); + + rtl_write_dword(rtlpriv, REG_LLT_INIT, value); + + do { + value = rtl_read_dword(rtlpriv, REG_LLT_INIT); + if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) + break; + + if (count > POLLING_LLT_THRESHOLD) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to polling write LLT done at address %d!\n", + address); + status = false; + break; + } + } while (++count); + + return status; +} + +static bool _rtl88ee_llt_table_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + unsigned short i; + u8 txpktbuf_bndy; + u8 maxpage; + bool status; + + maxpage = 0xAF; + txpktbuf_bndy = 0xAB; + + rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x01); + rtl_write_dword(rtlpriv, REG_RQPN, 0x80730d29); + + /*0x2600 MaxRxBuff=10k-max(TxReportSize(64*8), WOLPattern(16*24)) */ + rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x25FF0000 | txpktbuf_bndy)); + rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_PBP, 0x11); + rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); + + for (i = 0; i < (txpktbuf_bndy - 1); i++) { + status = _rtl88ee_llt_write(hw, i, i + 1); + if (true != status) + return status; + } + + status = _rtl88ee_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); + if (true != status) + return status; + + for (i = txpktbuf_bndy; i < maxpage; i++) { + status = _rtl88ee_llt_write(hw, i, (i + 1)); + if (true != status) + return status; + } + + status = _rtl88ee_llt_write(hw, maxpage, txpktbuf_bndy); + if (true != status) + return status; + + return true; +} + +static void _rtl88ee_gen_refresh_led_state(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + + if (rtlpriv->rtlhal.up_first_time) + return; + + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) + rtl88ee_sw_led_on(hw, pLed0); + else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) + rtl88ee_sw_led_on(hw, pLed0); + else + rtl88ee_sw_led_off(hw, pLed0); +} + +static bool _rtl88ee_init_mac(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + u8 bytetmp; + u16 wordtmp; + + /*Disable XTAL OUTPUT for power saving. YJ,add,111206. */ + bytetmp = rtl_read_byte(rtlpriv, REG_XCK_OUT_CTRL) & (~BIT(0)); + rtl_write_byte(rtlpriv, REG_XCK_OUT_CTRL, bytetmp); + /*Auto Power Down to CHIP-off State*/ + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7)); + rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); + + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); + /* HW Power on sequence */ + if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, + PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, + RTL8188EE_NIC_ENABLE_FLOW)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "init MAC Fail as rtl_hal_pwrseqcmdparsing\n"); + return false; + } + + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4); + rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp); + + bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2); + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+2, bytetmp|BIT(2)); + + bytetmp = rtl_read_byte(rtlpriv, REG_WATCH_DOG+1); + rtl_write_byte(rtlpriv, REG_WATCH_DOG+1, bytetmp|BIT(7)); + + bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1, bytetmp|BIT(1)); + + bytetmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL); + rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, bytetmp|BIT(1)|BIT(0)); + rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL+1, 2); + rtl_write_word(rtlpriv, REG_TX_RPT_TIME, 0xcdf0); + + /*Add for wake up online*/ + bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR); + + rtl_write_byte(rtlpriv, REG_SYS_CLKR, bytetmp|BIT(3)); + bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG+1); + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG+1, (bytetmp & (~BIT(4)))); + rtl_write_byte(rtlpriv, 0x367, 0x80); + + rtl_write_word(rtlpriv, REG_CR, 0x2ff); + rtl_write_byte(rtlpriv, REG_CR+1, 0x06); + rtl_write_byte(rtlpriv, MSR, 0x00); + + if (!rtlhal->mac_func_enable) { + if (_rtl88ee_llt_table_init(hw) == false) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "LLT table init fail\n"); + return false; + } + } + rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); + rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff); + + wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); + wordtmp &= 0xf; + wordtmp |= 0xE771; + rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); + + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xffff); + rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); + + rtl_write_dword(rtlpriv, REG_BCNQ_DESA, + ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_MGQ_DESA, + (u64) rtlpci->tx_ring[MGNT_QUEUE].dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VOQ_DESA, + (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VIQ_DESA, + (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BEQ_DESA, + (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BKQ_DESA, + (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_HQ_DESA, + (u64) rtlpci->tx_ring[HIGH_QUEUE].dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_RX_DESA, + (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma & + DMA_BIT_MASK(32)); + + /* if we want to support 64 bit DMA, we should set it here, + * but now we do not support 64 bit DMA + */ + rtl_write_dword(rtlpriv, REG_INT_MIG, 0); + + rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0);/*Enable RX DMA */ + + if (rtlhal->earlymode_enable) {/*Early mode enable*/ + bytetmp = rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL); + bytetmp |= 0x1f; + rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, bytetmp); + rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL+3, 0x81); + } + _rtl88ee_gen_refresh_led_state(hw); + return true; +} + +static void _rtl88ee_hw_configure(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 reg_bw_opmode; + u32 reg_ratr, reg_prsr; + + reg_bw_opmode = BW_OPMODE_20MHZ; + reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | + RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + + rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr); + rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); +} + +static void _rtl88ee_enable_aspm_back_door(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 tmp1byte = 0; + u32 tmp4byte = 0, count = 0; + + rtl_write_word(rtlpriv, 0x354, 0x8104); + rtl_write_word(rtlpriv, 0x358, 0x24); + + rtl_write_word(rtlpriv, 0x350, 0x70c); + rtl_write_byte(rtlpriv, 0x352, 0x2); + tmp1byte = rtl_read_byte(rtlpriv, 0x352); + count = 0; + while (tmp1byte && count < 20) { + udelay(10); + tmp1byte = rtl_read_byte(rtlpriv, 0x352); + count++; + } + if (0 == tmp1byte) { + tmp4byte = rtl_read_dword(rtlpriv, 0x34c); + rtl_write_dword(rtlpriv, 0x348, tmp4byte|BIT(31)); + rtl_write_word(rtlpriv, 0x350, 0xf70c); + rtl_write_byte(rtlpriv, 0x352, 0x1); + } + + tmp1byte = rtl_read_byte(rtlpriv, 0x352); + count = 0; + while (tmp1byte && count < 20) { + udelay(10); + tmp1byte = rtl_read_byte(rtlpriv, 0x352); + count++; + } + + rtl_write_word(rtlpriv, 0x350, 0x718); + rtl_write_byte(rtlpriv, 0x352, 0x2); + tmp1byte = rtl_read_byte(rtlpriv, 0x352); + count = 0; + while (tmp1byte && count < 20) { + udelay(10); + tmp1byte = rtl_read_byte(rtlpriv, 0x352); + count++; + } + + if (ppsc->support_backdoor || (0 == tmp1byte)) { + tmp4byte = rtl_read_dword(rtlpriv, 0x34c); + rtl_write_dword(rtlpriv, 0x348, tmp4byte|BIT(11)|BIT(12)); + rtl_write_word(rtlpriv, 0x350, 0xf718); + rtl_write_byte(rtlpriv, 0x352, 0x1); + } + + tmp1byte = rtl_read_byte(rtlpriv, 0x352); + count = 0; + while (tmp1byte && count < 20) { + udelay(10); + tmp1byte = rtl_read_byte(rtlpriv, 0x352); + count++; + } +} + +void rtl88ee_enable_hw_security_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 sec_reg_value; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", + rtlpriv->sec.pairwise_enc_algorithm, + rtlpriv->sec.group_enc_algorithm); + + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "not open hw encryption\n"); + return; + } + + sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; + + if (rtlpriv->sec.use_defaultkey) { + sec_reg_value |= SCR_TXUSEDK; + sec_reg_value |= SCR_RXUSEDK; + } + + sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); + + rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "The SECR-value %x\n", sec_reg_value); + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); +} + +int rtl88ee_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + bool rtstatus = true; + int err = 0; + u8 tmp_u1b, u1byte; + unsigned long flags; + + rtlpriv->rtlhal.being_init_adapter = true; + /* As this function can take a very long time (up to 350 ms) + * and can be called with irqs disabled, reenable the irqs + * to let the other devices continue being serviced. + * + * It is safe doing so since our own interrupts will only be enabled + * in a subsequent step. + */ + local_save_flags(flags); + local_irq_enable(); + rtlhal->fw_ready = false; + + rtlpriv->intf_ops->disable_aspm(hw); + + tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CLKR+1); + u1byte = rtl_read_byte(rtlpriv, REG_CR); + if ((tmp_u1b & BIT(3)) && (u1byte != 0 && u1byte != 0xEA)) { + rtlhal->mac_func_enable = true; + } else { + rtlhal->mac_func_enable = false; + rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E; + } + + rtstatus = _rtl88ee_init_mac(hw); + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); + err = 1; + goto exit; + } + + err = rtl88e_download_fw(hw, false); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW now..\n"); + err = 1; + goto exit; + } + rtlhal->fw_ready = true; + /*fw related variable initialize */ + rtlhal->last_hmeboxnum = 0; + rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E; + rtlhal->fw_clk_change_in_progress = false; + rtlhal->allow_sw_to_change_hwclc = false; + ppsc->fw_current_inpsmode = false; + + rtl88e_phy_mac_config(hw); + /* because last function modify RCR, so we update + * rcr var here, or TP will unstable for receive_config + * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx + * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 + */ + rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + + rtl88e_phy_bb_config(hw); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); + + rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; + rtl88e_phy_rf_config(hw); + + rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtlphy->rfreg_chnlval[0] = rtlphy->rfreg_chnlval[0] & 0xfff00fff; + + _rtl88ee_hw_configure(hw); + rtl_cam_reset_all_entry(hw); + rtl88ee_enable_hw_security_config(hw); + + rtlhal->mac_func_enable = true; + ppsc->rfpwr_state = ERFON; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); + _rtl88ee_enable_aspm_back_door(hw); + rtlpriv->intf_ops->enable_aspm(hw); + + if (ppsc->rfpwr_state == ERFON) { + if ((rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) || + ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) && + (rtlhal->oem_id == RT_CID_819X_HP))) { + rtl88e_phy_set_rfpath_switch(hw, true); + rtlpriv->dm.fat_table.rx_idle_ant = MAIN_ANT; + } else { + rtl88e_phy_set_rfpath_switch(hw, false); + rtlpriv->dm.fat_table.rx_idle_ant = AUX_ANT; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "rx idle ant %s\n", + (rtlpriv->dm.fat_table.rx_idle_ant == MAIN_ANT) ? + ("MAIN_ANT") : ("AUX_ANT")); + + if (rtlphy->iqk_initialized) { + rtl88e_phy_iq_calibrate(hw, true); + } else { + rtl88e_phy_iq_calibrate(hw, false); + rtlphy->iqk_initialized = true; + } + + rtl88e_dm_check_txpower_tracking(hw); + rtl88e_phy_lc_calibrate(hw); + } + + tmp_u1b = efuse_read_1byte(hw, 0x1FA); + if (!(tmp_u1b & BIT(0))) { + rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "PA BIAS path A\n"); + } + + if (!(tmp_u1b & BIT(4))) { + tmp_u1b = rtl_read_byte(rtlpriv, 0x16); + tmp_u1b &= 0x0F; + rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80); + udelay(10); + rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "under 1.5V\n"); + } + rtl_write_byte(rtlpriv, REG_NAV_CTRL+2, ((30000+127)/128)); + rtl88e_dm_init(hw); +exit: + local_irq_restore(flags); + rtlpriv->rtlhal.being_init_adapter = false; + return err; +} + +static enum version_8188e _rtl88ee_read_chip_version(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + enum version_8188e version = VERSION_UNKNOWN; + u32 value32; + + value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); + if (value32 & TRP_VAUX_EN) { + version = (enum version_8188e) VERSION_TEST_CHIP_88E; + } else { + version = NORMAL_CHIP; + version = version | ((value32 & TYPE_ID) ? RF_TYPE_2T2R : 0); + version = version | ((value32 & VENDOR_ID) ? + CHIP_VENDOR_UMC : 0); + } + + rtlphy->rf_type = RF_1T1R; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ? + "RF_2T2R" : "RF_1T1R"); + + return version; +} + +static int _rtl88ee_set_media_status(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_msr = rtl_read_byte(rtlpriv, MSR) & 0xfc; + enum led_ctl_mode ledaction = LED_CTL_NO_LINK; + u8 mode = MSR_NOLINK; + + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + mode = MSR_NOLINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to NO LINK!\n"); + break; + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + mode = MSR_ADHOC; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to Ad Hoc!\n"); + break; + case NL80211_IFTYPE_STATION: + mode = MSR_INFRA; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to STA!\n"); + break; + case NL80211_IFTYPE_AP: + mode = MSR_AP; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to AP!\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Network type %d not support!\n", type); + return 1; + break; + } + + /* MSR_INFRA == Link in infrastructure network; + * MSR_ADHOC == Link in ad hoc network; + * Therefore, check link state is necessary. + * + * MSR_AP == AP mode; link state is not cared here. + */ + if (mode != MSR_AP && rtlpriv->mac80211.link_state < MAC80211_LINKED) { + mode = MSR_NOLINK; + ledaction = LED_CTL_NO_LINK; + } + + if (mode == MSR_NOLINK || mode == MSR_INFRA) { + _rtl88ee_stop_tx_beacon(hw); + _rtl88ee_enable_bcn_sub_func(hw); + } else if (mode == MSR_ADHOC || mode == MSR_AP) { + _rtl88ee_resume_tx_beacon(hw); + _rtl88ee_disable_bcn_sub_func(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", + mode); + } + + rtl_write_byte(rtlpriv, MSR, bt_msr | mode); + rtlpriv->cfg->ops->led_control(hw, ledaction); + if (mode == MSR_AP) + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); + else + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); + return 0; +} + +void rtl88ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 reg_rcr = rtlpci->receive_config; + + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + if (check_bssid == true) { + reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, + (u8 *)(®_rcr)); + _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); + } else if (check_bssid == false) { + reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); + _rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_RCR, (u8 *)(®_rcr)); + } + +} + +int rtl88ee_set_network_type(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (_rtl88ee_set_media_status(hw, type)) + return -EOPNOTSUPP; + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP && + type != NL80211_IFTYPE_MESH_POINT) + rtl88ee_set_check_bssid(hw, true); + } else { + rtl88ee_set_check_bssid(hw, false); + } + + return 0; +} + +/* don't set REG_EDCA_BE_PARAM here + * because mac80211 will send pkt when scan + */ +void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtl88e_dm_init_edca_turbo(hw); + switch (aci) { + case AC1_BK: + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); + break; + case AC0_BE: + break; + case AC2_VI: + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); + break; + case AC3_VO: + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); + break; + default: + RT_ASSERT(false, "invalid aci: %d !\n", aci); + break; + } +} + +void rtl88ee_enable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, + rtlpci->irq_mask[0] & 0xFFFFFFFF); + rtl_write_dword(rtlpriv, REG_HIMRE, + rtlpci->irq_mask[1] & 0xFFFFFFFF); + rtlpci->irq_enabled = true; + /* there are some C2H CMDs have been sent + * before system interrupt is enabled, e.g., C2H, CPWM. + * So we need to clear all C2H events that FW has notified, + * otherwise FW won't schedule any commands anymore. + */ + rtl_write_byte(rtlpriv, REG_C2HEVT_CLEAR, 0); + /*enable system interrupt*/ + rtl_write_dword(rtlpriv, REG_HSIMR, + rtlpci->sys_irq_mask & 0xFFFFFFFF); +} + +void rtl88ee_disable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED); + rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED); + rtlpci->irq_enabled = false; + /*synchronize_irq(rtlpci->pdev->irq);*/ +} + +static void _rtl88ee_poweroff_adapter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 u1b_tmp; + u32 count = 0; + rtlhal->mac_func_enable = false; + rtlpriv->intf_ops->enable_aspm(hw); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "POWER OFF adapter\n"); + u1b_tmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL); + rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, u1b_tmp & (~BIT(1))); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + while (!(u1b_tmp & BIT(1)) && (count++ < 100)) { + udelay(10); + u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + count++; + } + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0xFF); + + rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, + RTL8188EE_NIC_LPS_ENTER_FLOW); + + rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); + + if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready) + rtl88e_firmware_selfreset(hw); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_32K_CTRL); + rtl_write_byte(rtlpriv, REG_32K_CTRL, (u1b_tmp & (~BIT(0)))); + + rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, RTL8188EE_NIC_DISABLE_FLOW); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp & (~BIT(3)))); + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp | BIT(3))); + + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E); + + u1b_tmp = rtl_read_byte(rtlpriv, GPIO_IN); + rtl_write_byte(rtlpriv, GPIO_OUT, u1b_tmp); + rtl_write_byte(rtlpriv, GPIO_IO_SEL, 0x7F); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); + rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL, (u1b_tmp << 4) | u1b_tmp); + u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL+1); + rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL+1, u1b_tmp | 0x0F); + + rtl_write_dword(rtlpriv, REG_GPIO_IO_SEL_2+2, 0x00080808); +} + +void rtl88ee_card_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + enum nl80211_iftype opmode; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RTL8188ee card disable\n"); + + mac->link_state = MAC80211_NOLINK; + opmode = NL80211_IFTYPE_UNSPECIFIED; + + _rtl88ee_set_media_status(hw, opmode); + + if (rtlpriv->rtlhal.driver_is_goingto_unload || + ppsc->rfoff_reason > RF_CHANGE_BY_PS) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + _rtl88ee_poweroff_adapter(hw); + + /* after power off we should do iqk again */ + rtlpriv->phy.iqk_initialized = false; +} + +void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; + rtl_write_dword(rtlpriv, ISR, *p_inta); + + *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; + rtl_write_dword(rtlpriv, REG_HISRE, *p_intb); + +} + +void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u16 bcn_interval, atim_window; + + bcn_interval = mac->beacon_interval; + atim_window = 2; /*FIX MERGE */ + rtl88ee_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); + rtl_write_byte(rtlpriv, 0x606, 0x30); + rtlpci->reg_bcn_ctrl_val |= BIT(3); + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); + /*rtl88ee_enable_interrupt(hw);*/ +} + +void rtl88ee_set_beacon_interval(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval = mac->beacon_interval; + + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "beacon_interval:%d\n", bcn_interval); + /*rtl88ee_disable_interrupt(hw);*/ + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + /*rtl88ee_enable_interrupt(hw);*/ +} + +void rtl88ee_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, + "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); + + if (add_msr) + rtlpci->irq_mask[0] |= add_msr; + if (rm_msr) + rtlpci->irq_mask[0] &= (~rm_msr); + rtl88ee_disable_interrupt(hw); + rtl88ee_enable_interrupt(hw); +} + +static u8 _rtl88e_get_chnl_group(u8 chnl) +{ + u8 group = 0; + + if (chnl < 3) + group = 0; + else if (chnl < 6) + group = 1; + else if (chnl < 9) + group = 2; + else if (chnl < 12) + group = 3; + else if (chnl < 14) + group = 4; + else if (chnl == 14) + group = 5; + + return group; +} + +static void set_24g_base(struct txpower_info_2g *pwrinfo24g, u32 rfpath) +{ + int group, txcnt; + + for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { + pwrinfo24g->index_cck_base[rfpath][group] = 0x2D; + pwrinfo24g->index_bw40_base[rfpath][group] = 0x2D; + } + for (txcnt = 0; txcnt < MAX_TX_COUNT; txcnt++) { + if (txcnt == 0) { + pwrinfo24g->bw20_diff[rfpath][0] = 0x02; + pwrinfo24g->ofdm_diff[rfpath][0] = 0x04; + } else { + pwrinfo24g->bw20_diff[rfpath][txcnt] = 0xFE; + pwrinfo24g->bw40_diff[rfpath][txcnt] = 0xFE; + pwrinfo24g->cck_diff[rfpath][txcnt] = 0xFE; + pwrinfo24g->ofdm_diff[rfpath][txcnt] = 0xFE; + } + } +} + +static void read_power_value_fromprom(struct ieee80211_hw *hw, + struct txpower_info_2g *pwrinfo24g, + struct txpower_info_5g *pwrinfo5g, + bool autoload_fail, u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 rfpath, eeaddr = EEPROM_TX_PWR_INX, group, txcnt = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "hal_ReadPowerValueFromPROM88E():PROMContent[0x%x]=0x%x\n", + (eeaddr+1), hwinfo[eeaddr+1]); + if (0xFF == hwinfo[eeaddr+1]) /*YJ,add,120316*/ + autoload_fail = true; + + if (autoload_fail) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "auto load fail : Use Default value!\n"); + for (rfpath = 0 ; rfpath < MAX_RF_PATH ; rfpath++) { + /* 2.4G default value */ + set_24g_base(pwrinfo24g, rfpath); + } + return; + } + + for (rfpath = 0 ; rfpath < MAX_RF_PATH ; rfpath++) { + /*2.4G default value*/ + for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { + pwrinfo24g->index_cck_base[rfpath][group] = + hwinfo[eeaddr++]; + if (pwrinfo24g->index_cck_base[rfpath][group] == 0xFF) + pwrinfo24g->index_cck_base[rfpath][group] = + 0x2D; + } + for (group = 0 ; group < MAX_CHNL_GROUP_24G-1; group++) { + pwrinfo24g->index_bw40_base[rfpath][group] = + hwinfo[eeaddr++]; + if (pwrinfo24g->index_bw40_base[rfpath][group] == 0xFF) + pwrinfo24g->index_bw40_base[rfpath][group] = + 0x2D; + } + pwrinfo24g->bw40_diff[rfpath][0] = 0; + if (hwinfo[eeaddr] == 0xFF) { + pwrinfo24g->bw20_diff[rfpath][0] = 0x02; + } else { + pwrinfo24g->bw20_diff[rfpath][0] = + (hwinfo[eeaddr]&0xf0)>>4; + /*bit sign number to 8 bit sign number*/ + if (pwrinfo24g->bw20_diff[rfpath][0] & BIT(3)) + pwrinfo24g->bw20_diff[rfpath][0] |= 0xF0; + } + + if (hwinfo[eeaddr] == 0xFF) { + pwrinfo24g->ofdm_diff[rfpath][0] = 0x04; + } else { + pwrinfo24g->ofdm_diff[rfpath][0] = + (hwinfo[eeaddr]&0x0f); + /*bit sign number to 8 bit sign number*/ + if (pwrinfo24g->ofdm_diff[rfpath][0] & BIT(3)) + pwrinfo24g->ofdm_diff[rfpath][0] |= 0xF0; + } + pwrinfo24g->cck_diff[rfpath][0] = 0; + eeaddr++; + for (txcnt = 1; txcnt < MAX_TX_COUNT; txcnt++) { + if (hwinfo[eeaddr] == 0xFF) { + pwrinfo24g->bw40_diff[rfpath][txcnt] = 0xFE; + } else { + pwrinfo24g->bw40_diff[rfpath][txcnt] = + (hwinfo[eeaddr]&0xf0)>>4; + if (pwrinfo24g->bw40_diff[rfpath][txcnt] & + BIT(3)) + pwrinfo24g->bw40_diff[rfpath][txcnt] |= + 0xF0; + } + + if (hwinfo[eeaddr] == 0xFF) { + pwrinfo24g->bw20_diff[rfpath][txcnt] = + 0xFE; + } else { + pwrinfo24g->bw20_diff[rfpath][txcnt] = + (hwinfo[eeaddr]&0x0f); + if (pwrinfo24g->bw20_diff[rfpath][txcnt] & + BIT(3)) + pwrinfo24g->bw20_diff[rfpath][txcnt] |= + 0xF0; + } + eeaddr++; + + if (hwinfo[eeaddr] == 0xFF) { + pwrinfo24g->ofdm_diff[rfpath][txcnt] = 0xFE; + } else { + pwrinfo24g->ofdm_diff[rfpath][txcnt] = + (hwinfo[eeaddr]&0xf0)>>4; + if (pwrinfo24g->ofdm_diff[rfpath][txcnt] & + BIT(3)) + pwrinfo24g->ofdm_diff[rfpath][txcnt] |= + 0xF0; + } + + if (hwinfo[eeaddr] == 0xFF) { + pwrinfo24g->cck_diff[rfpath][txcnt] = 0xFE; + } else { + pwrinfo24g->cck_diff[rfpath][txcnt] = + (hwinfo[eeaddr]&0x0f); + if (pwrinfo24g->cck_diff[rfpath][txcnt] & + BIT(3)) + pwrinfo24g->cck_diff[rfpath][txcnt] |= + 0xF0; + } + eeaddr++; + } + + /*5G default value*/ + for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) { + pwrinfo5g->index_bw40_base[rfpath][group] = + hwinfo[eeaddr++]; + if (pwrinfo5g->index_bw40_base[rfpath][group] == 0xFF) + pwrinfo5g->index_bw40_base[rfpath][group] = + 0xFE; + } + + pwrinfo5g->bw40_diff[rfpath][0] = 0; + + if (hwinfo[eeaddr] == 0xFF) { + pwrinfo5g->bw20_diff[rfpath][0] = 0; + } else { + pwrinfo5g->bw20_diff[rfpath][0] = + (hwinfo[eeaddr]&0xf0)>>4; + if (pwrinfo5g->bw20_diff[rfpath][0] & BIT(3)) + pwrinfo5g->bw20_diff[rfpath][0] |= 0xF0; + } + + if (hwinfo[eeaddr] == 0xFF) { + pwrinfo5g->ofdm_diff[rfpath][0] = 0x04; + } else { + pwrinfo5g->ofdm_diff[rfpath][0] = (hwinfo[eeaddr]&0x0f); + if (pwrinfo5g->ofdm_diff[rfpath][0] & BIT(3)) + pwrinfo5g->ofdm_diff[rfpath][0] |= 0xF0; + } + eeaddr++; + for (txcnt = 1; txcnt < MAX_TX_COUNT; txcnt++) { + if (hwinfo[eeaddr] == 0xFF) { + pwrinfo5g->bw40_diff[rfpath][txcnt] = 0xFE; + } else { + pwrinfo5g->bw40_diff[rfpath][txcnt] = + (hwinfo[eeaddr]&0xf0)>>4; + if (pwrinfo5g->bw40_diff[rfpath][txcnt] & + BIT(3)) + pwrinfo5g->bw40_diff[rfpath][txcnt] |= + 0xF0; + } + + if (hwinfo[eeaddr] == 0xFF) { + pwrinfo5g->bw20_diff[rfpath][txcnt] = 0xFE; + } else { + pwrinfo5g->bw20_diff[rfpath][txcnt] = + (hwinfo[eeaddr]&0x0f); + if (pwrinfo5g->bw20_diff[rfpath][txcnt] & + BIT(3)) + pwrinfo5g->bw20_diff[rfpath][txcnt] |= + 0xF0; + } + eeaddr++; + } + + if (hwinfo[eeaddr] == 0xFF) { + pwrinfo5g->ofdm_diff[rfpath][1] = 0xFE; + pwrinfo5g->ofdm_diff[rfpath][2] = 0xFE; + } else { + pwrinfo5g->ofdm_diff[rfpath][1] = + (hwinfo[eeaddr]&0xf0)>>4; + pwrinfo5g->ofdm_diff[rfpath][2] = + (hwinfo[eeaddr]&0x0f); + } + eeaddr++; + + if (hwinfo[eeaddr] == 0xFF) + pwrinfo5g->ofdm_diff[rfpath][3] = 0xFE; + else + pwrinfo5g->ofdm_diff[rfpath][3] = (hwinfo[eeaddr]&0x0f); + eeaddr++; + + for (txcnt = 1; txcnt < MAX_TX_COUNT; txcnt++) { + if (pwrinfo5g->ofdm_diff[rfpath][txcnt] == 0xFF) + pwrinfo5g->ofdm_diff[rfpath][txcnt] = 0xFE; + else if (pwrinfo5g->ofdm_diff[rfpath][txcnt] & BIT(3)) + pwrinfo5g->ofdm_diff[rfpath][txcnt] |= 0xF0; + } + } +} + +static void _rtl88ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, + u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct txpower_info_2g pwrinfo24g; + struct txpower_info_5g pwrinfo5g; + u8 rf_path, index; + u8 i; + + read_power_value_fromprom(hw, &pwrinfo24g, + &pwrinfo5g, autoload_fail, hwinfo); + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 14; i++) { + index = _rtl88e_get_chnl_group(i+1); + + rtlefuse->txpwrlevel_cck[rf_path][i] = + pwrinfo24g.index_cck_base[rf_path][index]; + rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = + pwrinfo24g.index_bw40_base[rf_path][index]; + rtlefuse->txpwr_ht20diff[rf_path][i] = + pwrinfo24g.bw20_diff[rf_path][0]; + rtlefuse->txpwr_legacyhtdiff[rf_path][i] = + pwrinfo24g.ofdm_diff[rf_path][0]; + } + + for (i = 0; i < 14; i++) { + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF(%d)-Ch(%d) [CCK / HT40_1S ] = [0x%x / 0x%x ]\n", + rf_path, i, + rtlefuse->txpwrlevel_cck[rf_path][i], + rtlefuse->txpwrlevel_ht40_1s[rf_path][i]); + } + } + + if (!autoload_fail) + rtlefuse->eeprom_thermalmeter = + hwinfo[EEPROM_THERMAL_METER_88E]; + else + rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; + + if (rtlefuse->eeprom_thermalmeter == 0xff || autoload_fail) { + rtlefuse->apk_thermalmeterignore = true; + rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; + } + + rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); + + if (!autoload_fail) { + rtlefuse->eeprom_regulatory = + hwinfo[EEPROM_RF_BOARD_OPTION_88E] & 0x07;/*bit0~2*/ + if (hwinfo[EEPROM_RF_BOARD_OPTION_88E] == 0xFF) + rtlefuse->eeprom_regulatory = 0; + } else { + rtlefuse->eeprom_regulatory = 0; + } + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); +} + +static void _rtl88ee_read_adapter_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u16 i, usvalue; + u8 hwinfo[HWSET_MAX_SIZE]; + u16 eeprom_id; + + if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + rtl_efuse_shadow_map_update(hw); + + memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + HWSET_MAX_SIZE); + } else if (rtlefuse->epromtype == EEPROM_93C46) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "RTL819X Not boot from eeprom, check it !!"); + return; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "boot from neither eeprom nor efuse, check it !!"); + return; + } + + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP\n", + hwinfo, HWSET_MAX_SIZE); + + eeprom_id = *((u16 *)&hwinfo[0]); + if (eeprom_id != RTL8188E_EEPROM_ID) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "EEPROM ID(%#x) is invalid!!\n", eeprom_id); + rtlefuse->autoload_failflag = true; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + } + + if (rtlefuse->autoload_failflag == true) + return; + /*VID DID SVID SDID*/ + rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; + rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; + rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; + rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROMId = 0x%4x\n", eeprom_id); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); + /*customer ID*/ + rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; + if (rtlefuse->eeprom_oemid == 0xFF) + rtlefuse->eeprom_oemid = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); + /*EEPROM version*/ + rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; + /*mac address*/ + for (i = 0; i < 6; i += 2) { + usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; + *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "dev_addr: %pM\n", rtlefuse->dev_addr); + /*channel plan */ + rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; + /* set channel plan from efuse */ + rtlefuse->channel_plan = rtlefuse->eeprom_channelplan; + /*tx power*/ + _rtl88ee_read_txpower_info_from_hwpg(hw, + rtlefuse->autoload_failflag, + hwinfo); + rtlefuse->txpwr_fromeprom = true; + + rtl8188ee_read_bt_coexist_info_from_hwpg(hw, + rtlefuse->autoload_failflag, + hwinfo); + + /*board type*/ + rtlefuse->board_type = + ((hwinfo[EEPROM_RF_BOARD_OPTION_88E] & 0xE0) >> 5); + rtlhal->board_type = rtlefuse->board_type; + /*Wake on wlan*/ + rtlefuse->wowlan_enable = + ((hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & 0x40) >> 6); + /*parse xtal*/ + rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_88E]; + if (hwinfo[EEPROM_XTAL_88E]) + rtlefuse->crystalcap = 0x20; + /*antenna diversity*/ + rtlefuse->antenna_div_cfg = + (hwinfo[EEPROM_RF_BOARD_OPTION_88E] & 0x18) >> 3; + if (hwinfo[EEPROM_RF_BOARD_OPTION_88E] == 0xFF) + rtlefuse->antenna_div_cfg = 0; + if (rtlpriv->btcoexist.eeprom_bt_coexist != 0 && + rtlpriv->btcoexist.eeprom_bt_ant_num == ANT_X1) + rtlefuse->antenna_div_cfg = 0; + + rtlefuse->antenna_div_type = hwinfo[EEPROM_RF_ANTENNA_OPT_88E]; + if (rtlefuse->antenna_div_type == 0xFF) + rtlefuse->antenna_div_type = 0x01; + if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV || + rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) + rtlefuse->antenna_div_cfg = 1; + + if (rtlhal->oem_id == RT_CID_DEFAULT) { + switch (rtlefuse->eeprom_oemid) { + case EEPROM_CID_DEFAULT: + if (rtlefuse->eeprom_did == 0x8179) { + if (rtlefuse->eeprom_svid == 0x1025) { + rtlhal->oem_id = RT_CID_819X_ACER; + } else if ((rtlefuse->eeprom_svid == 0x10EC && + rtlefuse->eeprom_smid == 0x0179) || + (rtlefuse->eeprom_svid == 0x17AA && + rtlefuse->eeprom_smid == 0x0179)) { + rtlhal->oem_id = RT_CID_819X_LENOVO; + } else if (rtlefuse->eeprom_svid == 0x103c && + rtlefuse->eeprom_smid == 0x197d) { + rtlhal->oem_id = RT_CID_819X_HP; + } else { + rtlhal->oem_id = RT_CID_DEFAULT; + } + } else { + rtlhal->oem_id = RT_CID_DEFAULT; + } + break; + case EEPROM_CID_TOSHIBA: + rtlhal->oem_id = RT_CID_TOSHIBA; + break; + case EEPROM_CID_QMI: + rtlhal->oem_id = RT_CID_819X_QMI; + break; + case EEPROM_CID_WHQL: + default: + rtlhal->oem_id = RT_CID_DEFAULT; + break; + + } + } +} + +static void _rtl88ee_hal_customized_behavior(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + pcipriv->ledctl.led_opendrain = true; + + switch (rtlhal->oem_id) { + case RT_CID_819X_HP: + pcipriv->ledctl.led_opendrain = true; + break; + case RT_CID_819X_LENOVO: + case RT_CID_DEFAULT: + case RT_CID_TOSHIBA: + case RT_CID_CCX: + case RT_CID_819X_ACER: + case RT_CID_WHQL: + default: + break; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "RT Customized ID: 0x%02X\n", rtlhal->oem_id); +} + +void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_u1b; + + rtlhal->version = _rtl88ee_read_chip_version(hw); + if (get_rf_type(rtlphy) == RF_1T1R) + rtlpriv->dm.rfpath_rxenable[0] = true; + else + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", + rtlhal->version); + tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); + if (tmp_u1b & BIT(4)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); + rtlefuse->epromtype = EEPROM_93C46; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); + rtlefuse->epromtype = EEPROM_BOOT_EFUSE; + } + if (tmp_u1b & BIT(5)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + _rtl88ee_read_adapter_info(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); + } + _rtl88ee_hal_customized_behavior(hw); +} + +static void rtl88ee_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 ratr_value; + u8 ratr_index = 0; + u8 b_nmode = mac->ht_enable; + /*u8 mimo_ps = IEEE80211_SMPS_OFF;*/ + u16 shortgi_rate; + u32 tmp_ratr_value; + u8 curtxbw_40mhz = mac->bw_40; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = mac->mode; + u32 ratr_mask; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_value = sta->supp_rates[1] << 4; + else + ratr_value = sta->supp_rates[0]; + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_value = 0xfff; + ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + if (ratr_value & 0x0000000c) + ratr_value &= 0x0000000d; + else + ratr_value &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_value &= 0x00000FF5; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + b_nmode = 1; + if (get_rf_type(rtlphy) == RF_1T2R || + get_rf_type(rtlphy) == RF_1T1R) + ratr_mask = 0x000ff005; + else + ratr_mask = 0x0f0ff005; + + ratr_value &= ratr_mask; + break; + default: + if (rtlphy->rf_type == RF_1T2R) + ratr_value &= 0x000ff0ff; + else + ratr_value &= 0x0f0ff0ff; + + break; + } + + if ((rtlpriv->btcoexist.bt_coexistence) && + (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4) && + (rtlpriv->btcoexist.bt_cur_state) && + (rtlpriv->btcoexist.bt_ant_isolation) && + ((rtlpriv->btcoexist.bt_service == BT_SCO) || + (rtlpriv->btcoexist.bt_service == BT_BUSY))) + ratr_value &= 0x0fffcfc0; + else + ratr_value &= 0x0FFFFFFF; + + if (b_nmode && + ((curtxbw_40mhz && curshortgi_40mhz) || + (!curtxbw_40mhz && curshortgi_20mhz))) { + ratr_value |= 0x10000000; + tmp_ratr_value = (ratr_value >> 12); + + for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { + if ((1 << shortgi_rate) & tmp_ratr_value) + break; + } + + shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | + (shortgi_rate << 4) | (shortgi_rate); + } + + rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)); +} + +static void rtl88ee_update_hal_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u32 ratr_bitmap; + u8 ratr_index; + u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) + ? 1 : 0; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = 0; + bool b_shortgi = false; + u8 rate_mask[5]; + u8 macid = 0; + /*u8 mimo_ps = IEEE80211_SMPS_OFF;*/ + + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + wirelessmode = sta_entry->wireless_mode; + if (mac->opmode == NL80211_IFTYPE_STATION || + mac->opmode == NL80211_IFTYPE_MESH_POINT) + curtxbw_40mhz = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + macid = sta->aid + 1; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_bitmap = sta->supp_rates[1] << 4; + else + ratr_bitmap = sta->supp_rates[0]; + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_bitmap = 0xfff; + ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + ratr_index = RATR_INX_WIRELESS_B; + if (ratr_bitmap & 0x0000000c) + ratr_bitmap &= 0x0000000d; + else + ratr_bitmap &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_index = RATR_INX_WIRELESS_GB; + + if (rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if (rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + ratr_index = RATR_INX_WIRELESS_NGB; + if (rtlphy->rf_type == RF_1T2R || + rtlphy->rf_type == RF_1T1R) { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff005; + } + } else { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x0f8f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f8ff000; + else + ratr_bitmap &= 0x0f8ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x0f8f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f8ff000; + else + ratr_bitmap &= 0x0f8ff005; + } + } + /*}*/ + + if ((curtxbw_40mhz && curshortgi_40mhz) || + (!curtxbw_40mhz && curshortgi_20mhz)) { + + if (macid == 0) + b_shortgi = true; + else if (macid == 1) + b_shortgi = false; + } + break; + default: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rtlphy->rf_type == RF_1T2R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0f0ff0ff; + break; + } + sta_entry->ratr_index = ratr_index; + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "ratr_bitmap :%x\n", ratr_bitmap); + *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | + (ratr_index << 28); + rate_mask[4] = macid | (b_shortgi ? 0x20 : 0x00) | 0x80; + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n", + ratr_index, ratr_bitmap, + rate_mask[0], rate_mask[1], + rate_mask[2], rate_mask[3], + rate_mask[4]); + rtl88e_fill_h2c_cmd(hw, H2C_88E_RA_MASK, 5, rate_mask); + _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); +} + +void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->dm.useramask) + rtl88ee_update_hal_rate_mask(hw, sta, rssi_level); + else + rtl88ee_update_hal_rate_table(hw, sta); +} + +void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 sifs_timer; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, &mac->slot_time); + if (!mac->ht_enable) + sifs_timer = 0x0a0a; + else + sifs_timer = 0x0e0e; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); +} + +bool rtl88ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; + u32 u4tmp; + bool b_actuallyset = false; + + if (rtlpriv->rtlhal.being_init_adapter) + return false; + + if (ppsc->swrf_processing) + return false; + + spin_lock(&rtlpriv->locks.rf_ps_lock); + if (ppsc->rfchange_inprogress) { + spin_unlock(&rtlpriv->locks.rf_ps_lock); + return false; + } else { + ppsc->rfchange_inprogress = true; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } + + cur_rfstate = ppsc->rfpwr_state; + + u4tmp = rtl_read_dword(rtlpriv, REG_GPIO_OUTPUT); + e_rfpowerstate_toset = (u4tmp & BIT(31)) ? ERFON : ERFOFF; + + if (ppsc->hwradiooff && (e_rfpowerstate_toset == ERFON)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "GPIOChangeRF - HW Radio ON, RF ON\n"); + + e_rfpowerstate_toset = ERFON; + ppsc->hwradiooff = false; + b_actuallyset = true; + } else if ((!ppsc->hwradiooff) && + (e_rfpowerstate_toset == ERFOFF)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "GPIOChangeRF - HW Radio OFF, RF OFF\n"); + + e_rfpowerstate_toset = ERFOFF; + ppsc->hwradiooff = true; + b_actuallyset = true; + } + + if (b_actuallyset) { + spin_lock(&rtlpriv->locks.rf_ps_lock); + ppsc->rfchange_inprogress = false; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } else { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + + spin_lock(&rtlpriv->locks.rf_ps_lock); + ppsc->rfchange_inprogress = false; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } + + *valid = 1; + return !ppsc->hwradiooff; + +} + +void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 *macaddr = p_macaddr; + u32 entry_id = 0; + bool is_pairwise = false; + static u8 cam_const_addr[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} + }; + static u8 cam_const_broad[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (clear_all) { + u8 idx = 0; + u8 cam_offset = 0; + u8 clear_number = 5; + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); + + for (idx = 0; idx < clear_number; idx++) { + rtl_cam_mark_invalid(hw, cam_offset + idx); + rtl_cam_empty_entry(hw, cam_offset + idx); + + if (idx < 5) { + memset(rtlpriv->sec.key_buf[idx], 0, + MAX_KEY_LEN); + rtlpriv->sec.key_len[idx] = 0; + } + } + + } else { + switch (enc_algo) { + case WEP40_ENCRYPTION: + enc_algo = CAM_WEP40; + break; + case WEP104_ENCRYPTION: + enc_algo = CAM_WEP104; + break; + case TKIP_ENCRYPTION: + enc_algo = CAM_TKIP; + break; + case AESCCMP_ENCRYPTION: + enc_algo = CAM_AES; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + enc_algo = CAM_TKIP; + break; + } + + if (is_wepkey || rtlpriv->sec.use_defaultkey) { + macaddr = cam_const_addr[key_index]; + entry_id = key_index; + } else { + if (is_group) { + macaddr = cam_const_broad; + entry_id = key_index; + } else { + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + entry_id = + rtl_cam_get_free_entry(hw, p_macaddr); + if (entry_id >= TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, COMP_SEC, + DBG_EMERG, + "Can not find free hw security cam entry\n"); + return; + } + } else { + entry_id = CAM_PAIRWISE_KEY_POSITION; + } + key_index = PAIRWISE_KEYIDX; + is_pairwise = true; + } + } + + if (rtlpriv->sec.key_len[key_index] == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "delete one entry, entry_id is %d\n", + entry_id); + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_MESH_POINT) + rtl_cam_del_entry(hw, p_macaddr); + rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "add one entry\n"); + if (is_pairwise) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set Pairwise key\n"); + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[key_index]); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set group key\n"); + + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_cam_add_one_entry(hw, + rtlefuse->dev_addr, + PAIRWISE_KEYIDX, + CAM_PAIRWISE_KEY_POSITION, + enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf + [entry_id]); + } + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + + } + } +} + +static void rtl8188ee_bt_var_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->btcoexist.bt_coexistence = + rtlpriv->btcoexist.eeprom_bt_coexist; + rtlpriv->btcoexist.bt_ant_num = rtlpriv->btcoexist.eeprom_bt_ant_num; + rtlpriv->btcoexist.bt_coexist_type = rtlpriv->btcoexist.eeprom_bt_type; + + if (rtlpriv->btcoexist.reg_bt_iso == 2) + rtlpriv->btcoexist.bt_ant_isolation = + rtlpriv->btcoexist.eeprom_bt_ant_isol; + else + rtlpriv->btcoexist.bt_ant_isolation = + rtlpriv->btcoexist.reg_bt_iso; + + rtlpriv->btcoexist.bt_radio_shared_type = + rtlpriv->btcoexist.eeprom_bt_radio_shared; + + if (rtlpriv->btcoexist.bt_coexistence) { + if (rtlpriv->btcoexist.reg_bt_sco == 1) + rtlpriv->btcoexist.bt_service = BT_OTHER_ACTION; + else if (rtlpriv->btcoexist.reg_bt_sco == 2) + rtlpriv->btcoexist.bt_service = BT_SCO; + else if (rtlpriv->btcoexist.reg_bt_sco == 4) + rtlpriv->btcoexist.bt_service = BT_BUSY; + else if (rtlpriv->btcoexist.reg_bt_sco == 5) + rtlpriv->btcoexist.bt_service = BT_OTHERBUSY; + else + rtlpriv->btcoexist.bt_service = BT_IDLE; + + rtlpriv->btcoexist.bt_edca_ul = 0; + rtlpriv->btcoexist.bt_edca_dl = 0; + rtlpriv->btcoexist.bt_rssi_state = 0xff; + } +} + +void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool auto_load_fail, u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 value; + + if (!auto_load_fail) { + rtlpriv->btcoexist.eeprom_bt_coexist = + ((hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & 0xe0) >> 5); + if (hwinfo[EEPROM_RF_FEATURE_OPTION_88E] == 0xFF) + rtlpriv->btcoexist.eeprom_bt_coexist = 0; + value = hwinfo[EEPROM_RF_BT_SETTING_88E]; + rtlpriv->btcoexist.eeprom_bt_type = ((value & 0xe) >> 1); + rtlpriv->btcoexist.eeprom_bt_ant_num = (value & 0x1); + rtlpriv->btcoexist.eeprom_bt_ant_isol = ((value & 0x10) >> 4); + rtlpriv->btcoexist.eeprom_bt_radio_shared = + ((value & 0x20) >> 5); + } else { + rtlpriv->btcoexist.eeprom_bt_coexist = 0; + rtlpriv->btcoexist.eeprom_bt_type = BT_2WIRE; + rtlpriv->btcoexist.eeprom_bt_ant_num = ANT_X2; + rtlpriv->btcoexist.eeprom_bt_ant_isol = 0; + rtlpriv->btcoexist.eeprom_bt_radio_shared = BT_RADIO_SHARED; + } + + rtl8188ee_bt_var_init(hw); +} + +void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* 0:Low, 1:High, 2:From Efuse. */ + rtlpriv->btcoexist.reg_bt_iso = 2; + /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ + rtlpriv->btcoexist.reg_bt_sco = 3; + /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ + rtlpriv->btcoexist.reg_bt_sco = 0; +} + +void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 u1_tmp; + + if (rtlpriv->btcoexist.bt_coexistence && + ((rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4) || + rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC8)) { + if (rtlpriv->btcoexist.bt_ant_isolation) + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + + u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) & + BIT_OFFSET_LEN_MASK_32(0, 1); + u1_tmp = u1_tmp | + ((rtlpriv->btcoexist.bt_ant_isolation == 1) ? + 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | + ((rtlpriv->btcoexist.bt_service == BT_SCO) ? + 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); + rtl_write_byte(rtlpriv, 0x4fd, u1_tmp); + + rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa); + rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040); + rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010); + + /* Config to 1T1R. */ + if (rtlphy->rf_type == RF_1T1R) { + u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE); + u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); + rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp); + + u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE); + u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); + rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp); + } + } +} + +void rtl88ee_suspend(struct ieee80211_hw *hw) +{ +} + +void rtl88ee_resume(struct ieee80211_hw *hw) +{ +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h new file mode 100644 index 000000000000..1850fde881b5 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/hw.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CE_HW_H__ +#define __RTL92CE_HW_H__ + +void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw); +void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb); +int rtl88ee_hw_init(struct ieee80211_hw *hw); +void rtl88ee_card_disable(struct ieee80211_hw *hw); +void rtl88ee_enable_interrupt(struct ieee80211_hw *hw); +void rtl88ee_disable_interrupt(struct ieee80211_hw *hw); +int rtl88ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); +void rtl88ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); +void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci); +void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw); +void rtl88ee_set_beacon_interval(struct ieee80211_hw *hw); +void rtl88ee_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); +void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); +void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw); +bool rtl88ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); +void rtl88ee_enable_hw_security_config(struct ieee80211_hw *hw); +void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all); + +void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo); +void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw); +void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw); +void rtl88ee_suspend(struct ieee80211_hw *hw); +void rtl88ee_resume(struct ieee80211_hw *hw); +void rtl88ee_fw_clk_off_timer_callback(unsigned long data); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c new file mode 100644 index 000000000000..b504bd092fc4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.c @@ -0,0 +1,154 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "reg.h" +#include "led.h" + +static void _rtl88ee_init_led(struct ieee80211_hw *hw, + struct rtl_led *pled, enum rtl_led_pin ledpin) +{ + pled->hw = hw; + pled->ledpin = ledpin; + pled->ledon = false; +} + +void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u8 ledcfg; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + rtl_write_byte(rtlpriv, + REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6)); + break; + case LED_PIN_LED1: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); + rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + pled->ledon = true; +} + +void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + u8 ledcfg; + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + ledcfg &= 0xf0; + if (pcipriv->ledctl.led_opendrain) { + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(3) | BIT(5) | BIT(6))); + ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); + rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, + (ledcfg & 0xFE)); + } else + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(3) | BIT(5) | BIT(6))); + break; + case LED_PIN_LED1: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); + ledcfg &= 0x10; + rtl_write_byte(rtlpriv, REG_LEDCFG1, (ledcfg | BIT(3))); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + pled->ledon = false; +} + +void rtl88ee_init_sw_leds(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + _rtl88ee_init_led(hw, &pcipriv->ledctl.sw_led0, LED_PIN_LED0); + _rtl88ee_init_led(hw, &pcipriv->ledctl.sw_led1, LED_PIN_LED1); +} + +static void _rtl88ee_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + switch (ledaction) { + case LED_CTL_POWER_ON: + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + rtl88ee_sw_led_on(hw, pLed0); + break; + case LED_CTL_POWER_OFF: + rtl88ee_sw_led_off(hw, pLed0); + break; + default: + break; + } +} + +void rtl88ee_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && + (ledaction == LED_CTL_TX || + ledaction == LED_CTL_RX || + ledaction == LED_CTL_SITE_SURVEY || + ledaction == LED_CTL_LINK || + ledaction == LED_CTL_NO_LINK || + ledaction == LED_CTL_START_TO_LINK || + ledaction == LED_CTL_POWER_ON)) { + return; + } + RT_TRACE(rtlpriv, COMP_LED, DBG_TRACE, "ledaction %d,\n", + ledaction); + _rtl88ee_sw_led_control(hw, ledaction); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h new file mode 100644 index 000000000000..4b325b75faaf --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/led.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CE_LED_H__ +#define __RTL92CE_LED_H__ + +void rtl88ee_init_sw_leds(struct ieee80211_hw *hw); +void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl88ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c new file mode 100644 index 000000000000..a2bb02c7b837 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c @@ -0,0 +1,2343 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../ps.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "table.h" + +static u32 _rtl88e_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +static void _rtl88e_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +static u32 _rtl88e_phy_calculate_bit_shift(u32 bitmask); +static bool _rtl88e_phy_bb8188e_config_parafile(struct ieee80211_hw *hw); +static bool _rtl88e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); +static bool phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +static bool phy_config_bb_with_pghdr(struct ieee80211_hw *hw, + u8 configtype); +static void _rtl88e_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); +static bool _rtl88e_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, + enum swchnlcmd_id cmdid, u32 para1, + u32 para2, u32 msdelay); +static bool _rtl88e_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay); + +static long _rtl88e_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u8 txpwridx); +static void rtl88ee_phy_set_rf_on(struct ieee80211_hw *hw); +static void rtl88e_phy_set_io(struct ieee80211_hw *hw); + +u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 returnvalue, originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask); + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl88e_phy_calculate_bit_shift(bitmask); + returnvalue = (originalvalue & bitmask) >> bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "BBR MASK=0x%x Addr[0x%x]=0x%x\n", bitmask, + regaddr, originalvalue); + + return returnvalue; + +} + +void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); + + if (bitmask != MASKDWORD) { + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl88e_phy_calculate_bit_shift(bitmask); + data = ((originalvalue & (~bitmask)) | (data << bitshift)); + } + + rtl_write_dword(rtlpriv, regaddr, data); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); +} + +u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, readback_value, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", + regaddr, rfpath, bitmask); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + + original_value = _rtl88e_phy_rf_serial_read(hw, rfpath, regaddr); + bitshift = _rtl88e_phy_calculate_bit_shift(bitmask); + readback_value = (original_value & bitmask) >> bitshift; + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", + regaddr, rfpath, bitmask, original_value); + return readback_value; +} + +void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + if (bitmask != RFREG_OFFSET_MASK) { + original_value = _rtl88e_phy_rf_serial_read(hw, + rfpath, + regaddr); + bitshift = _rtl88e_phy_calculate_bit_shift(bitmask); + data = + ((original_value & (~bitmask)) | + (data << bitshift)); + } + + _rtl88e_phy_rf_serial_write(hw, rfpath, regaddr, data); + + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); +} + +static u32 _rtl88e_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + u32 newoffset; + u32 tmplong, tmplong2; + u8 rfpi_enable = 0; + u32 retvalue; + + offset &= 0xff; + newoffset = offset; + if (RT_CANNOT_IO(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n"); + return 0xFFFFFFFF; + } + tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); + if (rfpath == RF90_PATH_A) + tmplong2 = tmplong; + else + tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); + tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | + (newoffset << 23) | BLSSIREADEDGE; + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, + tmplong & (~BLSSIREADEDGE)); + mdelay(1); + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); + mdelay(2); + if (rfpath == RF90_PATH_A) + rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, + BIT(8)); + else if (rfpath == RF90_PATH_B) + rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, + BIT(8)); + if (rfpi_enable) + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, + BLSSIREADBACKDATA); + else + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, + BLSSIREADBACKDATA); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "RFR-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf_rb, retvalue); + return retvalue; +} + +static void _rtl88e_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data) +{ + u32 data_and_addr; + u32 newoffset; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + + if (RT_CANNOT_IO(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n"); + return; + } + offset &= 0xff; + newoffset = offset; + data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; + rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "RFW-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf3wire_offset, data_and_addr); +} + +static u32 _rtl88e_phy_calculate_bit_shift(u32 bitmask) +{ + u32 i; + + for (i = 0; i <= 31; i++) { + if (((bitmask >> i) & 0x1) == 1) + break; + } + return i; +} + +bool rtl88e_phy_mac_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool rtstatus = _rtl88e_phy_config_mac_with_headerfile(hw); + + rtl_write_byte(rtlpriv, 0x04CA, 0x0B); + return rtstatus; +} + +bool rtl88e_phy_bb_config(struct ieee80211_hw *hw) +{ + bool rtstatus = true; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 regval; + u8 b_reg_hwparafile = 1; + u32 tmp; + _rtl88e_phy_init_bb_rf_register_definition(hw); + regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, + regval | BIT(13) | BIT(0) | BIT(1)); + + rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, + FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | + FEN_BB_GLB_RSTN | FEN_BBRSTB); + tmp = rtl_read_dword(rtlpriv, 0x4c); + rtl_write_dword(rtlpriv, 0x4c, tmp | BIT(23)); + if (b_reg_hwparafile == 1) + rtstatus = _rtl88e_phy_bb8188e_config_parafile(hw); + return rtstatus; +} + +bool rtl88e_phy_rf_config(struct ieee80211_hw *hw) +{ + return rtl88e_phy_rf6052_config(hw); +} + +static bool _rtl88e_check_condition(struct ieee80211_hw *hw, + const u32 condition) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 _board = rtlefuse->board_type; /*need efuse define*/ + u32 _interface = rtlhal->interface; + u32 _platform = 0x08;/*SupportPlatform */ + u32 cond = condition; + + if (condition == 0xCDCDCDCD) + return true; + + cond = condition & 0xFF; + if ((_board & cond) == 0 && cond != 0x1F) + return false; + + cond = condition & 0xFF00; + cond = cond >> 8; + if ((_interface & cond) == 0 && cond != 0x07) + return false; + + cond = condition & 0xFF0000; + cond = cond >> 16; + if ((_platform & cond) == 0 && cond != 0x0F) + return false; + return true; +} + +static void _rtl8188e_config_rf_reg(struct ieee80211_hw *hw, u32 addr, + u32 data, enum radio_path rfpath, + u32 regaddr) +{ + if (addr == 0xffe) { + mdelay(50); + } else if (addr == 0xfd) { + mdelay(5); + } else if (addr == 0xfc) { + mdelay(1); + } else if (addr == 0xfb) { + udelay(50); + } else if (addr == 0xfa) { + udelay(5); + } else if (addr == 0xf9) { + udelay(1); + } else { + rtl_set_rfreg(hw, rfpath, regaddr, + RFREG_OFFSET_MASK, + data); + udelay(1); + } +} + +static void _rtl8188e_config_rf_radio_a(struct ieee80211_hw *hw, + u32 addr, u32 data) +{ + u32 content = 0x1000; /*RF Content: radio_a_txt*/ + u32 maskforphyset = (u32)(content & 0xE000); + + _rtl8188e_config_rf_reg(hw, addr, data, RF90_PATH_A, + addr | maskforphyset); +} + +static void _rtl8188e_config_bb_reg(struct ieee80211_hw *hw, + u32 addr, u32 data) +{ + if (addr == 0xfe) { + mdelay(50); + } else if (addr == 0xfd) { + mdelay(5); + } else if (addr == 0xfc) { + mdelay(1); + } else if (addr == 0xfb) { + udelay(50); + } else if (addr == 0xfa) { + udelay(5); + } else if (addr == 0xf9) { + udelay(1); + } else { + rtl_set_bbreg(hw, addr, MASKDWORD, data); + udelay(1); + } +} + +static bool _rtl88e_phy_bb8188e_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + bool rtstatus; + + rtstatus = phy_config_bb_with_headerfile(hw, BASEBAND_CONFIG_PHY_REG); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); + return false; + } + + if (!rtlefuse->autoload_failflag) { + rtlphy->pwrgroup_cnt = 0; + rtstatus = + phy_config_bb_with_pghdr(hw, BASEBAND_CONFIG_PHY_REG); + } + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); + return false; + } + rtstatus = + phy_config_bb_with_headerfile(hw, BASEBAND_CONFIG_AGC_TAB); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); + return false; + } + rtlphy->cck_high_power = + (bool)(rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, 0x200)); + + return true; +} + +static bool _rtl88e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + u32 arraylength; + u32 *ptrarray; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl8188EMACPHY_Array\n"); + arraylength = RTL8188EEMAC_1T_ARRAYLEN; + ptrarray = RTL8188EEMAC_1T_ARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Img:RTL8188EEMAC_1T_ARRAY LEN %d\n", arraylength); + for (i = 0; i < arraylength; i = i + 2) + rtl_write_byte(rtlpriv, ptrarray[i], (u8)ptrarray[i + 1]); + return true; +} + +#define READ_NEXT_PAIR(v1, v2, i) \ + do { \ + i += 2; v1 = array_table[i]; \ + v2 = array_table[i+1]; \ + } while (0) + +static void handle_branch1(struct ieee80211_hw *hw, u16 arraylen, + u32 *array_table) +{ + u32 v1; + u32 v2; + int i; + + for (i = 0; i < arraylen; i = i + 2) { + v1 = array_table[i]; + v2 = array_table[i+1]; + if (v1 < 0xcdcdcdcd) { + _rtl8188e_config_bb_reg(hw, v1, v2); + } else { /*This line is the start line of branch.*/ + /* to protect READ_NEXT_PAIR not overrun */ + if (i >= arraylen - 2) + break; + + if (!_rtl88e_check_condition(hw, array_table[i])) { + /*Discard the following (offset, data) pairs*/ + READ_NEXT_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < arraylen - 2) + READ_NEXT_PAIR(v1, v2, i); + i -= 2; /* prevent from for-loop += 2*/ + } else { /* Configure matched pairs and skip + * to end of if-else. + */ + READ_NEXT_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < arraylen - 2) { + _rtl8188e_config_bb_reg(hw, v1, v2); + READ_NEXT_PAIR(v1, v2, i); + } + + while (v2 != 0xDEAD && i < arraylen - 2) + READ_NEXT_PAIR(v1, v2, i); + } + } + } +} + +static void handle_branch2(struct ieee80211_hw *hw, u16 arraylen, + u32 *array_table) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 v1; + u32 v2; + int i; + + for (i = 0; i < arraylen; i = i + 2) { + v1 = array_table[i]; + v2 = array_table[i+1]; + if (v1 < 0xCDCDCDCD) { + rtl_set_bbreg(hw, array_table[i], MASKDWORD, + array_table[i + 1]); + udelay(1); + continue; + } else { /*This line is the start line of branch.*/ + /* to protect READ_NEXT_PAIR not overrun */ + if (i >= arraylen - 2) + break; + + if (!_rtl88e_check_condition(hw, array_table[i])) { + /*Discard the following (offset, data) pairs*/ + READ_NEXT_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < arraylen - 2) + READ_NEXT_PAIR(v1, v2, i); + i -= 2; /* prevent from for-loop += 2*/ + } else { /* Configure matched pairs and skip + * to end of if-else. + */ + READ_NEXT_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < arraylen - 2) { + rtl_set_bbreg(hw, array_table[i], + MASKDWORD, + array_table[i + 1]); + udelay(1); + READ_NEXT_PAIR(v1, v2, i); + } + + while (v2 != 0xDEAD && i < arraylen - 2) + READ_NEXT_PAIR(v1, v2, i); + } + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The agctab_array_table[0] is %x Rtl818EEPHY_REGArray[1] is %x\n", + array_table[i], array_table[i + 1]); + } +} + +static bool phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype) +{ + u32 *array_table; + u16 arraylen; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + arraylen = RTL8188EEPHY_REG_1TARRAYLEN; + array_table = RTL8188EEPHY_REG_1TARRAY; + handle_branch1(hw, arraylen, array_table); + } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { + arraylen = RTL8188EEAGCTAB_1TARRAYLEN; + array_table = RTL8188EEAGCTAB_1TARRAY; + handle_branch2(hw, arraylen, array_table); + } + return true; +} + +static void store_pwrindex_rate_offset(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, + u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + int count = rtlphy->pwrgroup_cnt; + + if (regaddr == RTXAGC_A_RATE18_06) { + rtlphy->mcs_txpwrlevel_origoffset[count][0] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][0]); + } + if (regaddr == RTXAGC_A_RATE54_24) { + rtlphy->mcs_txpwrlevel_origoffset[count][1] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][1]); + } + if (regaddr == RTXAGC_A_CCK1_MCS32) { + rtlphy->mcs_txpwrlevel_origoffset[count][6] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][6]); + } + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { + rtlphy->mcs_txpwrlevel_origoffset[count][7] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][7]); + } + if (regaddr == RTXAGC_A_MCS03_MCS00) { + rtlphy->mcs_txpwrlevel_origoffset[count][2] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][2]); + } + if (regaddr == RTXAGC_A_MCS07_MCS04) { + rtlphy->mcs_txpwrlevel_origoffset[count][3] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][3]); + } + if (regaddr == RTXAGC_A_MCS11_MCS08) { + rtlphy->mcs_txpwrlevel_origoffset[count][4] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][4]); + } + if (regaddr == RTXAGC_A_MCS15_MCS12) { + rtlphy->mcs_txpwrlevel_origoffset[count][5] = data; + if (get_rf_type(rtlphy) == RF_1T1R) { + count++; + rtlphy->pwrgroup_cnt = count; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][5]); + } + if (regaddr == RTXAGC_B_RATE18_06) { + rtlphy->mcs_txpwrlevel_origoffset[count][8] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][8]); + } + if (regaddr == RTXAGC_B_RATE54_24) { + rtlphy->mcs_txpwrlevel_origoffset[count][9] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][9]); + } + if (regaddr == RTXAGC_B_CCK1_55_MCS32) { + rtlphy->mcs_txpwrlevel_origoffset[count][14] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][14]); + } + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { + rtlphy->mcs_txpwrlevel_origoffset[count][15] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][15]); + } + if (regaddr == RTXAGC_B_MCS03_MCS00) { + rtlphy->mcs_txpwrlevel_origoffset[count][10] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][10]); + } + if (regaddr == RTXAGC_B_MCS07_MCS04) { + rtlphy->mcs_txpwrlevel_origoffset[count][11] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][11]); + } + if (regaddr == RTXAGC_B_MCS11_MCS08) { + rtlphy->mcs_txpwrlevel_origoffset[count][12] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][12]); + } + if (regaddr == RTXAGC_B_MCS15_MCS12) { + rtlphy->mcs_txpwrlevel_origoffset[count][13] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", + count, + rtlphy->mcs_txpwrlevel_origoffset[count][13]); + if (get_rf_type(rtlphy) != RF_1T1R) { + count++; + rtlphy->pwrgroup_cnt = count; + } + } +} + +static bool phy_config_bb_with_pghdr(struct ieee80211_hw *hw, u8 configtype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int i; + u32 *phy_reg_page; + u16 phy_reg_page_len; + u32 v1 = 0, v2 = 0, v3 = 0; + + phy_reg_page_len = RTL8188EEPHY_REG_ARRAY_PGLEN; + phy_reg_page = RTL8188EEPHY_REG_ARRAY_PG; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_reg_page_len; i = i + 3) { + v1 = phy_reg_page[i]; + v2 = phy_reg_page[i+1]; + v3 = phy_reg_page[i+2]; + + if (v1 < 0xcdcdcdcd) { + if (phy_reg_page[i] == 0xfe) + mdelay(50); + else if (phy_reg_page[i] == 0xfd) + mdelay(5); + else if (phy_reg_page[i] == 0xfc) + mdelay(1); + else if (phy_reg_page[i] == 0xfb) + udelay(50); + else if (phy_reg_page[i] == 0xfa) + udelay(5); + else if (phy_reg_page[i] == 0xf9) + udelay(1); + + store_pwrindex_rate_offset(hw, phy_reg_page[i], + phy_reg_page[i + 1], + phy_reg_page[i + 2]); + continue; + } else { + if (!_rtl88e_check_condition(hw, + phy_reg_page[i])) { + /*don't need the hw_body*/ + i += 2; /* skip the pair of expression*/ + /* to protect 'i+1' 'i+2' not overrun */ + if (i >= phy_reg_page_len - 2) + break; + + v1 = phy_reg_page[i]; + v2 = phy_reg_page[i+1]; + v3 = phy_reg_page[i+2]; + while (v2 != 0xDEAD && + i < phy_reg_page_len - 5) { + i += 3; + v1 = phy_reg_page[i]; + v2 = phy_reg_page[i+1]; + v3 = phy_reg_page[i+2]; + } + } + } + } + } else { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "configtype != BaseBand_Config_PHY_REG\n"); + } + return true; +} + +#define READ_NEXT_RF_PAIR(v1, v2, i) \ +do { \ + i += 2; \ + v1 = radioa_array_table[i]; \ + v2 = radioa_array_table[i+1]; \ +} while (0) + +static void process_path_a(struct ieee80211_hw *hw, + u16 radioa_arraylen, + u32 *radioa_array_table) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 v1, v2; + int i; + + for (i = 0; i < radioa_arraylen; i = i + 2) { + v1 = radioa_array_table[i]; + v2 = radioa_array_table[i+1]; + if (v1 < 0xcdcdcdcd) { + _rtl8188e_config_rf_radio_a(hw, v1, v2); + } else { /*This line is the start line of branch.*/ + /* to protect READ_NEXT_PAIR not overrun */ + if (i >= radioa_arraylen - 2) + break; + + if (!_rtl88e_check_condition(hw, radioa_array_table[i])) { + /*Discard the following (offset, data) pairs*/ + READ_NEXT_RF_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < radioa_arraylen - 2) { + READ_NEXT_RF_PAIR(v1, v2, i); + } + i -= 2; /* prevent from for-loop += 2*/ + } else { /* Configure matched pairs and + * skip to end of if-else. + */ + READ_NEXT_RF_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < radioa_arraylen - 2) { + _rtl8188e_config_rf_radio_a(hw, v1, v2); + READ_NEXT_RF_PAIR(v1, v2, i); + } + + while (v2 != 0xDEAD && + i < radioa_arraylen - 2) + READ_NEXT_RF_PAIR(v1, v2, i); + } + } + } + + if (rtlhal->oem_id == RT_CID_819X_HP) + _rtl8188e_config_rf_radio_a(hw, 0x52, 0x7E4BD); +} + +bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool rtstatus = true; + u32 *radioa_array_table; + u16 radioa_arraylen; + + radioa_arraylen = RTL8188EE_RADIOA_1TARRAYLEN; + radioa_array_table = RTL8188EE_RADIOA_1TARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Radio_A:RTL8188EE_RADIOA_1TARRAY %d\n", radioa_arraylen); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); + rtstatus = true; + switch (rfpath) { + case RF90_PATH_A: + process_path_a(hw, radioa_arraylen, radioa_array_table); + break; + case RF90_PATH_B: + case RF90_PATH_C: + case RF90_PATH_D: + break; + } + return true; +} + +void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + rtlphy->default_initialgain[0] = + (u8)rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[1] = + (u8)rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[2] = + (u8)rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[3] = + (u8)rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", + rtlphy->default_initialgain[0], + rtlphy->default_initialgain[1], + rtlphy->default_initialgain[2], + rtlphy->default_initialgain[3]); + + rtlphy->framesync = (u8)rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, + MASKBYTE0); + rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, + MASKDWORD); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default framesync (0x%x) = 0x%x\n", + ROFDM0_RXDETECTOR3, rtlphy->framesync); +} + +static void _rtl88e_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; + + rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = + RFPGA0_XA_LSSIPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = + RFPGA0_XB_LSSIPARAMETER; + + rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; + + rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; + + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; + + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; + + rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = + RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = + RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = + RFPGA0_XCD_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = + RFPGA0_XCD_SWITCHCONTROL; + + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; + + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; + + rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBANLANCE; + rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; + + rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; + + rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE; + + rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; + + rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; + + rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK; + rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK; +} + +void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 txpwr_level; + long txpwr_dbm; + + txpwr_level = rtlphy->cur_cck_txpwridx; + txpwr_dbm = _rtl88e_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_B, txpwr_level); + txpwr_level = rtlphy->cur_ofdm24g_txpwridx; + if (_rtl88e_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_G, + txpwr_level) > txpwr_dbm) + txpwr_dbm = + _rtl88e_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, + txpwr_level); + txpwr_level = rtlphy->cur_ofdm24g_txpwridx; + if (_rtl88e_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_N_24G, + txpwr_level) > txpwr_dbm) + txpwr_dbm = + _rtl88e_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, + txpwr_level); + *powerlevel = txpwr_dbm; +} + +static void handle_path_a(struct rtl_efuse *rtlefuse, u8 index, + u8 *cckpowerlevel, u8 *ofdmpowerlevel, + u8 *bw20powerlevel, u8 *bw40powerlevel) +{ + cckpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_cck[RF90_PATH_A][index]; + /*-8~7 */ + if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][index] > 0x0f) + bw20powerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index] - + (~(rtlefuse->txpwr_ht20diff[RF90_PATH_A][index]) + 1); + else + bw20powerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index] + + rtlefuse->txpwr_ht20diff[RF90_PATH_A][index]; + if (rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][index] > 0xf) + ofdmpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index] - + (~(rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][index])+1); + else + ofdmpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index] + + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][index]; + bw40powerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index]; +} + +static void _rtl88e_get_txpower_index(struct ieee80211_hw *hw, u8 channel, + u8 *cckpowerlevel, u8 *ofdmpowerlevel, + u8 *bw20powerlevel, u8 *bw40powerlevel) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 index = (channel - 1); + u8 rf_path = 0; + + for (rf_path = 0; rf_path < 2; rf_path++) { + if (rf_path == RF90_PATH_A) { + handle_path_a(rtlefuse, index, cckpowerlevel, + ofdmpowerlevel, bw20powerlevel, + bw40powerlevel); + } else if (rf_path == RF90_PATH_B) { + cckpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_cck[RF90_PATH_B][index]; + bw20powerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index] + + rtlefuse->txpwr_ht20diff[RF90_PATH_B][index]; + ofdmpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index] + + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][index]; + bw40powerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index]; + } + } + +} + +static void _rtl88e_ccxpower_index_check(struct ieee80211_hw *hw, + u8 channel, u8 *cckpowerlevel, + u8 *ofdmpowerlevel, u8 *bw20powerlevel, + u8 *bw40powerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; + rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; + rtlphy->cur_bw20_txpwridx = bw20powerlevel[0]; + rtlphy->cur_bw40_txpwridx = bw40powerlevel[0]; + +} + +void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 cckpowerlevel[MAX_TX_COUNT] = {0}; + u8 ofdmpowerlevel[MAX_TX_COUNT] = {0}; + u8 bw20powerlevel[MAX_TX_COUNT] = {0}; + u8 bw40powerlevel[MAX_TX_COUNT] = {0}; + + if (!rtlefuse->txpwr_fromeprom) + return; + _rtl88e_get_txpower_index(hw, channel, + &cckpowerlevel[0], &ofdmpowerlevel[0], + &bw20powerlevel[0], &bw40powerlevel[0]); + _rtl88e_ccxpower_index_check(hw, channel, + &cckpowerlevel[0], &ofdmpowerlevel[0], + &bw20powerlevel[0], &bw40powerlevel[0]); + rtl88e_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]); + rtl88e_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], + &bw20powerlevel[0], + &bw40powerlevel[0], channel); +} + +static long _rtl88e_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u8 txpwridx) +{ + long offset; + long pwrout_dbm; + + switch (wirelessmode) { + case WIRELESS_MODE_B: + offset = -7; + break; + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + offset = -8; + break; + default: + offset = -8; + break; + } + pwrout_dbm = txpwridx / 2 + offset; + return pwrout_dbm; +} + +void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + enum io_type iotype; + + if (!is_hal_stop(rtlhal)) { + switch (operation) { + case SCAN_OPT_BACKUP_BAND0: + iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_IO_CMD, + (u8 *)&iotype); + + break; + case SCAN_OPT_RESTORE: + iotype = IO_CMD_RESUME_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_IO_CMD, + (u8 *)&iotype); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Unknown Scan Backup operation.\n"); + break; + } + } +} + +void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 reg_bw_opmode; + u8 reg_prsr_rsc; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz"); + + if (is_hal_stop(rtlhal)) { + rtlphy->set_bwmode_inprogress = false; + return; + } + + reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); + reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + break; + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + reg_prsr_rsc = + (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + /* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);*/ + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); + /*rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);*/ + + rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), + (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + rtl88e_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n"); +} + +void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_bw = rtlphy->current_chan_bw; + + if (rtlphy->set_bwmode_inprogress) + return; + rtlphy->set_bwmode_inprogress = true; + if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtl88e_phy_set_bw_mode_callback(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "false driver sleep or unload\n"); + rtlphy->set_bwmode_inprogress = false; + rtlphy->current_chan_bw = tmp_bw; + } +} + +void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 delay; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "switch to channel%d\n", rtlphy->current_channel); + if (is_hal_stop(rtlhal)) + return; + do { + if (!rtlphy->sw_chnl_inprogress) + break; + if (!_rtl88e_phy_sw_chnl_step_by_step + (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage, + &rtlphy->sw_chnl_step, &delay)) { + if (delay > 0) + mdelay(delay); + else + continue; + } else { + rtlphy->sw_chnl_inprogress = false; + } + break; + } while (true); + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); +} + +u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlphy->sw_chnl_inprogress) + return 0; + if (rtlphy->set_bwmode_inprogress) + return 0; + RT_ASSERT((rtlphy->current_channel <= 14), + "WIRELESS_MODE_G but channel>14"); + rtlphy->sw_chnl_inprogress = true; + rtlphy->sw_chnl_stage = 0; + rtlphy->sw_chnl_step = 0; + if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtl88e_phy_sw_chnl_callback(hw); + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + "sw_chnl_inprogress false schdule workitem current channel %d\n", + rtlphy->current_channel); + rtlphy->sw_chnl_inprogress = false; + } else { + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + "sw_chnl_inprogress false driver sleep or unload\n"); + rtlphy->sw_chnl_inprogress = false; + } + return 1; +} + +static bool _rtl88e_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; + u32 precommoncmdcnt; + struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; + u32 postcommoncmdcnt; + struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; + u32 rfdependcmdcnt; + struct swchnlcmd *currentcmd = NULL; + u8 rfpath; + u8 num_total_rfpath = rtlphy->num_total_rfpath; + + precommoncmdcnt = 0; + _rtl88e_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, + CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); + _rtl88e_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); + + postcommoncmdcnt = 0; + + _rtl88e_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, + MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); + + rfdependcmdcnt = 0; + + RT_ASSERT((channel >= 1 && channel <= 14), + "illegal channel for Zebra: %d\n", channel); + + _rtl88e_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, + RF_CHNLBW, channel, 10); + + _rtl88e_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, + 0); + + do { + switch (*stage) { + case 0: + currentcmd = &precommoncmd[*step]; + break; + case 1: + currentcmd = &rfdependcmd[*step]; + break; + case 2: + currentcmd = &postcommoncmd[*step]; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Invalid 'stage' = %d, Check it!\n", *stage); + return true; + } + + if (currentcmd->cmdid == CMDID_END) { + if ((*stage) == 2) + return true; + (*stage)++; + (*step) = 0; + continue; + } + + switch (currentcmd->cmdid) { + case CMDID_SET_TXPOWEROWER_LEVEL: + rtl88e_phy_set_txpower_level(hw, channel); + break; + case CMDID_WRITEPORT_ULONG: + rtl_write_dword(rtlpriv, currentcmd->para1, + currentcmd->para2); + break; + case CMDID_WRITEPORT_USHORT: + rtl_write_word(rtlpriv, currentcmd->para1, + (u16)currentcmd->para2); + break; + case CMDID_WRITEPORT_UCHAR: + rtl_write_byte(rtlpriv, currentcmd->para1, + (u8)currentcmd->para2); + break; + case CMDID_RF_WRITEREG: + for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { + rtlphy->rfreg_chnlval[rfpath] = + ((rtlphy->rfreg_chnlval[rfpath] & + 0xfffffc00) | currentcmd->para2); + + rtl_set_rfreg(hw, (enum radio_path)rfpath, + currentcmd->para1, + RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[rfpath]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + + break; + } while (true); + + (*delay) = currentcmd->msdelay; + (*step)++; + return false; +} + +static bool _rtl88e_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, + enum swchnlcmd_id cmdid, + u32 para1, u32 para2, u32 msdelay) +{ + struct swchnlcmd *pcmd; + + if (cmdtable == NULL) { + RT_ASSERT(false, "cmdtable cannot be NULL.\n"); + return false; + } + + if (cmdtableidx >= cmdtablesz) + return false; + + pcmd = cmdtable + cmdtableidx; + pcmd->cmdid = cmdid; + pcmd->para1 = para1; + pcmd->para2 = para2; + pcmd->msdelay = msdelay; + return true; +} + +static u8 _rtl88e_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) +{ + u32 reg_eac, reg_e94, reg_e9c, reg_ea4; + u8 result = 0x00; + + rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1c); + rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x30008c1c); + rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x8214032a); + rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x28160000); + + rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); + reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); + reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + return result; +} + +static u8 _rtl88e_phy_path_b_iqk(struct ieee80211_hw *hw) +{ + u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; + u8 result = 0x00; + + rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002); + rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000); + mdelay(IQK_DELAY_TIME); + reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); + reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); + reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); + reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); + + if (!(reg_eac & BIT(31)) && + (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && + (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + if (!(reg_eac & BIT(30)) && + (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + return result; +} + +static u8 _rtl88e_phy_path_a_rx_iqk(struct ieee80211_hw *hw, bool config_pathb) +{ + u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u32temp; + u8 result = 0x00; + + /*Get TXIMR Setting*/ + /*Modify RX IQK mode table*/ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf117b); + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /*IQK Setting*/ + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x81004800); + + /*path a IQK setting*/ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x10008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x30008c1c); + rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160804); + rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160000); + + /*LO calibration Setting*/ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); + /*one shot,path A LOK & iqk*/ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); + reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); + reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); + + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + + u32temp = 0x80007C00 | (reg_e94&0x3FF0000) | + ((reg_e9c&0x3FF0000) >> 16); + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32temp); + /*RX IQK*/ + /*Modify RX IQK mode table*/ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ffa); + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /*IQK Setting*/ + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + + /*path a IQK setting*/ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x30008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x10008c1c); + rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160c05); + rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160c05); + + /*LO calibration Setting*/ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); + /*one shot,path A LOK & iqk*/ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); + reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); + reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); + reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD); + + if (!(reg_eac & BIT(27)) && + (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_eac & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + return result; +} + +static void _rtl88e_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, + bool iqk_ok, long result[][8], + u8 final_candidate, bool btxonly) +{ + u32 oldval_0, x, tx0_a, reg; + long y, tx0_c; + + if (final_candidate == 0xFF) { + return; + } else if (iqk_ok) { + oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD) >> 22) & 0x3FF; + x = result[final_candidate][0]; + if ((x & 0x00000200) != 0) + x = x | 0xFFFFFC00; + tx0_a = (x * oldval_0) >> 8; + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31), + ((x * oldval_0 >> 7) & 0x1)); + y = result[final_candidate][1]; + if ((y & 0x00000200) != 0) + y = y | 0xFFFFFC00; + tx0_c = (y * oldval_0) >> 8; + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, + ((tx0_c & 0x3C0) >> 6)); + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000, + (tx0_c & 0x3F)); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29), + ((y * oldval_0 >> 7) & 0x1)); + if (btxonly) + return; + reg = result[final_candidate][2]; + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg); + reg = result[final_candidate][3] & 0x3F; + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg); + reg = (result[final_candidate][3] >> 6) & 0xF; + rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); + } +} + +static void _rtl88e_phy_save_adda_registers(struct ieee80211_hw *hw, + u32 *addareg, u32 *addabackup, + u32 registernum) +{ + u32 i; + + for (i = 0; i < registernum; i++) + addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD); +} + +static void _rtl88e_phy_save_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) + macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); + macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); +} + +static void _rtl88e_phy_reload_adda_registers(struct ieee80211_hw *hw, + u32 *addareg, u32 *addabackup, + u32 regiesternum) +{ + u32 i; + + for (i = 0; i < regiesternum; i++) + rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]); +} + +static void _rtl88e_phy_reload_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) + rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]); + rtl_write_dword(rtlpriv, macreg[i], macbackup[i]); +} + +static void _rtl88e_phy_path_adda_on(struct ieee80211_hw *hw, + u32 *addareg, bool is_patha_on, bool is2t) +{ + u32 pathon; + u32 i; + + pathon = is_patha_on ? 0x04db25a4 : 0x0b1b25a4; + if (false == is2t) { + pathon = 0x0bdb25a0; + rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0); + } else { + rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon); + } + + for (i = 1; i < IQK_ADDA_REG_NUM; i++) + rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathon); +} + +static void _rtl88e_phy_mac_setting_calibration(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i = 0; + + rtl_write_byte(rtlpriv, macreg[i], 0x3F); + + for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) + rtl_write_byte(rtlpriv, macreg[i], + (u8) (macbackup[i] & (~BIT(3)))); + rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5)))); +} + +static void _rtl88e_phy_path_a_standby(struct ieee80211_hw *hw) +{ + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); +} + +static void _rtl88e_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode) +{ + u32 mode; + + mode = pi_mode ? 0x01000100 : 0x01000000; + rtl_set_bbreg(hw, 0x820, MASKDWORD, mode); + rtl_set_bbreg(hw, 0x828, MASKDWORD, mode); +} + +static bool _rtl88e_phy_simularity_compare(struct ieee80211_hw *hw, + long result[][8], u8 c1, u8 c2) +{ + u32 i, j, diff, simularity_bitmap, bound; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + u8 final_candidate[2] = { 0xFF, 0xFF }; + bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version); + + if (is2t) + bound = 8; + else + bound = 4; + + simularity_bitmap = 0; + + for (i = 0; i < bound; i++) { + diff = (result[c1][i] > result[c2][i]) ? + (result[c1][i] - result[c2][i]) : + (result[c2][i] - result[c1][i]); + + if (diff > MAX_TOLERANCE) { + if ((i == 2 || i == 6) && !simularity_bitmap) { + if (result[c1][i] + result[c1][i + 1] == 0) + final_candidate[(i / 4)] = c2; + else if (result[c2][i] + result[c2][i + 1] == 0) + final_candidate[(i / 4)] = c1; + else + simularity_bitmap = simularity_bitmap | + (1 << i); + } else + simularity_bitmap = + simularity_bitmap | (1 << i); + } + } + + if (simularity_bitmap == 0) { + for (i = 0; i < (bound / 4); i++) { + if (final_candidate[i] != 0xFF) { + for (j = i * 4; j < (i + 1) * 4 - 2; j++) + result[3][j] = + result[final_candidate[i]][j]; + bresult = false; + } + } + return bresult; + } else if (!(simularity_bitmap & 0x0F)) { + for (i = 0; i < 4; i++) + result[3][i] = result[c1][i]; + return false; + } else if (!(simularity_bitmap & 0xF0) && is2t) { + for (i = 4; i < 8; i++) + result[3][i] = result[c1][i]; + return false; + } else { + return false; + } + +} + +static void _rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, + long result[][8], u8 t, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 i; + u8 patha_ok, pathb_ok; + u32 adda_reg[IQK_ADDA_REG_NUM] = { + 0x85c, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec + }; + u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { + 0x522, 0x550, 0x551, 0x040 + }; + u32 iqk_bb_reg[IQK_BB_REG_NUM] = { + ROFDM0_TRXPATHENABLE, ROFDM0_TRMUXPAR, + RFPGA0_XCD_RFINTERFACESW, 0xb68, 0xb6c, + 0x870, 0x860, 0x864, 0x800 + }; + const u32 retrycount = 2; + + if (t == 0) { + _rtl88e_phy_save_adda_registers(hw, adda_reg, + rtlphy->adda_backup, 16); + _rtl88e_phy_save_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + _rtl88e_phy_save_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, + IQK_BB_REG_NUM); + } + _rtl88e_phy_path_adda_on(hw, adda_reg, true, is2t); + if (t == 0) { + rtlphy->rfpi_enable = + (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, BIT(8)); + } + + if (!rtlphy->rfpi_enable) + _rtl88e_phy_pi_mode_switch(hw, true); + /*BB Setting*/ + rtl_set_bbreg(hw, 0x800, BIT(24), 0x00); + rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); + rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); + rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); + + rtl_set_bbreg(hw, 0x870, BIT(10), 0x01); + rtl_set_bbreg(hw, 0x870, BIT(26), 0x01); + rtl_set_bbreg(hw, 0x860, BIT(10), 0x00); + rtl_set_bbreg(hw, 0x864, BIT(10), 0x00); + + if (is2t) { + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); + rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); + } + _rtl88e_phy_mac_setting_calibration(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x0f600000); + if (is2t) + rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x0f600000); + + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); + rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x81004800); + for (i = 0; i < retrycount; i++) { + patha_ok = _rtl88e_phy_path_a_iqk(hw, is2t); + if (patha_ok == 0x01) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Path A Tx IQK Success!!\n"); + result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & + 0x3FF0000) >> 16; + break; + } + } + + for (i = 0; i < retrycount; i++) { + patha_ok = _rtl88e_phy_path_a_rx_iqk(hw, is2t); + if (patha_ok == 0x03) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Path A Rx IQK Success!!\n"); + result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & + 0x3FF0000) >> 16; + break; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Path a RX iqk fail!!!\n"); + } + } + + if (0 == patha_ok) + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Path A IQK Success!!\n"); + if (is2t) { + _rtl88e_phy_path_a_standby(hw); + _rtl88e_phy_path_adda_on(hw, adda_reg, false, is2t); + for (i = 0; i < retrycount; i++) { + pathb_ok = _rtl88e_phy_path_b_iqk(hw); + if (pathb_ok == 0x03) { + result[t][4] = (rtl_get_bbreg(hw, + 0xeb4, + MASKDWORD) & + 0x3FF0000) >> 16; + result[t][5] = + (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][6] = + (rtl_get_bbreg(hw, 0xec4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][7] = + (rtl_get_bbreg(hw, 0xecc, MASKDWORD) & + 0x3FF0000) >> 16; + break; + } else if (i == (retrycount - 1) && pathb_ok == 0x01) { + result[t][4] = (rtl_get_bbreg(hw, + 0xeb4, + MASKDWORD) & + 0x3FF0000) >> 16; + } + result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & + 0x3FF0000) >> 16; + } + } + + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); + + if (t != 0) { + if (!rtlphy->rfpi_enable) + _rtl88e_phy_pi_mode_switch(hw, false); + _rtl88e_phy_reload_adda_registers(hw, adda_reg, + rtlphy->adda_backup, 16); + _rtl88e_phy_reload_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + _rtl88e_phy_reload_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, + IQK_BB_REG_NUM); + + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); + if (is2t) + rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); + rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00); + rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00); + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "88ee IQK Finish!!\n"); +} + +static void _rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) +{ + u8 tmpreg; + u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + tmpreg = rtl_read_byte(rtlpriv, 0xd03); + + if ((tmpreg & 0x70) != 0) + rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); + else + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + + if ((tmpreg & 0x70) != 0) { + rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); + + if (is2t) + rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, + MASK12BITS); + + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, + (rf_a_mode & 0x8FFFF) | 0x10000); + + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + (rf_b_mode & 0x8FFFF) | 0x10000); + } + lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); + + rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); + + mdelay(100); + + if ((tmpreg & 0x70) != 0) { + rtl_write_byte(rtlpriv, 0xd03, tmpreg); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); + + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + rf_b_mode); + } else { + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + } +RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); + +} + +static void _rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, + bool bmain, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); + + if (is_hal_stop(rtlhal)) { + u8 u1btmp; + u1btmp = rtl_read_byte(rtlpriv, REG_LEDCFG0); + rtl_write_byte(rtlpriv, REG_LEDCFG0, u1btmp | BIT(7)); + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); + } + if (is2t) { + if (bmain) + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(6), 0x1); + else + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(6), 0x2); + } else { + rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(8) | BIT(9), 0); + rtl_set_bbreg(hw, 0x914, MASKLWORD, 0x0201); + + /* We use the RF definition of MAIN and AUX, + * left antenna and right antenna repectively. + * Default output at AUX. + */ + if (bmain) { + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, + BIT(14) | BIT(13) | BIT(12), 0); + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(4) | BIT(3), 0); + if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) + rtl_set_bbreg(hw, RCONFIG_RAM64x16, BIT(31), 0); + } else { + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, + BIT(14) | BIT(13) | BIT(12), 1); + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(4) | BIT(3), 1); + if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) + rtl_set_bbreg(hw, RCONFIG_RAM64x16, BIT(31), 1); + } + } +} + +#undef IQK_ADDA_REG_NUM +#undef IQK_DELAY_TIME + +void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + long result[4][8]; + u8 i, final_candidate; + bool b_patha_ok, b_pathb_ok; + long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, + reg_ecc, reg_tmp = 0; + bool is12simular, is13simular, is23simular; + u32 iqk_bb_reg[9] = { + ROFDM0_XARXIQIMBALANCE, + ROFDM0_XBRXIQIMBALANCE, + ROFDM0_ECCATHRESHOLD, + ROFDM0_AGCRSSITABLE, + ROFDM0_XATXIQIMBALANCE, + ROFDM0_XBTXIQIMBALANCE, + ROFDM0_XCTXAFE, + ROFDM0_XDTXAFE, + ROFDM0_RXIQEXTANTA + }; + + if (b_recovery) { + _rtl88e_phy_reload_adda_registers(hw, + iqk_bb_reg, + rtlphy->iqk_bb_backup, 9); + return; + } + + for (i = 0; i < 8; i++) { + result[0][i] = 0; + result[1][i] = 0; + result[2][i] = 0; + result[3][i] = 0; + } + final_candidate = 0xff; + b_patha_ok = false; + b_pathb_ok = false; + is12simular = false; + is23simular = false; + is13simular = false; + for (i = 0; i < 3; i++) { + if (get_rf_type(rtlphy) == RF_2T2R) + _rtl88e_phy_iq_calibrate(hw, result, i, true); + else + _rtl88e_phy_iq_calibrate(hw, result, i, false); + if (i == 1) { + is12simular = + _rtl88e_phy_simularity_compare(hw, result, 0, 1); + if (is12simular) { + final_candidate = 0; + break; + } + } + if (i == 2) { + is13simular = + _rtl88e_phy_simularity_compare(hw, result, 0, 2); + if (is13simular) { + final_candidate = 0; + break; + } + is23simular = + _rtl88e_phy_simularity_compare(hw, result, 1, 2); + if (is23simular) { + final_candidate = 1; + } else { + for (i = 0; i < 8; i++) + reg_tmp += result[3][i]; + + if (reg_tmp != 0) + final_candidate = 3; + else + final_candidate = 0xFF; + } + } + } + for (i = 0; i < 4; i++) { + reg_e94 = result[i][0]; + reg_e9c = result[i][1]; + reg_ea4 = result[i][2]; + reg_eac = result[i][3]; + reg_eb4 = result[i][4]; + reg_ebc = result[i][5]; + reg_ec4 = result[i][6]; + reg_ecc = result[i][7]; + } + if (final_candidate != 0xff) { + reg_e94 = result[final_candidate][0]; + reg_e9c = result[final_candidate][1]; + reg_ea4 = result[final_candidate][2]; + reg_eac = result[final_candidate][3]; + reg_eb4 = result[final_candidate][4]; + reg_ebc = result[final_candidate][5]; + reg_ec4 = result[final_candidate][6]; + reg_ecc = result[final_candidate][7]; + rtlphy->reg_eb4 = reg_eb4; + rtlphy->reg_ebc = reg_ebc; + rtlphy->reg_e94 = reg_e94; + rtlphy->reg_e9c = reg_e9c; + b_patha_ok = true; + b_pathb_ok = true; + } else { + rtlphy->reg_e94 = 0x100; + rtlphy->reg_eb4 = 0x100; + rtlphy->reg_e9c = 0x0; + rtlphy->reg_ebc = 0x0; + } + if (reg_e94 != 0) /*&&(reg_ea4 != 0) */ + _rtl88e_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result, + final_candidate, + (reg_ea4 == 0)); + if (final_candidate != 0xFF) { + for (i = 0; i < IQK_MATRIX_REG_NUM; i++) + rtlphy->iqk_matrix[0].value[0][i] = + result[final_candidate][i]; + rtlphy->iqk_matrix[0].iqk_done = true; + + } + _rtl88e_phy_save_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, 9); +} + +void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = &rtlpriv->rtlhal; + u32 timeout = 2000, timecount = 0; + + while (rtlpriv->mac80211.act_scanning && timecount < timeout) { + udelay(50); + timecount += 50; + } + + rtlphy->lck_inprogress = true; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "LCK:Start!!! currentband %x delay %d ms\n", + rtlhal->current_bandtype, timecount); + + _rtl88e_phy_lc_calibrate(hw, false); + + rtlphy->lck_inprogress = false; +} + +void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) +{ + _rtl88e_phy_set_rfpath_switch(hw, bmain, false); +} + +bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + bool postprocessing = false; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "-->IO Cmd(%#x), set_io_inprogress(%d)\n", + iotype, rtlphy->set_io_inprogress); + do { + switch (iotype) { + case IO_CMD_RESUME_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Resume DM after scan.\n"); + postprocessing = true; + break; + case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Pause DM before scan.\n"); + postprocessing = true; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + } while (false); + if (postprocessing && !rtlphy->set_io_inprogress) { + rtlphy->set_io_inprogress = true; + rtlphy->current_io_type = iotype; + } else { + return false; + } + rtl88e_phy_set_io(hw); + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); + return true; +} + +static void rtl88e_phy_set_io(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "--->Cmd(%#x), set_io_inprogress(%d)\n", + rtlphy->current_io_type, rtlphy->set_io_inprogress); + switch (rtlphy->current_io_type) { + case IO_CMD_RESUME_DM_BY_SCAN: + dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; + /*rtl92c_dm_write_dig(hw);*/ + rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel); + rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x83); + break; + case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: + rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; + dm_digtable->cur_igvalue = 0x17; + rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x40); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + rtlphy->set_io_inprogress = false; + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "(%#x)\n", rtlphy->current_io_type); +} + +static void rtl88ee_phy_set_rf_on(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + /*rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);*/ + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); +} + +static void _rtl88ee_phy_set_rf_sleep(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); +} + +static bool _rtl88ee_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = true; + u8 i, queue_id; + struct rtl8192_tx_ring *ring = NULL; + + switch (rfpwr_state) { + case ERFON: + if ((ppsc->rfpwr_state == ERFOFF) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + bool rtstatus; + u32 initializecount = 0; + + do { + initializecount++; + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic enable\n"); + rtstatus = rtl_ps_enable_nic(hw); + } while (!rtstatus && + (initializecount < 10)); + RT_CLEAR_PS_LEVEL(ppsc, + RT_RF_OFF_LEVL_HALT_NIC); + } else { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFON sleeped:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc-> + last_sleep_jiffies)); + ppsc->last_awake_jiffies = jiffies; + rtl88ee_phy_set_rf_on(hw); + } + if (mac->link_state == MAC80211_LINKED) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } + break; + case ERFOFF: + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (queue_id == BEACON_QUEUE || + skb_queue_len(&ring->queue) == 0) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", + (i + 1), queue_id, + skb_queue_len(&ring->queue)); + + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic disable\n"); + rtl_ps_disable_nic(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } else { + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_POWER_OFF); + } + } + break; + case ERFSLEEP:{ + if (ppsc->rfpwr_state == ERFOFF) + break; + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (skb_queue_len(&ring->queue) == 0) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", + (i + 1), queue_id, + skb_queue_len(&ring->queue)); + + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFSLEEP awaked:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc->last_awake_jiffies)); + ppsc->last_sleep_jiffies = jiffies; + _rtl88ee_phy_set_rf_sleep(hw); + break; + } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + bresult = false; + break; + } + if (bresult) + ppsc->rfpwr_state = rfpwr_state; + return bresult; +} + +bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + bool bresult = false; + + if (rfpwr_state == ppsc->rfpwr_state) + return bresult; + bresult = _rtl88ee_phy_set_rf_power_state(hw, rfpwr_state); + return bresult; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h new file mode 100644 index 000000000000..b29bd77210f4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.h @@ -0,0 +1,233 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_PHY_H__ +#define __RTL92C_PHY_H__ + +/* MAX_TX_COUNT must always set to 4, otherwise read efuse + * table secquence will be wrong. + */ +#define MAX_TX_COUNT 4 + +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define MAX_DOZE_WAITING_TIMES_9x 64 + +#define RT_CANNOT_IO(hw) false +#define HIGHPOWER_RADIOA_ARRAYLEN 22 + +#define IQK_ADDA_REG_NUM 16 +#define IQK_BB_REG_NUM 9 +#define MAX_TOLERANCE 5 +#define IQK_DELAY_TIME 10 +#define INDEX_MAPPING_NUM 15 + +#define APK_BB_REG_NUM 5 +#define APK_AFE_REG_NUM 16 +#define APK_CURVE_REG_NUM 4 +#define PATH_NUM 2 + +#define LOOP_LIMIT 5 +#define MAX_STALL_TIME 50 +#define ANTENNADIVERSITYVALUE 0x80 +#define MAX_TXPWR_IDX_NMODE_92S 63 +#define RESET_CNT_LIMIT 3 + +#define IQK_ADDA_REG_NUM 16 +#define IQK_MAC_REG_NUM 4 + +#define RF6052_MAX_PATH 2 + +#define CT_OFFSET_MAC_ADDR 0X16 + +#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A +#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 +#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 +#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 +#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C + +#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F +#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 + +#define CT_OFFSET_CHANNEL_PLAH 0x75 +#define CT_OFFSET_THERMAL_METER 0x78 +#define CT_OFFSET_RF_OPTION 0x79 +#define CT_OFFSET_VERSION 0x7E +#define CT_OFFSET_CUSTOMER_ID 0x7F + +#define RTL92C_MAX_PATH_NUM 2 + +enum swchnlcmd_id { + CMDID_END, + CMDID_SET_TXPOWEROWER_LEVEL, + CMDID_BBREGWRITE10, + CMDID_WRITEPORT_ULONG, + CMDID_WRITEPORT_USHORT, + CMDID_WRITEPORT_UCHAR, + CMDID_RF_WRITEREG, +}; + +struct swchnlcmd { + enum swchnlcmd_id cmdid; + u32 para1; + u32 para2; + u32 msdelay; +}; + +enum hw90_block_e { + HW90_BLOCK_MAC = 0, + HW90_BLOCK_PHY0 = 1, + HW90_BLOCK_PHY1 = 2, + HW90_BLOCK_RF = 3, + HW90_BLOCK_MAXIMUM = 4, +}; + +enum baseband_config_type { + BASEBAND_CONFIG_PHY_REG = 0, + BASEBAND_CONFIG_AGC_TAB = 1, +}; + +enum ra_offset_area { + RA_OFFSET_LEGACY_OFDM1, + RA_OFFSET_LEGACY_OFDM2, + RA_OFFSET_HT_OFDM1, + RA_OFFSET_HT_OFDM2, + RA_OFFSET_HT_OFDM3, + RA_OFFSET_HT_OFDM4, + RA_OFFSET_HT_CCK, +}; + +enum antenna_path { + ANTENNA_NONE, + ANTENNA_D, + ANTENNA_C, + ANTENNA_CD, + ANTENNA_B, + ANTENNA_BD, + ANTENNA_BC, + ANTENNA_BCD, + ANTENNA_A, + ANTENNA_AD, + ANTENNA_AC, + ANTENNA_ACD, + ANTENNA_AB, + ANTENNA_ABD, + ANTENNA_ABC, + ANTENNA_ABCD +}; + +struct r_antenna_select_ofdm { + u32 r_tx_antenna:4; + u32 r_ant_l:4; + u32 r_ant_non_ht:4; + u32 r_ant_ht1:4; + u32 r_ant_ht2:4; + u32 r_ant_ht_s1:4; + u32 r_ant_non_ht_s1:4; + u32 ofdm_txsc:2; + u32 reserved:2; +}; + +struct r_antenna_select_cck { + u8 r_cckrx_enable_2:2; + u8 r_cckrx_enable:2; + u8 r_ccktx_enable:4; +}; + +struct efuse_contents { + u8 mac_addr[ETH_ALEN]; + u8 cck_tx_power_idx[6]; + u8 ht40_1s_tx_power_idx[6]; + u8 ht40_2s_tx_power_idx_diff[3]; + u8 ht20_tx_power_idx_diff[3]; + u8 ofdm_tx_power_idx_diff[3]; + u8 ht40_max_power_offset[3]; + u8 ht20_max_power_offset[3]; + u8 channel_plan; + u8 thermal_meter; + u8 rf_option[5]; + u8 version; + u8 oem_id; + u8 regulatory; +}; + +struct tx_power_struct { + u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 legacy_ht_txpowerdiff; + u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 pwrgroup_cnt; + u32 mcs_original_offset[4][16]; +}; + +enum _ANT_DIV_TYPE { + NO_ANTDIV = 0xFF, + CG_TRX_HW_ANTDIV = 0x01, + CGCS_RX_HW_ANTDIV = 0x02, + FIXED_HW_ANTDIV = 0x03, + CG_TRX_SMART_ANTDIV = 0x04, + CGCS_RX_SW_ANTDIV = 0x05, +}; + +u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask); +void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, u32 data); +u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask); +void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask, u32 data); +bool rtl88e_phy_mac_config(struct ieee80211_hw *hw); +bool rtl88e_phy_bb_config(struct ieee80211_hw *hw); +bool rtl88e_phy_rf_config(struct ieee80211_hw *hw); +void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, + long *powerlevel); +void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw, + u8 operation); +void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw); +void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); +void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw); +u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw); +void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); +void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw); +void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); +bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); +bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c new file mode 100644 index 000000000000..02013df968a0 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.c @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../pwrseqcmd.h" +#include "pwrseq.h" + +/* drivers should parse below arrays and do the corresponding actions */ +/*3 Power on Array*/ +struct wlan_pwr_cfg rtl8188ee_power_on_flow[RTL8188EE_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8188EE_TRANS_END_STEPS] = { + RTL8188EE_TRANS_CARDEMU_TO_ACT + RTL8188EE_TRANS_END +}; + +/*3Radio off GPIO Array */ +struct wlan_pwr_cfg rtl8188ee_radio_off_flow[RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8188EE_TRANS_END_STEPS] = { + RTL8188EE_TRANS_ACT_TO_CARDEMU + RTL8188EE_TRANS_END +}; + +/*3Card Disable Array*/ +struct wlan_pwr_cfg rtl8188ee_card_disable_flow + [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8188EE_TRANS_END_STEPS] = { + RTL8188EE_TRANS_ACT_TO_CARDEMU + RTL8188EE_TRANS_CARDEMU_TO_CARDDIS + RTL8188EE_TRANS_END +}; + +/*3 Card Enable Array*/ +struct wlan_pwr_cfg rtl8188ee_card_enable_flow + [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8188EE_TRANS_END_STEPS] = { + RTL8188EE_TRANS_CARDDIS_TO_CARDEMU + RTL8188EE_TRANS_CARDEMU_TO_ACT + RTL8188EE_TRANS_END +}; + +/*3Suspend Array*/ +struct wlan_pwr_cfg rtl8188ee_suspend_flow[RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8188EE_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8188EE_TRANS_END_STEPS] = { + RTL8188EE_TRANS_ACT_TO_CARDEMU + RTL8188EE_TRANS_CARDEMU_TO_SUS + RTL8188EE_TRANS_END +}; + +/*3 Resume Array*/ +struct wlan_pwr_cfg rtl8188ee_resume_flow[RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8188EE_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8188EE_TRANS_END_STEPS] = { + RTL8188EE_TRANS_SUS_TO_CARDEMU + RTL8188EE_TRANS_CARDEMU_TO_ACT + RTL8188EE_TRANS_END +}; + +/*3HWPDN Array*/ +struct wlan_pwr_cfg rtl8188ee_hwpdn_flow[RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8188EE_TRANS_END_STEPS] = { + RTL8188EE_TRANS_ACT_TO_CARDEMU + RTL8188EE_TRANS_CARDEMU_TO_PDN + RTL8188EE_TRANS_END +}; + +/*3 Enter LPS */ +struct wlan_pwr_cfg rtl8188ee_enter_lps_flow[RTL8188EE_TRANS_ACT_TO_LPS_STEPS + + RTL8188EE_TRANS_END_STEPS] = { + /*FW behavior*/ + RTL8188EE_TRANS_ACT_TO_LPS + RTL8188EE_TRANS_END +}; + +/*3 Leave LPS */ +struct wlan_pwr_cfg rtl8188ee_leave_lps_flow[RTL8188EE_TRANS_LPS_TO_ACT_STEPS + + RTL8188EE_TRANS_END_STEPS] = { + /*FW behavior*/ + RTL8188EE_TRANS_LPS_TO_ACT + RTL8188EE_TRANS_END +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h new file mode 100644 index 000000000000..f2d9c6116e5c --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h @@ -0,0 +1,311 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_PWRSEQ_H__ +#define __RTL8723E_PWRSEQ_H__ + +#include "../pwrseqcmd.h" +/* Check document WM-20110607-Paul-RTL8188EE_Power_Architecture-R02.vsd + * There are 6 HW Power States: + * 0: POFF--Power Off + * 1: PDN--Power Down + * 2: CARDEMU--Card Emulation + * 3: ACT--Active Mode + * 4: LPS--Low Power State + * 5: SUS--Suspend + * + * The transision from different states are defined below + * TRANS_CARDEMU_TO_ACT + * TRANS_ACT_TO_CARDEMU + * TRANS_CARDEMU_TO_SUS + * TRANS_SUS_TO_CARDEMU + * TRANS_CARDEMU_TO_PDN + * TRANS_ACT_TO_LPS + * TRANS_LPS_TO_ACT + * + * TRANS_END + * PWR SEQ Version: rtl8188ee_PwrSeq_V09.h + */ + +#define RTL8188EE_TRANS_CARDEMU_TO_ACT_STEPS 10 +#define RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS 10 +#define RTL8188EE_TRANS_CARDEMU_TO_SUS_STEPS 10 +#define RTL8188EE_TRANS_SUS_TO_CARDEMU_STEPS 10 +#define RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS 10 +#define RTL8188EE_TRANS_PDN_TO_CARDEMU_STEPS 10 +#define RTL8188EE_TRANS_ACT_TO_LPS_STEPS 15 +#define RTL8188EE_TRANS_LPS_TO_ACT_STEPS 15 +#define RTL8188EE_TRANS_END_STEPS 1 + +/* The following macros have the following format: + * { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value + * comments }, + */ +#define RTL8188EE_TRANS_CARDEMU_TO_ACT \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1) \ + /* wait till 0x04[17] = 1 power ready*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0)|BIT(1), 0 \ + /* 0x02[1:0] = 0 reset BB*/}, \ + {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7) \ + /*0x24[23] = 2b'01 schmit trigger */}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0 \ + /* 0x04[15] = 0 disable HWPDN (control by DRV)*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4)|BIT(3), 0 \ + /*0x04[12:11] = 2b'00 disable WL suspend*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0) \ + /*0x04[8] = 1 polling until return 0*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0 \ + /*wait till 0x04[8] = 0*/}, \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0 \ + /*LDO normal mode*/}, \ + {0x0074, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4) \ + /*SDIO Driving*/}, + +#define RTL8188EE_TRANS_ACT_TO_CARDEMU \ + {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ + /*0x1F[7:0] = 0 turn off RF*/}, \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4) \ + /*LDO Sleep mode*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1) \ + /*0x04[9] = 1 turn off MAC by HW state machine*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0 \ + /*wait till 0x04[9] = 0 polling until return 0 to disable*/}, + +#define RTL8188EE_TRANS_CARDEMU_TO_SUS \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3) \ + /*0x04[12:11] = 2b'01enable WL suspend*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)|BIT(4) \ + /*0x04[12:11] = 2b'11enable WL suspend for PCIe*/}, \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, BIT(7) \ + /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */},\ + {0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0 \ + /*Clear SIC_EN register 0x40[12] = 1'b0 */}, \ + {0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4) \ + /*Set USB suspend enable local register 0xfe10[4]=1 */}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0) \ + /*Set SDIO suspend local register*/}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0 \ + /*wait power state to suspend*/}, + +#define RTL8188EE_TRANS_SUS_TO_CARDEMU \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0 \ + /*Set SDIO suspend local register*/}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1) \ + /*wait power state to suspend*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), 0 \ + /*0x04[12:11] = 2b'01enable WL suspend*/}, + +#define RTL8188EE_TRANS_CARDEMU_TO_CARDDIS \ + {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7) \ + /*0x24[23] = 2b'01 schmit trigger */}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3) \ + /*0x04[12:11] = 2b'01 enable WL suspend*/}, \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ + /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */},\ + {0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0 \ + /*Clear SIC_EN register 0x40[12] = 1'b0 */}, \ + {0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4) \ + /*Set USB suspend enable local register 0xfe10[4]=1 */}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0) \ + /*Set SDIO suspend local register*/}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0 \ + /*wait power state to suspend*/}, + +#define RTL8188EE_TRANS_CARDDIS_TO_CARDEMU \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0 \ + /*Set SDIO suspend local register*/}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1) \ + /*wait power state to suspend*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0 \ + /*0x04[12:11] = 2b'01enable WL suspend*/}, + +#define RTL8188EE_TRANS_CARDEMU_TO_PDN \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0/* 0x04[16] = 0*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7) \ + /* 0x04[15] = 1*/}, + +#define RTL8188EE_TRANS_PDN_TO_CARDEMU \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0/* 0x04[15] = 0*/}, + +#define RTL8188EE_TRANS_ACT_TO_LPS \ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x7F \ + /*Tx Pause*/}, \ + {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ + /*Should be zero if no packet is transmitting*/}, \ + {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ + /*Should be zero if no packet is transmitting*/}, \ + {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ + /*Should be zero if no packet is transmitting*/}, \ + {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ + /*Should be zero if no packet is transmitting*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0 \ + /*CCK and OFDM are disabled,and clock are gated*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US \ + /*Delay 1us*/}, \ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3F \ + /*Reset MAC TRX*/}, \ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0 \ + /*check if removed later*/}, \ + {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5) \ + /*Respond TxOK to scheduler*/}, + + +#define RTL8188EE_TRANS_LPS_TO_ACT \ + {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84 \ + /*SDIO RPWM*/}, \ + {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84 \ + /*USB RPWM*/}, \ + {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84 \ + /*PCIe RPWM*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS \ + /*Delay*/}, \ + {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0 \ + /*. 0x08[4] = 0 switch TSF to 40M*/}, \ + {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0 \ + /*Polling 0x109[7]=0 TSF in 40M*/}, \ + {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0 \ + /*. 0x29[7:6] = 2b'00 enable BB clock*/}, \ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1) \ + /*. 0x101[1] = 1*/}, \ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF \ + /*. 0x100[7:0] = 0xFF enable WMAC TRX*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1)|BIT(0), BIT(1)|BIT(0) \ + /*. 0x02[1:0] = 2b'11 enable BB macro*/}, \ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ + /*. 0x522 = 0*/}, + +#define RTL8188EE_TRANS_END \ + {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + 0, PWR_CMD_END, 0, 0} + +extern struct wlan_pwr_cfg rtl8188ee_power_on_flow + [RTL8188EE_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8188EE_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8188ee_radio_off_flow + [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8188EE_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8188ee_card_disable_flow + [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8188EE_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8188ee_card_enable_flow + [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8188EE_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8188ee_suspend_flow + [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8188EE_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8188EE_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8188ee_resume_flow + [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8188EE_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8188EE_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8188ee_hwpdn_flow + [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8188EE_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8188ee_enter_lps_flow + [RTL8188EE_TRANS_ACT_TO_LPS_STEPS + + RTL8188EE_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8188ee_leave_lps_flow + [RTL8188EE_TRANS_LPS_TO_ACT_STEPS + + RTL8188EE_TRANS_END_STEPS]; + +/* RTL8723 Power Configuration CMDs for PCIe interface */ +#define RTL8188EE_NIC_PWR_ON_FLOW rtl8188ee_power_on_flow +#define RTL8188EE_NIC_RF_OFF_FLOW rtl8188ee_radio_off_flow +#define RTL8188EE_NIC_DISABLE_FLOW rtl8188ee_card_disable_flow +#define RTL8188EE_NIC_ENABLE_FLOW rtl8188ee_card_enable_flow +#define RTL8188EE_NIC_SUSPEND_FLOW rtl8188ee_suspend_flow +#define RTL8188EE_NIC_RESUME_FLOW rtl8188ee_resume_flow +#define RTL8188EE_NIC_PDN_FLOW rtl8188ee_hwpdn_flow +#define RTL8188EE_NIC_LPS_ENTER_FLOW rtl8188ee_enter_lps_flow +#define RTL8188EE_NIC_LPS_LEAVE_FLOW rtl8188ee_leave_lps_flow + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h new file mode 100644 index 000000000000..15400ee6c04b --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/reg.h @@ -0,0 +1,2271 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_REG_H__ +#define __RTL92C_REG_H__ + +#define TXPKT_BUF_SELECT 0x69 +#define RXPKT_BUF_SELECT 0xA5 +#define DISABLE_TRXPKT_BUF_ACCESS 0x0 + +#define REG_SYS_ISO_CTRL 0x0000 +#define REG_SYS_FUNC_EN 0x0002 +#define REG_APS_FSMCO 0x0004 +#define REG_SYS_CLKR 0x0008 +#define REG_9346CR 0x000A +#define REG_EE_VPD 0x000C +#define REG_AFE_MISC 0x0010 +#define REG_SPS0_CTRL 0x0011 +#define REG_SPS_OCP_CFG 0x0018 +#define REG_RSV_CTRL 0x001C +#define REG_RF_CTRL 0x001F +#define REG_LDOA15_CTRL 0x0020 +#define REG_LDOV12D_CTRL 0x0021 +#define REG_LDOHCI12_CTRL 0x0022 +#define REG_LPLDO_CTRL 0x0023 +#define REG_AFE_XTAL_CTRL 0x0024 +/* 1.5v for 8188EE test chip, 1.4v for MP chip */ +#define REG_AFE_LDO_CTRL 0x0027 +#define REG_AFE_PLL_CTRL 0x0028 +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define REG_PWR_DATA 0x0038 +#define REG_CAL_TIMER 0x003C +#define REG_ACLK_MON 0x003E +#define REG_GPIO_MUXCFG 0x0040 +#define REG_GPIO_IO_SEL 0x0042 +#define REG_MAC_PINMUX_CFG 0x0043 +#define REG_GPIO_PIN_CTRL 0x0044 +#define REG_GPIO_INTM 0x0048 +#define REG_LEDCFG0 0x004C +#define REG_LEDCFG1 0x004D +#define REG_LEDCFG2 0x004E +#define REG_LEDCFG3 0x004F +#define REG_FSIMR 0x0050 +#define REG_FSISR 0x0054 +#define REG_HSIMR 0x0058 +#define REG_HSISR 0x005c +#define REG_GPIO_PIN_CTRL_2 0x0060 +#define REG_GPIO_IO_SEL_2 0x0062 +#define REG_GPIO_OUTPUT 0x006c +#define REG_AFE_XTAL_CTRL_EXT 0x0078 +#define REG_XCK_OUT_CTRL 0x007c +#define REG_MCUFWDL 0x0080 +#define REG_WOL_EVENT 0x0081 +#define REG_MCUTSTCFG 0x0084 + +#define REG_HIMR 0x00B0 +#define REG_HISR 0x00B4 +#define REG_HIMRE 0x00B8 +#define REG_HISRE 0x00BC + +#define REG_EFUSE_ACCESS 0x00CF + +#define REG_BIST_SCAN 0x00D0 +#define REG_BIST_RPT 0x00D4 +#define REG_BIST_ROM_RPT 0x00D8 +#define REG_USB_SIE_INTF 0x00E0 +#define REG_PCIE_MIO_INTF 0x00E4 +#define REG_PCIE_MIO_INTD 0x00E8 +#define REG_HPON_FSM 0x00EC +#define REG_SYS_CFG 0x00F0 + +#define REG_CR 0x0100 +#define REG_PBP 0x0104 +#define REG_PKT_BUFF_ACCESS_CTRL 0x0106 +#define REG_TRXDMA_CTRL 0x010C +#define REG_TRXFF_BNDY 0x0114 +#define REG_TRXFF_STATUS 0x0118 +#define REG_RXFF_PTR 0x011C + +#define REG_CPWM 0x012F +#define REG_FWIMR 0x0130 +#define REG_FWISR 0x0134 +#define REG_PKTBUF_DBG_CTRL 0x0140 +#define REG_PKTBUF_DBG_DATA_L 0x0144 +#define REG_PKTBUF_DBG_DATA_H 0x0148 +#define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL+2) + +#define REG_TC0_CTRL 0x0150 +#define REG_TC1_CTRL 0x0154 +#define REG_TC2_CTRL 0x0158 +#define REG_TC3_CTRL 0x015C +#define REG_TC4_CTRL 0x0160 +#define REG_TCUNIT_BASE 0x0164 +#define REG_MBIST_START 0x0174 +#define REG_MBIST_DONE 0x0178 +#define REG_MBIST_FAIL 0x017C +#define REG_32K_CTRL 0x0194 +#define REG_C2HEVT_MSG_NORMAL 0x01A0 +#define REG_C2HEVT_CLEAR 0x01AF +#define REG_C2HEVT_MSG_TEST 0x01B8 +#define REG_MCUTST_1 0x01c0 +#define REG_FMETHR 0x01C8 +#define REG_HMETFR 0x01CC +#define REG_HMEBOX_0 0x01D0 +#define REG_HMEBOX_1 0x01D4 +#define REG_HMEBOX_2 0x01D8 +#define REG_HMEBOX_3 0x01DC + +#define REG_LLT_INIT 0x01E0 +#define REG_BB_ACCEESS_CTRL 0x01E8 +#define REG_BB_ACCESS_DATA 0x01EC + +#define REG_HMEBOX_EXT_0 0x01F0 +#define REG_HMEBOX_EXT_1 0x01F4 +#define REG_HMEBOX_EXT_2 0x01F8 +#define REG_HMEBOX_EXT_3 0x01FC + +#define REG_RQPN 0x0200 +#define REG_FIFOPAGE 0x0204 +#define REG_TDECTRL 0x0208 +#define REG_TXDMA_OFFSET_CHK 0x020C +#define REG_TXDMA_STATUS 0x0210 +#define REG_RQPN_NPQ 0x0214 + +#define REG_RXDMA_AGG_PG_TH 0x0280 +/* FW shall update this register before + * FW write RXPKT_RELEASE_POLL to 1 + */ +#define REG_FW_UPD_RDPTR 0x0284 +/* Control the RX DMA.*/ +#define REG_RXDMA_CONTROL 0x0286 +/* The number of packets in RXPKTBUF. */ +#define REG_RXPKT_NUM 0x0287 + +#define REG_PCIE_CTRL_REG 0x0300 +#define REG_INT_MIG 0x0304 +#define REG_BCNQ_DESA 0x0308 +#define REG_HQ_DESA 0x0310 +#define REG_MGQ_DESA 0x0318 +#define REG_VOQ_DESA 0x0320 +#define REG_VIQ_DESA 0x0328 +#define REG_BEQ_DESA 0x0330 +#define REG_BKQ_DESA 0x0338 +#define REG_RX_DESA 0x0340 + +#define REG_DBI 0x0348 +#define REG_MDIO 0x0354 +#define REG_DBG_SEL 0x0360 +#define REG_PCIE_HRPWM 0x0361 +#define REG_PCIE_HCPWM 0x0363 +#define REG_UART_CTRL 0x0364 +#define REG_WATCH_DOG 0x0368 +#define REG_UART_TX_DESA 0x0370 +#define REG_UART_RX_DESA 0x0378 + +#define REG_HDAQ_DESA_NODEF 0x0000 +#define REG_CMDQ_DESA_NODEF 0x0000 + +#define REG_VOQ_INFORMATION 0x0400 +#define REG_VIQ_INFORMATION 0x0404 +#define REG_BEQ_INFORMATION 0x0408 +#define REG_BKQ_INFORMATION 0x040C +#define REG_MGQ_INFORMATION 0x0410 +#define REG_HGQ_INFORMATION 0x0414 +#define REG_BCNQ_INFORMATION 0x0418 +#define REG_TXPKT_EMPTY 0x041A + +#define REG_CPU_MGQ_INFORMATION 0x041C +#define REG_FWHW_TXQ_CTRL 0x0420 +#define REG_HWSEQ_CTRL 0x0423 +#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 +#define REG_TXPKTBUF_MGQ_BDNY 0x0425 +#define REG_MULTI_BCNQ_EN 0x0426 +#define REG_MULTI_BCNQ_OFFSET 0x0427 +#define REG_SPEC_SIFS 0x0428 +#define REG_RL 0x042A +#define REG_DARFRC 0x0430 +#define REG_RARFRC 0x0438 +#define REG_RRSR 0x0440 +#define REG_ARFR0 0x0444 +#define REG_ARFR1 0x0448 +#define REG_ARFR2 0x044C +#define REG_ARFR3 0x0450 +#define REG_AGGLEN_LMT 0x0458 +#define REG_AMPDU_MIN_SPACE 0x045C +#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D +#define REG_FAST_EDCA_CTRL 0x0460 +#define REG_RD_RESP_PKT_TH 0x0463 +#define REG_INIRTS_RATE_SEL 0x0480 +#define REG_INIDATA_RATE_SEL 0x0484 +#define REG_POWER_STATUS 0x04A4 +#define REG_POWER_STAGE1 0x04B4 +#define REG_POWER_STAGE2 0x04B8 +#define REG_PKT_LIFE_TIME 0x04C0 +#define REG_STBC_SETTING 0x04C4 +#define REG_PROT_MODE_CTRL 0x04C8 +#define REG_BAR_MODE_CTRL 0x04CC +#define REG_RA_TRY_RATE_AGG_LMT 0x04CF +#define REG_EARLY_MODE_CONTROL 0x04D0 +#define REG_NQOS_SEQ 0x04DC +#define REG_QOS_SEQ 0x04DE +#define REG_NEED_CPU_HANDLE 0x04E0 +#define REG_PKT_LOSE_RPT 0x04E1 +#define REG_PTCL_ERR_STATUS 0x04E2 +#define REG_TX_RPT_CTRL 0x04EC +#define REG_TX_RPT_TIME 0x04F0 +#define REG_DUMMY 0x04FC + +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050C +#define REG_BCNTCFG 0x0510 +#define REG_PIFS 0x0512 +#define REG_RDG_PIFS 0x0513 +#define REG_SIFS_CTX 0x0514 +#define REG_SIFS_TRX 0x0516 +#define REG_AGGR_BREAK_TIME 0x051A +#define REG_SLOT 0x051B +#define REG_TX_PTCL_CTRL 0x0520 +#define REG_TXPAUSE 0x0522 +#define REG_DIS_TXREQ_CLR 0x0523 +#define REG_RD_CTRL 0x0524 +#define REG_TBTT_PROHIBIT 0x0540 +#define REG_RD_NAV_NXT 0x0544 +#define REG_NAV_PROT_LEN 0x0546 +#define REG_BCN_CTRL 0x0550 +#define REG_USTIME_TSF 0x0551 +#define REG_MBID_NUM 0x0552 +#define REG_DUAL_TSF_RST 0x0553 +#define REG_BCN_INTERVAL 0x0554 +#define REG_MBSSID_BCN_SPACE 0x0554 +#define REG_DRVERLYINT 0x0558 +#define REG_BCNDMATIM 0x0559 +#define REG_ATIMWND 0x055A +#define REG_BCN_MAX_ERR 0x055D +#define REG_RXTSF_OFFSET_CCK 0x055E +#define REG_RXTSF_OFFSET_OFDM 0x055F +#define REG_TSFTR 0x0560 +#define REG_INIT_TSFTR 0x0564 +#define REG_PSTIMER 0x0580 +#define REG_TIMER0 0x0584 +#define REG_TIMER1 0x0588 +#define REG_ACMHWCTRL 0x05C0 +#define REG_ACMRSTCTRL 0x05C1 +#define REG_ACMAVG 0x05C2 +#define REG_VO_ADMTIME 0x05C4 +#define REG_VI_ADMTIME 0x05C6 +#define REG_BE_ADMTIME 0x05C8 +#define REG_EDCA_RANDOM_GEN 0x05CC +#define REG_SCH_TXCMD 0x05D0 + +#define REG_APSD_CTRL 0x0600 +#define REG_BWOPMODE 0x0603 +#define REG_TCR 0x0604 +#define REG_RCR 0x0608 +#define REG_RX_PKT_LIMIT 0x060C +#define REG_RX_DLK_TIME 0x060D +#define REG_RX_DRVINFO_SZ 0x060F + +#define REG_MACID 0x0610 +#define REG_BSSID 0x0618 +#define REG_MAR 0x0620 +#define REG_MBIDCAMCFG 0x0628 + +#define REG_USTIME_EDCA 0x0638 +#define REG_MAC_SPEC_SIFS 0x063A +#define REG_RESP_SIFS_CCK 0x063C +#define REG_RESP_SIFS_OFDM 0x063E +#define REG_ACKTO 0x0640 +#define REG_CTS2TO 0x0641 +#define REG_EIFS 0x0642 + +#define REG_NAV_CTRL 0x0650 +#define REG_BACAMCMD 0x0654 +#define REG_BACAMCONTENT 0x0658 +#define REG_LBDLY 0x0660 +#define REG_FWDLY 0x0661 +#define REG_RXERR_RPT 0x0664 +#define REG_TRXPTCL_CTL 0x0668 + +#define REG_CAMCMD 0x0670 +#define REG_CAMWRITE 0x0674 +#define REG_CAMREAD 0x0678 +#define REG_CAMDBG 0x067C +#define REG_SECCFG 0x0680 + +#define REG_WOW_CTRL 0x0690 +#define REG_PSSTATUS 0x0691 +#define REG_PS_RX_INFO 0x0692 +#define REG_UAPSD_TID 0x0693 +#define REG_LPNAV_CTRL 0x0694 +#define REG_WKFMCAM_NUM 0x0698 +#define REG_WKFMCAM_RWD 0x069C +#define REG_RXFLTMAP0 0x06A0 +#define REG_RXFLTMAP1 0x06A2 +#define REG_RXFLTMAP2 0x06A4 +#define REG_BCN_PSR_RPT 0x06A8 +#define REG_CALB32K_CTRL 0x06AC +#define REG_PKT_MON_CTRL 0x06B4 +#define REG_BT_COEX_TABLE 0x06C0 +#define REG_WMAC_RESP_TXINFO 0x06D8 + +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_TEST_USB_TXQS 0xFE48 +#define REG_TEST_SIE_VID 0xFE60 +#define REG_TEST_SIE_PID 0xFE62 +#define REG_TEST_SIE_OPTIONAL 0xFE64 +#define REG_TEST_SIE_CHIRP_K 0xFE65 +#define REG_TEST_SIE_PHY 0xFE66 +#define REG_TEST_SIE_MAC_ADDR 0xFE70 +#define REG_TEST_SIE_STRING 0xFE80 + +#define REG_NORMAL_SIE_VID 0xFE60 +#define REG_NORMAL_SIE_PID 0xFE62 +#define REG_NORMAL_SIE_OPTIONAL 0xFE64 +#define REG_NORMAL_SIE_EP 0xFE65 +#define REG_NORMAL_SIE_PHY 0xFE68 +#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 +#define REG_NORMAL_SIE_STRING 0xFE80 + +#define CR9346 REG_9346CR +#define MSR (REG_CR + 2) +#define ISR REG_HISR +#define TSFR REG_TSFTR + +#define MACIDR0 REG_MACID +#define MACIDR4 (REG_MACID + 4) + +#define PBP REG_PBP + +#define IDR0 MACIDR0 +#define IDR4 MACIDR4 + +#define UNUSED_REGISTER 0x1BF +#define DCAM UNUSED_REGISTER +#define PSR UNUSED_REGISTER +#define BBADDR UNUSED_REGISTER +#define PHYDATAR UNUSED_REGISTER + +#define INVALID_BBRF_VALUE 0x12345678 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define CMDEEPROM_EN BIT(5) +#define CMDEEPROM_SEL BIT(4) +#define CMD9346CR_9356SEL BIT(4) +#define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL) +#define AUTOLOAD_EFUSE CMDEEPROM_EN + +#define GPIOSEL_GPIO 0 +#define GPIOSEL_ENBT BIT(5) + +#define GPIO_IN REG_GPIO_PIN_CTRL +#define GPIO_OUT (REG_GPIO_PIN_CTRL+1) +#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) +#define GPIO_MOD (REG_GPIO_PIN_CTRL+3) + +/*8723/8188E Host System Interrupt + *Mask Register (offset 0x58, 32 byte) + */ +#define HSIMR_GPIO12_0_INT_EN BIT(0) +#define HSIMR_SPS_OCP_INT_EN BIT(5) +#define HSIMR_RON_INT_EN BIT(6) +#define HSIMR_PDN_INT_EN BIT(7) +#define HSIMR_GPIO9_INT_EN BIT(25) + +/* 8723/8188E Host System Interrupt + * Status Register (offset 0x5C, 32 byte) + */ +#define HSISR_GPIO12_0_INT BIT(0) +#define HSISR_SPS_OCP_INT BIT(5) +#define HSISR_RON_INT_EN BIT(6) +#define HSISR_PDNINT BIT(7) +#define HSISR_GPIO9_INT BIT(25) + +#define MSR_NOLINK 0x00 +#define MSR_ADHOC 0x01 +#define MSR_INFRA 0x02 +#define MSR_AP 0x03 + +#define RRSR_RSC_OFFSET 21 +#define RRSR_SHORT_OFFSET 23 +#define RRSR_RSC_BW_40M 0x600000 +#define RRSR_RSC_UPSUBCHNL 0x400000 +#define RRSR_RSC_LOWSUBCHNL 0x200000 +#define RRSR_SHORT 0x800000 +#define RRSR_1M BIT(0) +#define RRSR_2M BIT(1) +#define RRSR_5_5M BIT(2) +#define RRSR_11M BIT(3) +#define RRSR_6M BIT(4) +#define RRSR_9M BIT(5) +#define RRSR_12M BIT(6) +#define RRSR_18M BIT(7) +#define RRSR_24M BIT(8) +#define RRSR_36M BIT(9) +#define RRSR_48M BIT(10) +#define RRSR_54M BIT(11) +#define RRSR_MCS0 BIT(12) +#define RRSR_MCS1 BIT(13) +#define RRSR_MCS2 BIT(14) +#define RRSR_MCS3 BIT(15) +#define RRSR_MCS4 BIT(16) +#define RRSR_MCS5 BIT(17) +#define RRSR_MCS6 BIT(18) +#define RRSR_MCS7 BIT(19) +#define BRSR_ACKSHORTPMB BIT(23) + +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 + +#define RATE_1M BIT(0) +#define RATE_2M BIT(1) +#define RATE_5_5M BIT(2) +#define RATE_11M BIT(3) +#define RATE_6M BIT(4) +#define RATE_9M BIT(5) +#define RATE_12M BIT(6) +#define RATE_18M BIT(7) +#define RATE_24M BIT(8) +#define RATE_36M BIT(9) +#define RATE_48M BIT(10) +#define RATE_54M BIT(11) +#define RATE_MCS0 BIT(12) +#define RATE_MCS1 BIT(13) +#define RATE_MCS2 BIT(14) +#define RATE_MCS3 BIT(15) +#define RATE_MCS4 BIT(16) +#define RATE_MCS5 BIT(17) +#define RATE_MCS6 BIT(18) +#define RATE_MCS7 BIT(19) +#define RATE_MCS8 BIT(20) +#define RATE_MCS9 BIT(21) +#define RATE_MCS10 BIT(22) +#define RATE_MCS11 BIT(23) +#define RATE_MCS12 BIT(24) +#define RATE_MCS13 BIT(25) +#define RATE_MCS14 BIT(26) +#define RATE_MCS15 BIT(27) + +#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) +#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\ + RATR_24M | RATR_36M | RATR_48M | RATR_54M) +#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 |\ + RATR_MCS3 | RATR_MCS4 | RATR_MCS5 |\ + RATR_MCS6 | RATR_MCS7) +#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 |\ + RATR_MCS11 | RATR_MCS12 | RATR_MCS13 |\ + RATR_MCS14 | RATR_MCS15) + +#define BW_OPMODE_20MHZ BIT(2) +#define BW_OPMODE_5G BIT(1) +#define BW_OPMODE_11J BIT(0) + +#define CAM_VALID BIT(15) +#define CAM_NOTVALID 0x0000 +#define CAM_USEDK BIT(5) + +#define CAM_NONE 0x0 +#define CAM_WEP40 0x01 +#define CAM_TKIP 0x02 +#define CAM_AES 0x04 +#define CAM_WEP104 0x05 + +#define TOTAL_CAM_ENTRY 32 +#define HALF_CAM_ENTRY 16 + +#define CAM_WRITE BIT(16) +#define CAM_READ 0x00000000 +#define CAM_POLLINIG BIT(31) + +#define SCR_USEDK 0x01 +#define SCR_TXSEC_ENABLE 0x02 +#define SCR_RXSEC_ENABLE 0x04 + +#define WOW_PMEN BIT(0) +#define WOW_WOMEN BIT(1) +#define WOW_MAGIC BIT(2) +#define WOW_UWF BIT(3) + +/********************************************* +* 8188 IMR/ISR bits +**********************************************/ +#define IMR_DISABLED 0x0 +/* IMR DW0(0x0060-0063) Bit 0-31 */ +/* TXRPT interrupt when CCX bit of the packet is set */ +#define IMR_TXCCK BIT(30) +/* Power Save Time Out Interrupt */ +#define IMR_PSTIMEOUT BIT(29) +/* When GTIMER4 expires, this bit is set to 1 */ +#define IMR_GTINT4 BIT(28) +/* When GTIMER3 expires, this bit is set to 1 */ +#define IMR_GTINT3 BIT(27) +/* Transmit Beacon0 Error */ +#define IMR_TBDER BIT(26) +/* Transmit Beacon0 OK */ +#define IMR_TBDOK BIT(25) +/* TSF Timer BIT32 toggle indication interrupt */ +#define IMR_TSF_BIT32_TOGGLE BIT(24) +/* Beacon DMA Interrupt 0 */ +#define IMR_BCNDMAINT0 BIT(20) +/* Beacon Queue DMA OK0 */ +#define IMR_BCNDOK0 BIT(16) +/* HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */ +#define IMR_HSISR_IND_ON_INT BIT(15) +/* Beacon DMA Interrupt Extension for Win7 */ +#define IMR_BCNDMAINT_E BIT(14) +/* CTWidnow End or ATIM Window End */ +#define IMR_ATIMEND BIT(12) +/* HISR1 Indicator (HISR1 & HIMR1 is true, this bit is set to 1)*/ +#define IMR_HISR1_IND_INT BIT(11) +/* CPU to Host Command INT Status, Write 1 clear */ +#define IMR_C2HCMD BIT(10) +/* CPU power Mode exchange INT Status, Write 1 clear */ +#define IMR_CPWM2 BIT(9) +/* CPU power Mode exchange INT Status, Write 1 clear */ +#define IMR_CPWM BIT(8) +/* High Queue DMA OK */ +#define IMR_HIGHDOK BIT(7) +/* Management Queue DMA OK */ +#define IMR_MGNTDOK BIT(6) +/* AC_BK DMA OK */ +#define IMR_BKDOK BIT(5) +/* AC_BE DMA OK */ +#define IMR_BEDOK BIT(4) +/* AC_VI DMA OK */ +#define IMR_VIDOK BIT(3) +/* AC_VO DMA OK */ +#define IMR_VODOK BIT(2) +/* Rx Descriptor Unavailable */ +#define IMR_RDU BIT(1) +/* Receive DMA OK */ +#define IMR_ROK BIT(0) + +/* IMR DW1(0x00B4-00B7) Bit 0-31 */ +/* Beacon DMA Interrupt 7 */ +#define IMR_BCNDMAINT7 BIT(27) +/* Beacon DMA Interrupt 6 */ +#define IMR_BCNDMAINT6 BIT(26) +/* Beacon DMA Interrupt 5 */ +#define IMR_BCNDMAINT5 BIT(25) +/* Beacon DMA Interrupt 4 */ +#define IMR_BCNDMAINT4 BIT(24) +/* Beacon DMA Interrupt 3 */ +#define IMR_BCNDMAINT3 BIT(23) +/* Beacon DMA Interrupt 2 */ +#define IMR_BCNDMAINT2 BIT(22) +/* Beacon DMA Interrupt 1 */ +#define IMR_BCNDMAINT1 BIT(21) +/* Beacon Queue DMA OK Interrup 7 */ +#define IMR_BCNDOK7 BIT(20) +/* Beacon Queue DMA OK Interrup 6 */ +#define IMR_BCNDOK6 BIT(19) +/* Beacon Queue DMA OK Interrup 5 */ +#define IMR_BCNDOK5 BIT(18) +/* Beacon Queue DMA OK Interrup 4 */ +#define IMR_BCNDOK4 BIT(17) +/* Beacon Queue DMA OK Interrup 3 */ +#define IMR_BCNDOK3 BIT(16) +/* Beacon Queue DMA OK Interrup 2 */ +#define IMR_BCNDOK2 BIT(15) +/* Beacon Queue DMA OK Interrup 1 */ +#define IMR_BCNDOK1 BIT(14) +/* ATIM Window End Extension for Win7 */ +#define IMR_ATIMEND_E BIT(13) +/* Tx Error Flag Interrupt Status, write 1 clear. */ +#define IMR_TXERR BIT(11) +/* Rx Error Flag INT Status, Write 1 clear */ +#define IMR_RXERR BIT(10) +/* Transmit FIFO Overflow */ +#define IMR_TXFOVW BIT(9) +/* Receive FIFO Overflow */ +#define IMR_RXFOVW BIT(8) + +#define HWSET_MAX_SIZE 512 +#define EFUSE_MAX_SECTION 64 +#define EFUSE_REAL_CONTENT_LEN 256 +/* PG data exclude header, dummy 7 bytes frome CP test and reserved 1byte.*/ +#define EFUSE_OOB_PROTECT_BYTES 18 + +#define EEPROM_DEFAULT_TSSI 0x0 +#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_BOARDTYPE 0x02 +#define EEPROM_DEFAULT_TXPOWER 0x1010 +#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 + +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_THERMALMETER 0x18 +#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 +#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 +#define EEPROM_DEFAULT_HT20_DIFF 2 +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 +#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 + +#define RF_OPTION1 0x79 +#define RF_OPTION2 0x7A +#define RF_OPTION3 0x7B +#define RF_OPTION4 0x7C + +#define EEPROM_DEFAULT_PID 0x1234 +#define EEPROM_DEFAULT_VID 0x5678 +#define EEPROM_DEFAULT_CUSTOMERID 0xAB +#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD +#define EEPROM_DEFAULT_VERSION 0 + +#define EEPROM_CHANNEL_PLAN_FCC 0x0 +#define EEPROM_CHANNEL_PLAN_IC 0x1 +#define EEPROM_CHANNEL_PLAN_ETSI 0x2 +#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 +#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 +#define EEPROM_CHANNEL_PLAN_MKK 0x5 +#define EEPROM_CHANNEL_PLAN_MKK1 0x6 +#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 +#define EEPROM_CHANNEL_PLAN_TELEC 0x8 +#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 +#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA +#define EEPROM_CHANNEL_PLAN_NCC 0xB +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + +#define EEPROM_CID_DEFAULT 0x0 +#define EEPROM_CID_TOSHIBA 0x4 +#define EEPROM_CID_CCX 0x10 +#define EEPROM_CID_QMI 0x0D +#define EEPROM_CID_WHQL 0xFE + +#define RTL8188E_EEPROM_ID 0x8129 + +#define EEPROM_HPON 0x02 +#define EEPROM_CLK 0x06 +#define EEPROM_TESTR 0x08 + +#define EEPROM_TXPOWERCCK 0x10 +#define EEPROM_TXPOWERHT40_1S 0x16 +#define EEPROM_TXPOWERHT20DIFF 0x1B +#define EEPROM_TXPOWER_OFDMDIFF 0x1B + +#define EEPROM_TX_PWR_INX 0x10 + +#define EEPROM_CHANNELPLAN 0xB8 +#define EEPROM_XTAL_88E 0xB9 +#define EEPROM_THERMAL_METER_88E 0xBA +#define EEPROM_IQK_LCK_88E 0xBB + +#define EEPROM_RF_BOARD_OPTION_88E 0xC1 +#define EEPROM_RF_FEATURE_OPTION_88E 0xC2 +#define EEPROM_RF_BT_SETTING_88E 0xC3 +#define EEPROM_VERSION 0xC4 +#define EEPROM_CUSTOMER_ID 0xC5 +#define EEPROM_RF_ANTENNA_OPT_88E 0xC9 + +#define EEPROM_MAC_ADDR 0xD0 +#define EEPROM_VID 0xD6 +#define EEPROM_DID 0xD8 +#define EEPROM_SVID 0xDA +#define EEPROM_SMID 0xDC + +#define STOPBECON BIT(6) +#define STOPHIGHT BIT(5) +#define STOPMGT BIT(4) +#define STOPVO BIT(3) +#define STOPVI BIT(2) +#define STOPBE BIT(1) +#define STOPBK BIT(0) + +#define RCR_APPFCS BIT(31) +#define RCR_APP_MIC BIT(30) +#define RCR_APP_ICV BIT(29) +#define RCR_APP_PHYST_RXFF BIT(28) +#define RCR_APP_BA_SSN BIT(27) +#define RCR_ENMBID BIT(24) +#define RCR_LSIGEN BIT(23) +#define RCR_MFBEN BIT(22) +#define RCR_HTC_LOC_CTRL BIT(14) +#define RCR_AMF BIT(13) +#define RCR_ACF BIT(12) +#define RCR_ADF BIT(11) +#define RCR_AICV BIT(9) +#define RCR_ACRC32 BIT(8) +#define RCR_CBSSID_BCN BIT(7) +#define RCR_CBSSID_DATA BIT(6) +#define RCR_CBSSID RCR_CBSSID_DATA +#define RCR_APWRMGT BIT(5) +#define RCR_ADD3 BIT(4) +#define RCR_AB BIT(3) +#define RCR_AM BIT(2) +#define RCR_APM BIT(1) +#define RCR_AAP BIT(0) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 + +#define RSV_CTRL 0x001C +#define RD_CTRL 0x0524 + +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_USB_VID 0xFE60 +#define REG_USB_PID 0xFE62 +#define REG_USB_OPTIONAL 0xFE64 +#define REG_USB_CHIRP_K 0xFE65 +#define REG_USB_PHY 0xFE66 +#define REG_USB_MAC_ADDR 0xFE70 +#define REG_USB_HRPWM 0xFE58 +#define REG_USB_HCPWM 0xFE57 + +#define SW18_FPWM BIT(3) + +#define ISO_MD2PP BIT(0) +#define ISO_UA2USB BIT(1) +#define ISO_UD2CORE BIT(2) +#define ISO_PA2PCIE BIT(3) +#define ISO_PD2CORE BIT(4) +#define ISO_IP2MAC BIT(5) +#define ISO_DIOP BIT(6) +#define ISO_DIOE BIT(7) +#define ISO_EB2CORE BIT(8) +#define ISO_DIOR BIT(9) + +#define PWC_EV25V BIT(14) +#define PWC_EV12V BIT(15) + +#define FEN_BBRSTB BIT(0) +#define FEN_BB_GLB_RSTN BIT(1) +#define FEN_USBA BIT(2) +#define FEN_UPLL BIT(3) +#define FEN_USBD BIT(4) +#define FEN_DIO_PCIE BIT(5) +#define FEN_PCIEA BIT(6) +#define FEN_PPLL BIT(7) +#define FEN_PCIED BIT(8) +#define FEN_DIOE BIT(9) +#define FEN_CPUEN BIT(10) +#define FEN_DCORE BIT(11) +#define FEN_ELDR BIT(12) +#define FEN_DIO_RF BIT(13) +#define FEN_HWPDN BIT(14) +#define FEN_MREGEN BIT(15) + +#define PFM_LDALL BIT(0) +#define PFM_ALDN BIT(1) +#define PFM_LDKP BIT(2) +#define PFM_WOWL BIT(3) +#define ENPDN BIT(4) +#define PDN_PL BIT(5) +#define APFM_ONMAC BIT(8) +#define APFM_OFF BIT(9) +#define APFM_RSM BIT(10) +#define AFSM_HSUS BIT(11) +#define AFSM_PCIE BIT(12) +#define APDM_MAC BIT(13) +#define APDM_HOST BIT(14) +#define APDM_HPDN BIT(15) +#define RDY_MACON BIT(16) +#define SUS_HOST BIT(17) +#define ROP_ALD BIT(20) +#define ROP_PWR BIT(21) +#define ROP_SPS BIT(22) +#define SOP_MRST BIT(25) +#define SOP_FUSE BIT(26) +#define SOP_ABG BIT(27) +#define SOP_AMB BIT(28) +#define SOP_RCK BIT(29) +#define SOP_A8M BIT(30) +#define XOP_BTCK BIT(31) + +#define ANAD16V_EN BIT(0) +#define ANA8M BIT(1) +#define MACSLP BIT(4) +#define LOADER_CLK_EN BIT(5) +#define _80M_SSC_DIS BIT(7) +#define _80M_SSC_EN_HO BIT(8) +#define PHY_SSC_RSTB BIT(9) +#define SEC_CLK_EN BIT(10) +#define MAC_CLK_EN BIT(11) +#define SYS_CLK_EN BIT(12) +#define RING_CLK_EN BIT(13) + +#define BOOT_FROM_EEPROM BIT(4) +#define EEPROM_EN BIT(5) + +#define AFE_BGEN BIT(0) +#define AFE_MBEN BIT(1) +#define MAC_ID_EN BIT(7) + +#define WLOCK_ALL BIT(0) +#define WLOCK_00 BIT(1) +#define WLOCK_04 BIT(2) +#define WLOCK_08 BIT(3) +#define WLOCK_40 BIT(4) +#define R_DIS_PRST_0 BIT(5) +#define R_DIS_PRST_1 BIT(6) +#define LOCK_ALL_EN BIT(7) + +#define RF_EN BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + +#define LDA15_EN BIT(0) +#define LDA15_STBY BIT(1) +#define LDA15_OBUF BIT(2) +#define LDA15_REG_VOS BIT(3) +#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) + +#define LDV12_EN BIT(0) +#define LDV12_SDBY BIT(1) +#define LPLDO_HSM BIT(2) +#define LPLDO_LSM_DIS BIT(3) +#define _LDV12_VADJ(x) (((x) & 0xF) << 4) + +#define XTAL_EN BIT(0) +#define XTAL_BSEL BIT(1) +#define _XTAL_BOSC(x) (((x) & 0x3) << 2) +#define _XTAL_CADJ(x) (((x) & 0xF) << 4) +#define XTAL_GATE_USB BIT(8) +#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) +#define XTAL_GATE_AFE BIT(11) +#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) +#define XTAL_RF_GATE BIT(14) +#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) +#define XTAL_GATE_DIG BIT(17) +#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) +#define XTAL_BT_GATE BIT(20) +#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) +#define _XTAL_GPIO(x) (((x) & 0x7) << 23) + +#define CKDLY_AFE BIT(26) +#define CKDLY_USB BIT(27) +#define CKDLY_DIG BIT(28) +#define CKDLY_BT BIT(29) + +#define APLL_EN BIT(0) +#define APLL_320_EN BIT(1) +#define APLL_FREF_SEL BIT(2) +#define APLL_EDGE_SEL BIT(3) +#define APLL_WDOGB BIT(4) +#define APLL_LPFEN BIT(5) + +#define APLL_REF_CLK_13MHZ 0x1 +#define APLL_REF_CLK_19_2MHZ 0x2 +#define APLL_REF_CLK_20MHZ 0x3 +#define APLL_REF_CLK_25MHZ 0x4 +#define APLL_REF_CLK_26MHZ 0x5 +#define APLL_REF_CLK_38_4MHZ 0x6 +#define APLL_REF_CLK_40MHZ 0x7 + +#define APLL_320EN BIT(14) +#define APLL_80EN BIT(15) +#define APLL_1MEN BIT(24) + +#define ALD_EN BIT(18) +#define EF_PD BIT(19) +#define EF_FLAG BIT(31) + +#define EF_TRPT BIT(7) +#define LDOE25_EN BIT(31) + +#define RSM_EN BIT(0) +#define TIMER_EN BIT(4) + +#define TRSW0EN BIT(2) +#define TRSW1EN BIT(3) +#define EROM_EN BIT(4) +#define ENBT BIT(5) +#define ENUART BIT(8) +#define UART_910 BIT(9) +#define ENPMAC BIT(10) +#define SIC_SWRST BIT(11) +#define ENSIC BIT(12) +#define SIC_23 BIT(13) +#define ENHDP BIT(14) +#define SIC_LBK BIT(15) + +#define LED0PL BIT(4) +#define LED1PL BIT(12) +#define LED0DIS BIT(7) + +#define MCUFWDL_EN BIT(0) +#define MCUFWDL_RDY BIT(1) +#define FWDL_CHKSUM_RPT BIT(2) +#define MACINI_RDY BIT(3) +#define BBINI_RDY BIT(4) +#define RFINI_RDY BIT(5) +#define WINTINI_RDY BIT(6) +#define CPRST BIT(23) + +#define XCLK_VLD BIT(0) +#define ACLK_VLD BIT(1) +#define UCLK_VLD BIT(2) +#define PCLK_VLD BIT(3) +#define PCIRSTB BIT(4) +#define V15_VLD BIT(5) +#define TRP_B15V_EN BIT(7) +#define SIC_IDLE BIT(8) +#define BD_MAC2 BIT(9) +#define BD_MAC1 BIT(10) +#define IC_MACPHY_MODE BIT(11) +#define VENDOR_ID BIT(19) +#define PAD_HWPD_IDN BIT(22) +#define TRP_VAUX_EN BIT(23) +#define TRP_BT_EN BIT(24) +#define BD_PKG_SEL BIT(25) +#define BD_HCI_SEL BIT(26) +#define TYPE_ID BIT(27) + +#define CHIP_VER_RTL_MASK 0xF000 +#define CHIP_VER_RTL_SHIFT 12 + +#define REG_LBMODE (REG_CR + 3) + +#define HCI_TXDMA_EN BIT(0) +#define HCI_RXDMA_EN BIT(1) +#define TXDMA_EN BIT(2) +#define RXDMA_EN BIT(3) +#define PROTOCOL_EN BIT(4) +#define SCHEDULE_EN BIT(5) +#define MACTXEN BIT(6) +#define MACRXEN BIT(7) +#define ENSWBCN BIT(8) +#define ENSEC BIT(9) + +#define _NETTYPE(x) (((x) & 0x3) << 16) +#define MASK_NETTYPE 0x30000 +#define NT_NO_LINK 0x0 +#define NT_LINK_AD_HOC 0x1 +#define NT_LINK_AP 0x2 +#define NT_AS_AP 0x3 + +#define _LBMODE(x) (((x) & 0xF) << 24) +#define MASK_LBMODE 0xF000000 +#define LOOPBACK_NORMAL 0x0 +#define LOOPBACK_IMMEDIATELY 0xB +#define LOOPBACK_MAC_DELAY 0x3 +#define LOOPBACK_PHY 0x1 +#define LOOPBACK_DMA 0x7 + +#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) +#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) +#define _PSRX_MASK 0xF +#define _PSTX_MASK 0xF0 +#define _PSRX(x) (x) +#define _PSTX(x) ((x) << 4) + +#define PBP_64 0x0 +#define PBP_128 0x1 +#define PBP_256 0x2 +#define PBP_512 0x3 +#define PBP_1024 0x4 + +#define RXDMA_ARBBW_EN BIT(0) +#define RXSHFT_EN BIT(1) +#define RXDMA_AGG_EN BIT(2) +#define QS_VO_QUEUE BIT(8) +#define QS_VI_QUEUE BIT(9) +#define QS_BE_QUEUE BIT(10) +#define QS_BK_QUEUE BIT(11) +#define QS_MANAGER_QUEUE BIT(12) +#define QS_HIGH_QUEUE BIT(13) + +#define HQSEL_VOQ BIT(0) +#define HQSEL_VIQ BIT(1) +#define HQSEL_BEQ BIT(2) +#define HQSEL_BKQ BIT(3) +#define HQSEL_MGTQ BIT(4) +#define HQSEL_HIQ BIT(5) + +#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) +#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) +#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) +#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) +#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) +#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) + +#define QUEUE_LOW 1 +#define QUEUE_NORMAL 2 +#define QUEUE_HIGH 3 + +#define _LLT_NO_ACTIVE 0x0 +#define _LLT_WRITE_ACCESS 0x1 +#define _LLT_READ_ACCESS 0x2 + +#define _LLT_INIT_DATA(x) ((x) & 0xFF) +#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) +#define _LLT_OP(x) (((x) & 0x3) << 30) +#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) + +#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) +#define BB_WRITE_EN BIT(30) +#define BB_READ_EN BIT(31) + +#define _HPQ(x) ((x) & 0xFF) +#define _LPQ(x) (((x) & 0xFF) << 8) +#define _PUBQ(x) (((x) & 0xFF) << 16) +#define _NPQ(x) ((x) & 0xFF) + +#define HPQ_PUBLIC_DIS BIT(24) +#define LPQ_PUBLIC_DIS BIT(25) +#define LD_RQPN BIT(31) + +#define BCN_VALID BIT(16) +#define BCN_HEAD(x) (((x) & 0xFF) << 8) +#define BCN_HEAD_MASK 0xFF00 + +#define BLK_DESC_NUM_SHIFT 4 +#define BLK_DESC_NUM_MASK 0xF + +#define DROP_DATA_EN BIT(9) + +#define EN_AMPDU_RTY_NEW BIT(7) + +#define _INIRTSMCS_SEL(x) ((x) & 0x3F) + +#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) +#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) + +#define RATE_REG_BITMAP_ALL 0xFFFFF + +#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) + +#define _RRSR_RSC(x) (((x) & 0x3) << 21) +#define RRSR_RSC_RESERVED 0x0 +#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 +#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 +#define RRSR_RSC_DUPLICATE_MODE 0x3 + +#define USE_SHORT_G1 BIT(20) + +#define _AGGLMT_MCS0(x) ((x) & 0xF) +#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) +#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) +#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) +#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) +#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) +#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) +#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) + +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + +#define _DARF_RC1(x) ((x) & 0x1F) +#define _DARF_RC2(x) (((x) & 0x1F) << 8) +#define _DARF_RC3(x) (((x) & 0x1F) << 16) +#define _DARF_RC4(x) (((x) & 0x1F) << 24) +#define _DARF_RC5(x) ((x) & 0x1F) +#define _DARF_RC6(x) (((x) & 0x1F) << 8) +#define _DARF_RC7(x) (((x) & 0x1F) << 16) +#define _DARF_RC8(x) (((x) & 0x1F) << 24) + +#define _RARF_RC1(x) ((x) & 0x1F) +#define _RARF_RC2(x) (((x) & 0x1F) << 8) +#define _RARF_RC3(x) (((x) & 0x1F) << 16) +#define _RARF_RC4(x) (((x) & 0x1F) << 24) +#define _RARF_RC5(x) ((x) & 0x1F) +#define _RARF_RC6(x) (((x) & 0x1F) << 8) +#define _RARF_RC7(x) (((x) & 0x1F) << 16) +#define _RARF_RC8(x) (((x) & 0x1F) << 24) + +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + +#define _AIFS(x) (x) +#define _ECW_MAX_MIN(x) ((x) << 8) +#define _TXOP_LIMIT(x) ((x) << 16) + +#define _BCNIFS(x) ((x) & 0xFF) +#define _BCNECW(x) ((((x) & 0xF)) << 8) + +#define _LRL(x) ((x) & 0x3F) +#define _SRL(x) (((x) & 0x3F) << 8) + +#define _SIFS_CCK_CTX(x) ((x) & 0xFF) +#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8); + +#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) +#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8); + +#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) + +#define DIS_EDCA_CNT_DWN BIT(11) + +#define EN_MBSSID BIT(1) +#define EN_TXBCN_RPT BIT(2) +#define EN_BCN_FUNCTION BIT(3) + +#define TSFTR_RST BIT(0) +#define TSFTR1_RST BIT(1) + +#define STOP_BCNQ BIT(6) + +#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) +#define DIS_TSF_UDT0_TEST_CHIP BIT(5) + +#define ACMHW_HWEN BIT(0) +#define ACMHW_BEQEN BIT(1) +#define ACMHW_VIQEN BIT(2) +#define ACMHW_VOQEN BIT(3) +#define ACMHW_BEQSTATUS BIT(4) +#define ACMHW_VIQSTATUS BIT(5) +#define ACMHW_VOQSTATUS BIT(6) + +#define APSDOFF BIT(6) +#define APSDOFF_STATUS BIT(7) + +#define BW_20MHZ BIT(2) + +#define RATE_BITMAP_ALL 0xFFFFF + +#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 + +#define TSFRST BIT(0) +#define DIS_GCLK BIT(1) +#define PAD_SEL BIT(2) +#define PWR_ST BIT(6) +#define PWRBIT_OW_EN BIT(7) +#define ACRC BIT(8) +#define CFENDFORM BIT(9) +#define ICV BIT(10) + +#define AAP BIT(0) +#define APM BIT(1) +#define AM BIT(2) +#define AB BIT(3) +#define ADD3 BIT(4) +#define APWRMGT BIT(5) +#define CBSSID BIT(6) +#define CBSSID_DATA BIT(6) +#define CBSSID_BCN BIT(7) +#define ACRC32 BIT(8) +#define AICV BIT(9) +#define ADF BIT(11) +#define ACF BIT(12) +#define AMF BIT(13) +#define HTC_LOC_CTRL BIT(14) +#define UC_DATA_EN BIT(16) +#define BM_DATA_EN BIT(17) +#define MFBEN BIT(22) +#define LSIGEN BIT(23) +#define ENMBID BIT(24) +#define APP_BASSN BIT(27) +#define APP_PHYSTS BIT(28) +#define APP_ICV BIT(29) +#define APP_MIC BIT(30) +#define APP_FCS BIT(31) + +#define _MIN_SPACE(x) ((x) & 0x7) +#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) + +#define RXERR_TYPE_OFDM_PPDU 0 +#define RXERR_TYPE_OFDM_FALSE_ALARM 1 +#define RXERR_TYPE_OFDM_MPDU_OK 2 +#define RXERR_TYPE_OFDM_MPDU_FAIL 3 +#define RXERR_TYPE_CCK_PPDU 4 +#define RXERR_TYPE_CCK_FALSE_ALARM 5 +#define RXERR_TYPE_CCK_MPDU_OK 6 +#define RXERR_TYPE_CCK_MPDU_FAIL 7 +#define RXERR_TYPE_HT_PPDU 8 +#define RXERR_TYPE_HT_FALSE_ALARM 9 +#define RXERR_TYPE_HT_MPDU_TOTAL 10 +#define RXERR_TYPE_HT_MPDU_OK 11 +#define RXERR_TYPE_HT_MPDU_FAIL 12 +#define RXERR_TYPE_RX_FULL_DROP 15 + +#define RXERR_COUNTER_MASK 0xFFFFF +#define RXERR_RPT_RST BIT(27) +#define _RXERR_RPT_SEL(type) ((type) << 28) + +#define SCR_TXUSEDK BIT(0) +#define SCR_RXUSEDK BIT(1) +#define SCR_TXENCENABLE BIT(2) +#define SCR_RXDECENABLE BIT(3) +#define SCR_SKBYA2 BIT(4) +#define SCR_NOSKMC BIT(5) +#define SCR_TXBCUSEDK BIT(6) +#define SCR_RXBCUSEDK BIT(7) + +#define USB_IS_HIGH_SPEED 0 +#define USB_IS_FULL_SPEED 1 +#define USB_SPEED_MASK BIT(5) + +#define USB_NORMAL_SIE_EP_MASK 0xF +#define USB_NORMAL_SIE_EP_SHIFT 4 + +#define USB_TEST_EP_MASK 0x30 +#define USB_TEST_EP_SHIFT 4 + +#define USB_AGG_EN BIT(3) + +#define MAC_ADDR_LEN 6 +#define LAST_ENTRY_OF_TX_PKT_BUFFER 175/*255 88e*/ + +#define POLLING_LLT_THRESHOLD 20 +#define POLLING_READY_TIMEOUT_COUNT 3000 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) +#define EPROM_CMD_CONFIG 0x3 +#define EPROM_CMD_LOAD 1 + +#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE + +#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) + +#define RPMAC_RESET 0x100 +#define RPMAC_TXSTART 0x104 +#define RPMAC_TXLEGACYSIG 0x108 +#define RPMAC_TXHTSIG1 0x10c +#define RPMAC_TXHTSIG2 0x110 +#define RPMAC_PHYDEBUG 0x114 +#define RPMAC_TXPACKETNUM 0x118 +#define RPMAC_TXIDLE 0x11c +#define RPMAC_TXMACHEADER0 0x120 +#define RPMAC_TXMACHEADER1 0x124 +#define RPMAC_TXMACHEADER2 0x128 +#define RPMAC_TXMACHEADER3 0x12c +#define RPMAC_TXMACHEADER4 0x130 +#define RPMAC_TXMACHEADER5 0x134 +#define RPMAC_TXDADATYPE 0x138 +#define RPMAC_TXRANDOMSEED 0x13c +#define RPMAC_CCKPLCPPREAMBLE 0x140 +#define RPMAC_CCKPLCPHEADER 0x144 +#define RPMAC_CCKCRC16 0x148 +#define RPMAC_OFDMRXCRC32OK 0x170 +#define RPMAC_OFDMRXCRC32ER 0x174 +#define RPMAC_OFDMRXPARITYER 0x178 +#define RPMAC_OFDMRXCRC8ER 0x17c +#define RPMAC_CCKCRXRC16ER 0x180 +#define RPMAC_CCKCRXRC32ER 0x184 +#define RPMAC_CCKCRXRC32OK 0x188 +#define RPMAC_TXSTATUS 0x18c + +#define RFPGA0_RFMOD 0x800 + +#define RFPGA0_TXINFO 0x804 +#define RFPGA0_PSDFUNCTION 0x808 + +#define RFPGA0_TXGAINSTAGE 0x80c + +#define RFPGA0_RFTIMING1 0x810 +#define RFPGA0_RFTIMING2 0x814 + +#define RFPGA0_XA_HSSIPARAMETER1 0x820 +#define RFPGA0_XA_HSSIPARAMETER2 0x824 +#define RFPGA0_XB_HSSIPARAMETER1 0x828 +#define RFPGA0_XB_HSSIPARAMETER2 0x82c + +#define RFPGA0_XA_LSSIPARAMETER 0x840 +#define RFPGA0_XB_LSSIPARAMETER 0x844 + +#define RFPGA0_RFWAKEUPPARAMETER 0x850 +#define RFPGA0_RFSLEEPUPPARAMETER 0x854 + +#define RFPGA0_XAB_SWITCHCONTROL 0x858 +#define RFPGA0_XCD_SWITCHCONTROL 0x85c + +#define RFPGA0_XA_RFINTERFACEOE 0x860 +#define RFPGA0_XB_RFINTERFACEOE 0x864 + +#define RFPGA0_XAB_RFINTERFACESW 0x870 +#define RFPGA0_XCD_RFINTERFACESW 0x874 + +#define RFPGA0_XAB_RFPARAMETER 0x878 +#define RFPGA0_XCD_RFPARAMETER 0x87c + +#define RFPGA0_ANALOGPARAMETER1 0x880 +#define RFPGA0_ANALOGPARAMETER2 0x884 +#define RFPGA0_ANALOGPARAMETER3 0x888 +#define RFPGA0_ANALOGPARAMETER4 0x88c + +#define RFPGA0_XA_LSSIREADBACK 0x8a0 +#define RFPGA0_XB_LSSIREADBACK 0x8a4 +#define RFPGA0_XC_LSSIREADBACK 0x8a8 +#define RFPGA0_XD_LSSIREADBACK 0x8ac + +#define RFPGA0_PSDREPORT 0x8b4 +#define TRANSCEIVEA_HSPI_READBACK 0x8b8 +#define TRANSCEIVEB_HSPI_READBACK 0x8bc +#define REG_SC_CNT 0x8c4 +#define RFPGA0_XAB_RFINTERFACERB 0x8e0 +#define RFPGA0_XCD_RFINTERFACERB 0x8e4 + +#define RFPGA1_RFMOD 0x900 + +#define RFPGA1_TXBLOCK 0x904 +#define RFPGA1_DEBUGSELECT 0x908 +#define RFPGA1_TXINFO 0x90c + +#define RCCK0_SYSTEM 0xa00 + +#define RCCK0_AFESETTING 0xa04 +#define RCCK0_CCA 0xa08 + +#define RCCK0_RXAGC1 0xa0c +#define RCCK0_RXAGC2 0xa10 + +#define RCCK0_RXHP 0xa14 + +#define RCCK0_DSPPARAMETER1 0xa18 +#define RCCK0_DSPPARAMETER2 0xa1c + +#define RCCK0_TXFILTER1 0xa20 +#define RCCK0_TXFILTER2 0xa24 +#define RCCK0_DEBUGPORT 0xa28 +#define RCCK0_FALSEALARMREPORT 0xa2c +#define RCCK0_TRSSIREPORT 0xa50 +#define RCCK0_RXREPORT 0xa54 +#define RCCK0_FACOUNTERLOWER 0xa5c +#define RCCK0_FACOUNTERUPPER 0xa58 +#define RCCK0_CCA_CNT 0xa60 + +/* PageB(0xB00) */ +#define RPDP_ANTA 0xb00 +#define RPDP_ANTA_4 0xb04 +#define RPDP_ANTA_8 0xb08 +#define RPDP_ANTA_C 0xb0c +#define RPDP_ANTA_10 0xb10 +#define RPDP_ANTA_14 0xb14 +#define RPDP_ANTA_18 0xb18 +#define RPDP_ANTA_1C 0xb1c +#define RPDP_ANTA_20 0xb20 +#define RPDP_ANTA_24 0xb24 + +#define RCONFIG_PMPD_ANTA 0xb28 +#define RCONFIG_RAM64x16 0xb2c + +#define RBNDA 0xb30 +#define RHSSIPAR 0xb34 + +#define RCONFIG_ANTA 0xb68 +#define RCONFIG_ANTB 0xb6c + +#define RPDP_ANTB 0xb70 +#define RPDP_ANTB_4 0xb74 +#define RPDP_ANTB_8 0xb78 +#define RPDP_ANTB_C 0xb7c +#define RPDP_ANTB_10 0xb80 +#define RPDP_ANTB_14 0xb84 +#define RPDP_ANTB_18 0xb88 +#define RPDP_ANTB_1C 0xb8c +#define RPDP_ANTB_20 0xb90 +#define RPDP_ANTB_24 0xb94 + +#define RCONFIG_PMPD_ANTB 0xb98 + +#define RBNDB 0xba0 + +#define RAPK 0xbd8 +#define RPM_RX0_ANTA 0xbdc +#define RPM_RX1_ANTA 0xbe0 +#define RPM_RX2_ANTA 0xbe4 +#define RPM_RX3_ANTA 0xbe8 +#define RPM_RX0_ANTB 0xbec +#define RPM_RX1_ANTB 0xbf0 +#define RPM_RX2_ANTB 0xbf4 +#define RPM_RX3_ANTB 0xbf8 + +/*Page C*/ +#define ROFDM0_LSTF 0xc00 + +#define ROFDM0_TRXPATHENABLE 0xc04 +#define ROFDM0_TRMUXPAR 0xc08 +#define ROFDM0_TRSWISOLATION 0xc0c + +#define ROFDM0_XARXAFE 0xc10 +#define ROFDM0_XARXIQIMBALANCE 0xc14 +#define ROFDM0_XBRXAFE 0xc18 +#define ROFDM0_XBRXIQIMBALANCE 0xc1c +#define ROFDM0_XCRXAFE 0xc20 +#define ROFDM0_XCRXIQIMBANLANCE 0xc24 +#define ROFDM0_XDRXAFE 0xc28 +#define ROFDM0_XDRXIQIMBALANCE 0xc2c + +#define ROFDM0_RXDETECTOR1 0xc30 +#define ROFDM0_RXDETECTOR2 0xc34 +#define ROFDM0_RXDETECTOR3 0xc38 +#define ROFDM0_RXDETECTOR4 0xc3c + +#define ROFDM0_RXDSP 0xc40 +#define ROFDM0_CFOANDDAGC 0xc44 +#define ROFDM0_CCADROPTHRESHOLD 0xc48 +#define ROFDM0_ECCATHRESHOLD 0xc4c + +#define ROFDM0_XAAGCCORE1 0xc50 +#define ROFDM0_XAAGCCORE2 0xc54 +#define ROFDM0_XBAGCCORE1 0xc58 +#define ROFDM0_XBAGCCORE2 0xc5c +#define ROFDM0_XCAGCCORE1 0xc60 +#define ROFDM0_XCAGCCORE2 0xc64 +#define ROFDM0_XDAGCCORE1 0xc68 +#define ROFDM0_XDAGCCORE2 0xc6c + +#define ROFDM0_AGCPARAMETER1 0xc70 +#define ROFDM0_AGCPARAMETER2 0xc74 +#define ROFDM0_AGCRSSITABLE 0xc78 +#define ROFDM0_HTSTFAGC 0xc7c + +#define ROFDM0_XATXIQIMBALANCE 0xc80 +#define ROFDM0_XATXAFE 0xc84 +#define ROFDM0_XBTXIQIMBALANCE 0xc88 +#define ROFDM0_XBTXAFE 0xc8c +#define ROFDM0_XCTXIQIMBALANCE 0xc90 +#define ROFDM0_XCTXAFE 0xc94 +#define ROFDM0_XDTXIQIMBALANCE 0xc98 +#define ROFDM0_XDTXAFE 0xc9c + +#define ROFDM0_RXIQEXTANTA 0xca0 +#define ROFDM0_TXCOEFF1 0xca4 +#define ROFDM0_TXCOEFF2 0xca8 +#define ROFDM0_TXCOEFF3 0xcac +#define ROFDM0_TXCOEFF4 0xcb0 +#define ROFDM0_TXCOEFF5 0xcb4 +#define ROFDM0_TXCOEFF6 0xcb8 + +#define ROFDM0_RXHPPARAMETER 0xce0 +#define ROFDM0_TXPSEUDONOISEWGT 0xce4 +#define ROFDM0_FRAMESYNC 0xcf0 +#define ROFDM0_DFSREPORT 0xcf4 + +#define ROFDM1_LSTF 0xd00 +#define ROFDM1_TRXPATHENABLE 0xd04 + +#define ROFDM1_CF0 0xd08 +#define ROFDM1_CSI1 0xd10 +#define ROFDM1_SBD 0xd14 +#define ROFDM1_CSI2 0xd18 +#define ROFDM1_CFOTRACKING 0xd2c +#define ROFDM1_TRXMESAURE1 0xd34 +#define ROFDM1_INTFDET 0xd3c +#define ROFDM1_PSEUDONOISESTATEAB 0xd50 +#define ROFDM1_PSEUDONOISESTATECD 0xd54 +#define ROFDM1_RXPSEUDONOISEWGT 0xd58 + +#define ROFDM_PHYCOUNTER1 0xda0 +#define ROFDM_PHYCOUNTER2 0xda4 +#define ROFDM_PHYCOUNTER3 0xda8 + +#define ROFDM_SHORTCFOAB 0xdac +#define ROFDM_SHORTCFOCD 0xdb0 +#define ROFDM_LONGCFOAB 0xdb4 +#define ROFDM_LONGCFOCD 0xdb8 +#define ROFDM_TAILCF0AB 0xdbc +#define ROFDM_TAILCF0CD 0xdc0 +#define ROFDM_PWMEASURE1 0xdc4 +#define ROFDM_PWMEASURE2 0xdc8 +#define ROFDM_BWREPORT 0xdcc +#define ROFDM_AGCREPORT 0xdd0 +#define ROFDM_RXSNR 0xdd4 +#define ROFDM_RXEVMCSI 0xdd8 +#define ROFDM_SIGREPORT 0xddc + +#define RTXAGC_A_RATE18_06 0xe00 +#define RTXAGC_A_RATE54_24 0xe04 +#define RTXAGC_A_CCK1_MCS32 0xe08 +#define RTXAGC_A_MCS03_MCS00 0xe10 +#define RTXAGC_A_MCS07_MCS04 0xe14 +#define RTXAGC_A_MCS11_MCS08 0xe18 +#define RTXAGC_A_MCS15_MCS12 0xe1c + +#define RTXAGC_B_RATE18_06 0x830 +#define RTXAGC_B_RATE54_24 0x834 +#define RTXAGC_B_CCK1_55_MCS32 0x838 +#define RTXAGC_B_MCS03_MCS00 0x83c +#define RTXAGC_B_MCS07_MCS04 0x848 +#define RTXAGC_B_MCS11_MCS08 0x84c +#define RTXAGC_B_MCS15_MCS12 0x868 +#define RTXAGC_B_CCK11_A_CCK2_11 0x86c + +#define RFPGA0_IQK 0xe28 +#define RTX_IQK_TONE_A 0xe30 +#define RRX_IQK_TONE_A 0xe34 +#define RTX_IQK_PI_A 0xe38 +#define RRX_IQK_PI_A 0xe3c + +#define RTX_IQK 0xe40 +#define RRX_IQK 0xe44 +#define RIQK_AGC_PTS 0xe48 +#define RIQK_AGC_RSP 0xe4c +#define RTX_IQK_TONE_B 0xe50 +#define RRX_IQK_TONE_B 0xe54 +#define RTX_IQK_PI_B 0xe58 +#define RRX_IQK_PI_B 0xe5c +#define RIQK_AGC_CONT 0xe60 + +#define RBLUE_TOOTH 0xe6c +#define RRX_WAIT_CCA 0xe70 +#define RTX_CCK_RFON 0xe74 +#define RTX_CCK_BBON 0xe78 +#define RTX_OFDM_RFON 0xe7c +#define RTX_OFDM_BBON 0xe80 +#define RTX_TO_RX 0xe84 +#define RTX_TO_TX 0xe88 +#define RRX_CCK 0xe8c + +#define RTX_POWER_BEFORE_IQK_A 0xe94 +#define RTX_POWER_AFTER_IQK_A 0xe9c + +#define RRX_POWER_BEFORE_IQK_A 0xea0 +#define RRX_POWER_BEFORE_IQK_A_2 0xea4 +#define RRX_POWER_AFTER_IQK_A 0xea8 +#define RRX_POWER_AFTER_IQK_A_2 0xeac + +#define RTX_POWER_BEFORE_IQK_B 0xeb4 +#define RTX_POWER_AFTER_IQK_B 0xebc + +#define RRX_POWER_BEFORE_IQK_B 0xec0 +#define RRX_POWER_BEFORE_IQK_B_2 0xec4 +#define RRX_POWER_AFTER_IQK_B 0xec8 +#define RRX_POWER_AFTER_IQK_B_2 0xecc + +#define RRX_OFDM 0xed0 +#define RRX_WAIT_RIFS 0xed4 +#define RRX_TO_RX 0xed8 +#define RSTANDBY 0xedc +#define RSLEEP 0xee0 +#define RPMPD_ANAEN 0xeec + +#define RZEBRA1_HSSIENABLE 0x0 +#define RZEBRA1_TRXENABLE1 0x1 +#define RZEBRA1_TRXENABLE2 0x2 +#define RZEBRA1_AGC 0x4 +#define RZEBRA1_CHARGEPUMP 0x5 +#define RZEBRA1_CHANNEL 0x7 + +#define RZEBRA1_TXGAIN 0x8 +#define RZEBRA1_TXLPF 0x9 +#define RZEBRA1_RXLPF 0xb +#define RZEBRA1_RXHPFCORNER 0xc + +#define RGLOBALCTRL 0 +#define RRTL8256_TXLPF 19 +#define RRTL8256_RXLPF 11 +#define RRTL8258_TXLPF 0x11 +#define RRTL8258_RXLPF 0x13 +#define RRTL8258_RSSILPF 0xa + +#define RF_AC 0x00 + +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_POW_TRSW 0x05 + +#define RF_GAIN_RX 0x06 +#define RF_GAIN_TX 0x07 + +#define RF_TXM_IDAC 0x08 +#define RF_BS_IQGEN 0x0F + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 + +#define RF_RX_AGC_HP 0x12 +#define RF_TX_AGC 0x13 +#define RF_BIAS 0x14 +#define RF_IPA 0x15 +#define RF_POW_ABILITY 0x17 +#define RF_MODE_AG 0x18 +#define RRFCHANNEL 0x18 +#define RF_CHNLBW 0x18 +#define RF_TOP 0x19 + +#define RF_RX_G1 0x1A +#define RF_RX_G2 0x1B + +#define RF_RX_BB2 0x1C +#define RF_RX_BB1 0x1D + +#define RF_RCK1 0x1E +#define RF_RCK2 0x1F + +#define RF_TX_G1 0x20 +#define RF_TX_G2 0x21 +#define RF_TX_G3 0x22 + +#define RF_TX_BB1 0x23 +#define RF_T_METER 0x42 + +#define RF_SYN_G1 0x25 +#define RF_SYN_G2 0x26 +#define RF_SYN_G3 0x27 +#define RF_SYN_G4 0x28 +#define RF_SYN_G5 0x29 +#define RF_SYN_G6 0x2A +#define RF_SYN_G7 0x2B +#define RF_SYN_G8 0x2C + +#define RF_RCK_OS 0x30 +#define RF_TXPA_G1 0x31 +#define RF_TXPA_G2 0x32 +#define RF_TXPA_G3 0x33 + +#define RF_TX_BIAS_A 0x35 +#define RF_TX_BIAS_D 0x36 +#define RF_LOBF_9 0x38 +#define RF_RXRF_A3 0x3C +#define RF_TRSW 0x3F + +#define RF_TXRF_A2 0x41 +#define RF_TXPA_G4 0x46 +#define RF_TXPA_A4 0x4B + +#define RF_WE_LUT 0xEF + +#define BBBRESETB 0x100 +#define BGLOBALRESETB 0x200 +#define BOFDMTXSTART 0x4 +#define BCCKTXSTART 0x8 +#define BCRC32DEBUG 0x100 +#define BPMACLOOPBACK 0x10 +#define BTXLSIG 0xffffff +#define BOFDMTXRATE 0xf +#define BOFDMTXRESERVED 0x10 +#define BOFDMTXLENGTH 0x1ffe0 +#define BOFDMTXPARITY 0x20000 +#define BTXHTSIG1 0xffffff +#define BTXHTMCSRATE 0x7f +#define BTXHTBW 0x80 +#define BTXHTLENGTH 0xffff00 +#define BTXHTSIG2 0xffffff +#define BTXHTSMOOTHING 0x1 +#define BTXHTSOUNDING 0x2 +#define BTXHTRESERVED 0x4 +#define BTXHTAGGREATION 0x8 +#define BTXHTSTBC 0x30 +#define BTXHTADVANCECODING 0x40 +#define BTXHTSHORTGI 0x80 +#define BTXHTNUMBERHT_LTF 0x300 +#define BTXHTCRC8 0x3fc00 +#define BCOUNTERRESET 0x10000 +#define BNUMOFOFDMTX 0xffff +#define BNUMOFCCKTX 0xffff0000 +#define BTXIDLEINTERVAL 0xffff +#define BOFDMSERVICE 0xffff0000 +#define BTXMACHEADER 0xffffffff +#define BTXDATAINIT 0xff +#define BTXHTMODE 0x100 +#define BTXDATATYPE 0x30000 +#define BTXRANDOMSEED 0xffffffff +#define BCCKTXPREAMBLE 0x1 +#define BCCKTXSFD 0xffff0000 +#define BCCKTXSIG 0xff +#define BCCKTXSERVICE 0xff00 +#define BCCKLENGTHEXT 0x8000 +#define BCCKTXLENGHT 0xffff0000 +#define BCCKTXCRC16 0xffff +#define BCCKTXSTATUS 0x1 +#define BOFDMTXSTATUS 0x2 +#define IS_BB_REG_OFFSET_92S(_offset) \ + ((_offset >= 0x800) && (_offset <= 0xfff)) + +#define BRFMOD 0x1 +#define BJAPANMODE 0x2 +#define BCCKTXSC 0x30 +#define BCCKEN 0x1000000 +#define BOFDMEN 0x2000000 + +#define BOFDMRXADCPHASE 0x10000 +#define BOFDMTXDACPHASE 0x40000 +#define BXATXAGC 0x3f + +#define BXBTXAGC 0xf00 +#define BXCTXAGC 0xf000 +#define BXDTXAGC 0xf0000 + +#define BPASTART 0xf0000000 +#define BTRSTART 0x00f00000 +#define BRFSTART 0x0000f000 +#define BBBSTART 0x000000f0 +#define BBBCCKSTART 0x0000000f +#define BPAEND 0xf +#define BTREND 0x0f000000 +#define BRFEND 0x000f0000 +#define BCCAMASK 0x000000f0 +#define BR2RCCAMASK 0x00000f00 +#define BHSSI_R2TDELAY 0xf8000000 +#define BHSSI_T2RDELAY 0xf80000 +#define BCONTXHSSI 0x400 +#define BIGFROMCCK 0x200 +#define BAGCADDRESS 0x3f +#define BRXHPTX 0x7000 +#define BRXHP2RX 0x38000 +#define BRXHPCCKINI 0xc0000 +#define BAGCTXCODE 0xc00000 +#define BAGCRXCODE 0x300000 + +#define B3WIREDATALENGTH 0x800 +#define B3WIREADDREAALENGTH 0x400 + +#define B3WIRERFPOWERDOWN 0x1 +#define B5GPAPEPOLARITY 0x40000000 +#define B2GPAPEPOLARITY 0x80000000 +#define BRFSW_TXDEFAULTANT 0x3 +#define BRFSW_TXOPTIONANT 0x30 +#define BRFSW_RXDEFAULTANT 0x300 +#define BRFSW_RXOPTIONANT 0x3000 +#define BRFSI_3WIREDATA 0x1 +#define BRFSI_3WIRECLOCK 0x2 +#define BRFSI_3WIRELOAD 0x4 +#define BRFSI_3WIRERW 0x8 +#define BRFSI_3WIRE 0xf + +#define BRFSI_RFENV 0x10 + +#define BRFSI_TRSW 0x20 +#define BRFSI_TRSWB 0x40 +#define BRFSI_ANTSW 0x100 +#define BRFSI_ANTSWB 0x200 +#define BRFSI_PAPE 0x400 +#define BRFSI_PAPE5G 0x800 +#define BBANDSELECT 0x1 +#define BHTSIG2_GI 0x80 +#define BHTSIG2_SMOOTHING 0x01 +#define BHTSIG2_SOUNDING 0x02 +#define BHTSIG2_AGGREATON 0x08 +#define BHTSIG2_STBC 0x30 +#define BHTSIG2_ADVCODING 0x40 +#define BHTSIG2_NUMOFHTLTF 0x300 +#define BHTSIG2_CRC8 0x3fc +#define BHTSIG1_MCS 0x7f +#define BHTSIG1_BANDWIDTH 0x80 +#define BHTSIG1_HTLENGTH 0xffff +#define BLSIG_RATE 0xf +#define BLSIG_RESERVED 0x10 +#define BLSIG_LENGTH 0x1fffe +#define BLSIG_PARITY 0x20 +#define BCCKRXPHASE 0x4 + +#define BLSSIREADADDRESS 0x7f800000 +#define BLSSIREADEDGE 0x80000000 + +#define BLSSIREADBACKDATA 0xfffff + +#define BLSSIREADOKFLAG 0x1000 +#define BCCKSAMPLERATE 0x8 +#define BREGULATOR0STANDBY 0x1 +#define BREGULATORPLLSTANDBY 0x2 +#define BREGULATOR1STANDBY 0x4 +#define BPLLPOWERUP 0x8 +#define BDPLLPOWERUP 0x10 +#define BDA10POWERUP 0x20 +#define BAD7POWERUP 0x200 +#define BDA6POWERUP 0x2000 +#define BXTALPOWERUP 0x4000 +#define B40MDCLKPOWERUP 0x8000 +#define BDA6DEBUGMODE 0x20000 +#define BDA6SWING 0x380000 + +#define BADCLKPHASE 0x4000000 +#define B80MCLKDELAY 0x18000000 +#define BAFEWATCHDOGENABLE 0x20000000 + +#define BXTALCAP01 0xc0000000 +#define BXTALCAP23 0x3 +#define BXTALCAP92X 0x0f000000 +#define BXTALCAP 0x0f000000 + +#define BINTDIFCLKENABLE 0x400 +#define BEXTSIGCLKENABLE 0x800 +#define BBANDGAP_MBIAS_POWERUP 0x10000 +#define BAD11SH_GAIN 0xc0000 +#define BAD11NPUT_RANGE 0x700000 +#define BAD110P_CURRENT 0x3800000 +#define BLPATH_LOOPBACK 0x4000000 +#define BQPATH_LOOPBACK 0x8000000 +#define BAFE_LOOPBACK 0x10000000 +#define BDA10_SWING 0x7e0 +#define BDA10_REVERSE 0x800 +#define BDA_CLK_SOURCE 0x1000 +#define BDA7INPUT_RANGE 0x6000 +#define BDA7_GAIN 0x38000 +#define BDA7OUTPUT_CM_MODE 0x40000 +#define BDA7INPUT_CM_MODE 0x380000 +#define BDA7CURRENT 0xc00000 +#define BREGULATOR_ADJUST 0x7000000 +#define BAD11POWERUP_ATTX 0x1 +#define BDA10PS_ATTX 0x10 +#define BAD11POWERUP_ATRX 0x100 +#define BDA10PS_ATRX 0x1000 +#define BCCKRX_AGC_FORMAT 0x200 +#define BPSDFFT_SAMPLE_POINT 0xc000 +#define BPSD_AVERAGE_NUM 0x3000 +#define BIQPATH_CONTROL 0xc00 +#define BPSD_FREQ 0x3ff +#define BPSD_ANTENNA_PATH 0x30 +#define BPSD_IQ_SWITCH 0x40 +#define BPSD_RX_TRIGGER 0x400000 +#define BPSD_TX_TRIGGER 0x80000000 +#define BPSD_SINE_TONE_SCALE 0x7f000000 +#define BPSD_REPORT 0xffff + +#define BOFDM_TXSC 0x30000000 +#define BCCK_TXON 0x1 +#define BOFDM_TXON 0x2 +#define BDEBUG_PAGE 0xfff +#define BDEBUG_ITEM 0xff +#define BANTL 0x10 +#define BANT_NONHT 0x100 +#define BANT_HT1 0x1000 +#define BANT_HT2 0x10000 +#define BANT_HT1S1 0x100000 +#define BANT_NONHTS1 0x1000000 + +#define BCCK_BBMODE 0x3 +#define BCCK_TXPOWERSAVING 0x80 +#define BCCK_RXPOWERSAVING 0x40 + +#define BCCK_SIDEBAND 0x10 + +#define BCCK_SCRAMBLE 0x8 +#define BCCK_ANTDIVERSITY 0x8000 +#define BCCK_CARRIER_RECOVERY 0x4000 +#define BCCK_TXRATE 0x3000 +#define BCCK_DCCANCEL 0x0800 +#define BCCK_ISICANCEL 0x0400 +#define BCCK_MATCH_FILTER 0x0200 +#define BCCK_EQUALIZER 0x0100 +#define BCCK_PREAMBLE_DETECT 0x800000 +#define BCCK_FAST_FALSECCA 0x400000 +#define BCCK_CH_ESTSTART 0x300000 +#define BCCK_CCA_COUNT 0x080000 +#define BCCK_CS_LIM 0x070000 +#define BCCK_BIST_MODE 0x80000000 +#define BCCK_CCAMASK 0x40000000 +#define BCCK_TX_DAC_PHASE 0x4 +#define BCCK_RX_ADC_PHASE 0x20000000 +#define BCCKR_CP_MODE 0x0100 +#define BCCK_TXDC_OFFSET 0xf0 +#define BCCK_RXDC_OFFSET 0xf +#define BCCK_CCA_MODE 0xc000 +#define BCCK_FALSECS_LIM 0x3f00 +#define BCCK_CS_RATIO 0xc00000 +#define BCCK_CORGBIT_SEL 0x300000 +#define BCCK_PD_LIM 0x0f0000 +#define BCCK_NEWCCA 0x80000000 +#define BCCK_RXHP_OF_IG 0x8000 +#define BCCK_RXIG 0x7f00 +#define BCCK_LNA_POLARITY 0x800000 +#define BCCK_RX1ST_BAIN 0x7f0000 +#define BCCK_RF_EXTEND 0x20000000 +#define BCCK_RXAGC_SATLEVEL 0x1f000000 +#define BCCK_RXAGC_SATCOUNT 0xe0 +#define BCCKRXRFSETTLE 0x1f +#define BCCK_FIXED_RXAGC 0x8000 +#define BCCK_ANTENNA_POLARITY 0x2000 +#define BCCK_TXFILTER_TYPE 0x0c00 +#define BCCK_RXAGC_REPORTTYPE 0x0300 +#define BCCK_RXDAGC_EN 0x80000000 +#define BCCK_RXDAGC_PERIOD 0x20000000 +#define BCCK_RXDAGC_SATLEVEL 0x1f000000 +#define BCCK_TIMING_RECOVERY 0x800000 +#define BCCK_TXC0 0x3f0000 +#define BCCK_TXC1 0x3f000000 +#define BCCK_TXC2 0x3f +#define BCCK_TXC3 0x3f00 +#define BCCK_TXC4 0x3f0000 +#define BCCK_TXC5 0x3f000000 +#define BCCK_TXC6 0x3f +#define BCCK_TXC7 0x3f00 +#define BCCK_DEBUGPORT 0xff0000 +#define BCCK_DAC_DEBUG 0x0f000000 +#define BCCK_FALSEALARM_ENABLE 0x8000 +#define BCCK_FALSEALARM_READ 0x4000 +#define BCCK_TRSSI 0x7f +#define BCCK_RXAGC_REPORT 0xfe +#define BCCK_RXREPORT_ANTSEL 0x80000000 +#define BCCK_RXREPORT_MFOFF 0x40000000 +#define BCCK_RXREPORT_SQLOSS 0x20000000 +#define BCCK_RXREPORT_PKTLOSS 0x10000000 +#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 +#define BCCK_RXREPORT_RATEERROR 0x04000000 +#define BCCK_RXREPORT_RXRATE 0x03000000 +#define BCCK_RXFA_COUNTER_LOWER 0xff +#define BCCK_RXFA_COUNTER_UPPER 0xff000000 +#define BCCK_RXHPAGC_START 0xe000 +#define BCCK_RXHPAGC_FINAL 0x1c00 +#define BCCK_RXFALSEALARM_ENABLE 0x8000 +#define BCCK_FACOUNTER_FREEZE 0x4000 +#define BCCK_TXPATH_SEL 0x10000000 +#define BCCK_DEFAULT_RXPATH 0xc000000 +#define BCCK_OPTION_RXPATH 0x3000000 + +#define BNUM_OFSTF 0x3 +#define BSHIFT_L 0xc0 +#define BGI_TH 0xc +#define BRXPATH_A 0x1 +#define BRXPATH_B 0x2 +#define BRXPATH_C 0x4 +#define BRXPATH_D 0x8 +#define BTXPATH_A 0x1 +#define BTXPATH_B 0x2 +#define BTXPATH_C 0x4 +#define BTXPATH_D 0x8 +#define BTRSSI_FREQ 0x200 +#define BADC_BACKOFF 0x3000 +#define BDFIR_BACKOFF 0xc000 +#define BTRSSI_LATCH_PHASE 0x10000 +#define BRX_LDC_OFFSET 0xff +#define BRX_QDC_OFFSET 0xff00 +#define BRX_DFIR_MODE 0x1800000 +#define BRX_DCNF_TYPE 0xe000000 +#define BRXIQIMB_A 0x3ff +#define BRXIQIMB_B 0xfc00 +#define BRXIQIMB_C 0x3f0000 +#define BRXIQIMB_D 0xffc00000 +#define BDC_DC_NOTCH 0x60000 +#define BRXNB_NOTCH 0x1f000000 +#define BPD_TH 0xf +#define BPD_TH_OPT2 0xc000 +#define BPWED_TH 0x700 +#define BIFMF_WIN_L 0x800 +#define BPD_OPTION 0x1000 +#define BMF_WIN_L 0xe000 +#define BBW_SEARCH_L 0x30000 +#define BWIN_ENH_L 0xc0000 +#define BBW_TH 0x700000 +#define BED_TH2 0x3800000 +#define BBW_OPTION 0x4000000 +#define BRADIO_TH 0x18000000 +#define BWINDOW_L 0xe0000000 +#define BSBD_OPTION 0x1 +#define BFRAME_TH 0x1c +#define BFS_OPTION 0x60 +#define BDC_SLOPE_CHECK 0x80 +#define BFGUARD_COUNTER_DC_L 0xe00 +#define BFRAME_WEIGHT_SHORT 0x7000 +#define BSUB_TUNE 0xe00000 +#define BFRAME_DC_LENGTH 0xe000000 +#define BSBD_START_OFFSET 0x30000000 +#define BFRAME_TH_2 0x7 +#define BFRAME_GI2_TH 0x38 +#define BGI2_SYNC_EN 0x40 +#define BSARCH_SHORT_EARLY 0x300 +#define BSARCH_SHORT_LATE 0xc00 +#define BSARCH_GI2_LATE 0x70000 +#define BCFOANTSUM 0x1 +#define BCFOACC 0x2 +#define BCFOSTARTOFFSET 0xc +#define BCFOLOOPBACK 0x70 +#define BCFOSUMWEIGHT 0x80 +#define BDAGCENABLE 0x10000 +#define BTXIQIMB_A 0x3ff +#define BTXIQIMB_b 0xfc00 +#define BTXIQIMB_C 0x3f0000 +#define BTXIQIMB_D 0xffc00000 +#define BTXIDCOFFSET 0xff +#define BTXIQDCOFFSET 0xff00 +#define BTXDFIRMODE 0x10000 +#define BTXPESUDO_NOISEON 0x4000000 +#define BTXPESUDO_NOISE_A 0xff +#define BTXPESUDO_NOISE_B 0xff00 +#define BTXPESUDO_NOISE_C 0xff0000 +#define BTXPESUDO_NOISE_D 0xff000000 +#define BCCA_DROPOPTION 0x20000 +#define BCCA_DROPTHRES 0xfff00000 +#define BEDCCA_H 0xf +#define BEDCCA_L 0xf0 +#define BLAMBDA_ED 0x300 +#define BRX_INITIALGAIN 0x7f +#define BRX_ANTDIV_EN 0x80 +#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 +#define BRX_HIGHPOWER_FLOW 0x8000 +#define BRX_AGC_FREEZE_THRES 0xc0000 +#define BRX_FREEZESTEP_AGC1 0x300000 +#define BRX_FREEZESTEP_AGC2 0xc00000 +#define BRX_FREEZESTEP_AGC3 0x3000000 +#define BRX_FREEZESTEP_AGC0 0xc000000 +#define BRXRSSI_CMP_EN 0x10000000 +#define BRXQUICK_AGCEN 0x20000000 +#define BRXAGC_FREEZE_THRES_MODE 0x40000000 +#define BRX_OVERFLOW_CHECKTYPE 0x80000000 +#define BRX_AGCSHIFT 0x7f +#define BTRSW_TRI_ONLY 0x80 +#define BPOWER_THRES 0x300 +#define BRXAGC_EN 0x1 +#define BRXAGC_TOGETHER_EN 0x2 +#define BRXAGC_MIN 0x4 +#define BRXHP_INI 0x7 +#define BRXHP_TRLNA 0x70 +#define BRXHP_RSSI 0x700 +#define BRXHP_BBP1 0x7000 +#define BRXHP_BBP2 0x70000 +#define BRXHP_BBP3 0x700000 +#define BRSSI_H 0x7f0000 +#define BRSSI_GEN 0x7f000000 +#define BRXSETTLE_TRSW 0x7 +#define BRXSETTLE_LNA 0x38 +#define BRXSETTLE_RSSI 0x1c0 +#define BRXSETTLE_BBP 0xe00 +#define BRXSETTLE_RXHP 0x7000 +#define BRXSETTLE_ANTSW_RSSI 0x38000 +#define BRXSETTLE_ANTSW 0xc0000 +#define BRXPROCESS_TIME_DAGC 0x300000 +#define BRXSETTLE_HSSI 0x400000 +#define BRXPROCESS_TIME_BBPPW 0x800000 +#define BRXANTENNA_POWER_SHIFT 0x3000000 +#define BRSSI_TABLE_SELECT 0xc000000 +#define BRXHP_FINAL 0x7000000 +#define BRXHPSETTLE_BBP 0x7 +#define BRXHTSETTLE_HSSI 0x8 +#define BRXHTSETTLE_RXHP 0x70 +#define BRXHTSETTLE_BBPPW 0x80 +#define BRXHTSETTLE_IDLE 0x300 +#define BRXHTSETTLE_RESERVED 0x1c00 +#define BRXHT_RXHP_EN 0x8000 +#define BRXAGC_FREEZE_THRES 0x30000 +#define BRXAGC_TOGETHEREN 0x40000 +#define BRXHTAGC_MIN 0x80000 +#define BRXHTAGC_EN 0x100000 +#define BRXHTDAGC_EN 0x200000 +#define BRXHT_RXHP_BBP 0x1c00000 +#define BRXHT_RXHP_FINAL 0xe0000000 +#define BRXPW_RADIO_TH 0x3 +#define BRXPW_RADIO_EN 0x4 +#define BRXMF_HOLD 0x3800 +#define BRXPD_DELAY_TH1 0x38 +#define BRXPD_DELAY_TH2 0x1c0 +#define BRXPD_DC_COUNT_MAX 0x600 +#define BRXPD_DELAY_TH 0x8000 +#define BRXPROCESS_DELAY 0xf0000 +#define BRXSEARCHRANGE_GI2_EARLY 0x700000 +#define BRXFRAME_FUARD_COUNTER_L 0x3800000 +#define BRXSGI_GUARD_L 0xc000000 +#define BRXSGI_SEARCH_L 0x30000000 +#define BRXSGI_TH 0xc0000000 +#define BDFSCNT0 0xff +#define BDFSCNT1 0xff00 +#define BDFSFLAG 0xf0000 +#define BMF_WEIGHT_SUM 0x300000 +#define BMINIDX_TH 0x7f000000 +#define BDAFORMAT 0x40000 +#define BTXCH_EMU_ENABLE 0x01000000 +#define BTRSW_ISOLATION_A 0x7f +#define BTRSW_ISOLATION_B 0x7f00 +#define BTRSW_ISOLATION_C 0x7f0000 +#define BTRSW_ISOLATION_D 0x7f000000 +#define BEXT_LNA_GAIN 0x7c00 + +#define BSTBC_EN 0x4 +#define BANTENNA_MAPPING 0x10 +#define BNSS 0x20 +#define BCFO_ANTSUM_ID 0x200 +#define BPHY_COUNTER_RESET 0x8000000 +#define BCFO_REPORT_GET 0x4000000 +#define BOFDM_CONTINUE_TX 0x10000000 +#define BOFDM_SINGLE_CARRIER 0x20000000 +#define BOFDM_SINGLE_TONE 0x40000000 +#define BHT_DETECT 0x100 +#define BCFOEN 0x10000 +#define BCFOVALUE 0xfff00000 +#define BSIGTONE_RE 0x3f +#define BSIGTONE_IM 0x7f00 +#define BCOUNTER_CCA 0xffff +#define BCOUNTER_PARITYFAIL 0xffff0000 +#define BCOUNTER_RATEILLEGAL 0xffff +#define BCOUNTER_CRC8FAIL 0xffff0000 +#define BCOUNTER_MCSNOSUPPORT 0xffff +#define BCOUNTER_FASTSYNC 0xffff +#define BSHORTCFO 0xfff +#define BSHORTCFOT_LENGTH 12 +#define BSHORTCFOF_LENGTH 11 +#define BLONGCFO 0x7ff +#define BLONGCFOT_LENGTH 11 +#define BLONGCFOF_LENGTH 11 +#define BTAILCFO 0x1fff +#define BTAILCFOT_LENGTH 13 +#define BTAILCFOF_LENGTH 12 +#define BNOISE_EN_PWDB 0xffff +#define BCC_POWER_DB 0xffff0000 +#define BMOISE_PWDB 0xffff +#define BPOWERMEAST_LENGTH 10 +#define BPOWERMEASF_LENGTH 3 +#define BRX_HT_BW 0x1 +#define BRXSC 0x6 +#define BRX_HT 0x8 +#define BNB_INTF_DET_ON 0x1 +#define BINTF_WIN_LEN_CFG 0x30 +#define BNB_INTF_TH_CFG 0x1c0 +#define BRFGAIN 0x3f +#define BTABLESEL 0x40 +#define BTRSW 0x80 +#define BRXSNR_A 0xff +#define BRXSNR_B 0xff00 +#define BRXSNR_C 0xff0000 +#define BRXSNR_D 0xff000000 +#define BSNR_EVMT_LENGTH 8 +#define BSNR_EVMF_LENGTH 1 +#define BCSI1ST 0xff +#define BCSI2ND 0xff00 +#define BRXEVM1ST 0xff0000 +#define BRXEVM2ND 0xff000000 +#define BSIGEVM 0xff +#define BPWDB 0xff00 +#define BSGIEN 0x10000 + +#define BSFACTOR_QMA1 0xf +#define BSFACTOR_QMA2 0xf0 +#define BSFACTOR_QMA3 0xf00 +#define BSFACTOR_QMA4 0xf000 +#define BSFACTOR_QMA5 0xf0000 +#define BSFACTOR_QMA6 0xf0000 +#define BSFACTOR_QMA7 0xf00000 +#define BSFACTOR_QMA8 0xf000000 +#define BSFACTOR_QMA9 0xf0000000 +#define BCSI_SCHEME 0x100000 + +#define BNOISE_LVL_TOP_SET 0x3 +#define BCHSMOOTH 0x4 +#define BCHSMOOTH_CFG1 0x38 +#define BCHSMOOTH_CFG2 0x1c0 +#define BCHSMOOTH_CFG3 0xe00 +#define BCHSMOOTH_CFG4 0x7000 +#define BMRCMODE 0x800000 +#define BTHEVMCFG 0x7000000 + +#define BLOOP_FIT_TYPE 0x1 +#define BUPD_CFO 0x40 +#define BUPD_CFO_OFFDATA 0x80 +#define BADV_UPD_CFO 0x100 +#define BADV_TIME_CTRL 0x800 +#define BUPD_CLKO 0x1000 +#define BFC 0x6000 +#define BTRACKING_MODE 0x8000 +#define BPHCMP_ENABLE 0x10000 +#define BUPD_CLKO_LTF 0x20000 +#define BCOM_CH_CFO 0x40000 +#define BCSI_ESTI_MODE 0x80000 +#define BADV_UPD_EQZ 0x100000 +#define BUCHCFG 0x7000000 +#define BUPDEQZ 0x8000000 + +#define BRX_PESUDO_NOISE_ON 0x20000000 +#define BRX_PESUDO_NOISE_A 0xff +#define BRX_PESUDO_NOISE_B 0xff00 +#define BRX_PESUDO_NOISE_C 0xff0000 +#define BRX_PESUDO_NOISE_D 0xff000000 +#define BRX_PESUDO_NOISESTATE_A 0xffff +#define BRX_PESUDO_NOISESTATE_B 0xffff0000 +#define BRX_PESUDO_NOISESTATE_C 0xffff +#define BRX_PESUDO_NOISESTATE_D 0xffff0000 + +#define BZEBRA1_HSSIENABLE 0x8 +#define BZEBRA1_TRXCONTROL 0xc00 +#define BZEBRA1_TRXGAINSETTING 0x07f +#define BZEBRA1_RXCOUNTER 0xc00 +#define BZEBRA1_TXCHANGEPUMP 0x38 +#define BZEBRA1_RXCHANGEPUMP 0x7 +#define BZEBRA1_CHANNEL_NUM 0xf80 +#define BZEBRA1_TXLPFBW 0x400 +#define BZEBRA1_RXLPFBW 0x600 + +#define BRTL8256REG_MODE_CTRL1 0x100 +#define BRTL8256REG_MODE_CTRL0 0x40 +#define BRTL8256REG_TXLPFBW 0x18 +#define BRTL8256REG_RXLPFBW 0x600 + +#define BRTL8258_TXLPFBW 0xc +#define BRTL8258_RXLPFBW 0xc00 +#define BRTL8258_RSSILPFBW 0xc0 + +#define BBYTE0 0x1 +#define BBYTE1 0x2 +#define BBYTE2 0x4 +#define BBYTE3 0x8 +#define BWORD0 0x3 +#define BWORD1 0xc +#define BWORD 0xf + +#define MASKBYTE0 0xff +#define MASKBYTE1 0xff00 +#define MASKBYTE2 0xff0000 +#define MASKBYTE3 0xff000000 +#define MASKHWORD 0xffff0000 +#define MASKLWORD 0x0000ffff +#define MASKDWORD 0xffffffff +#define MASK12BITS 0xfff +#define MASKH4BITS 0xf0000000 +#define MASKOFDM_D 0xffc00000 +#define MASKCCK 0x3f3f3f3f + +#define MASK4BITS 0x0f +#define MASK20BITS 0xfffff +#define RFREG_OFFSET_MASK 0xfffff + +#define BENABLE 0x1 +#define BDISABLE 0x0 + +#define LEFT_ANTENNA 0x0 +#define RIGHT_ANTENNA 0x1 + +#define TCHECK_TXSTATUS 500 +#define TUPDATE_RXCOUNTER 100 + +#define REG_UN_used_register 0x01bf + +/* WOL bit information */ +#define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0) +#define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1) +#define HAL92C_WOL_DISASSOC_EVENT BIT(2) +#define HAL92C_WOL_DEAUTH_EVENT BIT(3) +#define HAL92C_WOL_FW_DISCONNECT_EVENT BIT(4) + +#define WOL_REASON_PTK_UPDATE BIT(0) +#define WOL_REASON_GTK_UPDATE BIT(1) +#define WOL_REASON_DISASSOC BIT(2) +#define WOL_REASON_DEAUTH BIT(3) +#define WOL_REASON_FW_DISCONNECT BIT(4) +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c new file mode 100644 index 000000000000..40893cef7dfe --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.c @@ -0,0 +1,509 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" + +static bool _rtl88e_phy_rf6052_config_parafile(struct ieee80211_hw *hw); + +void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff) | BIT(10) | BIT(11)); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + case HT_CHANNEL_WIDTH_20_40: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff) | BIT(10)); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", bandwidth); + break; + } +} + +void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 tx_agc[2] = {0, 0}, tmpval; + bool turbo_scanoff = false; + u8 idx1, idx2; + u8 *ptr; + u8 direction; + u32 pwrtrac_value; + + if (rtlefuse->eeprom_regulatory != 0) + turbo_scanoff = true; + + if (mac->act_scanning == true) { + tx_agc[RF90_PATH_A] = 0x3f3f3f3f; + tx_agc[RF90_PATH_B] = 0x3f3f3f3f; + + if (turbo_scanoff) { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + } + } else { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + + if (rtlefuse->eeprom_regulatory == 0) { + tmpval = + (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + + (rtlphy->mcs_txpwrlevel_origoffset[0][7] << + 8); + tx_agc[RF90_PATH_A] += tmpval; + + tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + + (rtlphy->mcs_txpwrlevel_origoffset[0][15] << + 24); + tx_agc[RF90_PATH_B] += tmpval; + } + } + + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + ptr = (u8 *)(&tx_agc[idx1]); + for (idx2 = 0; idx2 < 4; idx2++) { + if (*ptr > RF6052_MAX_TX_PWR) + *ptr = RF6052_MAX_TX_PWR; + ptr++; + } + } + rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); + if (direction == 1) { + tx_agc[0] += pwrtrac_value; + tx_agc[1] += pwrtrac_value; + } else if (direction == 2) { + tx_agc[0] -= pwrtrac_value; + tx_agc[1] -= pwrtrac_value; + } + tmpval = tx_agc[RF90_PATH_A] & 0xff; + rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_A_CCK1_MCS32); + + tmpval = tx_agc[RF90_PATH_A] >> 8; + + /*tmpval = tmpval & 0xff00ffff;*/ + + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK11_A_CCK2_11); + + tmpval = tx_agc[RF90_PATH_B] >> 24; + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK11_A_CCK2_11); + + tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; + rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK1_55_MCS32); +} + +static void rtl88e_phy_get_power_base(struct ieee80211_hw *hw, + u8 *ppowerlevel_ofdm, + u8 *ppowerlevel_bw20, + u8 *ppowerlevel_bw40, u8 channel, + u32 *ofdmbase, u32 *mcsbase) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 powerbase0, powerbase1; + u8 i, powerlevel[2]; + + for (i = 0; i < 2; i++) { + powerbase0 = ppowerlevel_ofdm[i]; + + powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | + (powerbase0 << 8) | powerbase0; + *(ofdmbase + i) = powerbase0; + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [OFDM power base index rf(%c) = 0x%x]\n", + ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)); + } + + for (i = 0; i < 2; i++) { + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) + powerlevel[i] = ppowerlevel_bw20[i]; + else + powerlevel[i] = ppowerlevel_bw40[i]; + + powerbase1 = powerlevel[i]; + powerbase1 = (powerbase1 << 24) | + (powerbase1 << 16) | (powerbase1 << 8) | powerbase1; + + *(mcsbase + i) = powerbase1; + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [MCS power base index rf(%c) = 0x%x]\n", + ((i == 0) ? 'A' : 'B'), *(mcsbase + i)); + } +} + +static void _rtl88e_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, + u8 channel, u8 index, + u32 *powerbase0, + u32 *powerbase1, + u32 *p_outwriteval) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff; + u32 writeval, customer_limit, rf; + + for (rf = 0; rf < 2; rf++) { + switch (rtlefuse->eeprom_regulatory) { + case 0: + chnlgroup = 0; + + writeval = + rtlphy->mcs_txpwrlevel_origoffset + [chnlgroup][index + (rf ? 8 : 0)] + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + case 1: + if (rtlphy->pwrgroup_cnt == 1) { + chnlgroup = 0; + } else { + if (channel < 3) + chnlgroup = 0; + else if (channel < 6) + chnlgroup = 1; + else if (channel < 9) + chnlgroup = 2; + else if (channel < 12) + chnlgroup = 3; + else if (channel < 14) + chnlgroup = 4; + else if (channel == 14) + chnlgroup = 5; + } + + writeval = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] + [index + (rf ? 8 : 0)] + ((index < 2) ? + powerbase0[rf] : + powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + + break; + case 2: + writeval = + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Better regulatory, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + case 3: + chnlgroup = 0; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 40MHz rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), + rtlefuse->pwrgroup_ht40[rf][channel - + 1]); + } else { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 20MHz rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), + rtlefuse->pwrgroup_ht20[rf][channel - + 1]); + } + + if (index < 2) + pwr_diff = + rtlefuse->txpwr_legacyhtdiff[rf][channel-1]; + else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) + pwr_diff = + rtlefuse->txpwr_ht20diff[rf][channel-1]; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) + customer_pwr_diff = + rtlefuse->pwrgroup_ht40[rf][channel-1]; + else + customer_pwr_diff = + rtlefuse->pwrgroup_ht20[rf][channel-1]; + + if (pwr_diff > customer_pwr_diff) + pwr_diff = 0; + else + pwr_diff = customer_pwr_diff - pwr_diff; + + for (i = 0; i < 4; i++) { + pwr_diff_limit[i] = + (u8)((rtlphy->mcs_txpwrlevel_origoffset + [chnlgroup][index + + (rf ? 8 : 0)] & (0x7f << + (i * 8))) >> (i * 8)); + + if (pwr_diff_limit[i] > pwr_diff) + pwr_diff_limit[i] = pwr_diff; + } + + customer_limit = (pwr_diff_limit[3] << 24) | + (pwr_diff_limit[2] << 16) | + (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer's limit rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), customer_limit); + + writeval = customer_limit + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer, writeval rf(%c)= 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + default: + chnlgroup = 0; + writeval = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] + [index + (rf ? 8 : 0)] + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeval rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + } + + if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) + writeval = writeval - 0x06060606; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_BT2) + writeval = writeval - 0x0c0c0c0c; + *(p_outwriteval + rf) = writeval; + } +} + +static void _rtl88e_write_ofdm_power_reg(struct ieee80211_hw *hw, + u8 index, u32 *value) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 regoffset_a[6] = { + RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, + RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, + RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 + }; + u16 regoffset_b[6] = { + RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, + RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, + RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 + }; + u8 i, rf, pwr_val[4]; + u32 writeval; + u16 regoffset; + + for (rf = 0; rf < 2; rf++) { + writeval = value[rf]; + for (i = 0; i < 4; i++) { + pwr_val[i] = (u8)((writeval & (0x7f << + (i * 8))) >> (i * 8)); + + if (pwr_val[i] > RF6052_MAX_TX_PWR) + pwr_val[i] = RF6052_MAX_TX_PWR; + } + writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | + (pwr_val[1] << 8) | pwr_val[0]; + + if (rf == 0) + regoffset = regoffset_a[index]; + else + regoffset = regoffset_b[index]; + rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Set 0x%x = %08x\n", regoffset, writeval); + } +} + +void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel_ofdm, + u8 *ppowerlevel_bw20, + u8 *ppowerlevel_bw40, u8 channel) +{ + u32 writeval[2], powerbase0[2], powerbase1[2]; + u8 index; + u8 direction; + u32 pwrtrac_value; + + rtl88e_phy_get_power_base(hw, ppowerlevel_ofdm, + ppowerlevel_bw20, ppowerlevel_bw40, + channel, &powerbase0[0], &powerbase1[0]); + + rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); + + for (index = 0; index < 6; index++) { + _rtl88e_get_txpower_writeval_by_regulatory(hw, + channel, index, + &powerbase0[0], + &powerbase1[0], + &writeval[0]); + if (direction == 1) { + writeval[0] += pwrtrac_value; + writeval[1] += pwrtrac_value; + } else if (direction == 2) { + writeval[0] -= pwrtrac_value; + writeval[1] -= pwrtrac_value; + } + _rtl88e_write_ofdm_power_reg(hw, index, &writeval[0]); + } +} + +bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + if (rtlphy->rf_type == RF_1T1R) + rtlphy->num_total_rfpath = 1; + else + rtlphy->num_total_rfpath = 2; + + return _rtl88e_phy_rf6052_config_parafile(hw); +} + +static bool _rtl88e_phy_rf6052_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 u4_regvalue = 0; + u8 rfpath; + bool rtstatus = true; + struct bb_reg_def *pphyreg; + + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + pphyreg = &rtlphy->phyreg_def[rfpath]; + + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV); + break; + case RF90_PATH_B: + case RF90_PATH_D: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16); + break; + } + + rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, + B3WIREADDREAALENGTH, 0x0); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); + udelay(1); + + switch (rfpath) { + case RF90_PATH_A: + rtstatus = rtl88e_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_B: + rtstatus = rtl88e_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_C: + break; + case RF90_PATH_D: + break; + } + + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV, u4_regvalue); + break; + case RF90_PATH_B: + case RF90_PATH_D: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16, u4_regvalue); + break; + } + + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio[%d] Fail!!", rfpath); + return false; + } + + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); + return rtstatus; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h new file mode 100644 index 000000000000..0eca030e3238 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/rf.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_RF_H__ +#define __RTL92C_RF_H__ + +#define RF6052_MAX_TX_PWR 0x3F + +void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, + u8 bandwidth); +void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel_ofdm, + u8 *ppowerlevel_bw20, + u8 *ppowerlevel_bw40, + u8 channel); +bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c new file mode 100644 index 000000000000..11344121c55e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c @@ -0,0 +1,419 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../core.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "hw.h" +#include "sw.h" +#include "trx.h" +#include "led.h" +#include "table.h" + +#include +#include + +static void rtl88e_init_aspm_vars(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /* ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + */ + rtlpci->const_pci_aspm = 3; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /* In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 0; + + /* This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 1; +} + +int rtl88e_init_sw_vars(struct ieee80211_hw *hw) +{ + int err = 0; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 tid; + + rtl8188ee_bt_reg_init(hw); + rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; + + rtlpriv->dm.dm_initialgain_enable = 1; + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.disable_framebursting = 0; + rtlpriv->dm.thermalvalue = 0; + rtlpci->transmit_config = CFENDFORM | BIT(15); + + /* compatible 5G band 88ce just 2.4G band & smsp */ + rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; + rtlpriv->rtlhal.bandset = BAND_ON_2_4G; + rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; + + rtlpci->receive_config = (RCR_APPFCS | + RCR_APP_MIC | + RCR_APP_ICV | + RCR_APP_PHYST_RXFF | + RCR_HTC_LOC_CTRL | + RCR_AMF | + RCR_ACF | + RCR_ADF | + RCR_AICV | + RCR_ACRC32 | + RCR_AB | + RCR_AM | + RCR_APM | + 0); + + rtlpci->irq_mask[0] = + (u32)(IMR_PSTIMEOUT | + IMR_HSISR_IND_ON_INT | + IMR_C2HCMD | + IMR_HIGHDOK | + IMR_MGNTDOK | + IMR_BKDOK | + IMR_BEDOK | + IMR_VIDOK | + IMR_VODOK | + IMR_RDU | + IMR_ROK | + 0); + 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; + rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; + if (rtlpriv->cfg->mod_params->disable_watchdog) + pr_info("watchdog disabled\n"); + if (!rtlpriv->psc.inactiveps) + pr_info("rtl8188ee: Power Save off (module option)\n"); + if (!rtlpriv->psc.fwctrl_lps) + pr_info("rtl8188ee: FW Power Save off (module option)\n"); + rtlpriv->psc.reg_fwctrl_lps = 3; + rtlpriv->psc.reg_max_lps_awakeintvl = 5; + /* for ASPM, you can close aspm through + * set const_support_pciaspm = 0 + */ + rtl88e_init_aspm_vars(hw); + + if (rtlpriv->psc.reg_fwctrl_lps == 1) + rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 2) + rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 3) + rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); + if (!rtlpriv->rtlhal.pfirmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't alloc buffer for fw.\n"); + return 1; + } + + rtlpriv->cfg->fw_name = "rtlwifi/rtl8188efw.bin"; + rtlpriv->max_fw_size = 0x8000; + pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); + err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, + rtlpriv->io.dev, GFP_KERNEL, hw, + rtl_fw_cb); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to request firmware!\n"); + return 1; + } + + /* for early mode */ + rtlpriv->rtlhal.earlymode_enable = false; + rtlpriv->rtlhal.max_earlymode_num = 10; + for (tid = 0; tid < 8; tid++) + skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); + + /*low power */ + rtlpriv->psc.low_power_enable = false; + if (rtlpriv->psc.low_power_enable) { + init_timer(&rtlpriv->works.fw_clockoff_timer); + setup_timer(&rtlpriv->works.fw_clockoff_timer, + rtl88ee_fw_clk_off_timer_callback, + (unsigned long)hw); + } + + init_timer(&rtlpriv->works.fast_antenna_training_timer); + setup_timer(&rtlpriv->works.fast_antenna_training_timer, + rtl88e_dm_fast_antenna_training_callback, + (unsigned long)hw); + return err; +} + +void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.pfirmware) { + vfree(rtlpriv->rtlhal.pfirmware); + rtlpriv->rtlhal.pfirmware = NULL; + } + + if (rtlpriv->psc.low_power_enable) + del_timer_sync(&rtlpriv->works.fw_clockoff_timer); + + del_timer_sync(&rtlpriv->works.fast_antenna_training_timer); +} + +/* get bt coexist status */ +bool rtl88e_get_btc_status(void) +{ + return false; +} + +static struct rtl_hal_ops rtl8188ee_hal_ops = { + .init_sw_vars = rtl88e_init_sw_vars, + .deinit_sw_vars = rtl88e_deinit_sw_vars, + .read_eeprom_info = rtl88ee_read_eeprom_info, + .interrupt_recognized = rtl88ee_interrupt_recognized,/*need check*/ + .hw_init = rtl88ee_hw_init, + .hw_disable = rtl88ee_card_disable, + .hw_suspend = rtl88ee_suspend, + .hw_resume = rtl88ee_resume, + .enable_interrupt = rtl88ee_enable_interrupt, + .disable_interrupt = rtl88ee_disable_interrupt, + .set_network_type = rtl88ee_set_network_type, + .set_chk_bssid = rtl88ee_set_check_bssid, + .set_qos = rtl88ee_set_qos, + .set_bcn_reg = rtl88ee_set_beacon_related_registers, + .set_bcn_intv = rtl88ee_set_beacon_interval, + .update_interrupt_mask = rtl88ee_update_interrupt_mask, + .get_hw_reg = rtl88ee_get_hw_reg, + .set_hw_reg = rtl88ee_set_hw_reg, + .update_rate_tbl = rtl88ee_update_hal_rate_tbl, + .fill_tx_desc = rtl88ee_tx_fill_desc, + .fill_tx_cmddesc = rtl88ee_tx_fill_cmddesc, + .query_rx_desc = rtl88ee_rx_query_desc, + .set_channel_access = rtl88ee_update_channel_access_setting, + .radio_onoff_checking = rtl88ee_gpio_radio_on_off_checking, + .set_bw_mode = rtl88e_phy_set_bw_mode, + .switch_channel = rtl88e_phy_sw_chnl, + .dm_watchdog = rtl88e_dm_watchdog, + .scan_operation_backup = rtl88e_phy_scan_operation_backup, + .set_rf_power_state = rtl88e_phy_set_rf_power_state, + .led_control = rtl88ee_led_control, + .set_desc = rtl88ee_set_desc, + .get_desc = rtl88ee_get_desc, + .is_tx_desc_closed = rtl88ee_is_tx_desc_closed, + .tx_polling = rtl88ee_tx_polling, + .enable_hw_sec = rtl88ee_enable_hw_security_config, + .set_key = rtl88ee_set_key, + .init_sw_leds = rtl88ee_init_sw_leds, + .get_bbreg = rtl88e_phy_query_bb_reg, + .set_bbreg = rtl88e_phy_set_bb_reg, + .get_rfreg = rtl88e_phy_query_rf_reg, + .set_rfreg = rtl88e_phy_set_rf_reg, + .get_btc_status = rtl88e_get_btc_status, + .rx_command_packet = rtl88ee_rx_command_packet, + +}; + +static struct rtl_mod_params rtl88ee_mod_params = { + .sw_crypto = false, + .inactiveps = false, + .swctrl_lps = false, + .fwctrl_lps = false, + .msi_support = true, + .debug = DBG_EMERG, +}; + +static struct rtl_hal_cfg rtl88ee_hal_cfg = { + .bar_id = 2, + .write_readback = true, + .name = "rtl88e_pci", + .fw_name = "rtlwifi/rtl8188efw.bin", + .ops = &rtl8188ee_hal_ops, + .mod_params = &rtl88ee_mod_params, + + .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, + .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, + .maps[SYS_CLK] = REG_SYS_CLKR, + .maps[MAC_RCR_AM] = AM, + .maps[MAC_RCR_AB] = AB, + .maps[MAC_RCR_ACRC32] = ACRC32, + .maps[MAC_RCR_ACF] = ACF, + .maps[MAC_RCR_AAP] = AAP, + .maps[MAC_HIMR] = REG_HIMR, + .maps[MAC_HIMRE] = REG_HIMRE, + .maps[MAC_HSISR] = REG_HSISR, + + .maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS, + + .maps[EFUSE_TEST] = REG_EFUSE_TEST, + .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_CLK] = 0, + .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_PWC_EV12V] = PWC_EV12V, + .maps[EFUSE_FEN_ELDR] = FEN_ELDR, + .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, + .maps[EFUSE_ANA8M] = ANA8M, + .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, + .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, + .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, + .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, + + .maps[RWCAM] = REG_CAMCMD, + .maps[WCAMI] = REG_CAMWRITE, + .maps[RCAMO] = REG_CAMREAD, + .maps[CAMDBG] = REG_CAMDBG, + .maps[SECR] = REG_SECCFG, + .maps[SEC_CAM_NONE] = CAM_NONE, + .maps[SEC_CAM_WEP40] = CAM_WEP40, + .maps[SEC_CAM_TKIP] = CAM_TKIP, + .maps[SEC_CAM_AES] = CAM_AES, + .maps[SEC_CAM_WEP104] = CAM_WEP104, + + .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, + .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, + .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, + .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, + .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, + .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, +/* .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, */ /*need check*/ + .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, + .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, + .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, + .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, + .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, + .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, + .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, +/* .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,*/ +/* .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,*/ + + .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, + .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, + .maps[RTL_IMR_BCNINT] = IMR_BCNDMAINT0, + .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, + .maps[RTL_IMR_RDU] = IMR_RDU, + .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, + .maps[RTL_IMR_BDOK] = IMR_BCNDOK0, + .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, + .maps[RTL_IMR_TBDER] = IMR_TBDER, + .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, + .maps[RTL_IMR_TBDOK] = IMR_TBDOK, + .maps[RTL_IMR_BKDOK] = IMR_BKDOK, + .maps[RTL_IMR_BEDOK] = IMR_BEDOK, + .maps[RTL_IMR_VIDOK] = IMR_VIDOK, + .maps[RTL_IMR_VODOK] = IMR_VODOK, + .maps[RTL_IMR_ROK] = IMR_ROK, + .maps[RTL_IMR_HSISR_IND] = IMR_HSISR_IND_ON_INT, + .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER), + + .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, +}; + +static struct pci_device_id rtl88ee_pci_ids[] = { + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8179, rtl88ee_hal_cfg)}, + {}, +}; + +MODULE_DEVICE_TABLE(pci, rtl88ee_pci_ids); + +MODULE_AUTHOR("zhiyuan_yang "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +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(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); +module_param_named(msi, rtl88ee_mod_params.msi_support, bool, 0444); +module_param_named(disable_watchdog, rtl88ee_mod_params.disable_watchdog, + bool, 0444); +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(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(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); + +static struct pci_driver rtl88ee_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl88ee_pci_ids, + .probe = rtl_pci_probe, + .remove = rtl_pci_disconnect, + .driver.pm = &rtlwifi_pm_ops, +}; + +module_pci_driver(rtl88ee_driver); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h new file mode 100644 index 000000000000..22398c3753a6 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CE_SW_H__ +#define __RTL92CE_SW_H__ + +int rtl88e_init_sw_vars(struct ieee80211_hw *hw); +void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw); +bool rtl88e_get_btc_status(void); + + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c new file mode 100644 index 000000000000..68bcb7fe6a65 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.c @@ -0,0 +1,639 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger + * + *****************************************************************************/ + +#include "table.h" +u32 RTL8188EEPHY_REG_1TARRAY[] = { + 0x800, 0x80040000, + 0x804, 0x00000003, + 0x808, 0x0000FC00, + 0x80C, 0x0000000A, + 0x810, 0x10001331, + 0x814, 0x020C3D10, + 0x818, 0x02200385, + 0x81C, 0x00000000, + 0x820, 0x01000100, + 0x824, 0x00390204, + 0x828, 0x00000000, + 0x82C, 0x00000000, + 0x830, 0x00000000, + 0x834, 0x00000000, + 0x838, 0x00000000, + 0x83C, 0x00000000, + 0x840, 0x00010000, + 0x844, 0x00000000, + 0x848, 0x00000000, + 0x84C, 0x00000000, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x569A11A9, + 0x85C, 0x01000014, + 0x860, 0x66F60110, + 0x864, 0x061F0649, + 0x868, 0x00000000, + 0x86C, 0x27272700, + 0x870, 0x07000760, + 0x874, 0x25004000, + 0x878, 0x00000808, + 0x87C, 0x00000000, + 0x880, 0xB0000C1C, + 0x884, 0x00000001, + 0x888, 0x00000000, + 0x88C, 0xCCC000C0, + 0x890, 0x00000800, + 0x894, 0xFFFFFFFE, + 0x898, 0x40302010, + 0x89C, 0x00706050, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90C, 0x81121111, + 0x910, 0x00000002, + 0x914, 0x00000201, + 0xA00, 0x00D047C8, + 0xA04, 0x80FF000C, + 0xA08, 0x8C838300, + 0xA0C, 0x2E7F120F, + 0xA10, 0x9500BB78, + 0xA14, 0x1114D028, + 0xA18, 0x00881117, + 0xA1C, 0x89140F00, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0xA2C, 0x00D30000, + 0xA70, 0x101FBF00, + 0xA74, 0x00000007, + 0xA78, 0x00000900, + 0xA7C, 0x225B0606, + 0xA80, 0x218075B1, + 0xB2C, 0x80000000, + 0xC00, 0x48071D40, + 0xC04, 0x03A05611, + 0xC08, 0x000000E4, + 0xC0C, 0x6C6C6C6C, + 0xC10, 0x08800000, + 0xC14, 0x40000100, + 0xC18, 0x08800000, + 0xC1C, 0x40000100, + 0xC20, 0x00000000, + 0xC24, 0x00000000, + 0xC28, 0x00000000, + 0xC2C, 0x00000000, + 0xC30, 0x69E9AC47, + 0xC34, 0x469652AF, + 0xC38, 0x49795994, + 0xC3C, 0x0A97971C, + 0xC40, 0x1F7C403F, + 0xC44, 0x000100B7, + 0xC48, 0xEC020107, + 0xC4C, 0x007F037F, + 0xC50, 0x69553420, + 0xC54, 0x43BC0094, + 0xC58, 0x00013169, + 0xC5C, 0x00250492, + 0xC60, 0x00000000, + 0xC64, 0x7112848B, + 0xC68, 0x47C00BFF, + 0xC6C, 0x00000036, + 0xC70, 0x2C7F000D, + 0xC74, 0x020610DB, + 0xC78, 0x0000001F, + 0xC7C, 0x00B91612, + 0xC80, 0x390000E4, + 0xC84, 0x20F60000, + 0xC88, 0x40000100, + 0xC8C, 0x20200000, + 0xC90, 0x00091521, + 0xC94, 0x00000000, + 0xC98, 0x00121820, + 0xC9C, 0x00007F7F, + 0xCA0, 0x00000000, + 0xCA4, 0x000300A0, + 0xCA8, 0x00000000, + 0xCAC, 0x00000000, + 0xCB0, 0x00000000, + 0xCB4, 0x00000000, + 0xCB8, 0x00000000, + 0xCBC, 0x28000000, + 0xCC0, 0x00000000, + 0xCC4, 0x00000000, + 0xCC8, 0x00000000, + 0xCCC, 0x00000000, + 0xCD0, 0x00000000, + 0xCD4, 0x00000000, + 0xCD8, 0x64B22427, + 0xCDC, 0x00766932, + 0xCE0, 0x00222222, + 0xCE4, 0x00000000, + 0xCE8, 0x37644302, + 0xCEC, 0x2F97D40C, + 0xD00, 0x00000740, + 0xD04, 0x00020401, + 0xD08, 0x0000907F, + 0xD0C, 0x20010201, + 0xD10, 0xA0633333, + 0xD14, 0x3333BC43, + 0xD18, 0x7A8F5B6F, + 0xD2C, 0xCC979975, + 0xD30, 0x00000000, + 0xD34, 0x80608000, + 0xD38, 0x00000000, + 0xD3C, 0x00127353, + 0xD40, 0x00000000, + 0xD44, 0x00000000, + 0xD48, 0x00000000, + 0xD4C, 0x00000000, + 0xD50, 0x6437140A, + 0xD54, 0x00000000, + 0xD58, 0x00000282, + 0xD5C, 0x30032064, + 0xD60, 0x4653DE68, + 0xD64, 0x04518A3C, + 0xD68, 0x00002101, + 0xD6C, 0x2A201C16, + 0xD70, 0x1812362E, + 0xD74, 0x322C2220, + 0xD78, 0x000E3C24, + 0xE00, 0x2D2D2D2D, + 0xE04, 0x2D2D2D2D, + 0xE08, 0x0390272D, + 0xE10, 0x2D2D2D2D, + 0xE14, 0x2D2D2D2D, + 0xE18, 0x2D2D2D2D, + 0xE1C, 0x2D2D2D2D, + 0xE28, 0x00000000, + 0xE30, 0x1000DC1F, + 0xE34, 0x10008C1F, + 0xE38, 0x02140102, + 0xE3C, 0x681604C2, + 0xE40, 0x01007C00, + 0xE44, 0x01004800, + 0xE48, 0xFB000000, + 0xE4C, 0x000028D1, + 0xE50, 0x1000DC1F, + 0xE54, 0x10008C1F, + 0xE58, 0x02140102, + 0xE5C, 0x28160D05, + 0xE60, 0x00000008, + 0xE68, 0x001B25A4, + 0xE6C, 0x00C00014, + 0xE70, 0x00C00014, + 0xE74, 0x01000014, + 0xE78, 0x01000014, + 0xE7C, 0x01000014, + 0xE80, 0x01000014, + 0xE84, 0x00C00014, + 0xE88, 0x01000014, + 0xE8C, 0x00C00014, + 0xED0, 0x00C00014, + 0xED4, 0x00C00014, + 0xED8, 0x00C00014, + 0xEDC, 0x00000014, + 0xEE0, 0x00000014, + 0xEEC, 0x01C00014, + 0xF14, 0x00000003, + 0xF4C, 0x00000000, + 0xF00, 0x00000300, + +}; + +u32 RTL8188EEPHY_REG_ARRAY_PG[] = { + 0xE00, 0xFFFFFFFF, 0x06070809, + 0xE04, 0xFFFFFFFF, 0x02020405, + 0xE08, 0x0000FF00, 0x00000006, + 0x86C, 0xFFFFFF00, 0x00020400, + 0xE10, 0xFFFFFFFF, 0x08090A0B, + 0xE14, 0xFFFFFFFF, 0x01030607, + 0xE18, 0xFFFFFFFF, 0x08090A0B, + 0xE1C, 0xFFFFFFFF, 0x01030607, + 0xE00, 0xFFFFFFFF, 0x00000000, + 0xE04, 0xFFFFFFFF, 0x00000000, + 0xE08, 0x0000FF00, 0x00000000, + 0x86C, 0xFFFFFF00, 0x00000000, + 0xE10, 0xFFFFFFFF, 0x00000000, + 0xE14, 0xFFFFFFFF, 0x00000000, + 0xE18, 0xFFFFFFFF, 0x00000000, + 0xE1C, 0xFFFFFFFF, 0x00000000, + 0xE00, 0xFFFFFFFF, 0x02020202, + 0xE04, 0xFFFFFFFF, 0x00020202, + 0xE08, 0x0000FF00, 0x00000000, + 0x86C, 0xFFFFFF00, 0x00000000, + 0xE10, 0xFFFFFFFF, 0x04040404, + 0xE14, 0xFFFFFFFF, 0x00020404, + 0xE18, 0xFFFFFFFF, 0x00000000, + 0xE1C, 0xFFFFFFFF, 0x00000000, + 0xE00, 0xFFFFFFFF, 0x02020202, + 0xE04, 0xFFFFFFFF, 0x00020202, + 0xE08, 0x0000FF00, 0x00000000, + 0x86C, 0xFFFFFF00, 0x00000000, + 0xE10, 0xFFFFFFFF, 0x04040404, + 0xE14, 0xFFFFFFFF, 0x00020404, + 0xE18, 0xFFFFFFFF, 0x00000000, + 0xE1C, 0xFFFFFFFF, 0x00000000, + 0xE00, 0xFFFFFFFF, 0x00000000, + 0xE04, 0xFFFFFFFF, 0x00000000, + 0xE08, 0x0000FF00, 0x00000000, + 0x86C, 0xFFFFFF00, 0x00000000, + 0xE10, 0xFFFFFFFF, 0x00000000, + 0xE14, 0xFFFFFFFF, 0x00000000, + 0xE18, 0xFFFFFFFF, 0x00000000, + 0xE1C, 0xFFFFFFFF, 0x00000000, + 0xE00, 0xFFFFFFFF, 0x02020202, + 0xE04, 0xFFFFFFFF, 0x00020202, + 0xE08, 0x0000FF00, 0x00000000, + 0x86C, 0xFFFFFF00, 0x00000000, + 0xE10, 0xFFFFFFFF, 0x04040404, + 0xE14, 0xFFFFFFFF, 0x00020404, + 0xE18, 0xFFFFFFFF, 0x00000000, + 0xE1C, 0xFFFFFFFF, 0x00000000, + 0xE00, 0xFFFFFFFF, 0x00000000, + 0xE04, 0xFFFFFFFF, 0x00000000, + 0xE08, 0x0000FF00, 0x00000000, + 0x86C, 0xFFFFFF00, 0x00000000, + 0xE10, 0xFFFFFFFF, 0x00000000, + 0xE14, 0xFFFFFFFF, 0x00000000, + 0xE18, 0xFFFFFFFF, 0x00000000, + 0xE1C, 0xFFFFFFFF, 0x00000000, + 0xE00, 0xFFFFFFFF, 0x00000000, + 0xE04, 0xFFFFFFFF, 0x00000000, + 0xE08, 0x0000FF00, 0x00000000, + 0x86C, 0xFFFFFF00, 0x00000000, + 0xE10, 0xFFFFFFFF, 0x00000000, + 0xE14, 0xFFFFFFFF, 0x00000000, + 0xE18, 0xFFFFFFFF, 0x00000000, + 0xE1C, 0xFFFFFFFF, 0x00000000, + 0xE00, 0xFFFFFFFF, 0x00000000, + 0xE04, 0xFFFFFFFF, 0x00000000, + 0xE08, 0x0000FF00, 0x00000000, + 0x86C, 0xFFFFFF00, 0x00000000, + 0xE10, 0xFFFFFFFF, 0x00000000, + 0xE14, 0xFFFFFFFF, 0x00000000, + 0xE18, 0xFFFFFFFF, 0x00000000, + 0xE1C, 0xFFFFFFFF, 0x00000000, + 0xE00, 0xFFFFFFFF, 0x00000000, + 0xE04, 0xFFFFFFFF, 0x00000000, + 0xE08, 0x0000FF00, 0x00000000, + 0x86C, 0xFFFFFF00, 0x00000000, + 0xE10, 0xFFFFFFFF, 0x00000000, + 0xE14, 0xFFFFFFFF, 0x00000000, + 0xE18, 0xFFFFFFFF, 0x00000000, + 0xE1C, 0xFFFFFFFF, 0x00000000, + 0xE00, 0xFFFFFFFF, 0x00000000, + 0xE04, 0xFFFFFFFF, 0x00000000, + 0xE08, 0x0000FF00, 0x00000000, + 0x86C, 0xFFFFFF00, 0x00000000, + 0xE10, 0xFFFFFFFF, 0x00000000, + 0xE14, 0xFFFFFFFF, 0x00000000, + 0xE18, 0xFFFFFFFF, 0x00000000, + 0xE1C, 0xFFFFFFFF, 0x00000000, + +}; + +u32 RTL8188EE_RADIOA_1TARRAY[] = { + 0x000, 0x00030000, + 0x008, 0x00084000, + 0x018, 0x00000407, + 0x019, 0x00000012, + 0x01E, 0x00080009, + 0x01F, 0x00000880, + 0x02F, 0x0001A060, + 0x03F, 0x00000000, + 0x042, 0x000060C0, + 0x057, 0x000D0000, + 0x058, 0x000BE180, + 0x067, 0x00001552, + 0x083, 0x00000000, + 0x0B0, 0x000FF8FC, + 0x0B1, 0x00054400, + 0x0B2, 0x000CCC19, + 0x0B4, 0x00043003, + 0x0B6, 0x0004953E, + 0x0B7, 0x0001C718, + 0x0B8, 0x000060FF, + 0x0B9, 0x00080001, + 0x0BA, 0x00040000, + 0x0BB, 0x00000400, + 0x0BF, 0x000C0000, + 0x0C2, 0x00002400, + 0x0C3, 0x00000009, + 0x0C4, 0x00040C91, + 0x0C5, 0x00099999, + 0x0C6, 0x000000A3, + 0x0C7, 0x00088820, + 0x0C8, 0x00076C06, + 0x0C9, 0x00000000, + 0x0CA, 0x00080000, + 0x0DF, 0x00000180, + 0x0EF, 0x000001A0, + 0x051, 0x0006B27D, + 0x052, 0x0007E49D, + 0x053, 0x00000073, + 0x056, 0x00051FF3, + 0x035, 0x00000086, + 0x035, 0x00000186, + 0x035, 0x00000286, + 0x036, 0x00001C25, + 0x036, 0x00009C25, + 0x036, 0x00011C25, + 0x036, 0x00019C25, + 0x0B6, 0x00048538, + 0x018, 0x00000C07, + 0x05A, 0x0004BD00, + 0x019, 0x000739D0, + 0x034, 0x0000ADF3, + 0x034, 0x00009DF0, + 0x034, 0x00008DED, + 0x034, 0x00007DEA, + 0x034, 0x00006DE7, + 0x034, 0x000054EE, + 0x034, 0x000044EB, + 0x034, 0x000034E8, + 0x034, 0x0000246B, + 0x034, 0x00001468, + 0x034, 0x0000006D, + 0x000, 0x00030159, + 0x084, 0x00068200, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0x08E, 0x00065540, + 0x08F, 0x00088000, + 0x0EF, 0x000020A0, + 0x03B, 0x000F02B0, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0x03B, 0x000722B0, + 0x03B, 0x0006F7B0, + 0x03B, 0x00054FB0, + 0x03B, 0x0004F060, + 0x03B, 0x00030090, + 0x03B, 0x00020080, + 0x03B, 0x00010080, + 0x03B, 0x0000F780, + 0x0EF, 0x000000A0, + 0x000, 0x00010159, + 0x018, 0x0000F407, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, + 0x01F, 0x00080003, + 0xFFE, 0x00000000, + 0xFFE, 0x00000000, + 0x01E, 0x00000001, + 0x01F, 0x00080000, + 0x000, 0x00033E60, + +}; + +u32 RTL8188EEMAC_1T_ARRAY[] = { + 0x026, 0x00000041, + 0x027, 0x00000035, + 0x428, 0x0000000A, + 0x429, 0x00000010, + 0x430, 0x00000000, + 0x431, 0x00000001, + 0x432, 0x00000002, + 0x433, 0x00000004, + 0x434, 0x00000005, + 0x435, 0x00000006, + 0x436, 0x00000007, + 0x437, 0x00000008, + 0x438, 0x00000000, + 0x439, 0x00000000, + 0x43A, 0x00000001, + 0x43B, 0x00000002, + 0x43C, 0x00000004, + 0x43D, 0x00000005, + 0x43E, 0x00000006, + 0x43F, 0x00000007, + 0x440, 0x0000005D, + 0x441, 0x00000001, + 0x442, 0x00000000, + 0x444, 0x00000015, + 0x445, 0x000000F0, + 0x446, 0x0000000F, + 0x447, 0x00000000, + 0x458, 0x00000041, + 0x459, 0x000000A8, + 0x45A, 0x00000072, + 0x45B, 0x000000B9, + 0x460, 0x00000066, + 0x461, 0x00000066, + 0x480, 0x00000008, + 0x4C8, 0x000000FF, + 0x4C9, 0x00000008, + 0x4CC, 0x000000FF, + 0x4CD, 0x000000FF, + 0x4CE, 0x00000001, + 0x4D3, 0x00000001, + 0x500, 0x00000026, + 0x501, 0x000000A2, + 0x502, 0x0000002F, + 0x503, 0x00000000, + 0x504, 0x00000028, + 0x505, 0x000000A3, + 0x506, 0x0000005E, + 0x507, 0x00000000, + 0x508, 0x0000002B, + 0x509, 0x000000A4, + 0x50A, 0x0000005E, + 0x50B, 0x00000000, + 0x50C, 0x0000004F, + 0x50D, 0x000000A4, + 0x50E, 0x00000000, + 0x50F, 0x00000000, + 0x512, 0x0000001C, + 0x514, 0x0000000A, + 0x516, 0x0000000A, + 0x525, 0x0000004F, + 0x550, 0x00000010, + 0x551, 0x00000010, + 0x559, 0x00000002, + 0x55D, 0x000000FF, + 0x605, 0x00000030, + 0x608, 0x0000000E, + 0x609, 0x0000002A, + 0x620, 0x000000FF, + 0x621, 0x000000FF, + 0x622, 0x000000FF, + 0x623, 0x000000FF, + 0x624, 0x000000FF, + 0x625, 0x000000FF, + 0x626, 0x000000FF, + 0x627, 0x000000FF, + 0x652, 0x00000020, + 0x63C, 0x0000000A, + 0x63D, 0x0000000A, + 0x63E, 0x0000000E, + 0x63F, 0x0000000E, + 0x640, 0x00000040, + 0x66E, 0x00000005, + 0x700, 0x00000021, + 0x701, 0x00000043, + 0x702, 0x00000065, + 0x703, 0x00000087, + 0x708, 0x00000021, + 0x709, 0x00000043, + 0x70A, 0x00000065, + 0x70B, 0x00000087, + +}; + +u32 RTL8188EEAGCTAB_1TARRAY[] = { + 0xC78, 0xFB000001, + 0xC78, 0xFB010001, + 0xC78, 0xFB020001, + 0xC78, 0xFB030001, + 0xC78, 0xFB040001, + 0xC78, 0xFB050001, + 0xC78, 0xFA060001, + 0xC78, 0xF9070001, + 0xC78, 0xF8080001, + 0xC78, 0xF7090001, + 0xC78, 0xF60A0001, + 0xC78, 0xF50B0001, + 0xC78, 0xF40C0001, + 0xC78, 0xF30D0001, + 0xC78, 0xF20E0001, + 0xC78, 0xF10F0001, + 0xC78, 0xF0100001, + 0xC78, 0xEF110001, + 0xC78, 0xEE120001, + 0xC78, 0xED130001, + 0xC78, 0xEC140001, + 0xC78, 0xEB150001, + 0xC78, 0xEA160001, + 0xC78, 0xE9170001, + 0xC78, 0xE8180001, + 0xC78, 0xE7190001, + 0xC78, 0xE61A0001, + 0xC78, 0xE51B0001, + 0xC78, 0xE41C0001, + 0xC78, 0xE31D0001, + 0xC78, 0xE21E0001, + 0xC78, 0xE11F0001, + 0xC78, 0x8A200001, + 0xC78, 0x89210001, + 0xC78, 0x88220001, + 0xC78, 0x87230001, + 0xC78, 0x86240001, + 0xC78, 0x85250001, + 0xC78, 0x84260001, + 0xC78, 0x83270001, + 0xC78, 0x82280001, + 0xC78, 0x6B290001, + 0xC78, 0x6A2A0001, + 0xC78, 0x692B0001, + 0xC78, 0x682C0001, + 0xC78, 0x672D0001, + 0xC78, 0x662E0001, + 0xC78, 0x652F0001, + 0xC78, 0x64300001, + 0xC78, 0x63310001, + 0xC78, 0x62320001, + 0xC78, 0x61330001, + 0xC78, 0x46340001, + 0xC78, 0x45350001, + 0xC78, 0x44360001, + 0xC78, 0x43370001, + 0xC78, 0x42380001, + 0xC78, 0x41390001, + 0xC78, 0x403A0001, + 0xC78, 0x403B0001, + 0xC78, 0x403C0001, + 0xC78, 0x403D0001, + 0xC78, 0x403E0001, + 0xC78, 0x403F0001, + 0xC78, 0xFB400001, + 0xC78, 0xFB410001, + 0xC78, 0xFB420001, + 0xC78, 0xFB430001, + 0xC78, 0xFB440001, + 0xC78, 0xFB450001, + 0xC78, 0xFB460001, + 0xC78, 0xFB470001, + 0xC78, 0xFB480001, + 0xC78, 0xFA490001, + 0xC78, 0xF94A0001, + 0xC78, 0xF84B0001, + 0xC78, 0xF74C0001, + 0xC78, 0xF64D0001, + 0xC78, 0xF54E0001, + 0xC78, 0xF44F0001, + 0xC78, 0xF3500001, + 0xC78, 0xF2510001, + 0xC78, 0xF1520001, + 0xC78, 0xF0530001, + 0xC78, 0xEF540001, + 0xC78, 0xEE550001, + 0xC78, 0xED560001, + 0xC78, 0xEC570001, + 0xC78, 0xEB580001, + 0xC78, 0xEA590001, + 0xC78, 0xE95A0001, + 0xC78, 0xE85B0001, + 0xC78, 0xE75C0001, + 0xC78, 0xE65D0001, + 0xC78, 0xE55E0001, + 0xC78, 0xE45F0001, + 0xC78, 0xE3600001, + 0xC78, 0xE2610001, + 0xC78, 0xC3620001, + 0xC78, 0xC2630001, + 0xC78, 0xC1640001, + 0xC78, 0x8B650001, + 0xC78, 0x8A660001, + 0xC78, 0x89670001, + 0xC78, 0x88680001, + 0xC78, 0x87690001, + 0xC78, 0x866A0001, + 0xC78, 0x856B0001, + 0xC78, 0x846C0001, + 0xC78, 0x676D0001, + 0xC78, 0x666E0001, + 0xC78, 0x656F0001, + 0xC78, 0x64700001, + 0xC78, 0x63710001, + 0xC78, 0x62720001, + 0xC78, 0x61730001, + 0xC78, 0x60740001, + 0xC78, 0x46750001, + 0xC78, 0x45760001, + 0xC78, 0x44770001, + 0xC78, 0x43780001, + 0xC78, 0x42790001, + 0xC78, 0x417A0001, + 0xC78, 0x407B0001, + 0xC78, 0x407C0001, + 0xC78, 0x407D0001, + 0xC78, 0x407E0001, + 0xC78, 0x407F0001, + +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h new file mode 100644 index 000000000000..403c4ddd236f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/table.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CE_TABLE__H_ +#define __RTL92CE_TABLE__H_ + +#include +#define RTL8188EEPHY_REG_1TARRAYLEN 382 +extern u32 RTL8188EEPHY_REG_1TARRAY[]; +#define RTL8188EEPHY_REG_ARRAY_PGLEN 264 +extern u32 RTL8188EEPHY_REG_ARRAY_PG[]; +#define RTL8188EE_RADIOA_1TARRAYLEN 190 +extern u32 RTL8188EE_RADIOA_1TARRAY[]; +#define RTL8188EEMAC_1T_ARRAYLEN 180 +extern u32 RTL8188EEMAC_1T_ARRAY[]; +#define RTL8188EEAGCTAB_1TARRAYLEN 256 +extern u32 RTL8188EEAGCTAB_1TARRAY[]; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c new file mode 100644 index 000000000000..791efbe6b18c --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c @@ -0,0 +1,858 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../stats.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "trx.h" +#include "led.h" +#include "dm.h" +#include "phy.h" + +static u8 _rtl88ee_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) +{ + __le16 fc = rtl_get_fc(skb); + + if (unlikely(ieee80211_is_beacon(fc))) + return QSLT_BEACON; + if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) + return QSLT_MGNT; + + return skb->priority; +} + +static void _rtl88ee_query_rxphystatus(struct ieee80211_hw *hw, + struct rtl_stats *pstatus, u8 *pdesc, + struct rx_fwinfo_88e *p_drvinfo, + bool bpacket_match_bssid, + bool bpacket_toself, bool packet_beacon) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); + struct phy_sts_cck_8192s_t *cck_buf; + struct phy_status_rpt *phystrpt = + (struct phy_status_rpt *)p_drvinfo; + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + char rx_pwr_all = 0, rx_pwr[4]; + u8 rf_rx_num = 0, evm, pwdb_all; + u8 i, max_spatial_stream; + u32 rssi, total_rssi = 0; + bool is_cck = pstatus->is_cck; + u8 lan_idx, vga_idx; + + /* Record it for next packet processing */ + pstatus->packet_matchbssid = bpacket_match_bssid; + pstatus->packet_toself = bpacket_toself; + pstatus->packet_beacon = packet_beacon; + pstatus->rx_mimo_signalquality[0] = -1; + pstatus->rx_mimo_signalquality[1] = -1; + + if (is_cck) { + u8 cck_highpwr; + u8 cck_agc_rpt; + /* CCK Driver info Structure is not the same as OFDM packet. */ + cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; + cck_agc_rpt = cck_buf->cck_agc_rpt; + + /* (1)Hardware does not provide RSSI for CCK + * (2)PWDB, Average PWDB cacluated by + * hardware (for rate adaptive) + */ + if (ppsc->rfpwr_state == ERFON) + cck_highpwr = + (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, + BIT(9)); + else + cck_highpwr = false; + + lan_idx = ((cck_agc_rpt & 0xE0) >> 5); + vga_idx = (cck_agc_rpt & 0x1f); + switch (lan_idx) { + case 7: + if (vga_idx <= 27) + /*VGA_idx = 27~2*/ + rx_pwr_all = -100 + 2*(27-vga_idx); + else + rx_pwr_all = -100; + break; + case 6: + /*VGA_idx = 2~0*/ + rx_pwr_all = -48 + 2*(2-vga_idx); + break; + case 5: + /*VGA_idx = 7~5*/ + rx_pwr_all = -42 + 2*(7-vga_idx); + break; + case 4: + /*VGA_idx = 7~4*/ + rx_pwr_all = -36 + 2*(7-vga_idx); + break; + case 3: + /*VGA_idx = 7~0*/ + rx_pwr_all = -24 + 2*(7-vga_idx); + break; + case 2: + if (cck_highpwr) + /*VGA_idx = 5~0*/ + rx_pwr_all = -12 + 2*(5-vga_idx); + else + rx_pwr_all = -6 + 2*(5-vga_idx); + break; + case 1: + rx_pwr_all = 8-2*vga_idx; + break; + case 0: + rx_pwr_all = 14-2*vga_idx; + break; + default: + break; + } + rx_pwr_all += 6; + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + /* CCK gain is smaller than OFDM/MCS gain, */ + /* so we add gain diff by experiences, the val is 6 */ + pwdb_all += 6; + if (pwdb_all > 100) + pwdb_all = 100; + /* modify the offset to make the same + * gain index with OFDM. + */ + if (pwdb_all > 34 && pwdb_all <= 42) + pwdb_all -= 2; + else if (pwdb_all > 26 && pwdb_all <= 34) + pwdb_all -= 6; + else if (pwdb_all > 14 && pwdb_all <= 26) + pwdb_all -= 8; + else if (pwdb_all > 4 && pwdb_all <= 14) + pwdb_all -= 4; + if (!cck_highpwr) { + if (pwdb_all >= 80) + pwdb_all = ((pwdb_all-80)<<1) + + ((pwdb_all-80)>>1) + 80; + else if ((pwdb_all <= 78) && (pwdb_all >= 20)) + pwdb_all += 3; + if (pwdb_all > 100) + pwdb_all = 100; + } + + pstatus->rx_pwdb_all = pwdb_all; + pstatus->recvsignalpower = rx_pwr_all; + + /* (3) Get Signal Quality (EVM) */ + if (bpacket_match_bssid) { + u8 sq; + + if (pstatus->rx_pwdb_all > 40) + sq = 100; + else { + sq = cck_buf->sq_rpt; + if (sq > 64) + sq = 0; + else if (sq < 20) + sq = 100; + else + sq = ((64 - sq) * 100) / 44; + } + + pstatus->signalquality = sq; + pstatus->rx_mimo_signalquality[0] = sq; + pstatus->rx_mimo_signalquality[1] = -1; + } + } else { + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + + /* (1)Get RSSI for HT rate */ + for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { + /* we will judge RF RX path now. */ + if (rtlpriv->dm.rfpath_rxenable[i]) + rf_rx_num++; + + rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & + 0x3f) * 2) - 110; + + /* Translate DBM to percentage. */ + rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + + /* Get Rx snr value in DB */ + rtlpriv->stats.rx_snr_db[i] = + (long)(p_drvinfo->rxsnr[i] / 2); + + /* Record Signal Strength for next packet */ + if (bpacket_match_bssid) + pstatus->rx_mimo_signalstrength[i] = (u8)rssi; + } + + /* (2)PWDB, Average PWDB cacluated by + * hardware (for rate adaptive) + */ + rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; + + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + pstatus->rx_pwdb_all = pwdb_all; + pstatus->rxpower = rx_pwr_all; + pstatus->recvsignalpower = rx_pwr_all; + + /* (3)EVM of HT rate */ + if (pstatus->is_ht && pstatus->rate >= DESC92C_RATEMCS8 && + pstatus->rate <= DESC92C_RATEMCS15) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + + for (i = 0; i < max_spatial_stream; i++) { + evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]); + + if (bpacket_match_bssid) { + /* Fill value in RFD, Get the first + * spatial stream onlyi + */ + if (i == 0) + pstatus->signalquality = + (u8)(evm & 0xff); + pstatus->rx_mimo_signalquality[i] = + (u8)(evm & 0xff); + } + } + } + + /* UI BSS List signal strength(in percentage), + * make it good looking, from 0~100. + */ + if (is_cck) + pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, + pwdb_all)); + else if (rf_rx_num != 0) + pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, + total_rssi /= rf_rx_num)); + /*HW antenna diversity*/ + rtldm->fat_table.antsel_rx_keep_0 = phystrpt->ant_sel; + rtldm->fat_table.antsel_rx_keep_1 = phystrpt->ant_sel_b; + rtldm->fat_table.antsel_rx_keep_2 = phystrpt->antsel_rx_keep_2; +} + +static void _rtl88ee_smart_antenna(struct ieee80211_hw *hw, + struct rtl_stats *pstatus) +{ + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 antsel_tr_mux; + struct fast_ant_training *pfat_table = &rtldm->fat_table; + + if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) { + if (pfat_table->fat_state == FAT_TRAINING_STATE) { + if (pstatus->packet_toself) { + antsel_tr_mux = + (pfat_table->antsel_rx_keep_2 << 2) | + (pfat_table->antsel_rx_keep_1 << 1) | + pfat_table->antsel_rx_keep_0; + pfat_table->ant_sum[antsel_tr_mux] += + pstatus->rx_pwdb_all; + pfat_table->ant_cnt[antsel_tr_mux]++; + } + } + } else if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || + (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)) { + if (pstatus->packet_toself || pstatus->packet_matchbssid) { + antsel_tr_mux = (pfat_table->antsel_rx_keep_2 << 2) | + (pfat_table->antsel_rx_keep_1 << 1) | + pfat_table->antsel_rx_keep_0; + rtl88e_dm_ant_sel_statistics(hw, antsel_tr_mux, 0, + pstatus->rx_pwdb_all); + } + + } +} + +static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct rtl_stats *pstatus, + u8 *pdesc, + struct rx_fwinfo_88e *p_drvinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct ieee80211_hdr *hdr; + u8 *tmp_buf; + u8 *praddr; + u8 *psaddr; + __le16 fc; + bool packet_matchbssid, packet_toself, packet_beacon; + + tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; + + hdr = (struct ieee80211_hdr *)tmp_buf; + fc = hdr->frame_control; + praddr = hdr->addr1; + psaddr = ieee80211_get_SA(hdr); + memcpy(pstatus->psaddr, psaddr, ETH_ALEN); + + packet_matchbssid = ((!ieee80211_is_ctl(fc)) && + (ether_addr_equal(mac->bssid, ieee80211_has_tods(fc) ? + hdr->addr1 : ieee80211_has_fromds(fc) ? + hdr->addr2 : hdr->addr3)) && + (!pstatus->hwerror) && + (!pstatus->crc) && (!pstatus->icv)); + + packet_toself = packet_matchbssid && + (ether_addr_equal(praddr, rtlefuse->dev_addr)); + + if (ieee80211_is_beacon(hdr->frame_control)) + packet_beacon = true; + else + packet_beacon = false; + + _rtl88ee_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo, + packet_matchbssid, packet_toself, + packet_beacon); + _rtl88ee_smart_antenna(hw, pstatus); + rtl_process_phyinfo(hw, tmp_buf, pstatus); +} + +static void _rtl88ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, + u8 *virtualaddress) +{ + u32 dwtmp = 0; + memset(virtualaddress, 0, 8); + + SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); + if (ptcb_desc->empkt_num == 1) { + dwtmp = ptcb_desc->empkt_len[0]; + } else { + dwtmp = ptcb_desc->empkt_len[0]; + dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; + dwtmp += ptcb_desc->empkt_len[1]; + } + SET_EARLYMODE_LEN0(virtualaddress, dwtmp); + + if (ptcb_desc->empkt_num <= 3) { + dwtmp = ptcb_desc->empkt_len[2]; + } else { + dwtmp = ptcb_desc->empkt_len[2]; + dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; + dwtmp += ptcb_desc->empkt_len[3]; + } + SET_EARLYMODE_LEN1(virtualaddress, dwtmp); + if (ptcb_desc->empkt_num <= 5) { + dwtmp = ptcb_desc->empkt_len[4]; + } else { + dwtmp = ptcb_desc->empkt_len[4]; + dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; + dwtmp += ptcb_desc->empkt_len[5]; + } + SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF); + SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4); + if (ptcb_desc->empkt_num <= 7) { + dwtmp = ptcb_desc->empkt_len[6]; + } else { + dwtmp = ptcb_desc->empkt_len[6]; + dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; + dwtmp += ptcb_desc->empkt_len[7]; + } + SET_EARLYMODE_LEN3(virtualaddress, dwtmp); + if (ptcb_desc->empkt_num <= 9) { + dwtmp = ptcb_desc->empkt_len[8]; + } else { + dwtmp = ptcb_desc->empkt_len[8]; + dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; + dwtmp += ptcb_desc->empkt_len[9]; + } + SET_EARLYMODE_LEN4(virtualaddress, dwtmp); +} + +bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *status, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rx_fwinfo_88e *p_drvinfo; + struct ieee80211_hdr *hdr; + + u32 phystatus = GET_RX_DESC_PHYST(pdesc); + status->packet_report_type = (u8)GET_RX_STATUS_DESC_RPT_SEL(pdesc); + if (status->packet_report_type == TX_REPORT2) + status->length = (u16)GET_RX_RPT2_DESC_PKT_LEN(pdesc); + else + status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); + status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * + RX_DRV_INFO_SIZE_UNIT; + status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03); + status->icv = (u16)GET_RX_DESC_ICV(pdesc); + status->crc = (u16)GET_RX_DESC_CRC32(pdesc); + status->hwerror = (status->crc | status->icv); + status->decrypted = !GET_RX_DESC_SWDEC(pdesc); + status->rate = (u8)GET_RX_DESC_RXMCS(pdesc); + status->shortpreamble = (u16)GET_RX_DESC_SPLCP(pdesc); + status->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); + status->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1) && + (GET_RX_DESC_FAGGR(pdesc) == 1)); + if (status->packet_report_type == NORMAL_RX) + status->timestamp_low = GET_RX_DESC_TSFL(pdesc); + status->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); + status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); + + status->is_cck = RTL8188_RX_HAL_IS_CCK_RATE(status->rate); + + status->macid = GET_RX_DESC_MACID(pdesc); + if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) + status->wake_match = BIT(2); + else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) + status->wake_match = BIT(1); + else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) + status->wake_match = BIT(0); + else + status->wake_match = 0; + if (status->wake_match) + RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, + "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n", + status->wake_match); + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + + hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size + + status->rx_bufshift); + + if (status->crc) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (status->rx_is40Mhzpacket) + rx_status->flag |= RX_FLAG_40MHZ; + + if (status->is_ht) + rx_status->flag |= RX_FLAG_HT; + + rx_status->flag |= RX_FLAG_MACTIME_START; + + /* hw will set status->decrypted true, if it finds the + * frame is open data frame or mgmt frame. + * So hw will not decryption robust managment frame + * for IEEE80211w but still set status->decrypted + * true, so here we should set it back to undecrypted + * for IEEE80211w frame, and mac80211 sw will help + * to decrypt it + */ + if (status->decrypted) { + if ((!_ieee80211_is_robust_mgmt_frame(hdr)) && + (ieee80211_has_protected(hdr->frame_control))) + rx_status->flag |= RX_FLAG_DECRYPTED; + else + rx_status->flag &= ~RX_FLAG_DECRYPTED; + } + + /* rate_idx: index of data rate into band's + * supported rates or MCS index if HT rates + * are use (RX_FLAG_HT) + * Notice: this is diff with windows define + */ + rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht, + false, status->rate); + + rx_status->mactime = status->timestamp_low; + if (phystatus == true) { + p_drvinfo = (struct rx_fwinfo_88e *)(skb->data + + status->rx_bufshift); + + _rtl88ee_translate_rx_signal_stuff(hw, + skb, status, pdesc, + p_drvinfo); + } + rx_status->signal = status->recvsignalpower + 10; + if (status->packet_report_type == TX_REPORT2) { + status->macid_valid_entry[0] = + GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); + status->macid_valid_entry[1] = + GET_RX_RPT2_DESC_MACID_VALID_2(pdesc); + } + return true; +} + +void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *txbd, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) + +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 *pdesc = (u8 *)pdesc_tx; + u16 seq_number; + __le16 fc = hdr->frame_control; + unsigned int buf_len = 0; + unsigned int skb_len = skb->len; + u8 fw_qsel = _rtl88ee_map_hwqueue_to_fwqueue(skb, hw_queue); + bool firstseg = ((hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); + bool lastseg = ((hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); + dma_addr_t mapping; + u8 bw_40 = 0; + u8 short_gi = 0; + + if (mac->opmode == NL80211_IFTYPE_STATION) { + bw_40 = mac->bw_40; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta) + bw_40 = sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40; + } + seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); + /* reserve 8 byte for AMPDU early mode */ + if (rtlhal->earlymode_enable) { + skb_push(skb, EM_HDR_LEN); + memset(skb->data, 0, EM_HDR_LEN); + } + buf_len = skb->len; + mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_88e)); + if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { + firstseg = true; + lastseg = true; + } + if (firstseg) { + if (rtlhal->earlymode_enable) { + SET_TX_DESC_PKT_OFFSET(pdesc, 1); + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + + EM_HDR_LEN); + if (ptcb_desc->empkt_num) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "Insert 8 byte.pTcb->EMPktNum:%d\n", + ptcb_desc->empkt_num); + _rtl88ee_insert_emcontent(ptcb_desc, + (u8 *)(skb->data)); + } + } else { + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + } + + ptcb_desc->use_driver_rate = true; + SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); + if (ptcb_desc->hw_rate > DESC92C_RATEMCS0) + short_gi = (ptcb_desc->use_shortgi) ? 1 : 0; + else + short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0; + + SET_TX_DESC_DATA_SHORTGI(pdesc, short_gi); + + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + SET_TX_DESC_AGG_ENABLE(pdesc, 1); + SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); + } + SET_TX_DESC_SEQ(pdesc, seq_number); + SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && + !ptcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_HW_RTS_ENABLE(pdesc, 0); + SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); + + SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); + SET_TX_DESC_RTS_BW(pdesc, 0); + SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); + SET_TX_DESC_RTS_SHORT(pdesc, + ((ptcb_desc->rts_rate <= DESC92C_RATE54M) ? + (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : + (ptcb_desc->rts_use_shortgi ? 1 : 0))); + + if (ptcb_desc->tx_enable_sw_calc_duration) + SET_TX_DESC_NAV_USE_HDR(pdesc, 1); + + if (bw_40) { + if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { + SET_TX_DESC_DATA_BW(pdesc, 1); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + mac->cur_40_prime_sc); + } + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + } + + SET_TX_DESC_LINIP(pdesc, 0); + SET_TX_DESC_PKT_SIZE(pdesc, (u16)skb_len); + if (sta) { + u8 ampdu_density = sta->ht_cap.ampdu_density; + SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); + } + if (info->control.hw_key) { + struct ieee80211_key_conf *keyconf; + + keyconf = info->control.hw_key; + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x1); + break; + case WLAN_CIPHER_SUITE_CCMP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x3); + break; + default: + SET_TX_DESC_SEC_TYPE(pdesc, 0x0); + break; + + } + } + + SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); + SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); + SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); + SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ? + 1 : 0); + SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); + + /*SET_TX_DESC_PWR_STATUS(pdesc, pwr_status);*/ + /* Set TxRate and RTSRate in TxDesc */ + /* This prevent Tx initial rate of new-coming packets */ + /* from being overwritten by retried packet rate.*/ + if (!ptcb_desc->use_driver_rate) { + /*SET_TX_DESC_RTS_RATE(pdesc, 0x08); */ + /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */ + } + if (ieee80211_is_data_qos(fc)) { + if (mac->rdg_en) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "Enable RDG function.\n"); + SET_TX_DESC_RDG_ENABLE(pdesc, 1); + SET_TX_DESC_HTC(pdesc, 1); + } + } + } + + SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); + SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)buf_len); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + if (rtlpriv->dm.useramask) { + SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); + } else { + SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); + } + if (ieee80211_is_data_qos(fc)) + SET_TX_DESC_QOS(pdesc, 1); + + if (!ieee80211_is_data_qos(fc)) + SET_TX_DESC_HWSEQ_EN(pdesc, 1); + SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { + SET_TX_DESC_BMC(pdesc, 1); + } + + rtl88e_dm_set_tx_ant_by_tx_info(hw, pdesc, ptcb_desc->mac_id); + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); +} + +void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, + u8 *pdesc, bool firstseg, + bool lastseg, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 fw_queue = QSLT_BEACON; + + dma_addr_t mapping = pci_map_single(rtlpci->pdev, + skb->data, skb->len, + PCI_DMA_TODEVICE); + + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + __le16 fc = hdr->frame_control; + + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); + + if (firstseg) + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + + SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); + + SET_TX_DESC_SEQ(pdesc, 0); + + SET_TX_DESC_LINIP(pdesc, 0); + + SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); + + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + + SET_TX_DESC_RATE_ID(pdesc, 7); + SET_TX_DESC_MACID(pdesc, 0); + + SET_TX_DESC_OWN(pdesc, 1); + + SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_OFFSET(pdesc, 0x20); + + SET_TX_DESC_USE_RATE(pdesc, 1); + + if (!ieee80211_is_data_qos(fc)) + SET_TX_DESC_HWSEQ_EN(pdesc, 1); + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C Tx Cmd Content\n", + pdesc, TX_DESC_SIZE); +} + +void rtl88ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, + bool istx, u8 desc_name, u8 *val) +{ + if (istx == true) { + switch (desc_name) { + case HW_DESC_OWN: + SET_TX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_TX_NEXTDESC_ADDR: + SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *)val); + break; + default: + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_RXOWN: + SET_RX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_RXBUFF_ADDR: + SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *)val); + break; + case HW_DESC_RXPKT_LEN: + SET_RX_DESC_PKT_LEN(pdesc, *(u32 *)val); + break; + case HW_DESC_RXERO: + SET_RX_DESC_EOR(pdesc, 1); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); + break; + } + } +} + +u32 rtl88ee_get_desc(u8 *pdesc, bool istx, u8 desc_name) +{ + u32 ret = 0; + + if (istx == true) { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_TX_DESC_OWN(pdesc); + break; + case HW_DESC_TXBUFF_ADDR: + ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc); + break; + default: + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_RX_DESC_OWN(pdesc); + break; + case HW_DESC_RXPKT_LEN: + ret = GET_RX_DESC_PKT_LEN(pdesc); + break; + case HW_DESC_RXBUFF_ADDR: + ret = GET_RX_DESC_BUFF_ADDR(pdesc); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); + break; + } + } + return ret; +} + +bool rtl88ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; + u8 *entry = (u8 *)(&ring->desc[ring->idx]); + u8 own = (u8)rtl88ee_get_desc(entry, true, HW_DESC_OWN); + + /*beacon packet will only use the first + *descriptor defautly,and the own may not + *be cleared by the hardware + */ + if (own) + return false; + return true; +} + +void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (hw_queue == BEACON_QUEUE) { + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); + } else { + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, + BIT(0) << (hw_queue)); + } +} + +u32 rtl88ee_rx_command_packet(struct ieee80211_hw *hw, + struct rtl_stats status, + struct sk_buff *skb) +{ + return 0; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h new file mode 100644 index 000000000000..eab5ae0eb46c --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h @@ -0,0 +1,796 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2013 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CE_TRX_H__ +#define __RTL92CE_TRX_H__ + +#define TX_DESC_SIZE 64 +#define TX_DESC_AGGR_SUBFRAME_SIZE 32 + +#define RX_DESC_SIZE 32 +#define RX_DRV_INFO_SIZE_UNIT 8 + +#define TX_DESC_NEXT_DESC_OFFSET 40 +#define USB_HWDESC_HEADER_LEN 32 +#define CRCLENGTH 4 + +#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) +#define SET_TX_DESC_OFFSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) +#define SET_TX_DESC_BMC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) +#define SET_TX_DESC_HTC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) +#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) +#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) +#define SET_TX_DESC_LINIP(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) +#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) +#define SET_TX_DESC_GF(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) +#define SET_TX_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +#define GET_TX_DESC_PKT_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 0, 16) +#define GET_TX_DESC_OFFSET(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 16, 8) +#define GET_TX_DESC_BMC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 24, 1) +#define GET_TX_DESC_HTC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 25, 1) +#define GET_TX_DESC_LAST_SEG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 26, 1) +#define GET_TX_DESC_FIRST_SEG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 27, 1) +#define GET_TX_DESC_LINIP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 28, 1) +#define GET_TX_DESC_NO_ACM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 29, 1) +#define GET_TX_DESC_GF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 30, 1) +#define GET_TX_DESC_OWN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 31, 1) + +#define SET_TX_DESC_MACID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 6, __val) +#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) +#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) +#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) +#define SET_TX_DESC_PIFS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) +#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val) +#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val) +#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) +#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) +#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 26, 5, __val) +#define SET_TX_DESC_PADDING_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val) + +#define GET_TX_DESC_MACID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) +#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 5, 1) +#define GET_TX_DESC_AGG_BREAK(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 6, 1) +#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 7, 1) +#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 8, 5) +#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) +#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) +#define GET_TX_DESC_PIFS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) +#define GET_TX_DESC_RATE_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) +#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) +#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) +#define GET_TX_DESC_SEC_TYPE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 22, 2) +#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 24, 8) + +#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val) +#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val) +#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val) +#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val) +#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val) +#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val) +#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) +#define SET_TX_DESC_RAW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) +#define SET_TX_DESC_CCX(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) +#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) +#define SET_TX_DESC_BT_INT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val) +#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val) +#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val) +#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val) +#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val) +#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val) + +#define GET_TX_DESC_RTS_RC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 0, 6) +#define GET_TX_DESC_DATA_RC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 6, 6) +#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 14, 2) +#define GET_TX_DESC_MORE_FRAG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 17, 1) +#define GET_TX_DESC_RAW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 18, 1) +#define GET_TX_DESC_CCX(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 19, 1) +#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 20, 3) +#define GET_TX_DESC_ANTSEL_A(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 24, 1) +#define GET_TX_DESC_ANTSEL_B(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 25, 1) +#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 26, 2) +#define GET_TX_DESC_TX_ANTL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 28, 2) +#define GET_TX_DESC_TX_ANT_HT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 30, 2) + +#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val) +#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val) +#define SET_TX_DESC_SEQ(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val) +#define SET_TX_DESC_CPU_HANDLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 1, __val) +#define SET_TX_DESC_TAG1(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 29, 1, __val) +#define SET_TX_DESC_TRIGGER_INT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 30, 1, __val) +#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 31, 1, __val) + +#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 0, 8) +#define GET_TX_DESC_TAIL_PAGE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 8, 8) +#define GET_TX_DESC_SEQ(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 16, 12) + +#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val) +#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val) +#define SET_TX_DESC_QOS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val) +#define SET_TX_DESC_HWSEQ_SSN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val) +#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val) +#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val) +#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val) +#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val) +#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val) +#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val) +#define SET_TX_DESC_PORT_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val) +#define SET_TX_DESC_PWR_STATUS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 15, 3, __val) +#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val) +#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val) +#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val) +#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val) +#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val) +#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val) +#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val) +#define SET_TX_DESC_RTS_BW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val) +#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val) +#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val) + +#define GET_TX_DESC_RTS_RATE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 0, 5) +#define GET_TX_DESC_AP_DCFE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 5, 1) +#define GET_TX_DESC_QOS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 6, 1) +#define GET_TX_DESC_HWSEQ_EN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 7, 1) +#define GET_TX_DESC_USE_RATE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 8, 1) +#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 9, 1) +#define GET_TX_DESC_DISABLE_FB(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 10, 1) +#define GET_TX_DESC_CTS2SELF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 11, 1) +#define GET_TX_DESC_RTS_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 12, 1) +#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 13, 1) +#define GET_TX_DESC_PORT_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 14, 1) +#define GET_TX_DESC_WAIT_DCTS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 18, 1) +#define GET_TX_DESC_CTS2AP_EN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 19, 1) +#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 20, 2) +#define GET_TX_DESC_TX_STBC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 22, 2) +#define GET_TX_DESC_DATA_SHORT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 24, 1) +#define GET_TX_DESC_DATA_BW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 25, 1) +#define GET_TX_DESC_RTS_SHORT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 26, 1) +#define GET_TX_DESC_RTS_BW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 27, 1) +#define GET_TX_DESC_RTS_SC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 28, 2) +#define GET_TX_DESC_RTS_STBC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 30, 2) + +#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val) +#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val) +#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val) +#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val) +#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val) + +#define GET_TX_DESC_TX_RATE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 0, 6) +#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 6, 1) +#define GET_TX_DESC_CCX_TAG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 7, 1) +#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 8, 5) +#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 13, 4) +#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 17, 1) +#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 18, 6) +#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 24, 8) + +#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val) +#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val) +#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val) +#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val) +#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val) +#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val) +#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val) +#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val) + +#define GET_TX_DESC_TXAGC_A(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 0, 5) +#define GET_TX_DESC_TXAGC_B(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 5, 5) +#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 10, 1) +#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 11, 5) +#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 16, 4) +#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 20, 4) +#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 24, 4) +#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 28, 4) + +#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) +#define SET_TX_DESC_SW_OFFSET30(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 8, __val) +#define SET_TX_DESC_SW_OFFSET31(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val) +#define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 29, 1, __val) +#define SET_TX_DESC_NULL_0(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val) +#define SET_TX_DESC_NULL_1(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val) + +#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) + +#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val) +#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val) + +#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+32, 0, 32) +#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+36, 0, 32) + +#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) +#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val) + +#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+40, 0, 32) +#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+44, 0, 32) + +#define GET_RX_DESC_PKT_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 0, 14) +#define GET_RX_DESC_CRC32(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 14, 1) +#define GET_RX_DESC_ICV(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 15, 1) +#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 16, 4) +#define GET_RX_DESC_SECURITY(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 20, 3) +#define GET_RX_DESC_QOS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 23, 1) +#define GET_RX_DESC_SHIFT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 24, 2) +#define GET_RX_DESC_PHYST(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 26, 1) +#define GET_RX_DESC_SWDEC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 27, 1) +#define GET_RX_DESC_LS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 28, 1) +#define GET_RX_DESC_FS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 29, 1) +#define GET_RX_DESC_EOR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 30, 1) +#define GET_RX_DESC_OWN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 31, 1) + +#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) +#define SET_RX_DESC_EOR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) +#define SET_RX_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +#define GET_RX_DESC_MACID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 0, 6) +#define GET_RX_DESC_PAGGR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) +#define GET_RX_DESC_FAGGR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) +#define GET_RX_DESC_A1_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) +#define GET_RX_DESC_A2_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 20, 4) +#define GET_RX_DESC_PAM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) +#define GET_RX_DESC_PWR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) +#define GET_RX_DESC_MD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) +#define GET_RX_DESC_MF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) +#define GET_RX_DESC_TYPE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) +#define GET_RX_DESC_MC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) +#define GET_RX_DESC_BC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) +#define GET_RX_DESC_SEQ(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) +#define GET_RX_DESC_FRAG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) + +#define GET_RX_DESC_RXMCS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 0, 6) +#define GET_RX_DESC_RXHT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 6, 1) +#define GET_RX_STATUS_DESC_RX_GF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 7, 1) +#define GET_RX_DESC_SPLCP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 8, 1) +#define GET_RX_DESC_BW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 9, 1) +#define GET_RX_DESC_HTC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) +#define GET_RX_STATUS_DESC_EOSP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 11, 1) +#define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 12, 2) +#define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 14, 2) + +#define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 29, 1) +#define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 30, 1) +#define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 31, 1) + +#define GET_RX_DESC_IV1(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 0, 32) +#define GET_RX_DESC_TSFL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) + +#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) +#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) + +#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) +#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) + +/* TX report 2 format in Rx desc*/ + +#define GET_RX_RPT2_DESC_PKT_LEN(__status) \ + LE_BITS_TO_4BYTE(__status, 0, 9) +#define GET_RX_RPT2_DESC_MACID_VALID_1(__status) \ + LE_BITS_TO_4BYTE(__status+16, 0, 32) +#define GET_RX_RPT2_DESC_MACID_VALID_2(__status) \ + LE_BITS_TO_4BYTE(__status+20, 0, 32) + +#define SET_EARLYMODE_PKTNUM(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __value) +#define SET_EARLYMODE_LEN0(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr, 4, 12, __value) +#define SET_EARLYMODE_LEN1(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr, 16, 12, __value) +#define SET_EARLYMODE_LEN2_1(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr, 28, 4, __value) +#define SET_EARLYMODE_LEN2_2(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __value) +#define SET_EARLYMODE_LEN3(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 8, 12, __value) +#define SET_EARLYMODE_LEN4(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __value) + +#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ +do { \ + if (_size > TX_DESC_NEXT_DESC_OFFSET) \ + memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ + else \ + memset(__pdesc, 0, _size); \ +} while (0) + +#define RTL8188_RX_HAL_IS_CCK_RATE(rxmcs)\ + (rxmcs == DESC92C_RATE1M ||\ + rxmcs == DESC92C_RATE2M ||\ + rxmcs == DESC92C_RATE5_5M ||\ + rxmcs == DESC92C_RATE11M) + +#define IS_LITTLE_ENDIAN 1 + +struct phy_rx_agc_info_t { + #if IS_LITTLE_ENDIAN + u8 gain:7, trsw:1; + #else + u8 trsw:1, gain:7; + #endif +}; +struct phy_status_rpt { + struct phy_rx_agc_info_t path_agc[2]; + u8 ch_corr[2]; + u8 cck_sig_qual_ofdm_pwdb_all; + u8 cck_agc_rpt_ofdm_cfosho_a; + u8 cck_rpt_b_ofdm_cfosho_b; + u8 rsvd_1;/* ch_corr_msb; */ + u8 noise_power_db_msb; + u8 path_cfotail[2]; + u8 pcts_mask[2]; + u8 stream_rxevm[2]; + u8 path_rxsnr[2]; + u8 noise_power_db_lsb; + u8 rsvd_2[3]; + u8 stream_csi[2]; + u8 stream_target_csi[2]; + u8 sig_evm; + u8 rsvd_3; +#if IS_LITTLE_ENDIAN + u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ + u8 sgi_en:1; + u8 rxsc:2; + u8 idle_long:1; + u8 r_ant_train_en:1; + u8 ant_sel_b:1; + u8 ant_sel:1; +#else /* _BIG_ENDIAN_ */ + u8 ant_sel:1; + u8 ant_sel_b:1; + u8 r_ant_train_en:1; + u8 idle_long:1; + u8 rxsc:2; + u8 sgi_en:1; + u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ +#endif +} __packed; + +struct rx_fwinfo_88e { + u8 gain_trsw[4]; + u8 pwdb_all; + u8 cfosho[4]; + u8 cfotail[4]; + char rxevm[2]; + char rxsnr[4]; + u8 pdsnr[2]; + u8 csi_current[2]; + u8 csi_target[2]; + u8 sigevm; + u8 max_ex_pwr; + u8 ex_intf_flag:1; + u8 sgi_en:1; + u8 rxsc:2; + u8 reserve:4; +} __packed; + +struct tx_desc_88e { + u32 pktsize:16; + u32 offset:8; + u32 bmc:1; + u32 htc:1; + u32 lastseg:1; + u32 firstseg:1; + u32 linip:1; + u32 noacm:1; + u32 gf:1; + u32 own:1; + + u32 macid:6; + u32 rsvd0:2; + u32 queuesel:5; + u32 rd_nav_ext:1; + u32 lsig_txop_en:1; + u32 pifs:1; + u32 rateid:4; + u32 nav_usehdr:1; + u32 en_descid:1; + u32 sectype:2; + u32 pktoffset:8; + + u32 rts_rc:6; + u32 data_rc:6; + u32 agg_en:1; + u32 rdg_en:1; + u32 bar_retryht:2; + u32 agg_break:1; + u32 morefrag:1; + u32 raw:1; + u32 ccx:1; + u32 ampdudensity:3; + u32 bt_int:1; + u32 ant_sela:1; + u32 ant_selb:1; + u32 txant_cck:2; + u32 txant_l:2; + u32 txant_ht:2; + + u32 nextheadpage:8; + u32 tailpage:8; + u32 seq:12; + u32 cpu_handle:1; + u32 tag1:1; + u32 trigger_int:1; + u32 hwseq_en:1; + + u32 rtsrate:5; + u32 apdcfe:1; + u32 qos:1; + u32 hwseq_ssn:1; + u32 userrate:1; + u32 dis_rtsfb:1; + u32 dis_datafb:1; + u32 cts2self:1; + u32 rts_en:1; + u32 hwrts_en:1; + u32 portid:1; + u32 pwr_status:3; + u32 waitdcts:1; + u32 cts2ap_en:1; + u32 txsc:2; + u32 stbc:2; + u32 txshort:1; + u32 txbw:1; + u32 rtsshort:1; + u32 rtsbw:1; + u32 rtssc:2; + u32 rtsstbc:2; + + u32 txrate:6; + u32 shortgi:1; + u32 ccxt:1; + u32 txrate_fb_lmt:5; + u32 rtsrate_fb_lmt:4; + u32 retrylmt_en:1; + u32 txretrylmt:6; + u32 usb_txaggnum:8; + + u32 txagca:5; + u32 txagcb:5; + u32 usemaxlen:1; + u32 maxaggnum:5; + u32 mcsg1maxlen:4; + u32 mcsg2maxlen:4; + u32 mcsg3maxlen:4; + u32 mcs7sgimaxlen:4; + + u32 txbuffersize:16; + u32 sw_offset30:8; + u32 sw_offset31:4; + u32 rsvd1:1; + u32 antsel_c:1; + u32 null_0:1; + u32 null_1:1; + + u32 txbuffaddr; + u32 txbufferaddr64; + u32 nextdescaddress; + u32 nextdescaddress64; + + u32 reserve_pass_pcie_mm_limit[4]; +} __packed; + +struct rx_desc_88e { + u32 length:14; + u32 crc32:1; + u32 icverror:1; + u32 drv_infosize:4; + u32 security:3; + u32 qos:1; + u32 shift:2; + u32 phystatus:1; + u32 swdec:1; + u32 lastseg:1; + u32 firstseg:1; + u32 eor:1; + u32 own:1; + + u32 macid:6; + u32 tid:4; + u32 hwrsvd:5; + u32 paggr:1; + u32 faggr:1; + u32 a1_fit:4; + u32 a2_fit:4; + u32 pam:1; + u32 pwr:1; + u32 moredata:1; + u32 morefrag:1; + u32 type:2; + u32 mc:1; + u32 bc:1; + + u32 seq:12; + u32 frag:4; + u32 nextpktlen:14; + u32 nextind:1; + u32 rsvd:1; + + u32 rxmcs:6; + u32 rxht:1; + u32 amsdu:1; + u32 splcp:1; + u32 bandwidth:1; + u32 htc:1; + u32 tcpchk_rpt:1; + u32 ipcchk_rpt:1; + u32 tcpchk_valid:1; + u32 hwpcerr:1; + u32 hwpcind:1; + u32 iv0:16; + + u32 iv1; + + u32 tsfl; + + u32 bufferaddress; + u32 bufferaddress64; + +} __packed; + +void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *txbd, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); +bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *status, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb); +void rtl88ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, + bool istx, u8 desc_name, u8 *val); +u32 rtl88ee_get_desc(u8 *pdesc, bool istx, u8 desc_name); +bool rtl88ee_is_tx_desc_closed(struct ieee80211_hw *hw, + u8 hw_queue, u16 index); +void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); +void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool firstseg, bool lastseg, + struct sk_buff *skb); +u32 rtl88ee_rx_command_packet(struct ieee80211_hw *hw, + struct rtl_stats status, + struct sk_buff *skb); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/Makefile new file mode 100644 index 000000000000..aee42d7ae8a2 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/Makefile @@ -0,0 +1,9 @@ +rtl8192c-common-objs := \ + main.o \ + dm_common.o \ + fw_common.o \ + phy_common.o + +obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c-common.o + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c new file mode 100644 index 000000000000..03cbe4cf110b --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c @@ -0,0 +1,1778 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include +#include "dm_common.h" +#include "phy_common.h" +#include "../pci.h" +#include "../base.h" +#include "../core.h" + +#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1) +#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1) +#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1) +#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1) +#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1) +#define BT_MASK 0x00ffffff + +#define RTLPRIV (struct rtl_priv *) +#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ + ((RTLPRIV(_priv))->mac80211.opmode == \ + NL80211_IFTYPE_ADHOC) ? \ + ((RTLPRIV(_priv))->dm.entry_min_undec_sm_pwdb) : \ + ((RTLPRIV(_priv))->dm.undec_sm_pwdb) + +static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { + 0x7f8001fe, + 0x788001e2, + 0x71c001c7, + 0x6b8001ae, + 0x65400195, + 0x5fc0017f, + 0x5a400169, + 0x55400155, + 0x50800142, + 0x4c000130, + 0x47c0011f, + 0x43c0010f, + 0x40000100, + 0x3c8000f2, + 0x390000e4, + 0x35c000d7, + 0x32c000cb, + 0x300000c0, + 0x2d4000b5, + 0x2ac000ab, + 0x288000a2, + 0x26000098, + 0x24000090, + 0x22000088, + 0x20000080, + 0x1e400079, + 0x1c800072, + 0x1b00006c, + 0x19800066, + 0x18000060, + 0x16c0005b, + 0x15800056, + 0x14400051, + 0x1300004c, + 0x12000048, + 0x11000044, + 0x10000040, +}; + +static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, + {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, + {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, + {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, + {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, + {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, + {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, + {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, + {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, + {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, + {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, + {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, + {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, + {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, + {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, + {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, + {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, + {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, + {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, + {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, + {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, + {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} +}; + +static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, + {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, + {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, + {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, + {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, + {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, + {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, + {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, + {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, + {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, + {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, + {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, + {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, + {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, + {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, + {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, + {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, + {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} +}; + +static u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a}; + +void dm_restorepowerindex(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 index; + + for (index = 0; index < 6; index++) + rtl_write_byte(rtlpriv, power_index_reg[index], + rtlpriv->dm.powerindex_backup[index]); +} +EXPORT_SYMBOL_GPL(dm_restorepowerindex); + +void dm_writepowerindex(struct ieee80211_hw *hw, u8 value) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 index; + + for (index = 0; index < 6; index++) + rtl_write_byte(rtlpriv, power_index_reg[index], value); +} +EXPORT_SYMBOL_GPL(dm_writepowerindex); + +void dm_savepowerindex(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 index; + u8 tmp; + + for (index = 0; index < 6; index++) { + tmp = rtl_read_byte(rtlpriv, power_index_reg[index]); + rtlpriv->dm.powerindex_backup[index] = tmp; + } +} +EXPORT_SYMBOL_GPL(dm_savepowerindex); + +static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + long rssi_val_min = 0; + + if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) && + (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) { + if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0) + rssi_val_min = + (rtlpriv->dm.entry_min_undec_sm_pwdb > + rtlpriv->dm.undec_sm_pwdb) ? + rtlpriv->dm.undec_sm_pwdb : + rtlpriv->dm.entry_min_undec_sm_pwdb; + else + rssi_val_min = rtlpriv->dm.undec_sm_pwdb; + } else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT || + dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) { + rssi_val_min = rtlpriv->dm.undec_sm_pwdb; + } else if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) { + rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb; + } + + if (rssi_val_min > 100) + rssi_val_min = 100; + return (u8)rssi_val_min; +} + +static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) +{ + u32 ret_value; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); + falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); + falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); + falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); + falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); + + ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD); + falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff); + falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16); + + falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_fast_fsync_fail + + falsealm_cnt->cnt_sb_search_fail; + + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1); + ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); + falsealm_cnt->cnt_cck_fail = ret_value; + + ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3); + falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; + falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_cck_fail); + + rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0); + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0); + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", + falsealm_cnt->cnt_parity_fail, + falsealm_cnt->cnt_rate_illegal, + falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", + falsealm_cnt->cnt_ofdm_fail, + falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all); +} + +static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + u8 value_igi = dm_digtable->cur_igvalue; + + if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) + value_igi--; + else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1) + value_igi += 0; + else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2) + value_igi++; + else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2) + value_igi += 2; + + if (value_igi > DM_DIG_FA_UPPER) + value_igi = DM_DIG_FA_UPPER; + else if (value_igi < DM_DIG_FA_LOWER) + value_igi = DM_DIG_FA_LOWER; + + if (rtlpriv->falsealm_cnt.cnt_all > 10000) + value_igi = DM_DIG_FA_UPPER; + + dm_digtable->cur_igvalue = value_igi; + rtl92c_dm_write_dig(hw); +} + +static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *digtable = &rtlpriv->dm_digtable; + u32 isbt; + + /* modify DIG lower bound, deal with abnormally large false alarm */ + if (rtlpriv->falsealm_cnt.cnt_all > 10000) { + digtable->large_fa_hit++; + if (digtable->forbidden_igi < digtable->cur_igvalue) { + digtable->forbidden_igi = digtable->cur_igvalue; + digtable->large_fa_hit = 1; + } + + if (digtable->large_fa_hit >= 3) { + if ((digtable->forbidden_igi + 1) > + digtable->rx_gain_max) + digtable->rx_gain_min = digtable->rx_gain_max; + else + digtable->rx_gain_min = (digtable->forbidden_igi + 1); + digtable->recover_cnt = 3600; /* 3600=2hr */ + } + } else { + /* Recovery mechanism for IGI lower bound */ + if (digtable->recover_cnt != 0) { + digtable->recover_cnt--; + } else { + if (digtable->large_fa_hit == 0) { + if ((digtable->forbidden_igi-1) < DM_DIG_MIN) { + digtable->forbidden_igi = DM_DIG_MIN; + digtable->rx_gain_min = DM_DIG_MIN; + } else { + digtable->forbidden_igi--; + digtable->rx_gain_min = digtable->forbidden_igi + 1; + } + } else if (digtable->large_fa_hit == 3) { + digtable->large_fa_hit = 0; + } + } + } + if (rtlpriv->falsealm_cnt.cnt_all < 250) { + isbt = rtl_read_byte(rtlpriv, 0x4fd) & 0x01; + + if (!isbt) { + if (rtlpriv->falsealm_cnt.cnt_all > + digtable->fa_lowthresh) { + if ((digtable->back_val - 2) < + digtable->back_range_min) + digtable->back_val = digtable->back_range_min; + else + digtable->back_val -= 2; + } else if (rtlpriv->falsealm_cnt.cnt_all < + digtable->fa_lowthresh) { + if ((digtable->back_val + 2) > + digtable->back_range_max) + digtable->back_val = digtable->back_range_max; + else + digtable->back_val += 2; + } + } else { + digtable->back_val = DM_DIG_BACKOFF_DEFAULT; + } + } else { + /* Adjust initial gain by false alarm */ + if (rtlpriv->falsealm_cnt.cnt_all > 1000) + digtable->cur_igvalue = digtable->pre_igvalue + 2; + else if (rtlpriv->falsealm_cnt.cnt_all > 750) + digtable->cur_igvalue = digtable->pre_igvalue + 1; + else if (rtlpriv->falsealm_cnt.cnt_all < 500) + digtable->cur_igvalue = digtable->pre_igvalue - 1; + } + + /* Check initial gain by upper/lower bound */ + if (digtable->cur_igvalue > digtable->rx_gain_max) + digtable->cur_igvalue = digtable->rx_gain_max; + + if (digtable->cur_igvalue < digtable->rx_gain_min) + digtable->cur_igvalue = digtable->rx_gain_min; + + rtl92c_dm_write_dig(hw); +} + +static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) +{ + static u8 initialized; /* initialized to false */ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb; + bool multi_sta = false; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) + multi_sta = true; + + if (!multi_sta || + dm_digtable->cursta_cstate == DIG_STA_DISCONNECT) { + initialized = false; + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; + return; + } else if (initialized == false) { + initialized = true; + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; + dm_digtable->cur_igvalue = 0x20; + rtl92c_dm_write_dig(hw); + } + + if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) { + if ((rssi_strength < dm_digtable->rssi_lowthresh) && + (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) { + + if (dm_digtable->dig_ext_port_stage == + DIG_EXT_PORT_STAGE_2) { + dm_digtable->cur_igvalue = 0x20; + rtl92c_dm_write_dig(hw); + } + + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1; + } else if (rssi_strength > dm_digtable->rssi_highthresh) { + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2; + rtl92c_dm_ctrl_initgain_by_fa(hw); + } + } else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) { + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; + dm_digtable->cur_igvalue = 0x20; + rtl92c_dm_write_dig(hw); + } + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "curmultista_cstate = %x dig_ext_port_stage %x\n", + dm_digtable->curmultista_cstate, + dm_digtable->dig_ext_port_stage); +} + +static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "presta_cstate = %x, cursta_cstate = %x\n", + dm_digtable->presta_cstate, dm_digtable->cursta_cstate); + if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate || + dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT || + dm_digtable->cursta_cstate == DIG_STA_CONNECT) { + + if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { + dm_digtable->rssi_val_min = + rtl92c_dm_initial_gain_min_pwdb(hw); + if (dm_digtable->rssi_val_min > 100) + dm_digtable->rssi_val_min = 100; + rtl92c_dm_ctrl_initgain_by_rssi(hw); + } + } else { + dm_digtable->rssi_val_min = 0; + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; + dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; + dm_digtable->cur_igvalue = 0x20; + dm_digtable->pre_igvalue = 0; + rtl92c_dm_write_dig(hw); + } +} + +static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) { + dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw); + if (dm_digtable->rssi_val_min > 100) + dm_digtable->rssi_val_min = 100; + + if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { + if (dm_digtable->rssi_val_min <= 25) + dm_digtable->cur_cck_pd_state = + CCK_PD_STAGE_LOWRSSI; + else + dm_digtable->cur_cck_pd_state = + CCK_PD_STAGE_HIGHRSSI; + } else { + if (dm_digtable->rssi_val_min <= 20) + dm_digtable->cur_cck_pd_state = + CCK_PD_STAGE_LOWRSSI; + else + dm_digtable->cur_cck_pd_state = + CCK_PD_STAGE_HIGHRSSI; + } + } else { + dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX; + } + + if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) { + if ((dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) || + (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_MAX)) + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83); + else + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); + + dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state; + } +} + +static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + if (mac->act_scanning) + return; + + if (mac->link_state >= MAC80211_LINKED) + dm_digtable->cursta_cstate = DIG_STA_CONNECT; + else + dm_digtable->cursta_cstate = DIG_STA_DISCONNECT; + + dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT; + + rtl92c_dm_initial_gain_sta(hw); + rtl92c_dm_initial_gain_multi_sta(hw); + rtl92c_dm_cck_packet_detection_thresh(hw); + + dm_digtable->presta_cstate = dm_digtable->cursta_cstate; + +} + +static void rtl92c_dm_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->dm.dm_initialgain_enable == false) + return; + if (!(rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG)) + return; + + rtl92c_dm_ctrl_initgain_by_twoport(hw); +} + +static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.interface == INTF_USB && + rtlpriv->rtlhal.board_type & 0x1) { + dm_savepowerindex(hw); + rtlpriv->dm.dynamic_txpower_enable = true; + } else { + rtlpriv->dm.dynamic_txpower_enable = false; + } + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; +} + +void rtl92c_dm_write_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n", + dm_digtable->cur_igvalue, dm_digtable->pre_igvalue, + dm_digtable->back_val); + + if (rtlpriv->rtlhal.interface == INTF_USB && + !dm_digtable->dig_enable_flag) { + dm_digtable->pre_igvalue = 0x17; + return; + } + dm_digtable->cur_igvalue -= 1; + if (dm_digtable->cur_igvalue < DM_DIG_MIN) + dm_digtable->cur_igvalue = DM_DIG_MIN; + + if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) { + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, + dm_digtable->cur_igvalue); + rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, + dm_digtable->cur_igvalue); + + dm_digtable->pre_igvalue = dm_digtable->cur_igvalue; + } + RT_TRACE(rtlpriv, COMP_DIG, DBG_WARNING, + "dig values 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + dm_digtable->cur_igvalue, dm_digtable->pre_igvalue, + dm_digtable->rssi_val_min, dm_digtable->back_val, + dm_digtable->rx_gain_max, dm_digtable->rx_gain_min, + dm_digtable->large_fa_hit, dm_digtable->forbidden_igi); +} +EXPORT_SYMBOL(rtl92c_dm_write_dig); + +static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff; + + if (mac->link_state != MAC80211_LINKED) + return; + + if (mac->opmode == NL80211_IFTYPE_ADHOC || + mac->opmode == NL80211_IFTYPE_AP) { + /* TODO: Handle ADHOC and AP Mode */ + } + + if (tmpentry_max_pwdb != 0) + rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb; + else + rtlpriv->dm.entry_max_undec_sm_pwdb = 0; + + if (tmpentry_min_pwdb != 0xff) + rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb; + else + rtlpriv->dm.entry_min_undec_sm_pwdb = 0; + +/* TODO: + * if (mac->opmode == NL80211_IFTYPE_STATION) { + * if (rtlpriv->rtlhal.fw_ready) { + * u32 param = (u32)(rtlpriv->dm.undec_sm_pwdb << 16); + * rtl8192c_set_rssi_cmd(hw, param); + * } + * } + */ +} + +void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtlpriv->dm.current_turbo_edca = false; + rtlpriv->dm.is_any_nonbepkts = false; + rtlpriv->dm.is_cur_rdlstate = false; +} +EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo); + +static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + static u64 last_txok_cnt; + static u64 last_rxok_cnt; + static u32 last_bt_edca_ul; + static u32 last_bt_edca_dl; + u64 cur_txok_cnt = 0; + u64 cur_rxok_cnt = 0; + u32 edca_be_ul = 0x5ea42b; + u32 edca_be_dl = 0x5ea42b; + bool bt_change_edca = false; + + if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) || + (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) { + rtlpriv->dm.current_turbo_edca = false; + last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul; + last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl; + } + + if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) { + edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul; + bt_change_edca = true; + } + + if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) { + edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl; + bt_change_edca = true; + } + + if (mac->link_state != MAC80211_LINKED) { + rtlpriv->dm.current_turbo_edca = false; + return; + } + + if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) { + if (!(edca_be_ul & 0xffff0000)) + edca_be_ul |= 0x005e0000; + + if (!(edca_be_dl & 0xffff0000)) + edca_be_dl |= 0x005e0000; + } + + if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && + (!rtlpriv->dm.disable_framebursting))) { + + cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; + cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; + + if (cur_rxok_cnt > 4 * cur_txok_cnt) { + if (!rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + rtl_write_dword(rtlpriv, + REG_EDCA_BE_PARAM, + edca_be_dl); + rtlpriv->dm.is_cur_rdlstate = true; + } + } else { + if (rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + rtl_write_dword(rtlpriv, + REG_EDCA_BE_PARAM, + edca_be_ul); + rtlpriv->dm.is_cur_rdlstate = false; + } + } + rtlpriv->dm.current_turbo_edca = true; + } else { + if (rtlpriv->dm.current_turbo_edca) { + u8 tmp = AC0_BE; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + &tmp); + rtlpriv->dm.current_turbo_edca = false; + } + } + + rtlpriv->dm.is_any_nonbepkts = false; + last_txok_cnt = rtlpriv->stats.txbytesunicast; + last_rxok_cnt = rtlpriv->stats.rxbytesunicast; +} + +static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw + *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 thermalvalue, delta, delta_lck, delta_iqk; + long ele_a, ele_d, temp_cck, val_x, value32; + long val_y, ele_c = 0; + u8 ofdm_index[2], ofdm_index_old[2] = {0, 0}, cck_index_old = 0; + s8 cck_index = 0; + int i; + bool is2t = IS_92C_SERIAL(rtlhal->version); + s8 txpwr_level[3] = {0, 0, 0}; + u8 ofdm_min_index = 6, rf; + + rtlpriv->dm.txpower_trackinginit = true; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "rtl92c_dm_txpower_tracking_callback_thermalmeter\n"); + + thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n", + thermalvalue, rtlpriv->dm.thermalvalue, + rtlefuse->eeprom_thermalmeter); + + rtl92c_phy_ap_calibrate(hw, (thermalvalue - + rtlefuse->eeprom_thermalmeter)); + if (is2t) + rf = 2; + else + rf = 1; + + if (thermalvalue) { + ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD) & MASKOFDM_D; + + for (i = 0; i < OFDM_TABLE_LENGTH; i++) { + if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { + ofdm_index_old[0] = (u8) i; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n", + ROFDM0_XATXIQIMBALANCE, + ele_d, ofdm_index_old[0]); + break; + } + } + + if (is2t) { + ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, + MASKDWORD) & MASKOFDM_D; + + for (i = 0; i < OFDM_TABLE_LENGTH; i++) { + if (ele_d == (ofdmswing_table[i] & + MASKOFDM_D)) { + ofdm_index_old[1] = (u8) i; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, + DBG_LOUD, + "Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n", + ROFDM0_XBTXIQIMBALANCE, ele_d, + ofdm_index_old[1]); + break; + } + } + } + + temp_cck = + rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK; + + for (i = 0; i < CCK_TABLE_LENGTH; i++) { + if (rtlpriv->dm.cck_inch14) { + if (memcmp((void *)&temp_cck, + (void *)&cckswing_table_ch14[i][2], + 4) == 0) { + cck_index_old = (u8) i; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, + DBG_LOUD, + "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch 14 %d\n", + RCCK0_TXFILTER2, temp_cck, + cck_index_old, + rtlpriv->dm.cck_inch14); + break; + } + } else { + if (memcmp((void *)&temp_cck, + (void *) + &cckswing_table_ch1ch13[i][2], + 4) == 0) { + cck_index_old = (u8) i; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, + DBG_LOUD, + "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch14 %d\n", + RCCK0_TXFILTER2, temp_cck, + cck_index_old, + rtlpriv->dm.cck_inch14); + break; + } + } + } + + if (!rtlpriv->dm.thermalvalue) { + rtlpriv->dm.thermalvalue = + rtlefuse->eeprom_thermalmeter; + rtlpriv->dm.thermalvalue_lck = thermalvalue; + rtlpriv->dm.thermalvalue_iqk = thermalvalue; + for (i = 0; i < rf; i++) + rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; + rtlpriv->dm.cck_index = cck_index_old; + } + /* Handle USB High PA boards */ + + delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? + (thermalvalue - rtlpriv->dm.thermalvalue) : + (rtlpriv->dm.thermalvalue - thermalvalue); + + delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? + (thermalvalue - rtlpriv->dm.thermalvalue_lck) : + (rtlpriv->dm.thermalvalue_lck - thermalvalue); + + delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? + (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : + (rtlpriv->dm.thermalvalue_iqk - thermalvalue); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n", + thermalvalue, rtlpriv->dm.thermalvalue, + rtlefuse->eeprom_thermalmeter, delta, delta_lck, + delta_iqk); + + if (delta_lck > 1) { + rtlpriv->dm.thermalvalue_lck = thermalvalue; + rtl92c_phy_lc_calibrate(hw); + } + + if (delta > 0 && rtlpriv->dm.txpower_track_control) { + if (thermalvalue > rtlpriv->dm.thermalvalue) { + for (i = 0; i < rf; i++) + rtlpriv->dm.ofdm_index[i] -= delta; + rtlpriv->dm.cck_index -= delta; + } else { + for (i = 0; i < rf; i++) + rtlpriv->dm.ofdm_index[i] += delta; + rtlpriv->dm.cck_index += delta; + } + + if (is2t) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n", + rtlpriv->dm.ofdm_index[0], + rtlpriv->dm.ofdm_index[1], + rtlpriv->dm.cck_index); + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "temp OFDM_A_index=0x%x, cck_index=0x%x\n", + rtlpriv->dm.ofdm_index[0], + rtlpriv->dm.cck_index); + } + + if (thermalvalue > rtlefuse->eeprom_thermalmeter) { + for (i = 0; i < rf; i++) + ofdm_index[i] = + rtlpriv->dm.ofdm_index[i] + + 1; + cck_index = rtlpriv->dm.cck_index + 1; + } else { + for (i = 0; i < rf; i++) + ofdm_index[i] = + rtlpriv->dm.ofdm_index[i]; + cck_index = rtlpriv->dm.cck_index; + } + + for (i = 0; i < rf; i++) { + if (txpwr_level[i] >= 0 && + txpwr_level[i] <= 26) { + if (thermalvalue > + rtlefuse->eeprom_thermalmeter) { + if (delta < 5) + ofdm_index[i] -= 1; + + else + ofdm_index[i] -= 2; + } else if (delta > 5 && thermalvalue < + rtlefuse-> + eeprom_thermalmeter) { + ofdm_index[i] += 1; + } + } else if (txpwr_level[i] >= 27 && + txpwr_level[i] <= 32 + && thermalvalue > + rtlefuse->eeprom_thermalmeter) { + if (delta < 5) + ofdm_index[i] -= 1; + + else + ofdm_index[i] -= 2; + } else if (txpwr_level[i] >= 32 && + txpwr_level[i] <= 38 && + thermalvalue > + rtlefuse->eeprom_thermalmeter + && delta > 5) { + ofdm_index[i] -= 1; + } + } + + if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) { + if (thermalvalue > + rtlefuse->eeprom_thermalmeter) { + if (delta < 5) + cck_index -= 1; + + else + cck_index -= 2; + } else if (delta > 5 && thermalvalue < + rtlefuse->eeprom_thermalmeter) { + cck_index += 1; + } + } else if (txpwr_level[i] >= 27 && + txpwr_level[i] <= 32 && + thermalvalue > + rtlefuse->eeprom_thermalmeter) { + if (delta < 5) + cck_index -= 1; + + else + cck_index -= 2; + } else if (txpwr_level[i] >= 32 && + txpwr_level[i] <= 38 && + thermalvalue > rtlefuse->eeprom_thermalmeter + && delta > 5) { + cck_index -= 1; + } + + for (i = 0; i < rf; i++) { + if (ofdm_index[i] > OFDM_TABLE_SIZE - 1) + ofdm_index[i] = OFDM_TABLE_SIZE - 1; + + else if (ofdm_index[i] < ofdm_min_index) + ofdm_index[i] = ofdm_min_index; + } + + if (cck_index > CCK_TABLE_SIZE - 1) + cck_index = CCK_TABLE_SIZE - 1; + else if (cck_index < 0) + cck_index = 0; + + if (is2t) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "new OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n", + ofdm_index[0], ofdm_index[1], + cck_index); + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "new OFDM_A_index=0x%x, cck_index=0x%x\n", + ofdm_index[0], cck_index); + } + } + + if (rtlpriv->dm.txpower_track_control && delta != 0) { + ele_d = + (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22; + val_x = rtlphy->reg_e94; + val_y = rtlphy->reg_e9c; + + if (val_x != 0) { + if ((val_x & 0x00000200) != 0) + val_x = val_x | 0xFFFFFC00; + ele_a = ((val_x * ele_d) >> 8) & 0x000003FF; + + if ((val_y & 0x00000200) != 0) + val_y = val_y | 0xFFFFFC00; + ele_c = ((val_y * ele_d) >> 8) & 0x000003FF; + + value32 = (ele_d << 22) | + ((ele_c & 0x3F) << 16) | ele_a; + + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD, value32); + + value32 = (ele_c & 0x000003C0) >> 6; + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, + value32); + + value32 = ((val_x * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(31), value32); + + value32 = ((val_y * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(29), value32); + } else { + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD, + ofdmswing_table[ofdm_index[0]]); + + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, + 0x00); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(31) | BIT(29), 0x00); + } + + if (!rtlpriv->dm.cck_inch14) { + rtl_write_byte(rtlpriv, 0xa22, + cckswing_table_ch1ch13[cck_index] + [0]); + rtl_write_byte(rtlpriv, 0xa23, + cckswing_table_ch1ch13[cck_index] + [1]); + rtl_write_byte(rtlpriv, 0xa24, + cckswing_table_ch1ch13[cck_index] + [2]); + rtl_write_byte(rtlpriv, 0xa25, + cckswing_table_ch1ch13[cck_index] + [3]); + rtl_write_byte(rtlpriv, 0xa26, + cckswing_table_ch1ch13[cck_index] + [4]); + rtl_write_byte(rtlpriv, 0xa27, + cckswing_table_ch1ch13[cck_index] + [5]); + rtl_write_byte(rtlpriv, 0xa28, + cckswing_table_ch1ch13[cck_index] + [6]); + rtl_write_byte(rtlpriv, 0xa29, + cckswing_table_ch1ch13[cck_index] + [7]); + } else { + rtl_write_byte(rtlpriv, 0xa22, + cckswing_table_ch14[cck_index] + [0]); + rtl_write_byte(rtlpriv, 0xa23, + cckswing_table_ch14[cck_index] + [1]); + rtl_write_byte(rtlpriv, 0xa24, + cckswing_table_ch14[cck_index] + [2]); + rtl_write_byte(rtlpriv, 0xa25, + cckswing_table_ch14[cck_index] + [3]); + rtl_write_byte(rtlpriv, 0xa26, + cckswing_table_ch14[cck_index] + [4]); + rtl_write_byte(rtlpriv, 0xa27, + cckswing_table_ch14[cck_index] + [5]); + rtl_write_byte(rtlpriv, 0xa28, + cckswing_table_ch14[cck_index] + [6]); + rtl_write_byte(rtlpriv, 0xa29, + cckswing_table_ch14[cck_index] + [7]); + } + + if (is2t) { + ele_d = (ofdmswing_table[ofdm_index[1]] & + 0xFFC00000) >> 22; + + val_x = rtlphy->reg_eb4; + val_y = rtlphy->reg_ebc; + + if (val_x != 0) { + if ((val_x & 0x00000200) != 0) + val_x = val_x | 0xFFFFFC00; + ele_a = ((val_x * ele_d) >> 8) & + 0x000003FF; + + if ((val_y & 0x00000200) != 0) + val_y = val_y | 0xFFFFFC00; + ele_c = ((val_y * ele_d) >> 8) & + 0x00003FF; + + value32 = (ele_d << 22) | + ((ele_c & 0x3F) << 16) | ele_a; + rtl_set_bbreg(hw, + ROFDM0_XBTXIQIMBALANCE, + MASKDWORD, value32); + + value32 = (ele_c & 0x000003C0) >> 6; + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, + MASKH4BITS, value32); + + value32 = ((val_x * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(27), value32); + + value32 = ((val_y * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(25), value32); + } else { + rtl_set_bbreg(hw, + ROFDM0_XBTXIQIMBALANCE, + MASKDWORD, + ofdmswing_table[ofdm_index + [1]]); + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, + MASKH4BITS, 0x00); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(27) | BIT(25), 0x00); + } + + } + } + + if (delta_iqk > 3) { + rtlpriv->dm.thermalvalue_iqk = thermalvalue; + rtl92c_phy_iq_calibrate(hw, false); + } + + if (rtlpriv->dm.txpower_track_control) + rtlpriv->dm.thermalvalue = thermalvalue; + } + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===\n"); + +} + +static void rtl92c_dm_initialize_txpower_tracking_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.txpower_tracking = true; + rtlpriv->dm.txpower_trackinginit = false; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pMgntInfo->txpower_tracking = %d\n", + rtlpriv->dm.txpower_tracking); +} + +static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw) +{ + rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw); +} + +static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw) +{ + rtl92c_dm_txpower_tracking_callback_thermalmeter(hw); +} + +static void rtl92c_dm_check_txpower_tracking_thermal_meter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (!rtlpriv->dm.txpower_tracking) + return; + + if (!rtlpriv->dm.tm_trigger) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK, + 0x60); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Trigger 92S Thermal Meter!!\n"); + rtlpriv->dm.tm_trigger = 1; + return; + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Schedule TxPowerTracking direct call!!\n"); + rtl92c_dm_txpower_tracking_directcall(hw); + rtlpriv->dm.tm_trigger = 0; + } +} + +void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw) +{ + rtl92c_dm_check_txpower_tracking_thermal_meter(hw); +} +EXPORT_SYMBOL(rtl92c_dm_check_txpower_tracking); + +void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rate_adaptive *p_ra = &(rtlpriv->ra); + + p_ra->ratr_state = DM_RATR_STA_INIT; + p_ra->pre_ratr_state = DM_RATR_STA_INIT; + + if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) + rtlpriv->dm.useramask = true; + else + rtlpriv->dm.useramask = false; + +} +EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask); + +static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ps_t *dm_pstable = &rtlpriv->dm_pstable; + + dm_pstable->pre_ccastate = CCA_MAX; + dm_pstable->cur_ccasate = CCA_MAX; + dm_pstable->pre_rfstate = RF_MAX; + dm_pstable->cur_rfstate = RF_MAX; + dm_pstable->rssi_val_min = 0; +} + +void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ps_t *dm_pstable = &rtlpriv->dm_pstable; + + if (!rtlpriv->reg_init) { + rtlpriv->reg_874 = (rtl_get_bbreg(hw, + RFPGA0_XCD_RFINTERFACESW, + MASKDWORD) & 0x1CC000) >> 14; + + rtlpriv->reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1, + MASKDWORD) & BIT(3)) >> 3; + + rtlpriv->reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, + MASKDWORD) & 0xFF000000) >> 24; + + rtlpriv->reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & + 0xF000) >> 12; + + rtlpriv->reg_init = true; + } + + if (!bforce_in_normal) { + if (dm_pstable->rssi_val_min != 0) { + if (dm_pstable->pre_rfstate == RF_NORMAL) { + if (dm_pstable->rssi_val_min >= 30) + dm_pstable->cur_rfstate = RF_SAVE; + else + dm_pstable->cur_rfstate = RF_NORMAL; + } else { + if (dm_pstable->rssi_val_min <= 25) + dm_pstable->cur_rfstate = RF_NORMAL; + else + dm_pstable->cur_rfstate = RF_SAVE; + } + } else { + dm_pstable->cur_rfstate = RF_MAX; + } + } else { + dm_pstable->cur_rfstate = RF_NORMAL; + } + + if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) { + if (dm_pstable->cur_rfstate == RF_SAVE) { + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + 0x1C0000, 0x2); + rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0); + rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, + 0xFF000000, 0x63); + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + 0xC000, 0x2); + rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3); + rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); + rtl_set_bbreg(hw, 0x818, BIT(28), 0x1); + } else { + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + 0x1CC000, rtlpriv->reg_874); + rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), + rtlpriv->reg_c70); + rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000, + rtlpriv->reg_85c); + rtl_set_bbreg(hw, 0xa74, 0xF000, rtlpriv->reg_a74); + rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); + } + + dm_pstable->pre_rfstate = dm_pstable->cur_rfstate; + } +} +EXPORT_SYMBOL(rtl92c_dm_rf_saving); + +static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ps_t *dm_pstable = &rtlpriv->dm_pstable; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + /* Determine the minimum RSSI */ + if (((mac->link_state == MAC80211_NOLINK)) && + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { + dm_pstable->rssi_val_min = 0; + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, "Not connected to any\n"); + } + + if (mac->link_state == MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + dm_pstable->rssi_val_min = + rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, + "AP Client PWDB = 0x%lx\n", + dm_pstable->rssi_val_min); + } else { + dm_pstable->rssi_val_min = rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, + "STA Default Port PWDB = 0x%lx\n", + dm_pstable->rssi_val_min); + } + } else { + dm_pstable->rssi_val_min = + rtlpriv->dm.entry_min_undec_sm_pwdb; + + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, + "AP Ext Port PWDB = 0x%lx\n", + dm_pstable->rssi_val_min); + } + + /* Power Saving for 92C */ + if (IS_92C_SERIAL(rtlhal->version)) + ;/* rtl92c_dm_1r_cca(hw); */ + else + rtl92c_dm_rf_saving(hw, false); +} + +void rtl92c_dm_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; + rtlpriv->dm.dm_flag = DYNAMIC_FUNC_DISABLE | DYNAMIC_FUNC_DIG; + rtlpriv->dm.undec_sm_pwdb = -1; + rtlpriv->dm.undec_sm_cck = -1; + rtlpriv->dm.dm_initialgain_enable = true; + rtl_dm_diginit(hw, 0x20); + + rtlpriv->dm.dm_flag |= HAL_DM_HIPWR_DISABLE; + rtl92c_dm_init_dynamic_txpower(hw); + + rtl92c_dm_init_edca_turbo(hw); + rtl92c_dm_init_rate_adaptive_mask(hw); + rtlpriv->dm.dm_flag |= DYNAMIC_FUNC_SS; + rtl92c_dm_initialize_txpower_tracking(hw); + rtl92c_dm_init_dynamic_bb_powersaving(hw); + + rtlpriv->dm.ofdm_pkt_cnt = 0; + rtlpriv->dm.dm_rssi_sel = RSSI_DEFAULT; +} +EXPORT_SYMBOL(rtl92c_dm_init); + +void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undec_sm_pwdb; + + if (!rtlpriv->dm.dynamic_txpower_enable) + return; + + if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "Not connected to any\n"); + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Client PWDB = 0x%lx\n", + undec_sm_pwdb); + } else { + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "STA Default Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + } else { + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Ext Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + + if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL2; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); + } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && + (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) { + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); + } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_NORMAL\n"); + } + + if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "PHY_SetTxPowerLevel8192S() Channel = %d\n", + rtlphy->current_channel); + rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_NORMAL) + dm_restorepowerindex(hw); + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL1) + dm_writepowerindex(hw, 0x14); + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL2) + dm_writepowerindex(hw, 0x10); + } + rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; +} + +void rtl92c_dm_watchdog(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool fw_current_inpsmode = false; + bool fw_ps_awake = true; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *) (&fw_current_inpsmode)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, + (u8 *) (&fw_ps_awake)); + + if (ppsc->p2p_ps_info.p2p_ps_mode) + fw_ps_awake = false; + + if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) && + fw_ps_awake) + && (!ppsc->rfchange_inprogress)) { + rtl92c_dm_pwdb_monitor(hw); + rtl92c_dm_dig(hw); + rtl92c_dm_false_alarm_counter_statistics(hw); + rtl92c_dm_dynamic_bb_powersaving(hw); + rtl92c_dm_dynamic_txpower(hw); + rtl92c_dm_check_txpower_tracking(hw); + /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */ + rtl92c_dm_bt_coexist(hw); + rtl92c_dm_check_edca_turbo(hw); + } +} +EXPORT_SYMBOL(rtl92c_dm_watchdog); + +u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + long undec_sm_pwdb; + u8 curr_bt_rssi_state = 0x00; + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + undec_sm_pwdb = GET_UNDECORATED_AVERAGE_RSSI(rtlpriv); + } else { + if (rtlpriv->dm.entry_min_undec_sm_pwdb == 0) + undec_sm_pwdb = 100; + else + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; + } + + /* Check RSSI to determine HighPower/NormalPower state for + * BT coexistence. */ + if (undec_sm_pwdb >= 67) + curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER); + else if (undec_sm_pwdb < 62) + curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER; + + /* Check RSSI to determine AMPDU setting for BT coexistence. */ + if (undec_sm_pwdb >= 40) + curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF); + else if (undec_sm_pwdb <= 32) + curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF; + + /* Marked RSSI state. It will be used to determine BT coexistence + * setting later. */ + if (undec_sm_pwdb < 35) + curr_bt_rssi_state |= BT_RSSI_STATE_SPECIAL_LOW; + else + curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW); + + /* Check BT state related to BT_Idle in B/G mode. */ + if (undec_sm_pwdb < 15) + curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW; + else + curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW); + + if (curr_bt_rssi_state != rtlpcipriv->bt_coexist.bt_rssi_state) { + rtlpcipriv->bt_coexist.bt_rssi_state = curr_bt_rssi_state; + return true; + } else { + return false; + } +} +EXPORT_SYMBOL(rtl92c_bt_rssi_state_change); + +static bool rtl92c_bt_state_change(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + u32 polling, ratio_tx, ratio_pri; + u32 bt_tx, bt_pri; + u8 bt_state; + u8 cur_service_type; + + if (rtlpriv->mac80211.link_state < MAC80211_LINKED) + return false; + + bt_state = rtl_read_byte(rtlpriv, 0x4fd); + bt_tx = rtl_read_dword(rtlpriv, 0x488) & BT_MASK; + bt_pri = rtl_read_dword(rtlpriv, 0x48c) & BT_MASK; + polling = rtl_read_dword(rtlpriv, 0x490); + + if (bt_tx == BT_MASK && bt_pri == BT_MASK && + polling == 0xffffffff && bt_state == 0xff) + return false; + + bt_state &= BIT_OFFSET_LEN_MASK_32(0, 1); + if (bt_state != rtlpcipriv->bt_coexist.bt_cur_state) { + rtlpcipriv->bt_coexist.bt_cur_state = bt_state; + + if (rtlpcipriv->bt_coexist.reg_bt_sco == 3) { + rtlpcipriv->bt_coexist.bt_service = BT_IDLE; + + bt_state = bt_state | + ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? + 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | + BIT_OFFSET_LEN_MASK_32(2, 1); + rtl_write_byte(rtlpriv, 0x4fd, bt_state); + } + return true; + } + + ratio_tx = bt_tx * 1000 / polling; + ratio_pri = bt_pri * 1000 / polling; + rtlpcipriv->bt_coexist.ratio_tx = ratio_tx; + rtlpcipriv->bt_coexist.ratio_pri = ratio_pri; + + if (bt_state && rtlpcipriv->bt_coexist.reg_bt_sco == 3) { + + if ((ratio_tx < 30) && (ratio_pri < 30)) + cur_service_type = BT_IDLE; + else if ((ratio_pri > 110) && (ratio_pri < 250)) + cur_service_type = BT_SCO; + else if ((ratio_tx >= 200) && (ratio_pri >= 200)) + cur_service_type = BT_BUSY; + else if ((ratio_tx >= 350) && (ratio_tx < 500)) + cur_service_type = BT_OTHERBUSY; + else if (ratio_tx >= 500) + cur_service_type = BT_PAN; + else + cur_service_type = BT_OTHER_ACTION; + + if (cur_service_type != rtlpcipriv->bt_coexist.bt_service) { + rtlpcipriv->bt_coexist.bt_service = cur_service_type; + bt_state = bt_state | + ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? + 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | + ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) ? + 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); + + /* Add interrupt migration when bt is not ini + * idle state (no traffic). */ + if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { + rtl_write_word(rtlpriv, 0x504, 0x0ccc); + rtl_write_byte(rtlpriv, 0x506, 0x54); + rtl_write_byte(rtlpriv, 0x507, 0x54); + } else { + rtl_write_byte(rtlpriv, 0x506, 0x00); + rtl_write_byte(rtlpriv, 0x507, 0x00); + } + + rtl_write_byte(rtlpriv, 0x4fd, bt_state); + return true; + } + } + + return false; + +} + +static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + static bool media_connect; + + if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { + media_connect = false; + } else { + if (!media_connect) { + media_connect = true; + return true; + } + media_connect = true; + } + + return false; +} + +static void rtl92c_bt_set_normal(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + + if (rtlpcipriv->bt_coexist.bt_service == BT_OTHERBUSY) { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72b; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72b; + } else if (rtlpcipriv->bt_coexist.bt_service == BT_BUSY) { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82f; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82f; + } else if (rtlpcipriv->bt_coexist.bt_service == BT_SCO) { + if (rtlpcipriv->bt_coexist.ratio_tx > 160) { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72f; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72f; + } else { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea32b; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea42b; + } + } else { + rtlpcipriv->bt_coexist.bt_edca_ul = 0; + rtlpcipriv->bt_coexist.bt_edca_dl = 0; + } + + if ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) && + (rtlpriv->mac80211.mode == WIRELESS_MODE_G || + (rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) && + (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_BG_EDCA_LOW)) { + rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82b; + rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82b; + } +} + +static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + + /* Only enable HW BT coexist when BT in "Busy" state. */ + if (rtlpriv->mac80211.vendor == PEER_CISCO && + rtlpcipriv->bt_coexist.bt_service == BT_OTHER_ACTION) { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + } else { + if ((rtlpcipriv->bt_coexist.bt_service == BT_BUSY) && + (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_NORMAL_POWER)) { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + } else if ((rtlpcipriv->bt_coexist.bt_service == + BT_OTHER_ACTION) && (rtlpriv->mac80211.mode < + WIRELESS_MODE_N_24G) && + (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_SPECIAL_LOW)) { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + } else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte); + } else { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte); + } + } + + if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100); + else + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0); + + if (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_NORMAL_POWER) { + rtl92c_bt_set_normal(hw); + } else { + rtlpcipriv->bt_coexist.bt_edca_ul = 0; + rtlpcipriv->bt_coexist.bt_edca_dl = 0; + } + + if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { + rtlpriv->cfg->ops->set_rfreg(hw, + RF90_PATH_A, + 0x1e, + 0xf0, 0xf); + } else { + rtlpriv->cfg->ops->set_rfreg(hw, + RF90_PATH_A, 0x1e, 0xf0, + rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); + } + + if (!rtlpriv->dm.dynamic_txpower_enable) { + if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { + if (rtlpcipriv->bt_coexist.bt_rssi_state & + BT_RSSI_STATE_TXPOWER_LOW) { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_BT2; + } else { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_BT1; + } + } else { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_NORMAL; + } + rtl92c_phy_set_txpower_level(hw, + rtlpriv->phy.current_channel); + } +} + +static void rtl92c_check_bt_change(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp1byte = 0; + + if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version) && + rtlpcipriv->bt_coexist.bt_coexistence) + tmp1byte |= BIT(5); + if (rtlpcipriv->bt_coexist.bt_cur_state) { + if (rtlpcipriv->bt_coexist.bt_ant_isolation) + rtl92c_bt_ant_isolation(hw, tmp1byte); + } else { + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte); + rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0, + rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); + + rtlpcipriv->bt_coexist.bt_edca_ul = 0; + rtlpcipriv->bt_coexist.bt_edca_dl = 0; + } +} + +void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + bool wifi_connect_change; + bool bt_state_change; + bool rssi_state_change; + + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) { + + wifi_connect_change = rtl92c_bt_wifi_connect_change(hw); + bt_state_change = rtl92c_bt_state_change(hw); + rssi_state_change = rtl92c_bt_rssi_state_change(hw); + + if (wifi_connect_change || bt_state_change || rssi_state_change) + rtl92c_check_bt_change(hw); + } +} +EXPORT_SYMBOL(rtl92c_dm_bt_coexist); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h new file mode 100644 index 000000000000..4422e31fedd9 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.h @@ -0,0 +1,147 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92COMMON_DM_H__ +#define __RTL92COMMON_DM_H__ + +#include "../wifi.h" +#include "../rtl8192ce/def.h" +#include "../rtl8192ce/reg.h" +#include "fw_common.h" + +#define HAL_DM_DIG_DISABLE BIT(0) +#define HAL_DM_HIPWR_DISABLE BIT(1) + +#define OFDM_TABLE_LENGTH 37 +#define CCK_TABLE_LENGTH 33 + +#define OFDM_TABLE_SIZE 37 +#define CCK_TABLE_SIZE 33 + +#define BW_AUTO_SWITCH_HIGH_LOW 25 +#define BW_AUTO_SWITCH_LOW_HIGH 30 + +#define DM_DIG_FA_UPPER 0x32 +#define DM_DIG_FA_LOWER 0x20 +#define DM_DIG_FA_TH0 0x20 +#define DM_DIG_FA_TH1 0x100 +#define DM_DIG_FA_TH2 0x200 + +#define RXPATHSELECTION_SS_TH_lOW 30 +#define RXPATHSELECTION_DIFF_TH 18 + +#define DM_RATR_STA_INIT 0 +#define DM_RATR_STA_HIGH 1 +#define DM_RATR_STA_MIDDLE 2 +#define DM_RATR_STA_LOW 3 + +#define CTS2SELF_THVAL 30 +#define REGC38_TH 20 + +#define WAIOTTHVal 25 + +#define TXHIGHPWRLEVEL_NORMAL 0 +#define TXHIGHPWRLEVEL_LEVEL1 1 +#define TXHIGHPWRLEVEL_LEVEL2 2 +#define TXHIGHPWRLEVEL_BT1 3 +#define TXHIGHPWRLEVEL_BT2 4 + +#define DM_TYPE_BYFW 0 +#define DM_TYPE_BYDRIVER 1 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 + +#define DYNAMIC_FUNC_DISABLE 0x0 +#define DYNAMIC_FUNC_DIG BIT(0) +#define DYNAMIC_FUNC_HP BIT(1) +#define DYNAMIC_FUNC_SS BIT(2) /*Tx Power Tracking*/ +#define DYNAMIC_FUNC_BT BIT(3) +#define DYNAMIC_FUNC_ANT_DIV BIT(4) + +#define RSSI_CCK 0 +#define RSSI_OFDM 1 +#define RSSI_DEFAULT 2 + +struct swat_t { + u8 failure_cnt; + u8 try_flag; + u8 stop_trying; + long pre_rssi; + long trying_threshold; + u8 cur_antenna; + u8 pre_antenna; +}; + +enum tag_dynamic_init_gain_operation_type_definition { + DIG_TYPE_THRESH_HIGH = 0, + DIG_TYPE_THRESH_LOW = 1, + DIG_TYPE_BACKOFF = 2, + DIG_TYPE_RX_GAIN_MIN = 3, + DIG_TYPE_RX_GAIN_MAX = 4, + DIG_TYPE_ENABLE = 5, + DIG_TYPE_DISABLE = 6, + DIG_OP_TYPE_MAX +}; + +enum dm_1r_cca_e { + CCA_1R = 0, + CCA_2R = 1, + CCA_MAX = 2, +}; + +enum dm_rf_e { + RF_SAVE = 0, + RF_NORMAL = 1, + RF_MAX = 2, +}; + +enum dm_sw_ant_switch_e { + ANS_ANTENNA_B = 1, + ANS_ANTENNA_A = 2, + ANS_ANTENNA_MAX = 3, +}; + +void rtl92c_dm_init(struct ieee80211_hw *hw); +void rtl92c_dm_watchdog(struct ieee80211_hw *hw); +void rtl92c_dm_write_dig(struct ieee80211_hw *hw); +void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw); +void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw); +void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); +void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); +void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); +void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); +void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery); +void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw); +void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); +void dm_savepowerindex(struct ieee80211_hw *hw); +void dm_writepowerindex(struct ieee80211_hw *hw, u8 value); +void dm_restorepowerindex(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c new file mode 100644 index 000000000000..43fcb25c885f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.c @@ -0,0 +1,867 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../core.h" +#include "../rtl8192ce/reg.h" +#include "../rtl8192ce/def.h" +#include "fw_common.h" +#include +#include + +static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) { + u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + if (enable) + value32 |= MCUFWDL_EN; + else + value32 &= ~MCUFWDL_EN; + rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); + } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) { + u8 tmp; + if (enable) { + + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, + tmp | 0x04); + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); + rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); + } else { + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); + + rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00); + } + } +} + +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) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool is_version_b; + u8 *bufferptr = (u8 *)buffer; + + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size); + is_version_b = IS_NORMAL_CHIP(version); + if (is_version_b) { + u32 pageNums, remainsize; + u32 page, offset; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) + _rtl92c_fill_dummy(bufferptr, &size); + + pageNums = size / FW_8192C_PAGE_SIZE; + remainsize = size % FW_8192C_PAGE_SIZE; + + if (pageNums > 4) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Page numbers should not greater then 4\n"); + } + + for (page = 0; page < pageNums; page++) { + offset = page * FW_8192C_PAGE_SIZE; + _rtl92c_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); + } + } else { + _rtl92c_fw_block_write(hw, buffer, size); + } +} + +static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int err = -EIO; + u32 counter = 0; + u32 value32; + + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && + (!(value32 & FWDL_ChkSum_rpt))); + + if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "chksum report faill ! REG_MCUFWDL:0x%08x .\n", + value32); + goto exit; + } + + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); + + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + value32 |= MCUFWDL_RDY; + value32 &= ~WINTINI_RDY; + rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); + + counter = 0; + + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + if (value32 & WINTINI_RDY) { + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n", + value32); + err = 0; + goto exit; + } + + mdelay(FW_8192C_POLLING_DELAY); + + } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT); + + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32); + +exit: + return err; +} + +int rtl92c_download_fw(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtlwifi_firmware_header *pfwheader; + u8 *pfwdata; + u32 fwsize; + int err; + enum version_8192c version = rtlhal->version; + + if (!rtlhal->pfirmware) + return 1; + + pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; + pfwdata = (u8 *)rtlhal->pfirmware; + fwsize = rtlhal->fwsize; + if (IS_FW_HEADER_EXIST(pfwheader)) { + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "Firmware Version(%d), Signature(%#x),Size(%d)\n", + pfwheader->version, pfwheader->signature, + (int)sizeof(struct rtlwifi_firmware_header)); + + rtlhal->fw_version = le16_to_cpu(pfwheader->version); + rtlhal->fw_subversion = pfwheader->subversion; + pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); + fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); + } + + _rtl92c_enable_fw_download(hw, true); + _rtl92c_write_fw(hw, version, pfwdata, fwsize); + _rtl92c_enable_fw_download(hw, false); + + err = _rtl92c_fw_free_to_go(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Firmware is not ready to run!\n"); + } else { + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "Firmware is ready to run!\n"); + } + + return 0; +} +EXPORT_SYMBOL(rtl92c_download_fw); + +static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 val_hmetfr, val_mcutst_1; + bool result = false; + + val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); + val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum)); + + if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0) + result = true; + return result; +} + +static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, u8 *cmdbuffer) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 boxnum; + u16 box_reg = 0, box_extreg = 0; + u8 u1b_tmp; + bool isfw_read = false; + u8 buf_index = 0; + bool bwrite_sucess = false; + u8 wait_h2c_limmit = 100; + u8 wait_writeh2c_limmit = 100; + u8 boxcontent[4], boxextcontent[2]; + u32 h2c_waitcounter = 0; + unsigned long flag; + u8 idx; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); + + while (true) { + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + if (rtlhal->h2c_setinprogress) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C set in progress! Wait to set..element_id(%d).\n", + element_id); + while (rtlhal->h2c_setinprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, + flag); + h2c_waitcounter++; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Wait 100 us (%d times)...\n", + h2c_waitcounter); + udelay(100); + + if (h2c_waitcounter > 1000) + return; + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, + flag); + } + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + } else { + rtlhal->h2c_setinprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + break; + } + } + + while (!bwrite_sucess) { + wait_writeh2c_limmit--; + if (wait_writeh2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Write H2C fail because no trigger for FW INT!\n"); + break; + } + + boxnum = rtlhal->last_hmeboxnum; + switch (boxnum) { + case 0: + box_reg = REG_HMEBOX_0; + box_extreg = REG_HMEBOX_EXT_0; + break; + case 1: + box_reg = REG_HMEBOX_1; + box_extreg = REG_HMEBOX_EXT_1; + break; + case 2: + box_reg = REG_HMEBOX_2; + box_extreg = REG_HMEBOX_EXT_2; + break; + case 3: + box_reg = REG_HMEBOX_3; + box_extreg = REG_HMEBOX_EXT_3; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + + isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum); + while (!isfw_read) { + wait_h2c_limmit--; + if (wait_h2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Waiting too long for FW read clear HMEBox(%d)!\n", + boxnum); + break; + } + + udelay(10); + + isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum); + u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF); + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n", + boxnum, u1b_tmp); + } + + if (!isfw_read) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", + boxnum); + break; + } + + memset(boxcontent, 0, sizeof(boxcontent)); + memset(boxextcontent, 0, sizeof(boxextcontent)); + boxcontent[0] = element_id; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Write element_id box_reg(%4x) = %2x\n", + box_reg, element_id); + + switch (cmd_len) { + case 1: + boxcontent[0] &= ~(BIT(7)); + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index, 1); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 2: + boxcontent[0] &= ~(BIT(7)); + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index, 2); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 3: + boxcontent[0] &= ~(BIT(7)); + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index, 3); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 4: + boxcontent[0] |= (BIT(7)); + memcpy((u8 *)(boxextcontent), + cmdbuffer + buf_index, 2); + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index + 2, 2); + + for (idx = 0; idx < 2; idx++) { + rtl_write_byte(rtlpriv, box_extreg + idx, + boxextcontent[idx]); + } + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 5: + boxcontent[0] |= (BIT(7)); + memcpy((u8 *)(boxextcontent), + cmdbuffer + buf_index, 2); + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index + 2, 3); + + for (idx = 0; idx < 2; idx++) { + rtl_write_byte(rtlpriv, box_extreg + idx, + boxextcontent[idx]); + } + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + + bwrite_sucess = true; + + rtlhal->last_hmeboxnum = boxnum + 1; + if (rtlhal->last_hmeboxnum == 4) + rtlhal->last_hmeboxnum = 0; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "pHalData->last_hmeboxnum = %d\n", + rtlhal->last_hmeboxnum); + } + + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + rtlhal->h2c_setinprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); +} + +void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, u8 *cmdbuffer) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 tmp_cmdbuf[2]; + + if (!rtlhal->fw_ready) { + RT_ASSERT(false, + "return H2C cmd because of Fw download fail!!!\n"); + return; + } + + memset(tmp_cmdbuf, 0, 8); + memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); + _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); + + return; +} +EXPORT_SYMBOL(rtl92c_fill_h2c_cmd); + +void rtl92c_firmware_selfreset(struct ieee80211_hw *hw) +{ + u8 u1b_tmp; + u8 delay = 100; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20); + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + + while (u1b_tmp & BIT(2)) { + delay--; + if (delay == 0) { + RT_ASSERT(false, "8051 reset fail.\n"); + break; + } + udelay(50); + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + } +} +EXPORT_SYMBOL(rtl92c_firmware_selfreset); + +void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1_h2c_set_pwrmode[3] = { 0 }; + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); + + SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); + SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, + (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1); + SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, + ppsc->reg_max_lps_awakeintvl); + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n", + u1_h2c_set_pwrmode, 3); + rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode); +} +EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd); + +#define BEACON_PG 0 /*->1*/ +#define PSPOLL_PG 2 +#define NULL_PG 3 +#define PROBERSP_PG 4 /*->5*/ + +#define TOTAL_RESERVED_PKT_LEN 768 + +static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { + /* page 0 beacon */ + 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, + 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, + 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, + 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, + 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, + 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, + 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 1 beacon */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 2 ps-poll */ + 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 3 null */ + 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 4 probe_resp */ + 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, + 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, + 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, + 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, + 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, + 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, + 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, + 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, + 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 5 probe_resp */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, + bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *)) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct sk_buff *skb = NULL; + + u32 totalpacketlen; + bool rtstatus; + u8 u1rsvdpageloc[3] = { 0 }; + bool b_dlok = false; + + u8 *beacon; + u8 *p_pspoll; + u8 *nullfunc; + u8 *p_probersp; + /*--------------------------------------------------------- + (1) beacon + ---------------------------------------------------------*/ + beacon = &reserved_page_packet[BEACON_PG * 128]; + SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); + SET_80211_HDR_ADDRESS3(beacon, mac->bssid); + + /*------------------------------------------------------- + (2) ps-poll + --------------------------------------------------------*/ + p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; + SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); + SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); + SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); + + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); + + /*-------------------------------------------------------- + (3) null data + ---------------------------------------------------------*/ + nullfunc = &reserved_page_packet[NULL_PG * 128]; + SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); + SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); + SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); + + /*--------------------------------------------------------- + (4) probe response + ----------------------------------------------------------*/ + p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; + SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); + SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); + SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); + + totalpacketlen = TOTAL_RESERVED_PKT_LEN; + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + &reserved_page_packet[0], totalpacketlen); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + u1rsvdpageloc, 3); + + + skb = dev_alloc_skb(totalpacketlen); + memcpy((u8 *)skb_put(skb, totalpacketlen), + &reserved_page_packet, totalpacketlen); + + if (cmd_send_packet) + rtstatus = cmd_send_packet(hw, skb); + else + rtstatus = rtl_cmd_send_packet(hw, skb); + + if (rtstatus) + b_dlok = true; + + if (b_dlok) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Set RSVD page location to Fw.\n"); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "H2C_RSVDPAGE:\n", + u1rsvdpageloc, 3); + rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE, + sizeof(u1rsvdpageloc), u1rsvdpageloc); + } else + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set RSVD page location to Fw FAIL!!!!!!.\n"); +} +EXPORT_SYMBOL(rtl92c_set_fw_rsvdpagepkt); + +void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) +{ + u8 u1_joinbssrpt_parm[1] = { 0 }; + + SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); + + rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); +} +EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd); + +static void rtl92c_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) +{ + u8 u1_ctwindow_period[1] = { ctwindow}; + + rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); +} + +/* refactored routine */ +static void set_noa_data(struct rtl_priv *rtlpriv, + struct rtl_p2p_ps_info *p2pinfo, + struct p2p_ps_offload_t *p2p_ps_offload) +{ + int i; + u32 start_time, tsf_low; + + /* hw only support 2 set of NoA */ + for (i = 0 ; i < p2pinfo->noa_num ; i++) { + /* To control the reg setting for which NOA*/ + rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); + if (i == 0) + p2p_ps_offload->noa0_en = 1; + else + p2p_ps_offload->noa1_en = 1; + + /* config P2P NoA Descriptor Register */ + rtl_write_dword(rtlpriv, 0x5E0, + p2pinfo->noa_duration[i]); + rtl_write_dword(rtlpriv, 0x5E4, + p2pinfo->noa_interval[i]); + + /*Get Current TSF value */ + tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + start_time = p2pinfo->noa_start_time[i]; + if (p2pinfo->noa_count_type[i] != 1) { + while (start_time <= (tsf_low+(50*1024))) { + start_time += p2pinfo->noa_interval[i]; + if (p2pinfo->noa_count_type[i] != 255) + p2pinfo->noa_count_type[i]--; + } + } + rtl_write_dword(rtlpriv, 0x5E8, start_time); + rtl_write_dword(rtlpriv, 0x5EC, + p2pinfo->noa_count_type[i]); + } +} + +void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); + struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; + u16 ctwindow; + + switch (p2p_ps_state) { + case P2P_PS_DISABLE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "P2P_PS_DISABLE\n"); + memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); + break; + case P2P_PS_ENABLE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "P2P_PS_ENABLE\n"); + /* update CTWindow value. */ + if (p2pinfo->ctwindow > 0) { + p2p_ps_offload->ctwindow_en = 1; + ctwindow = p2pinfo->ctwindow; + rtl92c_set_p2p_ctw_period_cmd(hw, ctwindow); + } + /* call refactored routine */ + set_noa_data(rtlpriv, p2pinfo, p2p_ps_offload); + + if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { + /* rst p2p circuit */ + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, + BIT(4)); + + p2p_ps_offload->offload_en = 1; + + if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { + p2p_ps_offload->role = 1; + p2p_ps_offload->allstasleep = 0; + } else { + p2p_ps_offload->role = 0; + } + + p2p_ps_offload->discovery = 0; + } + break; + case P2P_PS_SCAN: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); + p2p_ps_offload->discovery = 1; + break; + case P2P_PS_SCAN_DONE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "P2P_PS_SCAN_DONE\n"); + p2p_ps_offload->discovery = 0; + p2pinfo->p2p_ps_state = P2P_PS_ENABLE; + break; + default: + break; + } + + rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload); + +} +EXPORT_SYMBOL_GPL(rtl92c_set_p2p_ps_offload_cmd); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h new file mode 100644 index 000000000000..864806c19ca7 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/fw_common.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C__FW__COMMON__H__ +#define __RTL92C__FW__COMMON__H__ + +#define FW_8192C_SIZE 0x3000 +#define FW_8192C_START_ADDRESS 0x1000 +#define FW_8192C_END_ADDRESS 0x1FFF +#define FW_8192C_PAGE_SIZE 4096 +#define FW_8192C_POLLING_DELAY 5 +#define FW_8192C_POLLING_TIMEOUT_COUNT 100 +#define NORMAL_CHIP BIT(4) +#define H2C_92C_KEEP_ALIVE_CTRL 48 + +#define IS_FW_HEADER_EXIST(_pfwhdr) \ + ((le16_to_cpu(_pfwhdr->signature)&0xFFF0) == 0x92C0 ||\ + (le16_to_cpu(_pfwhdr->signature)&0xFFF0) == 0x88C0) + +#define CUT_VERSION_MASK (BIT(6)|BIT(7)) +#define CHIP_VENDOR_UMC BIT(5) +#define CHIP_VENDOR_UMC_B_CUT BIT(6) /* Chip version for ECO */ +#define IS_CHIP_VER_B(version) ((version & CHIP_VER_B) ? true : false) +#define RF_TYPE_MASK (BIT(0)|BIT(1)) +#define GET_CVID_RF_TYPE(version) \ + ((version) & RF_TYPE_MASK) +#define GET_CVID_CUT_VERSION(version) \ + ((version) & CUT_VERSION_MASK) +#define IS_NORMAL_CHIP(version) \ + ((version & NORMAL_CHIP) ? true : false) +#define IS_2T2R(version) \ + (((GET_CVID_RF_TYPE(version)) == \ + CHIP_92C_BITMASK) ? true : false) +#define IS_92C_SERIAL(version) \ + ((IS_2T2R(version)) ? true : false) +#define IS_CHIP_VENDOR_UMC(version) \ + ((version & CHIP_VENDOR_UMC) ? true : false) +#define IS_VENDOR_UMC_A_CUT(version) \ + ((IS_CHIP_VENDOR_UMC(version)) ? \ + ((GET_CVID_CUT_VERSION(version)) ? false : true) : false) +#define IS_81XXC_VENDOR_UMC_B_CUT(version) \ + ((IS_CHIP_VENDOR_UMC(version)) ? \ + ((GET_CVID_CUT_VERSION(version) == \ + CHIP_VENDOR_UMC_B_CUT) ? true : false) : false) + +#define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) + +#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) +#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) + +int rtl92c_download_fw(struct ieee80211_hw *hw); +void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *p_cmdbuffer); +void rtl92c_firmware_selfreset(struct ieee80211_hw *hw); +void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); +void rtl92c_set_fw_rsvdpagepkt + (struct ieee80211_hw *hw, + bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *)); +void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); +void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len); +void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c new file mode 100644 index 000000000000..918b1d129e77 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/main.c @@ -0,0 +1,40 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include + + +MODULE_AUTHOR("lizhaoming "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Georgia "); +MODULE_AUTHOR("Ziv Huang "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n PCI wireless"); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c new file mode 100644 index 000000000000..77e61b19bf36 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c @@ -0,0 +1,1659 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../rtl8192ce/reg.h" +#include "../rtl8192ce/def.h" +#include "dm_common.h" +#include "fw_common.h" +#include "phy_common.h" +#include + +u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 returnvalue, originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n", + regaddr, bitmask); + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + returnvalue = (originalvalue & bitmask) >> bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "BBR MASK=0x%x Addr[0x%x]=0x%x\n", + bitmask, regaddr, originalvalue); + + return returnvalue; +} +EXPORT_SYMBOL(rtl92c_phy_query_bb_reg); + +void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); + + if (bitmask != MASKDWORD) { + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + data = ((originalvalue & (~bitmask)) | (data << bitshift)); + } + + rtl_write_dword(rtlpriv, regaddr, data); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); +} +EXPORT_SYMBOL(rtl92c_phy_set_bb_reg); + +u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset) +{ + RT_ASSERT(false, "deprecated!\n"); + return 0; +} +EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_read); + +void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data) +{ + RT_ASSERT(false, "deprecated!\n"); +} +EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_write); + +u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + u32 newoffset; + u32 tmplong, tmplong2; + u8 rfpi_enable = 0; + u32 retvalue; + + offset &= 0x3f; + newoffset = offset; + if (RT_CANNOT_IO(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n"); + return 0xFFFFFFFF; + } + tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); + if (rfpath == RF90_PATH_A) + tmplong2 = tmplong; + else + tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); + tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | + (newoffset << 23) | BLSSIREADEDGE; + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, + tmplong & (~BLSSIREADEDGE)); + mdelay(1); + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); + mdelay(1); + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, + tmplong | BLSSIREADEDGE); + mdelay(1); + if (rfpath == RF90_PATH_A) + rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, + BIT(8)); + else if (rfpath == RF90_PATH_B) + rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, + BIT(8)); + if (rfpi_enable) + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, + BLSSIREADBACKDATA); + else + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, + BLSSIREADBACKDATA); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf_rb, + retvalue); + return retvalue; +} +EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read); + +void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data) +{ + u32 data_and_addr; + u32 newoffset; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + + if (RT_CANNOT_IO(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n"); + return; + } + offset &= 0x3f; + newoffset = offset; + data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; + rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf3wire_offset, + data_and_addr); +} +EXPORT_SYMBOL(_rtl92c_phy_rf_serial_write); + +u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask) +{ + u32 i; + + for (i = 0; i <= 31; i++) { + if (((bitmask >> i) & 0x1) == 1) + break; + } + return i; +} +EXPORT_SYMBOL(_rtl92c_phy_calculate_bit_shift); + +static void _rtl92c_phy_bb_config_1t(struct ieee80211_hw *hw) +{ + rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2); + rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022); + rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45); + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23); + rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1); + rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2); + rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2); + rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2); + rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2); + rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2); +} + +bool rtl92c_phy_rf_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + return rtlpriv->cfg->ops->phy_rf6052_config(hw); +} +EXPORT_SYMBOL(rtl92c_phy_rf_config); + +bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + bool rtstatus; + + rtstatus = rtlpriv->cfg->ops->config_bb_with_headerfile(hw, + BASEBAND_CONFIG_PHY_REG); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); + return false; + } + if (rtlphy->rf_type == RF_1T2R) { + _rtl92c_phy_bb_config_1t(hw); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Config to 1T!!\n"); + } + if (rtlefuse->autoload_failflag == false) { + rtlphy->pwrgroup_cnt = 0; + rtstatus = rtlpriv->cfg->ops->config_bb_with_pgheaderfile(hw, + BASEBAND_CONFIG_PHY_REG); + } + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); + return false; + } + rtstatus = rtlpriv->cfg->ops->config_bb_with_headerfile(hw, + BASEBAND_CONFIG_AGC_TAB); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); + return false; + } + rtlphy->cck_high_power = + (bool)(rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, 0x200)); + + return true; +} + +EXPORT_SYMBOL(_rtl92c_phy_bb8192c_config_parafile); + +void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, + u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + if (regaddr == RTXAGC_A_RATE18_06) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][0]); + } + if (regaddr == RTXAGC_A_RATE54_24) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][1]); + } + if (regaddr == RTXAGC_A_CCK1_MCS32) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][6]); + } + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][7]); + } + if (regaddr == RTXAGC_A_MCS03_MCS00) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][2]); + } + if (regaddr == RTXAGC_A_MCS07_MCS04) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][3]); + } + if (regaddr == RTXAGC_A_MCS11_MCS08) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][4]); + } + if (regaddr == RTXAGC_A_MCS15_MCS12) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][5]); + } + if (regaddr == RTXAGC_B_RATE18_06) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][8]); + } + if (regaddr == RTXAGC_B_RATE54_24) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][9]); + } + if (regaddr == RTXAGC_B_CCK1_55_MCS32) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][14]); + } + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][15]); + } + if (regaddr == RTXAGC_B_MCS03_MCS00) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][10]); + } + if (regaddr == RTXAGC_B_MCS07_MCS04) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][11]); + } + if (regaddr == RTXAGC_B_MCS11_MCS08) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][12]); + } + if (regaddr == RTXAGC_B_MCS15_MCS12) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][13]); + + rtlphy->pwrgroup_cnt++; + } +} +EXPORT_SYMBOL(_rtl92c_store_pwrIndex_diffrate_offset); + +void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + rtlphy->default_initialgain[0] = + (u8)rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[1] = + (u8)rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[2] = + (u8)rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[3] = + (u8)rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", + rtlphy->default_initialgain[0], + rtlphy->default_initialgain[1], + rtlphy->default_initialgain[2], + rtlphy->default_initialgain[3]); + + rtlphy->framesync = (u8)rtl_get_bbreg(hw, + ROFDM0_RXDETECTOR3, MASKBYTE0); + rtlphy->framesync_c34 = rtl_get_bbreg(hw, + ROFDM0_RXDETECTOR2, MASKDWORD); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default framesync (0x%x) = 0x%x\n", + ROFDM0_RXDETECTOR3, rtlphy->framesync); +} + +void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; + + rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = + RFPGA0_XA_LSSIPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = + RFPGA0_XB_LSSIPARAMETER; + + rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = rFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = rFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER; + + rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; + + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; + + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; + + rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; + + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; + + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; + + rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBANLANCE; + rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; + + rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; + + rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE; + + rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; + + rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK; + + rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK; + rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK; + +} +EXPORT_SYMBOL(_rtl92c_phy_init_bb_rf_register_definition); + +void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 txpwr_level; + long txpwr_dbm; + + txpwr_level = rtlphy->cur_cck_txpwridx; + txpwr_dbm = _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_B, + txpwr_level); + txpwr_level = rtlphy->cur_ofdm24g_txpwridx + + rtlefuse->legacy_ht_txpowerdiff; + if (_rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, + txpwr_level) > txpwr_dbm) + txpwr_dbm = + _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, + txpwr_level); + txpwr_level = rtlphy->cur_ofdm24g_txpwridx; + if (_rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, + txpwr_level) > txpwr_dbm) + txpwr_dbm = + _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, + txpwr_level); + *powerlevel = txpwr_dbm; +} + +static void _rtl92c_get_txpower_index(struct ieee80211_hw *hw, u8 channel, + u8 *cckpowerlevel, u8 *ofdmpowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 index = (channel - 1); + + cckpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_cck[RF90_PATH_A][index]; + cckpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_cck[RF90_PATH_B][index]; + if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) { + ofdmpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index]; + ofdmpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index]; + } else if (get_rf_type(rtlphy) == RF_2T2R) { + ofdmpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index]; + ofdmpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index]; + } +} + +static void _rtl92c_ccxpower_index_check(struct ieee80211_hw *hw, + u8 channel, u8 *cckpowerlevel, + u8 *ofdmpowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; + rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; +} + +void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 cckpowerlevel[2], ofdmpowerlevel[2]; + + if (!rtlefuse->txpwr_fromeprom) + return; + _rtl92c_get_txpower_index(hw, channel, + &cckpowerlevel[0], &ofdmpowerlevel[0]); + _rtl92c_ccxpower_index_check(hw, channel, &cckpowerlevel[0], + &ofdmpowerlevel[0]); + rtlpriv->cfg->ops->phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]); + rtlpriv->cfg->ops->phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], + channel); +} +EXPORT_SYMBOL(rtl92c_phy_set_txpower_level); + +bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 idx; + u8 rf_path; + u8 ccktxpwridx = _rtl92c_phy_dbm_to_txpwr_idx(hw, WIRELESS_MODE_B, + power_indbm); + u8 ofdmtxpwridx = _rtl92c_phy_dbm_to_txpwr_idx(hw, WIRELESS_MODE_N_24G, + power_indbm); + if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0) + ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff; + else + ofdmtxpwridx = 0; + RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE, + "%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n", + power_indbm, ccktxpwridx, ofdmtxpwridx); + for (idx = 0; idx < 14; idx++) { + for (rf_path = 0; rf_path < 2; rf_path++) { + rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx; + rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] = + ofdmtxpwridx; + rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] = + ofdmtxpwridx; + } + } + rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + return true; +} +EXPORT_SYMBOL(rtl92c_phy_update_txpower_dbm); + +u8 _rtl92c_phy_dbm_to_txpwr_idx(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + long power_indbm) +{ + u8 txpwridx; + long offset; + + switch (wirelessmode) { + case WIRELESS_MODE_B: + offset = -7; + break; + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + offset = -8; + break; + default: + offset = -8; + break; + } + + if ((power_indbm - offset) > 0) + txpwridx = (u8)((power_indbm - offset) * 2); + else + txpwridx = 0; + + if (txpwridx > MAX_TXPWR_IDX_NMODE_92S) + txpwridx = MAX_TXPWR_IDX_NMODE_92S; + + return txpwridx; +} +EXPORT_SYMBOL(_rtl92c_phy_dbm_to_txpwr_idx); + +long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u8 txpwridx) +{ + long offset; + long pwrout_dbm; + + switch (wirelessmode) { + case WIRELESS_MODE_B: + offset = -7; + break; + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + offset = -8; + break; + default: + offset = -8; + break; + } + pwrout_dbm = txpwridx / 2 + offset; + return pwrout_dbm; +} +EXPORT_SYMBOL(_rtl92c_phy_txpwr_idx_to_dbm); + +void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_bw = rtlphy->current_chan_bw; + + if (rtlphy->set_bwmode_inprogress) + return; + rtlphy->set_bwmode_inprogress = true; + if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtlpriv->cfg->ops->phy_set_bw_mode_callback(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "false driver sleep or unload\n"); + rtlphy->set_bwmode_inprogress = false; + rtlphy->current_chan_bw = tmp_bw; + } +} +EXPORT_SYMBOL(rtl92c_phy_set_bw_mode); + +void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 delay; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "switch to channel%d\n", rtlphy->current_channel); + if (is_hal_stop(rtlhal)) + return; + do { + if (!rtlphy->sw_chnl_inprogress) + break; + if (!_rtl92c_phy_sw_chnl_step_by_step + (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage, + &rtlphy->sw_chnl_step, &delay)) { + if (delay > 0) + mdelay(delay); + else + continue; + } else { + rtlphy->sw_chnl_inprogress = false; + } + break; + } while (true); + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); +} +EXPORT_SYMBOL(rtl92c_phy_sw_chnl_callback); + +u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlphy->sw_chnl_inprogress) + return 0; + if (rtlphy->set_bwmode_inprogress) + return 0; + RT_ASSERT((rtlphy->current_channel <= 14), + "WIRELESS_MODE_G but channel>14"); + rtlphy->sw_chnl_inprogress = true; + rtlphy->sw_chnl_stage = 0; + rtlphy->sw_chnl_step = 0; + if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtl92c_phy_sw_chnl_callback(hw); + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + "sw_chnl_inprogress false schdule workitem\n"); + rtlphy->sw_chnl_inprogress = false; + } else { + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + "sw_chnl_inprogress false driver sleep or unload\n"); + rtlphy->sw_chnl_inprogress = false; + } + return 1; +} +EXPORT_SYMBOL(rtl92c_phy_sw_chnl); + +static void _rtl92c_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) { + if (channel == 6 && + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, + MASKDWORD, 0x00255); + } else { + u32 backuprf0x1A = + (u32)rtl_get_rfreg(hw, RF90_PATH_A, RF_RX_G1, + RFREG_OFFSET_MASK); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, + backuprf0x1A); + } + } +} + +static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, + enum swchnlcmd_id cmdid, + u32 para1, u32 para2, u32 msdelay) +{ + struct swchnlcmd *pcmd; + + if (cmdtable == NULL) { + RT_ASSERT(false, "cmdtable cannot be NULL.\n"); + return false; + } + + if (cmdtableidx >= cmdtablesz) + return false; + + pcmd = cmdtable + cmdtableidx; + pcmd->cmdid = cmdid; + pcmd->para1 = para1; + pcmd->para2 = para2; + pcmd->msdelay = msdelay; + return true; +} + +bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; + u32 precommoncmdcnt; + struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; + u32 postcommoncmdcnt; + struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; + u32 rfdependcmdcnt; + struct swchnlcmd *currentcmd = NULL; + u8 rfpath; + u8 num_total_rfpath = rtlphy->num_total_rfpath; + + precommoncmdcnt = 0; + _rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, + CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); + _rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); + + postcommoncmdcnt = 0; + + _rtl92c_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, + MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); + + rfdependcmdcnt = 0; + + RT_ASSERT((channel >= 1 && channel <= 14), + "illegal channel for Zebra: %d\n", channel); + + _rtl92c_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, + RF_CHNLBW, channel, 10); + + _rtl92c_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, + 0); + + do { + switch (*stage) { + case 0: + currentcmd = &precommoncmd[*step]; + break; + case 1: + currentcmd = &rfdependcmd[*step]; + break; + case 2: + currentcmd = &postcommoncmd[*step]; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Invalid 'stage' = %d, Check it!\n", *stage); + return true; + } + + if (currentcmd->cmdid == CMDID_END) { + if ((*stage) == 2) { + return true; + } else { + (*stage)++; + (*step) = 0; + continue; + } + } + + switch (currentcmd->cmdid) { + case CMDID_SET_TXPOWEROWER_LEVEL: + rtl92c_phy_set_txpower_level(hw, channel); + break; + case CMDID_WRITEPORT_ULONG: + rtl_write_dword(rtlpriv, currentcmd->para1, + currentcmd->para2); + break; + case CMDID_WRITEPORT_USHORT: + rtl_write_word(rtlpriv, currentcmd->para1, + (u16) currentcmd->para2); + break; + case CMDID_WRITEPORT_UCHAR: + rtl_write_byte(rtlpriv, currentcmd->para1, + (u8)currentcmd->para2); + break; + case CMDID_RF_WRITEREG: + for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { + rtlphy->rfreg_chnlval[rfpath] = + ((rtlphy->rfreg_chnlval[rfpath] & + 0xfffffc00) | currentcmd->para2); + + rtl_set_rfreg(hw, (enum radio_path)rfpath, + currentcmd->para1, + RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[rfpath]); + } + _rtl92c_phy_sw_rf_seting(hw, channel); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + + break; + } while (true); + + (*delay) = currentcmd->msdelay; + (*step)++; + return false; +} + +bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath) +{ + return true; +} +EXPORT_SYMBOL(rtl8192_phy_check_is_legal_rfpath); + +static u8 _rtl92c_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) +{ + u32 reg_eac, reg_e94, reg_e9c, reg_ea4; + u8 result = 0x00; + + rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f); + rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f); + rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102); + rtl_set_bbreg(hw, 0xe3c, MASKDWORD, + config_pathb ? 0x28160202 : 0x28160502); + + if (config_pathb) { + rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22); + rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22); + rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102); + rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202); + } + + rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); + reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); + reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + + if (!(reg_eac & BIT(27)) && + (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_eac & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + return result; +} + +static u8 _rtl92c_phy_path_b_iqk(struct ieee80211_hw *hw) +{ + u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; + u8 result = 0x00; + + rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002); + rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000); + mdelay(IQK_DELAY_TIME); + reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); + reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); + reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); + reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); + + if (!(reg_eac & BIT(31)) && + (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && + (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + if (!(reg_eac & BIT(30)) && + (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + return result; +} + +static void _rtl92c_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, + bool b_iqk_ok, long result[][8], + u8 final_candidate, bool btxonly) +{ + u32 oldval_0, x, tx0_a, reg; + long y, tx0_c; + + if (final_candidate == 0xFF) { + return; + } else if (b_iqk_ok) { + oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD) >> 22) & 0x3FF; + x = result[final_candidate][0]; + if ((x & 0x00000200) != 0) + x = x | 0xFFFFFC00; + tx0_a = (x * oldval_0) >> 8; + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31), + ((x * oldval_0 >> 7) & 0x1)); + y = result[final_candidate][1]; + if ((y & 0x00000200) != 0) + y = y | 0xFFFFFC00; + tx0_c = (y * oldval_0) >> 8; + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, + ((tx0_c & 0x3C0) >> 6)); + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000, + (tx0_c & 0x3F)); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29), + ((y * oldval_0 >> 7) & 0x1)); + if (btxonly) + return; + reg = result[final_candidate][2]; + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg); + reg = result[final_candidate][3] & 0x3F; + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg); + reg = (result[final_candidate][3] >> 6) & 0xF; + rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); + } +} + +static void _rtl92c_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw, + bool b_iqk_ok, long result[][8], + u8 final_candidate, bool btxonly) +{ + u32 oldval_1, x, tx1_a, reg; + long y, tx1_c; + + if (final_candidate == 0xFF) { + return; + } else if (b_iqk_ok) { + oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, + MASKDWORD) >> 22) & 0x3FF; + x = result[final_candidate][4]; + if ((x & 0x00000200) != 0) + x = x | 0xFFFFFC00; + tx1_a = (x * oldval_1) >> 8; + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x3FF, tx1_a); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(27), + ((x * oldval_1 >> 7) & 0x1)); + y = result[final_candidate][5]; + if ((y & 0x00000200) != 0) + y = y | 0xFFFFFC00; + tx1_c = (y * oldval_1) >> 8; + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000, + ((tx1_c & 0x3C0) >> 6)); + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000, + (tx1_c & 0x3F)); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(25), + ((y * oldval_1 >> 7) & 0x1)); + if (btxonly) + return; + reg = result[final_candidate][6]; + rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg); + reg = result[final_candidate][7] & 0x3F; + rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg); + reg = (result[final_candidate][7] >> 6) & 0xF; + rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg); + } +} + +static void _rtl92c_phy_save_adda_registers(struct ieee80211_hw *hw, + u32 *addareg, u32 *addabackup, + u32 registernum) +{ + u32 i; + + for (i = 0; i < registernum; i++) + addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD); +} + +static void _rtl92c_phy_save_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) + macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); + macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); +} + +static void _rtl92c_phy_reload_adda_registers(struct ieee80211_hw *hw, + u32 *addareg, u32 *addabackup, + u32 regiesternum) +{ + u32 i; + + for (i = 0; i < regiesternum; i++) + rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]); +} + +static void _rtl92c_phy_reload_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) + rtl_write_byte(rtlpriv, macreg[i], (u8)macbackup[i]); + rtl_write_dword(rtlpriv, macreg[i], macbackup[i]); +} + +static void _rtl92c_phy_path_adda_on(struct ieee80211_hw *hw, + u32 *addareg, bool is_patha_on, bool is2t) +{ + u32 pathOn; + u32 i; + + pathOn = is_patha_on ? 0x04db25a4 : 0x0b1b25a4; + if (false == is2t) { + pathOn = 0x0bdb25a0; + rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0); + } else { + rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathOn); + } + + for (i = 1; i < IQK_ADDA_REG_NUM; i++) + rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathOn); +} + +static void _rtl92c_phy_mac_setting_calibration(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i = 0; + + rtl_write_byte(rtlpriv, macreg[i], 0x3F); + + for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) + rtl_write_byte(rtlpriv, macreg[i], + (u8)(macbackup[i] & (~BIT(3)))); + rtl_write_byte(rtlpriv, macreg[i], (u8)(macbackup[i] & (~BIT(5)))); +} + +static void _rtl92c_phy_path_a_standby(struct ieee80211_hw *hw) +{ + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); +} + +static void _rtl92c_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode) +{ + u32 mode; + + mode = pi_mode ? 0x01000100 : 0x01000000; + rtl_set_bbreg(hw, 0x820, MASKDWORD, mode); + rtl_set_bbreg(hw, 0x828, MASKDWORD, mode); +} + +static bool _rtl92c_phy_simularity_compare(struct ieee80211_hw *hw, + long result[][8], u8 c1, u8 c2) +{ + u32 i, j, diff, simularity_bitmap, bound; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + u8 final_candidate[2] = { 0xFF, 0xFF }; + bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version); + + if (is2t) + bound = 8; + else + bound = 4; + + simularity_bitmap = 0; + + for (i = 0; i < bound; i++) { + diff = (result[c1][i] > result[c2][i]) ? + (result[c1][i] - result[c2][i]) : + (result[c2][i] - result[c1][i]); + + if (diff > MAX_TOLERANCE) { + if ((i == 2 || i == 6) && !simularity_bitmap) { + if (result[c1][i] + result[c1][i + 1] == 0) + final_candidate[(i / 4)] = c2; + else if (result[c2][i] + result[c2][i + 1] == 0) + final_candidate[(i / 4)] = c1; + else + simularity_bitmap = simularity_bitmap | + (1 << i); + } else + simularity_bitmap = + simularity_bitmap | (1 << i); + } + } + + if (simularity_bitmap == 0) { + for (i = 0; i < (bound / 4); i++) { + if (final_candidate[i] != 0xFF) { + for (j = i * 4; j < (i + 1) * 4 - 2; j++) + result[3][j] = + result[final_candidate[i]][j]; + bresult = false; + } + } + return bresult; + } else if (!(simularity_bitmap & 0x0F)) { + for (i = 0; i < 4; i++) + result[3][i] = result[c1][i]; + return false; + } else if (!(simularity_bitmap & 0xF0) && is2t) { + for (i = 4; i < 8; i++) + result[3][i] = result[c1][i]; + return false; + } else { + return false; + } +} + +static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, + long result[][8], u8 t, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 i; + u8 patha_ok, pathb_ok; + u32 adda_reg[IQK_ADDA_REG_NUM] = { + 0x85c, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec + }; + u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { + 0x522, 0x550, 0x551, 0x040 + }; + const u32 retrycount = 2; + u32 bbvalue; + + if (t == 0) { + bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD); + + _rtl92c_phy_save_adda_registers(hw, adda_reg, + rtlphy->adda_backup, 16); + _rtl92c_phy_save_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + } + _rtl92c_phy_path_adda_on(hw, adda_reg, true, is2t); + if (t == 0) { + rtlphy->rfpi_enable = + (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, + BIT(8)); + } + + if (!rtlphy->rfpi_enable) + _rtl92c_phy_pi_mode_switch(hw, true); + if (t == 0) { + rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD); + rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD); + rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD); + } + rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); + rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); + rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); + if (is2t) { + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); + rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); + } + _rtl92c_phy_mac_setting_calibration(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000); + if (is2t) + rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); + rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800); + for (i = 0; i < retrycount; i++) { + patha_ok = _rtl92c_phy_path_a_iqk(hw, is2t); + if (patha_ok == 0x03) { + result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & + 0x3FF0000) >> 16; + break; + } else if (i == (retrycount - 1) && patha_ok == 0x01) + + result[t][0] = (rtl_get_bbreg(hw, 0xe94, + MASKDWORD) & 0x3FF0000) >> + 16; + result[t][1] = + (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16; + + } + + if (is2t) { + _rtl92c_phy_path_a_standby(hw); + _rtl92c_phy_path_adda_on(hw, adda_reg, false, is2t); + for (i = 0; i < retrycount; i++) { + pathb_ok = _rtl92c_phy_path_b_iqk(hw); + if (pathb_ok == 0x03) { + result[t][4] = (rtl_get_bbreg(hw, + 0xeb4, + MASKDWORD) & + 0x3FF0000) >> 16; + result[t][5] = + (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][6] = + (rtl_get_bbreg(hw, 0xec4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][7] = + (rtl_get_bbreg(hw, 0xecc, MASKDWORD) & + 0x3FF0000) >> 16; + break; + } else if (i == (retrycount - 1) && pathb_ok == 0x01) { + result[t][4] = (rtl_get_bbreg(hw, + 0xeb4, + MASKDWORD) & + 0x3FF0000) >> 16; + } + result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & + 0x3FF0000) >> 16; + } + } + rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04); + rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874); + rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); + if (is2t) + rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); + if (t != 0) { + if (!rtlphy->rfpi_enable) + _rtl92c_phy_pi_mode_switch(hw, false); + _rtl92c_phy_reload_adda_registers(hw, adda_reg, + rtlphy->adda_backup, 16); + _rtl92c_phy_reload_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + } +} + +static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, + char delta, bool is2t) +{ +} + +static void _rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, + bool bmain, bool is2t) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (is_hal_stop(rtlhal)) { + rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01); + rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); + } + if (is2t) { + if (bmain) + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(6), 0x1); + else + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(6), 0x2); + } else { + if (bmain) + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2); + else + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1); + } +} + +#undef IQK_ADDA_REG_NUM +#undef IQK_DELAY_TIME + +void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + long result[4][8]; + u8 i, final_candidate; + bool b_patha_ok, b_pathb_ok; + long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, + reg_ecc, reg_tmp = 0; + bool is12simular, is13simular, is23simular; + u32 iqk_bb_reg[10] = { + ROFDM0_XARXIQIMBALANCE, + ROFDM0_XBRXIQIMBALANCE, + ROFDM0_ECCATHRESHOLD, + ROFDM0_AGCRSSITABLE, + ROFDM0_XATXIQIMBALANCE, + ROFDM0_XBTXIQIMBALANCE, + ROFDM0_XCTXIQIMBALANCE, + ROFDM0_XCTXAFE, + ROFDM0_XDTXAFE, + ROFDM0_RXIQEXTANTA + }; + + if (b_recovery) { + _rtl92c_phy_reload_adda_registers(hw, + iqk_bb_reg, + rtlphy->iqk_bb_backup, 10); + return; + } + for (i = 0; i < 8; i++) { + result[0][i] = 0; + result[1][i] = 0; + result[2][i] = 0; + result[3][i] = 0; + } + final_candidate = 0xff; + b_patha_ok = false; + b_pathb_ok = false; + is12simular = false; + is23simular = false; + is13simular = false; + for (i = 0; i < 3; i++) { + if (IS_92C_SERIAL(rtlhal->version)) + _rtl92c_phy_iq_calibrate(hw, result, i, true); + else + _rtl92c_phy_iq_calibrate(hw, result, i, false); + if (i == 1) { + is12simular = _rtl92c_phy_simularity_compare(hw, + result, 0, + 1); + if (is12simular) { + final_candidate = 0; + break; + } + } + if (i == 2) { + is13simular = _rtl92c_phy_simularity_compare(hw, + result, 0, + 2); + if (is13simular) { + final_candidate = 0; + break; + } + is23simular = _rtl92c_phy_simularity_compare(hw, + result, 1, + 2); + if (is23simular) + final_candidate = 1; + else { + for (i = 0; i < 8; i++) + reg_tmp += result[3][i]; + + if (reg_tmp != 0) + final_candidate = 3; + else + final_candidate = 0xFF; + } + } + } + for (i = 0; i < 4; i++) { + reg_e94 = result[i][0]; + reg_e9c = result[i][1]; + reg_ea4 = result[i][2]; + reg_eac = result[i][3]; + reg_eb4 = result[i][4]; + reg_ebc = result[i][5]; + reg_ec4 = result[i][6]; + reg_ecc = result[i][7]; + } + if (final_candidate != 0xff) { + rtlphy->reg_e94 = reg_e94 = result[final_candidate][0]; + rtlphy->reg_e9c = reg_e9c = result[final_candidate][1]; + reg_ea4 = result[final_candidate][2]; + reg_eac = result[final_candidate][3]; + rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4]; + rtlphy->reg_ebc = reg_ebc = result[final_candidate][5]; + reg_ec4 = result[final_candidate][6]; + reg_ecc = result[final_candidate][7]; + b_patha_ok = true; + b_pathb_ok = true; + } else { + rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; + rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0; + } + if (reg_e94 != 0) /*&&(reg_ea4 != 0) */ + _rtl92c_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result, + final_candidate, + (reg_ea4 == 0)); + if (IS_92C_SERIAL(rtlhal->version)) { + if (reg_eb4 != 0) /*&&(reg_ec4 != 0) */ + _rtl92c_phy_path_b_fill_iqk_matrix(hw, b_pathb_ok, + result, + final_candidate, + (reg_ec4 == 0)); + } + _rtl92c_phy_save_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, 10); +} +EXPORT_SYMBOL(rtl92c_phy_iq_calibrate); + +void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (IS_92C_SERIAL(rtlhal->version)) + rtlpriv->cfg->ops->phy_lc_calibrate(hw, true); + else + rtlpriv->cfg->ops->phy_lc_calibrate(hw, false); +} +EXPORT_SYMBOL(rtl92c_phy_lc_calibrate); + +void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlphy->apk_done) + return; + if (IS_92C_SERIAL(rtlhal->version)) + _rtl92c_phy_ap_calibrate(hw, delta, true); + else + _rtl92c_phy_ap_calibrate(hw, delta, false); +} +EXPORT_SYMBOL(rtl92c_phy_ap_calibrate); + +void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (IS_92C_SERIAL(rtlhal->version)) + _rtl92c_phy_set_rfpath_switch(hw, bmain, true); + else + _rtl92c_phy_set_rfpath_switch(hw, bmain, false); +} +EXPORT_SYMBOL(rtl92c_phy_set_rfpath_switch); + +bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + bool postprocessing = false; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "-->IO Cmd(%#x), set_io_inprogress(%d)\n", + iotype, rtlphy->set_io_inprogress); + do { + switch (iotype) { + case IO_CMD_RESUME_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Resume DM after scan.\n"); + postprocessing = true; + break; + case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Pause DM before scan.\n"); + postprocessing = true; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + } while (false); + if (postprocessing && !rtlphy->set_io_inprogress) { + rtlphy->set_io_inprogress = true; + rtlphy->current_io_type = iotype; + } else { + return false; + } + rtl92c_phy_set_io(hw); + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); + return true; +} +EXPORT_SYMBOL(rtl92c_phy_set_io_cmd); + +void rtl92c_phy_set_io(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "--->Cmd(%#x), set_io_inprogress(%d)\n", + rtlphy->current_io_type, rtlphy->set_io_inprogress); + switch (rtlphy->current_io_type) { + case IO_CMD_RESUME_DM_BY_SCAN: + dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; + rtl92c_dm_write_dig(hw); + rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + break; + case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: + rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; + dm_digtable->cur_igvalue = 0x17; + rtl92c_dm_write_dig(hw); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + rtlphy->set_io_inprogress = false; + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "(%#x)\n", rtlphy->current_io_type); +} +EXPORT_SYMBOL(rtl92c_phy_set_io); + +void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); +} +EXPORT_SYMBOL(rtl92ce_phy_set_rf_on); + +void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw) +{ + u32 u4b_tmp; + u8 delay = 5; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + while (u4b_tmp != 0 && delay > 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + delay--; + } + if (delay == 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "Switch RF timeout !!!.\n"); + return; + } + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); +} +EXPORT_SYMBOL(_rtl92c_phy_set_rf_sleep); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h new file mode 100644 index 000000000000..64bc49f4dbc6 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h @@ -0,0 +1,254 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_PHY_COMMON_H__ +#define __RTL92C_PHY_COMMON_H__ + +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define MAX_DOZE_WAITING_TIMES_9x 64 + +#define RT_CANNOT_IO(hw) false +#define HIGHPOWER_RADIOA_ARRAYLEN 22 + +#define MAX_TOLERANCE 5 + +#define APK_BB_REG_NUM 5 +#define APK_AFE_REG_NUM 16 +#define APK_CURVE_REG_NUM 4 +#define PATH_NUM 2 + +#define LOOP_LIMIT 5 +#define MAX_STALL_TIME 50 +#define AntennaDiversityValue 0x80 +#define MAX_TXPWR_IDX_NMODE_92S 63 +#define Reset_Cnt_Limit 3 + +#define IQK_ADDA_REG_NUM 16 +#define IQK_MAC_REG_NUM 4 + +#define IQK_DELAY_TIME 1 +#define RF90_PATH_MAX 2 + +#define CT_OFFSET_MAC_ADDR 0X16 + +#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A +#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 +#define CT_OFFSET_HT402S_TX_PWR_IDX_DIF 0x66 +#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 +#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C + +#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F +#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 + +#define CT_OFFSET_CHANNEL_PLAH 0x75 +#define CT_OFFSET_THERMAL_METER 0x78 +#define CT_OFFSET_RF_OPTION 0x79 +#define CT_OFFSET_VERSION 0x7E +#define CT_OFFSET_CUSTOMER_ID 0x7F + +#define RTL92C_MAX_PATH_NUM 2 +#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 + +enum swchnlcmd_id { + CMDID_END, + CMDID_SET_TXPOWEROWER_LEVEL, + CMDID_BBREGWRITE10, + CMDID_WRITEPORT_ULONG, + CMDID_WRITEPORT_USHORT, + CMDID_WRITEPORT_UCHAR, + CMDID_RF_WRITEREG, +}; + +struct swchnlcmd { + enum swchnlcmd_id cmdid; + u32 para1; + u32 para2; + u32 msdelay; +}; + +enum hw90_block_e { + HW90_BLOCK_MAC = 0, + HW90_BLOCK_PHY0 = 1, + HW90_BLOCK_PHY1 = 2, + HW90_BLOCK_RF = 3, + HW90_BLOCK_MAXIMUM = 4, +}; + +enum baseband_config_type { + BASEBAND_CONFIG_PHY_REG = 0, + BASEBAND_CONFIG_AGC_TAB = 1, +}; + +enum ra_offset_area { + RA_OFFSET_LEGACY_OFDM1, + RA_OFFSET_LEGACY_OFDM2, + RA_OFFSET_HT_OFDM1, + RA_OFFSET_HT_OFDM2, + RA_OFFSET_HT_OFDM3, + RA_OFFSET_HT_OFDM4, + RA_OFFSET_HT_CCK, +}; + +enum antenna_path { + ANTENNA_NONE, + ANTENNA_D, + ANTENNA_C, + ANTENNA_CD, + ANTENNA_B, + ANTENNA_BD, + ANTENNA_BC, + ANTENNA_BCD, + ANTENNA_A, + ANTENNA_AD, + ANTENNA_AC, + ANTENNA_ACD, + ANTENNA_AB, + ANTENNA_ABD, + ANTENNA_ABC, + ANTENNA_ABCD +}; + +struct r_antenna_select_ofdm { + u32 r_tx_antenna:4; + u32 r_ant_l:4; + u32 r_ant_non_ht:4; + u32 r_ant_ht1:4; + u32 r_ant_ht2:4; + u32 r_ant_ht_s1:4; + u32 r_ant_non_ht_s1:4; + u32 ofdm_txsc:2; + u32 reserved:2; +}; + +struct r_antenna_select_cck { + u8 r_cckrx_enable_2:2; + u8 r_cckrx_enable:2; + u8 r_ccktx_enable:4; +}; + +struct efuse_contents { + u8 mac_addr[ETH_ALEN]; + u8 cck_tx_power_idx[6]; + u8 ht40_1s_tx_power_idx[6]; + u8 ht40_2s_tx_power_idx_diff[3]; + u8 ht20_tx_power_idx_diff[3]; + u8 ofdm_tx_power_idx_diff[3]; + u8 ht40_max_power_offset[3]; + u8 ht20_max_power_offset[3]; + u8 channel_plan; + u8 thermal_meter; + u8 rf_option[5]; + u8 version; + u8 oem_id; + u8 regulatory; +}; + +struct tx_power_struct { + u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 legacy_ht_txpowerdiff; + u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 pwrgroup_cnt; + u32 mcs_original_offset[4][16]; +}; + +u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask); +void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, u32 data); +u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask); +bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); +bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); +bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); +bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, + long *powerlevel); +void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, + long power_indbm); +void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); +void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); +u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); +void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); +void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, + u16 beaconinterval); +void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); +void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); +void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); +bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, + u32 rfpath); +bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); +void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw); +void rtl92c_phy_set_io(struct ieee80211_hw *hw); +void rtl92c_bb_block_on(struct ieee80211_hw *hw); +u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask); +long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u8 txpwridx); +u8 _rtl92c_phy_dbm_to_txpwr_idx(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + long power_indbm); +void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); +void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); +bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay); +u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw); +u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); +void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, + u32 data); +bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/Makefile new file mode 100644 index 000000000000..c0cb0cfe7d37 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/Makefile @@ -0,0 +1,13 @@ +rtl8192ce-objs := \ + dm.o \ + hw.o \ + led.o \ + phy.o \ + rf.o \ + sw.o \ + table.o \ + trx.o + +obj-$(CONFIG_RTL8192CE) += rtl8192ce.o + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h new file mode 100644 index 000000000000..690a7a1675e2 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/def.h @@ -0,0 +1,197 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_DEF_H__ +#define __RTL92C_DEF_H__ + +#define PHY_RSSI_SLID_WIN_MAX 100 +#define PHY_LINKQUALITY_SLID_WIN_MAX 20 +#define PHY_BEACON_RSSI_SLID_WIN_MAX 10 + +#define RX_SMOOTH_FACTOR 20 + +#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 +#define HAL_PRIME_CHNL_OFFSET_LOWER 1 +#define HAL_PRIME_CHNL_OFFSET_UPPER 2 + +#define RX_MPDU_QUEUE 0 +#define RX_CMD_QUEUE 1 + +#define C2H_RX_CMD_HDR_LEN 8 +#define GET_C2H_CMD_CMD_LEN(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 0, 16) +#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 16, 8) +#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 24, 7) +#define GET_C2H_CMD_CONTINUE(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 31, 1) +#define GET_C2H_CMD_CONTENT(__prxhdr) \ + ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) + +#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) +#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) +#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) +#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32) + +#define CHIP_VER_B BIT(4) +#define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3) +#define CHIP_BONDING_92C_1T2R 0x1 +#define RF_TYPE_1T2R BIT(1) +#define CHIP_92C_BITMASK BIT(0) +#define CHIP_UNKNOWN BIT(7) +#define CHIP_92C_1T2R 0x03 +#define CHIP_92C 0x01 +#define CHIP_88C 0x00 + +enum version_8192c { + VERSION_A_CHIP_92C = 0x01, + VERSION_A_CHIP_88C = 0x00, + VERSION_B_CHIP_92C = 0x11, + VERSION_B_CHIP_88C = 0x10, + VERSION_TEST_CHIP_88C = 0x00, + VERSION_TEST_CHIP_92C = 0x01, + VERSION_NORMAL_TSMC_CHIP_88C = 0x10, + VERSION_NORMAL_TSMC_CHIP_92C = 0x11, + VERSION_NORMAL_TSMC_CHIP_92C_1T2R = 0x13, + VERSION_NORMAL_UMC_CHIP_88C_A_CUT = 0x30, + VERSION_NORMAL_UMC_CHIP_92C_A_CUT = 0x31, + VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT = 0x33, + VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT = 0x34, + VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT = 0x3c, + VERSION_NORMAL_UMC_CHIP_88C_B_CUT = 0x70, + VERSION_NORMAL_UMC_CHIP_92C_B_CUT = 0x71, + VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT = 0x73, + VERSION_UNKNOWN = 0x88, +}; + +enum rtl819x_loopback_e { + RTL819X_NO_LOOPBACK = 0, + RTL819X_MAC_LOOPBACK = 1, + RTL819X_DMA_LOOPBACK = 2, + RTL819X_CCK_LOOPBACK = 3, +}; + +enum rf_optype { + RF_OP_BY_SW_3WIRE = 0, + RF_OP_BY_FW, + RF_OP_MAX +}; + +enum rf_power_state { + RF_ON, + RF_OFF, + RF_SLEEP, + RF_SHUT_DOWN, +}; + +enum power_save_mode { + POWER_SAVE_MODE_ACTIVE, + POWER_SAVE_MODE_SAVE, +}; + +enum power_polocy_config { + POWERCFG_MAX_POWER_SAVINGS, + POWERCFG_GLOBAL_POWER_SAVINGS, + POWERCFG_LOCAL_POWER_SAVINGS, + POWERCFG_LENOVO, +}; + +enum interface_select_pci { + INTF_SEL1_MINICARD = 0, + INTF_SEL0_PCIE = 1, + INTF_SEL2_RSV = 2, + INTF_SEL3_RSV = 3, +}; + +enum hal_fw_c2h_cmd_id { + HAL_FW_C2H_CMD_Read_MACREG = 0, + HAL_FW_C2H_CMD_Read_BBREG = 1, + HAL_FW_C2H_CMD_Read_RFREG = 2, + HAL_FW_C2H_CMD_Read_EEPROM = 3, + HAL_FW_C2H_CMD_Read_EFUSE = 4, + HAL_FW_C2H_CMD_Read_CAM = 5, + HAL_FW_C2H_CMD_Get_BasicRate = 6, + HAL_FW_C2H_CMD_Get_DataRate = 7, + HAL_FW_C2H_CMD_Survey = 8, + HAL_FW_C2H_CMD_SurveyDone = 9, + HAL_FW_C2H_CMD_JoinBss = 10, + HAL_FW_C2H_CMD_AddSTA = 11, + HAL_FW_C2H_CMD_DelSTA = 12, + HAL_FW_C2H_CMD_AtimDone = 13, + HAL_FW_C2H_CMD_TX_Report = 14, + HAL_FW_C2H_CMD_CCX_Report = 15, + HAL_FW_C2H_CMD_DTM_Report = 16, + HAL_FW_C2H_CMD_TX_Rate_Statistics = 17, + HAL_FW_C2H_CMD_C2HLBK = 18, + HAL_FW_C2H_CMD_C2HDBG = 19, + HAL_FW_C2H_CMD_C2HFEEDBACK = 20, + HAL_FW_C2H_CMD_MAX +}; + +enum rtl_desc_qsel { + QSLT_BK = 0x2, + QSLT_BE = 0x0, + QSLT_VI = 0x5, + QSLT_VO = 0x7, + QSLT_BEACON = 0x10, + QSLT_HIGH = 0x11, + QSLT_MGNT = 0x12, + QSLT_CMD = 0x13, +}; + +struct phy_sts_cck_8192s_t { + u8 adc_pwdb_X[4]; + u8 sq_rpt; + u8 cck_agc_rpt; +}; + +struct h2c_cmd_8192c { + u8 element_id; + u32 cmd_len; + u8 *p_cmdbuffer; +}; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c new file mode 100644 index 000000000000..09898cf2e07a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.c @@ -0,0 +1,110 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../base.h" +#include "../pci.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "../rtl8192c/fw_common.h" + +void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undec_sm_pwdb; + + if (!rtlpriv->dm.dynamic_txpower_enable) + return; + + if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "Not connected to any\n"); + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Client PWDB = 0x%lx\n", + undec_sm_pwdb); + } else { + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "STA Default Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + } else { + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Ext Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + + if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); + } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && + (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) { + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); + } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_NORMAL\n"); + } + + if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "PHY_SetTxPowerLevel8192S() Channel = %d\n", + rtlphy->current_channel); + rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + } + + rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h new file mode 100644 index 000000000000..38ba707015f5 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/dm.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_DM_H__ +#define __RTL92C_DM_H__ + +#define HAL_DM_DIG_DISABLE BIT(0) +#define HAL_DM_HIPWR_DISABLE BIT(1) + +#define OFDM_TABLE_LENGTH 37 +#define CCK_TABLE_LENGTH 33 + +#define OFDM_TABLE_SIZE 37 +#define CCK_TABLE_SIZE 33 + +#define BW_AUTO_SWITCH_HIGH_LOW 25 +#define BW_AUTO_SWITCH_LOW_HIGH 30 + +#define DM_DIG_FA_UPPER 0x32 +#define DM_DIG_FA_LOWER 0x20 +#define DM_DIG_FA_TH0 0x20 +#define DM_DIG_FA_TH1 0x100 +#define DM_DIG_FA_TH2 0x200 + +#define RXPATHSELECTION_SS_TH_lOW 30 +#define RXPATHSELECTION_DIFF_TH 18 + +#define DM_RATR_STA_INIT 0 +#define DM_RATR_STA_HIGH 1 +#define DM_RATR_STA_MIDDLE 2 +#define DM_RATR_STA_LOW 3 + +#define CTS2SELF_THVAL 30 +#define REGC38_TH 20 + +#define WAIOTTHVal 25 + +#define TXHIGHPWRLEVEL_NORMAL 0 +#define TXHIGHPWRLEVEL_LEVEL1 1 +#define TXHIGHPWRLEVEL_LEVEL2 2 +#define TXHIGHPWRLEVEL_BT1 3 +#define TXHIGHPWRLEVEL_BT2 4 + +#define DM_TYPE_BYFW 0 +#define DM_TYPE_BYDRIVER 1 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 + +void rtl92c_dm_init(struct ieee80211_hw *hw); +void rtl92c_dm_watchdog(struct ieee80211_hw *hw); +void rtl92c_dm_write_dig(struct ieee80211_hw *hw); +void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw); +void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw); +void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); +void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); +void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); +void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c new file mode 100644 index 000000000000..04eb5c3f8464 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c @@ -0,0 +1,2426 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../regd.h" +#include "../cam.h" +#include "../ps.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "../rtl8192c/dm_common.h" +#include "../rtl8192c/fw_common.h" +#include "../rtl8192c/phy_common.h" +#include "dm.h" +#include "led.h" +#include "hw.h" + +#define LLT_CONFIG 5 + +static void _rtl92ce_set_bcn_ctrl_reg(struct ieee80211_hw *hw, + u8 set_bits, u8 clear_bits) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpci->reg_bcn_ctrl_val |= set_bits; + rtlpci->reg_bcn_ctrl_val &= ~clear_bits; + + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); +} + +static void _rtl92ce_stop_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl92ce_resume_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte |= BIT(0); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl92ce_enable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(1)); +} + +static void _rtl92ce_disable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl92ce_set_bcn_ctrl_reg(hw, BIT(1), 0); +} + +void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + switch (variable) { + case HW_VAR_RCR: + *((u32 *) (val)) = rtlpci->receive_config; + break; + case HW_VAR_RF_STATE: + *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; + break; + case HW_VAR_FWLPS_RF_ON:{ + enum rf_pwrstate rfState; + u32 val_rcr; + + rtlpriv->cfg->ops->get_hw_reg(hw, + HW_VAR_RF_STATE, + (u8 *) (&rfState)); + if (rfState == ERFOFF) { + *((bool *) (val)) = true; + } else { + val_rcr = rtl_read_dword(rtlpriv, REG_RCR); + val_rcr &= 0x00070000; + if (val_rcr) + *((bool *) (val)) = false; + else + *((bool *) (val)) = true; + } + break; + } + case HW_VAR_FW_PSMODE_STATUS: + *((bool *) (val)) = ppsc->fw_current_inpsmode; + break; + case HW_VAR_CORRECT_TSF:{ + u64 tsf; + u32 *ptsf_low = (u32 *)&tsf; + u32 *ptsf_high = ((u32 *)&tsf) + 1; + + *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); + *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + *((u64 *) (val)) = tsf; + + break; + } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } +} + +void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 idx; + + switch (variable) { + case HW_VAR_ETHER_ADDR:{ + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_MACID + idx), + val[idx]); + } + break; + } + case HW_VAR_BASIC_RATE:{ + u16 rate_cfg = ((u16 *) val)[0]; + u8 rate_index = 0; + rate_cfg &= 0x15f; + rate_cfg |= 0x01; + rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); + rtl_write_byte(rtlpriv, REG_RRSR + 1, + (rate_cfg >> 8) & 0xff); + while (rate_cfg > 0x1) { + rate_cfg = (rate_cfg >> 1); + rate_index++; + } + rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, + rate_index); + break; + } + case HW_VAR_BSSID:{ + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_BSSID + idx), + val[idx]); + } + break; + } + case HW_VAR_SIFS:{ + rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); + rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); + + rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); + rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); + + if (!mac->ht_enable) + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, + 0x0e0e); + else + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, + *((u16 *) val)); + break; + } + case HW_VAR_SLOT_TIME:{ + u8 e_aci; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "HW_VAR_SLOT_TIME %x\n", val[0]); + + rtl_write_byte(rtlpriv, REG_SLOT, val[0]); + + for (e_aci = 0; e_aci < AC_MAX; e_aci++) { + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AC_PARAM, + &e_aci); + } + break; + } + case HW_VAR_ACK_PREAMBLE:{ + u8 reg_tmp; + u8 short_preamble = (bool)*val; + reg_tmp = (mac->cur_40_prime_sc) << 5; + if (short_preamble) + reg_tmp |= 0x80; + + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp); + break; + } + case HW_VAR_AMPDU_MIN_SPACE:{ + u8 min_spacing_to_set; + u8 sec_min_space; + + min_spacing_to_set = *val; + if (min_spacing_to_set <= 7) { + sec_min_space = 0; + + if (min_spacing_to_set < sec_min_space) + min_spacing_to_set = sec_min_space; + + mac->min_space_cfg = ((mac->min_space_cfg & + 0xf8) | + min_spacing_to_set); + + *val = min_spacing_to_set; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", + mac->min_space_cfg); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + } + break; + } + case HW_VAR_SHORTGI_DENSITY:{ + u8 density_to_set; + + density_to_set = *val; + mac->min_space_cfg |= (density_to_set << 3); + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_SHORTGI_DENSITY: %#x\n", + mac->min_space_cfg); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + + break; + } + case HW_VAR_AMPDU_FACTOR:{ + u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9}; + u8 regtoset_bt[4] = {0x31, 0x74, 0x42, 0x97}; + + u8 factor_toset; + u8 *p_regtoset = NULL; + u8 index = 0; + + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == + BT_CSR_BC4)) + p_regtoset = regtoset_bt; + else + p_regtoset = regtoset_normal; + + factor_toset = *(val); + if (factor_toset <= 3) { + factor_toset = (1 << (factor_toset + 2)); + if (factor_toset > 0xf) + factor_toset = 0xf; + + for (index = 0; index < 4; index++) { + if ((p_regtoset[index] & 0xf0) > + (factor_toset << 4)) + p_regtoset[index] = + (p_regtoset[index] & 0x0f) | + (factor_toset << 4); + + if ((p_regtoset[index] & 0x0f) > + factor_toset) + p_regtoset[index] = + (p_regtoset[index] & 0xf0) | + (factor_toset); + + rtl_write_byte(rtlpriv, + (REG_AGGLEN_LMT + index), + p_regtoset[index]); + + } + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_FACTOR: %#x\n", + factor_toset); + } + break; + } + case HW_VAR_AC_PARAM:{ + u8 e_aci = *(val); + rtl92c_dm_init_edca_turbo(hw); + + if (rtlpci->acm_method != EACMWAY2_SW) + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_ACM_CTRL, + (&e_aci)); + break; + } + case HW_VAR_ACM_CTRL:{ + u8 e_aci = *(val); + union aci_aifsn *p_aci_aifsn = + (union aci_aifsn *)(&(mac->ac[0].aifs)); + u8 acm = p_aci_aifsn->f.acm; + u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); + + acm_ctrl = + acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); + + if (acm) { + switch (e_aci) { + case AC0_BE: + acm_ctrl |= AcmHw_BeqEn; + break; + case AC2_VI: + acm_ctrl |= AcmHw_ViqEn; + break; + case AC3_VO: + acm_ctrl |= AcmHw_VoqEn; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", + acm); + break; + } + } else { + switch (e_aci) { + case AC0_BE: + acm_ctrl &= (~AcmHw_BeqEn); + break; + case AC2_VI: + acm_ctrl &= (~AcmHw_ViqEn); + break; + case AC3_VO: + acm_ctrl &= (~AcmHw_VoqEn); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + } + + RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, + "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", + acm_ctrl); + rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); + break; + } + case HW_VAR_RCR:{ + rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]); + rtlpci->receive_config = ((u32 *) (val))[0]; + break; + } + case HW_VAR_RETRY_LIMIT:{ + u8 retry_limit = val[0]; + + rtl_write_word(rtlpriv, REG_RL, + retry_limit << RETRY_LIMIT_SHORT_SHIFT | + retry_limit << RETRY_LIMIT_LONG_SHIFT); + break; + } + case HW_VAR_DUAL_TSF_RST: + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); + break; + case HW_VAR_EFUSE_BYTES: + rtlefuse->efuse_usedbytes = *((u16 *) val); + break; + case HW_VAR_EFUSE_USAGE: + rtlefuse->efuse_usedpercentage = *val; + break; + case HW_VAR_IO_CMD: + rtl92c_phy_set_io_cmd(hw, (*(enum io_type *)val)); + break; + case HW_VAR_WPA_CONFIG: + rtl_write_byte(rtlpriv, REG_SECCFG, *val); + break; + case HW_VAR_SET_RPWM:{ + u8 rpwm_val; + + rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); + udelay(1); + + if (rpwm_val & BIT(7)) { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, *val); + } else { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, + *val | BIT(7)); + } + + break; + } + case HW_VAR_H2C_FW_PWRMODE:{ + u8 psmode = *val; + + if ((psmode != FW_PS_ACTIVE_MODE) && + (!IS_92C_SERIAL(rtlhal->version))) { + rtl92c_dm_rf_saving(hw, true); + } + + rtl92c_set_fw_pwrmode_cmd(hw, *val); + break; + } + case HW_VAR_FW_PSMODE_STATUS: + ppsc->fw_current_inpsmode = *((bool *) val); + break; + case HW_VAR_H2C_FW_JOINBSSRPT:{ + u8 mstatus = *val; + u8 tmp_regcr, tmp_reg422; + bool recover = false; + + if (mstatus == RT_MEDIA_CONNECT) { + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, + NULL); + + tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, + (tmp_regcr | BIT(0))); + + _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(3)); + _rtl92ce_set_bcn_ctrl_reg(hw, BIT(4), 0); + + tmp_reg422 = + rtl_read_byte(rtlpriv, + REG_FWHW_TXQ_CTRL + 2); + if (tmp_reg422 & BIT(6)) + recover = true; + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, + tmp_reg422 & (~BIT(6))); + + rtl92c_set_fw_rsvdpagepkt(hw, NULL); + + _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); + _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); + + if (recover) { + rtl_write_byte(rtlpriv, + REG_FWHW_TXQ_CTRL + 2, + tmp_reg422); + } + + rtl_write_byte(rtlpriv, REG_CR + 1, + (tmp_regcr & ~(BIT(0)))); + } + rtl92c_set_fw_joinbss_report_cmd(hw, *val); + + break; + } + case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: + rtl92c_set_p2p_ps_offload_cmd(hw, *val); + break; + case HW_VAR_AID:{ + u16 u2btmp; + u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); + u2btmp &= 0xC000; + rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | + mac->assoc_id)); + + break; + } + case HW_VAR_CORRECT_TSF:{ + u8 btype_ibss = val[0]; + + if (btype_ibss) + _rtl92ce_stop_tx_beacon(hw); + + _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(3)); + + rtl_write_dword(rtlpriv, REG_TSFTR, + (u32) (mac->tsf & 0xffffffff)); + rtl_write_dword(rtlpriv, REG_TSFTR + 4, + (u32) ((mac->tsf >> 32) & 0xffffffff)); + + _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); + + if (btype_ibss) + _rtl92ce_resume_tx_beacon(hw); + + break; + + } + case HW_VAR_FW_LPS_ACTION: { + bool enter_fwlps = *((bool *)val); + u8 rpwm_val, fw_pwrmode; + bool fw_current_inps; + + if (enter_fwlps) { + rpwm_val = 0x02; /* RF off */ + fw_current_inps = true; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_PWRMODE, + &ppsc->fwctrl_psmode); + + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_SET_RPWM, + &rpwm_val); + } else { + rpwm_val = 0x0C; /* RF on */ + fw_pwrmode = FW_PS_ACTIVE_MODE; + fw_current_inps = false; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_SET_RPWM, + &rpwm_val); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_PWRMODE, + &fw_pwrmode); + + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + } + break; } + case HW_VAR_KEEP_ALIVE: { + u8 array[2]; + + array[0] = 0xff; + array[1] = *((u8 *)val); + rtl92c_fill_h2c_cmd(hw, H2C_92C_KEEP_ALIVE_CTRL, 2, array); + break; } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case %d not processed\n", variable); + break; + } +} + +static bool _rtl92ce_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool status = true; + long count = 0; + u32 value = _LLT_INIT_ADDR(address) | + _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); + + rtl_write_dword(rtlpriv, REG_LLT_INIT, value); + + do { + value = rtl_read_dword(rtlpriv, REG_LLT_INIT); + if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) + break; + + if (count > POLLING_LLT_THRESHOLD) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to polling write LLT done at address %d!\n", + address); + status = false; + break; + } + } while (++count); + + return status; +} + +static bool _rtl92ce_llt_table_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + unsigned short i; + u8 txpktbuf_bndy; + u8 maxPage; + bool status; + +#if LLT_CONFIG == 1 + maxPage = 255; + txpktbuf_bndy = 252; +#elif LLT_CONFIG == 2 + maxPage = 127; + txpktbuf_bndy = 124; +#elif LLT_CONFIG == 3 + maxPage = 255; + txpktbuf_bndy = 174; +#elif LLT_CONFIG == 4 + maxPage = 255; + txpktbuf_bndy = 246; +#elif LLT_CONFIG == 5 + maxPage = 255; + txpktbuf_bndy = 246; +#endif + +#if LLT_CONFIG == 1 + rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x1c); + rtl_write_dword(rtlpriv, REG_RQPN, 0x80a71c1c); +#elif LLT_CONFIG == 2 + rtl_write_dword(rtlpriv, REG_RQPN, 0x845B1010); +#elif LLT_CONFIG == 3 + rtl_write_dword(rtlpriv, REG_RQPN, 0x84838484); +#elif LLT_CONFIG == 4 + rtl_write_dword(rtlpriv, REG_RQPN, 0x80bd1c1c); +#elif LLT_CONFIG == 5 + rtl_write_word(rtlpriv, REG_RQPN_NPQ, 0x0000); + + rtl_write_dword(rtlpriv, REG_RQPN, 0x80b01c29); +#endif + + rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x27FF0000 | txpktbuf_bndy)); + rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_PBP, 0x11); + rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); + + for (i = 0; i < (txpktbuf_bndy - 1); i++) { + status = _rtl92ce_llt_write(hw, i, i + 1); + if (true != status) + return status; + } + + status = _rtl92ce_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); + if (true != status) + return status; + + for (i = txpktbuf_bndy; i < maxPage; i++) { + status = _rtl92ce_llt_write(hw, i, (i + 1)); + if (true != status) + return status; + } + + status = _rtl92ce_llt_write(hw, maxPage, txpktbuf_bndy); + if (true != status) + return status; + + return true; +} + +static void _rtl92ce_gen_refresh_led_state(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + + if (rtlpci->up_first_time) + return; + + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) + rtl92ce_sw_led_on(hw, pLed0); + else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) + rtl92ce_sw_led_on(hw, pLed0); + else + rtl92ce_sw_led_off(hw, pLed0); +} + +static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + unsigned char bytetmp; + unsigned short wordtmp; + u16 retry; + + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); + if (rtlpcipriv->bt_coexist.bt_coexistence) { + u32 value32; + value32 = rtl_read_dword(rtlpriv, REG_APS_FSMCO); + value32 |= (SOP_ABG | SOP_AMB | XOP_BTCK); + rtl_write_dword(rtlpriv, REG_APS_FSMCO, value32); + } + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F); + + if (rtlpcipriv->bt_coexist.bt_coexistence) { + u32 u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); + + u4b_tmp &= (~0x00024800); + rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp); + } + + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0); + udelay(2); + + rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); + udelay(2); + + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); + udelay(2); + + retry = 0; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "reg0xec:%x:%x\n", + rtl_read_dword(rtlpriv, 0xEC), bytetmp); + + while ((bytetmp & BIT(0)) && retry < 1000) { + retry++; + udelay(50); + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "reg0xec:%x:%x\n", + rtl_read_dword(rtlpriv, 0xEC), bytetmp); + udelay(50); + } + + rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x1012); + + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82); + udelay(2); + + if (rtlpcipriv->bt_coexist.bt_coexistence) { + bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2) & 0xfd; + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, bytetmp); + } + + rtl_write_word(rtlpriv, REG_CR, 0x2ff); + + if (!_rtl92ce_llt_table_init(hw)) + return false; + + rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); + rtl_write_byte(rtlpriv, REG_HISRE, 0xff); + + rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x27ff); + + wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); + wordtmp &= 0xf; + wordtmp |= 0xF771; + rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); + + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); + + rtl_write_byte(rtlpriv, 0x4d0, 0x0); + + rtl_write_dword(rtlpriv, REG_BCNQ_DESA, + ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_MGQ_DESA, + (u64) rtlpci->tx_ring[MGNT_QUEUE].dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VOQ_DESA, + (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VIQ_DESA, + (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BEQ_DESA, + (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BKQ_DESA, + (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_HQ_DESA, + (u64) rtlpci->tx_ring[HIGH_QUEUE].dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_RX_DESA, + (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma & + DMA_BIT_MASK(32)); + + if (IS_92C_SERIAL(rtlhal->version)) + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x77); + else + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x22); + + rtl_write_dword(rtlpriv, REG_INT_MIG, 0); + + bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6)); + do { + retry++; + bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); + } while ((retry < 200) && (bytetmp & BIT(7))); + + _rtl92ce_gen_refresh_led_state(hw); + + rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); + + return true; +} + +static void _rtl92ce_hw_configure(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + u8 reg_bw_opmode; + u32 reg_prsr; + + reg_bw_opmode = BW_OPMODE_20MHZ; + reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + + rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8); + + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + + rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr); + + rtl_write_byte(rtlpriv, REG_SLOT, 0x09); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0); + + rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80); + + rtl_write_word(rtlpriv, REG_RL, 0x0707); + + rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802); + + rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); + + rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); + rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); + + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x97427431); + else + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); + + rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); + + rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff); + + rtlpci->reg_bcn_ctrl_val = 0x1f; + rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); + + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + + rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); + rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); + + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) { + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0402); + } else { + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + } + + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); + else + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); + + rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); + + rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010); + rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010); + + rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010); + + rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010); + + rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff); + rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff); + +} + +static void _rtl92ce_enable_aspm_back_door(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + rtl_write_byte(rtlpriv, 0x34b, 0x93); + rtl_write_word(rtlpriv, 0x350, 0x870c); + rtl_write_byte(rtlpriv, 0x352, 0x1); + + if (ppsc->support_backdoor) + rtl_write_byte(rtlpriv, 0x349, 0x1b); + else + rtl_write_byte(rtlpriv, 0x349, 0x03); + + rtl_write_word(rtlpriv, 0x350, 0x2718); + rtl_write_byte(rtlpriv, 0x352, 0x1); +} + +void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 sec_reg_value; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", + rtlpriv->sec.pairwise_enc_algorithm, + rtlpriv->sec.group_enc_algorithm); + + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "not open hw encryption\n"); + return; + } + + sec_reg_value = SCR_TxEncEnable | SCR_RxDecEnable; + + if (rtlpriv->sec.use_defaultkey) { + sec_reg_value |= SCR_TxUseDK; + sec_reg_value |= SCR_RxUseDK; + } + + sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); + + rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "The SECR-value %x\n", sec_reg_value); + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); + +} + +int rtl92ce_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool rtstatus = true; + bool is92c; + int err; + u8 tmp_u1b; + unsigned long flags; + + rtlpci->being_init_adapter = true; + + /* Since this function can take a very long time (up to 350 ms) + * and can be called with irqs disabled, reenable the irqs + * to let the other devices continue being serviced. + * + * It is safe doing so since our own interrupts will only be enabled + * in a subsequent step. + */ + local_save_flags(flags); + local_irq_enable(); + + rtlhal->fw_ready = false; + rtlpriv->intf_ops->disable_aspm(hw); + rtstatus = _rtl92ce_init_mac(hw); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); + err = 1; + goto exit; + } + + err = rtl92c_download_fw(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW now..\n"); + err = 1; + goto exit; + } + + rtlhal->fw_ready = true; + rtlhal->last_hmeboxnum = 0; + rtl92c_phy_mac_config(hw); + /* because last function modify RCR, so we update + * rcr var here, or TP will unstable for receive_config + * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx + * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/ + rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); + rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + rtl92c_phy_bb_config(hw); + rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; + rtl92c_phy_rf_config(hw); + if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && + !IS_92C_SERIAL(rtlhal->version)) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00); + } else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) { + rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE); + rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31); + rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425); + rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201); + } + rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); + _rtl92ce_hw_configure(hw); + rtl_cam_reset_all_entry(hw); + rtl92ce_enable_hw_security_config(hw); + + ppsc->rfpwr_state = ERFON; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); + _rtl92ce_enable_aspm_back_door(hw); + rtlpriv->intf_ops->enable_aspm(hw); + + rtl8192ce_bt_hw_init(hw); + + if (ppsc->rfpwr_state == ERFON) { + rtl92c_phy_set_rfpath_switch(hw, 1); + if (rtlphy->iqk_initialized) { + rtl92c_phy_iq_calibrate(hw, true); + } else { + rtl92c_phy_iq_calibrate(hw, false); + rtlphy->iqk_initialized = true; + } + + rtl92c_dm_check_txpower_tracking(hw); + rtl92c_phy_lc_calibrate(hw); + } + + is92c = IS_92C_SERIAL(rtlhal->version); + tmp_u1b = efuse_read_1byte(hw, 0x1FA); + if (!(tmp_u1b & BIT(0))) { + rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "PA BIAS path A\n"); + } + + if (!(tmp_u1b & BIT(1)) && is92c) { + rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0F, 0x05); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "PA BIAS path B\n"); + } + + if (!(tmp_u1b & BIT(4))) { + tmp_u1b = rtl_read_byte(rtlpriv, 0x16); + tmp_u1b &= 0x0F; + rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80); + udelay(10); + rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n"); + } + rtl92c_dm_init(hw); +exit: + local_irq_restore(flags); + rtlpci->being_init_adapter = false; + return err; +} + +static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + enum version_8192c version = VERSION_UNKNOWN; + u32 value32; + const char *versionid; + + value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); + if (value32 & TRP_VAUX_EN) { + version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C : + VERSION_A_CHIP_88C; + } else { + version = (enum version_8192c) (CHIP_VER_B | + ((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0) | + ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); + if ((!IS_CHIP_VENDOR_UMC(version)) && (value32 & + CHIP_VER_RTL_MASK)) { + version = (enum version_8192c)(version | + ((((value32 & CHIP_VER_RTL_MASK) == BIT(12)) + ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) | + CHIP_VENDOR_UMC)); + } + if (IS_92C_SERIAL(version)) { + value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM); + version = (enum version_8192c)(version | + ((CHIP_BONDING_IDENTIFIER(value32) + == CHIP_BONDING_92C_1T2R) ? + RF_TYPE_1T2R : 0)); + } + } + + switch (version) { + case VERSION_B_CHIP_92C: + versionid = "B_CHIP_92C"; + break; + case VERSION_B_CHIP_88C: + versionid = "B_CHIP_88C"; + break; + case VERSION_A_CHIP_92C: + versionid = "A_CHIP_92C"; + break; + case VERSION_A_CHIP_88C: + versionid = "A_CHIP_88C"; + break; + case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT: + versionid = "A_CUT_92C_1T2R"; + break; + case VERSION_NORMAL_UMC_CHIP_92C_A_CUT: + versionid = "A_CUT_92C"; + break; + case VERSION_NORMAL_UMC_CHIP_88C_A_CUT: + versionid = "A_CUT_88C"; + break; + case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT: + versionid = "B_CUT_92C_1T2R"; + break; + case VERSION_NORMAL_UMC_CHIP_92C_B_CUT: + versionid = "B_CUT_92C"; + break; + case VERSION_NORMAL_UMC_CHIP_88C_B_CUT: + versionid = "B_CUT_88C"; + break; + default: + versionid = "Unknown. Bug?"; + break; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + "Chip Version ID: %s\n", versionid); + + switch (version & 0x3) { + case CHIP_88C: + rtlphy->rf_type = RF_1T1R; + break; + case CHIP_92C: + rtlphy->rf_type = RF_2T2R; + break; + case CHIP_92C_1T2R: + rtlphy->rf_type = RF_1T2R; + break; + default: + rtlphy->rf_type = RF_1T1R; + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "ERROR RF_Type is set!!\n"); + break; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Chip RF Type: %s\n", + rtlphy->rf_type == RF_2T2R ? "RF_2T2R" : "RF_1T1R"); + + return version; +} + +static int _rtl92ce_set_media_status(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_msr = rtl_read_byte(rtlpriv, MSR); + enum led_ctl_mode ledaction = LED_CTL_NO_LINK; + u8 mode = MSR_NOLINK; + + bt_msr &= 0xfc; + + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + mode = MSR_NOLINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to NO LINK!\n"); + break; + case NL80211_IFTYPE_ADHOC: + mode = MSR_ADHOC; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to Ad Hoc!\n"); + break; + case NL80211_IFTYPE_STATION: + mode = MSR_INFRA; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to STA!\n"); + break; + case NL80211_IFTYPE_AP: + mode = MSR_AP; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to AP!\n"); + break; + case NL80211_IFTYPE_MESH_POINT: + mode = MSR_ADHOC; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to Mesh Point!\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Network type %d not supported!\n", type); + return 1; + + } + + /* MSR_INFRA == Link in infrastructure network; + * MSR_ADHOC == Link in ad hoc network; + * Therefore, check link state is necessary. + * + * MSR_AP == AP mode; link state does not matter here. + */ + if (mode != MSR_AP && + rtlpriv->mac80211.link_state < MAC80211_LINKED) { + mode = MSR_NOLINK; + ledaction = LED_CTL_NO_LINK; + } + if (mode == MSR_NOLINK || mode == MSR_INFRA) { + _rtl92ce_stop_tx_beacon(hw); + _rtl92ce_enable_bcn_sub_func(hw); + } else if (mode == MSR_ADHOC || mode == MSR_AP) { + _rtl92ce_resume_tx_beacon(hw); + _rtl92ce_disable_bcn_sub_func(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", + mode); + } + rtl_write_byte(rtlpriv, MSR, bt_msr | mode); + + rtlpriv->cfg->ops->led_control(hw, ledaction); + if (mode == MSR_AP) + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); + else + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); + return 0; +} + +void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 reg_rcr; + + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); + + if (check_bssid) { + reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, + (u8 *) (®_rcr)); + _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); + } else if (!check_bssid) { + reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); + _rtl92ce_set_bcn_ctrl_reg(hw, BIT(4), 0); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_RCR, (u8 *) (®_rcr)); + } + +} + +int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (_rtl92ce_set_media_status(hw, type)) + return -EOPNOTSUPP; + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP && + type != NL80211_IFTYPE_MESH_POINT) + rtl92ce_set_check_bssid(hw, true); + } else { + rtl92ce_set_check_bssid(hw, false); + } + + return 0; +} + +/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ +void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtl92c_dm_init_edca_turbo(hw); + switch (aci) { + case AC1_BK: + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); + break; + case AC0_BE: + /* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); */ + break; + case AC2_VI: + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); + break; + case AC3_VO: + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); + break; + default: + RT_ASSERT(false, "invalid aci: %d !\n", aci); + break; + } +} + +void rtl92ce_enable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); + rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); + rtlpci->irq_enabled = true; +} + +void rtl92ce_disable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED); + rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); + rtlpci->irq_enabled = false; +} + +static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 u1b_tmp; + u32 u4b_tmp; + + rtlpriv->intf_ops->enable_aspm(hw); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0); + if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) + rtl92c_firmware_selfreset(hw); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51); + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000); + u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL); + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + ((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) || + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8))) { + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00F30000 | + (u1b_tmp << 8)); + } else { + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00FF0000 | + (u1b_tmp << 8)); + } + rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); + rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); + if (!IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); + if (rtlpcipriv->bt_coexist.bt_coexistence) { + u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); + u4b_tmp |= 0x03824800; + rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp); + } else { + rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); + } + + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); + rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10); +} + +void rtl92ce_card_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + enum nl80211_iftype opmode; + + mac->link_state = MAC80211_NOLINK; + opmode = NL80211_IFTYPE_UNSPECIFIED; + _rtl92ce_set_media_status(hw, opmode); + if (rtlpci->driver_is_goingto_unload || + ppsc->rfoff_reason > RF_CHANGE_BY_PS) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + _rtl92ce_poweroff_adapter(hw); + + /* after power off we should do iqk again */ + rtlpriv->phy.iqk_initialized = false; +} + +void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; + rtl_write_dword(rtlpriv, ISR, *p_inta); + + /* + * *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; + * rtl_write_dword(rtlpriv, ISR + 4, *p_intb); + */ +} + +void rtl92ce_set_beacon_related_registers(struct ieee80211_hw *hw) +{ + + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval, atim_window; + + bcn_interval = mac->beacon_interval; + atim_window = 2; /*FIX MERGE */ + rtl92ce_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); + rtl_write_byte(rtlpriv, 0x606, 0x30); + rtl92ce_enable_interrupt(hw); +} + +void rtl92ce_set_beacon_interval(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval = mac->beacon_interval; + + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "beacon_interval:%d\n", bcn_interval); + rtl92ce_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl92ce_enable_interrupt(hw); +} + +void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, "add_msr:%x, rm_msr:%x\n", + add_msr, rm_msr); + + if (add_msr) + rtlpci->irq_mask[0] |= add_msr; + if (rm_msr) + rtlpci->irq_mask[0] &= (~rm_msr); + rtl92ce_disable_interrupt(hw); + rtl92ce_enable_interrupt(hw); +} + +static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, + u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 rf_path, index, tempval; + u16 i; + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 3; i++) { + if (!autoload_fail) { + rtlefuse-> + eeprom_chnlarea_txpwr_cck[rf_path][i] = + hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i]; + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = + hwinfo[EEPROM_TXPOWERHT40_1S + rf_path * 3 + + i]; + } else { + rtlefuse-> + eeprom_chnlarea_txpwr_cck[rf_path][i] = + EEPROM_DEFAULT_TXPOWERLEVEL; + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = + EEPROM_DEFAULT_TXPOWERLEVEL; + } + } + } + + for (i = 0; i < 3; i++) { + if (!autoload_fail) + tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i]; + else + tempval = EEPROM_DEFAULT_HT40_2SDIFF; + rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] = + (tempval & 0xf); + rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] = + ((tempval & 0xf0) >> 4); + } + + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + "RF(%d) EEPROM CCK Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse-> + eeprom_chnlarea_txpwr_cck[rf_path][i]); + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + "RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][i]); + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse-> + eprom_chnl_txpwr_ht40_2sdf[rf_path][i]); + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 14; i++) { + index = rtl92c_get_chnl_group((u8)i); + + rtlefuse->txpwrlevel_cck[rf_path][i] = + rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][index]; + rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][index]; + + if ((rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] - + rtlefuse-> + eprom_chnl_txpwr_ht40_2sdf[rf_path][index]) + > 0) { + rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path] + [index] - + rtlefuse-> + eprom_chnl_txpwr_ht40_2sdf[rf_path] + [index]; + } else { + rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0; + } + } + + for (i = 0; i < 14; i++) { + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", + rf_path, i, + rtlefuse->txpwrlevel_cck[rf_path][i], + rtlefuse->txpwrlevel_ht40_1s[rf_path][i], + rtlefuse->txpwrlevel_ht40_2s[rf_path][i]); + } + } + + for (i = 0; i < 3; i++) { + if (!autoload_fail) { + rtlefuse->eeprom_pwrlimit_ht40[i] = + hwinfo[EEPROM_TXPWR_GROUP + i]; + rtlefuse->eeprom_pwrlimit_ht20[i] = + hwinfo[EEPROM_TXPWR_GROUP + 3 + i]; + } else { + rtlefuse->eeprom_pwrlimit_ht40[i] = 0; + rtlefuse->eeprom_pwrlimit_ht20[i] = 0; + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 14; i++) { + index = rtl92c_get_chnl_group((u8)i); + + if (rf_path == RF90_PATH_A) { + rtlefuse->pwrgroup_ht20[rf_path][i] = + (rtlefuse->eeprom_pwrlimit_ht20[index] + & 0xf); + rtlefuse->pwrgroup_ht40[rf_path][i] = + (rtlefuse->eeprom_pwrlimit_ht40[index] + & 0xf); + } else if (rf_path == RF90_PATH_B) { + rtlefuse->pwrgroup_ht20[rf_path][i] = + ((rtlefuse->eeprom_pwrlimit_ht20[index] + & 0xf0) >> 4); + rtlefuse->pwrgroup_ht40[rf_path][i] = + ((rtlefuse->eeprom_pwrlimit_ht40[index] + & 0xf0) >> 4); + } + + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-%d pwrgroup_ht20[%d] = 0x%x\n", + rf_path, i, + rtlefuse->pwrgroup_ht20[rf_path][i]); + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-%d pwrgroup_ht40[%d] = 0x%x\n", + rf_path, i, + rtlefuse->pwrgroup_ht40[rf_path][i]); + } + } + + for (i = 0; i < 14; i++) { + index = rtl92c_get_chnl_group((u8)i); + + if (!autoload_fail) + tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index]; + else + tempval = EEPROM_DEFAULT_HT20_DIFF; + + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = + ((tempval >> 4) & 0xF); + + if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] & BIT(3)) + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] |= 0xF0; + + if (rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] & BIT(3)) + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] |= 0xF0; + + index = rtl92c_get_chnl_group((u8)i); + + if (!autoload_fail) + tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index]; + else + tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; + + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = (tempval & 0xF); + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = + ((tempval >> 4) & 0xF); + } + + rtlefuse->legacy_ht_txpowerdiff = + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; + + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", + i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", + i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", + i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", + i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); + + if (!autoload_fail) + rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); + else + rtlefuse->eeprom_regulatory = 0; + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); + + if (!autoload_fail) { + rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; + rtlefuse->eeprom_tssi[RF90_PATH_B] = hwinfo[EEPROM_TSSI_B]; + } else { + rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; + rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; + } + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, "TSSI_A = 0x%x, TSSI_B = 0x%x\n", + rtlefuse->eeprom_tssi[RF90_PATH_A], + rtlefuse->eeprom_tssi[RF90_PATH_B]); + + if (!autoload_fail) + tempval = hwinfo[EEPROM_THERMAL_METER]; + else + tempval = EEPROM_DEFAULT_THERMALMETER; + rtlefuse->eeprom_thermalmeter = (tempval & 0x1f); + + if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail) + rtlefuse->apk_thermalmeterignore = true; + + rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); +} + +static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u16 i, usvalue; + u8 hwinfo[HWSET_MAX_SIZE]; + u16 eeprom_id; + + if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + rtl_efuse_shadow_map_update(hw); + + memcpy((void *)hwinfo, + (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + HWSET_MAX_SIZE); + } else if (rtlefuse->epromtype == EEPROM_93C46) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "RTL819X Not boot from eeprom, check it !!"); + } + + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP", + hwinfo, HWSET_MAX_SIZE); + + eeprom_id = *((u16 *)&hwinfo[0]); + if (eeprom_id != RTL8190_EEPROM_ID) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "EEPROM ID(%#x) is invalid!!\n", eeprom_id); + rtlefuse->autoload_failflag = true; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + } + + if (rtlefuse->autoload_failflag) + return; + + rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; + rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; + rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; + rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROMId = 0x%4x\n", eeprom_id); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); + + for (i = 0; i < 6; i += 2) { + usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; + *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%pM\n", rtlefuse->dev_addr); + + _rtl92ce_read_txpower_info_from_hwpg(hw, + rtlefuse->autoload_failflag, + hwinfo); + + rtl8192ce_read_bt_coexist_info_from_hwpg(hw, + rtlefuse->autoload_failflag, + hwinfo); + + rtlefuse->eeprom_channelplan = *&hwinfo[EEPROM_CHANNELPLAN]; + rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; + rtlefuse->txpwr_fromeprom = true; + rtlefuse->eeprom_oemid = *&hwinfo[EEPROM_CUSTOMER_ID]; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); + + /* set channel paln to world wide 13 */ + rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; + + if (rtlhal->oem_id == RT_CID_DEFAULT) { + switch (rtlefuse->eeprom_oemid) { + case EEPROM_CID_DEFAULT: + if (rtlefuse->eeprom_did == 0x8176) { + if ((rtlefuse->eeprom_svid == 0x103C && + rtlefuse->eeprom_smid == 0x1629)) + rtlhal->oem_id = RT_CID_819X_HP; + else + rtlhal->oem_id = RT_CID_DEFAULT; + } else { + rtlhal->oem_id = RT_CID_DEFAULT; + } + break; + case EEPROM_CID_TOSHIBA: + rtlhal->oem_id = RT_CID_TOSHIBA; + break; + case EEPROM_CID_QMI: + rtlhal->oem_id = RT_CID_819X_QMI; + break; + case EEPROM_CID_WHQL: + default: + rtlhal->oem_id = RT_CID_DEFAULT; + break; + + } + } + +} + +static void _rtl92ce_hal_customized_behavior(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + switch (rtlhal->oem_id) { + case RT_CID_819X_HP: + pcipriv->ledctl.led_opendrain = true; + break; + case RT_CID_819X_LENOVO: + case RT_CID_DEFAULT: + case RT_CID_TOSHIBA: + case RT_CID_CCX: + case RT_CID_819X_ACER: + case RT_CID_WHQL: + default: + break; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "RT Customized ID: 0x%02X\n", rtlhal->oem_id); +} + +void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_u1b; + + rtlhal->version = _rtl92ce_read_chip_version(hw); + if (get_rf_type(rtlphy) == RF_1T1R) + rtlpriv->dm.rfpath_rxenable[0] = true; + else + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", + rtlhal->version); + tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); + if (tmp_u1b & BIT(4)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); + rtlefuse->epromtype = EEPROM_93C46; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); + rtlefuse->epromtype = EEPROM_BOOT_EFUSE; + } + if (tmp_u1b & BIT(5)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + _rtl92ce_read_adapter_info(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); + } + _rtl92ce_hal_customized_behavior(hw); +} + +static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 ratr_value; + u8 ratr_index = 0; + u8 nmode = mac->ht_enable; + u16 shortgi_rate; + u32 tmp_ratr_value; + u8 curtxbw_40mhz = mac->bw_40; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = mac->mode; + u32 ratr_mask; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_value = sta->supp_rates[1] << 4; + else + ratr_value = sta->supp_rates[0]; + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_value = 0xfff; + + ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + if (ratr_value & 0x0000000c) + ratr_value &= 0x0000000d; + else + ratr_value &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_value &= 0x00000FF5; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + nmode = 1; + if (get_rf_type(rtlphy) == RF_1T2R || + get_rf_type(rtlphy) == RF_1T1R) + ratr_mask = 0x000ff005; + else + ratr_mask = 0x0f0ff005; + + ratr_value &= ratr_mask; + break; + default: + if (rtlphy->rf_type == RF_1T2R) + ratr_value &= 0x000ff0ff; + else + ratr_value &= 0x0f0ff0ff; + + break; + } + + if ((rtlpcipriv->bt_coexist.bt_coexistence) && + (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) && + (rtlpcipriv->bt_coexist.bt_cur_state) && + (rtlpcipriv->bt_coexist.bt_ant_isolation) && + ((rtlpcipriv->bt_coexist.bt_service == BT_SCO) || + (rtlpcipriv->bt_coexist.bt_service == BT_BUSY))) + ratr_value &= 0x0fffcfc0; + else + ratr_value &= 0x0FFFFFFF; + + if (nmode && ((curtxbw_40mhz && + curshortgi_40mhz) || (!curtxbw_40mhz && + curshortgi_20mhz))) { + + ratr_value |= 0x10000000; + tmp_ratr_value = (ratr_value >> 12); + + for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { + if ((1 << shortgi_rate) & tmp_ratr_value) + break; + } + + shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | + (shortgi_rate << 4) | (shortgi_rate); + } + + rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n", + rtl_read_dword(rtlpriv, REG_ARFR0)); +} + +static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u32 ratr_bitmap; + u8 ratr_index; + u8 curtxbw_40mhz = (sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0; + u8 curshortgi_40mhz = (sta->ht_cap.cap & + IEEE80211_HT_CAP_SGI_40) ? 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = 0; + bool shortgi = false; + u8 rate_mask[5]; + u8 macid = 0; + + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + wirelessmode = sta_entry->wireless_mode; + if (mac->opmode == NL80211_IFTYPE_STATION || + mac->opmode == NL80211_IFTYPE_MESH_POINT) + curtxbw_40mhz = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + macid = sta->aid + 1; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_bitmap = sta->supp_rates[1] << 4; + else + ratr_bitmap = sta->supp_rates[0]; + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_bitmap = 0xfff; + ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + ratr_index = RATR_INX_WIRELESS_B; + if (ratr_bitmap & 0x0000000c) + ratr_bitmap &= 0x0000000d; + else + ratr_bitmap &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_index = RATR_INX_WIRELESS_GB; + + if (rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if (rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + break; + case WIRELESS_MODE_A: + ratr_index = RATR_INX_WIRELESS_A; + ratr_bitmap &= 0x00000ff0; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rtlphy->rf_type == RF_1T2R || + rtlphy->rf_type == RF_1T1R) { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff005; + } + } else { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x0f0f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f0ff000; + else + ratr_bitmap &= 0x0f0ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x0f0f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f0ff000; + else + ratr_bitmap &= 0x0f0ff005; + } + } + + if ((curtxbw_40mhz && curshortgi_40mhz) || + (!curtxbw_40mhz && curshortgi_20mhz)) { + + if (macid == 0) + shortgi = true; + else if (macid == 1) + shortgi = false; + } + break; + default: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rtlphy->rf_type == RF_1T2R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0f0ff0ff; + break; + } + sta_entry->ratr_index = ratr_index; + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "ratr_bitmap :%x\n", ratr_bitmap); + *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | + (ratr_index << 28); + rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "Rate_index:%x, ratr_val:%x, %5phC\n", + ratr_index, ratr_bitmap, rate_mask); + rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); +} + +void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->dm.useramask) + rtl92ce_update_hal_rate_mask(hw, sta, rssi_level); + else + rtl92ce_update_hal_rate_table(hw, sta); +} + +void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 sifs_timer; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, + &mac->slot_time); + if (!mac->ht_enable) + sifs_timer = 0x0a0a; + else + sifs_timer = 0x1010; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); +} + +bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + enum rf_pwrstate e_rfpowerstate_toset; + u8 u1tmp; + bool actuallyset = false; + unsigned long flag; + + if (rtlpci->being_init_adapter) + return false; + + if (ppsc->swrf_processing) + return false; + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + if (ppsc->rfchange_inprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + return false; + } else { + ppsc->rfchange_inprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + + rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv, + REG_MAC_PINMUX_CFG)&~(BIT(3))); + + u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); + e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF; + + if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "GPIOChangeRF - HW Radio ON, RF ON\n"); + + e_rfpowerstate_toset = ERFON; + ppsc->hwradiooff = false; + actuallyset = true; + } else if (!ppsc->hwradiooff && (e_rfpowerstate_toset == ERFOFF)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "GPIOChangeRF - HW Radio OFF, RF OFF\n"); + + e_rfpowerstate_toset = ERFOFF; + ppsc->hwradiooff = true; + actuallyset = true; + } + + if (actuallyset) { + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } else { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + + *valid = 1; + return !ppsc->hwradiooff; + +} + +void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 *macaddr = p_macaddr; + u32 entry_id = 0; + bool is_pairwise = false; + + static u8 cam_const_addr[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} + }; + static u8 cam_const_broad[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (clear_all) { + u8 idx = 0; + u8 cam_offset = 0; + u8 clear_number = 5; + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); + + for (idx = 0; idx < clear_number; idx++) { + rtl_cam_mark_invalid(hw, cam_offset + idx); + rtl_cam_empty_entry(hw, cam_offset + idx); + + if (idx < 5) { + memset(rtlpriv->sec.key_buf[idx], 0, + MAX_KEY_LEN); + rtlpriv->sec.key_len[idx] = 0; + } + } + + } else { + switch (enc_algo) { + case WEP40_ENCRYPTION: + enc_algo = CAM_WEP40; + break; + case WEP104_ENCRYPTION: + enc_algo = CAM_WEP104; + break; + case TKIP_ENCRYPTION: + enc_algo = CAM_TKIP; + break; + case AESCCMP_ENCRYPTION: + enc_algo = CAM_AES; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + enc_algo = CAM_TKIP; + break; + } + + if (is_wepkey || rtlpriv->sec.use_defaultkey) { + macaddr = cam_const_addr[key_index]; + entry_id = key_index; + } else { + if (is_group) { + macaddr = cam_const_broad; + entry_id = key_index; + } else { + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + entry_id = rtl_cam_get_free_entry(hw, + p_macaddr); + if (entry_id >= TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, COMP_SEC, + DBG_EMERG, + "Can not find free hw security cam entry\n"); + return; + } + } else { + entry_id = CAM_PAIRWISE_KEY_POSITION; + } + + key_index = PAIRWISE_KEYIDX; + is_pairwise = true; + } + } + + if (rtlpriv->sec.key_len[key_index] == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "delete one entry, entry_id is %d\n", + entry_id); + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_MESH_POINT) + rtl_cam_del_entry(hw, p_macaddr); + rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "The insert KEY length is %d\n", + rtlpriv->sec.key_len[PAIRWISE_KEYIDX]); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "The insert KEY is %x %x\n", + rtlpriv->sec.key_buf[0][0], + rtlpriv->sec.key_buf[0][1]); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "add one entry\n"); + if (is_pairwise) { + RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, + "Pairwise Key content", + rtlpriv->sec.pairwise_key, + rtlpriv->sec. + key_len[PAIRWISE_KEYIDX]); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set Pairwise key\n"); + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec. + key_buf[key_index]); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set group key\n"); + + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_cam_add_one_entry(hw, + rtlefuse->dev_addr, + PAIRWISE_KEYIDX, + CAM_PAIRWISE_KEY_POSITION, + enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf + [entry_id]); + } + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + + } + } +} + +static void rtl8192ce_bt_var_init(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + rtlpcipriv->bt_coexist.bt_coexistence = + rtlpcipriv->bt_coexist.eeprom_bt_coexist; + rtlpcipriv->bt_coexist.bt_ant_num = + rtlpcipriv->bt_coexist.eeprom_bt_ant_num; + rtlpcipriv->bt_coexist.bt_coexist_type = + rtlpcipriv->bt_coexist.eeprom_bt_type; + + if (rtlpcipriv->bt_coexist.reg_bt_iso == 2) + rtlpcipriv->bt_coexist.bt_ant_isolation = + rtlpcipriv->bt_coexist.eeprom_bt_ant_isol; + else + rtlpcipriv->bt_coexist.bt_ant_isolation = + rtlpcipriv->bt_coexist.reg_bt_iso; + + rtlpcipriv->bt_coexist.bt_radio_shared_type = + rtlpcipriv->bt_coexist.eeprom_bt_radio_shared; + + if (rtlpcipriv->bt_coexist.bt_coexistence) { + + if (rtlpcipriv->bt_coexist.reg_bt_sco == 1) + rtlpcipriv->bt_coexist.bt_service = BT_OTHER_ACTION; + else if (rtlpcipriv->bt_coexist.reg_bt_sco == 2) + rtlpcipriv->bt_coexist.bt_service = BT_SCO; + else if (rtlpcipriv->bt_coexist.reg_bt_sco == 4) + rtlpcipriv->bt_coexist.bt_service = BT_BUSY; + else if (rtlpcipriv->bt_coexist.reg_bt_sco == 5) + rtlpcipriv->bt_coexist.bt_service = BT_OTHERBUSY; + else + rtlpcipriv->bt_coexist.bt_service = BT_IDLE; + + rtlpcipriv->bt_coexist.bt_edca_ul = 0; + rtlpcipriv->bt_coexist.bt_edca_dl = 0; + rtlpcipriv->bt_coexist.bt_rssi_state = 0xff; + } +} + +void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool auto_load_fail, u8 *hwinfo) +{ + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + u8 val; + + if (!auto_load_fail) { + rtlpcipriv->bt_coexist.eeprom_bt_coexist = + ((hwinfo[RF_OPTION1] & 0xe0) >> 5); + val = hwinfo[RF_OPTION4]; + rtlpcipriv->bt_coexist.eeprom_bt_type = ((val & 0xe) >> 1); + rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (val & 0x1); + rtlpcipriv->bt_coexist.eeprom_bt_ant_isol = ((val & 0x10) >> 4); + rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = + ((val & 0x20) >> 5); + } else { + rtlpcipriv->bt_coexist.eeprom_bt_coexist = 0; + rtlpcipriv->bt_coexist.eeprom_bt_type = BT_2WIRE; + rtlpcipriv->bt_coexist.eeprom_bt_ant_num = ANT_X2; + rtlpcipriv->bt_coexist.eeprom_bt_ant_isol = 0; + rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = BT_RADIO_SHARED; + } + + rtl8192ce_bt_var_init(hw); +} + +void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + /* 0:Low, 1:High, 2:From Efuse. */ + rtlpcipriv->bt_coexist.reg_bt_iso = 2; + /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ + rtlpcipriv->bt_coexist.reg_bt_sco = 3; + /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ + rtlpcipriv->bt_coexist.reg_bt_sco = 0; +} + + +void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + + u8 u1_tmp; + + if (rtlpcipriv->bt_coexist.bt_coexistence && + ((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) || + rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8)) { + + if (rtlpcipriv->bt_coexist.bt_ant_isolation) + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); + + u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) & + BIT_OFFSET_LEN_MASK_32(0, 1); + u1_tmp = u1_tmp | + ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? + 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | + ((rtlpcipriv->bt_coexist.bt_service == BT_SCO) ? + 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); + rtl_write_byte(rtlpriv, 0x4fd, u1_tmp); + + rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa); + rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040); + rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010); + + /* Config to 1T1R. */ + if (rtlphy->rf_type == RF_1T1R) { + u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE); + u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); + rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp); + + u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE); + u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); + rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp); + } + } +} + +void rtl92ce_suspend(struct ieee80211_hw *hw) +{ +} + +void rtl92ce_resume(struct ieee80211_hw *hw) +{ +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h new file mode 100644 index 000000000000..98a086822aac --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.h @@ -0,0 +1,80 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CE_HW_H__ +#define __RTL92CE_HW_H__ + +static inline u8 rtl92c_get_chnl_group(u8 chnl) +{ + u8 group; + + if (chnl < 3) + group = 0; + else if (chnl < 9) + group = 1; + else + group = 2; + return group; +} + +void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw); +void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb); +int rtl92ce_hw_init(struct ieee80211_hw *hw); +void rtl92ce_card_disable(struct ieee80211_hw *hw); +void rtl92ce_enable_interrupt(struct ieee80211_hw *hw); +void rtl92ce_disable_interrupt(struct ieee80211_hw *hw); +int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); +void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); +void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci); +void rtl92ce_set_beacon_related_registers(struct ieee80211_hw *hw); +void rtl92ce_set_beacon_interval(struct ieee80211_hw *hw); +void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); +void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); +void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); +void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw); +bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); +void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw); +void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all); + +void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo); +void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw); +void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw); +void rtl92ce_suspend(struct ieee80211_hw *hw); +void rtl92ce_resume(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c new file mode 100644 index 000000000000..8283e9b27639 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.c @@ -0,0 +1,151 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "reg.h" +#include "led.h" + +static void _rtl92ce_init_led(struct ieee80211_hw *hw, + struct rtl_led *pled, enum rtl_led_pin ledpin) +{ + pled->hw = hw; + pled->ledpin = ledpin; + pled->ledon = false; +} + +void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u8 ledcfg; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", + REG_LEDCFG2, pled->ledpin); + + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + rtl_write_byte(rtlpriv, + REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6)); + break; + case LED_PIN_LED1: + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + pled->ledon = true; +} + +void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + u8 ledcfg; + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", + REG_LEDCFG2, pled->ledpin); + + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg &= 0xf0; + if (pcipriv->ledctl.led_opendrain) + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(1) | BIT(5) | BIT(6))); + else + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(3) | BIT(5) | BIT(6))); + break; + case LED_PIN_LED1: + ledcfg &= 0x0f; + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + pled->ledon = false; +} + +void rtl92ce_init_sw_leds(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); + _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); +} + +static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + switch (ledaction) { + case LED_CTL_POWER_ON: + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + rtl92ce_sw_led_on(hw, pLed0); + break; + case LED_CTL_POWER_OFF: + rtl92ce_sw_led_off(hw, pLed0); + break; + default: + break; + } +} + +void rtl92ce_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && + (ledaction == LED_CTL_TX || + ledaction == LED_CTL_RX || + ledaction == LED_CTL_SITE_SURVEY || + ledaction == LED_CTL_LINK || + ledaction == LED_CTL_NO_LINK || + ledaction == LED_CTL_START_TO_LINK || + ledaction == LED_CTL_POWER_ON)) { + return; + } + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d\n", + ledaction); + _rtl92ce_sw_led_control(hw, ledaction); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h new file mode 100644 index 000000000000..c5761066d383 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/led.h @@ -0,0 +1,38 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CE_LED_H__ +#define __RTL92CE_LED_H__ + +void rtl92ce_init_sw_leds(struct ieee80211_hw *hw); +void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92ce_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c new file mode 100644 index 000000000000..1ee5a6ae9960 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c @@ -0,0 +1,577 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../ps.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "hw.h" +#include "phy.h" +#include "../rtl8192c/phy_common.h" +#include "rf.h" +#include "dm.h" +#include "../rtl8192c/dm_common.h" +#include "../rtl8192c/fw_common.h" +#include "table.h" + +static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); + +u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, readback_value, bitshift; + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", + regaddr, rfpath, bitmask); + + spin_lock(&rtlpriv->locks.rf_lock); + + if (rtlphy->rf_mode != RF_OP_BY_FW) { + original_value = _rtl92c_phy_rf_serial_read(hw, + rfpath, regaddr); + } else { + original_value = _rtl92c_phy_fw_rf_serial_read(hw, + rfpath, regaddr); + } + + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + readback_value = (original_value & bitmask) >> bitshift; + + spin_unlock(&rtlpriv->locks.rf_lock); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", + regaddr, rfpath, bitmask, original_value); + + return readback_value; +} + +bool rtl92c_phy_mac_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool is92c = IS_92C_SERIAL(rtlhal->version); + bool rtstatus = _rtl92c_phy_config_mac_with_headerfile(hw); + + if (is92c) + rtl_write_byte(rtlpriv, 0x14, 0x71); + else + rtl_write_byte(rtlpriv, 0x04CA, 0x0A); + return rtstatus; +} + +bool rtl92c_phy_bb_config(struct ieee80211_hw *hw) +{ + bool rtstatus = true; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 regval; + u32 regvaldw; + u8 reg_hwparafile = 1; + + _rtl92c_phy_init_bb_rf_register_definition(hw); + regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, + regval | BIT(13) | BIT(0) | BIT(1)); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); + rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, + FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | + FEN_BB_GLB_RSTn | FEN_BBRSTB); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); + regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); + rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); + if (reg_hwparafile == 1) + rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); + return rtstatus; +} + +void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 original_value, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); + + spin_lock(&rtlpriv->locks.rf_lock); + + if (rtlphy->rf_mode != RF_OP_BY_FW) { + if (bitmask != RFREG_OFFSET_MASK) { + original_value = _rtl92c_phy_rf_serial_read(hw, + rfpath, + regaddr); + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + data = + ((original_value & (~bitmask)) | + (data << bitshift)); + } + + _rtl92c_phy_rf_serial_write(hw, rfpath, regaddr, data); + } else { + if (bitmask != RFREG_OFFSET_MASK) { + original_value = _rtl92c_phy_fw_rf_serial_read(hw, + rfpath, + regaddr); + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + data = + ((original_value & (~bitmask)) | + (data << bitshift)); + } + _rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data); + } + + spin_unlock(&rtlpriv->locks.rf_lock); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); +} + +static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + u32 arraylength; + u32 *ptrarray; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n"); + arraylength = MAC_2T_ARRAYLENGTH; + ptrarray = RTL8192CEMAC_2T_ARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CEMAC_2T_ARRAY\n"); + for (i = 0; i < arraylength; i = i + 2) + rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); + return true; +} + +bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype) +{ + int i; + u32 *phy_regarray_table; + u32 *agctab_array_table; + u16 phy_reg_arraylen, agctab_arraylen; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (IS_92C_SERIAL(rtlhal->version)) { + agctab_arraylen = AGCTAB_2TARRAYLENGTH; + agctab_array_table = RTL8192CEAGCTAB_2TARRAY; + phy_reg_arraylen = PHY_REG_2TARRAY_LENGTH; + phy_regarray_table = RTL8192CEPHY_REG_2TARRAY; + } else { + agctab_arraylen = AGCTAB_1TARRAYLENGTH; + agctab_array_table = RTL8192CEAGCTAB_1TARRAY; + phy_reg_arraylen = PHY_REG_1TARRAY_LENGTH; + phy_regarray_table = RTL8192CEPHY_REG_1TARRAY; + } + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_reg_arraylen; i = i + 2) { + rtl_addr_delay(phy_regarray_table[i]); + rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD, + phy_regarray_table[i + 1]); + udelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", + phy_regarray_table[i], + phy_regarray_table[i + 1]); + } + } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { + for (i = 0; i < agctab_arraylen; i = i + 2) { + rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD, + agctab_array_table[i + 1]); + udelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", + agctab_array_table[i], + agctab_array_table[i + 1]); + } + } + return true; +} + +bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int i; + u32 *phy_regarray_table_pg; + u16 phy_regarray_pg_len; + + phy_regarray_pg_len = PHY_REG_ARRAY_PGLENGTH; + phy_regarray_table_pg = RTL8192CEPHY_REG_ARRAY_PG; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_regarray_pg_len; i = i + 3) { + rtl_addr_delay(phy_regarray_table_pg[i]); + + _rtl92c_store_pwrIndex_diffrate_offset(hw, + phy_regarray_table_pg[i], + phy_regarray_table_pg[i + 1], + phy_regarray_table_pg[i + 2]); + } + } else { + + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "configtype != BaseBand_Config_PHY_REG\n"); + } + return true; +} + +bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath) +{ + + int i; + u32 *radioa_array_table; + u32 *radiob_array_table; + u16 radioa_arraylen, radiob_arraylen; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (IS_92C_SERIAL(rtlhal->version)) { + radioa_arraylen = RADIOA_2TARRAYLENGTH; + radioa_array_table = RTL8192CERADIOA_2TARRAY; + radiob_arraylen = RADIOB_2TARRAYLENGTH; + radiob_array_table = RTL8192CE_RADIOB_2TARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio_A:RTL8192CERADIOA_2TARRAY\n"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio_B:RTL8192CE_RADIOB_2TARRAY\n"); + } else { + radioa_arraylen = RADIOA_1TARRAYLENGTH; + radioa_array_table = RTL8192CE_RADIOA_1TARRAY; + radiob_arraylen = RADIOB_1TARRAYLENGTH; + radiob_array_table = RTL8192CE_RADIOB_1TARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio_A:RTL8192CE_RADIOA_1TARRAY\n"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio_B:RTL8192CE_RADIOB_1TARRAY\n"); + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath); + switch (rfpath) { + case RF90_PATH_A: + for (i = 0; i < radioa_arraylen; i = i + 2) { + rtl_rfreg_delay(hw, rfpath, radioa_array_table[i], + RFREG_OFFSET_MASK, + radioa_array_table[i + 1]); + } + break; + case RF90_PATH_B: + for (i = 0; i < radiob_arraylen; i = i + 2) { + rtl_rfreg_delay(hw, rfpath, radiob_array_table[i], + RFREG_OFFSET_MASK, + radiob_array_table[i + 1]); + } + break; + case RF90_PATH_C: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + case RF90_PATH_D: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + default: + break; + } + return true; +} + +void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 reg_bw_opmode; + u8 reg_prsr_rsc; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz"); + + if (is_hal_stop(rtlhal)) { + rtlphy->set_bwmode_inprogress = false; + return; + } + + reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); + reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + break; + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + reg_prsr_rsc = + (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); + + rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), + (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + rtl92ce_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); +} + +void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) +{ + u8 tmpreg; + u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + tmpreg = rtl_read_byte(rtlpriv, 0xd03); + + if ((tmpreg & 0x70) != 0) + rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); + else + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + + if ((tmpreg & 0x70) != 0) { + rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); + + if (is2t) + rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, + MASK12BITS); + + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, + (rf_a_mode & 0x8FFFF) | 0x10000); + + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + (rf_b_mode & 0x8FFFF) | 0x10000); + } + lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); + + rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); + + mdelay(100); + + if ((tmpreg & 0x70) != 0) { + rtl_write_byte(rtlpriv, 0xd03, tmpreg); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); + + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + rf_b_mode); + } else { + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + } +} + +static void _rtl92ce_phy_set_rf_sleep(struct ieee80211_hw *hw) +{ + u32 u4b_tmp; + u8 delay = 5; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + while (u4b_tmp != 0 && delay > 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + delay--; + } + if (delay == 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "Switch RF timeout !!!\n"); + return; + } + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); +} + +static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = true; + u8 i, queue_id; + struct rtl8192_tx_ring *ring = NULL; + + switch (rfpwr_state) { + case ERFON:{ + if ((ppsc->rfpwr_state == ERFOFF) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + bool rtstatus; + u32 InitializeCount = 0; + do { + InitializeCount++; + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic enable\n"); + rtstatus = rtl_ps_enable_nic(hw); + } while (!rtstatus && (InitializeCount < 10)); + RT_CLEAR_PS_LEVEL(ppsc, + RT_RF_OFF_LEVL_HALT_NIC); + } else { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFON sleeped:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc-> + last_sleep_jiffies)); + ppsc->last_awake_jiffies = jiffies; + rtl92ce_phy_set_rf_on(hw); + } + if (mac->link_state == MAC80211_LINKED) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } + break; + } + case ERFOFF:{ + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic disable\n"); + rtl_ps_disable_nic(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } else { + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_POWER_OFF); + } + } + break; + } + case ERFSLEEP:{ + if (ppsc->rfpwr_state == ERFOFF) + break; + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (queue_id == BEACON_QUEUE || + skb_queue_len(&ring->queue) == 0) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", + i + 1, queue_id, + skb_queue_len(&ring->queue)); + + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFSLEEP awaked:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc->last_awake_jiffies)); + ppsc->last_sleep_jiffies = jiffies; + _rtl92ce_phy_set_rf_sleep(hw); + break; + } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + bresult = false; + break; + } + if (bresult) + ppsc->rfpwr_state = rfpwr_state; + return bresult; +} + +bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + bool bresult = false; + + if (rfpwr_state == ppsc->rfpwr_state) + return bresult; + bresult = _rtl92ce_phy_set_rf_power_state(hw, rfpwr_state); + return bresult; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h new file mode 100644 index 000000000000..e5e1353a94c3 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h @@ -0,0 +1,143 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_PHY_H__ +#define __RTL92C_PHY_H__ + +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define MAX_DOZE_WAITING_TIMES_9x 64 + +#define RT_CANNOT_IO(hw) false +#define HIGHPOWER_RADIOA_ARRAYLEN 22 + +#define MAX_TOLERANCE 5 + +#define APK_BB_REG_NUM 5 +#define APK_AFE_REG_NUM 16 +#define APK_CURVE_REG_NUM 4 +#define PATH_NUM 2 + +#define LOOP_LIMIT 5 +#define MAX_STALL_TIME 50 +#define AntennaDiversityValue 0x80 +#define MAX_TXPWR_IDX_NMODE_92S 63 +#define Reset_Cnt_Limit 3 + +#define IQK_ADDA_REG_NUM 16 +#define IQK_MAC_REG_NUM 4 + +#define IQK_DELAY_TIME 1 + +#define RF90_PATH_MAX 2 + +#define CT_OFFSET_MAC_ADDR 0X16 + +#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A +#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 +#define CT_OFFSET_HT402S_TX_PWR_IDX_DIF 0x66 +#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 +#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C + +#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F +#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 + +#define CT_OFFSET_CHANNEL_PLAH 0x75 +#define CT_OFFSET_THERMAL_METER 0x78 +#define CT_OFFSET_RF_OPTION 0x79 +#define CT_OFFSET_VERSION 0x7E +#define CT_OFFSET_CUSTOMER_ID 0x7F + +#define RTL92C_MAX_PATH_NUM 2 + +bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); +u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); +void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, + u32 data); +u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask); +void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data); +bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); +bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw); +bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); +bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel); +void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, + long power_indbm); +void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); +void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); +u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); +void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); +void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval); +void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); +void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); +void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); +void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); +bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, + u32 rfpath); +bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); +void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw); +bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); +void rtl92c_phy_set_io(struct ieee80211_hw *hw); +void rtl92c_bb_block_on(struct ieee80211_hw *hw); +u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 offset); +u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask); +void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, u32 data); +void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, u32 data); +bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); +void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); +bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); +void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); +bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); +bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype); +void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h new file mode 100644 index 000000000000..dc8460c0b32f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/reg.h @@ -0,0 +1,2057 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_REG_H__ +#define __RTL92C_REG_H__ + +#define REG_SYS_ISO_CTRL 0x0000 +#define REG_SYS_FUNC_EN 0x0002 +#define REG_APS_FSMCO 0x0004 +#define REG_SYS_CLKR 0x0008 +#define REG_9346CR 0x000A +#define REG_EE_VPD 0x000C +#define REG_AFE_MISC 0x0010 +#define REG_SPS0_CTRL 0x0011 +#define REG_SPS_OCP_CFG 0x0018 +#define REG_RSV_CTRL 0x001C +#define REG_RF_CTRL 0x001F +#define REG_LDOA15_CTRL 0x0020 +#define REG_LDOV12D_CTRL 0x0021 +#define REG_LDOHCI12_CTRL 0x0022 +#define REG_LPLDO_CTRL 0x0023 +#define REG_AFE_XTAL_CTRL 0x0024 +#define REG_AFE_PLL_CTRL 0x0028 +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define REG_PWR_DATA 0x0038 +#define REG_CAL_TIMER 0x003C +#define REG_ACLK_MON 0x003E +#define REG_GPIO_MUXCFG 0x0040 +#define REG_GPIO_IO_SEL 0x0042 +#define REG_MAC_PINMUX_CFG 0x0043 +#define REG_GPIO_PIN_CTRL 0x0044 +#define REG_GPIO_INTM 0x0048 +#define REG_LEDCFG0 0x004C +#define REG_LEDCFG1 0x004D +#define REG_LEDCFG2 0x004E +#define REG_LEDCFG3 0x004F +#define REG_FSIMR 0x0050 +#define REG_FSISR 0x0054 +#define REG_HSIMR 0x0058 +#define REG_HSISR 0x005c + +/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. */ +#define REG_GPIO_PIN_CTRL_2 0x0060 +/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. */ +#define REG_GPIO_IO_SEL_2 0x0062 +/* RTL8723 WIFI/BT/GPS Multi-Function control source. */ +#define REG_MULTI_FUNC_CTRL 0x0068 + +#define REG_MCUFWDL 0x0080 + +#define REG_HMEBOX_EXT_0 0x0088 +#define REG_HMEBOX_EXT_1 0x008A +#define REG_HMEBOX_EXT_2 0x008C +#define REG_HMEBOX_EXT_3 0x008E + +#define REG_BIST_SCAN 0x00D0 +#define REG_BIST_RPT 0x00D4 +#define REG_BIST_ROM_RPT 0x00D8 +#define REG_USB_SIE_INTF 0x00E0 +#define REG_PCIE_MIO_INTF 0x00E4 +#define REG_PCIE_MIO_INTD 0x00E8 +#define REG_HPON_FSM 0x00EC +#define REG_SYS_CFG 0x00F0 +#define REG_GPIO_OUTSTS 0x00F4 /* For RTL8723 only.*/ + +#define REG_CR 0x0100 +#define REG_PBP 0x0104 +#define REG_TRXDMA_CTRL 0x010C +#define REG_TRXFF_BNDY 0x0114 +#define REG_TRXFF_STATUS 0x0118 +#define REG_RXFF_PTR 0x011C +#define REG_HIMR 0x0120 +#define REG_HISR 0x0124 +#define REG_HIMRE 0x0128 +#define REG_HISRE 0x012C +#define REG_CPWM 0x012F +#define REG_FWIMR 0x0130 +#define REG_FWISR 0x0134 +#define REG_PKTBUF_DBG_CTRL 0x0140 +#define REG_PKTBUF_DBG_DATA_L 0x0144 +#define REG_PKTBUF_DBG_DATA_H 0x0148 + +#define REG_TC0_CTRL 0x0150 +#define REG_TC1_CTRL 0x0154 +#define REG_TC2_CTRL 0x0158 +#define REG_TC3_CTRL 0x015C +#define REG_TC4_CTRL 0x0160 +#define REG_TCUNIT_BASE 0x0164 +#define REG_MBIST_START 0x0174 +#define REG_MBIST_DONE 0x0178 +#define REG_MBIST_FAIL 0x017C +#define REG_C2HEVT_MSG_NORMAL 0x01A0 +#define REG_C2HEVT_MSG_TEST 0x01B8 +#define REG_C2HEVT_CLEAR 0x01BF +#define REG_MCUTST_1 0x01c0 +#define REG_FMETHR 0x01C8 +#define REG_HMETFR 0x01CC +#define REG_HMEBOX_0 0x01D0 +#define REG_HMEBOX_1 0x01D4 +#define REG_HMEBOX_2 0x01D8 +#define REG_HMEBOX_3 0x01DC + +#define REG_LLT_INIT 0x01E0 +#define REG_BB_ACCEESS_CTRL 0x01E8 +#define REG_BB_ACCESS_DATA 0x01EC + +#define REG_RQPN 0x0200 +#define REG_FIFOPAGE 0x0204 +#define REG_TDECTRL 0x0208 +#define REG_TXDMA_OFFSET_CHK 0x020C +#define REG_TXDMA_STATUS 0x0210 +#define REG_RQPN_NPQ 0x0214 + +#define REG_RXDMA_AGG_PG_TH 0x0280 +#define REG_RXPKT_NUM 0x0284 +#define REG_RXDMA_STATUS 0x0288 + +#define REG_PCIE_CTRL_REG 0x0300 +#define REG_INT_MIG 0x0304 +#define REG_BCNQ_DESA 0x0308 +#define REG_HQ_DESA 0x0310 +#define REG_MGQ_DESA 0x0318 +#define REG_VOQ_DESA 0x0320 +#define REG_VIQ_DESA 0x0328 +#define REG_BEQ_DESA 0x0330 +#define REG_BKQ_DESA 0x0338 +#define REG_RX_DESA 0x0340 +#define REG_DBI 0x0348 +#define REG_MDIO 0x0354 +#define REG_DBG_SEL 0x0360 +#define REG_PCIE_HRPWM 0x0361 +#define REG_PCIE_HCPWM 0x0363 +#define REG_UART_CTRL 0x0364 +#define REG_UART_TX_DESA 0x0370 +#define REG_UART_RX_DESA 0x0378 + +#define REG_HDAQ_DESA_NODEF 0x0000 +#define REG_CMDQ_DESA_NODEF 0x0000 + +#define REG_VOQ_INFORMATION 0x0400 +#define REG_VIQ_INFORMATION 0x0404 +#define REG_BEQ_INFORMATION 0x0408 +#define REG_BKQ_INFORMATION 0x040C +#define REG_MGQ_INFORMATION 0x0410 +#define REG_HGQ_INFORMATION 0x0414 +#define REG_BCNQ_INFORMATION 0x0418 + +#define REG_CPU_MGQ_INFORMATION 0x041C +#define REG_FWHW_TXQ_CTRL 0x0420 +#define REG_HWSEQ_CTRL 0x0423 +#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 +#define REG_TXPKTBUF_MGQ_BDNY 0x0425 +#define REG_MULTI_BCNQ_EN 0x0426 +#define REG_MULTI_BCNQ_OFFSET 0x0427 +#define REG_SPEC_SIFS 0x0428 +#define REG_RL 0x042A +#define REG_DARFRC 0x0430 +#define REG_RARFRC 0x0438 +#define REG_RRSR 0x0440 +#define REG_ARFR0 0x0444 +#define REG_ARFR1 0x0448 +#define REG_ARFR2 0x044C +#define REG_ARFR3 0x0450 +#define REG_AGGLEN_LMT 0x0458 +#define REG_AMPDU_MIN_SPACE 0x045C +#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D +#define REG_FAST_EDCA_CTRL 0x0460 +#define REG_RD_RESP_PKT_TH 0x0463 +#define REG_INIRTS_RATE_SEL 0x0480 +#define REG_INIDATA_RATE_SEL 0x0484 +#define REG_POWER_STATUS 0x04A4 +#define REG_POWER_STAGE1 0x04B4 +#define REG_POWER_STAGE2 0x04B8 +#define REG_PKT_LIFE_TIME 0x04C0 +#define REG_STBC_SETTING 0x04C4 +#define REG_PROT_MODE_CTRL 0x04C8 +#define REG_BAR_MODE_CTRL 0x04CC +#define REG_RA_TRY_RATE_AGG_LMT 0x04CF +#define REG_NQOS_SEQ 0x04DC +#define REG_QOS_SEQ 0x04DE +#define REG_NEED_CPU_HANDLE 0x04E0 +#define REG_PKT_LOSE_RPT 0x04E1 +#define REG_PTCL_ERR_STATUS 0x04E2 +#define REG_DUMMY 0x04FC + +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050C +#define REG_BCNTCFG 0x0510 +#define REG_PIFS 0x0512 +#define REG_RDG_PIFS 0x0513 +#define REG_SIFS_CTX 0x0514 +#define REG_SIFS_TRX 0x0516 +#define REG_SIFS_CCK 0x0514 +#define REG_SIFS_OFDM 0x0516 +#define REG_AGGR_BREAK_TIME 0x051A +#define REG_SLOT 0x051B +#define REG_TX_PTCL_CTRL 0x0520 +#define REG_TXPAUSE 0x0522 +#define REG_DIS_TXREQ_CLR 0x0523 +#define REG_RD_CTRL 0x0524 +#define REG_TBTT_PROHIBIT 0x0540 +#define REG_RD_NAV_NXT 0x0544 +#define REG_NAV_PROT_LEN 0x0546 +#define REG_BCN_CTRL 0x0550 +#define REG_USTIME_TSF 0x0551 +#define REG_MBID_NUM 0x0552 +#define REG_DUAL_TSF_RST 0x0553 +#define REG_BCN_INTERVAL 0x0554 +#define REG_MBSSID_BCN_SPACE 0x0554 +#define REG_DRVERLYINT 0x0558 +#define REG_BCNDMATIM 0x0559 +#define REG_ATIMWND 0x055A +#define REG_BCN_MAX_ERR 0x055D +#define REG_RXTSF_OFFSET_CCK 0x055E +#define REG_RXTSF_OFFSET_OFDM 0x055F +#define REG_TSFTR 0x0560 +#define REG_INIT_TSFTR 0x0564 +#define REG_PSTIMER 0x0580 +#define REG_TIMER0 0x0584 +#define REG_TIMER1 0x0588 +#define REG_ACMHWCTRL 0x05C0 +#define REG_ACMRSTCTRL 0x05C1 +#define REG_ACMAVG 0x05C2 +#define REG_VO_ADMTIME 0x05C4 +#define REG_VI_ADMTIME 0x05C6 +#define REG_BE_ADMTIME 0x05C8 +#define REG_EDCA_RANDOM_GEN 0x05CC +#define REG_SCH_TXCMD 0x05D0 + +#define REG_APSD_CTRL 0x0600 +#define REG_BWOPMODE 0x0603 +#define REG_TCR 0x0604 +#define REG_RCR 0x0608 +#define REG_RX_PKT_LIMIT 0x060C +#define REG_RX_DLK_TIME 0x060D +#define REG_RX_DRVINFO_SZ 0x060F + +#define REG_MACID 0x0610 +#define REG_BSSID 0x0618 +#define REG_MAR 0x0620 +#define REG_MBIDCAMCFG 0x0628 + +#define REG_USTIME_EDCA 0x0638 +#define REG_MAC_SPEC_SIFS 0x063A +#define REG_RESP_SIFS_CCK 0x063C +#define REG_RESP_SIFS_OFDM 0x063E +/* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */ +#define REG_R2T_SIFS 0x063C +/* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */ +#define REG_T2T_SIFS 0x063E +#define REG_ACKTO 0x0640 +#define REG_CTS2TO 0x0641 +#define REG_EIFS 0x0642 + +#define REG_NAV_CTRL 0x0650 +#define REG_BACAMCMD 0x0654 +#define REG_BACAMCONTENT 0x0658 +#define REG_LBDLY 0x0660 +#define REG_FWDLY 0x0661 +#define REG_RXERR_RPT 0x0664 +#define REG_WMAC_TRXPTCL_CTL 0x0668 + +#define REG_CAMCMD 0x0670 +#define REG_CAMWRITE 0x0674 +#define REG_CAMREAD 0x0678 +#define REG_CAMDBG 0x067C +#define REG_SECCFG 0x0680 + +#define REG_WOW_CTRL 0x0690 +#define REG_PSSTATUS 0x0691 +#define REG_PS_RX_INFO 0x0692 +#define REG_LPNAV_CTRL 0x0694 +#define REG_WKFMCAM_CMD 0x0698 +#define REG_WKFMCAM_RWD 0x069C +#define REG_RXFLTMAP0 0x06A0 +#define REG_RXFLTMAP1 0x06A2 +#define REG_RXFLTMAP2 0x06A4 +#define REG_BCN_PSR_RPT 0x06A8 +#define REG_CALB32K_CTRL 0x06AC +#define REG_PKT_MON_CTRL 0x06B4 +#define REG_BT_COEX_TABLE 0x06C0 +#define REG_WMAC_RESP_TXINFO 0x06D8 + +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_TEST_USB_TXQS 0xFE48 +#define REG_TEST_SIE_VID 0xFE60 +#define REG_TEST_SIE_PID 0xFE62 +#define REG_TEST_SIE_OPTIONAL 0xFE64 +#define REG_TEST_SIE_CHIRP_K 0xFE65 +#define REG_TEST_SIE_PHY 0xFE66 +#define REG_TEST_SIE_MAC_ADDR 0xFE70 +#define REG_TEST_SIE_STRING 0xFE80 + +#define REG_NORMAL_SIE_VID 0xFE60 +#define REG_NORMAL_SIE_PID 0xFE62 +#define REG_NORMAL_SIE_OPTIONAL 0xFE64 +#define REG_NORMAL_SIE_EP 0xFE65 +#define REG_NORMAL_SIE_PHY 0xFE68 +#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 +#define REG_NORMAL_SIE_STRING 0xFE80 + +#define CR9346 REG_9346CR +#define MSR (REG_CR + 2) +#define ISR REG_HISR +#define TSFR REG_TSFTR + +#define MACIDR0 REG_MACID +#define MACIDR4 (REG_MACID + 4) + +#define PBP REG_PBP + +#define IDR0 MACIDR0 +#define IDR4 MACIDR4 + +#define UNUSED_REGISTER 0x1BF +#define DCAM UNUSED_REGISTER +#define PSR UNUSED_REGISTER +#define BBADDR UNUSED_REGISTER +#define PHYDATAR UNUSED_REGISTER + +#define INVALID_BBRF_VALUE 0x12345678 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define CMDEEPROM_EN BIT(5) +#define CMDEEPROM_SEL BIT(4) +#define CMD9346CR_9356SEL BIT(4) +#define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL) +#define AUTOLOAD_EFUSE CMDEEPROM_EN + +#define GPIOSEL_GPIO 0 +#define GPIOSEL_ENBT BIT(5) + +#define GPIO_IN REG_GPIO_PIN_CTRL +#define GPIO_OUT (REG_GPIO_PIN_CTRL+1) +#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) +#define GPIO_MOD (REG_GPIO_PIN_CTRL+3) + +#define MSR_NOLINK 0x00 +#define MSR_ADHOC 0x01 +#define MSR_INFRA 0x02 +#define MSR_AP 0x03 +#define MSR_MASK 0x03 + +#define RRSR_RSC_OFFSET 21 +#define RRSR_SHORT_OFFSET 23 +#define RRSR_RSC_BW_40M 0x600000 +#define RRSR_RSC_UPSUBCHNL 0x400000 +#define RRSR_RSC_LOWSUBCHNL 0x200000 +#define RRSR_SHORT 0x800000 +#define RRSR_1M BIT(0) +#define RRSR_2M BIT(1) +#define RRSR_5_5M BIT(2) +#define RRSR_11M BIT(3) +#define RRSR_6M BIT(4) +#define RRSR_9M BIT(5) +#define RRSR_12M BIT(6) +#define RRSR_18M BIT(7) +#define RRSR_24M BIT(8) +#define RRSR_36M BIT(9) +#define RRSR_48M BIT(10) +#define RRSR_54M BIT(11) +#define RRSR_MCS0 BIT(12) +#define RRSR_MCS1 BIT(13) +#define RRSR_MCS2 BIT(14) +#define RRSR_MCS3 BIT(15) +#define RRSR_MCS4 BIT(16) +#define RRSR_MCS5 BIT(17) +#define RRSR_MCS6 BIT(18) +#define RRSR_MCS7 BIT(19) +#define BRSR_ACKSHORTPMB BIT(23) + +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 + +#define RATE_1M BIT(0) +#define RATE_2M BIT(1) +#define RATE_5_5M BIT(2) +#define RATE_11M BIT(3) +#define RATE_6M BIT(4) +#define RATE_9M BIT(5) +#define RATE_12M BIT(6) +#define RATE_18M BIT(7) +#define RATE_24M BIT(8) +#define RATE_36M BIT(9) +#define RATE_48M BIT(10) +#define RATE_54M BIT(11) +#define RATE_MCS0 BIT(12) +#define RATE_MCS1 BIT(13) +#define RATE_MCS2 BIT(14) +#define RATE_MCS3 BIT(15) +#define RATE_MCS4 BIT(16) +#define RATE_MCS5 BIT(17) +#define RATE_MCS6 BIT(18) +#define RATE_MCS7 BIT(19) +#define RATE_MCS8 BIT(20) +#define RATE_MCS9 BIT(21) +#define RATE_MCS10 BIT(22) +#define RATE_MCS11 BIT(23) +#define RATE_MCS12 BIT(24) +#define RATE_MCS13 BIT(25) +#define RATE_MCS14 BIT(26) +#define RATE_MCS15 BIT(27) + +#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) +#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M \ + | RATR_24M | RATR_36M | RATR_48M | RATR_54M) +#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \ + RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \ + RATR_MCS6 | RATR_MCS7) +#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \ + RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \ + RATR_MCS14 | RATR_MCS15) + +#define BW_OPMODE_20MHZ BIT(2) +#define BW_OPMODE_5G BIT(1) +#define BW_OPMODE_11J BIT(0) + +#define CAM_VALID BIT(15) +#define CAM_NOTVALID 0x0000 +#define CAM_USEDK BIT(5) + +#define CAM_NONE 0x0 +#define CAM_WEP40 0x01 +#define CAM_TKIP 0x02 +#define CAM_AES 0x04 +#define CAM_WEP104 0x05 + +#define TOTAL_CAM_ENTRY 32 +#define HALF_CAM_ENTRY 16 + +#define CAM_WRITE BIT(16) +#define CAM_READ 0x00000000 +#define CAM_POLLINIG BIT(31) + +#define SCR_USEDK 0x01 +#define SCR_TXSEC_ENABLE 0x02 +#define SCR_RXSEC_ENABLE 0x04 + +#define WOW_PMEN BIT(0) +#define WOW_WOMEN BIT(1) +#define WOW_MAGIC BIT(2) +#define WOW_UWF BIT(3) + +#define IMR8190_DISABLED 0x0 +#define IMR_BCNDMAINT6 BIT(31) +#define IMR_BCNDMAINT5 BIT(30) +#define IMR_BCNDMAINT4 BIT(29) +#define IMR_BCNDMAINT3 BIT(28) +#define IMR_BCNDMAINT2 BIT(27) +#define IMR_BCNDMAINT1 BIT(26) +#define IMR_BCNDOK8 BIT(25) +#define IMR_BCNDOK7 BIT(24) +#define IMR_BCNDOK6 BIT(23) +#define IMR_BCNDOK5 BIT(22) +#define IMR_BCNDOK4 BIT(21) +#define IMR_BCNDOK3 BIT(20) +#define IMR_BCNDOK2 BIT(19) +#define IMR_BCNDOK1 BIT(18) +#define IMR_TIMEOUT2 BIT(17) +#define IMR_TIMEOUT1 BIT(16) +#define IMR_TXFOVW BIT(15) +#define IMR_PSTIMEOUT BIT(14) +#define IMR_BCNINT BIT(13) +#define IMR_RXFOVW BIT(12) +#define IMR_RDU BIT(11) +#define IMR_ATIMEND BIT(10) +#define IMR_BDOK BIT(9) +#define IMR_HIGHDOK BIT(8) +#define IMR_TBDOK BIT(7) +#define IMR_MGNTDOK BIT(6) +#define IMR_TBDER BIT(5) +#define IMR_BKDOK BIT(4) +#define IMR_BEDOK BIT(3) +#define IMR_VIDOK BIT(2) +#define IMR_VODOK BIT(1) +#define IMR_ROK BIT(0) + +#define IMR_TXERR BIT(11) +#define IMR_RXERR BIT(10) +#define IMR_C2HCMD BIT(9) +#define IMR_CPWM BIT(8) +#define IMR_OCPINT BIT(1) +#define IMR_WLANOFF BIT(0) + +#define EFUSE_REAL_CONTENT_LEN 512 +#define EFUSE_OOB_PROTECT_BYTES 15 + +#define EEPROM_DEFAULT_TSSI 0x0 +#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_BOARDTYPE 0x02 +#define EEPROM_DEFAULT_TXPOWER 0x1010 +#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 + +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_THERMALMETER 0x12 +#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 +#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 +#define EEPROM_DEFAULT_HT20_DIFF 2 +#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 +#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 + +#define RF_OPTION1 0x79 +#define RF_OPTION2 0x7A +#define RF_OPTION3 0x7B +#define RF_OPTION4 0x7C + +#define EEPROM_DEFAULT_PID 0x1234 +#define EEPROM_DEFAULT_VID 0x5678 +#define EEPROM_DEFAULT_CUSTOMERID 0xAB +#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD +#define EEPROM_DEFAULT_VERSION 0 + +#define EEPROM_CHANNEL_PLAN_FCC 0x0 +#define EEPROM_CHANNEL_PLAN_IC 0x1 +#define EEPROM_CHANNEL_PLAN_ETSI 0x2 +#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 +#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 +#define EEPROM_CHANNEL_PLAN_MKK 0x5 +#define EEPROM_CHANNEL_PLAN_MKK1 0x6 +#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 +#define EEPROM_CHANNEL_PLAN_TELEC 0x8 +#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 +#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA +#define EEPROM_CHANNEL_PLAN_NCC 0xB +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + +#define EEPROM_CID_DEFAULT 0x0 +#define EEPROM_CID_TOSHIBA 0x4 +#define EEPROM_CID_CCX 0x10 +#define EEPROM_CID_QMI 0x0D +#define EEPROM_CID_WHQL 0xFE + +#define RTL8192_EEPROM_ID 0x8129 + +#define RTL8190_EEPROM_ID 0x8129 +#define EEPROM_HPON 0x02 +#define EEPROM_CLK 0x06 +#define EEPROM_TESTR 0x08 + +#define EEPROM_VID 0x0A +#define EEPROM_DID 0x0C +#define EEPROM_SVID 0x0E +#define EEPROM_SMID 0x10 + +#define EEPROM_MAC_ADDR 0x16 + +#define EEPROM_CCK_TX_PWR_INX 0x5A +#define EEPROM_HT40_1S_TX_PWR_INX 0x60 +#define EEPROM_HT40_2S_TX_PWR_INX_DIFF 0x66 +#define EEPROM_HT20_TX_PWR_INX_DIFF 0x69 +#define EEPROM_OFDM_TX_PWR_INX_DIFF 0x6C +#define EEPROM_HT40_MAX_PWR_OFFSET 0x6F +#define EEPROM_HT20_MAX_PWR_OFFSET 0x72 + +#define EEPROM_TSSI_A 0x76 +#define EEPROM_TSSI_B 0x77 +#define EEPROM_THERMAL_METER 0x78 +#define EEPROM_XTAL_K 0x78 +#define EEPROM_RF_OPT1 0x79 +#define EEPROM_RF_OPT2 0x7A +#define EEPROM_RF_OPT3 0x7B +#define EEPROM_RF_OPT4 0x7C +#define EEPROM_CHANNEL_PLAN 0x7D +#define EEPROM_VERSION 0x7E +#define EEPROM_CUSTOMER_ID 0x7F + +#define EEPROM_PWRDIFF 0x54 + +#define EEPROM_TXPOWERCCK 0x5A +#define EEPROM_TXPOWERHT40_1S 0x60 +#define EEPROM_TXPOWERHT40_2SDIFF 0x66 +#define EEPROM_TXPOWERHT20DIFF 0x69 +#define EEPROM_TXPOWER_OFDMDIFF 0x6C + +#define EEPROM_TXPWR_GROUP 0x6F + +#define EEPROM_CHANNELPLAN 0x75 + +#define STOPBECON BIT(6) +#define STOPHIGHT BIT(5) +#define STOPMGT BIT(4) +#define STOPVO BIT(3) +#define STOPVI BIT(2) +#define STOPBE BIT(1) +#define STOPBK BIT(0) + +#define RCR_APPFCS BIT(31) +#define RCR_APP_FCS BIT(31) +#define RCR_APP_MIC BIT(30) +#define RCR_APP_ICV BIT(29) +#define RCR_APP_PHYSTS BIT(28) +#define RCR_APP_PHYST_RXFF BIT(28) +#define RCR_APP_BA_SSN BIT(27) +#define RCR_ENMBID BIT(24) +#define RCR_LSIGEN BIT(23) +#define RCR_MFBEN BIT(22) +#define RCR_HTC_LOC_CTRL BIT(14) +#define RCR_AMF BIT(13) +#define RCR_ACF BIT(12) +#define RCR_ADF BIT(11) +#define RCR_AICV BIT(9) +#define RCR_ACRC32 BIT(8) +#define RCR_CBSSID_BCN BIT(7) +#define RCR_CBSSID_DATA BIT(6) +#define RCR_CBSSID RCR_CBSSID_DATA +#define RCR_APWRMGT BIT(5) +#define RCR_ADD3 BIT(4) +#define RCR_AB BIT(3) +#define RCR_AM BIT(2) +#define RCR_APM BIT(1) +#define RCR_AAP BIT(0) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 + +#define RSV_CTRL 0x001C +#define RD_CTRL 0x0524 + +#define REG_USB_VID 0xFE60 +#define REG_USB_PID 0xFE62 +#define REG_USB_OPTIONAL 0xFE64 +#define REG_USB_CHIRP_K 0xFE65 +#define REG_USB_PHY 0xFE66 +#define REG_USB_MAC_ADDR 0xFE70 +#define REG_USB_HRPWM 0xFE58 +#define REG_USB_HCPWM 0xFE57 + +#define SW18_FPWM BIT(3) + +#define ISO_MD2PP BIT(0) +#define ISO_UA2USB BIT(1) +#define ISO_UD2CORE BIT(2) +#define ISO_PA2PCIE BIT(3) +#define ISO_PD2CORE BIT(4) +#define ISO_IP2MAC BIT(5) +#define ISO_DIOP BIT(6) +#define ISO_DIOE BIT(7) +#define ISO_EB2CORE BIT(8) +#define ISO_DIOR BIT(9) + +#define PWC_EV25V BIT(14) +#define PWC_EV12V BIT(15) + +#define FEN_BBRSTB BIT(0) +#define FEN_BB_GLB_RSTn BIT(1) +#define FEN_USBA BIT(2) +#define FEN_UPLL BIT(3) +#define FEN_USBD BIT(4) +#define FEN_DIO_PCIE BIT(5) +#define FEN_PCIEA BIT(6) +#define FEN_PPLL BIT(7) +#define FEN_PCIED BIT(8) +#define FEN_DIOE BIT(9) +#define FEN_CPUEN BIT(10) +#define FEN_DCORE BIT(11) +#define FEN_ELDR BIT(12) +#define FEN_DIO_RF BIT(13) +#define FEN_HWPDN BIT(14) +#define FEN_MREGEN BIT(15) + +#define PFM_LDALL BIT(0) +#define PFM_ALDN BIT(1) +#define PFM_LDKP BIT(2) +#define PFM_WOWL BIT(3) +#define EnPDN BIT(4) +#define PDN_PL BIT(5) +#define APFM_ONMAC BIT(8) +#define APFM_OFF BIT(9) +#define APFM_RSM BIT(10) +#define AFSM_HSUS BIT(11) +#define AFSM_PCIE BIT(12) +#define APDM_MAC BIT(13) +#define APDM_HOST BIT(14) +#define APDM_HPDN BIT(15) +#define RDY_MACON BIT(16) +#define SUS_HOST BIT(17) +#define ROP_ALD BIT(20) +#define ROP_PWR BIT(21) +#define ROP_SPS BIT(22) +#define SOP_MRST BIT(25) +#define SOP_FUSE BIT(26) +#define SOP_ABG BIT(27) +#define SOP_AMB BIT(28) +#define SOP_RCK BIT(29) +#define SOP_A8M BIT(30) +#define XOP_BTCK BIT(31) + +#define ANAD16V_EN BIT(0) +#define ANA8M BIT(1) +#define MACSLP BIT(4) +#define LOADER_CLK_EN BIT(5) +#define _80M_SSC_DIS BIT(7) +#define _80M_SSC_EN_HO BIT(8) +#define PHY_SSC_RSTB BIT(9) +#define SEC_CLK_EN BIT(10) +#define MAC_CLK_EN BIT(11) +#define SYS_CLK_EN BIT(12) +#define RING_CLK_EN BIT(13) + +#define BOOT_FROM_EEPROM BIT(4) +#define EEPROM_EN BIT(5) + +#define AFE_BGEN BIT(0) +#define AFE_MBEN BIT(1) +#define MAC_ID_EN BIT(7) + +#define WLOCK_ALL BIT(0) +#define WLOCK_00 BIT(1) +#define WLOCK_04 BIT(2) +#define WLOCK_08 BIT(3) +#define WLOCK_40 BIT(4) +#define R_DIS_PRST_0 BIT(5) +#define R_DIS_PRST_1 BIT(6) +#define LOCK_ALL_EN BIT(7) + +#define RF_EN BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + +#define LDA15_EN BIT(0) +#define LDA15_STBY BIT(1) +#define LDA15_OBUF BIT(2) +#define LDA15_REG_VOS BIT(3) +#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) + +#define LDV12_EN BIT(0) +#define LDV12_SDBY BIT(1) +#define LPLDO_HSM BIT(2) +#define LPLDO_LSM_DIS BIT(3) +#define _LDV12_VADJ(x) (((x) & 0xF) << 4) + +#define XTAL_EN BIT(0) +#define XTAL_BSEL BIT(1) +#define _XTAL_BOSC(x) (((x) & 0x3) << 2) +#define _XTAL_CADJ(x) (((x) & 0xF) << 4) +#define XTAL_GATE_USB BIT(8) +#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) +#define XTAL_GATE_AFE BIT(11) +#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) +#define XTAL_RF_GATE BIT(14) +#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) +#define XTAL_GATE_DIG BIT(17) +#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) +#define XTAL_BT_GATE BIT(20) +#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) +#define _XTAL_GPIO(x) (((x) & 0x7) << 23) + +#define CKDLY_AFE BIT(26) +#define CKDLY_USB BIT(27) +#define CKDLY_DIG BIT(28) +#define CKDLY_BT BIT(29) + +#define APLL_EN BIT(0) +#define APLL_320_EN BIT(1) +#define APLL_FREF_SEL BIT(2) +#define APLL_EDGE_SEL BIT(3) +#define APLL_WDOGB BIT(4) +#define APLL_LPFEN BIT(5) + +#define APLL_REF_CLK_13MHZ 0x1 +#define APLL_REF_CLK_19_2MHZ 0x2 +#define APLL_REF_CLK_20MHZ 0x3 +#define APLL_REF_CLK_25MHZ 0x4 +#define APLL_REF_CLK_26MHZ 0x5 +#define APLL_REF_CLK_38_4MHZ 0x6 +#define APLL_REF_CLK_40MHZ 0x7 + +#define APLL_320EN BIT(14) +#define APLL_80EN BIT(15) +#define APLL_1MEN BIT(24) + +#define ALD_EN BIT(18) +#define EF_PD BIT(19) +#define EF_FLAG BIT(31) + +#define EF_TRPT BIT(7) +#define LDOE25_EN BIT(31) + +#define RSM_EN BIT(0) +#define Timer_EN BIT(4) + +#define TRSW0EN BIT(2) +#define TRSW1EN BIT(3) +#define EROM_EN BIT(4) +#define EnBT BIT(5) +#define EnUart BIT(8) +#define Uart_910 BIT(9) +#define EnPMAC BIT(10) +#define SIC_SWRST BIT(11) +#define EnSIC BIT(12) +#define SIC_23 BIT(13) +#define EnHDP BIT(14) +#define SIC_LBK BIT(15) + +#define LED0PL BIT(4) +#define LED1PL BIT(12) +#define LED0DIS BIT(7) + +#define MCUFWDL_EN BIT(0) +#define MCUFWDL_RDY BIT(1) +#define FWDL_ChkSum_rpt BIT(2) +#define MACINI_RDY BIT(3) +#define BBINI_RDY BIT(4) +#define RFINI_RDY BIT(5) +#define WINTINI_RDY BIT(6) +#define CPRST BIT(23) + +#define XCLK_VLD BIT(0) +#define ACLK_VLD BIT(1) +#define UCLK_VLD BIT(2) +#define PCLK_VLD BIT(3) +#define PCIRSTB BIT(4) +#define V15_VLD BIT(5) +#define TRP_B15V_EN BIT(7) +#define SIC_IDLE BIT(8) +#define BD_MAC2 BIT(9) +#define BD_MAC1 BIT(10) +#define IC_MACPHY_MODE BIT(11) +#define BT_FUNC BIT(16) +#define VENDOR_ID BIT(19) +#define PAD_HWPD_IDN BIT(22) +#define TRP_VAUX_EN BIT(23) +#define TRP_BT_EN BIT(24) +#define BD_PKG_SEL BIT(25) +#define BD_HCI_SEL BIT(26) +#define TYPE_ID BIT(27) +#define RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28)) + +#define CHIP_VER_RTL_MASK 0xF000 +#define CHIP_VER_RTL_SHIFT 12 + +#define REG_LBMODE (REG_CR + 3) + +#define HCI_TXDMA_EN BIT(0) +#define HCI_RXDMA_EN BIT(1) +#define TXDMA_EN BIT(2) +#define RXDMA_EN BIT(3) +#define PROTOCOL_EN BIT(4) +#define SCHEDULE_EN BIT(5) +#define MACTXEN BIT(6) +#define MACRXEN BIT(7) +#define ENSWBCN BIT(8) +#define ENSEC BIT(9) + +#define _NETTYPE(x) (((x) & 0x3) << 16) +#define MASK_NETTYPE 0x30000 +#define NT_NO_LINK 0x0 +#define NT_LINK_AD_HOC 0x1 +#define NT_LINK_AP 0x2 +#define NT_AS_AP 0x3 + +#define _LBMODE(x) (((x) & 0xF) << 24) +#define MASK_LBMODE 0xF000000 +#define LOOPBACK_NORMAL 0x0 +#define LOOPBACK_IMMEDIATELY 0xB +#define LOOPBACK_MAC_DELAY 0x3 +#define LOOPBACK_PHY 0x1 +#define LOOPBACK_DMA 0x7 + +#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) +#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) +#define _PSRX_MASK 0xF +#define _PSTX_MASK 0xF0 +#define _PSRX(x) (x) +#define _PSTX(x) ((x) << 4) + +#define PBP_64 0x0 +#define PBP_128 0x1 +#define PBP_256 0x2 +#define PBP_512 0x3 +#define PBP_1024 0x4 + +#define RXDMA_ARBBW_EN BIT(0) +#define RXSHFT_EN BIT(1) +#define RXDMA_AGG_EN BIT(2) +#define QS_VO_QUEUE BIT(8) +#define QS_VI_QUEUE BIT(9) +#define QS_BE_QUEUE BIT(10) +#define QS_BK_QUEUE BIT(11) +#define QS_MANAGER_QUEUE BIT(12) +#define QS_HIGH_QUEUE BIT(13) + +#define HQSEL_VOQ BIT(0) +#define HQSEL_VIQ BIT(1) +#define HQSEL_BEQ BIT(2) +#define HQSEL_BKQ BIT(3) +#define HQSEL_MGTQ BIT(4) +#define HQSEL_HIQ BIT(5) + +#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) +#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) +#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) +#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) +#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) +#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) + +#define QUEUE_LOW 1 +#define QUEUE_NORMAL 2 +#define QUEUE_HIGH 3 + +#define _LLT_NO_ACTIVE 0x0 +#define _LLT_WRITE_ACCESS 0x1 +#define _LLT_READ_ACCESS 0x2 + +#define _LLT_INIT_DATA(x) ((x) & 0xFF) +#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) +#define _LLT_OP(x) (((x) & 0x3) << 30) +#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) + +#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) +#define BB_WRITE_EN BIT(30) +#define BB_READ_EN BIT(31) + +#define _HPQ(x) ((x) & 0xFF) +#define _LPQ(x) (((x) & 0xFF) << 8) +#define _PUBQ(x) (((x) & 0xFF) << 16) +#define _NPQ(x) ((x) & 0xFF) + +#define HPQ_PUBLIC_DIS BIT(24) +#define LPQ_PUBLIC_DIS BIT(25) +#define LD_RQPN BIT(31) + +#define BCN_VALID BIT(16) +#define BCN_HEAD(x) (((x) & 0xFF) << 8) +#define BCN_HEAD_MASK 0xFF00 + +#define BLK_DESC_NUM_SHIFT 4 +#define BLK_DESC_NUM_MASK 0xF + +#define DROP_DATA_EN BIT(9) + +#define EN_AMPDU_RTY_NEW BIT(7) + +#define _INIRTSMCS_SEL(x) ((x) & 0x3F) + +#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) +#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) + +#define RATE_REG_BITMAP_ALL 0xFFFFF + +#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) + +#define _RRSR_RSC(x) (((x) & 0x3) << 21) +#define RRSR_RSC_RESERVED 0x0 +#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 +#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 +#define RRSR_RSC_DUPLICATE_MODE 0x3 + +#define USE_SHORT_G1 BIT(20) + +#define _AGGLMT_MCS0(x) ((x) & 0xF) +#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) +#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) +#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) +#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) +#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) +#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) +#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) + +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + +#define _DARF_RC1(x) ((x) & 0x1F) +#define _DARF_RC2(x) (((x) & 0x1F) << 8) +#define _DARF_RC3(x) (((x) & 0x1F) << 16) +#define _DARF_RC4(x) (((x) & 0x1F) << 24) +#define _DARF_RC5(x) ((x) & 0x1F) +#define _DARF_RC6(x) (((x) & 0x1F) << 8) +#define _DARF_RC7(x) (((x) & 0x1F) << 16) +#define _DARF_RC8(x) (((x) & 0x1F) << 24) + +#define _RARF_RC1(x) ((x) & 0x1F) +#define _RARF_RC2(x) (((x) & 0x1F) << 8) +#define _RARF_RC3(x) (((x) & 0x1F) << 16) +#define _RARF_RC4(x) (((x) & 0x1F) << 24) +#define _RARF_RC5(x) ((x) & 0x1F) +#define _RARF_RC6(x) (((x) & 0x1F) << 8) +#define _RARF_RC7(x) (((x) & 0x1F) << 16) +#define _RARF_RC8(x) (((x) & 0x1F) << 24) + +#define AC_PARAM_TXOP_OFFSET 16 +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + +#define _AIFS(x) (x) +#define _ECW_MAX_MIN(x) ((x) << 8) +#define _TXOP_LIMIT(x) ((x) << 16) + +#define _BCNIFS(x) ((x) & 0xFF) +#define _BCNECW(x) ((((x) & 0xF)) << 8) + +#define _LRL(x) ((x) & 0x3F) +#define _SRL(x) (((x) & 0x3F) << 8) + +#define _SIFS_CCK_CTX(x) ((x) & 0xFF) +#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8) + +#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) +#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8) + +#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) + +#define DIS_EDCA_CNT_DWN BIT(11) + +#define EN_MBSSID BIT(1) +#define EN_TXBCN_RPT BIT(2) +#define EN_BCN_FUNCTION BIT(3) + +#define TSFTR_RST BIT(0) +#define TSFTR1_RST BIT(1) + +#define STOP_BCNQ BIT(6) + +#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) +#define DIS_TSF_UDT0_TEST_CHIP BIT(5) + +#define AcmHw_HwEn BIT(0) +#define AcmHw_BeqEn BIT(1) +#define AcmHw_ViqEn BIT(2) +#define AcmHw_VoqEn BIT(3) +#define AcmHw_BeqStatus BIT(4) +#define AcmHw_ViqStatus BIT(5) +#define AcmHw_VoqStatus BIT(6) + +#define APSDOFF BIT(6) +#define APSDOFF_STATUS BIT(7) + +#define BW_20MHZ BIT(2) + +#define RATE_BITMAP_ALL 0xFFFFF + +#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 + +#define TSFRST BIT(0) +#define DIS_GCLK BIT(1) +#define PAD_SEL BIT(2) +#define PWR_ST BIT(6) +#define PWRBIT_OW_EN BIT(7) +#define ACRC BIT(8) +#define CFENDFORM BIT(9) +#define ICV BIT(10) + +#define AAP BIT(0) +#define APM BIT(1) +#define AM BIT(2) +#define AB BIT(3) +#define ADD3 BIT(4) +#define APWRMGT BIT(5) +#define CBSSID BIT(6) +#define CBSSID_DATA BIT(6) +#define CBSSID_BCN BIT(7) +#define ACRC32 BIT(8) +#define AICV BIT(9) +#define ADF BIT(11) +#define ACF BIT(12) +#define AMF BIT(13) +#define HTC_LOC_CTRL BIT(14) +#define UC_DATA_EN BIT(16) +#define BM_DATA_EN BIT(17) +#define MFBEN BIT(22) +#define LSIGEN BIT(23) +#define EnMBID BIT(24) +#define APP_BASSN BIT(27) +#define APP_PHYSTS BIT(28) +#define APP_ICV BIT(29) +#define APP_MIC BIT(30) +#define APP_FCS BIT(31) + +#define _MIN_SPACE(x) ((x) & 0x7) +#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) + +#define RXERR_TYPE_OFDM_PPDU 0 +#define RXERR_TYPE_OFDM_FALSE_ALARM 1 +#define RXERR_TYPE_OFDM_MPDU_OK 2 +#define RXERR_TYPE_OFDM_MPDU_FAIL 3 +#define RXERR_TYPE_CCK_PPDU 4 +#define RXERR_TYPE_CCK_FALSE_ALARM 5 +#define RXERR_TYPE_CCK_MPDU_OK 6 +#define RXERR_TYPE_CCK_MPDU_FAIL 7 +#define RXERR_TYPE_HT_PPDU 8 +#define RXERR_TYPE_HT_FALSE_ALARM 9 +#define RXERR_TYPE_HT_MPDU_TOTAL 10 +#define RXERR_TYPE_HT_MPDU_OK 11 +#define RXERR_TYPE_HT_MPDU_FAIL 12 +#define RXERR_TYPE_RX_FULL_DROP 15 + +#define RXERR_COUNTER_MASK 0xFFFFF +#define RXERR_RPT_RST BIT(27) +#define _RXERR_RPT_SEL(type) ((type) << 28) + +#define SCR_TxUseDK BIT(0) +#define SCR_RxUseDK BIT(1) +#define SCR_TxEncEnable BIT(2) +#define SCR_RxDecEnable BIT(3) +#define SCR_SKByA2 BIT(4) +#define SCR_NoSKMC BIT(5) +#define SCR_TXBCUSEDK BIT(6) +#define SCR_RXBCUSEDK BIT(7) + +#define USB_IS_HIGH_SPEED 0 +#define USB_IS_FULL_SPEED 1 +#define USB_SPEED_MASK BIT(5) + +#define USB_NORMAL_SIE_EP_MASK 0xF +#define USB_NORMAL_SIE_EP_SHIFT 4 + +#define USB_TEST_EP_MASK 0x30 +#define USB_TEST_EP_SHIFT 4 + +#define USB_AGG_EN BIT(3) + +#define LAST_ENTRY_OF_TX_PKT_BUFFER 255 + +#define POLLING_LLT_THRESHOLD 20 +#define POLLING_READY_TIMEOUT_COUNT 1000 + +#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) +#define EPROM_CMD_CONFIG 0x3 +#define EPROM_CMD_LOAD 1 + +#define HWSET_MAX_SIZE 128 +#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE +#define EFUSE_MAX_SECTION 16 + +#define WL_HWPDN_EN BIT(0) + +#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) + +#define RPMAC_RESET 0x100 +#define RPMAC_TXSTART 0x104 +#define RPMAC_TXLEGACYSIG 0x108 +#define RPMAC_TXHTSIG1 0x10c +#define RPMAC_TXHTSIG2 0x110 +#define RPMAC_PHYDEBUG 0x114 +#define RPMAC_TXPACKETNUM 0x118 +#define RPMAC_TXIDLE 0x11c +#define RPMAC_TXMACHEADER0 0x120 +#define RPMAC_TXMACHEADER1 0x124 +#define RPMAC_TXMACHEADER2 0x128 +#define RPMAC_TXMACHEADER3 0x12c +#define RPMAC_TXMACHEADER4 0x130 +#define RPMAC_TXMACHEADER5 0x134 +#define RPMAC_TXDADATYPE 0x138 +#define RPMAC_TXRANDOMSEED 0x13c +#define RPMAC_CCKPLCPPREAMBLE 0x140 +#define RPMAC_CCKPLCPHEADER 0x144 +#define RPMAC_CCKCRC16 0x148 +#define RPMAC_OFDMRXCRC32OK 0x170 +#define RPMAC_OFDMRXCRC32Er 0x174 +#define RPMAC_OFDMRXPARITYER 0x178 +#define RPMAC_OFDMRXCRC8ER 0x17c +#define RPMAC_CCKCRXRC16ER 0x180 +#define RPMAC_CCKCRXRC32ER 0x184 +#define RPMAC_CCKCRXRC32OK 0x188 +#define RPMAC_TXSTATUS 0x18c + +#define RFPGA0_RFMOD 0x800 + +#define RFPGA0_TXINFO 0x804 +#define RFPGA0_PSDFUNCTION 0x808 + +#define RFPGA0_TXGAINSTAGE 0x80c + +#define RFPGA0_RFTIMING1 0x810 +#define RFPGA0_RFTIMING2 0x814 + +#define RFPGA0_XA_HSSIPARAMETER1 0x820 +#define RFPGA0_XA_HSSIPARAMETER2 0x824 +#define RFPGA0_XB_HSSIPARAMETER1 0x828 +#define RFPGA0_XB_HSSIPARAMETER2 0x82c + +#define RFPGA0_XA_LSSIPARAMETER 0x840 +#define RFPGA0_XB_LSSIPARAMETER 0x844 + +#define RFPGA0_RFWAKEUPPARAMETER 0x850 +#define RFPGA0_RFSLEEPUPPARAMETER 0x854 + +#define RFPGA0_XAB_SWITCHCONTROL 0x858 +#define RFPGA0_XCD_SWITCHCONTROL 0x85c + +#define RFPGA0_XA_RFINTERFACEOE 0x860 +#define RFPGA0_XB_RFINTERFACEOE 0x864 + +#define RFPGA0_XAB_RFINTERFACESW 0x870 +#define RFPGA0_XCD_RFINTERFACESW 0x874 + +#define rFPGA0_XAB_RFPARAMETER 0x878 +#define rFPGA0_XCD_RFPARAMETER 0x87c + +#define RFPGA0_ANALOGPARAMETER1 0x880 +#define RFPGA0_ANALOGPARAMETER2 0x884 +#define RFPGA0_ANALOGPARAMETER3 0x888 +#define RFPGA0_ANALOGPARAMETER4 0x88c + +#define RFPGA0_XA_LSSIREADBACK 0x8a0 +#define RFPGA0_XB_LSSIREADBACK 0x8a4 +#define RFPGA0_XC_LSSIREADBACK 0x8a8 +#define RFPGA0_XD_LSSIREADBACK 0x8ac + +#define RFPGA0_PSDREPORT 0x8b4 +#define TRANSCEIVEA_HSPI_READBACK 0x8b8 +#define TRANSCEIVEB_HSPI_READBACK 0x8bc +#define RFPGA0_XAB_RFINTERFACERB 0x8e0 +#define RFPGA0_XCD_RFINTERFACERB 0x8e4 + +#define RFPGA1_RFMOD 0x900 + +#define RFPGA1_TXBLOCK 0x904 +#define RFPGA1_DEBUGSELECT 0x908 +#define RFPGA1_TXINFO 0x90c + +#define RCCK0_SYSTEM 0xa00 + +#define RCCK0_AFESETTING 0xa04 +#define RCCK0_CCA 0xa08 + +#define RCCK0_RXAGC1 0xa0c +#define RCCK0_RXAGC2 0xa10 + +#define RCCK0_RXHP 0xa14 + +#define RCCK0_DSPPARAMETER1 0xa18 +#define RCCK0_DSPPARAMETER2 0xa1c + +#define RCCK0_TXFILTER1 0xa20 +#define RCCK0_TXFILTER2 0xa24 +#define RCCK0_DEBUGPORT 0xa28 +#define RCCK0_FALSEALARMREPORT 0xa2c +#define RCCK0_TRSSIREPORT 0xa50 +#define RCCK0_RXREPORT 0xa54 +#define RCCK0_FACOUNTERLOWER 0xa5c +#define RCCK0_FACOUNTERUPPER 0xa58 + +#define ROFDM0_LSTF 0xc00 + +#define ROFDM0_TRXPATHENABLE 0xc04 +#define ROFDM0_TRMUXPAR 0xc08 +#define ROFDM0_TRSWISOLATION 0xc0c + +#define ROFDM0_XARXAFE 0xc10 +#define ROFDM0_XARXIQIMBALANCE 0xc14 +#define ROFDM0_XBRXAFE 0xc18 +#define ROFDM0_XBRXIQIMBALANCE 0xc1c +#define ROFDM0_XCRXAFE 0xc20 +#define ROFDM0_XCRXIQIMBANLANCE 0xc24 +#define ROFDM0_XDRXAFE 0xc28 +#define ROFDM0_XDRXIQIMBALANCE 0xc2c + +#define ROFDM0_RXDETECTOR1 0xc30 +#define ROFDM0_RXDETECTOR2 0xc34 +#define ROFDM0_RXDETECTOR3 0xc38 +#define ROFDM0_RXDETECTOR4 0xc3c + +#define ROFDM0_RXDSP 0xc40 +#define ROFDM0_CFOANDDAGC 0xc44 +#define ROFDM0_CCADROPTHRESHOLD 0xc48 +#define ROFDM0_ECCATHRESHOLD 0xc4c + +#define ROFDM0_XAAGCCORE1 0xc50 +#define ROFDM0_XAAGCCORE2 0xc54 +#define ROFDM0_XBAGCCORE1 0xc58 +#define ROFDM0_XBAGCCORE2 0xc5c +#define ROFDM0_XCAGCCORE1 0xc60 +#define ROFDM0_XCAGCCORE2 0xc64 +#define ROFDM0_XDAGCCORE1 0xc68 +#define ROFDM0_XDAGCCORE2 0xc6c + +#define ROFDM0_AGCPARAMETER1 0xc70 +#define ROFDM0_AGCPARAMETER2 0xc74 +#define ROFDM0_AGCRSSITABLE 0xc78 +#define ROFDM0_HTSTFAGC 0xc7c + +#define ROFDM0_XATXIQIMBALANCE 0xc80 +#define ROFDM0_XATXAFE 0xc84 +#define ROFDM0_XBTXIQIMBALANCE 0xc88 +#define ROFDM0_XBTXAFE 0xc8c +#define ROFDM0_XCTXIQIMBALANCE 0xc90 +#define ROFDM0_XCTXAFE 0xc94 +#define ROFDM0_XDTXIQIMBALANCE 0xc98 +#define ROFDM0_XDTXAFE 0xc9c + +#define ROFDM0_RXIQEXTANTA 0xca0 + +#define ROFDM0_RXHPPARAMETER 0xce0 +#define ROFDM0_TXPSEUDONOISEWGT 0xce4 +#define ROFDM0_FRAMESYNC 0xcf0 +#define ROFDM0_DFSREPORT 0xcf4 +#define ROFDM0_TXCOEFF1 0xca4 +#define ROFDM0_TXCOEFF2 0xca8 +#define ROFDM0_TXCOEFF3 0xcac +#define ROFDM0_TXCOEFF4 0xcb0 +#define ROFDM0_TXCOEFF5 0xcb4 +#define ROFDM0_TXCOEFF6 0xcb8 + +#define ROFDM1_LSTF 0xd00 +#define ROFDM1_TRXPATHENABLE 0xd04 + +#define ROFDM1_CF0 0xd08 +#define ROFDM1_CSI1 0xd10 +#define ROFDM1_SBD 0xd14 +#define ROFDM1_CSI2 0xd18 +#define ROFDM1_CFOTRACKING 0xd2c +#define ROFDM1_TRXMESAURE1 0xd34 +#define ROFDM1_INTFDET 0xd3c +#define ROFDM1_PSEUDONOISESTATEAB 0xd50 +#define ROFDM1_PSEUDONOISESTATECD 0xd54 +#define ROFDM1_RXPSEUDONOISEWGT 0xd58 + +#define ROFDM_PHYCOUNTER1 0xda0 +#define ROFDM_PHYCOUNTER2 0xda4 +#define ROFDM_PHYCOUNTER3 0xda8 + +#define ROFDM_SHORTCFOAB 0xdac +#define ROFDM_SHORTCFOCD 0xdb0 +#define ROFDM_LONGCFOAB 0xdb4 +#define ROFDM_LONGCFOCD 0xdb8 +#define ROFDM_TAILCF0AB 0xdbc +#define ROFDM_TAILCF0CD 0xdc0 +#define ROFDM_PWMEASURE1 0xdc4 +#define ROFDM_PWMEASURE2 0xdc8 +#define ROFDM_BWREPORT 0xdcc +#define ROFDM_AGCREPORT 0xdd0 +#define ROFDM_RXSNR 0xdd4 +#define ROFDM_RXEVMCSI 0xdd8 +#define ROFDM_SIGREPORT 0xddc + +#define RTXAGC_A_RATE18_06 0xe00 +#define RTXAGC_A_RATE54_24 0xe04 +#define RTXAGC_A_CCK1_MCS32 0xe08 +#define RTXAGC_A_MCS03_MCS00 0xe10 +#define RTXAGC_A_MCS07_MCS04 0xe14 +#define RTXAGC_A_MCS11_MCS08 0xe18 +#define RTXAGC_A_MCS15_MCS12 0xe1c + +#define RTXAGC_B_RATE18_06 0x830 +#define RTXAGC_B_RATE54_24 0x834 +#define RTXAGC_B_CCK1_55_MCS32 0x838 +#define RTXAGC_B_MCS03_MCS00 0x83c +#define RTXAGC_B_MCS07_MCS04 0x848 +#define RTXAGC_B_MCS11_MCS08 0x84c +#define RTXAGC_B_MCS15_MCS12 0x868 +#define RTXAGC_B_CCK11_A_CCK2_11 0x86c + +#define RZEBRA1_HSSIENABLE 0x0 +#define RZEBRA1_TRXENABLE1 0x1 +#define RZEBRA1_TRXENABLE2 0x2 +#define RZEBRA1_AGC 0x4 +#define RZEBRA1_CHARGEPUMP 0x5 +#define RZEBRA1_CHANNEL 0x7 + +#define RZEBRA1_TXGAIN 0x8 +#define RZEBRA1_TXLPF 0x9 +#define RZEBRA1_RXLPF 0xb +#define RZEBRA1_RXHPFCORNER 0xc + +#define RGLOBALCTRL 0 +#define RRTL8256_TXLPF 19 +#define RRTL8256_RXLPF 11 +#define RRTL8258_TXLPF 0x11 +#define RRTL8258_RXLPF 0x13 +#define RRTL8258_RSSILPF 0xa + +#define RF_AC 0x00 + +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_POW_TRSW 0x05 + +#define RF_GAIN_RX 0x06 +#define RF_GAIN_TX 0x07 + +#define RF_TXM_IDAC 0x08 +#define RF_BS_IQGEN 0x0F + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 + +#define RF_RX_AGC_HP 0x12 +#define RF_TX_AGC 0x13 +#define RF_BIAS 0x14 +#define RF_IPA 0x15 +#define RF_POW_ABILITY 0x17 +#define RF_MODE_AG 0x18 +#define RRFCHANNEL 0x18 +#define RF_CHNLBW 0x18 +#define RF_TOP 0x19 + +#define RF_RX_G1 0x1A +#define RF_RX_G2 0x1B + +#define RF_RX_BB2 0x1C +#define RF_RX_BB1 0x1D + +#define RF_RCK1 0x1E +#define RF_RCK2 0x1F + +#define RF_TX_G1 0x20 +#define RF_TX_G2 0x21 +#define RF_TX_G3 0x22 + +#define RF_TX_BB1 0x23 +#define RF_T_METER 0x24 + +#define RF_SYN_G1 0x25 +#define RF_SYN_G2 0x26 +#define RF_SYN_G3 0x27 +#define RF_SYN_G4 0x28 +#define RF_SYN_G5 0x29 +#define RF_SYN_G6 0x2A +#define RF_SYN_G7 0x2B +#define RF_SYN_G8 0x2C + +#define RF_RCK_OS 0x30 +#define RF_TXPA_G1 0x31 +#define RF_TXPA_G2 0x32 +#define RF_TXPA_G3 0x33 + +#define BBBRESETB 0x100 +#define BGLOBALRESETB 0x200 +#define BOFDMTXSTART 0x4 +#define BCCKTXSTART 0x8 +#define BCRC32DEBUG 0x100 +#define BPMACLOOPBACK 0x10 +#define BTXLSIG 0xffffff +#define BOFDMTXRATE 0xf +#define BOFDMTXRESERVED 0x10 +#define BOFDMTXLENGTH 0x1ffe0 +#define BOFDMTXPARITY 0x20000 +#define BTXHTSIG1 0xffffff +#define BTXHTMCSRATE 0x7f +#define BTXHTBW 0x80 +#define BTXHTLENGTH 0xffff00 +#define BTXHTSIG2 0xffffff +#define BTXHTSMOOTHING 0x1 +#define BTXHTSOUNDING 0x2 +#define BTXHTRESERVED 0x4 +#define BTXHTAGGREATION 0x8 +#define BTXHTSTBC 0x30 +#define BTXHTADVANCECODING 0x40 +#define BTXHTSHORTGI 0x80 +#define BTXHTNUMBERHT_LTF 0x300 +#define BTXHTCRC8 0x3fc00 +#define BCOUNTERRESET 0x10000 +#define BNUMOFOFDMTX 0xffff +#define BNUMOFCCKTX 0xffff0000 +#define BTXIDLEINTERVAL 0xffff +#define BOFDMSERVICE 0xffff0000 +#define BTXMACHEADER 0xffffffff +#define BTXDATAINIT 0xff +#define BTXHTMODE 0x100 +#define BTXDATATYPE 0x30000 +#define BTXRANDOMSEED 0xffffffff +#define BCCKTXPREAMBLE 0x1 +#define BCCKTXSFD 0xffff0000 +#define BCCKTXSIG 0xff +#define BCCKTXSERVICE 0xff00 +#define BCCKLENGTHEXT 0x8000 +#define BCCKTXLENGHT 0xffff0000 +#define BCCKTXCRC16 0xffff +#define BCCKTXSTATUS 0x1 +#define BOFDMTXSTATUS 0x2 +#define IS_BB_REG_OFFSET_92S(_Offset) \ + ((_Offset >= 0x800) && (_Offset <= 0xfff)) + +#define BRFMOD 0x1 +#define BJAPANMODE 0x2 +#define BCCKTXSC 0x30 +#define BCCKEN 0x1000000 +#define BOFDMEN 0x2000000 + +#define BOFDMRXADCPHASE 0x10000 +#define BOFDMTXDACPHASE 0x40000 +#define BXATXAGC 0x3f + +#define BXBTXAGC 0xf00 +#define BXCTXAGC 0xf000 +#define BXDTXAGC 0xf0000 + +#define BPASTART 0xf0000000 +#define BTRSTART 0x00f00000 +#define BRFSTART 0x0000f000 +#define BBBSTART 0x000000f0 +#define BBBCCKSTART 0x0000000f +#define BPAEND 0xf +#define BTREND 0x0f000000 +#define BRFEND 0x000f0000 +#define BCCAMASK 0x000000f0 +#define BR2RCCAMASK 0x00000f00 +#define BHSSI_R2TDELAY 0xf8000000 +#define BHSSI_T2RDELAY 0xf80000 +#define BCONTXHSSI 0x400 +#define BIGFROMCCK 0x200 +#define BAGCADDRESS 0x3f +#define BRXHPTX 0x7000 +#define BRXHP2RX 0x38000 +#define BRXHPCCKINI 0xc0000 +#define BAGCTXCODE 0xc00000 +#define BAGCRXCODE 0x300000 + +#define B3WIREDATALENGTH 0x800 +#define B3WIREADDREAALENGTH 0x400 + +#define B3WIRERFPOWERDOWN 0x1 +#define B5GPAPEPOLARITY 0x40000000 +#define B2GPAPEPOLARITY 0x80000000 +#define BRFSW_TXDEFAULTANT 0x3 +#define BRFSW_TXOPTIONANT 0x30 +#define BRFSW_RXDEFAULTANT 0x300 +#define BRFSW_RXOPTIONANT 0x3000 +#define BRFSI_3WIREDATA 0x1 +#define BRFSI_3WIRECLOCK 0x2 +#define BRFSI_3WIRELOAD 0x4 +#define BRFSI_3WIRERW 0x8 +#define BRFSI_3WIRE 0xf + +#define BRFSI_RFENV 0x10 + +#define BRFSI_TRSW 0x20 +#define BRFSI_TRSWB 0x40 +#define BRFSI_ANTSW 0x100 +#define BRFSI_ANTSWB 0x200 +#define BRFSI_PAPE 0x400 +#define BRFSI_PAPE5G 0x800 +#define BBANDSELECT 0x1 +#define BHTSIG2_GI 0x80 +#define BHTSIG2_SMOOTHING 0x01 +#define BHTSIG2_SOUNDING 0x02 +#define BHTSIG2_AGGREATON 0x08 +#define BHTSIG2_STBC 0x30 +#define BHTSIG2_ADVCODING 0x40 +#define BHTSIG2_NUMOFHTLTF 0x300 +#define BHTSIG2_CRC8 0x3fc +#define BHTSIG1_MCS 0x7f +#define BHTSIG1_BANDWIDTH 0x80 +#define BHTSIG1_HTLENGTH 0xffff +#define BLSIG_RATE 0xf +#define BLSIG_RESERVED 0x10 +#define BLSIG_LENGTH 0x1fffe +#define BLSIG_PARITY 0x20 +#define BCCKRXPHASE 0x4 + +#define BLSSIREADADDRESS 0x7f800000 +#define BLSSIREADEDGE 0x80000000 + +#define BLSSIREADBACKDATA 0xfffff + +#define BLSSIREADOKFLAG 0x1000 +#define BCCKSAMPLERATE 0x8 +#define BREGULATOR0STANDBY 0x1 +#define BREGULATORPLLSTANDBY 0x2 +#define BREGULATOR1STANDBY 0x4 +#define BPLLPOWERUP 0x8 +#define BDPLLPOWERUP 0x10 +#define BDA10POWERUP 0x20 +#define BAD7POWERUP 0x200 +#define BDA6POWERUP 0x2000 +#define BXTALPOWERUP 0x4000 +#define B40MDCLKPOWERUP 0x8000 +#define BDA6DEBUGMODE 0x20000 +#define BDA6SWING 0x380000 + +#define BADCLKPHASE 0x4000000 +#define B80MCLKDELAY 0x18000000 +#define BAFEWATCHDOGENABLE 0x20000000 + +#define BXTALCAP01 0xc0000000 +#define BXTALCAP23 0x3 +#define BXTALCAP92X 0x0f000000 +#define BXTALCAP 0x0f000000 + +#define BINTDIFCLKENABLE 0x400 +#define BEXTSIGCLKENABLE 0x800 +#define BBANDGAP_MBIAS_POWERUP 0x10000 +#define BAD11SH_GAIN 0xc0000 +#define BAD11NPUT_RANGE 0x700000 +#define BAD110P_CURRENT 0x3800000 +#define BLPATH_LOOPBACK 0x4000000 +#define BQPATH_LOOPBACK 0x8000000 +#define BAFE_LOOPBACK 0x10000000 +#define BDA10_SWING 0x7e0 +#define BDA10_REVERSE 0x800 +#define BDA_CLK_SOURCE 0x1000 +#define BDA7INPUT_RANGE 0x6000 +#define BDA7_GAIN 0x38000 +#define BDA7OUTPUT_CM_MODE 0x40000 +#define BDA7INPUT_CM_MODE 0x380000 +#define BDA7CURRENT 0xc00000 +#define BREGULATOR_ADJUST 0x7000000 +#define BAD11POWERUP_ATTX 0x1 +#define BDA10PS_ATTX 0x10 +#define BAD11POWERUP_ATRX 0x100 +#define BDA10PS_ATRX 0x1000 +#define BCCKRX_AGC_FORMAT 0x200 +#define BPSDFFT_SAMPLE_POINT 0xc000 +#define BPSD_AVERAGE_NUM 0x3000 +#define BIQPATH_CONTROL 0xc00 +#define BPSD_FREQ 0x3ff +#define BPSD_ANTENNA_PATH 0x30 +#define BPSD_IQ_SWITCH 0x40 +#define BPSD_RX_TRIGGER 0x400000 +#define BPSD_TX_TRIGGER 0x80000000 +#define BPSD_SINE_TONE_SCALE 0x7f000000 +#define BPSD_REPORT 0xffff + +#define BOFDM_TXSC 0x30000000 +#define BCCK_TXON 0x1 +#define BOFDM_TXON 0x2 +#define BDEBUG_PAGE 0xfff +#define BDEBUG_ITEM 0xff +#define BANTL 0x10 +#define BANT_NONHT 0x100 +#define BANT_HT1 0x1000 +#define BANT_HT2 0x10000 +#define BANT_HT1S1 0x100000 +#define BANT_NONHTS1 0x1000000 + +#define BCCK_BBMODE 0x3 +#define BCCK_TXPOWERSAVING 0x80 +#define BCCK_RXPOWERSAVING 0x40 + +#define BCCK_SIDEBAND 0x10 + +#define BCCK_SCRAMBLE 0x8 +#define BCCK_ANTDIVERSITY 0x8000 +#define BCCK_CARRIER_RECOVERY 0x4000 +#define BCCK_TXRATE 0x3000 +#define BCCK_DCCANCEL 0x0800 +#define BCCK_ISICANCEL 0x0400 +#define BCCK_MATCH_FILTER 0x0200 +#define BCCK_EQUALIZER 0x0100 +#define BCCK_PREAMBLE_DETECT 0x800000 +#define BCCK_FAST_FALSECCA 0x400000 +#define BCCK_CH_ESTSTART 0x300000 +#define BCCK_CCA_COUNT 0x080000 +#define BCCK_CS_LIM 0x070000 +#define BCCK_BIST_MODE 0x80000000 +#define BCCK_CCAMASK 0x40000000 +#define BCCK_TX_DAC_PHASE 0x4 +#define BCCK_RX_ADC_PHASE 0x20000000 +#define BCCKR_CP_MODE 0x0100 +#define BCCK_TXDC_OFFSET 0xf0 +#define BCCK_RXDC_OFFSET 0xf +#define BCCK_CCA_MODE 0xc000 +#define BCCK_FALSECS_LIM 0x3f00 +#define BCCK_CS_RATIO 0xc00000 +#define BCCK_CORGBIT_SEL 0x300000 +#define BCCK_PD_LIM 0x0f0000 +#define BCCK_NEWCCA 0x80000000 +#define BCCK_RXHP_OF_IG 0x8000 +#define BCCK_RXIG 0x7f00 +#define BCCK_LNA_POLARITY 0x800000 +#define BCCK_RX1ST_BAIN 0x7f0000 +#define BCCK_RF_EXTEND 0x20000000 +#define BCCK_RXAGC_SATLEVEL 0x1f000000 +#define BCCK_RXAGC_SATCOUNT 0xe0 +#define bCCKRxRFSettle 0x1f +#define BCCK_FIXED_RXAGC 0x8000 +#define BCCK_ANTENNA_POLARITY 0x2000 +#define BCCK_TXFILTER_TYPE 0x0c00 +#define BCCK_RXAGC_REPORTTYPE 0x0300 +#define BCCK_RXDAGC_EN 0x80000000 +#define BCCK_RXDAGC_PERIOD 0x20000000 +#define BCCK_RXDAGC_SATLEVEL 0x1f000000 +#define BCCK_TIMING_RECOVERY 0x800000 +#define BCCK_TXC0 0x3f0000 +#define BCCK_TXC1 0x3f000000 +#define BCCK_TXC2 0x3f +#define BCCK_TXC3 0x3f00 +#define BCCK_TXC4 0x3f0000 +#define BCCK_TXC5 0x3f000000 +#define BCCK_TXC6 0x3f +#define BCCK_TXC7 0x3f00 +#define BCCK_DEBUGPORT 0xff0000 +#define BCCK_DAC_DEBUG 0x0f000000 +#define BCCK_FALSEALARM_ENABLE 0x8000 +#define BCCK_FALSEALARM_READ 0x4000 +#define BCCK_TRSSI 0x7f +#define BCCK_RXAGC_REPORT 0xfe +#define BCCK_RXREPORT_ANTSEL 0x80000000 +#define BCCK_RXREPORT_MFOFF 0x40000000 +#define BCCK_RXREPORT_SQLOSS 0x20000000 +#define BCCK_RXREPORT_PKTLOSS 0x10000000 +#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 +#define BCCK_RXREPORT_RATEERROR 0x04000000 +#define BCCK_RXREPORT_RXRATE 0x03000000 +#define BCCK_RXFA_COUNTER_LOWER 0xff +#define BCCK_RXFA_COUNTER_UPPER 0xff000000 +#define BCCK_RXHPAGC_START 0xe000 +#define BCCK_RXHPAGC_FINAL 0x1c00 +#define BCCK_RXFALSEALARM_ENABLE 0x8000 +#define BCCK_FACOUNTER_FREEZE 0x4000 +#define BCCK_TXPATH_SEL 0x10000000 +#define BCCK_DEFAULT_RXPATH 0xc000000 +#define BCCK_OPTION_RXPATH 0x3000000 + +#define BNUM_OFSTF 0x3 +#define BSHIFT_L 0xc0 +#define BGI_TH 0xc +#define BRXPATH_A 0x1 +#define BRXPATH_B 0x2 +#define BRXPATH_C 0x4 +#define BRXPATH_D 0x8 +#define BTXPATH_A 0x1 +#define BTXPATH_B 0x2 +#define BTXPATH_C 0x4 +#define BTXPATH_D 0x8 +#define BTRSSI_FREQ 0x200 +#define BADC_BACKOFF 0x3000 +#define BDFIR_BACKOFF 0xc000 +#define BTRSSI_LATCH_PHASE 0x10000 +#define BRX_LDC_OFFSET 0xff +#define BRX_QDC_OFFSET 0xff00 +#define BRX_DFIR_MODE 0x1800000 +#define BRX_DCNF_TYPE 0xe000000 +#define BRXIQIMB_A 0x3ff +#define BRXIQIMB_B 0xfc00 +#define BRXIQIMB_C 0x3f0000 +#define BRXIQIMB_D 0xffc00000 +#define BDC_DC_NOTCH 0x60000 +#define BRXNB_NOTCH 0x1f000000 +#define BPD_TH 0xf +#define BPD_TH_OPT2 0xc000 +#define BPWED_TH 0x700 +#define BIFMF_WIN_L 0x800 +#define BPD_OPTION 0x1000 +#define BMF_WIN_L 0xe000 +#define BBW_SEARCH_L 0x30000 +#define BWIN_ENH_L 0xc0000 +#define BBW_TH 0x700000 +#define BED_TH2 0x3800000 +#define BBW_OPTION 0x4000000 +#define BRADIO_TH 0x18000000 +#define BWINDOW_L 0xe0000000 +#define BSBD_OPTION 0x1 +#define BFRAME_TH 0x1c +#define BFS_OPTION 0x60 +#define BDC_SLOPE_CHECK 0x80 +#define BFGUARD_COUNTER_DC_L 0xe00 +#define BFRAME_WEIGHT_SHORT 0x7000 +#define BSUB_TUNE 0xe00000 +#define BFRAME_DC_LENGTH 0xe000000 +#define BSBD_START_OFFSET 0x30000000 +#define BFRAME_TH_2 0x7 +#define BFRAME_GI2_TH 0x38 +#define BGI2_SYNC_EN 0x40 +#define BSARCH_SHORT_EARLY 0x300 +#define BSARCH_SHORT_LATE 0xc00 +#define BSARCH_GI2_LATE 0x70000 +#define BCFOANTSUM 0x1 +#define BCFOACC 0x2 +#define BCFOSTARTOFFSET 0xc +#define BCFOLOOPBACK 0x70 +#define BCFOSUMWEIGHT 0x80 +#define BDAGCENABLE 0x10000 +#define BTXIQIMB_A 0x3ff +#define BTXIQIMB_b 0xfc00 +#define BTXIQIMB_C 0x3f0000 +#define BTXIQIMB_D 0xffc00000 +#define BTXIDCOFFSET 0xff +#define BTXIQDCOFFSET 0xff00 +#define BTXDFIRMODE 0x10000 +#define BTXPESUDO_NOISEON 0x4000000 +#define BTXPESUDO_NOISE_A 0xff +#define BTXPESUDO_NOISE_B 0xff00 +#define BTXPESUDO_NOISE_C 0xff0000 +#define BTXPESUDO_NOISE_D 0xff000000 +#define BCCA_DROPOPTION 0x20000 +#define BCCA_DROPTHRES 0xfff00000 +#define BEDCCA_H 0xf +#define BEDCCA_L 0xf0 +#define BLAMBDA_ED 0x300 +#define BRX_INITIALGAIN 0x7f +#define BRX_ANTDIV_EN 0x80 +#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 +#define BRX_HIGHPOWER_FLOW 0x8000 +#define BRX_AGC_FREEZE_THRES 0xc0000 +#define BRX_FREEZESTEP_AGC1 0x300000 +#define BRX_FREEZESTEP_AGC2 0xc00000 +#define BRX_FREEZESTEP_AGC3 0x3000000 +#define BRX_FREEZESTEP_AGC0 0xc000000 +#define BRXRSSI_CMP_EN 0x10000000 +#define BRXQUICK_AGCEN 0x20000000 +#define BRXAGC_FREEZE_THRES_MODE 0x40000000 +#define BRX_OVERFLOW_CHECKTYPE 0x80000000 +#define BRX_AGCSHIFT 0x7f +#define BTRSW_TRI_ONLY 0x80 +#define BPOWER_THRES 0x300 +#define BRXAGC_EN 0x1 +#define BRXAGC_TOGETHER_EN 0x2 +#define BRXAGC_MIN 0x4 +#define BRXHP_INI 0x7 +#define BRXHP_TRLNA 0x70 +#define BRXHP_RSSI 0x700 +#define BRXHP_BBP1 0x7000 +#define BRXHP_BBP2 0x70000 +#define BRXHP_BBP3 0x700000 +#define BRSSI_H 0x7f0000 +#define BRSSI_GEN 0x7f000000 +#define BRXSETTLE_TRSW 0x7 +#define BRXSETTLE_LNA 0x38 +#define BRXSETTLE_RSSI 0x1c0 +#define BRXSETTLE_BBP 0xe00 +#define BRXSETTLE_RXHP 0x7000 +#define BRXSETTLE_ANTSW_RSSI 0x38000 +#define BRXSETTLE_ANTSW 0xc0000 +#define BRXPROCESS_TIME_DAGC 0x300000 +#define BRXSETTLE_HSSI 0x400000 +#define BRXPROCESS_TIME_BBPPW 0x800000 +#define BRXANTENNA_POWER_SHIFT 0x3000000 +#define BRSSI_TABLE_SELECT 0xc000000 +#define BRXHP_FINAL 0x7000000 +#define BRXHPSETTLE_BBP 0x7 +#define BRXHTSETTLE_HSSI 0x8 +#define BRXHTSETTLE_RXHP 0x70 +#define BRXHTSETTLE_BBPPW 0x80 +#define BRXHTSETTLE_IDLE 0x300 +#define BRXHTSETTLE_RESERVED 0x1c00 +#define BRXHT_RXHP_EN 0x8000 +#define BRXAGC_FREEZE_THRES 0x30000 +#define BRXAGC_TOGETHEREN 0x40000 +#define BRXHTAGC_MIN 0x80000 +#define BRXHTAGC_EN 0x100000 +#define BRXHTDAGC_EN 0x200000 +#define BRXHT_RXHP_BBP 0x1c00000 +#define BRXHT_RXHP_FINAL 0xe0000000 +#define BRXPW_RADIO_TH 0x3 +#define BRXPW_RADIO_EN 0x4 +#define BRXMF_HOLD 0x3800 +#define BRXPD_DELAY_TH1 0x38 +#define BRXPD_DELAY_TH2 0x1c0 +#define BRXPD_DC_COUNT_MAX 0x600 +#define BRXPD_DELAY_TH 0x8000 +#define BRXPROCESS_DELAY 0xf0000 +#define BRXSEARCHRANGE_GI2_EARLY 0x700000 +#define BRXFRAME_FUARD_COUNTER_L 0x3800000 +#define BRXSGI_GUARD_L 0xc000000 +#define BRXSGI_SEARCH_L 0x30000000 +#define BRXSGI_TH 0xc0000000 +#define BDFSCNT0 0xff +#define BDFSCNT1 0xff00 +#define BDFSFLAG 0xf0000 +#define BMF_WEIGHT_SUM 0x300000 +#define BMINIDX_TH 0x7f000000 +#define BDAFORMAT 0x40000 +#define BTXCH_EMU_ENABLE 0x01000000 +#define BTRSW_ISOLATION_A 0x7f +#define BTRSW_ISOLATION_B 0x7f00 +#define BTRSW_ISOLATION_C 0x7f0000 +#define BTRSW_ISOLATION_D 0x7f000000 +#define BEXT_LNA_GAIN 0x7c00 + +#define BSTBC_EN 0x4 +#define BANTENNA_MAPPING 0x10 +#define BNSS 0x20 +#define BCFO_ANTSUM_ID 0x200 +#define BPHY_COUNTER_RESET 0x8000000 +#define BCFO_REPORT_GET 0x4000000 +#define BOFDM_CONTINUE_TX 0x10000000 +#define BOFDM_SINGLE_CARRIER 0x20000000 +#define BOFDM_SINGLE_TONE 0x40000000 +#define BHT_DETECT 0x100 +#define BCFOEN 0x10000 +#define BCFOVALUE 0xfff00000 +#define BSIGTONE_RE 0x3f +#define BSIGTONE_IM 0x7f00 +#define BCOUNTER_CCA 0xffff +#define BCOUNTER_PARITYFAIL 0xffff0000 +#define BCOUNTER_RATEILLEGAL 0xffff +#define BCOUNTER_CRC8FAIL 0xffff0000 +#define BCOUNTER_MCSNOSUPPORT 0xffff +#define BCOUNTER_FASTSYNC 0xffff +#define BSHORTCFO 0xfff +#define BSHORTCFOT_LENGTH 12 +#define BSHORTCFOF_LENGTH 11 +#define BLONGCFO 0x7ff +#define BLONGCFOT_LENGTH 11 +#define BLONGCFOF_LENGTH 11 +#define BTAILCFO 0x1fff +#define BTAILCFOT_LENGTH 13 +#define BTAILCFOF_LENGTH 12 +#define BNOISE_EN_PWDB 0xffff +#define BCC_POWER_DB 0xffff0000 +#define BMOISE_PWDB 0xffff +#define BPOWERMEAST_LENGTH 10 +#define BPOWERMEASF_LENGTH 3 +#define BRX_HT_BW 0x1 +#define BRXSC 0x6 +#define BRX_HT 0x8 +#define BNB_INTF_DET_ON 0x1 +#define BINTF_WIN_LEN_CFG 0x30 +#define BNB_INTF_TH_CFG 0x1c0 +#define BRFGAIN 0x3f +#define BTABLESEL 0x40 +#define BTRSW 0x80 +#define BRXSNR_A 0xff +#define BRXSNR_B 0xff00 +#define BRXSNR_C 0xff0000 +#define BRXSNR_D 0xff000000 +#define BSNR_EVMT_LENGTH 8 +#define BSNR_EVMF_LENGTH 1 +#define BCSI1ST 0xff +#define BCSI2ND 0xff00 +#define BRXEVM1ST 0xff0000 +#define BRXEVM2ND 0xff000000 +#define BSIGEVM 0xff +#define BPWDB 0xff00 +#define BSGIEN 0x10000 + +#define BSFACTOR_QMA1 0xf +#define BSFACTOR_QMA2 0xf0 +#define BSFACTOR_QMA3 0xf00 +#define BSFACTOR_QMA4 0xf000 +#define BSFACTOR_QMA5 0xf0000 +#define BSFACTOR_QMA6 0xf0000 +#define BSFACTOR_QMA7 0xf00000 +#define BSFACTOR_QMA8 0xf000000 +#define BSFACTOR_QMA9 0xf0000000 +#define BCSI_SCHEME 0x100000 + +#define BNOISE_LVL_TOP_SET 0x3 +#define BCHSMOOTH 0x4 +#define BCHSMOOTH_CFG1 0x38 +#define BCHSMOOTH_CFG2 0x1c0 +#define BCHSMOOTH_CFG3 0xe00 +#define BCHSMOOTH_CFG4 0x7000 +#define BMRCMODE 0x800000 +#define BTHEVMCFG 0x7000000 + +#define BLOOP_FIT_TYPE 0x1 +#define BUPD_CFO 0x40 +#define BUPD_CFO_OFFDATA 0x80 +#define BADV_UPD_CFO 0x100 +#define BADV_TIME_CTRL 0x800 +#define BUPD_CLKO 0x1000 +#define BFC 0x6000 +#define BTRACKING_MODE 0x8000 +#define BPHCMP_ENABLE 0x10000 +#define BUPD_CLKO_LTF 0x20000 +#define BCOM_CH_CFO 0x40000 +#define BCSI_ESTI_MODE 0x80000 +#define BADV_UPD_EQZ 0x100000 +#define BUCHCFG 0x7000000 +#define BUPDEQZ 0x8000000 + +#define BRX_PESUDO_NOISE_ON 0x20000000 +#define BRX_PESUDO_NOISE_A 0xff +#define BRX_PESUDO_NOISE_B 0xff00 +#define BRX_PESUDO_NOISE_C 0xff0000 +#define BRX_PESUDO_NOISE_D 0xff000000 +#define BRX_PESUDO_NOISESTATE_A 0xffff +#define BRX_PESUDO_NOISESTATE_B 0xffff0000 +#define BRX_PESUDO_NOISESTATE_C 0xffff +#define BRX_PESUDO_NOISESTATE_D 0xffff0000 + +#define BZEBRA1_HSSIENABLE 0x8 +#define BZEBRA1_TRXCONTROL 0xc00 +#define BZEBRA1_TRXGAINSETTING 0x07f +#define BZEBRA1_RXCOUNTER 0xc00 +#define BZEBRA1_TXCHANGEPUMP 0x38 +#define BZEBRA1_RXCHANGEPUMP 0x7 +#define BZEBRA1_CHANNEL_NUM 0xf80 +#define BZEBRA1_TXLPFBW 0x400 +#define BZEBRA1_RXLPFBW 0x600 + +#define BRTL8256REG_MODE_CTRL1 0x100 +#define BRTL8256REG_MODE_CTRL0 0x40 +#define BRTL8256REG_TXLPFBW 0x18 +#define BRTL8256REG_RXLPFBW 0x600 + +#define BRTL8258_TXLPFBW 0xc +#define BRTL8258_RXLPFBW 0xc00 +#define BRTL8258_RSSILPFBW 0xc0 + +#define BBYTE0 0x1 +#define BBYTE1 0x2 +#define BBYTE2 0x4 +#define BBYTE3 0x8 +#define BWORD0 0x3 +#define BWORD1 0xc +#define BWORD 0xf + +#define BENABLE 0x1 +#define BDISABLE 0x0 + +#define LEFT_ANTENNA 0x0 +#define RIGHT_ANTENNA 0x1 + +#define TCHECK_TXSTATUS 500 +#define TUPDATE_RXCOUNTER 100 + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c new file mode 100644 index 000000000000..a9c406f33d0a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.c @@ -0,0 +1,509 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" + +static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw); + +void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff) | 0x0400); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + case HT_CHANNEL_WIDTH_20_40: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff)); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", bandwidth); + break; + } +} + +void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 tx_agc[2] = {0, 0}, tmpval; + bool turbo_scanoff = false; + u8 idx1, idx2; + u8 *ptr; + + if (rtlefuse->eeprom_regulatory != 0) + turbo_scanoff = true; + + if (mac->act_scanning) { + tx_agc[RF90_PATH_A] = 0x3f3f3f3f; + tx_agc[RF90_PATH_B] = 0x3f3f3f3f; + + if (turbo_scanoff) { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + } + } else { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + + if (rtlefuse->eeprom_regulatory == 0) { + tmpval = (rtlphy->mcs_offset[0][6]) + + (rtlphy->mcs_offset[0][7] << 8); + tx_agc[RF90_PATH_A] += tmpval; + + tmpval = (rtlphy->mcs_offset[0][14]) + + (rtlphy->mcs_offset[0][15] << 24); + tx_agc[RF90_PATH_B] += tmpval; + } + } + + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + ptr = (u8 *) (&(tx_agc[idx1])); + for (idx2 = 0; idx2 < 4; idx2++) { + if (*ptr > RF6052_MAX_TX_PWR) + *ptr = RF6052_MAX_TX_PWR; + ptr++; + } + } + + tmpval = tx_agc[RF90_PATH_A] & 0xff; + rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", + tmpval, RTXAGC_A_CCK1_MCS32); + + tmpval = tx_agc[RF90_PATH_A] >> 8; + + tmpval = tmpval & 0xff00ffff; + + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", + tmpval, RTXAGC_B_CCK11_A_CCK2_11); + + tmpval = tx_agc[RF90_PATH_B] >> 24; + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", + tmpval, RTXAGC_B_CCK11_A_CCK2_11); + + tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; + rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", + tmpval, RTXAGC_B_CCK1_55_MCS32); +} + +static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel, + u32 *ofdmbase, u32 *mcsbase) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 powerBase0, powerBase1; + u8 legacy_pwrdiff, ht20_pwrdiff; + u8 i, powerlevel[2]; + + for (i = 0; i < 2; i++) { + powerlevel[i] = ppowerlevel[i]; + legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; + powerBase0 = powerlevel[i] + legacy_pwrdiff; + + powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | + (powerBase0 << 8) | powerBase0; + *(ofdmbase + i) = powerBase0; + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [OFDM power base index rf(%c) = 0x%x]\n", + i == 0 ? 'A' : 'B', *(ofdmbase + i)); + } + + for (i = 0; i < 2; i++) { + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { + ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1]; + powerlevel[i] += ht20_pwrdiff; + } + powerBase1 = powerlevel[i]; + powerBase1 = (powerBase1 << 24) | + (powerBase1 << 16) | (powerBase1 << 8) | powerBase1; + + *(mcsbase + i) = powerBase1; + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [MCS power base index rf(%c) = 0x%x]\n", + i == 0 ? 'A' : 'B', *(mcsbase + i)); + } +} + +static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, + u8 channel, u8 index, + u32 *powerBase0, + u32 *powerBase1, + u32 *p_outwriteval) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 i, chnlgroup = 0, pwr_diff_limit[4]; + u32 writeVal, customer_limit, rf; + + for (rf = 0; rf < 2; rf++) { + switch (rtlefuse->eeprom_regulatory) { + case 0: + chnlgroup = 0; + + writeVal = rtlphy->mcs_offset[chnlgroup][index + + (rf ? 8 : 0)] + + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeVal(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeVal); + break; + case 1: + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + writeVal = ((index < 2) ? powerBase0[rf] : + powerBase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Realtek regulatory, 40MHz, writeVal(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeVal); + } else { + if (rtlphy->pwrgroup_cnt == 1) + chnlgroup = 0; + if (rtlphy->pwrgroup_cnt >= 3) { + if (channel <= 3) + chnlgroup = 0; + else if (channel >= 4 && channel <= 9) + chnlgroup = 1; + else if (channel > 9) + chnlgroup = 2; + if (rtlphy->pwrgroup_cnt == 4) + chnlgroup++; + } + + writeVal = rtlphy->mcs_offset[chnlgroup] + [index + (rf ? 8 : 0)] + ((index < 2) ? + powerBase0[rf] : + powerBase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeVal); + } + break; + case 2: + writeVal = + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Better regulatory, writeVal(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeVal); + break; + case 3: + chnlgroup = 0; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 40MHz rf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', + rtlefuse->pwrgroup_ht40[rf][channel - + 1]); + } else { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 20MHz rf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', + rtlefuse->pwrgroup_ht20[rf][channel - + 1]); + } + for (i = 0; i < 4; i++) { + pwr_diff_limit[i] = (u8) ((rtlphy->mcs_offset + [chnlgroup][index + + (rf ? 8 : 0)] & (0x7f << (i * 8))) >> + (i * 8)); + + if (rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20_40) { + if (pwr_diff_limit[i] > + rtlefuse-> + pwrgroup_ht40[rf][channel - 1]) + pwr_diff_limit[i] = + rtlefuse->pwrgroup_ht40[rf] + [channel - 1]; + } else { + if (pwr_diff_limit[i] > + rtlefuse-> + pwrgroup_ht20[rf][channel - 1]) + pwr_diff_limit[i] = + rtlefuse->pwrgroup_ht20[rf] + [channel - 1]; + } + } + + customer_limit = (pwr_diff_limit[3] << 24) | + (pwr_diff_limit[2] << 16) | + (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer's limit rf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', customer_limit); + + writeVal = customer_limit + + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer, writeVal rf(%c)= 0x%x\n", + rf == 0 ? 'A' : 'B', writeVal); + break; + default: + chnlgroup = 0; + writeVal = rtlphy->mcs_offset[chnlgroup] + [index + (rf ? 8 : 0)] + + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeVal rf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeVal); + break; + } + + if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) + writeVal = writeVal - 0x06060606; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_BT2) + writeVal = writeVal - 0x0c0c0c0c; + *(p_outwriteval + rf) = writeVal; + } +} + +static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, + u8 index, u32 *pValue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + u16 regoffset_a[6] = { + RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, + RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, + RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 + }; + u16 regoffset_b[6] = { + RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, + RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, + RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 + }; + u8 i, rf, pwr_val[4]; + u32 writeVal; + u16 regoffset; + + for (rf = 0; rf < 2; rf++) { + writeVal = pValue[rf]; + for (i = 0; i < 4; i++) { + pwr_val[i] = (u8) ((writeVal & (0x7f << + (i * 8))) >> (i * 8)); + + if (pwr_val[i] > RF6052_MAX_TX_PWR) + pwr_val[i] = RF6052_MAX_TX_PWR; + } + writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) | + (pwr_val[1] << 8) | pwr_val[0]; + + if (rf == 0) + regoffset = regoffset_a[index]; + else + regoffset = regoffset_b[index]; + rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Set 0x%x = %08x\n", regoffset, writeVal); + + if (((get_rf_type(rtlphy) == RF_2T2R) && + (regoffset == RTXAGC_A_MCS15_MCS12 || + regoffset == RTXAGC_B_MCS15_MCS12)) || + ((get_rf_type(rtlphy) != RF_2T2R) && + (regoffset == RTXAGC_A_MCS07_MCS04 || + regoffset == RTXAGC_B_MCS07_MCS04))) { + + writeVal = pwr_val[3]; + if (regoffset == RTXAGC_A_MCS15_MCS12 || + regoffset == RTXAGC_A_MCS07_MCS04) + regoffset = 0xc90; + if (regoffset == RTXAGC_B_MCS15_MCS12 || + regoffset == RTXAGC_B_MCS07_MCS04) + regoffset = 0xc98; + + for (i = 0; i < 3; i++) { + writeVal = (writeVal > 6) ? (writeVal - 6) : 0; + rtl_write_byte(rtlpriv, (u32) (regoffset + i), + (u8) writeVal); + } + } + } +} + +void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel) +{ + u32 writeVal[2], powerBase0[2], powerBase1[2]; + u8 index; + + rtl92c_phy_get_power_base(hw, ppowerlevel, + channel, &powerBase0[0], &powerBase1[0]); + + for (index = 0; index < 6; index++) { + _rtl92c_get_txpower_writeval_by_regulatory(hw, + channel, index, + &powerBase0[0], + &powerBase1[0], + &writeVal[0]); + + _rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]); + } +} + +bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + if (rtlphy->rf_type == RF_1T1R) + rtlphy->num_total_rfpath = 1; + else + rtlphy->num_total_rfpath = 2; + + return _rtl92ce_phy_rf6052_config_parafile(hw); + +} + +static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 u4_regvalue = 0; + u8 rfpath; + bool rtstatus = true; + struct bb_reg_def *pphyreg; + + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + + pphyreg = &rtlphy->phyreg_def[rfpath]; + + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV); + break; + case RF90_PATH_B: + case RF90_PATH_D: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16); + break; + } + + rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, + B3WIREADDREAALENGTH, 0x0); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); + udelay(1); + + switch (rfpath) { + case RF90_PATH_A: + rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_B: + rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_C: + break; + case RF90_PATH_D: + break; + } + + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV, u4_regvalue); + break; + case RF90_PATH_B: + case RF90_PATH_D: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16, u4_regvalue); + break; + } + + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio[%d] Fail!!\n", rfpath); + return false; + } + + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n"); + return rtstatus; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h new file mode 100644 index 000000000000..ebd72cae10b6 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/rf.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_RF_H__ +#define __RTL92C_RF_H__ + +#define RF6052_MAX_TX_PWR 0x3F +#define RF6052_MAX_PATH 2 + +void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth); +void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); +bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c new file mode 100644 index 000000000000..de6cb6c3a48c --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c @@ -0,0 +1,394 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../core.h" +#include "../pci.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "../rtl8192c/dm_common.h" +#include "../rtl8192c/fw_common.h" +#include "../rtl8192c/phy_common.h" +#include "hw.h" +#include "rf.h" +#include "sw.h" +#include "trx.h" +#include "led.h" + +#include + +static void rtl92c_init_aspm_vars(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /* + * ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + * */ + rtlpci->const_pci_aspm = 3; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /* + * In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 0; + + /* + * This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 1; +} + +int rtl92c_init_sw_vars(struct ieee80211_hw *hw) +{ + int err; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + rtl8192ce_bt_reg_init(hw); + + rtlpriv->dm.dm_initialgain_enable = true; + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.disable_framebursting = false; + rtlpriv->dm.thermalvalue = 0; + rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13); + + /* compatible 5G band 88ce just 2.4G band & smsp */ + rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; + rtlpriv->rtlhal.bandset = BAND_ON_2_4G; + rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; + + rtlpci->receive_config = (RCR_APPFCS | + RCR_AMF | + RCR_ADF | + RCR_APP_MIC | + RCR_APP_ICV | + RCR_AICV | + RCR_ACRC32 | + RCR_AB | + RCR_AM | + RCR_APM | + RCR_APP_PHYST_RXFF | RCR_HTC_LOC_CTRL | 0); + + rtlpci->irq_mask[0] = + (u32) (IMR_ROK | + IMR_VODOK | + IMR_VIDOK | + IMR_BEDOK | + IMR_BKDOK | + IMR_MGNTDOK | + IMR_HIGHDOK | IMR_BDOK | IMR_RDU | IMR_RXFOVW | 0); + + 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; + rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; + if (!rtlpriv->psc.inactiveps) + pr_info("rtl8192ce: Power Save off (module option)\n"); + if (!rtlpriv->psc.fwctrl_lps) + pr_info("rtl8192ce: FW Power Save off (module option)\n"); + rtlpriv->psc.reg_fwctrl_lps = 3; + rtlpriv->psc.reg_max_lps_awakeintvl = 5; + /* for ASPM, you can close aspm through + * set const_support_pciaspm = 0 */ + rtl92c_init_aspm_vars(hw); + + if (rtlpriv->psc.reg_fwctrl_lps == 1) + rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 2) + rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 3) + rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(0x4000); + if (!rtlpriv->rtlhal.pfirmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't alloc buffer for fw\n"); + return 1; + } + + /* request fw */ + if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && + !IS_92C_SERIAL(rtlhal->version)) + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; + else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; + + rtlpriv->max_fw_size = 0x4000; + pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); + err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, + rtlpriv->io.dev, GFP_KERNEL, hw, + rtl_fw_cb); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to request firmware!\n"); + return 1; + } + + return 0; +} + +void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.pfirmware) { + vfree(rtlpriv->rtlhal.pfirmware); + rtlpriv->rtlhal.pfirmware = NULL; + } +} + +static struct rtl_hal_ops rtl8192ce_hal_ops = { + .init_sw_vars = rtl92c_init_sw_vars, + .deinit_sw_vars = rtl92c_deinit_sw_vars, + .read_eeprom_info = rtl92ce_read_eeprom_info, + .interrupt_recognized = rtl92ce_interrupt_recognized, + .hw_init = rtl92ce_hw_init, + .hw_disable = rtl92ce_card_disable, + .hw_suspend = rtl92ce_suspend, + .hw_resume = rtl92ce_resume, + .enable_interrupt = rtl92ce_enable_interrupt, + .disable_interrupt = rtl92ce_disable_interrupt, + .set_network_type = rtl92ce_set_network_type, + .set_chk_bssid = rtl92ce_set_check_bssid, + .set_qos = rtl92ce_set_qos, + .set_bcn_reg = rtl92ce_set_beacon_related_registers, + .set_bcn_intv = rtl92ce_set_beacon_interval, + .update_interrupt_mask = rtl92ce_update_interrupt_mask, + .get_hw_reg = rtl92ce_get_hw_reg, + .set_hw_reg = rtl92ce_set_hw_reg, + .update_rate_tbl = rtl92ce_update_hal_rate_tbl, + .fill_tx_desc = rtl92ce_tx_fill_desc, + .fill_tx_cmddesc = rtl92ce_tx_fill_cmddesc, + .query_rx_desc = rtl92ce_rx_query_desc, + .set_channel_access = rtl92ce_update_channel_access_setting, + .radio_onoff_checking = rtl92ce_gpio_radio_on_off_checking, + .set_bw_mode = rtl92c_phy_set_bw_mode, + .switch_channel = rtl92c_phy_sw_chnl, + .dm_watchdog = rtl92c_dm_watchdog, + .scan_operation_backup = rtl_phy_scan_operation_backup, + .set_rf_power_state = rtl92c_phy_set_rf_power_state, + .led_control = rtl92ce_led_control, + .set_desc = rtl92ce_set_desc, + .get_desc = rtl92ce_get_desc, + .is_tx_desc_closed = rtl92ce_is_tx_desc_closed, + .tx_polling = rtl92ce_tx_polling, + .enable_hw_sec = rtl92ce_enable_hw_security_config, + .set_key = rtl92ce_set_key, + .init_sw_leds = rtl92ce_init_sw_leds, + .get_bbreg = rtl92c_phy_query_bb_reg, + .set_bbreg = rtl92c_phy_set_bb_reg, + .set_rfreg = rtl92ce_phy_set_rf_reg, + .get_rfreg = rtl92c_phy_query_rf_reg, + .phy_rf6052_config = rtl92ce_phy_rf6052_config, + .phy_rf6052_set_cck_txpower = rtl92ce_phy_rf6052_set_cck_txpower, + .phy_rf6052_set_ofdm_txpower = rtl92ce_phy_rf6052_set_ofdm_txpower, + .config_bb_with_headerfile = _rtl92ce_phy_config_bb_with_headerfile, + .config_bb_with_pgheaderfile = _rtl92ce_phy_config_bb_with_pgheaderfile, + .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate, + .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback, + .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, + .get_btc_status = rtl_btc_status_false, +}; + +static struct rtl_mod_params rtl92ce_mod_params = { + .sw_crypto = false, + .inactiveps = true, + .swctrl_lps = false, + .fwctrl_lps = true, + .debug = DBG_EMERG, +}; + +static struct rtl_hal_cfg rtl92ce_hal_cfg = { + .bar_id = 2, + .write_readback = true, + .name = "rtl92c_pci", + .fw_name = "rtlwifi/rtl8192cfw.bin", + .ops = &rtl8192ce_hal_ops, + .mod_params = &rtl92ce_mod_params, + + .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, + .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, + .maps[SYS_CLK] = REG_SYS_CLKR, + .maps[MAC_RCR_AM] = AM, + .maps[MAC_RCR_AB] = AB, + .maps[MAC_RCR_ACRC32] = ACRC32, + .maps[MAC_RCR_ACF] = ACF, + .maps[MAC_RCR_AAP] = AAP, + .maps[MAC_HIMR] = REG_HIMR, + .maps[MAC_HIMRE] = REG_HIMRE, + + .maps[EFUSE_TEST] = REG_EFUSE_TEST, + .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_CLK] = 0, + .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_PWC_EV12V] = PWC_EV12V, + .maps[EFUSE_FEN_ELDR] = FEN_ELDR, + .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, + .maps[EFUSE_ANA8M] = EFUSE_ANA8M, + .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, + .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, + .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, + .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, + + .maps[RWCAM] = REG_CAMCMD, + .maps[WCAMI] = REG_CAMWRITE, + .maps[RCAMO] = REG_CAMREAD, + .maps[CAMDBG] = REG_CAMDBG, + .maps[SECR] = REG_SECCFG, + .maps[SEC_CAM_NONE] = CAM_NONE, + .maps[SEC_CAM_WEP40] = CAM_WEP40, + .maps[SEC_CAM_TKIP] = CAM_TKIP, + .maps[SEC_CAM_AES] = CAM_AES, + .maps[SEC_CAM_WEP104] = CAM_WEP104, + + .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, + .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, + .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, + .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, + .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, + .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, + .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, + .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, + .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, + .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, + .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, + .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, + .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, + .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, + .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, + .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, + + .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, + .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, + .maps[RTL_IMR_BCNINT] = IMR_BCNINT, + .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, + .maps[RTL_IMR_RDU] = IMR_RDU, + .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, + .maps[RTL_IMR_BDOK] = IMR_BDOK, + .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, + .maps[RTL_IMR_TBDER] = IMR_TBDER, + .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, + .maps[RTL_IMR_TBDOK] = IMR_TBDOK, + .maps[RTL_IMR_BKDOK] = IMR_BKDOK, + .maps[RTL_IMR_BEDOK] = IMR_BEDOK, + .maps[RTL_IMR_VIDOK] = IMR_VIDOK, + .maps[RTL_IMR_VODOK] = IMR_VODOK, + .maps[RTL_IMR_ROK] = IMR_ROK, + .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), + + .maps[RTL_RC_CCK_RATE1M] = DESC_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC_RATEMCS15, +}; + +static const struct pci_device_id rtl92ce_pci_ids[] = { + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8191, rtl92ce_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8178, rtl92ce_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8177, rtl92ce_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8176, rtl92ce_hal_cfg)}, + {}, +}; + +MODULE_DEVICE_TABLE(pci, rtl92ce_pci_ids); + +MODULE_AUTHOR("lizhaoming "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n PCI wireless"); +MODULE_FIRMWARE("rtlwifi/rtl8192cfw.bin"); +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(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); +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)"); + +static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); + +static struct pci_driver rtl92ce_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl92ce_pci_ids, + .probe = rtl_pci_probe, + .remove = rtl_pci_disconnect, + .driver.pm = &rtlwifi_pm_ops, +}; + +module_pci_driver(rtl92ce_driver); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h new file mode 100644 index 000000000000..d2367a5d0cf5 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CE_SW_H__ +#define __RTL92CE_SW_H__ + +int rtl92c_init_sw_vars(struct ieee80211_hw *hw); +void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw); +void rtl92c_init_var_map(struct ieee80211_hw *hw); +bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c new file mode 100644 index 000000000000..752f943a84ae --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.c @@ -0,0 +1,1224 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger + * + *****************************************************************************/ + +#include "table.h" + + +u32 RTL8192CEPHY_REG_2TARRAY[PHY_REG_2TARRAY_LENGTH] = { + 0x024, 0x0011800f, + 0x028, 0x00ffdb83, + 0x800, 0x80040002, + 0x804, 0x00000003, + 0x808, 0x0000fc00, + 0x80c, 0x0000000a, + 0x810, 0x10005388, + 0x814, 0x020c3d10, + 0x818, 0x02200385, + 0x81c, 0x00000000, + 0x820, 0x01000100, + 0x824, 0x00390004, + 0x828, 0x01000100, + 0x82c, 0x00390004, + 0x830, 0x27272727, + 0x834, 0x27272727, + 0x838, 0x27272727, + 0x83c, 0x27272727, + 0x840, 0x00010000, + 0x844, 0x00010000, + 0x848, 0x27272727, + 0x84c, 0x27272727, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x569a569a, + 0x85c, 0x0c1b25a4, + 0x860, 0x66e60230, + 0x864, 0x061f0130, + 0x868, 0x27272727, + 0x86c, 0x2b2b2b27, + 0x870, 0x07000700, + 0x874, 0x22184000, + 0x878, 0x08080808, + 0x87c, 0x00000000, + 0x880, 0xc0083070, + 0x884, 0x000004d5, + 0x888, 0x00000000, + 0x88c, 0xcc0000c0, + 0x890, 0x00000800, + 0x894, 0xfffffffe, + 0x898, 0x40302010, + 0x89c, 0x00706050, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90c, 0x81121313, + 0xa00, 0x00d047c8, + 0xa04, 0x80ff000c, + 0xa08, 0x8c838300, + 0xa0c, 0x2e68120f, + 0xa10, 0x9500bb78, + 0xa14, 0x11144028, + 0xa18, 0x00881117, + 0xa1c, 0x89140f00, + 0xa20, 0x1a1b0000, + 0xa24, 0x090e1317, + 0xa28, 0x00000204, + 0xa2c, 0x00d30000, + 0xa70, 0x101fbf00, + 0xa74, 0x00000007, + 0xc00, 0x48071d40, + 0xc04, 0x03a05633, + 0xc08, 0x000000e4, + 0xc0c, 0x6c6c6c6c, + 0xc10, 0x08800000, + 0xc14, 0x40000100, + 0xc18, 0x08800000, + 0xc1c, 0x40000100, + 0xc20, 0x00000000, + 0xc24, 0x00000000, + 0xc28, 0x00000000, + 0xc2c, 0x00000000, + 0xc30, 0x69e9ac44, + 0xc34, 0x469652cf, + 0xc38, 0x49795994, + 0xc3c, 0x0a97971c, + 0xc40, 0x1f7c403f, + 0xc44, 0x000100b7, + 0xc48, 0xec020107, + 0xc4c, 0x007f037f, + 0xc50, 0x69543420, + 0xc54, 0x43bc0094, + 0xc58, 0x69543420, + 0xc5c, 0x433c0094, + 0xc60, 0x00000000, + 0xc64, 0x5116848b, + 0xc68, 0x47c00bff, + 0xc6c, 0x00000036, + 0xc70, 0x2c7f000d, + 0xc74, 0x018610db, + 0xc78, 0x0000001f, + 0xc7c, 0x00b91612, + 0xc80, 0x40000100, + 0xc84, 0x20f60000, + 0xc88, 0x40000100, + 0xc8c, 0x20200000, + 0xc90, 0x00121820, + 0xc94, 0x00000000, + 0xc98, 0x00121820, + 0xc9c, 0x00007f7f, + 0xca0, 0x00000000, + 0xca4, 0x00000080, + 0xca8, 0x00000000, + 0xcac, 0x00000000, + 0xcb0, 0x00000000, + 0xcb4, 0x00000000, + 0xcb8, 0x00000000, + 0xcbc, 0x28000000, + 0xcc0, 0x00000000, + 0xcc4, 0x00000000, + 0xcc8, 0x00000000, + 0xccc, 0x00000000, + 0xcd0, 0x00000000, + 0xcd4, 0x00000000, + 0xcd8, 0x64b22427, + 0xcdc, 0x00766932, + 0xce0, 0x00222222, + 0xce4, 0x00000000, + 0xce8, 0x37644302, + 0xcec, 0x2f97d40c, + 0xd00, 0x00080740, + 0xd04, 0x00020403, + 0xd08, 0x0000907f, + 0xd0c, 0x20010201, + 0xd10, 0xa0633333, + 0xd14, 0x3333bc43, + 0xd18, 0x7a8f5b6b, + 0xd2c, 0xcc979975, + 0xd30, 0x00000000, + 0xd34, 0x80608000, + 0xd38, 0x00000000, + 0xd3c, 0x00027293, + 0xd40, 0x00000000, + 0xd44, 0x00000000, + 0xd48, 0x00000000, + 0xd4c, 0x00000000, + 0xd50, 0x6437140a, + 0xd54, 0x00000000, + 0xd58, 0x00000000, + 0xd5c, 0x30032064, + 0xd60, 0x4653de68, + 0xd64, 0x04518a3c, + 0xd68, 0x00002101, + 0xd6c, 0x2a201c16, + 0xd70, 0x1812362e, + 0xd74, 0x322c2220, + 0xd78, 0x000e3c24, + 0xe00, 0x2a2a2a2a, + 0xe04, 0x2a2a2a2a, + 0xe08, 0x03902a2a, + 0xe10, 0x2a2a2a2a, + 0xe14, 0x2a2a2a2a, + 0xe18, 0x2a2a2a2a, + 0xe1c, 0x2a2a2a2a, + 0xe28, 0x00000000, + 0xe30, 0x1000dc1f, + 0xe34, 0x10008c1f, + 0xe38, 0x02140102, + 0xe3c, 0x681604c2, + 0xe40, 0x01007c00, + 0xe44, 0x01004800, + 0xe48, 0xfb000000, + 0xe4c, 0x000028d1, + 0xe50, 0x1000dc1f, + 0xe54, 0x10008c1f, + 0xe58, 0x02140102, + 0xe5c, 0x28160d05, + 0xe60, 0x00000010, + 0xe68, 0x001b25a4, + 0xe6c, 0x63db25a4, + 0xe70, 0x63db25a4, + 0xe74, 0x0c1b25a4, + 0xe78, 0x0c1b25a4, + 0xe7c, 0x0c1b25a4, + 0xe80, 0x0c1b25a4, + 0xe84, 0x63db25a4, + 0xe88, 0x0c1b25a4, + 0xe8c, 0x63db25a4, + 0xed0, 0x63db25a4, + 0xed4, 0x63db25a4, + 0xed8, 0x63db25a4, + 0xedc, 0x001b25a4, + 0xee0, 0x001b25a4, + 0xeec, 0x6fdb25a4, + 0xf14, 0x00000003, + 0xf4c, 0x00000000, + 0xf00, 0x00000300, +}; + +u32 RTL8192CEPHY_REG_1TARRAY[PHY_REG_1TARRAY_LENGTH] = { + 0x024, 0x0011800f, + 0x028, 0x00ffdb83, + 0x800, 0x80040000, + 0x804, 0x00000001, + 0x808, 0x0000fc00, + 0x80c, 0x0000000a, + 0x810, 0x10005388, + 0x814, 0x020c3d10, + 0x818, 0x02200385, + 0x81c, 0x00000000, + 0x820, 0x01000100, + 0x824, 0x00390004, + 0x828, 0x00000000, + 0x82c, 0x00000000, + 0x830, 0x00000000, + 0x834, 0x00000000, + 0x838, 0x00000000, + 0x83c, 0x00000000, + 0x840, 0x00010000, + 0x844, 0x00000000, + 0x848, 0x00000000, + 0x84c, 0x00000000, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x569a569a, + 0x85c, 0x001b25a4, + 0x860, 0x66e60230, + 0x864, 0x061f0130, + 0x868, 0x00000000, + 0x86c, 0x32323200, + 0x870, 0x07000700, + 0x874, 0x22004000, + 0x878, 0x00000808, + 0x87c, 0x00000000, + 0x880, 0xc0083070, + 0x884, 0x000004d5, + 0x888, 0x00000000, + 0x88c, 0xccc000c0, + 0x890, 0x00000800, + 0x894, 0xfffffffe, + 0x898, 0x40302010, + 0x89c, 0x00706050, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90c, 0x81121111, + 0xa00, 0x00d047c8, + 0xa04, 0x80ff000c, + 0xa08, 0x8c838300, + 0xa0c, 0x2e68120f, + 0xa10, 0x9500bb78, + 0xa14, 0x11144028, + 0xa18, 0x00881117, + 0xa1c, 0x89140f00, + 0xa20, 0x1a1b0000, + 0xa24, 0x090e1317, + 0xa28, 0x00000204, + 0xa2c, 0x00d30000, + 0xa70, 0x101fbf00, + 0xa74, 0x00000007, + 0xc00, 0x48071d40, + 0xc04, 0x03a05611, + 0xc08, 0x000000e4, + 0xc0c, 0x6c6c6c6c, + 0xc10, 0x08800000, + 0xc14, 0x40000100, + 0xc18, 0x08800000, + 0xc1c, 0x40000100, + 0xc20, 0x00000000, + 0xc24, 0x00000000, + 0xc28, 0x00000000, + 0xc2c, 0x00000000, + 0xc30, 0x69e9ac44, + 0xc34, 0x469652cf, + 0xc38, 0x49795994, + 0xc3c, 0x0a97971c, + 0xc40, 0x1f7c403f, + 0xc44, 0x000100b7, + 0xc48, 0xec020107, + 0xc4c, 0x007f037f, + 0xc50, 0x69543420, + 0xc54, 0x43bc0094, + 0xc58, 0x69543420, + 0xc5c, 0x433c0094, + 0xc60, 0x00000000, + 0xc64, 0x5116848b, + 0xc68, 0x47c00bff, + 0xc6c, 0x00000036, + 0xc70, 0x2c7f000d, + 0xc74, 0x018610db, + 0xc78, 0x0000001f, + 0xc7c, 0x00b91612, + 0xc80, 0x40000100, + 0xc84, 0x20f60000, + 0xc88, 0x40000100, + 0xc8c, 0x20200000, + 0xc90, 0x00121820, + 0xc94, 0x00000000, + 0xc98, 0x00121820, + 0xc9c, 0x00007f7f, + 0xca0, 0x00000000, + 0xca4, 0x00000080, + 0xca8, 0x00000000, + 0xcac, 0x00000000, + 0xcb0, 0x00000000, + 0xcb4, 0x00000000, + 0xcb8, 0x00000000, + 0xcbc, 0x28000000, + 0xcc0, 0x00000000, + 0xcc4, 0x00000000, + 0xcc8, 0x00000000, + 0xccc, 0x00000000, + 0xcd0, 0x00000000, + 0xcd4, 0x00000000, + 0xcd8, 0x64b22427, + 0xcdc, 0x00766932, + 0xce0, 0x00222222, + 0xce4, 0x00000000, + 0xce8, 0x37644302, + 0xcec, 0x2f97d40c, + 0xd00, 0x00080740, + 0xd04, 0x00020401, + 0xd08, 0x0000907f, + 0xd0c, 0x20010201, + 0xd10, 0xa0633333, + 0xd14, 0x3333bc43, + 0xd18, 0x7a8f5b6b, + 0xd2c, 0xcc979975, + 0xd30, 0x00000000, + 0xd34, 0x80608000, + 0xd38, 0x00000000, + 0xd3c, 0x00027293, + 0xd40, 0x00000000, + 0xd44, 0x00000000, + 0xd48, 0x00000000, + 0xd4c, 0x00000000, + 0xd50, 0x6437140a, + 0xd54, 0x00000000, + 0xd58, 0x00000000, + 0xd5c, 0x30032064, + 0xd60, 0x4653de68, + 0xd64, 0x04518a3c, + 0xd68, 0x00002101, + 0xd6c, 0x2a201c16, + 0xd70, 0x1812362e, + 0xd74, 0x322c2220, + 0xd78, 0x000e3c24, + 0xe00, 0x2a2a2a2a, + 0xe04, 0x2a2a2a2a, + 0xe08, 0x03902a2a, + 0xe10, 0x2a2a2a2a, + 0xe14, 0x2a2a2a2a, + 0xe18, 0x2a2a2a2a, + 0xe1c, 0x2a2a2a2a, + 0xe28, 0x00000000, + 0xe30, 0x1000dc1f, + 0xe34, 0x10008c1f, + 0xe38, 0x02140102, + 0xe3c, 0x681604c2, + 0xe40, 0x01007c00, + 0xe44, 0x01004800, + 0xe48, 0xfb000000, + 0xe4c, 0x000028d1, + 0xe50, 0x1000dc1f, + 0xe54, 0x10008c1f, + 0xe58, 0x02140102, + 0xe5c, 0x28160d05, + 0xe60, 0x00000010, + 0xe68, 0x001b25a4, + 0xe6c, 0x631b25a0, + 0xe70, 0x631b25a0, + 0xe74, 0x081b25a0, + 0xe78, 0x081b25a0, + 0xe7c, 0x081b25a0, + 0xe80, 0x081b25a0, + 0xe84, 0x631b25a0, + 0xe88, 0x081b25a0, + 0xe8c, 0x631b25a0, + 0xed0, 0x631b25a0, + 0xed4, 0x631b25a0, + 0xed8, 0x631b25a0, + 0xedc, 0x001b25a0, + 0xee0, 0x001b25a0, + 0xeec, 0x6b1b25a0, + 0xf14, 0x00000003, + 0xf4c, 0x00000000, + 0xf00, 0x00000300, +}; + +u32 RTL8192CEPHY_REG_ARRAY_PG[PHY_REG_ARRAY_PGLENGTH] = { + 0xe00, 0xffffffff, 0x0a0c0c0c, + 0xe04, 0xffffffff, 0x02040608, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x0a0c0d0e, + 0xe14, 0xffffffff, 0x02040608, + 0xe18, 0xffffffff, 0x0a0c0d0e, + 0xe1c, 0xffffffff, 0x02040608, + 0x830, 0xffffffff, 0x0a0c0c0c, + 0x834, 0xffffffff, 0x02040608, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x0a0c0d0e, + 0x848, 0xffffffff, 0x02040608, + 0x84c, 0xffffffff, 0x0a0c0d0e, + 0x868, 0xffffffff, 0x02040608, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x06060606, + 0xe14, 0xffffffff, 0x00020406, + 0xe18, 0xffffffff, 0x06060606, + 0xe1c, 0xffffffff, 0x00020406, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x06060606, + 0x848, 0xffffffff, 0x00020406, + 0x84c, 0xffffffff, 0x06060606, + 0x868, 0xffffffff, 0x00020406, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, +}; + +u32 RTL8192CERADIOA_2TARRAY[RADIOA_2TARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00031284, + 0x002, 0x00098000, + 0x003, 0x00018c63, + 0x004, 0x000210e7, + 0x009, 0x0002044f, + 0x00a, 0x0001adb0, + 0x00b, 0x00054867, + 0x00c, 0x0008992e, + 0x00d, 0x0000e52c, + 0x00e, 0x00039ce7, + 0x00f, 0x00000451, + 0x019, 0x00000000, + 0x01a, 0x00010255, + 0x01b, 0x00060a00, + 0x01c, 0x000fc378, + 0x01d, 0x000a1250, + 0x01e, 0x0004445f, + 0x01f, 0x00080001, + 0x020, 0x0000b614, + 0x021, 0x0006c000, + 0x022, 0x00000000, + 0x023, 0x00001558, + 0x024, 0x00000060, + 0x025, 0x00000483, + 0x026, 0x0004f000, + 0x027, 0x000ec7d9, + 0x028, 0x000977c0, + 0x029, 0x00004783, + 0x02a, 0x00000001, + 0x02b, 0x00021334, + 0x02a, 0x00000000, + 0x02b, 0x00000054, + 0x02a, 0x00000001, + 0x02b, 0x00000808, + 0x02b, 0x00053333, + 0x02c, 0x0000000c, + 0x02a, 0x00000002, + 0x02b, 0x00000808, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000003, + 0x02b, 0x00000808, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000004, + 0x02b, 0x00000808, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000005, + 0x02b, 0x00000808, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x00000006, + 0x02b, 0x00000709, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000007, + 0x02b, 0x00000709, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000008, + 0x02b, 0x0000060a, + 0x02b, 0x0004b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000009, + 0x02b, 0x0000060a, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000a, + 0x02b, 0x0000060a, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000b, + 0x02b, 0x0000060a, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000c, + 0x02b, 0x0000060a, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000d, + 0x02b, 0x0000060a, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000e, + 0x02b, 0x0000050b, + 0x02b, 0x00066666, + 0x02c, 0x0000001a, + 0x02a, 0x000e0000, + 0x010, 0x0004000f, + 0x011, 0x000e31fc, + 0x010, 0x0006000f, + 0x011, 0x000ff9f8, + 0x010, 0x0002000f, + 0x011, 0x000203f9, + 0x010, 0x0003000f, + 0x011, 0x000ff500, + 0x010, 0x00000000, + 0x011, 0x00000000, + 0x010, 0x0008000f, + 0x011, 0x0003f100, + 0x010, 0x0009000f, + 0x011, 0x00023100, + 0x012, 0x00032000, + 0x012, 0x00071000, + 0x012, 0x000b0000, + 0x012, 0x000fc000, + 0x013, 0x000287af, + 0x013, 0x000244b7, + 0x013, 0x000204ab, + 0x013, 0x0001c49f, + 0x013, 0x00018493, + 0x013, 0x00014297, + 0x013, 0x00010295, + 0x013, 0x0000c298, + 0x013, 0x0000819c, + 0x013, 0x000040a8, + 0x013, 0x0000001c, + 0x014, 0x0001944c, + 0x014, 0x00059444, + 0x014, 0x0009944c, + 0x014, 0x000d9444, + 0x015, 0x0000f424, + 0x015, 0x0004f424, + 0x015, 0x0008f424, + 0x015, 0x000cf424, + 0x016, 0x000e0330, + 0x016, 0x000a0330, + 0x016, 0x00060330, + 0x016, 0x00020330, + 0x000, 0x00010159, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01f, 0x00080003, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01e, 0x00044457, + 0x01f, 0x00080000, + 0x000, 0x00030159, +}; + +u32 RTL8192CE_RADIOB_2TARRAY[RADIOB_2TARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00031284, + 0x002, 0x00098000, + 0x003, 0x00018c63, + 0x004, 0x000210e7, + 0x009, 0x0002044f, + 0x00a, 0x0001adb0, + 0x00b, 0x00054867, + 0x00c, 0x0008992e, + 0x00d, 0x0000e52c, + 0x00e, 0x00039ce7, + 0x00f, 0x00000451, + 0x012, 0x00032000, + 0x012, 0x00071000, + 0x012, 0x000b0000, + 0x012, 0x000fc000, + 0x013, 0x000287af, + 0x013, 0x000244b7, + 0x013, 0x000204ab, + 0x013, 0x0001c49f, + 0x013, 0x00018493, + 0x013, 0x00014297, + 0x013, 0x00010295, + 0x013, 0x0000c298, + 0x013, 0x0000819c, + 0x013, 0x000040a8, + 0x013, 0x0000001c, + 0x014, 0x0001944c, + 0x014, 0x00059444, + 0x014, 0x0009944c, + 0x014, 0x000d9444, + 0x015, 0x0000f424, + 0x015, 0x0004f424, + 0x015, 0x0008f424, + 0x015, 0x000cf424, + 0x016, 0x000e0330, + 0x016, 0x000a0330, + 0x016, 0x00060330, + 0x016, 0x00020330, +}; + +u32 RTL8192CE_RADIOA_1TARRAY[RADIOA_1TARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00031284, + 0x002, 0x00098000, + 0x003, 0x00018c63, + 0x004, 0x000210e7, + 0x009, 0x0002044f, + 0x00a, 0x0001adb0, + 0x00b, 0x00054867, + 0x00c, 0x0008992e, + 0x00d, 0x0000e52c, + 0x00e, 0x00039ce7, + 0x00f, 0x00000451, + 0x019, 0x00000000, + 0x01a, 0x00010255, + 0x01b, 0x00060a00, + 0x01c, 0x000fc378, + 0x01d, 0x000a1250, + 0x01e, 0x0004445f, + 0x01f, 0x00080001, + 0x020, 0x0000b614, + 0x021, 0x0006c000, + 0x022, 0x00000000, + 0x023, 0x00001558, + 0x024, 0x00000060, + 0x025, 0x00000483, + 0x026, 0x0004f000, + 0x027, 0x000ec7d9, + 0x028, 0x000977c0, + 0x029, 0x00004783, + 0x02a, 0x00000001, + 0x02b, 0x00021334, + 0x02a, 0x00000000, + 0x02b, 0x00000054, + 0x02a, 0x00000001, + 0x02b, 0x00000808, + 0x02b, 0x00053333, + 0x02c, 0x0000000c, + 0x02a, 0x00000002, + 0x02b, 0x00000808, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000003, + 0x02b, 0x00000808, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000004, + 0x02b, 0x00000808, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000005, + 0x02b, 0x00000808, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x00000006, + 0x02b, 0x00000709, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000007, + 0x02b, 0x00000709, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000008, + 0x02b, 0x0000060a, + 0x02b, 0x0004b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000009, + 0x02b, 0x0000060a, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000a, + 0x02b, 0x0000060a, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000b, + 0x02b, 0x0000060a, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000c, + 0x02b, 0x0000060a, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000d, + 0x02b, 0x0000060a, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000e, + 0x02b, 0x0000050b, + 0x02b, 0x00066666, + 0x02c, 0x0000001a, + 0x02a, 0x000e0000, + 0x010, 0x0004000f, + 0x011, 0x000e31fc, + 0x010, 0x0006000f, + 0x011, 0x000ff9f8, + 0x010, 0x0002000f, + 0x011, 0x000203f9, + 0x010, 0x0003000f, + 0x011, 0x000ff500, + 0x010, 0x00000000, + 0x011, 0x00000000, + 0x010, 0x0008000f, + 0x011, 0x0003f100, + 0x010, 0x0009000f, + 0x011, 0x00023100, + 0x012, 0x00032000, + 0x012, 0x00071000, + 0x012, 0x000b0000, + 0x012, 0x000fc000, + 0x013, 0x000287af, + 0x013, 0x000244b7, + 0x013, 0x000204ab, + 0x013, 0x0001c49f, + 0x013, 0x00018493, + 0x013, 0x00014297, + 0x013, 0x00010295, + 0x013, 0x0000c298, + 0x013, 0x0000819c, + 0x013, 0x000040a8, + 0x013, 0x0000001c, + 0x014, 0x0001944c, + 0x014, 0x00059444, + 0x014, 0x0009944c, + 0x014, 0x000d9444, + 0x015, 0x0000f424, + 0x015, 0x0004f424, + 0x015, 0x0008f424, + 0x015, 0x000cf424, + 0x016, 0x000e0330, + 0x016, 0x000a0330, + 0x016, 0x00060330, + 0x016, 0x00020330, + 0x000, 0x00010159, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01f, 0x00080003, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01e, 0x00044457, + 0x01f, 0x00080000, + 0x000, 0x00030159, +}; + +u32 RTL8192CE_RADIOB_1TARRAY[RADIOB_1TARRAYLENGTH] = { + 0x0, +}; + +u32 RTL8192CEMAC_2T_ARRAY[MAC_2T_ARRAYLENGTH] = { + 0x420, 0x00000080, + 0x423, 0x00000000, + 0x430, 0x00000000, + 0x431, 0x00000000, + 0x432, 0x00000000, + 0x433, 0x00000001, + 0x434, 0x00000004, + 0x435, 0x00000005, + 0x436, 0x00000006, + 0x437, 0x00000007, + 0x438, 0x00000000, + 0x439, 0x00000000, + 0x43a, 0x00000000, + 0x43b, 0x00000001, + 0x43c, 0x00000004, + 0x43d, 0x00000005, + 0x43e, 0x00000006, + 0x43f, 0x00000007, + 0x440, 0x0000005d, + 0x441, 0x00000001, + 0x442, 0x00000000, + 0x444, 0x00000015, + 0x445, 0x000000f0, + 0x446, 0x0000000f, + 0x447, 0x00000000, + 0x458, 0x00000041, + 0x459, 0x000000a8, + 0x45a, 0x00000072, + 0x45b, 0x000000b9, + 0x460, 0x00000088, + 0x461, 0x00000088, + 0x462, 0x00000006, + 0x463, 0x00000003, + 0x4c8, 0x00000004, + 0x4c9, 0x00000008, + 0x4cc, 0x00000002, + 0x4cd, 0x00000028, + 0x4ce, 0x00000001, + 0x500, 0x00000026, + 0x501, 0x000000a2, + 0x502, 0x0000002f, + 0x503, 0x00000000, + 0x504, 0x00000028, + 0x505, 0x000000a3, + 0x506, 0x0000005e, + 0x507, 0x00000000, + 0x508, 0x0000002b, + 0x509, 0x000000a4, + 0x50a, 0x0000005e, + 0x50b, 0x00000000, + 0x50c, 0x0000004f, + 0x50d, 0x000000a4, + 0x50e, 0x00000000, + 0x50f, 0x00000000, + 0x512, 0x0000001c, + 0x514, 0x0000000a, + 0x515, 0x00000010, + 0x516, 0x0000000a, + 0x517, 0x00000010, + 0x51a, 0x00000016, + 0x524, 0x0000000f, + 0x525, 0x0000004f, + 0x546, 0x00000020, + 0x547, 0x00000000, + 0x559, 0x00000002, + 0x55a, 0x00000002, + 0x55d, 0x000000ff, + 0x605, 0x00000030, + 0x608, 0x0000000e, + 0x609, 0x0000002a, + 0x652, 0x00000020, + 0x63c, 0x0000000a, + 0x63d, 0x0000000a, + 0x700, 0x00000021, + 0x701, 0x00000043, + 0x702, 0x00000065, + 0x703, 0x00000087, + 0x708, 0x00000021, + 0x709, 0x00000043, + 0x70a, 0x00000065, + 0x70b, 0x00000087, +}; + +u32 RTL8192CEAGCTAB_2TARRAY[AGCTAB_2TARRAYLENGTH] = { + 0xc78, 0x7b000001, + 0xc78, 0x7b010001, + 0xc78, 0x7b020001, + 0xc78, 0x7b030001, + 0xc78, 0x7b040001, + 0xc78, 0x7b050001, + 0xc78, 0x7a060001, + 0xc78, 0x79070001, + 0xc78, 0x78080001, + 0xc78, 0x77090001, + 0xc78, 0x760a0001, + 0xc78, 0x750b0001, + 0xc78, 0x740c0001, + 0xc78, 0x730d0001, + 0xc78, 0x720e0001, + 0xc78, 0x710f0001, + 0xc78, 0x70100001, + 0xc78, 0x6f110001, + 0xc78, 0x6e120001, + 0xc78, 0x6d130001, + 0xc78, 0x6c140001, + 0xc78, 0x6b150001, + 0xc78, 0x6a160001, + 0xc78, 0x69170001, + 0xc78, 0x68180001, + 0xc78, 0x67190001, + 0xc78, 0x661a0001, + 0xc78, 0x651b0001, + 0xc78, 0x641c0001, + 0xc78, 0x631d0001, + 0xc78, 0x621e0001, + 0xc78, 0x611f0001, + 0xc78, 0x60200001, + 0xc78, 0x49210001, + 0xc78, 0x48220001, + 0xc78, 0x47230001, + 0xc78, 0x46240001, + 0xc78, 0x45250001, + 0xc78, 0x44260001, + 0xc78, 0x43270001, + 0xc78, 0x42280001, + 0xc78, 0x41290001, + 0xc78, 0x402a0001, + 0xc78, 0x262b0001, + 0xc78, 0x252c0001, + 0xc78, 0x242d0001, + 0xc78, 0x232e0001, + 0xc78, 0x222f0001, + 0xc78, 0x21300001, + 0xc78, 0x20310001, + 0xc78, 0x06320001, + 0xc78, 0x05330001, + 0xc78, 0x04340001, + 0xc78, 0x03350001, + 0xc78, 0x02360001, + 0xc78, 0x01370001, + 0xc78, 0x00380001, + 0xc78, 0x00390001, + 0xc78, 0x003a0001, + 0xc78, 0x003b0001, + 0xc78, 0x003c0001, + 0xc78, 0x003d0001, + 0xc78, 0x003e0001, + 0xc78, 0x003f0001, + 0xc78, 0x7b400001, + 0xc78, 0x7b410001, + 0xc78, 0x7b420001, + 0xc78, 0x7b430001, + 0xc78, 0x7b440001, + 0xc78, 0x7b450001, + 0xc78, 0x7a460001, + 0xc78, 0x79470001, + 0xc78, 0x78480001, + 0xc78, 0x77490001, + 0xc78, 0x764a0001, + 0xc78, 0x754b0001, + 0xc78, 0x744c0001, + 0xc78, 0x734d0001, + 0xc78, 0x724e0001, + 0xc78, 0x714f0001, + 0xc78, 0x70500001, + 0xc78, 0x6f510001, + 0xc78, 0x6e520001, + 0xc78, 0x6d530001, + 0xc78, 0x6c540001, + 0xc78, 0x6b550001, + 0xc78, 0x6a560001, + 0xc78, 0x69570001, + 0xc78, 0x68580001, + 0xc78, 0x67590001, + 0xc78, 0x665a0001, + 0xc78, 0x655b0001, + 0xc78, 0x645c0001, + 0xc78, 0x635d0001, + 0xc78, 0x625e0001, + 0xc78, 0x615f0001, + 0xc78, 0x60600001, + 0xc78, 0x49610001, + 0xc78, 0x48620001, + 0xc78, 0x47630001, + 0xc78, 0x46640001, + 0xc78, 0x45650001, + 0xc78, 0x44660001, + 0xc78, 0x43670001, + 0xc78, 0x42680001, + 0xc78, 0x41690001, + 0xc78, 0x406a0001, + 0xc78, 0x266b0001, + 0xc78, 0x256c0001, + 0xc78, 0x246d0001, + 0xc78, 0x236e0001, + 0xc78, 0x226f0001, + 0xc78, 0x21700001, + 0xc78, 0x20710001, + 0xc78, 0x06720001, + 0xc78, 0x05730001, + 0xc78, 0x04740001, + 0xc78, 0x03750001, + 0xc78, 0x02760001, + 0xc78, 0x01770001, + 0xc78, 0x00780001, + 0xc78, 0x00790001, + 0xc78, 0x007a0001, + 0xc78, 0x007b0001, + 0xc78, 0x007c0001, + 0xc78, 0x007d0001, + 0xc78, 0x007e0001, + 0xc78, 0x007f0001, + 0xc78, 0x3800001e, + 0xc78, 0x3801001e, + 0xc78, 0x3802001e, + 0xc78, 0x3803001e, + 0xc78, 0x3804001e, + 0xc78, 0x3805001e, + 0xc78, 0x3806001e, + 0xc78, 0x3807001e, + 0xc78, 0x3808001e, + 0xc78, 0x3c09001e, + 0xc78, 0x3e0a001e, + 0xc78, 0x400b001e, + 0xc78, 0x440c001e, + 0xc78, 0x480d001e, + 0xc78, 0x4c0e001e, + 0xc78, 0x500f001e, + 0xc78, 0x5210001e, + 0xc78, 0x5611001e, + 0xc78, 0x5a12001e, + 0xc78, 0x5e13001e, + 0xc78, 0x6014001e, + 0xc78, 0x6015001e, + 0xc78, 0x6016001e, + 0xc78, 0x6217001e, + 0xc78, 0x6218001e, + 0xc78, 0x6219001e, + 0xc78, 0x621a001e, + 0xc78, 0x621b001e, + 0xc78, 0x621c001e, + 0xc78, 0x621d001e, + 0xc78, 0x621e001e, + 0xc78, 0x621f001e, +}; + +u32 RTL8192CEAGCTAB_1TARRAY[AGCTAB_1TARRAYLENGTH] = { + 0xc78, 0x7b000001, + 0xc78, 0x7b010001, + 0xc78, 0x7b020001, + 0xc78, 0x7b030001, + 0xc78, 0x7b040001, + 0xc78, 0x7b050001, + 0xc78, 0x7a060001, + 0xc78, 0x79070001, + 0xc78, 0x78080001, + 0xc78, 0x77090001, + 0xc78, 0x760a0001, + 0xc78, 0x750b0001, + 0xc78, 0x740c0001, + 0xc78, 0x730d0001, + 0xc78, 0x720e0001, + 0xc78, 0x710f0001, + 0xc78, 0x70100001, + 0xc78, 0x6f110001, + 0xc78, 0x6e120001, + 0xc78, 0x6d130001, + 0xc78, 0x6c140001, + 0xc78, 0x6b150001, + 0xc78, 0x6a160001, + 0xc78, 0x69170001, + 0xc78, 0x68180001, + 0xc78, 0x67190001, + 0xc78, 0x661a0001, + 0xc78, 0x651b0001, + 0xc78, 0x641c0001, + 0xc78, 0x631d0001, + 0xc78, 0x621e0001, + 0xc78, 0x611f0001, + 0xc78, 0x60200001, + 0xc78, 0x49210001, + 0xc78, 0x48220001, + 0xc78, 0x47230001, + 0xc78, 0x46240001, + 0xc78, 0x45250001, + 0xc78, 0x44260001, + 0xc78, 0x43270001, + 0xc78, 0x42280001, + 0xc78, 0x41290001, + 0xc78, 0x402a0001, + 0xc78, 0x262b0001, + 0xc78, 0x252c0001, + 0xc78, 0x242d0001, + 0xc78, 0x232e0001, + 0xc78, 0x222f0001, + 0xc78, 0x21300001, + 0xc78, 0x20310001, + 0xc78, 0x06320001, + 0xc78, 0x05330001, + 0xc78, 0x04340001, + 0xc78, 0x03350001, + 0xc78, 0x02360001, + 0xc78, 0x01370001, + 0xc78, 0x00380001, + 0xc78, 0x00390001, + 0xc78, 0x003a0001, + 0xc78, 0x003b0001, + 0xc78, 0x003c0001, + 0xc78, 0x003d0001, + 0xc78, 0x003e0001, + 0xc78, 0x003f0001, + 0xc78, 0x7b400001, + 0xc78, 0x7b410001, + 0xc78, 0x7b420001, + 0xc78, 0x7b430001, + 0xc78, 0x7b440001, + 0xc78, 0x7b450001, + 0xc78, 0x7a460001, + 0xc78, 0x79470001, + 0xc78, 0x78480001, + 0xc78, 0x77490001, + 0xc78, 0x764a0001, + 0xc78, 0x754b0001, + 0xc78, 0x744c0001, + 0xc78, 0x734d0001, + 0xc78, 0x724e0001, + 0xc78, 0x714f0001, + 0xc78, 0x70500001, + 0xc78, 0x6f510001, + 0xc78, 0x6e520001, + 0xc78, 0x6d530001, + 0xc78, 0x6c540001, + 0xc78, 0x6b550001, + 0xc78, 0x6a560001, + 0xc78, 0x69570001, + 0xc78, 0x68580001, + 0xc78, 0x67590001, + 0xc78, 0x665a0001, + 0xc78, 0x655b0001, + 0xc78, 0x645c0001, + 0xc78, 0x635d0001, + 0xc78, 0x625e0001, + 0xc78, 0x615f0001, + 0xc78, 0x60600001, + 0xc78, 0x49610001, + 0xc78, 0x48620001, + 0xc78, 0x47630001, + 0xc78, 0x46640001, + 0xc78, 0x45650001, + 0xc78, 0x44660001, + 0xc78, 0x43670001, + 0xc78, 0x42680001, + 0xc78, 0x41690001, + 0xc78, 0x406a0001, + 0xc78, 0x266b0001, + 0xc78, 0x256c0001, + 0xc78, 0x246d0001, + 0xc78, 0x236e0001, + 0xc78, 0x226f0001, + 0xc78, 0x21700001, + 0xc78, 0x20710001, + 0xc78, 0x06720001, + 0xc78, 0x05730001, + 0xc78, 0x04740001, + 0xc78, 0x03750001, + 0xc78, 0x02760001, + 0xc78, 0x01770001, + 0xc78, 0x00780001, + 0xc78, 0x00790001, + 0xc78, 0x007a0001, + 0xc78, 0x007b0001, + 0xc78, 0x007c0001, + 0xc78, 0x007d0001, + 0xc78, 0x007e0001, + 0xc78, 0x007f0001, + 0xc78, 0x3800001e, + 0xc78, 0x3801001e, + 0xc78, 0x3802001e, + 0xc78, 0x3803001e, + 0xc78, 0x3804001e, + 0xc78, 0x3805001e, + 0xc78, 0x3806001e, + 0xc78, 0x3807001e, + 0xc78, 0x3808001e, + 0xc78, 0x3c09001e, + 0xc78, 0x3e0a001e, + 0xc78, 0x400b001e, + 0xc78, 0x440c001e, + 0xc78, 0x480d001e, + 0xc78, 0x4c0e001e, + 0xc78, 0x500f001e, + 0xc78, 0x5210001e, + 0xc78, 0x5611001e, + 0xc78, 0x5a12001e, + 0xc78, 0x5e13001e, + 0xc78, 0x6014001e, + 0xc78, 0x6015001e, + 0xc78, 0x6016001e, + 0xc78, 0x6217001e, + 0xc78, 0x6218001e, + 0xc78, 0x6219001e, + 0xc78, 0x621a001e, + 0xc78, 0x621b001e, + 0xc78, 0x621c001e, + 0xc78, 0x621d001e, + 0xc78, 0x621e001e, + 0xc78, 0x621f001e, +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h new file mode 100644 index 000000000000..8b79161f71be --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/table.h @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CE_TABLE__H_ +#define __RTL92CE_TABLE__H_ + +#include + +#define PHY_REG_2TARRAY_LENGTH 374 +extern u32 RTL8192CEPHY_REG_2TARRAY[PHY_REG_2TARRAY_LENGTH]; +#define PHY_REG_1TARRAY_LENGTH 374 +extern u32 RTL8192CEPHY_REG_1TARRAY[PHY_REG_1TARRAY_LENGTH]; +#define PHY_REG_ARRAY_PGLENGTH 192 +extern u32 RTL8192CEPHY_REG_ARRAY_PG[PHY_REG_ARRAY_PGLENGTH]; +#define RADIOA_2TARRAYLENGTH 282 +extern u32 RTL8192CERADIOA_2TARRAY[RADIOA_2TARRAYLENGTH]; +#define RADIOB_2TARRAYLENGTH 78 +extern u32 RTL8192CE_RADIOB_2TARRAY[RADIOB_2TARRAYLENGTH]; +#define RADIOA_1TARRAYLENGTH 282 +extern u32 RTL8192CE_RADIOA_1TARRAY[RADIOA_1TARRAYLENGTH]; +#define RADIOB_1TARRAYLENGTH 1 +extern u32 RTL8192CE_RADIOB_1TARRAY[RADIOB_1TARRAYLENGTH]; +#define MAC_2T_ARRAYLENGTH 162 +extern u32 RTL8192CEMAC_2T_ARRAY[MAC_2T_ARRAYLENGTH]; +#define AGCTAB_2TARRAYLENGTH 320 +extern u32 RTL8192CEAGCTAB_2TARRAY[AGCTAB_2TARRAYLENGTH]; +#define AGCTAB_1TARRAYLENGTH 320 +extern u32 RTL8192CEAGCTAB_1TARRAY[AGCTAB_1TARRAYLENGTH]; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c new file mode 100644 index 000000000000..84ddd4d07a1d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c @@ -0,0 +1,768 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../stats.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "trx.h" +#include "led.h" + +static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) +{ + __le16 fc = rtl_get_fc(skb); + + if (unlikely(ieee80211_is_beacon(fc))) + return QSLT_BEACON; + if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) + return QSLT_MGNT; + + return skb->priority; +} + +static u8 _rtl92c_query_rxpwrpercentage(char antpower) +{ + if ((antpower <= -100) || (antpower >= 20)) + return 0; + else if (antpower >= 0) + return 100; + else + return 100 + antpower; +} + +static u8 _rtl92c_evm_db_to_percentage(char value) +{ + char ret_val; + ret_val = value; + + if (ret_val >= 0) + ret_val = 0; + + if (ret_val <= -33) + ret_val = -33; + + ret_val = 0 - ret_val; + ret_val *= 3; + + if (ret_val == 99) + ret_val = 100; + + return ret_val; +} + +static long _rtl92ce_signal_scale_mapping(struct ieee80211_hw *hw, + long currsig) +{ + long retsig; + + if (currsig >= 61 && currsig <= 100) + retsig = 90 + ((currsig - 60) / 4); + else if (currsig >= 41 && currsig <= 60) + retsig = 78 + ((currsig - 40) / 2); + else if (currsig >= 31 && currsig <= 40) + retsig = 66 + (currsig - 30); + else if (currsig >= 21 && currsig <= 30) + retsig = 54 + (currsig - 20); + else if (currsig >= 5 && currsig <= 20) + retsig = 42 + (((currsig - 5) * 2) / 3); + else if (currsig == 4) + retsig = 36; + else if (currsig == 3) + retsig = 27; + else if (currsig == 2) + retsig = 18; + else if (currsig == 1) + retsig = 9; + else + retsig = currsig; + + return retsig; +} + +static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, + struct rtl_stats *pstats, + struct rx_desc_92c *pdesc, + struct rx_fwinfo_92c *p_drvinfo, + bool packet_match_bssid, + bool packet_toself, + bool packet_beacon) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct phy_sts_cck_8192s_t *cck_buf; + struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); + s8 rx_pwr_all = 0, rx_pwr[4]; + u8 evm, pwdb_all, rf_rx_num = 0; + u8 i, max_spatial_stream; + u32 rssi, total_rssi = 0; + bool is_cck_rate; + + is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc->rxmcs); + pstats->packet_matchbssid = packet_match_bssid; + pstats->packet_toself = packet_toself; + pstats->is_cck = is_cck_rate; + pstats->packet_beacon = packet_beacon; + pstats->rx_mimo_sig_qual[0] = -1; + pstats->rx_mimo_sig_qual[1] = -1; + + if (is_cck_rate) { + u8 report, cck_highpwr; + cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; + + if (ppsc->rfpwr_state == ERFON) + cck_highpwr = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + BIT(9)); + else + cck_highpwr = false; + + if (!cck_highpwr) { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = cck_buf->cck_agc_rpt & 0xc0; + report = report >> 6; + switch (report) { + case 0x3: + rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); + break; + case 0x2: + rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); + break; + case 0x1: + rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); + break; + case 0x0: + rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); + break; + } + } else { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = p_drvinfo->cfosho[0] & 0x60; + report = report >> 5; + switch (report) { + case 0x3: + rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x2: + rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x1: + rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x0: + rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1); + break; + } + } + + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + /* CCK gain is smaller than OFDM/MCS gain, + * so we add gain diff by experiences, + * the val is 6 + */ + pwdb_all += 6; + if (pwdb_all > 100) + pwdb_all = 100; + /* modify the offset to make the same + * gain index with OFDM. + */ + if (pwdb_all > 34 && pwdb_all <= 42) + pwdb_all -= 2; + else if (pwdb_all > 26 && pwdb_all <= 34) + pwdb_all -= 6; + else if (pwdb_all > 14 && pwdb_all <= 26) + pwdb_all -= 8; + else if (pwdb_all > 4 && pwdb_all <= 14) + pwdb_all -= 4; + + pstats->rx_pwdb_all = pwdb_all; + pstats->recvsignalpower = rx_pwr_all; + + /* (3) Get Signal Quality (EVM) */ + if (packet_match_bssid) { + u8 sq; + if (pstats->rx_pwdb_all > 40) + sq = 100; + else { + sq = cck_buf->sq_rpt; + if (sq > 64) + sq = 0; + else if (sq < 20) + sq = 100; + else + sq = ((64 - sq) * 100) / 44; + } + + pstats->signalquality = sq; + pstats->rx_mimo_sig_qual[0] = sq; + pstats->rx_mimo_sig_qual[1] = -1; + } + } else { + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + /* (1)Get RSSI for HT rate */ + for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { + /* we will judge RF RX path now. */ + if (rtlpriv->dm.rfpath_rxenable[i]) + rf_rx_num++; + + rx_pwr[i] = + ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110; + /* Translate DBM to percentage. */ + rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + /* Get Rx snr value in DB */ + rtlpriv->stats.rx_snr_db[i] = + (long)(p_drvinfo->rxsnr[i] / 2); + + /* Record Signal Strength for next packet */ + if (packet_match_bssid) + pstats->rx_mimo_signalstrength[i] = (u8) rssi; + } + + /* (2)PWDB, Average PWDB cacluated by + * hardware (for rate adaptive) + */ + rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; + pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); + pstats->rx_pwdb_all = pwdb_all; + pstats->rxpower = rx_pwr_all; + pstats->recvsignalpower = rx_pwr_all; + + /* (3)EVM of HT rate */ + if (pstats->is_ht && pstats->rate >= DESC_RATEMCS8 && + pstats->rate <= DESC_RATEMCS15) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + + for (i = 0; i < max_spatial_stream; i++) { + evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]); + + if (packet_match_bssid) { + /* Fill value in RFD, Get the first + * spatial stream only + */ + if (i == 0) + pstats->signalquality = + (u8) (evm & 0xff); + pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff); + } + } + } + + /* UI BSS List signal strength(in percentage), + * make it good looking, from 0~100. + */ + if (is_cck_rate) + pstats->signalstrength = + (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all)); + else if (rf_rx_num != 0) + pstats->signalstrength = + (u8) (_rtl92ce_signal_scale_mapping + (hw, total_rssi /= rf_rx_num)); +} + +static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct rtl_stats *pstats, + struct rx_desc_92c *pdesc, + struct rx_fwinfo_92c *p_drvinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + struct ieee80211_hdr *hdr; + u8 *tmp_buf; + u8 *praddr; + __le16 fc; + u16 type, c_fc; + bool packet_matchbssid, packet_toself, packet_beacon = false; + + tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; + + hdr = (struct ieee80211_hdr *)tmp_buf; + fc = hdr->frame_control; + c_fc = le16_to_cpu(fc); + type = WLAN_FC_GET_TYPE(fc); + praddr = hdr->addr1; + + packet_matchbssid = + ((IEEE80211_FTYPE_CTL != type) && + ether_addr_equal(mac->bssid, + (c_fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : + (c_fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : + hdr->addr3) && + (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv)); + + packet_toself = packet_matchbssid && + ether_addr_equal(praddr, rtlefuse->dev_addr); + + if (ieee80211_is_beacon(fc)) + packet_beacon = true; + + _rtl92ce_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, + packet_matchbssid, packet_toself, + packet_beacon); + + rtl_process_phyinfo(hw, tmp_buf, pstats); +} + +bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, + u8 *p_desc, struct sk_buff *skb) +{ + struct rx_fwinfo_92c *p_drvinfo; + struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; + struct ieee80211_hdr *hdr; + u32 phystatus = GET_RX_DESC_PHYST(pdesc); + stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); + stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * + RX_DRV_INFO_SIZE_UNIT; + stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); + stats->icv = (u16) GET_RX_DESC_ICV(pdesc); + stats->crc = (u16) GET_RX_DESC_CRC32(pdesc); + stats->hwerror = (stats->crc | stats->icv); + stats->decrypted = !GET_RX_DESC_SWDEC(pdesc); + stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc); + stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); + stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); + stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) + && (GET_RX_DESC_FAGGR(pdesc) == 1)); + stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); + stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); + stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); + + stats->is_cck = RX_HAL_IS_CCK_RATE(pdesc->rxmcs); + + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + + hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size + + stats->rx_bufshift); + + if (stats->crc) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (stats->rx_is40Mhzpacket) + rx_status->flag |= RX_FLAG_40MHZ; + + if (stats->is_ht) + rx_status->flag |= RX_FLAG_HT; + + rx_status->flag |= RX_FLAG_MACTIME_START; + + /* hw will set stats->decrypted true, if it finds the + * frame is open data frame or mgmt frame. + * So hw will not decryption robust managment frame + * for IEEE80211w but still set status->decrypted + * true, so here we should set it back to undecrypted + * for IEEE80211w frame, and mac80211 sw will help + * to decrypt it + */ + if (stats->decrypted) { + if ((_ieee80211_is_robust_mgmt_frame(hdr)) && + (ieee80211_has_protected(hdr->frame_control))) + rx_status->flag &= ~RX_FLAG_DECRYPTED; + else + rx_status->flag |= RX_FLAG_DECRYPTED; + } + /* rate_idx: index of data rate into band's + * supported rates or MCS index if HT rates + * are use (RX_FLAG_HT) + * Notice: this is diff with windows define + */ + rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht, + false, stats->rate); + + rx_status->mactime = stats->timestamp_low; + if (phystatus) { + p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + + stats->rx_bufshift); + + _rtl92ce_translate_rx_signal_stuff(hw, + skb, stats, pdesc, + p_drvinfo); + } + + /*rx_status->qual = stats->signal; */ + rx_status->signal = stats->recvsignalpower + 10; + + return true; +} + +void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *pbd_desc_tx, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *tcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool defaultadapter = true; + u8 *pdesc = pdesc_tx; + u16 seq_number; + __le16 fc = hdr->frame_control; + u8 fw_qsel = _rtl92ce_map_hwqueue_to_fwqueue(skb, hw_queue); + bool firstseg = ((hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); + + bool lastseg = ((hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); + + dma_addr_t mapping = pci_map_single(rtlpci->pdev, + skb->data, skb->len, + PCI_DMA_TODEVICE); + + u8 bw_40 = 0; + + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + rcu_read_lock(); + sta = get_sta(hw, mac->vif, mac->bssid); + if (mac->opmode == NL80211_IFTYPE_STATION) { + bw_40 = mac->bw_40; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + if (sta) + bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; + } + + seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + + rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); + + CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c)); + + if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { + firstseg = true; + lastseg = true; + } + if (firstseg) { + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + + SET_TX_DESC_TX_RATE(pdesc, tcb_desc->hw_rate); + + if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) + SET_TX_DESC_DATA_SHORTGI(pdesc, 1); + + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + SET_TX_DESC_AGG_BREAK(pdesc, 1); + SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); + } + SET_TX_DESC_SEQ(pdesc, seq_number); + + SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc->rts_enable && + !tcb_desc-> + cts_enable) ? 1 : 0)); + SET_TX_DESC_HW_RTS_ENABLE(pdesc, + ((tcb_desc->rts_enable + || tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); + + SET_TX_DESC_RTS_RATE(pdesc, tcb_desc->rts_rate); + SET_TX_DESC_RTS_BW(pdesc, 0); + SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc); + SET_TX_DESC_RTS_SHORT(pdesc, + ((tcb_desc->rts_rate <= DESC_RATE54M) ? + (tcb_desc->rts_use_shortpreamble ? 1 : 0) + : (tcb_desc->rts_use_shortgi ? 1 : 0))); + + if (bw_40) { + if (tcb_desc->packet_bw) { + SET_TX_DESC_DATA_BW(pdesc, 1); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + mac->cur_40_prime_sc); + } + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + } + + SET_TX_DESC_LINIP(pdesc, 0); + SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); + + if (sta) { + u8 ampdu_density = sta->ht_cap.ampdu_density; + SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); + } + + if (info->control.hw_key) { + struct ieee80211_key_conf *keyconf = + info->control.hw_key; + + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x1); + break; + case WLAN_CIPHER_SUITE_CCMP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x3); + break; + default: + SET_TX_DESC_SEC_TYPE(pdesc, 0x0); + break; + + } + } + + SET_TX_DESC_PKT_ID(pdesc, 0); + SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); + + SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); + SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); + SET_TX_DESC_DISABLE_FB(pdesc, 0); + SET_TX_DESC_USE_RATE(pdesc, tcb_desc->use_driver_rate ? 1 : 0); + + if (ieee80211_is_data_qos(fc)) { + if (mac->rdg_en) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "Enable RDG function\n"); + SET_TX_DESC_RDG_ENABLE(pdesc, 1); + SET_TX_DESC_HTC(pdesc, 1); + } + } + } + rcu_read_unlock(); + + SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); + SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); + + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); + + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + + if (rtlpriv->dm.useramask) { + SET_TX_DESC_RATE_ID(pdesc, tcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, tcb_desc->mac_id); + } else { + SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, tcb_desc->ratr_index); + } + + if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { + SET_TX_DESC_HWSEQ_EN(pdesc, 1); + SET_TX_DESC_PKT_ID(pdesc, 8); + + if (!defaultadapter) + SET_TX_DESC_QOS(pdesc, 1); + } + + SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); + + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { + SET_TX_DESC_BMC(pdesc, 1); + } + + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); +} + +void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, + u8 *pdesc, bool firstseg, + bool lastseg, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 fw_queue = QSLT_BEACON; + + dma_addr_t mapping = pci_map_single(rtlpci->pdev, + skb->data, skb->len, + PCI_DMA_TODEVICE); + + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + __le16 fc = hdr->frame_control; + + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); + + if (firstseg) + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + + SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M); + + SET_TX_DESC_SEQ(pdesc, 0); + + SET_TX_DESC_LINIP(pdesc, 0); + + SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len)); + + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + + SET_TX_DESC_RATE_ID(pdesc, 7); + SET_TX_DESC_MACID(pdesc, 0); + + SET_TX_DESC_OWN(pdesc, 1); + + SET_TX_DESC_PKT_SIZE(pdesc, (u16) (skb->len)); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_OFFSET(pdesc, 0x20); + + SET_TX_DESC_USE_RATE(pdesc, 1); + + if (!ieee80211_is_data_qos(fc)) { + SET_TX_DESC_HWSEQ_EN(pdesc, 1); + SET_TX_DESC_PKT_ID(pdesc, 8); + } + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C Tx Cmd Content", pdesc, TX_DESC_SIZE); +} + +void rtl92ce_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, + u8 desc_name, u8 *val) +{ + if (istx) { + switch (desc_name) { + case HW_DESC_OWN: + wmb(); + SET_TX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_TX_NEXTDESC_ADDR: + SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); + break; + default: + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_RXOWN: + wmb(); + SET_RX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_RXBUFF_ADDR: + SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val); + break; + case HW_DESC_RXPKT_LEN: + SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val); + break; + case HW_DESC_RXERO: + SET_RX_DESC_EOR(pdesc, 1); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); + break; + } + } +} + +u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name) +{ + u32 ret = 0; + + if (istx) { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_TX_DESC_OWN(p_desc); + break; + case HW_DESC_TXBUFF_ADDR: + ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc); + break; + default: + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_RX_DESC_OWN(p_desc); + break; + case HW_DESC_RXPKT_LEN: + ret = GET_RX_DESC_PKT_LEN(p_desc); + break; + case HW_DESC_RXBUFF_ADDR: + ret = GET_RX_DESC_BUFF_ADDR(p_desc); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); + break; + } + } + return ret; +} + +bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw, + u8 hw_queue, u16 index) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; + u8 *entry = (u8 *)(&ring->desc[ring->idx]); + u8 own = (u8)rtl92ce_get_desc(entry, true, HW_DESC_OWN); + + /*beacon packet will only use the first + *descriptor defautly,and the own may not + *be cleared by the hardware + */ + if (own) + return false; + return true; +} + +void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (hw_queue == BEACON_QUEUE) { + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); + } else { + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, + BIT(0) << (hw_queue)); + } +} + diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h new file mode 100644 index 000000000000..4bec4b07e3e0 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.h @@ -0,0 +1,732 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CE_TRX_H__ +#define __RTL92CE_TRX_H__ + +#define TX_DESC_SIZE 64 +#define TX_DESC_AGGR_SUBFRAME_SIZE 32 + +#define RX_DESC_SIZE 32 +#define RX_DRV_INFO_SIZE_UNIT 8 + +#define TX_DESC_NEXT_DESC_OFFSET 40 +#define USB_HWDESC_HEADER_LEN 32 +#define CRCLENGTH 4 + +/* 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, __mask) \ + ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ + BIT_LEN_MASK_32(__mask)) + +/* 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/write various fields in RX or TX descriptors */ + +#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val) +#define SET_TX_DESC_OFFSET(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val) +#define SET_TX_DESC_BMC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 24, 1, __val) +#define SET_TX_DESC_HTC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 25, 1, __val) +#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) +#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) +#define SET_TX_DESC_LINIP(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) +#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) +#define SET_TX_DESC_GF(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) +#define SET_TX_DESC_OWN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) + +#define GET_TX_DESC_PKT_SIZE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 0, 16) +#define GET_TX_DESC_OFFSET(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 16, 8) +#define GET_TX_DESC_BMC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 24, 1) +#define GET_TX_DESC_HTC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 25, 1) +#define GET_TX_DESC_LAST_SEG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 26, 1) +#define GET_TX_DESC_FIRST_SEG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 27, 1) +#define GET_TX_DESC_LINIP(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 28, 1) +#define GET_TX_DESC_NO_ACM(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 29, 1) +#define GET_TX_DESC_GF(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 30, 1) +#define GET_TX_DESC_OWN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 31, 1) + +#define SET_TX_DESC_MACID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 0, 5, __val) +#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 5, 1, __val) +#define SET_TX_DESC_BK(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 6, 1, __val) +#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 7, 1, __val) +#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 8, 5, __val) +#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 13, 1, __val) +#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 14, 1, __val) +#define SET_TX_DESC_PIFS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 15, 1, __val) +#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 16, 4, __val) +#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 20, 1, __val) +#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 21, 1, __val) +#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 22, 2, __val) +#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 24, 8, __val) + +#define GET_TX_DESC_MACID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 0, 5) +#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 5, 1) +#define GET_TX_DESC_AGG_BREAK(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 6, 1) +#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 7, 1) +#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 8, 5) +#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 13, 1) +#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) +#define GET_TX_DESC_PIFS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) +#define GET_TX_DESC_RATE_ID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 16, 4) +#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 20, 1) +#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 21, 1) +#define GET_TX_DESC_SEC_TYPE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 22, 2) +#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 24, 8) + +#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 0, 6, __val) +#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 6, 6, __val) +#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 14, 2, __val) +#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 17, 1, __val) +#define SET_TX_DESC_RAW(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 18, 1, __val) +#define SET_TX_DESC_CCX(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 19, 1, __val) +#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 20, 3, __val) +#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 24, 1, __val) +#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 25, 1, __val) +#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 26, 2, __val) +#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 28, 2, __val) +#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 30, 2, __val) + +#define GET_TX_DESC_RTS_RC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 0, 6) +#define GET_TX_DESC_DATA_RC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 6, 6) +#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 14, 2) +#define GET_TX_DESC_MORE_FRAG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 17, 1) +#define GET_TX_DESC_RAW(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 18, 1) +#define GET_TX_DESC_CCX(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 19, 1) +#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 20, 3) +#define GET_TX_DESC_ANTSEL_A(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 24, 1) +#define GET_TX_DESC_ANTSEL_B(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 25, 1) +#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 26, 2) +#define GET_TX_DESC_TX_ANTL(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 28, 2) +#define GET_TX_DESC_TX_ANT_HT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 30, 2) + +#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+12, 0, 8, __val) +#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+12, 8, 8, __val) +#define SET_TX_DESC_SEQ(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+12, 16, 12, __val) +#define SET_TX_DESC_PKT_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+12, 28, 4, __val) + +#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 0, 8) +#define GET_TX_DESC_TAIL_PAGE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 8, 8) +#define GET_TX_DESC_SEQ(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 16, 12) +#define GET_TX_DESC_PKT_ID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 28, 4) + +#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 0, 5, __val) +#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 5, 1, __val) +#define SET_TX_DESC_QOS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 6, 1, __val) +#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 7, 1, __val) +#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 8, 1, __val) +#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 9, 1, __val) +#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 10, 1, __val) +#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 11, 1, __val) +#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 12, 1, __val) +#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 13, 1, __val) +#define SET_TX_DESC_PORT_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 14, 1, __val) +#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 18, 1, __val) +#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 19, 1, __val) +#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 20, 2, __val) +#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 22, 2, __val) +#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 24, 1, __val) +#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 25, 1, __val) +#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 26, 1, __val) +#define SET_TX_DESC_RTS_BW(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 27, 1, __val) +#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 28, 2, __val) +#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 30, 2, __val) + +#define GET_TX_DESC_RTS_RATE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 0, 5) +#define GET_TX_DESC_AP_DCFE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 5, 1) +#define GET_TX_DESC_QOS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 6, 1) +#define GET_TX_DESC_HWSEQ_EN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 7, 1) +#define GET_TX_DESC_USE_RATE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 8, 1) +#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 9, 1) +#define GET_TX_DESC_DISABLE_FB(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 10, 1) +#define GET_TX_DESC_CTS2SELF(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 11, 1) +#define GET_TX_DESC_RTS_ENABLE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 12, 1) +#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 13, 1) +#define GET_TX_DESC_PORT_ID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 14, 1) +#define GET_TX_DESC_WAIT_DCTS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 18, 1) +#define GET_TX_DESC_CTS2AP_EN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 19, 1) +#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 20, 2) +#define GET_TX_DESC_TX_STBC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 22, 2) +#define GET_TX_DESC_DATA_SHORT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 24, 1) +#define GET_TX_DESC_DATA_BW(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 25, 1) +#define GET_TX_DESC_RTS_SHORT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 26, 1) +#define GET_TX_DESC_RTS_BW(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 27, 1) +#define GET_TX_DESC_RTS_SC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 28, 2) +#define GET_TX_DESC_RTS_STBC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 30, 2) + +#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val) +#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val) +#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 8, 5, __val) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 13, 4, __val) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 17, 1, __val) +#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 18, 6, __val) +#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 24, 8, __val) + +#define GET_TX_DESC_TX_RATE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 0, 6) +#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 6, 1) +#define GET_TX_DESC_CCX_TAG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 7, 1) +#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 8, 5) +#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 13, 4) +#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 17, 1) +#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 18, 6) +#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 24, 8) + +#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 0, 5, __val) +#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 5, 5, __val) +#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 10, 1, __val) +#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 11, 5, __val) +#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 16, 4, __val) +#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 20, 4, __val) +#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 24, 4, __val) +#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 28, 4, __val) + +#define GET_TX_DESC_TXAGC_A(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 0, 5) +#define GET_TX_DESC_TXAGC_B(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 5, 5) +#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 10, 1) +#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 11, 5) +#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 16, 4) +#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 20, 4) +#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 24, 4) +#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 28, 4) + +#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+28, 0, 16, __val) +#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+28, 16, 4, __val) +#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+28, 20, 4, __val) +#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+28, 24, 4, __val) +#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+28, 28, 4, __val) + +#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+28, 0, 16) +#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+28, 16, 4) +#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+28, 20, 4) +#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+28, 24, 4) +#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+28, 28, 4) + +#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+32, 0, 32, __val) +#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+36, 0, 32, __val) + +#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+32, 0, 32) +#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+36, 0, 32) + +#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+40, 0, 32, __val) +#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+44, 0, 32, __val) + +#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+40, 0, 32) +#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+44, 0, 32) + +#define GET_RX_DESC_PKT_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 0, 14) +#define GET_RX_DESC_CRC32(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 14, 1) +#define GET_RX_DESC_ICV(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 15, 1) +#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 16, 4) +#define GET_RX_DESC_SECURITY(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 20, 3) +#define GET_RX_DESC_QOS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 23, 1) +#define GET_RX_DESC_SHIFT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 24, 2) +#define GET_RX_DESC_PHYST(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 26, 1) +#define GET_RX_DESC_SWDEC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 27, 1) +#define GET_RX_DESC_LS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 28, 1) +#define GET_RX_DESC_FS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 29, 1) +#define GET_RX_DESC_EOR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 30, 1) +#define GET_RX_DESC_OWN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 31, 1) + +#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val) +#define SET_RX_DESC_EOR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) +#define SET_RX_DESC_OWN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) + +#define GET_RX_DESC_MACID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 0, 5) +#define GET_RX_DESC_TID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 5, 4) +#define GET_RX_DESC_HWRSVD(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 9, 5) +#define GET_RX_DESC_PAGGR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) +#define GET_RX_DESC_FAGGR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) +#define GET_RX_DESC_A1_FIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 16, 4) +#define GET_RX_DESC_A2_FIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 20, 4) +#define GET_RX_DESC_PAM(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 24, 1) +#define GET_RX_DESC_PWR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 25, 1) +#define GET_RX_DESC_MD(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 26, 1) +#define GET_RX_DESC_MF(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 27, 1) +#define GET_RX_DESC_TYPE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 28, 2) +#define GET_RX_DESC_MC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 30, 1) +#define GET_RX_DESC_BC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 31, 1) +#define GET_RX_DESC_SEQ(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 0, 12) +#define GET_RX_DESC_FRAG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 12, 4) +#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 16, 14) +#define GET_RX_DESC_NEXT_IND(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 30, 1) +#define GET_RX_DESC_RSVD(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 31, 1) + +#define GET_RX_DESC_RXMCS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 0, 6) +#define GET_RX_DESC_RXHT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 6, 1) +#define GET_RX_DESC_SPLCP(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 8, 1) +#define GET_RX_DESC_BW(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 9, 1) +#define GET_RX_DESC_HTC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 10, 1) +#define GET_RX_DESC_HWPC_ERR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 14, 1) +#define GET_RX_DESC_HWPC_IND(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 15, 1) +#define GET_RX_DESC_IV0(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 16, 16) + +#define GET_RX_DESC_IV1(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 0, 32) +#define GET_RX_DESC_TSFL(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 0, 32) + +#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 0, 32) +#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+28, 0, 32) + +#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 0, 32, __val) +#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val) + +#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ + memset(__pdesc, 0, min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) + +struct rx_fwinfo_92c { + u8 gain_trsw[4]; + u8 pwdb_all; + u8 cfosho[4]; + u8 cfotail[4]; + char rxevm[2]; + char rxsnr[4]; + u8 pdsnr[2]; + u8 csi_current[2]; + u8 csi_target[2]; + u8 sigevm; + u8 max_ex_pwr; + u8 ex_intf_flag:1; + u8 sgi_en:1; + u8 rxsc:2; + u8 reserve:4; +} __packed; + +struct tx_desc_92c { + u32 pktsize:16; + u32 offset:8; + u32 bmc:1; + u32 htc:1; + u32 lastseg:1; + u32 firstseg:1; + u32 linip:1; + u32 noacm:1; + u32 gf:1; + u32 own:1; + + u32 macid:5; + u32 agg_en:1; + u32 bk:1; + u32 rdg_en:1; + u32 queuesel:5; + u32 rd_nav_ext:1; + u32 lsig_txop_en:1; + u32 pifs:1; + u32 rateid:4; + u32 nav_usehdr:1; + u32 en_descid:1; + u32 sectype:2; + u32 pktoffset:8; + + u32 rts_rc:6; + u32 data_rc:6; + u32 rsvd0:2; + u32 bar_retryht:2; + u32 rsvd1:1; + u32 morefrag:1; + u32 raw:1; + u32 ccx:1; + u32 ampdudensity:3; + u32 rsvd2:1; + u32 ant_sela:1; + u32 ant_selb:1; + u32 txant_cck:2; + u32 txant_l:2; + u32 txant_ht:2; + + u32 nextheadpage:8; + u32 tailpage:8; + u32 seq:12; + u32 pktid:4; + + u32 rtsrate:5; + u32 apdcfe:1; + u32 qos:1; + u32 hwseq_enable:1; + u32 userrate:1; + u32 dis_rtsfb:1; + u32 dis_datafb:1; + u32 cts2self:1; + u32 rts_en:1; + u32 hwrts_en:1; + u32 portid:1; + u32 rsvd3:3; + u32 waitdcts:1; + u32 cts2ap_en:1; + u32 txsc:2; + u32 stbc:2; + u32 txshort:1; + u32 txbw:1; + u32 rtsshort:1; + u32 rtsbw:1; + u32 rtssc:2; + u32 rtsstbc:2; + + u32 txrate:6; + u32 shortgi:1; + u32 ccxt:1; + u32 txrate_fb_lmt:5; + u32 rtsrate_fb_lmt:4; + u32 retrylmt_en:1; + u32 txretrylmt:6; + u32 usb_txaggnum:8; + + u32 txagca:5; + u32 txagcb:5; + u32 usemaxlen:1; + u32 maxaggnum:5; + u32 mcsg1maxlen:4; + u32 mcsg2maxlen:4; + u32 mcsg3maxlen:4; + u32 mcs7sgimaxlen:4; + + u32 txbuffersize:16; + u32 mcsg4maxlen:4; + u32 mcsg5maxlen:4; + u32 mcsg6maxlen:4; + u32 mcsg15sgimaxlen:4; + + u32 txbuffaddr; + u32 txbufferaddr64; + u32 nextdescaddress; + u32 nextdescaddress64; + + u32 reserve_pass_pcie_mm_limit[4]; +} __packed; + +struct rx_desc_92c { + u32 length:14; + u32 crc32:1; + u32 icverror:1; + u32 drv_infosize:4; + u32 security:3; + u32 qos:1; + u32 shift:2; + u32 phystatus:1; + u32 swdec:1; + u32 lastseg:1; + u32 firstseg:1; + u32 eor:1; + u32 own:1; + + u32 macid:5; + u32 tid:4; + u32 hwrsvd:5; + u32 paggr:1; + u32 faggr:1; + u32 a1_fit:4; + u32 a2_fit:4; + u32 pam:1; + u32 pwr:1; + u32 moredata:1; + u32 morefrag:1; + u32 type:2; + u32 mc:1; + u32 bc:1; + + u32 seq:12; + u32 frag:4; + u32 nextpktlen:14; + u32 nextind:1; + u32 rsvd:1; + + u32 rxmcs:6; + u32 rxht:1; + u32 amsdu:1; + u32 splcp:1; + u32 bandwidth:1; + u32 htc:1; + u32 tcpchk_rpt:1; + u32 ipcchk_rpt:1; + u32 tcpchk_valid:1; + u32 hwpcerr:1; + u32 hwpcind:1; + u32 iv0:16; + + u32 iv1; + + u32 tsfl; + + u32 bufferaddress; + u32 bufferaddress64; + +} __packed; + +void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc, + u8 *pbd_desc_tx, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, u8 hw_queue, + struct rtl_tcb_desc *ptcb_desc); +bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb); +void rtl92ce_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, + u8 desc_name, u8 *val); +u32 rtl92ce_get_desc(u8 *pdesc, bool istx, u8 desc_name); +bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw, + u8 hw_queue, u16 index); +void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); +void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool b_firstseg, bool b_lastseg, + struct sk_buff *skb); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/Makefile new file mode 100644 index 000000000000..ad2de6b839ef --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/Makefile @@ -0,0 +1,14 @@ +rtl8192cu-objs := \ + dm.o \ + hw.o \ + led.o \ + mac.o \ + phy.o \ + rf.o \ + sw.o \ + table.o \ + trx.o + +obj-$(CONFIG_RTL8192CU) += rtl8192cu.o + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h new file mode 100644 index 000000000000..74a479ac323d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/def.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../rtl8192ce/def.h" + +/*------------------------------------------------------------------------- + * Chip specific + *-------------------------------------------------------------------------*/ +#define NORMAL_CHIP BIT(4) +#define CHIP_VENDOR_UMC BIT(5) +#define CHIP_VENDOR_UMC_B_CUT BIT(6) + +#define IS_92C_1T2R(version) \ + (((version) & CHIP_92C) && ((version) & CHIP_92C_1T2R)) + +#define IS_VENDOR_UMC(version) \ + (((version) & CHIP_VENDOR_UMC) ? true : false) + +#define CHIP_BONDING_92C_1T2R 0x1 +#define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c new file mode 100644 index 000000000000..c16209a336ea --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.c @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" + +void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undec_sm_pwdb; + + if (!rtlpriv->dm.dynamic_txpower_enable) + return; + + if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "Not connected to any\n"); + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Client PWDB = 0x%lx\n", + undec_sm_pwdb); + } else { + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "STA Default Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + } else { + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Ext Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + + if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); + } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && + (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) { + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); + } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_NORMAL\n"); + } + + if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "PHY_SetTxPowerLevel8192S() Channel = %d\n", + rtlphy->current_channel); + rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); + if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_NORMAL) + dm_restorepowerindex(hw); + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL1) + dm_writepowerindex(hw, 0x14); + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL2) + dm_writepowerindex(hw, 0x10); + } + + rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h new file mode 100644 index 000000000000..fafa6bac2a3f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/dm.h @@ -0,0 +1,35 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../rtl8192ce/dm.h" + +void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw); +void dm_savepowerindex(struct ieee80211_hw *hw); +void dm_writepowerindex(struct ieee80211_hw *hw, u8 value); +void dm_restorepowerindex(struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c new file mode 100644 index 000000000000..25db369b5d18 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c @@ -0,0 +1,2323 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../cam.h" +#include "../ps.h" +#include "../usb.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "../rtl8192c/phy_common.h" +#include "mac.h" +#include "dm.h" +#include "../rtl8192c/dm_common.h" +#include "../rtl8192c/fw_common.h" +#include "hw.h" +#include "../rtl8192ce/hw.h" +#include "trx.h" +#include "led.h" +#include "table.h" + +static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); + + rtlphy->hwparam_tables[MAC_REG].length = RTL8192CUMAC_2T_ARRAYLENGTH; + rtlphy->hwparam_tables[MAC_REG].pdata = RTL8192CUMAC_2T_ARRAY; + if (IS_HIGHT_PA(rtlefuse->board_type)) { + rtlphy->hwparam_tables[PHY_REG_PG].length = + RTL8192CUPHY_REG_Array_PG_HPLength; + rtlphy->hwparam_tables[PHY_REG_PG].pdata = + RTL8192CUPHY_REG_Array_PG_HP; + } else { + rtlphy->hwparam_tables[PHY_REG_PG].length = + RTL8192CUPHY_REG_ARRAY_PGLENGTH; + rtlphy->hwparam_tables[PHY_REG_PG].pdata = + RTL8192CUPHY_REG_ARRAY_PG; + } + /* 2T */ + rtlphy->hwparam_tables[PHY_REG_2T].length = + RTL8192CUPHY_REG_2TARRAY_LENGTH; + rtlphy->hwparam_tables[PHY_REG_2T].pdata = + RTL8192CUPHY_REG_2TARRAY; + rtlphy->hwparam_tables[RADIOA_2T].length = + RTL8192CURADIOA_2TARRAYLENGTH; + rtlphy->hwparam_tables[RADIOA_2T].pdata = + RTL8192CURADIOA_2TARRAY; + rtlphy->hwparam_tables[RADIOB_2T].length = + RTL8192CURADIOB_2TARRAYLENGTH; + rtlphy->hwparam_tables[RADIOB_2T].pdata = + RTL8192CU_RADIOB_2TARRAY; + rtlphy->hwparam_tables[AGCTAB_2T].length = + RTL8192CUAGCTAB_2TARRAYLENGTH; + rtlphy->hwparam_tables[AGCTAB_2T].pdata = + RTL8192CUAGCTAB_2TARRAY; + /* 1T */ + if (IS_HIGHT_PA(rtlefuse->board_type)) { + rtlphy->hwparam_tables[PHY_REG_1T].length = + RTL8192CUPHY_REG_1T_HPArrayLength; + rtlphy->hwparam_tables[PHY_REG_1T].pdata = + RTL8192CUPHY_REG_1T_HPArray; + rtlphy->hwparam_tables[RADIOA_1T].length = + RTL8192CURadioA_1T_HPArrayLength; + rtlphy->hwparam_tables[RADIOA_1T].pdata = + RTL8192CURadioA_1T_HPArray; + rtlphy->hwparam_tables[RADIOB_1T].length = + RTL8192CURADIOB_1TARRAYLENGTH; + rtlphy->hwparam_tables[RADIOB_1T].pdata = + RTL8192CU_RADIOB_1TARRAY; + rtlphy->hwparam_tables[AGCTAB_1T].length = + RTL8192CUAGCTAB_1T_HPArrayLength; + rtlphy->hwparam_tables[AGCTAB_1T].pdata = + Rtl8192CUAGCTAB_1T_HPArray; + } else { + rtlphy->hwparam_tables[PHY_REG_1T].length = + RTL8192CUPHY_REG_1TARRAY_LENGTH; + rtlphy->hwparam_tables[PHY_REG_1T].pdata = + RTL8192CUPHY_REG_1TARRAY; + rtlphy->hwparam_tables[RADIOA_1T].length = + RTL8192CURADIOA_1TARRAYLENGTH; + rtlphy->hwparam_tables[RADIOA_1T].pdata = + RTL8192CU_RADIOA_1TARRAY; + rtlphy->hwparam_tables[RADIOB_1T].length = + RTL8192CURADIOB_1TARRAYLENGTH; + rtlphy->hwparam_tables[RADIOB_1T].pdata = + RTL8192CU_RADIOB_1TARRAY; + rtlphy->hwparam_tables[AGCTAB_1T].length = + RTL8192CUAGCTAB_1TARRAYLENGTH; + rtlphy->hwparam_tables[AGCTAB_1T].pdata = + RTL8192CUAGCTAB_1TARRAY; + } +} + +static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, + u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 rf_path, index, tempval; + u16 i; + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 3; i++) { + if (!autoload_fail) { + rtlefuse-> + eeprom_chnlarea_txpwr_cck[rf_path][i] = + hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i]; + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = + hwinfo[EEPROM_TXPOWERHT40_1S + rf_path * 3 + + i]; + } else { + rtlefuse-> + eeprom_chnlarea_txpwr_cck[rf_path][i] = + EEPROM_DEFAULT_TXPOWERLEVEL; + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = + EEPROM_DEFAULT_TXPOWERLEVEL; + } + } + } + for (i = 0; i < 3; i++) { + if (!autoload_fail) + tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i]; + else + tempval = EEPROM_DEFAULT_HT40_2SDIFF; + rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] = + (tempval & 0xf); + rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] = + ((tempval & 0xf0) >> 4); + } + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + "RF(%d) EEPROM CCK Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse-> + eeprom_chnlarea_txpwr_cck[rf_path][i]); + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + "RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][i]); + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse-> + eprom_chnl_txpwr_ht40_2sdf[rf_path][i]); + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 14; i++) { + index = rtl92c_get_chnl_group((u8)i); + rtlefuse->txpwrlevel_cck[rf_path][i] = + rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][index]; + rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][index]; + if ((rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] - + rtlefuse-> + eprom_chnl_txpwr_ht40_2sdf[rf_path][index]) + > 0) { + rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = + rtlefuse-> + eeprom_chnlarea_txpwr_ht40_1s[rf_path] + [index] - rtlefuse-> + eprom_chnl_txpwr_ht40_2sdf[rf_path] + [index]; + } else { + rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0; + } + } + for (i = 0; i < 14; i++) { + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", rf_path, i, + rtlefuse->txpwrlevel_cck[rf_path][i], + rtlefuse->txpwrlevel_ht40_1s[rf_path][i], + rtlefuse->txpwrlevel_ht40_2s[rf_path][i]); + } + } + for (i = 0; i < 3; i++) { + if (!autoload_fail) { + rtlefuse->eeprom_pwrlimit_ht40[i] = + hwinfo[EEPROM_TXPWR_GROUP + i]; + rtlefuse->eeprom_pwrlimit_ht20[i] = + hwinfo[EEPROM_TXPWR_GROUP + 3 + i]; + } else { + rtlefuse->eeprom_pwrlimit_ht40[i] = 0; + rtlefuse->eeprom_pwrlimit_ht20[i] = 0; + } + } + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 14; i++) { + index = rtl92c_get_chnl_group((u8)i); + if (rf_path == RF90_PATH_A) { + rtlefuse->pwrgroup_ht20[rf_path][i] = + (rtlefuse->eeprom_pwrlimit_ht20[index] + & 0xf); + rtlefuse->pwrgroup_ht40[rf_path][i] = + (rtlefuse->eeprom_pwrlimit_ht40[index] + & 0xf); + } else if (rf_path == RF90_PATH_B) { + rtlefuse->pwrgroup_ht20[rf_path][i] = + ((rtlefuse->eeprom_pwrlimit_ht20[index] + & 0xf0) >> 4); + rtlefuse->pwrgroup_ht40[rf_path][i] = + ((rtlefuse->eeprom_pwrlimit_ht40[index] + & 0xf0) >> 4); + } + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-%d pwrgroup_ht20[%d] = 0x%x\n", + rf_path, i, + rtlefuse->pwrgroup_ht20[rf_path][i]); + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-%d pwrgroup_ht40[%d] = 0x%x\n", + rf_path, i, + rtlefuse->pwrgroup_ht40[rf_path][i]); + } + } + for (i = 0; i < 14; i++) { + index = rtl92c_get_chnl_group((u8)i); + if (!autoload_fail) + tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index]; + else + tempval = EEPROM_DEFAULT_HT20_DIFF; + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = + ((tempval >> 4) & 0xF); + if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] & BIT(3)) + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] |= 0xF0; + if (rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] & BIT(3)) + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] |= 0xF0; + index = rtl92c_get_chnl_group((u8)i); + if (!autoload_fail) + tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index]; + else + tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = (tempval & 0xF); + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = + ((tempval >> 4) & 0xF); + } + rtlefuse->legacy_ht_txpowerdiff = + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", + i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", + i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", + i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", + i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); + if (!autoload_fail) + rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); + else + rtlefuse->eeprom_regulatory = 0; + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); + if (!autoload_fail) { + rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; + rtlefuse->eeprom_tssi[RF90_PATH_B] = hwinfo[EEPROM_TSSI_B]; + } else { + rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; + rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; + } + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "TSSI_A = 0x%x, TSSI_B = 0x%x\n", + rtlefuse->eeprom_tssi[RF90_PATH_A], + rtlefuse->eeprom_tssi[RF90_PATH_B]); + if (!autoload_fail) + tempval = hwinfo[EEPROM_THERMAL_METER]; + else + tempval = EEPROM_DEFAULT_THERMALMETER; + rtlefuse->eeprom_thermalmeter = (tempval & 0x1f); + if (rtlefuse->eeprom_thermalmeter < 0x06 || + rtlefuse->eeprom_thermalmeter > 0x1c) + rtlefuse->eeprom_thermalmeter = 0x12; + if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail) + rtlefuse->apk_thermalmeterignore = true; + rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); +} + +static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 boardType; + + if (IS_NORMAL_CHIP(rtlhal->version)) { + boardType = ((contents[EEPROM_RF_OPT1]) & + BOARD_TYPE_NORMAL_MASK) >> 5; /*bit[7:5]*/ + } else { + boardType = contents[EEPROM_RF_OPT4]; + boardType &= BOARD_TYPE_TEST_MASK; + } + rtlefuse->board_type = boardType; + if (IS_HIGHT_PA(rtlefuse->board_type)) + rtlefuse->external_pa = 1; + pr_info("Board Type %x\n", rtlefuse->board_type); +} + +static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u16 i, usvalue; + u8 hwinfo[HWSET_MAX_SIZE] = {0}; + u16 eeprom_id; + + if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + rtl_efuse_shadow_map_update(hw); + memcpy((void *)hwinfo, + (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + HWSET_MAX_SIZE); + } else if (rtlefuse->epromtype == EEPROM_93C46) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "RTL819X Not boot from eeprom, check it !!\n"); + } + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, "MAP", + hwinfo, HWSET_MAX_SIZE); + eeprom_id = le16_to_cpu(*((__le16 *)&hwinfo[0])); + if (eeprom_id != RTL8190_EEPROM_ID) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "EEPROM ID(%#x) is invalid!!\n", eeprom_id); + rtlefuse->autoload_failflag = true; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + } + if (rtlefuse->autoload_failflag) + return; + for (i = 0; i < 6; i += 2) { + usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; + *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; + } + pr_info("MAC address: %pM\n", rtlefuse->dev_addr); + _rtl92cu_read_txpower_info_from_hwpg(hw, + rtlefuse->autoload_failflag, hwinfo); + rtlefuse->eeprom_vid = le16_to_cpu(*(__le16 *)&hwinfo[EEPROM_VID]); + rtlefuse->eeprom_did = le16_to_cpu(*(__le16 *)&hwinfo[EEPROM_DID]); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, " VID = 0x%02x PID = 0x%02x\n", + rtlefuse->eeprom_vid, rtlefuse->eeprom_did); + rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; + rtlefuse->eeprom_version = + le16_to_cpu(*(__le16 *)&hwinfo[EEPROM_VERSION]); + rtlefuse->txpwr_fromeprom = true; + rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM Customer ID: 0x%2x\n", + rtlefuse->eeprom_oemid); + if (rtlhal->oem_id == RT_CID_DEFAULT) { + switch (rtlefuse->eeprom_oemid) { + case EEPROM_CID_DEFAULT: + if (rtlefuse->eeprom_did == 0x8176) { + if ((rtlefuse->eeprom_svid == 0x103C && + rtlefuse->eeprom_smid == 0x1629)) + rtlhal->oem_id = RT_CID_819X_HP; + else + rtlhal->oem_id = RT_CID_DEFAULT; + } else { + rtlhal->oem_id = RT_CID_DEFAULT; + } + break; + case EEPROM_CID_TOSHIBA: + rtlhal->oem_id = RT_CID_TOSHIBA; + break; + case EEPROM_CID_QMI: + rtlhal->oem_id = RT_CID_819X_QMI; + break; + case EEPROM_CID_WHQL: + default: + rtlhal->oem_id = RT_CID_DEFAULT; + break; + } + } + _rtl92cu_read_board_type(hw, hwinfo); +} + +static void _rtl92cu_hal_customized_behavior(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + switch (rtlhal->oem_id) { + case RT_CID_819X_HP: + usb_priv->ledctl.led_opendrain = true; + break; + case RT_CID_819X_LENOVO: + case RT_CID_DEFAULT: + case RT_CID_TOSHIBA: + case RT_CID_CCX: + case RT_CID_819X_ACER: + case RT_CID_WHQL: + default: + break; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "RT Customized ID: 0x%02X\n", + rtlhal->oem_id); +} + +void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw) +{ + + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_u1b; + + if (!IS_NORMAL_CHIP(rtlhal->version)) + return; + tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); + rtlefuse->epromtype = (tmp_u1b & BOOT_FROM_EEPROM) ? + EEPROM_93C46 : EEPROM_BOOT_EFUSE; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from %s\n", + tmp_u1b & BOOT_FROM_EEPROM ? "EERROM" : "EFUSE"); + rtlefuse->autoload_failflag = (tmp_u1b & EEPROM_EN) ? false : true; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload %s\n", + tmp_u1b & EEPROM_EN ? "OK!!" : "ERR!!"); + _rtl92cu_read_adapter_info(hw); + _rtl92cu_hal_customized_behavior(hw); + return; +} + +static int _rtl92cu_init_power_on(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int status = 0; + u16 value16; + u8 value8; + /* polling autoload done. */ + u32 pollingCount = 0; + + do { + if (rtl_read_byte(rtlpriv, REG_APS_FSMCO) & PFM_ALDN) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Autoload Done!\n"); + break; + } + if (pollingCount++ > 100) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + "Failed to polling REG_APS_FSMCO[PFM_ALDN] done!\n"); + return -ENODEV; + } + } while (true); + /* 0. RSV_CTRL 0x1C[7:0] = 0 unlock ISO/CLK/Power control register */ + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0); + /* Power on when re-enter from IPS/Radio off/card disable */ + /* enable SPS into PWM mode */ + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + udelay(100); + value8 = rtl_read_byte(rtlpriv, REG_LDOV12D_CTRL); + if (0 == (value8 & LDV12_EN)) { + value8 |= LDV12_EN; + rtl_write_byte(rtlpriv, REG_LDOV12D_CTRL, value8); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + " power-on :REG_LDOV12D_CTRL Reg0x21:0x%02x\n", + value8); + udelay(100); + value8 = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL); + value8 &= ~ISO_MD2PP; + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, value8); + } + /* auto enable WLAN */ + pollingCount = 0; + value16 = rtl_read_word(rtlpriv, REG_APS_FSMCO); + value16 |= APFM_ONMAC; + rtl_write_word(rtlpriv, REG_APS_FSMCO, value16); + do { + if (!(rtl_read_word(rtlpriv, REG_APS_FSMCO) & APFM_ONMAC)) { + pr_info("MAC auto ON okay!\n"); + break; + } + if (pollingCount++ > 1000) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + "Failed to polling REG_APS_FSMCO[APFM_ONMAC] done!\n"); + return -ENODEV; + } + } while (true); + /* Enable Radio ,GPIO ,and LED function */ + rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x0812); + /* release RF digital isolation */ + value16 = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL); + value16 &= ~ISO_DIOR; + rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, value16); + /* Reconsider when to do this operation after asking HWSD. */ + pollingCount = 0; + rtl_write_byte(rtlpriv, REG_APSD_CTRL, (rtl_read_byte(rtlpriv, + REG_APSD_CTRL) & ~BIT(6))); + do { + pollingCount++; + } while ((pollingCount < 200) && + (rtl_read_byte(rtlpriv, REG_APSD_CTRL) & BIT(7))); + /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */ + value16 = rtl_read_word(rtlpriv, REG_CR); + value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN | + PROTOCOL_EN | SCHEDULE_EN | MACTXEN | MACRXEN | ENSEC); + rtl_write_word(rtlpriv, REG_CR, value16); + return status; +} + +static void _rtl92cu_init_queue_reserved_page(struct ieee80211_hw *hw, + bool wmm_enable, + u8 out_ep_num, + u8 queue_sel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool isChipN = IS_NORMAL_CHIP(rtlhal->version); + u32 outEPNum = (u32)out_ep_num; + u32 numHQ = 0; + u32 numLQ = 0; + u32 numNQ = 0; + u32 numPubQ; + u32 value32; + u8 value8; + u32 txQPageNum, txQPageUnit, txQRemainPage; + + if (!wmm_enable) { + numPubQ = (isChipN) ? CHIP_B_PAGE_NUM_PUBQ : + CHIP_A_PAGE_NUM_PUBQ; + txQPageNum = TX_TOTAL_PAGE_NUMBER - numPubQ; + + txQPageUnit = txQPageNum/outEPNum; + txQRemainPage = txQPageNum % outEPNum; + if (queue_sel & TX_SELE_HQ) + numHQ = txQPageUnit; + if (queue_sel & TX_SELE_LQ) + numLQ = txQPageUnit; + /* HIGH priority queue always present in the configuration of + * 2 out-ep. Remainder pages have assigned to High queue */ + if ((outEPNum > 1) && (txQRemainPage)) + numHQ += txQRemainPage; + /* NOTE: This step done before writting REG_RQPN. */ + if (isChipN) { + if (queue_sel & TX_SELE_NQ) + numNQ = txQPageUnit; + value8 = (u8)_NPQ(numNQ); + rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8); + } + } else { + /* for WMM ,number of out-ep must more than or equal to 2! */ + numPubQ = isChipN ? WMM_CHIP_B_PAGE_NUM_PUBQ : + WMM_CHIP_A_PAGE_NUM_PUBQ; + if (queue_sel & TX_SELE_HQ) { + numHQ = isChipN ? WMM_CHIP_B_PAGE_NUM_HPQ : + WMM_CHIP_A_PAGE_NUM_HPQ; + } + if (queue_sel & TX_SELE_LQ) { + numLQ = isChipN ? WMM_CHIP_B_PAGE_NUM_LPQ : + WMM_CHIP_A_PAGE_NUM_LPQ; + } + /* NOTE: This step done before writting REG_RQPN. */ + if (isChipN) { + if (queue_sel & TX_SELE_NQ) + numNQ = WMM_CHIP_B_PAGE_NUM_NPQ; + value8 = (u8)_NPQ(numNQ); + rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8); + } + } + /* TX DMA */ + value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN; + rtl_write_dword(rtlpriv, REG_RQPN, value32); +} + +static void _rtl92c_init_trx_buffer(struct ieee80211_hw *hw, bool wmm_enable) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 txpktbuf_bndy; + u8 value8; + + if (!wmm_enable) + txpktbuf_bndy = TX_PAGE_BOUNDARY; + else /* for WMM */ + txpktbuf_bndy = (IS_NORMAL_CHIP(rtlhal->version)) + ? WMM_CHIP_B_TX_PAGE_BOUNDARY + : WMM_CHIP_A_TX_PAGE_BOUNDARY; + rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_TRXFF_BNDY, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_TDECTRL+1, txpktbuf_bndy); + rtl_write_word(rtlpriv, (REG_TRXFF_BNDY + 2), 0x27FF); + value8 = _PSRX(RX_PAGE_SIZE_REG_VALUE) | _PSTX(PBP_128); + rtl_write_byte(rtlpriv, REG_PBP, value8); +} + +static void _rtl92c_init_chipN_reg_priority(struct ieee80211_hw *hw, u16 beQ, + u16 bkQ, u16 viQ, u16 voQ, + u16 mgtQ, u16 hiQ) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 value16 = (rtl_read_word(rtlpriv, REG_TRXDMA_CTRL) & 0x7); + + value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) | + _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) | + _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ); + rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, value16); +} + +static void _rtl92cu_init_chipN_one_out_ep_priority(struct ieee80211_hw *hw, + bool wmm_enable, + u8 queue_sel) +{ + u16 uninitialized_var(value); + + switch (queue_sel) { + case TX_SELE_HQ: + value = QUEUE_HIGH; + break; + case TX_SELE_LQ: + value = QUEUE_LOW; + break; + case TX_SELE_NQ: + value = QUEUE_NORMAL; + break; + default: + WARN_ON(1); /* Shall not reach here! */ + break; + } + _rtl92c_init_chipN_reg_priority(hw, value, value, value, value, + value, value); + pr_info("Tx queue select: 0x%02x\n", queue_sel); +} + +static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw, + bool wmm_enable, + u8 queue_sel) +{ + u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; + u16 uninitialized_var(valueHi); + u16 uninitialized_var(valueLow); + + switch (queue_sel) { + case (TX_SELE_HQ | TX_SELE_LQ): + valueHi = QUEUE_HIGH; + valueLow = QUEUE_LOW; + break; + case (TX_SELE_NQ | TX_SELE_LQ): + valueHi = QUEUE_NORMAL; + valueLow = QUEUE_LOW; + break; + case (TX_SELE_HQ | TX_SELE_NQ): + valueHi = QUEUE_HIGH; + valueLow = QUEUE_NORMAL; + break; + default: + WARN_ON(1); + break; + } + if (!wmm_enable) { + beQ = valueLow; + bkQ = valueLow; + viQ = valueHi; + voQ = valueHi; + mgtQ = valueHi; + hiQ = valueHi; + } else {/* for WMM ,CONFIG_OUT_EP_WIFI_MODE */ + beQ = valueHi; + bkQ = valueLow; + viQ = valueLow; + voQ = valueHi; + mgtQ = valueHi; + hiQ = valueHi; + } + _rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ); + pr_info("Tx queue select: 0x%02x\n", queue_sel); +} + +static void _rtl92cu_init_chipN_three_out_ep_priority(struct ieee80211_hw *hw, + bool wmm_enable, + u8 queue_sel) +{ + u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (!wmm_enable) { /* typical setting */ + beQ = QUEUE_LOW; + bkQ = QUEUE_LOW; + viQ = QUEUE_NORMAL; + voQ = QUEUE_HIGH; + mgtQ = QUEUE_HIGH; + hiQ = QUEUE_HIGH; + } else { /* for WMM */ + beQ = QUEUE_LOW; + bkQ = QUEUE_NORMAL; + viQ = QUEUE_NORMAL; + voQ = QUEUE_HIGH; + mgtQ = QUEUE_HIGH; + hiQ = QUEUE_HIGH; + } + _rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ); + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Tx queue select :0x%02x..\n", + queue_sel); +} + +static void _rtl92cu_init_chipN_queue_priority(struct ieee80211_hw *hw, + bool wmm_enable, + u8 out_ep_num, + u8 queue_sel) +{ + switch (out_ep_num) { + case 1: + _rtl92cu_init_chipN_one_out_ep_priority(hw, wmm_enable, + queue_sel); + break; + case 2: + _rtl92cu_init_chipN_two_out_ep_priority(hw, wmm_enable, + queue_sel); + break; + case 3: + _rtl92cu_init_chipN_three_out_ep_priority(hw, wmm_enable, + queue_sel); + break; + default: + WARN_ON(1); /* Shall not reach here! */ + break; + } +} + +static void _rtl92cu_init_chipT_queue_priority(struct ieee80211_hw *hw, + bool wmm_enable, + u8 out_ep_num, + u8 queue_sel) +{ + u8 hq_sele = 0; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (out_ep_num) { + case 2: /* (TX_SELE_HQ|TX_SELE_LQ) */ + if (!wmm_enable) /* typical setting */ + hq_sele = HQSEL_VOQ | HQSEL_VIQ | HQSEL_MGTQ | + HQSEL_HIQ; + else /* for WMM */ + hq_sele = HQSEL_VOQ | HQSEL_BEQ | HQSEL_MGTQ | + HQSEL_HIQ; + break; + case 1: + if (TX_SELE_LQ == queue_sel) { + /* map all endpoint to Low queue */ + hq_sele = 0; + } else if (TX_SELE_HQ == queue_sel) { + /* map all endpoint to High queue */ + hq_sele = HQSEL_VOQ | HQSEL_VIQ | HQSEL_BEQ | + HQSEL_BKQ | HQSEL_MGTQ | HQSEL_HIQ; + } + break; + default: + WARN_ON(1); /* Shall not reach here! */ + break; + } + rtl_write_byte(rtlpriv, (REG_TRXDMA_CTRL+1), hq_sele); + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Tx queue select :0x%02x..\n", + hq_sele); +} + +static void _rtl92cu_init_queue_priority(struct ieee80211_hw *hw, + bool wmm_enable, + u8 out_ep_num, + u8 queue_sel) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + if (IS_NORMAL_CHIP(rtlhal->version)) + _rtl92cu_init_chipN_queue_priority(hw, wmm_enable, out_ep_num, + queue_sel); + else + _rtl92cu_init_chipT_queue_priority(hw, wmm_enable, out_ep_num, + queue_sel); +} + +static void _rtl92cu_init_usb_aggregation(struct ieee80211_hw *hw) +{ +} + +static void _rtl92cu_init_wmac_setting(struct ieee80211_hw *hw) +{ + u16 value16; + u32 value32; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + value32 = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APPFCS | + RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL | + RCR_APP_MIC | RCR_APP_PHYSTS | RCR_ACRC32); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&value32)); + /* Accept all multicast address */ + rtl_write_dword(rtlpriv, REG_MAR, 0xFFFFFFFF); + rtl_write_dword(rtlpriv, REG_MAR + 4, 0xFFFFFFFF); + /* Accept all management frames */ + value16 = 0xFFFF; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MGT_FILTER, + (u8 *)(&value16)); + /* Reject all control frame - default value is 0 */ + value16 = 0x0; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CTRL_FILTER, + (u8 *)(&value16)); + /* Accept all data frames */ + value16 = 0xFFFF; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_DATA_FILTER, + (u8 *)(&value16)); +} + +static void _rtl92cu_init_beacon_parameters(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + + rtl_write_word(rtlpriv, REG_BCN_CTRL, 0x1010); + + /* TODO: Remove these magic number */ + rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404); + rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME); + rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); + /* Change beacon AIFS to the largest number + * beacause test chip does not contension before sending beacon. + */ + if (IS_NORMAL_CHIP(rtlhal->version)) + rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F); + else + rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF); +} + +static int _rtl92cu_init_mac(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); + int err = 0; + u32 boundary = 0; + u8 wmm_enable = false; /* TODO */ + u8 out_ep_nums = rtlusb->out_ep_nums; + u8 queue_sel = rtlusb->out_queue_sel; + err = _rtl92cu_init_power_on(hw); + + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to init power on!\n"); + return err; + } + if (!wmm_enable) { + boundary = TX_PAGE_BOUNDARY; + } else { /* for WMM */ + boundary = (IS_NORMAL_CHIP(rtlhal->version)) + ? WMM_CHIP_B_TX_PAGE_BOUNDARY + : WMM_CHIP_A_TX_PAGE_BOUNDARY; + } + if (false == rtl92c_init_llt_table(hw, boundary)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to init LLT Table!\n"); + return -EINVAL; + } + _rtl92cu_init_queue_reserved_page(hw, wmm_enable, out_ep_nums, + queue_sel); + _rtl92c_init_trx_buffer(hw, wmm_enable); + _rtl92cu_init_queue_priority(hw, wmm_enable, out_ep_nums, + queue_sel); + /* Get Rx PHY status in order to report RSSI and others. */ + rtl92c_init_driver_info_size(hw, RTL92C_DRIVER_INFO_SIZE); + rtl92c_init_interrupt(hw); + rtl92c_init_network_type(hw); + _rtl92cu_init_wmac_setting(hw); + rtl92c_init_adaptive_ctrl(hw); + rtl92c_init_edca(hw); + rtl92c_init_rate_fallback(hw); + rtl92c_init_retry_function(hw); + _rtl92cu_init_usb_aggregation(hw); + rtlpriv->cfg->ops->set_bw_mode(hw, NL80211_CHAN_HT20); + rtl92c_set_min_space(hw, IS_92C_SERIAL(rtlhal->version)); + _rtl92cu_init_beacon_parameters(hw); + rtl92c_init_ampdu_aggregation(hw); + rtl92c_init_beacon_max_error(hw); + return err; +} + +void rtl92cu_enable_hw_security_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 sec_reg_value = 0x0; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", + rtlpriv->sec.pairwise_enc_algorithm, + rtlpriv->sec.group_enc_algorithm); + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "not open sw encryption\n"); + return; + } + sec_reg_value = SCR_TxEncEnable | SCR_RxDecEnable; + if (rtlpriv->sec.use_defaultkey) { + sec_reg_value |= SCR_TxUseDK; + sec_reg_value |= SCR_RxUseDK; + } + if (IS_NORMAL_CHIP(rtlhal->version)) + sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); + rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "The SECR-value %x\n", + sec_reg_value); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); +} + +static void _rtl92cu_hw_configure(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + + /* To Fix MAC loopback mode fail. */ + rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f); + rtl_write_byte(rtlpriv, 0x15, 0xe9); + /* HW SEQ CTRL */ + /* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */ + rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); + /* fixed USB interface interference issue */ + rtl_write_byte(rtlpriv, 0xfe40, 0xe0); + rtl_write_byte(rtlpriv, 0xfe41, 0x8d); + rtl_write_byte(rtlpriv, 0xfe42, 0x80); + rtlusb->reg_bcn_ctrl_val = 0x18; + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlusb->reg_bcn_ctrl_val); +} + +static void _InitPABias(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 pa_setting; + + /* FIXED PA current issue */ + pa_setting = efuse_read_1byte(hw, 0x1FA); + if (!(pa_setting & BIT(0))) { + rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0x0F406); + rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0x4F406); + rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0x8F406); + rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0xCF406); + } + if (!(pa_setting & BIT(1)) && IS_NORMAL_CHIP(rtlhal->version) && + IS_92C_SERIAL(rtlhal->version)) { + rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0x0F406); + rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0x4F406); + rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0x8F406); + rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0xCF406); + } + if (!(pa_setting & BIT(4))) { + pa_setting = rtl_read_byte(rtlpriv, 0x16); + pa_setting &= 0x0F; + rtl_write_byte(rtlpriv, 0x16, pa_setting | 0x90); + } +} + +int rtl92cu_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + int err = 0; + unsigned long flags; + + /* As this function can take a very long time (up to 350 ms) + * and can be called with irqs disabled, reenable the irqs + * to let the other devices continue being serviced. + * + * It is safe doing so since our own interrupts will only be enabled + * in a subsequent step. + */ + local_save_flags(flags); + local_irq_enable(); + + rtlhal->fw_ready = false; + rtlhal->hw_type = HARDWARE_TYPE_RTL8192CU; + err = _rtl92cu_init_mac(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "init mac failed!\n"); + goto exit; + } + err = rtl92c_download_fw(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW now..\n"); + err = 1; + goto exit; + } + + rtlhal->fw_ready = true; + rtlhal->last_hmeboxnum = 0; /* h2c */ + _rtl92cu_phy_param_tab_init(hw); + rtl92cu_phy_mac_config(hw); + rtl92cu_phy_bb_config(hw); + rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; + rtl92c_phy_rf_config(hw); + if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && + !IS_92C_SERIAL(rtlhal->version)) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00); + } + rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtl92cu_bb_block_on(hw); + rtl_cam_reset_all_entry(hw); + rtl92cu_enable_hw_security_config(hw); + ppsc->rfpwr_state = ERFON; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); + if (ppsc->rfpwr_state == ERFON) { + rtl92c_phy_set_rfpath_switch(hw, 1); + if (rtlphy->iqk_initialized) { + rtl92c_phy_iq_calibrate(hw, true); + } else { + rtl92c_phy_iq_calibrate(hw, false); + rtlphy->iqk_initialized = true; + } + rtl92c_dm_check_txpower_tracking(hw); + rtl92c_phy_lc_calibrate(hw); + } + _rtl92cu_hw_configure(hw); + _InitPABias(hw); + rtl92c_dm_init(hw); +exit: + local_irq_restore(flags); + return err; +} + +static void _DisableRFAFEAndResetBB(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); +/************************************** +a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue +b. RF path 0 offset 0x00 = 0x00 disable RF +c. APSD_CTRL 0x600[7:0] = 0x40 +d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine +e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine +***************************************/ + u8 eRFPath = 0, value8 = 0; + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_rfreg(hw, (enum radio_path)eRFPath, 0x0, MASKBYTE0, 0x0); + + value8 |= APSDOFF; + rtl_write_byte(rtlpriv, REG_APSD_CTRL, value8); /*0x40*/ + value8 = 0; + value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, value8);/*0x16*/ + value8 &= (~FEN_BB_GLB_RSTn); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, value8); /*0x14*/ +} + +static void _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlhal->fw_version <= 0x20) { + /***************************** + f. MCUFWDL 0x80[7:0]=0 reset MCU ready status + g. SYS_FUNC_EN 0x02[10]= 0 reset MCU reg, (8051 reset) + h. SYS_FUNC_EN 0x02[15-12]= 5 reset MAC reg, DCORE + i. SYS_FUNC_EN 0x02[10]= 1 enable MCU reg, (8051 enable) + ******************************/ + u16 valu16 = 0; + + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); + valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (valu16 & + (~FEN_CPUEN))); /* reset MCU ,8051 */ + valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN)&0x0FFF; + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (valu16 | + (FEN_HWPDN|FEN_ELDR))); /* reset MAC */ + valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (valu16 | + FEN_CPUEN)); /* enable MCU ,8051 */ + } else { + u8 retry_cnts = 0; + + /* IF fw in RAM code, do reset */ + if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(1)) { + /* reset MCU ready status */ + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); + /* 8051 reset by self */ + rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20); + while ((retry_cnts++ < 100) && + (FEN_CPUEN & rtl_read_word(rtlpriv, + REG_SYS_FUNC_EN))) { + udelay(50); + } + if (retry_cnts >= 100) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "#####=> 8051 reset failed!.........................\n"); + /* if 8051 reset fail, reset MAC. */ + rtl_write_byte(rtlpriv, + REG_SYS_FUNC_EN + 1, + 0x50); + udelay(100); + } + } + /* Reset MAC and Enable 8051 */ + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x54); + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); + } + if (bWithoutHWSM) { + /***************************** + Without HW auto state machine + g.SYS_CLKR 0x08[15:0] = 0x30A3 disable MAC clock + h.AFE_PLL_CTRL 0x28[7:0] = 0x80 disable AFE PLL + i.AFE_XTAL_CTRL 0x24[15:0] = 0x880F gated AFE DIG_CLOCK + j.SYS_ISu_CTRL 0x00[7:0] = 0xF9 isolated digital to PON + ******************************/ + rtl_write_word(rtlpriv, REG_SYS_CLKR, 0x70A3); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); + rtl_write_word(rtlpriv, REG_AFE_XTAL_CTRL, 0x880F); + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xF9); + } +} + +static void _ResetDigitalProcedure2(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); +/***************************** +k. SYS_FUNC_EN 0x03[7:0] = 0x44 disable ELDR runction +l. SYS_CLKR 0x08[15:0] = 0x3083 disable ELDR clock +m. SYS_ISO_CTRL 0x01[7:0] = 0x83 isolated ELDR to PON +******************************/ + rtl_write_word(rtlpriv, REG_SYS_CLKR, 0x70A3); + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL+1, 0x82); +} + +static void _DisableGPIO(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); +/*************************************** +j. GPIO_PIN_CTRL 0x44[31:0]=0x000 +k. Value = GPIO_PIN_CTRL[7:0] +l. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); write ext PIN level +m. GPIO_MUXCFG 0x42 [15:0] = 0x0780 +n. LEDCFG 0x4C[15:0] = 0x8080 +***************************************/ + u8 value8; + u16 value16; + u32 value32; + + /* 1. Disable GPIO[7:0] */ + rtl_write_word(rtlpriv, REG_GPIO_PIN_CTRL+2, 0x0000); + value32 = rtl_read_dword(rtlpriv, REG_GPIO_PIN_CTRL) & 0xFFFF00FF; + value8 = (u8)(value32&0x000000FF); + value32 |= ((value8<<8) | 0x00FF0000); + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, value32); + /* 2. Disable GPIO[10:8] */ + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG+3, 0x00); + value16 = rtl_read_word(rtlpriv, REG_GPIO_MUXCFG+2) & 0xFF0F; + value8 = (u8)(value16&0x000F); + value16 |= ((value8<<4) | 0x0780); + rtl_write_word(rtlpriv, REG_GPIO_PIN_CTRL+2, value16); + /* 3. Disable LED0 & 1 */ + rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); +} + +static void _DisableAnalog(struct ieee80211_hw *hw, bool bWithoutHWSM) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 value16 = 0; + u8 value8 = 0; + + if (bWithoutHWSM) { + /***************************** + n. LDOA15_CTRL 0x20[7:0] = 0x04 disable A15 power + o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power + r. When driver call disable, the ASIC will turn off remaining + clock automatically + ******************************/ + rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x04); + value8 = rtl_read_byte(rtlpriv, REG_LDOV12D_CTRL); + value8 &= (~LDV12_EN); + rtl_write_byte(rtlpriv, REG_LDOV12D_CTRL, value8); + } + +/***************************** +h. SPS0_CTRL 0x11[7:0] = 0x23 enter PFM mode +i. APS_FSMCO 0x04[15:0] = 0x4802 set USB suspend +******************************/ + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); + value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN); + rtl_write_word(rtlpriv, REG_APS_FSMCO, (u16)value16); + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E); +} + +static void _CardDisableHWSM(struct ieee80211_hw *hw) +{ + /* ==== RF Off Sequence ==== */ + _DisableRFAFEAndResetBB(hw); + /* ==== Reset digital sequence ====== */ + _ResetDigitalProcedure1(hw, false); + /* ==== Pull GPIO PIN to balance level and LED control ====== */ + _DisableGPIO(hw); + /* ==== Disable analog sequence === */ + _DisableAnalog(hw, false); +} + +static void _CardDisableWithoutHWSM(struct ieee80211_hw *hw) +{ + /*==== RF Off Sequence ==== */ + _DisableRFAFEAndResetBB(hw); + /* ==== Reset digital sequence ====== */ + _ResetDigitalProcedure1(hw, true); + /* ==== Pull GPIO PIN to balance level and LED control ====== */ + _DisableGPIO(hw); + /* ==== Reset digital sequence ====== */ + _ResetDigitalProcedure2(hw); + /* ==== Disable analog sequence === */ + _DisableAnalog(hw, true); +} + +static void _rtl92cu_set_bcn_ctrl_reg(struct ieee80211_hw *hw, + u8 set_bits, u8 clear_bits) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + + rtlusb->reg_bcn_ctrl_val |= set_bits; + rtlusb->reg_bcn_ctrl_val &= ~clear_bits; + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlusb->reg_bcn_ctrl_val); +} + +static void _rtl92cu_stop_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 tmp1byte = 0; + if (IS_NORMAL_CHIP(rtlhal->version)) { + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, + tmp1byte & (~BIT(6))); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); + } else { + rtl_write_byte(rtlpriv, REG_TXPAUSE, + rtl_read_byte(rtlpriv, REG_TXPAUSE) | BIT(6)); + } +} + +static void _rtl92cu_resume_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 tmp1byte = 0; + + if (IS_NORMAL_CHIP(rtlhal->version)) { + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, + tmp1byte | BIT(6)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte |= BIT(0); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); + } else { + rtl_write_byte(rtlpriv, REG_TXPAUSE, + rtl_read_byte(rtlpriv, REG_TXPAUSE) & (~BIT(6))); + } +} + +static void _rtl92cu_enable_bcn_sub_func(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + + if (IS_NORMAL_CHIP(rtlhal->version)) + _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(1)); + else + _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4)); +} + +static void _rtl92cu_disable_bcn_sub_func(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + + if (IS_NORMAL_CHIP(rtlhal->version)) + _rtl92cu_set_bcn_ctrl_reg(hw, BIT(1), 0); + else + _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0); +} + +static int _rtl92cu_set_media_status(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_msr = rtl_read_byte(rtlpriv, MSR); + enum led_ctl_mode ledaction = LED_CTL_NO_LINK; + + bt_msr &= 0xfc; + if (type == NL80211_IFTYPE_UNSPECIFIED || type == + NL80211_IFTYPE_STATION) { + _rtl92cu_stop_tx_beacon(hw); + _rtl92cu_enable_bcn_sub_func(hw); + } else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP) { + _rtl92cu_resume_tx_beacon(hw); + _rtl92cu_disable_bcn_sub_func(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set HW_VAR_MEDIA_STATUS:No such media status(%x)\n", + type); + } + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + bt_msr |= MSR_NOLINK; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to NO LINK!\n"); + break; + case NL80211_IFTYPE_ADHOC: + bt_msr |= MSR_ADHOC; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to Ad Hoc!\n"); + break; + case NL80211_IFTYPE_STATION: + bt_msr |= MSR_INFRA; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to STA!\n"); + break; + case NL80211_IFTYPE_AP: + bt_msr |= MSR_AP; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to AP!\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Network type %d not supported!\n", type); + goto error_out; + } + rtl_write_byte(rtlpriv, MSR, bt_msr); + rtlpriv->cfg->ops->led_control(hw, ledaction); + if ((bt_msr & MSR_MASK) == MSR_AP) + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); + else + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); + return 0; +error_out: + return 1; +} + +void rtl92cu_card_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + enum nl80211_iftype opmode; + + mac->link_state = MAC80211_NOLINK; + opmode = NL80211_IFTYPE_UNSPECIFIED; + _rtl92cu_set_media_status(hw, opmode); + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + if (rtlusb->disableHWSM) + _CardDisableHWSM(hw); + else + _CardDisableWithoutHWSM(hw); + + /* after power off we should do iqk again */ + rtlpriv->phy.iqk_initialized = false; +} + +void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u32 reg_rcr; + + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); + + if (check_bssid) { + u8 tmp; + if (IS_NORMAL_CHIP(rtlhal->version)) { + reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); + tmp = BIT(4); + } else { + reg_rcr |= RCR_CBSSID; + tmp = BIT(4) | BIT(5); + } + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, + (u8 *) (®_rcr)); + _rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp); + } else { + u8 tmp; + if (IS_NORMAL_CHIP(rtlhal->version)) { + reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); + tmp = BIT(4); + } else { + reg_rcr &= ~RCR_CBSSID; + tmp = BIT(4) | BIT(5); + } + reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_RCR, (u8 *) (®_rcr)); + _rtl92cu_set_bcn_ctrl_reg(hw, tmp, 0); + } +} + +/*========================================================================== */ + +int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (_rtl92cu_set_media_status(hw, type)) + return -EOPNOTSUPP; + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP) + rtl92cu_set_check_bssid(hw, true); + } else { + rtl92cu_set_check_bssid(hw, false); + } + + return 0; +} + +static void _beacon_function_enable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + _rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4) | BIT(3) | BIT(1)), 0x00); + rtl_write_byte(rtlpriv, REG_RD_CTRL+1, 0x6F); +} + +void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw) +{ + + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval, atim_window; + u32 value32; + + bcn_interval = mac->beacon_interval; + atim_window = 2; /*FIX MERGE */ + rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + _rtl92cu_init_beacon_parameters(hw); + rtl_write_byte(rtlpriv, REG_SLOT, 0x09); + /* + * Force beacon frame transmission even after receiving beacon frame + * from other ad hoc STA + * + * + * Reset TSF Timer to zero, added by Roger. 2008.06.24 + */ + value32 = rtl_read_dword(rtlpriv, REG_TCR); + value32 &= ~TSFRST; + rtl_write_dword(rtlpriv, REG_TCR, value32); + value32 |= TSFRST; + rtl_write_dword(rtlpriv, REG_TCR, value32); + RT_TRACE(rtlpriv, COMP_INIT|COMP_BEACON, DBG_LOUD, + "SetBeaconRelatedRegisters8192CUsb(): Set TCR(%x)\n", + value32); + /* TODO: Modify later (Find the right parameters) + * NOTE: Fix test chip's bug (about contention windows's randomness) */ + if ((mac->opmode == NL80211_IFTYPE_ADHOC) || + (mac->opmode == NL80211_IFTYPE_MESH_POINT) || + (mac->opmode == NL80211_IFTYPE_AP)) { + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x50); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x50); + } + _beacon_function_enable(hw); +} + +void rtl92cu_set_beacon_interval(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval = mac->beacon_interval; + + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, "beacon_interval:%d\n", + bcn_interval); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); +} + +void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr) +{ +} + +void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + switch (variable) { + case HW_VAR_RCR: + *((u32 *)(val)) = mac->rx_conf; + break; + case HW_VAR_RF_STATE: + *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; + break; + case HW_VAR_FWLPS_RF_ON:{ + enum rf_pwrstate rfState; + u32 val_rcr; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, + (u8 *)(&rfState)); + if (rfState == ERFOFF) { + *((bool *) (val)) = true; + } else { + val_rcr = rtl_read_dword(rtlpriv, REG_RCR); + val_rcr &= 0x00070000; + if (val_rcr) + *((bool *) (val)) = false; + else + *((bool *) (val)) = true; + } + break; + } + case HW_VAR_FW_PSMODE_STATUS: + *((bool *) (val)) = ppsc->fw_current_inpsmode; + break; + case HW_VAR_CORRECT_TSF:{ + u64 tsf; + u32 *ptsf_low = (u32 *)&tsf; + u32 *ptsf_high = ((u32 *)&tsf) + 1; + + *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); + *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + *((u64 *)(val)) = tsf; + break; + } + case HW_VAR_MGT_FILTER: + *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP0); + break; + case HW_VAR_CTRL_FILTER: + *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP1); + break; + case HW_VAR_DATA_FILTER: + *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP2); + break; + case HAL_DEF_WOWLAN: + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } +} + +static bool usb_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + /* Currently nothing happens here. + * Traffic stops after some seconds in WPA2 802.11n mode. + * Maybe because rtl8192cu chip should be set from here? + * If I understand correctly, the realtek vendor driver sends some urbs + * if its "here". + * + * This is maybe necessary: + * rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, 1, 1, skb); + */ + return true; +} + +void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + enum wireless_mode wirelessmode = mac->mode; + u8 idx = 0; + + switch (variable) { + case HW_VAR_ETHER_ADDR:{ + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_MACID + idx), + val[idx]); + } + break; + } + case HW_VAR_BASIC_RATE:{ + u16 rate_cfg = ((u16 *) val)[0]; + u8 rate_index = 0; + + rate_cfg &= 0x15f; + /* TODO */ + /* if (mac->current_network.vender == HT_IOT_PEER_CISCO + * && ((rate_cfg & 0x150) == 0)) { + * rate_cfg |= 0x010; + * } */ + rate_cfg |= 0x01; + rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); + rtl_write_byte(rtlpriv, REG_RRSR + 1, + (rate_cfg >> 8) & 0xff); + while (rate_cfg > 0x1) { + rate_cfg >>= 1; + rate_index++; + } + rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, + rate_index); + break; + } + case HW_VAR_BSSID:{ + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_BSSID + idx), + val[idx]); + } + break; + } + case HW_VAR_SIFS:{ + rtl_write_byte(rtlpriv, REG_SIFS_CCK + 1, val[0]); + rtl_write_byte(rtlpriv, REG_SIFS_OFDM + 1, val[1]); + rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); + rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); + rtl_write_byte(rtlpriv, REG_R2T_SIFS+1, val[0]); + rtl_write_byte(rtlpriv, REG_T2T_SIFS+1, val[0]); + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, "HW_VAR_SIFS\n"); + break; + } + case HW_VAR_SLOT_TIME:{ + u8 e_aci; + u8 QOS_MODE = 1; + + rtl_write_byte(rtlpriv, REG_SLOT, val[0]); + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "HW_VAR_SLOT_TIME %x\n", val[0]); + if (QOS_MODE) { + for (e_aci = 0; e_aci < AC_MAX; e_aci++) + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AC_PARAM, + &e_aci); + } else { + u8 sifstime = 0; + u8 u1bAIFS; + + if (IS_WIRELESS_MODE_A(wirelessmode) || + IS_WIRELESS_MODE_N_24G(wirelessmode) || + IS_WIRELESS_MODE_N_5G(wirelessmode)) + sifstime = 16; + else + sifstime = 10; + u1bAIFS = sifstime + (2 * val[0]); + rtl_write_byte(rtlpriv, REG_EDCA_VO_PARAM, + u1bAIFS); + rtl_write_byte(rtlpriv, REG_EDCA_VI_PARAM, + u1bAIFS); + rtl_write_byte(rtlpriv, REG_EDCA_BE_PARAM, + u1bAIFS); + rtl_write_byte(rtlpriv, REG_EDCA_BK_PARAM, + u1bAIFS); + } + break; + } + case HW_VAR_ACK_PREAMBLE:{ + u8 reg_tmp; + u8 short_preamble = (bool)*val; + reg_tmp = 0; + if (short_preamble) + reg_tmp |= 0x80; + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp); + break; + } + case HW_VAR_AMPDU_MIN_SPACE:{ + u8 min_spacing_to_set; + u8 sec_min_space; + + min_spacing_to_set = *val; + if (min_spacing_to_set <= 7) { + switch (rtlpriv->sec.pairwise_enc_algorithm) { + case NO_ENCRYPTION: + case AESCCMP_ENCRYPTION: + sec_min_space = 0; + break; + case WEP40_ENCRYPTION: + case WEP104_ENCRYPTION: + case TKIP_ENCRYPTION: + sec_min_space = 6; + break; + default: + sec_min_space = 7; + break; + } + if (min_spacing_to_set < sec_min_space) + min_spacing_to_set = sec_min_space; + mac->min_space_cfg = ((mac->min_space_cfg & + 0xf8) | + min_spacing_to_set); + *val = min_spacing_to_set; + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", + mac->min_space_cfg); + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + } + break; + } + case HW_VAR_SHORTGI_DENSITY:{ + u8 density_to_set; + + density_to_set = *val; + density_to_set &= 0x1f; + mac->min_space_cfg &= 0x07; + mac->min_space_cfg |= (density_to_set << 3); + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_SHORTGI_DENSITY: %#x\n", + mac->min_space_cfg); + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + break; + } + case HW_VAR_AMPDU_FACTOR:{ + u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9}; + u8 factor_toset; + u8 *p_regtoset = NULL; + u8 index = 0; + + p_regtoset = regtoset_normal; + factor_toset = *val; + if (factor_toset <= 3) { + factor_toset = (1 << (factor_toset + 2)); + if (factor_toset > 0xf) + factor_toset = 0xf; + for (index = 0; index < 4; index++) { + if ((p_regtoset[index] & 0xf0) > + (factor_toset << 4)) + p_regtoset[index] = + (p_regtoset[index] & 0x0f) + | (factor_toset << 4); + if ((p_regtoset[index] & 0x0f) > + factor_toset) + p_regtoset[index] = + (p_regtoset[index] & 0xf0) + | (factor_toset); + rtl_write_byte(rtlpriv, + (REG_AGGLEN_LMT + index), + p_regtoset[index]); + } + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_FACTOR: %#x\n", + factor_toset); + } + break; + } + case HW_VAR_AC_PARAM:{ + u8 e_aci = *val; + u32 u4b_ac_param; + u16 cw_min = le16_to_cpu(mac->ac[e_aci].cw_min); + u16 cw_max = le16_to_cpu(mac->ac[e_aci].cw_max); + u16 tx_op = le16_to_cpu(mac->ac[e_aci].tx_op); + + u4b_ac_param = (u32) mac->ac[e_aci].aifs; + u4b_ac_param |= (u32) ((cw_min & 0xF) << + AC_PARAM_ECW_MIN_OFFSET); + u4b_ac_param |= (u32) ((cw_max & 0xF) << + AC_PARAM_ECW_MAX_OFFSET); + u4b_ac_param |= (u32) tx_op << AC_PARAM_TXOP_OFFSET; + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "queue:%x, ac_param:%x\n", + e_aci, u4b_ac_param); + switch (e_aci) { + case AC1_BK: + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, + u4b_ac_param); + break; + case AC0_BE: + rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, + u4b_ac_param); + break; + case AC2_VI: + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, + u4b_ac_param); + break; + case AC3_VO: + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, + u4b_ac_param); + break; + default: + RT_ASSERT(false, "invalid aci: %d !\n", + e_aci); + break; + } + break; + } + case HW_VAR_RCR:{ + rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]); + mac->rx_conf = ((u32 *) (val))[0]; + RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG, + "### Set RCR(0x%08x) ###\n", mac->rx_conf); + break; + } + case HW_VAR_RETRY_LIMIT:{ + u8 retry_limit = val[0]; + + rtl_write_word(rtlpriv, REG_RL, + retry_limit << RETRY_LIMIT_SHORT_SHIFT | + retry_limit << RETRY_LIMIT_LONG_SHIFT); + RT_TRACE(rtlpriv, COMP_MLME, DBG_DMESG, + "Set HW_VAR_RETRY_LIMIT(0x%08x)\n", + retry_limit); + break; + } + case HW_VAR_DUAL_TSF_RST: + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); + break; + case HW_VAR_EFUSE_BYTES: + rtlefuse->efuse_usedbytes = *((u16 *) val); + break; + case HW_VAR_EFUSE_USAGE: + rtlefuse->efuse_usedpercentage = *val; + break; + case HW_VAR_IO_CMD: + rtl92c_phy_set_io_cmd(hw, (*(enum io_type *)val)); + break; + case HW_VAR_WPA_CONFIG: + rtl_write_byte(rtlpriv, REG_SECCFG, *val); + break; + case HW_VAR_SET_RPWM:{ + u8 rpwm_val = rtl_read_byte(rtlpriv, REG_USB_HRPWM); + + if (rpwm_val & BIT(7)) + rtl_write_byte(rtlpriv, REG_USB_HRPWM, *val); + else + rtl_write_byte(rtlpriv, REG_USB_HRPWM, + *val | BIT(7)); + break; + } + case HW_VAR_H2C_FW_PWRMODE:{ + u8 psmode = *val; + + if ((psmode != FW_PS_ACTIVE_MODE) && + (!IS_92C_SERIAL(rtlhal->version))) + rtl92c_dm_rf_saving(hw, true); + rtl92c_set_fw_pwrmode_cmd(hw, (*val)); + break; + } + case HW_VAR_FW_PSMODE_STATUS: + ppsc->fw_current_inpsmode = *((bool *) val); + break; + case HW_VAR_H2C_FW_JOINBSSRPT:{ + u8 mstatus = *val; + u8 tmp_reg422; + bool recover = false; + + if (mstatus == RT_MEDIA_CONNECT) { + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AID, NULL); + rtl_write_byte(rtlpriv, REG_CR + 1, 0x03); + _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3)); + _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0); + tmp_reg422 = rtl_read_byte(rtlpriv, + REG_FWHW_TXQ_CTRL + 2); + if (tmp_reg422 & BIT(6)) + recover = true; + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, + tmp_reg422 & (~BIT(6))); + rtl92c_set_fw_rsvdpagepkt(hw, + &usb_cmd_send_packet); + _rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0); + _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4)); + if (recover) + rtl_write_byte(rtlpriv, + REG_FWHW_TXQ_CTRL + 2, + tmp_reg422 | BIT(6)); + rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); + } + rtl92c_set_fw_joinbss_report_cmd(hw, (*val)); + break; + } + case HW_VAR_AID:{ + u16 u2btmp; + + u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); + u2btmp &= 0xC000; + rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, + (u2btmp | mac->assoc_id)); + break; + } + case HW_VAR_CORRECT_TSF:{ + u8 btype_ibss = val[0]; + + if (btype_ibss) + _rtl92cu_stop_tx_beacon(hw); + _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3)); + rtl_write_dword(rtlpriv, REG_TSFTR, (u32)(mac->tsf & + 0xffffffff)); + rtl_write_dword(rtlpriv, REG_TSFTR + 4, + (u32)((mac->tsf >> 32) & 0xffffffff)); + _rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0); + if (btype_ibss) + _rtl92cu_resume_tx_beacon(hw); + break; + } + case HW_VAR_MGT_FILTER: + rtl_write_word(rtlpriv, REG_RXFLTMAP0, *(u16 *)val); + mac->rx_mgt_filter = *(u16 *)val; + break; + case HW_VAR_CTRL_FILTER: + rtl_write_word(rtlpriv, REG_RXFLTMAP1, *(u16 *)val); + mac->rx_ctrl_filter = *(u16 *)val; + break; + case HW_VAR_DATA_FILTER: + rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *)val); + mac->rx_data_filter = *(u16 *)val; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } +} + +static void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 ratr_value; + u8 ratr_index = 0; + u8 nmode = mac->ht_enable; + u8 mimo_ps = IEEE80211_SMPS_OFF; + u16 shortgi_rate; + u32 tmp_ratr_value; + u8 curtxbw_40mhz = mac->bw_40; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = mac->mode; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_value = sta->supp_rates[1] << 4; + else + ratr_value = sta->supp_rates[0]; + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_value = 0xfff; + + ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + if (ratr_value & 0x0000000c) + ratr_value &= 0x0000000d; + else + ratr_value &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_value &= 0x00000FF5; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + nmode = 1; + if (mimo_ps == IEEE80211_SMPS_STATIC) { + ratr_value &= 0x0007F005; + } else { + u32 ratr_mask; + + if (get_rf_type(rtlphy) == RF_1T2R || + get_rf_type(rtlphy) == RF_1T1R) + ratr_mask = 0x000ff005; + else + ratr_mask = 0x0f0ff005; + + ratr_value &= ratr_mask; + } + break; + default: + if (rtlphy->rf_type == RF_1T2R) + ratr_value &= 0x000ff0ff; + else + ratr_value &= 0x0f0ff0ff; + + break; + } + + ratr_value &= 0x0FFFFFFF; + + if (nmode && ((curtxbw_40mhz && + curshortgi_40mhz) || (!curtxbw_40mhz && + curshortgi_20mhz))) { + + ratr_value |= 0x10000000; + tmp_ratr_value = (ratr_value >> 12); + + for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { + if ((1 << shortgi_rate) & tmp_ratr_value) + break; + } + + shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | + (shortgi_rate << 4) | (shortgi_rate); + } + + rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n", + rtl_read_dword(rtlpriv, REG_ARFR0)); +} + +static void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u32 ratr_bitmap; + u8 ratr_index; + u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0; + u8 curshortgi_40mhz = curtxbw_40mhz && + (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = 0; + bool shortgi = false; + u8 rate_mask[5]; + u8 macid = 0; + u8 mimo_ps = IEEE80211_SMPS_OFF; + + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + wirelessmode = sta_entry->wireless_mode; + if (mac->opmode == NL80211_IFTYPE_STATION || + mac->opmode == NL80211_IFTYPE_MESH_POINT) + curtxbw_40mhz = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + macid = sta->aid + 1; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_bitmap = sta->supp_rates[1] << 4; + else + ratr_bitmap = sta->supp_rates[0]; + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_bitmap = 0xfff; + ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + ratr_index = RATR_INX_WIRELESS_B; + if (ratr_bitmap & 0x0000000c) + ratr_bitmap &= 0x0000000d; + else + ratr_bitmap &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_index = RATR_INX_WIRELESS_GB; + + if (rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if (rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + break; + case WIRELESS_MODE_A: + ratr_index = RATR_INX_WIRELESS_A; + ratr_bitmap &= 0x00000ff0; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (mimo_ps == IEEE80211_SMPS_STATIC) { + if (rssi_level == 1) + ratr_bitmap &= 0x00070000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0007f000; + else + ratr_bitmap &= 0x0007f005; + } else { + if (rtlphy->rf_type == RF_1T2R || + rtlphy->rf_type == RF_1T1R) { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff005; + } + } else { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x0f0f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f0ff000; + else + ratr_bitmap &= 0x0f0ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x0f0f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f0ff000; + else + ratr_bitmap &= 0x0f0ff005; + } + } + } + + if ((curtxbw_40mhz && curshortgi_40mhz) || + (!curtxbw_40mhz && curshortgi_20mhz)) { + + if (macid == 0) + shortgi = true; + else if (macid == 1) + shortgi = false; + } + break; + default: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rtlphy->rf_type == RF_1T2R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0f0ff0ff; + break; + } + sta_entry->ratr_index = ratr_index; + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "ratr_bitmap :%x\n", ratr_bitmap); + *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | + (ratr_index << 28); + rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "Rate_index:%x, ratr_val:%x, %5phC\n", + ratr_index, ratr_bitmap, rate_mask); + memcpy(rtlpriv->rate_mask, rate_mask, 5); + /* rtl92c_fill_h2c_cmd() does USB I/O and will result in a + * "scheduled while atomic" if called directly */ + schedule_work(&rtlpriv->works.fill_h2c_cmd); + + if (macid != 0) + sta_entry->ratr_index = ratr_index; +} + +void rtl92cu_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->dm.useramask) + rtl92cu_update_hal_rate_mask(hw, sta, rssi_level); + else + rtl92cu_update_hal_rate_table(hw, sta); +} + +void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 sifs_timer; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, + &mac->slot_time); + if (!mac->ht_enable) + sifs_timer = 0x0a0a; + else + sifs_timer = 0x0e0e; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); +} + +bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; + u8 u1tmp = 0; + bool actuallyset = false; + unsigned long flag = 0; + /* to do - usb autosuspend */ + u8 usb_autosuspend = 0; + + if (ppsc->swrf_processing) + return false; + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + if (ppsc->rfchange_inprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + return false; + } else { + ppsc->rfchange_inprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + cur_rfstate = ppsc->rfpwr_state; + if (usb_autosuspend) { + /* to do................... */ + } else { + if (ppsc->pwrdown_mode) { + u1tmp = rtl_read_byte(rtlpriv, REG_HSISR); + e_rfpowerstate_toset = (u1tmp & BIT(7)) ? + ERFOFF : ERFON; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "pwrdown, 0x5c(BIT7)=%02x\n", u1tmp); + } else { + rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, + rtl_read_byte(rtlpriv, + REG_MAC_PINMUX_CFG) & ~(BIT(3))); + u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); + e_rfpowerstate_toset = (u1tmp & BIT(3)) ? + ERFON : ERFOFF; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "GPIO_IN=%02x\n", u1tmp); + } + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "N-SS RF =%x\n", + e_rfpowerstate_toset); + } + if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "GPIOChangeRF - HW Radio ON, RF ON\n"); + ppsc->hwradiooff = false; + actuallyset = true; + } else if ((!ppsc->hwradiooff) && (e_rfpowerstate_toset == + ERFOFF)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "GPIOChangeRF - HW Radio OFF\n"); + ppsc->hwradiooff = true; + actuallyset = true; + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "pHalData->bHwRadioOff and eRfPowerStateToSet do not match: pHalData->bHwRadioOff %x, eRfPowerStateToSet %x\n", + ppsc->hwradiooff, e_rfpowerstate_toset); + } + if (actuallyset) { + ppsc->hwradiooff = true; + if (e_rfpowerstate_toset == ERFON) { + if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + else if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_PCI_D3) + && RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3)) + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3); + } + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + /* For power down module, we need to enable register block + * contrl reg at 0x1c. Then enable power down control bit + * of register 0x04 BIT4 and BIT15 as 1. + */ + if (ppsc->pwrdown_mode && e_rfpowerstate_toset == ERFOFF) { + /* Enable register area 0x0-0xc. */ + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0); + rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x8812); + } + if (e_rfpowerstate_toset == ERFOFF) { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + else if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_PCI_D3) + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3); + } + } else if (e_rfpowerstate_toset == ERFOFF || cur_rfstate == ERFOFF) { + /* Enter D3 or ASPM after GPIO had been done. */ + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); + else if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_PCI_D3) + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3); + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } else { + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + *valid = 1; + return !ppsc->hwradiooff; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h new file mode 100644 index 000000000000..67588083e6cc --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CU_HW_H__ +#define __RTL92CU_HW_H__ + +#define H2C_RA_MASK 6 + +#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 + +#define RX_PAGE_SIZE_REG_VALUE PBP_128 +/* Note: We will divide number of page equally for each queue + * other than public queue! */ +#define TX_TOTAL_PAGE_NUMBER 0xF8 +#define TX_PAGE_BOUNDARY (TX_TOTAL_PAGE_NUMBER + 1) + + +#define CHIP_B_PAGE_NUM_PUBQ 0xE7 + +/* For Test Chip Setting + * (HPQ + LPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */ +#define CHIP_A_PAGE_NUM_PUBQ 0x7E + + +/* For Chip A Setting */ +#define WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER 0xF5 +#define WMM_CHIP_A_TX_PAGE_BOUNDARY \ + (WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */ + +#define WMM_CHIP_A_PAGE_NUM_PUBQ 0xA3 +#define WMM_CHIP_A_PAGE_NUM_HPQ 0x29 +#define WMM_CHIP_A_PAGE_NUM_LPQ 0x29 + + + +/* Note: For Chip B Setting ,modify later */ +#define WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER 0xF5 +#define WMM_CHIP_B_TX_PAGE_BOUNDARY \ + (WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */ + +#define WMM_CHIP_B_PAGE_NUM_PUBQ 0xB0 +#define WMM_CHIP_B_PAGE_NUM_HPQ 0x29 +#define WMM_CHIP_B_PAGE_NUM_LPQ 0x1C +#define WMM_CHIP_B_PAGE_NUM_NPQ 0x1C + +#define BOARD_TYPE_NORMAL_MASK 0xE0 +#define BOARD_TYPE_TEST_MASK 0x0F + +/* should be renamed and moved to another file */ +enum _BOARD_TYPE_8192CUSB { + BOARD_USB_DONGLE = 0, /* USB dongle */ + BOARD_USB_High_PA = 1, /* USB dongle - high power PA */ + BOARD_MINICARD = 2, /* Minicard */ + BOARD_USB_SOLO = 3, /* USB solo-Slim module */ + BOARD_USB_COMBO = 4, /* USB Combo-Slim module */ +}; + +#define IS_HIGHT_PA(boardtype) \ + ((boardtype == BOARD_USB_High_PA) ? true : false) + +#define RTL92C_DRIVER_INFO_SIZE 4 +void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw); +void rtl92cu_enable_hw_security_config(struct ieee80211_hw *hw); +int rtl92cu_hw_init(struct ieee80211_hw *hw); +void rtl92cu_card_disable(struct ieee80211_hw *hw); +int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); +void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw); +void rtl92cu_set_beacon_interval(struct ieee80211_hw *hw); +void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); +void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); + +void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw); +bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid); +void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); +int rtl92c_download_fw(struct ieee80211_hw *hw); +void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); +void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); +void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, u8 *p_cmdbuffer); +bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw); +void rtl92cu_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c new file mode 100644 index 000000000000..75a2deb23af1 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.c @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../usb.h" +#include "reg.h" +#include "led.h" + +static void _rtl92cu_init_led(struct ieee80211_hw *hw, + struct rtl_led *pled, enum rtl_led_pin ledpin) +{ + pled->hw = hw; + pled->ledpin = ledpin; + pled->ledon = false; +} + +static void _rtl92cu_deInit_led(struct rtl_led *pled) +{ +} + +void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u8 ledcfg; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", + REG_LEDCFG2, pled->ledpin); + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + rtl_write_byte(rtlpriv, + REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6)); + break; + case LED_PIN_LED1: + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + pled->ledon = true; +} + +void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw); + u8 ledcfg; + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", + REG_LEDCFG2, pled->ledpin); + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg &= 0xf0; + if (usbpriv->ledctl.led_opendrain) + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(1) | BIT(5) | BIT(6))); + else + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(3) | BIT(5) | BIT(6))); + break; + case LED_PIN_LED1: + ledcfg &= 0x0f; + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + pled->ledon = false; +} + +void rtl92cu_init_sw_leds(struct ieee80211_hw *hw) +{ + struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw); + _rtl92cu_init_led(hw, &(usbpriv->ledctl.sw_led0), LED_PIN_LED0); + _rtl92cu_init_led(hw, &(usbpriv->ledctl.sw_led1), LED_PIN_LED1); +} + +void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw) +{ + struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw); + _rtl92cu_deInit_led(&(usbpriv->ledctl.sw_led0)); + _rtl92cu_deInit_led(&(usbpriv->ledctl.sw_led1)); +} + +static void _rtl92cu_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ +} + +void rtl92cu_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && + (ledaction == LED_CTL_TX || + ledaction == LED_CTL_RX || + ledaction == LED_CTL_SITE_SURVEY || + ledaction == LED_CTL_LINK || + ledaction == LED_CTL_NO_LINK || + ledaction == LED_CTL_START_TO_LINK || + ledaction == LED_CTL_POWER_ON)) { + return; + } + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d\n", ledaction); + _rtl92cu_sw_led_control(hw, ledaction); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h new file mode 100644 index 000000000000..0f372278b7af --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/led.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + *****************************************************************************/ + +#ifndef __RTL92CU_LED_H__ +#define __RTL92CU_LED_H__ + +void rtl92cu_init_sw_leds(struct ieee80211_hw *hw); +void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw); +void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92cu_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c new file mode 100644 index 000000000000..035713311a4a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c @@ -0,0 +1,827 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * +****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../usb.h" +#include "../ps.h" +#include "../cam.h" +#include "../stats.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "mac.h" +#include "trx.h" +#include "../rtl8192c/fw_common.h" + +#include + +/* macro to shorten lines */ + +#define LINK_Q ui_link_quality +#define RX_EVM rx_evm_percentage +#define RX_SIGQ rx_mimo_sig_qual + + +void rtl92c_read_chip_version(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + enum version_8192c chip_version = VERSION_UNKNOWN; + const char *versionid; + u32 value32; + + value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); + if (value32 & TRP_VAUX_EN) { + chip_version = (value32 & TYPE_ID) ? VERSION_TEST_CHIP_92C : + VERSION_TEST_CHIP_88C; + } else { + /* Normal mass production chip. */ + chip_version = NORMAL_CHIP; + chip_version |= ((value32 & TYPE_ID) ? CHIP_92C : 0); + chip_version |= ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0); + if (IS_VENDOR_UMC(chip_version)) + chip_version |= ((value32 & CHIP_VER_RTL_MASK) ? + CHIP_VENDOR_UMC_B_CUT : 0); + if (IS_92C_SERIAL(chip_version)) { + value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM); + chip_version |= ((CHIP_BONDING_IDENTIFIER(value32) == + CHIP_BONDING_92C_1T2R) ? CHIP_92C_1T2R : 0); + } + } + rtlhal->version = (enum version_8192c)chip_version; + pr_info("Chip version 0x%x\n", chip_version); + switch (rtlhal->version) { + case VERSION_NORMAL_TSMC_CHIP_92C_1T2R: + versionid = "NORMAL_B_CHIP_92C"; + break; + case VERSION_NORMAL_TSMC_CHIP_92C: + versionid = "NORMAL_TSMC_CHIP_92C"; + break; + case VERSION_NORMAL_TSMC_CHIP_88C: + versionid = "NORMAL_TSMC_CHIP_88C"; + break; + case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT: + versionid = "NORMAL_UMC_CHIP_i92C_1T2R_A_CUT"; + break; + case VERSION_NORMAL_UMC_CHIP_92C_A_CUT: + versionid = "NORMAL_UMC_CHIP_92C_A_CUT"; + break; + case VERSION_NORMAL_UMC_CHIP_88C_A_CUT: + versionid = "NORMAL_UMC_CHIP_88C_A_CUT"; + break; + case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT: + versionid = "NORMAL_UMC_CHIP_92C_1T2R_B_CUT"; + break; + case VERSION_NORMAL_UMC_CHIP_92C_B_CUT: + versionid = "NORMAL_UMC_CHIP_92C_B_CUT"; + break; + case VERSION_NORMAL_UMC_CHIP_88C_B_CUT: + versionid = "NORMAL_UMC_CHIP_88C_B_CUT"; + break; + case VERSION_TEST_CHIP_92C: + versionid = "TEST_CHIP_92C"; + break; + case VERSION_TEST_CHIP_88C: + versionid = "TEST_CHIP_88C"; + break; + default: + versionid = "UNKNOWN"; + break; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Chip Version ID: %s\n", versionid); + + if (IS_92C_SERIAL(rtlhal->version)) + rtlphy->rf_type = + (IS_92C_1T2R(rtlhal->version)) ? RF_1T2R : RF_2T2R; + else + rtlphy->rf_type = RF_1T1R; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip RF Type: %s\n", + rtlphy->rf_type == RF_2T2R ? "RF_2T2R" : "RF_1T1R"); + if (get_rf_type(rtlphy) == RF_1T1R) + rtlpriv->dm.rfpath_rxenable[0] = true; + else + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", + rtlhal->version); +} + +/** + * writeLLT - LLT table write access + * @io: io callback + * @address: LLT logical address. + * @data: LLT data content + * + * Realtek hardware access function. + * + */ +bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool status = true; + long count = 0; + u32 value = _LLT_INIT_ADDR(address) | + _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); + + rtl_write_dword(rtlpriv, REG_LLT_INIT, value); + do { + value = rtl_read_dword(rtlpriv, REG_LLT_INIT); + if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) + break; + if (count > POLLING_LLT_THRESHOLD) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to polling write LLT done at address %d! _LLT_OP_VALUE(%x)\n", + address, _LLT_OP_VALUE(value)); + status = false; + break; + } + } while (++count); + return status; +} +/** + * rtl92c_init_LLT_table - Init LLT table + * @io: io callback + * @boundary: + * + * Realtek hardware access function. + * + */ +bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary) +{ + bool rst = true; + u32 i; + + for (i = 0; i < (boundary - 1); i++) { + rst = rtl92c_llt_write(hw, i , i + 1); + if (true != rst) { + pr_err("===> %s #1 fail\n", __func__); + return rst; + } + } + /* end of list */ + rst = rtl92c_llt_write(hw, (boundary - 1), 0xFF); + if (true != rst) { + pr_err("===> %s #2 fail\n", __func__); + return rst; + } + /* Make the other pages as ring buffer + * This ring buffer is used as beacon buffer if we config this MAC + * as two MAC transfer. + * Otherwise used as local loopback buffer. + */ + for (i = boundary; i < LLT_LAST_ENTRY_OF_TX_PKT_BUFFER; i++) { + rst = rtl92c_llt_write(hw, i, (i + 1)); + if (true != rst) { + pr_err("===> %s #3 fail\n", __func__); + return rst; + } + } + /* Let last entry point to the start entry of ring buffer */ + rst = rtl92c_llt_write(hw, LLT_LAST_ENTRY_OF_TX_PKT_BUFFER, boundary); + if (true != rst) { + pr_err("===> %s #4 fail\n", __func__); + return rst; + } + return rst; +} +void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 *macaddr = p_macaddr; + u32 entry_id = 0; + bool is_pairwise = false; + static u8 cam_const_addr[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} + }; + static u8 cam_const_broad[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (clear_all) { + u8 idx = 0; + u8 cam_offset = 0; + u8 clear_number = 5; + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); + for (idx = 0; idx < clear_number; idx++) { + rtl_cam_mark_invalid(hw, cam_offset + idx); + rtl_cam_empty_entry(hw, cam_offset + idx); + if (idx < 5) { + memset(rtlpriv->sec.key_buf[idx], 0, + MAX_KEY_LEN); + rtlpriv->sec.key_len[idx] = 0; + } + } + } else { + switch (enc_algo) { + case WEP40_ENCRYPTION: + enc_algo = CAM_WEP40; + break; + case WEP104_ENCRYPTION: + enc_algo = CAM_WEP104; + break; + case TKIP_ENCRYPTION: + enc_algo = CAM_TKIP; + break; + case AESCCMP_ENCRYPTION: + enc_algo = CAM_AES; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "illegal switch case\n"); + enc_algo = CAM_TKIP; + break; + } + if (is_wepkey || rtlpriv->sec.use_defaultkey) { + macaddr = cam_const_addr[key_index]; + entry_id = key_index; + } else { + if (is_group) { + macaddr = cam_const_broad; + entry_id = key_index; + } else { + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + entry_id = rtl_cam_get_free_entry(hw, + p_macaddr); + if (entry_id >= TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, COMP_SEC, + DBG_EMERG, + "Can not find free hw security cam entry\n"); + return; + } + } else { + entry_id = CAM_PAIRWISE_KEY_POSITION; + } + + key_index = PAIRWISE_KEYIDX; + is_pairwise = true; + } + } + if (rtlpriv->sec.key_len[key_index] == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "delete one entry\n"); + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_MESH_POINT) + rtl_cam_del_entry(hw, p_macaddr); + rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "The insert KEY length is %d\n", + rtlpriv->sec.key_len[PAIRWISE_KEYIDX]); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "The insert KEY is %x %x\n", + rtlpriv->sec.key_buf[0][0], + rtlpriv->sec.key_buf[0][1]); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "add one entry\n"); + if (is_pairwise) { + RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, + "Pairwise Key content", + rtlpriv->sec.pairwise_key, + rtlpriv->sec. + key_len[PAIRWISE_KEYIDX]); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set Pairwise key\n"); + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec. + key_buf[key_index]); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set group key\n"); + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_cam_add_one_entry(hw, + rtlefuse->dev_addr, + PAIRWISE_KEYIDX, + CAM_PAIRWISE_KEY_POSITION, + enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf + [entry_id]); + } + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + } + } +} + +u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + return rtl_read_dword(rtlpriv, REG_TXDMA_STATUS); +} + +void rtl92c_enable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + + if (IS_HARDWARE_TYPE_8192CE(rtlhal)) { + rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & + 0xFFFFFFFF); + rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & + 0xFFFFFFFF); + } else { + rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] & + 0xFFFFFFFF); + rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] & + 0xFFFFFFFF); + } +} + +void rtl92c_init_interrupt(struct ieee80211_hw *hw) +{ + rtl92c_enable_interrupt(hw); +} + +void rtl92c_disable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED); + rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); +} + +void rtl92c_set_qos(struct ieee80211_hw *hw, int aci) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl92c_dm_init_edca_turbo(hw); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, (u8 *)&aci); +} + +void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size); +} + +int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) +{ + u8 value; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + value = NT_NO_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Set Network type to NO LINK!\n"); + break; + case NL80211_IFTYPE_ADHOC: + value = NT_LINK_AD_HOC; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Set Network type to Ad Hoc!\n"); + break; + case NL80211_IFTYPE_STATION: + value = NT_LINK_AP; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Set Network type to STA!\n"); + break; + case NL80211_IFTYPE_AP: + value = NT_AS_AP; + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Set Network type to AP!\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Network type %d not supported!\n", type); + return -EOPNOTSUPP; + } + rtl_write_byte(rtlpriv, MSR, value); + return 0; +} + +void rtl92c_init_network_type(struct ieee80211_hw *hw) +{ + rtl92c_set_network_type(hw, NL80211_IFTYPE_UNSPECIFIED); +} + +void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw) +{ + u16 value16; + u32 value32; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* Response Rate Set */ + value32 = rtl_read_dword(rtlpriv, REG_RRSR); + value32 &= ~RATE_BITMAP_ALL; + value32 |= RATE_RRSR_CCK_ONLY_1M; + rtl_write_dword(rtlpriv, REG_RRSR, value32); + /* SIFS (used in NAV) */ + value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10); + rtl_write_word(rtlpriv, REG_SPEC_SIFS, value16); + /* Retry Limit */ + value16 = _LRL(0x30) | _SRL(0x30); + rtl_write_dword(rtlpriv, REG_RL, value16); +} + +void rtl92c_init_rate_fallback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* Set Data Auto Rate Fallback Retry Count register. */ + rtl_write_dword(rtlpriv, REG_DARFRC, 0x00000000); + rtl_write_dword(rtlpriv, REG_DARFRC+4, 0x10080404); + rtl_write_dword(rtlpriv, REG_RARFRC, 0x04030201); + rtl_write_dword(rtlpriv, REG_RARFRC+4, 0x08070605); +} + +static void rtl92c_set_cck_sifs(struct ieee80211_hw *hw, u8 trx_sifs, + u8 ctx_sifs) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_SIFS_CCK, trx_sifs); + rtl_write_byte(rtlpriv, (REG_SIFS_CCK + 1), ctx_sifs); +} + +static void rtl92c_set_ofdm_sifs(struct ieee80211_hw *hw, u8 trx_sifs, + u8 ctx_sifs) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_SIFS_OFDM, trx_sifs); + rtl_write_byte(rtlpriv, (REG_SIFS_OFDM + 1), ctx_sifs); +} + +void rtl92c_init_edca_param(struct ieee80211_hw *hw, + u16 queue, u16 txop, u8 cw_min, u8 cw_max, u8 aifs) +{ + /* sequence: VO, VI, BE, BK ==> the same as 92C hardware design. + * referenc : enum nl80211_txq_q or ieee80211_set_wmm_default function. + */ + u32 value; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + value = (u32)aifs; + value |= ((u32)cw_min & 0xF) << 8; + value |= ((u32)cw_max & 0xF) << 12; + value |= (u32)txop << 16; + /* 92C hardware register sequence is the same as queue number. */ + rtl_write_dword(rtlpriv, (REG_EDCA_VO_PARAM + (queue * 4)), value); +} + +void rtl92c_init_edca(struct ieee80211_hw *hw) +{ + u16 value16; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* disable EDCCA count down, to reduce collison and retry */ + value16 = rtl_read_word(rtlpriv, REG_RD_CTRL); + value16 |= DIS_EDCA_CNT_DWN; + rtl_write_word(rtlpriv, REG_RD_CTRL, value16); + /* Update SIFS timing. ?????????? + * pHalData->SifsTime = 0x0e0e0a0a; */ + rtl92c_set_cck_sifs(hw, 0xa, 0xa); + rtl92c_set_ofdm_sifs(hw, 0xe, 0xe); + /* Set CCK/OFDM SIFS to be 10us. */ + rtl_write_word(rtlpriv, REG_SIFS_CCK, 0x0a0a); + rtl_write_word(rtlpriv, REG_SIFS_OFDM, 0x1010); + rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0204); + rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x014004); + /* TXOP */ + rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, 0x005EA42B); + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0x0000A44F); + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x005EA324); + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x002FA226); + /* PIFS */ + rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); + /* AGGR BREAK TIME Register */ + rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040); + rtl_write_byte(rtlpriv, REG_BCNDMATIM, 0x02); + rtl_write_byte(rtlpriv, REG_ATIMWND, 0x02); +} + +void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x99997631); + rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); + /* init AMPDU aggregation number, tuning for Tx's TP, */ + rtl_write_word(rtlpriv, 0x4CA, 0x0708); +} + +void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xFF); +} + +void rtl92c_init_rdg_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xFF); + rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200); + rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05); +} + +void rtl92c_init_retry_function(struct ieee80211_hw *hw) +{ + u8 value8; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + value8 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL); + value8 |= EN_AMPDU_RTY_NEW; + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL, value8); + /* Set ACK timeout */ + rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); +} + +void rtl92c_disable_fast_edca(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0); +} + +void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 value = is2T ? MAX_MSS_DENSITY_2T : MAX_MSS_DENSITY_1T; + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, value); +} + +/*==============================================================*/ + +static u8 _rtl92c_query_rxpwrpercentage(char antpower) +{ + if ((antpower <= -100) || (antpower >= 20)) + return 0; + else if (antpower >= 0) + return 100; + else + return 100 + antpower; +} + +static u8 _rtl92c_evm_db_to_percentage(char value) +{ + char ret_val; + + ret_val = value; + if (ret_val >= 0) + ret_val = 0; + if (ret_val <= -33) + ret_val = -33; + ret_val = 0 - ret_val; + ret_val *= 3; + if (ret_val == 99) + ret_val = 100; + return ret_val; +} + +static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw, + long currsig) +{ + long retsig; + + if (currsig >= 61 && currsig <= 100) + retsig = 90 + ((currsig - 60) / 4); + else if (currsig >= 41 && currsig <= 60) + retsig = 78 + ((currsig - 40) / 2); + else if (currsig >= 31 && currsig <= 40) + retsig = 66 + (currsig - 30); + else if (currsig >= 21 && currsig <= 30) + retsig = 54 + (currsig - 20); + else if (currsig >= 5 && currsig <= 20) + retsig = 42 + (((currsig - 5) * 2) / 3); + else if (currsig == 4) + retsig = 36; + else if (currsig == 3) + retsig = 27; + else if (currsig == 2) + retsig = 18; + else if (currsig == 1) + retsig = 9; + else + retsig = currsig; + return retsig; +} + +static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, + struct rtl_stats *pstats, + struct rx_desc_92c *p_desc, + struct rx_fwinfo_92c *p_drvinfo, + bool packet_match_bssid, + bool packet_toself, + bool packet_beacon) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct phy_sts_cck_8192s_t *cck_buf; + s8 rx_pwr_all = 0, rx_pwr[4]; + u8 rf_rx_num = 0, evm, pwdb_all; + u8 i, max_spatial_stream; + u32 rssi, total_rssi = 0; + bool in_powersavemode = false; + bool is_cck_rate; + u8 *pdesc = (u8 *)p_desc; + + is_cck_rate = RX_HAL_IS_CCK_RATE(p_desc->rxmcs); + pstats->packet_matchbssid = packet_match_bssid; + pstats->packet_toself = packet_toself; + pstats->packet_beacon = packet_beacon; + pstats->is_cck = is_cck_rate; + pstats->RX_SIGQ[0] = -1; + pstats->RX_SIGQ[1] = -1; + if (is_cck_rate) { + u8 report, cck_highpwr; + cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; + if (!in_powersavemode) + cck_highpwr = rtlphy->cck_high_power; + else + cck_highpwr = false; + if (!cck_highpwr) { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = cck_buf->cck_agc_rpt & 0xc0; + report = report >> 6; + switch (report) { + case 0x3: + rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); + break; + case 0x2: + rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); + break; + case 0x1: + rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); + break; + case 0x0: + rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); + break; + } + } else { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = p_drvinfo->cfosho[0] & 0x60; + report = report >> 5; + switch (report) { + case 0x3: + rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x2: + rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x1: + rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x0: + rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1); + break; + } + } + pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); + pstats->rx_pwdb_all = pwdb_all; + pstats->recvsignalpower = rx_pwr_all; + if (packet_match_bssid) { + u8 sq; + if (pstats->rx_pwdb_all > 40) + sq = 100; + else { + sq = cck_buf->sq_rpt; + if (sq > 64) + sq = 0; + else if (sq < 20) + sq = 100; + else + sq = ((64 - sq) * 100) / 44; + } + pstats->signalquality = sq; + pstats->RX_SIGQ[0] = sq; + pstats->RX_SIGQ[1] = -1; + } + } else { + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { + if (rtlpriv->dm.rfpath_rxenable[i]) + rf_rx_num++; + rx_pwr[i] = + ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110; + rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + rtlpriv->stats.rx_snr_db[i] = + (long)(p_drvinfo->rxsnr[i] / 2); + + if (packet_match_bssid) + pstats->rx_mimo_signalstrength[i] = (u8) rssi; + } + rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; + pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); + pstats->rx_pwdb_all = pwdb_all; + pstats->rxpower = rx_pwr_all; + pstats->recvsignalpower = rx_pwr_all; + if (GET_RX_DESC_RX_MCS(pdesc) && + GET_RX_DESC_RX_MCS(pdesc) >= DESC_RATEMCS8 && + GET_RX_DESC_RX_MCS(pdesc) <= DESC_RATEMCS15) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + for (i = 0; i < max_spatial_stream; i++) { + evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]); + if (packet_match_bssid) { + if (i == 0) + pstats->signalquality = + (u8) (evm & 0xff); + pstats->RX_SIGQ[i] = + (u8) (evm & 0xff); + } + } + } + if (is_cck_rate) + pstats->signalstrength = + (u8) (_rtl92c_signal_scale_mapping(hw, pwdb_all)); + else if (rf_rx_num != 0) + pstats->signalstrength = + (u8) (_rtl92c_signal_scale_mapping + (hw, total_rssi /= rf_rx_num)); +} + +void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct rtl_stats *pstats, + struct rx_desc_92c *pdesc, + struct rx_fwinfo_92c *p_drvinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct ieee80211_hdr *hdr; + u8 *tmp_buf; + u8 *praddr; + __le16 fc; + u16 type, cpu_fc; + bool packet_matchbssid, packet_toself, packet_beacon = false; + + tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; + hdr = (struct ieee80211_hdr *)tmp_buf; + fc = hdr->frame_control; + cpu_fc = le16_to_cpu(fc); + type = WLAN_FC_GET_TYPE(fc); + praddr = hdr->addr1; + packet_matchbssid = + ((IEEE80211_FTYPE_CTL != type) && + ether_addr_equal(mac->bssid, + (cpu_fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : + (cpu_fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : + hdr->addr3) && + (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv)); + + packet_toself = packet_matchbssid && + ether_addr_equal(praddr, rtlefuse->dev_addr); + if (ieee80211_is_beacon(fc)) + packet_beacon = true; + _rtl92c_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, + packet_matchbssid, packet_toself, + packet_beacon); + rtl_process_phyinfo(hw, tmp_buf, pstats); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h new file mode 100644 index 000000000000..553a4bfac668 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.h @@ -0,0 +1,161 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_MAC_H__ +#define __RTL92C_MAC_H__ + +#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 +#define DRIVER_EARLY_INT_TIME 0x05 +#define BCN_DMA_ATIME_INT_TIME 0x02 + +void rtl92c_read_chip_version(struct ieee80211_hw *hw); +bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data); +bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary); +void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all); +void rtl92c_enable_interrupt(struct ieee80211_hw *hw); +void rtl92c_disable_interrupt(struct ieee80211_hw *hw); +void rtl92c_set_qos(struct ieee80211_hw *hw, int aci); + + +/*--------------------------------------------------------------- + * Hardware init functions + *---------------------------------------------------------------*/ +void rtl92c_init_interrupt(struct ieee80211_hw *hw); +void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size); + +int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); +void rtl92c_init_network_type(struct ieee80211_hw *hw); +void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw); +void rtl92c_init_rate_fallback(struct ieee80211_hw *hw); + +void rtl92c_init_edca_param(struct ieee80211_hw *hw, + u16 queue, + u16 txop, + u8 ecwmax, + u8 ecwmin, + u8 aifs); + +void rtl92c_init_edca(struct ieee80211_hw *hw); +void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw); +void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw); +void rtl92c_init_rdg_setting(struct ieee80211_hw *hw); +void rtl92c_init_retry_function(struct ieee80211_hw *hw); + +void rtl92c_disable_fast_edca(struct ieee80211_hw *hw); +void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T); + +u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw); + +struct rx_fwinfo_92c { + u8 gain_trsw[4]; + u8 pwdb_all; + u8 cfosho[4]; + u8 cfotail[4]; + char rxevm[2]; + char rxsnr[4]; + u8 pdsnr[2]; + u8 csi_current[2]; + u8 csi_target[2]; + u8 sigevm; + u8 max_ex_pwr; + u8 ex_intf_flag:1; + u8 sgi_en:1; + u8 rxsc:2; + u8 reserve:4; +} __packed; + +struct rx_desc_92c { + u32 length:14; + u32 crc32:1; + u32 icverror:1; + u32 drv_infosize:4; + u32 security:3; + u32 qos:1; + u32 shift:2; + u32 phystatus:1; + u32 swdec:1; + u32 lastseg:1; + u32 firstseg:1; + u32 eor:1; + u32 own:1; + u32 macid:5; /* word 1 */ + u32 tid:4; + u32 hwrsvd:5; + u32 paggr:1; + u32 faggr:1; + u32 a1_fit:4; + u32 a2_fit:4; + u32 pam:1; + u32 pwr:1; + u32 moredata:1; + u32 morefrag:1; + u32 type:2; + u32 mc:1; + u32 bc:1; + u32 seq:12; /* word 2 */ + u32 frag:4; + u32 nextpktlen:14; + u32 nextind:1; + u32 rsvd:1; + u32 rxmcs:6; /* word 3 */ + u32 rxht:1; + u32 amsdu:1; + u32 splcp:1; + u32 bandwidth:1; + u32 htc:1; + u32 tcpchk_rpt:1; + u32 ipcchk_rpt:1; + u32 tcpchk_valid:1; + u32 hwpcerr:1; + u32 hwpcind:1; + u32 iv0:16; + u32 iv1; /* word 4 */ + u32 tsfl; /* word 5 */ + u32 bufferaddress; /* word 6 */ + u32 bufferaddress64; /* word 7 */ +} __packed; + +enum rtl_desc_qsel rtl92c_map_hwqueue_to_fwqueue(u16 fc, + unsigned int + skb_queue); +void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct rtl_stats *pstats, + struct rx_desc_92c *pdesc, + struct rx_fwinfo_92c *p_drvinfo); + +/*--------------------------------------------------------------- + * Card disable functions + *---------------------------------------------------------------*/ + + + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c new file mode 100644 index 000000000000..c972fa50926d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c @@ -0,0 +1,539 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../ps.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "../rtl8192c/phy_common.h" +#include "rf.h" +#include "dm.h" +#include "../rtl8192c/dm_common.h" +#include "../rtl8192c/fw_common.h" +#include "table.h" + +u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, readback_value, bitshift; + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", + regaddr, rfpath, bitmask); + if (rtlphy->rf_mode != RF_OP_BY_FW) { + original_value = _rtl92c_phy_rf_serial_read(hw, + rfpath, regaddr); + } else { + original_value = _rtl92c_phy_fw_rf_serial_read(hw, + rfpath, regaddr); + } + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + readback_value = (original_value & bitmask) >> bitshift; + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", + regaddr, rfpath, bitmask, original_value); + return readback_value; +} + +void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 original_value, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); + if (rtlphy->rf_mode != RF_OP_BY_FW) { + if (bitmask != RFREG_OFFSET_MASK) { + original_value = _rtl92c_phy_rf_serial_read(hw, + rfpath, + regaddr); + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + data = + ((original_value & (~bitmask)) | + (data << bitshift)); + } + _rtl92c_phy_rf_serial_write(hw, rfpath, regaddr, data); + } else { + if (bitmask != RFREG_OFFSET_MASK) { + original_value = _rtl92c_phy_fw_rf_serial_read(hw, + rfpath, + regaddr); + bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); + data = + ((original_value & (~bitmask)) | + (data << bitshift)); + } + _rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data); + } + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); +} + +bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw) +{ + bool rtstatus; + + rtstatus = _rtl92cu_phy_config_mac_with_headerfile(hw); + return rtstatus; +} + +bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw) +{ + bool rtstatus = true; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 regval; + u32 regval32; + u8 b_reg_hwparafile = 1; + + _rtl92c_phy_init_bb_rf_register_definition(hw); + regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, regval | BIT(13) | + BIT(0) | BIT(1)); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); + rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | + FEN_BB_GLB_RSTn | FEN_BBRSTB); + regval32 = rtl_read_dword(rtlpriv, 0x87c); + rtl_write_dword(rtlpriv, 0x87c, regval32 & (~BIT(31))); + rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); + if (b_reg_hwparafile == 1) + rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); + return rtstatus; +} + +bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 i; + u32 arraylength; + u32 *ptrarray; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n"); + arraylength = rtlphy->hwparam_tables[MAC_REG].length ; + ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CUMAC_2T_ARRAY\n"); + for (i = 0; i < arraylength; i = i + 2) + rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); + return true; +} + +bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype) +{ + int i; + u32 *phy_regarray_table; + u32 *agctab_array_table; + u16 phy_reg_arraylen, agctab_arraylen; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + if (IS_92C_SERIAL(rtlhal->version)) { + agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_2T].length; + agctab_array_table = rtlphy->hwparam_tables[AGCTAB_2T].pdata; + phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_2T].length; + phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_2T].pdata; + } else { + agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_1T].length; + agctab_array_table = rtlphy->hwparam_tables[AGCTAB_1T].pdata; + phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_1T].length; + phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_1T].pdata; + } + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_reg_arraylen; i = i + 2) { + rtl_addr_delay(phy_regarray_table[i]); + rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD, + phy_regarray_table[i + 1]); + udelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", + phy_regarray_table[i], + phy_regarray_table[i + 1]); + } + } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { + for (i = 0; i < agctab_arraylen; i = i + 2) { + rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD, + agctab_array_table[i + 1]); + udelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", + agctab_array_table[i], + agctab_array_table[i + 1]); + } + } + return true; +} + +bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + int i; + u32 *phy_regarray_table_pg; + u16 phy_regarray_pg_len; + + rtlphy->pwrgroup_cnt = 0; + phy_regarray_pg_len = rtlphy->hwparam_tables[PHY_REG_PG].length; + phy_regarray_table_pg = rtlphy->hwparam_tables[PHY_REG_PG].pdata; + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_regarray_pg_len; i = i + 3) { + rtl_addr_delay(phy_regarray_table_pg[i]); + _rtl92c_store_pwrIndex_diffrate_offset(hw, + phy_regarray_table_pg[i], + phy_regarray_table_pg[i + 1], + phy_regarray_table_pg[i + 2]); + } + } else { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "configtype != BaseBand_Config_PHY_REG\n"); + } + return true; +} + +bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath) +{ + int i; + u32 *radioa_array_table; + u32 *radiob_array_table; + u16 radioa_arraylen, radiob_arraylen; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + if (IS_92C_SERIAL(rtlhal->version)) { + radioa_arraylen = rtlphy->hwparam_tables[RADIOA_2T].length; + radioa_array_table = rtlphy->hwparam_tables[RADIOA_2T].pdata; + radiob_arraylen = rtlphy->hwparam_tables[RADIOB_2T].length; + radiob_array_table = rtlphy->hwparam_tables[RADIOB_2T].pdata; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio_A:RTL8192CURADIOA_2TARRAY\n"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio_B:RTL8192CU_RADIOB_2TARRAY\n"); + } else { + radioa_arraylen = rtlphy->hwparam_tables[RADIOA_1T].length; + radioa_array_table = rtlphy->hwparam_tables[RADIOA_1T].pdata; + radiob_arraylen = rtlphy->hwparam_tables[RADIOB_1T].length; + radiob_array_table = rtlphy->hwparam_tables[RADIOB_1T].pdata; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio_A:RTL8192CU_RADIOA_1TARRAY\n"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio_B:RTL8192CU_RADIOB_1TARRAY\n"); + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath); + switch (rfpath) { + case RF90_PATH_A: + for (i = 0; i < radioa_arraylen; i = i + 2) { + rtl_rfreg_delay(hw, rfpath, radioa_array_table[i], + RFREG_OFFSET_MASK, + radioa_array_table[i + 1]); + } + break; + case RF90_PATH_B: + for (i = 0; i < radiob_arraylen; i = i + 2) { + rtl_rfreg_delay(hw, rfpath, radiob_array_table[i], + RFREG_OFFSET_MASK, + radiob_array_table[i + 1]); + } + break; + case RF90_PATH_C: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + case RF90_PATH_D: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + default: + break; + } + return true; +} + +void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 reg_bw_opmode; + u8 reg_prsr_rsc; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz"); + if (is_hal_stop(rtlhal)) { + rtlphy->set_bwmode_inprogress = false; + return; + } + reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); + reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + break; + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + reg_prsr_rsc = + (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); + rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), + (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + rtl92cu_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); +} + +void rtl92cu_bb_block_on(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + mutex_lock(&rtlpriv->io.bb_mutex); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); + mutex_unlock(&rtlpriv->io.bb_mutex); +} + +void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) +{ + u8 tmpreg; + u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + tmpreg = rtl_read_byte(rtlpriv, 0xd03); + + if ((tmpreg & 0x70) != 0) + rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); + else + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + + if ((tmpreg & 0x70) != 0) { + rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); + if (is2t) + rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, + MASK12BITS); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, + (rf_a_mode & 0x8FFFF) | 0x10000); + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + (rf_b_mode & 0x8FFFF) | 0x10000); + } + lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); + rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); + mdelay(100); + if ((tmpreg & 0x70) != 0) { + rtl_write_byte(rtlpriv, 0xd03, tmpreg); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + rf_b_mode); + } else { + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + } +} + +static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = true; + u8 i, queue_id; + struct rtl8192_tx_ring *ring = NULL; + + switch (rfpwr_state) { + case ERFON: + if ((ppsc->rfpwr_state == ERFOFF) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + bool rtstatus; + u32 InitializeCount = 0; + + do { + InitializeCount++; + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic enable\n"); + rtstatus = rtl_ps_enable_nic(hw); + } while (!rtstatus && (InitializeCount < 10)); + RT_CLEAR_PS_LEVEL(ppsc, + RT_RF_OFF_LEVL_HALT_NIC); + } else { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFON sleeped:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc->last_sleep_jiffies)); + ppsc->last_awake_jiffies = jiffies; + rtl92ce_phy_set_rf_on(hw); + } + if (mac->link_state == MAC80211_LINKED) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } + break; + case ERFOFF: + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (skb_queue_len(&ring->queue) == 0 || + queue_id == BEACON_QUEUE) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", + i + 1, + queue_id, + skb_queue_len(&ring->queue)); + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "ERFOFF: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic disable\n"); + rtl_ps_disable_nic(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } else { + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_POWER_OFF); + } + } + break; + case ERFSLEEP: + if (ppsc->rfpwr_state == ERFOFF) + return false; + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (skb_queue_len(&ring->queue) == 0) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", + i + 1, queue_id, + skb_queue_len(&ring->queue)); + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFSLEEP awaked:%d ms\n", + jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies)); + ppsc->last_sleep_jiffies = jiffies; + _rtl92c_phy_set_rf_sleep(hw); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + bresult = false; + break; + } + if (bresult) + ppsc->rfpwr_state = rfpwr_state; + return bresult; +} + +bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = false; + + if (rfpwr_state == ppsc->rfpwr_state) + return bresult; + bresult = _rtl92cu_phy_set_rf_power_state(hw, rfpwr_state); + return bresult; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h new file mode 100644 index 000000000000..42b068660483 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.h @@ -0,0 +1,50 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../rtl8192ce/phy.h" + +void rtl92cu_bb_block_on(struct ieee80211_hw *hw); +bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath); +void rtl92c_phy_set_io(struct ieee80211_hw *hw); +bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); +bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw); +u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, u32 bitmask); +void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data); +bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw); +bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype); +void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); +bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw); +bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h new file mode 100644 index 000000000000..8b81465c629b --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/reg.h @@ -0,0 +1,30 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../rtl8192ce/reg.h" diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c new file mode 100644 index 000000000000..5624ade92cc0 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.c @@ -0,0 +1,475 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" + +static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw); + +void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff) | 0x0400); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + case HT_CHANNEL_WIDTH_20_40: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff)); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", bandwidth); + break; + } +} + +void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 tx_agc[2] = { 0, 0 }, tmpval = 0; + bool turbo_scanoff = false; + u8 idx1, idx2; + u8 *ptr; + + if ((rtlefuse->eeprom_regulatory != 0) || (rtlefuse->external_pa)) + turbo_scanoff = true; + if (mac->act_scanning) { + tx_agc[RF90_PATH_A] = 0x3f3f3f3f; + tx_agc[RF90_PATH_B] = 0x3f3f3f3f; + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + if (tx_agc[idx1] > 0x20 && rtlefuse->external_pa) + tx_agc[idx1] = 0x20; + } + } else { + if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL1) { + tx_agc[RF90_PATH_A] = 0x10101010; + tx_agc[RF90_PATH_B] = 0x10101010; + } else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL2) { + tx_agc[RF90_PATH_A] = 0x00000000; + tx_agc[RF90_PATH_B] = 0x00000000; + } else { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + if (rtlefuse->eeprom_regulatory == 0) { + tmpval = (rtlphy->mcs_offset[0][6]) + + (rtlphy->mcs_offset[0][7] << 8); + tx_agc[RF90_PATH_A] += tmpval; + tmpval = (rtlphy->mcs_offset[0][14]) + + (rtlphy->mcs_offset[0][15] << 24); + tx_agc[RF90_PATH_B] += tmpval; + } + } + } + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + ptr = (u8 *) (&(tx_agc[idx1])); + for (idx2 = 0; idx2 < 4; idx2++) { + if (*ptr > RF6052_MAX_TX_PWR) + *ptr = RF6052_MAX_TX_PWR; + ptr++; + } + } + tmpval = tx_agc[RF90_PATH_A] & 0xff; + rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", + tmpval, RTXAGC_A_CCK1_MCS32); + + tmpval = tx_agc[RF90_PATH_A] >> 8; + if (mac->mode == WIRELESS_MODE_B) + tmpval = tmpval & 0xff00ffff; + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", + tmpval, RTXAGC_B_CCK11_A_CCK2_11); + tmpval = tx_agc[RF90_PATH_B] >> 24; + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", + tmpval, RTXAGC_B_CCK11_A_CCK2_11); + tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; + rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", + tmpval, RTXAGC_B_CCK1_55_MCS32); +} + +static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel, + u32 *ofdmbase, u32 *mcsbase) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 powerBase0, powerBase1; + u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0; + u8 i, powerlevel[2]; + + for (i = 0; i < 2; i++) { + powerlevel[i] = ppowerlevel[i]; + legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; + powerBase0 = powerlevel[i] + legacy_pwrdiff; + powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | + (powerBase0 << 8) | powerBase0; + *(ofdmbase + i) = powerBase0; + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [OFDM power base index rf(%c) = 0x%x]\n", + i == 0 ? 'A' : 'B', *(ofdmbase + i)); + } + for (i = 0; i < 2; i++) { + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { + ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1]; + powerlevel[i] += ht20_pwrdiff; + } + powerBase1 = powerlevel[i]; + powerBase1 = (powerBase1 << 24) | + (powerBase1 << 16) | (powerBase1 << 8) | powerBase1; + *(mcsbase + i) = powerBase1; + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [MCS power base index rf(%c) = 0x%x]\n", + i == 0 ? 'A' : 'B', *(mcsbase + i)); + } +} + +static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, + u8 channel, u8 index, + u32 *powerBase0, + u32 *powerBase1, + u32 *p_outwriteval) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 i, chnlgroup = 0, pwr_diff_limit[4]; + u32 writeVal, customer_limit, rf; + + for (rf = 0; rf < 2; rf++) { + switch (rtlefuse->eeprom_regulatory) { + case 0: + chnlgroup = 0; + writeVal = rtlphy->mcs_offset + [chnlgroup][index + (rf ? 8 : 0)] + + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance,writeVal(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeVal); + break; + case 1: + if (rtlphy->pwrgroup_cnt == 1) + chnlgroup = 0; + if (rtlphy->pwrgroup_cnt >= 3) { + if (channel <= 3) + chnlgroup = 0; + else if (channel >= 4 && channel <= 9) + chnlgroup = 1; + else if (channel > 9) + chnlgroup = 2; + if (rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20) + chnlgroup++; + else + chnlgroup += 4; + } + writeVal = rtlphy->mcs_offset[chnlgroup][index + + (rf ? 8 : 0)] + + ((index < 2) ? powerBase0[rf] : + powerBase1[rf]); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeVal); + break; + case 2: + writeVal = ((index < 2) ? powerBase0[rf] : + powerBase1[rf]); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Better regulatory,writeVal(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeVal); + break; + case 3: + chnlgroup = 0; + if (rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20_40) { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 40MHzrf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', + rtlefuse->pwrgroup_ht40[rf] + [channel - 1]); + } else { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 20MHz rf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', + rtlefuse->pwrgroup_ht20[rf] + [channel - 1]); + } + for (i = 0; i < 4; i++) { + pwr_diff_limit[i] = (u8) ((rtlphy->mcs_offset + [chnlgroup][index + (rf ? 8 : 0)] + & (0x7f << (i * 8))) >> (i * 8)); + if (rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20_40) { + if (pwr_diff_limit[i] > + rtlefuse->pwrgroup_ht40[rf] + [channel - 1]) + pwr_diff_limit[i] = rtlefuse-> + pwrgroup_ht40[rf] + [channel - 1]; + } else { + if (pwr_diff_limit[i] > + rtlefuse->pwrgroup_ht20[rf] + [channel - 1]) + pwr_diff_limit[i] = + rtlefuse->pwrgroup_ht20[rf] + [channel - 1]; + } + } + customer_limit = (pwr_diff_limit[3] << 24) | + (pwr_diff_limit[2] << 16) | + (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer's limit rf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', customer_limit); + writeVal = customer_limit + ((index < 2) ? + powerBase0[rf] : powerBase1[rf]); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer, writeVal rf(%c)= 0x%x\n", + rf == 0 ? 'A' : 'B', writeVal); + break; + default: + chnlgroup = 0; + writeVal = rtlphy->mcs_offset[chnlgroup] + [index + (rf ? 8 : 0)] + ((index < 2) ? + powerBase0[rf] : powerBase1[rf]); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeValrf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeVal); + break; + } + if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL1) + writeVal = 0x14141414; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_LEVEL2) + writeVal = 0x00000000; + if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) + writeVal = writeVal - 0x06060606; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_BT2) + writeVal = writeVal; + *(p_outwriteval + rf) = writeVal; + } +} + +static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, + u8 index, u32 *pValue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u16 regoffset_a[6] = { + RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, + RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, + RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 + }; + u16 regoffset_b[6] = { + RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, + RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, + RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 + }; + u8 i, rf, pwr_val[4]; + u32 writeVal; + u16 regoffset; + + for (rf = 0; rf < 2; rf++) { + writeVal = pValue[rf]; + for (i = 0; i < 4; i++) { + pwr_val[i] = (u8)((writeVal & (0x7f << (i * 8))) >> + (i * 8)); + if (pwr_val[i] > RF6052_MAX_TX_PWR) + pwr_val[i] = RF6052_MAX_TX_PWR; + } + writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) | + (pwr_val[1] << 8) | pwr_val[0]; + if (rf == 0) + regoffset = regoffset_a[index]; + else + regoffset = regoffset_b[index]; + rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Set 0x%x = %08x\n", regoffset, writeVal); + if (((get_rf_type(rtlphy) == RF_2T2R) && + (regoffset == RTXAGC_A_MCS15_MCS12 || + regoffset == RTXAGC_B_MCS15_MCS12)) || + ((get_rf_type(rtlphy) != RF_2T2R) && + (regoffset == RTXAGC_A_MCS07_MCS04 || + regoffset == RTXAGC_B_MCS07_MCS04))) { + writeVal = pwr_val[3]; + if (regoffset == RTXAGC_A_MCS15_MCS12 || + regoffset == RTXAGC_A_MCS07_MCS04) + regoffset = 0xc90; + if (regoffset == RTXAGC_B_MCS15_MCS12 || + regoffset == RTXAGC_B_MCS07_MCS04) + regoffset = 0xc98; + for (i = 0; i < 3; i++) { + if (i != 2) + writeVal = (writeVal > 8) ? + (writeVal - 8) : 0; + else + writeVal = (writeVal > 6) ? + (writeVal - 6) : 0; + rtl_write_byte(rtlpriv, (u32)(regoffset + i), + (u8)writeVal); + } + } + } +} + +void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel) +{ + u32 writeVal[2], powerBase0[2], powerBase1[2]; + u8 index = 0; + + rtl92c_phy_get_power_base(hw, ppowerlevel, + channel, &powerBase0[0], &powerBase1[0]); + for (index = 0; index < 6; index++) { + _rtl92c_get_txpower_writeval_by_regulatory(hw, + channel, index, + &powerBase0[0], + &powerBase1[0], + &writeVal[0]); + _rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]); + } +} + +bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + bool rtstatus = true; + u8 b_reg_hwparafile = 1; + + if (rtlphy->rf_type == RF_1T1R) + rtlphy->num_total_rfpath = 1; + else + rtlphy->num_total_rfpath = 2; + if (b_reg_hwparafile == 1) + rtstatus = _rtl92c_phy_rf6052_config_parafile(hw); + return rtstatus; +} + +static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 u4_regvalue = 0; + u8 rfpath; + bool rtstatus = true; + struct bb_reg_def *pphyreg; + + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + pphyreg = &rtlphy->phyreg_def[rfpath]; + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV); + break; + case RF90_PATH_B: + case RF90_PATH_D: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16); + break; + } + rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); + udelay(1); + rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); + udelay(1); + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, + B3WIREADDREAALENGTH, 0x0); + udelay(1); + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); + udelay(1); + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_B: + rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw, + (enum radio_path) rfpath); + break; + case RF90_PATH_C: + break; + case RF90_PATH_D: + break; + } + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV, u4_regvalue); + break; + case RF90_PATH_B: + case RF90_PATH_D: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16, u4_regvalue); + break; + } + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio[%d] Fail!!", rfpath); + goto phy_rf_cfg_fail; + } + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n"); +phy_rf_cfg_fail: + return rtstatus; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h new file mode 100644 index 000000000000..6f987de5b441 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/rf.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CU_RF_H__ +#define __RTL92CU_RF_H__ + +#define RF6052_MAX_TX_PWR 0x3F +#define RF6052_MAX_PATH 2 + +void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth); +void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); +bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw); +bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c new file mode 100644 index 000000000000..fd4a5353d216 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c @@ -0,0 +1,412 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../core.h" +#include "../usb.h" +#include "../efuse.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "mac.h" +#include "dm.h" +#include "rf.h" +#include "sw.h" +#include "trx.h" +#include "led.h" +#include "hw.h" +#include "../rtl8192c/fw_common.h" +#include + +MODULE_AUTHOR("Georgia "); +MODULE_AUTHOR("Ziv Huang "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_A.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_B.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_TMSC.bin"); + +static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int err; + + rtlpriv->dm.dm_initialgain_enable = true; + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.disable_framebursting = false; + rtlpriv->dm.thermalvalue = 0; + rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(0x4000); + if (!rtlpriv->rtlhal.pfirmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't alloc buffer for fw\n"); + return 1; + } + if (IS_VENDOR_UMC_A_CUT(rtlpriv->rtlhal.version) && + !IS_92C_SERIAL(rtlpriv->rtlhal.version)) { + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_A.bin"; + } else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlpriv->rtlhal.version)) { + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_B.bin"; + } else { + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_TMSC.bin"; + } + /* provide name of alternative file */ + rtlpriv->cfg->alt_fw_name = "rtlwifi/rtl8192cufw.bin"; + pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name); + rtlpriv->max_fw_size = 0x4000; + err = request_firmware_nowait(THIS_MODULE, 1, + rtlpriv->cfg->fw_name, rtlpriv->io.dev, + GFP_KERNEL, hw, rtl_fw_cb); + return err; +} + +static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.pfirmware) { + vfree(rtlpriv->rtlhal.pfirmware); + rtlpriv->rtlhal.pfirmware = NULL; + } +} + +/* get bt coexist status */ +static bool rtl92cu_get_btc_status(void) +{ + return false; +} + +static struct rtl_hal_ops rtl8192cu_hal_ops = { + .init_sw_vars = rtl92cu_init_sw_vars, + .deinit_sw_vars = rtl92cu_deinit_sw_vars, + .read_chip_version = rtl92c_read_chip_version, + .read_eeprom_info = rtl92cu_read_eeprom_info, + .enable_interrupt = rtl92c_enable_interrupt, + .disable_interrupt = rtl92c_disable_interrupt, + .hw_init = rtl92cu_hw_init, + .hw_disable = rtl92cu_card_disable, + .set_network_type = rtl92cu_set_network_type, + .set_chk_bssid = rtl92cu_set_check_bssid, + .set_qos = rtl92c_set_qos, + .set_bcn_reg = rtl92cu_set_beacon_related_registers, + .set_bcn_intv = rtl92cu_set_beacon_interval, + .update_interrupt_mask = rtl92cu_update_interrupt_mask, + .get_hw_reg = rtl92cu_get_hw_reg, + .set_hw_reg = rtl92cu_set_hw_reg, + .update_rate_tbl = rtl92cu_update_hal_rate_tbl, + .fill_tx_desc = rtl92cu_tx_fill_desc, + .fill_fake_txdesc = rtl92cu_fill_fake_txdesc, + .fill_tx_cmddesc = rtl92cu_tx_fill_cmddesc, + .query_rx_desc = rtl92cu_rx_query_desc, + .set_channel_access = rtl92cu_update_channel_access_setting, + .radio_onoff_checking = rtl92cu_gpio_radio_on_off_checking, + .set_bw_mode = rtl92c_phy_set_bw_mode, + .switch_channel = rtl92c_phy_sw_chnl, + .dm_watchdog = rtl92c_dm_watchdog, + .scan_operation_backup = rtl_phy_scan_operation_backup, + .set_rf_power_state = rtl92cu_phy_set_rf_power_state, + .led_control = rtl92cu_led_control, + .enable_hw_sec = rtl92cu_enable_hw_security_config, + .set_key = rtl92c_set_key, + .init_sw_leds = rtl92cu_init_sw_leds, + .deinit_sw_leds = rtl92cu_deinit_sw_leds, + .get_bbreg = rtl92c_phy_query_bb_reg, + .set_bbreg = rtl92c_phy_set_bb_reg, + .get_rfreg = rtl92cu_phy_query_rf_reg, + .set_rfreg = rtl92cu_phy_set_rf_reg, + .phy_rf6052_config = rtl92cu_phy_rf6052_config, + .phy_rf6052_set_cck_txpower = rtl92cu_phy_rf6052_set_cck_txpower, + .phy_rf6052_set_ofdm_txpower = rtl92cu_phy_rf6052_set_ofdm_txpower, + .config_bb_with_headerfile = _rtl92cu_phy_config_bb_with_headerfile, + .config_bb_with_pgheaderfile = _rtl92cu_phy_config_bb_with_pgheaderfile, + .phy_lc_calibrate = _rtl92cu_phy_lc_calibrate, + .phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback, + .dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower, + .fill_h2c_cmd = rtl92c_fill_h2c_cmd, + .get_btc_status = rtl92cu_get_btc_status, +}; + +static struct rtl_mod_params rtl92cu_mod_params = { + .sw_crypto = 0, + .debug = DBG_EMERG, +}; + +module_param_named(swenc, rtl92cu_mod_params.sw_crypto, bool, 0444); +module_param_named(debug, rtl92cu_mod_params.debug, int, 0444); +MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); +MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); + +static struct rtl_hal_usbint_cfg rtl92cu_interface_cfg = { + /* rx */ + .in_ep_num = RTL92C_USB_BULK_IN_NUM, + .rx_urb_num = RTL92C_NUM_RX_URBS, + .rx_max_size = RTL92C_SIZE_MAX_RX_BUFFER, + .usb_rx_hdl = rtl8192cu_rx_hdl, + .usb_rx_segregate_hdl = NULL, /* rtl8192c_rx_segregate_hdl; */ + /* tx */ + .usb_tx_cleanup = rtl8192c_tx_cleanup, + .usb_tx_post_hdl = rtl8192c_tx_post_hdl, + .usb_tx_aggregate_hdl = rtl8192c_tx_aggregate_hdl, + /* endpoint mapping */ + .usb_endpoint_mapping = rtl8192cu_endpoint_mapping, + .usb_mq_to_hwq = rtl8192cu_mq_to_hwq, +}; + +static struct rtl_hal_cfg rtl92cu_hal_cfg = { + .name = "rtl92c_usb", + .fw_name = "rtlwifi/rtl8192cufw.bin", + .ops = &rtl8192cu_hal_ops, + .mod_params = &rtl92cu_mod_params, + .usb_interface_cfg = &rtl92cu_interface_cfg, + + .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, + .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, + .maps[SYS_CLK] = REG_SYS_CLKR, + .maps[MAC_RCR_AM] = AM, + .maps[MAC_RCR_AB] = AB, + .maps[MAC_RCR_ACRC32] = ACRC32, + .maps[MAC_RCR_ACF] = ACF, + .maps[MAC_RCR_AAP] = AAP, + + .maps[EFUSE_TEST] = REG_EFUSE_TEST, + .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_CLK] = 0, + .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_PWC_EV12V] = PWC_EV12V, + .maps[EFUSE_FEN_ELDR] = FEN_ELDR, + .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, + .maps[EFUSE_ANA8M] = EFUSE_ANA8M, + .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, + .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, + .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, + + .maps[RWCAM] = REG_CAMCMD, + .maps[WCAMI] = REG_CAMWRITE, + .maps[RCAMO] = REG_CAMREAD, + .maps[CAMDBG] = REG_CAMDBG, + .maps[SECR] = REG_SECCFG, + .maps[SEC_CAM_NONE] = CAM_NONE, + .maps[SEC_CAM_WEP40] = CAM_WEP40, + .maps[SEC_CAM_TKIP] = CAM_TKIP, + .maps[SEC_CAM_AES] = CAM_AES, + .maps[SEC_CAM_WEP104] = CAM_WEP104, + + .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, + .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, + .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, + .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, + .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, + .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, + .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, + .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, + .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, + .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, + .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, + .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, + .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, + .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, + .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, + .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, + + .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, + .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, + .maps[RTL_IMR_BCNINT] = IMR_BCNINT, + .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, + .maps[RTL_IMR_RDU] = IMR_RDU, + .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, + .maps[RTL_IMR_BDOK] = IMR_BDOK, + .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, + .maps[RTL_IMR_TBDER] = IMR_TBDER, + .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, + .maps[RTL_IMR_TBDOK] = IMR_TBDOK, + .maps[RTL_IMR_BKDOK] = IMR_BKDOK, + .maps[RTL_IMR_BEDOK] = IMR_BEDOK, + .maps[RTL_IMR_VIDOK] = IMR_VIDOK, + .maps[RTL_IMR_VODOK] = IMR_VODOK, + .maps[RTL_IMR_ROK] = IMR_ROK, + .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), + + .maps[RTL_RC_CCK_RATE1M] = DESC_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC_RATE54M, + .maps[RTL_RC_HT_RATEMCS7] = DESC_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC_RATEMCS15, +}; + +#define USB_VENDER_ID_REALTEK 0x0bda + +/* 2010-10-19 DID_USB_V3.4 */ +static struct usb_device_id rtl8192c_usb_ids[] = { + + /*=== Realtek demoboard ===*/ + /* Default ID */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8191, rtl92cu_hal_cfg)}, + + /****** 8188CU ********/ + /* RTL8188CTV */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x018a, rtl92cu_hal_cfg)}, + /* 8188CE-VAU USB minCard */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8170, rtl92cu_hal_cfg)}, + /* 8188cu 1*1 dongle */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8176, rtl92cu_hal_cfg)}, + /* 8188cu 1*1 dongle, (b/g mode only) */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8177, rtl92cu_hal_cfg)}, + /* 8188cu Slim Solo */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817a, rtl92cu_hal_cfg)}, + /* 8188cu Slim Combo */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817b, rtl92cu_hal_cfg)}, + /* 8188RU High-power USB Dongle */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817d, rtl92cu_hal_cfg)}, + /* 8188CE-VAU USB minCard (b/g mode only) */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817e, rtl92cu_hal_cfg)}, + /* 8188RU in Alfa AWUS036NHR */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)}, + /* RTL8188CUS-VL */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x819a, rtl92cu_hal_cfg)}, + /* 8188 Combo for BC4 */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)}, + + /****** 8192CU ********/ + /* 8192cu 2*2 */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8178, rtl92cu_hal_cfg)}, + /* 8192CE-VAU USB minCard */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817c, rtl92cu_hal_cfg)}, + + /*=== Customer ID ===*/ + /****** 8188CU ********/ + {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/ + {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/ + {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ + {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ + {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ + {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/ + {RTL_USB_DEVICE(0x0846, 0x9043, rtl92cu_hal_cfg)}, /*NG WNA1000Mv2*/ + {RTL_USB_DEVICE(0x0b05, 0x17ba, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/ + {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/ + {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ + {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ + {RTL_USB_DEVICE(0x0df6, 0x0070, rtl92cu_hal_cfg)}, /*Sitecom - 150N */ + {RTL_USB_DEVICE(0x0df6, 0x0077, rtl92cu_hal_cfg)}, /*Sitecom-WLA2100V2*/ + {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/ + {RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/ + /* HP - Lite-On ,8188CUS Slim Combo */ + {RTL_USB_DEVICE(0x103c, 0x1629, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(0x13d3, 0x3357, rtl92cu_hal_cfg)}, /* AzureWave */ + {RTL_USB_DEVICE(0x2001, 0x3308, rtl92cu_hal_cfg)}, /*D-Link - Alpha*/ + {RTL_USB_DEVICE(0x2019, 0x4902, rtl92cu_hal_cfg)}, /*Planex - Etop*/ + {RTL_USB_DEVICE(0x2019, 0xab2a, rtl92cu_hal_cfg)}, /*Planex - Abocom*/ + /*SW-WF02-AD15 -Abocom*/ + {RTL_USB_DEVICE(0x2019, 0xab2e, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(0x2019, 0xed17, rtl92cu_hal_cfg)}, /*PCI - Edimax*/ + {RTL_USB_DEVICE(0x20f4, 0x648b, rtl92cu_hal_cfg)}, /*TRENDnet - Cameo*/ + {RTL_USB_DEVICE(0x7392, 0x7811, rtl92cu_hal_cfg)}, /*Edimax - Edimax*/ + {RTL_USB_DEVICE(0x13d3, 0x3358, rtl92cu_hal_cfg)}, /*Azwave 8188CE-VAU*/ + /* Russian customer -Azwave (8188CE-VAU b/g mode only) */ + {RTL_USB_DEVICE(0x13d3, 0x3359, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(0x4855, 0x0090, rtl92cu_hal_cfg)}, /* Feixun */ + {RTL_USB_DEVICE(0x4855, 0x0091, rtl92cu_hal_cfg)}, /* NetweeN-Feixun */ + {RTL_USB_DEVICE(0x9846, 0x9041, rtl92cu_hal_cfg)}, /* Netgear Cameo */ + + /****** 8188 RU ********/ + /* Netcore */ + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x317f, rtl92cu_hal_cfg)}, + + /****** 8188CUS Slim Solo********/ + {RTL_USB_DEVICE(0x04f2, 0xaff7, rtl92cu_hal_cfg)}, /*Xavi*/ + {RTL_USB_DEVICE(0x04f2, 0xaff9, rtl92cu_hal_cfg)}, /*Xavi*/ + {RTL_USB_DEVICE(0x04f2, 0xaffa, rtl92cu_hal_cfg)}, /*Xavi*/ + + /****** 8188CUS Slim Combo ********/ + {RTL_USB_DEVICE(0x04f2, 0xaff8, rtl92cu_hal_cfg)}, /*Xavi*/ + {RTL_USB_DEVICE(0x04f2, 0xaffb, rtl92cu_hal_cfg)}, /*Xavi*/ + {RTL_USB_DEVICE(0x04f2, 0xaffc, rtl92cu_hal_cfg)}, /*Xavi*/ + {RTL_USB_DEVICE(0x2019, 0x1201, rtl92cu_hal_cfg)}, /*Planex-Vencer*/ + + /****** 8192CU ********/ + {RTL_USB_DEVICE(0x050d, 0x1004, rtl92cu_hal_cfg)}, /*Belcom-SurfN300*/ + {RTL_USB_DEVICE(0x050d, 0x2102, rtl92cu_hal_cfg)}, /*Belcom-Sercomm*/ + {RTL_USB_DEVICE(0x050d, 0x2103, rtl92cu_hal_cfg)}, /*Belcom-Edimax*/ + {RTL_USB_DEVICE(0x0586, 0x341f, rtl92cu_hal_cfg)}, /*Zyxel -Abocom*/ + {RTL_USB_DEVICE(0x07aa, 0x0056, rtl92cu_hal_cfg)}, /*ATKK-Gemtek*/ + {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/ + {RTL_USB_DEVICE(0x0846, 0x9021, rtl92cu_hal_cfg)}, /*Netgear-Sercomm*/ + {RTL_USB_DEVICE(0x0846, 0xf001, rtl92cu_hal_cfg)}, /*On Netwrks N300MA*/ + {RTL_USB_DEVICE(0x0b05, 0x17ab, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/ + {RTL_USB_DEVICE(0x0bda, 0x8186, rtl92cu_hal_cfg)}, /*Realtek 92CE-VAU*/ + {RTL_USB_DEVICE(0x0df6, 0x0061, rtl92cu_hal_cfg)}, /*Sitecom-Edimax*/ + {RTL_USB_DEVICE(0x0e66, 0x0019, rtl92cu_hal_cfg)}, /*Hawking-Edimax*/ + {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/ + {RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ + {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ + {RTL_USB_DEVICE(0x2001, 0x330d, rtl92cu_hal_cfg)}, /*D-Link DWA-131 */ + {RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/ + {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/ + {RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/ + {RTL_USB_DEVICE(0x7392, 0x7822, rtl92cu_hal_cfg)}, /*Edimax -Edimax*/ + {} +}; + +MODULE_DEVICE_TABLE(usb, rtl8192c_usb_ids); + +static int rtl8192cu_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return rtl_usb_probe(intf, id, &rtl92cu_hal_cfg); +} + +static struct usb_driver rtl8192cu_driver = { + .name = "rtl8192cu", + .probe = rtl8192cu_probe, + .disconnect = rtl_usb_disconnect, + .id_table = rtl8192c_usb_ids, + +#ifdef CONFIG_PM + /* .suspend = rtl_usb_suspend, */ + /* .resume = rtl_usb_resume, */ + /* .reset_resume = rtl8192c_resume, */ +#endif /* CONFIG_PM */ + .disable_hub_initiated_lpm = 1, +}; + +module_usb_driver(rtl8192cu_driver); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h new file mode 100644 index 000000000000..a1310abd0d54 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CU_SW_H__ +#define __RTL92CU_SW_H__ + +#define EFUSE_MAX_SECTION 16 + +void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *powerlevel); +void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); +bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype); +void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); +void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data); +bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); +u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, u32 bitmask); +void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c new file mode 100644 index 000000000000..7903c154de00 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.c @@ -0,0 +1,1888 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "table.h" + +u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH] = { + 0x024, 0x0011800f, + 0x028, 0x00ffdb83, + 0x800, 0x80040002, + 0x804, 0x00000003, + 0x808, 0x0000fc00, + 0x80c, 0x0000000a, + 0x810, 0x10000330, + 0x814, 0x020c3d10, + 0x818, 0x02200385, + 0x81c, 0x00000000, + 0x820, 0x01000100, + 0x824, 0x00390004, + 0x828, 0x01000100, + 0x82c, 0x00390004, + 0x830, 0x27272727, + 0x834, 0x27272727, + 0x838, 0x27272727, + 0x83c, 0x27272727, + 0x840, 0x00010000, + 0x844, 0x00010000, + 0x848, 0x27272727, + 0x84c, 0x27272727, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x569a569a, + 0x85c, 0x0c1b25a4, + 0x860, 0x66e60230, + 0x864, 0x061f0130, + 0x868, 0x27272727, + 0x86c, 0x2b2b2b27, + 0x870, 0x07000700, + 0x874, 0x22184000, + 0x878, 0x08080808, + 0x87c, 0x00000000, + 0x880, 0xc0083070, + 0x884, 0x000004d5, + 0x888, 0x00000000, + 0x88c, 0xcc0000c0, + 0x890, 0x00000800, + 0x894, 0xfffffffe, + 0x898, 0x40302010, + 0x89c, 0x00706050, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90c, 0x81121313, + 0xa00, 0x00d047c8, + 0xa04, 0x80ff000c, + 0xa08, 0x8c838300, + 0xa0c, 0x2e68120f, + 0xa10, 0x9500bb78, + 0xa14, 0x11144028, + 0xa18, 0x00881117, + 0xa1c, 0x89140f00, + 0xa20, 0x1a1b0000, + 0xa24, 0x090e1317, + 0xa28, 0x00000204, + 0xa2c, 0x00d30000, + 0xa70, 0x101fbf00, + 0xa74, 0x00000007, + 0xc00, 0x48071d40, + 0xc04, 0x03a05633, + 0xc08, 0x000000e4, + 0xc0c, 0x6c6c6c6c, + 0xc10, 0x08800000, + 0xc14, 0x40000100, + 0xc18, 0x08800000, + 0xc1c, 0x40000100, + 0xc20, 0x00000000, + 0xc24, 0x00000000, + 0xc28, 0x00000000, + 0xc2c, 0x00000000, + 0xc30, 0x69e9ac44, + 0xc34, 0x469652cf, + 0xc38, 0x49795994, + 0xc3c, 0x0a97971c, + 0xc40, 0x1f7c403f, + 0xc44, 0x000100b7, + 0xc48, 0xec020107, + 0xc4c, 0x007f037f, + 0xc50, 0x69543420, + 0xc54, 0x43bc0094, + 0xc58, 0x69543420, + 0xc5c, 0x433c0094, + 0xc60, 0x00000000, + 0xc64, 0x5116848b, + 0xc68, 0x47c00bff, + 0xc6c, 0x00000036, + 0xc70, 0x2c7f000d, + 0xc74, 0x2186115b, + 0xc78, 0x0000001f, + 0xc7c, 0x00b99612, + 0xc80, 0x40000100, + 0xc84, 0x20f60000, + 0xc88, 0x40000100, + 0xc8c, 0xa0e40000, + 0xc90, 0x00121820, + 0xc94, 0x00000000, + 0xc98, 0x00121820, + 0xc9c, 0x00007f7f, + 0xca0, 0x00000000, + 0xca4, 0x00000080, + 0xca8, 0x00000000, + 0xcac, 0x00000000, + 0xcb0, 0x00000000, + 0xcb4, 0x00000000, + 0xcb8, 0x00000000, + 0xcbc, 0x28000000, + 0xcc0, 0x00000000, + 0xcc4, 0x00000000, + 0xcc8, 0x00000000, + 0xccc, 0x00000000, + 0xcd0, 0x00000000, + 0xcd4, 0x00000000, + 0xcd8, 0x64b22427, + 0xcdc, 0x00766932, + 0xce0, 0x00222222, + 0xce4, 0x00000000, + 0xce8, 0x37644302, + 0xcec, 0x2f97d40c, + 0xd00, 0x00080740, + 0xd04, 0x00020403, + 0xd08, 0x0000907f, + 0xd0c, 0x20010201, + 0xd10, 0xa0633333, + 0xd14, 0x3333bc43, + 0xd18, 0x7a8f5b6b, + 0xd2c, 0xcc979975, + 0xd30, 0x00000000, + 0xd34, 0x80608000, + 0xd38, 0x00000000, + 0xd3c, 0x00027293, + 0xd40, 0x00000000, + 0xd44, 0x00000000, + 0xd48, 0x00000000, + 0xd4c, 0x00000000, + 0xd50, 0x6437140a, + 0xd54, 0x00000000, + 0xd58, 0x00000000, + 0xd5c, 0x30032064, + 0xd60, 0x4653de68, + 0xd64, 0x04518a3c, + 0xd68, 0x00002101, + 0xd6c, 0x2a201c16, + 0xd70, 0x1812362e, + 0xd74, 0x322c2220, + 0xd78, 0x000e3c24, + 0xe00, 0x2a2a2a2a, + 0xe04, 0x2a2a2a2a, + 0xe08, 0x03902a2a, + 0xe10, 0x2a2a2a2a, + 0xe14, 0x2a2a2a2a, + 0xe18, 0x2a2a2a2a, + 0xe1c, 0x2a2a2a2a, + 0xe28, 0x00000000, + 0xe30, 0x1000dc1f, + 0xe34, 0x10008c1f, + 0xe38, 0x02140102, + 0xe3c, 0x681604c2, + 0xe40, 0x01007c00, + 0xe44, 0x01004800, + 0xe48, 0xfb000000, + 0xe4c, 0x000028d1, + 0xe50, 0x1000dc1f, + 0xe54, 0x10008c1f, + 0xe58, 0x02140102, + 0xe5c, 0x28160d05, + 0xe60, 0x00000010, + 0xe68, 0x001b25a4, + 0xe6c, 0x63db25a4, + 0xe70, 0x63db25a4, + 0xe74, 0x0c1b25a4, + 0xe78, 0x0c1b25a4, + 0xe7c, 0x0c1b25a4, + 0xe80, 0x0c1b25a4, + 0xe84, 0x63db25a4, + 0xe88, 0x0c1b25a4, + 0xe8c, 0x63db25a4, + 0xed0, 0x63db25a4, + 0xed4, 0x63db25a4, + 0xed8, 0x63db25a4, + 0xedc, 0x001b25a4, + 0xee0, 0x001b25a4, + 0xeec, 0x6fdb25a4, + 0xf14, 0x00000003, + 0xf4c, 0x00000000, + 0xf00, 0x00000300, +}; + +u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = { + 0x024, 0x0011800f, + 0x028, 0x00ffdb83, + 0x800, 0x80040000, + 0x804, 0x00000001, + 0x808, 0x0000fc00, + 0x80c, 0x0000000a, + 0x810, 0x10000330, + 0x814, 0x020c3d10, + 0x818, 0x02200385, + 0x81c, 0x00000000, + 0x820, 0x01000100, + 0x824, 0x00390004, + 0x828, 0x00000000, + 0x82c, 0x00000000, + 0x830, 0x00000000, + 0x834, 0x00000000, + 0x838, 0x00000000, + 0x83c, 0x00000000, + 0x840, 0x00010000, + 0x844, 0x00000000, + 0x848, 0x00000000, + 0x84c, 0x00000000, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x569a569a, + 0x85c, 0x001b25a4, + 0x860, 0x66e60230, + 0x864, 0x061f0130, + 0x868, 0x00000000, + 0x86c, 0x32323200, + 0x870, 0x07000700, + 0x874, 0x22004000, + 0x878, 0x00000808, + 0x87c, 0x00000000, + 0x880, 0xc0083070, + 0x884, 0x000004d5, + 0x888, 0x00000000, + 0x88c, 0xccc000c0, + 0x890, 0x00000800, + 0x894, 0xfffffffe, + 0x898, 0x40302010, + 0x89c, 0x00706050, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90c, 0x81121111, + 0xa00, 0x00d047c8, + 0xa04, 0x80ff000c, + 0xa08, 0x8c838300, + 0xa0c, 0x2e68120f, + 0xa10, 0x9500bb78, + 0xa14, 0x11144028, + 0xa18, 0x00881117, + 0xa1c, 0x89140f00, + 0xa20, 0x1a1b0000, + 0xa24, 0x090e1317, + 0xa28, 0x00000204, + 0xa2c, 0x00d30000, + 0xa70, 0x101fbf00, + 0xa74, 0x00000007, + 0xc00, 0x48071d40, + 0xc04, 0x03a05611, + 0xc08, 0x000000e4, + 0xc0c, 0x6c6c6c6c, + 0xc10, 0x08800000, + 0xc14, 0x40000100, + 0xc18, 0x08800000, + 0xc1c, 0x40000100, + 0xc20, 0x00000000, + 0xc24, 0x00000000, + 0xc28, 0x00000000, + 0xc2c, 0x00000000, + 0xc30, 0x69e9ac44, + 0xc34, 0x469652cf, + 0xc38, 0x49795994, + 0xc3c, 0x0a97971c, + 0xc40, 0x1f7c403f, + 0xc44, 0x000100b7, + 0xc48, 0xec020107, + 0xc4c, 0x007f037f, + 0xc50, 0x69543420, + 0xc54, 0x43bc0094, + 0xc58, 0x69543420, + 0xc5c, 0x433c0094, + 0xc60, 0x00000000, + 0xc64, 0x5116848b, + 0xc68, 0x47c00bff, + 0xc6c, 0x00000036, + 0xc70, 0x2c7f000d, + 0xc74, 0x018610db, + 0xc78, 0x0000001f, + 0xc7c, 0x00b91612, + 0xc80, 0x40000100, + 0xc84, 0x20f60000, + 0xc88, 0x40000100, + 0xc8c, 0x20200000, + 0xc90, 0x00121820, + 0xc94, 0x00000000, + 0xc98, 0x00121820, + 0xc9c, 0x00007f7f, + 0xca0, 0x00000000, + 0xca4, 0x00000080, + 0xca8, 0x00000000, + 0xcac, 0x00000000, + 0xcb0, 0x00000000, + 0xcb4, 0x00000000, + 0xcb8, 0x00000000, + 0xcbc, 0x28000000, + 0xcc0, 0x00000000, + 0xcc4, 0x00000000, + 0xcc8, 0x00000000, + 0xccc, 0x00000000, + 0xcd0, 0x00000000, + 0xcd4, 0x00000000, + 0xcd8, 0x64b22427, + 0xcdc, 0x00766932, + 0xce0, 0x00222222, + 0xce4, 0x00000000, + 0xce8, 0x37644302, + 0xcec, 0x2f97d40c, + 0xd00, 0x00000740, + 0xd04, 0x00020401, + 0xd08, 0x0000907f, + 0xd0c, 0x20010201, + 0xd10, 0xa0633333, + 0xd14, 0x3333bc43, + 0xd18, 0x7a8f5b6b, + 0xd2c, 0xcc979975, + 0xd30, 0x00000000, + 0xd34, 0x80608000, + 0xd38, 0x00000000, + 0xd3c, 0x00027293, + 0xd40, 0x00000000, + 0xd44, 0x00000000, + 0xd48, 0x00000000, + 0xd4c, 0x00000000, + 0xd50, 0x6437140a, + 0xd54, 0x00000000, + 0xd58, 0x00000000, + 0xd5c, 0x30032064, + 0xd60, 0x4653de68, + 0xd64, 0x04518a3c, + 0xd68, 0x00002101, + 0xd6c, 0x2a201c16, + 0xd70, 0x1812362e, + 0xd74, 0x322c2220, + 0xd78, 0x000e3c24, + 0xe00, 0x2a2a2a2a, + 0xe04, 0x2a2a2a2a, + 0xe08, 0x03902a2a, + 0xe10, 0x2a2a2a2a, + 0xe14, 0x2a2a2a2a, + 0xe18, 0x2a2a2a2a, + 0xe1c, 0x2a2a2a2a, + 0xe28, 0x00000000, + 0xe30, 0x1000dc1f, + 0xe34, 0x10008c1f, + 0xe38, 0x02140102, + 0xe3c, 0x681604c2, + 0xe40, 0x01007c00, + 0xe44, 0x01004800, + 0xe48, 0xfb000000, + 0xe4c, 0x000028d1, + 0xe50, 0x1000dc1f, + 0xe54, 0x10008c1f, + 0xe58, 0x02140102, + 0xe5c, 0x28160d05, + 0xe60, 0x00000008, + 0xe68, 0x001b25a4, + 0xe6c, 0x631b25a0, + 0xe70, 0x631b25a0, + 0xe74, 0x081b25a0, + 0xe78, 0x081b25a0, + 0xe7c, 0x081b25a0, + 0xe80, 0x081b25a0, + 0xe84, 0x631b25a0, + 0xe88, 0x081b25a0, + 0xe8c, 0x631b25a0, + 0xed0, 0x631b25a0, + 0xed4, 0x631b25a0, + 0xed8, 0x631b25a0, + 0xedc, 0x001b25a0, + 0xee0, 0x001b25a0, + 0xeec, 0x6b1b25a0, + 0xf14, 0x00000003, + 0xf4c, 0x00000000, + 0xf00, 0x00000300, +}; + +u32 RTL8192CUPHY_REG_ARRAY_PG[RTL8192CUPHY_REG_ARRAY_PGLENGTH] = { + 0xe00, 0xffffffff, 0x07090c0c, + 0xe04, 0xffffffff, 0x01020405, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x0b0c0c0e, + 0xe14, 0xffffffff, 0x01030506, + 0xe18, 0xffffffff, 0x0b0c0d0e, + 0xe1c, 0xffffffff, 0x01030509, + 0x830, 0xffffffff, 0x07090c0c, + 0x834, 0xffffffff, 0x01020405, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x0b0c0d0e, + 0x848, 0xffffffff, 0x01030509, + 0x84c, 0xffffffff, 0x0b0c0d0e, + 0x868, 0xffffffff, 0x01030509, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x06060606, + 0xe14, 0xffffffff, 0x00020406, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x06060606, + 0x848, 0xffffffff, 0x00020406, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, +}; + +u32 RTL8192CURADIOA_2TARRAY[RTL8192CURADIOA_2TARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00031284, + 0x002, 0x00098000, + 0x003, 0x00018c63, + 0x004, 0x000210e7, + 0x009, 0x0002044f, + 0x00a, 0x0001adb1, + 0x00b, 0x00054867, + 0x00c, 0x0008992e, + 0x00d, 0x0000e52c, + 0x00e, 0x00039ce7, + 0x00f, 0x00000451, + 0x019, 0x00000000, + 0x01a, 0x00010255, + 0x01b, 0x00060a00, + 0x01c, 0x000fc378, + 0x01d, 0x000a1250, + 0x01e, 0x0004445f, + 0x01f, 0x00080001, + 0x020, 0x0000b614, + 0x021, 0x0006c000, + 0x022, 0x00000000, + 0x023, 0x00001558, + 0x024, 0x00000060, + 0x025, 0x00000483, + 0x026, 0x0004f000, + 0x027, 0x000ec7d9, + 0x028, 0x000577c0, + 0x029, 0x00004783, + 0x02a, 0x00000001, + 0x02b, 0x00021334, + 0x02a, 0x00000000, + 0x02b, 0x00000054, + 0x02a, 0x00000001, + 0x02b, 0x00000808, + 0x02b, 0x00053333, + 0x02c, 0x0000000c, + 0x02a, 0x00000002, + 0x02b, 0x00000808, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000003, + 0x02b, 0x00000808, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000004, + 0x02b, 0x00000808, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000005, + 0x02b, 0x00000808, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x00000006, + 0x02b, 0x00000709, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000007, + 0x02b, 0x00000709, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000008, + 0x02b, 0x0000060a, + 0x02b, 0x0004b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000009, + 0x02b, 0x0000060a, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000a, + 0x02b, 0x0000060a, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000b, + 0x02b, 0x0000060a, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000c, + 0x02b, 0x0000060a, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000d, + 0x02b, 0x0000060a, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000e, + 0x02b, 0x0000050b, + 0x02b, 0x00066666, + 0x02c, 0x0000001a, + 0x02a, 0x000e0000, + 0x010, 0x0004000f, + 0x011, 0x000e31fc, + 0x010, 0x0006000f, + 0x011, 0x000ff9f8, + 0x010, 0x0002000f, + 0x011, 0x000203f9, + 0x010, 0x0003000f, + 0x011, 0x000ff500, + 0x010, 0x00000000, + 0x011, 0x00000000, + 0x010, 0x0008000f, + 0x011, 0x0003f100, + 0x010, 0x0009000f, + 0x011, 0x00023100, + 0x012, 0x00032000, + 0x012, 0x00071000, + 0x012, 0x000b0000, + 0x012, 0x000fc000, + 0x013, 0x000287b3, + 0x013, 0x000244b7, + 0x013, 0x000204ab, + 0x013, 0x0001c49f, + 0x013, 0x00018493, + 0x013, 0x0001429b, + 0x013, 0x00010299, + 0x013, 0x0000c29c, + 0x013, 0x000081a0, + 0x013, 0x000040ac, + 0x013, 0x00000020, + 0x014, 0x0001944c, + 0x014, 0x00059444, + 0x014, 0x0009944c, + 0x014, 0x000d9444, + 0x015, 0x0000f424, + 0x015, 0x0004f424, + 0x015, 0x0008f424, + 0x015, 0x000cf424, + 0x016, 0x000e0330, + 0x016, 0x000a0330, + 0x016, 0x00060330, + 0x016, 0x00020330, + 0x000, 0x00010159, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01f, 0x00080003, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01e, 0x00044457, + 0x01f, 0x00080000, + 0x000, 0x00030159, +}; + +u32 RTL8192CU_RADIOB_2TARRAY[RTL8192CURADIOB_2TARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00031284, + 0x002, 0x00098000, + 0x003, 0x00018c63, + 0x004, 0x000210e7, + 0x009, 0x0002044f, + 0x00a, 0x0001adb1, + 0x00b, 0x00054867, + 0x00c, 0x0008992e, + 0x00d, 0x0000e52c, + 0x00e, 0x00039ce7, + 0x00f, 0x00000451, + 0x012, 0x00032000, + 0x012, 0x00071000, + 0x012, 0x000b0000, + 0x012, 0x000fc000, + 0x013, 0x000287af, + 0x013, 0x000244b7, + 0x013, 0x000204ab, + 0x013, 0x0001c49f, + 0x013, 0x00018493, + 0x013, 0x00014297, + 0x013, 0x00010295, + 0x013, 0x0000c298, + 0x013, 0x0000819c, + 0x013, 0x000040a8, + 0x013, 0x0000001c, + 0x014, 0x0001944c, + 0x014, 0x00059444, + 0x014, 0x0009944c, + 0x014, 0x000d9444, + 0x015, 0x0000f424, + 0x015, 0x0004f424, + 0x015, 0x0008f424, + 0x015, 0x000cf424, + 0x016, 0x000e0330, + 0x016, 0x000a0330, + 0x016, 0x00060330, + 0x016, 0x00020330, +}; + +u32 RTL8192CU_RADIOA_1TARRAY[RTL8192CURADIOA_1TARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00031284, + 0x002, 0x00098000, + 0x003, 0x00018c63, + 0x004, 0x000210e7, + 0x009, 0x0002044f, + 0x00a, 0x0001adb1, + 0x00b, 0x00054867, + 0x00c, 0x0008992e, + 0x00d, 0x0000e52c, + 0x00e, 0x00039ce7, + 0x00f, 0x00000451, + 0x019, 0x00000000, + 0x01a, 0x00010255, + 0x01b, 0x00060a00, + 0x01c, 0x000fc378, + 0x01d, 0x000a1250, + 0x01e, 0x0004445f, + 0x01f, 0x00080001, + 0x020, 0x0000b614, + 0x021, 0x0006c000, + 0x022, 0x00000000, + 0x023, 0x00001558, + 0x024, 0x00000060, + 0x025, 0x00000483, + 0x026, 0x0004f000, + 0x027, 0x000ec7d9, + 0x028, 0x000577c0, + 0x029, 0x00004783, + 0x02a, 0x00000001, + 0x02b, 0x00021334, + 0x02a, 0x00000000, + 0x02b, 0x00000054, + 0x02a, 0x00000001, + 0x02b, 0x00000808, + 0x02b, 0x00053333, + 0x02c, 0x0000000c, + 0x02a, 0x00000002, + 0x02b, 0x00000808, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000003, + 0x02b, 0x00000808, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000004, + 0x02b, 0x00000808, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000005, + 0x02b, 0x00000808, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x00000006, + 0x02b, 0x00000709, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000007, + 0x02b, 0x00000709, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000008, + 0x02b, 0x0000060a, + 0x02b, 0x0004b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000009, + 0x02b, 0x0000060a, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000a, + 0x02b, 0x0000060a, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000b, + 0x02b, 0x0000060a, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000c, + 0x02b, 0x0000060a, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000d, + 0x02b, 0x0000060a, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000e, + 0x02b, 0x0000050b, + 0x02b, 0x00066666, + 0x02c, 0x0000001a, + 0x02a, 0x000e0000, + 0x010, 0x0004000f, + 0x011, 0x000e31fc, + 0x010, 0x0006000f, + 0x011, 0x000ff9f8, + 0x010, 0x0002000f, + 0x011, 0x000203f9, + 0x010, 0x0003000f, + 0x011, 0x000ff500, + 0x010, 0x00000000, + 0x011, 0x00000000, + 0x010, 0x0008000f, + 0x011, 0x0003f100, + 0x010, 0x0009000f, + 0x011, 0x00023100, + 0x012, 0x00032000, + 0x012, 0x00071000, + 0x012, 0x000b0000, + 0x012, 0x000fc000, + 0x013, 0x000287b3, + 0x013, 0x000244b7, + 0x013, 0x000204ab, + 0x013, 0x0001c49f, + 0x013, 0x00018493, + 0x013, 0x0001429b, + 0x013, 0x00010299, + 0x013, 0x0000c29c, + 0x013, 0x000081a0, + 0x013, 0x000040ac, + 0x013, 0x00000020, + 0x014, 0x0001944c, + 0x014, 0x00059444, + 0x014, 0x0009944c, + 0x014, 0x000d9444, + 0x015, 0x0000f405, + 0x015, 0x0004f405, + 0x015, 0x0008f405, + 0x015, 0x000cf405, + 0x016, 0x000e0330, + 0x016, 0x000a0330, + 0x016, 0x00060330, + 0x016, 0x00020330, + 0x000, 0x00010159, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01f, 0x00080003, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01e, 0x00044457, + 0x01f, 0x00080000, + 0x000, 0x00030159, +}; + +u32 RTL8192CU_RADIOB_1TARRAY[RTL8192CURADIOB_1TARRAYLENGTH] = { + 0x0, +}; + +u32 RTL8192CUMAC_2T_ARRAY[RTL8192CUMAC_2T_ARRAYLENGTH] = { + 0x420, 0x00000080, + 0x423, 0x00000000, + 0x430, 0x00000000, + 0x431, 0x00000000, + 0x432, 0x00000000, + 0x433, 0x00000001, + 0x434, 0x00000004, + 0x435, 0x00000005, + 0x436, 0x00000006, + 0x437, 0x00000007, + 0x438, 0x00000000, + 0x439, 0x00000000, + 0x43a, 0x00000000, + 0x43b, 0x00000001, + 0x43c, 0x00000004, + 0x43d, 0x00000005, + 0x43e, 0x00000006, + 0x43f, 0x00000007, + 0x440, 0x0000005d, + 0x441, 0x00000001, + 0x442, 0x00000000, + 0x444, 0x00000015, + 0x445, 0x000000f0, + 0x446, 0x0000000f, + 0x447, 0x00000000, + 0x458, 0x00000041, + 0x459, 0x000000a8, + 0x45a, 0x00000072, + 0x45b, 0x000000b9, + 0x460, 0x00000066, + 0x461, 0x00000066, + 0x462, 0x00000008, + 0x463, 0x00000003, + 0x4c8, 0x000000ff, + 0x4c9, 0x00000008, + 0x4cc, 0x000000ff, + 0x4cd, 0x000000ff, + 0x4ce, 0x00000001, + 0x500, 0x00000026, + 0x501, 0x000000a2, + 0x502, 0x0000002f, + 0x503, 0x00000000, + 0x504, 0x00000028, + 0x505, 0x000000a3, + 0x506, 0x0000005e, + 0x507, 0x00000000, + 0x508, 0x0000002b, + 0x509, 0x000000a4, + 0x50a, 0x0000005e, + 0x50b, 0x00000000, + 0x50c, 0x0000004f, + 0x50d, 0x000000a4, + 0x50e, 0x00000000, + 0x50f, 0x00000000, + 0x512, 0x0000001c, + 0x514, 0x0000000a, + 0x515, 0x00000010, + 0x516, 0x0000000a, + 0x517, 0x00000010, + 0x51a, 0x00000016, + 0x524, 0x0000000f, + 0x525, 0x0000004f, + 0x546, 0x00000040, + 0x547, 0x00000000, + 0x550, 0x00000010, + 0x551, 0x00000010, + 0x559, 0x00000002, + 0x55a, 0x00000002, + 0x55d, 0x000000ff, + 0x605, 0x00000030, + 0x608, 0x0000000e, + 0x609, 0x0000002a, + 0x652, 0x00000020, + 0x63c, 0x00000008, + 0x63d, 0x00000008, + 0x63e, 0x0000000c, + 0x63f, 0x0000000c, + 0x66e, 0x00000005, + 0x700, 0x00000021, + 0x701, 0x00000043, + 0x702, 0x00000065, + 0x703, 0x00000087, + 0x708, 0x00000021, + 0x709, 0x00000043, + 0x70a, 0x00000065, + 0x70b, 0x00000087, +}; + +u32 RTL8192CUAGCTAB_2TARRAY[RTL8192CUAGCTAB_2TARRAYLENGTH] = { + 0xc78, 0x7b000001, + 0xc78, 0x7b010001, + 0xc78, 0x7b020001, + 0xc78, 0x7b030001, + 0xc78, 0x7b040001, + 0xc78, 0x7b050001, + 0xc78, 0x7a060001, + 0xc78, 0x79070001, + 0xc78, 0x78080001, + 0xc78, 0x77090001, + 0xc78, 0x760a0001, + 0xc78, 0x750b0001, + 0xc78, 0x740c0001, + 0xc78, 0x730d0001, + 0xc78, 0x720e0001, + 0xc78, 0x710f0001, + 0xc78, 0x70100001, + 0xc78, 0x6f110001, + 0xc78, 0x6e120001, + 0xc78, 0x6d130001, + 0xc78, 0x6c140001, + 0xc78, 0x6b150001, + 0xc78, 0x6a160001, + 0xc78, 0x69170001, + 0xc78, 0x68180001, + 0xc78, 0x67190001, + 0xc78, 0x661a0001, + 0xc78, 0x651b0001, + 0xc78, 0x641c0001, + 0xc78, 0x631d0001, + 0xc78, 0x621e0001, + 0xc78, 0x611f0001, + 0xc78, 0x60200001, + 0xc78, 0x49210001, + 0xc78, 0x48220001, + 0xc78, 0x47230001, + 0xc78, 0x46240001, + 0xc78, 0x45250001, + 0xc78, 0x44260001, + 0xc78, 0x43270001, + 0xc78, 0x42280001, + 0xc78, 0x41290001, + 0xc78, 0x402a0001, + 0xc78, 0x262b0001, + 0xc78, 0x252c0001, + 0xc78, 0x242d0001, + 0xc78, 0x232e0001, + 0xc78, 0x222f0001, + 0xc78, 0x21300001, + 0xc78, 0x20310001, + 0xc78, 0x06320001, + 0xc78, 0x05330001, + 0xc78, 0x04340001, + 0xc78, 0x03350001, + 0xc78, 0x02360001, + 0xc78, 0x01370001, + 0xc78, 0x00380001, + 0xc78, 0x00390001, + 0xc78, 0x003a0001, + 0xc78, 0x003b0001, + 0xc78, 0x003c0001, + 0xc78, 0x003d0001, + 0xc78, 0x003e0001, + 0xc78, 0x003f0001, + 0xc78, 0x7b400001, + 0xc78, 0x7b410001, + 0xc78, 0x7b420001, + 0xc78, 0x7b430001, + 0xc78, 0x7b440001, + 0xc78, 0x7b450001, + 0xc78, 0x7a460001, + 0xc78, 0x79470001, + 0xc78, 0x78480001, + 0xc78, 0x77490001, + 0xc78, 0x764a0001, + 0xc78, 0x754b0001, + 0xc78, 0x744c0001, + 0xc78, 0x734d0001, + 0xc78, 0x724e0001, + 0xc78, 0x714f0001, + 0xc78, 0x70500001, + 0xc78, 0x6f510001, + 0xc78, 0x6e520001, + 0xc78, 0x6d530001, + 0xc78, 0x6c540001, + 0xc78, 0x6b550001, + 0xc78, 0x6a560001, + 0xc78, 0x69570001, + 0xc78, 0x68580001, + 0xc78, 0x67590001, + 0xc78, 0x665a0001, + 0xc78, 0x655b0001, + 0xc78, 0x645c0001, + 0xc78, 0x635d0001, + 0xc78, 0x625e0001, + 0xc78, 0x615f0001, + 0xc78, 0x60600001, + 0xc78, 0x49610001, + 0xc78, 0x48620001, + 0xc78, 0x47630001, + 0xc78, 0x46640001, + 0xc78, 0x45650001, + 0xc78, 0x44660001, + 0xc78, 0x43670001, + 0xc78, 0x42680001, + 0xc78, 0x41690001, + 0xc78, 0x406a0001, + 0xc78, 0x266b0001, + 0xc78, 0x256c0001, + 0xc78, 0x246d0001, + 0xc78, 0x236e0001, + 0xc78, 0x226f0001, + 0xc78, 0x21700001, + 0xc78, 0x20710001, + 0xc78, 0x06720001, + 0xc78, 0x05730001, + 0xc78, 0x04740001, + 0xc78, 0x03750001, + 0xc78, 0x02760001, + 0xc78, 0x01770001, + 0xc78, 0x00780001, + 0xc78, 0x00790001, + 0xc78, 0x007a0001, + 0xc78, 0x007b0001, + 0xc78, 0x007c0001, + 0xc78, 0x007d0001, + 0xc78, 0x007e0001, + 0xc78, 0x007f0001, + 0xc78, 0x3800001e, + 0xc78, 0x3801001e, + 0xc78, 0x3802001e, + 0xc78, 0x3803001e, + 0xc78, 0x3804001e, + 0xc78, 0x3805001e, + 0xc78, 0x3806001e, + 0xc78, 0x3807001e, + 0xc78, 0x3808001e, + 0xc78, 0x3c09001e, + 0xc78, 0x3e0a001e, + 0xc78, 0x400b001e, + 0xc78, 0x440c001e, + 0xc78, 0x480d001e, + 0xc78, 0x4c0e001e, + 0xc78, 0x500f001e, + 0xc78, 0x5210001e, + 0xc78, 0x5611001e, + 0xc78, 0x5a12001e, + 0xc78, 0x5e13001e, + 0xc78, 0x6014001e, + 0xc78, 0x6015001e, + 0xc78, 0x6016001e, + 0xc78, 0x6217001e, + 0xc78, 0x6218001e, + 0xc78, 0x6219001e, + 0xc78, 0x621a001e, + 0xc78, 0x621b001e, + 0xc78, 0x621c001e, + 0xc78, 0x621d001e, + 0xc78, 0x621e001e, + 0xc78, 0x621f001e, +}; + +u32 RTL8192CUAGCTAB_1TARRAY[RTL8192CUAGCTAB_1TARRAYLENGTH] = { + 0xc78, 0x7b000001, + 0xc78, 0x7b010001, + 0xc78, 0x7b020001, + 0xc78, 0x7b030001, + 0xc78, 0x7b040001, + 0xc78, 0x7b050001, + 0xc78, 0x7a060001, + 0xc78, 0x79070001, + 0xc78, 0x78080001, + 0xc78, 0x77090001, + 0xc78, 0x760a0001, + 0xc78, 0x750b0001, + 0xc78, 0x740c0001, + 0xc78, 0x730d0001, + 0xc78, 0x720e0001, + 0xc78, 0x710f0001, + 0xc78, 0x70100001, + 0xc78, 0x6f110001, + 0xc78, 0x6e120001, + 0xc78, 0x6d130001, + 0xc78, 0x6c140001, + 0xc78, 0x6b150001, + 0xc78, 0x6a160001, + 0xc78, 0x69170001, + 0xc78, 0x68180001, + 0xc78, 0x67190001, + 0xc78, 0x661a0001, + 0xc78, 0x651b0001, + 0xc78, 0x641c0001, + 0xc78, 0x631d0001, + 0xc78, 0x621e0001, + 0xc78, 0x611f0001, + 0xc78, 0x60200001, + 0xc78, 0x49210001, + 0xc78, 0x48220001, + 0xc78, 0x47230001, + 0xc78, 0x46240001, + 0xc78, 0x45250001, + 0xc78, 0x44260001, + 0xc78, 0x43270001, + 0xc78, 0x42280001, + 0xc78, 0x41290001, + 0xc78, 0x402a0001, + 0xc78, 0x262b0001, + 0xc78, 0x252c0001, + 0xc78, 0x242d0001, + 0xc78, 0x232e0001, + 0xc78, 0x222f0001, + 0xc78, 0x21300001, + 0xc78, 0x20310001, + 0xc78, 0x06320001, + 0xc78, 0x05330001, + 0xc78, 0x04340001, + 0xc78, 0x03350001, + 0xc78, 0x02360001, + 0xc78, 0x01370001, + 0xc78, 0x00380001, + 0xc78, 0x00390001, + 0xc78, 0x003a0001, + 0xc78, 0x003b0001, + 0xc78, 0x003c0001, + 0xc78, 0x003d0001, + 0xc78, 0x003e0001, + 0xc78, 0x003f0001, + 0xc78, 0x7b400001, + 0xc78, 0x7b410001, + 0xc78, 0x7b420001, + 0xc78, 0x7b430001, + 0xc78, 0x7b440001, + 0xc78, 0x7b450001, + 0xc78, 0x7a460001, + 0xc78, 0x79470001, + 0xc78, 0x78480001, + 0xc78, 0x77490001, + 0xc78, 0x764a0001, + 0xc78, 0x754b0001, + 0xc78, 0x744c0001, + 0xc78, 0x734d0001, + 0xc78, 0x724e0001, + 0xc78, 0x714f0001, + 0xc78, 0x70500001, + 0xc78, 0x6f510001, + 0xc78, 0x6e520001, + 0xc78, 0x6d530001, + 0xc78, 0x6c540001, + 0xc78, 0x6b550001, + 0xc78, 0x6a560001, + 0xc78, 0x69570001, + 0xc78, 0x68580001, + 0xc78, 0x67590001, + 0xc78, 0x665a0001, + 0xc78, 0x655b0001, + 0xc78, 0x645c0001, + 0xc78, 0x635d0001, + 0xc78, 0x625e0001, + 0xc78, 0x615f0001, + 0xc78, 0x60600001, + 0xc78, 0x49610001, + 0xc78, 0x48620001, + 0xc78, 0x47630001, + 0xc78, 0x46640001, + 0xc78, 0x45650001, + 0xc78, 0x44660001, + 0xc78, 0x43670001, + 0xc78, 0x42680001, + 0xc78, 0x41690001, + 0xc78, 0x406a0001, + 0xc78, 0x266b0001, + 0xc78, 0x256c0001, + 0xc78, 0x246d0001, + 0xc78, 0x236e0001, + 0xc78, 0x226f0001, + 0xc78, 0x21700001, + 0xc78, 0x20710001, + 0xc78, 0x06720001, + 0xc78, 0x05730001, + 0xc78, 0x04740001, + 0xc78, 0x03750001, + 0xc78, 0x02760001, + 0xc78, 0x01770001, + 0xc78, 0x00780001, + 0xc78, 0x00790001, + 0xc78, 0x007a0001, + 0xc78, 0x007b0001, + 0xc78, 0x007c0001, + 0xc78, 0x007d0001, + 0xc78, 0x007e0001, + 0xc78, 0x007f0001, + 0xc78, 0x3800001e, + 0xc78, 0x3801001e, + 0xc78, 0x3802001e, + 0xc78, 0x3803001e, + 0xc78, 0x3804001e, + 0xc78, 0x3805001e, + 0xc78, 0x3806001e, + 0xc78, 0x3807001e, + 0xc78, 0x3808001e, + 0xc78, 0x3c09001e, + 0xc78, 0x3e0a001e, + 0xc78, 0x400b001e, + 0xc78, 0x440c001e, + 0xc78, 0x480d001e, + 0xc78, 0x4c0e001e, + 0xc78, 0x500f001e, + 0xc78, 0x5210001e, + 0xc78, 0x5611001e, + 0xc78, 0x5a12001e, + 0xc78, 0x5e13001e, + 0xc78, 0x6014001e, + 0xc78, 0x6015001e, + 0xc78, 0x6016001e, + 0xc78, 0x6217001e, + 0xc78, 0x6218001e, + 0xc78, 0x6219001e, + 0xc78, 0x621a001e, + 0xc78, 0x621b001e, + 0xc78, 0x621c001e, + 0xc78, 0x621d001e, + 0xc78, 0x621e001e, + 0xc78, 0x621f001e, +}; + +u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength] = { + 0x024, 0x0011800f, + 0x028, 0x00ffdb83, + 0x040, 0x000c0004, + 0x800, 0x80040000, + 0x804, 0x00000001, + 0x808, 0x0000fc00, + 0x80c, 0x0000000a, + 0x810, 0x10005388, + 0x814, 0x020c3d10, + 0x818, 0x02200385, + 0x81c, 0x00000000, + 0x820, 0x01000100, + 0x824, 0x00390204, + 0x828, 0x00000000, + 0x82c, 0x00000000, + 0x830, 0x00000000, + 0x834, 0x00000000, + 0x838, 0x00000000, + 0x83c, 0x00000000, + 0x840, 0x00010000, + 0x844, 0x00000000, + 0x848, 0x00000000, + 0x84c, 0x00000000, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x569a569a, + 0x85c, 0x001b25a4, + 0x860, 0x66e60230, + 0x864, 0x061f0130, + 0x868, 0x00000000, + 0x86c, 0x20202000, + 0x870, 0x03000300, + 0x874, 0x22004000, + 0x878, 0x00000808, + 0x87c, 0x00ffc3f1, + 0x880, 0xc0083070, + 0x884, 0x000004d5, + 0x888, 0x00000000, + 0x88c, 0xccc000c0, + 0x890, 0x00000800, + 0x894, 0xfffffffe, + 0x898, 0x40302010, + 0x89c, 0x00706050, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90c, 0x81121111, + 0xa00, 0x00d047c8, + 0xa04, 0x80ff000c, + 0xa08, 0x8c838300, + 0xa0c, 0x2e68120f, + 0xa10, 0x9500bb78, + 0xa14, 0x11144028, + 0xa18, 0x00881117, + 0xa1c, 0x89140f00, + 0xa20, 0x15160000, + 0xa24, 0x070b0f12, + 0xa28, 0x00000104, + 0xa2c, 0x00d30000, + 0xa70, 0x101fbf00, + 0xa74, 0x00000007, + 0xc00, 0x48071d40, + 0xc04, 0x03a05611, + 0xc08, 0x000000e4, + 0xc0c, 0x6c6c6c6c, + 0xc10, 0x08800000, + 0xc14, 0x40000100, + 0xc18, 0x08800000, + 0xc1c, 0x40000100, + 0xc20, 0x00000000, + 0xc24, 0x00000000, + 0xc28, 0x00000000, + 0xc2c, 0x00000000, + 0xc30, 0x69e9ac44, + 0xc34, 0x469652cf, + 0xc38, 0x49795994, + 0xc3c, 0x0a97971c, + 0xc40, 0x1f7c403f, + 0xc44, 0x000100b7, + 0xc48, 0xec020107, + 0xc4c, 0x007f037f, + 0xc50, 0x6954342e, + 0xc54, 0x43bc0094, + 0xc58, 0x6954342f, + 0xc5c, 0x433c0094, + 0xc60, 0x00000000, + 0xc64, 0x5116848b, + 0xc68, 0x47c00bff, + 0xc6c, 0x00000036, + 0xc70, 0x2c46000d, + 0xc74, 0x018610db, + 0xc78, 0x0000001f, + 0xc7c, 0x00b91612, + 0xc80, 0x24000090, + 0xc84, 0x20f60000, + 0xc88, 0x24000090, + 0xc8c, 0x20200000, + 0xc90, 0x00121820, + 0xc94, 0x00000000, + 0xc98, 0x00121820, + 0xc9c, 0x00007f7f, + 0xca0, 0x00000000, + 0xca4, 0x00000080, + 0xca8, 0x00000000, + 0xcac, 0x00000000, + 0xcb0, 0x00000000, + 0xcb4, 0x00000000, + 0xcb8, 0x00000000, + 0xcbc, 0x28000000, + 0xcc0, 0x00000000, + 0xcc4, 0x00000000, + 0xcc8, 0x00000000, + 0xccc, 0x00000000, + 0xcd0, 0x00000000, + 0xcd4, 0x00000000, + 0xcd8, 0x64b22427, + 0xcdc, 0x00766932, + 0xce0, 0x00222222, + 0xce4, 0x00000000, + 0xce8, 0x37644302, + 0xcec, 0x2f97d40c, + 0xd00, 0x00080740, + 0xd04, 0x00020401, + 0xd08, 0x0000907f, + 0xd0c, 0x20010201, + 0xd10, 0xa0633333, + 0xd14, 0x3333bc43, + 0xd18, 0x7a8f5b6b, + 0xd2c, 0xcc979975, + 0xd30, 0x00000000, + 0xd34, 0x80608000, + 0xd38, 0x00000000, + 0xd3c, 0x00027293, + 0xd40, 0x00000000, + 0xd44, 0x00000000, + 0xd48, 0x00000000, + 0xd4c, 0x00000000, + 0xd50, 0x6437140a, + 0xd54, 0x00000000, + 0xd58, 0x00000000, + 0xd5c, 0x30032064, + 0xd60, 0x4653de68, + 0xd64, 0x04518a3c, + 0xd68, 0x00002101, + 0xd6c, 0x2a201c16, + 0xd70, 0x1812362e, + 0xd74, 0x322c2220, + 0xd78, 0x000e3c24, + 0xe00, 0x24242424, + 0xe04, 0x24242424, + 0xe08, 0x03902024, + 0xe10, 0x24242424, + 0xe14, 0x24242424, + 0xe18, 0x24242424, + 0xe1c, 0x24242424, + 0xe28, 0x00000000, + 0xe30, 0x1000dc1f, + 0xe34, 0x10008c1f, + 0xe38, 0x02140102, + 0xe3c, 0x681604c2, + 0xe40, 0x01007c00, + 0xe44, 0x01004800, + 0xe48, 0xfb000000, + 0xe4c, 0x000028d1, + 0xe50, 0x1000dc1f, + 0xe54, 0x10008c1f, + 0xe58, 0x02140102, + 0xe5c, 0x28160d05, + 0xe60, 0x00000008, + 0xe68, 0x001b25a4, + 0xe6c, 0x631b25a0, + 0xe70, 0x631b25a0, + 0xe74, 0x081b25a0, + 0xe78, 0x081b25a0, + 0xe7c, 0x081b25a0, + 0xe80, 0x081b25a0, + 0xe84, 0x631b25a0, + 0xe88, 0x081b25a0, + 0xe8c, 0x631b25a0, + 0xed0, 0x631b25a0, + 0xed4, 0x631b25a0, + 0xed8, 0x631b25a0, + 0xedc, 0x001b25a0, + 0xee0, 0x001b25a0, + 0xeec, 0x6b1b25a0, + 0xee8, 0x31555448, + 0xf14, 0x00000003, + 0xf4c, 0x00000000, + 0xf00, 0x00000300, +}; + +u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength] = { + 0xe00, 0xffffffff, 0x06080808, + 0xe04, 0xffffffff, 0x00040406, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x04060608, + 0xe14, 0xffffffff, 0x00020204, + 0xe18, 0xffffffff, 0x04060608, + 0xe1c, 0xffffffff, 0x00020204, + 0x830, 0xffffffff, 0x06080808, + 0x834, 0xffffffff, 0x00040406, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x04060608, + 0x848, 0xffffffff, 0x00020204, + 0x84c, 0xffffffff, 0x04060608, + 0x868, 0xffffffff, 0x00020204, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, +}; + +u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength] = { + 0x000, 0x00030159, + 0x001, 0x00031284, + 0x002, 0x00098000, + 0x003, 0x00018c63, + 0x004, 0x000210e7, + 0x009, 0x0002044f, + 0x00a, 0x0001adb0, + 0x00b, 0x00054867, + 0x00c, 0x0008992e, + 0x00d, 0x0000e529, + 0x00e, 0x00039ce7, + 0x00f, 0x00000451, + 0x019, 0x00000000, + 0x01a, 0x00000255, + 0x01b, 0x00060a00, + 0x01c, 0x000fc378, + 0x01d, 0x000a1250, + 0x01e, 0x0004445f, + 0x01f, 0x00080001, + 0x020, 0x0000b614, + 0x021, 0x0006c000, + 0x022, 0x0000083c, + 0x023, 0x00001558, + 0x024, 0x00000060, + 0x025, 0x00000483, + 0x026, 0x0004f000, + 0x027, 0x000ec7d9, + 0x028, 0x000977c0, + 0x029, 0x00004783, + 0x02a, 0x00000001, + 0x02b, 0x00021334, + 0x02a, 0x00000000, + 0x02b, 0x00000054, + 0x02a, 0x00000001, + 0x02b, 0x00000808, + 0x02b, 0x00053333, + 0x02c, 0x0000000c, + 0x02a, 0x00000002, + 0x02b, 0x00000808, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000003, + 0x02b, 0x00000808, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000004, + 0x02b, 0x00000808, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000005, + 0x02b, 0x00000808, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x00000006, + 0x02b, 0x00000709, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000007, + 0x02b, 0x00000709, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000008, + 0x02b, 0x0000060a, + 0x02b, 0x0004b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000009, + 0x02b, 0x0000060a, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000a, + 0x02b, 0x0000060a, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000b, + 0x02b, 0x0000060a, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000c, + 0x02b, 0x0000060a, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000d, + 0x02b, 0x0000060a, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000e, + 0x02b, 0x0000050b, + 0x02b, 0x00066666, + 0x02c, 0x0000001a, + 0x02a, 0x000e0000, + 0x010, 0x0004000f, + 0x011, 0x000e31fc, + 0x010, 0x0006000f, + 0x011, 0x000ff9f8, + 0x010, 0x0002000f, + 0x011, 0x000203f9, + 0x010, 0x0003000f, + 0x011, 0x000ff500, + 0x010, 0x00000000, + 0x011, 0x00000000, + 0x010, 0x0008000f, + 0x011, 0x0003f100, + 0x010, 0x0009000f, + 0x011, 0x00023100, + 0x012, 0x000d8000, + 0x012, 0x00090000, + 0x012, 0x00051000, + 0x012, 0x00012000, + 0x013, 0x00028fb4, + 0x013, 0x00024fa8, + 0x013, 0x000207a4, + 0x013, 0x0001c798, + 0x013, 0x000183a4, + 0x013, 0x00014398, + 0x013, 0x000101a4, + 0x013, 0x0000c198, + 0x013, 0x000080a4, + 0x013, 0x00004098, + 0x013, 0x00000000, + 0x014, 0x0001944c, + 0x014, 0x00059444, + 0x014, 0x0009944c, + 0x014, 0x000d9444, + 0x015, 0x0000f405, + 0x015, 0x0004f405, + 0x015, 0x0008f405, + 0x015, 0x000cf405, + 0x016, 0x000e0330, + 0x016, 0x000a0330, + 0x016, 0x00060330, + 0x016, 0x00020330, + 0x000, 0x00010159, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01f, 0x00080003, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01e, 0x00044457, + 0x01f, 0x00080000, + 0x000, 0x00030159, +}; + +u32 Rtl8192CUAGCTAB_1T_HPArray[RTL8192CUAGCTAB_1T_HPArrayLength] = { + 0xc78, 0x7b000001, + 0xc78, 0x7b010001, + 0xc78, 0x7b020001, + 0xc78, 0x7b030001, + 0xc78, 0x7b040001, + 0xc78, 0x7b050001, + 0xc78, 0x7b060001, + 0xc78, 0x7b070001, + 0xc78, 0x7b080001, + 0xc78, 0x7a090001, + 0xc78, 0x790a0001, + 0xc78, 0x780b0001, + 0xc78, 0x770c0001, + 0xc78, 0x760d0001, + 0xc78, 0x750e0001, + 0xc78, 0x740f0001, + 0xc78, 0x73100001, + 0xc78, 0x72110001, + 0xc78, 0x71120001, + 0xc78, 0x70130001, + 0xc78, 0x6f140001, + 0xc78, 0x6e150001, + 0xc78, 0x6d160001, + 0xc78, 0x6c170001, + 0xc78, 0x6b180001, + 0xc78, 0x6a190001, + 0xc78, 0x691a0001, + 0xc78, 0x681b0001, + 0xc78, 0x671c0001, + 0xc78, 0x661d0001, + 0xc78, 0x651e0001, + 0xc78, 0x641f0001, + 0xc78, 0x63200001, + 0xc78, 0x62210001, + 0xc78, 0x61220001, + 0xc78, 0x60230001, + 0xc78, 0x46240001, + 0xc78, 0x45250001, + 0xc78, 0x44260001, + 0xc78, 0x43270001, + 0xc78, 0x42280001, + 0xc78, 0x41290001, + 0xc78, 0x402a0001, + 0xc78, 0x262b0001, + 0xc78, 0x252c0001, + 0xc78, 0x242d0001, + 0xc78, 0x232e0001, + 0xc78, 0x222f0001, + 0xc78, 0x21300001, + 0xc78, 0x20310001, + 0xc78, 0x06320001, + 0xc78, 0x05330001, + 0xc78, 0x04340001, + 0xc78, 0x03350001, + 0xc78, 0x02360001, + 0xc78, 0x01370001, + 0xc78, 0x00380001, + 0xc78, 0x00390001, + 0xc78, 0x003a0001, + 0xc78, 0x003b0001, + 0xc78, 0x003c0001, + 0xc78, 0x003d0001, + 0xc78, 0x003e0001, + 0xc78, 0x003f0001, + 0xc78, 0x7b400001, + 0xc78, 0x7b410001, + 0xc78, 0x7b420001, + 0xc78, 0x7b430001, + 0xc78, 0x7b440001, + 0xc78, 0x7b450001, + 0xc78, 0x7b460001, + 0xc78, 0x7b470001, + 0xc78, 0x7b480001, + 0xc78, 0x7a490001, + 0xc78, 0x794a0001, + 0xc78, 0x784b0001, + 0xc78, 0x774c0001, + 0xc78, 0x764d0001, + 0xc78, 0x754e0001, + 0xc78, 0x744f0001, + 0xc78, 0x73500001, + 0xc78, 0x72510001, + 0xc78, 0x71520001, + 0xc78, 0x70530001, + 0xc78, 0x6f540001, + 0xc78, 0x6e550001, + 0xc78, 0x6d560001, + 0xc78, 0x6c570001, + 0xc78, 0x6b580001, + 0xc78, 0x6a590001, + 0xc78, 0x695a0001, + 0xc78, 0x685b0001, + 0xc78, 0x675c0001, + 0xc78, 0x665d0001, + 0xc78, 0x655e0001, + 0xc78, 0x645f0001, + 0xc78, 0x63600001, + 0xc78, 0x62610001, + 0xc78, 0x61620001, + 0xc78, 0x60630001, + 0xc78, 0x46640001, + 0xc78, 0x45650001, + 0xc78, 0x44660001, + 0xc78, 0x43670001, + 0xc78, 0x42680001, + 0xc78, 0x41690001, + 0xc78, 0x406a0001, + 0xc78, 0x266b0001, + 0xc78, 0x256c0001, + 0xc78, 0x246d0001, + 0xc78, 0x236e0001, + 0xc78, 0x226f0001, + 0xc78, 0x21700001, + 0xc78, 0x20710001, + 0xc78, 0x06720001, + 0xc78, 0x05730001, + 0xc78, 0x04740001, + 0xc78, 0x03750001, + 0xc78, 0x02760001, + 0xc78, 0x01770001, + 0xc78, 0x00780001, + 0xc78, 0x00790001, + 0xc78, 0x007a0001, + 0xc78, 0x007b0001, + 0xc78, 0x007c0001, + 0xc78, 0x007d0001, + 0xc78, 0x007e0001, + 0xc78, 0x007f0001, + 0xc78, 0x3800001e, + 0xc78, 0x3801001e, + 0xc78, 0x3802001e, + 0xc78, 0x3803001e, + 0xc78, 0x3804001e, + 0xc78, 0x3805001e, + 0xc78, 0x3806001e, + 0xc78, 0x3807001e, + 0xc78, 0x3808001e, + 0xc78, 0x3c09001e, + 0xc78, 0x3e0a001e, + 0xc78, 0x400b001e, + 0xc78, 0x440c001e, + 0xc78, 0x480d001e, + 0xc78, 0x4c0e001e, + 0xc78, 0x500f001e, + 0xc78, 0x5210001e, + 0xc78, 0x5611001e, + 0xc78, 0x5a12001e, + 0xc78, 0x5e13001e, + 0xc78, 0x6014001e, + 0xc78, 0x6015001e, + 0xc78, 0x6016001e, + 0xc78, 0x6217001e, + 0xc78, 0x6218001e, + 0xc78, 0x6219001e, + 0xc78, 0x621a001e, + 0xc78, 0x621b001e, + 0xc78, 0x621c001e, + 0xc78, 0x621d001e, + 0xc78, 0x621e001e, + 0xc78, 0x621f001e, +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h new file mode 100644 index 000000000000..4b020e9e30b1 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/table.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CU_TABLE__H_ +#define __RTL92CU_TABLE__H_ + +#include + +#define RTL8192CUPHY_REG_2TARRAY_LENGTH 374 +extern u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH]; +#define RTL8192CUPHY_REG_1TARRAY_LENGTH 374 +extern u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH]; + +#define RTL8192CUPHY_REG_ARRAY_PGLENGTH 336 +extern u32 RTL8192CUPHY_REG_ARRAY_PG[RTL8192CUPHY_REG_ARRAY_PGLENGTH]; + +#define RTL8192CURADIOA_2TARRAYLENGTH 282 +extern u32 RTL8192CURADIOA_2TARRAY[RTL8192CURADIOA_2TARRAYLENGTH]; +#define RTL8192CURADIOB_2TARRAYLENGTH 78 +extern u32 RTL8192CU_RADIOB_2TARRAY[RTL8192CURADIOB_2TARRAYLENGTH]; +#define RTL8192CURADIOA_1TARRAYLENGTH 282 +extern u32 RTL8192CU_RADIOA_1TARRAY[RTL8192CURADIOA_1TARRAYLENGTH]; +#define RTL8192CURADIOB_1TARRAYLENGTH 1 +extern u32 RTL8192CU_RADIOB_1TARRAY[RTL8192CURADIOB_1TARRAYLENGTH]; + +#define RTL8192CUMAC_2T_ARRAYLENGTH 172 +extern u32 RTL8192CUMAC_2T_ARRAY[RTL8192CUMAC_2T_ARRAYLENGTH]; + +#define RTL8192CUAGCTAB_2TARRAYLENGTH 320 +extern u32 RTL8192CUAGCTAB_2TARRAY[RTL8192CUAGCTAB_2TARRAYLENGTH]; +#define RTL8192CUAGCTAB_1TARRAYLENGTH 320 +extern u32 RTL8192CUAGCTAB_1TARRAY[RTL8192CUAGCTAB_1TARRAYLENGTH]; + +#define RTL8192CUPHY_REG_1T_HPArrayLength 378 +extern u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength]; + +#define RTL8192CUPHY_REG_Array_PG_HPLength 336 +extern u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength]; + +#define RTL8192CURadioA_1T_HPArrayLength 282 +extern u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength]; +#define RTL8192CUAGCTAB_1T_HPArrayLength 320 +extern u32 Rtl8192CUAGCTAB_1T_HPArray[RTL8192CUAGCTAB_1T_HPArrayLength]; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c new file mode 100644 index 000000000000..95880fe4106e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c @@ -0,0 +1,686 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../usb.h" +#include "../ps.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "mac.h" +#include "trx.h" +#include "../rtl8192c/fw_common.h" + +static int _ConfigVerTOutEP(struct ieee80211_hw *hw) +{ + u8 ep_cfg, txqsele; + u8 ep_nums = 0; + + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); + + rtlusb->out_queue_sel = 0; + ep_cfg = rtl_read_byte(rtlpriv, REG_TEST_SIE_OPTIONAL); + ep_cfg = (ep_cfg & USB_TEST_EP_MASK) >> USB_TEST_EP_SHIFT; + switch (ep_cfg) { + case 0: /* 2 bulk OUT, 1 bulk IN */ + case 3: + rtlusb->out_queue_sel = TX_SELE_HQ | TX_SELE_LQ; + ep_nums = 2; + break; + case 1: /* 1 bulk IN/OUT => map all endpoint to Low queue */ + case 2: /* 1 bulk IN, 1 bulk OUT => map all endpoint to High queue */ + txqsele = rtl_read_byte(rtlpriv, REG_TEST_USB_TXQS); + if (txqsele & 0x0F) /* /map all endpoint to High queue */ + rtlusb->out_queue_sel = TX_SELE_HQ; + else if (txqsele&0xF0) /* map all endpoint to Low queue */ + rtlusb->out_queue_sel = TX_SELE_LQ; + ep_nums = 1; + break; + default: + break; + } + return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; +} + +static int _ConfigVerNOutEP(struct ieee80211_hw *hw) +{ + u8 ep_cfg; + u8 ep_nums = 0; + + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); + + rtlusb->out_queue_sel = 0; + /* Normal and High queue */ + ep_cfg = rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 1)); + if (ep_cfg & USB_NORMAL_SIE_EP_MASK) { + rtlusb->out_queue_sel |= TX_SELE_HQ; + ep_nums++; + } + if ((ep_cfg >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) { + rtlusb->out_queue_sel |= TX_SELE_NQ; + ep_nums++; + } + /* Low queue */ + ep_cfg = rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 2)); + if (ep_cfg & USB_NORMAL_SIE_EP_MASK) { + rtlusb->out_queue_sel |= TX_SELE_LQ; + ep_nums++; + } + return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; +} + +static void _TwoOutEpMapping(struct ieee80211_hw *hw, bool bIsChipB, + bool bwificfg, struct rtl_ep_map *ep_map) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (bwificfg) { /* for WMM */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "USB Chip-B & WMM Setting.....\n"); + ep_map->ep_mapping[RTL_TXQ_BE] = 2; + ep_map->ep_mapping[RTL_TXQ_BK] = 3; + ep_map->ep_mapping[RTL_TXQ_VI] = 3; + ep_map->ep_mapping[RTL_TXQ_VO] = 2; + ep_map->ep_mapping[RTL_TXQ_MGT] = 2; + ep_map->ep_mapping[RTL_TXQ_BCN] = 2; + ep_map->ep_mapping[RTL_TXQ_HI] = 2; + } else { /* typical setting */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "USB typical Setting.....\n"); + ep_map->ep_mapping[RTL_TXQ_BE] = 3; + ep_map->ep_mapping[RTL_TXQ_BK] = 3; + ep_map->ep_mapping[RTL_TXQ_VI] = 2; + ep_map->ep_mapping[RTL_TXQ_VO] = 2; + ep_map->ep_mapping[RTL_TXQ_MGT] = 2; + ep_map->ep_mapping[RTL_TXQ_BCN] = 2; + ep_map->ep_mapping[RTL_TXQ_HI] = 2; + } +} + +static void _ThreeOutEpMapping(struct ieee80211_hw *hw, bool bwificfg, + struct rtl_ep_map *ep_map) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (bwificfg) { /* for WMM */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "USB 3EP Setting for WMM.....\n"); + ep_map->ep_mapping[RTL_TXQ_BE] = 5; + ep_map->ep_mapping[RTL_TXQ_BK] = 3; + ep_map->ep_mapping[RTL_TXQ_VI] = 3; + ep_map->ep_mapping[RTL_TXQ_VO] = 2; + ep_map->ep_mapping[RTL_TXQ_MGT] = 2; + ep_map->ep_mapping[RTL_TXQ_BCN] = 2; + ep_map->ep_mapping[RTL_TXQ_HI] = 2; + } else { /* typical setting */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "USB 3EP Setting for typical.....\n"); + ep_map->ep_mapping[RTL_TXQ_BE] = 5; + ep_map->ep_mapping[RTL_TXQ_BK] = 5; + ep_map->ep_mapping[RTL_TXQ_VI] = 3; + ep_map->ep_mapping[RTL_TXQ_VO] = 2; + ep_map->ep_mapping[RTL_TXQ_MGT] = 2; + ep_map->ep_mapping[RTL_TXQ_BCN] = 2; + ep_map->ep_mapping[RTL_TXQ_HI] = 2; + } +} + +static void _OneOutEpMapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map) +{ + ep_map->ep_mapping[RTL_TXQ_BE] = 2; + ep_map->ep_mapping[RTL_TXQ_BK] = 2; + ep_map->ep_mapping[RTL_TXQ_VI] = 2; + ep_map->ep_mapping[RTL_TXQ_VO] = 2; + ep_map->ep_mapping[RTL_TXQ_MGT] = 2; + ep_map->ep_mapping[RTL_TXQ_BCN] = 2; + ep_map->ep_mapping[RTL_TXQ_HI] = 2; +} +static int _out_ep_mapping(struct ieee80211_hw *hw) +{ + int err = 0; + bool bIsChipN, bwificfg = false; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); + struct rtl_ep_map *ep_map = &(rtlusb->ep_map); + + bIsChipN = IS_NORMAL_CHIP(rtlhal->version); + switch (rtlusb->out_ep_nums) { + case 2: + _TwoOutEpMapping(hw, bIsChipN, bwificfg, ep_map); + break; + case 3: + /* Test chip doesn't support three out EPs. */ + if (!bIsChipN) { + err = -EINVAL; + goto err_out; + } + _ThreeOutEpMapping(hw, bIsChipN, ep_map); + break; + case 1: + _OneOutEpMapping(hw, ep_map); + break; + default: + err = -EINVAL; + break; + } +err_out: + return err; + +} +/* endpoint mapping */ +int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + int error = 0; + if (likely(IS_NORMAL_CHIP(rtlhal->version))) + error = _ConfigVerNOutEP(hw); + else + error = _ConfigVerTOutEP(hw); + if (error) + goto err_out; + error = _out_ep_mapping(hw); + if (error) + goto err_out; +err_out: + return error; +} + +u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index) +{ + u16 hw_queue_index; + + if (unlikely(ieee80211_is_beacon(fc))) { + hw_queue_index = RTL_TXQ_BCN; + goto out; + } + if (ieee80211_is_mgmt(fc)) { + hw_queue_index = RTL_TXQ_MGT; + goto out; + } + switch (mac80211_queue_index) { + case 0: + hw_queue_index = RTL_TXQ_VO; + break; + case 1: + hw_queue_index = RTL_TXQ_VI; + break; + case 2: + hw_queue_index = RTL_TXQ_BE; + break; + case 3: + hw_queue_index = RTL_TXQ_BK; + break; + default: + hw_queue_index = RTL_TXQ_BE; + RT_ASSERT(false, "QSLT_BE queue, skb_queue:%d\n", + mac80211_queue_index); + break; + } +out: + return hw_queue_index; +} + +static enum rtl_desc_qsel _rtl8192cu_mq_to_descq(struct ieee80211_hw *hw, + __le16 fc, u16 mac80211_queue_index) +{ + enum rtl_desc_qsel qsel; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (unlikely(ieee80211_is_beacon(fc))) { + qsel = QSLT_BEACON; + goto out; + } + if (ieee80211_is_mgmt(fc)) { + qsel = QSLT_MGNT; + goto out; + } + switch (mac80211_queue_index) { + case 0: /* VO */ + qsel = QSLT_VO; + RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, + "VO queue, set qsel = 0x%x\n", QSLT_VO); + break; + case 1: /* VI */ + qsel = QSLT_VI; + RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, + "VI queue, set qsel = 0x%x\n", QSLT_VI); + break; + case 3: /* BK */ + qsel = QSLT_BK; + RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, + "BK queue, set qsel = 0x%x\n", QSLT_BK); + break; + case 2: /* BE */ + default: + qsel = QSLT_BE; + RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, + "BE queue, set qsel = 0x%x\n", QSLT_BE); + break; + } +out: + return qsel; +} + +/* =============================================================== */ + +/*---------------------------------------------------------------------- + * + * Rx handler + * + *---------------------------------------------------------------------- */ +bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb) +{ + struct rx_fwinfo_92c *p_drvinfo; + struct rx_desc_92c *p_desc = (struct rx_desc_92c *)pdesc; + u32 phystatus = GET_RX_DESC_PHY_STATUS(pdesc); + + stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); + stats->rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(pdesc) * + RX_DRV_INFO_SIZE_UNIT; + stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); + stats->icv = (u16) GET_RX_DESC_ICV(pdesc); + stats->crc = (u16) GET_RX_DESC_CRC32(pdesc); + stats->hwerror = (stats->crc | stats->icv); + stats->decrypted = !GET_RX_DESC_SWDEC(pdesc); + stats->rate = (u8) GET_RX_DESC_RX_MCS(pdesc); + stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); + stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); + stats->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1) + && (GET_RX_DESC_FAGGR(pdesc) == 1)); + stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); + stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); + stats->is_ht = (bool)GET_RX_DESC_RX_HT(pdesc); + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + if (GET_RX_DESC_CRC32(pdesc)) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (!GET_RX_DESC_SWDEC(pdesc)) + rx_status->flag |= RX_FLAG_DECRYPTED; + if (GET_RX_DESC_BW(pdesc)) + rx_status->flag |= RX_FLAG_40MHZ; + if (GET_RX_DESC_RX_HT(pdesc)) + rx_status->flag |= RX_FLAG_HT; + rx_status->flag |= RX_FLAG_MACTIME_START; + if (stats->decrypted) + rx_status->flag |= RX_FLAG_DECRYPTED; + rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht, + false, stats->rate); + rx_status->mactime = GET_RX_DESC_TSFL(pdesc); + if (phystatus) { + p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + + stats->rx_bufshift); + rtl92c_translate_rx_signal_stuff(hw, skb, stats, p_desc, + p_drvinfo); + } + /*rx_status->qual = stats->signal; */ + rx_status->signal = stats->recvsignalpower + 10; + return true; +} + +#define RTL_RX_DRV_INFO_UNIT 8 + +static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ieee80211_rx_status *rx_status = + (struct ieee80211_rx_status *)IEEE80211_SKB_RXCB(skb); + u32 skb_len, pkt_len, drvinfo_len; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 *rxdesc; + struct rtl_stats stats = { + .signal = 0, + .rate = 0, + }; + struct rx_fwinfo_92c *p_drvinfo; + bool bv; + __le16 fc; + struct ieee80211_hdr *hdr; + + memset(rx_status, 0, sizeof(*rx_status)); + rxdesc = skb->data; + skb_len = skb->len; + drvinfo_len = (GET_RX_DESC_DRVINFO_SIZE(rxdesc) * RTL_RX_DRV_INFO_UNIT); + pkt_len = GET_RX_DESC_PKT_LEN(rxdesc); + /* TODO: Error recovery. drop this skb or something. */ + WARN_ON(skb_len < (pkt_len + RTL_RX_DESC_SIZE + drvinfo_len)); + stats.length = (u16) GET_RX_DESC_PKT_LEN(rxdesc); + stats.rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(rxdesc) * + RX_DRV_INFO_SIZE_UNIT; + stats.rx_bufshift = (u8) (GET_RX_DESC_SHIFT(rxdesc) & 0x03); + stats.icv = (u16) GET_RX_DESC_ICV(rxdesc); + stats.crc = (u16) GET_RX_DESC_CRC32(rxdesc); + stats.hwerror = (stats.crc | stats.icv); + stats.decrypted = !GET_RX_DESC_SWDEC(rxdesc); + stats.rate = (u8) GET_RX_DESC_RX_MCS(rxdesc); + stats.shortpreamble = (u16) GET_RX_DESC_SPLCP(rxdesc); + stats.isampdu = (bool) ((GET_RX_DESC_PAGGR(rxdesc) == 1) + && (GET_RX_DESC_FAGGR(rxdesc) == 1)); + stats.timestamp_low = GET_RX_DESC_TSFL(rxdesc); + stats.rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(rxdesc); + stats.is_ht = (bool)GET_RX_DESC_RX_HT(rxdesc); + /* TODO: is center_freq changed when doing scan? */ + /* TODO: Shall we add protection or just skip those two step? */ + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + if (GET_RX_DESC_CRC32(rxdesc)) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (!GET_RX_DESC_SWDEC(rxdesc)) + rx_status->flag |= RX_FLAG_DECRYPTED; + if (GET_RX_DESC_BW(rxdesc)) + rx_status->flag |= RX_FLAG_40MHZ; + if (GET_RX_DESC_RX_HT(rxdesc)) + rx_status->flag |= RX_FLAG_HT; + /* Data rate */ + rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats.is_ht, + false, stats.rate); + /* There is a phy status after this rx descriptor. */ + if (GET_RX_DESC_PHY_STATUS(rxdesc)) { + p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE); + rtl92c_translate_rx_signal_stuff(hw, skb, &stats, + (struct rx_desc_92c *)rxdesc, p_drvinfo); + } + skb_pull(skb, (drvinfo_len + RTL_RX_DESC_SIZE)); + hdr = (struct ieee80211_hdr *)(skb->data); + fc = hdr->frame_control; + bv = ieee80211_is_probe_resp(fc); + if (bv) + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Got probe response frame\n"); + if (ieee80211_is_beacon(fc)) + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Got beacon frame\n"); + if (ieee80211_is_data(fc)) + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Got data frame\n"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Fram: fc = 0x%X addr1 = 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X\n", + fc, + (u32)hdr->addr1[0], (u32)hdr->addr1[1], + (u32)hdr->addr1[2], (u32)hdr->addr1[3], + (u32)hdr->addr1[4], (u32)hdr->addr1[5]); + memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); + ieee80211_rx(hw, skb); +} + +void rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb) +{ + _rtl_rx_process(hw, skb); +} + +void rtl8192c_rx_segregate_hdl( + struct ieee80211_hw *hw, + struct sk_buff *skb, + struct sk_buff_head *skb_list) +{ +} + +/*---------------------------------------------------------------------- + * + * Tx handler + * + *---------------------------------------------------------------------- */ +void rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff *skb) +{ +} + +int rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb, + struct sk_buff *skb) +{ + return 0; +} + +struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *hw, + struct sk_buff_head *list) +{ + return skb_dequeue(list); +} + +/*======================================== trx ===============================*/ + +static void _rtl_fill_usb_tx_desc(u8 *txdesc) +{ + SET_TX_DESC_OWN(txdesc, 1); + SET_TX_DESC_LAST_SEG(txdesc, 1); + SET_TX_DESC_FIRST_SEG(txdesc, 1); +} +/** + * For HW recovery information + */ +static void _rtl_tx_desc_checksum(u8 *txdesc) +{ + u16 *ptr = (u16 *)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)); + SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, checksum); +} + +void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *pbd_desc_tx, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 queue_index, + struct rtl_tcb_desc *tcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool defaultadapter = true; + u8 *qc = ieee80211_get_qos_ctl(hdr); + u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + u16 seq_number; + __le16 fc = hdr->frame_control; + u8 rate_flag = info->control.rates[0].flags; + u16 pktlen = skb->len; + enum rtl_desc_qsel fw_qsel = _rtl8192cu_mq_to_descq(hw, fc, + skb_get_queue_mapping(skb)); + u8 *txdesc; + + seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); + txdesc = (u8 *)skb_push(skb, RTL_TX_HEADER_SIZE); + memset(txdesc, 0, RTL_TX_HEADER_SIZE); + SET_TX_DESC_PKT_SIZE(txdesc, pktlen); + SET_TX_DESC_LINIP(txdesc, 0); + SET_TX_DESC_PKT_OFFSET(txdesc, RTL_DUMMY_OFFSET); + SET_TX_DESC_OFFSET(txdesc, RTL_TX_HEADER_SIZE); + SET_TX_DESC_TX_RATE(txdesc, tcb_desc->hw_rate); + if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) + SET_TX_DESC_DATA_SHORTGI(txdesc, 1); + if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && + info->flags & IEEE80211_TX_CTL_AMPDU) { + SET_TX_DESC_AGG_ENABLE(txdesc, 1); + SET_TX_DESC_MAX_AGG_NUM(txdesc, 0x14); + } else { + SET_TX_DESC_AGG_BREAK(txdesc, 1); + } + SET_TX_DESC_SEQ(txdesc, seq_number); + SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable && + !tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable || + tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); + SET_TX_DESC_RTS_RATE(txdesc, tcb_desc->rts_rate); + SET_TX_DESC_RTS_BW(txdesc, 0); + SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc); + SET_TX_DESC_RTS_SHORT(txdesc, + ((tcb_desc->rts_rate <= DESC_RATE54M) ? + (tcb_desc->rts_use_shortpreamble ? 1 : 0) + : (tcb_desc->rts_use_shortgi ? 1 : 0))); + if (mac->bw_40) { + if (rate_flag & IEEE80211_TX_RC_DUP_DATA) { + SET_TX_DESC_DATA_BW(txdesc, 1); + SET_TX_DESC_DATA_SC(txdesc, 3); + } else if(rate_flag & IEEE80211_TX_RC_40_MHZ_WIDTH){ + SET_TX_DESC_DATA_BW(txdesc, 1); + SET_TX_DESC_DATA_SC(txdesc, mac->cur_40_prime_sc); + } else { + SET_TX_DESC_DATA_BW(txdesc, 0); + SET_TX_DESC_DATA_SC(txdesc, 0); + } + } else { + SET_TX_DESC_DATA_BW(txdesc, 0); + SET_TX_DESC_DATA_SC(txdesc, 0); + } + rcu_read_lock(); + sta = ieee80211_find_sta(mac->vif, mac->bssid); + if (sta) { + u8 ampdu_density = sta->ht_cap.ampdu_density; + SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density); + } + rcu_read_unlock(); + if (info->control.hw_key) { + struct ieee80211_key_conf *keyconf = info->control.hw_key; + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + SET_TX_DESC_SEC_TYPE(txdesc, 0x1); + break; + case WLAN_CIPHER_SUITE_CCMP: + SET_TX_DESC_SEC_TYPE(txdesc, 0x3); + break; + default: + SET_TX_DESC_SEC_TYPE(txdesc, 0x0); + break; + } + } + SET_TX_DESC_PKT_ID(txdesc, 0); + SET_TX_DESC_QUEUE_SEL(txdesc, fw_qsel); + SET_TX_DESC_DATA_RATE_FB_LIMIT(txdesc, 0x1F); + SET_TX_DESC_RTS_RATE_FB_LIMIT(txdesc, 0xF); + SET_TX_DESC_DISABLE_FB(txdesc, 0); + SET_TX_DESC_USE_RATE(txdesc, tcb_desc->use_driver_rate ? 1 : 0); + if (ieee80211_is_data_qos(fc)) { + if (mac->rdg_en) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "Enable RDG function\n"); + SET_TX_DESC_RDG_ENABLE(txdesc, 1); + SET_TX_DESC_HTC(txdesc, 1); + } + } + if (rtlpriv->dm.useramask) { + SET_TX_DESC_RATE_ID(txdesc, tcb_desc->ratr_index); + SET_TX_DESC_MACID(txdesc, tcb_desc->mac_id); + } else { + SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc->ratr_index); + SET_TX_DESC_MACID(txdesc, tcb_desc->ratr_index); + } + if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && + ppsc->fwctrl_lps) { + SET_TX_DESC_HWSEQ_EN(txdesc, 1); + SET_TX_DESC_PKT_ID(txdesc, 8); + if (!defaultadapter) + SET_TX_DESC_QOS(txdesc, 1); + } + if (ieee80211_has_morefrags(fc)) + SET_TX_DESC_MORE_FRAG(txdesc, 1); + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) + SET_TX_DESC_BMC(txdesc, 1); + _rtl_fill_usb_tx_desc(txdesc); + _rtl_tx_desc_checksum(txdesc); + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "==>\n"); +} + +void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, + u32 buffer_len, bool bIsPsPoll) +{ + /* Clear all status */ + memset(pDesc, 0, RTL_TX_HEADER_SIZE); + SET_TX_DESC_FIRST_SEG(pDesc, 1); /* bFirstSeg; */ + SET_TX_DESC_LAST_SEG(pDesc, 1); /* bLastSeg; */ + SET_TX_DESC_OFFSET(pDesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */ + SET_TX_DESC_PKT_SIZE(pDesc, buffer_len); /* Buffer size + command hdr */ + SET_TX_DESC_QUEUE_SEL(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */ + /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error + * vlaue by Hw. */ + if (bIsPsPoll) { + SET_TX_DESC_NAV_USE_HDR(pDesc, 1); + } else { + SET_TX_DESC_HWSEQ_EN(pDesc, 1); /* Hw set sequence number */ + SET_TX_DESC_PKT_ID(pDesc, 0x100); /* set bit3 to 1. */ + } + SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */ + SET_TX_DESC_OWN(pDesc, 1); + SET_TX_DESC_TX_RATE(pDesc, DESC_RATE1M); + _rtl_tx_desc_checksum(pDesc); +} + +void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, + u8 *pdesc, bool firstseg, + bool lastseg, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 fw_queue = QSLT_BEACON; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + __le16 fc = hdr->frame_control; + + memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE); + if (firstseg) + SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); + SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M); + SET_TX_DESC_SEQ(pdesc, 0); + SET_TX_DESC_LINIP(pdesc, 0); + SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + SET_TX_DESC_RATE_ID(pdesc, 7); + SET_TX_DESC_MACID(pdesc, 0); + SET_TX_DESC_OWN(pdesc, 1); + SET_TX_DESC_PKT_SIZE(pdesc, (u16)skb->len); + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + SET_TX_DESC_OFFSET(pdesc, 0x20); + SET_TX_DESC_USE_RATE(pdesc, 1); + if (!ieee80211_is_data_qos(fc)) { + SET_TX_DESC_HWSEQ_EN(pdesc, 1); + SET_TX_DESC_PKT_ID(pdesc, 8); + } + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C Tx Cmd Content", + pdesc, RTL_TX_DESC_SIZE); +} + +bool rtl92cu_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + return true; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h new file mode 100644 index 000000000000..fd8051dcd98a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h @@ -0,0 +1,435 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CU_TRX_H__ +#define __RTL92CU_TRX_H__ + +#define RTL92C_USB_BULK_IN_NUM 1 +#define RTL92C_NUM_RX_URBS 8 +#define RTL92C_NUM_TX_URBS 32 + +#define RTL92C_SIZE_MAX_RX_BUFFER 15360 /* 8192 */ +#define RX_DRV_INFO_SIZE_UNIT 8 + +#define RTL_AGG_ON 1 + +enum usb_rx_agg_mode { + USB_RX_AGG_DISABLE, + USB_RX_AGG_DMA, + USB_RX_AGG_USB, + USB_RX_AGG_DMA_USB +}; + +#define TX_SELE_HQ BIT(0) /* High Queue */ +#define TX_SELE_LQ BIT(1) /* Low Queue */ +#define TX_SELE_NQ BIT(2) /* Normal Queue */ + +#define RTL_USB_TX_AGG_NUM_DESC 5 + +#define RTL_USB_RX_AGG_PAGE_NUM 4 +#define RTL_USB_RX_AGG_PAGE_TIMEOUT 3 + +#define RTL_USB_RX_AGG_BLOCK_NUM 5 +#define RTL_USB_RX_AGG_BLOCK_TIMEOUT 3 + +/*======================== rx status =========================================*/ + +struct rx_drv_info_92c { + /* + * Driver info contain PHY status and other variabel size info + * PHY Status content as below + */ + + /* DWORD 0 */ + u8 gain_trsw[4]; + + /* DWORD 1 */ + u8 pwdb_all; + u8 cfosho[4]; + + /* DWORD 2 */ + u8 cfotail[4]; + + /* DWORD 3 */ + s8 rxevm[2]; + s8 rxsnr[4]; + + /* DWORD 4 */ + u8 pdsnr[2]; + + /* DWORD 5 */ + u8 csi_current[2]; + u8 csi_target[2]; + + /* DWORD 6 */ + u8 sigevm; + u8 max_ex_pwr; + u8 ex_intf_flag:1; + u8 sgi_en:1; + u8 rxsc:2; + 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) +#define GET_RX_DESC_CRC32(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc, 14, 1) +#define GET_RX_DESC_ICV(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc, 15, 1) +#define GET_RX_DESC_DRVINFO_SIZE(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc, 16, 4) +#define GET_RX_DESC_SECURITY(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc, 20, 3) +#define GET_RX_DESC_QOS(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc, 23, 1) +#define GET_RX_DESC_SHIFT(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc, 24, 2) +#define GET_RX_DESC_PHY_STATUS(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc, 26, 1) +#define GET_RX_DESC_SWDEC(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc, 27, 1) +#define GET_RX_DESC_LAST_SEG(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc, 28, 1) +#define GET_RX_DESC_FIRST_SEG(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc, 29, 1) +#define GET_RX_DESC_EOR(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc, 30, 1) +#define GET_RX_DESC_OWN(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc, 31, 1) + +/* DWORD 1 */ +#define GET_RX_DESC_MACID(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 0, 5) +#define GET_RX_DESC_TID(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 5, 4) +#define GET_RX_DESC_PAGGR(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 14, 1) +#define GET_RX_DESC_FAGGR(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 15, 1) +#define GET_RX_DESC_A1_FIT(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 16, 4) +#define GET_RX_DESC_A2_FIT(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 20, 4) +#define GET_RX_DESC_PAM(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 24, 1) +#define GET_RX_DESC_PWR(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 25, 1) +#define GET_RX_DESC_MORE_DATA(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 26, 1) +#define GET_RX_DESC_MORE_FRAG(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 27, 1) +#define GET_RX_DESC_TYPE(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 28, 2) +#define GET_RX_DESC_MC(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 30, 1) +#define GET_RX_DESC_BC(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+4, 31, 1) + +/* DWORD 2 */ +#define GET_RX_DESC_SEQ(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+8, 0, 12) +#define GET_RX_DESC_FRAG(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+8, 12, 4) +#define GET_RX_DESC_USB_AGG_PKTNUM(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+8, 16, 8) +#define GET_RX_DESC_NEXT_IND(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+8, 30, 1) + +/* DWORD 3 */ +#define GET_RX_DESC_RX_MCS(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+12, 0, 6) +#define GET_RX_DESC_RX_HT(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+12, 6, 1) +#define GET_RX_DESC_AMSDU(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+12, 7, 1) +#define GET_RX_DESC_SPLCP(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+12, 8, 1) +#define GET_RX_DESC_BW(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+12, 9, 1) +#define GET_RX_DESC_HTC(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+12, 10, 1) +#define GET_RX_DESC_TCP_CHK_RPT(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+12, 11, 1) +#define GET_RX_DESC_IP_CHK_RPT(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+12, 12, 1) +#define GET_RX_DESC_TCP_CHK_VALID(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+12, 13, 1) +#define GET_RX_DESC_HWPC_ERR(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+12, 14, 1) +#define GET_RX_DESC_HWPC_IND(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+12, 15, 1) +#define GET_RX_DESC_IV0(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+12, 16, 16) + +/* DWORD 4 */ +#define GET_RX_DESC_IV1(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+16, 0, 32) + +/* DWORD 5 */ +#define GET_RX_DESC_TSFL(__rxdesc) \ + SHIFT_AND_MASK_LE(__rxdesc+20, 0, 32) + +/*======================= tx desc ============================================*/ + +/* macros to set various fields in TX descriptor */ + +/* Dword 0 */ +#define SET_TX_DESC_PKT_SIZE(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc, 0, 16, __value) +#define SET_TX_DESC_OFFSET(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc, 16, 8, __value) +#define SET_TX_DESC_BMC(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc, 24, 1, __value) +#define SET_TX_DESC_HTC(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc, 25, 1, __value) +#define SET_TX_DESC_LAST_SEG(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc, 26, 1, __value) +#define SET_TX_DESC_FIRST_SEG(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc, 27, 1, __value) +#define SET_TX_DESC_LINIP(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc, 28, 1, __value) +#define SET_TX_DESC_NO_ACM(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc, 29, 1, __value) +#define SET_TX_DESC_GF(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc, 30, 1, __value) +#define SET_TX_DESC_OWN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc, 31, 1, __value) + + +/* Dword 1 */ +#define SET_TX_DESC_MACID(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 0, 5, __value) +#define SET_TX_DESC_AGG_ENABLE(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 5, 1, __value) +#define SET_TX_DESC_AGG_BREAK(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 6, 1, __value) +#define SET_TX_DESC_RDG_ENABLE(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 7, 1, __value) +#define SET_TX_DESC_QUEUE_SEL(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 8, 5, __value) +#define SET_TX_DESC_RDG_NAV_EXT(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 13, 1, __value) +#define SET_TX_DESC_LSIG_TXOP_EN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 14, 1, __value) +#define SET_TX_DESC_PIFS(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 15, 1, __value) +#define SET_TX_DESC_RATE_ID(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 16, 4, __value) +#define SET_TX_DESC_RA_BRSR_ID(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 16, 4, __value) +#define SET_TX_DESC_NAV_USE_HDR(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 20, 1, __value) +#define SET_TX_DESC_EN_DESC_ID(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 21, 1, __value) +#define SET_TX_DESC_SEC_TYPE(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 22, 2, __value) +#define SET_TX_DESC_PKT_OFFSET(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+4, 26, 5, __value) + +/* Dword 2 */ +#define SET_TX_DESC_RTS_RC(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+8, 0, 6, __value) +#define SET_TX_DESC_DATA_RC(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+8, 6, 6, __value) +#define SET_TX_DESC_BAR_RTY_TH(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+8, 14, 2, __value) +#define SET_TX_DESC_MORE_FRAG(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+8, 17, 1, __value) +#define SET_TX_DESC_RAW(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+8, 18, 1, __value) +#define SET_TX_DESC_CCX(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+8, 19, 1, __value) +#define SET_TX_DESC_AMPDU_DENSITY(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+8, 20, 3, __value) +#define SET_TX_DESC_ANTSEL_A(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+8, 24, 1, __value) +#define SET_TX_DESC_ANTSEL_B(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+8, 25, 1, __value) +#define SET_TX_DESC_TX_ANT_CCK(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+8, 26, 2, __value) +#define SET_TX_DESC_TX_ANTL(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+8, 28, 2, __value) +#define SET_TX_DESC_TX_ANT_HT(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__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) +#define SET_TX_DESC_TAIL_PAGE(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+12, 8, 8, __value) +#define SET_TX_DESC_SEQ(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+12, 16, 12, __value) +#define SET_TX_DESC_PKT_ID(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+12, 28, 4, __value) + +/* Dword 4 */ +#define SET_TX_DESC_RTS_RATE(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 0, 5, __value) +#define SET_TX_DESC_AP_DCFE(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 5, 1, __value) +#define SET_TX_DESC_QOS(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 6, 1, __value) +#define SET_TX_DESC_HWSEQ_EN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 7, 1, __value) +#define SET_TX_DESC_USE_RATE(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 8, 1, __value) +#define SET_TX_DESC_DISABLE_RTS_FB(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 9, 1, __value) +#define SET_TX_DESC_DISABLE_FB(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 10, 1, __value) +#define SET_TX_DESC_CTS2SELF(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 11, 1, __value) +#define SET_TX_DESC_RTS_ENABLE(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 12, 1, __value) +#define SET_TX_DESC_HW_RTS_ENABLE(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 13, 1, __value) +#define SET_TX_DESC_WAIT_DCTS(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 18, 1, __value) +#define SET_TX_DESC_CTS2AP_EN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 19, 1, __value) +#define SET_TX_DESC_DATA_SC(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 20, 2, __value) +#define SET_TX_DESC_DATA_STBC(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 22, 2, __value) +#define SET_TX_DESC_DATA_SHORT(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 24, 1, __value) +#define SET_TX_DESC_DATA_BW(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 25, 1, __value) +#define SET_TX_DESC_RTS_SHORT(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 26, 1, __value) +#define SET_TX_DESC_RTS_BW(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 27, 1, __value) +#define SET_TX_DESC_RTS_SC(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 28, 2, __value) +#define SET_TX_DESC_RTS_STBC(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+16, 30, 2, __value) + +/* Dword 5 */ +#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val) +#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val) +#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+20, 8, 5, __value) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+20, 13, 4, __value) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+20, 17, 1, __value) +#define SET_TX_DESC_DATA_RETRY_LIMIT(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+20, 18, 6, __value) +#define SET_TX_DESC_USB_TXAGG_NUM(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+20, 24, 8, __value) + +/* Dword 6 */ +#define SET_TX_DESC_TXAGC_A(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+24, 0, 5, __value) +#define SET_TX_DESC_TXAGC_B(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+24, 5, 5, __value) +#define SET_TX_DESC_USB_MAX_LEN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+24, 10, 1, __value) +#define SET_TX_DESC_MAX_AGG_NUM(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+24, 11, 5, __value) +#define SET_TX_DESC_MCSG1_MAX_LEN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+24, 16, 4, __value) +#define SET_TX_DESC_MCSG2_MAX_LEN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+24, 20, 4, __value) +#define SET_TX_DESC_MCSG3_MAX_LEN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+24, 24, 4, __value) +#define SET_TX_DESC_MCSG7_MAX_LEN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__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) +#define SET_TX_DESC_MCSG4_MAX_LEN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+28, 16, 4, __value) +#define SET_TX_DESC_MCSG5_MAX_LEN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+28, 20, 4, __value) +#define SET_TX_DESC_MCSG6_MAX_LEN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+28, 24, 4, __value) +#define SET_TX_DESC_MCSG15_MAX_LEN(__txdesc, __value) \ + SET_BITS_OFFSET_LE(__txdesc+28, 28, 4, __value) + + +int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw); +u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index); +bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, + u8 *p_desc, struct sk_buff *skb); +void rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb); +void rtl8192c_rx_segregate_hdl(struct ieee80211_hw *, struct sk_buff *, + struct sk_buff_head *); +void rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff *skb); +int rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb, + struct sk_buff *skb); +struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *, + struct sk_buff_head *); +void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *pbd_desc_tx, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 queue_index, + struct rtl_tcb_desc *tcb_desc); +void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, + u32 buffer_len, bool bIsPsPoll); +void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, + u8 *pdesc, bool b_firstseg, + bool b_lastseg, struct sk_buff *skb); +bool rtl92cu_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/Makefile new file mode 100644 index 000000000000..e3213c8264b6 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/Makefile @@ -0,0 +1,14 @@ +rtl8192de-objs := \ + dm.o \ + fw.o \ + hw.o \ + led.o \ + phy.o \ + rf.o \ + sw.o \ + table.o \ + trx.o + +obj-$(CONFIG_RTL8192DE) += rtl8192de.o + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h new file mode 100644 index 000000000000..0a443ed17cf4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/def.h @@ -0,0 +1,232 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92D_DEF_H__ +#define __RTL92D_DEF_H__ + +/* Min Spacing related settings. */ +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define RF6052_MAX_TX_PWR 0x3F +#define RF6052_MAX_PATH 2 + +#define PHY_RSSI_SLID_WIN_MAX 100 +#define PHY_LINKQUALITY_SLID_WIN_MAX 20 +#define PHY_BEACON_RSSI_SLID_WIN_MAX 10 + +#define RT_AC_INT_MASKS (IMR_VIDOK | IMR_VODOK | IMR_BEDOK|IMR_BKDOK) + +#define RX_SMOOTH_FACTOR 20 + +#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 +#define HAL_PRIME_CHNL_OFFSET_LOWER 1 +#define HAL_PRIME_CHNL_OFFSET_UPPER 2 + +#define RX_MPDU_QUEUE 0 +#define RX_CMD_QUEUE 1 + +#define C2H_RX_CMD_HDR_LEN 8 +#define GET_C2H_CMD_CMD_LEN(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 0, 16) +#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 16, 8) +#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 24, 7) +#define GET_C2H_CMD_CONTINUE(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 31, 1) +#define GET_C2H_CMD_CONTENT(__prxhdr) \ + ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) + +#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) +#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) +#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) + +enum version_8192d { + VERSION_TEST_CHIP_88C = 0x0000, + VERSION_TEST_CHIP_92C = 0x0020, + VERSION_TEST_UMC_CHIP_8723 = 0x0081, + VERSION_NORMAL_TSMC_CHIP_88C = 0x0008, + VERSION_NORMAL_TSMC_CHIP_92C = 0x0028, + VERSION_NORMAL_TSMC_CHIP_92C_1T2R = 0x0018, + VERSION_NORMAL_UMC_CHIP_88C_A_CUT = 0x0088, + VERSION_NORMAL_UMC_CHIP_92C_A_CUT = 0x00a8, + VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT = 0x0098, + VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT = 0x0089, + VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT = 0x1089, + VERSION_NORMAL_UMC_CHIP_88C_B_CUT = 0x1088, + VERSION_NORMAL_UMC_CHIP_92C_B_CUT = 0x10a8, + VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT = 0x1090, + VERSION_TEST_CHIP_92D_SINGLEPHY = 0x0022, + VERSION_TEST_CHIP_92D_DUALPHY = 0x0002, + VERSION_NORMAL_CHIP_92D_SINGLEPHY = 0x002a, + VERSION_NORMAL_CHIP_92D_DUALPHY = 0x000a, + VERSION_NORMAL_CHIP_92D_C_CUT_SINGLEPHY = 0x202a, + VERSION_NORMAL_CHIP_92D_C_CUT_DUALPHY = 0x200a, + VERSION_NORMAL_CHIP_92D_D_CUT_SINGLEPHY = 0x302a, + VERSION_NORMAL_CHIP_92D_D_CUT_DUALPHY = 0x300a, + VERSION_NORMAL_CHIP_92D_E_CUT_SINGLEPHY = 0x402a, + VERSION_NORMAL_CHIP_92D_E_CUT_DUALPHY = 0x400a, +}; + +/* for 92D */ +#define CHIP_92D_SINGLEPHY BIT(9) + +/* Chip specific */ +#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) +#define CHIP_BONDING_92C_1T2R 0x1 +#define CHIP_BONDING_88C_USB_MCARD 0x2 +#define CHIP_BONDING_88C_USB_HP 0x1 + +/* [15:12] IC version(CUT): A-cut=0, B-cut=1, C-cut=2, D-cut=3 */ +/* [7] Manufacturer: TSMC=0, UMC=1 */ +/* [6:4] RF type: 1T1R=0, 1T2R=1, 2T2R=2 */ +/* [3] Chip type: TEST=0, NORMAL=1 */ +/* [2:0] IC type: 81xxC=0, 8723=1, 92D=2 */ +#define CHIP_8723 BIT(0) +#define CHIP_92D BIT(1) +#define NORMAL_CHIP BIT(3) +#define RF_TYPE_1T1R (~(BIT(4)|BIT(5)|BIT(6))) +#define RF_TYPE_1T2R BIT(4) +#define RF_TYPE_2T2R BIT(5) +#define CHIP_VENDOR_UMC BIT(7) +#define CHIP_92D_B_CUT BIT(12) +#define CHIP_92D_C_CUT BIT(13) +#define CHIP_92D_D_CUT (BIT(13)|BIT(12)) +#define CHIP_92D_E_CUT BIT(14) + +/* MASK */ +#define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2)) +#define CHIP_TYPE_MASK BIT(3) +#define RF_TYPE_MASK (BIT(4)|BIT(5)|BIT(6)) +#define MANUFACTUER_MASK BIT(7) +#define ROM_VERSION_MASK (BIT(11)|BIT(10)|BIT(9)|BIT(8)) +#define CUT_VERSION_MASK (BIT(15)|BIT(14)|BIT(13)|BIT(12)) + + +/* Get element */ +#define GET_CVID_IC_TYPE(version) ((version) & IC_TYPE_MASK) +#define GET_CVID_CHIP_TYPE(version) ((version) & CHIP_TYPE_MASK) +#define GET_CVID_RF_TYPE(version) ((version) & RF_TYPE_MASK) +#define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK) +#define GET_CVID_ROM_VERSION(version) ((version) & ROM_VERSION_MASK) +#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK) + +#define IS_1T1R(version) ((GET_CVID_RF_TYPE(version)) ? \ + false : true) +#define IS_1T2R(version) ((GET_CVID_RF_TYPE(version) == \ + RF_TYPE_1T2R) ? true : false) +#define IS_2T2R(version) ((GET_CVID_RF_TYPE(version) == \ + RF_TYPE_2T2R) ? true : false) + +#define IS_92D_SINGLEPHY(version) ((IS_92D(version)) ? \ + (IS_2T2R(version) ? true : false) : false) +#define IS_92D(version) ((GET_CVID_IC_TYPE(version) == \ + CHIP_92D) ? true : false) +#define IS_92D_C_CUT(version) ((IS_92D(version)) ? \ + ((GET_CVID_CUT_VERSION(version) == \ + CHIP_92D_C_CUT) ? true : false) : false) +#define IS_92D_D_CUT(version) ((IS_92D(version)) ? \ + ((GET_CVID_CUT_VERSION(version) == \ + CHIP_92D_D_CUT) ? true : false) : false) +#define IS_92D_E_CUT(version) ((IS_92D(version)) ? \ + ((GET_CVID_CUT_VERSION(version) == \ + CHIP_92D_E_CUT) ? true : false) : false) + +enum rf_optype { + RF_OP_BY_SW_3WIRE = 0, + RF_OP_BY_FW, + RF_OP_MAX +}; + +enum rtl_desc_qsel { + QSLT_BK = 0x2, + QSLT_BE = 0x0, + QSLT_VI = 0x5, + QSLT_VO = 0x7, + QSLT_BEACON = 0x10, + QSLT_HIGH = 0x11, + QSLT_MGNT = 0x12, + QSLT_CMD = 0x13, +}; + +enum channel_plan { + CHPL_FCC = 0, + CHPL_IC = 1, + CHPL_ETSI = 2, + CHPL_SPAIN = 3, + CHPL_FRANCE = 4, + CHPL_MKK = 5, + CHPL_MKK1 = 6, + CHPL_ISRAEL = 7, + CHPL_TELEC = 8, + CHPL_GLOBAL = 9, + CHPL_WORLD = 10, +}; + +struct phy_sts_cck_8192d { + u8 adc_pwdb_X[4]; + u8 sq_rpt; + u8 cck_agc_rpt; +}; + +struct h2c_cmd_8192c { + u8 element_id; + u32 cmd_len; + u8 *p_cmdbuffer; +}; + +struct txpower_info { + u8 cck_index[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; + u8 ht40_1sindex[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; + u8 ht40_2sindexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; + u8 ht20indexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; + u8 ofdmindexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; + u8 ht40maxoffset[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; + u8 ht20maxoffset[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; + u8 tssi_a[3]; /* 5GL/5GM/5GH */ + u8 tssi_b[3]; +}; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c new file mode 100644 index 000000000000..7c1db7e7572d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c @@ -0,0 +1,1316 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../base.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" + +#define UNDEC_SM_PWDB entry_min_undec_sm_pwdb + +static const u32 ofdmswing_table[OFDM_TABLE_SIZE_92D] = { + 0x7f8001fe, /* 0, +6.0dB */ + 0x788001e2, /* 1, +5.5dB */ + 0x71c001c7, /* 2, +5.0dB */ + 0x6b8001ae, /* 3, +4.5dB */ + 0x65400195, /* 4, +4.0dB */ + 0x5fc0017f, /* 5, +3.5dB */ + 0x5a400169, /* 6, +3.0dB */ + 0x55400155, /* 7, +2.5dB */ + 0x50800142, /* 8, +2.0dB */ + 0x4c000130, /* 9, +1.5dB */ + 0x47c0011f, /* 10, +1.0dB */ + 0x43c0010f, /* 11, +0.5dB */ + 0x40000100, /* 12, +0dB */ + 0x3c8000f2, /* 13, -0.5dB */ + 0x390000e4, /* 14, -1.0dB */ + 0x35c000d7, /* 15, -1.5dB */ + 0x32c000cb, /* 16, -2.0dB */ + 0x300000c0, /* 17, -2.5dB */ + 0x2d4000b5, /* 18, -3.0dB */ + 0x2ac000ab, /* 19, -3.5dB */ + 0x288000a2, /* 20, -4.0dB */ + 0x26000098, /* 21, -4.5dB */ + 0x24000090, /* 22, -5.0dB */ + 0x22000088, /* 23, -5.5dB */ + 0x20000080, /* 24, -6.0dB */ + 0x1e400079, /* 25, -6.5dB */ + 0x1c800072, /* 26, -7.0dB */ + 0x1b00006c, /* 27. -7.5dB */ + 0x19800066, /* 28, -8.0dB */ + 0x18000060, /* 29, -8.5dB */ + 0x16c0005b, /* 30, -9.0dB */ + 0x15800056, /* 31, -9.5dB */ + 0x14400051, /* 32, -10.0dB */ + 0x1300004c, /* 33, -10.5dB */ + 0x12000048, /* 34, -11.0dB */ + 0x11000044, /* 35, -11.5dB */ + 0x10000040, /* 36, -12.0dB */ + 0x0f00003c, /* 37, -12.5dB */ + 0x0e400039, /* 38, -13.0dB */ + 0x0d800036, /* 39, -13.5dB */ + 0x0cc00033, /* 40, -14.0dB */ + 0x0c000030, /* 41, -14.5dB */ + 0x0b40002d, /* 42, -15.0dB */ +}; + +static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ + {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ + {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ + {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ + {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ + {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ + {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ + {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ + {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ + {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ + {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */ + {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */ + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */ + {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */ + {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */ + {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */ + {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */ + {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */ + {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */ + {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */ + {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */ + {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */ + {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */ +}; + +static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */ + {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */ + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */ + {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */ + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */ + {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */ + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */ + {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */ + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */ + {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */ + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */ + {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */ + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */ + {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */ + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */ + {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */ + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ + {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */ + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */ + {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */ + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */ + {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */ + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */ + {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */ + {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */ + {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */ + {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */ + {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */ + {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */ + {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */ + {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */ + {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */ + {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */ +}; + +static void rtl92d_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) +{ + u32 ret_value; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); + unsigned long flag = 0; + + /* hold ofdm counter */ + rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1); /* hold page C counter */ + rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1); /*hold page D counter */ + + ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD); + falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff); + falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16); + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); + falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); + falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); + falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); + falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); + falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_fast_fsync_fail + + falsealm_cnt->cnt_sb_search_fail; + + if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) { + /* hold cck counter */ + rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); + ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); + falsealm_cnt->cnt_cck_fail = ret_value; + ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3); + falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; + rtl92d_release_cckandrw_pagea_ctl(hw, &flag); + } else { + falsealm_cnt->cnt_cck_fail = 0; + } + + /* reset false alarm counter registers */ + falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail + + falsealm_cnt->cnt_sb_search_fail + + falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_cck_fail; + + rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1); + /* update ofdm counter */ + rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0); + /* update page C counter */ + rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0); + /* update page D counter */ + rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0); + if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) { + /* reset cck counter */ + rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0); + /* enable cck counter */ + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2); + rtl92d_release_cckandrw_pagea_ctl(hw, &flag); + } + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Cnt_Fast_Fsync_fail = %x, Cnt_SB_Search_fail = %x\n", + falsealm_cnt->cnt_fast_fsync_fail, + falsealm_cnt->cnt_sb_search_fail); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Cnt_Parity_Fail = %x, Cnt_Rate_Illegal = %x, Cnt_Crc8_fail = %x, Cnt_Mcs_fail = %x\n", + falsealm_cnt->cnt_parity_fail, + falsealm_cnt->cnt_rate_illegal, + falsealm_cnt->cnt_crc8_fail, + falsealm_cnt->cnt_mcs_fail); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Cnt_Ofdm_fail = %x, Cnt_Cck_fail = %x, Cnt_all = %x\n", + falsealm_cnt->cnt_ofdm_fail, + falsealm_cnt->cnt_cck_fail, + falsealm_cnt->cnt_all); +} + +static void rtl92d_dm_find_minimum_rssi(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *de_digtable = &rtlpriv->dm_digtable; + struct rtl_mac *mac = rtl_mac(rtlpriv); + + /* Determine the minimum RSSI */ + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.UNDEC_SM_PWDB == 0)) { + de_digtable->min_undec_pwdb_for_dm = 0; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "Not connected to any\n"); + } + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + de_digtable->min_undec_pwdb_for_dm = + rtlpriv->dm.UNDEC_SM_PWDB; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "AP Client PWDB = 0x%lx\n", + rtlpriv->dm.UNDEC_SM_PWDB); + } else { + de_digtable->min_undec_pwdb_for_dm = + rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "STA Default Port PWDB = 0x%x\n", + de_digtable->min_undec_pwdb_for_dm); + } + } else { + de_digtable->min_undec_pwdb_for_dm = rtlpriv->dm.UNDEC_SM_PWDB; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "AP Ext Port or disconnect PWDB = 0x%x\n", + de_digtable->min_undec_pwdb_for_dm); + } + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n", + de_digtable->min_undec_pwdb_for_dm); +} + +static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *de_digtable = &rtlpriv->dm_digtable; + unsigned long flag = 0; + + if (de_digtable->cursta_cstate == DIG_STA_CONNECT) { + if (de_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { + if (de_digtable->min_undec_pwdb_for_dm <= 25) + de_digtable->cur_cck_pd_state = + CCK_PD_STAGE_LOWRSSI; + else + de_digtable->cur_cck_pd_state = + CCK_PD_STAGE_HIGHRSSI; + } else { + if (de_digtable->min_undec_pwdb_for_dm <= 20) + de_digtable->cur_cck_pd_state = + CCK_PD_STAGE_LOWRSSI; + else + de_digtable->cur_cck_pd_state = + CCK_PD_STAGE_HIGHRSSI; + } + } else { + de_digtable->cur_cck_pd_state = CCK_PD_STAGE_LOWRSSI; + } + if (de_digtable->pre_cck_pd_state != de_digtable->cur_cck_pd_state) { + if (de_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { + rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83); + rtl92d_release_cckandrw_pagea_ctl(hw, &flag); + } else { + rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); + rtl92d_release_cckandrw_pagea_ctl(hw, &flag); + } + de_digtable->pre_cck_pd_state = de_digtable->cur_cck_pd_state; + } + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "CurSTAConnectState=%s\n", + de_digtable->cursta_cstate == DIG_STA_CONNECT ? + "DIG_STA_CONNECT " : "DIG_STA_DISCONNECT"); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "CCKPDStage=%s\n", + de_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI ? + "Low RSSI " : "High RSSI "); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "is92d single phy =%x\n", + IS_92D_SINGLEPHY(rtlpriv->rtlhal.version)); + +} + +void rtl92d_dm_write_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *de_digtable = &rtlpriv->dm_digtable; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n", + de_digtable->cur_igvalue, de_digtable->pre_igvalue, + de_digtable->back_val); + if (de_digtable->dig_enable_flag == false) { + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "DIG is disabled\n"); + de_digtable->pre_igvalue = 0x17; + return; + } + if (de_digtable->pre_igvalue != de_digtable->cur_igvalue) { + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, + de_digtable->cur_igvalue); + rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, + de_digtable->cur_igvalue); + de_digtable->pre_igvalue = de_digtable->cur_igvalue; + } +} + +static void rtl92d_early_mode_enabled(struct rtl_priv *rtlpriv) +{ + struct dig_t *de_digtable = &rtlpriv->dm_digtable; + + if ((rtlpriv->mac80211.link_state >= MAC80211_LINKED) && + (rtlpriv->mac80211.vendor == PEER_CISCO)) { + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "IOT_PEER = CISCO\n"); + if (de_digtable->last_min_undec_pwdb_for_dm >= 50 + && de_digtable->min_undec_pwdb_for_dm < 50) { + rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x00); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Early Mode Off\n"); + } else if (de_digtable->last_min_undec_pwdb_for_dm <= 55 && + de_digtable->min_undec_pwdb_for_dm > 55) { + rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Early Mode On\n"); + } + } else if (!(rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL) & 0xf)) { + rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "Early Mode On\n"); + } +} + +static void rtl92d_dm_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *de_digtable = &rtlpriv->dm_digtable; + u8 value_igi = de_digtable->cur_igvalue; + struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "==>\n"); + if (rtlpriv->rtlhal.earlymode_enable) { + rtl92d_early_mode_enabled(rtlpriv); + de_digtable->last_min_undec_pwdb_for_dm = + de_digtable->min_undec_pwdb_for_dm; + } + if (!rtlpriv->dm.dm_initialgain_enable) + return; + + /* because we will send data pkt when scanning + * this will cause some ap like gear-3700 wep TP + * lower if we return here, this is the diff of + * mac80211 driver vs ieee80211 driver */ + /* if (rtlpriv->mac80211.act_scanning) + * return; */ + + /* Not STA mode return tmp */ + if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) + return; + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "progress\n"); + /* Decide the current status and if modify initial gain or not */ + if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) + de_digtable->cursta_cstate = DIG_STA_CONNECT; + else + de_digtable->cursta_cstate = DIG_STA_DISCONNECT; + + /* adjust initial gain according to false alarm counter */ + if (falsealm_cnt->cnt_all < DM_DIG_FA_TH0) + value_igi--; + else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH1) + value_igi += 0; + else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH2) + value_igi++; + else if (falsealm_cnt->cnt_all >= DM_DIG_FA_TH2) + value_igi += 2; + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "dm_DIG() Before: large_fa_hit=%d, forbidden_igi=%x\n", + de_digtable->large_fa_hit, de_digtable->forbidden_igi); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "dm_DIG() Before: Recover_cnt=%d, rx_gain_min=%x\n", + de_digtable->recover_cnt, de_digtable->rx_gain_min); + + /* deal with abnormally large false alarm */ + if (falsealm_cnt->cnt_all > 10000) { + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "dm_DIG(): Abnormally false alarm case\n"); + + de_digtable->large_fa_hit++; + if (de_digtable->forbidden_igi < de_digtable->cur_igvalue) { + de_digtable->forbidden_igi = de_digtable->cur_igvalue; + de_digtable->large_fa_hit = 1; + } + if (de_digtable->large_fa_hit >= 3) { + if ((de_digtable->forbidden_igi + 1) > DM_DIG_MAX) + de_digtable->rx_gain_min = DM_DIG_MAX; + else + de_digtable->rx_gain_min = + (de_digtable->forbidden_igi + 1); + de_digtable->recover_cnt = 3600; /* 3600=2hr */ + } + } else { + /* Recovery mechanism for IGI lower bound */ + if (de_digtable->recover_cnt != 0) { + de_digtable->recover_cnt--; + } else { + if (de_digtable->large_fa_hit == 0) { + if ((de_digtable->forbidden_igi - 1) < + DM_DIG_FA_LOWER) { + de_digtable->forbidden_igi = + DM_DIG_FA_LOWER; + de_digtable->rx_gain_min = + DM_DIG_FA_LOWER; + + } else { + de_digtable->forbidden_igi--; + de_digtable->rx_gain_min = + (de_digtable->forbidden_igi + 1); + } + } else if (de_digtable->large_fa_hit == 3) { + de_digtable->large_fa_hit = 0; + } + } + } + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "dm_DIG() After: large_fa_hit=%d, forbidden_igi=%x\n", + de_digtable->large_fa_hit, de_digtable->forbidden_igi); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "dm_DIG() After: recover_cnt=%d, rx_gain_min=%x\n", + de_digtable->recover_cnt, de_digtable->rx_gain_min); + + if (value_igi > DM_DIG_MAX) + value_igi = DM_DIG_MAX; + else if (value_igi < de_digtable->rx_gain_min) + value_igi = de_digtable->rx_gain_min; + de_digtable->cur_igvalue = value_igi; + rtl92d_dm_write_dig(hw); + if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) + rtl92d_dm_cck_packet_detection_thresh(hw); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "<<==\n"); +} + +static void rtl92d_dm_init_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.dynamic_txpower_enable = true; + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; +} + +static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undec_sm_pwdb; + + if ((!rtlpriv->dm.dynamic_txpower_enable) + || rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.UNDEC_SM_PWDB == 0)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "Not connected to any\n"); + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + undec_sm_pwdb = + rtlpriv->dm.UNDEC_SM_PWDB; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "IBSS Client PWDB = 0x%lx\n", + undec_sm_pwdb); + } else { + undec_sm_pwdb = + rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "STA Default Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + } else { + undec_sm_pwdb = + rtlpriv->dm.UNDEC_SM_PWDB; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Ext Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + if (rtlhal->current_bandtype == BAND_ON_5G) { + if (undec_sm_pwdb >= 0x33) { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_LEVEL2; + RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD, + "5G:TxHighPwrLevel_Level2 (TxPwr=0x0)\n"); + } else if ((undec_sm_pwdb < 0x33) + && (undec_sm_pwdb >= 0x2b)) { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD, + "5G:TxHighPwrLevel_Level1 (TxPwr=0x10)\n"); + } else if (undec_sm_pwdb < 0x2b) { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_NORMAL; + RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD, + "5G:TxHighPwrLevel_Normal\n"); + } + } else { + if (undec_sm_pwdb >= + TX_POWER_NEAR_FIELD_THRESH_LVL2) { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_LEVEL2; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); + } else + if ((undec_sm_pwdb < + (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) + && (undec_sm_pwdb >= + TX_POWER_NEAR_FIELD_THRESH_LVL1)) { + + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); + } else if (undec_sm_pwdb < + (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { + rtlpriv->dm.dynamic_txhighpower_lvl = + TXHIGHPWRLEVEL_NORMAL; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_NORMAL\n"); + } + } + if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "PHY_SetTxPowerLevel8192S() Channel = %d\n", + rtlphy->current_channel); + rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel); + } + rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; +} + +static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* AP & ADHOC & MESH will return tmp */ + if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) + return; + /* Indicate Rx signal strength to FW. */ + if (rtlpriv->dm.useramask) { + u32 temp = rtlpriv->dm.undec_sm_pwdb; + + temp <<= 16; + temp |= 0x100; + /* fw v12 cmdid 5:use max macid ,for nic , + * default macid is 0 ,max macid is 1 */ + rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *) (&temp)); + } else { + rtl_write_byte(rtlpriv, 0x4fe, + (u8) rtlpriv->dm.undec_sm_pwdb); + } +} + +void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.current_turbo_edca = false; + rtlpriv->dm.is_any_nonbepkts = false; + rtlpriv->dm.is_cur_rdlstate = false; +} + +static void rtl92d_dm_check_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + static u64 last_txok_cnt; + static u64 last_rxok_cnt; + u64 cur_txok_cnt; + u64 cur_rxok_cnt; + u32 edca_be_ul = 0x5ea42b; + u32 edca_be_dl = 0x5ea42b; + + if (mac->link_state != MAC80211_LINKED) { + rtlpriv->dm.current_turbo_edca = false; + goto exit; + } + + /* Enable BEQ TxOP limit configuration in wireless G-mode. */ + /* To check whether we shall force turn on TXOP configuration. */ + if ((!rtlpriv->dm.disable_framebursting) && + (rtlpriv->sec.pairwise_enc_algorithm == WEP40_ENCRYPTION || + rtlpriv->sec.pairwise_enc_algorithm == WEP104_ENCRYPTION || + rtlpriv->sec.pairwise_enc_algorithm == TKIP_ENCRYPTION)) { + /* Force TxOP limit to 0x005e for UL. */ + if (!(edca_be_ul & 0xffff0000)) + edca_be_ul |= 0x005e0000; + /* Force TxOP limit to 0x005e for DL. */ + if (!(edca_be_dl & 0xffff0000)) + edca_be_dl |= 0x005e0000; + } + + if ((!rtlpriv->dm.is_any_nonbepkts) && + (!rtlpriv->dm.disable_framebursting)) { + cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; + cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; + if (cur_rxok_cnt > 4 * cur_txok_cnt) { + if (!rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, + edca_be_dl); + rtlpriv->dm.is_cur_rdlstate = true; + } + } else { + if (rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, + edca_be_ul); + rtlpriv->dm.is_cur_rdlstate = false; + } + } + rtlpriv->dm.current_turbo_edca = true; + } else { + if (rtlpriv->dm.current_turbo_edca) { + u8 tmp = AC0_BE; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + &tmp); + rtlpriv->dm.current_turbo_edca = false; + } + } + +exit: + rtlpriv->dm.is_any_nonbepkts = false; + last_txok_cnt = rtlpriv->stats.txbytesunicast; + last_rxok_cnt = rtlpriv->stats.rxbytesunicast; +} + +static void rtl92d_dm_rxgain_tracking_thermalmeter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 index_mapping[RX_INDEX_MAPPING_NUM] = { + 0x0f, 0x0f, 0x0d, 0x0c, 0x0b, + 0x0a, 0x09, 0x08, 0x07, 0x06, + 0x05, 0x04, 0x04, 0x03, 0x02 + }; + int i; + u32 u4tmp; + + u4tmp = (index_mapping[(rtlpriv->efuse.eeprom_thermalmeter - + rtlpriv->dm.thermalvalue_rxgain)]) << 12; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "===> Rx Gain %x\n", u4tmp); + for (i = RF90_PATH_A; i < rtlpriv->phy.num_total_rfpath; i++) + rtl_set_rfreg(hw, i, 0x3C, RFREG_OFFSET_MASK, + (rtlpriv->phy.reg_rf3c[i] & (~(0xF000))) | u4tmp); +} + +static void rtl92d_bandtype_2_4G(struct ieee80211_hw *hw, long *temp_cckg, + u8 *cck_index_old) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int i; + unsigned long flag = 0; + long temp_cck; + + /* Query CCK default setting From 0xa24 */ + rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); + temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2, + MASKDWORD) & MASKCCK; + rtl92d_release_cckandrw_pagea_ctl(hw, &flag); + for (i = 0; i < CCK_TABLE_LENGTH; i++) { + if (rtlpriv->dm.cck_inch14) { + if (!memcmp((void *)&temp_cck, + (void *)&cckswing_table_ch14[i][2], 4)) { + *cck_index_old = (u8) i; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch 14 %d\n", + RCCK0_TXFILTER2, temp_cck, + *cck_index_old, + rtlpriv->dm.cck_inch14); + break; + } + } else { + if (!memcmp((void *) &temp_cck, + &cckswing_table_ch1ch13[i][2], 4)) { + *cck_index_old = (u8) i; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch14 %d\n", + RCCK0_TXFILTER2, temp_cck, + *cck_index_old, + rtlpriv->dm.cck_inch14); + break; + } + } + } + *temp_cckg = temp_cck; +} + +static void rtl92d_bandtype_5G(struct rtl_hal *rtlhal, u8 *ofdm_index, + bool *internal_pa, u8 thermalvalue, u8 delta, + u8 rf, struct rtl_efuse *rtlefuse, + struct rtl_priv *rtlpriv, struct rtl_phy *rtlphy, + u8 index_mapping[5][INDEX_MAPPING_NUM], + u8 index_mapping_pa[8][INDEX_MAPPING_NUM]) +{ + int i; + u8 index; + u8 offset = 0; + + for (i = 0; i < rf; i++) { + if (rtlhal->macphymode == DUALMAC_DUALPHY && + rtlhal->interfaceindex == 1) /* MAC 1 5G */ + *internal_pa = rtlefuse->internal_pa_5g[1]; + else + *internal_pa = rtlefuse->internal_pa_5g[i]; + if (*internal_pa) { + if (rtlhal->interfaceindex == 1 || i == rf) + offset = 4; + else + offset = 0; + if (rtlphy->current_channel >= 100 && + rtlphy->current_channel <= 165) + offset += 2; + } else { + if (rtlhal->interfaceindex == 1 || i == rf) + offset = 2; + else + offset = 0; + } + if (thermalvalue > rtlefuse->eeprom_thermalmeter) + offset++; + if (*internal_pa) { + if (delta > INDEX_MAPPING_NUM - 1) + index = index_mapping_pa[offset] + [INDEX_MAPPING_NUM - 1]; + else + index = + index_mapping_pa[offset][delta]; + } else { + if (delta > INDEX_MAPPING_NUM - 1) + index = + index_mapping[offset][INDEX_MAPPING_NUM - 1]; + else + index = index_mapping[offset][delta]; + } + if (thermalvalue > rtlefuse->eeprom_thermalmeter) { + if (*internal_pa && thermalvalue > 0x12) { + ofdm_index[i] = rtlpriv->dm.ofdm_index[i] - + ((delta / 2) * 3 + (delta % 2)); + } else { + ofdm_index[i] -= index; + } + } else { + ofdm_index[i] += index; + } + } +} + +static void rtl92d_dm_txpower_tracking_callback_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 thermalvalue, delta, delta_lck, delta_iqk, delta_rxgain; + u8 offset, thermalvalue_avg_count = 0; + u32 thermalvalue_avg = 0; + bool internal_pa = false; + long ele_a = 0, ele_d, temp_cck, val_x, value32; + long val_y, ele_c = 0; + u8 ofdm_index[3]; + s8 cck_index = 0; + u8 ofdm_index_old[3] = {0, 0, 0}; + s8 cck_index_old = 0; + u8 index; + int i; + bool is2t = IS_92D_SINGLEPHY(rtlhal->version); + u8 ofdm_min_index = 6, ofdm_min_index_internal_pa = 3, rf; + u8 indexforchannel = + rtl92d_get_rightchnlplace_for_iqk(rtlphy->current_channel); + u8 index_mapping[5][INDEX_MAPPING_NUM] = { + /* 5G, path A/MAC 0, decrease power */ + {0, 1, 3, 6, 8, 9, 11, 13, 14, 16, 17, 18, 18}, + /* 5G, path A/MAC 0, increase power */ + {0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18}, + /* 5G, path B/MAC 1, decrease power */ + {0, 2, 3, 6, 8, 9, 11, 13, 14, 16, 17, 18, 18}, + /* 5G, path B/MAC 1, increase power */ + {0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18}, + /* 2.4G, for decreas power */ + {0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10}, + }; + u8 index_mapping_internal_pa[8][INDEX_MAPPING_NUM] = { + /* 5G, path A/MAC 0, ch36-64, decrease power */ + {0, 1, 2, 4, 6, 7, 9, 11, 12, 14, 15, 16, 16}, + /* 5G, path A/MAC 0, ch36-64, increase power */ + {0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18}, + /* 5G, path A/MAC 0, ch100-165, decrease power */ + {0, 1, 2, 3, 5, 6, 8, 10, 11, 13, 14, 15, 15}, + /* 5G, path A/MAC 0, ch100-165, increase power */ + {0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18}, + /* 5G, path B/MAC 1, ch36-64, decrease power */ + {0, 1, 2, 4, 6, 7, 9, 11, 12, 14, 15, 16, 16}, + /* 5G, path B/MAC 1, ch36-64, increase power */ + {0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18}, + /* 5G, path B/MAC 1, ch100-165, decrease power */ + {0, 1, 2, 3, 5, 6, 8, 9, 10, 12, 13, 14, 14}, + /* 5G, path B/MAC 1, ch100-165, increase power */ + {0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18}, + }; + + rtlpriv->dm.txpower_trackinginit = true; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "\n"); + thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xf800); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n", + thermalvalue, + rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter); + rtl92d_phy_ap_calibrate(hw, (thermalvalue - + rtlefuse->eeprom_thermalmeter)); + if (is2t) + rf = 2; + else + rf = 1; + if (thermalvalue) { + ele_d = rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE, + MASKDWORD) & MASKOFDM_D; + for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { + if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { + ofdm_index_old[0] = (u8) i; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n", + ROFDM0_XATxIQIMBALANCE, + ele_d, ofdm_index_old[0]); + break; + } + } + if (is2t) { + ele_d = rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, + MASKDWORD) & MASKOFDM_D; + for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { + if (ele_d == + (ofdmswing_table[i] & MASKOFDM_D)) { + ofdm_index_old[1] = (u8) i; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, + DBG_LOUD, + "Initial pathB ele_d reg 0x%x = 0x%lx, ofdm_index = 0x%x\n", + ROFDM0_XBTxIQIMBALANCE, ele_d, + ofdm_index_old[1]); + break; + } + } + } + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + rtl92d_bandtype_2_4G(hw, &temp_cck, &cck_index_old); + } else { + temp_cck = 0x090e1317; + cck_index_old = 12; + } + + if (!rtlpriv->dm.thermalvalue) { + rtlpriv->dm.thermalvalue = + rtlefuse->eeprom_thermalmeter; + rtlpriv->dm.thermalvalue_lck = thermalvalue; + rtlpriv->dm.thermalvalue_iqk = thermalvalue; + rtlpriv->dm.thermalvalue_rxgain = + rtlefuse->eeprom_thermalmeter; + for (i = 0; i < rf; i++) + rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; + rtlpriv->dm.cck_index = cck_index_old; + } + if (rtlhal->reloadtxpowerindex) { + for (i = 0; i < rf; i++) + rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; + rtlpriv->dm.cck_index = cck_index_old; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "reload ofdm index for band switch\n"); + } + rtlpriv->dm.thermalvalue_avg + [rtlpriv->dm.thermalvalue_avg_index] = thermalvalue; + rtlpriv->dm.thermalvalue_avg_index++; + if (rtlpriv->dm.thermalvalue_avg_index == AVG_THERMAL_NUM) + rtlpriv->dm.thermalvalue_avg_index = 0; + for (i = 0; i < AVG_THERMAL_NUM; i++) { + if (rtlpriv->dm.thermalvalue_avg[i]) { + thermalvalue_avg += + rtlpriv->dm.thermalvalue_avg[i]; + thermalvalue_avg_count++; + } + } + if (thermalvalue_avg_count) + thermalvalue = (u8) (thermalvalue_avg / + thermalvalue_avg_count); + if (rtlhal->reloadtxpowerindex) { + delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? + (thermalvalue - rtlefuse->eeprom_thermalmeter) : + (rtlefuse->eeprom_thermalmeter - thermalvalue); + rtlhal->reloadtxpowerindex = false; + rtlpriv->dm.done_txpower = false; + } else if (rtlpriv->dm.done_txpower) { + delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? + (thermalvalue - rtlpriv->dm.thermalvalue) : + (rtlpriv->dm.thermalvalue - thermalvalue); + } else { + delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? + (thermalvalue - rtlefuse->eeprom_thermalmeter) : + (rtlefuse->eeprom_thermalmeter - thermalvalue); + } + delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? + (thermalvalue - rtlpriv->dm.thermalvalue_lck) : + (rtlpriv->dm.thermalvalue_lck - thermalvalue); + delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? + (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : + (rtlpriv->dm.thermalvalue_iqk - thermalvalue); + delta_rxgain = + (thermalvalue > rtlpriv->dm.thermalvalue_rxgain) ? + (thermalvalue - rtlpriv->dm.thermalvalue_rxgain) : + (rtlpriv->dm.thermalvalue_rxgain - thermalvalue); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n", + thermalvalue, rtlpriv->dm.thermalvalue, + rtlefuse->eeprom_thermalmeter, delta, delta_lck, + delta_iqk); + if ((delta_lck > rtlefuse->delta_lck) && + (rtlefuse->delta_lck != 0)) { + rtlpriv->dm.thermalvalue_lck = thermalvalue; + rtl92d_phy_lc_calibrate(hw); + } + if (delta > 0 && rtlpriv->dm.txpower_track_control) { + rtlpriv->dm.done_txpower = true; + delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? + (thermalvalue - rtlefuse->eeprom_thermalmeter) : + (rtlefuse->eeprom_thermalmeter - thermalvalue); + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + offset = 4; + if (delta > INDEX_MAPPING_NUM - 1) + index = index_mapping[offset] + [INDEX_MAPPING_NUM - 1]; + else + index = index_mapping[offset][delta]; + if (thermalvalue > rtlpriv->dm.thermalvalue) { + for (i = 0; i < rf; i++) + ofdm_index[i] -= delta; + cck_index -= delta; + } else { + for (i = 0; i < rf; i++) + ofdm_index[i] += index; + cck_index += index; + } + } else if (rtlhal->current_bandtype == BAND_ON_5G) { + rtl92d_bandtype_5G(rtlhal, ofdm_index, + &internal_pa, thermalvalue, + delta, rf, rtlefuse, rtlpriv, + rtlphy, index_mapping, + index_mapping_internal_pa); + } + if (is2t) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "temp OFDM_A_index=0x%x, OFDM_B_index = 0x%x,cck_index=0x%x\n", + rtlpriv->dm.ofdm_index[0], + rtlpriv->dm.ofdm_index[1], + rtlpriv->dm.cck_index); + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "temp OFDM_A_index=0x%x,cck_index = 0x%x\n", + rtlpriv->dm.ofdm_index[0], + rtlpriv->dm.cck_index); + } + for (i = 0; i < rf; i++) { + if (ofdm_index[i] > OFDM_TABLE_SIZE_92D - 1) + ofdm_index[i] = OFDM_TABLE_SIZE_92D - 1; + else if (ofdm_index[i] < ofdm_min_index) + ofdm_index[i] = ofdm_min_index; + } + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + if (cck_index > CCK_TABLE_SIZE - 1) { + cck_index = CCK_TABLE_SIZE - 1; + } else if (internal_pa || + rtlhal->current_bandtype == + BAND_ON_2_4G) { + if (ofdm_index[i] < + ofdm_min_index_internal_pa) + ofdm_index[i] = + ofdm_min_index_internal_pa; + } else if (cck_index < 0) { + cck_index = 0; + } + } + if (is2t) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "new OFDM_A_index=0x%x, OFDM_B_index = 0x%x, cck_index=0x%x\n", + ofdm_index[0], ofdm_index[1], + cck_index); + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "new OFDM_A_index=0x%x,cck_index = 0x%x\n", + ofdm_index[0], cck_index); + } + ele_d = (ofdmswing_table[(u8) ofdm_index[0]] & + 0xFFC00000) >> 22; + val_x = rtlphy->iqk_matrix + [indexforchannel].value[0][0]; + val_y = rtlphy->iqk_matrix + [indexforchannel].value[0][1]; + if (val_x != 0) { + if ((val_x & 0x00000200) != 0) + val_x = val_x | 0xFFFFFC00; + ele_a = + ((val_x * ele_d) >> 8) & 0x000003FF; + + /* new element C = element D x Y */ + if ((val_y & 0x00000200) != 0) + val_y = val_y | 0xFFFFFC00; + ele_c = ((val_y * ele_d) >> 8) & 0x000003FF; + + /* wirte new elements A, C, D to regC80 and + * regC94, element B is always 0 */ + value32 = (ele_d << 22) | ((ele_c & 0x3F) << + 16) | ele_a; + rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, + MASKDWORD, value32); + + value32 = (ele_c & 0x000003C0) >> 6; + rtl_set_bbreg(hw, ROFDM0_XCTxAFE, MASKH4BITS, + value32); + + value32 = ((val_x * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), + value32); + + } else { + rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, + MASKDWORD, + ofdmswing_table + [(u8)ofdm_index[0]]); + rtl_set_bbreg(hw, ROFDM0_XCTxAFE, MASKH4BITS, + 0x00); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(24), 0x00); + } + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "TxPwrTracking for interface %d path A: X = 0x%lx, Y = 0x%lx ele_A = 0x%lx ele_C = 0x%lx ele_D = 0x%lx 0xe94 = 0x%lx 0xe9c = 0x%lx\n", + rtlhal->interfaceindex, + val_x, val_y, ele_a, ele_c, ele_d, + val_x, val_y); + + if (cck_index >= CCK_TABLE_SIZE) + cck_index = CCK_TABLE_SIZE - 1; + if (cck_index < 0) + cck_index = 0; + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + /* Adjust CCK according to IQK result */ + if (!rtlpriv->dm.cck_inch14) { + rtl_write_byte(rtlpriv, 0xa22, + cckswing_table_ch1ch13 + [(u8)cck_index][0]); + rtl_write_byte(rtlpriv, 0xa23, + cckswing_table_ch1ch13 + [(u8)cck_index][1]); + rtl_write_byte(rtlpriv, 0xa24, + cckswing_table_ch1ch13 + [(u8)cck_index][2]); + rtl_write_byte(rtlpriv, 0xa25, + cckswing_table_ch1ch13 + [(u8)cck_index][3]); + rtl_write_byte(rtlpriv, 0xa26, + cckswing_table_ch1ch13 + [(u8)cck_index][4]); + rtl_write_byte(rtlpriv, 0xa27, + cckswing_table_ch1ch13 + [(u8)cck_index][5]); + rtl_write_byte(rtlpriv, 0xa28, + cckswing_table_ch1ch13 + [(u8)cck_index][6]); + rtl_write_byte(rtlpriv, 0xa29, + cckswing_table_ch1ch13 + [(u8)cck_index][7]); + } else { + rtl_write_byte(rtlpriv, 0xa22, + cckswing_table_ch14 + [(u8)cck_index][0]); + rtl_write_byte(rtlpriv, 0xa23, + cckswing_table_ch14 + [(u8)cck_index][1]); + rtl_write_byte(rtlpriv, 0xa24, + cckswing_table_ch14 + [(u8)cck_index][2]); + rtl_write_byte(rtlpriv, 0xa25, + cckswing_table_ch14 + [(u8)cck_index][3]); + rtl_write_byte(rtlpriv, 0xa26, + cckswing_table_ch14 + [(u8)cck_index][4]); + rtl_write_byte(rtlpriv, 0xa27, + cckswing_table_ch14 + [(u8)cck_index][5]); + rtl_write_byte(rtlpriv, 0xa28, + cckswing_table_ch14 + [(u8)cck_index][6]); + rtl_write_byte(rtlpriv, 0xa29, + cckswing_table_ch14 + [(u8)cck_index][7]); + } + } + if (is2t) { + ele_d = (ofdmswing_table[(u8) ofdm_index[1]] & + 0xFFC00000) >> 22; + val_x = rtlphy->iqk_matrix + [indexforchannel].value[0][4]; + val_y = rtlphy->iqk_matrix + [indexforchannel].value[0][5]; + if (val_x != 0) { + if ((val_x & 0x00000200) != 0) + /* consider minus */ + val_x = val_x | 0xFFFFFC00; + ele_a = ((val_x * ele_d) >> 8) & + 0x000003FF; + /* new element C = element D x Y */ + if ((val_y & 0x00000200) != 0) + val_y = + val_y | 0xFFFFFC00; + ele_c = + ((val_y * + ele_d) >> 8) & 0x00003FF; + /* write new elements A, C, D to regC88 + * and regC9C, element B is always 0 + */ + value32 = (ele_d << 22) | + ((ele_c & 0x3F) << 16) | + ele_a; + rtl_set_bbreg(hw, + ROFDM0_XBTxIQIMBALANCE, + MASKDWORD, value32); + value32 = (ele_c & 0x000003C0) >> 6; + rtl_set_bbreg(hw, ROFDM0_XDTxAFE, + MASKH4BITS, value32); + value32 = ((val_x * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(28), value32); + } else { + rtl_set_bbreg(hw, + ROFDM0_XBTxIQIMBALANCE, + MASKDWORD, + ofdmswing_table + [(u8) ofdm_index[1]]); + rtl_set_bbreg(hw, ROFDM0_XDTxAFE, + MASKH4BITS, 0x00); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, + BIT(28), 0x00); + } + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "TxPwrTracking path B: X = 0x%lx, Y = 0x%lx ele_A = 0x%lx ele_C = 0x%lx ele_D = 0x%lx 0xeb4 = 0x%lx 0xebc = 0x%lx\n", + val_x, val_y, ele_a, ele_c, + ele_d, val_x, val_y); + } + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "TxPwrTracking 0xc80 = 0x%x, 0xc94 = 0x%x RF 0x24 = 0x%x\n", + rtl_get_bbreg(hw, 0xc80, MASKDWORD), + rtl_get_bbreg(hw, 0xc94, MASKDWORD), + rtl_get_rfreg(hw, RF90_PATH_A, 0x24, + RFREG_OFFSET_MASK)); + } + if ((delta_iqk > rtlefuse->delta_iqk) && + (rtlefuse->delta_iqk != 0)) { + rtl92d_phy_reset_iqk_result(hw); + rtlpriv->dm.thermalvalue_iqk = thermalvalue; + rtl92d_phy_iq_calibrate(hw); + } + if (delta_rxgain > 0 && rtlhal->current_bandtype == BAND_ON_5G + && thermalvalue <= rtlefuse->eeprom_thermalmeter) { + rtlpriv->dm.thermalvalue_rxgain = thermalvalue; + rtl92d_dm_rxgain_tracking_thermalmeter(hw); + } + if (rtlpriv->dm.txpower_track_control) + rtlpriv->dm.thermalvalue = thermalvalue; + } + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===\n"); +} + +static void rtl92d_dm_initialize_txpower_tracking(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.txpower_tracking = true; + rtlpriv->dm.txpower_trackinginit = false; + rtlpriv->dm.txpower_track_control = true; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pMgntInfo->txpower_tracking = %d\n", + rtlpriv->dm.txpower_tracking); +} + +void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (!rtlpriv->dm.txpower_tracking) + return; + + if (!rtlpriv->dm.tm_trigger) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | + BIT(16), 0x03); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Trigger 92S Thermal Meter!!\n"); + rtlpriv->dm.tm_trigger = 1; + return; + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Schedule TxPowerTracking direct call!!\n"); + rtl92d_dm_txpower_tracking_callback_thermalmeter(hw); + rtlpriv->dm.tm_trigger = 0; + } +} + +void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rate_adaptive *ra = &(rtlpriv->ra); + + ra->ratr_state = DM_RATR_STA_INIT; + ra->pre_ratr_state = DM_RATR_STA_INIT; + if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) + rtlpriv->dm.useramask = true; + else + rtlpriv->dm.useramask = false; +} + +void rtl92d_dm_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; + rtl_dm_diginit(hw, 0x20); + rtlpriv->dm_digtable.rx_gain_max = DM_DIG_FA_UPPER; + rtlpriv->dm_digtable.rx_gain_min = DM_DIG_FA_LOWER; + rtl92d_dm_init_dynamic_txpower(hw); + rtl92d_dm_init_edca_turbo(hw); + rtl92d_dm_init_rate_adaptive_mask(hw); + rtl92d_dm_initialize_txpower_tracking(hw); +} + +void rtl92d_dm_watchdog(struct ieee80211_hw *hw) +{ + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool fw_current_inpsmode = false; + bool fwps_awake = true; + + /* 1. RF is OFF. (No need to do DM.) + * 2. Fw is under power saving mode for FwLPS. + * (Prevent from SW/FW I/O racing.) + * 3. IPS workitem is scheduled. (Prevent from IPS sequence + * to be swapped with DM. + * 4. RFChangeInProgress is TRUE. + * (Prevent from broken by IPS/HW/SW Rf off.) */ + + if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) && + fwps_awake) && (!ppsc->rfchange_inprogress)) { + rtl92d_dm_pwdb_monitor(hw); + rtl92d_dm_false_alarm_counter_statistics(hw); + rtl92d_dm_find_minimum_rssi(hw); + rtl92d_dm_dig(hw); + /* rtl92d_dm_dynamic_bb_powersaving(hw); */ + rtl92d_dm_dynamic_txpower(hw); + /* rtl92d_dm_check_txpower_tracking_thermal_meter(hw); */ + /* rtl92d_dm_refresh_rate_adaptive_mask(hw); */ + /* rtl92d_dm_interrupt_migration(hw); */ + rtl92d_dm_check_edca_turbo(hw); + } +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h new file mode 100644 index 000000000000..f2d318ceeb28 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.h @@ -0,0 +1,123 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_DM_H__ +#define __RTL92C_DM_H__ + +#define HAL_DM_DIG_DISABLE BIT(0) +#define HAL_DM_HIPWR_DISABLE BIT(1) + +#define OFDM_TABLE_LENGTH 37 +#define OFDM_TABLE_SIZE_92D 43 +#define CCK_TABLE_LENGTH 33 + +#define CCK_TABLE_SIZE 33 + +#define BW_AUTO_SWITCH_HIGH_LOW 25 +#define BW_AUTO_SWITCH_LOW_HIGH 30 + +#define DM_DIG_FA_UPPER 0x32 +#define DM_DIG_FA_LOWER 0x20 +#define DM_DIG_FA_TH0 0x100 +#define DM_DIG_FA_TH1 0x400 +#define DM_DIG_FA_TH2 0x600 + +#define RXPATHSELECTION_SS_TH_lOW 30 +#define RXPATHSELECTION_DIFF_TH 18 + +#define DM_RATR_STA_INIT 0 +#define DM_RATR_STA_HIGH 1 +#define DM_RATR_STA_MIDDLE 2 +#define DM_RATR_STA_LOW 3 + +#define CTS2SELF_THVAL 30 +#define REGC38_TH 20 + +#define WAIOTTHVAL 25 + +#define TXHIGHPWRLEVEL_NORMAL 0 +#define TXHIGHPWRLEVEL_LEVEL1 1 +#define TXHIGHPWRLEVEL_LEVEL2 2 +#define TXHIGHPWRLEVEL_BT1 3 +#define TXHIGHPWRLEVEL_BT2 4 + +#define DM_TYPE_BYFW 0 +#define DM_TYPE_BYDRIVER 1 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 +#define INDEX_MAPPING_NUM 13 + +struct swat { + u8 failure_cnt; + u8 try_flag; + u8 stop_trying; + long pre_rssi; + long trying_threshold; + u8 cur_antenna; + u8 pre_antenna; +}; + +enum tag_dynamic_init_gain_operation_type_definition { + DIG_TYPE_THRESH_HIGH = 0, + DIG_TYPE_THRESH_LOW = 1, + DIG_TYPE_BACKOFF = 2, + DIG_TYPE_RX_GAIN_MIN = 3, + DIG_TYPE_RX_GAIN_MAX = 4, + DIG_TYPE_ENABLE = 5, + DIG_TYPE_DISABLE = 6, + DIG_OP_TYPE_MAX +}; + +enum dm_1r_cca { + CCA_1R = 0, + CCA_2R = 1, + CCA_MAX = 2, +}; + +enum dm_rf { + RF_SAVE = 0, + RF_NORMAL = 1, + RF_MAX = 2, +}; + +enum dm_sw_ant_switch { + ANS_ANTENNA_B = 1, + ANS_ANTENNA_A = 2, + ANS_ANTENNA_MAX = 3, +}; + +void rtl92d_dm_init(struct ieee80211_hw *hw); +void rtl92d_dm_watchdog(struct ieee80211_hw *hw); +void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw); +void rtl92d_dm_write_dig(struct ieee80211_hw *hw); +void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw); +void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c new file mode 100644 index 000000000000..62ef8209718f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.c @@ -0,0 +1,763 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "fw.h" +#include "sw.h" + +static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv) +{ + return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ? + true : false; +} + +static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp; + + if (enable) { + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04); + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); + rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); + } else { + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); + /* Reserved for fw extension. + * 0x81[7] is used for mac0 status , + * so don't write this reg here + * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/ + } +} + +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; + 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); + pagenums = size / FW_8192D_PAGE_SIZE; + remainSize = size % FW_8192D_PAGE_SIZE; + if (pagenums > 8) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "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); + } + if (remainSize) { + offset = pagenums * FW_8192D_PAGE_SIZE; + page = pagenums; + _rtl92d_fw_page_write(hw, page, (bufferPtr + offset), + remainSize); + } +} + +static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 counter = 0; + u32 value32; + + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + } while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) && + (!(value32 & FWDL_ChkSum_rpt))); + if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "chksum report faill ! REG_MCUFWDL:0x%08x\n", + value32); + return -EIO; + } + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "Checksum report OK ! REG_MCUFWDL:0x%08x\n", value32); + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + value32 |= MCUFWDL_RDY; + rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); + return 0; +} + +void rtl92d_firmware_selfreset(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1b_tmp; + u8 delay = 100; + + /* Set (REG_HMETFR + 3) to 0x20 is reset 8051 */ + rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20); + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + while (u1b_tmp & BIT(2)) { + delay--; + if (delay == 0) + break; + udelay(50); + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + } + RT_ASSERT((delay > 0), "8051 reset failed!\n"); + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "=====> 8051 reset success (%d)\n", delay); +} + +static int _rtl92d_fw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 counter; + + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, "FW already have download\n"); + /* polling for FW ready */ + counter = 0; + do { + if (rtlhal->interfaceindex == 0) { + if (rtl_read_byte(rtlpriv, FW_MAC0_READY) & + MAC0_READY) { + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "Polling FW ready success!! REG_MCUFWDL: 0x%x\n", + rtl_read_byte(rtlpriv, + FW_MAC0_READY)); + return 0; + } + udelay(5); + } else { + if (rtl_read_byte(rtlpriv, FW_MAC1_READY) & + MAC1_READY) { + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "Polling FW ready success!! REG_MCUFWDL: 0x%x\n", + rtl_read_byte(rtlpriv, + FW_MAC1_READY)); + return 0; + } + udelay(5); + } + } while (counter++ < POLLING_READY_TIMEOUT_COUNT); + + if (rtlhal->interfaceindex == 0) { + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "Polling FW ready fail!! MAC0 FW init not ready: 0x%x\n", + rtl_read_byte(rtlpriv, FW_MAC0_READY)); + } else { + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "Polling FW ready fail!! MAC1 FW init not ready: 0x%x\n", + rtl_read_byte(rtlpriv, FW_MAC1_READY)); + } + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "Polling FW ready fail!! REG_MCUFWDL:0x%08ul\n", + rtl_read_dword(rtlpriv, REG_MCUFWDL)); + return -1; +} + +int rtl92d_download_fw(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 *pfwheader; + u8 *pfwdata; + u32 fwsize; + int err; + enum version_8192d version = rtlhal->version; + u8 value; + u32 count; + bool fw_downloaded = false, fwdl_in_process = false; + unsigned long flags; + + if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) + return 1; + fwsize = rtlhal->fwsize; + pfwheader = rtlhal->pfirmware; + pfwdata = rtlhal->pfirmware; + rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader); + rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "FirmwareVersion(%d), FirmwareSubVersion(%d), Signature(%#x)\n", + rtlhal->fw_version, rtlhal->fw_subversion, + GET_FIRMWARE_HDR_SIGNATURE(pfwheader)); + if (IS_FW_HEADER_EXIST(pfwheader)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Shift 32 bytes for FW header!!\n"); + pfwdata = pfwdata + 32; + fwsize = fwsize - 32; + } + + spin_lock_irqsave(&globalmutex_for_fwdownload, flags); + fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv); + if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5)) + fwdl_in_process = true; + else + fwdl_in_process = false; + if (fw_downloaded) { + spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); + goto exit; + } else if (fwdl_in_process) { + spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); + for (count = 0; count < 5000; count++) { + udelay(500); + spin_lock_irqsave(&globalmutex_for_fwdownload, flags); + fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv); + if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5)) + fwdl_in_process = true; + else + fwdl_in_process = false; + spin_unlock_irqrestore(&globalmutex_for_fwdownload, + flags); + if (fw_downloaded) + goto exit; + else if (!fwdl_in_process) + break; + else + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "Wait for another mac download fw\n"); + } + spin_lock_irqsave(&globalmutex_for_fwdownload, flags); + value = rtl_read_byte(rtlpriv, 0x1f); + value |= BIT(5); + rtl_write_byte(rtlpriv, 0x1f, value); + spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); + } else { + value = rtl_read_byte(rtlpriv, 0x1f); + value |= BIT(5); + rtl_write_byte(rtlpriv, 0x1f, value); + spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); + } + + /* If 8051 is running in RAM code, driver should + * inform Fw to reset by itself, or it will cause + * download Fw fail.*/ + /* 8051 RAM code */ + if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { + rtl92d_firmware_selfreset(hw); + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); + } + _rtl92d_enable_fw_download(hw, true); + _rtl92d_write_fw(hw, version, pfwdata, fwsize); + _rtl92d_enable_fw_download(hw, false); + spin_lock_irqsave(&globalmutex_for_fwdownload, flags); + err = _rtl92d_fw_free_to_go(hw); + /* download fw over,clear 0x1f[5] */ + value = rtl_read_byte(rtlpriv, 0x1f); + value &= (~BIT(5)); + rtl_write_byte(rtlpriv, 0x1f, value); + spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "fw is not ready to run!\n"); + goto exit; + } else { + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "fw is ready to run!\n"); + } +exit: + err = _rtl92d_fw_init(hw); + return err; +} + +static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 val_hmetfr; + bool result = false; + + val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); + if (((val_hmetfr >> boxnum) & BIT(0)) == 0) + result = true; + return result; +} + +static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, u8 *cmdbuffer) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 boxnum; + u16 box_reg = 0, box_extreg = 0; + u8 u1b_tmp; + bool isfw_read = false; + u8 buf_index = 0; + bool bwrite_success = false; + u8 wait_h2c_limmit = 100; + u8 wait_writeh2c_limmit = 100; + u8 boxcontent[4], boxextcontent[2]; + u32 h2c_waitcounter = 0; + unsigned long flag; + u8 idx; + + if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Return as RF is off!!!\n"); + return; + } + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); + while (true) { + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + if (rtlhal->h2c_setinprogress) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C set in progress! Wait to set..element_id(%d)\n", + element_id); + + while (rtlhal->h2c_setinprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, + flag); + h2c_waitcounter++; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Wait 100 us (%d times)...\n", + h2c_waitcounter); + udelay(100); + + if (h2c_waitcounter > 1000) + return; + + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, + flag); + } + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + } else { + rtlhal->h2c_setinprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + break; + } + } + while (!bwrite_success) { + wait_writeh2c_limmit--; + if (wait_writeh2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Write H2C fail because no trigger for FW INT!\n"); + break; + } + boxnum = rtlhal->last_hmeboxnum; + switch (boxnum) { + case 0: + box_reg = REG_HMEBOX_0; + box_extreg = REG_HMEBOX_EXT_0; + break; + case 1: + box_reg = REG_HMEBOX_1; + box_extreg = REG_HMEBOX_EXT_1; + break; + case 2: + box_reg = REG_HMEBOX_2; + box_extreg = REG_HMEBOX_EXT_2; + break; + case 3: + box_reg = REG_HMEBOX_3; + box_extreg = REG_HMEBOX_EXT_3; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum); + while (!isfw_read) { + wait_h2c_limmit--; + if (wait_h2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Waiting too long for FW read clear HMEBox(%d)!\n", + boxnum); + break; + } + udelay(10); + isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum); + u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF); + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n", + boxnum, u1b_tmp); + } + if (!isfw_read) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", + boxnum); + break; + } + memset(boxcontent, 0, sizeof(boxcontent)); + memset(boxextcontent, 0, sizeof(boxextcontent)); + boxcontent[0] = element_id; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Write element_id box_reg(%4x) = %2x\n", + box_reg, element_id); + switch (cmd_len) { + case 1: + boxcontent[0] &= ~(BIT(7)); + memcpy(boxcontent + 1, cmdbuffer + buf_index, 1); + for (idx = 0; idx < 4; idx++) + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + break; + case 2: + boxcontent[0] &= ~(BIT(7)); + memcpy(boxcontent + 1, cmdbuffer + buf_index, 2); + for (idx = 0; idx < 4; idx++) + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + break; + case 3: + boxcontent[0] &= ~(BIT(7)); + memcpy(boxcontent + 1, cmdbuffer + buf_index, 3); + for (idx = 0; idx < 4; idx++) + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + break; + case 4: + boxcontent[0] |= (BIT(7)); + memcpy(boxextcontent, cmdbuffer + buf_index, 2); + memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2); + for (idx = 0; idx < 2; idx++) + rtl_write_byte(rtlpriv, box_extreg + idx, + boxextcontent[idx]); + for (idx = 0; idx < 4; idx++) + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + break; + case 5: + boxcontent[0] |= (BIT(7)); + memcpy(boxextcontent, cmdbuffer + buf_index, 2); + memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3); + for (idx = 0; idx < 2; idx++) + rtl_write_byte(rtlpriv, box_extreg + idx, + boxextcontent[idx]); + for (idx = 0; idx < 4; idx++) + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + bwrite_success = true; + rtlhal->last_hmeboxnum = boxnum + 1; + if (rtlhal->last_hmeboxnum == 4) + rtlhal->last_hmeboxnum = 0; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "pHalData->last_hmeboxnum = %d\n", + rtlhal->last_hmeboxnum); + } + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + rtlhal->h2c_setinprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); +} + +void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, u8 *cmdbuffer) +{ + u32 tmp_cmdbuf[2]; + + memset(tmp_cmdbuf, 0, 8); + memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); + _rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); + return; +} + +static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + struct rtl_tx_desc *pdesc; + u8 idx = 0; + unsigned long flags; + struct sk_buff *pskb; + + ring = &rtlpci->tx_ring[BEACON_QUEUE]; + pskb = __skb_dequeue(&ring->queue); + kfree_skb(pskb); + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + pdesc = &ring->desc[idx]; + /* discard output from call below */ + rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); + rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); + __skb_queue_tail(&ring->queue, skb); + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); + return true; +} + +#define BEACON_PG 0 /*->1 */ +#define PSPOLL_PG 2 +#define NULL_PG 3 +#define PROBERSP_PG 4 /*->5 */ +#define TOTAL_RESERVED_PKT_LEN 768 + +static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { + /* page 0 beacon */ + 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, + 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, + 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, + 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, + 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, + 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, + 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 1 beacon */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 2 ps-poll */ + 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 3 null */ + 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 4 probe_resp */ + 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, + 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, + 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, + 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, + 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, + 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, + 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, + 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, + 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 5 probe_resp */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct sk_buff *skb = NULL; + u32 totalpacketlen; + bool rtstatus; + u8 u1RsvdPageLoc[3] = { 0 }; + bool dlok = false; + u8 *beacon; + u8 *p_pspoll; + u8 *nullfunc; + u8 *p_probersp; + /*--------------------------------------------------------- + (1) beacon + ---------------------------------------------------------*/ + beacon = &reserved_page_packet[BEACON_PG * 128]; + SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); + SET_80211_HDR_ADDRESS3(beacon, mac->bssid); + /*------------------------------------------------------- + (2) ps-poll + --------------------------------------------------------*/ + p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; + SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); + SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); + SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); + /*-------------------------------------------------------- + (3) null data + ---------------------------------------------------------*/ + nullfunc = &reserved_page_packet[NULL_PG * 128]; + SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); + SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); + SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); + /*--------------------------------------------------------- + (4) probe response + ----------------------------------------------------------*/ + p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; + SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); + SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); + SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); + SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG); + totalpacketlen = TOTAL_RESERVED_PKT_LEN; + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL", + &reserved_page_packet[0], totalpacketlen); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL", + u1RsvdPageLoc, 3); + skb = dev_alloc_skb(totalpacketlen); + if (!skb) { + dlok = false; + } else { + memcpy((u8 *) skb_put(skb, totalpacketlen), + &reserved_page_packet, totalpacketlen); + rtstatus = _rtl92d_cmd_send_packet(hw, skb); + + if (rtstatus) + dlok = true; + } + if (dlok) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Set RSVD page location to Fw\n"); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "H2C_RSVDPAGE", u1RsvdPageLoc, 3); + rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE, + sizeof(u1RsvdPageLoc), u1RsvdPageLoc); + } else + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set RSVD page location to Fw FAIL!!!!!!\n"); +} + +void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) +{ + u8 u1_joinbssrpt_parm[1] = {0}; + + SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); + rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h new file mode 100644 index 000000000000..8a38daa316cb --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.h @@ -0,0 +1,120 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92D__FW__H__ +#define __RTL92D__FW__H__ + +#define FW_8192D_START_ADDRESS 0x1000 +#define FW_8192D_PAGE_SIZE 4096 +#define FW_8192D_POLLING_TIMEOUT_COUNT 1000 + +#define IS_FW_HEADER_EXIST(_pfwhdr) \ + ((GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFF0) == 0x92C0 || \ + (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFF0) == 0x88C0 || \ + (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D0 || \ + (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D1 || \ + (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D2 || \ + (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D3) + +/* Define a macro that takes an 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, __mask) \ + ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ + BIT_LEN_MASK_32(__mask)) + +/* Firmware Header(8-byte alinment required) */ +/* --- LONG WORD 0 ---- */ +#define GET_FIRMWARE_HDR_SIGNATURE(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr, 0, 16) +#define GET_FIRMWARE_HDR_CATEGORY(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr, 16, 8) +#define GET_FIRMWARE_HDR_FUNCTION(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr, 24, 8) +#define GET_FIRMWARE_HDR_VERSION(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 4, 0, 16) +#define GET_FIRMWARE_HDR_SUB_VER(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 4, 16, 8) +#define GET_FIRMWARE_HDR_RSVD1(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 4, 24, 8) + +/* --- LONG WORD 1 ---- */ +#define GET_FIRMWARE_HDR_MONTH(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 8, 0, 8) +#define GET_FIRMWARE_HDR_DATE(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 8, 8, 8) +#define GET_FIRMWARE_HDR_HOUR(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 8, 16, 8) +#define GET_FIRMWARE_HDR_MINUTE(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 8, 24, 8) +#define GET_FIRMWARE_HDR_ROMCODE_SIZE(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 12, 0, 16) +#define GET_FIRMWARE_HDR_RSVD2(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 12, 16, 16) + +/* --- LONG WORD 2 ---- */ +#define GET_FIRMWARE_HDR_SVN_IDX(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 16, 0, 32) +#define GET_FIRMWARE_HDR_RSVD3(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 20, 0, 32) + +/* --- LONG WORD 3 ---- */ +#define GET_FIRMWARE_HDR_RSVD4(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 24, 0, 32) +#define GET_FIRMWARE_HDR_RSVD5(__fwhdr) \ + SHIFT_AND_MASK_LE(__fwhdr + 28, 0, 32) + +#define pagenum_128(_len) \ + (u32)(((_len) >> 7) + ((_len) & 0x7F ? 1 : 0)) + +#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val) +#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val) + +int rtl92d_download_fw(struct ieee80211_hw *hw); +void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *p_cmdbuffer); +void rtl92d_firmware_selfreset(struct ieee80211_hw *hw); +void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); +void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c new file mode 100644 index 000000000000..f49b60d31450 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c @@ -0,0 +1,2307 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../regd.h" +#include "../cam.h" +#include "../ps.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "led.h" +#include "sw.h" +#include "hw.h" + +u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, u8 direct) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 value; + + rtl_write_word(rtlpriv, REG_DBI_CTRL, (offset & 0xFFC)); + rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(1) | direct); + udelay(10); + value = rtl_read_dword(rtlpriv, REG_DBI_RDATA); + return value; +} + +void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, + u16 offset, u32 value, u8 direct) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_word(rtlpriv, REG_DBI_CTRL, ((offset & 0xFFC) | 0xF000)); + rtl_write_dword(rtlpriv, REG_DBI_WDATA, value); + rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(0) | direct); +} + +static void _rtl92de_set_bcn_ctrl_reg(struct ieee80211_hw *hw, + u8 set_bits, u8 clear_bits) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpci->reg_bcn_ctrl_val |= set_bits; + rtlpci->reg_bcn_ctrl_val &= ~clear_bits; + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); +} + +static void _rtl92de_stop_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); + rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl92de_resume_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); + rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte |= BIT(0); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl92de_enable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(1)); +} + +static void _rtl92de_disable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl92de_set_bcn_ctrl_reg(hw, BIT(1), 0); +} + +void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + switch (variable) { + case HW_VAR_RCR: + *((u32 *) (val)) = rtlpci->receive_config; + break; + case HW_VAR_RF_STATE: + *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; + break; + case HW_VAR_FWLPS_RF_ON:{ + enum rf_pwrstate rfState; + u32 val_rcr; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, + (u8 *) (&rfState)); + if (rfState == ERFOFF) { + *((bool *) (val)) = true; + } else { + val_rcr = rtl_read_dword(rtlpriv, REG_RCR); + val_rcr &= 0x00070000; + if (val_rcr) + *((bool *) (val)) = false; + else + *((bool *) (val)) = true; + } + break; + } + case HW_VAR_FW_PSMODE_STATUS: + *((bool *) (val)) = ppsc->fw_current_inpsmode; + break; + case HW_VAR_CORRECT_TSF:{ + u64 tsf; + u32 *ptsf_low = (u32 *)&tsf; + u32 *ptsf_high = ((u32 *)&tsf) + 1; + + *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); + *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + *((u64 *) (val)) = tsf; + break; + } + case HW_VAR_INT_MIGRATION: + *((bool *)(val)) = rtlpriv->dm.interrupt_migration; + break; + case HW_VAR_INT_AC: + *((bool *)(val)) = rtlpriv->dm.disable_tx_int; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } +} + +void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 idx; + + switch (variable) { + case HW_VAR_ETHER_ADDR: + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_MACID + idx), + val[idx]); + } + break; + case HW_VAR_BASIC_RATE: { + u16 rate_cfg = ((u16 *) val)[0]; + u8 rate_index = 0; + + rate_cfg = rate_cfg & 0x15f; + if (mac->vendor == PEER_CISCO && + ((rate_cfg & 0x150) == 0)) + rate_cfg |= 0x01; + rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); + rtl_write_byte(rtlpriv, REG_RRSR + 1, + (rate_cfg >> 8) & 0xff); + while (rate_cfg > 0x1) { + rate_cfg = (rate_cfg >> 1); + rate_index++; + } + if (rtlhal->fw_version > 0xe) + rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, + rate_index); + break; + } + case HW_VAR_BSSID: + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_BSSID + idx), + val[idx]); + } + break; + case HW_VAR_SIFS: + rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); + rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); + rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); + rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); + if (!mac->ht_enable) + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, + 0x0e0e); + else + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, + *((u16 *) val)); + break; + case HW_VAR_SLOT_TIME: { + u8 e_aci; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "HW_VAR_SLOT_TIME %x\n", val[0]); + rtl_write_byte(rtlpriv, REG_SLOT, val[0]); + for (e_aci = 0; e_aci < AC_MAX; e_aci++) + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AC_PARAM, + (&e_aci)); + break; + } + case HW_VAR_ACK_PREAMBLE: { + u8 reg_tmp; + u8 short_preamble = (bool) (*val); + + reg_tmp = (mac->cur_40_prime_sc) << 5; + if (short_preamble) + reg_tmp |= 0x80; + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp); + break; + } + case HW_VAR_AMPDU_MIN_SPACE: { + u8 min_spacing_to_set; + u8 sec_min_space; + + min_spacing_to_set = *val; + if (min_spacing_to_set <= 7) { + sec_min_space = 0; + if (min_spacing_to_set < sec_min_space) + min_spacing_to_set = sec_min_space; + mac->min_space_cfg = ((mac->min_space_cfg & 0xf8) | + min_spacing_to_set); + *val = min_spacing_to_set; + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", + mac->min_space_cfg); + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + } + break; + } + case HW_VAR_SHORTGI_DENSITY: { + u8 density_to_set; + + density_to_set = *val; + mac->min_space_cfg = rtlpriv->rtlhal.minspace_cfg; + mac->min_space_cfg |= (density_to_set << 3); + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_SHORTGI_DENSITY: %#x\n", + mac->min_space_cfg); + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + break; + } + case HW_VAR_AMPDU_FACTOR: { + u8 factor_toset; + u32 regtoSet; + u8 *ptmp_byte = NULL; + u8 index; + + if (rtlhal->macphymode == DUALMAC_DUALPHY) + regtoSet = 0xb9726641; + else if (rtlhal->macphymode == DUALMAC_SINGLEPHY) + regtoSet = 0x66626641; + else + regtoSet = 0xb972a841; + factor_toset = *val; + if (factor_toset <= 3) { + factor_toset = (1 << (factor_toset + 2)); + if (factor_toset > 0xf) + factor_toset = 0xf; + for (index = 0; index < 4; index++) { + ptmp_byte = (u8 *) (®toSet) + index; + if ((*ptmp_byte & 0xf0) > + (factor_toset << 4)) + *ptmp_byte = (*ptmp_byte & 0x0f) + | (factor_toset << 4); + if ((*ptmp_byte & 0x0f) > factor_toset) + *ptmp_byte = (*ptmp_byte & 0xf0) + | (factor_toset); + } + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, regtoSet); + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_FACTOR: %#x\n", + factor_toset); + } + break; + } + case HW_VAR_AC_PARAM: { + u8 e_aci = *val; + rtl92d_dm_init_edca_turbo(hw); + if (rtlpci->acm_method != EACMWAY2_SW) + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, + &e_aci); + break; + } + case HW_VAR_ACM_CTRL: { + u8 e_aci = *val; + union aci_aifsn *p_aci_aifsn = + (union aci_aifsn *)(&(mac->ac[0].aifs)); + u8 acm = p_aci_aifsn->f.acm; + u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); + + acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); + if (acm) { + switch (e_aci) { + case AC0_BE: + acm_ctrl |= ACMHW_BEQEN; + break; + case AC2_VI: + acm_ctrl |= ACMHW_VIQEN; + break; + case AC3_VO: + acm_ctrl |= ACMHW_VOQEN; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", + acm); + break; + } + } else { + switch (e_aci) { + case AC0_BE: + acm_ctrl &= (~ACMHW_BEQEN); + break; + case AC2_VI: + acm_ctrl &= (~ACMHW_VIQEN); + break; + case AC3_VO: + acm_ctrl &= (~ACMHW_VOQEN); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + } + RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, + "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", + acm_ctrl); + rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); + break; + } + case HW_VAR_RCR: + rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]); + rtlpci->receive_config = ((u32 *) (val))[0]; + break; + case HW_VAR_RETRY_LIMIT: { + u8 retry_limit = val[0]; + + rtl_write_word(rtlpriv, REG_RL, + retry_limit << RETRY_LIMIT_SHORT_SHIFT | + retry_limit << RETRY_LIMIT_LONG_SHIFT); + break; + } + case HW_VAR_DUAL_TSF_RST: + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); + break; + case HW_VAR_EFUSE_BYTES: + rtlefuse->efuse_usedbytes = *((u16 *) val); + break; + case HW_VAR_EFUSE_USAGE: + rtlefuse->efuse_usedpercentage = *val; + break; + case HW_VAR_IO_CMD: + rtl92d_phy_set_io_cmd(hw, (*(enum io_type *)val)); + break; + case HW_VAR_WPA_CONFIG: + rtl_write_byte(rtlpriv, REG_SECCFG, *val); + break; + case HW_VAR_SET_RPWM: + rtl92d_fill_h2c_cmd(hw, H2C_PWRM, 1, (val)); + break; + case HW_VAR_H2C_FW_PWRMODE: + break; + case HW_VAR_FW_PSMODE_STATUS: + ppsc->fw_current_inpsmode = *((bool *) val); + break; + case HW_VAR_H2C_FW_JOINBSSRPT: { + u8 mstatus = (*val); + u8 tmp_regcr, tmp_reg422; + bool recover = false; + + if (mstatus == RT_MEDIA_CONNECT) { + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AID, NULL); + tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, + (tmp_regcr | BIT(0))); + _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3)); + _rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0); + tmp_reg422 = rtl_read_byte(rtlpriv, + REG_FWHW_TXQ_CTRL + 2); + if (tmp_reg422 & BIT(6)) + recover = true; + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, + tmp_reg422 & (~BIT(6))); + rtl92d_set_fw_rsvdpagepkt(hw, 0); + _rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0); + _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4)); + if (recover) + rtl_write_byte(rtlpriv, + REG_FWHW_TXQ_CTRL + 2, + tmp_reg422); + rtl_write_byte(rtlpriv, REG_CR + 1, + (tmp_regcr & ~(BIT(0)))); + } + rtl92d_set_fw_joinbss_report_cmd(hw, (*val)); + break; + } + case HW_VAR_AID: { + u16 u2btmp; + u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); + u2btmp &= 0xC000; + rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | + mac->assoc_id)); + break; + } + case HW_VAR_CORRECT_TSF: { + u8 btype_ibss = val[0]; + + if (btype_ibss) + _rtl92de_stop_tx_beacon(hw); + _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3)); + rtl_write_dword(rtlpriv, REG_TSFTR, + (u32) (mac->tsf & 0xffffffff)); + rtl_write_dword(rtlpriv, REG_TSFTR + 4, + (u32) ((mac->tsf >> 32) & 0xffffffff)); + _rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0); + if (btype_ibss) + _rtl92de_resume_tx_beacon(hw); + + break; + } + case HW_VAR_INT_MIGRATION: { + bool int_migration = *(bool *) (val); + + if (int_migration) { + /* Set interrupt migration timer and + * corresponding Tx/Rx counter. + * timer 25ns*0xfa0=100us for 0xf packets. + * 0x306:Rx, 0x307:Tx */ + rtl_write_dword(rtlpriv, REG_INT_MIG, 0xfe000fa0); + rtlpriv->dm.interrupt_migration = int_migration; + } else { + /* Reset all interrupt migration settings. */ + rtl_write_dword(rtlpriv, REG_INT_MIG, 0); + rtlpriv->dm.interrupt_migration = int_migration; + } + break; + } + case HW_VAR_INT_AC: { + bool disable_ac_int = *((bool *) val); + + /* Disable four ACs interrupts. */ + if (disable_ac_int) { + /* Disable VO, VI, BE and BK four AC interrupts + * to gain more efficient CPU utilization. + * When extremely highly Rx OK occurs, + * we will disable Tx interrupts. + */ + rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, + RT_AC_INT_MASKS); + rtlpriv->dm.disable_tx_int = disable_ac_int; + /* Enable four ACs interrupts. */ + } else { + rtlpriv->cfg->ops->update_interrupt_mask(hw, + RT_AC_INT_MASKS, 0); + rtlpriv->dm.disable_tx_int = disable_ac_int; + } + break; + } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } +} + +static bool _rtl92de_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool status = true; + long count = 0; + u32 value = _LLT_INIT_ADDR(address) | + _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); + + rtl_write_dword(rtlpriv, REG_LLT_INIT, value); + do { + value = rtl_read_dword(rtlpriv, REG_LLT_INIT); + if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) + break; + if (count > POLLING_LLT_THRESHOLD) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to polling write LLT done at address %d!\n", + address); + status = false; + break; + } + } while (++count); + return status; +} + +static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + unsigned short i; + u8 txpktbuf_bndy; + u8 maxPage; + bool status; + u32 value32; /* High+low page number */ + u8 value8; /* normal page number */ + + if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) { + maxPage = 255; + txpktbuf_bndy = 246; + value8 = 0; + value32 = 0x80bf0d29; + } else { + maxPage = 127; + txpktbuf_bndy = 123; + value8 = 0; + value32 = 0x80750005; + } + + /* Set reserved page for each queue */ + /* 11. RQPN 0x200[31:0] = 0x80BD1C1C */ + /* load RQPN */ + rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8); + rtl_write_dword(rtlpriv, REG_RQPN, value32); + + /* 12. TXRKTBUG_PG_BNDY 0x114[31:0] = 0x27FF00F6 */ + /* TXRKTBUG_PG_BNDY */ + rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, + (rtl_read_word(rtlpriv, REG_TRXFF_BNDY + 2) << 16 | + txpktbuf_bndy)); + + /* 13. TDECTRL[15:8] 0x209[7:0] = 0xF6 */ + /* Beacon Head for TXDMA */ + rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); + + /* 14. BCNQ_PGBNDY 0x424[7:0] = 0xF6 */ + /* BCNQ_PGBNDY */ + rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); + + /* 15. WMAC_LBK_BF_HD 0x45D[7:0] = 0xF6 */ + /* WMAC_LBK_BF_HD */ + rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); + + /* Set Tx/Rx page size (Tx must be 128 Bytes, */ + /* Rx can be 64,128,256,512,1024 bytes) */ + /* 16. PBP [7:0] = 0x11 */ + /* TRX page size */ + rtl_write_byte(rtlpriv, REG_PBP, 0x11); + + /* 17. DRV_INFO_SZ = 0x04 */ + rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); + + /* 18. LLT_table_init(Adapter); */ + for (i = 0; i < (txpktbuf_bndy - 1); i++) { + status = _rtl92de_llt_write(hw, i, i + 1); + if (true != status) + return status; + } + + /* end of list */ + status = _rtl92de_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); + if (true != status) + return status; + + /* Make the other pages as ring buffer */ + /* This ring buffer is used as beacon buffer if we */ + /* config this MAC as two MAC transfer. */ + /* Otherwise used as local loopback buffer. */ + for (i = txpktbuf_bndy; i < maxPage; i++) { + status = _rtl92de_llt_write(hw, i, (i + 1)); + if (true != status) + return status; + } + + /* Let last entry point to the start entry of ring buffer */ + status = _rtl92de_llt_write(hw, maxPage, txpktbuf_bndy); + if (true != status) + return status; + + return true; +} + +static void _rtl92de_gen_refresh_led_state(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + + if (rtlpci->up_first_time) + return; + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) + rtl92de_sw_led_on(hw, pLed0); + else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) + rtl92de_sw_led_on(hw, pLed0); + else + rtl92de_sw_led_off(hw, pLed0); +} + +static bool _rtl92de_init_mac(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + unsigned char bytetmp; + unsigned short wordtmp; + u16 retry; + + rtl92d_phy_set_poweron(hw); + /* Add for resume sequence of power domain according + * to power document V11. Chapter V.11.... */ + /* 0. RSV_CTRL 0x1C[7:0] = 0x00 */ + /* unlock ISO/CLK/Power control register */ + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x05); + + /* 1. AFE_XTAL_CTRL [7:0] = 0x0F enable XTAL */ + /* 2. SPS0_CTRL 0x11[7:0] = 0x2b enable SPS into PWM mode */ + /* 3. delay (1ms) this is not necessary when initially power on */ + + /* C. Resume Sequence */ + /* a. SPS0_CTRL 0x11[7:0] = 0x2b */ + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + + /* b. AFE_XTAL_CTRL [7:0] = 0x0F */ + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F); + + /* c. DRV runs power on init flow */ + + /* auto enable WLAN */ + /* 4. APS_FSMCO 0x04[8] = 1; wait till 0x04[8] = 0 */ + /* Power On Reset for MAC Block */ + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0); + udelay(2); + rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); + udelay(2); + + /* 5. Wait while 0x04[8] == 0 goto 2, otherwise goto 1 */ + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); + udelay(50); + retry = 0; + while ((bytetmp & BIT(0)) && retry < 1000) { + retry++; + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); + udelay(50); + } + + /* Enable Radio off, GPIO, and LED function */ + /* 6. APS_FSMCO 0x04[15:0] = 0x0012 when enable HWPDN */ + rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x1012); + + /* release RF digital isolation */ + /* 7. SYS_ISO_CTRL 0x01[1] = 0x0; */ + /*Set REG_SYS_ISO_CTRL 0x1=0x82 to prevent wake# problem. */ + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82); + udelay(2); + + /* make sure that BB reset OK. */ + /* rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); */ + + /* Disable REG_CR before enable it to assure reset */ + rtl_write_word(rtlpriv, REG_CR, 0x0); + + /* Release MAC IO register reset */ + rtl_write_word(rtlpriv, REG_CR, 0x2ff); + + /* clear stopping tx/rx dma */ + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x0); + + /* rtl_write_word(rtlpriv,REG_CR+2, 0x2); */ + + /* System init */ + /* 18. LLT_table_init(Adapter); */ + if (!_rtl92de_llt_table_init(hw)) + return false; + + /* Clear interrupt and enable interrupt */ + /* 19. HISR 0x124[31:0] = 0xffffffff; */ + /* HISRE 0x12C[7:0] = 0xFF */ + rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); + rtl_write_byte(rtlpriv, REG_HISRE, 0xff); + + /* 20. HIMR 0x120[31:0] |= [enable INT mask bit map]; */ + /* 21. HIMRE 0x128[7:0] = [enable INT mask bit map] */ + /* The IMR should be enabled later after all init sequence + * is finished. */ + + /* 22. PCIE configuration space configuration */ + /* 23. Ensure PCIe Device 0x80[15:0] = 0x0143 (ASPM+CLKREQ), */ + /* and PCIe gated clock function is enabled. */ + /* PCIE configuration space will be written after + * all init sequence.(Or by BIOS) */ + + rtl92d_phy_config_maccoexist_rfpage(hw); + + /* THe below section is not related to power document Vxx . */ + /* This is only useful for driver and OS setting. */ + /* -------------------Software Relative Setting---------------------- */ + wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); + wordtmp &= 0xf; + wordtmp |= 0xF771; + rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); + + /* Reported Tx status from HW for rate adaptive. */ + /* This should be realtive to power on step 14. But in document V11 */ + /* still not contain the description.!!! */ + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); + + /* Set Tx/Rx page size (Tx must be 128 Bytes, + * Rx can be 64,128,256,512,1024 bytes) */ + /* rtl_write_byte(rtlpriv,REG_PBP, 0x11); */ + + /* Set RCR register */ + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + /* rtl_write_byte(rtlpriv,REG_RX_DRVINFO_SZ, 4); */ + + /* Set TCR register */ + rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); + + /* disable earlymode */ + rtl_write_byte(rtlpriv, 0x4d0, 0x0); + + /* Set TX/RX descriptor physical address(from OS API). */ + rtl_write_dword(rtlpriv, REG_BCNQ_DESA, + rtlpci->tx_ring[BEACON_QUEUE].dma); + rtl_write_dword(rtlpriv, REG_MGQ_DESA, rtlpci->tx_ring[MGNT_QUEUE].dma); + rtl_write_dword(rtlpriv, REG_VOQ_DESA, rtlpci->tx_ring[VO_QUEUE].dma); + rtl_write_dword(rtlpriv, REG_VIQ_DESA, rtlpci->tx_ring[VI_QUEUE].dma); + rtl_write_dword(rtlpriv, REG_BEQ_DESA, rtlpci->tx_ring[BE_QUEUE].dma); + rtl_write_dword(rtlpriv, REG_BKQ_DESA, rtlpci->tx_ring[BK_QUEUE].dma); + rtl_write_dword(rtlpriv, REG_HQ_DESA, rtlpci->tx_ring[HIGH_QUEUE].dma); + /* Set RX Desc Address */ + rtl_write_dword(rtlpriv, REG_RX_DESA, + rtlpci->rx_ring[RX_MPDU_QUEUE].dma); + + /* if we want to support 64 bit DMA, we should set it here, + * but now we do not support 64 bit DMA*/ + + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x33); + + /* Reset interrupt migration setting when initialization */ + rtl_write_dword(rtlpriv, REG_INT_MIG, 0); + + /* Reconsider when to do this operation after asking HWSD. */ + bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6)); + do { + retry++; + bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); + } while ((retry < 200) && !(bytetmp & BIT(7))); + + /* After MACIO reset,we must refresh LED state. */ + _rtl92de_gen_refresh_led_state(hw); + + /* Reset H2C protection register */ + rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); + + return true; +} + +static void _rtl92de_hw_configure(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 reg_bw_opmode = BW_OPMODE_20MHZ; + u32 reg_rrsr; + + reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8); + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr); + rtl_write_byte(rtlpriv, REG_SLOT, 0x09); + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0); + rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80); + rtl_write_word(rtlpriv, REG_RL, 0x0707); + rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802); + rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); + rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); + rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); + /* Aggregation threshold */ + if (rtlhal->macphymode == DUALMAC_DUALPHY) + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb9726641); + else if (rtlhal->macphymode == DUALMAC_SINGLEPHY) + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x66626641); + else + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); + rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); + rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a); + rtlpci->reg_bcn_ctrl_val = 0x1f; + rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); + rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + /* For throughput */ + rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0x6666); + /* ACKTO for IOT issue. */ + rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); + /* Set Spec SIFS (used in NAV) */ + rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010); + rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010); + /* Set SIFS for CCK */ + rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010); + /* Set SIFS for OFDM */ + rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010); + /* Set Multicast Address. */ + rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff); + rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff); + switch (rtlpriv->phy.rf_type) { + case RF_1T2R: + case RF_1T1R: + rtlhal->minspace_cfg = (MAX_MSS_DENSITY_1T << 3); + break; + case RF_2T2R: + case RF_2T2R_GREEN: + rtlhal->minspace_cfg = (MAX_MSS_DENSITY_2T << 3); + break; + } +} + +static void _rtl92de_enable_aspm_back_door(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + rtl_write_byte(rtlpriv, 0x34b, 0x93); + rtl_write_word(rtlpriv, 0x350, 0x870c); + rtl_write_byte(rtlpriv, 0x352, 0x1); + if (ppsc->support_backdoor) + rtl_write_byte(rtlpriv, 0x349, 0x1b); + else + rtl_write_byte(rtlpriv, 0x349, 0x03); + rtl_write_word(rtlpriv, 0x350, 0x2718); + rtl_write_byte(rtlpriv, 0x352, 0x1); +} + +void rtl92de_enable_hw_security_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 sec_reg_value; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", + rtlpriv->sec.pairwise_enc_algorithm, + rtlpriv->sec.group_enc_algorithm); + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "not open hw encryption\n"); + return; + } + sec_reg_value = SCR_TXENCENABLE | SCR_RXENCENABLE; + if (rtlpriv->sec.use_defaultkey) { + sec_reg_value |= SCR_TXUSEDK; + sec_reg_value |= SCR_RXUSEDK; + } + sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); + rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "The SECR-value %x\n", sec_reg_value); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); +} + +int rtl92de_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool rtstatus = true; + u8 tmp_u1b; + int i; + int err; + unsigned long flags; + + rtlpci->being_init_adapter = true; + rtlpci->init_ready = false; + spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags); + /* we should do iqk after disable/enable */ + rtl92d_phy_reset_iqk_result(hw); + /* rtlpriv->intf_ops->disable_aspm(hw); */ + rtstatus = _rtl92de_init_mac(hw); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); + err = 1; + spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags); + return err; + } + err = rtl92d_download_fw(hw); + spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW..\n"); + return 1; + } + rtlhal->last_hmeboxnum = 0; + rtlpriv->psc.fw_current_inpsmode = false; + + tmp_u1b = rtl_read_byte(rtlpriv, 0x605); + tmp_u1b = tmp_u1b | 0x30; + rtl_write_byte(rtlpriv, 0x605, tmp_u1b); + + if (rtlhal->earlymode_enable) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EarlyMode Enabled!!!\n"); + + tmp_u1b = rtl_read_byte(rtlpriv, 0x4d0); + tmp_u1b = tmp_u1b | 0x1f; + rtl_write_byte(rtlpriv, 0x4d0, tmp_u1b); + + rtl_write_byte(rtlpriv, 0x4d3, 0x80); + + tmp_u1b = rtl_read_byte(rtlpriv, 0x605); + tmp_u1b = tmp_u1b | 0x40; + rtl_write_byte(rtlpriv, 0x605, tmp_u1b); + } + + if (mac->rdg_en) { + rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xff); + rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200); + rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05); + } + + rtl92d_phy_mac_config(hw); + /* because last function modify RCR, so we update + * rcr var here, or TP will unstable for receive_config + * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx + * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/ + rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); + rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); + + rtl92d_phy_bb_config(hw); + + rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; + /* set before initialize RF */ + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf); + + /* config RF */ + rtl92d_phy_rf_config(hw); + + /* After read predefined TXT, we must set BB/MAC/RF + * register as our requirement */ + /* After load BB,RF params,we need do more for 92D. */ + rtl92d_update_bbrf_configuration(hw); + /* set default value after initialize RF, */ + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0); + rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, + RF_CHNLBW, RFREG_OFFSET_MASK); + + /*---- Set CCK and OFDM Block "ON"----*/ + if (rtlhal->current_bandtype == BAND_ON_2_4G) + rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); + if (rtlhal->interfaceindex == 0) { + /* RFPGA0_ANALOGPARAMETER2: cck clock select, + * set to 20MHz by default */ + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) | + BIT(11), 3); + } else { + /* Mac1 */ + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(11) | + BIT(10), 3); + } + + _rtl92de_hw_configure(hw); + + /* reset hw sec */ + rtl_cam_reset_all_entry(hw); + rtl92de_enable_hw_security_config(hw); + + /* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */ + /* TX power index for different rate set. */ + rtl92d_phy_get_hw_reg_originalvalue(hw); + rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel); + + ppsc->rfpwr_state = ERFON; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); + + _rtl92de_enable_aspm_back_door(hw); + /* rtlpriv->intf_ops->enable_aspm(hw); */ + + rtl92d_dm_init(hw); + rtlpci->being_init_adapter = false; + + if (ppsc->rfpwr_state == ERFON) { + rtl92d_phy_lc_calibrate(hw); + /* 5G and 2.4G must wait sometime to let RF LO ready */ + if (rtlhal->macphymode == DUALMAC_DUALPHY) { + u32 tmp_rega; + for (i = 0; i < 10000; i++) { + udelay(MAX_STALL_TIME); + + tmp_rega = rtl_get_rfreg(hw, + (enum radio_path)RF90_PATH_A, + 0x2a, MASKDWORD); + + if (((tmp_rega & BIT(11)) == BIT(11))) + break; + } + /* check that loop was successful. If not, exit now */ + if (i == 10000) { + rtlpci->init_ready = false; + return 1; + } + } + } + rtlpci->init_ready = true; + return err; +} + +static enum version_8192d _rtl92de_read_chip_version(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + enum version_8192d version = VERSION_NORMAL_CHIP_92D_SINGLEPHY; + u32 value32; + + value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); + if (!(value32 & 0x000f0000)) { + version = VERSION_TEST_CHIP_92D_SINGLEPHY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "TEST CHIP!!!\n"); + } else { + version = VERSION_NORMAL_CHIP_92D_SINGLEPHY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Normal CHIP!!!\n"); + } + return version; +} + +static int _rtl92de_set_media_status(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_msr = rtl_read_byte(rtlpriv, MSR); + enum led_ctl_mode ledaction = LED_CTL_NO_LINK; + u8 bcnfunc_enable; + + bt_msr &= 0xfc; + + if (type == NL80211_IFTYPE_UNSPECIFIED || + type == NL80211_IFTYPE_STATION) { + _rtl92de_stop_tx_beacon(hw); + _rtl92de_enable_bcn_sub_func(hw); + } else if (type == NL80211_IFTYPE_ADHOC || + type == NL80211_IFTYPE_AP) { + _rtl92de_resume_tx_beacon(hw); + _rtl92de_disable_bcn_sub_func(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set HW_VAR_MEDIA_STATUS: No such media status(%x)\n", + type); + } + bcnfunc_enable = rtl_read_byte(rtlpriv, REG_BCN_CTRL); + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + bt_msr |= MSR_NOLINK; + ledaction = LED_CTL_LINK; + bcnfunc_enable &= 0xF7; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to NO LINK!\n"); + break; + case NL80211_IFTYPE_ADHOC: + bt_msr |= MSR_ADHOC; + bcnfunc_enable |= 0x08; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to Ad Hoc!\n"); + break; + case NL80211_IFTYPE_STATION: + bt_msr |= MSR_INFRA; + ledaction = LED_CTL_LINK; + bcnfunc_enable &= 0xF7; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to STA!\n"); + break; + case NL80211_IFTYPE_AP: + bt_msr |= MSR_AP; + bcnfunc_enable |= 0x08; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to AP!\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Network type %d not supported!\n", type); + return 1; + break; + + } + rtl_write_byte(rtlpriv, MSR, bt_msr); + rtlpriv->cfg->ops->led_control(hw, ledaction); + if ((bt_msr & MSR_MASK) == MSR_AP) + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); + else + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); + return 0; +} + +void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 reg_rcr; + + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); + + if (check_bssid) { + reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); + _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4)); + } else if (!check_bssid) { + reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); + _rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); + } +} + +int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (_rtl92de_set_media_status(hw, type)) + return -EOPNOTSUPP; + + /* check bssid */ + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP) + rtl92de_set_check_bssid(hw, true); + } else { + rtl92de_set_check_bssid(hw, false); + } + return 0; +} + +/* do iqk or reload iqk */ +/* windows just rtl92d_phy_reload_iqk_setting in set channel, + * but it's very strict for time sequence so we add + * rtl92d_phy_reload_iqk_setting here */ +void rtl92d_linked_set_reg(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u8 indexforchannel; + u8 channel = rtlphy->current_channel; + + indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); + if (!rtlphy->iqk_matrix[indexforchannel].iqk_done) { + RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_DMESG, + "Do IQK for channel:%d\n", channel); + rtl92d_phy_iq_calibrate(hw); + } +} + +/* don't set REG_EDCA_BE_PARAM here because + * mac80211 will send pkt when scan */ +void rtl92de_set_qos(struct ieee80211_hw *hw, int aci) +{ + rtl92d_dm_init_edca_turbo(hw); +} + +void rtl92de_enable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); + rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); +} + +void rtl92de_disable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED); + rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); + synchronize_irq(rtlpci->pdev->irq); +} + +static void _rtl92de_poweroff_adapter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1b_tmp; + unsigned long flags; + + rtlpriv->intf_ops->enable_aspm(hw); + rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); + rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(3), 0); + rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(15), 0); + + /* 0x20:value 05-->04 */ + rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x04); + + /* ==== Reset digital sequence ====== */ + rtl92d_firmware_selfreset(hw); + + /* f. SYS_FUNC_EN 0x03[7:0]=0x51 reset MCU, MAC register, DCORE */ + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51); + + /* g. MCUFWDL 0x80[1:0]=0 reset MCU ready status */ + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); + + /* ==== Pull GPIO PIN to balance level and LED control ====== */ + + /* h. GPIO_PIN_CTRL 0x44[31:0]=0x000 */ + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000); + + /* i. Value = GPIO_PIN_CTRL[7:0] */ + u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL); + + /* j. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); */ + /* write external PIN level */ + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, + 0x00FF0000 | (u1b_tmp << 8)); + + /* k. GPIO_MUXCFG 0x42 [15:0] = 0x0780 */ + rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); + + /* l. LEDCFG 0x4C[15:0] = 0x8080 */ + rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); + + /* ==== Disable analog sequence === */ + + /* m. AFE_PLL_CTRL[7:0] = 0x80 disable PLL */ + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); + + /* n. SPS0_CTRL 0x11[7:0] = 0x22 enter PFM mode */ + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); + + /* o. AFE_XTAL_CTRL 0x24[7:0] = 0x0E disable XTAL, if No BT COEX */ + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); + + /* p. RSV_CTRL 0x1C[7:0] = 0x0E lock ISO/CLK/Power control register */ + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); + + /* ==== interface into suspend === */ + + /* q. APS_FSMCO[15:8] = 0x58 PCIe suspend mode */ + /* According to power document V11, we need to set this */ + /* value as 0x18. Otherwise, we may not L0s sometimes. */ + /* This indluences power consumption. Bases on SD1's test, */ + /* set as 0x00 do not affect power current. And if it */ + /* is set as 0x18, they had ever met auto load fail problem. */ + rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "In PowerOff,reg0x%x=%X\n", + REG_SPS0_CTRL, rtl_read_byte(rtlpriv, REG_SPS0_CTRL)); + /* r. Note: for PCIe interface, PON will not turn */ + /* off m-bias and BandGap in PCIe suspend mode. */ + + /* 0x17[7] 1b': power off in process 0b' : power off over */ + if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) { + spin_lock_irqsave(&globalmutex_power, flags); + u1b_tmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS); + u1b_tmp &= (~BIT(7)); + rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1b_tmp); + spin_unlock_irqrestore(&globalmutex_power, flags); + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "<=======\n"); +} + +void rtl92de_card_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + enum nl80211_iftype opmode; + + mac->link_state = MAC80211_NOLINK; + opmode = NL80211_IFTYPE_UNSPECIFIED; + _rtl92de_set_media_status(hw, opmode); + + if (rtlpci->driver_is_goingto_unload || + ppsc->rfoff_reason > RF_CHANGE_BY_PS) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + /* Power sequence for each MAC. */ + /* a. stop tx DMA */ + /* b. close RF */ + /* c. clear rx buf */ + /* d. stop rx DMA */ + /* e. reset MAC */ + + /* a. stop tx DMA */ + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE); + udelay(50); + + /* b. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue */ + + /* c. ========RF OFF sequence========== */ + /* 0x88c[23:20] = 0xf. */ + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + + /* APSD_CTRL 0x600[7:0] = 0x40 */ + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + + /* Close antenna 0,0xc04,0xd04 */ + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0); + rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0); + + /* SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB state machine */ + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + + /* Mac0 can not do Global reset. Mac1 can do. */ + /* SYS_FUNC_EN 0x02[7:0] = 0xE0 reset BB state machine */ + if (rtlpriv->rtlhal.interfaceindex == 1) + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0); + udelay(50); + + /* d. stop tx/rx dma before disable REG_CR (0x100) to fix */ + /* dma hang issue when disable/enable device. */ + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xff); + udelay(50); + rtl_write_byte(rtlpriv, REG_CR, 0x0); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "==> Do power off.......\n"); + if (rtl92d_phy_check_poweroff(hw)) + _rtl92de_poweroff_adapter(hw); + return; +} + +void rtl92de_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; + rtl_write_dword(rtlpriv, ISR, *p_inta); + + /* + * *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; + * rtl_write_dword(rtlpriv, ISR + 4, *p_intb); + */ +} + +void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval, atim_window; + + bcn_interval = mac->beacon_interval; + atim_window = 2; + /*rtl92de_disable_interrupt(hw); */ + rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x20); + if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x30); + else + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x20); + rtl_write_byte(rtlpriv, 0x606, 0x30); +} + +void rtl92de_set_beacon_interval(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval = mac->beacon_interval; + + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "beacon_interval:%d\n", bcn_interval); + /* rtl92de_disable_interrupt(hw); */ + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + /* rtl92de_enable_interrupt(hw); */ +} + +void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, "add_msr:%x, rm_msr:%x\n", + add_msr, rm_msr); + if (add_msr) + rtlpci->irq_mask[0] |= add_msr; + if (rm_msr) + rtlpci->irq_mask[0] &= (~rm_msr); + rtl92de_disable_interrupt(hw); + rtl92de_enable_interrupt(hw); +} + +static void _rtl92de_readpowervalue_fromprom(struct txpower_info *pwrinfo, + u8 *rom_content, bool autoLoadfail) +{ + u32 rfpath, eeaddr, group, offset1, offset2; + u8 i; + + memset(pwrinfo, 0, sizeof(struct txpower_info)); + if (autoLoadfail) { + for (group = 0; group < CHANNEL_GROUP_MAX; group++) { + for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { + if (group < CHANNEL_GROUP_MAX_2G) { + pwrinfo->cck_index[rfpath][group] = + EEPROM_DEFAULT_TXPOWERLEVEL_2G; + pwrinfo->ht40_1sindex[rfpath][group] = + EEPROM_DEFAULT_TXPOWERLEVEL_2G; + } else { + pwrinfo->ht40_1sindex[rfpath][group] = + EEPROM_DEFAULT_TXPOWERLEVEL_5G; + } + pwrinfo->ht40_2sindexdiff[rfpath][group] = + EEPROM_DEFAULT_HT40_2SDIFF; + pwrinfo->ht20indexdiff[rfpath][group] = + EEPROM_DEFAULT_HT20_DIFF; + pwrinfo->ofdmindexdiff[rfpath][group] = + EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; + pwrinfo->ht40maxoffset[rfpath][group] = + EEPROM_DEFAULT_HT40_PWRMAXOFFSET; + pwrinfo->ht20maxoffset[rfpath][group] = + EEPROM_DEFAULT_HT20_PWRMAXOFFSET; + } + } + for (i = 0; i < 3; i++) { + pwrinfo->tssi_a[i] = EEPROM_DEFAULT_TSSI; + pwrinfo->tssi_b[i] = EEPROM_DEFAULT_TSSI; + } + return; + } + + /* Maybe autoload OK,buf the tx power index value is not filled. + * If we find it, we set it to default value. */ + for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { + for (group = 0; group < CHANNEL_GROUP_MAX_2G; group++) { + eeaddr = EEPROM_CCK_TX_PWR_INX_2G + (rfpath * 3) + + group; + pwrinfo->cck_index[rfpath][group] = + (rom_content[eeaddr] == 0xFF) ? + (eeaddr > 0x7B ? + EEPROM_DEFAULT_TXPOWERLEVEL_5G : + EEPROM_DEFAULT_TXPOWERLEVEL_2G) : + rom_content[eeaddr]; + } + } + for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { + for (group = 0; group < CHANNEL_GROUP_MAX; group++) { + offset1 = group / 3; + offset2 = group % 3; + eeaddr = EEPROM_HT40_1S_TX_PWR_INX_2G + (rfpath * 3) + + offset2 + offset1 * 21; + pwrinfo->ht40_1sindex[rfpath][group] = + (rom_content[eeaddr] == 0xFF) ? (eeaddr > 0x7B ? + EEPROM_DEFAULT_TXPOWERLEVEL_5G : + EEPROM_DEFAULT_TXPOWERLEVEL_2G) : + rom_content[eeaddr]; + } + } + /* These just for 92D efuse offset. */ + for (group = 0; group < CHANNEL_GROUP_MAX; group++) { + for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { + int base1 = EEPROM_HT40_2S_TX_PWR_INX_DIFF_2G; + + offset1 = group / 3; + offset2 = group % 3; + + if (rom_content[base1 + offset2 + offset1 * 21] != 0xFF) + pwrinfo->ht40_2sindexdiff[rfpath][group] = + (rom_content[base1 + + offset2 + offset1 * 21] >> (rfpath * 4)) + & 0xF; + else + pwrinfo->ht40_2sindexdiff[rfpath][group] = + EEPROM_DEFAULT_HT40_2SDIFF; + if (rom_content[EEPROM_HT20_TX_PWR_INX_DIFF_2G + offset2 + + offset1 * 21] != 0xFF) + pwrinfo->ht20indexdiff[rfpath][group] = + (rom_content[EEPROM_HT20_TX_PWR_INX_DIFF_2G + + offset2 + offset1 * 21] >> (rfpath * 4)) + & 0xF; + else + pwrinfo->ht20indexdiff[rfpath][group] = + EEPROM_DEFAULT_HT20_DIFF; + if (rom_content[EEPROM_OFDM_TX_PWR_INX_DIFF_2G + offset2 + + offset1 * 21] != 0xFF) + pwrinfo->ofdmindexdiff[rfpath][group] = + (rom_content[EEPROM_OFDM_TX_PWR_INX_DIFF_2G + + offset2 + offset1 * 21] >> (rfpath * 4)) + & 0xF; + else + pwrinfo->ofdmindexdiff[rfpath][group] = + EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; + if (rom_content[EEPROM_HT40_MAX_PWR_OFFSET_2G + offset2 + + offset1 * 21] != 0xFF) + pwrinfo->ht40maxoffset[rfpath][group] = + (rom_content[EEPROM_HT40_MAX_PWR_OFFSET_2G + + offset2 + offset1 * 21] >> (rfpath * 4)) + & 0xF; + else + pwrinfo->ht40maxoffset[rfpath][group] = + EEPROM_DEFAULT_HT40_PWRMAXOFFSET; + if (rom_content[EEPROM_HT20_MAX_PWR_OFFSET_2G + offset2 + + offset1 * 21] != 0xFF) + pwrinfo->ht20maxoffset[rfpath][group] = + (rom_content[EEPROM_HT20_MAX_PWR_OFFSET_2G + + offset2 + offset1 * 21] >> (rfpath * 4)) & + 0xF; + else + pwrinfo->ht20maxoffset[rfpath][group] = + EEPROM_DEFAULT_HT20_PWRMAXOFFSET; + } + } + if (rom_content[EEPROM_TSSI_A_5G] != 0xFF) { + /* 5GL */ + pwrinfo->tssi_a[0] = rom_content[EEPROM_TSSI_A_5G] & 0x3F; + pwrinfo->tssi_b[0] = rom_content[EEPROM_TSSI_B_5G] & 0x3F; + /* 5GM */ + pwrinfo->tssi_a[1] = rom_content[EEPROM_TSSI_AB_5G] & 0x3F; + pwrinfo->tssi_b[1] = + (rom_content[EEPROM_TSSI_AB_5G] & 0xC0) >> 6 | + (rom_content[EEPROM_TSSI_AB_5G + 1] & 0x0F) << 2; + /* 5GH */ + pwrinfo->tssi_a[2] = (rom_content[EEPROM_TSSI_AB_5G + 1] & + 0xF0) >> 4 | + (rom_content[EEPROM_TSSI_AB_5G + 2] & 0x03) << 4; + pwrinfo->tssi_b[2] = (rom_content[EEPROM_TSSI_AB_5G + 2] & + 0xFC) >> 2; + } else { + for (i = 0; i < 3; i++) { + pwrinfo->tssi_a[i] = EEPROM_DEFAULT_TSSI; + pwrinfo->tssi_b[i] = EEPROM_DEFAULT_TSSI; + } + } +} + +static void _rtl92de_read_txpower_info(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct txpower_info pwrinfo; + u8 tempval[2], i, pwr, diff; + u32 ch, rfPath, group; + + _rtl92de_readpowervalue_fromprom(&pwrinfo, hwinfo, autoload_fail); + if (!autoload_fail) { + /* bit0~2 */ + rtlefuse->eeprom_regulatory = (hwinfo[EEPROM_RF_OPT1] & 0x7); + rtlefuse->eeprom_thermalmeter = + hwinfo[EEPROM_THERMAL_METER] & 0x1f; + rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_K]; + tempval[0] = hwinfo[EEPROM_IQK_DELTA] & 0x03; + tempval[1] = (hwinfo[EEPROM_LCK_DELTA] & 0x0C) >> 2; + rtlefuse->txpwr_fromeprom = true; + if (IS_92D_D_CUT(rtlpriv->rtlhal.version) || + IS_92D_E_CUT(rtlpriv->rtlhal.version)) { + rtlefuse->internal_pa_5g[0] = + !((hwinfo[EEPROM_TSSI_A_5G] & BIT(6)) >> 6); + rtlefuse->internal_pa_5g[1] = + !((hwinfo[EEPROM_TSSI_B_5G] & BIT(6)) >> 6); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Is D cut,Internal PA0 %d Internal PA1 %d\n", + rtlefuse->internal_pa_5g[0], + rtlefuse->internal_pa_5g[1]); + } + rtlefuse->eeprom_c9 = hwinfo[EEPROM_RF_OPT6]; + rtlefuse->eeprom_cc = hwinfo[EEPROM_RF_OPT7]; + } else { + rtlefuse->eeprom_regulatory = 0; + rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; + rtlefuse->crystalcap = EEPROM_DEFAULT_CRYSTALCAP; + tempval[0] = tempval[1] = 3; + } + + /* Use default value to fill parameters if + * efuse is not filled on some place. */ + + /* ThermalMeter from EEPROM */ + if (rtlefuse->eeprom_thermalmeter < 0x06 || + rtlefuse->eeprom_thermalmeter > 0x1c) + rtlefuse->eeprom_thermalmeter = 0x12; + rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; + + /* check XTAL_K */ + if (rtlefuse->crystalcap == 0xFF) + rtlefuse->crystalcap = 0; + if (rtlefuse->eeprom_regulatory > 3) + rtlefuse->eeprom_regulatory = 0; + + for (i = 0; i < 2; i++) { + switch (tempval[i]) { + case 0: + tempval[i] = 5; + break; + case 1: + tempval[i] = 4; + break; + case 2: + tempval[i] = 3; + break; + case 3: + default: + tempval[i] = 0; + break; + } + } + + rtlefuse->delta_iqk = tempval[0]; + if (tempval[1] > 0) + rtlefuse->delta_lck = tempval[1] - 1; + if (rtlefuse->eeprom_c9 == 0xFF) + rtlefuse->eeprom_c9 = 0x00; + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, + "EEPROMRegulatory = 0x%x\n", rtlefuse->eeprom_regulatory); + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, + "ThermalMeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, + "CrystalCap = 0x%x\n", rtlefuse->crystalcap); + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, + "Delta_IQK = 0x%x Delta_LCK = 0x%x\n", + rtlefuse->delta_iqk, rtlefuse->delta_lck); + + for (rfPath = 0; rfPath < RF6052_MAX_PATH; rfPath++) { + for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { + group = rtl92d_get_chnlgroup_fromarray((u8) ch); + if (ch < CHANNEL_MAX_NUMBER_2G) + rtlefuse->txpwrlevel_cck[rfPath][ch] = + pwrinfo.cck_index[rfPath][group]; + rtlefuse->txpwrlevel_ht40_1s[rfPath][ch] = + pwrinfo.ht40_1sindex[rfPath][group]; + rtlefuse->txpwr_ht20diff[rfPath][ch] = + pwrinfo.ht20indexdiff[rfPath][group]; + rtlefuse->txpwr_legacyhtdiff[rfPath][ch] = + pwrinfo.ofdmindexdiff[rfPath][group]; + rtlefuse->pwrgroup_ht20[rfPath][ch] = + pwrinfo.ht20maxoffset[rfPath][group]; + rtlefuse->pwrgroup_ht40[rfPath][ch] = + pwrinfo.ht40maxoffset[rfPath][group]; + pwr = pwrinfo.ht40_1sindex[rfPath][group]; + diff = pwrinfo.ht40_2sindexdiff[rfPath][group]; + rtlefuse->txpwrlevel_ht40_2s[rfPath][ch] = + (pwr > diff) ? (pwr - diff) : 0; + } + } +} + +static void _rtl92de_read_macphymode_from_prom(struct ieee80211_hw *hw, + u8 *content) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 macphy_crvalue = content[EEPROM_MAC_FUNCTION]; + + if (macphy_crvalue & BIT(3)) { + rtlhal->macphymode = SINGLEMAC_SINGLEPHY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "MacPhyMode SINGLEMAC_SINGLEPHY\n"); + } else { + rtlhal->macphymode = DUALMAC_DUALPHY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "MacPhyMode DUALMAC_DUALPHY\n"); + } +} + +static void _rtl92de_read_macphymode_and_bandtype(struct ieee80211_hw *hw, + u8 *content) +{ + _rtl92de_read_macphymode_from_prom(hw, content); + rtl92d_phy_config_macphymode(hw); + rtl92d_phy_config_macphymode_info(hw); +} + +static void _rtl92de_efuse_update_chip_version(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + enum version_8192d chipver = rtlpriv->rtlhal.version; + u8 cutvalue[2]; + u16 chipvalue; + + rtlpriv->intf_ops->read_efuse_byte(hw, EEPROME_CHIP_VERSION_H, + &cutvalue[1]); + rtlpriv->intf_ops->read_efuse_byte(hw, EEPROME_CHIP_VERSION_L, + &cutvalue[0]); + chipvalue = (cutvalue[1] << 8) | cutvalue[0]; + switch (chipvalue) { + case 0xAA55: + chipver |= CHIP_92D_C_CUT; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "C-CUT!!!\n"); + break; + case 0x9966: + chipver |= CHIP_92D_D_CUT; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "D-CUT!!!\n"); + break; + case 0xCC33: + chipver |= CHIP_92D_E_CUT; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "E-CUT!!!\n"); + break; + default: + chipver |= CHIP_92D_D_CUT; + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Unknown CUT!\n"); + break; + } + rtlpriv->rtlhal.version = chipver; +} + +static void _rtl92de_read_adapter_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u16 i, usvalue; + u8 hwinfo[HWSET_MAX_SIZE]; + u16 eeprom_id; + unsigned long flags; + + if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags); + rtl_efuse_shadow_map_update(hw); + _rtl92de_efuse_update_chip_version(hw); + spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags); + memcpy((void *)hwinfo, (void *)&rtlefuse->efuse_map + [EFUSE_INIT_MAP][0], + HWSET_MAX_SIZE); + } else if (rtlefuse->epromtype == EEPROM_93C46) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "RTL819X Not boot from eeprom, check it !!\n"); + } + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP", + hwinfo, HWSET_MAX_SIZE); + + eeprom_id = *((u16 *)&hwinfo[0]); + if (eeprom_id != RTL8190_EEPROM_ID) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "EEPROM ID(%#x) is invalid!!\n", eeprom_id); + rtlefuse->autoload_failflag = true; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + } + if (rtlefuse->autoload_failflag) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "RTL819X Not boot from eeprom, check it !!\n"); + return; + } + rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; + _rtl92de_read_macphymode_and_bandtype(hw, hwinfo); + + /* VID, DID SE 0xA-D */ + rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; + rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; + rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; + rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROMId = 0x%4x\n", eeprom_id); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); + + /* Read Permanent MAC address */ + if (rtlhal->interfaceindex == 0) { + for (i = 0; i < 6; i += 2) { + usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_MAC0_92D + i]; + *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; + } + } else { + for (i = 0; i < 6; i += 2) { + usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_MAC1_92D + i]; + *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; + } + } + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, + rtlefuse->dev_addr); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%pM\n", rtlefuse->dev_addr); + _rtl92de_read_txpower_info(hw, rtlefuse->autoload_failflag, hwinfo); + + /* Read Channel Plan */ + switch (rtlhal->bandset) { + case BAND_ON_2_4G: + rtlefuse->channel_plan = COUNTRY_CODE_TELEC; + break; + case BAND_ON_5G: + rtlefuse->channel_plan = COUNTRY_CODE_FCC; + break; + case BAND_ON_BOTH: + rtlefuse->channel_plan = COUNTRY_CODE_FCC; + break; + default: + rtlefuse->channel_plan = COUNTRY_CODE_FCC; + break; + } + rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; + rtlefuse->txpwr_fromeprom = true; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); +} + +void rtl92de_read_eeprom_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_u1b; + + rtlhal->version = _rtl92de_read_chip_version(hw); + tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); + rtlefuse->autoload_status = tmp_u1b; + if (tmp_u1b & BIT(4)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); + rtlefuse->epromtype = EEPROM_93C46; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); + rtlefuse->epromtype = EEPROM_BOOT_EFUSE; + } + if (tmp_u1b & BIT(5)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + + rtlefuse->autoload_failflag = false; + _rtl92de_read_adapter_info(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); + } + return; +} + +static void rtl92de_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 ratr_value; + u8 ratr_index = 0; + u8 nmode = mac->ht_enable; + u8 mimo_ps = IEEE80211_SMPS_OFF; + u16 shortgi_rate; + u32 tmp_ratr_value; + u8 curtxbw_40mhz = mac->bw_40; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = mac->mode; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_value = sta->supp_rates[1] << 4; + else + ratr_value = sta->supp_rates[0]; + ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_A: + ratr_value &= 0x00000FF0; + break; + case WIRELESS_MODE_B: + if (ratr_value & 0x0000000c) + ratr_value &= 0x0000000d; + else + ratr_value &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_value &= 0x00000FF5; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + nmode = 1; + if (mimo_ps == IEEE80211_SMPS_STATIC) { + ratr_value &= 0x0007F005; + } else { + u32 ratr_mask; + + if (get_rf_type(rtlphy) == RF_1T2R || + get_rf_type(rtlphy) == RF_1T1R) { + ratr_mask = 0x000ff005; + } else { + ratr_mask = 0x0f0ff005; + } + + ratr_value &= ratr_mask; + } + break; + default: + if (rtlphy->rf_type == RF_1T2R) + ratr_value &= 0x000ff0ff; + else + ratr_value &= 0x0f0ff0ff; + + break; + } + ratr_value &= 0x0FFFFFFF; + if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) || + (!curtxbw_40mhz && curshortgi_20mhz))) { + ratr_value |= 0x10000000; + tmp_ratr_value = (ratr_value >> 12); + for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { + if ((1 << shortgi_rate) & tmp_ratr_value) + break; + } + shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | + (shortgi_rate << 4) | (shortgi_rate); + } + rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n", + rtl_read_dword(rtlpriv, REG_ARFR0)); +} + +static void rtl92de_update_hal_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u32 ratr_bitmap; + u8 ratr_index; + u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = 0; + bool shortgi = false; + u32 value[2]; + u8 macid = 0; + u8 mimo_ps = IEEE80211_SMPS_OFF; + + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + mimo_ps = sta_entry->mimo_ps; + wirelessmode = sta_entry->wireless_mode; + if (mac->opmode == NL80211_IFTYPE_STATION) + curtxbw_40mhz = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + macid = sta->aid + 1; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_bitmap = sta->supp_rates[1] << 4; + else + ratr_bitmap = sta->supp_rates[0]; + ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + ratr_index = RATR_INX_WIRELESS_B; + if (ratr_bitmap & 0x0000000c) + ratr_bitmap &= 0x0000000d; + else + ratr_bitmap &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_index = RATR_INX_WIRELESS_GB; + + if (rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if (rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + break; + case WIRELESS_MODE_A: + ratr_index = RATR_INX_WIRELESS_G; + ratr_bitmap &= 0x00000ff0; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + if (wirelessmode == WIRELESS_MODE_N_24G) + ratr_index = RATR_INX_WIRELESS_NGB; + else + ratr_index = RATR_INX_WIRELESS_NG; + if (mimo_ps == IEEE80211_SMPS_STATIC) { + if (rssi_level == 1) + ratr_bitmap &= 0x00070000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0007f000; + else + ratr_bitmap &= 0x0007f005; + } else { + if (rtlphy->rf_type == RF_1T2R || + rtlphy->rf_type == RF_1T1R) { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff005; + } + } else { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x0f0f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f0ff000; + else + ratr_bitmap &= 0x0f0ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x0f0f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f0ff000; + else + ratr_bitmap &= 0x0f0ff005; + } + } + } + if ((curtxbw_40mhz && curshortgi_40mhz) || + (!curtxbw_40mhz && curshortgi_20mhz)) { + + if (macid == 0) + shortgi = true; + else if (macid == 1) + shortgi = false; + } + break; + default: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rtlphy->rf_type == RF_1T2R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0f0ff0ff; + break; + } + + value[0] = (ratr_bitmap & 0x0fffffff) | (ratr_index << 28); + value[1] = macid | (shortgi ? 0x20 : 0x00) | 0x80; + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "ratr_bitmap :%x value0:%x value1:%x\n", + ratr_bitmap, value[0], value[1]); + rtl92d_fill_h2c_cmd(hw, H2C_RA_MASK, 5, (u8 *) value); + if (macid != 0) + sta_entry->ratr_index = ratr_index; +} + +void rtl92de_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->dm.useramask) + rtl92de_update_hal_rate_mask(hw, sta, rssi_level); + else + rtl92de_update_hal_rate_table(hw, sta); +} + +void rtl92de_update_channel_access_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 sifs_timer; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, + &mac->slot_time); + if (!mac->ht_enable) + sifs_timer = 0x0a0a; + else + sifs_timer = 0x1010; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); +} + +bool rtl92de_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + enum rf_pwrstate e_rfpowerstate_toset; + u8 u1tmp; + bool actuallyset = false; + unsigned long flag; + + if (rtlpci->being_init_adapter) + return false; + if (ppsc->swrf_processing) + return false; + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + if (ppsc->rfchange_inprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + return false; + } else { + ppsc->rfchange_inprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv, + REG_MAC_PINMUX_CFG) & ~(BIT(3))); + u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); + e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF; + if (ppsc->hwradiooff && (e_rfpowerstate_toset == ERFON)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "GPIOChangeRF - HW Radio ON, RF ON\n"); + e_rfpowerstate_toset = ERFON; + ppsc->hwradiooff = false; + actuallyset = true; + } else if (!ppsc->hwradiooff && (e_rfpowerstate_toset == ERFOFF)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "GPIOChangeRF - HW Radio OFF, RF OFF\n"); + e_rfpowerstate_toset = ERFOFF; + ppsc->hwradiooff = true; + actuallyset = true; + } + if (actuallyset) { + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } else { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + *valid = 1; + return !ppsc->hwradiooff; +} + +void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 *macaddr = p_macaddr; + u32 entry_id; + bool is_pairwise = false; + static u8 cam_const_addr[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} + }; + static u8 cam_const_broad[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (clear_all) { + u8 idx; + u8 cam_offset = 0; + u8 clear_number = 5; + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); + for (idx = 0; idx < clear_number; idx++) { + rtl_cam_mark_invalid(hw, cam_offset + idx); + rtl_cam_empty_entry(hw, cam_offset + idx); + + if (idx < 5) { + memset(rtlpriv->sec.key_buf[idx], 0, + MAX_KEY_LEN); + rtlpriv->sec.key_len[idx] = 0; + } + } + } else { + switch (enc_algo) { + case WEP40_ENCRYPTION: + enc_algo = CAM_WEP40; + break; + case WEP104_ENCRYPTION: + enc_algo = CAM_WEP104; + break; + case TKIP_ENCRYPTION: + enc_algo = CAM_TKIP; + break; + case AESCCMP_ENCRYPTION: + enc_algo = CAM_AES; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + enc_algo = CAM_TKIP; + break; + } + if (is_wepkey || rtlpriv->sec.use_defaultkey) { + macaddr = cam_const_addr[key_index]; + entry_id = key_index; + } else { + if (is_group) { + macaddr = cam_const_broad; + entry_id = key_index; + } else { + if (mac->opmode == NL80211_IFTYPE_AP) { + entry_id = rtl_cam_get_free_entry(hw, + p_macaddr); + if (entry_id >= TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, COMP_SEC, + DBG_EMERG, + "Can not find free hw security cam entry\n"); + return; + } + } else { + entry_id = CAM_PAIRWISE_KEY_POSITION; + } + key_index = PAIRWISE_KEYIDX; + is_pairwise = true; + } + } + if (rtlpriv->sec.key_len[key_index] == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "delete one entry, entry_id is %d\n", + entry_id); + if (mac->opmode == NL80211_IFTYPE_AP) + rtl_cam_del_entry(hw, p_macaddr); + rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "The insert KEY length is %d\n", + rtlpriv->sec.key_len[PAIRWISE_KEYIDX]); + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, + "The insert KEY is %x %x\n", + rtlpriv->sec.key_buf[0][0], + rtlpriv->sec.key_buf[0][1]); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "add one entry\n"); + if (is_pairwise) { + RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, + "Pairwise Key content", + rtlpriv->sec.pairwise_key, + rtlpriv-> + sec.key_len[PAIRWISE_KEYIDX]); + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set Pairwise key\n"); + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv-> + sec.key_buf[key_index]); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set group key\n"); + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_cam_add_one_entry(hw, + rtlefuse->dev_addr, + PAIRWISE_KEYIDX, + CAM_PAIRWISE_KEY_POSITION, + enc_algo, CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf + [entry_id]); + } + } + } +} + +void rtl92de_suspend(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->rtlhal.macphyctl_reg = rtl_read_byte(rtlpriv, + REG_MAC_PHY_CTRL_NORMAL); +} + +void rtl92de_resume(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL, + rtlpriv->rtlhal.macphyctl_reg); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h new file mode 100644 index 000000000000..1bc7b1a96d4a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92DE_HW_H__ +#define __RTL92DE_HW_H__ + +void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl92de_read_eeprom_info(struct ieee80211_hw *hw); +void rtl92de_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb); +int rtl92de_hw_init(struct ieee80211_hw *hw); +void rtl92de_card_disable(struct ieee80211_hw *hw); +void rtl92de_enable_interrupt(struct ieee80211_hw *hw); +void rtl92de_disable_interrupt(struct ieee80211_hw *hw); +int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); +void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); +void rtl92de_set_qos(struct ieee80211_hw *hw, int aci); +void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw); +void rtl92de_set_beacon_interval(struct ieee80211_hw *hw); +void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); +void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl92de_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); +void rtl92de_update_channel_access_setting(struct ieee80211_hw *hw); +bool rtl92de_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); +void rtl92de_enable_hw_security_config(struct ieee80211_hw *hw); +void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all); + +void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, u16 offset, u32 value, + u8 direct); +u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, u8 direct); +void rtl92de_suspend(struct ieee80211_hw *hw); +void rtl92de_resume(struct ieee80211_hw *hw); +void rtl92d_linked_set_reg(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c new file mode 100644 index 000000000000..76a57ae4af3e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.c @@ -0,0 +1,159 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "reg.h" +#include "led.h" + +static void _rtl92ce_init_led(struct ieee80211_hw *hw, + struct rtl_led *pled, enum rtl_led_pin ledpin) +{ + pled->hw = hw; + pled->ledpin = ledpin; + pled->ledon = false; +} + +void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u8 ledcfg; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", + REG_LEDCFG2, pled->ledpin); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + + if ((rtlpriv->efuse.eeprom_did == 0x8176) || + (rtlpriv->efuse.eeprom_did == 0x8193)) + /* BIT7 of REG_LEDCFG2 should be set to + * make sure we could emit the led2. */ + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) | + BIT(7) | BIT(5) | BIT(6)); + else + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) | + BIT(7) | BIT(5)); + break; + case LED_PIN_LED1: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); + + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + pled->ledon = true; +} + +void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + u8 ledcfg; + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", + REG_LEDCFG2, pled->ledpin); + + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg &= 0xf0; + if (pcipriv->ledctl.led_opendrain) + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(1) | BIT(5) | BIT(6))); + else + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(3) | BIT(5) | BIT(6))); + break; + case LED_PIN_LED1: + ledcfg &= 0x0f; + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + pled->ledon = false; +} + +void rtl92de_init_sw_leds(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); + _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); +} + +static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + switch (ledaction) { + case LED_CTL_POWER_ON: + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + rtl92de_sw_led_on(hw, pLed0); + break; + case LED_CTL_POWER_OFF: + rtl92de_sw_led_off(hw, pLed0); + break; + default: + break; + } +} + +void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && + (ledaction == LED_CTL_TX || + ledaction == LED_CTL_RX || + ledaction == LED_CTL_SITE_SURVEY || + ledaction == LED_CTL_LINK || + ledaction == LED_CTL_NO_LINK || + ledaction == LED_CTL_START_TO_LINK || + ledaction == LED_CTL_POWER_ON)) { + return; + } + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n", ledaction); + + _rtl92ce_sw_led_control(hw, ledaction); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h new file mode 100644 index 000000000000..a29df30c3025 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/led.h @@ -0,0 +1,38 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CE_LED_H__ +#define __RTL92CE_LED_H__ + +void rtl92de_init_sw_leds(struct ieee80211_hw *hw); +void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c new file mode 100644 index 000000000000..bb06fe836fe7 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c @@ -0,0 +1,3609 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../ps.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "table.h" +#include "sw.h" +#include "hw.h" + +#define MAX_RF_IMR_INDEX 12 +#define MAX_RF_IMR_INDEX_NORMAL 13 +#define RF_REG_NUM_FOR_C_CUT_5G 6 +#define RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA 7 +#define RF_REG_NUM_FOR_C_CUT_2G 5 +#define RF_CHNL_NUM_5G 19 +#define RF_CHNL_NUM_5G_40M 17 +#define TARGET_CHNL_NUM_5G 221 +#define TARGET_CHNL_NUM_2G 14 +#define CV_CURVE_CNT 64 + +static u32 rf_reg_for_5g_swchnl_normal[MAX_RF_IMR_INDEX_NORMAL] = { + 0, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x0 +}; + +static u8 rf_reg_for_c_cut_5g[RF_REG_NUM_FOR_C_CUT_5G] = { + RF_SYN_G1, RF_SYN_G2, RF_SYN_G3, RF_SYN_G4, RF_SYN_G5, RF_SYN_G6 +}; + +static u8 rf_reg_for_c_cut_2g[RF_REG_NUM_FOR_C_CUT_2G] = { + RF_SYN_G1, RF_SYN_G2, RF_SYN_G3, RF_SYN_G7, RF_SYN_G8 +}; + +static u8 rf_for_c_cut_5g_internal_pa[RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA] = { + 0x0B, 0x48, 0x49, 0x4B, 0x03, 0x04, 0x0E +}; + +static u32 rf_reg_mask_for_c_cut_2g[RF_REG_NUM_FOR_C_CUT_2G] = { + BIT(19) | BIT(18) | BIT(17) | BIT(14) | BIT(1), + BIT(10) | BIT(9), + BIT(18) | BIT(17) | BIT(16) | BIT(1), + BIT(2) | BIT(1), + BIT(15) | BIT(14) | BIT(13) | BIT(12) | BIT(11) +}; + +static u8 rf_chnl_5g[RF_CHNL_NUM_5G] = { + 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, + 112, 116, 120, 124, 128, 132, 136, 140 +}; + +static u8 rf_chnl_5g_40m[RF_CHNL_NUM_5G_40M] = { + 38, 42, 46, 50, 54, 58, 62, 102, 106, 110, 114, + 118, 122, 126, 130, 134, 138 +}; +static u32 rf_reg_pram_c_5g[5][RF_REG_NUM_FOR_C_CUT_5G] = { + {0xE43BE, 0xFC638, 0x77C0A, 0xDE471, 0xd7110, 0x8EB04}, + {0xE43BE, 0xFC078, 0xF7C1A, 0xE0C71, 0xD7550, 0xAEB04}, + {0xE43BF, 0xFF038, 0xF7C0A, 0xDE471, 0xE5550, 0xAEB04}, + {0xE43BF, 0xFF079, 0xF7C1A, 0xDE471, 0xE5550, 0xAEB04}, + {0xE43BF, 0xFF038, 0xF7C1A, 0xDE471, 0xd7550, 0xAEB04} +}; + +static u32 rf_reg_param_for_c_cut_2g[3][RF_REG_NUM_FOR_C_CUT_2G] = { + {0x643BC, 0xFC038, 0x77C1A, 0x41289, 0x01840}, + {0x643BC, 0xFC038, 0x07C1A, 0x41289, 0x01840}, + {0x243BC, 0xFC438, 0x07C1A, 0x4128B, 0x0FC41} +}; + +static u32 rf_syn_g4_for_c_cut_2g = 0xD1C31 & 0x7FF; + +static u32 rf_pram_c_5g_int_pa[3][RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA] = { + {0x01a00, 0x40443, 0x00eb5, 0x89bec, 0x94a12, 0x94a12, 0x94a12}, + {0x01800, 0xc0443, 0x00730, 0x896ee, 0x94a52, 0x94a52, 0x94a52}, + {0x01800, 0xc0443, 0x00730, 0x896ee, 0x94a12, 0x94a12, 0x94a12} +}; + +/* [mode][patha+b][reg] */ +static u32 rf_imr_param_normal[1][3][MAX_RF_IMR_INDEX_NORMAL] = { + { + /* channel 1-14. */ + { + 0x70000, 0x00ff0, 0x4400f, 0x00ff0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x64888, 0xe266c, 0x00090, 0x22fff + }, + /* path 36-64 */ + { + 0x70000, 0x22880, 0x4470f, 0x55880, 0x00070, 0x88000, + 0x0, 0x88080, 0x70000, 0x64a82, 0xe466c, 0x00090, + 0x32c9a + }, + /* 100 -165 */ + { + 0x70000, 0x44880, 0x4477f, 0x77880, 0x00070, 0x88000, + 0x0, 0x880b0, 0x0, 0x64b82, 0xe466c, 0x00090, 0x32c9a + } + } +}; + +static u32 curveindex_5g[TARGET_CHNL_NUM_5G] = {0}; + +static u32 curveindex_2g[TARGET_CHNL_NUM_2G] = {0}; + +static u32 targetchnl_5g[TARGET_CHNL_NUM_5G] = { + 25141, 25116, 25091, 25066, 25041, + 25016, 24991, 24966, 24941, 24917, + 24892, 24867, 24843, 24818, 24794, + 24770, 24765, 24721, 24697, 24672, + 24648, 24624, 24600, 24576, 24552, + 24528, 24504, 24480, 24457, 24433, + 24409, 24385, 24362, 24338, 24315, + 24291, 24268, 24245, 24221, 24198, + 24175, 24151, 24128, 24105, 24082, + 24059, 24036, 24013, 23990, 23967, + 23945, 23922, 23899, 23876, 23854, + 23831, 23809, 23786, 23764, 23741, + 23719, 23697, 23674, 23652, 23630, + 23608, 23586, 23564, 23541, 23519, + 23498, 23476, 23454, 23432, 23410, + 23388, 23367, 23345, 23323, 23302, + 23280, 23259, 23237, 23216, 23194, + 23173, 23152, 23130, 23109, 23088, + 23067, 23046, 23025, 23003, 22982, + 22962, 22941, 22920, 22899, 22878, + 22857, 22837, 22816, 22795, 22775, + 22754, 22733, 22713, 22692, 22672, + 22652, 22631, 22611, 22591, 22570, + 22550, 22530, 22510, 22490, 22469, + 22449, 22429, 22409, 22390, 22370, + 22350, 22336, 22310, 22290, 22271, + 22251, 22231, 22212, 22192, 22173, + 22153, 22134, 22114, 22095, 22075, + 22056, 22037, 22017, 21998, 21979, + 21960, 21941, 21921, 21902, 21883, + 21864, 21845, 21826, 21807, 21789, + 21770, 21751, 21732, 21713, 21695, + 21676, 21657, 21639, 21620, 21602, + 21583, 21565, 21546, 21528, 21509, + 21491, 21473, 21454, 21436, 21418, + 21400, 21381, 21363, 21345, 21327, + 21309, 21291, 21273, 21255, 21237, + 21219, 21201, 21183, 21166, 21148, + 21130, 21112, 21095, 21077, 21059, + 21042, 21024, 21007, 20989, 20972, + 25679, 25653, 25627, 25601, 25575, + 25549, 25523, 25497, 25471, 25446, + 25420, 25394, 25369, 25343, 25318, + 25292, 25267, 25242, 25216, 25191, + 25166 +}; + +/* channel 1~14 */ +static u32 targetchnl_2g[TARGET_CHNL_NUM_2G] = { + 26084, 26030, 25976, 25923, 25869, 25816, 25764, + 25711, 25658, 25606, 25554, 25502, 25451, 25328 +}; + +static u32 _rtl92d_phy_calculate_bit_shift(u32 bitmask) +{ + u32 i; + + for (i = 0; i <= 31; i++) { + if (((bitmask >> i) & 0x1) == 1) + break; + } + + return i; +} + +u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u32 returnvalue, originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n", + regaddr, bitmask); + if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob) { + u8 dbi_direct = 0; + + /* mac1 use phy0 read radio_b. */ + /* mac0 use phy1 read radio_b. */ + if (rtlhal->during_mac1init_radioa) + dbi_direct = BIT(3); + else if (rtlhal->during_mac0init_radiob) + dbi_direct = BIT(3) | BIT(2); + originalvalue = rtl92de_read_dword_dbi(hw, (u16)regaddr, + dbi_direct); + } else { + originalvalue = rtl_read_dword(rtlpriv, regaddr); + } + bitshift = _rtl92d_phy_calculate_bit_shift(bitmask); + returnvalue = (originalvalue & bitmask) >> bitshift; + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "BBR MASK=0x%x Addr[0x%x]=0x%x\n", + bitmask, regaddr, originalvalue); + return returnvalue; +} + +void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 dbi_direct = 0; + u32 originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); + if (rtlhal->during_mac1init_radioa) + dbi_direct = BIT(3); + else if (rtlhal->during_mac0init_radiob) + /* mac0 use phy1 write radio_b. */ + dbi_direct = BIT(3) | BIT(2); + if (bitmask != MASKDWORD) { + if (rtlhal->during_mac1init_radioa || + rtlhal->during_mac0init_radiob) + originalvalue = rtl92de_read_dword_dbi(hw, + (u16) regaddr, + dbi_direct); + else + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl92d_phy_calculate_bit_shift(bitmask); + data = ((originalvalue & (~bitmask)) | (data << bitshift)); + } + if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob) + rtl92de_write_dword_dbi(hw, (u16) regaddr, data, dbi_direct); + else + rtl_write_dword(rtlpriv, regaddr, data); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); +} + +static u32 _rtl92d_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset) +{ + + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + u32 newoffset; + u32 tmplong, tmplong2; + u8 rfpi_enable = 0; + u32 retvalue; + + newoffset = offset; + tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); + if (rfpath == RF90_PATH_A) + tmplong2 = tmplong; + else + tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); + tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | + (newoffset << 23) | BLSSIREADEDGE; + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, + tmplong & (~BLSSIREADEDGE)); + udelay(10); + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); + udelay(50); + udelay(50); + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, + tmplong | BLSSIREADEDGE); + udelay(10); + if (rfpath == RF90_PATH_A) + rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, + BIT(8)); + else if (rfpath == RF90_PATH_B) + rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, + BIT(8)); + if (rfpi_enable) + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, + BLSSIREADBACKDATA); + else + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, + BLSSIREADBACKDATA); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x] = 0x%x\n", + rfpath, pphyreg->rf_rb, retvalue); + return retvalue; +} + +static void _rtl92d_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 offset, u32 data) +{ + u32 data_and_addr; + u32 newoffset; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + + newoffset = offset; + /* T65 RF */ + data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; + rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf3wire_offset, data_and_addr); +} + +u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, readback_value, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", + regaddr, rfpath, bitmask); + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + original_value = _rtl92d_phy_rf_serial_read(hw, rfpath, regaddr); + bitshift = _rtl92d_phy_calculate_bit_shift(bitmask); + readback_value = (original_value & bitmask) >> bitshift; + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", + regaddr, rfpath, bitmask, original_value); + return readback_value; +} + +void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 original_value, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); + if (bitmask == 0) + return; + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + if (rtlphy->rf_mode != RF_OP_BY_FW) { + if (bitmask != RFREG_OFFSET_MASK) { + original_value = _rtl92d_phy_rf_serial_read(hw, + rfpath, regaddr); + bitshift = _rtl92d_phy_calculate_bit_shift(bitmask); + data = ((original_value & (~bitmask)) | + (data << bitshift)); + } + _rtl92d_phy_rf_serial_write(hw, rfpath, regaddr, data); + } + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); +} + +bool rtl92d_phy_mac_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + u32 arraylength; + u32 *ptrarray; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n"); + arraylength = MAC_2T_ARRAYLENGTH; + ptrarray = rtl8192de_mac_2tarray; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:Rtl819XMAC_Array\n"); + for (i = 0; i < arraylength; i = i + 2) + rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); + if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) { + /* improve 2-stream TX EVM */ + /* rtl_write_byte(rtlpriv, 0x14,0x71); */ + /* AMPDU aggregation number 9 */ + /* rtl_write_word(rtlpriv, REG_MAX_AGGR_NUM, MAX_AGGR_NUM); */ + rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x0B); + } else { + /* 92D need to test to decide the num. */ + rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x07); + } + return true; +} + +static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + /* RF Interface Sowrtware Control */ + /* 16 LSBs if read 32-bit from 0x870 */ + rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; + /* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */ + rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; + /* 16 LSBs if read 32-bit from 0x874 */ + rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; + /* 16 MSBs if read 32-bit from 0x874 (16-bit for 0x876) */ + + rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; + /* RF Interface Readback Value */ + /* 16 LSBs if read 32-bit from 0x8E0 */ + rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; + /* 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) */ + rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; + /* 16 LSBs if read 32-bit from 0x8E4 */ + rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; + /* 16 MSBs if read 32-bit from 0x8E4 (16-bit for 0x8E6) */ + rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; + + /* RF Interface Output (and Enable) */ + /* 16 LSBs if read 32-bit from 0x860 */ + rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; + /* 16 LSBs if read 32-bit from 0x864 */ + rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; + + /* RF Interface (Output and) Enable */ + /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */ + rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; + /* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */ + rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; + + /* Addr of LSSI. Wirte RF register by driver */ + /* LSSI Parameter */ + rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = + RFPGA0_XA_LSSIPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = + RFPGA0_XB_LSSIPARAMETER; + + /* RF parameter */ + /* BB Band Select */ + rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; + + /* Tx AGC Gain Stage (same for all path. Should we remove this?) */ + /* Tx gain stage */ + rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; + /* Tx gain stage */ + rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; + /* Tx gain stage */ + rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; + /* Tx gain stage */ + rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; + + /* Tranceiver A~D HSSI Parameter-1 */ + /* wire control parameter1 */ + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; + /* wire control parameter1 */ + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; + + /* Tranceiver A~D HSSI Parameter-2 */ + /* wire control parameter2 */ + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; + /* wire control parameter2 */ + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; + + /* RF switch Control */ + /* TR/Ant switch control */ + rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; + + /* AGC control 1 */ + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; + + /* AGC control 2 */ + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; + + /* RX AFE control 1 */ + rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; + + /*RX AFE control 1 */ + rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; + + /* Tx AFE control 1 */ + rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATxIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTxIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTxIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTxIQIMBALANCE; + + /* Tx AFE control 2 */ + rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATxAFE; + rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTxAFE; + rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTxAFE; + rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTxAFE; + + /* Tranceiver LSSI Readback SI mode */ + rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK; + + /* Tranceiver LSSI Readback PI mode */ + rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVERA_HSPI_READBACK; + rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVERB_HSPI_READBACK; +} + +static bool _rtl92d_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype) +{ + int i; + u32 *phy_regarray_table; + u32 *agctab_array_table = NULL; + u32 *agctab_5garray_table; + u16 phy_reg_arraylen, agctab_arraylen = 0, agctab_5garraylen; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + /* Normal chip,Mac0 use AGC_TAB.txt for 2G and 5G band. */ + if (rtlhal->interfaceindex == 0) { + agctab_arraylen = AGCTAB_ARRAYLENGTH; + agctab_array_table = rtl8192de_agctab_array; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + " ===> phy:MAC0, Rtl819XAGCTAB_Array\n"); + } else { + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + agctab_arraylen = AGCTAB_2G_ARRAYLENGTH; + agctab_array_table = rtl8192de_agctab_2garray; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + " ===> phy:MAC1, Rtl819XAGCTAB_2GArray\n"); + } else { + agctab_5garraylen = AGCTAB_5G_ARRAYLENGTH; + agctab_5garray_table = rtl8192de_agctab_5garray; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + " ===> phy:MAC1, Rtl819XAGCTAB_5GArray\n"); + + } + } + phy_reg_arraylen = PHY_REG_2T_ARRAYLENGTH; + phy_regarray_table = rtl8192de_phy_reg_2tarray; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + " ===> phy:Rtl819XPHY_REG_Array_PG\n"); + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_reg_arraylen; i = i + 2) { + rtl_addr_delay(phy_regarray_table[i]); + rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD, + phy_regarray_table[i + 1]); + udelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", + phy_regarray_table[i], + phy_regarray_table[i + 1]); + } + } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { + if (rtlhal->interfaceindex == 0) { + for (i = 0; i < agctab_arraylen; i = i + 2) { + rtl_set_bbreg(hw, agctab_array_table[i], + MASKDWORD, + agctab_array_table[i + 1]); + /* Add 1us delay between BB/RF register + * setting. */ + udelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The Rtl819XAGCTAB_Array_Table[0] is %ul Rtl819XPHY_REGArray[1] is %ul\n", + agctab_array_table[i], + agctab_array_table[i + 1]); + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Normal Chip, MAC0, load Rtl819XAGCTAB_Array\n"); + } else { + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + for (i = 0; i < agctab_arraylen; i = i + 2) { + rtl_set_bbreg(hw, agctab_array_table[i], + MASKDWORD, + agctab_array_table[i + 1]); + /* Add 1us delay between BB/RF register + * setting. */ + udelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The Rtl819XAGCTAB_Array_Table[0] is %ul Rtl819XPHY_REGArray[1] is %ul\n", + agctab_array_table[i], + agctab_array_table[i + 1]); + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Load Rtl819XAGCTAB_2GArray\n"); + } else { + for (i = 0; i < agctab_5garraylen; i = i + 2) { + rtl_set_bbreg(hw, + agctab_5garray_table[i], + MASKDWORD, + agctab_5garray_table[i + 1]); + /* Add 1us delay between BB/RF registeri + * setting. */ + udelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The Rtl819XAGCTAB_5GArray_Table[0] is %ul Rtl819XPHY_REGArray[1] is %ul\n", + agctab_5garray_table[i], + agctab_5garray_table[i + 1]); + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Load Rtl819XAGCTAB_5GArray\n"); + } + } + } + return true; +} + +static void _rtl92d_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, + u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + int index; + + if (regaddr == RTXAGC_A_RATE18_06) + index = 0; + else if (regaddr == RTXAGC_A_RATE54_24) + index = 1; + else if (regaddr == RTXAGC_A_CCK1_MCS32) + index = 6; + else if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) + index = 7; + else if (regaddr == RTXAGC_A_MCS03_MCS00) + index = 2; + else if (regaddr == RTXAGC_A_MCS07_MCS04) + index = 3; + else if (regaddr == RTXAGC_A_MCS11_MCS08) + index = 4; + else if (regaddr == RTXAGC_A_MCS15_MCS12) + index = 5; + else if (regaddr == RTXAGC_B_RATE18_06) + index = 8; + else if (regaddr == RTXAGC_B_RATE54_24) + index = 9; + else if (regaddr == RTXAGC_B_CCK1_55_MCS32) + index = 14; + else if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) + index = 15; + else if (regaddr == RTXAGC_B_MCS03_MCS00) + index = 10; + else if (regaddr == RTXAGC_B_MCS07_MCS04) + index = 11; + else if (regaddr == RTXAGC_B_MCS11_MCS08) + index = 12; + else if (regaddr == RTXAGC_B_MCS15_MCS12) + index = 13; + else + return; + + rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%x\n", + rtlphy->pwrgroup_cnt, index, + rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index]); + if (index == 13) + rtlphy->pwrgroup_cnt++; +} + +static bool _rtl92d_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int i; + u32 *phy_regarray_table_pg; + u16 phy_regarray_pg_len; + + phy_regarray_pg_len = PHY_REG_ARRAY_PG_LENGTH; + phy_regarray_table_pg = rtl8192de_phy_reg_array_pg; + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_regarray_pg_len; i = i + 3) { + rtl_addr_delay(phy_regarray_table_pg[i]); + _rtl92d_store_pwrindex_diffrate_offset(hw, + phy_regarray_table_pg[i], + phy_regarray_table_pg[i + 1], + phy_regarray_table_pg[i + 2]); + } + } else { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "configtype != BaseBand_Config_PHY_REG\n"); + } + return true; +} + +static bool _rtl92d_phy_bb_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + bool rtstatus = true; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "==>\n"); + rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw, + BASEBAND_CONFIG_PHY_REG); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!\n"); + return false; + } + + /* if (rtlphy->rf_type == RF_1T2R) { + * _rtl92c_phy_bb_config_1t(hw); + * RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Config to 1T!!\n"); + *} */ + + if (rtlefuse->autoload_failflag == false) { + rtlphy->pwrgroup_cnt = 0; + rtstatus = _rtl92d_phy_config_bb_with_pgheaderfile(hw, + BASEBAND_CONFIG_PHY_REG); + } + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!\n"); + return false; + } + rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw, + BASEBAND_CONFIG_AGC_TAB); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); + return false; + } + rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, 0x200)); + + return true; +} + +bool rtl92d_phy_bb_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 regval; + u32 regvaldw; + u8 value; + + _rtl92d_phy_init_bb_rf_register_definition(hw); + regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, + regval | BIT(13) | BIT(0) | BIT(1)); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); + /* 0x1f bit7 bit6 represent for mac0/mac1 driver ready */ + value = rtl_read_byte(rtlpriv, REG_RF_CTRL); + rtl_write_byte(rtlpriv, REG_RF_CTRL, value | RF_EN | RF_RSTB | + RF_SDMRSTB); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA | + FEN_DIO_PCIE | FEN_BB_GLB_RSTn | FEN_BBRSTB); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); + if (!(IS_92D_SINGLEPHY(rtlpriv->rtlhal.version))) { + regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); + rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); + } + + return _rtl92d_phy_bb_config(hw); +} + +bool rtl92d_phy_rf_config(struct ieee80211_hw *hw) +{ + return rtl92d_phy_rf6052_config(hw); +} + +bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum rf_content content, + enum radio_path rfpath) +{ + int i; + u32 *radioa_array_table; + u32 *radiob_array_table; + u16 radioa_arraylen, radiob_arraylen; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + radioa_arraylen = RADIOA_2T_ARRAYLENGTH; + radioa_array_table = rtl8192de_radioa_2tarray; + radiob_arraylen = RADIOB_2T_ARRAYLENGTH; + radiob_array_table = rtl8192de_radiob_2tarray; + if (rtlpriv->efuse.internal_pa_5g[0]) { + radioa_arraylen = RADIOA_2T_INT_PA_ARRAYLENGTH; + radioa_array_table = rtl8192de_radioa_2t_int_paarray; + } + if (rtlpriv->efuse.internal_pa_5g[1]) { + radiob_arraylen = RADIOB_2T_INT_PA_ARRAYLENGTH; + radiob_array_table = rtl8192de_radiob_2t_int_paarray; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "PHY_ConfigRFWithHeaderFile() Radio_A:Rtl819XRadioA_1TArray\n"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "PHY_ConfigRFWithHeaderFile() Radio_B:Rtl819XRadioB_1TArray\n"); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath); + + /* this only happens when DMDP, mac0 start on 2.4G, + * mac1 start on 5G, mac 0 has to set phy0&phy1 + * pathA or mac1 has to set phy0&phy1 pathA */ + if ((content == radiob_txt) && (rfpath == RF90_PATH_A)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + " ===> althougth Path A, we load radiob.txt\n"); + radioa_arraylen = radiob_arraylen; + radioa_array_table = radiob_array_table; + } + switch (rfpath) { + case RF90_PATH_A: + for (i = 0; i < radioa_arraylen; i = i + 2) { + rtl_rfreg_delay(hw, rfpath, radioa_array_table[i], + RFREG_OFFSET_MASK, + radioa_array_table[i + 1]); + } + break; + case RF90_PATH_B: + for (i = 0; i < radiob_arraylen; i = i + 2) { + rtl_rfreg_delay(hw, rfpath, radiob_array_table[i], + RFREG_OFFSET_MASK, + radiob_array_table[i + 1]); + } + break; + case RF90_PATH_C: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + case RF90_PATH_D: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + return true; +} + +void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + rtlphy->default_initialgain[0] = + (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[1] = + (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[2] = + (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[3] = + (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", + rtlphy->default_initialgain[0], + rtlphy->default_initialgain[1], + rtlphy->default_initialgain[2], + rtlphy->default_initialgain[3]); + rtlphy->framesync = (u8)rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, + MASKBYTE0); + rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, + MASKDWORD); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default framesync (0x%x) = 0x%x\n", + ROFDM0_RXDETECTOR3, rtlphy->framesync); +} + +static void _rtl92d_get_txpower_index(struct ieee80211_hw *hw, u8 channel, + u8 *cckpowerlevel, u8 *ofdmpowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 index = (channel - 1); + + /* 1. CCK */ + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + /* RF-A */ + cckpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_cck[RF90_PATH_A][index]; + /* RF-B */ + cckpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_cck[RF90_PATH_B][index]; + } else { + cckpowerlevel[RF90_PATH_A] = 0; + cckpowerlevel[RF90_PATH_B] = 0; + } + /* 2. OFDM for 1S or 2S */ + if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) { + /* Read HT 40 OFDM TX power */ + ofdmpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index]; + ofdmpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index]; + } else if (rtlphy->rf_type == RF_2T2R) { + /* Read HT 40 OFDM TX power */ + ofdmpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index]; + ofdmpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index]; + } +} + +static void _rtl92d_ccxpower_index_check(struct ieee80211_hw *hw, + u8 channel, u8 *cckpowerlevel, u8 *ofdmpowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; + rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; +} + +static u8 _rtl92c_phy_get_rightchnlplace(u8 chnl) +{ + u8 channel_5g[59] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, + 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, + 114, 116, 118, 120, 122, 124, 126, 128, + 130, 132, 134, 136, 138, 140, 149, 151, + 153, 155, 157, 159, 161, 163, 165 + }; + u8 place = chnl; + + if (chnl > 14) { + for (place = 14; place < sizeof(channel_5g); place++) { + if (channel_5g[place] == chnl) { + place++; + break; + } + } + } + return place; +} + +void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 cckpowerlevel[2], ofdmpowerlevel[2]; + + if (!rtlefuse->txpwr_fromeprom) + return; + channel = _rtl92c_phy_get_rightchnlplace(channel); + _rtl92d_get_txpower_index(hw, channel, &cckpowerlevel[0], + &ofdmpowerlevel[0]); + if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) + _rtl92d_ccxpower_index_check(hw, channel, &cckpowerlevel[0], + &ofdmpowerlevel[0]); + if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) + rtl92d_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]); + rtl92d_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel); +} + +void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + unsigned long flag = 0; + u8 reg_prsr_rsc; + u8 reg_bw_opmode; + + if (rtlphy->set_bwmode_inprogress) + return; + if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "FALSE driver sleep or unload\n"); + return; + } + rtlphy->set_bwmode_inprogress = true; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz"); + reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); + reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + break; + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + + reg_prsr_rsc = (reg_prsr_rsc & 0x90) | + (mac->cur_40_prime_sc << 5); + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + /* SET BIT10 BIT11 for receive cck */ + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) | + BIT(11), 3); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + /* Set Control channel to upper or lower. + * These settings are required only for 40MHz */ + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCKSIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl92d_release_cckandrw_pagea_ctl(hw, &flag); + } + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); + /* SET BIT10 BIT11 for receive cck */ + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) | + BIT(11), 0); + rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), + (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + + } + rtl92d_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); +} + +static void _rtl92d_phy_stop_trx_before_changeband(struct ieee80211_hw *hw) +{ + rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0); + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x00); + rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x0); +} + +static void rtl92d_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 value8; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "==>\n"); + rtlhal->bandset = band; + rtlhal->current_bandtype = band; + if (IS_92D_SINGLEPHY(rtlhal->version)) + rtlhal->bandset = BAND_ON_BOTH; + /* stop RX/Tx */ + _rtl92d_phy_stop_trx_before_changeband(hw); + /* reconfig BB/RF according to wireless mode */ + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + /* BB & RF Config */ + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "====>2.4G\n"); + if (rtlhal->interfaceindex == 1) + _rtl92d_phy_config_bb_with_headerfile(hw, + BASEBAND_CONFIG_AGC_TAB); + } else { + /* 5G band */ + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "====>5G\n"); + if (rtlhal->interfaceindex == 1) + _rtl92d_phy_config_bb_with_headerfile(hw, + BASEBAND_CONFIG_AGC_TAB); + } + rtl92d_update_bbrf_configuration(hw); + if (rtlhal->current_bandtype == BAND_ON_2_4G) + rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); + + /* 20M BW. */ + /* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); */ + rtlhal->reloadtxpowerindex = true; + /* notice fw know band status 0x81[1]/0x53[1] = 0: 5G, 1: 2G */ + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + value8 = rtl_read_byte(rtlpriv, (rtlhal->interfaceindex == + 0 ? REG_MAC0 : REG_MAC1)); + value8 |= BIT(1); + rtl_write_byte(rtlpriv, (rtlhal->interfaceindex == + 0 ? REG_MAC0 : REG_MAC1), value8); + } else { + value8 = rtl_read_byte(rtlpriv, (rtlhal->interfaceindex == + 0 ? REG_MAC0 : REG_MAC1)); + value8 &= (~BIT(1)); + rtl_write_byte(rtlpriv, (rtlhal->interfaceindex == + 0 ? REG_MAC0 : REG_MAC1), value8); + } + mdelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "<==Switch Band OK\n"); +} + +static void _rtl92d_phy_reload_imr_setting(struct ieee80211_hw *hw, + u8 channel, u8 rfpath) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 imr_num = MAX_RF_IMR_INDEX; + u32 rfmask = RFREG_OFFSET_MASK; + u8 group, i; + unsigned long flag = 0; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "====>path %d\n", rfpath); + if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "====>5G\n"); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(25) | BIT(24), 0); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf); + /* fc area 0xd2c */ + if (channel > 99) + rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(13) | + BIT(14), 2); + else + rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(13) | + BIT(14), 1); + /* leave 0 for channel1-14. */ + group = channel <= 64 ? 1 : 2; + imr_num = MAX_RF_IMR_INDEX_NORMAL; + for (i = 0; i < imr_num; i++) + rtl_set_rfreg(hw, (enum radio_path)rfpath, + rf_reg_for_5g_swchnl_normal[i], rfmask, + rf_imr_param_normal[0][group][i]); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 1); + } else { + /* G band. */ + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, + "Load RF IMR parameters for G band. IMR already setting %d\n", + rtlpriv->rtlhal.load_imrandiqk_setting_for2g); + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "====>2.4G\n"); + if (!rtlpriv->rtlhal.load_imrandiqk_setting_for2g) { + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, + "Load RF IMR parameters for G band. %d\n", + rfpath); + rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(25) | BIT(24), 0); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, + 0x00f00000, 0xf); + imr_num = MAX_RF_IMR_INDEX_NORMAL; + for (i = 0; i < imr_num; i++) { + rtl_set_rfreg(hw, (enum radio_path)rfpath, + rf_reg_for_5g_swchnl_normal[i], + RFREG_OFFSET_MASK, + rf_imr_param_normal[0][0][i]); + } + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, + 0x00f00000, 0); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN | BCCKEN, 3); + rtl92d_release_cckandrw_pagea_ctl(hw, &flag); + } + } + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "<====\n"); +} + +static void _rtl92d_phy_enable_rf_env(struct ieee80211_hw *hw, + u8 rfpath, u32 *pu4_regval) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "====>\n"); + /*----Store original RFENV control type----*/ + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + *pu4_regval = rtl_get_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV); + break; + case RF90_PATH_B: + case RF90_PATH_D: + *pu4_regval = + rtl_get_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16); + break; + } + /*----Set RF_ENV enable----*/ + rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); + udelay(1); + /*----Set RF_ENV output high----*/ + rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); + udelay(1); + /* Set bit number of Address and Data for RF register */ + /* Set 1 to 4 bits for 8255 */ + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREADDRESSLENGTH, 0x0); + udelay(1); + /*Set 0 to 12 bits for 8255 */ + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); + udelay(1); + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "<====\n"); +} + +static void _rtl92d_phy_restore_rf_env(struct ieee80211_hw *hw, u8 rfpath, + u32 *pu4_regval) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "=====>\n"); + /*----Restore RFENV control type----*/ + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, *pu4_regval); + break; + case RF90_PATH_B: + case RF90_PATH_D: + rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16, + *pu4_regval); + break; + } + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "<=====\n"); +} + +static void _rtl92d_phy_switch_rf_setting(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + u8 path = rtlhal->current_bandtype == + BAND_ON_5G ? RF90_PATH_A : RF90_PATH_B; + u8 index = 0, i = 0, rfpath = RF90_PATH_A; + bool need_pwr_down = false, internal_pa = false; + u32 u4regvalue, mask = 0x1C000, value = 0, u4tmp, u4tmp2; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "====>\n"); + /* config path A for 5G */ + if (rtlhal->current_bandtype == BAND_ON_5G) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "====>5G\n"); + u4tmp = curveindex_5g[channel - 1]; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "ver 1 set RF-A, 5G, 0x28 = 0x%x !!\n", u4tmp); + for (i = 0; i < RF_CHNL_NUM_5G; i++) { + if (channel == rf_chnl_5g[i] && channel <= 140) + index = 0; + } + for (i = 0; i < RF_CHNL_NUM_5G_40M; i++) { + if (channel == rf_chnl_5g_40m[i] && channel <= 140) + index = 1; + } + if (channel == 149 || channel == 155 || channel == 161) + index = 2; + else if (channel == 151 || channel == 153 || channel == 163 + || channel == 165) + index = 3; + else if (channel == 157 || channel == 159) + index = 4; + + if (rtlhal->macphymode == DUALMAC_DUALPHY + && rtlhal->interfaceindex == 1) { + need_pwr_down = rtl92d_phy_enable_anotherphy(hw, false); + rtlhal->during_mac1init_radioa = true; + /* asume no this case */ + if (need_pwr_down) + _rtl92d_phy_enable_rf_env(hw, path, + &u4regvalue); + } + for (i = 0; i < RF_REG_NUM_FOR_C_CUT_5G; i++) { + if (i == 0 && (rtlhal->macphymode == DUALMAC_DUALPHY)) { + rtl_set_rfreg(hw, (enum radio_path)path, + rf_reg_for_c_cut_5g[i], + RFREG_OFFSET_MASK, 0xE439D); + } else if (rf_reg_for_c_cut_5g[i] == RF_SYN_G4) { + u4tmp2 = (rf_reg_pram_c_5g[index][i] & + 0x7FF) | (u4tmp << 11); + if (channel == 36) + u4tmp2 &= ~(BIT(7) | BIT(6)); + rtl_set_rfreg(hw, (enum radio_path)path, + rf_reg_for_c_cut_5g[i], + RFREG_OFFSET_MASK, u4tmp2); + } else { + rtl_set_rfreg(hw, (enum radio_path)path, + rf_reg_for_c_cut_5g[i], + RFREG_OFFSET_MASK, + rf_reg_pram_c_5g[index][i]); + } + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "offset 0x%x value 0x%x path %d index %d readback 0x%x\n", + rf_reg_for_c_cut_5g[i], + rf_reg_pram_c_5g[index][i], + path, index, + rtl_get_rfreg(hw, (enum radio_path)path, + rf_reg_for_c_cut_5g[i], + RFREG_OFFSET_MASK)); + } + if (need_pwr_down) + _rtl92d_phy_restore_rf_env(hw, path, &u4regvalue); + if (rtlhal->during_mac1init_radioa) + rtl92d_phy_powerdown_anotherphy(hw, false); + if (channel < 149) + value = 0x07; + else if (channel >= 149) + value = 0x02; + if (channel >= 36 && channel <= 64) + index = 0; + else if (channel >= 100 && channel <= 140) + index = 1; + else + index = 2; + for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; + rfpath++) { + if (rtlhal->macphymode == DUALMAC_DUALPHY && + rtlhal->interfaceindex == 1) /* MAC 1 5G */ + internal_pa = rtlpriv->efuse.internal_pa_5g[1]; + else + internal_pa = + rtlpriv->efuse.internal_pa_5g[rfpath]; + if (internal_pa) { + for (i = 0; + i < RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA; + i++) { + rtl_set_rfreg(hw, rfpath, + rf_for_c_cut_5g_internal_pa[i], + RFREG_OFFSET_MASK, + rf_pram_c_5g_int_pa[index][i]); + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "offset 0x%x value 0x%x path %d index %d\n", + rf_for_c_cut_5g_internal_pa[i], + rf_pram_c_5g_int_pa[index][i], + rfpath, index); + } + } else { + rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B, + mask, value); + } + } + } else if (rtlhal->current_bandtype == BAND_ON_2_4G) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "====>2.4G\n"); + u4tmp = curveindex_2g[channel - 1]; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n", u4tmp); + if (channel == 1 || channel == 2 || channel == 4 || channel == 9 + || channel == 10 || channel == 11 || channel == 12) + index = 0; + else if (channel == 3 || channel == 13 || channel == 14) + index = 1; + else if (channel >= 5 && channel <= 8) + index = 2; + if (rtlhal->macphymode == DUALMAC_DUALPHY) { + path = RF90_PATH_A; + if (rtlhal->interfaceindex == 0) { + need_pwr_down = + rtl92d_phy_enable_anotherphy(hw, true); + rtlhal->during_mac0init_radiob = true; + + if (need_pwr_down) + _rtl92d_phy_enable_rf_env(hw, path, + &u4regvalue); + } + } + for (i = 0; i < RF_REG_NUM_FOR_C_CUT_2G; i++) { + if (rf_reg_for_c_cut_2g[i] == RF_SYN_G7) + rtl_set_rfreg(hw, (enum radio_path)path, + rf_reg_for_c_cut_2g[i], + RFREG_OFFSET_MASK, + (rf_reg_param_for_c_cut_2g[index][i] | + BIT(17))); + else + rtl_set_rfreg(hw, (enum radio_path)path, + rf_reg_for_c_cut_2g[i], + RFREG_OFFSET_MASK, + rf_reg_param_for_c_cut_2g + [index][i]); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "offset 0x%x value 0x%x mak 0x%x path %d index %d readback 0x%x\n", + rf_reg_for_c_cut_2g[i], + rf_reg_param_for_c_cut_2g[index][i], + rf_reg_mask_for_c_cut_2g[i], path, index, + rtl_get_rfreg(hw, (enum radio_path)path, + rf_reg_for_c_cut_2g[i], + RFREG_OFFSET_MASK)); + } + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "cosa ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n", + rf_syn_g4_for_c_cut_2g | (u4tmp << 11)); + + rtl_set_rfreg(hw, (enum radio_path)path, RF_SYN_G4, + RFREG_OFFSET_MASK, + rf_syn_g4_for_c_cut_2g | (u4tmp << 11)); + if (need_pwr_down) + _rtl92d_phy_restore_rf_env(hw, path, &u4regvalue); + if (rtlhal->during_mac0init_radiob) + rtl92d_phy_powerdown_anotherphy(hw, true); + } + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "<====\n"); +} + +u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl) +{ + u8 channel_all[59] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, + 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, + 114, 116, 118, 120, 122, 124, 126, 128, 130, + 132, 134, 136, 138, 140, 149, 151, 153, 155, + 157, 159, 161, 163, 165 + }; + u8 place = chnl; + + if (chnl > 14) { + for (place = 14; place < sizeof(channel_all); place++) { + if (channel_all[place] == chnl) + return place - 13; + } + } + + return 0; +} + +#define MAX_TOLERANCE 5 +#define IQK_DELAY_TIME 1 /* ms */ +#define MAX_TOLERANCE_92D 3 + +/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +static u8 _rtl92d_phy_patha_iqk(struct ieee80211_hw *hw, bool configpathb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 regeac, rege94, rege9c, regea4; + u8 result = 0; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A IQK!\n"); + /* path-A IQK setting */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path-A IQK setting!\n"); + if (rtlhal->interfaceindex == 0) { + rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f); + rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f); + } else { + rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c22); + rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c22); + } + rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102); + rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x28160206); + /* path-B IQK setting */ + if (configpathb) { + rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22); + rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22); + rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102); + rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160206); + } + /* LO calibration setting */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, "LO calibration setting!\n"); + rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911); + /* One shot, path A LOK & IQK */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, "One shot, path A LOK & IQK!\n"); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); + /* delay x ms */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Delay %d ms for One shot, path A LOK & IQK\n", + IQK_DELAY_TIME); + mdelay(IQK_DELAY_TIME); + /* Check failed */ + regeac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xeac = 0x%x\n", regeac); + rege94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xe94 = 0x%x\n", rege94); + rege9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xe9c = 0x%x\n", rege9c); + regea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xea4 = 0x%x\n", regea4); + if (!(regeac & BIT(28)) && (((rege94 & 0x03FF0000) >> 16) != 0x142) && + (((rege9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else /* if Tx not OK, ignore Rx */ + return result; + /* if Tx is OK, check whether Rx is OK */ + if (!(regeac & BIT(27)) && (((regea4 & 0x03FF0000) >> 16) != 0x132) && + (((regeac & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + else + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A Rx IQK fail!!\n"); + return result; +} + +/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +static u8 _rtl92d_phy_patha_iqk_5g_normal(struct ieee80211_hw *hw, + bool configpathb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 regeac, rege94, rege9c, regea4; + u8 result = 0; + u8 i; + u8 retrycount = 2; + u32 TxOKBit = BIT(28), RxOKBit = BIT(27); + + if (rtlhal->interfaceindex == 1) { /* PHY1 */ + TxOKBit = BIT(31); + RxOKBit = BIT(30); + } + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A IQK!\n"); + /* path-A IQK setting */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path-A IQK setting!\n"); + rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x18008c1f); + rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x18008c1f); + rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140307); + rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x68160960); + /* path-B IQK setting */ + if (configpathb) { + rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x18008c2f); + rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x18008c2f); + rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82110000); + rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x68110000); + } + /* LO calibration setting */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, "LO calibration setting!\n"); + rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911); + /* path-A PA on */ + rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, MASKDWORD, 0x07000f60); + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, MASKDWORD, 0x66e60e30); + for (i = 0; i < retrycount; i++) { + /* One shot, path A LOK & IQK */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "One shot, path A LOK & IQK!\n"); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); + /* delay x ms */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Delay %d ms for One shot, path A LOK & IQK.\n", + IQK_DELAY_TIME); + mdelay(IQK_DELAY_TIME * 10); + /* Check failed */ + regeac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xeac = 0x%x\n", regeac); + rege94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xe94 = 0x%x\n", rege94); + rege9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xe9c = 0x%x\n", rege9c); + regea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xea4 = 0x%x\n", regea4); + if (!(regeac & TxOKBit) && + (((rege94 & 0x03FF0000) >> 16) != 0x142)) { + result |= 0x01; + } else { /* if Tx not OK, ignore Rx */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path A Tx IQK fail!!\n"); + continue; + } + + /* if Tx is OK, check whether Rx is OK */ + if (!(regeac & RxOKBit) && + (((regea4 & 0x03FF0000) >> 16) != 0x132)) { + result |= 0x02; + break; + } else { + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path A Rx IQK fail!!\n"); + } + } + /* path A PA off */ + rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, MASKDWORD, + rtlphy->iqk_bb_backup[0]); + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, MASKDWORD, + rtlphy->iqk_bb_backup[1]); + return result; +} + +/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +static u8 _rtl92d_phy_pathb_iqk(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 regeac, regeb4, regebc, regec4, regecc; + u8 result = 0; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path B IQK!\n"); + /* One shot, path B LOK & IQK */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, "One shot, path A LOK & IQK!\n"); + rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002); + rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000); + /* delay x ms */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Delay %d ms for One shot, path B LOK & IQK\n", IQK_DELAY_TIME); + mdelay(IQK_DELAY_TIME); + /* Check failed */ + regeac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xeac = 0x%x\n", regeac); + regeb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xeb4 = 0x%x\n", regeb4); + regebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xebc = 0x%x\n", regebc); + regec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xec4 = 0x%x\n", regec4); + regecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xecc = 0x%x\n", regecc); + if (!(regeac & BIT(31)) && (((regeb4 & 0x03FF0000) >> 16) != 0x142) && + (((regebc & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + if (!(regeac & BIT(30)) && (((regec4 & 0x03FF0000) >> 16) != 0x132) && + (((regecc & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + else + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path B Rx IQK fail!!\n"); + return result; +} + +/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +static u8 _rtl92d_phy_pathb_iqk_5g_normal(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 regeac, regeb4, regebc, regec4, regecc; + u8 result = 0; + u8 i; + u8 retrycount = 2; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path B IQK!\n"); + /* path-A IQK setting */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path-A IQK setting!\n"); + rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x18008c1f); + rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x18008c1f); + rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82110000); + rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x68110000); + + /* path-B IQK setting */ + rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x18008c2f); + rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x18008c2f); + rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140307); + rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x68160960); + + /* LO calibration setting */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, "LO calibration setting!\n"); + rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911); + + /* path-B PA on */ + rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, MASKDWORD, 0x0f600700); + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, MASKDWORD, 0x061f0d30); + + for (i = 0; i < retrycount; i++) { + /* One shot, path B LOK & IQK */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "One shot, path A LOK & IQK!\n"); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xfa000000); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); + + /* delay x ms */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Delay %d ms for One shot, path B LOK & IQK.\n", 10); + mdelay(IQK_DELAY_TIME * 10); + + /* Check failed */ + regeac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xeac = 0x%x\n", regeac); + regeb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xeb4 = 0x%x\n", regeb4); + regebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xebc = 0x%x\n", regebc); + regec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xec4 = 0x%x\n", regec4); + regecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xecc = 0x%x\n", regecc); + if (!(regeac & BIT(31)) && + (((regeb4 & 0x03FF0000) >> 16) != 0x142)) + result |= 0x01; + else + continue; + if (!(regeac & BIT(30)) && + (((regec4 & 0x03FF0000) >> 16) != 0x132)) { + result |= 0x02; + break; + } else { + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path B Rx IQK fail!!\n"); + } + } + + /* path B PA off */ + rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, MASKDWORD, + rtlphy->iqk_bb_backup[0]); + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, MASKDWORD, + rtlphy->iqk_bb_backup[2]); + return result; +} + +static void _rtl92d_phy_save_adda_registers(struct ieee80211_hw *hw, + u32 *adda_reg, u32 *adda_backup, + u32 regnum) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Save ADDA parameters.\n"); + for (i = 0; i < regnum; i++) + adda_backup[i] = rtl_get_bbreg(hw, adda_reg[i], MASKDWORD); +} + +static void _rtl92d_phy_save_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Save MAC parameters.\n"); + for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) + macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); + macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); +} + +static void _rtl92d_phy_reload_adda_registers(struct ieee80211_hw *hw, + u32 *adda_reg, u32 *adda_backup, + u32 regnum) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Reload ADDA power saving parameters !\n"); + for (i = 0; i < regnum; i++) + rtl_set_bbreg(hw, adda_reg[i], MASKDWORD, adda_backup[i]); +} + +static void _rtl92d_phy_reload_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Reload MAC parameters !\n"); + for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) + rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]); + rtl_write_byte(rtlpriv, macreg[i], macbackup[i]); +} + +static void _rtl92d_phy_path_adda_on(struct ieee80211_hw *hw, + u32 *adda_reg, bool patha_on, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 pathon; + u32 i; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, "ADDA ON.\n"); + pathon = patha_on ? 0x04db25a4 : 0x0b1b25a4; + if (patha_on) + pathon = rtlpriv->rtlhal.interfaceindex == 0 ? + 0x04db25a4 : 0x0b1b25a4; + for (i = 0; i < IQK_ADDA_REG_NUM; i++) + rtl_set_bbreg(hw, adda_reg[i], MASKDWORD, pathon); +} + +static void _rtl92d_phy_mac_setting_calibration(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, "MAC settings for Calibration.\n"); + rtl_write_byte(rtlpriv, macreg[0], 0x3F); + + for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) + rtl_write_byte(rtlpriv, macreg[i], (u8)(macbackup[i] & + (~BIT(3)))); + rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5)))); +} + +static void _rtl92d_phy_patha_standby(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path-A standby mode!\n"); + + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); + rtl_set_bbreg(hw, RFPGA0_XA_LSSIPARAMETER, MASKDWORD, 0x00010000); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); +} + +static void _rtl92d_phy_pimode_switch(struct ieee80211_hw *hw, bool pi_mode) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 mode; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "BB Switch to %s mode!\n", pi_mode ? "PI" : "SI"); + mode = pi_mode ? 0x01000100 : 0x01000000; + rtl_set_bbreg(hw, 0x820, MASKDWORD, mode); + rtl_set_bbreg(hw, 0x828, MASKDWORD, mode); +} + +static void _rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw, long result[][8], + u8 t, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 i; + u8 patha_ok, pathb_ok; + static u32 adda_reg[IQK_ADDA_REG_NUM] = { + RFPGA0_XCD_SWITCHCONTROL, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec + }; + static u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { + 0x522, 0x550, 0x551, 0x040 + }; + static u32 iqk_bb_reg[IQK_BB_REG_NUM] = { + RFPGA0_XAB_RFINTERFACESW, RFPGA0_XA_RFINTERFACEOE, + RFPGA0_XB_RFINTERFACEOE, ROFDM0_TRMUXPAR, + RFPGA0_XCD_RFINTERFACESW, ROFDM0_TRXPATHENABLE, + RFPGA0_RFMOD, RFPGA0_ANALOGPARAMETER4, + ROFDM0_XAAGCCORE1, ROFDM0_XBAGCCORE1 + }; + const u32 retrycount = 2; + u32 bbvalue; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, "IQK for 2.4G :Start!!!\n"); + if (t == 0) { + bbvalue = rtl_get_bbreg(hw, RFPGA0_RFMOD, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "==>0x%08x\n", bbvalue); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "IQ Calibration for %s\n", + is2t ? "2T2R" : "1T1R"); + + /* Save ADDA parameters, turn Path A ADDA on */ + _rtl92d_phy_save_adda_registers(hw, adda_reg, + rtlphy->adda_backup, IQK_ADDA_REG_NUM); + _rtl92d_phy_save_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + _rtl92d_phy_save_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, IQK_BB_REG_NUM); + } + _rtl92d_phy_path_adda_on(hw, adda_reg, true, is2t); + if (t == 0) + rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER1, BIT(8)); + + /* Switch BB to PI mode to do IQ Calibration. */ + if (!rtlphy->rfpi_enable) + _rtl92d_phy_pimode_switch(hw, true); + + rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00); + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKDWORD, 0x03a05600); + rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, MASKDWORD, 0x000800e4); + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, MASKDWORD, 0x22204000); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xf00000, 0x0f); + if (is2t) { + rtl_set_bbreg(hw, RFPGA0_XA_LSSIPARAMETER, MASKDWORD, + 0x00010000); + rtl_set_bbreg(hw, RFPGA0_XB_LSSIPARAMETER, MASKDWORD, + 0x00010000); + } + /* MAC settings */ + _rtl92d_phy_mac_setting_calibration(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + /* Page B init */ + rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x0f600000); + if (is2t) + rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x0f600000); + /* IQ calibration setting */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, "IQK setting!\n"); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); + rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800); + for (i = 0; i < retrycount; i++) { + patha_ok = _rtl92d_phy_patha_iqk(hw, is2t); + if (patha_ok == 0x03) { + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path A IQK Success!!\n"); + result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & + 0x3FF0000) >> 16; + break; + } else if (i == (retrycount - 1) && patha_ok == 0x01) { + /* Tx IQK OK */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path A IQK Only Tx Success!!\n"); + + result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & + 0x3FF0000) >> 16; + } + } + if (0x00 == patha_ok) + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A IQK failed!!\n"); + if (is2t) { + _rtl92d_phy_patha_standby(hw); + /* Turn Path B ADDA on */ + _rtl92d_phy_path_adda_on(hw, adda_reg, false, is2t); + for (i = 0; i < retrycount; i++) { + pathb_ok = _rtl92d_phy_pathb_iqk(hw); + if (pathb_ok == 0x03) { + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path B IQK Success!!\n"); + result[t][4] = (rtl_get_bbreg(hw, 0xeb4, + MASKDWORD) & 0x3FF0000) >> 16; + result[t][5] = (rtl_get_bbreg(hw, 0xebc, + MASKDWORD) & 0x3FF0000) >> 16; + result[t][6] = (rtl_get_bbreg(hw, 0xec4, + MASKDWORD) & 0x3FF0000) >> 16; + result[t][7] = (rtl_get_bbreg(hw, 0xecc, + MASKDWORD) & 0x3FF0000) >> 16; + break; + } else if (i == (retrycount - 1) && pathb_ok == 0x01) { + /* Tx IQK OK */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path B Only Tx IQK Success!!\n"); + result[t][4] = (rtl_get_bbreg(hw, 0xeb4, + MASKDWORD) & 0x3FF0000) >> 16; + result[t][5] = (rtl_get_bbreg(hw, 0xebc, + MASKDWORD) & 0x3FF0000) >> 16; + } + } + if (0x00 == pathb_ok) + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path B IQK failed!!\n"); + } + + /* Back to BB mode, load original value */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "IQK:Back to BB mode, load original value!\n"); + + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); + if (t != 0) { + /* Switch back BB to SI mode after finish IQ Calibration. */ + if (!rtlphy->rfpi_enable) + _rtl92d_phy_pimode_switch(hw, false); + /* Reload ADDA power saving parameters */ + _rtl92d_phy_reload_adda_registers(hw, adda_reg, + rtlphy->adda_backup, IQK_ADDA_REG_NUM); + /* Reload MAC parameters */ + _rtl92d_phy_reload_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + if (is2t) + _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, + IQK_BB_REG_NUM); + else + _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, + IQK_BB_REG_NUM - 1); + /* load 0xe30 IQC default value */ + rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00); + rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00); + } + RTPRINT(rtlpriv, FINIT, INIT_IQK, "<==\n"); +} + +static void _rtl92d_phy_iq_calibrate_5g_normal(struct ieee80211_hw *hw, + long result[][8], u8 t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + u8 patha_ok, pathb_ok; + static u32 adda_reg[IQK_ADDA_REG_NUM] = { + RFPGA0_XCD_SWITCHCONTROL, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec + }; + static u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { + 0x522, 0x550, 0x551, 0x040 + }; + static u32 iqk_bb_reg[IQK_BB_REG_NUM] = { + RFPGA0_XAB_RFINTERFACESW, RFPGA0_XA_RFINTERFACEOE, + RFPGA0_XB_RFINTERFACEOE, ROFDM0_TRMUXPAR, + RFPGA0_XCD_RFINTERFACESW, ROFDM0_TRXPATHENABLE, + RFPGA0_RFMOD, RFPGA0_ANALOGPARAMETER4, + ROFDM0_XAAGCCORE1, ROFDM0_XBAGCCORE1 + }; + u32 bbvalue; + bool is2t = IS_92D_SINGLEPHY(rtlhal->version); + + /* Note: IQ calibration must be performed after loading + * PHY_REG.txt , and radio_a, radio_b.txt */ + + RTPRINT(rtlpriv, FINIT, INIT_IQK, "IQK for 5G NORMAL:Start!!!\n"); + mdelay(IQK_DELAY_TIME * 20); + if (t == 0) { + bbvalue = rtl_get_bbreg(hw, RFPGA0_RFMOD, MASKDWORD); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "==>0x%08x\n", bbvalue); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "IQ Calibration for %s\n", + is2t ? "2T2R" : "1T1R"); + /* Save ADDA parameters, turn Path A ADDA on */ + _rtl92d_phy_save_adda_registers(hw, adda_reg, + rtlphy->adda_backup, + IQK_ADDA_REG_NUM); + _rtl92d_phy_save_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + if (is2t) + _rtl92d_phy_save_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, + IQK_BB_REG_NUM); + else + _rtl92d_phy_save_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, + IQK_BB_REG_NUM - 1); + } + _rtl92d_phy_path_adda_on(hw, adda_reg, true, is2t); + /* MAC settings */ + _rtl92d_phy_mac_setting_calibration(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + if (t == 0) + rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER1, BIT(8)); + /* Switch BB to PI mode to do IQ Calibration. */ + if (!rtlphy->rfpi_enable) + _rtl92d_phy_pimode_switch(hw, true); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00); + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKDWORD, 0x03a05600); + rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, MASKDWORD, 0x000800e4); + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, MASKDWORD, 0x22208000); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xf00000, 0x0f); + + /* Page B init */ + rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x0f600000); + if (is2t) + rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x0f600000); + /* IQ calibration setting */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, "IQK setting!\n"); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); + rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x10007c00); + rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800); + patha_ok = _rtl92d_phy_patha_iqk_5g_normal(hw, is2t); + if (patha_ok == 0x03) { + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A IQK Success!!\n"); + result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & + 0x3FF0000) >> 16; + } else if (patha_ok == 0x01) { /* Tx IQK OK */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path A IQK Only Tx Success!!\n"); + + result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & + 0x3FF0000) >> 16; + } else { + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A IQK Fail!!\n"); + } + if (is2t) { + /* _rtl92d_phy_patha_standby(hw); */ + /* Turn Path B ADDA on */ + _rtl92d_phy_path_adda_on(hw, adda_reg, false, is2t); + pathb_ok = _rtl92d_phy_pathb_iqk_5g_normal(hw); + if (pathb_ok == 0x03) { + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path B IQK Success!!\n"); + result[t][4] = (rtl_get_bbreg(hw, 0xeb4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][6] = (rtl_get_bbreg(hw, 0xec4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][7] = (rtl_get_bbreg(hw, 0xecc, MASKDWORD) & + 0x3FF0000) >> 16; + } else if (pathb_ok == 0x01) { /* Tx IQK OK */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path B Only Tx IQK Success!!\n"); + result[t][4] = (rtl_get_bbreg(hw, 0xeb4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & + 0x3FF0000) >> 16; + } else { + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path B IQK failed!!\n"); + } + } + + /* Back to BB mode, load original value */ + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "IQK:Back to BB mode, load original value!\n"); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); + if (t != 0) { + if (is2t) + _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, + IQK_BB_REG_NUM); + else + _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, + IQK_BB_REG_NUM - 1); + /* Reload MAC parameters */ + _rtl92d_phy_reload_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + /* Switch back BB to SI mode after finish IQ Calibration. */ + if (!rtlphy->rfpi_enable) + _rtl92d_phy_pimode_switch(hw, false); + /* Reload ADDA power saving parameters */ + _rtl92d_phy_reload_adda_registers(hw, adda_reg, + rtlphy->adda_backup, + IQK_ADDA_REG_NUM); + } + RTPRINT(rtlpriv, FINIT, INIT_IQK, "<==\n"); +} + +static bool _rtl92d_phy_simularity_compare(struct ieee80211_hw *hw, + long result[][8], u8 c1, u8 c2) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + u32 i, j, diff, sim_bitmap, bound; + u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */ + bool bresult = true; + bool is2t = IS_92D_SINGLEPHY(rtlhal->version); + + if (is2t) + bound = 8; + else + bound = 4; + sim_bitmap = 0; + for (i = 0; i < bound; i++) { + diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] - + result[c2][i]) : (result[c2][i] - result[c1][i]); + if (diff > MAX_TOLERANCE_92D) { + if ((i == 2 || i == 6) && !sim_bitmap) { + if (result[c1][i] + result[c1][i + 1] == 0) + final_candidate[(i / 4)] = c2; + else if (result[c2][i] + result[c2][i + 1] == 0) + final_candidate[(i / 4)] = c1; + else + sim_bitmap = sim_bitmap | (1 << i); + } else { + sim_bitmap = sim_bitmap | (1 << i); + } + } + } + if (sim_bitmap == 0) { + for (i = 0; i < (bound / 4); i++) { + if (final_candidate[i] != 0xFF) { + for (j = i * 4; j < (i + 1) * 4 - 2; j++) + result[3][j] = + result[final_candidate[i]][j]; + bresult = false; + } + } + return bresult; + } + if (!(sim_bitmap & 0x0F)) { /* path A OK */ + for (i = 0; i < 4; i++) + result[3][i] = result[c1][i]; + } else if (!(sim_bitmap & 0x03)) { /* path A, Tx OK */ + for (i = 0; i < 2; i++) + result[3][i] = result[c1][i]; + } + if (!(sim_bitmap & 0xF0) && is2t) { /* path B OK */ + for (i = 4; i < 8; i++) + result[3][i] = result[c1][i]; + } else if (!(sim_bitmap & 0x30)) { /* path B, Tx OK */ + for (i = 4; i < 6; i++) + result[3][i] = result[c1][i]; + } + return false; +} + +static void _rtl92d_phy_patha_fill_iqk_matrix(struct ieee80211_hw *hw, + bool iqk_ok, long result[][8], + u8 final_candidate, bool txonly) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + u32 oldval_0, val_x, tx0_a, reg; + long val_y, tx0_c; + bool is2t = IS_92D_SINGLEPHY(rtlhal->version) || + rtlhal->macphymode == DUALMAC_DUALPHY; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Path A IQ Calibration %s !\n", iqk_ok ? "Success" : "Failed"); + if (final_candidate == 0xFF) { + return; + } else if (iqk_ok) { + oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE, + MASKDWORD) >> 22) & 0x3FF; /* OFDM0_D */ + val_x = result[final_candidate][0]; + if ((val_x & 0x00000200) != 0) + val_x = val_x | 0xFFFFFC00; + tx0_a = (val_x * oldval_0) >> 8; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "X = 0x%x, tx0_a = 0x%x, oldval_0 0x%x\n", + val_x, tx0_a, oldval_0); + rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x3FF, tx0_a); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), + ((val_x * oldval_0 >> 7) & 0x1)); + val_y = result[final_candidate][1]; + if ((val_y & 0x00000200) != 0) + val_y = val_y | 0xFFFFFC00; + /* path B IQK result + 3 */ + if (rtlhal->interfaceindex == 1 && + rtlhal->current_bandtype == BAND_ON_5G) + val_y += 3; + tx0_c = (val_y * oldval_0) >> 8; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "Y = 0x%lx, tx0_c = 0x%lx\n", + val_y, tx0_c); + rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000, + ((tx0_c & 0x3C0) >> 6)); + rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x003F0000, + (tx0_c & 0x3F)); + if (is2t) + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(26), + ((val_y * oldval_0 >> 7) & 0x1)); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xC80 = 0x%x\n", + rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE, + MASKDWORD)); + if (txonly) { + RTPRINT(rtlpriv, FINIT, INIT_IQK, "only Tx OK\n"); + return; + } + reg = result[final_candidate][2]; + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg); + reg = result[final_candidate][3] & 0x3F; + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg); + reg = (result[final_candidate][3] >> 6) & 0xF; + rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); + } +} + +static void _rtl92d_phy_pathb_fill_iqk_matrix(struct ieee80211_hw *hw, + bool iqk_ok, long result[][8], u8 final_candidate, bool txonly) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + u32 oldval_1, val_x, tx1_a, reg; + long val_y, tx1_c; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path B IQ Calibration %s !\n", + iqk_ok ? "Success" : "Failed"); + if (final_candidate == 0xFF) { + return; + } else if (iqk_ok) { + oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, + MASKDWORD) >> 22) & 0x3FF; + val_x = result[final_candidate][4]; + if ((val_x & 0x00000200) != 0) + val_x = val_x | 0xFFFFFC00; + tx1_a = (val_x * oldval_1) >> 8; + RTPRINT(rtlpriv, FINIT, INIT_IQK, "X = 0x%x, tx1_a = 0x%x\n", + val_x, tx1_a); + rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x3FF, tx1_a); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28), + ((val_x * oldval_1 >> 7) & 0x1)); + val_y = result[final_candidate][5]; + if ((val_y & 0x00000200) != 0) + val_y = val_y | 0xFFFFFC00; + if (rtlhal->current_bandtype == BAND_ON_5G) + val_y += 3; + tx1_c = (val_y * oldval_1) >> 8; + RTPRINT(rtlpriv, FINIT, INIT_IQK, "Y = 0x%lx, tx1_c = 0x%lx\n", + val_y, tx1_c); + rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000, + ((tx1_c & 0x3C0) >> 6)); + rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x003F0000, + (tx1_c & 0x3F)); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30), + ((val_y * oldval_1 >> 7) & 0x1)); + if (txonly) + return; + reg = result[final_candidate][6]; + rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg); + reg = result[final_candidate][7] & 0x3F; + rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg); + reg = (result[final_candidate][7] >> 6) & 0xF; + rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg); + } +} + +void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + long result[4][8]; + u8 i, final_candidate, indexforchannel; + bool patha_ok, pathb_ok; + long rege94, rege9c, regea4, regeac, regeb4; + long regebc, regec4, regecc, regtmp = 0; + bool is12simular, is13simular, is23simular; + unsigned long flag = 0; + + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "IQK:Start!!!channel %d\n", rtlphy->current_channel); + for (i = 0; i < 8; i++) { + result[0][i] = 0; + result[1][i] = 0; + result[2][i] = 0; + result[3][i] = 0; + } + final_candidate = 0xff; + patha_ok = false; + pathb_ok = false; + is12simular = false; + is23simular = false; + is13simular = false; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "IQK !!!currentband %d\n", rtlhal->current_bandtype); + rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); + for (i = 0; i < 3; i++) { + if (rtlhal->current_bandtype == BAND_ON_5G) { + _rtl92d_phy_iq_calibrate_5g_normal(hw, result, i); + } else if (rtlhal->current_bandtype == BAND_ON_2_4G) { + if (IS_92D_SINGLEPHY(rtlhal->version)) + _rtl92d_phy_iq_calibrate(hw, result, i, true); + else + _rtl92d_phy_iq_calibrate(hw, result, i, false); + } + if (i == 1) { + is12simular = _rtl92d_phy_simularity_compare(hw, result, + 0, 1); + if (is12simular) { + final_candidate = 0; + break; + } + } + if (i == 2) { + is13simular = _rtl92d_phy_simularity_compare(hw, result, + 0, 2); + if (is13simular) { + final_candidate = 0; + break; + } + is23simular = _rtl92d_phy_simularity_compare(hw, result, + 1, 2); + if (is23simular) { + final_candidate = 1; + } else { + for (i = 0; i < 8; i++) + regtmp += result[3][i]; + + if (regtmp != 0) + final_candidate = 3; + else + final_candidate = 0xFF; + } + } + } + rtl92d_release_cckandrw_pagea_ctl(hw, &flag); + for (i = 0; i < 4; i++) { + rege94 = result[i][0]; + rege9c = result[i][1]; + regea4 = result[i][2]; + regeac = result[i][3]; + regeb4 = result[i][4]; + regebc = result[i][5]; + regec4 = result[i][6]; + regecc = result[i][7]; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "IQK: rege94=%lx rege9c=%lx regea4=%lx regeac=%lx regeb4=%lx regebc=%lx regec4=%lx regecc=%lx\n", + rege94, rege9c, regea4, regeac, regeb4, regebc, regec4, + regecc); + } + if (final_candidate != 0xff) { + rtlphy->reg_e94 = rege94 = result[final_candidate][0]; + rtlphy->reg_e9c = rege9c = result[final_candidate][1]; + regea4 = result[final_candidate][2]; + regeac = result[final_candidate][3]; + rtlphy->reg_eb4 = regeb4 = result[final_candidate][4]; + rtlphy->reg_ebc = regebc = result[final_candidate][5]; + regec4 = result[final_candidate][6]; + regecc = result[final_candidate][7]; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "IQK: final_candidate is %x\n", final_candidate); + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "IQK: rege94=%lx rege9c=%lx regea4=%lx regeac=%lx regeb4=%lx regebc=%lx regec4=%lx regecc=%lx\n", + rege94, rege9c, regea4, regeac, regeb4, regebc, regec4, + regecc); + patha_ok = pathb_ok = true; + } else { + rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; /* X default value */ + rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0; /* Y default value */ + } + if ((rege94 != 0) /*&&(regea4 != 0) */) + _rtl92d_phy_patha_fill_iqk_matrix(hw, patha_ok, result, + final_candidate, (regea4 == 0)); + if (IS_92D_SINGLEPHY(rtlhal->version)) { + if ((regeb4 != 0) /*&&(regec4 != 0) */) + _rtl92d_phy_pathb_fill_iqk_matrix(hw, pathb_ok, result, + final_candidate, (regec4 == 0)); + } + if (final_candidate != 0xFF) { + indexforchannel = rtl92d_get_rightchnlplace_for_iqk( + rtlphy->current_channel); + + for (i = 0; i < IQK_MATRIX_REG_NUM; i++) + rtlphy->iqk_matrix[indexforchannel]. + value[0][i] = result[final_candidate][i]; + rtlphy->iqk_matrix[indexforchannel].iqk_done = + true; + + RT_TRACE(rtlpriv, COMP_SCAN | COMP_MLME, DBG_LOUD, + "IQK OK indexforchannel %d\n", indexforchannel); + } +} + +void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + u8 indexforchannel; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "channel %d\n", channel); + /*------Do IQK for normal chip and test chip 5G band------- */ + indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "indexforchannel %d done %d\n", + indexforchannel, + rtlphy->iqk_matrix[indexforchannel].iqk_done); + if (0 && !rtlphy->iqk_matrix[indexforchannel].iqk_done && + rtlphy->need_iqk) { + /* Re Do IQK. */ + RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_LOUD, + "Do IQK Matrix reg for channel:%d....\n", channel); + rtl92d_phy_iq_calibrate(hw); + } else { + /* Just load the value. */ + /* 2G band just load once. */ + if (((!rtlhal->load_imrandiqk_setting_for2g) && + indexforchannel == 0) || indexforchannel > 0) { + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, + "Just Read IQK Matrix reg for channel:%d....\n", + channel); + if ((rtlphy->iqk_matrix[indexforchannel]. + value[0] != NULL) + /*&&(regea4 != 0) */) + _rtl92d_phy_patha_fill_iqk_matrix(hw, true, + rtlphy->iqk_matrix[ + indexforchannel].value, 0, + (rtlphy->iqk_matrix[ + indexforchannel].value[0][2] == 0)); + if (IS_92D_SINGLEPHY(rtlhal->version)) { + if ((rtlphy->iqk_matrix[ + indexforchannel].value[0][4] != 0) + /*&&(regec4 != 0) */) + _rtl92d_phy_pathb_fill_iqk_matrix(hw, + true, + rtlphy->iqk_matrix[ + indexforchannel].value, 0, + (rtlphy->iqk_matrix[ + indexforchannel].value[0][6] + == 0)); + } + } + } + rtlphy->need_iqk = false; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "<====\n"); +} + +static u32 _rtl92d_phy_get_abs(u32 val1, u32 val2) +{ + u32 ret; + + if (val1 >= val2) + ret = val1 - val2; + else + ret = val2 - val1; + return ret; +} + +static bool _rtl92d_is_legal_5g_channel(struct ieee80211_hw *hw, u8 channel) +{ + + int i; + u8 channel_5g[45] = { + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, + 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, + 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, + 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, + 161, 163, 165 + }; + + for (i = 0; i < sizeof(channel_5g); i++) + if (channel == channel_5g[i]) + return true; + return false; +} + +static void _rtl92d_phy_calc_curvindex(struct ieee80211_hw *hw, + u32 *targetchnl, u32 * curvecount_val, + bool is5g, u32 *curveindex) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 smallest_abs_val = 0xffffffff, u4tmp; + u8 i, j; + u8 chnl_num = is5g ? TARGET_CHNL_NUM_5G : TARGET_CHNL_NUM_2G; + + for (i = 0; i < chnl_num; i++) { + if (is5g && !_rtl92d_is_legal_5g_channel(hw, i + 1)) + continue; + curveindex[i] = 0; + for (j = 0; j < (CV_CURVE_CNT * 2); j++) { + u4tmp = _rtl92d_phy_get_abs(targetchnl[i], + curvecount_val[j]); + + if (u4tmp < smallest_abs_val) { + curveindex[i] = j; + smallest_abs_val = u4tmp; + } + } + smallest_abs_val = 0xffffffff; + RTPRINT(rtlpriv, FINIT, INIT_IQK, "curveindex[%d] = %x\n", + i, curveindex[i]); + } +} + +static void _rtl92d_phy_reload_lck_setting(struct ieee80211_hw *hw, + u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 erfpath = rtlpriv->rtlhal.current_bandtype == + BAND_ON_5G ? RF90_PATH_A : + IS_92D_SINGLEPHY(rtlpriv->rtlhal.version) ? + RF90_PATH_B : RF90_PATH_A; + u32 u4tmp = 0, u4regvalue = 0; + bool bneed_powerdown_radio = false; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "path %d\n", erfpath); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "band type = %d\n", + rtlpriv->rtlhal.current_bandtype); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "channel = %d\n", channel); + if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) {/* Path-A for 5G */ + u4tmp = curveindex_5g[channel-1]; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "ver 1 set RF-A, 5G, 0x28 = 0x%x !!\n", u4tmp); + if (rtlpriv->rtlhal.macphymode == DUALMAC_DUALPHY && + rtlpriv->rtlhal.interfaceindex == 1) { + bneed_powerdown_radio = + rtl92d_phy_enable_anotherphy(hw, false); + rtlpriv->rtlhal.during_mac1init_radioa = true; + /* asume no this case */ + if (bneed_powerdown_radio) + _rtl92d_phy_enable_rf_env(hw, erfpath, + &u4regvalue); + } + rtl_set_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800, u4tmp); + if (bneed_powerdown_radio) + _rtl92d_phy_restore_rf_env(hw, erfpath, &u4regvalue); + if (rtlpriv->rtlhal.during_mac1init_radioa) + rtl92d_phy_powerdown_anotherphy(hw, false); + } else if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) { + u4tmp = curveindex_2g[channel-1]; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n", u4tmp); + if (rtlpriv->rtlhal.macphymode == DUALMAC_DUALPHY && + rtlpriv->rtlhal.interfaceindex == 0) { + bneed_powerdown_radio = + rtl92d_phy_enable_anotherphy(hw, true); + rtlpriv->rtlhal.during_mac0init_radiob = true; + if (bneed_powerdown_radio) + _rtl92d_phy_enable_rf_env(hw, erfpath, + &u4regvalue); + } + rtl_set_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800, u4tmp); + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n", + rtl_get_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800)); + if (bneed_powerdown_radio) + _rtl92d_phy_restore_rf_env(hw, erfpath, &u4regvalue); + if (rtlpriv->rtlhal.during_mac0init_radiob) + rtl92d_phy_powerdown_anotherphy(hw, true); + } + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "<====\n"); +} + +static void _rtl92d_phy_lc_calibrate_sw(struct ieee80211_hw *hw, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 tmpreg, index, rf_mode[2]; + u8 path = is2t ? 2 : 1; + u8 i; + u32 u4tmp, offset; + u32 curvecount_val[CV_CURVE_CNT * 2] = {0}; + u16 timeout = 800, timecount = 0; + + /* Check continuous TX and Packet TX */ + tmpreg = rtl_read_byte(rtlpriv, 0xd03); + /* if Deal with contisuous TX case, disable all continuous TX */ + /* if Deal with Packet TX case, block all queues */ + if ((tmpreg & 0x70) != 0) + rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); + else + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xF00000, 0x0F); + for (index = 0; index < path; index++) { + /* 1. Read original RF mode */ + offset = index == 0 ? ROFDM0_XAAGCCORE1 : ROFDM0_XBAGCCORE1; + rf_mode[index] = rtl_read_byte(rtlpriv, offset); + /* 2. Set RF mode = standby mode */ + rtl_set_rfreg(hw, (enum radio_path)index, RF_AC, + RFREG_OFFSET_MASK, 0x010000); + if (rtlpci->init_ready) { + /* switch CV-curve control by LC-calibration */ + rtl_set_rfreg(hw, (enum radio_path)index, RF_SYN_G7, + BIT(17), 0x0); + /* 4. Set LC calibration begin */ + rtl_set_rfreg(hw, (enum radio_path)index, RF_CHNLBW, + 0x08000, 0x01); + } + u4tmp = rtl_get_rfreg(hw, (enum radio_path)index, RF_SYN_G6, + RFREG_OFFSET_MASK); + while ((!(u4tmp & BIT(11))) && timecount <= timeout) { + mdelay(50); + timecount += 50; + u4tmp = rtl_get_rfreg(hw, (enum radio_path)index, + RF_SYN_G6, RFREG_OFFSET_MASK); + } + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "PHY_LCK finish delay for %d ms=2\n", timecount); + u4tmp = rtl_get_rfreg(hw, index, RF_SYN_G4, RFREG_OFFSET_MASK); + if (index == 0 && rtlhal->interfaceindex == 0) { + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "path-A / 5G LCK\n"); + } else { + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "path-B / 2.4G LCK\n"); + } + memset(&curvecount_val[0], 0, CV_CURVE_CNT * 2); + /* Set LC calibration off */ + rtl_set_rfreg(hw, (enum radio_path)index, RF_CHNLBW, + 0x08000, 0x0); + RTPRINT(rtlpriv, FINIT, INIT_IQK, "set RF 0x18[15] = 0\n"); + /* save Curve-counting number */ + for (i = 0; i < CV_CURVE_CNT; i++) { + u32 readval = 0, readval2 = 0; + rtl_set_rfreg(hw, (enum radio_path)index, 0x3F, + 0x7f, i); + + rtl_set_rfreg(hw, (enum radio_path)index, 0x4D, + RFREG_OFFSET_MASK, 0x0); + readval = rtl_get_rfreg(hw, (enum radio_path)index, + 0x4F, RFREG_OFFSET_MASK); + curvecount_val[2 * i + 1] = (readval & 0xfffe0) >> 5; + /* reg 0x4f [4:0] */ + /* reg 0x50 [19:10] */ + readval2 = rtl_get_rfreg(hw, (enum radio_path)index, + 0x50, 0xffc00); + curvecount_val[2 * i] = (((readval & 0x1F) << 10) | + readval2); + } + if (index == 0 && rtlhal->interfaceindex == 0) + _rtl92d_phy_calc_curvindex(hw, targetchnl_5g, + curvecount_val, + true, curveindex_5g); + else + _rtl92d_phy_calc_curvindex(hw, targetchnl_2g, + curvecount_val, + false, curveindex_2g); + /* switch CV-curve control mode */ + rtl_set_rfreg(hw, (enum radio_path)index, RF_SYN_G7, + BIT(17), 0x1); + } + + /* Restore original situation */ + for (index = 0; index < path; index++) { + offset = index == 0 ? ROFDM0_XAAGCCORE1 : ROFDM0_XBAGCCORE1; + rtl_write_byte(rtlpriv, offset, 0x50); + rtl_write_byte(rtlpriv, offset, rf_mode[index]); + } + if ((tmpreg & 0x70) != 0) + rtl_write_byte(rtlpriv, 0xd03, tmpreg); + else /*Deal with Packet TX case */ + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xF00000, 0x00); + _rtl92d_phy_reload_lck_setting(hw, rtlpriv->phy.current_channel); +} + +static void _rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RTPRINT(rtlpriv, FINIT, INIT_IQK, "cosa PHY_LCK ver=2\n"); + _rtl92d_phy_lc_calibrate_sw(hw, is2t); +} + +void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + u32 timeout = 2000, timecount = 0; + + while (rtlpriv->mac80211.act_scanning && timecount < timeout) { + udelay(50); + timecount += 50; + } + + rtlphy->lck_inprogress = true; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "LCK:Start!!! currentband %x delay %d ms\n", + rtlhal->current_bandtype, timecount); + if (IS_92D_SINGLEPHY(rtlhal->version)) { + _rtl92d_phy_lc_calibrate(hw, true); + } else { + /* For 1T1R */ + _rtl92d_phy_lc_calibrate(hw, false); + } + rtlphy->lck_inprogress = false; + RTPRINT(rtlpriv, FINIT, INIT_IQK, "LCK:Finish!!!\n"); +} + +void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, char delta) +{ + return; +} + +static bool _rtl92d_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, enum swchnlcmd_id cmdid, + u32 para1, u32 para2, u32 msdelay) +{ + struct swchnlcmd *pcmd; + + if (cmdtable == NULL) { + RT_ASSERT(false, "cmdtable cannot be NULL\n"); + return false; + } + if (cmdtableidx >= cmdtablesz) + return false; + + pcmd = cmdtable + cmdtableidx; + pcmd->cmdid = cmdid; + pcmd->para1 = para1; + pcmd->para2 = para2; + pcmd->msdelay = msdelay; + return true; +} + +void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u8 i; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "settings regs %d default regs %d\n", + (int)(sizeof(rtlphy->iqk_matrix) / + sizeof(struct iqk_matrix_regs)), + IQK_MATRIX_REG_NUM); + /* 0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc */ + for (i = 0; i < IQK_MATRIX_SETTINGS_NUM; i++) { + rtlphy->iqk_matrix[i].value[0][0] = 0x100; + rtlphy->iqk_matrix[i].value[0][2] = 0x100; + rtlphy->iqk_matrix[i].value[0][4] = 0x100; + rtlphy->iqk_matrix[i].value[0][6] = 0x100; + rtlphy->iqk_matrix[i].value[0][1] = 0x0; + rtlphy->iqk_matrix[i].value[0][3] = 0x0; + rtlphy->iqk_matrix[i].value[0][5] = 0x0; + rtlphy->iqk_matrix[i].value[0][7] = 0x0; + rtlphy->iqk_matrix[i].iqk_done = false; + } +} + +static bool _rtl92d_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; + u32 precommoncmdcnt; + struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; + u32 postcommoncmdcnt; + struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; + u32 rfdependcmdcnt; + struct swchnlcmd *currentcmd = NULL; + u8 rfpath; + u8 num_total_rfpath = rtlphy->num_total_rfpath; + + precommoncmdcnt = 0; + _rtl92d_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, + CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); + _rtl92d_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); + postcommoncmdcnt = 0; + _rtl92d_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, + MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); + rfdependcmdcnt = 0; + _rtl92d_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, + RF_CHNLBW, channel, 0); + _rtl92d_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_END, + 0, 0, 0); + + do { + switch (*stage) { + case 0: + currentcmd = &precommoncmd[*step]; + break; + case 1: + currentcmd = &rfdependcmd[*step]; + break; + case 2: + currentcmd = &postcommoncmd[*step]; + break; + } + if (currentcmd->cmdid == CMDID_END) { + if ((*stage) == 2) { + return true; + } else { + (*stage)++; + (*step) = 0; + continue; + } + } + switch (currentcmd->cmdid) { + case CMDID_SET_TXPOWEROWER_LEVEL: + rtl92d_phy_set_txpower_level(hw, channel); + break; + case CMDID_WRITEPORT_ULONG: + rtl_write_dword(rtlpriv, currentcmd->para1, + currentcmd->para2); + break; + case CMDID_WRITEPORT_USHORT: + rtl_write_word(rtlpriv, currentcmd->para1, + (u16)currentcmd->para2); + break; + case CMDID_WRITEPORT_UCHAR: + rtl_write_byte(rtlpriv, currentcmd->para1, + (u8)currentcmd->para2); + break; + case CMDID_RF_WRITEREG: + for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { + rtlphy->rfreg_chnlval[rfpath] = + ((rtlphy->rfreg_chnlval[rfpath] & + 0xffffff00) | currentcmd->para2); + if (rtlpriv->rtlhal.current_bandtype == + BAND_ON_5G) { + if (currentcmd->para2 > 99) + rtlphy->rfreg_chnlval[rfpath] = + rtlphy->rfreg_chnlval + [rfpath] | (BIT(18)); + else + rtlphy->rfreg_chnlval[rfpath] = + rtlphy->rfreg_chnlval + [rfpath] & (~BIT(18)); + rtlphy->rfreg_chnlval[rfpath] |= + (BIT(16) | BIT(8)); + } else { + rtlphy->rfreg_chnlval[rfpath] &= + ~(BIT(8) | BIT(16) | BIT(18)); + } + rtl_set_rfreg(hw, (enum radio_path)rfpath, + currentcmd->para1, + RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[rfpath]); + _rtl92d_phy_reload_imr_setting(hw, channel, + rfpath); + } + _rtl92d_phy_switch_rf_setting(hw, channel); + /* do IQK when all parameters are ready */ + rtl92d_phy_reload_iqk_setting(hw, channel); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + break; + } while (true); + (*delay) = currentcmd->msdelay; + (*step)++; + return false; +} + +u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 delay; + u32 timeout = 1000, timecount = 0; + u8 channel = rtlphy->current_channel; + u32 ret_value; + + if (rtlphy->sw_chnl_inprogress) + return 0; + if (rtlphy->set_bwmode_inprogress) + return 0; + + if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) { + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + "sw_chnl_inprogress false driver sleep or unload\n"); + return 0; + } + while (rtlphy->lck_inprogress && timecount < timeout) { + mdelay(50); + timecount += 50; + } + if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && + rtlhal->bandset == BAND_ON_BOTH) { + ret_value = rtl_get_bbreg(hw, RFPGA0_XAB_RFPARAMETER, + MASKDWORD); + if (rtlphy->current_channel > 14 && !(ret_value & BIT(0))) + rtl92d_phy_switch_wirelessband(hw, BAND_ON_5G); + else if (rtlphy->current_channel <= 14 && (ret_value & BIT(0))) + rtl92d_phy_switch_wirelessband(hw, BAND_ON_2_4G); + } + switch (rtlhal->current_bandtype) { + case BAND_ON_5G: + /* Get first channel error when change between + * 5G and 2.4G band. */ + if (channel <= 14) + return 0; + RT_ASSERT((channel > 14), "5G but channel<=14\n"); + break; + case BAND_ON_2_4G: + /* Get first channel error when change between + * 5G and 2.4G band. */ + if (channel > 14) + return 0; + RT_ASSERT((channel <= 14), "2G but channel>14\n"); + break; + default: + RT_ASSERT(false, "Invalid WirelessMode(%#x)!!\n", + rtlpriv->mac80211.mode); + break; + } + rtlphy->sw_chnl_inprogress = true; + if (channel == 0) + channel = 1; + rtlphy->sw_chnl_stage = 0; + rtlphy->sw_chnl_step = 0; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "switch to channel%d\n", rtlphy->current_channel); + + do { + if (!rtlphy->sw_chnl_inprogress) + break; + if (!_rtl92d_phy_sw_chnl_step_by_step(hw, + rtlphy->current_channel, + &rtlphy->sw_chnl_stage, &rtlphy->sw_chnl_step, &delay)) { + if (delay > 0) + mdelay(delay); + else + continue; + } else { + rtlphy->sw_chnl_inprogress = false; + } + break; + } while (true); + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); + rtlphy->sw_chnl_inprogress = false; + return 1; +} + +static void rtl92d_phy_set_io(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *de_digtable = &rtlpriv->dm_digtable; + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "--->Cmd(%#x), set_io_inprogress(%d)\n", + rtlphy->current_io_type, rtlphy->set_io_inprogress); + switch (rtlphy->current_io_type) { + case IO_CMD_RESUME_DM_BY_SCAN: + de_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; + rtl92d_dm_write_dig(hw); + rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel); + break; + case IO_CMD_PAUSE_DM_BY_SCAN: + rtlphy->initgain_backup.xaagccore1 = de_digtable->cur_igvalue; + de_digtable->cur_igvalue = 0x37; + rtl92d_dm_write_dig(hw); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + rtlphy->set_io_inprogress = false; + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "<---(%#x)\n", + rtlphy->current_io_type); +} + +bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + bool postprocessing = false; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "-->IO Cmd(%#x), set_io_inprogress(%d)\n", + iotype, rtlphy->set_io_inprogress); + do { + switch (iotype) { + case IO_CMD_RESUME_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Resume DM after scan\n"); + postprocessing = true; + break; + case IO_CMD_PAUSE_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Pause DM before scan\n"); + postprocessing = true; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + } while (false); + if (postprocessing && !rtlphy->set_io_inprogress) { + rtlphy->set_io_inprogress = true; + rtlphy->current_io_type = iotype; + } else { + return false; + } + rtl92d_phy_set_io(hw); + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "<--IO Type(%#x)\n", iotype); + return true; +} + +static void _rtl92d_phy_set_rfon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* a. SYS_CLKR 0x08[11] = 1 restore MAC clock */ + /* b. SPS_CTRL 0x11[7:0] = 0x2b */ + if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + /* c. For PCIE: SYS_FUNC_EN 0x02[7:0] = 0xE3 enable BB TRX function */ + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + /* RF_ON_EXCEP(d~g): */ + /* d. APSD_CTRL 0x600[7:0] = 0x00 */ + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); + /* e. SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB TRX function again */ + /* f. SYS_FUNC_EN 0x02[7:0] = 0xE3 enable BB TRX function*/ + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + /* g. txpause 0x522[7:0] = 0x00 enable mac tx queue */ + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); +} + +static void _rtl92d_phy_set_rfsleep(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 u4btmp; + u8 delay = 5; + + /* a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue */ + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + /* b. RF path 0 offset 0x00 = 0x00 disable RF */ + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + /* c. APSD_CTRL 0x600[7:0] = 0x40 */ + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + /* d. APSD_CTRL 0x600[7:0] = 0x00 + * APSD_CTRL 0x600[7:0] = 0x00 + * RF path 0 offset 0x00 = 0x00 + * APSD_CTRL 0x600[7:0] = 0x40 + * */ + u4btmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + while (u4btmp != 0 && delay > 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4btmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + delay--; + } + if (delay == 0) { + /* Jump out the LPS turn off sequence to RF_ON_EXCEP */ + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); + + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Fail !!! Switch RF timeout\n"); + return; + } + /* e. For PCIE: SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB TRX function */ + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + /* f. SPS_CTRL 0x11[7:0] = 0x22 */ + if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); + /* g. SYS_CLKR 0x08[11] = 0 gated MAC clock */ +} + +bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + + bool bresult = true; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 i, queue_id; + struct rtl8192_tx_ring *ring = NULL; + + if (rfpwr_state == ppsc->rfpwr_state) + return false; + switch (rfpwr_state) { + case ERFON: + if ((ppsc->rfpwr_state == ERFOFF) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + bool rtstatus; + u32 InitializeCount = 0; + do { + InitializeCount++; + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic enable\n"); + rtstatus = rtl_ps_enable_nic(hw); + } while (!rtstatus && (InitializeCount < 10)); + + RT_CLEAR_PS_LEVEL(ppsc, + RT_RF_OFF_LEVL_HALT_NIC); + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "awake, sleeped:%d ms state_inap:%x\n", + jiffies_to_msecs(jiffies - + ppsc->last_sleep_jiffies), + rtlpriv->psc.state_inap); + ppsc->last_awake_jiffies = jiffies; + _rtl92d_phy_set_rfon(hw); + } + + if (mac->link_state == MAC80211_LINKED) + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_LINK); + else + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + break; + case ERFOFF: + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic disable\n"); + rtl_ps_disable_nic(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } else { + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + else + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_POWER_OFF); + } + break; + case ERFSLEEP: + if (ppsc->rfpwr_state == ERFOFF) + return false; + + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (skb_queue_len(&ring->queue) == 0 || + queue_id == BEACON_QUEUE) { + queue_id++; + continue; + } else if (rtlpci->pdev->current_state != PCI_D0) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 but lower power state!\n", + i + 1, queue_id); + break; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", + i + 1, queue_id, + skb_queue_len(&ring->queue)); + udelay(10); + i++; + } + + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "ERFOFF: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "Set rfsleep awaked:%d ms\n", + jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies)); + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "sleep awaked:%d ms state_inap:%x\n", + jiffies_to_msecs(jiffies - + ppsc->last_awake_jiffies), + rtlpriv->psc.state_inap); + ppsc->last_sleep_jiffies = jiffies; + _rtl92d_phy_set_rfsleep(hw); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + bresult = false; + break; + } + if (bresult) + ppsc->rfpwr_state = rfpwr_state; + return bresult; +} + +void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 offset = REG_MAC_PHY_CTRL_NORMAL; + + switch (rtlhal->macphymode) { + case DUALMAC_DUALPHY: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "MacPhyMode: DUALMAC_DUALPHY\n"); + rtl_write_byte(rtlpriv, offset, 0xF3); + break; + case SINGLEMAC_SINGLEPHY: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "MacPhyMode: SINGLEMAC_SINGLEPHY\n"); + rtl_write_byte(rtlpriv, offset, 0xF4); + break; + case DUALMAC_SINGLEPHY: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "MacPhyMode: DUALMAC_SINGLEPHY\n"); + rtl_write_byte(rtlpriv, offset, 0xF1); + break; + } +} + +void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + switch (rtlhal->macphymode) { + case DUALMAC_SINGLEPHY: + rtlphy->rf_type = RF_2T2R; + rtlhal->version |= RF_TYPE_2T2R; + rtlhal->bandset = BAND_ON_BOTH; + rtlhal->current_bandtype = BAND_ON_2_4G; + break; + + case SINGLEMAC_SINGLEPHY: + rtlphy->rf_type = RF_2T2R; + rtlhal->version |= RF_TYPE_2T2R; + rtlhal->bandset = BAND_ON_BOTH; + rtlhal->current_bandtype = BAND_ON_2_4G; + break; + + case DUALMAC_DUALPHY: + rtlphy->rf_type = RF_1T1R; + rtlhal->version &= RF_TYPE_1T1R; + /* Now we let MAC0 run on 5G band. */ + if (rtlhal->interfaceindex == 0) { + rtlhal->bandset = BAND_ON_5G; + rtlhal->current_bandtype = BAND_ON_5G; + } else { + rtlhal->bandset = BAND_ON_2_4G; + rtlhal->current_bandtype = BAND_ON_2_4G; + } + break; + default: + break; + } +} + +u8 rtl92d_get_chnlgroup_fromarray(u8 chnl) +{ + u8 group; + u8 channel_info[59] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, + 58, 60, 62, 64, 100, 102, 104, 106, 108, + 110, 112, 114, 116, 118, 120, 122, 124, + 126, 128, 130, 132, 134, 136, 138, 140, + 149, 151, 153, 155, 157, 159, 161, 163, + 165 + }; + + if (channel_info[chnl] <= 3) + group = 0; + else if (channel_info[chnl] <= 9) + group = 1; + else if (channel_info[chnl] <= 14) + group = 2; + else if (channel_info[chnl] <= 44) + group = 3; + else if (channel_info[chnl] <= 54) + group = 4; + else if (channel_info[chnl] <= 64) + group = 5; + else if (channel_info[chnl] <= 112) + group = 6; + else if (channel_info[chnl] <= 126) + group = 7; + else if (channel_info[chnl] <= 140) + group = 8; + else if (channel_info[chnl] <= 153) + group = 9; + else if (channel_info[chnl] <= 159) + group = 10; + else + group = 11; + return group; +} + +void rtl92d_phy_set_poweron(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + unsigned long flags; + u8 value8; + u16 i; + u32 mac_reg = (rtlhal->interfaceindex == 0 ? REG_MAC0 : REG_MAC1); + + /* notice fw know band status 0x81[1]/0x53[1] = 0: 5G, 1: 2G */ + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + value8 = rtl_read_byte(rtlpriv, mac_reg); + value8 |= BIT(1); + rtl_write_byte(rtlpriv, mac_reg, value8); + } else { + value8 = rtl_read_byte(rtlpriv, mac_reg); + value8 &= (~BIT(1)); + rtl_write_byte(rtlpriv, mac_reg, value8); + } + + if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY) { + value8 = rtl_read_byte(rtlpriv, REG_MAC0); + rtl_write_byte(rtlpriv, REG_MAC0, value8 | MAC0_ON); + } else { + spin_lock_irqsave(&globalmutex_power, flags); + if (rtlhal->interfaceindex == 0) { + value8 = rtl_read_byte(rtlpriv, REG_MAC0); + rtl_write_byte(rtlpriv, REG_MAC0, value8 | MAC0_ON); + } else { + value8 = rtl_read_byte(rtlpriv, REG_MAC1); + rtl_write_byte(rtlpriv, REG_MAC1, value8 | MAC1_ON); + } + value8 = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS); + spin_unlock_irqrestore(&globalmutex_power, flags); + for (i = 0; i < 200; i++) { + if ((value8 & BIT(7)) == 0) { + break; + } else { + udelay(500); + spin_lock_irqsave(&globalmutex_power, flags); + value8 = rtl_read_byte(rtlpriv, + REG_POWER_OFF_IN_PROCESS); + spin_unlock_irqrestore(&globalmutex_power, + flags); + } + } + if (i == 200) + RT_ASSERT(false, "Another mac power off over time\n"); + } +} + +void rtl92d_phy_config_maccoexist_rfpage(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (rtlpriv->rtlhal.macphymode) { + case DUALMAC_DUALPHY: + rtl_write_byte(rtlpriv, REG_DMC, 0x0); + rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x08); + rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x13ff); + break; + case DUALMAC_SINGLEPHY: + rtl_write_byte(rtlpriv, REG_DMC, 0xf8); + rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x08); + rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x13ff); + break; + case SINGLEMAC_SINGLEPHY: + rtl_write_byte(rtlpriv, REG_DMC, 0x0); + rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x10); + rtl_write_word(rtlpriv, (REG_TRXFF_BNDY + 2), 0x27FF); + break; + default: + break; + } +} + +void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 rfpath, i; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "==>\n"); + /* r_select_5G for path_A/B 0 for 2.4G, 1 for 5G */ + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + /* r_select_5G for path_A/B,0x878 */ + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(0), 0x0); + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0x0); + if (rtlhal->macphymode != DUALMAC_DUALPHY) { + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(16), 0x0); + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(31), 0x0); + } + /* rssi_table_select:index 0 for 2.4G.1~3 for 5G,0xc78 */ + rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, BIT(6) | BIT(7), 0x0); + /* fc_area 0xd2c */ + rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(14) | BIT(13), 0x0); + /* 5G LAN ON */ + rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0xa); + /* TX BB gain shift*1,Just for testchip,0xc80,0xc88 */ + rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, MASKDWORD, + 0x40000100); + rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, MASKDWORD, + 0x40000100); + if (rtlhal->macphymode == DUALMAC_DUALPHY) { + rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, + BIT(10) | BIT(6) | BIT(5), + ((rtlefuse->eeprom_c9 & BIT(3)) >> 3) | + (rtlefuse->eeprom_c9 & BIT(1)) | + ((rtlefuse->eeprom_cc & BIT(1)) << 4)); + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, + BIT(10) | BIT(6) | BIT(5), + ((rtlefuse->eeprom_c9 & BIT(2)) >> 2) | + ((rtlefuse->eeprom_c9 & BIT(0)) << 1) | + ((rtlefuse->eeprom_cc & BIT(0)) << 5)); + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0); + } else { + rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, + BIT(26) | BIT(22) | BIT(21) | BIT(10) | + BIT(6) | BIT(5), + ((rtlefuse->eeprom_c9 & BIT(3)) >> 3) | + (rtlefuse->eeprom_c9 & BIT(1)) | + ((rtlefuse->eeprom_cc & BIT(1)) << 4) | + ((rtlefuse->eeprom_c9 & BIT(7)) << 9) | + ((rtlefuse->eeprom_c9 & BIT(5)) << 12) | + ((rtlefuse->eeprom_cc & BIT(3)) << 18)); + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, + BIT(10) | BIT(6) | BIT(5), + ((rtlefuse->eeprom_c9 & BIT(2)) >> 2) | + ((rtlefuse->eeprom_c9 & BIT(0)) << 1) | + ((rtlefuse->eeprom_cc & BIT(0)) << 5)); + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(10) | BIT(6) | BIT(5), + ((rtlefuse->eeprom_c9 & BIT(6)) >> 6) | + ((rtlefuse->eeprom_c9 & BIT(4)) >> 3) | + ((rtlefuse->eeprom_cc & BIT(2)) << 3)); + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, + BIT(31) | BIT(15), 0); + } + /* 1.5V_LDO */ + } else { + /* r_select_5G for path_A/B */ + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(0), 0x1); + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0x1); + if (rtlhal->macphymode != DUALMAC_DUALPHY) { + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(16), 0x1); + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(31), 0x1); + } + /* rssi_table_select:index 0 for 2.4G.1~3 for 5G */ + rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, BIT(6) | BIT(7), 0x1); + /* fc_area */ + rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(14) | BIT(13), 0x1); + /* 5G LAN ON */ + rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0x0); + /* TX BB gain shift,Just for testchip,0xc80,0xc88 */ + if (rtlefuse->internal_pa_5g[0]) + rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, MASKDWORD, + 0x2d4000b5); + else + rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, MASKDWORD, + 0x20000080); + if (rtlefuse->internal_pa_5g[1]) + rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, MASKDWORD, + 0x2d4000b5); + else + rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, MASKDWORD, + 0x20000080); + if (rtlhal->macphymode == DUALMAC_DUALPHY) { + rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, + BIT(10) | BIT(6) | BIT(5), + (rtlefuse->eeprom_cc & BIT(5))); + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10), + ((rtlefuse->eeprom_cc & BIT(4)) >> 4)); + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), + (rtlefuse->eeprom_cc & BIT(4)) >> 4); + } else { + rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, + BIT(26) | BIT(22) | BIT(21) | BIT(10) | + BIT(6) | BIT(5), + (rtlefuse->eeprom_cc & BIT(5)) | + ((rtlefuse->eeprom_cc & BIT(7)) << 14)); + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10), + ((rtlefuse->eeprom_cc & BIT(4)) >> 4)); + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(10), + ((rtlefuse->eeprom_cc & BIT(6)) >> 6)); + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, + BIT(31) | BIT(15), + ((rtlefuse->eeprom_cc & BIT(4)) >> 4) | + ((rtlefuse->eeprom_cc & BIT(6)) << 10)); + } + } + /* update IQK related settings */ + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, MASKDWORD, 0x40000100); + rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, MASKDWORD, 0x40000100); + rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000, 0x00); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30) | BIT(28) | + BIT(26) | BIT(24), 0x00); + rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000, 0x00); + rtl_set_bbreg(hw, 0xca0, 0xF0000000, 0x00); + rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, 0x00); + + /* Update RF */ + for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; + rfpath++) { + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + /* MOD_AG for RF path_A 0x18 BIT8,BIT16 */ + rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) | BIT(16) | + BIT(18), 0); + /* RF0x0b[16:14] =3b'111 */ + rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B, + 0x1c000, 0x07); + } else { + /* MOD_AG for RF path_A 0x18 BIT8,BIT16 */ + rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) | + BIT(16) | BIT(18), + (BIT(16) | BIT(8)) >> 8); + } + } + /* Update for all band. */ + /* DMDP */ + if (rtlphy->rf_type == RF_1T1R) { + /* Use antenna 0,0xc04,0xd04 */ + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x11); + rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x1); + + /* enable ad/da clock1 for dual-phy reg0x888 */ + if (rtlhal->interfaceindex == 0) { + rtl_set_bbreg(hw, RFPGA0_ADDALLOCKEN, BIT(12) | + BIT(13), 0x3); + } else { + rtl92d_phy_enable_anotherphy(hw, false); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "MAC1 use DBI to update 0x888\n"); + /* 0x888 */ + rtl92de_write_dword_dbi(hw, RFPGA0_ADDALLOCKEN, + rtl92de_read_dword_dbi(hw, + RFPGA0_ADDALLOCKEN, + BIT(3)) | BIT(12) | BIT(13), + BIT(3)); + rtl92d_phy_powerdown_anotherphy(hw, false); + } + } else { + /* Single PHY */ + /* Use antenna 0 & 1,0xc04,0xd04 */ + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x33); + rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x3); + /* disable ad/da clock1,0x888 */ + rtl_set_bbreg(hw, RFPGA0_ADDALLOCKEN, BIT(12) | BIT(13), 0); + } + for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; + rfpath++) { + rtlphy->rfreg_chnlval[rfpath] = rtl_get_rfreg(hw, rfpath, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtlphy->reg_rf3c[rfpath] = rtl_get_rfreg(hw, rfpath, 0x3C, + RFREG_OFFSET_MASK); + } + for (i = 0; i < 2; i++) + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "RF 0x18 = 0x%x\n", + rtlphy->rfreg_chnlval[i]); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "<==\n"); + +} + +bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 u1btmp; + unsigned long flags; + + if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY) { + u1btmp = rtl_read_byte(rtlpriv, REG_MAC0); + rtl_write_byte(rtlpriv, REG_MAC0, u1btmp & (~MAC0_ON)); + return true; + } + spin_lock_irqsave(&globalmutex_power, flags); + if (rtlhal->interfaceindex == 0) { + u1btmp = rtl_read_byte(rtlpriv, REG_MAC0); + rtl_write_byte(rtlpriv, REG_MAC0, u1btmp & (~MAC0_ON)); + u1btmp = rtl_read_byte(rtlpriv, REG_MAC1); + u1btmp &= MAC1_ON; + } else { + u1btmp = rtl_read_byte(rtlpriv, REG_MAC1); + rtl_write_byte(rtlpriv, REG_MAC1, u1btmp & (~MAC1_ON)); + u1btmp = rtl_read_byte(rtlpriv, REG_MAC0); + u1btmp &= MAC0_ON; + } + if (u1btmp) { + spin_unlock_irqrestore(&globalmutex_power, flags); + return false; + } + u1btmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS); + u1btmp |= BIT(7); + rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1btmp); + spin_unlock_irqrestore(&globalmutex_power, flags); + return true; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h new file mode 100644 index 000000000000..48d5c6835b6a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.h @@ -0,0 +1,173 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92D_PHY_H__ +#define __RTL92D_PHY_H__ + +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define MAX_DOZE_WAITING_TIMES_9x 64 + +#define RT_CANNOT_IO(hw) false +#define HIGHPOWER_RADIOA_ARRAYLEN 22 + +#define MAX_TOLERANCE 5 + +#define APK_BB_REG_NUM 5 +#define APK_AFE_REG_NUM 16 +#define APK_CURVE_REG_NUM 4 +#define PATH_NUM 2 + +#define LOOP_LIMIT 5 +#define MAX_STALL_TIME 50 +#define ANTENNA_DIVERSITY_VALUE 0x80 +#define MAX_TXPWR_IDX_NMODE_92S 63 +#define RESET_CNT_LIMIT 3 + +#define IQK_ADDA_REG_NUM 16 +#define IQK_BB_REG_NUM 10 +#define IQK_BB_REG_NUM_test 6 +#define IQK_MAC_REG_NUM 4 +#define RX_INDEX_MAPPING_NUM 15 + +#define IQK_DELAY_TIME 1 + +#define CT_OFFSET_MAC_ADDR 0X16 + +#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A +#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 +#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 +#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 +#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C + +#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F +#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 + +#define CT_OFFSET_CHANNEL_PLAH 0x75 +#define CT_OFFSET_THERMAL_METER 0x78 +#define CT_OFFSET_RF_OPTION 0x79 +#define CT_OFFSET_VERSION 0x7E +#define CT_OFFSET_CUSTOMER_ID 0x7F + +enum swchnlcmd_id { + CMDID_END, + CMDID_SET_TXPOWEROWER_LEVEL, + CMDID_BBREGWRITE10, + CMDID_WRITEPORT_ULONG, + CMDID_WRITEPORT_USHORT, + CMDID_WRITEPORT_UCHAR, + CMDID_RF_WRITEREG, +}; + +struct swchnlcmd { + enum swchnlcmd_id cmdid; + u32 para1; + u32 para2; + u32 msdelay; +}; + +enum baseband_config_type { + BASEBAND_CONFIG_PHY_REG = 0, + BASEBAND_CONFIG_AGC_TAB = 1, +}; + +enum rf_content { + radioa_txt = 0, + radiob_txt = 1, + radioc_txt = 2, + radiod_txt = 3 +}; + +static inline void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw, + unsigned long *flag) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.interfaceindex == 1) + spin_lock_irqsave(&rtlpriv->locks.cck_and_rw_pagea_lock, *flag); +} + +static inline void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw, + unsigned long *flag) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.interfaceindex == 1) + spin_unlock_irqrestore(&rtlpriv->locks.cck_and_rw_pagea_lock, + *flag); +} + +u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask); +void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, u32 data); +u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask); +void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask, u32 data); +bool rtl92d_phy_mac_config(struct ieee80211_hw *hw); +bool rtl92d_phy_bb_config(struct ieee80211_hw *hw); +bool rtl92d_phy_rf_config(struct ieee80211_hw *hw); +bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); +u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw); +bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum rf_content content, + enum radio_path rfpath); +bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); +bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); + +void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw); +void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw); +u8 rtl92d_get_chnlgroup_fromarray(u8 chnl); +void rtl92d_phy_set_poweron(struct ieee80211_hw *hw); +void rtl92d_phy_config_maccoexist_rfpage(struct ieee80211_hw *hw); +bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw); +void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw); +void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw); +void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); +void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw); +void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw); +void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw, + unsigned long *flag); +void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw, + unsigned long *flag); +u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl); +void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h new file mode 100644 index 000000000000..315a298bab06 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/reg.h @@ -0,0 +1,1299 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92D_REG_H__ +#define __RTL92D_REG_H__ + +/* ----------------------------------------------------- */ +/* 0x0000h ~ 0x00FFh System Configuration */ +/* ----------------------------------------------------- */ +#define REG_SYS_ISO_CTRL 0x0000 +#define REG_SYS_FUNC_EN 0x0002 +#define REG_APS_FSMCO 0x0004 +#define REG_SYS_CLKR 0x0008 +#define REG_9346CR 0x000A +#define REG_EE_VPD 0x000C +#define REG_AFE_MISC 0x0010 +#define REG_SPS0_CTRL 0x0011 +#define REG_POWER_OFF_IN_PROCESS 0x0017 +#define REG_SPS_OCP_CFG 0x0018 +#define REG_RSV_CTRL 0x001C +#define REG_RF_CTRL 0x001F +#define REG_LDOA15_CTRL 0x0020 +#define REG_LDOV12D_CTRL 0x0021 +#define REG_LDOHCI12_CTRL 0x0022 +#define REG_LPLDO_CTRL 0x0023 +#define REG_AFE_XTAL_CTRL 0x0024 +#define REG_AFE_PLL_CTRL 0x0028 +/* for 92d, DMDP,SMSP,DMSP contrl */ +#define REG_MAC_PHY_CTRL 0x002c +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define REG_PWR_DATA 0x0038 +#define REG_CAL_TIMER 0x003C +#define REG_ACLK_MON 0x003E +#define REG_GPIO_MUXCFG 0x0040 +#define REG_GPIO_IO_SEL 0x0042 +#define REG_MAC_PINMUX_CFG 0x0043 +#define REG_GPIO_PIN_CTRL 0x0044 +#define REG_GPIO_INTM 0x0048 +#define REG_LEDCFG0 0x004C +#define REG_LEDCFG1 0x004D +#define REG_LEDCFG2 0x004E +#define REG_LEDCFG3 0x004F +#define REG_FSIMR 0x0050 +#define REG_FSISR 0x0054 + +#define REG_MCUFWDL 0x0080 + +#define REG_HMEBOX_EXT_0 0x0088 +#define REG_HMEBOX_EXT_1 0x008A +#define REG_HMEBOX_EXT_2 0x008C +#define REG_HMEBOX_EXT_3 0x008E + +#define REG_BIST_SCAN 0x00D0 +#define REG_BIST_RPT 0x00D4 +#define REG_BIST_ROM_RPT 0x00D8 +#define REG_USB_SIE_INTF 0x00E0 +#define REG_PCIE_MIO_INTF 0x00E4 +#define REG_PCIE_MIO_INTD 0x00E8 +#define REG_HPON_FSM 0x00EC +#define REG_SYS_CFG 0x00F0 +#define REG_MAC_PHY_CTRL_NORMAL 0x00f8 + +#define REG_MAC0 0x0081 +#define REG_MAC1 0x0053 +#define FW_MAC0_READY 0x18 +#define FW_MAC1_READY 0x1A +#define MAC0_ON BIT(7) +#define MAC1_ON BIT(0) +#define MAC0_READY BIT(0) +#define MAC1_READY BIT(0) + +/* ----------------------------------------------------- */ +/* 0x0100h ~ 0x01FFh MACTOP General Configuration */ +/* ----------------------------------------------------- */ +#define REG_CR 0x0100 +#define REG_PBP 0x0104 +#define REG_TRXDMA_CTRL 0x010C +#define REG_TRXFF_BNDY 0x0114 +#define REG_TRXFF_STATUS 0x0118 +#define REG_RXFF_PTR 0x011C +#define REG_HIMR 0x0120 +#define REG_HISR 0x0124 +#define REG_HIMRE 0x0128 +#define REG_HISRE 0x012C +#define REG_CPWM 0x012F +#define REG_FWIMR 0x0130 +#define REG_FWISR 0x0134 +#define REG_PKTBUF_DBG_CTRL 0x0140 +#define REG_PKTBUF_DBG_DATA_L 0x0144 +#define REG_PKTBUF_DBG_DATA_H 0x0148 + +#define REG_TC0_CTRL 0x0150 +#define REG_TC1_CTRL 0x0154 +#define REG_TC2_CTRL 0x0158 +#define REG_TC3_CTRL 0x015C +#define REG_TC4_CTRL 0x0160 +#define REG_TCUNIT_BASE 0x0164 +#define REG_MBIST_START 0x0174 +#define REG_MBIST_DONE 0x0178 +#define REG_MBIST_FAIL 0x017C +#define REG_C2HEVT_MSG_NORMAL 0x01A0 +#define REG_C2HEVT_MSG_TEST 0x01B8 +#define REG_C2HEVT_CLEAR 0x01BF +#define REG_MCUTST_1 0x01c0 +#define REG_FMETHR 0x01C8 +#define REG_HMETFR 0x01CC +#define REG_HMEBOX_0 0x01D0 +#define REG_HMEBOX_1 0x01D4 +#define REG_HMEBOX_2 0x01D8 +#define REG_HMEBOX_3 0x01DC + +#define REG_LLT_INIT 0x01E0 +#define REG_BB_ACCEESS_CTRL 0x01E8 +#define REG_BB_ACCESS_DATA 0x01EC + + +/* ----------------------------------------------------- */ +/* 0x0200h ~ 0x027Fh TXDMA Configuration */ +/* ----------------------------------------------------- */ +#define REG_RQPN 0x0200 +#define REG_FIFOPAGE 0x0204 +#define REG_TDECTRL 0x0208 +#define REG_TXDMA_OFFSET_CHK 0x020C +#define REG_TXDMA_STATUS 0x0210 +#define REG_RQPN_NPQ 0x0214 + +/* ----------------------------------------------------- */ +/* 0x0280h ~ 0x02FFh RXDMA Configuration */ +/* ----------------------------------------------------- */ +#define REG_RXDMA_AGG_PG_TH 0x0280 +#define REG_RXPKT_NUM 0x0284 +#define REG_RXDMA_STATUS 0x0288 + +/* ----------------------------------------------------- */ +/* 0x0300h ~ 0x03FFh PCIe */ +/* ----------------------------------------------------- */ +#define REG_PCIE_CTRL_REG 0x0300 +#define REG_INT_MIG 0x0304 +#define REG_BCNQ_DESA 0x0308 +#define REG_HQ_DESA 0x0310 +#define REG_MGQ_DESA 0x0318 +#define REG_VOQ_DESA 0x0320 +#define REG_VIQ_DESA 0x0328 +#define REG_BEQ_DESA 0x0330 +#define REG_BKQ_DESA 0x0338 +#define REG_RX_DESA 0x0340 +#define REG_DBI 0x0348 +#define REG_DBI_WDATA 0x0348 +#define REG_DBI_RDATA 0x034C +#define REG_DBI_CTRL 0x0350 +#define REG_DBI_FLAG 0x0352 +#define REG_MDIO 0x0354 +#define REG_DBG_SEL 0x0360 +#define REG_PCIE_HRPWM 0x0361 +#define REG_PCIE_HCPWM 0x0363 +#define REG_UART_CTRL 0x0364 +#define REG_UART_TX_DESA 0x0370 +#define REG_UART_RX_DESA 0x0378 + +/* ----------------------------------------------------- */ +/* 0x0400h ~ 0x047Fh Protocol Configuration */ +/* ----------------------------------------------------- */ +#define REG_VOQ_INFORMATION 0x0400 +#define REG_VIQ_INFORMATION 0x0404 +#define REG_BEQ_INFORMATION 0x0408 +#define REG_BKQ_INFORMATION 0x040C +#define REG_MGQ_INFORMATION 0x0410 +#define REG_HGQ_INFORMATION 0x0414 +#define REG_BCNQ_INFORMATION 0x0418 + + +#define REG_CPU_MGQ_INFORMATION 0x041C +#define REG_FWHW_TXQ_CTRL 0x0420 +#define REG_HWSEQ_CTRL 0x0423 +#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 +#define REG_TXPKTBUF_MGQ_BDNY 0x0425 +#define REG_MULTI_BCNQ_EN 0x0426 +#define REG_MULTI_BCNQ_OFFSET 0x0427 +#define REG_SPEC_SIFS 0x0428 +#define REG_RL 0x042A +#define REG_DARFRC 0x0430 +#define REG_RARFRC 0x0438 +#define REG_RRSR 0x0440 +#define REG_ARFR0 0x0444 +#define REG_ARFR1 0x0448 +#define REG_ARFR2 0x044C +#define REG_ARFR3 0x0450 +#define REG_AGGLEN_LMT 0x0458 +#define REG_AMPDU_MIN_SPACE 0x045C +#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D +#define REG_FAST_EDCA_CTRL 0x0460 +#define REG_RD_RESP_PKT_TH 0x0463 +#define REG_INIRTS_RATE_SEL 0x0480 +#define REG_INIDATA_RATE_SEL 0x0484 +#define REG_POWER_STATUS 0x04A4 +#define REG_POWER_STAGE1 0x04B4 +#define REG_POWER_STAGE2 0x04B8 +#define REG_PKT_LIFE_TIME 0x04C0 +#define REG_STBC_SETTING 0x04C4 +#define REG_PROT_MODE_CTRL 0x04C8 +#define REG_MAX_AGGR_NUM 0x04CA +#define REG_RTS_MAX_AGGR_NUM 0x04CB +#define REG_BAR_MODE_CTRL 0x04CC +#define REG_RA_TRY_RATE_AGG_LMT 0x04CF +#define REG_EARLY_MODE_CONTROL 0x4D0 +#define REG_NQOS_SEQ 0x04DC +#define REG_QOS_SEQ 0x04DE +#define REG_NEED_CPU_HANDLE 0x04E0 +#define REG_PKT_LOSE_RPT 0x04E1 +#define REG_PTCL_ERR_STATUS 0x04E2 +#define REG_DUMMY 0x04FC + +/* ----------------------------------------------------- */ +/* 0x0500h ~ 0x05FFh EDCA Configuration */ +/* ----------------------------------------------------- */ +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050C +#define REG_BCNTCFG 0x0510 +#define REG_PIFS 0x0512 +#define REG_RDG_PIFS 0x0513 +#define REG_SIFS_CTX 0x0514 +#define REG_SIFS_TRX 0x0516 +#define REG_AGGR_BREAK_TIME 0x051A +#define REG_SLOT 0x051B +#define REG_TX_PTCL_CTRL 0x0520 +#define REG_TXPAUSE 0x0522 +#define REG_DIS_TXREQ_CLR 0x0523 +#define REG_RD_CTRL 0x0524 +#define REG_TBTT_PROHIBIT 0x0540 +#define REG_RD_NAV_NXT 0x0544 +#define REG_NAV_PROT_LEN 0x0546 +#define REG_BCN_CTRL 0x0550 +#define REG_USTIME_TSF 0x0551 +#define REG_MBID_NUM 0x0552 +#define REG_DUAL_TSF_RST 0x0553 +#define REG_BCN_INTERVAL 0x0554 +#define REG_MBSSID_BCN_SPACE 0x0554 +#define REG_DRVERLYINT 0x0558 +#define REG_BCNDMATIM 0x0559 +#define REG_ATIMWND 0x055A +#define REG_BCN_MAX_ERR 0x055D +#define REG_RXTSF_OFFSET_CCK 0x055E +#define REG_RXTSF_OFFSET_OFDM 0x055F +#define REG_TSFTR 0x0560 +#define REG_INIT_TSFTR 0x0564 +#define REG_PSTIMER 0x0580 +#define REG_TIMER0 0x0584 +#define REG_TIMER1 0x0588 +#define REG_ACMHWCTRL 0x05C0 +#define REG_ACMRSTCTRL 0x05C1 +#define REG_ACMAVG 0x05C2 +#define REG_VO_ADMTIME 0x05C4 +#define REG_VI_ADMTIME 0x05C6 +#define REG_BE_ADMTIME 0x05C8 +#define REG_EDCA_RANDOM_GEN 0x05CC +#define REG_SCH_TXCMD 0x05D0 + +/* Dual MAC Co-Existence Register */ +#define REG_DMC 0x05F0 + +/* ----------------------------------------------------- */ +/* 0x0600h ~ 0x07FFh WMAC Configuration */ +/* ----------------------------------------------------- */ +#define REG_APSD_CTRL 0x0600 +#define REG_BWOPMODE 0x0603 +#define REG_TCR 0x0604 +#define REG_RCR 0x0608 +#define REG_RX_PKT_LIMIT 0x060C +#define REG_RX_DLK_TIME 0x060D +#define REG_RX_DRVINFO_SZ 0x060F + +#define REG_MACID 0x0610 +#define REG_BSSID 0x0618 +#define REG_MAR 0x0620 +#define REG_MBIDCAMCFG 0x0628 + +#define REG_USTIME_EDCA 0x0638 +#define REG_MAC_SPEC_SIFS 0x063A +#define REG_RESP_SIFS_CCK 0x063C +#define REG_RESP_SIFS_OFDM 0x063E +#define REG_ACKTO 0x0640 +#define REG_CTS2TO 0x0641 +#define REG_EIFS 0x0642 + + +/* WMA, BA, CCX */ +#define REG_NAV_CTRL 0x0650 +#define REG_BACAMCMD 0x0654 +#define REG_BACAMCONTENT 0x0658 +#define REG_LBDLY 0x0660 +#define REG_FWDLY 0x0661 +#define REG_RXERR_RPT 0x0664 +#define REG_WMAC_TRXPTCL_CTL 0x0668 + + +/* Security */ +#define REG_CAMCMD 0x0670 +#define REG_CAMWRITE 0x0674 +#define REG_CAMREAD 0x0678 +#define REG_CAMDBG 0x067C +#define REG_SECCFG 0x0680 + +/* Power */ +#define REG_WOW_CTRL 0x0690 +#define REG_PSSTATUS 0x0691 +#define REG_PS_RX_INFO 0x0692 +#define REG_LPNAV_CTRL 0x0694 +#define REG_WKFMCAM_CMD 0x0698 +#define REG_WKFMCAM_RWD 0x069C +#define REG_RXFLTMAP0 0x06A0 +#define REG_RXFLTMAP1 0x06A2 +#define REG_RXFLTMAP2 0x06A4 +#define REG_BCN_PSR_RPT 0x06A8 +#define REG_CALB32K_CTRL 0x06AC +#define REG_PKT_MON_CTRL 0x06B4 +#define REG_BT_COEX_TABLE 0x06C0 +#define REG_WMAC_RESP_TXINFO 0x06D8 + + +/* ----------------------------------------------------- */ +/* Redifine 8192C register definition for compatibility */ +/* ----------------------------------------------------- */ +#define CR9346 REG_9346CR +#define MSR (REG_CR + 2) +#define ISR REG_HISR +#define TSFR REG_TSFTR + +#define MACIDR0 REG_MACID +#define MACIDR4 (REG_MACID + 4) + +#define PBP REG_PBP + +#define IDR0 MACIDR0 +#define IDR4 MACIDR4 + +/* ----------------------------------------------------- */ +/* 8192C (MSR) Media Status Register(Offset 0x4C, 8 bits)*/ +/* ----------------------------------------------------- */ +#define MSR_NOLINK 0x00 +#define MSR_ADHOC 0x01 +#define MSR_INFRA 0x02 +#define MSR_AP 0x03 +#define MSR_MASK 0x03 + +/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */ +/* ----------------------------------------------------- */ +/* 8192C Response Rate Set Register(offset 0x181, 24bits)*/ +/* ----------------------------------------------------- */ +#define RRSR_RSC_OFFSET 21 +#define RRSR_SHORT_OFFSET 23 +#define RRSR_RSC_BW_40M 0x600000 +#define RRSR_RSC_UPSUBCHNL 0x400000 +#define RRSR_RSC_LOWSUBCHNL 0x200000 +#define RRSR_SHORT 0x800000 +#define RRSR_1M BIT0 +#define RRSR_2M BIT1 +#define RRSR_5_5M BIT2 +#define RRSR_11M BIT3 +#define RRSR_6M BIT4 +#define RRSR_9M BIT5 +#define RRSR_12M BIT6 +#define RRSR_18M BIT7 +#define RRSR_24M BIT8 +#define RRSR_36M BIT9 +#define RRSR_48M BIT10 +#define RRSR_54M BIT11 +#define RRSR_MCS0 BIT12 +#define RRSR_MCS1 BIT13 +#define RRSR_MCS2 BIT14 +#define RRSR_MCS3 BIT15 +#define RRSR_MCS4 BIT16 +#define RRSR_MCS5 BIT17 +#define RRSR_MCS6 BIT18 +#define RRSR_MCS7 BIT19 +#define BRSR_ACKSHORTPMB BIT23 + +/* ----------------------------------------------------- */ +/* 8192C Rate Definition */ +/* ----------------------------------------------------- */ +/* CCK */ +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +/* OFDM */ +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +/* MCS 1 Spatial Stream */ +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +/* MCS 2 Spatial Stream */ +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 + +/* CCK */ +#define RATE_1M BIT(0) +#define RATE_2M BIT(1) +#define RATE_5_5M BIT(2) +#define RATE_11M BIT(3) +/* OFDM */ +#define RATE_6M BIT(4) +#define RATE_9M BIT(5) +#define RATE_12M BIT(6) +#define RATE_18M BIT(7) +#define RATE_24M BIT(8) +#define RATE_36M BIT(9) +#define RATE_48M BIT(10) +#define RATE_54M BIT(11) +/* MCS 1 Spatial Stream */ +#define RATE_MCS0 BIT(12) +#define RATE_MCS1 BIT(13) +#define RATE_MCS2 BIT(14) +#define RATE_MCS3 BIT(15) +#define RATE_MCS4 BIT(16) +#define RATE_MCS5 BIT(17) +#define RATE_MCS6 BIT(18) +#define RATE_MCS7 BIT(19) +/* MCS 2 Spatial Stream */ +#define RATE_MCS8 BIT(20) +#define RATE_MCS9 BIT(21) +#define RATE_MCS10 BIT(22) +#define RATE_MCS11 BIT(23) +#define RATE_MCS12 BIT(24) +#define RATE_MCS13 BIT(25) +#define RATE_MCS14 BIT(26) +#define RATE_MCS15 BIT(27) + +/* ALL CCK Rate */ +#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | \ + RATR_11M) +#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | \ + RATR_18M | RATR_24M | \ + RATR_36M | RATR_48M | RATR_54M) +#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \ + RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \ + RATR_MCS6 | RATR_MCS7) +#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \ + RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \ + RATR_MCS14 | RATR_MCS15) + +/* ----------------------------------------------------- */ +/* 8192C BW_OPMODE bits (Offset 0x203, 8bit) */ +/* ----------------------------------------------------- */ +#define BW_OPMODE_20MHZ BIT(2) +#define BW_OPMODE_5G BIT(1) +#define BW_OPMODE_11J BIT(0) + + +/* ----------------------------------------------------- */ +/* 8192C CAM Config Setting (offset 0x250, 1 byte) */ +/* ----------------------------------------------------- */ +#define CAM_VALID BIT(15) +#define CAM_NOTVALID 0x0000 +#define CAM_USEDK BIT(5) + +#define CAM_NONE 0x0 +#define CAM_WEP40 0x01 +#define CAM_TKIP 0x02 +#define CAM_AES 0x04 +#define CAM_WEP104 0x05 +#define CAM_SMS4 0x6 + + +#define TOTAL_CAM_ENTRY 32 +#define HALF_CAM_ENTRY 16 + +#define CAM_WRITE BIT(16) +#define CAM_READ 0x00000000 +#define CAM_POLLINIG BIT(31) + +/* 10. Power Save Control Registers (Offset: 0x0260 - 0x02DF) */ +#define WOW_PMEN BIT0 /* Power management Enable. */ +#define WOW_WOMEN BIT1 /* WoW function on or off. */ +#define WOW_MAGIC BIT2 /* Magic packet */ +#define WOW_UWF BIT3 /* Unicast Wakeup frame. */ + +/* 12. Host Interrupt Status Registers (Offset: 0x0300 - 0x030F) */ +/* ----------------------------------------------------- */ +/* 8190 IMR/ISR bits (offset 0xfd, 8bits) */ +/* ----------------------------------------------------- */ +#define IMR8190_DISABLED 0x0 +#define IMR_BCNDMAINT6 BIT(31) +#define IMR_BCNDMAINT5 BIT(30) +#define IMR_BCNDMAINT4 BIT(29) +#define IMR_BCNDMAINT3 BIT(28) +#define IMR_BCNDMAINT2 BIT(27) +#define IMR_BCNDMAINT1 BIT(26) +#define IMR_BCNDOK8 BIT(25) +#define IMR_BCNDOK7 BIT(24) +#define IMR_BCNDOK6 BIT(23) +#define IMR_BCNDOK5 BIT(22) +#define IMR_BCNDOK4 BIT(21) +#define IMR_BCNDOK3 BIT(20) +#define IMR_BCNDOK2 BIT(19) +#define IMR_BCNDOK1 BIT(18) +#define IMR_TIMEOUT2 BIT(17) +#define IMR_TIMEOUT1 BIT(16) +#define IMR_TXFOVW BIT(15) +#define IMR_PSTIMEOUT BIT(14) +#define IMR_BCNINT BIT(13) +#define IMR_RXFOVW BIT(12) +#define IMR_RDU BIT(11) +#define IMR_ATIMEND BIT(10) +#define IMR_BDOK BIT(9) +#define IMR_HIGHDOK BIT(8) +#define IMR_TBDOK BIT(7) +#define IMR_MGNTDOK BIT(6) +#define IMR_TBDER BIT(5) +#define IMR_BKDOK BIT(4) +#define IMR_BEDOK BIT(3) +#define IMR_VIDOK BIT(2) +#define IMR_VODOK BIT(1) +#define IMR_ROK BIT(0) + +#define IMR_TXERR BIT(11) +#define IMR_RXERR BIT(10) +#define IMR_C2HCMD BIT(9) +#define IMR_CPWM BIT(8) +#define IMR_OCPINT BIT(1) +#define IMR_WLANOFF BIT(0) + +/* ----------------------------------------------------- */ +/* 8192C EFUSE */ +/* ----------------------------------------------------- */ +#define HWSET_MAX_SIZE 256 +#define EFUSE_MAX_SECTION 32 +#define EFUSE_REAL_CONTENT_LEN 512 + +/* ----------------------------------------------------- */ +/* 8192C EEPROM/EFUSE share register definition. */ +/* ----------------------------------------------------- */ +#define EEPROM_DEFAULT_TSSI 0x0 +#define EEPROM_DEFAULT_CRYSTALCAP 0x0 +#define EEPROM_DEFAULT_THERMALMETER 0x12 + +#define EEPROM_DEFAULT_TXPOWERLEVEL_2G 0x2C +#define EEPROM_DEFAULT_TXPOWERLEVEL_5G 0x22 + +#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 +/* HT20<->40 default Tx Power Index Difference */ +#define EEPROM_DEFAULT_HT20_DIFF 2 +/* OFDM Tx Power index diff */ +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x4 +#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 +#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 + +#define EEPROM_CHANNEL_PLAN_FCC 0x0 +#define EEPROM_CHANNEL_PLAN_IC 0x1 +#define EEPROM_CHANNEL_PLAN_ETSI 0x2 +#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 +#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 +#define EEPROM_CHANNEL_PLAN_MKK 0x5 +#define EEPROM_CHANNEL_PLAN_MKK1 0x6 +#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 +#define EEPROM_CHANNEL_PLAN_TELEC 0x8 +#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 +#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA +#define EEPROM_CHANNEL_PLAN_NCC 0xB +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + +#define EEPROM_CID_DEFAULT 0x0 +#define EEPROM_CID_TOSHIBA 0x4 +#define EEPROM_CID_CCX 0x10 +#define EEPROM_CID_QMI 0x0D +#define EEPROM_CID_WHQL 0xFE + + +#define RTL8192_EEPROM_ID 0x8129 +#define EEPROM_WAPI_SUPPORT 0x78 + + +#define RTL8190_EEPROM_ID 0x8129 /* 0-1 */ +#define EEPROM_HPON 0x02 /* LDO settings.2-5 */ +#define EEPROM_CLK 0x06 /* Clock settings.6-7 */ +#define EEPROM_MAC_FUNCTION 0x08 /* SE Test mode.8 */ + +#define EEPROM_VID 0x28 /* SE Vendor ID.A-B */ +#define EEPROM_DID 0x2A /* SE Device ID. C-D */ +#define EEPROM_SVID 0x2C /* SE Vendor ID.E-F */ +#define EEPROM_SMID 0x2E /* SE PCI Subsystem ID. 10-11 */ + +#define EEPROM_MAC_ADDR 0x16 /* SEMAC Address. 12-17 */ +#define EEPROM_MAC_ADDR_MAC0_92D 0x55 +#define EEPROM_MAC_ADDR_MAC1_92D 0x5B + +/* 2.4G band Tx power index setting */ +#define EEPROM_CCK_TX_PWR_INX_2G 0x61 +#define EEPROM_HT40_1S_TX_PWR_INX_2G 0x67 +#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_2G 0x6D +#define EEPROM_HT20_TX_PWR_INX_DIFF_2G 0x70 +#define EEPROM_OFDM_TX_PWR_INX_DIFF_2G 0x73 +#define EEPROM_HT40_MAX_PWR_OFFSET_2G 0x76 +#define EEPROM_HT20_MAX_PWR_OFFSET_2G 0x79 + +/*5GL channel 32-64 */ +#define EEPROM_HT40_1S_TX_PWR_INX_5GL 0x7C +#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GL 0x82 +#define EEPROM_HT20_TX_PWR_INX_DIFF_5GL 0x85 +#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GL 0x88 +#define EEPROM_HT40_MAX_PWR_OFFSET_5GL 0x8B +#define EEPROM_HT20_MAX_PWR_OFFSET_5GL 0x8E + +/* 5GM channel 100-140 */ +#define EEPROM_HT40_1S_TX_PWR_INX_5GM 0x91 +#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GM 0x97 +#define EEPROM_HT20_TX_PWR_INX_DIFF_5GM 0x9A +#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GM 0x9D +#define EEPROM_HT40_MAX_PWR_OFFSET_5GM 0xA0 +#define EEPROM_HT20_MAX_PWR_OFFSET_5GM 0xA3 + +/* 5GH channel 149-165 */ +#define EEPROM_HT40_1S_TX_PWR_INX_5GH 0xA6 +#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GH 0xAC +#define EEPROM_HT20_TX_PWR_INX_DIFF_5GH 0xAF +#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GH 0xB2 +#define EEPROM_HT40_MAX_PWR_OFFSET_5GH 0xB5 +#define EEPROM_HT20_MAX_PWR_OFFSET_5GH 0xB8 + +/* Map of supported channels. */ +#define EEPROM_CHANNEL_PLAN 0xBB +#define EEPROM_IQK_DELTA 0xBC +#define EEPROM_LCK_DELTA 0xBC +#define EEPROM_XTAL_K 0xBD /* [7:5] */ +#define EEPROM_TSSI_A_5G 0xBE +#define EEPROM_TSSI_B_5G 0xBF +#define EEPROM_TSSI_AB_5G 0xC0 +#define EEPROM_THERMAL_METER 0xC3 /* [4:0] */ +#define EEPROM_RF_OPT1 0xC4 +#define EEPROM_RF_OPT2 0xC5 +#define EEPROM_RF_OPT3 0xC6 +#define EEPROM_RF_OPT4 0xC7 +#define EEPROM_RF_OPT5 0xC8 +#define EEPROM_RF_OPT6 0xC9 +#define EEPROM_VERSION 0xCA +#define EEPROM_CUSTOMER_ID 0xCB +#define EEPROM_RF_OPT7 0xCC + +#define EEPROM_DEF_PART_NO 0x3FD /* Byte */ +#define EEPROME_CHIP_VERSION_L 0x3FF +#define EEPROME_CHIP_VERSION_H 0x3FE + +/* + * Current IOREG MAP + * 0x0000h ~ 0x00FFh System Configuration (256 Bytes) + * 0x0100h ~ 0x01FFh MACTOP General Configuration (256 Bytes) + * 0x0200h ~ 0x027Fh TXDMA Configuration (128 Bytes) + * 0x0280h ~ 0x02FFh RXDMA Configuration (128 Bytes) + * 0x0300h ~ 0x03FFh PCIE EMAC Reserved Region (256 Bytes) + * 0x0400h ~ 0x04FFh Protocol Configuration (256 Bytes) + * 0x0500h ~ 0x05FFh EDCA Configuration (256 Bytes) + * 0x0600h ~ 0x07FFh WMAC Configuration (512 Bytes) + * 0x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes) + */ + +/* ----------------------------------------------------- */ +/* 8192C (RCR) (Offset 0x608, 32 bits) */ +/* ----------------------------------------------------- */ +#define RCR_APPFCS BIT(31) +#define RCR_APP_MIC BIT(30) +#define RCR_APP_ICV BIT(29) +#define RCR_APP_PHYST_RXFF BIT(28) +#define RCR_APP_BA_SSN BIT(27) +#define RCR_ENMBID BIT(24) +#define RCR_LSIGEN BIT(23) +#define RCR_MFBEN BIT(22) +#define RCR_HTC_LOC_CTRL BIT(14) +#define RCR_AMF BIT(13) +#define RCR_ACF BIT(12) +#define RCR_ADF BIT(11) +#define RCR_AICV BIT(9) +#define RCR_ACRC32 BIT(8) +#define RCR_CBSSID_BCN BIT(7) +#define RCR_CBSSID_DATA BIT(6) +#define RCR_APWRMGT BIT(5) +#define RCR_ADD3 BIT(4) +#define RCR_AB BIT(3) +#define RCR_AM BIT(2) +#define RCR_APM BIT(1) +#define RCR_AAP BIT(0) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 + +/* ----------------------------------------------------- */ +/* 8192C Regsiter Bit and Content definition */ +/* ----------------------------------------------------- */ +/* ----------------------------------------------------- */ +/* 0x0000h ~ 0x00FFh System Configuration */ +/* ----------------------------------------------------- */ + +/* SPS0_CTRL */ +#define SW18_FPWM BIT(3) + + +/* SYS_ISO_CTRL */ +#define ISO_MD2PP BIT(0) +#define ISO_UA2USB BIT(1) +#define ISO_UD2CORE BIT(2) +#define ISO_PA2PCIE BIT(3) +#define ISO_PD2CORE BIT(4) +#define ISO_IP2MAC BIT(5) +#define ISO_DIOP BIT(6) +#define ISO_DIOE BIT(7) +#define ISO_EB2CORE BIT(8) +#define ISO_DIOR BIT(9) + +#define PWC_EV25V BIT(14) +#define PWC_EV12V BIT(15) + + +/* SYS_FUNC_EN */ +#define FEN_BBRSTB BIT(0) +#define FEN_BB_GLB_RSTn BIT(1) +#define FEN_USBA BIT(2) +#define FEN_UPLL BIT(3) +#define FEN_USBD BIT(4) +#define FEN_DIO_PCIE BIT(5) +#define FEN_PCIEA BIT(6) +#define FEN_PPLL BIT(7) +#define FEN_PCIED BIT(8) +#define FEN_DIOE BIT(9) +#define FEN_CPUEN BIT(10) +#define FEN_DCORE BIT(11) +#define FEN_ELDR BIT(12) +#define FEN_DIO_RF BIT(13) +#define FEN_HWPDN BIT(14) +#define FEN_MREGEN BIT(15) + +/* APS_FSMCO */ +#define PFM_LDALL BIT(0) +#define PFM_ALDN BIT(1) +#define PFM_LDKP BIT(2) +#define PFM_WOWL BIT(3) +#define EnPDN BIT(4) +#define PDN_PL BIT(5) +#define APFM_ONMAC BIT(8) +#define APFM_OFF BIT(9) +#define APFM_RSM BIT(10) +#define AFSM_HSUS BIT(11) +#define AFSM_PCIE BIT(12) +#define APDM_MAC BIT(13) +#define APDM_HOST BIT(14) +#define APDM_HPDN BIT(15) +#define RDY_MACON BIT(16) +#define SUS_HOST BIT(17) +#define ROP_ALD BIT(20) +#define ROP_PWR BIT(21) +#define ROP_SPS BIT(22) +#define SOP_MRST BIT(25) +#define SOP_FUSE BIT(26) +#define SOP_ABG BIT(27) +#define SOP_AMB BIT(28) +#define SOP_RCK BIT(29) +#define SOP_A8M BIT(30) +#define XOP_BTCK BIT(31) + +/* SYS_CLKR */ +#define ANAD16V_EN BIT(0) +#define ANA8M BIT(1) +#define MACSLP BIT(4) +#define LOADER_CLK_EN BIT(5) +#define _80M_SSC_DIS BIT(7) +#define _80M_SSC_EN_HO BIT(8) +#define PHY_SSC_RSTB BIT(9) +#define SEC_CLK_EN BIT(10) +#define MAC_CLK_EN BIT(11) +#define SYS_CLK_EN BIT(12) +#define RING_CLK_EN BIT(13) + + +/* 9346CR */ +#define BOOT_FROM_EEPROM BIT(4) +#define EEPROM_EN BIT(5) + +/* AFE_MISC */ +#define AFE_BGEN BIT(0) +#define AFE_MBEN BIT(1) +#define MAC_ID_EN BIT(7) + +/* RSV_CTRL */ +#define WLOCK_ALL BIT(0) +#define WLOCK_00 BIT(1) +#define WLOCK_04 BIT(2) +#define WLOCK_08 BIT(3) +#define WLOCK_40 BIT(4) +#define R_DIS_PRST_0 BIT(5) +#define R_DIS_PRST_1 BIT(6) +#define LOCK_ALL_EN BIT(7) + +/* RF_CTRL */ +#define RF_EN BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + + + +/* LDOA15_CTRL */ +#define LDA15_EN BIT(0) +#define LDA15_STBY BIT(1) +#define LDA15_OBUF BIT(2) +#define LDA15_REG_VOS BIT(3) +#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) + + + +/* LDOV12D_CTRL */ +#define LDV12_EN BIT(0) +#define LDV12_SDBY BIT(1) +#define LPLDO_HSM BIT(2) +#define LPLDO_LSM_DIS BIT(3) +#define _LDV12_VADJ(x) (((x) & 0xF) << 4) + + +/* AFE_XTAL_CTRL */ +#define XTAL_EN BIT(0) +#define XTAL_BSEL BIT(1) +#define _XTAL_BOSC(x) (((x) & 0x3) << 2) +#define _XTAL_CADJ(x) (((x) & 0xF) << 4) +#define XTAL_GATE_USB BIT(8) +#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) +#define XTAL_GATE_AFE BIT(11) +#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) +#define XTAL_RF_GATE BIT(14) +#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) +#define XTAL_GATE_DIG BIT(17) +#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) +#define XTAL_BT_GATE BIT(20) +#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) +#define _XTAL_GPIO(x) (((x) & 0x7) << 23) + + +#define CKDLY_AFE BIT(26) +#define CKDLY_USB BIT(27) +#define CKDLY_DIG BIT(28) +#define CKDLY_BT BIT(29) + + +/* AFE_PLL_CTRL */ +#define APLL_EN BIT(0) +#define APLL_320_EN BIT(1) +#define APLL_FREF_SEL BIT(2) +#define APLL_EDGE_SEL BIT(3) +#define APLL_WDOGB BIT(4) +#define APLL_LPFEN BIT(5) + +#define APLL_REF_CLK_13MHZ 0x1 +#define APLL_REF_CLK_19_2MHZ 0x2 +#define APLL_REF_CLK_20MHZ 0x3 +#define APLL_REF_CLK_25MHZ 0x4 +#define APLL_REF_CLK_26MHZ 0x5 +#define APLL_REF_CLK_38_4MHZ 0x6 +#define APLL_REF_CLK_40MHZ 0x7 + +#define APLL_320EN BIT(14) +#define APLL_80EN BIT(15) +#define APLL_1MEN BIT(24) + + +/* EFUSE_CTRL */ +#define ALD_EN BIT(18) +#define EF_PD BIT(19) +#define EF_FLAG BIT(31) + +/* EFUSE_TEST */ +#define EF_TRPT BIT(7) +#define LDOE25_EN BIT(31) + +/* MCUFWDL */ +#define MCUFWDL_EN BIT(0) +#define MCUFWDL_RDY BIT(1) +#define FWDL_ChkSum_rpt BIT(2) +#define MACINI_RDY BIT(3) +#define BBINI_RDY BIT(4) +#define RFINI_RDY BIT(5) +#define WINTINI_RDY BIT(6) +#define MAC1_WINTINI_RDY BIT(11) +#define CPRST BIT(23) + +/* REG_SYS_CFG */ +#define XCLK_VLD BIT(0) +#define ACLK_VLD BIT(1) +#define UCLK_VLD BIT(2) +#define PCLK_VLD BIT(3) +#define PCIRSTB BIT(4) +#define V15_VLD BIT(5) +#define TRP_B15V_EN BIT(7) +#define SIC_IDLE BIT(8) +#define BD_MAC2 BIT(9) +#define BD_MAC1 BIT(10) +#define IC_MACPHY_MODE BIT(11) +#define PAD_HWPD_IDN BIT(22) +#define TRP_VAUX_EN BIT(23) +#define TRP_BT_EN BIT(24) +#define BD_PKG_SEL BIT(25) +#define BD_HCI_SEL BIT(26) +#define TYPE_ID BIT(27) + +/* LLT_INIT */ +#define _LLT_NO_ACTIVE 0x0 +#define _LLT_WRITE_ACCESS 0x1 +#define _LLT_READ_ACCESS 0x2 + +#define _LLT_INIT_DATA(x) ((x) & 0xFF) +#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) +#define _LLT_OP(x) (((x) & 0x3) << 30) +#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) + + +/* ----------------------------------------------------- */ +/* 0x0400h ~ 0x047Fh Protocol Configuration */ +/* ----------------------------------------------------- */ +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + + +/* ----------------------------------------------------- */ +/* 0x0500h ~ 0x05FFh EDCA Configuration */ +/* ----------------------------------------------------- */ +/* EDCA setting */ +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + +/* ACMHWCTRL */ +#define ACMHW_HWEN BIT(0) +#define ACMHW_BEQEN BIT(1) +#define ACMHW_VIQEN BIT(2) +#define ACMHW_VOQEN BIT(3) + +/* ----------------------------------------------------- */ +/* 0x0600h ~ 0x07FFh WMAC Configuration */ +/* ----------------------------------------------------- */ + +/* TCR */ +#define TSFRST BIT(0) +#define DIS_GCLK BIT(1) +#define PAD_SEL BIT(2) +#define PWR_ST BIT(6) +#define PWRBIT_OW_EN BIT(7) +#define ACRC BIT(8) +#define CFENDFORM BIT(9) +#define ICV BIT(10) + +/* SECCFG */ +#define SCR_TXUSEDK BIT(0) +#define SCR_RXUSEDK BIT(1) +#define SCR_TXENCENABLE BIT(2) +#define SCR_RXENCENABLE BIT(3) +#define SCR_SKBYA2 BIT(4) +#define SCR_NOSKMC BIT(5) +#define SCR_TXBCUSEDK BIT(6) +#define SCR_RXBCUSEDK BIT(7) + +/* General definitions */ +#define LAST_ENTRY_OF_TX_PKT_BUFFER 255 +#define LAST_ENTRY_OF_TX_PKT_BUFFER_DUAL_MAC 127 + +#define POLLING_LLT_THRESHOLD 20 +#define POLLING_READY_TIMEOUT_COUNT 1000 + +/* Min Spacing related settings. */ +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + + +/* BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF */ +/* 1. PMAC duplicate register due to connection: */ +/* RF_Mode, TRxRN, NumOf L-STF */ +/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */ +/* 3. RF register 0x00-2E */ +/* 4. Bit Mask for BB/RF register */ +/* 5. Other defintion for BB/RF R/W */ + +/* 3. Page8(0x800) */ +#define RFPGA0_RFMOD 0x800 + +#define RFPGA0_TXINFO 0x804 +#define RFPGA0_PSDFUNCTION 0x808 + +#define RFPGA0_TXGAINSTAGE 0x80c + +#define RFPGA0_RFTIMING1 0x810 +#define RFPGA0_RFTIMING2 0x814 + +#define RFPGA0_XA_HSSIPARAMETER1 0x820 +#define RFPGA0_XA_HSSIPARAMETER2 0x824 +#define RFPGA0_XB_HSSIPARAMETER1 0x828 +#define RFPGA0_XB_HSSIPARAMETER2 0x82c + +#define RFPGA0_XA_LSSIPARAMETER 0x840 +#define RFPGA0_XB_LSSIPARAMETER 0x844 + +#define RFPGA0_RFWAkEUPPARAMETER 0x850 +#define RFPGA0_RFSLEEPUPPARAMETER 0x854 + +#define RFPGA0_XAB_SWITCHCONTROL 0x858 +#define RFPGA0_XCD_SWITCHCONTROL 0x85c + +#define RFPGA0_XA_RFINTERFACEOE 0x860 +#define RFPGA0_XB_RFINTERFACEOE 0x864 + +#define RFPGA0_XAB_RFINTERFACESW 0x870 +#define RFPGA0_XCD_RFINTERFACESW 0x874 + +#define RFPGA0_XAB_RFPARAMETER 0x878 +#define RFPGA0_XCD_RFPARAMETER 0x87c + +#define RFPGA0_ANALOGPARAMETER1 0x880 +#define RFPGA0_ANALOGPARAMETER2 0x884 +#define RFPGA0_ANALOGPARAMETER3 0x888 +#define RFPGA0_ADDALLOCKEN 0x888 +#define RFPGA0_ANALOGPARAMETER4 0x88c + +#define RFPGA0_XA_LSSIREADBACK 0x8a0 +#define RFPGA0_XB_LSSIREADBACK 0x8a4 +#define RFPGA0_XC_LSSIREADBACK 0x8a8 +#define RFPGA0_XD_LSSIREADBACK 0x8ac + +#define RFPGA0_PSDREPORT 0x8b4 +#define TRANSCEIVERA_HSPI_READBACK 0x8b8 +#define TRANSCEIVERB_HSPI_READBACK 0x8bc +#define RFPGA0_XAB_RFINTERFACERB 0x8e0 +#define RFPGA0_XCD_RFINTERFACERB 0x8e4 + +/* 4. Page9(0x900) */ +#define RFPGA1_RFMOD 0x900 + +#define RFPGA1_TXBLOCK 0x904 +#define RFPGA1_DEBUGSELECT 0x908 +#define RFPGA1_TXINFO 0x90c + +/* 5. PageA(0xA00) */ +#define RCCK0_SYSTEM 0xa00 + +#define RCCK0_AFESSTTING 0xa04 +#define RCCK0_CCA 0xa08 + +#define RCCK0_RXAGC1 0xa0c +#define RCCK0_RXAGC2 0xa10 + +#define RCCK0_RXHP 0xa14 + +#define RCCK0_DSPPARAMETER1 0xa18 +#define RCCK0_DSPPARAMETER2 0xa1c + +#define RCCK0_TXFILTER1 0xa20 +#define RCCK0_TXFILTER2 0xa24 +#define RCCK0_DEBUGPORT 0xa28 +#define RCCK0_FALSEALARMREPORT 0xa2c +#define RCCK0_TRSSIREPORT 0xa50 +#define RCCK0_RXREPORT 0xa54 +#define RCCK0_FACOUNTERLOWER 0xa5c +#define RCCK0_FACOUNTERUPPER 0xa58 + +/* 6. PageC(0xC00) */ +#define ROFDM0_LSTF 0xc00 + +#define ROFDM0_TRXPATHENABLE 0xc04 +#define ROFDM0_TRMUXPAR 0xc08 +#define ROFDM0_TRSWISOLATION 0xc0c + +#define ROFDM0_XARXAFE 0xc10 +#define ROFDM0_XARXIQIMBALANCE 0xc14 +#define ROFDM0_XBRXAFE 0xc18 +#define ROFDM0_XBRXIQIMBALANCE 0xc1c +#define ROFDM0_XCRXAFE 0xc20 +#define ROFDM0_XCRXIQIMBALANCE 0xc24 +#define ROFDM0_XDRXAFE 0xc28 +#define ROFDM0_XDRXIQIMBALANCE 0xc2c + +#define ROFDM0_RXDETECTOR1 0xc30 +#define ROFDM0_RXDETECTOR2 0xc34 +#define ROFDM0_RXDETECTOR3 0xc38 +#define ROFDM0_RXDETECTOR4 0xc3c + +#define ROFDM0_RXDSP 0xc40 +#define ROFDM0_CFOANDDAGC 0xc44 +#define ROFDM0_CCADROPTHRESHOLD 0xc48 +#define ROFDM0_ECCATHRESHOLD 0xc4c + +#define ROFDM0_XAAGCCORE1 0xc50 +#define ROFDM0_XAAGCCORE2 0xc54 +#define ROFDM0_XBAGCCORE1 0xc58 +#define ROFDM0_XBAGCCORE2 0xc5c +#define ROFDM0_XCAGCCORE1 0xc60 +#define ROFDM0_XCAGCCORE2 0xc64 +#define ROFDM0_XDAGCCORE1 0xc68 +#define ROFDM0_XDAGCCORE2 0xc6c + +#define ROFDM0_AGCPARAMETER1 0xc70 +#define ROFDM0_AGCPARAMETER2 0xc74 +#define ROFDM0_AGCRSSITABLE 0xc78 +#define ROFDM0_HTSTFAGC 0xc7c + +#define ROFDM0_XATxIQIMBALANCE 0xc80 +#define ROFDM0_XATxAFE 0xc84 +#define ROFDM0_XBTxIQIMBALANCE 0xc88 +#define ROFDM0_XBTxAFE 0xc8c +#define ROFDM0_XCTxIQIMBALANCE 0xc90 +#define ROFDM0_XCTxAFE 0xc94 +#define ROFDM0_XDTxIQIMBALANCE 0xc98 +#define ROFDM0_XDTxAFE 0xc9c + +#define ROFDM0_RXHPPARAMETER 0xce0 +#define ROFDM0_TXPSEUDONOISEWGT 0xce4 +#define ROFDM0_FRAMESYNC 0xcf0 +#define ROFDM0_DFSREPORT 0xcf4 +#define ROFDM0_TXCOEFF1 0xca4 +#define ROFDM0_TXCOEFF2 0xca8 +#define ROFDM0_TXCOEFF3 0xcac +#define ROFDM0_TXCOEFF4 0xcb0 +#define ROFDM0_TXCOEFF5 0xcb4 +#define ROFDM0_TXCOEFF6 0xcb8 + +/* 7. PageD(0xD00) */ +#define ROFDM1_LSTF 0xd00 +#define ROFDM1_TRXPATHENABLE 0xd04 + +#define ROFDM1_CFO 0xd08 +#define ROFDM1_CSI1 0xd10 +#define ROFDM1_SBD 0xd14 +#define ROFDM1_CSI2 0xd18 +#define ROFDM1_CFOTRACKING 0xd2c +#define ROFDM1_TRXMESAURE1 0xd34 +#define ROFDM1_INTFDET 0xd3c +#define ROFDM1_PSEUDONOISESTATEAB 0xd50 +#define ROFDM1_PSEUDONOISESTATECD 0xd54 +#define ROFDM1_RXPSEUDONOISEWGT 0xd58 + +#define ROFDM_PHYCOUNTER1 0xda0 +#define ROFDM_PHYCOUNTER2 0xda4 +#define ROFDM_PHYCOUNTER3 0xda8 + +#define ROFDM_SHORTCFOAB 0xdac +#define ROFDM_SHORTCFOCD 0xdb0 +#define ROFDM_LONGCFOAB 0xdb4 +#define ROFDM_LONGCFOCD 0xdb8 +#define ROFDM_TAILCFOAB 0xdbc +#define ROFDM_TAILCFOCD 0xdc0 +#define ROFDM_PWMEASURE1 0xdc4 +#define ROFDM_PWMEASURE2 0xdc8 +#define ROFDM_BWREPORT 0xdcc +#define ROFDM_AGCREPORT 0xdd0 +#define ROFDM_RXSNR 0xdd4 +#define ROFDM_RXEVMCSI 0xdd8 +#define ROFDM_SIGReport 0xddc + +/* 8. PageE(0xE00) */ +#define RTXAGC_A_RATE18_06 0xe00 +#define RTXAGC_A_RATE54_24 0xe04 +#define RTXAGC_A_CCK1_MCS32 0xe08 +#define RTXAGC_A_MCS03_MCS00 0xe10 +#define RTXAGC_A_MCS07_MCS04 0xe14 +#define RTXAGC_A_MCS11_MCS08 0xe18 +#define RTXAGC_A_MCS15_MCS12 0xe1c + +#define RTXAGC_B_RATE18_06 0x830 +#define RTXAGC_B_RATE54_24 0x834 +#define RTXAGC_B_CCK1_55_MCS32 0x838 +#define RTXAGC_B_MCS03_MCS00 0x83c +#define RTXAGC_B_MCS07_MCS04 0x848 +#define RTXAGC_B_MCS11_MCS08 0x84c +#define RTXAGC_B_MCS15_MCS12 0x868 +#define RTXAGC_B_CCK11_A_CCK2_11 0x86c + +/* RL6052 Register definition */ +#define RF_AC 0x00 + +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_POW_TRSW 0x05 + +#define RF_GAIN_RX 0x06 +#define RF_GAIN_TX 0x07 + +#define RF_TXM_IDAC 0x08 +#define RF_BS_IQGEN 0x0F + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 + +#define RF_RX_AGC_HP 0x12 +#define RF_TX_AGC 0x13 +#define RF_BIAS 0x14 +#define RF_IPA 0x15 +#define RF_POW_ABILITY 0x17 +#define RF_MODE_AG 0x18 +#define rRfChannel 0x18 +#define RF_CHNLBW 0x18 +#define RF_TOP 0x19 + +#define RF_RX_G1 0x1A +#define RF_RX_G2 0x1B + +#define RF_RX_BB2 0x1C +#define RF_RX_BB1 0x1D + +#define RF_RCK1 0x1E +#define RF_RCK2 0x1F + +#define RF_TX_G1 0x20 +#define RF_TX_G2 0x21 +#define RF_TX_G3 0x22 + +#define RF_TX_BB1 0x23 + +#define RF_T_METER 0x42 + +#define RF_SYN_G1 0x25 +#define RF_SYN_G2 0x26 +#define RF_SYN_G3 0x27 +#define RF_SYN_G4 0x28 +#define RF_SYN_G5 0x29 +#define RF_SYN_G6 0x2A +#define RF_SYN_G7 0x2B +#define RF_SYN_G8 0x2C + +#define RF_RCK_OS 0x30 + +#define RF_TXPA_G1 0x31 +#define RF_TXPA_G2 0x32 +#define RF_TXPA_G3 0x33 + +/* Bit Mask */ + +/* 2. Page8(0x800) */ +#define BRFMOD 0x1 +#define BCCKTXSC 0x30 +#define BCCKEN 0x1000000 +#define BOFDMEN 0x2000000 + +#define B3WIREDATALENGTH 0x800 +#define B3WIREADDRESSLENGTH 0x400 + +#define BRFSI_RFENV 0x10 + +#define BLSSIREADADDRESS 0x7f800000 +#define BLSSIREADEDGE 0x80000000 +#define BLSSIREADBACKDATA 0xfffff +/* 4. PageA(0xA00) */ +#define BCCKSIDEBAND 0x10 + +/* Other Definition */ +#define BBYTE0 0x1 +#define BBYTE1 0x2 +#define BBYTE2 0x4 +#define BBYTE3 0x8 +#define BWORD0 0x3 +#define BWORD1 0xc +#define BDWORD 0xf + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c new file mode 100644 index 000000000000..6a6ac540d5b5 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.c @@ -0,0 +1,623 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "hw.h" + +void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u8 rfpath; + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + rtlphy->rfreg_chnlval[rfpath] = ((rtlphy->rfreg_chnlval + [rfpath] & 0xfffff3ff) | 0x0400); + rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) | + BIT(11), 0x01); + + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "20M RF 0x18 = 0x%x\n", + rtlphy->rfreg_chnlval[rfpath]); + } + + break; + case HT_CHANNEL_WIDTH_20_40: + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + rtlphy->rfreg_chnlval[rfpath] = + ((rtlphy->rfreg_chnlval[rfpath] & 0xfffff3ff)); + rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) | BIT(11), + 0x00); + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "40M RF 0x18 = 0x%x\n", + rtlphy->rfreg_chnlval[rfpath]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", bandwidth); + break; + } +} + +void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 tx_agc[2] = {0, 0}, tmpval; + bool turbo_scanoff = false; + u8 idx1, idx2; + u8 *ptr; + + if (rtlefuse->eeprom_regulatory != 0) + turbo_scanoff = true; + if (mac->act_scanning) { + tx_agc[RF90_PATH_A] = 0x3f3f3f3f; + tx_agc[RF90_PATH_B] = 0x3f3f3f3f; + if (turbo_scanoff) { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + } + } else { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + if (rtlefuse->eeprom_regulatory == 0) { + tmpval = (rtlphy->mcs_offset[0][6]) + + (rtlphy->mcs_offset[0][7] << 8); + tx_agc[RF90_PATH_A] += tmpval; + tmpval = (rtlphy->mcs_offset[0][14]) + + (rtlphy->mcs_offset[0][15] << 24); + tx_agc[RF90_PATH_B] += tmpval; + } + } + + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + ptr = (u8 *) (&(tx_agc[idx1])); + for (idx2 = 0; idx2 < 4; idx2++) { + if (*ptr > RF6052_MAX_TX_PWR) + *ptr = RF6052_MAX_TX_PWR; + ptr++; + } + } + + tmpval = tx_agc[RF90_PATH_A] & 0xff; + rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", + tmpval, RTXAGC_A_CCK1_MCS32); + tmpval = tx_agc[RF90_PATH_A] >> 8; + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", + tmpval, RTXAGC_B_CCK11_A_CCK2_11); + tmpval = tx_agc[RF90_PATH_B] >> 24; + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", + tmpval, RTXAGC_B_CCK11_A_CCK2_11); + tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; + rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", + tmpval, RTXAGC_B_CCK1_55_MCS32); +} + +static void _rtl92d_phy_get_power_base(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel, + u32 *ofdmbase, u32 *mcsbase) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 powerbase0, powerbase1; + u8 legacy_pwrdiff, ht20_pwrdiff; + u8 i, powerlevel[2]; + + for (i = 0; i < 2; i++) { + powerlevel[i] = ppowerlevel[i]; + legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; + powerbase0 = powerlevel[i] + legacy_pwrdiff; + powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | + (powerbase0 << 8) | powerbase0; + *(ofdmbase + i) = powerbase0; + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [OFDM power base index rf(%c) = 0x%x]\n", + i == 0 ? 'A' : 'B', *(ofdmbase + i)); + } + + for (i = 0; i < 2; i++) { + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { + ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1]; + powerlevel[i] += ht20_pwrdiff; + } + powerbase1 = powerlevel[i]; + powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) | + (powerbase1 << 8) | powerbase1; + *(mcsbase + i) = powerbase1; + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [MCS power base index rf(%c) = 0x%x]\n", + i == 0 ? 'A' : 'B', *(mcsbase + i)); + } +} + +static u8 _rtl92d_phy_get_chnlgroup_bypg(u8 chnlindex) +{ + u8 group; + u8 channel_info[59] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, + 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, + 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, + 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, + 161, 163, 165 + }; + + if (channel_info[chnlindex] <= 3) /* Chanel 1-3 */ + group = 0; + else if (channel_info[chnlindex] <= 9) /* Channel 4-9 */ + group = 1; + else if (channel_info[chnlindex] <= 14) /* Channel 10-14 */ + group = 2; + else if (channel_info[chnlindex] <= 64) + group = 6; + else if (channel_info[chnlindex] <= 140) + group = 7; + else + group = 8; + return group; +} + +static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, + u8 channel, u8 index, + u32 *powerbase0, + u32 *powerbase1, + u32 *p_outwriteval) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 i, chnlgroup = 0, pwr_diff_limit[4]; + u32 writeval = 0, customer_limit, rf; + + for (rf = 0; rf < 2; rf++) { + switch (rtlefuse->eeprom_regulatory) { + case 0: + chnlgroup = 0; + writeval = rtlphy->mcs_offset + [chnlgroup][index + + (rf ? 8 : 0)] + ((index < 2) ? + powerbase0[rf] : + powerbase1[rf]); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeval(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); + break; + case 1: + if (rtlphy->pwrgroup_cnt == 1) + chnlgroup = 0; + if (rtlphy->pwrgroup_cnt >= MAX_PG_GROUP) { + chnlgroup = _rtl92d_phy_get_chnlgroup_bypg( + channel - 1); + if (rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20) + chnlgroup++; + else + chnlgroup += 4; + writeval = rtlphy->mcs_offset + [chnlgroup][index + + (rf ? 8 : 0)] + ((index < 2) ? + powerbase0[rf] : + powerbase1[rf]); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); + } + break; + case 2: + writeval = ((index < 2) ? powerbase0[rf] : + powerbase1[rf]); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Better regulatory, writeval(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); + break; + case 3: + chnlgroup = 0; + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 40MHz rf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', + rtlefuse->pwrgroup_ht40[rf] + [channel - 1]); + } else { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 20MHz rf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', + rtlefuse->pwrgroup_ht20[rf] + [channel - 1]); + } + for (i = 0; i < 4; i++) { + pwr_diff_limit[i] = (u8)((rtlphy->mcs_offset + [chnlgroup][index + (rf ? 8 : 0)] & + (0x7f << (i * 8))) >> (i * 8)); + if (rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20_40) { + if (pwr_diff_limit[i] > + rtlefuse->pwrgroup_ht40[rf] + [channel - 1]) + pwr_diff_limit[i] = + rtlefuse->pwrgroup_ht40 + [rf][channel - 1]; + } else { + if (pwr_diff_limit[i] > + rtlefuse->pwrgroup_ht20[rf][ + channel - 1]) + pwr_diff_limit[i] = + rtlefuse->pwrgroup_ht20[rf] + [channel - 1]; + } + } + customer_limit = (pwr_diff_limit[3] << 24) | + (pwr_diff_limit[2] << 16) | + (pwr_diff_limit[1] << 8) | + (pwr_diff_limit[0]); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer's limit rf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', customer_limit); + writeval = customer_limit + ((index < 2) ? + powerbase0[rf] : powerbase1[rf]); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer, writeval rf(%c)= 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); + break; + default: + chnlgroup = 0; + writeval = rtlphy->mcs_offset[chnlgroup][index + + (rf ? 8 : 0)] + ((index < 2) ? + powerbase0[rf] : powerbase1[rf]); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeval rf(%c) = 0x%x\n", + rf == 0 ? 'A' : 'B', writeval); + break; + } + *(p_outwriteval + rf) = writeval; + } +} + +static void _rtl92d_write_ofdm_power_reg(struct ieee80211_hw *hw, + u8 index, u32 *pvalue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + static u16 regoffset_a[6] = { + RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, + RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, + RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 + }; + static u16 regoffset_b[6] = { + RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, + RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, + RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 + }; + u8 i, rf, pwr_val[4]; + u32 writeval; + u16 regoffset; + + for (rf = 0; rf < 2; rf++) { + writeval = pvalue[rf]; + for (i = 0; i < 4; i++) { + pwr_val[i] = (u8) ((writeval & (0x7f << + (i * 8))) >> (i * 8)); + if (pwr_val[i] > RF6052_MAX_TX_PWR) + pwr_val[i] = RF6052_MAX_TX_PWR; + } + writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | + (pwr_val[1] << 8) | pwr_val[0]; + if (rf == 0) + regoffset = regoffset_a[index]; + else + regoffset = regoffset_b[index]; + rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Set 0x%x = %08x\n", regoffset, writeval); + if (((get_rf_type(rtlphy) == RF_2T2R) && + (regoffset == RTXAGC_A_MCS15_MCS12 || + regoffset == RTXAGC_B_MCS15_MCS12)) || + ((get_rf_type(rtlphy) != RF_2T2R) && + (regoffset == RTXAGC_A_MCS07_MCS04 || + regoffset == RTXAGC_B_MCS07_MCS04))) { + writeval = pwr_val[3]; + if (regoffset == RTXAGC_A_MCS15_MCS12 || + regoffset == RTXAGC_A_MCS07_MCS04) + regoffset = 0xc90; + if (regoffset == RTXAGC_B_MCS15_MCS12 || + regoffset == RTXAGC_B_MCS07_MCS04) + regoffset = 0xc98; + for (i = 0; i < 3; i++) { + if (i != 2) + writeval = (writeval > 8) ? + (writeval - 8) : 0; + else + writeval = (writeval > 6) ? + (writeval - 6) : 0; + rtl_write_byte(rtlpriv, (u32) (regoffset + i), + (u8) writeval); + } + } + } +} + +void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel) +{ + u32 writeval[2], powerbase0[2], powerbase1[2]; + u8 index; + + _rtl92d_phy_get_power_base(hw, ppowerlevel, channel, + &powerbase0[0], &powerbase1[0]); + for (index = 0; index < 6; index++) { + _rtl92d_get_txpower_writeval_by_regulatory(hw, + channel, index, &powerbase0[0], + &powerbase1[0], &writeval[0]); + _rtl92d_write_ofdm_power_reg(hw, index, &writeval[0]); + } +} + +bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + u8 u1btmp; + u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3); + u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0; + u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON; + bool bresult = true; /* true: need to enable BB/RF power */ + + rtlhal->during_mac0init_radiob = false; + rtlhal->during_mac1init_radioa = false; + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "===>\n"); + /* MAC0 Need PHY1 load radio_b.txt . Driver use DBI to write. */ + u1btmp = rtl_read_byte(rtlpriv, mac_reg); + if (!(u1btmp & mac_on_bit)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "enable BB & RF\n"); + /* Enable BB and RF power */ + rtl92de_write_dword_dbi(hw, REG_SYS_ISO_CTRL, + rtl92de_read_dword_dbi(hw, REG_SYS_ISO_CTRL, direct) | + BIT(29) | BIT(16) | BIT(17), direct); + } else { + /* We think if MAC1 is ON,then radio_a.txt + * and radio_b.txt has been load. */ + bresult = false; + } + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "<===\n"); + return bresult; + +} + +void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, bool bmac0) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + u8 u1btmp; + u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3); + u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0; + u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON; + + rtlhal->during_mac0init_radiob = false; + rtlhal->during_mac1init_radioa = false; + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "====>\n"); + /* check MAC0 enable or not again now, if + * enabled, not power down radio A. */ + u1btmp = rtl_read_byte(rtlpriv, mac_reg); + if (!(u1btmp & mac_on_bit)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "power down\n"); + /* power down RF radio A according to YuNan's advice. */ + rtl92de_write_dword_dbi(hw, RFPGA0_XA_LSSIPARAMETER, + 0x00000000, direct); + } + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "<====\n"); +} + +bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + bool rtstatus = true; + struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); + u32 u4_regvalue = 0; + u8 rfpath; + struct bb_reg_def *pphyreg; + bool mac1_initradioa_first = false, mac0_initradiob_first = false; + bool need_pwrdown_radioa = false, need_pwrdown_radiob = false; + bool true_bpath = false; + + if (rtlphy->rf_type == RF_1T1R) + rtlphy->num_total_rfpath = 1; + else + rtlphy->num_total_rfpath = 2; + + /* Single phy mode: use radio_a radio_b config path_A path_B */ + /* seperately by MAC0, and MAC1 needn't configure RF; */ + /* Dual PHY mode:MAC0 use radio_a config 1st phy path_A, */ + /* MAC1 use radio_b config 2nd PHY path_A. */ + /* DMDP,MAC0 on G band,MAC1 on A band. */ + if (rtlhal->macphymode == DUALMAC_DUALPHY) { + if (rtlhal->current_bandtype == BAND_ON_2_4G && + rtlhal->interfaceindex == 0) { + /* MAC0 needs PHY1 load radio_b.txt. + * Driver use DBI to write. */ + if (rtl92d_phy_enable_anotherphy(hw, true)) { + rtlphy->num_total_rfpath = 2; + mac0_initradiob_first = true; + } else { + /* We think if MAC1 is ON,then radio_a.txt and + * radio_b.txt has been load. */ + return rtstatus; + } + } else if (rtlhal->current_bandtype == BAND_ON_5G && + rtlhal->interfaceindex == 1) { + /* MAC1 needs PHY0 load radio_a.txt. + * Driver use DBI to write. */ + if (rtl92d_phy_enable_anotherphy(hw, false)) { + rtlphy->num_total_rfpath = 2; + mac1_initradioa_first = true; + } else { + /* We think if MAC0 is ON,then radio_a.txt and + * radio_b.txt has been load. */ + return rtstatus; + } + } else if (rtlhal->interfaceindex == 1) { + /* MAC0 enabled, only init radia B. */ + true_bpath = true; + } + } + + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + /* Mac1 use PHY0 write */ + if (mac1_initradioa_first) { + if (rfpath == RF90_PATH_A) { + rtlhal->during_mac1init_radioa = true; + need_pwrdown_radioa = true; + } else if (rfpath == RF90_PATH_B) { + rtlhal->during_mac1init_radioa = false; + mac1_initradioa_first = false; + rfpath = RF90_PATH_A; + true_bpath = true; + rtlphy->num_total_rfpath = 1; + } + } else if (mac0_initradiob_first) { + /* Mac0 use PHY1 write */ + if (rfpath == RF90_PATH_A) + rtlhal->during_mac0init_radiob = false; + if (rfpath == RF90_PATH_B) { + rtlhal->during_mac0init_radiob = true; + mac0_initradiob_first = false; + need_pwrdown_radiob = true; + rfpath = RF90_PATH_A; + true_bpath = true; + rtlphy->num_total_rfpath = 1; + } + } + pphyreg = &rtlphy->phyreg_def[rfpath]; + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV); + break; + case RF90_PATH_B: + case RF90_PATH_D: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16); + break; + } + rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); + udelay(1); + rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); + udelay(1); + /* Set bit number of Address and Data for RF register */ + /* Set 1 to 4 bits for 8255 */ + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, + B3WIREADDRESSLENGTH, 0x0); + udelay(1); + /* Set 0 to 12 bits for 8255 */ + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); + udelay(1); + switch (rfpath) { + case RF90_PATH_A: + if (true_bpath) + rtstatus = rtl92d_phy_config_rf_with_headerfile( + hw, radiob_txt, + (enum radio_path)rfpath); + else + rtstatus = rtl92d_phy_config_rf_with_headerfile( + hw, radioa_txt, + (enum radio_path)rfpath); + break; + case RF90_PATH_B: + rtstatus = + rtl92d_phy_config_rf_with_headerfile(hw, radiob_txt, + (enum radio_path) rfpath); + break; + case RF90_PATH_C: + break; + case RF90_PATH_D: + break; + } + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, + u4_regvalue); + break; + case RF90_PATH_B: + case RF90_PATH_D: + rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16, + u4_regvalue); + break; + } + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio[%d] Fail!!", rfpath); + goto phy_rf_cfg_fail; + } + + } + + /* check MAC0 enable or not again, if enabled, + * not power down radio A. */ + /* check MAC1 enable or not again, if enabled, + * not power down radio B. */ + if (need_pwrdown_radioa) + rtl92d_phy_powerdown_anotherphy(hw, false); + else if (need_pwrdown_radiob) + rtl92d_phy_powerdown_anotherphy(hw, true); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n"); + return rtstatus; + +phy_rf_cfg_fail: + return rtstatus; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h new file mode 100644 index 000000000000..7303d12c266f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rf.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92D_RF_H__ +#define __RTL92D_RF_H__ + +void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth); +void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); +bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw); +bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0); +void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, bool bmac0); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c new file mode 100644 index 000000000000..b19d0398215f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c @@ -0,0 +1,419 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../core.h" +#include "../pci.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "hw.h" +#include "sw.h" +#include "trx.h" +#include "led.h" + +#include + +static void rtl92d_init_aspm_vars(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /* + * ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + * */ + rtlpci->const_pci_aspm = 3; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /* + * In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 0; + + /* + * This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 1; +} + +static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) +{ + int err; + u8 tid; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtlpriv->dm.dm_initialgain_enable = true; + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.disable_framebursting = false; + rtlpriv->dm.thermalvalue = 0; + rtlpriv->dm.useramask = true; + + /* dual mac */ + if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) + rtlpriv->phy.current_channel = 36; + else + rtlpriv->phy.current_channel = 1; + + if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) { + rtlpriv->rtlhal.disable_amsdu_8k = true; + /* No long RX - reduce fragmentation */ + rtlpci->rxbuffersize = 4096; + } + + rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13); + + rtlpci->receive_config = ( + RCR_APPFCS + | RCR_AMF + | RCR_ADF + | RCR_APP_MIC + | RCR_APP_ICV + | RCR_AICV + | RCR_ACRC32 + | RCR_AB + | RCR_AM + | RCR_APM + | RCR_APP_PHYST_RXFF + | RCR_HTC_LOC_CTRL + ); + + rtlpci->irq_mask[0] = (u32) ( + IMR_ROK + | IMR_VODOK + | IMR_VIDOK + | IMR_BEDOK + | IMR_BKDOK + | IMR_MGNTDOK + | IMR_HIGHDOK + | IMR_BDOK + | IMR_RDU + | IMR_RXFOVW + ); + + 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; + rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; + if (!rtlpriv->psc.inactiveps) + pr_info("Power Save off (module option)\n"); + if (!rtlpriv->psc.fwctrl_lps) + pr_info("FW Power Save off (module option)\n"); + rtlpriv->psc.reg_fwctrl_lps = 3; + rtlpriv->psc.reg_max_lps_awakeintvl = 5; + /* for ASPM, you can close aspm through + * set const_support_pciaspm = 0 */ + rtl92d_init_aspm_vars(hw); + + if (rtlpriv->psc.reg_fwctrl_lps == 1) + rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 2) + rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 3) + rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + + /* for early mode */ + rtlpriv->rtlhal.earlymode_enable = false; + for (tid = 0; tid < 8; tid++) + skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); + if (!rtlpriv->rtlhal.pfirmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't alloc buffer for fw\n"); + return 1; + } + + rtlpriv->max_fw_size = 0x8000; + pr_info("Driver for Realtek RTL8192DE WLAN interface\n"); + pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); + + /* request fw */ + err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, + rtlpriv->io.dev, GFP_KERNEL, hw, + rtl_fw_cb); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to request firmware!\n"); + return 1; + } + + return 0; +} + +static void rtl92d_deinit_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tid; + + if (rtlpriv->rtlhal.pfirmware) { + vfree(rtlpriv->rtlhal.pfirmware); + rtlpriv->rtlhal.pfirmware = NULL; + } + for (tid = 0; tid < 8; tid++) + skb_queue_purge(&rtlpriv->mac80211.skb_waitq[tid]); +} + +static struct rtl_hal_ops rtl8192de_hal_ops = { + .init_sw_vars = rtl92d_init_sw_vars, + .deinit_sw_vars = rtl92d_deinit_sw_vars, + .read_eeprom_info = rtl92de_read_eeprom_info, + .interrupt_recognized = rtl92de_interrupt_recognized, + .hw_init = rtl92de_hw_init, + .hw_disable = rtl92de_card_disable, + .hw_suspend = rtl92de_suspend, + .hw_resume = rtl92de_resume, + .enable_interrupt = rtl92de_enable_interrupt, + .disable_interrupt = rtl92de_disable_interrupt, + .set_network_type = rtl92de_set_network_type, + .set_chk_bssid = rtl92de_set_check_bssid, + .set_qos = rtl92de_set_qos, + .set_bcn_reg = rtl92de_set_beacon_related_registers, + .set_bcn_intv = rtl92de_set_beacon_interval, + .update_interrupt_mask = rtl92de_update_interrupt_mask, + .get_hw_reg = rtl92de_get_hw_reg, + .set_hw_reg = rtl92de_set_hw_reg, + .update_rate_tbl = rtl92de_update_hal_rate_tbl, + .fill_tx_desc = rtl92de_tx_fill_desc, + .fill_tx_cmddesc = rtl92de_tx_fill_cmddesc, + .query_rx_desc = rtl92de_rx_query_desc, + .set_channel_access = rtl92de_update_channel_access_setting, + .radio_onoff_checking = rtl92de_gpio_radio_on_off_checking, + .set_bw_mode = rtl92d_phy_set_bw_mode, + .switch_channel = rtl92d_phy_sw_chnl, + .dm_watchdog = rtl92d_dm_watchdog, + .scan_operation_backup = rtl_phy_scan_operation_backup, + .set_rf_power_state = rtl92d_phy_set_rf_power_state, + .led_control = rtl92de_led_control, + .set_desc = rtl92de_set_desc, + .get_desc = rtl92de_get_desc, + .tx_polling = rtl92de_tx_polling, + .enable_hw_sec = rtl92de_enable_hw_security_config, + .set_key = rtl92de_set_key, + .init_sw_leds = rtl92de_init_sw_leds, + .get_bbreg = rtl92d_phy_query_bb_reg, + .set_bbreg = rtl92d_phy_set_bb_reg, + .get_rfreg = rtl92d_phy_query_rf_reg, + .set_rfreg = rtl92d_phy_set_rf_reg, + .linked_set_reg = rtl92d_linked_set_reg, + .get_btc_status = rtl_btc_status_false, +}; + +static struct rtl_mod_params rtl92de_mod_params = { + .sw_crypto = false, + .inactiveps = true, + .swctrl_lps = true, + .fwctrl_lps = false, + .debug = DBG_EMERG, +}; + +static struct rtl_hal_cfg rtl92de_hal_cfg = { + .bar_id = 2, + .write_readback = true, + .name = "rtl8192de", + .fw_name = "rtlwifi/rtl8192defw.bin", + .ops = &rtl8192de_hal_ops, + .mod_params = &rtl92de_mod_params, + + .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, + .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, + .maps[SYS_CLK] = REG_SYS_CLKR, + .maps[MAC_RCR_AM] = RCR_AM, + .maps[MAC_RCR_AB] = RCR_AB, + .maps[MAC_RCR_ACRC32] = RCR_ACRC32, + .maps[MAC_RCR_ACF] = RCR_ACF, + .maps[MAC_RCR_AAP] = RCR_AAP, + + .maps[EFUSE_TEST] = REG_EFUSE_TEST, + .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_CLK] = 0, /* just for 92se */ + .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_PWC_EV12V] = PWC_EV12V, + .maps[EFUSE_FEN_ELDR] = FEN_ELDR, + .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, + .maps[EFUSE_ANA8M] = 0, /* just for 92se */ + .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, + .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, + .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, + + .maps[RWCAM] = REG_CAMCMD, + .maps[WCAMI] = REG_CAMWRITE, + .maps[RCAMO] = REG_CAMREAD, + .maps[CAMDBG] = REG_CAMDBG, + .maps[SECR] = REG_SECCFG, + .maps[SEC_CAM_NONE] = CAM_NONE, + .maps[SEC_CAM_WEP40] = CAM_WEP40, + .maps[SEC_CAM_TKIP] = CAM_TKIP, + .maps[SEC_CAM_AES] = CAM_AES, + .maps[SEC_CAM_WEP104] = CAM_WEP104, + + .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, + .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, + .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, + .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, + .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, + .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, + .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, + .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, + .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, + .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, + .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, + .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, + .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, + .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, + .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, + .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, + + .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, + .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, + .maps[RTL_IMR_BCNINT] = IMR_BCNINT, + .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, + .maps[RTL_IMR_RDU] = IMR_RDU, + .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, + .maps[RTL_IMR_BDOK] = IMR_BDOK, + .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, + .maps[RTL_IMR_TBDER] = IMR_TBDER, + .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, + .maps[RTL_IMR_TBDOK] = IMR_TBDOK, + .maps[RTL_IMR_BKDOK] = IMR_BKDOK, + .maps[RTL_IMR_BEDOK] = IMR_BEDOK, + .maps[RTL_IMR_VIDOK] = IMR_VIDOK, + .maps[RTL_IMR_VODOK] = IMR_VODOK, + .maps[RTL_IMR_ROK] = IMR_ROK, + .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), + + .maps[RTL_RC_CCK_RATE1M] = DESC_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC_RATEMCS15, +}; + +static struct pci_device_id rtl92de_pci_ids[] = { + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8193, rtl92de_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x002B, rtl92de_hal_cfg)}, + {}, +}; + +MODULE_DEVICE_TABLE(pci, rtl92de_pci_ids); + +MODULE_AUTHOR("lizhaoming "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +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(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_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)"); + +static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); + +static struct pci_driver rtl92de_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl92de_pci_ids, + .probe = rtl_pci_probe, + .remove = rtl_pci_disconnect, + .driver.pm = &rtlwifi_pm_ops, +}; + +/* add global spin lock to solve the problem that + * Dul mac register operation on the same time */ +spinlock_t globalmutex_power; +spinlock_t globalmutex_for_fwdownload; +spinlock_t globalmutex_for_power_and_efuse; + +static int __init rtl92de_module_init(void) +{ + int ret = 0; + + spin_lock_init(&globalmutex_power); + spin_lock_init(&globalmutex_for_fwdownload); + spin_lock_init(&globalmutex_for_power_and_efuse); + + ret = pci_register_driver(&rtl92de_driver); + if (ret) + RT_ASSERT(false, "No device found\n"); + return ret; +} + +static void __exit rtl92de_module_exit(void) +{ + pci_unregister_driver(&rtl92de_driver); +} + +module_init(rtl92de_module_init); +module_exit(rtl92de_module_exit); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h new file mode 100644 index 000000000000..0e6035b8fd86 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92DE_SW_H__ +#define __RTL92DE_SW_H__ + +extern spinlock_t globalmutex_power; +extern spinlock_t globalmutex_for_fwdownload; +extern spinlock_t globalmutex_for_power_and_efuse; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c new file mode 100644 index 000000000000..8ea6f528dfa6 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.c @@ -0,0 +1,1690 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + * Created on 2010/12/23, 6:38 + *****************************************************************************/ + +#include + +#include "table.h" + +u32 rtl8192de_phy_reg_2tarray[PHY_REG_2T_ARRAYLENGTH] = { + 0x024, 0x0011800d, + 0x028, 0x00ffdb83, + 0x014, 0x088ba955, + 0x010, 0x49022b03, + 0x800, 0x80040002, + 0x804, 0x00000003, + 0x808, 0x0000fc00, + 0x80c, 0x0000000a, + 0x810, 0x80706388, + 0x814, 0x020c3d10, + 0x818, 0x02200385, + 0x81c, 0x00000000, + 0x820, 0x01000100, + 0x824, 0x00390004, + 0x828, 0x01000100, + 0x82c, 0x00390004, + 0x830, 0x27272727, + 0x834, 0x27272727, + 0x838, 0x27272727, + 0x83c, 0x27272727, + 0x840, 0x00010000, + 0x844, 0x00010000, + 0x848, 0x27272727, + 0x84c, 0x27272727, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x569a569a, + 0x85c, 0x0c1b25a4, + 0x860, 0x66e60230, + 0x864, 0x061f0130, + 0x868, 0x27272727, + 0x86c, 0x272b2b2b, + 0x870, 0x07000700, + 0x874, 0x22188000, + 0x878, 0x08080808, + 0x87c, 0x00007ff8, + 0x880, 0xc0083070, + 0x884, 0x00000cd5, + 0x888, 0x00000000, + 0x88c, 0xcc0000c0, + 0x890, 0x00000800, + 0x894, 0xfffffffe, + 0x898, 0x40302010, + 0x89c, 0x00706050, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90c, 0x81121313, + 0xa00, 0x00d047c8, + 0xa04, 0x80ff000c, + 0xa08, 0x8c838300, + 0xa0c, 0x2e68120f, + 0xa10, 0x9500bb78, + 0xa14, 0x11144028, + 0xa18, 0x00881117, + 0xa1c, 0x89140f00, + 0xa20, 0x1a1b0000, + 0xa24, 0x090e1317, + 0xa28, 0x00000204, + 0xa2c, 0x00d30000, + 0xa70, 0x101fbf00, + 0xa74, 0x00000007, + 0xc00, 0x40071d40, + 0xc04, 0x03a05633, + 0xc08, 0x001000e4, + 0xc0c, 0x6c6c6c6c, + 0xc10, 0x08800000, + 0xc14, 0x40000100, + 0xc18, 0x08800000, + 0xc1c, 0x40000100, + 0xc20, 0x00000000, + 0xc24, 0x00000000, + 0xc28, 0x00000000, + 0xc2c, 0x00000000, + 0xc30, 0x69e9ac44, + 0xc34, 0x469652cf, + 0xc38, 0x49795994, + 0xc3c, 0x0a979718, + 0xc40, 0x1f7c403f, + 0xc44, 0x000100b7, + 0xc48, 0xec020107, + 0xc4c, 0x007f037f, + 0xc50, 0x69543420, + 0xc54, 0x43bc009e, + 0xc58, 0x69543420, + 0xc5c, 0x433c00a8, + 0xc60, 0x00000000, + 0xc64, 0x5116848b, + 0xc68, 0x47c00bff, + 0xc6c, 0x00000036, + 0xc70, 0x2c7f000d, + 0xc74, 0x058610db, + 0xc78, 0x0000001f, + 0xc7c, 0x40b95612, + 0xc80, 0x40000100, + 0xc84, 0x20f60000, + 0xc88, 0x40000100, + 0xc8c, 0x20e00000, + 0xc90, 0x00121820, + 0xc94, 0x00000007, + 0xc98, 0x00121820, + 0xc9c, 0x00007f7f, + 0xca0, 0x00000000, + 0xca4, 0x00000080, + 0xca8, 0x00000000, + 0xcac, 0x00000000, + 0xcb0, 0x00000000, + 0xcb4, 0x00000000, + 0xcb8, 0x00000000, + 0xcbc, 0x28000000, + 0xcc0, 0x00000000, + 0xcc4, 0x00000000, + 0xcc8, 0x00000000, + 0xccc, 0x00000000, + 0xcd0, 0x00000000, + 0xcd4, 0x00000000, + 0xcd8, 0x64b11e20, + 0xcdc, 0xe8767533, + 0xce0, 0x00222222, + 0xce4, 0x00000000, + 0xce8, 0x37644302, + 0xcec, 0x2f97d40c, + 0xd00, 0x00080740, + 0xd04, 0x00020403, + 0xd08, 0x0000907f, + 0xd0c, 0x20010201, + 0xd10, 0xa0633333, + 0xd14, 0x3333bc43, + 0xd18, 0x7a8f5b6b, + 0xd2c, 0xcc979975, + 0xd30, 0x00000000, + 0xd34, 0x80608404, + 0xd38, 0x00000000, + 0xd3c, 0x00027293, + 0xd40, 0x00000000, + 0xd44, 0x00000000, + 0xd48, 0x00000000, + 0xd4c, 0x00000000, + 0xd50, 0x6437140a, + 0xd54, 0x00000000, + 0xd58, 0x00000000, + 0xd5c, 0x30032064, + 0xd60, 0x4653de68, + 0xd64, 0x04518a3c, + 0xd68, 0x00002101, + 0xd6c, 0x2a201c16, + 0xd70, 0x1812362e, + 0xd74, 0x322c2220, + 0xd78, 0x000e3c24, + 0xe00, 0x2a2a2a2a, + 0xe04, 0x2a2a2a2a, + 0xe08, 0x03902a2a, + 0xe10, 0x2a2a2a2a, + 0xe14, 0x2a2a2a2a, + 0xe18, 0x2a2a2a2a, + 0xe1c, 0x2a2a2a2a, + 0xe28, 0x00000000, + 0xe30, 0x1000dc1f, + 0xe34, 0x10008c1f, + 0xe38, 0x02140102, + 0xe3c, 0x681604c2, + 0xe40, 0x01007c00, + 0xe44, 0x01004800, + 0xe48, 0xfb000000, + 0xe4c, 0x000028d1, + 0xe50, 0x1000dc1f, + 0xe54, 0x10008c1f, + 0xe58, 0x02140102, + 0xe5c, 0x28160d05, + 0xe60, 0x00000010, + 0xe68, 0x001b25a4, + 0xe6c, 0x63db25a4, + 0xe70, 0x63db25a4, + 0xe74, 0x0c126da4, + 0xe78, 0x0c126da4, + 0xe7c, 0x0c126da4, + 0xe80, 0x0c126da4, + 0xe84, 0x63db25a4, + 0xe88, 0x0c126da4, + 0xe8c, 0x63db25a4, + 0xed0, 0x63db25a4, + 0xed4, 0x63db25a4, + 0xed8, 0x63db25a4, + 0xedc, 0x001b25a4, + 0xee0, 0x001b25a4, + 0xeec, 0x6fdb25a4, + 0xf14, 0x00000003, + 0xf1c, 0x00000064, + 0xf4c, 0x00000004, + 0xf00, 0x00000300, +}; + +u32 rtl8192de_phy_reg_array_pg[PHY_REG_ARRAY_PG_LENGTH] = { + 0xe00, 0xffffffff, 0x07090c0c, + 0xe04, 0xffffffff, 0x01020405, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x0b0c0c0e, + 0xe14, 0xffffffff, 0x01030506, + 0xe18, 0xffffffff, 0x0b0c0d0e, + 0xe1c, 0xffffffff, 0x01030509, + 0x830, 0xffffffff, 0x07090c0c, + 0x834, 0xffffffff, 0x01020405, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x0b0c0c0e, + 0x848, 0xffffffff, 0x01030506, + 0x84c, 0xffffffff, 0x0b0c0d0e, + 0x868, 0xffffffff, 0x01030509, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x06060606, + 0xe14, 0xffffffff, 0x00020406, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x06060606, + 0x848, 0xffffffff, 0x00020406, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x08080808, + 0xe14, 0xffffffff, 0x00040408, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x08080808, + 0x848, 0xffffffff, 0x00040408, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x08080808, + 0xe14, 0xffffffff, 0x00040408, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x08080808, + 0x848, 0xffffffff, 0x00040408, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x08080808, + 0xe14, 0xffffffff, 0x00040408, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x08080808, + 0x848, 0xffffffff, 0x00040408, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x08080808, + 0xe14, 0xffffffff, 0x00040408, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x08080808, + 0x848, 0xffffffff, 0x00040408, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x08080808, + 0xe14, 0xffffffff, 0x00040408, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x08080808, + 0x848, 0xffffffff, 0x00040408, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x08080808, + 0xe14, 0xffffffff, 0x00040408, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x08080808, + 0x848, 0xffffffff, 0x00040408, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, +}; + +u32 rtl8192de_radioa_2tarray[RADIOA_2T_ARRAYLENGTH] = { + 0x000, 0x00030000, + 0x001, 0x00030000, + 0x002, 0x00000000, + 0x003, 0x00018c63, + 0x004, 0x00018c63, + 0x008, 0x00084000, + 0x00b, 0x0001c000, + 0x00e, 0x00018c67, + 0x00f, 0x00000851, + 0x014, 0x00021440, + 0x018, 0x00017524, + 0x019, 0x00000000, + 0x01d, 0x000a1290, + 0x023, 0x00001558, + 0x01a, 0x00030a99, + 0x01b, 0x00040b00, + 0x01c, 0x000fc339, + 0x03a, 0x000a57eb, + 0x03b, 0x00020000, + 0x03c, 0x000ff454, + 0x020, 0x0000aa52, + 0x021, 0x00054000, + 0x040, 0x0000aa52, + 0x041, 0x00014000, + 0x025, 0x000803be, + 0x026, 0x000fc638, + 0x027, 0x00077c18, + 0x028, 0x000de471, + 0x029, 0x000d7110, + 0x02a, 0x0008cb04, + 0x02b, 0x0004128b, + 0x02c, 0x00001840, + 0x043, 0x0002444f, + 0x044, 0x0001adb0, + 0x045, 0x00056467, + 0x046, 0x0008992c, + 0x047, 0x0000452c, + 0x048, 0x000f9c43, + 0x049, 0x00002e0c, + 0x04a, 0x000546eb, + 0x04b, 0x0008966c, + 0x04c, 0x0000dde9, + 0x018, 0x00007401, + 0x000, 0x00070000, + 0x012, 0x000dc000, + 0x012, 0x00090000, + 0x012, 0x00051000, + 0x012, 0x00012000, + 0x013, 0x000287b7, + 0x013, 0x000247ab, + 0x013, 0x0002079f, + 0x013, 0x0001c793, + 0x013, 0x0001839b, + 0x013, 0x00014392, + 0x013, 0x0001019a, + 0x013, 0x0000c191, + 0x013, 0x00008194, + 0x013, 0x000040a0, + 0x013, 0x00000018, + 0x015, 0x0000f424, + 0x015, 0x0004f424, + 0x015, 0x0008f424, + 0x016, 0x000e1330, + 0x016, 0x000a1330, + 0x016, 0x00061330, + 0x016, 0x00021330, + 0x018, 0x00017524, + 0x000, 0x00070000, + 0x012, 0x000cf000, + 0x012, 0x000bc000, + 0x012, 0x00078000, + 0x012, 0x00000000, + 0x013, 0x000287bc, + 0x013, 0x000247b0, + 0x013, 0x000203b4, + 0x013, 0x0001c3a8, + 0x013, 0x000181b4, + 0x013, 0x000141a8, + 0x013, 0x000100b0, + 0x013, 0x0000c0a4, + 0x013, 0x0000b02c, + 0x013, 0x00004020, + 0x013, 0x00000014, + 0x015, 0x0000f4c3, + 0x015, 0x0004f4c3, + 0x015, 0x0008f4c3, + 0x016, 0x000e085f, + 0x016, 0x000a085f, + 0x016, 0x0006085f, + 0x016, 0x0002085f, + 0x018, 0x00037524, + 0x000, 0x00070000, + 0x012, 0x000cf000, + 0x012, 0x000bc000, + 0x012, 0x00078000, + 0x012, 0x00000000, + 0x013, 0x000287bc, + 0x013, 0x000247b0, + 0x013, 0x000203b4, + 0x013, 0x0001c3a8, + 0x013, 0x000181b4, + 0x013, 0x000141a8, + 0x013, 0x000100b0, + 0x013, 0x0000c0a4, + 0x013, 0x0000b02c, + 0x013, 0x00004020, + 0x013, 0x00000014, + 0x015, 0x0000f4c3, + 0x015, 0x0004f4c3, + 0x015, 0x0008f4c3, + 0x016, 0x000e085f, + 0x016, 0x000a085f, + 0x016, 0x0006085f, + 0x016, 0x0002085f, + 0x018, 0x00057568, + 0x000, 0x00070000, + 0x012, 0x000cf000, + 0x012, 0x000bc000, + 0x012, 0x00078000, + 0x012, 0x00000000, + 0x013, 0x000287bc, + 0x013, 0x000247b0, + 0x013, 0x000203b4, + 0x013, 0x0001c3a8, + 0x013, 0x000181b4, + 0x013, 0x000141a8, + 0x013, 0x000100b0, + 0x013, 0x0000c0a4, + 0x013, 0x0000b02c, + 0x013, 0x00004020, + 0x013, 0x00000014, + 0x015, 0x0000f4c3, + 0x015, 0x0004f4c3, + 0x015, 0x0008f4c3, + 0x016, 0x000e085f, + 0x016, 0x000a085f, + 0x016, 0x0006085f, + 0x016, 0x0002085f, + 0x030, 0x0004470f, + 0x031, 0x00044ff0, + 0x032, 0x00000070, + 0x033, 0x000dd480, + 0x034, 0x000ffac0, + 0x035, 0x000b80c0, + 0x036, 0x00077000, + 0x037, 0x00064ff2, + 0x038, 0x000e7661, + 0x039, 0x00000e90, + 0x000, 0x00030000, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01e, 0x00088009, + 0x01f, 0x00080003, + 0x0fe, 0x00000000, + 0x01e, 0x00088001, + 0x01f, 0x00080000, + 0x0fe, 0x00000000, + 0x018, 0x00097524, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x02b, 0x00041289, + 0x0fe, 0x00000000, + 0x02d, 0x0006aaaa, + 0x02e, 0x000b4d01, + 0x02d, 0x00080000, + 0x02e, 0x00004d02, + 0x02d, 0x00095555, + 0x02e, 0x00054d03, + 0x02d, 0x000aaaaa, + 0x02e, 0x000b4d04, + 0x02d, 0x000c0000, + 0x02e, 0x00004d05, + 0x02d, 0x000d5555, + 0x02e, 0x00054d06, + 0x02d, 0x000eaaaa, + 0x02e, 0x000b4d07, + 0x02d, 0x00000000, + 0x02e, 0x00005108, + 0x02d, 0x00015555, + 0x02e, 0x00055109, + 0x02d, 0x0002aaaa, + 0x02e, 0x000b510a, + 0x02d, 0x00040000, + 0x02e, 0x0000510b, + 0x02d, 0x00055555, + 0x02e, 0x0005510c, +}; + +u32 rtl8192de_radiob_2tarray[RADIOB_2T_ARRAYLENGTH] = { + 0x000, 0x00030000, + 0x001, 0x00030000, + 0x002, 0x00000000, + 0x003, 0x00018c63, + 0x004, 0x00018c63, + 0x008, 0x00084000, + 0x00b, 0x0001c000, + 0x00e, 0x00018c67, + 0x00f, 0x00000851, + 0x014, 0x00021440, + 0x018, 0x00007401, + 0x019, 0x00000060, + 0x01d, 0x000a1290, + 0x023, 0x00001558, + 0x01a, 0x00030a99, + 0x01b, 0x00040b00, + 0x01c, 0x000fc339, + 0x03a, 0x000a57eb, + 0x03b, 0x00020000, + 0x03c, 0x000ff454, + 0x020, 0x0000aa52, + 0x021, 0x00054000, + 0x040, 0x0000aa52, + 0x041, 0x00014000, + 0x025, 0x000803be, + 0x026, 0x000fc638, + 0x027, 0x00077c18, + 0x028, 0x000d1c31, + 0x029, 0x000d7110, + 0x02a, 0x000aeb04, + 0x02b, 0x0004128b, + 0x02c, 0x00001840, + 0x043, 0x0002444f, + 0x044, 0x0001adb0, + 0x045, 0x00056467, + 0x046, 0x0008992c, + 0x047, 0x0000452c, + 0x048, 0x000f9c43, + 0x049, 0x00002e0c, + 0x04a, 0x000546eb, + 0x04b, 0x0008966c, + 0x04c, 0x0000dde9, + 0x018, 0x00007401, + 0x000, 0x00070000, + 0x012, 0x000dc000, + 0x012, 0x00090000, + 0x012, 0x00051000, + 0x012, 0x00012000, + 0x013, 0x000287b7, + 0x013, 0x000247ab, + 0x013, 0x0002079f, + 0x013, 0x0001c793, + 0x013, 0x0001839b, + 0x013, 0x00014392, + 0x013, 0x0001019a, + 0x013, 0x0000c191, + 0x013, 0x00008194, + 0x013, 0x000040a0, + 0x013, 0x00000018, + 0x015, 0x0000f424, + 0x015, 0x0004f424, + 0x015, 0x0008f424, + 0x016, 0x000e1330, + 0x016, 0x000a1330, + 0x016, 0x00061330, + 0x016, 0x00021330, + 0x018, 0x00017524, + 0x000, 0x00070000, + 0x012, 0x000cf000, + 0x012, 0x000bc000, + 0x012, 0x00078000, + 0x012, 0x00000000, + 0x013, 0x000287bc, + 0x013, 0x000247b0, + 0x013, 0x000203b4, + 0x013, 0x0001c3a8, + 0x013, 0x000181b4, + 0x013, 0x000141a8, + 0x013, 0x000100b0, + 0x013, 0x0000c0a4, + 0x013, 0x0000b02c, + 0x013, 0x00004020, + 0x013, 0x00000014, + 0x015, 0x0000f4c3, + 0x015, 0x0004f4c3, + 0x015, 0x0008f4c3, + 0x016, 0x000e085f, + 0x016, 0x000a085f, + 0x016, 0x0006085f, + 0x016, 0x0002085f, + 0x018, 0x00037524, + 0x000, 0x00070000, + 0x012, 0x000cf000, + 0x012, 0x000bc000, + 0x012, 0x00078000, + 0x012, 0x00000000, + 0x013, 0x000287bc, + 0x013, 0x000247b0, + 0x013, 0x000203b4, + 0x013, 0x0001c3a8, + 0x013, 0x000181b4, + 0x013, 0x000141a8, + 0x013, 0x000100b0, + 0x013, 0x0000c0a4, + 0x013, 0x0000b02c, + 0x013, 0x00004020, + 0x013, 0x00000014, + 0x015, 0x0000f4c3, + 0x015, 0x0004f4c3, + 0x015, 0x0008f4c3, + 0x016, 0x000e085f, + 0x016, 0x000a085f, + 0x016, 0x0006085f, + 0x016, 0x0002085f, + 0x018, 0x00057524, + 0x000, 0x00070000, + 0x012, 0x000cf000, + 0x012, 0x000bc000, + 0x012, 0x00078000, + 0x012, 0x00000000, + 0x013, 0x000287bc, + 0x013, 0x000247b0, + 0x013, 0x000203b4, + 0x013, 0x0001c3a8, + 0x013, 0x000181b4, + 0x013, 0x000141a8, + 0x013, 0x000100b0, + 0x013, 0x0000c0a4, + 0x013, 0x0000b02c, + 0x013, 0x00004020, + 0x013, 0x00000014, + 0x015, 0x0000f4c3, + 0x015, 0x0004f4c3, + 0x015, 0x0008f4c3, + 0x016, 0x000e085f, + 0x016, 0x000a085f, + 0x016, 0x0006085f, + 0x016, 0x0002085f, + 0x030, 0x0004470f, + 0x031, 0x00044ff0, + 0x032, 0x00000070, + 0x033, 0x000dd480, + 0x034, 0x000ffac0, + 0x035, 0x000b80c0, + 0x036, 0x00077000, + 0x037, 0x00064ff2, + 0x038, 0x000e7661, + 0x039, 0x00000e90, + 0x000, 0x00030000, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01e, 0x00088009, + 0x01f, 0x00080003, + 0x0fe, 0x00000000, + 0x01e, 0x00088001, + 0x01f, 0x00080000, + 0x0fe, 0x00000000, + 0x018, 0x00087401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x02b, 0x00041289, + 0x0fe, 0x00000000, + 0x02d, 0x00066666, + 0x02e, 0x00064001, + 0x02d, 0x00091111, + 0x02e, 0x00014002, + 0x02d, 0x000bbbbb, + 0x02e, 0x000b4003, + 0x02d, 0x000e6666, + 0x02e, 0x00064004, + 0x02d, 0x00088888, + 0x02e, 0x00084005, + 0x02d, 0x0009dddd, + 0x02e, 0x000d4006, + 0x02d, 0x000b3333, + 0x02e, 0x00034007, + 0x02d, 0x00048888, + 0x02e, 0x00084408, + 0x02d, 0x000bbbbb, + 0x02e, 0x000b4409, + 0x02d, 0x000e6666, + 0x02e, 0x0006440a, + 0x02d, 0x00011111, + 0x02e, 0x0001480b, + 0x02d, 0x0003bbbb, + 0x02e, 0x000b480c, + 0x02d, 0x00066666, + 0x02e, 0x0006480d, + 0x02d, 0x000ccccc, + 0x02e, 0x000c480e, +}; + +u32 rtl8192de_radioa_2t_int_paarray[RADIOA_2T_INT_PA_ARRAYLENGTH] = { + 0x000, 0x00030000, + 0x001, 0x00030000, + 0x002, 0x00000000, + 0x003, 0x00018c63, + 0x004, 0x00018c63, + 0x008, 0x00084000, + 0x00b, 0x0001c000, + 0x00e, 0x00018c67, + 0x00f, 0x00000851, + 0x014, 0x00021440, + 0x018, 0x00017524, + 0x019, 0x00000000, + 0x01d, 0x000a1290, + 0x023, 0x00001558, + 0x01a, 0x00030a99, + 0x01b, 0x00040b00, + 0x01c, 0x000fc339, + 0x03a, 0x000a57eb, + 0x03b, 0x00020000, + 0x03c, 0x000ff454, + 0x020, 0x0000aa52, + 0x021, 0x00054000, + 0x040, 0x0000aa52, + 0x041, 0x00014000, + 0x025, 0x000803be, + 0x026, 0x000fc638, + 0x027, 0x00077c18, + 0x028, 0x000de471, + 0x029, 0x000d7110, + 0x02a, 0x0008eb04, + 0x02b, 0x0004128b, + 0x02c, 0x00001840, + 0x043, 0x0002444f, + 0x044, 0x0001adb0, + 0x045, 0x00056467, + 0x046, 0x0008992c, + 0x047, 0x0000452c, + 0x048, 0x000c0443, + 0x049, 0x00000730, + 0x04a, 0x00050f0f, + 0x04b, 0x000896ee, + 0x04c, 0x0000ddee, + 0x018, 0x00007401, + 0x000, 0x00070000, + 0x012, 0x000dc000, + 0x012, 0x00090000, + 0x012, 0x00051000, + 0x012, 0x00012000, + 0x013, 0x000287b7, + 0x013, 0x000247ab, + 0x013, 0x0002079f, + 0x013, 0x0001c793, + 0x013, 0x0001839b, + 0x013, 0x00014392, + 0x013, 0x0001019a, + 0x013, 0x0000c191, + 0x013, 0x00008194, + 0x013, 0x000040a0, + 0x013, 0x00000018, + 0x015, 0x0000f424, + 0x015, 0x0004f424, + 0x015, 0x0008f424, + 0x016, 0x000e1330, + 0x016, 0x000a1330, + 0x016, 0x00061330, + 0x016, 0x00021330, + 0x018, 0x00017524, + 0x000, 0x00070000, + 0x012, 0x000cf000, + 0x012, 0x000bc000, + 0x012, 0x00078000, + 0x012, 0x00000000, + 0x013, 0x000287bf, + 0x013, 0x000247b3, + 0x013, 0x000207a7, + 0x013, 0x0001c79b, + 0x013, 0x0001839f, + 0x013, 0x00014393, + 0x013, 0x00010399, + 0x013, 0x0000c38d, + 0x013, 0x00008199, + 0x013, 0x0000418d, + 0x013, 0x00000099, + 0x015, 0x0000f495, + 0x015, 0x0004f495, + 0x015, 0x0008f495, + 0x016, 0x000e1874, + 0x016, 0x000a1874, + 0x016, 0x00061874, + 0x016, 0x00021874, + 0x018, 0x00037564, + 0x000, 0x00070000, + 0x012, 0x000cf000, + 0x012, 0x000bc000, + 0x012, 0x00078000, + 0x012, 0x00000000, + 0x013, 0x000287bf, + 0x013, 0x000247b3, + 0x013, 0x000207a7, + 0x013, 0x0001c79b, + 0x013, 0x0001839f, + 0x013, 0x00014393, + 0x013, 0x00010399, + 0x013, 0x0000c38d, + 0x013, 0x00008199, + 0x013, 0x0000418d, + 0x013, 0x00000099, + 0x015, 0x0000f495, + 0x015, 0x0004f495, + 0x015, 0x0008f495, + 0x016, 0x000e1874, + 0x016, 0x000a1874, + 0x016, 0x00061874, + 0x016, 0x00021874, + 0x018, 0x00057595, + 0x000, 0x00070000, + 0x012, 0x000cf000, + 0x012, 0x000bc000, + 0x012, 0x00078000, + 0x012, 0x00000000, + 0x013, 0x000287bf, + 0x013, 0x000247b3, + 0x013, 0x000207a7, + 0x013, 0x0001c79b, + 0x013, 0x0001839f, + 0x013, 0x00014393, + 0x013, 0x00010399, + 0x013, 0x0000c38d, + 0x013, 0x00008199, + 0x013, 0x0000418d, + 0x013, 0x00000099, + 0x015, 0x0000f495, + 0x015, 0x0004f495, + 0x015, 0x0008f495, + 0x016, 0x000e1874, + 0x016, 0x000a1874, + 0x016, 0x00061874, + 0x016, 0x00021874, + 0x030, 0x0004470f, + 0x031, 0x00044ff0, + 0x032, 0x00000070, + 0x033, 0x000dd480, + 0x034, 0x000ffac0, + 0x035, 0x000b80c0, + 0x036, 0x00077000, + 0x037, 0x00064ff2, + 0x038, 0x000e7661, + 0x039, 0x00000e90, + 0x000, 0x00030000, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01e, 0x00088009, + 0x01f, 0x00080003, + 0x0fe, 0x00000000, + 0x01e, 0x00088001, + 0x01f, 0x00080000, + 0x0fe, 0x00000000, + 0x018, 0x00097524, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x02b, 0x00041289, + 0x0fe, 0x00000000, + 0x02d, 0x0006aaaa, + 0x02e, 0x000b4d01, + 0x02d, 0x00080000, + 0x02e, 0x00004d02, + 0x02d, 0x00095555, + 0x02e, 0x00054d03, + 0x02d, 0x000aaaaa, + 0x02e, 0x000b4d04, + 0x02d, 0x000c0000, + 0x02e, 0x00004d05, + 0x02d, 0x000d5555, + 0x02e, 0x00054d06, + 0x02d, 0x000eaaaa, + 0x02e, 0x000b4d07, + 0x02d, 0x00000000, + 0x02e, 0x00005108, + 0x02d, 0x00015555, + 0x02e, 0x00055109, + 0x02d, 0x0002aaaa, + 0x02e, 0x000b510a, + 0x02d, 0x00040000, + 0x02e, 0x0000510b, + 0x02d, 0x00055555, + 0x02e, 0x0005510c, +}; + +u32 rtl8192de_radiob_2t_int_paarray[RADIOB_2T_INT_PA_ARRAYLENGTH] = { + 0x000, 0x00030000, + 0x001, 0x00030000, + 0x002, 0x00000000, + 0x003, 0x00018c63, + 0x004, 0x00018c63, + 0x008, 0x00084000, + 0x00b, 0x0001c000, + 0x00e, 0x00018c67, + 0x00f, 0x00000851, + 0x014, 0x00021440, + 0x018, 0x00007401, + 0x019, 0x00000060, + 0x01d, 0x000a1290, + 0x023, 0x00001558, + 0x01a, 0x00030a99, + 0x01b, 0x00040b00, + 0x01c, 0x000fc339, + 0x03a, 0x000a57eb, + 0x03b, 0x00020000, + 0x03c, 0x000ff454, + 0x020, 0x0000aa52, + 0x021, 0x00054000, + 0x040, 0x0000aa52, + 0x041, 0x00014000, + 0x025, 0x000803be, + 0x026, 0x000fc638, + 0x027, 0x00077c18, + 0x028, 0x000d1c31, + 0x029, 0x000d7110, + 0x02a, 0x000aeb04, + 0x02b, 0x0004128b, + 0x02c, 0x00001840, + 0x043, 0x0002444f, + 0x044, 0x0001adb0, + 0x045, 0x00056467, + 0x046, 0x0008992c, + 0x047, 0x0000452c, + 0x048, 0x000c0443, + 0x049, 0x00000730, + 0x04a, 0x00050f0f, + 0x04b, 0x000896ee, + 0x04c, 0x0000ddee, + 0x018, 0x00007401, + 0x000, 0x00070000, + 0x012, 0x000dc000, + 0x012, 0x00090000, + 0x012, 0x00051000, + 0x012, 0x00012000, + 0x013, 0x000287b7, + 0x013, 0x000247ab, + 0x013, 0x0002079f, + 0x013, 0x0001c793, + 0x013, 0x0001839b, + 0x013, 0x00014392, + 0x013, 0x0001019a, + 0x013, 0x0000c191, + 0x013, 0x00008194, + 0x013, 0x000040a0, + 0x013, 0x00000018, + 0x015, 0x0000f424, + 0x015, 0x0004f424, + 0x015, 0x0008f424, + 0x016, 0x000e1330, + 0x016, 0x000a1330, + 0x016, 0x00061330, + 0x016, 0x00021330, + 0x018, 0x00017524, + 0x000, 0x00070000, + 0x012, 0x000cf000, + 0x012, 0x000bc000, + 0x012, 0x00078000, + 0x012, 0x00000000, + 0x013, 0x000287bf, + 0x013, 0x000247b3, + 0x013, 0x000207a7, + 0x013, 0x0001c79b, + 0x013, 0x0001839f, + 0x013, 0x00014393, + 0x013, 0x00010399, + 0x013, 0x0000c38d, + 0x013, 0x00008199, + 0x013, 0x0000418d, + 0x013, 0x00000099, + 0x015, 0x0000f495, + 0x015, 0x0004f495, + 0x015, 0x0008f495, + 0x016, 0x000e1874, + 0x016, 0x000a1874, + 0x016, 0x00061874, + 0x016, 0x00021874, + 0x018, 0x00037564, + 0x000, 0x00070000, + 0x012, 0x000cf000, + 0x012, 0x000bc000, + 0x012, 0x00078000, + 0x012, 0x00000000, + 0x013, 0x000287bf, + 0x013, 0x000247b3, + 0x013, 0x000207a7, + 0x013, 0x0001c79b, + 0x013, 0x0001839f, + 0x013, 0x00014393, + 0x013, 0x00010399, + 0x013, 0x0000c38d, + 0x013, 0x00008199, + 0x013, 0x0000418d, + 0x013, 0x00000099, + 0x015, 0x0000f495, + 0x015, 0x0004f495, + 0x015, 0x0008f495, + 0x016, 0x000e1874, + 0x016, 0x000a1874, + 0x016, 0x00061874, + 0x016, 0x00021874, + 0x018, 0x00057595, + 0x000, 0x00070000, + 0x012, 0x000cf000, + 0x012, 0x000bc000, + 0x012, 0x00078000, + 0x012, 0x00000000, + 0x013, 0x000287bf, + 0x013, 0x000247b3, + 0x013, 0x000207a7, + 0x013, 0x0001c79b, + 0x013, 0x0001839f, + 0x013, 0x00014393, + 0x013, 0x00010399, + 0x013, 0x0000c38d, + 0x013, 0x00008199, + 0x013, 0x0000418d, + 0x013, 0x00000099, + 0x015, 0x0000f495, + 0x015, 0x0004f495, + 0x015, 0x0008f495, + 0x016, 0x000e1874, + 0x016, 0x000a1874, + 0x016, 0x00061874, + 0x016, 0x00021874, + 0x030, 0x0004470f, + 0x031, 0x00044ff0, + 0x032, 0x00000070, + 0x033, 0x000dd480, + 0x034, 0x000ffac0, + 0x035, 0x000b80c0, + 0x036, 0x00077000, + 0x037, 0x00064ff2, + 0x038, 0x000e7661, + 0x039, 0x00000e90, + 0x000, 0x00030000, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01e, 0x00088009, + 0x01f, 0x00080003, + 0x0fe, 0x00000000, + 0x01e, 0x00088001, + 0x01f, 0x00080000, + 0x0fe, 0x00000000, + 0x018, 0x00087401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x02b, 0x00041289, + 0x0fe, 0x00000000, + 0x02d, 0x00066666, + 0x02e, 0x00064001, + 0x02d, 0x00091111, + 0x02e, 0x00014002, + 0x02d, 0x000bbbbb, + 0x02e, 0x000b4003, + 0x02d, 0x000e6666, + 0x02e, 0x00064004, + 0x02d, 0x00088888, + 0x02e, 0x00084005, + 0x02d, 0x0009dddd, + 0x02e, 0x000d4006, + 0x02d, 0x000b3333, + 0x02e, 0x00034007, + 0x02d, 0x00048888, + 0x02e, 0x00084408, + 0x02d, 0x000bbbbb, + 0x02e, 0x000b4409, + 0x02d, 0x000e6666, + 0x02e, 0x0006440a, + 0x02d, 0x00011111, + 0x02e, 0x0001480b, + 0x02d, 0x0003bbbb, + 0x02e, 0x000b480c, + 0x02d, 0x00066666, + 0x02e, 0x0006480d, + 0x02d, 0x000ccccc, + 0x02e, 0x000c480e, +}; + +u32 rtl8192de_mac_2tarray[MAC_2T_ARRAYLENGTH] = { + 0x420, 0x00000080, + 0x423, 0x00000000, + 0x430, 0x00000000, + 0x431, 0x00000000, + 0x432, 0x00000000, + 0x433, 0x00000001, + 0x434, 0x00000004, + 0x435, 0x00000005, + 0x436, 0x00000006, + 0x437, 0x00000007, + 0x438, 0x00000000, + 0x439, 0x00000000, + 0x43a, 0x00000000, + 0x43b, 0x00000001, + 0x43c, 0x00000004, + 0x43d, 0x00000005, + 0x43e, 0x00000006, + 0x43f, 0x00000007, + 0x440, 0x00000050, + 0x441, 0x00000001, + 0x442, 0x00000000, + 0x444, 0x00000015, + 0x445, 0x000000f0, + 0x446, 0x0000000f, + 0x447, 0x00000000, + 0x462, 0x00000008, + 0x463, 0x00000003, + 0x4c8, 0x000000ff, + 0x4c9, 0x00000008, + 0x4cc, 0x000000ff, + 0x4cd, 0x000000ff, + 0x4ce, 0x00000001, + 0x500, 0x00000026, + 0x501, 0x000000a2, + 0x502, 0x0000002f, + 0x503, 0x00000000, + 0x504, 0x00000028, + 0x505, 0x000000a3, + 0x506, 0x0000005e, + 0x507, 0x00000000, + 0x508, 0x0000002b, + 0x509, 0x000000a4, + 0x50a, 0x0000005e, + 0x50b, 0x00000000, + 0x50c, 0x0000004f, + 0x50d, 0x000000a4, + 0x50e, 0x00000000, + 0x50f, 0x00000000, + 0x512, 0x0000001c, + 0x514, 0x0000000a, + 0x515, 0x00000010, + 0x516, 0x0000000a, + 0x517, 0x00000010, + 0x51a, 0x00000016, + 0x524, 0x0000000f, + 0x525, 0x0000004f, + 0x546, 0x00000040, + 0x547, 0x00000000, + 0x550, 0x00000010, + 0x551, 0x00000010, + 0x559, 0x00000002, + 0x55a, 0x00000002, + 0x55d, 0x000000ff, + 0x605, 0x00000030, + 0x608, 0x0000000e, + 0x609, 0x0000002a, + 0x652, 0x00000020, + 0x63c, 0x0000000a, + 0x63d, 0x0000000a, + 0x63e, 0x0000000e, + 0x63f, 0x0000000e, + 0x66e, 0x00000005, + 0x700, 0x00000021, + 0x701, 0x00000043, + 0x702, 0x00000065, + 0x703, 0x00000087, + 0x708, 0x00000021, + 0x709, 0x00000043, + 0x70a, 0x00000065, + 0x70b, 0x00000087, +}; + +u32 rtl8192de_agctab_array[AGCTAB_ARRAYLENGTH] = { + 0xc78, 0x7b000001, + 0xc78, 0x7b010001, + 0xc78, 0x7b020001, + 0xc78, 0x7b030001, + 0xc78, 0x7b040001, + 0xc78, 0x7b050001, + 0xc78, 0x7b060001, + 0xc78, 0x7a070001, + 0xc78, 0x79080001, + 0xc78, 0x78090001, + 0xc78, 0x770a0001, + 0xc78, 0x760b0001, + 0xc78, 0x750c0001, + 0xc78, 0x740d0001, + 0xc78, 0x730e0001, + 0xc78, 0x720f0001, + 0xc78, 0x71100001, + 0xc78, 0x70110001, + 0xc78, 0x6f120001, + 0xc78, 0x6e130001, + 0xc78, 0x6d140001, + 0xc78, 0x6c150001, + 0xc78, 0x6b160001, + 0xc78, 0x6a170001, + 0xc78, 0x69180001, + 0xc78, 0x68190001, + 0xc78, 0x671a0001, + 0xc78, 0x661b0001, + 0xc78, 0x651c0001, + 0xc78, 0x641d0001, + 0xc78, 0x631e0001, + 0xc78, 0x621f0001, + 0xc78, 0x61200001, + 0xc78, 0x60210001, + 0xc78, 0x49220001, + 0xc78, 0x48230001, + 0xc78, 0x47240001, + 0xc78, 0x46250001, + 0xc78, 0x45260001, + 0xc78, 0x44270001, + 0xc78, 0x43280001, + 0xc78, 0x42290001, + 0xc78, 0x412a0001, + 0xc78, 0x402b0001, + 0xc78, 0x262c0001, + 0xc78, 0x252d0001, + 0xc78, 0x242e0001, + 0xc78, 0x232f0001, + 0xc78, 0x22300001, + 0xc78, 0x21310001, + 0xc78, 0x20320001, + 0xc78, 0x06330001, + 0xc78, 0x05340001, + 0xc78, 0x04350001, + 0xc78, 0x03360001, + 0xc78, 0x02370001, + 0xc78, 0x01380001, + 0xc78, 0x00390001, + 0xc78, 0x003a0001, + 0xc78, 0x003b0001, + 0xc78, 0x003c0001, + 0xc78, 0x003d0001, + 0xc78, 0x003e0001, + 0xc78, 0x003f0001, + 0xc78, 0x7b400001, + 0xc78, 0x7b410001, + 0xc78, 0x7a420001, + 0xc78, 0x79430001, + 0xc78, 0x78440001, + 0xc78, 0x77450001, + 0xc78, 0x76460001, + 0xc78, 0x75470001, + 0xc78, 0x74480001, + 0xc78, 0x73490001, + 0xc78, 0x724a0001, + 0xc78, 0x714b0001, + 0xc78, 0x704c0001, + 0xc78, 0x6f4d0001, + 0xc78, 0x6e4e0001, + 0xc78, 0x6d4f0001, + 0xc78, 0x6c500001, + 0xc78, 0x6b510001, + 0xc78, 0x6a520001, + 0xc78, 0x69530001, + 0xc78, 0x68540001, + 0xc78, 0x67550001, + 0xc78, 0x66560001, + 0xc78, 0x65570001, + 0xc78, 0x64580001, + 0xc78, 0x63590001, + 0xc78, 0x625a0001, + 0xc78, 0x615b0001, + 0xc78, 0x605c0001, + 0xc78, 0x485d0001, + 0xc78, 0x475e0001, + 0xc78, 0x465f0001, + 0xc78, 0x45600001, + 0xc78, 0x44610001, + 0xc78, 0x43620001, + 0xc78, 0x42630001, + 0xc78, 0x41640001, + 0xc78, 0x40650001, + 0xc78, 0x27660001, + 0xc78, 0x26670001, + 0xc78, 0x25680001, + 0xc78, 0x24690001, + 0xc78, 0x236a0001, + 0xc78, 0x226b0001, + 0xc78, 0x216c0001, + 0xc78, 0x206d0001, + 0xc78, 0x206e0001, + 0xc78, 0x206f0001, + 0xc78, 0x20700001, + 0xc78, 0x20710001, + 0xc78, 0x20720001, + 0xc78, 0x20730001, + 0xc78, 0x20740001, + 0xc78, 0x20750001, + 0xc78, 0x20760001, + 0xc78, 0x20770001, + 0xc78, 0x20780001, + 0xc78, 0x20790001, + 0xc78, 0x207a0001, + 0xc78, 0x207b0001, + 0xc78, 0x207c0001, + 0xc78, 0x207d0001, + 0xc78, 0x207e0001, + 0xc78, 0x207f0001, + 0xc78, 0x38000002, + 0xc78, 0x38010002, + 0xc78, 0x38020002, + 0xc78, 0x38030002, + 0xc78, 0x38040002, + 0xc78, 0x38050002, + 0xc78, 0x38060002, + 0xc78, 0x38070002, + 0xc78, 0x38080002, + 0xc78, 0x3c090002, + 0xc78, 0x3e0a0002, + 0xc78, 0x400b0002, + 0xc78, 0x440c0002, + 0xc78, 0x480d0002, + 0xc78, 0x4c0e0002, + 0xc78, 0x500f0002, + 0xc78, 0x52100002, + 0xc78, 0x56110002, + 0xc78, 0x5a120002, + 0xc78, 0x5e130002, + 0xc78, 0x60140002, + 0xc78, 0x60150002, + 0xc78, 0x60160002, + 0xc78, 0x62170002, + 0xc78, 0x62180002, + 0xc78, 0x62190002, + 0xc78, 0x621a0002, + 0xc78, 0x621b0002, + 0xc78, 0x621c0002, + 0xc78, 0x621d0002, + 0xc78, 0x621e0002, + 0xc78, 0x621f0002, + 0xc78, 0x32000044, + 0xc78, 0x32010044, + 0xc78, 0x32020044, + 0xc78, 0x32030044, + 0xc78, 0x32040044, + 0xc78, 0x32050044, + 0xc78, 0x32060044, + 0xc78, 0x32070044, + 0xc78, 0x32080044, + 0xc78, 0x34090044, + 0xc78, 0x350a0044, + 0xc78, 0x360b0044, + 0xc78, 0x370c0044, + 0xc78, 0x380d0044, + 0xc78, 0x390e0044, + 0xc78, 0x3a0f0044, + 0xc78, 0x3e100044, + 0xc78, 0x42110044, + 0xc78, 0x44120044, + 0xc78, 0x46130044, + 0xc78, 0x4a140044, + 0xc78, 0x4e150044, + 0xc78, 0x50160044, + 0xc78, 0x55170044, + 0xc78, 0x5a180044, + 0xc78, 0x5e190044, + 0xc78, 0x641a0044, + 0xc78, 0x6e1b0044, + 0xc78, 0x6e1c0044, + 0xc78, 0x6e1d0044, + 0xc78, 0x6e1e0044, + 0xc78, 0x6e1f0044, + 0xc78, 0x6e1f0000, +}; + +u32 rtl8192de_agctab_5garray[AGCTAB_5G_ARRAYLENGTH] = { + 0xc78, 0x7b000001, + 0xc78, 0x7b010001, + 0xc78, 0x7a020001, + 0xc78, 0x79030001, + 0xc78, 0x78040001, + 0xc78, 0x77050001, + 0xc78, 0x76060001, + 0xc78, 0x75070001, + 0xc78, 0x74080001, + 0xc78, 0x73090001, + 0xc78, 0x720a0001, + 0xc78, 0x710b0001, + 0xc78, 0x700c0001, + 0xc78, 0x6f0d0001, + 0xc78, 0x6e0e0001, + 0xc78, 0x6d0f0001, + 0xc78, 0x6c100001, + 0xc78, 0x6b110001, + 0xc78, 0x6a120001, + 0xc78, 0x69130001, + 0xc78, 0x68140001, + 0xc78, 0x67150001, + 0xc78, 0x66160001, + 0xc78, 0x65170001, + 0xc78, 0x64180001, + 0xc78, 0x63190001, + 0xc78, 0x621a0001, + 0xc78, 0x611b0001, + 0xc78, 0x601c0001, + 0xc78, 0x481d0001, + 0xc78, 0x471e0001, + 0xc78, 0x461f0001, + 0xc78, 0x45200001, + 0xc78, 0x44210001, + 0xc78, 0x43220001, + 0xc78, 0x42230001, + 0xc78, 0x41240001, + 0xc78, 0x40250001, + 0xc78, 0x27260001, + 0xc78, 0x26270001, + 0xc78, 0x25280001, + 0xc78, 0x24290001, + 0xc78, 0x232a0001, + 0xc78, 0x222b0001, + 0xc78, 0x212c0001, + 0xc78, 0x202d0001, + 0xc78, 0x202e0001, + 0xc78, 0x202f0001, + 0xc78, 0x20300001, + 0xc78, 0x20310001, + 0xc78, 0x20320001, + 0xc78, 0x20330001, + 0xc78, 0x20340001, + 0xc78, 0x20350001, + 0xc78, 0x20360001, + 0xc78, 0x20370001, + 0xc78, 0x20380001, + 0xc78, 0x20390001, + 0xc78, 0x203a0001, + 0xc78, 0x203b0001, + 0xc78, 0x203c0001, + 0xc78, 0x203d0001, + 0xc78, 0x203e0001, + 0xc78, 0x203f0001, + 0xc78, 0x32000044, + 0xc78, 0x32010044, + 0xc78, 0x32020044, + 0xc78, 0x32030044, + 0xc78, 0x32040044, + 0xc78, 0x32050044, + 0xc78, 0x32060044, + 0xc78, 0x32070044, + 0xc78, 0x32080044, + 0xc78, 0x34090044, + 0xc78, 0x350a0044, + 0xc78, 0x360b0044, + 0xc78, 0x370c0044, + 0xc78, 0x380d0044, + 0xc78, 0x390e0044, + 0xc78, 0x3a0f0044, + 0xc78, 0x3e100044, + 0xc78, 0x42110044, + 0xc78, 0x44120044, + 0xc78, 0x46130044, + 0xc78, 0x4a140044, + 0xc78, 0x4e150044, + 0xc78, 0x50160044, + 0xc78, 0x55170044, + 0xc78, 0x5a180044, + 0xc78, 0x5e190044, + 0xc78, 0x641a0044, + 0xc78, 0x6e1b0044, + 0xc78, 0x6e1c0044, + 0xc78, 0x6e1d0044, + 0xc78, 0x6e1e0044, + 0xc78, 0x6e1f0044, + 0xc78, 0x6e1f0000, +}; + +u32 rtl8192de_agctab_2garray[AGCTAB_2G_ARRAYLENGTH] = { + 0xc78, 0x7b000001, + 0xc78, 0x7b010001, + 0xc78, 0x7b020001, + 0xc78, 0x7b030001, + 0xc78, 0x7b040001, + 0xc78, 0x7b050001, + 0xc78, 0x7b060001, + 0xc78, 0x7a070001, + 0xc78, 0x79080001, + 0xc78, 0x78090001, + 0xc78, 0x770a0001, + 0xc78, 0x760b0001, + 0xc78, 0x750c0001, + 0xc78, 0x740d0001, + 0xc78, 0x730e0001, + 0xc78, 0x720f0001, + 0xc78, 0x71100001, + 0xc78, 0x70110001, + 0xc78, 0x6f120001, + 0xc78, 0x6e130001, + 0xc78, 0x6d140001, + 0xc78, 0x6c150001, + 0xc78, 0x6b160001, + 0xc78, 0x6a170001, + 0xc78, 0x69180001, + 0xc78, 0x68190001, + 0xc78, 0x671a0001, + 0xc78, 0x661b0001, + 0xc78, 0x651c0001, + 0xc78, 0x641d0001, + 0xc78, 0x631e0001, + 0xc78, 0x621f0001, + 0xc78, 0x61200001, + 0xc78, 0x60210001, + 0xc78, 0x49220001, + 0xc78, 0x48230001, + 0xc78, 0x47240001, + 0xc78, 0x46250001, + 0xc78, 0x45260001, + 0xc78, 0x44270001, + 0xc78, 0x43280001, + 0xc78, 0x42290001, + 0xc78, 0x412a0001, + 0xc78, 0x402b0001, + 0xc78, 0x262c0001, + 0xc78, 0x252d0001, + 0xc78, 0x242e0001, + 0xc78, 0x232f0001, + 0xc78, 0x22300001, + 0xc78, 0x21310001, + 0xc78, 0x20320001, + 0xc78, 0x06330001, + 0xc78, 0x05340001, + 0xc78, 0x04350001, + 0xc78, 0x03360001, + 0xc78, 0x02370001, + 0xc78, 0x01380001, + 0xc78, 0x00390001, + 0xc78, 0x003a0001, + 0xc78, 0x003b0001, + 0xc78, 0x003c0001, + 0xc78, 0x003d0001, + 0xc78, 0x003e0001, + 0xc78, 0x003f0001, + 0xc78, 0x38000002, + 0xc78, 0x38010002, + 0xc78, 0x38020002, + 0xc78, 0x38030002, + 0xc78, 0x38040002, + 0xc78, 0x38050002, + 0xc78, 0x38060002, + 0xc78, 0x38070002, + 0xc78, 0x38080002, + 0xc78, 0x3c090002, + 0xc78, 0x3e0a0002, + 0xc78, 0x400b0002, + 0xc78, 0x440c0002, + 0xc78, 0x480d0002, + 0xc78, 0x4c0e0002, + 0xc78, 0x500f0002, + 0xc78, 0x52100002, + 0xc78, 0x56110002, + 0xc78, 0x5a120002, + 0xc78, 0x5e130002, + 0xc78, 0x60140002, + 0xc78, 0x60150002, + 0xc78, 0x60160002, + 0xc78, 0x62170002, + 0xc78, 0x62180002, + 0xc78, 0x62190002, + 0xc78, 0x621a0002, + 0xc78, 0x621b0002, + 0xc78, 0x621c0002, + 0xc78, 0x621d0002, + 0xc78, 0x621e0002, + 0xc78, 0x621f0002, + 0xc78, 0x6e1f0000, +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h new file mode 100644 index 000000000000..8b724a86117a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/table.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + * Created on 2010/ 5/18, 1:41 + *****************************************************************************/ + +#ifndef __RTL92DE_TABLE__H_ +#define __RTL92DE_TABLE__H_ + +/*Created on 2011/ 1/14, 1:35*/ + +#define PHY_REG_2T_ARRAYLENGTH 380 +extern u32 rtl8192de_phy_reg_2tarray[PHY_REG_2T_ARRAYLENGTH]; +#define PHY_REG_ARRAY_PG_LENGTH 624 +extern u32 rtl8192de_phy_reg_array_pg[PHY_REG_ARRAY_PG_LENGTH]; +#define RADIOA_2T_ARRAYLENGTH 378 +extern u32 rtl8192de_radioa_2tarray[RADIOA_2T_ARRAYLENGTH]; +#define RADIOB_2T_ARRAYLENGTH 384 +extern u32 rtl8192de_radiob_2tarray[RADIOB_2T_ARRAYLENGTH]; +#define RADIOA_2T_INT_PA_ARRAYLENGTH 378 +extern u32 rtl8192de_radioa_2t_int_paarray[RADIOA_2T_INT_PA_ARRAYLENGTH]; +#define RADIOB_2T_INT_PA_ARRAYLENGTH 384 +extern u32 rtl8192de_radiob_2t_int_paarray[RADIOB_2T_INT_PA_ARRAYLENGTH]; +#define MAC_2T_ARRAYLENGTH 160 +extern u32 rtl8192de_mac_2tarray[MAC_2T_ARRAYLENGTH]; +#define AGCTAB_ARRAYLENGTH 386 +extern u32 rtl8192de_agctab_array[AGCTAB_ARRAYLENGTH]; +#define AGCTAB_5G_ARRAYLENGTH 194 +extern u32 rtl8192de_agctab_5garray[AGCTAB_5G_ARRAYLENGTH]; +#define AGCTAB_2G_ARRAYLENGTH 194 +extern u32 rtl8192de_agctab_2garray[AGCTAB_2G_ARRAYLENGTH]; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c new file mode 100644 index 000000000000..1feaa629dd4f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c @@ -0,0 +1,871 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "trx.h" +#include "led.h" + +static u8 _rtl92de_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) +{ + __le16 fc = rtl_get_fc(skb); + + if (unlikely(ieee80211_is_beacon(fc))) + return QSLT_BEACON; + if (ieee80211_is_mgmt(fc)) + return QSLT_MGNT; + + return skb->priority; +} + +static u8 _rtl92d_query_rxpwrpercentage(char antpower) +{ + if ((antpower <= -100) || (antpower >= 20)) + return 0; + else if (antpower >= 0) + return 100; + else + return 100 + antpower; +} + +static u8 _rtl92d_evm_db_to_percentage(char value) +{ + char ret_val = value; + + if (ret_val >= 0) + ret_val = 0; + if (ret_val <= -33) + ret_val = -33; + ret_val = 0 - ret_val; + ret_val *= 3; + if (ret_val == 99) + ret_val = 100; + return ret_val; +} + +static long _rtl92de_translate_todbm(struct ieee80211_hw *hw, + u8 signal_strength_index) +{ + long signal_power; + + signal_power = (long)((signal_strength_index + 1) >> 1); + signal_power -= 95; + return signal_power; +} + +static long _rtl92de_signal_scale_mapping(struct ieee80211_hw *hw, long currsig) +{ + long retsig; + + if (currsig >= 61 && currsig <= 100) + retsig = 90 + ((currsig - 60) / 4); + else if (currsig >= 41 && currsig <= 60) + retsig = 78 + ((currsig - 40) / 2); + else if (currsig >= 31 && currsig <= 40) + retsig = 66 + (currsig - 30); + else if (currsig >= 21 && currsig <= 30) + retsig = 54 + (currsig - 20); + else if (currsig >= 5 && currsig <= 20) + retsig = 42 + (((currsig - 5) * 2) / 3); + else if (currsig == 4) + retsig = 36; + else if (currsig == 3) + retsig = 27; + else if (currsig == 2) + retsig = 18; + else if (currsig == 1) + retsig = 9; + else + retsig = currsig; + return retsig; +} + +static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw, + struct rtl_stats *pstats, + struct rx_desc_92d *pdesc, + struct rx_fwinfo_92d *p_drvinfo, + bool packet_match_bssid, + bool packet_toself, + bool packet_beacon) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); + struct phy_sts_cck_8192d *cck_buf; + s8 rx_pwr_all, rx_pwr[4]; + u8 rf_rx_num = 0, evm, pwdb_all; + u8 i, max_spatial_stream; + u32 rssi, total_rssi = 0; + bool is_cck_rate; + + is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc->rxmcs); + pstats->packet_matchbssid = packet_match_bssid; + pstats->packet_toself = packet_toself; + pstats->packet_beacon = packet_beacon; + pstats->is_cck = is_cck_rate; + pstats->rx_mimo_sig_qual[0] = -1; + pstats->rx_mimo_sig_qual[1] = -1; + + if (is_cck_rate) { + u8 report, cck_highpwr; + cck_buf = (struct phy_sts_cck_8192d *)p_drvinfo; + if (ppsc->rfpwr_state == ERFON) + cck_highpwr = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + BIT(9)); + else + cck_highpwr = false; + if (!cck_highpwr) { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = cck_buf->cck_agc_rpt & 0xc0; + report = report >> 6; + switch (report) { + case 0x3: + rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); + break; + case 0x2: + rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); + break; + case 0x1: + rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); + break; + case 0x0: + rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); + break; + } + } else { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = p_drvinfo->cfosho[0] & 0x60; + report = report >> 5; + switch (report) { + case 0x3: + rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x2: + rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x1: + rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x0: + rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1); + break; + } + } + pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all); + /* CCK gain is smaller than OFDM/MCS gain, */ + /* so we add gain diff by experiences, the val is 6 */ + pwdb_all += 6; + if (pwdb_all > 100) + pwdb_all = 100; + /* modify the offset to make the same gain index with OFDM. */ + if (pwdb_all > 34 && pwdb_all <= 42) + pwdb_all -= 2; + else if (pwdb_all > 26 && pwdb_all <= 34) + pwdb_all -= 6; + else if (pwdb_all > 14 && pwdb_all <= 26) + pwdb_all -= 8; + else if (pwdb_all > 4 && pwdb_all <= 14) + pwdb_all -= 4; + pstats->rx_pwdb_all = pwdb_all; + pstats->recvsignalpower = rx_pwr_all; + if (packet_match_bssid) { + u8 sq; + if (pstats->rx_pwdb_all > 40) { + sq = 100; + } else { + sq = cck_buf->sq_rpt; + if (sq > 64) + sq = 0; + else if (sq < 20) + sq = 100; + else + sq = ((64 - sq) * 100) / 44; + } + pstats->signalquality = sq; + pstats->rx_mimo_sig_qual[0] = sq; + pstats->rx_mimo_sig_qual[1] = -1; + } + } else { + rtlpriv->dm.rfpath_rxenable[0] = true; + rtlpriv->dm.rfpath_rxenable[1] = true; + for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { + if (rtlpriv->dm.rfpath_rxenable[i]) + rf_rx_num++; + rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) + - 110; + rssi = _rtl92d_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + rtlpriv->stats.rx_snr_db[i] = + (long)(p_drvinfo->rxsnr[i] / 2); + if (packet_match_bssid) + pstats->rx_mimo_signalstrength[i] = (u8) rssi; + } + rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 106; + pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all); + pstats->rx_pwdb_all = pwdb_all; + pstats->rxpower = rx_pwr_all; + pstats->recvsignalpower = rx_pwr_all; + if (pdesc->rxht && pdesc->rxmcs >= DESC_RATEMCS8 && + pdesc->rxmcs <= DESC_RATEMCS15) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + for (i = 0; i < max_spatial_stream; i++) { + evm = _rtl92d_evm_db_to_percentage(p_drvinfo->rxevm[i]); + if (packet_match_bssid) { + if (i == 0) + pstats->signalquality = + (u8)(evm & 0xff); + pstats->rx_mimo_sig_qual[i] = + (u8)(evm & 0xff); + } + } + } + if (is_cck_rate) + pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw, + pwdb_all)); + else if (rf_rx_num != 0) + pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw, + total_rssi /= rf_rx_num)); +} + +static void rtl92d_loop_over_paths(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u8 rfpath; + + for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; + rfpath++) { + if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { + rtlpriv->stats.rx_rssi_percentage[rfpath] = + pstats->rx_mimo_signalstrength[rfpath]; + + } + if (pstats->rx_mimo_signalstrength[rfpath] > + rtlpriv->stats.rx_rssi_percentage[rfpath]) { + rtlpriv->stats.rx_rssi_percentage[rfpath] = + ((rtlpriv->stats.rx_rssi_percentage[rfpath] * + (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_mimo_signalstrength[rfpath])) / + (RX_SMOOTH_FACTOR); + rtlpriv->stats.rx_rssi_percentage[rfpath] = + rtlpriv->stats.rx_rssi_percentage[rfpath] + 1; + } else { + rtlpriv->stats.rx_rssi_percentage[rfpath] = + ((rtlpriv->stats.rx_rssi_percentage[rfpath] * + (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_mimo_signalstrength[rfpath])) / + (RX_SMOOTH_FACTOR); + } + } +} + +static void _rtl92de_process_ui_rssi(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 last_rssi, tmpval; + + if (pstats->packet_toself || pstats->packet_beacon) { + rtlpriv->stats.rssi_calculate_cnt++; + if (rtlpriv->stats.ui_rssi.total_num++ >= + PHY_RSSI_SLID_WIN_MAX) { + rtlpriv->stats.ui_rssi.total_num = + PHY_RSSI_SLID_WIN_MAX; + last_rssi = rtlpriv->stats.ui_rssi.elements[ + rtlpriv->stats.ui_rssi.index]; + rtlpriv->stats.ui_rssi.total_val -= last_rssi; + } + rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; + rtlpriv->stats.ui_rssi.elements + [rtlpriv->stats.ui_rssi.index++] = + pstats->signalstrength; + if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) + rtlpriv->stats.ui_rssi.index = 0; + tmpval = rtlpriv->stats.ui_rssi.total_val / + rtlpriv->stats.ui_rssi.total_num; + rtlpriv->stats.signal_strength = _rtl92de_translate_todbm(hw, + (u8) tmpval); + pstats->rssi = rtlpriv->stats.signal_strength; + } + if (!pstats->is_cck && pstats->packet_toself) + rtl92d_loop_over_paths(hw, pstats); +} + +static void _rtl92de_update_rxsignalstatistics(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int weighting = 0; + + if (rtlpriv->stats.recv_signal_power == 0) + rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; + if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) + weighting = 5; + else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) + weighting = (-5); + rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power * + 5 + pstats->recvsignalpower + weighting) / 6; +} + +static void _rtl92de_process_pwdb(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undec_sm_pwdb; + + if (mac->opmode == NL80211_IFTYPE_ADHOC || + mac->opmode == NL80211_IFTYPE_AP) + return; + else + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; + + if (pstats->packet_toself || pstats->packet_beacon) { + if (undec_sm_pwdb < 0) + undec_sm_pwdb = pstats->rx_pwdb_all; + if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { + undec_sm_pwdb = (((undec_sm_pwdb) * + (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + undec_sm_pwdb = undec_sm_pwdb + 1; + } else { + undec_sm_pwdb = (((undec_sm_pwdb) * + (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + } + rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; + _rtl92de_update_rxsignalstatistics(hw, pstats); + } +} + +static void rtl92d_loop_over_streams(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int stream; + + for (stream = 0; stream < 2; stream++) { + if (pstats->rx_mimo_sig_qual[stream] != -1) { + if (rtlpriv->stats.rx_evm_percentage[stream] == 0) { + rtlpriv->stats.rx_evm_percentage[stream] = + pstats->rx_mimo_sig_qual[stream]; + } + rtlpriv->stats.rx_evm_percentage[stream] = + ((rtlpriv->stats.rx_evm_percentage[stream] + * (RX_SMOOTH_FACTOR - 1)) + + (pstats->rx_mimo_sig_qual[stream] * 1)) / + (RX_SMOOTH_FACTOR); + } + } +} + +static void _rtl92de_process_ui_link_quality(struct ieee80211_hw *hw, + struct rtl_stats *pstats) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 last_evm, tmpval; + + if (pstats->signalquality == 0) + return; + if (pstats->packet_toself || pstats->packet_beacon) { + if (rtlpriv->stats.ui_link_quality.total_num++ >= + PHY_LINKQUALITY_SLID_WIN_MAX) { + rtlpriv->stats.ui_link_quality.total_num = + PHY_LINKQUALITY_SLID_WIN_MAX; + last_evm = rtlpriv->stats.ui_link_quality.elements[ + rtlpriv->stats.ui_link_quality.index]; + rtlpriv->stats.ui_link_quality.total_val -= last_evm; + } + rtlpriv->stats.ui_link_quality.total_val += + pstats->signalquality; + rtlpriv->stats.ui_link_quality.elements[ + rtlpriv->stats.ui_link_quality.index++] = + pstats->signalquality; + if (rtlpriv->stats.ui_link_quality.index >= + PHY_LINKQUALITY_SLID_WIN_MAX) + rtlpriv->stats.ui_link_quality.index = 0; + tmpval = rtlpriv->stats.ui_link_quality.total_val / + rtlpriv->stats.ui_link_quality.total_num; + rtlpriv->stats.signal_quality = tmpval; + rtlpriv->stats.last_sigstrength_inpercent = tmpval; + rtl92d_loop_over_streams(hw, pstats); + } +} + +static void _rtl92de_process_phyinfo(struct ieee80211_hw *hw, + u8 *buffer, + struct rtl_stats *pcurrent_stats) +{ + + if (!pcurrent_stats->packet_matchbssid && + !pcurrent_stats->packet_beacon) + return; + + _rtl92de_process_ui_rssi(hw, pcurrent_stats); + _rtl92de_process_pwdb(hw, pcurrent_stats); + _rtl92de_process_ui_link_quality(hw, pcurrent_stats); +} + +static void _rtl92de_translate_rx_signal_stuff(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct rtl_stats *pstats, + struct rx_desc_92d *pdesc, + struct rx_fwinfo_92d *p_drvinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct ieee80211_hdr *hdr; + u8 *tmp_buf; + u8 *praddr; + u16 type, cfc; + __le16 fc; + bool packet_matchbssid, packet_toself, packet_beacon = false; + + tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; + hdr = (struct ieee80211_hdr *)tmp_buf; + fc = hdr->frame_control; + cfc = le16_to_cpu(fc); + type = WLAN_FC_GET_TYPE(fc); + praddr = hdr->addr1; + packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && + ether_addr_equal(mac->bssid, + (cfc & IEEE80211_FCTL_TODS) ? hdr->addr1 : + (cfc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : + hdr->addr3) && + (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv)); + packet_toself = packet_matchbssid && + ether_addr_equal(praddr, rtlefuse->dev_addr); + if (ieee80211_is_beacon(fc)) + packet_beacon = true; + _rtl92de_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, + packet_matchbssid, packet_toself, + packet_beacon); + _rtl92de_process_phyinfo(hw, tmp_buf, pstats); +} + +bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, + u8 *p_desc, struct sk_buff *skb) +{ + struct rx_fwinfo_92d *p_drvinfo; + struct rx_desc_92d *pdesc = (struct rx_desc_92d *)p_desc; + u32 phystatus = GET_RX_DESC_PHYST(pdesc); + + stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); + stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * + RX_DRV_INFO_SIZE_UNIT; + stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); + stats->icv = (u16) GET_RX_DESC_ICV(pdesc); + stats->crc = (u16) GET_RX_DESC_CRC32(pdesc); + stats->hwerror = (stats->crc | stats->icv); + stats->decrypted = !GET_RX_DESC_SWDEC(pdesc); + stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc); + stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); + stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); + stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) + && (GET_RX_DESC_FAGGR(pdesc) == 1)); + stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); + stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); + stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + if (GET_RX_DESC_CRC32(pdesc)) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (!GET_RX_DESC_SWDEC(pdesc)) + rx_status->flag |= RX_FLAG_DECRYPTED; + if (GET_RX_DESC_BW(pdesc)) + rx_status->flag |= RX_FLAG_40MHZ; + if (GET_RX_DESC_RXHT(pdesc)) + rx_status->flag |= RX_FLAG_HT; + rx_status->flag |= RX_FLAG_MACTIME_START; + if (stats->decrypted) + rx_status->flag |= RX_FLAG_DECRYPTED; + rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht, + false, stats->rate); + rx_status->mactime = GET_RX_DESC_TSFL(pdesc); + if (phystatus) { + p_drvinfo = (struct rx_fwinfo_92d *)(skb->data + + stats->rx_bufshift); + _rtl92de_translate_rx_signal_stuff(hw, + skb, stats, pdesc, + p_drvinfo); + } + /*rx_status->qual = stats->signal; */ + rx_status->signal = stats->recvsignalpower + 10; + return true; +} + +static void _rtl92de_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, + u8 *virtualaddress) +{ + memset(virtualaddress, 0, 8); + + SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); + SET_EARLYMODE_LEN0(virtualaddress, ptcb_desc->empkt_len[0]); + SET_EARLYMODE_LEN1(virtualaddress, ptcb_desc->empkt_len[1]); + SET_EARLYMODE_LEN2_1(virtualaddress, ptcb_desc->empkt_len[2] & 0xF); + SET_EARLYMODE_LEN2_2(virtualaddress, ptcb_desc->empkt_len[2] >> 4); + SET_EARLYMODE_LEN3(virtualaddress, ptcb_desc->empkt_len[3]); + SET_EARLYMODE_LEN4(virtualaddress, ptcb_desc->empkt_len[4]); +} + +void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *pbd_desc_tx, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 *pdesc = pdesc_tx; + u16 seq_number; + __le16 fc = hdr->frame_control; + unsigned int buf_len = 0; + unsigned int skb_len = skb->len; + u8 fw_qsel = _rtl92de_map_hwqueue_to_fwqueue(skb, hw_queue); + bool firstseg = ((hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); + bool lastseg = ((hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); + dma_addr_t mapping; + u8 bw_40 = 0; + + if (mac->opmode == NL80211_IFTYPE_STATION) { + bw_40 = mac->bw_40; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta) + bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; + } + seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); + /* reserve 8 byte for AMPDU early mode */ + if (rtlhal->earlymode_enable) { + skb_push(skb, EM_HDR_LEN); + memset(skb->data, 0, EM_HDR_LEN); + } + buf_len = skb->len; + mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92d)); + if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { + firstseg = true; + lastseg = true; + } + if (firstseg) { + if (rtlhal->earlymode_enable) { + SET_TX_DESC_PKT_OFFSET(pdesc, 1); + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + + EM_HDR_LEN); + if (ptcb_desc->empkt_num) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD, + "Insert 8 byte.pTcb->EMPktNum:%d\n", + ptcb_desc->empkt_num); + _rtl92de_insert_emcontent(ptcb_desc, + (u8 *)(skb->data)); + } + } else { + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + } + /* 5G have no CCK rate */ + if (rtlhal->current_bandtype == BAND_ON_5G) + if (ptcb_desc->hw_rate < DESC_RATE6M) + ptcb_desc->hw_rate = DESC_RATE6M; + SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); + if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) + SET_TX_DESC_DATA_SHORTGI(pdesc, 1); + + if (rtlhal->macphymode == DUALMAC_DUALPHY && + ptcb_desc->hw_rate == DESC_RATEMCS7) + SET_TX_DESC_DATA_SHORTGI(pdesc, 1); + + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + SET_TX_DESC_AGG_ENABLE(pdesc, 1); + SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); + } + SET_TX_DESC_SEQ(pdesc, seq_number); + SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && + !ptcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_HW_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable + || ptcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); + /* 5G have no CCK rate */ + if (rtlhal->current_bandtype == BAND_ON_5G) + if (ptcb_desc->rts_rate < DESC_RATE6M) + ptcb_desc->rts_rate = DESC_RATE6M; + SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); + SET_TX_DESC_RTS_BW(pdesc, 0); + SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); + SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= + DESC_RATE54M) ? + (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : + (ptcb_desc->rts_use_shortgi ? 1 : 0))); + if (bw_40) { + if (ptcb_desc->packet_bw) { + SET_TX_DESC_DATA_BW(pdesc, 1); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + mac->cur_40_prime_sc); + } + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + } + SET_TX_DESC_LINIP(pdesc, 0); + SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb_len); + if (sta) { + u8 ampdu_density = sta->ht_cap.ampdu_density; + SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); + } + if (info->control.hw_key) { + struct ieee80211_key_conf *keyconf; + + keyconf = info->control.hw_key; + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x1); + break; + case WLAN_CIPHER_SUITE_CCMP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x3); + break; + default: + SET_TX_DESC_SEC_TYPE(pdesc, 0x0); + break; + + } + } + SET_TX_DESC_PKT_ID(pdesc, 0); + SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); + SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); + SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); + SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ? + 1 : 0); + SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); + + /* Set TxRate and RTSRate in TxDesc */ + /* This prevent Tx initial rate of new-coming packets */ + /* from being overwritten by retried packet rate.*/ + if (!ptcb_desc->use_driver_rate) { + SET_TX_DESC_RTS_RATE(pdesc, 0x08); + /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */ + } + if (ieee80211_is_data_qos(fc)) { + if (mac->rdg_en) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "Enable RDG function\n"); + SET_TX_DESC_RDG_ENABLE(pdesc, 1); + SET_TX_DESC_HTC(pdesc, 1); + } + } + } + + SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); + SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) buf_len); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + if (rtlpriv->dm.useramask) { + SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); + } else { + SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); + } + if (ieee80211_is_data_qos(fc)) + SET_TX_DESC_QOS(pdesc, 1); + + if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { + SET_TX_DESC_HWSEQ_EN(pdesc, 1); + SET_TX_DESC_PKT_ID(pdesc, 8); + } + SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); +} + +void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, + u8 *pdesc, bool firstseg, + bool lastseg, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 fw_queue = QSLT_BEACON; + dma_addr_t mapping = pci_map_single(rtlpci->pdev, + skb->data, skb->len, PCI_DMA_TODEVICE); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + __le16 fc = hdr->frame_control; + + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); + if (firstseg) + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + /* 5G have no CCK rate + * Caution: The macros below are multi-line expansions. + * The braces are needed no matter what checkpatch says + */ + if (rtlhal->current_bandtype == BAND_ON_5G) { + SET_TX_DESC_TX_RATE(pdesc, DESC_RATE6M); + } else { + SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M); + } + SET_TX_DESC_SEQ(pdesc, 0); + SET_TX_DESC_LINIP(pdesc, 0); + SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)skb->len); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + SET_TX_DESC_RATE_ID(pdesc, 7); + SET_TX_DESC_MACID(pdesc, 0); + SET_TX_DESC_PKT_SIZE(pdesc, (u16) (skb->len)); + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + SET_TX_DESC_OFFSET(pdesc, 0x20); + SET_TX_DESC_USE_RATE(pdesc, 1); + + if (!ieee80211_is_data_qos(fc) && ppsc->fwctrl_lps) { + SET_TX_DESC_HWSEQ_EN(pdesc, 1); + SET_TX_DESC_PKT_ID(pdesc, 8); + } + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C Tx Cmd Content", pdesc, TX_DESC_SIZE); + wmb(); + SET_TX_DESC_OWN(pdesc, 1); +} + +void rtl92de_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, + u8 desc_name, u8 *val) +{ + if (istx) { + switch (desc_name) { + case HW_DESC_OWN: + wmb(); + SET_TX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_TX_NEXTDESC_ADDR: + SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); + break; + default: + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_RXOWN: + wmb(); + SET_RX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_RXBUFF_ADDR: + SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val); + break; + case HW_DESC_RXPKT_LEN: + SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val); + break; + case HW_DESC_RXERO: + SET_RX_DESC_EOR(pdesc, 1); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); + break; + } + } +} + +u32 rtl92de_get_desc(u8 *p_desc, bool istx, u8 desc_name) +{ + u32 ret = 0; + + if (istx) { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_TX_DESC_OWN(p_desc); + break; + case HW_DESC_TXBUFF_ADDR: + ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc); + break; + default: + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); + break; + } + } else { + struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_RX_DESC_OWN(pdesc); + break; + case HW_DESC_RXPKT_LEN: + ret = GET_RX_DESC_PKT_LEN(pdesc); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); + break; + } + } + return ret; +} + +void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (hw_queue == BEACON_QUEUE) + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); + else + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, + BIT(0) << (hw_queue)); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h new file mode 100644 index 000000000000..fb5cf0634e8d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h @@ -0,0 +1,748 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92DE_TRX_H__ +#define __RTL92DE_TRX_H__ + +#define TX_DESC_SIZE 64 +#define TX_DESC_AGGR_SUBFRAME_SIZE 32 + +#define RX_DESC_SIZE 32 +#define RX_DRV_INFO_SIZE_UNIT 8 + +#define TX_DESC_NEXT_DESC_OFFSET 40 +#define USB_HWDESC_HEADER_LEN 32 +#define CRCLENGTH 4 + +/* 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, __mask) \ + ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ + BIT_LEN_MASK_32(__mask)) + +/* 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/write various fields in RX or TX descriptors */ + +#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val) +#define SET_TX_DESC_OFFSET(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val) +#define SET_TX_DESC_BMC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 24, 1, __val) +#define SET_TX_DESC_HTC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 25, 1, __val) +#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) +#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) +#define SET_TX_DESC_LINIP(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) +#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) +#define SET_TX_DESC_GF(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) +#define SET_TX_DESC_OWN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) + +#define GET_TX_DESC_PKT_SIZE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 0, 16) +#define GET_TX_DESC_OFFSET(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 16, 8) +#define GET_TX_DESC_BMC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 24, 1) +#define GET_TX_DESC_HTC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 25, 1) +#define GET_TX_DESC_LAST_SEG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 26, 1) +#define GET_TX_DESC_FIRST_SEG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 27, 1) +#define GET_TX_DESC_LINIP(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 28, 1) +#define GET_TX_DESC_NO_ACM(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 29, 1) +#define GET_TX_DESC_GF(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 30, 1) +#define GET_TX_DESC_OWN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 31, 1) + +#define SET_TX_DESC_MACID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 0, 5, __val) +#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 5, 1, __val) +#define SET_TX_DESC_BK(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 6, 1, __val) +#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 7, 1, __val) +#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 8, 5, __val) +#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 13, 1, __val) +#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 14, 1, __val) +#define SET_TX_DESC_PIFS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 15, 1, __val) +#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 16, 4, __val) +#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 20, 1, __val) +#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 21, 1, __val) +#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 22, 2, __val) +#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+4, 26, 8, __val) + +#define GET_TX_DESC_MACID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 0, 5) +#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 5, 1) +#define GET_TX_DESC_AGG_BREAK(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 6, 1) +#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 7, 1) +#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 8, 5) +#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 13, 1) +#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) +#define GET_TX_DESC_PIFS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) +#define GET_TX_DESC_RATE_ID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 16, 4) +#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 20, 1) +#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 21, 1) +#define GET_TX_DESC_SEC_TYPE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 22, 2) +#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 24, 8) + +#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 0, 6, __val) +#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 6, 6, __val) +#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 14, 2, __val) +#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 17, 1, __val) +#define SET_TX_DESC_RAW(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 18, 1, __val) +#define SET_TX_DESC_CCX(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 19, 1, __val) +#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 20, 3, __val) +#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 24, 1, __val) +#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 25, 1, __val) +#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 26, 2, __val) +#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 28, 2, __val) +#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+8, 30, 2, __val) + +#define GET_TX_DESC_RTS_RC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 0, 6) +#define GET_TX_DESC_DATA_RC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 6, 6) +#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 14, 2) +#define GET_TX_DESC_MORE_FRAG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 17, 1) +#define GET_TX_DESC_RAW(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 18, 1) +#define GET_TX_DESC_CCX(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 19, 1) +#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 20, 3) +#define GET_TX_DESC_ANTSEL_A(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 24, 1) +#define GET_TX_DESC_ANTSEL_B(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 25, 1) +#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 26, 2) +#define GET_TX_DESC_TX_ANTL(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 28, 2) +#define GET_TX_DESC_TX_ANT_HT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 30, 2) + +#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+12, 0, 8, __val) +#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+12, 8, 8, __val) +#define SET_TX_DESC_SEQ(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+12, 16, 12, __val) +#define SET_TX_DESC_PKT_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+12, 28, 4, __val) + +#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 0, 8) +#define GET_TX_DESC_TAIL_PAGE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 8, 8) +#define GET_TX_DESC_SEQ(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 16, 12) +#define GET_TX_DESC_PKT_ID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 28, 4) + +#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 0, 5, __val) +#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 5, 1, __val) +#define SET_TX_DESC_QOS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 6, 1, __val) +#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 7, 1, __val) +#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 8, 1, __val) +#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 9, 1, __val) +#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 10, 1, __val) +#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 11, 1, __val) +#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 12, 1, __val) +#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 13, 1, __val) +#define SET_TX_DESC_PORT_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 14, 1, __val) +#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 18, 1, __val) +#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 19, 1, __val) +#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 20, 2, __val) +#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 22, 2, __val) +#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 24, 1, __val) +#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 25, 1, __val) +#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 26, 1, __val) +#define SET_TX_DESC_RTS_BW(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 27, 1, __val) +#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 28, 2, __val) +#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+16, 30, 2, __val) + +#define GET_TX_DESC_RTS_RATE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 0, 5) +#define GET_TX_DESC_AP_DCFE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 5, 1) +#define GET_TX_DESC_QOS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 6, 1) +#define GET_TX_DESC_HWSEQ_EN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 7, 1) +#define GET_TX_DESC_USE_RATE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 8, 1) +#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 9, 1) +#define GET_TX_DESC_DISABLE_FB(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 10, 1) +#define GET_TX_DESC_CTS2SELF(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 11, 1) +#define GET_TX_DESC_RTS_ENABLE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 12, 1) +#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 13, 1) +#define GET_TX_DESC_PORT_ID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 14, 1) +#define GET_TX_DESC_WAIT_DCTS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 18, 1) +#define GET_TX_DESC_CTS2AP_EN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 19, 1) +#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 20, 2) +#define GET_TX_DESC_TX_STBC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 22, 2) +#define GET_TX_DESC_DATA_SHORT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 24, 1) +#define GET_TX_DESC_DATA_BW(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 25, 1) +#define GET_TX_DESC_RTS_SHORT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 26, 1) +#define GET_TX_DESC_RTS_BW(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 27, 1) +#define GET_TX_DESC_RTS_SC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 28, 2) +#define GET_TX_DESC_RTS_STBC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 30, 2) + +#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val) +#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val) +#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 8, 5, __val) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 13, 4, __val) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 17, 1, __val) +#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 18, 6, __val) +#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+20, 24, 8, __val) + +#define GET_TX_DESC_TX_RATE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 0, 6) +#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 6, 1) +#define GET_TX_DESC_CCX_TAG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 7, 1) +#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 8, 5) +#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 13, 4) +#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 17, 1) +#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 18, 6) +#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 24, 8) + +#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 0, 5, __val) +#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 5, 5, __val) +#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 10, 1, __val) +#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 11, 5, __val) +#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 16, 4, __val) +#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 20, 4, __val) +#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 24, 4, __val) +#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 28, 4, __val) + +#define GET_TX_DESC_TXAGC_A(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 0, 5) +#define GET_TX_DESC_TXAGC_B(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 5, 5) +#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 10, 1) +#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 11, 5) +#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 16, 4) +#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 20, 4) +#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 24, 4) +#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 28, 4) + +#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+28, 0, 16, __val) +#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+28, 16, 4, __val) +#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+28, 20, 4, __val) +#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+28, 24, 4, __val) +#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+28, 28, 4, __val) + +#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+28, 0, 16) +#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+28, 16, 4) +#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+28, 20, 4) +#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+28, 24, 4) +#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+28, 28, 4) + +#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+32, 0, 32, __val) +#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+36, 0, 32, __val) + +#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+32, 0, 32) +#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+36, 0, 32) + +#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+40, 0, 32, __val) +#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+44, 0, 32, __val) + +#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+40, 0, 32) +#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+44, 0, 32) + +#define GET_RX_DESC_PKT_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 0, 14) +#define GET_RX_DESC_CRC32(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 14, 1) +#define GET_RX_DESC_ICV(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 15, 1) +#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 16, 4) +#define GET_RX_DESC_SECURITY(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 20, 3) +#define GET_RX_DESC_QOS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 23, 1) +#define GET_RX_DESC_SHIFT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 24, 2) +#define GET_RX_DESC_PHYST(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 26, 1) +#define GET_RX_DESC_SWDEC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 27, 1) +#define GET_RX_DESC_LS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 28, 1) +#define GET_RX_DESC_FS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 29, 1) +#define GET_RX_DESC_EOR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 30, 1) +#define GET_RX_DESC_OWN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 31, 1) + +#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val) +#define SET_RX_DESC_EOR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) +#define SET_RX_DESC_OWN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) + +#define GET_RX_DESC_MACID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 0, 5) +#define GET_RX_DESC_TID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 5, 4) +#define GET_RX_DESC_HWRSVD(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 9, 5) +#define GET_RX_DESC_PAGGR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) +#define GET_RX_DESC_FAGGR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) +#define GET_RX_DESC_A1_FIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 16, 4) +#define GET_RX_DESC_A2_FIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 20, 4) +#define GET_RX_DESC_PAM(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 24, 1) +#define GET_RX_DESC_PWR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 25, 1) +#define GET_RX_DESC_MD(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 26, 1) +#define GET_RX_DESC_MF(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 27, 1) +#define GET_RX_DESC_TYPE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 28, 2) +#define GET_RX_DESC_MC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 30, 1) +#define GET_RX_DESC_BC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+4, 31, 1) +#define GET_RX_DESC_SEQ(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 0, 12) +#define GET_RX_DESC_FRAG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 12, 4) +#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 16, 14) +#define GET_RX_DESC_NEXT_IND(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 30, 1) +#define GET_RX_DESC_RSVD(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+8, 31, 1) + +#define GET_RX_DESC_RXMCS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 0, 6) +#define GET_RX_DESC_RXHT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 6, 1) +#define GET_RX_DESC_SPLCP(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 8, 1) +#define GET_RX_DESC_BW(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 9, 1) +#define GET_RX_DESC_HTC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 10, 1) +#define GET_RX_DESC_HWPC_ERR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 14, 1) +#define GET_RX_DESC_HWPC_IND(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 15, 1) +#define GET_RX_DESC_IV0(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+12, 16, 16) + +#define GET_RX_DESC_IV1(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+16, 0, 32) +#define GET_RX_DESC_TSFL(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+20, 0, 32) + +#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+24, 0, 32) +#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc+28, 0, 32) + +#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+24, 0, 32, __val) +#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val) + +#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ + memset((void *)__pdesc, 0, \ + min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) + +/* For 92D early mode */ +#define SET_EARLYMODE_PKTNUM(__paddr, __value) \ + SET_BITS_OFFSET_LE(__paddr, 0, 3, __value) +#define SET_EARLYMODE_LEN0(__paddr, __value) \ + SET_BITS_OFFSET_LE(__paddr, 4, 12, __value) +#define SET_EARLYMODE_LEN1(__paddr, __value) \ + SET_BITS_OFFSET_LE(__paddr, 16, 12, __value) +#define SET_EARLYMODE_LEN2_1(__paddr, __value) \ + SET_BITS_OFFSET_LE(__paddr, 28, 4, __value) +#define SET_EARLYMODE_LEN2_2(__paddr, __value) \ + SET_BITS_OFFSET_LE(__paddr+4, 0, 8, __value) +#define SET_EARLYMODE_LEN3(__paddr, __value) \ + SET_BITS_OFFSET_LE(__paddr+4, 8, 12, __value) +#define SET_EARLYMODE_LEN4(__paddr, __value) \ + SET_BITS_OFFSET_LE(__paddr+4, 20, 12, __value) + +struct rx_fwinfo_92d { + u8 gain_trsw[4]; + u8 pwdb_all; + u8 cfosho[4]; + u8 cfotail[4]; + char rxevm[2]; + char rxsnr[4]; + u8 pdsnr[2]; + u8 csi_current[2]; + u8 csi_target[2]; + u8 sigevm; + u8 max_ex_pwr; + u8 ex_intf_flag:1; + u8 sgi_en:1; + u8 rxsc:2; + u8 reserve:4; +} __packed; + +struct tx_desc_92d { + u32 pktsize:16; + u32 offset:8; + u32 bmc:1; + u32 htc:1; + u32 lastseg:1; + u32 firstseg:1; + u32 linip:1; + u32 noacm:1; + u32 gf:1; + u32 own:1; + + u32 macid:5; + u32 agg_en:1; + u32 bk:1; + u32 rdg_en:1; + u32 queuesel:5; + u32 rd_nav_ext:1; + u32 lsig_txop_en:1; + u32 pifs:1; + u32 rateid:4; + u32 nav_usehdr:1; + u32 en_descid:1; + u32 sectype:2; + u32 pktoffset:8; + + u32 rts_rc:6; + u32 data_rc:6; + u32 rsvd0:2; + u32 bar_retryht:2; + u32 rsvd1:1; + u32 morefrag:1; + u32 raw:1; + u32 ccx:1; + u32 ampdudensity:3; + u32 rsvd2:1; + u32 ant_sela:1; + u32 ant_selb:1; + u32 txant_cck:2; + u32 txant_l:2; + u32 txant_ht:2; + + u32 nextheadpage:8; + u32 tailpage:8; + u32 seq:12; + u32 pktid:4; + + u32 rtsrate:5; + u32 apdcfe:1; + u32 qos:1; + u32 hwseq_enable:1; + u32 userrate:1; + u32 dis_rtsfb:1; + u32 dis_datafb:1; + u32 cts2self:1; + u32 rts_en:1; + u32 hwrts_en:1; + u32 portid:1; + u32 rsvd3:3; + u32 waitdcts:1; + u32 cts2ap_en:1; + u32 txsc:2; + u32 stbc:2; + u32 txshort:1; + u32 txbw:1; + u32 rtsshort:1; + u32 rtsbw:1; + u32 rtssc:2; + u32 rtsstbc:2; + + u32 txrate:6; + u32 shortgi:1; + u32 ccxt:1; + u32 txrate_fb_lmt:5; + u32 rtsrate_fb_lmt:4; + u32 retrylmt_en:1; + u32 txretrylmt:6; + u32 usb_txaggnum:8; + + u32 txagca:5; + u32 txagcb:5; + u32 usemaxlen:1; + u32 maxaggnum:5; + u32 mcsg1maxlen:4; + u32 mcsg2maxlen:4; + u32 mcsg3maxlen:4; + u32 mcs7sgimaxlen:4; + + u32 txbuffersize:16; + u32 mcsg4maxlen:4; + u32 mcsg5maxlen:4; + u32 mcsg6maxlen:4; + u32 mcsg15sgimaxlen:4; + + u32 txbuffaddr; + u32 txbufferaddr64; + u32 nextdescaddress; + u32 nextdescaddress64; + + u32 reserve_pass_pcie_mm_limit[4]; +} __packed; + +struct rx_desc_92d { + u32 length:14; + u32 crc32:1; + u32 icverror:1; + u32 drv_infosize:4; + u32 security:3; + u32 qos:1; + u32 shift:2; + u32 phystatus:1; + u32 swdec:1; + u32 lastseg:1; + u32 firstseg:1; + u32 eor:1; + u32 own:1; + + u32 macid:5; + u32 tid:4; + u32 hwrsvd:5; + u32 paggr:1; + u32 faggr:1; + u32 a1_fit:4; + u32 a2_fit:4; + u32 pam:1; + u32 pwr:1; + u32 moredata:1; + u32 morefrag:1; + u32 type:2; + u32 mc:1; + u32 bc:1; + + u32 seq:12; + u32 frag:4; + u32 nextpktlen:14; + u32 nextind:1; + u32 rsvd:1; + + u32 rxmcs:6; + u32 rxht:1; + u32 amsdu:1; + u32 splcp:1; + u32 bandwidth:1; + u32 htc:1; + u32 tcpchk_rpt:1; + u32 ipcchk_rpt:1; + u32 tcpchk_valid:1; + u32 hwpcerr:1; + u32 hwpcind:1; + u32 iv0:16; + + u32 iv1; + + u32 tsfl; + + u32 bufferaddress; + u32 bufferaddress64; + +} __packed; + +void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc, + u8 *pbd_desc_tx, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, u8 hw_queue, + struct rtl_tcb_desc *ptcb_desc); +bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb); +void rtl92de_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, + u8 desc_name, u8 *val); +u32 rtl92de_get_desc(u8 *pdesc, bool istx, u8 desc_name); +void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); +void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool b_firstseg, bool b_lastseg, + struct sk_buff *skb); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/Makefile new file mode 100644 index 000000000000..0315eeda9b60 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/Makefile @@ -0,0 +1,16 @@ +rtl8192ee-objs := \ + dm.o \ + fw.o \ + hw.o \ + led.o \ + phy.o \ + pwrseq.o \ + rf.o \ + sw.o \ + table.o \ + trx.o \ + + +obj-$(CONFIG_RTL8192EE) += rtl8192ee.o + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h new file mode 100644 index 000000000000..60f5728b4e2d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/def.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92E_DEF_H__ +#define __RTL92E_DEF_H__ + +#define RX_DESC_NUM_92E 512 + +#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 +#define HAL_PRIME_CHNL_OFFSET_LOWER 1 +#define HAL_PRIME_CHNL_OFFSET_UPPER 2 + +#define RX_MPDU_QUEUE 0 + +#define IS_HT_RATE(_rate) \ + (_rate >= DESC92C_RATEMCS0) +#define IS_CCK_RATE(_rate) \ + (_rate >= DESC92C_RATE1M && _rate <= DESC92C_RATE11M) +#define IS_OFDM_RATE(_rate) \ + (_rate >= DESC92C_RATE6M && _rate <= DESC92C_RATE54M) + +enum version_8192e { + VERSION_TEST_CHIP_2T2R_8192E = 0x0024, + VERSION_NORMAL_CHIP_2T2R_8192E = 0x102C, + VERSION_UNKNOWN = 0xFF, +}; + +enum rx_packet_type { + NORMAL_RX, + TX_REPORT1, + TX_REPORT2, + HIS_REPORT, + C2H_PACKET, +}; + +enum rtl_desc_qsel { + QSLT_BK = 0x2, + QSLT_BE = 0x0, + QSLT_VI = 0x5, + QSLT_VO = 0x7, + QSLT_BEACON = 0x10, + QSLT_HIGH = 0x11, + QSLT_MGNT = 0x12, + QSLT_CMD = 0x13, +}; + +enum rtl_desc92c_rate { + DESC92C_RATE1M = 0x00, + DESC92C_RATE2M = 0x01, + DESC92C_RATE5_5M = 0x02, + DESC92C_RATE11M = 0x03, + + DESC92C_RATE6M = 0x04, + DESC92C_RATE9M = 0x05, + DESC92C_RATE12M = 0x06, + DESC92C_RATE18M = 0x07, + DESC92C_RATE24M = 0x08, + DESC92C_RATE36M = 0x09, + DESC92C_RATE48M = 0x0a, + DESC92C_RATE54M = 0x0b, + + DESC92C_RATEMCS0 = 0x0c, + DESC92C_RATEMCS1 = 0x0d, + DESC92C_RATEMCS2 = 0x0e, + DESC92C_RATEMCS3 = 0x0f, + DESC92C_RATEMCS4 = 0x10, + DESC92C_RATEMCS5 = 0x11, + DESC92C_RATEMCS6 = 0x12, + DESC92C_RATEMCS7 = 0x13, + DESC92C_RATEMCS8 = 0x14, + DESC92C_RATEMCS9 = 0x15, + DESC92C_RATEMCS10 = 0x16, + DESC92C_RATEMCS11 = 0x17, + DESC92C_RATEMCS12 = 0x18, + DESC92C_RATEMCS13 = 0x19, + DESC92C_RATEMCS14 = 0x1a, + DESC92C_RATEMCS15 = 0x1b, +}; +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c new file mode 100644 index 000000000000..459f3d0efa2f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.c @@ -0,0 +1,1236 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../base.h" +#include "../pci.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "trx.h" + +static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { + 0x7f8001fe, /* 0, +6.0dB */ + 0x788001e2, /* 1, +5.5dB */ + 0x71c001c7, /* 2, +5.0dB */ + 0x6b8001ae, /* 3, +4.5dB */ + 0x65400195, /* 4, +4.0dB */ + 0x5fc0017f, /* 5, +3.5dB */ + 0x5a400169, /* 6, +3.0dB */ + 0x55400155, /* 7, +2.5dB */ + 0x50800142, /* 8, +2.0dB */ + 0x4c000130, /* 9, +1.5dB */ + 0x47c0011f, /* 10, +1.0dB */ + 0x43c0010f, /* 11, +0.5dB */ + 0x40000100, /* 12, +0dB */ + 0x3c8000f2, /* 13, -0.5dB */ + 0x390000e4, /* 14, -1.0dB */ + 0x35c000d7, /* 15, -1.5dB */ + 0x32c000cb, /* 16, -2.0dB */ + 0x300000c0, /* 17, -2.5dB */ + 0x2d4000b5, /* 18, -3.0dB */ + 0x2ac000ab, /* 19, -3.5dB */ + 0x288000a2, /* 20, -4.0dB */ + 0x26000098, /* 21, -4.5dB */ + 0x24000090, /* 22, -5.0dB */ + 0x22000088, /* 23, -5.5dB */ + 0x20000080, /* 24, -6.0dB */ + 0x1e400079, /* 25, -6.5dB */ + 0x1c800072, /* 26, -7.0dB */ + 0x1b00006c, /* 27. -7.5dB */ + 0x19800066, /* 28, -8.0dB */ + 0x18000060, /* 29, -8.5dB */ + 0x16c0005b, /* 30, -9.0dB */ + 0x15800056, /* 31, -9.5dB */ + 0x14400051, /* 32, -10.0dB */ + 0x1300004c, /* 33, -10.5dB */ + 0x12000048, /* 34, -11.0dB */ + 0x11000044, /* 35, -11.5dB */ + 0x10000040, /* 36, -12.0dB */ + 0x0f00003c, /* 37, -12.5dB */ + 0x0e400039, /* 38, -13.0dB */ + 0x0d800036, /* 39, -13.5dB */ + 0x0cc00033, /* 40, -14.0dB */ + 0x0c000030, /* 41, -14.5dB */ + 0x0b40002d, /* 42, -15.0dB */ +}; + +static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ + {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ + {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ + {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ + {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ + {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ + {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ + {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ + {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ + {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ + {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */ + {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */ + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */ + {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */ + {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */ + {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */ + {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */ + {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */ + {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */ + {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */ + {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */ + {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */ + {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */ +}; + +static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */ + {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */ + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */ + {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */ + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */ + {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */ + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */ + {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */ + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */ + {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */ + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */ + {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */ + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */ + {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */ + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */ + {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */ + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ + {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */ + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */ + {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */ + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */ + {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */ + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */ + {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */ + {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */ + {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */ + {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */ + {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */ + {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */ + {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */ + {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */ + {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */ + {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */ +}; + +static void rtl92ee_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) +{ + u32 ret_value; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt; + + rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); + rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); + + ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD); + falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff); + falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD); + falsealm_cnt->cnt_ofdm_cca = (ret_value & 0xffff); + falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD); + falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); + falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD); + falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); + + falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_fast_fsync_fail + + falsealm_cnt->cnt_sb_search_fail; + + ret_value = rtl_get_bbreg(hw, DM_REG_SC_CNT_11N, MASKDWORD); + falsealm_cnt->cnt_bw_lsc = (ret_value & 0xffff); + falsealm_cnt->cnt_bw_usc = ((ret_value & 0xffff0000) >> 16); + + rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1); + rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1); + + ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_LSB_11N, MASKBYTE0); + falsealm_cnt->cnt_cck_fail = ret_value; + + ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3); + falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; + + ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD); + falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) | + ((ret_value & 0xFF00) >> 8); + + falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail + + falsealm_cnt->cnt_sb_search_fail + + falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_cck_fail; + + falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca + + falsealm_cnt->cnt_cck_cca; + + /*reset false alarm counter registers*/ + rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1); + rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0); + rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1); + rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0); + /*update ofdm counter*/ + rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0); + rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0); + /*reset CCK CCA counter*/ + rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0); + rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2); + /*reset CCK FA counter*/ + rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0); + rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", + falsealm_cnt->cnt_parity_fail, + falsealm_cnt->cnt_rate_illegal, + falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", + falsealm_cnt->cnt_ofdm_fail, + falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all); +} + +static void rtl92ee_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_dig = &rtlpriv->dm_digtable; + u8 cur_cck_cca_thresh; + + if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) { + if (dm_dig->rssi_val_min > 25) { + cur_cck_cca_thresh = 0xcd; + } else if ((dm_dig->rssi_val_min <= 25) && + (dm_dig->rssi_val_min > 10)) { + cur_cck_cca_thresh = 0x83; + } else { + if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) + cur_cck_cca_thresh = 0x83; + else + cur_cck_cca_thresh = 0x40; + } + } else { + if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) + cur_cck_cca_thresh = 0x83; + else + cur_cck_cca_thresh = 0x40; + } + rtl92ee_dm_write_cck_cca_thres(hw, cur_cck_cca_thresh); +} + +static void rtl92ee_dm_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct dig_t *dm_dig = &rtlpriv->dm_digtable; + u8 dig_min_0, dig_maxofmin; + bool bfirstconnect , bfirstdisconnect; + u8 dm_dig_max, dm_dig_min; + u8 current_igi = dm_dig->cur_igvalue; + u8 offset; + + /* AP,BT */ + if (mac->act_scanning) + return; + + dig_min_0 = dm_dig->dig_min_0; + bfirstconnect = (mac->link_state >= MAC80211_LINKED) && + !dm_dig->media_connect_0; + bfirstdisconnect = (mac->link_state < MAC80211_LINKED) && + dm_dig->media_connect_0; + + dm_dig_max = 0x5a; + dm_dig_min = DM_DIG_MIN; + dig_maxofmin = DM_DIG_MAX_AP; + + if (mac->link_state >= MAC80211_LINKED) { + if ((dm_dig->rssi_val_min + 10) > dm_dig_max) + dm_dig->rx_gain_max = dm_dig_max; + else if ((dm_dig->rssi_val_min + 10) < dm_dig_min) + dm_dig->rx_gain_max = dm_dig_min; + else + dm_dig->rx_gain_max = dm_dig->rssi_val_min + 10; + + if (rtlpriv->dm.one_entry_only) { + offset = 0; + if (dm_dig->rssi_val_min - offset < dm_dig_min) + dig_min_0 = dm_dig_min; + else if (dm_dig->rssi_val_min - offset > + dig_maxofmin) + dig_min_0 = dig_maxofmin; + else + dig_min_0 = dm_dig->rssi_val_min - offset; + } else { + dig_min_0 = dm_dig_min; + } + + } else { + dm_dig->rx_gain_max = dm_dig_max; + dig_min_0 = dm_dig_min; + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n"); + } + + if (rtlpriv->falsealm_cnt.cnt_all > 10000) { + if (dm_dig->large_fa_hit != 3) + dm_dig->large_fa_hit++; + if (dm_dig->forbidden_igi < current_igi) { + dm_dig->forbidden_igi = current_igi; + dm_dig->large_fa_hit = 1; + } + + if (dm_dig->large_fa_hit >= 3) { + if (dm_dig->forbidden_igi + 1 > dm_dig->rx_gain_max) + dm_dig->rx_gain_min = + dm_dig->rx_gain_max; + else + dm_dig->rx_gain_min = + dm_dig->forbidden_igi + 1; + dm_dig->recover_cnt = 3600; + } + } else { + if (dm_dig->recover_cnt != 0) { + dm_dig->recover_cnt--; + } else { + if (dm_dig->large_fa_hit < 3) { + if ((dm_dig->forbidden_igi - 1) < + dig_min_0) { + dm_dig->forbidden_igi = dig_min_0; + dm_dig->rx_gain_min = + dig_min_0; + } else { + dm_dig->forbidden_igi--; + dm_dig->rx_gain_min = + dm_dig->forbidden_igi + 1; + } + } else { + dm_dig->large_fa_hit = 0; + } + } + } + + if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 5) + dm_dig->rx_gain_min = dm_dig_min; + + if (dm_dig->rx_gain_min > dm_dig->rx_gain_max) + dm_dig->rx_gain_min = dm_dig->rx_gain_max; + + if (mac->link_state >= MAC80211_LINKED) { + if (bfirstconnect) { + if (dm_dig->rssi_val_min <= dig_maxofmin) + current_igi = dm_dig->rssi_val_min; + else + current_igi = dig_maxofmin; + + dm_dig->large_fa_hit = 0; + } else { + if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2) + current_igi += 4; + else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1) + current_igi += 2; + else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) + current_igi -= 2; + + if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 5 && + rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1) + current_igi = dm_dig->rx_gain_min; + } + } else { + if (bfirstdisconnect) { + current_igi = dm_dig->rx_gain_min; + } else { + if (rtlpriv->falsealm_cnt.cnt_all > 10000) + current_igi += 4; + else if (rtlpriv->falsealm_cnt.cnt_all > 8000) + current_igi += 2; + else if (rtlpriv->falsealm_cnt.cnt_all < 500) + current_igi -= 2; + } + } + + if (current_igi > dm_dig->rx_gain_max) + current_igi = dm_dig->rx_gain_max; + if (current_igi < dm_dig->rx_gain_min) + current_igi = dm_dig->rx_gain_min; + + rtl92ee_dm_write_dig(hw , current_igi); + dm_dig->media_connect_0 = ((mac->link_state >= MAC80211_LINKED) ? + true : false); + dm_dig->dig_min_0 = dig_min_0; +} + +void rtl92ee_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 cur_thres) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_dig = &rtlpriv->dm_digtable; + + if (dm_dig->cur_cck_cca_thres != cur_thres) + rtl_write_byte(rtlpriv, DM_REG_CCK_CCA_11N, cur_thres); + + dm_dig->pre_cck_cca_thres = dm_dig->cur_cck_cca_thres; + dm_dig->cur_cck_cca_thres = cur_thres; +} + +void rtl92ee_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_dig = &rtlpriv->dm_digtable; + + if (dm_dig->stop_dig) + return; + + if (dm_dig->cur_igvalue != current_igi) { + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi); + if (rtlpriv->phy.rf_type != RF_1T1R) + rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, current_igi); + } + dm_dig->pre_igvalue = dm_dig->cur_igvalue; + dm_dig->cur_igvalue = current_igi; +} + +static void rtl92ee_rssi_dump_to_register(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, RA_RSSIDUMP, + rtlpriv->stats.rx_rssi_percentage[0]); + rtl_write_byte(rtlpriv, RB_RSSIDUMP, + rtlpriv->stats.rx_rssi_percentage[1]); + /*It seems the following values are not initialized. + *According to Windows code, + *these value will only be valid with JAGUAR chips + */ + /* Rx EVM */ + rtl_write_byte(rtlpriv, RS1_RXEVMDUMP, rtlpriv->stats.rx_evm_dbm[0]); + rtl_write_byte(rtlpriv, RS2_RXEVMDUMP, rtlpriv->stats.rx_evm_dbm[1]); + /* Rx SNR */ + rtl_write_byte(rtlpriv, RA_RXSNRDUMP, + (u8)(rtlpriv->stats.rx_snr_db[0])); + rtl_write_byte(rtlpriv, RB_RXSNRDUMP, + (u8)(rtlpriv->stats.rx_snr_db[1])); + /* Rx Cfo_Short */ + rtl_write_word(rtlpriv, RA_CFOSHORTDUMP, + rtlpriv->stats.rx_cfo_short[0]); + rtl_write_word(rtlpriv, RB_CFOSHORTDUMP, + rtlpriv->stats.rx_cfo_short[1]); + /* Rx Cfo_Tail */ + rtl_write_word(rtlpriv, RA_CFOLONGDUMP, rtlpriv->stats.rx_cfo_tail[0]); + rtl_write_word(rtlpriv, RB_CFOLONGDUMP, rtlpriv->stats.rx_cfo_tail[1]); +} + +static void rtl92ee_dm_find_minimum_rssi(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable; + struct rtl_mac *mac = rtl_mac(rtlpriv); + + /* Determine the minimum RSSI */ + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { + rtl_dm_dig->min_undec_pwdb_for_dm = 0; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "Not connected to any\n"); + } + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_dm_dig->min_undec_pwdb_for_dm = + rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "AP Client PWDB = 0x%lx\n", + rtlpriv->dm.entry_min_undec_sm_pwdb); + } else { + rtl_dm_dig->min_undec_pwdb_for_dm = + rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "STA Default Port PWDB = 0x%x\n", + rtl_dm_dig->min_undec_pwdb_for_dm); + } + } else { + rtl_dm_dig->min_undec_pwdb_for_dm = + rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "AP Ext Port or disconnet PWDB = 0x%x\n", + rtl_dm_dig->min_undec_pwdb_for_dm); + } + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "MinUndecoratedPWDBForDM =%d\n", + rtl_dm_dig->min_undec_pwdb_for_dm); +} + +static void rtl92ee_dm_check_rssi_monitor(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_dig = &rtlpriv->dm_digtable; + struct rtl_mac *mac = rtl_mac(rtlpriv); + struct rtl_dm *dm = rtl_dm(rtlpriv); + struct rtl_sta_info *drv_priv; + u8 h2c[4] = { 0 }; + long max = 0, min = 0xff; + u8 i = 0; + + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + /* AP & ADHOC & MESH */ + spin_lock_bh(&rtlpriv->locks.entry_list_lock); + list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { + struct rssi_sta *stat = &drv_priv->rssi_stat; + + if (stat->undec_sm_pwdb < min) + min = stat->undec_sm_pwdb; + if (stat->undec_sm_pwdb > max) + max = stat->undec_sm_pwdb; + + h2c[3] = 0; + h2c[2] = (u8)(dm->undec_sm_pwdb & 0xFF); + h2c[1] = 0x20; + h2c[0] = ++i; + rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSSI_REPORT, 4, h2c); + } + spin_unlock_bh(&rtlpriv->locks.entry_list_lock); + + /* If associated entry is found */ + if (max != 0) { + dm->entry_max_undec_sm_pwdb = max; + RTPRINT(rtlpriv, FDM, DM_PWDB, + "EntryMaxPWDB = 0x%lx(%ld)\n", max, max); + } else { + dm->entry_max_undec_sm_pwdb = 0; + } + /* If associated entry is found */ + if (min != 0xff) { + dm->entry_min_undec_sm_pwdb = min; + RTPRINT(rtlpriv, FDM, DM_PWDB, + "EntryMinPWDB = 0x%lx(%ld)\n", min, min); + } else { + dm->entry_min_undec_sm_pwdb = 0; + } + } + + /* Indicate Rx signal strength to FW. */ + if (dm->useramask) { + h2c[3] = 0; + h2c[2] = (u8)(dm->undec_sm_pwdb & 0xFF); + h2c[1] = 0x20; + h2c[0] = 0; + rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSSI_REPORT, 4, h2c); + } else { + rtl_write_byte(rtlpriv, 0x4fe, dm->undec_sm_pwdb); + } + rtl92ee_rssi_dump_to_register(hw); + rtl92ee_dm_find_minimum_rssi(hw); + dm_dig->rssi_val_min = rtlpriv->dm_digtable.min_undec_pwdb_for_dm; +} + +static void rtl92ee_dm_init_primary_cca_check(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct dynamic_primary_cca *primarycca = &rtlpriv->primarycca; + + rtlhal->rts_en = 0; + primarycca->dup_rts_flag = 0; + primarycca->intf_flag = 0; + primarycca->intf_type = 0; + primarycca->monitor_flag = 0; + primarycca->ch_offset = 0; + primarycca->mf_state = 0; +} + +static bool rtl92ee_dm_is_edca_turbo_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->mac80211.mode == WIRELESS_MODE_B) + return true; + + return false; +} + +void rtl92ee_dm_init_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.current_turbo_edca = false; + rtlpriv->dm.is_cur_rdlstate = false; + rtlpriv->dm.is_any_nonbepkts = false; +} + +static void rtl92ee_dm_check_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + static u64 last_txok_cnt; + static u64 last_rxok_cnt; + u64 cur_txok_cnt = 0; + u64 cur_rxok_cnt = 0; + u32 edca_be_ul = 0x5ea42b; + u32 edca_be_dl = 0x5ea42b; /*not sure*/ + u32 edca_be = 0x5ea42b; + bool is_cur_rdlstate; + bool b_edca_turbo_on = false; + + if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100) + rtlpriv->dm.is_any_nonbepkts = true; + rtlpriv->dm.dbginfo.num_non_be_pkt = 0; + + cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; + cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; + + /*b_bias_on_rx = false;*/ + b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) && + (!rtlpriv->dm.disable_framebursting)) ? + true : false; + + if (rtl92ee_dm_is_edca_turbo_disable(hw)) + goto check_exit; + + if (b_edca_turbo_on) { + is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ? + true : false; + + edca_be = is_cur_rdlstate ? edca_be_dl : edca_be_ul; + rtl_write_dword(rtlpriv , REG_EDCA_BE_PARAM , edca_be); + rtlpriv->dm.is_cur_rdlstate = is_cur_rdlstate; + rtlpriv->dm.current_turbo_edca = true; + } else { + if (rtlpriv->dm.current_turbo_edca) { + u8 tmp = AC0_BE; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + (u8 *)(&tmp)); + } + rtlpriv->dm.current_turbo_edca = false; + } + +check_exit: + rtlpriv->dm.is_any_nonbepkts = false; + last_txok_cnt = rtlpriv->stats.txbytesunicast; + last_rxok_cnt = rtlpriv->stats.rxbytesunicast; +} + +static void rtl92ee_dm_dynamic_edcca(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 reg_c50 , reg_c58; + bool fw_current_in_ps_mode = false; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_in_ps_mode)); + if (fw_current_in_ps_mode) + return; + + reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); + reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); + + if (reg_c50 > 0x28 && reg_c58 > 0x28) { + if (!rtlpriv->rtlhal.pre_edcca_enable) { + rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03); + rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00); + rtlpriv->rtlhal.pre_edcca_enable = true; + } + } else if (reg_c50 < 0x25 && reg_c58 < 0x25) { + if (rtlpriv->rtlhal.pre_edcca_enable) { + rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f); + rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f); + rtlpriv->rtlhal.pre_edcca_enable = false; + } + } +} + +static void rtl92ee_dm_adaptivity(struct ieee80211_hw *hw) +{ + rtl92ee_dm_dynamic_edcca(hw); +} + +static void rtl92ee_dm_write_dynamic_cca(struct ieee80211_hw *hw, + u8 cur_mf_state) +{ + struct dynamic_primary_cca *primarycca = &rtl_priv(hw)->primarycca; + + if (primarycca->mf_state != cur_mf_state) + rtl_set_bbreg(hw, DM_REG_L1SBD_PD_CH_11N, BIT(8) | BIT(7), + cur_mf_state); + + primarycca->mf_state = cur_mf_state; +} + +static void rtl92ee_dm_dynamic_primary_cca_ckeck(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt; + struct dynamic_primary_cca *primarycca = &rtlpriv->primarycca; + bool is40mhz = false; + u64 ofdm_cca, ofdm_fa, bw_usc_cnt, bw_lsc_cnt; + u8 sec_ch_offset; + u8 cur_mf_state; + static u8 count_down = MONITOR_TIME; + + ofdm_cca = falsealm_cnt->cnt_ofdm_cca; + ofdm_fa = falsealm_cnt->cnt_ofdm_fail; + bw_usc_cnt = falsealm_cnt->cnt_bw_usc; + bw_lsc_cnt = falsealm_cnt->cnt_bw_lsc; + is40mhz = rtlpriv->mac80211.bw_40; + sec_ch_offset = rtlpriv->mac80211.cur_40_prime_sc; + /* NIC: 2: sec is below, 1: sec is above */ + + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) { + cur_mf_state = MF_USC_LSC; + rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); + return; + } + + if (rtlpriv->mac80211.link_state < MAC80211_LINKED) + return; + + if (is40mhz) + return; + + if (primarycca->pricca_flag == 0) { + /* Primary channel is above + * NOTE: duplicate CTS can remove this condition + */ + if (sec_ch_offset == 2) { + if ((ofdm_cca > OFDMCCA_TH) && + (bw_lsc_cnt > (bw_usc_cnt + BW_IND_BIAS)) && + (ofdm_fa > (ofdm_cca >> 1))) { + primarycca->intf_type = 1; + primarycca->intf_flag = 1; + cur_mf_state = MF_USC; + rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); + primarycca->pricca_flag = 1; + } else if ((ofdm_cca > OFDMCCA_TH) && + (bw_lsc_cnt > (bw_usc_cnt + BW_IND_BIAS)) && + (ofdm_fa < (ofdm_cca >> 1))) { + primarycca->intf_type = 2; + primarycca->intf_flag = 1; + cur_mf_state = MF_USC; + rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); + primarycca->pricca_flag = 1; + primarycca->dup_rts_flag = 1; + rtlpriv->rtlhal.rts_en = 1; + } else { + primarycca->intf_type = 0; + primarycca->intf_flag = 0; + cur_mf_state = MF_USC_LSC; + rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); + rtlpriv->rtlhal.rts_en = 0; + primarycca->dup_rts_flag = 0; + } + } else if (sec_ch_offset == 1) { + if ((ofdm_cca > OFDMCCA_TH) && + (bw_usc_cnt > (bw_lsc_cnt + BW_IND_BIAS)) && + (ofdm_fa > (ofdm_cca >> 1))) { + primarycca->intf_type = 1; + primarycca->intf_flag = 1; + cur_mf_state = MF_LSC; + rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); + primarycca->pricca_flag = 1; + } else if ((ofdm_cca > OFDMCCA_TH) && + (bw_usc_cnt > (bw_lsc_cnt + BW_IND_BIAS)) && + (ofdm_fa < (ofdm_cca >> 1))) { + primarycca->intf_type = 2; + primarycca->intf_flag = 1; + cur_mf_state = MF_LSC; + rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); + primarycca->pricca_flag = 1; + primarycca->dup_rts_flag = 1; + rtlpriv->rtlhal.rts_en = 1; + } else { + primarycca->intf_type = 0; + primarycca->intf_flag = 0; + cur_mf_state = MF_USC_LSC; + rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); + rtlpriv->rtlhal.rts_en = 0; + primarycca->dup_rts_flag = 0; + } + } + } else {/* PrimaryCCA->PriCCA_flag==1 */ + count_down--; + if (count_down == 0) { + count_down = MONITOR_TIME; + primarycca->pricca_flag = 0; + cur_mf_state = MF_USC_LSC; + /* default */ + rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); + rtlpriv->rtlhal.rts_en = 0; + primarycca->dup_rts_flag = 0; + primarycca->intf_type = 0; + primarycca->intf_flag = 0; + } + } +} + +static void rtl92ee_dm_dynamic_atc_switch(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + u8 crystal_cap; + u32 packet_count; + int cfo_khz_a , cfo_khz_b , cfo_ave = 0, adjust_xtal = 0; + int cfo_ave_diff; + + if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { + if (rtldm->atc_status == ATC_STATUS_OFF) { + rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), + ATC_STATUS_ON); + rtldm->atc_status = ATC_STATUS_ON; + } + /* Disable CFO tracking for BT */ + if (rtlpriv->cfg->ops->get_btc_status()) { + if (!rtlpriv->btcoexist.btc_ops-> + btc_is_bt_disabled(rtlpriv)) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, + "odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n"); + return; + } + } + /* Reset Crystal Cap */ + if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) { + rtldm->crystal_cap = rtlpriv->efuse.crystalcap; + crystal_cap = rtldm->crystal_cap & 0x3f; + rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, + (crystal_cap | (crystal_cap << 6))); + } + } else { + cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280; + cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280; + packet_count = rtldm->packet_count; + + if (packet_count == rtldm->packet_count_pre) + return; + + rtldm->packet_count_pre = packet_count; + + if (rtlpriv->phy.rf_type == RF_1T1R) + cfo_ave = cfo_khz_a; + else + cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1; + + cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ? + (rtldm->cfo_ave_pre - cfo_ave) : + (cfo_ave - rtldm->cfo_ave_pre); + + if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) { + rtldm->large_cfo_hit = 1; + return; + } + rtldm->large_cfo_hit = 0; + + rtldm->cfo_ave_pre = cfo_ave; + + if (cfo_ave >= -rtldm->cfo_threshold && + cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) { + if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) { + rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10; + rtldm->is_freeze = 1; + } else { + rtldm->cfo_threshold = CFO_THRESHOLD_XTAL; + } + } + + if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f) + adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1; + else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) && + rtlpriv->dm.crystal_cap > 0) + adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1; + + if (adjust_xtal != 0) { + rtldm->is_freeze = 0; + rtldm->crystal_cap += adjust_xtal; + + if (rtldm->crystal_cap > 0x3f) + rtldm->crystal_cap = 0x3f; + else if (rtldm->crystal_cap < 0) + rtldm->crystal_cap = 0; + + crystal_cap = rtldm->crystal_cap & 0x3f; + rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, + (crystal_cap | (crystal_cap << 6))); + } + + if (cfo_ave < CFO_THRESHOLD_ATC && + cfo_ave > -CFO_THRESHOLD_ATC) { + if (rtldm->atc_status == ATC_STATUS_ON) { + rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), + ATC_STATUS_OFF); + rtldm->atc_status = ATC_STATUS_OFF; + } + } else { + if (rtldm->atc_status == ATC_STATUS_OFF) { + rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), + ATC_STATUS_ON); + rtldm->atc_status = ATC_STATUS_ON; + } + } + } +} + +static void rtl92ee_dm_init_txpower_tracking(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *dm = rtl_dm(rtlpriv); + u8 path; + + dm->txpower_tracking = true; + dm->default_ofdm_index = 30; + dm->default_cck_index = 20; + + dm->swing_idx_cck_base = dm->default_cck_index; + dm->cck_index = dm->default_cck_index; + + for (path = RF90_PATH_A; path < MAX_RF_PATH; path++) { + dm->swing_idx_ofdm_base[path] = dm->default_ofdm_index; + dm->ofdm_index[path] = dm->default_ofdm_index; + dm->delta_power_index[path] = 0; + dm->delta_power_index_last[path] = 0; + dm->power_index_offset[path] = 0; + } +} + +void rtl92ee_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rate_adaptive *p_ra = &rtlpriv->ra; + + p_ra->ratr_state = DM_RATR_STA_INIT; + p_ra->pre_ratr_state = DM_RATR_STA_INIT; + + if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) + rtlpriv->dm.useramask = true; + else + rtlpriv->dm.useramask = false; + + p_ra->ldpc_thres = 35; + p_ra->use_ldpc = false; + p_ra->high_rssi_thresh_for_ra = 50; + p_ra->low_rssi_thresh_for_ra40m = 20; +} + +static bool _rtl92ee_dm_ra_state_check(struct ieee80211_hw *hw, + s32 rssi, u8 *ratr_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rate_adaptive *p_ra = &rtlpriv->ra; + const u8 go_up_gap = 5; + u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra; + u32 low_rssithresh_for_ra = p_ra->low_rssi_thresh_for_ra40m; + u8 state; + + /* Threshold Adjustment: + * when RSSI state trends to go up one or two levels, + * make sure RSSI is high enough. + * Here GoUpGap is added to solve + * the boundary's level alternation issue. + */ + switch (*ratr_state) { + case DM_RATR_STA_INIT: + case DM_RATR_STA_HIGH: + break; + case DM_RATR_STA_MIDDLE: + high_rssithresh_for_ra += go_up_gap; + break; + case DM_RATR_STA_LOW: + high_rssithresh_for_ra += go_up_gap; + low_rssithresh_for_ra += go_up_gap; + break; + default: + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "wrong rssi level setting %d !", *ratr_state); + break; + } + + /* Decide RATRState by RSSI. */ + if (rssi > high_rssithresh_for_ra) + state = DM_RATR_STA_HIGH; + else if (rssi > low_rssithresh_for_ra) + state = DM_RATR_STA_MIDDLE; + else + state = DM_RATR_STA_LOW; + + if (*ratr_state != state) { + *ratr_state = state; + return true; + } + + return false; +} + +static void rtl92ee_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rate_adaptive *p_ra = &rtlpriv->ra; + struct ieee80211_sta *sta = NULL; + + if (is_hal_stop(rtlhal)) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "driver is going to unload\n"); + return; + } + + if (!rtlpriv->dm.useramask) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "driver does not control rate adaptive mask\n"); + return; + } + + if (mac->link_state == MAC80211_LINKED && + mac->opmode == NL80211_IFTYPE_STATION) { + if (rtlpriv->dm.undec_sm_pwdb < p_ra->ldpc_thres) { + p_ra->use_ldpc = true; + p_ra->lower_rts_rate = true; + } else if (rtlpriv->dm.undec_sm_pwdb > + (p_ra->ldpc_thres - 5)) { + p_ra->use_ldpc = false; + p_ra->lower_rts_rate = false; + } + if (_rtl92ee_dm_ra_state_check(hw, rtlpriv->dm.undec_sm_pwdb, + &p_ra->ratr_state)) { + rcu_read_lock(); + sta = rtl_find_sta(hw, mac->bssid); + if (sta) + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, + p_ra->ratr_state); + rcu_read_unlock(); + + p_ra->pre_ratr_state = p_ra->ratr_state; + } + } +} + +static void rtl92ee_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap; + + rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11)); + rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL; +} + +void rtl92ee_dm_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 cur_igvalue = rtl_get_bbreg(hw, DM_REG_IGI_A_11N, DM_BIT_IGI_11N); + + rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; + + rtl_dm_diginit(hw, cur_igvalue); + rtl92ee_dm_init_rate_adaptive_mask(hw); + rtl92ee_dm_init_primary_cca_check(hw); + rtl92ee_dm_init_edca_turbo(hw); + rtl92ee_dm_init_txpower_tracking(hw); + rtl92ee_dm_init_dynamic_atc_switch(hw); +} + +static void rtl92ee_dm_common_info_self_update(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_sta_info *drv_priv; + u8 cnt = 0; + + rtlpriv->dm.one_entry_only = false; + + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION && + rtlpriv->mac80211.link_state >= MAC80211_LINKED) { + rtlpriv->dm.one_entry_only = true; + return; + } + + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || + rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC || + rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) { + spin_lock_bh(&rtlpriv->locks.entry_list_lock); + list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { + cnt++; + } + spin_unlock_bh(&rtlpriv->locks.entry_list_lock); + + if (cnt == 1) + rtlpriv->dm.one_entry_only = true; + } +} + +void rtl92ee_dm_dynamic_arfb_select(struct ieee80211_hw *hw, + u8 rate, bool collision_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rate >= DESC92C_RATEMCS8 && rate <= DESC92C_RATEMCS12) { + if (collision_state == 1) { + if (rate == DESC92C_RATEMCS12) { + rtl_write_dword(rtlpriv, REG_DARFRC, 0x0); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x07060501); + } else if (rate == DESC92C_RATEMCS11) { + rtl_write_dword(rtlpriv, REG_DARFRC, 0x0); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x07070605); + } else if (rate == DESC92C_RATEMCS10) { + rtl_write_dword(rtlpriv, REG_DARFRC, 0x0); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x08080706); + } else if (rate == DESC92C_RATEMCS9) { + rtl_write_dword(rtlpriv, REG_DARFRC, 0x0); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x08080707); + } else { + rtl_write_dword(rtlpriv, REG_DARFRC, 0x0); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x09090808); + } + } else { /* collision_state == 0 */ + if (rate == DESC92C_RATEMCS12) { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x05010000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x09080706); + } else if (rate == DESC92C_RATEMCS11) { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x06050000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x09080807); + } else if (rate == DESC92C_RATEMCS10) { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x07060000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x0a090908); + } else if (rate == DESC92C_RATEMCS9) { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x07070000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x0a090808); + } else { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x08080000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x0b0a0909); + } + } + } else { /* MCS13~MCS15, 1SS, G-mode */ + if (collision_state == 1) { + if (rate == DESC92C_RATEMCS15) { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x00000000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x05040302); + } else if (rate == DESC92C_RATEMCS14) { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x00000000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x06050302); + } else if (rate == DESC92C_RATEMCS13) { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x00000000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x07060502); + } else { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x00000000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x06050402); + } + } else{ /* collision_state == 0 */ + if (rate == DESC92C_RATEMCS15) { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x03020000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x07060504); + } else if (rate == DESC92C_RATEMCS14) { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x03020000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x08070605); + } else if (rate == DESC92C_RATEMCS13) { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x05020000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x09080706); + } else { + rtl_write_dword(rtlpriv, REG_DARFRC, + 0x04020000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, + 0x08070605); + } + } + } +} + +void rtl92ee_dm_watchdog(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool fw_current_inpsmode = false; + bool fw_ps_awake = true; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inpsmode)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, + (u8 *)(&fw_ps_awake)); + if (ppsc->p2p_ps_info.p2p_ps_mode) + fw_ps_awake = false; + + if ((ppsc->rfpwr_state == ERFON) && + ((!fw_current_inpsmode) && fw_ps_awake) && + (!ppsc->rfchange_inprogress)) { + rtl92ee_dm_common_info_self_update(hw); + rtl92ee_dm_false_alarm_counter_statistics(hw); + rtl92ee_dm_check_rssi_monitor(hw); + rtl92ee_dm_dig(hw); + rtl92ee_dm_adaptivity(hw); + rtl92ee_dm_cck_packet_detection_thresh(hw); + rtl92ee_dm_refresh_rate_adaptive_mask(hw); + rtl92ee_dm_check_edca_turbo(hw); + rtl92ee_dm_dynamic_atc_switch(hw); + rtl92ee_dm_dynamic_primary_cca_ckeck(hw); + } +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h new file mode 100644 index 000000000000..107d5a488fa8 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/dm.h @@ -0,0 +1,251 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92E_DM_H__ +#define __RTL92E_DM_H__ + +#define OFDMCCA_TH 500 +#define BW_IND_BIAS 500 +#define MF_USC 2 +#define MF_LSC 1 +#define MF_USC_LSC 0 +#define MONITOR_TIME 30 + +#define MAIN_ANT 0 +#define AUX_ANT 1 +#define MAIN_ANT_CG_TRX 1 +#define AUX_ANT_CG_TRX 0 +#define MAIN_ANT_CGCS_RX 0 +#define AUX_ANT_CGCS_RX 1 + +/*RF REG LIST*/ +#define DM_REG_RF_MODE_11N 0x00 +#define DM_REG_RF_0B_11N 0x0B +#define DM_REG_CHNBW_11N 0x18 +#define DM_REG_T_METER_11N 0x24 +#define DM_REG_RF_25_11N 0x25 +#define DM_REG_RF_26_11N 0x26 +#define DM_REG_RF_27_11N 0x27 +#define DM_REG_RF_2B_11N 0x2B +#define DM_REG_RF_2C_11N 0x2C +#define DM_REG_RXRF_A3_11N 0x3C +#define DM_REG_T_METER_92D_11N 0x42 +#define DM_REG_T_METER_92E_11N 0x42 + +/*BB REG LIST*/ +/*PAGE 8 */ +#define DM_REG_BB_CTRL_11N 0x800 +#define DM_REG_RF_PIN_11N 0x804 +#define DM_REG_PSD_CTRL_11N 0x808 +#define DM_REG_TX_ANT_CTRL_11N 0x80C +#define DM_REG_BB_PWR_SAV5_11N 0x818 +#define DM_REG_CCK_RPT_FORMAT_11N 0x824 +#define DM_REG_RX_DEFUALT_A_11N 0x858 +#define DM_REG_RX_DEFUALT_B_11N 0x85A +#define DM_REG_BB_PWR_SAV3_11N 0x85C +#define DM_REG_ANTSEL_CTRL_11N 0x860 +#define DM_REG_RX_ANT_CTRL_11N 0x864 +#define DM_REG_PIN_CTRL_11N 0x870 +#define DM_REG_BB_PWR_SAV1_11N 0x874 +#define DM_REG_ANTSEL_PATH_11N 0x878 +#define DM_REG_BB_3WIRE_11N 0x88C +#define DM_REG_SC_CNT_11N 0x8C4 +#define DM_REG_PSD_DATA_11N 0x8B4 +/*PAGE 9*/ +#define DM_REG_ANT_MAPPING1_11N 0x914 +#define DM_REG_ANT_MAPPING2_11N 0x918 +/*PAGE A*/ +#define DM_REG_CCK_ANTDIV_PARA1_11N 0xA00 +#define DM_REG_CCK_CCA_11N 0xA0A +#define DM_REG_CCK_ANTDIV_PARA2_11N 0xA0C +#define DM_REG_CCK_ANTDIV_PARA3_11N 0xA10 +#define DM_REG_CCK_ANTDIV_PARA4_11N 0xA14 +#define DM_REG_CCK_FILTER_PARA1_11N 0xA22 +#define DM_REG_CCK_FILTER_PARA2_11N 0xA23 +#define DM_REG_CCK_FILTER_PARA3_11N 0xA24 +#define DM_REG_CCK_FILTER_PARA4_11N 0xA25 +#define DM_REG_CCK_FILTER_PARA5_11N 0xA26 +#define DM_REG_CCK_FILTER_PARA6_11N 0xA27 +#define DM_REG_CCK_FILTER_PARA7_11N 0xA28 +#define DM_REG_CCK_FILTER_PARA8_11N 0xA29 +#define DM_REG_CCK_FA_RST_11N 0xA2C +#define DM_REG_CCK_FA_MSB_11N 0xA58 +#define DM_REG_CCK_FA_LSB_11N 0xA5C +#define DM_REG_CCK_CCA_CNT_11N 0xA60 +#define DM_REG_BB_PWR_SAV4_11N 0xA74 +/*PAGE B */ +#define DM_REG_LNA_SWITCH_11N 0xB2C +#define DM_REG_PATH_SWITCH_11N 0xB30 +#define DM_REG_RSSI_CTRL_11N 0xB38 +#define DM_REG_CONFIG_ANTA_11N 0xB68 +#define DM_REG_RSSI_BT_11N 0xB9C +/*PAGE C */ +#define DM_REG_OFDM_FA_HOLDC_11N 0xC00 +#define DM_REG_RX_PATH_11N 0xC04 +#define DM_REG_TRMUX_11N 0xC08 +#define DM_REG_OFDM_FA_RSTC_11N 0xC0C +#define DM_REG_RXIQI_MATRIX_11N 0xC14 +#define DM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C +#define DM_REG_IGI_A_11N 0xC50 +#define DM_REG_ANTDIV_PARA2_11N 0xC54 +#define DM_REG_IGI_B_11N 0xC58 +#define DM_REG_ANTDIV_PARA3_11N 0xC5C +#define DM_REG_L1SBD_PD_CH_11N 0XC6C +#define DM_REG_BB_PWR_SAV2_11N 0xC70 +#define DM_REG_RX_OFF_11N 0xC7C +#define DM_REG_TXIQK_MATRIXA_11N 0xC80 +#define DM_REG_TXIQK_MATRIXB_11N 0xC88 +#define DM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 +#define DM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C +#define DM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 +#define DM_REG_ANTDIV_PARA1_11N 0xCA4 +#define DM_REG_OFDM_FA_TYPE1_11N 0xCF0 +/*PAGE D */ +#define DM_REG_OFDM_FA_RSTD_11N 0xD00 +#define DM_REG_OFDM_FA_TYPE2_11N 0xDA0 +#define DM_REG_OFDM_FA_TYPE3_11N 0xDA4 +#define DM_REG_OFDM_FA_TYPE4_11N 0xDA8 +/*PAGE E */ +#define DM_REG_TXAGC_A_6_18_11N 0xE00 +#define DM_REG_TXAGC_A_24_54_11N 0xE04 +#define DM_REG_TXAGC_A_1_MCS32_11N 0xE08 +#define DM_REG_TXAGC_A_MCS0_3_11N 0xE10 +#define DM_REG_TXAGC_A_MCS4_7_11N 0xE14 +#define DM_REG_TXAGC_A_MCS8_11_11N 0xE18 +#define DM_REG_TXAGC_A_MCS12_15_11N 0xE1C +#define DM_REG_FPGA0_IQK_11N 0xE28 +#define DM_REG_TXIQK_TONE_A_11N 0xE30 +#define DM_REG_RXIQK_TONE_A_11N 0xE34 +#define DM_REG_TXIQK_PI_A_11N 0xE38 +#define DM_REG_RXIQK_PI_A_11N 0xE3C +#define DM_REG_TXIQK_11N 0xE40 +#define DM_REG_RXIQK_11N 0xE44 +#define DM_REG_IQK_AGC_PTS_11N 0xE48 +#define DM_REG_IQK_AGC_RSP_11N 0xE4C +#define DM_REG_BLUETOOTH_11N 0xE6C +#define DM_REG_RX_WAIT_CCA_11N 0xE70 +#define DM_REG_TX_CCK_RFON_11N 0xE74 +#define DM_REG_TX_CCK_BBON_11N 0xE78 +#define DM_REG_OFDM_RFON_11N 0xE7C +#define DM_REG_OFDM_BBON_11N 0xE80 +#define DM_REG_TX2RX_11N 0xE84 +#define DM_REG_TX2TX_11N 0xE88 +#define DM_REG_RX_CCK_11N 0xE8C +#define DM_REG_RX_OFDM_11N 0xED0 +#define DM_REG_RX_WAIT_RIFS_11N 0xED4 +#define DM_REG_RX2RX_11N 0xED8 +#define DM_REG_STANDBY_11N 0xEDC +#define DM_REG_SLEEP_11N 0xEE0 +#define DM_REG_PMPD_ANAEN_11N 0xEEC + +/*MAC REG LIST*/ +#define DM_REG_BB_RST_11N 0x02 +#define DM_REG_ANTSEL_PIN_11N 0x4C +#define DM_REG_EARLY_MODE_11N 0x4D0 +#define DM_REG_RSSI_MONITOR_11N 0x4FE +#define DM_REG_EDCA_VO_11N 0x500 +#define DM_REG_EDCA_VI_11N 0x504 +#define DM_REG_EDCA_BE_11N 0x508 +#define DM_REG_EDCA_BK_11N 0x50C +#define DM_REG_TXPAUSE_11N 0x522 +#define DM_REG_RESP_TX_11N 0x6D8 +#define DM_REG_ANT_TRAIN_PARA1_11N 0x7b0 +#define DM_REG_ANT_TRAIN_PARA2_11N 0x7b4 + +/*DIG Related*/ +#define DM_BIT_IGI_11N 0x0000007F + +#define HAL_DM_DIG_DISABLE BIT(0) +#define HAL_DM_HIPWR_DISABLE BIT(1) + +#define OFDM_TABLE_LENGTH 43 +#define CCK_TABLE_LENGTH 33 + +#define OFDM_TABLE_SIZE 43 +#define CCK_TABLE_SIZE 33 + +#define BW_AUTO_SWITCH_HIGH_LOW 25 +#define BW_AUTO_SWITCH_LOW_HIGH 30 + +#define DM_DIG_FA_UPPER 0x3e +#define DM_DIG_FA_LOWER 0x1e +#define DM_DIG_FA_TH0 0x200 +#define DM_DIG_FA_TH1 0x300 +#define DM_DIG_FA_TH2 0x400 + +#define RXPATHSELECTION_SS_TH_LOW 30 +#define RXPATHSELECTION_DIFF_TH 18 + +#define DM_RATR_STA_INIT 0 +#define DM_RATR_STA_HIGH 1 +#define DM_RATR_STA_MIDDLE 2 +#define DM_RATR_STA_LOW 3 + +#define CTS2SELF_THVAL 30 +#define REGC38_TH 20 + +#define WAIOTTHVAL 25 + +#define TXHIGHPWRLEVEL_NORMAL 0 +#define TXHIGHPWRLEVEL_LEVEL1 1 +#define TXHIGHPWRLEVEL_LEVEL2 2 +#define TXHIGHPWRLEVEL_BT1 3 +#define TXHIGHPWRLEVEL_BT2 4 + +#define DM_TYPE_BYFW 0 +#define DM_TYPE_BYDRIVER 1 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 +#define TXPWRTRACK_MAX_IDX 6 + +/* Dynamic ATC switch */ +#define ATC_STATUS_OFF 0x0 /* enable */ +#define ATC_STATUS_ON 0x1 /* disable */ +#define CFO_THRESHOLD_XTAL 10 /* kHz */ +#define CFO_THRESHOLD_ATC 80 /* kHz */ + +/* RSSI Dump Message */ +#define RA_RSSIDUMP 0xcb0 +#define RB_RSSIDUMP 0xcb1 +#define RS1_RXEVMDUMP 0xcb2 +#define RS2_RXEVMDUMP 0xcb3 +#define RA_RXSNRDUMP 0xcb4 +#define RB_RXSNRDUMP 0xcb5 +#define RA_CFOSHORTDUMP 0xcb6 +#define RB_CFOSHORTDUMP 0xcb8 +#define RA_CFOLONGDUMP 0xcba +#define RB_CFOLONGDUMP 0xcbc + +void rtl92ee_dm_init(struct ieee80211_hw *hw); +void rtl92ee_dm_watchdog(struct ieee80211_hw *hw); +void rtl92ee_dm_write_cck_cca_thres(struct ieee80211_hw *hw, + u8 cur_thres); +void rtl92ee_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi); +void rtl92ee_dm_init_edca_turbo(struct ieee80211_hw *hw); +void rtl92ee_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); +void rtl92ee_dm_dynamic_arfb_select(struct ieee80211_hw *hw, + u8 rate, bool collision_state); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c new file mode 100644 index 000000000000..0708eedd9671 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c @@ -0,0 +1,902 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "fw.h" +#include "dm.h" + +static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp; + + if (enable) { + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05); + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); + rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); + } else { + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); + } +} + +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) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 *bufferptr = (u8 *)buffer; + u32 pagenums, remainsize; + u32 page, offset; + + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size); + + _rtl92ee_fill_dummy(bufferptr, &size); + + pagenums = size / FW_8192C_PAGE_SIZE; + remainsize = size % FW_8192C_PAGE_SIZE; + + if (pagenums > 8) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Page numbers should not greater then 8\n"); + } + + for (page = 0; page < pagenums; page++) { + offset = page * FW_8192C_PAGE_SIZE; + _rtl92ee_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); + } +} + +static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int err = -EIO; + u32 counter = 0; + u32 value32; + + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && + (!(value32 & FWDL_CHKSUM_RPT))); + + if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "chksum report faill ! REG_MCUFWDL:0x%08x .\n", + value32); + goto exit; + } + + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); + + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + value32 |= MCUFWDL_RDY; + value32 &= ~WINTINI_RDY; + rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); + + rtl92ee_firmware_selfreset(hw); + counter = 0; + + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + if (value32 & WINTINI_RDY) { + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , + "Polling FW ready success!! REG_MCUFWDL:0x%08x. count = %d\n", + value32, counter); + err = 0; + goto exit; + } + + udelay(FW_8192C_POLLING_DELAY*10); + + } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT); + + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n", + value32, counter); + +exit: + return err; +} + +int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtlwifi_firmware_header *pfwheader; + u8 *pfwdata; + u32 fwsize; + int err; + enum version_8192e version = rtlhal->version; + + if (!rtlhal->pfirmware) + return 1; + + pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; + rtlhal->fw_version = le16_to_cpu(pfwheader->version); + rtlhal->fw_subversion = pfwheader->subversion; + pfwdata = (u8 *)rtlhal->pfirmware; + fwsize = rtlhal->fwsize; + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "normal Firmware SIZE %d\n" , fwsize); + + if (IS_FW_HEADER_EXIST(pfwheader)) { + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "Firmware Version(%d), Signature(%#x),Size(%d)\n", + pfwheader->version, pfwheader->signature, + (int)sizeof(struct rtlwifi_firmware_header)); + + pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); + fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); + } else { + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "Firmware no Header, Signature(%#x)\n", + pfwheader->signature); + } + + if (rtlhal->mac_func_enable) { + if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); + rtl92ee_firmware_selfreset(hw); + } + } + _rtl92ee_enable_fw_download(hw, true); + _rtl92ee_write_fw(hw, version, pfwdata, fwsize); + _rtl92ee_enable_fw_download(hw, false); + + err = _rtl92ee_fw_free_to_go(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Firmware is not ready to run!\n"); + } else { + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , + "Firmware is ready to run!\n"); + } + + return 0; +} + +static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 val_hmetfr; + bool result = false; + + val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); + if (((val_hmetfr >> boxnum) & BIT(0)) == 0) + result = true; + return result; +} + +static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *cmdbuffer) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 boxnum; + u16 box_reg = 0, box_extreg = 0; + u8 u1b_tmp; + bool isfw_read = false; + u8 buf_index = 0; + bool bwrite_sucess = false; + u8 wait_h2c_limmit = 100; + u8 boxcontent[4], boxextcontent[4]; + u32 h2c_waitcounter = 0; + unsigned long flag; + u8 idx; + + if (ppsc->dot11_psmode != EACTIVE || + ppsc->inactive_pwrstate == ERFOFF) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , + "FillH2CCommand8192E(): Return because RF is off!!!\n"); + return; + } + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n"); + + /* 1. Prevent race condition in setting H2C cmd. + * (copy from MgntActSet_RF_State().) + */ + while (true) { + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + if (rtlhal->h2c_setinprogress) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , + "H2C set in progress! Wait to set..element_id(%d).\n", + element_id); + + while (rtlhal->h2c_setinprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, + flag); + h2c_waitcounter++; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , + "Wait 100 us (%d times)...\n", + h2c_waitcounter); + udelay(100); + + if (h2c_waitcounter > 1000) + return; + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, + flag); + } + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + } else { + rtlhal->h2c_setinprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + break; + } + } + + while (!bwrite_sucess) { + /* 2. Find the last BOX number which has been writen. */ + boxnum = rtlhal->last_hmeboxnum; + switch (boxnum) { + case 0: + box_reg = REG_HMEBOX_0; + box_extreg = REG_HMEBOX_EXT_0; + break; + case 1: + box_reg = REG_HMEBOX_1; + box_extreg = REG_HMEBOX_EXT_1; + break; + case 2: + box_reg = REG_HMEBOX_2; + box_extreg = REG_HMEBOX_EXT_2; + break; + case 3: + box_reg = REG_HMEBOX_3; + box_extreg = REG_HMEBOX_EXT_3; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + + /* 3. Check if the box content is empty. */ + isfw_read = false; + u1b_tmp = rtl_read_byte(rtlpriv, REG_CR); + + if (u1b_tmp != 0xea) { + isfw_read = true; + } else { + if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea || + rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea) + rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff); + } + + if (isfw_read) { + wait_h2c_limmit = 100; + isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum); + while (!isfw_read) { + wait_h2c_limmit--; + if (wait_h2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , + "Waiting too long for FW read clear HMEBox(%d)!!!\n", + boxnum); + break; + } + udelay(10); + isfw_read = + _rtl92ee_check_fw_read_last_h2c(hw, boxnum); + u1b_tmp = rtl_read_byte(rtlpriv, 0x130); + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , + "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", + boxnum, u1b_tmp); + } + } + + /* If Fw has not read the last + * H2C cmd, break and give up this H2C. + */ + if (!isfw_read) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , + "Write H2C reg BOX[%d] fail,Fw don't read.\n", + boxnum); + break; + } + /* 4. Fill the H2C cmd into box */ + memset(boxcontent, 0, sizeof(boxcontent)); + memset(boxextcontent, 0, sizeof(boxextcontent)); + boxcontent[0] = element_id; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , + "Write element_id box_reg(%4x) = %2x\n", + box_reg, element_id); + + switch (cmd_len) { + case 1: + case 2: + case 3: + /*boxcontent[0] &= ~(BIT(7));*/ + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index, cmd_len); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 4: + case 5: + case 6: + case 7: + /*boxcontent[0] |= (BIT(7));*/ + memcpy((u8 *)(boxextcontent), + cmdbuffer + buf_index+3, cmd_len-3); + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index, 3); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_extreg + idx, + boxextcontent[idx]); + } + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + + bwrite_sucess = true; + + rtlhal->last_hmeboxnum = boxnum + 1; + if (rtlhal->last_hmeboxnum == 4) + rtlhal->last_hmeboxnum = 0; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , + "pHalData->last_hmeboxnum = %d\n", + rtlhal->last_hmeboxnum); + } + + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + rtlhal->h2c_setinprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n"); +} + +void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, u8 *cmdbuffer) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 tmp_cmdbuf[2]; + + if (!rtlhal->fw_ready) { + RT_ASSERT(false, + "return H2C cmd because of Fw download fail!!!\n"); + return; + } + + memset(tmp_cmdbuf, 0, 8); + memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); + _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); +} + +void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw) +{ + u8 u1b_tmp; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); + + udelay(50); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0))); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2))); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD , + " _8051Reset92E(): 8051 reset success .\n"); +} + +void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 }; + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 rlbm , power_state = 0; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , "FW LPS mode = %d\n", mode); + + SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); + rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/ + SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); + SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, + (rtlpriv->mac80211.p2p) ? + ppsc->smart_ps : 1); + SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, + ppsc->reg_max_lps_awakeintvl); + SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); + if (mode == FW_PS_ACTIVE_MODE) + power_state |= FW_PWR_STATE_ACTIVE; + else + power_state |= FW_PWR_STATE_RF_OFF; + SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", + u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH); + rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH, + u1_h2c_set_pwrmode); +} + +void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus) +{ + u8 parm[3] = { 0 , 0 , 0 }; + /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect + * bit1=0-->update Media Status to MACID + * bit1=1-->update Media Status from MACID to MACID_End + * parm[1]: MACID, if this is INFRA_STA, MacID = 0 + * parm[2]: MACID_End + */ + + SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); + SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); + + rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm); +} + +#define BEACON_PG 0 /* ->1 */ +#define PSPOLL_PG 2 +#define NULL_PG 3 +#define PROBERSP_PG 4 /* ->5 */ + +#define TOTAL_RESERVED_PKT_LEN 768 + +static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { + /* page 0 beacon */ + 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, + 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65, + 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B, + 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06, + 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, + 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, + 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, + 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, + 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, + 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00, + + /* page 1 beacon */ + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 2 ps-poll */ + 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B, + 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 3 null */ + 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B, + 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, + 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 4 probe_resp */ + 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, + 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, + 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, + 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, + 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, + 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, + 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, + 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, + 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 5 probe_resp */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct sk_buff *skb = NULL; + + u32 totalpacketlen; + u8 u1rsvdpageloc[5] = { 0 }; + bool b_dlok = false; + + u8 *beacon; + u8 *p_pspoll; + u8 *nullfunc; + u8 *p_probersp; + /*--------------------------------------------------------- + * (1) beacon + *--------------------------------------------------------- + */ + beacon = &reserved_page_packet[BEACON_PG * 128]; + SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); + SET_80211_HDR_ADDRESS3(beacon, mac->bssid); + + /*------------------------------------------------------- + * (2) ps-poll + *-------------------------------------------------------- + */ + p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; + SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); + SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); + SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); + + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); + + /*-------------------------------------------------------- + * (3) null data + *--------------------------------------------------------- + */ + nullfunc = &reserved_page_packet[NULL_PG * 128]; + SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); + SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); + SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); + + /*--------------------------------------------------------- + * (4) probe response + *---------------------------------------------------------- + */ + p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; + SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); + SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); + SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); + + totalpacketlen = TOTAL_RESERVED_PKT_LEN; + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , + "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + &reserved_page_packet[0], totalpacketlen); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , + "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + u1rsvdpageloc, 3); + + skb = dev_alloc_skb(totalpacketlen); + memcpy((u8 *)skb_put(skb, totalpacketlen), + &reserved_page_packet, totalpacketlen); + + b_dlok = true; + + if (b_dlok) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , + "Set RSVD page location to Fw.\n"); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , + "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3); + rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE, + sizeof(u1rsvdpageloc), u1rsvdpageloc); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set RSVD page location to Fw FAIL!!!!!!.\n"); + } +} + +/*Shoud check FW support p2p or not.*/ +static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) +{ + u8 u1_ctwindow_period[1] = {ctwindow}; + + rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); +} + +void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info; + struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; + u8 i; + u16 ctwindow; + u32 start_time, tsf_low; + + switch (p2p_ps_state) { + case P2P_PS_DISABLE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n"); + memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); + break; + case P2P_PS_ENABLE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n"); + /* update CTWindow value. */ + if (p2pinfo->ctwindow > 0) { + p2p_ps_offload->ctwindow_en = 1; + ctwindow = p2pinfo->ctwindow; + rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow); + } + /* hw only support 2 set of NoA */ + for (i = 0 ; i < p2pinfo->noa_num ; i++) { + /* To control the register setting for which NOA*/ + rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); + if (i == 0) + p2p_ps_offload->noa0_en = 1; + else + p2p_ps_offload->noa1_en = 1; + /* config P2P NoA Descriptor Register */ + rtl_write_dword(rtlpriv, 0x5E0, + p2pinfo->noa_duration[i]); + rtl_write_dword(rtlpriv, 0x5E4, + p2pinfo->noa_interval[i]); + + /*Get Current TSF value */ + tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + start_time = p2pinfo->noa_start_time[i]; + if (p2pinfo->noa_count_type[i] != 1) { + while (start_time <= (tsf_low + (50 * 1024))) { + start_time += p2pinfo->noa_interval[i]; + if (p2pinfo->noa_count_type[i] != 255) + p2pinfo->noa_count_type[i]--; + } + } + rtl_write_dword(rtlpriv, 0x5E8, start_time); + rtl_write_dword(rtlpriv, 0x5EC, + p2pinfo->noa_count_type[i]); + } + if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { + /* rst p2p circuit */ + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); + p2p_ps_offload->offload_en = 1; + + if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { + p2p_ps_offload->role = 1; + p2p_ps_offload->allstasleep = 0; + } else { + p2p_ps_offload->role = 0; + } + p2p_ps_offload->discovery = 0; + } + break; + case P2P_PS_SCAN: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n"); + p2p_ps_offload->discovery = 1; + break; + case P2P_PS_SCAN_DONE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n"); + p2p_ps_offload->discovery = 0; + p2pinfo->p2p_ps_state = P2P_PS_ENABLE; + break; + default: + break; + } + rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1, + (u8 *)p2p_ps_offload); +} + +static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw, + u8 *cmd_buf, u8 cmd_len) +{ + u8 rate = cmd_buf[0] & 0x3F; + bool collision_state = cmd_buf[3] & BIT(0); + + rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state); +} + +static void _rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id, + u8 c2h_cmd_len, u8 *tmp_buf) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (c2h_cmd_id) { + case C2H_8192E_DBG: + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H], C2H_8723BE_DBG!!\n"); + break; + case C2H_8192E_TXBF: + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H], C2H_8192E_TXBF!!\n"); + break; + case C2H_8192E_TX_REPORT: + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE , + "[C2H], C2H_8723BE_TX_REPORT!\n"); + break; + case C2H_8192E_BT_INFO: + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H], C2H_8723BE_BT_INFO!!\n"); + rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf, + c2h_cmd_len); + break; + case C2H_8192E_BT_MP: + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H], C2H_8723BE_BT_MP!!\n"); + break; + case C2H_8192E_RA_RPT: + _rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len); + break; + default: + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id); + break; + } +} + +void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0; + u8 *tmp_buf = NULL; + + c2h_cmd_id = buffer[0]; + c2h_cmd_seq = buffer[1]; + c2h_cmd_len = len - 2; + tmp_buf = buffer + 2; + + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n", + c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len); + + RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len); + + _rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h new file mode 100644 index 000000000000..069da1e7e80a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.h @@ -0,0 +1,189 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92E__FW__H__ +#define __RTL92E__FW__H__ + +#define FW_8192C_SIZE 0x8000 +#define FW_8192C_START_ADDRESS 0x1000 +#define FW_8192C_END_ADDRESS 0x5FFF +#define FW_8192C_PAGE_SIZE 4096 +#define FW_8192C_POLLING_DELAY 5 +#define FW_8192C_POLLING_TIMEOUT_COUNT 3000 + +#define IS_FW_HEADER_EXIST(_pfwhdr) \ + ((le16_to_cpu(_pfwhdr->signature) & 0xFFF0) == 0x92E0) +#define USE_OLD_WOWLAN_DEBUG_FW 0 + +#define H2C_92E_RSVDPAGE_LOC_LEN 5 +#define H2C_92E_PWEMODE_LENGTH 5 +#define H2C_92E_JOINBSSRPT_LENGTH 1 +#define H2C_92E_AP_OFFLOAD_LENGTH 3 +#define H2C_92E_WOWLAN_LENGTH 3 +#define H2C_92E_KEEP_ALIVE_CTRL_LENGTH 3 +#if (USE_OLD_WOWLAN_DEBUG_FW == 0) +#define H2C_92E_REMOTE_WAKE_CTRL_LEN 1 +#else +#define H2C_92E_REMOTE_WAKE_CTRL_LEN 3 +#endif +#define H2C_92E_AOAC_GLOBAL_INFO_LEN 2 +#define H2C_92E_AOAC_RSVDPAGE_LOC_LEN 7 + +/* Fw PS state for RPWM. +*BIT[2:0] = HW state +*BIT[3] = Protocol PS state, 1: register active state, 0: register sleep state +*BIT[4] = sub-state +*/ +#define FW_PS_RF_ON BIT(2) +#define FW_PS_REGISTER_ACTIVE BIT(3) + +#define FW_PS_ACK BIT(6) +#define FW_PS_TOGGLE BIT(7) + + /* 92E RPWM value*/ + /* BIT[0] = 1: 32k, 0: 40M*/ +#define FW_PS_CLOCK_OFF BIT(0) /* 32k */ +#define FW_PS_CLOCK_ON 0 /* 40M */ + +#define FW_PS_STATE_MASK (0x0F) +#define FW_PS_STATE_HW_MASK (0x07) +#define FW_PS_STATE_INT_MASK (0x3F) + +#define FW_PS_STATE(x) (FW_PS_STATE_MASK & (x)) + +#define FW_PS_STATE_ALL_ON_92E (FW_PS_CLOCK_ON) +#define FW_PS_STATE_RF_ON_92E (FW_PS_CLOCK_ON) +#define FW_PS_STATE_RF_OFF_92E (FW_PS_CLOCK_ON) +#define FW_PS_STATE_RF_OFF_LOW_PWR (FW_PS_CLOCK_OFF) + +/* For 92E H2C PwrMode Cmd ID 5.*/ +#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) +#define FW_PWR_STATE_RF_OFF 0 + +#define FW_PS_IS_ACK(x) ((x) & FW_PS_ACK) + +#define IS_IN_LOW_POWER_STATE_92E(__state) \ + (FW_PS_STATE(__state) == FW_PS_CLOCK_OFF) + +#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) +#define FW_PWR_STATE_RF_OFF 0 + +enum rtl8192e_h2c_cmd { + H2C_92E_RSVDPAGE = 0, + H2C_92E_MSRRPT = 1, + H2C_92E_SCAN = 2, + H2C_92E_KEEP_ALIVE_CTRL = 3, + H2C_92E_DISCONNECT_DECISION = 4, +#if (USE_OLD_WOWLAN_DEBUG_FW == 1) + H2C_92E_WO_WLAN = 5, +#endif + H2C_92E_INIT_OFFLOAD = 6, +#if (USE_OLD_WOWLAN_DEBUG_FW == 1) + H2C_92E_REMOTE_WAKE_CTRL = 7, +#endif + H2C_92E_AP_OFFLOAD = 8, + H2C_92E_BCN_RSVDPAGE = 9, + H2C_92E_PROBERSP_RSVDPAGE = 10, + + H2C_92E_SETPWRMODE = 0x20, + H2C_92E_PS_TUNING_PARA = 0x21, + H2C_92E_PS_TUNING_PARA2 = 0x22, + H2C_92E_PS_LPS_PARA = 0x23, + H2C_92E_P2P_PS_OFFLOAD = 024, + +#if (USE_OLD_WOWLAN_DEBUG_FW == 0) + H2C_92E_WO_WLAN = 0x80, + H2C_92E_REMOTE_WAKE_CTRL = 0x81, + H2C_92E_AOAC_GLOBAL_INFO = 0x82, + H2C_92E_AOAC_RSVDPAGE = 0x83, +#endif + H2C_92E_RA_MASK = 0x40, + H2C_92E_RSSI_REPORT = 0x42, + H2C_92E_SELECTIVE_SUSPEND_ROF_CMD, + H2C_92E_P2P_PS_MODE, + H2C_92E_PSD_RESULT, + /*Not defined CTW CMD for P2P yet*/ + H2C_92E_P2P_PS_CTW_CMD, + MAX_92E_H2CCMD +}; + +enum rtl8192e_c2h_evt { + C2H_8192E_DBG = 0, + C2H_8192E_LB = 1, + C2H_8192E_TXBF = 2, + C2H_8192E_TX_REPORT = 3, + C2H_8192E_BT_INFO = 9, + C2H_8192E_BT_MP = 11, + C2H_8192E_RA_RPT = 12, + MAX_8192E_C2HEVENT +}; + +#define pagenum_128(_len) \ + (u32)(((_len) >> 7) + ((_len) & 0x7F ? 1 : 0)) + +#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_RLBM(__cmd, __val) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 4, __val) +#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__cmd, __val) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 4, 4, __val) +#define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__cmd, __val) \ + SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__cmd, __val) \ + SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __val) \ + SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __val) +#define GET_92E_H2CCMD_PWRMODE_PARM_MODE(__cmd) \ + LE_BITS_TO_1BYTE(__cmd, 0, 8) + +#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) + +/* _MEDIA_STATUS_RPT_PARM_CMD1 */ +#define SET_H2CCMD_MSRRPT_PARM_OPMODE(__cmd, __val) \ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __val) +#define SET_H2CCMD_MSRRPT_PARM_MACID_IND(__cmd, __val) \ + SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __val) +#define SET_H2CCMD_MSRRPT_PARM_MACID(__cmd, __val) \ + SET_BITS_TO_LE_1BYTE(__cmd+1, 0, 8, __val) +#define SET_H2CCMD_MSRRPT_PARM_MACID_END(__cmd, __val) \ + SET_BITS_TO_LE_1BYTE(__cmd+2, 0, 8, __val) + +int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw); +void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *cmdbuffer); +void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw); +void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); +void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus); +void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); +void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); +void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c new file mode 100644 index 000000000000..5f14308e8eb3 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.c @@ -0,0 +1,2666 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../regd.h" +#include "../cam.h" +#include "../ps.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "led.h" +#include "hw.h" +#include "../pwrseqcmd.h" +#include "pwrseq.h" + +#define LLT_CONFIG 5 + +static void _rtl92ee_set_bcn_ctrl_reg(struct ieee80211_hw *hw, + u8 set_bits, u8 clear_bits) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpci->reg_bcn_ctrl_val |= set_bits; + rtlpci->reg_bcn_ctrl_val &= ~clear_bits; + + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); +} + +static void _rtl92ee_stop_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp; + + tmp = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp & (~BIT(6))); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); + tmp = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp); +} + +static void _rtl92ee_resume_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp; + + tmp = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp | BIT(6)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + tmp = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp |= BIT(0); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp); +} + +static void _rtl92ee_enable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(1)); +} + +static void _rtl92ee_disable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl92ee_set_bcn_ctrl_reg(hw, BIT(1), 0); +} + +static void _rtl92ee_set_fw_clock_on(struct ieee80211_hw *hw, + u8 rpwm_val, bool b_need_turn_off_ckk) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool b_support_remote_wake_up; + u32 count = 0, isr_regaddr, content; + bool b_schedule_timer = b_need_turn_off_ckk; + + rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, + (u8 *)(&b_support_remote_wake_up)); + + if (!rtlhal->fw_ready) + return; + if (!rtlpriv->psc.fw_current_inpsmode) + return; + + while (1) { + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + if (rtlhal->fw_clk_change_in_progress) { + while (rtlhal->fw_clk_change_in_progress) { + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + count++; + udelay(100); + if (count > 1000) + return; + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + } + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + } else { + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + break; + } + } + + if (IS_IN_LOW_POWER_STATE_92E(rtlhal->fw_ps_state)) { + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + if (FW_PS_IS_ACK(rpwm_val)) { + isr_regaddr = REG_HISR; + content = rtl_read_dword(rtlpriv, isr_regaddr); + while (!(content & IMR_CPWM) && (count < 500)) { + udelay(50); + count++; + content = rtl_read_dword(rtlpriv, isr_regaddr); + } + + if (content & IMR_CPWM) { + rtl_write_word(rtlpriv, isr_regaddr, 0x0100); + rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_92E; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Receive CPWM INT!!! PSState = %X\n", + rtlhal->fw_ps_state); + } + } + + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + if (b_schedule_timer) { + mod_timer(&rtlpriv->works.fw_clockoff_timer, + jiffies + MSECS(10)); + } + } else { + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + } +} + +static void _rtl92ee_set_fw_clock_off(struct ieee80211_hw *hw, u8 rpwm_val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + enum rf_pwrstate rtstate; + bool b_schedule_timer = false; + u8 queue; + + if (!rtlhal->fw_ready) + return; + if (!rtlpriv->psc.fw_current_inpsmode) + return; + if (!rtlhal->allow_sw_to_change_hwclc) + return; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate)); + if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF) + return; + + for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) { + ring = &rtlpci->tx_ring[queue]; + if (skb_queue_len(&ring->queue)) { + b_schedule_timer = true; + break; + } + } + + if (b_schedule_timer) { + mod_timer(&rtlpriv->works.fw_clockoff_timer, + jiffies + MSECS(10)); + return; + } + + if (FW_PS_STATE(rtlhal->fw_ps_state) != FW_PS_STATE_RF_OFF_LOW_PWR) { + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + if (!rtlhal->fw_clk_change_in_progress) { + rtlhal->fw_clk_change_in_progress = true; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); + rtl_write_word(rtlpriv, REG_HISR, 0x0100); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + } else { + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + mod_timer(&rtlpriv->works.fw_clockoff_timer, + jiffies + MSECS(10)); + } + } +} + +static void _rtl92ee_set_fw_ps_rf_on(struct ieee80211_hw *hw) +{ + u8 rpwm_val = 0; + + rpwm_val |= (FW_PS_STATE_RF_OFF_92E | FW_PS_ACK); + _rtl92ee_set_fw_clock_on(hw, rpwm_val, true); +} + +static void _rtl92ee_set_fw_ps_rf_off_low_power(struct ieee80211_hw *hw) +{ + u8 rpwm_val = 0; + + rpwm_val |= FW_PS_STATE_RF_OFF_LOW_PWR; + _rtl92ee_set_fw_clock_off(hw, rpwm_val); +} + +void rtl92ee_fw_clk_off_timer_callback(unsigned long data) +{ + struct ieee80211_hw *hw = (struct ieee80211_hw *)data; + + _rtl92ee_set_fw_ps_rf_off_low_power(hw); +} + +static void _rtl92ee_fwlps_leave(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool fw_current_inps = false; + u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE; + + if (ppsc->low_power_enable) { + rpwm_val = (FW_PS_STATE_ALL_ON_92E | FW_PS_ACK);/* RF on */ + _rtl92ee_set_fw_clock_on(hw, rpwm_val, false); + rtlhal->allow_sw_to_change_hwclc = false; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&fw_pwrmode)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + } else { + rpwm_val = FW_PS_STATE_ALL_ON_92E; /* RF on */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&fw_pwrmode)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + } +} + +static void _rtl92ee_fwlps_enter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool fw_current_inps = true; + u8 rpwm_val; + + if (ppsc->low_power_enable) { + rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR; /* RF off */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&ppsc->fwctrl_psmode)); + rtlhal->allow_sw_to_change_hwclc = true; + _rtl92ee_set_fw_clock_off(hw, rpwm_val); + } else { + rpwm_val = FW_PS_STATE_RF_OFF_92E; /* RF off */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&ppsc->fwctrl_psmode)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + } +} + +void rtl92ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + switch (variable) { + case HW_VAR_RCR: + *((u32 *)(val)) = rtlpci->receive_config; + break; + case HW_VAR_RF_STATE: + *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; + break; + case HW_VAR_FWLPS_RF_ON:{ + enum rf_pwrstate rfstate; + u32 val_rcr; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, + (u8 *)(&rfstate)); + if (rfstate == ERFOFF) { + *((bool *)(val)) = true; + } else { + val_rcr = rtl_read_dword(rtlpriv, REG_RCR); + val_rcr &= 0x00070000; + if (val_rcr) + *((bool *)(val)) = false; + else + *((bool *)(val)) = true; + } + } + break; + case HW_VAR_FW_PSMODE_STATUS: + *((bool *)(val)) = ppsc->fw_current_inpsmode; + break; + case HW_VAR_CORRECT_TSF:{ + u64 tsf; + u32 *ptsf_low = (u32 *)&tsf; + u32 *ptsf_high = ((u32 *)&tsf) + 1; + + *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); + *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + *((u64 *)(val)) = tsf; + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, + "switch case not process %x\n", variable); + break; + } +} + +static void _rtl92ee_download_rsvd_page(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp_regcr, tmp_reg422; + u8 bcnvalid_reg, txbc_reg; + u8 count = 0, dlbcn_count = 0; + bool b_recover = false; + + /*Set REG_CR bit 8. DMA beacon by SW.*/ + tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, tmp_regcr | BIT(0)); + + /* Disable Hw protection for a time which revserd for Hw sending beacon. + * Fix download reserved page packet fail + * that access collision with the protection time. + * 2010.05.11. Added by tynli. + */ + _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); + _rtl92ee_set_bcn_ctrl_reg(hw, BIT(4), 0); + + /* Set FWHW_TXQ_CTRL 0x422[6]=0 to + * tell Hw the packet is not a real beacon frame. + */ + tmp_reg422 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422 & (~BIT(6))); + + if (tmp_reg422 & BIT(6)) + b_recover = true; + + do { + /* Clear beacon valid check bit */ + bcnvalid_reg = rtl_read_byte(rtlpriv, REG_DWBCN0_CTRL + 2); + rtl_write_byte(rtlpriv, REG_DWBCN0_CTRL + 2, + bcnvalid_reg | BIT(0)); + + /* download rsvd page */ + rtl92ee_set_fw_rsvdpagepkt(hw, false); + + txbc_reg = rtl_read_byte(rtlpriv, REG_MGQ_TXBD_NUM + 3); + count = 0; + while ((txbc_reg & BIT(4)) && count < 20) { + count++; + udelay(10); + txbc_reg = rtl_read_byte(rtlpriv, REG_MGQ_TXBD_NUM + 3); + } + rtl_write_byte(rtlpriv, REG_MGQ_TXBD_NUM + 3, + txbc_reg | BIT(4)); + + /* check rsvd page download OK. */ + bcnvalid_reg = rtl_read_byte(rtlpriv, REG_DWBCN0_CTRL + 2); + count = 0; + while (!(bcnvalid_reg & BIT(0)) && count < 20) { + count++; + udelay(50); + bcnvalid_reg = rtl_read_byte(rtlpriv, + REG_DWBCN0_CTRL + 2); + } + + if (bcnvalid_reg & BIT(0)) + rtl_write_byte(rtlpriv, REG_DWBCN0_CTRL + 2, BIT(0)); + + dlbcn_count++; + } while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5); + + if (!(bcnvalid_reg & BIT(0))) + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Download RSVD page failed!\n"); + + /* Enable Bcn */ + _rtl92ee_set_bcn_ctrl_reg(hw, BIT(3), 0); + _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); + + if (b_recover) + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422); + + tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, tmp_regcr & (~BIT(0))); +} + +void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *efuse = rtl_efuse(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 idx; + + switch (variable) { + case HW_VAR_ETHER_ADDR: + for (idx = 0; idx < ETH_ALEN; idx++) + rtl_write_byte(rtlpriv, (REG_MACID + idx), val[idx]); + break; + case HW_VAR_BASIC_RATE:{ + u16 b_rate_cfg = ((u16 *)val)[0]; + + b_rate_cfg = b_rate_cfg & 0x15f; + b_rate_cfg |= 0x01; + b_rate_cfg = (b_rate_cfg | 0xd) & (~BIT(1)); + rtl_write_byte(rtlpriv, REG_RRSR, b_rate_cfg & 0xff); + rtl_write_byte(rtlpriv, REG_RRSR + 1, (b_rate_cfg >> 8) & 0xff); + break; } + case HW_VAR_BSSID: + for (idx = 0; idx < ETH_ALEN; idx++) + rtl_write_byte(rtlpriv, (REG_BSSID + idx), val[idx]); + break; + case HW_VAR_SIFS: + rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); + rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); + + rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); + rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); + + if (!mac->ht_enable) + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, 0x0e0e); + else + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, + *((u16 *)val)); + break; + case HW_VAR_SLOT_TIME:{ + u8 e_aci; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_TRACE, + "HW_VAR_SLOT_TIME %x\n", val[0]); + + rtl_write_byte(rtlpriv, REG_SLOT, val[0]); + + for (e_aci = 0; e_aci < AC_MAX; e_aci++) { + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + (u8 *)(&e_aci)); + } + break; } + case HW_VAR_ACK_PREAMBLE:{ + u8 reg_tmp; + u8 short_preamble = (bool)(*(u8 *)val); + + reg_tmp = (rtlpriv->mac80211.cur_40_prime_sc) << 5; + if (short_preamble) + reg_tmp |= 0x80; + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp); + rtlpriv->mac80211.short_preamble = short_preamble; + } + break; + case HW_VAR_WPA_CONFIG: + rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); + break; + case HW_VAR_AMPDU_FACTOR:{ + u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; + u8 fac; + u8 *reg = NULL; + u8 i = 0; + + reg = regtoset_normal; + + fac = *((u8 *)val); + if (fac <= 3) { + fac = (1 << (fac + 2)); + if (fac > 0xf) + fac = 0xf; + for (i = 0; i < 4; i++) { + if ((reg[i] & 0xf0) > (fac << 4)) + reg[i] = (reg[i] & 0x0f) | + (fac << 4); + if ((reg[i] & 0x0f) > fac) + reg[i] = (reg[i] & 0xf0) | fac; + rtl_write_byte(rtlpriv, + (REG_AGGLEN_LMT + i), + reg[i]); + } + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_FACTOR:%#x\n", fac); + } + } + break; + case HW_VAR_AC_PARAM:{ + u8 e_aci = *((u8 *)val); + + if (rtlpci->acm_method != EACMWAY2_SW) + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, + (u8 *)(&e_aci)); + } + break; + case HW_VAR_ACM_CTRL:{ + u8 e_aci = *((u8 *)val); + union aci_aifsn *aifs = (union aci_aifsn *)(&mac->ac[0].aifs); + + u8 acm = aifs->f.acm; + u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); + + acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); + + if (acm) { + switch (e_aci) { + case AC0_BE: + acm_ctrl |= ACMHW_BEQEN; + break; + case AC2_VI: + acm_ctrl |= ACMHW_VIQEN; + break; + case AC3_VO: + acm_ctrl |= ACMHW_VOQEN; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", + acm); + break; + } + } else { + switch (e_aci) { + case AC0_BE: + acm_ctrl &= (~ACMHW_BEQEN); + break; + case AC2_VI: + acm_ctrl &= (~ACMHW_VIQEN); + break; + case AC3_VO: + acm_ctrl &= (~ACMHW_VOQEN); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, + "switch case not process\n"); + break; + } + } + + RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, + "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", + acm_ctrl); + rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); + } + break; + case HW_VAR_RCR:{ + rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); + rtlpci->receive_config = ((u32 *)(val))[0]; + } + break; + case HW_VAR_RETRY_LIMIT:{ + u8 retry_limit = ((u8 *)(val))[0]; + + rtl_write_word(rtlpriv, REG_RETRY_LIMIT, + retry_limit << RETRY_LIMIT_SHORT_SHIFT | + retry_limit << RETRY_LIMIT_LONG_SHIFT); + } + break; + case HW_VAR_DUAL_TSF_RST: + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); + break; + case HW_VAR_EFUSE_BYTES: + efuse->efuse_usedbytes = *((u16 *)val); + break; + case HW_VAR_EFUSE_USAGE: + efuse->efuse_usedpercentage = *((u8 *)val); + break; + case HW_VAR_IO_CMD: + rtl92ee_phy_set_io_cmd(hw, (*(enum io_type *)val)); + break; + case HW_VAR_SET_RPWM:{ + u8 rpwm_val; + + rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); + udelay(1); + + if (rpwm_val & BIT(7)) { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, (*(u8 *)val)); + } else { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, + ((*(u8 *)val) | BIT(7))); + } + } + break; + case HW_VAR_H2C_FW_PWRMODE: + rtl92ee_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); + break; + case HW_VAR_FW_PSMODE_STATUS: + ppsc->fw_current_inpsmode = *((bool *)val); + break; + case HW_VAR_RESUME_CLK_ON: + _rtl92ee_set_fw_ps_rf_on(hw); + break; + case HW_VAR_FW_LPS_ACTION:{ + bool b_enter_fwlps = *((bool *)val); + + if (b_enter_fwlps) + _rtl92ee_fwlps_enter(hw); + else + _rtl92ee_fwlps_leave(hw); + } + break; + case HW_VAR_H2C_FW_JOINBSSRPT:{ + u8 mstatus = (*(u8 *)val); + + if (mstatus == RT_MEDIA_CONNECT) { + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL); + _rtl92ee_download_rsvd_page(hw); + } + rtl92ee_set_fw_media_status_rpt_cmd(hw, mstatus); + } + break; + case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: + rtl92ee_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); + break; + case HW_VAR_AID:{ + u16 u2btmp; + + u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); + u2btmp &= 0xC000; + rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, + (u2btmp | mac->assoc_id)); + } + break; + case HW_VAR_CORRECT_TSF:{ + u8 btype_ibss = ((u8 *)(val))[0]; + + if (btype_ibss) + _rtl92ee_stop_tx_beacon(hw); + + _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); + + rtl_write_dword(rtlpriv, REG_TSFTR, + (u32)(mac->tsf & 0xffffffff)); + rtl_write_dword(rtlpriv, REG_TSFTR + 4, + (u32)((mac->tsf >> 32) & 0xffffffff)); + + _rtl92ee_set_bcn_ctrl_reg(hw, BIT(3), 0); + + if (btype_ibss) + _rtl92ee_resume_tx_beacon(hw); + } + break; + case HW_VAR_KEEP_ALIVE: { + u8 array[2]; + + array[0] = 0xff; + array[1] = *((u8 *)val); + rtl92ee_fill_h2c_cmd(hw, H2C_92E_KEEP_ALIVE_CTRL, 2, array); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, + "switch case not process %x\n", variable); + break; + } +} + +static bool _rtl92ee_llt_table_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 txpktbuf_bndy; + u8 u8tmp, testcnt = 0; + + txpktbuf_bndy = 0xFA; + + rtl_write_dword(rtlpriv, REG_RQPN, 0x80E90808); + + rtl_write_byte(rtlpriv, REG_TRXFF_BNDY, txpktbuf_bndy); + rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x3d00 - 1); + + rtl_write_byte(rtlpriv, REG_DWBCN0_CTRL + 1, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_DWBCN1_CTRL + 1, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, REG_BCNQ_BDNY, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_BCNQ1_BDNY, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, REG_MGQ_BDNY, txpktbuf_bndy); + rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, REG_PBP, 0x31); + rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); + + u8tmp = rtl_read_byte(rtlpriv, REG_AUTO_LLT + 2); + rtl_write_byte(rtlpriv, REG_AUTO_LLT + 2, u8tmp | BIT(0)); + + while (u8tmp & BIT(0)) { + u8tmp = rtl_read_byte(rtlpriv, REG_AUTO_LLT + 2); + udelay(10); + testcnt++; + if (testcnt > 10) + break; + } + + return true; +} + +static void _rtl92ee_gen_refresh_led_state(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_led *pled0 = &pcipriv->ledctl.sw_led0; + + if (rtlpriv->rtlhal.up_first_time) + return; + + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) + rtl92ee_sw_led_on(hw, pled0); + else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) + rtl92ee_sw_led_on(hw, pled0); + else + rtl92ee_sw_led_off(hw, pled0); +} + +static bool _rtl92ee_init_mac(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + u8 bytetmp; + u16 wordtmp; + u32 dwordtmp; + + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0); + + dwordtmp = rtl_read_dword(rtlpriv, REG_SYS_CFG1); + if (dwordtmp & BIT(24)) { + rtl_write_byte(rtlpriv, 0x7c, 0xc3); + } else { + bytetmp = rtl_read_byte(rtlpriv, 0x16); + rtl_write_byte(rtlpriv, 0x16, bytetmp | BIT(4) | BIT(6)); + rtl_write_byte(rtlpriv, 0x7c, 0x83); + } + /* 1. 40Mhz crystal source*/ + bytetmp = rtl_read_byte(rtlpriv, REG_AFE_CTRL2); + bytetmp &= 0xfb; + rtl_write_byte(rtlpriv, REG_AFE_CTRL2, bytetmp); + + dwordtmp = rtl_read_dword(rtlpriv, REG_AFE_CTRL4); + dwordtmp &= 0xfffffc7f; + rtl_write_dword(rtlpriv, REG_AFE_CTRL4, dwordtmp); + + /* 2. 92E AFE parameter + * MP chip then check version + */ + bytetmp = rtl_read_byte(rtlpriv, REG_AFE_CTRL2); + bytetmp &= 0xbf; + rtl_write_byte(rtlpriv, REG_AFE_CTRL2, bytetmp); + + dwordtmp = rtl_read_dword(rtlpriv, REG_AFE_CTRL4); + dwordtmp &= 0xffdfffff; + rtl_write_dword(rtlpriv, REG_AFE_CTRL4, dwordtmp); + + /* HW Power on sequence */ + if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, + RTL8192E_NIC_ENABLE_FLOW)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "init MAC Fail as rtl_hal_pwrseqcmdparsing\n"); + return false; + } + + /* Release MAC IO register reset */ + bytetmp = rtl_read_byte(rtlpriv, REG_CR); + bytetmp = 0xff; + rtl_write_byte(rtlpriv, REG_CR, bytetmp); + mdelay(2); + bytetmp = 0x7f; + rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, bytetmp); + mdelay(2); + + /* Add for wakeup online */ + bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR); + rtl_write_byte(rtlpriv, REG_SYS_CLKR, bytetmp | BIT(3)); + bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG + 1); + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG + 1, bytetmp & (~BIT(4))); + /* Release MAC IO register reset */ + rtl_write_word(rtlpriv, REG_CR, 0x2ff); + + if (!rtlhal->mac_func_enable) { + if (_rtl92ee_llt_table_init(hw) == false) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "LLT table init fail\n"); + return false; + } + } + + rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); + rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff); + + wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); + wordtmp &= 0xf; + wordtmp |= 0xF5B1; + rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); + /* Reported Tx status from HW for rate adaptive.*/ + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); + + /* Set RCR register */ + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xffff); + + /* Set TCR register */ + rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); + + /* Set TX/RX descriptor physical address(from OS API). */ + rtl_write_dword(rtlpriv, REG_BCNQ_DESA, + ((u64)rtlpci->tx_ring[BEACON_QUEUE].buffer_desc_dma) & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_MGQ_DESA, + (u64)rtlpci->tx_ring[MGNT_QUEUE].buffer_desc_dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VOQ_DESA, + (u64)rtlpci->tx_ring[VO_QUEUE].buffer_desc_dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VIQ_DESA, + (u64)rtlpci->tx_ring[VI_QUEUE].buffer_desc_dma & + DMA_BIT_MASK(32)); + + rtl_write_dword(rtlpriv, REG_BEQ_DESA, + (u64)rtlpci->tx_ring[BE_QUEUE].buffer_desc_dma & + DMA_BIT_MASK(32)); + + dwordtmp = rtl_read_dword(rtlpriv, REG_BEQ_DESA); + + rtl_write_dword(rtlpriv, REG_BKQ_DESA, + (u64)rtlpci->tx_ring[BK_QUEUE].buffer_desc_dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_HQ0_DESA, + (u64)rtlpci->tx_ring[HIGH_QUEUE].buffer_desc_dma & + DMA_BIT_MASK(32)); + + rtl_write_dword(rtlpriv, REG_RX_DESA, + (u64)rtlpci->rx_ring[RX_MPDU_QUEUE].dma & + DMA_BIT_MASK(32)); + + /* if we want to support 64 bit DMA, we should set it here, + * but now we do not support 64 bit DMA + */ + + rtl_write_dword(rtlpriv, REG_TSFTIMER_HCI, 0x3fffffff); + + bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 3); + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, bytetmp | 0xF7); + + rtl_write_dword(rtlpriv, REG_INT_MIG, 0); + + rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); + + rtl_write_word(rtlpriv, REG_MGQ_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_VOQ_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_VIQ_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_BEQ_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_VOQ_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_BKQ_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_HI0Q_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_HI1Q_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_HI2Q_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_HI3Q_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_HI4Q_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_HI5Q_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_HI6Q_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + rtl_write_word(rtlpriv, REG_HI7Q_TXBD_NUM, + TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); + /*Rx*/ +#if (DMA_IS_64BIT == 1) + rtl_write_word(rtlpriv, REG_RX_RXBD_NUM, + RX_DESC_NUM_92E | + ((RTL8192EE_SEG_NUM << 13) & 0x6000) | 0x8000); +#else + rtl_write_word(rtlpriv, REG_RX_RXBD_NUM, + RX_DESC_NUM_92E | + ((RTL8192EE_SEG_NUM << 13) & 0x6000) | 0x0000); +#endif + + rtl_write_dword(rtlpriv, REG_TSFTIMER_HCI, 0XFFFFFFFF); + + _rtl92ee_gen_refresh_led_state(hw); + return true; +} + +static void _rtl92ee_hw_configure(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 reg_rrsr; + + reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + /* Init value for RRSR. */ + rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr); + + /* ARFB table 9 for 11ac 5G 2SS */ + rtl_write_dword(rtlpriv, REG_ARFR0, 0x00000010); + rtl_write_dword(rtlpriv, REG_ARFR0 + 4, 0x3e0ff000); + + /* ARFB table 10 for 11ac 5G 1SS */ + rtl_write_dword(rtlpriv, REG_ARFR1, 0x00000010); + rtl_write_dword(rtlpriv, REG_ARFR1 + 4, 0x000ff000); + + /* Set SLOT time */ + rtl_write_byte(rtlpriv, REG_SLOT, 0x09); + + /* CF-End setting. */ + rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80); + + /* Set retry limit */ + rtl_write_word(rtlpriv, REG_RETRY_LIMIT, 0x0707); + + /* BAR settings */ + rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x0201ffff); + + /* Set Data / Response auto rate fallack retry count */ + rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); + rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); + + /* Beacon related, for rate adaptive */ + rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); + rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff); + + rtlpci->reg_bcn_ctrl_val = 0x1d; + rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); + + /* Marked out by Bruce, 2010-09-09. + * This register is configured for the 2nd Beacon (multiple BSSID). + * We shall disable this register if we only support 1 BSSID. + * vivi guess 92d also need this, also 92d now doesnot set this reg + */ + rtl_write_byte(rtlpriv, REG_BCN_CTRL_1, 0); + + /* TBTT prohibit hold time. Suggested by designer TimChen. */ + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); /* 8 ms */ + + rtl_write_byte(rtlpriv, REG_PIFS, 0); + rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); + + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040); + rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x08ff); + + /* For Rx TP. Suggested by SD1 Richard. Added by tynli. 2010.04.12.*/ + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); + + /* ACKTO for IOT issue. */ + rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); + + /* Set Spec SIFS (used in NAV) */ + rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x100a); + rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x100a); + + /* Set SIFS for CCK */ + rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x100a); + + /* Set SIFS for OFDM */ + rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x100a); + + /* Note Data sheet don't define */ + rtl_write_word(rtlpriv, 0x4C7, 0x80); + + rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20); + + rtl_write_word(rtlpriv, REG_MAX_AGGR_NUM, 0x1717); + + /* Set Multicast Address. 2009.01.07. by tynli. */ + rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff); + rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff); +} + +static void _rtl92ee_enable_aspm_back_door(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u32 tmp32 = 0, count = 0; + u8 tmp8 = 0; + + rtl_write_word(rtlpriv, REG_BACKDOOR_DBI_DATA, 0x78); + rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2, 0x2); + tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); + count = 0; + while (tmp8 && count < 20) { + udelay(10); + tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); + count++; + } + + if (0 == tmp8) { + tmp32 = rtl_read_dword(rtlpriv, REG_BACKDOOR_DBI_RDATA); + if ((tmp32 & 0xff00) != 0x2000) { + tmp32 &= 0xffff00ff; + rtl_write_dword(rtlpriv, REG_BACKDOOR_DBI_WDATA, + tmp32 | BIT(13)); + rtl_write_word(rtlpriv, REG_BACKDOOR_DBI_DATA, 0xf078); + rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2, 0x1); + + tmp8 = rtl_read_byte(rtlpriv, + REG_BACKDOOR_DBI_DATA + 2); + count = 0; + while (tmp8 && count < 20) { + udelay(10); + tmp8 = rtl_read_byte(rtlpriv, + REG_BACKDOOR_DBI_DATA + 2); + count++; + } + } + } + + rtl_write_word(rtlpriv, REG_BACKDOOR_DBI_DATA, 0x70c); + rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2, 0x2); + tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); + count = 0; + while (tmp8 && count < 20) { + udelay(10); + tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); + count++; + } + if (0 == tmp8) { + tmp32 = rtl_read_dword(rtlpriv, REG_BACKDOOR_DBI_RDATA); + rtl_write_dword(rtlpriv, REG_BACKDOOR_DBI_WDATA, + tmp32 | BIT(31)); + rtl_write_word(rtlpriv, REG_BACKDOOR_DBI_DATA, 0xf70c); + rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2, 0x1); + } + + tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); + count = 0; + while (tmp8 && count < 20) { + udelay(10); + tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); + count++; + } + + rtl_write_word(rtlpriv, REG_BACKDOOR_DBI_DATA, 0x718); + rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2, 0x2); + tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); + count = 0; + while (tmp8 && count < 20) { + udelay(10); + tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); + count++; + } + if (ppsc->support_backdoor || (0 == tmp8)) { + tmp32 = rtl_read_dword(rtlpriv, REG_BACKDOOR_DBI_RDATA); + rtl_write_dword(rtlpriv, REG_BACKDOOR_DBI_WDATA, + tmp32 | BIT(11) | BIT(12)); + rtl_write_word(rtlpriv, REG_BACKDOOR_DBI_DATA, 0xf718); + rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2, 0x1); + } + tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); + count = 0; + while (tmp8 && count < 20) { + udelay(10); + tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); + count++; + } +} + +void rtl92ee_enable_hw_security_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 sec_reg_value; + u8 tmp; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", + rtlpriv->sec.pairwise_enc_algorithm, + rtlpriv->sec.group_enc_algorithm); + + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "not open hw encryption\n"); + return; + } + + sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; + + if (rtlpriv->sec.use_defaultkey) { + sec_reg_value |= SCR_TXUSEDK; + sec_reg_value |= SCR_RXUSEDK; + } + + sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); + + tmp = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, tmp | BIT(1)); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "The SECR-value %x\n", sec_reg_value); + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); +} + +static bool _rtl8192ee_check_pcie_dma_hang(struct rtl_priv *rtlpriv) +{ + u8 tmp; + + /* write reg 0x350 Bit[26]=1. Enable debug port. */ + tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3); + if (!(tmp & BIT(2))) { + rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3, + tmp | BIT(2)); + mdelay(100); /* Suggested by DD Justin_tsai. */ + } + + /* read reg 0x350 Bit[25] if 1 : RX hang + * read reg 0x350 Bit[24] if 1 : TX hang + */ + tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3); + if ((tmp & BIT(0)) || (tmp & BIT(1))) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "CheckPcieDMAHang8192EE(): true!!\n"); + return true; + } + return false; +} + +static void _rtl8192ee_reset_pcie_interface_dma(struct rtl_priv *rtlpriv, + bool mac_power_on) +{ + u8 tmp; + bool release_mac_rx_pause; + u8 backup_pcie_dma_pause; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "ResetPcieInterfaceDMA8192EE()\n"); + + /* Revise Note: Follow the document "PCIe RX DMA Hang Reset Flow_v03" + * released by SD1 Alan. + */ + + /* 1. disable register write lock + * write 0x1C bit[1:0] = 2'h0 + * write 0xCC bit[2] = 1'b1 + */ + tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL); + tmp &= ~(BIT(1) | BIT(0)); + rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp); + tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); + tmp |= BIT(2); + rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); + + /* 2. Check and pause TRX DMA + * write 0x284 bit[18] = 1'b1 + * write 0x301 = 0xFF + */ + tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + if (tmp & BIT(2)) { + /* Already pause before the function for another reason. */ + release_mac_rx_pause = false; + } else { + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2))); + release_mac_rx_pause = true; + } + + backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1); + if (backup_pcie_dma_pause != 0xFF) + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF); + + if (mac_power_on) { + /* 3. reset TRX function + * write 0x100 = 0x00 + */ + rtl_write_byte(rtlpriv, REG_CR, 0); + } + + /* 4. Reset PCIe DMA + * write 0x003 bit[0] = 0 + */ + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + tmp &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); + + /* 5. Enable PCIe DMA + * write 0x003 bit[0] = 1 + */ + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + tmp |= BIT(0); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); + + if (mac_power_on) { + /* 6. enable TRX function + * write 0x100 = 0xFF + */ + rtl_write_byte(rtlpriv, REG_CR, 0xFF); + + /* We should init LLT & RQPN and + * prepare Tx/Rx descrptor address later + * because MAC function is reset. + */ + } + + /* 7. Restore PCIe autoload down bit + * write 0xF8 bit[17] = 1'b1 + */ + tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2); + tmp |= BIT(1); + rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp); + + /* In MAC power on state, BB and RF maybe in ON state, + * if we release TRx DMA here + * it will cause packets to be started to Tx/Rx, + * so we release Tx/Rx DMA later. + */ + if (!mac_power_on) { + /* 8. release TRX DMA + * write 0x284 bit[18] = 1'b0 + * write 0x301 = 0x00 + */ + if (release_mac_rx_pause) { + tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, + (tmp & (~BIT(2)))); + } + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, + backup_pcie_dma_pause); + } + + /* 9. lock system register + * write 0xCC bit[2] = 1'b0 + */ + tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); + tmp &= ~(BIT(2)); + rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); +} + +int rtl92ee_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool rtstatus = true; + int err = 0; + u8 tmp_u1b, u1byte; + u32 tmp_u4b; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, " Rtl8192EE hw init\n"); + rtlpriv->rtlhal.being_init_adapter = true; + rtlpriv->intf_ops->disable_aspm(hw); + + tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CLKR+1); + u1byte = rtl_read_byte(rtlpriv, REG_CR); + if ((tmp_u1b & BIT(3)) && (u1byte != 0 && u1byte != 0xEA)) { + rtlhal->mac_func_enable = true; + } else { + rtlhal->mac_func_enable = false; + rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_92E; + } + + if (_rtl8192ee_check_pcie_dma_hang(rtlpriv)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "92ee dma hang!\n"); + _rtl8192ee_reset_pcie_interface_dma(rtlpriv, + rtlhal->mac_func_enable); + rtlhal->mac_func_enable = false; + } + + rtstatus = _rtl92ee_init_mac(hw); + + rtl_write_byte(rtlpriv, 0x577, 0x03); + + /*for Crystal 40 Mhz setting */ + rtl_write_byte(rtlpriv, REG_AFE_CTRL4, 0x2A); + rtl_write_byte(rtlpriv, REG_AFE_CTRL4 + 1, 0x00); + rtl_write_byte(rtlpriv, REG_AFE_CTRL2, 0x83); + + /*Forced the antenna b to wifi */ + if (rtlpriv->btcoexist.btc_info.btcoexist == 1) { + rtl_write_byte(rtlpriv, 0x64, 0); + rtl_write_byte(rtlpriv, 0x65, 1); + } + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); + err = 1; + return err; + } + rtlhal->rx_tag = 0; + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, 0x8000); + err = rtl92ee_download_fw(hw, false); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW now..\n"); + err = 1; + rtlhal->fw_ready = false; + return err; + } + rtlhal->fw_ready = true; + /*fw related variable initialize */ + ppsc->fw_current_inpsmode = false; + rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_92E; + rtlhal->fw_clk_change_in_progress = false; + rtlhal->allow_sw_to_change_hwclc = false; + rtlhal->last_hmeboxnum = 0; + + rtl92ee_phy_mac_config(hw); + + rtl92ee_phy_bb_config(hw); + + rtl92ee_phy_rf_config(hw); + + rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, RF90_PATH_A, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, RF90_PATH_B, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtlphy->backup_rf_0x1a = (u32)rtl_get_rfreg(hw, RF90_PATH_A, RF_RX_G1, + RFREG_OFFSET_MASK); + rtlphy->rfreg_chnlval[0] = (rtlphy->rfreg_chnlval[0] & 0xfffff3ff) | + BIT(10) | BIT(11); + + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + + /*---- Set CCK and OFDM Block "ON"----*/ + rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); + + /* Must set this, + * otherwise the rx sensitivity will be very pool. Maddest + */ + rtl_set_rfreg(hw, RF90_PATH_A, 0xB1, RFREG_OFFSET_MASK, 0x54418); + + /*Set Hardware(MAC default setting.)*/ + _rtl92ee_hw_configure(hw); + + rtlhal->mac_func_enable = true; + + rtl_cam_reset_all_entry(hw); + rtl92ee_enable_hw_security_config(hw); + + ppsc->rfpwr_state = ERFON; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); + _rtl92ee_enable_aspm_back_door(hw); + rtlpriv->intf_ops->enable_aspm(hw); + + rtl92ee_bt_hw_init(hw); + + rtlpriv->rtlhal.being_init_adapter = false; + + if (ppsc->rfpwr_state == ERFON) { + if (rtlphy->iqk_initialized) { + rtl92ee_phy_iq_calibrate(hw, true); + } else { + rtl92ee_phy_iq_calibrate(hw, false); + rtlphy->iqk_initialized = true; + } + } + + rtlphy->rfpath_rx_enable[0] = true; + if (rtlphy->rf_type == RF_2T2R) + rtlphy->rfpath_rx_enable[1] = true; + + efuse_one_byte_read(hw, 0x1FA, &tmp_u1b); + if (!(tmp_u1b & BIT(0))) { + rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "PA BIAS path A\n"); + } + + if ((!(tmp_u1b & BIT(1))) && (rtlphy->rf_type == RF_2T2R)) { + rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0F, 0x05); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "PA BIAS path B\n"); + } + + rtl_write_byte(rtlpriv, REG_NAV_UPPER, ((30000 + 127) / 128)); + + /*Fixed LDPC rx hang issue. */ + tmp_u4b = rtl_read_dword(rtlpriv, REG_SYS_SWR_CTRL1); + rtl_write_byte(rtlpriv, REG_SYS_SWR_CTRL2, 0x75); + tmp_u4b = (tmp_u4b & 0xfff00fff) | (0x7E << 12); + rtl_write_dword(rtlpriv, REG_SYS_SWR_CTRL1, tmp_u4b); + + rtl92ee_dm_init(hw); + + rtl_write_dword(rtlpriv, 0x4fc, 0); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "end of Rtl8192EE hw init %x\n", err); + return 0; +} + +static enum version_8192e _rtl92ee_read_chip_version(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + enum version_8192e version = VERSION_UNKNOWN; + u32 value32; + + rtlphy->rf_type = RF_2T2R; + + value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG1); + if (value32 & TRP_VAUX_EN) + version = (enum version_8192e)VERSION_TEST_CHIP_2T2R_8192E; + else + version = (enum version_8192e)VERSION_NORMAL_CHIP_2T2R_8192E; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ? + "RF_2T2R" : "RF_1T1R"); + + return version; +} + +static int _rtl92ee_set_media_status(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_msr = rtl_read_byte(rtlpriv, MSR) & 0xfc; + enum led_ctl_mode ledaction = LED_CTL_NO_LINK; + u8 mode = MSR_NOLINK; + + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + mode = MSR_NOLINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to NO LINK!\n"); + break; + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + mode = MSR_ADHOC; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to Ad Hoc!\n"); + break; + case NL80211_IFTYPE_STATION: + mode = MSR_INFRA; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to STA!\n"); + break; + case NL80211_IFTYPE_AP: + mode = MSR_AP; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to AP!\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Network type %d not support!\n", type); + return 1; + } + + /* MSR_INFRA == Link in infrastructure network; + * MSR_ADHOC == Link in ad hoc network; + * Therefore, check link state is necessary. + * + * MSR_AP == AP mode; link state is not cared here. + */ + if (mode != MSR_AP && rtlpriv->mac80211.link_state < MAC80211_LINKED) { + mode = MSR_NOLINK; + ledaction = LED_CTL_NO_LINK; + } + + if (mode == MSR_NOLINK || mode == MSR_INFRA) { + _rtl92ee_stop_tx_beacon(hw); + _rtl92ee_enable_bcn_sub_func(hw); + } else if (mode == MSR_ADHOC || mode == MSR_AP) { + _rtl92ee_resume_tx_beacon(hw); + _rtl92ee_disable_bcn_sub_func(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", + mode); + } + + rtl_write_byte(rtlpriv, MSR, bt_msr | mode); + rtlpriv->cfg->ops->led_control(hw, ledaction); + if (mode == MSR_AP) + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); + else + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); + return 0; +} + +void rtl92ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 reg_rcr = rtlpci->receive_config; + + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + if (check_bssid) { + reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, + (u8 *)(®_rcr)); + _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); + } else { + reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); + _rtl92ee_set_bcn_ctrl_reg(hw, BIT(4), 0); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, + (u8 *)(®_rcr)); + } +} + +int rtl92ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (_rtl92ee_set_media_status(hw, type)) + return -EOPNOTSUPP; + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP && + type != NL80211_IFTYPE_MESH_POINT) + rtl92ee_set_check_bssid(hw, true); + } else { + rtl92ee_set_check_bssid(hw, false); + } + + return 0; +} + +/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ +void rtl92ee_set_qos(struct ieee80211_hw *hw, int aci) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl92ee_dm_init_edca_turbo(hw); + switch (aci) { + case AC1_BK: + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); + break; + case AC0_BE: + /* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); */ + break; + case AC2_VI: + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); + break; + case AC3_VO: + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); + break; + default: + RT_ASSERT(false, "invalid aci: %d !\n", aci); + break; + } +} + +void rtl92ee_enable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); + rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); + rtlpci->irq_enabled = true; +} + +void rtl92ee_disable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED); + rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED); + rtlpci->irq_enabled = false; + /*synchronize_irq(rtlpci->pdev->irq);*/ +} + +static void _rtl92ee_poweroff_adapter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 u1b_tmp; + + rtlhal->mac_func_enable = false; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "POWER OFF adapter\n"); + + /* Run LPS WL RFOFF flow */ + rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, RTL8192E_NIC_LPS_ENTER_FLOW); + /* turn off RF */ + rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); + + /* ==== Reset digital sequence ====== */ + if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready) + rtl92ee_firmware_selfreset(hw); + + /* Reset MCU */ + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); + + /* reset MCU ready status */ + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); + + /* HW card disable configuration. */ + rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, RTL8192E_NIC_DISABLE_FLOW); + + /* Reset MCU IO Wrapper */ + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0))); + + /* lock ISO/CLK/Power control register */ + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E); +} + +void rtl92ee_card_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + enum nl80211_iftype opmode; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RTL8192ee card disable\n"); + + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + + mac->link_state = MAC80211_NOLINK; + opmode = NL80211_IFTYPE_UNSPECIFIED; + + _rtl92ee_set_media_status(hw, opmode); + + if (rtlpriv->rtlhal.driver_is_goingto_unload || + ppsc->rfoff_reason > RF_CHANGE_BY_PS) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + + _rtl92ee_poweroff_adapter(hw); + + /* after power off we should do iqk again */ + rtlpriv->phy.iqk_initialized = false; +} + +void rtl92ee_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; + rtl_write_dword(rtlpriv, ISR, *p_inta); + + *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; + rtl_write_dword(rtlpriv, REG_HISRE, *p_intb); +} + +void rtl92ee_set_beacon_related_registers(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u16 bcn_interval, atim_window; + + bcn_interval = mac->beacon_interval; + atim_window = 2; /*FIX MERGE */ + rtl92ee_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); + rtl_write_byte(rtlpriv, 0x606, 0x30); + rtlpci->reg_bcn_ctrl_val |= BIT(3); + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); +} + +void rtl92ee_set_beacon_interval(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval = mac->beacon_interval; + + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "beacon_interval:%d\n", bcn_interval); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); +} + +void rtl92ee_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, + "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); + + if (add_msr) + rtlpci->irq_mask[0] |= add_msr; + if (rm_msr) + rtlpci->irq_mask[0] &= (~rm_msr); + rtl92ee_disable_interrupt(hw); + rtl92ee_enable_interrupt(hw); +} + +static u8 _rtl92ee_get_chnl_group(u8 chnl) +{ + u8 group = 0; + + if (chnl <= 14) { + if (1 <= chnl && chnl <= 2) + group = 0; + else if (3 <= chnl && chnl <= 5) + group = 1; + else if (6 <= chnl && chnl <= 8) + group = 2; + else if (9 <= chnl && chnl <= 11) + group = 3; + else if (12 <= chnl && chnl <= 14) + group = 4; + } else { + if (36 <= chnl && chnl <= 42) + group = 0; + else if (44 <= chnl && chnl <= 48) + group = 1; + else if (50 <= chnl && chnl <= 58) + group = 2; + else if (60 <= chnl && chnl <= 64) + group = 3; + else if (100 <= chnl && chnl <= 106) + group = 4; + else if (108 <= chnl && chnl <= 114) + group = 5; + else if (116 <= chnl && chnl <= 122) + group = 6; + else if (124 <= chnl && chnl <= 130) + group = 7; + else if (132 <= chnl && chnl <= 138) + group = 8; + else if (140 <= chnl && chnl <= 144) + group = 9; + else if (149 <= chnl && chnl <= 155) + group = 10; + else if (157 <= chnl && chnl <= 161) + group = 11; + else if (165 <= chnl && chnl <= 171) + group = 12; + else if (173 <= chnl && chnl <= 177) + group = 13; + } + return group; +} + +static void _rtl8192ee_read_power_value_fromprom(struct ieee80211_hw *hw, + struct txpower_info_2g *pwr2g, + struct txpower_info_5g *pwr5g, + bool autoload_fail, u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 rf, addr = EEPROM_TX_PWR_INX, group, i = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "hal_ReadPowerValueFromPROM92E(): PROMContent[0x%x]=0x%x\n", + (addr + 1), hwinfo[addr + 1]); + if (0xFF == hwinfo[addr+1]) /*YJ,add,120316*/ + autoload_fail = true; + + if (autoload_fail) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "auto load fail : Use Default value!\n"); + for (rf = 0 ; rf < MAX_RF_PATH ; rf++) { + /* 2.4G default value */ + for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { + pwr2g->index_cck_base[rf][group] = 0x2D; + pwr2g->index_bw40_base[rf][group] = 0x2D; + } + for (i = 0; i < MAX_TX_COUNT; i++) { + if (i == 0) { + pwr2g->bw20_diff[rf][0] = 0x02; + pwr2g->ofdm_diff[rf][0] = 0x04; + } else { + pwr2g->bw20_diff[rf][i] = 0xFE; + pwr2g->bw40_diff[rf][i] = 0xFE; + pwr2g->cck_diff[rf][i] = 0xFE; + pwr2g->ofdm_diff[rf][i] = 0xFE; + } + } + + /*5G default value*/ + for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) + pwr5g->index_bw40_base[rf][group] = 0x2A; + + for (i = 0; i < MAX_TX_COUNT; i++) { + if (i == 0) { + pwr5g->ofdm_diff[rf][0] = 0x04; + pwr5g->bw20_diff[rf][0] = 0x00; + pwr5g->bw80_diff[rf][0] = 0xFE; + pwr5g->bw160_diff[rf][0] = 0xFE; + } else { + pwr5g->ofdm_diff[rf][0] = 0xFE; + pwr5g->bw20_diff[rf][0] = 0xFE; + pwr5g->bw40_diff[rf][0] = 0xFE; + pwr5g->bw80_diff[rf][0] = 0xFE; + pwr5g->bw160_diff[rf][0] = 0xFE; + } + } + } + return; + } + + rtl_priv(hw)->efuse.txpwr_fromeprom = true; + + for (rf = 0 ; rf < MAX_RF_PATH ; rf++) { + /*2.4G default value*/ + for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { + pwr2g->index_cck_base[rf][group] = hwinfo[addr++]; + if (pwr2g->index_cck_base[rf][group] == 0xFF) + pwr2g->index_cck_base[rf][group] = 0x2D; + } + for (group = 0 ; group < MAX_CHNL_GROUP_24G - 1; group++) { + pwr2g->index_bw40_base[rf][group] = hwinfo[addr++]; + if (pwr2g->index_bw40_base[rf][group] == 0xFF) + pwr2g->index_bw40_base[rf][group] = 0x2D; + } + for (i = 0; i < MAX_TX_COUNT; i++) { + if (i == 0) { + pwr2g->bw40_diff[rf][i] = 0; + if (hwinfo[addr] == 0xFF) { + pwr2g->bw20_diff[rf][i] = 0x02; + } else { + pwr2g->bw20_diff[rf][i] = (hwinfo[addr] + & 0xf0) >> 4; + if (pwr2g->bw20_diff[rf][i] & BIT(3)) + pwr2g->bw20_diff[rf][i] |= 0xF0; + } + + if (hwinfo[addr] == 0xFF) { + pwr2g->ofdm_diff[rf][i] = 0x04; + } else { + pwr2g->ofdm_diff[rf][i] = (hwinfo[addr] + & 0x0f); + if (pwr2g->ofdm_diff[rf][i] & BIT(3)) + pwr2g->ofdm_diff[rf][i] |= 0xF0; + } + pwr2g->cck_diff[rf][i] = 0; + addr++; + } else { + if (hwinfo[addr] == 0xFF) { + pwr2g->bw40_diff[rf][i] = 0xFE; + } else { + pwr2g->bw40_diff[rf][i] = (hwinfo[addr] + & 0xf0) >> 4; + if (pwr2g->bw40_diff[rf][i] & BIT(3)) + pwr2g->bw40_diff[rf][i] |= 0xF0; + } + + if (hwinfo[addr] == 0xFF) { + pwr2g->bw20_diff[rf][i] = 0xFE; + } else { + pwr2g->bw20_diff[rf][i] = (hwinfo[addr] + & 0x0f); + if (pwr2g->bw20_diff[rf][i] & BIT(3)) + pwr2g->bw20_diff[rf][i] |= 0xF0; + } + addr++; + + if (hwinfo[addr] == 0xFF) { + pwr2g->ofdm_diff[rf][i] = 0xFE; + } else { + pwr2g->ofdm_diff[rf][i] = (hwinfo[addr] + & 0xf0) >> 4; + if (pwr2g->ofdm_diff[rf][i] & BIT(3)) + pwr2g->ofdm_diff[rf][i] |= 0xF0; + } + + if (hwinfo[addr] == 0xFF) { + pwr2g->cck_diff[rf][i] = 0xFE; + } else { + pwr2g->cck_diff[rf][i] = (hwinfo[addr] + & 0x0f); + if (pwr2g->cck_diff[rf][i] & BIT(3)) + pwr2g->cck_diff[rf][i] |= 0xF0; + } + addr++; + } + } + + /*5G default value*/ + for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) { + pwr5g->index_bw40_base[rf][group] = hwinfo[addr++]; + if (pwr5g->index_bw40_base[rf][group] == 0xFF) + pwr5g->index_bw40_base[rf][group] = 0xFE; + } + + for (i = 0; i < MAX_TX_COUNT; i++) { + if (i == 0) { + pwr5g->bw40_diff[rf][i] = 0; + + if (hwinfo[addr] == 0xFF) { + pwr5g->bw20_diff[rf][i] = 0; + } else { + pwr5g->bw20_diff[rf][0] = (hwinfo[addr] + & 0xf0) >> 4; + if (pwr5g->bw20_diff[rf][i] & BIT(3)) + pwr5g->bw20_diff[rf][i] |= 0xF0; + } + + if (hwinfo[addr] == 0xFF) { + pwr5g->ofdm_diff[rf][i] = 0x04; + } else { + pwr5g->ofdm_diff[rf][0] = (hwinfo[addr] + & 0x0f); + if (pwr5g->ofdm_diff[rf][i] & BIT(3)) + pwr5g->ofdm_diff[rf][i] |= 0xF0; + } + addr++; + } else { + if (hwinfo[addr] == 0xFF) { + pwr5g->bw40_diff[rf][i] = 0xFE; + } else { + pwr5g->bw40_diff[rf][i] = (hwinfo[addr] + & 0xf0) >> 4; + if (pwr5g->bw40_diff[rf][i] & BIT(3)) + pwr5g->bw40_diff[rf][i] |= 0xF0; + } + + if (hwinfo[addr] == 0xFF) { + pwr5g->bw20_diff[rf][i] = 0xFE; + } else { + pwr5g->bw20_diff[rf][i] = (hwinfo[addr] + & 0x0f); + if (pwr5g->bw20_diff[rf][i] & BIT(3)) + pwr5g->bw20_diff[rf][i] |= 0xF0; + } + addr++; + } + } + + if (hwinfo[addr] == 0xFF) { + pwr5g->ofdm_diff[rf][1] = 0xFE; + pwr5g->ofdm_diff[rf][2] = 0xFE; + } else { + pwr5g->ofdm_diff[rf][1] = (hwinfo[addr] & 0xf0) >> 4; + pwr5g->ofdm_diff[rf][2] = (hwinfo[addr] & 0x0f); + } + addr++; + + if (hwinfo[addr] == 0xFF) + pwr5g->ofdm_diff[rf][3] = 0xFE; + else + pwr5g->ofdm_diff[rf][3] = (hwinfo[addr] & 0x0f); + addr++; + + for (i = 1; i < MAX_TX_COUNT; i++) { + if (pwr5g->ofdm_diff[rf][i] == 0xFF) + pwr5g->ofdm_diff[rf][i] = 0xFE; + else if (pwr5g->ofdm_diff[rf][i] & BIT(3)) + pwr5g->ofdm_diff[rf][i] |= 0xF0; + } + + for (i = 0; i < MAX_TX_COUNT; i++) { + if (hwinfo[addr] == 0xFF) { + pwr5g->bw80_diff[rf][i] = 0xFE; + } else { + pwr5g->bw80_diff[rf][i] = (hwinfo[addr] & 0xf0) + >> 4; + if (pwr5g->bw80_diff[rf][i] & BIT(3)) + pwr5g->bw80_diff[rf][i] |= 0xF0; + } + + if (hwinfo[addr] == 0xFF) { + pwr5g->bw160_diff[rf][i] = 0xFE; + } else { + pwr5g->bw160_diff[rf][i] = + (hwinfo[addr] & 0x0f); + if (pwr5g->bw160_diff[rf][i] & BIT(3)) + pwr5g->bw160_diff[rf][i] |= 0xF0; + } + addr++; + } + } +} + +static void _rtl92ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *efu = rtl_efuse(rtl_priv(hw)); + struct txpower_info_2g pwr2g; + struct txpower_info_5g pwr5g; + u8 channel5g[CHANNEL_MAX_NUMBER_5G] = { + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, + 56, 58, 60, 62, 64, 100, 102, 104, 106, + 108, 110, 112, 114, 116, 118, 120, 122, + 124, 126, 128, 130, 132, 134, 136, 138, + 140, 142, 144, 149, 151, 153, 155, 157, + 159, 161, 163, 165, 167, 168, 169, 171, + 173, 175, 177 + }; + u8 channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = { + 42, 58, 106, 122, 138, 155, 171 + }; + u8 rf, idx; + u8 i; + + _rtl8192ee_read_power_value_fromprom(hw, &pwr2g, &pwr5g, + autoload_fail, hwinfo); + + for (rf = 0; rf < MAX_RF_PATH; rf++) { + for (i = 0; i < 14; i++) { + idx = _rtl92ee_get_chnl_group(i + 1); + + if (i == CHANNEL_MAX_NUMBER_2G - 1) { + efu->txpwrlevel_cck[rf][i] = + pwr2g.index_cck_base[rf][5]; + efu->txpwrlevel_ht40_1s[rf][i] = + pwr2g.index_bw40_base[rf][idx]; + } else { + efu->txpwrlevel_cck[rf][i] = + pwr2g.index_cck_base[rf][idx]; + efu->txpwrlevel_ht40_1s[rf][i] = + pwr2g.index_bw40_base[rf][idx]; + } + } + for (i = 0; i < CHANNEL_MAX_NUMBER_5G; i++) { + idx = _rtl92ee_get_chnl_group(channel5g[i]); + efu->txpwr_5g_bw40base[rf][i] = + pwr5g.index_bw40_base[rf][idx]; + } + for (i = 0; i < CHANNEL_MAX_NUMBER_5G_80M; i++) { + u8 upper, lower; + + idx = _rtl92ee_get_chnl_group(channel5g_80m[i]); + upper = pwr5g.index_bw40_base[rf][idx]; + lower = pwr5g.index_bw40_base[rf][idx + 1]; + + efu->txpwr_5g_bw80base[rf][i] = (upper + lower) / 2; + } + for (i = 0; i < MAX_TX_COUNT; i++) { + efu->txpwr_cckdiff[rf][i] = pwr2g.cck_diff[rf][i]; + efu->txpwr_legacyhtdiff[rf][i] = pwr2g.ofdm_diff[rf][i]; + efu->txpwr_ht20diff[rf][i] = pwr2g.bw20_diff[rf][i]; + efu->txpwr_ht40diff[rf][i] = pwr2g.bw40_diff[rf][i]; + + efu->txpwr_5g_ofdmdiff[rf][i] = pwr5g.ofdm_diff[rf][i]; + efu->txpwr_5g_bw20diff[rf][i] = pwr5g.bw20_diff[rf][i]; + efu->txpwr_5g_bw40diff[rf][i] = pwr5g.bw40_diff[rf][i]; + efu->txpwr_5g_bw80diff[rf][i] = pwr5g.bw80_diff[rf][i]; + } + } + + if (!autoload_fail) + efu->eeprom_thermalmeter = hwinfo[EEPROM_THERMAL_METER_92E]; + else + efu->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; + + if (efu->eeprom_thermalmeter == 0xff || autoload_fail) { + efu->apk_thermalmeterignore = true; + efu->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; + } + + efu->thermalmeter[0] = efu->eeprom_thermalmeter; + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "thermalmeter = 0x%x\n", efu->eeprom_thermalmeter); + + if (!autoload_fail) { + efu->eeprom_regulatory = hwinfo[EEPROM_RF_BOARD_OPTION_92E] + & 0x07; + if (hwinfo[EEPROM_RF_BOARD_OPTION_92E] == 0xFF) + efu->eeprom_regulatory = 0; + } else { + efu->eeprom_regulatory = 0; + } + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "eeprom_regulatory = 0x%x\n", efu->eeprom_regulatory); +} + +static void _rtl92ee_read_adapter_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u16 i, usvalue; + u8 hwinfo[HWSET_MAX_SIZE]; + u16 eeprom_id; + + if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + rtl_efuse_shadow_map_update(hw); + + memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + HWSET_MAX_SIZE); + } else if (rtlefuse->epromtype == EEPROM_93C46) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "RTL819X Not boot from eeprom, check it !!"); + return; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "boot from neither eeprom nor efuse, check it !!"); + return; + } + + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP\n", + hwinfo, HWSET_MAX_SIZE); + + eeprom_id = *((u16 *)&hwinfo[0]); + if (eeprom_id != RTL8192E_EEPROM_ID) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "EEPROM ID(%#x) is invalid!!\n", eeprom_id); + rtlefuse->autoload_failflag = true; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + } + + if (rtlefuse->autoload_failflag) + return; + /*VID DID SVID SDID*/ + rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; + rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; + rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; + rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROMId = 0x%4x\n", eeprom_id); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); + /*customer ID*/ + rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID]; + if (rtlefuse->eeprom_oemid == 0xFF) + rtlefuse->eeprom_oemid = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); + /*EEPROM version*/ + rtlefuse->eeprom_version = *(u8 *)&hwinfo[EEPROM_VERSION]; + /*mac address*/ + for (i = 0; i < 6; i += 2) { + usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; + *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "dev_addr: %pM\n", rtlefuse->dev_addr); + /*channel plan */ + rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; + /* set channel plan from efuse */ + rtlefuse->channel_plan = rtlefuse->eeprom_channelplan; + /*tx power*/ + _rtl92ee_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, + hwinfo); + + rtl92ee_read_bt_coexist_info_from_hwpg(hw, rtlefuse->autoload_failflag, + hwinfo); + + /*board type*/ + rtlefuse->board_type = (((*(u8 *)&hwinfo[EEPROM_RF_BOARD_OPTION_92E]) + & 0xE0) >> 5); + if ((*(u8 *)&hwinfo[EEPROM_RF_BOARD_OPTION_92E]) == 0xFF) + rtlefuse->board_type = 0; + + rtlhal->board_type = rtlefuse->board_type; + /*parse xtal*/ + rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_92E]; + if (hwinfo[EEPROM_XTAL_92E] == 0xFF) + rtlefuse->crystalcap = 0x20; + + /*antenna diversity*/ + rtlefuse->antenna_div_type = NO_ANTDIV; + rtlefuse->antenna_div_cfg = 0; + + if (rtlhal->oem_id == RT_CID_DEFAULT) { + switch (rtlefuse->eeprom_oemid) { + case EEPROM_CID_DEFAULT: + if (rtlefuse->eeprom_did == 0x818B) { + if ((rtlefuse->eeprom_svid == 0x10EC) && + (rtlefuse->eeprom_smid == 0x001B)) + rtlhal->oem_id = RT_CID_819X_LENOVO; + } else { + rtlhal->oem_id = RT_CID_DEFAULT; + } + break; + default: + rtlhal->oem_id = RT_CID_DEFAULT; + break; + } + } +} + +static void _rtl92ee_hal_customized_behavior(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + pcipriv->ledctl.led_opendrain = true; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "RT Customized ID: 0x%02X\n", rtlhal->oem_id); +} + +void rtl92ee_read_eeprom_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_u1b; + + rtlhal->version = _rtl92ee_read_chip_version(hw); + if (get_rf_type(rtlphy) == RF_1T1R) { + rtlpriv->dm.rfpath_rxenable[0] = true; + } else { + rtlpriv->dm.rfpath_rxenable[0] = true; + rtlpriv->dm.rfpath_rxenable[1] = true; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", + rtlhal->version); + tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); + if (tmp_u1b & BIT(4)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); + rtlefuse->epromtype = EEPROM_93C46; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); + rtlefuse->epromtype = EEPROM_BOOT_EFUSE; + } + if (tmp_u1b & BIT(5)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + _rtl92ee_read_adapter_info(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); + } + _rtl92ee_hal_customized_behavior(hw); + + rtlphy->rfpath_rx_enable[0] = true; + if (rtlphy->rf_type == RF_2T2R) + rtlphy->rfpath_rx_enable[1] = true; +} + +static u8 _rtl92ee_mrate_idx_to_arfr_id(struct ieee80211_hw *hw, u8 rate_index) +{ + u8 ret = 0; + + switch (rate_index) { + case RATR_INX_WIRELESS_NGB: + ret = 0; + break; + case RATR_INX_WIRELESS_N: + case RATR_INX_WIRELESS_NG: + ret = 4; + break; + case RATR_INX_WIRELESS_NB: + ret = 2; + break; + case RATR_INX_WIRELESS_GB: + ret = 6; + break; + case RATR_INX_WIRELESS_G: + ret = 7; + break; + case RATR_INX_WIRELESS_B: + ret = 8; + break; + default: + ret = 0; + break; + } + return ret; +} + +static void rtl92ee_update_hal_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u32 ratr_bitmap; + u8 ratr_index; + u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) + ? 1 : 0; + u8 b_curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 b_curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = 0; + bool b_shortgi = false; + u8 rate_mask[7] = {0}; + u8 macid = 0; + /*u8 mimo_ps = IEEE80211_SMPS_OFF;*/ + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + wirelessmode = sta_entry->wireless_mode; + if (mac->opmode == NL80211_IFTYPE_STATION || + mac->opmode == NL80211_IFTYPE_MESH_POINT) + curtxbw_40mhz = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + macid = sta->aid + 1; + + ratr_bitmap = sta->supp_rates[0]; + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_bitmap = 0xfff; + + ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + + switch (wirelessmode) { + case WIRELESS_MODE_B: + ratr_index = RATR_INX_WIRELESS_B; + if (ratr_bitmap & 0x0000000c) + ratr_bitmap &= 0x0000000d; + else + ratr_bitmap &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_index = RATR_INX_WIRELESS_GB; + + if (rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if (rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + break; + case WIRELESS_MODE_N_24G: + if (curtxbw_40mhz) + ratr_index = RATR_INX_WIRELESS_NGB; + else + ratr_index = RATR_INX_WIRELESS_NB; + + if (rtlphy->rf_type == RF_1T1R) { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff005; + } + } else { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x0f8f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0ffff000; + else + ratr_bitmap &= 0x0ffff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x0f8f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0ffff000; + else + ratr_bitmap &= 0x0ffff005; + } + } + + if ((curtxbw_40mhz && b_curshortgi_40mhz) || + (!curtxbw_40mhz && b_curshortgi_20mhz)) { + if (macid == 0) + b_shortgi = true; + else if (macid == 1) + b_shortgi = false; + } + break; + default: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rtlphy->rf_type == RF_1T1R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0f8ff0ff; + break; + } + ratr_index = _rtl92ee_mrate_idx_to_arfr_id(hw, ratr_index); + sta_entry->ratr_index = ratr_index; + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "ratr_bitmap :%x\n", ratr_bitmap); + *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | + (ratr_index << 28); + rate_mask[0] = macid; + rate_mask[1] = ratr_index | (b_shortgi ? 0x80 : 0x00); + rate_mask[2] = curtxbw_40mhz; + rate_mask[3] = (u8)(ratr_bitmap & 0x000000ff); + rate_mask[4] = (u8)((ratr_bitmap & 0x0000ff00) >> 8); + rate_mask[5] = (u8)((ratr_bitmap & 0x00ff0000) >> 16); + rate_mask[6] = (u8)((ratr_bitmap & 0xff000000) >> 24); + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x:%x:%x\n", + ratr_index, ratr_bitmap, rate_mask[0], rate_mask[1], + rate_mask[2], rate_mask[3], rate_mask[4], + rate_mask[5], rate_mask[6]); + rtl92ee_fill_h2c_cmd(hw, H2C_92E_RA_MASK, 7, rate_mask); + _rtl92ee_set_bcn_ctrl_reg(hw, BIT(3), 0); +} + +void rtl92ee_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->dm.useramask) + rtl92ee_update_hal_rate_mask(hw, sta, rssi_level); +} + +void rtl92ee_update_channel_access_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 sifs_timer; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, + (u8 *)&mac->slot_time); + if (!mac->ht_enable) + sifs_timer = 0x0a0a; + else + sifs_timer = 0x0e0e; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); +} + +bool rtl92ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) +{ + *valid = 1; + return true; +} + +void rtl92ee_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 *macaddr = p_macaddr; + u32 entry_id = 0; + bool is_pairwise = false; + + static u8 cam_const_addr[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} + }; + static u8 cam_const_broad[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (clear_all) { + u8 idx = 0; + u8 cam_offset = 0; + u8 clear_number = 5; + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); + + for (idx = 0; idx < clear_number; idx++) { + rtl_cam_mark_invalid(hw, cam_offset + idx); + rtl_cam_empty_entry(hw, cam_offset + idx); + + if (idx < 5) { + memset(rtlpriv->sec.key_buf[idx], 0, + MAX_KEY_LEN); + rtlpriv->sec.key_len[idx] = 0; + } + } + + } else { + switch (enc_algo) { + case WEP40_ENCRYPTION: + enc_algo = CAM_WEP40; + break; + case WEP104_ENCRYPTION: + enc_algo = CAM_WEP104; + break; + case TKIP_ENCRYPTION: + enc_algo = CAM_TKIP; + break; + case AESCCMP_ENCRYPTION: + enc_algo = CAM_AES; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, + "switch case not process\n"); + enc_algo = CAM_TKIP; + break; + } + + if (is_wepkey || rtlpriv->sec.use_defaultkey) { + macaddr = cam_const_addr[key_index]; + entry_id = key_index; + } else { + if (is_group) { + macaddr = cam_const_broad; + entry_id = key_index; + } else { + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + entry_id = rtl_cam_get_free_entry(hw, + p_macaddr); + if (entry_id >= TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, COMP_SEC, + DBG_EMERG, + "Can not find free hw security cam entry\n"); + return; + } + } else { + entry_id = CAM_PAIRWISE_KEY_POSITION; + } + + key_index = PAIRWISE_KEYIDX; + is_pairwise = true; + } + } + + if (rtlpriv->sec.key_len[key_index] == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "delete one entry, entry_id is %d\n", + entry_id); + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_MESH_POINT) + rtl_cam_del_entry(hw, p_macaddr); + rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "add one entry\n"); + if (is_pairwise) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set Pairwiase key\n"); + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[key_index]); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set group key\n"); + + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_cam_add_one_entry(hw, + rtlefuse->dev_addr, + PAIRWISE_KEYIDX, + CAM_PAIRWISE_KEY_POSITION, + enc_algo, CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + } + } +} + +void rtl92ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool auto_load_fail, u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 value; + + if (!auto_load_fail) { + value = hwinfo[EEPROM_RF_BOARD_OPTION_92E]; + if (((value & 0xe0) >> 5) == 0x1) + rtlpriv->btcoexist.btc_info.btcoexist = 1; + else + rtlpriv->btcoexist.btc_info.btcoexist = 0; + + rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8192E; + rtlpriv->btcoexist.btc_info.ant_num = ANT_TOTAL_X2; + } else { + rtlpriv->btcoexist.btc_info.btcoexist = 1; + rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8192E; + rtlpriv->btcoexist.btc_info.ant_num = ANT_TOTAL_X1; + } +} + +void rtl92ee_bt_reg_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* 0:Low, 1:High, 2:From Efuse. */ + rtlpriv->btcoexist.reg_bt_iso = 2; + /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ + rtlpriv->btcoexist.reg_bt_sco = 3; + /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ + rtlpriv->btcoexist.reg_bt_sco = 0; +} + +void rtl92ee_bt_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_init_hw_config(rtlpriv); +} + +void rtl92ee_suspend(struct ieee80211_hw *hw) +{ +} + +void rtl92ee_resume(struct ieee80211_hw *hw) +{ +} + +/* Turn on AAP (RCR:bit 0) for promicuous mode. */ +void rtl92ee_allow_all_destaddr(struct ieee80211_hw *hw, + bool allow_all_da, bool write_into_reg) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + if (allow_all_da) /* Set BIT0 */ + rtlpci->receive_config |= RCR_AAP; + else /* Clear BIT0 */ + rtlpci->receive_config &= ~RCR_AAP; + + if (write_into_reg) + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + + RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, + "receive_config=0x%08X, write_into_reg=%d\n", + rtlpci->receive_config, write_into_reg); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h new file mode 100644 index 000000000000..05413f189685 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/hw.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92E_HW_H__ +#define __RTL92E_HW_H__ + +void rtl92ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl92ee_read_eeprom_info(struct ieee80211_hw *hw); +void rtl92ee_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb); +int rtl92ee_hw_init(struct ieee80211_hw *hw); +void rtl92ee_card_disable(struct ieee80211_hw *hw); +void rtl92ee_enable_interrupt(struct ieee80211_hw *hw); +void rtl92ee_disable_interrupt(struct ieee80211_hw *hw); +int rtl92ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); +void rtl92ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); +void rtl92ee_set_qos(struct ieee80211_hw *hw, int aci); +void rtl92ee_set_beacon_related_registers(struct ieee80211_hw *hw); +void rtl92ee_set_beacon_interval(struct ieee80211_hw *hw); +void rtl92ee_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); +void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl92ee_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); +void rtl92ee_update_channel_access_setting(struct ieee80211_hw *hw); +bool rtl92ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); +void rtl92ee_enable_hw_security_config(struct ieee80211_hw *hw); +void rtl92ee_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all); +void rtl92ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo); +void rtl92ee_bt_reg_init(struct ieee80211_hw *hw); +void rtl92ee_bt_hw_init(struct ieee80211_hw *hw); +void rtl92ee_suspend(struct ieee80211_hw *hw); +void rtl92ee_resume(struct ieee80211_hw *hw); +void rtl92ee_allow_all_destaddr(struct ieee80211_hw *hw, bool allow_all_da, + bool write_into_reg); +void rtl92ee_fw_clk_off_timer_callback(unsigned long data); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c new file mode 100644 index 000000000000..8388e371c8e2 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.c @@ -0,0 +1,145 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "reg.h" +#include "led.h" + +static void _rtl92ee_init_led(struct ieee80211_hw *hw, + struct rtl_led *pled, enum rtl_led_pin ledpin) +{ + pled->hw = hw; + pled->ledpin = ledpin; + pled->ledon = false; +} + +void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u32 ledcfg; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg = rtl_read_dword(rtlpriv , REG_GPIO_PIN_CTRL); + ledcfg &= ~BIT(13); + ledcfg |= BIT(21); + ledcfg &= ~BIT(29); + + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, ledcfg); + + break; + case LED_PIN_LED1: + + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + pled->ledon = true; +} + +void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 ledcfg; + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + + ledcfg = rtl_read_dword(rtlpriv , REG_GPIO_PIN_CTRL); + ledcfg |= ~BIT(21); + ledcfg &= ~BIT(29); + rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, ledcfg); + + break; + case LED_PIN_LED1: + + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + pled->ledon = false; +} + +void rtl92ee_init_sw_leds(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + + _rtl92ee_init_led(hw, &pcipriv->ledctl.sw_led0, LED_PIN_LED0); + _rtl92ee_init_led(hw, &pcipriv->ledctl.sw_led1, LED_PIN_LED1); +} + +static void _rtl92ee_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &pcipriv->ledctl.sw_led0; + + switch (ledaction) { + case LED_CTL_POWER_ON: + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + rtl92ee_sw_led_on(hw, pLed0); + break; + case LED_CTL_POWER_OFF: + rtl92ee_sw_led_off(hw, pLed0); + break; + default: + break; + } +} + +void rtl92ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && + (ledaction == LED_CTL_TX || + ledaction == LED_CTL_RX || + ledaction == LED_CTL_SITE_SURVEY || + ledaction == LED_CTL_LINK || + ledaction == LED_CTL_NO_LINK || + ledaction == LED_CTL_START_TO_LINK || + ledaction == LED_CTL_POWER_ON)) { + return; + } + RT_TRACE(rtlpriv, COMP_LED, DBG_TRACE, "ledaction %d,\n", ledaction); + _rtl92ee_sw_led_control(hw, ledaction); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h new file mode 100644 index 000000000000..8ef640a2ef7f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/led.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92E_LED_H__ +#define __RTL92E_LED_H__ + +void rtl92ee_init_sw_leds(struct ieee80211_hw *hw); +void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c new file mode 100644 index 000000000000..018340aedf09 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c @@ -0,0 +1,3219 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../ps.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "table.h" + +static u32 _rtl92ee_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +static void _rtl92ee_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +static u32 _rtl92ee_phy_calculate_bit_shift(u32 bitmask); +static bool _rtl92ee_phy_bb8192ee_config_parafile(struct ieee80211_hw *hw); +static bool _rtl92ee_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); +static bool phy_config_bb_with_hdr_file(struct ieee80211_hw *hw, + u8 configtype); +static bool phy_config_bb_with_pghdrfile(struct ieee80211_hw *hw, + u8 configtype); +static void phy_init_bb_rf_register_def(struct ieee80211_hw *hw); +static bool _rtl92ee_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, + enum swchnlcmd_id cmdid, + u32 para1, u32 para2, + u32 msdelay); +static bool _rtl92ee_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, + u8 *step, u32 *delay); +static long _rtl92ee_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u8 txpwridx); +static void rtl92ee_phy_set_rf_on(struct ieee80211_hw *hw); +static void rtl92ee_phy_set_io(struct ieee80211_hw *hw); + +u32 rtl92ee_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 returnvalue, originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask); + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask); + returnvalue = (originalvalue & bitmask) >> bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "BBR MASK=0x%x Addr[0x%x]=0x%x\n", + bitmask, regaddr, originalvalue); + + return returnvalue; +} + +void rtl92ee_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, + u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); + + if (bitmask != MASKDWORD) { + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask); + data = ((originalvalue & (~bitmask)) | (data << bitshift)); + } + + rtl_write_dword(rtlpriv, regaddr, data); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); +} + +u32 rtl92ee_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, readback_value, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", + regaddr, rfpath, bitmask); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + original_value = _rtl92ee_phy_rf_serial_read(hw , rfpath, regaddr); + bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask); + readback_value = (original_value & bitmask) >> bitshift; + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x),rfpath(%#x),bitmask(%#x),original_value(%#x)\n", + regaddr, rfpath, bitmask, original_value); + + return readback_value; +} + +void rtl92ee_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 addr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + addr, bitmask, data, rfpath); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + if (bitmask != RFREG_OFFSET_MASK) { + original_value = _rtl92ee_phy_rf_serial_read(hw, rfpath, addr); + bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask); + data = (original_value & (~bitmask)) | (data << bitshift); + } + + _rtl92ee_phy_rf_serial_write(hw, rfpath, addr, data); + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + addr, bitmask, data, rfpath); +} + +static u32 _rtl92ee_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + u32 newoffset; + u32 tmplong, tmplong2; + u8 rfpi_enable = 0; + u32 retvalue; + + offset &= 0xff; + newoffset = offset; + if (RT_CANNOT_IO(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n"); + return 0xFFFFFFFF; + } + tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); + if (rfpath == RF90_PATH_A) + tmplong2 = tmplong; + else + tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); + tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | + (newoffset << 23) | BLSSIREADEDGE; + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, + tmplong & (~BLSSIREADEDGE)); + mdelay(1); + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); + mdelay(2); + if (rfpath == RF90_PATH_A) + rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, + BIT(8)); + else if (rfpath == RF90_PATH_B) + rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, + BIT(8)); + if (rfpi_enable) + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, + BLSSIREADBACKDATA); + else + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, + BLSSIREADBACKDATA); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "RFR-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf_rb, retvalue); + return retvalue; +} + +static void _rtl92ee_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data) +{ + u32 data_and_addr; + u32 newoffset; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + + if (RT_CANNOT_IO(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n"); + return; + } + offset &= 0xff; + newoffset = offset; + data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; + rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "RFW-%d Addr[0x%x]=0x%x\n", rfpath, + pphyreg->rf3wire_offset, data_and_addr); +} + +static u32 _rtl92ee_phy_calculate_bit_shift(u32 bitmask) +{ + u32 i; + + for (i = 0; i <= 31; i++) { + if (((bitmask >> i) & 0x1) == 1) + break; + } + return i; +} + +bool rtl92ee_phy_mac_config(struct ieee80211_hw *hw) +{ + return _rtl92ee_phy_config_mac_with_headerfile(hw); +} + +bool rtl92ee_phy_bb_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool rtstatus = true; + u16 regval; + u32 tmp; + u8 crystal_cap; + + phy_init_bb_rf_register_def(hw); + regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, + regval | BIT(13) | BIT(0) | BIT(1)); + + rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, + FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | + FEN_BB_GLB_RSTN | FEN_BBRSTB); + + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); + + tmp = rtl_read_dword(rtlpriv, 0x4c); + rtl_write_dword(rtlpriv, 0x4c, tmp | BIT(23)); + + rtstatus = _rtl92ee_phy_bb8192ee_config_parafile(hw); + + crystal_cap = rtlpriv->efuse.eeprom_crystalcap & 0x3F; + rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, + (crystal_cap | (crystal_cap << 6))); + return rtstatus; +} + +bool rtl92ee_phy_rf_config(struct ieee80211_hw *hw) +{ + return rtl92ee_phy_rf6052_config(hw); +} + +static bool _check_condition(struct ieee80211_hw *hw, + const u32 condition) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 _board = rtlefuse->board_type; /*need efuse define*/ + u32 _interface = rtlhal->interface; + u32 _platform = 0x08;/*SupportPlatform */ + u32 cond = condition; + + if (condition == 0xCDCDCDCD) + return true; + + cond = condition & 0xFF; + if ((_board != cond) && (cond != 0xFF)) + return false; + + cond = condition & 0xFF00; + cond = cond >> 8; + if ((_interface & cond) == 0 && cond != 0x07) + return false; + + cond = condition & 0xFF0000; + cond = cond >> 16; + if ((_platform & cond) == 0 && cond != 0x0F) + return false; + + return true; +} + +static void _rtl92ee_config_rf_reg(struct ieee80211_hw *hw, u32 addr, u32 data, + enum radio_path rfpath, u32 regaddr) +{ + if (addr == 0xfe || addr == 0xffe) { + mdelay(50); + } else { + rtl_set_rfreg(hw, rfpath, regaddr, RFREG_OFFSET_MASK, data); + udelay(1); + + if (addr == 0xb6) { + u32 getvalue; + u8 count = 0; + + getvalue = rtl_get_rfreg(hw, rfpath, addr, MASKDWORD); + udelay(1); + + while ((getvalue >> 8) != (data >> 8)) { + count++; + rtl_set_rfreg(hw, rfpath, regaddr, + RFREG_OFFSET_MASK, data); + udelay(1); + getvalue = rtl_get_rfreg(hw, rfpath, addr, + MASKDWORD); + if (count > 5) + break; + } + } + + if (addr == 0xb2) { + u32 getvalue; + u8 count = 0; + + getvalue = rtl_get_rfreg(hw, rfpath, addr, MASKDWORD); + udelay(1); + + while (getvalue != data) { + count++; + rtl_set_rfreg(hw, rfpath, regaddr, + RFREG_OFFSET_MASK, data); + udelay(1); + rtl_set_rfreg(hw, rfpath, 0x18, + RFREG_OFFSET_MASK, 0x0fc07); + udelay(1); + getvalue = rtl_get_rfreg(hw, rfpath, addr, + MASKDWORD); + if (count > 5) + break; + } + } + } +} + +static void _rtl92ee_config_rf_radio_a(struct ieee80211_hw *hw, + u32 addr, u32 data) +{ + u32 content = 0x1000; /*RF Content: radio_a_txt*/ + u32 maskforphyset = (u32)(content & 0xE000); + + _rtl92ee_config_rf_reg(hw, addr, data, RF90_PATH_A, + addr | maskforphyset); +} + +static void _rtl92ee_config_rf_radio_b(struct ieee80211_hw *hw, + u32 addr, u32 data) +{ + u32 content = 0x1001; /*RF Content: radio_b_txt*/ + u32 maskforphyset = (u32)(content & 0xE000); + + _rtl92ee_config_rf_reg(hw, addr, data, RF90_PATH_B, + addr | maskforphyset); +} + +static void _rtl92ee_config_bb_reg(struct ieee80211_hw *hw, + u32 addr, u32 data) +{ + if (addr == 0xfe) + mdelay(50); + else if (addr == 0xfd) + mdelay(5); + else if (addr == 0xfc) + mdelay(1); + else if (addr == 0xfb) + udelay(50); + else if (addr == 0xfa) + udelay(5); + else if (addr == 0xf9) + udelay(1); + else + rtl_set_bbreg(hw, addr, MASKDWORD , data); + + udelay(1); +} + +static void _rtl92ee_phy_init_tx_power_by_rate(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + u8 band = BAND_ON_2_4G, rf = 0, txnum = 0, sec = 0; + + for (; band <= BAND_ON_5G; ++band) + for (; rf < TX_PWR_BY_RATE_NUM_RF; ++rf) + for (; txnum < TX_PWR_BY_RATE_NUM_RF; ++txnum) + for (; sec < TX_PWR_BY_RATE_NUM_SECTION; ++sec) + rtlphy->tx_power_by_rate_offset + [band][rf][txnum][sec] = 0; +} + +static void _rtl92ee_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw, + u8 band, u8 path, + u8 rate_section, u8 txnum, + u8 value) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + if (path > RF90_PATH_D) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid Rf Path %d\n", path); + return; + } + + if (band == BAND_ON_2_4G) { + switch (rate_section) { + case CCK: + rtlphy->txpwr_by_rate_base_24g[path][txnum][0] = value; + break; + case OFDM: + rtlphy->txpwr_by_rate_base_24g[path][txnum][1] = value; + break; + case HT_MCS0_MCS7: + rtlphy->txpwr_by_rate_base_24g[path][txnum][2] = value; + break; + case HT_MCS8_MCS15: + rtlphy->txpwr_by_rate_base_24g[path][txnum][3] = value; + break; + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid RateSection %d in 2.4G,Rf %d,%dTx\n", + rate_section, path, txnum); + break; + } + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid Band %d\n", band); + } +} + +static u8 _rtl92ee_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw, + u8 band, u8 path, u8 txnum, + u8 rate_section) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 value = 0; + + if (path > RF90_PATH_D) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid Rf Path %d\n", path); + return 0; + } + + if (band == BAND_ON_2_4G) { + switch (rate_section) { + case CCK: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][0]; + break; + case OFDM: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][1]; + break; + case HT_MCS0_MCS7: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][2]; + break; + case HT_MCS8_MCS15: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][3]; + break; + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid RateSection %d in 2.4G,Rf %d,%dTx\n", + rate_section, path, txnum); + break; + } + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid Band %d()\n", band); + } + return value; +} + +static void _rtl92ee_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u16 raw = 0; + u8 base = 0, path = 0; + + for (path = RF90_PATH_A; path <= RF90_PATH_B; ++path) { + if (path == RF90_PATH_A) { + raw = (u16)(rtlphy->tx_power_by_rate_offset + [BAND_ON_2_4G][path][RF_1TX][3] >> 24) & + 0xFF; + base = (raw >> 4) * 10 + (raw & 0xF); + _rtl92ee_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, + path, CCK, RF_1TX, + base); + } else if (path == RF90_PATH_B) { + raw = (u16)(rtlphy->tx_power_by_rate_offset + [BAND_ON_2_4G][path][RF_1TX][3] >> 0) & + 0xFF; + base = (raw >> 4) * 10 + (raw & 0xF); + _rtl92ee_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, + path, CCK, RF_1TX, + base); + } + raw = (u16)(rtlphy->tx_power_by_rate_offset + [BAND_ON_2_4G][path][RF_1TX][1] >> 24) & 0xFF; + base = (raw >> 4) * 10 + (raw & 0xF); + _rtl92ee_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, + OFDM, RF_1TX, base); + + raw = (u16)(rtlphy->tx_power_by_rate_offset + [BAND_ON_2_4G][path][RF_1TX][5] >> 24) & 0xFF; + base = (raw >> 4) * 10 + (raw & 0xF); + _rtl92ee_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, + HT_MCS0_MCS7, RF_1TX, + base); + + raw = (u16)(rtlphy->tx_power_by_rate_offset + [BAND_ON_2_4G][path][RF_2TX][7] >> 24) & 0xFF; + base = (raw >> 4) * 10 + (raw & 0xF); + _rtl92ee_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, + HT_MCS8_MCS15, RF_2TX, + base); + } +} + +static void _phy_convert_txpower_dbm_to_relative_value(u32 *data, u8 start, + u8 end, u8 base) +{ + char i = 0; + u8 tmp = 0; + u32 temp_data = 0; + + for (i = 3; i >= 0; --i) { + if (i >= start && i <= end) { + /* Get the exact value */ + tmp = (u8)(*data >> (i * 8)) & 0xF; + tmp += ((u8)((*data >> (i * 8 + 4)) & 0xF)) * 10; + + /* Change the value to a relative value */ + tmp = (tmp > base) ? tmp - base : base - tmp; + } else { + tmp = (u8)(*data >> (i * 8)) & 0xFF; + } + temp_data <<= 8; + temp_data |= tmp; + } + *data = temp_data; +} + +static void phy_convert_txpwr_dbm_to_rel_val(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 base = 0, rf = 0, band = BAND_ON_2_4G; + + for (rf = RF90_PATH_A; rf <= RF90_PATH_B; ++rf) { + if (rf == RF90_PATH_A) { + base = _rtl92ee_phy_get_txpower_by_rate_base(hw, band, + rf, RF_1TX, + CCK); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset + [band][rf][RF_1TX][2], + 1, 1, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset + [band][rf][RF_1TX][3], + 1, 3, base); + } else if (rf == RF90_PATH_B) { + base = _rtl92ee_phy_get_txpower_by_rate_base(hw, band, + rf, RF_1TX, + CCK); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset + [band][rf][RF_1TX][3], + 0, 0, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset + [band][rf][RF_1TX][2], + 1, 3, base); + } + base = _rtl92ee_phy_get_txpower_by_rate_base(hw, band, rf, + RF_1TX, OFDM); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[band][rf][RF_1TX][0], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[band][rf][RF_1TX][1], + 0, 3, base); + + base = _rtl92ee_phy_get_txpower_by_rate_base(hw, band, rf, + RF_1TX, + HT_MCS0_MCS7); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[band][rf][RF_1TX][4], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[band][rf][RF_1TX][5], + 0, 3, base); + + base = _rtl92ee_phy_get_txpower_by_rate_base(hw, band, rf, + RF_2TX, + HT_MCS8_MCS15); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[band][rf][RF_2TX][6], + 0, 3, base); + + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[band][rf][RF_2TX][7], + 0, 3, base); + } + + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "<==phy_convert_txpwr_dbm_to_rel_val()\n"); +} + +static void _rtl92ee_phy_txpower_by_rate_configuration(struct ieee80211_hw *hw) +{ + _rtl92ee_phy_store_txpower_by_rate_base(hw); + phy_convert_txpwr_dbm_to_rel_val(hw); +} + +static bool _rtl92ee_phy_bb8192ee_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + bool rtstatus; + + rtstatus = phy_config_bb_with_hdr_file(hw, BASEBAND_CONFIG_PHY_REG); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); + return false; + } + + _rtl92ee_phy_init_tx_power_by_rate(hw); + if (!rtlefuse->autoload_failflag) { + rtlphy->pwrgroup_cnt = 0; + rtstatus = + phy_config_bb_with_pghdrfile(hw, BASEBAND_CONFIG_PHY_REG); + } + _rtl92ee_phy_txpower_by_rate_configuration(hw); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); + return false; + } + rtstatus = phy_config_bb_with_hdr_file(hw, BASEBAND_CONFIG_AGC_TAB); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); + return false; + } + rtlphy->cck_high_power = (bool)(rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + 0x200)); + + return true; +} + +static bool _rtl92ee_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + u32 arraylength; + u32 *ptrarray; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl8192EMACPHY_Array\n"); + arraylength = RTL8192EE_MAC_ARRAY_LEN; + ptrarray = RTL8192EE_MAC_ARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Img:RTL8192EE_MAC_ARRAY LEN %d\n" , arraylength); + for (i = 0; i < arraylength; i = i + 2) + rtl_write_byte(rtlpriv, ptrarray[i], (u8)ptrarray[i + 1]); + return true; +} + +#define READ_NEXT_PAIR(v1, v2, i) \ + do { \ + i += 2; \ + v1 = array[i]; \ + v2 = array[i+1]; \ + } while (0) + +static bool phy_config_bb_with_hdr_file(struct ieee80211_hw *hw, + u8 configtype) +{ + int i; + u32 *array; + u16 len; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 v1 = 0, v2 = 0; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + len = RTL8192EE_PHY_REG_ARRAY_LEN; + array = RTL8192EE_PHY_REG_ARRAY; + + for (i = 0; i < len; i = i + 2) { + v1 = array[i]; + v2 = array[i+1]; + if (v1 < 0xcdcdcdcd) { + _rtl92ee_config_bb_reg(hw, v1, v2); + } else {/*This line is the start line of branch.*/ + /* to protect READ_NEXT_PAIR not overrun */ + if (i >= len - 2) + break; + + if (!_check_condition(hw , array[i])) { + /*Discard the following pairs*/ + READ_NEXT_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < len - 2) { + READ_NEXT_PAIR(v1, v2, i); + } + i -= 2; /* prevent from for-loop += 2*/ + } else { + /* Configure matched pairs and + * skip to end of if-else. + */ + READ_NEXT_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < len - 2) { + _rtl92ee_config_bb_reg(hw, v1, + v2); + READ_NEXT_PAIR(v1, v2, i); + } + + while (v2 != 0xDEAD && i < len - 2) + READ_NEXT_PAIR(v1, v2, i); + } + } + } + } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { + len = RTL8192EE_AGC_TAB_ARRAY_LEN; + array = RTL8192EE_AGC_TAB_ARRAY; + + for (i = 0; i < len; i = i + 2) { + v1 = array[i]; + v2 = array[i+1]; + if (v1 < 0xCDCDCDCD) { + rtl_set_bbreg(hw, array[i], MASKDWORD, + array[i + 1]); + udelay(1); + continue; + } else{/*This line is the start line of branch.*/ + /* to protect READ_NEXT_PAIR not overrun */ + if (i >= len - 2) + break; + + if (!_check_condition(hw , array[i])) { + /*Discard the following pairs*/ + READ_NEXT_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < len - 2) { + READ_NEXT_PAIR(v1, v2, i); + } + i -= 2; /* prevent from for-loop += 2*/ + } else { + /* Configure matched pairs and + * skip to end of if-else. + */ + READ_NEXT_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < len - 2) { + rtl_set_bbreg(hw, + array[i], + MASKDWORD, + array[i + 1]); + udelay(1); + READ_NEXT_PAIR(v1 , v2 , i); + } + + while (v2 != 0xDEAD && + i < len - 2) { + READ_NEXT_PAIR(v1 , v2 , i); + } + } + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The agctab_array_table[0] is %x Rtl818EEPHY_REGArray[1] is %x\n", + array[i], + array[i + 1]); + } + } + return true; +} + +static u8 _rtl92ee_get_rate_section_index(u32 regaddr) +{ + u8 index = 0; + + switch (regaddr) { + case RTXAGC_A_RATE18_06: + case RTXAGC_B_RATE18_06: + index = 0; + break; + case RTXAGC_A_RATE54_24: + case RTXAGC_B_RATE54_24: + index = 1; + break; + case RTXAGC_A_CCK1_MCS32: + case RTXAGC_B_CCK1_55_MCS32: + index = 2; + break; + case RTXAGC_B_CCK11_A_CCK2_11: + index = 3; + break; + case RTXAGC_A_MCS03_MCS00: + case RTXAGC_B_MCS03_MCS00: + index = 4; + break; + case RTXAGC_A_MCS07_MCS04: + case RTXAGC_B_MCS07_MCS04: + index = 5; + break; + case RTXAGC_A_MCS11_MCS08: + case RTXAGC_B_MCS11_MCS08: + index = 6; + break; + case RTXAGC_A_MCS15_MCS12: + case RTXAGC_B_MCS15_MCS12: + index = 7; + break; + default: + regaddr &= 0xFFF; + if (regaddr >= 0xC20 && regaddr <= 0xC4C) + index = (u8)((regaddr - 0xC20) / 4); + else if (regaddr >= 0xE20 && regaddr <= 0xE4C) + index = (u8)((regaddr - 0xE20) / 4); + break; + } + return index; +} + +static void _rtl92ee_store_tx_power_by_rate(struct ieee80211_hw *hw, + enum band_type band, + enum radio_path rfpath, + u32 txnum, u32 regaddr, + u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 section = _rtl92ee_get_rate_section_index(regaddr); + + if (band != BAND_ON_2_4G && band != BAND_ON_5G) { + RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, "Invalid Band %d\n", band); + return; + } + + if (rfpath > MAX_RF_PATH - 1) { + RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, + "Invalid RfPath %d\n", rfpath); + return; + } + if (txnum > MAX_RF_PATH - 1) { + RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, "Invalid TxNum %d\n", txnum); + return; + } + + rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][section] = data; +} + +static bool phy_config_bb_with_pghdrfile(struct ieee80211_hw *hw, + u8 configtype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int i; + u32 *phy_regarray_table_pg; + u16 phy_regarray_pg_len; + u32 v1 = 0, v2 = 0, v3 = 0, v4 = 0, v5 = 0, v6 = 0; + + phy_regarray_pg_len = RTL8192EE_PHY_REG_ARRAY_PG_LEN; + phy_regarray_table_pg = RTL8192EE_PHY_REG_ARRAY_PG; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_regarray_pg_len; i = i + 6) { + v1 = phy_regarray_table_pg[i]; + v2 = phy_regarray_table_pg[i+1]; + v3 = phy_regarray_table_pg[i+2]; + v4 = phy_regarray_table_pg[i+3]; + v5 = phy_regarray_table_pg[i+4]; + v6 = phy_regarray_table_pg[i+5]; + + if (v1 < 0xcdcdcdcd) { + _rtl92ee_store_tx_power_by_rate(hw, v1, v2, v3, + v4, v5, v6); + continue; + } + } + } else { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "configtype != BaseBand_Config_PHY_REG\n"); + } + return true; +} + +#define READ_NEXT_RF_PAIR(v1, v2, i) \ + do { \ + i += 2; \ + v1 = array[i]; \ + v2 = array[i+1]; \ + } while (0) + +bool rtl92ee_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int i; + u32 *array; + u16 len; + u32 v1 = 0, v2 = 0; + + switch (rfpath) { + case RF90_PATH_A: + len = RTL8192EE_RADIOA_ARRAY_LEN; + array = RTL8192EE_RADIOA_ARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Radio_A:RTL8192EE_RADIOA_ARRAY %d\n" , len); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); + for (i = 0; i < len; i = i + 2) { + v1 = array[i]; + v2 = array[i+1]; + if (v1 < 0xcdcdcdcd) { + _rtl92ee_config_rf_radio_a(hw, v1, v2); + continue; + } else {/*This line is the start line of branch.*/ + /* to protect READ_NEXT_PAIR not overrun */ + if (i >= len - 2) + break; + + if (!_check_condition(hw , array[i])) { + /*Discard the following pairs*/ + READ_NEXT_RF_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < len - 2) { + READ_NEXT_RF_PAIR(v1, v2, i); + } + i -= 2; /* prevent from for-loop += 2*/ + } else { + /* Configure matched pairs and + * skip to end of if-else. + */ + READ_NEXT_RF_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < len - 2) { + _rtl92ee_config_rf_radio_a(hw, + v1, + v2); + READ_NEXT_RF_PAIR(v1, v2, i); + } + + while (v2 != 0xDEAD && i < len - 2) + READ_NEXT_RF_PAIR(v1, v2, i); + } + } + } + break; + + case RF90_PATH_B: + len = RTL8192EE_RADIOB_ARRAY_LEN; + array = RTL8192EE_RADIOB_ARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Radio_A:RTL8192EE_RADIOB_ARRAY %d\n" , len); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); + for (i = 0; i < len; i = i + 2) { + v1 = array[i]; + v2 = array[i+1]; + if (v1 < 0xcdcdcdcd) { + _rtl92ee_config_rf_radio_b(hw, v1, v2); + continue; + } else {/*This line is the start line of branch.*/ + /* to protect READ_NEXT_PAIR not overrun */ + if (i >= len - 2) + break; + + if (!_check_condition(hw , array[i])) { + /*Discard the following pairs*/ + READ_NEXT_RF_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < len - 2) { + READ_NEXT_RF_PAIR(v1, v2, i); + } + i -= 2; /* prevent from for-loop += 2*/ + } else { + /* Configure matched pairs and + * skip to end of if-else. + */ + READ_NEXT_RF_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < len - 2) { + _rtl92ee_config_rf_radio_b(hw, + v1, + v2); + READ_NEXT_RF_PAIR(v1, v2, i); + } + + while (v2 != 0xDEAD && i < len - 2) + READ_NEXT_RF_PAIR(v1, v2, i); + } + } + } + break; + case RF90_PATH_C: + case RF90_PATH_D: + break; + } + return true; +} + +void rtl92ee_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + rtlphy->default_initialgain[0] = + (u8)rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[1] = + (u8)rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[2] = + (u8)rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[3] = + (u8)rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", + rtlphy->default_initialgain[0], + rtlphy->default_initialgain[1], + rtlphy->default_initialgain[2], + rtlphy->default_initialgain[3]); + + rtlphy->framesync = (u8)rtl_get_bbreg(hw, + ROFDM0_RXDETECTOR3, MASKBYTE0); + rtlphy->framesync_c34 = rtl_get_bbreg(hw, + ROFDM0_RXDETECTOR2, MASKDWORD); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default framesync (0x%x) = 0x%x\n", + ROFDM0_RXDETECTOR3, rtlphy->framesync); +} + +static void phy_init_bb_rf_register_def(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; + + rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = + RFPGA0_XA_LSSIPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = + RFPGA0_XB_LSSIPARAMETER; + + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; + + rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; + + rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK; + rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK; +} + +void rtl92ee_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 txpwr_level; + long txpwr_dbm; + + txpwr_level = rtlphy->cur_cck_txpwridx; + txpwr_dbm = _rtl92ee_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_B, + txpwr_level); + txpwr_level = rtlphy->cur_ofdm24g_txpwridx; + if (_rtl92ee_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, txpwr_level) > + txpwr_dbm) + txpwr_dbm = _rtl92ee_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, + txpwr_level); + txpwr_level = rtlphy->cur_ofdm24g_txpwridx; + if (_rtl92ee_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, + txpwr_level) > txpwr_dbm) + txpwr_dbm = _rtl92ee_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_N_24G, + txpwr_level); + *powerlevel = txpwr_dbm; +} + +static u8 _rtl92ee_phy_get_ratesection_intxpower_byrate(enum radio_path path, + u8 rate) +{ + u8 rate_section = 0; + + switch (rate) { + case DESC92C_RATE1M: + rate_section = 2; + break; + case DESC92C_RATE2M: + case DESC92C_RATE5_5M: + if (path == RF90_PATH_A) + rate_section = 3; + else if (path == RF90_PATH_B) + rate_section = 2; + break; + case DESC92C_RATE11M: + rate_section = 3; + break; + case DESC92C_RATE6M: + case DESC92C_RATE9M: + case DESC92C_RATE12M: + case DESC92C_RATE18M: + rate_section = 0; + break; + case DESC92C_RATE24M: + case DESC92C_RATE36M: + case DESC92C_RATE48M: + case DESC92C_RATE54M: + rate_section = 1; + break; + case DESC92C_RATEMCS0: + case DESC92C_RATEMCS1: + case DESC92C_RATEMCS2: + case DESC92C_RATEMCS3: + rate_section = 4; + break; + case DESC92C_RATEMCS4: + case DESC92C_RATEMCS5: + case DESC92C_RATEMCS6: + case DESC92C_RATEMCS7: + rate_section = 5; + break; + case DESC92C_RATEMCS8: + case DESC92C_RATEMCS9: + case DESC92C_RATEMCS10: + case DESC92C_RATEMCS11: + rate_section = 6; + break; + case DESC92C_RATEMCS12: + case DESC92C_RATEMCS13: + case DESC92C_RATEMCS14: + case DESC92C_RATEMCS15: + rate_section = 7; + break; + default: + RT_ASSERT(true, "Rate_Section is Illegal\n"); + break; + } + return rate_section; +} + +static u8 _rtl92ee_get_txpower_by_rate(struct ieee80211_hw *hw, + enum band_type band, + enum radio_path rf, u8 rate) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 shift = 0, sec, tx_num; + char diff = 0; + + sec = _rtl92ee_phy_get_ratesection_intxpower_byrate(rf, rate); + tx_num = RF_TX_NUM_NONIMPLEMENT; + + if (tx_num == RF_TX_NUM_NONIMPLEMENT) { + if ((rate >= DESC92C_RATEMCS8 && rate <= DESC92C_RATEMCS15)) + tx_num = RF_2TX; + else + tx_num = RF_1TX; + } + + switch (rate) { + case DESC92C_RATE1M: + case DESC92C_RATE6M: + case DESC92C_RATE24M: + case DESC92C_RATEMCS0: + case DESC92C_RATEMCS4: + case DESC92C_RATEMCS8: + case DESC92C_RATEMCS12: + shift = 0; + break; + case DESC92C_RATE2M: + case DESC92C_RATE9M: + case DESC92C_RATE36M: + case DESC92C_RATEMCS1: + case DESC92C_RATEMCS5: + case DESC92C_RATEMCS9: + case DESC92C_RATEMCS13: + shift = 8; + break; + case DESC92C_RATE5_5M: + case DESC92C_RATE12M: + case DESC92C_RATE48M: + case DESC92C_RATEMCS2: + case DESC92C_RATEMCS6: + case DESC92C_RATEMCS10: + case DESC92C_RATEMCS14: + shift = 16; + break; + case DESC92C_RATE11M: + case DESC92C_RATE18M: + case DESC92C_RATE54M: + case DESC92C_RATEMCS3: + case DESC92C_RATEMCS7: + case DESC92C_RATEMCS11: + case DESC92C_RATEMCS15: + shift = 24; + break; + default: + RT_ASSERT(true, "Rate_Section is Illegal\n"); + break; + } + + diff = (u8)(rtlphy->tx_power_by_rate_offset[band][rf][tx_num][sec] >> + shift) & 0xff; + + return diff; +} + +static u8 _rtl92ee_get_txpower_index(struct ieee80211_hw *hw, + enum radio_path rfpath, u8 rate, + u8 bw, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); + u8 index = (channel - 1); + u8 tx_power = 0; + u8 diff = 0; + + if (channel < 1 || channel > 14) { + index = 0; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_DMESG, + "Illegal channel!!\n"); + } + + if (IS_CCK_RATE(rate)) + tx_power = rtlefuse->txpwrlevel_cck[rfpath][index]; + else if (DESC92C_RATE6M <= rate) + tx_power = rtlefuse->txpwrlevel_ht40_1s[rfpath][index]; + + /* OFDM-1T*/ + if (DESC92C_RATE6M <= rate && rate <= DESC92C_RATE54M && + !IS_CCK_RATE(rate)) + tx_power += rtlefuse->txpwr_legacyhtdiff[rfpath][TX_1S]; + + /* BW20-1S, BW20-2S */ + if (bw == HT_CHANNEL_WIDTH_20) { + if (DESC92C_RATEMCS0 <= rate && rate <= DESC92C_RATEMCS15) + tx_power += rtlefuse->txpwr_ht20diff[rfpath][TX_1S]; + if (DESC92C_RATEMCS8 <= rate && rate <= DESC92C_RATEMCS15) + tx_power += rtlefuse->txpwr_ht20diff[rfpath][TX_2S]; + } else if (bw == HT_CHANNEL_WIDTH_20_40) {/* BW40-1S, BW40-2S */ + if (DESC92C_RATEMCS0 <= rate && rate <= DESC92C_RATEMCS15) + tx_power += rtlefuse->txpwr_ht40diff[rfpath][TX_1S]; + if (DESC92C_RATEMCS8 <= rate && rate <= DESC92C_RATEMCS15) + tx_power += rtlefuse->txpwr_ht40diff[rfpath][TX_2S]; + } + + if (rtlefuse->eeprom_regulatory != 2) + diff = _rtl92ee_get_txpower_by_rate(hw, BAND_ON_2_4G, + rfpath, rate); + + tx_power += diff; + + if (tx_power > MAX_POWER_INDEX) + tx_power = MAX_POWER_INDEX; + + return tx_power; +} + +static void _rtl92ee_set_txpower_index(struct ieee80211_hw *hw, u8 pwr_idx, + enum radio_path rfpath, u8 rate) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rfpath == RF90_PATH_A) { + switch (rate) { + case DESC92C_RATE1M: + rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATE2M: + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATE5_5M: + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATE11M: + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE3, + pwr_idx); + break; + case DESC92C_RATE6M: + rtl_set_bbreg(hw, RTXAGC_A_RATE18_06, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATE9M: + rtl_set_bbreg(hw, RTXAGC_A_RATE18_06, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATE12M: + rtl_set_bbreg(hw, RTXAGC_A_RATE18_06, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATE18M: + rtl_set_bbreg(hw, RTXAGC_A_RATE18_06, MASKBYTE3, + pwr_idx); + break; + case DESC92C_RATE24M: + rtl_set_bbreg(hw, RTXAGC_A_RATE54_24, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATE36M: + rtl_set_bbreg(hw, RTXAGC_A_RATE54_24, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATE48M: + rtl_set_bbreg(hw, RTXAGC_A_RATE54_24, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATE54M: + rtl_set_bbreg(hw, RTXAGC_A_RATE54_24, MASKBYTE3, + pwr_idx); + break; + case DESC92C_RATEMCS0: + rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATEMCS1: + rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATEMCS2: + rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATEMCS3: + rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, MASKBYTE3, + pwr_idx); + break; + case DESC92C_RATEMCS4: + rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATEMCS5: + rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATEMCS6: + rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATEMCS7: + rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, MASKBYTE3, + pwr_idx); + break; + case DESC92C_RATEMCS8: + rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATEMCS9: + rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATEMCS10: + rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATEMCS11: + rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, MASKBYTE3, + pwr_idx); + break; + case DESC92C_RATEMCS12: + rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATEMCS13: + rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATEMCS14: + rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATEMCS15: + rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, MASKBYTE3, + pwr_idx); + break; + default: + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Invalid Rate!!\n"); + break; + } + } else if (rfpath == RF90_PATH_B) { + switch (rate) { + case DESC92C_RATE1M: + rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATE2M: + rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATE5_5M: + rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, MASKBYTE3, + pwr_idx); + break; + case DESC92C_RATE11M: + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATE6M: + rtl_set_bbreg(hw, RTXAGC_B_RATE18_06, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATE9M: + rtl_set_bbreg(hw, RTXAGC_B_RATE18_06, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATE12M: + rtl_set_bbreg(hw, RTXAGC_B_RATE18_06, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATE18M: + rtl_set_bbreg(hw, RTXAGC_B_RATE18_06, MASKBYTE3, + pwr_idx); + break; + case DESC92C_RATE24M: + rtl_set_bbreg(hw, RTXAGC_B_RATE54_24, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATE36M: + rtl_set_bbreg(hw, RTXAGC_B_RATE54_24, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATE48M: + rtl_set_bbreg(hw, RTXAGC_B_RATE54_24, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATE54M: + rtl_set_bbreg(hw, RTXAGC_B_RATE54_24, MASKBYTE3, + pwr_idx); + break; + case DESC92C_RATEMCS0: + rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATEMCS1: + rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATEMCS2: + rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATEMCS3: + rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, MASKBYTE3, + pwr_idx); + break; + case DESC92C_RATEMCS4: + rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATEMCS5: + rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATEMCS6: + rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATEMCS7: + rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, MASKBYTE3, + pwr_idx); + break; + case DESC92C_RATEMCS8: + rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATEMCS9: + rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATEMCS10: + rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATEMCS11: + rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, MASKBYTE3, + pwr_idx); + break; + case DESC92C_RATEMCS12: + rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, MASKBYTE0, + pwr_idx); + break; + case DESC92C_RATEMCS13: + rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, MASKBYTE1, + pwr_idx); + break; + case DESC92C_RATEMCS14: + rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, MASKBYTE2, + pwr_idx); + break; + case DESC92C_RATEMCS15: + rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, MASKBYTE3, + pwr_idx); + break; + default: + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Invalid Rate!!\n"); + break; + } + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Invalid RFPath!!\n"); + } +} + +static void phy_set_txpower_index_by_rate_array(struct ieee80211_hw *hw, + enum radio_path rfpath, u8 bw, + u8 channel, u8 *rates, u8 size) +{ + u8 i; + u8 power_index; + + for (i = 0; i < size; i++) { + power_index = _rtl92ee_get_txpower_index(hw, rfpath, rates[i], + bw, channel); + _rtl92ee_set_txpower_index(hw, power_index, rfpath, rates[i]); + } +} + +static void phy_set_txpower_index_by_rate_section(struct ieee80211_hw *hw, + enum radio_path rfpath, + u8 channel, + enum rate_section section) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + if (section == CCK) { + u8 cck_rates[] = {DESC92C_RATE1M, DESC92C_RATE2M, + DESC92C_RATE5_5M, DESC92C_RATE11M}; + if (rtlhal->current_bandtype == BAND_ON_2_4G) + phy_set_txpower_index_by_rate_array(hw, rfpath, + rtlphy->current_chan_bw, + channel, cck_rates, 4); + } else if (section == OFDM) { + u8 ofdm_rates[] = {DESC92C_RATE6M, DESC92C_RATE9M, + DESC92C_RATE12M, DESC92C_RATE18M, + DESC92C_RATE24M, DESC92C_RATE36M, + DESC92C_RATE48M, DESC92C_RATE54M}; + phy_set_txpower_index_by_rate_array(hw, rfpath, + rtlphy->current_chan_bw, + channel, ofdm_rates, 8); + } else if (section == HT_MCS0_MCS7) { + u8 ht_rates1t[] = {DESC92C_RATEMCS0, DESC92C_RATEMCS1, + DESC92C_RATEMCS2, DESC92C_RATEMCS3, + DESC92C_RATEMCS4, DESC92C_RATEMCS5, + DESC92C_RATEMCS6, DESC92C_RATEMCS7}; + phy_set_txpower_index_by_rate_array(hw, rfpath, + rtlphy->current_chan_bw, + channel, ht_rates1t, 8); + } else if (section == HT_MCS8_MCS15) { + u8 ht_rates2t[] = {DESC92C_RATEMCS8, DESC92C_RATEMCS9, + DESC92C_RATEMCS10, DESC92C_RATEMCS11, + DESC92C_RATEMCS12, DESC92C_RATEMCS13, + DESC92C_RATEMCS14, DESC92C_RATEMCS15}; + phy_set_txpower_index_by_rate_array(hw, rfpath, + rtlphy->current_chan_bw, + channel, ht_rates2t, 8); + } else + RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, + "Invalid RateSection %d\n", section); +} + +void rtl92ee_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtl_priv(hw)->phy; + enum radio_path rfpath; + + if (!rtlefuse->txpwr_fromeprom) + return; + for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; + rfpath++) { + phy_set_txpower_index_by_rate_section(hw, rfpath, + channel, CCK); + phy_set_txpower_index_by_rate_section(hw, rfpath, + channel, OFDM); + phy_set_txpower_index_by_rate_section(hw, rfpath, + channel, + HT_MCS0_MCS7); + + if (rtlphy->num_total_rfpath >= 2) + phy_set_txpower_index_by_rate_section(hw, + rfpath, channel, + HT_MCS8_MCS15); + } +} + +static long _rtl92ee_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u8 txpwridx) +{ + long offset; + long pwrout_dbm; + + switch (wirelessmode) { + case WIRELESS_MODE_B: + offset = -7; + break; + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + offset = -8; + break; + default: + offset = -8; + break; + } + pwrout_dbm = txpwridx / 2 + offset; + return pwrout_dbm; +} + +void rtl92ee_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + enum io_type iotype; + + if (!is_hal_stop(rtlhal)) { + switch (operation) { + case SCAN_OPT_BACKUP_BAND0: + iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, + (u8 *)&iotype); + + break; + case SCAN_OPT_RESTORE: + iotype = IO_CMD_RESUME_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, + (u8 *)&iotype); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Unknown Scan Backup operation.\n"); + break; + } + } +} + +void rtl92ee_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 reg_bw_opmode; + u8 reg_prsr_rsc; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz"); + + if (is_hal_stop(rtlhal)) { + rtlphy->set_bwmode_inprogress = false; + return; + } + + reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); + reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + break; + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + reg_prsr_rsc = (reg_prsr_rsc & 0x90) | + (mac->cur_40_prime_sc << 5); + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, ROFDM0_TXPSEUDONOISEWGT, + (BIT(31) | BIT(30)), 0); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, + mac->cur_40_prime_sc); + + rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), + (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + rtl92ee_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n"); +} + +void rtl92ee_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_bw = rtlphy->current_chan_bw; + + if (rtlphy->set_bwmode_inprogress) + return; + rtlphy->set_bwmode_inprogress = true; + if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtl92ee_phy_set_bw_mode_callback(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "false driver sleep or unload\n"); + rtlphy->set_bwmode_inprogress = false; + rtlphy->current_chan_bw = tmp_bw; + } +} + +void rtl92ee_phy_sw_chnl_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 delay; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "switch to channel%d\n", rtlphy->current_channel); + if (is_hal_stop(rtlhal)) + return; + do { + if (!rtlphy->sw_chnl_inprogress) + break; + if (!_rtl92ee_phy_sw_chnl_step_by_step + (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage, + &rtlphy->sw_chnl_step, &delay)) { + if (delay > 0) + mdelay(delay); + else + continue; + } else { + rtlphy->sw_chnl_inprogress = false; + } + break; + } while (true); + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); +} + +u8 rtl92ee_phy_sw_chnl(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlphy->sw_chnl_inprogress) + return 0; + if (rtlphy->set_bwmode_inprogress) + return 0; + RT_ASSERT((rtlphy->current_channel <= 14), + "WIRELESS_MODE_G but channel>14"); + rtlphy->sw_chnl_inprogress = true; + rtlphy->sw_chnl_stage = 0; + rtlphy->sw_chnl_step = 0; + if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtl92ee_phy_sw_chnl_callback(hw); + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + "sw_chnl_inprogress false schdule workitem current channel %d\n", + rtlphy->current_channel); + rtlphy->sw_chnl_inprogress = false; + } else { + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + "sw_chnl_inprogress false driver sleep or unload\n"); + rtlphy->sw_chnl_inprogress = false; + } + return 1; +} + +static bool _rtl92ee_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; + u32 precommoncmdcnt; + struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; + u32 postcommoncmdcnt; + struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; + u32 rfdependcmdcnt; + struct swchnlcmd *currentcmd = NULL; + u8 rfpath; + u8 num_total_rfpath = rtlphy->num_total_rfpath; + + precommoncmdcnt = 0; + _rtl92ee_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, + CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); + _rtl92ee_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); + + postcommoncmdcnt = 0; + + _rtl92ee_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, + MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); + + rfdependcmdcnt = 0; + + RT_ASSERT((channel >= 1 && channel <= 14), + "illegal channel for Zebra: %d\n", channel); + + _rtl92ee_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, + CMDID_RF_WRITEREG, + RF_CHNLBW, channel, 10); + + _rtl92ee_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_END, + 0, 0, 0); + + do { + switch (*stage) { + case 0: + currentcmd = &precommoncmd[*step]; + break; + case 1: + currentcmd = &rfdependcmd[*step]; + break; + case 2: + currentcmd = &postcommoncmd[*step]; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Invalid 'stage' = %d, Check it!\n" , *stage); + return true; + } + + if (currentcmd->cmdid == CMDID_END) { + if ((*stage) == 2) + return true; + (*stage)++; + (*step) = 0; + continue; + } + + switch (currentcmd->cmdid) { + case CMDID_SET_TXPOWEROWER_LEVEL: + rtl92ee_phy_set_txpower_level(hw, channel); + break; + case CMDID_WRITEPORT_ULONG: + rtl_write_dword(rtlpriv, currentcmd->para1, + currentcmd->para2); + break; + case CMDID_WRITEPORT_USHORT: + rtl_write_word(rtlpriv, currentcmd->para1, + (u16)currentcmd->para2); + break; + case CMDID_WRITEPORT_UCHAR: + rtl_write_byte(rtlpriv, currentcmd->para1, + (u8)currentcmd->para2); + break; + case CMDID_RF_WRITEREG: + for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { + rtlphy->rfreg_chnlval[rfpath] = + ((rtlphy->rfreg_chnlval[rfpath] & + 0xfffff00) | currentcmd->para2); + + rtl_set_rfreg(hw, (enum radio_path)rfpath, + currentcmd->para1, + 0x3ff, + rtlphy->rfreg_chnlval[rfpath]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + + break; + } while (true); + + (*delay) = currentcmd->msdelay; + (*step)++; + return false; +} + +static bool _rtl92ee_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, + enum swchnlcmd_id cmdid, + u32 para1, u32 para2, u32 msdelay) +{ + struct swchnlcmd *pcmd; + + if (cmdtable == NULL) { + RT_ASSERT(false, "cmdtable cannot be NULL.\n"); + return false; + } + + if (cmdtableidx >= cmdtablesz) + return false; + + pcmd = cmdtable + cmdtableidx; + pcmd->cmdid = cmdid; + pcmd->para1 = para1; + pcmd->para2 = para2; + pcmd->msdelay = msdelay; + return true; +} + +static u8 _rtl92ee_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) +{ + u32 reg_eac, reg_e94, reg_e9c; + u8 result = 0x00; + /* path-A IQK setting */ + /* PA/PAD controlled by 0x0 */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x180); + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + + rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82140303); + rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x68160000); + + /*LO calibration setting*/ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x00462911); + + /*One shot, path A LOK & IQK*/ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); + reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + + return result; +} + +static u8 _rtl92ee_phy_path_b_iqk(struct ieee80211_hw *hw) +{ + u32 reg_eac, reg_eb4, reg_ebc; + u8 result = 0x00; + + /* PA/PAD controlled by 0x0 */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + rtl_set_rfreg(hw, RF90_PATH_B, 0xdf, RFREG_OFFSET_MASK, 0x180); + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); + + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x18008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + + rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x821403e2); + rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x68160000); + + /* LO calibration setting */ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x00462911); + + /*One shot, path B LOK & IQK*/ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xfa000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); + reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); + + if (!(reg_eac & BIT(31)) && + (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && + (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + + return result; +} + +static u8 _rtl92ee_phy_path_a_rx_iqk(struct ieee80211_hw *hw, bool config_pathb) +{ + u32 reg_eac, reg_e94, reg_e9c, reg_ea4 , u32temp; + u8 result = 0x00; + + /*Get TXIMR Setting*/ + /*Modify RX IQK mode table*/ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + + rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf117b); + + /*PA/PAD control by 0x56, and set = 0x0*/ + rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x980); + rtl_set_rfreg(hw, RF90_PATH_A, 0x56, RFREG_OFFSET_MASK, 0x51000); + + /*enter IQK mode*/ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /*IQK Setting*/ + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + + /*path a IQK setting*/ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + + rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160c1f); + rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x68160c1f); + + /*LO calibration Setting*/ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); + + /*one shot,path A LOK & iqk*/ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xfa000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + /* Check failed */ + reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); + reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); + reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) { + result |= 0x01; + } else { + /* PA/PAD controlled by 0x0 */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x180); + return result; + } + + u32temp = 0x80007C00 | (reg_e94 & 0x3FF0000) | + ((reg_e9c & 0x3FF0000) >> 16); + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32temp); + /*RX IQK*/ + /*Modify RX IQK mode table*/ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + + rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); + + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ffa); + + /*PA/PAD control by 0x56, and set = 0x0*/ + rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x980); + rtl_set_rfreg(hw, RF90_PATH_A, 0x56, RFREG_OFFSET_MASK, 0x51000); + + /*enter IQK mode*/ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /*IQK Setting*/ + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + + /*path a IQK setting*/ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x18008c1c); + rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + + rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160c1f); + rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160c1f); + + /*LO calibration Setting*/ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a891); + /*one shot,path A LOK & iqk*/ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xfa000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + /*Check failed*/ + reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); + reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD); + + /*PA/PAD controlled by 0x0*/ + /*leave IQK mode*/ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x180); + /*if Tx is OK, check whether Rx is OK*/ + if (!(reg_eac & BIT(27)) && + (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_eac & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + + return result; +} + +static u8 _rtl92ee_phy_path_b_rx_iqk(struct ieee80211_hw *hw, bool config_pathb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 reg_eac, reg_eb4, reg_ebc, reg_ecc, reg_ec4, u32temp; + u8 result = 0x00; + + /*Get TXIMR Setting*/ + /*Modify RX IQK mode table*/ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + + rtl_set_rfreg(hw, RF90_PATH_B, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); + rtl_set_rfreg(hw, RF90_PATH_B, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, RF90_PATH_B, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); + rtl_set_rfreg(hw, RF90_PATH_B, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf117b); + + /*PA/PAD all off*/ + rtl_set_rfreg(hw, RF90_PATH_B, 0xdf, RFREG_OFFSET_MASK, 0x980); + rtl_set_rfreg(hw, RF90_PATH_B, 0x56, RFREG_OFFSET_MASK, 0x51000); + + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /*IQK Setting*/ + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + + /*path a IQK setting*/ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x18008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + + rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82160c1f); + rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x68160c1f); + + /*LO calibration Setting*/ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); + + /*one shot,path A LOK & iqk*/ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xfa000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + /* Check failed */ + reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); + reg_eb4 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_B, MASKDWORD); + reg_ebc = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_B, MASKDWORD); + + if (!(reg_eac & BIT(31)) && + (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && + (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) { + result |= 0x01; + } else { + /* PA/PAD controlled by 0x0 */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + rtl_set_rfreg(hw, RF90_PATH_B, 0xdf, RFREG_OFFSET_MASK, 0x180); + return result; + } + + u32temp = 0x80007C00 | (reg_eb4 & 0x3FF0000) | + ((reg_ebc & 0x3FF0000) >> 16); + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32temp); + /*RX IQK*/ + /*Modify RX IQK mode table*/ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + rtl_set_rfreg(hw, RF90_PATH_B, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); + + rtl_set_rfreg(hw, RF90_PATH_B, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, RF90_PATH_B, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); + rtl_set_rfreg(hw, RF90_PATH_B, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ffa); + + /*PA/PAD all off*/ + rtl_set_rfreg(hw, RF90_PATH_B, 0xdf, RFREG_OFFSET_MASK, 0x980); + rtl_set_rfreg(hw, RF90_PATH_B, 0x56, RFREG_OFFSET_MASK, 0x51000); + + /*enter IQK mode*/ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /*IQK Setting*/ + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + + /*path b IQK setting*/ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x18008c1c); + + rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82160c1f); + rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28160c1f); + + /*LO calibration Setting*/ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a891); + /*one shot,path A LOK & iqk*/ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xfa000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + /*Check failed*/ + reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); + reg_ec4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_B_2, MASKDWORD); + reg_ecc = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_B_2, MASKDWORD); + /*PA/PAD controlled by 0x0*/ + /*leave IQK mode*/ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + rtl_set_rfreg(hw, RF90_PATH_B, 0xdf, RFREG_OFFSET_MASK, 0x180); + /*if Tx is OK, check whether Rx is OK*/ + if (!(reg_eac & BIT(30)) && + (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + else + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "Path B Rx IQK fail!!\n"); + + return result; +} + +static void _rtl92ee_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, + bool b_iqk_ok, long result[][8], + u8 final_candidate, + bool btxonly) +{ + u32 oldval_0, x, tx0_a, reg; + long y, tx0_c; + + if (final_candidate == 0xFF) { + return; + } else if (b_iqk_ok) { + oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD) >> 22) & 0x3FF; + x = result[final_candidate][0]; + if ((x & 0x00000200) != 0) + x = x | 0xFFFFFC00; + tx0_a = (x * oldval_0) >> 8; + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31), + ((x * oldval_0 >> 7) & 0x1)); + y = result[final_candidate][1]; + if ((y & 0x00000200) != 0) + y = y | 0xFFFFFC00; + tx0_c = (y * oldval_0) >> 8; + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, + ((tx0_c & 0x3C0) >> 6)); + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000, + (tx0_c & 0x3F)); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29), + ((y * oldval_0 >> 7) & 0x1)); + + if (btxonly) + return; + + reg = result[final_candidate][2]; + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg); + + reg = result[final_candidate][3] & 0x3F; + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg); + + reg = (result[final_candidate][3] >> 6) & 0xF; + rtl_set_bbreg(hw, ROFDM0_RXIQEXTANTA, 0xF0000000, reg); + } +} + +static void _rtl92ee_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw, + bool b_iqk_ok, long result[][8], + u8 final_candidate, + bool btxonly) +{ + u32 oldval_1, x, tx1_a, reg; + long y, tx1_c; + + if (final_candidate == 0xFF) { + return; + } else if (b_iqk_ok) { + oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD) >> 22) & 0x3FF; + x = result[final_candidate][4]; + if ((x & 0x00000200) != 0) + x = x | 0xFFFFFC00; + tx1_a = (x * oldval_1) >> 8; + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx1_a); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(27), + ((x * oldval_1 >> 7) & 0x1)); + y = result[final_candidate][5]; + if ((y & 0x00000200) != 0) + y = y | 0xFFFFFC00; + tx1_c = (y * oldval_1) >> 8; + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000, + ((tx1_c & 0x3C0) >> 6)); + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000, + (tx1_c & 0x3F)); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(25), + ((y * oldval_1 >> 7) & 0x1)); + + if (btxonly) + return; + + reg = result[final_candidate][6]; + rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg); + + reg = result[final_candidate][7] & 0x3F; + rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg); + + reg = (result[final_candidate][7] >> 6) & 0xF; + rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0xF0000000, reg); + } +} + +static void _rtl92ee_phy_save_adda_registers(struct ieee80211_hw *hw, + u32 *addareg, u32 *addabackup, + u32 registernum) +{ + u32 i; + + for (i = 0; i < registernum; i++) + addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD); +} + +static void _rtl92ee_phy_save_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) + macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); + + macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); +} + +static void _rtl92ee_phy_reload_adda_registers(struct ieee80211_hw *hw, + u32 *addareg, u32 *addabackup, + u32 regiesternum) +{ + u32 i; + + for (i = 0; i < regiesternum; i++) + rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]); +} + +static void _rtl92ee_phy_reload_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) + rtl_write_byte(rtlpriv, macreg[i], (u8)macbackup[i]); + rtl_write_dword(rtlpriv, macreg[i], macbackup[i]); +} + +static void _rtl92ee_phy_path_adda_on(struct ieee80211_hw *hw, u32 *addareg, + bool is_patha_on, bool is2t) +{ + u32 pathon; + u32 i; + + pathon = is_patha_on ? 0x0fc01616 : 0x0fc01616; + if (!is2t) { + pathon = 0x0fc01616; + rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0fc01616); + } else { + rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon); + } + + for (i = 1; i < IQK_ADDA_REG_NUM; i++) + rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathon); +} + +static void _rtl92ee_phy_mac_setting_calibration(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + rtl_set_bbreg(hw, 0x520, 0x00ff0000, 0xff); +} + +static void _rtl92ee_phy_path_a_standby(struct ieee80211_hw *hw) +{ + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); + rtl_set_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK, 0x10000); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); +} + +static bool _rtl92ee_phy_simularity_compare(struct ieee80211_hw *hw, + long result[][8], u8 c1, u8 c2) +{ + u32 i, j, diff, simularity_bitmap, bound; + + u8 final_candidate[2] = { 0xFF, 0xFF }; + bool bresult = true/*, is2t = true*/; + s32 tmp1, tmp2; + + bound = 8; + + simularity_bitmap = 0; + + for (i = 0; i < bound; i++) { + if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) { + if ((result[c1][i] & 0x00000200) != 0) + tmp1 = result[c1][i] | 0xFFFFFC00; + else + tmp1 = result[c1][i]; + + if ((result[c2][i] & 0x00000200) != 0) + tmp2 = result[c2][i] | 0xFFFFFC00; + else + tmp2 = result[c2][i]; + } else { + tmp1 = result[c1][i]; + tmp2 = result[c2][i]; + } + + diff = (tmp1 > tmp2) ? (tmp1 - tmp2) : (tmp2 - tmp1); + + if (diff > MAX_TOLERANCE) { + if ((i == 2 || i == 6) && !simularity_bitmap) { + if (result[c1][i] + result[c1][i + 1] == 0) + final_candidate[(i / 4)] = c2; + else if (result[c2][i] + result[c2][i + 1] == 0) + final_candidate[(i / 4)] = c1; + else + simularity_bitmap |= (1 << i); + } else { + simularity_bitmap |= (1 << i); + } + } + } + + if (simularity_bitmap == 0) { + for (i = 0; i < (bound / 4); i++) { + if (final_candidate[i] != 0xFF) { + for (j = i * 4; j < (i + 1) * 4 - 2; j++) + result[3][j] = + result[final_candidate[i]][j]; + bresult = false; + } + } + return bresult; + } + if (!(simularity_bitmap & 0x03)) {/*path A TX OK*/ + for (i = 0; i < 2; i++) + result[3][i] = result[c1][i]; + } + if (!(simularity_bitmap & 0x0c)) {/*path A RX OK*/ + for (i = 2; i < 4; i++) + result[3][i] = result[c1][i]; + } + if (!(simularity_bitmap & 0x30)) {/*path B TX OK*/ + for (i = 4; i < 6; i++) + result[3][i] = result[c1][i]; + } + if (!(simularity_bitmap & 0xc0)) {/*path B RX OK*/ + for (i = 6; i < 8; i++) + result[3][i] = result[c1][i]; + } + return false; +} + +static void _rtl92ee_phy_iq_calibrate(struct ieee80211_hw *hw, + long result[][8], u8 t, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 i; + u8 patha_ok, pathb_ok; + u8 tmp_0xc50 = (u8)rtl_get_bbreg(hw, 0xc50, MASKBYTE0); + u8 tmp_0xc58 = (u8)rtl_get_bbreg(hw, 0xc58, MASKBYTE0); + u32 adda_reg[IQK_ADDA_REG_NUM] = { + 0x85c, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec + }; + u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { + 0x522, 0x550, 0x551, 0x040 + }; + u32 iqk_bb_reg[IQK_BB_REG_NUM] = { + ROFDM0_TRXPATHENABLE, ROFDM0_TRMUXPAR, + RFPGA0_XCD_RFINTERFACESW, 0xb68, 0xb6c, + 0x870, 0x860, + 0x864, 0x800 + }; + const u32 retrycount = 2; + + if (t == 0) { + _rtl92ee_phy_save_adda_registers(hw, adda_reg, + rtlphy->adda_backup, + IQK_ADDA_REG_NUM); + _rtl92ee_phy_save_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + _rtl92ee_phy_save_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, + IQK_BB_REG_NUM); + } + + _rtl92ee_phy_path_adda_on(hw, adda_reg, true, is2t); + + /*BB setting*/ + rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00); + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKDWORD, 0x03a05600); + rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, MASKDWORD, 0x000800e4); + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, MASKDWORD, 0x22208200); + + rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(10), 0x01); + rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(26), 0x01); + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10), 0x01); + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(10), 0x01); + + _rtl92ee_phy_mac_setting_calibration(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + /* Page B init*/ + /* IQ calibration setting*/ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + + for (i = 0 ; i < retrycount ; i++) { + patha_ok = _rtl92ee_phy_path_a_iqk(hw, is2t); + + if (patha_ok == 0x01) { + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "Path A Tx IQK Success!!\n"); + result[t][0] = (rtl_get_bbreg(hw, + RTX_POWER_BEFORE_IQK_A, + MASKDWORD) & 0x3FF0000) + >> 16; + result[t][1] = (rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, + MASKDWORD) & 0x3FF0000) + >> 16; + break; + } + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "Path A Tx IQK Fail!!, ret = 0x%x\n", + patha_ok); + } + + for (i = 0 ; i < retrycount ; i++) { + patha_ok = _rtl92ee_phy_path_a_rx_iqk(hw, is2t); + + if (patha_ok == 0x03) { + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "Path A Rx IQK Success!!\n"); + result[t][2] = (rtl_get_bbreg(hw, + RRX_POWER_BEFORE_IQK_A_2, + MASKDWORD) & 0x3FF0000) + >> 16; + result[t][3] = (rtl_get_bbreg(hw, + RRX_POWER_AFTER_IQK_A_2, + MASKDWORD) & 0x3FF0000) + >> 16; + break; + } + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "Path A Rx IQK Fail!!, ret = 0x%x\n", + patha_ok); + } + + if (0x00 == patha_ok) + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "Path A IQK failed!!, ret = 0\n"); + if (is2t) { + _rtl92ee_phy_path_a_standby(hw); + /* Turn Path B ADDA on */ + _rtl92ee_phy_path_adda_on(hw, adda_reg, false, is2t); + + /* IQ calibration setting */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + + for (i = 0 ; i < retrycount ; i++) { + pathb_ok = _rtl92ee_phy_path_b_iqk(hw); + if (pathb_ok == 0x01) { + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "Path B Tx IQK Success!!\n"); + result[t][4] = (rtl_get_bbreg(hw, + RTX_POWER_BEFORE_IQK_B, + MASKDWORD) & 0x3FF0000) + >> 16; + result[t][5] = (rtl_get_bbreg(hw, + RTX_POWER_AFTER_IQK_B, + MASKDWORD) & 0x3FF0000) + >> 16; + break; + } + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "Path B Tx IQK Fail!!, ret = 0x%x\n", + pathb_ok); + } + + for (i = 0 ; i < retrycount ; i++) { + pathb_ok = _rtl92ee_phy_path_b_rx_iqk(hw, is2t); + if (pathb_ok == 0x03) { + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "Path B Rx IQK Success!!\n"); + result[t][6] = (rtl_get_bbreg(hw, + RRX_POWER_BEFORE_IQK_B_2, + MASKDWORD) & 0x3FF0000) + >> 16; + result[t][7] = (rtl_get_bbreg(hw, + RRX_POWER_AFTER_IQK_B_2, + MASKDWORD) & 0x3FF0000) + >> 16; + break; + } + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "Path B Rx IQK Fail!!, ret = 0x%x\n", + pathb_ok); + } + + if (0x00 == pathb_ok) + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "Path B IQK failed!!, ret = 0\n"); + } + /* Back to BB mode, load original value */ + RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, + "IQK:Back to BB mode, load original value!\n"); + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0); + + if (t != 0) { + /* Reload ADDA power saving parameters */ + _rtl92ee_phy_reload_adda_registers(hw, adda_reg, + rtlphy->adda_backup, + IQK_ADDA_REG_NUM); + + /* Reload MAC parameters */ + _rtl92ee_phy_reload_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + + _rtl92ee_phy_reload_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, + IQK_BB_REG_NUM); + + /* Restore RX initial gain */ + rtl_set_bbreg(hw, 0xc50, MASKBYTE0, 0x50); + rtl_set_bbreg(hw, 0xc50, MASKBYTE0, tmp_0xc50); + if (is2t) { + rtl_set_bbreg(hw, 0xc50, MASKBYTE0, 0x50); + rtl_set_bbreg(hw, 0xc58, MASKBYTE0, tmp_0xc58); + } + + /* load 0xe30 IQC default value */ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x01008c00); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x01008c00); + } +} + +static void _rtl92ee_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) +{ + u8 tmpreg; + u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + tmpreg = rtl_read_byte(rtlpriv, 0xd03); + + if ((tmpreg & 0x70) != 0) + rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); + else + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + + if ((tmpreg & 0x70) != 0) { + rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); + + if (is2t) + rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, + MASK12BITS); + + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, + (rf_a_mode & 0x8FFFF) | 0x10000); + + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + (rf_b_mode & 0x8FFFF) | 0x10000); + } + lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); + + rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); + + mdelay(100); + + if ((tmpreg & 0x70) != 0) { + rtl_write_byte(rtlpriv, 0xd03, tmpreg); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); + + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + rf_b_mode); + } else { + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + } +} + +static void _rtl92ee_phy_set_rfpath_switch(struct ieee80211_hw *hw, + bool bmain, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD , "\n"); + + if (is_hal_stop(rtlhal)) { + u8 u1btmp; + + u1btmp = rtl_read_byte(rtlpriv, REG_LEDCFG0); + rtl_write_byte(rtlpriv, REG_LEDCFG0, u1btmp | BIT(7)); + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); + } + if (is2t) { + if (bmain) + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(6), 0x1); + else + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(6), 0x2); + } else { + rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(8) | BIT(9), 0); + rtl_set_bbreg(hw, 0x914, MASKLWORD, 0x0201); + + /* We use the RF definition of MAIN and AUX, + * left antenna and right antenna repectively. + * Default output at AUX. + */ + if (bmain) { + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, + BIT(14) | BIT(13) | BIT(12), 0); + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(4) | BIT(3), 0); + if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) + rtl_set_bbreg(hw, RCONFIG_RAM64x16, BIT(31), 0); + } else { + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, + BIT(14) | BIT(13) | BIT(12), 1); + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(4) | BIT(3), 1); + if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) + rtl_set_bbreg(hw, RCONFIG_RAM64x16, BIT(31), 1); + } + } +} + +#undef IQK_ADDA_REG_NUM +#undef IQK_DELAY_TIME + +static u8 rtl92ee_get_rightchnlplace_for_iqk(u8 chnl) +{ + u8 channel_all[59] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, + 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, + 114, 116, 118, 120, 122, 124, 126, 128, 130, + 132, 134, 136, 138, 140, 149, 151, 153, 155, + 157, 159, 161, 163, 165 + }; + u8 place = chnl; + + if (chnl > 14) { + for (place = 14; place < sizeof(channel_all); place++) { + if (channel_all[place] == chnl) + return place - 13; + } + } + + return 0; +} + +void rtl92ee_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + long result[4][8]; + u8 i, final_candidate; + bool b_patha_ok, b_pathb_ok; + long reg_e94, reg_e9c, reg_ea4, reg_eac; + long reg_eb4, reg_ebc, reg_ec4, reg_ecc; + bool is12simular, is13simular, is23simular; + u8 idx; + u32 iqk_bb_reg[IQK_BB_REG_NUM] = { + ROFDM0_XARXIQIMBALANCE, + ROFDM0_XBRXIQIMBALANCE, + ROFDM0_ECCATHRESHOLD, + ROFDM0_AGCRSSITABLE, + ROFDM0_XATXIQIMBALANCE, + ROFDM0_XBTXIQIMBALANCE, + ROFDM0_XCTXAFE, + ROFDM0_XDTXAFE, + ROFDM0_RXIQEXTANTA + }; + + if (b_recovery) { + _rtl92ee_phy_reload_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, 9); + return; + } + + for (i = 0; i < 8; i++) { + result[0][i] = 0; + result[1][i] = 0; + result[2][i] = 0; + + if ((i == 0) || (i == 2) || (i == 4) || (i == 6)) + result[3][i] = 0x100; + else + result[3][i] = 0; + } + final_candidate = 0xff; + b_patha_ok = false; + b_pathb_ok = false; + is12simular = false; + is23simular = false; + is13simular = false; + for (i = 0; i < 3; i++) { + _rtl92ee_phy_iq_calibrate(hw, result, i, true); + if (i == 1) { + is12simular = _rtl92ee_phy_simularity_compare(hw, + result, + 0, 1); + if (is12simular) { + final_candidate = 0; + break; + } + } + + if (i == 2) { + is13simular = _rtl92ee_phy_simularity_compare(hw, + result, + 0, 2); + if (is13simular) { + final_candidate = 0; + break; + } + is23simular = _rtl92ee_phy_simularity_compare(hw, + result, + 1, 2); + if (is23simular) + final_candidate = 1; + else + final_candidate = 3; + } + } + + for (i = 0; i < 4; i++) { + reg_e94 = result[i][0]; + reg_e9c = result[i][1]; + reg_ea4 = result[i][2]; + reg_eac = result[i][3]; + reg_eb4 = result[i][4]; + reg_ebc = result[i][5]; + reg_ec4 = result[i][6]; + reg_ecc = result[i][7]; + } + + if (final_candidate != 0xff) { + reg_e94 = result[final_candidate][0]; + rtlphy->reg_e94 = reg_e94; + reg_e9c = result[final_candidate][1]; + rtlphy->reg_e9c = reg_e9c; + reg_ea4 = result[final_candidate][2]; + reg_eac = result[final_candidate][3]; + reg_eb4 = result[final_candidate][4]; + rtlphy->reg_eb4 = reg_eb4; + reg_ebc = result[final_candidate][5]; + rtlphy->reg_ebc = reg_ebc; + reg_ec4 = result[final_candidate][6]; + reg_ecc = result[final_candidate][7]; + b_patha_ok = true; + b_pathb_ok = true; + } else { + rtlphy->reg_e94 = 0x100; + rtlphy->reg_eb4 = 0x100; + rtlphy->reg_e9c = 0x0; + rtlphy->reg_ebc = 0x0; + } + + if (reg_e94 != 0) + _rtl92ee_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result, + final_candidate, + (reg_ea4 == 0)); + + _rtl92ee_phy_path_b_fill_iqk_matrix(hw, b_pathb_ok, result, + final_candidate, + (reg_ec4 == 0)); + + idx = rtl92ee_get_rightchnlplace_for_iqk(rtlphy->current_channel); + + /* To Fix BSOD when final_candidate is 0xff */ + if (final_candidate < 4) { + for (i = 0; i < IQK_MATRIX_REG_NUM; i++) + rtlphy->iqk_matrix[idx].value[0][i] = + result[final_candidate][i]; + + rtlphy->iqk_matrix[idx].iqk_done = true; + } + _rtl92ee_phy_save_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, 9); +} + +void rtl92ee_phy_lc_calibrate(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = &rtlpriv->rtlhal; + u32 timeout = 2000, timecount = 0; + + while (rtlpriv->mac80211.act_scanning && timecount < timeout) { + udelay(50); + timecount += 50; + } + + rtlphy->lck_inprogress = true; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "LCK:Start!!! currentband %x delay %d ms\n", + rtlhal->current_bandtype, timecount); + + _rtl92ee_phy_lc_calibrate(hw, false); + + rtlphy->lck_inprogress = false; +} + +void rtl92ee_phy_ap_calibrate(struct ieee80211_hw *hw, char delta) +{ +} + +void rtl92ee_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) +{ + _rtl92ee_phy_set_rfpath_switch(hw, bmain, false); +} + +bool rtl92ee_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + bool postprocessing = false; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "-->IO Cmd(%#x), set_io_inprogress(%d)\n", + iotype, rtlphy->set_io_inprogress); + do { + switch (iotype) { + case IO_CMD_RESUME_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Resume DM after scan.\n"); + postprocessing = true; + break; + case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Pause DM before scan.\n"); + postprocessing = true; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + } while (false); + if (postprocessing && !rtlphy->set_io_inprogress) { + rtlphy->set_io_inprogress = true; + rtlphy->current_io_type = iotype; + } else { + return false; + } + rtl92ee_phy_set_io(hw); + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); + return true; +} + +static void rtl92ee_phy_set_io(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct dig_t *dm_dig = &rtlpriv->dm_digtable; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "--->Cmd(%#x), set_io_inprogress(%d)\n", + rtlphy->current_io_type, rtlphy->set_io_inprogress); + switch (rtlphy->current_io_type) { + case IO_CMD_RESUME_DM_BY_SCAN: + rtl92ee_dm_write_dig(hw, rtlphy->initgain_backup.xaagccore1); + rtl92ee_dm_write_cck_cca_thres(hw, rtlphy->initgain_backup.cca); + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE , "no set txpower\n"); + rtl92ee_phy_set_txpower_level(hw, rtlphy->current_channel); + break; + case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: + /* 8192eebt */ + rtlphy->initgain_backup.xaagccore1 = dm_dig->cur_igvalue; + rtl92ee_dm_write_dig(hw, 0x17); + rtlphy->initgain_backup.cca = dm_dig->cur_cck_cca_thres; + rtl92ee_dm_write_cck_cca_thres(hw, 0x40); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + rtlphy->set_io_inprogress = false; + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "(%#x)\n", rtlphy->current_io_type); +} + +static void rtl92ee_phy_set_rf_on(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + /*rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);*/ + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); +} + +static void _rtl92ee_phy_set_rf_sleep(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); +} + +static bool _rtl92ee_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = true; + u8 i, queue_id; + struct rtl8192_tx_ring *ring = NULL; + + switch (rfpwr_state) { + case ERFON: + if ((ppsc->rfpwr_state == ERFOFF) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + bool rtstatus; + u32 initializecount = 0; + + do { + initializecount++; + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic enable\n"); + rtstatus = rtl_ps_enable_nic(hw); + } while (!rtstatus && (initializecount < 10)); + RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } else { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFON sleeping:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc->last_sleep_jiffies)); + ppsc->last_awake_jiffies = jiffies; + rtl92ee_phy_set_rf_on(hw); + } + if (mac->link_state == MAC80211_LINKED) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_LINK); + else + rtlpriv->cfg->ops->led_control(hw, LED_CTL_NO_LINK); + break; + case ERFOFF: + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (queue_id == BEACON_QUEUE || + skb_queue_len(&ring->queue) == 0) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", + (i + 1), queue_id, + skb_queue_len(&ring->queue)); + + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic disable\n"); + rtl_ps_disable_nic(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } else { + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_POWER_OFF); + } + } + break; + case ERFSLEEP: + if (ppsc->rfpwr_state == ERFOFF) + break; + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (skb_queue_len(&ring->queue) == 0) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", + (i + 1), queue_id, + skb_queue_len(&ring->queue)); + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFSLEEP awaked:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc->last_awake_jiffies)); + ppsc->last_sleep_jiffies = jiffies; + _rtl92ee_phy_set_rf_sleep(hw); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + bresult = false; + break; + } + if (bresult) + ppsc->rfpwr_state = rfpwr_state; + return bresult; +} + +bool rtl92ee_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + bool bresult = false; + + if (rfpwr_state == ppsc->rfpwr_state) + return bresult; + bresult = _rtl92ee_phy_set_rf_power_state(hw, rfpwr_state); + return bresult; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h new file mode 100644 index 000000000000..c6e97c8df54c --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.h @@ -0,0 +1,153 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92E_PHY_H__ +#define __RTL92E_PHY_H__ + +/* MAX_TX_COUNT must always set to 4, otherwise read efuse table sequence + * will be wrong. + */ +#define MAX_TX_COUNT 4 +#define TX_1S 0 +#define TX_2S 1 +#define TX_3S 2 +#define TX_4S 3 + +#define MAX_POWER_INDEX 0x3f + +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define MAX_DOZE_WAITING_TIMES_9x 64 + +#define RT_CANNOT_IO(hw) false +#define HIGHPOWER_RADIOA_ARRAYLEN 22 + +#define IQK_ADDA_REG_NUM 16 +#define IQK_MAC_REG_NUM 4 +#define IQK_BB_REG_NUM 9 +#define MAX_TOLERANCE 5 +#define IQK_DELAY_TIME 10 +#define index_mapping_NUM 15 + +#define APK_BB_REG_NUM 5 +#define APK_AFE_REG_NUM 16 +#define APK_CURVE_REG_NUM 4 +#define PATH_NUM 2 + +#define LOOP_LIMIT 5 +#define MAX_STALL_TIME 50 +#define ANTENNADIVERSITYVALUE 0x80 +#define MAX_TXPWR_IDX_NMODE_92S 63 +#define RESET_CNT_LIMIT 3 + +#define RF6052_MAX_PATH 2 + +#define CT_OFFSET_MAC_ADDR 0X16 + +#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A +#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 +#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 +#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 +#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C + +#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F +#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 + +#define CT_OFFSET_CHANNEL_PLAH 0x75 +#define CT_OFFSET_THERMAL_METER 0x78 +#define CT_OFFSET_RF_OPTION 0x79 +#define CT_OFFSET_VERSION 0x7E +#define CT_OFFSET_CUSTOMER_ID 0x7F + +#define RTL92C_MAX_PATH_NUM 2 + +enum swchnlcmd_id { + CMDID_END, + CMDID_SET_TXPOWEROWER_LEVEL, + CMDID_BBREGWRITE10, + CMDID_WRITEPORT_ULONG, + CMDID_WRITEPORT_USHORT, + CMDID_WRITEPORT_UCHAR, + CMDID_RF_WRITEREG, +}; + +struct swchnlcmd { + enum swchnlcmd_id cmdid; + u32 para1; + u32 para2; + u32 msdelay; +}; + +enum baseband_config_type { + BASEBAND_CONFIG_PHY_REG = 0, + BASEBAND_CONFIG_AGC_TAB = 1, +}; + +enum ant_div_type { + NO_ANTDIV = 0xFF, + CG_TRX_HW_ANTDIV = 0x01, + CGCS_RX_HW_ANTDIV = 0x02, + FIXED_HW_ANTDIV = 0x03, + CG_TRX_SMART_ANTDIV = 0x04, + CGCS_RX_SW_ANTDIV = 0x05, +}; + +u32 rtl92ee_phy_query_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask); +void rtl92ee_phy_set_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, u32 data); +u32 rtl92ee_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask); +void rtl92ee_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask, u32 data); +bool rtl92ee_phy_mac_config(struct ieee80211_hw *hw); +bool rtl92ee_phy_bb_config(struct ieee80211_hw *hw); +bool rtl92ee_phy_rf_config(struct ieee80211_hw *hw); +void rtl92ee_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl92ee_phy_get_txpower_level(struct ieee80211_hw *hw, + long *powerlevel); +void rtl92ee_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +void rtl92ee_phy_scan_operation_backup(struct ieee80211_hw *hw, + u8 operation); +void rtl92ee_phy_set_bw_mode_callback(struct ieee80211_hw *hw); +void rtl92ee_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); +void rtl92ee_phy_sw_chnl_callback(struct ieee80211_hw *hw); +u8 rtl92ee_phy_sw_chnl(struct ieee80211_hw *hw); +void rtl92ee_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); +void rtl92ee_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); +void rtl92ee_phy_lc_calibrate(struct ieee80211_hw *hw); +void rtl92ee_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); +bool rtl92ee_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +bool rtl92ee_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); +bool rtl92ee_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c new file mode 100644 index 000000000000..1a701d007f0c --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.c @@ -0,0 +1,112 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "pwrseq.h" + +/* drivers should parse below arrays and do the corresponding actions */ + +/*3 Power on Array*/ +struct wlan_pwr_cfg rtl8192E_power_on_flow + [RTL8192E_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8192E_TRANS_END_STEPS] = { + RTL8192E_TRANS_CARDEMU_TO_ACT + RTL8192E_TRANS_END +}; + +/*3Radio off GPIO Array */ +struct wlan_pwr_cfg rtl8192E_radio_off_flow + [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8192E_TRANS_END_STEPS] = { + RTL8192E_TRANS_ACT_TO_CARDEMU + RTL8192E_TRANS_END +}; + +/*3Card Disable Array*/ +struct wlan_pwr_cfg rtl8192E_card_disable_flow + [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8192E_TRANS_END_STEPS] = { + RTL8192E_TRANS_ACT_TO_CARDEMU + RTL8192E_TRANS_CARDEMU_TO_CARDDIS + RTL8192E_TRANS_END +}; + +/*3 Card Enable Array*/ +struct wlan_pwr_cfg rtl8192E_card_enable_flow + [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8192E_TRANS_END_STEPS] = { + RTL8192E_TRANS_CARDDIS_TO_CARDEMU + RTL8192E_TRANS_CARDEMU_TO_ACT + RTL8192E_TRANS_END +}; + +/*3Suspend Array*/ +struct wlan_pwr_cfg rtl8192E_suspend_flow + [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8192E_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8192E_TRANS_END_STEPS] = { + RTL8192E_TRANS_ACT_TO_CARDEMU + RTL8192E_TRANS_CARDEMU_TO_SUS + RTL8192E_TRANS_END +}; + +/*3 Resume Array*/ +struct wlan_pwr_cfg rtl8192E_resume_flow + [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8192E_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8192E_TRANS_END_STEPS] = { + RTL8192E_TRANS_SUS_TO_CARDEMU + RTL8192E_TRANS_CARDEMU_TO_ACT + RTL8192E_TRANS_END +}; + +/*3HWPDN Array*/ +struct wlan_pwr_cfg rtl8192E_hwpdn_flow + [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8192E_TRANS_END_STEPS] = { + RTL8192E_TRANS_ACT_TO_CARDEMU + RTL8192E_TRANS_CARDEMU_TO_PDN + RTL8192E_TRANS_END +}; + +/*3 Enter LPS */ +struct wlan_pwr_cfg rtl8192E_enter_lps_flow + [RTL8192E_TRANS_ACT_TO_LPS_STEPS + + RTL8192E_TRANS_END_STEPS] = { + /*FW behavior*/ + RTL8192E_TRANS_ACT_TO_LPS + RTL8192E_TRANS_END +}; + +/*3 Leave LPS */ +struct wlan_pwr_cfg rtl8192E_leave_lps_flow + [RTL8192E_TRANS_LPS_TO_ACT_STEPS + + RTL8192E_TRANS_END_STEPS] = { + /*FW behavior*/ + RTL8192E_TRANS_LPS_TO_ACT + RTL8192E_TRANS_END +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h new file mode 100644 index 000000000000..781eeaa6af49 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h @@ -0,0 +1,340 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92E_PWRSEQ_H__ +#define __RTL92E_PWRSEQ_H__ + +#include "../pwrseqcmd.h" +/** + * Check document WM-20110607-Paul-RTL8192E_Power_Architecture-R02.vsd + * There are 6 HW Power States: + * 0: POFF--Power Off + * 1: PDN--Power Down + * 2: CARDEMU--Card Emulation + * 3: ACT--Active Mode + * 4: LPS--Low Power State + * 5: SUS--Suspend + * + * The transision from different states are defined below + * TRANS_CARDEMU_TO_ACT + * TRANS_ACT_TO_CARDEMU + * TRANS_CARDEMU_TO_SUS + * TRANS_SUS_TO_CARDEMU + * TRANS_CARDEMU_TO_PDN + * TRANS_ACT_TO_LPS + * TRANS_LPS_TO_ACT + * + * TRANS_END + * PWR SEQ Version: rtl8192E_PwrSeq_V09.h + */ + +#define RTL8192E_TRANS_CARDEMU_TO_ACT_STEPS 18 +#define RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS 18 +#define RTL8192E_TRANS_CARDEMU_TO_SUS_STEPS 18 +#define RTL8192E_TRANS_SUS_TO_CARDEMU_STEPS 18 +#define RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS 18 +#define RTL8192E_TRANS_PDN_TO_CARDEMU_STEPS 18 +#define RTL8192E_TRANS_ACT_TO_LPS_STEPS 23 +#define RTL8192E_TRANS_LPS_TO_ACT_STEPS 23 +#define RTL8192E_TRANS_END_STEPS 1 + +#define RTL8192E_TRANS_CARDEMU_TO_ACT \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ + /* disable HWPDN 0x04[15]=0*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(7), 0}, \ + /* disable SW LPS 0x04[10]=0*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(2), 0}, \ + /* disable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, (BIT(4)|BIT(3)), 0}, \ + /* wait till 0x04[17] = 1 power ready*/ \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_POLLING, BIT(1), BIT(1)}, \ + /* release WLON reset 0x04[16]=1*/ \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(0), BIT(0)}, \ + /* polling until return 0*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(0), BIT(0)}, \ + /**/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_POLLING, BIT(0), 0}, + +#define RTL8192E_TRANS_ACT_TO_CARDEMU \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ + /*0x1F[7:0] = 0 turn off RF*/ \ + {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0}, \ + /*0x4C[23]=0x4E[7]=0, switch DPDT_SEL_P output from register 0x65[2] */\ + {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(7), 0}, \ + /*0x04[9] = 1 turn off MAC by HW state machine*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(1), BIT(1)}, \ + /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_POLLING, BIT(1), 0}, + +#define RTL8192E_TRANS_CARDEMU_TO_SUS \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ + /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(4) | BIT(3), (BIT(4) | BIT(3))},\ + /*0x04[12:11] = 2b'01 enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \ + PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \ + /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3) | BIT(4)},\ + /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO , PWR_CMD_WRITE, BIT(0), BIT(0)}, \ + /*wait power state to suspend*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO , PWR_CMD_POLLING, BIT(1), 0}, + +#define RTL8192E_TRANS_SUS_TO_CARDEMU \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ + /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO , PWR_CMD_WRITE, BIT(0), 0}, \ + /*wait power state to suspend*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO , PWR_CMD_POLLING, BIT(1), BIT(1)}, \ + /*0x04[12:11] = 2b'01enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, + +#define RTL8192E_TRANS_CARDEMU_TO_CARDDIS \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ + /*0x07=0x20 , SOP option to disable BG/MB*/ \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0x20}, \ + /*Unlock small LDO Register*/ \ + {0x00CC, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(2), BIT(2)}, \ + /*Disable small LDO*/ \ + {0x0011, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(0), 0}, \ + /*0x04[12:11] = 2b'01 enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \ + PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \ + /*0x04[10] = 1, enable SW LPS*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(2), BIT(2)}, \ + /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO , PWR_CMD_WRITE, BIT(0), BIT(0)}, \ + /*wait power state to suspend*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO , PWR_CMD_POLLING, BIT(1), 0}, + +#define RTL8192E_TRANS_CARDDIS_TO_CARDEMU \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ + /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO , PWR_CMD_WRITE, BIT(0), 0}, \ + /*wait power state to suspend*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO , PWR_CMD_POLLING, BIT(1), BIT(1)}, \ + /*Enable small LDO*/ \ + {0x0011, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(0), BIT(0)}, \ + /*Lock small LDO Register*/ \ + {0x00CC, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(2), 0}, \ + /*0x04[12:11] = 2b'01enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, + +#define RTL8192E_TRANS_CARDEMU_TO_PDN \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ + /* 0x04[16] = 0*/ \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(0), 0}, \ + /* 0x04[15] = 1*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(7), BIT(7)}, + +#define RTL8192E_TRANS_PDN_TO_CARDEMU \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ + /* 0x04[15] = 0*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(7), 0}, + +#define RTL8192E_TRANS_ACT_TO_LPS \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ + /*PCIe DMA stop*/ \ + {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0xFF}, \ + /*Tx Pause*/ \ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0xFF}, \ + /*Should be zero if no packet is transmitting*/ \ + {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_POLLING, 0xFF, 0}, \ + /*Should be zero if no packet is transmitting*/ \ + {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_POLLING, 0xFF, 0}, \ + /*Should be zero if no packet is transmitting*/ \ + {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_POLLING, 0xFF, 0}, \ + /*Should be zero if no packet is transmitting*/ \ + {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_POLLING, 0xFF, 0}, \ + /*CCK and OFDM are disabled,and clock are gated*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(0), 0}, \ + /*Delay 1us*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US}, \ + /*Whole BB is reset*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(1), 0}, \ + /*Reset MAC TRX*/ \ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0x03}, \ + /*check if removed later*/ \ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(1), 0}, \ + /*When driver enter Sus/ Disable, enable LOP for BT*/ \ + {0x0093, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0x00}, \ + /*Respond TxOK to scheduler*/ \ + {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(5), BIT(5)}, + +#define RTL8192E_TRANS_LPS_TO_ACT \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ + /*SDIO RPWM, For Repeatly In and out, Taggle bit should be changed*/\ + {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO , PWR_CMD_WRITE, 0xFF, 0x84}, \ + /*USB RPWM*/ \ + {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0x84}, \ + /*PCIe RPWM*/ \ + {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0x84}, \ + /*Delay*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, \ + /*0x08[4] = 0 switch TSF to 40M*/ \ + {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(4), 0}, \ + /*Polling 0x109[7]=0 TSF in 40M*/ \ + {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_POLLING, BIT(7), 0}, \ + /*0x101[1] = 1*/ \ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(1), BIT(1)}, \ + /*0x100[7:0] = 0xFF enable WMAC TRX*/ \ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0xFF}, \ + /* 0x02[1:0] = 2b'11 enable BB macro*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(1) | BIT(0), BIT(1) | BIT(0)},\ + /*0x522 = 0*/ \ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0}, \ + /*Clear ISR*/ \ + {0x013D, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0xFF}, + +#define RTL8192E_TRANS_END \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ + {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + 0, PWR_CMD_END, 0, 0}, + +extern struct wlan_pwr_cfg rtl8192E_power_on_flow + [RTL8192E_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8192E_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8192E_radio_off_flow + [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8192E_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8192E_card_disable_flow + [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8192E_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8192E_card_enable_flow + [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8192E_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8192E_suspend_flow + [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8192E_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8192E_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8192E_resume_flow + [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8192E_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8192E_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8192E_hwpdn_flow + [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8192E_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8192E_enter_lps_flow + [RTL8192E_TRANS_ACT_TO_LPS_STEPS + + RTL8192E_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8192E_leave_lps_flow + [RTL8192E_TRANS_LPS_TO_ACT_STEPS + + RTL8192E_TRANS_END_STEPS]; + +/* RTL8192EE Power Configuration CMDs for PCIe interface */ +#define RTL8192E_NIC_PWR_ON_FLOW rtl8192E_power_on_flow +#define RTL8192E_NIC_RF_OFF_FLOW rtl8192E_radio_off_flow +#define RTL8192E_NIC_DISABLE_FLOW rtl8192E_card_disable_flow +#define RTL8192E_NIC_ENABLE_FLOW rtl8192E_card_enable_flow +#define RTL8192E_NIC_SUSPEND_FLOW rtl8192E_suspend_flow +#define RTL8192E_NIC_RESUME_FLOW rtl8192E_resume_flow +#define RTL8192E_NIC_PDN_FLOW rtl8192E_hwpdn_flow +#define RTL8192E_NIC_LPS_ENTER_FLOW rtl8192E_enter_lps_flow +#define RTL8192E_NIC_LPS_LEAVE_FLOW rtl8192E_leave_lps_flow + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h new file mode 100644 index 000000000000..1eaa1fab550d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/reg.h @@ -0,0 +1,2233 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92E_REG_H__ +#define __RTL92E_REG_H__ + +#define TXPKT_BUF_SELECT 0x69 +#define RXPKT_BUF_SELECT 0xA5 +#define DISABLE_TRXPKT_BUF_ACCESS 0x0 + +#define REG_SYS_ISO_CTRL 0x0000 +#define REG_SYS_FUNC_EN 0x0002 +#define REG_APS_FSMCO 0x0004 +#define REG_SYS_CLKR 0x0008 +#define REG_9346CR 0x000A +#define REG_EE_VPD 0x000C +#define REG_SYS_SWR_CTRL1 0x0010 +#define REG_SPS0_CTRL 0x0011 +#define REG_SYS_SWR_CTRL2 0x0014 +#define REG_SYS_SWR_CTRL3 0x0018 +#define REG_RSV_CTRL 0x001C +#define REG_RF_CTRL 0x001F +#define REG_LPLDO_CTRL 0x0023 +#define REG_AFE_CTRL1 0x0024 +#define REG_AFE_XTAL_CTRL 0x0024 +#define REG_AFE_CTRL2 0x0028 +#define REG_MAC_PHY_CTRL 0x002c +#define REG_AFE_CTRL3 0x002c +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define REG_PWR_DATA 0x0038 +#define REG_CAL_TIMER 0x003C +#define REG_ACLK_MON 0x003E +#define REG_GPIO_MUXCFG 0x0040 +#define REG_GPIO_IO_SEL 0x0042 +#define REG_MAC_PINMUX_CFG 0x0043 +#define REG_GPIO_PIN_CTRL 0x0044 +#define REG_GPIO_INTM 0x0048 +#define REG_LEDCFG0 0x004C +#define REG_LEDCFG1 0x004D +#define REG_LEDCFG2 0x004E +#define REG_LEDCFG3 0x004F +#define REG_FSIMR 0x0050 +#define REG_FSISR 0x0054 +#define REG_HSIMR 0x0058 +#define REG_HSISR 0x005c +#define REG_SDIO_CTRL 0x0070 +#define REG_OPT_CTRL 0x0074 +#define REG_GPIO_OUTPUT 0x006c +#define REG_AFE_CTRL4 0x0078 +#define REG_MCUFWDL 0x0080 + +#define REG_HIMR 0x00B0 +#define REG_HISR 0x00B4 +#define REG_HIMRE 0x00B8 +#define REG_HISRE 0x00BC + +#define REG_PMC_DBG_CTRL2 0x00CC +#define REG_EFUSE_ACCESS 0x00CF +#define REG_HPON_FSM 0x00EC +#define REG_SYS_CFG1 0x00F0 +#define REG_MAC_PHY_CTRL_NORMAL 0x00F8 +#define REG_SYS_CFG2 0x00FC + +#define REG_CR 0x0100 +#define REG_PBP 0x0104 +#define REG_PKT_BUFF_ACCESS_CTRL 0x0106 +#define REG_TRXDMA_CTRL 0x010C +#define REG_TRXFF_BNDY 0x0114 +#define REG_TRXFF_STATUS 0x0118 +#define REG_RXFF_PTR 0x011C + +#define REG_CPWM 0x012F +#define REG_FWIMR 0x0130 +#define REG_FWISR 0x0134 +#define REG_PKTBUF_DBG_CTRL 0x0140 +#define REG_RXPKTBUF_CTRL 0x0142 +#define REG_PKTBUF_DBG_DATA_L 0x0144 +#define REG_PKTBUF_DBG_DATA_H 0x0148 + +#define REG_TC0_CTRL 0x0150 +#define REG_TC1_CTRL 0x0154 +#define REG_TC2_CTRL 0x0158 +#define REG_TC3_CTRL 0x015C +#define REG_TC4_CTRL 0x0160 +#define REG_TCUNIT_BASE 0x0164 +#define REG_RSVD3 0x0168 +#define REG_C2HEVT_MSG_NORMAL 0x01A0 +#define REG_C2HEVT_CLEAR 0x01AF +#define REG_MCUTST_1 0x01c0 +#define REG_MCUTST_WOWLAN 0x01C7 +#define REG_FMETHR 0x01C8 +#define REG_HMETFR 0x01CC +#define REG_HMEBOX_0 0x01D0 +#define REG_HMEBOX_1 0x01D4 +#define REG_HMEBOX_2 0x01D8 +#define REG_HMEBOX_3 0x01DC + +#define REG_LLT_INIT 0x01E0 + +#define REG_HMEBOX_EXT_0 0x01F0 +#define REG_HMEBOX_EXT_1 0x01F4 +#define REG_HMEBOX_EXT_2 0x01F8 +#define REG_HMEBOX_EXT_3 0x01FC + +/*----------------------------------------------------- + * + * 0x0200h ~ 0x027Fh TXDMA Configuration + * + *----------------------------------------------------- + */ +#define REG_RQPN 0x0200 +#define REG_FIFOPAGE 0x0204 +#define REG_DWBCN0_CTRL 0x0208 +#define REG_TXDMA_OFFSET_CHK 0x020C +#define REG_TXDMA_STATUS 0x0210 +#define REG_RQPN_NPQ 0x0214 +#define REG_AUTO_LLT 0x0224 +#define REG_DWBCN1_CTRL 0x0228 + +/*----------------------------------------------------- + * + * 0x0280h ~ 0x02FFh RXDMA Configuration + * + *----------------------------------------------------- + */ +#define REG_RXDMA_AGG_PG_TH 0x0280 +#define REG_FW_UPD_RDPTR 0x0284 +#define REG_RXDMA_CONTROL 0x0286 +#define REG_RXPKT_NUM 0x0287 +#define REG_RXDMA_STATUS 0x0288 +#define REG_RXDMA_PRO 0x0290 +#define REG_EARLY_MODE_CONTROL 0x02BC +#define REG_RSVD5 0x02F0 +#define REG_RSVD6 0x02F4 + +/*----------------------------------------------------- + * + * 0x0300h ~ 0x03FFh PCIe + * + *----------------------------------------------------- + */ +#define REG_PCIE_CTRL_REG 0x0300 +#define REG_INT_MIG 0x0304 +#define REG_BCNQ_DESA 0x0308 +#define REG_MGQ_DESA 0x0310 +#define REG_VOQ_DESA 0x0318 +#define REG_VIQ_DESA 0x0320 +#define REG_BEQ_DESA 0x0328 +#define REG_BKQ_DESA 0x0330 +#define REG_RX_DESA 0x0338 +#define REG_HQ0_DESA 0x0340 +#define REG_HQ1_DESA 0x0348 +#define REG_HQ2_DESA 0x0350 +#define REG_HQ3_DESA 0x0358 +#define REG_HQ4_DESA 0x0360 +#define REG_HQ5_DESA 0x0368 +#define REG_HQ6_DESA 0x0370 +#define REG_HQ7_DESA 0x0378 +#define REG_MGQ_TXBD_NUM 0x0380 +#define REG_RX_RXBD_NUM 0x0382 +#define REG_VOQ_TXBD_NUM 0x0384 +#define REG_VIQ_TXBD_NUM 0x0386 +#define REG_BEQ_TXBD_NUM 0x0388 +#define REG_BKQ_TXBD_NUM 0x038A +#define REG_HI0Q_TXBD_NUM 0x038C +#define REG_HI1Q_TXBD_NUM 0x038E +#define REG_HI2Q_TXBD_NUM 0x0390 +#define REG_HI3Q_TXBD_NUM 0x0392 +#define REG_HI4Q_TXBD_NUM 0x0394 +#define REG_HI5Q_TXBD_NUM 0x0396 +#define REG_HI6Q_TXBD_NUM 0x0398 +#define REG_HI7Q_TXBD_NUM 0x039A +#define REG_TSFTIMER_HCI 0x039C +/*Read Write Point*/ +#define REG_VOQ_TXBD_IDX 0x03A0 +#define REG_VIQ_TXBD_IDX 0x03A4 +#define REG_BEQ_TXBD_IDX 0x03A8 +#define REG_BKQ_TXBD_IDX 0x03AC +#define REG_MGQ_TXBD_IDX 0x03B0 +#define REG_RXQ_TXBD_IDX 0x03B4 + +#define REG_HI0Q_TXBD_IDX 0x03B8 +#define REG_HI1Q_TXBD_IDX 0x03BC +#define REG_HI2Q_TXBD_IDX 0x03C0 +#define REG_HI3Q_TXBD_IDX 0x03C4 + +#define REG_HI4Q_TXBD_IDX 0x03C8 +#define REG_HI5Q_TXBD_IDX 0x03CC +#define REG_HI6Q_TXBD_IDX 0x03D0 +#define REG_HI7Q_TXBD_IDX 0x03D4 +#define REG_PCIE_HCPWM 0x03D8 +#define REG_PCIE_CTRL2 0x03DB +#define REG_PCIE_HRPWM 0x03DC +#define REG_H2C_MSG_DRV2FW_INFO 0x03E0 +#define REG_PCIE_C2H_MSG_REQUEST 0x03E4 +#define REG_BACKDOOR_DBI_WDATA 0x03E8 +#define REG_BACKDOOR_DBI_RDATA 0x03EC +#define REG_BACKDOOR_DBI_DATA 0x03F0 +#define REG_MDIO 0x03F4 +#define REG_MDIO_DATA 0x03F8 + +#define REG_HDAQ_DESA_NODEF 0x0000 +#define REG_CMDQ_DESA_NODEF 0x0000 +/* spec version 11 + *----------------------------------------------------- + * + * 0x0400h ~ 0x047Fh Protocol Configuration + * + *----------------------------------------------------- + */ +#define REG_VOQ_INFORMATION 0x0400 +#define REG_VIQ_INFORMATION 0x0404 +#define REG_BEQ_INFORMATION 0x0408 +#define REG_BKQ_INFORMATION 0x040C +#define REG_MGQ_INFORMATION 0x0410 +#define REG_HGQ_INFORMATION 0x0414 +#define REG_BCNQ_INFORMATION 0x0418 +#define REG_TXPKT_EMPTY 0x041A + +#define REG_FWHW_TXQ_CTRL 0x0420 +#define REG_HWSEQ_CTRL 0x0423 +#define REG_BCNQ_BDNY 0x0424 +#define REG_MGQ_BDNY 0x0425 +#define REG_LIFECTRL_CTRL 0x0426 +#define REG_MULTI_BCNQ_OFFSET 0x0427 +#define REG_SPEC_SIFS 0x0428 +#define REG_RETRY_LIMIT 0x042A +#define REG_TXBF_CTRL 0x042C +#define REG_DARFRC 0x0430 +#define REG_RARFRC 0x0438 +#define REG_RRSR 0x0440 +#define REG_ARFR0 0x0444 +#define REG_ARFR1 0x044C +#define REG_AMPDU_MAX_TIME 0x0456 +#define REG_BCNQ1_BDNY 0x0457 +#define REG_AGGLEN_LMT 0x0458 +#define REG_AMPDU_MIN_SPACE 0x045C +#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D +#define REG_NDPA_OPT_CTRL 0x045F +#define REG_FAST_EDCA_CTRL 0x0460 +#define REG_RD_RESP_PKT_TH 0x0463 +#define REG_POWER_STAGE1 0x04B4 +#define REG_POWER_STAGE2 0x04B8 +#define REG_AMPDU_BURST_MODE 0x04BC +#define REG_PKT_VO_VI_LIFE_TIME 0x04C0 +#define REG_PKT_BE_BK_LIFE_TIME 0x04C2 +#define REG_STBC_SETTING 0x04C4 +#define REG_PROT_MODE_CTRL 0x04C8 +#define REG_MAX_AGGR_NUM 0x04CA +#define REG_RTS_MAX_AGGR_NUM 0x04CB +#define REG_BAR_MODE_CTRL 0x04CC +#define REG_RA_TRY_RATE_AGG_LMT 0x04CF +#define REG_MACID_PKT_DROP0 0x04D0 + +/*----------------------------------------------------- + * + * 0x0500h ~ 0x05FFh EDCA Configuration + * + *----------------------------------------------------- + */ +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050C +#define REG_BCNTCFG 0x0510 +#define REG_PIFS 0x0512 +#define REG_RDG_PIFS 0x0513 +#define REG_SIFS_CTX 0x0514 +#define REG_SIFS_TRX 0x0516 +#define REG_AGGR_BREAK_TIME 0x051A +#define REG_SLOT 0x051B +#define REG_TX_PTCL_CTRL 0x0520 +#define REG_TXPAUSE 0x0522 +#define REG_DIS_TXREQ_CLR 0x0523 +#define REG_RD_CTRL 0x0524 + +#define REG_TBTT_PROHIBIT 0x0540 +#define REG_RD_NAV_NXT 0x0544 +#define REG_NAV_PROT_LEN 0x0546 +#define REG_BCN_CTRL 0x0550 +#define REG_BCN_CTRL_1 0x0551 +#define REG_MBID_NUM 0x0552 +#define REG_DUAL_TSF_RST 0x0553 +#define REG_BCN_INTERVAL 0x0554 +#define REG_DRVERLYINT 0x0558 +#define REG_BCNDMATIM 0x0559 +#define REG_ATIMWND 0x055A +#define REG_BCN_MAX_ERR 0x055D +#define REG_RXTSF_OFFSET_CCK 0x055E +#define REG_RXTSF_OFFSET_OFDM 0x055F +#define REG_TSFTR 0x0560 +#define REG_CTWND 0x0572 +#define REG_PSTIMER 0x0580 +#define REG_TIMER0 0x0584 +#define REG_TIMER1 0x0588 +#define REG_BCN_PREDL_ITV 0x058F +#define REG_ACMHWCTRL 0x05C0 + +/*----------------------------------------------------- + * + * 0x0600h ~ 0x07FFh WMAC Configuration + * + *----------------------------------------------------- + */ +#define REG_MAC_CR 0x0600 +#define REG_BWOPMODE 0x0603 +#define REG_TCR 0x0604 +#define REG_RCR 0x0608 +#define REG_RX_PKT_LIMIT 0x060C +#define REG_RX_DLK_TIME 0x060D +#define REG_RX_DRVINFO_SZ 0x060F + +#define REG_MACID 0x0610 +#define REG_BSSID 0x0618 +#define REG_MAR 0x0620 +#define REG_MBIDCAMCFG 0x0628 + +#define REG_USTIME_EDCA 0x0638 +#define REG_MAC_SPEC_SIFS 0x063A +#define REG_RESP_SIFS_CCK 0x063C +#define REG_RESP_SIFS_OFDM 0x063E +#define REG_ACKTO 0x0640 +#define REG_CTS2TO 0x0641 +#define REG_EIFS 0x0642 + +#define REG_NAV_UPPER 0x0652 + +/* Security*/ +#define REG_CAMCMD 0x0670 +#define REG_CAMWRITE 0x0674 +#define REG_CAMREAD 0x0678 +#define REG_CAMDBG 0x067C +#define REG_SECCFG 0x0680 + +/* Power*/ +#define REG_WOW_CTRL 0x0690 +#define REG_PS_RX_INFO 0x0692 +#define REG_UAPSD_TID 0x0693 +#define REG_WKFMCAM_NUM 0x0698 +#define REG_WKFMCAM_RWD 0x069C +#define REG_RXFLTMAP0 0x06A0 +#define REG_RXFLTMAP1 0x06A2 +#define REG_RXFLTMAP2 0x06A4 +#define REG_BCN_PSR_RPT 0x06A8 +#define REG_BT_COEX_TABLE 0x06C0 +#define REG_BFMER0_INFO 0x06E4 +#define REG_BFMER1_INFO 0x06EC +#define REG_CSI_RPT_PARAM_BW20 0x06F4 +#define REG_CSI_RPT_PARAM_BW40 0x06F8 +#define REG_CSI_RPT_PARAM_BW80 0x06FC +/* Hardware Port 2*/ +#define REG_MACID1 0x0700 +#define REG_BSSID1 0x0708 +#define REG_BFMEE_SEL 0x0714 +#define REG_SND_PTCL_CTRL 0x0718 + +#define CR9346 REG_9346CR +#define MSR (REG_CR + 2) +#define ISR REG_HISR +#define TSFR REG_TSFTR + +#define MACIDR0 REG_MACID +#define MACIDR4 (REG_MACID + 4) + +#define PBP REG_PBP + +#define IDR0 MACIDR0 +#define IDR4 MACIDR4 + +#define UNUSED_REGISTER 0x1BF +#define DCAM UNUSED_REGISTER +#define PSR UNUSED_REGISTER +#define BBADDR UNUSED_REGISTER +#define PHYDATAR UNUSED_REGISTER + +#define INVALID_BBRF_VALUE 0x12345678 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define CMDEEPROM_EN BIT(5) +#define CMDEEPROM_SEL BIT(4) +#define CMD9346CR_9356SEL BIT(4) +#define AUTOLOAD_EEPROM (CMDEEPROM_EN | CMDEEPROM_SEL) +#define AUTOLOAD_EFUSE CMDEEPROM_EN + +#define GPIOSEL_GPIO 0 +#define GPIOSEL_ENBT BIT(5) + +#define GPIO_IN REG_GPIO_PIN_CTRL +#define GPIO_OUT (REG_GPIO_PIN_CTRL + 1) +#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL + 2) +#define GPIO_MOD (REG_GPIO_PIN_CTRL + 3) + +#define MSR_NOLINK 0x00 +#define MSR_ADHOC 0x01 +#define MSR_INFRA 0x02 +#define MSR_AP 0x03 + +#define RRSR_RSC_OFFSET 21 +#define RRSR_SHORT_OFFSET 23 +#define RRSR_RSC_BW_40M 0x600000 +#define RRSR_RSC_UPSUBCHNL 0x400000 +#define RRSR_RSC_LOWSUBCHNL 0x200000 +#define RRSR_SHORT 0x800000 +#define RRSR_1M BIT(0) +#define RRSR_2M BIT(1) +#define RRSR_5_5M BIT(2) +#define RRSR_11M BIT(3) +#define RRSR_6M BIT(4) +#define RRSR_9M BIT(5) +#define RRSR_12M BIT(6) +#define RRSR_18M BIT(7) +#define RRSR_24M BIT(8) +#define RRSR_36M BIT(9) +#define RRSR_48M BIT(10) +#define RRSR_54M BIT(11) +#define RRSR_MCS0 BIT(12) +#define RRSR_MCS1 BIT(13) +#define RRSR_MCS2 BIT(14) +#define RRSR_MCS3 BIT(15) +#define RRSR_MCS4 BIT(16) +#define RRSR_MCS5 BIT(17) +#define RRSR_MCS6 BIT(18) +#define RRSR_MCS7 BIT(19) +#define BRSR_ACKSHORTPMB BIT(23) + +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 + +#define RATE_1M BIT(0) +#define RATE_2M BIT(1) +#define RATE_5_5M BIT(2) +#define RATE_11M BIT(3) +#define RATE_6M BIT(4) +#define RATE_9M BIT(5) +#define RATE_12M BIT(6) +#define RATE_18M BIT(7) +#define RATE_24M BIT(8) +#define RATE_36M BIT(9) +#define RATE_48M BIT(10) +#define RATE_54M BIT(11) +#define RATE_MCS0 BIT(12) +#define RATE_MCS1 BIT(13) +#define RATE_MCS2 BIT(14) +#define RATE_MCS3 BIT(15) +#define RATE_MCS4 BIT(16) +#define RATE_MCS5 BIT(17) +#define RATE_MCS6 BIT(18) +#define RATE_MCS7 BIT(19) +#define RATE_MCS8 BIT(20) +#define RATE_MCS9 BIT(21) +#define RATE_MCS10 BIT(22) +#define RATE_MCS11 BIT(23) +#define RATE_MCS12 BIT(24) +#define RATE_MCS13 BIT(25) +#define RATE_MCS14 BIT(26) +#define RATE_MCS15 BIT(27) + +#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) +#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\ + RATR_24M | RATR_36M | RATR_48M | RATR_54M) +#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 |\ + RATR_MCS3 | RATR_MCS4 | RATR_MCS5 |\ + RATR_MCS6 | RATR_MCS7) +#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 |\ + RATR_MCS11 | RATR_MCS12 | RATR_MCS13 |\ + RATR_MCS14 | RATR_MCS15) + +#define BW_OPMODE_20MHZ BIT(2) +#define BW_OPMODE_5G BIT(1) +#define CAM_VALID BIT(15) +#define CAM_NOTVALID 0x0000 +#define CAM_USEDK BIT(5) + +#define CAM_NONE 0x0 +#define CAM_WEP40 0x01 +#define CAM_TKIP 0x02 +#define CAM_AES 0x04 +#define CAM_WEP104 0x05 + +#define TOTAL_CAM_ENTRY 32 +#define HALF_CAM_ENTRY 16 + +#define CAM_WRITE BIT(16) +#define CAM_READ 0x00000000 +#define CAM_POLLINIG BIT(31) + +#define SCR_USEDK 0x01 +#define SCR_TXSEC_ENABLE 0x02 +#define SCR_RXSEC_ENABLE 0x04 + +/********************************************* +* 8192EE IMR/ISR bits +**********************************************/ +#define IMR_DISABLED 0x0 +/* IMR DW0(0x0060-0063) Bit 0-31 */ +#define IMR_TIMER2 BIT(31) +#define IMR_TIMER1 BIT(30) +#define IMR_PSTIMEOUT BIT(29) +#define IMR_GTINT4 BIT(28) +#define IMR_GTINT3 BIT(27) +#define IMR_TBDER BIT(26) +#define IMR_TBDOK BIT(25) +#define IMR_TSF_BIT32_TOGGLE BIT(24) +#define IMR_BCNDMAINT0 BIT(20) +#define IMR_BCNDOK0 BIT(16) +#define IMR_BCNDMAINT_E BIT(14) +#define IMR_ATIMEND BIT(12) +#define IMR_HISR1_IND_INT BIT(11) +#define IMR_C2HCMD BIT(10) +#define IMR_CPWM2 BIT(9) +#define IMR_CPWM BIT(8) +#define IMR_HIGHDOK BIT(7) +#define IMR_MGNTDOK BIT(6) +#define IMR_BKDOK BIT(5) +#define IMR_BEDOK BIT(4) +#define IMR_VIDOK BIT(3) +#define IMR_VODOK BIT(2) +#define IMR_RDU BIT(1) +#define IMR_ROK BIT(0) + +/* IMR DW1(0x00B4-00B7) Bit 0-31 */ +#define IMR_MCUERR BIT(28) +#define IMR_BCNDMAINT7 BIT(27) +#define IMR_BCNDMAINT6 BIT(26) +#define IMR_BCNDMAINT5 BIT(25) +#define IMR_BCNDMAINT4 BIT(24) +#define IMR_BCNDMAINT3 BIT(23) +#define IMR_BCNDMAINT2 BIT(22) +#define IMR_BCNDMAINT1 BIT(21) +#define IMR_BCNDOK7 BIT(20) +#define IMR_BCNDOK6 BIT(19) +#define IMR_BCNDOK5 BIT(18) +#define IMR_BCNDOK4 BIT(17) +#define IMR_BCNDOK3 BIT(16) +#define IMR_BCNDOK2 BIT(15) +#define IMR_BCNDOK1 BIT(14) +#define IMR_ATIMEND_E BIT(13) +#define IMR_TXERR BIT(11) +#define IMR_RXERR BIT(10) +#define IMR_TXFOVW BIT(9) +#define IMR_RXFOVW BIT(8) + +#define HWSET_MAX_SIZE 512 +#define EFUSE_MAX_SECTION 64 +#define EFUSE_REAL_CONTENT_LEN 256 +#define EFUSE_OOB_PROTECT_BYTES 18 + +#define EEPROM_DEFAULT_TSSI 0x0 +#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_BOARDTYPE 0x02 +#define EEPROM_DEFAULT_TXPOWER 0x1010 +#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 + +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_THERMALMETER 0x1A +#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 +#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 +#define EEPROM_DEFAULT_HT20_DIFF 2 +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 +#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 + +#define RF_OPTION1 0x79 +#define RF_OPTION2 0x7A +#define RF_OPTION3 0x7B +#define RF_OPTION4 0x7C + +#define EEPROM_DEFAULT_PID 0x1234 +#define EEPROM_DEFAULT_VID 0x5678 +#define EEPROM_DEFAULT_CUSTOMERID 0xAB +#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD +#define EEPROM_DEFAULT_VERSION 0 + +#define EEPROM_CHANNEL_PLAN_FCC 0x0 +#define EEPROM_CHANNEL_PLAN_IC 0x1 +#define EEPROM_CHANNEL_PLAN_ETSI 0x2 +#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 +#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 +#define EEPROM_CHANNEL_PLAN_MKK 0x5 +#define EEPROM_CHANNEL_PLAN_MKK1 0x6 +#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 +#define EEPROM_CHANNEL_PLAN_TELEC 0x8 +#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 +#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA +#define EEPROM_CHANNEL_PLAN_NCC 0xB +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + +#define EEPROM_CID_DEFAULT 0x0 +#define EEPROM_CID_TOSHIBA 0x4 +#define EEPROM_CID_CCX 0x10 +#define EEPROM_CID_QMI 0x0D +#define EEPROM_CID_WHQL 0xFE + +#define RTL8192E_EEPROM_ID 0x8129 + +#define EEPROM_HPON 0x02 +#define EEPROM_CLK 0x06 +#define EEPROM_TESTR 0x08 + +#define EEPROM_TXPOWERCCK 0x10 +#define EEPROM_TXPOWERHT40_1S 0x16 +#define EEPROM_TXPOWERHT20DIFF 0x1B +#define EEPROM_TXPOWER_OFDMDIFF 0x1B + +#define EEPROM_TX_PWR_INX 0x10 + +#define EEPROM_CHANNELPLAN 0xB8 +#define EEPROM_XTAL_92E 0xB9 +#define EEPROM_THERMAL_METER_92E 0xBA +#define EEPROM_IQK_LCK_92E 0xBB + +#define EEPROM_RF_BOARD_OPTION_92E 0xC1 +#define EEPROM_RF_FEATURE_OPTION_92E 0xC2 +#define EEPROM_RF_BT_SETTING_92E 0xC3 +#define EEPROM_VERSION 0xC4 +#define EEPROM_CUSTOMER_ID 0xC5 +#define EEPROM_RF_ANTENNA_OPT_92E 0xC9 + +#define EEPROM_MAC_ADDR 0xD0 +#define EEPROM_VID 0xD6 +#define EEPROM_DID 0xD8 +#define EEPROM_SVID 0xDA +#define EEPROM_SMID 0xDC + +#define STOPBECON BIT(6) +#define STOPHIGHT BIT(5) +#define STOPMGT BIT(4) +#define STOPVO BIT(3) +#define STOPVI BIT(2) +#define STOPBE BIT(1) +#define STOPBK BIT(0) + +#define RCR_APPFCS BIT(31) +#define RCR_APP_MIC BIT(30) +#define RCR_APP_ICV BIT(29) +#define RCR_APP_PHYST_RXFF BIT(28) +#define RCR_APP_BA_SSN BIT(27) +#define RCR_ENMBID BIT(24) +#define RCR_LSIGEN BIT(23) +#define RCR_MFBEN BIT(22) +#define RCR_HTC_LOC_CTRL BIT(14) +#define RCR_AMF BIT(13) +#define RCR_ACF BIT(12) +#define RCR_ADF BIT(11) +#define RCR_AICV BIT(9) +#define RCR_ACRC32 BIT(8) +#define RCR_CBSSID_BCN BIT(7) +#define RCR_CBSSID_DATA BIT(6) +#define RCR_CBSSID RCR_CBSSID_DATA +#define RCR_APWRMGT BIT(5) +#define RCR_ADD3 BIT(4) +#define RCR_AB BIT(3) +#define RCR_AM BIT(2) +#define RCR_APM BIT(1) +#define RCR_AAP BIT(0) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 + +#define RSV_CTRL 0x001C +#define RD_CTRL 0x0524 + +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_USB_VID 0xFE60 +#define REG_USB_PID 0xFE62 +#define REG_USB_OPTIONAL 0xFE64 +#define REG_USB_CHIRP_K 0xFE65 +#define REG_USB_PHY 0xFE66 +#define REG_USB_MAC_ADDR 0xFE70 +#define REG_USB_HRPWM 0xFE58 +#define REG_USB_HCPWM 0xFE57 + +#define SW18_FPWM BIT(3) + +#define ISO_MD2PP BIT(0) +#define ISO_UA2USB BIT(1) +#define ISO_UD2CORE BIT(2) +#define ISO_PA2PCIE BIT(3) +#define ISO_PD2CORE BIT(4) +#define ISO_IP2MAC BIT(5) +#define ISO_DIOP BIT(6) +#define ISO_DIOE BIT(7) +#define ISO_EB2CORE BIT(8) +#define ISO_DIOR BIT(9) + +#define PWC_EV25V BIT(14) +#define PWC_EV12V BIT(15) + +#define FEN_BBRSTB BIT(0) +#define FEN_BB_GLB_RSTN BIT(1) +#define FEN_USBA BIT(2) +#define FEN_UPLL BIT(3) +#define FEN_USBD BIT(4) +#define FEN_DIO_PCIE BIT(5) +#define FEN_PCIEA BIT(6) +#define FEN_PPLL BIT(7) +#define FEN_PCIED BIT(8) +#define FEN_DIOE BIT(9) +#define FEN_CPUEN BIT(10) +#define FEN_DCORE BIT(11) +#define FEN_ELDR BIT(12) +#define FEN_DIO_RF BIT(13) +#define FEN_HWPDN BIT(14) +#define FEN_MREGEN BIT(15) + +#define PFM_LDALL BIT(0) +#define PFM_ALDN BIT(1) +#define PFM_LDKP BIT(2) +#define PFM_WOWL BIT(3) +#define ENPDN BIT(4) +#define PDN_PL BIT(5) +#define APFM_ONMAC BIT(8) +#define APFM_OFF BIT(9) +#define APFM_RSM BIT(10) +#define AFSM_HSUS BIT(11) +#define AFSM_PCIE BIT(12) +#define APDM_MAC BIT(13) +#define APDM_HOST BIT(14) +#define APDM_HPDN BIT(15) +#define RDY_MACON BIT(16) +#define SUS_HOST BIT(17) +#define ROP_ALD BIT(20) +#define ROP_PWR BIT(21) +#define ROP_SPS BIT(22) +#define SOP_MRST BIT(25) +#define SOP_FUSE BIT(26) +#define SOP_ABG BIT(27) +#define SOP_AMB BIT(28) +#define SOP_RCK BIT(29) +#define SOP_A8M BIT(30) +#define XOP_BTCK BIT(31) + +#define ANAD16V_EN BIT(0) +#define ANA8M BIT(1) +#define MACSLP BIT(4) +#define LOADER_CLK_EN BIT(5) +#define _80M_SSC_DIS BIT(7) +#define _80M_SSC_EN_HO BIT(8) +#define PHY_SSC_RSTB BIT(9) +#define SEC_CLK_EN BIT(10) +#define MAC_CLK_EN BIT(11) +#define SYS_CLK_EN BIT(12) +#define RING_CLK_EN BIT(13) + +#define BOOT_FROM_EEPROM BIT(4) +#define EEPROM_EN BIT(5) + +#define AFE_BGEN BIT(0) +#define AFE_MBEN BIT(1) +#define MAC_ID_EN BIT(7) + +#define WLOCK_ALL BIT(0) +#define WLOCK_00 BIT(1) +#define WLOCK_04 BIT(2) +#define WLOCK_08 BIT(3) +#define WLOCK_40 BIT(4) +#define R_DIS_PRST_0 BIT(5) +#define R_DIS_PRST_1 BIT(6) +#define LOCK_ALL_EN BIT(7) + +#define RF_EN BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + +#define LDA15_EN BIT(0) +#define LDA15_STBY BIT(1) +#define LDA15_OBUF BIT(2) +#define LDA15_REG_VOS BIT(3) +#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) + +#define LDV12_EN BIT(0) +#define LDV12_SDBY BIT(1) +#define LPLDO_HSM BIT(2) +#define LPLDO_LSM_DIS BIT(3) +#define _LDV12_VADJ(x) (((x) & 0xF) << 4) + +#define XTAL_EN BIT(0) +#define XTAL_BSEL BIT(1) +#define _XTAL_BOSC(x) (((x) & 0x3) << 2) +#define _XTAL_CADJ(x) (((x) & 0xF) << 4) +#define XTAL_GATE_USB BIT(8) +#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) +#define XTAL_GATE_AFE BIT(11) +#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) +#define XTAL_RF_GATE BIT(14) +#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) +#define XTAL_GATE_DIG BIT(17) +#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) +#define XTAL_BT_GATE BIT(20) +#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) +#define _XTAL_GPIO(x) (((x) & 0x7) << 23) + +#define CKDLY_AFE BIT(26) +#define CKDLY_USB BIT(27) +#define CKDLY_DIG BIT(28) +#define CKDLY_BT BIT(29) + +#define APLL_EN BIT(0) +#define APLL_320_EN BIT(1) +#define APLL_FREF_SEL BIT(2) +#define APLL_EDGE_SEL BIT(3) +#define APLL_WDOGB BIT(4) +#define APLL_LPFEN BIT(5) + +#define APLL_REF_CLK_13MHZ 0x1 +#define APLL_REF_CLK_19_2MHZ 0x2 +#define APLL_REF_CLK_20MHZ 0x3 +#define APLL_REF_CLK_25MHZ 0x4 +#define APLL_REF_CLK_26MHZ 0x5 +#define APLL_REF_CLK_38_4MHZ 0x6 +#define APLL_REF_CLK_40MHZ 0x7 + +#define APLL_320EN BIT(14) +#define APLL_80EN BIT(15) +#define APLL_1MEN BIT(24) + +#define ALD_EN BIT(18) +#define EF_PD BIT(19) +#define EF_FLAG BIT(31) + +#define EF_TRPT BIT(7) +#define LDOE25_EN BIT(31) + +#define RSM_EN BIT(0) +#define TIMER_EN BIT(4) + +#define TRSW0EN BIT(2) +#define TRSW1EN BIT(3) +#define EROM_EN BIT(4) +#define ENBT BIT(5) +#define ENUART BIT(8) +#define UART_910 BIT(9) +#define ENPMAC BIT(10) +#define SIC_SWRST BIT(11) +#define ENSIC BIT(12) +#define SIC_23 BIT(13) +#define ENHDP BIT(14) +#define SIC_LBK BIT(15) + +#define LED0PL BIT(4) +#define LED1PL BIT(12) +#define LED0DIS BIT(7) + +#define MCUFWDL_EN BIT(0) +#define MCUFWDL_RDY BIT(1) +#define FWDL_CHKSUM_RPT BIT(2) +#define MACINI_RDY BIT(3) +#define BBINI_RDY BIT(4) +#define RFINI_RDY BIT(5) +#define WINTINI_RDY BIT(6) +#define CPRST BIT(23) + +#define XCLK_VLD BIT(0) +#define ACLK_VLD BIT(1) +#define UCLK_VLD BIT(2) +#define PCLK_VLD BIT(3) +#define PCIRSTB BIT(4) +#define V15_VLD BIT(5) +#define TRP_B15V_EN BIT(7) +#define SIC_IDLE BIT(8) +#define BD_MAC2 BIT(9) +#define BD_MAC1 BIT(10) +#define IC_MACPHY_MODE BIT(11) +#define VENDOR_ID BIT(19) +#define PAD_HWPD_IDN BIT(22) +#define TRP_VAUX_EN BIT(23) +#define TRP_BT_EN BIT(24) +#define BD_PKG_SEL BIT(25) +#define BD_HCI_SEL BIT(26) +#define TYPE_ID BIT(27) + +#define CHIP_VER_RTL_MASK 0xF000 +#define CHIP_VER_RTL_SHIFT 12 + +#define REG_LBMODE (REG_CR + 3) + +#define HCI_TXDMA_EN BIT(0) +#define HCI_RXDMA_EN BIT(1) +#define TXDMA_EN BIT(2) +#define RXDMA_EN BIT(3) +#define PROTOCOL_EN BIT(4) +#define SCHEDULE_EN BIT(5) +#define MACTXEN BIT(6) +#define MACRXEN BIT(7) +#define ENSWBCN BIT(8) +#define ENSEC BIT(9) + +#define _NETTYPE(x) (((x) & 0x3) << 16) +#define MASK_NETTYPE 0x30000 +#define NT_NO_LINK 0x0 +#define NT_LINK_AD_HOC 0x1 +#define NT_LINK_AP 0x2 +#define NT_AS_AP 0x3 + +#define _LBMODE(x) (((x) & 0xF) << 24) +#define MASK_LBMODE 0xF000000 +#define LOOPBACK_NORMAL 0x0 +#define LOOPBACK_IMMEDIATELY 0xB +#define LOOPBACK_MAC_DELAY 0x3 +#define LOOPBACK_PHY 0x1 +#define LOOPBACK_DMA 0x7 + +#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) +#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) +#define _PSRX_MASK 0xF +#define _PSTX_MASK 0xF0 +#define _PSRX(x) (x) +#define _PSTX(x) ((x) << 4) + +#define PBP_64 0x0 +#define PBP_128 0x1 +#define PBP_256 0x2 +#define PBP_512 0x3 +#define PBP_1024 0x4 + +#define RXDMA_ARBBW_EN BIT(0) +#define RXSHFT_EN BIT(1) +#define RXDMA_AGG_EN BIT(2) +#define QS_VO_QUEUE BIT(8) +#define QS_VI_QUEUE BIT(9) +#define QS_BE_QUEUE BIT(10) +#define QS_BK_QUEUE BIT(11) +#define QS_MANAGER_QUEUE BIT(12) +#define QS_HIGH_QUEUE BIT(13) + +#define HQSEL_VOQ BIT(0) +#define HQSEL_VIQ BIT(1) +#define HQSEL_BEQ BIT(2) +#define HQSEL_BKQ BIT(3) +#define HQSEL_MGTQ BIT(4) +#define HQSEL_HIQ BIT(5) + +#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) +#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) +#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) +#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) +#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) +#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) + +#define QUEUE_LOW 1 +#define QUEUE_NORMAL 2 +#define QUEUE_HIGH 3 + +#define _LLT_NO_ACTIVE 0x0 +#define _LLT_WRITE_ACCESS 0x1 +#define _LLT_READ_ACCESS 0x2 + +#define _LLT_INIT_DATA(x) ((x) & 0xFF) +#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) +#define _LLT_OP(x) (((x) & 0x3) << 30) +#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) + +#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) +#define BB_WRITE_EN BIT(30) +#define BB_READ_EN BIT(31) + +#define _HPQ(x) ((x) & 0xFF) +#define _LPQ(x) (((x) & 0xFF) << 8) +#define _PUBQ(x) (((x) & 0xFF) << 16) +#define _NPQ(x) ((x) & 0xFF) + +#define HPQ_PUBLIC_DIS BIT(24) +#define LPQ_PUBLIC_DIS BIT(25) +#define LD_RQPN BIT(31) + +#define BCN_VALID BIT(16) +#define BCN_HEAD(x) (((x) & 0xFF) << 8) +#define BCN_HEAD_MASK 0xFF00 + +#define BLK_DESC_NUM_SHIFT 4 +#define BLK_DESC_NUM_MASK 0xF + +#define DROP_DATA_EN BIT(9) + +#define EN_AMPDU_RTY_NEW BIT(7) + +#define _INIRTSMCS_SEL(x) ((x) & 0x3F) + +#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) +#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) + +#define RATE_REG_BITMAP_ALL 0xFFFFF + +#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) + +#define _RRSR_RSC(x) (((x) & 0x3) << 21) +#define RRSR_RSC_RESERVED 0x0 +#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 +#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 +#define RRSR_RSC_DUPLICATE_MODE 0x3 + +#define USE_SHORT_G1 BIT(20) + +#define _AGGLMT_MCS0(x) ((x) & 0xF) +#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) +#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) +#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) +#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) +#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) +#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) +#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) + +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + +#define _DARF_RC1(x) ((x) & 0x1F) +#define _DARF_RC2(x) (((x) & 0x1F) << 8) +#define _DARF_RC3(x) (((x) & 0x1F) << 16) +#define _DARF_RC4(x) (((x) & 0x1F) << 24) +#define _DARF_RC5(x) ((x) & 0x1F) +#define _DARF_RC6(x) (((x) & 0x1F) << 8) +#define _DARF_RC7(x) (((x) & 0x1F) << 16) +#define _DARF_RC8(x) (((x) & 0x1F) << 24) + +#define _RARF_RC1(x) ((x) & 0x1F) +#define _RARF_RC2(x) (((x) & 0x1F) << 8) +#define _RARF_RC3(x) (((x) & 0x1F) << 16) +#define _RARF_RC4(x) (((x) & 0x1F) << 24) +#define _RARF_RC5(x) ((x) & 0x1F) +#define _RARF_RC6(x) (((x) & 0x1F) << 8) +#define _RARF_RC7(x) (((x) & 0x1F) << 16) +#define _RARF_RC8(x) (((x) & 0x1F) << 24) + +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + +#define _AIFS(x) (x) +#define _ECW_MAX_MIN(x) ((x) << 8) +#define _TXOP_LIMIT(x) ((x) << 16) + +#define _BCNIFS(x) ((x) & 0xFF) +#define _BCNECW(x) ((((x) & 0xF)) << 8) + +#define _LRL(x) ((x) & 0x3F) +#define _SRL(x) (((x) & 0x3F) << 8) + +#define _SIFS_CCK_CTX(x) ((x) & 0xFF) +#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8) + +#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) +#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8) + +#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) + +#define DIS_EDCA_CNT_DWN BIT(11) + +#define EN_MBSSID BIT(1) +#define EN_TXBCN_RPT BIT(2) +#define EN_BCN_FUNCTION BIT(3) + +#define TSFTR_RST BIT(0) +#define TSFTR1_RST BIT(1) + +#define STOP_BCNQ BIT(6) + +#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) +#define DIS_TSF_UDT0_TEST_CHIP BIT(5) + +#define ACMHW_HWEN BIT(0) +#define ACMHW_BEQEN BIT(1) +#define ACMHW_VIQEN BIT(2) +#define ACMHW_VOQEN BIT(3) +#define ACMHW_BEQSTATUS BIT(4) +#define ACMHW_VIQSTATUS BIT(5) +#define ACMHW_VOQSTATUS BIT(6) + +#define APSDOFF BIT(6) +#define APSDOFF_STATUS BIT(7) + +#define BW_20MHZ BIT(2) + +#define RATE_BITMAP_ALL 0xFFFFF + +#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 + +#define TSFRST BIT(0) +#define DIS_GCLK BIT(1) +#define PAD_SEL BIT(2) +#define PWR_ST BIT(6) +#define PWRBIT_OW_EN BIT(7) +#define ACRC BIT(8) +#define CFENDFORM BIT(9) +#define ICV BIT(10) + +#define AAP BIT(0) +#define APM BIT(1) +#define AM BIT(2) +#define AB BIT(3) +#define ADD3 BIT(4) +#define APWRMGT BIT(5) +#define CBSSID BIT(6) +#define CBSSID_DATA BIT(6) +#define CBSSID_BCN BIT(7) +#define ACRC32 BIT(8) +#define AICV BIT(9) +#define ADF BIT(11) +#define ACF BIT(12) +#define AMF BIT(13) +#define HTC_LOC_CTRL BIT(14) +#define UC_DATA_EN BIT(16) +#define BM_DATA_EN BIT(17) +#define MFBEN BIT(22) +#define LSIGEN BIT(23) +#define ENMBID BIT(24) +#define APP_BASSN BIT(27) +#define APP_PHYSTS BIT(28) +#define APP_ICV BIT(29) +#define APP_MIC BIT(30) +#define APP_FCS BIT(31) + +#define _MIN_SPACE(x) ((x) & 0x7) +#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) + +#define RXERR_TYPE_OFDM_PPDU 0 +#define RXERR_TYPE_OFDM_FALSE_ALARM 1 +#define RXERR_TYPE_OFDM_MPDU_OK 2 +#define RXERR_TYPE_OFDM_MPDU_FAIL 3 +#define RXERR_TYPE_CCK_PPDU 4 +#define RXERR_TYPE_CCK_FALSE_ALARM 5 +#define RXERR_TYPE_CCK_MPDU_OK 6 +#define RXERR_TYPE_CCK_MPDU_FAIL 7 +#define RXERR_TYPE_HT_PPDU 8 +#define RXERR_TYPE_HT_FALSE_ALARM 9 +#define RXERR_TYPE_HT_MPDU_TOTAL 10 +#define RXERR_TYPE_HT_MPDU_OK 11 +#define RXERR_TYPE_HT_MPDU_FAIL 12 +#define RXERR_TYPE_RX_FULL_DROP 15 + +#define RXERR_COUNTER_MASK 0xFFFFF +#define RXERR_RPT_RST BIT(27) +#define _RXERR_RPT_SEL(type) ((type) << 28) + +#define SCR_TXUSEDK BIT(0) +#define SCR_RXUSEDK BIT(1) +#define SCR_TXENCENABLE BIT(2) +#define SCR_RXDECENABLE BIT(3) +#define SCR_SKBYA2 BIT(4) +#define SCR_NOSKMC BIT(5) +#define SCR_TXBCUSEDK BIT(6) +#define SCR_RXBCUSEDK BIT(7) + +#define USB_IS_HIGH_SPEED 0 +#define USB_IS_FULL_SPEED 1 +#define USB_SPEED_MASK BIT(5) + +#define USB_NORMAL_SIE_EP_MASK 0xF +#define USB_NORMAL_SIE_EP_SHIFT 4 + +#define USB_TEST_EP_MASK 0x30 +#define USB_TEST_EP_SHIFT 4 + +#define USB_AGG_EN BIT(3) + +#define MAC_ADDR_LEN 6 +#define LAST_ENTRY_OF_TX_PKT_BUFFER 175 + +#define POLLING_LLT_THRESHOLD 20 +#define POLLING_READY_TIMEOUT_COUNT 3000 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define EPROM_CMD_OPERATING_MODE_MASK ((1 << 7) | (1 << 6)) +#define EPROM_CMD_CONFIG 0x3 +#define EPROM_CMD_LOAD 1 + +#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE + +#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) + +#define RPMAC_RESET 0x100 +#define RPMAC_TXSTART 0x104 +#define RPMAC_TXLEGACYSIG 0x108 +#define RPMAC_TXHTSIG1 0x10c +#define RPMAC_TXHTSIG2 0x110 +#define RPMAC_PHYDEBUG 0x114 +#define RPMAC_TXPACKETNUM 0x118 +#define RPMAC_TXIDLE 0x11c +#define RPMAC_TXMACHEADER0 0x120 +#define RPMAC_TXMACHEADER1 0x124 +#define RPMAC_TXMACHEADER2 0x128 +#define RPMAC_TXMACHEADER3 0x12c +#define RPMAC_TXMACHEADER4 0x130 +#define RPMAC_TXMACHEADER5 0x134 +#define RPMAC_TXDADATYPE 0x138 +#define RPMAC_TXRANDOMSEED 0x13c +#define RPMAC_CCKPLCPPREAMBLE 0x140 +#define RPMAC_CCKPLCPHEADER 0x144 +#define RPMAC_CCKCRC16 0x148 +#define RPMAC_OFDMRXCRC32OK 0x170 +#define RPMAC_OFDMRXCRC32ER 0x174 +#define RPMAC_OFDMRXPARITYER 0x178 +#define RPMAC_OFDMRXCRC8ER 0x17c +#define RPMAC_CCKCRXRC16ER 0x180 +#define RPMAC_CCKCRXRC32ER 0x184 +#define RPMAC_CCKCRXRC32OK 0x188 +#define RPMAC_TXSTATUS 0x18c + +#define RFPGA0_RFMOD 0x800 + +#define RFPGA0_TXINFO 0x804 +#define RFPGA0_PSDFUNCTION 0x808 + +#define RFPGA0_TXGAINSTAGE 0x80c + +#define RFPGA0_RFTIMING1 0x810 +#define RFPGA0_RFTIMING2 0x814 + +#define RFPGA0_XA_HSSIPARAMETER1 0x820 +#define RFPGA0_XA_HSSIPARAMETER2 0x824 +#define RFPGA0_XB_HSSIPARAMETER1 0x828 +#define RFPGA0_XB_HSSIPARAMETER2 0x82c + +#define RFPGA0_XA_LSSIPARAMETER 0x840 +#define RFPGA0_XB_LSSIPARAMETER 0x844 + +#define RFPGA0_RFWAKEUPPARAMETER 0x850 +#define RFPGA0_RFSLEEPUPPARAMETER 0x854 + +#define RFPGA0_XAB_SWITCHCONTROL 0x858 +#define RFPGA0_XCD_SWITCHCONTROL 0x85c + +#define RFPGA0_XA_RFINTERFACEOE 0x860 +#define RFPGA0_XB_RFINTERFACEOE 0x864 + +#define RFPGA0_XAB_RFINTERFACESW 0x870 +#define RFPGA0_XCD_RFINTERFACESW 0x874 + +#define RFPGA0_XAB_RFPARAMETER 0x878 +#define RFPGA0_XCD_RFPARAMETER 0x87c + +#define RFPGA0_ANALOGPARAMETER1 0x880 +#define RFPGA0_ANALOGPARAMETER2 0x884 +#define RFPGA0_ANALOGPARAMETER3 0x888 +#define RFPGA0_ANALOGPARAMETER4 0x88c + +#define RFPGA0_XA_LSSIREADBACK 0x8a0 +#define RFPGA0_XB_LSSIREADBACK 0x8a4 +#define RFPGA0_XC_LSSIREADBACK 0x8a8 +#define RFPGA0_XD_LSSIREADBACK 0x8ac + +#define RFPGA0_PSDREPORT 0x8b4 +#define TRANSCEIVEA_HSPI_READBACK 0x8b8 +#define TRANSCEIVEB_HSPI_READBACK 0x8bc +#define REG_SC_CNT 0x8c4 +#define RFPGA0_XAB_RFINTERFACERB 0x8e0 +#define RFPGA0_XCD_RFINTERFACERB 0x8e4 + +#define RFPGA1_RFMOD 0x900 + +#define RFPGA1_TXBLOCK 0x904 +#define RFPGA1_DEBUGSELECT 0x908 +#define RFPGA1_TXINFO 0x90c + +#define RCCK0_SYSTEM 0xa00 + +#define RCCK0_AFESETTING 0xa04 +#define RCCK0_CCA 0xa08 + +#define RCCK0_RXAGC1 0xa0c +#define RCCK0_RXAGC2 0xa10 + +#define RCCK0_RXHP 0xa14 + +#define RCCK0_DSPPARAMETER1 0xa18 +#define RCCK0_DSPPARAMETER2 0xa1c + +#define RCCK0_TXFILTER1 0xa20 +#define RCCK0_TXFILTER2 0xa24 +#define RCCK0_DEBUGPORT 0xa28 +#define RCCK0_FALSEALARMREPORT 0xa2c +#define RCCK0_TRSSIREPORT 0xa50 +#define RCCK0_RXREPORT 0xa54 +#define RCCK0_FACOUNTERLOWER 0xa5c +#define RCCK0_FACOUNTERUPPER 0xa58 +#define RCCK0_CCA_CNT 0xa60 + +/* PageB(0xB00) */ +#define RPDP_ANTA 0xb00 +#define RPDP_ANTA_4 0xb04 +#define RPDP_ANTA_8 0xb08 +#define RPDP_ANTA_C 0xb0c +#define RPDP_ANTA_10 0xb10 +#define RPDP_ANTA_14 0xb14 +#define RPDP_ANTA_18 0xb18 +#define RPDP_ANTA_1C 0xb1c +#define RPDP_ANTA_20 0xb20 +#define RPDP_ANTA_24 0xb24 + +#define RCONFIG_PMPD_ANTA 0xb28 +#define RCONFIG_RAM64x16 0xb2c + +#define RBNDA 0xb30 +#define RHSSIPAR 0xb34 + +#define RCONFIG_ANTA 0xb68 +#define RCONFIG_ANTB 0xb6c + +#define RPDP_ANTB 0xb70 +#define RPDP_ANTB_4 0xb74 +#define RPDP_ANTB_8 0xb78 +#define RPDP_ANTB_C 0xb7c +#define RPDP_ANTB_10 0xb80 +#define RPDP_ANTB_14 0xb84 +#define RPDP_ANTB_18 0xb88 +#define RPDP_ANTB_1C 0xb8c +#define RPDP_ANTB_20 0xb90 +#define RPDP_ANTB_24 0xb94 + +#define RCONFIG_PMPD_ANTB 0xb98 + +#define RBNDB 0xba0 + +#define RAPK 0xbd8 +#define RPM_RX0_ANTA 0xbdc +#define RPM_RX1_ANTA 0xbe0 +#define RPM_RX2_ANTA 0xbe4 +#define RPM_RX3_ANTA 0xbe8 +#define RPM_RX0_ANTB 0xbec +#define RPM_RX1_ANTB 0xbf0 +#define RPM_RX2_ANTB 0xbf4 +#define RPM_RX3_ANTB 0xbf8 + +/*Page C*/ +#define ROFDM0_LSTF 0xc00 + +#define ROFDM0_TRXPATHENABLE 0xc04 +#define ROFDM0_TRMUXPAR 0xc08 +#define ROFDM0_TRSWISOLATION 0xc0c + +#define ROFDM0_XARXAFE 0xc10 +#define ROFDM0_XARXIQIMBALANCE 0xc14 +#define ROFDM0_XBRXAFE 0xc18 +#define ROFDM0_XBRXIQIMBALANCE 0xc1c +#define ROFDM0_XCRXAFE 0xc20 +#define ROFDM0_XCRXIQIMBANLANCE 0xc24 +#define ROFDM0_XDRXAFE 0xc28 +#define ROFDM0_XDRXIQIMBALANCE 0xc2c + +#define ROFDM0_RXDETECTOR1 0xc30 +#define ROFDM0_RXDETECTOR2 0xc34 +#define ROFDM0_RXDETECTOR3 0xc38 +#define ROFDM0_RXDETECTOR4 0xc3c + +#define ROFDM0_RXDSP 0xc40 +#define ROFDM0_CFOANDDAGC 0xc44 +#define ROFDM0_CCADROPTHRESHOLD 0xc48 +#define ROFDM0_ECCATHRESHOLD 0xc4c + +#define ROFDM0_XAAGCCORE1 0xc50 +#define ROFDM0_XAAGCCORE2 0xc54 +#define ROFDM0_XBAGCCORE1 0xc58 +#define ROFDM0_XBAGCCORE2 0xc5c +#define ROFDM0_XCAGCCORE1 0xc60 +#define ROFDM0_XCAGCCORE2 0xc64 +#define ROFDM0_XDAGCCORE1 0xc68 +#define ROFDM0_XDAGCCORE2 0xc6c + +#define ROFDM0_AGCPARAMETER1 0xc70 +#define ROFDM0_AGCPARAMETER2 0xc74 +#define ROFDM0_AGCRSSITABLE 0xc78 +#define ROFDM0_HTSTFAGC 0xc7c + +#define ROFDM0_XATXIQIMBALANCE 0xc80 +#define ROFDM0_XATXAFE 0xc84 +#define ROFDM0_XBTXIQIMBALANCE 0xc88 +#define ROFDM0_XBTXAFE 0xc8c +#define ROFDM0_XCTXIQIMBALANCE 0xc90 +#define ROFDM0_XCTXAFE 0xc94 +#define ROFDM0_XDTXIQIMBALANCE 0xc98 +#define ROFDM0_XDTXAFE 0xc9c + +#define ROFDM0_RXIQEXTANTA 0xca0 +#define ROFDM0_TXCOEFF1 0xca4 +#define ROFDM0_TXCOEFF2 0xca8 +#define ROFDM0_TXCOEFF3 0xcac +#define ROFDM0_TXCOEFF4 0xcb0 +#define ROFDM0_TXCOEFF5 0xcb4 +#define ROFDM0_TXCOEFF6 0xcb8 + +#define ROFDM0_RXHPPARAMETER 0xce0 +#define ROFDM0_TXPSEUDONOISEWGT 0xce4 +#define ROFDM0_FRAMESYNC 0xcf0 +#define ROFDM0_DFSREPORT 0xcf4 + +#define ROFDM1_LSTF 0xd00 +#define ROFDM1_TRXPATHENABLE 0xd04 + +#define ROFDM1_CF0 0xd08 +#define ROFDM1_CSI1 0xd10 +#define ROFDM1_SBD 0xd14 +#define ROFDM1_CSI2 0xd18 +#define ROFDM1_CFOTRACKING 0xd2c +#define ROFDM1_TRXMESAURE1 0xd34 +#define ROFDM1_INTFDET 0xd3c +#define ROFDM1_PSEUDONOISESTATEAB 0xd50 +#define ROFDM1_PSEUDONOISESTATECD 0xd54 +#define ROFDM1_RXPSEUDONOISEWGT 0xd58 + +#define ROFDM_PHYCOUNTER1 0xda0 +#define ROFDM_PHYCOUNTER2 0xda4 +#define ROFDM_PHYCOUNTER3 0xda8 + +#define ROFDM_SHORTCFOAB 0xdac +#define ROFDM_SHORTCFOCD 0xdb0 +#define ROFDM_LONGCFOAB 0xdb4 +#define ROFDM_LONGCFOCD 0xdb8 +#define ROFDM_TAILCF0AB 0xdbc +#define ROFDM_TAILCF0CD 0xdc0 +#define ROFDM_PWMEASURE1 0xdc4 +#define ROFDM_PWMEASURE2 0xdc8 +#define ROFDM_BWREPORT 0xdcc +#define ROFDM_AGCREPORT 0xdd0 +#define ROFDM_RXSNR 0xdd4 +#define ROFDM_RXEVMCSI 0xdd8 +#define ROFDM_SIGREPORT 0xddc + +#define RTXAGC_A_RATE18_06 0xe00 +#define RTXAGC_A_RATE54_24 0xe04 +#define RTXAGC_A_CCK1_MCS32 0xe08 +#define RTXAGC_A_MCS03_MCS00 0xe10 +#define RTXAGC_A_MCS07_MCS04 0xe14 +#define RTXAGC_A_MCS11_MCS08 0xe18 +#define RTXAGC_A_MCS15_MCS12 0xe1c + +#define RTXAGC_B_RATE18_06 0x830 +#define RTXAGC_B_RATE54_24 0x834 +#define RTXAGC_B_CCK1_55_MCS32 0x838 +#define RTXAGC_B_MCS03_MCS00 0x83c +#define RTXAGC_B_MCS07_MCS04 0x848 +#define RTXAGC_B_MCS11_MCS08 0x84c +#define RTXAGC_B_MCS15_MCS12 0x868 +#define RTXAGC_B_CCK11_A_CCK2_11 0x86c + +#define RFPGA0_IQK 0xe28 +#define RTX_IQK_TONE_A 0xe30 +#define RRX_IQK_TONE_A 0xe34 +#define RTX_IQK_PI_A 0xe38 +#define RRX_IQK_PI_A 0xe3c + +#define RTX_IQK 0xe40 +#define RRX_IQK 0xe44 +#define RIQK_AGC_PTS 0xe48 +#define RIQK_AGC_RSP 0xe4c +#define RTX_IQK_TONE_B 0xe50 +#define RRX_IQK_TONE_B 0xe54 +#define RTX_IQK_PI_B 0xe58 +#define RRX_IQK_PI_B 0xe5c +#define RIQK_AGC_CONT 0xe60 + +#define RBLUE_TOOTH 0xe6c +#define RRX_WAIT_CCA 0xe70 +#define RTX_CCK_RFON 0xe74 +#define RTX_CCK_BBON 0xe78 +#define RTX_OFDM_RFON 0xe7c +#define RTX_OFDM_BBON 0xe80 +#define RTX_TO_RX 0xe84 +#define RTX_TO_TX 0xe88 +#define RRX_CCK 0xe8c + +#define RTX_POWER_BEFORE_IQK_A 0xe94 +#define RTX_POWER_AFTER_IQK_A 0xe9c + +#define RRX_POWER_BEFORE_IQK_A 0xea0 +#define RRX_POWER_BEFORE_IQK_A_2 0xea4 +#define RRX_POWER_AFTER_IQK_A 0xea8 +#define RRX_POWER_AFTER_IQK_A_2 0xeac + +#define RTX_POWER_BEFORE_IQK_B 0xeb4 +#define RTX_POWER_AFTER_IQK_B 0xebc + +#define RRX_POWER_BEFORE_IQK_B 0xec0 +#define RRX_POWER_BEFORE_IQK_B_2 0xec4 +#define RRX_POWER_AFTER_IQK_B 0xec8 +#define RRX_POWER_AFTER_IQK_B_2 0xecc + +#define RRX_OFDM 0xed0 +#define RRX_WAIT_RIFS 0xed4 +#define RRX_TO_RX 0xed8 +#define RSTANDBY 0xedc +#define RSLEEP 0xee0 +#define RPMPD_ANAEN 0xeec + +#define RZEBRA1_HSSIENABLE 0x0 +#define RZEBRA1_TRXENABLE1 0x1 +#define RZEBRA1_TRXENABLE2 0x2 +#define RZEBRA1_AGC 0x4 +#define RZEBRA1_CHARGEPUMP 0x5 +#define RZEBRA1_CHANNEL 0x7 + +#define RZEBRA1_TXGAIN 0x8 +#define RZEBRA1_TXLPF 0x9 +#define RZEBRA1_RXLPF 0xb +#define RZEBRA1_RXHPFCORNER 0xc + +#define RGLOBALCTRL 0 +#define RRTL8256_TXLPF 19 +#define RRTL8256_RXLPF 11 +#define RRTL8258_TXLPF 0x11 +#define RRTL8258_RXLPF 0x13 +#define RRTL8258_RSSILPF 0xa + +#define RF_AC 0x00 + +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_POW_TRSW 0x05 + +#define RF_GAIN_RX 0x06 +#define RF_GAIN_TX 0x07 + +#define RF_TXM_IDAC 0x08 +#define RF_BS_IQGEN 0x0F + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 + +#define RF_RX_AGC_HP 0x12 +#define RF_TX_AGC 0x13 +#define RF_BIAS 0x14 +#define RF_IPA 0x15 +#define RF_POW_ABILITY 0x17 +#define RF_MODE_AG 0x18 +#define RRFCHANNEL 0x18 +#define RF_CHNLBW 0x18 +#define RF_TOP 0x19 + +#define RF_RX_G1 0x1A +#define RF_RX_G2 0x1B + +#define RF_RX_BB2 0x1C +#define RF_RX_BB1 0x1D + +#define RF_RCK1 0x1E +#define RF_RCK2 0x1F + +#define RF_TX_G1 0x20 +#define RF_TX_G2 0x21 +#define RF_TX_G3 0x22 + +#define RF_TX_BB1 0x23 +#define RF_T_METER 0x42 + +#define RF_SYN_G1 0x25 +#define RF_SYN_G2 0x26 +#define RF_SYN_G3 0x27 +#define RF_SYN_G4 0x28 +#define RF_SYN_G5 0x29 +#define RF_SYN_G6 0x2A +#define RF_SYN_G7 0x2B +#define RF_SYN_G8 0x2C + +#define RF_RCK_OS 0x30 +#define RF_TXPA_G1 0x31 +#define RF_TXPA_G2 0x32 +#define RF_TXPA_G3 0x33 + +#define RF_TX_BIAS_A 0x35 +#define RF_TX_BIAS_D 0x36 +#define RF_LOBF_9 0x38 +#define RF_RXRF_A3 0x3C +#define RF_TRSW 0x3F + +#define RF_TXRF_A2 0x41 +#define RF_TXPA_G4 0x46 +#define RF_TXPA_A4 0x4B + +#define RF_WE_LUT 0xEF + +#define BBBRESETB 0x100 +#define BGLOBALRESETB 0x200 +#define BOFDMTXSTART 0x4 +#define BCCKTXSTART 0x8 +#define BCRC32DEBUG 0x100 +#define BPMACLOOPBACK 0x10 +#define BTXLSIG 0xffffff +#define BOFDMTXRATE 0xf +#define BOFDMTXRESERVED 0x10 +#define BOFDMTXLENGTH 0x1ffe0 +#define BOFDMTXPARITY 0x20000 +#define BTXHTSIG1 0xffffff +#define BTXHTMCSRATE 0x7f +#define BTXHTBW 0x80 +#define BTXHTLENGTH 0xffff00 +#define BTXHTSIG2 0xffffff +#define BTXHTSMOOTHING 0x1 +#define BTXHTSOUNDING 0x2 +#define BTXHTRESERVED 0x4 +#define BTXHTAGGREATION 0x8 +#define BTXHTSTBC 0x30 +#define BTXHTADVANCECODING 0x40 +#define BTXHTSHORTGI 0x80 +#define BTXHTNUMBERHT_LTF 0x300 +#define BTXHTCRC8 0x3fc00 +#define BCOUNTERRESET 0x10000 +#define BNUMOFOFDMTX 0xffff +#define BNUMOFCCKTX 0xffff0000 +#define BTXIDLEINTERVAL 0xffff +#define BOFDMSERVICE 0xffff0000 +#define BTXMACHEADER 0xffffffff +#define BTXDATAINIT 0xff +#define BTXHTMODE 0x100 +#define BTXDATATYPE 0x30000 +#define BTXRANDOMSEED 0xffffffff +#define BCCKTXPREAMBLE 0x1 +#define BCCKTXSFD 0xffff0000 +#define BCCKTXSIG 0xff +#define BCCKTXSERVICE 0xff00 +#define BCCKLENGTHEXT 0x8000 +#define BCCKTXLENGHT 0xffff0000 +#define BCCKTXCRC16 0xffff +#define BCCKTXSTATUS 0x1 +#define BOFDMTXSTATUS 0x2 +#define IS_BB_REG_OFFSET_92S(_offset) \ + ((_offset >= 0x800) && (_offset <= 0xfff)) + +#define BRFMOD 0x1 +#define BJAPANMODE 0x2 +#define BCCKTXSC 0x30 +#define BCCKEN 0x1000000 +#define BOFDMEN 0x2000000 + +#define BOFDMRXADCPHASE 0x10000 +#define BOFDMTXDACPHASE 0x40000 +#define BXATXAGC 0x3f + +#define BXBTXAGC 0xf00 +#define BXCTXAGC 0xf000 +#define BXDTXAGC 0xf0000 + +#define BPASTART 0xf0000000 +#define BTRSTART 0x00f00000 +#define BRFSTART 0x0000f000 +#define BBBSTART 0x000000f0 +#define BBBCCKSTART 0x0000000f +#define BPAEND 0xf +#define BTREND 0x0f000000 +#define BRFEND 0x000f0000 +#define BCCAMASK 0x000000f0 +#define BR2RCCAMASK 0x00000f00 +#define BHSSI_R2TDELAY 0xf8000000 +#define BHSSI_T2RDELAY 0xf80000 +#define BCONTXHSSI 0x400 +#define BIGFROMCCK 0x200 +#define BAGCADDRESS 0x3f +#define BRXHPTX 0x7000 +#define BRXHP2RX 0x38000 +#define BRXHPCCKINI 0xc0000 +#define BAGCTXCODE 0xc00000 +#define BAGCRXCODE 0x300000 + +#define B3WIREDATALENGTH 0x800 +#define B3WIREADDREAALENGTH 0x400 + +#define B3WIRERFPOWERDOWN 0x1 +#define B5GPAPEPOLARITY 0x40000000 +#define B2GPAPEPOLARITY 0x80000000 +#define BRFSW_TXDEFAULTANT 0x3 +#define BRFSW_TXOPTIONANT 0x30 +#define BRFSW_RXDEFAULTANT 0x300 +#define BRFSW_RXOPTIONANT 0x3000 +#define BRFSI_3WIREDATA 0x1 +#define BRFSI_3WIRECLOCK 0x2 +#define BRFSI_3WIRELOAD 0x4 +#define BRFSI_3WIRERW 0x8 +#define BRFSI_3WIRE 0xf + +#define BRFSI_RFENV 0x10 + +#define BRFSI_TRSW 0x20 +#define BRFSI_TRSWB 0x40 +#define BRFSI_ANTSW 0x100 +#define BRFSI_ANTSWB 0x200 +#define BRFSI_PAPE 0x400 +#define BRFSI_PAPE5G 0x800 +#define BBANDSELECT 0x1 +#define BHTSIG2_GI 0x80 +#define BHTSIG2_SMOOTHING 0x01 +#define BHTSIG2_SOUNDING 0x02 +#define BHTSIG2_AGGREATON 0x08 +#define BHTSIG2_STBC 0x30 +#define BHTSIG2_ADVCODING 0x40 +#define BHTSIG2_NUMOFHTLTF 0x300 +#define BHTSIG2_CRC8 0x3fc +#define BHTSIG1_MCS 0x7f +#define BHTSIG1_BANDWIDTH 0x80 +#define BHTSIG1_HTLENGTH 0xffff +#define BLSIG_RATE 0xf +#define BLSIG_RESERVED 0x10 +#define BLSIG_LENGTH 0x1fffe +#define BLSIG_PARITY 0x20 +#define BCCKRXPHASE 0x4 + +#define BLSSIREADADDRESS 0x7f800000 +#define BLSSIREADEDGE 0x80000000 + +#define BLSSIREADBACKDATA 0xfffff + +#define BLSSIREADOKFLAG 0x1000 +#define BCCKSAMPLERATE 0x8 +#define BREGULATOR0STANDBY 0x1 +#define BREGULATORPLLSTANDBY 0x2 +#define BREGULATOR1STANDBY 0x4 +#define BPLLPOWERUP 0x8 +#define BDPLLPOWERUP 0x10 +#define BDA10POWERUP 0x20 +#define BAD7POWERUP 0x200 +#define BDA6POWERUP 0x2000 +#define BXTALPOWERUP 0x4000 +#define B40MDCLKPOWERUP 0x8000 +#define BDA6DEBUGMODE 0x20000 +#define BDA6SWING 0x380000 + +#define BADCLKPHASE 0x4000000 +#define B80MCLKDELAY 0x18000000 +#define BAFEWATCHDOGENABLE 0x20000000 + +#define BXTALCAP01 0xc0000000 +#define BXTALCAP23 0x3 +#define BXTALCAP92X 0x0f000000 +#define BXTALCAP 0x0f000000 + +#define BINTDIFCLKENABLE 0x400 +#define BEXTSIGCLKENABLE 0x800 +#define BBANDGAP_MBIAS_POWERUP 0x10000 +#define BAD11SH_GAIN 0xc0000 +#define BAD11NPUT_RANGE 0x700000 +#define BAD110P_CURRENT 0x3800000 +#define BLPATH_LOOPBACK 0x4000000 +#define BQPATH_LOOPBACK 0x8000000 +#define BAFE_LOOPBACK 0x10000000 +#define BDA10_SWING 0x7e0 +#define BDA10_REVERSE 0x800 +#define BDA_CLK_SOURCE 0x1000 +#define BDA7INPUT_RANGE 0x6000 +#define BDA7_GAIN 0x38000 +#define BDA7OUTPUT_CM_MODE 0x40000 +#define BDA7INPUT_CM_MODE 0x380000 +#define BDA7CURRENT 0xc00000 +#define BREGULATOR_ADJUST 0x7000000 +#define BAD11POWERUP_ATTX 0x1 +#define BDA10PS_ATTX 0x10 +#define BAD11POWERUP_ATRX 0x100 +#define BDA10PS_ATRX 0x1000 +#define BCCKRX_AGC_FORMAT 0x200 +#define BPSDFFT_SAMPLE_POINT 0xc000 +#define BPSD_AVERAGE_NUM 0x3000 +#define BIQPATH_CONTROL 0xc00 +#define BPSD_FREQ 0x3ff +#define BPSD_ANTENNA_PATH 0x30 +#define BPSD_IQ_SWITCH 0x40 +#define BPSD_RX_TRIGGER 0x400000 +#define BPSD_TX_TRIGGER 0x80000000 +#define BPSD_SINE_TONE_SCALE 0x7f000000 +#define BPSD_REPORT 0xffff + +#define BOFDM_TXSC 0x30000000 +#define BCCK_TXON 0x1 +#define BOFDM_TXON 0x2 +#define BDEBUG_PAGE 0xfff +#define BDEBUG_ITEM 0xff +#define BANTL 0x10 +#define BANT_NONHT 0x100 +#define BANT_HT1 0x1000 +#define BANT_HT2 0x10000 +#define BANT_HT1S1 0x100000 +#define BANT_NONHTS1 0x1000000 + +#define BCCK_BBMODE 0x3 +#define BCCK_TXPOWERSAVING 0x80 +#define BCCK_RXPOWERSAVING 0x40 + +#define BCCK_SIDEBAND 0x10 + +#define BCCK_SCRAMBLE 0x8 +#define BCCK_ANTDIVERSITY 0x8000 +#define BCCK_CARRIER_RECOVERY 0x4000 +#define BCCK_TXRATE 0x3000 +#define BCCK_DCCANCEL 0x0800 +#define BCCK_ISICANCEL 0x0400 +#define BCCK_MATCH_FILTER 0x0200 +#define BCCK_EQUALIZER 0x0100 +#define BCCK_PREAMBLE_DETECT 0x800000 +#define BCCK_FAST_FALSECCA 0x400000 +#define BCCK_CH_ESTSTART 0x300000 +#define BCCK_CCA_COUNT 0x080000 +#define BCCK_CS_LIM 0x070000 +#define BCCK_BIST_MODE 0x80000000 +#define BCCK_CCAMASK 0x40000000 +#define BCCK_TX_DAC_PHASE 0x4 +#define BCCK_RX_ADC_PHASE 0x20000000 +#define BCCKR_CP_MODE 0x0100 +#define BCCK_TXDC_OFFSET 0xf0 +#define BCCK_RXDC_OFFSET 0xf +#define BCCK_CCA_MODE 0xc000 +#define BCCK_FALSECS_LIM 0x3f00 +#define BCCK_CS_RATIO 0xc00000 +#define BCCK_CORGBIT_SEL 0x300000 +#define BCCK_PD_LIM 0x0f0000 +#define BCCK_NEWCCA 0x80000000 +#define BCCK_RXHP_OF_IG 0x8000 +#define BCCK_RXIG 0x7f00 +#define BCCK_LNA_POLARITY 0x800000 +#define BCCK_RX1ST_BAIN 0x7f0000 +#define BCCK_RF_EXTEND 0x20000000 +#define BCCK_RXAGC_SATLEVEL 0x1f000000 +#define BCCK_RXAGC_SATCOUNT 0xe0 +#define BCCKRXRFSETTLE 0x1f +#define BCCK_FIXED_RXAGC 0x8000 +#define BCCK_ANTENNA_POLARITY 0x2000 +#define BCCK_TXFILTER_TYPE 0x0c00 +#define BCCK_RXAGC_REPORTTYPE 0x0300 +#define BCCK_RXDAGC_EN 0x80000000 +#define BCCK_RXDAGC_PERIOD 0x20000000 +#define BCCK_RXDAGC_SATLEVEL 0x1f000000 +#define BCCK_TIMING_RECOVERY 0x800000 +#define BCCK_TXC0 0x3f0000 +#define BCCK_TXC1 0x3f000000 +#define BCCK_TXC2 0x3f +#define BCCK_TXC3 0x3f00 +#define BCCK_TXC4 0x3f0000 +#define BCCK_TXC5 0x3f000000 +#define BCCK_TXC6 0x3f +#define BCCK_TXC7 0x3f00 +#define BCCK_DEBUGPORT 0xff0000 +#define BCCK_DAC_DEBUG 0x0f000000 +#define BCCK_FALSEALARM_ENABLE 0x8000 +#define BCCK_FALSEALARM_READ 0x4000 +#define BCCK_TRSSI 0x7f +#define BCCK_RXAGC_REPORT 0xfe +#define BCCK_RXREPORT_ANTSEL 0x80000000 +#define BCCK_RXREPORT_MFOFF 0x40000000 +#define BCCK_RXREPORT_SQLOSS 0x20000000 +#define BCCK_RXREPORT_PKTLOSS 0x10000000 +#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 +#define BCCK_RXREPORT_RATEERROR 0x04000000 +#define BCCK_RXREPORT_RXRATE 0x03000000 +#define BCCK_RXFA_COUNTER_LOWER 0xff +#define BCCK_RXFA_COUNTER_UPPER 0xff000000 +#define BCCK_RXHPAGC_START 0xe000 +#define BCCK_RXHPAGC_FINAL 0x1c00 +#define BCCK_RXFALSEALARM_ENABLE 0x8000 +#define BCCK_FACOUNTER_FREEZE 0x4000 +#define BCCK_TXPATH_SEL 0x10000000 +#define BCCK_DEFAULT_RXPATH 0xc000000 +#define BCCK_OPTION_RXPATH 0x3000000 + +#define BNUM_OFSTF 0x3 +#define BSHIFT_L 0xc0 +#define BGI_TH 0xc +#define BRXPATH_A 0x1 +#define BRXPATH_B 0x2 +#define BRXPATH_C 0x4 +#define BRXPATH_D 0x8 +#define BTXPATH_A 0x1 +#define BTXPATH_B 0x2 +#define BTXPATH_C 0x4 +#define BTXPATH_D 0x8 +#define BTRSSI_FREQ 0x200 +#define BADC_BACKOFF 0x3000 +#define BDFIR_BACKOFF 0xc000 +#define BTRSSI_LATCH_PHASE 0x10000 +#define BRX_LDC_OFFSET 0xff +#define BRX_QDC_OFFSET 0xff00 +#define BRX_DFIR_MODE 0x1800000 +#define BRX_DCNF_TYPE 0xe000000 +#define BRXIQIMB_A 0x3ff +#define BRXIQIMB_B 0xfc00 +#define BRXIQIMB_C 0x3f0000 +#define BRXIQIMB_D 0xffc00000 +#define BDC_DC_NOTCH 0x60000 +#define BRXNB_NOTCH 0x1f000000 +#define BPD_TH 0xf +#define BPD_TH_OPT2 0xc000 +#define BPWED_TH 0x700 +#define BIFMF_WIN_L 0x800 +#define BPD_OPTION 0x1000 +#define BMF_WIN_L 0xe000 +#define BBW_SEARCH_L 0x30000 +#define BWIN_ENH_L 0xc0000 +#define BBW_TH 0x700000 +#define BED_TH2 0x3800000 +#define BBW_OPTION 0x4000000 +#define BRADIO_TH 0x18000000 +#define BWINDOW_L 0xe0000000 +#define BSBD_OPTION 0x1 +#define BFRAME_TH 0x1c +#define BFS_OPTION 0x60 +#define BDC_SLOPE_CHECK 0x80 +#define BFGUARD_COUNTER_DC_L 0xe00 +#define BFRAME_WEIGHT_SHORT 0x7000 +#define BSUB_TUNE 0xe00000 +#define BFRAME_DC_LENGTH 0xe000000 +#define BSBD_START_OFFSET 0x30000000 +#define BFRAME_TH_2 0x7 +#define BFRAME_GI2_TH 0x38 +#define BGI2_SYNC_EN 0x40 +#define BSARCH_SHORT_EARLY 0x300 +#define BSARCH_SHORT_LATE 0xc00 +#define BSARCH_GI2_LATE 0x70000 +#define BCFOANTSUM 0x1 +#define BCFOACC 0x2 +#define BCFOSTARTOFFSET 0xc +#define BCFOLOOPBACK 0x70 +#define BCFOSUMWEIGHT 0x80 +#define BDAGCENABLE 0x10000 +#define BTXIQIMB_A 0x3ff +#define BTXIQIMB_b 0xfc00 +#define BTXIQIMB_C 0x3f0000 +#define BTXIQIMB_D 0xffc00000 +#define BTXIDCOFFSET 0xff +#define BTXIQDCOFFSET 0xff00 +#define BTXDFIRMODE 0x10000 +#define BTXPESUDO_NOISEON 0x4000000 +#define BTXPESUDO_NOISE_A 0xff +#define BTXPESUDO_NOISE_B 0xff00 +#define BTXPESUDO_NOISE_C 0xff0000 +#define BTXPESUDO_NOISE_D 0xff000000 +#define BCCA_DROPOPTION 0x20000 +#define BCCA_DROPTHRES 0xfff00000 +#define BEDCCA_H 0xf +#define BEDCCA_L 0xf0 +#define BLAMBDA_ED 0x300 +#define BRX_INITIALGAIN 0x7f +#define BRX_ANTDIV_EN 0x80 +#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 +#define BRX_HIGHPOWER_FLOW 0x8000 +#define BRX_AGC_FREEZE_THRES 0xc0000 +#define BRX_FREEZESTEP_AGC1 0x300000 +#define BRX_FREEZESTEP_AGC2 0xc00000 +#define BRX_FREEZESTEP_AGC3 0x3000000 +#define BRX_FREEZESTEP_AGC0 0xc000000 +#define BRXRSSI_CMP_EN 0x10000000 +#define BRXQUICK_AGCEN 0x20000000 +#define BRXAGC_FREEZE_THRES_MODE 0x40000000 +#define BRX_OVERFLOW_CHECKTYPE 0x80000000 +#define BRX_AGCSHIFT 0x7f +#define BTRSW_TRI_ONLY 0x80 +#define BPOWER_THRES 0x300 +#define BRXAGC_EN 0x1 +#define BRXAGC_TOGETHER_EN 0x2 +#define BRXAGC_MIN 0x4 +#define BRXHP_INI 0x7 +#define BRXHP_TRLNA 0x70 +#define BRXHP_RSSI 0x700 +#define BRXHP_BBP1 0x7000 +#define BRXHP_BBP2 0x70000 +#define BRXHP_BBP3 0x700000 +#define BRSSI_H 0x7f0000 +#define BRSSI_GEN 0x7f000000 +#define BRXSETTLE_TRSW 0x7 +#define BRXSETTLE_LNA 0x38 +#define BRXSETTLE_RSSI 0x1c0 +#define BRXSETTLE_BBP 0xe00 +#define BRXSETTLE_RXHP 0x7000 +#define BRXSETTLE_ANTSW_RSSI 0x38000 +#define BRXSETTLE_ANTSW 0xc0000 +#define BRXPROCESS_TIME_DAGC 0x300000 +#define BRXSETTLE_HSSI 0x400000 +#define BRXPROCESS_TIME_BBPPW 0x800000 +#define BRXANTENNA_POWER_SHIFT 0x3000000 +#define BRSSI_TABLE_SELECT 0xc000000 +#define BRXHP_FINAL 0x7000000 +#define BRXHPSETTLE_BBP 0x7 +#define BRXHTSETTLE_HSSI 0x8 +#define BRXHTSETTLE_RXHP 0x70 +#define BRXHTSETTLE_BBPPW 0x80 +#define BRXHTSETTLE_IDLE 0x300 +#define BRXHTSETTLE_RESERVED 0x1c00 +#define BRXHT_RXHP_EN 0x8000 +#define BRXAGC_FREEZE_THRES 0x30000 +#define BRXAGC_TOGETHEREN 0x40000 +#define BRXHTAGC_MIN 0x80000 +#define BRXHTAGC_EN 0x100000 +#define BRXHTDAGC_EN 0x200000 +#define BRXHT_RXHP_BBP 0x1c00000 +#define BRXHT_RXHP_FINAL 0xe0000000 +#define BRXPW_RADIO_TH 0x3 +#define BRXPW_RADIO_EN 0x4 +#define BRXMF_HOLD 0x3800 +#define BRXPD_DELAY_TH1 0x38 +#define BRXPD_DELAY_TH2 0x1c0 +#define BRXPD_DC_COUNT_MAX 0x600 +#define BRXPD_DELAY_TH 0x8000 +#define BRXPROCESS_DELAY 0xf0000 +#define BRXSEARCHRANGE_GI2_EARLY 0x700000 +#define BRXFRAME_FUARD_COUNTER_L 0x3800000 +#define BRXSGI_GUARD_L 0xc000000 +#define BRXSGI_SEARCH_L 0x30000000 +#define BRXSGI_TH 0xc0000000 +#define BDFSCNT0 0xff +#define BDFSCNT1 0xff00 +#define BDFSFLAG 0xf0000 +#define BMF_WEIGHT_SUM 0x300000 +#define BMINIDX_TH 0x7f000000 +#define BDAFORMAT 0x40000 +#define BTXCH_EMU_ENABLE 0x01000000 +#define BTRSW_ISOLATION_A 0x7f +#define BTRSW_ISOLATION_B 0x7f00 +#define BTRSW_ISOLATION_C 0x7f0000 +#define BTRSW_ISOLATION_D 0x7f000000 +#define BEXT_LNA_GAIN 0x7c00 + +#define BSTBC_EN 0x4 +#define BANTENNA_MAPPING 0x10 +#define BNSS 0x20 +#define BCFO_ANTSUM_ID 0x200 +#define BPHY_COUNTER_RESET 0x8000000 +#define BCFO_REPORT_GET 0x4000000 +#define BOFDM_CONTINUE_TX 0x10000000 +#define BOFDM_SINGLE_CARRIER 0x20000000 +#define BOFDM_SINGLE_TONE 0x40000000 +#define BHT_DETECT 0x100 +#define BCFOEN 0x10000 +#define BCFOVALUE 0xfff00000 +#define BSIGTONE_RE 0x3f +#define BSIGTONE_IM 0x7f00 +#define BCOUNTER_CCA 0xffff +#define BCOUNTER_PARITYFAIL 0xffff0000 +#define BCOUNTER_RATEILLEGAL 0xffff +#define BCOUNTER_CRC8FAIL 0xffff0000 +#define BCOUNTER_MCSNOSUPPORT 0xffff +#define BCOUNTER_FASTSYNC 0xffff +#define BSHORTCFO 0xfff +#define BSHORTCFOT_LENGTH 12 +#define BSHORTCFOF_LENGTH 11 +#define BLONGCFO 0x7ff +#define BLONGCFOT_LENGTH 11 +#define BLONGCFOF_LENGTH 11 +#define BTAILCFO 0x1fff +#define BTAILCFOT_LENGTH 13 +#define BTAILCFOF_LENGTH 12 +#define BNOISE_EN_PWDB 0xffff +#define BCC_POWER_DB 0xffff0000 +#define BMOISE_PWDB 0xffff +#define BPOWERMEAST_LENGTH 10 +#define BPOWERMEASF_LENGTH 3 +#define BRX_HT_BW 0x1 +#define BRXSC 0x6 +#define BRX_HT 0x8 +#define BNB_INTF_DET_ON 0x1 +#define BINTF_WIN_LEN_CFG 0x30 +#define BNB_INTF_TH_CFG 0x1c0 +#define BRFGAIN 0x3f +#define BTABLESEL 0x40 +#define BTRSW 0x80 +#define BRXSNR_A 0xff +#define BRXSNR_B 0xff00 +#define BRXSNR_C 0xff0000 +#define BRXSNR_D 0xff000000 +#define BSNR_EVMT_LENGTH 8 +#define BSNR_EVMF_LENGTH 1 +#define BCSI1ST 0xff +#define BCSI2ND 0xff00 +#define BRXEVM1ST 0xff0000 +#define BRXEVM2ND 0xff000000 +#define BSIGEVM 0xff +#define BPWDB 0xff00 +#define BSGIEN 0x10000 + +#define BSFACTOR_QMA1 0xf +#define BSFACTOR_QMA2 0xf0 +#define BSFACTOR_QMA3 0xf00 +#define BSFACTOR_QMA4 0xf000 +#define BSFACTOR_QMA5 0xf0000 +#define BSFACTOR_QMA6 0xf0000 +#define BSFACTOR_QMA7 0xf00000 +#define BSFACTOR_QMA8 0xf000000 +#define BSFACTOR_QMA9 0xf0000000 +#define BCSI_SCHEME 0x100000 + +#define BNOISE_LVL_TOP_SET 0x3 +#define BCHSMOOTH 0x4 +#define BCHSMOOTH_CFG1 0x38 +#define BCHSMOOTH_CFG2 0x1c0 +#define BCHSMOOTH_CFG3 0xe00 +#define BCHSMOOTH_CFG4 0x7000 +#define BMRCMODE 0x800000 +#define BTHEVMCFG 0x7000000 + +#define BLOOP_FIT_TYPE 0x1 +#define BUPD_CFO 0x40 +#define BUPD_CFO_OFFDATA 0x80 +#define BADV_UPD_CFO 0x100 +#define BADV_TIME_CTRL 0x800 +#define BUPD_CLKO 0x1000 +#define BFC 0x6000 +#define BTRACKING_MODE 0x8000 +#define BPHCMP_ENABLE 0x10000 +#define BUPD_CLKO_LTF 0x20000 +#define BCOM_CH_CFO 0x40000 +#define BCSI_ESTI_MODE 0x80000 +#define BADV_UPD_EQZ 0x100000 +#define BUCHCFG 0x7000000 +#define BUPDEQZ 0x8000000 + +#define BRX_PESUDO_NOISE_ON 0x20000000 +#define BRX_PESUDO_NOISE_A 0xff +#define BRX_PESUDO_NOISE_B 0xff00 +#define BRX_PESUDO_NOISE_C 0xff0000 +#define BRX_PESUDO_NOISE_D 0xff000000 +#define BRX_PESUDO_NOISESTATE_A 0xffff +#define BRX_PESUDO_NOISESTATE_B 0xffff0000 +#define BRX_PESUDO_NOISESTATE_C 0xffff +#define BRX_PESUDO_NOISESTATE_D 0xffff0000 + +#define BZEBRA1_HSSIENABLE 0x8 +#define BZEBRA1_TRXCONTROL 0xc00 +#define BZEBRA1_TRXGAINSETTING 0x07f +#define BZEBRA1_RXCOUNTER 0xc00 +#define BZEBRA1_TXCHANGEPUMP 0x38 +#define BZEBRA1_RXCHANGEPUMP 0x7 +#define BZEBRA1_CHANNEL_NUM 0xf80 +#define BZEBRA1_TXLPFBW 0x400 +#define BZEBRA1_RXLPFBW 0x600 + +#define BRTL8256REG_MODE_CTRL1 0x100 +#define BRTL8256REG_MODE_CTRL0 0x40 +#define BRTL8256REG_TXLPFBW 0x18 +#define BRTL8256REG_RXLPFBW 0x600 + +#define BRTL8258_TXLPFBW 0xc +#define BRTL8258_RXLPFBW 0xc00 +#define BRTL8258_RSSILPFBW 0xc0 + +#define BBYTE0 0x1 +#define BBYTE1 0x2 +#define BBYTE2 0x4 +#define BBYTE3 0x8 +#define BWORD0 0x3 +#define BWORD1 0xc +#define BWORD 0xf + +#define MASKBYTE0 0xff +#define MASKBYTE1 0xff00 +#define MASKBYTE2 0xff0000 +#define MASKBYTE3 0xff000000 +#define MASKHWORD 0xffff0000 +#define MASKLWORD 0x0000ffff +#define MASKDWORD 0xffffffff +#define MASK12BITS 0xfff +#define MASKH4BITS 0xf0000000 +#define MASKOFDM_D 0xffc00000 +#define MASKCCK 0x3f3f3f3f + +#define MASK4BITS 0x0f +#define MASK20BITS 0xfffff +#define RFREG_OFFSET_MASK 0xfffff + +#define BENABLE 0x1 +#define BDISABLE 0x0 + +#define LEFT_ANTENNA 0x0 +#define RIGHT_ANTENNA 0x1 + +#define TCHECK_TXSTATUS 500 +#define TUPDATE_RXCOUNTER 100 + +#define REG_UN_used_register 0x01bf + +/* WOL bit information */ +#define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0) +#define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1) +#define HAL92C_WOL_DISASSOC_EVENT BIT(2) +#define HAL92C_WOL_DEAUTH_EVENT BIT(3) +#define HAL92C_WOL_FW_DISCONNECT_EVENT BIT(4) + +#define WOL_REASON_PTK_UPDATE BIT(0) +#define WOL_REASON_GTK_UPDATE BIT(1) +#define WOL_REASON_DISASSOC BIT(2) +#define WOL_REASON_DEAUTH BIT(3) +#define WOL_REASON_FW_DISCONNECT BIT(4) +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c new file mode 100644 index 000000000000..c9bc33cd1090 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.c @@ -0,0 +1,152 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" + +static bool _rtl92ee_phy_rf6052_config_parafile(struct ieee80211_hw *hw); + +void rtl92ee_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff) | BIT(10) | BIT(11)); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + case HT_CHANNEL_WIDTH_20_40: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff) | BIT(10)); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", bandwidth); + break; + } +} + +bool rtl92ee_phy_rf6052_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + if (rtlphy->rf_type == RF_1T1R) + rtlphy->num_total_rfpath = 1; + else + rtlphy->num_total_rfpath = 2; + + return _rtl92ee_phy_rf6052_config_parafile(hw); +} + +static bool _rtl92ee_phy_rf6052_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 u4_regvalue = 0; + u8 rfpath; + bool rtstatus = true; + struct bb_reg_def *pphyreg; + + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + pphyreg = &rtlphy->phyreg_def[rfpath]; + + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV); + break; + case RF90_PATH_B: + case RF90_PATH_D: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16); + break; + } + + rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, + B3WIREADDREAALENGTH, 0x0); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); + udelay(1); + + switch (rfpath) { + case RF90_PATH_A: + rtstatus = rtl92ee_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_B: + rtstatus = rtl92ee_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_C: + break; + case RF90_PATH_D: + break; + } + + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV, u4_regvalue); + break; + case RF90_PATH_B: + case RF90_PATH_D: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16, u4_regvalue); + break; + } + + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio[%d] Fail!!", rfpath); + return false; + } + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); + return rtstatus; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h new file mode 100644 index 000000000000..039c0133ad6b --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/rf.h @@ -0,0 +1,35 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92E_RF_H__ +#define __RTL92E_RF_H__ + +#define RF6052_MAX_TX_PWR 0x3F + +void rtl92ee_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, + u8 bandwidth); +bool rtl92ee_phy_rf6052_config(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c new file mode 100644 index 000000000000..c31c6bfb536d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c @@ -0,0 +1,398 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../core.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "hw.h" +#include "sw.h" +#include "fw.h" +#include "trx.h" +#include "led.h" +#include "table.h" + +#include "../btcoexist/rtl_btc.h" + +#include +#include + +static void rtl92ee_init_aspm_vars(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /** + * ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + */ + rtlpci->const_pci_aspm = 3; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /** + * In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 0; + + /** + * This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 1; +} + +int rtl92ee_init_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + int err = 0; + + rtl92ee_bt_reg_init(hw); + rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; + rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); + + rtlpriv->dm.dm_initialgain_enable = 1; + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.disable_framebursting = 0; + rtlpci->transmit_config = CFENDFORM | BIT(15); + + /*just 2.4G band*/ + rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; + rtlpriv->rtlhal.bandset = BAND_ON_2_4G; + rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; + + rtlpci->receive_config = (RCR_APPFCS | + RCR_APP_MIC | + RCR_APP_ICV | + RCR_APP_PHYST_RXFF | + RCR_HTC_LOC_CTRL | + RCR_AMF | + RCR_ACF | + RCR_ACRC32 | + RCR_AB | + RCR_AM | + RCR_APM | + 0); + + rtlpci->irq_mask[0] = (u32)(IMR_PSTIMEOUT | + IMR_C2HCMD | + IMR_HIGHDOK | + IMR_MGNTDOK | + IMR_BKDOK | + IMR_BEDOK | + IMR_VIDOK | + IMR_VODOK | + IMR_RDU | + IMR_ROK | + 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; + rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; + rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; + if (rtlpriv->cfg->mod_params->disable_watchdog) + pr_info("watchdog disabled\n"); + rtlpriv->psc.reg_fwctrl_lps = 3; + rtlpriv->psc.reg_max_lps_awakeintvl = 5; + /* for ASPM, you can close aspm through + * set const_support_pciaspm = 0 + */ + rtl92ee_init_aspm_vars(hw); + + if (rtlpriv->psc.reg_fwctrl_lps == 1) + rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 2) + rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 3) + rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + + /* for early mode */ + rtlpriv->rtlhal.earlymode_enable = false; + + /*low power */ + rtlpriv->psc.low_power_enable = false; + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); + if (!rtlpriv->rtlhal.pfirmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't alloc buffer for fw\n"); + return 1; + } + + /* request fw */ + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192eefw.bin"; + + rtlpriv->max_fw_size = 0x8000; + pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); + err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, + rtlpriv->io.dev, GFP_KERNEL, hw, + rtl_fw_cb); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to request firmware!\n"); + return 1; + } + + return 0; +} + +void rtl92ee_deinit_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.pfirmware) { + vfree(rtlpriv->rtlhal.pfirmware); + rtlpriv->rtlhal.pfirmware = NULL; + } +} + +/* get bt coexist status */ +bool rtl92ee_get_btc_status(void) +{ + return true; +} + +static struct rtl_hal_ops rtl8192ee_hal_ops = { + .init_sw_vars = rtl92ee_init_sw_vars, + .deinit_sw_vars = rtl92ee_deinit_sw_vars, + .read_eeprom_info = rtl92ee_read_eeprom_info, + .interrupt_recognized = rtl92ee_interrupt_recognized,/*need check*/ + .hw_init = rtl92ee_hw_init, + .hw_disable = rtl92ee_card_disable, + .hw_suspend = rtl92ee_suspend, + .hw_resume = rtl92ee_resume, + .enable_interrupt = rtl92ee_enable_interrupt, + .disable_interrupt = rtl92ee_disable_interrupt, + .set_network_type = rtl92ee_set_network_type, + .set_chk_bssid = rtl92ee_set_check_bssid, + .set_qos = rtl92ee_set_qos, + .set_bcn_reg = rtl92ee_set_beacon_related_registers, + .set_bcn_intv = rtl92ee_set_beacon_interval, + .update_interrupt_mask = rtl92ee_update_interrupt_mask, + .get_hw_reg = rtl92ee_get_hw_reg, + .set_hw_reg = rtl92ee_set_hw_reg, + .update_rate_tbl = rtl92ee_update_hal_rate_tbl, + .pre_fill_tx_bd_desc = rtl92ee_pre_fill_tx_bd_desc, + .rx_desc_buff_remained_cnt = rtl92ee_rx_desc_buff_remained_cnt, + .rx_check_dma_ok = rtl92ee_rx_check_dma_ok, + .fill_tx_desc = rtl92ee_tx_fill_desc, + .fill_tx_cmddesc = rtl92ee_tx_fill_cmddesc, + .query_rx_desc = rtl92ee_rx_query_desc, + .set_channel_access = rtl92ee_update_channel_access_setting, + .radio_onoff_checking = rtl92ee_gpio_radio_on_off_checking, + .set_bw_mode = rtl92ee_phy_set_bw_mode, + .switch_channel = rtl92ee_phy_sw_chnl, + .dm_watchdog = rtl92ee_dm_watchdog, + .scan_operation_backup = rtl92ee_phy_scan_operation_backup, + .set_rf_power_state = rtl92ee_phy_set_rf_power_state, + .led_control = rtl92ee_led_control, + .set_desc = rtl92ee_set_desc, + .get_desc = rtl92ee_get_desc, + .is_tx_desc_closed = rtl92ee_is_tx_desc_closed, + .get_available_desc = rtl92ee_get_available_desc, + .tx_polling = rtl92ee_tx_polling, + .enable_hw_sec = rtl92ee_enable_hw_security_config, + .set_key = rtl92ee_set_key, + .init_sw_leds = rtl92ee_init_sw_leds, + .get_bbreg = rtl92ee_phy_query_bb_reg, + .set_bbreg = rtl92ee_phy_set_bb_reg, + .get_rfreg = rtl92ee_phy_query_rf_reg, + .set_rfreg = rtl92ee_phy_set_rf_reg, + .fill_h2c_cmd = rtl92ee_fill_h2c_cmd, + .get_btc_status = rtl92ee_get_btc_status, + .rx_command_packet = rtl92ee_rx_command_packet, +}; + +static struct rtl_mod_params rtl92ee_mod_params = { + .sw_crypto = false, + .inactiveps = false, + .swctrl_lps = false, + .fwctrl_lps = true, + .msi_support = true, + .debug = DBG_EMERG, +}; + +static struct rtl_hal_cfg rtl92ee_hal_cfg = { + .bar_id = 2, + .write_readback = true, + .name = "rtl92ee_pci", + .fw_name = "rtlwifi/rtl8192eefw.bin", + .ops = &rtl8192ee_hal_ops, + .mod_params = &rtl92ee_mod_params, + + .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, + .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, + .maps[SYS_CLK] = REG_SYS_CLKR, + .maps[MAC_RCR_AM] = AM, + .maps[MAC_RCR_AB] = AB, + .maps[MAC_RCR_ACRC32] = ACRC32, + .maps[MAC_RCR_ACF] = ACF, + .maps[MAC_RCR_AAP] = AAP, + .maps[MAC_HIMR] = REG_HIMR, + .maps[MAC_HIMRE] = REG_HIMRE, + + .maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS, + + .maps[EFUSE_TEST] = REG_EFUSE_TEST, + .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_CLK] = 0, + .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_PWC_EV12V] = PWC_EV12V, + .maps[EFUSE_FEN_ELDR] = FEN_ELDR, + .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, + .maps[EFUSE_ANA8M] = ANA8M, + .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, + .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, + .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, + .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, + + .maps[RWCAM] = REG_CAMCMD, + .maps[WCAMI] = REG_CAMWRITE, + .maps[RCAMO] = REG_CAMREAD, + .maps[CAMDBG] = REG_CAMDBG, + .maps[SECR] = REG_SECCFG, + .maps[SEC_CAM_NONE] = CAM_NONE, + .maps[SEC_CAM_WEP40] = CAM_WEP40, + .maps[SEC_CAM_TKIP] = CAM_TKIP, + .maps[SEC_CAM_AES] = CAM_AES, + .maps[SEC_CAM_WEP104] = CAM_WEP104, + + .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, + .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, + .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, + .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, + .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, + .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, + .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, + .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, + .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, + .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, + .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, + .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, + .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, + + .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, + .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, + .maps[RTL_IMR_BCNINT] = IMR_BCNDMAINT0, + .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, + .maps[RTL_IMR_RDU] = IMR_RDU, + .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, + .maps[RTL_IMR_BDOK] = IMR_BCNDOK0, + .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, + .maps[RTL_IMR_TBDER] = IMR_TBDER, + .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, + .maps[RTL_IMR_TBDOK] = IMR_TBDOK, + .maps[RTL_IMR_BKDOK] = IMR_BKDOK, + .maps[RTL_IMR_BEDOK] = IMR_BEDOK, + .maps[RTL_IMR_VIDOK] = IMR_VIDOK, + .maps[RTL_IMR_VODOK] = IMR_VODOK, + .maps[RTL_IMR_ROK] = IMR_ROK, + .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER), + + .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, +}; + +static struct pci_device_id rtl92ee_pci_ids[] = { + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x818B, rtl92ee_hal_cfg)}, + {}, +}; + +MODULE_DEVICE_TABLE(pci, rtl92ee_pci_ids); + +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +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(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); +module_param_named(msi, rtl92ee_mod_params.msi_support, bool, 0444); +module_param_named(disable_watchdog, rtl92ee_mod_params.disable_watchdog, + bool, 0444); +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(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(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); + +static struct pci_driver rtl92ee_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl92ee_pci_ids, + .probe = rtl_pci_probe, + .remove = rtl_pci_disconnect, + .driver.pm = &rtlwifi_pm_ops, +}; + +module_pci_driver(rtl92ee_driver); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h new file mode 100644 index 000000000000..21433d0332d0 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.h @@ -0,0 +1,33 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92E_SW_H__ +#define __RTL92E_SW_H__ + +int rtl92ee_init_sw_vars(struct ieee80211_hw *hw); +void rtl92ee_deinit_sw_vars(struct ieee80211_hw *hw); +bool rtl92ee_get_btc_status(void); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c new file mode 100644 index 000000000000..abcdd0670fd8 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.c @@ -0,0 +1,882 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger + * + *****************************************************************************/ + +#include "table.h" +u32 RTL8192EE_PHY_REG_ARRAY[] = { + 0x800, 0x80040000, + 0x804, 0x00000003, + 0x808, 0x0000FC00, + 0x80C, 0x0000000A, + 0x810, 0x10001331, + 0x814, 0x020C3D10, + 0x818, 0x02220385, + 0x81C, 0x00000000, + 0x820, 0x01000100, + 0x824, 0x00390204, + 0x828, 0x01000100, + 0x82C, 0x00390204, + 0x830, 0x32323232, + 0x834, 0x30303030, + 0x838, 0x30303030, + 0x83C, 0x30303030, + 0x840, 0x00010000, + 0x844, 0x00010000, + 0x848, 0x28282828, + 0x84C, 0x28282828, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x009A009A, + 0x85C, 0x01000014, + 0x860, 0x66F60000, + 0x864, 0x061F0000, + 0x868, 0x30303030, + 0x86C, 0x30303030, + 0x870, 0x00000000, + 0x874, 0x55004200, + 0x878, 0x08080808, + 0x87C, 0x00000000, + 0x880, 0xB0000C1C, + 0x884, 0x00000001, + 0x888, 0x00000000, + 0x88C, 0xCC0000C0, + 0x890, 0x00000800, + 0x894, 0xFFFFFFFE, + 0x898, 0x40302010, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90C, 0x81121313, + 0x910, 0x806C0001, + 0x914, 0x00000001, + 0x918, 0x00000000, + 0x91C, 0x00010000, + 0x924, 0x00000001, + 0x928, 0x00000000, + 0x92C, 0x00000000, + 0x930, 0x00000000, + 0x934, 0x00000000, + 0x938, 0x00000000, + 0x93C, 0x00000000, + 0x940, 0x00000000, + 0x944, 0x00000000, + 0x94C, 0x00000008, + 0xA00, 0x00D0C7C8, + 0xA04, 0x81FF000C, + 0xA08, 0x8C838300, + 0xA0C, 0x2E68120F, + 0xA10, 0x95009B78, + 0xA14, 0x1114D028, + 0xA18, 0x00881117, + 0xA1C, 0x89140F00, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0xA2C, 0x00D30000, + 0xA70, 0x101FBF00, + 0xA74, 0x00000007, + 0xA78, 0x00000900, + 0xA7C, 0x225B0606, + 0xA80, 0x218075B1, + 0xB38, 0x00000000, + 0xC00, 0x48071D40, + 0xC04, 0x03A05633, + 0xC08, 0x000000E4, + 0xC0C, 0x6C6C6C6C, + 0xC10, 0x08800000, + 0xC14, 0x40000100, + 0xC18, 0x08800000, + 0xC1C, 0x40000100, + 0xC20, 0x00000000, + 0xC24, 0x00000000, + 0xC28, 0x00000000, + 0xC2C, 0x00000000, + 0xC30, 0x69E9AC47, + 0xC34, 0x469652AF, + 0xC38, 0x49795994, + 0xC3C, 0x0A97971C, + 0xC40, 0x1F7C403F, + 0xC44, 0x000100B7, + 0xC48, 0xEC020107, + 0xC4C, 0x007F037F, + 0xFF010718, 0xABCD, + 0xC50, 0x00340220, + 0xCDCDCDCD, 0xCDCD, + 0xC50, 0x00340020, + 0xFF010718, 0xDEAD, + 0xC54, 0x0080801F, + 0xFF010718, 0xABCD, + 0xC58, 0x00000220, + 0xCDCDCDCD, 0xCDCD, + 0xC58, 0x00000020, + 0xFF010718, 0xDEAD, + 0xC5C, 0x00248492, + 0xC60, 0x00000000, + 0xC64, 0x7112848B, + 0xC68, 0x47C00BFF, + 0xC6C, 0x00000036, + 0xC70, 0x00000600, + 0xC74, 0x02013169, + 0xC78, 0x0000001F, + 0xC7C, 0x00B91612, + 0xFF010718, 0xABCD, + 0xC80, 0x2D4000B5, + 0xCDCDCDCD, 0xCDCD, + 0xC80, 0x40000100, + 0xFF010718, 0xDEAD, + 0xC84, 0x21F60000, + 0xFF010718, 0xABCD, + 0xC88, 0x2D4000B5, + 0xCDCDCDCD, 0xCDCD, + 0xC88, 0x40000100, + 0xFF010718, 0xDEAD, + 0xC8C, 0xA0E40000, + 0xC90, 0x00121820, + 0xC94, 0x00000000, + 0xC98, 0x00121820, + 0xC9C, 0x00007F7F, + 0xCA0, 0x00000000, + 0xCA4, 0x000300A0, + 0xCA8, 0x00000000, + 0xCAC, 0x00000000, + 0xCB0, 0x00000000, + 0xCB4, 0x00000000, + 0xCB8, 0x00000000, + 0xCBC, 0x28000000, + 0xCC0, 0x00000000, + 0xCC4, 0x00000000, + 0xCC8, 0x00000000, + 0xCCC, 0x00000000, + 0xCD0, 0x00000000, + 0xCD4, 0x00000000, + 0xCD8, 0x64B22427, + 0xCDC, 0x00766932, + 0xCE0, 0x00222222, + 0xCE4, 0x00040000, + 0xCE8, 0x77644302, + 0xCEC, 0x2F97D40C, + 0xD00, 0x00080740, + 0xD04, 0x00020403, + 0xD08, 0x0000907F, + 0xD0C, 0x20010201, + 0xD10, 0xA0633333, + 0xD14, 0x3333BC43, + 0xD18, 0x7A8F5B6B, + 0xD1C, 0x0000007F, + 0xD2C, 0xCC979975, + 0xD30, 0x00000000, + 0xD34, 0x80608000, + 0xD38, 0x00000000, + 0xD3C, 0x00127353, + 0xD40, 0x00000000, + 0xD44, 0x00000000, + 0xD48, 0x00000000, + 0xD4C, 0x00000000, + 0xD50, 0x6437140A, + 0xD54, 0x00000000, + 0xD58, 0x00000282, + 0xD5C, 0x30032064, + 0xD60, 0x4653DE68, + 0xD64, 0x04518A3C, + 0xD68, 0x00002101, + 0xD6C, 0x2A201C16, + 0xD70, 0x1812362E, + 0xD74, 0x322C2220, + 0xD78, 0x000E3C24, + 0xD80, 0x01081008, + 0xD84, 0x00000800, + 0xD88, 0xF0B50000, + 0xE00, 0x30303030, + 0xE04, 0x30303030, + 0xE08, 0x03903030, + 0xE10, 0x30303030, + 0xE14, 0x30303030, + 0xE18, 0x30303030, + 0xE1C, 0x30303030, + 0xE28, 0x00000000, + 0xE30, 0x1000DC1F, + 0xE34, 0x10008C1F, + 0xE38, 0x02140102, + 0xE3C, 0x681604C2, + 0xE40, 0x01007C00, + 0xE44, 0x01004800, + 0xE48, 0xFB000000, + 0xE4C, 0x000028D1, + 0xE50, 0x1000DC1F, + 0xE54, 0x10008C1F, + 0xE58, 0x02140102, + 0xE5C, 0x28160D05, + 0xE60, 0x00000008, + 0xE68, 0x0FC05656, + 0xE6C, 0x03C09696, + 0xE70, 0x03C09696, + 0xE74, 0x0C005656, + 0xE78, 0x0C005656, + 0xE7C, 0x0C005656, + 0xE80, 0x0C005656, + 0xE84, 0x03C09696, + 0xE88, 0x0C005656, + 0xE8C, 0x03C09696, + 0xED0, 0x03C09696, + 0xED4, 0x03C09696, + 0xED8, 0x03C09696, + 0xEDC, 0x0000D6D6, + 0xEE0, 0x0000D6D6, + 0xEEC, 0x0FC01616, + 0xEE4, 0xB0000C1C, + 0xEE8, 0x00000001, + 0xF14, 0x00000003, + 0xF4C, 0x00000000, + 0xF00, 0x00000300, +}; + +u32 RTL8192EE_PHY_REG_ARRAY_PG[] = { + 0, 0, 0, 0x00000e08, 0x0000ff00, 0x00003200, + 0, 0, 1, 0x00000e08, 0x0000ff00, 0x00003200, + 0, 0, 0, 0x0000086c, 0xffffff00, 0x32323200, + 0, 0, 1, 0x0000086c, 0xffffff00, 0x32323200, + 0, 0, 0, 0x00000e00, 0xffffffff, 0x34343636, + 0, 0, 1, 0x00000e00, 0xffffffff, 0x34343636, + 0, 0, 0, 0x00000e04, 0xffffffff, 0x28283032, + 0, 0, 1, 0x00000e04, 0xffffffff, 0x28283032, + 0, 0, 0, 0x00000e10, 0xffffffff, 0x34363840, + 0, 0, 1, 0x00000e10, 0xffffffff, 0x34363840, + 0, 0, 0, 0x00000e14, 0xffffffff, 0x26283032, + 0, 0, 1, 0x00000e14, 0xffffffff, 0x26283032, + 0, 0, 1, 0x00000e18, 0xffffffff, 0x36384040, + 0, 0, 1, 0x00000e1c, 0xffffffff, 0x24262832, + 0, 1, 0, 0x00000838, 0xffffff00, 0x32323200, + 0, 1, 1, 0x00000838, 0xffffff00, 0x32323200, + 0, 1, 0, 0x0000086c, 0x000000ff, 0x00000032, + 0, 1, 1, 0x0000086c, 0x000000ff, 0x00000032, + 0, 1, 0, 0x00000830, 0xffffffff, 0x34343636, + 0, 1, 1, 0x00000830, 0xffffffff, 0x34343636, + 0, 1, 0, 0x00000834, 0xffffffff, 0x28283032, + 0, 1, 1, 0x00000834, 0xffffffff, 0x28283032, + 0, 1, 0, 0x0000083c, 0xffffffff, 0x34363840, + 0, 1, 1, 0x0000083c, 0xffffffff, 0x34363840, + 0, 1, 0, 0x00000848, 0xffffffff, 0x26283032, + 0, 1, 1, 0x00000848, 0xffffffff, 0x26283032, + 0, 1, 1, 0x0000084c, 0xffffffff, 0x36384040, + 0, 1, 1, 0x00000868, 0xffffffff, 0x24262832 +}; + +u32 RTL8192EE_RADIOA_ARRAY[] = { + 0x07F, 0x00000082, + 0x081, 0x0003FC00, + 0x000, 0x00030000, + 0x008, 0x00008400, + 0x018, 0x00000407, + 0x019, 0x00000012, + 0x01B, 0x00000064, + 0x01E, 0x00080009, + 0x01F, 0x00000880, + 0x02F, 0x0001A060, + 0x03F, 0x00000000, + 0x042, 0x000060C0, + 0x057, 0x000D0000, + 0x058, 0x000BE180, + 0x067, 0x00001552, + 0x083, 0x00000000, + 0x0B0, 0x000FF9F1, + 0x0B1, 0x00055418, + 0x0B2, 0x0008CC00, + 0x0B4, 0x00043083, + 0x0B5, 0x00008166, + 0x0B6, 0x0000803E, + 0x0B7, 0x0001C69F, + 0x0B8, 0x0000407F, + 0x0B9, 0x00080001, + 0x0BA, 0x00040001, + 0x0BB, 0x00000400, + 0x0BF, 0x000C0000, + 0x0C2, 0x00002400, + 0x0C3, 0x00000009, + 0x0C4, 0x00040C91, + 0x0C5, 0x00099999, + 0x0C6, 0x000000A3, + 0x0C7, 0x00088820, + 0x0C8, 0x00076C06, + 0x0C9, 0x00000000, + 0x0CA, 0x00080000, + 0x0DF, 0x00000180, + 0x0EF, 0x000001A0, + 0x051, 0x00069545, + 0x052, 0x0007E45E, + 0x053, 0x00000071, + 0x056, 0x00051FF3, + 0x035, 0x000000A8, + 0x035, 0x000001E2, + 0x035, 0x000002A8, + 0x036, 0x00001C24, + 0x036, 0x00009C24, + 0x036, 0x00011C24, + 0x036, 0x00019C24, + 0x018, 0x00000C07, + 0x05A, 0x00048000, + 0x019, 0x000739D0, + 0xFF010718, 0xABCD, + 0x034, 0x0000A093, + 0x034, 0x0000908F, + 0x034, 0x0000808C, + 0x034, 0x0000704D, + 0x034, 0x0000604A, + 0x034, 0x00005047, + 0x034, 0x0000400A, + 0x034, 0x00003007, + 0x034, 0x00002004, + 0x034, 0x00001001, + 0x034, 0x00000000, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0000ADD7, + 0x034, 0x00009DD4, + 0x034, 0x00008DD1, + 0x034, 0x00007DCE, + 0x034, 0x00006DCB, + 0x034, 0x00005DC8, + 0x034, 0x00004DC5, + 0x034, 0x000034CC, + 0x034, 0x0000244F, + 0x034, 0x0000144C, + 0x034, 0x00000014, + 0xFF010718, 0xDEAD, + 0x000, 0x00030159, + 0x084, 0x00068180, + 0x086, 0x0000014E, + 0x087, 0x00048E00, + 0x08E, 0x00065540, + 0x08F, 0x00088000, + 0x0EF, 0x000020A0, + 0xFF010718, 0xABCD, + 0x03B, 0x000F07B0, + 0xCDCDCDCD, 0xCDCD, + 0x03B, 0x000F02B0, + 0xFF010718, 0xDEAD, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0xFF010718, 0xABCD, + 0x03B, 0x000787B0, + 0xCDCDCDCD, 0xCDCD, + 0x03B, 0x00078730, + 0xFF010718, 0xDEAD, + 0x03B, 0x00060FB0, + 0x03B, 0x0005FFA0, + 0x03B, 0x00040620, + 0x03B, 0x00037090, + 0x03B, 0x00020080, + 0x03B, 0x0001F060, + 0x03B, 0x0000FFB0, + 0x0EF, 0x000000A0, + 0x0FE, 0x00000000, + 0x018, 0x0000FC07, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x01E, 0x00000001, + 0x01F, 0x00080000, + 0x000, 0x00033E70, +}; + +u32 RTL8192EE_RADIOB_ARRAY[] = { + 0x07F, 0x00000082, + 0x081, 0x0003FC00, + 0x000, 0x00030000, + 0x008, 0x00008400, + 0x018, 0x00000407, + 0x019, 0x00000012, + 0x01B, 0x00000064, + 0x01E, 0x00080009, + 0x01F, 0x00000880, + 0x02F, 0x0001A060, + 0x03F, 0x00000000, + 0x042, 0x000060C0, + 0x057, 0x000D0000, + 0x058, 0x000BE180, + 0x067, 0x00001552, + 0x07F, 0x00000082, + 0x081, 0x0003F000, + 0x083, 0x00000000, + 0x0DF, 0x00000180, + 0x0EF, 0x000001A0, + 0x051, 0x00069545, + 0x052, 0x0007E42E, + 0x053, 0x00000071, + 0x056, 0x00051FF3, + 0x035, 0x000000A8, + 0x035, 0x000001E0, + 0x035, 0x000002A8, + 0x036, 0x00001CA8, + 0x036, 0x00009C24, + 0x036, 0x00011C24, + 0x036, 0x00019C24, + 0x018, 0x00000C07, + 0x05A, 0x00048000, + 0x019, 0x000739D0, + 0xFF010718, 0xABCD, + 0x034, 0x0000A093, + 0x034, 0x0000908F, + 0x034, 0x0000808C, + 0x034, 0x0000704D, + 0x034, 0x0000604A, + 0x034, 0x00005047, + 0x034, 0x0000400A, + 0x034, 0x00003007, + 0x034, 0x00002004, + 0x034, 0x00001001, + 0x034, 0x00000000, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0000ADD7, + 0x034, 0x00009DD4, + 0x034, 0x00008DD1, + 0x034, 0x00007DCE, + 0x034, 0x00006DCB, + 0x034, 0x00005DC8, + 0x034, 0x00004DC5, + 0x034, 0x000034CC, + 0x034, 0x0000244F, + 0x034, 0x0000144C, + 0x034, 0x00000014, + 0xFF010718, 0xDEAD, + 0x000, 0x00030159, + 0x084, 0x00068180, + 0x086, 0x000000CE, + 0x087, 0x00048A00, + 0x08E, 0x00065540, + 0x08F, 0x00088000, + 0x0EF, 0x000020A0, + 0xFF010718, 0xABCD, + 0x03B, 0x000F07B0, + 0xCDCDCDCD, 0xCDCD, + 0x03B, 0x000F02B0, + 0xFF010718, 0xDEAD, + 0x03B, 0x000EF7B0, + 0x03B, 0x000D4FB0, + 0x03B, 0x000CF060, + 0x03B, 0x000B0090, + 0x03B, 0x000A0080, + 0x03B, 0x00090080, + 0x03B, 0x0008F780, + 0xFF010718, 0xABCD, + 0x03B, 0x000787B0, + 0xCDCDCDCD, 0xCDCD, + 0x03B, 0x00078730, + 0xFF010718, 0xDEAD, + 0x03B, 0x00060FB0, + 0x03B, 0x0005FFA0, + 0x03B, 0x00040620, + 0x03B, 0x00037090, + 0x03B, 0x00020080, + 0x03B, 0x0001F060, + 0x03B, 0x0000FFB0, + 0x0EF, 0x000000A0, + 0x000, 0x00010159, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x01E, 0x00000001, + 0x01F, 0x00080000, + 0x000, 0x00033E70, +}; + +u32 RTL8192EE_MAC_ARRAY[] = { + 0x011, 0x000000EB, + 0x012, 0x00000007, + 0x014, 0x00000075, + 0x303, 0x000000A7, + 0x428, 0x0000000A, + 0x429, 0x00000010, + 0x430, 0x00000000, + 0x431, 0x00000000, + 0x432, 0x00000000, + 0x433, 0x00000001, + 0x434, 0x00000004, + 0x435, 0x00000005, + 0x436, 0x00000007, + 0x437, 0x00000008, + 0x43C, 0x00000004, + 0x43D, 0x00000005, + 0x43E, 0x00000007, + 0x43F, 0x00000008, + 0x440, 0x0000005D, + 0x441, 0x00000001, + 0x442, 0x00000000, + 0x444, 0x00000010, + 0x445, 0x00000000, + 0x446, 0x00000000, + 0x447, 0x00000000, + 0x448, 0x00000000, + 0x449, 0x000000F0, + 0x44A, 0x0000000F, + 0x44B, 0x0000003E, + 0x44C, 0x00000010, + 0x44D, 0x00000000, + 0x44E, 0x00000000, + 0x44F, 0x00000000, + 0x450, 0x00000000, + 0x451, 0x000000F0, + 0x452, 0x0000000F, + 0x453, 0x00000000, + 0x456, 0x0000005E, + 0x460, 0x00000066, + 0x461, 0x00000066, + 0x4C8, 0x000000FF, + 0x4C9, 0x00000008, + 0x4CC, 0x000000FF, + 0x4CD, 0x000000FF, + 0x4CE, 0x00000001, + 0x500, 0x00000026, + 0x501, 0x000000A2, + 0x502, 0x0000002F, + 0x503, 0x00000000, + 0x504, 0x00000028, + 0x505, 0x000000A3, + 0x506, 0x0000005E, + 0x507, 0x00000000, + 0x508, 0x0000002B, + 0x509, 0x000000A4, + 0x50A, 0x0000005E, + 0x50B, 0x00000000, + 0x50C, 0x0000004F, + 0x50D, 0x000000A4, + 0x50E, 0x00000000, + 0x50F, 0x00000000, + 0x512, 0x0000001C, + 0x514, 0x0000000A, + 0x516, 0x0000000A, + 0x525, 0x0000004F, + 0x540, 0x00000012, + 0x541, 0x00000064, + 0x550, 0x00000010, + 0x551, 0x00000010, + 0x559, 0x00000002, + 0x55C, 0x00000050, + 0x55D, 0x000000FF, + 0x605, 0x00000030, + 0x608, 0x0000000E, + 0x609, 0x0000002A, + 0x620, 0x000000FF, + 0x621, 0x000000FF, + 0x622, 0x000000FF, + 0x623, 0x000000FF, + 0x624, 0x000000FF, + 0x625, 0x000000FF, + 0x626, 0x000000FF, + 0x627, 0x000000FF, + 0x638, 0x00000050, + 0x63C, 0x0000000A, + 0x63D, 0x0000000A, + 0x63E, 0x0000000E, + 0x63F, 0x0000000E, + 0x640, 0x00000040, + 0x642, 0x00000040, + 0x643, 0x00000000, + 0x652, 0x000000C8, + 0x66E, 0x00000005, + 0x700, 0x00000021, + 0x701, 0x00000043, + 0x702, 0x00000065, + 0x703, 0x00000087, + 0x708, 0x00000021, + 0x709, 0x00000043, + 0x70A, 0x00000065, + 0x70B, 0x00000087, +}; + +u32 RTL8192EE_AGC_TAB_ARRAY[] = { + 0xFF010718, 0xABCD, + 0xC78, 0xFA000001, + 0xC78, 0xF9010001, + 0xC78, 0xF8020001, + 0xC78, 0xF7030001, + 0xC78, 0xF6040001, + 0xC78, 0xF5050001, + 0xC78, 0xF4060001, + 0xC78, 0xF3070001, + 0xC78, 0xF2080001, + 0xC78, 0xF1090001, + 0xC78, 0xF00A0001, + 0xC78, 0xEF0B0001, + 0xC78, 0xEE0C0001, + 0xC78, 0xED0D0001, + 0xC78, 0xEC0E0001, + 0xC78, 0xEB0F0001, + 0xC78, 0xEA100001, + 0xC78, 0xE9110001, + 0xC78, 0xE8120001, + 0xC78, 0xE7130001, + 0xC78, 0xE6140001, + 0xC78, 0xE5150001, + 0xC78, 0xE4160001, + 0xC78, 0xE3170001, + 0xC78, 0xE2180001, + 0xC78, 0xE1190001, + 0xC78, 0x8A1A0001, + 0xC78, 0x891B0001, + 0xC78, 0x881C0001, + 0xC78, 0x871D0001, + 0xC78, 0x861E0001, + 0xC78, 0x851F0001, + 0xC78, 0x84200001, + 0xC78, 0x83210001, + 0xC78, 0x82220001, + 0xC78, 0x6A230001, + 0xC78, 0x69240001, + 0xC78, 0x68250001, + 0xC78, 0x67260001, + 0xC78, 0x66270001, + 0xC78, 0x65280001, + 0xC78, 0x64290001, + 0xC78, 0x632A0001, + 0xC78, 0x622B0001, + 0xC78, 0x612C0001, + 0xC78, 0x602D0001, + 0xC78, 0x472E0001, + 0xC78, 0x462F0001, + 0xC78, 0x45300001, + 0xC78, 0x44310001, + 0xC78, 0x43320001, + 0xC78, 0x42330001, + 0xC78, 0x41340001, + 0xC78, 0x40350001, + 0xC78, 0x40360001, + 0xC78, 0x40370001, + 0xC78, 0x40380001, + 0xC78, 0x40390001, + 0xC78, 0x403A0001, + 0xC78, 0x403B0001, + 0xC78, 0x403C0001, + 0xC78, 0x403D0001, + 0xC78, 0x403E0001, + 0xC78, 0x403F0001, + 0xCDCDCDCD, 0xCDCD, + 0xC78, 0xFB000001, + 0xC78, 0xFB010001, + 0xC78, 0xFB020001, + 0xC78, 0xFB030001, + 0xC78, 0xFB040001, + 0xC78, 0xFB050001, + 0xC78, 0xFA060001, + 0xC78, 0xF9070001, + 0xC78, 0xF8080001, + 0xC78, 0xF7090001, + 0xC78, 0xF60A0001, + 0xC78, 0xF50B0001, + 0xC78, 0xF40C0001, + 0xC78, 0xF30D0001, + 0xC78, 0xF20E0001, + 0xC78, 0xF10F0001, + 0xC78, 0xF0100001, + 0xC78, 0xEF110001, + 0xC78, 0xEE120001, + 0xC78, 0xED130001, + 0xC78, 0xEC140001, + 0xC78, 0xEB150001, + 0xC78, 0xEA160001, + 0xC78, 0xE9170001, + 0xC78, 0xE8180001, + 0xC78, 0xE7190001, + 0xC78, 0xC81A0001, + 0xC78, 0xC71B0001, + 0xC78, 0xC61C0001, + 0xC78, 0x071D0001, + 0xC78, 0x061E0001, + 0xC78, 0x051F0001, + 0xC78, 0x04200001, + 0xC78, 0x03210001, + 0xC78, 0xAA220001, + 0xC78, 0xA9230001, + 0xC78, 0xA8240001, + 0xC78, 0xA7250001, + 0xC78, 0xA6260001, + 0xC78, 0x85270001, + 0xC78, 0x84280001, + 0xC78, 0x83290001, + 0xC78, 0x252A0001, + 0xC78, 0x242B0001, + 0xC78, 0x232C0001, + 0xC78, 0x222D0001, + 0xC78, 0x672E0001, + 0xC78, 0x662F0001, + 0xC78, 0x65300001, + 0xC78, 0x64310001, + 0xC78, 0x63320001, + 0xC78, 0x62330001, + 0xC78, 0x61340001, + 0xC78, 0x45350001, + 0xC78, 0x44360001, + 0xC78, 0x43370001, + 0xC78, 0x42380001, + 0xC78, 0x41390001, + 0xC78, 0x403A0001, + 0xC78, 0x403B0001, + 0xC78, 0x403C0001, + 0xC78, 0x403D0001, + 0xC78, 0x403E0001, + 0xC78, 0x403F0001, + 0xFF010718, 0xDEAD, + 0xFF010718, 0xABCD, + 0xC78, 0xFA400001, + 0xC78, 0xF9410001, + 0xC78, 0xF8420001, + 0xC78, 0xF7430001, + 0xC78, 0xF6440001, + 0xC78, 0xF5450001, + 0xC78, 0xF4460001, + 0xC78, 0xF3470001, + 0xC78, 0xF2480001, + 0xC78, 0xF1490001, + 0xC78, 0xF04A0001, + 0xC78, 0xEF4B0001, + 0xC78, 0xEE4C0001, + 0xC78, 0xED4D0001, + 0xC78, 0xEC4E0001, + 0xC78, 0xEB4F0001, + 0xC78, 0xEA500001, + 0xC78, 0xE9510001, + 0xC78, 0xE8520001, + 0xC78, 0xE7530001, + 0xC78, 0xE6540001, + 0xC78, 0xE5550001, + 0xC78, 0xE4560001, + 0xC78, 0xE3570001, + 0xC78, 0xE2580001, + 0xC78, 0xE1590001, + 0xC78, 0x8A5A0001, + 0xC78, 0x895B0001, + 0xC78, 0x885C0001, + 0xC78, 0x875D0001, + 0xC78, 0x865E0001, + 0xC78, 0x855F0001, + 0xC78, 0x84600001, + 0xC78, 0x83610001, + 0xC78, 0x82620001, + 0xC78, 0x6A630001, + 0xC78, 0x69640001, + 0xC78, 0x68650001, + 0xC78, 0x67660001, + 0xC78, 0x66670001, + 0xC78, 0x65680001, + 0xC78, 0x64690001, + 0xC78, 0x636A0001, + 0xC78, 0x626B0001, + 0xC78, 0x616C0001, + 0xC78, 0x606D0001, + 0xC78, 0x476E0001, + 0xC78, 0x466F0001, + 0xC78, 0x45700001, + 0xC78, 0x44710001, + 0xC78, 0x43720001, + 0xC78, 0x42730001, + 0xC78, 0x41740001, + 0xC78, 0x40750001, + 0xC78, 0x40760001, + 0xC78, 0x40770001, + 0xC78, 0x40780001, + 0xC78, 0x40790001, + 0xC78, 0x407A0001, + 0xC78, 0x407B0001, + 0xC78, 0x407C0001, + 0xC78, 0x407D0001, + 0xC78, 0x407E0001, + 0xC78, 0x407F0001, + 0xC50, 0x00040222, + 0xC50, 0x00040220, + 0xCDCDCDCD, 0xCDCD, + 0xC78, 0xFB400001, + 0xC78, 0xFB410001, + 0xC78, 0xFB420001, + 0xC78, 0xFB430001, + 0xC78, 0xFB440001, + 0xC78, 0xFB450001, + 0xC78, 0xFA460001, + 0xC78, 0xF9470001, + 0xC78, 0xF8480001, + 0xC78, 0xF7490001, + 0xC78, 0xF64A0001, + 0xC78, 0xF54B0001, + 0xC78, 0xF44C0001, + 0xC78, 0xF34D0001, + 0xC78, 0xF24E0001, + 0xC78, 0xF14F0001, + 0xC78, 0xF0500001, + 0xC78, 0xEF510001, + 0xC78, 0xEE520001, + 0xC78, 0xED530001, + 0xC78, 0xEC540001, + 0xC78, 0xEB550001, + 0xC78, 0xEA560001, + 0xC78, 0xE9570001, + 0xC78, 0xE8580001, + 0xC78, 0xE7590001, + 0xC78, 0xE65A0001, + 0xC78, 0xE55B0001, + 0xC78, 0xE45C0001, + 0xC78, 0xE35D0001, + 0xC78, 0xE25E0001, + 0xC78, 0xE15F0001, + 0xC78, 0x8A600001, + 0xC78, 0x89610001, + 0xC78, 0x88620001, + 0xC78, 0x87630001, + 0xC78, 0x86640001, + 0xC78, 0x85650001, + 0xC78, 0x84660001, + 0xC78, 0x83670001, + 0xC78, 0x82680001, + 0xC78, 0x6B690001, + 0xC78, 0x6A6A0001, + 0xC78, 0x696B0001, + 0xC78, 0x686C0001, + 0xC78, 0x676D0001, + 0xC78, 0x666E0001, + 0xC78, 0x656F0001, + 0xC78, 0x64700001, + 0xC78, 0x63710001, + 0xC78, 0x62720001, + 0xC78, 0x61730001, + 0xC78, 0x49740001, + 0xC78, 0x48750001, + 0xC78, 0x47760001, + 0xC78, 0x46770001, + 0xC78, 0x45780001, + 0xC78, 0x44790001, + 0xC78, 0x437A0001, + 0xC78, 0x427B0001, + 0xC78, 0x417C0001, + 0xC78, 0x407D0001, + 0xC78, 0x407E0001, + 0xC78, 0x407F0001, + 0xC50, 0x00040022, + 0xC50, 0x00040020, + 0xFF010718, 0xDEAD, +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h new file mode 100644 index 000000000000..bff9df88815d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/table.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92E_TABLE__H_ +#define __RTL92E_TABLE__H_ + +#include +#define RTL8192EE_PHY_REG_ARRAY_LEN 448 +extern u32 RTL8192EE_PHY_REG_ARRAY[]; +#define RTL8192EE_PHY_REG_ARRAY_PG_LEN 168 +extern u32 RTL8192EE_PHY_REG_ARRAY_PG[]; +#define RTL8192EE_RADIOA_ARRAY_LEN 238 +extern u32 RTL8192EE_RADIOA_ARRAY[]; +#define RTL8192EE_RADIOB_ARRAY_LEN 198 +extern u32 RTL8192EE_RADIOB_ARRAY[]; +#define RTL8192EE_MAC_ARRAY_LEN 202 +extern u32 RTL8192EE_MAC_ARRAY[]; +#define RTL8192EE_AGC_TAB_ARRAY_LEN 532 +extern u32 RTL8192EE_AGC_TAB_ARRAY[]; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c new file mode 100644 index 000000000000..d39ee67f6113 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.c @@ -0,0 +1,1129 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../stats.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "trx.h" +#include "led.h" +#include "dm.h" +#include "fw.h" + +static u8 _rtl92ee_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) +{ + __le16 fc = rtl_get_fc(skb); + + if (unlikely(ieee80211_is_beacon(fc))) + return QSLT_BEACON; + if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) + return QSLT_MGNT; + + return skb->priority; +} + +static void _rtl92ee_query_rxphystatus(struct ieee80211_hw *hw, + struct rtl_stats *pstatus, u8 *pdesc, + struct rx_fwinfo *p_drvinfo, + bool bpacket_match_bssid, + bool bpacket_toself, + bool packet_beacon) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct phy_status_rpt *p_phystrpt = (struct phy_status_rpt *)p_drvinfo; + char rx_pwr_all = 0, rx_pwr[4]; + u8 rf_rx_num = 0, evm, pwdb_all; + u8 i, max_spatial_stream; + u32 rssi, total_rssi = 0; + bool is_cck = pstatus->is_cck; + u8 lan_idx, vga_idx; + + /* Record it for next packet processing */ + pstatus->packet_matchbssid = bpacket_match_bssid; + pstatus->packet_toself = bpacket_toself; + pstatus->packet_beacon = packet_beacon; + pstatus->rx_mimo_signalquality[0] = -1; + pstatus->rx_mimo_signalquality[1] = -1; + + if (is_cck) { + u8 cck_highpwr; + u8 cck_agc_rpt; + /* CCK Driver info Structure is not the same as OFDM packet. */ + cck_agc_rpt = p_phystrpt->cck_agc_rpt_ofdm_cfosho_a; + + /* (1)Hardware does not provide RSSI for CCK + * (2)PWDB, Average PWDB cacluated by + * hardware (for rate adaptive) + */ + cck_highpwr = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, + BIT(9)); + + lan_idx = ((cck_agc_rpt & 0xE0) >> 5); + vga_idx = (cck_agc_rpt & 0x1f); + switch (lan_idx) { + case 7: /*VGA_idx = 27~2*/ + if (vga_idx <= 27) + rx_pwr_all = -100 + 2 * (27 - vga_idx); + else + rx_pwr_all = -100; + break; + case 6: /*VGA_idx = 2~0*/ + rx_pwr_all = -48 + 2 * (2 - vga_idx); + break; + case 5: /*VGA_idx = 7~5*/ + rx_pwr_all = -42 + 2 * (7 - vga_idx); + break; + case 4: /*VGA_idx = 7~4*/ + rx_pwr_all = -36 + 2 * (7 - vga_idx); + break; + case 3: /*VGA_idx = 7~0*/ + rx_pwr_all = -24 + 2 * (7 - vga_idx); + break; + case 2: /*VGA_idx = 5~0*/ + if (cck_highpwr) + rx_pwr_all = -12 + 2 * (5 - vga_idx); + else + rx_pwr_all = -6 + 2 * (5 - vga_idx); + break; + case 1: + rx_pwr_all = 8 - 2 * vga_idx; + break; + case 0: + rx_pwr_all = 14 - 2 * vga_idx; + break; + default: + break; + } + rx_pwr_all += 16; + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + + if (!cck_highpwr) { + if (pwdb_all >= 80) + pwdb_all = ((pwdb_all - 80) << 1) + + ((pwdb_all - 80) >> 1) + 80; + else if ((pwdb_all <= 78) && (pwdb_all >= 20)) + pwdb_all += 3; + if (pwdb_all > 100) + pwdb_all = 100; + } + + pstatus->rx_pwdb_all = pwdb_all; + pstatus->bt_rx_rssi_percentage = pwdb_all; + pstatus->recvsignalpower = rx_pwr_all; + + /* (3) Get Signal Quality (EVM) */ + if (bpacket_match_bssid) { + u8 sq, sq_rpt; + + if (pstatus->rx_pwdb_all > 40) { + sq = 100; + } else { + sq_rpt = p_phystrpt->cck_sig_qual_ofdm_pwdb_all; + if (sq_rpt > 64) + sq = 0; + else if (sq_rpt < 20) + sq = 100; + else + sq = ((64 - sq_rpt) * 100) / 44; + } + + pstatus->signalquality = sq; + pstatus->rx_mimo_signalquality[0] = sq; + pstatus->rx_mimo_signalquality[1] = -1; + } + } else { + /* (1)Get RSSI for HT rate */ + for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { + /* we will judge RF RX path now. */ + if (rtlpriv->dm.rfpath_rxenable[i]) + rf_rx_num++; + + rx_pwr[i] = ((p_phystrpt->path_agc[i].gain & 0x3f) * 2) + - 110; + + pstatus->rx_pwr[i] = rx_pwr[i]; + /* Translate DBM to percentage. */ + rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + + pstatus->rx_mimo_signalstrength[i] = (u8)rssi; + } + + /* (2)PWDB, Average PWDB cacluated by + * hardware (for rate adaptive) + */ + rx_pwr_all = ((p_phystrpt->cck_sig_qual_ofdm_pwdb_all >> 1) + & 0x7f) - 110; + + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + pstatus->rx_pwdb_all = pwdb_all; + pstatus->bt_rx_rssi_percentage = pwdb_all; + pstatus->rxpower = rx_pwr_all; + pstatus->recvsignalpower = rx_pwr_all; + + /* (3)EVM of HT rate */ + if (pstatus->rate >= DESC_RATEMCS8 && + pstatus->rate <= DESC_RATEMCS15) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + + for (i = 0; i < max_spatial_stream; i++) { + evm = rtl_evm_db_to_percentage( + p_phystrpt->stream_rxevm[i]); + + if (bpacket_match_bssid) { + /* Fill value in RFD, Get the first + * spatial stream only + */ + if (i == 0) + pstatus->signalquality = (u8)(evm & + 0xff); + pstatus->rx_mimo_signalquality[i] = (u8)(evm & + 0xff); + } + } + + if (bpacket_match_bssid) { + for (i = RF90_PATH_A; i <= RF90_PATH_B; i++) + rtl_priv(hw)->dm.cfo_tail[i] = + (int)p_phystrpt->path_cfotail[i]; + + if (rtl_priv(hw)->dm.packet_count == 0xffffffff) + rtl_priv(hw)->dm.packet_count = 0; + else + rtl_priv(hw)->dm.packet_count++; + } + } + + /* UI BSS List signal strength(in percentage), + * make it good looking, from 0~100. + */ + if (is_cck) + pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, + pwdb_all)); + else if (rf_rx_num != 0) + pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, + total_rssi /= rf_rx_num)); +} + +static void _rtl92ee_translate_rx_signal_stuff(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct rtl_stats *pstatus, + u8 *pdesc, + struct rx_fwinfo *p_drvinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct ieee80211_hdr *hdr; + u8 *tmp_buf; + u8 *praddr; + u8 *psaddr; + __le16 fc; + bool packet_matchbssid, packet_toself, packet_beacon; + + tmp_buf = skb->data + pstatus->rx_drvinfo_size + + pstatus->rx_bufshift + 24; + + hdr = (struct ieee80211_hdr *)tmp_buf; + fc = hdr->frame_control; + praddr = hdr->addr1; + psaddr = ieee80211_get_SA(hdr); + ether_addr_copy(pstatus->psaddr, psaddr); + + packet_matchbssid = (!ieee80211_is_ctl(fc) && + (ether_addr_equal(mac->bssid, + ieee80211_has_tods(fc) ? + hdr->addr1 : + ieee80211_has_fromds(fc) ? + hdr->addr2 : hdr->addr3)) && + (!pstatus->hwerror) && (!pstatus->crc) && + (!pstatus->icv)); + + packet_toself = packet_matchbssid && + (ether_addr_equal(praddr, rtlefuse->dev_addr)); + + if (ieee80211_is_beacon(fc)) + packet_beacon = true; + else + packet_beacon = false; + + if (packet_beacon && packet_matchbssid) + rtl_priv(hw)->dm.dbginfo.num_qry_beacon_pkt++; + + if (packet_matchbssid && ieee80211_is_data_qos(hdr->frame_control) && + !is_multicast_ether_addr(ieee80211_get_DA(hdr))) { + struct ieee80211_qos_hdr *hdr_qos = + (struct ieee80211_qos_hdr *)tmp_buf; + u16 tid = le16_to_cpu(hdr_qos->qos_ctrl) & 0xf; + + if (tid != 0 && tid != 3) + rtl_priv(hw)->dm.dbginfo.num_non_be_pkt++; + } + + _rtl92ee_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo, + packet_matchbssid, packet_toself, + packet_beacon); + rtl_process_phyinfo(hw, tmp_buf, pstatus); +} + +static void _rtl92ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, + u8 *virtualaddress) +{ + u32 dwtmp = 0; + + memset(virtualaddress, 0, 8); + + SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); + if (ptcb_desc->empkt_num == 1) { + dwtmp = ptcb_desc->empkt_len[0]; + } else { + dwtmp = ptcb_desc->empkt_len[0]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += ptcb_desc->empkt_len[1]; + } + SET_EARLYMODE_LEN0(virtualaddress, dwtmp); + + if (ptcb_desc->empkt_num <= 3) { + dwtmp = ptcb_desc->empkt_len[2]; + } else { + dwtmp = ptcb_desc->empkt_len[2]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += ptcb_desc->empkt_len[3]; + } + SET_EARLYMODE_LEN1(virtualaddress, dwtmp); + if (ptcb_desc->empkt_num <= 5) { + dwtmp = ptcb_desc->empkt_len[4]; + } else { + dwtmp = ptcb_desc->empkt_len[4]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += ptcb_desc->empkt_len[5]; + } + SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF); + SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4); + if (ptcb_desc->empkt_num <= 7) { + dwtmp = ptcb_desc->empkt_len[6]; + } else { + dwtmp = ptcb_desc->empkt_len[6]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += ptcb_desc->empkt_len[7]; + } + SET_EARLYMODE_LEN3(virtualaddress, dwtmp); + if (ptcb_desc->empkt_num <= 9) { + dwtmp = ptcb_desc->empkt_len[8]; + } else { + dwtmp = ptcb_desc->empkt_len[8]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += ptcb_desc->empkt_len[9]; + } + SET_EARLYMODE_LEN4(virtualaddress, dwtmp); +} + +bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *status, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rx_fwinfo *p_drvinfo; + struct ieee80211_hdr *hdr; + u32 phystatus = GET_RX_DESC_PHYST(pdesc); + + if (GET_RX_STATUS_DESC_RPT_SEL(pdesc) == 0) + status->packet_report_type = NORMAL_RX; + else + status->packet_report_type = C2H_PACKET; + status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); + status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * + RX_DRV_INFO_SIZE_UNIT; + status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03); + status->icv = (u16)GET_RX_DESC_ICV(pdesc); + status->crc = (u16)GET_RX_DESC_CRC32(pdesc); + status->hwerror = (status->crc | status->icv); + status->decrypted = !GET_RX_DESC_SWDEC(pdesc); + status->rate = (u8)GET_RX_DESC_RXMCS(pdesc); + status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); + status->timestamp_low = GET_RX_DESC_TSFL(pdesc); + status->is_cck = RTL92EE_RX_HAL_IS_CCK_RATE(status->rate); + + status->macid = GET_RX_DESC_MACID(pdesc); + if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) + status->wake_match = BIT(2); + else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) + status->wake_match = BIT(1); + else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) + status->wake_match = BIT(0); + else + status->wake_match = 0; + if (status->wake_match) + RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, + "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n", + status->wake_match); + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + + hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size + + status->rx_bufshift + 24); + + if (status->crc) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (status->rx_is40Mhzpacket) + rx_status->flag |= RX_FLAG_40MHZ; + + if (status->is_ht) + rx_status->flag |= RX_FLAG_HT; + + rx_status->flag |= RX_FLAG_MACTIME_START; + + /* hw will set status->decrypted true, if it finds the + * frame is open data frame or mgmt frame. + * So hw will not decryption robust managment frame + * for IEEE80211w but still set status->decrypted + * true, so here we should set it back to undecrypted + * for IEEE80211w frame, and mac80211 sw will help + * to decrypt it + */ + if (status->decrypted) { + if ((!_ieee80211_is_robust_mgmt_frame(hdr)) && + (ieee80211_has_protected(hdr->frame_control))) + rx_status->flag |= RX_FLAG_DECRYPTED; + else + rx_status->flag &= ~RX_FLAG_DECRYPTED; + } + + /* rate_idx: index of data rate into band's + * supported rates or MCS index if HT rates + * are use (RX_FLAG_HT) + * Notice: this is diff with windows define + */ + rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht, + false, status->rate); + + rx_status->mactime = status->timestamp_low; + if (phystatus) { + p_drvinfo = (struct rx_fwinfo *)(skb->data + + status->rx_bufshift + 24); + + _rtl92ee_translate_rx_signal_stuff(hw, skb, status, pdesc, + p_drvinfo); + } + rx_status->signal = status->recvsignalpower + 10; + if (status->packet_report_type == TX_REPORT2) { + status->macid_valid_entry[0] = + GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); + status->macid_valid_entry[1] = + GET_RX_RPT2_DESC_MACID_VALID_2(pdesc); + } + return true; +} + +/*in Windows, this == Rx_92EE_Interrupt*/ +void rtl92ee_rx_check_dma_ok(struct ieee80211_hw *hw, u8 *header_desc, + u8 queue_index) +{ + u8 first_seg = 0; + u8 last_seg = 0; + u16 total_len = 0; + u16 read_cnt = 0; + + if (header_desc == NULL) + return; + + total_len = (u16)GET_RX_BUFFER_DESC_TOTAL_LENGTH(header_desc); + + first_seg = (u8)GET_RX_BUFFER_DESC_FS(header_desc); + + last_seg = (u8)GET_RX_BUFFER_DESC_LS(header_desc); + + while (total_len == 0 && first_seg == 0 && last_seg == 0) { + read_cnt++; + total_len = (u16)GET_RX_BUFFER_DESC_TOTAL_LENGTH(header_desc); + first_seg = (u8)GET_RX_BUFFER_DESC_FS(header_desc); + last_seg = (u8)GET_RX_BUFFER_DESC_LS(header_desc); + + if (read_cnt > 20) + break; + } +} + +u16 rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, u8 queue_index) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 read_point = 0, write_point = 0, remind_cnt = 0; + u32 tmp_4byte = 0; + static u16 last_read_point; + static bool start_rx; + + tmp_4byte = rtl_read_dword(rtlpriv, REG_RXQ_TXBD_IDX); + read_point = (u16)((tmp_4byte>>16) & 0x7ff); + write_point = (u16)(tmp_4byte & 0x7ff); + + if (write_point != rtlpci->rx_ring[queue_index].next_rx_rp) { + RT_TRACE(rtlpriv, COMP_RXDESC, DBG_DMESG, + "!!!write point is 0x%x, reg 0x3B4 value is 0x%x\n", + write_point, tmp_4byte); + tmp_4byte = rtl_read_dword(rtlpriv, REG_RXQ_TXBD_IDX); + read_point = (u16)((tmp_4byte>>16) & 0x7ff); + write_point = (u16)(tmp_4byte & 0x7ff); + } + + if (read_point > 0) + start_rx = true; + if (!start_rx) + return 0; + + remind_cnt = calc_fifo_space(read_point, write_point); + + if (remind_cnt == 0) + return 0; + + rtlpci->rx_ring[queue_index].next_rx_rp = write_point; + + last_read_point = read_point; + return remind_cnt; +} + +static u16 get_desc_addr_fr_q_idx(u16 queue_index) +{ + u16 desc_address = REG_BEQ_TXBD_IDX; + + switch (queue_index) { + case BK_QUEUE: + desc_address = REG_BKQ_TXBD_IDX; + break; + case BE_QUEUE: + desc_address = REG_BEQ_TXBD_IDX; + break; + case VI_QUEUE: + desc_address = REG_VIQ_TXBD_IDX; + break; + case VO_QUEUE: + desc_address = REG_VOQ_TXBD_IDX; + break; + case BEACON_QUEUE: + desc_address = REG_BEQ_TXBD_IDX; + break; + case TXCMD_QUEUE: + desc_address = REG_BEQ_TXBD_IDX; + break; + case MGNT_QUEUE: + desc_address = REG_MGQ_TXBD_IDX; + break; + case HIGH_QUEUE: + desc_address = REG_HI0Q_TXBD_IDX; + break; + case HCCA_QUEUE: + desc_address = REG_BEQ_TXBD_IDX; + break; + default: + break; + } + return desc_address; +} + +u16 rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 q_idx) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 point_diff = 0; + u16 current_tx_read_point = 0, current_tx_write_point = 0; + u32 tmp_4byte; + + tmp_4byte = rtl_read_dword(rtlpriv, + get_desc_addr_fr_q_idx(q_idx)); + current_tx_read_point = (u16)((tmp_4byte >> 16) & 0x0fff); + current_tx_write_point = (u16)((tmp_4byte) & 0x0fff); + + point_diff = calc_fifo_space(current_tx_read_point, + current_tx_write_point); + + rtlpci->tx_ring[q_idx].avl_desc = point_diff; + return point_diff; +} + +void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, + u8 *tx_bd_desc, u8 *desc, u8 queue_index, + struct sk_buff *skb, dma_addr_t addr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 pkt_len = skb->len; + u16 desc_size = 40; /*tx desc size*/ + u32 psblen = 0; + u16 tx_page_size = 0; + u32 total_packet_size = 0; + u16 current_bd_desc; + u8 i = 0; + u16 real_desc_size = 0x28; + u16 append_early_mode_size = 0; +#if (RTL8192EE_SEG_NUM == 0) + u8 segmentnum = 2; +#elif (RTL8192EE_SEG_NUM == 1) + u8 segmentnum = 4; +#elif (RTL8192EE_SEG_NUM == 2) + u8 segmentnum = 8; +#endif + + tx_page_size = 2; + current_bd_desc = rtlpci->tx_ring[queue_index].cur_tx_wp; + + total_packet_size = desc_size+pkt_len; + + if (rtlpriv->rtlhal.earlymode_enable) { + if (queue_index < BEACON_QUEUE) { + append_early_mode_size = 8; + total_packet_size += append_early_mode_size; + } + } + + if (tx_page_size > 0) { + psblen = (pkt_len + real_desc_size + append_early_mode_size) / + (tx_page_size * 128); + + if (psblen * (tx_page_size * 128) < total_packet_size) + psblen += 1; + } + + /* Reset */ + SET_TX_BUFF_DESC_LEN_0(tx_bd_desc, 0); + SET_TX_BUFF_DESC_PSB(tx_bd_desc, 0); + SET_TX_BUFF_DESC_OWN(tx_bd_desc, 0); + + for (i = 1; i < segmentnum; i++) { + SET_TXBUFFER_DESC_LEN_WITH_OFFSET(tx_bd_desc, i, 0); + SET_TXBUFFER_DESC_AMSDU_WITH_OFFSET(tx_bd_desc, i, 0); + SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(tx_bd_desc, i, 0); +#if (DMA_IS_64BIT == 1) + SET_TXBUFFER_DESC_ADD_HIGT_WITH_OFFSET(tx_bd_desc, i, 0); +#endif + } + SET_TX_BUFF_DESC_LEN_1(tx_bd_desc, 0); + SET_TX_BUFF_DESC_AMSDU_1(tx_bd_desc, 0); + + SET_TX_BUFF_DESC_LEN_2(tx_bd_desc, 0); + SET_TX_BUFF_DESC_AMSDU_2(tx_bd_desc, 0); + SET_TX_BUFF_DESC_LEN_3(tx_bd_desc, 0); + SET_TX_BUFF_DESC_AMSDU_3(tx_bd_desc, 0); + /* Clear all status */ + CLEAR_PCI_TX_DESC_CONTENT(desc, TX_DESC_SIZE); + + if (rtlpriv->rtlhal.earlymode_enable) { + if (queue_index < BEACON_QUEUE) { + /* This if needs braces */ + SET_TX_BUFF_DESC_LEN_0(tx_bd_desc, desc_size + 8); + } else { + SET_TX_BUFF_DESC_LEN_0(tx_bd_desc, desc_size); + } + } else { + SET_TX_BUFF_DESC_LEN_0(tx_bd_desc, desc_size); + } + SET_TX_BUFF_DESC_PSB(tx_bd_desc, psblen); + SET_TX_BUFF_DESC_ADDR_LOW_0(tx_bd_desc, + rtlpci->tx_ring[queue_index].dma + + (current_bd_desc * TX_DESC_SIZE)); + + SET_TXBUFFER_DESC_LEN_WITH_OFFSET(tx_bd_desc, 1, pkt_len); + /* don't using extendsion mode. */ + SET_TXBUFFER_DESC_AMSDU_WITH_OFFSET(tx_bd_desc, 1, 0); + SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(tx_bd_desc, 1, addr); + + SET_TX_DESC_PKT_SIZE(desc, (u16)(pkt_len)); + SET_TX_DESC_TX_BUFFER_SIZE(desc, (u16)(pkt_len)); +} + +void rtl92ee_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *pbd_desc_tx, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 *pdesc = (u8 *)pdesc_tx; + u16 seq_number; + __le16 fc = hdr->frame_control; + unsigned int buf_len = 0; + u8 fw_qsel = _rtl92ee_map_hwqueue_to_fwqueue(skb, hw_queue); + bool firstseg = ((hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); + bool lastseg = ((hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); + dma_addr_t mapping; + u8 bw_40 = 0; + u8 short_gi = 0; + + if (mac->opmode == NL80211_IFTYPE_STATION) { + bw_40 = mac->bw_40; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta) + bw_40 = sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40; + } + seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); + /* reserve 8 byte for AMPDU early mode */ + if (rtlhal->earlymode_enable) { + skb_push(skb, EM_HDR_LEN); + memset(skb->data, 0, EM_HDR_LEN); + } + buf_len = skb->len; + mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + + if (pbd_desc_tx != NULL) + rtl92ee_pre_fill_tx_bd_desc(hw, pbd_desc_tx, pdesc, hw_queue, + skb, mapping); + + if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { + firstseg = true; + lastseg = true; + } + if (firstseg) { + if (rtlhal->earlymode_enable) { + SET_TX_DESC_PKT_OFFSET(pdesc, 1); + SET_TX_DESC_OFFSET(pdesc, + USB_HWDESC_HEADER_LEN + EM_HDR_LEN); + if (ptcb_desc->empkt_num) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "Insert 8 byte.pTcb->EMPktNum:%d\n", + ptcb_desc->empkt_num); + _rtl92ee_insert_emcontent(ptcb_desc, + (u8 *)(skb->data)); + } + } else { + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + } + + SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); + + if (ieee80211_is_mgmt(fc)) { + ptcb_desc->use_driver_rate = true; + } else { + if (rtlpriv->ra.is_special_data) { + ptcb_desc->use_driver_rate = true; + SET_TX_DESC_TX_RATE(pdesc, DESC_RATE11M); + } else { + ptcb_desc->use_driver_rate = false; + } + } + + if (ptcb_desc->hw_rate > DESC_RATEMCS0) + short_gi = (ptcb_desc->use_shortgi) ? 1 : 0; + else + short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0; + + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + SET_TX_DESC_AGG_ENABLE(pdesc, 1); + SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); + } + SET_TX_DESC_SEQ(pdesc, seq_number); + SET_TX_DESC_RTS_ENABLE(pdesc, + ((ptcb_desc->rts_enable && + !ptcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_HW_RTS_ENABLE(pdesc, 0); + SET_TX_DESC_CTS2SELF(pdesc, + ((ptcb_desc->cts_enable) ? 1 : 0)); + + SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); + SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); + SET_TX_DESC_RTS_SHORT(pdesc, + ((ptcb_desc->rts_rate <= DESC_RATE54M) ? + (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : + (ptcb_desc->rts_use_shortgi ? 1 : 0))); + + if (ptcb_desc->tx_enable_sw_calc_duration) + SET_TX_DESC_NAV_USE_HDR(pdesc, 1); + + if (bw_40) { + if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { + SET_TX_DESC_DATA_BW(pdesc, 1); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + mac->cur_40_prime_sc); + } + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + } + + SET_TX_DESC_LINIP(pdesc, 0); + if (sta) { + u8 ampdu_density = sta->ht_cap.ampdu_density; + + SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); + } + if (info->control.hw_key) { + struct ieee80211_key_conf *key = info->control.hw_key; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x1); + break; + case WLAN_CIPHER_SUITE_CCMP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x3); + break; + default: + SET_TX_DESC_SEC_TYPE(pdesc, 0x0); + break; + } + } + + SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); + SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); + SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); + SET_TX_DESC_DISABLE_FB(pdesc, + ptcb_desc->disable_ratefallback ? 1 : 0); + SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); + + /*SET_TX_DESC_PWR_STATUS(pdesc, pwr_status);*/ + /* Set TxRate and RTSRate in TxDesc */ + /* This prevent Tx initial rate of new-coming packets */ + /* from being overwritten by retried packet rate.*/ + if (!ptcb_desc->use_driver_rate) { + /*SET_TX_DESC_RTS_RATE(pdesc, 0x08); */ + /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */ + } + if (ieee80211_is_data_qos(fc)) { + if (mac->rdg_en) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "Enable RDG function.\n"); + SET_TX_DESC_RDG_ENABLE(pdesc, 1); + SET_TX_DESC_HTC(pdesc, 1); + } + } + } + + SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); + SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + if (rtlpriv->dm.useramask) { + SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); + } else { + SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); + } + + SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { + SET_TX_DESC_BMC(pdesc, 1); + } + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); +} + +void rtl92ee_tx_fill_cmddesc(struct ieee80211_hw *hw, + u8 *pdesc, bool firstseg, + bool lastseg, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 fw_queue = QSLT_BEACON; + dma_addr_t mapping = pci_map_single(rtlpci->pdev, + skb->data, skb->len, + PCI_DMA_TODEVICE); + u8 txdesc_len = 40; + + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + CLEAR_PCI_TX_DESC_CONTENT(pdesc, txdesc_len); + + if (firstseg) + SET_TX_DESC_OFFSET(pdesc, txdesc_len); + + SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M); + + SET_TX_DESC_SEQ(pdesc, 0); + + SET_TX_DESC_LINIP(pdesc, 0); + + SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); + + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + + SET_TX_DESC_RATE_ID(pdesc, 7); + SET_TX_DESC_MACID(pdesc, 0); + + SET_TX_DESC_OWN(pdesc, 1); + + SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len)); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_OFFSET(pdesc, 40); + + SET_TX_DESC_USE_RATE(pdesc, 1); + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C Tx Cmd Content\n", pdesc, txdesc_len); +} + +void rtl92ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, + u8 desc_name, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 cur_tx_rp = 0; + u16 cur_tx_wp = 0; + static u16 last_txw_point; + static bool over_run; + u32 tmp = 0; + u8 q_idx = *val; + + if (istx) { + switch (desc_name) { + case HW_DESC_TX_NEXTDESC_ADDR: + SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *)val); + break; + case HW_DESC_OWN:{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[q_idx]; + u16 max_tx_desc = ring->entries; + + if (q_idx == BEACON_QUEUE) { + ring->cur_tx_wp = 0; + ring->cur_tx_rp = 0; + SET_TX_BUFF_DESC_OWN(pdesc, 1); + return; + } + + ring->cur_tx_wp = ((ring->cur_tx_wp + 1) % max_tx_desc); + + if (over_run) { + ring->cur_tx_wp = 0; + over_run = false; + } + if (ring->avl_desc > 1) { + ring->avl_desc--; + + rtl_write_word(rtlpriv, + get_desc_addr_fr_q_idx(q_idx), + ring->cur_tx_wp); + + if (q_idx == 1) + last_txw_point = cur_tx_wp; + } + + if (ring->avl_desc < (max_tx_desc - 15)) { + u16 point_diff = 0; + + tmp = + rtl_read_dword(rtlpriv, + get_desc_addr_fr_q_idx(q_idx)); + cur_tx_rp = (u16)((tmp >> 16) & 0x0fff); + cur_tx_wp = (u16)(tmp & 0x0fff); + + ring->cur_tx_wp = cur_tx_wp; + ring->cur_tx_rp = cur_tx_rp; + point_diff = ((cur_tx_rp > cur_tx_wp) ? + (cur_tx_rp - cur_tx_wp) : + (TX_DESC_NUM_92E - 1 - + cur_tx_wp + cur_tx_rp)); + + ring->avl_desc = point_diff; + } + } + break; + } + } else { + switch (desc_name) { + case HW_DESC_RX_PREPARE: + SET_RX_BUFFER_DESC_LS(pdesc, 0); + SET_RX_BUFFER_DESC_FS(pdesc, 0); + SET_RX_BUFFER_DESC_TOTAL_LENGTH(pdesc, 0); + + SET_RX_BUFFER_DESC_DATA_LENGTH(pdesc, + MAX_RECEIVE_BUFFER_SIZE + + RX_DESC_SIZE); + + SET_RX_BUFFER_PHYSICAL_LOW(pdesc, *(u32 *)val); + break; + case HW_DESC_RXERO: + SET_RX_DESC_EOR(pdesc, 1); + break; + default: + RT_ASSERT(false, + "ERR rxdesc :%d not process\n", desc_name); + break; + } + } +} + +u32 rtl92ee_get_desc(u8 *pdesc, bool istx, u8 desc_name) +{ + u32 ret = 0; + + if (istx) { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_TX_DESC_OWN(pdesc); + break; + case HW_DESC_TXBUFF_ADDR: + ret = GET_TXBUFFER_DESC_ADDR_LOW(pdesc, 1); + break; + default: + RT_ASSERT(false, + "ERR txdesc :%d not process\n", desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_RX_DESC_OWN(pdesc); + break; + case HW_DESC_RXPKT_LEN: + ret = GET_RX_DESC_PKT_LEN(pdesc); + break; + case HW_DESC_RXBUFF_ADDR: + ret = GET_RX_DESC_BUFF_ADDR(pdesc); + break; + default: + RT_ASSERT(false, + "ERR rxdesc :%d not process\n", desc_name); + break; + } + } + return ret; +} + +bool rtl92ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 read_point, write_point, available_desc_num; + bool ret = false; + static u8 stop_report_cnt; + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; + + { + u16 point_diff = 0; + u16 cur_tx_rp, cur_tx_wp; + u32 tmpu32 = 0; + + tmpu32 = + rtl_read_dword(rtlpriv, + get_desc_addr_fr_q_idx(hw_queue)); + cur_tx_rp = (u16)((tmpu32 >> 16) & 0x0fff); + cur_tx_wp = (u16)(tmpu32 & 0x0fff); + + ring->cur_tx_wp = cur_tx_wp; + ring->cur_tx_rp = cur_tx_rp; + point_diff = ((cur_tx_rp > cur_tx_wp) ? + (cur_tx_rp - cur_tx_wp) : + (TX_DESC_NUM_92E - cur_tx_wp + cur_tx_rp)); + + ring->avl_desc = point_diff; + } + + read_point = ring->cur_tx_rp; + write_point = ring->cur_tx_wp; + available_desc_num = ring->avl_desc; + + if (write_point > read_point) { + if (index < write_point && index >= read_point) + ret = false; + else + ret = true; + } else if (write_point < read_point) { + if (index > write_point && index < read_point) + ret = true; + else + ret = false; + } else { + if (index != read_point) + ret = true; + } + + if (hw_queue == BEACON_QUEUE) + ret = true; + + if (rtlpriv->rtlhal.driver_is_goingto_unload || + rtlpriv->psc.rfoff_reason > RF_CHANGE_BY_PS) + ret = true; + + if (hw_queue < BEACON_QUEUE) { + if (!ret) + stop_report_cnt++; + else + stop_report_cnt = 0; + } + + return ret; +} + +void rtl92ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) +{ +} + +u32 rtl92ee_rx_command_packet(struct ieee80211_hw *hw, + struct rtl_stats status, + struct sk_buff *skb) +{ + u32 result = 0; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (status.packet_report_type) { + case NORMAL_RX: + result = 0; + break; + case C2H_PACKET: + rtl92ee_c2h_packet_handler(hw, skb->data, (u8)skb->len); + result = 1; + break; + default: + RT_TRACE(rtlpriv, COMP_RECV, DBG_TRACE, + "Unknown packet type %d\n", status.packet_report_type); + break; + } + + return result; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h new file mode 100644 index 000000000000..8f78ac9e6040 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/trx.h @@ -0,0 +1,862 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92E_TRX_H__ +#define __RTL92E_TRX_H__ + +#if (DMA_IS_64BIT == 1) +#if (RTL8192EE_SEG_NUM == 2) +#define TX_BD_DESC_SIZE 128 +#elif (RTL8192EE_SEG_NUM == 1) +#define TX_BD_DESC_SIZE 64 +#elif (RTL8192EE_SEG_NUM == 0) +#define TX_BD_DESC_SIZE 32 +#endif +#else +#if (RTL8192EE_SEG_NUM == 2) +#define TX_BD_DESC_SIZE 64 +#elif (RTL8192EE_SEG_NUM == 1) +#define TX_BD_DESC_SIZE 32 +#elif (RTL8192EE_SEG_NUM == 0) +#define TX_BD_DESC_SIZE 16 +#endif +#endif + +#define TX_DESC_SIZE 64 + +#define RX_DRV_INFO_SIZE_UNIT 8 + +#define TX_DESC_NEXT_DESC_OFFSET 40 +#define USB_HWDESC_HEADER_LEN 40 + +#define RX_DESC_SIZE 24 +#define MAX_RECEIVE_BUFFER_SIZE 8192 + +#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) +#define SET_TX_DESC_OFFSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) +#define SET_TX_DESC_BMC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) +#define SET_TX_DESC_HTC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) +#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) +#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) +#define SET_TX_DESC_LINIP(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) +#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) +#define SET_TX_DESC_GF(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) +#define SET_TX_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +#define GET_TX_DESC_PKT_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 0, 16) +#define GET_TX_DESC_OFFSET(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 16, 8) +#define GET_TX_DESC_BMC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 24, 1) +#define GET_TX_DESC_HTC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 25, 1) +#define GET_TX_DESC_LAST_SEG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 26, 1) +#define GET_TX_DESC_FIRST_SEG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 27, 1) +#define GET_TX_DESC_LINIP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 28, 1) +#define GET_TX_DESC_NO_ACM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 29, 1) +#define GET_TX_DESC_GF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 30, 1) +#define GET_TX_DESC_OWN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 31, 1) + +#define SET_TX_DESC_MACID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 7, __val) +#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) +#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) +#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) +#define SET_TX_DESC_PIFS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) +#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 5, __val) +#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) +#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) +#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 5, __val) +#define SET_TX_DESC_MORE_DATA(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 29, 1, __val) +#define SET_TX_DESC_TXOP_PS_CAP(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 30, 1, __val) +#define SET_TX_DESC_TXOP_PS_MODE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 31, 1, __val) + +#define GET_TX_DESC_MACID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) +#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 5, 1) +#define GET_TX_DESC_AGG_BREAK(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 6, 1) +#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 7, 1) +#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 8, 5) +#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) +#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) +#define GET_TX_DESC_PIFS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) +#define GET_TX_DESC_RATE_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) +#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) +#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) +#define GET_TX_DESC_SEC_TYPE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 22, 2) +#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 24, 5) + +#define SET_TX_DESC_PAID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 9, __val) +#define SET_TX_DESC_CCA_RTS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 10, 2, __val) +#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val) +#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val) +#define SET_TX_DESC_NULL_0(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 1, __val) +#define SET_TX_DESC_NULL_1(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 15, 1, __val) +#define SET_TX_DESC_BK(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val) +#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) +#define SET_TX_DESC_RAW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) +#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) +#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) +#define SET_TX_DESC_BT_NULL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val) +#define SET_TX_DESC_GID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 6, __val) + +#define SET_TX_DESC_WHEADER_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 4, __val) +#define SET_TX_DESC_CHK_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 4, 1, __val) +#define SET_TX_DESC_EARLY_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 5, 1, __val) +#define SET_TX_DESC_HWSEQ_SEL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 6, 2, __val) +#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 1, __val) +#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 9, 1, __val) +#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 10, 1, __val) +#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 11, 1, __val) +#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 12, 1, __val) +#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 13, 1, __val) +#define SET_TX_DESC_HW_PORT_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 14, 1, __val) +#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 15, 1, __val) +#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 1, __val) +#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 17, 5, __val) +#define SET_TX_DESC_NDPA(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 22, 2, __val) +#define SET_TX_DESC_AMPDU_MAX_TIME(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 24, 8, __val) + +/* Dword 4 */ +#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 7, __val) +#define SET_TX_DESC_TRY_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 5, __val) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 4, __val) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 17, 1, __val) +#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 6, __val) +#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 5, __val) +#define SET_TX_DESC_PCTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 29, 1, __val) +#define SET_TX_DESC_PCTS_MASK_IDX(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val) + +/* Dword 5 */ +#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 4, __val) +#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 4, 1, __val) +#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 5, 2, __val) +#define SET_TX_DESC_DATA_LDPC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) +#define SET_TX_DESC_DATA_STBC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 2, __val) +#define SET_TX_DESC_VCS_STBC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 10, 2, __val) +#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 12, 1, __val) +#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) +#define SET_TX_DESC_TX_ANT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 4, __val) +#define SET_TX_DESC_TX_POWER_0_PSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 28, 3, __val) + +/* Dword 6 */ +#define SET_TX_DESC_SW_DEFINE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 12, __val) +#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 3, __val) +#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 19, 3, __val) +#define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 22, 3, __val) +#define SET_TX_DESC_ANTSEL_D(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 25, 3, __val) + +/* Dword 7 */ +#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) +#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 8, __val) + +/* Dword 8 */ +#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 6, __val) +#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 6, 2, __val) +#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 8, 6, __val) +#define SET_TX_DESC_ENABLE_HW_SELECT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 15, 1, __val) +#define SET_TX_DESC_NEXT_HEAD_PAGE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 16, 8, __val) +#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 24, 8, __val) + +/* Dword 9 */ +#define SET_TX_DESC_PADDING_LENGTH(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 11, __val) +#define SET_TX_DESC_TXBF_PATH(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+36, 11, 1, __val) +#define SET_TX_DESC_SEQ(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+36, 12, 12, __val) +#define SET_TX_DESC_FINAL_DATA_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+36, 24, 8, __val) + +/* Dword 10 */ +#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) + +/* Dword 11*/ +#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+48, 0, 32, __val) + +#define SET_EARLYMODE_PKTNUM(__paddr, __val) \ + SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __val) +#define SET_EARLYMODE_LEN0(__paddr, __val) \ + SET_BITS_TO_LE_4BYTE(__paddr, 4, 15, __val) +#define SET_EARLYMODE_LEN1(__paddr, __val) \ + SET_BITS_TO_LE_4BYTE(__paddr, 16, 2, __val) +#define SET_EARLYMODE_LEN1_1(__paddr, __val) \ + SET_BITS_TO_LE_4BYTE(__paddr, 19, 13, __val) +#define SET_EARLYMODE_LEN1_2(__paddr, __val) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 2, __val) +#define SET_EARLYMODE_LEN2(__paddr, __val) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 2, 15, __val) +#define SET_EARLYMODE_LEN2_1(__paddr, __val) \ + SET_BITS_TO_LE_4BYTE(__paddr, 2, 4, __val) +#define SET_EARLYMODE_LEN2_2(__paddr, __val) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __val) +#define SET_EARLYMODE_LEN3(__paddr, __val) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 17, 15, __val) +#define SET_EARLYMODE_LEN4(__paddr, __val) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __val) + +/* TX/RX buffer descriptor */ + +#define SET_TX_EXTBUFF_DESC_LEN(__pdesc, __val, __set) \ + SET_BITS_TO_LE_4BYTE(__pdesc+(__set*16), 0, 16, __val) +#define SET_TX_EXTBUFF_DESC_ADDR_LOW(__pdesc, __val, __set)\ + SET_BITS_TO_LE_4BYTE(__pdesc+(__set*16)+4, 0, 32, __val) +#define SET_TX_EXTBUFF_DESC_ADDR_HIGH(__pdesc, __val, __set)\ + SET_BITS_TO_LE_4BYTE(__pdesc+(__set*16)+8, 0, 32, __val) + +/* for Txfilldescroptor92ee, fill the desc content. */ +#if (DMA_IS_64BIT == 1) +#define SET_TXBUFFER_DESC_LEN_WITH_OFFSET(__pdesc, __offset, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*16), 0, 16, __val) +#define SET_TXBUFFER_DESC_AMSDU_WITH_OFFSET(__pdesc, __offset, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*16), 31, 1, __val) +#define SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(__pdesc, __offset, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*16)+4, 0, 32, __val) +#define SET_TXBUFFER_DESC_ADD_HIGT_WITH_OFFSET(__pdesc, __offset, __val)\ + SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*16)+8, 0, 32, __val) +#define GET_TXBUFFER_DESC_ADDR_LOW(__pdesc, __offset) \ + LE_BITS_TO_4BYTE(__pdesc+(__offset*16)+4, 0, 32) +#else +#define SET_TXBUFFER_DESC_LEN_WITH_OFFSET(__pdesc, __offset, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*8), 0, 16, __val) +#define SET_TXBUFFER_DESC_AMSDU_WITH_OFFSET(__pdesc, __offset, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*8), 31, 1, __val) +#define SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(__pdesc, __offset, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*8)+4, 0, 32, __val) +#define SET_TXBUFFER_DESC_ADD_HIGT_WITH_OFFSET(__pdesc, __offset, __val) +#define GET_TXBUFFER_DESC_ADDR_LOW(__pdesc, __offset) \ + LE_BITS_TO_4BYTE(__pdesc+(__offset*8)+4, 0, 32) +#endif + +/* Dword 0 */ +#define SET_TX_BUFF_DESC_LEN_0(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) +#define SET_TX_BUFF_DESC_PSB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 16, 15, __val) +#define SET_TX_BUFF_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +/* Dword 1 */ +#define SET_TX_BUFF_DESC_ADDR_LOW_0(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 32, __val) +#if (DMA_IS_64BIT == 1) +/* Dword 2 */ +#define SET_TX_BUFF_DESC_ADDR_HIGH_0(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 32, __val) +/* Dword 3 / RESERVED 0 */ +/* Dword 4 */ +#define SET_TX_BUFF_DESC_LEN_1(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 16, __val) +#define SET_TX_BUFF_DESC_AMSDU_1(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 31, 1, __val) +/* Dword 5 */ +#define SET_TX_BUFF_DESC_ADDR_LOW_1(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 32, __val) +/* Dword 6 */ +#define SET_TX_BUFF_DESC_ADDR_HIGH_1(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) +/* Dword 7 / RESERVED 0 */ +/* Dword 8 */ +#define SET_TX_BUFF_DESC_LEN_2(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 16, __val) +#define SET_TX_BUFF_DESC_AMSDU_2(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 31, 1, __val) +/* Dword 9 */ +#define SET_TX_BUFF_DESC_ADDR_LOW_2(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val) +/* Dword 10 */ +#define SET_TX_BUFF_DESC_ADDR_HIGH_2(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) +/* Dword 11 / RESERVED 0 */ +/* Dword 12 */ +#define SET_TX_BUFF_DESC_LEN_3(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+48, 0, 16, __val) +#define SET_TX_BUFF_DESC_AMSDU_3(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+48, 31, 1, __val) +/* Dword 13 */ +#define SET_TX_BUFF_DESC_ADDR_LOW_3(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+52, 0, 32, __val) +/* Dword 14 */ +#define SET_TX_BUFF_DESC_ADDR_HIGH_3(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+56, 0, 32, __val) +/* Dword 15 / RESERVED 0 */ +#else +#define SET_TX_BUFF_DESC_ADDR_HIGH_0(__pdesc, __val) +/* Dword 2 */ +#define SET_TX_BUFF_DESC_LEN_1(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 16, __val) +#define SET_TX_BUFF_DESC_AMSDU_1(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 31, 1, __val) +/* Dword 3 */ +#define SET_TX_BUFF_DESC_ADDR_LOW_1(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 32, __val) +#define SET_TX_BUFF_DESC_ADDR_HIGH_1(__pdesc, __val) +/* Dword 4 */ +#define SET_TX_BUFF_DESC_LEN_2(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 16, __val) +#define SET_TX_BUFF_DESC_AMSDU_2(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 31, 1, __val) +/* Dword 5 */ +#define SET_TX_BUFF_DESC_ADDR_LOW_2(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 32, __val) +#define SET_TX_BUFF_DESC_ADDR_HIGH_2(__pdesc, __val) +/* Dword 6 */ +#define SET_TX_BUFF_DESC_LEN_3(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 16, __val) +#define SET_TX_BUFF_DESC_AMSDU_3(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 31, 1, __val) +/* Dword 7 */ +#define SET_TX_BUFF_DESC_ADDR_LOW_3(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) +#define SET_TX_BUFF_DESC_ADDR_HIGH_3(__pdesc, __val) +#endif + +/* RX buffer */ + +/* DWORD 0 */ +#define SET_RX_BUFFER_DESC_DATA_LENGTH(__status, __val) \ + SET_BITS_TO_LE_4BYTE(__status, 0, 14, __val) +#define SET_RX_BUFFER_DESC_LS(__status, __val) \ + SET_BITS_TO_LE_4BYTE(__status, 15, 1, __val) +#define SET_RX_BUFFER_DESC_FS(__status, __val) \ + SET_BITS_TO_LE_4BYTE(__status, 16, 1, __val) +#define SET_RX_BUFFER_DESC_TOTAL_LENGTH(__status, __val) \ + SET_BITS_TO_LE_4BYTE(__status, 16, 15, __val) + +#define GET_RX_BUFFER_DESC_OWN(__status) \ + LE_BITS_TO_4BYTE(__status, 31, 1) +#define GET_RX_BUFFER_DESC_LS(__status) \ + LE_BITS_TO_4BYTE(__status, 15, 1) +#define GET_RX_BUFFER_DESC_FS(__status) \ + LE_BITS_TO_4BYTE(__status, 16, 1) +#define GET_RX_BUFFER_DESC_TOTAL_LENGTH(__status) \ + LE_BITS_TO_4BYTE(__status, 16, 15) + +/* DWORD 1 */ +#define SET_RX_BUFFER_PHYSICAL_LOW(__status, __val) \ + SET_BITS_TO_LE_4BYTE(__status+4, 0, 32, __val) + +/* DWORD 2 */ +#define SET_RX_BUFFER_PHYSICAL_HIGH(__status, __val) \ + SET_BITS_TO_LE_4BYTE(__status+8, 0, 32, __val) + +#define GET_RX_DESC_PKT_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 0, 14) +#define GET_RX_DESC_CRC32(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 14, 1) +#define GET_RX_DESC_ICV(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 15, 1) +#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 16, 4) +#define GET_RX_DESC_SECURITY(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 20, 3) +#define GET_RX_DESC_QOS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 23, 1) +#define GET_RX_DESC_SHIFT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 24, 2) +#define GET_RX_DESC_PHYST(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 26, 1) +#define GET_RX_DESC_SWDEC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 27, 1) +#define GET_RX_DESC_LS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 28, 1) +#define GET_RX_DESC_FS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 29, 1) +#define GET_RX_DESC_EOR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 30, 1) +#define GET_RX_DESC_OWN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 31, 1) + +#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) +#define SET_RX_DESC_EOR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) +#define SET_RX_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +#define GET_RX_DESC_MACID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 0, 7) +#define GET_RX_DESC_TID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 8, 4) +#define GET_RX_DESC_MACID_VLD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 12, 1) +#define GET_RX_DESC_AMSDU(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) +#define GET_RX_DESC_RXID_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) +#define GET_RX_DESC_PAGGR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) +#define GET_RX_DESC_A1_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) +#define GET_RX_DESC_TCPOFFLOAD_CHKERR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) +#define GET_RX_DESC_TCPOFFLOAD_IPVER(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) +#define GET_RX_DESC_TCPOFFLOAD_IS_TCPUDP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 22, 1) +#define GET_RX_DESC_TCPOFFLOAD_CHK_VLD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 23, 1) +#define GET_RX_DESC_PAM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) +#define GET_RX_DESC_PWR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) +#define GET_RX_DESC_MD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) +#define GET_RX_DESC_MF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) +#define GET_RX_DESC_TYPE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) +#define GET_RX_DESC_MC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) +#define GET_RX_DESC_BC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) +#define GET_RX_DESC_SEQ(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) +#define GET_RX_DESC_FRAG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) +#define GET_RX_DESC_RX_IS_QOS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 16, 1) +#define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 28, 1) + +#define GET_RX_DESC_RXMCS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 0, 7) +#define GET_RX_DESC_HTC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) +#define GET_RX_STATUS_DESC_EOSP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 11, 1) +#define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 12, 2) +#define GET_RX_STATUS_DESC_DMA_AGG_NUM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 16, 8) +#define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 29, 1) +#define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 30, 1) +#define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 31, 1) + +#define GET_RX_DESC_TSFL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) + +#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) +#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) + +#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) +#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) + +/* TX report 2 format in Rx desc*/ + +#define GET_RX_RPT2_DESC_PKT_LEN(__status) \ + LE_BITS_TO_4BYTE(__status, 0, 9) +#define GET_RX_RPT2_DESC_MACID_VALID_1(__status) \ + LE_BITS_TO_4BYTE(__status+16, 0, 32) +#define GET_RX_RPT2_DESC_MACID_VALID_2(__status) \ + LE_BITS_TO_4BYTE(__status+20, 0, 32) + +#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ +do { \ + if (_size > TX_DESC_NEXT_DESC_OFFSET) \ + memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ + else \ + memset(__pdesc, 0, _size); \ +} while (0) + +#define RTL92EE_RX_HAL_IS_CCK_RATE(rxmcs)\ + (rxmcs == DESC_RATE1M ||\ + rxmcs == DESC_RATE2M ||\ + rxmcs == DESC_RATE5_5M ||\ + rxmcs == DESC_RATE11M) + +#define IS_LITTLE_ENDIAN 1 + +struct phy_rx_agc_info_t { + #if IS_LITTLE_ENDIAN + u8 gain:7, trsw:1; + #else + u8 trsw:1, gain:7; + #endif +}; + +struct phy_status_rpt { + struct phy_rx_agc_info_t path_agc[2]; + u8 ch_corr[2]; + u8 cck_sig_qual_ofdm_pwdb_all; + u8 cck_agc_rpt_ofdm_cfosho_a; + u8 cck_rpt_b_ofdm_cfosho_b; + u8 rsvd_1; + u8 noise_power_db_msb; + u8 path_cfotail[2]; + u8 pcts_mask[2]; + u8 stream_rxevm[2]; + u8 path_rxsnr[2]; + u8 noise_power_db_lsb; + u8 rsvd_2[3]; + u8 stream_csi[2]; + u8 stream_target_csi[2]; + u8 sig_evm; + u8 rsvd_3; +#if IS_LITTLE_ENDIAN + u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ + u8 sgi_en:1; + u8 rxsc:2; + u8 idle_long:1; + u8 r_ant_train_en:1; + u8 ant_sel_b:1; + u8 ant_sel:1; +#else /* _BIG_ENDIAN_ */ + u8 ant_sel:1; + u8 ant_sel_b:1; + u8 r_ant_train_en:1; + u8 idle_long:1; + u8 rxsc:2; + u8 sgi_en:1; + u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ +#endif +} __packed; + +struct rx_fwinfo { + u8 gain_trsw[4]; + u8 pwdb_all; + u8 cfosho[4]; + u8 cfotail[4]; + char rxevm[2]; + char rxsnr[4]; + u8 pdsnr[2]; + u8 csi_current[2]; + u8 csi_target[2]; + u8 sigevm; + u8 max_ex_pwr; + u8 ex_intf_flag:1; + u8 sgi_en:1; + u8 rxsc:2; + u8 reserve:4; +} __packed; + +struct tx_desc { + u32 pktsize:16; + u32 offset:8; + u32 bmc:1; + u32 htc:1; + u32 lastseg:1; + u32 firstseg:1; + u32 linip:1; + u32 noacm:1; + u32 gf:1; + u32 own:1; + + u32 macid:6; + u32 rsvd0:2; + u32 queuesel:5; + u32 rd_nav_ext:1; + u32 lsig_txop_en:1; + u32 pifs:1; + u32 rateid:4; + u32 nav_usehdr:1; + u32 en_descid:1; + u32 sectype:2; + u32 pktoffset:8; + + u32 rts_rc:6; + u32 data_rc:6; + u32 agg_en:1; + u32 rdg_en:1; + u32 bar_retryht:2; + u32 agg_break:1; + u32 morefrag:1; + u32 raw:1; + u32 ccx:1; + u32 ampdudensity:3; + u32 bt_int:1; + u32 ant_sela:1; + u32 ant_selb:1; + u32 txant_cck:2; + u32 txant_l:2; + u32 txant_ht:2; + + u32 nextheadpage:8; + u32 tailpage:8; + u32 seq:12; + u32 cpu_handle:1; + u32 tag1:1; + u32 trigger_int:1; + u32 hwseq_en:1; + + u32 rtsrate:5; + u32 apdcfe:1; + u32 qos:1; + u32 hwseq_ssn:1; + u32 userrate:1; + u32 dis_rtsfb:1; + u32 dis_datafb:1; + u32 cts2self:1; + u32 rts_en:1; + u32 hwrts_en:1; + u32 portid:1; + u32 pwr_status:3; + u32 waitdcts:1; + u32 cts2ap_en:1; + u32 txsc:2; + u32 stbc:2; + u32 txshort:1; + u32 txbw:1; + u32 rtsshort:1; + u32 rtsbw:1; + u32 rtssc:2; + u32 rtsstbc:2; + + u32 txrate:6; + u32 shortgi:1; + u32 ccxt:1; + u32 txrate_fb_lmt:5; + u32 rtsrate_fb_lmt:4; + u32 retrylmt_en:1; + u32 txretrylmt:6; + u32 usb_txaggnum:8; + + u32 txagca:5; + u32 txagcb:5; + u32 usemaxlen:1; + u32 maxaggnum:5; + u32 mcsg1maxlen:4; + u32 mcsg2maxlen:4; + u32 mcsg3maxlen:4; + u32 mcs7sgimaxlen:4; + + u32 txbuffersize:16; + u32 sw_offset30:8; + u32 sw_offset31:4; + u32 rsvd1:1; + u32 antsel_c:1; + u32 null_0:1; + u32 null_1:1; + + u32 txbuffaddr; + u32 txbufferaddr64; + u32 nextdescaddress; + u32 nextdescaddress64; + + u32 reserve_pass_pcie_mm_limit[4]; +} __packed; + +struct rx_desc { + u32 length:14; + u32 crc32:1; + u32 icverror:1; + u32 drv_infosize:4; + u32 security:3; + u32 qos:1; + u32 shift:2; + u32 phystatus:1; + u32 swdec:1; + u32 lastseg:1; + u32 firstseg:1; + u32 eor:1; + u32 own:1; + + u32 macid:6; + u32 tid:4; + u32 hwrsvd:5; + u32 paggr:1; + u32 faggr:1; + u32 a1_fit:4; + u32 a2_fit:4; + u32 pam:1; + u32 pwr:1; + u32 moredata:1; + u32 morefrag:1; + u32 type:2; + u32 mc:1; + u32 bc:1; + + u32 seq:12; + u32 frag:4; + u32 nextpktlen:14; + u32 nextind:1; + u32 rsvd:1; + + u32 rxmcs:6; + u32 rxht:1; + u32 amsdu:1; + u32 splcp:1; + u32 bandwidth:1; + u32 htc:1; + u32 tcpchk_rpt:1; + u32 ipcchk_rpt:1; + u32 tcpchk_valid:1; + u32 hwpcerr:1; + u32 hwpcind:1; + u32 iv0:16; + + u32 iv1; + + u32 tsfl; + + u32 bufferaddress; + u32 bufferaddress64; + +} __packed; + +void rtl92ee_rx_check_dma_ok(struct ieee80211_hw *hw, u8 *header_desc, + u8 queue_index); +u16 rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, + u8 queue_index); +u16 rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 queue_index); +void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, + u8 *tx_bd_desc, u8 *desc, u8 queue_index, + struct sk_buff *skb, dma_addr_t addr); + +void rtl92ee_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *pbd_desc_tx, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); +bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *status, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb); +void rtl92ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, + u8 desc_name, u8 *val); + +u32 rtl92ee_get_desc(u8 *pdesc, bool istx, u8 desc_name); +bool rtl92ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index); +void rtl92ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); +void rtl92ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool firstseg, bool lastseg, + struct sk_buff *skb); +u32 rtl92ee_rx_command_packet(struct ieee80211_hw *hw, + struct rtl_stats status, + struct sk_buff *skb); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/Makefile new file mode 100644 index 000000000000..b7eb13819cbc --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/Makefile @@ -0,0 +1,15 @@ +rtl8192se-objs := \ + dm.o \ + fw.o \ + hw.o \ + led.o \ + phy.o \ + rf.o \ + sw.o \ + table.o \ + trx.o + +obj-$(CONFIG_RTL8192SE) += rtl8192se.o + +ccflags-y += -D__CHECK_ENDIAN__ + diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h new file mode 100644 index 000000000000..41466f957cdc --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/def.h @@ -0,0 +1,555 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __REALTEK_92S_DEF_H__ +#define __REALTEK_92S_DEF_H__ + +#define RX_MPDU_QUEUE 0 +#define RX_CMD_QUEUE 1 + +#define SHORT_SLOT_TIME 9 +#define NON_SHORT_SLOT_TIME 20 + +/* Queue Select Value in TxDesc */ +#define QSLT_BK 0x2 +#define QSLT_BE 0x0 +#define QSLT_VI 0x5 +#define QSLT_VO 0x6 +#define QSLT_BEACON 0x10 +#define QSLT_HIGH 0x11 +#define QSLT_MGNT 0x12 +#define QSLT_CMD 0x13 + +/* Tx Desc */ +#define TX_DESC_SIZE_RTL8192S (16 * 4) +#define TX_CMDDESC_SIZE_RTL8192S (16 * 4) + +/* 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, __mask) \ + ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ + BIT_LEN_MASK_32(__mask)) + +/* 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/write various fields in RX or TX descriptors */ + +/* Dword 0 */ +#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val) +#define SET_TX_DESC_OFFSET(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val) +#define SET_TX_DESC_TYPE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 24, 2, __val) +#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) +#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) +#define SET_TX_DESC_LINIP(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) +#define SET_TX_DESC_AMSDU(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) +#define SET_TX_DESC_GREEN_FIELD(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) +#define SET_TX_DESC_OWN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) + +#define GET_TX_DESC_OWN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 31, 1) + +/* Dword 1 */ +#define SET_TX_DESC_MACID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 0, 5, __val) +#define SET_TX_DESC_MORE_DATA(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 5, 1, __val) +#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 6, 1, __val) +#define SET_TX_DESC_PIFS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 7, 1, __val) +#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 8, 5, __val) +#define SET_TX_DESC_ACK_POLICY(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 13, 2, __val) +#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 15, 1, __val) +#define SET_TX_DESC_NON_QOS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 16, 1, __val) +#define SET_TX_DESC_KEY_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 17, 2, __val) +#define SET_TX_DESC_OUI(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 19, 1, __val) +#define SET_TX_DESC_PKT_TYPE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 20, 1, __val) +#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 21, 1, __val) +#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 22, 2, __val) +#define SET_TX_DESC_WDS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 24, 1, __val) +#define SET_TX_DESC_HTC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 25, 1, __val) +#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 26, 5, __val) +#define SET_TX_DESC_HWPC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 27, 1, __val) + +/* Dword 2 */ +#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 0, 6, __val) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 6, 1, __val) +#define SET_TX_DESC_TSFL(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 7, 5, __val) +#define SET_TX_DESC_RTS_RETRY_COUNT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 12, 6, __val) +#define SET_TX_DESC_DATA_RETRY_COUNT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 18, 6, __val) +#define SET_TX_DESC_RSVD_MACID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(((__pdesc) + 8), 24, 5, __val) +#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 29, 1, __val) +#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 30, 1, __val) +#define SET_TX_DESC_OWN_MAC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 31, 1, __val) + +/* Dword 3 */ +#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 0, 8, __val) +#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 8, 8, __val) +#define SET_TX_DESC_SEQ(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 16, 12, __val) +#define SET_TX_DESC_FRAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 28, 4, __val) + +/* Dword 4 */ +#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 0, 6, __val) +#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 6, 1, __val) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 7, 4, __val) +#define SET_TX_DESC_CTS_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 11, 1, __val) +#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 12, 1, __val) +#define SET_TX_DESC_RA_BRSR_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 13, 3, __val) +#define SET_TX_DESC_TXHT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 16, 1, __val) +#define SET_TX_DESC_TX_SHORT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 17, 1, __val) +#define SET_TX_DESC_TX_BANDWIDTH(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 18, 1, __val) +#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 19, 2, __val) +#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 21, 2, __val) +#define SET_TX_DESC_TX_REVERSE_DIRECTION(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 23, 1, __val) +#define SET_TX_DESC_RTS_HT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 24, 1, __val) +#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 25, 1, __val) +#define SET_TX_DESC_RTS_BANDWIDTH(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 26, 1, __val) +#define SET_TX_DESC_RTS_SUB_CARRIER(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 27, 2, __val) +#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 29, 2, __val) +#define SET_TX_DESC_USER_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 31, 1, __val) + +/* Dword 5 */ +#define SET_TX_DESC_PACKET_ID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 20, 0, 9, __val) +#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 20, 9, 6, __val) +#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 20, 15, 1, __val) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 20, 16, 5, __val) +#define SET_TX_DESC_TX_AGC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 20, 21, 11, __val) + +/* Dword 6 */ +#define SET_TX_DESC_IP_CHECK_SUM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 24, 0, 16, __val) +#define SET_TX_DESC_TCP_CHECK_SUM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 24, 16, 16, __val) + +/* Dword 7 */ +#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 28, 0, 16, __val) +#define SET_TX_DESC_IP_HEADER_OFFSET(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 28, 16, 8, __val) +#define SET_TX_DESC_TCP_ENABLE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 28, 31, 1, __val) + +/* Dword 8 */ +#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 32, 0, 32, __val) +#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 32, 0, 32) + +/* Dword 9 */ +#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 36, 0, 32, __val) + +/* Because the PCI Tx descriptors are chaied at the + * initialization and all the NextDescAddresses in + * these descriptors cannot not be cleared (,or + * driver/HW cannot find the next descriptor), the + * offset 36 (NextDescAddresses) is reserved when + * the desc is cleared. */ +#define TX_DESC_NEXT_DESC_OFFSET 36 +#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ + memset(__pdesc, 0, min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) + +/* Rx Desc */ +#define RX_STATUS_DESC_SIZE 24 +#define RX_DRV_INFO_SIZE_UNIT 8 + +/* DWORD 0 */ +#define SET_RX_STATUS_DESC_PKT_LEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val) +#define SET_RX_STATUS_DESC_CRC32(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 14, 1, __val) +#define SET_RX_STATUS_DESC_ICV(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 15, 1, __val) +#define SET_RX_STATUS_DESC_DRVINFO_SIZE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 16, 4, __val) +#define SET_RX_STATUS_DESC_SECURITY(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 20, 3, __val) +#define SET_RX_STATUS_DESC_QOS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 23, 1, __val) +#define SET_RX_STATUS_DESC_SHIFT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 24, 2, __val) +#define SET_RX_STATUS_DESC_PHY_STATUS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) +#define SET_RX_STATUS_DESC_SWDEC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) +#define SET_RX_STATUS_DESC_LAST_SEG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) +#define SET_RX_STATUS_DESC_FIRST_SEG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) +#define SET_RX_STATUS_DESC_EOR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) +#define SET_RX_STATUS_DESC_OWN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) + +#define GET_RX_STATUS_DESC_PKT_LEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 0, 14) +#define GET_RX_STATUS_DESC_CRC32(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 14, 1) +#define GET_RX_STATUS_DESC_ICV(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 15, 1) +#define GET_RX_STATUS_DESC_DRVINFO_SIZE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 16, 4) +#define GET_RX_STATUS_DESC_SECURITY(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 20, 3) +#define GET_RX_STATUS_DESC_QOS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 23, 1) +#define GET_RX_STATUS_DESC_SHIFT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 24, 2) +#define GET_RX_STATUS_DESC_PHY_STATUS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 26, 1) +#define GET_RX_STATUS_DESC_SWDEC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 27, 1) +#define GET_RX_STATUS_DESC_LAST_SEG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 28, 1) +#define GET_RX_STATUS_DESC_FIRST_SEG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 29, 1) +#define GET_RX_STATUS_DESC_EOR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 30, 1) +#define GET_RX_STATUS_DESC_OWN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc, 31, 1) + +/* DWORD 1 */ +#define SET_RX_STATUS_DESC_MACID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 0, 5, __val) +#define SET_RX_STATUS_DESC_TID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 5, 4, __val) +#define SET_RX_STATUS_DESC_PAGGR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 14, 1, __val) +#define SET_RX_STATUS_DESC_FAGGR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 15, 1, __val) +#define SET_RX_STATUS_DESC_A1_FIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 16, 4, __val) +#define SET_RX_STATUS_DESC_A2_FIT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 20, 4, __val) +#define SET_RX_STATUS_DESC_PAM(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 24, 1, __val) +#define SET_RX_STATUS_DESC_PWR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 25, 1, __val) +#define SET_RX_STATUS_DESC_MOREDATA(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 26, 1, __val) +#define SET_RX_STATUS_DESC_MOREFRAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 27, 1, __val) +#define SET_RX_STATUS_DESC_TYPE(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 28, 2, __val) +#define SET_RX_STATUS_DESC_MC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 30, 1, __val) +#define SET_RX_STATUS_DESC_BC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 4, 31, 1, __val) + +#define GET_RX_STATUS_DEC_MACID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 0, 5) +#define GET_RX_STATUS_DESC_TID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 5, 4) +#define GET_RX_STATUS_DESC_PAGGR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 14, 1) +#define GET_RX_STATUS_DESC_FAGGR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 15, 1) +#define GET_RX_STATUS_DESC_A1_FIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 16, 4) +#define GET_RX_STATUS_DESC_A2_FIT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 20, 4) +#define GET_RX_STATUS_DESC_PAM(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 24, 1) +#define GET_RX_STATUS_DESC_PWR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 25, 1) +#define GET_RX_STATUS_DESC_MORE_DATA(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 26, 1) +#define GET_RX_STATUS_DESC_MORE_FRAG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 27, 1) +#define GET_RX_STATUS_DESC_TYPE(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 28, 2) +#define GET_RX_STATUS_DESC_MC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 30, 1) +#define GET_RX_STATUS_DESC_BC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 4, 31, 1) + +/* DWORD 2 */ +#define SET_RX_STATUS_DESC_SEQ(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 0, 12, __val) +#define SET_RX_STATUS_DESC_FRAG(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 12, 4, __val) +#define SET_RX_STATUS_DESC_NEXT_PKTLEN(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 16, 8, __val) +#define SET_RX_STATUS_DESC_NEXT_IND(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 8, 30, 1, __val) + +#define GET_RX_STATUS_DESC_SEQ(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 8, 0, 12) +#define GET_RX_STATUS_DESC_FRAG(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 8, 12, 4) +#define GET_RX_STATUS_DESC_NEXT_PKTLEN(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 8, 16, 8) +#define GET_RX_STATUS_DESC_NEXT_IND(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 8, 30, 1) + +/* DWORD 3 */ +#define SET_RX_STATUS_DESC_RX_MCS(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 0, 6, __val) +#define SET_RX_STATUS_DESC_RX_HT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 6, 1, __val) +#define SET_RX_STATUS_DESC_AMSDU(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 7, 1, __val) +#define SET_RX_STATUS_DESC_SPLCP(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 8, 1, __val) +#define SET_RX_STATUS_DESC_BW(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 9, 1, __val) +#define SET_RX_STATUS_DESC_HTC(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 10, 1, __val) +#define SET_RX_STATUS_DESC_TCP_CHK_RPT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 11, 1, __val) +#define SET_RX_STATUS_DESC_IP_CHK_RPT(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 12, 1, __val) +#define SET_RX_STATUS_DESC_TCP_CHK_VALID(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 13, 1, __val) +#define SET_RX_STATUS_DESC_HWPC_ERR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 14, 1, __val) +#define SET_RX_STATUS_DESC_HWPC_IND(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 15, 1, __val) +#define SET_RX_STATUS_DESC_IV0(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 12, 16, 16, __val) + +#define GET_RX_STATUS_DESC_RX_MCS(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 0, 6) +#define GET_RX_STATUS_DESC_RX_HT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 6, 1) +#define GET_RX_STATUS_DESC_AMSDU(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 7, 1) +#define GET_RX_STATUS_DESC_SPLCP(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 8, 1) +#define GET_RX_STATUS_DESC_BW(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 9, 1) +#define GET_RX_STATUS_DESC_HTC(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 10, 1) +#define GET_RX_STATUS_DESC_TCP_CHK_RPT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 11, 1) +#define GET_RX_STATUS_DESC_IP_CHK_RPT(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 12, 1) +#define GET_RX_STATUS_DESC_TCP_CHK_VALID(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 13, 1) +#define GET_RX_STATUS_DESC_HWPC_ERR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 14, 1) +#define GET_RX_STATUS_DESC_HWPC_IND(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 15, 1) +#define GET_RX_STATUS_DESC_IV0(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 12, 16, 16) + +/* DWORD 4 */ +#define SET_RX_STATUS_DESC_IV1(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 16, 0, 32, __val) +#define GET_RX_STATUS_DESC_IV1(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 16, 0, 32) + +/* DWORD 5 */ +#define SET_RX_STATUS_DESC_TSFL(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 20, 0, 32, __val) +#define GET_RX_STATUS_DESC_TSFL(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 20, 0, 32) + +/* DWORD 6 */ +#define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \ + SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val) +#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc) \ + SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32) + +#define SE_RX_HAL_IS_CCK_RATE(_pdesc)\ + (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC_RATE1M || \ + GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC_RATE2M || \ + GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC_RATE5_5M ||\ + GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC_RATE11M) + +enum rf_optype { + RF_OP_BY_SW_3WIRE = 0, + RF_OP_BY_FW, + RF_OP_MAX +}; + +enum ic_inferiority { + IC_INFERIORITY_A = 0, + IC_INFERIORITY_B = 1, +}; + +enum fwcmd_iotype { + /* For DIG DM */ + FW_CMD_DIG_ENABLE = 0, + FW_CMD_DIG_DISABLE = 1, + FW_CMD_DIG_HALT = 2, + FW_CMD_DIG_RESUME = 3, + /* For High Power DM */ + FW_CMD_HIGH_PWR_ENABLE = 4, + FW_CMD_HIGH_PWR_DISABLE = 5, + /* For Rate adaptive DM */ + FW_CMD_RA_RESET = 6, + FW_CMD_RA_ACTIVE = 7, + FW_CMD_RA_REFRESH_N = 8, + FW_CMD_RA_REFRESH_BG = 9, + FW_CMD_RA_INIT = 10, + /* For FW supported IQK */ + FW_CMD_IQK_INIT = 11, + /* Tx power tracking switch, + * MP driver only */ + FW_CMD_TXPWR_TRACK_ENABLE = 12, + /* Tx power tracking switch, + * MP driver only */ + FW_CMD_TXPWR_TRACK_DISABLE = 13, + /* Tx power tracking with thermal + * indication, for Normal driver */ + FW_CMD_TXPWR_TRACK_THERMAL = 14, + FW_CMD_PAUSE_DM_BY_SCAN = 15, + FW_CMD_RESUME_DM_BY_SCAN = 16, + FW_CMD_RA_REFRESH_N_COMB = 17, + FW_CMD_RA_REFRESH_BG_COMB = 18, + FW_CMD_ANTENNA_SW_ENABLE = 19, + FW_CMD_ANTENNA_SW_DISABLE = 20, + /* Tx Status report for CCX from FW */ + FW_CMD_TX_FEEDBACK_CCX_ENABLE = 21, + /* Indifate firmware that driver + * enters LPS, For PS-Poll issue */ + FW_CMD_LPS_ENTER = 22, + /* Indicate firmware that driver + * leave LPS*/ + FW_CMD_LPS_LEAVE = 23, + /* Set DIG mode to signal strength */ + FW_CMD_DIG_MODE_SS = 24, + /* Set DIG mode to false alarm. */ + FW_CMD_DIG_MODE_FA = 25, + FW_CMD_ADD_A2_ENTRY = 26, + FW_CMD_CTRL_DM_BY_DRIVER = 27, + FW_CMD_CTRL_DM_BY_DRIVER_NEW = 28, + FW_CMD_PAPE_CONTROL = 29, + FW_CMD_IQK_ENABLE = 30, +}; + +/* Driver info contain PHY status + * and other variabel size info + * PHY Status content as below + */ +struct rx_fwinfo { + /* DWORD 0 */ + u8 gain_trsw[4]; + /* DWORD 1 */ + u8 pwdb_all; + u8 cfosho[4]; + /* DWORD 2 */ + u8 cfotail[4]; + /* DWORD 3 */ + s8 rxevm[2]; + s8 rxsnr[4]; + /* DWORD 4 */ + u8 pdsnr[2]; + /* DWORD 5 */ + u8 csi_current[2]; + u8 csi_target[2]; + /* DWORD 6 */ + u8 sigevm; + u8 max_ex_pwr; + u8 ex_intf_flag:1; + u8 sgi_en:1; + u8 rxsc:2; + u8 reserve:4; +}; + +struct phy_sts_cck_8192s_t { + u8 adc_pwdb_x[4]; + u8 sq_rpt; + u8 cck_agc_rpt; +}; + +#endif + diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c new file mode 100644 index 000000000000..9bae5a92e30f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c @@ -0,0 +1,742 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../base.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" + +static const u32 edca_setting_dl[PEER_MAX] = { + 0xa44f, /* 0 UNKNOWN */ + 0x5ea44f, /* 1 REALTEK_90 */ + 0x5ea44f, /* 2 REALTEK_92SE */ + 0xa630, /* 3 BROAD */ + 0xa44f, /* 4 RAL */ + 0xa630, /* 5 ATH */ + 0xa630, /* 6 CISCO */ + 0xa42b, /* 7 MARV */ +}; + +static const u32 edca_setting_dl_gmode[PEER_MAX] = { + 0x4322, /* 0 UNKNOWN */ + 0xa44f, /* 1 REALTEK_90 */ + 0x5ea44f, /* 2 REALTEK_92SE */ + 0xa42b, /* 3 BROAD */ + 0x5e4322, /* 4 RAL */ + 0x4322, /* 5 ATH */ + 0xa430, /* 6 CISCO */ + 0x5ea44f, /* 7 MARV */ +}; + +static const u32 edca_setting_ul[PEER_MAX] = { + 0x5e4322, /* 0 UNKNOWN */ + 0xa44f, /* 1 REALTEK_90 */ + 0x5ea44f, /* 2 REALTEK_92SE */ + 0x5ea322, /* 3 BROAD */ + 0x5ea422, /* 4 RAL */ + 0x5ea322, /* 5 ATH */ + 0x3ea44f, /* 6 CISCO */ + 0x5ea44f, /* 7 MARV */ +}; + +static void _rtl92s_dm_check_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + static u64 last_txok_cnt; + static u64 last_rxok_cnt; + u64 cur_txok_cnt = 0; + u64 cur_rxok_cnt = 0; + + u32 edca_be_ul = edca_setting_ul[mac->vendor]; + u32 edca_be_dl = edca_setting_dl[mac->vendor]; + u32 edca_gmode = edca_setting_dl_gmode[mac->vendor]; + + if (mac->link_state != MAC80211_LINKED) { + rtlpriv->dm.current_turbo_edca = false; + goto dm_checkedcaturbo_exit; + } + + if ((!rtlpriv->dm.is_any_nonbepkts) && + (!rtlpriv->dm.disable_framebursting)) { + cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; + cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; + + if (rtlpriv->phy.rf_type == RF_1T2R) { + if (cur_txok_cnt > 4 * cur_rxok_cnt) { + /* Uplink TP is present. */ + if (rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + rtl_write_dword(rtlpriv, EDCAPARA_BE, + edca_be_ul); + rtlpriv->dm.is_cur_rdlstate = false; + } + } else {/* Balance TP is present. */ + if (!rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + if (mac->mode == WIRELESS_MODE_G || + mac->mode == WIRELESS_MODE_B) + rtl_write_dword(rtlpriv, + EDCAPARA_BE, + edca_gmode); + else + rtl_write_dword(rtlpriv, + EDCAPARA_BE, + edca_be_dl); + rtlpriv->dm.is_cur_rdlstate = true; + } + } + rtlpriv->dm.current_turbo_edca = true; + } else { + if (cur_rxok_cnt > 4 * cur_txok_cnt) { + if (!rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + if (mac->mode == WIRELESS_MODE_G || + mac->mode == WIRELESS_MODE_B) + rtl_write_dword(rtlpriv, + EDCAPARA_BE, + edca_gmode); + else + rtl_write_dword(rtlpriv, + EDCAPARA_BE, + edca_be_dl); + rtlpriv->dm.is_cur_rdlstate = true; + } + } else { + if (rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + rtl_write_dword(rtlpriv, EDCAPARA_BE, + edca_be_ul); + rtlpriv->dm.is_cur_rdlstate = false; + } + } + rtlpriv->dm.current_turbo_edca = true; + } + } else { + if (rtlpriv->dm.current_turbo_edca) { + u8 tmp = AC0_BE; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + &tmp); + rtlpriv->dm.current_turbo_edca = false; + } + } + +dm_checkedcaturbo_exit: + rtlpriv->dm.is_any_nonbepkts = false; + last_txok_cnt = rtlpriv->stats.txbytesunicast; + last_rxok_cnt = rtlpriv->stats.rxbytesunicast; +} + +static void _rtl92s_dm_txpowertracking_callback_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 thermalvalue = 0; + u32 fw_cmd = 0; + + rtlpriv->dm.txpower_trackinginit = true; + + thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermal meter 0x%x\n", + thermalvalue, + rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter); + + if (thermalvalue) { + rtlpriv->dm.thermalvalue = thermalvalue; + if (hal_get_firmwareversion(rtlpriv) >= 0x35) { + rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL); + } else { + fw_cmd = (FW_TXPWR_TRACK_THERMAL | + (rtlpriv->efuse.thermalmeter[0] << 8) | + (thermalvalue << 16)); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Write to FW Thermal Val = 0x%x\n", fw_cmd); + + rtl_write_dword(rtlpriv, WFM5, fw_cmd); + rtl92s_phy_chk_fwcmd_iodone(hw); + } + } + + rtlpriv->dm.txpowercount = 0; +} + +static void _rtl92s_dm_check_txpowertracking_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u8 tx_power_checkcnt = 5; + + /* 2T2R TP issue */ + if (rtlphy->rf_type == RF_2T2R) + return; + + if (!rtlpriv->dm.txpower_tracking) + return; + + if (rtlpriv->dm.txpowercount <= tx_power_checkcnt) { + rtlpriv->dm.txpowercount++; + return; + } + + if (!rtlpriv->dm.tm_trigger) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, + RFREG_OFFSET_MASK, 0x60); + rtlpriv->dm.tm_trigger = 1; + } else { + _rtl92s_dm_txpowertracking_callback_thermalmeter(hw); + rtlpriv->dm.tm_trigger = 0; + } +} + +static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rate_adaptive *ra = &(rtlpriv->ra); + struct ieee80211_sta *sta = NULL; + u32 low_rssi_thresh = 0; + u32 middle_rssi_thresh = 0; + u32 high_rssi_thresh = 0; + + if (is_hal_stop(rtlhal)) + return; + + if (!rtlpriv->dm.useramask) + return; + + if (hal_get_firmwareversion(rtlpriv) >= 61 && + !rtlpriv->dm.inform_fw_driverctrldm) { + rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER); + rtlpriv->dm.inform_fw_driverctrldm = true; + } + + if ((mac->link_state == MAC80211_LINKED) && + (mac->opmode == NL80211_IFTYPE_STATION)) { + switch (ra->pre_ratr_state) { + case DM_RATR_STA_HIGH: + high_rssi_thresh = 40; + middle_rssi_thresh = 30; + low_rssi_thresh = 20; + break; + case DM_RATR_STA_MIDDLE: + high_rssi_thresh = 44; + middle_rssi_thresh = 30; + low_rssi_thresh = 20; + break; + case DM_RATR_STA_LOW: + high_rssi_thresh = 44; + middle_rssi_thresh = 34; + low_rssi_thresh = 20; + break; + case DM_RATR_STA_ULTRALOW: + high_rssi_thresh = 44; + middle_rssi_thresh = 34; + low_rssi_thresh = 24; + break; + default: + high_rssi_thresh = 44; + middle_rssi_thresh = 34; + low_rssi_thresh = 24; + break; + } + + if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) { + ra->ratr_state = DM_RATR_STA_HIGH; + } else if (rtlpriv->dm.undec_sm_pwdb > + (long)middle_rssi_thresh) { + ra->ratr_state = DM_RATR_STA_LOW; + } else if (rtlpriv->dm.undec_sm_pwdb > + (long)low_rssi_thresh) { + ra->ratr_state = DM_RATR_STA_LOW; + } else { + ra->ratr_state = DM_RATR_STA_ULTRALOW; + } + + if (ra->pre_ratr_state != ra->ratr_state) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n", + rtlpriv->dm.undec_sm_pwdb, ra->ratr_state, + ra->pre_ratr_state, ra->ratr_state); + + rcu_read_lock(); + sta = rtl_find_sta(hw, mac->bssid); + if (sta) + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, + ra->ratr_state); + rcu_read_unlock(); + + ra->pre_ratr_state = ra->ratr_state; + } + } +} + +static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + bool current_mrc; + bool enable_mrc = true; + long tmpentry_maxpwdb = 0; + u8 rssi_a = 0; + u8 rssi_b = 0; + + if (is_hal_stop(rtlhal)) + return; + + if ((rtlphy->rf_type == RF_1T1R) || (rtlphy->rf_type == RF_2T2R)) + return; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(¤t_mrc)); + + if (mac->link_state >= MAC80211_LINKED) { + if (rtlpriv->dm.undec_sm_pwdb > tmpentry_maxpwdb) { + rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A]; + rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B]; + } + } + + /* MRC settings would NOT affect TP on Wireless B mode. */ + if (mac->mode != WIRELESS_MODE_B) { + if ((rssi_a == 0) && (rssi_b == 0)) { + enable_mrc = true; + } else if (rssi_b > 30) { + /* Turn on B-Path */ + enable_mrc = true; + } else if (rssi_b < 5) { + /* Turn off B-path */ + enable_mrc = false; + /* Take care of RSSI differentiation. */ + } else if (rssi_a > 15 && (rssi_a >= rssi_b)) { + if ((rssi_a - rssi_b) > 15) + /* Turn off B-path */ + enable_mrc = false; + else if ((rssi_a - rssi_b) < 10) + /* Turn on B-Path */ + enable_mrc = true; + else + enable_mrc = current_mrc; + } else { + /* Turn on B-Path */ + enable_mrc = true; + } + } + + /* Update MRC settings if needed. */ + if (enable_mrc != current_mrc) + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC, + (u8 *)&enable_mrc); + +} + +void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.current_turbo_edca = false; + rtlpriv->dm.is_any_nonbepkts = false; + rtlpriv->dm.is_cur_rdlstate = false; +} + +static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rate_adaptive *ra = &(rtlpriv->ra); + + ra->ratr_state = DM_RATR_STA_MAX; + ra->pre_ratr_state = DM_RATR_STA_MAX; + + if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER && + hal_get_firmwareversion(rtlpriv) >= 60) + rtlpriv->dm.useramask = true; + else + rtlpriv->dm.useramask = false; + + rtlpriv->dm.useramask = false; + rtlpriv->dm.inform_fw_driverctrldm = false; +} + +static void _rtl92s_dm_init_txpowertracking_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.txpower_tracking = true; + rtlpriv->dm.txpowercount = 0; + rtlpriv->dm.txpower_trackinginit = false; +} + +static void _rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); + u32 ret_value; + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); + falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); + falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); + falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); + falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); + + falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail; + + /* read CCK false alarm */ + ret_value = rtl_get_bbreg(hw, 0xc64, MASKDWORD); + falsealm_cnt->cnt_cck_fail = (ret_value & 0xffff); + falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail + + falsealm_cnt->cnt_cck_fail; +} + +static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *digtable = &rtlpriv->dm_digtable; + struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); + + if (falsealm_cnt->cnt_all > digtable->fa_highthresh) { + if ((digtable->back_val - 6) < + digtable->backoffval_range_min) + digtable->back_val = digtable->backoffval_range_min; + else + digtable->back_val -= 6; + } else if (falsealm_cnt->cnt_all < digtable->fa_lowthresh) { + if ((digtable->back_val + 6) > + digtable->backoffval_range_max) + digtable->back_val = + digtable->backoffval_range_max; + else + digtable->back_val += 6; + } +} + +static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *digtable = &rtlpriv->dm_digtable; + struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); + static u8 initialized, force_write; + u8 initial_gain = 0; + + if ((digtable->pre_sta_cstate == digtable->cur_sta_cstate) || + (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT)) { + if (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT) { + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + if (digtable->backoff_enable_flag) + rtl92s_backoff_enable_flag(hw); + else + digtable->back_val = DM_DIG_BACKOFF_MAX; + + if ((digtable->rssi_val + 10 - digtable->back_val) > + digtable->rx_gain_max) + digtable->cur_igvalue = + digtable->rx_gain_max; + else if ((digtable->rssi_val + 10 - digtable->back_val) + < digtable->rx_gain_min) + digtable->cur_igvalue = + digtable->rx_gain_min; + else + digtable->cur_igvalue = digtable->rssi_val + 10 + - digtable->back_val; + + if (falsealm_cnt->cnt_all > 10000) + digtable->cur_igvalue = + (digtable->cur_igvalue > 0x33) ? + digtable->cur_igvalue : 0x33; + + if (falsealm_cnt->cnt_all > 16000) + digtable->cur_igvalue = + digtable->rx_gain_max; + /* connected -> connected or disconnected -> disconnected */ + } else { + /* Firmware control DIG, do nothing in driver dm */ + return; + } + /* disconnected -> connected or connected -> + * disconnected or beforeconnect->(dis)connected */ + } else { + /* Enable FW DIG */ + digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; + rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE); + + digtable->back_val = DM_DIG_BACKOFF_MAX; + digtable->cur_igvalue = rtlpriv->phy.default_initialgain[0]; + digtable->pre_igvalue = 0; + return; + } + + /* Forced writing to prevent from fw-dig overwriting. */ + if (digtable->pre_igvalue != rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, + MASKBYTE0)) + force_write = 1; + + if ((digtable->pre_igvalue != digtable->cur_igvalue) || + !initialized || force_write) { + /* Disable FW DIG */ + rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_DISABLE); + + initial_gain = (u8)digtable->cur_igvalue; + + /* Set initial gain. */ + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, initial_gain); + rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, initial_gain); + digtable->pre_igvalue = digtable->cur_igvalue; + initialized = 1; + force_write = 0; + } +} + +static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dig = &rtlpriv->dm_digtable; + + if (rtlpriv->mac80211.act_scanning) + return; + + /* Decide the current status and if modify initial gain or not */ + if (rtlpriv->mac80211.link_state >= MAC80211_LINKED || + rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) + dig->cur_sta_cstate = DIG_STA_CONNECT; + else + dig->cur_sta_cstate = DIG_STA_DISCONNECT; + + dig->rssi_val = rtlpriv->dm.undec_sm_pwdb; + + /* Change dig mode to rssi */ + if (dig->cur_sta_cstate != DIG_STA_DISCONNECT) { + if (dig->dig_twoport_algorithm == + DIG_TWO_PORT_ALGO_FALSE_ALARM) { + dig->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; + rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS); + } + } + + _rtl92s_dm_false_alarm_counter_statistics(hw); + _rtl92s_dm_initial_gain_sta_beforeconnect(hw); + + dig->pre_sta_cstate = dig->cur_sta_cstate; +} + +static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct dig_t *digtable = &rtlpriv->dm_digtable; + + /* 2T2R TP issue */ + if (rtlphy->rf_type == RF_2T2R) + return; + + if (!rtlpriv->dm.dm_initialgain_enable) + return; + + if (digtable->dig_enable_flag == false) + return; + + _rtl92s_dm_ctrl_initgain_bytwoport(hw); +} + +static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undec_sm_pwdb; + long txpwr_threshold_lv1, txpwr_threshold_lv2; + + /* 2T2R TP issue */ + if (rtlphy->rf_type == RF_2T2R) + return; + + if (!rtlpriv->dm.dynamic_txpower_enable || + rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; + return; + } + + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "Not connected to any\n"); + + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; + + rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; + return; + } + + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Client PWDB = 0x%lx\n", + undec_sm_pwdb); + } else { + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "STA Default Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + } else { + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Ext Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + + txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2; + txpwr_threshold_lv1 = TX_POWER_NEAR_FIELD_THRESH_LVL1; + + if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1) + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; + else if (undec_sm_pwdb >= txpwr_threshold_lv2) + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2; + else if ((undec_sm_pwdb < (txpwr_threshold_lv2 - 3)) && + (undec_sm_pwdb >= txpwr_threshold_lv1)) + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1; + else if (undec_sm_pwdb < (txpwr_threshold_lv1 - 3)) + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; + + if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) + rtl92s_phy_set_txpower(hw, rtlphy->current_channel); + + rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; +} + +static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *digtable = &rtlpriv->dm_digtable; + + /* Disable DIG scheme now.*/ + digtable->dig_enable_flag = true; + digtable->backoff_enable_flag = true; + + if ((rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) && + (hal_get_firmwareversion(rtlpriv) >= 0x3c)) + digtable->dig_algorithm = DIG_ALGO_BY_TOW_PORT; + else + digtable->dig_algorithm = + DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM; + + digtable->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; + digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; + /* off=by real rssi value, on=by digtable->rssi_val for new dig */ + digtable->dig_dbgmode = DM_DBG_OFF; + digtable->dig_slgorithm_switch = 0; + + /* 2007/10/04 MH Define init gain threshol. */ + digtable->dig_state = DM_STA_DIG_MAX; + digtable->dig_highpwrstate = DM_STA_DIG_MAX; + + digtable->cur_sta_cstate = DIG_STA_DISCONNECT; + digtable->pre_sta_cstate = DIG_STA_DISCONNECT; + digtable->cur_ap_cstate = DIG_AP_DISCONNECT; + digtable->pre_ap_cstate = DIG_AP_DISCONNECT; + + digtable->rssi_lowthresh = DM_DIG_THRESH_LOW; + digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; + + digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; + digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; + + digtable->rssi_highpower_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW; + digtable->rssi_highpower_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH; + + /* for dig debug rssi value */ + digtable->rssi_val = 50; + digtable->back_val = DM_DIG_BACKOFF_MAX; + digtable->rx_gain_max = DM_DIG_MAX; + + digtable->rx_gain_min = DM_DIG_MIN; + + digtable->backoffval_range_max = DM_DIG_BACKOFF_MAX; + digtable->backoffval_range_min = DM_DIG_BACKOFF_MIN; +} + +static void _rtl92s_dm_init_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if ((hal_get_firmwareversion(rtlpriv) >= 60) && + (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)) + rtlpriv->dm.dynamic_txpower_enable = true; + else + rtlpriv->dm.dynamic_txpower_enable = false; + + rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; + rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; +} + +void rtl92s_dm_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; + rtlpriv->dm.undec_sm_pwdb = -1; + + _rtl92s_dm_init_dynamic_txpower(hw); + rtl92s_dm_init_edca_turbo(hw); + _rtl92s_dm_init_rate_adaptive_mask(hw); + _rtl92s_dm_init_txpowertracking_thermalmeter(hw); + _rtl92s_dm_init_dig(hw); + + rtl_write_dword(rtlpriv, WFM5, FW_CCA_CHK_ENABLE); +} + +void rtl92s_dm_watchdog(struct ieee80211_hw *hw) +{ + _rtl92s_dm_check_edca_turbo(hw); + _rtl92s_dm_check_txpowertracking_thermalmeter(hw); + _rtl92s_dm_ctrl_initgain_byrssi(hw); + _rtl92s_dm_dynamic_txpower(hw); + _rtl92s_dm_refresh_rateadaptive_mask(hw); + _rtl92s_dm_switch_baseband_mrc(hw); +} + diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h new file mode 100644 index 000000000000..de6ac796c74d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __RTL_92S_DM_H__ +#define __RTL_92S_DM_H__ + +enum dm_dig_alg { + DIG_ALGO_BY_FALSE_ALARM = 0, + DIG_ALGO_BY_RSSI = 1, + DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM = 2, + DIG_ALGO_BY_TOW_PORT = 3, + DIG_ALGO_MAX +}; + +enum dm_dig_two_port_alg { + DIG_TWO_PORT_ALGO_RSSI = 0, + DIG_TWO_PORT_ALGO_FALSE_ALARM = 1, +}; + +enum dm_dig_dbg { + DM_DBG_OFF = 0, + DM_DBG_ON = 1, + DM_DBG_MAX +}; + +enum dm_dig_sta { + DM_STA_DIG_OFF = 0, + DM_STA_DIG_ON, + DM_STA_DIG_MAX +}; + +enum dm_ratr_sta { + DM_RATR_STA_HIGH = 0, + DM_RATR_STA_MIDDLEHIGH = 1, + DM_RATR_STA_MIDDLE = 2, + DM_RATR_STA_MIDDLELOW = 3, + DM_RATR_STA_LOW = 4, + DM_RATR_STA_ULTRALOW = 5, + DM_RATR_STA_MAX +}; + +#define DM_TYPE_BYFW 0 +#define DM_TYPE_BYDRIVER 1 + +#define TX_HIGH_PWR_LEVEL_NORMAL 0 +#define TX_HIGH_PWR_LEVEL_LEVEL1 1 +#define TX_HIGH_PWR_LEVEL_LEVEL2 2 + +#define HAL_DM_DIG_DISABLE BIT(0) /* Disable Dig */ +#define HAL_DM_HIPWR_DISABLE BIT(1) /* Disable High Power */ + +#define TX_HIGHPWR_LEVEL_NORMAL 0 +#define TX_HIGHPWR_LEVEL_NORMAL1 1 +#define TX_HIGHPWR_LEVEL_NORMAL2 2 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 + +#define DM_DIG_HIGH_PWR_THRESH_HIGH 75 +#define DM_DIG_HIGH_PWR_THRESH_LOW 70 +#define DM_DIG_MIN_Netcore 0x12 + +void rtl92s_dm_watchdog(struct ieee80211_hw *hw); +void rtl92s_dm_init(struct ieee80211_hw *hw); +void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c new file mode 100644 index 000000000000..331b1584a1a2 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c @@ -0,0 +1,652 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "fw.h" + +static void _rtl92s_fw_set_rqpn(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_dword(rtlpriv, RQPN, 0xffffffff); + rtl_write_dword(rtlpriv, RQPN + 4, 0xffffffff); + rtl_write_byte(rtlpriv, RQPN + 8, 0xff); + rtl_write_byte(rtlpriv, RQPN + 0xB, 0x80); +} + +static bool _rtl92s_firmware_enable_cpu(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 ichecktime = 200; + u16 tmpu2b; + u8 tmpu1b, cpustatus = 0; + + _rtl92s_fw_set_rqpn(hw); + + /* Enable CPU. */ + tmpu1b = rtl_read_byte(rtlpriv, SYS_CLKR); + /* AFE source */ + rtl_write_byte(rtlpriv, SYS_CLKR, (tmpu1b | SYS_CPU_CLKSEL)); + + tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | FEN_CPUEN)); + + /* Polling IMEM Ready after CPU has refilled. */ + do { + cpustatus = rtl_read_byte(rtlpriv, TCR); + if (cpustatus & IMEM_RDY) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "IMEM Ready after CPU has refilled\n"); + break; + } + + udelay(100); + } while (ichecktime--); + + if (!(cpustatus & IMEM_RDY)) + return false; + + return true; +} + +static enum fw_status _rtl92s_firmware_get_nextstatus( + enum fw_status fw_currentstatus) +{ + enum fw_status next_fwstatus = 0; + + switch (fw_currentstatus) { + case FW_STATUS_INIT: + next_fwstatus = FW_STATUS_LOAD_IMEM; + break; + case FW_STATUS_LOAD_IMEM: + next_fwstatus = FW_STATUS_LOAD_EMEM; + break; + case FW_STATUS_LOAD_EMEM: + next_fwstatus = FW_STATUS_LOAD_DMEM; + break; + case FW_STATUS_LOAD_DMEM: + next_fwstatus = FW_STATUS_READY; + break; + default: + break; + } + + return next_fwstatus; +} + +static u8 _rtl92s_firmware_header_map_rftype(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + switch (rtlphy->rf_type) { + case RF_1T1R: + return 0x11; + case RF_1T2R: + return 0x12; + case RF_2T2R: + return 0x22; + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Unknown RF type(%x)\n", + rtlphy->rf_type); + break; + } + return 0x22; +} + +static void _rtl92s_firmwareheader_priveupdate(struct ieee80211_hw *hw, + struct fw_priv *pfw_priv) +{ + /* Update RF types for RATR settings. */ + pfw_priv->rf_config = _rtl92s_firmware_header_map_rftype(hw); +} + + + +static bool _rtl92s_cmd_send_packet(struct ieee80211_hw *hw, + struct sk_buff *skb, u8 last) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + struct rtl_tx_desc *pdesc; + unsigned long flags; + u8 idx = 0; + + ring = &rtlpci->tx_ring[TXCMD_QUEUE]; + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + + idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; + pdesc = &ring->desc[idx]; + rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); + __skb_queue_tail(&ring->queue, skb); + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + + return true; +} + +static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw, + u8 *code_virtual_address, u32 buffer_len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct sk_buff *skb; + struct rtl_tcb_desc *tcb_desc; + unsigned char *seg_ptr; + u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE; + u16 frag_length, frag_offset = 0; + u16 extra_descoffset = 0; + u8 last_inipkt = 0; + + _rtl92s_fw_set_rqpn(hw); + + if (buffer_len >= MAX_FIRMWARE_CODE_SIZE) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Size over FIRMWARE_CODE_SIZE!\n"); + + return false; + } + + extra_descoffset = 0; + + do { + if ((buffer_len - frag_offset) > frag_threshold) { + frag_length = frag_threshold + extra_descoffset; + } else { + frag_length = (u16)(buffer_len - frag_offset + + extra_descoffset); + last_inipkt = 1; + } + + /* Allocate skb buffer to contain firmware */ + /* info and tx descriptor info. */ + skb = dev_alloc_skb(frag_length); + if (!skb) + return false; + skb_reserve(skb, extra_descoffset); + seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length - + extra_descoffset)); + memcpy(seg_ptr, code_virtual_address + frag_offset, + (u32)(frag_length - extra_descoffset)); + + tcb_desc = (struct rtl_tcb_desc *)(skb->cb); + tcb_desc->queue_index = TXCMD_QUEUE; + tcb_desc->cmd_or_init = DESC_PACKET_TYPE_INIT; + tcb_desc->last_inipkt = last_inipkt; + + _rtl92s_cmd_send_packet(hw, skb, last_inipkt); + + frag_offset += (frag_length - extra_descoffset); + + } while (frag_offset < buffer_len); + + rtl_write_byte(rtlpriv, TP_POLL, TPPOLL_CQ); + + return true ; +} + +static bool _rtl92s_firmware_checkready(struct ieee80211_hw *hw, + u8 loadfw_status) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rt_firmware *firmware = (struct rt_firmware *)rtlhal->pfirmware; + u32 tmpu4b; + u8 cpustatus = 0; + short pollingcnt = 1000; + bool rtstatus = true; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "LoadStaus(%d)\n", loadfw_status); + + firmware->fwstatus = (enum fw_status)loadfw_status; + + switch (loadfw_status) { + case FW_STATUS_LOAD_IMEM: + /* Polling IMEM code done. */ + do { + cpustatus = rtl_read_byte(rtlpriv, TCR); + if (cpustatus & IMEM_CODE_DONE) + break; + udelay(5); + } while (pollingcnt--); + + if (!(cpustatus & IMEM_CHK_RPT) || (pollingcnt <= 0)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\n", + cpustatus); + goto status_check_fail; + } + break; + + case FW_STATUS_LOAD_EMEM: + /* Check Put Code OK and Turn On CPU */ + /* Polling EMEM code done. */ + do { + cpustatus = rtl_read_byte(rtlpriv, TCR); + if (cpustatus & EMEM_CODE_DONE) + break; + udelay(5); + } while (pollingcnt--); + + if (!(cpustatus & EMEM_CHK_RPT) || (pollingcnt <= 0)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\n", + cpustatus); + goto status_check_fail; + } + + /* Turn On CPU */ + rtstatus = _rtl92s_firmware_enable_cpu(hw); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Enable CPU fail!\n"); + goto status_check_fail; + } + break; + + case FW_STATUS_LOAD_DMEM: + /* Polling DMEM code done */ + do { + cpustatus = rtl_read_byte(rtlpriv, TCR); + if (cpustatus & DMEM_CODE_DONE) + break; + udelay(5); + } while (pollingcnt--); + + if (!(cpustatus & DMEM_CODE_DONE) || (pollingcnt <= 0)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Polling DMEM code done fail ! cpustatus(%#x)\n", + cpustatus); + goto status_check_fail; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "DMEM code download success, cpustatus(%#x)\n", + cpustatus); + + /* Prevent Delay too much and being scheduled out */ + /* Polling Load Firmware ready */ + pollingcnt = 2000; + do { + cpustatus = rtl_read_byte(rtlpriv, TCR); + if (cpustatus & FWRDY) + break; + udelay(40); + } while (pollingcnt--); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Polling Load Firmware ready, cpustatus(%x)\n", + cpustatus); + + if (((cpustatus & LOAD_FW_READY) != LOAD_FW_READY) || + (pollingcnt <= 0)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Polling Load Firmware ready fail ! cpustatus(%x)\n", + cpustatus); + goto status_check_fail; + } + + /* If right here, we can set TCR/RCR to desired value */ + /* and config MAC lookback mode to normal mode */ + tmpu4b = rtl_read_dword(rtlpriv, TCR); + rtl_write_dword(rtlpriv, TCR, (tmpu4b & (~TCR_ICV))); + + tmpu4b = rtl_read_dword(rtlpriv, RCR); + rtl_write_dword(rtlpriv, RCR, (tmpu4b | RCR_APPFCS | + RCR_APP_ICV | RCR_APP_MIC)); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Current RCR settings(%#x)\n", tmpu4b); + + /* Set to normal mode. */ + rtl_write_byte(rtlpriv, LBKMD_SEL, LBK_NORMAL); + break; + + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + "Unknown status check!\n"); + rtstatus = false; + break; + } + +status_check_fail: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "loadfw_status(%d), rtstatus(%x)\n", + loadfw_status, rtstatus); + return rtstatus; +} + +int rtl92s_download_fw(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rt_firmware *firmware = NULL; + struct fw_hdr *pfwheader; + struct fw_priv *pfw_priv = NULL; + u8 *puc_mappedfile = NULL; + u32 ul_filelength = 0; + u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE; + u8 fwstatus = FW_STATUS_INIT; + bool rtstatus = true; + + if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) + return 1; + + firmware = (struct rt_firmware *)rtlhal->pfirmware; + firmware->fwstatus = FW_STATUS_INIT; + + puc_mappedfile = firmware->sz_fw_tmpbuffer; + + /* 1. Retrieve FW header. */ + firmware->pfwheader = (struct fw_hdr *) puc_mappedfile; + pfwheader = firmware->pfwheader; + firmware->firmwareversion = byte(pfwheader->version, 0); + firmware->pfwheader->fwpriv.hci_sel = 1;/* pcie */ + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", + pfwheader->signature, + pfwheader->version, pfwheader->dmem_size, + pfwheader->img_imem_size, pfwheader->img_sram_size); + + /* 2. Retrieve IMEM image. */ + if ((pfwheader->img_imem_size == 0) || (pfwheader->img_imem_size > + sizeof(firmware->fw_imem))) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "memory for data image is less than IMEM required\n"); + goto fail; + } else { + puc_mappedfile += fwhdr_size; + + memcpy(firmware->fw_imem, puc_mappedfile, + pfwheader->img_imem_size); + firmware->fw_imem_len = pfwheader->img_imem_size; + } + + /* 3. Retriecve EMEM image. */ + if (pfwheader->img_sram_size > sizeof(firmware->fw_emem)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "memory for data image is less than EMEM required\n"); + goto fail; + } else { + puc_mappedfile += firmware->fw_imem_len; + + memcpy(firmware->fw_emem, puc_mappedfile, + pfwheader->img_sram_size); + firmware->fw_emem_len = pfwheader->img_sram_size; + } + + /* 4. download fw now */ + fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus); + while (fwstatus != FW_STATUS_READY) { + /* Image buffer redirection. */ + switch (fwstatus) { + case FW_STATUS_LOAD_IMEM: + puc_mappedfile = firmware->fw_imem; + ul_filelength = firmware->fw_imem_len; + break; + case FW_STATUS_LOAD_EMEM: + puc_mappedfile = firmware->fw_emem; + ul_filelength = firmware->fw_emem_len; + break; + case FW_STATUS_LOAD_DMEM: + /* Partial update the content of header private. */ + pfwheader = firmware->pfwheader; + pfw_priv = &pfwheader->fwpriv; + _rtl92s_firmwareheader_priveupdate(hw, pfw_priv); + puc_mappedfile = (u8 *)(firmware->pfwheader) + + RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; + ul_filelength = fwhdr_size - + RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Unexpected Download step!!\n"); + goto fail; + } + + /* <2> Download image file */ + rtstatus = _rtl92s_firmware_downloadcode(hw, puc_mappedfile, + ul_filelength); + + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "fail!\n"); + goto fail; + } + + /* <3> Check whether load FW process is ready */ + rtstatus = _rtl92s_firmware_checkready(hw, fwstatus); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "fail!\n"); + goto fail; + } + + fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus); + } + + return rtstatus; +fail: + return 0; +} + +static u32 _rtl92s_fill_h2c_cmd(struct sk_buff *skb, u32 h2cbufferlen, + u32 cmd_num, u32 *pelement_id, u32 *pcmd_len, + u8 **pcmb_buffer, u8 *cmd_start_seq) +{ + u32 totallen = 0, len = 0, tx_desclen = 0; + u32 pre_continueoffset = 0; + u8 *ph2c_buffer; + u8 i = 0; + + do { + /* 8 - Byte aligment */ + len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); + + /* Buffer length is not enough */ + if (h2cbufferlen < totallen + len + tx_desclen) + break; + + /* Clear content */ + ph2c_buffer = (u8 *)skb_put(skb, (u32)len); + memset((ph2c_buffer + totallen + tx_desclen), 0, len); + + /* CMD len */ + SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), + 0, 16, pcmd_len[i]); + + /* CMD ID */ + SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), + 16, 8, pelement_id[i]); + + /* CMD Sequence */ + *cmd_start_seq = *cmd_start_seq % 0x80; + SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), + 24, 7, *cmd_start_seq); + ++*cmd_start_seq; + + /* Copy memory */ + memcpy((ph2c_buffer + totallen + tx_desclen + + H2C_TX_CMD_HDR_LEN), pcmb_buffer[i], pcmd_len[i]); + + /* CMD continue */ + /* set the continue in prevoius cmd. */ + if (i < cmd_num - 1) + SET_BITS_TO_LE_4BYTE((ph2c_buffer + pre_continueoffset), + 31, 1, 1); + + pre_continueoffset = totallen; + + totallen += len; + } while (++i < cmd_num); + + return totallen; +} + +static u32 _rtl92s_get_h2c_cmdlen(u32 h2cbufferlen, u32 cmd_num, u32 *pcmd_len) +{ + u32 totallen = 0, len = 0, tx_desclen = 0; + u8 i = 0; + + do { + /* 8 - Byte aligment */ + len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); + + /* Buffer length is not enough */ + if (h2cbufferlen < totallen + len + tx_desclen) + break; + + totallen += len; + } while (++i < cmd_num); + + return totallen + tx_desclen; +} + +static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd, + u8 *pcmd_buffer) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_tcb_desc *cb_desc; + struct sk_buff *skb; + u32 element_id = 0; + u32 cmd_len = 0; + u32 len; + + switch (h2c_cmd) { + case FW_H2C_SETPWRMODE: + element_id = H2C_SETPWRMODE_CMD ; + cmd_len = sizeof(struct h2c_set_pwrmode_parm); + break; + case FW_H2C_JOINBSSRPT: + element_id = H2C_JOINBSSRPT_CMD; + cmd_len = sizeof(struct h2c_joinbss_rpt_parm); + break; + case FW_H2C_WOWLAN_UPDATE_GTK: + element_id = H2C_WOWLAN_UPDATE_GTK_CMD; + cmd_len = sizeof(struct h2c_wpa_two_way_parm); + break; + case FW_H2C_WOWLAN_UPDATE_IV: + element_id = H2C_WOWLAN_UPDATE_IV_CMD; + cmd_len = sizeof(unsigned long long); + break; + case FW_H2C_WOWLAN_OFFLOAD: + element_id = H2C_WOWLAN_FW_OFFLOAD; + cmd_len = sizeof(u8); + break; + default: + break; + } + + len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len); + skb = dev_alloc_skb(len); + if (!skb) + return false; + cb_desc = (struct rtl_tcb_desc *)(skb->cb); + cb_desc->queue_index = TXCMD_QUEUE; + cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL; + cb_desc->last_inipkt = false; + + _rtl92s_fill_h2c_cmd(skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &element_id, + &cmd_len, &pcmd_buffer, &rtlhal->h2c_txcmd_seq); + _rtl92s_cmd_send_packet(hw, skb, false); + rtlpriv->cfg->ops->tx_polling(hw, TXCMD_QUEUE); + + return true; +} + +void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 Mode) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct h2c_set_pwrmode_parm pwrmode; + u16 max_wakeup_period = 0; + + pwrmode.mode = Mode; + pwrmode.flag_low_traffic_en = 0; + pwrmode.flag_lpnav_en = 0; + pwrmode.flag_rf_low_snr_en = 0; + pwrmode.flag_dps_en = 0; + pwrmode.bcn_rx_en = 0; + pwrmode.bcn_to = 0; + SET_BITS_TO_LE_2BYTE((u8 *)(&pwrmode) + 8, 0, 16, + mac->vif->bss_conf.beacon_int); + pwrmode.app_itv = 0; + pwrmode.awake_bcn_itvl = ppsc->reg_max_lps_awakeintvl; + pwrmode.smart_ps = 1; + pwrmode.bcn_pass_period = 10; + + /* Set beacon pass count */ + if (pwrmode.mode == FW_PS_MIN_MODE) + max_wakeup_period = mac->vif->bss_conf.beacon_int; + else if (pwrmode.mode == FW_PS_MAX_MODE) + max_wakeup_period = mac->vif->bss_conf.beacon_int * + mac->vif->bss_conf.dtim_period; + + if (max_wakeup_period >= 500) + pwrmode.bcn_pass_cnt = 1; + else if ((max_wakeup_period >= 300) && (max_wakeup_period < 500)) + pwrmode.bcn_pass_cnt = 2; + else if ((max_wakeup_period >= 200) && (max_wakeup_period < 300)) + pwrmode.bcn_pass_cnt = 3; + else if ((max_wakeup_period >= 20) && (max_wakeup_period < 200)) + pwrmode.bcn_pass_cnt = 5; + else + pwrmode.bcn_pass_cnt = 1; + + _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_SETPWRMODE, (u8 *)&pwrmode); + +} + +void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, + u8 mstatus, u8 ps_qosinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct h2c_joinbss_rpt_parm joinbss_rpt; + + joinbss_rpt.opmode = mstatus; + joinbss_rpt.ps_qos_info = ps_qosinfo; + joinbss_rpt.bssid[0] = mac->bssid[0]; + joinbss_rpt.bssid[1] = mac->bssid[1]; + joinbss_rpt.bssid[2] = mac->bssid[2]; + joinbss_rpt.bssid[3] = mac->bssid[3]; + joinbss_rpt.bssid[4] = mac->bssid[4]; + joinbss_rpt.bssid[5] = mac->bssid[5]; + SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 8, 0, 16, + mac->vif->bss_conf.beacon_int); + SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 10, 0, 16, mac->assoc_id); + + _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_JOINBSSRPT, (u8 *)&joinbss_rpt); +} + diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h new file mode 100644 index 000000000000..b1e44b86e8ed --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.h @@ -0,0 +1,375 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __REALTEK_FIRMWARE92S_H__ +#define __REALTEK_FIRMWARE92S_H__ + +#define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000 +#define RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE 90000 +#define RTL8190_CPU_START_OFFSET 0x80 +/* Firmware Local buffer size. 64k */ +#define MAX_FIRMWARE_CODE_SIZE 0xFF00 + +#define RT_8192S_FIRMWARE_HDR_SIZE 80 +#define RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE 32 + +/* support till 64 bit bus width OS */ +#define MAX_DEV_ADDR_SIZE 8 +#define MAX_FIRMWARE_INFORMATION_SIZE 32 +#define MAX_802_11_HEADER_LENGTH (40 + \ + MAX_FIRMWARE_INFORMATION_SIZE) +#define ENCRYPTION_MAX_OVERHEAD 128 +#define MAX_FRAGMENT_COUNT 8 +#define MAX_TRANSMIT_BUFFER_SIZE (1600 + \ + (MAX_802_11_HEADER_LENGTH + \ + ENCRYPTION_MAX_OVERHEAD) *\ + MAX_FRAGMENT_COUNT) + +#define H2C_TX_CMD_HDR_LEN 8 + +/* The following DM control code are for Reg0x364, */ +#define FW_DIG_ENABLE_CTL BIT(0) +#define FW_HIGH_PWR_ENABLE_CTL BIT(1) +#define FW_SS_CTL BIT(2) +#define FW_RA_INIT_CTL BIT(3) +#define FW_RA_BG_CTL BIT(4) +#define FW_RA_N_CTL BIT(5) +#define FW_PWR_TRK_CTL BIT(6) +#define FW_IQK_CTL BIT(7) +#define FW_FA_CTL BIT(8) +#define FW_DRIVER_CTRL_DM_CTL BIT(9) +#define FW_PAPE_CTL_BY_SW_HW BIT(10) +#define FW_DISABLE_ALL_DM 0 +#define FW_PWR_TRK_PARAM_CLR 0x0000ffff +#define FW_RA_PARAM_CLR 0xffff0000 + +enum desc_packet_type { + DESC_PACKET_TYPE_INIT = 0, + DESC_PACKET_TYPE_NORMAL = 1, +}; + +/* 8-bytes alignment required */ +struct fw_priv { + /* --- long word 0 ---- */ + /* 0x12: CE product, 0x92: IT product */ + u8 signature_0; + /* 0x87: CE product, 0x81: IT product */ + u8 signature_1; + /* 0x81: PCI-AP, 01:PCIe, 02: 92S-U, + * 0x82: USB-AP, 0x12: 72S-U, 03:SDIO */ + u8 hci_sel; + /* the same value as reigster value */ + u8 chip_version; + /* customer ID low byte */ + u8 customer_id_0; + /* customer ID high byte */ + u8 customer_id_1; + /* 0x11: 1T1R, 0x12: 1T2R, + * 0x92: 1T2R turbo, 0x22: 2T2R */ + u8 rf_config; + /* 4: 4EP, 6: 6EP, 11: 11EP */ + u8 usb_ep_num; + + /* --- long word 1 ---- */ + /* regulatory class bit map 0 */ + u8 regulatory_class_0; + /* regulatory class bit map 1 */ + u8 regulatory_class_1; + /* regulatory class bit map 2 */ + u8 regulatory_class_2; + /* regulatory class bit map 3 */ + u8 regulatory_class_3; + /* 0:SWSI, 1:HWSI, 2:HWPI */ + u8 rfintfs; + u8 def_nettype; + u8 rsvd010; + u8 rsvd011; + + /* --- long word 2 ---- */ + /* 0x00: normal, 0x03: MACLBK, 0x01: PHYLBK */ + u8 lbk_mode; + /* 1: for MP use, 0: for normal + * driver (to be discussed) */ + u8 mp_mode; + u8 rsvd020; + u8 rsvd021; + u8 rsvd022; + u8 rsvd023; + u8 rsvd024; + u8 rsvd025; + + /* --- long word 3 ---- */ + /* QoS enable */ + u8 qos_en; + /* 40MHz BW enable */ + /* 4181 convert AMSDU to AMPDU, 0: disable */ + u8 bw_40mhz_en; + u8 amsdu2ampdu_en; + /* 11n AMPDU enable */ + u8 ampdu_en; + /* FW offloads, 0: driver handles */ + u8 rate_control_offload; + /* FW offloads, 0: driver handles */ + u8 aggregation_offload; + u8 rsvd030; + u8 rsvd031; + + /* --- long word 4 ---- */ + /* 1. FW offloads, 0: driver handles */ + u8 beacon_offload; + /* 2. FW offloads, 0: driver handles */ + u8 mlme_offload; + /* 3. FW offloads, 0: driver handles */ + u8 hwpc_offload; + /* 4. FW offloads, 0: driver handles */ + u8 tcp_checksum_offload; + /* 5. FW offloads, 0: driver handles */ + u8 tcp_offload; + /* 6. FW offloads, 0: driver handles */ + u8 ps_control_offload; + /* 7. FW offloads, 0: driver handles */ + u8 wwlan_offload; + u8 rsvd040; + + /* --- long word 5 ---- */ + /* tcp tx packet length low byte */ + u8 tcp_tx_frame_len_L; + /* tcp tx packet length high byte */ + u8 tcp_tx_frame_len_H; + /* tcp rx packet length low byte */ + u8 tcp_rx_frame_len_L; + /* tcp rx packet length high byte */ + u8 tcp_rx_frame_len_H; + u8 rsvd050; + u8 rsvd051; + u8 rsvd052; + u8 rsvd053; +}; + +/* 8-byte alinment required */ +struct fw_hdr { + + /* --- LONG WORD 0 ---- */ + u16 signature; + /* 0x8000 ~ 0x8FFF for FPGA version, + * 0x0000 ~ 0x7FFF for ASIC version, */ + u16 version; + /* define the size of boot loader */ + u32 dmem_size; + + + /* --- LONG WORD 1 ---- */ + /* define the size of FW in IMEM */ + u32 img_imem_size; + /* define the size of FW in SRAM */ + u32 img_sram_size; + + /* --- LONG WORD 2 ---- */ + /* define the size of DMEM variable */ + u32 fw_priv_size; + u32 rsvd0; + + /* --- LONG WORD 3 ---- */ + u32 rsvd1; + u32 rsvd2; + + struct fw_priv fwpriv; + +} ; + +enum fw_status { + FW_STATUS_INIT = 0, + FW_STATUS_LOAD_IMEM = 1, + FW_STATUS_LOAD_EMEM = 2, + FW_STATUS_LOAD_DMEM = 3, + FW_STATUS_READY = 4, +}; + +struct rt_firmware { + struct fw_hdr *pfwheader; + enum fw_status fwstatus; + u16 firmwareversion; + u8 fw_imem[RTL8190_MAX_FIRMWARE_CODE_SIZE]; + u8 fw_emem[RTL8190_MAX_FIRMWARE_CODE_SIZE]; + u32 fw_imem_len; + u32 fw_emem_len; + u8 sz_fw_tmpbuffer[RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE]; + u32 sz_fw_tmpbufferlen; + u16 cmdpacket_fragthresold; +}; + +struct h2c_set_pwrmode_parm { + u8 mode; + u8 flag_low_traffic_en; + u8 flag_lpnav_en; + u8 flag_rf_low_snr_en; + /* 1: dps, 0: 32k */ + u8 flag_dps_en; + u8 bcn_rx_en; + u8 bcn_pass_cnt; + /* beacon TO (ms). ¡§=0¡¨ no limit. */ + u8 bcn_to; + u16 bcn_itv; + /* only for VOIP mode. */ + u8 app_itv; + u8 awake_bcn_itvl; + u8 smart_ps; + /* unit: 100 ms */ + u8 bcn_pass_period; +}; + +struct h2c_joinbss_rpt_parm { + u8 opmode; + u8 ps_qos_info; + u8 bssid[6]; + u16 bcnitv; + u16 aid; +} ; + +struct h2c_wpa_ptk { + /* EAPOL-Key Key Confirmation Key (KCK) */ + u8 kck[16]; + /* EAPOL-Key Key Encryption Key (KEK) */ + u8 kek[16]; + /* Temporal Key 1 (TK1) */ + u8 tk1[16]; + union { + /* Temporal Key 2 (TK2) */ + u8 tk2[16]; + struct { + u8 tx_mic_key[8]; + u8 rx_mic_key[8]; + } athu; + } u; +}; + +struct h2c_wpa_two_way_parm { + /* algorithm TKIP or AES */ + u8 pairwise_en_alg; + u8 group_en_alg; + struct h2c_wpa_ptk wpa_ptk_value; +} ; + +enum h2c_cmd { + FW_H2C_SETPWRMODE = 0, + FW_H2C_JOINBSSRPT = 1, + FW_H2C_WOWLAN_UPDATE_GTK = 2, + FW_H2C_WOWLAN_UPDATE_IV = 3, + FW_H2C_WOWLAN_OFFLOAD = 4, +}; + +enum fw_h2c_cmd { + H2C_READ_MACREG_CMD, /*0*/ + H2C_WRITE_MACREG_CMD, + H2C_READBB_CMD, + H2C_WRITEBB_CMD, + H2C_READRF_CMD, + H2C_WRITERF_CMD, /*5*/ + H2C_READ_EEPROM_CMD, + H2C_WRITE_EEPROM_CMD, + H2C_READ_EFUSE_CMD, + H2C_WRITE_EFUSE_CMD, + H2C_READ_CAM_CMD, /*10*/ + H2C_WRITE_CAM_CMD, + H2C_SETBCNITV_CMD, + H2C_SETMBIDCFG_CMD, + H2C_JOINBSS_CMD, + H2C_DISCONNECT_CMD, /*15*/ + H2C_CREATEBSS_CMD, + H2C_SETOPMode_CMD, + H2C_SITESURVEY_CMD, + H2C_SETAUTH_CMD, + H2C_SETKEY_CMD, /*20*/ + H2C_SETSTAKEY_CMD, + H2C_SETASSOCSTA_CMD, + H2C_DELASSOCSTA_CMD, + H2C_SETSTAPWRSTATE_CMD, + H2C_SETBASICRATE_CMD, /*25*/ + H2C_GETBASICRATE_CMD, + H2C_SETDATARATE_CMD, + H2C_GETDATARATE_CMD, + H2C_SETPHYINFO_CMD, + H2C_GETPHYINFO_CMD, /*30*/ + H2C_SETPHY_CMD, + H2C_GETPHY_CMD, + H2C_READRSSI_CMD, + H2C_READGAIN_CMD, + H2C_SETATIM_CMD, /*35*/ + H2C_SETPWRMODE_CMD, + H2C_JOINBSSRPT_CMD, + H2C_SETRATABLE_CMD, + H2C_GETRATABLE_CMD, + H2C_GETCCXREPORT_CMD, /*40*/ + H2C_GETDTMREPORT_CMD, + H2C_GETTXRATESTATICS_CMD, + H2C_SETUSBSUSPEND_CMD, + H2C_SETH2CLBK_CMD, + H2C_TMP1, /*45*/ + H2C_WOWLAN_UPDATE_GTK_CMD, + H2C_WOWLAN_FW_OFFLOAD, + H2C_TMP2, + H2C_TMP3, + H2C_WOWLAN_UPDATE_IV_CMD, /*50*/ + H2C_TMP4, +}; + +/* The following macros are used for FW + * CMD map and parameter updated. */ +#define FW_CMD_IO_CLR(rtlpriv, _Bit) \ + do { \ + udelay(1000); \ + rtlpriv->rtlhal.fwcmd_iomap &= (~_Bit); \ + } while (0) + +#define FW_CMD_IO_UPDATE(rtlpriv, _val) \ + rtlpriv->rtlhal.fwcmd_iomap = _val; + +#define FW_CMD_IO_SET(rtlpriv, _val) \ + do { \ + rtl_write_word(rtlpriv, LBUS_MON_ADDR, (u16)_val); \ + FW_CMD_IO_UPDATE(rtlpriv, _val); \ + } while (0) + +#define FW_CMD_PARA_SET(rtlpriv, _val) \ + do { \ + rtl_write_dword(rtlpriv, LBUS_ADDR_MASK, _val); \ + rtlpriv->rtlhal.fwcmd_ioparam = _val; \ + } while (0) + +#define FW_CMD_IO_QUERY(rtlpriv) \ + (u16)(rtlpriv->rtlhal.fwcmd_iomap) +#define FW_CMD_IO_PARA_QUERY(rtlpriv) \ + ((u32)(rtlpriv->rtlhal.fwcmd_ioparam)) + +int rtl92s_download_fw(struct ieee80211_hw *hw); +void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); +void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, + u8 mstatus, u8 ps_qosinfo); + +#endif + diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c new file mode 100644 index 000000000000..12b0978ba4fa --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c @@ -0,0 +1,2548 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../regd.h" +#include "../cam.h" +#include "../ps.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "led.h" +#include "hw.h" + +void rtl92se_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + switch (variable) { + case HW_VAR_RCR: { + *((u32 *) (val)) = rtlpci->receive_config; + break; + } + case HW_VAR_RF_STATE: { + *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; + break; + } + case HW_VAR_FW_PSMODE_STATUS: { + *((bool *) (val)) = ppsc->fw_current_inpsmode; + break; + } + case HW_VAR_CORRECT_TSF: { + u64 tsf; + u32 *ptsf_low = (u32 *)&tsf; + u32 *ptsf_high = ((u32 *)&tsf) + 1; + + *ptsf_high = rtl_read_dword(rtlpriv, (TSFR + 4)); + *ptsf_low = rtl_read_dword(rtlpriv, TSFR); + + *((u64 *) (val)) = tsf; + + break; + } + case HW_VAR_MRC: { + *((bool *)(val)) = rtlpriv->dm.current_mrc_switch; + break; + } + default: { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + } +} + +void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + switch (variable) { + case HW_VAR_ETHER_ADDR:{ + rtl_write_dword(rtlpriv, IDR0, ((u32 *)(val))[0]); + rtl_write_word(rtlpriv, IDR4, ((u16 *)(val + 4))[0]); + break; + } + case HW_VAR_BASIC_RATE:{ + u16 rate_cfg = ((u16 *) val)[0]; + u8 rate_index = 0; + + if (rtlhal->version == VERSION_8192S_ACUT) + rate_cfg = rate_cfg & 0x150; + else + rate_cfg = rate_cfg & 0x15f; + + rate_cfg |= 0x01; + + rtl_write_byte(rtlpriv, RRSR, rate_cfg & 0xff); + rtl_write_byte(rtlpriv, RRSR + 1, + (rate_cfg >> 8) & 0xff); + + while (rate_cfg > 0x1) { + rate_cfg = (rate_cfg >> 1); + rate_index++; + } + rtl_write_byte(rtlpriv, INIRTSMCS_SEL, rate_index); + + break; + } + case HW_VAR_BSSID:{ + rtl_write_dword(rtlpriv, BSSIDR, ((u32 *)(val))[0]); + rtl_write_word(rtlpriv, BSSIDR + 4, + ((u16 *)(val + 4))[0]); + break; + } + case HW_VAR_SIFS:{ + rtl_write_byte(rtlpriv, SIFS_OFDM, val[0]); + rtl_write_byte(rtlpriv, SIFS_OFDM + 1, val[1]); + break; + } + case HW_VAR_SLOT_TIME:{ + u8 e_aci; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "HW_VAR_SLOT_TIME %x\n", val[0]); + + rtl_write_byte(rtlpriv, SLOT_TIME, val[0]); + + for (e_aci = 0; e_aci < AC_MAX; e_aci++) { + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AC_PARAM, + (&e_aci)); + } + break; + } + case HW_VAR_ACK_PREAMBLE:{ + u8 reg_tmp; + u8 short_preamble = (bool) (*val); + reg_tmp = (mac->cur_40_prime_sc) << 5; + if (short_preamble) + reg_tmp |= 0x80; + + rtl_write_byte(rtlpriv, RRSR + 2, reg_tmp); + break; + } + case HW_VAR_AMPDU_MIN_SPACE:{ + u8 min_spacing_to_set; + u8 sec_min_space; + + min_spacing_to_set = *val; + if (min_spacing_to_set <= 7) { + if (rtlpriv->sec.pairwise_enc_algorithm == + NO_ENCRYPTION) + sec_min_space = 0; + else + sec_min_space = 1; + + if (min_spacing_to_set < sec_min_space) + min_spacing_to_set = sec_min_space; + if (min_spacing_to_set > 5) + min_spacing_to_set = 5; + + mac->min_space_cfg = + ((mac->min_space_cfg & 0xf8) | + min_spacing_to_set); + + *val = min_spacing_to_set; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", + mac->min_space_cfg); + + rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, + mac->min_space_cfg); + } + break; + } + case HW_VAR_SHORTGI_DENSITY:{ + u8 density_to_set; + + density_to_set = *val; + mac->min_space_cfg = rtlpriv->rtlhal.minspace_cfg; + mac->min_space_cfg |= (density_to_set << 3); + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_SHORTGI_DENSITY: %#x\n", + mac->min_space_cfg); + + rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, + mac->min_space_cfg); + + break; + } + case HW_VAR_AMPDU_FACTOR:{ + u8 factor_toset; + u8 regtoset; + u8 factorlevel[18] = { + 2, 4, 4, 7, 7, 13, 13, + 13, 2, 7, 7, 13, 13, + 15, 15, 15, 15, 0}; + u8 index = 0; + + factor_toset = *val; + if (factor_toset <= 3) { + factor_toset = (1 << (factor_toset + 2)); + if (factor_toset > 0xf) + factor_toset = 0xf; + + for (index = 0; index < 17; index++) { + if (factorlevel[index] > factor_toset) + factorlevel[index] = + factor_toset; + } + + for (index = 0; index < 8; index++) { + regtoset = ((factorlevel[index * 2]) | + (factorlevel[index * + 2 + 1] << 4)); + rtl_write_byte(rtlpriv, + AGGLEN_LMT_L + index, + regtoset); + } + + regtoset = ((factorlevel[16]) | + (factorlevel[17] << 4)); + rtl_write_byte(rtlpriv, AGGLEN_LMT_H, regtoset); + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_FACTOR: %#x\n", + factor_toset); + } + break; + } + case HW_VAR_AC_PARAM:{ + u8 e_aci = *val; + rtl92s_dm_init_edca_turbo(hw); + + if (rtlpci->acm_method != EACMWAY2_SW) + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_ACM_CTRL, + &e_aci); + break; + } + case HW_VAR_ACM_CTRL:{ + u8 e_aci = *val; + union aci_aifsn *p_aci_aifsn = (union aci_aifsn *)(&( + mac->ac[0].aifs)); + u8 acm = p_aci_aifsn->f.acm; + u8 acm_ctrl = rtl_read_byte(rtlpriv, AcmHwCtrl); + + acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? + 0x0 : 0x1); + + if (acm) { + switch (e_aci) { + case AC0_BE: + acm_ctrl |= AcmHw_BeqEn; + break; + case AC2_VI: + acm_ctrl |= AcmHw_ViqEn; + break; + case AC3_VO: + acm_ctrl |= AcmHw_VoqEn; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", + acm); + break; + } + } else { + switch (e_aci) { + case AC0_BE: + acm_ctrl &= (~AcmHw_BeqEn); + break; + case AC2_VI: + acm_ctrl &= (~AcmHw_ViqEn); + break; + case AC3_VO: + acm_ctrl &= (~AcmHw_VoqEn); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + } + + RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, + "HW_VAR_ACM_CTRL Write 0x%X\n", acm_ctrl); + rtl_write_byte(rtlpriv, AcmHwCtrl, acm_ctrl); + break; + } + case HW_VAR_RCR:{ + rtl_write_dword(rtlpriv, RCR, ((u32 *) (val))[0]); + rtlpci->receive_config = ((u32 *) (val))[0]; + break; + } + case HW_VAR_RETRY_LIMIT:{ + u8 retry_limit = val[0]; + + rtl_write_word(rtlpriv, RETRY_LIMIT, + retry_limit << RETRY_LIMIT_SHORT_SHIFT | + retry_limit << RETRY_LIMIT_LONG_SHIFT); + break; + } + case HW_VAR_DUAL_TSF_RST: { + break; + } + case HW_VAR_EFUSE_BYTES: { + rtlefuse->efuse_usedbytes = *((u16 *) val); + break; + } + case HW_VAR_EFUSE_USAGE: { + rtlefuse->efuse_usedpercentage = *val; + break; + } + case HW_VAR_IO_CMD: { + break; + } + case HW_VAR_WPA_CONFIG: { + rtl_write_byte(rtlpriv, REG_SECR, *val); + break; + } + case HW_VAR_SET_RPWM:{ + break; + } + case HW_VAR_H2C_FW_PWRMODE:{ + break; + } + case HW_VAR_FW_PSMODE_STATUS: { + ppsc->fw_current_inpsmode = *((bool *) val); + break; + } + case HW_VAR_H2C_FW_JOINBSSRPT:{ + break; + } + case HW_VAR_AID:{ + break; + } + case HW_VAR_CORRECT_TSF:{ + break; + } + case HW_VAR_MRC: { + bool bmrc_toset = *((bool *)val); + u8 u1bdata = 0; + + if (bmrc_toset) { + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, + MASKBYTE0, 0x33); + u1bdata = (u8)rtl_get_bbreg(hw, + ROFDM1_TRXPATHENABLE, + MASKBYTE0); + rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, + MASKBYTE0, + ((u1bdata & 0xf0) | 0x03)); + u1bdata = (u8)rtl_get_bbreg(hw, + ROFDM0_TRXPATHENABLE, + MASKBYTE1); + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, + MASKBYTE1, + (u1bdata | 0x04)); + + /* Update current settings. */ + rtlpriv->dm.current_mrc_switch = bmrc_toset; + } else { + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, + MASKBYTE0, 0x13); + u1bdata = (u8)rtl_get_bbreg(hw, + ROFDM1_TRXPATHENABLE, + MASKBYTE0); + rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, + MASKBYTE0, + ((u1bdata & 0xf0) | 0x01)); + u1bdata = (u8)rtl_get_bbreg(hw, + ROFDM0_TRXPATHENABLE, + MASKBYTE1); + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, + MASKBYTE1, (u1bdata & 0xfb)); + + /* Update current settings. */ + rtlpriv->dm.current_mrc_switch = bmrc_toset; + } + + break; + } + case HW_VAR_FW_LPS_ACTION: { + bool enter_fwlps = *((bool *)val); + u8 rpwm_val, fw_pwrmode; + bool fw_current_inps; + + if (enter_fwlps) { + rpwm_val = 0x02; /* RF off */ + fw_current_inps = true; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_PWRMODE, + &ppsc->fwctrl_psmode); + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + &rpwm_val); + } else { + rpwm_val = 0x0C; /* RF on */ + fw_pwrmode = FW_PS_ACTIVE_MODE; + fw_current_inps = false; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + &rpwm_val); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + &fw_pwrmode); + + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + } + break; } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + +} + +void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 sec_reg_value = 0x0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", + rtlpriv->sec.pairwise_enc_algorithm, + rtlpriv->sec.group_enc_algorithm); + + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "not open hw encryption\n"); + return; + } + + sec_reg_value = SCR_TXENCENABLE | SCR_RXENCENABLE; + + if (rtlpriv->sec.use_defaultkey) { + sec_reg_value |= SCR_TXUSEDK; + sec_reg_value |= SCR_RXUSEDK; + } + + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "The SECR-value %x\n", + sec_reg_value); + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); + +} + +static u8 _rtl92se_halset_sysclk(struct ieee80211_hw *hw, u8 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 waitcount = 100; + bool bresult = false; + u8 tmpvalue; + + rtl_write_byte(rtlpriv, SYS_CLKR + 1, data); + + /* Wait the MAC synchronized. */ + udelay(400); + + /* Check if it is set ready. */ + tmpvalue = rtl_read_byte(rtlpriv, SYS_CLKR + 1); + bresult = ((tmpvalue & BIT(7)) == (data & BIT(7))); + + if ((data & (BIT(6) | BIT(7))) == false) { + waitcount = 100; + tmpvalue = 0; + + while (1) { + waitcount--; + + tmpvalue = rtl_read_byte(rtlpriv, SYS_CLKR + 1); + if ((tmpvalue & BIT(6))) + break; + + pr_err("wait for BIT(6) return value %x\n", tmpvalue); + if (waitcount == 0) + break; + + udelay(10); + } + + if (waitcount == 0) + bresult = false; + else + bresult = true; + } + + return bresult; +} + +void rtl8192se_gpiobit3_cfg_inputmode(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1tmp; + + /* The following config GPIO function */ + rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); + u1tmp = rtl_read_byte(rtlpriv, GPIO_IO_SEL); + + /* config GPIO3 to input */ + u1tmp &= HAL_8192S_HW_GPIO_OFF_MASK; + rtl_write_byte(rtlpriv, GPIO_IO_SEL, u1tmp); + +} + +static u8 _rtl92se_rf_onoff_detect(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1tmp; + u8 retval = ERFON; + + /* The following config GPIO function */ + rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); + u1tmp = rtl_read_byte(rtlpriv, GPIO_IO_SEL); + + /* config GPIO3 to input */ + u1tmp &= HAL_8192S_HW_GPIO_OFF_MASK; + rtl_write_byte(rtlpriv, GPIO_IO_SEL, u1tmp); + + /* On some of the platform, driver cannot read correct + * value without delay between Write_GPIO_SEL and Read_GPIO_IN */ + mdelay(10); + + /* check GPIO3 */ + u1tmp = rtl_read_byte(rtlpriv, GPIO_IN_SE); + retval = (u1tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? ERFON : ERFOFF; + + return retval; +} + +static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + u8 i; + u8 tmpu1b; + u16 tmpu2b; + u8 pollingcnt = 20; + + if (rtlpci->first_init) { + /* Reset PCIE Digital */ + tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + tmpu1b &= 0xFE; + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b); + udelay(1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b | BIT(0)); + } + + /* Switch to SW IO control */ + tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); + if (tmpu1b & BIT(7)) { + tmpu1b &= ~(BIT(6) | BIT(7)); + + /* Set failed, return to prevent hang. */ + if (!_rtl92se_halset_sysclk(hw, tmpu1b)) + return; + } + + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x0); + udelay(50); + rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); + udelay(50); + + /* Clear FW RPWM for FW control LPS.*/ + rtl_write_byte(rtlpriv, RPWM, 0x0); + + /* Reset MAC-IO and CPU and Core Digital BIT(10)/11/15 */ + tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + tmpu1b &= 0x73; + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b); + /* wait for BIT 10/11/15 to pull high automatically!! */ + mdelay(1); + + rtl_write_byte(rtlpriv, CMDR, 0); + rtl_write_byte(rtlpriv, TCR, 0); + + /* Data sheet not define 0x562!!! Copy from WMAC!!!!! */ + tmpu1b = rtl_read_byte(rtlpriv, 0x562); + tmpu1b |= 0x08; + rtl_write_byte(rtlpriv, 0x562, tmpu1b); + tmpu1b &= ~(BIT(3)); + rtl_write_byte(rtlpriv, 0x562, tmpu1b); + + /* Enable AFE clock source */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL); + rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, (tmpu1b | 0x01)); + /* Delay 1.5ms */ + mdelay(2); + tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL + 1); + rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, (tmpu1b & 0xfb)); + + /* Enable AFE Macro Block's Bandgap */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); + rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | BIT(0))); + mdelay(1); + + /* Enable AFE Mbias */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); + rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | 0x02)); + mdelay(1); + + /* Enable LDOA15 block */ + tmpu1b = rtl_read_byte(rtlpriv, LDOA15_CTRL); + rtl_write_byte(rtlpriv, LDOA15_CTRL, (tmpu1b | BIT(0))); + + /* Set Digital Vdd to Retention isolation Path. */ + tmpu2b = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL); + rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, (tmpu2b | BIT(11))); + + /* For warm reboot NIC disappera bug. */ + tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(13))); + + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x68); + + /* Enable AFE PLL Macro Block */ + /* We need to delay 100u before enabling PLL. */ + udelay(200); + tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); + + /* for divider reset */ + udelay(100); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | + BIT(4) | BIT(6))); + udelay(10); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); + udelay(10); + + /* Enable MAC 80MHZ clock */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL + 1); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, (tmpu1b | BIT(0))); + mdelay(1); + + /* Release isolation AFE PLL & MD */ + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xA6); + + /* Enable MAC clock */ + tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); + rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b | BIT(12) | BIT(11))); + + /* Enable Core digital and enable IOREG R/W */ + tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11))); + + tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b & ~(BIT(7))); + + /* enable REG_EN */ + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15))); + + /* Switch the control path. */ + tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); + rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b & (~BIT(2)))); + + tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); + tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); + if (!_rtl92se_halset_sysclk(hw, tmpu1b)) + return; /* Set failed, return to prevent hang. */ + + rtl_write_word(rtlpriv, CMDR, 0x07FC); + + /* MH We must enable the section of code to prevent load IMEM fail. */ + /* Load MAC register from WMAc temporarily We simulate macreg. */ + /* txt HW will provide MAC txt later */ + rtl_write_byte(rtlpriv, 0x6, 0x30); + rtl_write_byte(rtlpriv, 0x49, 0xf0); + + rtl_write_byte(rtlpriv, 0x4b, 0x81); + + rtl_write_byte(rtlpriv, 0xb5, 0x21); + + rtl_write_byte(rtlpriv, 0xdc, 0xff); + rtl_write_byte(rtlpriv, 0xdd, 0xff); + rtl_write_byte(rtlpriv, 0xde, 0xff); + rtl_write_byte(rtlpriv, 0xdf, 0xff); + + rtl_write_byte(rtlpriv, 0x11a, 0x00); + rtl_write_byte(rtlpriv, 0x11b, 0x00); + + for (i = 0; i < 32; i++) + rtl_write_byte(rtlpriv, INIMCS_SEL + i, 0x1b); + + rtl_write_byte(rtlpriv, 0x236, 0xff); + + rtl_write_byte(rtlpriv, 0x503, 0x22); + + if (ppsc->support_aspm && !ppsc->support_backdoor) + rtl_write_byte(rtlpriv, 0x560, 0x40); + else + rtl_write_byte(rtlpriv, 0x560, 0x00); + + rtl_write_byte(rtlpriv, DBG_PORT, 0x91); + + /* Set RX Desc Address */ + rtl_write_dword(rtlpriv, RDQDA, rtlpci->rx_ring[RX_MPDU_QUEUE].dma); + rtl_write_dword(rtlpriv, RCDA, rtlpci->rx_ring[RX_CMD_QUEUE].dma); + + /* Set TX Desc Address */ + rtl_write_dword(rtlpriv, TBKDA, rtlpci->tx_ring[BK_QUEUE].dma); + rtl_write_dword(rtlpriv, TBEDA, rtlpci->tx_ring[BE_QUEUE].dma); + rtl_write_dword(rtlpriv, TVIDA, rtlpci->tx_ring[VI_QUEUE].dma); + rtl_write_dword(rtlpriv, TVODA, rtlpci->tx_ring[VO_QUEUE].dma); + rtl_write_dword(rtlpriv, TBDA, rtlpci->tx_ring[BEACON_QUEUE].dma); + rtl_write_dword(rtlpriv, TCDA, rtlpci->tx_ring[TXCMD_QUEUE].dma); + rtl_write_dword(rtlpriv, TMDA, rtlpci->tx_ring[MGNT_QUEUE].dma); + rtl_write_dword(rtlpriv, THPDA, rtlpci->tx_ring[HIGH_QUEUE].dma); + rtl_write_dword(rtlpriv, HDA, rtlpci->tx_ring[HCCA_QUEUE].dma); + + rtl_write_word(rtlpriv, CMDR, 0x37FC); + + /* To make sure that TxDMA can ready to download FW. */ + /* We should reset TxDMA if IMEM RPT was not ready. */ + do { + tmpu1b = rtl_read_byte(rtlpriv, TCR); + if ((tmpu1b & TXDMA_INIT_VALUE) == TXDMA_INIT_VALUE) + break; + + udelay(5); + } while (pollingcnt--); + + if (pollingcnt <= 0) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Polling TXDMA_INIT_VALUE timeout!! Current TCR(%#x)\n", + tmpu1b); + tmpu1b = rtl_read_byte(rtlpriv, CMDR); + rtl_write_byte(rtlpriv, CMDR, tmpu1b & (~TXDMA_EN)); + udelay(2); + /* Reset TxDMA */ + rtl_write_byte(rtlpriv, CMDR, tmpu1b | TXDMA_EN); + } + + /* After MACIO reset,we must refresh LED state. */ + if ((ppsc->rfoff_reason == RF_CHANGE_BY_IPS) || + (ppsc->rfoff_reason == 0)) { + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + enum rf_pwrstate rfpwr_state_toset; + rfpwr_state_toset = _rtl92se_rf_onoff_detect(hw); + + if (rfpwr_state_toset == ERFON) + rtl92se_sw_led_on(hw, pLed0); + } +} + +static void _rtl92se_macconfig_after_fwdownload(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 i; + u16 tmpu2b; + + /* 1. System Configure Register (Offset: 0x0000 - 0x003F) */ + + /* 2. Command Control Register (Offset: 0x0040 - 0x004F) */ + /* Turn on 0x40 Command register */ + rtl_write_word(rtlpriv, CMDR, (BBRSTN | BB_GLB_RSTN | + SCHEDULE_EN | MACRXEN | MACTXEN | DDMA_EN | FW2HW_EN | + RXDMA_EN | TXDMA_EN | HCI_RXDMA_EN | HCI_TXDMA_EN)); + + /* Set TCR TX DMA pre 2 FULL enable bit */ + rtl_write_dword(rtlpriv, TCR, rtl_read_dword(rtlpriv, TCR) | + TXDMAPRE2FULL); + + /* Set RCR */ + rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config); + + /* 3. MACID Setting Register (Offset: 0x0050 - 0x007F) */ + + /* 4. Timing Control Register (Offset: 0x0080 - 0x009F) */ + /* Set CCK/OFDM SIFS */ + /* CCK SIFS shall always be 10us. */ + rtl_write_word(rtlpriv, SIFS_CCK, 0x0a0a); + rtl_write_word(rtlpriv, SIFS_OFDM, 0x1010); + + /* Set AckTimeout */ + rtl_write_byte(rtlpriv, ACK_TIMEOUT, 0x40); + + /* Beacon related */ + rtl_write_word(rtlpriv, BCN_INTERVAL, 100); + rtl_write_word(rtlpriv, ATIMWND, 2); + + /* 5. FIFO Control Register (Offset: 0x00A0 - 0x015F) */ + /* 5.1 Initialize Number of Reserved Pages in Firmware Queue */ + /* Firmware allocate now, associate with FW internal setting.!!! */ + + /* 5.2 Setting TX/RX page size 0/1/2/3/4=64/128/256/512/1024 */ + /* 5.3 Set driver info, we only accept PHY status now. */ + /* 5.4 Set RXDMA arbitration to control RXDMA/MAC/FW R/W for RXFIFO */ + rtl_write_byte(rtlpriv, RXDMA, rtl_read_byte(rtlpriv, RXDMA) | BIT(6)); + + /* 6. Adaptive Control Register (Offset: 0x0160 - 0x01CF) */ + /* Set RRSR to all legacy rate and HT rate + * CCK rate is supported by default. + * CCK rate will be filtered out only when associated + * AP does not support it. + * Only enable ACK rate to OFDM 24M + * Disable RRSR for CCK rate in A-Cut */ + + if (rtlhal->version == VERSION_8192S_ACUT) + rtl_write_byte(rtlpriv, RRSR, 0xf0); + else if (rtlhal->version == VERSION_8192S_BCUT) + rtl_write_byte(rtlpriv, RRSR, 0xff); + rtl_write_byte(rtlpriv, RRSR + 1, 0x01); + rtl_write_byte(rtlpriv, RRSR + 2, 0x00); + + /* A-Cut IC do not support CCK rate. We forbid ARFR to */ + /* fallback to CCK rate */ + for (i = 0; i < 8; i++) { + /*Disable RRSR for CCK rate in A-Cut */ + if (rtlhal->version == VERSION_8192S_ACUT) + rtl_write_dword(rtlpriv, ARFR0 + i * 4, 0x1f0ff0f0); + } + + /* Different rate use different AMPDU size */ + /* MCS32/ MCS15_SG use max AMPDU size 15*2=30K */ + rtl_write_byte(rtlpriv, AGGLEN_LMT_H, 0x0f); + /* MCS0/1/2/3 use max AMPDU size 4*2=8K */ + rtl_write_word(rtlpriv, AGGLEN_LMT_L, 0x7442); + /* MCS4/5 use max AMPDU size 8*2=16K 6/7 use 10*2=20K */ + rtl_write_word(rtlpriv, AGGLEN_LMT_L + 2, 0xddd7); + /* MCS8/9 use max AMPDU size 8*2=16K 10/11 use 10*2=20K */ + rtl_write_word(rtlpriv, AGGLEN_LMT_L + 4, 0xd772); + /* MCS12/13/14/15 use max AMPDU size 15*2=30K */ + rtl_write_word(rtlpriv, AGGLEN_LMT_L + 6, 0xfffd); + + /* Set Data / Response auto rate fallack retry count */ + rtl_write_dword(rtlpriv, DARFRC, 0x04010000); + rtl_write_dword(rtlpriv, DARFRC + 4, 0x09070605); + rtl_write_dword(rtlpriv, RARFRC, 0x04010000); + rtl_write_dword(rtlpriv, RARFRC + 4, 0x09070605); + + /* 7. EDCA Setting Register (Offset: 0x01D0 - 0x01FF) */ + /* Set all rate to support SG */ + rtl_write_word(rtlpriv, SG_RATE, 0xFFFF); + + /* 8. WMAC, BA, and CCX related Register (Offset: 0x0200 - 0x023F) */ + /* Set NAV protection length */ + rtl_write_word(rtlpriv, NAV_PROT_LEN, 0x0080); + /* CF-END Threshold */ + rtl_write_byte(rtlpriv, CFEND_TH, 0xFF); + /* Set AMPDU minimum space */ + rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, 0x07); + /* Set TXOP stall control for several queue/HI/BCN/MGT/ */ + rtl_write_byte(rtlpriv, TXOP_STALL_CTRL, 0x00); + + /* 9. Security Control Register (Offset: 0x0240 - 0x025F) */ + /* 10. Power Save Control Register (Offset: 0x0260 - 0x02DF) */ + /* 11. General Purpose Register (Offset: 0x02E0 - 0x02FF) */ + /* 12. Host Interrupt Status Register (Offset: 0x0300 - 0x030F) */ + /* 13. Test Mode and Debug Control Register (Offset: 0x0310 - 0x034F) */ + + /* 14. Set driver info, we only accept PHY status now. */ + rtl_write_byte(rtlpriv, RXDRVINFO_SZ, 4); + + /* 15. For EEPROM R/W Workaround */ + /* 16. For EFUSE to share REG_SYS_FUNC_EN with EEPROM!!! */ + tmpu2b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, tmpu2b | BIT(13)); + tmpu2b = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL); + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, tmpu2b & (~BIT(8))); + + /* 17. For EFUSE */ + /* We may R/W EFUSE in EEPROM mode */ + if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + u8 tempval; + + tempval = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL + 1); + tempval &= 0xFE; + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, tempval); + + /* Change Program timing */ + rtl_write_byte(rtlpriv, REG_EFUSE_CTRL + 3, 0x72); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "EFUSE CONFIG OK\n"); + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "OK\n"); + +} + +static void _rtl92se_hw_configure(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + u8 reg_bw_opmode = 0; + u32 reg_rrsr = 0; + u8 regtmp = 0; + + reg_bw_opmode = BW_OPMODE_20MHZ; + reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + + regtmp = rtl_read_byte(rtlpriv, INIRTSMCS_SEL); + reg_rrsr = ((reg_rrsr & 0x000fffff) << 8) | regtmp; + rtl_write_dword(rtlpriv, INIRTSMCS_SEL, reg_rrsr); + rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); + + /* Set Retry Limit here */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT, + (u8 *)(&rtlpci->shortretry_limit)); + + rtl_write_byte(rtlpriv, MLT, 0x8f); + + /* For Min Spacing configuration. */ + switch (rtlphy->rf_type) { + case RF_1T2R: + case RF_1T1R: + rtlhal->minspace_cfg = (MAX_MSS_DENSITY_1T << 3); + break; + case RF_2T2R: + case RF_2T2R_GREEN: + rtlhal->minspace_cfg = (MAX_MSS_DENSITY_2T << 3); + break; + } + rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, rtlhal->minspace_cfg); +} + +int rtl92se_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 tmp_byte = 0; + unsigned long flags; + bool rtstatus = true; + u8 tmp_u1b; + int err = false; + u8 i; + int wdcapra_add[] = { + EDCAPARA_BE, EDCAPARA_BK, + EDCAPARA_VI, EDCAPARA_VO}; + u8 secr_value = 0x0; + + rtlpci->being_init_adapter = true; + + /* As this function can take a very long time (up to 350 ms) + * and can be called with irqs disabled, reenable the irqs + * to let the other devices continue being serviced. + * + * It is safe doing so since our own interrupts will only be enabled + * in a subsequent step. + */ + local_save_flags(flags); + local_irq_enable(); + + rtlpriv->intf_ops->disable_aspm(hw); + + /* 1. MAC Initialize */ + /* Before FW download, we have to set some MAC register */ + _rtl92se_macconfig_before_fwdownload(hw); + + rtlhal->version = (enum version_8192s)((rtl_read_dword(rtlpriv, + PMC_FSM) >> 16) & 0xF); + + rtl8192se_gpiobit3_cfg_inputmode(hw); + + /* 2. download firmware */ + rtstatus = rtl92s_download_fw(hw); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW now... " + "Please copy FW into /lib/firmware/rtlwifi\n"); + err = 1; + goto exit; + } + + /* After FW download, we have to reset MAC register */ + _rtl92se_macconfig_after_fwdownload(hw); + + /*Retrieve default FW Cmd IO map. */ + rtlhal->fwcmd_iomap = rtl_read_word(rtlpriv, LBUS_MON_ADDR); + rtlhal->fwcmd_ioparam = rtl_read_dword(rtlpriv, LBUS_ADDR_MASK); + + /* 3. Initialize MAC/PHY Config by MACPHY_reg.txt */ + if (!rtl92s_phy_mac_config(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "MAC Config failed\n"); + err = rtstatus; + goto exit; + } + + /* because last function modify RCR, so we update + * rcr var here, or TP will unstable for receive_config + * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx + * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 + */ + rtlpci->receive_config = rtl_read_dword(rtlpriv, RCR); + rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); + rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config); + + /* Make sure BB/RF write OK. We should prevent enter IPS. radio off. */ + /* We must set flag avoid BB/RF config period later!! */ + rtl_write_dword(rtlpriv, CMDR, 0x37FC); + + /* 4. Initialize BB After MAC Config PHY_reg.txt, AGC_Tab.txt */ + if (!rtl92s_phy_bb_config(hw)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "BB Config failed\n"); + err = rtstatus; + goto exit; + } + + /* 5. Initiailze RF RAIO_A.txt RF RAIO_B.txt */ + /* Before initalizing RF. We can not use FW to do RF-R/W. */ + + rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; + + /* Before RF-R/W we must execute the IO from Scott's suggestion. */ + rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, 0xDB); + if (rtlhal->version == VERSION_8192S_ACUT) + rtl_write_byte(rtlpriv, SPS1_CTRL + 3, 0x07); + else + rtl_write_byte(rtlpriv, RF_CTRL, 0x07); + + if (!rtl92s_phy_rf_config(hw)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "RF Config failed\n"); + err = rtstatus; + goto exit; + } + + /* After read predefined TXT, we must set BB/MAC/RF + * register as our requirement */ + + rtlphy->rfreg_chnlval[0] = rtl92s_phy_query_rf_reg(hw, + (enum radio_path)0, + RF_CHNLBW, + RFREG_OFFSET_MASK); + rtlphy->rfreg_chnlval[1] = rtl92s_phy_query_rf_reg(hw, + (enum radio_path)1, + RF_CHNLBW, + RFREG_OFFSET_MASK); + + /*---- Set CCK and OFDM Block "ON"----*/ + rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); + + /*3 Set Hardware(Do nothing now) */ + _rtl92se_hw_configure(hw); + + /* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */ + /* TX power index for different rate set. */ + /* Get original hw reg values */ + rtl92s_phy_get_hw_reg_originalvalue(hw); + /* Write correct tx power index */ + rtl92s_phy_set_txpower(hw, rtlphy->current_channel); + + /* We must set MAC address after firmware download. */ + for (i = 0; i < 6; i++) + rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]); + + /* EEPROM R/W workaround */ + tmp_u1b = rtl_read_byte(rtlpriv, MAC_PINMUX_CFG); + rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, tmp_u1b & (~BIT(3))); + + rtl_write_byte(rtlpriv, 0x4d, 0x0); + + if (hal_get_firmwareversion(rtlpriv) >= 0x49) { + tmp_byte = rtl_read_byte(rtlpriv, FW_RSVD_PG_CRTL) & (~BIT(4)); + tmp_byte = tmp_byte | BIT(5); + rtl_write_byte(rtlpriv, FW_RSVD_PG_CRTL, tmp_byte); + rtl_write_dword(rtlpriv, TXDESC_MSK, 0xFFFFCFFF); + } + + /* We enable high power and RA related mechanism after NIC + * initialized. */ + if (hal_get_firmwareversion(rtlpriv) >= 0x35) { + /* Fw v.53 and later. */ + rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT); + } else if (hal_get_firmwareversion(rtlpriv) == 0x34) { + /* Fw v.52. */ + rtl_write_dword(rtlpriv, WFM5, FW_RA_INIT); + rtl92s_phy_chk_fwcmd_iodone(hw); + } else { + /* Compatible earlier FW version. */ + rtl_write_dword(rtlpriv, WFM5, FW_RA_RESET); + rtl92s_phy_chk_fwcmd_iodone(hw); + rtl_write_dword(rtlpriv, WFM5, FW_RA_ACTIVE); + rtl92s_phy_chk_fwcmd_iodone(hw); + rtl_write_dword(rtlpriv, WFM5, FW_RA_REFRESH); + rtl92s_phy_chk_fwcmd_iodone(hw); + } + + /* Add to prevent ASPM bug. */ + /* Always enable hst and NIC clock request. */ + rtl92s_phy_switch_ephy_parameter(hw); + + /* Security related + * 1. Clear all H/W keys. + * 2. Enable H/W encryption/decryption. */ + rtl_cam_reset_all_entry(hw); + secr_value |= SCR_TXENCENABLE; + secr_value |= SCR_RXENCENABLE; + secr_value |= SCR_NOSKMC; + rtl_write_byte(rtlpriv, REG_SECR, secr_value); + + for (i = 0; i < 4; i++) + rtl_write_dword(rtlpriv, wdcapra_add[i], 0x5e4322); + + if (rtlphy->rf_type == RF_1T2R) { + bool mrc2set = true; + /* Turn on B-Path */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC, (u8 *)&mrc2set); + } + + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_ON); + rtl92s_dm_init(hw); +exit: + local_irq_restore(flags); + rtlpci->being_init_adapter = false; + return err; +} + +void rtl92se_set_mac_addr(struct rtl_io *io, const u8 *addr) +{ + /* This is a stub. */ +} + +void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 reg_rcr; + + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); + + if (check_bssid) { + reg_rcr |= (RCR_CBSSID); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); + } else if (!check_bssid) { + reg_rcr &= (~RCR_CBSSID); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); + } + +} + +static int _rtl92se_set_media_status(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_msr = rtl_read_byte(rtlpriv, MSR); + u32 temp; + bt_msr &= ~MSR_LINK_MASK; + + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + bt_msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to NO LINK!\n"); + break; + case NL80211_IFTYPE_ADHOC: + bt_msr |= (MSR_LINK_ADHOC << MSR_LINK_SHIFT); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to Ad Hoc!\n"); + break; + case NL80211_IFTYPE_STATION: + bt_msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to STA!\n"); + break; + case NL80211_IFTYPE_AP: + bt_msr |= (MSR_LINK_MASTER << MSR_LINK_SHIFT); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to AP!\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Network type %d not supported!\n", type); + return 1; + + } + + if (type != NL80211_IFTYPE_AP && + rtlpriv->mac80211.link_state < MAC80211_LINKED) + bt_msr = rtl_read_byte(rtlpriv, MSR) & ~MSR_LINK_MASK; + rtl_write_byte(rtlpriv, MSR, bt_msr); + + temp = rtl_read_dword(rtlpriv, TCR); + rtl_write_dword(rtlpriv, TCR, temp & (~BIT(8))); + rtl_write_dword(rtlpriv, TCR, temp | BIT(8)); + + + return 0; +} + +/* HW_VAR_MEDIA_STATUS & HW_VAR_CECHK_BSSID */ +int rtl92se_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (_rtl92se_set_media_status(hw, type)) + return -EOPNOTSUPP; + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP) + rtl92se_set_check_bssid(hw, true); + } else { + rtl92se_set_check_bssid(hw, false); + } + + return 0; +} + +/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ +void rtl92se_set_qos(struct ieee80211_hw *hw, int aci) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtl92s_dm_init_edca_turbo(hw); + + switch (aci) { + case AC1_BK: + rtl_write_dword(rtlpriv, EDCAPARA_BK, 0xa44f); + break; + case AC0_BE: + /* rtl_write_dword(rtlpriv, EDCAPARA_BE, u4b_ac_param); */ + break; + case AC2_VI: + rtl_write_dword(rtlpriv, EDCAPARA_VI, 0x5e4322); + break; + case AC3_VO: + rtl_write_dword(rtlpriv, EDCAPARA_VO, 0x2f3222); + break; + default: + RT_ASSERT(false, "invalid aci: %d !\n", aci); + break; + } +} + +void rtl92se_enable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]); + /* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */ + rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F); + rtlpci->irq_enabled = true; +} + +void rtl92se_disable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv; + struct rtl_pci *rtlpci; + + rtlpriv = rtl_priv(hw); + /* if firmware not available, no interrupts */ + if (!rtlpriv || !rtlpriv->max_fw_size) + return; + rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + rtl_write_dword(rtlpriv, INTA_MASK, 0); + rtl_write_dword(rtlpriv, INTA_MASK + 4, 0); + rtlpci->irq_enabled = false; +} + +static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 waitcnt = 100; + bool result = false; + u8 tmp; + + rtl_write_byte(rtlpriv, SYS_CLKR + 1, data); + + /* Wait the MAC synchronized. */ + udelay(400); + + /* Check if it is set ready. */ + tmp = rtl_read_byte(rtlpriv, SYS_CLKR + 1); + result = ((tmp & BIT(7)) == (data & BIT(7))); + + if ((data & (BIT(6) | BIT(7))) == false) { + waitcnt = 100; + tmp = 0; + + while (1) { + waitcnt--; + tmp = rtl_read_byte(rtlpriv, SYS_CLKR + 1); + + if ((tmp & BIT(6))) + break; + + pr_err("wait for BIT(6) return value %x\n", tmp); + + if (waitcnt == 0) + break; + udelay(10); + } + + if (waitcnt == 0) + result = false; + else + result = true; + } + + return result; +} + +static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 u1btmp; + + if (rtlhal->driver_going2unload) + rtl_write_byte(rtlpriv, 0x560, 0x0); + + /* Power save for BB/RF */ + u1btmp = rtl_read_byte(rtlpriv, LDOV12D_CTRL); + u1btmp |= BIT(0); + rtl_write_byte(rtlpriv, LDOV12D_CTRL, u1btmp); + rtl_write_byte(rtlpriv, SPS1_CTRL, 0x0); + rtl_write_byte(rtlpriv, TXPAUSE, 0xFF); + rtl_write_word(rtlpriv, CMDR, 0x57FC); + udelay(100); + rtl_write_word(rtlpriv, CMDR, 0x77FC); + rtl_write_byte(rtlpriv, PHY_CCA, 0x0); + udelay(10); + rtl_write_word(rtlpriv, CMDR, 0x37FC); + udelay(10); + rtl_write_word(rtlpriv, CMDR, 0x77FC); + udelay(10); + rtl_write_word(rtlpriv, CMDR, 0x57FC); + rtl_write_word(rtlpriv, CMDR, 0x0000); + + if (rtlhal->driver_going2unload) { + u1btmp = rtl_read_byte(rtlpriv, (REG_SYS_FUNC_EN + 1)); + u1btmp &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1btmp); + } + + u1btmp = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); + + /* Add description. After switch control path. register + * after page1 will be invisible. We can not do any IO + * for register>0x40. After resume&MACIO reset, we need + * to remember previous reg content. */ + if (u1btmp & BIT(7)) { + u1btmp &= ~(BIT(6) | BIT(7)); + if (!_rtl92s_set_sysclk(hw, u1btmp)) { + pr_err("Switch ctrl path fail\n"); + return; + } + } + + /* Power save for MAC */ + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS && + !rtlhal->driver_going2unload) { + /* enable LED function */ + rtl_write_byte(rtlpriv, 0x03, 0xF9); + /* SW/HW radio off or halt adapter!! For example S3/S4 */ + } else { + /* LED function disable. Power range is about 8mA now. */ + /* if write 0xF1 disconnet_pci power + * ifconfig wlan0 down power are both high 35:70 */ + /* if write oxF9 disconnet_pci power + * ifconfig wlan0 down power are both low 12:45*/ + rtl_write_byte(rtlpriv, 0x03, 0xF9); + } + + rtl_write_byte(rtlpriv, SYS_CLKR + 1, 0x70); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, 0x68); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x00); + rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); + rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, 0x0E); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + +} + +static void _rtl92se_gen_refreshledstate(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + + if (rtlpci->up_first_time == 1) + return; + + if (rtlpriv->psc.rfoff_reason == RF_CHANGE_BY_IPS) + rtl92se_sw_led_on(hw, pLed0); + else + rtl92se_sw_led_off(hw, pLed0); +} + + +static void _rtl92se_power_domain_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 tmpu2b; + u8 tmpu1b; + + rtlpriv->psc.pwrdomain_protect = true; + + tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); + if (tmpu1b & BIT(7)) { + tmpu1b &= ~(BIT(6) | BIT(7)); + if (!_rtl92s_set_sysclk(hw, tmpu1b)) { + rtlpriv->psc.pwrdomain_protect = false; + return; + } + } + + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x0); + rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); + + /* Reset MAC-IO and CPU and Core Digital BIT10/11/15 */ + tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + + /* If IPS we need to turn LED on. So we not + * not disable BIT 3/7 of reg3. */ + if (rtlpriv->psc.rfoff_reason & (RF_CHANGE_BY_IPS | RF_CHANGE_BY_HW)) + tmpu1b &= 0xFB; + else + tmpu1b &= 0x73; + + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b); + /* wait for BIT 10/11/15 to pull high automatically!! */ + mdelay(1); + + rtl_write_byte(rtlpriv, CMDR, 0); + rtl_write_byte(rtlpriv, TCR, 0); + + /* Data sheet not define 0x562!!! Copy from WMAC!!!!! */ + tmpu1b = rtl_read_byte(rtlpriv, 0x562); + tmpu1b |= 0x08; + rtl_write_byte(rtlpriv, 0x562, tmpu1b); + tmpu1b &= ~(BIT(3)); + rtl_write_byte(rtlpriv, 0x562, tmpu1b); + + /* Enable AFE clock source */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL); + rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, (tmpu1b | 0x01)); + /* Delay 1.5ms */ + udelay(1500); + tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL + 1); + rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, (tmpu1b & 0xfb)); + + /* Enable AFE Macro Block's Bandgap */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); + rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | BIT(0))); + mdelay(1); + + /* Enable AFE Mbias */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); + rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | 0x02)); + mdelay(1); + + /* Enable LDOA15 block */ + tmpu1b = rtl_read_byte(rtlpriv, LDOA15_CTRL); + rtl_write_byte(rtlpriv, LDOA15_CTRL, (tmpu1b | BIT(0))); + + /* Set Digital Vdd to Retention isolation Path. */ + tmpu2b = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL); + rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, (tmpu2b | BIT(11))); + + + /* For warm reboot NIC disappera bug. */ + tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(13))); + + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x68); + + /* Enable AFE PLL Macro Block */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); + /* Enable MAC 80MHZ clock */ + tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL + 1); + rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, (tmpu1b | BIT(0))); + mdelay(1); + + /* Release isolation AFE PLL & MD */ + rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xA6); + + /* Enable MAC clock */ + tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); + rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b | BIT(12) | BIT(11))); + + /* Enable Core digital and enable IOREG R/W */ + tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11))); + /* enable REG_EN */ + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15))); + + /* Switch the control path. */ + tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); + rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b & (~BIT(2)))); + + tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); + tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); + if (!_rtl92s_set_sysclk(hw, tmpu1b)) { + rtlpriv->psc.pwrdomain_protect = false; + return; + } + + rtl_write_word(rtlpriv, CMDR, 0x37FC); + + /* After MACIO reset,we must refresh LED state. */ + _rtl92se_gen_refreshledstate(hw); + + rtlpriv->psc.pwrdomain_protect = false; +} + +void rtl92se_card_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + enum nl80211_iftype opmode; + u8 wait = 30; + + rtlpriv->intf_ops->enable_aspm(hw); + + if (rtlpci->driver_is_goingto_unload || + ppsc->rfoff_reason > RF_CHANGE_BY_PS) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + + /* we should chnge GPIO to input mode + * this will drop away current about 25mA*/ + rtl8192se_gpiobit3_cfg_inputmode(hw); + + /* this is very important for ips power save */ + while (wait-- >= 10 && rtlpriv->psc.pwrdomain_protect) { + if (rtlpriv->psc.pwrdomain_protect) + mdelay(20); + else + break; + } + + mac->link_state = MAC80211_NOLINK; + opmode = NL80211_IFTYPE_UNSPECIFIED; + _rtl92se_set_media_status(hw, opmode); + + _rtl92s_phy_set_rfhalt(hw); + udelay(100); +} + +void rtl92se_interrupt_recognized(struct ieee80211_hw *hw, u32 *p_inta, + u32 *p_intb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; + rtl_write_dword(rtlpriv, ISR, *p_inta); + + *p_intb = rtl_read_dword(rtlpriv, ISR + 4) & rtlpci->irq_mask[1]; + rtl_write_dword(rtlpriv, ISR + 4, *p_intb); +} + +void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcntime_cfg = 0; + u16 bcn_cw = 6, bcn_ifs = 0xf; + u16 atim_window = 2; + + /* ATIM Window (in unit of TU). */ + rtl_write_word(rtlpriv, ATIMWND, atim_window); + + /* Beacon interval (in unit of TU). */ + rtl_write_word(rtlpriv, BCN_INTERVAL, mac->beacon_interval); + + /* DrvErlyInt (in unit of TU). (Time to send + * interrupt to notify driver to change + * beacon content) */ + rtl_write_word(rtlpriv, BCN_DRV_EARLY_INT, 10 << 4); + + /* BcnDMATIM(in unit of us). Indicates the + * time before TBTT to perform beacon queue DMA */ + rtl_write_word(rtlpriv, BCN_DMATIME, 256); + + /* Force beacon frame transmission even + * after receiving beacon frame from + * other ad hoc STA */ + rtl_write_byte(rtlpriv, BCN_ERR_THRESH, 100); + + /* Beacon Time Configuration */ + if (mac->opmode == NL80211_IFTYPE_ADHOC) + bcntime_cfg |= (bcn_cw << BCN_TCFG_CW_SHIFT); + + /* TODO: bcn_ifs may required to be changed on ASIC */ + bcntime_cfg |= bcn_ifs << BCN_TCFG_IFS; + + /*for beacon changed */ + rtl92s_phy_set_beacon_hwreg(hw, mac->beacon_interval); +} + +void rtl92se_set_beacon_interval(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval = mac->beacon_interval; + + /* Beacon interval (in unit of TU). */ + rtl_write_word(rtlpriv, BCN_INTERVAL, bcn_interval); + /* 2008.10.24 added by tynli for beacon changed. */ + rtl92s_phy_set_beacon_hwreg(hw, bcn_interval); +} + +void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, "add_msr:%x, rm_msr:%x\n", + add_msr, rm_msr); + + if (add_msr) + rtlpci->irq_mask[0] |= add_msr; + + if (rm_msr) + rtlpci->irq_mask[0] &= (~rm_msr); + + rtl92se_disable_interrupt(hw); + rtl92se_enable_interrupt(hw); +} + +static void _rtl8192se_get_IC_Inferiority(struct ieee80211_hw *hw) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 efuse_id; + + rtlhal->ic_class = IC_INFERIORITY_A; + + /* Only retrieving while using EFUSE. */ + if ((rtlefuse->epromtype == EEPROM_BOOT_EFUSE) && + !rtlefuse->autoload_failflag) { + efuse_id = efuse_read_1byte(hw, EFUSE_IC_ID_OFFSET); + + if (efuse_id == 0xfe) + rtlhal->ic_class = IC_INFERIORITY_B; + } +} + +static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u16 i, usvalue; + u16 eeprom_id; + u8 tempval; + u8 hwinfo[HWSET_MAX_SIZE_92S]; + u8 rf_path, index; + + if (rtlefuse->epromtype == EEPROM_93C46) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "RTL819X Not boot from eeprom, check it !!\n"); + } else if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + rtl_efuse_shadow_map_update(hw); + + memcpy((void *)hwinfo, (void *) + &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + HWSET_MAX_SIZE_92S); + } + + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP", + hwinfo, HWSET_MAX_SIZE_92S); + + eeprom_id = *((u16 *)&hwinfo[0]); + if (eeprom_id != RTL8190_EEPROM_ID) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "EEPROM ID(%#x) is invalid!!\n", eeprom_id); + rtlefuse->autoload_failflag = true; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + } + + if (rtlefuse->autoload_failflag) + return; + + _rtl8192se_get_IC_Inferiority(hw); + + /* Read IC Version && Channel Plan */ + /* VID, DID SE 0xA-D */ + rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; + rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; + rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; + rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; + rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROMId = 0x%4x\n", eeprom_id); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); + + for (i = 0; i < 6; i += 2) { + usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; + *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; + } + + for (i = 0; i < 6; i++) + rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%pM\n", rtlefuse->dev_addr); + + /* Get Tx Power Level by Channel */ + /* Read Tx power of Channel 1 ~ 14 from EEPROM. */ + /* 92S suupport RF A & B */ + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 3; i++) { + /* Read CCK RF A & B Tx power */ + rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][i] = + hwinfo[EEPROM_TXPOWERBASE + rf_path * 3 + i]; + + /* Read OFDM RF A & B Tx power for 1T */ + rtlefuse->eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = + hwinfo[EEPROM_TXPOWERBASE + 6 + rf_path * 3 + i]; + + /* Read OFDM RF A & B Tx power for 2T */ + rtlefuse->eprom_chnl_txpwr_ht40_2sdf[rf_path][i] + = hwinfo[EEPROM_TXPOWERBASE + 12 + + rf_path * 3 + i]; + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + "RF(%d) EEPROM CCK Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse->eeprom_chnlarea_txpwr_cck + [rf_path][i]); + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + "RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse->eeprom_chnlarea_txpwr_ht40_1s + [rf_path][i]); + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse->eprom_chnl_txpwr_ht40_2sdf + [rf_path][i]); + + for (rf_path = 0; rf_path < 2; rf_path++) { + + /* Assign dedicated channel tx power */ + for (i = 0; i < 14; i++) { + /* channel 1~3 use the same Tx Power Level. */ + if (i < 3) + index = 0; + /* Channel 4-8 */ + else if (i < 8) + index = 1; + /* Channel 9-14 */ + else + index = 2; + + /* Record A & B CCK /OFDM - 1T/2T Channel area + * tx power */ + rtlefuse->txpwrlevel_cck[rf_path][i] = + rtlefuse->eeprom_chnlarea_txpwr_cck + [rf_path][index]; + rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = + rtlefuse->eeprom_chnlarea_txpwr_ht40_1s + [rf_path][index]; + rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = + rtlefuse->eprom_chnl_txpwr_ht40_2sdf + [rf_path][index]; + } + + for (i = 0; i < 14; i++) { + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", + rf_path, i, + rtlefuse->txpwrlevel_cck[rf_path][i], + rtlefuse->txpwrlevel_ht40_1s[rf_path][i], + rtlefuse->txpwrlevel_ht40_2s[rf_path][i]); + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 3; i++) { + /* Read Power diff limit. */ + rtlefuse->eeprom_pwrgroup[rf_path][i] = + hwinfo[EEPROM_TXPWRGROUP + rf_path * 3 + i]; + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) { + /* Fill Pwr group */ + for (i = 0; i < 14; i++) { + /* Chanel 1-3 */ + if (i < 3) + index = 0; + /* Channel 4-8 */ + else if (i < 8) + index = 1; + /* Channel 9-13 */ + else + index = 2; + + rtlefuse->pwrgroup_ht20[rf_path][i] = + (rtlefuse->eeprom_pwrgroup[rf_path][index] & + 0xf); + rtlefuse->pwrgroup_ht40[rf_path][i] = + ((rtlefuse->eeprom_pwrgroup[rf_path][index] & + 0xf0) >> 4); + + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-%d pwrgroup_ht20[%d] = 0x%x\n", + rf_path, i, + rtlefuse->pwrgroup_ht20[rf_path][i]); + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-%d pwrgroup_ht40[%d] = 0x%x\n", + rf_path, i, + rtlefuse->pwrgroup_ht40[rf_path][i]); + } + } + + for (i = 0; i < 14; i++) { + /* Read tx power difference between HT OFDM 20/40 MHZ */ + /* channel 1-3 */ + if (i < 3) + index = 0; + /* Channel 4-8 */ + else if (i < 8) + index = 1; + /* Channel 9-14 */ + else + index = 2; + + tempval = hwinfo[EEPROM_TX_PWR_HT20_DIFF + index] & 0xff; + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = + ((tempval >> 4) & 0xF); + + /* Read OFDM<->HT tx power diff */ + /* Channel 1-3 */ + if (i < 3) + index = 0; + /* Channel 4-8 */ + else if (i < 8) + index = 0x11; + /* Channel 9-14 */ + else + index = 1; + + tempval = hwinfo[EEPROM_TX_PWR_OFDM_DIFF + index] & 0xff; + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = + (tempval & 0xF); + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = + ((tempval >> 4) & 0xF); + + tempval = hwinfo[TX_PWR_SAFETY_CHK]; + rtlefuse->txpwr_safetyflag = (tempval & 0x01); + } + + rtlefuse->eeprom_regulatory = 0; + if (rtlefuse->eeprom_version >= 2) { + /* BIT(0)~2 */ + if (rtlefuse->eeprom_version >= 4) + rtlefuse->eeprom_regulatory = + (hwinfo[EEPROM_REGULATORY] & 0x7); + else /* BIT(0) */ + rtlefuse->eeprom_regulatory = + (hwinfo[EEPROM_REGULATORY] & 0x1); + } + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); + + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", + i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", + i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", + i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", + i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); + + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "TxPwrSafetyFlag = %d\n", rtlefuse->txpwr_safetyflag); + + /* Read RF-indication and Tx Power gain + * index diff of legacy to HT OFDM rate. */ + tempval = hwinfo[EEPROM_RFIND_POWERDIFF] & 0xff; + rtlefuse->eeprom_txpowerdiff = tempval; + rtlefuse->legacy_httxpowerdiff = + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][0]; + + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "TxPowerDiff = %#x\n", rtlefuse->eeprom_txpowerdiff); + + /* Get TSSI value for each path. */ + usvalue = *(u16 *)&hwinfo[EEPROM_TSSI_A]; + rtlefuse->eeprom_tssi[RF90_PATH_A] = (u8)((usvalue & 0xff00) >> 8); + usvalue = hwinfo[EEPROM_TSSI_B]; + rtlefuse->eeprom_tssi[RF90_PATH_B] = (u8)(usvalue & 0xff); + + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, "TSSI_A = 0x%x, TSSI_B = 0x%x\n", + rtlefuse->eeprom_tssi[RF90_PATH_A], + rtlefuse->eeprom_tssi[RF90_PATH_B]); + + /* Read antenna tx power offset of B/C/D to A from EEPROM */ + /* and read ThermalMeter from EEPROM */ + tempval = hwinfo[EEPROM_THERMALMETER]; + rtlefuse->eeprom_thermalmeter = tempval; + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); + + /* ThermalMeter, BIT(0)~3 for RFIC1, BIT(4)~7 for RFIC2 */ + rtlefuse->thermalmeter[0] = (rtlefuse->eeprom_thermalmeter & 0x1f); + rtlefuse->tssi_13dbm = rtlefuse->eeprom_thermalmeter * 100; + + /* Read CrystalCap from EEPROM */ + tempval = hwinfo[EEPROM_CRYSTALCAP] >> 4; + rtlefuse->eeprom_crystalcap = tempval; + /* CrystalCap, BIT(12)~15 */ + rtlefuse->crystalcap = rtlefuse->eeprom_crystalcap; + + /* Read IC Version && Channel Plan */ + /* Version ID, Channel plan */ + rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; + rtlefuse->txpwr_fromeprom = true; + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "EEPROM ChannelPlan = 0x%4x\n", rtlefuse->eeprom_channelplan); + + /* Read Customer ID or Board Type!!! */ + tempval = hwinfo[EEPROM_BOARDTYPE]; + /* Change RF type definition */ + if (tempval == 0) + rtlphy->rf_type = RF_2T2R; + else if (tempval == 1) + rtlphy->rf_type = RF_1T2R; + else if (tempval == 2) + rtlphy->rf_type = RF_1T2R; + else if (tempval == 3) + rtlphy->rf_type = RF_1T1R; + + /* 1T2R but 1SS (1x1 receive combining) */ + rtlefuse->b1x1_recvcombine = false; + if (rtlphy->rf_type == RF_1T2R) { + tempval = rtl_read_byte(rtlpriv, 0x07); + if (!(tempval & BIT(0))) { + rtlefuse->b1x1_recvcombine = true; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "RF_TYPE=1T2R but only 1SS\n"); + } + } + rtlefuse->b1ss_support = rtlefuse->b1x1_recvcombine; + rtlefuse->eeprom_oemid = *&hwinfo[EEPROM_CUSTOMID]; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM Customer ID: 0x%2x", + rtlefuse->eeprom_oemid); + + /* set channel paln to world wide 13 */ + rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; +} + +void rtl92se_read_eeprom_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 tmp_u1b = 0; + + tmp_u1b = rtl_read_byte(rtlpriv, EPROM_CMD); + + if (tmp_u1b & BIT(4)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); + rtlefuse->epromtype = EEPROM_93C46; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); + rtlefuse->epromtype = EEPROM_BOOT_EFUSE; + } + + if (tmp_u1b & BIT(5)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + _rtl92se_read_adapter_info(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); + rtlefuse->autoload_failflag = true; + } +} + +static void rtl92se_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 ratr_value; + u8 ratr_index = 0; + u8 nmode = mac->ht_enable; + u8 mimo_ps = IEEE80211_SMPS_OFF; + u16 shortgi_rate = 0; + u32 tmp_ratr_value = 0; + u8 curtxbw_40mhz = mac->bw_40; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = mac->mode; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_value = sta->supp_rates[1] << 4; + else + ratr_value = sta->supp_rates[0]; + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_value = 0xfff; + ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + ratr_value &= 0x0000000D; + break; + case WIRELESS_MODE_G: + ratr_value &= 0x00000FF5; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + nmode = 1; + if (mimo_ps == IEEE80211_SMPS_STATIC) { + ratr_value &= 0x0007F005; + } else { + u32 ratr_mask; + + if (get_rf_type(rtlphy) == RF_1T2R || + get_rf_type(rtlphy) == RF_1T1R) { + if (curtxbw_40mhz) + ratr_mask = 0x000ff015; + else + ratr_mask = 0x000ff005; + } else { + if (curtxbw_40mhz) + ratr_mask = 0x0f0ff015; + else + ratr_mask = 0x0f0ff005; + } + + ratr_value &= ratr_mask; + } + break; + default: + if (rtlphy->rf_type == RF_1T2R) + ratr_value &= 0x000ff0ff; + else + ratr_value &= 0x0f0ff0ff; + + break; + } + + if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) + ratr_value &= 0x0FFFFFFF; + else if (rtlpriv->rtlhal.version == VERSION_8192S_ACUT) + ratr_value &= 0x0FFFFFF0; + + if (nmode && ((curtxbw_40mhz && + curshortgi_40mhz) || (!curtxbw_40mhz && + curshortgi_20mhz))) { + + ratr_value |= 0x10000000; + tmp_ratr_value = (ratr_value >> 12); + + for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { + if ((1 << shortgi_rate) & tmp_ratr_value) + break; + } + + shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | + (shortgi_rate << 4) | (shortgi_rate); + + rtl_write_byte(rtlpriv, SG_RATE, shortgi_rate); + } + + rtl_write_dword(rtlpriv, ARFR0 + ratr_index * 4, ratr_value); + if (ratr_value & 0xfffff000) + rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_REFRESH_N); + else + rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_REFRESH_BG); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n", + rtl_read_dword(rtlpriv, ARFR0)); +} + +static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u32 ratr_bitmap; + u8 ratr_index = 0; + u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = 0; + bool shortgi = false; + u32 ratr_value = 0; + u8 shortgi_rate = 0; + u32 mask = 0; + u32 band = 0; + bool bmulticast = false; + u8 macid = 0; + u8 mimo_ps = IEEE80211_SMPS_OFF; + + sta_entry = (struct rtl_sta_info *) sta->drv_priv; + wirelessmode = sta_entry->wireless_mode; + if (mac->opmode == NL80211_IFTYPE_STATION) + curtxbw_40mhz = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + macid = sta->aid + 1; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_bitmap = sta->supp_rates[1] << 4; + else + ratr_bitmap = sta->supp_rates[0]; + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_bitmap = 0xfff; + ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + band |= WIRELESS_11B; + ratr_index = RATR_INX_WIRELESS_B; + if (ratr_bitmap & 0x0000000c) + ratr_bitmap &= 0x0000000d; + else + ratr_bitmap &= 0x0000000f; + break; + case WIRELESS_MODE_G: + band |= (WIRELESS_11G | WIRELESS_11B); + ratr_index = RATR_INX_WIRELESS_GB; + + if (rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if (rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + break; + case WIRELESS_MODE_A: + band |= WIRELESS_11A; + ratr_index = RATR_INX_WIRELESS_A; + ratr_bitmap &= 0x00000ff0; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + band |= (WIRELESS_11N | WIRELESS_11G | WIRELESS_11B); + ratr_index = RATR_INX_WIRELESS_NGB; + + if (mimo_ps == IEEE80211_SMPS_STATIC) { + if (rssi_level == 1) + ratr_bitmap &= 0x00070000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0007f000; + else + ratr_bitmap &= 0x0007f005; + } else { + if (rtlphy->rf_type == RF_1T2R || + rtlphy->rf_type == RF_1T1R) { + if (rssi_level == 1) { + ratr_bitmap &= 0x000f0000; + } else if (rssi_level == 3) { + ratr_bitmap &= 0x000fc000; + } else if (rssi_level == 5) { + ratr_bitmap &= 0x000ff000; + } else { + if (curtxbw_40mhz) + ratr_bitmap &= 0x000ff015; + else + ratr_bitmap &= 0x000ff005; + } + } else { + if (rssi_level == 1) { + ratr_bitmap &= 0x0f8f0000; + } else if (rssi_level == 3) { + ratr_bitmap &= 0x0f8fc000; + } else if (rssi_level == 5) { + ratr_bitmap &= 0x0f8ff000; + } else { + if (curtxbw_40mhz) + ratr_bitmap &= 0x0f8ff015; + else + ratr_bitmap &= 0x0f8ff005; + } + } + } + + if ((curtxbw_40mhz && curshortgi_40mhz) || + (!curtxbw_40mhz && curshortgi_20mhz)) { + if (macid == 0) + shortgi = true; + else if (macid == 1) + shortgi = false; + } + break; + default: + band |= (WIRELESS_11N | WIRELESS_11G | WIRELESS_11B); + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rtlphy->rf_type == RF_1T2R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0f8ff0ff; + break; + } + sta_entry->ratr_index = ratr_index; + + if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) + ratr_bitmap &= 0x0FFFFFFF; + else if (rtlpriv->rtlhal.version == VERSION_8192S_ACUT) + ratr_bitmap &= 0x0FFFFFF0; + + if (shortgi) { + ratr_bitmap |= 0x10000000; + /* Get MAX MCS available. */ + ratr_value = (ratr_bitmap >> 12); + for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { + if ((1 << shortgi_rate) & ratr_value) + break; + } + + shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | + (shortgi_rate << 4) | (shortgi_rate); + rtl_write_byte(rtlpriv, SG_RATE, shortgi_rate); + } + + mask |= (bmulticast ? 1 : 0) << 9 | (macid & 0x1f) << 4 | (band & 0xf); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_TRACE, "mask = %x, bitmap = %x\n", + mask, ratr_bitmap); + rtl_write_dword(rtlpriv, 0x2c4, ratr_bitmap); + rtl_write_dword(rtlpriv, WFM5, (FW_RA_UPDATE_MASK | (mask << 8))); + + if (macid != 0) + sta_entry->ratr_index = ratr_index; +} + +void rtl92se_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->dm.useramask) + rtl92se_update_hal_rate_mask(hw, sta, rssi_level); + else + rtl92se_update_hal_rate_table(hw, sta); +} + +void rtl92se_update_channel_access_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 sifs_timer; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, + &mac->slot_time); + sifs_timer = 0x0e0e; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); + +} + +/* this ifunction is for RFKILL, it's different with windows, + * because UI will disable wireless when GPIO Radio Off. + * And here we not check or Disable/Enable ASPM like windows*/ +bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + enum rf_pwrstate rfpwr_toset /*, cur_rfstate */; + unsigned long flag = 0; + bool actuallyset = false; + bool turnonbypowerdomain = false; + + /* just 8191se can check gpio before firstup, 92c/92d have fixed it */ + if ((rtlpci->up_first_time == 1) || (rtlpci->being_init_adapter)) + return false; + + if (ppsc->swrf_processing) + return false; + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + if (ppsc->rfchange_inprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + return false; + } else { + ppsc->rfchange_inprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + + /* cur_rfstate = ppsc->rfpwr_state;*/ + + /* because after _rtl92s_phy_set_rfhalt, all power + * closed, so we must open some power for GPIO check, + * or we will always check GPIO RFOFF here, + * And we should close power after GPIO check */ + if (RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + _rtl92se_power_domain_init(hw); + turnonbypowerdomain = true; + } + + rfpwr_toset = _rtl92se_rf_onoff_detect(hw); + + if ((ppsc->hwradiooff) && (rfpwr_toset == ERFON)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "RFKILL-HW Radio ON, RF ON\n"); + + rfpwr_toset = ERFON; + ppsc->hwradiooff = false; + actuallyset = true; + } else if ((!ppsc->hwradiooff) && (rfpwr_toset == ERFOFF)) { + RT_TRACE(rtlpriv, COMP_RF, + DBG_DMESG, "RFKILL-HW Radio OFF, RF OFF\n"); + + rfpwr_toset = ERFOFF; + ppsc->hwradiooff = true; + actuallyset = true; + } + + if (actuallyset) { + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + + /* this not include ifconfig wlan0 down case */ + /* } else if (rfpwr_toset == ERFOFF || cur_rfstate == ERFOFF) { */ + } else { + /* because power_domain_init may be happen when + * _rtl92s_phy_set_rfhalt, this will open some powers + * and cause current increasing about 40 mA for ips, + * rfoff and ifconfig down, so we set + * _rtl92s_phy_set_rfhalt again here */ + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC && + turnonbypowerdomain) { + _rtl92s_phy_set_rfhalt(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } + + spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); + ppsc->rfchange_inprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); + } + + *valid = 1; + return !ppsc->hwradiooff; + +} + +/* Is_wepkey just used for WEP used as group & pairwise key + * if pairwise is AES ang group is WEP Is_wepkey == false.*/ +void rtl92se_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr, + bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 *macaddr = p_macaddr; + + u32 entry_id = 0; + bool is_pairwise = false; + + static u8 cam_const_addr[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} + }; + static u8 cam_const_broad[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (clear_all) { + u8 idx = 0; + u8 cam_offset = 0; + u8 clear_number = 5; + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); + + for (idx = 0; idx < clear_number; idx++) { + rtl_cam_mark_invalid(hw, cam_offset + idx); + rtl_cam_empty_entry(hw, cam_offset + idx); + + if (idx < 5) { + memset(rtlpriv->sec.key_buf[idx], 0, + MAX_KEY_LEN); + rtlpriv->sec.key_len[idx] = 0; + } + } + + } else { + switch (enc_algo) { + case WEP40_ENCRYPTION: + enc_algo = CAM_WEP40; + break; + case WEP104_ENCRYPTION: + enc_algo = CAM_WEP104; + break; + case TKIP_ENCRYPTION: + enc_algo = CAM_TKIP; + break; + case AESCCMP_ENCRYPTION: + enc_algo = CAM_AES; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + enc_algo = CAM_TKIP; + break; + } + + if (is_wepkey || rtlpriv->sec.use_defaultkey) { + macaddr = cam_const_addr[key_index]; + entry_id = key_index; + } else { + if (is_group) { + macaddr = cam_const_broad; + entry_id = key_index; + } else { + if (mac->opmode == NL80211_IFTYPE_AP) { + entry_id = rtl_cam_get_free_entry(hw, + p_macaddr); + if (entry_id >= TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, + COMP_SEC, DBG_EMERG, + "Can not find free hw security cam entry\n"); + return; + } + } else { + entry_id = CAM_PAIRWISE_KEY_POSITION; + } + + key_index = PAIRWISE_KEYIDX; + is_pairwise = true; + } + } + + if (rtlpriv->sec.key_len[key_index] == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "delete one entry, entry_id is %d\n", + entry_id); + if (mac->opmode == NL80211_IFTYPE_AP) + rtl_cam_del_entry(hw, p_macaddr); + rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "add one entry\n"); + if (is_pairwise) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set Pairwise key\n"); + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[key_index]); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set group key\n"); + + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_cam_add_one_entry(hw, + rtlefuse->dev_addr, + PAIRWISE_KEYIDX, + CAM_PAIRWISE_KEY_POSITION, + enc_algo, CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + + } + } +} + +void rtl92se_suspend(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtlpci->up_first_time = true; +} + +void rtl92se_resume(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 val; + + pci_read_config_dword(rtlpci->pdev, 0x40, &val); + if ((val & 0x0000ff00) != 0) + pci_write_config_dword(rtlpci->pdev, 0x40, + val & 0xffff00ff); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h new file mode 100644 index 000000000000..4cacee10f31e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.h @@ -0,0 +1,78 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __REALTEK_PCI92SE_HW_H__ +#define __REALTEK_PCI92SE_HW_H__ + +#define MSR_LINK_MANAGED 2 +#define MSR_LINK_NONE 0 +#define MSR_LINK_SHIFT 0 +#define MSR_LINK_ADHOC 1 +#define MSR_LINK_MASTER 3 + +enum WIRELESS_NETWORK_TYPE { + WIRELESS_11B = 1, + WIRELESS_11G = 2, + WIRELESS_11A = 4, + WIRELESS_11N = 8 +}; + +void rtl92se_get_hw_reg(struct ieee80211_hw *hw, + u8 variable, u8 *val); +void rtl92se_read_eeprom_info(struct ieee80211_hw *hw); +void rtl92se_interrupt_recognized(struct ieee80211_hw *hw, + u32 *inta, u32 *intb); +int rtl92se_hw_init(struct ieee80211_hw *hw); +void rtl92se_card_disable(struct ieee80211_hw *hw); +void rtl92se_enable_interrupt(struct ieee80211_hw *hw); +void rtl92se_disable_interrupt(struct ieee80211_hw *hw); +int rtl92se_set_network_type(struct ieee80211_hw *hw, + enum nl80211_iftype type); +void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); +void rtl92se_set_mac_addr(struct rtl_io *io, const u8 *addr); +void rtl92se_set_qos(struct ieee80211_hw *hw, int aci); +void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw); +void rtl92se_set_beacon_interval(struct ieee80211_hw *hw); +void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); +void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, + u8 *val); +void rtl92se_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); +void rtl92se_update_channel_access_setting(struct ieee80211_hw *hw); +bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, + u8 *valid); +void rtl8192se_gpiobit3_cfg_inputmode(struct ieee80211_hw *hw); +void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw); +void rtl92se_set_key(struct ieee80211_hw *hw, + u32 key_index, u8 *macaddr, bool is_group, + u8 enc_algo, bool is_wepkey, bool clear_all); +void rtl92se_suspend(struct ieee80211_hw *hw); +void rtl92se_resume(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c new file mode 100644 index 000000000000..44949b5cbb87 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c @@ -0,0 +1,151 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "reg.h" +#include "led.h" + +static void _rtl92se_init_led(struct ieee80211_hw *hw, + struct rtl_led *pled, enum rtl_led_pin ledpin) +{ + pled->hw = hw; + pled->ledpin = ledpin; + pled->ledon = false; +} + +void rtl92se_init_sw_leds(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + _rtl92se_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); + _rtl92se_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); +} + +void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u8 ledcfg; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", + LEDCFG, pled->ledpin); + + ledcfg = rtl_read_byte(rtlpriv, LEDCFG); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0xf0); + break; + case LED_PIN_LED1: + rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0x0f); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + pled->ledon = true; +} + +void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + struct rtl_priv *rtlpriv; + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + u8 ledcfg; + + rtlpriv = rtl_priv(hw); + if (!rtlpriv || rtlpriv->max_fw_size) + return; + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", + LEDCFG, pled->ledpin); + + ledcfg = rtl_read_byte(rtlpriv, LEDCFG); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg &= 0xf0; + if (pcipriv->ledctl.led_opendrain) + rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(1))); + else + rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3))); + break; + case LED_PIN_LED1: + ledcfg &= 0x0f; + rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3))); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + pled->ledon = false; +} + +static void _rtl92se_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + switch (ledaction) { + case LED_CTL_POWER_ON: + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + rtl92se_sw_led_on(hw, pLed0); + break; + case LED_CTL_POWER_OFF: + rtl92se_sw_led_off(hw, pLed0); + break; + default: + break; + } +} + +void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && + (ledaction == LED_CTL_TX || + ledaction == LED_CTL_RX || + ledaction == LED_CTL_SITE_SURVEY || + ledaction == LED_CTL_LINK || + ledaction == LED_CTL_NO_LINK || + ledaction == LED_CTL_START_TO_LINK || + ledaction == LED_CTL_POWER_ON)) { + return; + } + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d\n", ledaction); + + _rtl92se_sw_led_control(hw, ledaction); +} + diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h new file mode 100644 index 000000000000..2182dbeb5f32 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __REALTEK_PCI92SE_LED_H__ +#define __REALTEK_PCI92SE_LED_H__ + +void rtl92se_init_sw_leds(struct ieee80211_hw *hw); +void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c new file mode 100644 index 000000000000..4b4612fe2fdb --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c @@ -0,0 +1,1658 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../ps.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "fw.h" +#include "hw.h" +#include "table.h" + +static u32 _rtl92s_phy_calculate_bit_shift(u32 bitmask) +{ + u32 i; + + for (i = 0; i <= 31; i++) { + if (((bitmask >> i) & 0x1) == 1) + break; + } + + return i; +} + +u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 returnvalue = 0, originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n", + regaddr, bitmask); + + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); + returnvalue = (originalvalue & bitmask) >> bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "BBR MASK=0x%x Addr[0x%x]=0x%x\n", + bitmask, regaddr, originalvalue); + + return returnvalue; + +} + +void rtl92s_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, + u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); + + if (bitmask != MASKDWORD) { + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); + data = ((originalvalue & (~bitmask)) | (data << bitshift)); + } + + rtl_write_dword(rtlpriv, regaddr, data); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); + +} + +static u32 _rtl92s_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset) +{ + + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + u32 newoffset; + u32 tmplong, tmplong2; + u8 rfpi_enable = 0; + u32 retvalue = 0; + + offset &= 0x3f; + newoffset = offset; + + tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); + + if (rfpath == RF90_PATH_A) + tmplong2 = tmplong; + else + tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); + + tmplong2 = (tmplong2 & (~BLSSI_READADDRESS)) | (newoffset << 23) | + BLSSI_READEDGE; + + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, + tmplong & (~BLSSI_READEDGE)); + + mdelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); + mdelay(1); + + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, tmplong | + BLSSI_READEDGE); + mdelay(1); + + if (rfpath == RF90_PATH_A) + rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, + BIT(8)); + else if (rfpath == RF90_PATH_B) + rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, + BIT(8)); + + if (rfpi_enable) + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, + BLSSI_READBACK_DATA); + else + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, + BLSSI_READBACK_DATA); + + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, + BLSSI_READBACK_DATA); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf_rb, retvalue); + + return retvalue; + +} + +static void _rtl92s_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + u32 data_and_addr = 0; + u32 newoffset; + + offset &= 0x3f; + newoffset = offset; + + data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; + rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf3wire_offset, data_and_addr); +} + + +u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, readback_value, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", + regaddr, rfpath, bitmask); + + spin_lock(&rtlpriv->locks.rf_lock); + + original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr); + + bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); + readback_value = (original_value & bitmask) >> bitshift; + + spin_unlock(&rtlpriv->locks.rf_lock); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", + regaddr, rfpath, bitmask, original_value); + + return readback_value; +} + +void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 original_value, bitshift; + + if (!((rtlphy->rf_pathmap >> rfpath) & 0x1)) + return; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); + + spin_lock(&rtlpriv->locks.rf_lock); + + if (bitmask != RFREG_OFFSET_MASK) { + original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, + regaddr); + bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); + data = ((original_value & (~bitmask)) | (data << bitshift)); + } + + _rtl92s_phy_rf_serial_write(hw, rfpath, regaddr, data); + + spin_unlock(&rtlpriv->locks.rf_lock); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); + +} + +void rtl92s_phy_scan_operation_backup(struct ieee80211_hw *hw, + u8 operation) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (!is_hal_stop(rtlhal)) { + switch (operation) { + case SCAN_OPT_BACKUP: + rtl92s_phy_set_fw_cmd(hw, FW_CMD_PAUSE_DM_BY_SCAN); + break; + case SCAN_OPT_RESTORE: + rtl92s_phy_set_fw_cmd(hw, FW_CMD_RESUME_DM_BY_SCAN); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Unknown operation\n"); + break; + } + } +} + +void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 reg_bw_opmode; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz"); + + if (rtlphy->set_bwmode_inprogress) + return; + if (is_hal_stop(rtlhal)) + return; + + rtlphy->set_bwmode_inprogress = true; + + reg_bw_opmode = rtl_read_byte(rtlpriv, BW_OPMODE); + /* dummy read */ + rtl_read_byte(rtlpriv, RRSR + 2); + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); + break; + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + + if (rtlhal->version >= VERSION_8192S_BCUT) + rtl_write_byte(rtlpriv, RFPGA0_ANALOGPARAMETER2, 0x58); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); + + if (rtlhal->version >= VERSION_8192S_BCUT) + rtl_write_byte(rtlpriv, RFPGA0_ANALOGPARAMETER2, 0x18); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + + rtl92s_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); +} + +static bool _rtl92s_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, u32 cmdtablesz, enum swchnlcmd_id cmdid, + u32 para1, u32 para2, u32 msdelay) +{ + struct swchnlcmd *pcmd; + + if (cmdtable == NULL) { + RT_ASSERT(false, "cmdtable cannot be NULL\n"); + return false; + } + + if (cmdtableidx >= cmdtablesz) + return false; + + pcmd = cmdtable + cmdtableidx; + pcmd->cmdid = cmdid; + pcmd->para1 = para1; + pcmd->para2 = para2; + pcmd->msdelay = msdelay; + + return true; +} + +static bool _rtl92s_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, u32 *delay) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; + u32 precommoncmdcnt; + struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; + u32 postcommoncmdcnt; + struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; + u32 rfdependcmdcnt; + struct swchnlcmd *currentcmd = NULL; + u8 rfpath; + u8 num_total_rfpath = rtlphy->num_total_rfpath; + + precommoncmdcnt = 0; + _rtl92s_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); + _rtl92s_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); + + postcommoncmdcnt = 0; + + _rtl92s_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, + MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); + + rfdependcmdcnt = 0; + + RT_ASSERT((channel >= 1 && channel <= 14), + "invalid channel for Zebra: %d\n", channel); + + _rtl92s_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, + RF_CHNLBW, channel, 10); + + _rtl92s_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, 0); + + do { + switch (*stage) { + case 0: + currentcmd = &precommoncmd[*step]; + break; + case 1: + currentcmd = &rfdependcmd[*step]; + break; + case 2: + currentcmd = &postcommoncmd[*step]; + break; + default: + return true; + } + + if (currentcmd->cmdid == CMDID_END) { + if ((*stage) == 2) { + return true; + } else { + (*stage)++; + (*step) = 0; + continue; + } + } + + switch (currentcmd->cmdid) { + case CMDID_SET_TXPOWEROWER_LEVEL: + rtl92s_phy_set_txpower(hw, channel); + break; + case CMDID_WRITEPORT_ULONG: + rtl_write_dword(rtlpriv, currentcmd->para1, + currentcmd->para2); + break; + case CMDID_WRITEPORT_USHORT: + rtl_write_word(rtlpriv, currentcmd->para1, + (u16)currentcmd->para2); + break; + case CMDID_WRITEPORT_UCHAR: + rtl_write_byte(rtlpriv, currentcmd->para1, + (u8)currentcmd->para2); + break; + case CMDID_RF_WRITEREG: + for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { + rtlphy->rfreg_chnlval[rfpath] = + ((rtlphy->rfreg_chnlval[rfpath] & + 0xfffffc00) | currentcmd->para2); + rtl_set_rfreg(hw, (enum radio_path)rfpath, + currentcmd->para1, + RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[rfpath]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + break; + } + + break; + } while (true); + + (*delay) = currentcmd->msdelay; + (*step)++; + return false; +} + +u8 rtl92s_phy_sw_chnl(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 delay; + bool ret; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "switch to channel%d\n", + rtlphy->current_channel); + + if (rtlphy->sw_chnl_inprogress) + return 0; + + if (rtlphy->set_bwmode_inprogress) + return 0; + + if (is_hal_stop(rtlhal)) + return 0; + + rtlphy->sw_chnl_inprogress = true; + rtlphy->sw_chnl_stage = 0; + rtlphy->sw_chnl_step = 0; + + do { + if (!rtlphy->sw_chnl_inprogress) + break; + + ret = _rtl92s_phy_sw_chnl_step_by_step(hw, + rtlphy->current_channel, + &rtlphy->sw_chnl_stage, + &rtlphy->sw_chnl_step, &delay); + if (!ret) { + if (delay > 0) + mdelay(delay); + else + continue; + } else { + rtlphy->sw_chnl_inprogress = false; + } + break; + } while (true); + + rtlphy->sw_chnl_inprogress = false; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); + + return 1; +} + +static void _rtl92se_phy_set_rf_sleep(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1btmp; + + u1btmp = rtl_read_byte(rtlpriv, LDOV12D_CTRL); + u1btmp |= BIT(0); + + rtl_write_byte(rtlpriv, LDOV12D_CTRL, u1btmp); + rtl_write_byte(rtlpriv, SPS1_CTRL, 0x0); + rtl_write_byte(rtlpriv, TXPAUSE, 0xFF); + rtl_write_word(rtlpriv, CMDR, 0x57FC); + udelay(100); + + rtl_write_word(rtlpriv, CMDR, 0x77FC); + rtl_write_byte(rtlpriv, PHY_CCA, 0x0); + udelay(10); + + rtl_write_word(rtlpriv, CMDR, 0x37FC); + udelay(10); + + rtl_write_word(rtlpriv, CMDR, 0x77FC); + udelay(10); + + rtl_write_word(rtlpriv, CMDR, 0x57FC); + + /* we should chnge GPIO to input mode + * this will drop away current about 25mA*/ + rtl8192se_gpiobit3_cfg_inputmode(hw); +} + +bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = true; + u8 i, queue_id; + struct rtl8192_tx_ring *ring = NULL; + + if (rfpwr_state == ppsc->rfpwr_state) + return false; + + switch (rfpwr_state) { + case ERFON:{ + if ((ppsc->rfpwr_state == ERFOFF) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + + bool rtstatus; + u32 InitializeCount = 0; + do { + InitializeCount++; + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic enable\n"); + rtstatus = rtl_ps_enable_nic(hw); + } while (!rtstatus && (InitializeCount < 10)); + + RT_CLEAR_PS_LEVEL(ppsc, + RT_RF_OFF_LEVL_HALT_NIC); + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "awake, sleeped:%d ms state_inap:%x\n", + jiffies_to_msecs(jiffies - + ppsc-> + last_sleep_jiffies), + rtlpriv->psc.state_inap); + ppsc->last_awake_jiffies = jiffies; + rtl_write_word(rtlpriv, CMDR, 0x37FC); + rtl_write_byte(rtlpriv, TXPAUSE, 0x00); + rtl_write_byte(rtlpriv, PHY_CCA, 0x3); + } + + if (mac->link_state == MAC80211_LINKED) + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_LINK); + else + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + break; + } + case ERFOFF:{ + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic disable\n"); + rtl_ps_disable_nic(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } else { + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + else + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_POWER_OFF); + } + break; + } + case ERFSLEEP: + if (ppsc->rfpwr_state == ERFOFF) + return false; + + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (skb_queue_len(&ring->queue) == 0 || + queue_id == BEACON_QUEUE) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] = %d before doze!\n", + i + 1, queue_id, + skb_queue_len(&ring->queue)); + + udelay(10); + i++; + } + + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "ERFOFF: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "Set ERFSLEEP awaked:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc->last_awake_jiffies)); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "sleep awaked:%d ms state_inap:%x\n", + jiffies_to_msecs(jiffies - + ppsc->last_awake_jiffies), + rtlpriv->psc.state_inap); + ppsc->last_sleep_jiffies = jiffies; + _rtl92se_phy_set_rf_sleep(hw); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not processed\n"); + bresult = false; + break; + } + + if (bresult) + ppsc->rfpwr_state = rfpwr_state; + + return bresult; +} + +static bool _rtl92s_phy_config_rfpa_bias_current(struct ieee80211_hw *hw, + enum radio_path rfpath) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool rtstatus = true; + u32 tmpval = 0; + + /* If inferiority IC, we have to increase the PA bias current */ + if (rtlhal->ic_class != IC_INFERIORITY_A) { + tmpval = rtl92s_phy_query_rf_reg(hw, rfpath, RF_IPA, 0xf); + rtl92s_phy_set_rf_reg(hw, rfpath, RF_IPA, 0xf, tmpval + 1); + } + + return rtstatus; +} + +static void _rtl92s_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, + u32 reg_addr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + int index; + + if (reg_addr == RTXAGC_RATE18_06) + index = 0; + else if (reg_addr == RTXAGC_RATE54_24) + index = 1; + else if (reg_addr == RTXAGC_CCK_MCS32) + index = 6; + else if (reg_addr == RTXAGC_MCS03_MCS00) + index = 2; + else if (reg_addr == RTXAGC_MCS07_MCS04) + index = 3; + else if (reg_addr == RTXAGC_MCS11_MCS08) + index = 4; + else if (reg_addr == RTXAGC_MCS15_MCS12) + index = 5; + else + return; + + rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data; + if (index == 5) + rtlphy->pwrgroup_cnt++; +} + +static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + /*RF Interface Sowrtware Control */ + rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; + + /* RF Interface Readback Value */ + rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; + + /* RF Interface Output (and Enable) */ + rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_C].rfintfo = RFPGA0_XC_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_D].rfintfo = RFPGA0_XD_RFINTERFACEOE; + + /* RF Interface (Output and) Enable */ + rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_C].rfintfe = RFPGA0_XC_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_D].rfintfe = RFPGA0_XD_RFINTERFACEOE; + + /* Addr of LSSI. Wirte RF register by driver */ + rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = + RFPGA0_XA_LSSIPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = + RFPGA0_XB_LSSIPARAMETER; + rtlphy->phyreg_def[RF90_PATH_C].rf3wire_offset = + RFPGA0_XC_LSSIPARAMETER; + rtlphy->phyreg_def[RF90_PATH_D].rf3wire_offset = + RFPGA0_XD_LSSIPARAMETER; + + /* RF parameter */ + rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; + + /* Tx AGC Gain Stage (same for all path. Should we remove this?) */ + rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; + + /* Tranceiver A~D HSSI Parameter-1 */ + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; + rtlphy->phyreg_def[RF90_PATH_C].rfhssi_para1 = RFPGA0_XC_HSSIPARAMETER1; + rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para1 = RFPGA0_XD_HSSIPARAMETER1; + + /* Tranceiver A~D HSSI Parameter-2 */ + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; + rtlphy->phyreg_def[RF90_PATH_C].rfhssi_para2 = RFPGA0_XC_HSSIPARAMETER2; + rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para2 = RFPGA0_XD_HSSIPARAMETER2; + + /* RF switch Control */ + rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; + + /* AGC control 1 */ + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; + + /* AGC control 2 */ + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; + + /* RX AFE control 1 */ + rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; + + /* RX AFE control 1 */ + rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; + + /* Tx AFE control 1 */ + rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE; + + /* Tx AFE control 2 */ + rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; + + /* Tranceiver LSSI Readback */ + rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK; + + /* Tranceiver LSSI Readback PI mode */ + rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVERA_HSPI_READBACK; + rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVERB_HSPI_READBACK; +} + + +static bool _rtl92s_phy_config_bb(struct ieee80211_hw *hw, u8 configtype) +{ + int i; + u32 *phy_reg_table; + u32 *agc_table; + u16 phy_reg_len, agc_len; + + agc_len = AGCTAB_ARRAYLENGTH; + agc_table = rtl8192seagctab_array; + /* Default RF_type: 2T2R */ + phy_reg_len = PHY_REG_2T2RARRAYLENGTH; + phy_reg_table = rtl8192sephy_reg_2t2rarray; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_reg_len; i = i + 2) { + rtl_addr_delay(phy_reg_table[i]); + + /* Add delay for ECS T20 & LG malow platform, */ + udelay(1); + + rtl92s_phy_set_bb_reg(hw, phy_reg_table[i], MASKDWORD, + phy_reg_table[i + 1]); + } + } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { + for (i = 0; i < agc_len; i = i + 2) { + rtl92s_phy_set_bb_reg(hw, agc_table[i], MASKDWORD, + agc_table[i + 1]); + + /* Add delay for ECS T20 & LG malow platform */ + udelay(1); + } + } + + return true; +} + +static bool _rtl92s_phy_set_bb_to_diff_rf(struct ieee80211_hw *hw, + u8 configtype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 *phy_regarray2xtxr_table; + u16 phy_regarray2xtxr_len; + int i; + + if (rtlphy->rf_type == RF_1T1R) { + phy_regarray2xtxr_table = rtl8192sephy_changeto_1t1rarray; + phy_regarray2xtxr_len = PHY_CHANGETO_1T1RARRAYLENGTH; + } else if (rtlphy->rf_type == RF_1T2R) { + phy_regarray2xtxr_table = rtl8192sephy_changeto_1t2rarray; + phy_regarray2xtxr_len = PHY_CHANGETO_1T2RARRAYLENGTH; + } else { + return false; + } + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_regarray2xtxr_len; i = i + 3) { + rtl_addr_delay(phy_regarray2xtxr_table[i]); + + rtl92s_phy_set_bb_reg(hw, phy_regarray2xtxr_table[i], + phy_regarray2xtxr_table[i + 1], + phy_regarray2xtxr_table[i + 2]); + } + } + + return true; +} + +static bool _rtl92s_phy_config_bb_with_pg(struct ieee80211_hw *hw, + u8 configtype) +{ + int i; + u32 *phy_table_pg; + u16 phy_pg_len; + + phy_pg_len = PHY_REG_ARRAY_PGLENGTH; + phy_table_pg = rtl8192sephy_reg_array_pg; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_pg_len; i = i + 3) { + rtl_addr_delay(phy_table_pg[i]); + + _rtl92s_store_pwrindex_diffrate_offset(hw, + phy_table_pg[i], + phy_table_pg[i + 1], + phy_table_pg[i + 2]); + rtl92s_phy_set_bb_reg(hw, phy_table_pg[i], + phy_table_pg[i + 1], + phy_table_pg[i + 2]); + } + } + + return true; +} + +static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + bool rtstatus = true; + + /* 1. Read PHY_REG.TXT BB INIT!! */ + /* We will separate as 1T1R/1T2R/1T2R_GREEN/2T2R */ + if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_2T2R || + rtlphy->rf_type == RF_1T1R || rtlphy->rf_type == RF_2T2R_GREEN) { + rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_PHY_REG); + + if (rtlphy->rf_type != RF_2T2R && + rtlphy->rf_type != RF_2T2R_GREEN) + /* so we should reconfig BB reg with the right + * PHY parameters. */ + rtstatus = _rtl92s_phy_set_bb_to_diff_rf(hw, + BASEBAND_CONFIG_PHY_REG); + } else { + rtstatus = false; + } + + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + "Write BB Reg Fail!!\n"); + goto phy_BB8190_Config_ParaFile_Fail; + } + + /* 2. If EEPROM or EFUSE autoload OK, We must config by + * PHY_REG_PG.txt */ + if (rtlefuse->autoload_failflag == false) { + rtlphy->pwrgroup_cnt = 0; + + rtstatus = _rtl92s_phy_config_bb_with_pg(hw, + BASEBAND_CONFIG_PHY_REG); + } + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + "_rtl92s_phy_bb_config_parafile(): BB_PG Reg Fail!!\n"); + goto phy_BB8190_Config_ParaFile_Fail; + } + + /* 3. BB AGC table Initialization */ + rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_AGC_TAB); + + if (!rtstatus) { + pr_err("%s(): AGC Table Fail\n", __func__); + goto phy_BB8190_Config_ParaFile_Fail; + } + + /* Check if the CCK HighPower is turned ON. */ + /* This is used to calculate PWDB. */ + rtlphy->cck_high_power = (bool)(rtl92s_phy_query_bb_reg(hw, + RFPGA0_XA_HSSIPARAMETER2, 0x200)); + +phy_BB8190_Config_ParaFile_Fail: + return rtstatus; +} + +u8 rtl92s_phy_config_rf(struct ieee80211_hw *hw, enum radio_path rfpath) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + int i; + bool rtstatus = true; + u32 *radio_a_table; + u32 *radio_b_table; + u16 radio_a_tblen, radio_b_tblen; + + radio_a_tblen = RADIOA_1T_ARRAYLENGTH; + radio_a_table = rtl8192seradioa_1t_array; + + /* Using Green mode array table for RF_2T2R_GREEN */ + if (rtlphy->rf_type == RF_2T2R_GREEN) { + radio_b_table = rtl8192seradiob_gm_array; + radio_b_tblen = RADIOB_GM_ARRAYLENGTH; + } else { + radio_b_table = rtl8192seradiob_array; + radio_b_tblen = RADIOB_ARRAYLENGTH; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); + rtstatus = true; + + switch (rfpath) { + case RF90_PATH_A: + for (i = 0; i < radio_a_tblen; i = i + 2) { + rtl_rfreg_delay(hw, rfpath, radio_a_table[i], + MASK20BITS, radio_a_table[i + 1]); + + } + + /* PA Bias current for inferiority IC */ + _rtl92s_phy_config_rfpa_bias_current(hw, rfpath); + break; + case RF90_PATH_B: + for (i = 0; i < radio_b_tblen; i = i + 2) { + rtl_rfreg_delay(hw, rfpath, radio_b_table[i], + MASK20BITS, radio_b_table[i + 1]); + } + break; + case RF90_PATH_C: + ; + break; + case RF90_PATH_D: + ; + break; + default: + break; + } + + return rtstatus; +} + + +bool rtl92s_phy_mac_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + u32 arraylength; + u32 *ptraArray; + + arraylength = MAC_2T_ARRAYLENGTH; + ptraArray = rtl8192semac_2t_array; + + for (i = 0; i < arraylength; i = i + 2) + rtl_write_byte(rtlpriv, ptraArray[i], (u8)ptraArray[i + 1]); + + return true; +} + + +bool rtl92s_phy_bb_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + bool rtstatus = true; + u8 pathmap, index, rf_num = 0; + u8 path1, path2; + + _rtl92s_phy_init_register_definition(hw); + + /* Config BB and AGC */ + rtstatus = _rtl92s_phy_bb_config_parafile(hw); + + + /* Check BB/RF confiuration setting. */ + /* We only need to configure RF which is turned on. */ + path1 = (u8)(rtl92s_phy_query_bb_reg(hw, RFPGA0_TXINFO, 0xf)); + mdelay(10); + path2 = (u8)(rtl92s_phy_query_bb_reg(hw, ROFDM0_TRXPATHENABLE, 0xf)); + pathmap = path1 | path2; + + rtlphy->rf_pathmap = pathmap; + for (index = 0; index < 4; index++) { + if ((pathmap >> index) & 0x1) + rf_num++; + } + + if ((rtlphy->rf_type == RF_1T1R && rf_num != 1) || + (rtlphy->rf_type == RF_1T2R && rf_num != 2) || + (rtlphy->rf_type == RF_2T2R && rf_num != 2) || + (rtlphy->rf_type == RF_2T2R_GREEN && rf_num != 2)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + "RF_Type(%x) does not match RF_Num(%x)!!\n", + rtlphy->rf_type, rf_num); + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, + "path1 0x%x, path2 0x%x, pathmap 0x%x\n", + path1, path2, pathmap); + } + + return rtstatus; +} + +bool rtl92s_phy_rf_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + /* Initialize general global value */ + if (rtlphy->rf_type == RF_1T1R) + rtlphy->num_total_rfpath = 1; + else + rtlphy->num_total_rfpath = 2; + + /* Config BB and RF */ + return rtl92s_phy_rf6052_config(hw); +} + +void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + /* read rx initial gain */ + rtlphy->default_initialgain[0] = rtl_get_bbreg(hw, + ROFDM0_XAAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[1] = rtl_get_bbreg(hw, + ROFDM0_XBAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[2] = rtl_get_bbreg(hw, + ROFDM0_XCAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[3] = rtl_get_bbreg(hw, + ROFDM0_XDAGCCORE1, MASKBYTE0); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n", + rtlphy->default_initialgain[0], + rtlphy->default_initialgain[1], + rtlphy->default_initialgain[2], + rtlphy->default_initialgain[3]); + + /* read framesync */ + rtlphy->framesync = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, MASKBYTE0); + rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, + MASKDWORD); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Default framesync (0x%x) = 0x%x\n", + ROFDM0_RXDETECTOR3, rtlphy->framesync); + +} + +static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel, + u8 *cckpowerlevel, u8 *ofdmpowerLevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 index = (channel - 1); + + /* 1. CCK */ + /* RF-A */ + cckpowerlevel[0] = rtlefuse->txpwrlevel_cck[0][index]; + /* RF-B */ + cckpowerlevel[1] = rtlefuse->txpwrlevel_cck[1][index]; + + /* 2. OFDM for 1T or 2T */ + if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) { + /* Read HT 40 OFDM TX power */ + ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_1s[0][index]; + ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_1s[1][index]; + } else if (rtlphy->rf_type == RF_2T2R) { + /* Read HT 40 OFDM TX power */ + ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index]; + ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index]; + } else { + ofdmpowerLevel[0] = 0; + ofdmpowerLevel[1] = 0; + } +} + +static void _rtl92s_phy_ccxpower_indexcheck(struct ieee80211_hw *hw, + u8 channel, u8 *cckpowerlevel, u8 *ofdmpowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; + rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; +} + +void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + /* [0]:RF-A, [1]:RF-B */ + u8 cckpowerlevel[2], ofdmpowerLevel[2]; + + if (!rtlefuse->txpwr_fromeprom) + return; + + /* Mainly we use RF-A Tx Power to write the Tx Power registers, + * but the RF-B Tx Power must be calculated by the antenna diff. + * So we have to rewrite Antenna gain offset register here. + * Please refer to BB register 0x80c + * 1. For CCK. + * 2. For OFDM 1T or 2T */ + _rtl92s_phy_get_txpower_index(hw, channel, &cckpowerlevel[0], + &ofdmpowerLevel[0]); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Channel-%d, cckPowerLevel (A / B) = 0x%x / 0x%x, ofdmPowerLevel (A / B) = 0x%x / 0x%x\n", + channel, cckpowerlevel[0], cckpowerlevel[1], + ofdmpowerLevel[0], ofdmpowerLevel[1]); + + _rtl92s_phy_ccxpower_indexcheck(hw, channel, &cckpowerlevel[0], + &ofdmpowerLevel[0]); + + rtl92s_phy_rf6052_set_ccktxpower(hw, cckpowerlevel[0]); + rtl92s_phy_rf6052_set_ofdmtxpower(hw, &ofdmpowerLevel[0], channel); + +} + +void rtl92s_phy_chk_fwcmd_iodone(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 pollingcnt = 10000; + u32 tmpvalue; + + /* Make sure that CMD IO has be accepted by FW. */ + do { + udelay(10); + + tmpvalue = rtl_read_dword(rtlpriv, WFM5); + if (tmpvalue == 0) + break; + } while (--pollingcnt); + + if (pollingcnt == 0) + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Set FW Cmd fail!!\n"); +} + + +static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 input, current_aid = 0; + + if (is_hal_stop(rtlhal)) + return; + + if (hal_get_firmwareversion(rtlpriv) < 0x34) + goto skip; + /* We re-map RA related CMD IO to combinational ones */ + /* if FW version is v.52 or later. */ + switch (rtlhal->current_fwcmd_io) { + case FW_CMD_RA_REFRESH_N: + rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_N_COMB; + break; + case FW_CMD_RA_REFRESH_BG: + rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_BG_COMB; + break; + default: + break; + } + +skip: + switch (rtlhal->current_fwcmd_io) { + case FW_CMD_RA_RESET: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_RESET\n"); + rtl_write_dword(rtlpriv, WFM5, FW_RA_RESET); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_RA_ACTIVE: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_ACTIVE\n"); + rtl_write_dword(rtlpriv, WFM5, FW_RA_ACTIVE); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_RA_REFRESH_N: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_REFRESH_N\n"); + input = FW_RA_REFRESH; + rtl_write_dword(rtlpriv, WFM5, input); + rtl92s_phy_chk_fwcmd_iodone(hw); + rtl_write_dword(rtlpriv, WFM5, FW_RA_ENABLE_RSSI_MASK); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_RA_REFRESH_BG: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + "FW_CMD_RA_REFRESH_BG\n"); + rtl_write_dword(rtlpriv, WFM5, FW_RA_REFRESH); + rtl92s_phy_chk_fwcmd_iodone(hw); + rtl_write_dword(rtlpriv, WFM5, FW_RA_DISABLE_RSSI_MASK); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_RA_REFRESH_N_COMB: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + "FW_CMD_RA_REFRESH_N_COMB\n"); + input = FW_RA_IOT_N_COMB; + rtl_write_dword(rtlpriv, WFM5, input); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_RA_REFRESH_BG_COMB: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, + "FW_CMD_RA_REFRESH_BG_COMB\n"); + input = FW_RA_IOT_BG_COMB; + rtl_write_dword(rtlpriv, WFM5, input); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_IQK_ENABLE: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_IQK_ENABLE\n"); + rtl_write_dword(rtlpriv, WFM5, FW_IQK_ENABLE); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_PAUSE_DM_BY_SCAN: + /* Lower initial gain */ + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, 0x17); + rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, 0x17); + /* CCA threshold */ + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x40); + break; + case FW_CMD_RESUME_DM_BY_SCAN: + /* CCA threshold */ + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); + rtl92s_phy_set_txpower(hw, rtlphy->current_channel); + break; + case FW_CMD_HIGH_PWR_DISABLE: + if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) + break; + + /* Lower initial gain */ + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, 0x17); + rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, 0x17); + /* CCA threshold */ + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x40); + break; + case FW_CMD_HIGH_PWR_ENABLE: + if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) || + rtlpriv->dm.dynamic_txpower_enable) + break; + + /* CCA threshold */ + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); + break; + case FW_CMD_LPS_ENTER: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_LPS_ENTER\n"); + current_aid = rtlpriv->mac80211.assoc_id; + rtl_write_dword(rtlpriv, WFM5, (FW_LPS_ENTER | + ((current_aid | 0xc000) << 8))); + rtl92s_phy_chk_fwcmd_iodone(hw); + /* FW set TXOP disable here, so disable EDCA + * turbo mode until driver leave LPS */ + break; + case FW_CMD_LPS_LEAVE: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_LPS_LEAVE\n"); + rtl_write_dword(rtlpriv, WFM5, FW_LPS_LEAVE); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_ADD_A2_ENTRY: + RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_ADD_A2_ENTRY\n"); + rtl_write_dword(rtlpriv, WFM5, FW_ADD_A2_ENTRY); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + case FW_CMD_CTRL_DM_BY_DRIVER: + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "FW_CMD_CTRL_DM_BY_DRIVER\n"); + rtl_write_dword(rtlpriv, WFM5, FW_CTRL_DM_BY_DRIVER); + rtl92s_phy_chk_fwcmd_iodone(hw); + break; + + default: + break; + } + + rtl92s_phy_chk_fwcmd_iodone(hw); + + /* Clear FW CMD operation flag. */ + rtlhal->set_fwcmd_inprogress = false; +} + +bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *digtable = &rtlpriv->dm_digtable; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 fw_param = FW_CMD_IO_PARA_QUERY(rtlpriv); + u16 fw_cmdmap = FW_CMD_IO_QUERY(rtlpriv); + bool postprocessing = false; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n", + fw_cmdio, rtlhal->set_fwcmd_inprogress); + + do { + /* We re-map to combined FW CMD ones if firmware version */ + /* is v.53 or later. */ + if (hal_get_firmwareversion(rtlpriv) >= 0x35) { + switch (fw_cmdio) { + case FW_CMD_RA_REFRESH_N: + fw_cmdio = FW_CMD_RA_REFRESH_N_COMB; + break; + case FW_CMD_RA_REFRESH_BG: + fw_cmdio = FW_CMD_RA_REFRESH_BG_COMB; + break; + default: + break; + } + } else { + if ((fw_cmdio == FW_CMD_IQK_ENABLE) || + (fw_cmdio == FW_CMD_RA_REFRESH_N) || + (fw_cmdio == FW_CMD_RA_REFRESH_BG)) { + postprocessing = true; + break; + } + } + + /* If firmware version is v.62 or later, + * use FW_CMD_IO_SET for FW_CMD_CTRL_DM_BY_DRIVER */ + if (hal_get_firmwareversion(rtlpriv) >= 0x3E) { + if (fw_cmdio == FW_CMD_CTRL_DM_BY_DRIVER) + fw_cmdio = FW_CMD_CTRL_DM_BY_DRIVER_NEW; + } + + + /* We shall revise all FW Cmd IO into Reg0x364 + * DM map table in the future. */ + switch (fw_cmdio) { + case FW_CMD_RA_INIT: + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "RA init!!\n"); + fw_cmdmap |= FW_RA_INIT_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + /* Clear control flag to sync with FW. */ + FW_CMD_IO_CLR(rtlpriv, FW_RA_INIT_CTL); + break; + case FW_CMD_DIG_DISABLE: + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Set DIG disable!!\n"); + fw_cmdmap &= ~FW_DIG_ENABLE_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + break; + case FW_CMD_DIG_ENABLE: + case FW_CMD_DIG_RESUME: + if (!(rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE)) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Set DIG enable or resume!!\n"); + fw_cmdmap |= (FW_DIG_ENABLE_CTL | FW_SS_CTL); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + } + break; + case FW_CMD_DIG_HALT: + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Set DIG halt!!\n"); + fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | FW_SS_CTL); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + break; + case FW_CMD_TXPWR_TRACK_THERMAL: { + u8 thermalval = 0; + fw_cmdmap |= FW_PWR_TRK_CTL; + + /* Clear FW parameter in terms of thermal parts. */ + fw_param &= FW_PWR_TRK_PARAM_CLR; + + thermalval = rtlpriv->dm.thermalvalue; + fw_param |= ((thermalval << 24) | + (rtlefuse->thermalmeter[0] << 16)); + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Set TxPwr tracking!! FwCmdMap(%#x), FwParam(%#x)\n", + fw_cmdmap, fw_param); + + FW_CMD_PARA_SET(rtlpriv, fw_param); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + + /* Clear control flag to sync with FW. */ + FW_CMD_IO_CLR(rtlpriv, FW_PWR_TRK_CTL); + } + break; + /* The following FW CMDs are only compatible to + * v.53 or later. */ + case FW_CMD_RA_REFRESH_N_COMB: + fw_cmdmap |= FW_RA_N_CTL; + + /* Clear RA BG mode control. */ + fw_cmdmap &= ~(FW_RA_BG_CTL | FW_RA_INIT_CTL); + + /* Clear FW parameter in terms of RA parts. */ + fw_param &= FW_RA_PARAM_CLR; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "[FW CMD] [New Version] Set RA/IOT Comb in n mode!! FwCmdMap(%#x), FwParam(%#x)\n", + fw_cmdmap, fw_param); + + FW_CMD_PARA_SET(rtlpriv, fw_param); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + + /* Clear control flag to sync with FW. */ + FW_CMD_IO_CLR(rtlpriv, FW_RA_N_CTL); + break; + case FW_CMD_RA_REFRESH_BG_COMB: + fw_cmdmap |= FW_RA_BG_CTL; + + /* Clear RA n-mode control. */ + fw_cmdmap &= ~(FW_RA_N_CTL | FW_RA_INIT_CTL); + /* Clear FW parameter in terms of RA parts. */ + fw_param &= FW_RA_PARAM_CLR; + + FW_CMD_PARA_SET(rtlpriv, fw_param); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + + /* Clear control flag to sync with FW. */ + FW_CMD_IO_CLR(rtlpriv, FW_RA_BG_CTL); + break; + case FW_CMD_IQK_ENABLE: + fw_cmdmap |= FW_IQK_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + /* Clear control flag to sync with FW. */ + FW_CMD_IO_CLR(rtlpriv, FW_IQK_CTL); + break; + /* The following FW CMD is compatible to v.62 or later. */ + case FW_CMD_CTRL_DM_BY_DRIVER_NEW: + fw_cmdmap |= FW_DRIVER_CTRL_DM_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + break; + /* The followed FW Cmds needs post-processing later. */ + case FW_CMD_RESUME_DM_BY_SCAN: + fw_cmdmap |= (FW_DIG_ENABLE_CTL | + FW_HIGH_PWR_ENABLE_CTL | + FW_SS_CTL); + + if (rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE || + !digtable->dig_enable_flag) + fw_cmdmap &= ~FW_DIG_ENABLE_CTL; + + if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) || + rtlpriv->dm.dynamic_txpower_enable) + fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; + + if ((digtable->dig_ext_port_stage == + DIG_EXT_PORT_STAGE_0) || + (digtable->dig_ext_port_stage == + DIG_EXT_PORT_STAGE_1)) + fw_cmdmap &= ~FW_DIG_ENABLE_CTL; + + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + postprocessing = true; + break; + case FW_CMD_PAUSE_DM_BY_SCAN: + fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | + FW_HIGH_PWR_ENABLE_CTL | + FW_SS_CTL); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + postprocessing = true; + break; + case FW_CMD_HIGH_PWR_DISABLE: + fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + postprocessing = true; + break; + case FW_CMD_HIGH_PWR_ENABLE: + if (!(rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) && + !rtlpriv->dm.dynamic_txpower_enable) { + fw_cmdmap |= (FW_HIGH_PWR_ENABLE_CTL | + FW_SS_CTL); + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + postprocessing = true; + } + break; + case FW_CMD_DIG_MODE_FA: + fw_cmdmap |= FW_FA_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + break; + case FW_CMD_DIG_MODE_SS: + fw_cmdmap &= ~FW_FA_CTL; + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + break; + case FW_CMD_PAPE_CONTROL: + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "[FW CMD] Set PAPE Control\n"); + fw_cmdmap &= ~FW_PAPE_CTL_BY_SW_HW; + + FW_CMD_IO_SET(rtlpriv, fw_cmdmap); + break; + default: + /* Pass to original FW CMD processing callback + * routine. */ + postprocessing = true; + break; + } + } while (false); + + /* We shall post processing these FW CMD if + * variable postprocessing is set. + */ + if (postprocessing && !rtlhal->set_fwcmd_inprogress) { + rtlhal->set_fwcmd_inprogress = true; + /* Update current FW Cmd for callback use. */ + rtlhal->current_fwcmd_io = fw_cmdio; + } else { + return false; + } + + _rtl92s_phy_set_fwcmd_io(hw); + return true; +} + +static void _rtl92s_phy_check_ephy_switchready(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 delay = 100; + u8 regu1; + + regu1 = rtl_read_byte(rtlpriv, 0x554); + while ((regu1 & BIT(5)) && (delay > 0)) { + regu1 = rtl_read_byte(rtlpriv, 0x554); + delay--; + /* We delay only 50us to prevent + * being scheduled out. */ + udelay(50); + } +} + +void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + /* The way to be capable to switch clock request + * when the PG setting does not support clock request. + * This is the backdoor solution to switch clock + * request before ASPM or D3. */ + rtl_write_dword(rtlpriv, 0x540, 0x73c11); + rtl_write_dword(rtlpriv, 0x548, 0x2407c); + + /* Switch EPHY parameter!!!! */ + rtl_write_word(rtlpriv, 0x550, 0x1000); + rtl_write_byte(rtlpriv, 0x554, 0x20); + _rtl92s_phy_check_ephy_switchready(hw); + + rtl_write_word(rtlpriv, 0x550, 0xa0eb); + rtl_write_byte(rtlpriv, 0x554, 0x3e); + _rtl92s_phy_check_ephy_switchready(hw); + + rtl_write_word(rtlpriv, 0x550, 0xff80); + rtl_write_byte(rtlpriv, 0x554, 0x39); + _rtl92s_phy_check_ephy_switchready(hw); + + /* Delay L1 enter time */ + if (ppsc->support_aspm && !ppsc->support_backdoor) + rtl_write_byte(rtlpriv, 0x560, 0x40); + else + rtl_write_byte(rtlpriv, 0x560, 0x00); + +} + +void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 beaconinterval) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 new_bcn_num = 0; + + if (hal_get_firmwareversion(rtlpriv) >= 0x33) { + /* Fw v.51 and later. */ + rtl_write_dword(rtlpriv, WFM5, 0xF1000000 | + (beaconinterval << 8)); + } else { + new_bcn_num = beaconinterval * 32 - 64; + rtl_write_dword(rtlpriv, WFM3 + 4, new_bcn_num); + rtl_write_dword(rtlpriv, WFM3, 0xB026007C); + } +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h new file mode 100644 index 000000000000..8acf4765a7a6 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __RTL92S_PHY_H__ +#define __RTL92S_PHY_H__ + +#define MAX_TXPWR_IDX_NMODE_92S 63 +#define MAX_DOZE_WAITING_TIMES_9x 64 + +/* Channel switch:The size of + * command tables for switch channel */ +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define RF90_PATH_MAX 4 +#define RF6052_MAX_PATH 2 + +enum version_8192s { + VERSION_8192S_ACUT, + VERSION_8192S_BCUT, + VERSION_8192S_CCUT +}; + +enum swchnlcmd_id { + CMDID_END, + CMDID_SET_TXPOWEROWER_LEVEL, + CMDID_BBREGWRITE10, + CMDID_WRITEPORT_ULONG, + CMDID_WRITEPORT_USHORT, + CMDID_WRITEPORT_UCHAR, + CMDID_RF_WRITEREG, +}; + +struct swchnlcmd { + enum swchnlcmd_id cmdid; + u32 para1; + u32 para2; + u32 msdelay; +}; + +enum baseband_config_type { + /* Radio Path A */ + BASEBAND_CONFIG_PHY_REG = 0, + /* Radio Path B */ + BASEBAND_CONFIG_AGC_TAB = 1, +}; + +#define hal_get_firmwareversion(rtlpriv) \ + (((struct rt_firmware *)(rtlpriv->rtlhal.pfirmware))->firmwareversion) + +u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); +void rtl92s_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, + u32 data); +void rtl92s_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); +u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask); +void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data); +void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); +u8 rtl92s_phy_sw_chnl(struct ieee80211_hw *hw); +bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpower_state); +bool rtl92s_phy_mac_config(struct ieee80211_hw *hw); +void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw); +bool rtl92s_phy_bb_config(struct ieee80211_hw *hw); +bool rtl92s_phy_rf_config(struct ieee80211_hw *hw); +void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel); +bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fwcmd_io); +void rtl92s_phy_chk_fwcmd_iodone(struct ieee80211_hw *hw); +void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 beaconinterval); +u8 rtl92s_phy_config_rf(struct ieee80211_hw *hw, enum radio_path rfpath) ; + +#endif + diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h new file mode 100644 index 000000000000..e13043479b71 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/reg.h @@ -0,0 +1,1168 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __REALTEK_92S_REG_H__ +#define __REALTEK_92S_REG_H__ + +/* 1. System Configuration Registers */ +#define REG_SYS_ISO_CTRL 0x0000 +#define REG_SYS_FUNC_EN 0x0002 +#define PMC_FSM 0x0004 +#define SYS_CLKR 0x0008 +#define EPROM_CMD 0x000A +#define EE_VPD 0x000C +#define AFE_MISC 0x0010 +#define SPS0_CTRL 0x0011 +#define SPS1_CTRL 0x0018 +#define RF_CTRL 0x001F +#define LDOA15_CTRL 0x0020 +#define LDOV12D_CTRL 0x0021 +#define LDOHCI12_CTRL 0x0022 +#define LDO_USB_SDIO 0x0023 +#define LPLDO_CTRL 0x0024 +#define AFE_XTAL_CTRL 0x0026 +#define AFE_PLL_CTRL 0x0028 +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define PWR_DATA 0x0038 +#define DBG_PORT 0x003A +#define DPS_TIMER 0x003C +#define RCLK_MON 0x003E + +/* 2. Command Control Registers */ +#define CMDR 0x0040 +#define TXPAUSE 0x0042 +#define LBKMD_SEL 0x0043 +#define TCR 0x0044 +#define RCR 0x0048 +#define MSR 0x004C +#define SYSF_CFG 0x004D +#define RX_PKY_LIMIT 0x004E +#define MBIDCTRL 0x004F + +/* 3. MACID Setting Registers */ +#define MACIDR 0x0050 +#define MACIDR0 0x0050 +#define MACIDR4 0x0054 +#define BSSIDR 0x0058 +#define HWVID 0x005E +#define MAR 0x0060 +#define MBIDCAMCONTENT 0x0068 +#define MBIDCAMCFG 0x0070 +#define BUILDTIME 0x0074 +#define BUILDUSER 0x0078 + +#define IDR0 MACIDR0 +#define IDR4 MACIDR4 + +/* 4. Timing Control Registers */ +#define TSFR 0x0080 +#define SLOT_TIME 0x0089 +#define USTIME 0x008A +#define SIFS_CCK 0x008C +#define SIFS_OFDM 0x008E +#define PIFS_TIME 0x0090 +#define ACK_TIMEOUT 0x0091 +#define EIFSTR 0x0092 +#define BCN_INTERVAL 0x0094 +#define ATIMWND 0x0096 +#define BCN_DRV_EARLY_INT 0x0098 +#define BCN_DMATIME 0x009A +#define BCN_ERR_THRESH 0x009C +#define MLT 0x009D +#define RSVD_MAC_TUNE_US 0x009E + +/* 5. FIFO Control Registers */ +#define RQPN 0x00A0 +#define RQPN1 0x00A0 +#define RQPN2 0x00A1 +#define RQPN3 0x00A2 +#define RQPN4 0x00A3 +#define RQPN5 0x00A4 +#define RQPN6 0x00A5 +#define RQPN7 0x00A6 +#define RQPN8 0x00A7 +#define RQPN9 0x00A8 +#define RQPN10 0x00A9 +#define LD_RQPN 0x00AB +#define RXFF_BNDY 0x00AC +#define RXRPT_BNDY 0x00B0 +#define TXPKTBUF_PGBNDY 0x00B4 +#define PBP 0x00B5 +#define RXDRVINFO_SZ 0x00B6 +#define TXFF_STATUS 0x00B7 +#define RXFF_STATUS 0x00B8 +#define TXFF_EMPTY_TH 0x00B9 +#define SDIO_RX_BLKSZ 0x00BC +#define RXDMA 0x00BD +#define RXPKT_NUM 0x00BE +#define C2HCMD_UDT_SIZE 0x00C0 +#define C2HCMD_UDT_ADDR 0x00C2 +#define FIFOPAGE1 0x00C4 +#define FIFOPAGE2 0x00C8 +#define FIFOPAGE3 0x00CC +#define FIFOPAGE4 0x00D0 +#define FIFOPAGE5 0x00D4 +#define FW_RSVD_PG_CRTL 0x00D8 +#define RXDMA_AGG_PG_TH 0x00D9 +#define TXDESC_MSK 0x00DC +#define TXRPTFF_RDPTR 0x00E0 +#define TXRPTFF_WTPTR 0x00E4 +#define C2HFF_RDPTR 0x00E8 +#define C2HFF_WTPTR 0x00EC +#define RXFF0_RDPTR 0x00F0 +#define RXFF0_WTPTR 0x00F4 +#define RXFF1_RDPTR 0x00F8 +#define RXFF1_WTPTR 0x00FC +#define RXRPT0_RDPTR 0x0100 +#define RXRPT0_WTPTR 0x0104 +#define RXRPT1_RDPTR 0x0108 +#define RXRPT1_WTPTR 0x010C +#define RX0_UDT_SIZE 0x0110 +#define RX1PKTNUM 0x0114 +#define RXFILTERMAP 0x0116 +#define RXFILTERMAP_GP1 0x0118 +#define RXFILTERMAP_GP2 0x011A +#define RXFILTERMAP_GP3 0x011C +#define BCNQ_CTRL 0x0120 +#define MGTQ_CTRL 0x0124 +#define HIQ_CTRL 0x0128 +#define VOTID7_CTRL 0x012c +#define VOTID6_CTRL 0x0130 +#define VITID5_CTRL 0x0134 +#define VITID4_CTRL 0x0138 +#define BETID3_CTRL 0x013c +#define BETID0_CTRL 0x0140 +#define BKTID2_CTRL 0x0144 +#define BKTID1_CTRL 0x0148 +#define CMDQ_CTRL 0x014c +#define TXPKT_NUM_CTRL 0x0150 +#define TXQ_PGADD 0x0152 +#define TXFF_PG_NUM 0x0154 +#define TRXDMA_STATUS 0x0156 + +/* 6. Adaptive Control Registers */ +#define INIMCS_SEL 0x0160 +#define TX_RATE_REG INIMCS_SEL +#define INIRTSMCS_SEL 0x0180 +#define RRSR 0x0181 +#define ARFR0 0x0184 +#define ARFR1 0x0188 +#define ARFR2 0x018C +#define ARFR3 0x0190 +#define ARFR4 0x0194 +#define ARFR5 0x0198 +#define ARFR6 0x019C +#define ARFR7 0x01A0 +#define AGGLEN_LMT_H 0x01A7 +#define AGGLEN_LMT_L 0x01A8 +#define DARFRC 0x01B0 +#define RARFRC 0x01B8 +#define MCS_TXAGC 0x01C0 +#define CCK_TXAGC 0x01C8 + +/* 7. EDCA Setting Registers */ +#define EDCAPARA_VO 0x01D0 +#define EDCAPARA_VI 0x01D4 +#define EDCAPARA_BE 0x01D8 +#define EDCAPARA_BK 0x01DC +#define BCNTCFG 0x01E0 +#define CWRR 0x01E2 +#define ACMAVG 0x01E4 +#define AcmHwCtrl 0x01E7 +#define VO_ADMTM 0x01E8 +#define VI_ADMTM 0x01EC +#define BE_ADMTM 0x01F0 +#define RETRY_LIMIT 0x01F4 +#define SG_RATE 0x01F6 + +/* 8. WMAC, BA and CCX related Register. */ +#define NAV_CTRL 0x0200 +#define BW_OPMODE 0x0203 +#define BACAMCMD 0x0204 +#define BACAMCONTENT 0x0208 + +/* the 0x2xx register WMAC definition */ +#define LBDLY 0x0210 +#define FWDLY 0x0211 +#define HWPC_RX_CTRL 0x0218 +#define MQIR 0x0220 +#define MAIR 0x0222 +#define MSIR 0x0224 +#define CLM_RESULT 0x0227 +#define NHM_RPI_CNT 0x0228 +#define RXERR_RPT 0x0230 +#define NAV_PROT_LEN 0x0234 +#define CFEND_TH 0x0236 +#define AMPDU_MIN_SPACE 0x0237 +#define TXOP_STALL_CTRL 0x0238 + +/* 9. Security Control Registers */ +#define REG_RWCAM 0x0240 +#define REG_WCAMI 0x0244 +#define REG_RCAMO 0x0248 +#define REG_CAMDBG 0x024C +#define REG_SECR 0x0250 + +/* 10. Power Save Control Registers */ +#define WOW_CTRL 0x0260 +#define PSSTATUS 0x0261 +#define PSSWITCH 0x0262 +#define MIMOPS_WAIT_PERIOD 0x0263 +#define LPNAV_CTRL 0x0264 +#define WFM0 0x0270 +#define WFM1 0x0280 +#define WFM2 0x0290 +#define WFM3 0x02A0 +#define WFM4 0x02B0 +#define WFM5 0x02C0 +#define WFCRC 0x02D0 +#define FW_RPT_REG 0x02c4 + +/* 11. General Purpose Registers */ +#define PSTIME 0x02E0 +#define TIMER0 0x02E4 +#define TIMER1 0x02E8 +#define GPIO_IN_SE 0x02EC +#define GPIO_IO_SEL 0x02EE +#define MAC_PINMUX_CFG 0x02F1 +#define LEDCFG 0x02F2 +#define PHY_REG 0x02F3 +#define PHY_REG_DATA 0x02F4 +#define REG_EFUSE_CLK 0x02F8 + +/* 12. Host Interrupt Status Registers */ +#define INTA_MASK 0x0300 +#define ISR 0x0308 + +/* 13. Test Mode and Debug Control Registers */ +#define DBG_PORT_SWITCH 0x003A +#define BIST 0x0310 +#define DBS 0x0314 +#define CPUINST 0x0318 +#define CPUCAUSE 0x031C +#define LBUS_ERR_ADDR 0x0320 +#define LBUS_ERR_CMD 0x0324 +#define LBUS_ERR_DATA_L 0x0328 +#define LBUS_ERR_DATA_H 0x032C +#define LX_EXCEPTION_ADDR 0x0330 +#define WDG_CTRL 0x0334 +#define INTMTU 0x0338 +#define INTM 0x033A +#define FDLOCKTURN0 0x033C +#define FDLOCKTURN1 0x033D +#define TRXPKTBUF_DBG_DATA 0x0340 +#define TRXPKTBUF_DBG_CTRL 0x0348 +#define DPLL 0x034A +#define CBUS_ERR_ADDR 0x0350 +#define CBUS_ERR_CMD 0x0354 +#define CBUS_ERR_DATA_L 0x0358 +#define CBUS_ERR_DATA_H 0x035C +#define USB_SIE_INTF_ADDR 0x0360 +#define USB_SIE_INTF_WD 0x0361 +#define USB_SIE_INTF_RD 0x0362 +#define USB_SIE_INTF_CTRL 0x0363 +#define LBUS_MON_ADDR 0x0364 +#define LBUS_ADDR_MASK 0x0368 + +/* Boundary is 0x37F */ + +/* 14. PCIE config register */ +#define TP_POLL 0x0500 +#define PM_CTRL 0x0502 +#define PCIF 0x0503 + +#define THPDA 0x0514 +#define TMDA 0x0518 +#define TCDA 0x051C +#define HDA 0x0520 +#define TVODA 0x0524 +#define TVIDA 0x0528 +#define TBEDA 0x052C +#define TBKDA 0x0530 +#define TBDA 0x0534 +#define RCDA 0x0538 +#define RDQDA 0x053C +#define DBI_WDATA 0x0540 +#define DBI_RDATA 0x0544 +#define DBI_CTRL 0x0548 +#define MDIO_DATA 0x0550 +#define MDIO_CTRL 0x0554 +#define PCI_RPWM 0x0561 +#define PCI_CPWM 0x0563 + +/* Config register (Offset 0x800-) */ +#define PHY_CCA 0x803 + +/* Min Spacing related settings. */ +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +/* Rx DMA Control related settings */ +#define RXDMA_AGG_EN BIT(7) + +#define RPWM PCI_RPWM + +/* Regsiter Bit and Content definition */ + +#define ISO_MD2PP BIT(0) +#define ISO_PA2PCIE BIT(3) +#define ISO_PLL2MD BIT(4) +#define ISO_PWC_DV2RP BIT(11) +#define ISO_PWC_RV2RP BIT(12) + + +#define FEN_MREGEN BIT(15) +#define FEN_DCORE BIT(11) +#define FEN_CPUEN BIT(10) + +#define PAD_HWPD_IDN BIT(22) + +#define SYS_CLKSEL_80M BIT(0) +#define SYS_PS_CLKSEL BIT(1) +#define SYS_CPU_CLKSEL BIT(2) +#define SYS_MAC_CLK_EN BIT(11) +#define SYS_SWHW_SEL BIT(14) +#define SYS_FWHW_SEL BIT(15) + +#define CmdEEPROM_En BIT(5) +#define CmdEERPOMSEL BIT(4) +#define Cmd9346CR_9356SEL BIT(4) + +#define AFE_MBEN BIT(1) +#define AFE_BGEN BIT(0) + +#define SPS1_SWEN BIT(1) +#define SPS1_LDEN BIT(0) + +#define RF_EN BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + +#define LDA15_EN BIT(0) + +#define LDV12_EN BIT(0) +#define LDV12_SDBY BIT(1) + +#define XTAL_GATE_AFE BIT(10) + +#define APLL_EN BIT(0) + +#define AFR_CardBEn BIT(0) +#define AFR_CLKRUN_SEL BIT(1) +#define AFR_FuncRegEn BIT(2) + +#define APSDOFF_STATUS BIT(15) +#define APSDOFF BIT(14) +#define BBRSTN BIT(13) +#define BB_GLB_RSTN BIT(12) +#define SCHEDULE_EN BIT(10) +#define MACRXEN BIT(9) +#define MACTXEN BIT(8) +#define DDMA_EN BIT(7) +#define FW2HW_EN BIT(6) +#define RXDMA_EN BIT(5) +#define TXDMA_EN BIT(4) +#define HCI_RXDMA_EN BIT(3) +#define HCI_TXDMA_EN BIT(2) + +#define StopHCCA BIT(6) +#define StopHigh BIT(5) +#define StopMgt BIT(4) +#define StopVO BIT(3) +#define StopVI BIT(2) +#define StopBE BIT(1) +#define StopBK BIT(0) + +#define LBK_NORMAL 0x00 +#define LBK_MAC_LB (BIT(0) | BIT(1) | BIT(3)) +#define LBK_MAC_DLB (BIT(0) | BIT(1)) +#define LBK_DMA_LB (BIT(0) | BIT(1) | BIT(2)) + +#define TCP_OFDL_EN BIT(25) +#define HWPC_TX_EN BIT(24) +#define TXDMAPRE2FULL BIT(23) +#define DISCW BIT(20) +#define TCRICV BIT(19) +#define CfendForm BIT(17) +#define TCRCRC BIT(16) +#define FAKE_IMEM_EN BIT(15) +#define TSFRST BIT(9) +#define TSFEN BIT(8) +#define FWALLRDY (BIT(0) | BIT(1) | BIT(2) | \ + BIT(3) | BIT(4) | BIT(5) | \ + BIT(6) | BIT(7)) +#define FWRDY BIT(7) +#define BASECHG BIT(6) +#define IMEM BIT(5) +#define DMEM_CODE_DONE BIT(4) +#define EXT_IMEM_CHK_RPT BIT(3) +#define EXT_IMEM_CODE_DONE BIT(2) +#define IMEM_CHK_RPT BIT(1) +#define IMEM_CODE_DONE BIT(0) +#define EMEM_CODE_DONE BIT(2) +#define EMEM_CHK_RPT BIT(3) +#define IMEM_RDY BIT(5) +#define LOAD_FW_READY (IMEM_CODE_DONE | \ + IMEM_CHK_RPT | \ + EMEM_CODE_DONE | \ + EMEM_CHK_RPT | \ + DMEM_CODE_DONE | \ + IMEM_RDY | \ + BASECHG | \ + FWRDY) +#define TCR_TSFEN BIT(8) +#define TCR_TSFRST BIT(9) +#define TCR_FAKE_IMEM_EN BIT(15) +#define TCR_CRC BIT(16) +#define TCR_ICV BIT(19) +#define TCR_DISCW BIT(20) +#define TCR_HWPC_TX_EN BIT(24) +#define TCR_TCP_OFDL_EN BIT(25) +#define TXDMA_INIT_VALUE (IMEM_CHK_RPT | \ + EXT_IMEM_CHK_RPT) + +#define RCR_APPFCS BIT(31) +#define RCR_DIS_ENC_2BYTE BIT(30) +#define RCR_DIS_AES_2BYTE BIT(29) +#define RCR_HTC_LOC_CTRL BIT(28) +#define RCR_ENMBID BIT(27) +#define RCR_RX_TCPOFDL_EN BIT(26) +#define RCR_APP_PHYST_RXFF BIT(25) +#define RCR_APP_PHYST_STAFF BIT(24) +#define RCR_CBSSID BIT(23) +#define RCR_APWRMGT BIT(22) +#define RCR_ADD3 BIT(21) +#define RCR_AMF BIT(20) +#define RCR_ACF BIT(19) +#define RCR_ADF BIT(18) +#define RCR_APP_MIC BIT(17) +#define RCR_APP_ICV BIT(16) +#define RCR_RXFTH BIT(13) +#define RCR_AICV BIT(12) +#define RCR_RXDESC_LK_EN BIT(11) +#define RCR_APP_BA_SSN BIT(6) +#define RCR_ACRC32 BIT(5) +#define RCR_RXSHFT_EN BIT(4) +#define RCR_AB BIT(3) +#define RCR_AM BIT(2) +#define RCR_APM BIT(1) +#define RCR_AAP BIT(0) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 + + +#define MSR_LINK_MASK ((1 << 0) | (1 << 1)) +#define MSR_LINK_MANAGED 2 +#define MSR_LINK_NONE 0 +#define MSR_LINK_SHIFT 0 +#define MSR_LINK_ADHOC 1 +#define MSR_LINK_MASTER 3 +#define MSR_NOLINK 0x00 +#define MSR_ADHOC 0x01 +#define MSR_INFRA 0x02 +#define MSR_AP 0x03 + +#define ENUART BIT(7) +#define ENJTAG BIT(3) +#define BTMODE (BIT(2) | BIT(1)) +#define ENBT BIT(0) + +#define ENMBID BIT(7) +#define BCNUM (BIT(6) | BIT(5) | BIT(4)) + +#define USTIME_EDCA 0xFF00 +#define USTIME_TSF 0x00FF + +#define SIFS_TRX 0xFF00 +#define SIFS_CTX 0x00FF + +#define ENSWBCN BIT(15) +#define DRVERLY_TU 0x0FF0 +#define DRVERLY_US 0x000F +#define BCN_TCFG_CW_SHIFT 8 +#define BCN_TCFG_IFS 0 + +#define RRSR_RSC_OFFSET 21 +#define RRSR_SHORT_OFFSET 23 +#define RRSR_RSC_BW_40M 0x600000 +#define RRSR_RSC_UPSUBCHNL 0x400000 +#define RRSR_RSC_LOWSUBCHNL 0x200000 +#define RRSR_SHORT 0x800000 +#define RRSR_1M BIT(0) +#define RRSR_2M BIT(1) +#define RRSR_5_5M BIT(2) +#define RRSR_11M BIT(3) +#define RRSR_6M BIT(4) +#define RRSR_9M BIT(5) +#define RRSR_12M BIT(6) +#define RRSR_18M BIT(7) +#define RRSR_24M BIT(8) +#define RRSR_36M BIT(9) +#define RRSR_48M BIT(10) +#define RRSR_54M BIT(11) +#define RRSR_MCS0 BIT(12) +#define RRSR_MCS1 BIT(13) +#define RRSR_MCS2 BIT(14) +#define RRSR_MCS3 BIT(15) +#define RRSR_MCS4 BIT(16) +#define RRSR_MCS5 BIT(17) +#define RRSR_MCS6 BIT(18) +#define RRSR_MCS7 BIT(19) +#define BRSR_AckShortPmb BIT(23) + +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 + +#define RATE_ALL_CCK (RATR_1M | RATR_2M | \ + RATR_55M | RATR_11M) +#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | \ + RATR_12M | RATR_18M | \ + RATR_24M | RATR_36M | \ + RATR_48M | RATR_54M) +#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | \ + RATR_MCS2 | RATR_MCS3 | \ + RATR_MCS4 | RATR_MCS5 | \ + RATR_MCS6 | RATR_MCS7) +#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | \ + RATR_MCS10 | RATR_MCS11 | \ + RATR_MCS12 | RATR_MCS13 | \ + RATR_MCS14 | RATR_MCS15) + +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + +#define AcmHw_HwEn BIT(0) +#define AcmHw_BeqEn BIT(1) +#define AcmHw_ViqEn BIT(2) +#define AcmHw_VoqEn BIT(3) +#define AcmHw_BeqStatus BIT(4) +#define AcmHw_ViqStatus BIT(5) +#define AcmHw_VoqStatus BIT(6) + +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + +#define NAV_UPPER_EN BIT(16) +#define NAV_UPPER 0xFF00 +#define NAV_RTSRST 0xFF + +#define BW_OPMODE_20MHZ BIT(2) +#define BW_OPMODE_5G BIT(1) +#define BW_OPMODE_11J BIT(0) + +#define RXERR_RPT_RST BIT(27) +#define RXERR_OFDM_PPDU 0 +#define RXERR_OFDM_FALSE_ALARM 1 +#define RXERR_OFDM_MPDU_OK 2 +#define RXERR_OFDM_MPDU_FAIL 3 +#define RXERR_CCK_PPDU 4 +#define RXERR_CCK_FALSE_ALARM 5 +#define RXERR_CCK_MPDU_OK 6 +#define RXERR_CCK_MPDU_FAIL 7 +#define RXERR_HT_PPDU 8 +#define RXERR_HT_FALSE_ALARM 9 +#define RXERR_HT_MPDU_TOTAL 10 +#define RXERR_HT_MPDU_OK 11 +#define RXERR_HT_MPDU_FAIL 12 +#define RXERR_RX_FULL_DROP 15 + +#define SCR_TXUSEDK BIT(0) +#define SCR_RXUSEDK BIT(1) +#define SCR_TXENCENABLE BIT(2) +#define SCR_RXENCENABLE BIT(3) +#define SCR_SKBYA2 BIT(4) +#define SCR_NOSKMC BIT(5) + +#define CAM_VALID BIT(15) +#define CAM_NOTVALID 0x0000 +#define CAM_USEDK BIT(5) + +#define CAM_NONE 0x0 +#define CAM_WEP40 0x01 +#define CAM_TKIP 0x02 +#define CAM_AES 0x04 +#define CAM_WEP104 0x05 + +#define TOTAL_CAM_ENTRY 32 +#define HALF_CAM_ENTRY 16 + +#define CAM_WRITE BIT(16) +#define CAM_READ 0x00000000 +#define CAM_POLLINIG BIT(31) + +#define WOW_PMEN BIT(0) +#define WOW_WOMEN BIT(1) +#define WOW_MAGIC BIT(2) +#define WOW_UWF BIT(3) + +#define GPIOMUX_EN BIT(3) +#define GPIOSEL_GPIO 0 +#define GPIOSEL_PHYDBG 1 +#define GPIOSEL_BT 2 +#define GPIOSEL_WLANDBG 3 +#define GPIOSEL_GPIO_MASK (~(BIT(0)|BIT(1))) + +#define HST_RDBUSY BIT(0) +#define CPU_WTBUSY BIT(1) + +#define IMR8190_DISABLED 0x0 +#define IMR_CPUERR BIT(5) +#define IMR_ATIMEND BIT(4) +#define IMR_TBDOK BIT(3) +#define IMR_TBDER BIT(2) +#define IMR_BCNDMAINT8 BIT(1) +#define IMR_BCNDMAINT7 BIT(0) +#define IMR_BCNDMAINT6 BIT(31) +#define IMR_BCNDMAINT5 BIT(30) +#define IMR_BCNDMAINT4 BIT(29) +#define IMR_BCNDMAINT3 BIT(28) +#define IMR_BCNDMAINT2 BIT(27) +#define IMR_BCNDMAINT1 BIT(26) +#define IMR_BCNDOK8 BIT(25) +#define IMR_BCNDOK7 BIT(24) +#define IMR_BCNDOK6 BIT(23) +#define IMR_BCNDOK5 BIT(22) +#define IMR_BCNDOK4 BIT(21) +#define IMR_BCNDOK3 BIT(20) +#define IMR_BCNDOK2 BIT(19) +#define IMR_BCNDOK1 BIT(18) +#define IMR_TIMEOUT2 BIT(17) +#define IMR_TIMEOUT1 BIT(16) +#define IMR_TXFOVW BIT(15) +#define IMR_PSTIMEOUT BIT(14) +#define IMR_BCNINT BIT(13) +#define IMR_RXFOVW BIT(12) +#define IMR_RDU BIT(11) +#define IMR_RXCMDOK BIT(10) +#define IMR_BDOK BIT(9) +#define IMR_HIGHDOK BIT(8) +#define IMR_COMDOK BIT(7) +#define IMR_MGNTDOK BIT(6) +#define IMR_HCCADOK BIT(5) +#define IMR_BKDOK BIT(4) +#define IMR_BEDOK BIT(3) +#define IMR_VIDOK BIT(2) +#define IMR_VODOK BIT(1) +#define IMR_ROK BIT(0) + +#define TPPOLL_BKQ BIT(0) +#define TPPOLL_BEQ BIT(1) +#define TPPOLL_VIQ BIT(2) +#define TPPOLL_VOQ BIT(3) +#define TPPOLL_BQ BIT(4) +#define TPPOLL_CQ BIT(5) +#define TPPOLL_MQ BIT(6) +#define TPPOLL_HQ BIT(7) +#define TPPOLL_HCCAQ BIT(8) +#define TPPOLL_STOPBK BIT(9) +#define TPPOLL_STOPBE BIT(10) +#define TPPOLL_STOPVI BIT(11) +#define TPPOLL_STOPVO BIT(12) +#define TPPOLL_STOPMGT BIT(13) +#define TPPOLL_STOPHIGH BIT(14) +#define TPPOLL_STOPHCCA BIT(15) +#define TPPOLL_SHIFT 8 + +#define CCX_CMD_CLM_ENABLE BIT(0) +#define CCX_CMD_NHM_ENABLE BIT(1) +#define CCX_CMD_FUNCTION_ENABLE BIT(8) +#define CCX_CMD_IGNORE_CCA BIT(9) +#define CCX_CMD_IGNORE_TXON BIT(10) +#define CCX_CLM_RESULT_READY BIT(16) +#define CCX_NHM_RESULT_READY BIT(16) +#define CCX_CMD_RESET 0x0 + + +#define HWSET_MAX_SIZE_92S 128 +#define EFUSE_MAX_SECTION 16 +#define EFUSE_REAL_CONTENT_LEN 512 +#define EFUSE_OOB_PROTECT_BYTES 15 + +#define RTL8190_EEPROM_ID 0x8129 +#define EEPROM_HPON 0x02 +#define EEPROM_CLK 0x06 +#define EEPROM_TESTR 0x08 + +#define EEPROM_VID 0x0A +#define EEPROM_DID 0x0C +#define EEPROM_SVID 0x0E +#define EEPROM_SMID 0x10 + +#define EEPROM_MAC_ADDR 0x12 +#define EEPROM_NODE_ADDRESS_BYTE_0 0x12 + +#define EEPROM_PWDIFF 0x54 + +#define EEPROM_TXPOWERBASE 0x50 +#define EEPROM_TX_PWR_INDEX_RANGE 28 + +#define EEPROM_TX_PWR_HT20_DIFF 0x62 +#define DEFAULT_HT20_TXPWR_DIFF 2 +#define EEPROM_TX_PWR_OFDM_DIFF 0x65 + +#define EEPROM_TXPWRGROUP 0x67 +#define EEPROM_REGULATORY 0x6D + +#define TX_PWR_SAFETY_CHK 0x6D +#define EEPROM_TXPWINDEX_CCK_24G 0x5D +#define EEPROM_TXPWINDEX_OFDM_24G 0x6B +#define EEPROM_HT2T_CH1_A 0x6c +#define EEPROM_HT2T_CH7_A 0x6d +#define EEPROM_HT2T_CH13_A 0x6e +#define EEPROM_HT2T_CH1_B 0x6f +#define EEPROM_HT2T_CH7_B 0x70 +#define EEPROM_HT2T_CH13_B 0x71 + +#define EEPROM_TSSI_A 0x74 +#define EEPROM_TSSI_B 0x75 + +#define EEPROM_RFIND_POWERDIFF 0x76 +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 + +#define EEPROM_THERMALMETER 0x77 +#define EEPROM_BLUETOOTH_COEXIST 0x78 +#define EEPROM_BLUETOOTH_TYPE 0x4f + +#define EEPROM_OPTIONAL 0x78 +#define EEPROM_WOWLAN 0x78 + +#define EEPROM_CRYSTALCAP 0x79 +#define EEPROM_CHANNELPLAN 0x7B +#define EEPROM_VERSION 0x7C +#define EEPROM_CUSTOMID 0x7A +#define EEPROM_BOARDTYPE 0x7E + +#define EEPROM_CHANNEL_PLAN_FCC 0x0 +#define EEPROM_CHANNEL_PLAN_IC 0x1 +#define EEPROM_CHANNEL_PLAN_ETSI 0x2 +#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 +#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 +#define EEPROM_CHANNEL_PLAN_MKK 0x5 +#define EEPROM_CHANNEL_PLAN_MKK1 0x6 +#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 +#define EEPROM_CHANNEL_PLAN_TELEC 0x8 +#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 +#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA +#define EEPROM_CHANNEL_PLAN_NCC 0xB +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + +#define FW_DIG_DISABLE 0xfd00cc00 +#define FW_DIG_ENABLE 0xfd000000 +#define FW_DIG_HALT 0xfd000001 +#define FW_DIG_RESUME 0xfd000002 +#define FW_HIGH_PWR_DISABLE 0xfd000008 +#define FW_HIGH_PWR_ENABLE 0xfd000009 +#define FW_ADD_A2_ENTRY 0xfd000016 +#define FW_TXPWR_TRACK_ENABLE 0xfd000017 +#define FW_TXPWR_TRACK_DISABLE 0xfd000018 +#define FW_TXPWR_TRACK_THERMAL 0xfd000019 +#define FW_TXANT_SWITCH_ENABLE 0xfd000023 +#define FW_TXANT_SWITCH_DISABLE 0xfd000024 +#define FW_RA_INIT 0xfd000026 +#define FW_CTRL_DM_BY_DRIVER 0Xfd00002a +#define FW_RA_IOT_BG_COMB 0xfd000030 +#define FW_RA_IOT_N_COMB 0xfd000031 +#define FW_RA_REFRESH 0xfd0000a0 +#define FW_RA_UPDATE_MASK 0xfd0000a2 +#define FW_RA_DISABLE 0xfd0000a4 +#define FW_RA_ACTIVE 0xfd0000a6 +#define FW_RA_DISABLE_RSSI_MASK 0xfd0000ac +#define FW_RA_ENABLE_RSSI_MASK 0xfd0000ad +#define FW_RA_RESET 0xfd0000af +#define FW_DM_DISABLE 0xfd00aa00 +#define FW_IQK_ENABLE 0xf0000020 +#define FW_IQK_SUCCESS 0x0000dddd +#define FW_IQK_FAIL 0x0000ffff +#define FW_OP_FAILURE 0xffffffff +#define FW_TX_FEEDBACK_NONE 0xfb000000 +#define FW_TX_FEEDBACK_DTM_ENABLE (FW_TX_FEEDBACK_NONE | 0x1) +#define FW_TX_FEEDBACK_CCX_ENABL (FW_TX_FEEDBACK_NONE | 0x2) +#define FW_BB_RESET_ENABLE 0xff00000d +#define FW_BB_RESET_DISABLE 0xff00000e +#define FW_CCA_CHK_ENABLE 0xff000011 +#define FW_CCK_RESET_CNT 0xff000013 +#define FW_LPS_ENTER 0xfe000010 +#define FW_LPS_LEAVE 0xfe000011 +#define FW_INDIRECT_READ 0xf2000000 +#define FW_INDIRECT_WRITE 0xf2000001 +#define FW_CHAN_SET 0xf3000001 + +#define RFPC 0x5F +#define RCR_9356SEL BIT(6) +#define TCR_LRL_OFFSET 0 +#define TCR_SRL_OFFSET 8 +#define TCR_MXDMA_OFFSET 21 +#define TCR_SAT BIT(24) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 +#define RCR_OnlyErlPkt BIT(31) +#define CWR 0xDC +#define RETRYCTR 0xDE + +#define CPU_GEN_SYSTEM_RESET 0x00000001 + +#define CCX_COMMAND_REG 0x890 +#define CLM_PERIOD_REG 0x894 +#define NHM_PERIOD_REG 0x896 + +#define NHM_THRESHOLD0 0x898 +#define NHM_THRESHOLD1 0x899 +#define NHM_THRESHOLD2 0x89A +#define NHM_THRESHOLD3 0x89B +#define NHM_THRESHOLD4 0x89C +#define NHM_THRESHOLD5 0x89D +#define NHM_THRESHOLD6 0x89E +#define CLM_RESULT_REG 0x8D0 +#define NHM_RESULT_REG 0x8D4 +#define NHM_RPI_COUNTER0 0x8D8 +#define NHM_RPI_COUNTER1 0x8D9 +#define NHM_RPI_COUNTER2 0x8DA +#define NHM_RPI_COUNTER3 0x8DB +#define NHM_RPI_COUNTER4 0x8DC +#define NHM_RPI_COUNTER5 0x8DD +#define NHM_RPI_COUNTER6 0x8DE +#define NHM_RPI_COUNTER7 0x8DF + +#define HAL_8192S_HW_GPIO_OFF_BIT BIT(3) +#define HAL_8192S_HW_GPIO_OFF_MASK 0xF7 +#define HAL_8192S_HW_GPIO_WPS_BIT BIT(4) + +#define RPMAC_RESET 0x100 +#define RPMAC_TXSTART 0x104 +#define RPMAC_TXLEGACYSIG 0x108 +#define RPMAC_TXHTSIG1 0x10c +#define RPMAC_TXHTSIG2 0x110 +#define RPMAC_PHYDEBUG 0x114 +#define RPMAC_TXPACKETNNM 0x118 +#define RPMAC_TXIDLE 0x11c +#define RPMAC_TXMACHEADER0 0x120 +#define RPMAC_TXMACHEADER1 0x124 +#define RPMAC_TXMACHEADER2 0x128 +#define RPMAC_TXMACHEADER3 0x12c +#define RPMAC_TXMACHEADER4 0x130 +#define RPMAC_TXMACHEADER5 0x134 +#define RPMAC_TXDATATYPE 0x138 +#define RPMAC_TXRANDOMSEED 0x13c +#define RPMAC_CCKPLCPPREAMBLE 0x140 +#define RPMAC_CCKPLCPHEADER 0x144 +#define RPMAC_CCKCRC16 0x148 +#define RPMAC_OFDMRXCRC32OK 0x170 +#define RPMAC_OFDMRXCRC32ER 0x174 +#define RPMAC_OFDMRXPARITYER 0x178 +#define RPMAC_OFDMRXCRC8ER 0x17c +#define RPMAC_CCKCRXRC16ER 0x180 +#define RPMAC_CCKCRXRC32ER 0x184 +#define RPMAC_CCKCRXRC32OK 0x188 +#define RPMAC_TXSTATUS 0x18c + +#define RF_BB_CMD_ADDR 0x02c0 +#define RF_BB_CMD_DATA 0x02c4 + +#define RFPGA0_RFMOD 0x800 + +#define RFPGA0_TXINFO 0x804 +#define RFPGA0_PSDFUNCTION 0x808 + +#define RFPGA0_TXGAINSTAGE 0x80c + +#define RFPGA0_RFTIMING1 0x810 +#define RFPGA0_RFTIMING2 0x814 +#define RFPGA0_XA_HSSIPARAMETER1 0x820 +#define RFPGA0_XA_HSSIPARAMETER2 0x824 +#define RFPGA0_XB_HSSIPARAMETER1 0x828 +#define RFPGA0_XB_HSSIPARAMETER2 0x82c +#define RFPGA0_XC_HSSIPARAMETER1 0x830 +#define RFPGA0_XC_HSSIPARAMETER2 0x834 +#define RFPGA0_XD_HSSIPARAMETER1 0x838 +#define RFPGA0_XD_HSSIPARAMETER2 0x83c +#define RFPGA0_XA_LSSIPARAMETER 0x840 +#define RFPGA0_XB_LSSIPARAMETER 0x844 +#define RFPGA0_XC_LSSIPARAMETER 0x848 +#define RFPGA0_XD_LSSIPARAMETER 0x84c + +#define RFPGA0_RFWAKEUP_PARAMETER 0x850 +#define RFPGA0_RFSLEEPUP_PARAMETER 0x854 + +#define RFPGA0_XAB_SWITCHCONTROL 0x858 +#define RFPGA0_XCD_SWITCHCONTROL 0x85c + +#define RFPGA0_XA_RFINTERFACEOE 0x860 +#define RFPGA0_XB_RFINTERFACEOE 0x864 +#define RFPGA0_XC_RFINTERFACEOE 0x868 +#define RFPGA0_XD_RFINTERFACEOE 0x86c + +#define RFPGA0_XAB_RFINTERFACESW 0x870 +#define RFPGA0_XCD_RFINTERFACESW 0x874 + +#define RFPGA0_XAB_RFPARAMETER 0x878 +#define RFPGA0_XCD_RFPARAMETER 0x87c + +#define RFPGA0_ANALOGPARAMETER1 0x880 +#define RFPGA0_ANALOGPARAMETER2 0x884 +#define RFPGA0_ANALOGPARAMETER3 0x888 +#define RFPGA0_ANALOGPARAMETER4 0x88c + +#define RFPGA0_XA_LSSIREADBACK 0x8a0 +#define RFPGA0_XB_LSSIREADBACK 0x8a4 +#define RFPGA0_XC_LSSIREADBACK 0x8a8 +#define RFPGA0_XD_LSSIREADBACK 0x8ac + +#define RFPGA0_PSDREPORT 0x8b4 +#define TRANSCEIVERA_HSPI_READBACK 0x8b8 +#define TRANSCEIVERB_HSPI_READBACK 0x8bc +#define RFPGA0_XAB_RFINTERFACERB 0x8e0 +#define RFPGA0_XCD_RFINTERFACERB 0x8e4 +#define RFPGA1_RFMOD 0x900 + +#define RFPGA1_TXBLOCK 0x904 +#define RFPGA1_DEBUGSELECT 0x908 +#define RFPGA1_TXINFO 0x90c + +#define RCCK0_SYSTEM 0xa00 + +#define RCCK0_AFESETTING 0xa04 +#define RCCK0_CCA 0xa08 + +#define RCCK0_RXAGC1 0xa0c +#define RCCK0_RXAGC2 0xa10 + +#define RCCK0_RXHP 0xa14 + +#define RCCK0_DSPPARAMETER1 0xa18 +#define RCCK0_DSPPARAMETER2 0xa1c + +#define RCCK0_TXFILTER1 0xa20 +#define RCCK0_TXFILTER2 0xa24 +#define RCCK0_DEBUGPORT 0xa28 +#define RCCK0_FALSEALARMREPORT 0xa2c +#define RCCK0_TRSSIREPORT 0xa50 +#define RCCK0_RXREPORT 0xa54 +#define RCCK0_FACOUNTERLOWER 0xa5c +#define RCCK0_FACOUNTERUPPER 0xa58 + +#define ROFDM0_LSTF 0xc00 + +#define ROFDM0_TRXPATHENABLE 0xc04 +#define ROFDM0_TRMUXPAR 0xc08 +#define ROFDM0_TRSWISOLATION 0xc0c + +#define ROFDM0_XARXAFE 0xc10 +#define ROFDM0_XARXIQIMBALANCE 0xc14 +#define ROFDM0_XBRXAFE 0xc18 +#define ROFDM0_XBRXIQIMBALANCE 0xc1c +#define ROFDM0_XCRXAFE 0xc20 +#define ROFDM0_XCRXIQIMBALANCE 0xc24 +#define ROFDM0_XDRXAFE 0xc28 +#define ROFDM0_XDRXIQIMBALANCE 0xc2c + +#define ROFDM0_RXDETECTOR1 0xc30 +#define ROFDM0_RXDETECTOR2 0xc34 +#define ROFDM0_RXDETECTOR3 0xc38 +#define ROFDM0_RXDETECTOR4 0xc3c + +#define ROFDM0_RXDSP 0xc40 +#define ROFDM0_CFO_AND_DAGC 0xc44 +#define ROFDM0_CCADROP_THRESHOLD 0xc48 +#define ROFDM0_ECCA_THRESHOLD 0xc4c + +#define ROFDM0_XAAGCCORE1 0xc50 +#define ROFDM0_XAAGCCORE2 0xc54 +#define ROFDM0_XBAGCCORE1 0xc58 +#define ROFDM0_XBAGCCORE2 0xc5c +#define ROFDM0_XCAGCCORE1 0xc60 +#define ROFDM0_XCAGCCORE2 0xc64 +#define ROFDM0_XDAGCCORE1 0xc68 +#define ROFDM0_XDAGCCORE2 0xc6c + +#define ROFDM0_AGCPARAMETER1 0xc70 +#define ROFDM0_AGCPARAMETER2 0xc74 +#define ROFDM0_AGCRSSITABLE 0xc78 +#define ROFDM0_HTSTFAGC 0xc7c + +#define ROFDM0_XATXIQIMBALANCE 0xc80 +#define ROFDM0_XATXAFE 0xc84 +#define ROFDM0_XBTXIQIMBALANCE 0xc88 +#define ROFDM0_XBTXAFE 0xc8c +#define ROFDM0_XCTXIQIMBALANCE 0xc90 +#define ROFDM0_XCTXAFE 0xc94 +#define ROFDM0_XDTXIQIMBALANCE 0xc98 +#define ROFDM0_XDTXAFE 0xc9c + +#define ROFDM0_RXHP_PARAMETER 0xce0 +#define ROFDM0_TXPSEUDO_NOISE_WGT 0xce4 +#define ROFDM0_FRAME_SYNC 0xcf0 +#define ROFDM0_DFSREPORT 0xcf4 +#define ROFDM0_TXCOEFF1 0xca4 +#define ROFDM0_TXCOEFF2 0xca8 +#define ROFDM0_TXCOEFF3 0xcac +#define ROFDM0_TXCOEFF4 0xcb0 +#define ROFDM0_TXCOEFF5 0xcb4 +#define ROFDM0_TXCOEFF6 0xcb8 + + +#define ROFDM1_LSTF 0xd00 +#define ROFDM1_TRXPATHENABLE 0xd04 + +#define ROFDM1_CFO 0xd08 +#define ROFDM1_CSI1 0xd10 +#define ROFDM1_SBD 0xd14 +#define ROFDM1_CSI2 0xd18 +#define ROFDM1_CFOTRACKING 0xd2c +#define ROFDM1_TRXMESAURE1 0xd34 +#define ROFDM1_INTF_DET 0xd3c +#define ROFDM1_PSEUDO_NOISESTATEAB 0xd50 +#define ROFDM1_PSEUDO_NOISESTATECD 0xd54 +#define ROFDM1_RX_PSEUDO_NOISE_WGT 0xd58 + +#define ROFDM_PHYCOUNTER1 0xda0 +#define ROFDM_PHYCOUNTER2 0xda4 +#define ROFDM_PHYCOUNTER3 0xda8 + +#define ROFDM_SHORT_CFOAB 0xdac +#define ROFDM_SHORT_CFOCD 0xdb0 +#define ROFDM_LONG_CFOAB 0xdb4 +#define ROFDM_LONG_CFOCD 0xdb8 +#define ROFDM_TAIL_CFOAB 0xdbc +#define ROFDM_TAIL_CFOCD 0xdc0 +#define ROFDM_PW_MEASURE1 0xdc4 +#define ROFDM_PW_MEASURE2 0xdc8 +#define ROFDM_BW_REPORT 0xdcc +#define ROFDM_AGC_REPORT 0xdd0 +#define ROFDM_RXSNR 0xdd4 +#define ROFDM_RXEVMCSI 0xdd8 +#define ROFDM_SIG_REPORT 0xddc + + +#define RTXAGC_RATE18_06 0xe00 +#define RTXAGC_RATE54_24 0xe04 +#define RTXAGC_CCK_MCS32 0xe08 +#define RTXAGC_MCS03_MCS00 0xe10 +#define RTXAGC_MCS07_MCS04 0xe14 +#define RTXAGC_MCS11_MCS08 0xe18 +#define RTXAGC_MCS15_MCS12 0xe1c + + +#define RF_AC 0x00 +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_POW_TRSW 0x05 +#define RF_GAIN_RX 0x06 +#define RF_GAIN_TX 0x07 +#define RF_TXM_IDAC 0x08 +#define RF_BS_IQGEN 0x0F + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 +#define RF_RX_AGC_HP 0x12 +#define RF_TX_AGC 0x13 +#define RF_BIAS 0x14 +#define RF_IPA 0x15 +#define RF_POW_ABILITY 0x17 +#define RF_MODE_AG 0x18 +#define RF_CHANNEL 0x18 +#define RF_CHNLBW 0x18 +#define RF_TOP 0x19 +#define RF_RX_G1 0x1A +#define RF_RX_G2 0x1B +#define RF_RX_BB2 0x1C +#define RF_RX_BB1 0x1D +#define RF_RCK1 0x1E +#define RF_RCK2 0x1F + +#define RF_TX_G1 0x20 +#define RF_TX_G2 0x21 +#define RF_TX_G3 0x22 +#define RF_TX_BB1 0x23 +#define RF_T_METER 0x24 +#define RF_SYN_G1 0x25 +#define RF_SYN_G2 0x26 +#define RF_SYN_G3 0x27 +#define RF_SYN_G4 0x28 +#define RF_SYN_G5 0x29 +#define RF_SYN_G6 0x2A +#define RF_SYN_G7 0x2B +#define RF_SYN_G8 0x2C + +#define RF_RCK_OS 0x30 +#define RF_TXPA_G1 0x31 +#define RF_TXPA_G2 0x32 +#define RF_TXPA_G3 0x33 + +#define BRFMOD 0x1 +#define BCCKEN 0x1000000 +#define BOFDMEN 0x2000000 + +#define BXBTXAGC 0xf00 +#define BXCTXAGC 0xf000 +#define BXDTXAGC 0xf0000 + +#define B3WIRE_DATALENGTH 0x800 +#define B3WIRE_ADDRESSLENGTH 0x400 + +#define BRFSI_RFENV 0x10 + +#define BLSSI_READADDRESS 0x7f800000 +#define BLSSI_READEDGE 0x80000000 +#define BLSSI_READBACK_DATA 0xfffff + +#define BADCLKPHASE 0x4000000 + +#define BCCK_SIDEBAND 0x10 + +#define BTX_AGCRATECCK 0x7f00 + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c new file mode 100644 index 000000000000..78a81c1e390b --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c @@ -0,0 +1,535 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" + + +static void _rtl92s_get_powerbase(struct ieee80211_hw *hw, u8 *p_pwrlevel, + u8 chnl, u32 *ofdmbase, u32 *mcsbase, + u8 *p_final_pwridx) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 pwrbase0, pwrbase1; + u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0; + u8 i, pwrlevel[4]; + + for (i = 0; i < 2; i++) + pwrlevel[i] = p_pwrlevel[i]; + + /* We only care about the path A for legacy. */ + if (rtlefuse->eeprom_version < 2) { + pwrbase0 = pwrlevel[0] + (rtlefuse->legacy_httxpowerdiff & 0xf); + } else { + legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff + [RF90_PATH_A][chnl - 1]; + + /* For legacy OFDM, tx pwr always > HT OFDM pwr. + * We do not care Path B + * legacy OFDM pwr diff. NO BB register + * to notify HW. */ + pwrbase0 = pwrlevel[0] + legacy_pwrdiff; + } + + pwrbase0 = (pwrbase0 << 24) | (pwrbase0 << 16) | (pwrbase0 << 8) | + pwrbase0; + *ofdmbase = pwrbase0; + + /* MCS rates */ + if (rtlefuse->eeprom_version >= 2) { + /* Check HT20 to HT40 diff */ + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { + for (i = 0; i < 2; i++) { + /* rf-A, rf-B */ + /* HT 20<->40 pwr diff */ + ht20_pwrdiff = rtlefuse->txpwr_ht20diff + [i][chnl - 1]; + + if (ht20_pwrdiff < 8) /* 0~+7 */ + pwrlevel[i] += ht20_pwrdiff; + else /* index8-15=-8~-1 */ + pwrlevel[i] -= (16 - ht20_pwrdiff); + } + } + } + + /* use index of rf-A */ + pwrbase1 = pwrlevel[0]; + pwrbase1 = (pwrbase1 << 24) | (pwrbase1 << 16) | (pwrbase1 << 8) | + pwrbase1; + *mcsbase = pwrbase1; + + /* The following is for Antenna + * diff from Ant-B to Ant-A */ + p_final_pwridx[0] = pwrlevel[0]; + p_final_pwridx[1] = pwrlevel[1]; + + switch (rtlefuse->eeprom_regulatory) { + case 3: + /* The following is for calculation + * of the power diff for Ant-B to Ant-A. */ + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + p_final_pwridx[0] += rtlefuse->pwrgroup_ht40 + [RF90_PATH_A][ + chnl - 1]; + p_final_pwridx[1] += rtlefuse->pwrgroup_ht40 + [RF90_PATH_B][ + chnl - 1]; + } else { + p_final_pwridx[0] += rtlefuse->pwrgroup_ht20 + [RF90_PATH_A][ + chnl - 1]; + p_final_pwridx[1] += rtlefuse->pwrgroup_ht20 + [RF90_PATH_B][ + chnl - 1]; + } + break; + default: + break; + } + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "40MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n", + p_final_pwridx[0], p_final_pwridx[1]); + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "20MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n", + p_final_pwridx[0], p_final_pwridx[1]); + } +} + +static void _rtl92s_set_antennadiff(struct ieee80211_hw *hw, + u8 *p_final_pwridx) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + char ant_pwr_diff = 0; + u32 u4reg_val = 0; + + if (rtlphy->rf_type == RF_2T2R) { + ant_pwr_diff = p_final_pwridx[1] - p_final_pwridx[0]; + + /* range is from 7~-8, + * index = 0x0~0xf */ + if (ant_pwr_diff > 7) + ant_pwr_diff = 7; + if (ant_pwr_diff < -8) + ant_pwr_diff = -8; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Antenna Diff from RF-B to RF-A = %d (0x%x)\n", + ant_pwr_diff, ant_pwr_diff & 0xf); + + ant_pwr_diff &= 0xf; + } + + /* Antenna TX power difference */ + rtlefuse->antenna_txpwdiff[2] = 0;/* RF-D, don't care */ + rtlefuse->antenna_txpwdiff[1] = 0;/* RF-C, don't care */ + rtlefuse->antenna_txpwdiff[0] = (u8)(ant_pwr_diff); /* RF-B */ + + u4reg_val = rtlefuse->antenna_txpwdiff[2] << 8 | + rtlefuse->antenna_txpwdiff[1] << 4 | + rtlefuse->antenna_txpwdiff[0]; + + rtl_set_bbreg(hw, RFPGA0_TXGAINSTAGE, (BXBTXAGC | BXCTXAGC | BXDTXAGC), + u4reg_val); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Write BCD-Diff(0x%x) = 0x%x\n", + RFPGA0_TXGAINSTAGE, u4reg_val); +} + +static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw, + u8 chnl, u8 index, + u32 pwrbase0, + u32 pwrbase1, + u32 *p_outwrite_val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 i, chnlgroup, pwrdiff_limit[4]; + u32 writeval, customer_limit; + + /* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */ + switch (rtlefuse->eeprom_regulatory) { + case 0: + /* Realtek better performance increase power diff + * defined by Realtek for large power */ + chnlgroup = 0; + + writeval = rtlphy->mcs_offset[chnlgroup][index] + + ((index < 2) ? pwrbase0 : pwrbase1); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "RTK better performance, writeval = 0x%x\n", writeval); + break; + case 1: + /* Realtek regulatory increase power diff defined + * by Realtek for regulatory */ + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + writeval = ((index < 2) ? pwrbase0 : pwrbase1); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Realtek regulatory, 40MHz, writeval = 0x%x\n", + writeval); + } else { + if (rtlphy->pwrgroup_cnt == 1) + chnlgroup = 0; + + if (rtlphy->pwrgroup_cnt >= 3) { + if (chnl <= 3) + chnlgroup = 0; + else if (chnl >= 4 && chnl <= 8) + chnlgroup = 1; + else if (chnl > 8) + chnlgroup = 2; + if (rtlphy->pwrgroup_cnt == 4) + chnlgroup++; + } + + writeval = rtlphy->mcs_offset[chnlgroup][index] + + ((index < 2) ? + pwrbase0 : pwrbase1); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Realtek regulatory, 20MHz, writeval = 0x%x\n", + writeval); + } + break; + case 2: + /* Better regulatory don't increase any power diff */ + writeval = ((index < 2) ? pwrbase0 : pwrbase1); + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Better regulatory, writeval = 0x%x\n", writeval); + break; + case 3: + /* Customer defined power diff. increase power diff + defined by customer. */ + chnlgroup = 0; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "customer's limit, 40MHz = 0x%x\n", + rtlefuse->pwrgroup_ht40 + [RF90_PATH_A][chnl - 1]); + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "customer's limit, 20MHz = 0x%x\n", + rtlefuse->pwrgroup_ht20 + [RF90_PATH_A][chnl - 1]); + } + + for (i = 0; i < 4; i++) { + pwrdiff_limit[i] = (u8)((rtlphy->mcs_offset + [chnlgroup][index] & (0x7f << (i * 8))) + >> (i * 8)); + + if (rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20_40) { + if (pwrdiff_limit[i] > + rtlefuse->pwrgroup_ht40 + [RF90_PATH_A][chnl - 1]) { + pwrdiff_limit[i] = + rtlefuse->pwrgroup_ht40 + [RF90_PATH_A][chnl - 1]; + } + } else { + if (pwrdiff_limit[i] > + rtlefuse->pwrgroup_ht20 + [RF90_PATH_A][chnl - 1]) { + pwrdiff_limit[i] = + rtlefuse->pwrgroup_ht20 + [RF90_PATH_A][chnl - 1]; + } + } + } + + customer_limit = (pwrdiff_limit[3] << 24) | + (pwrdiff_limit[2] << 16) | + (pwrdiff_limit[1] << 8) | + (pwrdiff_limit[0]); + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Customer's limit = 0x%x\n", customer_limit); + + writeval = customer_limit + ((index < 2) ? + pwrbase0 : pwrbase1); + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Customer, writeval = 0x%x\n", writeval); + break; + default: + chnlgroup = 0; + writeval = rtlphy->mcs_offset[chnlgroup][index] + + ((index < 2) ? pwrbase0 : pwrbase1); + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "RTK better performance, writeval = 0x%x\n", writeval); + break; + } + + if (rtlpriv->dm.dynamic_txhighpower_lvl == TX_HIGH_PWR_LEVEL_LEVEL1) + writeval = 0x10101010; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TX_HIGH_PWR_LEVEL_LEVEL2) + writeval = 0x0; + + *p_outwrite_val = writeval; + +} + +static void _rtl92s_write_ofdm_powerreg(struct ieee80211_hw *hw, + u8 index, u32 val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u16 regoffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c}; + u8 i, rfa_pwr[4]; + u8 rfa_lower_bound = 0, rfa_upper_bound = 0, rf_pwr_diff = 0; + u32 writeval = val; + + /* If path A and Path B coexist, we must limit Path A tx power. + * Protect Path B pwr over or under flow. We need to calculate + * upper and lower bound of path A tx power. */ + if (rtlphy->rf_type == RF_2T2R) { + rf_pwr_diff = rtlefuse->antenna_txpwdiff[0]; + + /* Diff=-8~-1 */ + if (rf_pwr_diff >= 8) { + /* Prevent underflow!! */ + rfa_lower_bound = 0x10 - rf_pwr_diff; + /* if (rf_pwr_diff >= 0) Diff = 0-7 */ + } else { + rfa_upper_bound = RF6052_MAX_TX_PWR - rf_pwr_diff; + } + } + + for (i = 0; i < 4; i++) { + rfa_pwr[i] = (u8)((writeval & (0x7f << (i * 8))) >> (i * 8)); + if (rfa_pwr[i] > RF6052_MAX_TX_PWR) + rfa_pwr[i] = RF6052_MAX_TX_PWR; + + /* If path A and Path B coexist, we must limit Path A tx power. + * Protect Path B pwr over or under flow. We need to calculate + * upper and lower bound of path A tx power. */ + if (rtlphy->rf_type == RF_2T2R) { + /* Diff=-8~-1 */ + if (rf_pwr_diff >= 8) { + /* Prevent underflow!! */ + if (rfa_pwr[i] < rfa_lower_bound) + rfa_pwr[i] = rfa_lower_bound; + /* Diff = 0-7 */ + } else if (rf_pwr_diff >= 1) { + /* Prevent overflow */ + if (rfa_pwr[i] > rfa_upper_bound) + rfa_pwr[i] = rfa_upper_bound; + } + } + + } + + writeval = (rfa_pwr[3] << 24) | (rfa_pwr[2] << 16) | (rfa_pwr[1] << 8) | + rfa_pwr[0]; + + rtl_set_bbreg(hw, regoffset[index], 0x7f7f7f7f, writeval); +} + +void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw, + u8 *p_pwrlevel, u8 chnl) +{ + u32 writeval, pwrbase0, pwrbase1; + u8 index = 0; + u8 finalpwr_idx[4]; + + _rtl92s_get_powerbase(hw, p_pwrlevel, chnl, &pwrbase0, &pwrbase1, + &finalpwr_idx[0]); + _rtl92s_set_antennadiff(hw, &finalpwr_idx[0]); + + for (index = 0; index < 6; index++) { + _rtl92s_get_txpower_writeval_byregulatory(hw, chnl, index, + pwrbase0, pwrbase1, &writeval); + + _rtl92s_write_ofdm_powerreg(hw, index, writeval); + } +} + +void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 txagc = 0; + bool dont_inc_cck_or_turboscanoff = false; + + if (((rtlefuse->eeprom_version >= 2) && + (rtlefuse->txpwr_safetyflag == 1)) || + ((rtlefuse->eeprom_version >= 2) && + (rtlefuse->eeprom_regulatory != 0))) + dont_inc_cck_or_turboscanoff = true; + + if (mac->act_scanning) { + txagc = 0x3f; + if (dont_inc_cck_or_turboscanoff) + txagc = pwrlevel; + } else { + txagc = pwrlevel; + + if (rtlpriv->dm.dynamic_txhighpower_lvl == + TX_HIGH_PWR_LEVEL_LEVEL1) + txagc = 0x10; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TX_HIGH_PWR_LEVEL_LEVEL2) + txagc = 0x0; + } + + if (txagc > RF6052_MAX_TX_PWR) + txagc = RF6052_MAX_TX_PWR; + + rtl_set_bbreg(hw, RTXAGC_CCK_MCS32, BTX_AGCRATECCK, txagc); + +} + +bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 u4reg_val = 0; + u8 rfpath; + bool rtstatus = true; + struct bb_reg_def *pphyreg; + + /* Initialize RF */ + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + + pphyreg = &rtlphy->phyreg_def[rfpath]; + + /* Store original RFENV control type */ + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + u4reg_val = rtl92s_phy_query_bb_reg(hw, + pphyreg->rfintfs, + BRFSI_RFENV); + break; + case RF90_PATH_B: + case RF90_PATH_D: + u4reg_val = rtl92s_phy_query_bb_reg(hw, + pphyreg->rfintfs, + BRFSI_RFENV << 16); + break; + } + + /* Set RF_ENV enable */ + rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfe, + BRFSI_RFENV << 16, 0x1); + + /* Set RF_ENV output high */ + rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); + + /* Set bit number of Address and Data for RF register */ + rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2, + B3WIRE_ADDRESSLENGTH, 0x0); + rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2, + B3WIRE_DATALENGTH, 0x0); + + /* Initialize RF fom connfiguration file */ + switch (rfpath) { + case RF90_PATH_A: + rtstatus = rtl92s_phy_config_rf(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_B: + rtstatus = rtl92s_phy_config_rf(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_C: + break; + case RF90_PATH_D: + break; + } + + /* Restore RFENV control type */ + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, BRFSI_RFENV, + u4reg_val); + break; + case RF90_PATH_B: + case RF90_PATH_D: + rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16, + u4reg_val); + break; + } + + if (!rtstatus) { + pr_err("Radio[%d] Fail!!\n", rfpath); + goto fail; + } + + } + + return rtstatus; + +fail: + return rtstatus; +} + +void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff) | 0x0400); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + case HT_CHANNEL_WIDTH_20_40: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff)); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", bandwidth); + break; + } +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h new file mode 100644 index 000000000000..8a29eb94ab17 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __INC_RTL92S_RF_H +#define __INC_RTL92S_RF_H + +#define RF6052_MAX_TX_PWR 0x3F + +void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, + u8 bandwidth); +bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw) ; +void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, + u8 powerlevel); +void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw, + u8 *p_pwrlevel, u8 chnl); + +#endif + diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c new file mode 100644 index 000000000000..e1fd27c888bf --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c @@ -0,0 +1,442 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../core.h" +#include "../base.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "hw.h" +#include "sw.h" +#include "trx.h" +#include "led.h" + +#include + +static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /* ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + * */ + rtlpci->const_pci_aspm = 2; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /* In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 2; + + /* This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 2; +} + +static void rtl92se_fw_cb(const struct firmware *firmware, void *context) +{ + struct ieee80211_hw *hw = context; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rt_firmware *pfirmware = NULL; + + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "Firmware callback routine entered!\n"); + complete(&rtlpriv->firmware_loading_complete); + if (!firmware) { + pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name); + rtlpriv->max_fw_size = 0; + return; + } + if (firmware->size > rtlpriv->max_fw_size) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Firmware is too big!\n"); + rtlpriv->max_fw_size = 0; + release_firmware(firmware); + return; + } + pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware; + memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size); + pfirmware->sz_fw_tmpbufferlen = firmware->size; + release_firmware(firmware); +} + +static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + int err = 0; + u16 earlyrxthreshold = 7; + + rtlpriv->dm.dm_initialgain_enable = true; + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.disable_framebursting = false; + rtlpriv->dm.thermalvalue = 0; + rtlpriv->dm.useramask = true; + + /* compatible 5G band 91se just 2.4G band & smsp */ + rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; + rtlpriv->rtlhal.bandset = BAND_ON_2_4G; + rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; + + rtlpci->transmit_config = 0; + + rtlpci->receive_config = + RCR_APPFCS | + RCR_APWRMGT | + /*RCR_ADD3 |*/ + RCR_AMF | + RCR_ADF | + RCR_APP_MIC | + RCR_APP_ICV | + RCR_AICV | + /* Accept ICV error, CRC32 Error */ + RCR_ACRC32 | + RCR_AB | + /* Accept Broadcast, Multicast */ + RCR_AM | + /* Accept Physical match */ + RCR_APM | + /* Accept Destination Address packets */ + /*RCR_AAP |*/ + RCR_APP_PHYST_STAFF | + /* Accept PHY status */ + RCR_APP_PHYST_RXFF | + (earlyrxthreshold << RCR_FIFO_OFFSET); + + rtlpci->irq_mask[0] = (u32) + (IMR_ROK | + IMR_VODOK | + IMR_VIDOK | + IMR_BEDOK | + IMR_BKDOK | + IMR_HCCADOK | + IMR_MGNTDOK | + IMR_COMDOK | + IMR_HIGHDOK | + IMR_BDOK | + IMR_RXCMDOK | + /*IMR_TIMEOUT0 |*/ + IMR_RDU | + IMR_RXFOVW | + IMR_BCNINT + /*| IMR_TXFOVW*/ + /*| IMR_TBDOK | + IMR_TBDER*/); + + rtlpci->irq_mask[1] = (u32) 0; + + rtlpci->shortretry_limit = 0x30; + rtlpci->longretry_limit = 0x30; + + 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; + rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; + if (!rtlpriv->psc.inactiveps) + pr_info("Power Save off (module option)\n"); + if (!rtlpriv->psc.fwctrl_lps) + pr_info("FW Power Save off (module option)\n"); + rtlpriv->psc.reg_fwctrl_lps = 3; + rtlpriv->psc.reg_max_lps_awakeintvl = 5; + /* for ASPM, you can close aspm through + * set const_support_pciaspm = 0 */ + rtl92s_init_aspm_vars(hw); + + if (rtlpriv->psc.reg_fwctrl_lps == 1) + rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 2) + rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 3) + rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(sizeof(struct rt_firmware)); + if (!rtlpriv->rtlhal.pfirmware) + return 1; + + rtlpriv->max_fw_size = RTL8190_MAX_FIRMWARE_CODE_SIZE*2 + + sizeof(struct fw_hdr); + pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n" + "Loading firmware %s\n", rtlpriv->cfg->fw_name); + /* request fw */ + err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, + rtlpriv->io.dev, GFP_KERNEL, hw, + rtl92se_fw_cb); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to request firmware!\n"); + return 1; + } + + return err; +} + +static void rtl92s_deinit_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.pfirmware) { + vfree(rtlpriv->rtlhal.pfirmware); + rtlpriv->rtlhal.pfirmware = NULL; + } +} + +static bool rtl92se_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, + u16 index) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; + u8 *entry = (u8 *)(&ring->desc[ring->idx]); + u8 own = (u8)rtl92se_get_desc(entry, true, HW_DESC_OWN); + + if (own) + return false; + return true; +} + +static struct rtl_hal_ops rtl8192se_hal_ops = { + .init_sw_vars = rtl92s_init_sw_vars, + .deinit_sw_vars = rtl92s_deinit_sw_vars, + .read_eeprom_info = rtl92se_read_eeprom_info, + .interrupt_recognized = rtl92se_interrupt_recognized, + .hw_init = rtl92se_hw_init, + .hw_disable = rtl92se_card_disable, + .hw_suspend = rtl92se_suspend, + .hw_resume = rtl92se_resume, + .enable_interrupt = rtl92se_enable_interrupt, + .disable_interrupt = rtl92se_disable_interrupt, + .set_network_type = rtl92se_set_network_type, + .set_chk_bssid = rtl92se_set_check_bssid, + .set_qos = rtl92se_set_qos, + .set_bcn_reg = rtl92se_set_beacon_related_registers, + .set_bcn_intv = rtl92se_set_beacon_interval, + .update_interrupt_mask = rtl92se_update_interrupt_mask, + .get_hw_reg = rtl92se_get_hw_reg, + .set_hw_reg = rtl92se_set_hw_reg, + .update_rate_tbl = rtl92se_update_hal_rate_tbl, + .fill_tx_desc = rtl92se_tx_fill_desc, + .fill_tx_cmddesc = rtl92se_tx_fill_cmddesc, + .query_rx_desc = rtl92se_rx_query_desc, + .set_channel_access = rtl92se_update_channel_access_setting, + .radio_onoff_checking = rtl92se_gpio_radio_on_off_checking, + .set_bw_mode = rtl92s_phy_set_bw_mode, + .switch_channel = rtl92s_phy_sw_chnl, + .dm_watchdog = rtl92s_dm_watchdog, + .scan_operation_backup = rtl92s_phy_scan_operation_backup, + .set_rf_power_state = rtl92s_phy_set_rf_power_state, + .led_control = rtl92se_led_control, + .set_desc = rtl92se_set_desc, + .get_desc = rtl92se_get_desc, + .is_tx_desc_closed = rtl92se_is_tx_desc_closed, + .tx_polling = rtl92se_tx_polling, + .enable_hw_sec = rtl92se_enable_hw_security_config, + .set_key = rtl92se_set_key, + .init_sw_leds = rtl92se_init_sw_leds, + .get_bbreg = rtl92s_phy_query_bb_reg, + .set_bbreg = rtl92s_phy_set_bb_reg, + .get_rfreg = rtl92s_phy_query_rf_reg, + .set_rfreg = rtl92s_phy_set_rf_reg, + .get_btc_status = rtl_btc_status_false, +}; + +static struct rtl_mod_params rtl92se_mod_params = { + .sw_crypto = false, + .inactiveps = true, + .swctrl_lps = true, + .fwctrl_lps = false, + .debug = DBG_EMERG, +}; + +/* Because memory R/W bursting will cause system hang/crash + * for 92se, so we don't read back after every write action */ +static struct rtl_hal_cfg rtl92se_hal_cfg = { + .bar_id = 1, + .write_readback = false, + .name = "rtl92s_pci", + .fw_name = "rtlwifi/rtl8192sefw.bin", + .ops = &rtl8192se_hal_ops, + .mod_params = &rtl92se_mod_params, + + .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, + .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, + .maps[SYS_CLK] = SYS_CLKR, + .maps[MAC_RCR_AM] = RCR_AM, + .maps[MAC_RCR_AB] = RCR_AB, + .maps[MAC_RCR_ACRC32] = RCR_ACRC32, + .maps[MAC_RCR_ACF] = RCR_ACF, + .maps[MAC_RCR_AAP] = RCR_AAP, + .maps[MAC_HIMR] = INTA_MASK, + .maps[MAC_HIMRE] = INTA_MASK + 4, + + .maps[EFUSE_TEST] = REG_EFUSE_TEST, + .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_CLK] = REG_EFUSE_CLK, + .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_PWC_EV12V] = 0, /* nouse for 8192se */ + .maps[EFUSE_FEN_ELDR] = 0, /* nouse for 8192se */ + .maps[EFUSE_LOADER_CLK_EN] = 0,/* nouse for 8192se */ + .maps[EFUSE_ANA8M] = EFUSE_ANA8M, + .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE_92S, + .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, + .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, + .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, + + .maps[RWCAM] = REG_RWCAM, + .maps[WCAMI] = REG_WCAMI, + .maps[RCAMO] = REG_RCAMO, + .maps[CAMDBG] = REG_CAMDBG, + .maps[SECR] = REG_SECR, + .maps[SEC_CAM_NONE] = CAM_NONE, + .maps[SEC_CAM_WEP40] = CAM_WEP40, + .maps[SEC_CAM_TKIP] = CAM_TKIP, + .maps[SEC_CAM_AES] = CAM_AES, + .maps[SEC_CAM_WEP104] = CAM_WEP104, + + .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, + .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, + .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, + .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, + .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, + .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, + .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, + .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, + .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, + .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, + .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, + .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, + .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, + .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, + .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, + .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, + + .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, + .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, + .maps[RTL_IMR_BCNINT] = IMR_BCNINT, + .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, + .maps[RTL_IMR_RDU] = IMR_RDU, + .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, + .maps[RTL_IMR_BDOK] = IMR_BDOK, + .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, + .maps[RTL_IMR_TBDER] = IMR_TBDER, + .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, + .maps[RTL_IMR_COMDOK] = IMR_COMDOK, + .maps[RTL_IMR_TBDOK] = IMR_TBDOK, + .maps[RTL_IMR_BKDOK] = IMR_BKDOK, + .maps[RTL_IMR_BEDOK] = IMR_BEDOK, + .maps[RTL_IMR_VIDOK] = IMR_VIDOK, + .maps[RTL_IMR_VODOK] = IMR_VODOK, + .maps[RTL_IMR_ROK] = IMR_ROK, + .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), + + .maps[RTL_RC_CCK_RATE1M] = DESC_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC_RATEMCS15, +}; + +static struct pci_device_id rtl92se_pci_ids[] = { + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8192, rtl92se_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8171, rtl92se_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8172, rtl92se_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8173, rtl92se_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8174, rtl92se_hal_cfg)}, + {}, +}; + +MODULE_DEVICE_TABLE(pci, rtl92se_pci_ids); + +MODULE_AUTHOR("lizhaoming "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +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(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); +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)"); + +static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); + +static struct pci_driver rtl92se_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl92se_pci_ids, + .probe = rtl_pci_probe, + .remove = rtl_pci_disconnect, + .driver.pm = &rtlwifi_pm_ops, +}; + +module_pci_driver(rtl92se_driver); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h new file mode 100644 index 000000000000..2eb88862ebe4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + *****************************************************************************/ +#ifndef __REALTEK_PCI92SE_SW_H__ +#define __REALTEK_PCI92SE_SW_H__ + +#define EFUSE_MAX_SECTION 16 + +int rtl92se_init_sw(struct ieee80211_hw *hw); +void rtl92se_deinit_sw(struct ieee80211_hw *hw); +void rtl92se_init_var_map(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c new file mode 100644 index 000000000000..f1a73f75127e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.c @@ -0,0 +1,634 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + * Created on 2010/ 5/18, 1:41 + *****************************************************************************/ + +#include "table.h" + +u32 rtl8192sephy_reg_2t2rarray[PHY_REG_2T2RARRAYLENGTH] = { + 0x01c, 0x07000000, + 0x800, 0x00040000, + 0x804, 0x00008003, + 0x808, 0x0000fc00, + 0x80c, 0x0000000a, + 0x810, 0x10005088, + 0x814, 0x020c3d10, + 0x818, 0x00200185, + 0x81c, 0x00000000, + 0x820, 0x01000000, + 0x824, 0x00390004, + 0x828, 0x01000000, + 0x82c, 0x00390004, + 0x830, 0x00000004, + 0x834, 0x00690200, + 0x838, 0x00000004, + 0x83c, 0x00690200, + 0x840, 0x00010000, + 0x844, 0x00010000, + 0x848, 0x00000000, + 0x84c, 0x00000000, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x48484848, + 0x85c, 0x65a965a9, + 0x860, 0x0f7f0130, + 0x864, 0x0f7f0130, + 0x868, 0x0f7f0130, + 0x86c, 0x0f7f0130, + 0x870, 0x03000700, + 0x874, 0x03000300, + 0x878, 0x00020002, + 0x87c, 0x004f0201, + 0x880, 0xa8300ac1, + 0x884, 0x00000058, + 0x888, 0x00000008, + 0x88c, 0x00000004, + 0x890, 0x00000000, + 0x894, 0xfffffffe, + 0x898, 0x40302010, + 0x89c, 0x00706050, + 0x8b0, 0x00000000, + 0x8e0, 0x00000000, + 0x8e4, 0x00000000, + 0xe00, 0x30333333, + 0xe04, 0x2a2d2e2f, + 0xe08, 0x00003232, + 0xe10, 0x30333333, + 0xe14, 0x2a2d2e2f, + 0xe18, 0x30333333, + 0xe1c, 0x2a2d2e2f, + 0xe30, 0x01007c00, + 0xe34, 0x01004800, + 0xe38, 0x1000dc1f, + 0xe3c, 0x10008c1f, + 0xe40, 0x021400a0, + 0xe44, 0x281600a0, + 0xe48, 0xf8000001, + 0xe4c, 0x00002910, + 0xe50, 0x01007c00, + 0xe54, 0x01004800, + 0xe58, 0x1000dc1f, + 0xe5c, 0x10008c1f, + 0xe60, 0x021400a0, + 0xe64, 0x281600a0, + 0xe6c, 0x00002910, + 0xe70, 0x31ed92fb, + 0xe74, 0x361536fb, + 0xe78, 0x361536fb, + 0xe7c, 0x361536fb, + 0xe80, 0x361536fb, + 0xe84, 0x000d92fb, + 0xe88, 0x000d92fb, + 0xe8c, 0x31ed92fb, + 0xed0, 0x31ed92fb, + 0xed4, 0x31ed92fb, + 0xed8, 0x000d92fb, + 0xedc, 0x000d92fb, + 0xee0, 0x000d92fb, + 0xee4, 0x015e5448, + 0xee8, 0x21555448, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90c, 0x01121313, + 0xa00, 0x00d047c8, + 0xa04, 0x80ff0008, + 0xa08, 0x8ccd8300, + 0xa0c, 0x2e62120f, + 0xa10, 0x9500bb78, + 0xa14, 0x11144028, + 0xa18, 0x00881117, + 0xa1c, 0x89140f00, + 0xa20, 0x1a1b0000, + 0xa24, 0x090e1317, + 0xa28, 0x00000204, + 0xa2c, 0x10d30000, + 0xc00, 0x40071d40, + 0xc04, 0x00a05633, + 0xc08, 0x000000e4, + 0xc0c, 0x6c6c6c6c, + 0xc10, 0x08800000, + 0xc14, 0x40000100, + 0xc18, 0x08000000, + 0xc1c, 0x40000100, + 0xc20, 0x08000000, + 0xc24, 0x40000100, + 0xc28, 0x08000000, + 0xc2c, 0x40000100, + 0xc30, 0x6de9ac44, + 0xc34, 0x469652cf, + 0xc38, 0x49795994, + 0xc3c, 0x0a979764, + 0xc40, 0x1f7c403f, + 0xc44, 0x000100b7, + 0xc48, 0xec020000, + 0xc4c, 0x007f037f, + 0xc50, 0x69543420, + 0xc54, 0x433c0094, + 0xc58, 0x69543420, + 0xc5c, 0x433c0094, + 0xc60, 0x69543420, + 0xc64, 0x433c0094, + 0xc68, 0x69543420, + 0xc6c, 0x433c0094, + 0xc70, 0x2c7f000d, + 0xc74, 0x0186155b, + 0xc78, 0x0000001f, + 0xc7c, 0x00b91612, + 0xc80, 0x40000100, + 0xc84, 0x20f60000, + 0xc88, 0x20000080, + 0xc8c, 0x20200000, + 0xc90, 0x40000100, + 0xc94, 0x00000000, + 0xc98, 0x40000100, + 0xc9c, 0x00000000, + 0xca0, 0x00492492, + 0xca4, 0x00000000, + 0xca8, 0x00000000, + 0xcac, 0x00000000, + 0xcb0, 0x00000000, + 0xcb4, 0x00000000, + 0xcb8, 0x00000000, + 0xcbc, 0x28000000, + 0xcc0, 0x00000000, + 0xcc4, 0x00000000, + 0xcc8, 0x00000000, + 0xccc, 0x00000000, + 0xcd0, 0x00000000, + 0xcd4, 0x00000000, + 0xcd8, 0x64b22427, + 0xcdc, 0x00766932, + 0xce0, 0x00222222, + 0xce4, 0x00000000, + 0xce8, 0x37644302, + 0xcec, 0x2f97d40c, + 0xd00, 0x00000750, + 0xd04, 0x00000403, + 0xd08, 0x0000907f, + 0xd0c, 0x00000001, + 0xd10, 0xa0633333, + 0xd14, 0x33333c63, + 0xd18, 0x6a8f5b6b, + 0xd1c, 0x00000000, + 0xd20, 0x00000000, + 0xd24, 0x00000000, + 0xd28, 0x00000000, + 0xd2c, 0xcc979975, + 0xd30, 0x00000000, + 0xd34, 0x00000000, + 0xd38, 0x00000000, + 0xd3c, 0x00027293, + 0xd40, 0x00000000, + 0xd44, 0x00000000, + 0xd48, 0x00000000, + 0xd50, 0x6437140a, + 0xd54, 0x024dbd02, + 0xd58, 0x00000000, + 0xd5c, 0x30032064, + 0xd60, 0x4653de68, + 0xd64, 0x00518a3c, + 0xd68, 0x00002101, + 0xf14, 0x00000003, + 0xf4c, 0x00000000, + 0xf00, 0x00000300, +}; + +u32 rtl8192sephy_changeto_1t1rarray[PHY_CHANGETO_1T1RARRAYLENGTH] = { + 0x844, 0xffffffff, 0x00010000, + 0x804, 0x0000000f, 0x00000001, + 0x824, 0x00f0000f, 0x00300004, + 0x82c, 0x00f0000f, 0x00100002, + 0x870, 0x04000000, 0x00000001, + 0x864, 0x00000400, 0x00000000, + 0x878, 0x000f000f, 0x00000002, + 0xe74, 0x0f000000, 0x00000002, + 0xe78, 0x0f000000, 0x00000002, + 0xe7c, 0x0f000000, 0x00000002, + 0xe80, 0x0f000000, 0x00000002, + 0x90c, 0x000000ff, 0x00000011, + 0xc04, 0x000000ff, 0x00000011, + 0xd04, 0x0000000f, 0x00000001, + 0x1f4, 0xffff0000, 0x00007777, + 0x234, 0xf8000000, 0x0000000a, +}; + +u32 rtl8192sephy_changeto_1t2rarray[PHY_CHANGETO_1T2RARRAYLENGTH] = { + 0x804, 0x0000000f, 0x00000003, + 0x824, 0x00f0000f, 0x00300004, + 0x82c, 0x00f0000f, 0x00300002, + 0x870, 0x04000000, 0x00000001, + 0x864, 0x00000400, 0x00000000, + 0x878, 0x000f000f, 0x00000002, + 0xe74, 0x0f000000, 0x00000002, + 0xe78, 0x0f000000, 0x00000002, + 0xe7c, 0x0f000000, 0x00000002, + 0xe80, 0x0f000000, 0x00000002, + 0x90c, 0x000000ff, 0x00000011, + 0xc04, 0x000000ff, 0x00000033, + 0xd04, 0x0000000f, 0x00000003, + 0x1f4, 0xffff0000, 0x00007777, + 0x234, 0xf8000000, 0x0000000a, +}; + +u32 rtl8192sephy_reg_array_pg[PHY_REG_ARRAY_PGLENGTH] = { + 0xe00, 0xffffffff, 0x06090909, + 0xe04, 0xffffffff, 0x00030406, + 0xe08, 0x0000ff00, 0x00000000, + 0xe10, 0xffffffff, 0x0a0c0d0e, + 0xe14, 0xffffffff, 0x04070809, + 0xe18, 0xffffffff, 0x0a0c0d0e, + 0xe1c, 0xffffffff, 0x04070809, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0xe10, 0xffffffff, 0x02040404, + 0xe14, 0xffffffff, 0x00000002, + 0xe18, 0xffffffff, 0x02040404, + 0xe1c, 0xffffffff, 0x00000002, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0xe10, 0xffffffff, 0x02040404, + 0xe14, 0xffffffff, 0x00000002, + 0xe18, 0xffffffff, 0x02040404, + 0xe1c, 0xffffffff, 0x00000002, + 0xe00, 0xffffffff, 0x02020202, + 0xe04, 0xffffffff, 0x00020202, + 0xe08, 0x0000ff00, 0x00000000, + 0xe10, 0xffffffff, 0x02020202, + 0xe14, 0xffffffff, 0x00000002, + 0xe18, 0xffffffff, 0x02020202, + 0xe1c, 0xffffffff, 0x00000002, +}; + +u32 rtl8192seradioa_1t_array[RADIOA_1T_ARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00030250, + 0x002, 0x00010000, + 0x010, 0x0008000f, + 0x011, 0x000231fc, + 0x010, 0x000c000f, + 0x011, 0x0003f9f8, + 0x010, 0x0002000f, + 0x011, 0x00020101, + 0x014, 0x0001093e, + 0x014, 0x0009093e, + 0x015, 0x0000f8f4, + 0x017, 0x000f6500, + 0x01a, 0x00013056, + 0x01b, 0x00060000, + 0x01c, 0x00000300, + 0x01e, 0x00031059, + 0x021, 0x00054000, + 0x022, 0x0000083c, + 0x023, 0x00001558, + 0x024, 0x00000060, + 0x025, 0x00022583, + 0x026, 0x0000f200, + 0x027, 0x000eacf1, + 0x028, 0x0009bd54, + 0x029, 0x00004582, + 0x02a, 0x00000001, + 0x02b, 0x00021334, + 0x02a, 0x00000000, + 0x02b, 0x0000000a, + 0x02a, 0x00000001, + 0x02b, 0x00000808, + 0x02b, 0x00053333, + 0x02c, 0x0000000c, + 0x02a, 0x00000002, + 0x02b, 0x00000808, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000003, + 0x02b, 0x00000808, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000004, + 0x02b, 0x00000808, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000005, + 0x02b, 0x00000709, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x00000006, + 0x02b, 0x00000709, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000007, + 0x02b, 0x00000709, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000008, + 0x02b, 0x00000709, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000009, + 0x02b, 0x0000060a, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000a, + 0x02b, 0x0000060a, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000b, + 0x02b, 0x0000060a, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000c, + 0x02b, 0x0000060a, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000d, + 0x02b, 0x0000050b, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000e, + 0x02b, 0x0000050b, + 0x02b, 0x00066623, + 0x02c, 0x0000001a, + 0x02a, 0x000e4000, + 0x030, 0x00020000, + 0x031, 0x000b9631, + 0x032, 0x0000130d, + 0x033, 0x00000187, + 0x013, 0x00019e6c, + 0x013, 0x00015e94, + 0x000, 0x00010159, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x01e, 0x0003105b, + 0x0fe, 0x00000000, + 0x000, 0x00030159, + 0x010, 0x0004000f, + 0x011, 0x000203f9, +}; + +u32 rtl8192seradiob_array[RADIOB_ARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00001041, + 0x002, 0x00011000, + 0x005, 0x00080fc0, + 0x007, 0x000fc803, + 0x013, 0x00017cb0, + 0x013, 0x00011cc0, + 0x013, 0x0000dc60, + 0x013, 0x00008c60, + 0x013, 0x00004450, + 0x013, 0x00000020, +}; + +u32 rtl8192seradiob_gm_array[RADIOB_GM_ARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00001041, + 0x002, 0x00011000, + 0x005, 0x00080fc0, + 0x007, 0x000fc803, +}; + +u32 rtl8192semac_2t_array[MAC_2T_ARRAYLENGTH] = { + 0x020, 0x00000035, + 0x048, 0x0000000e, + 0x049, 0x000000f0, + 0x04a, 0x00000077, + 0x04b, 0x00000083, + 0x0b5, 0x00000021, + 0x0dc, 0x000000ff, + 0x0dd, 0x000000ff, + 0x0de, 0x000000ff, + 0x0df, 0x000000ff, + 0x116, 0x00000000, + 0x117, 0x00000000, + 0x118, 0x00000000, + 0x119, 0x00000000, + 0x11a, 0x00000000, + 0x11b, 0x00000000, + 0x11c, 0x00000000, + 0x11d, 0x00000000, + 0x160, 0x0000000b, + 0x161, 0x0000000b, + 0x162, 0x0000000b, + 0x163, 0x0000000b, + 0x164, 0x0000000b, + 0x165, 0x0000000b, + 0x166, 0x0000000b, + 0x167, 0x0000000b, + 0x168, 0x0000000b, + 0x169, 0x0000000b, + 0x16a, 0x0000000b, + 0x16b, 0x0000000b, + 0x16c, 0x0000000b, + 0x16d, 0x0000000b, + 0x16e, 0x0000000b, + 0x16f, 0x0000000b, + 0x170, 0x0000000b, + 0x171, 0x0000000b, + 0x172, 0x0000000b, + 0x173, 0x0000000b, + 0x174, 0x0000000b, + 0x175, 0x0000000b, + 0x176, 0x0000000b, + 0x177, 0x0000000b, + 0x178, 0x0000000b, + 0x179, 0x0000000b, + 0x17a, 0x0000000b, + 0x17b, 0x0000000b, + 0x17c, 0x0000000b, + 0x17d, 0x0000000b, + 0x17e, 0x0000000b, + 0x17f, 0x0000000b, + 0x236, 0x0000000c, + 0x503, 0x00000022, + 0x560, 0x00000000, +}; + +u32 rtl8192seagctab_array[AGCTAB_ARRAYLENGTH] = { + 0xc78, 0x7f000001, + 0xc78, 0x7f010001, + 0xc78, 0x7e020001, + 0xc78, 0x7d030001, + 0xc78, 0x7c040001, + 0xc78, 0x7b050001, + 0xc78, 0x7a060001, + 0xc78, 0x79070001, + 0xc78, 0x78080001, + 0xc78, 0x77090001, + 0xc78, 0x760a0001, + 0xc78, 0x750b0001, + 0xc78, 0x740c0001, + 0xc78, 0x730d0001, + 0xc78, 0x720e0001, + 0xc78, 0x710f0001, + 0xc78, 0x70100001, + 0xc78, 0x6f110001, + 0xc78, 0x6f120001, + 0xc78, 0x6e130001, + 0xc78, 0x6d140001, + 0xc78, 0x6d150001, + 0xc78, 0x6c160001, + 0xc78, 0x6b170001, + 0xc78, 0x6a180001, + 0xc78, 0x6a190001, + 0xc78, 0x691a0001, + 0xc78, 0x681b0001, + 0xc78, 0x671c0001, + 0xc78, 0x661d0001, + 0xc78, 0x651e0001, + 0xc78, 0x641f0001, + 0xc78, 0x63200001, + 0xc78, 0x4c210001, + 0xc78, 0x4b220001, + 0xc78, 0x4a230001, + 0xc78, 0x49240001, + 0xc78, 0x48250001, + 0xc78, 0x47260001, + 0xc78, 0x46270001, + 0xc78, 0x45280001, + 0xc78, 0x44290001, + 0xc78, 0x2c2a0001, + 0xc78, 0x2b2b0001, + 0xc78, 0x2a2c0001, + 0xc78, 0x292d0001, + 0xc78, 0x282e0001, + 0xc78, 0x272f0001, + 0xc78, 0x26300001, + 0xc78, 0x25310001, + 0xc78, 0x24320001, + 0xc78, 0x23330001, + 0xc78, 0x22340001, + 0xc78, 0x09350001, + 0xc78, 0x08360001, + 0xc78, 0x07370001, + 0xc78, 0x06380001, + 0xc78, 0x05390001, + 0xc78, 0x043a0001, + 0xc78, 0x033b0001, + 0xc78, 0x023c0001, + 0xc78, 0x013d0001, + 0xc78, 0x003e0001, + 0xc78, 0x003f0001, + 0xc78, 0x7f400001, + 0xc78, 0x7f410001, + 0xc78, 0x7e420001, + 0xc78, 0x7d430001, + 0xc78, 0x7c440001, + 0xc78, 0x7b450001, + 0xc78, 0x7a460001, + 0xc78, 0x79470001, + 0xc78, 0x78480001, + 0xc78, 0x77490001, + 0xc78, 0x764a0001, + 0xc78, 0x754b0001, + 0xc78, 0x744c0001, + 0xc78, 0x734d0001, + 0xc78, 0x724e0001, + 0xc78, 0x714f0001, + 0xc78, 0x70500001, + 0xc78, 0x6f510001, + 0xc78, 0x6f520001, + 0xc78, 0x6e530001, + 0xc78, 0x6d540001, + 0xc78, 0x6d550001, + 0xc78, 0x6c560001, + 0xc78, 0x6b570001, + 0xc78, 0x6a580001, + 0xc78, 0x6a590001, + 0xc78, 0x695a0001, + 0xc78, 0x685b0001, + 0xc78, 0x675c0001, + 0xc78, 0x665d0001, + 0xc78, 0x655e0001, + 0xc78, 0x645f0001, + 0xc78, 0x63600001, + 0xc78, 0x4c610001, + 0xc78, 0x4b620001, + 0xc78, 0x4a630001, + 0xc78, 0x49640001, + 0xc78, 0x48650001, + 0xc78, 0x47660001, + 0xc78, 0x46670001, + 0xc78, 0x45680001, + 0xc78, 0x44690001, + 0xc78, 0x2c6a0001, + 0xc78, 0x2b6b0001, + 0xc78, 0x2a6c0001, + 0xc78, 0x296d0001, + 0xc78, 0x286e0001, + 0xc78, 0x276f0001, + 0xc78, 0x26700001, + 0xc78, 0x25710001, + 0xc78, 0x24720001, + 0xc78, 0x23730001, + 0xc78, 0x22740001, + 0xc78, 0x09750001, + 0xc78, 0x08760001, + 0xc78, 0x07770001, + 0xc78, 0x06780001, + 0xc78, 0x05790001, + 0xc78, 0x047a0001, + 0xc78, 0x037b0001, + 0xc78, 0x027c0001, + 0xc78, 0x017d0001, + 0xc78, 0x007e0001, + 0xc78, 0x007f0001, + 0xc78, 0x3000001e, + 0xc78, 0x3001001e, + 0xc78, 0x3002001e, + 0xc78, 0x3003001e, + 0xc78, 0x3004001e, + 0xc78, 0x3405001e, + 0xc78, 0x3806001e, + 0xc78, 0x3e07001e, + 0xc78, 0x3e08001e, + 0xc78, 0x4409001e, + 0xc78, 0x460a001e, + 0xc78, 0x480b001e, + 0xc78, 0x480c001e, + 0xc78, 0x4e0d001e, + 0xc78, 0x560e001e, + 0xc78, 0x5a0f001e, + 0xc78, 0x5e10001e, + 0xc78, 0x6211001e, + 0xc78, 0x6c12001e, + 0xc78, 0x7213001e, + 0xc78, 0x7214001e, + 0xc78, 0x7215001e, + 0xc78, 0x7216001e, + 0xc78, 0x7217001e, + 0xc78, 0x7218001e, + 0xc78, 0x7219001e, + 0xc78, 0x721a001e, + 0xc78, 0x721b001e, + 0xc78, 0x721c001e, + 0xc78, 0x721d001e, + 0xc78, 0x721e001e, + 0xc78, 0x721f001e, +}; + diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h new file mode 100644 index 000000000000..2feb73b71a4f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/table.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2012 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * + * Larry Finger + * + ******************************************************************************/ +#ifndef __INC_HAL8192SE_FW_IMG_H +#define __INC_HAL8192SE_FW_IMG_H + +#include + +/*Created on 2010/ 4/12, 5:56*/ + +#define PHY_REG_2T2RARRAYLENGTH 372 +extern u32 rtl8192sephy_reg_2t2rarray[PHY_REG_2T2RARRAYLENGTH]; +#define PHY_CHANGETO_1T1RARRAYLENGTH 48 +extern u32 rtl8192sephy_changeto_1t1rarray[PHY_CHANGETO_1T1RARRAYLENGTH]; +#define PHY_CHANGETO_1T2RARRAYLENGTH 45 +extern u32 rtl8192sephy_changeto_1t2rarray[PHY_CHANGETO_1T2RARRAYLENGTH]; +#define PHY_REG_ARRAY_PGLENGTH 84 +extern u32 rtl8192sephy_reg_array_pg[PHY_REG_ARRAY_PGLENGTH]; +#define RADIOA_1T_ARRAYLENGTH 202 +extern u32 rtl8192seradioa_1t_array[RADIOA_1T_ARRAYLENGTH]; +#define RADIOB_ARRAYLENGTH 22 +extern u32 rtl8192seradiob_array[RADIOB_ARRAYLENGTH]; +#define RADIOB_GM_ARRAYLENGTH 10 +extern u32 rtl8192seradiob_gm_array[RADIOB_GM_ARRAYLENGTH]; +#define MAC_2T_ARRAYLENGTH 106 +extern u32 rtl8192semac_2t_array[MAC_2T_ARRAYLENGTH]; +#define AGCTAB_ARRAYLENGTH 320 +extern u32 rtl8192seagctab_array[AGCTAB_ARRAYLENGTH]; + +#endif + diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c new file mode 100644 index 000000000000..125b29bd2f93 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c @@ -0,0 +1,658 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../stats.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "fw.h" +#include "trx.h" +#include "led.h" + +static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) +{ + __le16 fc = rtl_get_fc(skb); + + if (unlikely(ieee80211_is_beacon(fc))) + return QSLT_BEACON; + if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) + return QSLT_MGNT; + if (ieee80211_is_nullfunc(fc)) + return QSLT_HIGH; + + /* Kernel commit 1bf4bbb4024dcdab changed EAPOL packets to use + * queue V0 at priority 7; however, the RTL8192SE appears to have + * that queue at priority 6 + */ + if (skb->priority == 7) + return QSLT_VO; + return skb->priority; +} + +static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, + struct rtl_stats *pstats, u8 *pdesc, + struct rx_fwinfo *p_drvinfo, + bool packet_match_bssid, + bool packet_toself, + bool packet_beacon) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct phy_sts_cck_8192s_t *cck_buf; + struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); + s8 rx_pwr_all = 0, rx_pwr[4]; + u8 rf_rx_num = 0, evm, pwdb_all; + u8 i, max_spatial_stream; + u32 rssi, total_rssi = 0; + bool is_cck = pstats->is_cck; + + pstats->packet_matchbssid = packet_match_bssid; + pstats->packet_toself = packet_toself; + pstats->packet_beacon = packet_beacon; + pstats->rx_mimo_sig_qual[0] = -1; + pstats->rx_mimo_sig_qual[1] = -1; + + if (is_cck) { + u8 report, cck_highpwr; + cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; + + if (ppsc->rfpwr_state == ERFON) + cck_highpwr = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + 0x200); + else + cck_highpwr = false; + + if (!cck_highpwr) { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = cck_buf->cck_agc_rpt & 0xc0; + report = report >> 6; + switch (report) { + case 0x3: + rx_pwr_all = -40 - (cck_agc_rpt & 0x3e); + break; + case 0x2: + rx_pwr_all = -20 - (cck_agc_rpt & 0x3e); + break; + case 0x1: + rx_pwr_all = -2 - (cck_agc_rpt & 0x3e); + break; + case 0x0: + rx_pwr_all = 14 - (cck_agc_rpt & 0x3e); + break; + } + } else { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = p_drvinfo->cfosho[0] & 0x60; + report = report >> 5; + switch (report) { + case 0x3: + rx_pwr_all = -40 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x2: + rx_pwr_all = -20 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x1: + rx_pwr_all = -2 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x0: + rx_pwr_all = 14 - ((cck_agc_rpt & 0x1f) << 1); + break; + } + } + + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + + /* CCK gain is smaller than OFDM/MCS gain, */ + /* so we add gain diff by experiences, the val is 6 */ + pwdb_all += 6; + if (pwdb_all > 100) + pwdb_all = 100; + /* modify the offset to make the same gain index with OFDM. */ + if (pwdb_all > 34 && pwdb_all <= 42) + pwdb_all -= 2; + else if (pwdb_all > 26 && pwdb_all <= 34) + pwdb_all -= 6; + else if (pwdb_all > 14 && pwdb_all <= 26) + pwdb_all -= 8; + else if (pwdb_all > 4 && pwdb_all <= 14) + pwdb_all -= 4; + + pstats->rx_pwdb_all = pwdb_all; + pstats->recvsignalpower = rx_pwr_all; + + if (packet_match_bssid) { + u8 sq; + if (pstats->rx_pwdb_all > 40) { + sq = 100; + } else { + sq = cck_buf->sq_rpt; + if (sq > 64) + sq = 0; + else if (sq < 20) + sq = 100; + else + sq = ((64 - sq) * 100) / 44; + } + + pstats->signalquality = sq; + pstats->rx_mimo_sig_qual[0] = sq; + pstats->rx_mimo_sig_qual[1] = -1; + } + } else { + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { + if (rtlpriv->dm.rfpath_rxenable[i]) + rf_rx_num++; + + rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & + 0x3f) * 2) - 110; + rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + rtlpriv->stats.rx_snr_db[i] = + (long)(p_drvinfo->rxsnr[i] / 2); + + if (packet_match_bssid) + pstats->rx_mimo_signalstrength[i] = (u8) rssi; + } + + rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + pstats->rx_pwdb_all = pwdb_all; + pstats->rxpower = rx_pwr_all; + pstats->recvsignalpower = rx_pwr_all; + + if (pstats->is_ht && pstats->rate >= DESC_RATEMCS8 && + pstats->rate <= DESC_RATEMCS15) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + + for (i = 0; i < max_spatial_stream; i++) { + evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]); + + if (packet_match_bssid) { + if (i == 0) + pstats->signalquality = (u8)(evm & + 0xff); + pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff); + } + } + } + + if (is_cck) + pstats->signalstrength = (u8)(rtl_signal_scale_mapping(hw, + pwdb_all)); + else if (rf_rx_num != 0) + pstats->signalstrength = (u8) (rtl_signal_scale_mapping(hw, + total_rssi /= rf_rx_num)); +} + +static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, + struct sk_buff *skb, struct rtl_stats *pstats, + u8 *pdesc, struct rx_fwinfo *p_drvinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + + struct ieee80211_hdr *hdr; + u8 *tmp_buf; + u8 *praddr; + __le16 fc; + u16 type, cfc; + bool packet_matchbssid, packet_toself, packet_beacon = false; + + tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; + + hdr = (struct ieee80211_hdr *)tmp_buf; + fc = hdr->frame_control; + cfc = le16_to_cpu(fc); + type = WLAN_FC_GET_TYPE(fc); + praddr = hdr->addr1; + + packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && + ether_addr_equal(mac->bssid, + (cfc & IEEE80211_FCTL_TODS) ? hdr->addr1 : + (cfc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : + hdr->addr3) && + (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv)); + + packet_toself = packet_matchbssid && + ether_addr_equal(praddr, rtlefuse->dev_addr); + + if (ieee80211_is_beacon(fc)) + packet_beacon = true; + + _rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, + packet_matchbssid, packet_toself, packet_beacon); + rtl_process_phyinfo(hw, tmp_buf, pstats); +} + +bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, u8 *pdesc, + struct sk_buff *skb) +{ + struct rx_fwinfo *p_drvinfo; + u32 phystatus = (u32)GET_RX_STATUS_DESC_PHY_STATUS(pdesc); + struct ieee80211_hdr *hdr; + + stats->length = (u16)GET_RX_STATUS_DESC_PKT_LEN(pdesc); + stats->rx_drvinfo_size = (u8)GET_RX_STATUS_DESC_DRVINFO_SIZE(pdesc) * 8; + stats->rx_bufshift = (u8)(GET_RX_STATUS_DESC_SHIFT(pdesc) & 0x03); + stats->icv = (u16)GET_RX_STATUS_DESC_ICV(pdesc); + stats->crc = (u16)GET_RX_STATUS_DESC_CRC32(pdesc); + stats->hwerror = (u16)(stats->crc | stats->icv); + stats->decrypted = !GET_RX_STATUS_DESC_SWDEC(pdesc); + + stats->rate = (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc); + stats->shortpreamble = (u16)GET_RX_STATUS_DESC_SPLCP(pdesc); + stats->isampdu = (bool)(GET_RX_STATUS_DESC_PAGGR(pdesc) == 1); + stats->isfirst_ampdu = (bool) ((GET_RX_STATUS_DESC_PAGGR(pdesc) == 1) + && (GET_RX_STATUS_DESC_FAGGR(pdesc) == 1)); + stats->timestamp_low = GET_RX_STATUS_DESC_TSFL(pdesc); + stats->rx_is40Mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc); + stats->is_ht = (bool)GET_RX_STATUS_DESC_RX_HT(pdesc); + stats->is_cck = SE_RX_HAL_IS_CCK_RATE(pdesc); + + if (stats->hwerror) + return false; + + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + + if (stats->crc) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (stats->rx_is40Mhzpacket) + rx_status->flag |= RX_FLAG_40MHZ; + + if (stats->is_ht) + rx_status->flag |= RX_FLAG_HT; + + rx_status->flag |= RX_FLAG_MACTIME_START; + + /* hw will set stats->decrypted true, if it finds the + * frame is open data frame or mgmt frame, + * hw will not decrypt robust managment frame + * for IEEE80211w but still set stats->decrypted + * true, so here we should set it back to undecrypted + * for IEEE80211w frame, and mac80211 sw will help + * to decrypt it */ + if (stats->decrypted) { + hdr = (struct ieee80211_hdr *)(skb->data + + stats->rx_drvinfo_size + stats->rx_bufshift); + + if ((_ieee80211_is_robust_mgmt_frame(hdr)) && + (ieee80211_has_protected(hdr->frame_control))) + rx_status->flag &= ~RX_FLAG_DECRYPTED; + else + rx_status->flag |= RX_FLAG_DECRYPTED; + } + + rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht, + false, stats->rate); + + rx_status->mactime = stats->timestamp_low; + if (phystatus) { + p_drvinfo = (struct rx_fwinfo *)(skb->data + + stats->rx_bufshift); + _rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc, + p_drvinfo); + } + + /*rx_status->qual = stats->signal; */ + rx_status->signal = stats->recvsignalpower + 10; + + return true; +} + +void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *pbd_desc_tx, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 *pdesc = pdesc_tx; + u16 seq_number; + __le16 fc = hdr->frame_control; + u8 reserved_macid = 0; + u8 fw_qsel = _rtl92se_map_hwqueue_to_fwqueue(skb, hw_queue); + bool firstseg = (!(hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG))); + bool lastseg = (!(hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_MOREFRAGS))); + dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + u8 bw_40 = 0; + + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + if (mac->opmode == NL80211_IFTYPE_STATION) { + bw_40 = mac->bw_40; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta) + bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; + } + + seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + + rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); + + CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S); + + if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { + firstseg = true; + lastseg = true; + } + + if (firstseg) { + if (rtlpriv->dm.useramask) { + /* set txdesc macId */ + if (ptcb_desc->mac_id < 32) { + SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); + reserved_macid |= ptcb_desc->mac_id; + } + } + SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid); + + SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >= + DESC_RATEMCS0) ? 1 : 0)); + + if (rtlhal->version == VERSION_8192S_ACUT) { + if (ptcb_desc->hw_rate == DESC_RATE1M || + ptcb_desc->hw_rate == DESC_RATE2M || + ptcb_desc->hw_rate == DESC_RATE5_5M || + ptcb_desc->hw_rate == DESC_RATE11M) { + ptcb_desc->hw_rate = DESC_RATE12M; + } + } + + SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); + + if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) + SET_TX_DESC_TX_SHORT(pdesc, 0); + + /* Aggregation related */ + if (info->flags & IEEE80211_TX_CTL_AMPDU) + SET_TX_DESC_AGG_ENABLE(pdesc, 1); + + /* For AMPDU, we must insert SSN into TX_DESC */ + SET_TX_DESC_SEQ(pdesc, seq_number); + + /* Protection mode related */ + /* For 92S, if RTS/CTS are set, HW will execute RTS. */ + /* We choose only one protection mode to execute */ + SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && + !ptcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS_ENABLE(pdesc, ((ptcb_desc->cts_enable) ? + 1 : 0)); + SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); + + SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); + SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0); + SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc); + SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= + DESC_RATE54M) ? + (ptcb_desc->rts_use_shortpreamble ? 1 : 0) + : (ptcb_desc->rts_use_shortgi ? 1 : 0))); + + + /* Set Bandwidth and sub-channel settings. */ + if (bw_40) { + if (ptcb_desc->packet_bw) { + SET_TX_DESC_TX_BANDWIDTH(pdesc, 1); + /* use duplicated mode */ + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + } else { + SET_TX_DESC_TX_BANDWIDTH(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + mac->cur_40_prime_sc); + } + } else { + SET_TX_DESC_TX_BANDWIDTH(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + } + + /* 3 Fill necessary field in First Descriptor */ + /*DWORD 0*/ + SET_TX_DESC_LINIP(pdesc, 0); + SET_TX_DESC_OFFSET(pdesc, 32); + SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); + + /*DWORD 1*/ + SET_TX_DESC_RA_BRSR_ID(pdesc, ptcb_desc->ratr_index); + + /* Fill security related */ + if (info->control.hw_key) { + struct ieee80211_key_conf *keyconf; + + keyconf = info->control.hw_key; + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + SET_TX_DESC_SEC_TYPE(pdesc, 0x1); + break; + case WLAN_CIPHER_SUITE_TKIP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x2); + break; + case WLAN_CIPHER_SUITE_CCMP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x3); + break; + default: + SET_TX_DESC_SEC_TYPE(pdesc, 0x0); + break; + + } + } + + /* Set Packet ID */ + SET_TX_DESC_PACKET_ID(pdesc, 0); + + /* We will assign magement queue to BK. */ + SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); + + /* Alwasy enable all rate fallback range */ + SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); + + /* Fix: I don't kown why hw use 6.5M to tx when set it */ + SET_TX_DESC_USER_RATE(pdesc, + ptcb_desc->use_driver_rate ? 1 : 0); + + /* Set NON_QOS bit. */ + if (!ieee80211_is_data_qos(fc)) + SET_TX_DESC_NON_QOS(pdesc, 1); + + } + + /* Fill fields that are required to be initialized + * in all of the descriptors */ + /*DWORD 0 */ + SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); + SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); + + /* DWORD 7 */ + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); + + /* DOWRD 8 */ + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); +} + +void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool firstseg, bool lastseg, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb); + + dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + /* Clear all status */ + CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S); + + /* This bit indicate this packet is used for FW download. */ + if (tcb_desc->cmd_or_init == DESC_PACKET_TYPE_INIT) { + /* For firmware downlaod we only need to set LINIP */ + SET_TX_DESC_LINIP(pdesc, tcb_desc->last_inipkt); + + /* 92SE must set as 1 for firmware download HW DMA error */ + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + /* 92SE need not to set TX packet size when firmware download */ + SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + + wmb(); + SET_TX_DESC_OWN(pdesc, 1); + } else { /* H2C Command Desc format (Host TXCMD) */ + /* 92SE must set as 1 for firmware download HW DMA error */ + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_OFFSET(pdesc, 0x20); + + /* Buffer size + command header */ + SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); + /* Fixed queue of H2C command */ + SET_TX_DESC_QUEUE_SEL(pdesc, 0x13); + + SET_BITS_TO_LE_4BYTE(skb->data, 24, 7, rtlhal->h2c_txcmd_seq); + + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + + wmb(); + SET_TX_DESC_OWN(pdesc, 1); + + } +} + +void rtl92se_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, + u8 desc_name, u8 *val) +{ + if (istx) { + switch (desc_name) { + case HW_DESC_OWN: + wmb(); + SET_TX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_TX_NEXTDESC_ADDR: + SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); + break; + default: + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_RXOWN: + wmb(); + SET_RX_STATUS_DESC_OWN(pdesc, 1); + break; + case HW_DESC_RXBUFF_ADDR: + SET_RX_STATUS__DESC_BUFF_ADDR(pdesc, *(u32 *) val); + break; + case HW_DESC_RXPKT_LEN: + SET_RX_STATUS_DESC_PKT_LEN(pdesc, *(u32 *) val); + break; + case HW_DESC_RXERO: + SET_RX_STATUS_DESC_EOR(pdesc, 1); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); + break; + } + } +} + +u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name) +{ + u32 ret = 0; + + if (istx) { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_TX_DESC_OWN(desc); + break; + case HW_DESC_TXBUFF_ADDR: + ret = GET_TX_DESC_TX_BUFFER_ADDRESS(desc); + break; + default: + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_RX_STATUS_DESC_OWN(desc); + break; + case HW_DESC_RXPKT_LEN: + ret = GET_RX_STATUS_DESC_PKT_LEN(desc); + break; + case HW_DESC_RXBUFF_ADDR: + ret = GET_RX_STATUS_DESC_BUFF_ADDR(desc); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); + break; + } + } + return ret; +} + +void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtl_write_word(rtlpriv, TP_POLL, BIT(0) << (hw_queue)); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h new file mode 100644 index 000000000000..5a13f17e3b41 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.h @@ -0,0 +1,48 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#ifndef __REALTEK_PCI92SE_TRX_H__ +#define __REALTEK_PCI92SE_TRX_H__ + +void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc, + u8 *pbd_desc_tx, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, u8 hw_queue, + struct rtl_tcb_desc *ptcb_desc); +void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, + bool lastseg, struct sk_buff *skb); +bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, u8 *pdesc, + struct sk_buff *skb); +void rtl92se_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, + u8 desc_name, u8 *val); +u32 rtl92se_get_desc(u8 *pdesc, bool istx, u8 desc_name); +void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/Makefile new file mode 100644 index 000000000000..6220672a96f4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/Makefile @@ -0,0 +1,18 @@ +rtl8723ae-objs := \ + dm.o \ + fw.o \ + hal_btc.o \ + hal_bt_coexist.o\ + hw.o \ + led.o \ + phy.o \ + pwrseq.o \ + rf.o \ + sw.o \ + table.o \ + trx.o \ + + +obj-$(CONFIG_RTL8723AE) += rtl8723ae.o + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h new file mode 100644 index 000000000000..06c448c010fd --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/btc.h @@ -0,0 +1,36 @@ +/****************************************************************************** + ** + ** Copyright(c) 2009-2012 Realtek Corporation. + ** + ** 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 + ** published by the Free Software Foundation. + ** + ** This program is distributed in the hope that it will be useful, but WITHOUT + ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + ** more details. + ** + ** The full GNU General Public License is included in this distribution in the + ** file called LICENSE. + ** + ** Contact Information: + ** wlanfae + ** Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + ** Hsinchu 300, Taiwan. + ** Larry Finger + ** + ******************************************************************************/ + +#ifndef __RTL8723E_BTC_H__ +#define __RTL8723E_BTC_H__ + +#include "../wifi.h" +#include "hal_bt_coexist.h" + +struct bt_coexist_c2h_info { + u8 no_parse_c2h; + u8 has_c2h; +}; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h new file mode 100644 index 000000000000..bcdf2273688e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/def.h @@ -0,0 +1,238 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_DEF_H__ +#define __RTL8723E_DEF_H__ + +#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 +#define HAL_PRIME_CHNL_OFFSET_LOWER 1 +#define HAL_PRIME_CHNL_OFFSET_UPPER 2 + +#define RX_MPDU_QUEUE 0 +#define RX_CMD_QUEUE 1 + +#define C2H_RX_CMD_HDR_LEN 8 +#define GET_C2H_CMD_CMD_LEN(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 0, 16) +#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 16, 8) +#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 24, 7) +#define GET_C2H_CMD_CONTINUE(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 31, 1) +#define GET_C2H_CMD_CONTENT(__prxhdr) \ + ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) + +#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) +#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) +#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) + +#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) +#define CHIP_BONDING_92C_1T2R 0x1 + +#define CHIP_8723 BIT(0) +#define NORMAL_CHIP BIT(3) +#define RF_TYPE_1T1R (~(BIT(4)|BIT(5)|BIT(6))) +#define RF_TYPE_1T2R BIT(4) +#define RF_TYPE_2T2R BIT(5) +#define CHIP_VENDOR_UMC BIT(7) +#define B_CUT_VERSION BIT(12) +#define C_CUT_VERSION BIT(13) +#define D_CUT_VERSION ((BIT(12)|BIT(13))) +#define E_CUT_VERSION BIT(14) +#define RF_RL_ID (BIT(31)|BIT(30)|BIT(29)|BIT(28)) + +/* MASK */ +#define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2)) +#define CHIP_TYPE_MASK BIT(3) +#define RF_TYPE_MASK (BIT(4)|BIT(5)|BIT(6)) +#define MANUFACTUER_MASK BIT(7) +#define ROM_VERSION_MASK (BIT(11)|BIT(10)|BIT(9)|BIT(8)) +#define CUT_VERSION_MASK (BIT(15)|BIT(14)|BIT(13)|BIT(12)) + +/* Get element */ +#define GET_CVID_IC_TYPE(version) ((version) & IC_TYPE_MASK) +#define GET_CVID_CHIP_TYPE(version) ((version) & CHIP_TYPE_MASK) +#define GET_CVID_RF_TYPE(version) ((version) & RF_TYPE_MASK) +#define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK) +#define GET_CVID_ROM_VERSION(version) ((version) & ROM_VERSION_MASK) +#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK) + +#define IS_81XXC(version) ((GET_CVID_IC_TYPE(version) == 0) ?\ + true : false) +#define IS_8723_SERIES(version) ((GET_CVID_IC_TYPE(version) == CHIP_8723) ? \ + true : false) +#define IS_1T1R(version) ((GET_CVID_RF_TYPE(version)) ? false : true) +#define IS_1T2R(version) ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R)\ + ? true : false) +#define IS_2T2R(version) ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R)\ + ? true : false) +#define IS_CHIP_VENDOR_UMC(version) ((GET_CVID_MANUFACTUER(version)) ? \ + true : false) + +#define IS_VENDOR_UMC_A_CUT(version) ((IS_CHIP_VENDOR_UMC(version))\ + ? ((GET_CVID_CUT_VERSION(version)) ? \ + false : true) : false) +#define IS_VENDOR_8723_A_CUT(version) ((IS_8723_SERIES(version))\ + ? ((GET_CVID_CUT_VERSION(version)) ? \ + false : true) : false) +#define IS_VENDOR_8723A_B_CUT(version) ((IS_8723_SERIES(version))\ + ? ((GET_CVID_CUT_VERSION(version) == \ + B_CUT_VERSION) ? true : false) : false) +#define IS_81xxC_VENDOR_UMC_B_CUT(version) ((IS_CHIP_VENDOR_UMC(version))\ + ? ((GET_CVID_CUT_VERSION(version) == \ + B_CUT_VERSION) ? true : false) : false) + +enum rf_optype { + RF_OP_BY_SW_3WIRE = 0, + RF_OP_BY_FW, + RF_OP_MAX +}; + +enum rf_power_state { + RF_ON, + RF_OFF, + RF_SLEEP, + RF_SHUT_DOWN, +}; + +enum power_save_mode { + POWER_SAVE_MODE_ACTIVE, + POWER_SAVE_MODE_SAVE, +}; + +enum power_policy_config { + POWERCFG_MAX_POWER_SAVINGS, + POWERCFG_GLOBAL_POWER_SAVINGS, + POWERCFG_LOCAL_POWER_SAVINGS, + POWERCFG_LENOVO, +}; + +enum interface_select_pci { + INTF_SEL1_MINICARD = 0, + INTF_SEL0_PCIE = 1, + INTF_SEL2_RSV = 2, + INTF_SEL3_RSV = 3, +}; + +enum hal_fw_c2h_cmd_id { + HAL_FW_C2H_CMD_Read_MACREG = 0, + HAL_FW_C2H_CMD_Read_BBREG = 1, + HAL_FW_C2H_CMD_Read_RFREG = 2, + HAL_FW_C2H_CMD_Read_EEPROM = 3, + HAL_FW_C2H_CMD_Read_EFUSE = 4, + HAL_FW_C2H_CMD_Read_CAM = 5, + HAL_FW_C2H_CMD_Get_BasicRate = 6, + HAL_FW_C2H_CMD_Get_DataRate = 7, + HAL_FW_C2H_CMD_Survey = 8, + HAL_FW_C2H_CMD_SurveyDone = 9, + HAL_FW_C2H_CMD_JoinBss = 10, + HAL_FW_C2H_CMD_AddSTA = 11, + HAL_FW_C2H_CMD_DelSTA = 12, + HAL_FW_C2H_CMD_AtimDone = 13, + HAL_FW_C2H_CMD_TX_Report = 14, + HAL_FW_C2H_CMD_CCX_Report = 15, + HAL_FW_C2H_CMD_DTM_Report = 16, + HAL_FW_C2H_CMD_TX_Rate_Statistics = 17, + HAL_FW_C2H_CMD_C2HLBK = 18, + HAL_FW_C2H_CMD_C2HDBG = 19, + HAL_FW_C2H_CMD_C2HFEEDBACK = 20, + HAL_FW_C2H_CMD_MAX +}; + +enum rtl_desc_qsel { + QSLT_BK = 0x2, + QSLT_BE = 0x0, + QSLT_VI = 0x5, + QSLT_VO = 0x7, + QSLT_BEACON = 0x10, + QSLT_HIGH = 0x11, + QSLT_MGNT = 0x12, + QSLT_CMD = 0x13, +}; + +enum rtl_desc8723e_rate { + DESC92C_RATE1M = 0x00, + DESC92C_RATE2M = 0x01, + DESC92C_RATE5_5M = 0x02, + DESC92C_RATE11M = 0x03, + + DESC92C_RATE6M = 0x04, + DESC92C_RATE9M = 0x05, + DESC92C_RATE12M = 0x06, + DESC92C_RATE18M = 0x07, + DESC92C_RATE24M = 0x08, + DESC92C_RATE36M = 0x09, + DESC92C_RATE48M = 0x0a, + DESC92C_RATE54M = 0x0b, + + DESC92C_RATEMCS0 = 0x0c, + DESC92C_RATEMCS1 = 0x0d, + DESC92C_RATEMCS2 = 0x0e, + DESC92C_RATEMCS3 = 0x0f, + DESC92C_RATEMCS4 = 0x10, + DESC92C_RATEMCS5 = 0x11, + DESC92C_RATEMCS6 = 0x12, + DESC92C_RATEMCS7 = 0x13, + DESC92C_RATEMCS8 = 0x14, + DESC92C_RATEMCS9 = 0x15, + DESC92C_RATEMCS10 = 0x16, + DESC92C_RATEMCS11 = 0x17, + DESC92C_RATEMCS12 = 0x18, + DESC92C_RATEMCS13 = 0x19, + DESC92C_RATEMCS14 = 0x1a, + DESC92C_RATEMCS15 = 0x1b, + DESC92C_RATEMCS15_SG = 0x1c, + DESC92C_RATEMCS32 = 0x20, +}; + +struct phy_sts_cck_8723e_t { + u8 adc_pwdb_X[4]; + u8 sq_rpt; + u8 cck_agc_rpt; +}; + +struct h2c_cmd_8723e { + u8 element_id; + u32 cmd_len; + u8 *p_cmdbuffer; +}; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c new file mode 100644 index 000000000000..4c1c96c96a5a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c @@ -0,0 +1,881 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../base.h" +#include "../pci.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "../rtl8723com/dm_common.h" +#include "fw.h" +#include "hal_btc.h" + +static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { + 0x7f8001fe, + 0x788001e2, + 0x71c001c7, + 0x6b8001ae, + 0x65400195, + 0x5fc0017f, + 0x5a400169, + 0x55400155, + 0x50800142, + 0x4c000130, + 0x47c0011f, + 0x43c0010f, + 0x40000100, + 0x3c8000f2, + 0x390000e4, + 0x35c000d7, + 0x32c000cb, + 0x300000c0, + 0x2d4000b5, + 0x2ac000ab, + 0x288000a2, + 0x26000098, + 0x24000090, + 0x22000088, + 0x20000080, + 0x1e400079, + 0x1c800072, + 0x1b00006c, + 0x19800066, + 0x18000060, + 0x16c0005b, + 0x15800056, + 0x14400051, + 0x1300004c, + 0x12000048, + 0x11000044, + 0x10000040, +}; + +static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, + {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, + {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, + {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, + {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, + {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, + {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, + {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, + {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, + {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, + {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, + {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, + {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, + {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, + {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, + {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, + {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, + {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, + {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, + {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, + {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, + {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} +}; + +static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, + {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, + {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, + {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, + {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, + {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, + {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, + {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, + {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, + {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, + {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, + {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, + {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, + {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, + {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, + {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, + {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, + {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} +}; + +static u8 rtl8723e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + long rssi_val_min = 0; + + if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) && + (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) { + if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0) + rssi_val_min = + (rtlpriv->dm.entry_min_undec_sm_pwdb > + rtlpriv->dm.undec_sm_pwdb) ? + rtlpriv->dm.undec_sm_pwdb : + rtlpriv->dm.entry_min_undec_sm_pwdb; + else + rssi_val_min = rtlpriv->dm.undec_sm_pwdb; + } else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT || + dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) { + rssi_val_min = rtlpriv->dm.undec_sm_pwdb; + } else if (dm_digtable->curmultista_cstate == + DIG_MULTISTA_CONNECT) { + rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb; + } + + return (u8) rssi_val_min; +} + +static void rtl8723e_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) +{ + u32 ret_value; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); + falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); + falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); + falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); + falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); + falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail; + + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1); + ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); + falsealm_cnt->cnt_cck_fail = ret_value; + + ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3); + falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; + falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_cck_fail); + + rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0); + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0); + rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", + falsealm_cnt->cnt_parity_fail, + falsealm_cnt->cnt_rate_illegal, + falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", + falsealm_cnt->cnt_ofdm_fail, + falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all); +} + +static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + u8 value_igi = dm_digtable->cur_igvalue; + + if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) + value_igi--; + else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1) + value_igi += 0; + else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2) + value_igi++; + else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2) + value_igi += 2; + if (value_igi > DM_DIG_FA_UPPER) + value_igi = DM_DIG_FA_UPPER; + else if (value_igi < DM_DIG_FA_LOWER) + value_igi = DM_DIG_FA_LOWER; + if (rtlpriv->falsealm_cnt.cnt_all > 10000) + value_igi = 0x32; + + dm_digtable->cur_igvalue = value_igi; + rtl8723e_dm_write_dig(hw); +} + +static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable->fa_highthresh) { + if ((dm_digtable->back_val - 2) < + dm_digtable->back_range_min) + dm_digtable->back_val = + dm_digtable->back_range_min; + else + dm_digtable->back_val -= 2; + } else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable->fa_lowthresh) { + if ((dm_digtable->back_val + 2) > + dm_digtable->back_range_max) + dm_digtable->back_val = + dm_digtable->back_range_max; + else + dm_digtable->back_val += 2; + } + + if ((dm_digtable->rssi_val_min + 10 - dm_digtable->back_val) > + dm_digtable->rx_gain_max) + dm_digtable->cur_igvalue = dm_digtable->rx_gain_max; + else if ((dm_digtable->rssi_val_min + 10 - + dm_digtable->back_val) < dm_digtable->rx_gain_min) + dm_digtable->cur_igvalue = dm_digtable->rx_gain_min; + else + dm_digtable->cur_igvalue = dm_digtable->rssi_val_min + 10 - + dm_digtable->back_val; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "rssi_val_min = %x back_val %x\n", + dm_digtable->rssi_val_min, dm_digtable->back_val); + + rtl8723e_dm_write_dig(hw); +} + +static void rtl8723e_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) +{ + static u8 binitialized; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb; + bool multi_sta = false; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) + multi_sta = true; + + if (!multi_sta || (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT)) { + binitialized = false; + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; + return; + } else if (!binitialized) { + binitialized = true; + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; + dm_digtable->cur_igvalue = 0x20; + rtl8723e_dm_write_dig(hw); + } + + if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) { + if ((rssi_strength < dm_digtable->rssi_lowthresh) && + (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) { + + if (dm_digtable->dig_ext_port_stage == + DIG_EXT_PORT_STAGE_2) { + dm_digtable->cur_igvalue = 0x20; + rtl8723e_dm_write_dig(hw); + } + + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1; + } else if (rssi_strength > dm_digtable->rssi_highthresh) { + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2; + rtl92c_dm_ctrl_initgain_by_fa(hw); + } + } else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) { + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; + dm_digtable->cur_igvalue = 0x20; + rtl8723e_dm_write_dig(hw); + } + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "curmultista_cstate = %x dig_ext_port_stage %x\n", + dm_digtable->curmultista_cstate, + dm_digtable->dig_ext_port_stage); +} + +static void rtl8723e_dm_initial_gain_sta(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "presta_cstate = %x, cursta_cstate = %x\n", + dm_digtable->presta_cstate, + dm_digtable->cursta_cstate); + + if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate || + dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT || + dm_digtable->cursta_cstate == DIG_STA_CONNECT) { + if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { + dm_digtable->rssi_val_min = + rtl8723e_dm_initial_gain_min_pwdb(hw); + rtl92c_dm_ctrl_initgain_by_rssi(hw); + } + } else { + dm_digtable->rssi_val_min = 0; + dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; + dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; + dm_digtable->cur_igvalue = 0x20; + dm_digtable->pre_igvalue = 0; + rtl8723e_dm_write_dig(hw); + } +} + +static void rtl8723e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) { + dm_digtable->rssi_val_min = rtl8723e_dm_initial_gain_min_pwdb(hw); + + if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { + if (dm_digtable->rssi_val_min <= 25) + dm_digtable->cur_cck_pd_state = + CCK_PD_STAGE_LOWRSSI; + else + dm_digtable->cur_cck_pd_state = + CCK_PD_STAGE_HIGHRSSI; + } else { + if (dm_digtable->rssi_val_min <= 20) + dm_digtable->cur_cck_pd_state = + CCK_PD_STAGE_LOWRSSI; + else + dm_digtable->cur_cck_pd_state = + CCK_PD_STAGE_HIGHRSSI; + } + } else { + dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX; + } + + if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) { + if (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { + if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800) + dm_digtable->cur_cck_fa_state = + CCK_FA_STAGE_HIGH; + else + dm_digtable->cur_cck_fa_state = + CCK_FA_STAGE_LOW; + if (dm_digtable->pre_cck_fa_state != + dm_digtable->cur_cck_fa_state) { + if (dm_digtable->cur_cck_fa_state == + CCK_FA_STAGE_LOW) + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, + 0x83); + else + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, + 0xcd); + + dm_digtable->pre_cck_fa_state = + dm_digtable->cur_cck_fa_state; + } + + rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40); + + } else { + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); + rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47); + + } + dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state; + } + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "CCKPDStage=%x\n", dm_digtable->cur_cck_pd_state); + +} + +static void rtl8723e_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + if (mac->act_scanning) + return; + + if (mac->link_state >= MAC80211_LINKED) + dm_digtable->cursta_cstate = DIG_STA_CONNECT; + else + dm_digtable->cursta_cstate = DIG_STA_DISCONNECT; + + rtl8723e_dm_initial_gain_sta(hw); + rtl8723e_dm_initial_gain_multi_sta(hw); + rtl8723e_dm_cck_packet_detection_thresh(hw); + + dm_digtable->presta_cstate = dm_digtable->cursta_cstate; + +} + +static void rtl8723e_dm_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + if (!rtlpriv->dm.dm_initialgain_enable) + return; + if (!dm_digtable->dig_enable_flag) + return; + + rtl8723e_dm_ctrl_initgain_by_twoport(hw); + +} + +static void rtl8723e_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + long undec_sm_pwdb; + + if (!rtlpriv->dm.dynamic_txpower_enable) + return; + + if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "Not connected to any\n"); + + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + return; + } + + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + undec_sm_pwdb = + rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Client PWDB = 0x%lx\n", + undec_sm_pwdb); + } else { + undec_sm_pwdb = + rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "STA Default Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + } else { + undec_sm_pwdb = + rtlpriv->dm.entry_min_undec_sm_pwdb; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "AP Ext Port PWDB = 0x%lx\n", + undec_sm_pwdb); + } + + if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); + } else if ((undec_sm_pwdb < + (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && + (undec_sm_pwdb >= + TX_POWER_NEAR_FIELD_THRESH_LVL1)) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); + } else if (undec_sm_pwdb < + (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "TXHIGHPWRLEVEL_NORMAL\n"); + } + + if (rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "PHY_SetTxPowerLevel8192S() Channel = %d\n", + rtlphy->current_channel); + rtl8723e_phy_set_txpower_level(hw, rtlphy->current_channel); + } + + rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; +} + +void rtl8723e_dm_write_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n", + dm_digtable->cur_igvalue, dm_digtable->pre_igvalue, + dm_digtable->back_val); + + if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) { + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, + dm_digtable->cur_igvalue); + rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, + dm_digtable->cur_igvalue); + + dm_digtable->pre_igvalue = dm_digtable->cur_igvalue; + } +} + +static void rtl8723e_dm_pwdb_monitor(struct ieee80211_hw *hw) +{ +} + +static void rtl8723e_dm_check_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + static u64 last_txok_cnt; + static u64 last_rxok_cnt; + static u32 last_bt_edca_ul; + static u32 last_bt_edca_dl; + u64 cur_txok_cnt = 0; + u64 cur_rxok_cnt = 0; + u32 edca_be_ul = 0x5ea42b; + u32 edca_be_dl = 0x5ea42b; + bool bt_change_edca = false; + + if ((last_bt_edca_ul != rtlpriv->btcoexist.bt_edca_ul) || + (last_bt_edca_dl != rtlpriv->btcoexist.bt_edca_dl)) { + rtlpriv->dm.current_turbo_edca = false; + last_bt_edca_ul = rtlpriv->btcoexist.bt_edca_ul; + last_bt_edca_dl = rtlpriv->btcoexist.bt_edca_dl; + } + + if (rtlpriv->btcoexist.bt_edca_ul != 0) { + edca_be_ul = rtlpriv->btcoexist.bt_edca_ul; + bt_change_edca = true; + } + + if (rtlpriv->btcoexist.bt_edca_dl != 0) { + edca_be_ul = rtlpriv->btcoexist.bt_edca_dl; + bt_change_edca = true; + } + + if (mac->link_state != MAC80211_LINKED) { + rtlpriv->dm.current_turbo_edca = false; + return; + } + if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && + (!rtlpriv->dm.disable_framebursting))) { + + cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; + cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; + + if (cur_rxok_cnt > 4 * cur_txok_cnt) { + if (!rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + rtl_write_dword(rtlpriv, + REG_EDCA_BE_PARAM, + edca_be_dl); + rtlpriv->dm.is_cur_rdlstate = true; + } + } else { + if (rtlpriv->dm.is_cur_rdlstate || + !rtlpriv->dm.current_turbo_edca) { + rtl_write_dword(rtlpriv, + REG_EDCA_BE_PARAM, + edca_be_ul); + rtlpriv->dm.is_cur_rdlstate = false; + } + } + rtlpriv->dm.current_turbo_edca = true; + } else { + if (rtlpriv->dm.current_turbo_edca) { + u8 tmp = AC0_BE; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AC_PARAM, + (u8 *)(&tmp)); + rtlpriv->dm.current_turbo_edca = false; + } + } + + rtlpriv->dm.is_any_nonbepkts = false; + last_txok_cnt = rtlpriv->stats.txbytesunicast; + last_rxok_cnt = rtlpriv->stats.rxbytesunicast; +} + +static void rtl8723e_dm_initialize_txpower_tracking_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.txpower_tracking = true; + rtlpriv->dm.txpower_trackinginit = false; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pMgntInfo->txpower_tracking = %d\n", + rtlpriv->dm.txpower_tracking); +} + +static void rtl8723e_dm_initialize_txpower_tracking(struct ieee80211_hw *hw) +{ + rtl8723e_dm_initialize_txpower_tracking_thermalmeter(hw); +} + +void rtl8723e_dm_check_txpower_tracking(struct ieee80211_hw *hw) +{ + return; +} + +void rtl8723e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rate_adaptive *p_ra = &(rtlpriv->ra); + + p_ra->ratr_state = DM_RATR_STA_INIT; + p_ra->pre_ratr_state = DM_RATR_STA_INIT; + + if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) + rtlpriv->dm.useramask = true; + else + rtlpriv->dm.useramask = false; + +} + +void rtl8723e_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ps_t *dm_pstable = &rtlpriv->dm_pstable; + static u8 initialize; + static u32 reg_874, reg_c70, reg_85c, reg_a74; + + if (initialize == 0) { + reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + MASKDWORD) & 0x1CC000) >> 14; + + reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1, + MASKDWORD) & BIT(3)) >> 3; + + reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, + MASKDWORD) & 0xFF000000) >> 24; + + reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12; + + initialize = 1; + } + + if (!bforce_in_normal) { + if (dm_pstable->rssi_val_min != 0) { + if (dm_pstable->pre_rfstate == RF_NORMAL) { + if (dm_pstable->rssi_val_min >= 30) + dm_pstable->cur_rfstate = RF_SAVE; + else + dm_pstable->cur_rfstate = RF_NORMAL; + } else { + if (dm_pstable->rssi_val_min <= 25) + dm_pstable->cur_rfstate = RF_NORMAL; + else + dm_pstable->cur_rfstate = RF_SAVE; + } + } else { + dm_pstable->cur_rfstate = RF_MAX; + } + } else { + dm_pstable->cur_rfstate = RF_NORMAL; + } + + if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) { + if (dm_pstable->cur_rfstate == RF_SAVE) { + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + BIT(5), 0x1); + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + 0x1C0000, 0x2); + rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0); + rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, + 0xFF000000, 0x63); + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + 0xC000, 0x2); + rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3); + rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); + rtl_set_bbreg(hw, 0x818, BIT(28), 0x1); + } else { + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + 0x1CC000, reg_874); + rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), + reg_c70); + rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000, + reg_85c); + rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74); + rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); + rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, + BIT(5), 0x0); + } + + dm_pstable->pre_rfstate = dm_pstable->cur_rfstate; + } +} + +static void rtl8723e_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct ps_t *dm_pstable = &rtlpriv->dm_pstable; + + if (((mac->link_state == MAC80211_NOLINK)) && + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { + dm_pstable->rssi_val_min = 0; + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, + "Not connected to any\n"); + } + + if (mac->link_state == MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + dm_pstable->rssi_val_min = + rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, + "AP Client PWDB = 0x%lx\n", + dm_pstable->rssi_val_min); + } else { + dm_pstable->rssi_val_min = + rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, + "STA Default Port PWDB = 0x%lx\n", + dm_pstable->rssi_val_min); + } + } else { + dm_pstable->rssi_val_min = + rtlpriv->dm.entry_min_undec_sm_pwdb; + + RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, + "AP Ext Port PWDB = 0x%lx\n", + dm_pstable->rssi_val_min); + } + + rtl8723e_dm_rf_saving(hw, false); +} + +void rtl8723e_dm_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; + rtl_dm_diginit(hw, 0x20); + rtl8723_dm_init_dynamic_txpower(hw); + rtl8723_dm_init_edca_turbo(hw); + rtl8723e_dm_init_rate_adaptive_mask(hw); + rtl8723e_dm_initialize_txpower_tracking(hw); + rtl8723_dm_init_dynamic_bb_powersaving(hw); +} + +void rtl8723e_dm_watchdog(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool fw_current_inpsmode = false; + bool fw_ps_awake = true; + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inpsmode)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, + (u8 *)(&fw_ps_awake)); + + if (ppsc->p2p_ps_info.p2p_ps_mode) + fw_ps_awake = false; + + if ((ppsc->rfpwr_state == ERFON) && + ((!fw_current_inpsmode) && fw_ps_awake) && + (!ppsc->rfchange_inprogress)) { + rtl8723e_dm_pwdb_monitor(hw); + rtl8723e_dm_dig(hw); + rtl8723e_dm_false_alarm_counter_statistics(hw); + rtl8723e_dm_dynamic_bb_powersaving(hw); + rtl8723e_dm_dynamic_txpower(hw); + rtl8723e_dm_check_txpower_tracking(hw); + /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */ + rtl8723e_dm_bt_coexist(hw); + rtl8723e_dm_check_edca_turbo(hw); + } + if (rtlpriv->btcoexist.init_set) + rtl_write_byte(rtlpriv, 0x76e, 0xc); +} + +static void rtl8723e_dm_init_bt_coexist(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->btcoexist.bt_rfreg_origin_1e + = rtl_get_rfreg(hw, (enum radio_path)0, RF_RCK1, 0xfffff); + rtlpriv->btcoexist.bt_rfreg_origin_1f + = rtl_get_rfreg(hw, (enum radio_path)0, RF_RCK2, 0xf0); + + rtlpriv->btcoexist.cstate = 0; + rtlpriv->btcoexist.previous_state = 0; + rtlpriv->btcoexist.cstate_h = 0; + rtlpriv->btcoexist.previous_state_h = 0; + rtlpriv->btcoexist.lps_counter = 0; + + /* Enable counter statistics */ + rtl_write_byte(rtlpriv, 0x76e, 0x4); + rtl_write_byte(rtlpriv, 0x778, 0x3); + rtl_write_byte(rtlpriv, 0x40, 0x20); + + rtlpriv->btcoexist.init_set = true; +} + +void rtl8723e_dm_bt_coexist(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp_byte = 0; + if (!rtlpriv->btcoexist.bt_coexistence) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, + "[DM]{BT], BT not exist!!\n"); + return; + } + + if (!rtlpriv->btcoexist.init_set) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, + "[DM][BT], rtl8723e_dm_bt_coexist()\n"); + rtl8723e_dm_init_bt_coexist(hw); + } + + tmp_byte = rtl_read_byte(rtlpriv, 0x40); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, + "[DM][BT], 0x40 is 0x%x", tmp_byte); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[DM][BT], bt_dm_coexist start"); + rtl8723e_dm_bt_coexist_8723(hw); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h new file mode 100644 index 000000000000..57111052e86b --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.h @@ -0,0 +1,136 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_DM_H__ +#define __RTL8723E_DM_H__ + +#define HAL_DM_DIG_DISABLE BIT(0) +#define HAL_DM_HIPWR_DISABLE BIT(1) + +#define OFDM_TABLE_LENGTH 37 +#define CCK_TABLE_LENGTH 33 + +#define OFDM_TABLE_SIZE 37 +#define CCK_TABLE_SIZE 33 + +#define BW_AUTO_SWITCH_HIGH_LOW 25 +#define BW_AUTO_SWITCH_LOW_HIGH 30 + +#define DM_DIG_FA_UPPER 0x32 +#define DM_DIG_FA_LOWER 0x20 +#define DM_DIG_FA_TH0 0x20 +#define DM_DIG_FA_TH1 0x100 +#define DM_DIG_FA_TH2 0x200 + +#define RXPATHSELECTION_SS_TH_LOW 30 +#define RXPATHSELECTION_DIFF_TH 18 + +#define DM_RATR_STA_INIT 0 +#define DM_RATR_STA_HIGH 1 +#define DM_RATR_STA_MIDDLE 2 +#define DM_RATR_STA_LOW 3 + +#define CTS2SELF_THVAL 30 +#define REGC38_TH 20 + +#define WAIOTTHVAL 25 + +#define TXHIGHPWRLEVEL_NORMAL 0 +#define TXHIGHPWRLEVEL_LEVEL1 1 +#define TXHIGHPWRLEVEL_LEVEL2 2 +#define TXHIGHPWRLEVEL_BT1 3 +#define TXHIGHPWRLEVEL_BT2 4 + +#define DM_TYPE_BYFW 0 +#define DM_TYPE_BYDRIVER 1 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 + +struct swat_t { + u8 failure_cnt; + u8 try_flag; + u8 stop_trying; + long pre_rssi; + long trying_threshold; + u8 cur_antenna; + u8 pre_antenna; + +}; + +enum tag_dynamic_init_gain_operation_type_definition { + DIG_TYPE_THRESH_HIGH = 0, + DIG_TYPE_THRESH_LOW = 1, + DIG_TYPE_BACKOFF = 2, + DIG_TYPE_RX_GAIN_MIN = 3, + DIG_TYPE_RX_GAIN_MAX = 4, + DIG_TYPE_ENABLE = 5, + DIG_TYPE_DISABLE = 6, + DIG_OP_TYPE_MAX +}; + +enum dm_1r_cca_e { + CCA_1R = 0, + CCA_2R = 1, + CCA_MAX = 2, +}; + +enum dm_rf_e { + RF_SAVE = 0, + RF_NORMAL = 1, + RF_MAX = 2, +}; + +enum dm_sw_ant_switch_e { + ANS_ANTENNA_B = 1, + ANS_ANTENNA_A = 2, + ANS_ANTENNA_MAX = 3, +}; + +#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1) +#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1) +#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1) +#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1) +#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1) +#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ + ( \ + (((struct rtl_priv *)(_priv))->mac80211.opmode == \ + NL80211_IFTYPE_ADHOC) ? \ + (((struct rtl_priv *)(_priv))->dm.entry_min_undec_sm_pwdb) : \ + (((struct rtl_priv *)(_priv))->dm.undec_sm_pwdb) \ + ) + +void rtl8723e_dm_init(struct ieee80211_hw *hw); +void rtl8723e_dm_watchdog(struct ieee80211_hw *hw); +void rtl8723e_dm_write_dig(struct ieee80211_hw *hw); +void rtl8723e_dm_check_txpower_tracking(struct ieee80211_hw *hw); +void rtl8723e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); +void rtl8723e_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); +void rtl8723e_dm_bt_coexist(struct ieee80211_hw *hw); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c new file mode 100644 index 000000000000..b7c0d38ee5b5 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.c @@ -0,0 +1,603 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "fw.h" +#include "../rtl8723com/fw_common.h" + +static bool _rtl8723e_check_fw_read_last_h2c(struct ieee80211_hw *hw, + u8 boxnum) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 val_hmetfr, val_mcutst_1; + bool result = false; + + val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); + val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum)); + + if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0) + result = true; + return result; +} + +static void _rtl8723e_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *cmdbuffer) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 boxnum; + u16 box_reg = 0, box_extreg = 0; + u8 u1b_tmp; + bool isfw_read = false; + u8 buf_index = 0; + bool bwrite_sucess = false; + u8 wait_h2c_limmit = 100; + u8 wait_writeh2c_limmit = 100; + u8 boxcontent[4], boxextcontent[2]; + u32 h2c_waitcounter = 0; + unsigned long flag; + u8 idx; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); + + while (true) { + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + if (rtlhal->h2c_setinprogress) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C set in progress! Wait to set..element_id(%d).\n", + element_id); + + while (rtlhal->h2c_setinprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, + flag); + h2c_waitcounter++; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Wait 100 us (%d times)...\n", + h2c_waitcounter); + udelay(100); + + if (h2c_waitcounter > 1000) + return; + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, + flag); + } + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + } else { + rtlhal->h2c_setinprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + break; + } + } + + while (!bwrite_sucess) { + wait_writeh2c_limmit--; + if (wait_writeh2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Write H2C fail because no trigger for FW INT!\n"); + break; + } + + boxnum = rtlhal->last_hmeboxnum; + switch (boxnum) { + case 0: + box_reg = REG_HMEBOX_0; + box_extreg = REG_HMEBOX_EXT_0; + break; + case 1: + box_reg = REG_HMEBOX_1; + box_extreg = REG_HMEBOX_EXT_1; + break; + case 2: + box_reg = REG_HMEBOX_2; + box_extreg = REG_HMEBOX_EXT_2; + break; + case 3: + box_reg = REG_HMEBOX_3; + box_extreg = REG_HMEBOX_EXT_3; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + + isfw_read = _rtl8723e_check_fw_read_last_h2c(hw, boxnum); + while (!isfw_read) { + + wait_h2c_limmit--; + if (wait_h2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Wating too long for FW read clear HMEBox(%d)!\n", + boxnum); + break; + } + + udelay(10); + + isfw_read = _rtl8723e_check_fw_read_last_h2c(hw, + boxnum); + u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF); + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n", + boxnum, u1b_tmp); + } + + if (!isfw_read) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", + boxnum); + break; + } + + memset(boxcontent, 0, sizeof(boxcontent)); + memset(boxextcontent, 0, sizeof(boxextcontent)); + boxcontent[0] = element_id; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Write element_id box_reg(%4x) = %2x\n", + box_reg, element_id); + + switch (cmd_len) { + case 1: + boxcontent[0] &= ~(BIT(7)); + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index, 1); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 2: + boxcontent[0] &= ~(BIT(7)); + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index, 2); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 3: + boxcontent[0] &= ~(BIT(7)); + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index, 3); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 4: + boxcontent[0] |= (BIT(7)); + memcpy((u8 *)(boxextcontent), + cmdbuffer + buf_index, 2); + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index + 2, 2); + + for (idx = 0; idx < 2; idx++) { + rtl_write_byte(rtlpriv, box_extreg + idx, + boxextcontent[idx]); + } + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 5: + boxcontent[0] |= (BIT(7)); + memcpy((u8 *)(boxextcontent), + cmdbuffer + buf_index, 2); + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index + 2, 3); + + for (idx = 0; idx < 2; idx++) { + rtl_write_byte(rtlpriv, box_extreg + idx, + boxextcontent[idx]); + } + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + + bwrite_sucess = true; + + rtlhal->last_hmeboxnum = boxnum + 1; + if (rtlhal->last_hmeboxnum == 4) + rtlhal->last_hmeboxnum = 0; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "pHalData->last_hmeboxnum = %d\n", + rtlhal->last_hmeboxnum); + } + + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + rtlhal->h2c_setinprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); +} + +void rtl8723e_fill_h2c_cmd(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, u8 *cmdbuffer) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 tmp_cmdbuf[2]; + + if (!rtlhal->fw_ready) { + RT_ASSERT(false, + "return H2C cmd because of Fw download fail!!!\n"); + return; + } + memset(tmp_cmdbuf, 0, 8); + memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); + _rtl8723e_fill_h2c_command(hw, element_id, cmd_len, + (u8 *)&tmp_cmdbuf); +} + +void rtl8723e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1_h2c_set_pwrmode[3] = { 0 }; + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); + + SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); + SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, + (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1); + SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, + ppsc->reg_max_lps_awakeintvl); + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl8723e_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n", + u1_h2c_set_pwrmode, 3); + rtl8723e_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode); +} + +#define BEACON_PG 0 /* ->1 */ +#define PSPOLL_PG 2 +#define NULL_PG 3 +#define PROBERSP_PG 4 /* ->5 */ + +#define TOTAL_RESERVED_PKT_LEN 768 + +static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { + /* page 0 beacon */ + 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, + 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, + 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, + 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, + 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, + 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, + 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 1 beacon */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 2 ps-poll */ + 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 3 null */ + 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 4 probe_resp */ + 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, + 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, + 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, + 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, + 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, + 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, + 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, + 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, + 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 5 probe_resp */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct sk_buff *skb = NULL; + u32 totalpacketlen; + bool rtstatus; + u8 u1rsvdpageloc[3] = { 0 }; + bool b_dlok = false; + u8 *beacon; + u8 *p_pspoll; + u8 *nullfunc; + u8 *p_probersp; + + /*--------------------------------------------------------- + * (1) beacon + *--------------------------------------------------------- + */ + beacon = &reserved_page_packet[BEACON_PG * 128]; + SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); + SET_80211_HDR_ADDRESS3(beacon, mac->bssid); + + /*------------------------------------------------------- + * (2) ps-poll + *-------------------------------------------------------- + */ + p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; + SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); + SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); + SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); + + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); + + /*-------------------------------------------------------- + * (3) null data + *--------------------------------------------------------- + */ + nullfunc = &reserved_page_packet[NULL_PG * 128]; + SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); + SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); + SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); + + /*--------------------------------------------------------- + * (4) probe response + *---------------------------------------------------------- + */ + p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; + SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); + SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); + SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); + + totalpacketlen = TOTAL_RESERVED_PKT_LEN; + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + &reserved_page_packet[0], totalpacketlen); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + u1rsvdpageloc, 3); + + skb = dev_alloc_skb(totalpacketlen); + memcpy((u8 *)skb_put(skb, totalpacketlen), + &reserved_page_packet, totalpacketlen); + + rtstatus = rtl_cmd_send_packet(hw, skb); + + if (rtstatus) + b_dlok = true; + + if (b_dlok) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Set RSVD page location to Fw.\n"); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "H2C_RSVDPAGE:\n", + u1rsvdpageloc, 3); + rtl8723e_fill_h2c_cmd(hw, H2C_RSVDPAGE, + sizeof(u1rsvdpageloc), u1rsvdpageloc); + } else + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set RSVD page location to Fw FAIL!!!!!!.\n"); +} + +void rtl8723e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) +{ + u8 u1_joinbssrpt_parm[1] = { 0 }; + + SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); + + rtl8723e_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); +} + +static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, + u8 ctwindow) +{ + u8 u1_ctwindow_period[1] = { ctwindow}; + + rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); + +} + +void rtl8723e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); + struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; + u8 i; + u16 ctwindow; + u32 start_time, tsf_low; + + switch (p2p_ps_state) { + case P2P_PS_DISABLE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); + memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); + break; + case P2P_PS_ENABLE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); + /* update CTWindow value. */ + if (p2pinfo->ctwindow > 0) { + p2p_ps_offload->ctwindow_en = 1; + ctwindow = p2pinfo->ctwindow; + rtl8723e_set_p2p_ctw_period_cmd(hw, ctwindow); + } + + /* hw only support 2 set of NoA */ + for (i = 0 ; i < p2pinfo->noa_num ; i++) { + /* To control the register setting for which NOA*/ + rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); + if (i == 0) + p2p_ps_offload->noa0_en = 1; + else + p2p_ps_offload->noa1_en = 1; + + /* config P2P NoA Descriptor Register */ + rtl_write_dword(rtlpriv, 0x5E0, + p2pinfo->noa_duration[i]); + rtl_write_dword(rtlpriv, 0x5E4, + p2pinfo->noa_interval[i]); + + /*Get Current TSF value */ + tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + start_time = p2pinfo->noa_start_time[i]; + if (p2pinfo->noa_count_type[i] != 1) { + while (start_time <= + (tsf_low+(50*1024))) { + start_time += + p2pinfo->noa_interval[i]; + if (p2pinfo->noa_count_type[i] != 255) + p2pinfo->noa_count_type[i]--; + } + } + rtl_write_dword(rtlpriv, 0x5E8, start_time); + rtl_write_dword(rtlpriv, 0x5EC, + p2pinfo->noa_count_type[i]); + + } + + if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { + /* rst p2p circuit */ + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); + + p2p_ps_offload->offload_en = 1; + + if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { + p2p_ps_offload->role = 1; + p2p_ps_offload->allstasleep = 0; + } else { + p2p_ps_offload->role = 0; + } + + p2p_ps_offload->discovery = 0; + } + break; + case P2P_PS_SCAN: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); + p2p_ps_offload->discovery = 1; + break; + case P2P_PS_SCAN_DONE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); + p2p_ps_offload->discovery = 0; + p2pinfo->p2p_ps_state = P2P_PS_ENABLE; + break; + default: + break; + } + + rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload); + +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h new file mode 100644 index 000000000000..9d1fe25db953 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/fw.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C__FW__H__ +#define __RTL92C__FW__H__ + +#define FW_8192C_SIZE 0x3000 +#define FW_8192C_START_ADDRESS 0x1000 +#define FW_8192C_END_ADDRESS 0x3FFF +#define FW_8192C_PAGE_SIZE 4096 +#define FW_8192C_POLLING_DELAY 5 + +#define IS_FW_HEADER_EXIST(_pfwhdr) \ + ((_pfwhdr->signature&0xFFFF) == 0x2300 ||\ + (_pfwhdr->signature&0xFFFF) == 0x2301 ||\ + (_pfwhdr->signature&0xFFFF) == 0x2302) + +#define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) + +#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) +#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) + +void rtl8723e_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *p_cmdbuffer); +void rtl8723e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); +void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); +void rtl8723e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); +void rtl8723e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c new file mode 100644 index 000000000000..5aac45d5a974 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c @@ -0,0 +1,537 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "hal_bt_coexist.h" +#include "../pci.h" +#include "dm.h" +#include "fw.h" +#include "phy.h" +#include "reg.h" +#include "hal_btc.h" + +static bool bt_operation_on; + +void rtl8723e_dm_bt_reject_ap_aggregated_packet(struct ieee80211_hw *hw, + bool b_reject) +{ +} + +void _rtl8723_dm_bt_check_wifi_state(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + if (rtlpriv->link_info.busytraffic) { + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_IDLE; + + if (rtlpriv->link_info.tx_busy_traffic) + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_WIFI_UPLINK; + else + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_UPLINK; + + if (rtlpriv->link_info.rx_busy_traffic) + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_WIFI_DOWNLINK; + else + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_DOWNLINK; + } else { + rtlpriv->btcoexist.cstate |= BT_COEX_STATE_WIFI_IDLE; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_UPLINK; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_DOWNLINK; + } + + if (rtlpriv->mac80211.mode == WIRELESS_MODE_G || + rtlpriv->mac80211.mode == WIRELESS_MODE_B) { + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_WIFI_LEGACY; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_HT20; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_HT40; + } else { + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_LEGACY; + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_WIFI_HT40; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_HT20; + } else { + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_WIFI_HT20; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_HT40; + } + } + + if (bt_operation_on) + rtlpriv->btcoexist.cstate |= BT_COEX_STATE_BT30; + else + rtlpriv->btcoexist.cstate &= ~BT_COEX_STATE_BT30; +} + +u8 rtl8723e_dm_bt_check_coex_rssi_state1(struct ieee80211_hw *hw, + u8 level_num, u8 rssi_thresh, + u8 rssi_thresh1) + +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + long undecoratedsmoothed_pwdb; + u8 bt_rssi_state = 0; + + undecoratedsmoothed_pwdb = rtl8723e_dm_bt_get_rx_ss(hw); + + if (level_num == 2) { + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; + + if ((rtlpriv->btcoexist.bt_pre_rssi_state == + BT_RSSI_STATE_LOW) || + (rtlpriv->btcoexist.bt_pre_rssi_state == + BT_RSSI_STATE_STAY_LOW)) { + if (undecoratedsmoothed_pwdb >= + (rssi_thresh + BT_FW_COEX_THRESH_TOL)) { + bt_rssi_state = BT_RSSI_STATE_HIGH; + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_WIFI_RSSI_1_HIGH; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_RSSI_1_LOW; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI_1 state switch to High\n"); + } else { + bt_rssi_state = BT_RSSI_STATE_STAY_LOW; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI_1 state stay at Low\n"); + } + } else { + if (undecoratedsmoothed_pwdb < rssi_thresh) { + bt_rssi_state = BT_RSSI_STATE_LOW; + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_WIFI_RSSI_1_LOW; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI_1 state switch to Low\n"); + } else { + bt_rssi_state = BT_RSSI_STATE_STAY_HIGH; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI_1 state stay at High\n"); + } + } + } else if (level_num == 3) { + if (rssi_thresh > rssi_thresh1) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI_1 thresh error!!\n"); + return rtlpriv->btcoexist.bt_pre_rssi_state; + } + + if ((rtlpriv->btcoexist.bt_pre_rssi_state == + BT_RSSI_STATE_LOW) || + (rtlpriv->btcoexist.bt_pre_rssi_state == + BT_RSSI_STATE_STAY_LOW)) { + if (undecoratedsmoothed_pwdb >= + (rssi_thresh+BT_FW_COEX_THRESH_TOL)) { + bt_rssi_state = BT_RSSI_STATE_MEDIUM; + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_RSSI_1_LOW; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI_1 state switch to Medium\n"); + } else { + bt_rssi_state = BT_RSSI_STATE_STAY_LOW; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI_1 state stay at Low\n"); + } + } else if ((rtlpriv->btcoexist.bt_pre_rssi_state == + BT_RSSI_STATE_MEDIUM) || + (rtlpriv->btcoexist.bt_pre_rssi_state == + BT_RSSI_STATE_STAY_MEDIUM)) { + if (undecoratedsmoothed_pwdb >= + (rssi_thresh1 + BT_FW_COEX_THRESH_TOL)) { + bt_rssi_state = BT_RSSI_STATE_HIGH; + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_WIFI_RSSI_1_HIGH; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_RSSI_1_LOW; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI_1 state switch to High\n"); + } else if (undecoratedsmoothed_pwdb < rssi_thresh) { + bt_rssi_state = BT_RSSI_STATE_LOW; + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_WIFI_RSSI_1_LOW; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI_1 state switch to Low\n"); + } else { + bt_rssi_state = BT_RSSI_STATE_STAY_MEDIUM; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI_1 state stay at Medium\n"); + } + } else { + if (undecoratedsmoothed_pwdb < rssi_thresh1) { + bt_rssi_state = BT_RSSI_STATE_MEDIUM; + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_RSSI_1_LOW; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI_1 state switch to Medium\n"); + } else { + bt_rssi_state = BT_RSSI_STATE_STAY_HIGH; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI_1 state stay at High\n"); + } + } + } + rtlpriv->btcoexist.bt_pre_rssi_state1 = bt_rssi_state; + + return bt_rssi_state; +} + +u8 rtl8723e_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw, + u8 level_num, + u8 rssi_thresh, + u8 rssi_thresh1) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + long undecoratedsmoothed_pwdb = 0; + u8 bt_rssi_state = 0; + + undecoratedsmoothed_pwdb = rtl8723e_dm_bt_get_rx_ss(hw); + + if (level_num == 2) { + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_WIFI_RSSI_MEDIUM; + + if ((rtlpriv->btcoexist.bt_pre_rssi_state == + BT_RSSI_STATE_LOW) || + (rtlpriv->btcoexist.bt_pre_rssi_state == + BT_RSSI_STATE_STAY_LOW)) { + if (undecoratedsmoothed_pwdb >= + (rssi_thresh + BT_FW_COEX_THRESH_TOL)) { + bt_rssi_state = BT_RSSI_STATE_HIGH; + rtlpriv->btcoexist.cstate + |= BT_COEX_STATE_WIFI_RSSI_HIGH; + rtlpriv->btcoexist.cstate + &= ~BT_COEX_STATE_WIFI_RSSI_LOW; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI state switch to High\n"); + } else { + bt_rssi_state = BT_RSSI_STATE_STAY_LOW; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI state stay at Low\n"); + } + } else { + if (undecoratedsmoothed_pwdb < rssi_thresh) { + bt_rssi_state = BT_RSSI_STATE_LOW; + rtlpriv->btcoexist.cstate + |= BT_COEX_STATE_WIFI_RSSI_LOW; + rtlpriv->btcoexist.cstate + &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI state switch to Low\n"); + } else { + bt_rssi_state = BT_RSSI_STATE_STAY_HIGH; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI state stay at High\n"); + } + } + } else if (level_num == 3) { + if (rssi_thresh > rssi_thresh1) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI thresh error!!\n"); + return rtlpriv->btcoexist.bt_pre_rssi_state; + } + if ((rtlpriv->btcoexist.bt_pre_rssi_state == + BT_RSSI_STATE_LOW) || + (rtlpriv->btcoexist.bt_pre_rssi_state == + BT_RSSI_STATE_STAY_LOW)) { + if (undecoratedsmoothed_pwdb >= + (rssi_thresh + BT_FW_COEX_THRESH_TOL)) { + bt_rssi_state = BT_RSSI_STATE_MEDIUM; + rtlpriv->btcoexist.cstate + |= BT_COEX_STATE_WIFI_RSSI_MEDIUM; + rtlpriv->btcoexist.cstate + &= ~BT_COEX_STATE_WIFI_RSSI_LOW; + rtlpriv->btcoexist.cstate + &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI state switch to Medium\n"); + } else { + bt_rssi_state = BT_RSSI_STATE_STAY_LOW; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI state stay at Low\n"); + } + } else if ((rtlpriv->btcoexist.bt_pre_rssi_state == + BT_RSSI_STATE_MEDIUM) || + (rtlpriv->btcoexist.bt_pre_rssi_state == + BT_RSSI_STATE_STAY_MEDIUM)) { + if (undecoratedsmoothed_pwdb >= + (rssi_thresh1 + BT_FW_COEX_THRESH_TOL)) { + bt_rssi_state = BT_RSSI_STATE_HIGH; + rtlpriv->btcoexist.cstate + |= BT_COEX_STATE_WIFI_RSSI_HIGH; + rtlpriv->btcoexist.cstate + &= ~BT_COEX_STATE_WIFI_RSSI_LOW; + rtlpriv->btcoexist.cstate + &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI state switch to High\n"); + } else if (undecoratedsmoothed_pwdb < rssi_thresh) { + bt_rssi_state = BT_RSSI_STATE_LOW; + rtlpriv->btcoexist.cstate + |= BT_COEX_STATE_WIFI_RSSI_LOW; + rtlpriv->btcoexist.cstate + &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; + rtlpriv->btcoexist.cstate + &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI state switch to Low\n"); + } else { + bt_rssi_state = BT_RSSI_STATE_STAY_MEDIUM; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI state stay at Medium\n"); + } + } else { + if (undecoratedsmoothed_pwdb < rssi_thresh1) { + bt_rssi_state = BT_RSSI_STATE_MEDIUM; + rtlpriv->btcoexist.cstate + |= BT_COEX_STATE_WIFI_RSSI_MEDIUM; + rtlpriv->btcoexist.cstate + &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; + rtlpriv->btcoexist.cstate + &= ~BT_COEX_STATE_WIFI_RSSI_LOW; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI state switch to Medium\n"); + } else { + bt_rssi_state = BT_RSSI_STATE_STAY_HIGH; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], RSSI state stay at High\n"); + } + } + } + rtlpriv->btcoexist.bt_pre_rssi_state = bt_rssi_state; + return bt_rssi_state; +} + +long rtl8723e_dm_bt_get_rx_ss(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + long undecoratedsmoothed_pwdb = 0; + + if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) { + undecoratedsmoothed_pwdb = + GET_UNDECORATED_AVERAGE_RSSI(rtlpriv); + } else { + undecoratedsmoothed_pwdb + = rtlpriv->dm.entry_min_undec_sm_pwdb; + } + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "rtl8723e_dm_bt_get_rx_ss() = %ld\n", + undecoratedsmoothed_pwdb); + + return undecoratedsmoothed_pwdb; +} + +void rtl8723e_dm_bt_balance(struct ieee80211_hw *hw, + bool balance_on, u8 ms0, u8 ms1) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 h2c_parameter[3] = {0}; + + if (balance_on) { + h2c_parameter[2] = 1; + h2c_parameter[1] = ms1; + h2c_parameter[0] = ms0; + rtlpriv->btcoexist.fw_coexist_all_off = false; + } else { + h2c_parameter[2] = 0; + h2c_parameter[1] = 0; + h2c_parameter[0] = 0; + } + rtlpriv->btcoexist.balance_on = balance_on; + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[DM][BT], Balance=[%s:%dms:%dms], write 0xc=0x%x\n", + balance_on ? "ON" : "OFF", ms0, ms1, h2c_parameter[0]<<16 | + h2c_parameter[1]<<8 | h2c_parameter[2]); + + rtl8723e_fill_h2c_cmd(hw, 0xc, 3, h2c_parameter); +} + + +void rtl8723e_dm_bt_agc_table(struct ieee80211_hw *hw, u8 type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (type == BT_AGCTABLE_OFF) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BT]AGCTable Off!\n"); + rtl_write_dword(rtlpriv, 0xc78, 0x641c0001); + rtl_write_dword(rtlpriv, 0xc78, 0x631d0001); + rtl_write_dword(rtlpriv, 0xc78, 0x621e0001); + rtl_write_dword(rtlpriv, 0xc78, 0x611f0001); + rtl_write_dword(rtlpriv, 0xc78, 0x60200001); + + rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, + RF_RX_AGC_HP, 0xfffff, 0x32000); + rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, + RF_RX_AGC_HP, 0xfffff, 0x71000); + rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, + RF_RX_AGC_HP, 0xfffff, 0xb0000); + rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, + RF_RX_AGC_HP, 0xfffff, 0xfc000); + rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, + RF_RX_G1, 0xfffff, 0x30355); + } else if (type == BT_AGCTABLE_ON) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BT]AGCTable On!\n"); + rtl_write_dword(rtlpriv, 0xc78, 0x4e1c0001); + rtl_write_dword(rtlpriv, 0xc78, 0x4d1d0001); + rtl_write_dword(rtlpriv, 0xc78, 0x4c1e0001); + rtl_write_dword(rtlpriv, 0xc78, 0x4b1f0001); + rtl_write_dword(rtlpriv, 0xc78, 0x4a200001); + + rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, + RF_RX_AGC_HP, 0xfffff, 0xdc000); + rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, + RF_RX_AGC_HP, 0xfffff, 0x90000); + rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, + RF_RX_AGC_HP, 0xfffff, 0x51000); + rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, + RF_RX_AGC_HP, 0xfffff, 0x12000); + rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, + RF_RX_G1, 0xfffff, 0x00355); + + rtlpriv->btcoexist.sw_coexist_all_off = false; + } +} + +void rtl8723e_dm_bt_bb_back_off_level(struct ieee80211_hw *hw, u8 type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (type == BT_BB_BACKOFF_OFF) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BT]BBBackOffLevel Off!\n"); + rtl_write_dword(rtlpriv, 0xc04, 0x3a05611); + } else if (type == BT_BB_BACKOFF_ON) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BT]BBBackOffLevel On!\n"); + rtl_write_dword(rtlpriv, 0xc04, 0x3a07611); + rtlpriv->btcoexist.sw_coexist_all_off = false; + } +} + +void rtl8723e_dm_bt_fw_coex_all_off(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "rtl8723e_dm_bt_fw_coex_all_off()\n"); + + if (rtlpriv->btcoexist.fw_coexist_all_off) + return; + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "rtl8723e_dm_bt_fw_coex_all_off(), real Do\n"); + rtl8723e_dm_bt_fw_coex_all_off_8723a(hw); + rtlpriv->btcoexist.fw_coexist_all_off = true; +} + +void rtl8723e_dm_bt_sw_coex_all_off(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "rtl8723e_dm_bt_sw_coex_all_off()\n"); + + if (rtlpriv->btcoexist.sw_coexist_all_off) + return; + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "rtl8723e_dm_bt_sw_coex_all_off(), real Do\n"); + rtl8723e_dm_bt_sw_coex_all_off_8723a(hw); + rtlpriv->btcoexist.sw_coexist_all_off = true; +} + +void rtl8723e_dm_bt_hw_coex_all_off(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "rtl8723e_dm_bt_hw_coex_all_off()\n"); + + if (rtlpriv->btcoexist.hw_coexist_all_off) + return; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "rtl8723e_dm_bt_hw_coex_all_off(), real Do\n"); + + rtl8723e_dm_bt_hw_coex_all_off_8723a(hw); + + rtlpriv->btcoexist.hw_coexist_all_off = true; +} + +void rtl8723e_btdm_coex_all_off(struct ieee80211_hw *hw) +{ + rtl8723e_dm_bt_fw_coex_all_off(hw); + rtl8723e_dm_bt_sw_coex_all_off(hw); + rtl8723e_dm_bt_hw_coex_all_off(hw); +} + +bool rtl8723e_dm_bt_is_coexist_state_changed(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if ((rtlpriv->btcoexist.previous_state == rtlpriv->btcoexist.cstate) && + (rtlpriv->btcoexist.previous_state_h == + rtlpriv->btcoexist.cstate_h)) + return false; + return true; +} + +bool rtl8723e_dm_bt_is_wifi_up_link(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->link_info.tx_busy_traffic) + return true; + return false; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h new file mode 100644 index 000000000000..bcd64a22acc0 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.h @@ -0,0 +1,158 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_HAL_BT_COEXIST_H__ +#define __RTL8723E_HAL_BT_COEXIST_H__ + +#include "../wifi.h" + +/* The reg define is for 8723 */ +#define REG_HIGH_PRIORITY_TXRX 0x770 +#define REG_LOW_PRIORITY_TXRX 0x774 + +#define BT_FW_COEX_THRESH_TOL 6 +#define BT_FW_COEX_THRESH_20 20 +#define BT_FW_COEX_THRESH_23 23 +#define BT_FW_COEX_THRESH_25 25 +#define BT_FW_COEX_THRESH_30 30 +#define BT_FW_COEX_THRESH_35 35 +#define BT_FW_COEX_THRESH_40 40 +#define BT_FW_COEX_THRESH_45 45 +#define BT_FW_COEX_THRESH_47 47 +#define BT_FW_COEX_THRESH_50 50 +#define BT_FW_COEX_THRESH_55 55 + +#define BT_COEX_STATE_BT30 BIT(0) +#define BT_COEX_STATE_WIFI_HT20 BIT(1) +#define BT_COEX_STATE_WIFI_HT40 BIT(2) +#define BT_COEX_STATE_WIFI_LEGACY BIT(3) + +#define BT_COEX_STATE_WIFI_RSSI_LOW BIT(4) +#define BT_COEX_STATE_WIFI_RSSI_MEDIUM BIT(5) +#define BT_COEX_STATE_WIFI_RSSI_HIGH BIT(6) +#define BT_COEX_STATE_DEC_BT_POWER BIT(7) + +#define BT_COEX_STATE_WIFI_IDLE BIT(8) +#define BT_COEX_STATE_WIFI_UPLINK BIT(9) +#define BT_COEX_STATE_WIFI_DOWNLINK BIT(10) + +#define BT_COEX_STATE_BT_INQ_PAGE BIT(11) +#define BT_COEX_STATE_BT_IDLE BIT(12) +#define BT_COEX_STATE_BT_UPLINK BIT(13) +#define BT_COEX_STATE_BT_DOWNLINK BIT(14) + +#define BT_COEX_STATE_HOLD_FOR_BT_OPERATION BIT(15) +#define BT_COEX_STATE_BT_RSSI_LOW BIT(19) + +#define BT_COEX_STATE_PROFILE_HID BIT(20) +#define BT_COEX_STATE_PROFILE_A2DP BIT(21) +#define BT_COEX_STATE_PROFILE_PAN BIT(22) +#define BT_COEX_STATE_PROFILE_SCO BIT(23) + +#define BT_COEX_STATE_WIFI_RSSI_1_LOW BIT(24) +#define BT_COEX_STATE_WIFI_RSSI_1_MEDIUM BIT(25) +#define BT_COEX_STATE_WIFI_RSSI_1_HIGH BIT(26) + +#define BT_COEX_STATE_BTINFO_COMMON BIT(30) +#define BT_COEX_STATE_BTINFO_B_HID_SCOESCO BIT(31) +#define BT_COEX_STATE_BTINFO_B_FTP_A2DP BIT(29) + +#define BT_COEX_STATE_BT_CNT_LEVEL_0 BIT(0) +#define BT_COEX_STATE_BT_CNT_LEVEL_1 BIT(1) +#define BT_COEX_STATE_BT_CNT_LEVEL_2 BIT(2) +#define BT_COEX_STATE_BT_CNT_LEVEL_3 BIT(3) + +#define BT_RSSI_STATE_HIGH 0 +#define BT_RSSI_STATE_MEDIUM 1 +#define BT_RSSI_STATE_LOW 2 +#define BT_RSSI_STATE_STAY_HIGH 3 +#define BT_RSSI_STATE_STAY_MEDIUM 4 +#define BT_RSSI_STATE_STAY_LOW 5 + +#define BT_AGCTABLE_OFF 0 +#define BT_AGCTABLE_ON 1 +#define BT_BB_BACKOFF_OFF 0 +#define BT_BB_BACKOFF_ON 1 +#define BT_FW_NAV_OFF 0 +#define BT_FW_NAV_ON 1 + +#define BT_COEX_MECH_NONE 0 +#define BT_COEX_MECH_SCO 1 +#define BT_COEX_MECH_HID 2 +#define BT_COEX_MECH_A2DP 3 +#define BT_COEX_MECH_PAN 4 +#define BT_COEX_MECH_HID_A2DP 5 +#define BT_COEX_MECH_HID_PAN 6 +#define BT_COEX_MECH_PAN_A2DP 7 +#define BT_COEX_MECH_HID_SCO_ESCO 8 +#define BT_COEX_MECH_FTP_A2DP 9 +#define BT_COEX_MECH_COMMON 10 +#define BT_COEX_MECH_MAX 11 + +#define BT_DBG_PROFILE_NONE 0 +#define BT_DBG_PROFILE_SCO 1 +#define BT_DBG_PROFILE_HID 2 +#define BT_DBG_PROFILE_A2DP 3 +#define BT_DBG_PROFILE_PAN 4 +#define BT_DBG_PROFILE_HID_A2DP 5 +#define BT_DBG_PROFILE_HID_PAN 6 +#define BT_DBG_PROFILE_PAN_A2DP 7 +#define BT_DBG_PROFILE_MAX 9 + +#define BTINFO_B_FTP BIT(7) +#define BTINFO_B_A2DP BIT(6) +#define BTINFO_B_HID BIT(5) +#define BTINFO_B_SCO_BUSY BIT(4) +#define BTINFO_B_ACL_BUSY BIT(3) +#define BTINFO_B_INQ_PAGE BIT(2) +#define BTINFO_B_SCO_ESCO BIT(1) +#define BTINFO_B_CONNECTION BIT(0) + +void rtl8723e_btdm_coex_all_off(struct ieee80211_hw *hw); +void rtl8723e_dm_bt_fw_coex_all_off(struct ieee80211_hw *hw); + +void rtl8723e_dm_bt_sw_coex_all_off(struct ieee80211_hw *hw); +void rtl8723e_dm_bt_hw_coex_all_off(struct ieee80211_hw *hw); +long rtl8723e_dm_bt_get_rx_ss(struct ieee80211_hw *hw); +void rtl8723e_dm_bt_balance(struct ieee80211_hw *hw, + bool balance_on, u8 ms0, u8 ms1); +void rtl8723e_dm_bt_agc_table(struct ieee80211_hw *hw, u8 tyep); +void rtl8723e_dm_bt_bb_back_off_level(struct ieee80211_hw *hw, u8 type); +u8 rtl8723e_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw, + u8 level_num, u8 rssi_thresh, + u8 rssi_thresh1); +u8 rtl8723e_dm_bt_check_coex_rssi_state1(struct ieee80211_hw *hw, + u8 level_num, u8 rssi_thresh, + u8 rssi_thresh1); +void _rtl8723_dm_bt_check_wifi_state(struct ieee80211_hw *hw); +void rtl8723e_dm_bt_reject_ap_aggregated_packet(struct ieee80211_hw *hw, + bool b_reject); +bool rtl8723e_dm_bt_is_coexist_state_changed(struct ieee80211_hw *hw); +bool rtl8723e_dm_bt_is_wifi_up_link(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c new file mode 100644 index 000000000000..00a0531cc5f4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.c @@ -0,0 +1,1780 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#include "hal_btc.h" +#include "../pci.h" +#include "phy.h" +#include "fw.h" +#include "reg.h" +#include "def.h" +#include "../rtl8723com/phy_common.h" + +static struct bt_coexist_8723 hal_coex_8723; + +void rtl8723e_dm_bt_turn_off_bt_coexist_before_enter_lps(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if (!rtlpriv->btcoexist.bt_coexistence) + return; + + if (ppsc->inactiveps) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BT][DM], Before enter IPS, turn off all Coexist DM\n"); + rtlpriv->btcoexist.cstate = 0; + rtlpriv->btcoexist.previous_state = 0; + rtlpriv->btcoexist.cstate_h = 0; + rtlpriv->btcoexist.previous_state_h = 0; + rtl8723e_btdm_coex_all_off(hw); + } +} + +static enum rt_media_status mgnt_link_status_query(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + enum rt_media_status m_status = RT_MEDIA_DISCONNECT; + u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0; + if (bibss || rtlpriv->mac80211.link_state >= MAC80211_LINKED) + m_status = RT_MEDIA_CONNECT; + + return m_status; +} + +void rtl_8723e_bt_wifi_media_status_notify(struct ieee80211_hw *hw, + bool mstatus) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u8 h2c_parameter[3] = {0}; + u8 chnl; + + if (!rtlpriv->btcoexist.bt_coexistence) + return; + + if (RT_MEDIA_CONNECT == mstatus) + h2c_parameter[0] = 0x1; /* 0: disconnected, 1:connected */ + else + h2c_parameter[0] = 0x0; + + if (mgnt_link_status_query(hw)) { + chnl = rtlphy->current_channel; + h2c_parameter[1] = chnl; + } + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) + h2c_parameter[2] = 0x30; + else + h2c_parameter[2] = 0x20; + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], FW write 0x19=0x%x\n", + h2c_parameter[0]<<16|h2c_parameter[1]<<8|h2c_parameter[2]); + + rtl8723e_fill_h2c_cmd(hw, 0x19, 3, h2c_parameter); +} + +static bool rtl8723e_dm_bt_is_wifi_busy(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (rtlpriv->link_info.busytraffic || + rtlpriv->link_info.rx_busy_traffic || + rtlpriv->link_info.tx_busy_traffic) + return true; + else + return false; +} + +static void rtl8723e_dm_bt_set_fw_3a(struct ieee80211_hw *hw, + u8 byte1, u8 byte2, u8 byte3, u8 byte4, + u8 byte5) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 h2c_parameter[5]; + + h2c_parameter[0] = byte1; + h2c_parameter[1] = byte2; + h2c_parameter[2] = byte3; + h2c_parameter[3] = byte4; + h2c_parameter[4] = byte5; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], FW write 0x3a(4bytes)=0x%x%8x\n", + h2c_parameter[0], h2c_parameter[1]<<24 | + h2c_parameter[2]<<16 | h2c_parameter[3]<<8 | + h2c_parameter[4]); + rtl8723e_fill_h2c_cmd(hw, 0x3a, 5, h2c_parameter); +} + +static bool rtl8723e_dm_bt_need_to_dec_bt_pwr(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (mgnt_link_status_query(hw) == RT_MEDIA_CONNECT) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Need to decrease bt power\n"); + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_DEC_BT_POWER; + return true; + } + + rtlpriv->btcoexist.cstate &= ~BT_COEX_STATE_DEC_BT_POWER; + return false; +} + +static bool rtl8723e_dm_bt_is_same_coexist_state(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if ((rtlpriv->btcoexist.previous_state == + rtlpriv->btcoexist.cstate) && + (rtlpriv->btcoexist.previous_state_h == + rtlpriv->btcoexist.cstate_h)) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[DM][BT], Coexist state do not chang!!\n"); + return true; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[DM][BT], Coexist state changed!!\n"); + return false; + } +} + +static void rtl8723e_dm_bt_set_coex_table(struct ieee80211_hw *hw, + u32 val_0x6c0, u32 val_0x6c8, + u32 val_0x6cc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "set coex table, set 0x6c0=0x%x\n", val_0x6c0); + rtl_write_dword(rtlpriv, 0x6c0, val_0x6c0); + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "set coex table, set 0x6c8=0x%x\n", val_0x6c8); + rtl_write_dword(rtlpriv, 0x6c8, val_0x6c8); + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "set coex table, set 0x6cc=0x%x\n", val_0x6cc); + rtl_write_byte(rtlpriv, 0x6cc, val_0x6cc); +} + +static void rtl8723e_dm_bt_set_hw_pta_mode(struct ieee80211_hw *hw, bool b_mode) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (BT_PTA_MODE_ON == b_mode) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, "PTA mode on, "); + /* Enable GPIO 0/1/2/3/8 pins for bt */ + rtl_write_byte(rtlpriv, 0x40, 0x20); + rtlpriv->btcoexist.hw_coexist_all_off = false; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, "PTA mode off\n"); + rtl_write_byte(rtlpriv, 0x40, 0x0); + } +} + +static void rtl8723e_dm_bt_set_sw_rf_rx_lpf_corner(struct ieee80211_hw *hw, + u8 type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (BT_RF_RX_LPF_CORNER_SHRINK == type) { + /* Shrink RF Rx LPF corner, 0x1e[7:4]=1111 ==> [11:4] */ + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "Shrink RF Rx LPF corner!!\n"); + rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, 0x1e, + 0xfffff, 0xf0ff7); + rtlpriv->btcoexist.sw_coexist_all_off = false; + } else if (BT_RF_RX_LPF_CORNER_RESUME == type) { + /*Resume RF Rx LPF corner*/ + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "Resume RF Rx LPF corner!!\n"); + rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, 0x1e, 0xfffff, + rtlpriv->btcoexist.bt_rfreg_origin_1e); + } +} + +static void dm_bt_set_sw_penalty_tx_rate_adapt(struct ieee80211_hw *hw, + u8 ra_type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp_u1; + + tmp_u1 = rtl_read_byte(rtlpriv, 0x4fd); + tmp_u1 |= BIT(0); + if (BT_TX_RATE_ADAPTIVE_LOW_PENALTY == ra_type) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "Tx rate adaptive, set low penalty!!\n"); + tmp_u1 &= ~BIT(2); + rtlpriv->btcoexist.sw_coexist_all_off = false; + } else if (BT_TX_RATE_ADAPTIVE_NORMAL == ra_type) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "Tx rate adaptive, set normal!!\n"); + tmp_u1 |= BIT(2); + } + + rtl_write_byte(rtlpriv, 0x4fd, tmp_u1); +} + +static void rtl8723e_dm_bt_btdm_structure_reload(struct ieee80211_hw *hw, + struct btdm_8723 *btdm) +{ + btdm->all_off = false; + btdm->agc_table_en = false; + btdm->adc_back_off_on = false; + btdm->b2_ant_hid_en = false; + btdm->low_penalty_rate_adaptive = false; + btdm->rf_rx_lpf_shrink = false; + btdm->reject_aggre_pkt = false; + + btdm->tdma_on = false; + btdm->tdma_ant = TDMA_2ANT; + btdm->tdma_nav = TDMA_NAV_OFF; + btdm->tdma_dac_swing = TDMA_DAC_SWING_OFF; + btdm->fw_dac_swing_lvl = 0x20; + + btdm->tra_tdma_on = false; + btdm->tra_tdma_ant = TDMA_2ANT; + btdm->tra_tdma_nav = TDMA_NAV_OFF; + btdm->ignore_wlan_act = false; + + btdm->ps_tdma_on = false; + btdm->ps_tdma_byte[0] = 0x0; + btdm->ps_tdma_byte[1] = 0x0; + btdm->ps_tdma_byte[2] = 0x0; + btdm->ps_tdma_byte[3] = 0x8; + btdm->ps_tdma_byte[4] = 0x0; + + btdm->pta_on = true; + btdm->val_0x6c0 = 0x5a5aaaaa; + btdm->val_0x6c8 = 0xcc; + btdm->val_0x6cc = 0x3; + + btdm->sw_dac_swing_on = false; + btdm->sw_dac_swing_lvl = 0xc0; + btdm->wlan_act_hi = 0x20; + btdm->wlan_act_lo = 0x10; + btdm->bt_retry_index = 2; + + btdm->dec_bt_pwr = false; +} + +static void rtl8723e_dm_bt_btdm_structure_reload_all_off(struct ieee80211_hw *hw, + struct btdm_8723 *btdm) +{ + rtl8723e_dm_bt_btdm_structure_reload(hw, btdm); + btdm->all_off = true; + btdm->pta_on = false; + btdm->wlan_act_hi = 0x10; +} + +static bool rtl8723e_dm_bt_is_2_ant_common_action(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct btdm_8723 btdm8723; + bool b_common = false; + + rtl8723e_dm_bt_btdm_structure_reload(hw, &btdm8723); + + if (!rtl8723e_dm_bt_is_wifi_busy(hw) && + !rtlpriv->btcoexist.bt_busy) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi idle + Bt idle, bt coex mechanism always off!!\n"); + rtl8723e_dm_bt_btdm_structure_reload_all_off(hw, &btdm8723); + b_common = true; + } else if (rtl8723e_dm_bt_is_wifi_busy(hw) && + !rtlpriv->btcoexist.bt_busy) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi non-idle + Bt disabled/idle!!\n"); + btdm8723.low_penalty_rate_adaptive = true; + btdm8723.rf_rx_lpf_shrink = false; + btdm8723.reject_aggre_pkt = false; + + /* sw mechanism */ + btdm8723.agc_table_en = false; + btdm8723.adc_back_off_on = false; + btdm8723.sw_dac_swing_on = false; + + btdm8723.pta_on = true; + btdm8723.val_0x6c0 = 0x5a5aaaaa; + btdm8723.val_0x6c8 = 0xcccc; + btdm8723.val_0x6cc = 0x3; + + btdm8723.tdma_on = false; + btdm8723.tdma_dac_swing = TDMA_DAC_SWING_OFF; + btdm8723.b2_ant_hid_en = false; + + b_common = true; + } else if (rtlpriv->btcoexist.bt_busy) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Bt non-idle!\n"); + if (mgnt_link_status_query(hw) == RT_MEDIA_CONNECT) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi connection exist\n"); + b_common = false; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "No Wifi connection!\n"); + btdm8723.rf_rx_lpf_shrink = true; + btdm8723.low_penalty_rate_adaptive = false; + btdm8723.reject_aggre_pkt = false; + + /* sw mechanism */ + btdm8723.agc_table_en = false; + btdm8723.adc_back_off_on = false; + btdm8723.sw_dac_swing_on = false; + + btdm8723.pta_on = true; + btdm8723.val_0x6c0 = 0x55555555; + btdm8723.val_0x6c8 = 0x0000ffff; + btdm8723.val_0x6cc = 0x3; + + btdm8723.tdma_on = false; + btdm8723.tdma_dac_swing = TDMA_DAC_SWING_OFF; + btdm8723.b2_ant_hid_en = false; + + b_common = true; + } + } + + if (rtl8723e_dm_bt_need_to_dec_bt_pwr(hw)) + btdm8723.dec_bt_pwr = true; + + if (b_common) + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_BTINFO_COMMON; + + if (b_common && rtl8723e_dm_bt_is_coexist_state_changed(hw)) + rtl8723e_dm_bt_set_bt_dm(hw, &btdm8723); + + return b_common; +} + +static void rtl8723e_dm_bt_set_sw_full_time_dac_swing( + struct ieee80211_hw *hw, + bool sw_dac_swing_on, + u32 sw_dac_swing_lvl) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (sw_dac_swing_on) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], SwDacSwing = 0x%x\n", sw_dac_swing_lvl); + rtl8723_phy_set_bb_reg(hw, 0x880, 0xff000000, + sw_dac_swing_lvl); + rtlpriv->btcoexist.sw_coexist_all_off = false; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], SwDacSwing Off!\n"); + rtl8723_phy_set_bb_reg(hw, 0x880, 0xff000000, 0xc0); + } +} + +static void rtl8723e_dm_bt_set_fw_dec_bt_pwr( + struct ieee80211_hw *hw, bool dec_bt_pwr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 h2c_parameter[1] = {0}; + + h2c_parameter[0] = 0; + + if (dec_bt_pwr) { + h2c_parameter[0] |= BIT(1); + rtlpriv->btcoexist.fw_coexist_all_off = false; + } + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], decrease Bt Power : %s, write 0x21=0x%x\n", + (dec_bt_pwr ? "Yes!!" : "No!!"), h2c_parameter[0]); + + rtl8723e_fill_h2c_cmd(hw, 0x21, 1, h2c_parameter); +} + +static void rtl8723e_dm_bt_set_fw_2_ant_hid(struct ieee80211_hw *hw, + bool b_enable, bool b_dac_swing_on) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 h2c_parameter[1] = {0}; + + if (b_enable) { + h2c_parameter[0] |= BIT(0); + rtlpriv->btcoexist.fw_coexist_all_off = false; + } + if (b_dac_swing_on) + h2c_parameter[0] |= BIT(1); /* Dac Swing default enable */ + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], turn 2-Ant+HID mode %s, DACSwing:%s, write 0x15=0x%x\n", + (b_enable ? "ON!!" : "OFF!!"), (b_dac_swing_on ? "ON" : "OFF"), + h2c_parameter[0]); + + rtl8723e_fill_h2c_cmd(hw, 0x15, 1, h2c_parameter); +} + +static void rtl8723e_dm_bt_set_fw_tdma_ctrl(struct ieee80211_hw *hw, + bool b_enable, u8 ant_num, + u8 nav_en, u8 dac_swing_en) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 h2c_parameter[1] = {0}; + u8 h2c_parameter1[1] = {0}; + + h2c_parameter[0] = 0; + h2c_parameter1[0] = 0; + + if (b_enable) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], set BT PTA update manager to trigger update!!\n"); + h2c_parameter1[0] |= BIT(0); + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], turn TDMA mode ON!!\n"); + h2c_parameter[0] |= BIT(0); /* function enable */ + if (TDMA_1ANT == ant_num) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], TDMA_1ANT\n"); + h2c_parameter[0] |= BIT(1); + } else if (TDMA_2ANT == ant_num) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], TDMA_2ANT\n"); + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], Unknown Ant\n"); + } + + if (TDMA_NAV_OFF == nav_en) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], TDMA_NAV_OFF\n"); + } else if (TDMA_NAV_ON == nav_en) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], TDMA_NAV_ON\n"); + h2c_parameter[0] |= BIT(2); + } + + if (TDMA_DAC_SWING_OFF == dac_swing_en) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], TDMA_DAC_SWING_OFF\n"); + } else if (TDMA_DAC_SWING_ON == dac_swing_en) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], TDMA_DAC_SWING_ON\n"); + h2c_parameter[0] |= BIT(4); + } + rtlpriv->btcoexist.fw_coexist_all_off = false; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], set BT PTA update manager to no update!!\n"); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], turn TDMA mode OFF!!\n"); + } + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], FW2AntTDMA, write 0x26=0x%x\n", + h2c_parameter1[0]); + rtl8723e_fill_h2c_cmd(hw, 0x26, 1, h2c_parameter1); + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], FW2AntTDMA, write 0x14=0x%x\n", + h2c_parameter[0]); + rtl8723e_fill_h2c_cmd(hw, 0x14, 1, h2c_parameter); +} + +static void rtl8723e_dm_bt_set_fw_ignore_wlan_act(struct ieee80211_hw *hw, + bool b_enable) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 h2c_parameter[1] = {0}; + + if (b_enable) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], BT Ignore Wlan_Act !!\n"); + h2c_parameter[0] |= BIT(0); /* function enable */ + rtlpriv->btcoexist.fw_coexist_all_off = false; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], BT don't ignore Wlan_Act !!\n"); + } + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], set FW for BT Ignore Wlan_Act, write 0x25=0x%x\n", + h2c_parameter[0]); + + rtl8723e_fill_h2c_cmd(hw, 0x25, 1, h2c_parameter); +} + +static void rtl8723e_dm_bt_set_fw_tra_tdma_ctrl(struct ieee80211_hw *hw, + bool b_enable, u8 ant_num, + u8 nav_en) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + u8 h2c_parameter[2] = {0}; + + /* Only 8723 B cut should do this */ + if (IS_VENDOR_8723_A_CUT(rtlhal->version)) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], not 8723B cut, don't set Traditional TDMA!!\n"); + return; + } + + if (b_enable) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], turn TTDMA mode ON!!\n"); + h2c_parameter[0] |= BIT(0); /* function enable */ + if (TDMA_1ANT == ant_num) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], TTDMA_1ANT\n"); + h2c_parameter[0] |= BIT(1); + } else if (TDMA_2ANT == ant_num) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], TTDMA_2ANT\n"); + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], Unknown Ant\n"); + } + + if (TDMA_NAV_OFF == nav_en) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], TTDMA_NAV_OFF\n"); + } else if (TDMA_NAV_ON == nav_en) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], TTDMA_NAV_ON\n"); + h2c_parameter[1] |= BIT(0); + } + + rtlpriv->btcoexist.fw_coexist_all_off = false; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], turn TTDMA mode OFF!!\n"); + } + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], FW Traditional TDMA, write 0x33=0x%x\n", + h2c_parameter[0] << 8 | h2c_parameter[1]); + + rtl8723e_fill_h2c_cmd(hw, 0x33, 2, h2c_parameter); +} + +static void rtl8723e_dm_bt_set_fw_dac_swing_level(struct ieee80211_hw *hw, + u8 dac_swing_lvl) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 h2c_parameter[1] = {0}; + h2c_parameter[0] = dac_swing_lvl; + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], Set Dac Swing Level=0x%x\n", dac_swing_lvl); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], write 0x29=0x%x\n", h2c_parameter[0]); + + rtl8723e_fill_h2c_cmd(hw, 0x29, 1, h2c_parameter); +} + +static void rtl8723e_dm_bt_set_fw_bt_hid_info(struct ieee80211_hw *hw, + bool b_enable) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 h2c_parameter[1] = {0}; + h2c_parameter[0] = 0; + + if (b_enable) { + h2c_parameter[0] |= BIT(0); + rtlpriv->btcoexist.fw_coexist_all_off = false; + } + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], Set BT HID information=0x%x\n", b_enable); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], write 0x24=0x%x\n", h2c_parameter[0]); + + rtl8723e_fill_h2c_cmd(hw, 0x24, 1, h2c_parameter); +} + +static void rtl8723e_dm_bt_set_fw_bt_retry_index(struct ieee80211_hw *hw, + u8 retry_index) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 h2c_parameter[1] = {0}; + h2c_parameter[0] = retry_index; + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], Set BT Retry Index=%d\n", retry_index); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], write 0x23=0x%x\n", h2c_parameter[0]); + + rtl8723e_fill_h2c_cmd(hw, 0x23, 1, h2c_parameter); +} + +static void rtl8723e_dm_bt_set_fw_wlan_act(struct ieee80211_hw *hw, + u8 wlan_act_hi, u8 wlan_act_lo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 h2c_parameter_hi[1] = {0}; + u8 h2c_parameter_lo[1] = {0}; + h2c_parameter_hi[0] = wlan_act_hi; + h2c_parameter_lo[0] = wlan_act_lo; + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], Set WLAN_ACT Hi:Lo=0x%x/0x%x\n", + wlan_act_hi, wlan_act_lo); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], write 0x22=0x%x\n", h2c_parameter_hi[0]); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], write 0x11=0x%x\n", h2c_parameter_lo[0]); + + /* WLAN_ACT = High duration, unit:ms */ + rtl8723e_fill_h2c_cmd(hw, 0x22, 1, h2c_parameter_hi); + /* WLAN_ACT = Low duration, unit:3*625us */ + rtl8723e_fill_h2c_cmd(hw, 0x11, 1, h2c_parameter_lo); +} + +void rtl8723e_dm_bt_set_bt_dm(struct ieee80211_hw *hw, + struct btdm_8723 *btdm) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct btdm_8723 *btdm_8723 = &hal_coex_8723.btdm; + u8 i; + + bool fw_current_inpsmode = false; + bool fw_ps_awake = true; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inpsmode)); + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, + (u8 *)(&fw_ps_awake)); + + /* check new setting is different with the old one, */ + /* if all the same, don't do the setting again. */ + if (memcmp(btdm_8723, btdm, sizeof(struct btdm_8723)) == 0) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], the same coexist setting, return!!\n"); + return; + } else { /* save the new coexist setting */ + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], UPDATE TO NEW COEX SETTING!!\n"); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new bAllOff=0x%x/ 0x%x\n", + btdm_8723->all_off, btdm->all_off); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new agc_table_en=0x%x/ 0x%x\n", + btdm_8723->agc_table_en, btdm->agc_table_en); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new adc_back_off_on=0x%x/ 0x%x\n", + btdm_8723->adc_back_off_on, + btdm->adc_back_off_on); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new b2_ant_hid_en=0x%x/ 0x%x\n", + btdm_8723->b2_ant_hid_en, btdm->b2_ant_hid_en); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new bLowPenaltyRateAdaptive=0x%x/ 0x%x\n", + btdm_8723->low_penalty_rate_adaptive, + btdm->low_penalty_rate_adaptive); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new bRfRxLpfShrink=0x%x/ 0x%x\n", + btdm_8723->rf_rx_lpf_shrink, + btdm->rf_rx_lpf_shrink); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new bRejectAggrePkt=0x%x/ 0x%x\n", + btdm_8723->reject_aggre_pkt, + btdm->reject_aggre_pkt); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new tdma_on=0x%x/ 0x%x\n", + btdm_8723->tdma_on, btdm->tdma_on); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new tdmaAnt=0x%x/ 0x%x\n", + btdm_8723->tdma_ant, btdm->tdma_ant); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new tdmaNav=0x%x/ 0x%x\n", + btdm_8723->tdma_nav, btdm->tdma_nav); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new tdma_dac_swing=0x%x/ 0x%x\n", + btdm_8723->tdma_dac_swing, btdm->tdma_dac_swing); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new fw_dac_swing_lvl=0x%x/ 0x%x\n", + btdm_8723->fw_dac_swing_lvl, + btdm->fw_dac_swing_lvl); + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new bTraTdmaOn=0x%x/ 0x%x\n", + btdm_8723->tra_tdma_on, btdm->tra_tdma_on); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new traTdmaAnt=0x%x/ 0x%x\n", + btdm_8723->tra_tdma_ant, btdm->tra_tdma_ant); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new traTdmaNav=0x%x/ 0x%x\n", + btdm_8723->tra_tdma_nav, btdm->tra_tdma_nav); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new bPsTdmaOn=0x%x/ 0x%x\n", + btdm_8723->ps_tdma_on, btdm->ps_tdma_on); + for (i = 0; i < 5; i++) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new psTdmaByte[i]=0x%x/ 0x%x\n", + btdm_8723->ps_tdma_byte[i], + btdm->ps_tdma_byte[i]); + } + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new bIgnoreWlanAct=0x%x/ 0x%x\n", + btdm_8723->ignore_wlan_act, + btdm->ignore_wlan_act); + + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new bPtaOn=0x%x/ 0x%x\n", + btdm_8723->pta_on, btdm->pta_on); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new val_0x6c0=0x%x/ 0x%x\n", + btdm_8723->val_0x6c0, btdm->val_0x6c0); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new val_0x6c8=0x%x/ 0x%x\n", + btdm_8723->val_0x6c8, btdm->val_0x6c8); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new val_0x6cc=0x%x/ 0x%x\n", + btdm_8723->val_0x6cc, btdm->val_0x6cc); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new sw_dac_swing_on=0x%x/ 0x%x\n", + btdm_8723->sw_dac_swing_on, + btdm->sw_dac_swing_on); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new sw_dac_swing_lvl=0x%x/ 0x%x\n", + btdm_8723->sw_dac_swing_lvl, + btdm->sw_dac_swing_lvl); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new wlanActHi=0x%x/ 0x%x\n", + btdm_8723->wlan_act_hi, btdm->wlan_act_hi); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new wlanActLo=0x%x/ 0x%x\n", + btdm_8723->wlan_act_lo, btdm->wlan_act_lo); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], original/new btRetryIndex=0x%x/ 0x%x\n", + btdm_8723->bt_retry_index, btdm->bt_retry_index); + + memcpy(btdm_8723, btdm, sizeof(struct btdm_8723)); + } + /* Here we only consider when Bt Operation + * inquiry/paging/pairing is ON + * we only need to turn off TDMA + */ + + if (rtlpriv->btcoexist.hold_for_bt_operation) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], set to ignore wlanAct for BT OP!!\n"); + rtl8723e_dm_bt_set_fw_ignore_wlan_act(hw, true); + return; + } + + if (btdm->all_off) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], disable all coexist mechanism !!\n"); + rtl8723e_btdm_coex_all_off(hw); + return; + } + + rtl8723e_dm_bt_reject_ap_aggregated_packet(hw, btdm->reject_aggre_pkt); + + if (btdm->low_penalty_rate_adaptive) + dm_bt_set_sw_penalty_tx_rate_adapt(hw, BT_TX_RATE_ADAPTIVE_LOW_PENALTY); + else + dm_bt_set_sw_penalty_tx_rate_adapt(hw, + BT_TX_RATE_ADAPTIVE_NORMAL); + + if (btdm->rf_rx_lpf_shrink) + rtl8723e_dm_bt_set_sw_rf_rx_lpf_corner(hw, + BT_RF_RX_LPF_CORNER_SHRINK); + else + rtl8723e_dm_bt_set_sw_rf_rx_lpf_corner(hw, + BT_RF_RX_LPF_CORNER_RESUME); + + if (btdm->agc_table_en) + rtl8723e_dm_bt_agc_table(hw, BT_AGCTABLE_ON); + else + rtl8723e_dm_bt_agc_table(hw, BT_AGCTABLE_OFF); + + if (btdm->adc_back_off_on) + rtl8723e_dm_bt_bb_back_off_level(hw, BT_BB_BACKOFF_ON); + else + rtl8723e_dm_bt_bb_back_off_level(hw, BT_BB_BACKOFF_OFF); + + rtl8723e_dm_bt_set_fw_bt_retry_index(hw, btdm->bt_retry_index); + + rtl8723e_dm_bt_set_fw_dac_swing_level(hw, btdm->fw_dac_swing_lvl); + rtl8723e_dm_bt_set_fw_wlan_act(hw, btdm->wlan_act_hi, + btdm->wlan_act_lo); + + rtl8723e_dm_bt_set_coex_table(hw, btdm->val_0x6c0, + btdm->val_0x6c8, btdm->val_0x6cc); + rtl8723e_dm_bt_set_hw_pta_mode(hw, btdm->pta_on); + + /* Note: There is a constraint between TDMA and 2AntHID + * Only one of 2AntHid and tdma can be turn on + * We should turn off those mechanisms should be turned off first + * and then turn on those mechanisms should be turned on. + */ + if (btdm->b2_ant_hid_en) { + /* turn off tdma */ + rtl8723e_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on, + btdm->tra_tdma_ant, + btdm->tra_tdma_nav); + rtl8723e_dm_bt_set_fw_tdma_ctrl(hw, false, btdm->tdma_ant, + btdm->tdma_nav, + btdm->tdma_dac_swing); + + /* turn off Pstdma */ + rtl8723e_dm_bt_set_fw_ignore_wlan_act(hw, + btdm->ignore_wlan_act); + /* Antenna control by PTA, 0x870 = 0x300. */ + rtl8723e_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0); + + /* turn on 2AntHid */ + rtl8723e_dm_bt_set_fw_bt_hid_info(hw, true); + rtl8723e_dm_bt_set_fw_2_ant_hid(hw, true, true); + } else if (btdm->tdma_on) { + /* turn off 2AntHid */ + rtl8723e_dm_bt_set_fw_bt_hid_info(hw, false); + rtl8723e_dm_bt_set_fw_2_ant_hid(hw, false, false); + + /* turn off pstdma */ + rtl8723e_dm_bt_set_fw_ignore_wlan_act(hw, + btdm->ignore_wlan_act); + /* Antenna control by PTA, 0x870 = 0x300. */ + rtl8723e_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0); + + /* turn on tdma */ + rtl8723e_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on, + btdm->tra_tdma_ant, + btdm->tra_tdma_nav); + rtl8723e_dm_bt_set_fw_tdma_ctrl(hw, true, btdm->tdma_ant, + btdm->tdma_nav, + btdm->tdma_dac_swing); + } else if (btdm->ps_tdma_on) { + /* turn off 2AntHid */ + rtl8723e_dm_bt_set_fw_bt_hid_info(hw, false); + rtl8723e_dm_bt_set_fw_2_ant_hid(hw, false, false); + + /* turn off tdma */ + rtl8723e_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on, + btdm->tra_tdma_ant, + btdm->tra_tdma_nav); + rtl8723e_dm_bt_set_fw_tdma_ctrl(hw, false, btdm->tdma_ant, + btdm->tdma_nav, + btdm->tdma_dac_swing); + + /* turn on pstdma */ + rtl8723e_dm_bt_set_fw_ignore_wlan_act(hw, + btdm->ignore_wlan_act); + rtl8723e_dm_bt_set_fw_3a(hw, btdm->ps_tdma_byte[0], + btdm->ps_tdma_byte[1], + btdm->ps_tdma_byte[2], + btdm->ps_tdma_byte[3], + btdm->ps_tdma_byte[4]); + } else { + /* turn off 2AntHid */ + rtl8723e_dm_bt_set_fw_bt_hid_info(hw, false); + rtl8723e_dm_bt_set_fw_2_ant_hid(hw, false, false); + + /* turn off tdma */ + rtl8723e_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on, + btdm->tra_tdma_ant, + btdm->tra_tdma_nav); + rtl8723e_dm_bt_set_fw_tdma_ctrl(hw, false, btdm->tdma_ant, + btdm->tdma_nav, + btdm->tdma_dac_swing); + + /* turn off pstdma */ + rtl8723e_dm_bt_set_fw_ignore_wlan_act(hw, + btdm->ignore_wlan_act); + /* Antenna control by PTA, 0x870 = 0x300. */ + rtl8723e_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0); + } + + /* Note: + * We should add delay for making sure + * sw DacSwing can be set sucessfully. + * because of that rtl8723e_dm_bt_set_fw_2_ant_hid() + * and rtl8723e_dm_bt_set_fw_tdma_ctrl() + * will overwrite the reg 0x880. + */ + mdelay(30); + rtl8723e_dm_bt_set_sw_full_time_dac_swing(hw, btdm->sw_dac_swing_on, + btdm->sw_dac_swing_lvl); + rtl8723e_dm_bt_set_fw_dec_bt_pwr(hw, btdm->dec_bt_pwr); +} + +/* ============================================================ */ +/* extern function start with BTDM_ */ +/* ============================================================i + */ +static u32 rtl8723e_dm_bt_tx_rx_couter_h(struct ieee80211_hw *hw) +{ + u32 counters = 0; + + counters = hal_coex_8723.high_priority_tx + + hal_coex_8723.high_priority_rx; + return counters; +} + +static u32 rtl8723e_dm_bt_tx_rx_couter_l(struct ieee80211_hw *hw) +{ + u32 counters = 0; + + counters = hal_coex_8723.low_priority_tx + + hal_coex_8723.low_priority_rx; + return counters; +} + +static u8 rtl8723e_dm_bt_bt_tx_rx_counter_level(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 bt_tx_rx_cnt = 0; + u8 bt_tx_rx_cnt_lvl = 0; + + bt_tx_rx_cnt = rtl8723e_dm_bt_tx_rx_couter_h(hw) + + rtl8723e_dm_bt_tx_rx_couter_l(hw); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters = %d\n", bt_tx_rx_cnt); + + rtlpriv->btcoexist.cstate_h &= ~ + (BT_COEX_STATE_BT_CNT_LEVEL_0 | BT_COEX_STATE_BT_CNT_LEVEL_1| + BT_COEX_STATE_BT_CNT_LEVEL_2); + + if (bt_tx_rx_cnt >= BT_TXRX_CNT_THRES_3) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters at level 3\n"); + bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_3; + rtlpriv->btcoexist.cstate_h |= + BT_COEX_STATE_BT_CNT_LEVEL_3; + } else if (bt_tx_rx_cnt >= BT_TXRX_CNT_THRES_2) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters at level 2\n"); + bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_2; + rtlpriv->btcoexist.cstate_h |= + BT_COEX_STATE_BT_CNT_LEVEL_2; + } else if (bt_tx_rx_cnt >= BT_TXRX_CNT_THRES_1) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters at level 1\n"); + bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_1; + rtlpriv->btcoexist.cstate_h |= + BT_COEX_STATE_BT_CNT_LEVEL_1; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters at level 0\n"); + bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_0; + rtlpriv->btcoexist.cstate_h |= + BT_COEX_STATE_BT_CNT_LEVEL_0; + } + return bt_tx_rx_cnt_lvl; +} + +static void rtl8723e_dm_bt_2_ant_hid_sco_esco(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct btdm_8723 btdm8723; + u8 bt_rssi_state, bt_rssi_state1; + u8 bt_tx_rx_cnt_lvl = 0; + + rtl8723e_dm_bt_btdm_structure_reload(hw, &btdm8723); + + btdm8723.rf_rx_lpf_shrink = true; + btdm8723.low_penalty_rate_adaptive = true; + btdm8723.reject_aggre_pkt = false; + + bt_tx_rx_cnt_lvl = rtl8723e_dm_bt_bt_tx_rx_counter_level(hw); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters = %d\n", bt_tx_rx_cnt_lvl); + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, "HT40\n"); + /* coex table */ + btdm8723.val_0x6c0 = 0x55555555; + btdm8723.val_0x6c8 = 0xffff; + btdm8723.val_0x6cc = 0x3; + + /* sw mechanism */ + btdm8723.agc_table_en = false; + btdm8723.adc_back_off_on = false; + btdm8723.sw_dac_swing_on = false; + + /* fw mechanism */ + btdm8723.ps_tdma_on = true; + if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0x5; + btdm8723.ps_tdma_byte[2] = 0x5; + btdm8723.ps_tdma_byte[3] = 0x2; + btdm8723.ps_tdma_byte[4] = 0x80; + } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xa; + btdm8723.ps_tdma_byte[2] = 0xa; + btdm8723.ps_tdma_byte[3] = 0x2; + btdm8723.ps_tdma_byte[4] = 0x80; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters < 1200\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xf; + btdm8723.ps_tdma_byte[2] = 0xf; + btdm8723.ps_tdma_byte[3] = 0x2; + btdm8723.ps_tdma_byte[4] = 0x80; + } + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "HT20 or Legacy\n"); + bt_rssi_state = + rtl8723e_dm_bt_check_coex_rssi_state(hw, 2, 47, 0); + bt_rssi_state1 = + rtl8723e_dm_bt_check_coex_rssi_state1(hw, 2, 27, 0); + + /* coex table */ + btdm8723.val_0x6c0 = 0x55555555; + btdm8723.val_0x6c8 = 0xffff; + btdm8723.val_0x6cc = 0x3; + + /* sw mechanism */ + if ((bt_rssi_state == BT_RSSI_STATE_HIGH) || + (bt_rssi_state == BT_RSSI_STATE_STAY_HIGH)) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi rssi high\n"); + btdm8723.agc_table_en = true; + btdm8723.adc_back_off_on = true; + btdm8723.sw_dac_swing_on = false; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi rssi low\n"); + btdm8723.agc_table_en = false; + btdm8723.adc_back_off_on = false; + btdm8723.sw_dac_swing_on = false; + } + + /* fw mechanism */ + btdm8723.ps_tdma_on = true; + if ((bt_rssi_state1 == BT_RSSI_STATE_HIGH) || + (bt_rssi_state1 == BT_RSSI_STATE_STAY_HIGH)) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi rssi-1 high\n"); + /* only rssi high we need to do this, */ + /* when rssi low, the value will modified by fw */ + rtl_write_byte(rtlpriv, 0x883, 0x40); + if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0x5; + btdm8723.ps_tdma_byte[2] = 0x5; + btdm8723.ps_tdma_byte[3] = 0x83; + btdm8723.ps_tdma_byte[4] = 0x80; + } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters>= 1200 && < 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xa; + btdm8723.ps_tdma_byte[2] = 0xa; + btdm8723.ps_tdma_byte[3] = 0x83; + btdm8723.ps_tdma_byte[4] = 0x80; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters < 1200\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xf; + btdm8723.ps_tdma_byte[2] = 0xf; + btdm8723.ps_tdma_byte[3] = 0x83; + btdm8723.ps_tdma_byte[4] = 0x80; + } + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi rssi-1 low\n"); + if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0x5; + btdm8723.ps_tdma_byte[2] = 0x5; + btdm8723.ps_tdma_byte[3] = 0x2; + btdm8723.ps_tdma_byte[4] = 0x80; + } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xa; + btdm8723.ps_tdma_byte[2] = 0xa; + btdm8723.ps_tdma_byte[3] = 0x2; + btdm8723.ps_tdma_byte[4] = 0x80; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters < 1200\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xf; + btdm8723.ps_tdma_byte[2] = 0xf; + btdm8723.ps_tdma_byte[3] = 0x2; + btdm8723.ps_tdma_byte[4] = 0x80; + } + } + } + + if (rtl8723e_dm_bt_need_to_dec_bt_pwr(hw)) + btdm8723.dec_bt_pwr = true; + + /* Always ignore WlanAct if bHid|bSCOBusy|bSCOeSCO */ + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT btInqPageStartTime = 0x%x, btTxRxCntLvl = %d\n", + hal_coex_8723.bt_inq_page_start_time, bt_tx_rx_cnt_lvl); + if ((hal_coex_8723.bt_inq_page_start_time) || + (BT_TXRX_CNT_LEVEL_3 == bt_tx_rx_cnt_lvl)) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], Set BT inquiry / page scan 0x3a setting\n"); + btdm8723.ps_tdma_on = true; + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0x5; + btdm8723.ps_tdma_byte[2] = 0x5; + btdm8723.ps_tdma_byte[3] = 0x2; + btdm8723.ps_tdma_byte[4] = 0x80; + } + + if (rtl8723e_dm_bt_is_coexist_state_changed(hw)) + rtl8723e_dm_bt_set_bt_dm(hw, &btdm8723); + +} + +static void rtl8723e_dm_bt_2_ant_ftp_a2dp(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct btdm_8723 btdm8723; + + u8 bt_rssi_state, bt_rssi_state1; + u32 bt_tx_rx_cnt_lvl = 0; + + rtl8723e_dm_bt_btdm_structure_reload(hw, &btdm8723); + + btdm8723.rf_rx_lpf_shrink = true; + btdm8723.low_penalty_rate_adaptive = true; + btdm8723.reject_aggre_pkt = false; + + bt_tx_rx_cnt_lvl = rtl8723e_dm_bt_bt_tx_rx_counter_level(hw); + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters = %d\n", bt_tx_rx_cnt_lvl); + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, "HT40\n"); + bt_rssi_state = + rtl8723e_dm_bt_check_coex_rssi_state(hw, 2, 37, 0); + + /* coex table */ + btdm8723.val_0x6c0 = 0x55555555; + btdm8723.val_0x6c8 = 0xffff; + btdm8723.val_0x6cc = 0x3; + + /* sw mechanism */ + btdm8723.agc_table_en = false; + btdm8723.adc_back_off_on = true; + btdm8723.sw_dac_swing_on = false; + + /* fw mechanism */ + btdm8723.ps_tdma_on = true; + if ((bt_rssi_state == BT_RSSI_STATE_HIGH) || + (bt_rssi_state == BT_RSSI_STATE_STAY_HIGH)) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi rssi high\n"); + if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0x5; + btdm8723.ps_tdma_byte[2] = 0x5; + btdm8723.ps_tdma_byte[3] = 0x81; + btdm8723.ps_tdma_byte[4] = 0x80; + } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xa; + btdm8723.ps_tdma_byte[2] = 0xa; + btdm8723.ps_tdma_byte[3] = 0x81; + btdm8723.ps_tdma_byte[4] = 0x80; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters < 1200\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xf; + btdm8723.ps_tdma_byte[2] = 0xf; + btdm8723.ps_tdma_byte[3] = 0x81; + btdm8723.ps_tdma_byte[4] = 0x80; + } + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi rssi low\n"); + if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0x5; + btdm8723.ps_tdma_byte[2] = 0x5; + btdm8723.ps_tdma_byte[3] = 0x0; + btdm8723.ps_tdma_byte[4] = 0x80; + } else if (bt_tx_rx_cnt_lvl == + BT_TXRX_CNT_LEVEL_1) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xa; + btdm8723.ps_tdma_byte[2] = 0xa; + btdm8723.ps_tdma_byte[3] = 0x0; + btdm8723.ps_tdma_byte[4] = 0x80; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters < 1200\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xf; + btdm8723.ps_tdma_byte[2] = 0xf; + btdm8723.ps_tdma_byte[3] = 0x0; + btdm8723.ps_tdma_byte[4] = 0x80; + } + } + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "HT20 or Legacy\n"); + bt_rssi_state = + rtl8723e_dm_bt_check_coex_rssi_state(hw, 2, 47, 0); + bt_rssi_state1 = + rtl8723e_dm_bt_check_coex_rssi_state1(hw, 2, 27, 0); + + /* coex table */ + btdm8723.val_0x6c0 = 0x55555555; + btdm8723.val_0x6c8 = 0xffff; + btdm8723.val_0x6cc = 0x3; + + /* sw mechanism */ + if ((bt_rssi_state == BT_RSSI_STATE_HIGH) || + (bt_rssi_state == BT_RSSI_STATE_STAY_HIGH)) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi rssi high\n"); + btdm8723.agc_table_en = true; + btdm8723.adc_back_off_on = true; + btdm8723.sw_dac_swing_on = false; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi rssi low\n"); + btdm8723.agc_table_en = false; + btdm8723.adc_back_off_on = false; + btdm8723.sw_dac_swing_on = false; + } + + /* fw mechanism */ + btdm8723.ps_tdma_on = true; + if ((bt_rssi_state1 == BT_RSSI_STATE_HIGH) || + (bt_rssi_state1 == BT_RSSI_STATE_STAY_HIGH)) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi rssi-1 high\n"); + /* only rssi high we need to do this, */ + /* when rssi low, the value will modified by fw */ + rtl_write_byte(rtlpriv, 0x883, 0x40); + if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0x5; + btdm8723.ps_tdma_byte[2] = 0x5; + btdm8723.ps_tdma_byte[3] = 0x81; + btdm8723.ps_tdma_byte[4] = 0x80; + } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xa; + btdm8723.ps_tdma_byte[2] = 0xa; + btdm8723.ps_tdma_byte[3] = 0x81; + btdm8723.ps_tdma_byte[4] = 0x80; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters < 1200\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xf; + btdm8723.ps_tdma_byte[2] = 0xf; + btdm8723.ps_tdma_byte[3] = 0x81; + btdm8723.ps_tdma_byte[4] = 0x80; + } + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Wifi rssi-1 low\n"); + if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0x5; + btdm8723.ps_tdma_byte[2] = 0x5; + btdm8723.ps_tdma_byte[3] = 0x0; + btdm8723.ps_tdma_byte[4] = 0x80; + } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xa; + btdm8723.ps_tdma_byte[2] = 0xa; + btdm8723.ps_tdma_byte[3] = 0x0; + btdm8723.ps_tdma_byte[4] = 0x80; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT TxRx Counters < 1200\n"); + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0xf; + btdm8723.ps_tdma_byte[2] = 0xf; + btdm8723.ps_tdma_byte[3] = 0x0; + btdm8723.ps_tdma_byte[4] = 0x80; + } + } + } + + if (rtl8723e_dm_bt_need_to_dec_bt_pwr(hw)) + btdm8723.dec_bt_pwr = true; + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT btInqPageStartTime = 0x%x, btTxRxCntLvl = %d\n", + hal_coex_8723.bt_inq_page_start_time, bt_tx_rx_cnt_lvl); + + if ((hal_coex_8723.bt_inq_page_start_time) || + (BT_TXRX_CNT_LEVEL_3 == bt_tx_rx_cnt_lvl)) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], Set BT inquiry / page scan 0x3a setting\n"); + btdm8723.ps_tdma_on = true; + btdm8723.ps_tdma_byte[0] = 0xa3; + btdm8723.ps_tdma_byte[1] = 0x5; + btdm8723.ps_tdma_byte[2] = 0x5; + btdm8723.ps_tdma_byte[3] = 0x83; + btdm8723.ps_tdma_byte[4] = 0x80; + } + + if (rtl8723e_dm_bt_is_coexist_state_changed(hw)) + rtl8723e_dm_bt_set_bt_dm(hw, &btdm8723); + +} + +static void rtl8723e_dm_bt_inq_page_monitor(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 cur_time; + + cur_time = jiffies; + if (hal_coex_8723.c2h_bt_inquiry_page) { + /* bt inquiry or page is started. */ + if (hal_coex_8723.bt_inq_page_start_time == 0) { + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_BT_INQ_PAGE; + hal_coex_8723.bt_inq_page_start_time = cur_time; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT Inquiry/page is started at time : 0x%x\n", + hal_coex_8723.bt_inq_page_start_time); + } + } + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT Inquiry/page started time : 0x%x, cur_time : 0x%x\n", + hal_coex_8723.bt_inq_page_start_time, cur_time); + + if (hal_coex_8723.bt_inq_page_start_time) { + if ((((long)cur_time - + (long)hal_coex_8723.bt_inq_page_start_time) / HZ) + >= 10) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BT Inquiry/page >= 10sec!!!"); + hal_coex_8723.bt_inq_page_start_time = 0; + rtlpriv->btcoexist.cstate &= + ~BT_COEX_STATE_BT_INQ_PAGE; + } + } +} + +static void rtl8723e_dm_bt_reset_action_profile_state(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->btcoexist.cstate &= ~ + (BT_COEX_STATE_PROFILE_HID | BT_COEX_STATE_PROFILE_A2DP| + BT_COEX_STATE_PROFILE_PAN | BT_COEX_STATE_PROFILE_SCO); + + rtlpriv->btcoexist.cstate &= ~ + (BT_COEX_STATE_BTINFO_COMMON | + BT_COEX_STATE_BTINFO_B_HID_SCOESCO| + BT_COEX_STATE_BTINFO_B_FTP_A2DP); +} + +static void _rtl8723e_dm_bt_coexist_2_ant(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_retry_cnt; + u8 bt_info_original; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex] Get bt info by fw!!\n"); + + _rtl8723_dm_bt_check_wifi_state(hw); + + if (hal_coex_8723.c2h_bt_info_req_sent) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex] c2h for bt_info not rcvd yet!!\n"); + } + + bt_retry_cnt = hal_coex_8723.bt_retry_cnt; + bt_info_original = hal_coex_8723.c2h_bt_info_original; + + /* when bt inquiry or page scan, we have to set h2c 0x25 */ + /* ignore wlanact for continuous 4x2secs */ + rtl8723e_dm_bt_inq_page_monitor(hw); + rtl8723e_dm_bt_reset_action_profile_state(hw); + + if (rtl8723e_dm_bt_is_2_ant_common_action(hw)) { + rtlpriv->btcoexist.bt_profile_case = BT_COEX_MECH_COMMON; + rtlpriv->btcoexist.bt_profile_action = BT_COEX_MECH_COMMON; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Action 2-Ant common.\n"); + } else { + if ((bt_info_original & BTINFO_B_HID) || + (bt_info_original & BTINFO_B_SCO_BUSY) || + (bt_info_original & BTINFO_B_SCO_ESCO)) { + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_BTINFO_B_HID_SCOESCO; + rtlpriv->btcoexist.bt_profile_case = + BT_COEX_MECH_HID_SCO_ESCO; + rtlpriv->btcoexist.bt_profile_action = + BT_COEX_MECH_HID_SCO_ESCO; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BTInfo: bHid|bSCOBusy|bSCOeSCO\n"); + rtl8723e_dm_bt_2_ant_hid_sco_esco(hw); + } else if ((bt_info_original & BTINFO_B_FTP) || + (bt_info_original & BTINFO_B_A2DP)) { + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_BTINFO_B_FTP_A2DP; + rtlpriv->btcoexist.bt_profile_case = + BT_COEX_MECH_FTP_A2DP; + rtlpriv->btcoexist.bt_profile_action = + BT_COEX_MECH_FTP_A2DP; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "BTInfo: bFTP|bA2DP\n"); + rtl8723e_dm_bt_2_ant_ftp_a2dp(hw); + } else { + rtlpriv->btcoexist.cstate |= + BT_COEX_STATE_BTINFO_B_HID_SCOESCO; + rtlpriv->btcoexist.bt_profile_case = + BT_COEX_MECH_NONE; + rtlpriv->btcoexist.bt_profile_action = + BT_COEX_MECH_NONE; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], BTInfo: undefined case!!!!\n"); + rtl8723e_dm_bt_2_ant_hid_sco_esco(hw); + } + } +} + +static void _rtl8723e_dm_bt_coexist_1_ant(struct ieee80211_hw *hw) +{ + return; +} + +void rtl8723e_dm_bt_hw_coex_all_off_8723a(struct ieee80211_hw *hw) +{ + rtl8723e_dm_bt_set_coex_table(hw, 0x5a5aaaaa, 0xcc, 0x3); + rtl8723e_dm_bt_set_hw_pta_mode(hw, true); +} + +void rtl8723e_dm_bt_fw_coex_all_off_8723a(struct ieee80211_hw *hw) +{ + rtl8723e_dm_bt_set_fw_ignore_wlan_act(hw, false); + rtl8723e_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0); + rtl8723e_dm_bt_set_fw_2_ant_hid(hw, false, false); + rtl8723e_dm_bt_set_fw_tra_tdma_ctrl(hw, false, TDMA_2ANT, + TDMA_NAV_OFF); + rtl8723e_dm_bt_set_fw_tdma_ctrl(hw, false, TDMA_2ANT, TDMA_NAV_OFF, + TDMA_DAC_SWING_OFF); + rtl8723e_dm_bt_set_fw_dac_swing_level(hw, 0); + rtl8723e_dm_bt_set_fw_bt_hid_info(hw, false); + rtl8723e_dm_bt_set_fw_bt_retry_index(hw, 2); + rtl8723e_dm_bt_set_fw_wlan_act(hw, 0x10, 0x10); + rtl8723e_dm_bt_set_fw_dec_bt_pwr(hw, false); +} + +void rtl8723e_dm_bt_sw_coex_all_off_8723a(struct ieee80211_hw *hw) +{ + rtl8723e_dm_bt_agc_table(hw, BT_AGCTABLE_OFF); + rtl8723e_dm_bt_bb_back_off_level(hw, BT_BB_BACKOFF_OFF); + rtl8723e_dm_bt_reject_ap_aggregated_packet(hw, false); + + dm_bt_set_sw_penalty_tx_rate_adapt(hw, BT_TX_RATE_ADAPTIVE_NORMAL); + rtl8723e_dm_bt_set_sw_rf_rx_lpf_corner(hw, BT_RF_RX_LPF_CORNER_RESUME); + rtl8723e_dm_bt_set_sw_full_time_dac_swing(hw, false, 0xc0); +} + +static void rtl8723e_dm_bt_query_bt_information(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 h2c_parameter[1] = {0}; + + hal_coex_8723.c2h_bt_info_req_sent = true; + + h2c_parameter[0] |= BIT(0); + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "Query Bt information, write 0x38=0x%x\n", h2c_parameter[0]); + + rtl8723e_fill_h2c_cmd(hw, 0x38, 1, h2c_parameter); +} + +static void rtl8723e_dm_bt_bt_hw_counters_monitor(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 reg_hp_tx_rx, reg_lp_tx_rx, u32_tmp; + u32 reg_hp_tx = 0, reg_hp_rx = 0, reg_lp_tx = 0, reg_lp_rx = 0; + + reg_hp_tx_rx = REG_HIGH_PRIORITY_TXRX; + reg_lp_tx_rx = REG_LOW_PRIORITY_TXRX; + + u32_tmp = rtl_read_dword(rtlpriv, reg_hp_tx_rx); + reg_hp_tx = u32_tmp & MASKLWORD; + reg_hp_rx = (u32_tmp & MASKHWORD)>>16; + + u32_tmp = rtl_read_dword(rtlpriv, reg_lp_tx_rx); + reg_lp_tx = u32_tmp & MASKLWORD; + reg_lp_rx = (u32_tmp & MASKHWORD)>>16; + + if (rtlpriv->btcoexist.lps_counter > 1) { + reg_hp_tx %= rtlpriv->btcoexist.lps_counter; + reg_hp_rx %= rtlpriv->btcoexist.lps_counter; + reg_lp_tx %= rtlpriv->btcoexist.lps_counter; + reg_lp_rx %= rtlpriv->btcoexist.lps_counter; + } + + hal_coex_8723.high_priority_tx = reg_hp_tx; + hal_coex_8723.high_priority_rx = reg_hp_rx; + hal_coex_8723.low_priority_tx = reg_lp_tx; + hal_coex_8723.low_priority_rx = reg_lp_rx; + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "High Priority Tx/Rx (reg 0x%x)=%x(%d)/%x(%d)\n", + reg_hp_tx_rx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "Low Priority Tx/Rx (reg 0x%x)=%x(%d)/%x(%d)\n", + reg_lp_tx_rx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); + rtlpriv->btcoexist.lps_counter = 0; + /* rtl_write_byte(rtlpriv, 0x76e, 0xc); */ +} + +static void rtl8723e_dm_bt_bt_enable_disable_check(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool bt_alife = true; + + if (hal_coex_8723.high_priority_tx == 0 && + hal_coex_8723.high_priority_rx == 0 && + hal_coex_8723.low_priority_tx == 0 && + hal_coex_8723.low_priority_rx == 0) { + bt_alife = false; + } + if (hal_coex_8723.high_priority_tx == 0xeaea && + hal_coex_8723.high_priority_rx == 0xeaea && + hal_coex_8723.low_priority_tx == 0xeaea && + hal_coex_8723.low_priority_rx == 0xeaea) { + bt_alife = false; + } + if (hal_coex_8723.high_priority_tx == 0xffff && + hal_coex_8723.high_priority_rx == 0xffff && + hal_coex_8723.low_priority_tx == 0xffff && + hal_coex_8723.low_priority_rx == 0xffff) { + bt_alife = false; + } + if (bt_alife) { + rtlpriv->btcoexist.bt_active_zero_cnt = 0; + rtlpriv->btcoexist.cur_bt_disabled = false; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "8723A BT is enabled !!\n"); + } else { + rtlpriv->btcoexist.bt_active_zero_cnt++; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "8723A bt all counters=0, %d times!!\n", + rtlpriv->btcoexist.bt_active_zero_cnt); + if (rtlpriv->btcoexist.bt_active_zero_cnt >= 2) { + rtlpriv->btcoexist.cur_bt_disabled = true; + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "8723A BT is disabled !!\n"); + } + } + if (rtlpriv->btcoexist.pre_bt_disabled != + rtlpriv->btcoexist.cur_bt_disabled) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, + DBG_TRACE, "8723A BT is from %s to %s!!\n", + (rtlpriv->btcoexist.pre_bt_disabled ? + "disabled" : "enabled"), + (rtlpriv->btcoexist.cur_bt_disabled ? + "disabled" : "enabled")); + rtlpriv->btcoexist.pre_bt_disabled + = rtlpriv->btcoexist.cur_bt_disabled; + } +} + + +void rtl8723e_dm_bt_coexist_8723(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl8723e_dm_bt_query_bt_information(hw); + rtl8723e_dm_bt_bt_hw_counters_monitor(hw); + rtl8723e_dm_bt_bt_enable_disable_check(hw); + + if (rtlpriv->btcoexist.bt_ant_num == ANT_X2) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], 2 Ant mechanism\n"); + _rtl8723e_dm_bt_coexist_2_ant(hw); + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "[BTCoex], 1 Ant mechanism\n"); + _rtl8723e_dm_bt_coexist_1_ant(hw); + } + + if (!rtl8723e_dm_bt_is_same_coexist_state(hw)) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTCoex], Coexist State[bitMap] change from 0x%x%8x to 0x%x%8x\n", + rtlpriv->btcoexist.previous_state_h, + rtlpriv->btcoexist.previous_state, + rtlpriv->btcoexist.cstate_h, + rtlpriv->btcoexist.cstate); + rtlpriv->btcoexist.previous_state + = rtlpriv->btcoexist.cstate; + rtlpriv->btcoexist.previous_state_h + = rtlpriv->btcoexist.cstate_h; + } +} + +static void rtl8723e_dm_bt_parse_bt_info(struct ieee80211_hw *hw, + u8 *tmp_buf, u8 len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_info; + u8 i; + + hal_coex_8723.c2h_bt_info_req_sent = false; + hal_coex_8723.bt_retry_cnt = 0; + for (i = 0; i < len; i++) { + if (i == 0) + hal_coex_8723.c2h_bt_info_original = tmp_buf[i]; + else if (i == 1) + hal_coex_8723.bt_retry_cnt = tmp_buf[i]; + if (i == len-1) + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "0x%2x]", tmp_buf[i]); + else + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "0x%2x, ", tmp_buf[i]); + + } + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "BT info bt_info (Data)= 0x%x\n", + hal_coex_8723.c2h_bt_info_original); + bt_info = hal_coex_8723.c2h_bt_info_original; + + if (bt_info & BIT(2)) + hal_coex_8723.c2h_bt_inquiry_page = true; + else + hal_coex_8723.c2h_bt_inquiry_page = false; + + + if (bt_info & BTINFO_B_CONNECTION) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTC2H], BTInfo: bConnect=true\n"); + rtlpriv->btcoexist.bt_busy = true; + rtlpriv->btcoexist.cstate &= ~BT_COEX_STATE_BT_IDLE; + } else { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, + "[BTC2H], BTInfo: bConnect=false\n"); + rtlpriv->btcoexist.bt_busy = false; + rtlpriv->btcoexist.cstate |= BT_COEX_STATE_BT_IDLE; + } +} +void rtl_8723e_c2h_command_handle(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct c2h_evt_hdr c2h_event; + u8 *ptmp_buf = NULL; + u8 index = 0; + u8 u1b_tmp = 0; + memset(&c2h_event, 0, sizeof(c2h_event)); + u1b_tmp = rtl_read_byte(rtlpriv, REG_C2HEVT_MSG_NORMAL); + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "&&&&&&: REG_C2HEVT_MSG_NORMAL is 0x%x\n", u1b_tmp); + c2h_event.cmd_id = u1b_tmp & 0xF; + c2h_event.cmd_len = (u1b_tmp & 0xF0) >> 4; + c2h_event.cmd_seq = rtl_read_byte(rtlpriv, REG_C2HEVT_MSG_NORMAL + 1); + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "cmd_id: %d, cmd_len: %d, cmd_seq: %d\n", + c2h_event.cmd_id , c2h_event.cmd_len, c2h_event.cmd_seq); + u1b_tmp = rtl_read_byte(rtlpriv, 0x01AF); + if (u1b_tmp == C2H_EVT_HOST_CLOSE) { + return; + } else if (u1b_tmp != C2H_EVT_FW_CLOSE) { + rtl_write_byte(rtlpriv, 0x1AF, 0x00); + return; + } + ptmp_buf = kzalloc(c2h_event.cmd_len, GFP_KERNEL); + if (ptmp_buf == NULL) { + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "malloc cmd buf failed\n"); + return; + } + + /* Read the content */ + for (index = 0; index < c2h_event.cmd_len; index++) + ptmp_buf[index] = rtl_read_byte(rtlpriv, + REG_C2HEVT_MSG_NORMAL + 2 + index); + + + switch (c2h_event.cmd_id) { + case C2H_BT_RSSI: + break; + + case C2H_BT_OP_MODE: + break; + + case BT_INFO: + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "BT info Byte[0] (ID) is 0x%x\n", + c2h_event.cmd_id); + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "BT info Byte[1] (Seq) is 0x%x\n", + c2h_event.cmd_seq); + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "BT info Byte[2] (Data)= 0x%x\n", ptmp_buf[0]); + + rtl8723e_dm_bt_parse_bt_info(hw, ptmp_buf, c2h_event.cmd_len); + + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_periodical(rtlpriv); + + break; + default: + break; + } + kfree(ptmp_buf); + + rtl_write_byte(rtlpriv, 0x01AF, C2H_EVT_HOST_CLOSE); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h new file mode 100644 index 000000000000..3723d7476717 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_btc.h @@ -0,0 +1,159 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_HAL_BTC_H__ +#define __RTL8723E_HAL_BTC_H__ + +#include "../wifi.h" +#include "btc.h" +#include "hal_bt_coexist.h" + +#define BT_TXRX_CNT_THRES_1 1200 +#define BT_TXRX_CNT_THRES_2 1400 +#define BT_TXRX_CNT_THRES_3 3000 +/* < 1200 */ +#define BT_TXRX_CNT_LEVEL_0 0 +/* >= 1200 && < 1400 */ +#define BT_TXRX_CNT_LEVEL_1 1 +/* >= 1400 */ +#define BT_TXRX_CNT_LEVEL_2 2 +#define BT_TXRX_CNT_LEVEL_3 3 + +#define BT_COEX_DISABLE 0 +#define BT_Q_PKT_OFF 0 +#define BT_Q_PKT_ON 1 + +#define BT_TX_PWR_OFF 0 +#define BT_TX_PWR_ON 1 + +/* TDMA mode definition */ +#define TDMA_2ANT 0 +#define TDMA_1ANT 1 +#define TDMA_NAV_OFF 0 +#define TDMA_NAV_ON 1 +#define TDMA_DAC_SWING_OFF 0 +#define TDMA_DAC_SWING_ON 1 + +/* PTA mode related definition */ +#define BT_PTA_MODE_OFF 0 +#define BT_PTA_MODE_ON 1 + +/* Penalty Tx Rate Adaptive */ +#define BT_TX_RATE_ADAPTIVE_NORMAL 0 +#define BT_TX_RATE_ADAPTIVE_LOW_PENALTY 1 + +/* RF Corner */ +#define BT_RF_RX_LPF_CORNER_RESUME 0 +#define BT_RF_RX_LPF_CORNER_SHRINK 1 + +#define C2H_EVT_HOST_CLOSE 0x00 +#define C2H_EVT_FW_CLOSE 0xFF + +enum bt_traffic_mode { + BT_MOTOR_EXT_BE = 0x00, + BT_MOTOR_EXT_GUL = 0x01, + BT_MOTOR_EXT_GUB = 0x02, + BT_MOTOR_EXT_GULB = 0x03 +}; + +enum bt_traffic_mode_profile { + BT_PROFILE_NONE, + BT_PROFILE_A2DP, + BT_PROFILE_PAN, + BT_PROFILE_HID, + BT_PROFILE_SCO +}; + +/* +enum hci_ext_bt_operation { + HCI_BT_OP_NONE = 0x0, + HCI_BT_OP_INQUIRE_START = 0x1, + HCI_BT_OP_INQUIRE_FINISH = 0x2, + HCI_BT_OP_PAGING_START = 0x3, + HCI_BT_OP_PAGING_SUCCESS = 0x4, + HCI_BT_OP_PAGING_UNSUCCESS = 0x5, + HCI_BT_OP_PAIRING_START = 0x6, + HCI_BT_OP_PAIRING_FINISH = 0x7, + HCI_BT_OP_BT_DEV_ENABLE = 0x8, + HCI_BT_OP_BT_DEV_DISABLE = 0x9, + HCI_BT_OP_MAX, +}; +*/ + +enum bt_spec { + BT_SPEC_1_0_b = 0x00, + BT_SPEC_1_1 = 0x01, + BT_SPEC_1_2 = 0x02, + BT_SPEC_2_0_EDR = 0x03, + BT_SPEC_2_1_EDR = 0x04, + BT_SPEC_3_0_HS = 0x05, + BT_SPEC_4_0 = 0x06 +}; + +struct c2h_evt_hdr { + u8 cmd_id; + u8 cmd_len; + u8 cmd_seq; +}; + +enum bt_state { + BT_INFO_STATE_DISABLED = 0, + BT_INFO_STATE_NO_CONNECTION = 1, + BT_INFO_STATE_CONNECT_IDLE = 2, + BT_INFO_STATE_INQ_OR_PAG = 3, + BT_INFO_STATE_ACL_ONLY_BUSY = 4, + BT_INFO_STATE_SCO_ONLY_BUSY = 5, + BT_INFO_STATE_ACL_SCO_BUSY = 6, + BT_INFO_STATE_HID_BUSY = 7, + BT_INFO_STATE_HID_SCO_BUSY = 8, + BT_INFO_STATE_MAX = 7 +}; + +enum rtl8723e_c2h_evt { + C2H_DBG = 0, + C2H_TSF = 1, + C2H_AP_RPT_RSP = 2, + /* The FW notify the report of the specific tx packet. */ + C2H_CCX_TX_RPT = 3, + C2H_BT_RSSI = 4, + C2H_BT_OP_MODE = 5, + C2H_HW_INFO_EXCH = 10, + C2H_C2H_H2C_TEST = 11, + BT_INFO = 12, + MAX_C2HEVENT +}; + +void rtl8723e_dm_bt_fw_coex_all_off_8723a(struct ieee80211_hw *hw); +void rtl8723e_dm_bt_sw_coex_all_off_8723a(struct ieee80211_hw *hw); +void rtl8723e_dm_bt_hw_coex_all_off_8723a(struct ieee80211_hw *hw); +void rtl8723e_dm_bt_coexist_8723(struct ieee80211_hw *hw); +void rtl8723e_dm_bt_set_bt_dm(struct ieee80211_hw *hw, + struct btdm_8723 *p_btdm); +void rtl_8723e_c2h_command_handle(struct ieee80211_hw *hw); +void rtl_8723e_bt_wifi_media_status_notify(struct ieee80211_hw *hw, + bool mstatus); +void rtl8723e_dm_bt_turn_off_bt_coexist_before_enter_lps( + struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c new file mode 100644 index 000000000000..a4b7eac6856f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c @@ -0,0 +1,2482 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../regd.h" +#include "../cam.h" +#include "../ps.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "../rtl8723com/phy_common.h" +#include "dm.h" +#include "../rtl8723com/dm_common.h" +#include "fw.h" +#include "../rtl8723com/fw_common.h" +#include "led.h" +#include "hw.h" +#include "../pwrseqcmd.h" +#include "pwrseq.h" +#include "btc.h" + +#define LLT_CONFIG 5 + +static void _rtl8723e_set_bcn_ctrl_reg(struct ieee80211_hw *hw, + u8 set_bits, u8 clear_bits) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpci->reg_bcn_ctrl_val |= set_bits; + rtlpci->reg_bcn_ctrl_val &= ~clear_bits; + + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); +} + +static void _rtl8723e_stop_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl8723e_resume_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte |= BIT(1); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl8723e_enable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl8723e_set_bcn_ctrl_reg(hw, 0, BIT(1)); +} + +static void _rtl8723e_disable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl8723e_set_bcn_ctrl_reg(hw, BIT(1), 0); +} + +void rtl8723e_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + switch (variable) { + case HW_VAR_RCR: + *((u32 *)(val)) = rtlpci->receive_config; + break; + case HW_VAR_RF_STATE: + *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; + break; + case HW_VAR_FWLPS_RF_ON:{ + enum rf_pwrstate rfstate; + u32 val_rcr; + + rtlpriv->cfg->ops->get_hw_reg(hw, + HW_VAR_RF_STATE, + (u8 *)(&rfstate)); + if (rfstate == ERFOFF) { + *((bool *)(val)) = true; + } else { + val_rcr = rtl_read_dword(rtlpriv, REG_RCR); + val_rcr &= 0x00070000; + if (val_rcr) + *((bool *)(val)) = false; + else + *((bool *)(val)) = true; + } + break; + } + case HW_VAR_FW_PSMODE_STATUS: + *((bool *)(val)) = ppsc->fw_current_inpsmode; + break; + case HW_VAR_CORRECT_TSF:{ + u64 tsf; + u32 *ptsf_low = (u32 *)&tsf; + u32 *ptsf_high = ((u32 *)&tsf) + 1; + + *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); + *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + *((u64 *)(val)) = tsf; + + break; + } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } +} + +void rtl8723e_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 idx; + + switch (variable) { + case HW_VAR_ETHER_ADDR:{ + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_MACID + idx), + val[idx]); + } + break; + } + case HW_VAR_BASIC_RATE:{ + u16 b_rate_cfg = ((u16 *)val)[0]; + u8 rate_index = 0; + + b_rate_cfg = b_rate_cfg & 0x15f; + b_rate_cfg |= 0x01; + rtl_write_byte(rtlpriv, REG_RRSR, b_rate_cfg & 0xff); + rtl_write_byte(rtlpriv, REG_RRSR + 1, + (b_rate_cfg >> 8) & 0xff); + while (b_rate_cfg > 0x1) { + b_rate_cfg = (b_rate_cfg >> 1); + rate_index++; + } + rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, + rate_index); + break; + } + case HW_VAR_BSSID:{ + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_BSSID + idx), + val[idx]); + } + break; + } + case HW_VAR_SIFS:{ + rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); + rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); + + rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); + rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); + + if (!mac->ht_enable) + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, + 0x0e0e); + else + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, + *((u16 *)val)); + break; + } + case HW_VAR_SLOT_TIME:{ + u8 e_aci; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "HW_VAR_SLOT_TIME %x\n", val[0]); + + rtl_write_byte(rtlpriv, REG_SLOT, val[0]); + + for (e_aci = 0; e_aci < AC_MAX; e_aci++) { + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AC_PARAM, + (u8 *)(&e_aci)); + } + break; + } + case HW_VAR_ACK_PREAMBLE:{ + u8 reg_tmp; + u8 short_preamble = (bool)(*(u8 *)val); + + reg_tmp = (mac->cur_40_prime_sc) << 5; + if (short_preamble) + reg_tmp |= 0x80; + + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp); + break; + } + case HW_VAR_AMPDU_MIN_SPACE:{ + u8 min_spacing_to_set; + u8 sec_min_space; + + min_spacing_to_set = *((u8 *)val); + if (min_spacing_to_set <= 7) { + sec_min_space = 0; + + if (min_spacing_to_set < sec_min_space) + min_spacing_to_set = sec_min_space; + + mac->min_space_cfg = ((mac->min_space_cfg & + 0xf8) | + min_spacing_to_set); + + *val = min_spacing_to_set; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", + mac->min_space_cfg); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + } + break; + } + case HW_VAR_SHORTGI_DENSITY:{ + u8 density_to_set; + + density_to_set = *((u8 *)val); + mac->min_space_cfg |= (density_to_set << 3); + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_SHORTGI_DENSITY: %#x\n", + mac->min_space_cfg); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + + break; + } + case HW_VAR_AMPDU_FACTOR:{ + u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; + u8 regtoset_bt[4] = {0x31, 0x74, 0x42, 0x97}; + u8 factor_toset; + u8 *p_regtoset = NULL; + u8 index = 0; + + if ((rtlpriv->btcoexist.bt_coexistence) && + (rtlpriv->btcoexist.bt_coexist_type == + BT_CSR_BC4)) + p_regtoset = regtoset_bt; + else + p_regtoset = regtoset_normal; + + factor_toset = *((u8 *)val); + if (factor_toset <= 3) { + factor_toset = (1 << (factor_toset + 2)); + if (factor_toset > 0xf) + factor_toset = 0xf; + + for (index = 0; index < 4; index++) { + if ((p_regtoset[index] & 0xf0) > + (factor_toset << 4)) + p_regtoset[index] = + (p_regtoset[index] & 0x0f) | + (factor_toset << 4); + + if ((p_regtoset[index] & 0x0f) > + factor_toset) + p_regtoset[index] = + (p_regtoset[index] & 0xf0) | + (factor_toset); + + rtl_write_byte(rtlpriv, + (REG_AGGLEN_LMT + index), + p_regtoset[index]); + } + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_FACTOR: %#x\n", + factor_toset); + } + break; + } + case HW_VAR_AC_PARAM:{ + u8 e_aci = *((u8 *)val); + + rtl8723_dm_init_edca_turbo(hw); + + if (rtlpci->acm_method != EACMWAY2_SW) + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_ACM_CTRL, + (u8 *)(&e_aci)); + break; + } + case HW_VAR_ACM_CTRL:{ + u8 e_aci = *((u8 *)val); + union aci_aifsn *p_aci_aifsn = + (union aci_aifsn *)(&mac->ac[0].aifs); + u8 acm = p_aci_aifsn->f.acm; + u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); + + acm_ctrl = + acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); + + if (acm) { + switch (e_aci) { + case AC0_BE: + acm_ctrl |= ACMHW_BEQEN; + break; + case AC2_VI: + acm_ctrl |= ACMHW_VIQEN; + break; + case AC3_VO: + acm_ctrl |= ACMHW_VOQEN; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", + acm); + break; + } + } else { + switch (e_aci) { + case AC0_BE: + acm_ctrl &= (~ACMHW_BEQEN); + break; + case AC2_VI: + acm_ctrl &= (~ACMHW_VIQEN); + break; + case AC3_VO: + acm_ctrl &= (~ACMHW_VOQEN); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + } + + RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, + "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", + acm_ctrl); + rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); + break; + } + case HW_VAR_RCR:{ + rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); + rtlpci->receive_config = ((u32 *)(val))[0]; + break; + } + case HW_VAR_RETRY_LIMIT:{ + u8 retry_limit = ((u8 *)(val))[0]; + + rtl_write_word(rtlpriv, REG_RL, + retry_limit << RETRY_LIMIT_SHORT_SHIFT | + retry_limit << RETRY_LIMIT_LONG_SHIFT); + break; + } + case HW_VAR_DUAL_TSF_RST: + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); + break; + case HW_VAR_EFUSE_BYTES: + rtlefuse->efuse_usedbytes = *((u16 *)val); + break; + case HW_VAR_EFUSE_USAGE: + rtlefuse->efuse_usedpercentage = *((u8 *)val); + break; + case HW_VAR_IO_CMD: + rtl8723e_phy_set_io_cmd(hw, (*(enum io_type *)val)); + break; + case HW_VAR_WPA_CONFIG: + rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); + break; + case HW_VAR_SET_RPWM:{ + u8 rpwm_val; + + rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); + udelay(1); + + if (rpwm_val & BIT(7)) { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, + (*(u8 *)val)); + } else { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, + ((*(u8 *)val) | BIT(7))); + } + + break; + } + case HW_VAR_H2C_FW_PWRMODE:{ + u8 psmode = (*(u8 *)val); + + if (psmode != FW_PS_ACTIVE_MODE) + rtl8723e_dm_rf_saving(hw, true); + + rtl8723e_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); + break; + } + case HW_VAR_FW_PSMODE_STATUS: + ppsc->fw_current_inpsmode = *((bool *)val); + break; + case HW_VAR_H2C_FW_JOINBSSRPT:{ + u8 mstatus = (*(u8 *)val); + u8 tmp_regcr, tmp_reg422; + bool b_recover = false; + + if (mstatus == RT_MEDIA_CONNECT) { + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, + NULL); + + tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, + (tmp_regcr | BIT(0))); + + _rtl8723e_set_bcn_ctrl_reg(hw, 0, BIT(3)); + _rtl8723e_set_bcn_ctrl_reg(hw, BIT(4), 0); + + tmp_reg422 = + rtl_read_byte(rtlpriv, + REG_FWHW_TXQ_CTRL + 2); + if (tmp_reg422 & BIT(6)) + b_recover = true; + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, + tmp_reg422 & (~BIT(6))); + + rtl8723e_set_fw_rsvdpagepkt(hw, 0); + + _rtl8723e_set_bcn_ctrl_reg(hw, BIT(3), 0); + _rtl8723e_set_bcn_ctrl_reg(hw, 0, BIT(4)); + + if (b_recover) { + rtl_write_byte(rtlpriv, + REG_FWHW_TXQ_CTRL + 2, + tmp_reg422); + } + + rtl_write_byte(rtlpriv, REG_CR + 1, + (tmp_regcr & ~(BIT(0)))); + } + rtl8723e_set_fw_joinbss_report_cmd(hw, (*(u8 *)val)); + + break; + } + case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:{ + rtl8723e_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); + break; + } + case HW_VAR_AID:{ + u16 u2btmp; + + u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); + u2btmp &= 0xC000; + rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, + (u2btmp | mac->assoc_id)); + + break; + } + case HW_VAR_CORRECT_TSF:{ + u8 btype_ibss = ((u8 *)(val))[0]; + + if (btype_ibss) + _rtl8723e_stop_tx_beacon(hw); + + _rtl8723e_set_bcn_ctrl_reg(hw, 0, BIT(3)); + + rtl_write_dword(rtlpriv, REG_TSFTR, + (u32)(mac->tsf & 0xffffffff)); + rtl_write_dword(rtlpriv, REG_TSFTR + 4, + (u32)((mac->tsf >> 32) & 0xffffffff)); + + _rtl8723e_set_bcn_ctrl_reg(hw, BIT(3), 0); + + if (btype_ibss) + _rtl8723e_resume_tx_beacon(hw); + + break; + } + case HW_VAR_FW_LPS_ACTION:{ + bool b_enter_fwlps = *((bool *)val); + u8 rpwm_val, fw_pwrmode; + bool fw_current_inps; + + if (b_enter_fwlps) { + rpwm_val = 0x02; /* RF off */ + fw_current_inps = true; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&ppsc->fwctrl_psmode)); + + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + } else { + rpwm_val = 0x0C; /* RF on */ + fw_pwrmode = FW_PS_ACTIVE_MODE; + fw_current_inps = false; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&fw_pwrmode)); + + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + } + break; + } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } +} + +static bool _rtl8723e_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool status = true; + long count = 0; + u32 value = _LLT_INIT_ADDR(address) | + _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); + + rtl_write_dword(rtlpriv, REG_LLT_INIT, value); + + do { + value = rtl_read_dword(rtlpriv, REG_LLT_INIT); + if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) + break; + + if (count > POLLING_LLT_THRESHOLD) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to polling write LLT done at address %d!\n", + address); + status = false; + break; + } + } while (++count); + + return status; +} + +static bool _rtl8723e_llt_table_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + unsigned short i; + u8 txpktbuf_bndy; + u8 maxpage; + bool status; + u8 ubyte; + +#if LLT_CONFIG == 1 + maxpage = 255; + txpktbuf_bndy = 252; +#elif LLT_CONFIG == 2 + maxpage = 127; + txpktbuf_bndy = 124; +#elif LLT_CONFIG == 3 + maxpage = 255; + txpktbuf_bndy = 174; +#elif LLT_CONFIG == 4 + maxpage = 255; + txpktbuf_bndy = 246; +#elif LLT_CONFIG == 5 + maxpage = 255; + txpktbuf_bndy = 246; +#endif + + rtl_write_byte(rtlpriv, REG_CR, 0x8B); + +#if LLT_CONFIG == 1 + rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x1c); + rtl_write_dword(rtlpriv, REG_RQPN, 0x80a71c1c); +#elif LLT_CONFIG == 2 + rtl_write_dword(rtlpriv, REG_RQPN, 0x845B1010); +#elif LLT_CONFIG == 3 + rtl_write_dword(rtlpriv, REG_RQPN, 0x84838484); +#elif LLT_CONFIG == 4 + rtl_write_dword(rtlpriv, REG_RQPN, 0x80bd1c1c); +#elif LLT_CONFIG == 5 + rtl_write_word(rtlpriv, REG_RQPN_NPQ, 0x0000); + + rtl_write_dword(rtlpriv, REG_RQPN, 0x80ac1c29); + rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x03); +#endif + + rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x27FF0000 | txpktbuf_bndy)); + rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_PBP, 0x11); + rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); + + for (i = 0; i < (txpktbuf_bndy - 1); i++) { + status = _rtl8723e_llt_write(hw, i, i + 1); + if (true != status) + return status; + } + + status = _rtl8723e_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); + if (true != status) + return status; + + for (i = txpktbuf_bndy; i < maxpage; i++) { + status = _rtl8723e_llt_write(hw, i, (i + 1)); + if (true != status) + return status; + } + + status = _rtl8723e_llt_write(hw, maxpage, txpktbuf_bndy); + if (true != status) + return status; + + rtl_write_byte(rtlpriv, REG_CR, 0xff); + ubyte = rtl_read_byte(rtlpriv, REG_RQPN + 3); + rtl_write_byte(rtlpriv, REG_RQPN + 3, ubyte | BIT(7)); + + return true; +} + +static void _rtl8723e_gen_refresh_led_state(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_led *pled0 = &pcipriv->ledctl.sw_led0; + + if (rtlpriv->rtlhal.up_first_time) + return; + + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) + rtl8723e_sw_led_on(hw, pled0); + else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) + rtl8723e_sw_led_on(hw, pled0); + else + rtl8723e_sw_led_off(hw, pled0); +} + +static bool _rtl8712e_init_mac(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + unsigned char bytetmp; + unsigned short wordtmp; + u16 retry = 0; + u16 tmpu2b; + bool mac_func_enable; + + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); + bytetmp = rtl_read_byte(rtlpriv, REG_CR); + if (bytetmp == 0xFF) + mac_func_enable = true; + else + mac_func_enable = false; + + /* HW Power on sequence */ + if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, Rtl8723_NIC_ENABLE_FLOW)) + return false; + + bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2); + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+2, bytetmp | BIT(4)); + + /* eMAC time out function enable, 0x369[7]=1 */ + bytetmp = rtl_read_byte(rtlpriv, 0x369); + rtl_write_byte(rtlpriv, 0x369, bytetmp | BIT(7)); + + /* ePHY reg 0x1e bit[4]=1 using MDIO interface, + * we should do this before Enabling ASPM backdoor. + */ + do { + rtl_write_word(rtlpriv, 0x358, 0x5e); + udelay(100); + rtl_write_word(rtlpriv, 0x356, 0xc280); + rtl_write_word(rtlpriv, 0x354, 0xc290); + rtl_write_word(rtlpriv, 0x358, 0x3e); + udelay(100); + rtl_write_word(rtlpriv, 0x358, 0x5e); + udelay(100); + tmpu2b = rtl_read_word(rtlpriv, 0x356); + retry++; + } while (tmpu2b != 0xc290 && retry < 100); + + if (retry >= 100) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "InitMAC(): ePHY configure fail!!!\n"); + return false; + } + + rtl_write_word(rtlpriv, REG_CR, 0x2ff); + rtl_write_word(rtlpriv, REG_CR + 1, 0x06); + + if (!mac_func_enable) { + if (!_rtl8723e_llt_table_init(hw)) + return false; + } + + rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); + rtl_write_byte(rtlpriv, REG_HISRE, 0xff); + + rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x27ff); + + wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); + wordtmp &= 0xf; + wordtmp |= 0xF771; + rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); + + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xFFFF); + rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); + + rtl_write_byte(rtlpriv, 0x4d0, 0x0); + + rtl_write_dword(rtlpriv, REG_BCNQ_DESA, + ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_MGQ_DESA, + (u64) rtlpci->tx_ring[MGNT_QUEUE].dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VOQ_DESA, + (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VIQ_DESA, + (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BEQ_DESA, + (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BKQ_DESA, + (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_HQ_DESA, + (u64) rtlpci->tx_ring[HIGH_QUEUE].dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_RX_DESA, + (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma & + DMA_BIT_MASK(32)); + + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x74); + + rtl_write_dword(rtlpriv, REG_INT_MIG, 0); + + bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6)); + do { + retry++; + bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); + } while ((retry < 200) && (bytetmp & BIT(7))); + + _rtl8723e_gen_refresh_led_state(hw); + + rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); + + return true; +} + +static void _rtl8723e_hw_configure(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 reg_bw_opmode; + u32 reg_ratr, reg_prsr; + + reg_bw_opmode = BW_OPMODE_20MHZ; + reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | + RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + + rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8); + + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + + rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr); + + rtl_write_byte(rtlpriv, REG_SLOT, 0x09); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0); + + rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80); + + rtl_write_word(rtlpriv, REG_RL, 0x0707); + + rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802); + + rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); + + rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); + rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); + + if ((rtlpriv->btcoexist.bt_coexistence) && + (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4)) + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x97427431); + else + rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); + + rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); + + rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff); + + rtlpci->reg_bcn_ctrl_val = 0x1f; + rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); + + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + + rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); + rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); + + if ((rtlpriv->btcoexist.bt_coexistence) && + (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4)) { + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0402); + } else { + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); + } + + if ((rtlpriv->btcoexist.bt_coexistence) && + (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4)) + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); + else + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); + + rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); + + rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010); + rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010); + + rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010); + + rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010); + + rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff); + rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff); + + rtl_write_dword(rtlpriv, 0x394, 0x1); +} + +static void _rtl8723e_enable_aspm_back_door(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + rtl_write_byte(rtlpriv, 0x34b, 0x93); + rtl_write_word(rtlpriv, 0x350, 0x870c); + rtl_write_byte(rtlpriv, 0x352, 0x1); + + if (ppsc->support_backdoor) + rtl_write_byte(rtlpriv, 0x349, 0x1b); + else + rtl_write_byte(rtlpriv, 0x349, 0x03); + + rtl_write_word(rtlpriv, 0x350, 0x2718); + rtl_write_byte(rtlpriv, 0x352, 0x1); +} + +void rtl8723e_enable_hw_security_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 sec_reg_value; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", + rtlpriv->sec.pairwise_enc_algorithm, + rtlpriv->sec.group_enc_algorithm); + + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "not open hw encryption\n"); + return; + } + + sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; + + if (rtlpriv->sec.use_defaultkey) { + sec_reg_value |= SCR_TXUSEDK; + sec_reg_value |= SCR_RXUSEDK; + } + + sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); + + rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "The SECR-value %x\n", sec_reg_value); + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); + +} + +int rtl8723e_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + bool rtstatus = true; + int err; + u8 tmp_u1b; + unsigned long flags; + + rtlpriv->rtlhal.being_init_adapter = true; + /* As this function can take a very long time (up to 350 ms) + * and can be called with irqs disabled, reenable the irqs + * to let the other devices continue being serviced. + * + * It is safe doing so since our own interrupts will only be enabled + * in a subsequent step. + */ + local_save_flags(flags); + local_irq_enable(); + rtlhal->fw_ready = false; + + rtlpriv->intf_ops->disable_aspm(hw); + rtstatus = _rtl8712e_init_mac(hw); + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); + err = 1; + goto exit; + } + + err = rtl8723_download_fw(hw, false, FW_8723A_POLLING_TIMEOUT_COUNT); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW now..\n"); + err = 1; + goto exit; + } + rtlhal->fw_ready = true; + + rtlhal->last_hmeboxnum = 0; + rtl8723e_phy_mac_config(hw); + /* because last function modify RCR, so we update + * rcr var here, or TP will unstable for receive_config + * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx + * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 + */ + rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); + rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + + rtl8723e_phy_bb_config(hw); + rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; + rtl8723e_phy_rf_config(hw); + if (IS_VENDOR_UMC_A_CUT(rtlhal->version)) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00); + } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { + rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE); + rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31); + rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425); + rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201); + } + rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); + _rtl8723e_hw_configure(hw); + rtl_cam_reset_all_entry(hw); + rtl8723e_enable_hw_security_config(hw); + + ppsc->rfpwr_state = ERFON; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); + _rtl8723e_enable_aspm_back_door(hw); + rtlpriv->intf_ops->enable_aspm(hw); + + rtl8723e_bt_hw_init(hw); + + if (ppsc->rfpwr_state == ERFON) { + rtl8723e_phy_set_rfpath_switch(hw, 1); + if (rtlphy->iqk_initialized) { + rtl8723e_phy_iq_calibrate(hw, true); + } else { + rtl8723e_phy_iq_calibrate(hw, false); + rtlphy->iqk_initialized = true; + } + + rtl8723e_dm_check_txpower_tracking(hw); + rtl8723e_phy_lc_calibrate(hw); + } + + tmp_u1b = efuse_read_1byte(hw, 0x1FA); + if (!(tmp_u1b & BIT(0))) { + rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "PA BIAS path A\n"); + } + + if (!(tmp_u1b & BIT(4))) { + tmp_u1b = rtl_read_byte(rtlpriv, 0x16); + tmp_u1b &= 0x0F; + rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80); + udelay(10); + rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n"); + } + rtl8723e_dm_init(hw); +exit: + local_irq_restore(flags); + rtlpriv->rtlhal.being_init_adapter = false; + return err; +} + +static enum version_8723e _rtl8723e_read_chip_version(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + enum version_8723e version = 0x0000; + u32 value32; + + value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); + if (value32 & TRP_VAUX_EN) { + version = (enum version_8723e)(version | + ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); + /* RTL8723 with BT function. */ + version = (enum version_8723e)(version | + ((value32 & BT_FUNC) ? CHIP_8723 : 0)); + + } else { + /* Normal mass production chip. */ + version = (enum version_8723e) NORMAL_CHIP; + version = (enum version_8723e)(version | + ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); + /* RTL8723 with BT function. */ + version = (enum version_8723e)(version | + ((value32 & BT_FUNC) ? CHIP_8723 : 0)); + if (IS_CHIP_VENDOR_UMC(version)) + version = (enum version_8723e)(version | + ((value32 & CHIP_VER_RTL_MASK)));/* IC version (CUT) */ + if (IS_8723_SERIES(version)) { + value32 = rtl_read_dword(rtlpriv, REG_GPIO_OUTSTS); + /* ROM code version. */ + version = (enum version_8723e)(version | + ((value32 & RF_RL_ID)>>20)); + } + } + + if (IS_8723_SERIES(version)) { + value32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL); + rtlphy->polarity_ctl = ((value32 & WL_HWPDN_SL) ? + RT_POLARITY_HIGH_ACT : + RT_POLARITY_LOW_ACT); + } + switch (version) { + case VERSION_TEST_UMC_CHIP_8723: + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Chip Version ID: VERSION_TEST_UMC_CHIP_8723.\n"); + break; + case VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT: + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Chip Version ID: VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT.\n"); + break; + case VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT: + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Chip Version ID: VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT.\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Chip Version ID: Unknown. Bug?\n"); + break; + } + + if (IS_8723_SERIES(version)) + rtlphy->rf_type = RF_1T1R; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Chip RF Type: %s\n", + (rtlphy->rf_type == RF_2T2R) ? "RF_2T2R" : "RF_1T1R"); + + return version; +} + +static int _rtl8723e_set_media_status(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_msr = rtl_read_byte(rtlpriv, MSR) & 0xfc; + enum led_ctl_mode ledaction = LED_CTL_NO_LINK; + u8 mode = MSR_NOLINK; + + rtl_write_dword(rtlpriv, REG_BCN_CTRL, 0); + RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD, + "clear 0x550 when set HW_VAR_MEDIA_STATUS\n"); + + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + mode = MSR_NOLINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to NO LINK!\n"); + break; + case NL80211_IFTYPE_ADHOC: + mode = MSR_ADHOC; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to Ad Hoc!\n"); + break; + case NL80211_IFTYPE_STATION: + mode = MSR_INFRA; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to STA!\n"); + break; + case NL80211_IFTYPE_AP: + mode = MSR_AP; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to AP!\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Network type %d not support!\n", type); + return 1; + break; + } + + /* MSR_INFRA == Link in infrastructure network; + * MSR_ADHOC == Link in ad hoc network; + * Therefore, check link state is necessary. + * + * MSR_AP == AP mode; link state is not cared here. + */ + if (mode != MSR_AP && + rtlpriv->mac80211.link_state < MAC80211_LINKED) { + mode = MSR_NOLINK; + ledaction = LED_CTL_NO_LINK; + } + if (mode == MSR_NOLINK || mode == MSR_INFRA) { + _rtl8723e_stop_tx_beacon(hw); + _rtl8723e_enable_bcn_sub_func(hw); + } else if (mode == MSR_ADHOC || mode == MSR_AP) { + _rtl8723e_resume_tx_beacon(hw); + _rtl8723e_disable_bcn_sub_func(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", + mode); + } + + rtl_write_byte(rtlpriv, MSR, bt_msr | mode); + rtlpriv->cfg->ops->led_control(hw, ledaction); + if (mode == MSR_AP) + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); + else + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); + return 0; +} + +void rtl8723e_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 reg_rcr = rtlpci->receive_config; + + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + if (check_bssid) { + reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, + (u8 *)(®_rcr)); + _rtl8723e_set_bcn_ctrl_reg(hw, 0, BIT(4)); + } else if (!check_bssid) { + reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); + _rtl8723e_set_bcn_ctrl_reg(hw, BIT(4), 0); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_RCR, (u8 *)(®_rcr)); + } +} + +int rtl8723e_set_network_type(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (_rtl8723e_set_media_status(hw, type)) + return -EOPNOTSUPP; + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP) + rtl8723e_set_check_bssid(hw, true); + } else { + rtl8723e_set_check_bssid(hw, false); + } + + return 0; +} + +/* don't set REG_EDCA_BE_PARAM here + * because mac80211 will send pkt when scan + */ +void rtl8723e_set_qos(struct ieee80211_hw *hw, int aci) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl8723_dm_init_edca_turbo(hw); + switch (aci) { + case AC1_BK: + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); + break; + case AC0_BE: + break; + case AC2_VI: + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); + break; + case AC3_VO: + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); + break; + default: + RT_ASSERT(false, "invalid aci: %d !\n", aci); + break; + } +} + +void rtl8723e_enable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, 0x3a8, rtlpci->irq_mask[0] & 0xFFFFFFFF); + rtl_write_dword(rtlpriv, 0x3ac, rtlpci->irq_mask[1] & 0xFFFFFFFF); + rtlpci->irq_enabled = true; +} + +void rtl8723e_disable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + rtl_write_dword(rtlpriv, 0x3a8, IMR8190_DISABLED); + rtl_write_dword(rtlpriv, 0x3ac, IMR8190_DISABLED); + rtlpci->irq_enabled = false; + /*synchronize_irq(rtlpci->pdev->irq);*/ +} + +static void _rtl8723e_poweroff_adapter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 u1b_tmp; + + /* Combo (PCIe + USB) Card and PCIe-MF Card */ + /* 1. Run LPS WL RFOFF flow */ + rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, Rtl8723_NIC_LPS_ENTER_FLOW); + + /* 2. 0x1F[7:0] = 0 */ + /* turn off RF */ + rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); + if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && + rtlhal->fw_ready) { + rtl8723ae_firmware_selfreset(hw); + } + + /* Reset MCU. Suggested by Filen. */ + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); + + /* g. MCUFWDL 0x80[1:0]=0 */ + /* reset MCU ready status */ + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); + + /* HW card disable configuration. */ + rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, Rtl8723_NIC_DISABLE_FLOW); + + /* Reset MCU IO Wrapper */ + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, u1b_tmp | BIT(0)); + + /* 7. RSV_CTRL 0x1C[7:0] = 0x0E */ + /* lock ISO/CLK/Power control register */ + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); +} + +void rtl8723e_card_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + enum nl80211_iftype opmode; + + mac->link_state = MAC80211_NOLINK; + opmode = NL80211_IFTYPE_UNSPECIFIED; + _rtl8723e_set_media_status(hw, opmode); + if (rtlpriv->rtlhal.driver_is_goingto_unload || + ppsc->rfoff_reason > RF_CHANGE_BY_PS) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + _rtl8723e_poweroff_adapter(hw); + + /* after power off we should do iqk again */ + rtlpriv->phy.iqk_initialized = false; +} + +void rtl8723e_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + *p_inta = rtl_read_dword(rtlpriv, 0x3a0) & rtlpci->irq_mask[0]; + rtl_write_dword(rtlpriv, 0x3a0, *p_inta); +} + +void rtl8723e_set_beacon_related_registers(struct ieee80211_hw *hw) +{ + + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval, atim_window; + + bcn_interval = mac->beacon_interval; + atim_window = 2; /*FIX MERGE */ + rtl8723e_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); + rtl_write_byte(rtlpriv, 0x606, 0x30); + rtl8723e_enable_interrupt(hw); +} + +void rtl8723e_set_beacon_interval(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval = mac->beacon_interval; + + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "beacon_interval:%d\n", bcn_interval); + rtl8723e_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl8723e_enable_interrupt(hw); +} + +void rtl8723e_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, + "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); + + if (add_msr) + rtlpci->irq_mask[0] |= add_msr; + if (rm_msr) + rtlpci->irq_mask[0] &= (~rm_msr); + rtl8723e_disable_interrupt(hw); + rtl8723e_enable_interrupt(hw); +} + +static u8 _rtl8723e_get_chnl_group(u8 chnl) +{ + u8 group; + + if (chnl < 3) + group = 0; + else if (chnl < 9) + group = 1; + else + group = 2; + return group; +} + +static void _rtl8723e_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, + u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 rf_path, index, tempval; + u16 i; + + for (rf_path = 0; rf_path < 1; rf_path++) { + for (i = 0; i < 3; i++) { + if (!autoload_fail) { + rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][i] = + hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i]; + rtlefuse->eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = + hwinfo[EEPROM_TXPOWERHT40_1S + rf_path * 3 + i]; + } else { + rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][i] = + EEPROM_DEFAULT_TXPOWERLEVEL; + rtlefuse->eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = + EEPROM_DEFAULT_TXPOWERLEVEL; + } + } + } + + for (i = 0; i < 3; i++) { + if (!autoload_fail) + tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i]; + else + tempval = EEPROM_DEFAULT_HT40_2SDIFF; + rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] = + (tempval & 0xf); + rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] = + ((tempval & 0xf0) >> 4); + } + + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + "RF(%d) EEPROM CCK Area(%d) = 0x%x\n", rf_path, + i, rtlefuse->eeprom_chnlarea_txpwr_cck + [rf_path][i]); + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + "RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse->eeprom_chnlarea_txpwr_ht40_1s + [rf_path][i]); + for (rf_path = 0; rf_path < 2; rf_path++) + for (i = 0; i < 3; i++) + RTPRINT(rtlpriv, FINIT, INIT_EEPROM, + "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", + rf_path, i, + rtlefuse->eprom_chnl_txpwr_ht40_2sdf + [rf_path][i]); + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 14; i++) { + index = _rtl8723e_get_chnl_group((u8)i); + + rtlefuse->txpwrlevel_cck[rf_path][i] = + rtlefuse->eeprom_chnlarea_txpwr_cck + [rf_path][index]; + rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = + rtlefuse->eeprom_chnlarea_txpwr_ht40_1s + [rf_path][index]; + + if ((rtlefuse->eeprom_chnlarea_txpwr_ht40_1s + [rf_path][index] - + rtlefuse->eprom_chnl_txpwr_ht40_2sdf + [rf_path][index]) > 0) { + rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = + rtlefuse->eeprom_chnlarea_txpwr_ht40_1s + [rf_path][index] - + rtlefuse->eprom_chnl_txpwr_ht40_2sdf + [rf_path][index]; + } else { + rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0; + } + } + + for (i = 0; i < 14; i++) { + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", + rf_path, i, + rtlefuse->txpwrlevel_cck[rf_path][i], + rtlefuse->txpwrlevel_ht40_1s[rf_path][i], + rtlefuse->txpwrlevel_ht40_2s[rf_path][i]); + } + } + + for (i = 0; i < 3; i++) { + if (!autoload_fail) { + rtlefuse->eeprom_pwrlimit_ht40[i] = + hwinfo[EEPROM_TXPWR_GROUP + i]; + rtlefuse->eeprom_pwrlimit_ht20[i] = + hwinfo[EEPROM_TXPWR_GROUP + 3 + i]; + } else { + rtlefuse->eeprom_pwrlimit_ht40[i] = 0; + rtlefuse->eeprom_pwrlimit_ht20[i] = 0; + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 14; i++) { + index = _rtl8723e_get_chnl_group((u8)i); + + if (rf_path == RF90_PATH_A) { + rtlefuse->pwrgroup_ht20[rf_path][i] = + (rtlefuse->eeprom_pwrlimit_ht20[index] & 0xf); + rtlefuse->pwrgroup_ht40[rf_path][i] = + (rtlefuse->eeprom_pwrlimit_ht40[index] & 0xf); + } else if (rf_path == RF90_PATH_B) { + rtlefuse->pwrgroup_ht20[rf_path][i] = + ((rtlefuse->eeprom_pwrlimit_ht20[index] & + 0xf0) >> 4); + rtlefuse->pwrgroup_ht40[rf_path][i] = + ((rtlefuse->eeprom_pwrlimit_ht40[index] & + 0xf0) >> 4); + } + + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-%d pwrgroup_ht20[%d] = 0x%x\n", rf_path, i, + rtlefuse->pwrgroup_ht20[rf_path][i]); + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-%d pwrgroup_ht40[%d] = 0x%x\n", rf_path, i, + rtlefuse->pwrgroup_ht40[rf_path][i]); + } + } + + for (i = 0; i < 14; i++) { + index = _rtl8723e_get_chnl_group((u8)i); + + if (!autoload_fail) + tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index]; + else + tempval = EEPROM_DEFAULT_HT20_DIFF; + + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = + ((tempval >> 4) & 0xF); + + if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] & BIT(3)) + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] |= 0xF0; + + if (rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] & BIT(3)) + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] |= 0xF0; + + index = _rtl8723e_get_chnl_group((u8)i); + + if (!autoload_fail) + tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index]; + else + tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; + + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = (tempval & 0xF); + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = + ((tempval >> 4) & 0xF); + } + + rtlefuse->legacy_ht_txpowerdiff = + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; + + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i, + rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i, + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i, + rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); + for (i = 0; i < 14; i++) + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i, + rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); + + if (!autoload_fail) + rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); + else + rtlefuse->eeprom_regulatory = 0; + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); + + if (!autoload_fail) + rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; + else + rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; + + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "TSSI_A = 0x%x, TSSI_B = 0x%x\n", + rtlefuse->eeprom_tssi[RF90_PATH_A], + rtlefuse->eeprom_tssi[RF90_PATH_B]); + + if (!autoload_fail) + tempval = hwinfo[EEPROM_THERMAL_METER]; + else + tempval = EEPROM_DEFAULT_THERMALMETER; + rtlefuse->eeprom_thermalmeter = (tempval & 0x1f); + + if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail) + rtlefuse->apk_thermalmeterignore = true; + + rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); +} + +static void _rtl8723e_read_adapter_info(struct ieee80211_hw *hw, + bool b_pseudo_test) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u16 i, usvalue; + u8 hwinfo[HWSET_MAX_SIZE]; + u16 eeprom_id; + + if (b_pseudo_test) { + /* need add */ + return; + } + if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + rtl_efuse_shadow_map_update(hw); + + memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + HWSET_MAX_SIZE); + } else if (rtlefuse->epromtype == EEPROM_93C46) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "RTL819X Not boot from eeprom, check it !!"); + } + + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP\n", + hwinfo, HWSET_MAX_SIZE); + + eeprom_id = *((u16 *)&hwinfo[0]); + if (eeprom_id != RTL8190_EEPROM_ID) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "EEPROM ID(%#x) is invalid!!\n", eeprom_id); + rtlefuse->autoload_failflag = true; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + } + + if (rtlefuse->autoload_failflag) + return; + + rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; + rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; + rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; + rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROMId = 0x%4x\n", eeprom_id); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); + + for (i = 0; i < 6; i += 2) { + usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; + *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "dev_addr: %pM\n", rtlefuse->dev_addr); + + _rtl8723e_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, + hwinfo); + + rtl8723e_read_bt_coexist_info_from_hwpg(hw, + rtlefuse->autoload_failflag, hwinfo); + + rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; + rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; + rtlefuse->txpwr_fromeprom = true; + rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); + + /* set channel paln to world wide 13 */ + rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; + + if (rtlhal->oem_id == RT_CID_DEFAULT) { + switch (rtlefuse->eeprom_oemid) { + case EEPROM_CID_DEFAULT: + if (rtlefuse->eeprom_did == 0x8176) { + if (CHK_SVID_SMID(0x10EC, 0x6151) || + CHK_SVID_SMID(0x10EC, 0x6152) || + CHK_SVID_SMID(0x10EC, 0x6154) || + CHK_SVID_SMID(0x10EC, 0x6155) || + CHK_SVID_SMID(0x10EC, 0x6177) || + CHK_SVID_SMID(0x10EC, 0x6178) || + CHK_SVID_SMID(0x10EC, 0x6179) || + CHK_SVID_SMID(0x10EC, 0x6180) || + CHK_SVID_SMID(0x10EC, 0x7151) || + CHK_SVID_SMID(0x10EC, 0x7152) || + CHK_SVID_SMID(0x10EC, 0x7154) || + CHK_SVID_SMID(0x10EC, 0x7155) || + CHK_SVID_SMID(0x10EC, 0x7177) || + CHK_SVID_SMID(0x10EC, 0x7178) || + CHK_SVID_SMID(0x10EC, 0x7179) || + CHK_SVID_SMID(0x10EC, 0x7180) || + CHK_SVID_SMID(0x10EC, 0x8151) || + CHK_SVID_SMID(0x10EC, 0x8152) || + CHK_SVID_SMID(0x10EC, 0x8154) || + CHK_SVID_SMID(0x10EC, 0x8155) || + CHK_SVID_SMID(0x10EC, 0x8181) || + CHK_SVID_SMID(0x10EC, 0x8182) || + CHK_SVID_SMID(0x10EC, 0x8184) || + CHK_SVID_SMID(0x10EC, 0x8185) || + CHK_SVID_SMID(0x10EC, 0x9151) || + CHK_SVID_SMID(0x10EC, 0x9152) || + CHK_SVID_SMID(0x10EC, 0x9154) || + CHK_SVID_SMID(0x10EC, 0x9155) || + CHK_SVID_SMID(0x10EC, 0x9181) || + CHK_SVID_SMID(0x10EC, 0x9182) || + CHK_SVID_SMID(0x10EC, 0x9184) || + CHK_SVID_SMID(0x10EC, 0x9185)) + rtlhal->oem_id = RT_CID_TOSHIBA; + else if (rtlefuse->eeprom_svid == 0x1025) + rtlhal->oem_id = RT_CID_819X_ACER; + else if (CHK_SVID_SMID(0x10EC, 0x6191) || + CHK_SVID_SMID(0x10EC, 0x6192) || + CHK_SVID_SMID(0x10EC, 0x6193) || + CHK_SVID_SMID(0x10EC, 0x7191) || + CHK_SVID_SMID(0x10EC, 0x7192) || + CHK_SVID_SMID(0x10EC, 0x7193) || + CHK_SVID_SMID(0x10EC, 0x8191) || + CHK_SVID_SMID(0x10EC, 0x8192) || + CHK_SVID_SMID(0x10EC, 0x8193) || + CHK_SVID_SMID(0x10EC, 0x9191) || + CHK_SVID_SMID(0x10EC, 0x9192) || + CHK_SVID_SMID(0x10EC, 0x9193)) + rtlhal->oem_id = RT_CID_819X_SAMSUNG; + else if (CHK_SVID_SMID(0x10EC, 0x8195) || + CHK_SVID_SMID(0x10EC, 0x9195) || + CHK_SVID_SMID(0x10EC, 0x7194) || + CHK_SVID_SMID(0x10EC, 0x8200) || + CHK_SVID_SMID(0x10EC, 0x8201) || + CHK_SVID_SMID(0x10EC, 0x8202) || + CHK_SVID_SMID(0x10EC, 0x9200)) + rtlhal->oem_id = RT_CID_819X_LENOVO; + else if (CHK_SVID_SMID(0x10EC, 0x8197) || + CHK_SVID_SMID(0x10EC, 0x9196)) + rtlhal->oem_id = RT_CID_819X_CLEVO; + else if (CHK_SVID_SMID(0x1028, 0x8194) || + CHK_SVID_SMID(0x1028, 0x8198) || + CHK_SVID_SMID(0x1028, 0x9197) || + CHK_SVID_SMID(0x1028, 0x9198)) + rtlhal->oem_id = RT_CID_819X_DELL; + else if (CHK_SVID_SMID(0x103C, 0x1629)) + rtlhal->oem_id = RT_CID_819X_HP; + else if (CHK_SVID_SMID(0x1A32, 0x2315)) + rtlhal->oem_id = RT_CID_819X_QMI; + else if (CHK_SVID_SMID(0x10EC, 0x8203)) + rtlhal->oem_id = RT_CID_819X_PRONETS; + else if (CHK_SVID_SMID(0x1043, 0x84B5)) + rtlhal->oem_id = + RT_CID_819X_EDIMAX_ASUS; + else + rtlhal->oem_id = RT_CID_DEFAULT; + } else if (rtlefuse->eeprom_did == 0x8178) { + if (CHK_SVID_SMID(0x10EC, 0x6181) || + CHK_SVID_SMID(0x10EC, 0x6182) || + CHK_SVID_SMID(0x10EC, 0x6184) || + CHK_SVID_SMID(0x10EC, 0x6185) || + CHK_SVID_SMID(0x10EC, 0x7181) || + CHK_SVID_SMID(0x10EC, 0x7182) || + CHK_SVID_SMID(0x10EC, 0x7184) || + CHK_SVID_SMID(0x10EC, 0x7185) || + CHK_SVID_SMID(0x10EC, 0x8181) || + CHK_SVID_SMID(0x10EC, 0x8182) || + CHK_SVID_SMID(0x10EC, 0x8184) || + CHK_SVID_SMID(0x10EC, 0x8185) || + CHK_SVID_SMID(0x10EC, 0x9181) || + CHK_SVID_SMID(0x10EC, 0x9182) || + CHK_SVID_SMID(0x10EC, 0x9184) || + CHK_SVID_SMID(0x10EC, 0x9185)) + rtlhal->oem_id = RT_CID_TOSHIBA; + else if (rtlefuse->eeprom_svid == 0x1025) + rtlhal->oem_id = RT_CID_819X_ACER; + else if (CHK_SVID_SMID(0x10EC, 0x8186)) + rtlhal->oem_id = RT_CID_819X_PRONETS; + else if (CHK_SVID_SMID(0x1043, 0x8486)) + rtlhal->oem_id = + RT_CID_819X_EDIMAX_ASUS; + else + rtlhal->oem_id = RT_CID_DEFAULT; + } else { + rtlhal->oem_id = RT_CID_DEFAULT; + } + break; + case EEPROM_CID_TOSHIBA: + rtlhal->oem_id = RT_CID_TOSHIBA; + break; + case EEPROM_CID_CCX: + rtlhal->oem_id = RT_CID_CCX; + break; + case EEPROM_CID_QMI: + rtlhal->oem_id = RT_CID_819X_QMI; + break; + case EEPROM_CID_WHQL: + break; + default: + rtlhal->oem_id = RT_CID_DEFAULT; + break; + + } + } +} + +static void _rtl8723e_hal_customized_behavior(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + pcipriv->ledctl.led_opendrain = true; + switch (rtlhal->oem_id) { + case RT_CID_819X_HP: + pcipriv->ledctl.led_opendrain = true; + break; + case RT_CID_819X_LENOVO: + case RT_CID_DEFAULT: + case RT_CID_TOSHIBA: + case RT_CID_CCX: + case RT_CID_819X_ACER: + case RT_CID_WHQL: + default: + break; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "RT Customized ID: 0x%02X\n", rtlhal->oem_id); +} + +void rtl8723e_read_eeprom_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_u1b; + u32 value32; + + value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST]); + value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0); + rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST], value32); + + rtlhal->version = _rtl8723e_read_chip_version(hw); + + if (get_rf_type(rtlphy) == RF_1T1R) + rtlpriv->dm.rfpath_rxenable[0] = true; + else + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", + rtlhal->version); + + tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); + if (tmp_u1b & BIT(4)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); + rtlefuse->epromtype = EEPROM_93C46; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); + rtlefuse->epromtype = EEPROM_BOOT_EFUSE; + } + if (tmp_u1b & BIT(5)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + _rtl8723e_read_adapter_info(hw, false); + } else { + rtlefuse->autoload_failflag = true; + _rtl8723e_read_adapter_info(hw, false); + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); + } + _rtl8723e_hal_customized_behavior(hw); +} + +static void rtl8723e_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 ratr_value; + u8 ratr_index = 0; + u8 b_nmode = mac->ht_enable; + u16 shortgi_rate; + u32 tmp_ratr_value; + u8 curtxbw_40mhz = mac->bw_40; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = mac->mode; + u32 ratr_mask; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_value = sta->supp_rates[1] << 4; + else + ratr_value = sta->supp_rates[0]; + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_value = 0xfff; + ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + if (ratr_value & 0x0000000c) + ratr_value &= 0x0000000d; + else + ratr_value &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_value &= 0x00000FF5; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + b_nmode = 1; + if (get_rf_type(rtlphy) == RF_1T2R || + get_rf_type(rtlphy) == RF_1T1R) + ratr_mask = 0x000ff005; + else + ratr_mask = 0x0f0ff005; + + ratr_value &= ratr_mask; + break; + default: + if (rtlphy->rf_type == RF_1T2R) + ratr_value &= 0x000ff0ff; + else + ratr_value &= 0x0f0ff0ff; + + break; + } + + if ((rtlpriv->btcoexist.bt_coexistence) && + (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4) && + (rtlpriv->btcoexist.bt_cur_state) && + (rtlpriv->btcoexist.bt_ant_isolation) && + ((rtlpriv->btcoexist.bt_service == BT_SCO) || + (rtlpriv->btcoexist.bt_service == BT_BUSY))) + ratr_value &= 0x0fffcfc0; + else + ratr_value &= 0x0FFFFFFF; + + if (b_nmode && + ((curtxbw_40mhz && curshortgi_40mhz) || + (!curtxbw_40mhz && curshortgi_20mhz))) { + ratr_value |= 0x10000000; + tmp_ratr_value = (ratr_value >> 12); + + for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { + if ((1 << shortgi_rate) & tmp_ratr_value) + break; + } + + shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | + (shortgi_rate << 4) | (shortgi_rate); + } + + rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)); +} + +static void rtl8723e_update_hal_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u32 ratr_bitmap; + u8 ratr_index; + u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) + ? 1 : 0; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = 0; + bool shortgi = false; + u8 rate_mask[5]; + u8 macid = 0; + /*u8 mimo_ps = IEEE80211_SMPS_OFF;*/ + + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + wirelessmode = sta_entry->wireless_mode; + if (mac->opmode == NL80211_IFTYPE_STATION) + curtxbw_40mhz = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + macid = sta->aid + 1; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_bitmap = sta->supp_rates[1] << 4; + else + ratr_bitmap = sta->supp_rates[0]; + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_bitmap = 0xfff; + ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + ratr_index = RATR_INX_WIRELESS_B; + if (ratr_bitmap & 0x0000000c) + ratr_bitmap &= 0x0000000d; + else + ratr_bitmap &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_index = RATR_INX_WIRELESS_GB; + + if (rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if (rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + break; + case WIRELESS_MODE_A: + ratr_index = RATR_INX_WIRELESS_G; + ratr_bitmap &= 0x00000ff0; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + ratr_index = RATR_INX_WIRELESS_NGB; + if (rtlphy->rf_type == RF_1T2R || + rtlphy->rf_type == RF_1T1R) { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff005; + } + } else { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x0f0f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f0ff000; + else + ratr_bitmap &= 0x0f0ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x0f0f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f0ff000; + else + ratr_bitmap &= 0x0f0ff005; + } + } + + if ((curtxbw_40mhz && curshortgi_40mhz) || + (!curtxbw_40mhz && curshortgi_20mhz)) { + if (macid == 0) + shortgi = true; + else if (macid == 1) + shortgi = false; + } + break; + default: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rtlphy->rf_type == RF_1T2R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0f0ff0ff; + break; + } + sta_entry->ratr_index = ratr_index; + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "ratr_bitmap :%x\n", ratr_bitmap); + *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | + (ratr_index << 28); + rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n", + ratr_index, ratr_bitmap, + rate_mask[0], rate_mask[1], + rate_mask[2], rate_mask[3], + rate_mask[4]); + rtl8723e_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); +} + +void rtl8723e_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->dm.useramask) + rtl8723e_update_hal_rate_mask(hw, sta, rssi_level); + else + rtl8723e_update_hal_rate_table(hw, sta); +} + +void rtl8723e_update_channel_access_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 sifs_timer; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, &mac->slot_time); + if (!mac->ht_enable) + sifs_timer = 0x0a0a; + else + sifs_timer = 0x1010; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); +} + +bool rtl8723e_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; + u8 u1tmp; + bool b_actuallyset = false; + + if (rtlpriv->rtlhal.being_init_adapter) + return false; + + if (ppsc->swrf_processing) + return false; + + spin_lock(&rtlpriv->locks.rf_ps_lock); + if (ppsc->rfchange_inprogress) { + spin_unlock(&rtlpriv->locks.rf_ps_lock); + return false; + } else { + ppsc->rfchange_inprogress = true; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } + + cur_rfstate = ppsc->rfpwr_state; + + rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL_2, + rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL_2)&~(BIT(1))); + + u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL_2); + + if (rtlphy->polarity_ctl) + e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFOFF : ERFON; + else + e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFON : ERFOFF; + + if (ppsc->hwradiooff && (e_rfpowerstate_toset == ERFON)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "GPIOChangeRF - HW Radio ON, RF ON\n"); + + e_rfpowerstate_toset = ERFON; + ppsc->hwradiooff = false; + b_actuallyset = true; + } else if (!ppsc->hwradiooff && (e_rfpowerstate_toset == ERFOFF)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "GPIOChangeRF - HW Radio OFF, RF OFF\n"); + + e_rfpowerstate_toset = ERFOFF; + ppsc->hwradiooff = true; + b_actuallyset = true; + } + + if (b_actuallyset) { + spin_lock(&rtlpriv->locks.rf_ps_lock); + ppsc->rfchange_inprogress = false; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } else { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + + spin_lock(&rtlpriv->locks.rf_ps_lock); + ppsc->rfchange_inprogress = false; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } + + *valid = 1; + return !ppsc->hwradiooff; + +} + +void rtl8723e_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 *macaddr = p_macaddr; + u32 entry_id = 0; + bool is_pairwise = false; + + static u8 cam_const_addr[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} + }; + static u8 cam_const_broad[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (clear_all) { + u8 idx = 0; + u8 cam_offset = 0; + u8 clear_number = 5; + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); + + for (idx = 0; idx < clear_number; idx++) { + rtl_cam_mark_invalid(hw, cam_offset + idx); + rtl_cam_empty_entry(hw, cam_offset + idx); + + if (idx < 5) { + memset(rtlpriv->sec.key_buf[idx], 0, + MAX_KEY_LEN); + rtlpriv->sec.key_len[idx] = 0; + } + } + + } else { + switch (enc_algo) { + case WEP40_ENCRYPTION: + enc_algo = CAM_WEP40; + break; + case WEP104_ENCRYPTION: + enc_algo = CAM_WEP104; + break; + case TKIP_ENCRYPTION: + enc_algo = CAM_TKIP; + break; + case AESCCMP_ENCRYPTION: + enc_algo = CAM_AES; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + enc_algo = CAM_TKIP; + break; + } + + if (is_wepkey || rtlpriv->sec.use_defaultkey) { + macaddr = cam_const_addr[key_index]; + entry_id = key_index; + } else { + if (is_group) { + macaddr = cam_const_broad; + entry_id = key_index; + } else { + if (mac->opmode == NL80211_IFTYPE_AP) { + entry_id = + rtl_cam_get_free_entry(hw, p_macaddr); + if (entry_id >= TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, COMP_SEC, + DBG_EMERG, + "Can not find free hw security cam entry\n"); + return; + } + } else { + entry_id = CAM_PAIRWISE_KEY_POSITION; + } + + key_index = PAIRWISE_KEYIDX; + is_pairwise = true; + } + } + + if (rtlpriv->sec.key_len[key_index] == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "delete one entry, entry_id is %d\n", + entry_id); + if (mac->opmode == NL80211_IFTYPE_AP) + rtl_cam_del_entry(hw, p_macaddr); + rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "add one entry\n"); + if (is_pairwise) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set Pairwiase key\n"); + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[key_index]); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set group key\n"); + + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_cam_add_one_entry(hw, + rtlefuse->dev_addr, + PAIRWISE_KEYIDX, + CAM_PAIRWISE_KEY_POSITION, + enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf + [entry_id]); + } + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + + } + } +} + +static void rtl8723e_bt_var_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->btcoexist.bt_coexistence = + rtlpriv->btcoexist.eeprom_bt_coexist; + rtlpriv->btcoexist.bt_ant_num = + rtlpriv->btcoexist.eeprom_bt_ant_num; + rtlpriv->btcoexist.bt_coexist_type = + rtlpriv->btcoexist.eeprom_bt_type; + + rtlpriv->btcoexist.bt_ant_isolation = + rtlpriv->btcoexist.eeprom_bt_ant_isol; + + rtlpriv->btcoexist.bt_radio_shared_type = + rtlpriv->btcoexist.eeprom_bt_radio_shared; + + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "BT Coexistance = 0x%x\n", + rtlpriv->btcoexist.bt_coexistence); + + if (rtlpriv->btcoexist.bt_coexistence) { + rtlpriv->btcoexist.bt_busy_traffic = false; + rtlpriv->btcoexist.bt_traffic_mode_set = false; + rtlpriv->btcoexist.bt_non_traffic_mode_set = false; + + rtlpriv->btcoexist.cstate = 0; + rtlpriv->btcoexist.previous_state = 0; + + if (rtlpriv->btcoexist.bt_ant_num == ANT_X2) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "BlueTooth BT_Ant_Num = Antx2\n"); + } else if (rtlpriv->btcoexist.bt_ant_num == ANT_X1) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "BlueTooth BT_Ant_Num = Antx1\n"); + } + switch (rtlpriv->btcoexist.bt_coexist_type) { + case BT_2WIRE: + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "BlueTooth BT_CoexistType = BT_2Wire\n"); + break; + case BT_ISSC_3WIRE: + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "BlueTooth BT_CoexistType = BT_ISSC_3Wire\n"); + break; + case BT_ACCEL: + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "BlueTooth BT_CoexistType = BT_ACCEL\n"); + break; + case BT_CSR_BC4: + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "BlueTooth BT_CoexistType = BT_CSR_BC4\n"); + break; + case BT_CSR_BC8: + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "BlueTooth BT_CoexistType = BT_CSR_BC8\n"); + break; + case BT_RTL8756: + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "BlueTooth BT_CoexistType = BT_RTL8756\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "BlueTooth BT_CoexistType = Unknown\n"); + break; + } + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "BlueTooth BT_Ant_isolation = %d\n", + rtlpriv->btcoexist.bt_ant_isolation); + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, + "BT_RadioSharedType = 0x%x\n", + rtlpriv->btcoexist.bt_radio_shared_type); + rtlpriv->btcoexist.bt_active_zero_cnt = 0; + rtlpriv->btcoexist.cur_bt_disabled = false; + rtlpriv->btcoexist.pre_bt_disabled = false; + } +} + +void rtl8723e_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool auto_load_fail, u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 value; + u32 tmpu_32; + + if (!auto_load_fail) { + tmpu_32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL); + if (tmpu_32 & BIT(18)) + rtlpriv->btcoexist.eeprom_bt_coexist = 1; + else + rtlpriv->btcoexist.eeprom_bt_coexist = 0; + value = hwinfo[RF_OPTION4]; + rtlpriv->btcoexist.eeprom_bt_type = BT_RTL8723A; + rtlpriv->btcoexist.eeprom_bt_ant_num = (value & 0x1); + rtlpriv->btcoexist.eeprom_bt_ant_isol = ((value & 0x10) >> 4); + rtlpriv->btcoexist.eeprom_bt_radio_shared = + ((value & 0x20) >> 5); + } else { + rtlpriv->btcoexist.eeprom_bt_coexist = 0; + rtlpriv->btcoexist.eeprom_bt_type = BT_RTL8723A; + rtlpriv->btcoexist.eeprom_bt_ant_num = ANT_X2; + rtlpriv->btcoexist.eeprom_bt_ant_isol = 0; + rtlpriv->btcoexist.eeprom_bt_radio_shared = BT_RADIO_SHARED; + } + + rtl8723e_bt_var_init(hw); +} + +void rtl8723e_bt_reg_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* 0:Low, 1:High, 2:From Efuse. */ + rtlpriv->btcoexist.reg_bt_iso = 2; + /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ + rtlpriv->btcoexist.reg_bt_sco = 3; + /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ + rtlpriv->btcoexist.reg_bt_sco = 0; +} + +void rtl8723e_bt_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_init_hw_config(rtlpriv); +} + +void rtl8723e_suspend(struct ieee80211_hw *hw) +{ +} + +void rtl8723e_resume(struct ieee80211_hw *hw) +{ +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h new file mode 100644 index 000000000000..32c1ace97c3f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_HW_H__ +#define __RTL8723E_HW_H__ + +#define CHK_SVID_SMID(_val1, _val2) \ + ((rtlefuse->eeprom_svid == (_val1)) && \ + (rtlefuse->eeprom_smid == (_val2))) + +void rtl8723e_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl8723e_read_eeprom_info(struct ieee80211_hw *hw); + +void rtl8723e_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb); +int rtl8723e_hw_init(struct ieee80211_hw *hw); +void rtl8723e_card_disable(struct ieee80211_hw *hw); +void rtl8723e_enable_interrupt(struct ieee80211_hw *hw); +void rtl8723e_disable_interrupt(struct ieee80211_hw *hw); +int rtl8723e_set_network_type(struct ieee80211_hw *hw, + enum nl80211_iftype type); +void rtl8723e_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); +void rtl8723e_set_qos(struct ieee80211_hw *hw, int aci); +void rtl8723e_set_beacon_related_registers(struct ieee80211_hw *hw); +void rtl8723e_set_beacon_interval(struct ieee80211_hw *hw); +void rtl8723e_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); +void rtl8723e_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl8723e_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); +void rtl8723e_update_channel_access_setting(struct ieee80211_hw *hw); +bool rtl8723e_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); +void rtl8723e_enable_hw_security_config(struct ieee80211_hw *hw); +void rtl8723e_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all); + +void rtl8723e_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo); +void rtl8723e_bt_reg_init(struct ieee80211_hw *hw); +void rtl8723e_bt_hw_init(struct ieee80211_hw *hw); +void rtl8723e_suspend(struct ieee80211_hw *hw); +void rtl8723e_resume(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c new file mode 100644 index 000000000000..13173351cbfd --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.c @@ -0,0 +1,159 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "reg.h" +#include "led.h" + +static void _rtl8723e_init_led(struct ieee80211_hw *hw, + struct rtl_led *pled, enum rtl_led_pin ledpin) +{ + pled->hw = hw; + pled->ledpin = ledpin; + pled->ledon = false; +} + +void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u8 ledcfg; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + ledcfg &= ~BIT(6); + rtl_write_byte(rtlpriv, + REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5)); + break; + case LED_PIN_LED1: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); + rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + pled->ledon = true; +} + +void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + u8 ledcfg; + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg &= 0xf0; + if (pcipriv->ledctl.led_opendrain) { + ledcfg &= 0x90; /* Set to software control. */ + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3))); + ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); + ledcfg &= 0xFE; + rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg); + } else { + ledcfg &= ~BIT(6); + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(3) | BIT(5))); + } + break; + case LED_PIN_LED1: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); + ledcfg &= 0x10; /* Set to software control. */ + rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg|BIT(3)); + + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + pled->ledon = false; +} + +void rtl8723e_init_sw_leds(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + _rtl8723e_init_led(hw, &pcipriv->ledctl.sw_led0, LED_PIN_LED0); + _rtl8723e_init_led(hw, &pcipriv->ledctl.sw_led1, LED_PIN_LED1); +} + +static void _rtl8723e_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + switch (ledaction) { + case LED_CTL_POWER_ON: + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + rtl8723e_sw_led_on(hw, pLed0); + break; + case LED_CTL_POWER_OFF: + rtl8723e_sw_led_off(hw, pLed0); + break; + default: + break; + } +} + +void rtl8723e_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && + (ledaction == LED_CTL_TX || + ledaction == LED_CTL_RX || + ledaction == LED_CTL_SITE_SURVEY || + ledaction == LED_CTL_LINK || + ledaction == LED_CTL_NO_LINK || + ledaction == LED_CTL_START_TO_LINK || + ledaction == LED_CTL_POWER_ON)) { + return; + } + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n", + ledaction); + _rtl8723e_sw_led_control(hw, ledaction); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h new file mode 100644 index 000000000000..c22b19f542a6 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/led.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92CE_LED_H__ +#define __RTL92CE_LED_H__ + +void rtl8723e_init_sw_leds(struct ieee80211_hw *hw); +void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl8723e_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c new file mode 100644 index 000000000000..d367097f490b --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c @@ -0,0 +1,1705 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../ps.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "table.h" +#include "../rtl8723com/phy_common.h" + +static void _rtl8723e_phy_fw_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +static bool _rtl8723e_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); +static bool _rtl8723e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); +static bool _rtl8723e_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +static bool _rtl8723e_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype); +static bool _rtl8723e_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay); +static u8 _rtl8723e_phy_dbm_to_txpwr_idx(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + long power_indbm); +static void rtl8723e_phy_set_rf_on(struct ieee80211_hw *hw); +static void rtl8723e_phy_set_io(struct ieee80211_hw *hw); + +u32 rtl8723e_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value = 0, readback_value, bitshift; + struct rtl_phy *rtlphy = &rtlpriv->phy; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", + regaddr, rfpath, bitmask); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + if (rtlphy->rf_mode != RF_OP_BY_FW) { + original_value = rtl8723_phy_rf_serial_read(hw, + rfpath, regaddr); + } + + bitshift = rtl8723_phy_calculate_bit_shift(bitmask); + readback_value = (original_value & bitmask) >> bitshift; + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", + regaddr, rfpath, bitmask, original_value); + + return readback_value; +} + +void rtl8723e_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 original_value = 0, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + if (rtlphy->rf_mode != RF_OP_BY_FW) { + if (bitmask != RFREG_OFFSET_MASK) { + original_value = rtl8723_phy_rf_serial_read(hw, + rfpath, + regaddr); + bitshift = rtl8723_phy_calculate_bit_shift(bitmask); + data = + ((original_value & (~bitmask)) | + (data << bitshift)); + } + + rtl8723_phy_rf_serial_write(hw, rfpath, regaddr, data); + } else { + if (bitmask != RFREG_OFFSET_MASK) { + bitshift = rtl8723_phy_calculate_bit_shift(bitmask); + data = + ((original_value & (~bitmask)) | + (data << bitshift)); + } + _rtl8723e_phy_fw_rf_serial_write(hw, rfpath, regaddr, data); + } + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); + +} + +static void _rtl8723e_phy_fw_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data) +{ + RT_ASSERT(false, "deprecated!\n"); +} + +static void _rtl8723e_phy_bb_config_1t(struct ieee80211_hw *hw) +{ + rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2); + rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022); + rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45); + rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23); + rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1); + rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2); + rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2); + rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2); + rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2); + rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2); +} + +bool rtl8723e_phy_mac_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool rtstatus = _rtl8723e_phy_config_mac_with_headerfile(hw); + rtl_write_byte(rtlpriv, 0x04CA, 0x0A); + return rtstatus; +} + +bool rtl8723e_phy_bb_config(struct ieee80211_hw *hw) +{ + bool rtstatus = true; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmpu1b; + u8 b_reg_hwparafile = 1; + + rtl8723_phy_init_bb_rf_reg_def(hw); + + /* 1. 0x28[1] = 1 */ + tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_PLL_CTRL); + udelay(2); + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, (tmpu1b|BIT(1))); + udelay(2); + /* 2. 0x29[7:0] = 0xFF */ + rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL+1, 0xff); + udelay(2); + + /* 3. 0x02[1:0] = 2b'11 */ + tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, + (tmpu1b | FEN_BB_GLB_RSTN | FEN_BBRSTB)); + + /* 4. 0x25[6] = 0 */ + tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+1); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+1, (tmpu1b & (~BIT(6)))); + + /* 5. 0x24[20] = 0 //Advised by SD3 Alex Wang. 2011.02.09. */ + tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2); + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, (tmpu1b & (~BIT(4)))); + + /* 6. 0x1f[7:0] = 0x07 */ + rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x07); + + if (b_reg_hwparafile == 1) + rtstatus = _rtl8723e_phy_bb8192c_config_parafile(hw); + return rtstatus; +} + +bool rtl8723e_phy_rf_config(struct ieee80211_hw *hw) +{ + return rtl8723e_phy_rf6052_config(hw); +} + +static bool _rtl8723e_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + bool rtstatus; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); + rtstatus = _rtl8723e_phy_config_bb_with_headerfile(hw, + BASEBAND_CONFIG_PHY_REG); + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); + return false; + } + + if (rtlphy->rf_type == RF_1T2R) { + _rtl8723e_phy_bb_config_1t(hw); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Config to 1T!!\n"); + } + if (rtlefuse->autoload_failflag == false) { + rtlphy->pwrgroup_cnt = 0; + rtstatus = _rtl8723e_phy_config_bb_with_pgheaderfile(hw, + BASEBAND_CONFIG_PHY_REG); + } + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); + return false; + } + rtstatus = + _rtl8723e_phy_config_bb_with_headerfile(hw, BASEBAND_CONFIG_AGC_TAB); + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); + return false; + } + rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + 0x200)); + + return true; +} + +static bool _rtl8723e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + u32 arraylength; + u32 *ptrarray; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl723MACPHY_Array\n"); + arraylength = RTL8723E_MACARRAYLENGTH; + ptrarray = RTL8723EMAC_ARRAY; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Img:RTL8192CEMAC_2T_ARRAY\n"); + for (i = 0; i < arraylength; i = i + 2) + rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); + return true; +} + +static bool _rtl8723e_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype) +{ + int i; + u32 *phy_regarray_table; + u32 *agctab_array_table; + u16 phy_reg_arraylen, agctab_arraylen; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + agctab_arraylen = RTL8723E_AGCTAB_1TARRAYLENGTH; + agctab_array_table = RTL8723EAGCTAB_1TARRAY; + phy_reg_arraylen = RTL8723E_PHY_REG_1TARRAY_LENGTH; + phy_regarray_table = RTL8723EPHY_REG_1TARRAY; + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_reg_arraylen; i = i + 2) { + if (phy_regarray_table[i] == 0xfe) + mdelay(50); + else if (phy_regarray_table[i] == 0xfd) + mdelay(5); + else if (phy_regarray_table[i] == 0xfc) + mdelay(1); + else if (phy_regarray_table[i] == 0xfb) + udelay(50); + else if (phy_regarray_table[i] == 0xfa) + udelay(5); + else if (phy_regarray_table[i] == 0xf9) + udelay(1); + rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD, + phy_regarray_table[i + 1]); + udelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", + phy_regarray_table[i], + phy_regarray_table[i + 1]); + } + } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { + for (i = 0; i < agctab_arraylen; i = i + 2) { + rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD, + agctab_array_table[i + 1]); + udelay(1); + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", + agctab_array_table[i], + agctab_array_table[i + 1]); + } + } + return true; +} + +static void store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, + u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + if (regaddr == RTXAGC_A_RATE18_06) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][0]); + } + if (regaddr == RTXAGC_A_RATE54_24) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][1]); + } + if (regaddr == RTXAGC_A_CCK1_MCS32) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][6]); + } + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][7]); + } + if (regaddr == RTXAGC_A_MCS03_MCS00) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][2]); + } + if (regaddr == RTXAGC_A_MCS07_MCS04) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][3]); + } + if (regaddr == RTXAGC_A_MCS11_MCS08) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][4]); + } + if (regaddr == RTXAGC_A_MCS15_MCS12) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][5]); + } + if (regaddr == RTXAGC_B_RATE18_06) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][8]); + } + if (regaddr == RTXAGC_B_RATE54_24) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][9]); + } + if (regaddr == RTXAGC_B_CCK1_55_MCS32) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][14]); + } + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][15]); + } + if (regaddr == RTXAGC_B_MCS03_MCS00) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][10]); + } + if (regaddr == RTXAGC_B_MCS07_MCS04) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][11]); + } + if (regaddr == RTXAGC_B_MCS11_MCS08) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][12]); + } + if (regaddr == RTXAGC_B_MCS15_MCS12) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> + pwrgroup_cnt][13]); + + rtlphy->pwrgroup_cnt++; + } +} + +static bool _rtl8723e_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int i; + u32 *phy_regarray_table_pg; + u16 phy_regarray_pg_len; + + phy_regarray_pg_len = RTL8723E_PHY_REG_ARRAY_PGLENGTH; + phy_regarray_table_pg = RTL8723EPHY_REG_ARRAY_PG; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_regarray_pg_len; i = i + 3) { + if (phy_regarray_table_pg[i] == 0xfe) + mdelay(50); + else if (phy_regarray_table_pg[i] == 0xfd) + mdelay(5); + else if (phy_regarray_table_pg[i] == 0xfc) + mdelay(1); + else if (phy_regarray_table_pg[i] == 0xfb) + udelay(50); + else if (phy_regarray_table_pg[i] == 0xfa) + udelay(5); + else if (phy_regarray_table_pg[i] == 0xf9) + udelay(1); + + store_pwrindex_diffrate_offset(hw, + phy_regarray_table_pg[i], + phy_regarray_table_pg[i + 1], + phy_regarray_table_pg[i + 2]); + } + } else { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "configtype != BaseBand_Config_PHY_REG\n"); + } + return true; +} + +bool rtl8723e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath) +{ + int i; + bool rtstatus = true; + u32 *radioa_array_table; + u32 *radiob_array_table; + u16 radioa_arraylen, radiob_arraylen; + + radioa_arraylen = RTL8723ERADIOA_1TARRAYLENGTH; + radioa_array_table = RTL8723E_RADIOA_1TARRAY; + radiob_arraylen = RTL8723E_RADIOB_1TARRAYLENGTH; + radiob_array_table = RTL8723E_RADIOB_1TARRAY; + + rtstatus = true; + + switch (rfpath) { + case RF90_PATH_A: + for (i = 0; i < radioa_arraylen; i = i + 2) { + if (radioa_array_table[i] == 0xfe) { + mdelay(50); + } else if (radioa_array_table[i] == 0xfd) { + mdelay(5); + } else if (radioa_array_table[i] == 0xfc) { + mdelay(1); + } else if (radioa_array_table[i] == 0xfb) { + udelay(50); + } else if (radioa_array_table[i] == 0xfa) { + udelay(5); + } else if (radioa_array_table[i] == 0xf9) { + udelay(1); + } else { + rtl_set_rfreg(hw, rfpath, radioa_array_table[i], + RFREG_OFFSET_MASK, + radioa_array_table[i + 1]); + udelay(1); + } + } + break; + case RF90_PATH_B: + case RF90_PATH_C: + case RF90_PATH_D: + break; + } + return true; +} + +void rtl8723e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + rtlphy->default_initialgain[0] = + (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[1] = + (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[2] = + (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[3] = + (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", + rtlphy->default_initialgain[0], + rtlphy->default_initialgain[1], + rtlphy->default_initialgain[2], + rtlphy->default_initialgain[3]); + + rtlphy->framesync = (u8) rtl_get_bbreg(hw, + ROFDM0_RXDETECTOR3, MASKBYTE0); + rtlphy->framesync_c34 = rtl_get_bbreg(hw, + ROFDM0_RXDETECTOR2, MASKDWORD); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default framesync (0x%x) = 0x%x\n", + ROFDM0_RXDETECTOR3, rtlphy->framesync); +} + +void rtl8723e_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 txpwr_level; + long txpwr_dbm; + + txpwr_level = rtlphy->cur_cck_txpwridx; + txpwr_dbm = rtl8723_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_B, txpwr_level); + txpwr_level = rtlphy->cur_ofdm24g_txpwridx + + rtlefuse->legacy_ht_txpowerdiff; + if (rtl8723_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_G, + txpwr_level) > txpwr_dbm) + txpwr_dbm = + rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, + txpwr_level); + txpwr_level = rtlphy->cur_ofdm24g_txpwridx; + if (rtl8723_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_N_24G, + txpwr_level) > txpwr_dbm) + txpwr_dbm = + rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, + txpwr_level); + *powerlevel = txpwr_dbm; +} + +static void _rtl8723e_get_txpower_index(struct ieee80211_hw *hw, u8 channel, + u8 *cckpowerlevel, u8 *ofdmpowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 index = (channel - 1); + + cckpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_cck[RF90_PATH_A][index]; + cckpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_cck[RF90_PATH_B][index]; + if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) { + ofdmpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index]; + ofdmpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index]; + } else if (get_rf_type(rtlphy) == RF_2T2R) { + ofdmpowerlevel[RF90_PATH_A] = + rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index]; + ofdmpowerlevel[RF90_PATH_B] = + rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index]; + } +} + +static void _rtl8723e_ccxpower_index_check(struct ieee80211_hw *hw, + u8 channel, u8 *cckpowerlevel, + u8 *ofdmpowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; + rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; + +} + +void rtl8723e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 cckpowerlevel[2], ofdmpowerlevel[2]; + + if (rtlefuse->txpwr_fromeprom == false) + return; + _rtl8723e_get_txpower_index(hw, channel, + &cckpowerlevel[0], &ofdmpowerlevel[0]); + _rtl8723e_ccxpower_index_check(hw, + channel, &cckpowerlevel[0], + &ofdmpowerlevel[0]); + rtl8723e_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]); + rtl8723e_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel); +} + +bool rtl8723e_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 idx; + u8 rf_path; + u8 ccktxpwridx = _rtl8723e_phy_dbm_to_txpwr_idx(hw, + WIRELESS_MODE_B, + power_indbm); + u8 ofdmtxpwridx = _rtl8723e_phy_dbm_to_txpwr_idx(hw, + WIRELESS_MODE_N_24G, + power_indbm); + if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0) + ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff; + else + ofdmtxpwridx = 0; + RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE, + "%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n", + power_indbm, ccktxpwridx, ofdmtxpwridx); + for (idx = 0; idx < 14; idx++) { + for (rf_path = 0; rf_path < 2; rf_path++) { + rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx; + rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] = + ofdmtxpwridx; + rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] = + ofdmtxpwridx; + } + } + rtl8723e_phy_set_txpower_level(hw, rtlphy->current_channel); + return true; +} + +static u8 _rtl8723e_phy_dbm_to_txpwr_idx(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + long power_indbm) +{ + u8 txpwridx; + long offset; + + switch (wirelessmode) { + case WIRELESS_MODE_B: + offset = -7; + break; + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + offset = -8; + break; + default: + offset = -8; + break; + } + + if ((power_indbm - offset) > 0) + txpwridx = (u8)((power_indbm - offset) * 2); + else + txpwridx = 0; + + if (txpwridx > MAX_TXPWR_IDX_NMODE_92S) + txpwridx = MAX_TXPWR_IDX_NMODE_92S; + + return txpwridx; +} + +void rtl8723e_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + enum io_type iotype; + + if (!is_hal_stop(rtlhal)) { + switch (operation) { + case SCAN_OPT_BACKUP_BAND0: + iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_IO_CMD, + (u8 *)&iotype); + + break; + case SCAN_OPT_RESTORE: + iotype = IO_CMD_RESUME_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_IO_CMD, + (u8 *)&iotype); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Unknown Scan Backup operation.\n"); + break; + } + } +} + +void rtl8723e_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 reg_bw_opmode; + u8 reg_prsr_rsc; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz"); + + if (is_hal_stop(rtlhal)) { + rtlphy->set_bwmode_inprogress = false; + return; + } + + reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); + reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + break; + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + reg_prsr_rsc = + (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); + rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); + + rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), + (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + rtl8723e_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); +} + +void rtl8723e_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_bw = rtlphy->current_chan_bw; + + if (rtlphy->set_bwmode_inprogress) + return; + rtlphy->set_bwmode_inprogress = true; + if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtl8723e_phy_set_bw_mode_callback(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "false driver sleep or unload\n"); + rtlphy->set_bwmode_inprogress = false; + rtlphy->current_chan_bw = tmp_bw; + } +} + +void rtl8723e_phy_sw_chnl_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 delay; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "switch to channel%d\n", rtlphy->current_channel); + if (is_hal_stop(rtlhal)) + return; + do { + if (!rtlphy->sw_chnl_inprogress) + break; + if (!_rtl8723e_phy_sw_chnl_step_by_step + (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage, + &rtlphy->sw_chnl_step, &delay)) { + if (delay > 0) + mdelay(delay); + else + continue; + } else { + rtlphy->sw_chnl_inprogress = false; + } + break; + } while (true); + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); +} + +u8 rtl8723e_phy_sw_chnl(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlphy->sw_chnl_inprogress) + return 0; + if (rtlphy->set_bwmode_inprogress) + return 0; + RT_ASSERT((rtlphy->current_channel <= 14), + "WIRELESS_MODE_G but channel>14"); + rtlphy->sw_chnl_inprogress = true; + rtlphy->sw_chnl_stage = 0; + rtlphy->sw_chnl_step = 0; + if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtl8723e_phy_sw_chnl_callback(hw); + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + "sw_chnl_inprogress false schdule workitem\n"); + rtlphy->sw_chnl_inprogress = false; + } else { + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + "sw_chnl_inprogress false driver sleep or unload\n"); + rtlphy->sw_chnl_inprogress = false; + } + return 1; +} + +static void _rtl8723e_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { + if (channel == 6 && rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20) + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, + MASKDWORD, 0x00255); + else{ + u32 backuprf0x1a = (u32)rtl_get_rfreg(hw, + RF90_PATH_A, RF_RX_G1, + RFREG_OFFSET_MASK); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, + MASKDWORD, backuprf0x1a); + } + } +} + +static bool _rtl8723e_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, u8 *step, + u32 *delay) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; + u32 precommoncmdcnt; + struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; + u32 postcommoncmdcnt; + struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; + u32 rfdependcmdcnt; + struct swchnlcmd *currentcmd = NULL; + u8 rfpath; + u8 num_total_rfpath = rtlphy->num_total_rfpath; + + precommoncmdcnt = 0; + rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, + CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); + rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); + + postcommoncmdcnt = 0; + + rtl8723_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, + MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); + + rfdependcmdcnt = 0; + + RT_ASSERT((channel >= 1 && channel <= 14), + "illegal channel for Zebra: %d\n", channel); + + rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, + RF_CHNLBW, channel, 10); + + rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, + 0); + + do { + switch (*stage) { + case 0: + currentcmd = &precommoncmd[*step]; + break; + case 1: + currentcmd = &rfdependcmd[*step]; + break; + case 2: + currentcmd = &postcommoncmd[*step]; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Invalid 'stage' = %d, Check it!\n", *stage); + return true; + } + + if (currentcmd->cmdid == CMDID_END) { + if ((*stage) == 2) { + return true; + } else { + (*stage)++; + (*step) = 0; + continue; + } + } + + switch (currentcmd->cmdid) { + case CMDID_SET_TXPOWEROWER_LEVEL: + rtl8723e_phy_set_txpower_level(hw, channel); + break; + case CMDID_WRITEPORT_ULONG: + rtl_write_dword(rtlpriv, currentcmd->para1, + currentcmd->para2); + break; + case CMDID_WRITEPORT_USHORT: + rtl_write_word(rtlpriv, currentcmd->para1, + (u16) currentcmd->para2); + break; + case CMDID_WRITEPORT_UCHAR: + rtl_write_byte(rtlpriv, currentcmd->para1, + (u8) currentcmd->para2); + break; + case CMDID_RF_WRITEREG: + for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { + rtlphy->rfreg_chnlval[rfpath] = + ((rtlphy->rfreg_chnlval[rfpath] & + 0xfffffc00) | currentcmd->para2); + + rtl_set_rfreg(hw, (enum radio_path)rfpath, + currentcmd->para1, + RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[rfpath]); + } + _rtl8723e_phy_sw_rf_seting(hw, channel); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + + break; + } while (true); + + (*delay) = currentcmd->msdelay; + (*step)++; + return false; +} + +static u8 _rtl8723e_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) +{ + u32 reg_eac, reg_e94, reg_e9c, reg_ea4; + u8 result = 0x00; + + rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f); + rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f); + rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102); + rtl_set_bbreg(hw, 0xe3c, MASKDWORD, + config_pathb ? 0x28160202 : 0x28160502); + + if (config_pathb) { + rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22); + rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22); + rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102); + rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202); + } + + rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); + reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); + reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + + if (!(reg_eac & BIT(27)) && + (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_eac & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + return result; +} + +static u8 _rtl8723e_phy_path_b_iqk(struct ieee80211_hw *hw) +{ + u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; + u8 result = 0x00; + + rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002); + rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000); + mdelay(IQK_DELAY_TIME); + reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); + reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); + reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); + reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); + + if (!(reg_eac & BIT(31)) && + (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && + (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + if (!(reg_eac & BIT(30)) && + (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + return result; +} + +static bool _rtl8723e_phy_simularity_compare(struct ieee80211_hw *hw, + long result[][8], u8 c1, u8 c2) +{ + u32 i, j, diff, simularity_bitmap, bound; + + u8 final_candidate[2] = { 0xFF, 0xFF }; + bool bresult = true; + + bound = 4; + + simularity_bitmap = 0; + + for (i = 0; i < bound; i++) { + diff = (result[c1][i] > result[c2][i]) ? + (result[c1][i] - result[c2][i]) : + (result[c2][i] - result[c1][i]); + + if (diff > MAX_TOLERANCE) { + if ((i == 2 || i == 6) && !simularity_bitmap) { + if (result[c1][i] + result[c1][i + 1] == 0) + final_candidate[(i / 4)] = c2; + else if (result[c2][i] + result[c2][i + 1] == 0) + final_candidate[(i / 4)] = c1; + else + simularity_bitmap = simularity_bitmap | + (1 << i); + } else + simularity_bitmap = + simularity_bitmap | (1 << i); + } + } + + if (simularity_bitmap == 0) { + for (i = 0; i < (bound / 4); i++) { + if (final_candidate[i] != 0xFF) { + for (j = i * 4; j < (i + 1) * 4 - 2; j++) + result[3][j] = + result[final_candidate[i]][j]; + bresult = false; + } + } + return bresult; + } else if (!(simularity_bitmap & 0x0F)) { + for (i = 0; i < 4; i++) + result[3][i] = result[c1][i]; + return false; + } else { + return false; + } + +} + +static void _rtl8723e_phy_iq_calibrate(struct ieee80211_hw *hw, + long result[][8], u8 t, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 i; + u8 patha_ok, pathb_ok; + u32 adda_reg[IQK_ADDA_REG_NUM] = { + 0x85c, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec + }; + + u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { + 0x522, 0x550, 0x551, 0x040 + }; + + const u32 retrycount = 2; + + u32 bbvalue; + + if (t == 0) { + bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD); + + rtl8723_save_adda_registers(hw, adda_reg, + rtlphy->adda_backup, 16); + rtl8723_phy_save_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + } + rtl8723_phy_path_adda_on(hw, adda_reg, true, is2t); + if (t == 0) { + rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER1, + BIT(8)); + } + + if (!rtlphy->rfpi_enable) + rtl8723_phy_pi_mode_switch(hw, true); + if (t == 0) { + rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD); + rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD); + rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD); + } + rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); + rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); + rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); + if (is2t) { + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); + rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); + } + rtl8723_phy_mac_setting_calibration(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000); + if (is2t) + rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); + rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800); + for (i = 0; i < retrycount; i++) { + patha_ok = _rtl8723e_phy_path_a_iqk(hw, is2t); + if (patha_ok == 0x03) { + result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & + 0x3FF0000) >> 16; + break; + } else if (i == (retrycount - 1) && patha_ok == 0x01) + + result[t][0] = (rtl_get_bbreg(hw, 0xe94, + MASKDWORD) & 0x3FF0000) >> + 16; + result[t][1] = + (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16; + + } + + if (is2t) { + rtl8723_phy_path_a_standby(hw); + rtl8723_phy_path_adda_on(hw, adda_reg, false, is2t); + for (i = 0; i < retrycount; i++) { + pathb_ok = _rtl8723e_phy_path_b_iqk(hw); + if (pathb_ok == 0x03) { + result[t][4] = (rtl_get_bbreg(hw, + 0xeb4, + MASKDWORD) & + 0x3FF0000) >> 16; + result[t][5] = + (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][6] = + (rtl_get_bbreg(hw, 0xec4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][7] = + (rtl_get_bbreg(hw, 0xecc, MASKDWORD) & + 0x3FF0000) >> 16; + break; + } else if (i == (retrycount - 1) && pathb_ok == 0x01) { + result[t][4] = (rtl_get_bbreg(hw, + 0xeb4, + MASKDWORD) & + 0x3FF0000) >> 16; + } + result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & + 0x3FF0000) >> 16; + } + } + rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04); + rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874); + rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); + if (is2t) + rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); + if (t != 0) { + if (!rtlphy->rfpi_enable) + rtl8723_phy_pi_mode_switch(hw, false); + rtl8723_phy_reload_adda_registers(hw, adda_reg, + rtlphy->adda_backup, 16); + rtl8723_phy_reload_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + } +} + +static void _rtl8723e_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) +{ + u8 tmpreg; + u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + tmpreg = rtl_read_byte(rtlpriv, 0xd03); + + if ((tmpreg & 0x70) != 0) + rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); + else + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + + if ((tmpreg & 0x70) != 0) { + rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); + + if (is2t) + rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, + MASK12BITS); + + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, + (rf_a_mode & 0x8FFFF) | 0x10000); + + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + (rf_b_mode & 0x8FFFF) | 0x10000); + } + lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); + + rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); + + mdelay(100); + + if ((tmpreg & 0x70) != 0) { + rtl_write_byte(rtlpriv, 0xd03, tmpreg); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); + + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + rf_b_mode); + } else { + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + } +} + +static void _rtl8723e_phy_set_rfpath_switch(struct ieee80211_hw *hw, + bool bmain, bool is2t) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (is_hal_stop(rtlhal)) { + rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01); + rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); + } + if (is2t) { + if (bmain) + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(6), 0x1); + else + rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, + BIT(5) | BIT(6), 0x2); + } else { + if (bmain) + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2); + else + rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1); + + } + +} + +#undef IQK_ADDA_REG_NUM +#undef IQK_DELAY_TIME + +void rtl8723e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + long result[4][8]; + u8 i, final_candidate; + bool b_patha_ok, b_pathb_ok; + long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, + reg_ecc, reg_tmp = 0; + bool is12simular, is13simular, is23simular; + u32 iqk_bb_reg[10] = { + ROFDM0_XARXIQIMBALANCE, + ROFDM0_XBRXIQIMBALANCE, + ROFDM0_ECCATHRESHOLD, + ROFDM0_AGCRSSITABLE, + ROFDM0_XATXIQIMBALANCE, + ROFDM0_XBTXIQIMBALANCE, + ROFDM0_XCTXIQIMBALANCE, + ROFDM0_XCTXAFE, + ROFDM0_XDTXAFE, + ROFDM0_RXIQEXTANTA + }; + + if (b_recovery) { + rtl8723_phy_reload_adda_registers(hw, + iqk_bb_reg, + rtlphy->iqk_bb_backup, 10); + return; + } + for (i = 0; i < 8; i++) { + result[0][i] = 0; + result[1][i] = 0; + result[2][i] = 0; + result[3][i] = 0; + } + final_candidate = 0xff; + b_patha_ok = false; + b_pathb_ok = false; + is12simular = false; + is23simular = false; + is13simular = false; + for (i = 0; i < 3; i++) { + _rtl8723e_phy_iq_calibrate(hw, result, i, false); + if (i == 1) { + is12simular = + _rtl8723e_phy_simularity_compare(hw, result, 0, 1); + if (is12simular) { + final_candidate = 0; + break; + } + } + if (i == 2) { + is13simular = + _rtl8723e_phy_simularity_compare(hw, result, 0, 2); + if (is13simular) { + final_candidate = 0; + break; + } + is23simular = + _rtl8723e_phy_simularity_compare(hw, result, 1, 2); + if (is23simular) + final_candidate = 1; + else { + for (i = 0; i < 8; i++) + reg_tmp += result[3][i]; + + if (reg_tmp != 0) + final_candidate = 3; + else + final_candidate = 0xFF; + } + } + } + for (i = 0; i < 4; i++) { + reg_e94 = result[i][0]; + reg_e9c = result[i][1]; + reg_ea4 = result[i][2]; + reg_eac = result[i][3]; + reg_eb4 = result[i][4]; + reg_ebc = result[i][5]; + reg_ec4 = result[i][6]; + reg_ecc = result[i][7]; + } + if (final_candidate != 0xff) { + rtlphy->reg_e94 = reg_e94 = result[final_candidate][0]; + rtlphy->reg_e9c = reg_e9c = result[final_candidate][1]; + reg_ea4 = result[final_candidate][2]; + reg_eac = result[final_candidate][3]; + rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4]; + rtlphy->reg_ebc = reg_ebc = result[final_candidate][5]; + reg_ec4 = result[final_candidate][6]; + reg_ecc = result[final_candidate][7]; + b_patha_ok = true; + b_pathb_ok = true; + } else { + rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; + rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0; + } + if (reg_e94 != 0) + rtl8723_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result, + final_candidate, + (reg_ea4 == 0)); + rtl8723_save_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, 10); +} + +void rtl8723e_phy_lc_calibrate(struct ieee80211_hw *hw) +{ + _rtl8723e_phy_lc_calibrate(hw, false); +} + +void rtl8723e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) +{ + _rtl8723e_phy_set_rfpath_switch(hw, bmain, false); +} + +bool rtl8723e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + bool postprocessing = false; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "-->IO Cmd(%#x), set_io_inprogress(%d)\n", + iotype, rtlphy->set_io_inprogress); + do { + switch (iotype) { + case IO_CMD_RESUME_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Resume DM after scan.\n"); + postprocessing = true; + break; + case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Pause DM before scan.\n"); + postprocessing = true; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + } while (false); + if (postprocessing && !rtlphy->set_io_inprogress) { + rtlphy->set_io_inprogress = true; + rtlphy->current_io_type = iotype; + } else { + return false; + } + rtl8723e_phy_set_io(hw); + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); + return true; +} + +static void rtl8723e_phy_set_io(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "--->Cmd(%#x), set_io_inprogress(%d)\n", + rtlphy->current_io_type, rtlphy->set_io_inprogress); + switch (rtlphy->current_io_type) { + case IO_CMD_RESUME_DM_BY_SCAN: + dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; + rtl8723e_dm_write_dig(hw); + rtl8723e_phy_set_txpower_level(hw, rtlphy->current_channel); + break; + case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: + rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; + dm_digtable->cur_igvalue = 0x17; + rtl8723e_dm_write_dig(hw); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + rtlphy->set_io_inprogress = false; + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "(%#x)\n", rtlphy->current_io_type); +} + +static void rtl8723e_phy_set_rf_on(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); +} + +static void _rtl8723e_phy_set_rf_sleep(struct ieee80211_hw *hw) +{ + u32 u4b_tmp; + u8 delay = 5; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + while (u4b_tmp != 0 && delay > 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); + delay--; + } + if (delay == 0) { + rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "Switch RF timeout !!!.\n"); + return; + } + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); +} + +static bool _rtl8723e_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = true; + u8 i, queue_id; + struct rtl8192_tx_ring *ring = NULL; + + switch (rfpwr_state) { + case ERFON: + if ((ppsc->rfpwr_state == ERFOFF) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + bool rtstatus; + u32 initializecount = 0; + + do { + initializecount++; + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic enable\n"); + rtstatus = rtl_ps_enable_nic(hw); + } while (!rtstatus && (initializecount < 10)); + RT_CLEAR_PS_LEVEL(ppsc, + RT_RF_OFF_LEVL_HALT_NIC); + } else { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFON sleeped:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc-> + last_sleep_jiffies)); + ppsc->last_awake_jiffies = jiffies; + rtl8723e_phy_set_rf_on(hw); + } + if (mac->link_state == MAC80211_LINKED) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } + break; + case ERFOFF: + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic disable\n"); + rtl_ps_disable_nic(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } else { + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_POWER_OFF); + } + } + break; + case ERFSLEEP: + if (ppsc->rfpwr_state == ERFOFF) + break; + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (queue_id == BEACON_QUEUE || + skb_queue_len(&ring->queue) == 0) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", + (i + 1), queue_id, + skb_queue_len(&ring->queue)); + + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFSLEEP awaked:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc->last_awake_jiffies)); + ppsc->last_sleep_jiffies = jiffies; + _rtl8723e_phy_set_rf_sleep(hw); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + bresult = false; + break; + } + if (bresult) + ppsc->rfpwr_state = rfpwr_state; + return bresult; +} + +bool rtl8723e_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + bool bresult = false; + + if (rfpwr_state == ppsc->rfpwr_state) + return bresult; + bresult = _rtl8723e_phy_set_rf_power_state(hw, rfpwr_state); + return bresult; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h new file mode 100644 index 000000000000..b85f5c7c5c01 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.h @@ -0,0 +1,202 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL92C_PHY_H__ +#define __RTL92C_PHY_H__ + +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define MAX_DOZE_WAITING_TIMES_9x 64 + +#define RT_CANNOT_IO(hw) false +#define HIGHPOWER_RADIOA_ARRAYLEN 22 + +#define IQK_ADDA_REG_NUM 16 +#define MAX_TOLERANCE 5 +#define IQK_DELAY_TIME 1 + +#define APK_BB_REG_NUM 5 +#define APK_AFE_REG_NUM 16 +#define APK_CURVE_REG_NUM 4 +#define PATH_NUM 2 + +#define LOOP_LIMIT 5 +#define MAX_STALL_TIME 50 +#define ANTENNADIVERSITYVALUE 0x80 +#define MAX_TXPWR_IDX_NMODE_92S 63 +#define Reset_Cnt_Limit 3 + +#define IQK_ADDA_REG_NUM 16 +#define IQK_MAC_REG_NUM 4 + +#define IQK_DELAY_TIME 1 + +#define RF6052_MAX_PATH 2 + +#define CT_OFFSET_MAC_ADDR 0X16 + +#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A +#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 +#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 +#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 +#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C + +#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F +#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 + +#define CT_OFFSET_CHANNEL_PLAH 0x75 +#define CT_OFFSET_THERMAL_METER 0x78 +#define CT_OFFSET_RF_OPTION 0x79 +#define CT_OFFSET_VERSION 0x7E +#define CT_OFFSET_CUSTOMER_ID 0x7F + +#define RTL92C_MAX_PATH_NUM 2 + +enum hw90_block_e { + HW90_BLOCK_MAC = 0, + HW90_BLOCK_PHY0 = 1, + HW90_BLOCK_PHY1 = 2, + HW90_BLOCK_RF = 3, + HW90_BLOCK_MAXIMUM = 4, +}; + +enum baseband_config_type { + BASEBAND_CONFIG_PHY_REG = 0, + BASEBAND_CONFIG_AGC_TAB = 1, +}; + +enum ra_offset_area { + RA_OFFSET_LEGACY_OFDM1, + RA_OFFSET_LEGACY_OFDM2, + RA_OFFSET_HT_OFDM1, + RA_OFFSET_HT_OFDM2, + RA_OFFSET_HT_OFDM3, + RA_OFFSET_HT_OFDM4, + RA_OFFSET_HT_CCK, +}; + +enum antenna_path { + ANTENNA_NONE, + ANTENNA_D, + ANTENNA_C, + ANTENNA_CD, + ANTENNA_B, + ANTENNA_BD, + ANTENNA_BC, + ANTENNA_BCD, + ANTENNA_A, + ANTENNA_AD, + ANTENNA_AC, + ANTENNA_ACD, + ANTENNA_AB, + ANTENNA_ABD, + ANTENNA_ABC, + ANTENNA_ABCD +}; + +struct r_antenna_select_ofdm { + u32 r_tx_antenna:4; + u32 r_ant_l:4; + u32 r_ant_non_ht:4; + u32 r_ant_ht1:4; + u32 r_ant_ht2:4; + u32 r_ant_ht_s1:4; + u32 r_ant_non_ht_s1:4; + u32 ofdm_txsc:2; + u32 reserved:2; +}; + +struct r_antenna_select_cck { + u8 r_cckrx_enable_2:2; + u8 r_cckrx_enable:2; + u8 r_ccktx_enable:4; +}; + +struct efuse_contents { + u8 mac_addr[ETH_ALEN]; + u8 cck_tx_power_idx[6]; + u8 ht40_1s_tx_power_idx[6]; + u8 ht40_2s_tx_power_idx_diff[3]; + u8 ht20_tx_power_idx_diff[3]; + u8 ofdm_tx_power_idx_diff[3]; + u8 ht40_max_power_offset[3]; + u8 ht20_max_power_offset[3]; + u8 channel_plan; + u8 thermal_meter; + u8 rf_option[5]; + u8 version; + u8 oem_id; + u8 regulatory; +}; + +struct tx_power_struct { + u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 legacy_ht_txpowerdiff; + u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 pwrgroup_cnt; + u32 mcs_original_offset[4][16]; +}; + +u32 rtl8723e_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask); +void rtl8723e_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask, u32 data); +bool rtl8723e_phy_mac_config(struct ieee80211_hw *hw); +bool rtl8723e_phy_bb_config(struct ieee80211_hw *hw); +bool rtl8723e_phy_rf_config(struct ieee80211_hw *hw); +bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +void rtl8723e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl8723e_phy_get_txpower_level(struct ieee80211_hw *hw, + long *powerlevel); +void rtl8723e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +bool rtl8723e_phy_update_txpower_dbm(struct ieee80211_hw *hw, + long power_indbm); +void rtl8723e_phy_scan_operation_backup(struct ieee80211_hw *hw, + u8 operation); +void rtl8723e_phy_set_bw_mode_callback(struct ieee80211_hw *hw); +void rtl8723e_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); +void rtl8723e_phy_sw_chnl_callback(struct ieee80211_hw *hw); +u8 rtl8723e_phy_sw_chnl(struct ieee80211_hw *hw); +void rtl8723e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); +void rtl8723e_phy_lc_calibrate(struct ieee80211_hw *hw); +void rtl8723e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); +bool rtl8723e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +bool rtl8723e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); +bool rtl8723e_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c new file mode 100644 index 000000000000..2f7f81af8a55 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.c @@ -0,0 +1,112 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../pwrseqcmd.h" +#include "pwrseq.h" + +/* drivers should parse below arrays and do the corresponding actions */ +/*3 Power on Array*/ +struct wlan_pwr_cfg rtl8723A_power_on_flow + [RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8723A_TRANS_END_STEPS] = { + RTL8723A_TRANS_CARDEMU_TO_ACT + RTL8723A_TRANS_END +}; + +/*3Radio off GPIO Array */ +struct wlan_pwr_cfg rtl8723A_radio_off_flow + [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723A_TRANS_END_STEPS] = { + RTL8723A_TRANS_ACT_TO_CARDEMU + RTL8723A_TRANS_END +}; + +/*3Card Disable Array*/ +struct wlan_pwr_cfg rtl8723A_card_disable_flow + [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8723A_TRANS_END_STEPS] = { + RTL8723A_TRANS_ACT_TO_CARDEMU + RTL8723A_TRANS_CARDEMU_TO_CARDDIS + RTL8723A_TRANS_END +}; + +/*3 Card Enable Array*/ +struct wlan_pwr_cfg rtl8723A_card_enable_flow + [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8723A_TRANS_END_STEPS] = { + RTL8723A_TRANS_CARDDIS_TO_CARDEMU + RTL8723A_TRANS_CARDEMU_TO_ACT + RTL8723A_TRANS_END +}; + +/*3Suspend Array*/ +struct wlan_pwr_cfg rtl8723A_suspend_flow + [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8723A_TRANS_END_STEPS] = { + RTL8723A_TRANS_ACT_TO_CARDEMU + RTL8723A_TRANS_CARDEMU_TO_SUS + RTL8723A_TRANS_END +}; + +/*3 Resume Array*/ +struct wlan_pwr_cfg rtl8723A_resume_flow + [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8723A_TRANS_END_STEPS] = { + RTL8723A_TRANS_SUS_TO_CARDEMU + RTL8723A_TRANS_CARDEMU_TO_ACT + RTL8723A_TRANS_END +}; + +/*3HWPDN Array*/ +struct wlan_pwr_cfg rtl8723A_hwpdn_flow + [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8723A_TRANS_END_STEPS] = { + RTL8723A_TRANS_ACT_TO_CARDEMU + RTL8723A_TRANS_CARDEMU_TO_PDN + RTL8723A_TRANS_END +}; + +/*3 Enter LPS */ +struct wlan_pwr_cfg rtl8723A_enter_lps_flow + [RTL8723A_TRANS_ACT_TO_LPS_STEPS + + RTL8723A_TRANS_END_STEPS] = { + /*FW behavior*/ + RTL8723A_TRANS_ACT_TO_LPS + RTL8723A_TRANS_END +}; + +/*3 Leave LPS */ +struct wlan_pwr_cfg rtl8723A_leave_lps_flow + [RTL8723A_TRANS_LPS_TO_ACT_STEPS + + RTL8723A_TRANS_END_STEPS] = { + /*FW behavior*/ + RTL8723A_TRANS_LPS_TO_ACT + RTL8723A_TRANS_END +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h new file mode 100644 index 000000000000..4ac7db526f15 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h @@ -0,0 +1,340 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_PWRSEQ_H__ +#define __RTL8723E_PWRSEQ_H__ + +#include "../pwrseqcmd.h" +/* + * Check document WM-20110607-Paul-RTL8723A_Power_Architecture-R02.vsd + * There are 6 HW Power States: + * 0: POFF--Power Off + * 1: PDN--Power Down + * 2: CARDEMU--Card Emulation + * 3: ACT--Active Mode + * 4: LPS--Low Power State + * 5: SUS--Suspend + * + * The transision from different states are defined below + * TRANS_CARDEMU_TO_ACT + * TRANS_ACT_TO_CARDEMU + * TRANS_CARDEMU_TO_SUS + * TRANS_SUS_TO_CARDEMU + * TRANS_CARDEMU_TO_PDN + * TRANS_ACT_TO_LPS + * TRANS_LPS_TO_ACT + * + * TRANS_END + */ + +#define RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS 10 +#define RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS 10 +#define RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS 10 +#define RTL8723A_TRANS_SUS_TO_CARDEMU_STEPS 10 +#define RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS 10 +#define RTL8723A_TRANS_PDN_TO_CARDEMU_STEPS 10 +#define RTL8723A_TRANS_ACT_TO_LPS_STEPS 15 +#define RTL8723A_TRANS_LPS_TO_ACT_STEPS 15 +#define RTL8723A_TRANS_END_STEPS 1 + +/* format */ +/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }*/ + +#define RTL8723A_TRANS_CARDEMU_TO_ACT \ + /* disable SW LPS 0x04[10]=0*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), 0},\ + /* wait till 0x04[17] = 1 power ready*/ \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)},\ + /* release WLON reset 0x04[16]=1*/ \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},\ + /* disable HWPDN 0x04[15]=0*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},\ + /* disable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT(4)|BIT(3)), 0},\ + /* polling until return 0*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},\ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0}, + +/* format */ +/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ + +#define RTL8723A_TRANS_ACT_TO_CARDEMU \ + /*0x1F[7:0] = 0 turn off RF*/ \ + {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, \ + {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},\ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, + +/* format */ +/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/ +#define RTL8723A_TRANS_CARDEMU_TO_SUS \ + /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, \ + BIT(4)|BIT(3), (BIT(4)|BIT(3))},\ +/*0x04[12:11] = 2b'01 enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK| \ + PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, \ + PWR_CMD_WRITE, \ + BIT(3)|BIT(4), BIT(3)}, \ +/*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, \ + PWR_CMD_WRITE, BIT(3)|BIT(4), \ + BIT(3)|BIT(4)}, \ +/*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ + PWR_CMD_WRITE, BIT(0), BIT(0)}, \ +/*wait power state to suspend*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ + PWR_CMD_POLLING, BIT(1), 0}, + +/* format */ +/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ + +#define RTL8723A_TRANS_SUS_TO_CARDEMU \ + /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0},\ + /*wait power state to suspend*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)},\ + /*0x04[12:11] = 2b'01enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, + +/* format */ +/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ + +#define RTL8723A_TRANS_CARDEMU_TO_CARDDIS \ + /*0x04[12:11] = 2b'01 enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \ +/*0x04[10] = 1, enable SW LPS*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(2), BIT(2)}, \ +/*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ + PWR_CMD_WRITE, BIT(0), BIT(0)}, \ + /*wait power state to suspend*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ + PWR_CMD_POLLING, BIT(1), 0}, + +/* format */ +/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ + +#define RTL8723A_TRANS_CARDDIS_TO_CARDEMU\ +/*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ + PWR_CMD_WRITE, BIT(0), 0}, \ + /*wait power state to suspend*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ + PWR_CMD_POLLING, BIT(1), BIT(1)},\ + /*0x04[12:11] = 2b'00enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(3)|BIT(4), 0},\ +/*PCIe DMA start*/ \ + {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, 0xFF, 0}, + +/* format */ +/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ +#define RTL8723A_TRANS_CARDEMU_TO_PDN \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(0), 0},/* 0x04[16] = 0*/\ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(7), BIT(7)},/* 0x04[15] = 1*/ + +/* format */ +/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ +#define RTL8723A_TRANS_PDN_TO_CARDEMU \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(7), 0},/* 0x04[15] = 0*/ + +/* format */ +/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ + +#define RTL8723A_TRANS_ACT_TO_LPS \ + {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, 0xFF, 0xFF},/*PCIe DMA stop*/ \ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, 0xFF, 0x7F},/*Tx Pause*/ \ + /*Should be zero if no packet is transmitting*/ \ + {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_POLLING, 0xFF, 0},\ + /*Should be zero if no packet is transmitting*/ \ + {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_POLLING, 0xFF, 0},\ + /*Should be zero if no packet is transmitting*/ \ + {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_POLLING, 0xFF, 0},\ + /*Should be zero if no packet is transmitting*/ \ + {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_POLLING, 0xFF, 0},\ + /*CCK and OFDM are disabled,and clock are gated*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(0), 0},\ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US},/*Delay 1us*/\ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(1), 0},/*Whole BB is reset*/ \ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, 0xFF, 0x3F},/*Reset MAC TRX*/ \ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(1), 0},/*check if removed later*/ \ + /*Respond TxOK to scheduler*/ \ + {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(5), BIT(5)},\ + +#define RTL8723A_TRANS_LPS_TO_ACT\ +/* format */ \ +/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ \ + {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ + PWR_CMD_WRITE, 0xFF, 0x84}, /*SDIO RPWM*/\ + {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/\ + {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, 0xFF, 0x84}, /*PCIe RPWM*/\ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/\ + /*. 0x08[4] = 0 switch TSF to 40M*/\ + {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(4), 0}, \ + /*Polling 0x109[7]=0 TSF in 40M*/\ + {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_POLLING, BIT(7), 0}, \ + /*. 0x29[7:6] = 2b'00 enable BB clock*/\ + {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(6)|BIT(7), 0},\ + /*. 0x101[1] = 1*/\ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(1), BIT(1)},\ + /*. 0x100[7:0] = 0xFF enable WMAC TRX*/\ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, 0xFF, 0xFF},\ + /*. 0x02[1:0] = 2b'11 enable BB macro*/\ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, BIT(1)|BIT(0), BIT(1)|BIT(0)},\ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ + PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/ + +/* format */ +/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ + +#define RTL8723A_TRANS_END \ + {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + 0, PWR_CMD_END, 0, 0} + +extern struct wlan_pwr_cfg rtl8723A_power_on_flow + [RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8723A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723A_radio_off_flow + [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723A_card_disable_flow + [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8723A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723A_card_enable_flow + [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8723A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723A_suspend_flow + [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8723A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723A_resume_flow + [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8723A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723A_hwpdn_flow + [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8723A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723A_enter_lps_flow + [RTL8723A_TRANS_ACT_TO_LPS_STEPS + RTL8723A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723A_leave_lps_flow + [RTL8723A_TRANS_LPS_TO_ACT_STEPS + RTL8723A_TRANS_END_STEPS]; + +/* RTL8723 Power Configuration CMDs for PCIe interface */ +#define Rtl8723_NIC_PWR_ON_FLOW rtl8723A_power_on_flow +#define Rtl8723_NIC_RF_OFF_FLOW rtl8723A_radio_off_flow +#define Rtl8723_NIC_DISABLE_FLOW rtl8723A_card_disable_flow +#define Rtl8723_NIC_ENABLE_FLOW rtl8723A_card_enable_flow +#define Rtl8723_NIC_SUSPEND_FLOW rtl8723A_suspend_flow +#define Rtl8723_NIC_RESUME_FLOW rtl8723A_resume_flow +#define Rtl8723_NIC_PDN_FLOW rtl8723A_hwpdn_flow +#define Rtl8723_NIC_LPS_ENTER_FLOW rtl8723A_enter_lps_flow +#define Rtl8723_NIC_LPS_LEAVE_FLOW rtl8723A_leave_lps_flow + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h new file mode 100644 index 000000000000..306059f9b9cc --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/reg.h @@ -0,0 +1,2120 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_REG_H__ +#define __RTL8723E_REG_H__ + +#define REG_SYS_ISO_CTRL 0x0000 +#define REG_SYS_FUNC_EN 0x0002 +#define REG_APS_FSMCO 0x0004 +#define REG_SYS_CLKR 0x0008 +#define REG_9346CR 0x000A +#define REG_EE_VPD 0x000C +#define REG_AFE_MISC 0x0010 +#define REG_SPS0_CTRL 0x0011 +#define REG_SPS_OCP_CFG 0x0018 +#define REG_RSV_CTRL 0x001C +#define REG_RF_CTRL 0x001F +#define REG_LDOA15_CTRL 0x0020 +#define REG_LDOV12D_CTRL 0x0021 +#define REG_LDOHCI12_CTRL 0x0022 +#define REG_LPLDO_CTRL 0x0023 +#define REG_AFE_XTAL_CTRL 0x0024 +#define REG_AFE_PLL_CTRL 0x0028 +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define REG_PWR_DATA 0x0038 +#define REG_CAL_TIMER 0x003C +#define REG_ACLK_MON 0x003E +#define REG_GPIO_MUXCFG 0x0040 +#define REG_GPIO_IO_SEL 0x0042 +#define REG_MAC_PINMUX_CFG 0x0043 +#define REG_GPIO_PIN_CTRL 0x0044 +#define REG_GPIO_INTM 0x0048 +#define REG_LEDCFG0 0x004C +#define REG_LEDCFG1 0x004D +#define REG_LEDCFG2 0x004E +#define REG_LEDCFG3 0x004F +#define REG_FSIMR 0x0050 +#define REG_FSISR 0x0054 +#define REG_GPIO_PIN_CTRL_2 0x0060 +#define REG_GPIO_IO_SEL_2 0x0062 +#define REG_MULTI_FUNC_CTRL 0x0068 + +#define REG_MCUFWDL 0x0080 + +#define REG_HMEBOX_EXT_0 0x0088 +#define REG_HMEBOX_EXT_1 0x008A +#define REG_HMEBOX_EXT_2 0x008C +#define REG_HMEBOX_EXT_3 0x008E + +#define REG_BIST_SCAN 0x00D0 +#define REG_BIST_RPT 0x00D4 +#define REG_BIST_ROM_RPT 0x00D8 +#define REG_USB_SIE_INTF 0x00E0 +#define REG_PCIE_MIO_INTF 0x00E4 +#define REG_PCIE_MIO_INTD 0x00E8 +#define REG_SYS_CFG 0x00F0 +#define REG_GPIO_OUTSTS 0x00F4 + +#define REG_CR 0x0100 +#define REG_PBP 0x0104 +#define REG_TRXDMA_CTRL 0x010C +#define REG_TRXFF_BNDY 0x0114 +#define REG_TRXFF_STATUS 0x0118 +#define REG_RXFF_PTR 0x011C +#define REG_HIMR 0x0120 +#define REG_HISR 0x0124 +#define REG_HIMRE 0x0128 +#define REG_HISRE 0x012C +#define REG_CPWM 0x012F +#define REG_FWIMR 0x0130 +#define REG_FWISR 0x0134 +#define REG_PKTBUF_DBG_CTRL 0x0140 +#define REG_PKTBUF_DBG_DATA_L 0x0144 +#define REG_PKTBUF_DBG_DATA_H 0x0148 + +#define REG_TC0_CTRL 0x0150 +#define REG_TC1_CTRL 0x0154 +#define REG_TC2_CTRL 0x0158 +#define REG_TC3_CTRL 0x015C +#define REG_TC4_CTRL 0x0160 +#define REG_TCUNIT_BASE 0x0164 +#define REG_MBIST_START 0x0174 +#define REG_MBIST_DONE 0x0178 +#define REG_MBIST_FAIL 0x017C +#define REG_C2HEVT_MSG_NORMAL 0x01A0 +#define REG_C2HEVT_MSG_TEST 0x01B8 +#define REG_MCUTST_1 0x01c0 +#define REG_FMETHR 0x01C8 +#define REG_HMETFR 0x01CC +#define REG_HMEBOX_0 0x01D0 +#define REG_HMEBOX_1 0x01D4 +#define REG_HMEBOX_2 0x01D8 +#define REG_HMEBOX_3 0x01DC + +#define REG_LLT_INIT 0x01E0 +#define REG_BB_ACCEESS_CTRL 0x01E8 +#define REG_BB_ACCESS_DATA 0x01EC + +#define REG_RQPN 0x0200 +#define REG_FIFOPAGE 0x0204 +#define REG_TDECTRL 0x0208 +#define REG_TXDMA_OFFSET_CHK 0x020C +#define REG_TXDMA_STATUS 0x0210 +#define REG_RQPN_NPQ 0x0214 + +#define REG_RXDMA_AGG_PG_TH 0x0280 +#define REG_RXPKT_NUM 0x0284 +#define REG_RXDMA_STATUS 0x0288 + +#define REG_PCIE_CTRL_REG 0x0300 +#define REG_INT_MIG 0x0304 +#define REG_BCNQ_DESA 0x0308 +#define REG_HQ_DESA 0x0310 +#define REG_MGQ_DESA 0x0318 +#define REG_VOQ_DESA 0x0320 +#define REG_VIQ_DESA 0x0328 +#define REG_BEQ_DESA 0x0330 +#define REG_BKQ_DESA 0x0338 +#define REG_RX_DESA 0x0340 +#define REG_DBI 0x0348 +#define REG_MDIO 0x0354 +#define REG_DBG_SEL 0x0360 +#define REG_PCIE_HRPWM 0x0361 +#define REG_PCIE_HCPWM 0x0363 +#define REG_UART_CTRL 0x0364 +#define REG_UART_TX_DESA 0x0370 +#define REG_UART_RX_DESA 0x0378 + +#define REG_HDAQ_DESA_NODEF 0x0000 +#define REG_CMDQ_DESA_NODEF 0x0000 + +#define REG_VOQ_INFORMATION 0x0400 +#define REG_VIQ_INFORMATION 0x0404 +#define REG_BEQ_INFORMATION 0x0408 +#define REG_BKQ_INFORMATION 0x040C +#define REG_MGQ_INFORMATION 0x0410 +#define REG_HGQ_INFORMATION 0x0414 +#define REG_BCNQ_INFORMATION 0x0418 + +#define REG_CPU_MGQ_INFORMATION 0x041C +#define REG_FWHW_TXQ_CTRL 0x0420 +#define REG_HWSEQ_CTRL 0x0423 +#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 +#define REG_TXPKTBUF_MGQ_BDNY 0x0425 +#define REG_MULTI_BCNQ_EN 0x0426 +#define REG_MULTI_BCNQ_OFFSET 0x0427 +#define REG_SPEC_SIFS 0x0428 +#define REG_RL 0x042A +#define REG_DARFRC 0x0430 +#define REG_RARFRC 0x0438 +#define REG_RRSR 0x0440 +#define REG_ARFR0 0x0444 +#define REG_ARFR1 0x0448 +#define REG_ARFR2 0x044C +#define REG_ARFR3 0x0450 +#define REG_AGGLEN_LMT 0x0458 +#define REG_AMPDU_MIN_SPACE 0x045C +#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D +#define REG_FAST_EDCA_CTRL 0x0460 +#define REG_RD_RESP_PKT_TH 0x0463 +#define REG_INIRTS_RATE_SEL 0x0480 +#define REG_INIDATA_RATE_SEL 0x0484 +#define REG_POWER_STATUS 0x04A4 +#define REG_POWER_STAGE1 0x04B4 +#define REG_POWER_STAGE2 0x04B8 +#define REG_PKT_LIFE_TIME 0x04C0 +#define REG_STBC_SETTING 0x04C4 +#define REG_PROT_MODE_CTRL 0x04C8 +#define REG_BAR_MODE_CTRL 0x04CC +#define REG_RA_TRY_RATE_AGG_LMT 0x04CF +#define REG_NQOS_SEQ 0x04DC +#define REG_QOS_SEQ 0x04DE +#define REG_NEED_CPU_HANDLE 0x04E0 +#define REG_PKT_LOSE_RPT 0x04E1 +#define REG_PTCL_ERR_STATUS 0x04E2 +#define REG_DUMMY 0x04FC + +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050C +#define REG_BCNTCFG 0x0510 +#define REG_PIFS 0x0512 +#define REG_RDG_PIFS 0x0513 +#define REG_SIFS_CTX 0x0514 +#define REG_SIFS_TRX 0x0516 +#define REG_AGGR_BREAK_TIME 0x051A +#define REG_SLOT 0x051B +#define REG_TX_PTCL_CTRL 0x0520 +#define REG_TXPAUSE 0x0522 +#define REG_DIS_TXREQ_CLR 0x0523 +#define REG_RD_CTRL 0x0524 +#define REG_TBTT_PROHIBIT 0x0540 +#define REG_RD_NAV_NXT 0x0544 +#define REG_NAV_PROT_LEN 0x0546 +#define REG_BCN_CTRL 0x0550 +#define REG_USTIME_TSF 0x0551 +#define REG_MBID_NUM 0x0552 +#define REG_DUAL_TSF_RST 0x0553 +#define REG_BCN_INTERVAL 0x0554 +#define REG_MBSSID_BCN_SPACE 0x0554 +#define REG_DRVERLYINT 0x0558 +#define REG_BCNDMATIM 0x0559 +#define REG_ATIMWND 0x055A +#define REG_BCN_MAX_ERR 0x055D +#define REG_RXTSF_OFFSET_CCK 0x055E +#define REG_RXTSF_OFFSET_OFDM 0x055F +#define REG_TSFTR 0x0560 +#define REG_INIT_TSFTR 0x0564 +#define REG_PSTIMER 0x0580 +#define REG_TIMER0 0x0584 +#define REG_TIMER1 0x0588 +#define REG_ACMHWCTRL 0x05C0 +#define REG_ACMRSTCTRL 0x05C1 +#define REG_ACMAVG 0x05C2 +#define REG_VO_ADMTIME 0x05C4 +#define REG_VI_ADMTIME 0x05C6 +#define REG_BE_ADMTIME 0x05C8 +#define REG_EDCA_RANDOM_GEN 0x05CC +#define REG_SCH_TXCMD 0x05D0 + +#define REG_APSD_CTRL 0x0600 +#define REG_BWOPMODE 0x0603 +#define REG_TCR 0x0604 +#define REG_RCR 0x0608 +#define REG_RX_PKT_LIMIT 0x060C +#define REG_RX_DLK_TIME 0x060D +#define REG_RX_DRVINFO_SZ 0x060F + +#define REG_MACID 0x0610 +#define REG_BSSID 0x0618 +#define REG_MAR 0x0620 +#define REG_MBIDCAMCFG 0x0628 + +#define REG_USTIME_EDCA 0x0638 +#define REG_MAC_SPEC_SIFS 0x063A +#define REG_RESP_SIFS_CCK 0x063C +#define REG_RESP_SIFS_OFDM 0x063E +#define REG_ACKTO 0x0640 +#define REG_CTS2TO 0x0641 +#define REG_EIFS 0x0642 + +#define REG_NAV_CTRL 0x0650 +#define REG_BACAMCMD 0x0654 +#define REG_BACAMCONTENT 0x0658 +#define REG_LBDLY 0x0660 +#define REG_FWDLY 0x0661 +#define REG_RXERR_RPT 0x0664 +#define REG_WMAC_TRXPTCL_CTL 0x0668 + +#define REG_CAMCMD 0x0670 +#define REG_CAMWRITE 0x0674 +#define REG_CAMREAD 0x0678 +#define REG_CAMDBG 0x067C +#define REG_SECCFG 0x0680 + +#define REG_WOW_CTRL 0x0690 +#define REG_PSSTATUS 0x0691 +#define REG_PS_RX_INFO 0x0692 +#define REG_LPNAV_CTRL 0x0694 +#define REG_WKFMCAM_CMD 0x0698 +#define REG_WKFMCAM_RWD 0x069C +#define REG_RXFLTMAP0 0x06A0 +#define REG_RXFLTMAP1 0x06A2 +#define REG_RXFLTMAP2 0x06A4 +#define REG_BCN_PSR_RPT 0x06A8 +#define REG_CALB32K_CTRL 0x06AC +#define REG_PKT_MON_CTRL 0x06B4 +#define REG_BT_COEX_TABLE 0x06C0 +#define REG_WMAC_RESP_TXINFO 0x06D8 + +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_TEST_USB_TXQS 0xFE48 +#define REG_TEST_SIE_VID 0xFE60 +#define REG_TEST_SIE_PID 0xFE62 +#define REG_TEST_SIE_OPTIONAL 0xFE64 +#define REG_TEST_SIE_CHIRP_K 0xFE65 +#define REG_TEST_SIE_PHY 0xFE66 +#define REG_TEST_SIE_MAC_ADDR 0xFE70 +#define REG_TEST_SIE_STRING 0xFE80 + +#define REG_NORMAL_SIE_VID 0xFE60 +#define REG_NORMAL_SIE_PID 0xFE62 +#define REG_NORMAL_SIE_OPTIONAL 0xFE64 +#define REG_NORMAL_SIE_EP 0xFE65 +#define REG_NORMAL_SIE_PHY 0xFE68 +#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 +#define REG_NORMAL_SIE_STRING 0xFE80 + +#define CR9346 REG_9346CR +#define MSR (REG_CR + 2) +#define ISR REG_HISR +#define TSFR REG_TSFTR + +#define MACIDR0 REG_MACID +#define MACIDR4 (REG_MACID + 4) + +#define PBP REG_PBP + +#define IDR0 MACIDR0 +#define IDR4 MACIDR4 + +#define UNUSED_REGISTER 0x1BF +#define DCAM UNUSED_REGISTER +#define PSR UNUSED_REGISTER +#define BBADDR UNUSED_REGISTER +#define PHYDATAR UNUSED_REGISTER + +#define INVALID_BBRF_VALUE 0x12345678 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define CMDEEPROM_EN BIT(5) +#define CMDEEPROM_SEL BIT(4) +#define CMD9346CR_9356SEL BIT(4) +#define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL) +#define AUTOLOAD_EFUSE CMDEEPROM_EN + +#define GPIOSEL_GPIO 0 +#define GPIOSEL_ENBT BIT(5) + +#define GPIO_IN REG_GPIO_PIN_CTRL +#define GPIO_OUT (REG_GPIO_PIN_CTRL+1) +#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) +#define GPIO_MOD (REG_GPIO_PIN_CTRL+3) + +#define MSR_NOLINK 0x00 +#define MSR_ADHOC 0x01 +#define MSR_INFRA 0x02 +#define MSR_AP 0x03 + +#define RRSR_RSC_OFFSET 21 +#define RRSR_SHORT_OFFSET 23 +#define RRSR_RSC_BW_40M 0x600000 +#define RRSR_RSC_UPSUBCHNL 0x400000 +#define RRSR_RSC_LOWSUBCHNL 0x200000 +#define RRSR_SHORT 0x800000 +#define RRSR_1M BIT(0) +#define RRSR_2M BIT(1) +#define RRSR_5_5M BIT(2) +#define RRSR_11M BIT(3) +#define RRSR_6M BIT(4) +#define RRSR_9M BIT(5) +#define RRSR_12M BIT(6) +#define RRSR_18M BIT(7) +#define RRSR_24M BIT(8) +#define RRSR_36M BIT(9) +#define RRSR_48M BIT(10) +#define RRSR_54M BIT(11) +#define RRSR_MCS0 BIT(12) +#define RRSR_MCS1 BIT(13) +#define RRSR_MCS2 BIT(14) +#define RRSR_MCS3 BIT(15) +#define RRSR_MCS4 BIT(16) +#define RRSR_MCS5 BIT(17) +#define RRSR_MCS6 BIT(18) +#define RRSR_MCS7 BIT(19) +#define BRSR_ACKSHORTPMB BIT(23) + +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 + +#define RATE_1M BIT(0) +#define RATE_2M BIT(1) +#define RATE_5_5M BIT(2) +#define RATE_11M BIT(3) +#define RATE_6M BIT(4) +#define RATE_9M BIT(5) +#define RATE_12M BIT(6) +#define RATE_18M BIT(7) +#define RATE_24M BIT(8) +#define RATE_36M BIT(9) +#define RATE_48M BIT(10) +#define RATE_54M BIT(11) +#define RATE_MCS0 BIT(12) +#define RATE_MCS1 BIT(13) +#define RATE_MCS2 BIT(14) +#define RATE_MCS3 BIT(15) +#define RATE_MCS4 BIT(16) +#define RATE_MCS5 BIT(17) +#define RATE_MCS6 BIT(18) +#define RATE_MCS7 BIT(19) +#define RATE_MCS8 BIT(20) +#define RATE_MCS9 BIT(21) +#define RATE_MCS10 BIT(22) +#define RATE_MCS11 BIT(23) +#define RATE_MCS12 BIT(24) +#define RATE_MCS13 BIT(25) +#define RATE_MCS14 BIT(26) +#define RATE_MCS15 BIT(27) + +#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) +#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\ + RATR_24M | RATR_36M | RATR_48M | RATR_54M) +#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 |\ + RATR_MCS3 | RATR_MCS4 | RATR_MCS5 |\ + RATR_MCS6 | RATR_MCS7) +#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 |\ + RATR_MCS11 | RATR_MCS12 | RATR_MCS13 |\ + RATR_MCS14 | RATR_MCS15) + +#define BW_OPMODE_20MHZ BIT(2) +#define BW_OPMODE_5G BIT(1) +#define BW_OPMODE_11J BIT(0) + +#define CAM_VALID BIT(15) +#define CAM_NOTVALID 0x0000 +#define CAM_USEDK BIT(5) + +#define CAM_NONE 0x0 +#define CAM_WEP40 0x01 +#define CAM_TKIP 0x02 +#define CAM_AES 0x04 +#define CAM_WEP104 0x05 + +#define TOTAL_CAM_ENTRY 32 +#define HALF_CAM_ENTRY 16 + +#define CAM_WRITE BIT(16) +#define CAM_READ 0x00000000 +#define CAM_POLLINIG BIT(31) + +#define SCR_USEDK 0x01 +#define SCR_TXSEC_ENABLE 0x02 +#define SCR_RXSEC_ENABLE 0x04 + +#define WOW_PMEN BIT(0) +#define WOW_WOMEN BIT(1) +#define WOW_MAGIC BIT(2) +#define WOW_UWF BIT(3) + +#define IMR8190_DISABLED 0x0 +#define IMR_BCNDMAINT6 BIT(31) +#define IMR_BCNDMAINT5 BIT(30) +#define IMR_BCNDMAINT4 BIT(29) +#define IMR_BCNDMAINT3 BIT(28) +#define IMR_BCNDMAINT2 BIT(27) +#define IMR_BCNDMAINT1 BIT(26) +#define IMR_BCNDOK8 BIT(25) +#define IMR_BCNDOK7 BIT(24) +#define IMR_BCNDOK6 BIT(23) +#define IMR_BCNDOK5 BIT(22) +#define IMR_BCNDOK4 BIT(21) +#define IMR_BCNDOK3 BIT(20) +#define IMR_BCNDOK2 BIT(19) +#define IMR_BCNDOK1 BIT(18) +#define IMR_TIMEOUT2 BIT(17) +#define IMR_TIMEOUT1 BIT(16) +#define IMR_TXFOVW BIT(15) +#define IMR_PSTIMEOUT BIT(14) +#define IMR_BCNINT BIT(13) +#define IMR_RXFOVW BIT(12) +#define IMR_RDU BIT(11) +#define IMR_ATIMEND BIT(10) +#define IMR_BDOK BIT(9) +#define IMR_HIGHDOK BIT(8) +#define IMR_TBDOK BIT(7) +#define IMR_MGNTDOK BIT(6) +#define IMR_TBDER BIT(5) +#define IMR_BKDOK BIT(4) +#define IMR_BEDOK BIT(3) +#define IMR_VIDOK BIT(2) +#define IMR_VODOK BIT(1) +#define IMR_ROK BIT(0) + +#define IMR_TXERR BIT(11) +#define IMR_RXERR BIT(10) +#define IMR_CPWM BIT(8) +#define IMR_OCPINT BIT(1) +#define IMR_WLANOFF BIT(0) + +/* 8723E series PCIE Host IMR/ISR bit */ +/* IMR DW0 Bit 0-31 */ +#define PHIMR_TIMEOUT2 BIT(31) +#define PHIMR_TIMEOUT1 BIT(30) +#define PHIMR_PSTIMEOUT BIT(29) +#define PHIMR_GTINT4 BIT(28) +#define PHIMR_GTINT3 BIT(27) +#define PHIMR_TXBCNERR BIT(26) +#define PHIMR_TXBCNOK BIT(25) +#define PHIMR_TSF_BIT32_TOGGLE BIT(24) +#define PHIMR_BCNDMAINT3 BIT(23) +#define PHIMR_BCNDMAINT2 BIT(22) +#define PHIMR_BCNDMAINT1 BIT(21) +#define PHIMR_BCNDMAINT0 BIT(20) +#define PHIMR_BCNDOK3 BIT(19) +#define PHIMR_BCNDOK2 BIT(18) +#define PHIMR_BCNDOK1 BIT(17) +#define PHIMR_BCNDOK0 BIT(16) +#define PHIMR_HSISR_IND_ON BIT(15) +#define PHIMR_BCNDMAINT_E BIT(14) +#define PHIMR_ATIMEND_E BIT(13) +#define PHIMR_ATIM_CTW_END BIT(12) +#define PHIMR_HISRE_IND BIT(11) +#define PHIMR_C2HCMD BIT(10) +#define PHIMR_CPWM2 BIT(9) +#define PHIMR_CPWM BIT(8) +#define PHIMR_HIGHDOK BIT(7) +#define PHIMR_MGNTDOK BIT(6) +#define PHIMR_BKDOK BIT(5) +#define PHIMR_BEDOK BIT(4) +#define PHIMR_VIDOK BIT(3) +#define PHIMR_VODOK BIT(2) +#define PHIMR_RDU BIT(1) +#define PHIMR_ROK BIT(0) + +/* PCIE Host Interrupt Status Extension bit */ +#define PHIMR_BCNDMAINT7 BIT(23) +#define PHIMR_BCNDMAINT6 BIT(22) +#define PHIMR_BCNDMAINT5 BIT(21) +#define PHIMR_BCNDMAINT4 BIT(20) +#define PHIMR_BCNDOK7 BIT(19) +#define PHIMR_BCNDOK6 BIT(18) +#define PHIMR_BCNDOK5 BIT(17) +#define PHIMR_BCNDOK4 BIT(16) +/* bit12-15: RSVD */ +#define PHIMR_TXERR BIT(11) +#define PHIMR_RXERR BIT(10) +#define PHIMR_TXFOVW BIT(9) +#define PHIMR_RXFOVW BIT(8) +/* bit2-7: RSVD */ +#define PHIMR_OCPINT BIT(1) + +#define HWSET_MAX_SIZE 256 +#define EFUSE_MAX_SECTION 32 +#define EFUSE_REAL_CONTENT_LEN 512 +#define EFUSE_OOB_PROTECT_BYTES 15 + +#define EEPROM_DEFAULT_TSSI 0x0 +#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_BOARDTYPE 0x02 +#define EEPROM_DEFAULT_TXPOWER 0x1010 +#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 + +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_THERMALMETER 0x12 +#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 +#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 +#define EEPROM_DEFAULT_HT20_DIFF 2 +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 +#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 + +#define EEPROM_DEFAULT_PID 0x1234 +#define EEPROM_DEFAULT_VID 0x5678 +#define EEPROM_DEFAULT_CUSTOMERID 0xAB +#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD +#define EEPROM_DEFAULT_VERSION 0 + +#define EEPROM_CHANNEL_PLAN_FCC 0x0 +#define EEPROM_CHANNEL_PLAN_IC 0x1 +#define EEPROM_CHANNEL_PLAN_ETSI 0x2 +#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 +#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 +#define EEPROM_CHANNEL_PLAN_MKK 0x5 +#define EEPROM_CHANNEL_PLAN_MKK1 0x6 +#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 +#define EEPROM_CHANNEL_PLAN_TELEC 0x8 +#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 +#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA +#define EEPROM_CHANNEL_PLAN_NCC 0xB +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + +#define EEPROM_CID_DEFAULT 0x0 +#define EEPROM_CID_TOSHIBA 0x4 +#define EEPROM_CID_CCX 0x10 +#define EEPROM_CID_QMI 0x0D +#define EEPROM_CID_WHQL 0xFE + +#define RTL8192_EEPROM_ID 0x8129 + +#define RTL8190_EEPROM_ID 0x8129 +#define EEPROM_HPON 0x02 +#define EEPROM_CLK 0x06 +#define EEPROM_TESTR 0x08 + +#define EEPROM_VID 0x49 +#define EEPROM_DID 0x4B +#define EEPROM_SVID 0x4D +#define EEPROM_SMID 0x4F + +#define EEPROM_MAC_ADDR 0x67 + +#define EEPROM_CCK_TX_PWR_INX 0x5A +#define EEPROM_HT40_1S_TX_PWR_INX 0x60 +#define EEPROM_HT40_2S_TX_PWR_INX_DIFF 0x66 +#define EEPROM_HT20_TX_PWR_INX_DIFF 0x69 +#define EEPROM_OFDM_TX_PWR_INX_DIFF 0x6C +#define EEPROM_HT40_MAX_PWR_OFFSET 0x25 +#define EEPROM_HT20_MAX_PWR_OFFSET 0x22 + +#define EEPROM_THERMAL_METER 0x2a +#define EEPROM_XTAL_K 0x78 +#define EEPROM_RF_OPT1 0x79 +#define EEPROM_RF_OPT2 0x7A +#define EEPROM_RF_OPT3 0x7B +#define EEPROM_RF_OPT4 0x7C +#define EEPROM_CHANNEL_PLAN 0x28 +#define EEPROM_VERSION 0x30 +#define EEPROM_CUSTOMER_ID 0x31 + +#define EEPROM_PWRDIFF 0x54 + +#define EEPROM_TXPOWERCCK 0x10 +#define EEPROM_TXPOWERHT40_1S 0x16 +#define EEPROM_TXPOWERHT40_2SDIFF 0x66 +#define EEPROM_TXPOWERHT20DIFF 0x1C +#define EEPROM_TXPOWER_OFDMDIFF 0x1F + +#define EEPROM_TXPWR_GROUP 0x22 + +#define EEPROM_TSSI_A 0x29 +#define EEPROM_TSSI_B 0x77 + +#define EEPROM_CHANNELPLAN 0x28 + +#define RF_OPTION1 0x2B +#define RF_OPTION2 0x2C +#define RF_OPTION3 0x2D +#define RF_OPTION4 0x2E + +#define STOPBECON BIT(6) +#define STOPHIGHT BIT(5) +#define STOPMGT BIT(4) +#define STOPVO BIT(3) +#define STOPVI BIT(2) +#define STOPBE BIT(1) +#define STOPBK BIT(0) + +#define RCR_APPFCS BIT(31) +#define RCR_APP_MIC BIT(30) +#define RCR_APP_ICV BIT(29) +#define RCR_APP_PHYST_RXFF BIT(28) +#define RCR_APP_BA_SSN BIT(27) +#define RCR_ENMBID BIT(24) +#define RCR_LSIGEN BIT(23) +#define RCR_MFBEN BIT(22) +#define RCR_HTC_LOC_CTRL BIT(14) +#define RCR_AMF BIT(13) +#define RCR_ACF BIT(12) +#define RCR_ADF BIT(11) +#define RCR_AICV BIT(9) +#define RCR_ACRC32 BIT(8) +#define RCR_CBSSID_BCN BIT(7) +#define RCR_CBSSID_DATA BIT(6) +#define RCR_CBSSID RCR_CBSSID_DATA +#define RCR_APWRMGT BIT(5) +#define RCR_ADD3 BIT(4) +#define RCR_AB BIT(3) +#define RCR_AM BIT(2) +#define RCR_APM BIT(1) +#define RCR_AAP BIT(0) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 + +#define RSV_CTRL 0x001C +#define RD_CTRL 0x0524 + +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_USB_VID 0xFE60 +#define REG_USB_PID 0xFE62 +#define REG_USB_OPTIONAL 0xFE64 +#define REG_USB_CHIRP_K 0xFE65 +#define REG_USB_PHY 0xFE66 +#define REG_USB_MAC_ADDR 0xFE70 +#define REG_USB_HRPWM 0xFE58 +#define REG_USB_HCPWM 0xFE57 + +#define SW18_FPWM BIT(3) + +#define ISO_MD2PP BIT(0) +#define ISO_UA2USB BIT(1) +#define ISO_UD2CORE BIT(2) +#define ISO_PA2PCIE BIT(3) +#define ISO_PD2CORE BIT(4) +#define ISO_IP2MAC BIT(5) +#define ISO_DIOP BIT(6) +#define ISO_DIOE BIT(7) +#define ISO_EB2CORE BIT(8) +#define ISO_DIOR BIT(9) + +#define PWC_EV25V BIT(14) +#define PWC_EV12V BIT(15) + +#define FEN_BBRSTB BIT(0) +#define FEN_BB_GLB_RSTN BIT(1) +#define FEN_USBA BIT(2) +#define FEN_UPLL BIT(3) +#define FEN_USBD BIT(4) +#define FEN_DIO_PCIE BIT(5) +#define FEN_PCIEA BIT(6) +#define FEN_PPLL BIT(7) +#define FEN_PCIED BIT(8) +#define FEN_DIOE BIT(9) +#define FEN_CPUEN BIT(10) +#define FEN_DCORE BIT(11) +#define FEN_ELDR BIT(12) +#define FEN_DIO_RF BIT(13) +#define FEN_HWPDN BIT(14) +#define FEN_MREGEN BIT(15) + +#define PFM_LDALL BIT(0) +#define PFM_ALDN BIT(1) +#define PFM_LDKP BIT(2) +#define PFM_WOWL BIT(3) +#define ENPDN BIT(4) +#define PDN_PL BIT(5) +#define APFM_ONMAC BIT(8) +#define APFM_OFF BIT(9) +#define APFM_RSM BIT(10) +#define AFSM_HSUS BIT(11) +#define AFSM_PCIE BIT(12) +#define APDM_MAC BIT(13) +#define APDM_HOST BIT(14) +#define APDM_HPDN BIT(15) +#define RDY_MACON BIT(16) +#define SUS_HOST BIT(17) +#define ROP_ALD BIT(20) +#define ROP_PWR BIT(21) +#define ROP_SPS BIT(22) +#define SOP_MRST BIT(25) +#define SOP_FUSE BIT(26) +#define SOP_ABG BIT(27) +#define SOP_AMB BIT(28) +#define SOP_RCK BIT(29) +#define SOP_A8M BIT(30) +#define XOP_BTCK BIT(31) + +#define ANAD16V_EN BIT(0) +#define ANA8M BIT(1) +#define MACSLP BIT(4) +#define LOADER_CLK_EN BIT(5) +#define _80M_SSC_DIS BIT(7) +#define _80M_SSC_EN_HO BIT(8) +#define PHY_SSC_RSTB BIT(9) +#define SEC_CLK_EN BIT(10) +#define MAC_CLK_EN BIT(11) +#define SYS_CLK_EN BIT(12) +#define RING_CLK_EN BIT(13) + +#define BOOT_FROM_EEPROM BIT(4) +#define EEPROM_EN BIT(5) + +#define AFE_BGEN BIT(0) +#define AFE_MBEN BIT(1) +#define MAC_ID_EN BIT(7) + +#define WLOCK_ALL BIT(0) +#define WLOCK_00 BIT(1) +#define WLOCK_04 BIT(2) +#define WLOCK_08 BIT(3) +#define WLOCK_40 BIT(4) +#define R_DIS_PRST_0 BIT(5) +#define R_DIS_PRST_1 BIT(6) +#define LOCK_ALL_EN BIT(7) + +#define RF_EN BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + +#define LDA15_EN BIT(0) +#define LDA15_STBY BIT(1) +#define LDA15_OBUF BIT(2) +#define LDA15_REG_VOS BIT(3) +#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) + +#define LDV12_EN BIT(0) +#define LDV12_SDBY BIT(1) +#define LPLDO_HSM BIT(2) +#define LPLDO_LSM_DIS BIT(3) +#define _LDV12_VADJ(x) (((x) & 0xF) << 4) + +#define XTAL_EN BIT(0) +#define XTAL_BSEL BIT(1) +#define _XTAL_BOSC(x) (((x) & 0x3) << 2) +#define _XTAL_CADJ(x) (((x) & 0xF) << 4) +#define XTAL_GATE_USB BIT(8) +#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) +#define XTAL_GATE_AFE BIT(11) +#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) +#define XTAL_RF_GATE BIT(14) +#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) +#define XTAL_GATE_DIG BIT(17) +#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) +#define XTAL_BT_GATE BIT(20) +#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) +#define _XTAL_GPIO(x) (((x) & 0x7) << 23) + +#define CKDLY_AFE BIT(26) +#define CKDLY_USB BIT(27) +#define CKDLY_DIG BIT(28) +#define CKDLY_BT BIT(29) + +#define APLL_EN BIT(0) +#define APLL_320_EN BIT(1) +#define APLL_FREF_SEL BIT(2) +#define APLL_EDGE_SEL BIT(3) +#define APLL_WDOGB BIT(4) +#define APLL_LPFEN BIT(5) + +#define APLL_REF_CLK_13MHZ 0x1 +#define APLL_REF_CLK_19_2MHZ 0x2 +#define APLL_REF_CLK_20MHZ 0x3 +#define APLL_REF_CLK_25MHZ 0x4 +#define APLL_REF_CLK_26MHZ 0x5 +#define APLL_REF_CLK_38_4MHZ 0x6 +#define APLL_REF_CLK_40MHZ 0x7 + +#define APLL_320EN BIT(14) +#define APLL_80EN BIT(15) +#define APLL_1MEN BIT(24) + +#define ALD_EN BIT(18) +#define EF_PD BIT(19) +#define EF_FLAG BIT(31) + +#define EF_TRPT BIT(7) +#define LDOE25_EN BIT(31) + +#define RSM_EN BIT(0) +#define TIMER_EN BIT(4) + +#define TRSW0EN BIT(2) +#define TRSW1EN BIT(3) +#define EROM_EN BIT(4) +#define ENBT BIT(5) +#define ENUART BIT(8) +#define UART_910 BIT(9) +#define ENPMAC BIT(10) +#define SIC_SWRST BIT(11) +#define ENSIC BIT(12) +#define SIC_23 BIT(13) +#define ENHDP BIT(14) +#define SIC_LBK BIT(15) + +#define LED0PL BIT(4) +#define LED1PL BIT(12) +#define LED0DIS BIT(7) + +#define MCUFWDL_EN BIT(0) +#define MCUFWDL_RDY BIT(1) +#define FWDL_CHKSUM_RPT BIT(2) +#define MACINI_RDY BIT(3) +#define BBINI_RDY BIT(4) +#define RFINI_RDY BIT(5) +#define WINTINI_RDY BIT(6) +#define CPRST BIT(23) + +#define XCLK_VLD BIT(0) +#define ACLK_VLD BIT(1) +#define UCLK_VLD BIT(2) +#define PCLK_VLD BIT(3) +#define PCIRSTB BIT(4) +#define V15_VLD BIT(5) +#define TRP_B15V_EN BIT(7) +#define SIC_IDLE BIT(8) +#define BD_MAC2 BIT(9) +#define BD_MAC1 BIT(10) +#define IC_MACPHY_MODE BIT(11) +#define BT_FUNC BIT(16) +#define VENDOR_ID BIT(19) +#define PAD_HWPD_IDN BIT(22) +#define TRP_VAUX_EN BIT(23) +#define TRP_BT_EN BIT(24) +#define BD_PKG_SEL BIT(25) +#define BD_HCI_SEL BIT(26) +#define TYPE_ID BIT(27) + +#define CHIP_VER_RTL_MASK 0xF000 +#define CHIP_VER_RTL_SHIFT 12 + +#define REG_LBMODE (REG_CR + 3) + +#define HCI_TXDMA_EN BIT(0) +#define HCI_RXDMA_EN BIT(1) +#define TXDMA_EN BIT(2) +#define RXDMA_EN BIT(3) +#define PROTOCOL_EN BIT(4) +#define SCHEDULE_EN BIT(5) +#define MACTXEN BIT(6) +#define MACRXEN BIT(7) +#define ENSWBCN BIT(8) +#define ENSEC BIT(9) + +#define _NETTYPE(x) (((x) & 0x3) << 16) +#define MASK_NETTYPE 0x30000 +#define NT_NO_LINK 0x0 +#define NT_LINK_AD_HOC 0x1 +#define NT_LINK_AP 0x2 +#define NT_AS_AP 0x3 + +#define _LBMODE(x) (((x) & 0xF) << 24) +#define MASK_LBMODE 0xF000000 +#define LOOPBACK_NORMAL 0x0 +#define LOOPBACK_IMMEDIATELY 0xB +#define LOOPBACK_MAC_DELAY 0x3 +#define LOOPBACK_PHY 0x1 +#define LOOPBACK_DMA 0x7 + +#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) +#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) +#define _PSRX_MASK 0xF +#define _PSTX_MASK 0xF0 +#define _PSRX(x) (x) +#define _PSTX(x) ((x) << 4) + +#define PBP_64 0x0 +#define PBP_128 0x1 +#define PBP_256 0x2 +#define PBP_512 0x3 +#define PBP_1024 0x4 + +#define RXDMA_ARBBW_EN BIT(0) +#define RXSHFT_EN BIT(1) +#define RXDMA_AGG_EN BIT(2) +#define QS_VO_QUEUE BIT(8) +#define QS_VI_QUEUE BIT(9) +#define QS_BE_QUEUE BIT(10) +#define QS_BK_QUEUE BIT(11) +#define QS_MANAGER_QUEUE BIT(12) +#define QS_HIGH_QUEUE BIT(13) + +#define HQSEL_VOQ BIT(0) +#define HQSEL_VIQ BIT(1) +#define HQSEL_BEQ BIT(2) +#define HQSEL_BKQ BIT(3) +#define HQSEL_MGTQ BIT(4) +#define HQSEL_HIQ BIT(5) + +#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) +#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) +#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) +#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) +#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) +#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) + +#define QUEUE_LOW 1 +#define QUEUE_NORMAL 2 +#define QUEUE_HIGH 3 + +#define _LLT_NO_ACTIVE 0x0 +#define _LLT_WRITE_ACCESS 0x1 +#define _LLT_READ_ACCESS 0x2 + +#define _LLT_INIT_DATA(x) ((x) & 0xFF) +#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) +#define _LLT_OP(x) (((x) & 0x3) << 30) +#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) + +#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) +#define BB_WRITE_EN BIT(30) +#define BB_READ_EN BIT(31) + +#define _HPQ(x) ((x) & 0xFF) +#define _LPQ(x) (((x) & 0xFF) << 8) +#define _PUBQ(x) (((x) & 0xFF) << 16) +#define _NPQ(x) ((x) & 0xFF) + +#define HPQ_PUBLIC_DIS BIT(24) +#define LPQ_PUBLIC_DIS BIT(25) +#define LD_RQPN BIT(31) + +#define BCN_VALID BIT(16) +#define BCN_HEAD(x) (((x) & 0xFF) << 8) +#define BCN_HEAD_MASK 0xFF00 + +#define BLK_DESC_NUM_SHIFT 4 +#define BLK_DESC_NUM_MASK 0xF + +#define DROP_DATA_EN BIT(9) + +#define EN_AMPDU_RTY_NEW BIT(7) + +#define _INIRTSMCS_SEL(x) ((x) & 0x3F) + +#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) +#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) + +#define RATE_REG_BITMAP_ALL 0xFFFFF + +#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) + +#define _RRSR_RSC(x) (((x) & 0x3) << 21) +#define RRSR_RSC_RESERVED 0x0 +#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 +#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 +#define RRSR_RSC_DUPLICATE_MODE 0x3 + +#define USE_SHORT_G1 BIT(20) + +#define _AGGLMT_MCS0(x) ((x) & 0xF) +#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) +#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) +#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) +#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) +#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) +#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) +#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) + +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + +#define _DARF_RC1(x) ((x) & 0x1F) +#define _DARF_RC2(x) (((x) & 0x1F) << 8) +#define _DARF_RC3(x) (((x) & 0x1F) << 16) +#define _DARF_RC4(x) (((x) & 0x1F) << 24) +#define _DARF_RC5(x) ((x) & 0x1F) +#define _DARF_RC6(x) (((x) & 0x1F) << 8) +#define _DARF_RC7(x) (((x) & 0x1F) << 16) +#define _DARF_RC8(x) (((x) & 0x1F) << 24) + +#define _RARF_RC1(x) ((x) & 0x1F) +#define _RARF_RC2(x) (((x) & 0x1F) << 8) +#define _RARF_RC3(x) (((x) & 0x1F) << 16) +#define _RARF_RC4(x) (((x) & 0x1F) << 24) +#define _RARF_RC5(x) ((x) & 0x1F) +#define _RARF_RC6(x) (((x) & 0x1F) << 8) +#define _RARF_RC7(x) (((x) & 0x1F) << 16) +#define _RARF_RC8(x) (((x) & 0x1F) << 24) + +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + +#define _AIFS(x) (x) +#define _ECW_MAX_MIN(x) ((x) << 8) +#define _TXOP_LIMIT(x) ((x) << 16) + +#define _BCNIFS(x) ((x) & 0xFF) +#define _BCNECW(x) ((((x) & 0xF)) << 8) + +#define _LRL(x) ((x) & 0x3F) +#define _SRL(x) (((x) & 0x3F) << 8) + +#define _SIFS_CCK_CTX(x) ((x) & 0xFF) +#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8) + +#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) +#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8) + +#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) + +#define DIS_EDCA_CNT_DWN BIT(11) + +#define EN_MBSSID BIT(1) +#define EN_TXBCN_RPT BIT(2) +#define EN_BCN_FUNCTION BIT(3) + +#define TSFTR_RST BIT(0) +#define TSFTR1_RST BIT(1) + +#define STOP_BCNQ BIT(6) + +#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) +#define DIS_TSF_UDT0_TEST_CHIP BIT(5) + +#define ACMHW_HWEN BIT(0) +#define ACMHW_BEQEN BIT(1) +#define ACMHW_VIQEN BIT(2) +#define ACMHW_VOQEN BIT(3) +#define ACMHW_BEQSTATUS BIT(4) +#define ACMHW_VIQSTATUS BIT(5) +#define ACMHW_VOQSTATUS BIT(6) + +#define APSDOFF BIT(6) +#define APSDOFF_STATUS BIT(7) + +#define BW_20MHZ BIT(2) + +#define RATE_BITMAP_ALL 0xFFFFF + +#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 + +#define TSFRST BIT(0) +#define DIS_GCLK BIT(1) +#define PAD_SEL BIT(2) +#define PWR_ST BIT(6) +#define PWRBIT_OW_EN BIT(7) +#define ACRC BIT(8) +#define CFENDFORM BIT(9) +#define ICV BIT(10) + +#define AAP BIT(0) +#define APM BIT(1) +#define AM BIT(2) +#define AB BIT(3) +#define ADD3 BIT(4) +#define APWRMGT BIT(5) +#define CBSSID BIT(6) +#define CBSSID_DATA BIT(6) +#define CBSSID_BCN BIT(7) +#define ACRC32 BIT(8) +#define AICV BIT(9) +#define ADF BIT(11) +#define ACF BIT(12) +#define AMF BIT(13) +#define HTC_LOC_CTRL BIT(14) +#define UC_DATA_EN BIT(16) +#define BM_DATA_EN BIT(17) +#define MFBEN BIT(22) +#define LSIGEN BIT(23) +#define ENMBID BIT(24) +#define APP_BASSN BIT(27) +#define APP_PHYSTS BIT(28) +#define APP_ICV BIT(29) +#define APP_MIC BIT(30) +#define APP_FCS BIT(31) + +#define _MIN_SPACE(x) ((x) & 0x7) +#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) + +#define RXERR_TYPE_OFDM_PPDU 0 +#define RXERR_TYPE_OFDM_FALSE_ALARM 1 +#define RXERR_TYPE_OFDM_MPDU_OK 2 +#define RXERR_TYPE_OFDM_MPDU_FAIL 3 +#define RXERR_TYPE_CCK_PPDU 4 +#define RXERR_TYPE_CCK_FALSE_ALARM 5 +#define RXERR_TYPE_CCK_MPDU_OK 6 +#define RXERR_TYPE_CCK_MPDU_FAIL 7 +#define RXERR_TYPE_HT_PPDU 8 +#define RXERR_TYPE_HT_FALSE_ALARM 9 +#define RXERR_TYPE_HT_MPDU_TOTAL 10 +#define RXERR_TYPE_HT_MPDU_OK 11 +#define RXERR_TYPE_HT_MPDU_FAIL 12 +#define RXERR_TYPE_RX_FULL_DROP 15 + +#define RXERR_COUNTER_MASK 0xFFFFF +#define RXERR_RPT_RST BIT(27) +#define _RXERR_RPT_SEL(type) ((type) << 28) + +#define SCR_TXUSEDK BIT(0) +#define SCR_RXUSEDK BIT(1) +#define SCR_TXENCENABLE BIT(2) +#define SCR_RXDECENABLE BIT(3) +#define SCR_SKBYA2 BIT(4) +#define SCR_NOSKMC BIT(5) +#define SCR_TXBCUSEDK BIT(6) +#define SCR_RXBCUSEDK BIT(7) + +#define USB_IS_HIGH_SPEED 0 +#define USB_IS_FULL_SPEED 1 +#define USB_SPEED_MASK BIT(5) + +#define USB_NORMAL_SIE_EP_MASK 0xF +#define USB_NORMAL_SIE_EP_SHIFT 4 + +#define USB_TEST_EP_MASK 0x30 +#define USB_TEST_EP_SHIFT 4 + +#define USB_AGG_EN BIT(3) + +#define MAC_ADDR_LEN 6 +#define LAST_ENTRY_OF_TX_PKT_BUFFER 255 + +#define POLLING_LLT_THRESHOLD 20 +#define POLLING_READY_TIMEOUT_COUNT 1000 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) +#define EPROM_CMD_CONFIG 0x3 +#define EPROM_CMD_LOAD 1 + +#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE + +#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) + +#define RPMAC_RESET 0x100 +#define RPMAC_TXSTART 0x104 +#define RPMAC_TXLEGACYSIG 0x108 +#define RPMAC_TXHTSIG1 0x10c +#define RPMAC_TXHTSIG2 0x110 +#define RPMAC_PHYDEBUG 0x114 +#define RPMAC_TXPACKETNUM 0x118 +#define RPMAC_TXIDLE 0x11c +#define RPMAC_TXMACHEADER0 0x120 +#define RPMAC_TXMACHEADER1 0x124 +#define RPMAC_TXMACHEADER2 0x128 +#define RPMAC_TXMACHEADER3 0x12c +#define RPMAC_TXMACHEADER4 0x130 +#define RPMAC_TXMACHEADER5 0x134 +#define RPMAC_TXDADATYPE 0x138 +#define RPMAC_TXRANDOMSEED 0x13c +#define RPMAC_CCKPLCPPREAMBLE 0x140 +#define RPMAC_CCKPLCPHEADER 0x144 +#define RPMAC_CCKCRC16 0x148 +#define RPMAC_OFDMRXCRC32OK 0x170 +#define RPMAC_OFDMRXCRC32ER 0x174 +#define RPMAC_OFDMRXPARITYER 0x178 +#define RPMAC_OFDMRXCRC8ER 0x17c +#define RPMAC_CCKCRXRC16ER 0x180 +#define RPMAC_CCKCRXRC32ER 0x184 +#define RPMAC_CCKCRXRC32OK 0x188 +#define RPMAC_TXSTATUS 0x18c + +#define RFPGA0_RFMOD 0x800 + +#define RFPGA0_TXINFO 0x804 +#define RFPGA0_PSDFUNCTION 0x808 + +#define RFPGA0_TXGAINSTAGE 0x80c + +#define RFPGA0_RFTIMING1 0x810 +#define RFPGA0_RFTIMING2 0x814 + +#define RFPGA0_XA_HSSIPARAMETER1 0x820 +#define RFPGA0_XA_HSSIPARAMETER2 0x824 +#define RFPGA0_XB_HSSIPARAMETER1 0x828 +#define RFPGA0_XB_HSSIPARAMETER2 0x82c + +#define RFPGA0_XA_LSSIPARAMETER 0x840 +#define RFPGA0_XB_LSSIPARAMETER 0x844 + +#define RFPGA0_RFWAKEUPPARAMETER 0x850 +#define RFPGA0_RFSLEEPUPPARAMETER 0x854 + +#define RFPGA0_XAB_SWITCHCONTROL 0x858 +#define RFPGA0_XCD_SWITCHCONTROL 0x85c + +#define RFPGA0_XA_RFINTERFACEOE 0x860 +#define RFPGA0_XB_RFINTERFACEOE 0x864 + +#define RFPGA0_XAB_RFINTERFACESW 0x870 +#define RFPGA0_XCD_RFINTERFACESW 0x874 + +#define RFPGA0_XAB_RFPARAMETER 0x878 +#define RFPGA0_XCD_RFPARAMETER 0x87c + +#define RFPGA0_ANALOGPARAMETER1 0x880 +#define RFPGA0_ANALOGPARAMETER2 0x884 +#define RFPGA0_ANALOGPARAMETER3 0x888 +#define RFPGA0_ANALOGPARAMETER4 0x88c + +#define RFPGA0_XA_LSSIREADBACK 0x8a0 +#define RFPGA0_XB_LSSIREADBACK 0x8a4 +#define RFPGA0_XC_LSSIREADBACK 0x8a8 +#define RFPGA0_XD_LSSIREADBACK 0x8ac + +#define RFPGA0_PSDREPORT 0x8b4 +#define TRANSCEIVEA_HSPI_READBACK 0x8b8 +#define TRANSCEIVEB_HSPI_READBACK 0x8bc +#define RFPGA0_XAB_RFINTERFACERB 0x8e0 +#define RFPGA0_XCD_RFINTERFACERB 0x8e4 + +#define RFPGA1_RFMOD 0x900 + +#define RFPGA1_TXBLOCK 0x904 +#define RFPGA1_DEBUGSELECT 0x908 +#define RFPGA1_TXINFO 0x90c + +#define RCCK0_SYSTEM 0xa00 + +#define RCCK0_AFESETTING 0xa04 +#define RCCK0_CCA 0xa08 + +#define RCCK0_RXAGC1 0xa0c +#define RCCK0_RXAGC2 0xa10 + +#define RCCK0_RXHP 0xa14 + +#define RCCK0_DSPPARAMETER1 0xa18 +#define RCCK0_DSPPARAMETER2 0xa1c + +#define RCCK0_TXFILTER1 0xa20 +#define RCCK0_TXFILTER2 0xa24 +#define RCCK0_DEBUGPORT 0xa28 +#define RCCK0_FALSEALARMREPORT 0xa2c +#define RCCK0_TRSSIREPORT 0xa50 +#define RCCK0_RXREPORT 0xa54 +#define RCCK0_FACOUNTERLOWER 0xa5c +#define RCCK0_FACOUNTERUPPER 0xa58 + +#define ROFDM0_LSTF 0xc00 + +#define ROFDM0_TRXPATHENABLE 0xc04 +#define ROFDM0_TRMUXPAR 0xc08 +#define ROFDM0_TRSWISOLATION 0xc0c + +#define ROFDM0_XARXAFE 0xc10 +#define ROFDM0_XARXIQIMBALANCE 0xc14 +#define ROFDM0_XBRXAFE 0xc18 +#define ROFDM0_XBRXIQIMBALANCE 0xc1c +#define ROFDM0_XCRXAFE 0xc20 +#define ROFDM0_XCRXIQIMBANLANCE 0xc24 +#define ROFDM0_XDRXAFE 0xc28 +#define ROFDM0_XDRXIQIMBALANCE 0xc2c + +#define ROFDM0_RXDETECTOR1 0xc30 +#define ROFDM0_RXDETECTOR2 0xc34 +#define ROFDM0_RXDETECTOR3 0xc38 +#define ROFDM0_RXDETECTOR4 0xc3c + +#define ROFDM0_RXDSP 0xc40 +#define ROFDM0_CFOANDDAGC 0xc44 +#define ROFDM0_CCADROPTHRESHOLD 0xc48 +#define ROFDM0_ECCATHRESHOLD 0xc4c + +#define ROFDM0_XAAGCCORE1 0xc50 +#define ROFDM0_XAAGCCORE2 0xc54 +#define ROFDM0_XBAGCCORE1 0xc58 +#define ROFDM0_XBAGCCORE2 0xc5c +#define ROFDM0_XCAGCCORE1 0xc60 +#define ROFDM0_XCAGCCORE2 0xc64 +#define ROFDM0_XDAGCCORE1 0xc68 +#define ROFDM0_XDAGCCORE2 0xc6c + +#define ROFDM0_AGCPARAMETER1 0xc70 +#define ROFDM0_AGCPARAMETER2 0xc74 +#define ROFDM0_AGCRSSITABLE 0xc78 +#define ROFDM0_HTSTFAGC 0xc7c + +#define ROFDM0_XATXIQIMBALANCE 0xc80 +#define ROFDM0_XATXAFE 0xc84 +#define ROFDM0_XBTXIQIMBALANCE 0xc88 +#define ROFDM0_XBTXAFE 0xc8c +#define ROFDM0_XCTXIQIMBALANCE 0xc90 +#define ROFDM0_XCTXAFE 0xc94 +#define ROFDM0_XDTXIQIMBALANCE 0xc98 +#define ROFDM0_XDTXAFE 0xc9c + +#define ROFDM0_RXIQEXTANTA 0xca0 + +#define ROFDM0_RXHPPARAMETER 0xce0 +#define ROFDM0_TXPSEUDONOISEWGT 0xce4 +#define ROFDM0_FRAMESYNC 0xcf0 +#define ROFDM0_DFSREPORT 0xcf4 +#define ROFDM0_TXCOEFF1 0xca4 +#define ROFDM0_TXCOEFF2 0xca8 +#define ROFDM0_TXCOEFF3 0xcac +#define ROFDM0_TXCOEFF4 0xcb0 +#define ROFDM0_TXCOEFF5 0xcb4 +#define ROFDM0_TXCOEFF6 0xcb8 + +#define ROFDM1_LSTF 0xd00 +#define ROFDM1_TRXPATHENABLE 0xd04 + +#define ROFDM1_CF0 0xd08 +#define ROFDM1_CSI1 0xd10 +#define ROFDM1_SBD 0xd14 +#define ROFDM1_CSI2 0xd18 +#define ROFDM1_CFOTRACKING 0xd2c +#define ROFDM1_TRXMESAURE1 0xd34 +#define ROFDM1_INTFDET 0xd3c +#define ROFDM1_PSEUDONOISESTATEAB 0xd50 +#define ROFDM1_PSEUDONOISESTATECD 0xd54 +#define ROFDM1_RXPSEUDONOISEWGT 0xd58 + +#define ROFDM_PHYCOUNTER1 0xda0 +#define ROFDM_PHYCOUNTER2 0xda4 +#define ROFDM_PHYCOUNTER3 0xda8 + +#define ROFDM_SHORTCFOAB 0xdac +#define ROFDM_SHORTCFOCD 0xdb0 +#define ROFDM_LONGCFOAB 0xdb4 +#define ROFDM_LONGCFOCD 0xdb8 +#define ROFDM_TAILCF0AB 0xdbc +#define ROFDM_TAILCF0CD 0xdc0 +#define ROFDM_PWMEASURE1 0xdc4 +#define ROFDM_PWMEASURE2 0xdc8 +#define ROFDM_BWREPORT 0xdcc +#define ROFDM_AGCREPORT 0xdd0 +#define ROFDM_RXSNR 0xdd4 +#define ROFDM_RXEVMCSI 0xdd8 +#define ROFDM_SIGREPORT 0xddc + +#define RTXAGC_A_RATE18_06 0xe00 +#define RTXAGC_A_RATE54_24 0xe04 +#define RTXAGC_A_CCK1_MCS32 0xe08 +#define RTXAGC_A_MCS03_MCS00 0xe10 +#define RTXAGC_A_MCS07_MCS04 0xe14 +#define RTXAGC_A_MCS11_MCS08 0xe18 +#define RTXAGC_A_MCS15_MCS12 0xe1c + +#define RTXAGC_B_RATE18_06 0x830 +#define RTXAGC_B_RATE54_24 0x834 +#define RTXAGC_B_CCK1_55_MCS32 0x838 +#define RTXAGC_B_MCS03_MCS00 0x83c +#define RTXAGC_B_MCS07_MCS04 0x848 +#define RTXAGC_B_MCS11_MCS08 0x84c +#define RTXAGC_B_MCS15_MCS12 0x868 +#define RTXAGC_B_CCK11_A_CCK2_11 0x86c + +#define RZEBRA1_HSSIENABLE 0x0 +#define RZEBRA1_TRXENABLE1 0x1 +#define RZEBRA1_TRXENABLE2 0x2 +#define RZEBRA1_AGC 0x4 +#define RZEBRA1_CHARGEPUMP 0x5 +#define RZEBRA1_CHANNEL 0x7 + +#define RZEBRA1_TXGAIN 0x8 +#define RZEBRA1_TXLPF 0x9 +#define RZEBRA1_RXLPF 0xb +#define RZEBRA1_RXHPFCORNER 0xc + +#define RGLOBALCTRL 0 +#define RRTL8256_TXLPF 19 +#define RRTL8256_RXLPF 11 +#define RRTL8258_TXLPF 0x11 +#define RRTL8258_RXLPF 0x13 +#define RRTL8258_RSSILPF 0xa + +#define RF_AC 0x00 + +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_POW_TRSW 0x05 + +#define RF_GAIN_RX 0x06 +#define RF_GAIN_TX 0x07 + +#define RF_TXM_IDAC 0x08 +#define RF_BS_IQGEN 0x0F + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 + +#define RF_RX_AGC_HP 0x12 +#define RF_TX_AGC 0x13 +#define RF_BIAS 0x14 +#define RF_IPA 0x15 +#define RF_POW_ABILITY 0x17 +#define RF_MODE_AG 0x18 +#define RRFCHANNEL 0x18 +#define RF_CHNLBW 0x18 +#define RF_TOP 0x19 + +#define RF_RX_G1 0x1A +#define RF_RX_G2 0x1B + +#define RF_RX_BB2 0x1C +#define RF_RX_BB1 0x1D + +#define RF_RCK1 0x1E +#define RF_RCK2 0x1F + +#define RF_TX_G1 0x20 +#define RF_TX_G2 0x21 +#define RF_TX_G3 0x22 + +#define RF_TX_BB1 0x23 +#define RF_T_METER 0x24 + +#define RF_SYN_G1 0x25 +#define RF_SYN_G2 0x26 +#define RF_SYN_G3 0x27 +#define RF_SYN_G4 0x28 +#define RF_SYN_G5 0x29 +#define RF_SYN_G6 0x2A +#define RF_SYN_G7 0x2B +#define RF_SYN_G8 0x2C + +#define RF_RCK_OS 0x30 +#define RF_TXPA_G1 0x31 +#define RF_TXPA_G2 0x32 +#define RF_TXPA_G3 0x33 + +#define BBBRESETB 0x100 +#define BGLOBALRESETB 0x200 +#define BOFDMTXSTART 0x4 +#define BCCKTXSTART 0x8 +#define BCRC32DEBUG 0x100 +#define BPMACLOOPBACK 0x10 +#define BTXLSIG 0xffffff +#define BOFDMTXRATE 0xf +#define BOFDMTXRESERVED 0x10 +#define BOFDMTXLENGTH 0x1ffe0 +#define BOFDMTXPARITY 0x20000 +#define BTXHTSIG1 0xffffff +#define BTXHTMCSRATE 0x7f +#define BTXHTBW 0x80 +#define BTXHTLENGTH 0xffff00 +#define BTXHTSIG2 0xffffff +#define BTXHTSMOOTHING 0x1 +#define BTXHTSOUNDING 0x2 +#define BTXHTRESERVED 0x4 +#define BTXHTAGGREATION 0x8 +#define BTXHTSTBC 0x30 +#define BTXHTADVANCECODING 0x40 +#define BTXHTSHORTGI 0x80 +#define BTXHTNUMBERHT_LTF 0x300 +#define BTXHTCRC8 0x3fc00 +#define BCOUNTERRESET 0x10000 +#define BNUMOFOFDMTX 0xffff +#define BNUMOFCCKTX 0xffff0000 +#define BTXIDLEINTERVAL 0xffff +#define BOFDMSERVICE 0xffff0000 +#define BTXMACHEADER 0xffffffff +#define BTXDATAINIT 0xff +#define BTXHTMODE 0x100 +#define BTXDATATYPE 0x30000 +#define BTXRANDOMSEED 0xffffffff +#define BCCKTXPREAMBLE 0x1 +#define BCCKTXSFD 0xffff0000 +#define BCCKTXSIG 0xff +#define BCCKTXSERVICE 0xff00 +#define BCCKLENGTHEXT 0x8000 +#define BCCKTXLENGHT 0xffff0000 +#define BCCKTXCRC16 0xffff +#define BCCKTXSTATUS 0x1 +#define BOFDMTXSTATUS 0x2 +#define IS_BB_REG_OFFSET_92S(_offset) \ + ((_offset >= 0x800) && (_offset <= 0xfff)) + +#define BRFMOD 0x1 +#define BJAPANMODE 0x2 +#define BCCKTXSC 0x30 +#define BCCKEN 0x1000000 +#define BOFDMEN 0x2000000 + +#define BOFDMRXADCPHASE 0x10000 +#define BOFDMTXDACPHASE 0x40000 +#define BXATXAGC 0x3f + +#define BXBTXAGC 0xf00 +#define BXCTXAGC 0xf000 +#define BXDTXAGC 0xf0000 + +#define BPASTART 0xf0000000 +#define BTRSTART 0x00f00000 +#define BRFSTART 0x0000f000 +#define BBBSTART 0x000000f0 +#define BBBCCKSTART 0x0000000f +#define BPAEND 0xf +#define BTREND 0x0f000000 +#define BRFEND 0x000f0000 +#define BCCAMASK 0x000000f0 +#define BR2RCCAMASK 0x00000f00 +#define BHSSI_R2TDELAY 0xf8000000 +#define BHSSI_T2RDELAY 0xf80000 +#define BCONTXHSSI 0x400 +#define BIGFROMCCK 0x200 +#define BAGCADDRESS 0x3f +#define BRXHPTX 0x7000 +#define BRXHP2RX 0x38000 +#define BRXHPCCKINI 0xc0000 +#define BAGCTXCODE 0xc00000 +#define BAGCRXCODE 0x300000 + +#define B3WIREDATALENGTH 0x800 +#define B3WIREADDREAALENGTH 0x400 + +#define B3WIRERFPOWERDOWN 0x1 +#define B5GPAPEPOLARITY 0x40000000 +#define B2GPAPEPOLARITY 0x80000000 +#define BRFSW_TXDEFAULTANT 0x3 +#define BRFSW_TXOPTIONANT 0x30 +#define BRFSW_RXDEFAULTANT 0x300 +#define BRFSW_RXOPTIONANT 0x3000 +#define BRFSI_3WIREDATA 0x1 +#define BRFSI_3WIRECLOCK 0x2 +#define BRFSI_3WIRELOAD 0x4 +#define BRFSI_3WIRERW 0x8 +#define BRFSI_3WIRE 0xf + +#define BRFSI_RFENV 0x10 + +#define BRFSI_TRSW 0x20 +#define BRFSI_TRSWB 0x40 +#define BRFSI_ANTSW 0x100 +#define BRFSI_ANTSWB 0x200 +#define BRFSI_PAPE 0x400 +#define BRFSI_PAPE5G 0x800 +#define BBANDSELECT 0x1 +#define BHTSIG2_GI 0x80 +#define BHTSIG2_SMOOTHING 0x01 +#define BHTSIG2_SOUNDING 0x02 +#define BHTSIG2_AGGREATON 0x08 +#define BHTSIG2_STBC 0x30 +#define BHTSIG2_ADVCODING 0x40 +#define BHTSIG2_NUMOFHTLTF 0x300 +#define BHTSIG2_CRC8 0x3fc +#define BHTSIG1_MCS 0x7f +#define BHTSIG1_BANDWIDTH 0x80 +#define BHTSIG1_HTLENGTH 0xffff +#define BLSIG_RATE 0xf +#define BLSIG_RESERVED 0x10 +#define BLSIG_LENGTH 0x1fffe +#define BLSIG_PARITY 0x20 +#define BCCKRXPHASE 0x4 + +#define BLSSIREADADDRESS 0x7f800000 +#define BLSSIREADEDGE 0x80000000 + +#define BLSSIREADBACKDATA 0xfffff + +#define BLSSIREADOKFLAG 0x1000 +#define BCCKSAMPLERATE 0x8 +#define BREGULATOR0STANDBY 0x1 +#define BREGULATORPLLSTANDBY 0x2 +#define BREGULATOR1STANDBY 0x4 +#define BPLLPOWERUP 0x8 +#define BDPLLPOWERUP 0x10 +#define BDA10POWERUP 0x20 +#define BAD7POWERUP 0x200 +#define BDA6POWERUP 0x2000 +#define BXTALPOWERUP 0x4000 +#define B40MDCLKPOWERUP 0x8000 +#define BDA6DEBUGMODE 0x20000 +#define BDA6SWING 0x380000 + +#define BADCLKPHASE 0x4000000 +#define B80MCLKDELAY 0x18000000 +#define BAFEWATCHDOGENABLE 0x20000000 + +#define BXTALCAP01 0xc0000000 +#define BXTALCAP23 0x3 +#define BXTALCAP92X 0x0f000000 +#define BXTALCAP 0x0f000000 + +#define BINTDIFCLKENABLE 0x400 +#define BEXTSIGCLKENABLE 0x800 +#define BBANDGAP_MBIAS_POWERUP 0x10000 +#define BAD11SH_GAIN 0xc0000 +#define BAD11NPUT_RANGE 0x700000 +#define BAD110P_CURRENT 0x3800000 +#define BLPATH_LOOPBACK 0x4000000 +#define BQPATH_LOOPBACK 0x8000000 +#define BAFE_LOOPBACK 0x10000000 +#define BDA10_SWING 0x7e0 +#define BDA10_REVERSE 0x800 +#define BDA_CLK_SOURCE 0x1000 +#define BDA7INPUT_RANGE 0x6000 +#define BDA7_GAIN 0x38000 +#define BDA7OUTPUT_CM_MODE 0x40000 +#define BDA7INPUT_CM_MODE 0x380000 +#define BDA7CURRENT 0xc00000 +#define BREGULATOR_ADJUST 0x7000000 +#define BAD11POWERUP_ATTX 0x1 +#define BDA10PS_ATTX 0x10 +#define BAD11POWERUP_ATRX 0x100 +#define BDA10PS_ATRX 0x1000 +#define BCCKRX_AGC_FORMAT 0x200 +#define BPSDFFT_SAMPLE_POINT 0xc000 +#define BPSD_AVERAGE_NUM 0x3000 +#define BIQPATH_CONTROL 0xc00 +#define BPSD_FREQ 0x3ff +#define BPSD_ANTENNA_PATH 0x30 +#define BPSD_IQ_SWITCH 0x40 +#define BPSD_RX_TRIGGER 0x400000 +#define BPSD_TX_TRIGGER 0x80000000 +#define BPSD_SINE_TONE_SCALE 0x7f000000 +#define BPSD_REPORT 0xffff + +#define BOFDM_TXSC 0x30000000 +#define BCCK_TXON 0x1 +#define BOFDM_TXON 0x2 +#define BDEBUG_PAGE 0xfff +#define BDEBUG_ITEM 0xff +#define BANTL 0x10 +#define BANT_NONHT 0x100 +#define BANT_HT1 0x1000 +#define BANT_HT2 0x10000 +#define BANT_HT1S1 0x100000 +#define BANT_NONHTS1 0x1000000 + +#define BCCK_BBMODE 0x3 +#define BCCK_TXPOWERSAVING 0x80 +#define BCCK_RXPOWERSAVING 0x40 + +#define BCCK_SIDEBAND 0x10 + +#define BCCK_SCRAMBLE 0x8 +#define BCCK_ANTDIVERSITY 0x8000 +#define BCCK_CARRIER_RECOVERY 0x4000 +#define BCCK_TXRATE 0x3000 +#define BCCK_DCCANCEL 0x0800 +#define BCCK_ISICANCEL 0x0400 +#define BCCK_MATCH_FILTER 0x0200 +#define BCCK_EQUALIZER 0x0100 +#define BCCK_PREAMBLE_DETECT 0x800000 +#define BCCK_FAST_FALSECCA 0x400000 +#define BCCK_CH_ESTSTART 0x300000 +#define BCCK_CCA_COUNT 0x080000 +#define BCCK_CS_LIM 0x070000 +#define BCCK_BIST_MODE 0x80000000 +#define BCCK_CCAMASK 0x40000000 +#define BCCK_TX_DAC_PHASE 0x4 +#define BCCK_RX_ADC_PHASE 0x20000000 +#define BCCKR_CP_MODE 0x0100 +#define BCCK_TXDC_OFFSET 0xf0 +#define BCCK_RXDC_OFFSET 0xf +#define BCCK_CCA_MODE 0xc000 +#define BCCK_FALSECS_LIM 0x3f00 +#define BCCK_CS_RATIO 0xc00000 +#define BCCK_CORGBIT_SEL 0x300000 +#define BCCK_PD_LIM 0x0f0000 +#define BCCK_NEWCCA 0x80000000 +#define BCCK_RXHP_OF_IG 0x8000 +#define BCCK_RXIG 0x7f00 +#define BCCK_LNA_POLARITY 0x800000 +#define BCCK_RX1ST_BAIN 0x7f0000 +#define BCCK_RF_EXTEND 0x20000000 +#define BCCK_RXAGC_SATLEVEL 0x1f000000 +#define BCCK_RXAGC_SATCOUNT 0xe0 +#define BCCKRXRFSETTLE 0x1f +#define BCCK_FIXED_RXAGC 0x8000 +#define BCCK_ANTENNA_POLARITY 0x2000 +#define BCCK_TXFILTER_TYPE 0x0c00 +#define BCCK_RXAGC_REPORTTYPE 0x0300 +#define BCCK_RXDAGC_EN 0x80000000 +#define BCCK_RXDAGC_PERIOD 0x20000000 +#define BCCK_RXDAGC_SATLEVEL 0x1f000000 +#define BCCK_TIMING_RECOVERY 0x800000 +#define BCCK_TXC0 0x3f0000 +#define BCCK_TXC1 0x3f000000 +#define BCCK_TXC2 0x3f +#define BCCK_TXC3 0x3f00 +#define BCCK_TXC4 0x3f0000 +#define BCCK_TXC5 0x3f000000 +#define BCCK_TXC6 0x3f +#define BCCK_TXC7 0x3f00 +#define BCCK_DEBUGPORT 0xff0000 +#define BCCK_DAC_DEBUG 0x0f000000 +#define BCCK_FALSEALARM_ENABLE 0x8000 +#define BCCK_FALSEALARM_READ 0x4000 +#define BCCK_TRSSI 0x7f +#define BCCK_RXAGC_REPORT 0xfe +#define BCCK_RXREPORT_ANTSEL 0x80000000 +#define BCCK_RXREPORT_MFOFF 0x40000000 +#define BCCK_RXREPORT_SQLOSS 0x20000000 +#define BCCK_RXREPORT_PKTLOSS 0x10000000 +#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 +#define BCCK_RXREPORT_RATEERROR 0x04000000 +#define BCCK_RXREPORT_RXRATE 0x03000000 +#define BCCK_RXFA_COUNTER_LOWER 0xff +#define BCCK_RXFA_COUNTER_UPPER 0xff000000 +#define BCCK_RXHPAGC_START 0xe000 +#define BCCK_RXHPAGC_FINAL 0x1c00 +#define BCCK_RXFALSEALARM_ENABLE 0x8000 +#define BCCK_FACOUNTER_FREEZE 0x4000 +#define BCCK_TXPATH_SEL 0x10000000 +#define BCCK_DEFAULT_RXPATH 0xc000000 +#define BCCK_OPTION_RXPATH 0x3000000 + +#define BNUM_OFSTF 0x3 +#define BSHIFT_L 0xc0 +#define BGI_TH 0xc +#define BRXPATH_A 0x1 +#define BRXPATH_B 0x2 +#define BRXPATH_C 0x4 +#define BRXPATH_D 0x8 +#define BTXPATH_A 0x1 +#define BTXPATH_B 0x2 +#define BTXPATH_C 0x4 +#define BTXPATH_D 0x8 +#define BTRSSI_FREQ 0x200 +#define BADC_BACKOFF 0x3000 +#define BDFIR_BACKOFF 0xc000 +#define BTRSSI_LATCH_PHASE 0x10000 +#define BRX_LDC_OFFSET 0xff +#define BRX_QDC_OFFSET 0xff00 +#define BRX_DFIR_MODE 0x1800000 +#define BRX_DCNF_TYPE 0xe000000 +#define BRXIQIMB_A 0x3ff +#define BRXIQIMB_B 0xfc00 +#define BRXIQIMB_C 0x3f0000 +#define BRXIQIMB_D 0xffc00000 +#define BDC_DC_NOTCH 0x60000 +#define BRXNB_NOTCH 0x1f000000 +#define BPD_TH 0xf +#define BPD_TH_OPT2 0xc000 +#define BPWED_TH 0x700 +#define BIFMF_WIN_L 0x800 +#define BPD_OPTION 0x1000 +#define BMF_WIN_L 0xe000 +#define BBW_SEARCH_L 0x30000 +#define BWIN_ENH_L 0xc0000 +#define BBW_TH 0x700000 +#define BED_TH2 0x3800000 +#define BBW_OPTION 0x4000000 +#define BRADIO_TH 0x18000000 +#define BWINDOW_L 0xe0000000 +#define BSBD_OPTION 0x1 +#define BFRAME_TH 0x1c +#define BFS_OPTION 0x60 +#define BDC_SLOPE_CHECK 0x80 +#define BFGUARD_COUNTER_DC_L 0xe00 +#define BFRAME_WEIGHT_SHORT 0x7000 +#define BSUB_TUNE 0xe00000 +#define BFRAME_DC_LENGTH 0xe000000 +#define BSBD_START_OFFSET 0x30000000 +#define BFRAME_TH_2 0x7 +#define BFRAME_GI2_TH 0x38 +#define BGI2_SYNC_EN 0x40 +#define BSARCH_SHORT_EARLY 0x300 +#define BSARCH_SHORT_LATE 0xc00 +#define BSARCH_GI2_LATE 0x70000 +#define BCFOANTSUM 0x1 +#define BCFOACC 0x2 +#define BCFOSTARTOFFSET 0xc +#define BCFOLOOPBACK 0x70 +#define BCFOSUMWEIGHT 0x80 +#define BDAGCENABLE 0x10000 +#define BTXIQIMB_A 0x3ff +#define BTXIQIMB_b 0xfc00 +#define BTXIQIMB_C 0x3f0000 +#define BTXIQIMB_D 0xffc00000 +#define BTXIDCOFFSET 0xff +#define BTXIQDCOFFSET 0xff00 +#define BTXDFIRMODE 0x10000 +#define BTXPESUDO_NOISEON 0x4000000 +#define BTXPESUDO_NOISE_A 0xff +#define BTXPESUDO_NOISE_B 0xff00 +#define BTXPESUDO_NOISE_C 0xff0000 +#define BTXPESUDO_NOISE_D 0xff000000 +#define BCCA_DROPOPTION 0x20000 +#define BCCA_DROPTHRES 0xfff00000 +#define BEDCCA_H 0xf +#define BEDCCA_L 0xf0 +#define BLAMBDA_ED 0x300 +#define BRX_INITIALGAIN 0x7f +#define BRX_ANTDIV_EN 0x80 +#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 +#define BRX_HIGHPOWER_FLOW 0x8000 +#define BRX_AGC_FREEZE_THRES 0xc0000 +#define BRX_FREEZESTEP_AGC1 0x300000 +#define BRX_FREEZESTEP_AGC2 0xc00000 +#define BRX_FREEZESTEP_AGC3 0x3000000 +#define BRX_FREEZESTEP_AGC0 0xc000000 +#define BRXRSSI_CMP_EN 0x10000000 +#define BRXQUICK_AGCEN 0x20000000 +#define BRXAGC_FREEZE_THRES_MODE 0x40000000 +#define BRX_OVERFLOW_CHECKTYPE 0x80000000 +#define BRX_AGCSHIFT 0x7f +#define BTRSW_TRI_ONLY 0x80 +#define BPOWER_THRES 0x300 +#define BRXAGC_EN 0x1 +#define BRXAGC_TOGETHER_EN 0x2 +#define BRXAGC_MIN 0x4 +#define BRXHP_INI 0x7 +#define BRXHP_TRLNA 0x70 +#define BRXHP_RSSI 0x700 +#define BRXHP_BBP1 0x7000 +#define BRXHP_BBP2 0x70000 +#define BRXHP_BBP3 0x700000 +#define BRSSI_H 0x7f0000 +#define BRSSI_GEN 0x7f000000 +#define BRXSETTLE_TRSW 0x7 +#define BRXSETTLE_LNA 0x38 +#define BRXSETTLE_RSSI 0x1c0 +#define BRXSETTLE_BBP 0xe00 +#define BRXSETTLE_RXHP 0x7000 +#define BRXSETTLE_ANTSW_RSSI 0x38000 +#define BRXSETTLE_ANTSW 0xc0000 +#define BRXPROCESS_TIME_DAGC 0x300000 +#define BRXSETTLE_HSSI 0x400000 +#define BRXPROCESS_TIME_BBPPW 0x800000 +#define BRXANTENNA_POWER_SHIFT 0x3000000 +#define BRSSI_TABLE_SELECT 0xc000000 +#define BRXHP_FINAL 0x7000000 +#define BRXHPSETTLE_BBP 0x7 +#define BRXHTSETTLE_HSSI 0x8 +#define BRXHTSETTLE_RXHP 0x70 +#define BRXHTSETTLE_BBPPW 0x80 +#define BRXHTSETTLE_IDLE 0x300 +#define BRXHTSETTLE_RESERVED 0x1c00 +#define BRXHT_RXHP_EN 0x8000 +#define BRXAGC_FREEZE_THRES 0x30000 +#define BRXAGC_TOGETHEREN 0x40000 +#define BRXHTAGC_MIN 0x80000 +#define BRXHTAGC_EN 0x100000 +#define BRXHTDAGC_EN 0x200000 +#define BRXHT_RXHP_BBP 0x1c00000 +#define BRXHT_RXHP_FINAL 0xe0000000 +#define BRXPW_RADIO_TH 0x3 +#define BRXPW_RADIO_EN 0x4 +#define BRXMF_HOLD 0x3800 +#define BRXPD_DELAY_TH1 0x38 +#define BRXPD_DELAY_TH2 0x1c0 +#define BRXPD_DC_COUNT_MAX 0x600 +#define BRXPD_DELAY_TH 0x8000 +#define BRXPROCESS_DELAY 0xf0000 +#define BRXSEARCHRANGE_GI2_EARLY 0x700000 +#define BRXFRAME_FUARD_COUNTER_L 0x3800000 +#define BRXSGI_GUARD_L 0xc000000 +#define BRXSGI_SEARCH_L 0x30000000 +#define BRXSGI_TH 0xc0000000 +#define BDFSCNT0 0xff +#define BDFSCNT1 0xff00 +#define BDFSFLAG 0xf0000 +#define BMF_WEIGHT_SUM 0x300000 +#define BMINIDX_TH 0x7f000000 +#define BDAFORMAT 0x40000 +#define BTXCH_EMU_ENABLE 0x01000000 +#define BTRSW_ISOLATION_A 0x7f +#define BTRSW_ISOLATION_B 0x7f00 +#define BTRSW_ISOLATION_C 0x7f0000 +#define BTRSW_ISOLATION_D 0x7f000000 +#define BEXT_LNA_GAIN 0x7c00 + +#define BSTBC_EN 0x4 +#define BANTENNA_MAPPING 0x10 +#define BNSS 0x20 +#define BCFO_ANTSUM_ID 0x200 +#define BPHY_COUNTER_RESET 0x8000000 +#define BCFO_REPORT_GET 0x4000000 +#define BOFDM_CONTINUE_TX 0x10000000 +#define BOFDM_SINGLE_CARRIER 0x20000000 +#define BOFDM_SINGLE_TONE 0x40000000 +#define BHT_DETECT 0x100 +#define BCFOEN 0x10000 +#define BCFOVALUE 0xfff00000 +#define BSIGTONE_RE 0x3f +#define BSIGTONE_IM 0x7f00 +#define BCOUNTER_CCA 0xffff +#define BCOUNTER_PARITYFAIL 0xffff0000 +#define BCOUNTER_RATEILLEGAL 0xffff +#define BCOUNTER_CRC8FAIL 0xffff0000 +#define BCOUNTER_MCSNOSUPPORT 0xffff +#define BCOUNTER_FASTSYNC 0xffff +#define BSHORTCFO 0xfff +#define BSHORTCFOT_LENGTH 12 +#define BSHORTCFOF_LENGTH 11 +#define BLONGCFO 0x7ff +#define BLONGCFOT_LENGTH 11 +#define BLONGCFOF_LENGTH 11 +#define BTAILCFO 0x1fff +#define BTAILCFOT_LENGTH 13 +#define BTAILCFOF_LENGTH 12 +#define BNOISE_EN_PWDB 0xffff +#define BCC_POWER_DB 0xffff0000 +#define BMOISE_PWDB 0xffff +#define BPOWERMEAST_LENGTH 10 +#define BPOWERMEASF_LENGTH 3 +#define BRX_HT_BW 0x1 +#define BRXSC 0x6 +#define BRX_HT 0x8 +#define BNB_INTF_DET_ON 0x1 +#define BINTF_WIN_LEN_CFG 0x30 +#define BNB_INTF_TH_CFG 0x1c0 +#define BRFGAIN 0x3f +#define BTABLESEL 0x40 +#define BTRSW 0x80 +#define BRXSNR_A 0xff +#define BRXSNR_B 0xff00 +#define BRXSNR_C 0xff0000 +#define BRXSNR_D 0xff000000 +#define BSNR_EVMT_LENGTH 8 +#define BSNR_EVMF_LENGTH 1 +#define BCSI1ST 0xff +#define BCSI2ND 0xff00 +#define BRXEVM1ST 0xff0000 +#define BRXEVM2ND 0xff000000 +#define BSIGEVM 0xff +#define BPWDB 0xff00 +#define BSGIEN 0x10000 + +#define BSFACTOR_QMA1 0xf +#define BSFACTOR_QMA2 0xf0 +#define BSFACTOR_QMA3 0xf00 +#define BSFACTOR_QMA4 0xf000 +#define BSFACTOR_QMA5 0xf0000 +#define BSFACTOR_QMA6 0xf0000 +#define BSFACTOR_QMA7 0xf00000 +#define BSFACTOR_QMA8 0xf000000 +#define BSFACTOR_QMA9 0xf0000000 +#define BCSI_SCHEME 0x100000 + +#define BNOISE_LVL_TOP_SET 0x3 +#define BCHSMOOTH 0x4 +#define BCHSMOOTH_CFG1 0x38 +#define BCHSMOOTH_CFG2 0x1c0 +#define BCHSMOOTH_CFG3 0xe00 +#define BCHSMOOTH_CFG4 0x7000 +#define BMRCMODE 0x800000 +#define BTHEVMCFG 0x7000000 + +#define BLOOP_FIT_TYPE 0x1 +#define BUPD_CFO 0x40 +#define BUPD_CFO_OFFDATA 0x80 +#define BADV_UPD_CFO 0x100 +#define BADV_TIME_CTRL 0x800 +#define BUPD_CLKO 0x1000 +#define BFC 0x6000 +#define BTRACKING_MODE 0x8000 +#define BPHCMP_ENABLE 0x10000 +#define BUPD_CLKO_LTF 0x20000 +#define BCOM_CH_CFO 0x40000 +#define BCSI_ESTI_MODE 0x80000 +#define BADV_UPD_EQZ 0x100000 +#define BUCHCFG 0x7000000 +#define BUPDEQZ 0x8000000 + +#define BRX_PESUDO_NOISE_ON 0x20000000 +#define BRX_PESUDO_NOISE_A 0xff +#define BRX_PESUDO_NOISE_B 0xff00 +#define BRX_PESUDO_NOISE_C 0xff0000 +#define BRX_PESUDO_NOISE_D 0xff000000 +#define BRX_PESUDO_NOISESTATE_A 0xffff +#define BRX_PESUDO_NOISESTATE_B 0xffff0000 +#define BRX_PESUDO_NOISESTATE_C 0xffff +#define BRX_PESUDO_NOISESTATE_D 0xffff0000 + +#define BZEBRA1_HSSIENABLE 0x8 +#define BZEBRA1_TRXCONTROL 0xc00 +#define BZEBRA1_TRXGAINSETTING 0x07f +#define BZEBRA1_RXCOUNTER 0xc00 +#define BZEBRA1_TXCHANGEPUMP 0x38 +#define BZEBRA1_RXCHANGEPUMP 0x7 +#define BZEBRA1_CHANNEL_NUM 0xf80 +#define BZEBRA1_TXLPFBW 0x400 +#define BZEBRA1_RXLPFBW 0x600 + +#define BRTL8256REG_MODE_CTRL1 0x100 +#define BRTL8256REG_MODE_CTRL0 0x40 +#define BRTL8256REG_TXLPFBW 0x18 +#define BRTL8256REG_RXLPFBW 0x600 + +#define BRTL8258_TXLPFBW 0xc +#define BRTL8258_RXLPFBW 0xc00 +#define BRTL8258_RSSILPFBW 0xc0 + +#define BBYTE0 0x1 +#define BBYTE1 0x2 +#define BBYTE2 0x4 +#define BBYTE3 0x8 +#define BWORD0 0x3 +#define BWORD1 0xc +#define BWORD 0xf + +#define MASKBYTE0 0xff +#define MASKBYTE1 0xff00 +#define MASKBYTE2 0xff0000 +#define MASKBYTE3 0xff000000 +#define MASKHWORD 0xffff0000 +#define MASKLWORD 0x0000ffff +#define MASKDWORD 0xffffffff +#define MASK12BITS 0xfff +#define MASKH4BITS 0xf0000000 +#define MASKOFDM_D 0xffc00000 +#define MASKCCK 0x3f3f3f3f + +#define MASK4BITS 0x0f +#define MASK20BITS 0xfffff +#define RFREG_OFFSET_MASK 0xfffff + +#define BENABLE 0x1 +#define BDISABLE 0x0 + +#define LEFT_ANTENNA 0x0 +#define RIGHT_ANTENNA 0x1 + +#define TCHECK_TXSTATUS 500 +#define TUPDATE_RXCOUNTER 100 + +/* 2 EFUSE_TEST (For RTL8723 partially) */ +#define EFUSE_SEL(x) (((x) & 0x3) << 8) +#define EFUSE_SEL_MASK 0x300 +#define EFUSE_WIFI_SEL_0 0x0 +/* Enable GPIO[9] as WiFi HW PDn source*/ +#define WL_HWPDN_EN BIT(0) +/* WiFi HW PDn polarity control*/ +#define WL_HWPDN_SL BIT(1) + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c new file mode 100644 index 000000000000..9ebc8281ff99 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.c @@ -0,0 +1,514 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" + +static bool _rtl8723e_phy_rf6052_config_parafile(struct ieee80211_hw *hw); + +void rtl8723e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff) | 0x0400); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + case HT_CHANNEL_WIDTH_20_40: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff)); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", bandwidth); + break; + } +} + +void rtl8723e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 tx_agc[2] = {0, 0}, tmpval; + bool turbo_scanoff = false; + u8 idx1, idx2; + u8 *ptr; + + if (rtlefuse->eeprom_regulatory != 0) + turbo_scanoff = true; + + if (mac->act_scanning == true) { + tx_agc[RF90_PATH_A] = 0x3f3f3f3f; + tx_agc[RF90_PATH_B] = 0x3f3f3f3f; + + if (turbo_scanoff) { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; + idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + } + } else { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + + if (rtlefuse->eeprom_regulatory == 0) { + tmpval = + (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + + (rtlphy->mcs_txpwrlevel_origoffset[0][7] << + 8); + tx_agc[RF90_PATH_A] += tmpval; + + tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + + (rtlphy->mcs_txpwrlevel_origoffset[0][15] << + 24); + tx_agc[RF90_PATH_B] += tmpval; + } + } + + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + ptr = (u8 *)&tx_agc[idx1]; + for (idx2 = 0; idx2 < 4; idx2++) { + if (*ptr > RF6052_MAX_TX_PWR) + *ptr = RF6052_MAX_TX_PWR; + ptr++; + } + } + + tmpval = tx_agc[RF90_PATH_A] & 0xff; + rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_A_CCK1_MCS32); + + tmpval = tx_agc[RF90_PATH_A] >> 8; + + tmpval = tmpval & 0xff00ffff; + + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK11_A_CCK2_11); + + tmpval = tx_agc[RF90_PATH_B] >> 24; + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK11_A_CCK2_11); + + tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; + rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK1_55_MCS32); +} + +static void rtl8723e_phy_get_power_base(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel, + u32 *ofdmbase, u32 *mcsbase) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 powerbase0, powerbase1; + u8 legacy_pwrdiff, ht20_pwrdiff; + u8 i, powerlevel[2]; + + for (i = 0; i < 2; i++) { + powerlevel[i] = ppowerlevel[i]; + legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; + powerbase0 = powerlevel[i] + legacy_pwrdiff; + + powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | + (powerbase0 << 8) | powerbase0; + *(ofdmbase + i) = powerbase0; + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [OFDM power base index rf(%c) = 0x%x]\n", + ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)); + } + + for (i = 0; i < 2; i++) { + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { + ht20_pwrdiff = + rtlefuse->txpwr_ht20diff[i][channel - 1]; + powerlevel[i] += ht20_pwrdiff; + } + powerbase1 = powerlevel[i]; + powerbase1 = (powerbase1 << 24) | + (powerbase1 << 16) | (powerbase1 << 8) | powerbase1; + + *(mcsbase + i) = powerbase1; + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [MCS power base index rf(%c) = 0x%x]\n", + ((i == 0) ? 'A' : 'B'), *(mcsbase + i)); + } +} + +static void get_txpower_writeval_by_reg(struct ieee80211_hw *hw, + u8 channel, u8 index, + u32 *powerbase0, + u32 *powerbase1, + u32 *p_outwriteval) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 i, chnlgroup = 0, pwr_diff_limit[4]; + u32 writeval, customer_limit, rf; + + for (rf = 0; rf < 2; rf++) { + switch (rtlefuse->eeprom_regulatory) { + case 0: + chnlgroup = 0; + + writeval = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index + + (rf ? 8 : 0)] + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + case 1: + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + writeval = ((index < 2) ? powerbase0[rf] : + powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Realtek regulatory, 40MHz, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + } else { + if (rtlphy->pwrgroup_cnt == 1) + chnlgroup = 0; + if (rtlphy->pwrgroup_cnt >= 3) { + if (channel <= 3) + chnlgroup = 0; + else if (channel >= 4 && channel <= 9) + chnlgroup = 1; + else if (channel > 9) + chnlgroup = 2; + if (rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20) + chnlgroup++; + else + chnlgroup += 4; + } + + writeval = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] + [index + (rf ? 8 : 0)] + ((index < 2) ? + powerbase0[rf] : + powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + } + break; + case 2: + writeval = + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Better regulatory, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + case 3: + chnlgroup = 0; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 40MHz rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), + rtlefuse->pwrgroup_ht40[rf][channel - + 1]); + } else { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 20MHz rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), + rtlefuse->pwrgroup_ht20[rf][channel - + 1]); + } + for (i = 0; i < 4; i++) { + pwr_diff_limit[i] = + (u8)((rtlphy->mcs_txpwrlevel_origoffset + [chnlgroup][index + + (rf ? 8 : 0)] & (0x7f << + (i * 8))) >> (i * 8)); + + if (rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20_40) { + if (pwr_diff_limit[i] > + rtlefuse-> + pwrgroup_ht40[rf][channel - 1]) + pwr_diff_limit[i] = + rtlefuse->pwrgroup_ht40[rf] + [channel - 1]; + } else { + if (pwr_diff_limit[i] > + rtlefuse-> + pwrgroup_ht20[rf][channel - 1]) + pwr_diff_limit[i] = + rtlefuse->pwrgroup_ht20[rf] + [channel - 1]; + } + } + + customer_limit = (pwr_diff_limit[3] << 24) | + (pwr_diff_limit[2] << 16) | + (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer's limit rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), customer_limit); + + writeval = customer_limit + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer, writeval rf(%c)= 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + default: + chnlgroup = 0; + writeval = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] + [index + (rf ? 8 : 0)] + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeval rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + } + + if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) + writeval = writeval - 0x06060606; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_BT2) + writeval = writeval - 0x0c0c0c0c; + *(p_outwriteval + rf) = writeval; + } +} + +static void _rtl8723e_write_ofdm_power_reg(struct ieee80211_hw *hw, + u8 index, u32 *pvalue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + u16 regoffset_a[6] = { + RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, + RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, + RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 + }; + u16 regoffset_b[6] = { + RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, + RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, + RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 + }; + u8 i, rf, pwr_val[4]; + u32 writeval; + u16 regoffset; + + for (rf = 0; rf < 2; rf++) { + writeval = pvalue[rf]; + for (i = 0; i < 4; i++) { + pwr_val[i] = (u8)((writeval & (0x7f << + (i * 8))) >> (i * 8)); + + if (pwr_val[i] > RF6052_MAX_TX_PWR) + pwr_val[i] = RF6052_MAX_TX_PWR; + } + writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | + (pwr_val[1] << 8) | pwr_val[0]; + + if (rf == 0) + regoffset = regoffset_a[index]; + else + regoffset = regoffset_b[index]; + rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Set 0x%x = %08x\n", regoffset, writeval); + + if (((get_rf_type(rtlphy) == RF_2T2R) && + (regoffset == RTXAGC_A_MCS15_MCS12 || + regoffset == RTXAGC_B_MCS15_MCS12)) || + ((get_rf_type(rtlphy) != RF_2T2R) && + (regoffset == RTXAGC_A_MCS07_MCS04 || + regoffset == RTXAGC_B_MCS07_MCS04))) { + + writeval = pwr_val[3]; + if (regoffset == RTXAGC_A_MCS15_MCS12 || + regoffset == RTXAGC_A_MCS07_MCS04) + regoffset = 0xc90; + if (regoffset == RTXAGC_B_MCS15_MCS12 || + regoffset == RTXAGC_B_MCS07_MCS04) + regoffset = 0xc98; + + for (i = 0; i < 3; i++) { + writeval = (writeval > 6) ? (writeval - 6) : 0; + rtl_write_byte(rtlpriv, (u32) (regoffset + i), + (u8)writeval); + } + } + } +} + +void rtl8723e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel) +{ + u32 writeval[2], powerbase0[2], powerbase1[2]; + u8 index; + + rtl8723e_phy_get_power_base(hw, ppowerlevel, + channel, &powerbase0[0], &powerbase1[0]); + + for (index = 0; index < 6; index++) { + get_txpower_writeval_by_reg(hw, channel, index, &powerbase0[0], + &powerbase1[0], + &writeval[0]); + + _rtl8723e_write_ofdm_power_reg(hw, index, &writeval[0]); + } +} + +bool rtl8723e_phy_rf6052_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + if (rtlphy->rf_type == RF_1T1R) + rtlphy->num_total_rfpath = 1; + else + rtlphy->num_total_rfpath = 2; + + return _rtl8723e_phy_rf6052_config_parafile(hw); +} + +static bool _rtl8723e_phy_rf6052_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 u4_regvalue = 0; + u8 rfpath; + bool rtstatus = true; + struct bb_reg_def *pphyreg; + + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + + pphyreg = &rtlphy->phyreg_def[rfpath]; + + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV); + break; + case RF90_PATH_B: + case RF90_PATH_D: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16); + break; + } + + rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, + B3WIREADDREAALENGTH, 0x0); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); + udelay(1); + + switch (rfpath) { + case RF90_PATH_A: + rtstatus = rtl8723e_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_B: + rtstatus = + rtl8723e_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_C: + break; + case RF90_PATH_D: + break; + } + + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV, u4_regvalue); + break; + case RF90_PATH_B: + case RF90_PATH_D: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16, u4_regvalue); + break; + } + + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio[%d] Fail!!", rfpath); + return false; + } + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); + return rtstatus; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h new file mode 100644 index 000000000000..7b44ebc0fac9 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/rf.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_RF_H__ +#define __RTL8723E_RF_H__ + +#define RF6052_MAX_TX_PWR 0x3F + +void rtl8723e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, + u8 bandwidth); +void rtl8723e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +void rtl8723e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); +bool rtl8723e_phy_rf6052_config(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c new file mode 100644 index 000000000000..3859b3e3d158 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c @@ -0,0 +1,405 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../core.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "../rtl8723com/fw_common.h" +#include "hw.h" +#include "sw.h" +#include "trx.h" +#include "led.h" +#include "table.h" +#include "hal_btc.h" +#include "../btcoexist/rtl_btc.h" +#include "../rtl8723com/phy_common.h" + +#include +#include + +static void rtl8723e_init_aspm_vars(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /** + * ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + */ + rtlpci->const_pci_aspm = 3; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /** + * In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 0; + + /** + * This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 1; +} + +int rtl8723e_init_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + int err = 0; + + rtl8723e_bt_reg_init(hw); + + rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); + + rtlpriv->dm.dm_initialgain_enable = 1; + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.disable_framebursting = 0; + rtlpriv->dm.thermalvalue = 0; + rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13); + + /* compatible 5G band 88ce just 2.4G band & smsp */ + rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; + rtlpriv->rtlhal.bandset = BAND_ON_2_4G; + rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; + + rtlpci->receive_config = (RCR_APPFCS | + RCR_APP_MIC | + RCR_APP_ICV | + RCR_APP_PHYST_RXFF | + RCR_HTC_LOC_CTRL | + RCR_AMF | + RCR_ACF | + RCR_ADF | + RCR_AICV | + RCR_AB | + RCR_AM | + RCR_APM | + 0); + + rtlpci->irq_mask[0] = + (u32) (PHIMR_ROK | + PHIMR_RDU | + PHIMR_VODOK | + PHIMR_VIDOK | + PHIMR_BEDOK | + PHIMR_BKDOK | + PHIMR_MGNTDOK | + PHIMR_HIGHDOK | + PHIMR_C2HCMD | + PHIMR_HISRE_IND | + PHIMR_TSF_BIT32_TOGGLE | + PHIMR_TXBCNOK | + PHIMR_PSTIMEOUT | + 0); + + rtlpci->irq_mask[1] = + (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; + rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; + if (rtlpriv->cfg->mod_params->disable_watchdog) + pr_info("watchdog disabled\n"); + rtlpriv->psc.reg_fwctrl_lps = 3; + rtlpriv->psc.reg_max_lps_awakeintvl = 5; + rtl8723e_init_aspm_vars(hw); + + if (rtlpriv->psc.reg_fwctrl_lps == 1) + rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 2) + rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 3) + rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(0x6000); + if (!rtlpriv->rtlhal.pfirmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't alloc buffer for fw.\n"); + return 1; + } + + if (IS_VENDOR_8723_A_CUT(rtlhal->version)) + rtlpriv->cfg->fw_name = "rtlwifi/rtl8723fw.bin"; + else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) + rtlpriv->cfg->fw_name = "rtlwifi/rtl8723fw_B.bin"; + + rtlpriv->max_fw_size = 0x6000; + pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); + err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, + rtlpriv->io.dev, GFP_KERNEL, hw, + rtl_fw_cb); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to request firmware!\n"); + return 1; + } + return 0; +} + +void rtl8723e_deinit_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.pfirmware) { + vfree(rtlpriv->rtlhal.pfirmware); + rtlpriv->rtlhal.pfirmware = NULL; + } +} + +/* get bt coexist status */ +bool rtl8723e_get_btc_status(void) +{ + return true; +} + +static bool is_fw_header(struct rtlwifi_firmware_header *hdr) +{ + return (le16_to_cpu(hdr->signature) & 0xfff0) == 0x2300; +} + +static struct rtl_hal_ops rtl8723e_hal_ops = { + .init_sw_vars = rtl8723e_init_sw_vars, + .deinit_sw_vars = rtl8723e_deinit_sw_vars, + .read_eeprom_info = rtl8723e_read_eeprom_info, + .interrupt_recognized = rtl8723e_interrupt_recognized, + .hw_init = rtl8723e_hw_init, + .hw_disable = rtl8723e_card_disable, + .hw_suspend = rtl8723e_suspend, + .hw_resume = rtl8723e_resume, + .enable_interrupt = rtl8723e_enable_interrupt, + .disable_interrupt = rtl8723e_disable_interrupt, + .set_network_type = rtl8723e_set_network_type, + .set_chk_bssid = rtl8723e_set_check_bssid, + .set_qos = rtl8723e_set_qos, + .set_bcn_reg = rtl8723e_set_beacon_related_registers, + .set_bcn_intv = rtl8723e_set_beacon_interval, + .update_interrupt_mask = rtl8723e_update_interrupt_mask, + .get_hw_reg = rtl8723e_get_hw_reg, + .set_hw_reg = rtl8723e_set_hw_reg, + .update_rate_tbl = rtl8723e_update_hal_rate_tbl, + .fill_tx_desc = rtl8723e_tx_fill_desc, + .fill_tx_cmddesc = rtl8723e_tx_fill_cmddesc, + .query_rx_desc = rtl8723e_rx_query_desc, + .set_channel_access = rtl8723e_update_channel_access_setting, + .radio_onoff_checking = rtl8723e_gpio_radio_on_off_checking, + .set_bw_mode = rtl8723e_phy_set_bw_mode, + .switch_channel = rtl8723e_phy_sw_chnl, + .dm_watchdog = rtl8723e_dm_watchdog, + .scan_operation_backup = rtl8723e_phy_scan_operation_backup, + .set_rf_power_state = rtl8723e_phy_set_rf_power_state, + .led_control = rtl8723e_led_control, + .set_desc = rtl8723e_set_desc, + .get_desc = rtl8723e_get_desc, + .is_tx_desc_closed = rtl8723e_is_tx_desc_closed, + .tx_polling = rtl8723e_tx_polling, + .enable_hw_sec = rtl8723e_enable_hw_security_config, + .set_key = rtl8723e_set_key, + .init_sw_leds = rtl8723e_init_sw_leds, + .get_bbreg = rtl8723_phy_query_bb_reg, + .set_bbreg = rtl8723_phy_set_bb_reg, + .get_rfreg = rtl8723e_phy_query_rf_reg, + .set_rfreg = rtl8723e_phy_set_rf_reg, + .c2h_command_handle = rtl_8723e_c2h_command_handle, + .bt_wifi_media_status_notify = rtl_8723e_bt_wifi_media_status_notify, + .bt_coex_off_before_lps = + rtl8723e_dm_bt_turn_off_bt_coexist_before_enter_lps, + .get_btc_status = rtl8723e_get_btc_status, + .rx_command_packet = rtl8723e_rx_command_packet, + .is_fw_header = is_fw_header, +}; + +static struct rtl_mod_params rtl8723e_mod_params = { + .sw_crypto = false, + .inactiveps = true, + .swctrl_lps = false, + .fwctrl_lps = true, + .debug = DBG_EMERG, +}; + +static struct rtl_hal_cfg rtl8723e_hal_cfg = { + .bar_id = 2, + .write_readback = true, + .name = "rtl8723e_pci", + .fw_name = "rtlwifi/rtl8723efw.bin", + .ops = &rtl8723e_hal_ops, + .mod_params = &rtl8723e_mod_params, + .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, + .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, + .maps[SYS_CLK] = REG_SYS_CLKR, + .maps[MAC_RCR_AM] = AM, + .maps[MAC_RCR_AB] = AB, + .maps[MAC_RCR_ACRC32] = ACRC32, + .maps[MAC_RCR_ACF] = ACF, + .maps[MAC_RCR_AAP] = AAP, + .maps[MAC_HIMR] = REG_HIMR, + .maps[MAC_HIMRE] = REG_HIMRE, + .maps[EFUSE_TEST] = REG_EFUSE_TEST, + .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_CLK] = 0, + .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_PWC_EV12V] = PWC_EV12V, + .maps[EFUSE_FEN_ELDR] = FEN_ELDR, + .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, + .maps[EFUSE_ANA8M] = ANA8M, + .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, + .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, + .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, + .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, + + .maps[RWCAM] = REG_CAMCMD, + .maps[WCAMI] = REG_CAMWRITE, + .maps[RCAMO] = REG_CAMREAD, + .maps[CAMDBG] = REG_CAMDBG, + .maps[SECR] = REG_SECCFG, + .maps[SEC_CAM_NONE] = CAM_NONE, + .maps[SEC_CAM_WEP40] = CAM_WEP40, + .maps[SEC_CAM_TKIP] = CAM_TKIP, + .maps[SEC_CAM_AES] = CAM_AES, + .maps[SEC_CAM_WEP104] = CAM_WEP104, + + .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, + .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, + .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, + .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, + .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, + .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, + .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, + .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, + .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, + .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, + .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, + .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, + .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, + .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, + .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, + .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, + + .maps[RTL_IMR_TXFOVW] = PHIMR_TXFOVW, + .maps[RTL_IMR_PSTIMEOUT] = PHIMR_PSTIMEOUT, + .maps[RTL_IMR_BCNINT] = PHIMR_BCNDMAINT0, + .maps[RTL_IMR_RXFOVW] = PHIMR_RXFOVW, + .maps[RTL_IMR_RDU] = PHIMR_RDU, + .maps[RTL_IMR_ATIMEND] = PHIMR_ATIMEND_E, + .maps[RTL_IMR_BDOK] = PHIMR_BCNDOK0, + .maps[RTL_IMR_MGNTDOK] = PHIMR_MGNTDOK, + .maps[RTL_IMR_TBDER] = PHIMR_TXBCNERR, + .maps[RTL_IMR_HIGHDOK] = PHIMR_HIGHDOK, + .maps[RTL_IMR_TBDOK] = PHIMR_TXBCNOK, + .maps[RTL_IMR_BKDOK] = PHIMR_BKDOK, + .maps[RTL_IMR_BEDOK] = PHIMR_BEDOK, + .maps[RTL_IMR_VIDOK] = PHIMR_VIDOK, + .maps[RTL_IMR_VODOK] = PHIMR_VODOK, + .maps[RTL_IMR_ROK] = PHIMR_ROK, + .maps[RTL_IBSS_INT_MASKS] = + (PHIMR_BCNDMAINT0 | PHIMR_TXBCNOK | PHIMR_TXBCNERR), + .maps[RTL_IMR_C2HCMD] = PHIMR_C2HCMD, + + + .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, +}; + +static struct pci_device_id rtl8723e_pci_ids[] = { + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8723, rtl8723e_hal_cfg)}, + {}, +}; + +MODULE_DEVICE_TABLE(pci, rtl8723e_pci_ids); + +MODULE_AUTHOR("lizhaoming "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_LICENSE("GPL"); +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(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); +module_param_named(disable_watchdog, rtl8723e_mod_params.disable_watchdog, + bool, 0444); +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(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); + +static struct pci_driver rtl8723e_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl8723e_pci_ids, + .probe = rtl_pci_probe, + .remove = rtl_pci_disconnect, + .driver.pm = &rtlwifi_pm_ops, +}; + +module_pci_driver(rtl8723e_driver); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h new file mode 100644 index 000000000000..46478780d262 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.h @@ -0,0 +1,35 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_SW_H__ +#define __RTL8723E_SW_H__ + +int rtl8723e_init_sw_vars(struct ieee80211_hw *hw); +void rtl8723e_deinit_sw_vars(struct ieee80211_hw *hw); +void rtl8723e_init_var_map(struct ieee80211_hw *hw); +bool rtl8723e_get_btc_status(void); + + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c new file mode 100644 index 000000000000..61e86045f15c --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.c @@ -0,0 +1,732 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger + * + *****************************************************************************/ + +#include "table.h" + +u32 RTL8723EPHY_REG_1TARRAY[RTL8723E_PHY_REG_1TARRAY_LENGTH] = { + 0x800, 0x80040000, + 0x804, 0x00000003, + 0x808, 0x0000fc00, + 0x80c, 0x0000000a, + 0x810, 0x10005388, + 0x814, 0x020c3d10, + 0x818, 0x02200385, + 0x81c, 0x00000000, + 0x820, 0x01000100, + 0x824, 0x00390004, + 0x828, 0x00000000, + 0x82c, 0x00000000, + 0x830, 0x00000000, + 0x834, 0x00000000, + 0x838, 0x00000000, + 0x83c, 0x00000000, + 0x840, 0x00010000, + 0x844, 0x00000000, + 0x848, 0x00000000, + 0x84c, 0x00000000, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x569a569a, + 0x85c, 0x001b25a4, + 0x860, 0x66f60110, + 0x864, 0x061f0130, + 0x868, 0x00000000, + 0x86c, 0x32323200, + 0x870, 0x07000760, + 0x874, 0x22004000, + 0x878, 0x00000808, + 0x87c, 0x00000000, + 0x880, 0xc0083070, + 0x884, 0x000004d5, + 0x888, 0x00000000, + 0x88c, 0xccc000c0, + 0x890, 0x00000800, + 0x894, 0xfffffffe, + 0x898, 0x40302010, + 0x89c, 0x00706050, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90c, 0x81121111, + 0xa00, 0x00d047c8, + 0xa04, 0x80ff000c, + 0xa08, 0x8c838300, + 0xa0c, 0x2e68120f, + 0xa10, 0x9500bb78, + 0xa14, 0x11144028, + 0xa18, 0x00881117, + 0xa1c, 0x89140f00, + 0xa20, 0x1a1b0000, + 0xa24, 0x090e1317, + 0xa28, 0x00000204, + 0xa2c, 0x00d30000, + 0xa70, 0x101fbf00, + 0xa74, 0x00000007, + 0xa78, 0x00000900, + 0xc00, 0x48071d40, + 0xc04, 0x03a05611, + 0xc08, 0x000000e4, + 0xc0c, 0x6c6c6c6c, + 0xc10, 0x08800000, + 0xc14, 0x40000100, + 0xc18, 0x08800000, + 0xc1c, 0x40000100, + 0xc20, 0x00000000, + 0xc24, 0x00000000, + 0xc28, 0x00000000, + 0xc2c, 0x00000000, + 0xc30, 0x69e9ac44, + 0xc34, 0x469652cf, + 0xc38, 0x49795994, + 0xc3c, 0x0a97971c, + 0xc40, 0x1f7c403f, + 0xc44, 0x000100b7, + 0xc48, 0xec020107, + 0xc4c, 0x007f037f, + 0xc50, 0x69543420, + 0xc54, 0x43bc0094, + 0xc58, 0x69543420, + 0xc5c, 0x433c0094, + 0xc60, 0x00000000, + 0xc64, 0x7116848b, + 0xc68, 0x47c00bff, + 0xc6c, 0x00000036, + 0xc70, 0x2c7f000d, + 0xc74, 0x018610db, + 0xc78, 0x0000001f, + 0xc7c, 0x00b91612, + 0xc80, 0x40000100, + 0xc84, 0x20f60000, + 0xc88, 0x40000100, + 0xc8c, 0x20200000, + 0xc90, 0x00121820, + 0xc94, 0x00000000, + 0xc98, 0x00121820, + 0xc9c, 0x00007f7f, + 0xca0, 0x00000000, + 0xca4, 0x00000080, + 0xca8, 0x00000000, + 0xcac, 0x00000000, + 0xcb0, 0x00000000, + 0xcb4, 0x00000000, + 0xcb8, 0x00000000, + 0xcbc, 0x28000000, + 0xcc0, 0x00000000, + 0xcc4, 0x00000000, + 0xcc8, 0x00000000, + 0xccc, 0x00000000, + 0xcd0, 0x00000000, + 0xcd4, 0x00000000, + 0xcd8, 0x64b22427, + 0xcdc, 0x00766932, + 0xce0, 0x00222222, + 0xce4, 0x00000000, + 0xce8, 0x37644302, + 0xcec, 0x2f97d40c, + 0xd00, 0x00080740, + 0xd04, 0x00020401, + 0xd08, 0x0000907f, + 0xd0c, 0x20010201, + 0xd10, 0xa0633333, + 0xd14, 0x3333bc43, + 0xd18, 0x7a8f5b6b, + 0xd2c, 0xcc979975, + 0xd30, 0x00000000, + 0xd34, 0x80608000, + 0xd38, 0x00000000, + 0xd3c, 0x00027293, + 0xd40, 0x00000000, + 0xd44, 0x00000000, + 0xd48, 0x00000000, + 0xd4c, 0x00000000, + 0xd50, 0x6437140a, + 0xd54, 0x00000000, + 0xd58, 0x00000000, + 0xd5c, 0x30032064, + 0xd60, 0x4653de68, + 0xd64, 0x04518a3c, + 0xd68, 0x00002101, + 0xd6c, 0x2a201c16, + 0xd70, 0x1812362e, + 0xd74, 0x322c2220, + 0xd78, 0x000e3c24, + 0xe00, 0x2a2a2a2a, + 0xe04, 0x2a2a2a2a, + 0xe08, 0x03902a2a, + 0xe10, 0x2a2a2a2a, + 0xe14, 0x2a2a2a2a, + 0xe18, 0x2a2a2a2a, + 0xe1c, 0x2a2a2a2a, + 0xe28, 0x00000000, + 0xe30, 0x1000dc1f, + 0xe34, 0x10008c1f, + 0xe38, 0x02140102, + 0xe3c, 0x681604c2, + 0xe40, 0x01007c00, + 0xe44, 0x01004800, + 0xe48, 0xfb000000, + 0xe4c, 0x000028d1, + 0xe50, 0x1000dc1f, + 0xe54, 0x10008c1f, + 0xe58, 0x02140102, + 0xe5c, 0x28160d05, + 0xe60, 0x00000008, + 0xe68, 0x001b25a4, + 0xe6c, 0x631b25a0, + 0xe70, 0x631b25a0, + 0xe74, 0x081b25a0, + 0xe78, 0x081b25a0, + 0xe7c, 0x081b25a0, + 0xe80, 0x081b25a0, + 0xe84, 0x631b25a0, + 0xe88, 0x081b25a0, + 0xe8c, 0x631b25a0, + 0xed0, 0x631b25a0, + 0xed4, 0x631b25a0, + 0xed8, 0x631b25a0, + 0xedc, 0x001b25a0, + 0xee0, 0x001b25a0, + 0xeec, 0x6b1b25a0, + 0xf14, 0x00000003, + 0xf4c, 0x00000000, + 0xf00, 0x00000300, +}; + +u32 RTL8723EPHY_REG_ARRAY_PG[RTL8723E_PHY_REG_ARRAY_PGLENGTH] = { + 0xe00, 0xffffffff, 0x0a0c0c0c, + 0xe04, 0xffffffff, 0x02040608, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x0a0c0d0e, + 0xe14, 0xffffffff, 0x02040608, + 0xe18, 0xffffffff, 0x0a0c0d0e, + 0xe1c, 0xffffffff, 0x02040608, + 0x830, 0xffffffff, 0x0a0c0c0c, + 0x834, 0xffffffff, 0x02040608, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x0a0c0d0e, + 0x848, 0xffffffff, 0x02040608, + 0x84c, 0xffffffff, 0x0a0c0d0e, + 0x868, 0xffffffff, 0x02040608, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x06060606, + 0xe14, 0xffffffff, 0x00020406, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x06060606, + 0x848, 0xffffffff, 0x00020406, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x04040404, + 0xe04, 0xffffffff, 0x00020204, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x04040404, + 0x834, 0xffffffff, 0x00020204, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, + 0xe00, 0xffffffff, 0x00000000, + 0xe04, 0xffffffff, 0x00000000, + 0xe08, 0x0000ff00, 0x00000000, + 0x86c, 0xffffff00, 0x00000000, + 0xe10, 0xffffffff, 0x00000000, + 0xe14, 0xffffffff, 0x00000000, + 0xe18, 0xffffffff, 0x00000000, + 0xe1c, 0xffffffff, 0x00000000, + 0x830, 0xffffffff, 0x00000000, + 0x834, 0xffffffff, 0x00000000, + 0x838, 0xffffff00, 0x00000000, + 0x86c, 0x000000ff, 0x00000000, + 0x83c, 0xffffffff, 0x00000000, + 0x848, 0xffffffff, 0x00000000, + 0x84c, 0xffffffff, 0x00000000, + 0x868, 0xffffffff, 0x00000000, +}; + +u32 RTL8723E_RADIOA_1TARRAY[RTL8723ERADIOA_1TARRAYLENGTH] = { + 0x000, 0x00030159, + 0x001, 0x00031284, + 0x002, 0x00098000, + 0x003, 0x00018c63, + 0x004, 0x000210e7, + 0x009, 0x0002044f, + 0x00a, 0x0001a3f1, + 0x00b, 0x00014787, + 0x00c, 0x000896fe, + 0x00d, 0x0000e02c, + 0x00e, 0x00039ce7, + 0x00f, 0x00000451, + 0x019, 0x00000000, + 0x01a, 0x00030355, + 0x01b, 0x00060a00, + 0x01c, 0x000fc378, + 0x01d, 0x000a1250, + 0x01e, 0x0004445f, + 0x01f, 0x00080001, + 0x020, 0x0000b614, + 0x021, 0x0006c000, + 0x022, 0x00000000, + 0x023, 0x00001558, + 0x024, 0x00000060, + 0x025, 0x00000483, + 0x026, 0x0004f000, + 0x027, 0x000ec7d9, + 0x028, 0x00057730, + 0x029, 0x00004783, + 0x02a, 0x00000001, + 0x02b, 0x00021334, + 0x02a, 0x00000000, + 0x02b, 0x00000054, + 0x02a, 0x00000001, + 0x02b, 0x00000808, + 0x02b, 0x00053333, + 0x02c, 0x0000000c, + 0x02a, 0x00000002, + 0x02b, 0x00000808, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000003, + 0x02b, 0x00000808, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000004, + 0x02b, 0x00000808, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000005, + 0x02b, 0x00000808, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x00000006, + 0x02b, 0x00000709, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000007, + 0x02b, 0x00000709, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x00000008, + 0x02b, 0x0000060a, + 0x02b, 0x0004b333, + 0x02c, 0x0000000d, + 0x02a, 0x00000009, + 0x02b, 0x0000060a, + 0x02b, 0x00053333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000a, + 0x02b, 0x0000060a, + 0x02b, 0x0005b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000b, + 0x02b, 0x0000060a, + 0x02b, 0x00063333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000c, + 0x02b, 0x0000060a, + 0x02b, 0x0006b333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000d, + 0x02b, 0x0000060a, + 0x02b, 0x00073333, + 0x02c, 0x0000000d, + 0x02a, 0x0000000e, + 0x02b, 0x0000050b, + 0x02b, 0x00066666, + 0x02c, 0x0000001a, + 0x02a, 0x000e0000, + 0x010, 0x0004000f, + 0x011, 0x000e31fc, + 0x010, 0x0006000f, + 0x011, 0x000ff9f8, + 0x010, 0x0002000f, + 0x011, 0x000203f9, + 0x010, 0x0003000f, + 0x011, 0x000ff500, + 0x010, 0x00000000, + 0x011, 0x00000000, + 0x010, 0x0008000f, + 0x011, 0x0003f100, + 0x010, 0x0009000f, + 0x011, 0x00023100, + 0x012, 0x00032000, + 0x012, 0x00071000, + 0x012, 0x000b0000, + 0x012, 0x000fc000, + 0x013, 0x000287b3, + 0x013, 0x000244b7, + 0x013, 0x000204ab, + 0x013, 0x0001c49f, + 0x013, 0x00018493, + 0x013, 0x0001429b, + 0x013, 0x00010299, + 0x013, 0x0000c29c, + 0x013, 0x000081a0, + 0x013, 0x000040ac, + 0x013, 0x00000020, + 0x014, 0x0001944c, + 0x014, 0x00059444, + 0x014, 0x0009944c, + 0x014, 0x000d9444, + 0x015, 0x0000f424, + 0x015, 0x0004f407, + 0x015, 0x0008f424, + 0x015, 0x000cf424, + 0x016, 0x00000339, + 0x016, 0x00040339, + 0x016, 0x00080339, + 0x016, 0x000c0336, + 0x000, 0x00010159, + 0x018, 0x0000f401, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01f, 0x00080003, + 0x0fe, 0x00000000, + 0x0fe, 0x00000000, + 0x01e, 0x00044457, + 0x01f, 0x00080000, + 0x000, 0x00030159, +}; + +u32 RTL8723E_RADIOB_1TARRAY[RTL8723E_RADIOB_1TARRAYLENGTH] = { + 0x0, +}; + +u32 RTL8723EMAC_ARRAY[RTL8723E_MACARRAYLENGTH] = { + 0x420, 0x00000080, + 0x423, 0x00000000, + 0x430, 0x00000000, + 0x431, 0x00000000, + 0x432, 0x00000000, + 0x433, 0x00000001, + 0x434, 0x00000004, + 0x435, 0x00000005, + 0x436, 0x00000006, + 0x437, 0x00000007, + 0x438, 0x00000000, + 0x439, 0x00000000, + 0x43a, 0x00000000, + 0x43b, 0x00000001, + 0x43c, 0x00000004, + 0x43d, 0x00000005, + 0x43e, 0x00000006, + 0x43f, 0x00000007, + 0x440, 0x0000005d, + 0x441, 0x00000001, + 0x442, 0x00000000, + 0x444, 0x00000015, + 0x445, 0x000000f0, + 0x446, 0x0000000f, + 0x447, 0x00000000, + 0x458, 0x00000041, + 0x459, 0x000000a8, + 0x45a, 0x00000072, + 0x45b, 0x000000b9, + 0x460, 0x00000066, + 0x461, 0x00000066, + 0x462, 0x00000008, + 0x463, 0x00000003, + 0x4c8, 0x000000ff, + 0x4c9, 0x00000008, + 0x4cc, 0x000000ff, + 0x4cd, 0x000000ff, + 0x4ce, 0x00000001, + 0x500, 0x00000026, + 0x501, 0x000000a2, + 0x502, 0x0000002f, + 0x503, 0x00000000, + 0x504, 0x00000028, + 0x505, 0x000000a3, + 0x506, 0x0000005e, + 0x507, 0x00000000, + 0x508, 0x0000002b, + 0x509, 0x000000a4, + 0x50a, 0x0000005e, + 0x50b, 0x00000000, + 0x50c, 0x0000004f, + 0x50d, 0x000000a4, + 0x50e, 0x00000000, + 0x50f, 0x00000000, + 0x512, 0x0000001c, + 0x514, 0x0000000a, + 0x515, 0x00000010, + 0x516, 0x0000000a, + 0x517, 0x00000010, + 0x51a, 0x00000016, + 0x524, 0x0000000f, + 0x525, 0x0000004f, + 0x546, 0x00000040, + 0x547, 0x00000000, + 0x550, 0x00000010, + 0x551, 0x00000010, + 0x559, 0x00000002, + 0x55a, 0x00000002, + 0x55d, 0x000000ff, + 0x605, 0x00000030, + 0x608, 0x0000000e, + 0x609, 0x0000002a, + 0x652, 0x00000020, + 0x63c, 0x0000000a, + 0x63d, 0x0000000e, + 0x63e, 0x0000000a, + 0x63f, 0x0000000e, + 0x66e, 0x00000005, + 0x700, 0x00000021, + 0x701, 0x00000043, + 0x702, 0x00000065, + 0x703, 0x00000087, + 0x708, 0x00000021, + 0x709, 0x00000043, + 0x70a, 0x00000065, + 0x70b, 0x00000087, +}; + +u32 RTL8723EAGCTAB_1TARRAY[RTL8723E_AGCTAB_1TARRAYLENGTH] = { + 0xc78, 0x7b000001, + 0xc78, 0x7b010001, + 0xc78, 0x7b020001, + 0xc78, 0x7b030001, + 0xc78, 0x7b040001, + 0xc78, 0x7b050001, + 0xc78, 0x7a060001, + 0xc78, 0x79070001, + 0xc78, 0x78080001, + 0xc78, 0x77090001, + 0xc78, 0x760a0001, + 0xc78, 0x750b0001, + 0xc78, 0x740c0001, + 0xc78, 0x730d0001, + 0xc78, 0x720e0001, + 0xc78, 0x710f0001, + 0xc78, 0x70100001, + 0xc78, 0x6f110001, + 0xc78, 0x6e120001, + 0xc78, 0x6d130001, + 0xc78, 0x6c140001, + 0xc78, 0x6b150001, + 0xc78, 0x6a160001, + 0xc78, 0x69170001, + 0xc78, 0x68180001, + 0xc78, 0x67190001, + 0xc78, 0x661a0001, + 0xc78, 0x651b0001, + 0xc78, 0x641c0001, + 0xc78, 0x631d0001, + 0xc78, 0x621e0001, + 0xc78, 0x611f0001, + 0xc78, 0x60200001, + 0xc78, 0x49210001, + 0xc78, 0x48220001, + 0xc78, 0x47230001, + 0xc78, 0x46240001, + 0xc78, 0x45250001, + 0xc78, 0x44260001, + 0xc78, 0x43270001, + 0xc78, 0x42280001, + 0xc78, 0x41290001, + 0xc78, 0x402a0001, + 0xc78, 0x262b0001, + 0xc78, 0x252c0001, + 0xc78, 0x242d0001, + 0xc78, 0x232e0001, + 0xc78, 0x222f0001, + 0xc78, 0x21300001, + 0xc78, 0x20310001, + 0xc78, 0x06320001, + 0xc78, 0x05330001, + 0xc78, 0x04340001, + 0xc78, 0x03350001, + 0xc78, 0x02360001, + 0xc78, 0x01370001, + 0xc78, 0x00380001, + 0xc78, 0x00390001, + 0xc78, 0x003a0001, + 0xc78, 0x003b0001, + 0xc78, 0x003c0001, + 0xc78, 0x003d0001, + 0xc78, 0x003e0001, + 0xc78, 0x003f0001, + 0xc78, 0x7b400001, + 0xc78, 0x7b410001, + 0xc78, 0x7b420001, + 0xc78, 0x7b430001, + 0xc78, 0x7b440001, + 0xc78, 0x7b450001, + 0xc78, 0x7a460001, + 0xc78, 0x79470001, + 0xc78, 0x78480001, + 0xc78, 0x77490001, + 0xc78, 0x764a0001, + 0xc78, 0x754b0001, + 0xc78, 0x744c0001, + 0xc78, 0x734d0001, + 0xc78, 0x724e0001, + 0xc78, 0x714f0001, + 0xc78, 0x70500001, + 0xc78, 0x6f510001, + 0xc78, 0x6e520001, + 0xc78, 0x6d530001, + 0xc78, 0x6c540001, + 0xc78, 0x6b550001, + 0xc78, 0x6a560001, + 0xc78, 0x69570001, + 0xc78, 0x68580001, + 0xc78, 0x67590001, + 0xc78, 0x665a0001, + 0xc78, 0x655b0001, + 0xc78, 0x645c0001, + 0xc78, 0x635d0001, + 0xc78, 0x625e0001, + 0xc78, 0x615f0001, + 0xc78, 0x60600001, + 0xc78, 0x49610001, + 0xc78, 0x48620001, + 0xc78, 0x47630001, + 0xc78, 0x46640001, + 0xc78, 0x45650001, + 0xc78, 0x44660001, + 0xc78, 0x43670001, + 0xc78, 0x42680001, + 0xc78, 0x41690001, + 0xc78, 0x406a0001, + 0xc78, 0x266b0001, + 0xc78, 0x256c0001, + 0xc78, 0x246d0001, + 0xc78, 0x236e0001, + 0xc78, 0x226f0001, + 0xc78, 0x21700001, + 0xc78, 0x20710001, + 0xc78, 0x06720001, + 0xc78, 0x05730001, + 0xc78, 0x04740001, + 0xc78, 0x03750001, + 0xc78, 0x02760001, + 0xc78, 0x01770001, + 0xc78, 0x00780001, + 0xc78, 0x00790001, + 0xc78, 0x007a0001, + 0xc78, 0x007b0001, + 0xc78, 0x007c0001, + 0xc78, 0x007d0001, + 0xc78, 0x007e0001, + 0xc78, 0x007f0001, + 0xc78, 0x3800001e, + 0xc78, 0x3801001e, + 0xc78, 0x3802001e, + 0xc78, 0x3803001e, + 0xc78, 0x3804001e, + 0xc78, 0x3805001e, + 0xc78, 0x3806001e, + 0xc78, 0x3807001e, + 0xc78, 0x3808001e, + 0xc78, 0x3c09001e, + 0xc78, 0x3e0a001e, + 0xc78, 0x400b001e, + 0xc78, 0x440c001e, + 0xc78, 0x480d001e, + 0xc78, 0x4c0e001e, + 0xc78, 0x500f001e, + 0xc78, 0x5210001e, + 0xc78, 0x5611001e, + 0xc78, 0x5a12001e, + 0xc78, 0x5e13001e, + 0xc78, 0x6014001e, + 0xc78, 0x6015001e, + 0xc78, 0x6016001e, + 0xc78, 0x6217001e, + 0xc78, 0x6218001e, + 0xc78, 0x6219001e, + 0xc78, 0x621a001e, + 0xc78, 0x621b001e, + 0xc78, 0x621c001e, + 0xc78, 0x621d001e, + 0xc78, 0x621e001e, + 0xc78, 0x621f001e, +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h new file mode 100644 index 000000000000..57a548ceba7d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/table.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_TABLE__H_ +#define __RTL8723E_TABLE__H_ + +#include + +#define RTL8723E_PHY_REG_1TARRAY_LENGTH 372 +extern u32 RTL8723EPHY_REG_1TARRAY[RTL8723E_PHY_REG_1TARRAY_LENGTH]; +#define RTL8723E_PHY_REG_ARRAY_PGLENGTH 336 +extern u32 RTL8723EPHY_REG_ARRAY_PG[RTL8723E_PHY_REG_ARRAY_PGLENGTH]; +#define RTL8723ERADIOA_1TARRAYLENGTH 282 +extern u32 RTL8723E_RADIOA_1TARRAY[RTL8723ERADIOA_1TARRAYLENGTH]; +#define RTL8723E_RADIOB_1TARRAYLENGTH 1 +extern u32 RTL8723E_RADIOB_1TARRAY[RTL8723E_RADIOB_1TARRAYLENGTH]; +#define RTL8723E_MACARRAYLENGTH 172 +extern u32 RTL8723EMAC_ARRAY[RTL8723E_MACARRAYLENGTH]; +#define RTL8723E_AGCTAB_1TARRAYLENGTH 320 +extern u32 RTL8723EAGCTAB_1TARRAY[RTL8723E_AGCTAB_1TARRAYLENGTH]; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c new file mode 100644 index 000000000000..2f7c144d7980 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c @@ -0,0 +1,717 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../stats.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "trx.h" +#include "led.h" + +static u8 _rtl8723e_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) +{ + __le16 fc = rtl_get_fc(skb); + + if (unlikely(ieee80211_is_beacon(fc))) + return QSLT_BEACON; + if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) + return QSLT_MGNT; + + return skb->priority; +} + +static void _rtl8723e_query_rxphystatus(struct ieee80211_hw *hw, + struct rtl_stats *pstatus, u8 *pdesc, + struct rx_fwinfo_8723e *p_drvinfo, + bool bpacket_match_bssid, + bool bpacket_toself, bool packet_beacon) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); + struct phy_sts_cck_8723e_t *cck_buf; + s8 rx_pwr_all = 0, rx_pwr[4]; + u8 rf_rx_num = 0, evm, pwdb_all; + u8 i, max_spatial_stream; + u32 rssi, total_rssi = 0; + bool is_cck = pstatus->is_cck; + + /* Record it for next packet processing */ + pstatus->packet_matchbssid = bpacket_match_bssid; + pstatus->packet_toself = bpacket_toself; + pstatus->packet_beacon = packet_beacon; + pstatus->rx_mimo_signalquality[0] = -1; + pstatus->rx_mimo_signalquality[1] = -1; + + if (is_cck) { + u8 report, cck_highpwr; + + /* CCK Driver info Structure is not the same as OFDM packet. */ + cck_buf = (struct phy_sts_cck_8723e_t *)p_drvinfo; + + /* (1)Hardware does not provide RSSI for CCK */ + /* (2)PWDB, Average PWDB cacluated by + * hardware (for rate adaptive) + */ + if (ppsc->rfpwr_state == ERFON) + cck_highpwr = (u8)rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + BIT(9)); + else + cck_highpwr = false; + + if (!cck_highpwr) { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = cck_buf->cck_agc_rpt & 0xc0; + report = report >> 6; + switch (report) { + case 0x3: + rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); + break; + case 0x2: + rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); + break; + case 0x1: + rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); + break; + case 0x0: + rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); + break; + } + } else { + u8 cck_agc_rpt = cck_buf->cck_agc_rpt; + report = p_drvinfo->cfosho[0] & 0x60; + report = report >> 5; + switch (report) { + case 0x3: + rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x2: + rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x1: + rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1); + break; + case 0x0: + rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1); + break; + } + } + + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + /* CCK gain is smaller than OFDM/MCS gain, */ + /* so we add gain diff by experiences, + * the val is 6 + */ + pwdb_all += 6; + if (pwdb_all > 100) + pwdb_all = 100; + /* modify the offset to make the same + * gain index with OFDM. + */ + if (pwdb_all > 34 && pwdb_all <= 42) + pwdb_all -= 2; + else if (pwdb_all > 26 && pwdb_all <= 34) + pwdb_all -= 6; + else if (pwdb_all > 14 && pwdb_all <= 26) + pwdb_all -= 8; + else if (pwdb_all > 4 && pwdb_all <= 14) + pwdb_all -= 4; + + pstatus->rx_pwdb_all = pwdb_all; + pstatus->recvsignalpower = rx_pwr_all; + + /* (3) Get Signal Quality (EVM) */ + if (bpacket_match_bssid) { + u8 sq; + + if (pstatus->rx_pwdb_all > 40) + sq = 100; + else { + sq = cck_buf->sq_rpt; + if (sq > 64) + sq = 0; + else if (sq < 20) + sq = 100; + else + sq = ((64 - sq) * 100) / 44; + } + + pstatus->signalquality = sq; + pstatus->rx_mimo_signalquality[0] = sq; + pstatus->rx_mimo_signalquality[1] = -1; + } + } else { + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + + /* (1)Get RSSI for HT rate */ + for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { + + /* we will judge RF RX path now. */ + if (rtlpriv->dm.rfpath_rxenable[i]) + rf_rx_num++; + + rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & + 0x3f) * 2) - 110; + + /* Translate DBM to percentage. */ + rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + + /* Get Rx snr value in DB */ + rtlpriv->stats.rx_snr_db[i] = + (long)(p_drvinfo->rxsnr[i] / 2); + + /* Record Signal Strength for next packet */ + if (bpacket_match_bssid) + pstatus->rx_mimo_signalstrength[i] = (u8)rssi; + } + + /* (2)PWDB, Average PWDB cacluated by + * hardware (for rate adaptive) + */ + rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; + + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + pstatus->rx_pwdb_all = pwdb_all; + pstatus->rxpower = rx_pwr_all; + pstatus->recvsignalpower = rx_pwr_all; + + /* (3)EVM of HT rate */ + if (pstatus->is_ht && pstatus->rate >= DESC92C_RATEMCS8 && + pstatus->rate <= DESC92C_RATEMCS15) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + + for (i = 0; i < max_spatial_stream; i++) { + evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]); + + if (bpacket_match_bssid) { + /* Fill value in RFD, Get the first + * spatial stream only + */ + if (i == 0) + pstatus->signalquality = + (u8)(evm & 0xff); + pstatus->rx_mimo_signalquality[i] = + (u8)(evm & 0xff); + } + } + } + + /* UI BSS List signal strength(in percentage), + * make it good looking, from 0~100. + */ + if (is_cck) + pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, + pwdb_all)); + else if (rf_rx_num != 0) + pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, + total_rssi /= rf_rx_num)); +} + +static void translate_rx_signal_stuff(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct rtl_stats *pstatus, u8 *pdesc, + struct rx_fwinfo_8723e *p_drvinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct ieee80211_hdr *hdr; + u8 *tmp_buf; + u8 *praddr; + /*u8 *psaddr;*/ + u16 fc, type; + bool packet_matchbssid, packet_toself, packet_beacon; + + tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; + + hdr = (struct ieee80211_hdr *)tmp_buf; + fc = le16_to_cpu(hdr->frame_control); + type = WLAN_FC_GET_TYPE(hdr->frame_control); + praddr = hdr->addr1; + + packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && + (ether_addr_equal(mac->bssid, (fc & IEEE80211_FCTL_TODS) ? + hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? + hdr->addr2 : hdr->addr3)) && + (!pstatus->hwerror) && + (!pstatus->crc) && (!pstatus->icv)); + + packet_toself = packet_matchbssid && + (ether_addr_equal(praddr, rtlefuse->dev_addr)); + + if (ieee80211_is_beacon(hdr->frame_control)) + packet_beacon = true; + else + packet_beacon = false; + + _rtl8723e_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo, + packet_matchbssid, packet_toself, + packet_beacon); + + rtl_process_phyinfo(hw, tmp_buf, pstatus); +} + +bool rtl8723e_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *status, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb) +{ + struct rx_fwinfo_8723e *p_drvinfo; + struct ieee80211_hdr *hdr; + u32 phystatus = GET_RX_DESC_PHYST(pdesc); + + status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); + status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * + RX_DRV_INFO_SIZE_UNIT; + status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03); + status->icv = (u16)GET_RX_DESC_ICV(pdesc); + status->crc = (u16)GET_RX_DESC_CRC32(pdesc); + status->hwerror = (status->crc | status->icv); + status->decrypted = !GET_RX_DESC_SWDEC(pdesc); + status->rate = (u8)GET_RX_DESC_RXMCS(pdesc); + status->shortpreamble = (u16)GET_RX_DESC_SPLCP(pdesc); + status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); + status->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1) && + (GET_RX_DESC_FAGGR(pdesc) == 1)); + status->timestamp_low = GET_RX_DESC_TSFL(pdesc); + status->rx_is40Mhzpacket = (bool)GET_RX_DESC_BW(pdesc); + status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); + + status->is_cck = RX_HAL_IS_CCK_RATE(status->rate); + + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + + hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size + + status->rx_bufshift); + + if (status->crc) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (status->rx_is40Mhzpacket) + rx_status->flag |= RX_FLAG_40MHZ; + + if (status->is_ht) + rx_status->flag |= RX_FLAG_HT; + + rx_status->flag |= RX_FLAG_MACTIME_START; + + /* hw will set status->decrypted true, if it finds the + * frame is open data frame or mgmt frame. + * So hw will not decryption robust managment frame + * for IEEE80211w but still set status->decrypted + * true, so here we should set it back to undecrypted + * for IEEE80211w frame, and mac80211 sw will help + * to decrypt it + */ + if (status->decrypted) { + if ((!_ieee80211_is_robust_mgmt_frame(hdr)) && + (ieee80211_has_protected(hdr->frame_control))) + rx_status->flag |= RX_FLAG_DECRYPTED; + else + rx_status->flag &= ~RX_FLAG_DECRYPTED; + } + + /* rate_idx: index of data rate into band's + * supported rates or MCS index if HT rates + * are use (RX_FLAG_HT) + * Notice: this is diff with windows define + */ + rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht, + false, status->rate); + + rx_status->mactime = status->timestamp_low; + if (phystatus == true) { + p_drvinfo = (struct rx_fwinfo_8723e *)(skb->data + + status->rx_bufshift); + + translate_rx_signal_stuff(hw, skb, status, pdesc, p_drvinfo); + } + rx_status->signal = status->recvsignalpower + 10; + return true; +} + +void rtl8723e_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *txbd, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool b_defaultadapter = true; + /* bool b_trigger_ac = false; */ + u8 *pdesc = (u8 *)pdesc_tx; + u16 seq_number; + __le16 fc = hdr->frame_control; + u8 fw_qsel = _rtl8723e_map_hwqueue_to_fwqueue(skb, hw_queue); + bool firstseg = ((hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); + + bool lastseg = ((hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); + + dma_addr_t mapping = pci_map_single(rtlpci->pdev, + skb->data, skb->len, + PCI_DMA_TODEVICE); + u8 bw_40 = 0; + + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + if (mac->opmode == NL80211_IFTYPE_STATION) { + bw_40 = mac->bw_40; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta) + bw_40 = sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40; + } + + seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + + rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); + + CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_8723e)); + + if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { + firstseg = true; + lastseg = true; + } + + if (firstseg) { + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + + SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); + + if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) + SET_TX_DESC_DATA_SHORTGI(pdesc, 1); + + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + SET_TX_DESC_AGG_BREAK(pdesc, 1); + SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); + } + SET_TX_DESC_SEQ(pdesc, seq_number); + + SET_TX_DESC_RTS_ENABLE(pdesc, + ((ptcb_desc->rts_enable && + !ptcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_HW_RTS_ENABLE(pdesc, + ((ptcb_desc->rts_enable || + ptcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_CTS2SELF(pdesc, + ((ptcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_RTS_STBC(pdesc, + ((ptcb_desc->rts_stbc) ? 1 : 0)); + + SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); + SET_TX_DESC_RTS_BW(pdesc, 0); + SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); + SET_TX_DESC_RTS_SHORT(pdesc, + ((ptcb_desc->rts_rate <= DESC92C_RATE54M) ? + (ptcb_desc->rts_use_shortpreamble ? 1 : 0) + : (ptcb_desc->rts_use_shortgi ? 1 : 0))); + + if (bw_40) { + if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { + SET_TX_DESC_DATA_BW(pdesc, 1); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + mac->cur_40_prime_sc); + } + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + } + + SET_TX_DESC_LINIP(pdesc, 0); + SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); + + if (sta) { + u8 ampdu_density = sta->ht_cap.ampdu_density; + SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); + } + + if (info->control.hw_key) { + struct ieee80211_key_conf *keyconf = + info->control.hw_key; + + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x1); + break; + case WLAN_CIPHER_SUITE_CCMP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x3); + break; + default: + SET_TX_DESC_SEC_TYPE(pdesc, 0x0); + break; + + } + } + + SET_TX_DESC_PKT_ID(pdesc, 0); + SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); + + SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); + SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); + SET_TX_DESC_DISABLE_FB(pdesc, 0); + SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); + + if (ieee80211_is_data_qos(fc)) { + if (mac->rdg_en) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "Enable RDG function.\n"); + SET_TX_DESC_RDG_ENABLE(pdesc, 1); + SET_TX_DESC_HTC(pdesc, 1); + } + } + } + + SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); + SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); + + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); + + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + + if (rtlpriv->dm.useramask) { + SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); + } else { + SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); + } + + if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { + SET_TX_DESC_HWSEQ_EN_8723(pdesc, 1); + /* SET_TX_DESC_HWSEQ_EN(pdesc, 1); */ + /* SET_TX_DESC_PKT_ID(pdesc, 8); */ + + if (!b_defaultadapter) + SET_TX_DESC_HWSEQ_SEL_8723(pdesc, 1); + /* SET_TX_DESC_QOS(pdesc, 1); */ + } + + SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); + + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { + SET_TX_DESC_BMC(pdesc, 1); + } + + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); +} + +void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw, + u8 *pdesc, bool firstseg, + bool lastseg, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 fw_queue = QSLT_BEACON; + + dma_addr_t mapping = pci_map_single(rtlpci->pdev, + skb->data, skb->len, + PCI_DMA_TODEVICE); + + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + __le16 fc = hdr->frame_control; + + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); + + if (firstseg) + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + + SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); + + SET_TX_DESC_SEQ(pdesc, 0); + + SET_TX_DESC_LINIP(pdesc, 0); + + SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len)); + + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + + SET_TX_DESC_RATE_ID(pdesc, 7); + SET_TX_DESC_MACID(pdesc, 0); + + SET_TX_DESC_OWN(pdesc, 1); + + SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len)); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_OFFSET(pdesc, 0x20); + + SET_TX_DESC_USE_RATE(pdesc, 1); + + if (!ieee80211_is_data_qos(fc)) { + SET_TX_DESC_HWSEQ_EN_8723(pdesc, 1); + /* SET_TX_DESC_HWSEQ_EN(pdesc, 1); */ + /* SET_TX_DESC_PKT_ID(pdesc, 8); */ + } + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C Tx Cmd Content\n", + pdesc, TX_DESC_SIZE); +} + +void rtl8723e_set_desc(struct ieee80211_hw *hw, u8 *pdesc, + bool istx, u8 desc_name, u8 *val) +{ + if (istx == true) { + switch (desc_name) { + case HW_DESC_OWN: + SET_TX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_TX_NEXTDESC_ADDR: + SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); + break; + default: + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_RXOWN: + SET_RX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_RXBUFF_ADDR: + SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val); + break; + case HW_DESC_RXPKT_LEN: + SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val); + break; + case HW_DESC_RXERO: + SET_RX_DESC_EOR(pdesc, 1); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); + break; + } + } +} + +u32 rtl8723e_get_desc(u8 *pdesc, bool istx, u8 desc_name) +{ + u32 ret = 0; + + if (istx == true) { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_TX_DESC_OWN(pdesc); + break; + case HW_DESC_TXBUFF_ADDR: + ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc); + break; + default: + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_RX_DESC_OWN(pdesc); + break; + case HW_DESC_RXPKT_LEN: + ret = GET_RX_DESC_PKT_LEN(pdesc); + break; + case HW_DESC_RXBUFF_ADDR: + ret = GET_RX_DESC_BUFF_ADDR(pdesc); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); + break; + } + } + return ret; +} + +bool rtl8723e_is_tx_desc_closed(struct ieee80211_hw *hw, + u8 hw_queue, u16 index) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; + u8 *entry = (u8 *)(&ring->desc[ring->idx]); + u8 own = (u8)rtl8723e_get_desc(entry, true, HW_DESC_OWN); + + /** + *beacon packet will only use the first + *descriptor defautly,and the own may not + *be cleared by the hardware + */ + if (own) + return false; + return true; +} + +void rtl8723e_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (hw_queue == BEACON_QUEUE) { + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); + } else { + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, + BIT(0) << (hw_queue)); + } +} + +u32 rtl8723e_rx_command_packet(struct ieee80211_hw *hw, + struct rtl_stats status, + struct sk_buff *skb) +{ + return 0; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h new file mode 100644 index 000000000000..017da7e194d8 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.h @@ -0,0 +1,721 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723E_TRX_H__ +#define __RTL8723E_TRX_H__ + +#define TX_DESC_SIZE 64 +#define TX_DESC_AGGR_SUBFRAME_SIZE 32 + +#define RX_DESC_SIZE 32 +#define RX_DRV_INFO_SIZE_UNIT 8 + +#define TX_DESC_NEXT_DESC_OFFSET 40 +#define USB_HWDESC_HEADER_LEN 32 +#define CRCLENGTH 4 + +#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) +#define SET_TX_DESC_OFFSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) +#define SET_TX_DESC_BMC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) +#define SET_TX_DESC_HTC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) +#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) +#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) +#define SET_TX_DESC_LINIP(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) +#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) +#define SET_TX_DESC_GF(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) +#define SET_TX_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +#define GET_TX_DESC_PKT_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 0, 16) +#define GET_TX_DESC_OFFSET(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 16, 8) +#define GET_TX_DESC_BMC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 24, 1) +#define GET_TX_DESC_HTC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 25, 1) +#define GET_TX_DESC_LAST_SEG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 26, 1) +#define GET_TX_DESC_FIRST_SEG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 27, 1) +#define GET_TX_DESC_LINIP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 28, 1) +#define GET_TX_DESC_NO_ACM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 29, 1) +#define GET_TX_DESC_GF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 30, 1) +#define GET_TX_DESC_OWN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 31, 1) + +#define SET_TX_DESC_MACID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 5, __val) +#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 5, 1, __val) +#define SET_TX_DESC_BK(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 6, 1, __val) +#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 7, 1, __val) +#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) +#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) +#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) +#define SET_TX_DESC_PIFS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) +#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val) +#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val) +#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) +#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) +#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val) + +#define GET_TX_DESC_MACID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) +#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 5, 1) +#define GET_TX_DESC_AGG_BREAK(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 6, 1) +#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 7, 1) +#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 8, 5) +#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) +#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) +#define GET_TX_DESC_PIFS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) +#define GET_TX_DESC_RATE_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) +#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) +#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) +#define GET_TX_DESC_SEC_TYPE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 22, 2) +#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 24, 8) + +#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val) +#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val) +#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val) +#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) +#define SET_TX_DESC_RAW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) +#define SET_TX_DESC_CCX(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) +#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) +#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val) +#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val) +#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val) +#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val) +#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val) + +#define GET_TX_DESC_RTS_RC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 0, 6) +#define GET_TX_DESC_DATA_RC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 6, 6) +#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 14, 2) +#define GET_TX_DESC_MORE_FRAG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 17, 1) +#define GET_TX_DESC_RAW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 18, 1) +#define GET_TX_DESC_CCX(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 19, 1) +#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 20, 3) +#define GET_TX_DESC_ANTSEL_A(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 24, 1) +#define GET_TX_DESC_ANTSEL_B(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 25, 1) +#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 26, 2) +#define GET_TX_DESC_TX_ANTL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 28, 2) +#define GET_TX_DESC_TX_ANT_HT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 30, 2) + +#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val) +#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val) +#define SET_TX_DESC_SEQ(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val) +#define SET_TX_DESC_PKT_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 4, __val) + +#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 0, 8) +#define GET_TX_DESC_TAIL_PAGE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 8, 8) +#define GET_TX_DESC_SEQ(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 16, 12) +#define GET_TX_DESC_PKT_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 28, 4) + +/* For RTL8723 */ +#define SET_TX_DESC_TRIGGER_INT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 30, 1, __val) +#define SET_TX_DESC_HWSEQ_EN_8723(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 31, 1, __val) +#define SET_TX_DESC_HWSEQ_SEL_8723(__txdesc, __value) \ + SET_BITS_TO_LE_4BYTE(__txdesc+16, 6, 2, __value) + +#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val) +#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val) +#define SET_TX_DESC_QOS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val) +#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val) +#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val) +#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val) +#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val) +#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val) +#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val) +#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val) +#define SET_TX_DESC_PORT_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val) +#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val) +#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val) +#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val) +#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val) +#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val) +#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val) +#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val) +#define SET_TX_DESC_RTS_BW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val) +#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val) +#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val) + +#define GET_TX_DESC_RTS_RATE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 0, 5) +#define GET_TX_DESC_AP_DCFE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 5, 1) +#define GET_TX_DESC_QOS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 6, 1) +#define GET_TX_DESC_HWSEQ_EN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 7, 1) +#define GET_TX_DESC_USE_RATE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 8, 1) +#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 9, 1) +#define GET_TX_DESC_DISABLE_FB(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 10, 1) +#define GET_TX_DESC_CTS2SELF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 11, 1) +#define GET_TX_DESC_RTS_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 12, 1) +#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 13, 1) +#define GET_TX_DESC_PORT_ID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 14, 1) +#define GET_TX_DESC_WAIT_DCTS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 18, 1) +#define GET_TX_DESC_CTS2AP_EN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 19, 1) +#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 20, 2) +#define GET_TX_DESC_TX_STBC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 22, 2) +#define GET_TX_DESC_DATA_SHORT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 24, 1) +#define GET_TX_DESC_DATA_BW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 25, 1) +#define GET_TX_DESC_RTS_SHORT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 26, 1) +#define GET_TX_DESC_RTS_BW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 27, 1) +#define GET_TX_DESC_RTS_SC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 28, 2) +#define GET_TX_DESC_RTS_STBC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 30, 2) + +#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val) +#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val) +#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val) +#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val) +#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val) + +#define GET_TX_DESC_TX_RATE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 0, 6) +#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 6, 1) +#define GET_TX_DESC_CCX_TAG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 7, 1) +#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 8, 5) +#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 13, 4) +#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 17, 1) +#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 18, 6) +#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 24, 8) + +#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val) +#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val) +#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val) +#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val) +#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val) +#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val) +#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val) +#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val)\ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val) + +#define GET_TX_DESC_TXAGC_A(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 0, 5) +#define GET_TX_DESC_TXAGC_B(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 5, 5) +#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 10, 1) +#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 11, 5) +#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 16, 4) +#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 20, 4) +#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 24, 4) +#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 28, 4) + +#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) +#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 4, __val) +#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 20, 4, __val) +#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val) +#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 28, 4, __val) + +#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) +#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 16, 4) +#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 20, 4) +#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 24, 4) +#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 28, 4) + +#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val) +#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val) + +#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+32, 0, 32) +#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+36, 0, 32) + +#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) +#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val) + +#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+40, 0, 32) +#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+44, 0, 32) + +#define GET_RX_DESC_PKT_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 0, 14) +#define GET_RX_DESC_CRC32(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 14, 1) +#define GET_RX_DESC_ICV(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 15, 1) +#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 16, 4) +#define GET_RX_DESC_SECURITY(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 20, 3) +#define GET_RX_DESC_QOS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 23, 1) +#define GET_RX_DESC_SHIFT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 24, 2) +#define GET_RX_DESC_PHYST(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 26, 1) +#define GET_RX_DESC_SWDEC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 27, 1) +#define GET_RX_DESC_LS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 28, 1) +#define GET_RX_DESC_FS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 29, 1) +#define GET_RX_DESC_EOR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 30, 1) +#define GET_RX_DESC_OWN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 31, 1) + +#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) +#define SET_RX_DESC_EOR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) +#define SET_RX_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +#define GET_RX_DESC_MACID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) +#define GET_RX_DESC_TID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 5, 4) +#define GET_RX_DESC_HWRSVD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 9, 5) +#define GET_RX_DESC_PAGGR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) +#define GET_RX_DESC_FAGGR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) +#define GET_RX_DESC_A1_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) +#define GET_RX_DESC_A2_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 20, 4) +#define GET_RX_DESC_PAM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) +#define GET_RX_DESC_PWR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) +#define GET_RX_DESC_MD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) +#define GET_RX_DESC_MF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) +#define GET_RX_DESC_TYPE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) +#define GET_RX_DESC_MC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) +#define GET_RX_DESC_BC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) +#define GET_RX_DESC_SEQ(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) +#define GET_RX_DESC_FRAG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) +#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 16, 14) +#define GET_RX_DESC_NEXT_IND(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 30, 1) +#define GET_RX_DESC_RSVD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 31, 1) + +#define GET_RX_DESC_RXMCS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 0, 6) +#define GET_RX_DESC_RXHT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 6, 1) +#define GET_RX_DESC_SPLCP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 8, 1) +#define GET_RX_DESC_BW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 9, 1) +#define GET_RX_DESC_HTC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) +#define GET_RX_DESC_HWPC_ERR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 14, 1) +#define GET_RX_DESC_HWPC_IND(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 15, 1) +#define GET_RX_DESC_IV0(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 16, 16) + +#define GET_RX_DESC_IV1(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 0, 32) +#define GET_RX_DESC_TSFL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) + +#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) +#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) + +#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) +#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) + +#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ +do { \ + if (_size > TX_DESC_NEXT_DESC_OFFSET) \ + memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ + else \ + memset(__pdesc, 0, _size); \ +} while (0) + +struct rx_fwinfo_8723e { + u8 gain_trsw[4]; + u8 pwdb_all; + u8 cfosho[4]; + u8 cfotail[4]; + char rxevm[2]; + char rxsnr[4]; + u8 pdsnr[2]; + u8 csi_current[2]; + u8 csi_target[2]; + u8 sigevm; + u8 max_ex_pwr; + u8 ex_intf_flag:1; + u8 sgi_en:1; + u8 rxsc:2; + u8 reserve:4; +} __packed; + +struct tx_desc_8723e { + u32 pktsize:16; + u32 offset:8; + u32 bmc:1; + u32 htc:1; + u32 lastseg:1; + u32 firstseg:1; + u32 linip:1; + u32 noacm:1; + u32 gf:1; + u32 own:1; + + u32 macid:5; + u32 agg_en:1; + u32 bk:1; + u32 rdg_en:1; + u32 queuesel:5; + u32 rd_nav_ext:1; + u32 lsig_txop_en:1; + u32 pifs:1; + u32 rateid:4; + u32 nav_usehdr:1; + u32 en_descid:1; + u32 sectype:2; + u32 pktoffset:8; + + u32 rts_rc:6; + u32 data_rc:6; + u32 rsvd0:2; + u32 bar_retryht:2; + u32 rsvd1:1; + u32 morefrag:1; + u32 raw:1; + u32 ccx:1; + u32 ampdudensity:3; + u32 rsvd2:1; + u32 ant_sela:1; + u32 ant_selb:1; + u32 txant_cck:2; + u32 txant_l:2; + u32 txant_ht:2; + + u32 nextheadpage:8; + u32 tailpage:8; + u32 seq:12; + u32 pktid:4; + + u32 rtsrate:5; + u32 apdcfe:1; + u32 qos:1; + u32 hwseq_enable:1; + u32 userrate:1; + u32 dis_rtsfb:1; + u32 dis_datafb:1; + u32 cts2self:1; + u32 rts_en:1; + u32 hwrts_en:1; + u32 portid:1; + u32 rsvd3:3; + u32 waitdcts:1; + u32 cts2ap_en:1; + u32 txsc:2; + u32 stbc:2; + u32 txshort:1; + u32 txbw:1; + u32 rtsshort:1; + u32 rtsbw:1; + u32 rtssc:2; + u32 rtsstbc:2; + + u32 txrate:6; + u32 shortgi:1; + u32 ccxt:1; + u32 txrate_fb_lmt:5; + u32 rtsrate_fb_lmt:4; + u32 retrylmt_en:1; + u32 txretrylmt:6; + u32 usb_txaggnum:8; + + u32 txagca:5; + u32 txagcb:5; + u32 usemaxlen:1; + u32 maxaggnum:5; + u32 mcsg1maxlen:4; + u32 mcsg2maxlen:4; + u32 mcsg3maxlen:4; + u32 mcs7sgimaxlen:4; + + u32 txbuffersize:16; + u32 mcsg4maxlen:4; + u32 mcsg5maxlen:4; + u32 mcsg6maxlen:4; + u32 mcsg15sgimaxlen:4; + + u32 txbuffaddr; + u32 txbufferaddr64; + u32 nextdescaddress; + u32 nextdescaddress64; + + u32 reserve_pass_pcie_mm_limit[4]; +} __packed; + +struct rx_desc_8723e { + u32 length:14; + u32 crc32:1; + u32 icverror:1; + u32 drv_infosize:4; + u32 security:3; + u32 qos:1; + u32 shift:2; + u32 phystatus:1; + u32 swdec:1; + u32 lastseg:1; + u32 firstseg:1; + u32 eor:1; + u32 own:1; + + u32 macid:5; + u32 tid:4; + u32 hwrsvd:5; + u32 paggr:1; + u32 faggr:1; + u32 a1_fit:4; + u32 a2_fit:4; + u32 pam:1; + u32 pwr:1; + u32 moredata:1; + u32 morefrag:1; + u32 type:2; + u32 mc:1; + u32 bc:1; + + u32 seq:12; + u32 frag:4; + u32 nextpktlen:14; + u32 nextind:1; + u32 rsvd:1; + + u32 rxmcs:6; + u32 rxht:1; + u32 amsdu:1; + u32 splcp:1; + u32 bandwidth:1; + u32 htc:1; + u32 tcpchk_rpt:1; + u32 ipcchk_rpt:1; + u32 tcpchk_valid:1; + u32 hwpcerr:1; + u32 hwpcind:1; + u32 iv0:16; + + u32 iv1; + + u32 tsfl; + + u32 bufferaddress; + u32 bufferaddress64; + +} __packed; + +void rtl8723e_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, + u8 *pdesc, u8 *txbd, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, u8 hw_queue, + struct rtl_tcb_desc *ptcb_desc); +bool rtl8723e_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *status, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb); +void rtl8723e_set_desc(struct ieee80211_hw *hw, + u8 *pdesc, bool istx, u8 desc_name, u8 *val); +u32 rtl8723e_get_desc(u8 *pdesc, bool istx, u8 desc_name); +bool rtl8723e_is_tx_desc_closed(struct ieee80211_hw *hw, + u8 hw_queue, u16 index); +void rtl8723e_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); +void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool firstseg, bool lastseg, + struct sk_buff *skb); +u32 rtl8723e_rx_command_packet(struct ieee80211_hw *hw, + struct rtl_stats status, + struct sk_buff *skb); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/Makefile new file mode 100644 index 000000000000..a77c34102792 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/Makefile @@ -0,0 +1,16 @@ +rtl8723be-objs := \ + dm.o \ + fw.o \ + hw.o \ + led.o \ + phy.o \ + pwrseq.o \ + rf.o \ + sw.o \ + table.o \ + trx.o \ + + +obj-$(CONFIG_RTL8723BE) += rtl8723be.o + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h new file mode 100644 index 000000000000..025ea5c0f3f6 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/def.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723BE_DEF_H__ +#define __RTL8723BE_DEF_H__ + +#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 +#define HAL_PRIME_CHNL_OFFSET_LOWER 1 +#define HAL_PRIME_CHNL_OFFSET_UPPER 2 + + +#define RX_MPDU_QUEUE 0 +#define CHIP_8723B (BIT(1) | BIT(2)) +#define NORMAL_CHIP BIT(3) +#define CHIP_VENDOR_SMIC BIT(8) +/* Currently only for RTL8723B */ +#define EXT_VENDOR_ID (BIT(18) | BIT(19)) + +enum rx_packet_type { + NORMAL_RX, + TX_REPORT1, + TX_REPORT2, + HIS_REPORT, + C2H_PACKET, +}; + +enum rtl_desc_qsel { + QSLT_BK = 0x2, + QSLT_BE = 0x0, + QSLT_VI = 0x5, + QSLT_VO = 0x7, + QSLT_BEACON = 0x10, + QSLT_HIGH = 0x11, + QSLT_MGNT = 0x12, + QSLT_CMD = 0x13, +}; + +enum rtl_desc8723e_rate { + DESC92C_RATE1M = 0x00, + DESC92C_RATE2M = 0x01, + DESC92C_RATE5_5M = 0x02, + DESC92C_RATE11M = 0x03, + + DESC92C_RATE6M = 0x04, + DESC92C_RATE9M = 0x05, + DESC92C_RATE12M = 0x06, + DESC92C_RATE18M = 0x07, + DESC92C_RATE24M = 0x08, + DESC92C_RATE36M = 0x09, + DESC92C_RATE48M = 0x0a, + DESC92C_RATE54M = 0x0b, + + DESC92C_RATEMCS0 = 0x0c, + DESC92C_RATEMCS1 = 0x0d, + DESC92C_RATEMCS2 = 0x0e, + DESC92C_RATEMCS3 = 0x0f, + DESC92C_RATEMCS4 = 0x10, + DESC92C_RATEMCS5 = 0x11, + DESC92C_RATEMCS6 = 0x12, + DESC92C_RATEMCS7 = 0x13, + DESC92C_RATEMCS8 = 0x14, + DESC92C_RATEMCS9 = 0x15, + DESC92C_RATEMCS10 = 0x16, + DESC92C_RATEMCS11 = 0x17, + DESC92C_RATEMCS12 = 0x18, + DESC92C_RATEMCS13 = 0x19, + DESC92C_RATEMCS14 = 0x1a, + DESC92C_RATEMCS15 = 0x1b, +}; +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c new file mode 100644 index 000000000000..3a81cdba8ca3 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c @@ -0,0 +1,1298 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../base.h" +#include "../pci.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "../rtl8723com/dm_common.h" +#include "fw.h" +#include "trx.h" +#include "../btcoexist/rtl_btc.h" + +static const u32 ofdmswing_table[] = { + 0x0b40002d, /* 0, -15.0dB */ + 0x0c000030, /* 1, -14.5dB */ + 0x0cc00033, /* 2, -14.0dB */ + 0x0d800036, /* 3, -13.5dB */ + 0x0e400039, /* 4, -13.0dB */ + 0x0f00003c, /* 5, -12.5dB */ + 0x10000040, /* 6, -12.0dB */ + 0x11000044, /* 7, -11.5dB */ + 0x12000048, /* 8, -11.0dB */ + 0x1300004c, /* 9, -10.5dB */ + 0x14400051, /* 10, -10.0dB */ + 0x15800056, /* 11, -9.5dB */ + 0x16c0005b, /* 12, -9.0dB */ + 0x18000060, /* 13, -8.5dB */ + 0x19800066, /* 14, -8.0dB */ + 0x1b00006c, /* 15, -7.5dB */ + 0x1c800072, /* 16, -7.0dB */ + 0x1e400079, /* 17, -6.5dB */ + 0x20000080, /* 18, -6.0dB */ + 0x22000088, /* 19, -5.5dB */ + 0x24000090, /* 20, -5.0dB */ + 0x26000098, /* 21, -4.5dB */ + 0x288000a2, /* 22, -4.0dB */ + 0x2ac000ab, /* 23, -3.5dB */ + 0x2d4000b5, /* 24, -3.0dB */ + 0x300000c0, /* 25, -2.5dB */ + 0x32c000cb, /* 26, -2.0dB */ + 0x35c000d7, /* 27, -1.5dB */ + 0x390000e4, /* 28, -1.0dB */ + 0x3c8000f2, /* 29, -0.5dB */ + 0x40000100, /* 30, +0dB */ + 0x43c0010f, /* 31, +0.5dB */ + 0x47c0011f, /* 32, +1.0dB */ + 0x4c000130, /* 33, +1.5dB */ + 0x50800142, /* 34, +2.0dB */ + 0x55400155, /* 35, +2.5dB */ + 0x5a400169, /* 36, +3.0dB */ + 0x5fc0017f, /* 37, +3.5dB */ + 0x65400195, /* 38, +4.0dB */ + 0x6b8001ae, /* 39, +4.5dB */ + 0x71c001c7, /* 40, +5.0dB */ + 0x788001e2, /* 41, +5.5dB */ + 0x7f8001fe /* 42, +6.0dB */ +}; + +static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { + {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /* 0, -16.0dB */ + {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 1, -15.5dB */ + {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 2, -15.0dB */ + {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 3, -14.5dB */ + {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 4, -14.0dB */ + {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 5, -13.5dB */ + {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 6, -13.0dB */ + {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 7, -12.5dB */ + {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 8, -12.0dB */ + {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 9, -11.5dB */ + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */ + {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */ + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */ + {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */ + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */ + {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */ + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ + {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */ + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */ + {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */ + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */ + {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */ + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */ + {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */ + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */ + {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */ + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */ + {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */ + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */ + {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */ + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */ + {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */ + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04} /* 32, +0dB */ +}; + +static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { + {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /* 0, -16.0dB */ + {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 1, -15.5dB */ + {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 2, -15.0dB */ + {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 3, -14.5dB */ + {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 4, -14.0dB */ + {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 5, -13.5dB */ + {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 6, -13.0dB */ + {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 7, -12.5dB */ + {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 8, -12.0dB */ + {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 9, -11.5dB */ + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */ + {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */ + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */ + {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */ + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */ + {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */ + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ + {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */ + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */ + {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */ + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */ + {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */ + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */ + {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */ + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */ + {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */ + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */ + {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */ + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */ + {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */ + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */ + {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */ + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00} /* 32, +0dB */ +}; + +static const u32 edca_setting_dl[PEER_MAX] = { + 0xa44f, /* 0 UNKNOWN */ + 0x5ea44f, /* 1 REALTEK_90 */ + 0x5e4322, /* 2 REALTEK_92SE */ + 0x5ea42b, /* 3 BROAD */ + 0xa44f, /* 4 RAL */ + 0xa630, /* 5 ATH */ + 0x5ea630, /* 6 CISCO */ + 0x5ea42b, /* 7 MARVELL */ +}; + +static const u32 edca_setting_ul[PEER_MAX] = { + 0x5e4322, /* 0 UNKNOWN */ + 0xa44f, /* 1 REALTEK_90 */ + 0x5ea44f, /* 2 REALTEK_92SE */ + 0x5ea32b, /* 3 BROAD */ + 0x5ea422, /* 4 RAL */ + 0x5ea322, /* 5 ATH */ + 0x3ea430, /* 6 CISCO */ + 0x5ea44f, /* 7 MARV */ +}; + +void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw *hw, u8 type, + u8 *pdirection, u32 *poutwrite_val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + u8 pwr_val = 0; + u8 ofdm_base = rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A]; + u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A]; + u8 cck_base = rtldm->swing_idx_cck_base; + u8 cck_val = rtldm->swing_idx_cck; + + if (type == 0) { + if (ofdm_val <= ofdm_base) { + *pdirection = 1; + pwr_val = ofdm_base - ofdm_val; + } else { + *pdirection = 2; + pwr_val = ofdm_val - ofdm_base; + } + } else if (type == 1) { + if (cck_val <= cck_base) { + *pdirection = 1; + pwr_val = cck_base - cck_val; + } else { + *pdirection = 2; + pwr_val = cck_val - cck_base; + } + } + + if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1)) + pwr_val = TXPWRTRACK_MAX_IDX; + + *poutwrite_val = pwr_val | (pwr_val << 8) | + (pwr_val << 16) | (pwr_val << 24); +} + +void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rate_adaptive *p_ra = &rtlpriv->ra; + + p_ra->ratr_state = DM_RATR_STA_INIT; + p_ra->pre_ratr_state = DM_RATR_STA_INIT; + + if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) + rtlpriv->dm.useramask = true; + else + rtlpriv->dm.useramask = false; + + p_ra->high_rssi_thresh_for_ra = 50; + p_ra->low_rssi_thresh_for_ra40m = 20; +} + +static void rtl8723be_dm_init_txpower_tracking(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.txpower_tracking = true; + rtlpriv->dm.txpower_track_control = true; + rtlpriv->dm.thermalvalue = 0; + + rtlpriv->dm.ofdm_index[0] = 30; + rtlpriv->dm.cck_index = 20; + + rtlpriv->dm.swing_idx_cck_base = rtlpriv->dm.cck_index; + + rtlpriv->dm.swing_idx_ofdm_base[0] = rtlpriv->dm.ofdm_index[0]; + rtlpriv->dm.delta_power_index[RF90_PATH_A] = 0; + rtlpriv->dm.delta_power_index_last[RF90_PATH_A] = 0; + rtlpriv->dm.power_index_offset[RF90_PATH_A] = 0; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + " rtlpriv->dm.txpower_tracking = %d\n", + rtlpriv->dm.txpower_tracking); +} + +static void rtl8723be_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap; + + rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, 0x800); + rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL; +} + +void rtl8723be_dm_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f); + + rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; + rtl_dm_diginit(hw, cur_igvalue); + rtl8723be_dm_init_rate_adaptive_mask(hw); + rtl8723_dm_init_edca_turbo(hw); + rtl8723_dm_init_dynamic_bb_powersaving(hw); + rtl8723_dm_init_dynamic_txpower(hw); + rtl8723be_dm_init_txpower_tracking(hw); + rtl8723be_dm_init_dynamic_atc_switch(hw); +} + +static void rtl8723be_dm_find_minimum_rssi(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable; + struct rtl_mac *mac = rtl_mac(rtlpriv); + + /* Determine the minimum RSSI */ + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { + rtl_dm_dig->min_undec_pwdb_for_dm = 0; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "Not connected to any\n"); + } + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_dm_dig->min_undec_pwdb_for_dm = + rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "AP Client PWDB = 0x%lx\n", + rtlpriv->dm.entry_min_undec_sm_pwdb); + } else { + rtl_dm_dig->min_undec_pwdb_for_dm = + rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "STA Default Port PWDB = 0x%x\n", + rtl_dm_dig->min_undec_pwdb_for_dm); + } + } else { + rtl_dm_dig->min_undec_pwdb_for_dm = + rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "AP Ext Port or disconnect PWDB = 0x%x\n", + rtl_dm_dig->min_undec_pwdb_for_dm); + } + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n", + rtl_dm_dig->min_undec_pwdb_for_dm); +} + +static void rtl8723be_dm_check_rssi_monitor(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + struct rtl_sta_info *drv_priv; + u8 h2c_parameter[3] = { 0 }; + long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff; + + /* AP & ADHOC & MESH */ + spin_lock_bh(&rtlpriv->locks.entry_list_lock); + list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { + if (drv_priv->rssi_stat.undec_sm_pwdb < + tmp_entry_min_pwdb) + tmp_entry_min_pwdb = + drv_priv->rssi_stat.undec_sm_pwdb; + if (drv_priv->rssi_stat.undec_sm_pwdb > + tmp_entry_max_pwdb) + tmp_entry_max_pwdb = + drv_priv->rssi_stat.undec_sm_pwdb; + } + spin_unlock_bh(&rtlpriv->locks.entry_list_lock); + + /* If associated entry is found */ + if (tmp_entry_max_pwdb != 0) { + rtlpriv->dm.entry_max_undec_sm_pwdb = + tmp_entry_max_pwdb; + RTPRINT(rtlpriv, FDM, DM_PWDB, + "EntryMaxPWDB = 0x%lx(%ld)\n", + tmp_entry_max_pwdb, tmp_entry_max_pwdb); + } else { + rtlpriv->dm.entry_max_undec_sm_pwdb = 0; + } + /* If associated entry is found */ + if (tmp_entry_min_pwdb != 0xff) { + rtlpriv->dm.entry_min_undec_sm_pwdb = + tmp_entry_min_pwdb; + RTPRINT(rtlpriv, FDM, DM_PWDB, + "EntryMinPWDB = 0x%lx(%ld)\n", + tmp_entry_min_pwdb, tmp_entry_min_pwdb); + } else { + rtlpriv->dm.entry_min_undec_sm_pwdb = 0; + } + /* Indicate Rx signal strength to FW. */ + if (rtlpriv->dm.useramask) { + h2c_parameter[2] = + (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF); + h2c_parameter[1] = 0x20; + h2c_parameter[0] = 0; + rtl8723be_fill_h2c_cmd(hw, H2C_RSSIBE_REPORT, 3, h2c_parameter); + } else { + rtl_write_byte(rtlpriv, 0x4fe, + rtlpriv->dm.undec_sm_pwdb); + } + rtl8723be_dm_find_minimum_rssi(hw); + dm_digtable->rssi_val_min = + rtlpriv->dm_digtable.min_undec_pwdb_for_dm; +} + +void rtl8723be_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + if (dm_digtable->stop_dig) + return; + + if (dm_digtable->cur_igvalue != current_igi) { + rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi); + if (rtlpriv->phy.rf_type != RF_1T1R) + rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, + 0x7f, current_igi); + } + dm_digtable->pre_igvalue = dm_digtable->cur_igvalue; + dm_digtable->cur_igvalue = current_igi; +} + +static void rtl8723be_dm_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 dig_min_0, dig_maxofmin; + bool bfirstconnect, bfirstdisconnect; + u8 dm_dig_max, dm_dig_min; + u8 current_igi = dm_digtable->cur_igvalue; + u8 offset; + + /* AP,BT */ + if (mac->act_scanning) + return; + + dig_min_0 = dm_digtable->dig_min_0; + bfirstconnect = (mac->link_state >= MAC80211_LINKED) && + !dm_digtable->media_connect_0; + bfirstdisconnect = (mac->link_state < MAC80211_LINKED) && + (dm_digtable->media_connect_0); + + dm_dig_max = 0x5a; + dm_dig_min = DM_DIG_MIN; + dig_maxofmin = DM_DIG_MAX_AP; + + if (mac->link_state >= MAC80211_LINKED) { + if ((dm_digtable->rssi_val_min + 10) > dm_dig_max) + dm_digtable->rx_gain_max = dm_dig_max; + else if ((dm_digtable->rssi_val_min + 10) < dm_dig_min) + dm_digtable->rx_gain_max = dm_dig_min; + else + dm_digtable->rx_gain_max = + dm_digtable->rssi_val_min + 10; + + if (rtlpriv->dm.one_entry_only) { + offset = 12; + if (dm_digtable->rssi_val_min - offset < dm_dig_min) + dig_min_0 = dm_dig_min; + else if (dm_digtable->rssi_val_min - offset > + dig_maxofmin) + dig_min_0 = dig_maxofmin; + else + dig_min_0 = + dm_digtable->rssi_val_min - offset; + } else { + dig_min_0 = dm_dig_min; + } + + } else { + dm_digtable->rx_gain_max = dm_dig_max; + dig_min_0 = dm_dig_min; + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n"); + } + + if (rtlpriv->falsealm_cnt.cnt_all > 10000) { + if (dm_digtable->large_fa_hit != 3) + dm_digtable->large_fa_hit++; + if (dm_digtable->forbidden_igi < current_igi) { + dm_digtable->forbidden_igi = current_igi; + dm_digtable->large_fa_hit = 1; + } + + if (dm_digtable->large_fa_hit >= 3) { + if ((dm_digtable->forbidden_igi + 1) > + dm_digtable->rx_gain_max) + dm_digtable->rx_gain_min = + dm_digtable->rx_gain_max; + else + dm_digtable->rx_gain_min = + dm_digtable->forbidden_igi + 1; + dm_digtable->recover_cnt = 3600; + } + } else { + if (dm_digtable->recover_cnt != 0) { + dm_digtable->recover_cnt--; + } else { + if (dm_digtable->large_fa_hit < 3) { + if ((dm_digtable->forbidden_igi - 1) < + dig_min_0) { + dm_digtable->forbidden_igi = + dig_min_0; + dm_digtable->rx_gain_min = + dig_min_0; + } else { + dm_digtable->forbidden_igi--; + dm_digtable->rx_gain_min = + dm_digtable->forbidden_igi + 1; + } + } else { + dm_digtable->large_fa_hit = 0; + } + } + } + if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max) + dm_digtable->rx_gain_min = dm_digtable->rx_gain_max; + + if (mac->link_state >= MAC80211_LINKED) { + if (bfirstconnect) { + if (dm_digtable->rssi_val_min <= dig_maxofmin) + current_igi = dm_digtable->rssi_val_min; + else + current_igi = dig_maxofmin; + + dm_digtable->large_fa_hit = 0; + } else { + if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2) + current_igi += 4; + else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1) + current_igi += 2; + else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) + current_igi -= 2; + } + } else { + if (bfirstdisconnect) { + current_igi = dm_digtable->rx_gain_min; + } else { + if (rtlpriv->falsealm_cnt.cnt_all > 10000) + current_igi += 4; + else if (rtlpriv->falsealm_cnt.cnt_all > 8000) + current_igi += 2; + else if (rtlpriv->falsealm_cnt.cnt_all < 500) + current_igi -= 2; + } + } + + if (current_igi > dm_digtable->rx_gain_max) + current_igi = dm_digtable->rx_gain_max; + else if (current_igi < dm_digtable->rx_gain_min) + current_igi = dm_digtable->rx_gain_min; + + rtl8723be_dm_write_dig(hw, current_igi); + dm_digtable->media_connect_0 = + ((mac->link_state >= MAC80211_LINKED) ? true : false); + dm_digtable->dig_min_0 = dig_min_0; +} + +static void rtl8723be_dm_false_alarm_counter_statistics( + struct ieee80211_hw *hw) +{ + u32 ret_value; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt; + + rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); + rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); + + ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD); + falsealm_cnt->cnt_fast_fsync_fail = ret_value & 0xffff; + falsealm_cnt->cnt_sb_search_fail = (ret_value & 0xffff0000) >> 16; + + ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD); + falsealm_cnt->cnt_ofdm_cca = ret_value & 0xffff; + falsealm_cnt->cnt_parity_fail = (ret_value & 0xffff0000) >> 16; + + ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD); + falsealm_cnt->cnt_rate_illegal = ret_value & 0xffff; + falsealm_cnt->cnt_crc8_fail = (ret_value & 0xffff0000) >> 16; + + ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD); + falsealm_cnt->cnt_mcs_fail = ret_value & 0xffff; + + falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_fast_fsync_fail + + falsealm_cnt->cnt_sb_search_fail; + + rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1); + rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1); + + ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_RST_11N, MASKBYTE0); + falsealm_cnt->cnt_cck_fail = ret_value; + + ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3); + falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; + + ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD); + falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) | + ((ret_value & 0xff00) >> 8); + + falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail + + falsealm_cnt->cnt_sb_search_fail + + falsealm_cnt->cnt_parity_fail + + falsealm_cnt->cnt_rate_illegal + + falsealm_cnt->cnt_crc8_fail + + falsealm_cnt->cnt_mcs_fail + + falsealm_cnt->cnt_cck_fail; + + falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca + + falsealm_cnt->cnt_cck_cca; + + rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1); + rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0); + rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1); + rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0); + + rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0); + rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0); + + rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0); + rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2); + + rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0); + rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", + falsealm_cnt->cnt_parity_fail, + falsealm_cnt->cnt_rate_illegal, + falsealm_cnt->cnt_crc8_fail, + falsealm_cnt->cnt_mcs_fail); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", + falsealm_cnt->cnt_ofdm_fail, + falsealm_cnt->cnt_cck_fail, + falsealm_cnt->cnt_all); +} + +static void rtl8723be_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ + /* 8723BE does not support ODM_BB_DYNAMIC_TXPWR*/ + return; +} + +static void rtl8723be_set_iqk_matrix(struct ieee80211_hw *hw, u8 ofdm_index, + u8 rfpath, long iqk_result_x, + long iqk_result_y) +{ + long ele_a = 0, ele_d, ele_c = 0, value32; + + if (ofdm_index >= 43) + ofdm_index = 43 - 1; + + ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000) >> 22; + + if (iqk_result_x != 0) { + if ((iqk_result_x & 0x00000200) != 0) + iqk_result_x = iqk_result_x | 0xFFFFFC00; + ele_a = ((iqk_result_x * ele_d) >> 8) & 0x000003FF; + + if ((iqk_result_y & 0x00000200) != 0) + iqk_result_y = iqk_result_y | 0xFFFFFC00; + ele_c = ((iqk_result_y * ele_d) >> 8) & 0x000003FF; + + switch (rfpath) { + case RF90_PATH_A: + value32 = (ele_d << 22) | + ((ele_c & 0x3F) << 16) | ele_a; + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD, + value32); + value32 = (ele_c & 0x000003C0) >> 6; + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32); + value32 = ((iqk_result_x * ele_d) >> 7) & 0x01; + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), + value32); + break; + default: + break; + } + } else { + switch (rfpath) { + case RF90_PATH_A: + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD, + ofdmswing_table[ofdm_index]); + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 0x00); + break; + default: + break; + } + } +} + +static void rtl8723be_dm_tx_power_track_set_power(struct ieee80211_hw *hw, + enum pwr_track_control_method method, + u8 rfpath, u8 idx) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + u8 swing_idx_ofdm_limit = 36; + + if (method == TXAGC) { + rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel); + } else if (method == BBSWING) { + if (rtldm->swing_idx_cck >= CCK_TABLE_SIZE) + rtldm->swing_idx_cck = CCK_TABLE_SIZE - 1; + + if (!rtldm->cck_inch14) { + rtl_write_byte(rtlpriv, 0xa22, + cckswing_table_ch1ch13[rtldm->swing_idx_cck][0]); + rtl_write_byte(rtlpriv, 0xa23, + cckswing_table_ch1ch13[rtldm->swing_idx_cck][1]); + rtl_write_byte(rtlpriv, 0xa24, + cckswing_table_ch1ch13[rtldm->swing_idx_cck][2]); + rtl_write_byte(rtlpriv, 0xa25, + cckswing_table_ch1ch13[rtldm->swing_idx_cck][3]); + rtl_write_byte(rtlpriv, 0xa26, + cckswing_table_ch1ch13[rtldm->swing_idx_cck][4]); + rtl_write_byte(rtlpriv, 0xa27, + cckswing_table_ch1ch13[rtldm->swing_idx_cck][5]); + rtl_write_byte(rtlpriv, 0xa28, + cckswing_table_ch1ch13[rtldm->swing_idx_cck][6]); + rtl_write_byte(rtlpriv, 0xa29, + cckswing_table_ch1ch13[rtldm->swing_idx_cck][7]); + } else { + rtl_write_byte(rtlpriv, 0xa22, + cckswing_table_ch14[rtldm->swing_idx_cck][0]); + rtl_write_byte(rtlpriv, 0xa23, + cckswing_table_ch14[rtldm->swing_idx_cck][1]); + rtl_write_byte(rtlpriv, 0xa24, + cckswing_table_ch14[rtldm->swing_idx_cck][2]); + rtl_write_byte(rtlpriv, 0xa25, + cckswing_table_ch14[rtldm->swing_idx_cck][3]); + rtl_write_byte(rtlpriv, 0xa26, + cckswing_table_ch14[rtldm->swing_idx_cck][4]); + rtl_write_byte(rtlpriv, 0xa27, + cckswing_table_ch14[rtldm->swing_idx_cck][5]); + rtl_write_byte(rtlpriv, 0xa28, + cckswing_table_ch14[rtldm->swing_idx_cck][6]); + rtl_write_byte(rtlpriv, 0xa29, + cckswing_table_ch14[rtldm->swing_idx_cck][7]); + } + + if (rfpath == RF90_PATH_A) { + if (rtldm->swing_idx_ofdm[RF90_PATH_A] < + swing_idx_ofdm_limit) + swing_idx_ofdm_limit = + rtldm->swing_idx_ofdm[RF90_PATH_A]; + + rtl8723be_set_iqk_matrix(hw, + rtldm->swing_idx_ofdm[rfpath], rfpath, + rtlphy->iqk_matrix[idx].value[0][0], + rtlphy->iqk_matrix[idx].value[0][1]); + } else if (rfpath == RF90_PATH_B) { + if (rtldm->swing_idx_ofdm[RF90_PATH_B] < + swing_idx_ofdm_limit) + swing_idx_ofdm_limit = + rtldm->swing_idx_ofdm[RF90_PATH_B]; + + rtl8723be_set_iqk_matrix(hw, + rtldm->swing_idx_ofdm[rfpath], rfpath, + rtlphy->iqk_matrix[idx].value[0][4], + rtlphy->iqk_matrix[idx].value[0][5]); + } + } else { + return; + } +} + +static void rtl8723be_dm_txpower_tracking_callback_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + u8 thermalvalue = 0, delta, delta_lck, delta_iqk; + u8 thermalvalue_avg_count = 0; + u32 thermalvalue_avg = 0; + int i = 0; + + u8 ofdm_min_index = 6; + u8 index_for_channel = 0; + + char delta_swing_table_idx_tup_a[TXSCALE_TABLE_SIZE] = { + 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5, + 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 14, 15}; + char delta_swing_table_idx_tdown_a[TXSCALE_TABLE_SIZE] = { + 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5, + 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 9, + 9, 10, 10, 11, 12, 13, 14, 15}; + + /*Initilization ( 7 steps in total )*/ + rtlpriv->dm.txpower_trackinginit = true; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "rtl8723be_dm_txpower_tracking_callback_thermalmeter\n"); + + thermalvalue = (u8)rtl_get_rfreg(hw, + RF90_PATH_A, RF_T_METER, 0xfc00); + if (!rtlpriv->dm.txpower_track_control || thermalvalue == 0 || + rtlefuse->eeprom_thermalmeter == 0xFF) + return; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n", + thermalvalue, rtldm->thermalvalue, + rtlefuse->eeprom_thermalmeter); + /*3 Initialize ThermalValues of RFCalibrateInfo*/ + if (!rtldm->thermalvalue) { + rtlpriv->dm.thermalvalue_lck = thermalvalue; + rtlpriv->dm.thermalvalue_iqk = thermalvalue; + } + + /*4 Calculate average thermal meter*/ + rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue; + rtldm->thermalvalue_avg_index++; + if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8723BE) + rtldm->thermalvalue_avg_index = 0; + + for (i = 0; i < AVG_THERMAL_NUM_8723BE; i++) { + if (rtldm->thermalvalue_avg[i]) { + thermalvalue_avg += rtldm->thermalvalue_avg[i]; + thermalvalue_avg_count++; + } + } + + if (thermalvalue_avg_count) + thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count); + + /* 5 Calculate delta, delta_LCK, delta_IQK.*/ + delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? + (thermalvalue - rtlpriv->dm.thermalvalue) : + (rtlpriv->dm.thermalvalue - thermalvalue); + delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? + (thermalvalue - rtlpriv->dm.thermalvalue_lck) : + (rtlpriv->dm.thermalvalue_lck - thermalvalue); + delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? + (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : + (rtlpriv->dm.thermalvalue_iqk - thermalvalue); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n", + thermalvalue, rtlpriv->dm.thermalvalue, + rtlefuse->eeprom_thermalmeter, delta, delta_lck, delta_iqk); + /* 6 If necessary, do LCK.*/ + if (delta_lck >= IQK_THRESHOLD) { + rtlpriv->dm.thermalvalue_lck = thermalvalue; + rtl8723be_phy_lc_calibrate(hw); + } + + /* 7 If necessary, move the index of + * swing table to adjust Tx power. + */ + if (delta > 0 && rtlpriv->dm.txpower_track_control) { + delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? + (thermalvalue - rtlefuse->eeprom_thermalmeter) : + (rtlefuse->eeprom_thermalmeter - thermalvalue); + + if (delta >= TXSCALE_TABLE_SIZE) + delta = TXSCALE_TABLE_SIZE - 1; + /* 7.1 Get the final CCK_index and + * OFDM_index for each swing table. + */ + if (thermalvalue > rtlefuse->eeprom_thermalmeter) { + rtldm->delta_power_index_last[RF90_PATH_A] = + rtldm->delta_power_index[RF90_PATH_A]; + rtldm->delta_power_index[RF90_PATH_A] = + delta_swing_table_idx_tup_a[delta]; + } else { + rtldm->delta_power_index_last[RF90_PATH_A] = + rtldm->delta_power_index[RF90_PATH_A]; + rtldm->delta_power_index[RF90_PATH_A] = + -1 * delta_swing_table_idx_tdown_a[delta]; + } + + /* 7.2 Handle boundary conditions of index.*/ + if (rtldm->delta_power_index[RF90_PATH_A] == + rtldm->delta_power_index_last[RF90_PATH_A]) + rtldm->power_index_offset[RF90_PATH_A] = 0; + else + rtldm->power_index_offset[RF90_PATH_A] = + rtldm->delta_power_index[RF90_PATH_A] - + rtldm->delta_power_index_last[RF90_PATH_A]; + + rtldm->ofdm_index[0] = + rtldm->swing_idx_ofdm_base[RF90_PATH_A] + + rtldm->power_index_offset[RF90_PATH_A]; + rtldm->cck_index = rtldm->swing_idx_cck_base + + rtldm->power_index_offset[RF90_PATH_A]; + + rtldm->swing_idx_cck = rtldm->cck_index; + rtldm->swing_idx_ofdm[0] = rtldm->ofdm_index[0]; + + if (rtldm->ofdm_index[0] > OFDM_TABLE_SIZE - 1) + rtldm->ofdm_index[0] = OFDM_TABLE_SIZE - 1; + else if (rtldm->ofdm_index[0] < ofdm_min_index) + rtldm->ofdm_index[0] = ofdm_min_index; + + if (rtldm->cck_index > CCK_TABLE_SIZE - 1) + rtldm->cck_index = CCK_TABLE_SIZE - 1; + else if (rtldm->cck_index < 0) + rtldm->cck_index = 0; + } else { + rtldm->power_index_offset[RF90_PATH_A] = 0; + } + + if ((rtldm->power_index_offset[RF90_PATH_A] != 0) && + (rtldm->txpower_track_control)) { + rtldm->done_txpower = true; + if (thermalvalue > rtlefuse->eeprom_thermalmeter) + rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0, + index_for_channel); + else + rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0, + index_for_channel); + + rtldm->swing_idx_cck_base = rtldm->swing_idx_cck; + rtldm->swing_idx_ofdm_base[RF90_PATH_A] = + rtldm->swing_idx_ofdm[0]; + rtldm->thermalvalue = thermalvalue; + } + + if (delta_iqk >= IQK_THRESHOLD) { + rtldm->thermalvalue_iqk = thermalvalue; + rtl8723be_phy_iq_calibrate(hw, false); + } + + rtldm->txpowercount = 0; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n"); + +} + +void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (!rtlpriv->dm.txpower_tracking) + return; + + if (!rtlpriv->dm.tm_trigger) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16), + 0x03); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Trigger 8723be Thermal Meter!!\n"); + rtlpriv->dm.tm_trigger = 1; + return; + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Schedule TxPowerTracking !!\n"); + rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw); + rtlpriv->dm.tm_trigger = 0; + } +} + +static void rtl8723be_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rate_adaptive *p_ra = &rtlpriv->ra; + u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m; + u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra; + u8 go_up_gap = 5; + struct ieee80211_sta *sta = NULL; + + if (is_hal_stop(rtlhal)) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "driver is going to unload\n"); + return; + } + + if (!rtlpriv->dm.useramask) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "driver does not control rate adaptive mask\n"); + return; + } + + if (mac->link_state == MAC80211_LINKED && + mac->opmode == NL80211_IFTYPE_STATION) { + switch (p_ra->pre_ratr_state) { + case DM_RATR_STA_MIDDLE: + high_rssithresh_for_ra += go_up_gap; + break; + case DM_RATR_STA_LOW: + high_rssithresh_for_ra += go_up_gap; + low_rssithresh_for_ra += go_up_gap; + break; + default: + break; + } + + if (rtlpriv->dm.undec_sm_pwdb > + (long)high_rssithresh_for_ra) + p_ra->ratr_state = DM_RATR_STA_HIGH; + else if (rtlpriv->dm.undec_sm_pwdb > + (long)low_rssithresh_for_ra) + p_ra->ratr_state = DM_RATR_STA_MIDDLE; + else + p_ra->ratr_state = DM_RATR_STA_LOW; + + if (p_ra->pre_ratr_state != p_ra->ratr_state) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "RSSI = %ld\n", + rtlpriv->dm.undec_sm_pwdb); + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "RSSI_LEVEL = %d\n", p_ra->ratr_state); + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "PreState = %d, CurState = %d\n", + p_ra->pre_ratr_state, p_ra->ratr_state); + + rcu_read_lock(); + sta = rtl_find_sta(hw, mac->bssid); + if (sta) + rtlpriv->cfg->ops->update_rate_tbl(hw, sta, + p_ra->ratr_state); + rcu_read_unlock(); + + p_ra->pre_ratr_state = p_ra->ratr_state; + } + } +} + +static bool rtl8723be_dm_is_edca_turbo_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->mac80211.mode == WIRELESS_MODE_B) + return true; + + return false; +} + +static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + static u64 last_txok_cnt; + static u64 last_rxok_cnt; + u64 cur_txok_cnt = 0; + u64 cur_rxok_cnt = 0; + u32 edca_be_ul = 0x6ea42b; + u32 edca_be_dl = 0x6ea42b;/*not sure*/ + u32 edca_be = 0x5ea42b; + u32 iot_peer = 0; + bool b_is_cur_rdlstate; + bool b_last_is_cur_rdlstate = false; + bool b_bias_on_rx = false; + bool b_edca_turbo_on = false; + + b_last_is_cur_rdlstate = rtlpriv->dm.is_cur_rdlstate; + + cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; + cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; + + iot_peer = rtlpriv->mac80211.vendor; + b_bias_on_rx = (iot_peer == PEER_RAL || iot_peer == PEER_ATH) ? + true : false; + b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) && + (!rtlpriv->dm.disable_framebursting)) ? + true : false; + + if ((iot_peer == PEER_CISCO) && + (mac->mode == WIRELESS_MODE_N_24G)) { + edca_be_dl = edca_setting_dl[iot_peer]; + edca_be_ul = edca_setting_ul[iot_peer]; + } + if (rtl8723be_dm_is_edca_turbo_disable(hw)) + goto exit; + + if (b_edca_turbo_on) { + if (b_bias_on_rx) + b_is_cur_rdlstate = (cur_txok_cnt > cur_rxok_cnt * 4) ? + false : true; + else + b_is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ? + true : false; + + edca_be = (b_is_cur_rdlstate) ? edca_be_dl : edca_be_ul; + rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, edca_be); + rtlpriv->dm.is_cur_rdlstate = b_is_cur_rdlstate; + rtlpriv->dm.current_turbo_edca = true; + } else { + if (rtlpriv->dm.current_turbo_edca) { + u8 tmp = AC0_BE; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + (u8 *)(&tmp)); + } + rtlpriv->dm.current_turbo_edca = false; + } + +exit: + rtlpriv->dm.is_any_nonbepkts = false; + last_txok_cnt = rtlpriv->stats.txbytesunicast; + last_rxok_cnt = rtlpriv->stats.rxbytesunicast; +} + +static void rtl8723be_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + u8 cur_cck_cca_thresh; + + if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) { + if (dm_digtable->rssi_val_min > 25) { + cur_cck_cca_thresh = 0xcd; + } else if ((dm_digtable->rssi_val_min <= 25) && + (dm_digtable->rssi_val_min > 10)) { + cur_cck_cca_thresh = 0x83; + } else { + if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) + cur_cck_cca_thresh = 0x83; + else + cur_cck_cca_thresh = 0x40; + } + } else { + if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) + cur_cck_cca_thresh = 0x83; + else + cur_cck_cca_thresh = 0x40; + } + + if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh) + rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh); + + dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres; + dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh; + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres); +} + +static void rtl8723be_dm_dynamic_edcca(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 reg_c50, reg_c58; + bool fw_current_in_ps_mode = false; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_in_ps_mode)); + if (fw_current_in_ps_mode) + return; + + reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); + reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); + + if (reg_c50 > 0x28 && reg_c58 > 0x28) { + if (!rtlpriv->rtlhal.pre_edcca_enable) { + rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03); + rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00); + } + } else if (reg_c50 < 0x25 && reg_c58 < 0x25) { + if (rtlpriv->rtlhal.pre_edcca_enable) { + rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f); + rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f); + } + } +} + +static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + u8 crystal_cap; + u32 packet_count; + int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0; + int cfo_ave_diff; + + if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { + if (rtldm->atc_status == ATC_STATUS_OFF) { + rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), + ATC_STATUS_ON); + rtldm->atc_status = ATC_STATUS_ON; + } + if (rtlpriv->cfg->ops->get_btc_status()) { + if (!rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(rtlpriv)) { + RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, + "odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n"); + return; + } + } + + if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) { + rtldm->crystal_cap = rtlpriv->efuse.crystalcap; + crystal_cap = rtldm->crystal_cap & 0x3f; + rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, + (crystal_cap | (crystal_cap << 6))); + } + } else { + cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280; + cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280; + packet_count = rtldm->packet_count; + + if (packet_count == rtldm->packet_count_pre) + return; + + rtldm->packet_count_pre = packet_count; + + if (rtlpriv->phy.rf_type == RF_1T1R) + cfo_ave = cfo_khz_a; + else + cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1; + + cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ? + (rtldm->cfo_ave_pre - cfo_ave) : + (cfo_ave - rtldm->cfo_ave_pre); + + if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) { + rtldm->large_cfo_hit = 1; + return; + } else + rtldm->large_cfo_hit = 0; + + rtldm->cfo_ave_pre = cfo_ave; + + if (cfo_ave >= -rtldm->cfo_threshold && + cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) { + if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) { + rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10; + rtldm->is_freeze = 1; + } else { + rtldm->cfo_threshold = CFO_THRESHOLD_XTAL; + } + } + + if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f) + adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 1) + 1; + else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) && + rtlpriv->dm.crystal_cap > 0) + adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 1) - 1; + + if (adjust_xtal != 0) { + rtldm->is_freeze = 0; + rtldm->crystal_cap += adjust_xtal; + + if (rtldm->crystal_cap > 0x3f) + rtldm->crystal_cap = 0x3f; + else if (rtldm->crystal_cap < 0) + rtldm->crystal_cap = 0; + + crystal_cap = rtldm->crystal_cap & 0x3f; + rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, + (crystal_cap | (crystal_cap << 6))); + } + + if (cfo_ave < CFO_THRESHOLD_ATC && + cfo_ave > -CFO_THRESHOLD_ATC) { + if (rtldm->atc_status == ATC_STATUS_ON) { + rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), + ATC_STATUS_OFF); + rtldm->atc_status = ATC_STATUS_OFF; + } + } else { + if (rtldm->atc_status == ATC_STATUS_OFF) { + rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), + ATC_STATUS_ON); + rtldm->atc_status = ATC_STATUS_ON; + } + } + } +} + +static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 cnt = 0; + struct rtl_sta_info *drv_priv; + + rtlpriv->dm.one_entry_only = false; + + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION && + rtlpriv->mac80211.link_state >= MAC80211_LINKED) { + rtlpriv->dm.one_entry_only = true; + return; + } + + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || + rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC || + rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) { + spin_lock_bh(&rtlpriv->locks.entry_list_lock); + list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { + cnt++; + } + spin_unlock_bh(&rtlpriv->locks.entry_list_lock); + + if (cnt == 1) + rtlpriv->dm.one_entry_only = true; + } +} + +void rtl8723be_dm_watchdog(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool fw_current_inpsmode = false; + bool fw_ps_awake = true; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inpsmode)); + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, + (u8 *)(&fw_ps_awake)); + + if (ppsc->p2p_ps_info.p2p_ps_mode) + fw_ps_awake = false; + + if ((ppsc->rfpwr_state == ERFON) && + ((!fw_current_inpsmode) && fw_ps_awake) && + (!ppsc->rfchange_inprogress)) { + rtl8723be_dm_common_info_self_update(hw); + rtl8723be_dm_false_alarm_counter_statistics(hw); + rtl8723be_dm_check_rssi_monitor(hw); + rtl8723be_dm_dig(hw); + rtl8723be_dm_dynamic_edcca(hw); + rtl8723be_dm_cck_packet_detection_thresh(hw); + rtl8723be_dm_refresh_rate_adaptive_mask(hw); + rtl8723be_dm_check_edca_turbo(hw); + rtl8723be_dm_dynamic_atc_switch(hw); + rtl8723be_dm_check_txpower_tracking(hw); + rtl8723be_dm_dynamic_txpower(hw); + } + rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h new file mode 100644 index 000000000000..f752a2cad63d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.h @@ -0,0 +1,267 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723BE_DM_H__ +#define __RTL8723BE_DM_H__ + +#define MAIN_ANT 0 +#define AUX_ANT 1 +#define MAIN_ANT_CG_TRX 1 +#define AUX_ANT_CG_TRX 0 +#define MAIN_ANT_CGCS_RX 0 +#define AUX_ANT_CGCS_RX 1 + +#define TXSCALE_TABLE_SIZE 30 + +/*RF REG LIST*/ +#define DM_REG_RF_MODE_11N 0x00 +#define DM_REG_RF_0B_11N 0x0B +#define DM_REG_CHNBW_11N 0x18 +#define DM_REG_T_METER_11N 0x24 +#define DM_REG_RF_25_11N 0x25 +#define DM_REG_RF_26_11N 0x26 +#define DM_REG_RF_27_11N 0x27 +#define DM_REG_RF_2B_11N 0x2B +#define DM_REG_RF_2C_11N 0x2C +#define DM_REG_RXRF_A3_11N 0x3C +#define DM_REG_T_METER_92D_11N 0x42 +#define DM_REG_T_METER_88E_11N 0x42 + +/*BB REG LIST*/ +/*PAGE 8 */ +#define DM_REG_BB_CTRL_11N 0x800 +#define DM_REG_RF_PIN_11N 0x804 +#define DM_REG_PSD_CTRL_11N 0x808 +#define DM_REG_TX_ANT_CTRL_11N 0x80C +#define DM_REG_BB_PWR_SAV5_11N 0x818 +#define DM_REG_CCK_RPT_FORMAT_11N 0x824 +#define DM_REG_RX_DEFUALT_A_11N 0x858 +#define DM_REG_RX_DEFUALT_B_11N 0x85A +#define DM_REG_BB_PWR_SAV3_11N 0x85C +#define DM_REG_ANTSEL_CTRL_11N 0x860 +#define DM_REG_RX_ANT_CTRL_11N 0x864 +#define DM_REG_PIN_CTRL_11N 0x870 +#define DM_REG_BB_PWR_SAV1_11N 0x874 +#define DM_REG_ANTSEL_PATH_11N 0x878 +#define DM_REG_BB_3WIRE_11N 0x88C +#define DM_REG_SC_CNT_11N 0x8C4 +#define DM_REG_PSD_DATA_11N 0x8B4 +/*PAGE 9*/ +#define DM_REG_ANT_MAPPING1_11N 0x914 +#define DM_REG_ANT_MAPPING2_11N 0x918 +/*PAGE A*/ +#define DM_REG_CCK_ANTDIV_PARA1_11N 0xA00 +#define DM_REG_CCK_CCA_11N 0xA0A +#define DM_REG_CCK_ANTDIV_PARA2_11N 0xA0C +#define DM_REG_CCK_ANTDIV_PARA3_11N 0xA10 +#define DM_REG_CCK_ANTDIV_PARA4_11N 0xA14 +#define DM_REG_CCK_FILTER_PARA1_11N 0xA22 +#define DM_REG_CCK_FILTER_PARA2_11N 0xA23 +#define DM_REG_CCK_FILTER_PARA3_11N 0xA24 +#define DM_REG_CCK_FILTER_PARA4_11N 0xA25 +#define DM_REG_CCK_FILTER_PARA5_11N 0xA26 +#define DM_REG_CCK_FILTER_PARA6_11N 0xA27 +#define DM_REG_CCK_FILTER_PARA7_11N 0xA28 +#define DM_REG_CCK_FILTER_PARA8_11N 0xA29 +#define DM_REG_CCK_FA_RST_11N 0xA2C +#define DM_REG_CCK_FA_MSB_11N 0xA58 +#define DM_REG_CCK_FA_LSB_11N 0xA5C +#define DM_REG_CCK_CCA_CNT_11N 0xA60 +#define DM_REG_BB_PWR_SAV4_11N 0xA74 +/*PAGE B */ +#define DM_REG_LNA_SWITCH_11N 0xB2C +#define DM_REG_PATH_SWITCH_11N 0xB30 +#define DM_REG_RSSI_CTRL_11N 0xB38 +#define DM_REG_CONFIG_ANTA_11N 0xB68 +#define DM_REG_RSSI_BT_11N 0xB9C +/*PAGE C */ +#define DM_REG_OFDM_FA_HOLDC_11N 0xC00 +#define DM_REG_RX_PATH_11N 0xC04 +#define DM_REG_TRMUX_11N 0xC08 +#define DM_REG_OFDM_FA_RSTC_11N 0xC0C +#define DM_REG_RXIQI_MATRIX_11N 0xC14 +#define DM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C +#define DM_REG_IGI_A_11N 0xC50 +#define DM_REG_ANTDIV_PARA2_11N 0xC54 +#define DM_REG_IGI_B_11N 0xC58 +#define DM_REG_ANTDIV_PARA3_11N 0xC5C +#define DM_REG_BB_PWR_SAV2_11N 0xC70 +#define DM_REG_RX_OFF_11N 0xC7C +#define DM_REG_TXIQK_MATRIXA_11N 0xC80 +#define DM_REG_TXIQK_MATRIXB_11N 0xC88 +#define DM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 +#define DM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C +#define DM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 +#define DM_REG_ANTDIV_PARA1_11N 0xCA4 +#define DM_REG_OFDM_FA_TYPE1_11N 0xCF0 +/*PAGE D */ +#define DM_REG_OFDM_FA_RSTD_11N 0xD00 +#define DM_REG_OFDM_FA_TYPE2_11N 0xDA0 +#define DM_REG_OFDM_FA_TYPE3_11N 0xDA4 +#define DM_REG_OFDM_FA_TYPE4_11N 0xDA8 +/*PAGE E */ +#define DM_REG_TXAGC_A_6_18_11N 0xE00 +#define DM_REG_TXAGC_A_24_54_11N 0xE04 +#define DM_REG_TXAGC_A_1_MCS32_11N 0xE08 +#define DM_REG_TXAGC_A_MCS0_3_11N 0xE10 +#define DM_REG_TXAGC_A_MCS4_7_11N 0xE14 +#define DM_REG_TXAGC_A_MCS8_11_11N 0xE18 +#define DM_REG_TXAGC_A_MCS12_15_11N 0xE1C +#define DM_REG_FPGA0_IQK_11N 0xE28 +#define DM_REG_TXIQK_TONE_A_11N 0xE30 +#define DM_REG_RXIQK_TONE_A_11N 0xE34 +#define DM_REG_TXIQK_PI_A_11N 0xE38 +#define DM_REG_RXIQK_PI_A_11N 0xE3C +#define DM_REG_TXIQK_11N 0xE40 +#define DM_REG_RXIQK_11N 0xE44 +#define DM_REG_IQK_AGC_PTS_11N 0xE48 +#define DM_REG_IQK_AGC_RSP_11N 0xE4C +#define DM_REG_BLUETOOTH_11N 0xE6C +#define DM_REG_RX_WAIT_CCA_11N 0xE70 +#define DM_REG_TX_CCK_RFON_11N 0xE74 +#define DM_REG_TX_CCK_BBON_11N 0xE78 +#define DM_REG_OFDM_RFON_11N 0xE7C +#define DM_REG_OFDM_BBON_11N 0xE80 +#define DM_REG_TX2RX_11N 0xE84 +#define DM_REG_TX2TX_11N 0xE88 +#define DM_REG_RX_CCK_11N 0xE8C +#define DM_REG_RX_OFDM_11N 0xED0 +#define DM_REG_RX_WAIT_RIFS_11N 0xED4 +#define DM_REG_RX2RX_11N 0xED8 +#define DM_REG_STANDBY_11N 0xEDC +#define DM_REG_SLEEP_11N 0xEE0 +#define DM_REG_PMPD_ANAEN_11N 0xEEC + +/*MAC REG LIST*/ +#define DM_REG_BB_RST_11N 0x02 +#define DM_REG_ANTSEL_PIN_11N 0x4C +#define DM_REG_EARLY_MODE_11N 0x4D0 +#define DM_REG_RSSI_MONITOR_11N 0x4FE +#define DM_REG_EDCA_VO_11N 0x500 +#define DM_REG_EDCA_VI_11N 0x504 +#define DM_REG_EDCA_BE_11N 0x508 +#define DM_REG_EDCA_BK_11N 0x50C +#define DM_REG_TXPAUSE_11N 0x522 +#define DM_REG_RESP_TX_11N 0x6D8 +#define DM_REG_ANT_TRAIN_PARA1_11N 0x7b0 +#define DM_REG_ANT_TRAIN_PARA2_11N 0x7b4 + +/*DIG Related*/ +#define DM_BIT_IGI_11N 0x0000007F + +#define HAL_DM_DIG_DISABLE BIT(0) +#define HAL_DM_HIPWR_DISABLE BIT(1) + +#define OFDM_TABLE_LENGTH 43 +#define CCK_TABLE_LENGTH 33 + +#define OFDM_TABLE_SIZE 37 +#define CCK_TABLE_SIZE 33 + +#define BW_AUTO_SWITCH_HIGH_LOW 25 +#define BW_AUTO_SWITCH_LOW_HIGH 30 + +#define DM_DIG_FA_UPPER 0x3e +#define DM_DIG_FA_LOWER 0x1e +#define DM_DIG_FA_TH0 0x200 +#define DM_DIG_FA_TH1 0x300 +#define DM_DIG_FA_TH2 0x400 + +#define RXPATHSELECTION_SS_TH_LOW 30 +#define RXPATHSELECTION_DIFF_TH 18 + +#define DM_RATR_STA_INIT 0 +#define DM_RATR_STA_HIGH 1 +#define DM_RATR_STA_MIDDLE 2 +#define DM_RATR_STA_LOW 3 + +#define CTS2SELF_THVAL 30 +#define REGC38_TH 20 + +#define WAIOTTHVAL 25 + +#define TXHIGHPWRLEVEL_NORMAL 0 +#define TXHIGHPWRLEVEL_LEVEL1 1 +#define TXHIGHPWRLEVEL_LEVEL2 2 +#define TXHIGHPWRLEVEL_BT1 3 +#define TXHIGHPWRLEVEL_BT2 4 + +#define DM_TYPE_BYFW 0 +#define DM_TYPE_BYDRIVER 1 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 +#define TXPWRTRACK_MAX_IDX 6 + +/* Dynamic ATC switch */ +#define ATC_STATUS_OFF 0x0 /* enable */ +#define ATC_STATUS_ON 0x1 /* disable */ +#define CFO_THRESHOLD_XTAL 10 /* kHz */ +#define CFO_THRESHOLD_ATC 80 /* kHz */ + +enum dm_1r_cca_e { + CCA_1R = 0, + CCA_2R = 1, + CCA_MAX = 2, +}; + +enum dm_rf_e { + RF_SAVE = 0, + RF_NORMAL = 1, + RF_MAX = 2, +}; + +enum dm_sw_ant_switch_e { + ANS_ANTENNA_B = 1, + ANS_ANTENNA_A = 2, + ANS_ANTENNA_MAX = 3, +}; + +enum pwr_track_control_method { + BBSWING, + TXAGC +}; + +#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1) +#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1) +#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1) +#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1) +#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1) +#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ + ((((struct rtl_priv *)(_priv))->mac80211.opmode == \ + NL80211_IFTYPE_ADHOC) ? \ + (((struct rtl_priv *)(_priv))->dm.entry_min_undecoratedsmoothed_pwdb) :\ + (((struct rtl_priv *)(_priv))->dm.undecorated_smoothed_pwdb)) + +void rtl8723be_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, u8 *pdesc, + u32 mac_id); +void rtl8723be_dm_ant_sel_statistics(struct ieee80211_hw *hw, u8 antsel_tr_mux, + u32 mac_id, u32 rx_pwdb_all); +void rtl8723be_dm_fast_antenna_training_callback(unsigned long data); +void rtl8723be_dm_init(struct ieee80211_hw *hw); +void rtl8723be_dm_watchdog(struct ieee80211_hw *hw); +void rtl8723be_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi); +void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw); +void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); +void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw *hw, u8 type, + u8 *pdirection, u32 *poutwrite_val); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c new file mode 100644 index 000000000000..d5da0f3c1217 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c @@ -0,0 +1,640 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "fw.h" +#include "../rtl8723com/fw_common.h" + +static bool _rtl8723be_check_fw_read_last_h2c(struct ieee80211_hw *hw, + u8 boxnum) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 val_hmetfr; + bool result = false; + + val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); + if (((val_hmetfr >> boxnum) & BIT(0)) == 0) + result = true; + return result; +} + +static void _rtl8723be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *p_cmdbuffer) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 boxnum; + u16 box_reg = 0, box_extreg = 0; + u8 u1b_tmp; + bool isfw_read = false; + u8 buf_index = 0; + bool bwrite_sucess = false; + u8 wait_h2c_limmit = 100; + u8 wait_writeh2c_limmit = 100; + u8 boxcontent[4], boxextcontent[4]; + u32 h2c_waitcounter = 0; + unsigned long flag; + u8 idx; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); + + while (true) { + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + if (rtlhal->h2c_setinprogress) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C set in progress! Wait to set..element_id(%d).\n", + element_id); + + while (rtlhal->h2c_setinprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, + flag); + h2c_waitcounter++; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Wait 100 us (%d times)...\n", + h2c_waitcounter); + udelay(100); + + if (h2c_waitcounter > 1000) + return; + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, + flag); + } + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + } else { + rtlhal->h2c_setinprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + break; + } + } + + while (!bwrite_sucess) { + wait_writeh2c_limmit--; + if (wait_writeh2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Write H2C fail because no trigger for FW INT!\n"); + break; + } + + boxnum = rtlhal->last_hmeboxnum; + switch (boxnum) { + case 0: + box_reg = REG_HMEBOX_0; + box_extreg = REG_HMEBOX_EXT_0; + break; + case 1: + box_reg = REG_HMEBOX_1; + box_extreg = REG_HMEBOX_EXT_1; + break; + case 2: + box_reg = REG_HMEBOX_2; + box_extreg = REG_HMEBOX_EXT_2; + break; + case 3: + box_reg = REG_HMEBOX_3; + box_extreg = REG_HMEBOX_EXT_3; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + + isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum); + while (!isfw_read) { + wait_h2c_limmit--; + if (wait_h2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Waiting too long for FW read clear HMEBox(%d)!\n", + boxnum); + break; + } + + udelay(10); + + isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, + boxnum); + u1b_tmp = rtl_read_byte(rtlpriv, 0x130); + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", + boxnum, u1b_tmp); + } + + if (!isfw_read) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", + boxnum); + break; + } + + memset(boxcontent, 0, sizeof(boxcontent)); + memset(boxextcontent, 0, sizeof(boxextcontent)); + boxcontent[0] = element_id; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Write element_id box_reg(%4x) = %2x\n", + box_reg, element_id); + + switch (cmd_len) { + case 1: + case 2: + case 3: + /*boxcontent[0] &= ~(BIT(7));*/ + memcpy((u8 *)(boxcontent) + 1, + p_cmdbuffer + buf_index, cmd_len); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 4: + case 5: + case 6: + case 7: + /*boxcontent[0] |= (BIT(7));*/ + memcpy((u8 *)(boxextcontent), + p_cmdbuffer + buf_index+3, cmd_len-3); + memcpy((u8 *)(boxcontent) + 1, + p_cmdbuffer + buf_index, 3); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_extreg + idx, + boxextcontent[idx]); + } + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + + bwrite_sucess = true; + + rtlhal->last_hmeboxnum = boxnum + 1; + if (rtlhal->last_hmeboxnum == 4) + rtlhal->last_hmeboxnum = 0; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "pHalData->last_hmeboxnum = %d\n", + rtlhal->last_hmeboxnum); + } + + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + rtlhal->h2c_setinprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); +} + +void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *p_cmdbuffer) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 tmp_cmdbuf[2]; + + if (!rtlhal->fw_ready) { + RT_ASSERT(false, + "return H2C cmd because of Fw download fail!!!\n"); + return; + } + + memset(tmp_cmdbuf, 0, 8); + memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len); + _rtl8723be_fill_h2c_command(hw, element_id, cmd_len, + (u8 *)&tmp_cmdbuf); + return; +} + +void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 }; + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 rlbm, power_state = 0; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); + + SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); + rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/ + SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); + SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, + (rtlpriv->mac80211.p2p) ? + ppsc->smart_ps : 1); + SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, + ppsc->reg_max_lps_awakeintvl); + SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); + if (mode == FW_PS_ACTIVE_MODE) + power_state |= FW_PWR_STATE_ACTIVE; + else + power_state |= FW_PWR_STATE_RF_OFF; + SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", + u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH); + rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH, + u1_h2c_set_pwrmode); +} + +void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus) +{ + u8 parm[3] = { 0, 0, 0 }; + /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect + * bit1=0-->update Media Status to MACID + * bit1=1-->update Media Status from MACID to MACID_End + * parm[1]: MACID, if this is INFRA_STA, MacID = 0 + * parm[2]: MACID_End + */ + SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); + SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); + + rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm); +} + +#define BEACON_PG 0 /* ->1 */ +#define PSPOLL_PG 2 +#define NULL_PG 3 +#define PROBERSP_PG 4 /* ->5 */ + +#define TOTAL_RESERVED_PKT_LEN 768 + +static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { + /* page 0 beacon */ + 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, + 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65, + 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B, + 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06, + 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, + 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, + 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, + 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, + 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, + 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00, + + /* page 1 beacon */ + 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 2 ps-poll */ + 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B, + 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 3 null */ + 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B, + 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, + 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 4 probe_resp */ + 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, + 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, + 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, + 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, + 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, + 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, + 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, + 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, + 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, + 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, + 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* page 5 probe_resp */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, + bool b_dl_finished) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct sk_buff *skb = NULL; + + u32 totalpacketlen; + bool rtstatus; + u8 u1rsvdpageloc[5] = { 0 }; + bool b_dlok = false; + + u8 *beacon; + u8 *p_pspoll; + u8 *nullfunc; + u8 *p_probersp; + /*--------------------------------------------------------- + * (1) beacon + *--------------------------------------------------------- + */ + beacon = &reserved_page_packet[BEACON_PG * 128]; + SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); + SET_80211_HDR_ADDRESS3(beacon, mac->bssid); + + /*------------------------------------------------------- + * (2) ps-poll + *------------------------------------------------------- + */ + p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; + SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); + SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); + SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); + + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); + + /*-------------------------------------------------------- + * (3) null data + *-------------------------------------------------------- + */ + nullfunc = &reserved_page_packet[NULL_PG * 128]; + SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); + SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); + SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); + + /*--------------------------------------------------------- + * (4) probe response + *--------------------------------------------------------- + */ + p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; + SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); + SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); + SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); + + totalpacketlen = TOTAL_RESERVED_PKT_LEN; + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + &reserved_page_packet[0], totalpacketlen); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", + u1rsvdpageloc, 3); + + skb = dev_alloc_skb(totalpacketlen); + memcpy((u8 *)skb_put(skb, totalpacketlen), + &reserved_page_packet, totalpacketlen); + + rtstatus = rtl_cmd_send_packet(hw, skb); + + if (rtstatus) + b_dlok = true; + + if (b_dlok) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Set RSVD page location to Fw.\n"); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n", + u1rsvdpageloc, 3); + rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE, + sizeof(u1rsvdpageloc), u1rsvdpageloc); + } else + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set RSVD page location to Fw FAIL!!!!!!.\n"); +} + +/*Should check FW support p2p or not.*/ +static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, + u8 ctwindow) +{ + u8 u1_ctwindow_period[1] = { ctwindow}; + + rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1, + u1_ctwindow_period); +} + +void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, + u8 p2p_ps_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); + struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; + u8 i; + u16 ctwindow; + u32 start_time, tsf_low; + + switch (p2p_ps_state) { + case P2P_PS_DISABLE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); + memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); + break; + case P2P_PS_ENABLE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); + /* update CTWindow value. */ + if (p2pinfo->ctwindow > 0) { + p2p_ps_offload->ctwindow_en = 1; + ctwindow = p2pinfo->ctwindow; + rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow); + } + /* hw only support 2 set of NoA */ + for (i = 0 ; i < p2pinfo->noa_num ; i++) { + /* To control the register setting + * for which NOA + */ + rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); + if (i == 0) + p2p_ps_offload->noa0_en = 1; + else + p2p_ps_offload->noa1_en = 1; + + /* config P2P NoA Descriptor Register */ + rtl_write_dword(rtlpriv, 0x5E0, + p2pinfo->noa_duration[i]); + rtl_write_dword(rtlpriv, 0x5E4, + p2pinfo->noa_interval[i]); + + /*Get Current TSF value */ + tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + start_time = p2pinfo->noa_start_time[i]; + if (p2pinfo->noa_count_type[i] != 1) { + while (start_time <= (tsf_low + (50 * 1024))) { + start_time += p2pinfo->noa_interval[i]; + if (p2pinfo->noa_count_type[i] != 255) + p2pinfo->noa_count_type[i]--; + } + } + rtl_write_dword(rtlpriv, 0x5E8, start_time); + rtl_write_dword(rtlpriv, 0x5EC, + p2pinfo->noa_count_type[i]); + } + + if ((p2pinfo->opp_ps == 1) || + (p2pinfo->noa_num > 0)) { + /* rst p2p circuit */ + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); + + p2p_ps_offload->offload_en = 1; + + if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { + p2p_ps_offload->role = 1; + p2p_ps_offload->allstasleep = 0; + } else { + p2p_ps_offload->role = 0; + } + p2p_ps_offload->discovery = 0; + } + break; + case P2P_PS_SCAN: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); + p2p_ps_offload->discovery = 1; + break; + case P2P_PS_SCAN_DONE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); + p2p_ps_offload->discovery = 0; + p2pinfo->p2p_ps_state = P2P_PS_ENABLE; + break; + default: + break; + } + + rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1, + (u8 *)p2p_ps_offload); +} + +static void _rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw, + u8 c2h_cmd_id, + u8 c2h_cmd_len, u8 *tmp_buf) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (c2h_cmd_id) { + case C2H_8723B_DBG: + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H], C2H_8723BE_DBG!!\n"); + break; + case C2H_8723B_TX_REPORT: + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H], C2H_8723BE_TX_REPORT!\n"); + break; + case C2H_8723B_BT_INFO: + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H], C2H_8723BE_BT_INFO!!\n"); + rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf, + c2h_cmd_len); + break; + case C2H_8723B_BT_MP: + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H], C2H_8723BE_BT_MP!!\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id); + break; + } +} + +void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0; + u8 *tmp_buf = NULL; + + c2h_cmd_id = buffer[0]; + c2h_cmd_seq = buffer[1]; + c2h_cmd_len = len - 2; + tmp_buf = buffer + 2; + + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n", + c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len); + + RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE, + "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len); + + _rtl8723be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h new file mode 100644 index 000000000000..067429669bda --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.h @@ -0,0 +1,152 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723BE__FW__H__ +#define __RTL8723BE__FW__H__ + +#define FW_8192C_SIZE 0x8000 +#define FW_8192C_START_ADDRESS 0x1000 +#define FW_8192C_END_ADDRESS 0x5FFF +#define FW_8192C_PAGE_SIZE 4096 +#define FW_8192C_POLLING_DELAY 5 + +#define USE_OLD_WOWLAN_DEBUG_FW 0 + +#define H2C_PWEMODE_LENGTH 5 + +/* Fw PS state for RPWM. +*BIT[2:0] = HW state +*BIT[3] = Protocol PS state, 1: register active state , 0: register sleep state +*BIT[4] = sub-state +*/ +#define FW_PS_RF_ON BIT(2) +#define FW_PS_REGISTER_ACTIVE BIT(3) + +#define FW_PS_ACK BIT(6) +#define FW_PS_TOGGLE BIT(7) + + /* 8723BE RPWM value*/ + /* BIT[0] = 1: 32k, 0: 40M*/ +#define FW_PS_CLOCK_OFF BIT(0) /* 32k*/ +#define FW_PS_CLOCK_ON 0 /*40M*/ + +#define FW_PS_STATE_MASK (0x0F) +#define FW_PS_STATE_HW_MASK (0x07) +/*ISR_ENABLE, IMR_ENABLE, and PS mode should be inherited.*/ +#define FW_PS_STATE_INT_MASK (0x3F) + +#define FW_PS_STATE(x) (FW_PS_STATE_MASK & (x)) + +/* ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE))*/ +#define FW_PS_STATE_ALL_ON (FW_PS_CLOCK_ON) +/* (FW_PS_RF_ON)*/ +#define FW_PS_STATE_RF_ON (FW_PS_CLOCK_ON) +/* 0x0*/ +#define FW_PS_STATE_RF_OFF (FW_PS_CLOCK_ON) +/* (FW_PS_STATE_RF_OFF)*/ +#define FW_PS_STATE_RF_OFF_LOW_PWR (FW_PS_CLOCK_OFF) + + +/* For 8723BE H2C PwrMode Cmd ID 5.*/ +#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) +#define FW_PWR_STATE_RF_OFF 0 + +#define FW_PS_IS_ACK(x) ((x) & FW_PS_ACK) + +#define IS_IN_LOW_POWER_STATE(__fwpsstate) \ + (FW_PS_STATE(__fwpsstate) == FW_PS_CLOCK_OFF) + +#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) +#define FW_PWR_STATE_RF_OFF 0 + +enum rtl8723b_h2c_cmd { + H2C_8723B_RSVDPAGE = 0, + H2C_8723B_MSRRPT = 1, + H2C_8723B_SCAN = 2, + H2C_8723B_KEEP_ALIVE_CTRL = 3, + H2C_8723B_DISCONNECT_DECISION = 4, + H2C_8723B_BCN_RSVDPAGE = 9, + H2C_8723B_PROBERSP_RSVDPAGE = 10, + + H2C_8723B_SETPWRMODE = 0x20, + H2C_8723B_PS_LPS_PARA = 0x23, + H2C_8723B_P2P_PS_OFFLOAD = 0x24, + + H2C_8723B_RA_MASK = 0x40, + H2C_RSSIBE_REPORT = 0x42, + /*Not defined CTW CMD for P2P yet*/ + H2C_8723B_P2P_PS_CTW_CMD, + MAX_8723B_H2CCMD +}; + +enum rtl8723b_c2h_evt { + C2H_8723B_DBG = 0, + C2H_8723B_LB = 1, + C2H_8723B_TXBF = 2, + C2H_8723B_TX_REPORT = 3, + C2H_8723B_BT_INFO = 9, + C2H_8723B_BT_MP = 11, + MAX_8723B_C2HEVENT +}; + +#define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) + + +#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_RLBM(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 4, __val) +#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 4, 4, __val) +#define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+3, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+4, 0, 8, __val) +#define GET_88E_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd) \ + LE_BITS_TO_1BYTE(__ph2ccmd, 0, 8) + +#define SET_H2CCMD_MSRRPT_PARM_OPMODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 1, __val) +#define SET_H2CCMD_MSRRPT_PARM_MACID_IND(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 1, 1, __val) + +#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) + + +void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *p_cmdbuffer); +void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); +void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus); +void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); +void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); +void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c new file mode 100644 index 000000000000..c983d2fe147f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c @@ -0,0 +1,2734 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../regd.h" +#include "../cam.h" +#include "../ps.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "../rtl8723com/phy_common.h" +#include "dm.h" +#include "../rtl8723com/dm_common.h" +#include "fw.h" +#include "../rtl8723com/fw_common.h" +#include "led.h" +#include "hw.h" +#include "../pwrseqcmd.h" +#include "pwrseq.h" +#include "../btcoexist/rtl_btc.h" + +#define LLT_CONFIG 5 + +static void _rtl8723be_return_beacon_queue_skb(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; + unsigned long flags; + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + while (skb_queue_len(&ring->queue)) { + struct rtl_tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb = __skb_dequeue(&ring->queue); + + pci_unmap_single(rtlpci->pdev, + rtlpriv->cfg->ops->get_desc( + (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), + skb->len, PCI_DMA_TODEVICE); + kfree_skb(skb); + ring->idx = (ring->idx + 1) % ring->entries; + } + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); +} + +static void _rtl8723be_set_bcn_ctrl_reg(struct ieee80211_hw *hw, + u8 set_bits, u8 clear_bits) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpci->reg_bcn_ctrl_val |= set_bits; + rtlpci->reg_bcn_ctrl_val &= ~clear_bits; + + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); +} + +static void _rtl8723be_stop_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl8723be_resume_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte |= BIT(1); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl8723be_enable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(1)); +} + +static void _rtl8723be_disable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl8723be_set_bcn_ctrl_reg(hw, BIT(1), 0); +} + +static void _rtl8723be_set_fw_clock_on(struct ieee80211_hw *hw, u8 rpwm_val, + bool b_need_turn_off_ckk) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool b_support_remote_wake_up; + u32 count = 0, isr_regaddr, content; + bool b_schedule_timer = b_need_turn_off_ckk; + rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, + (u8 *)(&b_support_remote_wake_up)); + + if (!rtlhal->fw_ready) + return; + if (!rtlpriv->psc.fw_current_inpsmode) + return; + + while (1) { + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + if (rtlhal->fw_clk_change_in_progress) { + while (rtlhal->fw_clk_change_in_progress) { + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + count++; + udelay(100); + if (count > 1000) + return; + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + } + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + } else { + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + break; + } + } + + if (IS_IN_LOW_POWER_STATE(rtlhal->fw_ps_state)) { + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + if (FW_PS_IS_ACK(rpwm_val)) { + isr_regaddr = REG_HISR; + content = rtl_read_dword(rtlpriv, isr_regaddr); + while (!(content & IMR_CPWM) && (count < 500)) { + udelay(50); + count++; + content = rtl_read_dword(rtlpriv, isr_regaddr); + } + + if (content & IMR_CPWM) { + rtl_write_word(rtlpriv, isr_regaddr, 0x0100); + rtlhal->fw_ps_state = FW_PS_STATE_RF_ON; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Receive CPWM INT!!! Set pHalData->FwPSState = %X\n", + rtlhal->fw_ps_state); + } + } + + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + if (b_schedule_timer) + mod_timer(&rtlpriv->works.fw_clockoff_timer, + jiffies + MSECS(10)); + } else { + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + } +} + +static void _rtl8723be_set_fw_clock_off(struct ieee80211_hw *hw, u8 rpwm_val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + enum rf_pwrstate rtstate; + bool b_schedule_timer = false; + u8 queue; + + if (!rtlhal->fw_ready) + return; + if (!rtlpriv->psc.fw_current_inpsmode) + return; + if (!rtlhal->allow_sw_to_change_hwclc) + return; + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate)); + if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF) + return; + + for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) { + ring = &rtlpci->tx_ring[queue]; + if (skb_queue_len(&ring->queue)) { + b_schedule_timer = true; + break; + } + } + + if (b_schedule_timer) { + mod_timer(&rtlpriv->works.fw_clockoff_timer, + jiffies + MSECS(10)); + return; + } + + if (FW_PS_STATE(rtlhal->fw_ps_state) != FW_PS_STATE_RF_OFF_LOW_PWR) { + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + if (!rtlhal->fw_clk_change_in_progress) { + rtlhal->fw_clk_change_in_progress = true; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); + rtl_write_word(rtlpriv, REG_HISR, 0x0100); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + } else { + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + mod_timer(&rtlpriv->works.fw_clockoff_timer, + jiffies + MSECS(10)); + } + } + +} + +static void _rtl8723be_set_fw_ps_rf_on(struct ieee80211_hw *hw) +{ + u8 rpwm_val = 0; + rpwm_val |= (FW_PS_STATE_RF_OFF | FW_PS_ACK); + _rtl8723be_set_fw_clock_on(hw, rpwm_val, true); +} + +static void _rtl8723be_fwlps_leave(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool fw_current_inps = false; + u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE; + + if (ppsc->low_power_enable) { + rpwm_val = (FW_PS_STATE_ALL_ON | FW_PS_ACK);/* RF on */ + _rtl8723be_set_fw_clock_on(hw, rpwm_val, false); + rtlhal->allow_sw_to_change_hwclc = false; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&fw_pwrmode)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + } else { + rpwm_val = FW_PS_STATE_ALL_ON; /* RF on */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&fw_pwrmode)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + } + +} + +static void _rtl8723be_fwlps_enter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool fw_current_inps = true; + u8 rpwm_val; + + if (ppsc->low_power_enable) { + rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR; /* RF off */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&ppsc->fwctrl_psmode)); + rtlhal->allow_sw_to_change_hwclc = true; + _rtl8723be_set_fw_clock_off(hw, rpwm_val); + } else { + rpwm_val = FW_PS_STATE_RF_OFF; /* RF off */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&ppsc->fwctrl_psmode)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + } + +} + +void rtl8723be_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + switch (variable) { + case HW_VAR_RCR: + *((u32 *)(val)) = rtlpci->receive_config; + break; + case HW_VAR_RF_STATE: + *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; + break; + case HW_VAR_FWLPS_RF_ON:{ + enum rf_pwrstate rfState; + u32 val_rcr; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, + (u8 *)(&rfState)); + if (rfState == ERFOFF) { + *((bool *)(val)) = true; + } else { + val_rcr = rtl_read_dword(rtlpriv, REG_RCR); + val_rcr &= 0x00070000; + if (val_rcr) + *((bool *)(val)) = false; + else + *((bool *)(val)) = true; + } + } + break; + case HW_VAR_FW_PSMODE_STATUS: + *((bool *)(val)) = ppsc->fw_current_inpsmode; + break; + case HW_VAR_CORRECT_TSF:{ + u64 tsf; + u32 *ptsf_low = (u32 *)&tsf; + u32 *ptsf_high = ((u32 *)&tsf) + 1; + + *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); + *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + *((u64 *)(val)) = tsf; + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process %x\n", variable); + break; + } +} + +static void _rtl8723be_download_rsvd_page(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp_regcr, tmp_reg422, bcnvalid_reg; + u8 count = 0, dlbcn_count = 0; + bool b_recover = false; + + tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, + (tmp_regcr | BIT(0))); + + _rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(3)); + _rtl8723be_set_bcn_ctrl_reg(hw, BIT(4), 0); + + tmp_reg422 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422 & (~BIT(6))); + if (tmp_reg422 & BIT(6)) + b_recover = true; + + do { + bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); + rtl_write_byte(rtlpriv, REG_TDECTRL + 2, + (bcnvalid_reg | BIT(0))); + _rtl8723be_return_beacon_queue_skb(hw); + + rtl8723be_set_fw_rsvdpagepkt(hw, 0); + bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); + count = 0; + while (!(bcnvalid_reg & BIT(0)) && count < 20) { + count++; + udelay(10); + bcnvalid_reg = rtl_read_byte(rtlpriv, + REG_TDECTRL + 2); + } + dlbcn_count++; + } while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5); + + if (bcnvalid_reg & BIT(0)) + rtl_write_byte(rtlpriv, REG_TDECTRL + 2, BIT(0)); + + _rtl8723be_set_bcn_ctrl_reg(hw, BIT(3), 0); + _rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(4)); + + if (b_recover) + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422); + + tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr & ~(BIT(0)))); +} + +void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 idx; + + switch (variable) { + case HW_VAR_ETHER_ADDR: + for (idx = 0; idx < ETH_ALEN; idx++) + rtl_write_byte(rtlpriv, (REG_MACID + idx), val[idx]); + break; + case HW_VAR_BASIC_RATE:{ + u16 b_rate_cfg = ((u16 *)val)[0]; + u8 rate_index = 0; + b_rate_cfg = b_rate_cfg & 0x15f; + b_rate_cfg |= 0x01; + rtl_write_byte(rtlpriv, REG_RRSR, b_rate_cfg & 0xff); + rtl_write_byte(rtlpriv, REG_RRSR + 1, (b_rate_cfg >> 8) & 0xff); + while (b_rate_cfg > 0x1) { + b_rate_cfg = (b_rate_cfg >> 1); + rate_index++; + } + rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, rate_index); + } + break; + case HW_VAR_BSSID: + for (idx = 0; idx < ETH_ALEN; idx++) + rtl_write_byte(rtlpriv, (REG_BSSID + idx), val[idx]); + + break; + case HW_VAR_SIFS: + rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); + rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); + + rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); + rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); + + if (!mac->ht_enable) + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, 0x0e0e); + else + rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, + *((u16 *)val)); + break; + case HW_VAR_SLOT_TIME:{ + u8 e_aci; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "HW_VAR_SLOT_TIME %x\n", val[0]); + + rtl_write_byte(rtlpriv, REG_SLOT, val[0]); + + for (e_aci = 0; e_aci < AC_MAX; e_aci++) { + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + (u8 *)(&e_aci)); + } + } + break; + case HW_VAR_ACK_PREAMBLE:{ + u8 reg_tmp; + u8 short_preamble = (bool)(*(u8 *)val); + reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL + 2); + if (short_preamble) { + reg_tmp |= 0x02; + rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp); + } else { + reg_tmp &= 0xFD; + rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp); + } + } + break; + case HW_VAR_WPA_CONFIG: + rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); + break; + case HW_VAR_AMPDU_MIN_SPACE:{ + u8 min_spacing_to_set; + u8 sec_min_space; + + min_spacing_to_set = *((u8 *)val); + if (min_spacing_to_set <= 7) { + sec_min_space = 0; + + if (min_spacing_to_set < sec_min_space) + min_spacing_to_set = sec_min_space; + + mac->min_space_cfg = ((mac->min_space_cfg & 0xf8) | + min_spacing_to_set); + + *val = min_spacing_to_set; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", + mac->min_space_cfg); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + } + } + break; + case HW_VAR_SHORTGI_DENSITY:{ + u8 density_to_set; + + density_to_set = *((u8 *)val); + mac->min_space_cfg |= (density_to_set << 3); + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_SHORTGI_DENSITY: %#x\n", + mac->min_space_cfg); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + } + break; + case HW_VAR_AMPDU_FACTOR:{ + u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9}; + u8 factor_toset; + u8 *p_regtoset = NULL; + u8 index = 0; + + p_regtoset = regtoset_normal; + + factor_toset = *((u8 *)val); + if (factor_toset <= 3) { + factor_toset = (1 << (factor_toset + 2)); + if (factor_toset > 0xf) + factor_toset = 0xf; + + for (index = 0; index < 4; index++) { + if ((p_regtoset[index] & 0xf0) > + (factor_toset << 4)) + p_regtoset[index] = + (p_regtoset[index] & 0x0f) | + (factor_toset << 4); + + if ((p_regtoset[index] & 0x0f) > factor_toset) + p_regtoset[index] = + (p_regtoset[index] & 0xf0) | + (factor_toset); + + rtl_write_byte(rtlpriv, + (REG_AGGLEN_LMT + index), + p_regtoset[index]); + + } + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_FACTOR: %#x\n", + factor_toset); + } + } + break; + case HW_VAR_AC_PARAM:{ + u8 e_aci = *((u8 *)val); + rtl8723_dm_init_edca_turbo(hw); + + if (rtlpci->acm_method != EACMWAY2_SW) + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, + (u8 *)(&e_aci)); + } + break; + case HW_VAR_ACM_CTRL:{ + u8 e_aci = *((u8 *)val); + union aci_aifsn *p_aci_aifsn = + (union aci_aifsn *)(&(mac->ac[0].aifs)); + u8 acm = p_aci_aifsn->f.acm; + u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); + + acm_ctrl = + acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); + + if (acm) { + switch (e_aci) { + case AC0_BE: + acm_ctrl |= ACMHW_BEQEN; + break; + case AC2_VI: + acm_ctrl |= ACMHW_VIQEN; + break; + case AC3_VO: + acm_ctrl |= ACMHW_VOQEN; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", + acm); + break; + } + } else { + switch (e_aci) { + case AC0_BE: + acm_ctrl &= (~ACMHW_BEQEN); + break; + case AC2_VI: + acm_ctrl &= (~ACMHW_VIQEN); + break; + case AC3_VO: + acm_ctrl &= (~ACMHW_VOQEN); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + } + + RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, + "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", + acm_ctrl); + rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); + } + break; + case HW_VAR_RCR: + rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); + rtlpci->receive_config = ((u32 *)(val))[0]; + break; + case HW_VAR_RETRY_LIMIT:{ + u8 retry_limit = ((u8 *)(val))[0]; + + rtl_write_word(rtlpriv, REG_RL, + retry_limit << RETRY_LIMIT_SHORT_SHIFT | + retry_limit << RETRY_LIMIT_LONG_SHIFT); + } + break; + case HW_VAR_DUAL_TSF_RST: + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); + break; + case HW_VAR_EFUSE_BYTES: + rtlefuse->efuse_usedbytes = *((u16 *)val); + break; + case HW_VAR_EFUSE_USAGE: + rtlefuse->efuse_usedpercentage = *((u8 *)val); + break; + case HW_VAR_IO_CMD: + rtl8723be_phy_set_io_cmd(hw, (*(enum io_type *)val)); + break; + case HW_VAR_SET_RPWM:{ + u8 rpwm_val; + + rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); + udelay(1); + + if (rpwm_val & BIT(7)) { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, (*(u8 *)val)); + } else { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, + ((*(u8 *)val) | BIT(7))); + } + } + break; + case HW_VAR_H2C_FW_PWRMODE: + rtl8723be_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); + break; + case HW_VAR_FW_PSMODE_STATUS: + ppsc->fw_current_inpsmode = *((bool *)val); + break; + case HW_VAR_RESUME_CLK_ON: + _rtl8723be_set_fw_ps_rf_on(hw); + break; + case HW_VAR_FW_LPS_ACTION:{ + bool b_enter_fwlps = *((bool *)val); + + if (b_enter_fwlps) + _rtl8723be_fwlps_enter(hw); + else + _rtl8723be_fwlps_leave(hw); + } + break; + case HW_VAR_H2C_FW_JOINBSSRPT:{ + u8 mstatus = (*(u8 *)val); + + if (mstatus == RT_MEDIA_CONNECT) { + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL); + _rtl8723be_download_rsvd_page(hw); + } + rtl8723be_set_fw_media_status_rpt_cmd(hw, mstatus); + } + break; + case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: + rtl8723be_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); + break; + case HW_VAR_AID:{ + u16 u2btmp; + u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); + u2btmp &= 0xC000; + rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, + (u2btmp | mac->assoc_id)); + } + break; + case HW_VAR_CORRECT_TSF:{ + u8 btype_ibss = ((u8 *)(val))[0]; + + if (btype_ibss) + _rtl8723be_stop_tx_beacon(hw); + + _rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(3)); + + rtl_write_dword(rtlpriv, REG_TSFTR, + (u32) (mac->tsf & 0xffffffff)); + rtl_write_dword(rtlpriv, REG_TSFTR + 4, + (u32) ((mac->tsf >> 32) & 0xffffffff)); + + _rtl8723be_set_bcn_ctrl_reg(hw, BIT(3), 0); + + if (btype_ibss) + _rtl8723be_resume_tx_beacon(hw); + } + break; + case HW_VAR_KEEP_ALIVE:{ + u8 array[2]; + array[0] = 0xff; + array[1] = *((u8 *)val); + rtl8723be_fill_h2c_cmd(hw, H2C_8723B_KEEP_ALIVE_CTRL, 2, array); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process %x\n", + variable); + break; + } +} + +static bool _rtl8723be_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool status = true; + long count = 0; + u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | + _LLT_OP(_LLT_WRITE_ACCESS); + + rtl_write_dword(rtlpriv, REG_LLT_INIT, value); + + do { + value = rtl_read_dword(rtlpriv, REG_LLT_INIT); + if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) + break; + + if (count > POLLING_LLT_THRESHOLD) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to polling write LLT done at address %d!\n", + address); + status = false; + break; + } + } while (++count); + + return status; +} + +static bool _rtl8723be_llt_table_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + unsigned short i; + u8 txpktbuf_bndy; + u8 maxPage; + bool status; + + maxPage = 255; + txpktbuf_bndy = 245; + + rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, + (0x27FF0000 | txpktbuf_bndy)); + rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_PBP, 0x31); + rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); + + for (i = 0; i < (txpktbuf_bndy - 1); i++) { + status = _rtl8723be_llt_write(hw, i, i + 1); + if (!status) + return status; + } + + status = _rtl8723be_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); + + if (!status) + return status; + + for (i = txpktbuf_bndy; i < maxPage; i++) { + status = _rtl8723be_llt_write(hw, i, (i + 1)); + if (!status) + return status; + } + + status = _rtl8723be_llt_write(hw, maxPage, txpktbuf_bndy); + if (!status) + return status; + + rtl_write_dword(rtlpriv, REG_RQPN, 0x80e40808); + rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x00); + + return true; +} + +static void _rtl8723be_gen_refresh_led_state(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_led *pled0 = &(pcipriv->ledctl.sw_led0); + + if (rtlpriv->rtlhal.up_first_time) + return; + + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) + rtl8723be_sw_led_on(hw, pled0); + else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) + rtl8723be_sw_led_on(hw, pled0); + else + rtl8723be_sw_led_off(hw, pled0); +} + +static bool _rtl8723be_init_mac(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + unsigned char bytetmp; + unsigned short wordtmp; + + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); + + /*Auto Power Down to CHIP-off State*/ + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7)); + rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); + + /* HW Power on sequence */ + if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, + PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, + RTL8723_NIC_ENABLE_FLOW)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "init MAC Fail as power on failure\n"); + return false; + } + + bytetmp = rtl_read_byte(rtlpriv, REG_MULTI_FUNC_CTRL); + rtl_write_byte(rtlpriv, REG_MULTI_FUNC_CTRL, bytetmp | BIT(3)); + + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4); + rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp); + + bytetmp = rtl_read_byte(rtlpriv, REG_CR); + bytetmp = 0xff; + rtl_write_byte(rtlpriv, REG_CR, bytetmp); + mdelay(2); + + bytetmp = rtl_read_byte(rtlpriv, REG_HWSEQ_CTRL); + bytetmp |= 0x7f; + rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, bytetmp); + mdelay(2); + + bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CFG + 3); + if (bytetmp & BIT(0)) { + bytetmp = rtl_read_byte(rtlpriv, 0x7c); + rtl_write_byte(rtlpriv, 0x7c, bytetmp | BIT(6)); + } + + bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR); + rtl_write_byte(rtlpriv, REG_SYS_CLKR, bytetmp | BIT(3)); + bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG + 1); + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG + 1, bytetmp & (~BIT(4))); + + rtl_write_word(rtlpriv, REG_CR, 0x2ff); + + if (!rtlhal->mac_func_enable) { + if (_rtl8723be_llt_table_init(hw) == false) + return false; + } + + rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); + rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff); + + /* Enable FW Beamformer Interrupt */ + bytetmp = rtl_read_byte(rtlpriv, REG_FWIMR + 3); + rtl_write_byte(rtlpriv, REG_FWIMR + 3, bytetmp | BIT(6)); + + wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); + wordtmp &= 0xf; + wordtmp |= 0xF5B1; + rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); + + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xFFFF); + rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); + + rtl_write_dword(rtlpriv, REG_BCNQ_DESA, + ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_MGQ_DESA, + (u64) rtlpci->tx_ring[MGNT_QUEUE].dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VOQ_DESA, + (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VIQ_DESA, + (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BEQ_DESA, + (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BKQ_DESA, + (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_HQ_DESA, + (u64) rtlpci->tx_ring[HIGH_QUEUE].dma & + DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_RX_DESA, + (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma & + DMA_BIT_MASK(32)); + + bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 3); + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, bytetmp | 0x77); + + rtl_write_dword(rtlpriv, REG_INT_MIG, 0); + + rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); + + rtl_write_byte(rtlpriv, REG_SECONDARY_CCA_CTRL, 0x3); + + /* <20130114, Kordan> The following setting is + * only for DPDT and Fixed board type. + * TODO: A better solution is configure it + * according EFUSE during the run-time. + */ + rtl_set_bbreg(hw, 0x64, BIT(20), 0x0);/* 0x66[4]=0 */ + rtl_set_bbreg(hw, 0x64, BIT(24), 0x0);/* 0x66[8]=0 */ + rtl_set_bbreg(hw, 0x40, BIT(4), 0x0)/* 0x40[4]=0 */; + rtl_set_bbreg(hw, 0x40, BIT(3), 0x1)/* 0x40[3]=1 */; + rtl_set_bbreg(hw, 0x4C, BIT(24) | BIT(23), 0x2)/* 0x4C[24:23]=10 */; + rtl_set_bbreg(hw, 0x944, BIT(1) | BIT(0), 0x3)/* 0x944[1:0]=11 */; + rtl_set_bbreg(hw, 0x930, MASKBYTE0, 0x77)/* 0x930[7:0]=77 */; + rtl_set_bbreg(hw, 0x38, BIT(11), 0x1)/* 0x38[11]=1 */; + + bytetmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, bytetmp & (~BIT(2))); + + _rtl8723be_gen_refresh_led_state(hw); + return true; +} + +static void _rtl8723be_hw_configure(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 reg_rrsr; + + reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + /* Init value for RRSR. */ + rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr); + + /* ARFB table 9 for 11ac 5G 2SS */ + rtl_write_dword(rtlpriv, REG_ARFR0 + 4, 0xfffff000); + + /* ARFB table 10 for 11ac 5G 1SS */ + rtl_write_dword(rtlpriv, REG_ARFR1 + 4, 0x003ff000); + + /* CF-End setting. */ + rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F00); + + /* 0x456 = 0x70, sugguested by Zhilin */ + rtl_write_byte(rtlpriv, REG_AMPDU_MAX_TIME, 0x70); + + /* Set retry limit */ + rtl_write_word(rtlpriv, REG_RL, 0x0707); + + /* Set Data / Response auto rate fallack retry count */ + rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); + rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); + + rtlpci->reg_bcn_ctrl_val = 0x1d; + rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); + + /* TBTT prohibit hold time. Suggested by designer TimChen. */ + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); /* 8 ms */ + + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040); + + /*For Rx TP. Suggested by SD1 Richard. Added by tynli. 2010.04.12.*/ + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); + + rtl_write_byte(rtlpriv, REG_HT_SINGLE_AMPDU, 0x80); + + rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20); + + rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x1F); +} + +static u8 _rtl8723be_dbi_read(struct rtl_priv *rtlpriv, u16 addr) +{ + u16 read_addr = addr & 0xfffc; + u8 ret = 0, tmp = 0, count = 0; + + rtl_write_word(rtlpriv, REG_DBI_ADDR, read_addr); + rtl_write_byte(rtlpriv, REG_DBI_FLAG, 0x2); + tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); + count = 0; + while (tmp && count < 20) { + udelay(10); + tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); + count++; + } + if (0 == tmp) { + read_addr = REG_DBI_RDATA + addr % 4; + ret = rtl_read_byte(rtlpriv, read_addr); + } + + return ret; +} + +static void _rtl8723be_dbi_write(struct rtl_priv *rtlpriv, u16 addr, u8 data) +{ + u8 tmp = 0, count = 0; + u16 write_addr = 0, remainder = addr % 4; + + /* Write DBI 1Byte Data */ + write_addr = REG_DBI_WDATA + remainder; + rtl_write_byte(rtlpriv, write_addr, data); + + /* Write DBI 2Byte Address & Write Enable */ + write_addr = (addr & 0xfffc) | (BIT(0) << (remainder + 12)); + rtl_write_word(rtlpriv, REG_DBI_ADDR, write_addr); + + /* Write DBI Write Flag */ + rtl_write_byte(rtlpriv, REG_DBI_FLAG, 0x1); + + tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); + count = 0; + while (tmp && count < 20) { + udelay(10); + tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); + count++; + } +} + +static u16 _rtl8723be_mdio_read(struct rtl_priv *rtlpriv, u8 addr) +{ + u16 ret = 0; + u8 tmp = 0, count = 0; + + rtl_write_byte(rtlpriv, REG_MDIO_CTL, addr | BIT(6)); + tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(6); + count = 0; + while (tmp && count < 20) { + udelay(10); + tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(6); + count++; + } + + if (0 == tmp) + ret = rtl_read_word(rtlpriv, REG_MDIO_RDATA); + + return ret; +} + +static void _rtl8723be_mdio_write(struct rtl_priv *rtlpriv, u8 addr, u16 data) +{ + u8 tmp = 0, count = 0; + + rtl_write_word(rtlpriv, REG_MDIO_WDATA, data); + rtl_write_byte(rtlpriv, REG_MDIO_CTL, addr | BIT(5)); + tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(5); + count = 0; + while (tmp && count < 20) { + udelay(10); + tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(5); + count++; + } +} + +static void _rtl8723be_enable_aspm_back_door(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp8 = 0; + u16 tmp16 = 0; + + /* Overwrite following ePHY parameter for + * some platform compatibility issue, + * especially when CLKReq is enabled, 2012.11.09. + */ + tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x01); + if (tmp16 != 0x0663) + _rtl8723be_mdio_write(rtlpriv, 0x01, 0x0663); + + tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x04); + if (tmp16 != 0x7544) + _rtl8723be_mdio_write(rtlpriv, 0x04, 0x7544); + + tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x06); + if (tmp16 != 0xB880) + _rtl8723be_mdio_write(rtlpriv, 0x06, 0xB880); + + tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x07); + if (tmp16 != 0x4000) + _rtl8723be_mdio_write(rtlpriv, 0x07, 0x4000); + + tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x08); + if (tmp16 != 0x9003) + _rtl8723be_mdio_write(rtlpriv, 0x08, 0x9003); + + tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x09); + if (tmp16 != 0x0D03) + _rtl8723be_mdio_write(rtlpriv, 0x09, 0x0D03); + + tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x0A); + if (tmp16 != 0x4037) + _rtl8723be_mdio_write(rtlpriv, 0x0A, 0x4037); + + tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x0B); + if (tmp16 != 0x0070) + _rtl8723be_mdio_write(rtlpriv, 0x0B, 0x0070); + + /* Configuration Space offset 0x70f BIT7 is used to control L0S */ + tmp8 = _rtl8723be_dbi_read(rtlpriv, 0x70f); + _rtl8723be_dbi_write(rtlpriv, 0x70f, tmp8 | BIT(7)); + + /* Configuration Space offset 0x719 Bit3 is for L1 + * BIT4 is for clock request + */ + tmp8 = _rtl8723be_dbi_read(rtlpriv, 0x719); + _rtl8723be_dbi_write(rtlpriv, 0x719, tmp8 | BIT(3) | BIT(4)); +} + +void rtl8723be_enable_hw_security_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 sec_reg_value; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", + rtlpriv->sec.pairwise_enc_algorithm, + rtlpriv->sec.group_enc_algorithm); + + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "not open hw encryption\n"); + return; + } + + sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; + + if (rtlpriv->sec.use_defaultkey) { + sec_reg_value |= SCR_TXUSEDK; + sec_reg_value |= SCR_RXUSEDK; + } + + sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); + + rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "The SECR-value %x\n", sec_reg_value); + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); +} + +static void _rtl8723be_poweroff_adapter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 u1b_tmp; + + rtlhal->mac_func_enable = false; + /* Combo (PCIe + USB) Card and PCIe-MF Card */ + /* 1. Run LPS WL RFOFF flow */ + rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, RTL8723_NIC_LPS_ENTER_FLOW); + + /* 2. 0x1F[7:0] = 0 */ + /* turn off RF */ + /* rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); */ + if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && + rtlhal->fw_ready) { + rtl8723be_firmware_selfreset(hw); + } + + /* Reset MCU. Suggested by Filen. */ + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); + + /* g. MCUFWDL 0x80[1:0]=0 */ + /* reset MCU ready status */ + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); + + /* HW card disable configuration. */ + rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, RTL8723_NIC_DISABLE_FLOW); + + /* Reset MCU IO Wrapper */ + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, u1b_tmp | BIT(0)); + + /* 7. RSV_CTRL 0x1C[7:0] = 0x0E */ + /* lock ISO/CLK/Power control register */ + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); +} + +static bool _rtl8723be_check_pcie_dma_hang(struct rtl_priv *rtlpriv) +{ + u8 tmp; + + /* write reg 0x350 Bit[26]=1. Enable debug port. */ + tmp = rtl_read_byte(rtlpriv, REG_DBI_CTRL + 3); + if (!(tmp & BIT(2))) { + rtl_write_byte(rtlpriv, REG_DBI_CTRL + 3, (tmp | BIT(2))); + mdelay(100); /* Suggested by DD Justin_tsai. */ + } + + /* read reg 0x350 Bit[25] if 1 : RX hang + * read reg 0x350 Bit[24] if 1 : TX hang + */ + tmp = rtl_read_byte(rtlpriv, REG_DBI_CTRL + 3); + if ((tmp & BIT(0)) || (tmp & BIT(1))) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "CheckPcieDMAHang8723BE(): true!!\n"); + return true; + } + return false; +} + +static void _rtl8723be_reset_pcie_interface_dma(struct rtl_priv *rtlpriv, + bool mac_power_on) +{ + u8 tmp; + bool release_mac_rx_pause; + u8 backup_pcie_dma_pause; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "ResetPcieInterfaceDMA8723BE()\n"); + + /* Revise Note: Follow the document "PCIe RX DMA Hang Reset Flow_v03" + * released by SD1 Alan. + * 2013.05.07, by tynli. + */ + + /* 1. disable register write lock + * write 0x1C bit[1:0] = 2'h0 + * write 0xCC bit[2] = 1'b1 + */ + tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL); + tmp &= ~(BIT(1) | BIT(0)); + rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp); + tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); + tmp |= BIT(2); + rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); + + /* 2. Check and pause TRX DMA + * write 0x284 bit[18] = 1'b1 + * write 0x301 = 0xFF + */ + tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + if (tmp & BIT(2)) { + /* Already pause before the function for another purpose. */ + release_mac_rx_pause = false; + } else { + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2))); + release_mac_rx_pause = true; + } + + backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1); + if (backup_pcie_dma_pause != 0xFF) + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF); + + if (mac_power_on) { + /* 3. reset TRX function + * write 0x100 = 0x00 + */ + rtl_write_byte(rtlpriv, REG_CR, 0); + } + + /* 4. Reset PCIe DMA + * write 0x003 bit[0] = 0 + */ + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + tmp &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); + + /* 5. Enable PCIe DMA + * write 0x003 bit[0] = 1 + */ + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + tmp |= BIT(0); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); + + if (mac_power_on) { + /* 6. enable TRX function + * write 0x100 = 0xFF + */ + rtl_write_byte(rtlpriv, REG_CR, 0xFF); + + /* We should init LLT & RQPN and + * prepare Tx/Rx descrptor address later + * because MAC function is reset. + */ + } + + /* 7. Restore PCIe autoload down bit + * write 0xF8 bit[17] = 1'b1 + */ + tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2); + tmp |= BIT(1); + rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp); + + /* In MAC power on state, BB and RF maybe in ON state, + * if we release TRx DMA here + * it will cause packets to be started to Tx/Rx, + * so we release Tx/Rx DMA later. + */ + if (!mac_power_on) { + /* 8. release TRX DMA + * write 0x284 bit[18] = 1'b0 + * write 0x301 = 0x00 + */ + if (release_mac_rx_pause) { + tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, + (tmp & (~BIT(2)))); + } + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, + backup_pcie_dma_pause); + } + + /* 9. lock system register + * write 0xCC bit[2] = 1'b0 + */ + tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); + tmp &= ~(BIT(2)); + rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); +} + +int rtl8723be_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + bool rtstatus = true; + int err; + u8 tmp_u1b; + unsigned long flags; + + /* reenable interrupts to not interfere with other devices */ + local_save_flags(flags); + local_irq_enable(); + + rtlhal->fw_ready = false; + rtlpriv->rtlhal.being_init_adapter = true; + rtlpriv->intf_ops->disable_aspm(hw); + + tmp_u1b = rtl_read_byte(rtlpriv, REG_CR); + if (tmp_u1b != 0 && tmp_u1b != 0xea) { + rtlhal->mac_func_enable = true; + } else { + rtlhal->mac_func_enable = false; + rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON; + } + + if (_rtl8723be_check_pcie_dma_hang(rtlpriv)) { + _rtl8723be_reset_pcie_interface_dma(rtlpriv, + rtlhal->mac_func_enable); + rtlhal->mac_func_enable = false; + } + if (rtlhal->mac_func_enable) { + _rtl8723be_poweroff_adapter(hw); + rtlhal->mac_func_enable = false; + } + rtstatus = _rtl8723be_init_mac(hw); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); + err = 1; + goto exit; + } + + tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CFG); + rtl_write_byte(rtlpriv, REG_SYS_CFG, tmp_u1b & 0x7F); + + err = rtl8723_download_fw(hw, true, FW_8723B_POLLING_TIMEOUT_COUNT); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW now..\n"); + err = 1; + goto exit; + } + rtlhal->fw_ready = true; + + rtlhal->last_hmeboxnum = 0; + rtl8723be_phy_mac_config(hw); + /* because last function modify RCR, so we update + * rcr var here, or TP will unstable for receive_config + * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx + * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 + */ + rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); + rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + + rtl8723be_phy_bb_config(hw); + rtl8723be_phy_rf_config(hw); + + rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, + RF_CHNLBW, RFREG_OFFSET_MASK); + rtlphy->rfreg_chnlval[0] &= 0xFFF03FF; + rtlphy->rfreg_chnlval[0] |= (BIT(10) | BIT(11)); + + _rtl8723be_hw_configure(hw); + rtlhal->mac_func_enable = true; + rtl_cam_reset_all_entry(hw); + rtl8723be_enable_hw_security_config(hw); + + ppsc->rfpwr_state = ERFON; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); + _rtl8723be_enable_aspm_back_door(hw); + rtlpriv->intf_ops->enable_aspm(hw); + + rtl8723be_bt_hw_init(hw); + + if (ppsc->rfpwr_state == ERFON) { + rtl8723be_phy_set_rfpath_switch(hw, 1); + /* when use 1ant NIC, iqk will disturb BT music + * root cause is not clear now, is something + * related with 'mdelay' and Reg[0x948] + */ + if (rtlpriv->btcoexist.btc_info.ant_num == ANT_X2 || + !rtlpriv->cfg->ops->get_btc_status()) { + rtl8723be_phy_iq_calibrate(hw, false); + rtlphy->iqk_initialized = true; + } + rtl8723be_dm_check_txpower_tracking(hw); + rtl8723be_phy_lc_calibrate(hw); + } + rtl_write_byte(rtlpriv, REG_NAV_UPPER, ((30000 + 127) / 128)); + + /* Release Rx DMA. */ + tmp_u1b = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + if (tmp_u1b & BIT(2)) { + /* Release Rx DMA if needed */ + tmp_u1b &= (~BIT(2)); + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, tmp_u1b); + } + /* Release Tx/Rx PCIE DMA. */ + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0); + + rtl8723be_dm_init(hw); +exit: + local_irq_restore(flags); + rtlpriv->rtlhal.being_init_adapter = false; + return err; +} + +static enum version_8723e _rtl8723be_read_chip_version(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + enum version_8723e version = VERSION_UNKNOWN; + u32 value32; + + value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG1); + if ((value32 & (CHIP_8723B)) != CHIP_8723B) + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "unkown chip version\n"); + else + version = (enum version_8723e)CHIP_8723B; + + rtlphy->rf_type = RF_1T1R; + + /* treat rtl8723be chip as MP version in default */ + version = (enum version_8723e)(version | NORMAL_CHIP); + + value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); + /* cut version */ + version |= (enum version_8723e)(value32 & CHIP_VER_RTL_MASK); + /* Manufacture */ + if (((value32 & EXT_VENDOR_ID) >> 18) == 0x01) + version = (enum version_8723e)(version | CHIP_VENDOR_SMIC); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ? + "RF_2T2R" : "RF_1T1R"); + + return version; +} + +static int _rtl8723be_set_media_status(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_msr = rtl_read_byte(rtlpriv, MSR) & 0xfc; + enum led_ctl_mode ledaction = LED_CTL_NO_LINK; + u8 mode = MSR_NOLINK; + + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + mode = MSR_NOLINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to NO LINK!\n"); + break; + case NL80211_IFTYPE_ADHOC: + case NL80211_IFTYPE_MESH_POINT: + mode = MSR_ADHOC; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to Ad Hoc!\n"); + break; + case NL80211_IFTYPE_STATION: + mode = MSR_INFRA; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to STA!\n"); + break; + case NL80211_IFTYPE_AP: + mode = MSR_AP; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to AP!\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Network type %d not support!\n", type); + return 1; + } + + /* MSR_INFRA == Link in infrastructure network; + * MSR_ADHOC == Link in ad hoc network; + * Therefore, check link state is necessary. + * + * MSR_AP == AP mode; link state is not cared here. + */ + if (mode != MSR_AP && rtlpriv->mac80211.link_state < MAC80211_LINKED) { + mode = MSR_NOLINK; + ledaction = LED_CTL_NO_LINK; + } + + if (mode == MSR_NOLINK || mode == MSR_INFRA) { + _rtl8723be_stop_tx_beacon(hw); + _rtl8723be_enable_bcn_sub_func(hw); + } else if (mode == MSR_ADHOC || mode == MSR_AP) { + _rtl8723be_resume_tx_beacon(hw); + _rtl8723be_disable_bcn_sub_func(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", + mode); + } + + rtl_write_byte(rtlpriv, MSR, bt_msr | mode); + rtlpriv->cfg->ops->led_control(hw, ledaction); + if (mode == MSR_AP) + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); + else + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); + return 0; +} + +void rtl8723be_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 reg_rcr = rtlpci->receive_config; + + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + if (check_bssid) { + reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, + (u8 *)(®_rcr)); + _rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(4)); + } else if (!check_bssid) { + reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); + _rtl8723be_set_bcn_ctrl_reg(hw, BIT(4), 0); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, + (u8 *)(®_rcr)); + } + +} + +int rtl8723be_set_network_type(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (_rtl8723be_set_media_status(hw, type)) + return -EOPNOTSUPP; + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP) + rtl8723be_set_check_bssid(hw, true); + } else { + rtl8723be_set_check_bssid(hw, false); + } + + return 0; +} + +/* don't set REG_EDCA_BE_PARAM here + * because mac80211 will send pkt when scan + */ +void rtl8723be_set_qos(struct ieee80211_hw *hw, int aci) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl8723_dm_init_edca_turbo(hw); + switch (aci) { + case AC1_BK: + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); + break; + case AC0_BE: + break; + case AC2_VI: + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); + break; + case AC3_VO: + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); + break; + default: + RT_ASSERT(false, "invalid aci: %d !\n", aci); + break; + } +} + +void rtl8723be_enable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); + rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); + rtlpci->irq_enabled = true; + + /*enable system interrupt*/ + rtl_write_dword(rtlpriv, REG_HSIMR, rtlpci->sys_irq_mask & 0xFFFFFFFF); +} + +void rtl8723be_disable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED); + rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED); + rtlpci->irq_enabled = false; + /*synchronize_irq(rtlpci->pdev->irq);*/ +} + +void rtl8723be_card_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + enum nl80211_iftype opmode; + + mac->link_state = MAC80211_NOLINK; + opmode = NL80211_IFTYPE_UNSPECIFIED; + _rtl8723be_set_media_status(hw, opmode); + if (rtlpriv->rtlhal.driver_is_goingto_unload || + ppsc->rfoff_reason > RF_CHANGE_BY_PS) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + _rtl8723be_poweroff_adapter(hw); + + /* after power off we should do iqk again */ + rtlpriv->phy.iqk_initialized = false; +} + +void rtl8723be_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; + rtl_write_dword(rtlpriv, ISR, *p_inta); + + *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & + rtlpci->irq_mask[1]; + rtl_write_dword(rtlpriv, REG_HISRE, *p_intb); +} + +void rtl8723be_set_beacon_related_registers(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval, atim_window; + + bcn_interval = mac->beacon_interval; + atim_window = 2; /*FIX MERGE */ + rtl8723be_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); + rtl_write_byte(rtlpriv, 0x606, 0x30); + rtl8723be_enable_interrupt(hw); +} + +void rtl8723be_set_beacon_interval(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval = mac->beacon_interval; + + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "beacon_interval:%d\n", bcn_interval); + rtl8723be_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl8723be_enable_interrupt(hw); +} + +void rtl8723be_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, + "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); + + if (add_msr) + rtlpci->irq_mask[0] |= add_msr; + if (rm_msr) + rtlpci->irq_mask[0] &= (~rm_msr); + rtl8723be_disable_interrupt(hw); + rtl8723be_enable_interrupt(hw); +} + +static u8 _rtl8723be_get_chnl_group(u8 chnl) +{ + u8 group; + + if (chnl < 3) + group = 0; + else if (chnl < 9) + group = 1; + else + group = 2; + return group; +} + +static void _rtl8723be_read_power_value_fromprom(struct ieee80211_hw *hw, + struct txpower_info_2g *pw2g, + struct txpower_info_5g *pw5g, + bool autoload_fail, u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 path, addr = EEPROM_TX_PWR_INX, group, cnt = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "hal_ReadPowerValueFromPROM8723BE(): PROMContent[0x%x]=0x%x\n", + (addr + 1), hwinfo[addr + 1]); + if (0xFF == hwinfo[addr + 1]) /*YJ,add,120316*/ + autoload_fail = true; + + if (autoload_fail) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "auto load fail : Use Default value!\n"); + for (path = 0; path < MAX_RF_PATH; path++) { + /* 2.4G default value */ + for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { + pw2g->index_cck_base[path][group] = 0x2D; + pw2g->index_bw40_base[path][group] = 0x2D; + } + for (cnt = 0; cnt < MAX_TX_COUNT; cnt++) { + if (cnt == 0) { + pw2g->bw20_diff[path][0] = 0x02; + pw2g->ofdm_diff[path][0] = 0x04; + } else { + pw2g->bw20_diff[path][cnt] = 0xFE; + pw2g->bw40_diff[path][cnt] = 0xFE; + pw2g->cck_diff[path][cnt] = 0xFE; + pw2g->ofdm_diff[path][cnt] = 0xFE; + } + } + } + return; + } + + for (path = 0; path < MAX_RF_PATH; path++) { + /*2.4G default value*/ + for (group = 0; group < MAX_CHNL_GROUP_24G; group++) { + pw2g->index_cck_base[path][group] = hwinfo[addr++]; + if (pw2g->index_cck_base[path][group] == 0xFF) + pw2g->index_cck_base[path][group] = 0x2D; + + } + for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++) { + pw2g->index_bw40_base[path][group] = hwinfo[addr++]; + if (pw2g->index_bw40_base[path][group] == 0xFF) + pw2g->index_bw40_base[path][group] = 0x2D; + } + for (cnt = 0; cnt < MAX_TX_COUNT; cnt++) { + if (cnt == 0) { + pw2g->bw40_diff[path][cnt] = 0; + if (hwinfo[addr] == 0xFF) { + pw2g->bw20_diff[path][cnt] = 0x02; + } else { + pw2g->bw20_diff[path][cnt] = + (hwinfo[addr] & 0xf0) >> 4; + /*bit sign number to 8 bit sign number*/ + if (pw2g->bw20_diff[path][cnt] & BIT(3)) + pw2g->bw20_diff[path][cnt] |= + 0xF0; + } + + if (hwinfo[addr] == 0xFF) { + pw2g->ofdm_diff[path][cnt] = 0x04; + } else { + pw2g->ofdm_diff[path][cnt] = + (hwinfo[addr] & 0x0f); + /*bit sign number to 8 bit sign number*/ + if (pw2g->ofdm_diff[path][cnt] & BIT(3)) + pw2g->ofdm_diff[path][cnt] |= + 0xF0; + } + pw2g->cck_diff[path][cnt] = 0; + addr++; + } else { + if (hwinfo[addr] == 0xFF) { + pw2g->bw40_diff[path][cnt] = 0xFE; + } else { + pw2g->bw40_diff[path][cnt] = + (hwinfo[addr] & 0xf0) >> 4; + if (pw2g->bw40_diff[path][cnt] & BIT(3)) + pw2g->bw40_diff[path][cnt] |= + 0xF0; + } + + if (hwinfo[addr] == 0xFF) { + pw2g->bw20_diff[path][cnt] = 0xFE; + } else { + pw2g->bw20_diff[path][cnt] = + (hwinfo[addr] & 0x0f); + if (pw2g->bw20_diff[path][cnt] & BIT(3)) + pw2g->bw20_diff[path][cnt] |= + 0xF0; + } + addr++; + + if (hwinfo[addr] == 0xFF) { + pw2g->ofdm_diff[path][cnt] = 0xFE; + } else { + pw2g->ofdm_diff[path][cnt] = + (hwinfo[addr] & 0xf0) >> 4; + if (pw2g->ofdm_diff[path][cnt] & BIT(3)) + pw2g->ofdm_diff[path][cnt] |= + 0xF0; + } + + if (hwinfo[addr] == 0xFF) + pw2g->cck_diff[path][cnt] = 0xFE; + else { + pw2g->cck_diff[path][cnt] = + (hwinfo[addr] & 0x0f); + if (pw2g->cck_diff[path][cnt] & BIT(3)) + pw2g->cck_diff[path][cnt] |= + 0xF0; + } + addr++; + } + } + + /*5G default value*/ + for (group = 0; group < MAX_CHNL_GROUP_5G; group++) { + pw5g->index_bw40_base[path][group] = hwinfo[addr++]; + if (pw5g->index_bw40_base[path][group] == 0xFF) + pw5g->index_bw40_base[path][group] = 0xFE; + } + + for (cnt = 0; cnt < MAX_TX_COUNT; cnt++) { + if (cnt == 0) { + pw5g->bw40_diff[path][cnt] = 0; + + if (hwinfo[addr] == 0xFF) { + pw5g->bw20_diff[path][cnt] = 0; + } else { + pw5g->bw20_diff[path][0] = + (hwinfo[addr] & 0xf0) >> 4; + if (pw5g->bw20_diff[path][cnt] & BIT(3)) + pw5g->bw20_diff[path][cnt] |= + 0xF0; + } + + if (hwinfo[addr] == 0xFF) + pw5g->ofdm_diff[path][cnt] = 0x04; + else { + pw5g->ofdm_diff[path][0] = + (hwinfo[addr] & 0x0f); + if (pw5g->ofdm_diff[path][cnt] & BIT(3)) + pw5g->ofdm_diff[path][cnt] |= + 0xF0; + } + addr++; + } else { + if (hwinfo[addr] == 0xFF) { + pw5g->bw40_diff[path][cnt] = 0xFE; + } else { + pw5g->bw40_diff[path][cnt] = + (hwinfo[addr] & 0xf0) >> 4; + if (pw5g->bw40_diff[path][cnt] & BIT(3)) + pw5g->bw40_diff[path][cnt] |= 0xF0; + } + + if (hwinfo[addr] == 0xFF) { + pw5g->bw20_diff[path][cnt] = 0xFE; + } else { + pw5g->bw20_diff[path][cnt] = + (hwinfo[addr] & 0x0f); + if (pw5g->bw20_diff[path][cnt] & BIT(3)) + pw5g->bw20_diff[path][cnt] |= 0xF0; + } + addr++; + } + } + + if (hwinfo[addr] == 0xFF) { + pw5g->ofdm_diff[path][1] = 0xFE; + pw5g->ofdm_diff[path][2] = 0xFE; + } else { + pw5g->ofdm_diff[path][1] = (hwinfo[addr] & 0xf0) >> 4; + pw5g->ofdm_diff[path][2] = (hwinfo[addr] & 0x0f); + } + addr++; + + if (hwinfo[addr] == 0xFF) + pw5g->ofdm_diff[path][3] = 0xFE; + else + pw5g->ofdm_diff[path][3] = (hwinfo[addr] & 0x0f); + addr++; + + for (cnt = 1; cnt < MAX_TX_COUNT; cnt++) { + if (pw5g->ofdm_diff[path][cnt] == 0xFF) + pw5g->ofdm_diff[path][cnt] = 0xFE; + else if (pw5g->ofdm_diff[path][cnt] & BIT(3)) + pw5g->ofdm_diff[path][cnt] |= 0xF0; + } + } +} + +static void _rtl8723be_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, + u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct txpower_info_2g pw2g; + struct txpower_info_5g pw5g; + u8 rf_path, index; + u8 i; + + _rtl8723be_read_power_value_fromprom(hw, &pw2g, &pw5g, autoload_fail, + hwinfo); + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < 14; i++) { + index = _rtl8723be_get_chnl_group(i+1); + + rtlefuse->txpwrlevel_cck[rf_path][i] = + pw2g.index_cck_base[rf_path][index]; + rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = + pw2g.index_bw40_base[rf_path][index]; + } + for (i = 0; i < MAX_TX_COUNT; i++) { + rtlefuse->txpwr_ht20diff[rf_path][i] = + pw2g.bw20_diff[rf_path][i]; + rtlefuse->txpwr_ht40diff[rf_path][i] = + pw2g.bw40_diff[rf_path][i]; + rtlefuse->txpwr_legacyhtdiff[rf_path][i] = + pw2g.ofdm_diff[rf_path][i]; + } + + for (i = 0; i < 14; i++) { + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "RF(%d)-Ch(%d) [CCK / HT40_1S ] = [0x%x / 0x%x ]\n", + rf_path, i, + rtlefuse->txpwrlevel_cck[rf_path][i], + rtlefuse->txpwrlevel_ht40_1s[rf_path][i]); + } + } + + if (!autoload_fail) + rtlefuse->eeprom_thermalmeter = + hwinfo[EEPROM_THERMAL_METER_88E]; + else + rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; + + if (rtlefuse->eeprom_thermalmeter == 0xff || autoload_fail) { + rtlefuse->apk_thermalmeterignore = true; + rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; + } + + rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); + + if (!autoload_fail) { + rtlefuse->eeprom_regulatory = + hwinfo[EEPROM_RF_BOARD_OPTION_88E] & 0x07;/*bit0~2*/ + if (hwinfo[EEPROM_RF_BOARD_OPTION_88E] == 0xFF) + rtlefuse->eeprom_regulatory = 0; + } else { + rtlefuse->eeprom_regulatory = 0; + } + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); +} + +static void _rtl8723be_read_adapter_info(struct ieee80211_hw *hw, + bool pseudo_test) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u16 i, usvalue; + u8 hwinfo[HWSET_MAX_SIZE]; + u16 eeprom_id; + bool is_toshiba_smid1 = false; + bool is_toshiba_smid2 = false; + bool is_samsung_smid = false; + bool is_lenovo_smid = false; + u16 toshiba_smid1[] = { + 0x6151, 0x6152, 0x6154, 0x6155, 0x6177, 0x6178, 0x6179, 0x6180, + 0x7151, 0x7152, 0x7154, 0x7155, 0x7177, 0x7178, 0x7179, 0x7180, + 0x8151, 0x8152, 0x8154, 0x8155, 0x8181, 0x8182, 0x8184, 0x8185, + 0x9151, 0x9152, 0x9154, 0x9155, 0x9181, 0x9182, 0x9184, 0x9185 + }; + u16 toshiba_smid2[] = { + 0x6181, 0x6184, 0x6185, 0x7181, 0x7182, 0x7184, 0x7185, 0x8181, + 0x8182, 0x8184, 0x8185, 0x9181, 0x9182, 0x9184, 0x9185 + }; + u16 samsung_smid[] = { + 0x6191, 0x6192, 0x6193, 0x7191, 0x7192, 0x7193, 0x8191, 0x8192, + 0x8193, 0x9191, 0x9192, 0x9193 + }; + u16 lenovo_smid[] = { + 0x8195, 0x9195, 0x7194, 0x8200, 0x8201, 0x8202, 0x9199, 0x9200 + }; + + if (pseudo_test) { + /* needs to be added */ + return; + } + if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + rtl_efuse_shadow_map_update(hw); + + memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + HWSET_MAX_SIZE); + } else if (rtlefuse->epromtype == EEPROM_93C46) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "RTL819X Not boot from eeprom, check it !!"); + } + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), + hwinfo, HWSET_MAX_SIZE); + + eeprom_id = *((u16 *)&hwinfo[0]); + if (eeprom_id != RTL8723BE_EEPROM_ID) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "EEPROM ID(%#x) is invalid!!\n", eeprom_id); + rtlefuse->autoload_failflag = true; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + } + + if (rtlefuse->autoload_failflag) + return; + + rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; + rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; + rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; + rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROMId = 0x%4x\n", eeprom_id); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); + + for (i = 0; i < 6; i += 2) { + usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; + *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "dev_addr: %pM\n", + rtlefuse->dev_addr); + + /*parse xtal*/ + rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_8723BE]; + if (rtlefuse->crystalcap == 0xFF) + rtlefuse->crystalcap = 0x20; + + _rtl8723be_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, + hwinfo); + + rtl8723be_read_bt_coexist_info_from_hwpg(hw, + rtlefuse->autoload_failflag, + hwinfo); + + rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; + rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; + rtlefuse->txpwr_fromeprom = true; + rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); + + /* set channel plan from efuse */ + rtlefuse->channel_plan = rtlefuse->eeprom_channelplan; + + if (rtlhal->oem_id == RT_CID_DEFAULT) { + /* Does this one have a Toshiba SMID from group 1? */ + for (i = 0; i < sizeof(toshiba_smid1) / sizeof(u16); i++) { + if (rtlefuse->eeprom_smid == toshiba_smid1[i]) { + is_toshiba_smid1 = true; + break; + } + } + /* Does this one have a Toshiba SMID from group 2? */ + for (i = 0; i < sizeof(toshiba_smid2) / sizeof(u16); i++) { + if (rtlefuse->eeprom_smid == toshiba_smid2[i]) { + is_toshiba_smid2 = true; + break; + } + } + /* Does this one have a Samsung SMID? */ + for (i = 0; i < sizeof(samsung_smid) / sizeof(u16); i++) { + if (rtlefuse->eeprom_smid == samsung_smid[i]) { + is_samsung_smid = true; + break; + } + } + /* Does this one have a Lenovo SMID? */ + for (i = 0; i < sizeof(lenovo_smid) / sizeof(u16); i++) { + if (rtlefuse->eeprom_smid == lenovo_smid[i]) { + is_lenovo_smid = true; + break; + } + } + switch (rtlefuse->eeprom_oemid) { + case EEPROM_CID_DEFAULT: + if (rtlefuse->eeprom_did == 0x8176) { + if (rtlefuse->eeprom_svid == 0x10EC && + is_toshiba_smid1) { + rtlhal->oem_id = RT_CID_TOSHIBA; + } else if (rtlefuse->eeprom_svid == 0x1025) { + rtlhal->oem_id = RT_CID_819X_ACER; + } else if (rtlefuse->eeprom_svid == 0x10EC && + is_samsung_smid) { + rtlhal->oem_id = RT_CID_819X_SAMSUNG; + } else if (rtlefuse->eeprom_svid == 0x10EC && + is_lenovo_smid) { + rtlhal->oem_id = RT_CID_819X_LENOVO; + } else if ((rtlefuse->eeprom_svid == 0x10EC && + rtlefuse->eeprom_smid == 0x8197) || + (rtlefuse->eeprom_svid == 0x10EC && + rtlefuse->eeprom_smid == 0x9196)) { + rtlhal->oem_id = RT_CID_819X_CLEVO; + } else if ((rtlefuse->eeprom_svid == 0x1028 && + rtlefuse->eeprom_smid == 0x8194) || + (rtlefuse->eeprom_svid == 0x1028 && + rtlefuse->eeprom_smid == 0x8198) || + (rtlefuse->eeprom_svid == 0x1028 && + rtlefuse->eeprom_smid == 0x9197) || + (rtlefuse->eeprom_svid == 0x1028 && + rtlefuse->eeprom_smid == 0x9198)) { + rtlhal->oem_id = RT_CID_819X_DELL; + } else if ((rtlefuse->eeprom_svid == 0x103C && + rtlefuse->eeprom_smid == 0x1629)) { + rtlhal->oem_id = RT_CID_819X_HP; + } else if ((rtlefuse->eeprom_svid == 0x1A32 && + rtlefuse->eeprom_smid == 0x2315)) { + rtlhal->oem_id = RT_CID_819X_QMI; + } else if ((rtlefuse->eeprom_svid == 0x10EC && + rtlefuse->eeprom_smid == 0x8203)) { + rtlhal->oem_id = RT_CID_819X_PRONETS; + } else if ((rtlefuse->eeprom_svid == 0x1043 && + rtlefuse->eeprom_smid == 0x84B5)) { + rtlhal->oem_id = RT_CID_819X_EDIMAX_ASUS; + } else { + rtlhal->oem_id = RT_CID_DEFAULT; + } + } else if (rtlefuse->eeprom_did == 0x8178) { + if (rtlefuse->eeprom_svid == 0x10EC && + is_toshiba_smid2) + rtlhal->oem_id = RT_CID_TOSHIBA; + else if (rtlefuse->eeprom_svid == 0x1025) + rtlhal->oem_id = RT_CID_819X_ACER; + else if ((rtlefuse->eeprom_svid == 0x10EC && + rtlefuse->eeprom_smid == 0x8186)) + rtlhal->oem_id = RT_CID_819X_PRONETS; + else if ((rtlefuse->eeprom_svid == 0x1043 && + rtlefuse->eeprom_smid == 0x84B6)) + rtlhal->oem_id = + RT_CID_819X_EDIMAX_ASUS; + else + rtlhal->oem_id = RT_CID_DEFAULT; + } else { + rtlhal->oem_id = RT_CID_DEFAULT; + } + break; + case EEPROM_CID_TOSHIBA: + rtlhal->oem_id = RT_CID_TOSHIBA; + break; + case EEPROM_CID_CCX: + rtlhal->oem_id = RT_CID_CCX; + break; + case EEPROM_CID_QMI: + rtlhal->oem_id = RT_CID_819X_QMI; + break; + case EEPROM_CID_WHQL: + break; + default: + rtlhal->oem_id = RT_CID_DEFAULT; + break; + } + } +} + +static void _rtl8723be_hal_customized_behavior(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + pcipriv->ledctl.led_opendrain = true; + switch (rtlhal->oem_id) { + case RT_CID_819X_HP: + pcipriv->ledctl.led_opendrain = true; + break; + case RT_CID_819X_LENOVO: + case RT_CID_DEFAULT: + case RT_CID_TOSHIBA: + case RT_CID_CCX: + case RT_CID_819X_ACER: + case RT_CID_WHQL: + default: + break; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "RT Customized ID: 0x%02X\n", rtlhal->oem_id); +} + +void rtl8723be_read_eeprom_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_u1b; + + rtlhal->version = _rtl8723be_read_chip_version(hw); + if (get_rf_type(rtlphy) == RF_1T1R) + rtlpriv->dm.rfpath_rxenable[0] = true; + else + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", + rtlhal->version); + tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); + if (tmp_u1b & BIT(4)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); + rtlefuse->epromtype = EEPROM_93C46; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); + rtlefuse->epromtype = EEPROM_BOOT_EFUSE; + } + if (tmp_u1b & BIT(5)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + _rtl8723be_read_adapter_info(hw, false); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); + } + _rtl8723be_hal_customized_behavior(hw); +} + +static u8 _rtl8723be_mrate_idx_to_arfr_id(struct ieee80211_hw *hw, + u8 rate_index) +{ + u8 ret = 0; + switch (rate_index) { + case RATR_INX_WIRELESS_NGB: + ret = 1; + break; + case RATR_INX_WIRELESS_N: + case RATR_INX_WIRELESS_NG: + ret = 5; + break; + case RATR_INX_WIRELESS_NB: + ret = 3; + break; + case RATR_INX_WIRELESS_GB: + ret = 6; + break; + case RATR_INX_WIRELESS_G: + ret = 7; + break; + case RATR_INX_WIRELESS_B: + ret = 8; + break; + default: + ret = 0; + break; + } + return ret; +} + +static void rtl8723be_update_hal_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u32 ratr_bitmap; + u8 ratr_index; + u8 curtxbw_40mhz = (sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0; + u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = 0; + bool shortgi = false; + u8 rate_mask[7]; + u8 macid = 0; + + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + wirelessmode = sta_entry->wireless_mode; + if (mac->opmode == NL80211_IFTYPE_STATION || + mac->opmode == NL80211_IFTYPE_MESH_POINT) + curtxbw_40mhz = mac->bw_40; + else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + macid = sta->aid + 1; + + ratr_bitmap = sta->supp_rates[0]; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_bitmap = 0xfff; + + ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + ratr_index = RATR_INX_WIRELESS_B; + if (ratr_bitmap & 0x0000000c) + ratr_bitmap &= 0x0000000d; + else + ratr_bitmap &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_index = RATR_INX_WIRELESS_GB; + + if (rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if (rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + ratr_index = RATR_INX_WIRELESS_NGB; + if (rtlphy->rf_type == RF_1T1R) { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff005; + } + } else { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x0f8f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f8ff000; + else + ratr_bitmap &= 0x0f8ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x0f8f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0f8ff000; + else + ratr_bitmap &= 0x0f8ff005; + } + } + if ((curtxbw_40mhz && curshortgi_40mhz) || + (!curtxbw_40mhz && curshortgi_20mhz)) { + if (macid == 0) + shortgi = true; + else if (macid == 1) + shortgi = false; + } + break; + default: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rtlphy->rf_type == RF_1T2R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0f0ff0ff; + break; + } + + sta_entry->ratr_index = ratr_index; + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "ratr_bitmap :%x\n", ratr_bitmap); + *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | + (ratr_index << 28); + rate_mask[0] = macid; + rate_mask[1] = _rtl8723be_mrate_idx_to_arfr_id(hw, ratr_index) | + (shortgi ? 0x80 : 0x00); + rate_mask[2] = curtxbw_40mhz; + + rate_mask[3] = (u8)(ratr_bitmap & 0x000000ff); + rate_mask[4] = (u8)((ratr_bitmap & 0x0000ff00) >> 8); + rate_mask[5] = (u8)((ratr_bitmap & 0x00ff0000) >> 16); + rate_mask[6] = (u8)((ratr_bitmap & 0xff000000) >> 24); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x:%x:%x\n", + ratr_index, ratr_bitmap, + rate_mask[0], rate_mask[1], + rate_mask[2], rate_mask[3], + rate_mask[4], rate_mask[5], + rate_mask[6]); + rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RA_MASK, 7, rate_mask); + _rtl8723be_set_bcn_ctrl_reg(hw, BIT(3), 0); +} + +void rtl8723be_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (rtlpriv->dm.useramask) + rtl8723be_update_hal_rate_mask(hw, sta, rssi_level); +} + +void rtl8723be_update_channel_access_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 sifs_timer; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, &mac->slot_time); + if (!mac->ht_enable) + sifs_timer = 0x0a0a; + else + sifs_timer = 0x0e0e; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); +} + +bool rtl8723be_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; + u8 u1tmp; + bool b_actuallyset = false; + + if (rtlpriv->rtlhal.being_init_adapter) + return false; + + if (ppsc->swrf_processing) + return false; + + spin_lock(&rtlpriv->locks.rf_ps_lock); + if (ppsc->rfchange_inprogress) { + spin_unlock(&rtlpriv->locks.rf_ps_lock); + return false; + } else { + ppsc->rfchange_inprogress = true; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } + + cur_rfstate = ppsc->rfpwr_state; + + rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL_2, + rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL_2) & ~(BIT(1))); + + u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL_2); + + if (rtlphy->polarity_ctl) + e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFOFF : ERFON; + else + e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFON : ERFOFF; + + if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "GPIOChangeRF - HW Radio ON, RF ON\n"); + + e_rfpowerstate_toset = ERFON; + ppsc->hwradiooff = false; + b_actuallyset = true; + } else if (!ppsc->hwradiooff && (e_rfpowerstate_toset == ERFOFF)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "GPIOChangeRF - HW Radio OFF, RF OFF\n"); + + e_rfpowerstate_toset = ERFOFF; + ppsc->hwradiooff = true; + b_actuallyset = true; + } + + if (b_actuallyset) { + spin_lock(&rtlpriv->locks.rf_ps_lock); + ppsc->rfchange_inprogress = false; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } else { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + + spin_lock(&rtlpriv->locks.rf_ps_lock); + ppsc->rfchange_inprogress = false; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } + + *valid = 1; + return !ppsc->hwradiooff; + +} + +void rtl8723be_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 *macaddr = p_macaddr; + u32 entry_id = 0; + bool is_pairwise = false; + + static u8 cam_const_addr[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} + }; + static u8 cam_const_broad[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (clear_all) { + u8 idx = 0; + u8 cam_offset = 0; + u8 clear_number = 5; + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); + + for (idx = 0; idx < clear_number; idx++) { + rtl_cam_mark_invalid(hw, cam_offset + idx); + rtl_cam_empty_entry(hw, cam_offset + idx); + + if (idx < 5) { + memset(rtlpriv->sec.key_buf[idx], 0, + MAX_KEY_LEN); + rtlpriv->sec.key_len[idx] = 0; + } + } + + } else { + switch (enc_algo) { + case WEP40_ENCRYPTION: + enc_algo = CAM_WEP40; + break; + case WEP104_ENCRYPTION: + enc_algo = CAM_WEP104; + break; + case TKIP_ENCRYPTION: + enc_algo = CAM_TKIP; + break; + case AESCCMP_ENCRYPTION: + enc_algo = CAM_AES; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + enc_algo = CAM_TKIP; + break; + } + + if (is_wepkey || rtlpriv->sec.use_defaultkey) { + macaddr = cam_const_addr[key_index]; + entry_id = key_index; + } else { + if (is_group) { + macaddr = cam_const_broad; + entry_id = key_index; + } else { + if (mac->opmode == NL80211_IFTYPE_AP) { + entry_id = rtl_cam_get_free_entry(hw, + p_macaddr); + if (entry_id >= TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, COMP_SEC, + DBG_EMERG, + "Can not find free hw security cam entry\n"); + return; + } + } else { + entry_id = CAM_PAIRWISE_KEY_POSITION; + } + + key_index = PAIRWISE_KEYIDX; + is_pairwise = true; + } + } + + if (rtlpriv->sec.key_len[key_index] == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "delete one entry, entry_id is %d\n", + entry_id); + if (mac->opmode == NL80211_IFTYPE_AP) + rtl_cam_del_entry(hw, p_macaddr); + rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "add one entry\n"); + if (is_pairwise) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set Pairwiase key\n"); + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[key_index]); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set group key\n"); + + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_cam_add_one_entry(hw, + rtlefuse->dev_addr, + PAIRWISE_KEYIDX, + CAM_PAIRWISE_KEY_POSITION, + enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf + [entry_id]); + } + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + } + } +} + +void rtl8723be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool auto_load_fail, u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 value; + u32 tmpu_32; + + if (!auto_load_fail) { + tmpu_32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL); + if (tmpu_32 & BIT(18)) + rtlpriv->btcoexist.btc_info.btcoexist = 1; + else + rtlpriv->btcoexist.btc_info.btcoexist = 0; + value = hwinfo[EEPROM_RF_BT_SETTING_8723B]; + rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8723B; + rtlpriv->btcoexist.btc_info.ant_num = (value & 0x1); + } else { + rtlpriv->btcoexist.btc_info.btcoexist = 0; + rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8723B; + rtlpriv->btcoexist.btc_info.ant_num = ANT_X2; + } + +} + +void rtl8723be_bt_reg_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* 0:Low, 1:High, 2:From Efuse. */ + rtlpriv->btcoexist.reg_bt_iso = 2; + /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ + rtlpriv->btcoexist.reg_bt_sco = 3; + /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ + rtlpriv->btcoexist.reg_bt_sco = 0; +} + +void rtl8723be_bt_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_init_hw_config(rtlpriv); + +} + +void rtl8723be_suspend(struct ieee80211_hw *hw) +{ +} + +void rtl8723be_resume(struct ieee80211_hw *hw) +{ +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h new file mode 100644 index 000000000000..eae863d08de8 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723BE_HW_H__ +#define __RTL8723BE_HW_H__ + +void rtl8723be_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl8723be_read_eeprom_info(struct ieee80211_hw *hw); + +void rtl8723be_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb); +int rtl8723be_hw_init(struct ieee80211_hw *hw); +void rtl8723be_card_disable(struct ieee80211_hw *hw); +void rtl8723be_enable_interrupt(struct ieee80211_hw *hw); +void rtl8723be_disable_interrupt(struct ieee80211_hw *hw); +int rtl8723be_set_network_type(struct ieee80211_hw *hw, + enum nl80211_iftype type); +void rtl8723be_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); +void rtl8723be_set_qos(struct ieee80211_hw *hw, int aci); +void rtl8723be_set_beacon_related_registers(struct ieee80211_hw *hw); +void rtl8723be_set_beacon_interval(struct ieee80211_hw *hw); +void rtl8723be_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); +void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl8723be_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level); +void rtl8723be_update_channel_access_setting(struct ieee80211_hw *hw); +bool rtl8723be_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); +void rtl8723be_enable_hw_security_config(struct ieee80211_hw *hw); +void rtl8723be_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all); +void rtl8723be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, u8 *hwinfo); +void rtl8723be_bt_reg_init(struct ieee80211_hw *hw); +void rtl8723be_bt_hw_init(struct ieee80211_hw *hw); +void rtl8723be_suspend(struct ieee80211_hw *hw); +void rtl8723be_resume(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c new file mode 100644 index 000000000000..4196efb723a2 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.c @@ -0,0 +1,153 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "reg.h" +#include "led.h" + +static void _rtl8723be_init_led(struct ieee80211_hw *hw, struct rtl_led *pled, + enum rtl_led_pin ledpin) +{ + pled->hw = hw; + pled->ledpin = ledpin; + pled->ledon = false; +} + +void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u8 ledcfg; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + ledcfg &= ~BIT(6); + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5)); + break; + case LED_PIN_LED1: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); + rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + pled->ledon = true; +} + +void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + u8 ledcfg; + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg &= 0xf0; + if (pcipriv->ledctl.led_opendrain) { + ledcfg &= 0x90; /* Set to software control. */ + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3))); + ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); + ledcfg &= 0xFE; + rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg); + } else { + ledcfg &= ~BIT(6); + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(3) | BIT(5))); + } + break; + case LED_PIN_LED1: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); + ledcfg &= 0x10; /* Set to software control. */ + rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg|BIT(3)); + + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + pled->ledon = false; +} + +void rtl8723be_init_sw_leds(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + _rtl8723be_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); + _rtl8723be_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); +} + +static void _rtl8723be_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pled0 = &(pcipriv->ledctl.sw_led0); + switch (ledaction) { + case LED_CTL_POWER_ON: + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + rtl8723be_sw_led_on(hw, pled0); + break; + case LED_CTL_POWER_OFF: + rtl8723be_sw_led_off(hw, pled0); + break; + default: + break; + } +} + +void rtl8723be_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && + (ledaction == LED_CTL_TX || + ledaction == LED_CTL_RX || + ledaction == LED_CTL_SITE_SURVEY || + ledaction == LED_CTL_LINK || + ledaction == LED_CTL_NO_LINK || + ledaction == LED_CTL_START_TO_LINK || + ledaction == LED_CTL_POWER_ON)) { + return; + } + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n", ledaction); + _rtl8723be_sw_led_control(hw, ledaction); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h new file mode 100644 index 000000000000..c57de379ee8d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/led.h @@ -0,0 +1,35 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723BE_LED_H__ +#define __RTL8723BE_LED_H__ + +void rtl8723be_init_sw_leds(struct ieee80211_hw *hw); +void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl8723be_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c new file mode 100644 index 000000000000..b7b73cbe346d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c @@ -0,0 +1,2730 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../ps.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "../rtl8723com/phy_common.h" +#include "rf.h" +#include "dm.h" +#include "../rtl8723com/dm_common.h" +#include "table.h" +#include "trx.h" + +static bool _rtl8723be_phy_bb8723b_config_parafile(struct ieee80211_hw *hw); +static bool _rtl8723be_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); +static bool _rtl8723be_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +static bool _rtl8723be_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype); +static bool _rtl8723be_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, + u8 *step, u32 *delay); + +static void rtl8723be_phy_set_rf_on(struct ieee80211_hw *hw); +static void rtl8723be_phy_set_io(struct ieee80211_hw *hw); + +u32 rtl8723be_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, readback_value, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", + regaddr, rfpath, bitmask); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + original_value = rtl8723_phy_rf_serial_read(hw, rfpath, regaddr); + bitshift = rtl8723_phy_calculate_bit_shift(bitmask); + readback_value = (original_value & bitmask) >> bitshift; + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", + regaddr, rfpath, bitmask, original_value); + + return readback_value; +} + +void rtl8723be_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path path, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, path); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + if (bitmask != RFREG_OFFSET_MASK) { + original_value = rtl8723_phy_rf_serial_read(hw, path, + regaddr); + bitshift = rtl8723_phy_calculate_bit_shift(bitmask); + data = ((original_value & (~bitmask)) | + (data << bitshift)); + } + + rtl8723_phy_rf_serial_write(hw, path, regaddr, data); + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, path); + +} + +bool rtl8723be_phy_mac_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool rtstatus = _rtl8723be_phy_config_mac_with_headerfile(hw); + + rtl_write_byte(rtlpriv, 0x04CA, 0x0B); + return rtstatus; +} + +bool rtl8723be_phy_bb_config(struct ieee80211_hw *hw) +{ + bool rtstatus = true; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 regval; + u8 b_reg_hwparafile = 1; + u32 tmp; + u8 crystalcap = rtlpriv->efuse.crystalcap; + rtl8723_phy_init_bb_rf_reg_def(hw); + regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, + regval | BIT(13) | BIT(0) | BIT(1)); + + rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, + FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | + FEN_BB_GLB_RSTN | FEN_BBRSTB); + tmp = rtl_read_dword(rtlpriv, 0x4c); + rtl_write_dword(rtlpriv, 0x4c, tmp | BIT(23)); + + rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); + + if (b_reg_hwparafile == 1) + rtstatus = _rtl8723be_phy_bb8723b_config_parafile(hw); + + crystalcap = crystalcap & 0x3F; + rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, + (crystalcap | crystalcap << 6)); + + return rtstatus; +} + +bool rtl8723be_phy_rf_config(struct ieee80211_hw *hw) +{ + return rtl8723be_phy_rf6052_config(hw); +} + +static bool _rtl8723be_check_condition(struct ieee80211_hw *hw, + const u32 condition) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 _board = rtlefuse->board_type; /*need efuse define*/ + u32 _interface = rtlhal->interface; + u32 _platform = 0x08;/*SupportPlatform */ + u32 cond = condition; + + if (condition == 0xCDCDCDCD) + return true; + + cond = condition & 0xFF; + if ((_board & cond) == 0 && cond != 0x1F) + return false; + + cond = condition & 0xFF00; + cond = cond >> 8; + if ((_interface & cond) == 0 && cond != 0x07) + return false; + + cond = condition & 0xFF0000; + cond = cond >> 16; + if ((_platform & cond) == 0 && cond != 0x0F) + return false; + return true; +} + +static void _rtl8723be_config_rf_reg(struct ieee80211_hw *hw, u32 addr, + u32 data, enum radio_path rfpath, + u32 regaddr) +{ + if (addr == 0xfe || addr == 0xffe) { + /* In order not to disturb BT music + * when wifi init.(1ant NIC only) + */ + mdelay(50); + } else { + rtl_set_rfreg(hw, rfpath, regaddr, RFREG_OFFSET_MASK, data); + udelay(1); + } +} +static void _rtl8723be_config_rf_radio_a(struct ieee80211_hw *hw, + u32 addr, u32 data) +{ + u32 content = 0x1000; /*RF Content: radio_a_txt*/ + u32 maskforphyset = (u32)(content & 0xE000); + + _rtl8723be_config_rf_reg(hw, addr, data, RF90_PATH_A, + addr | maskforphyset); + +} + +static void _rtl8723be_phy_init_tx_power_by_rate(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + u8 band, path, txnum, section; + + for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band) + for (path = 0; path < TX_PWR_BY_RATE_NUM_RF; ++path) + for (txnum = 0; txnum < TX_PWR_BY_RATE_NUM_RF; ++txnum) + for (section = 0; + section < TX_PWR_BY_RATE_NUM_SECTION; + ++section) + rtlphy->tx_power_by_rate_offset + [band][path][txnum][section] = 0; +} + +static void _rtl8723be_config_bb_reg(struct ieee80211_hw *hw, + u32 addr, u32 data) +{ + if (addr == 0xfe) { + mdelay(50); + } else if (addr == 0xfd) { + mdelay(5); + } else if (addr == 0xfc) { + mdelay(1); + } else if (addr == 0xfb) { + udelay(50); + } else if (addr == 0xfa) { + udelay(5); + } else if (addr == 0xf9) { + udelay(1); + } else { + rtl_set_bbreg(hw, addr, MASKDWORD, data); + udelay(1); + } +} + +static void _rtl8723be_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw, + u8 band, + u8 path, u8 rate_section, + u8 txnum, u8 value) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + if (path > RF90_PATH_D) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid Rf Path %d in phy_SetTxPowerByRatBase()\n", + path); + return; + } + + if (band == BAND_ON_2_4G) { + switch (rate_section) { + case CCK: + rtlphy->txpwr_by_rate_base_24g[path][txnum][0] = value; + break; + case OFDM: + rtlphy->txpwr_by_rate_base_24g[path][txnum][1] = value; + break; + case HT_MCS0_MCS7: + rtlphy->txpwr_by_rate_base_24g[path][txnum][2] = value; + break; + case HT_MCS8_MCS15: + rtlphy->txpwr_by_rate_base_24g[path][txnum][3] = value; + break; + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", + rate_section, path, txnum); + break; + }; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid Band %d in PHY_SetTxPowerByRateBase()\n", + band); + } + +} + +static u8 _rtl8723be_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw, + u8 band, u8 path, u8 txnum, + u8 rate_section) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 value = 0; + if (path > RF90_PATH_D) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid Rf Path %d in PHY_GetTxPowerByRateBase()\n", + path); + return 0; + } + + if (band == BAND_ON_2_4G) { + switch (rate_section) { + case CCK: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][0]; + break; + case OFDM: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][1]; + break; + case HT_MCS0_MCS7: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][2]; + break; + case HT_MCS8_MCS15: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][3]; + break; + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", + rate_section, path, txnum); + break; + }; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid Band %d in PHY_GetTxPowerByRateBase()\n", + band); + } + + return value; +} + +static void _rtl8723be_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u16 rawvalue = 0; + u8 base = 0, path = 0; + + for (path = RF90_PATH_A; path <= RF90_PATH_B; ++path) { + if (path == RF90_PATH_A) { + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset + [BAND_ON_2_4G][path][RF_1TX][3] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); + _rtl8723be_phy_set_txpower_by_rate_base(hw, + BAND_ON_2_4G, path, CCK, RF_1TX, base); + } else if (path == RF90_PATH_B) { + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset + [BAND_ON_2_4G][path][RF_1TX][3] >> 0) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); + _rtl8723be_phy_set_txpower_by_rate_base(hw, + BAND_ON_2_4G, + path, CCK, + RF_1TX, base); + } + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset + [BAND_ON_2_4G][path][RF_1TX][1] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); + _rtl8723be_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, + path, OFDM, RF_1TX, + base); + + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset + [BAND_ON_2_4G][path][RF_1TX][5] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); + _rtl8723be_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, + path, HT_MCS0_MCS7, + RF_1TX, base); + + rawvalue = (u16)(rtlphy->tx_power_by_rate_offset + [BAND_ON_2_4G][path][RF_2TX][7] >> 24) & 0xFF; + base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); + _rtl8723be_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, + path, HT_MCS8_MCS15, + RF_2TX, base); + } +} + +static void _phy_convert_txpower_dbm_to_relative_value(u32 *data, u8 start, + u8 end, u8 base_val) +{ + char i = 0; + u8 temp_value = 0; + u32 temp_data = 0; + + for (i = 3; i >= 0; --i) { + if (i >= start && i <= end) { + /* Get the exact value */ + temp_value = (u8)(*data >> (i * 8)) & 0xF; + temp_value += ((u8)((*data >> (i*8 + 4)) & 0xF)) * 10; + + /* Change the value to a relative value */ + temp_value = (temp_value > base_val) ? + temp_value - base_val : + base_val - temp_value; + } else { + temp_value = (u8)(*data >> (i * 8)) & 0xFF; + } + temp_data <<= 8; + temp_data |= temp_value; + } + *data = temp_data; +} + +static void _rtl8723be_phy_convert_txpower_dbm_to_relative_value( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 base = 0, rfpath = RF90_PATH_A; + + base = _rtl8723be_phy_get_txpower_by_rate_base(hw, + BAND_ON_2_4G, rfpath, RF_1TX, CCK); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][2], + 1, 1, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][3], + 1, 3, base); + + base = _rtl8723be_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, + RF_1TX, OFDM); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][0], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][1], + 0, 3, base); + + base = _rtl8723be_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, + rfpath, RF_1TX, HT_MCS0_MCS7); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][4], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][5], + 0, 3, base); + + base = _rtl8723be_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, + rfpath, RF_2TX, + HT_MCS8_MCS15); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][6], + 0, 3, base); + + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][7], + 0, 3, base); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "<===_rtl8723be_phy_convert_txpower_dbm_to_relative_value()\n"); +} + +static void phy_txpower_by_rate_config(struct ieee80211_hw *hw) +{ + _rtl8723be_phy_store_txpower_by_rate_base(hw); + _rtl8723be_phy_convert_txpower_dbm_to_relative_value(hw); +} + +static bool _rtl8723be_phy_bb8723b_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + bool rtstatus; + + rtstatus = _rtl8723be_phy_config_bb_with_headerfile(hw, + BASEBAND_CONFIG_PHY_REG); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); + return false; + } + _rtl8723be_phy_init_tx_power_by_rate(hw); + if (!rtlefuse->autoload_failflag) { + rtlphy->pwrgroup_cnt = 0; + rtstatus = _rtl8723be_phy_config_bb_with_pgheaderfile(hw, + BASEBAND_CONFIG_PHY_REG); + } + phy_txpower_by_rate_config(hw); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); + return false; + } + rtstatus = _rtl8723be_phy_config_bb_with_headerfile(hw, + BASEBAND_CONFIG_AGC_TAB); + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); + return false; + } + rtlphy->cck_high_power = (bool)(rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, + 0x200)); + return true; +} + +static bool _rtl8723be_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + u32 arraylength; + u32 *ptrarray; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read rtl8723beMACPHY_Array\n"); + arraylength = RTL8723BEMAC_1T_ARRAYLEN; + ptrarray = RTL8723BEMAC_1T_ARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Img:RTL8723bEMAC_1T_ARRAY LEN %d\n", arraylength); + for (i = 0; i < arraylength; i = i + 2) + rtl_write_byte(rtlpriv, ptrarray[i], (u8)ptrarray[i + 1]); + return true; +} + +static bool _rtl8723be_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype) +{ + #define READ_NEXT_PAIR(v1, v2, i) \ + do { \ + i += 2; \ + v1 = array_table[i];\ + v2 = array_table[i+1]; \ + } while (0) + + int i; + u32 *array_table; + u16 arraylen; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 v1 = 0, v2 = 0; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + arraylen = RTL8723BEPHY_REG_1TARRAYLEN; + array_table = RTL8723BEPHY_REG_1TARRAY; + + for (i = 0; i < arraylen; i = i + 2) { + v1 = array_table[i]; + v2 = array_table[i+1]; + if (v1 < 0xcdcdcdcd) { + _rtl8723be_config_bb_reg(hw, v1, v2); + } else {/*This line is the start line of branch.*/ + /* to protect READ_NEXT_PAIR not overrun */ + if (i >= arraylen - 2) + break; + + if (!_rtl8723be_check_condition(hw, + array_table[i])) { + /*Discard the following + *(offset, data) pairs + */ + READ_NEXT_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < arraylen - 2) { + READ_NEXT_PAIR(v1, v2, i); + } + i -= 2; /* prevent from for-loop += 2*/ + /*Configure matched pairs and + *skip to end of if-else. + */ + } else { + READ_NEXT_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < arraylen - 2) { + _rtl8723be_config_bb_reg(hw, + v1, v2); + READ_NEXT_PAIR(v1, v2, i); + } + + while (v2 != 0xDEAD && i < arraylen - 2) + READ_NEXT_PAIR(v1, v2, i); + } + } + } + } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { + arraylen = RTL8723BEAGCTAB_1TARRAYLEN; + array_table = RTL8723BEAGCTAB_1TARRAY; + + for (i = 0; i < arraylen; i = i + 2) { + v1 = array_table[i]; + v2 = array_table[i+1]; + if (v1 < 0xCDCDCDCD) { + rtl_set_bbreg(hw, array_table[i], + MASKDWORD, + array_table[i + 1]); + udelay(1); + continue; + } else {/*This line is the start line of branch.*/ + /* to protect READ_NEXT_PAIR not overrun */ + if (i >= arraylen - 2) + break; + + if (!_rtl8723be_check_condition(hw, + array_table[i])) { + /*Discard the following + *(offset, data) pairs + */ + READ_NEXT_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < arraylen - 2) { + READ_NEXT_PAIR(v1, v2, i); + } + i -= 2; /* prevent from for-loop += 2*/ + /*Configure matched pairs and + *skip to end of if-else. + */ + } else { + READ_NEXT_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < arraylen - 2) { + rtl_set_bbreg(hw, array_table[i], + MASKDWORD, + array_table[i + 1]); + udelay(1); + READ_NEXT_PAIR(v1, v2, i); + } + + while (v2 != 0xDEAD && i < arraylen - 2) + READ_NEXT_PAIR(v1, v2, i); + } + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The agctab_array_table[0] is %x Rtl818EEPHY_REGArray[1] is %x\n", + array_table[i], array_table[i + 1]); + } + } + return true; +} + +static u8 _rtl8723be_get_rate_section_index(u32 regaddr) +{ + u8 index = 0; + + switch (regaddr) { + case RTXAGC_A_RATE18_06: + index = 0; + break; + case RTXAGC_A_RATE54_24: + index = 1; + break; + case RTXAGC_A_CCK1_MCS32: + index = 2; + break; + case RTXAGC_B_CCK11_A_CCK2_11: + index = 3; + break; + case RTXAGC_A_MCS03_MCS00: + index = 4; + break; + case RTXAGC_A_MCS07_MCS04: + index = 5; + break; + case RTXAGC_A_MCS11_MCS08: + index = 6; + break; + case RTXAGC_A_MCS15_MCS12: + index = 7; + break; + case RTXAGC_B_RATE18_06: + index = 0; + break; + case RTXAGC_B_RATE54_24: + index = 1; + break; + case RTXAGC_B_CCK1_55_MCS32: + index = 2; + break; + case RTXAGC_B_MCS03_MCS00: + index = 4; + break; + case RTXAGC_B_MCS07_MCS04: + index = 5; + break; + case RTXAGC_B_MCS11_MCS08: + index = 6; + break; + case RTXAGC_B_MCS15_MCS12: + index = 7; + break; + default: + regaddr &= 0xFFF; + if (regaddr >= 0xC20 && regaddr <= 0xC4C) + index = (u8)((regaddr - 0xC20) / 4); + else if (regaddr >= 0xE20 && regaddr <= 0xE4C) + index = (u8)((regaddr - 0xE20) / 4); + break; + }; + return index; +} + +static void _rtl8723be_store_tx_power_by_rate(struct ieee80211_hw *hw, + u32 band, u32 rfpath, + u32 txnum, u32 regaddr, + u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 rate_section = _rtl8723be_get_rate_section_index(regaddr); + + if (band != BAND_ON_2_4G && band != BAND_ON_5G) { + RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, "Invalid Band %d\n", band); + return; + } + if (rfpath > MAX_RF_PATH - 1) { + RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, + "Invalid RfPath %d\n", rfpath); + return; + } + if (txnum > MAX_RF_PATH - 1) { + RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, "Invalid TxNum %d\n", txnum); + return; + } + + rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = + data; + +} + +static bool _rtl8723be_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int i; + u32 *phy_regarray_table_pg; + u16 phy_regarray_pg_len; + u32 v1 = 0, v2 = 0, v3 = 0, v4 = 0, v5 = 0, v6 = 0; + + phy_regarray_pg_len = RTL8723BEPHY_REG_ARRAY_PGLEN; + phy_regarray_table_pg = RTL8723BEPHY_REG_ARRAY_PG; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + for (i = 0; i < phy_regarray_pg_len; i = i + 6) { + v1 = phy_regarray_table_pg[i]; + v2 = phy_regarray_table_pg[i+1]; + v3 = phy_regarray_table_pg[i+2]; + v4 = phy_regarray_table_pg[i+3]; + v5 = phy_regarray_table_pg[i+4]; + v6 = phy_regarray_table_pg[i+5]; + + if (v1 < 0xcdcdcdcd) { + if (phy_regarray_table_pg[i] == 0xfe || + phy_regarray_table_pg[i] == 0xffe) + mdelay(50); + else + _rtl8723be_store_tx_power_by_rate(hw, + v1, v2, v3, v4, v5, v6); + continue; + } + } + } else { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "configtype != BaseBand_Config_PHY_REG\n"); + } + return true; +} + +bool rtl8723be_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath) +{ + #define READ_NEXT_RF_PAIR(v1, v2, i) \ + do { \ + i += 2; \ + v1 = radioa_array_table[i]; \ + v2 = radioa_array_table[i+1]; \ + } while (0) + + int i; + bool rtstatus = true; + u32 *radioa_array_table; + u16 radioa_arraylen; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 v1 = 0, v2 = 0; + + radioa_arraylen = RTL8723BE_RADIOA_1TARRAYLEN; + radioa_array_table = RTL8723BE_RADIOA_1TARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Radio_A:RTL8723BE_RADIOA_1TARRAY %d\n", radioa_arraylen); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); + rtstatus = true; + switch (rfpath) { + case RF90_PATH_A: + for (i = 0; i < radioa_arraylen; i = i + 2) { + v1 = radioa_array_table[i]; + v2 = radioa_array_table[i+1]; + if (v1 < 0xcdcdcdcd) { + _rtl8723be_config_rf_radio_a(hw, v1, v2); + } else {/*This line is the start line of branch.*/ + /* to protect READ_NEXT_PAIR not overrun */ + if (i >= radioa_arraylen - 2) + break; + + if (!_rtl8723be_check_condition(hw, + radioa_array_table[i])) { + /*Discard the following + *(offset, data) pairs + */ + READ_NEXT_RF_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < radioa_arraylen - 2) { + READ_NEXT_RF_PAIR(v1, v2, i); + } + i -= 2; /* prevent from for-loop += 2*/ + } else { + /*Configure matched pairs + *and skip to end of if-else. + */ + READ_NEXT_RF_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < radioa_arraylen - 2) { + _rtl8723be_config_rf_radio_a(hw, + v1, v2); + READ_NEXT_RF_PAIR(v1, v2, i); + } + + while (v2 != 0xDEAD && + i < radioa_arraylen - 2) { + READ_NEXT_RF_PAIR(v1, v2, i); + } + } + } + } + + if (rtlhal->oem_id == RT_CID_819X_HP) + _rtl8723be_config_rf_radio_a(hw, 0x52, 0x7E4BD); + break; + case RF90_PATH_B: + case RF90_PATH_C: + break; + case RF90_PATH_D: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + return true; +} + +void rtl8723be_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + rtlphy->default_initialgain[0] = + (u8)rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[1] = + (u8)rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[2] = + (u8)rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[3] = + (u8)rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", + rtlphy->default_initialgain[0], + rtlphy->default_initialgain[1], + rtlphy->default_initialgain[2], + rtlphy->default_initialgain[3]); + + rtlphy->framesync = (u8)rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, + MASKBYTE0); + rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, + MASKDWORD); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default framesync (0x%x) = 0x%x\n", + ROFDM0_RXDETECTOR3, rtlphy->framesync); +} + +static u8 _rtl8723be_phy_get_ratesection_intxpower_byrate(enum radio_path path, + u8 rate) +{ + u8 rate_section = 0; + + switch (rate) { + case DESC92C_RATE1M: + rate_section = 2; + break; + + case DESC92C_RATE2M: + case DESC92C_RATE5_5M: + if (path == RF90_PATH_A) + rate_section = 3; + else if (path == RF90_PATH_B) + rate_section = 2; + break; + + case DESC92C_RATE11M: + rate_section = 3; + break; + + case DESC92C_RATE6M: + case DESC92C_RATE9M: + case DESC92C_RATE12M: + case DESC92C_RATE18M: + rate_section = 0; + break; + + case DESC92C_RATE24M: + case DESC92C_RATE36M: + case DESC92C_RATE48M: + case DESC92C_RATE54M: + rate_section = 1; + break; + + case DESC92C_RATEMCS0: + case DESC92C_RATEMCS1: + case DESC92C_RATEMCS2: + case DESC92C_RATEMCS3: + rate_section = 4; + break; + + case DESC92C_RATEMCS4: + case DESC92C_RATEMCS5: + case DESC92C_RATEMCS6: + case DESC92C_RATEMCS7: + rate_section = 5; + break; + + case DESC92C_RATEMCS8: + case DESC92C_RATEMCS9: + case DESC92C_RATEMCS10: + case DESC92C_RATEMCS11: + rate_section = 6; + break; + + case DESC92C_RATEMCS12: + case DESC92C_RATEMCS13: + case DESC92C_RATEMCS14: + case DESC92C_RATEMCS15: + rate_section = 7; + break; + + default: + RT_ASSERT(true, "Rate_Section is Illegal\n"); + break; + } + + return rate_section; +} + +static u8 _rtl8723be_get_txpower_by_rate(struct ieee80211_hw *hw, + enum band_type band, + enum radio_path rfpath, u8 rate) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 shift = 0, rate_section, tx_num; + char tx_pwr_diff = 0; + + rate_section = _rtl8723be_phy_get_ratesection_intxpower_byrate(rfpath, + rate); + tx_num = RF_TX_NUM_NONIMPLEMENT; + + if (tx_num == RF_TX_NUM_NONIMPLEMENT) { + if (rate >= DESC92C_RATEMCS8 && rate <= DESC92C_RATEMCS15) + tx_num = RF_2TX; + else + tx_num = RF_1TX; + } + + switch (rate) { + case DESC92C_RATE6M: + case DESC92C_RATE24M: + case DESC92C_RATEMCS0: + case DESC92C_RATEMCS4: + case DESC92C_RATEMCS8: + case DESC92C_RATEMCS12: + shift = 0; + break; + case DESC92C_RATE1M: + case DESC92C_RATE2M: + case DESC92C_RATE9M: + case DESC92C_RATE36M: + case DESC92C_RATEMCS1: + case DESC92C_RATEMCS5: + case DESC92C_RATEMCS9: + case DESC92C_RATEMCS13: + shift = 8; + break; + case DESC92C_RATE5_5M: + case DESC92C_RATE12M: + case DESC92C_RATE48M: + case DESC92C_RATEMCS2: + case DESC92C_RATEMCS6: + case DESC92C_RATEMCS10: + case DESC92C_RATEMCS14: + shift = 16; + break; + case DESC92C_RATE11M: + case DESC92C_RATE18M: + case DESC92C_RATE54M: + case DESC92C_RATEMCS3: + case DESC92C_RATEMCS7: + case DESC92C_RATEMCS11: + case DESC92C_RATEMCS15: + shift = 24; + break; + default: + RT_ASSERT(true, "Rate_Section is Illegal\n"); + break; + } + tx_pwr_diff = (u8)(rtlphy->tx_power_by_rate_offset[band][rfpath][tx_num] + [rate_section] >> shift) & 0xff; + + return tx_pwr_diff; +} + +static u8 _rtl8723be_get_txpower_index(struct ieee80211_hw *hw, u8 path, + u8 rate, u8 bandwidth, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 index = (channel - 1); + u8 txpower; + u8 power_diff_byrate = 0; + + if (channel > 14 || channel < 1) { + index = 0; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Illegal channel!\n"); + } + if (RX_HAL_IS_CCK_RATE(rate)) + txpower = rtlefuse->txpwrlevel_cck[path][index]; + else if (DESC92C_RATE6M <= rate) + txpower = rtlefuse->txpwrlevel_ht40_1s[path][index]; + else + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "invalid rate\n"); + + if (DESC92C_RATE6M <= rate && rate <= DESC92C_RATE54M && + !RX_HAL_IS_CCK_RATE(rate)) + txpower += rtlefuse->txpwr_legacyhtdiff[0][TX_1S]; + + if (bandwidth == HT_CHANNEL_WIDTH_20) { + if (DESC92C_RATEMCS0 <= rate && rate <= DESC92C_RATEMCS15) + txpower += rtlefuse->txpwr_ht20diff[0][TX_1S]; + if (DESC92C_RATEMCS8 <= rate && rate <= DESC92C_RATEMCS15) + txpower += rtlefuse->txpwr_ht20diff[0][TX_2S]; + } else if (bandwidth == HT_CHANNEL_WIDTH_20_40) { + if (DESC92C_RATEMCS0 <= rate && rate <= DESC92C_RATEMCS15) + txpower += rtlefuse->txpwr_ht40diff[0][TX_1S]; + if (DESC92C_RATEMCS8 <= rate && rate <= DESC92C_RATEMCS15) + txpower += rtlefuse->txpwr_ht40diff[0][TX_2S]; + } + + if (rtlefuse->eeprom_regulatory != 2) + power_diff_byrate = _rtl8723be_get_txpower_by_rate(hw, + BAND_ON_2_4G, + path, rate); + + txpower += power_diff_byrate; + + if (txpower > MAX_POWER_INDEX) + txpower = MAX_POWER_INDEX; + + return txpower; +} + +static void _rtl8723be_phy_set_txpower_index(struct ieee80211_hw *hw, + u8 power_index, u8 path, u8 rate) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (path == RF90_PATH_A) { + switch (rate) { + case DESC92C_RATE1M: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_CCK1_MCS32, + MASKBYTE1, power_index); + break; + case DESC92C_RATE2M: + rtl8723_phy_set_bb_reg(hw, RTXAGC_B_CCK11_A_CCK2_11, + MASKBYTE1, power_index); + break; + case DESC92C_RATE5_5M: + rtl8723_phy_set_bb_reg(hw, RTXAGC_B_CCK11_A_CCK2_11, + MASKBYTE2, power_index); + break; + case DESC92C_RATE11M: + rtl8723_phy_set_bb_reg(hw, RTXAGC_B_CCK11_A_CCK2_11, + MASKBYTE3, power_index); + break; + + case DESC92C_RATE6M: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06, + MASKBYTE0, power_index); + break; + case DESC92C_RATE9M: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06, + MASKBYTE1, power_index); + break; + case DESC92C_RATE12M: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06, + MASKBYTE2, power_index); + break; + case DESC92C_RATE18M: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06, + MASKBYTE3, power_index); + break; + + case DESC92C_RATE24M: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24, + MASKBYTE0, power_index); + break; + case DESC92C_RATE36M: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24, + MASKBYTE1, power_index); + break; + case DESC92C_RATE48M: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24, + MASKBYTE2, power_index); + break; + case DESC92C_RATE54M: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24, + MASKBYTE3, power_index); + break; + + case DESC92C_RATEMCS0: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00, + MASKBYTE0, power_index); + break; + case DESC92C_RATEMCS1: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00, + MASKBYTE1, power_index); + break; + case DESC92C_RATEMCS2: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00, + MASKBYTE2, power_index); + break; + case DESC92C_RATEMCS3: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00, + MASKBYTE3, power_index); + break; + + case DESC92C_RATEMCS4: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04, + MASKBYTE0, power_index); + break; + case DESC92C_RATEMCS5: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04, + MASKBYTE1, power_index); + break; + case DESC92C_RATEMCS6: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04, + MASKBYTE2, power_index); + break; + case DESC92C_RATEMCS7: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04, + MASKBYTE3, power_index); + break; + + case DESC92C_RATEMCS8: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08, + MASKBYTE0, power_index); + break; + case DESC92C_RATEMCS9: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08, + MASKBYTE1, power_index); + break; + case DESC92C_RATEMCS10: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08, + MASKBYTE2, power_index); + break; + case DESC92C_RATEMCS11: + rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08, + MASKBYTE3, power_index); + break; + + default: + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Invalid Rate!!\n"); + break; + } + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Invalid RFPath!!\n"); + } +} + +void rtl8723be_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 cck_rates[] = {DESC92C_RATE1M, DESC92C_RATE2M, + DESC92C_RATE5_5M, DESC92C_RATE11M}; + u8 ofdm_rates[] = {DESC92C_RATE6M, DESC92C_RATE9M, + DESC92C_RATE12M, DESC92C_RATE18M, + DESC92C_RATE24M, DESC92C_RATE36M, + DESC92C_RATE48M, DESC92C_RATE54M}; + u8 ht_rates_1t[] = {DESC92C_RATEMCS0, DESC92C_RATEMCS1, + DESC92C_RATEMCS2, DESC92C_RATEMCS3, + DESC92C_RATEMCS4, DESC92C_RATEMCS5, + DESC92C_RATEMCS6, DESC92C_RATEMCS7}; + u8 i, size; + u8 power_index; + + if (!rtlefuse->txpwr_fromeprom) + return; + + size = sizeof(cck_rates) / sizeof(u8); + for (i = 0; i < size; i++) { + power_index = _rtl8723be_get_txpower_index(hw, RF90_PATH_A, + cck_rates[i], + rtl_priv(hw)->phy.current_chan_bw, + channel); + _rtl8723be_phy_set_txpower_index(hw, power_index, RF90_PATH_A, + cck_rates[i]); + } + size = sizeof(ofdm_rates) / sizeof(u8); + for (i = 0; i < size; i++) { + power_index = _rtl8723be_get_txpower_index(hw, RF90_PATH_A, + ofdm_rates[i], + rtl_priv(hw)->phy.current_chan_bw, + channel); + _rtl8723be_phy_set_txpower_index(hw, power_index, RF90_PATH_A, + ofdm_rates[i]); + } + size = sizeof(ht_rates_1t) / sizeof(u8); + for (i = 0; i < size; i++) { + power_index = _rtl8723be_get_txpower_index(hw, RF90_PATH_A, + ht_rates_1t[i], + rtl_priv(hw)->phy.current_chan_bw, + channel); + _rtl8723be_phy_set_txpower_index(hw, power_index, RF90_PATH_A, + ht_rates_1t[i]); + } +} + +void rtl8723be_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + enum io_type iotype; + + if (!is_hal_stop(rtlhal)) { + switch (operation) { + case SCAN_OPT_BACKUP_BAND0: + iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, + (u8 *)&iotype); + + break; + case SCAN_OPT_RESTORE: + iotype = IO_CMD_RESUME_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, + (u8 *)&iotype); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Unknown Scan Backup operation.\n"); + break; + } + } +} + +void rtl8723be_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 reg_bw_opmode; + u8 reg_prsr_rsc; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "Switch to %s bandwidth\n", + rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : "40MHz"); + + if (is_hal_stop(rtlhal)) { + rtlphy->set_bwmode_inprogress = false; + return; + } + + reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); + reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + reg_bw_opmode |= BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + break; + case HT_CHANNEL_WIDTH_20_40: + reg_bw_opmode &= ~BW_OPMODE_20MHZ; + rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + reg_prsr_rsc = (reg_prsr_rsc & 0x90) | + (mac->cur_40_prime_sc << 5); + rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); + /* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);*/ + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); + rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); + + rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, + (mac->cur_40_prime_sc >> 1)); + rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); + /*rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);*/ + + rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), + (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + rtl8723be_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n"); +} + +void rtl8723be_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_bw = rtlphy->current_chan_bw; + + if (rtlphy->set_bwmode_inprogress) + return; + rtlphy->set_bwmode_inprogress = true; + if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtl8723be_phy_set_bw_mode_callback(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "false driver sleep or unload\n"); + rtlphy->set_bwmode_inprogress = false; + rtlphy->current_chan_bw = tmp_bw; + } +} + +void rtl8723be_phy_sw_chnl_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 delay; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "switch to channel%d\n", rtlphy->current_channel); + if (is_hal_stop(rtlhal)) + return; + do { + if (!rtlphy->sw_chnl_inprogress) + break; + if (!_rtl8723be_phy_sw_chnl_step_by_step(hw, + rtlphy->current_channel, + &rtlphy->sw_chnl_stage, + &rtlphy->sw_chnl_step, + &delay)) { + if (delay > 0) + mdelay(delay); + else + continue; + } else { + rtlphy->sw_chnl_inprogress = false; + } + break; + } while (true); + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); +} + +u8 rtl8723be_phy_sw_chnl(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlphy->sw_chnl_inprogress) + return 0; + if (rtlphy->set_bwmode_inprogress) + return 0; + RT_ASSERT((rtlphy->current_channel <= 14), + "WIRELESS_MODE_G but channel>14"); + rtlphy->sw_chnl_inprogress = true; + rtlphy->sw_chnl_stage = 0; + rtlphy->sw_chnl_step = 0; + if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { + rtl8723be_phy_sw_chnl_callback(hw); + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + "sw_chnl_inprogress false schdule workitem current channel %d\n", + rtlphy->current_channel); + rtlphy->sw_chnl_inprogress = false; + } else { + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + "sw_chnl_inprogress false driver sleep or unload\n"); + rtlphy->sw_chnl_inprogress = false; + } + return 1; +} + +static bool _rtl8723be_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, + u8 channel, u8 *stage, + u8 *step, u32 *delay) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; + u32 precommoncmdcnt; + struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; + u32 postcommoncmdcnt; + struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; + u32 rfdependcmdcnt; + struct swchnlcmd *currentcmd = NULL; + u8 rfpath; + u8 num_total_rfpath = rtlphy->num_total_rfpath; + + precommoncmdcnt = 0; + rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, + CMDID_SET_TXPOWEROWER_LEVEL, + 0, 0, 0); + rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, + MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); + + postcommoncmdcnt = 0; + + rtl8723_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, + MAX_POSTCMD_CNT, CMDID_END, + 0, 0, 0); + + rfdependcmdcnt = 0; + + RT_ASSERT((channel >= 1 && channel <= 14), + "illegal channel for Zebra: %d\n", channel); + + rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, + CMDID_RF_WRITEREG, + RF_CHNLBW, channel, 10); + + rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, + MAX_RFDEPENDCMD_CNT, + CMDID_END, 0, 0, 0); + + do { + switch (*stage) { + case 0: + currentcmd = &precommoncmd[*step]; + break; + case 1: + currentcmd = &rfdependcmd[*step]; + break; + case 2: + currentcmd = &postcommoncmd[*step]; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Invalid 'stage' = %d, Check it!\n", *stage); + return true; + } + + if (currentcmd->cmdid == CMDID_END) { + if ((*stage) == 2) { + return true; + } else { + (*stage)++; + (*step) = 0; + continue; + } + } + + switch (currentcmd->cmdid) { + case CMDID_SET_TXPOWEROWER_LEVEL: + rtl8723be_phy_set_txpower_level(hw, channel); + break; + case CMDID_WRITEPORT_ULONG: + rtl_write_dword(rtlpriv, currentcmd->para1, + currentcmd->para2); + break; + case CMDID_WRITEPORT_USHORT: + rtl_write_word(rtlpriv, currentcmd->para1, + (u16)currentcmd->para2); + break; + case CMDID_WRITEPORT_UCHAR: + rtl_write_byte(rtlpriv, currentcmd->para1, + (u8)currentcmd->para2); + break; + case CMDID_RF_WRITEREG: + for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { + rtlphy->rfreg_chnlval[rfpath] = + ((rtlphy->rfreg_chnlval[rfpath] & + 0xfffffc00) | currentcmd->para2); + + rtl_set_rfreg(hw, (enum radio_path)rfpath, + currentcmd->para1, + RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[rfpath]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + + break; + } while (true); + + (*delay) = currentcmd->msdelay; + (*step)++; + return false; +} + +static u8 _rtl8723be_phy_path_a_iqk(struct ieee80211_hw *hw) +{ + u32 reg_eac, reg_e94, reg_e9c, tmp; + u8 result = 0x00; + + /* leave IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + /* switch to path A */ + rtl_set_bbreg(hw, 0x948, MASKDWORD, 0x00000000); + /* enable path A PA in TXIQK mode */ + rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x20000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0003f); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xc7f87); + + /* 1. TX IQK */ + /* path-A IQK setting */ + /* IQK setting */ + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + /* path-A IQK setting */ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + + rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x821403ea); + rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160000); + rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000); + rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000); + /* LO calibration setting */ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x00462911); + /* enter IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /* One shot, path A LOK & IQK */ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + /* leave IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + + /* Check failed */ + reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); + reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); + reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else /* if Tx not OK, ignore Rx */ + return result; + + /* Allen 20131125 */ + tmp = (reg_e9c & 0x03FF0000) >> 16; + if ((tmp & 0x200) > 0) + tmp = 0x400 - tmp; + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) < 0x110) && + (((reg_e94 & 0x03FF0000) >> 16) > 0xf0) && + (tmp < 0xf)) + result |= 0x01; + else /* if Tx not OK, ignore Rx */ + return result; + + return result; +} + +/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +static u8 _rtl8723be_phy_path_a_rx_iqk(struct ieee80211_hw *hw) +{ + u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u32tmp, tmp; + u8 result = 0x00; + + /* leave IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + + /* switch to path A */ + rtl_set_bbreg(hw, 0x948, MASKDWORD, 0x00000000); + + /* 1 Get TXIMR setting */ + /* modify RXIQK mode table */ + rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, 0x80000, 0x1); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0001f); + /* LNA2 off, PA on for Dcut */ + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7fb7); + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /* IQK setting */ + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + + /* path-A IQK setting */ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + + rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160ff0); + rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28110000); + rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000); + rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000); + + /* LO calibration setting */ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); + + /* enter IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /* One shot, path A LOK & IQK */ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + /* leave IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + + /* Check failed */ + reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); + reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); + reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else /* if Tx not OK, ignore Rx */ + return result; + + /* Allen 20131125 */ + tmp = (reg_e9c & 0x03FF0000) >> 16; + if ((tmp & 0x200) > 0) + tmp = 0x400 - tmp; + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) < 0x110) && + (((reg_e94 & 0x03FF0000) >> 16) > 0xf0) && + (tmp < 0xf)) + result |= 0x01; + else /* if Tx not OK, ignore Rx */ + return result; + + u32tmp = 0x80007C00 | (reg_e94 & 0x3FF0000) | + ((reg_e9c & 0x3FF0000) >> 16); + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32tmp); + + /* 1 RX IQK */ + /* modify RXIQK mode table */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, 0x80000, 0x1); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0001f); + /* LAN2 on, PA off for Dcut */ + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7d77); + + /* PA, PAD setting */ + rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0xf80); + rtl_set_rfreg(hw, RF90_PATH_A, 0x55, RFREG_OFFSET_MASK, 0x4021f); + + /* IQK setting */ + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + + /* path-A IQK setting */ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x18008c1c); + rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + + rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82110000); + rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x2816001f); + rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000); + rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000); + + /* LO calibration setting */ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a8d1); + + /* enter IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /* One shot, path A LOK & IQK */ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + /* leave IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + + /* Check failed */ + reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); + reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD); + + /* leave IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x780); + + /* Allen 20131125 */ + tmp = (reg_eac & 0x03FF0000) >> 16; + if ((tmp & 0x200) > 0) + tmp = 0x400 - tmp; + /* if Tx is OK, check whether Rx is OK */ + if (!(reg_eac & BIT(27)) && + (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_eac & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + else if (!(reg_eac & BIT(27)) && + (((reg_ea4 & 0x03FF0000) >> 16) < 0x110) && + (((reg_ea4 & 0x03FF0000) >> 16) > 0xf0) && + (tmp < 0xf)) + result |= 0x02; + + return result; +} + +static u8 _rtl8723be_phy_path_b_iqk(struct ieee80211_hw *hw) +{ + u32 reg_eac, reg_e94, reg_e9c, tmp; + u8 result = 0x00; + + /* leave IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + /* switch to path B */ + rtl_set_bbreg(hw, 0x948, MASKDWORD, 0x00000280); + + /* enable path B PA in TXIQK mode */ + rtl_set_rfreg(hw, RF90_PATH_A, 0xed, RFREG_OFFSET_MASK, 0x00020); + rtl_set_rfreg(hw, RF90_PATH_A, 0x43, RFREG_OFFSET_MASK, 0x40fc1); + + /* 1 Tx IQK */ + /* IQK setting */ + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + /* path-A IQK setting */ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + + rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x821403ea); + rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28110000); + rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000); + rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000); + + /* LO calibration setting */ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x00462911); + + /* enter IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /* One shot, path B LOK & IQK */ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + /* leave IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + + /* Check failed */ + reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); + reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); + reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else + return result; + + /* Allen 20131125 */ + tmp = (reg_e9c & 0x03FF0000) >> 16; + if ((tmp & 0x200) > 0) + tmp = 0x400 - tmp; + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) < 0x110) && + (((reg_e94 & 0x03FF0000) >> 16) > 0xf0) && + (tmp < 0xf)) + result |= 0x01; + else + return result; + + return result; +} + +/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +static u8 _rtl8723be_phy_path_b_rx_iqk(struct ieee80211_hw *hw) +{ + u32 reg_e94, reg_e9c, reg_ea4, reg_eac, u32tmp, tmp; + u8 result = 0x00; + + /* leave IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + /* switch to path B */ + rtl_set_bbreg(hw, 0x948, MASKDWORD, 0x00000280); + + /* 1 Get TXIMR setting */ + /* modify RXIQK mode table */ + rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0001f); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ff7); + + /* open PA S1 & SMIXER */ + rtl_set_rfreg(hw, RF90_PATH_A, 0xed, RFREG_OFFSET_MASK, 0x00020); + rtl_set_rfreg(hw, RF90_PATH_A, 0x43, RFREG_OFFSET_MASK, 0x60fed); + + /* IQK setting */ + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + + /* path-B IQK setting */ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + + rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160ff0); + rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28110000); + rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000); + rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000); + + /* LO calibration setting */ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); + /* enter IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /* One shot, path B TXIQK @ RXIQK */ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + /* leave IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + /* Check failed */ + reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); + reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); + reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && + (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) + result |= 0x01; + else /* if Tx not OK, ignore Rx */ + return result; + + /* Allen 20131125 */ + tmp = (reg_e9c & 0x03FF0000) >> 16; + if ((tmp & 0x200) > 0) + tmp = 0x400 - tmp; + + if (!(reg_eac & BIT(28)) && + (((reg_e94 & 0x03FF0000) >> 16) < 0x110) && + (((reg_e94 & 0x03FF0000) >> 16) > 0xf0) && + (tmp < 0xf)) + result |= 0x01; + else + return result; + + u32tmp = 0x80007C00 | (reg_e94 & 0x3FF0000) | + ((reg_e9c & 0x3FF0000) >> 16); + rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32tmp); + + /* 1 RX IQK */ + + /* <20121009, Kordan> RF Mode = 3 */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, 0x80000, 0x1); + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0001f); + rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7d77); + rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, 0x80000, 0x0); + + /* open PA S1 & close SMIXER */ + rtl_set_rfreg(hw, RF90_PATH_A, 0xed, RFREG_OFFSET_MASK, 0x00020); + rtl_set_rfreg(hw, RF90_PATH_A, 0x43, RFREG_OFFSET_MASK, 0x60fbd); + + /* IQK setting */ + rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); + + /* path-B IQK setting */ + rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x18008c1c); + rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); + + rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82110000); + rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x2816001f); + rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000); + rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000); + + /* LO calibration setting */ + rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a8d1); + /* enter IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); + + /* One shot, path B LOK & IQK */ + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); + rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); + + mdelay(IQK_DELAY_TIME); + + /* leave IQK mode */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); + /* Check failed */ + reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); + reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD); + + /* Allen 20131125 */ + tmp = (reg_eac & 0x03FF0000) >> 16; + if ((tmp & 0x200) > 0) + tmp = 0x400 - tmp; + + /* if Tx is OK, check whether Rx is OK */ + if (!(reg_eac & BIT(27)) && + (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && + (((reg_eac & 0x03FF0000) >> 16) != 0x36)) + result |= 0x02; + else if (!(reg_eac & BIT(27)) && + (((reg_ea4 & 0x03FF0000) >> 16) < 0x110) && + (((reg_ea4 & 0x03FF0000) >> 16) > 0xf0) && + (tmp < 0xf)) + result |= 0x02; + else + return result; + + return result; +} + +static void _rtl8723be_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw, + bool b_iqk_ok, + long result[][8], + u8 final_candidate, + bool btxonly) +{ + u32 oldval_1, x, tx1_a, reg; + long y, tx1_c; + + if (final_candidate == 0xFF) { + return; + } else if (b_iqk_ok) { + oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, + MASKDWORD) >> 22) & 0x3FF; + x = result[final_candidate][4]; + if ((x & 0x00000200) != 0) + x = x | 0xFFFFFC00; + tx1_a = (x * oldval_1) >> 8; + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x3FF, tx1_a); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(27), + ((x * oldval_1 >> 7) & 0x1)); + y = result[final_candidate][5]; + if ((y & 0x00000200) != 0) + y = y | 0xFFFFFC00; + tx1_c = (y * oldval_1) >> 8; + rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000, + ((tx1_c & 0x3C0) >> 6)); + rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000, + (tx1_c & 0x3F)); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(25), + ((y * oldval_1 >> 7) & 0x1)); + if (btxonly) + return; + reg = result[final_candidate][6]; + rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg); + reg = result[final_candidate][7] & 0x3F; + rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg); + reg = (result[final_candidate][7] >> 6) & 0xF; + /* rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); */ + } +} + +static bool _rtl8723be_phy_simularity_compare(struct ieee80211_hw *hw, + long result[][8], u8 c1, u8 c2) +{ + u32 i, j, diff, simularity_bitmap, bound = 0; + + u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */ + bool bresult = true; /* is2t = true*/ + s32 tmp1 = 0, tmp2 = 0; + + bound = 8; + + simularity_bitmap = 0; + + for (i = 0; i < bound; i++) { + if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) { + if ((result[c1][i] & 0x00000200) != 0) + tmp1 = result[c1][i] | 0xFFFFFC00; + else + tmp1 = result[c1][i]; + + if ((result[c2][i] & 0x00000200) != 0) + tmp2 = result[c2][i] | 0xFFFFFC00; + else + tmp2 = result[c2][i]; + } else { + tmp1 = result[c1][i]; + tmp2 = result[c2][i]; + } + + diff = (tmp1 > tmp2) ? (tmp1 - tmp2) : (tmp2 - tmp1); + + if (diff > MAX_TOLERANCE) { + if ((i == 2 || i == 6) && !simularity_bitmap) { + if (result[c1][i] + result[c1][i + 1] == 0) + final_candidate[(i / 4)] = c2; + else if (result[c2][i] + result[c2][i + 1] == 0) + final_candidate[(i / 4)] = c1; + else + simularity_bitmap |= (1 << i); + } else + simularity_bitmap |= (1 << i); + } + } + + if (simularity_bitmap == 0) { + for (i = 0; i < (bound / 4); i++) { + if (final_candidate[i] != 0xFF) { + for (j = i * 4; j < (i + 1) * 4 - 2; j++) + result[3][j] = + result[final_candidate[i]][j]; + bresult = false; + } + } + return bresult; + } else { + if (!(simularity_bitmap & 0x03)) { /* path A TX OK */ + for (i = 0; i < 2; i++) + result[3][i] = result[c1][i]; + } + if (!(simularity_bitmap & 0x0c)) { /* path A RX OK */ + for (i = 2; i < 4; i++) + result[3][i] = result[c1][i]; + } + if (!(simularity_bitmap & 0x30)) { /* path B TX OK */ + for (i = 4; i < 6; i++) + result[3][i] = result[c1][i]; + } + if (!(simularity_bitmap & 0xc0)) { /* path B RX OK */ + for (i = 6; i < 8; i++) + result[3][i] = result[c1][i]; + } + return false; + } +} + +static void _rtl8723be_phy_iq_calibrate(struct ieee80211_hw *hw, + long result[][8], u8 t, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 i; + u8 patha_ok, pathb_ok; + u32 adda_reg[IQK_ADDA_REG_NUM] = { + 0x85c, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec + }; + + u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { + 0x522, 0x550, 0x551, 0x040 + }; + u32 iqk_bb_reg[IQK_BB_REG_NUM] = { + ROFDM0_TRXPATHENABLE, ROFDM0_TRMUXPAR, + RFPGA0_XCD_RFINTERFACESW, 0xb68, 0xb6c, + 0x870, 0x860, + 0x864, 0xa04 + }; + const u32 retrycount = 2; + + u32 path_sel_bb;/* path_sel_rf */ + + u8 tmp_reg_c50, tmp_reg_c58; + + tmp_reg_c50 = rtl_get_bbreg(hw, 0xc50, MASKBYTE0); + tmp_reg_c58 = rtl_get_bbreg(hw, 0xc58, MASKBYTE0); + + if (t == 0) { + rtl8723_save_adda_registers(hw, adda_reg, + rtlphy->adda_backup, 16); + rtl8723_phy_save_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + rtl8723_save_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, + IQK_BB_REG_NUM); + } + rtl8723_phy_path_adda_on(hw, adda_reg, true, is2t); + if (t == 0) { + rtlphy->rfpi_enable = (u8)rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER1, + BIT(8)); + } + + path_sel_bb = rtl_get_bbreg(hw, 0x948, MASKDWORD); + + rtl8723_phy_mac_setting_calibration(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + /*BB Setting*/ + rtl_set_bbreg(hw, 0xa04, 0x0f000000, 0xf); + rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); + rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); + rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); + + /* path A TX IQK */ + for (i = 0; i < retrycount; i++) { + patha_ok = _rtl8723be_phy_path_a_iqk(hw); + if (patha_ok == 0x01) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Path A Tx IQK Success!!\n"); + result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & + 0x3FF0000) >> 16; + break; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Path A Tx IQK Fail!!\n"); + } + } + /* path A RX IQK */ + for (i = 0; i < retrycount; i++) { + patha_ok = _rtl8723be_phy_path_a_rx_iqk(hw); + if (patha_ok == 0x03) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Path A Rx IQK Success!!\n"); + result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & + 0x3FF0000) >> 16; + result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & + 0x3FF0000) >> 16; + break; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Path A Rx IQK Fail!!\n"); + } + + if (0x00 == patha_ok) + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Path A IQK Fail!!\n"); + + if (is2t) { + /* path B TX IQK */ + for (i = 0; i < retrycount; i++) { + pathb_ok = _rtl8723be_phy_path_b_iqk(hw); + if (pathb_ok == 0x01) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Path B Tx IQK Success!!\n"); + result[t][4] = (rtl_get_bbreg(hw, 0xe94, + MASKDWORD) & + 0x3FF0000) >> 16; + result[t][5] = (rtl_get_bbreg(hw, 0xe9c, + MASKDWORD) & + 0x3FF0000) >> 16; + break; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Path B Tx IQK Fail!!\n"); + } + /* path B RX IQK */ + for (i = 0; i < retrycount; i++) { + pathb_ok = _rtl8723be_phy_path_b_rx_iqk(hw); + if (pathb_ok == 0x03) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Path B Rx IQK Success!!\n"); + result[t][6] = (rtl_get_bbreg(hw, 0xea4, + MASKDWORD) & + 0x3FF0000) >> 16; + result[t][7] = (rtl_get_bbreg(hw, 0xeac, + MASKDWORD) & + 0x3FF0000) >> 16; + break; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Path B Rx IQK Fail!!\n"); + } + } + + /* Back to BB mode, load original value */ + rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0); + + if (t != 0) { + rtl8723_phy_reload_adda_registers(hw, adda_reg, + rtlphy->adda_backup, 16); + rtl8723_phy_reload_mac_registers(hw, iqk_mac_reg, + rtlphy->iqk_mac_backup); + rtl8723_phy_reload_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, + IQK_BB_REG_NUM); + + rtl_set_bbreg(hw, 0x948, MASKDWORD, path_sel_bb); + /*rtl_set_rfreg(hw, RF90_PATH_B, 0xb0, 0xfffff, path_sel_rf);*/ + + rtl_set_bbreg(hw, 0xc50, MASKBYTE0, 0x50); + rtl_set_bbreg(hw, 0xc50, MASKBYTE0, tmp_reg_c50); + if (is2t) { + rtl_set_bbreg(hw, 0xc58, MASKBYTE0, 0x50); + rtl_set_bbreg(hw, 0xc58, MASKBYTE0, tmp_reg_c58); + } + rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00); + rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00); + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "8723be IQK Finish!!\n"); +} + +static u8 _get_right_chnl_place_for_iqk(u8 chnl) +{ + u8 channel_all[TARGET_CHNL_NUM_2G_5G] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 36, 38, 40, 42, 44, 46, + 48, 50, 52, 54, 56, 58, 60, 62, 64, + 100, 102, 104, 106, 108, 110, + 112, 114, 116, 118, 120, 122, + 124, 126, 128, 130, 132, 134, 136, + 138, 140, 149, 151, 153, 155, 157, + 159, 161, 163, 165}; + u8 place = chnl; + + if (chnl > 14) { + for (place = 14; place < sizeof(channel_all); place++) { + if (channel_all[place] == chnl) + return place - 13; + } + } + return 0; +} + +static void _rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) +{ + u8 tmpreg; + u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + tmpreg = rtl_read_byte(rtlpriv, 0xd03); + + if ((tmpreg & 0x70) != 0) + rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); + else + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + + if ((tmpreg & 0x70) != 0) { + rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); + + if (is2t) + rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, + MASK12BITS); + + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, + (rf_a_mode & 0x8FFFF) | 0x10000); + + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, + (rf_b_mode & 0x8FFFF) | 0x10000); + } + lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); + + rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, RFREG_OFFSET_MASK, 0xdfbe0); + rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, 0x8c0a); + + /* In order not to disturb BT music when wifi init.(1ant NIC only) */ + /*mdelay(100);*/ + /* In order not to disturb BT music when wifi init.(1ant NIC only) */ + mdelay(50); + + rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, RFREG_OFFSET_MASK, 0xdffe0); + + if ((tmpreg & 0x70) != 0) { + rtl_write_byte(rtlpriv, 0xd03, tmpreg); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); + + if (is2t) + rtl_set_rfreg(hw, RF90_PATH_B, 0x00, + MASK12BITS, rf_b_mode); + } else { + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + } +RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); + +} + +static void _rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw *hw, + bool bmain, bool is2t) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); + + if (bmain) /* left antenna */ + rtl_set_bbreg(hw, 0x92C, MASKDWORD, 0x1); + else + rtl_set_bbreg(hw, 0x92C, MASKDWORD, 0x2); +} + +#undef IQK_ADDA_REG_NUM +#undef IQK_DELAY_TIME +/* IQK is merge from Merge Temp */ +void rtl8723be_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + long result[4][8]; + u8 i, final_candidate, idx; + bool b_patha_ok, b_pathb_ok; + long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4; + long reg_ecc, reg_tmp = 0; + bool is12simular, is13simular, is23simular; + u32 iqk_bb_reg[9] = { + ROFDM0_XARXIQIMBALANCE, + ROFDM0_XBRXIQIMBALANCE, + ROFDM0_ECCATHRESHOLD, + ROFDM0_AGCRSSITABLE, + ROFDM0_XATXIQIMBALANCE, + ROFDM0_XBTXIQIMBALANCE, + ROFDM0_XCTXAFE, + ROFDM0_XDTXAFE, + ROFDM0_RXIQEXTANTA + }; + u32 path_sel_bb = 0; /* path_sel_rf = 0 */ + + if (rtlphy->lck_inprogress) + return; + + spin_lock(&rtlpriv->locks.iqk_lock); + rtlphy->lck_inprogress = true; + spin_unlock(&rtlpriv->locks.iqk_lock); + + if (b_recovery) { + rtl8723_phy_reload_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, 9); + return; + } + /* Save RF Path */ + path_sel_bb = rtl_get_bbreg(hw, 0x948, MASKDWORD); + /* path_sel_rf = rtl_get_rfreg(hw, RF90_PATH_A, 0xb0, 0xfffff); */ + + for (i = 0; i < 8; i++) { + result[0][i] = 0; + result[1][i] = 0; + result[2][i] = 0; + result[3][i] = 0; + } + final_candidate = 0xff; + b_patha_ok = false; + b_pathb_ok = false; + is12simular = false; + is23simular = false; + is13simular = false; + for (i = 0; i < 3; i++) { + _rtl8723be_phy_iq_calibrate(hw, result, i, true); + if (i == 1) { + is12simular = _rtl8723be_phy_simularity_compare(hw, + result, + 0, 1); + if (is12simular) { + final_candidate = 0; + break; + } + } + if (i == 2) { + is13simular = _rtl8723be_phy_simularity_compare(hw, + result, + 0, 2); + if (is13simular) { + final_candidate = 0; + break; + } + is23simular = _rtl8723be_phy_simularity_compare(hw, + result, + 1, 2); + if (is23simular) { + final_candidate = 1; + } else { + for (i = 0; i < 8; i++) + reg_tmp += result[3][i]; + + if (reg_tmp != 0) + final_candidate = 3; + else + final_candidate = 0xFF; + } + } + } + for (i = 0; i < 4; i++) { + reg_e94 = result[i][0]; + reg_e9c = result[i][1]; + reg_ea4 = result[i][2]; + reg_eac = result[i][3]; + reg_eb4 = result[i][4]; + reg_ebc = result[i][5]; + reg_ec4 = result[i][6]; + reg_ecc = result[i][7]; + } + if (final_candidate != 0xff) { + reg_e94 = result[final_candidate][0]; + rtlphy->reg_e94 = reg_e94; + reg_e9c = result[final_candidate][1]; + rtlphy->reg_e9c = reg_e9c; + reg_ea4 = result[final_candidate][2]; + reg_eac = result[final_candidate][3]; + reg_eb4 = result[final_candidate][4]; + rtlphy->reg_eb4 = reg_eb4; + reg_ebc = result[final_candidate][5]; + rtlphy->reg_ebc = reg_ebc; + reg_ec4 = result[final_candidate][6]; + reg_ecc = result[final_candidate][7]; + b_patha_ok = true; + b_pathb_ok = true; + } else { + rtlphy->reg_e94 = 0x100; + rtlphy->reg_eb4 = 0x100; + rtlphy->reg_e9c = 0x0; + rtlphy->reg_ebc = 0x0; + } + if (reg_e94 != 0) + rtl8723_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result, + final_candidate, + (reg_ea4 == 0)); + if (reg_eb4 != 0) + _rtl8723be_phy_path_b_fill_iqk_matrix(hw, b_pathb_ok, result, + final_candidate, + (reg_ec4 == 0)); + + idx = _get_right_chnl_place_for_iqk(rtlphy->current_channel); + + if (final_candidate < 4) { + for (i = 0; i < IQK_MATRIX_REG_NUM; i++) + rtlphy->iqk_matrix[idx].value[0][i] = + result[final_candidate][i]; + rtlphy->iqk_matrix[idx].iqk_done = true; + + } + rtl8723_save_adda_registers(hw, iqk_bb_reg, + rtlphy->iqk_bb_backup, 9); + + rtl_set_bbreg(hw, 0x948, MASKDWORD, path_sel_bb); + /* rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, 0xfffff, path_sel_rf); */ + + spin_lock(&rtlpriv->locks.iqk_lock); + rtlphy->lck_inprogress = false; + spin_unlock(&rtlpriv->locks.iqk_lock); +} + +void rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = &rtlpriv->rtlhal; + u32 timeout = 2000, timecount = 0; + + while (rtlpriv->mac80211.act_scanning && timecount < timeout) { + udelay(50); + timecount += 50; + } + + rtlphy->lck_inprogress = true; + RTPRINT(rtlpriv, FINIT, INIT_IQK, + "LCK:Start!!! currentband %x delay %d ms\n", + rtlhal->current_bandtype, timecount); + + _rtl8723be_phy_lc_calibrate(hw, false); + + rtlphy->lck_inprogress = false; +} + +void rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) +{ + _rtl8723be_phy_set_rfpath_switch(hw, bmain, true); +} + +bool rtl8723be_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + bool b_postprocessing = false; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "-->IO Cmd(%#x), set_io_inprogress(%d)\n", + iotype, rtlphy->set_io_inprogress); + do { + switch (iotype) { + case IO_CMD_RESUME_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Resume DM after scan.\n"); + b_postprocessing = true; + break; + case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Pause DM before scan.\n"); + b_postprocessing = true; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + } while (false); + if (b_postprocessing && !rtlphy->set_io_inprogress) { + rtlphy->set_io_inprogress = true; + rtlphy->current_io_type = iotype; + } else { + return false; + } + rtl8723be_phy_set_io(hw); + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); + return true; +} + +static void rtl8723be_phy_set_io(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + struct rtl_phy *rtlphy = &rtlpriv->phy; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "--->Cmd(%#x), set_io_inprogress(%d)\n", + rtlphy->current_io_type, rtlphy->set_io_inprogress); + switch (rtlphy->current_io_type) { + case IO_CMD_RESUME_DM_BY_SCAN: + dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; + /*rtl92c_dm_write_dig(hw);*/ + rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel); + rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x83); + break; + case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: + rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; + dm_digtable->cur_igvalue = 0x17; + rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x40); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + rtlphy->set_io_inprogress = false; + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "(%#x)\n", rtlphy->current_io_type); +} + +static void rtl8723be_phy_set_rf_on(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); +} + +static void _rtl8723be_phy_set_rf_sleep(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); +} + +static bool _rtl8723be_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = true; + u8 i, queue_id; + struct rtl8192_tx_ring *ring = NULL; + + switch (rfpwr_state) { + case ERFON: + if ((ppsc->rfpwr_state == ERFOFF) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + bool rtstatus; + u32 initializecount = 0; + do { + initializecount++; + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic enable\n"); + rtstatus = rtl_ps_enable_nic(hw); + } while (!rtstatus && (initializecount < 10)); + RT_CLEAR_PS_LEVEL(ppsc, + RT_RF_OFF_LEVL_HALT_NIC); + } else { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFON sleeped:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc->last_sleep_jiffies)); + ppsc->last_awake_jiffies = jiffies; + rtl8723be_phy_set_rf_on(hw); + } + if (mac->link_state == MAC80211_LINKED) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_LINK); + else + rtlpriv->cfg->ops->led_control(hw, LED_CTL_NO_LINK); + + break; + + case ERFOFF: + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + /* Don't check BEACON Q. + * BEACON Q is always not empty, + * because '_rtl8723be_cmd_send_packet' + */ + if (queue_id == BEACON_QUEUE || + skb_queue_len(&ring->queue) == 0) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", + (i + 1), queue_id, + skb_queue_len(&ring->queue)); + + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic disable\n"); + rtl_ps_disable_nic(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } else { + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_POWER_OFF); + } + } + break; + + case ERFSLEEP: + if (ppsc->rfpwr_state == ERFOFF) + break; + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (skb_queue_len(&ring->queue) == 0) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", + (i + 1), queue_id, + skb_queue_len(&ring->queue)); + + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFSLEEP awaked:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc->last_awake_jiffies)); + ppsc->last_sleep_jiffies = jiffies; + _rtl8723be_phy_set_rf_sleep(hw); + break; + + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + bresult = false; + break; + } + if (bresult) + ppsc->rfpwr_state = rfpwr_state; + return bresult; +} + +bool rtl8723be_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + bool bresult = false; + + if (rfpwr_state == ppsc->rfpwr_state) + return bresult; + bresult = _rtl8723be_phy_set_rf_power_state(hw, rfpwr_state); + return bresult; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h new file mode 100644 index 000000000000..9021d4745ab7 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.h @@ -0,0 +1,135 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723BE_PHY_H__ +#define __RTL8723BE_PHY_H__ + +/* MAX_TX_COUNT must always set to 4, otherwise read efuse table sequence + * will be wrong. + */ +#define MAX_TX_COUNT 4 +#define TX_1S 0 +#define TX_2S 1 +#define TX_3S 2 +#define TX_4S 3 + +#define MAX_POWER_INDEX 0x3F + +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define MAX_DOZE_WAITING_TIMES_9x 64 + +#define RT_CANNOT_IO(hw) false +#define HIGHPOWER_RADIOA_ARRAYLEN 22 + +#define TARGET_CHNL_NUM_2G_5G 59 + +#define IQK_ADDA_REG_NUM 16 +#define IQK_BB_REG_NUM 9 +#define MAX_TOLERANCE 5 +#define IQK_DELAY_TIME 10 +#define index_mapping_NUM 15 + +#define APK_BB_REG_NUM 5 +#define APK_AFE_REG_NUM 16 +#define APK_CURVE_REG_NUM 4 +#define PATH_NUM 1 + +#define LOOP_LIMIT 5 +#define MAX_STALL_TIME 50 +#define ANTENNADIVERSITYVALUE 0x80 +#define MAX_TXPWR_IDX_NMODE_92S 63 +#define RESET_CNT_LIMIT 3 + +#define IQK_ADDA_REG_NUM 16 +#define IQK_MAC_REG_NUM 4 + +#define RF6052_MAX_PATH 2 + +#define CT_OFFSET_MAC_ADDR 0X16 + +#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A +#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 +#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 +#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 +#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C + +#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F +#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 + +#define CT_OFFSET_CHANNEL_PLAH 0x75 +#define CT_OFFSET_THERMAL_METER 0x78 +#define CT_OFFSET_RF_OPTION 0x79 +#define CT_OFFSET_VERSION 0x7E +#define CT_OFFSET_CUSTOMER_ID 0x7F + +#define RTL92C_MAX_PATH_NUM 2 + +enum baseband_config_type { + BASEBAND_CONFIG_PHY_REG = 0, + BASEBAND_CONFIG_AGC_TAB = 1, +}; + +enum ant_div_type { + NO_ANTDIV = 0xFF, + CG_TRX_HW_ANTDIV = 0x01, + CGCS_RX_HW_ANTDIV = 0x02, + FIXED_HW_ANTDIV = 0x03, + CG_TRX_SMART_ANTDIV = 0x04, + CGCS_RX_SW_ANTDIV = 0x05, + +}; + +u32 rtl8723be_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask); +void rtl8723be_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data); +bool rtl8723be_phy_mac_config(struct ieee80211_hw *hw); +bool rtl8723be_phy_bb_config(struct ieee80211_hw *hw); +bool rtl8723be_phy_rf_config(struct ieee80211_hw *hw); +void rtl8723be_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl8723be_phy_set_txpower_level(struct ieee80211_hw *hw, + u8 channel); +void rtl8723be_phy_scan_operation_backup(struct ieee80211_hw *hw, + u8 operation); +void rtl8723be_phy_set_bw_mode_callback(struct ieee80211_hw *hw); +void rtl8723be_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); +void rtl8723be_phy_sw_chnl_callback(struct ieee80211_hw *hw); +u8 rtl8723be_phy_sw_chnl(struct ieee80211_hw *hw); +void rtl8723be_phy_iq_calibrate(struct ieee80211_hw *hw, + bool b_recovery); +void rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw); +void rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); +bool rtl8723be_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +bool rtl8723be_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); +bool rtl8723be_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c new file mode 100644 index 000000000000..a1bb1f6116fb --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.c @@ -0,0 +1,106 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../pwrseqcmd.h" +#include "pwrseq.h" + + +/* drivers should parse below arrays and do the corresponding actions */ +/*3 Power on Array*/ +struct wlan_pwr_cfg rtl8723B_power_on_flow[RTL8723B_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8723B_TRANS_END_STEPS] = { + RTL8723B_TRANS_CARDEMU_TO_ACT + RTL8723B_TRANS_END +}; + +/*3Radio off GPIO Array */ +struct wlan_pwr_cfg rtl8723B_radio_off_flow[RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723B_TRANS_END_STEPS] = { + RTL8723B_TRANS_ACT_TO_CARDEMU + RTL8723B_TRANS_END +}; + +/*3Card Disable Array*/ +struct wlan_pwr_cfg rtl8723B_card_disable_flow + [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8723B_TRANS_END_STEPS] = { + RTL8723B_TRANS_ACT_TO_CARDEMU + RTL8723B_TRANS_CARDEMU_TO_CARDDIS + RTL8723B_TRANS_END +}; + +/*3 Card Enable Array*/ +struct wlan_pwr_cfg rtl8723B_card_enable_flow + [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8723B_TRANS_END_STEPS] = { + RTL8723B_TRANS_CARDDIS_TO_CARDEMU + RTL8723B_TRANS_CARDEMU_TO_ACT + RTL8723B_TRANS_END +}; + +/*3Suspend Array*/ +struct wlan_pwr_cfg rtl8723B_suspend_flow[RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8723B_TRANS_END_STEPS] = { + RTL8723B_TRANS_ACT_TO_CARDEMU + RTL8723B_TRANS_CARDEMU_TO_SUS + RTL8723B_TRANS_END +}; + +/*3 Resume Array*/ +struct wlan_pwr_cfg rtl8723B_resume_flow[RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8723B_TRANS_END_STEPS] = { + RTL8723B_TRANS_SUS_TO_CARDEMU + RTL8723B_TRANS_CARDEMU_TO_ACT + RTL8723B_TRANS_END +}; + +/*3HWPDN Array*/ +struct wlan_pwr_cfg rtl8723B_hwpdn_flow[RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8723B_TRANS_END_STEPS] = { + RTL8723B_TRANS_ACT_TO_CARDEMU + RTL8723B_TRANS_CARDEMU_TO_PDN + RTL8723B_TRANS_END +}; + +/*3 Enter LPS */ +struct wlan_pwr_cfg rtl8723B_enter_lps_flow[RTL8723B_TRANS_ACT_TO_LPS_STEPS + + RTL8723B_TRANS_END_STEPS] = { + /*FW behavior*/ + RTL8723B_TRANS_ACT_TO_LPS + RTL8723B_TRANS_END +}; + +/*3 Leave LPS */ +struct wlan_pwr_cfg rtl8723B_leave_lps_flow[RTL8723B_TRANS_LPS_TO_ACT_STEPS + + RTL8723B_TRANS_END_STEPS] = { + /*FW behavior*/ + RTL8723B_TRANS_LPS_TO_ACT + RTL8723B_TRANS_END +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h new file mode 100644 index 000000000000..0fee5e0e55c2 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h @@ -0,0 +1,423 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723BE_PWRSEQ_H__ +#define __RTL8723BE_PWRSEQ_H__ + +#include "../pwrseqcmd.h" +/** + * Check document WM-20130425-JackieLau-RTL8723B_Power_Architecture v05.vsd + * There are 6 HW Power States: + * 0: POFF--Power Off + * 1: PDN--Power Down + * 2: CARDEMU--Card Emulation + * 3: ACT--Active Mode + * 4: LPS--Low Power State + * 5: SUS--Suspend + * + * The transision from different states are defined below + * TRANS_CARDEMU_TO_ACT + * TRANS_ACT_TO_CARDEMU + * TRANS_CARDEMU_TO_SUS + * TRANS_SUS_TO_CARDEMU + * TRANS_CARDEMU_TO_PDN + * TRANS_ACT_TO_LPS + * TRANS_LPS_TO_ACT + * + * TRANS_END + */ +#define RTL8723B_TRANS_CARDEMU_TO_ACT_STEPS 23 +#define RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS 15 +#define RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS 15 +#define RTL8723B_TRANS_SUS_TO_CARDEMU_STEPS 15 +#define RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS 15 +#define RTL8723B_TRANS_PDN_TO_CARDEMU_STEPS 15 +#define RTL8723B_TRANS_ACT_TO_LPS_STEPS 15 +#define RTL8723B_TRANS_LPS_TO_ACT_STEPS 15 +#define RTL8723B_TRANS_END_STEPS 1 + +#define RTL8723B_TRANS_CARDEMU_TO_ACT \ + /* format */ \ + /* comments here */ \ + /* {offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value}, */\ + /*0x20[0] = 1b'1 enable LDOA12 MACRO block for all interface*/ \ + {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ + /*0x67[0] = 0 to disable BT_GPS_SEL pins*/ \ + {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ + /*Delay 1ms*/ \ + {0x0001, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_DELAY, 1, PWRSEQ_DELAY_MS}, \ + /*0x00[5] = 1b'0 release analog Ips to digital ,1:isolation*/ \ + {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), 0}, \ + /* disable SW LPS 0x04[10]=0 and WLSUS_EN 0x04[11]=0*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT(4)|BIT(3)|BIT(2)), 0}, \ + /* Disable USB suspend */ \ + {0x0075, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0) , BIT(0)}, \ + /* wait till 0x04[17] = 1 power ready*/ \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)}, \ + /* Enable USB suspend */ \ + {0x0075, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0) , 0}, \ + /* release WLON reset 0x04[16]=1*/ \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ + /* disable HWPDN 0x04[15]=0*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}, \ + /* disable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT(4)|BIT(3)), 0}, \ + /* polling until return 0*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0}, \ + /* Enable WL control XTAL setting*/ \ + {0x0010, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6), BIT(6)}, \ + /*Enable falling edge triggering interrupt*/ \ + {0x0049, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ + /*Enable GPIO9 interrupt mode*/ \ + {0x0063, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ + /*Enable GPIO9 input mode*/ \ + {0x0062, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \ + /*Enable HSISR GPIO[C:0] interrupt*/ \ + {0x0058, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ + /*Enable HSISR GPIO9 interrupt*/ \ + {0x005A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ + /*For GPIO9 internal pull high setting by test chip*/ \ + {0x0068, PWR_CUT_TESTCHIP_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3), BIT(3)}, \ + /*For GPIO9 internal pull high setting*/ \ + {0x0069, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6), BIT(6)}, + +#define RTL8723B_TRANS_ACT_TO_CARDEMU \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ + /*0x1F[7:0] = 0 turn off RF*/ \ + {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, \ + /*0x4C[24] = 0x4F[0] = 0, */ \ + /*switch DPDT_SEL_P output from register 0x65[2] */ \ + {0x004F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \ + /*Enable rising edge triggering interrupt*/ \ + {0x0049, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \ + /*0x04[9] = 1 turn off MAC by HW state machine*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ + /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, \ + /* Enable BT control XTAL setting*/ \ + {0x0010, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6), 0}, \ + /*0x00[5] = 1b'1 analog Ips to digital ,1:isolation*/ \ + {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \ + PWR_CMD_WRITE, BIT(5), BIT(5)}, \ + /*0x20[0] = 1b'0 disable LDOA12 MACRO block*/ \ + {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \ + PWR_CMD_WRITE, BIT(0), 0}, + +#define RTL8723B_TRANS_CARDEMU_TO_SUS \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ + /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4) | BIT(3), (BIT(4) | BIT(3))}, \ + /*0x04[12:11] = 2b'01 enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \ + PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)}, \ + /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \ + /*0x07[7:0] = 0x20 SDIO SOP option to disable BG/MB/ACK/SWR*/ \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, \ + /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3) | BIT(4)},\ + /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ + /*wait power state to suspend*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, + +#define RTL8723B_TRANS_SUS_TO_CARDEMU \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ + /*clear suspend enable and power down enable*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, \ + /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, \ + /*wait power state to suspend*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, \ + /*0x23[4] = 1b'0 12H LDO enter normal mode*/ \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ + /*0x04[12:11] = 2b'01enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, + +#define RTL8723B_TRANS_CARDEMU_TO_CARDDIS \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ + /*0x07=0x20 , SOP option to disable BG/MB*/ \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, \ + /*0x04[12:11] = 2b'01 enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \ + /*0x04[10] = 1, enable SW LPS*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), BIT(2)}, \ + /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/ \ + {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 1}, \ + /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \ + /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ + /*wait power state to suspend*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, + +#define RTL8723B_TRANS_CARDDIS_TO_CARDEMU \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ + /*clear suspend enable and power down enable*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, \ + /*Set SDIO suspend local register*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, \ + /*wait power state to suspend*/ \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, \ + /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ \ + {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \ + /*0x04[12:11] = 2b'01enable WL suspend*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, \ + /*0x23[4] = 1b'0 12H LDO enter normal mode*/ \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ + /*PCIe DMA start*/ \ + {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, + +#define RTL8723B_TRANS_CARDEMU_TO_PDN \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ + /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \ + /*0x07[7:0] = 0x20 SOP option to disable BG/MB/ACK/SWR*/ \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_SDIO_MSK | PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, \ + PWR_CMD_WRITE, 0xFF, 0x20}, \ + /* 0x04[16] = 0*/ \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \ + /* 0x04[15] = 1*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, + +#define RTL8723B_TRANS_PDN_TO_CARDEMU \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ + /* 0x04[15] = 0*/ \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}, + +#define RTL8723B_TRANS_ACT_TO_LPS \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ + /*PCIe DMA stop*/ \ + {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, \ + /*Tx Pause*/ \ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, \ + /*Should be zero if no packet is transmitting*/ \ + {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ + /*Should be zero if no packet is transmitting*/ \ + {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ + /*Should be zero if no packet is transmitting*/ \ + {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ + /*Should be zero if no packet is transmitting*/ \ + {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ + /*CCK and OFDM are disabled,and clock are gated*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \ + /*Delay 1us*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US}, \ + /*Whole BB is reset*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \ + /*Reset MAC TRX*/ \ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x03}, \ + /*check if removed later*/ \ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \ + /*When driver enter Sus/ Disable, enable LOP for BT*/ \ + {0x0093, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00}, \ + /*Respond TxOK to scheduler*/ \ + {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}, + +#define RTL8723B_TRANS_LPS_TO_ACT \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ + /*SDIO RPWM*/ \ + {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84}, \ + /*USB RPWM*/ \ + {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, \ + /*PCIe RPWM*/ \ + {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, \ + /*Delay*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, \ + /*. 0x08[4] = 0 switch TSF to 40M*/ \ + {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ + /*Polling 0x109[7]=0 TSF in 40M*/ \ + {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0}, \ + /*. 0x29[7:6] = 2b'00 enable BB clock*/ \ + {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0}, \ + /*. 0x101[1] = 1*/ \ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ + /*. 0x100[7:0] = 0xFF enable WMAC TRX*/ \ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, \ + /*. 0x02[1:0] = 2b'11 enable BB macro*/ \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1) | BIT(0), BIT(1) | BIT(0)}, \ + /*. 0x522 = 0*/ \ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, + +#define RTL8723B_TRANS_END \ + /* format */ \ + /* comments here */ \ + /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ + {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, 0, \ + PWR_CMD_END, 0, 0}, + +extern struct wlan_pwr_cfg rtl8723B_power_on_flow + [RTL8723B_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8723B_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723B_radio_off_flow + [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723B_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723B_card_disable_flow + [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8723B_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723B_card_enable_flow + [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8723B_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723B_suspend_flow + [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8723B_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723B_resume_flow + [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8723B_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723B_hwpdn_flow + [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8723B_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723B_enter_lps_flow + [RTL8723B_TRANS_ACT_TO_LPS_STEPS + + RTL8723B_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8723B_leave_lps_flow + [RTL8723B_TRANS_LPS_TO_ACT_STEPS + + RTL8723B_TRANS_END_STEPS]; + +/* RTL8723 Power Configuration CMDs for PCIe interface */ +#define RTL8723_NIC_PWR_ON_FLOW rtl8723B_power_on_flow +#define RTL8723_NIC_RF_OFF_FLOW rtl8723B_radio_off_flow +#define RTL8723_NIC_DISABLE_FLOW rtl8723B_card_disable_flow +#define RTL8723_NIC_ENABLE_FLOW rtl8723B_card_enable_flow +#define RTL8723_NIC_SUSPEND_FLOW rtl8723B_suspend_flow +#define RTL8723_NIC_RESUME_FLOW rtl8723B_resume_flow +#define RTL8723_NIC_PDN_FLOW rtl8723B_hwpdn_flow +#define RTL8723_NIC_LPS_ENTER_FLOW rtl8723B_enter_lps_flow +#define RTL8723_NIC_LPS_LEAVE_FLOW rtl8723B_leave_lps_flow + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h new file mode 100644 index 000000000000..03581d2a5da0 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/reg.h @@ -0,0 +1,2295 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723BE_REG_H__ +#define __RTL8723BE_REG_H__ + +#define TXPKT_BUF_SELECT 0x69 +#define RXPKT_BUF_SELECT 0xA5 +#define DISABLE_TRXPKT_BUF_ACCESS 0x0 + +#define REG_SYS_ISO_CTRL 0x0000 +#define REG_SYS_FUNC_EN 0x0002 +#define REG_APS_FSMCO 0x0004 +#define REG_SYS_CLKR 0x0008 +#define REG_9346CR 0x000A +#define REG_EE_VPD 0x000C +#define REG_AFE_MISC 0x0010 +#define REG_SPS0_CTRL 0x0011 +#define REG_SPS_OCP_CFG 0x0018 +#define REG_RSV_CTRL 0x001C +#define REG_RF_CTRL 0x001F +#define REG_LDOA15_CTRL 0x0020 +#define REG_LDOV12D_CTRL 0x0021 +#define REG_LDOHCI12_CTRL 0x0022 +#define REG_LPLDO_CTRL 0x0023 +#define REG_AFE_XTAL_CTRL 0x0024 +/* 1.5v for 8188EE test chip, 1.4v for MP chip */ +#define REG_AFE_LDO_CTRL 0x0027 +#define REG_AFE_PLL_CTRL 0x0028 +#define REG_MAC_PHY_CTRL 0x002c +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define REG_PWR_DATA 0x0038 +#define REG_CAL_TIMER 0x003C +#define REG_ACLK_MON 0x003E +#define REG_GPIO_MUXCFG 0x0040 +#define REG_GPIO_IO_SEL 0x0042 +#define REG_MAC_PINMUX_CFG 0x0043 +#define REG_GPIO_PIN_CTRL 0x0044 +#define REG_GPIO_INTM 0x0048 +#define REG_LEDCFG0 0x004C +#define REG_LEDCFG1 0x004D +#define REG_LEDCFG2 0x004E +#define REG_LEDCFG3 0x004F +#define REG_FSIMR 0x0050 +#define REG_FSISR 0x0054 +#define REG_HSIMR 0x0058 +#define REG_HSISR 0x005c +#define REG_GPIO_PIN_CTRL_2 0x0060 +#define REG_GPIO_IO_SEL_2 0x0062 +#define REG_MULTI_FUNC_CTRL 0x0068 +#define REG_GPIO_OUTPUT 0x006c +#define REG_AFE_XTAL_CTRL_EXT 0x0078 +#define REG_XCK_OUT_CTRL 0x007c +#define REG_MCUFWDL 0x0080 +#define REG_WOL_EVENT 0x0081 +#define REG_MCUTSTCFG 0x0084 + +#define REG_HIMR 0x00B0 +#define REG_HISR 0x00B4 +#define REG_HIMRE 0x00B8 +#define REG_HISRE 0x00BC +#define REG_PMC_DBG_CTRL2 0x00CC + +#define REG_EFUSE_ACCESS 0x00CF + +#define REG_BIST_SCAN 0x00D0 +#define REG_BIST_RPT 0x00D4 +#define REG_BIST_ROM_RPT 0x00D8 +#define REG_USB_SIE_INTF 0x00E0 +#define REG_PCIE_MIO_INTF 0x00E4 +#define REG_PCIE_MIO_INTD 0x00E8 +#define REG_HPON_FSM 0x00EC +#define REG_SYS_CFG 0x00F0 +#define REG_GPIO_OUTSTS 0x00F4 +#define REG_MAC_PHY_CTRL_NORMAL 0x00F8 +#define REG_SYS_CFG1 0x00FC +#define REG_ROM_VERSION 0x00FD + +#define REG_CR 0x0100 +#define REG_PBP 0x0104 +#define REG_PKT_BUFF_ACCESS_CTRL 0x0106 +#define REG_TRXDMA_CTRL 0x010C +#define REG_TRXFF_BNDY 0x0114 +#define REG_TRXFF_STATUS 0x0118 +#define REG_RXFF_PTR 0x011C + +#define REG_CPWM 0x012F +#define REG_FWIMR 0x0130 +#define REG_FWISR 0x0134 +#define REG_PKTBUF_DBG_CTRL 0x0140 +#define REG_PKTBUF_DBG_DATA_L 0x0144 +#define REG_PKTBUF_DBG_DATA_H 0x0148 +#define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL + 2) + +#define REG_TC0_CTRL 0x0150 +#define REG_TC1_CTRL 0x0154 +#define REG_TC2_CTRL 0x0158 +#define REG_TC3_CTRL 0x015C +#define REG_TC4_CTRL 0x0160 +#define REG_TCUNIT_BASE 0x0164 +#define REG_MBIST_START 0x0174 +#define REG_MBIST_DONE 0x0178 +#define REG_MBIST_FAIL 0x017C +#define REG_32K_CTRL 0x0194 +#define REG_C2HEVT_MSG_NORMAL 0x01A0 +#define REG_C2HEVT_CLEAR 0x01AF +#define REG_C2HEVT_MSG_TEST 0x01B8 +#define REG_MCUTST_1 0x01c0 +#define REG_FMETHR 0x01C8 +#define REG_HMETFR 0x01CC +#define REG_HMEBOX_0 0x01D0 +#define REG_HMEBOX_1 0x01D4 +#define REG_HMEBOX_2 0x01D8 +#define REG_HMEBOX_3 0x01DC + +#define REG_LLT_INIT 0x01E0 +#define REG_BB_ACCEESS_CTRL 0x01E8 +#define REG_BB_ACCESS_DATA 0x01EC + +#define REG_HMEBOX_EXT_0 0x01F0 +#define REG_HMEBOX_EXT_1 0x01F4 +#define REG_HMEBOX_EXT_2 0x01F8 +#define REG_HMEBOX_EXT_3 0x01FC + +#define REG_RQPN 0x0200 +#define REG_FIFOPAGE 0x0204 +#define REG_TDECTRL 0x0208 +#define REG_TXDMA_OFFSET_CHK 0x020C +#define REG_TXDMA_STATUS 0x0210 +#define REG_RQPN_NPQ 0x0214 + +#define REG_RXDMA_AGG_PG_TH 0x0280 +/* FW shall update this register before FW write RXPKT_RELEASE_POLL to 1 */ +#define REG_FW_UPD_RDPTR 0x0284 +/* Control the RX DMA.*/ +#define REG_RXDMA_CONTROL 0x0286 +/* The number of packets in RXPKTBUF. */ +#define REG_RXPKT_NUM 0x0287 + +#define REG_PCIE_CTRL_REG 0x0300 +#define REG_INT_MIG 0x0304 +#define REG_BCNQ_DESA 0x0308 +#define REG_HQ_DESA 0x0310 +#define REG_MGQ_DESA 0x0318 +#define REG_VOQ_DESA 0x0320 +#define REG_VIQ_DESA 0x0328 +#define REG_BEQ_DESA 0x0330 +#define REG_BKQ_DESA 0x0338 +#define REG_RX_DESA 0x0340 + +#define REG_DBI_WDATA 0x0348 +#define REG_DBI_RDATA 0x034C +#define REG_DBI_CTRL 0x0350 +#define REG_DBI_ADDR 0x0350 +#define REG_DBI_FLAG 0x0352 +#define REG_MDIO_WDATA 0x0354 +#define REG_MDIO_RDATA 0x0356 +#define REG_MDIO_CTL 0x0358 +#define REG_DBG_SEL 0x0360 +#define REG_PCIE_HRPWM 0x0361 +#define REG_PCIE_HCPWM 0x0363 +#define REG_UART_CTRL 0x0364 +#define REG_WATCH_DOG 0x0368 +#define REG_UART_TX_DESA 0x0370 +#define REG_UART_RX_DESA 0x0378 + +#define REG_HDAQ_DESA_NODEF 0x0000 +#define REG_CMDQ_DESA_NODEF 0x0000 + +#define REG_VOQ_INFORMATION 0x0400 +#define REG_VIQ_INFORMATION 0x0404 +#define REG_BEQ_INFORMATION 0x0408 +#define REG_BKQ_INFORMATION 0x040C +#define REG_MGQ_INFORMATION 0x0410 +#define REG_HGQ_INFORMATION 0x0414 +#define REG_BCNQ_INFORMATION 0x0418 +#define REG_TXPKT_EMPTY 0x041A + +#define REG_CPU_MGQ_INFORMATION 0x041C +#define REG_FWHW_TXQ_CTRL 0x0420 +#define REG_HWSEQ_CTRL 0x0423 +#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 +#define REG_TXPKTBUF_MGQ_BDNY 0x0425 +#define REG_MULTI_BCNQ_EN 0x0426 +#define REG_MULTI_BCNQ_OFFSET 0x0427 +#define REG_SPEC_SIFS 0x0428 +#define REG_RL 0x042A +#define REG_DARFRC 0x0430 +#define REG_RARFRC 0x0438 +#define REG_RRSR 0x0440 +#define REG_ARFR0 0x0444 +#define REG_ARFR1 0x044C +#define REG_AMPDU_MAX_TIME 0x0456 +#define REG_AGGLEN_LMT 0x0458 +#define REG_AMPDU_MIN_SPACE 0x045C +#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D +#define REG_FAST_EDCA_CTRL 0x0460 +#define REG_RD_RESP_PKT_TH 0x0463 +#define REG_INIRTS_RATE_SEL 0x0480 +#define REG_INIDATA_RATE_SEL 0x0484 +#define REG_POWER_STATUS 0x04A4 +#define REG_POWER_STAGE1 0x04B4 +#define REG_POWER_STAGE2 0x04B8 +#define REG_PKT_LIFE_TIME 0x04C0 +#define REG_STBC_SETTING 0x04C4 +#define REG_HT_SINGLE_AMPDU 0x04C7 + +#define REG_PROT_MODE_CTRL 0x04C8 +#define REG_MAX_AGGR_NUM 0x04CA +#define REG_BAR_MODE_CTRL 0x04CC +#define REG_RA_TRY_RATE_AGG_LMT 0x04CF +#define REG_EARLY_MODE_CONTROL 0x04D0 +#define REG_NQOS_SEQ 0x04DC +#define REG_QOS_SEQ 0x04DE +#define REG_NEED_CPU_HANDLE 0x04E0 +#define REG_PKT_LOSE_RPT 0x04E1 +#define REG_PTCL_ERR_STATUS 0x04E2 +#define REG_TX_RPT_CTRL 0x04EC +#define REG_TX_RPT_TIME 0x04F0 +#define REG_DUMMY 0x04FC + +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050C +#define REG_BCNTCFG 0x0510 +#define REG_PIFS 0x0512 +#define REG_RDG_PIFS 0x0513 +#define REG_SIFS_CTX 0x0514 +#define REG_SIFS_TRX 0x0516 +#define REG_AGGR_BREAK_TIME 0x051A +#define REG_SLOT 0x051B +#define REG_TX_PTCL_CTRL 0x0520 +#define REG_TXPAUSE 0x0522 +#define REG_DIS_TXREQ_CLR 0x0523 +#define REG_RD_CTRL 0x0524 +#define REG_TBTT_PROHIBIT 0x0540 +#define REG_RD_NAV_NXT 0x0544 +#define REG_NAV_PROT_LEN 0x0546 +#define REG_BCN_CTRL 0x0550 +#define REG_USTIME_TSF 0x0551 +#define REG_MBID_NUM 0x0552 +#define REG_DUAL_TSF_RST 0x0553 +#define REG_BCN_INTERVAL 0x0554 +#define REG_MBSSID_BCN_SPACE 0x0554 +#define REG_DRVERLYINT 0x0558 +#define REG_BCNDMATIM 0x0559 +#define REG_ATIMWND 0x055A +#define REG_BCN_MAX_ERR 0x055D +#define REG_RXTSF_OFFSET_CCK 0x055E +#define REG_RXTSF_OFFSET_OFDM 0x055F +#define REG_TSFTR 0x0560 +#define REG_INIT_TSFTR 0x0564 +#define REG_SECONDARY_CCA_CTRL 0x0577 +#define REG_PSTIMER 0x0580 +#define REG_TIMER0 0x0584 +#define REG_TIMER1 0x0588 +#define REG_ACMHWCTRL 0x05C0 +#define REG_ACMRSTCTRL 0x05C1 +#define REG_ACMAVG 0x05C2 +#define REG_VO_ADMTIME 0x05C4 +#define REG_VI_ADMTIME 0x05C6 +#define REG_BE_ADMTIME 0x05C8 +#define REG_EDCA_RANDOM_GEN 0x05CC +#define REG_SCH_TXCMD 0x05D0 + +#define REG_APSD_CTRL 0x0600 +#define REG_BWOPMODE 0x0603 +#define REG_TCR 0x0604 +#define REG_RCR 0x0608 +#define REG_RX_PKT_LIMIT 0x060C +#define REG_RX_DLK_TIME 0x060D +#define REG_RX_DRVINFO_SZ 0x060F + +#define REG_MACID 0x0610 +#define REG_BSSID 0x0618 +#define REG_MAR 0x0620 +#define REG_MBIDCAMCFG 0x0628 + +#define REG_USTIME_EDCA 0x0638 +#define REG_MAC_SPEC_SIFS 0x063A +#define REG_RESP_SIFS_CCK 0x063C +#define REG_RESP_SIFS_OFDM 0x063E +#define REG_ACKTO 0x0640 +#define REG_CTS2TO 0x0641 +#define REG_EIFS 0x0642 + +#define REG_NAV_CTRL 0x0650 +#define REG_NAV_UPPER 0x0652 +#define REG_BACAMCMD 0x0654 +#define REG_BACAMCONTENT 0x0658 +#define REG_LBDLY 0x0660 +#define REG_FWDLY 0x0661 +#define REG_RXERR_RPT 0x0664 +#define REG_TRXPTCL_CTL 0x0668 + +#define REG_CAMCMD 0x0670 +#define REG_CAMWRITE 0x0674 +#define REG_CAMREAD 0x0678 +#define REG_CAMDBG 0x067C +#define REG_SECCFG 0x0680 + +#define REG_WOW_CTRL 0x0690 +#define REG_PSSTATUS 0x0691 +#define REG_PS_RX_INFO 0x0692 +#define REG_UAPSD_TID 0x0693 +#define REG_LPNAV_CTRL 0x0694 +#define REG_WKFMCAM_NUM 0x0698 +#define REG_WKFMCAM_RWD 0x069C +#define REG_RXFLTMAP0 0x06A0 +#define REG_RXFLTMAP1 0x06A2 +#define REG_RXFLTMAP2 0x06A4 +#define REG_BCN_PSR_RPT 0x06A8 +#define REG_CALB32K_CTRL 0x06AC +#define REG_PKT_MON_CTRL 0x06B4 +#define REG_BT_COEX_TABLE 0x06C0 +#define REG_WMAC_RESP_TXINFO 0x06D8 + +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_TEST_USB_TXQS 0xFE48 +#define REG_TEST_SIE_VID 0xFE60 +#define REG_TEST_SIE_PID 0xFE62 +#define REG_TEST_SIE_OPTIONAL 0xFE64 +#define REG_TEST_SIE_CHIRP_K 0xFE65 +#define REG_TEST_SIE_PHY 0xFE66 +#define REG_TEST_SIE_MAC_ADDR 0xFE70 +#define REG_TEST_SIE_STRING 0xFE80 + +#define REG_NORMAL_SIE_VID 0xFE60 +#define REG_NORMAL_SIE_PID 0xFE62 +#define REG_NORMAL_SIE_OPTIONAL 0xFE64 +#define REG_NORMAL_SIE_EP 0xFE65 +#define REG_NORMAL_SIE_PHY 0xFE68 +#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 +#define REG_NORMAL_SIE_STRING 0xFE80 + +#define CR9346 REG_9346CR +#define MSR (REG_CR + 2) +#define ISR REG_HISR +#define TSFR REG_TSFTR + +#define MACIDR0 REG_MACID +#define MACIDR4 (REG_MACID + 4) + +#define PBP REG_PBP + +#define IDR0 MACIDR0 +#define IDR4 MACIDR4 + +#define UNUSED_REGISTER 0x1BF +#define DCAM UNUSED_REGISTER +#define PSR UNUSED_REGISTER +#define BBADDR UNUSED_REGISTER +#define PHYDATAR UNUSED_REGISTER + +#define INVALID_BBRF_VALUE 0x12345678 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define CMDEEPROM_EN BIT(5) +#define CMDEEPROM_SEL BIT(4) +#define CMD9346CR_9356SEL BIT(4) +#define AUTOLOAD_EEPROM (CMDEEPROM_EN | CMDEEPROM_SEL) +#define AUTOLOAD_EFUSE CMDEEPROM_EN + +#define GPIOSEL_GPIO 0 +#define GPIOSEL_ENBT BIT(5) + +#define GPIO_IN REG_GPIO_PIN_CTRL +#define GPIO_OUT (REG_GPIO_PIN_CTRL + 1) +#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL + 2) +#define GPIO_MOD (REG_GPIO_PIN_CTRL + 3) + +/* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */ +#define HSIMR_GPIO12_0_INT_EN BIT(0) +#define HSIMR_SPS_OCP_INT_EN BIT(5) +#define HSIMR_RON_INT_EN BIT(6) +#define HSIMR_PDN_INT_EN BIT(7) +#define HSIMR_GPIO9_INT_EN BIT(25) + +/* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */ +#define HSISR_GPIO12_0_INT BIT(0) +#define HSISR_SPS_OCP_INT BIT(5) +#define HSISR_RON_INT_EN BIT(6) +#define HSISR_PDNINT BIT(7) +#define HSISR_GPIO9_INT BIT(25) + +#define MSR_NOLINK 0x00 +#define MSR_ADHOC 0x01 +#define MSR_INFRA 0x02 +#define MSR_AP 0x03 + +#define RRSR_RSC_OFFSET 21 +#define RRSR_SHORT_OFFSET 23 +#define RRSR_RSC_BW_40M 0x600000 +#define RRSR_RSC_UPSUBCHNL 0x400000 +#define RRSR_RSC_LOWSUBCHNL 0x200000 +#define RRSR_SHORT 0x800000 +#define RRSR_1M BIT(0) +#define RRSR_2M BIT(1) +#define RRSR_5_5M BIT(2) +#define RRSR_11M BIT(3) +#define RRSR_6M BIT(4) +#define RRSR_9M BIT(5) +#define RRSR_12M BIT(6) +#define RRSR_18M BIT(7) +#define RRSR_24M BIT(8) +#define RRSR_36M BIT(9) +#define RRSR_48M BIT(10) +#define RRSR_54M BIT(11) +#define RRSR_MCS0 BIT(12) +#define RRSR_MCS1 BIT(13) +#define RRSR_MCS2 BIT(14) +#define RRSR_MCS3 BIT(15) +#define RRSR_MCS4 BIT(16) +#define RRSR_MCS5 BIT(17) +#define RRSR_MCS6 BIT(18) +#define RRSR_MCS7 BIT(19) +#define BRSR_ACKSHORTPMB BIT(23) + +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 + +#define RATE_1M BIT(0) +#define RATE_2M BIT(1) +#define RATE_5_5M BIT(2) +#define RATE_11M BIT(3) +#define RATE_6M BIT(4) +#define RATE_9M BIT(5) +#define RATE_12M BIT(6) +#define RATE_18M BIT(7) +#define RATE_24M BIT(8) +#define RATE_36M BIT(9) +#define RATE_48M BIT(10) +#define RATE_54M BIT(11) +#define RATE_MCS0 BIT(12) +#define RATE_MCS1 BIT(13) +#define RATE_MCS2 BIT(14) +#define RATE_MCS3 BIT(15) +#define RATE_MCS4 BIT(16) +#define RATE_MCS5 BIT(17) +#define RATE_MCS6 BIT(18) +#define RATE_MCS7 BIT(19) +#define RATE_MCS8 BIT(20) +#define RATE_MCS9 BIT(21) +#define RATE_MCS10 BIT(22) +#define RATE_MCS11 BIT(23) +#define RATE_MCS12 BIT(24) +#define RATE_MCS13 BIT(25) +#define RATE_MCS14 BIT(26) +#define RATE_MCS15 BIT(27) + +#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) +#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\ + RATR_24M | RATR_36M | RATR_48M | RATR_54M) +#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 |\ + RATR_MCS3 | RATR_MCS4 | RATR_MCS5 |\ + RATR_MCS6 | RATR_MCS7) +#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 |\ + RATR_MCS11 | RATR_MCS12 | RATR_MCS13 |\ + RATR_MCS14 | RATR_MCS15) + +#define BW_OPMODE_20MHZ BIT(2) +#define BW_OPMODE_5G BIT(1) +#define BW_OPMODE_11J BIT(0) + +#define CAM_VALID BIT(15) +#define CAM_NOTVALID 0x0000 +#define CAM_USEDK BIT(5) + +#define CAM_NONE 0x0 +#define CAM_WEP40 0x01 +#define CAM_TKIP 0x02 +#define CAM_AES 0x04 +#define CAM_WEP104 0x05 + +#define TOTAL_CAM_ENTRY 32 +#define HALF_CAM_ENTRY 16 + +#define CAM_WRITE BIT(16) +#define CAM_READ 0x00000000 +#define CAM_POLLINIG BIT(31) + +#define SCR_USEDK 0x01 +#define SCR_TXSEC_ENABLE 0x02 +#define SCR_RXSEC_ENABLE 0x04 + +#define WOW_PMEN BIT(0) +#define WOW_WOMEN BIT(1) +#define WOW_MAGIC BIT(2) +#define WOW_UWF BIT(3) + +/********************************************* +* 8723BE IMR/ISR bits +********************************************* +*/ +#define IMR_DISABLED 0x0 +/* IMR DW0(0x0060-0063) Bit 0-31 */ +#define IMR_TXCCK BIT(30) /* TXRPT interrupt when + * CCX bit of the packet is set + */ +#define IMR_PSTIMEOUT BIT(29) /* Power Save Time Out Interrupt */ +#define IMR_GTINT4 BIT(28) /* When GTIMER4 expires, + * this bit is set to 1 + */ +#define IMR_GTINT3 BIT(27) /* When GTIMER3 expires, + * this bit is set to 1 + */ +#define IMR_TBDER BIT(26) /* Transmit Beacon0 Error */ +#define IMR_TBDOK BIT(25) /* Transmit Beacon0 OK */ +#define IMR_TSF_BIT32_TOGGLE BIT(24) /* TSF Timer BIT32 toggle + * indication interrupt + */ +#define IMR_BCNDMAINT0 BIT(20) /* Beacon DMA Interrupt 0 */ +#define IMR_BCNDOK0 BIT(16) /* Beacon Queue DMA OK0 */ +#define IMR_HSISR_IND_ON_INT BIT(15) /* HSISR Indicator (HSIMR & HSISR is + * true, this bit is set to 1) + */ +#define IMR_BCNDMAINT_E BIT(14) /* Beacon DMA Interrupt + * Extension for Win7 + */ +#define IMR_ATIMEND BIT(12) /* CTWidnow End or ATIM Window End */ +#define IMR_HISR1_IND_INT BIT(11) /* HISR1 Indicator (HISR1 & HIMR1 is + * true, this bit is set to 1) + */ +#define IMR_C2HCMD BIT(10) /* CPU to Host Command INT Status, + * Write 1 clear + */ +#define IMR_CPWM2 BIT(9) /* CPU power Mode exchange INT Status, + * Write 1 clear + */ +#define IMR_CPWM BIT(8) /* CPU power Mode exchange INT Status, + * Write 1 clear + */ +#define IMR_HIGHDOK BIT(7) /* High Queue DMA OK */ +#define IMR_MGNTDOK BIT(6) /* Management Queue DMA OK */ +#define IMR_BKDOK BIT(5) /* AC_BK DMA OK */ +#define IMR_BEDOK BIT(4) /* AC_BE DMA OK */ +#define IMR_VIDOK BIT(3) /* AC_VI DMA OK */ +#define IMR_VODOK BIT(2) /* AC_VO DMA OK */ +#define IMR_RDU BIT(1) /* Rx Descriptor Unavailable */ +#define IMR_ROK BIT(0) /* Receive DMA OK */ + +/* IMR DW1(0x00B4-00B7) Bit 0-31 */ +#define IMR_BCNDMAINT7 BIT(27) /* Beacon DMA Interrupt 7 */ +#define IMR_BCNDMAINT6 BIT(26) /* Beacon DMA Interrupt 6 */ +#define IMR_BCNDMAINT5 BIT(25) /* Beacon DMA Interrupt 5 */ +#define IMR_BCNDMAINT4 BIT(24) /* Beacon DMA Interrupt 4 */ +#define IMR_BCNDMAINT3 BIT(23) /* Beacon DMA Interrupt 3 */ +#define IMR_BCNDMAINT2 BIT(22) /* Beacon DMA Interrupt 2 */ +#define IMR_BCNDMAINT1 BIT(21) /* Beacon DMA Interrupt 1 */ +#define IMR_BCNDOK7 BIT(20) /* Beacon Queue DMA OK Interrup 7 */ +#define IMR_BCNDOK6 BIT(19) /* Beacon Queue DMA OK Interrup 6 */ +#define IMR_BCNDOK5 BIT(18) /* Beacon Queue DMA OK Interrup 5 */ +#define IMR_BCNDOK4 BIT(17) /* Beacon Queue DMA OK Interrup 4 */ +#define IMR_BCNDOK3 BIT(16) /* Beacon Queue DMA OK Interrup 3 */ +#define IMR_BCNDOK2 BIT(15) /* Beacon Queue DMA OK Interrup 2 */ +#define IMR_BCNDOK1 BIT(14) /* Beacon Queue DMA OK Interrup 1 */ +#define IMR_ATIMEND_E BIT(13) /* ATIM Window End Extension for Win7 */ +#define IMR_TXERR BIT(11) /* Tx Error Flag Interrupt Status, + * write 1 clear. + */ +#define IMR_RXERR BIT(10) /* Rx Error Flag INT Status, + * Write 1 clear + */ +#define IMR_TXFOVW BIT(9) /* Transmit FIFO Overflow */ +#define IMR_RXFOVW BIT(8) /* Receive FIFO Overflow */ + +#define HWSET_MAX_SIZE 512 +#define EFUSE_MAX_SECTION 64 +#define EFUSE_REAL_CONTENT_LEN 256 +#define EFUSE_OOB_PROTECT_BYTES 18 /* PG data exclude header, + * dummy 7 bytes frome CP test + * and reserved 1byte. + */ + +#define EEPROM_DEFAULT_TSSI 0x0 +#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_BOARDTYPE 0x02 +#define EEPROM_DEFAULT_TXPOWER 0x1010 +#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 + +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_THERMALMETER 0x18 +#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 +#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 +#define EEPROM_DEFAULT_HT20_DIFF 2 +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 +#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 + +#define RF_OPTION1 0x79 +#define RF_OPTION2 0x7A +#define RF_OPTION3 0x7B +#define EEPROM_RF_BT_SETTING_8723B 0xC3 + +#define EEPROM_DEFAULT_PID 0x1234 +#define EEPROM_DEFAULT_VID 0x5678 +#define EEPROM_DEFAULT_CUSTOMERID 0xAB +#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD +#define EEPROM_DEFAULT_VERSION 0 + +#define EEPROM_CHANNEL_PLAN_FCC 0x0 +#define EEPROM_CHANNEL_PLAN_IC 0x1 +#define EEPROM_CHANNEL_PLAN_ETSI 0x2 +#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 +#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 +#define EEPROM_CHANNEL_PLAN_MKK 0x5 +#define EEPROM_CHANNEL_PLAN_MKK1 0x6 +#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 +#define EEPROM_CHANNEL_PLAN_TELEC 0x8 +#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 +#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA +#define EEPROM_CHANNEL_PLAN_NCC 0xB +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + +#define EEPROM_CID_DEFAULT 0x0 +#define EEPROM_CID_TOSHIBA 0x4 +#define EEPROM_CID_CCX 0x10 +#define EEPROM_CID_QMI 0x0D +#define EEPROM_CID_WHQL 0xFE + +#define RTL8723BE_EEPROM_ID 0x8129 + +#define EEPROM_HPON 0x02 +#define EEPROM_CLK 0x06 +#define EEPROM_TESTR 0x08 + +#define EEPROM_TXPOWERCCK 0x10 +#define EEPROM_TXPOWERHT40_1S 0x16 +#define EEPROM_TXPOWERHT20DIFF 0x1B +#define EEPROM_TXPOWER_OFDMDIFF 0x1B + +#define EEPROM_TX_PWR_INX 0x10 + +#define EEPROM_CHANNELPLAN 0xB8 +#define EEPROM_XTAL_8723BE 0xB9 +#define EEPROM_THERMAL_METER_88E 0xBA +#define EEPROM_IQK_LCK_88E 0xBB + +#define EEPROM_RF_BOARD_OPTION_88E 0xC1 +#define EEPROM_RF_FEATURE_OPTION_88E 0xC2 +#define EEPROM_RF_BT_SETTING_88E 0xC3 +#define EEPROM_VERSION 0xC4 +#define EEPROM_CUSTOMER_ID 0xC5 +#define EEPROM_RF_ANTENNA_OPT_88E 0xC9 + +#define EEPROM_MAC_ADDR 0xD0 +#define EEPROM_VID 0xD6 +#define EEPROM_DID 0xD8 +#define EEPROM_SVID 0xDA +#define EEPROM_SMID 0xDC + +#define STOPBECON BIT(6) +#define STOPHIGHT BIT(5) +#define STOPMGT BIT(4) +#define STOPVO BIT(3) +#define STOPVI BIT(2) +#define STOPBE BIT(1) +#define STOPBK BIT(0) + +#define RCR_APPFCS BIT(31) +#define RCR_APP_MIC BIT(30) +#define RCR_APP_ICV BIT(29) +#define RCR_APP_PHYST_RXFF BIT(28) +#define RCR_APP_BA_SSN BIT(27) +#define RCR_ENMBID BIT(24) +#define RCR_LSIGEN BIT(23) +#define RCR_MFBEN BIT(22) +#define RCR_HTC_LOC_CTRL BIT(14) +#define RCR_AMF BIT(13) +#define RCR_ACF BIT(12) +#define RCR_ADF BIT(11) +#define RCR_AICV BIT(9) +#define RCR_ACRC32 BIT(8) +#define RCR_CBSSID_BCN BIT(7) +#define RCR_CBSSID_DATA BIT(6) +#define RCR_CBSSID RCR_CBSSID_DATA +#define RCR_APWRMGT BIT(5) +#define RCR_ADD3 BIT(4) +#define RCR_AB BIT(3) +#define RCR_AM BIT(2) +#define RCR_APM BIT(1) +#define RCR_AAP BIT(0) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 + +#define RSV_CTRL 0x001C +#define RD_CTRL 0x0524 + +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_USB_VID 0xFE60 +#define REG_USB_PID 0xFE62 +#define REG_USB_OPTIONAL 0xFE64 +#define REG_USB_CHIRP_K 0xFE65 +#define REG_USB_PHY 0xFE66 +#define REG_USB_MAC_ADDR 0xFE70 +#define REG_USB_HRPWM 0xFE58 +#define REG_USB_HCPWM 0xFE57 + +#define SW18_FPWM BIT(3) + +#define ISO_MD2PP BIT(0) +#define ISO_UA2USB BIT(1) +#define ISO_UD2CORE BIT(2) +#define ISO_PA2PCIE BIT(3) +#define ISO_PD2CORE BIT(4) +#define ISO_IP2MAC BIT(5) +#define ISO_DIOP BIT(6) +#define ISO_DIOE BIT(7) +#define ISO_EB2CORE BIT(8) +#define ISO_DIOR BIT(9) + +#define PWC_EV25V BIT(14) +#define PWC_EV12V BIT(15) + +#define FEN_BBRSTB BIT(0) +#define FEN_BB_GLB_RSTN BIT(1) +#define FEN_USBA BIT(2) +#define FEN_UPLL BIT(3) +#define FEN_USBD BIT(4) +#define FEN_DIO_PCIE BIT(5) +#define FEN_PCIEA BIT(6) +#define FEN_PPLL BIT(7) +#define FEN_PCIED BIT(8) +#define FEN_DIOE BIT(9) +#define FEN_CPUEN BIT(10) +#define FEN_DCORE BIT(11) +#define FEN_ELDR BIT(12) +#define FEN_DIO_RF BIT(13) +#define FEN_HWPDN BIT(14) +#define FEN_MREGEN BIT(15) + +#define PFM_LDALL BIT(0) +#define PFM_ALDN BIT(1) +#define PFM_LDKP BIT(2) +#define PFM_WOWL BIT(3) +#define ENPDN BIT(4) +#define PDN_PL BIT(5) +#define APFM_ONMAC BIT(8) +#define APFM_OFF BIT(9) +#define APFM_RSM BIT(10) +#define AFSM_HSUS BIT(11) +#define AFSM_PCIE BIT(12) +#define APDM_MAC BIT(13) +#define APDM_HOST BIT(14) +#define APDM_HPDN BIT(15) +#define RDY_MACON BIT(16) +#define SUS_HOST BIT(17) +#define ROP_ALD BIT(20) +#define ROP_PWR BIT(21) +#define ROP_SPS BIT(22) +#define SOP_MRST BIT(25) +#define SOP_FUSE BIT(26) +#define SOP_ABG BIT(27) +#define SOP_AMB BIT(28) +#define SOP_RCK BIT(29) +#define SOP_A8M BIT(30) +#define XOP_BTCK BIT(31) + +#define ANAD16V_EN BIT(0) +#define ANA8M BIT(1) +#define MACSLP BIT(4) +#define LOADER_CLK_EN BIT(5) +#define _80M_SSC_DIS BIT(7) +#define _80M_SSC_EN_HO BIT(8) +#define PHY_SSC_RSTB BIT(9) +#define SEC_CLK_EN BIT(10) +#define MAC_CLK_EN BIT(11) +#define SYS_CLK_EN BIT(12) +#define RING_CLK_EN BIT(13) + +#define BOOT_FROM_EEPROM BIT(4) +#define EEPROM_EN BIT(5) + +#define AFE_BGEN BIT(0) +#define AFE_MBEN BIT(1) +#define MAC_ID_EN BIT(7) + +#define WLOCK_ALL BIT(0) +#define WLOCK_00 BIT(1) +#define WLOCK_04 BIT(2) +#define WLOCK_08 BIT(3) +#define WLOCK_40 BIT(4) +#define R_DIS_PRST_0 BIT(5) +#define R_DIS_PRST_1 BIT(6) +#define LOCK_ALL_EN BIT(7) + +#define RF_EN BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + +#define LDA15_EN BIT(0) +#define LDA15_STBY BIT(1) +#define LDA15_OBUF BIT(2) +#define LDA15_REG_VOS BIT(3) +#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) + +#define LDV12_EN BIT(0) +#define LDV12_SDBY BIT(1) +#define LPLDO_HSM BIT(2) +#define LPLDO_LSM_DIS BIT(3) +#define _LDV12_VADJ(x) (((x) & 0xF) << 4) + +#define XTAL_EN BIT(0) +#define XTAL_BSEL BIT(1) +#define _XTAL_BOSC(x) (((x) & 0x3) << 2) +#define _XTAL_CADJ(x) (((x) & 0xF) << 4) +#define XTAL_GATE_USB BIT(8) +#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) +#define XTAL_GATE_AFE BIT(11) +#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) +#define XTAL_RF_GATE BIT(14) +#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) +#define XTAL_GATE_DIG BIT(17) +#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) +#define XTAL_BT_GATE BIT(20) +#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) +#define _XTAL_GPIO(x) (((x) & 0x7) << 23) + +#define CKDLY_AFE BIT(26) +#define CKDLY_USB BIT(27) +#define CKDLY_DIG BIT(28) +#define CKDLY_BT BIT(29) + +#define APLL_EN BIT(0) +#define APLL_320_EN BIT(1) +#define APLL_FREF_SEL BIT(2) +#define APLL_EDGE_SEL BIT(3) +#define APLL_WDOGB BIT(4) +#define APLL_LPFEN BIT(5) + +#define APLL_REF_CLK_13MHZ 0x1 +#define APLL_REF_CLK_19_2MHZ 0x2 +#define APLL_REF_CLK_20MHZ 0x3 +#define APLL_REF_CLK_25MHZ 0x4 +#define APLL_REF_CLK_26MHZ 0x5 +#define APLL_REF_CLK_38_4MHZ 0x6 +#define APLL_REF_CLK_40MHZ 0x7 + +#define APLL_320EN BIT(14) +#define APLL_80EN BIT(15) +#define APLL_1MEN BIT(24) + +#define ALD_EN BIT(18) +#define EF_PD BIT(19) +#define EF_FLAG BIT(31) + +#define EF_TRPT BIT(7) +#define LDOE25_EN BIT(31) + +#define RSM_EN BIT(0) +#define TIMER_EN BIT(4) + +#define TRSW0EN BIT(2) +#define TRSW1EN BIT(3) +#define EROM_EN BIT(4) +#define ENBT BIT(5) +#define ENUART BIT(8) +#define UART_910 BIT(9) +#define ENPMAC BIT(10) +#define SIC_SWRST BIT(11) +#define ENSIC BIT(12) +#define SIC_23 BIT(13) +#define ENHDP BIT(14) +#define SIC_LBK BIT(15) + +#define LED0PL BIT(4) +#define LED1PL BIT(12) +#define LED0DIS BIT(7) + +#define MCUFWDL_EN BIT(0) +#define MCUFWDL_RDY BIT(1) +#define FWDL_CHKSUM_RPT BIT(2) +#define MACINI_RDY BIT(3) +#define BBINI_RDY BIT(4) +#define RFINI_RDY BIT(5) +#define WINTINI_RDY BIT(6) +#define CPRST BIT(23) + +#define XCLK_VLD BIT(0) +#define ACLK_VLD BIT(1) +#define UCLK_VLD BIT(2) +#define PCLK_VLD BIT(3) +#define PCIRSTB BIT(4) +#define V15_VLD BIT(5) +#define TRP_B15V_EN BIT(7) +#define SIC_IDLE BIT(8) +#define BD_MAC2 BIT(9) +#define BD_MAC1 BIT(10) +#define IC_MACPHY_MODE BIT(11) +#define VENDOR_ID BIT(19) +#define PAD_HWPD_IDN BIT(22) +#define TRP_VAUX_EN BIT(23) +#define TRP_BT_EN BIT(24) +#define BD_PKG_SEL BIT(25) +#define BD_HCI_SEL BIT(26) +#define TYPE_ID BIT(27) + +#define CHIP_VER_RTL_MASK 0xF000 +#define CHIP_VER_RTL_SHIFT 12 + +#define REG_LBMODE (REG_CR + 3) + +#define HCI_TXDMA_EN BIT(0) +#define HCI_RXDMA_EN BIT(1) +#define TXDMA_EN BIT(2) +#define RXDMA_EN BIT(3) +#define PROTOCOL_EN BIT(4) +#define SCHEDULE_EN BIT(5) +#define MACTXEN BIT(6) +#define MACRXEN BIT(7) +#define ENSWBCN BIT(8) +#define ENSEC BIT(9) + +#define _NETTYPE(x) (((x) & 0x3) << 16) +#define MASK_NETTYPE 0x30000 +#define NT_NO_LINK 0x0 +#define NT_LINK_AD_HOC 0x1 +#define NT_LINK_AP 0x2 +#define NT_AS_AP 0x3 + +#define _LBMODE(x) (((x) & 0xF) << 24) +#define MASK_LBMODE 0xF000000 +#define LOOPBACK_NORMAL 0x0 +#define LOOPBACK_IMMEDIATELY 0xB +#define LOOPBACK_MAC_DELAY 0x3 +#define LOOPBACK_PHY 0x1 +#define LOOPBACK_DMA 0x7 + +#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) +#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) +#define _PSRX_MASK 0xF +#define _PSTX_MASK 0xF0 +#define _PSRX(x) (x) +#define _PSTX(x) ((x) << 4) + +#define PBP_64 0x0 +#define PBP_128 0x1 +#define PBP_256 0x2 +#define PBP_512 0x3 +#define PBP_1024 0x4 + +#define RXDMA_ARBBW_EN BIT(0) +#define RXSHFT_EN BIT(1) +#define RXDMA_AGG_EN BIT(2) +#define QS_VO_QUEUE BIT(8) +#define QS_VI_QUEUE BIT(9) +#define QS_BE_QUEUE BIT(10) +#define QS_BK_QUEUE BIT(11) +#define QS_MANAGER_QUEUE BIT(12) +#define QS_HIGH_QUEUE BIT(13) + +#define HQSEL_VOQ BIT(0) +#define HQSEL_VIQ BIT(1) +#define HQSEL_BEQ BIT(2) +#define HQSEL_BKQ BIT(3) +#define HQSEL_MGTQ BIT(4) +#define HQSEL_HIQ BIT(5) + +#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) +#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) +#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) +#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) +#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) +#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) + +#define QUEUE_LOW 1 +#define QUEUE_NORMAL 2 +#define QUEUE_HIGH 3 + +#define _LLT_NO_ACTIVE 0x0 +#define _LLT_WRITE_ACCESS 0x1 +#define _LLT_READ_ACCESS 0x2 + +#define _LLT_INIT_DATA(x) ((x) & 0xFF) +#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) +#define _LLT_OP(x) (((x) & 0x3) << 30) +#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) + +#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) +#define BB_WRITE_EN BIT(30) +#define BB_READ_EN BIT(31) + +#define _HPQ(x) ((x) & 0xFF) +#define _LPQ(x) (((x) & 0xFF) << 8) +#define _PUBQ(x) (((x) & 0xFF) << 16) +#define _NPQ(x) ((x) & 0xFF) + +#define HPQ_PUBLIC_DIS BIT(24) +#define LPQ_PUBLIC_DIS BIT(25) +#define LD_RQPN BIT(31) + +#define BCN_VALID BIT(16) +#define BCN_HEAD(x) (((x) & 0xFF) << 8) +#define BCN_HEAD_MASK 0xFF00 + +#define BLK_DESC_NUM_SHIFT 4 +#define BLK_DESC_NUM_MASK 0xF + +#define DROP_DATA_EN BIT(9) + +#define EN_AMPDU_RTY_NEW BIT(7) + +#define _INIRTSMCS_SEL(x) ((x) & 0x3F) + +#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) +#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) + +#define RATE_REG_BITMAP_ALL 0xFFFFF + +#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) + +#define _RRSR_RSC(x) (((x) & 0x3) << 21) +#define RRSR_RSC_RESERVED 0x0 +#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 +#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 +#define RRSR_RSC_DUPLICATE_MODE 0x3 + +#define USE_SHORT_G1 BIT(20) + +#define _AGGLMT_MCS0(x) ((x) & 0xF) +#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) +#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) +#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) +#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) +#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) +#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) +#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) + +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + +#define _DARF_RC1(x) ((x) & 0x1F) +#define _DARF_RC2(x) (((x) & 0x1F) << 8) +#define _DARF_RC3(x) (((x) & 0x1F) << 16) +#define _DARF_RC4(x) (((x) & 0x1F) << 24) +#define _DARF_RC5(x) ((x) & 0x1F) +#define _DARF_RC6(x) (((x) & 0x1F) << 8) +#define _DARF_RC7(x) (((x) & 0x1F) << 16) +#define _DARF_RC8(x) (((x) & 0x1F) << 24) + +#define _RARF_RC1(x) ((x) & 0x1F) +#define _RARF_RC2(x) (((x) & 0x1F) << 8) +#define _RARF_RC3(x) (((x) & 0x1F) << 16) +#define _RARF_RC4(x) (((x) & 0x1F) << 24) +#define _RARF_RC5(x) ((x) & 0x1F) +#define _RARF_RC6(x) (((x) & 0x1F) << 8) +#define _RARF_RC7(x) (((x) & 0x1F) << 16) +#define _RARF_RC8(x) (((x) & 0x1F) << 24) + +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + +#define _AIFS(x) (x) +#define _ECW_MAX_MIN(x) ((x) << 8) +#define _TXOP_LIMIT(x) ((x) << 16) + +#define _BCNIFS(x) ((x) & 0xFF) +#define _BCNECW(x) ((((x) & 0xF)) << 8) + +#define _LRL(x) ((x) & 0x3F) +#define _SRL(x) (((x) & 0x3F) << 8) + +#define _SIFS_CCK_CTX(x) ((x) & 0xFF) +#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8) + +#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) +#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8) + +#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) + +#define DIS_EDCA_CNT_DWN BIT(11) + +#define EN_MBSSID BIT(1) +#define EN_TXBCN_RPT BIT(2) +#define EN_BCN_FUNCTION BIT(3) + +#define TSFTR_RST BIT(0) +#define TSFTR1_RST BIT(1) + +#define STOP_BCNQ BIT(6) + +#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) +#define DIS_TSF_UDT0_TEST_CHIP BIT(5) + +#define ACMHW_HWEN BIT(0) +#define ACMHW_BEQEN BIT(1) +#define ACMHW_VIQEN BIT(2) +#define ACMHW_VOQEN BIT(3) +#define ACMHW_BEQSTATUS BIT(4) +#define ACMHW_VIQSTATUS BIT(5) +#define ACMHW_VOQSTATUS BIT(6) + +#define APSDOFF BIT(6) +#define APSDOFF_STATUS BIT(7) + +#define BW_20MHZ BIT(2) + +#define RATE_BITMAP_ALL 0xFFFFF + +#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 + +#define TSFRST BIT(0) +#define DIS_GCLK BIT(1) +#define PAD_SEL BIT(2) +#define PWR_ST BIT(6) +#define PWRBIT_OW_EN BIT(7) +#define ACRC BIT(8) +#define CFENDFORM BIT(9) +#define ICV BIT(10) + +#define AAP BIT(0) +#define APM BIT(1) +#define AM BIT(2) +#define AB BIT(3) +#define ADD3 BIT(4) +#define APWRMGT BIT(5) +#define CBSSID BIT(6) +#define CBSSID_DATA BIT(6) +#define CBSSID_BCN BIT(7) +#define ACRC32 BIT(8) +#define AICV BIT(9) +#define ADF BIT(11) +#define ACF BIT(12) +#define AMF BIT(13) +#define HTC_LOC_CTRL BIT(14) +#define UC_DATA_EN BIT(16) +#define BM_DATA_EN BIT(17) +#define MFBEN BIT(22) +#define LSIGEN BIT(23) +#define ENMBID BIT(24) +#define APP_BASSN BIT(27) +#define APP_PHYSTS BIT(28) +#define APP_ICV BIT(29) +#define APP_MIC BIT(30) +#define APP_FCS BIT(31) + +#define _MIN_SPACE(x) ((x) & 0x7) +#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) + +#define RXERR_TYPE_OFDM_PPDU 0 +#define RXERR_TYPE_OFDM_FALSE_ALARM 1 +#define RXERR_TYPE_OFDM_MPDU_OK 2 +#define RXERR_TYPE_OFDM_MPDU_FAIL 3 +#define RXERR_TYPE_CCK_PPDU 4 +#define RXERR_TYPE_CCK_FALSE_ALARM 5 +#define RXERR_TYPE_CCK_MPDU_OK 6 +#define RXERR_TYPE_CCK_MPDU_FAIL 7 +#define RXERR_TYPE_HT_PPDU 8 +#define RXERR_TYPE_HT_FALSE_ALARM 9 +#define RXERR_TYPE_HT_MPDU_TOTAL 10 +#define RXERR_TYPE_HT_MPDU_OK 11 +#define RXERR_TYPE_HT_MPDU_FAIL 12 +#define RXERR_TYPE_RX_FULL_DROP 15 + +#define RXERR_COUNTER_MASK 0xFFFFF +#define RXERR_RPT_RST BIT(27) +#define _RXERR_RPT_SEL(type) ((type) << 28) + +#define SCR_TXUSEDK BIT(0) +#define SCR_RXUSEDK BIT(1) +#define SCR_TXENCENABLE BIT(2) +#define SCR_RXDECENABLE BIT(3) +#define SCR_SKBYA2 BIT(4) +#define SCR_NOSKMC BIT(5) +#define SCR_TXBCUSEDK BIT(6) +#define SCR_RXBCUSEDK BIT(7) + +#define XCLK_VLD BIT(0) +#define ACLK_VLD BIT(1) +#define UCLK_VLD BIT(2) +#define PCLK_VLD BIT(3) +#define PCIRSTB BIT(4) +#define V15_VLD BIT(5) +#define TRP_B15V_EN BIT(7) +#define SIC_IDLE BIT(8) +#define BD_MAC2 BIT(9) +#define BD_MAC1 BIT(10) +#define IC_MACPHY_MODE BIT(11) +#define BT_FUNC BIT(16) +#define VENDOR_ID BIT(19) +#define PAD_HWPD_IDN BIT(22) +#define TRP_VAUX_EN BIT(23) +#define TRP_BT_EN BIT(24) +#define BD_PKG_SEL BIT(25) +#define BD_HCI_SEL BIT(26) +#define TYPE_ID BIT(27) + +#define USB_IS_HIGH_SPEED 0 +#define USB_IS_FULL_SPEED 1 +#define USB_SPEED_MASK BIT(5) + +#define USB_NORMAL_SIE_EP_MASK 0xF +#define USB_NORMAL_SIE_EP_SHIFT 4 + +#define USB_TEST_EP_MASK 0x30 +#define USB_TEST_EP_SHIFT 4 + +#define USB_AGG_EN BIT(3) + +#define MAC_ADDR_LEN 6 +#define LAST_ENTRY_OF_TX_PKT_BUFFER 175/*255 88e*/ + +#define POLLING_LLT_THRESHOLD 20 +#define POLLING_READY_TIMEOUT_COUNT 3000 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) +#define EPROM_CMD_CONFIG 0x3 +#define EPROM_CMD_LOAD 1 + +#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE + +#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) + +#define RPMAC_RESET 0x100 +#define RPMAC_TXSTART 0x104 +#define RPMAC_TXLEGACYSIG 0x108 +#define RPMAC_TXHTSIG1 0x10c +#define RPMAC_TXHTSIG2 0x110 +#define RPMAC_PHYDEBUG 0x114 +#define RPMAC_TXPACKETNUM 0x118 +#define RPMAC_TXIDLE 0x11c +#define RPMAC_TXMACHEADER0 0x120 +#define RPMAC_TXMACHEADER1 0x124 +#define RPMAC_TXMACHEADER2 0x128 +#define RPMAC_TXMACHEADER3 0x12c +#define RPMAC_TXMACHEADER4 0x130 +#define RPMAC_TXMACHEADER5 0x134 +#define RPMAC_TXDADATYPE 0x138 +#define RPMAC_TXRANDOMSEED 0x13c +#define RPMAC_CCKPLCPPREAMBLE 0x140 +#define RPMAC_CCKPLCPHEADER 0x144 +#define RPMAC_CCKCRC16 0x148 +#define RPMAC_OFDMRXCRC32OK 0x170 +#define RPMAC_OFDMRXCRC32ER 0x174 +#define RPMAC_OFDMRXPARITYER 0x178 +#define RPMAC_OFDMRXCRC8ER 0x17c +#define RPMAC_CCKCRXRC16ER 0x180 +#define RPMAC_CCKCRXRC32ER 0x184 +#define RPMAC_CCKCRXRC32OK 0x188 +#define RPMAC_TXSTATUS 0x18c + +#define RFPGA0_RFMOD 0x800 + +#define RFPGA0_TXINFO 0x804 +#define RFPGA0_PSDFUNCTION 0x808 + +#define RFPGA0_TXGAINSTAGE 0x80c + +#define RFPGA0_RFTIMING1 0x810 +#define RFPGA0_RFTIMING2 0x814 + +#define RFPGA0_XA_HSSIPARAMETER1 0x820 +#define RFPGA0_XA_HSSIPARAMETER2 0x824 +#define RFPGA0_XB_HSSIPARAMETER1 0x828 +#define RFPGA0_XB_HSSIPARAMETER2 0x82c + +#define RFPGA0_XA_LSSIPARAMETER 0x840 +#define RFPGA0_XB_LSSIPARAMETER 0x844 + +#define RFPGA0_RFWAKEUPPARAMETER 0x850 +#define RFPGA0_RFSLEEPUPPARAMETER 0x854 + +#define RFPGA0_XAB_SWITCHCONTROL 0x858 +#define RFPGA0_XCD_SWITCHCONTROL 0x85c + +#define RFPGA0_XA_RFINTERFACEOE 0x860 +#define RFPGA0_XB_RFINTERFACEOE 0x864 + +#define RFPGA0_XAB_RFINTERFACESW 0x870 +#define RFPGA0_XCD_RFINTERFACESW 0x874 + +#define RFPGA0_XAB_RFPARAMETER 0x878 +#define RFPGA0_XCD_RFPARAMETER 0x87c + +#define RFPGA0_ANALOGPARAMETER1 0x880 +#define RFPGA0_ANALOGPARAMETER2 0x884 +#define RFPGA0_ANALOGPARAMETER3 0x888 +#define RFPGA0_ANALOGPARAMETER4 0x88c + +#define RFPGA0_XA_LSSIREADBACK 0x8a0 +#define RFPGA0_XB_LSSIREADBACK 0x8a4 +#define RFPGA0_XC_LSSIREADBACK 0x8a8 +#define RFPGA0_XD_LSSIREADBACK 0x8ac + +#define RFPGA0_PSDREPORT 0x8b4 +#define TRANSCEIVEA_HSPI_READBACK 0x8b8 +#define TRANSCEIVEB_HSPI_READBACK 0x8bc +#define REG_SC_CNT 0x8c4 +#define RFPGA0_XAB_RFINTERFACERB 0x8e0 +#define RFPGA0_XCD_RFINTERFACERB 0x8e4 + +#define RFPGA1_RFMOD 0x900 + +#define RFPGA1_TXBLOCK 0x904 +#define RFPGA1_DEBUGSELECT 0x908 +#define RFPGA1_TXINFO 0x90c + +#define RCCK0_SYSTEM 0xa00 + +#define RCCK0_AFESETTING 0xa04 +#define RCCK0_CCA 0xa08 + +#define RCCK0_RXAGC1 0xa0c +#define RCCK0_RXAGC2 0xa10 + +#define RCCK0_RXHP 0xa14 + +#define RCCK0_DSPPARAMETER1 0xa18 +#define RCCK0_DSPPARAMETER2 0xa1c + +#define RCCK0_TXFILTER1 0xa20 +#define RCCK0_TXFILTER2 0xa24 +#define RCCK0_DEBUGPORT 0xa28 +#define RCCK0_FALSEALARMREPORT 0xa2c +#define RCCK0_TRSSIREPORT 0xa50 +#define RCCK0_RXREPORT 0xa54 +#define RCCK0_FACOUNTERLOWER 0xa5c +#define RCCK0_FACOUNTERUPPER 0xa58 +#define RCCK0_CCA_CNT 0xa60 + +/* PageB(0xB00) */ +#define RPDP_ANTA 0xb00 +#define RPDP_ANTA_4 0xb04 +#define RPDP_ANTA_8 0xb08 +#define RPDP_ANTA_C 0xb0c +#define RPDP_ANTA_10 0xb10 +#define RPDP_ANTA_14 0xb14 +#define RPDP_ANTA_18 0xb18 +#define RPDP_ANTA_1C 0xb1c +#define RPDP_ANTA_20 0xb20 +#define RPDP_ANTA_24 0xb24 + +#define RCONFIG_PMPD_ANTA 0xb28 +#define RCONFIG_ram64x16 0xb2c + +#define RBNDA 0xb30 +#define RHSSIPAR 0xb34 + +#define RCONFIG_ANTA 0xb68 +#define RCONFIG_ANTB 0xb6c + +#define RPDP_ANTB 0xb70 +#define RPDP_ANTB_4 0xb74 +#define RPDP_ANTB_8 0xb78 +#define RPDP_ANTB_C 0xb7c +#define RPDP_ANTB_10 0xb80 +#define RPDP_ANTB_14 0xb84 +#define RPDP_ANTB_18 0xb88 +#define RPDP_ANTB_1C 0xb8c +#define RPDP_ANTB_20 0xb90 +#define RPDP_ANTB_24 0xb94 + +#define RCONFIG_PMPD_ANTB 0xb98 + +#define RBNDB 0xba0 + +#define RAPK 0xbd8 +#define RPM_RX0_ANTA 0xbdc +#define RPM_RX1_ANTA 0xbe0 +#define RPM_RX2_ANTA 0xbe4 +#define RPM_RX3_ANTA 0xbe8 +#define RPM_RX0_ANTB 0xbec +#define RPM_RX1_ANTB 0xbf0 +#define RPM_RX2_ANTB 0xbf4 +#define RPM_RX3_ANTB 0xbf8 + +/*Page C*/ +#define ROFDM0_LSTF 0xc00 + +#define ROFDM0_TRXPATHENABLE 0xc04 +#define ROFDM0_TRMUXPAR 0xc08 +#define ROFDM0_TRSWISOLATION 0xc0c + +#define ROFDM0_XARXAFE 0xc10 +#define ROFDM0_XARXIQIMBALANCE 0xc14 +#define ROFDM0_XBRXAFE 0xc18 +#define ROFDM0_XBRXIQIMBALANCE 0xc1c +#define ROFDM0_XCRXAFE 0xc20 +#define ROFDM0_XCRXIQIMBANLANCE 0xc24 +#define ROFDM0_XDRXAFE 0xc28 +#define ROFDM0_XDRXIQIMBALANCE 0xc2c + +#define ROFDM0_RXDETECTOR1 0xc30 +#define ROFDM0_RXDETECTOR2 0xc34 +#define ROFDM0_RXDETECTOR3 0xc38 +#define ROFDM0_RXDETECTOR4 0xc3c + +#define ROFDM0_RXDSP 0xc40 +#define ROFDM0_CFOANDDAGC 0xc44 +#define ROFDM0_CCADROPTHRESHOLD 0xc48 +#define ROFDM0_ECCATHRESHOLD 0xc4c + +#define ROFDM0_XAAGCCORE1 0xc50 +#define ROFDM0_XAAGCCORE2 0xc54 +#define ROFDM0_XBAGCCORE1 0xc58 +#define ROFDM0_XBAGCCORE2 0xc5c +#define ROFDM0_XCAGCCORE1 0xc60 +#define ROFDM0_XCAGCCORE2 0xc64 +#define ROFDM0_XDAGCCORE1 0xc68 +#define ROFDM0_XDAGCCORE2 0xc6c + +#define ROFDM0_AGCPARAMETER1 0xc70 +#define ROFDM0_AGCPARAMETER2 0xc74 +#define ROFDM0_AGCRSSITABLE 0xc78 +#define ROFDM0_HTSTFAGC 0xc7c + +#define ROFDM0_XATXIQIMBALANCE 0xc80 +#define ROFDM0_XATXAFE 0xc84 +#define ROFDM0_XBTXIQIMBALANCE 0xc88 +#define ROFDM0_XBTXAFE 0xc8c +#define ROFDM0_XCTXIQIMBALANCE 0xc90 +#define ROFDM0_XCTXAFE 0xc94 +#define ROFDM0_XDTXIQIMBALANCE 0xc98 +#define ROFDM0_XDTXAFE 0xc9c + +#define ROFDM0_RXIQEXTANTA 0xca0 +#define ROFDM0_TXCOEFF1 0xca4 +#define ROFDM0_TXCOEFF2 0xca8 +#define ROFDM0_TXCOEFF3 0xcac +#define ROFDM0_TXCOEFF4 0xcb0 +#define ROFDM0_TXCOEFF5 0xcb4 +#define ROFDM0_TXCOEFF6 0xcb8 + +#define ROFDM0_RXHPPARAMETER 0xce0 +#define ROFDM0_TXPSEUDONOISEWGT 0xce4 +#define ROFDM0_FRAMESYNC 0xcf0 +#define ROFDM0_DFSREPORT 0xcf4 + +#define ROFDM1_LSTF 0xd00 +#define ROFDM1_TRXPATHENABLE 0xd04 + +#define ROFDM1_CF0 0xd08 +#define ROFDM1_CSI1 0xd10 +#define ROFDM1_SBD 0xd14 +#define ROFDM1_CSI2 0xd18 +#define ROFDM1_CFOTRACKING 0xd2c +#define ROFDM1_TRXMESAURE1 0xd34 +#define ROFDM1_INTFDET 0xd3c +#define ROFDM1_PSEUDONOISESTATEAB 0xd50 +#define ROFDM1_PSEUDONOISESTATECD 0xd54 +#define ROFDM1_RXPSEUDONOISEWGT 0xd58 + +#define ROFDM_PHYCOUNTER1 0xda0 +#define ROFDM_PHYCOUNTER2 0xda4 +#define ROFDM_PHYCOUNTER3 0xda8 + +#define ROFDM_SHORTCFOAB 0xdac +#define ROFDM_SHORTCFOCD 0xdb0 +#define ROFDM_LONGCFOAB 0xdb4 +#define ROFDM_LONGCFOCD 0xdb8 +#define ROFDM_TAILCF0AB 0xdbc +#define ROFDM_TAILCF0CD 0xdc0 +#define ROFDM_PWMEASURE1 0xdc4 +#define ROFDM_PWMEASURE2 0xdc8 +#define ROFDM_BWREPORT 0xdcc +#define ROFDM_AGCREPORT 0xdd0 +#define ROFDM_RXSNR 0xdd4 +#define ROFDM_RXEVMCSI 0xdd8 +#define ROFDM_SIGREPORT 0xddc + +#define RTXAGC_A_RATE18_06 0xe00 +#define RTXAGC_A_RATE54_24 0xe04 +#define RTXAGC_A_CCK1_MCS32 0xe08 +#define RTXAGC_A_MCS03_MCS00 0xe10 +#define RTXAGC_A_MCS07_MCS04 0xe14 +#define RTXAGC_A_MCS11_MCS08 0xe18 +#define RTXAGC_A_MCS15_MCS12 0xe1c + +#define RTXAGC_B_RATE18_06 0x830 +#define RTXAGC_B_RATE54_24 0x834 +#define RTXAGC_B_CCK1_55_MCS32 0x838 +#define RTXAGC_B_MCS03_MCS00 0x83c +#define RTXAGC_B_MCS07_MCS04 0x848 +#define RTXAGC_B_MCS11_MCS08 0x84c +#define RTXAGC_B_MCS15_MCS12 0x868 +#define RTXAGC_B_CCK11_A_CCK2_11 0x86c + +#define RFPGA0_IQK 0xe28 +#define RTX_IQK_TONE_A 0xe30 +#define RRX_IQK_TONE_A 0xe34 +#define RTX_IQK_PI_A 0xe38 +#define RRX_IQK_PI_A 0xe3c + +#define RTX_IQK 0xe40 +#define RRX_IQK 0xe44 +#define RIQK_AGC_PTS 0xe48 +#define RIQK_AGC_RSP 0xe4c +#define RTX_IQK_TONE_B 0xe50 +#define RRX_IQK_TONE_B 0xe54 +#define RTX_IQK_PI_B 0xe58 +#define RRX_IQK_PI_B 0xe5c +#define RIQK_AGC_CONT 0xe60 + +#define RBLUE_TOOTH 0xe6c +#define RRX_WAIT_CCA 0xe70 +#define RTX_CCK_RFON 0xe74 +#define RTX_CCK_BBON 0xe78 +#define RTX_OFDM_RFON 0xe7c +#define RTX_OFDM_BBON 0xe80 +#define RTX_TO_RX 0xe84 +#define RTX_TO_TX 0xe88 +#define RRX_CCK 0xe8c + +#define RTX_POWER_BEFORE_IQK_A 0xe94 +#define RTX_POWER_AFTER_IQK_A 0xe9c + +#define RRX_POWER_BEFORE_IQK_A 0xea0 +#define RRX_POWER_BEFORE_IQK_A_2 0xea4 +#define RRX_POWER_AFTER_IQK_A 0xea8 +#define RRX_POWER_AFTER_IQK_A_2 0xeac + +#define RTX_POWER_BEFORE_IQK_B 0xeb4 +#define RTX_POWER_AFTER_IQK_B 0xebc + +#define RRX_POWER_BEFORE_IQK_B 0xec0 +#define RRX_POWER_BEFORE_IQK_B_2 0xec4 +#define RRX_POWER_AFTER_IQK_B 0xec8 +#define RRX_POWER_AFTER_IQK_B_2 0xecc + +#define RRX_OFDM 0xed0 +#define RRX_WAIT_RIFS 0xed4 +#define RRX_TO_RX 0xed8 +#define RSTANDBY 0xedc +#define RSLEEP 0xee0 +#define RPMPD_ANAEN 0xeec + +#define RZEBRA1_HSSIENABLE 0x0 +#define RZEBRA1_TRXENABLE1 0x1 +#define RZEBRA1_TRXENABLE2 0x2 +#define RZEBRA1_AGC 0x4 +#define RZEBRA1_CHARGEPUMP 0x5 +#define RZEBRA1_CHANNEL 0x7 + +#define RZEBRA1_TXGAIN 0x8 +#define RZEBRA1_TXLPF 0x9 +#define RZEBRA1_RXLPF 0xb +#define RZEBRA1_RXHPFCORNER 0xc + +#define RGLOBALCTRL 0 +#define RRTL8256_TXLPF 19 +#define RRTL8256_RXLPF 11 +#define RRTL8258_TXLPF 0x11 +#define RRTL8258_RXLPF 0x13 +#define RRTL8258_RSSILPF 0xa + +#define RF_AC 0x00 + +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_POW_TRSW 0x05 + +#define RF_GAIN_RX 0x06 +#define RF_GAIN_TX 0x07 + +#define RF_TXM_IDAC 0x08 +#define RF_BS_IQGEN 0x0F + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 + +#define RF_RX_AGC_HP 0x12 +#define RF_TX_AGC 0x13 +#define RF_BIAS 0x14 +#define RF_IPA 0x15 +#define RF_POW_ABILITY 0x17 +#define RF_MODE_AG 0x18 +#define RRFCHANNEL 0x18 +#define RF_CHNLBW 0x18 +#define RF_TOP 0x19 + +#define RF_RX_G1 0x1A +#define RF_RX_G2 0x1B + +#define RF_RX_BB2 0x1C +#define RF_RX_BB1 0x1D + +#define RF_RCK1 0x1E +#define RF_RCK2 0x1F + +#define RF_TX_G1 0x20 +#define RF_TX_G2 0x21 +#define RF_TX_G3 0x22 + +#define RF_TX_BB1 0x23 +#define RF_T_METER 0x42 + +#define RF_SYN_G1 0x25 +#define RF_SYN_G2 0x26 +#define RF_SYN_G3 0x27 +#define RF_SYN_G4 0x28 +#define RF_SYN_G5 0x29 +#define RF_SYN_G6 0x2A +#define RF_SYN_G7 0x2B +#define RF_SYN_G8 0x2C + +#define RF_RCK_OS 0x30 +#define RF_TXPA_G1 0x31 +#define RF_TXPA_G2 0x32 +#define RF_TXPA_G3 0x33 + +#define RF_TX_BIAS_A 0x35 +#define RF_TX_BIAS_D 0x36 +#define RF_LOBF_9 0x38 +#define RF_RXRF_A3 0x3C +#define RF_TRSW 0x3F + +#define RF_TXRF_A2 0x41 +#define RF_TXPA_G4 0x46 +#define RF_TXPA_A4 0x4B + +#define RF_WE_LUT 0xEF + +#define BBBRESETB 0x100 +#define BGLOBALRESETB 0x200 +#define BOFDMTXSTART 0x4 +#define BCCKTXSTART 0x8 +#define BCRC32DEBUG 0x100 +#define BPMACLOOPBACK 0x10 +#define BTXLSIG 0xffffff +#define BOFDMTXRATE 0xf +#define BOFDMTXRESERVED 0x10 +#define BOFDMTXLENGTH 0x1ffe0 +#define BOFDMTXPARITY 0x20000 +#define BTXHTSIG1 0xffffff +#define BTXHTMCSRATE 0x7f +#define BTXHTBW 0x80 +#define BTXHTLENGTH 0xffff00 +#define BTXHTSIG2 0xffffff +#define BTXHTSMOOTHING 0x1 +#define BTXHTSOUNDING 0x2 +#define BTXHTRESERVED 0x4 +#define BTXHTAGGREATION 0x8 +#define BTXHTSTBC 0x30 +#define BTXHTADVANCECODING 0x40 +#define BTXHTSHORTGI 0x80 +#define BTXHTNUMBERHT_LTF 0x300 +#define BTXHTCRC8 0x3fc00 +#define BCOUNTERRESET 0x10000 +#define BNUMOFOFDMTX 0xffff +#define BNUMOFCCKTX 0xffff0000 +#define BTXIDLEINTERVAL 0xffff +#define BOFDMSERVICE 0xffff0000 +#define BTXMACHEADER 0xffffffff +#define BTXDATAINIT 0xff +#define BTXHTMODE 0x100 +#define BTXDATATYPE 0x30000 +#define BTXRANDOMSEED 0xffffffff +#define BCCKTXPREAMBLE 0x1 +#define BCCKTXSFD 0xffff0000 +#define BCCKTXSIG 0xff +#define BCCKTXSERVICE 0xff00 +#define BCCKLENGTHEXT 0x8000 +#define BCCKTXLENGHT 0xffff0000 +#define BCCKTXCRC16 0xffff +#define BCCKTXSTATUS 0x1 +#define BOFDMTXSTATUS 0x2 +#define IS_BB_REG_OFFSET_92S(_offset) \ + ((_offset >= 0x800) && (_offset <= 0xfff)) + +#define BRFMOD 0x1 +#define BJAPANMODE 0x2 +#define BCCKTXSC 0x30 +#define BCCKEN 0x1000000 +#define BOFDMEN 0x2000000 + +#define BOFDMRXADCPHASE 0x10000 +#define BOFDMTXDACPHASE 0x40000 +#define BXATXAGC 0x3f + +#define BXBTXAGC 0xf00 +#define BXCTXAGC 0xf000 +#define BXDTXAGC 0xf0000 + +#define BPASTART 0xf0000000 +#define BTRSTART 0x00f00000 +#define BRFSTART 0x0000f000 +#define BBBSTART 0x000000f0 +#define BBBCCKSTART 0x0000000f +#define BPAEND 0xf +#define BTREND 0x0f000000 +#define BRFEND 0x000f0000 +#define BCCAMASK 0x000000f0 +#define BR2RCCAMASK 0x00000f00 +#define BHSSI_R2TDELAY 0xf8000000 +#define BHSSI_T2RDELAY 0xf80000 +#define BCONTXHSSI 0x400 +#define BIGFROMCCK 0x200 +#define BAGCADDRESS 0x3f +#define BRXHPTX 0x7000 +#define BRXHP2RX 0x38000 +#define BRXHPCCKINI 0xc0000 +#define BAGCTXCODE 0xc00000 +#define BAGCRXCODE 0x300000 + +#define B3WIREDATALENGTH 0x800 +#define B3WIREADDREAALENGTH 0x400 + +#define B3WIRERFPOWERDOWN 0x1 +#define B5GPAPEPOLARITY 0x40000000 +#define B2GPAPEPOLARITY 0x80000000 +#define BRFSW_TXDEFAULTANT 0x3 +#define BRFSW_TXOPTIONANT 0x30 +#define BRFSW_RXDEFAULTANT 0x300 +#define BRFSW_RXOPTIONANT 0x3000 +#define BRFSI_3WIREDATA 0x1 +#define BRFSI_3WIRECLOCK 0x2 +#define BRFSI_3WIRELOAD 0x4 +#define BRFSI_3WIRERW 0x8 +#define BRFSI_3WIRE 0xf + +#define BRFSI_RFENV 0x10 + +#define BRFSI_TRSW 0x20 +#define BRFSI_TRSWB 0x40 +#define BRFSI_ANTSW 0x100 +#define BRFSI_ANTSWB 0x200 +#define BRFSI_PAPE 0x400 +#define BRFSI_PAPE5G 0x800 +#define BBANDSELECT 0x1 +#define BHTSIG2_GI 0x80 +#define BHTSIG2_SMOOTHING 0x01 +#define BHTSIG2_SOUNDING 0x02 +#define BHTSIG2_AGGREATON 0x08 +#define BHTSIG2_STBC 0x30 +#define BHTSIG2_ADVCODING 0x40 +#define BHTSIG2_NUMOFHTLTF 0x300 +#define BHTSIG2_CRC8 0x3fc +#define BHTSIG1_MCS 0x7f +#define BHTSIG1_BANDWIDTH 0x80 +#define BHTSIG1_HTLENGTH 0xffff +#define BLSIG_RATE 0xf +#define BLSIG_RESERVED 0x10 +#define BLSIG_LENGTH 0x1fffe +#define BLSIG_PARITY 0x20 +#define BCCKRXPHASE 0x4 + +#define BLSSIREADADDRESS 0x7f800000 +#define BLSSIREADEDGE 0x80000000 + +#define BLSSIREADBACKDATA 0xfffff + +#define BLSSIREADOKFLAG 0x1000 +#define BCCKSAMPLERATE 0x8 +#define BREGULATOR0STANDBY 0x1 +#define BREGULATORPLLSTANDBY 0x2 +#define BREGULATOR1STANDBY 0x4 +#define BPLLPOWERUP 0x8 +#define BDPLLPOWERUP 0x10 +#define BDA10POWERUP 0x20 +#define BAD7POWERUP 0x200 +#define BDA6POWERUP 0x2000 +#define BXTALPOWERUP 0x4000 +#define B40MDCLKPOWERUP 0x8000 +#define BDA6DEBUGMODE 0x20000 +#define BDA6SWING 0x380000 + +#define BADCLKPHASE 0x4000000 +#define B80MCLKDELAY 0x18000000 +#define BAFEWATCHDOGENABLE 0x20000000 + +#define BXTALCAP01 0xc0000000 +#define BXTALCAP23 0x3 +#define BXTALCAP92X 0x0f000000 +#define BXTALCAP 0x0f000000 + +#define BINTDIFCLKENABLE 0x400 +#define BEXTSIGCLKENABLE 0x800 +#define BBANDGAP_MBIAS_POWERUP 0x10000 +#define BAD11SH_GAIN 0xc0000 +#define BAD11NPUT_RANGE 0x700000 +#define BAD110P_CURRENT 0x3800000 +#define BLPATH_LOOPBACK 0x4000000 +#define BQPATH_LOOPBACK 0x8000000 +#define BAFE_LOOPBACK 0x10000000 +#define BDA10_SWING 0x7e0 +#define BDA10_REVERSE 0x800 +#define BDA_CLK_SOURCE 0x1000 +#define BDA7INPUT_RANGE 0x6000 +#define BDA7_GAIN 0x38000 +#define BDA7OUTPUT_CM_MODE 0x40000 +#define BDA7INPUT_CM_MODE 0x380000 +#define BDA7CURRENT 0xc00000 +#define BREGULATOR_ADJUST 0x7000000 +#define BAD11POWERUP_ATTX 0x1 +#define BDA10PS_ATTX 0x10 +#define BAD11POWERUP_ATRX 0x100 +#define BDA10PS_ATRX 0x1000 +#define BCCKRX_AGC_FORMAT 0x200 +#define BPSDFFT_SAMPLE_POINT 0xc000 +#define BPSD_AVERAGE_NUM 0x3000 +#define BIQPATH_CONTROL 0xc00 +#define BPSD_FREQ 0x3ff +#define BPSD_ANTENNA_PATH 0x30 +#define BPSD_IQ_SWITCH 0x40 +#define BPSD_RX_TRIGGER 0x400000 +#define BPSD_TX_TRIGGER 0x80000000 +#define BPSD_SINE_TONE_SCALE 0x7f000000 +#define BPSD_REPORT 0xffff + +#define BOFDM_TXSC 0x30000000 +#define BCCK_TXON 0x1 +#define BOFDM_TXON 0x2 +#define BDEBUG_PAGE 0xfff +#define BDEBUG_ITEM 0xff +#define BANTL 0x10 +#define BANT_NONHT 0x100 +#define BANT_HT1 0x1000 +#define BANT_HT2 0x10000 +#define BANT_HT1S1 0x100000 +#define BANT_NONHTS1 0x1000000 + +#define BCCK_BBMODE 0x3 +#define BCCK_TXPOWERSAVING 0x80 +#define BCCK_RXPOWERSAVING 0x40 + +#define BCCK_SIDEBAND 0x10 + +#define BCCK_SCRAMBLE 0x8 +#define BCCK_ANTDIVERSITY 0x8000 +#define BCCK_CARRIER_RECOVERY 0x4000 +#define BCCK_TXRATE 0x3000 +#define BCCK_DCCANCEL 0x0800 +#define BCCK_ISICANCEL 0x0400 +#define BCCK_MATCH_FILTER 0x0200 +#define BCCK_EQUALIZER 0x0100 +#define BCCK_PREAMBLE_DETECT 0x800000 +#define BCCK_FAST_FALSECCA 0x400000 +#define BCCK_CH_ESTSTART 0x300000 +#define BCCK_CCA_COUNT 0x080000 +#define BCCK_CS_LIM 0x070000 +#define BCCK_BIST_MODE 0x80000000 +#define BCCK_CCAMASK 0x40000000 +#define BCCK_TX_DAC_PHASE 0x4 +#define BCCK_RX_ADC_PHASE 0x20000000 +#define BCCKR_CP_MODE 0x0100 +#define BCCK_TXDC_OFFSET 0xf0 +#define BCCK_RXDC_OFFSET 0xf +#define BCCK_CCA_MODE 0xc000 +#define BCCK_FALSECS_LIM 0x3f00 +#define BCCK_CS_RATIO 0xc00000 +#define BCCK_CORGBIT_SEL 0x300000 +#define BCCK_PD_LIM 0x0f0000 +#define BCCK_NEWCCA 0x80000000 +#define BCCK_RXHP_OF_IG 0x8000 +#define BCCK_RXIG 0x7f00 +#define BCCK_LNA_POLARITY 0x800000 +#define BCCK_RX1ST_BAIN 0x7f0000 +#define BCCK_RF_EXTEND 0x20000000 +#define BCCK_RXAGC_SATLEVEL 0x1f000000 +#define BCCK_RXAGC_SATCOUNT 0xe0 +#define BCCKRXRFSETTLE 0x1f +#define BCCK_FIXED_RXAGC 0x8000 +#define BCCK_ANTENNA_POLARITY 0x2000 +#define BCCK_TXFILTER_TYPE 0x0c00 +#define BCCK_RXAGC_REPORTTYPE 0x0300 +#define BCCK_RXDAGC_EN 0x80000000 +#define BCCK_RXDAGC_PERIOD 0x20000000 +#define BCCK_RXDAGC_SATLEVEL 0x1f000000 +#define BCCK_TIMING_RECOVERY 0x800000 +#define BCCK_TXC0 0x3f0000 +#define BCCK_TXC1 0x3f000000 +#define BCCK_TXC2 0x3f +#define BCCK_TXC3 0x3f00 +#define BCCK_TXC4 0x3f0000 +#define BCCK_TXC5 0x3f000000 +#define BCCK_TXC6 0x3f +#define BCCK_TXC7 0x3f00 +#define BCCK_DEBUGPORT 0xff0000 +#define BCCK_DAC_DEBUG 0x0f000000 +#define BCCK_FALSEALARM_ENABLE 0x8000 +#define BCCK_FALSEALARM_READ 0x4000 +#define BCCK_TRSSI 0x7f +#define BCCK_RXAGC_REPORT 0xfe +#define BCCK_RXREPORT_ANTSEL 0x80000000 +#define BCCK_RXREPORT_MFOFF 0x40000000 +#define BCCK_RXREPORT_SQLOSS 0x20000000 +#define BCCK_RXREPORT_PKTLOSS 0x10000000 +#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 +#define BCCK_RXREPORT_RATEERROR 0x04000000 +#define BCCK_RXREPORT_RXRATE 0x03000000 +#define BCCK_RXFA_COUNTER_LOWER 0xff +#define BCCK_RXFA_COUNTER_UPPER 0xff000000 +#define BCCK_RXHPAGC_START 0xe000 +#define BCCK_RXHPAGC_FINAL 0x1c00 +#define BCCK_RXFALSEALARM_ENABLE 0x8000 +#define BCCK_FACOUNTER_FREEZE 0x4000 +#define BCCK_TXPATH_SEL 0x10000000 +#define BCCK_DEFAULT_RXPATH 0xc000000 +#define BCCK_OPTION_RXPATH 0x3000000 + +#define BNUM_OFSTF 0x3 +#define BSHIFT_L 0xc0 +#define BGI_TH 0xc +#define BRXPATH_A 0x1 +#define BRXPATH_B 0x2 +#define BRXPATH_C 0x4 +#define BRXPATH_D 0x8 +#define BTXPATH_A 0x1 +#define BTXPATH_B 0x2 +#define BTXPATH_C 0x4 +#define BTXPATH_D 0x8 +#define BTRSSI_FREQ 0x200 +#define BADC_BACKOFF 0x3000 +#define BDFIR_BACKOFF 0xc000 +#define BTRSSI_LATCH_PHASE 0x10000 +#define BRX_LDC_OFFSET 0xff +#define BRX_QDC_OFFSET 0xff00 +#define BRX_DFIR_MODE 0x1800000 +#define BRX_DCNF_TYPE 0xe000000 +#define BRXIQIMB_A 0x3ff +#define BRXIQIMB_B 0xfc00 +#define BRXIQIMB_C 0x3f0000 +#define BRXIQIMB_D 0xffc00000 +#define BDC_DC_NOTCH 0x60000 +#define BRXNB_NOTCH 0x1f000000 +#define BPD_TH 0xf +#define BPD_TH_OPT2 0xc000 +#define BPWED_TH 0x700 +#define BIFMF_WIN_L 0x800 +#define BPD_OPTION 0x1000 +#define BMF_WIN_L 0xe000 +#define BBW_SEARCH_L 0x30000 +#define BWIN_ENH_L 0xc0000 +#define BBW_TH 0x700000 +#define BED_TH2 0x3800000 +#define BBW_OPTION 0x4000000 +#define BRADIO_TH 0x18000000 +#define BWINDOW_L 0xe0000000 +#define BSBD_OPTION 0x1 +#define BFRAME_TH 0x1c +#define BFS_OPTION 0x60 +#define BDC_SLOPE_CHECK 0x80 +#define BFGUARD_COUNTER_DC_L 0xe00 +#define BFRAME_WEIGHT_SHORT 0x7000 +#define BSUB_TUNE 0xe00000 +#define BFRAME_DC_LENGTH 0xe000000 +#define BSBD_START_OFFSET 0x30000000 +#define BFRAME_TH_2 0x7 +#define BFRAME_GI2_TH 0x38 +#define BGI2_SYNC_EN 0x40 +#define BSARCH_SHORT_EARLY 0x300 +#define BSARCH_SHORT_LATE 0xc00 +#define BSARCH_GI2_LATE 0x70000 +#define BCFOANTSUM 0x1 +#define BCFOACC 0x2 +#define BCFOSTARTOFFSET 0xc +#define BCFOLOOPBACK 0x70 +#define BCFOSUMWEIGHT 0x80 +#define BDAGCENABLE 0x10000 +#define BTXIQIMB_A 0x3ff +#define BTXIQIMB_b 0xfc00 +#define BTXIQIMB_C 0x3f0000 +#define BTXIQIMB_D 0xffc00000 +#define BTXIDCOFFSET 0xff +#define BTXIQDCOFFSET 0xff00 +#define BTXDFIRMODE 0x10000 +#define BTXPESUDO_NOISEON 0x4000000 +#define BTXPESUDO_NOISE_A 0xff +#define BTXPESUDO_NOISE_B 0xff00 +#define BTXPESUDO_NOISE_C 0xff0000 +#define BTXPESUDO_NOISE_D 0xff000000 +#define BCCA_DROPOPTION 0x20000 +#define BCCA_DROPTHRES 0xfff00000 +#define BEDCCA_H 0xf +#define BEDCCA_L 0xf0 +#define BLAMBDA_ED 0x300 +#define BRX_INITIALGAIN 0x7f +#define BRX_ANTDIV_EN 0x80 +#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 +#define BRX_HIGHPOWER_FLOW 0x8000 +#define BRX_AGC_FREEZE_THRES 0xc0000 +#define BRX_FREEZESTEP_AGC1 0x300000 +#define BRX_FREEZESTEP_AGC2 0xc00000 +#define BRX_FREEZESTEP_AGC3 0x3000000 +#define BRX_FREEZESTEP_AGC0 0xc000000 +#define BRXRSSI_CMP_EN 0x10000000 +#define BRXQUICK_AGCEN 0x20000000 +#define BRXAGC_FREEZE_THRES_MODE 0x40000000 +#define BRX_OVERFLOW_CHECKTYPE 0x80000000 +#define BRX_AGCSHIFT 0x7f +#define BTRSW_TRI_ONLY 0x80 +#define BPOWER_THRES 0x300 +#define BRXAGC_EN 0x1 +#define BRXAGC_TOGETHER_EN 0x2 +#define BRXAGC_MIN 0x4 +#define BRXHP_INI 0x7 +#define BRXHP_TRLNA 0x70 +#define BRXHP_RSSI 0x700 +#define BRXHP_BBP1 0x7000 +#define BRXHP_BBP2 0x70000 +#define BRXHP_BBP3 0x700000 +#define BRSSI_H 0x7f0000 +#define BRSSI_GEN 0x7f000000 +#define BRXSETTLE_TRSW 0x7 +#define BRXSETTLE_LNA 0x38 +#define BRXSETTLE_RSSI 0x1c0 +#define BRXSETTLE_BBP 0xe00 +#define BRXSETTLE_RXHP 0x7000 +#define BRXSETTLE_ANTSW_RSSI 0x38000 +#define BRXSETTLE_ANTSW 0xc0000 +#define BRXPROCESS_TIME_DAGC 0x300000 +#define BRXSETTLE_HSSI 0x400000 +#define BRXPROCESS_TIME_BBPPW 0x800000 +#define BRXANTENNA_POWER_SHIFT 0x3000000 +#define BRSSI_TABLE_SELECT 0xc000000 +#define BRXHP_FINAL 0x7000000 +#define BRXHPSETTLE_BBP 0x7 +#define BRXHTSETTLE_HSSI 0x8 +#define BRXHTSETTLE_RXHP 0x70 +#define BRXHTSETTLE_BBPPW 0x80 +#define BRXHTSETTLE_IDLE 0x300 +#define BRXHTSETTLE_RESERVED 0x1c00 +#define BRXHT_RXHP_EN 0x8000 +#define BRXAGC_FREEZE_THRES 0x30000 +#define BRXAGC_TOGETHEREN 0x40000 +#define BRXHTAGC_MIN 0x80000 +#define BRXHTAGC_EN 0x100000 +#define BRXHTDAGC_EN 0x200000 +#define BRXHT_RXHP_BBP 0x1c00000 +#define BRXHT_RXHP_FINAL 0xe0000000 +#define BRXPW_RADIO_TH 0x3 +#define BRXPW_RADIO_EN 0x4 +#define BRXMF_HOLD 0x3800 +#define BRXPD_DELAY_TH1 0x38 +#define BRXPD_DELAY_TH2 0x1c0 +#define BRXPD_DC_COUNT_MAX 0x600 +#define BRXPD_DELAY_TH 0x8000 +#define BRXPROCESS_DELAY 0xf0000 +#define BRXSEARCHRANGE_GI2_EARLY 0x700000 +#define BRXFRAME_FUARD_COUNTER_L 0x3800000 +#define BRXSGI_GUARD_L 0xc000000 +#define BRXSGI_SEARCH_L 0x30000000 +#define BRXSGI_TH 0xc0000000 +#define BDFSCNT0 0xff +#define BDFSCNT1 0xff00 +#define BDFSFLAG 0xf0000 +#define BMF_WEIGHT_SUM 0x300000 +#define BMINIDX_TH 0x7f000000 +#define BDAFORMAT 0x40000 +#define BTXCH_EMU_ENABLE 0x01000000 +#define BTRSW_ISOLATION_A 0x7f +#define BTRSW_ISOLATION_B 0x7f00 +#define BTRSW_ISOLATION_C 0x7f0000 +#define BTRSW_ISOLATION_D 0x7f000000 +#define BEXT_LNA_GAIN 0x7c00 + +#define BSTBC_EN 0x4 +#define BANTENNA_MAPPING 0x10 +#define BNSS 0x20 +#define BCFO_ANTSUM_ID 0x200 +#define BPHY_COUNTER_RESET 0x8000000 +#define BCFO_REPORT_GET 0x4000000 +#define BOFDM_CONTINUE_TX 0x10000000 +#define BOFDM_SINGLE_CARRIER 0x20000000 +#define BOFDM_SINGLE_TONE 0x40000000 +#define BHT_DETECT 0x100 +#define BCFOEN 0x10000 +#define BCFOVALUE 0xfff00000 +#define BSIGTONE_RE 0x3f +#define BSIGTONE_IM 0x7f00 +#define BCOUNTER_CCA 0xffff +#define BCOUNTER_PARITYFAIL 0xffff0000 +#define BCOUNTER_RATEILLEGAL 0xffff +#define BCOUNTER_CRC8FAIL 0xffff0000 +#define BCOUNTER_MCSNOSUPPORT 0xffff +#define BCOUNTER_FASTSYNC 0xffff +#define BSHORTCFO 0xfff +#define BSHORTCFOT_LENGTH 12 +#define BSHORTCFOF_LENGTH 11 +#define BLONGCFO 0x7ff +#define BLONGCFOT_LENGTH 11 +#define BLONGCFOF_LENGTH 11 +#define BTAILCFO 0x1fff +#define BTAILCFOT_LENGTH 13 +#define BTAILCFOF_LENGTH 12 +#define BNOISE_EN_PWDB 0xffff +#define BCC_POWER_DB 0xffff0000 +#define BMOISE_PWDB 0xffff +#define BPOWERMEAST_LENGTH 10 +#define BPOWERMEASF_LENGTH 3 +#define BRX_HT_BW 0x1 +#define BRXSC 0x6 +#define BRX_HT 0x8 +#define BNB_INTF_DET_ON 0x1 +#define BINTF_WIN_LEN_CFG 0x30 +#define BNB_INTF_TH_CFG 0x1c0 +#define BRFGAIN 0x3f +#define BTABLESEL 0x40 +#define BTRSW 0x80 +#define BRXSNR_A 0xff +#define BRXSNR_B 0xff00 +#define BRXSNR_C 0xff0000 +#define BRXSNR_D 0xff000000 +#define BSNR_EVMT_LENGTH 8 +#define BSNR_EVMF_LENGTH 1 +#define BCSI1ST 0xff +#define BCSI2ND 0xff00 +#define BRXEVM1ST 0xff0000 +#define BRXEVM2ND 0xff000000 +#define BSIGEVM 0xff +#define BPWDB 0xff00 +#define BSGIEN 0x10000 + +#define BSFACTOR_QMA1 0xf +#define BSFACTOR_QMA2 0xf0 +#define BSFACTOR_QMA3 0xf00 +#define BSFACTOR_QMA4 0xf000 +#define BSFACTOR_QMA5 0xf0000 +#define BSFACTOR_QMA6 0xf0000 +#define BSFACTOR_QMA7 0xf00000 +#define BSFACTOR_QMA8 0xf000000 +#define BSFACTOR_QMA9 0xf0000000 +#define BCSI_SCHEME 0x100000 + +#define BNOISE_LVL_TOP_SET 0x3 +#define BCHSMOOTH 0x4 +#define BCHSMOOTH_CFG1 0x38 +#define BCHSMOOTH_CFG2 0x1c0 +#define BCHSMOOTH_CFG3 0xe00 +#define BCHSMOOTH_CFG4 0x7000 +#define BMRCMODE 0x800000 +#define BTHEVMCFG 0x7000000 + +#define BLOOP_FIT_TYPE 0x1 +#define BUPD_CFO 0x40 +#define BUPD_CFO_OFFDATA 0x80 +#define BADV_UPD_CFO 0x100 +#define BADV_TIME_CTRL 0x800 +#define BUPD_CLKO 0x1000 +#define BFC 0x6000 +#define BTRACKING_MODE 0x8000 +#define BPHCMP_ENABLE 0x10000 +#define BUPD_CLKO_LTF 0x20000 +#define BCOM_CH_CFO 0x40000 +#define BCSI_ESTI_MODE 0x80000 +#define BADV_UPD_EQZ 0x100000 +#define BUCHCFG 0x7000000 +#define BUPDEQZ 0x8000000 + +#define BRX_PESUDO_NOISE_ON 0x20000000 +#define BRX_PESUDO_NOISE_A 0xff +#define BRX_PESUDO_NOISE_B 0xff00 +#define BRX_PESUDO_NOISE_C 0xff0000 +#define BRX_PESUDO_NOISE_D 0xff000000 +#define BRX_PESUDO_NOISESTATE_A 0xffff +#define BRX_PESUDO_NOISESTATE_B 0xffff0000 +#define BRX_PESUDO_NOISESTATE_C 0xffff +#define BRX_PESUDO_NOISESTATE_D 0xffff0000 + +#define BZEBRA1_HSSIENABLE 0x8 +#define BZEBRA1_TRXCONTROL 0xc00 +#define BZEBRA1_TRXGAINSETTING 0x07f +#define BZEBRA1_RXCOUNTER 0xc00 +#define BZEBRA1_TXCHANGEPUMP 0x38 +#define BZEBRA1_RXCHANGEPUMP 0x7 +#define BZEBRA1_CHANNEL_NUM 0xf80 +#define BZEBRA1_TXLPFBW 0x400 +#define BZEBRA1_RXLPFBW 0x600 + +#define BRTL8256REG_MODE_CTRL1 0x100 +#define BRTL8256REG_MODE_CTRL0 0x40 +#define BRTL8256REG_TXLPFBW 0x18 +#define BRTL8256REG_RXLPFBW 0x600 + +#define BRTL8258_TXLPFBW 0xc +#define BRTL8258_RXLPFBW 0xc00 +#define BRTL8258_RSSILPFBW 0xc0 + +#define BBYTE0 0x1 +#define BBYTE1 0x2 +#define BBYTE2 0x4 +#define BBYTE3 0x8 +#define BWORD0 0x3 +#define BWORD1 0xc +#define BWORD 0xf + +#define MASKBYTE0 0xff +#define MASKBYTE1 0xff00 +#define MASKBYTE2 0xff0000 +#define MASKBYTE3 0xff000000 +#define MASKHWORD 0xffff0000 +#define MASKLWORD 0x0000ffff +#define MASKDWORD 0xffffffff +#define MASK12BITS 0xfff +#define MASKH4BITS 0xf0000000 +#define MASKOFDM_D 0xffc00000 +#define MASKCCK 0x3f3f3f3f + +#define MASK4BITS 0x0f +#define MASK20BITS 0xfffff +#define RFREG_OFFSET_MASK 0xfffff + +#define BENABLE 0x1 +#define BDISABLE 0x0 + +#define LEFT_ANTENNA 0x0 +#define RIGHT_ANTENNA 0x1 + +#define TCHECK_TXSTATUS 500 +#define TUPDATE_RXCOUNTER 100 + +#define REG_UN_used_register 0x01bf + +/* WOL bit information */ +#define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0) +#define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1) +#define HAL92C_WOL_DISASSOC_EVENT BIT(2) +#define HAL92C_WOL_DEAUTH_EVENT BIT(3) +#define HAL92C_WOL_FW_DISCONNECT_EVENT BIT(4) + +#define WOL_REASON_PTK_UPDATE BIT(0) +#define WOL_REASON_GTK_UPDATE BIT(1) +#define WOL_REASON_DISASSOC BIT(2) +#define WOL_REASON_DEAUTH BIT(3) +#define WOL_REASON_FW_DISCONNECT BIT(4) + +/* 2 EFUSE_TEST (For RTL8723 partially) */ +#define EFUSE_SEL(x) (((x) & 0x3) << 8) +#define EFUSE_SEL_MASK 0x300 +#define EFUSE_WIFI_SEL_0 0x0 + +#define WL_HWPDN_EN BIT(0) /* Enable GPIO[9] as WiFi HW PDn source*/ +#define WL_HWPDN_SL BIT(1) /* WiFi HW PDn polarity control*/ + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c new file mode 100644 index 000000000000..5ed4492d3c80 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.c @@ -0,0 +1,512 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" + +static bool _rtl8723be_phy_rf6052_config_parafile(struct ieee80211_hw *hw); + +void rtl8723be_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff) | BIT(10) | BIT(11)); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + case HT_CHANNEL_WIDTH_20_40: + rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & + 0xfffff3ff) | BIT(10)); + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, + rtlphy->rfreg_chnlval[0]); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", bandwidth); + break; + } +} + +void rtl8723be_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 tx_agc[2] = {0, 0}, tmpval; + bool turbo_scanoff = false; + u8 idx1, idx2; + u8 *ptr; + u8 direction; + u32 pwrtrac_value; + + if (rtlefuse->eeprom_regulatory != 0) + turbo_scanoff = true; + + if (mac->act_scanning) { + tx_agc[RF90_PATH_A] = 0x3f3f3f3f; + tx_agc[RF90_PATH_B] = 0x3f3f3f3f; + + if (turbo_scanoff) { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + } + } else { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + + if (rtlefuse->eeprom_regulatory == 0) { + tmpval = + (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + + (rtlphy->mcs_txpwrlevel_origoffset[0][7] << 8); + tx_agc[RF90_PATH_A] += tmpval; + + tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + + (rtlphy->mcs_txpwrlevel_origoffset[0][15] << + 24); + tx_agc[RF90_PATH_B] += tmpval; + } + } + + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + ptr = (u8 *)(&(tx_agc[idx1])); + for (idx2 = 0; idx2 < 4; idx2++) { + if (*ptr > RF6052_MAX_TX_PWR) + *ptr = RF6052_MAX_TX_PWR; + ptr++; + } + } + rtl8723be_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); + if (direction == 1) { + tx_agc[0] += pwrtrac_value; + tx_agc[1] += pwrtrac_value; + } else if (direction == 2) { + tx_agc[0] -= pwrtrac_value; + tx_agc[1] -= pwrtrac_value; + } + tmpval = tx_agc[RF90_PATH_A] & 0xff; + rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_A_CCK1_MCS32); + + tmpval = tx_agc[RF90_PATH_A] >> 8; + + /*tmpval = tmpval & 0xff00ffff;*/ + + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK11_A_CCK2_11); + + tmpval = tx_agc[RF90_PATH_B] >> 24; + rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK11_A_CCK2_11); + + tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; + rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK1_55_MCS32); +} + +static void rtl8723be_phy_get_power_base(struct ieee80211_hw *hw, + u8 *ppowerlevel_ofdm, + u8 *ppowerlevel_bw20, + u8 *ppowerlevel_bw40, + u8 channel, u32 *ofdmbase, + u32 *mcsbase) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 powerbase0, powerbase1; + u8 i, powerlevel[2]; + + for (i = 0; i < 2; i++) { + powerbase0 = ppowerlevel_ofdm[i]; + + powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | + (powerbase0 << 8) | powerbase0; + *(ofdmbase + i) = powerbase0; + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [OFDM power base index rf(%c) = 0x%x]\n", + ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)); + } + + for (i = 0; i < 2; i++) { + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) + powerlevel[i] = ppowerlevel_bw20[i]; + else + powerlevel[i] = ppowerlevel_bw40[i]; + + powerbase1 = powerlevel[i]; + powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) | + (powerbase1 << 8) | powerbase1; + + *(mcsbase + i) = powerbase1; + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [MCS power base index rf(%c) = 0x%x]\n", + ((i == 0) ? 'A' : 'B'), *(mcsbase + i)); + } +} + +static void _rtl8723be_get_txpower_writeval_by_regulatory( + struct ieee80211_hw *hw, + u8 channel, u8 index, + u32 *powerbase0, + u32 *powerbase1, + u32 *p_outwriteval) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff; + u32 writeval, customer_limit, rf; + + for (rf = 0; rf < 2; rf++) { + switch (rtlefuse->eeprom_regulatory) { + case 0: + chnlgroup = 0; + + writeval = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index + + (rf ? 8 : 0)] + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + case 1: + if (rtlphy->pwrgroup_cnt == 1) { + chnlgroup = 0; + } else { + if (channel < 3) + chnlgroup = 0; + else if (channel < 6) + chnlgroup = 1; + else if (channel < 9) + chnlgroup = 2; + else if (channel < 12) + chnlgroup = 3; + else if (channel < 14) + chnlgroup = 4; + else if (channel == 14) + chnlgroup = 5; + } + + writeval = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] + [index + (rf ? 8 : 0)] + ((index < 2) ? + powerbase0[rf] : + powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + + break; + case 2: + writeval = + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Better regulatory, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + case 3: + chnlgroup = 0; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 40MHz rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), + rtlefuse->pwrgroup_ht40 + [rf][channel - 1]); + } else { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 20MHz rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), + rtlefuse->pwrgroup_ht20 + [rf][channel - 1]); + } + + if (index < 2) + pwr_diff = + rtlefuse->txpwr_legacyhtdiff[rf][channel-1]; + else if (rtlphy->current_chan_bw == + HT_CHANNEL_WIDTH_20) + pwr_diff = + rtlefuse->txpwr_ht20diff[rf][channel-1]; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) + customer_pwr_diff = + rtlefuse->pwrgroup_ht40[rf][channel-1]; + else + customer_pwr_diff = + rtlefuse->pwrgroup_ht20[rf][channel-1]; + + if (pwr_diff > customer_pwr_diff) + pwr_diff = 0; + else + pwr_diff = customer_pwr_diff - pwr_diff; + + for (i = 0; i < 4; i++) { + pwr_diff_limit[i] = + (u8)((rtlphy->mcs_txpwrlevel_origoffset + [chnlgroup][index + (rf ? 8 : 0)] & + (0x7f << (i * 8))) >> (i * 8)); + + if (pwr_diff_limit[i] > pwr_diff) + pwr_diff_limit[i] = pwr_diff; + } + + customer_limit = (pwr_diff_limit[3] << 24) | + (pwr_diff_limit[2] << 16) | + (pwr_diff_limit[1] << 8) | + (pwr_diff_limit[0]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer's limit rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), customer_limit); + + writeval = customer_limit + ((index < 2) ? + powerbase0[rf] : + powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer, writeval rf(%c)= 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + default: + chnlgroup = 0; + writeval = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] + [index + (rf ? 8 : 0)] + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeval rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + } + + if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) + writeval = writeval - 0x06060606; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_BT2) + writeval = writeval - 0x0c0c0c0c; + *(p_outwriteval + rf) = writeval; + } +} + +static void _rtl8723be_write_ofdm_power_reg(struct ieee80211_hw *hw, + u8 index, u32 *pvalue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 regoffset_a[6] = { + RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, + RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, + RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 + }; + u16 regoffset_b[6] = { + RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, + RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, + RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 + }; + u8 i, rf, pwr_val[4]; + u32 writeval; + u16 regoffset; + + for (rf = 0; rf < 2; rf++) { + writeval = pvalue[rf]; + for (i = 0; i < 4; i++) { + pwr_val[i] = (u8)((writeval & (0x7f << + (i * 8))) >> (i * 8)); + + if (pwr_val[i] > RF6052_MAX_TX_PWR) + pwr_val[i] = RF6052_MAX_TX_PWR; + } + writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | + (pwr_val[1] << 8) | pwr_val[0]; + + if (rf == 0) + regoffset = regoffset_a[index]; + else + regoffset = regoffset_b[index]; + rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Set 0x%x = %08x\n", regoffset, writeval); + } +} + +void rtl8723be_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel_ofdm, + u8 *ppowerlevel_bw20, + u8 *ppowerlevel_bw40, u8 channel) +{ + u32 writeval[2], powerbase0[2], powerbase1[2]; + u8 index; + u8 direction; + u32 pwrtrac_value; + + rtl8723be_phy_get_power_base(hw, ppowerlevel_ofdm, ppowerlevel_bw20, + ppowerlevel_bw40, channel, + &powerbase0[0], &powerbase1[0]); + + rtl8723be_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); + + for (index = 0; index < 6; index++) { + _rtl8723be_get_txpower_writeval_by_regulatory(hw, + channel, index, + &powerbase0[0], + &powerbase1[0], + &writeval[0]); + if (direction == 1) { + writeval[0] += pwrtrac_value; + writeval[1] += pwrtrac_value; + } else if (direction == 2) { + writeval[0] -= pwrtrac_value; + writeval[1] -= pwrtrac_value; + } + _rtl8723be_write_ofdm_power_reg(hw, index, &writeval[0]); + } +} + +bool rtl8723be_phy_rf6052_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + if (rtlphy->rf_type == RF_1T1R) + rtlphy->num_total_rfpath = 1; + else + rtlphy->num_total_rfpath = 2; + + return _rtl8723be_phy_rf6052_config_parafile(hw); + +} + +static bool _rtl8723be_phy_rf6052_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u32 u4_regvalue = 0; + u8 rfpath; + bool rtstatus = true; + struct bb_reg_def *pphyreg; + + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + pphyreg = &rtlphy->phyreg_def[rfpath]; + + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV); + break; + case RF90_PATH_B: + case RF90_PATH_D: + u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16); + break; + } + + rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, + B3WIREADDREAALENGTH, 0x0); + udelay(1); + + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); + udelay(1); + + switch (rfpath) { + case RF90_PATH_A: + rtstatus = rtl8723be_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_B: + rtstatus = rtl8723be_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_C: + break; + case RF90_PATH_D: + break; + } + + switch (rfpath) { + case RF90_PATH_A: + case RF90_PATH_C: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV, u4_regvalue); + break; + case RF90_PATH_B: + case RF90_PATH_D: + rtl_set_bbreg(hw, pphyreg->rfintfs, + BRFSI_RFENV << 16, u4_regvalue); + break; + } + + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio[%d] Fail!!", rfpath); + return false; + } + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); + return rtstatus; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h new file mode 100644 index 000000000000..f423e157020f --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/rf.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723BE_RF_H__ +#define __RTL8723BE_RF_H__ + +#define RF6052_MAX_TX_PWR 0x3F + +void rtl8723be_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, + u8 bandwidth); +void rtl8723be_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +void rtl8723be_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel_ofdm, + u8 *ppowerlevel_bw20, + u8 *ppowerlevel_bw40, + u8 channel); +bool rtl8723be_phy_rf6052_config(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c new file mode 100644 index 000000000000..d091f1d5f91e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c @@ -0,0 +1,410 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../core.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "../rtl8723com/phy_common.h" +#include "dm.h" +#include "../rtl8723com/dm_common.h" +#include "hw.h" +#include "fw.h" +#include "../rtl8723com/fw_common.h" +#include "sw.h" +#include "trx.h" +#include "led.h" +#include "table.h" +#include "../btcoexist/rtl_btc.h" + +#include +#include + +static void rtl8723be_init_aspm_vars(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /* ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + */ + rtlpci->const_pci_aspm = 3; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /* In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 0; + + /* This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 1; +} + +int rtl8723be_init_sw_vars(struct ieee80211_hw *hw) +{ + int err = 0; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + rtl8723be_bt_reg_init(hw); + rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; + rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); + + rtlpriv->dm.dm_initialgain_enable = 1; + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.disable_framebursting = 0; + rtlpriv->dm.thermalvalue = 0; + rtlpci->transmit_config = CFENDFORM | BIT(15) | BIT(24) | BIT(25); + + rtlpriv->phy.lck_inprogress = false; + + mac->ht_enable = true; + + /* compatible 5G band 88ce just 2.4G band & smsp */ + rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; + rtlpriv->rtlhal.bandset = BAND_ON_2_4G; + rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; + + rtlpci->receive_config = (RCR_APPFCS | + RCR_APP_MIC | + RCR_APP_ICV | + RCR_APP_PHYST_RXFF | + RCR_HTC_LOC_CTRL | + RCR_AMF | + RCR_ACF | + RCR_ADF | + RCR_AICV | + RCR_AB | + RCR_AM | + RCR_APM | + 0); + + rtlpci->irq_mask[0] = (u32) (IMR_PSTIMEOUT | + IMR_HSISR_IND_ON_INT | + IMR_C2HCMD | + IMR_HIGHDOK | + IMR_MGNTDOK | + IMR_BKDOK | + IMR_BEDOK | + IMR_VIDOK | + IMR_VODOK | + IMR_RDU | + IMR_ROK | + 0); + + rtlpci->irq_mask[1] = (u32)(IMR_RXFOVW | 0); + + rtlpci->sys_irq_mask = (u32)(HSIMR_PDN_INT_EN | + 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; + rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; + rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; + if (rtlpriv->cfg->mod_params->disable_watchdog) + pr_info("watchdog disabled\n"); + rtlpriv->psc.reg_fwctrl_lps = 3; + rtlpriv->psc.reg_max_lps_awakeintvl = 5; + /* for ASPM, you can close aspm through + * set const_support_pciaspm = 0 + */ + rtl8723be_init_aspm_vars(hw); + + if (rtlpriv->psc.reg_fwctrl_lps == 1) + rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 2) + rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 3) + rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + + /*low power: Disable 32k */ + rtlpriv->psc.low_power_enable = false; + + rtlpriv->rtlhal.earlymode_enable = false; + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); + if (!rtlpriv->rtlhal.pfirmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't alloc buffer for fw.\n"); + return 1; + } + + rtlpriv->max_fw_size = 0x8000; + pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); + err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, + rtlpriv->io.dev, GFP_KERNEL, hw, + rtl_fw_cb); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to request firmware!\n"); + return 1; + } + return 0; +} + +void rtl8723be_deinit_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.pfirmware) { + vfree(rtlpriv->rtlhal.pfirmware); + rtlpriv->rtlhal.pfirmware = NULL; + } +} + +/* get bt coexist status */ +bool rtl8723be_get_btc_status(void) +{ + return true; +} + +static bool is_fw_header(struct rtlwifi_firmware_header *hdr) +{ + return (le16_to_cpu(hdr->signature) & 0xfff0) == 0x5300; +} + +static struct rtl_hal_ops rtl8723be_hal_ops = { + .init_sw_vars = rtl8723be_init_sw_vars, + .deinit_sw_vars = rtl8723be_deinit_sw_vars, + .read_eeprom_info = rtl8723be_read_eeprom_info, + .interrupt_recognized = rtl8723be_interrupt_recognized, + .hw_init = rtl8723be_hw_init, + .hw_disable = rtl8723be_card_disable, + .hw_suspend = rtl8723be_suspend, + .hw_resume = rtl8723be_resume, + .enable_interrupt = rtl8723be_enable_interrupt, + .disable_interrupt = rtl8723be_disable_interrupt, + .set_network_type = rtl8723be_set_network_type, + .set_chk_bssid = rtl8723be_set_check_bssid, + .set_qos = rtl8723be_set_qos, + .set_bcn_reg = rtl8723be_set_beacon_related_registers, + .set_bcn_intv = rtl8723be_set_beacon_interval, + .update_interrupt_mask = rtl8723be_update_interrupt_mask, + .get_hw_reg = rtl8723be_get_hw_reg, + .set_hw_reg = rtl8723be_set_hw_reg, + .update_rate_tbl = rtl8723be_update_hal_rate_tbl, + .fill_tx_desc = rtl8723be_tx_fill_desc, + .fill_tx_cmddesc = rtl8723be_tx_fill_cmddesc, + .query_rx_desc = rtl8723be_rx_query_desc, + .set_channel_access = rtl8723be_update_channel_access_setting, + .radio_onoff_checking = rtl8723be_gpio_radio_on_off_checking, + .set_bw_mode = rtl8723be_phy_set_bw_mode, + .switch_channel = rtl8723be_phy_sw_chnl, + .dm_watchdog = rtl8723be_dm_watchdog, + .scan_operation_backup = rtl8723be_phy_scan_operation_backup, + .set_rf_power_state = rtl8723be_phy_set_rf_power_state, + .led_control = rtl8723be_led_control, + .set_desc = rtl8723be_set_desc, + .get_desc = rtl8723be_get_desc, + .is_tx_desc_closed = rtl8723be_is_tx_desc_closed, + .tx_polling = rtl8723be_tx_polling, + .enable_hw_sec = rtl8723be_enable_hw_security_config, + .set_key = rtl8723be_set_key, + .init_sw_leds = rtl8723be_init_sw_leds, + .get_bbreg = rtl8723_phy_query_bb_reg, + .set_bbreg = rtl8723_phy_set_bb_reg, + .get_rfreg = rtl8723be_phy_query_rf_reg, + .set_rfreg = rtl8723be_phy_set_rf_reg, + .fill_h2c_cmd = rtl8723be_fill_h2c_cmd, + .get_btc_status = rtl8723be_get_btc_status, + .rx_command_packet = rtl8723be_rx_command_packet, + .is_fw_header = is_fw_header, +}; + +static struct rtl_mod_params rtl8723be_mod_params = { + .sw_crypto = false, + .inactiveps = true, + .swctrl_lps = false, + .fwctrl_lps = true, +}; + +static struct rtl_hal_cfg rtl8723be_hal_cfg = { + .bar_id = 2, + .write_readback = true, + .name = "rtl8723be_pci", + .fw_name = "rtlwifi/rtl8723befw.bin", + .ops = &rtl8723be_hal_ops, + .mod_params = &rtl8723be_mod_params, + .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, + .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, + .maps[SYS_CLK] = REG_SYS_CLKR, + .maps[MAC_RCR_AM] = AM, + .maps[MAC_RCR_AB] = AB, + .maps[MAC_RCR_ACRC32] = ACRC32, + .maps[MAC_RCR_ACF] = ACF, + .maps[MAC_RCR_AAP] = AAP, + .maps[MAC_HIMR] = REG_HIMR, + .maps[MAC_HIMRE] = REG_HIMRE, + .maps[MAC_HSISR] = REG_HSISR, + + .maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS, + + .maps[EFUSE_TEST] = REG_EFUSE_TEST, + .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_CLK] = 0, + .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_PWC_EV12V] = PWC_EV12V, + .maps[EFUSE_FEN_ELDR] = FEN_ELDR, + .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, + .maps[EFUSE_ANA8M] = ANA8M, + .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, + .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, + .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, + .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, + + .maps[RWCAM] = REG_CAMCMD, + .maps[WCAMI] = REG_CAMWRITE, + .maps[RCAMO] = REG_CAMREAD, + .maps[CAMDBG] = REG_CAMDBG, + .maps[SECR] = REG_SECCFG, + .maps[SEC_CAM_NONE] = CAM_NONE, + .maps[SEC_CAM_WEP40] = CAM_WEP40, + .maps[SEC_CAM_TKIP] = CAM_TKIP, + .maps[SEC_CAM_AES] = CAM_AES, + .maps[SEC_CAM_WEP104] = CAM_WEP104, + + .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, + .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, + .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, + .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, + .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, + .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, +/* .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, */ /*need check*/ + .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, + .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, + .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, + .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, + .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, + .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, + .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, +/* .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,*/ +/* .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,*/ + + .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, + .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, + .maps[RTL_IMR_BCNINT] = IMR_BCNDMAINT0, + .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, + .maps[RTL_IMR_RDU] = IMR_RDU, + .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, + .maps[RTL_IMR_BDOK] = IMR_BCNDOK0, + .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, + .maps[RTL_IMR_TBDER] = IMR_TBDER, + .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, + .maps[RTL_IMR_TBDOK] = IMR_TBDOK, + .maps[RTL_IMR_BKDOK] = IMR_BKDOK, + .maps[RTL_IMR_BEDOK] = IMR_BEDOK, + .maps[RTL_IMR_VIDOK] = IMR_VIDOK, + .maps[RTL_IMR_VODOK] = IMR_VODOK, + .maps[RTL_IMR_ROK] = IMR_ROK, + .maps[RTL_IMR_HSISR_IND] = IMR_HSISR_IND_ON_INT, + .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER), + + .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, +}; + +static struct pci_device_id rtl8723be_pci_ids[] = { + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xB723, rtl8723be_hal_cfg)}, + {}, +}; + +MODULE_DEVICE_TABLE(pci, rtl8723be_pci_ids); + +MODULE_AUTHOR("PageHe "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_LICENSE("GPL"); +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(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); +module_param_named(msi, rtl8723be_mod_params.msi_support, bool, 0444); +module_param_named(disable_watchdog, rtl8723be_mod_params.disable_watchdog, + bool, 0444); +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(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(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); + +static struct pci_driver rtl8723be_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl8723be_pci_ids, + .probe = rtl_pci_probe, + .remove = rtl_pci_disconnect, + .driver.pm = &rtlwifi_pm_ops, +}; + +module_pci_driver(rtl8723be_driver); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h new file mode 100644 index 000000000000..a7b25e769950 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.h @@ -0,0 +1,35 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723BE_SW_H__ +#define __RTL8723BE_SW_H__ + +int rtl8723be_init_sw_vars(struct ieee80211_hw *hw); +void rtl8723be_deinit_sw_vars(struct ieee80211_hw *hw); +void rtl8723be_init_var_map(struct ieee80211_hw *hw); +bool rtl8723be_get_btc_status(void); + + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c new file mode 100644 index 000000000000..a180761e8810 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.c @@ -0,0 +1,577 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger + * + *****************************************************************************/ + +#include "table.h" +u32 RTL8723BEPHY_REG_1TARRAY[] = { + 0x800, 0x80040000, + 0x804, 0x00000003, + 0x808, 0x0000FC00, + 0x80C, 0x0000000A, + 0x810, 0x10001331, + 0x814, 0x020C3D10, + 0x818, 0x02200385, + 0x81C, 0x00000000, + 0x820, 0x01000100, + 0x824, 0x00390204, + 0x828, 0x00000000, + 0x82C, 0x00000000, + 0x830, 0x00000000, + 0x834, 0x00000000, + 0x838, 0x00000000, + 0x83C, 0x00000000, + 0x840, 0x00010000, + 0x844, 0x00000000, + 0x848, 0x00000000, + 0x84C, 0x00000000, + 0x850, 0x00000000, + 0x854, 0x00000000, + 0x858, 0x569A11A9, + 0x85C, 0x01000014, + 0x860, 0x66F60110, + 0x864, 0x061F0649, + 0x868, 0x00000000, + 0x86C, 0x27272700, + 0x870, 0x07000760, + 0x874, 0x25004000, + 0x878, 0x00000808, + 0x87C, 0x00000000, + 0x880, 0xB0000C1C, + 0x884, 0x00000001, + 0x888, 0x00000000, + 0x88C, 0xCCC000C0, + 0x890, 0x00000800, + 0x894, 0xFFFFFFFE, + 0x898, 0x40302010, + 0x89C, 0x00706050, + 0x900, 0x00000000, + 0x904, 0x00000023, + 0x908, 0x00000000, + 0x90C, 0x81121111, + 0x910, 0x00000002, + 0x914, 0x00000201, + 0x948, 0x00000280, + 0xA00, 0x00D047C8, + 0xA04, 0x80FF000C, + 0xA08, 0x8C838300, + 0xA0C, 0x2E7F120F, + 0xA10, 0x9500BB78, + 0xA14, 0x1114D028, + 0xA18, 0x00881117, + 0xA1C, 0x89140F00, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0xA2C, 0x00D30000, + 0xA70, 0x101FBF00, + 0xA74, 0x00000007, + 0xA78, 0x00000900, + 0xA7C, 0x225B0606, + 0xA80, 0x21806490, + 0xB2C, 0x00000000, + 0xC00, 0x48071D40, + 0xC04, 0x03A05611, + 0xC08, 0x000000E4, + 0xC0C, 0x6C6C6C6C, + 0xC10, 0x08800000, + 0xC14, 0x40000100, + 0xC18, 0x08800000, + 0xC1C, 0x40000100, + 0xC20, 0x00000000, + 0xC24, 0x00000000, + 0xC28, 0x00000000, + 0xC2C, 0x00000000, + 0xC30, 0x69E9AC44, + 0xC34, 0x469652AF, + 0xC38, 0x49795994, + 0xC3C, 0x0A97971C, + 0xC40, 0x1F7C403F, + 0xC44, 0x000100B7, + 0xC48, 0xEC020107, + 0xC4C, 0x007F037F, + 0xC50, 0x69553420, + 0xC54, 0x43BC0094, + 0xC58, 0x00023169, + 0xC5C, 0x00250492, + 0xC60, 0x00000000, + 0xC64, 0x7112848B, + 0xC68, 0x47C00BFF, + 0xC6C, 0x00000036, + 0xC70, 0x2C7F000D, + 0xC74, 0x020610DB, + 0xC78, 0x0000001F, + 0xC7C, 0x00B91612, + 0xC80, 0x390000E4, + 0xC84, 0x20F60000, + 0xC88, 0x40000100, + 0xC8C, 0x20200000, + 0xC90, 0x00020E1A, + 0xC94, 0x00000000, + 0xC98, 0x00020E1A, + 0xC9C, 0x00007F7F, + 0xCA0, 0x00000000, + 0xCA4, 0x000300A0, + 0xCA8, 0x00000000, + 0xCAC, 0x00000000, + 0xCB0, 0x00000000, + 0xCB4, 0x00000000, + 0xCB8, 0x00000000, + 0xCBC, 0x28000000, + 0xCC0, 0x00000000, + 0xCC4, 0x00000000, + 0xCC8, 0x00000000, + 0xCCC, 0x00000000, + 0xCD0, 0x00000000, + 0xCD4, 0x00000000, + 0xCD8, 0x64B22427, + 0xCDC, 0x00766932, + 0xCE0, 0x00222222, + 0xCE4, 0x00000000, + 0xCE8, 0x37644302, + 0xCEC, 0x2F97D40C, + 0xD00, 0x00000740, + 0xD04, 0x40020401, + 0xD08, 0x0000907F, + 0xD0C, 0x20010201, + 0xD10, 0xA0633333, + 0xD14, 0x3333BC53, + 0xD18, 0x7A8F5B6F, + 0xD2C, 0xCC979975, + 0xD30, 0x00000000, + 0xD34, 0x80608000, + 0xD38, 0x00000000, + 0xD3C, 0x00127353, + 0xD40, 0x00000000, + 0xD44, 0x00000000, + 0xD48, 0x00000000, + 0xD4C, 0x00000000, + 0xD50, 0x6437140A, + 0xD54, 0x00000000, + 0xD58, 0x00000282, + 0xD5C, 0x30032064, + 0xD60, 0x4653DE68, + 0xD64, 0x04518A3C, + 0xD68, 0x00002101, + 0xD6C, 0x2A201C16, + 0xD70, 0x1812362E, + 0xD74, 0x322C2220, + 0xD78, 0x000E3C24, + 0xE00, 0x2D2D2D2D, + 0xE04, 0x2D2D2D2D, + 0xE08, 0x0390272D, + 0xE10, 0x2D2D2D2D, + 0xE14, 0x2D2D2D2D, + 0xE18, 0x2D2D2D2D, + 0xE1C, 0x2D2D2D2D, + 0xE28, 0x00000000, + 0xE30, 0x1000DC1F, + 0xE34, 0x10008C1F, + 0xE38, 0x02140102, + 0xE3C, 0x681604C2, + 0xE40, 0x01007C00, + 0xE44, 0x01004800, + 0xE48, 0xFB000000, + 0xE4C, 0x000028D1, + 0xE50, 0x1000DC1F, + 0xE54, 0x10008C1F, + 0xE58, 0x02140102, + 0xE5C, 0x28160D05, + 0xE60, 0x00000008, + 0xE68, 0x001B2556, + 0xE6C, 0x00C00096, + 0xE70, 0x00C00096, + 0xE74, 0x01000056, + 0xE78, 0x01000014, + 0xE7C, 0x01000056, + 0xE80, 0x01000014, + 0xE84, 0x00C00096, + 0xE88, 0x01000056, + 0xE8C, 0x00C00096, + 0xED0, 0x00C00096, + 0xED4, 0x00C00096, + 0xED8, 0x00C00096, + 0xEDC, 0x000000D6, + 0xEE0, 0x000000D6, + 0xEEC, 0x01C00016, + 0xF14, 0x00000003, + 0xF4C, 0x00000000, + 0xF00, 0x00000300, + 0x820, 0x01000100, + 0x800, 0x83040000, + +}; + +u32 RTL8723BEPHY_REG_ARRAY_PG[] = { + 0, 0, 0, 0x00000e08, 0x0000ff00, 0x00004000, + 0, 0, 0, 0x0000086c, 0xffffff00, 0x34363800, + 0, 0, 0, 0x00000e00, 0xffffffff, 0x42444646, + 0, 0, 0, 0x00000e04, 0xffffffff, 0x30343840, + 0, 0, 0, 0x00000e10, 0xffffffff, 0x38404244, + 0, 0, 0, 0x00000e14, 0xffffffff, 0x26303436 +}; + +u32 RTL8723BE_RADIOA_1TARRAY[] = { + 0x000, 0x00010000, + 0x0B0, 0x000DFFE0, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0B1, 0x00000018, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0B2, 0x00084C00, + 0x0B5, 0x0000D2CC, + 0x0B6, 0x000925AA, + 0x0B7, 0x00000010, + 0x0B8, 0x0000907F, + 0x05C, 0x00000002, + 0x07C, 0x00000002, + 0x07E, 0x00000005, + 0x08B, 0x0006FC00, + 0x0B0, 0x000FF9F0, + 0x01C, 0x000739D2, + 0x01E, 0x00000000, + 0x0DF, 0x00000780, + 0x050, 0x00067435, + 0x051, 0x0006B04E, + 0x052, 0x000007D2, + 0x053, 0x00000000, + 0x054, 0x00050400, + 0x055, 0x0004026E, + 0x0DD, 0x0000004C, + 0x070, 0x00067435, + 0x071, 0x0006B04E, + 0x072, 0x000007D2, + 0x073, 0x00000000, + 0x074, 0x00050400, + 0x075, 0x0004026E, + 0x0EF, 0x00000100, + 0x034, 0x0000ADD7, + 0x035, 0x00005C00, + 0x034, 0x00009DD4, + 0x035, 0x00005000, + 0x034, 0x00008DD1, + 0x035, 0x00004400, + 0x034, 0x00007DCE, + 0x035, 0x00003800, + 0x034, 0x00006CD1, + 0x035, 0x00004400, + 0x034, 0x00005CCE, + 0x035, 0x00003800, + 0x034, 0x000048CE, + 0x035, 0x00004400, + 0x034, 0x000034CE, + 0x035, 0x00003800, + 0x034, 0x00002451, + 0x035, 0x00004400, + 0x034, 0x0000144E, + 0x035, 0x00003800, + 0x034, 0x00000051, + 0x035, 0x00004400, + 0x0EF, 0x00000000, + 0x0EF, 0x00000100, + 0x0ED, 0x00000010, + 0x044, 0x0000ADD7, + 0x044, 0x00009DD4, + 0x044, 0x00008DD1, + 0x044, 0x00007DCE, + 0x044, 0x00006CC1, + 0x044, 0x00005CCE, + 0x044, 0x000044D1, + 0x044, 0x000034CE, + 0x044, 0x00002451, + 0x044, 0x0000144E, + 0x044, 0x00000051, + 0x0EF, 0x00000000, + 0x0ED, 0x00000000, + 0x0EF, 0x00002000, + 0x03B, 0x000380EF, + 0x03B, 0x000302FE, + 0x03B, 0x00028CE6, + 0x03B, 0x000200BC, + 0x03B, 0x000188A5, + 0x03B, 0x00010FBC, + 0x03B, 0x00008F71, + 0x03B, 0x00000900, + 0x0EF, 0x00000000, + 0x0ED, 0x00000001, + 0x040, 0x000380EF, + 0x040, 0x000302FE, + 0x040, 0x00028CE6, + 0x040, 0x000200BC, + 0x040, 0x000188A5, + 0x040, 0x00010FBC, + 0x040, 0x00008F71, + 0x040, 0x00000900, + 0x0ED, 0x00000000, + 0x082, 0x00080000, + 0x083, 0x00008000, + 0x084, 0x00048D80, + 0x085, 0x00068000, + 0x0A2, 0x00080000, + 0x0A3, 0x00008000, + 0x0A4, 0x00048D80, + 0x0A5, 0x00068000, + 0x000, 0x00033D80, + +}; + +u32 RTL8723BEMAC_1T_ARRAY[] = { + 0x02F, 0x00000030, + 0x035, 0x00000000, + 0x067, 0x00000020, + 0x428, 0x0000000A, + 0x429, 0x00000010, + 0x430, 0x00000000, + 0x431, 0x00000000, + 0x432, 0x00000000, + 0x433, 0x00000001, + 0x434, 0x00000004, + 0x435, 0x00000005, + 0x436, 0x00000007, + 0x437, 0x00000008, + 0x43C, 0x00000004, + 0x43D, 0x00000005, + 0x43E, 0x00000007, + 0x43F, 0x00000008, + 0x440, 0x0000005D, + 0x441, 0x00000001, + 0x442, 0x00000000, + 0x444, 0x00000010, + 0x445, 0x00000000, + 0x446, 0x00000000, + 0x447, 0x00000000, + 0x448, 0x00000000, + 0x449, 0x000000F0, + 0x44A, 0x0000000F, + 0x44B, 0x0000003E, + 0x44C, 0x00000010, + 0x44D, 0x00000000, + 0x44E, 0x00000000, + 0x44F, 0x00000000, + 0x450, 0x00000000, + 0x451, 0x000000F0, + 0x452, 0x0000000F, + 0x453, 0x00000000, + 0x456, 0x0000005E, + 0x460, 0x00000066, + 0x461, 0x00000066, + 0x4C8, 0x000000FF, + 0x4C9, 0x00000008, + 0x4CC, 0x000000FF, + 0x4CD, 0x000000FF, + 0x4CE, 0x00000001, + 0x500, 0x00000026, + 0x501, 0x000000A2, + 0x502, 0x0000002F, + 0x503, 0x00000000, + 0x504, 0x00000028, + 0x505, 0x000000A3, + 0x506, 0x0000005E, + 0x507, 0x00000000, + 0x508, 0x0000002B, + 0x509, 0x000000A4, + 0x50A, 0x0000005E, + 0x50B, 0x00000000, + 0x50C, 0x0000004F, + 0x50D, 0x000000A4, + 0x50E, 0x00000000, + 0x50F, 0x00000000, + 0x512, 0x0000001C, + 0x514, 0x0000000A, + 0x516, 0x0000000A, + 0x525, 0x0000004F, + 0x550, 0x00000010, + 0x551, 0x00000010, + 0x559, 0x00000002, + 0x55C, 0x00000050, + 0x55D, 0x000000FF, + 0x605, 0x00000030, + 0x608, 0x0000000E, + 0x609, 0x0000002A, + 0x620, 0x000000FF, + 0x621, 0x000000FF, + 0x622, 0x000000FF, + 0x623, 0x000000FF, + 0x624, 0x000000FF, + 0x625, 0x000000FF, + 0x626, 0x000000FF, + 0x627, 0x000000FF, + 0x638, 0x00000050, + 0x63C, 0x0000000A, + 0x63D, 0x0000000A, + 0x63E, 0x0000000E, + 0x63F, 0x0000000E, + 0x640, 0x00000040, + 0x642, 0x00000040, + 0x643, 0x00000000, + 0x652, 0x000000C8, + 0x66E, 0x00000005, + 0x700, 0x00000021, + 0x701, 0x00000043, + 0x702, 0x00000065, + 0x703, 0x00000087, + 0x708, 0x00000021, + 0x709, 0x00000043, + 0x70A, 0x00000065, + 0x70B, 0x00000087, + +}; + +u32 RTL8723BEAGCTAB_1TARRAY[] = { + 0xC78, 0xFD000001, + 0xC78, 0xFC010001, + 0xC78, 0xFB020001, + 0xC78, 0xFA030001, + 0xC78, 0xF9040001, + 0xC78, 0xF8050001, + 0xC78, 0xF7060001, + 0xC78, 0xF6070001, + 0xC78, 0xF5080001, + 0xC78, 0xF4090001, + 0xC78, 0xF30A0001, + 0xC78, 0xF20B0001, + 0xC78, 0xF10C0001, + 0xC78, 0xF00D0001, + 0xC78, 0xEF0E0001, + 0xC78, 0xEE0F0001, + 0xC78, 0xED100001, + 0xC78, 0xEC110001, + 0xC78, 0xEB120001, + 0xC78, 0xEA130001, + 0xC78, 0xE9140001, + 0xC78, 0xE8150001, + 0xC78, 0xE7160001, + 0xC78, 0xAA170001, + 0xC78, 0xA9180001, + 0xC78, 0xA8190001, + 0xC78, 0xA71A0001, + 0xC78, 0xA61B0001, + 0xC78, 0xA51C0001, + 0xC78, 0xA41D0001, + 0xC78, 0xA31E0001, + 0xC78, 0x671F0001, + 0xC78, 0x66200001, + 0xC78, 0x65210001, + 0xC78, 0x64220001, + 0xC78, 0x63230001, + 0xC78, 0x62240001, + 0xC78, 0x61250001, + 0xC78, 0x47260001, + 0xC78, 0x46270001, + 0xC78, 0x45280001, + 0xC78, 0x44290001, + 0xC78, 0x432A0001, + 0xC78, 0x422B0001, + 0xC78, 0x292C0001, + 0xC78, 0x282D0001, + 0xC78, 0x272E0001, + 0xC78, 0x262F0001, + 0xC78, 0x25300001, + 0xC78, 0x24310001, + 0xC78, 0x09320001, + 0xC78, 0x08330001, + 0xC78, 0x07340001, + 0xC78, 0x06350001, + 0xC78, 0x05360001, + 0xC78, 0x04370001, + 0xC78, 0x03380001, + 0xC78, 0x02390001, + 0xC78, 0x013A0001, + 0xC78, 0x003B0001, + 0xC78, 0x003C0001, + 0xC78, 0x003D0001, + 0xC78, 0x003E0001, + 0xC78, 0x003F0001, + 0xC78, 0xFC400001, + 0xC78, 0xFB410001, + 0xC78, 0xFA420001, + 0xC78, 0xF9430001, + 0xC78, 0xF8440001, + 0xC78, 0xF7450001, + 0xC78, 0xF6460001, + 0xC78, 0xF5470001, + 0xC78, 0xF4480001, + 0xC78, 0xF3490001, + 0xC78, 0xF24A0001, + 0xC78, 0xF14B0001, + 0xC78, 0xF04C0001, + 0xC78, 0xEF4D0001, + 0xC78, 0xEE4E0001, + 0xC78, 0xED4F0001, + 0xC78, 0xEC500001, + 0xC78, 0xEB510001, + 0xC78, 0xEA520001, + 0xC78, 0xE9530001, + 0xC78, 0xE8540001, + 0xC78, 0xE7550001, + 0xC78, 0xE6560001, + 0xC78, 0xE5570001, + 0xC78, 0xAA580001, + 0xC78, 0xA9590001, + 0xC78, 0xA85A0001, + 0xC78, 0xA75B0001, + 0xC78, 0xA65C0001, + 0xC78, 0xA55D0001, + 0xC78, 0xA45E0001, + 0xC78, 0x675F0001, + 0xC78, 0x66600001, + 0xC78, 0x65610001, + 0xC78, 0x64620001, + 0xC78, 0x63630001, + 0xC78, 0x62640001, + 0xC78, 0x61650001, + 0xC78, 0x47660001, + 0xC78, 0x46670001, + 0xC78, 0x45680001, + 0xC78, 0x44690001, + 0xC78, 0x436A0001, + 0xC78, 0x426B0001, + 0xC78, 0x296C0001, + 0xC78, 0x286D0001, + 0xC78, 0x276E0001, + 0xC78, 0x266F0001, + 0xC78, 0x25700001, + 0xC78, 0x24710001, + 0xC78, 0x09720001, + 0xC78, 0x08730001, + 0xC78, 0x07740001, + 0xC78, 0x06750001, + 0xC78, 0x05760001, + 0xC78, 0x04770001, + 0xC78, 0x03780001, + 0xC78, 0x02790001, + 0xC78, 0x017A0001, + 0xC78, 0x007B0001, + 0xC78, 0x007C0001, + 0xC78, 0x007D0001, + 0xC78, 0x007E0001, + 0xC78, 0x007F0001, + 0xC50, 0x69553422, + 0xC50, 0x69553420, + +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h new file mode 100644 index 000000000000..dc17001632f7 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/table.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723BE_TABLE__H_ +#define __RTL8723BE_TABLE__H_ + +#include +#define RTL8723BEPHY_REG_1TARRAYLEN 388 +extern u32 RTL8723BEPHY_REG_1TARRAY[]; +#define RTL8723BEPHY_REG_ARRAY_PGLEN 36 +extern u32 RTL8723BEPHY_REG_ARRAY_PG[]; +#define RTL8723BE_RADIOA_1TARRAYLEN 206 +extern u32 RTL8723BE_RADIOA_1TARRAY[]; +#define RTL8723BEMAC_1T_ARRAYLEN 196 +extern u32 RTL8723BEMAC_1T_ARRAY[]; +#define RTL8723BEAGCTAB_1TARRAYLEN 260 +extern u32 RTL8723BEAGCTAB_1TARRAY[]; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c new file mode 100644 index 000000000000..338ec9a9d09b --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.c @@ -0,0 +1,783 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../stats.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "trx.h" +#include "led.h" +#include "dm.h" +#include "fw.h" + +static u8 _rtl8723be_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) +{ + __le16 fc = rtl_get_fc(skb); + + if (unlikely(ieee80211_is_beacon(fc))) + return QSLT_BEACON; + if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) + return QSLT_MGNT; + + return skb->priority; +} + +static void _rtl8723be_query_rxphystatus(struct ieee80211_hw *hw, + struct rtl_stats *pstatus, u8 *pdesc, + struct rx_fwinfo_8723be *p_drvinfo, + bool bpacket_match_bssid, + bool bpacket_toself, + bool packet_beacon) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct phy_status_rpt *p_phystrpt = (struct phy_status_rpt *)p_drvinfo; + char rx_pwr_all = 0, rx_pwr[4]; + u8 rf_rx_num = 0, evm, pwdb_all, pwdb_all_bt = 0; + u8 i, max_spatial_stream; + u32 rssi, total_rssi = 0; + bool is_cck = pstatus->is_cck; + u8 lan_idx, vga_idx; + + /* Record it for next packet processing */ + pstatus->packet_matchbssid = bpacket_match_bssid; + pstatus->packet_toself = bpacket_toself; + pstatus->packet_beacon = packet_beacon; + pstatus->rx_mimo_signalquality[0] = -1; + pstatus->rx_mimo_signalquality[1] = -1; + + if (is_cck) { + u8 cck_highpwr; + u8 cck_agc_rpt; + + cck_agc_rpt = p_phystrpt->cck_agc_rpt_ofdm_cfosho_a; + + /* (1)Hardware does not provide RSSI for CCK */ + /* (2)PWDB, Average PWDB cacluated by + * hardware (for rate adaptive) + */ + cck_highpwr = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, + BIT(9)); + + lan_idx = ((cck_agc_rpt & 0xE0) >> 5); + vga_idx = (cck_agc_rpt & 0x1f); + + switch (lan_idx) { + /* 46 53 73 95 201301231630 */ + /* 46 53 77 99 201301241630 */ + case 6: + rx_pwr_all = -34 - (2 * vga_idx); + break; + case 4: + rx_pwr_all = -14 - (2 * vga_idx); + break; + case 1: + rx_pwr_all = 6 - (2 * vga_idx); + break; + case 0: + rx_pwr_all = 16 - (2 * vga_idx); + break; + default: + break; + } + + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + if (pwdb_all > 100) + pwdb_all = 100; + + pstatus->rx_pwdb_all = pwdb_all; + pstatus->bt_rx_rssi_percentage = pwdb_all; + pstatus->recvsignalpower = rx_pwr_all; + + /* (3) Get Signal Quality (EVM) */ + if (bpacket_match_bssid) { + u8 sq, sq_rpt; + if (pstatus->rx_pwdb_all > 40) { + sq = 100; + } else { + sq_rpt = p_phystrpt->cck_sig_qual_ofdm_pwdb_all; + if (sq_rpt > 64) + sq = 0; + else if (sq_rpt < 20) + sq = 100; + else + sq = ((64 - sq_rpt) * 100) / 44; + } + pstatus->signalquality = sq; + pstatus->rx_mimo_signalquality[0] = sq; + pstatus->rx_mimo_signalquality[1] = -1; + } + } else { + /* (1)Get RSSI for HT rate */ + for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { + /* we will judge RF RX path now. */ + if (rtlpriv->dm.rfpath_rxenable[i]) + rf_rx_num++; + + rx_pwr[i] = ((p_phystrpt->path_agc[i].gain & 0x3f) * 2) + - 110; + + pstatus->rx_pwr[i] = rx_pwr[i]; + /* Translate DBM to percentage. */ + rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + + pstatus->rx_mimo_signalstrength[i] = (u8)rssi; + } + + /* (2)PWDB, Average PWDB cacluated by + * hardware (for rate adaptive) + */ + rx_pwr_all = ((p_phystrpt->cck_sig_qual_ofdm_pwdb_all >> 1) & + 0x7f) - 110; + + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + pwdb_all_bt = pwdb_all; + pstatus->rx_pwdb_all = pwdb_all; + pstatus->bt_rx_rssi_percentage = pwdb_all_bt; + pstatus->rxpower = rx_pwr_all; + pstatus->recvsignalpower = rx_pwr_all; + + /* (3)EVM of HT rate */ + if (pstatus->rate >= DESC92C_RATEMCS8 && + pstatus->rate <= DESC92C_RATEMCS15) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + + for (i = 0; i < max_spatial_stream; i++) { + evm = rtl_evm_db_to_percentage( + p_phystrpt->stream_rxevm[i]); + + if (bpacket_match_bssid) { + /* Fill value in RFD, Get the first + * spatial stream only + */ + if (i == 0) + pstatus->signalquality = + (u8)(evm & 0xff); + pstatus->rx_mimo_signalquality[i] = + (u8)(evm & 0xff); + } + } + + if (bpacket_match_bssid) { + for (i = RF90_PATH_A; i <= RF90_PATH_B; i++) + rtl_priv(hw)->dm.cfo_tail[i] = + (int)p_phystrpt->path_cfotail[i]; + + if (rtl_priv(hw)->dm.packet_count == 0xffffffff) + rtl_priv(hw)->dm.packet_count = 0; + else + rtl_priv(hw)->dm.packet_count++; + } + } + + /* UI BSS List signal strength(in percentage), + * make it good looking, from 0~100. + */ + if (is_cck) + pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, + pwdb_all)); + else if (rf_rx_num != 0) + pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, + total_rssi /= rf_rx_num)); +} + +static void _rtl8723be_translate_rx_signal_stuff(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct rtl_stats *pstatus, + u8 *pdesc, + struct rx_fwinfo_8723be *p_drvinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct ieee80211_hdr *hdr; + u8 *tmp_buf; + u8 *praddr; + u8 *psaddr; + u16 fc, type; + bool packet_matchbssid, packet_toself, packet_beacon; + + tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; + + hdr = (struct ieee80211_hdr *)tmp_buf; + fc = le16_to_cpu(hdr->frame_control); + type = WLAN_FC_GET_TYPE(hdr->frame_control); + praddr = hdr->addr1; + psaddr = ieee80211_get_SA(hdr); + memcpy(pstatus->psaddr, psaddr, ETH_ALEN); + + packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && + (ether_addr_equal(mac->bssid, (fc & IEEE80211_FCTL_TODS) ? + hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? + hdr->addr2 : hdr->addr3)) && + (!pstatus->hwerror) && + (!pstatus->crc) && (!pstatus->icv)); + + packet_toself = packet_matchbssid && + (ether_addr_equal(praddr, rtlefuse->dev_addr)); + + /* YP: packet_beacon is not initialized, + * this assignment is neccesary, + * otherwise it counld be true in this case + * the situation is much worse in Kernel 3.10 + */ + if (ieee80211_is_beacon(hdr->frame_control)) + packet_beacon = true; + else + packet_beacon = false; + + if (packet_beacon && packet_matchbssid) + rtl_priv(hw)->dm.dbginfo.num_qry_beacon_pkt++; + + _rtl8723be_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo, + packet_matchbssid, + packet_toself, + packet_beacon); + + rtl_process_phyinfo(hw, tmp_buf, pstatus); +} + +static void _rtl8723be_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, + u8 *virtualaddress) +{ + u32 dwtmp = 0; + memset(virtualaddress, 0, 8); + + SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); + if (ptcb_desc->empkt_num == 1) { + dwtmp = ptcb_desc->empkt_len[0]; + } else { + dwtmp = ptcb_desc->empkt_len[0]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += ptcb_desc->empkt_len[1]; + } + SET_EARLYMODE_LEN0(virtualaddress, dwtmp); + + if (ptcb_desc->empkt_num <= 3) { + dwtmp = ptcb_desc->empkt_len[2]; + } else { + dwtmp = ptcb_desc->empkt_len[2]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += ptcb_desc->empkt_len[3]; + } + SET_EARLYMODE_LEN1(virtualaddress, dwtmp); + if (ptcb_desc->empkt_num <= 5) { + dwtmp = ptcb_desc->empkt_len[4]; + } else { + dwtmp = ptcb_desc->empkt_len[4]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += ptcb_desc->empkt_len[5]; + } + SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF); + SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4); + if (ptcb_desc->empkt_num <= 7) { + dwtmp = ptcb_desc->empkt_len[6]; + } else { + dwtmp = ptcb_desc->empkt_len[6]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += ptcb_desc->empkt_len[7]; + } + SET_EARLYMODE_LEN3(virtualaddress, dwtmp); + if (ptcb_desc->empkt_num <= 9) { + dwtmp = ptcb_desc->empkt_len[8]; + } else { + dwtmp = ptcb_desc->empkt_len[8]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; + dwtmp += ptcb_desc->empkt_len[9]; + } + SET_EARLYMODE_LEN4(virtualaddress, dwtmp); +} + +bool rtl8723be_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *status, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rx_fwinfo_8723be *p_drvinfo; + struct ieee80211_hdr *hdr; + + u32 phystatus = GET_RX_DESC_PHYST(pdesc); + + status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); + status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * + RX_DRV_INFO_SIZE_UNIT; + status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03); + status->icv = (u16) GET_RX_DESC_ICV(pdesc); + status->crc = (u16) GET_RX_DESC_CRC32(pdesc); + status->hwerror = (status->crc | status->icv); + status->decrypted = !GET_RX_DESC_SWDEC(pdesc); + status->rate = (u8)GET_RX_DESC_RXMCS(pdesc); + status->shortpreamble = (u16)GET_RX_DESC_SPLCP(pdesc); + status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); + status->isfirst_ampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); + status->timestamp_low = GET_RX_DESC_TSFL(pdesc); + status->rx_is40Mhzpacket = (bool)GET_RX_DESC_BW(pdesc); + status->bandwidth = (u8)GET_RX_DESC_BW(pdesc); + status->macid = GET_RX_DESC_MACID(pdesc); + status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); + + status->is_cck = RX_HAL_IS_CCK_RATE(status->rate); + + if (GET_RX_STATUS_DESC_RPT_SEL(pdesc)) + status->packet_report_type = C2H_PACKET; + else + status->packet_report_type = NORMAL_RX; + + + if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) + status->wake_match = BIT(2); + else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) + status->wake_match = BIT(1); + else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) + status->wake_match = BIT(0); + else + status->wake_match = 0; + if (status->wake_match) + RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, + "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n", + status->wake_match); + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + + hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size + + status->rx_bufshift); + + if (status->crc) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (status->rx_is40Mhzpacket) + rx_status->flag |= RX_FLAG_40MHZ; + + if (status->is_ht) + rx_status->flag |= RX_FLAG_HT; + + rx_status->flag |= RX_FLAG_MACTIME_START; + + /* hw will set status->decrypted true, if it finds the + * frame is open data frame or mgmt frame. + * So hw will not decryption robust managment frame + * for IEEE80211w but still set status->decrypted + * true, so here we should set it back to undecrypted + * for IEEE80211w frame, and mac80211 sw will help + * to decrypt it + */ + if (status->decrypted) { + if ((!_ieee80211_is_robust_mgmt_frame(hdr)) && + (ieee80211_has_protected(hdr->frame_control))) + rx_status->flag |= RX_FLAG_DECRYPTED; + else + rx_status->flag &= ~RX_FLAG_DECRYPTED; + } + + /* rate_idx: index of data rate into band's + * supported rates or MCS index if HT rates + * are use (RX_FLAG_HT) + */ + rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht, + false, status->rate); + + rx_status->mactime = status->timestamp_low; + if (phystatus) { + p_drvinfo = (struct rx_fwinfo_8723be *)(skb->data + + status->rx_bufshift); + + _rtl8723be_translate_rx_signal_stuff(hw, skb, status, + pdesc, p_drvinfo); + } + rx_status->signal = status->recvsignalpower + 10; + if (status->packet_report_type == TX_REPORT2) { + status->macid_valid_entry[0] = + GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); + status->macid_valid_entry[1] = + GET_RX_RPT2_DESC_MACID_VALID_2(pdesc); + } + return true; +} + +void rtl8723be_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *txbd, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 *pdesc = (u8 *)pdesc_tx; + u16 seq_number; + __le16 fc = hdr->frame_control; + unsigned int buf_len = 0; + unsigned int skb_len = skb->len; + u8 fw_qsel = _rtl8723be_map_hwqueue_to_fwqueue(skb, hw_queue); + bool firstseg = ((hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); + bool lastseg = ((hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); + dma_addr_t mapping; + u8 bw_40 = 0; + u8 short_gi = 0; + + if (mac->opmode == NL80211_IFTYPE_STATION) { + bw_40 = mac->bw_40; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + if (sta) + bw_40 = sta->ht_cap.cap & + IEEE80211_HT_CAP_SUP_WIDTH_20_40; + } + seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); + /* reserve 8 byte for AMPDU early mode */ + if (rtlhal->earlymode_enable) { + skb_push(skb, EM_HDR_LEN); + memset(skb->data, 0, EM_HDR_LEN); + } + buf_len = skb->len; + mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "DMA mapping error"); + return; + } + CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_8723be)); + if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { + firstseg = true; + lastseg = true; + } + if (firstseg) { + if (rtlhal->earlymode_enable) { + SET_TX_DESC_PKT_OFFSET(pdesc, 1); + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + + EM_HDR_LEN); + if (ptcb_desc->empkt_num) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "Insert 8 byte.pTcb->EMPktNum:%d\n", + ptcb_desc->empkt_num); + _rtl8723be_insert_emcontent(ptcb_desc, + (u8 *)(skb->data)); + } + } else { + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + } + + /* ptcb_desc->use_driver_rate = true; */ + SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); + if (ptcb_desc->hw_rate > DESC92C_RATEMCS0) + short_gi = (ptcb_desc->use_shortgi) ? 1 : 0; + else + short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0; + + SET_TX_DESC_DATA_SHORTGI(pdesc, short_gi); + + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + SET_TX_DESC_AGG_ENABLE(pdesc, 1); + SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); + } + SET_TX_DESC_SEQ(pdesc, seq_number); + SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && + !ptcb_desc->cts_enable) ? + 1 : 0)); + SET_TX_DESC_HW_RTS_ENABLE(pdesc, 0); + SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? + 1 : 0)); + + SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); + + SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); + SET_TX_DESC_RTS_SHORT(pdesc, + ((ptcb_desc->rts_rate <= DESC92C_RATE54M) ? + (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : + (ptcb_desc->rts_use_shortgi ? 1 : 0))); + + if (ptcb_desc->tx_enable_sw_calc_duration) + SET_TX_DESC_NAV_USE_HDR(pdesc, 1); + + if (bw_40) { + if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { + SET_TX_DESC_DATA_BW(pdesc, 1); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, mac->cur_40_prime_sc); + } + } else { + SET_TX_DESC_DATA_BW(pdesc, 0); + SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); + } + + SET_TX_DESC_LINIP(pdesc, 0); + SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb_len); + if (sta) { + u8 ampdu_density = sta->ht_cap.ampdu_density; + SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); + } + if (info->control.hw_key) { + struct ieee80211_key_conf *keyconf = + info->control.hw_key; + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x1); + break; + case WLAN_CIPHER_SUITE_CCMP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x3); + break; + default: + SET_TX_DESC_SEC_TYPE(pdesc, 0x0); + break; + } + } + + SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); + SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); + SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); + SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ? + 1 : 0); + SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); + + /* Set TxRate and RTSRate in TxDesc */ + /* This prevent Tx initial rate of new-coming packets */ + /* from being overwritten by retried packet rate.*/ + if (ieee80211_is_data_qos(fc)) { + if (mac->rdg_en) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "Enable RDG function.\n"); + SET_TX_DESC_RDG_ENABLE(pdesc, 1); + SET_TX_DESC_HTC(pdesc, 1); + } + } + } + + SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); + SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) buf_len); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + /* if (rtlpriv->dm.useramask) { */ + if (1) { + SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); + } else { + SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); + } + if (!ieee80211_is_data_qos(fc)) { + SET_TX_DESC_HWSEQ_EN(pdesc, 1); + SET_TX_DESC_HWSEQ_SEL(pdesc, 0); + } + SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { + SET_TX_DESC_BMC(pdesc, 1); + } + + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); +} + +void rtl8723be_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool firstseg, bool lastseg, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 fw_queue = QSLT_BEACON; + + dma_addr_t mapping = pci_map_single(rtlpci->pdev, + skb->data, skb->len, + PCI_DMA_TODEVICE); + + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); + + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + + SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); + + SET_TX_DESC_SEQ(pdesc, 0); + + SET_TX_DESC_LINIP(pdesc, 0); + + SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); + + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + + SET_TX_DESC_RATE_ID(pdesc, 0); + SET_TX_DESC_MACID(pdesc, 0); + + SET_TX_DESC_OWN(pdesc, 1); + + SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len)); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_USE_RATE(pdesc, 1); + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C Tx Cmd Content\n", pdesc, TX_DESC_SIZE); +} + +void rtl8723be_set_desc(struct ieee80211_hw *hw, u8 *pdesc, + bool istx, u8 desc_name, u8 *val) +{ + if (istx) { + switch (desc_name) { + case HW_DESC_OWN: + SET_TX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_TX_NEXTDESC_ADDR: + SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *)val); + break; + default: + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_RXOWN: + SET_RX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_RXBUFF_ADDR: + SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *)val); + break; + case HW_DESC_RXPKT_LEN: + SET_RX_DESC_PKT_LEN(pdesc, *(u32 *)val); + break; + case HW_DESC_RXERO: + SET_RX_DESC_EOR(pdesc, 1); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); + break; + } + } +} + +u32 rtl8723be_get_desc(u8 *pdesc, bool istx, u8 desc_name) +{ + u32 ret = 0; + + if (istx) { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_TX_DESC_OWN(pdesc); + break; + case HW_DESC_TXBUFF_ADDR: + ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc); + break; + default: + RT_ASSERT(false, "ERR txdesc :%d not process\n", + desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_RX_DESC_OWN(pdesc); + break; + case HW_DESC_RXPKT_LEN: + ret = GET_RX_DESC_PKT_LEN(pdesc); + break; + case HW_DESC_RXBUFF_ADDR: + ret = GET_RX_DESC_BUFF_ADDR(pdesc); + break; + default: + RT_ASSERT(false, "ERR rxdesc :%d not process\n", + desc_name); + break; + } + } + return ret; +} + +bool rtl8723be_is_tx_desc_closed(struct ieee80211_hw *hw, + u8 hw_queue, u16 index) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; + u8 *entry = (u8 *)(&ring->desc[ring->idx]); + u8 own = (u8)rtl8723be_get_desc(entry, true, HW_DESC_OWN); + + /*beacon packet will only use the first + *descriptor defautly,and the own may not + *be cleared by the hardware + */ + if (own) + return false; + return true; +} + +void rtl8723be_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (hw_queue == BEACON_QUEUE) { + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); + } else { + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, + BIT(0) << (hw_queue)); + } +} + +u32 rtl8723be_rx_command_packet(struct ieee80211_hw *hw, + struct rtl_stats status, + struct sk_buff *skb) +{ + u32 result = 0; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (status.packet_report_type) { + case NORMAL_RX: + result = 0; + break; + case C2H_PACKET: + rtl8723be_c2h_packet_handler(hw, skb->data, + (u8)skb->len); + result = 1; + break; + default: + RT_TRACE(rtlpriv, COMP_RECV, DBG_TRACE, + "No this packet type!!\n"); + break; + } + + return result; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h new file mode 100644 index 000000000000..45949ac4854c --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/trx.h @@ -0,0 +1,625 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8723BE_TRX_H__ +#define __RTL8723BE_TRX_H__ + +#define TX_DESC_SIZE 40 +#define TX_DESC_AGGR_SUBFRAME_SIZE 32 + +#define RX_DESC_SIZE 32 +#define RX_DRV_INFO_SIZE_UNIT 8 + +#define TX_DESC_NEXT_DESC_OFFSET 40 +#define USB_HWDESC_HEADER_LEN 40 +#define CRCLENGTH 4 + +#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) +#define SET_TX_DESC_OFFSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) +#define SET_TX_DESC_BMC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) +#define SET_TX_DESC_HTC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) +#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) +#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) +#define SET_TX_DESC_LINIP(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) +#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) +#define SET_TX_DESC_GF(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) +#define SET_TX_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +#define GET_TX_DESC_PKT_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 0, 16) +#define GET_TX_DESC_OFFSET(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 16, 8) +#define GET_TX_DESC_BMC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 24, 1) +#define GET_TX_DESC_HTC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 25, 1) +#define GET_TX_DESC_LAST_SEG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 26, 1) +#define GET_TX_DESC_FIRST_SEG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 27, 1) +#define GET_TX_DESC_LINIP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 28, 1) +#define GET_TX_DESC_NO_ACM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 29, 1) +#define GET_TX_DESC_GF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 30, 1) +#define GET_TX_DESC_OWN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 31, 1) + +#define SET_TX_DESC_MACID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 7, __val) +#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) +#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) +#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) +#define SET_TX_DESC_PIFS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) +#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 5, __val) +#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) +#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) +#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 5, __val) + + +#define SET_TX_DESC_PAID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 9, __val) +#define SET_TX_DESC_CCA_RTS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 10, 2, __val) +#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val) +#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val) +#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val) +#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val) +#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) +#define SET_TX_DESC_RAW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) +#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) +#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) +#define SET_TX_DESC_BT_INT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val) +#define SET_TX_DESC_GID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 6, __val) + + +#define SET_TX_DESC_WHEADER_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 4, __val) +#define SET_TX_DESC_CHK_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 4, 1, __val) +#define SET_TX_DESC_EARLY_MODE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 5, 1, __val) +#define SET_TX_DESC_HWSEQ_SEL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 6, 2, __val) +#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 1, __val) +#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 9, 1, __val) +#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 10, 1, __val) +#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 11, 1, __val) +#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 12, 1, __val) +#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 13, 1, __val) +#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 15, 1, __val) +#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 1, __val) +#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 17, 5, __val) +#define SET_TX_DESC_NDPA(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 22, 2, __val) +#define SET_TX_DESC_AMPDU_MAX_TIME(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 24, 8, __val) + + +#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 7, __val) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 5, __val) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 4, __val) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 17, 1, __val) +#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 6, __val) +#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 5, __val) + + +#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 4, __val) +#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 4, 1, __val) +#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 5, 2, __val) +#define SET_TX_DESC_DATA_LDPC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) +#define SET_TX_DESC_DATA_STBC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 2, __val) +#define SET_TX_DESC_CTROL_STBC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 10, 2, __val) +#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 12, 1, __val) +#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) + + +#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) + +#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) + +#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 15, 1, __val) + +#define SET_TX_DESC_SEQ(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+36, 12, 12, __val) + +#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) + +#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+40, 0, 32) + + +#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+48, 0, 32, __val) + +#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+48, 0, 32) + +#define GET_RX_DESC_PKT_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 0, 14) +#define GET_RX_DESC_CRC32(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 14, 1) +#define GET_RX_DESC_ICV(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 15, 1) +#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 16, 4) +#define GET_RX_DESC_SECURITY(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 20, 3) +#define GET_RX_DESC_QOS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 23, 1) +#define GET_RX_DESC_SHIFT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 24, 2) +#define GET_RX_DESC_PHYST(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 26, 1) +#define GET_RX_DESC_SWDEC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 27, 1) +#define GET_RX_DESC_LS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 28, 1) +#define GET_RX_DESC_FS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 29, 1) +#define GET_RX_DESC_EOR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 30, 1) +#define GET_RX_DESC_OWN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 31, 1) + +#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) +#define SET_RX_DESC_EOR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) +#define SET_RX_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +#define GET_RX_DESC_MACID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 0, 7) +#define GET_RX_DESC_TID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 8, 4) +#define GET_RX_DESC_AMSDU(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) +#define GET_RX_STATUS_DESC_RXID_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) +#define GET_RX_DESC_PAGGR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) +#define GET_RX_DESC_A1_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) +#define GET_RX_DESC_CHKERR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) +#define GET_RX_DESC_IPVER(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) +#define GET_RX_STATUS_DESC_IS_TCPUDP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 22, 1) +#define GET_RX_STATUS_DESC_CHK_VLD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 23, 1) +#define GET_RX_DESC_PAM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) +#define GET_RX_DESC_PWR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) +#define GET_RX_DESC_MD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) +#define GET_RX_DESC_MF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) +#define GET_RX_DESC_TYPE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) +#define GET_RX_DESC_MC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) +#define GET_RX_DESC_BC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) + + +#define GET_RX_DESC_SEQ(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) +#define GET_RX_DESC_FRAG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) +#define GET_RX_STATUS_DESC_RX_IS_QOS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 16, 1) +#define GET_RX_STATUS_DESC_WLANHD_IV_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 18, 6) +#define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 28, 1) + + +#define GET_RX_DESC_RXMCS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 0, 7) +#define GET_RX_DESC_RXHT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 6, 1) +#define GET_RX_STATUS_DESC_RX_GF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 7, 1) +#define GET_RX_DESC_HTC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) +#define GET_RX_STATUS_DESC_EOSP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 11, 1) +#define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 12, 2) + +#define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 29, 1) +#define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 30, 1) +#define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 31, 1) + +#define GET_RX_DESC_SPLCP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 0, 1) +#define GET_RX_STATUS_DESC_LDPC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 1, 1) +#define GET_RX_STATUS_DESC_STBC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 2, 1) +#define GET_RX_DESC_BW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 4, 2) + +#define GET_RX_DESC_TSFL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) + +#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) +#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) + +#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) +#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) + + +/* TX report 2 format in Rx desc*/ + +#define GET_RX_RPT2_DESC_PKT_LEN(__rxstatusdesc) \ + LE_BITS_TO_4BYTE(__rxstatusdesc, 0, 9) +#define GET_RX_RPT2_DESC_MACID_VALID_1(__rxstatusdesc) \ + LE_BITS_TO_4BYTE(__rxstatusdesc+16, 0, 32) +#define GET_RX_RPT2_DESC_MACID_VALID_2(__rxstatusdesc) \ + LE_BITS_TO_4BYTE(__rxstatusdesc+20, 0, 32) + +#define SET_EARLYMODE_PKTNUM(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __value) +#define SET_EARLYMODE_LEN0(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr, 4, 12, __value) +#define SET_EARLYMODE_LEN1(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr, 16, 12, __value) +#define SET_EARLYMODE_LEN2_1(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr, 28, 4, __value) +#define SET_EARLYMODE_LEN2_2(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __value) +#define SET_EARLYMODE_LEN3(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 8, 12, __value) +#define SET_EARLYMODE_LEN4(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __value) + +#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ +do { \ + if (_size > TX_DESC_NEXT_DESC_OFFSET) \ + memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ + else \ + memset(__pdesc, 0, _size); \ +} while (0) + +struct phy_rx_agc_info_t { + #ifdef __LITTLE_ENDIAN + u8 gain:7, trsw:1; + #else + u8 trsw:1, gain:7; + #endif +}; +struct phy_status_rpt { + struct phy_rx_agc_info_t path_agc[2]; + u8 ch_corr[2]; + u8 cck_sig_qual_ofdm_pwdb_all; + u8 cck_agc_rpt_ofdm_cfosho_a; + u8 cck_rpt_b_ofdm_cfosho_b; + u8 rsvd_1;/* ch_corr_msb; */ + u8 noise_power_db_msb; + char path_cfotail[2]; + u8 pcts_mask[2]; + char stream_rxevm[2]; + u8 path_rxsnr[2]; + u8 noise_power_db_lsb; + u8 rsvd_2[3]; + u8 stream_csi[2]; + u8 stream_target_csi[2]; + u8 sig_evm; + u8 rsvd_3; +#ifdef __LITTLE_ENDIAN + u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ + u8 sgi_en:1; + u8 rxsc:2; + u8 idle_long:1; + u8 r_ant_train_en:1; + u8 ant_sel_b:1; + u8 ant_sel:1; +#else /* _BIG_ENDIAN_ */ + u8 ant_sel:1; + u8 ant_sel_b:1; + u8 r_ant_train_en:1; + u8 idle_long:1; + u8 rxsc:2; + u8 sgi_en:1; + u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ +#endif +} __packed; + +struct rx_fwinfo_8723be { + u8 gain_trsw[2]; + u16 chl_num:10; + u16 sub_chnl:4; + u16 r_rfmod:2; + u8 pwdb_all; + u8 cfosho[4]; + u8 cfotail[4]; + char rxevm[2]; + char rxsnr[2]; + u8 pcts_msk_rpt[2]; + u8 pdsnr[2]; + u8 csi_current[2]; + u8 rx_gain_c; + u8 rx_gain_d; + u8 sigevm; + u8 resvd_0; + u8 antidx_anta:3; + u8 antidx_antb:3; + u8 resvd_1:2; +} __packed; + +struct tx_desc_8723be { + u32 pktsize:16; + u32 offset:8; + u32 bmc:1; + u32 htc:1; + u32 lastseg:1; + u32 firstseg:1; + u32 linip:1; + u32 noacm:1; + u32 gf:1; + u32 own:1; + + u32 macid:6; + u32 rsvd0:2; + u32 queuesel:5; + u32 rd_nav_ext:1; + u32 lsig_txop_en:1; + u32 pifs:1; + u32 rateid:4; + u32 nav_usehdr:1; + u32 en_descid:1; + u32 sectype:2; + u32 pktoffset:8; + + u32 rts_rc:6; + u32 data_rc:6; + u32 agg_en:1; + u32 rdg_en:1; + u32 bar_retryht:2; + u32 agg_break:1; + u32 morefrag:1; + u32 raw:1; + u32 ccx:1; + u32 ampdudensity:3; + u32 bt_int:1; + u32 ant_sela:1; + u32 ant_selb:1; + u32 txant_cck:2; + u32 txant_l:2; + u32 txant_ht:2; + + u32 nextheadpage:8; + u32 tailpage:8; + u32 seq:12; + u32 cpu_handle:1; + u32 tag1:1; + u32 trigger_int:1; + u32 hwseq_en:1; + + u32 rtsrate:5; + u32 apdcfe:1; + u32 qos:1; + u32 hwseq_ssn:1; + u32 userrate:1; + u32 dis_rtsfb:1; + u32 dis_datafb:1; + u32 cts2self:1; + u32 rts_en:1; + u32 hwrts_en:1; + u32 portid:1; + u32 pwr_status:3; + u32 waitdcts:1; + u32 cts2ap_en:1; + u32 txsc:2; + u32 stbc:2; + u32 txshort:1; + u32 txbw:1; + u32 rtsshort:1; + u32 rtsbw:1; + u32 rtssc:2; + u32 rtsstbc:2; + + u32 txrate:6; + u32 shortgi:1; + u32 ccxt:1; + u32 txrate_fb_lmt:5; + u32 rtsrate_fb_lmt:4; + u32 retrylmt_en:1; + u32 txretrylmt:6; + u32 usb_txaggnum:8; + + u32 txagca:5; + u32 txagcb:5; + u32 usemaxlen:1; + u32 maxaggnum:5; + u32 mcsg1maxlen:4; + u32 mcsg2maxlen:4; + u32 mcsg3maxlen:4; + u32 mcs7sgimaxlen:4; + + u32 txbuffersize:16; + u32 sw_offset30:8; + u32 sw_offset31:4; + u32 rsvd1:1; + u32 antsel_c:1; + u32 null_0:1; + u32 null_1:1; + + u32 txbuffaddr; + u32 txbufferaddr64; + u32 nextdescaddress; + u32 nextdescaddress64; + + u32 reserve_pass_pcie_mm_limit[4]; +} __packed; + +struct rx_desc_8723be { + u32 length:14; + u32 crc32:1; + u32 icverror:1; + u32 drv_infosize:4; + u32 security:3; + u32 qos:1; + u32 shift:2; + u32 phystatus:1; + u32 swdec:1; + u32 lastseg:1; + u32 firstseg:1; + u32 eor:1; + u32 own:1; + + u32 macid:6; + u32 tid:4; + u32 hwrsvd:5; + u32 paggr:1; + u32 faggr:1; + u32 a1_fit:4; + u32 a2_fit:4; + u32 pam:1; + u32 pwr:1; + u32 moredata:1; + u32 morefrag:1; + u32 type:2; + u32 mc:1; + u32 bc:1; + + u32 seq:12; + u32 frag:4; + u32 nextpktlen:14; + u32 nextind:1; + u32 rsvd:1; + + u32 rxmcs:6; + u32 rxht:1; + u32 amsdu:1; + u32 splcp:1; + u32 bandwidth:1; + u32 htc:1; + u32 tcpchk_rpt:1; + u32 ipcchk_rpt:1; + u32 tcpchk_valid:1; + u32 hwpcerr:1; + u32 hwpcind:1; + u32 iv0:16; + + u32 iv1; + + u32 tsfl; + + u32 bufferaddress; + u32 bufferaddress64; + +} __packed; + +void rtl8723be_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, + u8 *pdesc_tx, u8 *txbd, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); +bool rtl8723be_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *status, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb); +void rtl8723be_set_desc(struct ieee80211_hw *hw, u8 *pdesc, + bool istx, u8 desc_name, u8 *val); +u32 rtl8723be_get_desc(u8 *pdesc, bool istx, u8 desc_name); +bool rtl8723be_is_tx_desc_closed(struct ieee80211_hw *hw, + u8 hw_queue, u16 index); +void rtl8723be_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); +void rtl8723be_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool firstseg, bool lastseg, + struct sk_buff *skb); +u32 rtl8723be_rx_command_packet(struct ieee80211_hw *hw, + struct rtl_stats status, + struct sk_buff *skb); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/Makefile new file mode 100644 index 000000000000..345a68adcf38 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/Makefile @@ -0,0 +1,9 @@ +rtl8723-common-objs := \ + main.o \ + dm_common.o \ + fw_common.o \ + phy_common.o + +obj-$(CONFIG_RTL8723_COMMON) += rtl8723-common.o + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c new file mode 100644 index 000000000000..064340641913 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.c @@ -0,0 +1,65 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "dm_common.h" +#include "../rtl8723ae/dm.h" +#include + +/* These routines are common to RTL8723AE and RTL8723bE */ + +void rtl8723_dm_init_dynamic_txpower(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.dynamic_txpower_enable = false; + + rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; + rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; +} +EXPORT_SYMBOL_GPL(rtl8723_dm_init_dynamic_txpower); + +void rtl8723_dm_init_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtlpriv->dm.current_turbo_edca = false; + rtlpriv->dm.is_any_nonbepkts = false; + rtlpriv->dm.is_cur_rdlstate = false; +} +EXPORT_SYMBOL_GPL(rtl8723_dm_init_edca_turbo); + +void rtl8723_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ps_t *dm_pstable = &rtlpriv->dm_pstable; + + dm_pstable->pre_ccastate = CCA_MAX; + dm_pstable->cur_ccasate = CCA_MAX; + dm_pstable->pre_rfstate = RF_MAX; + dm_pstable->cur_rfstate = RF_MAX; + dm_pstable->rssi_val_min = 0; + dm_pstable->initialize = 0; +} +EXPORT_SYMBOL_GPL(rtl8723_dm_init_dynamic_bb_powersaving); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h new file mode 100644 index 000000000000..5c1b94ce2f86 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/dm_common.h @@ -0,0 +1,33 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __DM_COMMON_H__ +#define __DM_COMMON_H__ + +void rtl8723_dm_init_dynamic_txpower(struct ieee80211_hw *hw); +void rtl8723_dm_init_edca_turbo(struct ieee80211_hw *hw); +void rtl8723_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c new file mode 100644 index 000000000000..a2f5e89bedfe --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c @@ -0,0 +1,339 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "fw_common.h" +#include + +void rtl8723_enable_fw_download(struct ieee80211_hw *hw, bool enable) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp; + + if (enable) { + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, + tmp | 0x04); + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); + rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); + } else { + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); + + rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00); + } +} +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) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 *bufferptr = buffer; + u32 page_nums, remain_size; + u32 page, offset; + + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size); + + rtl8723_fill_dummy(bufferptr, &size); + + page_nums = size / FW_8192C_PAGE_SIZE; + remain_size = size % FW_8192C_PAGE_SIZE; + + if (page_nums > max_page) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Page numbers should not greater than %d\n", max_page); + } + 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); + } + + if (remain_size) { + offset = page_nums * FW_8192C_PAGE_SIZE; + page = page_nums; + rtl8723_fw_page_write(hw, page, (bufferptr + offset), + remain_size); + } + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW write done.\n"); +} +EXPORT_SYMBOL_GPL(rtl8723_write_fw); + +void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw) +{ + u8 u1b_tmp; + u8 delay = 100; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20); + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + + while (u1b_tmp & BIT(2)) { + delay--; + if (delay == 0) + break; + udelay(50); + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + } + if (delay == 0) { + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, + u1b_tmp&(~BIT(2))); + } +} +EXPORT_SYMBOL_GPL(rtl8723ae_firmware_selfreset); + +void rtl8723be_firmware_selfreset(struct ieee80211_hw *hw) +{ + u8 u1b_tmp; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); + udelay(50); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0))); + + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2))); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + " _8051Reset8723be(): 8051 reset success .\n"); +} +EXPORT_SYMBOL_GPL(rtl8723be_firmware_selfreset); + +int rtl8723_fw_free_to_go(struct ieee80211_hw *hw, bool is_8723be, + int max_count) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int err = -EIO; + u32 counter = 0; + u32 value32; + + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + } while ((counter++ < max_count) && + (!(value32 & FWDL_CHKSUM_RPT))); + + if (counter >= max_count) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "chksum report fail ! REG_MCUFWDL:0x%08x .\n", + value32); + goto exit; + } + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); + + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL) | MCUFWDL_RDY; + value32 &= ~WINTINI_RDY; + rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); + + if (is_8723be) + rtl8723be_firmware_selfreset(hw); + counter = 0; + + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + if (value32 & WINTINI_RDY) { + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n", + value32); + err = 0; + goto exit; + } + + mdelay(FW_8192C_POLLING_DELAY); + + } while (counter++ < max_count); + + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", + value32); + +exit: + return err; +} +EXPORT_SYMBOL_GPL(rtl8723_fw_free_to_go); + +int rtl8723_download_fw(struct ieee80211_hw *hw, + bool is_8723be, int max_count) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtlwifi_firmware_header *pfwheader; + u8 *pfwdata; + u32 fwsize; + int err; + enum version_8723e version = rtlhal->version; + int max_page; + + if (!rtlhal->pfirmware) + return 1; + + pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; + pfwdata = rtlhal->pfirmware; + fwsize = rtlhal->fwsize; + + if (!is_8723be) + max_page = 6; + else + max_page = 8; + if (rtlpriv->cfg->ops->is_fw_header(pfwheader)) { + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "Firmware Version(%d), Signature(%#x), Size(%d)\n", + pfwheader->version, pfwheader->signature, + (int)sizeof(struct rtlwifi_firmware_header)); + + pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); + fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); + } + + if (rtl_read_byte(rtlpriv, REG_MCUFWDL)&BIT(7)) { + if (is_8723be) + rtl8723be_firmware_selfreset(hw); + else + rtl8723ae_firmware_selfreset(hw); + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); + } + rtl8723_enable_fw_download(hw, true); + rtl8723_write_fw(hw, version, pfwdata, fwsize, max_page); + rtl8723_enable_fw_download(hw, false); + + err = rtl8723_fw_free_to_go(hw, is_8723be, max_count); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Firmware is not ready to run!\n"); + } else { + RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, + "Firmware is ready to run!\n"); + } + return 0; +} +EXPORT_SYMBOL_GPL(rtl8723_download_fw); + +bool rtl8723_cmd_send_packet(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + struct rtl_tx_desc *pdesc; + struct sk_buff *pskb = NULL; + u8 own; + unsigned long flags; + + ring = &rtlpci->tx_ring[BEACON_QUEUE]; + + pskb = __skb_dequeue(&ring->queue); + if (pskb) + kfree_skb(pskb); + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + + pdesc = &ring->desc[0]; + own = (u8) rtlpriv->cfg->ops->get_desc((u8 *)pdesc, true, HW_DESC_OWN); + + rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); + + __skb_queue_tail(&ring->queue, skb); + + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); + + rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); + + return true; +} +EXPORT_SYMBOL_GPL(rtl8723_cmd_send_packet); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h new file mode 100644 index 000000000000..8ea372d1626e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __FW_COMMON_H__ +#define __FW_COMMON_H__ + +#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 +#define FW_8192C_POLLING_DELAY 5 + +#define MCUFWDL_RDY BIT(1) +#define FWDL_CHKSUM_RPT BIT(2) +#define WINTINI_RDY BIT(6) + +#define REG_RSV_CTRL 0x001C +#define REG_HMETFR 0x01CC + +enum version_8723e { + VERSION_TEST_UMC_CHIP_8723 = 0x0081, + VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT = 0x0089, + VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT = 0x1089, + VERSION_TEST_CHIP_1T1R_8723B = 0x0106, + VERSION_NORMAL_SMIC_CHIP_1T1R_8723B = 0x010E, + VERSION_UNKNOWN = 0xFF, +}; + +enum rtl8723be_cmd { + H2C_8723BE_RSVDPAGE = 0, + H2C_8723BE_JOINBSSRPT = 1, + H2C_8723BE_SCAN = 2, + H2C_8723BE_KEEP_ALIVE_CTRL = 3, + H2C_8723BE_DISCONNECT_DECISION = 4, + H2C_8723BE_INIT_OFFLOAD = 6, + H2C_8723BE_AP_OFFLOAD = 8, + H2C_8723BE_BCN_RSVDPAGE = 9, + H2C_8723BE_PROBERSP_RSVDPAGE = 10, + + H2C_8723BE_SETPWRMODE = 0x20, + H2C_8723BE_PS_TUNING_PARA = 0x21, + H2C_8723BE_PS_TUNING_PARA2 = 0x22, + H2C_8723BE_PS_LPS_PARA = 0x23, + H2C_8723BE_P2P_PS_OFFLOAD = 0x24, + + H2C_8723BE_WO_WLAN = 0x80, + H2C_8723BE_REMOTE_WAKE_CTRL = 0x81, + H2C_8723BE_AOAC_GLOBAL_INFO = 0x82, + H2C_8723BE_AOAC_RSVDPAGE = 0x83, + H2C_8723BE_RSSI_REPORT = 0x42, + H2C_8723BE_RA_MASK = 0x40, + H2C_8723BE_SELECTIVE_SUSPEND_ROF_CMD, + H2C_8723BE_P2P_PS_MODE, + H2C_8723BE_PSD_RESULT, + /*Not defined CTW CMD for P2P yet*/ + H2C_8723BE_P2P_PS_CTW_CMD, + MAX_8723BE_H2CCMD +}; + +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); +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/rtl8723com/main.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c new file mode 100644 index 000000000000..9014a94fac6a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/main.c @@ -0,0 +1,33 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include + + +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Realtek RTL8723AE/RTL8723BE 802.11n PCI wireless common routines"); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c new file mode 100644 index 000000000000..75cbd1509b52 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c @@ -0,0 +1,447 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "phy_common.h" +#include "../rtl8723ae/reg.h" +#include + +/* These routines are common to RTL8723AE and RTL8723bE */ + +u32 rtl8723_phy_query_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 returnvalue, originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask); + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = rtl8723_phy_calculate_bit_shift(bitmask); + returnvalue = (originalvalue & bitmask) >> bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "BBR MASK=0x%x Addr[0x%x]=0x%x\n", bitmask, + regaddr, originalvalue); + return returnvalue; +} +EXPORT_SYMBOL_GPL(rtl8723_phy_query_bb_reg); + +void rtl8723_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, + u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", regaddr, bitmask, + data); + + if (bitmask != MASKDWORD) { + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = rtl8723_phy_calculate_bit_shift(bitmask); + data = ((originalvalue & (~bitmask)) | (data << bitshift)); + } + + rtl_write_dword(rtlpriv, regaddr, data); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); +} +EXPORT_SYMBOL_GPL(rtl8723_phy_set_bb_reg); + +u32 rtl8723_phy_calculate_bit_shift(u32 bitmask) +{ + u32 i; + + for (i = 0; i <= 31; i++) { + if (((bitmask >> i) & 0x1) == 1) + break; + } + return i; +} +EXPORT_SYMBOL_GPL(rtl8723_phy_calculate_bit_shift); + +u32 rtl8723_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + u32 newoffset; + u32 tmplong, tmplong2; + u8 rfpi_enable = 0; + u32 retvalue; + + offset &= 0xff; + newoffset = offset; + if (RT_CANNOT_IO(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n"); + return 0xFFFFFFFF; + } + tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); + if (rfpath == RF90_PATH_A) + tmplong2 = tmplong; + else + tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); + tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | + (newoffset << 23) | BLSSIREADEDGE; + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, + tmplong & (~BLSSIREADEDGE)); + mdelay(1); + rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); + mdelay(1); + rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, + tmplong | BLSSIREADEDGE); + mdelay(1); + if (rfpath == RF90_PATH_A) + rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, + BIT(8)); + else if (rfpath == RF90_PATH_B) + rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, + BIT(8)); + if (rfpi_enable) + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, + BLSSIREADBACKDATA); + else + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, + BLSSIREADBACKDATA); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "RFR-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf_rb, retvalue); + return retvalue; +} +EXPORT_SYMBOL_GPL(rtl8723_phy_rf_serial_read); + +void rtl8723_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 offset, u32 data) +{ + u32 data_and_addr; + u32 newoffset; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + + if (RT_CANNOT_IO(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n"); + return; + } + offset &= 0xff; + newoffset = offset; + data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; + rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "RFW-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf3wire_offset, + data_and_addr); +} +EXPORT_SYMBOL_GPL(rtl8723_phy_rf_serial_write); + +long rtl8723_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u8 txpwridx) +{ + long offset; + long pwrout_dbm; + + switch (wirelessmode) { + case WIRELESS_MODE_B: + offset = -7; + break; + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + offset = -8; + break; + default: + offset = -8; + break; + } + pwrout_dbm = txpwridx / 2 + offset; + return pwrout_dbm; +} +EXPORT_SYMBOL_GPL(rtl8723_phy_txpwr_idx_to_dbm); + +void rtl8723_phy_init_bb_rf_reg_def(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + + rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; + rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; + + rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = + RFPGA0_XA_LSSIPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = + RFPGA0_XB_LSSIPARAMETER; + + rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; + rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; + + rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; + rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; + + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; + + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; + + rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; + rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; + + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; + + rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; + rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; + + rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBANLANCE; + rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; + + rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; + + rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE; + rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE; + + rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; + rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; + rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE; + rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; + + rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK; + rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK; + + rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK; + rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK; + +} +EXPORT_SYMBOL_GPL(rtl8723_phy_init_bb_rf_reg_def); + +bool rtl8723_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, + u32 cmdtablesz, + enum swchnlcmd_id cmdid, + u32 para1, u32 para2, + u32 msdelay) +{ + struct swchnlcmd *pcmd; + + if (cmdtable == NULL) { + RT_ASSERT(false, "cmdtable cannot be NULL.\n"); + return false; + } + + if (cmdtableidx >= cmdtablesz) + return false; + + pcmd = cmdtable + cmdtableidx; + pcmd->cmdid = cmdid; + pcmd->para1 = para1; + pcmd->para2 = para2; + pcmd->msdelay = msdelay; + return true; +} +EXPORT_SYMBOL_GPL(rtl8723_phy_set_sw_chnl_cmdarray); + +void rtl8723_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, + bool iqk_ok, + long result[][8], + u8 final_candidate, + bool btxonly) +{ + u32 oldval_0, x, tx0_a, reg; + long y, tx0_c; + + if (final_candidate == 0xFF) { + return; + } else if (iqk_ok) { + oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, + MASKDWORD) >> 22) & 0x3FF; + x = result[final_candidate][0]; + if ((x & 0x00000200) != 0) + x = x | 0xFFFFFC00; + tx0_a = (x * oldval_0) >> 8; + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31), + ((x * oldval_0 >> 7) & 0x1)); + y = result[final_candidate][1]; + if ((y & 0x00000200) != 0) + y = y | 0xFFFFFC00; + tx0_c = (y * oldval_0) >> 8; + rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, + ((tx0_c & 0x3C0) >> 6)); + rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000, + (tx0_c & 0x3F)); + rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29), + ((y * oldval_0 >> 7) & 0x1)); + if (btxonly) + return; + reg = result[final_candidate][2]; + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg); + reg = result[final_candidate][3] & 0x3F; + rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg); + reg = (result[final_candidate][3] >> 6) & 0xF; + rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); + } +} +EXPORT_SYMBOL_GPL(rtl8723_phy_path_a_fill_iqk_matrix); + +void rtl8723_save_adda_registers(struct ieee80211_hw *hw, u32 *addareg, + u32 *addabackup, u32 registernum) +{ + u32 i; + + for (i = 0; i < registernum; i++) + addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD); +} +EXPORT_SYMBOL_GPL(rtl8723_save_adda_registers); + +void rtl8723_phy_save_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) + macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); + macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); +} +EXPORT_SYMBOL_GPL(rtl8723_phy_save_mac_registers); + +void rtl8723_phy_reload_adda_registers(struct ieee80211_hw *hw, + u32 *addareg, u32 *addabackup, + u32 regiesternum) +{ + u32 i; + + for (i = 0; i < regiesternum; i++) + rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]); +} +EXPORT_SYMBOL_GPL(rtl8723_phy_reload_adda_registers); + +void rtl8723_phy_reload_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) + rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]); + rtl_write_dword(rtlpriv, macreg[i], macbackup[i]); +} +EXPORT_SYMBOL_GPL(rtl8723_phy_reload_mac_registers); + +void rtl8723_phy_path_adda_on(struct ieee80211_hw *hw, u32 *addareg, + bool is_patha_on, bool is2t) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 pathon; + u32 i; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723AE) { + pathon = is_patha_on ? 0x04db25a4 : 0x0b1b25a4; + if (!is2t) { + pathon = 0x0bdb25a0; + rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0); + } else { + rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon); + } + } else { + /* rtl8723be */ + pathon = 0x01c00014; + rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon); + } + + for (i = 1; i < IQK_ADDA_REG_NUM; i++) + rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathon); +} +EXPORT_SYMBOL_GPL(rtl8723_phy_path_adda_on); + +void rtl8723_phy_mac_setting_calibration(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i = 0; + + rtl_write_byte(rtlpriv, macreg[i], 0x3F); + + for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) + rtl_write_byte(rtlpriv, macreg[i], + (u8) (macbackup[i] & (~BIT(3)))); + rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5)))); +} +EXPORT_SYMBOL_GPL(rtl8723_phy_mac_setting_calibration); + +void rtl8723_phy_path_a_standby(struct ieee80211_hw *hw) +{ + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); + rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); + rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); +} +EXPORT_SYMBOL_GPL(rtl8723_phy_path_a_standby); + +void rtl8723_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode) +{ + u32 mode; + + mode = pi_mode ? 0x01000100 : 0x01000000; + rtl_set_bbreg(hw, 0x820, MASKDWORD, mode); + rtl_set_bbreg(hw, 0x828, MASKDWORD, mode); +} +EXPORT_SYMBOL_GPL(rtl8723_phy_pi_mode_switch); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h new file mode 100644 index 000000000000..83b891a9adb8 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.h @@ -0,0 +1,89 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2014 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __PHY_COMMON__ +#define __PHY_COMMON__ + +#define RT_CANNOT_IO(hw) false + +enum swchnlcmd_id { + CMDID_END, + CMDID_SET_TXPOWEROWER_LEVEL, + CMDID_BBREGWRITE10, + CMDID_WRITEPORT_ULONG, + CMDID_WRITEPORT_USHORT, + CMDID_WRITEPORT_UCHAR, + CMDID_RF_WRITEREG, +}; + +struct swchnlcmd { + enum swchnlcmd_id cmdid; + u32 para1; + u32 para2; + u32 msdelay; +}; + +u32 rtl8723_phy_query_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask); +void rtl8723_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, + u32 bitmask, u32 data); +u32 rtl8723_phy_calculate_bit_shift(u32 bitmask); +u32 rtl8723_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +void rtl8723_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 offset, u32 data); +long rtl8723_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u8 txpwridx); +void rtl8723_phy_init_bb_rf_reg_def(struct ieee80211_hw *hw); +bool rtl8723_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, + u32 cmdtableidx, + u32 cmdtablesz, + enum swchnlcmd_id cmdid, + u32 para1, u32 para2, + u32 msdelay); +void rtl8723_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, + bool iqk_ok, + long result[][8], + u8 final_candidate, + bool btxonly); +void rtl8723_save_adda_registers(struct ieee80211_hw *hw, u32 *addareg, + u32 *addabackup, u32 registernum); +void rtl8723_phy_save_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup); +void rtl8723_phy_reload_adda_registers(struct ieee80211_hw *hw, + u32 *addareg, u32 *addabackup, + u32 regiesternum); +void rtl8723_phy_reload_mac_registers(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup); +void rtl8723_phy_path_adda_on(struct ieee80211_hw *hw, u32 *addareg, + bool is_patha_on, bool is2t); +void rtl8723_phy_mac_setting_calibration(struct ieee80211_hw *hw, + u32 *macreg, u32 *macbackup); +void rtl8723_phy_path_a_standby(struct ieee80211_hw *hw); +void rtl8723_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/Makefile b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/Makefile new file mode 100644 index 000000000000..f7a26f71197e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/Makefile @@ -0,0 +1,16 @@ +rtl8821ae-objs := \ + dm.o \ + fw.o \ + hw.o \ + led.o \ + phy.o \ + pwrseq.o \ + rf.o \ + sw.o \ + table.o \ + trx.o \ + + +obj-$(CONFIG_RTL8821AE) += rtl8821ae.o + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h new file mode 100644 index 000000000000..dfbdf539de1a --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/def.h @@ -0,0 +1,355 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8821AE_DEF_H__ +#define __RTL8821AE_DEF_H__ + +/*--------------------------Define -------------------------------------------*/ +#define USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN 1 + +/* BIT 7 HT Rate*/ +/*TxHT = 0*/ +#define MGN_1M 0x02 +#define MGN_2M 0x04 +#define MGN_5_5M 0x0b +#define MGN_11M 0x16 + +#define MGN_6M 0x0c +#define MGN_9M 0x12 +#define MGN_12M 0x18 +#define MGN_18M 0x24 +#define MGN_24M 0x30 +#define MGN_36M 0x48 +#define MGN_48M 0x60 +#define MGN_54M 0x6c + +/* TxHT = 1 */ +#define MGN_MCS0 0x80 +#define MGN_MCS1 0x81 +#define MGN_MCS2 0x82 +#define MGN_MCS3 0x83 +#define MGN_MCS4 0x84 +#define MGN_MCS5 0x85 +#define MGN_MCS6 0x86 +#define MGN_MCS7 0x87 +#define MGN_MCS8 0x88 +#define MGN_MCS9 0x89 +#define MGN_MCS10 0x8a +#define MGN_MCS11 0x8b +#define MGN_MCS12 0x8c +#define MGN_MCS13 0x8d +#define MGN_MCS14 0x8e +#define MGN_MCS15 0x8f +/* VHT rate */ +#define MGN_VHT1SS_MCS0 0x90 +#define MGN_VHT1SS_MCS1 0x91 +#define MGN_VHT1SS_MCS2 0x92 +#define MGN_VHT1SS_MCS3 0x93 +#define MGN_VHT1SS_MCS4 0x94 +#define MGN_VHT1SS_MCS5 0x95 +#define MGN_VHT1SS_MCS6 0x96 +#define MGN_VHT1SS_MCS7 0x97 +#define MGN_VHT1SS_MCS8 0x98 +#define MGN_VHT1SS_MCS9 0x99 +#define MGN_VHT2SS_MCS0 0x9a +#define MGN_VHT2SS_MCS1 0x9b +#define MGN_VHT2SS_MCS2 0x9c +#define MGN_VHT2SS_MCS3 0x9d +#define MGN_VHT2SS_MCS4 0x9e +#define MGN_VHT2SS_MCS5 0x9f +#define MGN_VHT2SS_MCS6 0xa0 +#define MGN_VHT2SS_MCS7 0xa1 +#define MGN_VHT2SS_MCS8 0xa2 +#define MGN_VHT2SS_MCS9 0xa3 + +#define MGN_VHT3SS_MCS0 0xa4 +#define MGN_VHT3SS_MCS1 0xa5 +#define MGN_VHT3SS_MCS2 0xa6 +#define MGN_VHT3SS_MCS3 0xa7 +#define MGN_VHT3SS_MCS4 0xa8 +#define MGN_VHT3SS_MCS5 0xa9 +#define MGN_VHT3SS_MCS6 0xaa +#define MGN_VHT3SS_MCS7 0xab +#define MGN_VHT3SS_MCS8 0xac +#define MGN_VHT3SS_MCS9 0xad + +#define MGN_MCS0_SG 0xc0 +#define MGN_MCS1_SG 0xc1 +#define MGN_MCS2_SG 0xc2 +#define MGN_MCS3_SG 0xc3 +#define MGN_MCS4_SG 0xc4 +#define MGN_MCS5_SG 0xc5 +#define MGN_MCS6_SG 0xc6 +#define MGN_MCS7_SG 0xc7 +#define MGN_MCS8_SG 0xc8 +#define MGN_MCS9_SG 0xc9 +#define MGN_MCS10_SG 0xca +#define MGN_MCS11_SG 0xcb +#define MGN_MCS12_SG 0xcc +#define MGN_MCS13_SG 0xcd +#define MGN_MCS14_SG 0xce +#define MGN_MCS15_SG 0xcf + +#define MGN_UNKNOWN 0xff + +/* 30 ms */ +#define WIFI_NAV_UPPER_US 30000 +#define HAL_92C_NAV_UPPER_UNIT 128 + +#define MAX_RX_DMA_BUFFER_SIZE 0x3E80 + +#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 +#define HAL_PRIME_CHNL_OFFSET_LOWER 1 +#define HAL_PRIME_CHNL_OFFSET_UPPER 2 + +#define RX_MPDU_QUEUE 0 +#define RX_CMD_QUEUE 1 + +#define MAX_RX_DMA_BUFFER_SIZE_8812 0x3E80 + +#define C2H_RX_CMD_HDR_LEN 8 +#define GET_C2H_CMD_CMD_LEN(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 0, 16) +#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 16, 8) +#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 24, 7) +#define GET_C2H_CMD_CONTINUE(__prxhdr) \ + LE_BITS_TO_4BYTE((__prxhdr), 31, 1) +#define GET_C2H_CMD_CONTENT(__prxhdr) \ + ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) + +#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) +#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) +#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ + LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) + +#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) + +#define CHIP_8812 BIT(2) +#define CHIP_8821 (BIT(0)|BIT(2)) + +#define CHIP_8821A (BIT(0)|BIT(2)) +#define NORMAL_CHIP BIT(3) +#define RF_TYPE_1T1R (~(BIT(4)|BIT(5)|BIT(6))) +#define RF_TYPE_1T2R BIT(4) +#define RF_TYPE_2T2R BIT(5) +#define CHIP_VENDOR_UMC BIT(7) +#define B_CUT_VERSION BIT(12) +#define C_CUT_VERSION BIT(13) +#define D_CUT_VERSION ((BIT(12)|BIT(13))) +#define E_CUT_VERSION BIT(14) +#define RF_RL_ID (BIT(31)|BIT(30)|BIT(29)|BIT(28)) + +enum version_8821ae { + VERSION_TEST_CHIP_1T1R_8812 = 0x0004, + VERSION_TEST_CHIP_2T2R_8812 = 0x0024, + VERSION_NORMAL_TSMC_CHIP_1T1R_8812 = 0x100c, + VERSION_NORMAL_TSMC_CHIP_2T2R_8812 = 0x102c, + VERSION_NORMAL_TSMC_CHIP_1T1R_8812_C_CUT = 0x200c, + VERSION_NORMAL_TSMC_CHIP_2T2R_8812_C_CUT = 0x202c, + VERSION_TEST_CHIP_8821 = 0x0005, + VERSION_NORMAL_TSMC_CHIP_8821 = 0x000d, + VERSION_NORMAL_TSMC_CHIP_8821_B_CUT = 0x100d, + VERSION_UNKNOWN = 0xFF, +}; + +enum vht_data_sc { + VHT_DATA_SC_DONOT_CARE = 0, + VHT_DATA_SC_20_UPPER_OF_80MHZ = 1, + VHT_DATA_SC_20_LOWER_OF_80MHZ = 2, + VHT_DATA_SC_20_UPPERST_OF_80MHZ = 3, + VHT_DATA_SC_20_LOWEST_OF_80MHZ = 4, + VHT_DATA_SC_20_RECV1 = 5, + VHT_DATA_SC_20_RECV2 = 6, + VHT_DATA_SC_20_RECV3 = 7, + VHT_DATA_SC_20_RECV4 = 8, + VHT_DATA_SC_40_UPPER_OF_80MHZ = 9, + VHT_DATA_SC_40_LOWER_OF_80MHZ = 10, +}; + +/* MASK */ +#define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2)) +#define CHIP_TYPE_MASK BIT(3) +#define RF_TYPE_MASK (BIT(4)|BIT(5)|BIT(6)) +#define MANUFACTUER_MASK BIT(7) +#define ROM_VERSION_MASK (BIT(11)|BIT(10)|BIT(9)|BIT(8)) +#define CUT_VERSION_MASK (BIT(15)|BIT(14)|BIT(13)|BIT(12)) + +/* Get element */ +#define GET_CVID_IC_TYPE(version) ((version) & IC_TYPE_MASK) +#define GET_CVID_CHIP_TYPE(version) ((version) & CHIP_TYPE_MASK) +#define GET_CVID_RF_TYPE(version) ((version) & RF_TYPE_MASK) +#define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK) +#define GET_CVID_ROM_VERSION(version) ((version) & ROM_VERSION_MASK) +#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK) + +#define IS_1T1R(version) ((GET_CVID_RF_TYPE(version)) ? false : true) +#define IS_1T2R(version) ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R)\ + ? true : false) +#define IS_2T2R(version) ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R)\ + ? true : false) + +#define IS_8812_SERIES(version) ((GET_CVID_IC_TYPE(version) == CHIP_8812) ? \ + true : false) +#define IS_8821_SERIES(version) ((GET_CVID_IC_TYPE(version) == CHIP_8821) ? \ + true : false) + +#define IS_VENDOR_8812A_TEST_CHIP(version) ((IS_8812_SERIES(version)) ? \ + ((IS_NORMAL_CHIP(version)) ? \ + false : true) : false) +#define IS_VENDOR_8812A_MP_CHIP(version) ((IS_8812_SERIES(version)) ? \ + ((IS_NORMAL_CHIP(version)) ? \ + true : false) : false) +#define IS_VENDOR_8812A_C_CUT(version) ((IS_8812_SERIES(version)) ? \ + ((GET_CVID_CUT_VERSION(version) == \ + C_CUT_VERSION) ? \ + true : false) : false) + +#define IS_VENDOR_8821A_TEST_CHIP(version) ((IS_8821_SERIES(version)) ? \ + ((IS_NORMAL_CHIP(version)) ? \ + false : true) : false) +#define IS_VENDOR_8821A_MP_CHIP(version) ((IS_8821_SERIES(version)) ? \ + ((IS_NORMAL_CHIP(version)) ? \ + true : false) : false) +#define IS_VENDOR_8821A_B_CUT(version) ((IS_8821_SERIES(version)) ? \ + ((GET_CVID_CUT_VERSION(version) == \ + B_CUT_VERSION) ? \ + true : false) : false) +enum board_type { + ODM_BOARD_DEFAULT = 0, /* The DEFAULT case. */ + ODM_BOARD_MINICARD = BIT(0), /* 0 = non-mini card, 1 = mini card. */ + ODM_BOARD_SLIM = BIT(1), /* 0 = non-slim card, 1 = slim card */ + ODM_BOARD_BT = BIT(2), /* 0 = without BT card, 1 = with BT */ + ODM_BOARD_EXT_PA = BIT(3), /* 1 = existing 2G ext-PA */ + ODM_BOARD_EXT_LNA = BIT(4), /* 1 = existing 2G ext-LNA */ + ODM_BOARD_EXT_TRSW = BIT(5), /* 1 = existing ext-TRSW */ + ODM_BOARD_EXT_PA_5G = BIT(6), /* 1 = existing 5G ext-PA */ + ODM_BOARD_EXT_LNA_5G = BIT(7), /* 1 = existing 5G ext-LNA */ +}; + +enum rf_optype { + RF_OP_BY_SW_3WIRE = 0, + RF_OP_BY_FW, + RF_OP_MAX +}; + +enum rf_power_state { + RF_ON, + RF_OFF, + RF_SLEEP, + RF_SHUT_DOWN, +}; + +enum power_save_mode { + POWER_SAVE_MODE_ACTIVE, + POWER_SAVE_MODE_SAVE, +}; + +enum power_polocy_config { + POWERCFG_MAX_POWER_SAVINGS, + POWERCFG_GLOBAL_POWER_SAVINGS, + POWERCFG_LOCAL_POWER_SAVINGS, + POWERCFG_LENOVO, +}; + +enum interface_select_pci { + INTF_SEL1_MINICARD = 0, + INTF_SEL0_PCIE = 1, + INTF_SEL2_RSV = 2, + INTF_SEL3_RSV = 3, +}; + +enum hal_fw_c2h_cmd_id { + HAL_FW_C2H_CMD_READ_MACREG = 0, + HAL_FW_C2H_CMD_READ_BBREG = 1, + HAL_FW_C2H_CMD_READ_RFREG = 2, + HAL_FW_C2H_CMD_READ_EEPROM = 3, + HAL_FW_C2H_CMD_READ_EFUSE = 4, + HAL_FW_C2H_CMD_READ_CAM = 5, + HAL_FW_C2H_CMD_GET_BASICRATE = 6, + HAL_FW_C2H_CMD_GET_DATARATE = 7, + HAL_FW_C2H_CMD_SURVEY = 8, + HAL_FW_C2H_CMD_SURVEYDONE = 9, + HAL_FW_C2H_CMD_JOINBSS = 10, + HAL_FW_C2H_CMD_ADDSTA = 11, + HAL_FW_C2H_CMD_DELSTA = 12, + HAL_FW_C2H_CMD_ATIMDONE = 13, + HAL_FW_C2H_CMD_TX_REPORT = 14, + HAL_FW_C2H_CMD_CCX_REPORT = 15, + HAL_FW_C2H_CMD_DTM_REPORT = 16, + HAL_FW_C2H_CMD_TX_RATE_STATISTICS = 17, + HAL_FW_C2H_CMD_C2HLBK = 18, + HAL_FW_C2H_CMD_C2HDBG = 19, + HAL_FW_C2H_CMD_C2HFEEDBACK = 20, + HAL_FW_C2H_CMD_MAX +}; + +enum rtl_desc_qsel { + QSLT_BK = 0x2, + QSLT_BE = 0x0, + QSLT_VI = 0x5, + QSLT_VO = 0x7, + QSLT_BEACON = 0x10, + QSLT_HIGH = 0x11, + QSLT_MGNT = 0x12, + QSLT_CMD = 0x13, +}; + +enum rx_packet_type { + NORMAL_RX, + TX_REPORT1, + TX_REPORT2, + HIS_REPORT, + C2H_PACKET, +}; + +struct phy_sts_cck_8821ae_t { + u8 adc_pwdb_X[4]; + u8 sq_rpt; + u8 cck_agc_rpt; +}; + +struct h2c_cmd_8821ae { + u8 element_id; + u32 cmd_len; + u8 *p_cmdbuffer; +}; + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c new file mode 100644 index 000000000000..b57cfd965196 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c @@ -0,0 +1,2988 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../base.h" +#include "../pci.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "trx.h" +#include "../btcoexist/rtl_btc.h" + +static const u32 txscaling_tbl[TXSCALE_TABLE_SIZE] = { + 0x081, /* 0, -12.0dB */ + 0x088, /* 1, -11.5dB */ + 0x090, /* 2, -11.0dB */ + 0x099, /* 3, -10.5dB */ + 0x0A2, /* 4, -10.0dB */ + 0x0AC, /* 5, -9.5dB */ + 0x0B6, /* 6, -9.0dB */ + 0x0C0, /* 7, -8.5dB */ + 0x0CC, /* 8, -8.0dB */ + 0x0D8, /* 9, -7.5dB */ + 0x0E5, /* 10, -7.0dB */ + 0x0F2, /* 11, -6.5dB */ + 0x101, /* 12, -6.0dB */ + 0x110, /* 13, -5.5dB */ + 0x120, /* 14, -5.0dB */ + 0x131, /* 15, -4.5dB */ + 0x143, /* 16, -4.0dB */ + 0x156, /* 17, -3.5dB */ + 0x16A, /* 18, -3.0dB */ + 0x180, /* 19, -2.5dB */ + 0x197, /* 20, -2.0dB */ + 0x1AF, /* 21, -1.5dB */ + 0x1C8, /* 22, -1.0dB */ + 0x1E3, /* 23, -0.5dB */ + 0x200, /* 24, +0 dB */ + 0x21E, /* 25, +0.5dB */ + 0x23E, /* 26, +1.0dB */ + 0x261, /* 27, +1.5dB */ + 0x285, /* 28, +2.0dB */ + 0x2AB, /* 29, +2.5dB */ + 0x2D3, /* 30, +3.0dB */ + 0x2FE, /* 31, +3.5dB */ + 0x32B, /* 32, +4.0dB */ + 0x35C, /* 33, +4.5dB */ + 0x38E, /* 34, +5.0dB */ + 0x3C4, /* 35, +5.5dB */ + 0x3FE /* 36, +6.0dB */ +}; + +static const u32 rtl8821ae_txscaling_table[TXSCALE_TABLE_SIZE] = { + 0x081, /* 0, -12.0dB */ + 0x088, /* 1, -11.5dB */ + 0x090, /* 2, -11.0dB */ + 0x099, /* 3, -10.5dB */ + 0x0A2, /* 4, -10.0dB */ + 0x0AC, /* 5, -9.5dB */ + 0x0B6, /* 6, -9.0dB */ + 0x0C0, /* 7, -8.5dB */ + 0x0CC, /* 8, -8.0dB */ + 0x0D8, /* 9, -7.5dB */ + 0x0E5, /* 10, -7.0dB */ + 0x0F2, /* 11, -6.5dB */ + 0x101, /* 12, -6.0dB */ + 0x110, /* 13, -5.5dB */ + 0x120, /* 14, -5.0dB */ + 0x131, /* 15, -4.5dB */ + 0x143, /* 16, -4.0dB */ + 0x156, /* 17, -3.5dB */ + 0x16A, /* 18, -3.0dB */ + 0x180, /* 19, -2.5dB */ + 0x197, /* 20, -2.0dB */ + 0x1AF, /* 21, -1.5dB */ + 0x1C8, /* 22, -1.0dB */ + 0x1E3, /* 23, -0.5dB */ + 0x200, /* 24, +0 dB */ + 0x21E, /* 25, +0.5dB */ + 0x23E, /* 26, +1.0dB */ + 0x261, /* 27, +1.5dB */ + 0x285, /* 28, +2.0dB */ + 0x2AB, /* 29, +2.5dB */ + 0x2D3, /* 30, +3.0dB */ + 0x2FE, /* 31, +3.5dB */ + 0x32B, /* 32, +4.0dB */ + 0x35C, /* 33, +4.5dB */ + 0x38E, /* 34, +5.0dB */ + 0x3C4, /* 35, +5.5dB */ + 0x3FE /* 36, +6.0dB */ +}; + +static const u32 ofdmswing_table[] = { + 0x0b40002d, /* 0, -15.0dB */ + 0x0c000030, /* 1, -14.5dB */ + 0x0cc00033, /* 2, -14.0dB */ + 0x0d800036, /* 3, -13.5dB */ + 0x0e400039, /* 4, -13.0dB */ + 0x0f00003c, /* 5, -12.5dB */ + 0x10000040, /* 6, -12.0dB */ + 0x11000044, /* 7, -11.5dB */ + 0x12000048, /* 8, -11.0dB */ + 0x1300004c, /* 9, -10.5dB */ + 0x14400051, /* 10, -10.0dB */ + 0x15800056, /* 11, -9.5dB */ + 0x16c0005b, /* 12, -9.0dB */ + 0x18000060, /* 13, -8.5dB */ + 0x19800066, /* 14, -8.0dB */ + 0x1b00006c, /* 15, -7.5dB */ + 0x1c800072, /* 16, -7.0dB */ + 0x1e400079, /* 17, -6.5dB */ + 0x20000080, /* 18, -6.0dB */ + 0x22000088, /* 19, -5.5dB */ + 0x24000090, /* 20, -5.0dB */ + 0x26000098, /* 21, -4.5dB */ + 0x288000a2, /* 22, -4.0dB */ + 0x2ac000ab, /* 23, -3.5dB */ + 0x2d4000b5, /* 24, -3.0dB */ + 0x300000c0, /* 25, -2.5dB */ + 0x32c000cb, /* 26, -2.0dB */ + 0x35c000d7, /* 27, -1.5dB */ + 0x390000e4, /* 28, -1.0dB */ + 0x3c8000f2, /* 29, -0.5dB */ + 0x40000100, /* 30, +0dB */ + 0x43c0010f, /* 31, +0.5dB */ + 0x47c0011f, /* 32, +1.0dB */ + 0x4c000130, /* 33, +1.5dB */ + 0x50800142, /* 34, +2.0dB */ + 0x55400155, /* 35, +2.5dB */ + 0x5a400169, /* 36, +3.0dB */ + 0x5fc0017f, /* 37, +3.5dB */ + 0x65400195, /* 38, +4.0dB */ + 0x6b8001ae, /* 39, +4.5dB */ + 0x71c001c7, /* 40, +5.0dB */ + 0x788001e2, /* 41, +5.5dB */ + 0x7f8001fe /* 42, +6.0dB */ +}; + +static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { + {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /* 0, -16.0dB */ + {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 1, -15.5dB */ + {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 2, -15.0dB */ + {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 3, -14.5dB */ + {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 4, -14.0dB */ + {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 5, -13.5dB */ + {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 6, -13.0dB */ + {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 7, -12.5dB */ + {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 8, -12.0dB */ + {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 9, -11.5dB */ + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */ + {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */ + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */ + {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */ + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */ + {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */ + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ + {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */ + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */ + {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */ + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */ + {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */ + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */ + {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */ + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */ + {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */ + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */ + {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */ + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */ + {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */ + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */ + {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */ + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04} /* 32, +0dB */ +}; + +static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { + {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /* 0, -16.0dB */ + {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 1, -15.5dB */ + {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 2, -15.0dB */ + {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 3, -14.5dB */ + {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 4, -14.0dB */ + {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 5, -13.5dB */ + {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 6, -13.0dB */ + {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 7, -12.5dB */ + {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 8, -12.0dB */ + {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 9, -11.5dB */ + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */ + {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */ + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */ + {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */ + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */ + {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */ + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ + {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */ + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */ + {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */ + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */ + {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */ + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */ + {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */ + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */ + {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */ + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */ + {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */ + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */ + {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */ + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */ + {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */ + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00} /* 32, +0dB */ +}; + +static const u32 edca_setting_dl[PEER_MAX] = { + 0xa44f, /* 0 UNKNOWN */ + 0x5ea44f, /* 1 REALTEK_90 */ + 0x5e4322, /* 2 REALTEK_92SE */ + 0x5ea42b, /* 3 BROAD */ + 0xa44f, /* 4 RAL */ + 0xa630, /* 5 ATH */ + 0x5ea630, /* 6 CISCO */ + 0x5ea42b, /* 7 MARVELL */ +}; + +static const u32 edca_setting_ul[PEER_MAX] = { + 0x5e4322, /* 0 UNKNOWN */ + 0xa44f, /* 1 REALTEK_90 */ + 0x5ea44f, /* 2 REALTEK_92SE */ + 0x5ea32b, /* 3 BROAD */ + 0x5ea422, /* 4 RAL */ + 0x5ea322, /* 5 ATH */ + 0x3ea430, /* 6 CISCO */ + 0x5ea44f, /* 7 MARV */ +}; + +static u8 rtl8818e_delta_swing_table_idx_24gb_p[] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9}; + +static u8 rtl8818e_delta_swing_table_idx_24gb_n[] = { + 0, 0, 0, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, + 7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11}; + +static u8 rtl8812ae_delta_swing_table_idx_24gb_n[] = { + 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, + 6, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11}; + +static u8 rtl8812ae_delta_swing_table_idx_24gb_p[] = { + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, + 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9}; + +static u8 rtl8812ae_delta_swing_table_idx_24ga_n[] = { + 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, + 6, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11}; + +static u8 rtl8812ae_delta_swing_table_idx_24ga_p[] = { + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, + 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9}; + +static u8 rtl8812ae_delta_swing_table_idx_24gcckb_n[] = { + 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, + 6, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11}; + +static u8 rtl8812ae_delta_swing_table_idx_24gcckb_p[] = { + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, + 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9}; + +static u8 rtl8812ae_delta_swing_table_idx_24gccka_n[] = { + 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, + 6, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11}; + +static u8 rtl8812ae_delta_swing_table_idx_24gccka_p[] = { + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, + 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9}; + +static u8 rtl8812ae_delta_swing_table_idx_5gb_n[][DEL_SW_IDX_SZ] = { + {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, + 7, 8, 8, 9, 9, 9, 10, 10, 11, 11, 12, 12, 13}, + {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, + 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13}, + {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, + 12, 12, 13, 14, 14, 14, 15, 16, 17, 17, 17, 18, 18, 18}, +}; + +static u8 rtl8812ae_delta_swing_table_idx_5gb_p[][DEL_SW_IDX_SZ] = { + {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11}, + {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11}, + {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, + 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}, +}; + +static u8 rtl8812ae_delta_swing_table_idx_5ga_n[][DEL_SW_IDX_SZ] = { + {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13}, + {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, + 9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13}, + {0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, + 12, 13, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 18, 18}, +}; + +static u8 rtl8812ae_delta_swing_table_idx_5ga_p[][DEL_SW_IDX_SZ] = { + {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11}, + {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 9, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}, + {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 9, + 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}, +}; + +static u8 rtl8821ae_delta_swing_table_idx_24gb_n[] = { + 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, + 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10}; + +static u8 rtl8821ae_delta_swing_table_idx_24gb_p[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12}; + +static u8 rtl8821ae_delta_swing_table_idx_24ga_n[] = { + 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, + 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10}; + +static u8 rtl8821ae_delta_swing_table_idx_24ga_p[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12}; + +static u8 rtl8821ae_delta_swing_table_idx_24gcckb_n[] = { + 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, + 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10}; + +static u8 rtl8821ae_delta_swing_table_idx_24gcckb_p[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12}; + +static u8 rtl8821ae_delta_swing_table_idx_24gccka_n[] = { + 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, + 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10}; + +static u8 rtl8821ae_delta_swing_table_idx_24gccka_p[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12}; + +static u8 rtl8821ae_delta_swing_table_idx_5gb_n[][DEL_SW_IDX_SZ] = { + {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, + 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, + {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, + 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, + {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, + 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static u8 rtl8821ae_delta_swing_table_idx_5gb_p[][DEL_SW_IDX_SZ] = { + {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, + 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, + {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, + 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, + {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, + 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static u8 rtl8821ae_delta_swing_table_idx_5ga_n[][DEL_SW_IDX_SZ] = { + {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, + 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, + {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, + 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, + {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, + 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +static u8 rtl8821ae_delta_swing_table_idx_5ga_p[][DEL_SW_IDX_SZ] = { + {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, + 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, + {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, + 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, + {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, + 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, +}; + +void rtl8821ae_dm_txpower_track_adjust(struct ieee80211_hw *hw, + u8 type, u8 *pdirection, + u32 *poutwrite_val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + u8 pwr_val = 0; + + if (type == 0) { + if (rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] <= + rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A]) { + *pdirection = 1; + pwr_val = rtldm->swing_idx_ofdm_base[RF90_PATH_A] - + rtldm->swing_idx_ofdm[RF90_PATH_A]; + } else { + *pdirection = 2; + pwr_val = rtldm->swing_idx_ofdm[RF90_PATH_A] - + rtldm->swing_idx_ofdm_base[RF90_PATH_A]; + } + } else if (type == 1) { + if (rtldm->swing_idx_cck <= rtldm->swing_idx_cck_base) { + *pdirection = 1; + pwr_val = rtldm->swing_idx_cck_base - + rtldm->swing_idx_cck; + } else { + *pdirection = 2; + pwr_val = rtldm->swing_idx_cck - + rtldm->swing_idx_cck_base; + } + } + + if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1)) + pwr_val = TXPWRTRACK_MAX_IDX; + + *poutwrite_val = pwr_val | (pwr_val << 8)| + (pwr_val << 16)| + (pwr_val << 24); +} + +void rtl8821ae_dm_clear_txpower_tracking_state(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtlpriv); + struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); + u8 p = 0; + + rtldm->swing_idx_cck_base = rtldm->default_cck_index; + rtldm->swing_idx_cck = rtldm->default_cck_index; + rtldm->cck_index = 0; + + for (p = RF90_PATH_A; p <= RF90_PATH_B; ++p) { + rtldm->swing_idx_ofdm_base[p] = rtldm->default_ofdm_index; + rtldm->swing_idx_ofdm[p] = rtldm->default_ofdm_index; + rtldm->ofdm_index[p] = rtldm->default_ofdm_index; + + rtldm->power_index_offset[p] = 0; + rtldm->delta_power_index[p] = 0; + rtldm->delta_power_index_last[p] = 0; + /*Initial Mix mode power tracking*/ + rtldm->absolute_ofdm_swing_idx[p] = 0; + rtldm->remnant_ofdm_swing_idx[p] = 0; + } + /*Initial at Modify Tx Scaling Mode*/ + rtldm->modify_txagc_flag_path_a = false; + /*Initial at Modify Tx Scaling Mode*/ + rtldm->modify_txagc_flag_path_b = false; + rtldm->remnant_cck_idx = 0; + rtldm->thermalvalue = rtlefuse->eeprom_thermalmeter; + rtldm->thermalvalue_iqk = rtlefuse->eeprom_thermalmeter; + rtldm->thermalvalue_lck = rtlefuse->eeprom_thermalmeter; +} + +static u8 rtl8821ae_dm_get_swing_index(struct ieee80211_hw *hw) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 i = 0; + u32 bb_swing; + + bb_swing = phy_get_tx_swing_8812A(hw, rtlhal->current_bandtype, + RF90_PATH_A); + + for (i = 0; i < TXSCALE_TABLE_SIZE; ++i) + if (bb_swing == rtl8821ae_txscaling_table[i]) + break; + + return i; +} + +void rtl8821ae_dm_initialize_txpower_tracking_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtlpriv); + struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); + u8 default_swing_index = 0; + u8 p = 0; + + rtlpriv->dm.txpower_track_control = true; + rtldm->thermalvalue = rtlefuse->eeprom_thermalmeter; + rtldm->thermalvalue_iqk = rtlefuse->eeprom_thermalmeter; + rtldm->thermalvalue_lck = rtlefuse->eeprom_thermalmeter; + default_swing_index = rtl8821ae_dm_get_swing_index(hw); + + rtldm->default_ofdm_index = + (default_swing_index == TXSCALE_TABLE_SIZE) ? + 24 : default_swing_index; + rtldm->default_cck_index = 24; + + rtldm->swing_idx_cck_base = rtldm->default_cck_index; + rtldm->cck_index = rtldm->default_cck_index; + + for (p = RF90_PATH_A; p < MAX_RF_PATH; ++p) { + rtldm->swing_idx_ofdm_base[p] = + rtldm->default_ofdm_index; + rtldm->ofdm_index[p] = rtldm->default_ofdm_index; + rtldm->delta_power_index[p] = 0; + rtldm->power_index_offset[p] = 0; + rtldm->delta_power_index_last[p] = 0; + } +} + +void rtl8821ae_dm_init_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.current_turbo_edca = false; + rtlpriv->dm.is_any_nonbepkts = false; + rtlpriv->dm.is_cur_rdlstate = false; +} + +void rtl8821ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rate_adaptive *p_ra = &rtlpriv->ra; + + p_ra->ratr_state = DM_RATR_STA_INIT; + p_ra->pre_ratr_state = DM_RATR_STA_INIT; + + rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; + if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) + rtlpriv->dm.useramask = true; + else + rtlpriv->dm.useramask = false; + + p_ra->high_rssi_thresh_for_ra = 50; + p_ra->low_rssi_thresh_for_ra40m = 20; +} + +static void rtl8821ae_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap; + + rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11)); + rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL; +} + +static void rtl8821ae_dm_common_info_self_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 tmp; + + rtlphy->cck_high_power = + (bool)rtl_get_bbreg(hw, ODM_REG_CCK_RPT_FORMAT_11AC, + ODM_BIT_CCK_RPT_FORMAT_11AC); + + tmp = (u8)rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC, + ODM_BIT_BB_RX_PATH_11AC); + if (tmp & BIT(0)) + rtlpriv->dm.rfpath_rxenable[0] = true; + if (tmp & BIT(1)) + rtlpriv->dm.rfpath_rxenable[1] = true; +} + +void rtl8821ae_dm_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f); + + spin_lock(&rtlpriv->locks.iqk_lock); + rtlphy->lck_inprogress = false; + spin_unlock(&rtlpriv->locks.iqk_lock); + + rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; + rtl8821ae_dm_common_info_self_init(hw); + rtl_dm_diginit(hw, cur_igvalue); + rtl8821ae_dm_init_rate_adaptive_mask(hw); + rtl8821ae_dm_init_edca_turbo(hw); + rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(hw); + rtl8821ae_dm_init_dynamic_atc_switch(hw); +} + +static void rtl8821ae_dm_find_minimum_rssi(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable; + struct rtl_mac *mac = rtl_mac(rtlpriv); + + /* Determine the minimum RSSI */ + if ((mac->link_state < MAC80211_LINKED) && + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { + rtl_dm_dig->min_undec_pwdb_for_dm = 0; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "Not connected to any\n"); + } + if (mac->link_state >= MAC80211_LINKED) { + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_dm_dig->min_undec_pwdb_for_dm = + rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "AP Client PWDB = 0x%lx\n", + rtlpriv->dm.entry_min_undec_sm_pwdb); + } else { + rtl_dm_dig->min_undec_pwdb_for_dm = + rtlpriv->dm.undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "STA Default Port PWDB = 0x%x\n", + rtl_dm_dig->min_undec_pwdb_for_dm); + } + } else { + rtl_dm_dig->min_undec_pwdb_for_dm = + rtlpriv->dm.entry_min_undec_sm_pwdb; + RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, + "AP Ext Port or disconnet PWDB = 0x%x\n", + rtl_dm_dig->min_undec_pwdb_for_dm); + } + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "MinUndecoratedPWDBForDM =%d\n", + rtl_dm_dig->min_undec_pwdb_for_dm); +} + +static void rtl8812ae_dm_rssi_dump_to_register(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, RA_RSSI_DUMP, + rtlpriv->stats.rx_rssi_percentage[0]); + rtl_write_byte(rtlpriv, RB_RSSI_DUMP, + rtlpriv->stats.rx_rssi_percentage[1]); + + /* Rx EVM*/ + rtl_write_byte(rtlpriv, RS1_RX_EVM_DUMP, + rtlpriv->stats.rx_evm_dbm[0]); + rtl_write_byte(rtlpriv, RS2_RX_EVM_DUMP, + rtlpriv->stats.rx_evm_dbm[1]); + + /*Rx SNR*/ + rtl_write_byte(rtlpriv, RA_RX_SNR_DUMP, + (u8)(rtlpriv->stats.rx_snr_db[0])); + rtl_write_byte(rtlpriv, RB_RX_SNR_DUMP, + (u8)(rtlpriv->stats.rx_snr_db[1])); + + /*Rx Cfo_Short*/ + rtl_write_word(rtlpriv, RA_CFO_SHORT_DUMP, + rtlpriv->stats.rx_cfo_short[0]); + rtl_write_word(rtlpriv, RB_CFO_SHORT_DUMP, + rtlpriv->stats.rx_cfo_short[1]); + + /*Rx Cfo_Tail*/ + rtl_write_word(rtlpriv, RA_CFO_LONG_DUMP, + rtlpriv->stats.rx_cfo_tail[0]); + rtl_write_word(rtlpriv, RB_CFO_LONG_DUMP, + rtlpriv->stats.rx_cfo_tail[1]); +} + +static void rtl8821ae_dm_check_rssi_monitor(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_sta_info *drv_priv; + u8 h2c_parameter[4] = { 0 }; + long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff; + u8 stbc_tx = 0; + u64 cur_txokcnt = 0, cur_rxokcnt = 0; + static u64 last_txokcnt = 0, last_rxokcnt; + + cur_txokcnt = rtlpriv->stats.txbytesunicast - last_txokcnt; + cur_rxokcnt = rtlpriv->stats.rxbytesunicast - last_rxokcnt; + last_txokcnt = rtlpriv->stats.txbytesunicast; + last_rxokcnt = rtlpriv->stats.rxbytesunicast; + if (cur_rxokcnt > (last_txokcnt * 6)) + h2c_parameter[3] = 0x01; + else + h2c_parameter[3] = 0x00; + + /* AP & ADHOC & MESH */ + if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + spin_lock_bh(&rtlpriv->locks.entry_list_lock); + list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { + if (drv_priv->rssi_stat.undec_sm_pwdb < + tmp_entry_min_pwdb) + tmp_entry_min_pwdb = + drv_priv->rssi_stat.undec_sm_pwdb; + if (drv_priv->rssi_stat.undec_sm_pwdb > + tmp_entry_max_pwdb) + tmp_entry_max_pwdb = + drv_priv->rssi_stat.undec_sm_pwdb; + } + spin_unlock_bh(&rtlpriv->locks.entry_list_lock); + + /* If associated entry is found */ + if (tmp_entry_max_pwdb != 0) { + rtlpriv->dm.entry_max_undec_sm_pwdb = + tmp_entry_max_pwdb; + RTPRINT(rtlpriv, FDM, DM_PWDB, + "EntryMaxPWDB = 0x%lx(%ld)\n", + tmp_entry_max_pwdb, tmp_entry_max_pwdb); + } else { + rtlpriv->dm.entry_max_undec_sm_pwdb = 0; + } + /* If associated entry is found */ + if (tmp_entry_min_pwdb != 0xff) { + rtlpriv->dm.entry_min_undec_sm_pwdb = + tmp_entry_min_pwdb; + RTPRINT(rtlpriv, FDM, DM_PWDB, + "EntryMinPWDB = 0x%lx(%ld)\n", + tmp_entry_min_pwdb, tmp_entry_min_pwdb); + } else { + rtlpriv->dm.entry_min_undec_sm_pwdb = 0; + } + } + /* Indicate Rx signal strength to FW. */ + if (rtlpriv->dm.useramask) { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + if (mac->mode == WIRELESS_MODE_AC_24G || + mac->mode == WIRELESS_MODE_AC_5G || + mac->mode == WIRELESS_MODE_AC_ONLY) + stbc_tx = (mac->vht_cur_stbc & + STBC_VHT_ENABLE_TX) ? 1 : 0; + else + stbc_tx = (mac->ht_cur_stbc & + STBC_HT_ENABLE_TX) ? 1 : 0; + h2c_parameter[3] |= stbc_tx << 1; + } + h2c_parameter[2] = + (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF); + h2c_parameter[1] = 0x20; + h2c_parameter[0] = 0; + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 4, + h2c_parameter); + else + rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 3, + h2c_parameter); + } else { + rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb); + } + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtl8812ae_dm_rssi_dump_to_register(hw); + rtl8821ae_dm_find_minimum_rssi(hw); + dm_digtable->rssi_val_min = rtlpriv->dm_digtable.min_undec_pwdb_for_dm; +} + +void rtl8821ae_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 current_cca) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + if (dm_digtable->cur_cck_cca_thres != current_cca) + rtl_write_byte(rtlpriv, DM_REG_CCK_CCA_11AC, current_cca); + + dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres; + dm_digtable->cur_cck_cca_thres = current_cca; +} + +void rtl8821ae_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + + if (dm_digtable->stop_dig) + return; + + if (dm_digtable->cur_igvalue != current_igi) { + rtl_set_bbreg(hw, DM_REG_IGI_A_11AC, + DM_BIT_IGI_11AC, current_igi); + if (rtlpriv->phy.rf_type != RF_1T1R) + rtl_set_bbreg(hw, DM_REG_IGI_B_11AC, + DM_BIT_IGI_11AC, current_igi); + } + dm_digtable->cur_igvalue = current_igi; +} + +static void rtl8821ae_dm_dig(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 dig_min_0; + u8 dig_max_of_min; + bool first_connect, first_disconnect; + u8 dm_dig_max, dm_dig_min, offset; + u8 current_igi = dm_digtable->cur_igvalue; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "\n"); + + if (mac->act_scanning) { + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Return: In Scan Progress\n"); + return; + } + + /*add by Neil Chen to avoid PSD is processing*/ + dig_min_0 = dm_digtable->dig_min_0; + first_connect = (mac->link_state >= MAC80211_LINKED) && + (!dm_digtable->media_connect_0); + first_disconnect = (mac->link_state < MAC80211_LINKED) && + (dm_digtable->media_connect_0); + + /*1 Boundary Decision*/ + + dm_dig_max = 0x5A; + + if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE) + dm_dig_min = DM_DIG_MIN; + else + dm_dig_min = 0x1C; + + dig_max_of_min = DM_DIG_MAX_AP; + + if (mac->link_state >= MAC80211_LINKED) { + if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE) + offset = 20; + else + offset = 10; + + if ((dm_digtable->rssi_val_min + offset) > dm_dig_max) + dm_digtable->rx_gain_max = dm_dig_max; + else if ((dm_digtable->rssi_val_min + offset) < dm_dig_min) + dm_digtable->rx_gain_max = dm_dig_min; + else + dm_digtable->rx_gain_max = + dm_digtable->rssi_val_min + offset; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "dm_digtable->rssi_val_min=0x%x,dm_digtable->rx_gain_max = 0x%x", + dm_digtable->rssi_val_min, + dm_digtable->rx_gain_max); + if (rtlpriv->dm.one_entry_only) { + offset = 0; + + if (dm_digtable->rssi_val_min - offset < dm_dig_min) + dig_min_0 = dm_dig_min; + else if (dm_digtable->rssi_val_min - + offset > dig_max_of_min) + dig_min_0 = dig_max_of_min; + else + dig_min_0 = + dm_digtable->rssi_val_min - offset; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "bOneEntryOnly=TRUE, dig_min_0=0x%x\n", + dig_min_0); + } else { + dig_min_0 = dm_dig_min; + } + } else { + dm_digtable->rx_gain_max = dm_dig_max; + dig_min_0 = dm_dig_min; + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "No Link\n"); + } + + if (rtlpriv->falsealm_cnt.cnt_all > 10000) { + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Abnormally false alarm case.\n"); + + if (dm_digtable->large_fa_hit != 3) + dm_digtable->large_fa_hit++; + if (dm_digtable->forbidden_igi < current_igi) { + dm_digtable->forbidden_igi = current_igi; + dm_digtable->large_fa_hit = 1; + } + + if (dm_digtable->large_fa_hit >= 3) { + if ((dm_digtable->forbidden_igi + 1) > + dm_digtable->rx_gain_max) + dm_digtable->rx_gain_min = + dm_digtable->rx_gain_max; + else + dm_digtable->rx_gain_min = + (dm_digtable->forbidden_igi + 1); + dm_digtable->recover_cnt = 3600; + } + } else { + /*Recovery mechanism for IGI lower bound*/ + if (dm_digtable->recover_cnt != 0) { + dm_digtable->recover_cnt--; + } else { + if (dm_digtable->large_fa_hit < 3) { + if ((dm_digtable->forbidden_igi - 1) < + dig_min_0) { + dm_digtable->forbidden_igi = + dig_min_0; + dm_digtable->rx_gain_min = + dig_min_0; + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Normal Case: At Lower Bound\n"); + } else { + dm_digtable->forbidden_igi--; + dm_digtable->rx_gain_min = + (dm_digtable->forbidden_igi + 1); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Normal Case: Approach Lower Bound\n"); + } + } else { + dm_digtable->large_fa_hit = 0; + } + } + } + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "pDM_DigTable->LargeFAHit=%d\n", + dm_digtable->large_fa_hit); + + if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10) + dm_digtable->rx_gain_min = dm_dig_min; + + if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max) + dm_digtable->rx_gain_min = dm_digtable->rx_gain_max; + + /*Adjust initial gain by false alarm*/ + if (mac->link_state >= MAC80211_LINKED) { + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "DIG AfterLink\n"); + if (first_connect) { + if (dm_digtable->rssi_val_min <= dig_max_of_min) + current_igi = dm_digtable->rssi_val_min; + else + current_igi = dig_max_of_min; + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "First Connect\n"); + } else { + if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2) + current_igi = current_igi + 4; + else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1) + current_igi = current_igi + 2; + else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) + current_igi = current_igi - 2; + + if ((rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10) && + (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)) { + current_igi = dm_digtable->rx_gain_min; + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Beacon is less than 10 and FA is less than 768, IGI GOES TO 0x1E!!!!!!!!!!!!\n"); + } + } + } else { + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "DIG BeforeLink\n"); + if (first_disconnect) { + current_igi = dm_digtable->rx_gain_min; + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "First DisConnect\n"); + } else { + /* 2012.03.30 LukeLee: enable DIG before + * link but with very high thresholds + */ + if (rtlpriv->falsealm_cnt.cnt_all > 2000) + current_igi = current_igi + 4; + else if (rtlpriv->falsealm_cnt.cnt_all > 600) + current_igi = current_igi + 2; + else if (rtlpriv->falsealm_cnt.cnt_all < 300) + current_igi = current_igi - 2; + + if (current_igi >= 0x3e) + current_igi = 0x3e; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "England DIG\n"); + } + } + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "DIG End Adjust IGI\n"); + /* Check initial gain by upper/lower bound*/ + + if (current_igi > dm_digtable->rx_gain_max) + current_igi = dm_digtable->rx_gain_max; + if (current_igi < dm_digtable->rx_gain_min) + current_igi = dm_digtable->rx_gain_min; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "rx_gain_max=0x%x, rx_gain_min=0x%x\n", + dm_digtable->rx_gain_max, dm_digtable->rx_gain_min); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "TotalFA=%d\n", rtlpriv->falsealm_cnt.cnt_all); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "CurIGValue=0x%x\n", current_igi); + + rtl8821ae_dm_write_dig(hw, current_igi); + dm_digtable->media_connect_0 = + ((mac->link_state >= MAC80211_LINKED) ? true : false); + dm_digtable->dig_min_0 = dig_min_0; +} + +static void rtl8821ae_dm_common_info_self_update(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 cnt = 0; + struct rtl_sta_info *drv_priv; + + rtlpriv->dm.tx_rate = 0xff; + + rtlpriv->dm.one_entry_only = false; + + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION && + rtlpriv->mac80211.link_state >= MAC80211_LINKED) { + rtlpriv->dm.one_entry_only = true; + return; + } + + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || + rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC || + rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) { + spin_lock_bh(&rtlpriv->locks.entry_list_lock); + list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) + cnt++; + spin_unlock_bh(&rtlpriv->locks.entry_list_lock); + + if (cnt == 1) + rtlpriv->dm.one_entry_only = true; + } +} + +static void rtl8821ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt; + u32 cck_enable = 0; + + /*read OFDM FA counter*/ + falsealm_cnt->cnt_ofdm_fail = + rtl_get_bbreg(hw, ODM_REG_OFDM_FA_11AC, BMASKLWORD); + falsealm_cnt->cnt_cck_fail = + rtl_get_bbreg(hw, ODM_REG_CCK_FA_11AC, BMASKLWORD); + + cck_enable = rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC, BIT(28)); + if (cck_enable) /*if(pDM_Odm->pBandType == ODM_BAND_2_4G)*/ + falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail + + falsealm_cnt->cnt_cck_fail; + else + falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail; + + /*reset OFDM FA coutner*/ + rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1); + rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0); + /* reset CCK FA counter*/ + rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 0); + rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 1); + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "Cnt_Cck_fail=%d\n", + falsealm_cnt->cnt_cck_fail); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "cnt_ofdm_fail=%d\n", + falsealm_cnt->cnt_ofdm_fail); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "Total False Alarm=%d\n", + falsealm_cnt->cnt_all); +} + +static void rtl8812ae_dm_check_txpower_tracking_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (!rtlpriv->dm.tm_trigger) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, + BIT(17) | BIT(16), 0x03); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Trigger 8812 Thermal Meter!!\n"); + rtlpriv->dm.tm_trigger = 1; + return; + } + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Schedule TxPowerTracking direct call!!\n"); + rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw); +} + +static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (mac->link_state >= MAC80211_LINKED) { + if (rtldm->linked_interval < 3) + rtldm->linked_interval++; + + if (rtldm->linked_interval == 2) { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtl8812ae_phy_iq_calibrate(hw, false); + else + rtl8821ae_phy_iq_calibrate(hw, false); + } + } else { + rtldm->linked_interval = 0; + } +} + +static void rtl8812ae_get_delta_swing_table(struct ieee80211_hw *hw, + u8 **up_a, u8 **down_a, + u8 **up_b, u8 **down_b) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + u8 channel = rtlphy->current_channel; + u8 rate = rtldm->tx_rate; + + if (1 <= channel && channel <= 14) { + if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) { + *up_a = rtl8812ae_delta_swing_table_idx_24gccka_p; + *down_a = rtl8812ae_delta_swing_table_idx_24gccka_n; + *up_b = rtl8812ae_delta_swing_table_idx_24gcckb_p; + *down_b = rtl8812ae_delta_swing_table_idx_24gcckb_n; + } else { + *up_a = rtl8812ae_delta_swing_table_idx_24ga_p; + *down_a = rtl8812ae_delta_swing_table_idx_24ga_n; + *up_b = rtl8812ae_delta_swing_table_idx_24gb_p; + *down_b = rtl8812ae_delta_swing_table_idx_24gb_n; + } + } else if (36 <= channel && channel <= 64) { + *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[0]; + *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[0]; + *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[0]; + *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[0]; + } else if (100 <= channel && channel <= 140) { + *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[1]; + *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[1]; + *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[1]; + *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[1]; + } else if (149 <= channel && channel <= 173) { + *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[2]; + *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[2]; + *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[2]; + *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[2]; + } else { + *up_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p; + *down_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n; + *up_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p; + *down_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n; + } +} + +void rtl8821ae_dm_update_init_rate(struct ieee80211_hw *hw, u8 rate) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 p = 0; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Get C2H Command! Rate=0x%x\n", rate); + + rtldm->tx_rate = rate; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + rtl8821ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, RF90_PATH_A, 0); + } else { + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) + rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, p, 0); + } +} + +u8 rtl8821ae_hw_rate_to_mrate(struct ieee80211_hw *hw, u8 rate) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 ret_rate = MGN_1M; + + switch (rate) { + case DESC_RATE1M: + ret_rate = MGN_1M; + break; + case DESC_RATE2M: + ret_rate = MGN_2M; + break; + case DESC_RATE5_5M: + ret_rate = MGN_5_5M; + break; + case DESC_RATE11M: + ret_rate = MGN_11M; + break; + case DESC_RATE6M: + ret_rate = MGN_6M; + break; + case DESC_RATE9M: + ret_rate = MGN_9M; + break; + case DESC_RATE12M: + ret_rate = MGN_12M; + break; + case DESC_RATE18M: + ret_rate = MGN_18M; + break; + case DESC_RATE24M: + ret_rate = MGN_24M; + break; + case DESC_RATE36M: + ret_rate = MGN_36M; + break; + case DESC_RATE48M: + ret_rate = MGN_48M; + break; + case DESC_RATE54M: + ret_rate = MGN_54M; + break; + case DESC_RATEMCS0: + ret_rate = MGN_MCS0; + break; + case DESC_RATEMCS1: + ret_rate = MGN_MCS1; + break; + case DESC_RATEMCS2: + ret_rate = MGN_MCS2; + break; + case DESC_RATEMCS3: + ret_rate = MGN_MCS3; + break; + case DESC_RATEMCS4: + ret_rate = MGN_MCS4; + break; + case DESC_RATEMCS5: + ret_rate = MGN_MCS5; + break; + case DESC_RATEMCS6: + ret_rate = MGN_MCS6; + break; + case DESC_RATEMCS7: + ret_rate = MGN_MCS7; + break; + case DESC_RATEMCS8: + ret_rate = MGN_MCS8; + break; + case DESC_RATEMCS9: + ret_rate = MGN_MCS9; + break; + case DESC_RATEMCS10: + ret_rate = MGN_MCS10; + break; + case DESC_RATEMCS11: + ret_rate = MGN_MCS11; + break; + case DESC_RATEMCS12: + ret_rate = MGN_MCS12; + break; + case DESC_RATEMCS13: + ret_rate = MGN_MCS13; + break; + case DESC_RATEMCS14: + ret_rate = MGN_MCS14; + break; + case DESC_RATEMCS15: + ret_rate = MGN_MCS15; + break; + case DESC_RATEVHT1SS_MCS0: + ret_rate = MGN_VHT1SS_MCS0; + break; + case DESC_RATEVHT1SS_MCS1: + ret_rate = MGN_VHT1SS_MCS1; + break; + case DESC_RATEVHT1SS_MCS2: + ret_rate = MGN_VHT1SS_MCS2; + break; + case DESC_RATEVHT1SS_MCS3: + ret_rate = MGN_VHT1SS_MCS3; + break; + case DESC_RATEVHT1SS_MCS4: + ret_rate = MGN_VHT1SS_MCS4; + break; + case DESC_RATEVHT1SS_MCS5: + ret_rate = MGN_VHT1SS_MCS5; + break; + case DESC_RATEVHT1SS_MCS6: + ret_rate = MGN_VHT1SS_MCS6; + break; + case DESC_RATEVHT1SS_MCS7: + ret_rate = MGN_VHT1SS_MCS7; + break; + case DESC_RATEVHT1SS_MCS8: + ret_rate = MGN_VHT1SS_MCS8; + break; + case DESC_RATEVHT1SS_MCS9: + ret_rate = MGN_VHT1SS_MCS9; + break; + case DESC_RATEVHT2SS_MCS0: + ret_rate = MGN_VHT2SS_MCS0; + break; + case DESC_RATEVHT2SS_MCS1: + ret_rate = MGN_VHT2SS_MCS1; + break; + case DESC_RATEVHT2SS_MCS2: + ret_rate = MGN_VHT2SS_MCS2; + break; + case DESC_RATEVHT2SS_MCS3: + ret_rate = MGN_VHT2SS_MCS3; + break; + case DESC_RATEVHT2SS_MCS4: + ret_rate = MGN_VHT2SS_MCS4; + break; + case DESC_RATEVHT2SS_MCS5: + ret_rate = MGN_VHT2SS_MCS5; + break; + case DESC_RATEVHT2SS_MCS6: + ret_rate = MGN_VHT2SS_MCS6; + break; + case DESC_RATEVHT2SS_MCS7: + ret_rate = MGN_VHT2SS_MCS7; + break; + case DESC_RATEVHT2SS_MCS8: + ret_rate = MGN_VHT2SS_MCS8; + break; + case DESC_RATEVHT2SS_MCS9: + ret_rate = MGN_VHT2SS_MCS9; + break; + default: + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "HwRateToMRate8812(): Non supported Rate [%x]!!!\n", + rate); + break; + } + return ret_rate; +} + +/*----------------------------------------------------------------------------- + * Function: odm_TxPwrTrackSetPwr88E() + * + * Overview: 88E change all channel tx power accordign to flag. + * OFDM & CCK are all different. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 04/23/2012 MHC Create Version 0. + * + *--------------------------------------------------------------------------- + */ +void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw, + enum pwr_track_control_method method, + u8 rf_path, u8 channel_mapped_index) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 final_swing_idx[2]; + u8 pwr_tracking_limit = 26; /*+1.0dB*/ + u8 tx_rate = 0xFF; + char final_ofdm_swing_index = 0; + + if (rtldm->tx_rate != 0xFF) + tx_rate = + rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "===>rtl8812ae_dm_txpwr_track_set_pwr\n"); + /*20130429 Mimic Modify High Rate BBSwing Limit.*/ + if (tx_rate != 0xFF) { + /*CCK*/ + if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M)) + pwr_tracking_limit = 32; /*+4dB*/ + /*OFDM*/ + else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M)) + pwr_tracking_limit = 30; /*+3dB*/ + else if (tx_rate == MGN_54M) + pwr_tracking_limit = 28; /*+2dB*/ + /*HT*/ + /*QPSK/BPSK*/ + else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2)) + pwr_tracking_limit = 34; /*+5dB*/ + /*16QAM*/ + else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4)) + pwr_tracking_limit = 30; /*+3dB*/ + /*64QAM*/ + else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7)) + pwr_tracking_limit = 28; /*+2dB*/ + /*QPSK/BPSK*/ + else if ((tx_rate >= MGN_MCS8) && (tx_rate <= MGN_MCS10)) + pwr_tracking_limit = 34; /*+5dB*/ + /*16QAM*/ + else if ((tx_rate >= MGN_MCS11) && (tx_rate <= MGN_MCS12)) + pwr_tracking_limit = 30; /*+3dB*/ + /*64QAM*/ + else if ((tx_rate >= MGN_MCS13) && (tx_rate <= MGN_MCS15)) + pwr_tracking_limit = 28; /*+2dB*/ + + /*2 VHT*/ + /*QPSK/BPSK*/ + else if ((tx_rate >= MGN_VHT1SS_MCS0) && + (tx_rate <= MGN_VHT1SS_MCS2)) + pwr_tracking_limit = 34; /*+5dB*/ + /*16QAM*/ + else if ((tx_rate >= MGN_VHT1SS_MCS3) && + (tx_rate <= MGN_VHT1SS_MCS4)) + pwr_tracking_limit = 30; /*+3dB*/ + /*64QAM*/ + else if ((tx_rate >= MGN_VHT1SS_MCS5) && + (tx_rate <= MGN_VHT1SS_MCS6)) + pwr_tracking_limit = 28; /*+2dB*/ + else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/ + pwr_tracking_limit = 26; /*+1dB*/ + else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/ + pwr_tracking_limit = 24; /*+0dB*/ + else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/ + pwr_tracking_limit = 22; /*-1dB*/ + /*QPSK/BPSK*/ + else if ((tx_rate >= MGN_VHT2SS_MCS0) && + (tx_rate <= MGN_VHT2SS_MCS2)) + pwr_tracking_limit = 34; /*+5dB*/ + /*16QAM*/ + else if ((tx_rate >= MGN_VHT2SS_MCS3) && + (tx_rate <= MGN_VHT2SS_MCS4)) + pwr_tracking_limit = 30; /*+3dB*/ + /*64QAM*/ + else if ((tx_rate >= MGN_VHT2SS_MCS5) && + (tx_rate <= MGN_VHT2SS_MCS6)) + pwr_tracking_limit = 28; /*+2dB*/ + else if (tx_rate == MGN_VHT2SS_MCS7) /*64QAM*/ + pwr_tracking_limit = 26; /*+1dB*/ + else if (tx_rate == MGN_VHT2SS_MCS8) /*256QAM*/ + pwr_tracking_limit = 24; /*+0dB*/ + else if (tx_rate == MGN_VHT2SS_MCS9) /*256QAM*/ + pwr_tracking_limit = 22; /*-1dB*/ + else + pwr_tracking_limit = 24; + } + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "TxRate=0x%x, PwrTrackingLimit=%d\n", + tx_rate, pwr_tracking_limit); + + if (method == BBSWING) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "===>rtl8812ae_dm_txpwr_track_set_pwr\n"); + + if (rf_path == RF90_PATH_A) { + u32 tmp; + + final_swing_idx[RF90_PATH_A] = + (rtldm->ofdm_index[RF90_PATH_A] > + pwr_tracking_limit) ? + pwr_tracking_limit : + rtldm->ofdm_index[RF90_PATH_A]; + tmp = final_swing_idx[RF90_PATH_A]; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n", + rtldm->ofdm_index[RF90_PATH_A], + final_swing_idx[RF90_PATH_A]); + + rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, + txscaling_tbl[tmp]); + } else { + u32 tmp; + + final_swing_idx[RF90_PATH_B] = + rtldm->ofdm_index[RF90_PATH_B] > + pwr_tracking_limit ? + pwr_tracking_limit : + rtldm->ofdm_index[RF90_PATH_B]; + tmp = final_swing_idx[RF90_PATH_B]; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_B]=%d, pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_B]=%d\n", + rtldm->ofdm_index[RF90_PATH_B], + final_swing_idx[RF90_PATH_B]); + + rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000, + txscaling_tbl[tmp]); + } + } else if (method == MIX_MODE) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pDM_Odm->DefaultOfdmIndex=%d, pDM_Odm->Aboslute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n", + rtldm->default_ofdm_index, + rtldm->absolute_ofdm_swing_idx[rf_path], + rf_path); + + final_ofdm_swing_index = rtldm->default_ofdm_index + + rtldm->absolute_ofdm_swing_idx[rf_path]; + + if (rf_path == RF90_PATH_A) { + /*BBSwing higher then Limit*/ + if (final_ofdm_swing_index > pwr_tracking_limit) { + rtldm->remnant_cck_idx = + final_ofdm_swing_index - + pwr_tracking_limit; + /* CCK Follow the same compensation value + * as Path A + */ + rtldm->remnant_ofdm_swing_idx[rf_path] = + final_ofdm_swing_index - + pwr_tracking_limit; + + rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, + txscaling_tbl[pwr_tracking_limit]); + + rtldm->modify_txagc_flag_path_a = true; + + /*Set TxAGC Page C{};*/ + rtl8821ae_phy_set_txpower_level_by_path(hw, + rtlphy->current_channel, + RF90_PATH_A); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Path_A Over BBSwing Limit ,PwrTrackingLimit = %d ,Remnant TxAGC Value = %d\n", + pwr_tracking_limit, + rtldm->remnant_ofdm_swing_idx[rf_path]); + } else if (final_ofdm_swing_index < 0) { + rtldm->remnant_cck_idx = final_ofdm_swing_index; + /* CCK Follow the same compensate value as Path A*/ + rtldm->remnant_ofdm_swing_idx[rf_path] = + final_ofdm_swing_index; + + rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, + txscaling_tbl[0]); + + rtldm->modify_txagc_flag_path_a = true; + + /*Set TxAGC Page C{};*/ + rtl8821ae_phy_set_txpower_level_by_path(hw, + rtlphy->current_channel, RF90_PATH_A); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Path_A Lower then BBSwing lower bound 0 , Remnant TxAGC Value = %d\n", + rtldm->remnant_ofdm_swing_idx[rf_path]); + } else { + rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, + txscaling_tbl[(u8)final_ofdm_swing_index]); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Path_A Compensate with BBSwing, Final_OFDM_Swing_Index = %d\n", + final_ofdm_swing_index); + /*If TxAGC has changed, reset TxAGC again*/ + if (rtldm->modify_txagc_flag_path_a) { + rtldm->remnant_cck_idx = 0; + rtldm->remnant_ofdm_swing_idx[rf_path] = 0; + + /*Set TxAGC Page C{};*/ + rtl8821ae_phy_set_txpower_level_by_path(hw, + rtlphy->current_channel, RF90_PATH_A); + rtldm->modify_txagc_flag_path_a = false; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, + DBG_LOUD, + "******Path_A pDM_Odm->Modify_TxAGC_Flag = FALSE\n"); + } + } + } + /*BBSwing higher then Limit*/ + if (rf_path == RF90_PATH_B) { + if (final_ofdm_swing_index > pwr_tracking_limit) { + rtldm->remnant_ofdm_swing_idx[rf_path] = + final_ofdm_swing_index - + pwr_tracking_limit; + + rtl_set_bbreg(hw, RB_TXSCALE, + 0xFFE00000, + txscaling_tbl[pwr_tracking_limit]); + + rtldm->modify_txagc_flag_path_b = true; + + /*Set TxAGC Page E{};*/ + rtl8821ae_phy_set_txpower_level_by_path(hw, + rtlphy->current_channel, RF90_PATH_B); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Path_B Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n", + pwr_tracking_limit, + rtldm->remnant_ofdm_swing_idx[rf_path]); + } else if (final_ofdm_swing_index < 0) { + rtldm->remnant_ofdm_swing_idx[rf_path] = + final_ofdm_swing_index; + + rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000, + txscaling_tbl[0]); + + rtldm->modify_txagc_flag_path_b = true; + + /*Set TxAGC Page E{};*/ + rtl8821ae_phy_set_txpower_level_by_path(hw, + rtlphy->current_channel, RF90_PATH_B); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Path_B Lower then BBSwing lower bound 0 , Remnant TxAGC Value = %d\n", + rtldm->remnant_ofdm_swing_idx[rf_path]); + } else { + rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000, + txscaling_tbl[(u8)final_ofdm_swing_index]); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Path_B Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n", + final_ofdm_swing_index); + /*If TxAGC has changed, reset TxAGC again*/ + if (rtldm->modify_txagc_flag_path_b) { + rtldm->remnant_ofdm_swing_idx[rf_path] = 0; + + /*Set TxAGC Page E{};*/ + rtl8821ae_phy_set_txpower_level_by_path(hw, + rtlphy->current_channel, RF90_PATH_B); + + rtldm->modify_txagc_flag_path_b = + false; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE\n"); + } + } + } + } else { + return; + } +} + +void rtl8812ae_dm_txpower_tracking_callback_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0; + u8 thermal_value_avg_count = 0; + u32 thermal_value_avg = 0; + /* OFDM BB Swing should be less than +3.0dB, */ + u8 ofdm_min_index = 6; + /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/ + u8 index_for_channel = 0; + /* 1. The following TWO tables decide + * the final index of OFDM/CCK swing table. + */ + u8 *delta_swing_table_idx_tup_a; + u8 *delta_swing_table_idx_tdown_a; + u8 *delta_swing_table_idx_tup_b; + u8 *delta_swing_table_idx_tdown_b; + + /*2. Initilization ( 7 steps in total )*/ + rtl8812ae_get_delta_swing_table(hw, + (u8 **)&delta_swing_table_idx_tup_a, + (u8 **)&delta_swing_table_idx_tdown_a, + (u8 **)&delta_swing_table_idx_tup_b, + (u8 **)&delta_swing_table_idx_tdown_b); + + rtldm->txpower_trackinginit = true; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pDM_Odm->BbSwingIdxCckBase: %d, pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n", + rtldm->swing_idx_cck_base, + rtldm->swing_idx_ofdm_base[RF90_PATH_A], + rtldm->default_ofdm_index); + + thermal_value = (u8)rtl_get_rfreg(hw, RF90_PATH_A, + /*0x42: RF Reg[15:10] 88E*/ + RF_T_METER_8812A, 0xfc00); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n", + thermal_value, rtlefuse->eeprom_thermalmeter); + if (!rtldm->txpower_track_control || + rtlefuse->eeprom_thermalmeter == 0 || + rtlefuse->eeprom_thermalmeter == 0xFF) + return; + + /* 3. Initialize ThermalValues of RFCalibrateInfo*/ + + if (rtlhal->reloadtxpowerindex) + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "reload ofdm index for band switch\n"); + + /*4. Calculate average thermal meter*/ + rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value; + rtldm->thermalvalue_avg_index++; + if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A) + /*Average times = c.AverageThermalNum*/ + rtldm->thermalvalue_avg_index = 0; + + for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) { + if (rtldm->thermalvalue_avg[i]) { + thermal_value_avg += rtldm->thermalvalue_avg[i]; + thermal_value_avg_count++; + } + } + /*Calculate Average ThermalValue after average enough times*/ + if (thermal_value_avg_count) { + thermal_value = (u8)(thermal_value_avg / + thermal_value_avg_count); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n", + thermal_value, rtlefuse->eeprom_thermalmeter); + } + + /*5. Calculate delta, delta_LCK, delta_IQK. + *"delta" here is used to determine whether + *thermal value changes or not. + */ + delta = (thermal_value > rtldm->thermalvalue) ? + (thermal_value - rtldm->thermalvalue) : + (rtldm->thermalvalue - thermal_value); + delta_lck = (thermal_value > rtldm->thermalvalue_lck) ? + (thermal_value - rtldm->thermalvalue_lck) : + (rtldm->thermalvalue_lck - thermal_value); + delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ? + (thermal_value - rtldm->thermalvalue_iqk) : + (rtldm->thermalvalue_iqk - thermal_value); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n", + delta, delta_lck, delta_iqk); + + /* 6. If necessary, do LCK. + * Delta temperature is equal to or larger than 20 centigrade. + */ + if (delta_lck >= IQK_THRESHOLD) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "delta_LCK(%d) >= Threshold_IQK(%d)\n", + delta_lck, IQK_THRESHOLD); + rtldm->thermalvalue_lck = thermal_value; + rtl8821ae_phy_lc_calibrate(hw); + } + + /*7. If necessary, move the index of swing table to adjust Tx power.*/ + + if (delta > 0 && rtldm->txpower_track_control) { + /* "delta" here is used to record the + * absolute value of differrence. + */ + delta = thermal_value > rtlefuse->eeprom_thermalmeter ? + (thermal_value - rtlefuse->eeprom_thermalmeter) : + (rtlefuse->eeprom_thermalmeter - thermal_value); + + if (delta >= TXPWR_TRACK_TABLE_SIZE) + delta = TXPWR_TRACK_TABLE_SIZE - 1; + + /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/ + + if (thermal_value > rtlefuse->eeprom_thermalmeter) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "delta_swing_table_idx_tup_a[%d] = %d\n", + delta, delta_swing_table_idx_tup_a[delta]); + rtldm->delta_power_index_last[RF90_PATH_A] = + rtldm->delta_power_index[RF90_PATH_A]; + rtldm->delta_power_index[RF90_PATH_A] = + delta_swing_table_idx_tup_a[delta]; + + rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] = + delta_swing_table_idx_tup_a[delta]; + /*Record delta swing for mix mode power tracking*/ + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", + rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "delta_swing_table_idx_tup_b[%d] = %d\n", + delta, delta_swing_table_idx_tup_b[delta]); + rtldm->delta_power_index_last[RF90_PATH_B] = + rtldm->delta_power_index[RF90_PATH_B]; + rtldm->delta_power_index[RF90_PATH_B] = + delta_swing_table_idx_tup_b[delta]; + + rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] = + delta_swing_table_idx_tup_b[delta]; + /*Record delta swing for mix mode power tracking*/ + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", + rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]); + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "delta_swing_table_idx_tdown_a[%d] = %d\n", + delta, delta_swing_table_idx_tdown_a[delta]); + + rtldm->delta_power_index_last[RF90_PATH_A] = + rtldm->delta_power_index[RF90_PATH_A]; + rtldm->delta_power_index[RF90_PATH_A] = + -1 * delta_swing_table_idx_tdown_a[delta]; + + rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] = + -1 * delta_swing_table_idx_tdown_a[delta]; + /* Record delta swing for mix mode power tracking*/ + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", + rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "deltaSwingTableIdx_TDOWN_B[%d] = %d\n", + delta, delta_swing_table_idx_tdown_b[delta]); + + rtldm->delta_power_index_last[RF90_PATH_B] = + rtldm->delta_power_index[RF90_PATH_B]; + rtldm->delta_power_index[RF90_PATH_B] = + -1 * delta_swing_table_idx_tdown_b[delta]; + + rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] = + -1 * delta_swing_table_idx_tdown_b[delta]; + /*Record delta swing for mix mode power tracking*/ + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", + rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]); + } + + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "============================= [Path-%c]Calculating PowerIndexOffset =============================\n", + (p == RF90_PATH_A ? 'A' : 'B')); + + if (rtldm->delta_power_index[p] == + rtldm->delta_power_index_last[p]) + /*If Thermal value changes but lookup + table value still the same*/ + rtldm->power_index_offset[p] = 0; + else + rtldm->power_index_offset[p] = + rtldm->delta_power_index[p] - + rtldm->delta_power_index_last[p]; + /* Power Index Diff between 2 + * times Power Tracking + */ + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "[Path-%c] PowerIndexOffset(%d) =DeltaPowerIndex(%d) -DeltaPowerIndexLast(%d)\n", + (p == RF90_PATH_A ? 'A' : 'B'), + rtldm->power_index_offset[p], + rtldm->delta_power_index[p] , + rtldm->delta_power_index_last[p]); + + rtldm->ofdm_index[p] = + rtldm->swing_idx_ofdm_base[p] + + rtldm->power_index_offset[p]; + rtldm->cck_index = + rtldm->swing_idx_cck_base + + rtldm->power_index_offset[p]; + + rtldm->swing_idx_cck = rtldm->cck_index; + rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p]; + + /****Print BB Swing Base and Index Offset */ + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n", + rtldm->swing_idx_cck, + rtldm->swing_idx_cck_base, + rtldm->power_index_offset[p]); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n", + rtldm->swing_idx_ofdm[p], + (p == RF90_PATH_A ? 'A' : 'B'), + rtldm->swing_idx_ofdm_base[p], + rtldm->power_index_offset[p]); + + /*7.1 Handle boundary conditions of index.*/ + + if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1) + rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1; + else if (rtldm->ofdm_index[p] < ofdm_min_index) + rtldm->ofdm_index[p] = ofdm_min_index; + } + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "\n\n====================================================================================\n"); + if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1) + rtldm->cck_index = TXSCALE_TABLE_SIZE - 1; + else if (rtldm->cck_index < 0) + rtldm->cck_index = 0; + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "The thermal meter is unchanged or TxPowerTracking OFF(%d): ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n", + rtldm->txpower_track_control, + thermal_value, + rtldm->thermalvalue); + + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) + rtldm->power_index_offset[p] = 0; + } + /*Print Swing base & current*/ + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "TxPowerTracking: [CCK] Swing Current Index: %d,Swing Base Index: %d\n", + rtldm->cck_index, rtldm->swing_idx_cck_base); + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "TxPowerTracking: [OFDM] Swing Current Index: %d,Swing Base Index[%c]: %d\n", + rtldm->ofdm_index[p], + (p == RF90_PATH_A ? 'A' : 'B'), + rtldm->swing_idx_ofdm_base[p]); + } + + if ((rtldm->power_index_offset[RF90_PATH_A] != 0 || + rtldm->power_index_offset[RF90_PATH_B] != 0) && + rtldm->txpower_track_control) { + /*7.2 Configure the Swing Table to adjust Tx Power. + *Always TRUE after Tx Power is adjusted by power tracking. + * + *2012/04/23 MH According to Luke's suggestion, + *we can not write BB digital + *to increase TX power. Otherwise, EVM will be bad. + * + *2012/04/25 MH Add for tx power tracking to set + *tx power in tx agc for 88E. + */ + if (thermal_value > rtldm->thermalvalue) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Temperature Increasing(A): delta_pi: %d , delta_t: %d, Now_t: %d,EFUSE_t: %d, Last_t: %d\n", + rtldm->power_index_offset[RF90_PATH_A], + delta, thermal_value, + rtlefuse->eeprom_thermalmeter, + rtldm->thermalvalue); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Temperature Increasing(B): delta_pi: %d ,delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", + rtldm->power_index_offset[RF90_PATH_B], + delta, thermal_value, + rtlefuse->eeprom_thermalmeter, + rtldm->thermalvalue); + } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/ + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", + rtldm->power_index_offset[RF90_PATH_A], + delta, thermal_value, + rtlefuse->eeprom_thermalmeter, + rtldm->thermalvalue); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Temperature Decreasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", + rtldm->power_index_offset[RF90_PATH_B], + delta, thermal_value, + rtlefuse->eeprom_thermalmeter, + rtldm->thermalvalue); + } + + if (thermal_value > rtlefuse->eeprom_thermalmeter) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Temperature(%d) higher than PG value(%d)\n", + thermal_value, rtlefuse->eeprom_thermalmeter); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "**********Enter POWER Tracking MIX_MODE**********\n"); + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) + rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, + p, 0); + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Temperature(%d) lower than PG value(%d)\n", + thermal_value, rtlefuse->eeprom_thermalmeter); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "**********Enter POWER Tracking MIX_MODE**********\n"); + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) + rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, + p, index_for_channel); + } + /*Record last time Power Tracking result as base.*/ + rtldm->swing_idx_cck_base = rtldm->swing_idx_cck; + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) + rtldm->swing_idx_ofdm_base[p] = + rtldm->swing_idx_ofdm[p]; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pDM_Odm->RFCalibrateInfo.ThermalValue =%d ThermalValue= %d\n", + rtldm->thermalvalue, thermal_value); + /*Record last Power Tracking Thermal Value*/ + rtldm->thermalvalue = thermal_value; + } + /*Delta temperature is equal to or larger than + 20 centigrade (When threshold is 8).*/ + if (delta_iqk >= IQK_THRESHOLD) + rtl8812ae_do_iqk(hw, delta_iqk, thermal_value, 8); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "<===rtl8812ae_dm_txpower_tracking_callback_thermalmeter\n"); +} + +static void rtl8821ae_get_delta_swing_table(struct ieee80211_hw *hw, u8 **up_a, + u8 **down_a, u8 **up_b, u8 **down_b) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + u8 channel = rtlphy->current_channel; + u8 rate = rtldm->tx_rate; + + if (1 <= channel && channel <= 14) { + if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) { + *up_a = rtl8821ae_delta_swing_table_idx_24gccka_p; + *down_a = rtl8821ae_delta_swing_table_idx_24gccka_n; + *up_b = rtl8821ae_delta_swing_table_idx_24gcckb_p; + *down_b = rtl8821ae_delta_swing_table_idx_24gcckb_n; + } else { + *up_a = rtl8821ae_delta_swing_table_idx_24ga_p; + *down_a = rtl8821ae_delta_swing_table_idx_24ga_n; + *up_b = rtl8821ae_delta_swing_table_idx_24gb_p; + *down_b = rtl8821ae_delta_swing_table_idx_24gb_n; + } + } else if (36 <= channel && channel <= 64) { + *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[0]; + *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[0]; + *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[0]; + *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[0]; + } else if (100 <= channel && channel <= 140) { + *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[1]; + *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[1]; + *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[1]; + *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[1]; + } else if (149 <= channel && channel <= 173) { + *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[2]; + *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[2]; + *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[2]; + *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[2]; + } else { + *up_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p; + *down_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n; + *up_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p; + *down_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n; + } + return; +} + +/*----------------------------------------------------------------------------- + * Function: odm_TxPwrTrackSetPwr88E() + * + * Overview: 88E change all channel tx power accordign to flag. + * OFDM & CCK are all different. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 04/23/2012 MHC Create Version 0. + * + *--------------------------------------------------------------------------- + */ +void rtl8821ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw, + enum pwr_track_control_method method, + u8 rf_path, u8 channel_mapped_index) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 final_swing_idx[1]; + u8 pwr_tracking_limit = 26; /*+1.0dB*/ + u8 tx_rate = 0xFF; + char final_ofdm_swing_index = 0; + + if (rtldm->tx_rate != 0xFF) + tx_rate = rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "===>%s\n", __func__); + + if (tx_rate != 0xFF) { /* Mimic Modify High Rate BBSwing Limit.*/ + /*CCK*/ + if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M)) + pwr_tracking_limit = 32; /*+4dB*/ + /*OFDM*/ + else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M)) + pwr_tracking_limit = 30; /*+3dB*/ + else if (tx_rate == MGN_54M) + pwr_tracking_limit = 28; /*+2dB*/ + /*HT*/ + /*QPSK/BPSK*/ + else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2)) + pwr_tracking_limit = 34; /*+5dB*/ + /*16QAM*/ + else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4)) + pwr_tracking_limit = 30; /*+3dB*/ + /*64QAM*/ + else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7)) + pwr_tracking_limit = 28; /*+2dB*/ + /*2 VHT*/ + /*QPSK/BPSK*/ + else if ((tx_rate >= MGN_VHT1SS_MCS0) && + (tx_rate <= MGN_VHT1SS_MCS2)) + pwr_tracking_limit = 34; /*+5dB*/ + /*16QAM*/ + else if ((tx_rate >= MGN_VHT1SS_MCS3) && + (tx_rate <= MGN_VHT1SS_MCS4)) + pwr_tracking_limit = 30; /*+3dB*/ + /*64QAM*/ + else if ((tx_rate >= MGN_VHT1SS_MCS5) && + (tx_rate <= MGN_VHT1SS_MCS6)) + pwr_tracking_limit = 28; /*+2dB*/ + else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/ + pwr_tracking_limit = 26; /*+1dB*/ + else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/ + pwr_tracking_limit = 24; /*+0dB*/ + else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/ + pwr_tracking_limit = 22; /*-1dB*/ + else + pwr_tracking_limit = 24; + } + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "TxRate=0x%x, PwrTrackingLimit=%d\n", + tx_rate, pwr_tracking_limit); + + if (method == BBSWING) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "===>%s\n", __func__); + if (rf_path == RF90_PATH_A) { + final_swing_idx[RF90_PATH_A] = + (rtldm->ofdm_index[RF90_PATH_A] > + pwr_tracking_limit) ? + pwr_tracking_limit : + rtldm->ofdm_index[RF90_PATH_A]; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n", + rtldm->ofdm_index[RF90_PATH_A], + final_swing_idx[RF90_PATH_A]); + + rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, + txscaling_tbl[final_swing_idx[RF90_PATH_A]]); + } + } else if (method == MIX_MODE) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pDM_Odm->DefaultOfdmIndex=%d,pDM_Odm->Aboslute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n", + rtldm->default_ofdm_index, + rtldm->absolute_ofdm_swing_idx[rf_path], + rf_path); + + final_ofdm_swing_index = + rtldm->default_ofdm_index + + rtldm->absolute_ofdm_swing_idx[rf_path]; + /*BBSwing higher then Limit*/ + if (rf_path == RF90_PATH_A) { + if (final_ofdm_swing_index > pwr_tracking_limit) { + rtldm->remnant_cck_idx = + final_ofdm_swing_index - + pwr_tracking_limit; + /* CCK Follow the same compensate value as Path A*/ + rtldm->remnant_ofdm_swing_idx[rf_path] = + final_ofdm_swing_index - + pwr_tracking_limit; + + rtl_set_bbreg(hw, RA_TXSCALE, + 0xFFE00000, + txscaling_tbl[pwr_tracking_limit]); + + rtldm->modify_txagc_flag_path_a = true; + + /*Set TxAGC Page C{};*/ + rtl8821ae_phy_set_txpower_level_by_path(hw, + rtlphy->current_channel, + RF90_PATH_A); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + " ******Path_A Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n", + pwr_tracking_limit, + rtldm->remnant_ofdm_swing_idx[rf_path]); + } else if (final_ofdm_swing_index < 0) { + rtldm->remnant_cck_idx = final_ofdm_swing_index; + /* CCK Follow the same compensate value as Path A*/ + rtldm->remnant_ofdm_swing_idx[rf_path] = + final_ofdm_swing_index; + + rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, + txscaling_tbl[0]); + + rtldm->modify_txagc_flag_path_a = true; + + /*Set TxAGC Page C{};*/ + rtl8821ae_phy_set_txpower_level_by_path(hw, + rtlphy->current_channel, RF90_PATH_A); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Path_A Lower then BBSwing lower bound 0 , Remnant TxAGC Value = %d\n", + rtldm->remnant_ofdm_swing_idx[rf_path]); + } else { + rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, + txscaling_tbl[(u8)final_ofdm_swing_index]); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Path_A Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n", + final_ofdm_swing_index); + /*If TxAGC has changed, reset TxAGC again*/ + if (rtldm->modify_txagc_flag_path_a) { + rtldm->remnant_cck_idx = 0; + rtldm->remnant_ofdm_swing_idx[rf_path] = 0; + + /*Set TxAGC Page C{};*/ + rtl8821ae_phy_set_txpower_level_by_path(hw, + rtlphy->current_channel, RF90_PATH_A); + + rtldm->modify_txagc_flag_path_a = false; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, + DBG_LOUD, + "******Path_A pDM_Odm->Modify_TxAGC_Flag= FALSE\n"); + } + } + } + } else { + return; + } +} + +void rtl8821ae_dm_txpower_tracking_callback_thermalmeter( + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0; + u8 thermal_value_avg_count = 0; + u32 thermal_value_avg = 0; + + u8 ofdm_min_index = 6; /*OFDM BB Swing should be less than +3.0dB */ + /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/ + u8 index_for_channel = 0; + + /* 1. The following TWO tables decide the final + * index of OFDM/CCK swing table. + */ + u8 *delta_swing_table_idx_tup_a; + u8 *delta_swing_table_idx_tdown_a; + u8 *delta_swing_table_idx_tup_b; + u8 *delta_swing_table_idx_tdown_b; + + /*2. Initilization ( 7 steps in total )*/ + rtl8821ae_get_delta_swing_table(hw, (u8 **)&delta_swing_table_idx_tup_a, + (u8 **)&delta_swing_table_idx_tdown_a, + (u8 **)&delta_swing_table_idx_tup_b, + (u8 **)&delta_swing_table_idx_tdown_b); + + rtldm->txpower_trackinginit = true; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "===>%s,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n", + __func__, + rtldm->swing_idx_cck_base, + rtldm->swing_idx_ofdm_base[RF90_PATH_A], + rtldm->default_ofdm_index); + /*0x42: RF Reg[15:10] 88E*/ + thermal_value = (u8)rtl_get_rfreg(hw, + RF90_PATH_A, RF_T_METER_8812A, 0xfc00); + if (!rtldm->txpower_track_control || + rtlefuse->eeprom_thermalmeter == 0 || + rtlefuse->eeprom_thermalmeter == 0xFF) + return; + + /* 3. Initialize ThermalValues of RFCalibrateInfo*/ + + if (rtlhal->reloadtxpowerindex) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "reload ofdm index for band switch\n"); + } + + /*4. Calculate average thermal meter*/ + rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value; + rtldm->thermalvalue_avg_index++; + if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A) + /*Average times = c.AverageThermalNum*/ + rtldm->thermalvalue_avg_index = 0; + + for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) { + if (rtldm->thermalvalue_avg[i]) { + thermal_value_avg += rtldm->thermalvalue_avg[i]; + thermal_value_avg_count++; + } + } + /*Calculate Average ThermalValue after average enough times*/ + if (thermal_value_avg_count) { + thermal_value = (u8)(thermal_value_avg / + thermal_value_avg_count); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n", + thermal_value, rtlefuse->eeprom_thermalmeter); + } + + /*5. Calculate delta, delta_LCK, delta_IQK. + *"delta" here is used to determine whether + * thermal value changes or not. + */ + delta = (thermal_value > rtldm->thermalvalue) ? + (thermal_value - rtldm->thermalvalue) : + (rtldm->thermalvalue - thermal_value); + delta_lck = (thermal_value > rtldm->thermalvalue_lck) ? + (thermal_value - rtldm->thermalvalue_lck) : + (rtldm->thermalvalue_lck - thermal_value); + delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ? + (thermal_value - rtldm->thermalvalue_iqk) : + (rtldm->thermalvalue_iqk - thermal_value); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n", + delta, delta_lck, delta_iqk); + + /* 6. If necessary, do LCK. */ + /*Delta temperature is equal to or larger than 20 centigrade.*/ + if (delta_lck >= IQK_THRESHOLD) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "delta_LCK(%d) >= Threshold_IQK(%d)\n", + delta_lck, IQK_THRESHOLD); + rtldm->thermalvalue_lck = thermal_value; + rtl8821ae_phy_lc_calibrate(hw); + } + + /*7. If necessary, move the index of swing table to adjust Tx power.*/ + + if (delta > 0 && rtldm->txpower_track_control) { + /*"delta" here is used to record the + * absolute value of differrence. + */ + delta = thermal_value > rtlefuse->eeprom_thermalmeter ? + (thermal_value - rtlefuse->eeprom_thermalmeter) : + (rtlefuse->eeprom_thermalmeter - thermal_value); + + if (delta >= TXSCALE_TABLE_SIZE) + delta = TXSCALE_TABLE_SIZE - 1; + + /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/ + + if (thermal_value > rtlefuse->eeprom_thermalmeter) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "delta_swing_table_idx_tup_a[%d] = %d\n", + delta, delta_swing_table_idx_tup_a[delta]); + rtldm->delta_power_index_last[RF90_PATH_A] = + rtldm->delta_power_index[RF90_PATH_A]; + rtldm->delta_power_index[RF90_PATH_A] = + delta_swing_table_idx_tup_a[delta]; + + rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] = + delta_swing_table_idx_tup_a[delta]; + /*Record delta swing for mix mode power tracking*/ + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", + rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "delta_swing_table_idx_tdown_a[%d] = %d\n", + delta, delta_swing_table_idx_tdown_a[delta]); + + rtldm->delta_power_index_last[RF90_PATH_A] = + rtldm->delta_power_index[RF90_PATH_A]; + rtldm->delta_power_index[RF90_PATH_A] = + -1 * delta_swing_table_idx_tdown_a[delta]; + + rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] = + -1 * delta_swing_table_idx_tdown_a[delta]; + /* Record delta swing for mix mode power tracking*/ + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", + rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); + } + + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "\n\n================================ [Path-%c]Calculating PowerIndexOffset ================================\n", + (p == RF90_PATH_A ? 'A' : 'B')); + /*If Thermal value changes but lookup table value + * still the same + */ + if (rtldm->delta_power_index[p] == + rtldm->delta_power_index_last[p]) + + rtldm->power_index_offset[p] = 0; + else + rtldm->power_index_offset[p] = + rtldm->delta_power_index[p] - + rtldm->delta_power_index_last[p]; + /*Power Index Diff between 2 times Power Tracking*/ + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "[Path-%c] PowerIndexOffset(%d) = DeltaPowerIndex(%d) - DeltaPowerIndexLast(%d)\n", + (p == RF90_PATH_A ? 'A' : 'B'), + rtldm->power_index_offset[p], + rtldm->delta_power_index[p] , + rtldm->delta_power_index_last[p]); + + rtldm->ofdm_index[p] = + rtldm->swing_idx_ofdm_base[p] + + rtldm->power_index_offset[p]; + rtldm->cck_index = + rtldm->swing_idx_cck_base + + rtldm->power_index_offset[p]; + + rtldm->swing_idx_cck = rtldm->cck_index; + rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p]; + + /*********Print BB Swing Base and Index Offset********/ + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n", + rtldm->swing_idx_cck, + rtldm->swing_idx_cck_base, + rtldm->power_index_offset[p]); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n", + rtldm->swing_idx_ofdm[p], + (p == RF90_PATH_A ? 'A' : 'B'), + rtldm->swing_idx_ofdm_base[p], + rtldm->power_index_offset[p]); + + /*7.1 Handle boundary conditions of index.*/ + + if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1) + rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1; + else if (rtldm->ofdm_index[p] < ofdm_min_index) + rtldm->ofdm_index[p] = ofdm_min_index; + } + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "\n\n========================================================================================================\n"); + if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1) + rtldm->cck_index = TXSCALE_TABLE_SIZE - 1; + else if (rtldm->cck_index < 0) + rtldm->cck_index = 0; + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "The thermal meter is unchanged or TxPowerTracking OFF(%d):ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n", + rtldm->txpower_track_control, + thermal_value, + rtldm->thermalvalue); + + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) + rtldm->power_index_offset[p] = 0; + } + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "TxPowerTracking: [CCK] Swing Current Index: %d, Swing Base Index: %d\n", + /*Print Swing base & current*/ + rtldm->cck_index, rtldm->swing_idx_cck_base); + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "TxPowerTracking: [OFDM] Swing Current Index: %d, Swing Base Index[%c]: %d\n", + rtldm->ofdm_index[p], + (p == RF90_PATH_A ? 'A' : 'B'), + rtldm->swing_idx_ofdm_base[p]); + } + + if ((rtldm->power_index_offset[RF90_PATH_A] != 0 || + rtldm->power_index_offset[RF90_PATH_B] != 0) && + rtldm->txpower_track_control) { + /*7.2 Configure the Swing Table to adjust Tx Power.*/ + /*Always TRUE after Tx Power is adjusted by power tracking.*/ + /* + * 2012/04/23 MH According to Luke's suggestion, + * we can not write BB digital + * to increase TX power. Otherwise, EVM will be bad. + * + * 2012/04/25 MH Add for tx power tracking to + * set tx power in tx agc for 88E. + */ + if (thermal_value > rtldm->thermalvalue) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Temperature Increasing(A): delta_pi: %d , delta_t: %d,Now_t: %d, EFUSE_t: %d, Last_t: %d\n", + rtldm->power_index_offset[RF90_PATH_A], + delta, thermal_value, + rtlefuse->eeprom_thermalmeter, + rtldm->thermalvalue); + } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/ + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", + rtldm->power_index_offset[RF90_PATH_A], + delta, thermal_value, + rtlefuse->eeprom_thermalmeter, + rtldm->thermalvalue); + } + + if (thermal_value > rtlefuse->eeprom_thermalmeter) { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Temperature(%d) higher than PG value(%d)\n", + thermal_value, rtlefuse->eeprom_thermalmeter); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "****Enter POWER Tracking MIX_MODE****\n"); + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) + rtl8821ae_dm_txpwr_track_set_pwr(hw, + MIX_MODE, p, index_for_channel); + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Temperature(%d) lower than PG value(%d)\n", + thermal_value, rtlefuse->eeprom_thermalmeter); + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "*****Enter POWER Tracking MIX_MODE*****\n"); + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) + rtl8812ae_dm_txpwr_track_set_pwr(hw, + MIX_MODE, p, index_for_channel); + } + /*Record last time Power Tracking result as base.*/ + rtldm->swing_idx_cck_base = rtldm->swing_idx_cck; + for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) + rtldm->swing_idx_ofdm_base[p] = rtldm->swing_idx_ofdm[p]; + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n", + rtldm->thermalvalue, thermal_value); + /*Record last Power Tracking Thermal Value*/ + rtldm->thermalvalue = thermal_value; + } + /* Delta temperature is equal to or larger than + * 20 centigrade (When threshold is 8). + */ + if (delta_iqk >= IQK_THRESHOLD) { + if (!rtlphy->lck_inprogress) { + spin_lock(&rtlpriv->locks.iqk_lock); + rtlphy->lck_inprogress = true; + spin_unlock(&rtlpriv->locks.iqk_lock); + + rtl8821ae_do_iqk(hw, delta_iqk, thermal_value, 8); + + spin_lock(&rtlpriv->locks.iqk_lock); + rtlphy->lck_inprogress = false; + spin_unlock(&rtlpriv->locks.iqk_lock); + } + } + + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===%s\n", __func__); +} + +void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (!rtlpriv->dm.tm_trigger) { + rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16), + 0x03); + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Trigger 8821ae Thermal Meter!!\n"); + rtlpriv->dm.tm_trigger = 1; + return; + } else { + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Schedule TxPowerTracking !!\n"); + + rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw); + rtlpriv->dm.tm_trigger = 0; + } +} + +static void rtl8821ae_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rate_adaptive *p_ra = &rtlpriv->ra; + u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m; + u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra; + u8 go_up_gap = 5; + struct ieee80211_sta *sta = NULL; + + if (is_hal_stop(rtlhal)) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "driver is going to unload\n"); + return; + } + + if (!rtlpriv->dm.useramask) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "driver does not control rate adaptive mask\n"); + return; + } + + if (mac->link_state == MAC80211_LINKED && + mac->opmode == NL80211_IFTYPE_STATION) { + switch (p_ra->pre_ratr_state) { + case DM_RATR_STA_MIDDLE: + high_rssithresh_for_ra += go_up_gap; + break; + case DM_RATR_STA_LOW: + high_rssithresh_for_ra += go_up_gap; + low_rssithresh_for_ra += go_up_gap; + break; + default: + break; + } + + if (rtlpriv->dm.undec_sm_pwdb > + (long)high_rssithresh_for_ra) + p_ra->ratr_state = DM_RATR_STA_HIGH; + else if (rtlpriv->dm.undec_sm_pwdb > + (long)low_rssithresh_for_ra) + p_ra->ratr_state = DM_RATR_STA_MIDDLE; + else + p_ra->ratr_state = DM_RATR_STA_LOW; + + if (p_ra->pre_ratr_state != p_ra->ratr_state) { + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "RSSI = %ld\n", + rtlpriv->dm.undec_sm_pwdb); + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "RSSI_LEVEL = %d\n", p_ra->ratr_state); + RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, + "PreState = %d, CurState = %d\n", + p_ra->pre_ratr_state, p_ra->ratr_state); + + rcu_read_lock(); + sta = rtl_find_sta(hw, mac->bssid); + if (sta) + rtlpriv->cfg->ops->update_rate_tbl(hw, + sta, p_ra->ratr_state); + rcu_read_unlock(); + + p_ra->pre_ratr_state = p_ra->ratr_state; + } + } +} + +static void rtl8821ae_dm_refresh_basic_rate_mask(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + struct rtl_mac *mac = &rtlpriv->mac80211; + static u8 stage; + u8 cur_stage = 0; + u16 basic_rate = RRSR_1M | RRSR_2M | RRSR_5_5M | RRSR_11M | RRSR_6M; + + if (mac->link_state < MAC80211_LINKED) + cur_stage = 0; + else if (dm_digtable->rssi_val_min < 25) + cur_stage = 1; + else if (dm_digtable->rssi_val_min > 30) + cur_stage = 3; + else + cur_stage = 2; + + if (cur_stage != stage) { + if (cur_stage == 1) { + basic_rate &= (!(basic_rate ^ mac->basic_rates)); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_BASIC_RATE, (u8 *)&basic_rate); + } else if (cur_stage == 3 && (stage == 1 || stage == 2)) { + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_BASIC_RATE, (u8 *)&mac->basic_rates); + } + } + stage = cur_stage; +} + +static void rtl8821ae_dm_edca_choose_traffic_idx( + struct ieee80211_hw *hw, u64 cur_tx_bytes, + u64 cur_rx_bytes, bool b_bias_on_rx, + bool *pb_is_cur_rdl_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (b_bias_on_rx) { + if (cur_tx_bytes > (cur_rx_bytes*4)) { + *pb_is_cur_rdl_state = false; + RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, + "Uplink Traffic\n "); + } else { + *pb_is_cur_rdl_state = true; + RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, + "Balance Traffic\n"); + } + } else { + if (cur_rx_bytes > (cur_tx_bytes*4)) { + *pb_is_cur_rdl_state = true; + RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, + "Downlink Traffic\n"); + } else { + *pb_is_cur_rdl_state = false; + RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, + "Balance Traffic\n"); + } + } + return; +} + +static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + + /*Keep past Tx/Rx packet count for RT-to-RT EDCA turbo.*/ + u64 cur_tx_ok_cnt = 0; + u64 cur_rx_ok_cnt = 0; + u32 edca_be_ul = 0x5ea42b; + u32 edca_be_dl = 0x5ea42b; + u32 edca_be = 0x5ea42b; + u8 iot_peer = 0; + bool *pb_is_cur_rdl_state = NULL; + bool b_last_is_cur_rdl_state = false; + bool b_bias_on_rx = false; + bool b_edca_turbo_on = false; + + RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, + "rtl8821ae_dm_check_edca_turbo=====>"); + RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, + "Orginial BE PARAM: 0x%x\n", + rtl_read_dword(rtlpriv, DM_REG_EDCA_BE_11N)); + + if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100) + rtlpriv->dm.is_any_nonbepkts = true; + rtlpriv->dm.dbginfo.num_non_be_pkt = 0; + + /*=============================== + * list paramter for different platform + *=============================== + */ + b_last_is_cur_rdl_state = rtlpriv->dm.is_cur_rdlstate; + pb_is_cur_rdl_state = &rtlpriv->dm.is_cur_rdlstate; + + cur_tx_ok_cnt = rtlpriv->stats.txbytesunicast - rtldm->last_tx_ok_cnt; + cur_rx_ok_cnt = rtlpriv->stats.rxbytesunicast - rtldm->last_rx_ok_cnt; + + rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast; + rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast; + + iot_peer = rtlpriv->mac80211.vendor; + b_bias_on_rx = false; + b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) && + (!rtlpriv->dm.disable_framebursting)) ? + true : false; + + if (rtlpriv->rtlhal.hw_type != HARDWARE_TYPE_RTL8812AE) { + if ((iot_peer == PEER_CISCO) && + (mac->mode == WIRELESS_MODE_N_24G)) { + edca_be_dl = edca_setting_dl[iot_peer]; + edca_be_ul = edca_setting_ul[iot_peer]; + } + } + + RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, + "bIsAnyNonBEPkts : 0x%x bDisableFrameBursting : 0x%x\n", + rtlpriv->dm.is_any_nonbepkts, + rtlpriv->dm.disable_framebursting); + + RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, + "bEdcaTurboOn : 0x%x bBiasOnRx : 0x%x\n", + b_edca_turbo_on, b_bias_on_rx); + + if (b_edca_turbo_on) { + RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, + "curTxOkCnt : 0x%llx\n", cur_tx_ok_cnt); + RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, + "curRxOkCnt : 0x%llx\n", cur_rx_ok_cnt); + if (b_bias_on_rx) + rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt, + cur_rx_ok_cnt, true, pb_is_cur_rdl_state); + else + rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt, + cur_rx_ok_cnt, false, pb_is_cur_rdl_state); + + edca_be = (*pb_is_cur_rdl_state) ? edca_be_dl : edca_be_ul; + + rtl_write_dword(rtlpriv, DM_REG_EDCA_BE_11N, edca_be); + + RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, + "EDCA Turbo on: EDCA_BE:0x%x\n", edca_be); + + rtlpriv->dm.current_turbo_edca = true; + + RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, + "EDCA_BE_DL : 0x%x EDCA_BE_UL : 0x%x EDCA_BE : 0x%x\n", + edca_be_dl, edca_be_ul, edca_be); + } else { + if (rtlpriv->dm.current_turbo_edca) { + u8 tmp = AC0_BE; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, + (u8 *)(&tmp)); + } + rtlpriv->dm.current_turbo_edca = false; + } + + rtlpriv->dm.is_any_nonbepkts = false; + rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast; + rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast; +} + +static void rtl8821ae_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + u8 cur_cck_cca_thresh; + + if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) { + if (dm_digtable->rssi_val_min > 25) { + cur_cck_cca_thresh = 0xcd; + } else if ((dm_digtable->rssi_val_min <= 25) && + (dm_digtable->rssi_val_min > 10)) { + cur_cck_cca_thresh = 0x83; + } else { + if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) + cur_cck_cca_thresh = 0x83; + else + cur_cck_cca_thresh = 0x40; + } + } else { + if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) + cur_cck_cca_thresh = 0x83; + else + cur_cck_cca_thresh = 0x40; + } + + if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh) + rtl_write_byte(rtlpriv, ODM_REG_CCK_CCA_11AC, + cur_cck_cca_thresh); + + dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres; + dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh; + RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, + "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres); +} + +static void rtl8821ae_dm_dynamic_atc_switch(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + u8 crystal_cap; + u32 packet_count; + int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0; + int cfo_ave_diff; + + if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { + /*1.Enable ATC*/ + if (rtldm->atc_status == ATC_STATUS_OFF) { + rtl_set_bbreg(hw, RFC_AREA, BIT(14), ATC_STATUS_ON); + rtldm->atc_status = ATC_STATUS_ON; + } + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "No link!!\n"); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "atc_status = %d\n", rtldm->atc_status); + + if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) { + rtldm->crystal_cap = rtlpriv->efuse.crystalcap; + crystal_cap = rtldm->crystal_cap & 0x3f; + crystal_cap = crystal_cap & 0x3f; + if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE) + rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, + 0x7ff80000, (crystal_cap | + (crystal_cap << 6))); + else + rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, + 0xfff000, (crystal_cap | + (crystal_cap << 6))); + } + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "crystal_cap = 0x%x\n", + rtldm->crystal_cap); + } else{ + /*1. Calculate CFO for path-A & path-B*/ + cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280; + cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280; + packet_count = rtldm->packet_count; + + /*2.No new packet*/ + if (packet_count == rtldm->packet_count_pre) { + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "packet counter doesn't change\n"); + return; + } + + rtldm->packet_count_pre = packet_count; + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "packet counter = %d\n", + rtldm->packet_count); + + /*3.Average CFO*/ + if (rtlpriv->phy.rf_type == RF_1T1R) + cfo_ave = cfo_khz_a; + else + cfo_ave = (cfo_khz_a + cfo_khz_b) >> 1; + + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "cfo_khz_a = %dkHz, cfo_khz_b = %dkHz, cfo_ave = %dkHz\n", + cfo_khz_a, cfo_khz_b, cfo_ave); + + /*4.Avoid abnormal large CFO*/ + cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ? + (rtldm->cfo_ave_pre - cfo_ave) : + (cfo_ave - rtldm->cfo_ave_pre); + + if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) { + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "first large CFO hit\n"); + rtldm->large_cfo_hit = 1; + return; + } else + rtldm->large_cfo_hit = 0; + + rtldm->cfo_ave_pre = cfo_ave; + + /*CFO tracking by adjusting Xtal cap.*/ + + /*1.Dynamic Xtal threshold*/ + if (cfo_ave >= -rtldm->cfo_threshold && + cfo_ave <= rtldm->cfo_threshold && + rtldm->is_freeze == 0) { + if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) { + rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10; + rtldm->is_freeze = 1; + } else { + rtldm->cfo_threshold = CFO_THRESHOLD_XTAL; + } + } + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Dynamic threshold = %d\n", + rtldm->cfo_threshold); + + /* 2.Calculate Xtal offset*/ + if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f) + adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1; + else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) && + rtlpriv->dm.crystal_cap > 0) + adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1; + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "Crystal cap = 0x%x, Crystal cap offset = %d\n", + rtldm->crystal_cap, adjust_xtal); + + /*3.Adjudt Crystal Cap.*/ + if (adjust_xtal != 0) { + rtldm->is_freeze = 0; + rtldm->crystal_cap += adjust_xtal; + + if (rtldm->crystal_cap > 0x3f) + rtldm->crystal_cap = 0x3f; + else if (rtldm->crystal_cap < 0) + rtldm->crystal_cap = 0; + + crystal_cap = rtldm->crystal_cap & 0x3f; + crystal_cap = crystal_cap & 0x3f; + if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE) + rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, + 0x7ff80000, (crystal_cap | + (crystal_cap << 6))); + else + rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, + 0xfff000, (crystal_cap | + (crystal_cap << 6))); + RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, + "New crystal cap = 0x%x\n", + rtldm->crystal_cap); + } + } +} + +void rtl8821ae_dm_watchdog(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool fw_current_inpsmode = false; + bool fw_ps_awake = true; + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inpsmode)); + + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, + (u8 *)(&fw_ps_awake)); + + if (ppsc->p2p_ps_info.p2p_ps_mode) + fw_ps_awake = false; + + if ((ppsc->rfpwr_state == ERFON) && + ((!fw_current_inpsmode) && fw_ps_awake) && + (!ppsc->rfchange_inprogress)) { + rtl8821ae_dm_common_info_self_update(hw); + rtl8821ae_dm_false_alarm_counter_statistics(hw); + rtl8821ae_dm_check_rssi_monitor(hw); + rtl8821ae_dm_dig(hw); + rtl8821ae_dm_cck_packet_detection_thresh(hw); + rtl8821ae_dm_refresh_rate_adaptive_mask(hw); + rtl8821ae_dm_refresh_basic_rate_mask(hw); + rtl8821ae_dm_check_edca_turbo(hw); + rtl8821ae_dm_dynamic_atc_switch(hw); + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtl8812ae_dm_check_txpower_tracking_thermalmeter(hw); + else + rtl8821ae_dm_check_txpower_tracking_thermalmeter(hw); + rtl8821ae_dm_iq_calibrate(hw); + } + + rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0; + RT_TRACE(rtlpriv, COMP_DIG, DBG_DMESG, "\n"); +} + +void rtl8821ae_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, + u8 *pdesc, u32 mac_id) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct fast_ant_training *pfat_table = &rtldm->fat_table; + + if (rtlhal->hw_type != HARDWARE_TYPE_RTL8812AE) + return; + + if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) + SET_TX_DESC_TX_ANT(pdesc, pfat_table->antsel_a[mac_id]); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h new file mode 100644 index 000000000000..625a6bbb21fc --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.h @@ -0,0 +1,315 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8821AE_DM_H__ +#define __RTL8821AE_DM_H__ + +#define MAIN_ANT 0 +#define AUX_ANT 1 +#define MAIN_ANT_CG_TRX 1 +#define AUX_ANT_CG_TRX 0 +#define MAIN_ANT_CGCS_RX 0 +#define AUX_ANT_CGCS_RX 1 + +#define TXSCALE_TABLE_SIZE 37 + +/*RF REG LIST*/ +#define DM_REG_RF_MODE_11N 0x00 +#define DM_REG_RF_0B_11N 0x0B +#define DM_REG_CHNBW_11N 0x18 +#define DM_REG_T_METER_11N 0x24 +#define DM_REG_RF_25_11N 0x25 +#define DM_REG_RF_26_11N 0x26 +#define DM_REG_RF_27_11N 0x27 +#define DM_REG_RF_2B_11N 0x2B +#define DM_REG_RF_2C_11N 0x2C +#define DM_REG_RXRF_A3_11N 0x3C +#define DM_REG_T_METER_92D_11N 0x42 +#define DM_REG_T_METER_88E_11N 0x42 + +/*BB REG LIST*/ +/*PAGE 8 */ +#define DM_REG_BB_CTRL_11N 0x800 +#define DM_REG_RF_PIN_11N 0x804 +#define DM_REG_PSD_CTRL_11N 0x808 +#define DM_REG_TX_ANT_CTRL_11N 0x80C +#define DM_REG_BB_PWR_SAV5_11N 0x818 +#define DM_REG_CCK_RPT_FORMAT_11N 0x824 +#define DM_REG_RX_DEFUALT_A_11N 0x858 +#define DM_REG_RX_DEFUALT_B_11N 0x85A +#define DM_REG_BB_PWR_SAV3_11N 0x85C +#define DM_REG_ANTSEL_CTRL_11N 0x860 +#define DM_REG_RX_ANT_CTRL_11N 0x864 +#define DM_REG_PIN_CTRL_11N 0x870 +#define DM_REG_BB_PWR_SAV1_11N 0x874 +#define DM_REG_ANTSEL_PATH_11N 0x878 +#define DM_REG_BB_3WIRE_11N 0x88C +#define DM_REG_SC_CNT_11N 0x8C4 +#define DM_REG_PSD_DATA_11N 0x8B4 +/*PAGE 9*/ +#define DM_REG_ANT_MAPPING1_11N 0x914 +#define DM_REG_ANT_MAPPING2_11N 0x918 +/*PAGE A*/ +#define DM_REG_CCK_ANTDIV_PARA1_11N 0xA00 +#define DM_REG_CCK_CCA_11N 0xA0A +#define DM_REG_CCK_CCA_11AC 0xA0A +#define DM_REG_CCK_ANTDIV_PARA2_11N 0xA0C +#define DM_REG_CCK_ANTDIV_PARA3_11N 0xA10 +#define DM_REG_CCK_ANTDIV_PARA4_11N 0xA14 +#define DM_REG_CCK_FILTER_PARA1_11N 0xA22 +#define DM_REG_CCK_FILTER_PARA2_11N 0xA23 +#define DM_REG_CCK_FILTER_PARA3_11N 0xA24 +#define DM_REG_CCK_FILTER_PARA4_11N 0xA25 +#define DM_REG_CCK_FILTER_PARA5_11N 0xA26 +#define DM_REG_CCK_FILTER_PARA6_11N 0xA27 +#define DM_REG_CCK_FILTER_PARA7_11N 0xA28 +#define DM_REG_CCK_FILTER_PARA8_11N 0xA29 +#define DM_REG_CCK_FA_RST_11N 0xA2C +#define DM_REG_CCK_FA_MSB_11N 0xA58 +#define DM_REG_CCK_FA_LSB_11N 0xA5C +#define DM_REG_CCK_CCA_CNT_11N 0xA60 +#define DM_REG_BB_PWR_SAV4_11N 0xA74 +/*PAGE B */ +#define DM_REG_LNA_SWITCH_11N 0xB2C +#define DM_REG_PATH_SWITCH_11N 0xB30 +#define DM_REG_RSSI_CTRL_11N 0xB38 +#define DM_REG_CONFIG_ANTA_11N 0xB68 +#define DM_REG_RSSI_BT_11N 0xB9C +/*PAGE C */ +#define DM_REG_OFDM_FA_HOLDC_11N 0xC00 +#define DM_REG_RX_PATH_11N 0xC04 +#define DM_REG_TRMUX_11N 0xC08 +#define DM_REG_OFDM_FA_RSTC_11N 0xC0C +#define DM_REG_RXIQI_MATRIX_11N 0xC14 +#define DM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C +#define DM_REG_IGI_A_11N 0xC50 +#define DM_REG_IGI_A_11AC 0xC50 +#define DM_REG_ANTDIV_PARA2_11N 0xC54 +#define DM_REG_IGI_B_11N 0xC58 +#define DM_REG_IGI_B_11AC 0xE50 +#define DM_REG_ANTDIV_PARA3_11N 0xC5C +#define DM_REG_BB_PWR_SAV2_11N 0xC70 +#define DM_REG_RX_OFF_11N 0xC7C +#define DM_REG_TXIQK_MATRIXA_11N 0xC80 +#define DM_REG_TXIQK_MATRIXB_11N 0xC88 +#define DM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 +#define DM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C +#define DM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 +#define DM_REG_ANTDIV_PARA1_11N 0xCA4 +#define DM_REG_OFDM_FA_TYPE1_11N 0xCF0 +/*PAGE D */ +#define DM_REG_OFDM_FA_RSTD_11N 0xD00 +#define DM_REG_OFDM_FA_TYPE2_11N 0xDA0 +#define DM_REG_OFDM_FA_TYPE3_11N 0xDA4 +#define DM_REG_OFDM_FA_TYPE4_11N 0xDA8 +/*PAGE E */ +#define DM_REG_TXAGC_A_6_18_11N 0xE00 +#define DM_REG_TXAGC_A_24_54_11N 0xE04 +#define DM_REG_TXAGC_A_1_MCS32_11N 0xE08 +#define DM_REG_TXAGC_A_MCS0_3_11N 0xE10 +#define DM_REG_TXAGC_A_MCS4_7_11N 0xE14 +#define DM_REG_TXAGC_A_MCS8_11_11N 0xE18 +#define DM_REG_TXAGC_A_MCS12_15_11N 0xE1C +#define DM_REG_FPGA0_IQK_11N 0xE28 +#define DM_REG_TXIQK_TONE_A_11N 0xE30 +#define DM_REG_RXIQK_TONE_A_11N 0xE34 +#define DM_REG_TXIQK_PI_A_11N 0xE38 +#define DM_REG_RXIQK_PI_A_11N 0xE3C +#define DM_REG_TXIQK_11N 0xE40 +#define DM_REG_RXIQK_11N 0xE44 +#define DM_REG_IQK_AGC_PTS_11N 0xE48 +#define DM_REG_IQK_AGC_RSP_11N 0xE4C +#define DM_REG_BLUETOOTH_11N 0xE6C +#define DM_REG_RX_WAIT_CCA_11N 0xE70 +#define DM_REG_TX_CCK_RFON_11N 0xE74 +#define DM_REG_TX_CCK_BBON_11N 0xE78 +#define DM_REG_OFDM_RFON_11N 0xE7C +#define DM_REG_OFDM_BBON_11N 0xE80 +#define DM_REG_TX2RX_11N 0xE84 +#define DM_REG_TX2TX_11N 0xE88 +#define DM_REG_RX_CCK_11N 0xE8C +#define DM_REG_RX_OFDM_11N 0xED0 +#define DM_REG_RX_WAIT_RIFS_11N 0xED4 +#define DM_REG_RX2RX_11N 0xED8 +#define DM_REG_STANDBY_11N 0xEDC +#define DM_REG_SLEEP_11N 0xEE0 +#define DM_REG_PMPD_ANAEN_11N 0xEEC + +/*MAC REG LIST*/ +#define DM_REG_BB_RST_11N 0x02 +#define DM_REG_ANTSEL_PIN_11N 0x4C +#define DM_REG_EARLY_MODE_11N 0x4D0 +#define DM_REG_RSSI_MONITOR_11N 0x4FE +#define DM_REG_EDCA_VO_11N 0x500 +#define DM_REG_EDCA_VI_11N 0x504 +#define DM_REG_EDCA_BE_11N 0x508 +#define DM_REG_EDCA_BK_11N 0x50C +#define DM_REG_TXPAUSE_11N 0x522 +#define DM_REG_RESP_TX_11N 0x6D8 +#define DM_REG_ANT_TRAIN_PARA1_11N 0x7b0 +#define DM_REG_ANT_TRAIN_PARA2_11N 0x7b4 + +/*DIG Related*/ +#define DM_BIT_IGI_11N 0x0000007F +#define DM_BIT_IGI_11AC 0xFFFFFFFF + +#define HAL_DM_DIG_DISABLE BIT(0) +#define HAL_DM_HIPWR_DISABLE BIT(1) + +#define OFDM_TABLE_LENGTH 43 +#define CCK_TABLE_LENGTH 33 + +#define OFDM_TABLE_SIZE 37 +#define CCK_TABLE_SIZE 33 + +#define BW_AUTO_SWITCH_HIGH_LOW 25 +#define BW_AUTO_SWITCH_LOW_HIGH 30 + +#define DM_DIG_FA_UPPER 0x3e +#define DM_DIG_FA_LOWER 0x1e +#define DM_DIG_FA_TH0 200 +#define DM_DIG_FA_TH1 0x300 +#define DM_DIG_FA_TH2 0x400 + +#define RXPATHSELECTION_SS_TH_LOW 30 +#define RXPATHSELECTION_DIFF_TH 18 + +#define DM_RATR_STA_INIT 0 +#define DM_RATR_STA_HIGH 1 +#define DM_RATR_STA_MIDDLE 2 +#define DM_RATR_STA_LOW 3 + +#define CTS2SELF_THVAL 30 +#define REGC38_TH 20 + +#define WAIOTTHVAL 25 + +#define TXHIGHPWRLEVEL_NORMAL 0 +#define TXHIGHPWRLEVEL_LEVEL1 1 +#define TXHIGHPWRLEVEL_LEVEL2 2 +#define TXHIGHPWRLEVEL_BT1 3 +#define TXHIGHPWRLEVEL_BT2 4 + +#define DM_TYPE_BYFW 0 +#define DM_TYPE_BYDRIVER 1 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 +#define TXPWRTRACK_MAX_IDX 6 + +/* Dynamic ATC switch */ +#define ATC_STATUS_OFF 0x0 /* enable */ +#define ATC_STATUS_ON 0x1 /* disable */ +#define CFO_THRESHOLD_XTAL 10 /* kHz */ +#define CFO_THRESHOLD_ATC 80 /* kHz */ + +#define AVG_THERMAL_NUM_8812A 4 +#define TXPWR_TRACK_TABLE_SIZE 30 +#define MAX_PATH_NUM_8812A 2 +#define MAX_PATH_NUM_8821A 1 + +enum FAT_STATE { + FAT_NORMAL_STATE = 0, + FAT_TRAINING_STATE = 1, +}; + +enum tag_dynamic_init_gain_operation_type_definition { + DIG_TYPE_THRESH_HIGH = 0, + DIG_TYPE_THRESH_LOW = 1, + DIG_TYPE_BACKOFF = 2, + DIG_TYPE_RX_GAIN_MIN = 3, + DIG_TYPE_RX_GAIN_MAX = 4, + DIG_TYPE_ENABLE = 5, + DIG_TYPE_DISABLE = 6, + DIG_OP_TYPE_MAX +}; + +enum dm_1r_cca_e { + CCA_1R = 0, + CCA_2R = 1, + CCA_MAX = 2, +}; + +enum dm_rf_e { + RF_SAVE = 0, + RF_NORMAL = 1, + RF_MAX = 2, +}; + +enum dm_sw_ant_switch_e { + ANS_ANTENNA_B = 1, + ANS_ANTENNA_A = 2, + ANS_ANTENNA_MAX = 3, +}; + +enum pwr_track_control_method { + BBSWING, + TXAGC, + MIX_MODE +}; + +#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1) +#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1) +#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1) +#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1) +#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1) +#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ + ((((struct rtl_priv *)(_priv))->mac80211.opmode == \ + NL80211_IFTYPE_ADHOC) ? \ + (((struct rtl_priv *)(_priv))->dm.entry_min_undec_sm_pwdb) : \ + (((struct rtl_priv *)(_priv))->dm.undec_sm_pwdb)) + +void rtl8821ae_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, + u8 *pdesc, u32 mac_id); +void rtl8821ae_dm_ant_sel_statistics(struct ieee80211_hw *hw, + u8 antsel_tr_mux, u32 mac_id, + u32 rx_pwdb_all); +void rtl8821ae_dm_fast_antenna_training_callback(unsigned long data); +void rtl8821ae_dm_init(struct ieee80211_hw *hw); +void rtl8821ae_dm_watchdog(struct ieee80211_hw *hw); +void rtl8821ae_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi); +void rtl8821ae_dm_init_edca_turbo(struct ieee80211_hw *hw); +void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw); +void rtl8821ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); +void rtl8821ae_dm_txpower_track_adjust(struct ieee80211_hw *hw, + u8 type, u8 *pdirection, + u32 *poutwrite_val); +void rtl8821ae_dm_clear_txpower_tracking_state(struct ieee80211_hw *hw); +void rtl8821ae_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 current_cca); +void rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(struct ieee80211_hw *hw); +void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw, + enum pwr_track_control_method method, + u8 rf_path, + u8 channel_mapped_index); +void rtl8821ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw, + enum pwr_track_control_method method, + u8 rf_path, u8 channel_mapped_index); + +void rtl8821ae_dm_update_init_rate(struct ieee80211_hw *hw, u8 rate); +u8 rtl8821ae_hw_rate_to_mrate(struct ieee80211_hw *hw, u8 rate); +void rtl8812ae_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw *hw); +void rtl8821ae_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c new file mode 100644 index 000000000000..525eb234627c --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c @@ -0,0 +1,1857 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../core.h" +#include "reg.h" +#include "def.h" +#include "fw.h" +#include "dm.h" + +static void _rtl8821ae_enable_fw_download(struct ieee80211_hw *hw, bool enable) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp; + + if (enable) { + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05); + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); + rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); + + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + } else { + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); + tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); + } +} + +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) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 *bufferptr = (u8 *)buffer; + u32 pagenums, remainsize; + u32 page, offset; + + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size); + + _rtl8821ae_fill_dummy(bufferptr, &size); + + pagenums = size / FW_8821AE_PAGE_SIZE; + remainsize = size % FW_8821AE_PAGE_SIZE; + + if (pagenums > 8) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Page numbers should not greater then 8\n"); + } + + for (page = 0; page < pagenums; page++) { + offset = page * FW_8821AE_PAGE_SIZE; + _rtl8821ae_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); + } +} + +static int _rtl8821ae_fw_free_to_go(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int err = -EIO; + u32 counter = 0; + u32 value32; + + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + } while ((counter++ < FW_8821AE_POLLING_TIMEOUT_COUNT) && + (!(value32 & FWDL_CHKSUM_RPT))); + + if (counter >= FW_8821AE_POLLING_TIMEOUT_COUNT) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "chksum report faill ! REG_MCUFWDL:0x%08x .\n", + value32); + goto exit; + } + + RT_TRACE(rtlpriv, COMP_FW, DBG_EMERG, + "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); + + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + value32 |= MCUFWDL_RDY; + value32 &= ~WINTINI_RDY; + rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); + + rtl8821ae_firmware_selfreset(hw); + + counter = 0; + do { + value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); + if (value32 & WINTINI_RDY) { + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n", + value32); + err = 0; + goto exit; + } + + udelay(FW_8821AE_POLLING_DELAY); + } while (counter++ < FW_8821AE_POLLING_TIMEOUT_COUNT); + + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", + value32); + +exit: + return err; +} + +static void _rtl8821ae_wait_for_h2c_cmd_finish(struct rtl_priv *rtlpriv) +{ + u8 val; + u16 count = 0; + + do { + val = rtl_read_byte(rtlpriv, REG_HMETFR); + mdelay(1); + count++; + } while ((val & 0x0F) && (count < 1000)); +} + +int rtl8821ae_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtlwifi_firmware_header *pfwheader; + u8 *pfwdata; + u32 fwsize; + int err; + bool support_remote_wakeup; + enum version_8821ae version = rtlhal->version; + + rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, + (u8 *)(&support_remote_wakeup)); + + if (support_remote_wakeup) + _rtl8821ae_wait_for_h2c_cmd_finish(rtlpriv); + + if (buse_wake_on_wlan_fw) { + if (!rtlhal->wowlan_firmware) + return 1; + + pfwheader = + (struct rtlwifi_firmware_header *)rtlhal->wowlan_firmware; + rtlhal->fw_version = le16_to_cpu(pfwheader->version); + rtlhal->fw_subversion = pfwheader->subversion; + pfwdata = (u8 *)rtlhal->wowlan_firmware; + fwsize = rtlhal->wowlan_fwsize; + } else { + if (!rtlhal->pfirmware) + return 1; + + pfwheader = + (struct rtlwifi_firmware_header *)rtlhal->pfirmware; + rtlhal->fw_version = le16_to_cpu(pfwheader->version); + rtlhal->fw_subversion = pfwheader->subversion; + pfwdata = (u8 *)rtlhal->pfirmware; + fwsize = rtlhal->fwsize; + } + + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "%s Firmware SIZE %d\n", + buse_wake_on_wlan_fw ? "Wowlan" : "Normal", fwsize); + + if (IS_FW_HEADER_EXIST_8812(pfwheader) || + IS_FW_HEADER_EXIST_8821(pfwheader)) { + RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, + "Firmware Version(%d), Signature(%#x)\n", + pfwheader->version, pfwheader->signature); + + pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); + fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); + } + + if (rtlhal->mac_func_enable) { + if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); + rtl8821ae_firmware_selfreset(hw); + } + } + _rtl8821ae_enable_fw_download(hw, true); + _rtl8821ae_write_fw(hw, version, pfwdata, fwsize); + _rtl8821ae_enable_fw_download(hw, false); + + err = _rtl8821ae_fw_free_to_go(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Firmware is not ready to run!\n"); + } else { + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "Firmware is ready to run!\n"); + } + + return 0; +} + +#if (USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN == 1) +void rtl8821ae_set_fw_related_for_wowlan(struct ieee80211_hw *hw, + bool used_wowlan_fw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + /* 1. Before WoWLAN or After WOWLAN we need to re-download Fw. */ + if (rtl8821ae_download_fw(hw, used_wowlan_fw)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Re-Download Firmware failed!!\n"); + rtlhal->fw_ready = false; + return; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Re-Download Firmware Success !!\n"); + rtlhal->fw_ready = true; + + /* 2. Re-Init the variables about Fw related setting. */ + ppsc->fw_current_inpsmode = false; + rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_8821AE; + rtlhal->fw_clk_change_in_progress = false; + rtlhal->allow_sw_to_change_hwclc = false; + rtlhal->last_hmeboxnum = 0; +} +#endif + +static bool _rtl8821ae_check_fw_read_last_h2c(struct ieee80211_hw *hw, + u8 boxnum) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 val_hmetfr; + bool result = false; + + val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); + if (((val_hmetfr >> boxnum) & BIT(0)) == 0) + result = true; + return result; +} + +static void _rtl8821ae_fill_h2c_command(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, + u8 *cmdbuffer) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 boxnum = 0; + u16 box_reg = 0, box_extreg = 0; + u8 u1b_tmp = 0; + bool isfw_read = false; + u8 buf_index = 0; + bool bwrite_sucess = false; + u8 wait_h2c_limmit = 100; + /*u8 wait_writeh2c_limmit = 100;*/ + u8 boxcontent[4], boxextcontent[4]; + u32 h2c_waitcounter = 0; + unsigned long flag = 0; + u8 idx = 0; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); + + while (true) { + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + if (rtlhal->h2c_setinprogress) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C set in progress! Wait to set..element_id(%d).\n", + element_id); + + while (rtlhal->h2c_setinprogress) { + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, + flag); + h2c_waitcounter++; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Wait 100 us (%d times)...\n", + h2c_waitcounter); + udelay(100); + + if (h2c_waitcounter > 1000) + return; + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, + flag); + } + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + } else { + rtlhal->h2c_setinprogress = true; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + break; + } + } + + while (!bwrite_sucess) { + boxnum = rtlhal->last_hmeboxnum; + switch (boxnum) { + case 0: + box_reg = REG_HMEBOX_0; + box_extreg = REG_HMEBOX_EXT_0; + break; + case 1: + box_reg = REG_HMEBOX_1; + box_extreg = REG_HMEBOX_EXT_1; + break; + case 2: + box_reg = REG_HMEBOX_2; + box_extreg = REG_HMEBOX_EXT_2; + break; + case 3: + box_reg = REG_HMEBOX_3; + box_extreg = REG_HMEBOX_EXT_3; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + + isfw_read = false; + u1b_tmp = rtl_read_byte(rtlpriv, REG_CR); + + if (u1b_tmp != 0xEA) { + isfw_read = true; + } else { + if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xEA || + rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xEA) + rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xFF); + } + + if (isfw_read) { + wait_h2c_limmit = 100; + isfw_read = + _rtl8821ae_check_fw_read_last_h2c(hw, boxnum); + while (!isfw_read) { + /*wait until Fw read*/ + wait_h2c_limmit--; + if (wait_h2c_limmit == 0) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Waiting too long for FW read clear HMEBox(%d)!\n", + boxnum); + break; + } + + udelay(10); + + isfw_read = + _rtl8821ae_check_fw_read_last_h2c(hw, boxnum); + u1b_tmp = rtl_read_byte(rtlpriv, 0x130); + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", + boxnum, u1b_tmp); + } + } + + if (!isfw_read) { + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", + boxnum); + break; + } + + memset(boxcontent, 0, sizeof(boxcontent)); + memset(boxextcontent, 0, sizeof(boxextcontent)); + boxcontent[0] = element_id; + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "Write element_id box_reg(%4x) = %2x\n", + box_reg, element_id); + + switch (cmd_len) { + case 1: + case 2: + case 3: + /*boxcontent[0] &= ~(BIT(7));*/ + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index, cmd_len); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + case 4: + case 5: + case 6: + case 7: + /*boxcontent[0] |= (BIT(7));*/ + memcpy((u8 *)(boxextcontent), + cmdbuffer + buf_index+3, cmd_len-3); + memcpy((u8 *)(boxcontent) + 1, + cmdbuffer + buf_index, 3); + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_extreg + idx, + boxextcontent[idx]); + } + + for (idx = 0; idx < 4; idx++) { + rtl_write_byte(rtlpriv, box_reg + idx, + boxcontent[idx]); + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + + bwrite_sucess = true; + + rtlhal->last_hmeboxnum = boxnum + 1; + if (rtlhal->last_hmeboxnum == 4) + rtlhal->last_hmeboxnum = 0; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, + "pHalData->last_hmeboxnum = %d\n", + rtlhal->last_hmeboxnum); + } + + spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); + rtlhal->h2c_setinprogress = false; + spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); + + RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); +} + +void rtl8821ae_fill_h2c_cmd(struct ieee80211_hw *hw, + u8 element_id, u32 cmd_len, u8 *cmdbuffer) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 tmp_cmdbuf[2]; + + if (!rtlhal->fw_ready) { + RT_ASSERT(false, + "return H2C cmd because of Fw download fail!!!\n"); + return; + } + + memset(tmp_cmdbuf, 0, 8); + memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); + _rtl8821ae_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); +} + +void rtl8821ae_firmware_selfreset(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 u1b_tmp; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp & (~BIT(3)))); + } else { + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp & (~BIT(0)))); + } + + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); + udelay(50); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp | BIT(3))); + } else { + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp | BIT(0))); + } + + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2))); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "_8051Reset8812ae(): 8051 reset success .\n"); +} + +void rtl8821ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 u1_h2c_set_pwrmode[H2C_8821AE_PWEMODE_LENGTH] = { 0 }; + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 rlbm, power_state = 0; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); + + SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); + rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/ + SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); + SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, + (rtlpriv->mac80211.p2p) ? + ppsc->smart_ps : 1); + SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, + ppsc->reg_max_lps_awakeintvl); + SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); + if (mode == FW_PS_ACTIVE_MODE) + power_state |= FW_PWR_STATE_ACTIVE; + else + power_state |= FW_PWR_STATE_RF_OFF; + + SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", + u1_h2c_set_pwrmode, H2C_8821AE_PWEMODE_LENGTH); + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_SETPWRMODE, + H2C_8821AE_PWEMODE_LENGTH, + u1_h2c_set_pwrmode); +} + +void rtl8821ae_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, + u8 mstatus) +{ + u8 parm[3] = { 0, 0, 0 }; + /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect + * bit1=0-->update Media Status to MACID + * bit1=1-->update Media Status from MACID to MACID_End + * parm[1]: MACID, if this is INFRA_STA, MacID = 0 + * parm[2]: MACID_End + */ + + SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); + SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); + + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_MSRRPT, 3, parm); +} + +void rtl8821ae_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, + u8 ap_offload_enable) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 u1_apoffload_parm[H2C_8821AE_AP_OFFLOAD_LENGTH] = { 0 }; + + SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable); + SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid); + SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0); + + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_AP_OFFLOAD, + H2C_8821AE_AP_OFFLOAD_LENGTH, + u1_apoffload_parm); +} + +void rtl8821ae_set_fw_wowlan_mode(struct ieee80211_hw *hw, bool func_en) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + u8 fw_wowlan_info[H2C_8821AE_WOWLAN_LENGTH] = {0}; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "enable(%d)\n", func_en); + + SET_8812_H2CCMD_WOWLAN_FUNC_ENABLE(fw_wowlan_info, + (func_en ? true : false)); + + SET_8812_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(fw_wowlan_info, + ((ppsc->wo_wlan_mode & WAKE_ON_PATTERN_MATCH) ? 1 : 0)); + SET_8812_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(fw_wowlan_info, + ((ppsc->wo_wlan_mode & WAKE_ON_MAGIC_PACKET) ? 1 : 0)); + + SET_8812_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(fw_wowlan_info, 0); + SET_8812_H2CCMD_WOWLAN_ALL_PKT_DROP(fw_wowlan_info, false); + SET_8812_H2CCMD_WOWLAN_GPIO_ACTIVE(fw_wowlan_info, 0); + SET_8812_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(fw_wowlan_info, 1); + SET_8812_H2CCMD_WOWLAN_GPIONUM(fw_wowlan_info, 0); + SET_8812_H2CCMD_WOWLAN_GPIO_DURATION(fw_wowlan_info, 0); + + RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_DMESG, + "wowlan mode: cmd 0x80: Content:\n", + fw_wowlan_info, H2C_8821AE_WOWLAN_LENGTH); + + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_WO_WLAN, + H2C_8821AE_WOWLAN_LENGTH, + fw_wowlan_info); +} + +void rtl8821ae_set_fw_remote_wake_ctrl_cmd(struct ieee80211_hw *hw, + u8 enable) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 remote_wake_ctrl_parm[H2C_8821AE_REMOTE_WAKE_CTRL_LEN] = {0}; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "enable=%d, ARP offload=%d, GTK offload=%d\n", + enable, ppsc->arp_offload_enable, ppsc->gtk_offload_enable); + + SET_8812_H2CCMD_REMOTE_WAKECTRL_ENABLE(remote_wake_ctrl_parm, enable); + SET_8812_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(remote_wake_ctrl_parm, + (ppsc->arp_offload_enable ? 1 : 0)); + SET_8812_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(remote_wake_ctrl_parm, + (ppsc->gtk_offload_enable ? 1 : 0)); + SET_8812_H2CCMD_REMOTE_WAKE_CTRL_REALWOWV2_EN(remote_wake_ctrl_parm, + (rtlhal->real_wow_v2_enable ? 1 : 0)); + + RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, + "remote_wake_ctrl: cmd 0x4: Content:\n", + remote_wake_ctrl_parm, H2C_8821AE_REMOTE_WAKE_CTRL_LEN); + + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_REMOTE_WAKE_CTRL, + H2C_8821AE_REMOTE_WAKE_CTRL_LEN, + remote_wake_ctrl_parm); +} + +void rtl8821ae_set_fw_keep_alive_cmd(struct ieee80211_hw *hw, + bool func_en) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 keep_alive_info[H2C_8821AE_KEEP_ALIVE_CTRL_LENGTH] = {0}; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Enable(%d)\n", func_en); + + SET_8812_H2CCMD_KEEP_ALIVE_ENABLE(keep_alive_info, func_en); + /* 1: the period is controled by driver, 0: by Fw default */ + SET_8812_H2CCMD_KEEP_ALIVE_ACCPEPT_USER_DEFINED(keep_alive_info, 1); + SET_8812_H2CCMD_KEEP_ALIVE_PERIOD(keep_alive_info, 10); /* 10 sec */ + + RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, + "keep alive: cmd 0x3: Content:\n", + keep_alive_info, H2C_8821AE_KEEP_ALIVE_CTRL); + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_KEEP_ALIVE_CTRL, + H2C_8821AE_KEEP_ALIVE_CTRL_LENGTH, + keep_alive_info); +} + +void rtl8821ae_set_fw_disconnect_decision_ctrl_cmd(struct ieee80211_hw *hw, + bool enabled) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 parm[H2C_8821AE_DISCONNECT_DECISION_CTRL_LEN] = {0}; + + SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_ENABLE(parm, enabled); + SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_USER_SETTING(parm, 1); + SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_CHECK_PERIOD(parm, 30); + SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_TRYPKT_NUM(parm, 3); + + RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, + "disconnect_decision_ctrl: cmd 0x4: Content:\n", + parm, H2C_8821AE_DISCONNECT_DECISION_CTRL_LEN); + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_DISCONNECT_DECISION, + H2C_8821AE_DISCONNECT_DECISION_CTRL_LEN, parm); +} + +void rtl8821ae_set_fw_global_info_cmd(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_security *sec = &rtlpriv->sec; + u8 remote_wakeup_sec_info[H2C_8821AE_AOAC_GLOBAL_INFO_LEN] = {0}; + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "PairwiseEncAlgorithm=%d, GroupEncAlgorithm=%d\n", + sec->pairwise_enc_algorithm, sec->group_enc_algorithm); + + SET_8812_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG( + remote_wakeup_sec_info, + sec->pairwise_enc_algorithm); + SET_8812_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(remote_wakeup_sec_info, + sec->group_enc_algorithm); + + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_AOAC_GLOBAL_INFO, + H2C_8821AE_AOAC_GLOBAL_INFO_LEN, + remote_wakeup_sec_info); + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_TRACE, + "rtl8821ae_set_global_info: cmd 0x82:\n", + remote_wakeup_sec_info, H2C_8821AE_AOAC_GLOBAL_INFO_LEN); +} + +#define BEACON_PG 0 +#define PSPOLL_PG 1 +#define NULL_PG 2 +#define QOSNULL_PG 3 +#define ARPRESP_PG 4 +#define REMOTE_PG 5 +#define GTKEXT_PG 6 + +#define TOTAL_RESERVED_PKT_LEN_8812 3584 +#define TOTAL_RESERVED_PKT_LEN_8821 1792 + +static u8 reserved_page_packet_8821[TOTAL_RESERVED_PKT_LEN_8821] = { + /* page 0: beacon */ + 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xe0, 0x4c, 0x02, 0xe2, 0x64, + 0x40, 0x16, 0x9f, 0x23, 0xd4, 0x46, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x20, 0x04, 0x00, 0x06, 0x64, 0x6c, + 0x69, 0x6e, 0x6b, 0x31, 0x01, 0x08, 0x82, 0x84, + 0x8b, 0x96, 0x0c, 0x18, 0x30, 0x48, 0x03, 0x01, + 0x0b, 0x06, 0x02, 0x00, 0x00, 0x2a, 0x01, 0x8b, + 0x32, 0x04, 0x12, 0x24, 0x60, 0x6c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x28, 0x8c, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* page 1: ps-poll */ + 0xa4, 0x10, 0x01, 0xc0, 0x40, 0x16, 0x9f, 0x23, + 0xd4, 0x46, 0x00, 0xe0, 0x4c, 0x02, 0xe2, 0x64, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x28, 0x8c, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* page 2: null data */ + 0x48, 0x01, 0x00, 0x00, 0x40, 0x16, 0x9f, 0x23, + 0xd4, 0x46, 0x00, 0xe0, 0x4c, 0x02, 0xe2, 0x64, + 0x40, 0x16, 0x9f, 0x23, 0xd4, 0x46, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* page 3: qos null data */ + 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, + 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* page 4~6 is for wowlan */ + /* page 4: ARP resp */ + 0x08, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, + 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, + 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06, + 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, + 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* page 5: H2C_REMOTE_WAKE_CTRL_INFO */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* page 6: Rsvd GTK extend memory (zero memory) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = { + /* page 0: beacon */ + 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x00, 0x20, 0x04, 0x00, 0x03, 0x32, 0x31, + 0x35, 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x0C, + 0x12, 0x18, 0x24, 0x03, 0x01, 0x01, 0x06, 0x02, + 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, 0x04, 0x30, + 0x48, 0x60, 0x6C, 0x2D, 0x1A, 0xED, 0x09, 0x03, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, + 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, 0x02, 0x02, + 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* page 1: ps-poll */ + 0xA4, 0x10, 0x09, 0xC0, 0x84, 0xC9, 0xB2, 0xA7, + 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* page 2: null data */ + 0x48, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, + 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* page 3: Qos null data */ + 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, + 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* page 4~6 is for wowlan */ + /* page 4: ARP resp */ + 0x08, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, + 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, + 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06, + 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, + 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* page 5: H2C_REMOTE_WAKE_CTRL_INFO */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* page 6: Rsvd GTK extend memory (zero memory) */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, + bool b_dl_finished, bool dl_whole_packets) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtlpriv); + struct sk_buff *skb = NULL; + u32 totalpacketlen; + bool rtstatus; + u8 u1RsvdPageLoc[5] = { 0 }; + u8 u1RsvdPageLoc2[7] = { 0 }; + bool b_dlok = false; + u8 *beacon; + u8 *p_pspoll; + u8 *nullfunc; + u8 *qosnull; + u8 *arpresp; + + /*--------------------------------------------------------- + * (1) beacon + *--------------------------------------------------------- + */ + beacon = &reserved_page_packet_8812[BEACON_PG * 512]; + SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); + SET_80211_HDR_ADDRESS3(beacon, mac->bssid); + + if (b_dl_finished) { + totalpacketlen = 512 - 40; + goto out; + } + /*------------------------------------------------------- + * (2) ps-poll + *-------------------------------------------------------- + */ + p_pspoll = &reserved_page_packet_8812[PSPOLL_PG * 512]; + SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); + SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); + SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); + + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); + + /*-------------------------------------------------------- + * (3) null data + *--------------------------------------------------------- + */ + nullfunc = &reserved_page_packet_8812[NULL_PG * 512]; + SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); + SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); + SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); + + /*--------------------------------------------------------- + * (4) Qos null data + *---------------------------------------------------------- + */ + qosnull = &reserved_page_packet_8812[QOSNULL_PG * 512]; + SET_80211_HDR_ADDRESS1(qosnull, mac->bssid); + SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr); + SET_80211_HDR_ADDRESS3(qosnull, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1RsvdPageLoc, QOSNULL_PG); + + if (!dl_whole_packets) { + totalpacketlen = 512 * (QOSNULL_PG + 1) - 40; + goto out; + } + /*--------------------------------------------------------- + * (5) ARP Resp + *---------------------------------------------------------- + */ + arpresp = &reserved_page_packet_8812[ARPRESP_PG * 512]; + SET_80211_HDR_ADDRESS1(arpresp, mac->bssid); + SET_80211_HDR_ADDRESS2(arpresp, mac->mac_addr); + SET_80211_HDR_ADDRESS3(arpresp, mac->bssid); + + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1RsvdPageLoc2, ARPRESP_PG); + + /*--------------------------------------------------------- + * (6) Remote Wake Ctrl + *---------------------------------------------------------- + */ + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1RsvdPageLoc2, + REMOTE_PG); + + /*--------------------------------------------------------- + * (7) GTK Ext Memory + *---------------------------------------------------------- + */ + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1RsvdPageLoc2, GTKEXT_PG); + + totalpacketlen = TOTAL_RESERVED_PKT_LEN_8812 - 40; + +out: + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "rtl8812ae_set_fw_rsvdpagepkt(): packet data\n", + &reserved_page_packet_8812[0], totalpacketlen); + + skb = dev_alloc_skb(totalpacketlen); + memcpy((u8 *)skb_put(skb, totalpacketlen), + &reserved_page_packet_8812, totalpacketlen); + + rtstatus = rtl_cmd_send_packet(hw, skb); + + if (rtstatus) + b_dlok = true; + + if (!b_dl_finished && b_dlok) { + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 5); + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_RSVDPAGE, + sizeof(u1RsvdPageLoc), u1RsvdPageLoc); + if (dl_whole_packets) { + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "wowlan H2C_RSVDPAGE:\n", u1RsvdPageLoc2, 7); + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_AOAC_RSVDPAGE, + sizeof(u1RsvdPageLoc2), u1RsvdPageLoc2); + } + } + + if (!b_dlok) + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set RSVD page location to Fw FAIL!!!!!!.\n"); +} + +void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, + bool b_dl_finished, bool dl_whole_packets) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct sk_buff *skb = NULL; + u32 totalpacketlen; + bool rtstatus; + u8 u1RsvdPageLoc[5] = { 0 }; + u8 u1RsvdPageLoc2[7] = { 0 }; + bool b_dlok = false; + u8 *beacon; + u8 *p_pspoll; + u8 *nullfunc; + u8 *qosnull; + u8 *arpresp; + + /*--------------------------------------------------------- + * (1) beacon + *--------------------------------------------------------- + */ + beacon = &reserved_page_packet_8821[BEACON_PG * 256]; + SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); + SET_80211_HDR_ADDRESS3(beacon, mac->bssid); + + if (b_dl_finished) { + totalpacketlen = 256 - 40; + goto out; + } + /*------------------------------------------------------- + * (2) ps-poll + *-------------------------------------------------------- + */ + p_pspoll = &reserved_page_packet_8821[PSPOLL_PG * 256]; + SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); + SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); + SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); + + SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); + + /*-------------------------------------------------------- + * (3) null data + *---------------------------------------------------------i + */ + nullfunc = &reserved_page_packet_8821[NULL_PG * 256]; + SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); + SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); + SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); + + /*--------------------------------------------------------- + * (4) Qos null data + *---------------------------------------------------------- + */ + qosnull = &reserved_page_packet_8821[QOSNULL_PG * 256]; + SET_80211_HDR_ADDRESS1(qosnull, mac->bssid); + SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr); + SET_80211_HDR_ADDRESS3(qosnull, mac->bssid); + + SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1RsvdPageLoc, QOSNULL_PG); + + if (!dl_whole_packets) { + totalpacketlen = 256 * (QOSNULL_PG + 1) - 40; + goto out; + } + /*--------------------------------------------------------- + * (5) ARP Resp + *---------------------------------------------------------- + */ + arpresp = &reserved_page_packet_8821[ARPRESP_PG * 256]; + SET_80211_HDR_ADDRESS1(arpresp, mac->bssid); + SET_80211_HDR_ADDRESS2(arpresp, mac->mac_addr); + SET_80211_HDR_ADDRESS3(arpresp, mac->bssid); + + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1RsvdPageLoc2, ARPRESP_PG); + + /*--------------------------------------------------------- + * (6) Remote Wake Ctrl + *---------------------------------------------------------- + */ + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1RsvdPageLoc2, + REMOTE_PG); + + /*--------------------------------------------------------- + * (7) GTK Ext Memory + *---------------------------------------------------------- + */ + SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1RsvdPageLoc2, GTKEXT_PG); + + totalpacketlen = TOTAL_RESERVED_PKT_LEN_8821 - 40; + +out: + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "rtl8821ae_set_fw_rsvdpagepkt(): packet data\n", + &reserved_page_packet_8821[0], totalpacketlen); + + skb = dev_alloc_skb(totalpacketlen); + memcpy((u8 *)skb_put(skb, totalpacketlen), + &reserved_page_packet_8821, totalpacketlen); + + rtstatus = rtl_cmd_send_packet(hw, skb); + + if (rtstatus) + b_dlok = true; + + if (!b_dl_finished && b_dlok) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Set RSVD page location to Fw.\n"); + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 5); + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_RSVDPAGE, + sizeof(u1RsvdPageLoc), u1RsvdPageLoc); + if (dl_whole_packets) { + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, + "wowlan H2C_RSVDPAGE:\n", + u1RsvdPageLoc2, 7); + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_AOAC_RSVDPAGE, + sizeof(u1RsvdPageLoc2), + u1RsvdPageLoc2); + } + } + + if (!b_dlok) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set RSVD page location to Fw FAIL!!!!!!.\n"); + } +} + +/*Should check FW support p2p or not.*/ +static void rtl8821ae_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) +{ + u8 u1_ctwindow_period[1] = { ctwindow}; + + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_P2P_PS_CTW_CMD, 1, + u1_ctwindow_period); +} + +void rtl8821ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info; + struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; + u8 i; + u16 ctwindow; + u32 start_time, tsf_low; + + switch (p2p_ps_state) { + case P2P_PS_DISABLE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); + memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); + break; + case P2P_PS_ENABLE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); + /* update CTWindow value. */ + if (p2pinfo->ctwindow > 0) { + p2p_ps_offload->ctwindow_en = 1; + ctwindow = p2pinfo->ctwindow; + rtl8821ae_set_p2p_ctw_period_cmd(hw, ctwindow); + } + + /* hw only support 2 set of NoA */ + for (i = 0 ; i < p2pinfo->noa_num ; i++) { + /* To control the register setting for which NOA*/ + rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); + if (i == 0) + p2p_ps_offload->noa0_en = 1; + else + p2p_ps_offload->noa1_en = 1; + + /* config P2P NoA Descriptor Register */ + rtl_write_dword(rtlpriv, 0x5E0, p2pinfo->noa_duration[i]); + rtl_write_dword(rtlpriv, 0x5E4, p2pinfo->noa_interval[i]); + + /*Get Current TSF value */ + tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + start_time = p2pinfo->noa_start_time[i]; + if (p2pinfo->noa_count_type[i] != 1) { + while (start_time <= (tsf_low+(50*1024))) { + start_time += p2pinfo->noa_interval[i]; + if (p2pinfo->noa_count_type[i] != 255) + p2pinfo->noa_count_type[i]--; + } + } + rtl_write_dword(rtlpriv, 0x5E8, start_time); + rtl_write_dword(rtlpriv, 0x5EC, + p2pinfo->noa_count_type[i]); + } + + if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { + /* rst p2p circuit */ + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); + + p2p_ps_offload->offload_en = 1; + + if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { + p2p_ps_offload->role = 1; + p2p_ps_offload->allstasleep = 0; + } else { + p2p_ps_offload->role = 0; + } + + p2p_ps_offload->discovery = 0; + } + break; + case P2P_PS_SCAN: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); + p2p_ps_offload->discovery = 1; + break; + case P2P_PS_SCAN_DONE: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); + p2p_ps_offload->discovery = 0; + p2pinfo->p2p_ps_state = P2P_PS_ENABLE; + break; + default: + break; + } + + rtl8821ae_fill_h2c_cmd(hw, + H2C_8821AE_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload); +} + +static void rtl8821ae_c2h_ra_report_handler(struct ieee80211_hw *hw, + u8 *cmd_buf, u8 cmd_len) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 rate = cmd_buf[0] & 0x3F; + + rtlhal->current_ra_rate = rtl8821ae_hw_rate_to_mrate(hw, rate); + + rtl8821ae_dm_update_init_rate(hw, rate); +} + +static void _rtl8821ae_c2h_content_parsing(struct ieee80211_hw *hw, + u8 c2h_cmd_id, u8 c2h_cmd_len, + u8 *tmp_buf) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (c2h_cmd_id) { + case C2H_8812_DBG: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "[C2H], C2H_8812_DBG!!\n"); + break; + case C2H_8812_RA_RPT: + rtl8821ae_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len); + break; + case C2H_8812_BT_INFO: + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "[C2H], C2H_8812_BT_INFO!!\n"); + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, + tmp_buf, + c2h_cmd_len); + break; + default: + break; + } +} + +void rtl8821ae_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, + u8 length) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0; + u8 *tmp_buf = NULL; + + c2h_cmd_id = buffer[0]; + c2h_cmd_seq = buffer[1]; + c2h_cmd_len = length - 2; + tmp_buf = buffer + 2; + + RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, + "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n", + c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len); + + RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_LOUD, + "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len); + _rtl8821ae_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h new file mode 100644 index 000000000000..8f5b4aade3c9 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.h @@ -0,0 +1,332 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8821AE__FW__H__ +#define __RTL8821AE__FW__H__ +#include "def.h" + +#define FW_8821AE_SIZE 0x8000 +#define FW_8821AE_START_ADDRESS 0x1000 +#define FW_8821AE_END_ADDRESS 0x5FFF +#define FW_8821AE_PAGE_SIZE 4096 +#define FW_8821AE_POLLING_DELAY 5 +#define FW_8821AE_POLLING_TIMEOUT_COUNT 6000 + +#define IS_FW_HEADER_EXIST_8812(_pfwhdr) \ + ((le16_to_cpu(_pfwhdr->signature) & 0xFFF0) == 0x9500) + +#define IS_FW_HEADER_EXIST_8821(_pfwhdr) \ + ((le16_to_cpu(_pfwhdr->signature) & 0xFFF0) == 0x2100) + +#define USE_OLD_WOWLAN_DEBUG_FW 0 + +#define H2C_8821AE_RSVDPAGE_LOC_LEN 5 +#define H2C_8821AE_PWEMODE_LENGTH 5 +#define H2C_8821AE_JOINBSSRPT_LENGTH 1 +#define H2C_8821AE_AP_OFFLOAD_LENGTH 3 +#define H2C_8821AE_WOWLAN_LENGTH 3 +#define H2C_8821AE_KEEP_ALIVE_CTRL_LENGTH 3 +#if (USE_OLD_WOWLAN_DEBUG_FW == 0) +#define H2C_8821AE_REMOTE_WAKE_CTRL_LEN 1 +#else +#define H2C_8821AE_REMOTE_WAKE_CTRL_LEN 3 +#endif +#define H2C_8821AE_AOAC_GLOBAL_INFO_LEN 2 +#define H2C_8821AE_AOAC_RSVDPAGE_LOC_LEN 7 +#define H2C_8821AE_DISCONNECT_DECISION_CTRL_LEN 3 + +/* Fw PS state for RPWM. +*BIT[2:0] = HW state + +*BIT[3] = Protocol PS state, +1: register active state , +0: register sleep state + +*BIT[4] = sub-state +*/ +#define FW_PS_GO_ON BIT(0) +#define FW_PS_TX_NULL BIT(1) +#define FW_PS_RF_ON BIT(2) +#define FW_PS_REGISTER_ACTIVE BIT(3) + +#define FW_PS_DPS BIT(0) +#define FW_PS_LCLK (FW_PS_DPS) +#define FW_PS_RF_OFF BIT(1) +#define FW_PS_ALL_ON BIT(2) +#define FW_PS_ST_ACTIVE BIT(3) +#define FW_PS_ISR_ENABLE BIT(4) +#define FW_PS_IMR_ENABLE BIT(5) + +#define FW_PS_ACK BIT(6) +#define FW_PS_TOGGLE BIT(7) + + /* 8821AE RPWM value*/ + /* BIT[0] = 1: 32k, 0: 40M*/ + /* 32k*/ +#define FW_PS_CLOCK_OFF BIT(0) +/*40M*/ +#define FW_PS_CLOCK_ON 0 + +#define FW_PS_STATE_MASK (0x0F) +#define FW_PS_STATE_HW_MASK (0x07) +/*ISR_ENABLE, IMR_ENABLE, and PS mode should be inherited.*/ +#define FW_PS_STATE_INT_MASK (0x3F) + +#define FW_PS_STATE(x) (FW_PS_STATE_MASK & (x)) +#define FW_PS_STATE_HW(x) (FW_PS_STATE_HW_MASK & (x)) +#define FW_PS_STATE_INT(x) (FW_PS_STATE_INT_MASK & (x)) +#define FW_PS_ISR_VAL(x) ((x) & 0x70) +#define FW_PS_IMR_MASK(x) ((x) & 0xDF) +#define FW_PS_KEEP_IMR(x) ((x) & 0x20) + +#define FW_PS_STATE_S0 (FW_PS_DPS) +#define FW_PS_STATE_S1 (FW_PS_LCLK) +#define FW_PS_STATE_S2 (FW_PS_RF_OFF) +#define FW_PS_STATE_S3 (FW_PS_ALL_ON) +#define FW_PS_STATE_S4 ((FW_PS_ST_ACTIVE) | (FW_PS_ALL_ON)) + /* ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE))*/ +#define FW_PS_STATE_ALL_ON_8821AE (FW_PS_CLOCK_ON) + /* (FW_PS_RF_ON)*/ +#define FW_PS_STATE_RF_ON_8821AE (FW_PS_CLOCK_ON) + /* 0x0*/ +#define FW_PS_STATE_RF_OFF_8821AE (FW_PS_CLOCK_ON) + /* (FW_PS_STATE_RF_OFF)*/ +#define FW_PS_STATE_RF_OFF_LOW_PWR_8821AE (FW_PS_CLOCK_OFF) + +#define FW_PS_STATE_ALL_ON_92C (FW_PS_STATE_S4) +#define FW_PS_STATE_RF_ON_92C (FW_PS_STATE_S3) +#define FW_PS_STATE_RF_OFF_92C (FW_PS_STATE_S2) +#define FW_PS_STATE_RF_OFF_LOW_PWR_92C (FW_PS_STATE_S1) + +/* For 8821AE H2C PwrMode Cmd ID 5.*/ +#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) +#define FW_PWR_STATE_RF_OFF 0 + +#define FW_PS_IS_ACK(x) ((x) & FW_PS_ACK) +#define FW_PS_IS_CLK_ON(x) ((x) & (FW_PS_RF_OFF | FW_PS_ALL_ON)) +#define FW_PS_IS_RF_ON(x) ((x) & (FW_PS_ALL_ON)) +#define FW_PS_IS_ACTIVE(x) ((x) & (FW_PS_ST_ACTIVE)) +#define FW_PS_IS_CPWM_INT(x) ((x) & 0x40) + +#define FW_CLR_PS_STATE(x) ((x) = ((x) & (0xF0))) + +#define IS_IN_LOW_POWER_STATE_8821AE(__state) \ + (FW_PS_STATE(__state) == FW_PS_CLOCK_OFF) + +#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) +#define FW_PWR_STATE_RF_OFF 0 + +enum rtl8812_c2h_evt { + C2H_8812_DBG = 0, + C2H_8812_LB = 1, + C2H_8812_TXBF = 2, + C2H_8812_TX_REPORT = 3, + C2H_8812_BT_INFO = 9, + C2H_8812_BT_MP = 11, + C2H_8812_RA_RPT = 12, + + C2H_8812_FW_SWCHNL = 0x10, + C2H_8812_IQK_FINISH = 0x11, + MAX_8812_C2HEVENT +}; + +enum rtl8821a_h2c_cmd { + H2C_8821AE_RSVDPAGE = 0, + H2C_8821AE_MSRRPT = 1, + H2C_8821AE_SCAN = 2, + H2C_8821AE_KEEP_ALIVE_CTRL = 3, + H2C_8821AE_DISCONNECT_DECISION = 4, + H2C_8821AE_INIT_OFFLOAD = 6, + H2C_8821AE_AP_OFFLOAD = 8, + H2C_8821AE_BCN_RSVDPAGE = 9, + H2C_8821AE_PROBERSP_RSVDPAGE = 10, + + H2C_8821AE_SETPWRMODE = 0x20, + H2C_8821AE_PS_TUNING_PARA = 0x21, + H2C_8821AE_PS_TUNING_PARA2 = 0x22, + H2C_8821AE_PS_LPS_PARA = 0x23, + H2C_8821AE_P2P_PS_OFFLOAD = 024, + + H2C_8821AE_WO_WLAN = 0x80, + H2C_8821AE_REMOTE_WAKE_CTRL = 0x81, + H2C_8821AE_AOAC_GLOBAL_INFO = 0x82, + H2C_8821AE_AOAC_RSVDPAGE = 0x83, + + H2C_RSSI_21AE_REPORT = 0x42, + H2C_8821AE_RA_MASK = 0x40, + H2C_8821AE_SELECTIVE_SUSPEND_ROF_CMD, + H2C_8821AE_P2P_PS_MODE, + H2C_8821AE_PSD_RESULT, + /*Not defined CTW CMD for P2P yet*/ + H2C_8821AE_P2P_PS_CTW_CMD, + MAX_8821AE_H2CCMD +}; + +#define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) + +#define SET_8812_H2CCMD_WOWLAN_FUNC_ENABLE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) +#define SET_8812_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) +#define SET_8812_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value) +#define SET_8812_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value) +#define SET_8812_H2CCMD_WOWLAN_ALL_PKT_DROP(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 4, 1, __value) +#define SET_8812_H2CCMD_WOWLAN_GPIO_ACTIVE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 5, 1, __value) +#define SET_8812_H2CCMD_WOWLAN_REKEY_WAKE_UP(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 6, 1, __value) +#define SET_8812_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 7, 1, __value) +#define SET_8812_H2CCMD_WOWLAN_GPIONUM(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd) + 1, 0, 8, __value) +#define SET_8812_H2CCMD_WOWLAN_GPIO_DURATION(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd) + 2, 0, 8, __value) + +#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_RLBM(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 4, __value) +#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 4, 4, __value) +#define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) +#define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) +#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value) +#define GET_8821AE_H2CCMD_PWRMODE_PARM_MODE(__cmd) \ + LE_BITS_TO_1BYTE(__cmd, 0, 8) + +#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(__ph2ccmd, __val) \ + SET_BITS_TO_LE_1BYTE((__ph2ccmd)+3, 0, 8, __val) + +/* _MEDIA_STATUS_RPT_PARM_CMD1 */ +#define SET_H2CCMD_MSRRPT_PARM_OPMODE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) +#define SET_H2CCMD_MSRRPT_PARM_MACID_IND(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) +#define SET_H2CCMD_MSRRPT_PARM_MACID(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd+1, 0, 8, __value) +#define SET_H2CCMD_MSRRPT_PARM_MACID_END(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd+2, 0, 8, __value) + +/* AP_OFFLOAD */ +#define SET_H2CCMD_AP_OFFLOAD_ON(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value) +#define SET_H2CCMD_AP_OFFLOAD_HIDDEN(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) +#define SET_H2CCMD_AP_OFFLOAD_DENYANY(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) +#define SET_H2CCMD_AP_OFFLOAD_WAKEUP_EVT_RPT(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) + +/* Keep Alive Control*/ +#define SET_8812_H2CCMD_KEEP_ALIVE_ENABLE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) +#define SET_8812_H2CCMD_KEEP_ALIVE_ACCPEPT_USER_DEFINED(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) +#define SET_8812_H2CCMD_KEEP_ALIVE_PERIOD(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) + +/*REMOTE_WAKE_CTRL */ +#define SET_8812_H2CCMD_REMOTE_WAKECTRL_ENABLE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) +#define SET_8812_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(__cmd, __value)\ + SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) +#define SET_8812_H2CCMD_REMOTE_WAKE_CTRL_NDP_OFFLOAD_EN(__cmd, __value)\ + SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value) +#define SET_8812_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(__cmd, __value)\ + SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value) +#define SET_8812_H2CCMD_REMOTE_WAKE_CTRL_REALWOWV2_EN(__cmd, __value)\ + SET_BITS_TO_LE_1BYTE(__cmd, 6, 1, __value) + +/* GTK_OFFLOAD */ +#define SET_8812_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(__cmd, __value)\ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value) +#define SET_8812_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) + +/* AOAC_RSVDPAGE_LOC */ +#define SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd), 0, 8, __value) +#define SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) +#define SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(__cmd, __value)\ + SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) +#define SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) +#define SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value) +#define SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE((__cmd)+5, 0, 8, __value) + +/* Disconnect_Decision_Control */ +#define SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_ENABLE(__cmd, __value) \ + SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) +#define SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_USER_SETTING(__cmd, __value)\ + SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) +#define SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_CHECK_PERIOD(__cmd, __value)\ + SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) /* unit: beacon period */ +#define SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_TRYPKT_NUM(__cmd, __value)\ + SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) + +int rtl8821ae_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw); +#if (USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN == 1) +void rtl8821ae_set_fw_related_for_wowlan(struct ieee80211_hw *hw, + bool used_wowlan_fw); + +#endif +void rtl8821ae_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *cmdbuffer); +void rtl8821ae_firmware_selfreset(struct ieee80211_hw *hw); +void rtl8821ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); +void rtl8821ae_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, + u8 mstatus); +void rtl8821ae_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, + u8 ap_offload_enable); +void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, + bool b_dl_finished, bool dl_whole_packet); +void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, + bool b_dl_finished, bool dl_whole_packet); +void rtl8821ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, + u8 p2p_ps_state); +void rtl8821ae_set_fw_wowlan_mode(struct ieee80211_hw *hw, bool func_en); +void rtl8821ae_set_fw_remote_wake_ctrl_cmd(struct ieee80211_hw *hw, + u8 enable); +void rtl8821ae_set_fw_keep_alive_cmd(struct ieee80211_hw *hw, bool func_en); +void rtl8821ae_set_fw_disconnect_decision_ctrl_cmd(struct ieee80211_hw *hw, + bool enabled); +void rtl8821ae_set_fw_global_info_cmd(struct ieee80211_hw *hw); +void rtl8821ae_c2h_packet_handler(struct ieee80211_hw *hw, + u8 *buffer, u8 length); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c new file mode 100644 index 000000000000..b7f18e2155eb --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c @@ -0,0 +1,4199 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../regd.h" +#include "../cam.h" +#include "../ps.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "led.h" +#include "hw.h" +#include "../pwrseqcmd.h" +#include "pwrseq.h" +#include "../btcoexist/rtl_btc.h" + +#define LLT_CONFIG 5 + +static void _rtl8821ae_return_beacon_queue_skb(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; + unsigned long flags; + + spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); + while (skb_queue_len(&ring->queue)) { + struct rtl_tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb = __skb_dequeue(&ring->queue); + + pci_unmap_single(rtlpci->pdev, + rtlpriv->cfg->ops->get_desc( + (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), + skb->len, PCI_DMA_TODEVICE); + kfree_skb(skb); + ring->idx = (ring->idx + 1) % ring->entries; + } + spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); +} + +static void _rtl8821ae_set_bcn_ctrl_reg(struct ieee80211_hw *hw, + u8 set_bits, u8 clear_bits) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpci->reg_bcn_ctrl_val |= set_bits; + rtlpci->reg_bcn_ctrl_val &= ~clear_bits; + + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); +} + +void _rtl8821ae_stop_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +void _rtl8821ae_resume_tx_beacon(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp1byte; + + tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); + tmp1byte |= BIT(0); + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl8821ae_enable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(1)); +} + +static void _rtl8821ae_disable_bcn_sub_func(struct ieee80211_hw *hw) +{ + _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(1), 0); +} + +static void _rtl8821ae_set_fw_clock_on(struct ieee80211_hw *hw, + u8 rpwm_val, bool b_need_turn_off_ckk) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool b_support_remote_wake_up; + u32 count = 0, isr_regaddr, content; + bool b_schedule_timer = b_need_turn_off_ckk; + + rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, + (u8 *)(&b_support_remote_wake_up)); + + if (!rtlhal->fw_ready) + return; + if (!rtlpriv->psc.fw_current_inpsmode) + return; + + while (1) { + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + if (rtlhal->fw_clk_change_in_progress) { + while (rtlhal->fw_clk_change_in_progress) { + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + count++; + udelay(100); + if (count > 1000) + goto change_done; + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + } + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + } else { + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + goto change_done; + } + } +change_done: + if (IS_IN_LOW_POWER_STATE_8821AE(rtlhal->fw_ps_state)) { + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + if (FW_PS_IS_ACK(rpwm_val)) { + isr_regaddr = REG_HISR; + content = rtl_read_dword(rtlpriv, isr_regaddr); + while (!(content & IMR_CPWM) && (count < 500)) { + udelay(50); + count++; + content = rtl_read_dword(rtlpriv, isr_regaddr); + } + + if (content & IMR_CPWM) { + rtl_write_word(rtlpriv, isr_regaddr, 0x0100); + rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_8821AE; + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Receive CPWM INT!!! Set rtlhal->FwPSState = %X\n", + rtlhal->fw_ps_state); + } + } + + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + if (b_schedule_timer) + mod_timer(&rtlpriv->works.fw_clockoff_timer, + jiffies + MSECS(10)); + } else { + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + } +} + +static void _rtl8821ae_set_fw_clock_off(struct ieee80211_hw *hw, + u8 rpwm_val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring; + enum rf_pwrstate rtstate; + bool b_schedule_timer = false; + u8 queue; + + if (!rtlhal->fw_ready) + return; + if (!rtlpriv->psc.fw_current_inpsmode) + return; + if (!rtlhal->allow_sw_to_change_hwclc) + return; + rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate)); + if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF) + return; + + for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) { + ring = &rtlpci->tx_ring[queue]; + if (skb_queue_len(&ring->queue)) { + b_schedule_timer = true; + break; + } + } + + if (b_schedule_timer) { + mod_timer(&rtlpriv->works.fw_clockoff_timer, + jiffies + MSECS(10)); + return; + } + + if (FW_PS_STATE(rtlhal->fw_ps_state) != + FW_PS_STATE_RF_OFF_LOW_PWR_8821AE) { + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + if (!rtlhal->fw_clk_change_in_progress) { + rtlhal->fw_clk_change_in_progress = true; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); + rtl_write_word(rtlpriv, REG_HISR, 0x0100); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + spin_lock_bh(&rtlpriv->locks.fw_ps_lock); + rtlhal->fw_clk_change_in_progress = false; + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + } else { + spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); + mod_timer(&rtlpriv->works.fw_clockoff_timer, + jiffies + MSECS(10)); + } + } +} + +static void _rtl8821ae_set_fw_ps_rf_on(struct ieee80211_hw *hw) +{ + u8 rpwm_val = 0; + + rpwm_val |= (FW_PS_STATE_RF_OFF_8821AE | FW_PS_ACK); + _rtl8821ae_set_fw_clock_on(hw, rpwm_val, true); +} + +static void _rtl8821ae_fwlps_leave(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool fw_current_inps = false; + u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE; + + if (ppsc->low_power_enable) { + rpwm_val = (FW_PS_STATE_ALL_ON_8821AE|FW_PS_ACK);/* RF on */ + _rtl8821ae_set_fw_clock_on(hw, rpwm_val, false); + rtlhal->allow_sw_to_change_hwclc = false; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&fw_pwrmode)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + } else { + rpwm_val = FW_PS_STATE_ALL_ON_8821AE; /* RF on */ + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&fw_pwrmode)); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + } +} + +static void _rtl8821ae_fwlps_enter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool fw_current_inps = true; + u8 rpwm_val; + + if (ppsc->low_power_enable) { + rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR_8821AE; /* RF off */ + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&ppsc->fwctrl_psmode)); + rtlhal->allow_sw_to_change_hwclc = true; + _rtl8821ae_set_fw_clock_off(hw, rpwm_val); + } else { + rpwm_val = FW_PS_STATE_RF_OFF_8821AE; /* RF off */ + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_FW_PSMODE_STATUS, + (u8 *)(&fw_current_inps)); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_PWRMODE, + (u8 *)(&ppsc->fwctrl_psmode)); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_SET_RPWM, + (u8 *)(&rpwm_val)); + } +} + +static void _rtl8821ae_download_rsvd_page(struct ieee80211_hw *hw, + bool dl_whole_packets) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 tmp_regcr, tmp_reg422, bcnvalid_reg; + u8 count = 0, dlbcn_count = 0; + bool send_beacon = false; + + tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr | BIT(0))); + + _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(3)); + _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(4), 0); + + tmp_reg422 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, + tmp_reg422 & (~BIT(6))); + if (tmp_reg422 & BIT(6)) + send_beacon = true; + + do { + bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); + rtl_write_byte(rtlpriv, REG_TDECTRL + 2, + (bcnvalid_reg | BIT(0))); + _rtl8821ae_return_beacon_queue_skb(hw); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtl8812ae_set_fw_rsvdpagepkt(hw, false, + dl_whole_packets); + else + rtl8821ae_set_fw_rsvdpagepkt(hw, false, + dl_whole_packets); + + bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); + count = 0; + while (!(bcnvalid_reg & BIT(0)) && count < 20) { + count++; + udelay(10); + bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); + } + dlbcn_count++; + } while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5); + + if (!(bcnvalid_reg & BIT(0))) + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Download RSVD page failed!\n"); + if (bcnvalid_reg & BIT(0) && rtlhal->enter_pnp_sleep) { + rtl_write_byte(rtlpriv, REG_TDECTRL + 2, bcnvalid_reg | BIT(0)); + _rtl8821ae_return_beacon_queue_skb(hw); + if (send_beacon) { + dlbcn_count = 0; + do { + rtl_write_byte(rtlpriv, REG_TDECTRL + 2, + bcnvalid_reg | BIT(0)); + + _rtl8821ae_return_beacon_queue_skb(hw); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtl8812ae_set_fw_rsvdpagepkt(hw, true, + false); + else + rtl8821ae_set_fw_rsvdpagepkt(hw, true, + false); + + /* check rsvd page download OK. */ + bcnvalid_reg = rtl_read_byte(rtlpriv, + REG_TDECTRL + 2); + count = 0; + while (!(bcnvalid_reg & BIT(0)) && count < 20) { + count++; + udelay(10); + bcnvalid_reg = + rtl_read_byte(rtlpriv, + REG_TDECTRL + 2); + } + dlbcn_count++; + } while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5); + + if (!(bcnvalid_reg & BIT(0))) + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "2 Download RSVD page failed!\n"); + } + } + + if (bcnvalid_reg & BIT(0)) + rtl_write_byte(rtlpriv, REG_TDECTRL + 2, BIT(0)); + + _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(3), 0); + _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(4)); + + if (send_beacon) + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422); + + if (!rtlhal->enter_pnp_sleep) { + tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr & ~(BIT(0)))); + } +} + +void rtl8821ae_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + + switch (variable) { + case HW_VAR_ETHER_ADDR: + *((u32 *)(val)) = rtl_read_dword(rtlpriv, REG_MACID); + *((u16 *)(val+4)) = rtl_read_word(rtlpriv, REG_MACID + 4); + break; + case HW_VAR_BSSID: + *((u32 *)(val)) = rtl_read_dword(rtlpriv, REG_BSSID); + *((u16 *)(val+4)) = rtl_read_word(rtlpriv, REG_BSSID+4); + break; + case HW_VAR_MEDIA_STATUS: + val[0] = rtl_read_byte(rtlpriv, MSR) & 0x3; + break; + case HW_VAR_SLOT_TIME: + *((u8 *)(val)) = mac->slot_time; + break; + case HW_VAR_BEACON_INTERVAL: + *((u16 *)(val)) = rtl_read_word(rtlpriv, REG_BCN_INTERVAL); + break; + case HW_VAR_ATIM_WINDOW: + *((u16 *)(val)) = rtl_read_word(rtlpriv, REG_ATIMWND); + break; + case HW_VAR_RCR: + *((u32 *)(val)) = rtlpci->receive_config; + break; + case HW_VAR_RF_STATE: + *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; + break; + case HW_VAR_FWLPS_RF_ON:{ + enum rf_pwrstate rfstate; + u32 val_rcr; + + rtlpriv->cfg->ops->get_hw_reg(hw, + HW_VAR_RF_STATE, + (u8 *)(&rfstate)); + if (rfstate == ERFOFF) { + *((bool *)(val)) = true; + } else { + val_rcr = rtl_read_dword(rtlpriv, REG_RCR); + val_rcr &= 0x00070000; + if (val_rcr) + *((bool *)(val)) = false; + else + *((bool *)(val)) = true; + } + break; } + case HW_VAR_FW_PSMODE_STATUS: + *((bool *)(val)) = ppsc->fw_current_inpsmode; + break; + case HW_VAR_CORRECT_TSF:{ + u64 tsf; + u32 *ptsf_low = (u32 *)&tsf; + u32 *ptsf_high = ((u32 *)&tsf) + 1; + + *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); + *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); + + *((u64 *)(val)) = tsf; + + break; } + case HAL_DEF_WOWLAN: + if (ppsc->wo_wlan_mode) + *((bool *)(val)) = true; + else + *((bool *)(val)) = false; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process %x\n", variable); + break; + } +} + +void rtl8821ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 idx; + + switch (variable) { + case HW_VAR_ETHER_ADDR:{ + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_MACID + idx), + val[idx]); + } + break; + } + case HW_VAR_BASIC_RATE:{ + u16 b_rate_cfg = ((u16 *)val)[0]; + b_rate_cfg = b_rate_cfg & 0x15f; + rtl_write_word(rtlpriv, REG_RRSR, b_rate_cfg); + break; + } + case HW_VAR_BSSID:{ + for (idx = 0; idx < ETH_ALEN; idx++) { + rtl_write_byte(rtlpriv, (REG_BSSID + idx), + val[idx]); + } + break; + } + case HW_VAR_SIFS: + rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); + rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[0]); + + rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); + rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); + + rtl_write_byte(rtlpriv, REG_RESP_SIFS_OFDM + 1, val[0]); + rtl_write_byte(rtlpriv, REG_RESP_SIFS_OFDM, val[0]); + break; + case HW_VAR_R2T_SIFS: + rtl_write_byte(rtlpriv, REG_RESP_SIFS_OFDM + 1, val[0]); + break; + case HW_VAR_SLOT_TIME:{ + u8 e_aci; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "HW_VAR_SLOT_TIME %x\n", val[0]); + + rtl_write_byte(rtlpriv, REG_SLOT, val[0]); + + for (e_aci = 0; e_aci < AC_MAX; e_aci++) { + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_AC_PARAM, + (u8 *)(&e_aci)); + } + break; } + case HW_VAR_ACK_PREAMBLE:{ + u8 reg_tmp; + u8 short_preamble = (bool)(*(u8 *)val); + + reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL+2); + if (short_preamble) { + reg_tmp |= BIT(1); + rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, + reg_tmp); + } else { + reg_tmp &= (~BIT(1)); + rtl_write_byte(rtlpriv, + REG_TRXPTCL_CTL + 2, + reg_tmp); + } + break; } + case HW_VAR_WPA_CONFIG: + rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); + break; + case HW_VAR_AMPDU_MIN_SPACE:{ + u8 min_spacing_to_set; + u8 sec_min_space; + + min_spacing_to_set = *((u8 *)val); + if (min_spacing_to_set <= 7) { + sec_min_space = 0; + + if (min_spacing_to_set < sec_min_space) + min_spacing_to_set = sec_min_space; + + mac->min_space_cfg = ((mac->min_space_cfg & + 0xf8) | + min_spacing_to_set); + + *val = min_spacing_to_set; + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", + mac->min_space_cfg); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + } + break; } + case HW_VAR_SHORTGI_DENSITY:{ + u8 density_to_set; + + density_to_set = *((u8 *)val); + mac->min_space_cfg |= (density_to_set << 3); + + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "Set HW_VAR_SHORTGI_DENSITY: %#x\n", + mac->min_space_cfg); + + rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, + mac->min_space_cfg); + + break; } + case HW_VAR_AMPDU_FACTOR:{ + u32 ampdu_len = (*((u8 *)val)); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + if (ampdu_len < VHT_AGG_SIZE_128K) + ampdu_len = + (0x2000 << (*((u8 *)val))) - 1; + else + ampdu_len = 0x1ffff; + } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + if (ampdu_len < HT_AGG_SIZE_64K) + ampdu_len = + (0x2000 << (*((u8 *)val))) - 1; + else + ampdu_len = 0xffff; + } + ampdu_len |= BIT(31); + + rtl_write_dword(rtlpriv, + REG_AMPDU_MAX_LENGTH_8812, ampdu_len); + break; } + case HW_VAR_AC_PARAM:{ + u8 e_aci = *((u8 *)val); + + rtl8821ae_dm_init_edca_turbo(hw); + if (rtlpci->acm_method != EACMWAY2_SW) + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_ACM_CTRL, + (u8 *)(&e_aci)); + break; } + case HW_VAR_ACM_CTRL:{ + u8 e_aci = *((u8 *)val); + union aci_aifsn *p_aci_aifsn = + (union aci_aifsn *)(&mac->ac[0].aifs); + u8 acm = p_aci_aifsn->f.acm; + u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); + + acm_ctrl = + acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); + + if (acm) { + switch (e_aci) { + case AC0_BE: + acm_ctrl |= ACMHW_BEQEN; + break; + case AC2_VI: + acm_ctrl |= ACMHW_VIQEN; + break; + case AC3_VO: + acm_ctrl |= ACMHW_VOQEN; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", + acm); + break; + } + } else { + switch (e_aci) { + case AC0_BE: + acm_ctrl &= (~ACMHW_BEQEN); + break; + case AC2_VI: + acm_ctrl &= (~ACMHW_VIQEN); + break; + case AC3_VO: + acm_ctrl &= (~ACMHW_VOQEN); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + } + + RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, + "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", + acm_ctrl); + rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); + break; } + case HW_VAR_RCR: + rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); + rtlpci->receive_config = ((u32 *)(val))[0]; + break; + case HW_VAR_RETRY_LIMIT:{ + u8 retry_limit = ((u8 *)(val))[0]; + + rtl_write_word(rtlpriv, REG_RL, + retry_limit << RETRY_LIMIT_SHORT_SHIFT | + retry_limit << RETRY_LIMIT_LONG_SHIFT); + break; } + case HW_VAR_DUAL_TSF_RST: + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); + break; + case HW_VAR_EFUSE_BYTES: + rtlefuse->efuse_usedbytes = *((u16 *)val); + break; + case HW_VAR_EFUSE_USAGE: + rtlefuse->efuse_usedpercentage = *((u8 *)val); + break; + case HW_VAR_IO_CMD: + rtl8821ae_phy_set_io_cmd(hw, (*(enum io_type *)val)); + break; + case HW_VAR_SET_RPWM:{ + u8 rpwm_val; + + rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); + udelay(1); + + if (rpwm_val & BIT(7)) { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, + (*(u8 *)val)); + } else { + rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, + ((*(u8 *)val) | BIT(7))); + } + + break; } + case HW_VAR_H2C_FW_PWRMODE: + rtl8821ae_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); + break; + case HW_VAR_FW_PSMODE_STATUS: + ppsc->fw_current_inpsmode = *((bool *)val); + break; + case HW_VAR_INIT_RTS_RATE: + break; + case HW_VAR_RESUME_CLK_ON: + _rtl8821ae_set_fw_ps_rf_on(hw); + break; + case HW_VAR_FW_LPS_ACTION:{ + bool b_enter_fwlps = *((bool *)val); + + if (b_enter_fwlps) + _rtl8821ae_fwlps_enter(hw); + else + _rtl8821ae_fwlps_leave(hw); + break; } + case HW_VAR_H2C_FW_JOINBSSRPT:{ + u8 mstatus = (*(u8 *)val); + + if (mstatus == RT_MEDIA_CONNECT) { + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, + NULL); + _rtl8821ae_download_rsvd_page(hw, false); + } + rtl8821ae_set_fw_media_status_rpt_cmd(hw, mstatus); + + break; } + case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: + rtl8821ae_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); + break; + case HW_VAR_AID:{ + u16 u2btmp; + u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); + u2btmp &= 0xC000; + rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | + mac->assoc_id)); + break; } + case HW_VAR_CORRECT_TSF:{ + u8 btype_ibss = ((u8 *)(val))[0]; + + if (btype_ibss) + _rtl8821ae_stop_tx_beacon(hw); + + _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(3)); + + rtl_write_dword(rtlpriv, REG_TSFTR, + (u32)(mac->tsf & 0xffffffff)); + rtl_write_dword(rtlpriv, REG_TSFTR + 4, + (u32)((mac->tsf >> 32) & 0xffffffff)); + + _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(3), 0); + + if (btype_ibss) + _rtl8821ae_resume_tx_beacon(hw); + break; } + case HW_VAR_NAV_UPPER: { + u32 us_nav_upper = ((u32)*val); + + if (us_nav_upper > HAL_92C_NAV_UPPER_UNIT * 0xFF) { + RT_TRACE(rtlpriv, COMP_INIT , DBG_WARNING, + "The setting value (0x%08X us) of NAV_UPPER is larger than (%d * 0xFF)!!!\n", + us_nav_upper, HAL_92C_NAV_UPPER_UNIT); + break; + } + rtl_write_byte(rtlpriv, REG_NAV_UPPER, + ((u8)((us_nav_upper + + HAL_92C_NAV_UPPER_UNIT - 1) / + HAL_92C_NAV_UPPER_UNIT))); + break; } + case HW_VAR_KEEP_ALIVE: { + u8 array[2]; + array[0] = 0xff; + array[1] = *((u8 *)val); + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_KEEP_ALIVE_CTRL, 2, + array); + break; } + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process %x\n", variable); + break; + } +} + +static bool _rtl8821ae_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + bool status = true; + long count = 0; + u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | + _LLT_OP(_LLT_WRITE_ACCESS); + + rtl_write_dword(rtlpriv, REG_LLT_INIT, value); + + do { + value = rtl_read_dword(rtlpriv, REG_LLT_INIT); + if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) + break; + + if (count > POLLING_LLT_THRESHOLD) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to polling write LLT done at address %d!\n", + address); + status = false; + break; + } + } while (++count); + + return status; +} + +static bool _rtl8821ae_llt_table_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + unsigned short i; + u8 txpktbuf_bndy; + u32 rqpn; + u8 maxpage; + bool status; + + maxpage = 255; + txpktbuf_bndy = 0xF8; + rqpn = 0x80e70808; + if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE) { + txpktbuf_bndy = 0xFA; + rqpn = 0x80e90808; + } + + rtl_write_byte(rtlpriv, REG_TRXFF_BNDY, txpktbuf_bndy); + rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, MAX_RX_DMA_BUFFER_SIZE - 1); + + rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); + rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); + + rtl_write_byte(rtlpriv, REG_PBP, 0x31); + rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); + + for (i = 0; i < (txpktbuf_bndy - 1); i++) { + status = _rtl8821ae_llt_write(hw, i, i + 1); + if (!status) + return status; + } + + status = _rtl8821ae_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); + if (!status) + return status; + + for (i = txpktbuf_bndy; i < maxpage; i++) { + status = _rtl8821ae_llt_write(hw, i, (i + 1)); + if (!status) + return status; + } + + status = _rtl8821ae_llt_write(hw, maxpage, txpktbuf_bndy); + if (!status) + return status; + + rtl_write_dword(rtlpriv, REG_RQPN, rqpn); + + rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x00); + + return true; +} + +static void _rtl8821ae_gen_refresh_led_state(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_led *pled0 = &pcipriv->ledctl.sw_led0; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + if (rtlpriv->rtlhal.up_first_time) + return; + + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtl8812ae_sw_led_on(hw, pled0); + else + rtl8821ae_sw_led_on(hw, pled0); + else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtl8812ae_sw_led_on(hw, pled0); + else + rtl8821ae_sw_led_on(hw, pled0); + else + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtl8812ae_sw_led_off(hw, pled0); + else + rtl8821ae_sw_led_off(hw, pled0); +} + +static bool _rtl8821ae_init_mac(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + u8 bytetmp = 0; + u16 wordtmp = 0; + bool mac_func_enable = rtlhal->mac_func_enable; + + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); + + /*Auto Power Down to CHIP-off State*/ + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7)); + rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + /* HW Power on sequence*/ + if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, + PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, + RTL8812_NIC_ENABLE_FLOW)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "init 8812 MAC Fail as power on failure\n"); + return false; + } + } else { + /* HW Power on sequence */ + if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_A_MSK, + PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, + RTL8821A_NIC_ENABLE_FLOW)){ + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "init 8821 MAC Fail as power on failure\n"); + return false; + } + } + + bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4); + rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp); + + bytetmp = rtl_read_byte(rtlpriv, REG_CR); + bytetmp = 0xff; + rtl_write_byte(rtlpriv, REG_CR, bytetmp); + mdelay(2); + + bytetmp = 0xff; + rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, bytetmp); + mdelay(2); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CFG + 3); + if (bytetmp & BIT(0)) { + bytetmp = rtl_read_byte(rtlpriv, 0x7c); + bytetmp |= BIT(6); + rtl_write_byte(rtlpriv, 0x7c, bytetmp); + } + } + + bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG + 1); + bytetmp &= ~BIT(4); + rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG + 1, bytetmp); + + rtl_write_word(rtlpriv, REG_CR, 0x2ff); + + if (!mac_func_enable) { + if (!_rtl8821ae_llt_table_init(hw)) + return false; + } + + rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); + rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff); + + /* Enable FW Beamformer Interrupt */ + bytetmp = rtl_read_byte(rtlpriv, REG_FWIMR + 3); + rtl_write_byte(rtlpriv, REG_FWIMR + 3, bytetmp | BIT(6)); + + wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); + wordtmp &= 0xf; + wordtmp |= 0xF5B1; + rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); + + rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xFFFF); + /*low address*/ + rtl_write_dword(rtlpriv, REG_BCNQ_DESA, + rtlpci->tx_ring[BEACON_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_MGQ_DESA, + rtlpci->tx_ring[MGNT_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VOQ_DESA, + rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VIQ_DESA, + rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BEQ_DESA, + rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BKQ_DESA, + rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_HQ_DESA, + rtlpci->tx_ring[HIGH_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_RX_DESA, + rtlpci->rx_ring[RX_MPDU_QUEUE].dma & DMA_BIT_MASK(32)); + + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x77); + + rtl_write_dword(rtlpriv, REG_INT_MIG, 0); + + rtl_write_dword(rtlpriv, REG_MCUTST_1, 0); + + rtl_write_byte(rtlpriv, REG_SECONDARY_CCA_CTRL, 0x3); + _rtl8821ae_gen_refresh_led_state(hw); + + return true; +} + +static void _rtl8821ae_hw_configure(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 reg_rrsr; + + reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + + rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr); + /* ARFB table 9 for 11ac 5G 2SS */ + rtl_write_dword(rtlpriv, REG_ARFR0 + 4, 0xfffff000); + /* ARFB table 10 for 11ac 5G 1SS */ + rtl_write_dword(rtlpriv, REG_ARFR1 + 4, 0x003ff000); + /* ARFB table 11 for 11ac 24G 1SS */ + rtl_write_dword(rtlpriv, REG_ARFR2, 0x00000015); + rtl_write_dword(rtlpriv, REG_ARFR2 + 4, 0x003ff000); + /* ARFB table 12 for 11ac 24G 1SS */ + rtl_write_dword(rtlpriv, REG_ARFR3, 0x00000015); + rtl_write_dword(rtlpriv, REG_ARFR3 + 4, 0xffcff000); + /* 0x420[7] = 0 , enable retry AMPDU in new AMPD not singal MPDU. */ + rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F00); + rtl_write_byte(rtlpriv, REG_AMPDU_MAX_TIME, 0x70); + + /*Set retry limit*/ + rtl_write_word(rtlpriv, REG_RL, 0x0707); + + /* Set Data / Response auto rate fallack retry count*/ + rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); + rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); + rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); + + rtlpci->reg_bcn_ctrl_val = 0x1d; + rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); + + /* TBTT prohibit hold time. Suggested by designer TimChen. */ + rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); + + /* AGGR_BK_TIME Reg51A 0x16 */ + rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040); + + /*For Rx TP. Suggested by SD1 Richard. Added by tynli. 2010.04.12.*/ + rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); + + rtl_write_byte(rtlpriv, REG_HT_SINGLE_AMPDU, 0x80); + rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20); + rtl_write_word(rtlpriv, REG_MAX_AGGR_NUM, 0x1F1F); +} + +static u16 _rtl8821ae_mdio_read(struct rtl_priv *rtlpriv, u8 addr) +{ + u16 ret = 0; + u8 tmp = 0, count = 0; + + rtl_write_byte(rtlpriv, REG_MDIO_CTL, addr | BIT(6)); + tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(6); + count = 0; + while (tmp && count < 20) { + udelay(10); + tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(6); + count++; + } + if (0 == tmp) + ret = rtl_read_word(rtlpriv, REG_MDIO_RDATA); + + return ret; +} + +static void _rtl8821ae_mdio_write(struct rtl_priv *rtlpriv, u8 addr, u16 data) +{ + u8 tmp = 0, count = 0; + + rtl_write_word(rtlpriv, REG_MDIO_WDATA, data); + rtl_write_byte(rtlpriv, REG_MDIO_CTL, addr | BIT(5)); + tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(5); + count = 0; + while (tmp && count < 20) { + udelay(10); + tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(5); + count++; + } +} + +static u8 _rtl8821ae_dbi_read(struct rtl_priv *rtlpriv, u16 addr) +{ + u16 read_addr = addr & 0xfffc; + u8 tmp = 0, count = 0, ret = 0; + + rtl_write_word(rtlpriv, REG_DBI_ADDR, read_addr); + rtl_write_byte(rtlpriv, REG_DBI_FLAG, 0x2); + tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); + count = 0; + while (tmp && count < 20) { + udelay(10); + tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); + count++; + } + if (0 == tmp) { + read_addr = REG_DBI_RDATA + addr % 4; + ret = rtl_read_word(rtlpriv, read_addr); + } + return ret; +} + +static void _rtl8821ae_dbi_write(struct rtl_priv *rtlpriv, u16 addr, u8 data) +{ + u8 tmp = 0, count = 0; + u16 wrtie_addr, remainder = addr % 4; + + wrtie_addr = REG_DBI_WDATA + remainder; + rtl_write_byte(rtlpriv, wrtie_addr, data); + + wrtie_addr = (addr & 0xfffc) | (BIT(0) << (remainder + 12)); + rtl_write_word(rtlpriv, REG_DBI_ADDR, wrtie_addr); + + rtl_write_byte(rtlpriv, REG_DBI_FLAG, 0x1); + + tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); + count = 0; + while (tmp && count < 20) { + udelay(10); + tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); + count++; + } +} + +static void _rtl8821ae_enable_aspm_back_door(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + if (_rtl8821ae_mdio_read(rtlpriv, 0x04) != 0x8544) + _rtl8821ae_mdio_write(rtlpriv, 0x04, 0x8544); + + if (_rtl8821ae_mdio_read(rtlpriv, 0x0b) != 0x0070) + _rtl8821ae_mdio_write(rtlpriv, 0x0b, 0x0070); + } + + tmp = _rtl8821ae_dbi_read(rtlpriv, 0x70f); + _rtl8821ae_dbi_write(rtlpriv, 0x70f, tmp | BIT(7)); + + tmp = _rtl8821ae_dbi_read(rtlpriv, 0x719); + _rtl8821ae_dbi_write(rtlpriv, 0x719, tmp | BIT(3) | BIT(4)); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + tmp = _rtl8821ae_dbi_read(rtlpriv, 0x718); + _rtl8821ae_dbi_write(rtlpriv, 0x718, tmp|BIT(4)); + } +} + +void rtl8821ae_enable_hw_security_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 sec_reg_value; + u8 tmp; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", + rtlpriv->sec.pairwise_enc_algorithm, + rtlpriv->sec.group_enc_algorithm); + + if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "not open hw encryption\n"); + return; + } + + sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; + + if (rtlpriv->sec.use_defaultkey) { + sec_reg_value |= SCR_TXUSEDK; + sec_reg_value |= SCR_RXUSEDK; + } + + sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); + + tmp = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, tmp | BIT(1)); + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "The SECR-value %x\n", sec_reg_value); + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); +} + +/* Static MacID Mapping (cf. Used in MacIdDoStaticMapping) ---------- */ +#define MAC_ID_STATIC_FOR_DEFAULT_PORT 0 +#define MAC_ID_STATIC_FOR_BROADCAST_MULTICAST 1 +#define MAC_ID_STATIC_FOR_BT_CLIENT_START 2 +#define MAC_ID_STATIC_FOR_BT_CLIENT_END 3 +/* ----------------------------------------------------------- */ + +static void rtl8821ae_macid_initialize_mediastatus(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 media_rpt[4] = {RT_MEDIA_CONNECT, 1, + MAC_ID_STATIC_FOR_BROADCAST_MULTICAST, + MAC_ID_STATIC_FOR_BT_CLIENT_END}; + + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_H2C_FW_MEDIASTATUSRPT, media_rpt); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Initialize MacId media status: from %d to %d\n", + MAC_ID_STATIC_FOR_BROADCAST_MULTICAST, + MAC_ID_STATIC_FOR_BT_CLIENT_END); +} + +static bool _rtl8821ae_check_pcie_dma_hang(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp; + + /* write reg 0x350 Bit[26]=1. Enable debug port. */ + tmp = rtl_read_byte(rtlpriv, REG_DBI_CTRL + 3); + if (!(tmp & BIT(2))) { + rtl_write_byte(rtlpriv, REG_DBI_CTRL + 3, (tmp | BIT(2))); + mdelay(100); + } + + /* read reg 0x350 Bit[25] if 1 : RX hang */ + /* read reg 0x350 Bit[24] if 1 : TX hang */ + tmp = rtl_read_byte(rtlpriv, REG_DBI_CTRL + 3); + if ((tmp & BIT(0)) || (tmp & BIT(1))) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "CheckPcieDMAHang8821AE(): true! Reset PCIE DMA!\n"); + return true; + } else { + return false; + } +} + +static bool _rtl8821ae_reset_pcie_interface_dma(struct ieee80211_hw *hw, + bool mac_power_on, + bool in_watchdog) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp; + bool release_mac_rx_pause; + u8 backup_pcie_dma_pause; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); + + /* 1. Disable register write lock. 0x1c[1] = 0 */ + tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL); + tmp &= ~(BIT(1)); + rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp); + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + /* write 0xCC bit[2] = 1'b1 */ + tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); + tmp |= BIT(2); + rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); + } + + /* 2. Check and pause TRX DMA */ + /* write 0x284 bit[18] = 1'b1 */ + /* write 0x301 = 0xFF */ + tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + if (tmp & BIT(2)) { + /* Already pause before the function for another purpose. */ + release_mac_rx_pause = false; + } else { + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2))); + release_mac_rx_pause = true; + } + backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1); + if (backup_pcie_dma_pause != 0xFF) + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF); + + if (mac_power_on) { + /* 3. reset TRX function */ + /* write 0x100 = 0x00 */ + rtl_write_byte(rtlpriv, REG_CR, 0); + } + + /* 4. Reset PCIe DMA. 0x3[0] = 0 */ + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + tmp &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); + + /* 5. Enable PCIe DMA. 0x3[0] = 1 */ + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); + tmp |= BIT(0); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); + + if (mac_power_on) { + /* 6. enable TRX function */ + /* write 0x100 = 0xFF */ + rtl_write_byte(rtlpriv, REG_CR, 0xFF); + + /* We should init LLT & RQPN and + * prepare Tx/Rx descrptor address later + * because MAC function is reset.*/ + } + + /* 7. Restore PCIe autoload down bit */ + /* 8812AE does not has the defination. */ + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + /* write 0xF8 bit[17] = 1'b1 */ + tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2); + tmp |= BIT(1); + rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp); + } + + /* In MAC power on state, BB and RF maybe in ON state, + * if we release TRx DMA here. + * it will cause packets to be started to Tx/Rx, + * so we release Tx/Rx DMA later.*/ + if (!mac_power_on/* || in_watchdog*/) { + /* 8. release TRX DMA */ + /* write 0x284 bit[18] = 1'b0 */ + /* write 0x301 = 0x00 */ + if (release_mac_rx_pause) { + tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, + tmp & (~BIT(2))); + } + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, + backup_pcie_dma_pause); + } + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + /* 9. lock system register */ + /* write 0xCC bit[2] = 1'b0 */ + tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); + tmp &= ~(BIT(2)); + rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); + } + return true; +} + +static void _rtl8821ae_get_wakeup_reason(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); + u8 fw_reason = 0; + struct timeval ts; + + fw_reason = rtl_read_byte(rtlpriv, REG_MCUTST_WOWLAN); + + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "WOL Read 0x1c7 = %02X\n", + fw_reason); + + ppsc->wakeup_reason = 0; + + rtlhal->last_suspend_sec = ts.tv_sec; + + switch (fw_reason) { + case FW_WOW_V2_PTK_UPDATE_EVENT: + ppsc->wakeup_reason = WOL_REASON_PTK_UPDATE; + do_gettimeofday(&ts); + ppsc->last_wakeup_time = ts.tv_sec*1000 + ts.tv_usec/1000; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "It's a WOL PTK Key update event!\n"); + break; + case FW_WOW_V2_GTK_UPDATE_EVENT: + ppsc->wakeup_reason = WOL_REASON_GTK_UPDATE; + do_gettimeofday(&ts); + ppsc->last_wakeup_time = ts.tv_sec*1000 + ts.tv_usec/1000; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "It's a WOL GTK Key update event!\n"); + break; + case FW_WOW_V2_DISASSOC_EVENT: + ppsc->wakeup_reason = WOL_REASON_DISASSOC; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "It's a disassociation event!\n"); + break; + case FW_WOW_V2_DEAUTH_EVENT: + ppsc->wakeup_reason = WOL_REASON_DEAUTH; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "It's a deauth event!\n"); + break; + case FW_WOW_V2_FW_DISCONNECT_EVENT: + ppsc->wakeup_reason = WOL_REASON_AP_LOST; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "It's a Fw disconnect decision (AP lost) event!\n"); + break; + case FW_WOW_V2_MAGIC_PKT_EVENT: + ppsc->wakeup_reason = WOL_REASON_MAGIC_PKT; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "It's a magic packet event!\n"); + break; + case FW_WOW_V2_UNICAST_PKT_EVENT: + ppsc->wakeup_reason = WOL_REASON_UNICAST_PKT; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "It's an unicast packet event!\n"); + break; + case FW_WOW_V2_PATTERN_PKT_EVENT: + ppsc->wakeup_reason = WOL_REASON_PATTERN_PKT; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "It's a pattern match event!\n"); + break; + case FW_WOW_V2_RTD3_SSID_MATCH_EVENT: + ppsc->wakeup_reason = WOL_REASON_RTD3_SSID_MATCH; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "It's an RTD3 Ssid match event!\n"); + break; + case FW_WOW_V2_REALWOW_V2_WAKEUPPKT: + ppsc->wakeup_reason = WOL_REASON_REALWOW_V2_WAKEUPPKT; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "It's an RealWoW wake packet event!\n"); + break; + case FW_WOW_V2_REALWOW_V2_ACKLOST: + ppsc->wakeup_reason = WOL_REASON_REALWOW_V2_ACKLOST; + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "It's an RealWoW ack lost event!\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, + "WOL Read 0x1c7 = %02X, Unknown reason!\n", + fw_reason); + break; + } +} + +static void _rtl8821ae_init_trx_desc_hw_address(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*low address*/ + rtl_write_dword(rtlpriv, REG_BCNQ_DESA, + rtlpci->tx_ring[BEACON_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_MGQ_DESA, + rtlpci->tx_ring[MGNT_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VOQ_DESA, + rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_VIQ_DESA, + rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BEQ_DESA, + rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_BKQ_DESA, + rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_HQ_DESA, + rtlpci->tx_ring[HIGH_QUEUE].dma & DMA_BIT_MASK(32)); + rtl_write_dword(rtlpriv, REG_RX_DESA, + rtlpci->rx_ring[RX_MPDU_QUEUE].dma & DMA_BIT_MASK(32)); +} + +static bool _rtl8821ae_init_llt_table(struct ieee80211_hw *hw, u32 boundary) +{ + bool status = true; + u32 i; + u32 txpktbuf_bndy = boundary; + u32 last_entry_of_txpktbuf = LAST_ENTRY_OF_TX_PKT_BUFFER; + + for (i = 0 ; i < (txpktbuf_bndy - 1) ; i++) { + status = _rtl8821ae_llt_write(hw, i , i + 1); + if (!status) + return status; + } + + status = _rtl8821ae_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); + if (!status) + return status; + + for (i = txpktbuf_bndy ; i < last_entry_of_txpktbuf ; i++) { + status = _rtl8821ae_llt_write(hw, i, (i + 1)); + if (!status) + return status; + } + + status = _rtl8821ae_llt_write(hw, last_entry_of_txpktbuf, + txpktbuf_bndy); + if (!status) + return status; + + return status; +} + +static bool _rtl8821ae_dynamic_rqpn(struct ieee80211_hw *hw, u32 boundary, + u16 npq_rqpn_value, u32 rqpn_val) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 tmp; + bool ret = true; + u16 count = 0, tmp16; + bool support_remote_wakeup; + + rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, + (u8 *)(&support_remote_wakeup)); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "boundary=%#X, NPQ_RQPNValue=%#X, RQPNValue=%#X\n", + boundary, npq_rqpn_value, rqpn_val); + + /* stop PCIe DMA + * 1. 0x301[7:0] = 0xFE */ + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE); + + /* wait TXFF empty + * 2. polling till 0x41A[15:0]=0x07FF */ + tmp16 = rtl_read_word(rtlpriv, REG_TXPKT_EMPTY); + while ((tmp16 & 0x07FF) != 0x07FF) { + udelay(100); + tmp16 = rtl_read_word(rtlpriv, REG_TXPKT_EMPTY); + count++; + if ((count % 200) == 0) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Tx queue is not empty for 20ms!\n"); + } + if (count >= 1000) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Wait for Tx FIFO empty timeout!\n"); + break; + } + } + + /* TX pause + * 3. reg 0x522=0xFF */ + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); + + /* Wait TX State Machine OK + * 4. polling till reg 0x5FB~0x5F8 = 0x00000000 for 50ms */ + count = 0; + while (rtl_read_byte(rtlpriv, REG_SCH_TXCMD) != 0) { + udelay(100); + count++; + if (count >= 500) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Wait for TX State Machine ready timeout !!\n"); + break; + } + } + + /* stop RX DMA path + * 5. 0x284[18] = 1 + * 6. wait till 0x284[17] == 1 + * wait RX DMA idle */ + count = 0; + tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2))); + do { + tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + udelay(10); + count++; + } while (!(tmp & BIT(1)) && count < 100); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Wait until Rx DMA Idle. count=%d REG[0x286]=0x%x\n", + count, tmp); + + /* reset BB + * 7. 0x02 [0] = 0 */ + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); + tmp &= ~(BIT(0)); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, tmp); + + /* Reset TRX MAC + * 8. 0x100 = 0x00 + * Delay (1ms) */ + rtl_write_byte(rtlpriv, REG_CR, 0x00); + udelay(1000); + + /* Disable MAC Security Engine + * 9. 0x100 bit[9]=0 */ + tmp = rtl_read_byte(rtlpriv, REG_CR + 1); + tmp &= ~(BIT(1)); + rtl_write_byte(rtlpriv, REG_CR + 1, tmp); + + /* To avoid DD-Tim Circuit hang + * 10. 0x553 bit[5]=1 */ + tmp = rtl_read_byte(rtlpriv, REG_DUAL_TSF_RST); + rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (tmp | BIT(5))); + + /* Enable MAC Security Engine + * 11. 0x100 bit[9]=1 */ + tmp = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, (tmp | BIT(1))); + + /* Enable TRX MAC + * 12. 0x100 = 0xFF + * Delay (1ms) */ + rtl_write_byte(rtlpriv, REG_CR, 0xFF); + udelay(1000); + + /* Enable BB + * 13. 0x02 [0] = 1 */ + tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, (tmp | BIT(0))); + + /* beacon setting + * 14,15. set beacon head page (reg 0x209 and 0x424) */ + rtl_write_byte(rtlpriv, REG_TDECTRL + 1, (u8)boundary); + rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, (u8)boundary); + rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, (u8)boundary); + + /* 16. WMAC_LBK_BF_HD 0x45D[7:0] + * WMAC_LBK_BF_HD */ + rtl_write_byte(rtlpriv, REG_TXPKTBUF_WMAC_LBK_BF_HD, + (u8)boundary); + + rtl_write_word(rtlpriv, REG_TRXFF_BNDY, boundary); + + /* init LLT + * 17. init LLT */ + if (!_rtl8821ae_init_llt_table(hw, boundary)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, + "Failed to init LLT table!\n"); + return false; + } + + /* reallocate RQPN + * 18. reallocate RQPN and init LLT */ + rtl_write_word(rtlpriv, REG_RQPN_NPQ, npq_rqpn_value); + rtl_write_dword(rtlpriv, REG_RQPN, rqpn_val); + + /* release Tx pause + * 19. 0x522=0x00 */ + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); + + /* enable PCIE DMA + * 20. 0x301[7:0] = 0x00 + * 21. 0x284[18] = 0 */ + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x00); + tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp&~BIT(2))); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "End.\n"); + return ret; +} + +static void _rtl8821ae_simple_initialize_adapter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); + +#if (USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN == 1) + /* Re-download normal Fw. */ + rtl8821ae_set_fw_related_for_wowlan(hw, false); +#endif + + /* Re-Initialize LLT table. */ + if (rtlhal->re_init_llt_table) { + u32 rqpn = 0x80e70808; + u8 rqpn_npq = 0, boundary = 0xF8; + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + rqpn = 0x80e90808; + boundary = 0xFA; + } + if (_rtl8821ae_dynamic_rqpn(hw, boundary, rqpn_npq, rqpn)) + rtlhal->re_init_llt_table = false; + } + + ppsc->rfpwr_state = ERFON; +} + +static void _rtl8821ae_enable_l1off(struct ieee80211_hw *hw) +{ + u8 tmp = 0; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "--->\n"); + + tmp = _rtl8821ae_dbi_read(rtlpriv, 0x160); + if (!(tmp & (BIT(2) | BIT(3)))) { + RT_TRACE(rtlpriv, COMP_POWER | COMP_INIT, DBG_LOUD, + "0x160(%#x)return!!\n", tmp); + return; + } + + tmp = _rtl8821ae_mdio_read(rtlpriv, 0x1b); + _rtl8821ae_mdio_write(rtlpriv, 0x1b, (tmp | BIT(4))); + + tmp = _rtl8821ae_dbi_read(rtlpriv, 0x718); + _rtl8821ae_dbi_write(rtlpriv, 0x718, tmp | BIT(5)); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "<---\n"); +} + +static void _rtl8821ae_enable_ltr(struct ieee80211_hw *hw) +{ + u8 tmp = 0; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "--->\n"); + + /* Check 0x98[10] */ + tmp = _rtl8821ae_dbi_read(rtlpriv, 0x99); + if (!(tmp & BIT(2))) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "<---0x99(%#x) return!!\n", tmp); + return; + } + + /* LTR idle latency, 0x90 for 144us */ + rtl_write_dword(rtlpriv, 0x798, 0x88908890); + + /* LTR active latency, 0x3c for 60us */ + rtl_write_dword(rtlpriv, 0x79c, 0x883c883c); + + tmp = rtl_read_byte(rtlpriv, 0x7a4); + rtl_write_byte(rtlpriv, 0x7a4, (tmp | BIT(4))); + + tmp = rtl_read_byte(rtlpriv, 0x7a4); + rtl_write_byte(rtlpriv, 0x7a4, (tmp & (~BIT(0)))); + rtl_write_byte(rtlpriv, 0x7a4, (tmp | BIT(0))); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "<---\n"); +} + +static bool _rtl8821ae_wowlan_initialize_adapter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + bool init_finished = true; + u8 tmp = 0; + + /* Get Fw wake up reason. */ + _rtl8821ae_get_wakeup_reason(hw); + + /* Patch Pcie Rx DMA hang after S3/S4 several times. + * The root cause has not be found. */ + if (_rtl8821ae_check_pcie_dma_hang(hw)) + _rtl8821ae_reset_pcie_interface_dma(hw, true, false); + + /* Prepare Tx/Rx Desc Hw address. */ + _rtl8821ae_init_trx_desc_hw_address(hw); + + /* Release Pcie Interface Rx DMA to allow wake packet DMA. */ + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE); + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Enable PCIE Rx DMA.\n"); + + /* Check wake up event. + * We should check wake packet bit before disable wowlan by H2C or + * Fw will clear the bit. */ + tmp = rtl_read_byte(rtlpriv, REG_FTISR + 3); + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Read REG_FTISR 0x13f = %#X\n", tmp); + + /* Set the WoWLAN related function control disable. */ + rtl8821ae_set_fw_wowlan_mode(hw, false); + rtl8821ae_set_fw_remote_wake_ctrl_cmd(hw, 0); + + if (rtlhal->hw_rof_enable) { + tmp = rtl_read_byte(rtlpriv, REG_HSISR + 3); + if (tmp & BIT(1)) { + /* Clear GPIO9 ISR */ + rtl_write_byte(rtlpriv, REG_HSISR + 3, tmp | BIT(1)); + init_finished = false; + } else { + init_finished = true; + } + } + + if (init_finished) { + _rtl8821ae_simple_initialize_adapter(hw); + + /* Release Pcie Interface Tx DMA. */ + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x00); + /* Release Pcie RX DMA */ + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, 0x02); + + tmp = rtl_read_byte(rtlpriv, REG_CR + 1); + rtl_write_byte(rtlpriv, REG_CR + 1, (tmp & (~BIT(0)))); + + _rtl8821ae_enable_l1off(hw); + _rtl8821ae_enable_ltr(hw); + } + + return init_finished; +} + +static void _rtl8812ae_bb8812_config_1t(struct ieee80211_hw *hw) +{ + /* BB OFDM RX Path_A */ + rtl_set_bbreg(hw, 0x808, 0xff, 0x11); + /* BB OFDM TX Path_A */ + rtl_set_bbreg(hw, 0x80c, MASKLWORD, 0x1111); + /* BB CCK R/Rx Path_A */ + rtl_set_bbreg(hw, 0xa04, 0x0c000000, 0x0); + /* MCS support */ + rtl_set_bbreg(hw, 0x8bc, 0xc0000060, 0x4); + /* RF Path_B HSSI OFF */ + rtl_set_bbreg(hw, 0xe00, 0xf, 0x4); + /* RF Path_B Power Down */ + rtl_set_bbreg(hw, 0xe90, MASKDWORD, 0); + /* ADDA Path_B OFF */ + rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0); + rtl_set_bbreg(hw, 0xe64, MASKDWORD, 0); +} + +static void _rtl8821ae_poweroff_adapter(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 u1b_tmp; + + rtlhal->mac_func_enable = false; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + /* Combo (PCIe + USB) Card and PCIe-MF Card */ + /* 1. Run LPS WL RFOFF flow */ + /* RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "=====>CardDisableRTL8812E,RTL8821A_NIC_LPS_ENTER_FLOW\n"); + */ + rtl_hal_pwrseqcmdparsing(rtlpriv, + PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, RTL8821A_NIC_LPS_ENTER_FLOW); + } + /* 2. 0x1F[7:0] = 0 */ + /* turn off RF */ + /* rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); */ + if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && + rtlhal->fw_ready) { + rtl8821ae_firmware_selfreset(hw); + } + + /* Reset MCU. Suggested by Filen. */ + u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); + + /* g. MCUFWDL 0x80[1:0]=0 */ + /* reset MCU ready status */ + rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + /* HW card disable configuration. */ + rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, RTL8821A_NIC_DISABLE_FLOW); + } else { + /* HW card disable configuration. */ + rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, + PWR_INTF_PCI_MSK, RTL8812_NIC_DISABLE_FLOW); + } + + /* Reset MCU IO Wrapper */ + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); + u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); + rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, u1b_tmp | BIT(0)); + + /* 7. RSV_CTRL 0x1C[7:0] = 0x0E */ + /* lock ISO/CLK/Power control register */ + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); +} + +int rtl8821ae_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool rtstatus = true; + int err; + u8 tmp_u1b; + bool support_remote_wakeup; + u32 nav_upper = WIFI_NAV_UPPER_US; + + rtlhal->being_init_adapter = true; + rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, + (u8 *)(&support_remote_wakeup)); + rtlpriv->intf_ops->disable_aspm(hw); + + /*YP wowlan not considered*/ + + tmp_u1b = rtl_read_byte(rtlpriv, REG_CR); + if (tmp_u1b != 0 && tmp_u1b != 0xEA) { + rtlhal->mac_func_enable = true; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "MAC has already power on.\n"); + } else { + rtlhal->mac_func_enable = false; + rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_8821AE; + } + + if (support_remote_wakeup && + rtlhal->wake_from_pnp_sleep && + rtlhal->mac_func_enable) { + if (_rtl8821ae_wowlan_initialize_adapter(hw)) { + rtlhal->being_init_adapter = false; + return 0; + } + } + + if (_rtl8821ae_check_pcie_dma_hang(hw)) { + _rtl8821ae_reset_pcie_interface_dma(hw, + rtlhal->mac_func_enable, + false); + rtlhal->mac_func_enable = false; + } + + /* Reset MAC/BB/RF status if it is not powered off + * before calling initialize Hw flow to prevent + * from interface and MAC status mismatch. + * 2013.06.21, by tynli. Suggested by SD1 JackieLau. */ + if (rtlhal->mac_func_enable) { + _rtl8821ae_poweroff_adapter(hw); + rtlhal->mac_func_enable = false; + } + + rtstatus = _rtl8821ae_init_mac(hw); + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); + err = 1; + return err; + } + + tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CFG); + tmp_u1b &= 0x7F; + rtl_write_byte(rtlpriv, REG_SYS_CFG, tmp_u1b); + + err = rtl8821ae_download_fw(hw, false); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Failed to download FW. Init HW without FW now\n"); + err = 1; + rtlhal->fw_ready = false; + return err; + } else { + rtlhal->fw_ready = true; + } + ppsc->fw_current_inpsmode = false; + rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_8821AE; + rtlhal->fw_clk_change_in_progress = false; + rtlhal->allow_sw_to_change_hwclc = false; + rtlhal->last_hmeboxnum = 0; + + /*SIC_Init(Adapter); + if(rtlhal->AMPDUBurstMode) + rtl_write_byte(rtlpriv,REG_AMPDU_BURST_MODE_8812, 0x7F);*/ + + rtl8821ae_phy_mac_config(hw); + /* because last function modify RCR, so we update + * rcr var here, or TP will unstable for receive_config + * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx + * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 + rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); + rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);*/ + rtl8821ae_phy_bb_config(hw); + + rtl8821ae_phy_rf_config(hw); + + if (rtlpriv->phy.rf_type == RF_1T1R && + rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + _rtl8812ae_bb8812_config_1t(hw); + + _rtl8821ae_hw_configure(hw); + + rtl8821ae_phy_switch_wirelessband(hw, BAND_ON_2_4G); + + /*set wireless mode*/ + + rtlhal->mac_func_enable = true; + + rtl_cam_reset_all_entry(hw); + + rtl8821ae_enable_hw_security_config(hw); + + ppsc->rfpwr_state = ERFON; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); + _rtl8821ae_enable_aspm_back_door(hw); + rtlpriv->intf_ops->enable_aspm(hw); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE && + (rtlhal->rfe_type == 1 || rtlhal->rfe_type == 5)) + rtl_set_bbreg(hw, 0x900, 0x00000303, 0x0302); + + rtl8821ae_bt_hw_init(hw); + rtlpriv->rtlhal.being_init_adapter = false; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_NAV_UPPER, (u8 *)&nav_upper); + + /* rtl8821ae_dm_check_txpower_tracking(hw); */ + /* rtl8821ae_phy_lc_calibrate(hw); */ + if (support_remote_wakeup) + rtl_write_byte(rtlpriv, REG_WOW_CTRL, 0); + + /* Release Rx DMA*/ + tmp_u1b = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + if (tmp_u1b & BIT(2)) { + /* Release Rx DMA if needed*/ + tmp_u1b &= ~BIT(2); + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, tmp_u1b); + } + + /* Release Tx/Rx PCIE DMA if*/ + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0); + + rtl8821ae_dm_init(hw); + rtl8821ae_macid_initialize_mediastatus(hw); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "rtl8821ae_hw_init() <====\n"); + return err; +} + +static enum version_8821ae _rtl8821ae_read_chip_version(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + enum version_8821ae version = VERSION_UNKNOWN; + u32 value32; + + value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "ReadChipVersion8812A 0xF0 = 0x%x\n", value32); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtlphy->rf_type = RF_2T2R; + else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) + rtlphy->rf_type = RF_1T1R; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "RF_Type is %x!!\n", rtlphy->rf_type); + + if (value32 & TRP_VAUX_EN) { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + if (rtlphy->rf_type == RF_2T2R) + version = VERSION_TEST_CHIP_2T2R_8812; + else + version = VERSION_TEST_CHIP_1T1R_8812; + } else + version = VERSION_TEST_CHIP_8821; + } else { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + u32 rtl_id = ((value32 & CHIP_VER_RTL_MASK) >> 12) + 1; + + if (rtlphy->rf_type == RF_2T2R) + version = + (enum version_8821ae)(CHIP_8812 + | NORMAL_CHIP | + RF_TYPE_2T2R); + else + version = (enum version_8821ae)(CHIP_8812 + | NORMAL_CHIP); + + version = (enum version_8821ae)(version | (rtl_id << 12)); + } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + u32 rtl_id = value32 & CHIP_VER_RTL_MASK; + + version = (enum version_8821ae)(CHIP_8821 + | NORMAL_CHIP | rtl_id); + } + } + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + /*WL_HWROF_EN.*/ + value32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL); + rtlhal->hw_rof_enable = ((value32 & WL_HWROF_EN) ? 1 : 0); + } + + switch (version) { + case VERSION_TEST_CHIP_1T1R_8812: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip Version ID: VERSION_TEST_CHIP_1T1R_8812\n"); + break; + case VERSION_TEST_CHIP_2T2R_8812: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip Version ID: VERSION_TEST_CHIP_2T2R_8812\n"); + break; + case VERSION_NORMAL_TSMC_CHIP_1T1R_8812: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip Version ID:VERSION_NORMAL_TSMC_CHIP_1T1R_8812\n"); + break; + case VERSION_NORMAL_TSMC_CHIP_2T2R_8812: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_2T2R_8812\n"); + break; + case VERSION_NORMAL_TSMC_CHIP_1T1R_8812_C_CUT: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_1T1R_8812 C CUT\n"); + break; + case VERSION_NORMAL_TSMC_CHIP_2T2R_8812_C_CUT: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_2T2R_8812 C CUT\n"); + break; + case VERSION_TEST_CHIP_8821: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip Version ID: VERSION_TEST_CHIP_8821\n"); + break; + case VERSION_NORMAL_TSMC_CHIP_8821: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_8821 A CUT\n"); + break; + case VERSION_NORMAL_TSMC_CHIP_8821_B_CUT: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_8821 B CUT\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Chip Version ID: Unknow (0x%X)\n", version); + break; + } + + return version; +} + +static int _rtl8821ae_set_media_status(struct ieee80211_hw *hw, + enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 bt_msr = rtl_read_byte(rtlpriv, MSR); + enum led_ctl_mode ledaction = LED_CTL_NO_LINK; + bt_msr &= 0xfc; + + rtl_write_dword(rtlpriv, REG_BCN_CTRL, 0); + RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD, + "clear 0x550 when set HW_VAR_MEDIA_STATUS\n"); + + if (type == NL80211_IFTYPE_UNSPECIFIED || + type == NL80211_IFTYPE_STATION) { + _rtl8821ae_stop_tx_beacon(hw); + _rtl8821ae_enable_bcn_sub_func(hw); + } else if (type == NL80211_IFTYPE_ADHOC || + type == NL80211_IFTYPE_AP) { + _rtl8821ae_resume_tx_beacon(hw); + _rtl8821ae_disable_bcn_sub_func(hw); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", + type); + } + + switch (type) { + case NL80211_IFTYPE_UNSPECIFIED: + bt_msr |= MSR_NOLINK; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to NO LINK!\n"); + break; + case NL80211_IFTYPE_ADHOC: + bt_msr |= MSR_ADHOC; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to Ad Hoc!\n"); + break; + case NL80211_IFTYPE_STATION: + bt_msr |= MSR_INFRA; + ledaction = LED_CTL_LINK; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to STA!\n"); + break; + case NL80211_IFTYPE_AP: + bt_msr |= MSR_AP; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Set Network type to AP!\n"); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Network type %d not support!\n", type); + return 1; + } + + rtl_write_byte(rtlpriv, MSR, bt_msr); + rtlpriv->cfg->ops->led_control(hw, ledaction); + if ((bt_msr & MSR_MASK) == MSR_AP) + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); + else + rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); + + return 0; +} + +void rtl8821ae_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u32 reg_rcr = rtlpci->receive_config; + + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + if (check_bssid) { + reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, + (u8 *)(®_rcr)); + _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(4)); + } else if (!check_bssid) { + reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); + _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(4), 0); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_RCR, (u8 *)(®_rcr)); + } +} + +int rtl8821ae_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "rtl8821ae_set_network_type!\n"); + + if (_rtl8821ae_set_media_status(hw, type)) + return -EOPNOTSUPP; + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP) + rtl8821ae_set_check_bssid(hw, true); + } else { + rtl8821ae_set_check_bssid(hw, false); + } + + return 0; +} + +/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ +void rtl8821ae_set_qos(struct ieee80211_hw *hw, int aci) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + rtl8821ae_dm_init_edca_turbo(hw); + switch (aci) { + case AC1_BK: + rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); + break; + case AC0_BE: + /* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); */ + break; + case AC2_VI: + rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); + break; + case AC3_VO: + rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); + break; + default: + RT_ASSERT(false, "invalid aci: %d !\n", aci); + break; + } +} + +void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); + rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); + rtlpci->irq_enabled = true; + /* there are some C2H CMDs have been sent before + system interrupt is enabled, e.g., C2H, CPWM. + *So we need to clear all C2H events that FW has + notified, otherwise FW won't schedule any commands anymore. + */ + /* rtl_write_byte(rtlpriv, REG_C2HEVT_CLEAR, 0); */ + /*enable system interrupt*/ + rtl_write_dword(rtlpriv, REG_HSIMR, rtlpci->sys_irq_mask & 0xFFFFFFFF); +} + +void rtl8821ae_disable_interrupt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED); + rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED); + rtlpci->irq_enabled = false; + /*synchronize_irq(rtlpci->pdev->irq);*/ +} + +static void _rtl8821ae_clear_pci_pme_status(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u16 cap_hdr; + u8 cap_pointer; + u8 cap_id = 0xff; + u8 pmcs_reg; + u8 cnt = 0; + + /* Get the Capability pointer first, + * the Capability Pointer is located at + * offset 0x34 from the Function Header */ + + pci_read_config_byte(rtlpci->pdev, 0x34, &cap_pointer); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "PCI configration 0x34 = 0x%2x\n", cap_pointer); + + do { + pci_read_config_word(rtlpci->pdev, cap_pointer, &cap_hdr); + cap_id = cap_hdr & 0xFF; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "in pci configration, cap_pointer%x = %x\n", + cap_pointer, cap_id); + + if (cap_id == 0x01) { + break; + } else { + /* point to next Capability */ + cap_pointer = (cap_hdr >> 8) & 0xFF; + /* 0: end of pci capability, 0xff: invalid value */ + if (cap_pointer == 0x00 || cap_pointer == 0xff) { + cap_id = 0xff; + break; + } + } + } while (cnt++ < 200); + + if (cap_id == 0x01) { + /* Get the PM CSR (Control/Status Register), + * The PME_Status is located at PM Capatibility offset 5, bit 7 + */ + pci_read_config_byte(rtlpci->pdev, cap_pointer + 5, &pmcs_reg); + + if (pmcs_reg & BIT(7)) { + /* PME event occured, clear the PM_Status by write 1 */ + pmcs_reg = pmcs_reg | BIT(7); + + pci_write_config_byte(rtlpci->pdev, cap_pointer + 5, + pmcs_reg); + /* Read it back to check */ + pci_read_config_byte(rtlpci->pdev, cap_pointer + 5, + &pmcs_reg); + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Clear PME status 0x%2x to 0x%2x\n", + cap_pointer + 5, pmcs_reg); + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "PME status(0x%2x) = 0x%2x\n", + cap_pointer + 5, pmcs_reg); + } + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, + "Cannot find PME Capability\n"); + } +} + +void rtl8821ae_card_disable(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); + struct rtl_mac *mac = rtl_mac(rtlpriv); + enum nl80211_iftype opmode; + bool support_remote_wakeup; + u8 tmp; + u32 count = 0; + + rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, + (u8 *)(&support_remote_wakeup)); + + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + + if (!(support_remote_wakeup && mac->opmode == NL80211_IFTYPE_STATION) + || !rtlhal->enter_pnp_sleep) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Normal Power off\n"); + mac->link_state = MAC80211_NOLINK; + opmode = NL80211_IFTYPE_UNSPECIFIED; + _rtl8821ae_set_media_status(hw, opmode); + _rtl8821ae_poweroff_adapter(hw); + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Wowlan Supported.\n"); + /* 3 <1> Prepare for configuring wowlan related infomations */ + /* Clear Fw WoWLAN event. */ + rtl_write_byte(rtlpriv, REG_MCUTST_WOWLAN, 0x0); + +#if (USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN == 1) + rtl8821ae_set_fw_related_for_wowlan(hw, true); +#endif + /* Dynamically adjust Tx packet boundary + * for download reserved page packet. + * reserve 30 pages for rsvd page */ + if (_rtl8821ae_dynamic_rqpn(hw, 0xE0, 0x3, 0x80c20d0d)) + rtlhal->re_init_llt_table = true; + + /* 3 <2> Set Fw releted H2C cmd. */ + + /* Set WoWLAN related security information. */ + rtl8821ae_set_fw_global_info_cmd(hw); + + _rtl8821ae_download_rsvd_page(hw, true); + + /* Just enable AOAC related functions when we connect to AP. */ + printk("mac->link_state = %d\n", mac->link_state); + if (mac->link_state >= MAC80211_LINKED && + mac->opmode == NL80211_IFTYPE_STATION) { + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL); + rtl8821ae_set_fw_media_status_rpt_cmd(hw, + RT_MEDIA_CONNECT); + + rtl8821ae_set_fw_wowlan_mode(hw, true); + /* Enable Fw Keep alive mechanism. */ + rtl8821ae_set_fw_keep_alive_cmd(hw, true); + + /* Enable disconnect decision control. */ + rtl8821ae_set_fw_disconnect_decision_ctrl_cmd(hw, true); + } + + /* 3 <3> Hw Configutations */ + + /* Wait untill Rx DMA Finished before host sleep. + * FW Pause Rx DMA may happens when received packet doing dma. + */ + rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, BIT(2)); + + tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + count = 0; + while (!(tmp & BIT(1)) && (count++ < 100)) { + udelay(10); + tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Wait Rx DMA Finished before host sleep. count=%d\n", + count); + + /* reset trx ring */ + rtlpriv->intf_ops->reset_trx_ring(hw); + + rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x0); + + _rtl8821ae_clear_pci_pme_status(hw); + tmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR); + rtl_write_byte(rtlpriv, REG_SYS_CLKR, tmp | BIT(3)); + /* prevent 8051 to be reset by PERST */ + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x20); + rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x60); + } + + if (rtlpriv->rtlhal.driver_is_goingto_unload || + ppsc->rfoff_reason > RF_CHANGE_BY_PS) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); + /* For wowlan+LPS+32k. */ + if (support_remote_wakeup && rtlhal->enter_pnp_sleep) { + /* Set the WoWLAN related function control enable. + * It should be the last H2C cmd in the WoWLAN flow. */ + rtl8821ae_set_fw_remote_wake_ctrl_cmd(hw, 1); + + /* Stop Pcie Interface Tx DMA. */ + rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xff); + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Stop PCIE Tx DMA.\n"); + + /* Wait for TxDMA idle. */ + count = 0; + do { + tmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG); + udelay(10); + count++; + } while ((tmp != 0) && (count < 100)); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Wait Tx DMA Finished before host sleep. count=%d\n", + count); + + if (rtlhal->hw_rof_enable) { + printk("hw_rof_enable\n"); + tmp = rtl_read_byte(rtlpriv, REG_HSISR + 3); + rtl_write_byte(rtlpriv, REG_HSISR + 3, tmp | BIT(1)); + } + } + /* after power off we should do iqk again */ + rtlpriv->phy.iqk_initialized = false; +} + +void rtl8821ae_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; + rtl_write_dword(rtlpriv, ISR, *p_inta); + + *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; + rtl_write_dword(rtlpriv, REG_HISRE, *p_intb); +} + +void rtl8821ae_set_beacon_related_registers(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u16 bcn_interval, atim_window; + + bcn_interval = mac->beacon_interval; + atim_window = 2; /*FIX MERGE */ + rtl8821ae_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); + rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); + rtl_write_byte(rtlpriv, 0x606, 0x30); + rtlpci->reg_bcn_ctrl_val |= BIT(3); + rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); + rtl8821ae_enable_interrupt(hw); +} + +void rtl8821ae_set_beacon_interval(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u16 bcn_interval = mac->beacon_interval; + + RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, + "beacon_interval:%d\n", bcn_interval); + rtl8821ae_disable_interrupt(hw); + rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); + rtl8821ae_enable_interrupt(hw); +} + +void rtl8821ae_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, + "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); + + if (add_msr) + rtlpci->irq_mask[0] |= add_msr; + if (rm_msr) + rtlpci->irq_mask[0] &= (~rm_msr); + rtl8821ae_disable_interrupt(hw); + rtl8821ae_enable_interrupt(hw); +} + +static u8 _rtl8821ae_get_chnl_group(u8 chnl) +{ + u8 group = 0; + + if (chnl <= 14) { + if (1 <= chnl && chnl <= 2) + group = 0; + else if (3 <= chnl && chnl <= 5) + group = 1; + else if (6 <= chnl && chnl <= 8) + group = 2; + else if (9 <= chnl && chnl <= 11) + group = 3; + else /*if (12 <= chnl && chnl <= 14)*/ + group = 4; + } else { + if (36 <= chnl && chnl <= 42) + group = 0; + else if (44 <= chnl && chnl <= 48) + group = 1; + else if (50 <= chnl && chnl <= 58) + group = 2; + else if (60 <= chnl && chnl <= 64) + group = 3; + else if (100 <= chnl && chnl <= 106) + group = 4; + else if (108 <= chnl && chnl <= 114) + group = 5; + else if (116 <= chnl && chnl <= 122) + group = 6; + else if (124 <= chnl && chnl <= 130) + group = 7; + else if (132 <= chnl && chnl <= 138) + group = 8; + else if (140 <= chnl && chnl <= 144) + group = 9; + else if (149 <= chnl && chnl <= 155) + group = 10; + else if (157 <= chnl && chnl <= 161) + group = 11; + else if (165 <= chnl && chnl <= 171) + group = 12; + else if (173 <= chnl && chnl <= 177) + group = 13; + else + /*RT_TRACE(rtlpriv, COMP_EFUSE,DBG_LOUD, + "5G, Channel %d in Group not found\n",chnl);*/ + RT_ASSERT(!COMP_EFUSE, + "5G, Channel %d in Group not found\n", chnl); + } + return group; +} + +static void _rtl8821ae_read_power_value_fromprom(struct ieee80211_hw *hw, + struct txpower_info_2g *pwrinfo24g, + struct txpower_info_5g *pwrinfo5g, + bool autoload_fail, + u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 rfPath, eeAddr = EEPROM_TX_PWR_INX, group, TxCount = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "hal_ReadPowerValueFromPROM8821ae(): hwinfo[0x%x]=0x%x\n", + (eeAddr+1), hwinfo[eeAddr+1]); + if (0xFF == hwinfo[eeAddr+1]) /*YJ,add,120316*/ + autoload_fail = true; + + if (autoload_fail) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "auto load fail : Use Default value!\n"); + for (rfPath = 0 ; rfPath < MAX_RF_PATH ; rfPath++) { + /*2.4G default value*/ + for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { + pwrinfo24g->index_cck_base[rfPath][group] = 0x2D; + pwrinfo24g->index_bw40_base[rfPath][group] = 0x2D; + } + for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { + if (TxCount == 0) { + pwrinfo24g->bw20_diff[rfPath][0] = 0x02; + pwrinfo24g->ofdm_diff[rfPath][0] = 0x04; + } else { + pwrinfo24g->bw20_diff[rfPath][TxCount] = 0xFE; + pwrinfo24g->bw40_diff[rfPath][TxCount] = 0xFE; + pwrinfo24g->cck_diff[rfPath][TxCount] = 0xFE; + pwrinfo24g->ofdm_diff[rfPath][TxCount] = 0xFE; + } + } + /*5G default value*/ + for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) + pwrinfo5g->index_bw40_base[rfPath][group] = 0x2A; + + for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { + if (TxCount == 0) { + pwrinfo5g->ofdm_diff[rfPath][0] = 0x04; + pwrinfo5g->bw20_diff[rfPath][0] = 0x00; + pwrinfo5g->bw80_diff[rfPath][0] = 0xFE; + pwrinfo5g->bw160_diff[rfPath][0] = 0xFE; + } else { + pwrinfo5g->ofdm_diff[rfPath][0] = 0xFE; + pwrinfo5g->bw20_diff[rfPath][0] = 0xFE; + pwrinfo5g->bw40_diff[rfPath][0] = 0xFE; + pwrinfo5g->bw80_diff[rfPath][0] = 0xFE; + pwrinfo5g->bw160_diff[rfPath][0] = 0xFE; + } + } + } + return; + } + + rtl_priv(hw)->efuse.txpwr_fromeprom = true; + + for (rfPath = 0 ; rfPath < MAX_RF_PATH ; rfPath++) { + /*2.4G default value*/ + for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { + pwrinfo24g->index_cck_base[rfPath][group] = hwinfo[eeAddr++]; + if (pwrinfo24g->index_cck_base[rfPath][group] == 0xFF) + pwrinfo24g->index_cck_base[rfPath][group] = 0x2D; + } + for (group = 0 ; group < MAX_CHNL_GROUP_24G - 1; group++) { + pwrinfo24g->index_bw40_base[rfPath][group] = hwinfo[eeAddr++]; + if (pwrinfo24g->index_bw40_base[rfPath][group] == 0xFF) + pwrinfo24g->index_bw40_base[rfPath][group] = 0x2D; + } + for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { + if (TxCount == 0) { + pwrinfo24g->bw40_diff[rfPath][TxCount] = 0; + /*bit sign number to 8 bit sign number*/ + pwrinfo24g->bw20_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4; + if (pwrinfo24g->bw20_diff[rfPath][TxCount] & BIT(3)) + pwrinfo24g->bw20_diff[rfPath][TxCount] |= 0xF0; + /*bit sign number to 8 bit sign number*/ + pwrinfo24g->ofdm_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); + if (pwrinfo24g->ofdm_diff[rfPath][TxCount] & BIT(3)) + pwrinfo24g->ofdm_diff[rfPath][TxCount] |= 0xF0; + + pwrinfo24g->cck_diff[rfPath][TxCount] = 0; + eeAddr++; + } else { + pwrinfo24g->bw40_diff[rfPath][TxCount] = (hwinfo[eeAddr]&0xf0) >> 4; + if (pwrinfo24g->bw40_diff[rfPath][TxCount] & BIT(3)) + pwrinfo24g->bw40_diff[rfPath][TxCount] |= 0xF0; + + pwrinfo24g->bw20_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); + if (pwrinfo24g->bw20_diff[rfPath][TxCount] & BIT(3)) + pwrinfo24g->bw20_diff[rfPath][TxCount] |= 0xF0; + + eeAddr++; + + pwrinfo24g->ofdm_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4; + if (pwrinfo24g->ofdm_diff[rfPath][TxCount] & BIT(3)) + pwrinfo24g->ofdm_diff[rfPath][TxCount] |= 0xF0; + + pwrinfo24g->cck_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); + if (pwrinfo24g->cck_diff[rfPath][TxCount] & BIT(3)) + pwrinfo24g->cck_diff[rfPath][TxCount] |= 0xF0; + + eeAddr++; + } + } + + /*5G default value*/ + for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) { + pwrinfo5g->index_bw40_base[rfPath][group] = hwinfo[eeAddr++]; + if (pwrinfo5g->index_bw40_base[rfPath][group] == 0xFF) + pwrinfo5g->index_bw40_base[rfPath][group] = 0xFE; + } + + for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { + if (TxCount == 0) { + pwrinfo5g->bw40_diff[rfPath][TxCount] = 0; + + pwrinfo5g->bw20_diff[rfPath][0] = (hwinfo[eeAddr] & 0xf0) >> 4; + if (pwrinfo5g->bw20_diff[rfPath][TxCount] & BIT(3)) + pwrinfo5g->bw20_diff[rfPath][TxCount] |= 0xF0; + + pwrinfo5g->ofdm_diff[rfPath][0] = (hwinfo[eeAddr] & 0x0f); + if (pwrinfo5g->ofdm_diff[rfPath][TxCount] & BIT(3)) + pwrinfo5g->ofdm_diff[rfPath][TxCount] |= 0xF0; + + eeAddr++; + } else { + pwrinfo5g->bw40_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4; + if (pwrinfo5g->bw40_diff[rfPath][TxCount] & BIT(3)) + pwrinfo5g->bw40_diff[rfPath][TxCount] |= 0xF0; + + pwrinfo5g->bw20_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); + if (pwrinfo5g->bw20_diff[rfPath][TxCount] & BIT(3)) + pwrinfo5g->bw20_diff[rfPath][TxCount] |= 0xF0; + + eeAddr++; + } + } + + pwrinfo5g->ofdm_diff[rfPath][1] = (hwinfo[eeAddr] & 0xf0) >> 4; + pwrinfo5g->ofdm_diff[rfPath][2] = (hwinfo[eeAddr] & 0x0f); + + eeAddr++; + + pwrinfo5g->ofdm_diff[rfPath][3] = (hwinfo[eeAddr] & 0x0f); + + eeAddr++; + + for (TxCount = 1; TxCount < MAX_TX_COUNT; TxCount++) { + if (pwrinfo5g->ofdm_diff[rfPath][TxCount] & BIT(3)) + pwrinfo5g->ofdm_diff[rfPath][TxCount] |= 0xF0; + } + for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { + pwrinfo5g->bw80_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4; + /* 4bit sign number to 8 bit sign number */ + if (pwrinfo5g->bw80_diff[rfPath][TxCount] & BIT(3)) + pwrinfo5g->bw80_diff[rfPath][TxCount] |= 0xF0; + /* 4bit sign number to 8 bit sign number */ + pwrinfo5g->bw160_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); + if (pwrinfo5g->bw160_diff[rfPath][TxCount] & BIT(3)) + pwrinfo5g->bw160_diff[rfPath][TxCount] |= 0xF0; + + eeAddr++; + } + } +} +#if 0 +static void _rtl8812ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, + u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct txpower_info_2g pwrinfo24g; + struct txpower_info_5g pwrinfo5g; + u8 channel5g[CHANNEL_MAX_NUMBER_5G] = { + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, + 56, 58, 60, 62, 64, 100, 102, 104, 106, + 108, 110, 112, 114, 116, 118, 120, 122, + 124, 126, 128, 130, 132, 134, 136, 138, + 140, 142, 144, 149, 151, 153, 155, 157, + 159, 161, 163, 165, 167, 168, 169, 171, 173, 175, 177}; + u8 channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = {42, 58, 106, 122, 138, 155, 171}; + u8 rf_path, index; + u8 i; + + _rtl8821ae_read_power_value_fromprom(hw, &pwrinfo24g, + &pwrinfo5g, autoload_fail, hwinfo); + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < CHANNEL_MAX_NUMBER_2G; i++) { + index = _rtl8821ae_get_chnl_group(i + 1); + + if (i == CHANNEL_MAX_NUMBER_2G - 1) { + rtlefuse->txpwrlevel_cck[rf_path][i] = + pwrinfo24g.index_cck_base[rf_path][5]; + rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = + pwrinfo24g.index_bw40_base[rf_path][index]; + } else { + rtlefuse->txpwrlevel_cck[rf_path][i] = + pwrinfo24g.index_cck_base[rf_path][index]; + rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = + pwrinfo24g.index_bw40_base[rf_path][index]; + } + } + + for (i = 0; i < CHANNEL_MAX_NUMBER_5G; i++) { + index = _rtl8821ae_get_chnl_group(channel5g[i]); + rtlefuse->txpwr_5g_bw40base[rf_path][i] = + pwrinfo5g.index_bw40_base[rf_path][index]; + } + for (i = 0; i < CHANNEL_MAX_NUMBER_5G_80M; i++) { + u8 upper, lower; + index = _rtl8821ae_get_chnl_group(channel5g_80m[i]); + upper = pwrinfo5g.index_bw40_base[rf_path][index]; + lower = pwrinfo5g.index_bw40_base[rf_path][index + 1]; + + rtlefuse->txpwr_5g_bw80base[rf_path][i] = (upper + lower) / 2; + } + for (i = 0; i < MAX_TX_COUNT; i++) { + rtlefuse->txpwr_cckdiff[rf_path][i] = + pwrinfo24g.cck_diff[rf_path][i]; + rtlefuse->txpwr_legacyhtdiff[rf_path][i] = + pwrinfo24g.ofdm_diff[rf_path][i]; + rtlefuse->txpwr_ht20diff[rf_path][i] = + pwrinfo24g.bw20_diff[rf_path][i]; + rtlefuse->txpwr_ht40diff[rf_path][i] = + pwrinfo24g.bw40_diff[rf_path][i]; + + rtlefuse->txpwr_5g_ofdmdiff[rf_path][i] = + pwrinfo5g.ofdm_diff[rf_path][i]; + rtlefuse->txpwr_5g_bw20diff[rf_path][i] = + pwrinfo5g.bw20_diff[rf_path][i]; + rtlefuse->txpwr_5g_bw40diff[rf_path][i] = + pwrinfo5g.bw40_diff[rf_path][i]; + rtlefuse->txpwr_5g_bw80diff[rf_path][i] = + pwrinfo5g.bw80_diff[rf_path][i]; + } + } + + if (!autoload_fail) { + rtlefuse->eeprom_regulatory = + hwinfo[EEPROM_RF_BOARD_OPTION] & 0x07;/*bit0~2*/ + if (hwinfo[EEPROM_RF_BOARD_OPTION] == 0xFF) + rtlefuse->eeprom_regulatory = 0; + } else { + rtlefuse->eeprom_regulatory = 0; + } + + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); +} +#endif +static void _rtl8821ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, + bool autoload_fail, + u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct txpower_info_2g pwrinfo24g; + struct txpower_info_5g pwrinfo5g; + u8 channel5g[CHANNEL_MAX_NUMBER_5G] = { + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, + 56, 58, 60, 62, 64, 100, 102, 104, 106, + 108, 110, 112, 114, 116, 118, 120, 122, + 124, 126, 128, 130, 132, 134, 136, 138, + 140, 142, 144, 149, 151, 153, 155, 157, + 159, 161, 163, 165, 167, 168, 169, 171, + 173, 175, 177}; + u8 channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = { + 42, 58, 106, 122, 138, 155, 171}; + u8 rf_path, index; + u8 i; + + _rtl8821ae_read_power_value_fromprom(hw, &pwrinfo24g, + &pwrinfo5g, autoload_fail, hwinfo); + + for (rf_path = 0; rf_path < 2; rf_path++) { + for (i = 0; i < CHANNEL_MAX_NUMBER_2G; i++) { + index = _rtl8821ae_get_chnl_group(i + 1); + + if (i == CHANNEL_MAX_NUMBER_2G - 1) { + rtlefuse->txpwrlevel_cck[rf_path][i] = + pwrinfo24g.index_cck_base[rf_path][5]; + rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = + pwrinfo24g.index_bw40_base[rf_path][index]; + } else { + rtlefuse->txpwrlevel_cck[rf_path][i] = + pwrinfo24g.index_cck_base[rf_path][index]; + rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = + pwrinfo24g.index_bw40_base[rf_path][index]; + } + } + + for (i = 0; i < CHANNEL_MAX_NUMBER_5G; i++) { + index = _rtl8821ae_get_chnl_group(channel5g[i]); + rtlefuse->txpwr_5g_bw40base[rf_path][i] = + pwrinfo5g.index_bw40_base[rf_path][index]; + } + for (i = 0; i < CHANNEL_MAX_NUMBER_5G_80M; i++) { + u8 upper, lower; + index = _rtl8821ae_get_chnl_group(channel5g_80m[i]); + upper = pwrinfo5g.index_bw40_base[rf_path][index]; + lower = pwrinfo5g.index_bw40_base[rf_path][index + 1]; + + rtlefuse->txpwr_5g_bw80base[rf_path][i] = (upper + lower) / 2; + } + for (i = 0; i < MAX_TX_COUNT; i++) { + rtlefuse->txpwr_cckdiff[rf_path][i] = + pwrinfo24g.cck_diff[rf_path][i]; + rtlefuse->txpwr_legacyhtdiff[rf_path][i] = + pwrinfo24g.ofdm_diff[rf_path][i]; + rtlefuse->txpwr_ht20diff[rf_path][i] = + pwrinfo24g.bw20_diff[rf_path][i]; + rtlefuse->txpwr_ht40diff[rf_path][i] = + pwrinfo24g.bw40_diff[rf_path][i]; + + rtlefuse->txpwr_5g_ofdmdiff[rf_path][i] = + pwrinfo5g.ofdm_diff[rf_path][i]; + rtlefuse->txpwr_5g_bw20diff[rf_path][i] = + pwrinfo5g.bw20_diff[rf_path][i]; + rtlefuse->txpwr_5g_bw40diff[rf_path][i] = + pwrinfo5g.bw40_diff[rf_path][i]; + rtlefuse->txpwr_5g_bw80diff[rf_path][i] = + pwrinfo5g.bw80_diff[rf_path][i]; + } + } + /*bit0~2*/ + if (!autoload_fail) { + rtlefuse->eeprom_regulatory = hwinfo[EEPROM_RF_BOARD_OPTION] & 0x07; + if (hwinfo[EEPROM_RF_BOARD_OPTION] == 0xFF) + rtlefuse->eeprom_regulatory = 0; + } else { + rtlefuse->eeprom_regulatory = 0; + } + + RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, + "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); +} + +static void _rtl8812ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo, + bool autoload_fail) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + + if (!autoload_fail) { + rtlhal->pa_type_2g = hwinfo[0xBC]; + rtlhal->lna_type_2g = hwinfo[0xBD]; + if (rtlhal->pa_type_2g == 0xFF && rtlhal->lna_type_2g == 0xFF) { + rtlhal->pa_type_2g = 0; + rtlhal->lna_type_2g = 0; + } + rtlhal->external_pa_2g = ((rtlhal->pa_type_2g & BIT(5)) && + (rtlhal->pa_type_2g & BIT(4))) ? + 1 : 0; + rtlhal->external_lna_2g = ((rtlhal->lna_type_2g & BIT(7)) && + (rtlhal->lna_type_2g & BIT(3))) ? + 1 : 0; + + rtlhal->pa_type_5g = hwinfo[0xBC]; + rtlhal->lna_type_5g = hwinfo[0xBF]; + if (rtlhal->pa_type_5g == 0xFF && rtlhal->lna_type_5g == 0xFF) { + rtlhal->pa_type_5g = 0; + rtlhal->lna_type_5g = 0; + } + rtlhal->external_pa_5g = ((rtlhal->pa_type_5g & BIT(1)) && + (rtlhal->pa_type_5g & BIT(0))) ? + 1 : 0; + rtlhal->external_lna_5g = ((rtlhal->lna_type_5g & BIT(7)) && + (rtlhal->lna_type_5g & BIT(3))) ? + 1 : 0; + } else { + rtlhal->external_pa_2g = 0; + rtlhal->external_lna_2g = 0; + rtlhal->external_pa_5g = 0; + rtlhal->external_lna_5g = 0; + } +} + +static void _rtl8821ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo, + bool autoload_fail) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + + if (!autoload_fail) { + rtlhal->pa_type_2g = hwinfo[0xBC]; + rtlhal->lna_type_2g = hwinfo[0xBD]; + if (rtlhal->pa_type_2g == 0xFF && rtlhal->lna_type_2g == 0xFF) { + rtlhal->pa_type_2g = 0; + rtlhal->lna_type_2g = 0; + } + rtlhal->external_pa_2g = (rtlhal->pa_type_2g & BIT(5)) ? 1 : 0; + rtlhal->external_lna_2g = (rtlhal->lna_type_2g & BIT(7)) ? 1 : 0; + + rtlhal->pa_type_5g = hwinfo[0xBC]; + rtlhal->lna_type_5g = hwinfo[0xBF]; + if (rtlhal->pa_type_5g == 0xFF && rtlhal->lna_type_5g == 0xFF) { + rtlhal->pa_type_5g = 0; + rtlhal->lna_type_5g = 0; + } + rtlhal->external_pa_5g = (rtlhal->pa_type_5g & BIT(1)) ? 1 : 0; + rtlhal->external_lna_5g = (rtlhal->lna_type_5g & BIT(7)) ? 1 : 0; + } else { + rtlhal->external_pa_2g = 0; + rtlhal->external_lna_2g = 0; + rtlhal->external_pa_5g = 0; + rtlhal->external_lna_5g = 0; + } +} + +static void _rtl8821ae_read_rfe_type(struct ieee80211_hw *hw, u8 *hwinfo, + bool autoload_fail) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + + if (!autoload_fail) { + if (hwinfo[EEPROM_RFE_OPTION] & BIT(7)) { + if (rtlhal->external_lna_5g) { + if (rtlhal->external_pa_5g) { + if (rtlhal->external_lna_2g && + rtlhal->external_pa_2g) + rtlhal->rfe_type = 3; + else + rtlhal->rfe_type = 0; + } else { + rtlhal->rfe_type = 2; + } + } else { + rtlhal->rfe_type = 4; + } + } else { + rtlhal->rfe_type = hwinfo[EEPROM_RFE_OPTION] & 0x3F; + + if (rtlhal->rfe_type == 4 && + (rtlhal->external_pa_5g || + rtlhal->external_pa_2g || + rtlhal->external_lna_5g || + rtlhal->external_lna_2g)) { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtlhal->rfe_type = 2; + } + } + } else { + rtlhal->rfe_type = 0x04; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "RFE Type: 0x%2x\n", rtlhal->rfe_type); +} + +static void _rtl8812ae_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool auto_load_fail, u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 value; + + if (!auto_load_fail) { + value = *(u8 *)&hwinfo[EEPROM_RF_BOARD_OPTION]; + if (((value & 0xe0) >> 5) == 0x1) + rtlpriv->btcoexist.btc_info.btcoexist = 1; + else + rtlpriv->btcoexist.btc_info.btcoexist = 0; + rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8812A; + + value = hwinfo[EEPROM_RF_BT_SETTING]; + rtlpriv->btcoexist.btc_info.ant_num = (value & 0x1); + } else { + rtlpriv->btcoexist.btc_info.btcoexist = 0; + rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8812A; + rtlpriv->btcoexist.btc_info.ant_num = ANT_X2; + } + /*move BT_InitHalVars() to init_sw_vars*/ +} + +static void _rtl8821ae_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, + bool auto_load_fail, u8 *hwinfo) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 value; + u32 tmpu_32; + + if (!auto_load_fail) { + tmpu_32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL); + if (tmpu_32 & BIT(18)) + rtlpriv->btcoexist.btc_info.btcoexist = 1; + else + rtlpriv->btcoexist.btc_info.btcoexist = 0; + rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8821A; + + value = hwinfo[EEPROM_RF_BT_SETTING]; + rtlpriv->btcoexist.btc_info.ant_num = (value & 0x1); + } else { + rtlpriv->btcoexist.btc_info.btcoexist = 0; + rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8821A; + rtlpriv->btcoexist.btc_info.ant_num = ANT_X2; + } + /*move BT_InitHalVars() to init_sw_vars*/ +} + +static void _rtl8821ae_read_adapter_info(struct ieee80211_hw *hw, bool b_pseudo_test) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + u16 i, usvalue; + u8 hwinfo[HWSET_MAX_SIZE]; + u16 eeprom_id; + + if (b_pseudo_test) { + ;/* need add */ + } + + if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { + rtl_efuse_shadow_map_update(hw); + memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], + HWSET_MAX_SIZE); + } else if (rtlefuse->epromtype == EEPROM_93C46) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "RTL819X Not boot from eeprom, check it !!"); + } + + RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP\n", + hwinfo, HWSET_MAX_SIZE); + + eeprom_id = *((u16 *)&hwinfo[0]); + if (eeprom_id != RTL_EEPROM_ID) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "EEPROM ID(%#x) is invalid!!\n", eeprom_id); + rtlefuse->autoload_failflag = true; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + } + + if (rtlefuse->autoload_failflag) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "RTL8812AE autoload_failflag, check it !!"); + return; + } + + rtlefuse->eeprom_version = *(u8 *)&hwinfo[EEPROM_VERSION]; + if (rtlefuse->eeprom_version == 0xff) + rtlefuse->eeprom_version = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM version: 0x%2x\n", rtlefuse->eeprom_version); + + rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; + rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; + rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; + rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROMId = 0x%4x\n", eeprom_id); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); + + /*customer ID*/ + rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID]; + if (rtlefuse->eeprom_oemid == 0xFF) + rtlefuse->eeprom_oemid = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); + + for (i = 0; i < 6; i += 2) { + usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; + *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "dev_addr: %pM\n", rtlefuse->dev_addr); + + _rtl8821ae_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, + hwinfo); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + _rtl8812ae_read_pa_type(hw, hwinfo, rtlefuse->autoload_failflag); + _rtl8812ae_read_bt_coexist_info_from_hwpg(hw, + rtlefuse->autoload_failflag, hwinfo); + } else { + _rtl8821ae_read_pa_type(hw, hwinfo, rtlefuse->autoload_failflag); + _rtl8821ae_read_bt_coexist_info_from_hwpg(hw, + rtlefuse->autoload_failflag, hwinfo); + } + + _rtl8821ae_read_rfe_type(hw, hwinfo, rtlefuse->autoload_failflag); + /*board type*/ + rtlefuse->board_type = ODM_BOARD_DEFAULT; + if (rtlhal->external_lna_2g != 0) + rtlefuse->board_type |= ODM_BOARD_EXT_LNA; + if (rtlhal->external_lna_5g != 0) + rtlefuse->board_type |= ODM_BOARD_EXT_LNA_5G; + if (rtlhal->external_pa_2g != 0) + rtlefuse->board_type |= ODM_BOARD_EXT_PA; + if (rtlhal->external_pa_5g != 0) + rtlefuse->board_type |= ODM_BOARD_EXT_PA_5G; + + if (rtlpriv->btcoexist.btc_info.btcoexist == 1) + rtlefuse->board_type |= ODM_BOARD_BT; + + rtlhal->board_type = rtlefuse->board_type; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "board_type = 0x%x\n", rtlefuse->board_type); + + rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; + if (rtlefuse->eeprom_channelplan == 0xff) + rtlefuse->eeprom_channelplan = 0x7F; + + /* set channel plan from efuse */ + rtlefuse->channel_plan = rtlefuse->eeprom_channelplan; + + /*parse xtal*/ + rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_8821AE]; + if (rtlefuse->crystalcap == 0xFF) + rtlefuse->crystalcap = 0x20; + + rtlefuse->eeprom_thermalmeter = *(u8 *)&hwinfo[EEPROM_THERMAL_METER]; + if ((rtlefuse->eeprom_thermalmeter == 0xff) || + rtlefuse->autoload_failflag) { + rtlefuse->apk_thermalmeterignore = true; + rtlefuse->eeprom_thermalmeter = 0xff; + } + + rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); + + if (!rtlefuse->autoload_failflag) { + rtlefuse->antenna_div_cfg = + (hwinfo[EEPROM_RF_BOARD_OPTION] & 0x18) >> 3; + if (hwinfo[EEPROM_RF_BOARD_OPTION] == 0xff) + rtlefuse->antenna_div_cfg = 0; + + if (rtlpriv->btcoexist.btc_info.btcoexist == 1 && + rtlpriv->btcoexist.btc_info.ant_num == ANT_X1) + rtlefuse->antenna_div_cfg = 0; + + rtlefuse->antenna_div_type = hwinfo[EEPROM_RF_ANTENNA_OPT_88E]; + if (rtlefuse->antenna_div_type == 0xff) + rtlefuse->antenna_div_type = FIXED_HW_ANTDIV; + } else { + rtlefuse->antenna_div_cfg = 0; + rtlefuse->antenna_div_type = 0; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "SWAS: bHwAntDiv = %x, TRxAntDivType = %x\n", + rtlefuse->antenna_div_cfg, rtlefuse->antenna_div_type); + + pcipriv->ledctl.led_opendrain = true; + + if (rtlhal->oem_id == RT_CID_DEFAULT) { + switch (rtlefuse->eeprom_oemid) { + case RT_CID_DEFAULT: + break; + case EEPROM_CID_TOSHIBA: + rtlhal->oem_id = RT_CID_TOSHIBA; + break; + case EEPROM_CID_CCX: + rtlhal->oem_id = RT_CID_CCX; + break; + case EEPROM_CID_QMI: + rtlhal->oem_id = RT_CID_819X_QMI; + break; + case EEPROM_CID_WHQL: + break; + default: + break; + } + } +} + +/*static void _rtl8821ae_hal_customized_behavior(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + pcipriv->ledctl.led_opendrain = true; + switch (rtlhal->oem_id) { + case RT_CID_819X_HP: + pcipriv->ledctl.led_opendrain = true; + break; + case RT_CID_819X_LENOVO: + case RT_CID_DEFAULT: + case RT_CID_TOSHIBA: + case RT_CID_CCX: + case RT_CID_819X_ACER: + case RT_CID_WHQL: + default: + break; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "RT Customized ID: 0x%02X\n", rtlhal->oem_id); +}*/ + +void rtl8821ae_read_eeprom_info(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_u1b; + + rtlhal->version = _rtl8821ae_read_chip_version(hw); + if (get_rf_type(rtlphy) == RF_1T1R) + rtlpriv->dm.rfpath_rxenable[0] = true; + else + rtlpriv->dm.rfpath_rxenable[0] = + rtlpriv->dm.rfpath_rxenable[1] = true; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", + rtlhal->version); + + tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); + if (tmp_u1b & BIT(4)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); + rtlefuse->epromtype = EEPROM_93C46; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); + rtlefuse->epromtype = EEPROM_BOOT_EFUSE; + } + + if (tmp_u1b & BIT(5)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); + rtlefuse->autoload_failflag = false; + _rtl8821ae_read_adapter_info(hw, false); + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); + } + /*hal_ReadRFType_8812A()*/ + /* _rtl8821ae_hal_customized_behavior(hw); */ +} + +static void rtl8821ae_update_hal_rate_table(struct ieee80211_hw *hw, + struct ieee80211_sta *sta) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 ratr_value; + u8 ratr_index = 0; + u8 b_nmode = mac->ht_enable; + u8 mimo_ps = IEEE80211_SMPS_OFF; + u16 shortgi_rate; + u32 tmp_ratr_value; + u8 curtxbw_40mhz = mac->bw_40; + u8 b_curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 b_curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + enum wireless_mode wirelessmode = mac->mode; + + if (rtlhal->current_bandtype == BAND_ON_5G) + ratr_value = sta->supp_rates[1] << 4; + else + ratr_value = sta->supp_rates[0]; + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_value = 0xfff; + ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + switch (wirelessmode) { + case WIRELESS_MODE_B: + if (ratr_value & 0x0000000c) + ratr_value &= 0x0000000d; + else + ratr_value &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_value &= 0x00000FF5; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + b_nmode = 1; + if (mimo_ps == IEEE80211_SMPS_STATIC) { + ratr_value &= 0x0007F005; + } else { + u32 ratr_mask; + + if (get_rf_type(rtlphy) == RF_1T2R || + get_rf_type(rtlphy) == RF_1T1R) + ratr_mask = 0x000ff005; + else + ratr_mask = 0x0f0ff005; + + ratr_value &= ratr_mask; + } + break; + default: + if (rtlphy->rf_type == RF_1T2R) + ratr_value &= 0x000ff0ff; + else + ratr_value &= 0x0f0ff0ff; + + break; + } + + if ((rtlpriv->btcoexist.bt_coexistence) && + (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4) && + (rtlpriv->btcoexist.bt_cur_state) && + (rtlpriv->btcoexist.bt_ant_isolation) && + ((rtlpriv->btcoexist.bt_service == BT_SCO) || + (rtlpriv->btcoexist.bt_service == BT_BUSY))) + ratr_value &= 0x0fffcfc0; + else + ratr_value &= 0x0FFFFFFF; + + if (b_nmode && ((curtxbw_40mhz && + b_curshortgi_40mhz) || (!curtxbw_40mhz && + b_curshortgi_20mhz))) { + ratr_value |= 0x10000000; + tmp_ratr_value = (ratr_value >> 12); + + for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { + if ((1 << shortgi_rate) & tmp_ratr_value) + break; + } + + shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | + (shortgi_rate << 4) | (shortgi_rate); + } + + rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)); +} + +static u8 _rtl8821ae_mrate_idx_to_arfr_id( + struct ieee80211_hw *hw, u8 rate_index, + enum wireless_mode wirelessmode) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 ret = 0; + switch (rate_index) { + case RATR_INX_WIRELESS_NGB: + if (rtlphy->rf_type == RF_1T1R) + ret = 1; + else + ret = 0; + ; break; + case RATR_INX_WIRELESS_N: + case RATR_INX_WIRELESS_NG: + if (rtlphy->rf_type == RF_1T1R) + ret = 5; + else + ret = 4; + ; break; + case RATR_INX_WIRELESS_NB: + if (rtlphy->rf_type == RF_1T1R) + ret = 3; + else + ret = 2; + ; break; + case RATR_INX_WIRELESS_GB: + ret = 6; + break; + case RATR_INX_WIRELESS_G: + ret = 7; + break; + case RATR_INX_WIRELESS_B: + ret = 8; + break; + case RATR_INX_WIRELESS_MC: + if ((wirelessmode == WIRELESS_MODE_B) + || (wirelessmode == WIRELESS_MODE_G) + || (wirelessmode == WIRELESS_MODE_N_24G) + || (wirelessmode == WIRELESS_MODE_AC_24G)) + ret = 6; + else + ret = 7; + case RATR_INX_WIRELESS_AC_5N: + if (rtlphy->rf_type == RF_1T1R) + ret = 10; + else + ret = 9; + break; + case RATR_INX_WIRELESS_AC_24N: + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) { + if (rtlphy->rf_type == RF_1T1R) + ret = 10; + else + ret = 9; + } else { + if (rtlphy->rf_type == RF_1T1R) + ret = 11; + else + ret = 12; + } + break; + default: + ret = 0; break; + } + return ret; +} + +static u32 _rtl8821ae_rate_to_bitmap_2ssvht(__le16 vht_rate) +{ + u8 i, j, tmp_rate; + u32 rate_bitmap = 0; + + for (i = j = 0; i < 4; i += 2, j += 10) { + tmp_rate = (le16_to_cpu(vht_rate) >> i) & 3; + + switch (tmp_rate) { + case 2: + rate_bitmap = rate_bitmap | (0x03ff << j); + break; + case 1: + rate_bitmap = rate_bitmap | (0x01ff << j); + break; + case 0: + rate_bitmap = rate_bitmap | (0x00ff << j); + break; + default: + break; + } + } + + return rate_bitmap; +} + +static u32 _rtl8821ae_set_ra_vht_ratr_bitmap(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u32 ratr_bitmap) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 ret_bitmap = ratr_bitmap; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40 + || rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) + ret_bitmap = ratr_bitmap; + else if (wirelessmode == WIRELESS_MODE_AC_5G + || wirelessmode == WIRELESS_MODE_AC_24G) { + if (rtlphy->rf_type == RF_1T1R) + ret_bitmap = ratr_bitmap & (~BIT21); + else + ret_bitmap = ratr_bitmap & (~(BIT31|BIT21)); + } + + return ret_bitmap; +} + +static u8 _rtl8821ae_get_vht_eni(enum wireless_mode wirelessmode, + u32 ratr_bitmap) +{ + u8 ret = 0; + if (wirelessmode < WIRELESS_MODE_N_24G) + ret = 0; + else if (wirelessmode == WIRELESS_MODE_AC_24G) { + if (ratr_bitmap & 0xfff00000) /* Mix , 2SS */ + ret = 3; + else /* Mix, 1SS */ + ret = 2; + } else if (wirelessmode == WIRELESS_MODE_AC_5G) { + ret = 1; + } /* VHT */ + + return ret << 4; +} + +static u8 _rtl8821ae_get_ra_ldpc(struct ieee80211_hw *hw, + u8 mac_id, struct rtl_sta_info *sta_entry, + enum wireless_mode wirelessmode) +{ + u8 b_ldpc = 0; + /*not support ldpc, do not open*/ + return b_ldpc << 2; +} + +static u8 _rtl8821ae_get_ra_rftype(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u32 ratr_bitmap) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 rf_type = RF_1T1R; + + if (rtlphy->rf_type == RF_1T1R) + rf_type = RF_1T1R; + else if (wirelessmode == WIRELESS_MODE_AC_5G + || wirelessmode == WIRELESS_MODE_AC_24G + || wirelessmode == WIRELESS_MODE_AC_ONLY) { + if (ratr_bitmap & 0xffc00000) + rf_type = RF_2T2R; + } else if (wirelessmode == WIRELESS_MODE_N_5G + || wirelessmode == WIRELESS_MODE_N_24G) { + if (ratr_bitmap & 0xfff00000) + rf_type = RF_2T2R; + } + + return rf_type; +} + +static bool _rtl8821ae_get_ra_shortgi(struct ieee80211_hw *hw, struct ieee80211_sta *sta, + u8 mac_id) +{ + bool b_short_gi = false; + u8 b_curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? + 1 : 0; + u8 b_curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? + 1 : 0; + u8 b_curshortgi_80mhz = 0; + b_curshortgi_80mhz = (sta->vht_cap.cap & + IEEE80211_VHT_CAP_SHORT_GI_80) ? 1 : 0; + + if (mac_id == MAC_ID_STATIC_FOR_BROADCAST_MULTICAST) + b_short_gi = false; + + if (b_curshortgi_40mhz || b_curshortgi_80mhz + || b_curshortgi_20mhz) + b_short_gi = true; + + return b_short_gi; +} + +static void rtl8821ae_update_hal_rate_mask(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_sta_info *sta_entry = NULL; + u32 ratr_bitmap; + u8 ratr_index; + enum wireless_mode wirelessmode = 0; + u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) + ? 1 : 0; + bool b_shortgi = false; + u8 rate_mask[7]; + u8 macid = 0; + u8 mimo_ps = IEEE80211_SMPS_OFF; + u8 rf_type; + + sta_entry = (struct rtl_sta_info *)sta->drv_priv; + wirelessmode = sta_entry->wireless_mode; + + RT_TRACE(rtlpriv, COMP_RATR, DBG_LOUD, + "wireless mode = 0x%x\n", wirelessmode); + if (mac->opmode == NL80211_IFTYPE_STATION || + mac->opmode == NL80211_IFTYPE_MESH_POINT) { + curtxbw_40mhz = mac->bw_40; + } else if (mac->opmode == NL80211_IFTYPE_AP || + mac->opmode == NL80211_IFTYPE_ADHOC) + macid = sta->aid + 1; + if (wirelessmode == WIRELESS_MODE_N_5G || + wirelessmode == WIRELESS_MODE_AC_5G || + wirelessmode == WIRELESS_MODE_A) + ratr_bitmap = sta->supp_rates[NL80211_BAND_5GHZ] << 4; + else + ratr_bitmap = sta->supp_rates[NL80211_BAND_2GHZ]; + + if (mac->opmode == NL80211_IFTYPE_ADHOC) + ratr_bitmap = 0xfff; + + if (wirelessmode == WIRELESS_MODE_N_24G + || wirelessmode == WIRELESS_MODE_N_5G) + ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | + sta->ht_cap.mcs.rx_mask[0] << 12); + else if (wirelessmode == WIRELESS_MODE_AC_24G + || wirelessmode == WIRELESS_MODE_AC_5G + || wirelessmode == WIRELESS_MODE_AC_ONLY) + ratr_bitmap |= _rtl8821ae_rate_to_bitmap_2ssvht( + sta->vht_cap.vht_mcs.rx_mcs_map) << 12; + + b_shortgi = _rtl8821ae_get_ra_shortgi(hw, sta, macid); + rf_type = _rtl8821ae_get_ra_rftype(hw, wirelessmode, ratr_bitmap); + +/*mac id owner*/ + switch (wirelessmode) { + case WIRELESS_MODE_B: + ratr_index = RATR_INX_WIRELESS_B; + if (ratr_bitmap & 0x0000000c) + ratr_bitmap &= 0x0000000d; + else + ratr_bitmap &= 0x0000000f; + break; + case WIRELESS_MODE_G: + ratr_index = RATR_INX_WIRELESS_GB; + + if (rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if (rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + break; + case WIRELESS_MODE_A: + ratr_index = RATR_INX_WIRELESS_G; + ratr_bitmap &= 0x00000ff0; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + if (wirelessmode == WIRELESS_MODE_N_24G) + ratr_index = RATR_INX_WIRELESS_NGB; + else + ratr_index = RATR_INX_WIRELESS_NG; + + if (mimo_ps == IEEE80211_SMPS_STATIC + || mimo_ps == IEEE80211_SMPS_DYNAMIC) { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff005; + } else { + if (rf_type == RF_1T1R) { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x000ff000; + else + ratr_bitmap &= 0x000ff005; + } + } else { + if (curtxbw_40mhz) { + if (rssi_level == 1) + ratr_bitmap &= 0x0fff0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0ffff000; + else + ratr_bitmap &= 0x0ffff015; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0x0fff0000; + else if (rssi_level == 2) + ratr_bitmap &= 0x0ffff000; + else + ratr_bitmap &= 0x0ffff005; + } + } + } + break; + + case WIRELESS_MODE_AC_24G: + ratr_index = RATR_INX_WIRELESS_AC_24N; + if (rssi_level == 1) + ratr_bitmap &= 0xfc3f0000; + else if (rssi_level == 2) + ratr_bitmap &= 0xfffff000; + else + ratr_bitmap &= 0xffffffff; + break; + + case WIRELESS_MODE_AC_5G: + ratr_index = RATR_INX_WIRELESS_AC_5N; + + if (rf_type == RF_1T1R) { + if (rssi_level == 1) /*add by Gary for ac-series*/ + ratr_bitmap &= 0x003f8000; + else if (rssi_level == 2) + ratr_bitmap &= 0x003ff000; + else + ratr_bitmap &= 0x003ff010; + } else { + if (rssi_level == 1) + ratr_bitmap &= 0xfe3f8000; + else if (rssi_level == 2) + ratr_bitmap &= 0xfffff000; + else + ratr_bitmap &= 0xfffff010; + } + break; + + default: + ratr_index = RATR_INX_WIRELESS_NGB; + + if (rf_type == RF_1T2R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0f8ff0ff; + break; + } + + ratr_index = _rtl8821ae_mrate_idx_to_arfr_id(hw, ratr_index, wirelessmode); + sta_entry->ratr_index = ratr_index; + ratr_bitmap = _rtl8821ae_set_ra_vht_ratr_bitmap(hw, wirelessmode, + ratr_bitmap); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_LOUD, + "ratr_bitmap :%x\n", ratr_bitmap); + + /* *(u32 *)& rate_mask = EF4BYTE((ratr_bitmap & 0x0fffffff) | + (ratr_index << 28)); */ + + rate_mask[0] = macid; + rate_mask[1] = ratr_index | (b_shortgi ? 0x80 : 0x00); + rate_mask[2] = rtlphy->current_chan_bw + | _rtl8821ae_get_vht_eni(wirelessmode, ratr_bitmap) + | _rtl8821ae_get_ra_ldpc(hw, macid, sta_entry, wirelessmode); + + rate_mask[3] = (u8)(ratr_bitmap & 0x000000ff); + rate_mask[4] = (u8)((ratr_bitmap & 0x0000ff00) >> 8); + rate_mask[5] = (u8)((ratr_bitmap & 0x00ff0000) >> 16); + rate_mask[6] = (u8)((ratr_bitmap & 0xff000000) >> 24); + + RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, + "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x:%x:%x\n", + ratr_index, ratr_bitmap, + rate_mask[0], rate_mask[1], + rate_mask[2], rate_mask[3], + rate_mask[4], rate_mask[5], + rate_mask[6]); + rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_RA_MASK, 7, rate_mask); + _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(3), 0); +} + +void rtl8821ae_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (rtlpriv->dm.useramask) + rtl8821ae_update_hal_rate_mask(hw, sta, rssi_level); + else + /*RT_TRACE(rtlpriv, COMP_RATR,DBG_LOUD, + "rtl8821ae_update_hal_rate_tbl() Error! 8821ae FW RA Only");*/ + rtl8821ae_update_hal_rate_table(hw, sta); +} + +void rtl8821ae_update_channel_access_setting(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + u8 wireless_mode = mac->mode; + u8 sifs_timer, r2t_sifs; + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, + (u8 *)&mac->slot_time); + if (wireless_mode == WIRELESS_MODE_G) + sifs_timer = 0x0a; + else + sifs_timer = 0x0e; + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); + + r2t_sifs = 0xa; + + if (wireless_mode == WIRELESS_MODE_AC_5G && + (mac->vht_ldpc_cap & LDPC_VHT_ENABLE_RX) && + (mac->vht_stbc_cap & STBC_VHT_ENABLE_RX)) { + if (mac->vendor == PEER_ATH) + r2t_sifs = 0x8; + else + r2t_sifs = 0xa; + } else if (wireless_mode == WIRELESS_MODE_AC_5G) { + r2t_sifs = 0xa; + } + + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_R2T_SIFS, (u8 *)&r2t_sifs); +} + +bool rtl8821ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; + u8 u1tmp = 0; + bool b_actuallyset = false; + + if (rtlpriv->rtlhal.being_init_adapter) + return false; + + if (ppsc->swrf_processing) + return false; + + spin_lock(&rtlpriv->locks.rf_ps_lock); + if (ppsc->rfchange_inprogress) { + spin_unlock(&rtlpriv->locks.rf_ps_lock); + return false; + } else { + ppsc->rfchange_inprogress = true; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } + + cur_rfstate = ppsc->rfpwr_state; + + rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL_2, + rtl_read_byte(rtlpriv, + REG_GPIO_IO_SEL_2) & ~(BIT(1))); + + u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL_2); + + if (rtlphy->polarity_ctl) + e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFOFF : ERFON; + else + e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFON : ERFOFF; + + if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "GPIOChangeRF - HW Radio ON, RF ON\n"); + + e_rfpowerstate_toset = ERFON; + ppsc->hwradiooff = false; + b_actuallyset = true; + } else if ((!ppsc->hwradiooff) + && (e_rfpowerstate_toset == ERFOFF)) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "GPIOChangeRF - HW Radio OFF, RF OFF\n"); + + e_rfpowerstate_toset = ERFOFF; + ppsc->hwradiooff = true; + b_actuallyset = true; + } + + if (b_actuallyset) { + spin_lock(&rtlpriv->locks.rf_ps_lock); + ppsc->rfchange_inprogress = false; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } else { + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + + spin_lock(&rtlpriv->locks.rf_ps_lock); + ppsc->rfchange_inprogress = false; + spin_unlock(&rtlpriv->locks.rf_ps_lock); + } + + *valid = 1; + return !ppsc->hwradiooff; +} + +void rtl8821ae_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 *macaddr = p_macaddr; + u32 entry_id = 0; + bool is_pairwise = false; + + static u8 cam_const_addr[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} + }; + static u8 cam_const_broad[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (clear_all) { + u8 idx = 0; + u8 cam_offset = 0; + u8 clear_number = 5; + + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); + + for (idx = 0; idx < clear_number; idx++) { + rtl_cam_mark_invalid(hw, cam_offset + idx); + rtl_cam_empty_entry(hw, cam_offset + idx); + + if (idx < 5) { + memset(rtlpriv->sec.key_buf[idx], 0, + MAX_KEY_LEN); + rtlpriv->sec.key_len[idx] = 0; + } + } + } else { + switch (enc_algo) { + case WEP40_ENCRYPTION: + enc_algo = CAM_WEP40; + break; + case WEP104_ENCRYPTION: + enc_algo = CAM_WEP104; + break; + case TKIP_ENCRYPTION: + enc_algo = CAM_TKIP; + break; + case AESCCMP_ENCRYPTION: + enc_algo = CAM_AES; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + enc_algo = CAM_TKIP; + break; + } + + if (is_wepkey || rtlpriv->sec.use_defaultkey) { + macaddr = cam_const_addr[key_index]; + entry_id = key_index; + } else { + if (is_group) { + macaddr = cam_const_broad; + entry_id = key_index; + } else { + if (mac->opmode == NL80211_IFTYPE_AP) { + entry_id = rtl_cam_get_free_entry(hw, p_macaddr); + if (entry_id >= TOTAL_CAM_ENTRY) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, + "Can not find free hwsecurity cam entry\n"); + return; + } + } else { + entry_id = CAM_PAIRWISE_KEY_POSITION; + } + + key_index = PAIRWISE_KEYIDX; + is_pairwise = true; + } + } + + if (rtlpriv->sec.key_len[key_index] == 0) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "delete one entry, entry_id is %d\n", + entry_id); + if (mac->opmode == NL80211_IFTYPE_AP) + rtl_cam_del_entry(hw, p_macaddr); + rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "add one entry\n"); + if (is_pairwise) { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set Pairwise key\n"); + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[key_index]); + } else { + RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, + "set group key\n"); + + if (mac->opmode == NL80211_IFTYPE_ADHOC) { + rtl_cam_add_one_entry(hw, + rtlefuse->dev_addr, + PAIRWISE_KEYIDX, + CAM_PAIRWISE_KEY_POSITION, + enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf + [entry_id]); + } + + rtl_cam_add_one_entry(hw, macaddr, key_index, + entry_id, enc_algo, + CAM_CONFIG_NO_USEDK, + rtlpriv->sec.key_buf[entry_id]); + } + } + } +} + +void rtl8821ae_bt_reg_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + /* 0:Low, 1:High, 2:From Efuse. */ + rtlpriv->btcoexist.reg_bt_iso = 2; + /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ + rtlpriv->btcoexist.reg_bt_sco = 3; + /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ + rtlpriv->btcoexist.reg_bt_sco = 0; +} + +void rtl8821ae_bt_hw_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->cfg->ops->get_btc_status()) + rtlpriv->btcoexist.btc_ops->btc_init_hw_config(rtlpriv); +} + +void rtl8821ae_suspend(struct ieee80211_hw *hw) +{ +} + +void rtl8821ae_resume(struct ieee80211_hw *hw) +{ +} + +/* Turn on AAP (RCR:bit 0) for promicuous mode. */ +void rtl8821ae_allow_all_destaddr(struct ieee80211_hw *hw, + bool allow_all_da, bool write_into_reg) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + if (allow_all_da) /* Set BIT0 */ + rtlpci->receive_config |= RCR_AAP; + else /* Clear BIT0 */ + rtlpci->receive_config &= ~RCR_AAP; + + if (write_into_reg) + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); + + RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, + "receive_config=0x%08X, write_into_reg=%d\n", + rtlpci->receive_config, write_into_reg); +} + +/* WKFMCAMAddAllEntry8812 */ +void rtl8821ae_add_wowlan_pattern(struct ieee80211_hw *hw, + struct rtl_wow_pattern *rtl_pattern, + u8 index) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 cam = 0; + u8 addr = 0; + u16 rxbuf_addr; + u8 tmp, count = 0; + u16 cam_start; + u16 offset; + + /* Count the WFCAM entry start offset. */ + + /* RX page size = 128 byte */ + offset = MAX_RX_DMA_BUFFER_SIZE_8812 / 128; + /* We should start from the boundry */ + cam_start = offset * 128; + + /* Enable Rx packet buffer access. */ + rtl_write_byte(rtlpriv, REG_PKT_BUFF_ACCESS_CTRL, RXPKT_BUF_SELECT); + for (addr = 0; addr < WKFMCAM_ADDR_NUM; addr++) { + /* Set Rx packet buffer offset. + * RxBufer pointer increases 1, + * we can access 8 bytes in Rx packet buffer. + * CAM start offset (unit: 1 byte) = index*WKFMCAM_SIZE + * RxBufer addr = (CAM start offset + + * per entry offset of a WKFM CAM)/8 + * * index: The index of the wake up frame mask + * * WKFMCAM_SIZE: the total size of one WKFM CAM + * * per entry offset of a WKFM CAM: Addr*4 bytes + */ + rxbuf_addr = (cam_start + index * WKFMCAM_SIZE + addr * 4) >> 3; + /* Set R/W start offset */ + rtl_write_word(rtlpriv, REG_PKTBUF_DBG_CTRL, rxbuf_addr); + + if (addr == 0) { + cam = BIT(31) | rtl_pattern->crc; + + if (rtl_pattern->type == UNICAST_PATTERN) + cam |= BIT(24); + else if (rtl_pattern->type == MULTICAST_PATTERN) + cam |= BIT(25); + else if (rtl_pattern->type == BROADCAST_PATTERN) + cam |= BIT(26); + + rtl_write_dword(rtlpriv, REG_PKTBUF_DBG_DATA_L, cam); + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "WRITE entry[%d] 0x%x: %x\n", addr, + REG_PKTBUF_DBG_DATA_L, cam); + + /* Write to Rx packet buffer. */ + rtl_write_word(rtlpriv, REG_RXPKTBUF_CTRL, 0x0f01); + } else if (addr == 2 || addr == 4) {/* WKFM[127:0] */ + cam = rtl_pattern->mask[addr - 2]; + + rtl_write_dword(rtlpriv, REG_PKTBUF_DBG_DATA_L, cam); + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "WRITE entry[%d] 0x%x: %x\n", addr, + REG_PKTBUF_DBG_DATA_L, cam); + + rtl_write_word(rtlpriv, REG_RXPKTBUF_CTRL, 0x0f01); + } else if (addr == 3 || addr == 5) {/* WKFM[127:0] */ + cam = rtl_pattern->mask[addr - 2]; + + rtl_write_dword(rtlpriv, REG_PKTBUF_DBG_DATA_H, cam); + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "WRITE entry[%d] 0x%x: %x\n", addr, + REG_PKTBUF_DBG_DATA_H, cam); + + rtl_write_word(rtlpriv, REG_RXPKTBUF_CTRL, 0xf001); + } + + count = 0; + do { + tmp = rtl_read_byte(rtlpriv, REG_RXPKTBUF_CTRL); + udelay(2); + count++; + } while (tmp && count < 100); + + RT_ASSERT((count < 100), + "Write wake up frame mask FAIL %d value!\n", tmp); + } + /* Disable Rx packet buffer access. */ + rtl_write_byte(rtlpriv, REG_PKT_BUFF_ACCESS_CTRL, + DISABLE_TRXPKT_BUF_ACCESS); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h new file mode 100644 index 000000000000..a3553e3abaa1 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8821AE_HW_H__ +#define __RTL8821AE_HW_H__ + +void rtl8821ae_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl8821ae_read_eeprom_info(struct ieee80211_hw *hw); + +void rtl8821ae_interrupt_recognized(struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb); +int rtl8821ae_hw_init(struct ieee80211_hw *hw); +void rtl8821ae_card_disable(struct ieee80211_hw *hw); +void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw); +void rtl8821ae_disable_interrupt(struct ieee80211_hw *hw); +int rtl8821ae_set_network_type(struct ieee80211_hw *hw, + enum nl80211_iftype type); +void rtl8821ae_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); +void rtl8821ae_set_qos(struct ieee80211_hw *hw, int aci); +void rtl8821ae_set_beacon_related_registers(struct ieee80211_hw *hw); +void rtl8821ae_set_beacon_interval(struct ieee80211_hw *hw); +void rtl8821ae_update_interrupt_mask(struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); +void rtl8821ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl8821ae_update_hal_rate_tbl(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + u8 rssi_level); +void rtl8821ae_update_channel_access_setting(struct ieee80211_hw *hw); +bool rtl8821ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); +void rtl8821ae_enable_hw_security_config(struct ieee80211_hw *hw); +void rtl8821ae_set_key(struct ieee80211_hw *hw, u32 key_index, + u8 *p_macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all); + +void rtl8821ae_bt_reg_init(struct ieee80211_hw *hw); +void rtl8821ae_bt_hw_init(struct ieee80211_hw *hw); +void rtl8821ae_suspend(struct ieee80211_hw *hw); +void rtl8821ae_resume(struct ieee80211_hw *hw); +void rtl8821ae_allow_all_destaddr(struct ieee80211_hw *hw, + bool allow_all_da, + bool write_into_reg); +void _rtl8821ae_stop_tx_beacon(struct ieee80211_hw *hw); +void _rtl8821ae_resume_tx_beacon(struct ieee80211_hw *hw); +void rtl8821ae_add_wowlan_pattern(struct ieee80211_hw *hw, + struct rtl_wow_pattern *rtl_pattern, + u8 index); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c new file mode 100644 index 000000000000..ba1946a0280e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.c @@ -0,0 +1,237 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "reg.h" +#include "led.h" + +static void _rtl8821ae_init_led(struct ieee80211_hw *hw, + struct rtl_led *pled, + enum rtl_led_pin ledpin) +{ + pled->hw = hw; + pled->ledpin = ledpin; + pled->ledon = false; +} + +void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u8 ledcfg; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + ledcfg &= ~BIT(6); + rtl_write_byte(rtlpriv, + REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5)); + break; + case LED_PIN_LED1: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); + rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + pled->ledon = true; +} + +void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u16 ledreg = REG_LEDCFG1; + u8 ledcfg = 0; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (pled->ledpin) { + case LED_PIN_LED0: + ledreg = REG_LEDCFG1; + break; + + case LED_PIN_LED1: + ledreg = REG_LEDCFG2; + break; + + case LED_PIN_GPIO0: + default: + break; + } + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + "In SwLedOn, LedAddr:%X LEDPIN=%d\n", + ledreg, pled->ledpin); + + ledcfg = rtl_read_byte(rtlpriv, ledreg); + ledcfg |= BIT(5); /*Set 0x4c[21]*/ + ledcfg &= ~(BIT(7) | BIT(6) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); + /*Clear 0x4c[23:22] and 0x4c[19:16]*/ + rtl_write_byte(rtlpriv, ledreg, ledcfg); /*SW control led0 on.*/ + pled->ledon = true; +} + +void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + u8 ledcfg; + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); + + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + + switch (pled->ledpin) { + case LED_PIN_GPIO0: + break; + case LED_PIN_LED0: + ledcfg &= 0xf0; + if (pcipriv->ledctl.led_opendrain) { + ledcfg &= 0x90; /* Set to software control. */ + rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3))); + ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); + ledcfg &= 0xFE; + rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg); + } else { + ledcfg &= ~BIT(6); + rtl_write_byte(rtlpriv, REG_LEDCFG2, + (ledcfg | BIT(3) | BIT(5))); + } + break; + case LED_PIN_LED1: + ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); + ledcfg &= 0x10; /* Set to software control. */ + rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg|BIT(3)); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + "switch case not process\n"); + break; + } + pled->ledon = false; +} + +void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ + u16 ledreg = REG_LEDCFG1; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + + switch (pled->ledpin) { + case LED_PIN_LED0: + ledreg = REG_LEDCFG1; + break; + + case LED_PIN_LED1: + ledreg = REG_LEDCFG2; + break; + + case LED_PIN_GPIO0: + default: + break; + } + + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, + "In SwLedOff,LedAddr:%X LEDPIN=%d\n", + ledreg, pled->ledpin); + /*Open-drain arrangement for controlling the LED*/ + if (pcipriv->ledctl.led_opendrain) { + u8 ledcfg = rtl_read_byte(rtlpriv, ledreg); + + ledreg &= 0xd0; /* Set to software control.*/ + rtl_write_byte(rtlpriv, ledreg, (ledcfg | BIT(3))); + + /*Open-drain arrangement*/ + ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); + ledcfg &= 0xFE;/*Set GPIO[8] to input mode*/ + rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg); + } else { + rtl_write_byte(rtlpriv, ledreg, 0x28); + } + + pled->ledon = false; +} + +void rtl8821ae_init_sw_leds(struct ieee80211_hw *hw) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + + _rtl8821ae_init_led(hw, &pcipriv->ledctl.sw_led0, LED_PIN_LED0); + _rtl8821ae_init_led(hw, &pcipriv->ledctl.sw_led1, LED_PIN_LED1); +} + +static void _rtl8821ae_sw_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_led *pLed0 = &pcipriv->ledctl.sw_led0; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + switch (ledaction) { + case LED_CTL_POWER_ON: + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtl8812ae_sw_led_on(hw, pLed0); + else + rtl8821ae_sw_led_on(hw, pLed0); + break; + case LED_CTL_POWER_OFF: + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtl8812ae_sw_led_off(hw, pLed0); + else + rtl8821ae_sw_led_off(hw, pLed0); + break; + default: + break; + } +} + +void rtl8821ae_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && + (ledaction == LED_CTL_TX || + ledaction == LED_CTL_RX || + ledaction == LED_CTL_SITE_SURVEY || + ledaction == LED_CTL_LINK || + ledaction == LED_CTL_NO_LINK || + ledaction == LED_CTL_START_TO_LINK || + ledaction == LED_CTL_POWER_ON)) { + return; + } + RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n", + ledaction); + _rtl8821ae_sw_led_control(hw, ledaction); +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h new file mode 100644 index 000000000000..038e64e18ae8 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/led.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8821AE_LED_H__ +#define __RTL8821AE_LED_H__ + +void rtl8821ae_init_sw_leds(struct ieee80211_hw *hw); +void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl8821ae_led_control(struct ieee80211_hw *hw, + enum led_ctl_mode ledaction); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c new file mode 100644 index 000000000000..9b4d8a637915 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c @@ -0,0 +1,4858 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../ps.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "table.h" +#include "trx.h" +#include "../btcoexist/halbt_precomp.h" +#include "hw.h" +#include "../efuse.h" + +#define READ_NEXT_PAIR(array_table, v1, v2, i) \ + do { \ + i += 2; \ + v1 = array_table[i]; \ + v2 = array_table[i+1]; \ + } while (0) + +static u32 _rtl8821ae_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset); +static void _rtl8821ae_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data); +static u32 _rtl8821ae_phy_calculate_bit_shift(u32 bitmask); +static bool _rtl8821ae_phy_bb8821a_config_parafile(struct ieee80211_hw *hw); +/*static bool _rtl8812ae_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);*/ +static bool _rtl8821ae_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); +static bool _rtl8821ae_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype); +static bool _rtl8821ae_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype); +static void phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); + +static long _rtl8821ae_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u8 txpwridx); +static void rtl8821ae_phy_set_rf_on(struct ieee80211_hw *hw); +static void rtl8821ae_phy_set_io(struct ieee80211_hw *hw); + +static void rtl8812ae_fixspur(struct ieee80211_hw *hw, + enum ht_channel_width band_width, u8 channel) +{ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + /*C cut Item12 ADC FIFO CLOCK*/ + if (IS_VENDOR_8812A_C_CUT(rtlhal->version)) { + if (band_width == HT_CHANNEL_WIDTH_20_40 && channel == 11) + rtl_set_bbreg(hw, RRFMOD, 0xC00, 0x3); + /* 0x8AC[11:10] = 2'b11*/ + else + rtl_set_bbreg(hw, RRFMOD, 0xC00, 0x2); + /* 0x8AC[11:10] = 2'b10*/ + + /* <20120914, Kordan> A workarould to resolve + * 2480Mhz spur by setting ADC clock as 160M. (Asked by Binson) + */ + if (band_width == HT_CHANNEL_WIDTH_20 && + (channel == 13 || channel == 14)) { + rtl_set_bbreg(hw, RRFMOD, 0x300, 0x3); + /*0x8AC[9:8] = 2'b11*/ + rtl_set_bbreg(hw, RADC_BUF_CLK, BIT(30), 1); + /* 0x8C4[30] = 1*/ + } else if (band_width == HT_CHANNEL_WIDTH_20_40 && + channel == 11) { + rtl_set_bbreg(hw, RADC_BUF_CLK, BIT(30), 1); + /*0x8C4[30] = 1*/ + } else if (band_width != HT_CHANNEL_WIDTH_80) { + rtl_set_bbreg(hw, RRFMOD, 0x300, 0x2); + /*0x8AC[9:8] = 2'b10*/ + rtl_set_bbreg(hw, RADC_BUF_CLK, BIT(30), 0); + /*0x8C4[30] = 0*/ + } + } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + /* <20120914, Kordan> A workarould to resolve + * 2480Mhz spur by setting ADC clock as 160M. + */ + if (band_width == HT_CHANNEL_WIDTH_20 && + (channel == 13 || channel == 14)) + rtl_set_bbreg(hw, RRFMOD, 0x300, 0x3); + /*0x8AC[9:8] = 11*/ + else if (channel <= 14) /*2.4G only*/ + rtl_set_bbreg(hw, RRFMOD, 0x300, 0x2); + /*0x8AC[9:8] = 10*/ + } +} + +u32 rtl8821ae_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, + u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 returnvalue, originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x)\n", + regaddr, bitmask); + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl8821ae_phy_calculate_bit_shift(bitmask); + returnvalue = (originalvalue & bitmask) >> bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "BBR MASK=0x%x Addr[0x%x]=0x%x\n", + bitmask, regaddr, originalvalue); + return returnvalue; +} + +void rtl8821ae_phy_set_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 originalvalue, bitshift; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); + + if (bitmask != MASKDWORD) { + originalvalue = rtl_read_dword(rtlpriv, regaddr); + bitshift = _rtl8821ae_phy_calculate_bit_shift(bitmask); + data = ((originalvalue & (~bitmask)) | + ((data << bitshift) & bitmask)); + } + + rtl_write_dword(rtlpriv, regaddr, data); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x)\n", + regaddr, bitmask, data); +} + +u32 rtl8821ae_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, readback_value, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", + regaddr, rfpath, bitmask); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + original_value = _rtl8821ae_phy_rf_serial_read(hw, rfpath, regaddr); + bitshift = _rtl8821ae_phy_calculate_bit_shift(bitmask); + readback_value = (original_value & bitmask) >> bitshift; + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", + regaddr, rfpath, bitmask, original_value); + + return readback_value; +} + +void rtl8821ae_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 original_value, bitshift; + unsigned long flags; + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); + + spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); + + if (bitmask != RFREG_OFFSET_MASK) { + original_value = + _rtl8821ae_phy_rf_serial_read(hw, rfpath, regaddr); + bitshift = _rtl8821ae_phy_calculate_bit_shift(bitmask); + data = ((original_value & (~bitmask)) | (data << bitshift)); + } + + _rtl8821ae_phy_rf_serial_write(hw, rfpath, regaddr, data); + + spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); + + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", + regaddr, bitmask, data, rfpath); +} + +static u32 _rtl8821ae_phy_rf_serial_read(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + bool is_pi_mode = false; + u32 retvalue = 0; + + /* 2009/06/17 MH We can not execute IO for power + save or other accident mode.*/ + if (RT_CANNOT_IO(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n"); + return 0xFFFFFFFF; + } + /* <20120809, Kordan> CCA OFF(when entering), + asked by James to avoid reading the wrong value. + <20120828, Kordan> Toggling CCA would affect RF 0x0, skip it!*/ + if (offset != 0x0 && + !((rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) || + (IS_VENDOR_8812A_C_CUT(rtlhal->version)))) + rtl_set_bbreg(hw, RCCAONSEC, 0x8, 1); + offset &= 0xff; + + if (rfpath == RF90_PATH_A) + is_pi_mode = (bool)rtl_get_bbreg(hw, 0xC00, 0x4); + else if (rfpath == RF90_PATH_B) + is_pi_mode = (bool)rtl_get_bbreg(hw, 0xE00, 0x4); + + rtl_set_bbreg(hw, RHSSIREAD_8821AE, 0xff, offset); + + if ((rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) || + (IS_VENDOR_8812A_C_CUT(rtlhal->version))) + udelay(20); + + if (is_pi_mode) { + if (rfpath == RF90_PATH_A) + retvalue = + rtl_get_bbreg(hw, RA_PIREAD_8821A, BLSSIREADBACKDATA); + else if (rfpath == RF90_PATH_B) + retvalue = + rtl_get_bbreg(hw, RB_PIREAD_8821A, BLSSIREADBACKDATA); + } else { + if (rfpath == RF90_PATH_A) + retvalue = + rtl_get_bbreg(hw, RA_SIREAD_8821A, BLSSIREADBACKDATA); + else if (rfpath == RF90_PATH_B) + retvalue = + rtl_get_bbreg(hw, RB_SIREAD_8821A, BLSSIREADBACKDATA); + } + + /*<20120809, Kordan> CCA ON(when exiting), + * asked by James to avoid reading the wrong value. + * <20120828, Kordan> Toggling CCA would affect RF 0x0, skip it! + */ + if (offset != 0x0 && + !((rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) || + (IS_VENDOR_8812A_C_CUT(rtlhal->version)))) + rtl_set_bbreg(hw, RCCAONSEC, 0x8, 0); + return retvalue; +} + +static void _rtl8821ae_phy_rf_serial_write(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 offset, + u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + u32 data_and_addr; + u32 newoffset; + + if (RT_CANNOT_IO(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n"); + return; + } + offset &= 0xff; + newoffset = offset; + data_and_addr = ((newoffset << 20) | + (data & 0x000fffff)) & 0x0fffffff; + rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); + RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, + "RFW-%d Addr[0x%x]=0x%x\n", + rfpath, pphyreg->rf3wire_offset, data_and_addr); +} + +static u32 _rtl8821ae_phy_calculate_bit_shift(u32 bitmask) +{ + u32 i; + + for (i = 0; i <= 31; i++) { + if (((bitmask >> i) & 0x1) == 1) + break; + } + return i; +} + +bool rtl8821ae_phy_mac_config(struct ieee80211_hw *hw) +{ + bool rtstatus = 0; + + rtstatus = _rtl8821ae_phy_config_mac_with_headerfile(hw); + + return rtstatus; +} + +bool rtl8821ae_phy_bb_config(struct ieee80211_hw *hw) +{ + bool rtstatus = true; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 regval; + u8 crystal_cap; + + phy_init_bb_rf_register_definition(hw); + + regval = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); + regval |= FEN_PCIEA; + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, regval); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, + regval | FEN_BB_GLB_RSTN | FEN_BBRSTB); + + rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x7); + rtl_write_byte(rtlpriv, REG_OPT_CTRL + 2, 0x7); + + rtstatus = _rtl8821ae_phy_bb8821a_config_parafile(hw); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + crystal_cap = rtlefuse->crystalcap & 0x3F; + rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0x7FF80000, + (crystal_cap | (crystal_cap << 6))); + } else { + crystal_cap = rtlefuse->crystalcap & 0x3F; + rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, + (crystal_cap | (crystal_cap << 6))); + } + rtlphy->reg_837 = rtl_read_byte(rtlpriv, 0x837); + + return rtstatus; +} + +bool rtl8821ae_phy_rf_config(struct ieee80211_hw *hw) +{ + return rtl8821ae_phy_rf6052_config(hw); +} + +u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band, + u8 rf_path) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtlpriv); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + char reg_swing_2g = -1;/* 0xff; */ + char reg_swing_5g = -1;/* 0xff; */ + char swing_2g = -1 * reg_swing_2g; + char swing_5g = -1 * reg_swing_5g; + u32 out = 0x200; + const char auto_temp = -1; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, + "===> PHY_GetTxBBSwing_8812A, bbSwing_2G: %d, bbSwing_5G: %d,autoload_failflag=%d.\n", + (int)swing_2g, (int)swing_5g, + (int)rtlefuse->autoload_failflag); + + if (rtlefuse->autoload_failflag) { + if (band == BAND_ON_2_4G) { + rtldm->swing_diff_2g = swing_2g; + if (swing_2g == 0) { + out = 0x200; /* 0 dB */ + } else if (swing_2g == -3) { + out = 0x16A; /* -3 dB */ + } else if (swing_2g == -6) { + out = 0x101; /* -6 dB */ + } else if (swing_2g == -9) { + out = 0x0B6; /* -9 dB */ + } else { + rtldm->swing_diff_2g = 0; + out = 0x200; + } + } else if (band == BAND_ON_5G) { + rtldm->swing_diff_5g = swing_5g; + if (swing_5g == 0) { + out = 0x200; /* 0 dB */ + } else if (swing_5g == -3) { + out = 0x16A; /* -3 dB */ + } else if (swing_5g == -6) { + out = 0x101; /* -6 dB */ + } else if (swing_5g == -9) { + out = 0x0B6; /* -9 dB */ + } else { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + rtldm->swing_diff_5g = -3; + out = 0x16A; + } else { + rtldm->swing_diff_5g = 0; + out = 0x200; + } + } + } else { + rtldm->swing_diff_2g = -3; + rtldm->swing_diff_5g = -3; + out = 0x16A; /* -3 dB */ + } + } else { + u32 swing = 0, swing_a = 0, swing_b = 0; + + if (band == BAND_ON_2_4G) { + if (reg_swing_2g == auto_temp) { + efuse_shadow_read(hw, 1, 0xC6, (u32 *)&swing); + swing = (swing == 0xFF) ? 0x00 : swing; + } else if (swing_2g == 0) { + swing = 0x00; /* 0 dB */ + } else if (swing_2g == -3) { + swing = 0x05; /* -3 dB */ + } else if (swing_2g == -6) { + swing = 0x0A; /* -6 dB */ + } else if (swing_2g == -9) { + swing = 0xFF; /* -9 dB */ + } else { + swing = 0x00; + } + } else { + if (reg_swing_5g == auto_temp) { + efuse_shadow_read(hw, 1, 0xC7, (u32 *)&swing); + swing = (swing == 0xFF) ? 0x00 : swing; + } else if (swing_5g == 0) { + swing = 0x00; /* 0 dB */ + } else if (swing_5g == -3) { + swing = 0x05; /* -3 dB */ + } else if (swing_5g == -6) { + swing = 0x0A; /* -6 dB */ + } else if (swing_5g == -9) { + swing = 0xFF; /* -9 dB */ + } else { + swing = 0x00; + } + } + + swing_a = (swing & 0x3) >> 0; /* 0xC6/C7[1:0] */ + swing_b = (swing & 0xC) >> 2; /* 0xC6/C7[3:2] */ + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, + "===> PHY_GetTxBBSwing_8812A, swingA: 0x%X, swingB: 0x%X\n", + swing_a, swing_b); + + /* 3 Path-A */ + if (swing_a == 0x0) { + if (band == BAND_ON_2_4G) + rtldm->swing_diff_2g = 0; + else + rtldm->swing_diff_5g = 0; + out = 0x200; /* 0 dB */ + } else if (swing_a == 0x1) { + if (band == BAND_ON_2_4G) + rtldm->swing_diff_2g = -3; + else + rtldm->swing_diff_5g = -3; + out = 0x16A; /* -3 dB */ + } else if (swing_a == 0x2) { + if (band == BAND_ON_2_4G) + rtldm->swing_diff_2g = -6; + else + rtldm->swing_diff_5g = -6; + out = 0x101; /* -6 dB */ + } else if (swing_a == 0x3) { + if (band == BAND_ON_2_4G) + rtldm->swing_diff_2g = -9; + else + rtldm->swing_diff_5g = -9; + out = 0x0B6; /* -9 dB */ + } + /* 3 Path-B */ + if (swing_b == 0x0) { + if (band == BAND_ON_2_4G) + rtldm->swing_diff_2g = 0; + else + rtldm->swing_diff_5g = 0; + out = 0x200; /* 0 dB */ + } else if (swing_b == 0x1) { + if (band == BAND_ON_2_4G) + rtldm->swing_diff_2g = -3; + else + rtldm->swing_diff_5g = -3; + out = 0x16A; /* -3 dB */ + } else if (swing_b == 0x2) { + if (band == BAND_ON_2_4G) + rtldm->swing_diff_2g = -6; + else + rtldm->swing_diff_5g = -6; + out = 0x101; /* -6 dB */ + } else if (swing_b == 0x3) { + if (band == BAND_ON_2_4G) + rtldm->swing_diff_2g = -9; + else + rtldm->swing_diff_5g = -9; + out = 0x0B6; /* -9 dB */ + } + } + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, + "<=== PHY_GetTxBBSwing_8812A, out = 0x%X\n", out); + return out; +} + +void rtl8821ae_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_dm *rtldm = rtl_dm(rtlpriv); + u8 current_band = rtlhal->current_bandtype; + u32 txpath, rxpath; + char bb_diff_between_band; + + txpath = rtl8821ae_phy_query_bb_reg(hw, RTXPATH, 0xf0); + rxpath = rtl8821ae_phy_query_bb_reg(hw, RCCK_RX, 0x0f000000); + rtlhal->current_bandtype = (enum band_type) band; + /* reconfig BB/RF according to wireless mode */ + if (rtlhal->current_bandtype == BAND_ON_2_4G) { + /* BB & RF Config */ + rtl_set_bbreg(hw, ROFDMCCKEN, BOFDMEN|BCCKEN, 0x03); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + /* 0xCB0[15:12] = 0x7 (LNA_On)*/ + rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xF000, 0x7); + /* 0xCB0[7:4] = 0x7 (PAPE_A)*/ + rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xF0, 0x7); + } + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + /*0x834[1:0] = 0x1*/ + rtl_set_bbreg(hw, 0x834, 0x3, 0x1); + } + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + /* 0xC1C[11:8] = 0 */ + rtl_set_bbreg(hw, RA_TXSCALE, 0xF00, 0); + } else { + /* 0x82C[1:0] = 2b'00 */ + rtl_set_bbreg(hw, 0x82c, 0x3, 0); + } + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, + 0x77777777); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, + 0x77777777); + rtl_set_bbreg(hw, RA_RFE_INV, 0x3ff00000, 0x000); + rtl_set_bbreg(hw, RB_RFE_INV, 0x3ff00000, 0x000); + } + + rtl_set_bbreg(hw, RTXPATH, 0xf0, 0x1); + rtl_set_bbreg(hw, RCCK_RX, 0x0f000000, 0x1); + + rtl_write_byte(rtlpriv, REG_CCK_CHECK, 0x0); + } else {/* 5G band */ + u16 count, reg_41a; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + /*0xCB0[15:12] = 0x5 (LNA_On)*/ + rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xF000, 0x5); + /*0xCB0[7:4] = 0x4 (PAPE_A)*/ + rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xF0, 0x4); + } + /*CCK_CHECK_en*/ + rtl_write_byte(rtlpriv, REG_CCK_CHECK, 0x80); + + count = 0; + reg_41a = rtl_read_word(rtlpriv, REG_TXPKT_EMPTY); + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, + "Reg41A value %d", reg_41a); + reg_41a &= 0x30; + while ((reg_41a != 0x30) && (count < 50)) { + udelay(50); + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "Delay 50us\n"); + + reg_41a = rtl_read_word(rtlpriv, REG_TXPKT_EMPTY); + reg_41a &= 0x30; + count++; + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, + "Reg41A value %d", reg_41a); + } + if (count != 0) + RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, + "PHY_SwitchWirelessBand8812(): Switch to 5G Band. Count = %d reg41A=0x%x\n", + count, reg_41a); + + /* 2012/02/01, Sinda add registry to switch workaround + without long-run verification for scan issue. */ + rtl_set_bbreg(hw, ROFDMCCKEN, BOFDMEN|BCCKEN, 0x03); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + /*0x834[1:0] = 0x2*/ + rtl_set_bbreg(hw, 0x834, 0x3, 0x2); + } + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + /* AGC table select */ + /* 0xC1C[11:8] = 1*/ + rtl_set_bbreg(hw, RA_TXSCALE, 0xF00, 1); + } else + /* 0x82C[1:0] = 2'b00 */ + rtl_set_bbreg(hw, 0x82c, 0x3, 1); + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, + 0x77337777); + rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, + 0x77337777); + rtl_set_bbreg(hw, RA_RFE_INV, 0x3ff00000, 0x010); + rtl_set_bbreg(hw, RB_RFE_INV, 0x3ff00000, 0x010); + } + + rtl_set_bbreg(hw, RTXPATH, 0xf0, 0); + rtl_set_bbreg(hw, RCCK_RX, 0x0f000000, 0xf); + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, + "==>PHY_SwitchWirelessBand8812() BAND_ON_5G settings OFDM index 0x%x\n", + rtlpriv->dm.ofdm_index[RF90_PATH_A]); + } + + if ((rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) || + (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)) { + /* 0xC1C[31:21] */ + rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, + phy_get_tx_swing_8812A(hw, band, RF90_PATH_A)); + /* 0xE1C[31:21] */ + rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000, + phy_get_tx_swing_8812A(hw, band, RF90_PATH_B)); + + /* <20121005, Kordan> When TxPowerTrack is ON, + * we should take care of the change of BB swing. + * That is, reset all info to trigger Tx power tracking. + */ + if (band != current_band) { + bb_diff_between_band = + (rtldm->swing_diff_2g - rtldm->swing_diff_5g); + bb_diff_between_band = (band == BAND_ON_2_4G) ? + bb_diff_between_band : + (-1 * bb_diff_between_band); + rtldm->default_ofdm_index += bb_diff_between_band * 2; + } + rtl8821ae_dm_clear_txpower_tracking_state(hw); + } + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "<==rtl8821ae_phy_switch_wirelessband():Switch Band OK.\n"); + return; +} + +static bool _rtl8821ae_check_condition(struct ieee80211_hw *hw, + const u32 condition) +{ + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 _board = rtlefuse->board_type; /*need efuse define*/ + u32 _interface = 0x01; /* ODM_ITRF_PCIE */ + u32 _platform = 0x08;/* ODM_WIN */ + u32 cond = condition; + + if (condition == 0xCDCDCDCD) + return true; + + cond = condition & 0xFF; + if ((_board != cond) && cond != 0xFF) + return false; + + cond = condition & 0xFF00; + cond = cond >> 8; + if ((_interface & cond) == 0 && cond != 0x07) + return false; + + cond = condition & 0xFF0000; + cond = cond >> 16; + if ((_platform & cond) == 0 && cond != 0x0F) + return false; + return true; +} + +static void _rtl8821ae_config_rf_reg(struct ieee80211_hw *hw, + u32 addr, u32 data, + enum radio_path rfpath, u32 regaddr) +{ + if (addr == 0xfe || addr == 0xffe) { + /* In order not to disturb BT music when + * wifi init.(1ant NIC only) + */ + mdelay(50); + } else { + rtl_set_rfreg(hw, rfpath, regaddr, RFREG_OFFSET_MASK, data); + udelay(1); + } +} + +static void _rtl8821ae_config_rf_radio_a(struct ieee80211_hw *hw, + u32 addr, u32 data) +{ + u32 content = 0x1000; /*RF Content: radio_a_txt*/ + u32 maskforphyset = (u32)(content & 0xE000); + + _rtl8821ae_config_rf_reg(hw, addr, data, + RF90_PATH_A, addr | maskforphyset); +} + +static void _rtl8821ae_config_rf_radio_b(struct ieee80211_hw *hw, + u32 addr, u32 data) +{ + u32 content = 0x1001; /*RF Content: radio_b_txt*/ + u32 maskforphyset = (u32)(content & 0xE000); + + _rtl8821ae_config_rf_reg(hw, addr, data, + RF90_PATH_B, addr | maskforphyset); +} + +static void _rtl8821ae_config_bb_reg(struct ieee80211_hw *hw, + u32 addr, u32 data) +{ + if (addr == 0xfe) + mdelay(50); + else if (addr == 0xfd) + mdelay(5); + else if (addr == 0xfc) + mdelay(1); + else if (addr == 0xfb) + udelay(50); + else if (addr == 0xfa) + udelay(5); + else if (addr == 0xf9) + udelay(1); + else + rtl_set_bbreg(hw, addr, MASKDWORD, data); + + udelay(1); +} + +static void _rtl8821ae_phy_init_tx_power_by_rate(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 band, rfpath, txnum, rate_section; + + for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band) + for (rfpath = 0; rfpath < TX_PWR_BY_RATE_NUM_RF; ++rfpath) + for (txnum = 0; txnum < TX_PWR_BY_RATE_NUM_RF; ++txnum) + for (rate_section = 0; + rate_section < TX_PWR_BY_RATE_NUM_SECTION; + ++rate_section) + rtlphy->tx_power_by_rate_offset[band] + [rfpath][txnum][rate_section] = 0; +} + +static void _rtl8821ae_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw, + u8 band, u8 path, + u8 rate_section, + u8 txnum, u8 value) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + if (path > RF90_PATH_D) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid Rf Path %d in phy_SetTxPowerByRatBase()\n", path); + return; + } + + if (band == BAND_ON_2_4G) { + switch (rate_section) { + case CCK: + rtlphy->txpwr_by_rate_base_24g[path][txnum][0] = value; + break; + case OFDM: + rtlphy->txpwr_by_rate_base_24g[path][txnum][1] = value; + break; + case HT_MCS0_MCS7: + rtlphy->txpwr_by_rate_base_24g[path][txnum][2] = value; + break; + case HT_MCS8_MCS15: + rtlphy->txpwr_by_rate_base_24g[path][txnum][3] = value; + break; + case VHT_1SSMCS0_1SSMCS9: + rtlphy->txpwr_by_rate_base_24g[path][txnum][4] = value; + break; + case VHT_2SSMCS0_2SSMCS9: + rtlphy->txpwr_by_rate_base_24g[path][txnum][5] = value; + break; + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid RateSection %d in Band 2.4G,Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", + rate_section, path, txnum); + break; + } + } else if (band == BAND_ON_5G) { + switch (rate_section) { + case OFDM: + rtlphy->txpwr_by_rate_base_5g[path][txnum][0] = value; + break; + case HT_MCS0_MCS7: + rtlphy->txpwr_by_rate_base_5g[path][txnum][1] = value; + break; + case HT_MCS8_MCS15: + rtlphy->txpwr_by_rate_base_5g[path][txnum][2] = value; + break; + case VHT_1SSMCS0_1SSMCS9: + rtlphy->txpwr_by_rate_base_5g[path][txnum][3] = value; + break; + case VHT_2SSMCS0_2SSMCS9: + rtlphy->txpwr_by_rate_base_5g[path][txnum][4] = value; + break; + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", + rate_section, path, txnum); + break; + } + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid Band %d in PHY_SetTxPowerByRateBase()\n", band); + } +} + +static u8 _rtl8821ae_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw, + u8 band, u8 path, + u8 txnum, u8 rate_section) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 value = 0; + + if (path > RF90_PATH_D) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid Rf Path %d in PHY_GetTxPowerByRateBase()\n", + path); + return 0; + } + + if (band == BAND_ON_2_4G) { + switch (rate_section) { + case CCK: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][0]; + break; + case OFDM: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][1]; + break; + case HT_MCS0_MCS7: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][2]; + break; + case HT_MCS8_MCS15: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][3]; + break; + case VHT_1SSMCS0_1SSMCS9: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][4]; + break; + case VHT_2SSMCS0_2SSMCS9: + value = rtlphy->txpwr_by_rate_base_24g[path][txnum][5]; + break; + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", + rate_section, path, txnum); + break; + } + } else if (band == BAND_ON_5G) { + switch (rate_section) { + case OFDM: + value = rtlphy->txpwr_by_rate_base_5g[path][txnum][0]; + break; + case HT_MCS0_MCS7: + value = rtlphy->txpwr_by_rate_base_5g[path][txnum][1]; + break; + case HT_MCS8_MCS15: + value = rtlphy->txpwr_by_rate_base_5g[path][txnum][2]; + break; + case VHT_1SSMCS0_1SSMCS9: + value = rtlphy->txpwr_by_rate_base_5g[path][txnum][3]; + break; + case VHT_2SSMCS0_2SSMCS9: + value = rtlphy->txpwr_by_rate_base_5g[path][txnum][4]; + break; + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", + rate_section, path, txnum); + break; + } + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Invalid Band %d in PHY_GetTxPowerByRateBase()\n", band); + } + + return value; +} + +static void _rtl8821ae_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u16 rawValue = 0; + u8 base = 0, path = 0; + + for (path = RF90_PATH_A; path <= RF90_PATH_B; ++path) { + rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][0] >> 24) & 0xFF; + base = (rawValue >> 4) * 10 + (rawValue & 0xF); + _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, CCK, RF_1TX, base); + + rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][2] >> 24) & 0xFF; + base = (rawValue >> 4) * 10 + (rawValue & 0xF); + _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, OFDM, RF_1TX, base); + + rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][4] >> 24) & 0xFF; + base = (rawValue >> 4) * 10 + (rawValue & 0xF); + _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, HT_MCS0_MCS7, RF_1TX, base); + + rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_2TX][6] >> 24) & 0xFF; + base = (rawValue >> 4) * 10 + (rawValue & 0xF); + _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, HT_MCS8_MCS15, RF_2TX, base); + + rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][8] >> 24) & 0xFF; + base = (rawValue >> 4) * 10 + (rawValue & 0xF); + _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, VHT_1SSMCS0_1SSMCS9, RF_1TX, base); + + rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_2TX][11] >> 8) & 0xFF; + base = (rawValue >> 4) * 10 + (rawValue & 0xF); + _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, VHT_2SSMCS0_2SSMCS9, RF_2TX, base); + + rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][2] >> 24) & 0xFF; + base = (rawValue >> 4) * 10 + (rawValue & 0xF); + _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, OFDM, RF_1TX, base); + + rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][4] >> 24) & 0xFF; + base = (rawValue >> 4) * 10 + (rawValue & 0xF); + _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, HT_MCS0_MCS7, RF_1TX, base); + + rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_2TX][6] >> 24) & 0xFF; + base = (rawValue >> 4) * 10 + (rawValue & 0xF); + _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, HT_MCS8_MCS15, RF_2TX, base); + + rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][8] >> 24) & 0xFF; + base = (rawValue >> 4) * 10 + (rawValue & 0xF); + _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, VHT_1SSMCS0_1SSMCS9, RF_1TX, base); + + rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_2TX][11] >> 8) & 0xFF; + base = (rawValue >> 4) * 10 + (rawValue & 0xF); + _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, VHT_2SSMCS0_2SSMCS9, RF_2TX, base); + } +} + +static void _phy_convert_txpower_dbm_to_relative_value(u32 *data, u8 start, + u8 end, u8 base_val) +{ + char i = 0; + u8 temp_value = 0; + u32 temp_data = 0; + + for (i = 3; i >= 0; --i) { + if (i >= start && i <= end) { + /* Get the exact value */ + temp_value = (u8)(*data >> (i * 8)) & 0xF; + temp_value += ((u8)((*data >> (i * 8 + 4)) & 0xF)) * 10; + + /* Change the value to a relative value */ + temp_value = (temp_value > base_val) ? temp_value - + base_val : base_val - temp_value; + } else { + temp_value = (u8)(*data >> (i * 8)) & 0xFF; + } + temp_data <<= 8; + temp_data |= temp_value; + } + *data = temp_data; +} + +static void _rtl8812ae_phy_cross_reference_ht_and_vht_txpower_limit(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 regulation, bw, channel, rate_section; + char temp_pwrlmt = 0; + + for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) { + for (bw = 0; bw < MAX_5G_BANDWITH_NUM; ++bw) { + for (channel = 0; channel < CHANNEL_MAX_NUMBER_5G; ++channel) { + for (rate_section = 0; rate_section < MAX_RATE_SECTION_NUM; ++rate_section) { + temp_pwrlmt = rtlphy->txpwr_limit_5g[regulation] + [bw][rate_section][channel][RF90_PATH_A]; + if (temp_pwrlmt == MAX_POWER_INDEX) { + if (bw == 0 || bw == 1) { /*5G 20M 40M VHT and HT can cross reference*/ + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "No power limit table of the specified band %d, bandwidth %d, ratesection %d, channel %d, rf path %d\n", + 1, bw, rate_section, channel, RF90_PATH_A); + if (rate_section == 2) { + rtlphy->txpwr_limit_5g[regulation][bw][2][channel][RF90_PATH_A] = + rtlphy->txpwr_limit_5g[regulation][bw][4][channel][RF90_PATH_A]; + } else if (rate_section == 4) { + rtlphy->txpwr_limit_5g[regulation][bw][4][channel][RF90_PATH_A] = + rtlphy->txpwr_limit_5g[regulation][bw][2][channel][RF90_PATH_A]; + } else if (rate_section == 3) { + rtlphy->txpwr_limit_5g[regulation][bw][3][channel][RF90_PATH_A] = + rtlphy->txpwr_limit_5g[regulation][bw][5][channel][RF90_PATH_A]; + } else if (rate_section == 5) { + rtlphy->txpwr_limit_5g[regulation][bw][5][channel][RF90_PATH_A] = + rtlphy->txpwr_limit_5g[regulation][bw][3][channel][RF90_PATH_A]; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "use other value %d", temp_pwrlmt); + } + } + } + } + } + } +} + +static u8 _rtl8812ae_phy_get_txpower_by_rate_base_index(struct ieee80211_hw *hw, + enum band_type band, u8 rate) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 index = 0; + if (band == BAND_ON_2_4G) { + switch (rate) { + case MGN_1M: + case MGN_2M: + case MGN_5_5M: + case MGN_11M: + index = 0; + break; + + case MGN_6M: + case MGN_9M: + case MGN_12M: + case MGN_18M: + case MGN_24M: + case MGN_36M: + case MGN_48M: + case MGN_54M: + index = 1; + break; + + case MGN_MCS0: + case MGN_MCS1: + case MGN_MCS2: + case MGN_MCS3: + case MGN_MCS4: + case MGN_MCS5: + case MGN_MCS6: + case MGN_MCS7: + index = 2; + break; + + case MGN_MCS8: + case MGN_MCS9: + case MGN_MCS10: + case MGN_MCS11: + case MGN_MCS12: + case MGN_MCS13: + case MGN_MCS14: + case MGN_MCS15: + index = 3; + break; + + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Wrong rate 0x%x to obtain index in 2.4G in PHY_GetTxPowerByRateBaseIndex()\n", + rate); + break; + } + } else if (band == BAND_ON_5G) { + switch (rate) { + case MGN_6M: + case MGN_9M: + case MGN_12M: + case MGN_18M: + case MGN_24M: + case MGN_36M: + case MGN_48M: + case MGN_54M: + index = 0; + break; + + case MGN_MCS0: + case MGN_MCS1: + case MGN_MCS2: + case MGN_MCS3: + case MGN_MCS4: + case MGN_MCS5: + case MGN_MCS6: + case MGN_MCS7: + index = 1; + break; + + case MGN_MCS8: + case MGN_MCS9: + case MGN_MCS10: + case MGN_MCS11: + case MGN_MCS12: + case MGN_MCS13: + case MGN_MCS14: + case MGN_MCS15: + index = 2; + break; + + case MGN_VHT1SS_MCS0: + case MGN_VHT1SS_MCS1: + case MGN_VHT1SS_MCS2: + case MGN_VHT1SS_MCS3: + case MGN_VHT1SS_MCS4: + case MGN_VHT1SS_MCS5: + case MGN_VHT1SS_MCS6: + case MGN_VHT1SS_MCS7: + case MGN_VHT1SS_MCS8: + case MGN_VHT1SS_MCS9: + index = 3; + break; + + case MGN_VHT2SS_MCS0: + case MGN_VHT2SS_MCS1: + case MGN_VHT2SS_MCS2: + case MGN_VHT2SS_MCS3: + case MGN_VHT2SS_MCS4: + case MGN_VHT2SS_MCS5: + case MGN_VHT2SS_MCS6: + case MGN_VHT2SS_MCS7: + case MGN_VHT2SS_MCS8: + case MGN_VHT2SS_MCS9: + index = 4; + break; + + default: + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Wrong rate 0x%x to obtain index in 5G in PHY_GetTxPowerByRateBaseIndex()\n", + rate); + break; + } + } + + return index; +} + +static void _rtl8812ae_phy_convert_txpower_limit_to_power_index(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 bw40_pwr_base_dbm2_4G, bw40_pwr_base_dbm5G; + u8 regulation, bw, channel, rate_section; + u8 base_index2_4G = 0; + u8 base_index5G = 0; + char temp_value = 0, temp_pwrlmt = 0; + u8 rf_path = 0; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "=====> _rtl8812ae_phy_convert_txpower_limit_to_power_index()\n"); + + _rtl8812ae_phy_cross_reference_ht_and_vht_txpower_limit(hw); + + for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) { + for (bw = 0; bw < MAX_2_4G_BANDWITH_NUM; ++bw) { + for (channel = 0; channel < CHANNEL_MAX_NUMBER_2G; ++channel) { + for (rate_section = 0; rate_section < MAX_RATE_SECTION_NUM; ++rate_section) { + /* obtain the base dBm values in 2.4G band + CCK => 11M, OFDM => 54M, HT 1T => MCS7, HT 2T => MCS15*/ + if (rate_section == 0) { /*CCK*/ + base_index2_4G = + _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, + BAND_ON_2_4G, MGN_11M); + } else if (rate_section == 1) { /*OFDM*/ + base_index2_4G = + _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, + BAND_ON_2_4G, MGN_54M); + } else if (rate_section == 2) { /*HT IT*/ + base_index2_4G = + _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, + BAND_ON_2_4G, MGN_MCS7); + } else if (rate_section == 3) { /*HT 2T*/ + base_index2_4G = + _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, + BAND_ON_2_4G, MGN_MCS15); + } + + temp_pwrlmt = rtlphy->txpwr_limit_2_4g[regulation] + [bw][rate_section][channel][RF90_PATH_A]; + + for (rf_path = RF90_PATH_A; + rf_path < MAX_RF_PATH_NUM; + ++rf_path) { + if (rate_section == 3) + bw40_pwr_base_dbm2_4G = + rtlphy->txpwr_by_rate_base_24g[rf_path][RF_2TX][base_index2_4G]; + else + bw40_pwr_base_dbm2_4G = + rtlphy->txpwr_by_rate_base_24g[rf_path][RF_1TX][base_index2_4G]; + + if (temp_pwrlmt != MAX_POWER_INDEX) { + temp_value = temp_pwrlmt - bw40_pwr_base_dbm2_4G; + rtlphy->txpwr_limit_2_4g[regulation] + [bw][rate_section][channel][rf_path] = + temp_value; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "TxPwrLimit_2_4G[regulation %d][bw %d][rateSection %d][channel %d] = %d\n(TxPwrLimit in dBm %d - BW40PwrLmt2_4G[channel %d][rfPath %d] %d)\n", + regulation, bw, rate_section, channel, + rtlphy->txpwr_limit_2_4g[regulation][bw] + [rate_section][channel][rf_path], (temp_pwrlmt == 63) + ? 0 : temp_pwrlmt/2, channel, rf_path, + bw40_pwr_base_dbm2_4G); + } + } + } + } + } + for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) { + for (bw = 0; bw < MAX_5G_BANDWITH_NUM; ++bw) { + for (channel = 0; channel < CHANNEL_MAX_NUMBER_5G; ++channel) { + for (rate_section = 0; rate_section < MAX_RATE_SECTION_NUM; ++rate_section) { + /* obtain the base dBm values in 5G band + OFDM => 54M, HT 1T => MCS7, HT 2T => MCS15, + VHT => 1SSMCS7, VHT 2T => 2SSMCS7*/ + if (rate_section == 1) { /*OFDM*/ + base_index5G = + _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, + BAND_ON_5G, MGN_54M); + } else if (rate_section == 2) { /*HT 1T*/ + base_index5G = + _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, + BAND_ON_5G, MGN_MCS7); + } else if (rate_section == 3) { /*HT 2T*/ + base_index5G = + _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, + BAND_ON_5G, MGN_MCS15); + } else if (rate_section == 4) { /*VHT 1T*/ + base_index5G = + _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, + BAND_ON_5G, MGN_VHT1SS_MCS7); + } else if (rate_section == 5) { /*VHT 2T*/ + base_index5G = + _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, + BAND_ON_5G, MGN_VHT2SS_MCS7); + } + + temp_pwrlmt = rtlphy->txpwr_limit_5g[regulation] + [bw][rate_section][channel] + [RF90_PATH_A]; + + for (rf_path = RF90_PATH_A; + rf_path < MAX_RF_PATH_NUM; + ++rf_path) { + if (rate_section == 3 || rate_section == 5) + bw40_pwr_base_dbm5G = + rtlphy->txpwr_by_rate_base_5g[rf_path] + [RF_2TX][base_index5G]; + else + bw40_pwr_base_dbm5G = + rtlphy->txpwr_by_rate_base_5g[rf_path] + [RF_1TX][base_index5G]; + + if (temp_pwrlmt != MAX_POWER_INDEX) { + temp_value = + temp_pwrlmt - bw40_pwr_base_dbm5G; + rtlphy->txpwr_limit_5g[regulation] + [bw][rate_section][channel] + [rf_path] = temp_value; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "TxPwrLimit_5G[regulation %d][bw %d][rateSection %d][channel %d] =%d\n(TxPwrLimit in dBm %d - BW40PwrLmt5G[chnl group %d][rfPath %d] %d)\n", + regulation, bw, rate_section, + channel, rtlphy->txpwr_limit_5g[regulation] + [bw][rate_section][channel][rf_path], + temp_pwrlmt, channel, rf_path, bw40_pwr_base_dbm5G); + } + } + } + } + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "<===== _rtl8812ae_phy_convert_txpower_limit_to_power_index()\n"); +} + +static void _rtl8821ae_phy_init_txpower_limit(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 i, j, k, l, m; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "=====> _rtl8821ae_phy_init_txpower_limit()!\n"); + + for (i = 0; i < MAX_REGULATION_NUM; ++i) { + for (j = 0; j < MAX_2_4G_BANDWITH_NUM; ++j) + for (k = 0; k < MAX_RATE_SECTION_NUM; ++k) + for (m = 0; m < CHANNEL_MAX_NUMBER_2G; ++m) + for (l = 0; l < MAX_RF_PATH_NUM; ++l) + rtlphy->txpwr_limit_2_4g + [i][j][k][m][l] + = MAX_POWER_INDEX; + } + for (i = 0; i < MAX_REGULATION_NUM; ++i) { + for (j = 0; j < MAX_5G_BANDWITH_NUM; ++j) + for (k = 0; k < MAX_RATE_SECTION_NUM; ++k) + for (m = 0; m < CHANNEL_MAX_NUMBER_5G; ++m) + for (l = 0; l < MAX_RF_PATH_NUM; ++l) + rtlphy->txpwr_limit_5g + [i][j][k][m][l] + = MAX_POWER_INDEX; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "<===== _rtl8821ae_phy_init_txpower_limit()!\n"); +} + +static void _rtl8821ae_phy_convert_txpower_dbm_to_relative_value(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 base = 0, rfPath = 0; + + for (rfPath = RF90_PATH_A; rfPath <= RF90_PATH_B; ++rfPath) { + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, CCK); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][0], + 0, 3, base); + + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, OFDM); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][1], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][2], + 0, 3, base); + + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, HT_MCS0_MCS7); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][3], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][4], + 0, 3, base); + + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_2TX, HT_MCS8_MCS15); + + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][5], + 0, 3, base); + + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][6], + 0, 3, base); + + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, VHT_1SSMCS0_1SSMCS9); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][7], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][8], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][9], + 0, 1, base); + + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_2TX, VHT_2SSMCS0_2SSMCS9); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][9], + 2, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][10], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][11], + 0, 3, base); + + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_1TX, OFDM); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][1], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][2], + 0, 3, base); + + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_1TX, HT_MCS0_MCS7); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][3], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][4], + 0, 3, base); + + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_2TX, HT_MCS8_MCS15); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][5], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][6], + 0, 3, base); + + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_1TX, VHT_1SSMCS0_1SSMCS9); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][7], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][8], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][9], + 0, 1, base); + + base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_2TX, VHT_2SSMCS0_2SSMCS9); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][9], + 2, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][10], + 0, 3, base); + _phy_convert_txpower_dbm_to_relative_value( + &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][11], + 0, 3, base); + } + + RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, + "<===_rtl8821ae_phy_convert_txpower_dbm_to_relative_value()\n"); +} + +static void _rtl8821ae_phy_txpower_by_rate_configuration(struct ieee80211_hw *hw) +{ + _rtl8821ae_phy_store_txpower_by_rate_base(hw); + _rtl8821ae_phy_convert_txpower_dbm_to_relative_value(hw); +} + +/* string is in decimal */ +static bool _rtl8812ae_get_integer_from_string(char *str, u8 *pint) +{ + u16 i = 0; + *pint = 0; + + while (str[i] != '\0') { + if (str[i] >= '0' && str[i] <= '9') { + *pint *= 10; + *pint += (str[i] - '0'); + } else { + return false; + } + ++i; + } + + return true; +} + +static bool _rtl8812ae_eq_n_byte(u8 *str1, u8 *str2, u32 num) +{ + if (num == 0) + return false; + while (num > 0) { + num--; + if (str1[num] != str2[num]) + return false; + } + return true; +} + +static char _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(struct ieee80211_hw *hw, + u8 band, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + char channel_index = -1; + u8 channel_5g[CHANNEL_MAX_NUMBER_5G] = { + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, + 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, + 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 149, + 151, 153, 155, 157, 159, 161, 163, 165, 167, 168, 169, 171, + 173, 175, 177}; + u8 i = 0; + if (band == BAND_ON_2_4G) + channel_index = channel - 1; + else if (band == BAND_ON_5G) { + for (i = 0; i < sizeof(channel_5g)/sizeof(u8); ++i) { + if (channel_5g[i] == channel) + channel_index = i; + } + } else + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Invalid Band %d in %s", + band, __func__); + + if (channel_index == -1) + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Invalid Channel %d of Band %d in %s", channel, + band, __func__); + + return channel_index; +} + +static void _rtl8812ae_phy_set_txpower_limit(struct ieee80211_hw *hw, u8 *pregulation, + u8 *pband, u8 *pbandwidth, + u8 *prate_section, u8 *prf_path, + u8 *pchannel, u8 *ppower_limit) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 regulation = 0, bandwidth = 0, rate_section = 0, channel; + u8 channel_index; + char power_limit = 0, prev_power_limit, ret; + + if (!_rtl8812ae_get_integer_from_string((char *)pchannel, &channel) || + !_rtl8812ae_get_integer_from_string((char *)ppower_limit, + &power_limit)) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Illegal index of pwr_lmt table [chnl %d][val %d]\n", + channel, power_limit); + } + + power_limit = power_limit > MAX_POWER_INDEX ? + MAX_POWER_INDEX : power_limit; + + if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("FCC"), 3)) + regulation = 0; + else if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("MKK"), 3)) + regulation = 1; + else if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("ETSI"), 4)) + regulation = 2; + else if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("WW13"), 4)) + regulation = 3; + + if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("CCK"), 3)) + rate_section = 0; + else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("OFDM"), 4)) + rate_section = 1; + else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("HT"), 2) && + _rtl8812ae_eq_n_byte(prf_path, (u8 *)("1T"), 2)) + rate_section = 2; + else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("HT"), 2) && + _rtl8812ae_eq_n_byte(prf_path, (u8 *)("2T"), 2)) + rate_section = 3; + else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("VHT"), 3) && + _rtl8812ae_eq_n_byte(prf_path, (u8 *)("1T"), 2)) + rate_section = 4; + else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("VHT"), 3) && + _rtl8812ae_eq_n_byte(prf_path, (u8 *)("2T"), 2)) + rate_section = 5; + + if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("20M"), 3)) + bandwidth = 0; + else if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("40M"), 3)) + bandwidth = 1; + else if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("80M"), 3)) + bandwidth = 2; + else if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("160M"), 4)) + bandwidth = 3; + + if (_rtl8812ae_eq_n_byte(pband, (u8 *)("2.4G"), 4)) { + ret = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw, + BAND_ON_2_4G, + channel); + + if (ret == -1) + return; + + channel_index = ret; + + prev_power_limit = rtlphy->txpwr_limit_2_4g[regulation] + [bandwidth][rate_section] + [channel_index][RF90_PATH_A]; + + if (power_limit < prev_power_limit) + rtlphy->txpwr_limit_2_4g[regulation][bandwidth] + [rate_section][channel_index][RF90_PATH_A] = + power_limit; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "2.4G [regula %d][bw %d][sec %d][chnl %d][val %d]\n", + regulation, bandwidth, rate_section, channel_index, + rtlphy->txpwr_limit_2_4g[regulation][bandwidth] + [rate_section][channel_index][RF90_PATH_A]); + } else if (_rtl8812ae_eq_n_byte(pband, (u8 *)("5G"), 2)) { + ret = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw, + BAND_ON_5G, + channel); + + if (ret == -1) + return; + + channel_index = ret; + + prev_power_limit = rtlphy->txpwr_limit_5g[regulation][bandwidth] + [rate_section][channel_index] + [RF90_PATH_A]; + + if (power_limit < prev_power_limit) + rtlphy->txpwr_limit_5g[regulation][bandwidth] + [rate_section][channel_index][RF90_PATH_A] = power_limit; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "5G: [regul %d][bw %d][sec %d][chnl %d][val %d]\n", + regulation, bandwidth, rate_section, channel, + rtlphy->txpwr_limit_5g[regulation][bandwidth] + [rate_section][channel_index][RF90_PATH_A]); + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Cannot recognize the band info in %s\n", pband); + return; + } +} + +static void _rtl8812ae_phy_config_bb_txpwr_lmt(struct ieee80211_hw *hw, + u8 *regulation, u8 *band, + u8 *bandwidth, u8 *rate_section, + u8 *rf_path, u8 *channel, + u8 *power_limit) +{ + _rtl8812ae_phy_set_txpower_limit(hw, regulation, band, bandwidth, + rate_section, rf_path, channel, + power_limit); +} + +static void _rtl8821ae_phy_read_and_config_txpwr_lmt(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u32 i = 0; + u32 array_len; + u8 **array; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + array_len = RTL8812AE_TXPWR_LMT_ARRAY_LEN; + array = RTL8812AE_TXPWR_LMT; + } else { + array_len = RTL8821AE_TXPWR_LMT_ARRAY_LEN; + array = RTL8821AE_TXPWR_LMT; + } + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "\n"); + + for (i = 0; i < array_len; i += 7) { + u8 *regulation = array[i]; + u8 *band = array[i+1]; + u8 *bandwidth = array[i+2]; + u8 *rate = array[i+3]; + u8 *rf_path = array[i+4]; + u8 *chnl = array[i+5]; + u8 *val = array[i+6]; + + _rtl8812ae_phy_config_bb_txpwr_lmt(hw, regulation, band, + bandwidth, rate, rf_path, + chnl, val); + } +} + +static bool _rtl8821ae_phy_bb8821a_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + bool rtstatus; + + _rtl8821ae_phy_init_txpower_limit(hw); + + /* RegEnableTxPowerLimit == 1 for 8812a & 8821a */ + if (rtlefuse->eeprom_regulatory != 2) + _rtl8821ae_phy_read_and_config_txpwr_lmt(hw); + + rtstatus = _rtl8821ae_phy_config_bb_with_headerfile(hw, + BASEBAND_CONFIG_PHY_REG); + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); + return false; + } + _rtl8821ae_phy_init_tx_power_by_rate(hw); + if (rtlefuse->autoload_failflag == false) { + rtstatus = _rtl8821ae_phy_config_bb_with_pgheaderfile(hw, + BASEBAND_CONFIG_PHY_REG); + } + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); + return false; + } + + _rtl8821ae_phy_txpower_by_rate_configuration(hw); + + /* RegEnableTxPowerLimit == 1 for 8812a & 8821a */ + if (rtlefuse->eeprom_regulatory != 2) + _rtl8812ae_phy_convert_txpower_limit_to_power_index(hw); + + rtstatus = _rtl8821ae_phy_config_bb_with_headerfile(hw, + BASEBAND_CONFIG_AGC_TAB); + + if (rtstatus != true) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); + return false; + } + rtlphy->cck_high_power = (bool)(rtl_get_bbreg(hw, + RFPGA0_XA_HSSIPARAMETER2, 0x200)); + return true; +} + +static bool _rtl8821ae_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u32 i, v1, v2; + u32 arraylength; + u32 *ptrarray; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read MAC_REG_Array\n"); + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + arraylength = RTL8821AEMAC_1T_ARRAYLEN; + ptrarray = RTL8821AE_MAC_REG_ARRAY; + } else { + arraylength = RTL8812AEMAC_1T_ARRAYLEN; + ptrarray = RTL8812AE_MAC_REG_ARRAY; + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Img: MAC_REG_ARRAY LEN %d\n", arraylength); + for (i = 0; i < arraylength; i += 2) { + v1 = ptrarray[i]; + v2 = (u8)ptrarray[i + 1]; + if (v1 < 0xCDCDCDCD) { + rtl_write_byte(rtlpriv, v1, (u8)v2); + continue; + } else { + if (!_rtl8821ae_check_condition(hw, v1)) { + /*Discard the following (offset, data) pairs*/ + READ_NEXT_PAIR(ptrarray, v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < arraylength - 2) { + READ_NEXT_PAIR(ptrarray, v1, v2, i); + } + i -= 2; /* prevent from for-loop += 2*/ + } else {/*Configure matched pairs and skip to end of if-else.*/ + READ_NEXT_PAIR(ptrarray, v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < arraylength - 2) { + rtl_write_byte(rtlpriv, v1, v2); + READ_NEXT_PAIR(ptrarray, v1, v2, i); + } + + while (v2 != 0xDEAD && i < arraylength - 2) + READ_NEXT_PAIR(ptrarray, v1, v2, i); + } + } + } + return true; +} + +static bool _rtl8821ae_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, + u8 configtype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + int i; + u32 *array_table; + u16 arraylen; + u32 v1 = 0, v2 = 0; + + if (configtype == BASEBAND_CONFIG_PHY_REG) { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + arraylen = RTL8812AEPHY_REG_1TARRAYLEN; + array_table = RTL8812AE_PHY_REG_ARRAY; + } else { + arraylen = RTL8821AEPHY_REG_1TARRAYLEN; + array_table = RTL8821AE_PHY_REG_ARRAY; + } + + for (i = 0; i < arraylen; i += 2) { + v1 = array_table[i]; + v2 = array_table[i + 1]; + if (v1 < 0xCDCDCDCD) { + _rtl8821ae_config_bb_reg(hw, v1, v2); + continue; + } else {/*This line is the start line of branch.*/ + if (!_rtl8821ae_check_condition(hw, v1)) { + /*Discard the following (offset, data) pairs*/ + READ_NEXT_PAIR(array_table, v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < arraylen - 2) { + READ_NEXT_PAIR(array_table, v1, + v2, i); + } + + i -= 2; /* prevent from for-loop += 2*/ + } else {/*Configure matched pairs and skip to end of if-else.*/ + READ_NEXT_PAIR(array_table, v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < arraylen - 2) { + _rtl8821ae_config_bb_reg(hw, v1, + v2); + READ_NEXT_PAIR(array_table, v1, + v2, i); + } + + while (v2 != 0xDEAD && + i < arraylen - 2) { + READ_NEXT_PAIR(array_table, v1, + v2, i); + } + } + } + } + } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + arraylen = RTL8812AEAGCTAB_1TARRAYLEN; + array_table = RTL8812AE_AGC_TAB_ARRAY; + } else { + arraylen = RTL8821AEAGCTAB_1TARRAYLEN; + array_table = RTL8821AE_AGC_TAB_ARRAY; + } + + for (i = 0; i < arraylen; i = i + 2) { + v1 = array_table[i]; + v2 = array_table[i+1]; + if (v1 < 0xCDCDCDCD) { + rtl_set_bbreg(hw, v1, MASKDWORD, v2); + udelay(1); + continue; + } else {/*This line is the start line of branch.*/ + if (!_rtl8821ae_check_condition(hw, v1)) { + /*Discard the following (offset, data) pairs*/ + READ_NEXT_PAIR(array_table, v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < arraylen - 2) { + READ_NEXT_PAIR(array_table, v1, + v2, i); + } + i -= 2; /* prevent from for-loop += 2*/ + } else {/*Configure matched pairs and skip to end of if-else.*/ + READ_NEXT_PAIR(array_table, v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && + i < arraylen - 2) { + rtl_set_bbreg(hw, v1, MASKDWORD, + v2); + udelay(1); + READ_NEXT_PAIR(array_table, v1, + v2, i); + } + + while (v2 != 0xDEAD && + i < arraylen - 2) { + READ_NEXT_PAIR(array_table, v1, + v2, i); + } + } + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "The agctab_array_table[0] is %x Rtl818EEPHY_REGArray[1] is %x\n", + array_table[i], array_table[i + 1]); + } + } + } + return true; +} + +static u8 _rtl8821ae_get_rate_section_index(u32 regaddr) +{ + u8 index = 0; + regaddr &= 0xFFF; + if (regaddr >= 0xC20 && regaddr <= 0xC4C) + index = (u8)((regaddr - 0xC20) / 4); + else if (regaddr >= 0xE20 && regaddr <= 0xE4C) + index = (u8)((regaddr - 0xE20) / 4); + else + RT_ASSERT(!COMP_INIT, + "Invalid RegAddr 0x%x\n", regaddr); + return index; +} + +static void _rtl8821ae_store_tx_power_by_rate(struct ieee80211_hw *hw, + u32 band, u32 rfpath, + u32 txnum, u32 regaddr, + u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 rate_section = _rtl8821ae_get_rate_section_index(regaddr); + + if (band != BAND_ON_2_4G && band != BAND_ON_5G) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid Band %d\n", band); + band = BAND_ON_2_4G; + } + if (rfpath >= MAX_RF_PATH) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid RfPath %d\n", rfpath); + rfpath = MAX_RF_PATH - 1; + } + if (txnum >= MAX_RF_PATH) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid TxNum %d\n", txnum); + txnum = MAX_RF_PATH - 1; + } + rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "TxPwrByRateOffset[Band %d][RfPath %d][TxNum %d][RateSection %d] = 0x%x\n", + band, rfpath, txnum, rate_section, + rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section]); +} + +static bool _rtl8821ae_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, + u8 configtype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + int i; + u32 *array; + u16 arraylen; + u32 v1, v2, v3, v4, v5, v6; + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + arraylen = RTL8812AEPHY_REG_ARRAY_PGLEN; + array = RTL8812AE_PHY_REG_ARRAY_PG; + } else { + arraylen = RTL8821AEPHY_REG_ARRAY_PGLEN; + array = RTL8821AE_PHY_REG_ARRAY_PG; + } + + if (configtype != BASEBAND_CONFIG_PHY_REG) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "configtype != BaseBand_Config_PHY_REG\n"); + return true; + } + for (i = 0; i < arraylen; i += 6) { + v1 = array[i]; + v2 = array[i+1]; + v3 = array[i+2]; + v4 = array[i+3]; + v5 = array[i+4]; + v6 = array[i+5]; + + if (v1 < 0xCDCDCDCD) { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE && + (v4 == 0xfe || v4 == 0xffe)) { + msleep(50); + continue; + } + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + if (v4 == 0xfe) + msleep(50); + else if (v4 == 0xfd) + mdelay(5); + else if (v4 == 0xfc) + mdelay(1); + else if (v4 == 0xfb) + udelay(50); + else if (v4 == 0xfa) + udelay(5); + else if (v4 == 0xf9) + udelay(1); + } + _rtl8821ae_store_tx_power_by_rate(hw, v1, v2, v3, + v4, v5, v6); + continue; + } else { + /*don't need the hw_body*/ + if (!_rtl8821ae_check_condition(hw, v1)) { + i += 2; /* skip the pair of expression*/ + v1 = array[i]; + v2 = array[i+1]; + v3 = array[i+2]; + while (v2 != 0xDEAD) { + i += 3; + v1 = array[i]; + v2 = array[i+1]; + v3 = array[i+2]; + } + } + } + } + + return true; +} + +bool rtl8812ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath) +{ + int i; + bool rtstatus = true; + u32 *radioa_array_table_a, *radioa_array_table_b; + u16 radioa_arraylen_a, radioa_arraylen_b; + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 v1 = 0, v2 = 0; + + radioa_arraylen_a = RTL8812AE_RADIOA_1TARRAYLEN; + radioa_array_table_a = RTL8812AE_RADIOA_ARRAY; + radioa_arraylen_b = RTL8812AE_RADIOB_1TARRAYLEN; + radioa_array_table_b = RTL8812AE_RADIOB_ARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Radio_A:RTL8821AE_RADIOA_ARRAY %d\n", radioa_arraylen_a); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); + rtstatus = true; + switch (rfpath) { + case RF90_PATH_A: + for (i = 0; i < radioa_arraylen_a; i = i + 2) { + v1 = radioa_array_table_a[i]; + v2 = radioa_array_table_a[i+1]; + if (v1 < 0xcdcdcdcd) { + _rtl8821ae_config_rf_radio_a(hw, v1, v2); + continue; + } else{/*This line is the start line of branch.*/ + if (!_rtl8821ae_check_condition(hw, v1)) { + /*Discard the following (offset, data) pairs*/ + READ_NEXT_PAIR(radioa_array_table_a, v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < radioa_arraylen_a-2) + READ_NEXT_PAIR(radioa_array_table_a, v1, v2, i); + + i -= 2; /* prevent from for-loop += 2*/ + } else {/*Configure matched pairs and skip to end of if-else.*/ + READ_NEXT_PAIR(radioa_array_table_a, v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < radioa_arraylen_a - 2) { + _rtl8821ae_config_rf_radio_a(hw, v1, v2); + READ_NEXT_PAIR(radioa_array_table_a, v1, v2, i); + } + + while (v2 != 0xDEAD && i < radioa_arraylen_a-2) + READ_NEXT_PAIR(radioa_array_table_a, v1, v2, i); + + } + } + } + break; + case RF90_PATH_B: + for (i = 0; i < radioa_arraylen_b; i = i + 2) { + v1 = radioa_array_table_b[i]; + v2 = radioa_array_table_b[i+1]; + if (v1 < 0xcdcdcdcd) { + _rtl8821ae_config_rf_radio_b(hw, v1, v2); + continue; + } else{/*This line is the start line of branch.*/ + if (!_rtl8821ae_check_condition(hw, v1)) { + /*Discard the following (offset, data) pairs*/ + READ_NEXT_PAIR(radioa_array_table_b, v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < radioa_arraylen_b-2) + READ_NEXT_PAIR(radioa_array_table_b, v1, v2, i); + + i -= 2; /* prevent from for-loop += 2*/ + } else {/*Configure matched pairs and skip to end of if-else.*/ + READ_NEXT_PAIR(radioa_array_table_b, v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < radioa_arraylen_b-2) { + _rtl8821ae_config_rf_radio_b(hw, v1, v2); + READ_NEXT_PAIR(radioa_array_table_b, v1, v2, i); + } + + while (v2 != 0xDEAD && i < radioa_arraylen_b-2) + READ_NEXT_PAIR(radioa_array_table_b, v1, v2, i); + } + } + } + break; + case RF90_PATH_C: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + case RF90_PATH_D: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + return true; +} + +bool rtl8821ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath) +{ + #define READ_NEXT_RF_PAIR(v1, v2, i) \ + do { \ + i += 2; \ + v1 = radioa_array_table[i]; \ + v2 = radioa_array_table[i+1]; \ + } \ + while (0) + + int i; + bool rtstatus = true; + u32 *radioa_array_table; + u16 radioa_arraylen; + struct rtl_priv *rtlpriv = rtl_priv(hw); + /* struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); */ + u32 v1 = 0, v2 = 0; + + radioa_arraylen = RTL8821AE_RADIOA_1TARRAYLEN; + radioa_array_table = RTL8821AE_RADIOA_ARRAY; + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "Radio_A:RTL8821AE_RADIOA_ARRAY %d\n", radioa_arraylen); + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); + rtstatus = true; + switch (rfpath) { + case RF90_PATH_A: + for (i = 0; i < radioa_arraylen; i = i + 2) { + v1 = radioa_array_table[i]; + v2 = radioa_array_table[i+1]; + if (v1 < 0xcdcdcdcd) + _rtl8821ae_config_rf_radio_a(hw, v1, v2); + else{/*This line is the start line of branch.*/ + if (!_rtl8821ae_check_condition(hw, v1)) { + /*Discard the following (offset, data) pairs*/ + READ_NEXT_RF_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < radioa_arraylen - 2) + READ_NEXT_RF_PAIR(v1, v2, i); + + i -= 2; /* prevent from for-loop += 2*/ + } else {/*Configure matched pairs and skip to end of if-else.*/ + READ_NEXT_RF_PAIR(v1, v2, i); + while (v2 != 0xDEAD && + v2 != 0xCDEF && + v2 != 0xCDCD && i < radioa_arraylen - 2) { + _rtl8821ae_config_rf_radio_a(hw, v1, v2); + READ_NEXT_RF_PAIR(v1, v2, i); + } + + while (v2 != 0xDEAD && i < radioa_arraylen - 2) + READ_NEXT_RF_PAIR(v1, v2, i); + } + } + } + break; + + case RF90_PATH_B: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + case RF90_PATH_C: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + case RF90_PATH_D: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + return true; +} + +void rtl8821ae_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + rtlphy->default_initialgain[0] = + (u8)rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[1] = + (u8)rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[2] = + (u8)rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); + rtlphy->default_initialgain[3] = + (u8)rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", + rtlphy->default_initialgain[0], + rtlphy->default_initialgain[1], + rtlphy->default_initialgain[2], + rtlphy->default_initialgain[3]); + + rtlphy->framesync = (u8)rtl_get_bbreg(hw, + ROFDM0_RXDETECTOR3, MASKBYTE0); + rtlphy->framesync_c34 = rtl_get_bbreg(hw, + ROFDM0_RXDETECTOR2, MASKDWORD); + + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Default framesync (0x%x) = 0x%x\n", + ROFDM0_RXDETECTOR3, rtlphy->framesync); +} + +static void phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; + rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; + + rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; + rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; + + rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = RA_LSSIWRITE_8821A; + rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = RB_LSSIWRITE_8821A; + + rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RHSSIREAD_8821AE; + rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RHSSIREAD_8821AE; + + rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RA_SIREAD_8821A; + rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RB_SIREAD_8821A; + + rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = RA_PIREAD_8821A; + rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = RB_PIREAD_8821A; +} + +void rtl8821ae_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 txpwr_level; + long txpwr_dbm; + + txpwr_level = rtlphy->cur_cck_txpwridx; + txpwr_dbm = _rtl8821ae_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_B, txpwr_level); + txpwr_level = rtlphy->cur_ofdm24g_txpwridx; + if (_rtl8821ae_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_G, + txpwr_level) > txpwr_dbm) + txpwr_dbm = + _rtl8821ae_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, + txpwr_level); + txpwr_level = rtlphy->cur_ofdm24g_txpwridx; + if (_rtl8821ae_phy_txpwr_idx_to_dbm(hw, + WIRELESS_MODE_N_24G, + txpwr_level) > txpwr_dbm) + txpwr_dbm = + _rtl8821ae_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, + txpwr_level); + *powerlevel = txpwr_dbm; +} + +static bool _rtl8821ae_phy_get_chnl_index(u8 channel, u8 *chnl_index) +{ + u8 channel_5g[CHANNEL_MAX_NUMBER_5G] = { + 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, + 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, + 142, 144, 149, 151, 153, 155, 157, 159, 161, 163, 165, + 167, 168, 169, 171, 173, 175, 177 + }; + u8 i = 0; + bool in_24g = true; + + if (channel <= 14) { + in_24g = true; + *chnl_index = channel - 1; + } else { + in_24g = false; + + for (i = 0; i < CHANNEL_MAX_NUMBER_5G; ++i) { + if (channel_5g[i] == channel) { + *chnl_index = i; + return in_24g; + } + } + } + return in_24g; +} + +static char _rtl8821ae_phy_get_ratesection_intxpower_byrate(u8 path, u8 rate) +{ + char rate_section = 0; + switch (rate) { + case DESC_RATE1M: + case DESC_RATE2M: + case DESC_RATE5_5M: + case DESC_RATE11M: + rate_section = 0; + break; + case DESC_RATE6M: + case DESC_RATE9M: + case DESC_RATE12M: + case DESC_RATE18M: + rate_section = 1; + break; + case DESC_RATE24M: + case DESC_RATE36M: + case DESC_RATE48M: + case DESC_RATE54M: + rate_section = 2; + break; + case DESC_RATEMCS0: + case DESC_RATEMCS1: + case DESC_RATEMCS2: + case DESC_RATEMCS3: + rate_section = 3; + break; + case DESC_RATEMCS4: + case DESC_RATEMCS5: + case DESC_RATEMCS6: + case DESC_RATEMCS7: + rate_section = 4; + break; + case DESC_RATEMCS8: + case DESC_RATEMCS9: + case DESC_RATEMCS10: + case DESC_RATEMCS11: + rate_section = 5; + break; + case DESC_RATEMCS12: + case DESC_RATEMCS13: + case DESC_RATEMCS14: + case DESC_RATEMCS15: + rate_section = 6; + break; + case DESC_RATEVHT1SS_MCS0: + case DESC_RATEVHT1SS_MCS1: + case DESC_RATEVHT1SS_MCS2: + case DESC_RATEVHT1SS_MCS3: + rate_section = 7; + break; + case DESC_RATEVHT1SS_MCS4: + case DESC_RATEVHT1SS_MCS5: + case DESC_RATEVHT1SS_MCS6: + case DESC_RATEVHT1SS_MCS7: + rate_section = 8; + break; + case DESC_RATEVHT1SS_MCS8: + case DESC_RATEVHT1SS_MCS9: + case DESC_RATEVHT2SS_MCS0: + case DESC_RATEVHT2SS_MCS1: + rate_section = 9; + break; + case DESC_RATEVHT2SS_MCS2: + case DESC_RATEVHT2SS_MCS3: + case DESC_RATEVHT2SS_MCS4: + case DESC_RATEVHT2SS_MCS5: + rate_section = 10; + break; + case DESC_RATEVHT2SS_MCS6: + case DESC_RATEVHT2SS_MCS7: + case DESC_RATEVHT2SS_MCS8: + case DESC_RATEVHT2SS_MCS9: + rate_section = 11; + break; + default: + RT_ASSERT(true, "Rate_Section is Illegal\n"); + break; + } + + return rate_section; +} + +static char _rtl8812ae_phy_get_world_wide_limit(char *limit_table) +{ + char min = limit_table[0]; + u8 i = 0; + + for (i = 0; i < MAX_REGULATION_NUM; ++i) { + if (limit_table[i] < min) + min = limit_table[i]; + } + return min; +} + +static char _rtl8812ae_phy_get_txpower_limit(struct ieee80211_hw *hw, + u8 band, + enum ht_channel_width bandwidth, + enum radio_path rf_path, + u8 rate, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); + struct rtl_phy *rtlphy = &rtlpriv->phy; + short band_temp = -1, regulation = -1, bandwidth_temp = -1, + rate_section = -1, channel_temp = -1; + u16 bd, regu, bdwidth, sec, chnl; + char power_limit = MAX_POWER_INDEX; + + if (rtlefuse->eeprom_regulatory == 2) + return MAX_POWER_INDEX; + + regulation = TXPWR_LMT_WW; + + if (band == BAND_ON_2_4G) + band_temp = 0; + else if (band == BAND_ON_5G) + band_temp = 1; + + if (bandwidth == HT_CHANNEL_WIDTH_20) + bandwidth_temp = 0; + else if (bandwidth == HT_CHANNEL_WIDTH_20_40) + bandwidth_temp = 1; + else if (bandwidth == HT_CHANNEL_WIDTH_80) + bandwidth_temp = 2; + + switch (rate) { + case DESC_RATE1M: + case DESC_RATE2M: + case DESC_RATE5_5M: + case DESC_RATE11M: + rate_section = 0; + break; + case DESC_RATE6M: + case DESC_RATE9M: + case DESC_RATE12M: + case DESC_RATE18M: + case DESC_RATE24M: + case DESC_RATE36M: + case DESC_RATE48M: + case DESC_RATE54M: + rate_section = 1; + break; + case DESC_RATEMCS0: + case DESC_RATEMCS1: + case DESC_RATEMCS2: + case DESC_RATEMCS3: + case DESC_RATEMCS4: + case DESC_RATEMCS5: + case DESC_RATEMCS6: + case DESC_RATEMCS7: + rate_section = 2; + break; + case DESC_RATEMCS8: + case DESC_RATEMCS9: + case DESC_RATEMCS10: + case DESC_RATEMCS11: + case DESC_RATEMCS12: + case DESC_RATEMCS13: + case DESC_RATEMCS14: + case DESC_RATEMCS15: + rate_section = 3; + break; + case DESC_RATEVHT1SS_MCS0: + case DESC_RATEVHT1SS_MCS1: + case DESC_RATEVHT1SS_MCS2: + case DESC_RATEVHT1SS_MCS3: + case DESC_RATEVHT1SS_MCS4: + case DESC_RATEVHT1SS_MCS5: + case DESC_RATEVHT1SS_MCS6: + case DESC_RATEVHT1SS_MCS7: + case DESC_RATEVHT1SS_MCS8: + case DESC_RATEVHT1SS_MCS9: + rate_section = 4; + break; + case DESC_RATEVHT2SS_MCS0: + case DESC_RATEVHT2SS_MCS1: + case DESC_RATEVHT2SS_MCS2: + case DESC_RATEVHT2SS_MCS3: + case DESC_RATEVHT2SS_MCS4: + case DESC_RATEVHT2SS_MCS5: + case DESC_RATEVHT2SS_MCS6: + case DESC_RATEVHT2SS_MCS7: + case DESC_RATEVHT2SS_MCS8: + case DESC_RATEVHT2SS_MCS9: + rate_section = 5; + break; + default: + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Wrong rate 0x%x\n", rate); + break; + } + + if (band_temp == BAND_ON_5G && rate_section == 0) + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Wrong rate 0x%x: No CCK in 5G Band\n", rate); + + /*workaround for wrong index combination to obtain tx power limit, + OFDM only exists in BW 20M*/ + if (rate_section == 1) + bandwidth_temp = 0; + + /*workaround for wrong index combination to obtain tx power limit, + *HT on 80M will reference to HT on 40M + */ + if ((rate_section == 2 || rate_section == 3) && band == BAND_ON_5G && + bandwidth_temp == 2) + bandwidth_temp = 1; + + if (band == BAND_ON_2_4G) + channel_temp = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw, + BAND_ON_2_4G, channel); + else if (band == BAND_ON_5G) + channel_temp = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw, + BAND_ON_5G, channel); + else if (band == BAND_ON_BOTH) + ;/* BAND_ON_BOTH don't care temporarily */ + + if (band_temp == -1 || regulation == -1 || bandwidth_temp == -1 || + rate_section == -1 || channel_temp == -1) { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Wrong index value to access power limit table [band %d][regulation %d][bandwidth %d][rf_path %d][rate_section %d][chnl %d]\n", + band_temp, regulation, bandwidth_temp, rf_path, + rate_section, channel_temp); + return MAX_POWER_INDEX; + } + + bd = band_temp; + regu = regulation; + bdwidth = bandwidth_temp; + sec = rate_section; + chnl = channel_temp; + + if (band == BAND_ON_2_4G) { + char limits[10] = {0}; + u8 i; + + for (i = 0; i < 4; ++i) + limits[i] = rtlphy->txpwr_limit_2_4g[i][bdwidth] + [sec][chnl][rf_path]; + + power_limit = (regulation == TXPWR_LMT_WW) ? + _rtl8812ae_phy_get_world_wide_limit(limits) : + rtlphy->txpwr_limit_2_4g[regu][bdwidth] + [sec][chnl][rf_path]; + } else if (band == BAND_ON_5G) { + char limits[10] = {0}; + u8 i; + + for (i = 0; i < MAX_REGULATION_NUM; ++i) + limits[i] = rtlphy->txpwr_limit_5g[i][bdwidth] + [sec][chnl][rf_path]; + + power_limit = (regulation == TXPWR_LMT_WW) ? + _rtl8812ae_phy_get_world_wide_limit(limits) : + rtlphy->txpwr_limit_5g[regu][chnl] + [sec][chnl][rf_path]; + } else { + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, + "No power limit table of the specified band\n"); + } + return power_limit; +} + +static char _rtl8821ae_phy_get_txpower_by_rate(struct ieee80211_hw *hw, + u8 band, u8 path, u8 rate) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 shift = 0, rate_section, tx_num; + char tx_pwr_diff = 0; + char limit = 0; + + rate_section = _rtl8821ae_phy_get_ratesection_intxpower_byrate(path, rate); + tx_num = RF_TX_NUM_NONIMPLEMENT; + + if (tx_num == RF_TX_NUM_NONIMPLEMENT) { + if ((rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) || + (rate >= DESC_RATEVHT2SS_MCS2 && rate <= DESC_RATEVHT2SS_MCS9)) + tx_num = RF_2TX; + else + tx_num = RF_1TX; + } + + switch (rate) { + case DESC_RATE1M: + case DESC_RATE6M: + case DESC_RATE24M: + case DESC_RATEMCS0: + case DESC_RATEMCS4: + case DESC_RATEMCS8: + case DESC_RATEMCS12: + case DESC_RATEVHT1SS_MCS0: + case DESC_RATEVHT1SS_MCS4: + case DESC_RATEVHT1SS_MCS8: + case DESC_RATEVHT2SS_MCS2: + case DESC_RATEVHT2SS_MCS6: + shift = 0; + break; + case DESC_RATE2M: + case DESC_RATE9M: + case DESC_RATE36M: + case DESC_RATEMCS1: + case DESC_RATEMCS5: + case DESC_RATEMCS9: + case DESC_RATEMCS13: + case DESC_RATEVHT1SS_MCS1: + case DESC_RATEVHT1SS_MCS5: + case DESC_RATEVHT1SS_MCS9: + case DESC_RATEVHT2SS_MCS3: + case DESC_RATEVHT2SS_MCS7: + shift = 8; + break; + case DESC_RATE5_5M: + case DESC_RATE12M: + case DESC_RATE48M: + case DESC_RATEMCS2: + case DESC_RATEMCS6: + case DESC_RATEMCS10: + case DESC_RATEMCS14: + case DESC_RATEVHT1SS_MCS2: + case DESC_RATEVHT1SS_MCS6: + case DESC_RATEVHT2SS_MCS0: + case DESC_RATEVHT2SS_MCS4: + case DESC_RATEVHT2SS_MCS8: + shift = 16; + break; + case DESC_RATE11M: + case DESC_RATE18M: + case DESC_RATE54M: + case DESC_RATEMCS3: + case DESC_RATEMCS7: + case DESC_RATEMCS11: + case DESC_RATEMCS15: + case DESC_RATEVHT1SS_MCS3: + case DESC_RATEVHT1SS_MCS7: + case DESC_RATEVHT2SS_MCS1: + case DESC_RATEVHT2SS_MCS5: + case DESC_RATEVHT2SS_MCS9: + shift = 24; + break; + default: + RT_ASSERT(true, "Rate_Section is Illegal\n"); + break; + } + + tx_pwr_diff = (u8)(rtlphy->tx_power_by_rate_offset[band][path] + [tx_num][rate_section] >> shift) & 0xff; + + /* RegEnableTxPowerLimit == 1 for 8812a & 8821a */ + if (rtlpriv->efuse.eeprom_regulatory != 2) { + limit = _rtl8812ae_phy_get_txpower_limit(hw, band, + rtlphy->current_chan_bw, path, rate, + rtlphy->current_channel); + + if (rate == DESC_RATEVHT1SS_MCS8 || rate == DESC_RATEVHT1SS_MCS9 || + rate == DESC_RATEVHT2SS_MCS8 || rate == DESC_RATEVHT2SS_MCS9) { + if (limit < 0) { + if (tx_pwr_diff < (-limit)) + tx_pwr_diff = -limit; + } + } else { + if (limit < 0) + tx_pwr_diff = limit; + else + tx_pwr_diff = tx_pwr_diff > limit ? limit : tx_pwr_diff; + } + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Maximum power by rate %d, final power by rate %d\n", + limit, tx_pwr_diff); + } + + return tx_pwr_diff; +} + +static u8 _rtl8821ae_get_txpower_index(struct ieee80211_hw *hw, u8 path, + u8 rate, u8 bandwidth, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 index = (channel - 1); + u8 txpower = 0; + bool in_24g = false; + char powerdiff_byrate = 0; + + if (((rtlhal->current_bandtype == BAND_ON_2_4G) && + (channel > 14 || channel < 1)) || + ((rtlhal->current_bandtype == BAND_ON_5G) && (channel <= 14))) { + index = 0; + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, + "Illegal channel!!\n"); + } + + in_24g = _rtl8821ae_phy_get_chnl_index(channel, &index); + if (in_24g) { + if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) + txpower = rtlefuse->txpwrlevel_cck[path][index]; + else if (DESC_RATE6M <= rate) + txpower = rtlefuse->txpwrlevel_ht40_1s[path][index]; + else + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "invalid rate\n"); + + if (DESC_RATE6M <= rate && rate <= DESC_RATE54M && + !RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) + txpower += rtlefuse->txpwr_legacyhtdiff[path][TX_1S]; + + if (bandwidth == HT_CHANNEL_WIDTH_20) { + if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || + (DESC_RATEVHT1SS_MCS0 <= rate && rate <= DESC_RATEVHT2SS_MCS9)) + txpower += rtlefuse->txpwr_ht20diff[path][TX_1S]; + if ((DESC_RATEMCS8 <= rate && rate <= DESC_RATEMCS15) || + (DESC_RATEVHT2SS_MCS0 <= rate && rate <= DESC_RATEVHT2SS_MCS9)) + txpower += rtlefuse->txpwr_ht20diff[path][TX_2S]; + } else if (bandwidth == HT_CHANNEL_WIDTH_20_40) { + if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || + (DESC_RATEVHT1SS_MCS0 <= rate && rate <= DESC_RATEVHT2SS_MCS9)) + txpower += rtlefuse->txpwr_ht40diff[path][TX_1S]; + if ((DESC_RATEMCS8 <= rate && rate <= DESC_RATEMCS15) || + (DESC_RATEVHT2SS_MCS0 <= rate && rate <= DESC_RATEVHT2SS_MCS9)) + txpower += rtlefuse->txpwr_ht40diff[path][TX_2S]; + } else if (bandwidth == HT_CHANNEL_WIDTH_80) { + if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || + (DESC_RATEVHT1SS_MCS0 <= rate && + rate <= DESC_RATEVHT2SS_MCS9)) + txpower += rtlefuse->txpwr_ht40diff[path][TX_1S]; + if ((DESC_RATEMCS8 <= rate && rate <= DESC_RATEMCS15) || + (DESC_RATEVHT2SS_MCS0 <= rate && + rate <= DESC_RATEVHT2SS_MCS9)) + txpower += rtlefuse->txpwr_ht40diff[path][TX_2S]; + } + } else { + if (DESC_RATE6M <= rate) + txpower = rtlefuse->txpwr_5g_bw40base[path][index]; + else + RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_WARNING, + "INVALID Rate.\n"); + + if (DESC_RATE6M <= rate && rate <= DESC_RATE54M && + !RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) + txpower += rtlefuse->txpwr_5g_ofdmdiff[path][TX_1S]; + + if (bandwidth == HT_CHANNEL_WIDTH_20) { + if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || + (DESC_RATEVHT1SS_MCS0 <= rate && + rate <= DESC_RATEVHT2SS_MCS9)) + txpower += rtlefuse->txpwr_5g_bw20diff[path][TX_1S]; + if ((DESC_RATEMCS8 <= rate && rate <= DESC_RATEMCS15) || + (DESC_RATEVHT2SS_MCS0 <= rate && + rate <= DESC_RATEVHT2SS_MCS9)) + txpower += rtlefuse->txpwr_5g_bw20diff[path][TX_2S]; + } else if (bandwidth == HT_CHANNEL_WIDTH_20_40) { + if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || + (DESC_RATEVHT1SS_MCS0 <= rate && + rate <= DESC_RATEVHT2SS_MCS9)) + txpower += rtlefuse->txpwr_5g_bw40diff[path][TX_1S]; + if ((DESC_RATEMCS8 <= rate && rate <= DESC_RATEMCS15) || + (DESC_RATEVHT2SS_MCS0 <= rate && + rate <= DESC_RATEVHT2SS_MCS9)) + txpower += rtlefuse->txpwr_5g_bw40diff[path][TX_2S]; + } else if (bandwidth == HT_CHANNEL_WIDTH_80) { + u8 channel_5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = { + 42, 58, 106, 122, 138, 155, 171 + }; + u8 i; + + for (i = 0; i < sizeof(channel_5g_80m) / sizeof(u8); ++i) + if (channel_5g_80m[i] == channel) + index = i; + + if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || + (DESC_RATEVHT1SS_MCS0 <= rate && + rate <= DESC_RATEVHT2SS_MCS9)) + txpower = rtlefuse->txpwr_5g_bw80base[path][index] + + rtlefuse->txpwr_5g_bw80diff[path][TX_1S]; + if ((DESC_RATEMCS8 <= rate && rate <= DESC_RATEMCS15) || + (DESC_RATEVHT2SS_MCS0 <= rate && + rate <= DESC_RATEVHT2SS_MCS9)) + txpower = rtlefuse->txpwr_5g_bw80base[path][index] + + rtlefuse->txpwr_5g_bw80diff[path][TX_1S] + + rtlefuse->txpwr_5g_bw80diff[path][TX_2S]; + } + } + if (rtlefuse->eeprom_regulatory != 2) + powerdiff_byrate = + _rtl8821ae_phy_get_txpower_by_rate(hw, (u8)(!in_24g), + path, rate); + + if (rate == DESC_RATEVHT1SS_MCS8 || rate == DESC_RATEVHT1SS_MCS9 || + rate == DESC_RATEVHT2SS_MCS8 || rate == DESC_RATEVHT2SS_MCS9) + txpower -= powerdiff_byrate; + else + txpower += powerdiff_byrate; + + if (rate > DESC_RATE11M) + txpower += rtlpriv->dm.remnant_ofdm_swing_idx[path]; + else + txpower += rtlpriv->dm.remnant_cck_idx; + + if (txpower > MAX_POWER_INDEX) + txpower = MAX_POWER_INDEX; + + return txpower; +} + +static void _rtl8821ae_phy_set_txpower_index(struct ieee80211_hw *hw, + u8 power_index, u8 path, u8 rate) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (path == RF90_PATH_A) { + switch (rate) { + case DESC_RATE1M: + rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, + MASKBYTE0, power_index); + break; + case DESC_RATE2M: + rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, + MASKBYTE1, power_index); + break; + case DESC_RATE5_5M: + rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, + MASKBYTE2, power_index); + break; + case DESC_RATE11M: + rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, + MASKBYTE3, power_index); + break; + case DESC_RATE6M: + rtl_set_bbreg(hw, RTXAGC_A_OFDM18_OFDM6, + MASKBYTE0, power_index); + break; + case DESC_RATE9M: + rtl_set_bbreg(hw, RTXAGC_A_OFDM18_OFDM6, + MASKBYTE1, power_index); + break; + case DESC_RATE12M: + rtl_set_bbreg(hw, RTXAGC_A_OFDM18_OFDM6, + MASKBYTE2, power_index); + break; + case DESC_RATE18M: + rtl_set_bbreg(hw, RTXAGC_A_OFDM18_OFDM6, + MASKBYTE3, power_index); + break; + case DESC_RATE24M: + rtl_set_bbreg(hw, RTXAGC_A_OFDM54_OFDM24, + MASKBYTE0, power_index); + break; + case DESC_RATE36M: + rtl_set_bbreg(hw, RTXAGC_A_OFDM54_OFDM24, + MASKBYTE1, power_index); + break; + case DESC_RATE48M: + rtl_set_bbreg(hw, RTXAGC_A_OFDM54_OFDM24, + MASKBYTE2, power_index); + break; + case DESC_RATE54M: + rtl_set_bbreg(hw, RTXAGC_A_OFDM54_OFDM24, + MASKBYTE3, power_index); + break; + case DESC_RATEMCS0: + rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, + MASKBYTE0, power_index); + break; + case DESC_RATEMCS1: + rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, + MASKBYTE1, power_index); + break; + case DESC_RATEMCS2: + rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, + MASKBYTE2, power_index); + break; + case DESC_RATEMCS3: + rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, + MASKBYTE3, power_index); + break; + case DESC_RATEMCS4: + rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, + MASKBYTE0, power_index); + break; + case DESC_RATEMCS5: + rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, + MASKBYTE1, power_index); + break; + case DESC_RATEMCS6: + rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, + MASKBYTE2, power_index); + break; + case DESC_RATEMCS7: + rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, + MASKBYTE3, power_index); + break; + case DESC_RATEMCS8: + rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, + MASKBYTE0, power_index); + break; + case DESC_RATEMCS9: + rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, + MASKBYTE1, power_index); + break; + case DESC_RATEMCS10: + rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, + MASKBYTE2, power_index); + break; + case DESC_RATEMCS11: + rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, + MASKBYTE3, power_index); + break; + case DESC_RATEMCS12: + rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, + MASKBYTE0, power_index); + break; + case DESC_RATEMCS13: + rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, + MASKBYTE1, power_index); + break; + case DESC_RATEMCS14: + rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, + MASKBYTE2, power_index); + break; + case DESC_RATEMCS15: + rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, + MASKBYTE3, power_index); + break; + case DESC_RATEVHT1SS_MCS0: + rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX3_NSS1INDEX0, + MASKBYTE0, power_index); + break; + case DESC_RATEVHT1SS_MCS1: + rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX3_NSS1INDEX0, + MASKBYTE1, power_index); + break; + case DESC_RATEVHT1SS_MCS2: + rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX3_NSS1INDEX0, + MASKBYTE2, power_index); + break; + case DESC_RATEVHT1SS_MCS3: + rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX3_NSS1INDEX0, + MASKBYTE3, power_index); + break; + case DESC_RATEVHT1SS_MCS4: + rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX7_NSS1INDEX4, + MASKBYTE0, power_index); + break; + case DESC_RATEVHT1SS_MCS5: + rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX7_NSS1INDEX4, + MASKBYTE1, power_index); + break; + case DESC_RATEVHT1SS_MCS6: + rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX7_NSS1INDEX4, + MASKBYTE2, power_index); + break; + case DESC_RATEVHT1SS_MCS7: + rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX7_NSS1INDEX4, + MASKBYTE3, power_index); + break; + case DESC_RATEVHT1SS_MCS8: + rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX1_NSS1INDEX8, + MASKBYTE0, power_index); + break; + case DESC_RATEVHT1SS_MCS9: + rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX1_NSS1INDEX8, + MASKBYTE1, power_index); + break; + case DESC_RATEVHT2SS_MCS0: + rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX1_NSS1INDEX8, + MASKBYTE2, power_index); + break; + case DESC_RATEVHT2SS_MCS1: + rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX1_NSS1INDEX8, + MASKBYTE3, power_index); + break; + case DESC_RATEVHT2SS_MCS2: + rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX5_NSS2INDEX2, + MASKBYTE0, power_index); + break; + case DESC_RATEVHT2SS_MCS3: + rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX5_NSS2INDEX2, + MASKBYTE1, power_index); + break; + case DESC_RATEVHT2SS_MCS4: + rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX5_NSS2INDEX2, + MASKBYTE2, power_index); + break; + case DESC_RATEVHT2SS_MCS5: + rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX5_NSS2INDEX2, + MASKBYTE3, power_index); + break; + case DESC_RATEVHT2SS_MCS6: + rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX9_NSS2INDEX6, + MASKBYTE0, power_index); + break; + case DESC_RATEVHT2SS_MCS7: + rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX9_NSS2INDEX6, + MASKBYTE1, power_index); + break; + case DESC_RATEVHT2SS_MCS8: + rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX9_NSS2INDEX6, + MASKBYTE2, power_index); + break; + case DESC_RATEVHT2SS_MCS9: + rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX9_NSS2INDEX6, + MASKBYTE3, power_index); + break; + default: + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Invalid Rate!!\n"); + break; + } + } else if (path == RF90_PATH_B) { + switch (rate) { + case DESC_RATE1M: + rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, + MASKBYTE0, power_index); + break; + case DESC_RATE2M: + rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, + MASKBYTE1, power_index); + break; + case DESC_RATE5_5M: + rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, + MASKBYTE2, power_index); + break; + case DESC_RATE11M: + rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, + MASKBYTE3, power_index); + break; + case DESC_RATE6M: + rtl_set_bbreg(hw, RTXAGC_B_OFDM18_OFDM6, + MASKBYTE0, power_index); + break; + case DESC_RATE9M: + rtl_set_bbreg(hw, RTXAGC_B_OFDM18_OFDM6, + MASKBYTE1, power_index); + break; + case DESC_RATE12M: + rtl_set_bbreg(hw, RTXAGC_B_OFDM18_OFDM6, + MASKBYTE2, power_index); + break; + case DESC_RATE18M: + rtl_set_bbreg(hw, RTXAGC_B_OFDM18_OFDM6, + MASKBYTE3, power_index); + break; + case DESC_RATE24M: + rtl_set_bbreg(hw, RTXAGC_B_OFDM54_OFDM24, + MASKBYTE0, power_index); + break; + case DESC_RATE36M: + rtl_set_bbreg(hw, RTXAGC_B_OFDM54_OFDM24, + MASKBYTE1, power_index); + break; + case DESC_RATE48M: + rtl_set_bbreg(hw, RTXAGC_B_OFDM54_OFDM24, + MASKBYTE2, power_index); + break; + case DESC_RATE54M: + rtl_set_bbreg(hw, RTXAGC_B_OFDM54_OFDM24, + MASKBYTE3, power_index); + break; + case DESC_RATEMCS0: + rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, + MASKBYTE0, power_index); + break; + case DESC_RATEMCS1: + rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, + MASKBYTE1, power_index); + break; + case DESC_RATEMCS2: + rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, + MASKBYTE2, power_index); + break; + case DESC_RATEMCS3: + rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, + MASKBYTE3, power_index); + break; + case DESC_RATEMCS4: + rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, + MASKBYTE0, power_index); + break; + case DESC_RATEMCS5: + rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, + MASKBYTE1, power_index); + break; + case DESC_RATEMCS6: + rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, + MASKBYTE2, power_index); + break; + case DESC_RATEMCS7: + rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, + MASKBYTE3, power_index); + break; + case DESC_RATEMCS8: + rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, + MASKBYTE0, power_index); + break; + case DESC_RATEMCS9: + rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, + MASKBYTE1, power_index); + break; + case DESC_RATEMCS10: + rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, + MASKBYTE2, power_index); + break; + case DESC_RATEMCS11: + rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, + MASKBYTE3, power_index); + break; + case DESC_RATEMCS12: + rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, + MASKBYTE0, power_index); + break; + case DESC_RATEMCS13: + rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, + MASKBYTE1, power_index); + break; + case DESC_RATEMCS14: + rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, + MASKBYTE2, power_index); + break; + case DESC_RATEMCS15: + rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, + MASKBYTE3, power_index); + break; + case DESC_RATEVHT1SS_MCS0: + rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX3_NSS1INDEX0, + MASKBYTE0, power_index); + break; + case DESC_RATEVHT1SS_MCS1: + rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX3_NSS1INDEX0, + MASKBYTE1, power_index); + break; + case DESC_RATEVHT1SS_MCS2: + rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX3_NSS1INDEX0, + MASKBYTE2, power_index); + break; + case DESC_RATEVHT1SS_MCS3: + rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX3_NSS1INDEX0, + MASKBYTE3, power_index); + break; + case DESC_RATEVHT1SS_MCS4: + rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX7_NSS1INDEX4, + MASKBYTE0, power_index); + break; + case DESC_RATEVHT1SS_MCS5: + rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX7_NSS1INDEX4, + MASKBYTE1, power_index); + break; + case DESC_RATEVHT1SS_MCS6: + rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX7_NSS1INDEX4, + MASKBYTE2, power_index); + break; + case DESC_RATEVHT1SS_MCS7: + rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX7_NSS1INDEX4, + MASKBYTE3, power_index); + break; + case DESC_RATEVHT1SS_MCS8: + rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX1_NSS1INDEX8, + MASKBYTE0, power_index); + break; + case DESC_RATEVHT1SS_MCS9: + rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX1_NSS1INDEX8, + MASKBYTE1, power_index); + break; + case DESC_RATEVHT2SS_MCS0: + rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX1_NSS1INDEX8, + MASKBYTE2, power_index); + break; + case DESC_RATEVHT2SS_MCS1: + rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX1_NSS1INDEX8, + MASKBYTE3, power_index); + break; + case DESC_RATEVHT2SS_MCS2: + rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX5_NSS2INDEX2, + MASKBYTE0, power_index); + break; + case DESC_RATEVHT2SS_MCS3: + rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX5_NSS2INDEX2, + MASKBYTE1, power_index); + break; + case DESC_RATEVHT2SS_MCS4: + rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX5_NSS2INDEX2, + MASKBYTE2, power_index); + break; + case DESC_RATEVHT2SS_MCS5: + rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX5_NSS2INDEX2, + MASKBYTE3, power_index); + break; + case DESC_RATEVHT2SS_MCS6: + rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX9_NSS2INDEX6, + MASKBYTE0, power_index); + break; + case DESC_RATEVHT2SS_MCS7: + rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX9_NSS2INDEX6, + MASKBYTE1, power_index); + break; + case DESC_RATEVHT2SS_MCS8: + rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX9_NSS2INDEX6, + MASKBYTE2, power_index); + break; + case DESC_RATEVHT2SS_MCS9: + rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX9_NSS2INDEX6, + MASKBYTE3, power_index); + break; + default: + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Invalid Rate!!\n"); + break; + } + } else { + RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, + "Invalid RFPath!!\n"); + } +} + +static void _rtl8821ae_phy_set_txpower_level_by_path(struct ieee80211_hw *hw, + u8 *array, u8 path, + u8 channel, u8 size) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 i; + u8 power_index; + + for (i = 0; i < size; i++) { + power_index = + _rtl8821ae_get_txpower_index(hw, path, array[i], + rtlphy->current_chan_bw, + channel); + _rtl8821ae_phy_set_txpower_index(hw, power_index, path, + array[i]); + } +} + +static void _rtl8821ae_phy_txpower_training_by_path(struct ieee80211_hw *hw, + u8 bw, u8 channel, u8 path) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + u8 i; + u32 power_level, data, offset; + + if (path >= rtlphy->num_total_rfpath) + return; + + data = 0; + if (path == RF90_PATH_A) { + power_level = + _rtl8821ae_get_txpower_index(hw, RF90_PATH_A, + DESC_RATEMCS7, bw, channel); + offset = RA_TXPWRTRAING; + } else { + power_level = + _rtl8821ae_get_txpower_index(hw, RF90_PATH_B, + DESC_RATEMCS7, bw, channel); + offset = RB_TXPWRTRAING; + } + + for (i = 0; i < 3; i++) { + if (i == 0) + power_level = power_level - 10; + else if (i == 1) + power_level = power_level - 8; + else + power_level = power_level - 6; + + data |= (((power_level > 2) ? (power_level) : 2) << (i * 8)); + } + rtl_set_bbreg(hw, offset, 0xffffff, data); +} + +void rtl8821ae_phy_set_txpower_level_by_path(struct ieee80211_hw *hw, + u8 channel, u8 path) +{ + /* struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); */ + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 cck_rates[] = {DESC_RATE1M, DESC_RATE2M, DESC_RATE5_5M, + DESC_RATE11M}; + u8 sizes_of_cck_retes = 4; + u8 ofdm_rates[] = {DESC_RATE6M, DESC_RATE9M, DESC_RATE12M, + DESC_RATE18M, DESC_RATE24M, DESC_RATE36M, + DESC_RATE48M, DESC_RATE54M}; + u8 sizes_of_ofdm_retes = 8; + u8 ht_rates_1t[] = {DESC_RATEMCS0, DESC_RATEMCS1, DESC_RATEMCS2, + DESC_RATEMCS3, DESC_RATEMCS4, DESC_RATEMCS5, + DESC_RATEMCS6, DESC_RATEMCS7}; + u8 sizes_of_ht_retes_1t = 8; + u8 ht_rates_2t[] = {DESC_RATEMCS8, DESC_RATEMCS9, + DESC_RATEMCS10, DESC_RATEMCS11, + DESC_RATEMCS12, DESC_RATEMCS13, + DESC_RATEMCS14, DESC_RATEMCS15}; + u8 sizes_of_ht_retes_2t = 8; + u8 vht_rates_1t[] = {DESC_RATEVHT1SS_MCS0, DESC_RATEVHT1SS_MCS1, + DESC_RATEVHT1SS_MCS2, DESC_RATEVHT1SS_MCS3, + DESC_RATEVHT1SS_MCS4, DESC_RATEVHT1SS_MCS5, + DESC_RATEVHT1SS_MCS6, DESC_RATEVHT1SS_MCS7, + DESC_RATEVHT1SS_MCS8, DESC_RATEVHT1SS_MCS9}; + u8 vht_rates_2t[] = {DESC_RATEVHT2SS_MCS0, DESC_RATEVHT2SS_MCS1, + DESC_RATEVHT2SS_MCS2, DESC_RATEVHT2SS_MCS3, + DESC_RATEVHT2SS_MCS4, DESC_RATEVHT2SS_MCS5, + DESC_RATEVHT2SS_MCS6, DESC_RATEVHT2SS_MCS7, + DESC_RATEVHT2SS_MCS8, DESC_RATEVHT2SS_MCS9}; + u8 sizes_of_vht_retes = 10; + + if (rtlhal->current_bandtype == BAND_ON_2_4G) + _rtl8821ae_phy_set_txpower_level_by_path(hw, cck_rates, path, channel, + sizes_of_cck_retes); + + _rtl8821ae_phy_set_txpower_level_by_path(hw, ofdm_rates, path, channel, + sizes_of_ofdm_retes); + _rtl8821ae_phy_set_txpower_level_by_path(hw, ht_rates_1t, path, channel, + sizes_of_ht_retes_1t); + _rtl8821ae_phy_set_txpower_level_by_path(hw, vht_rates_1t, path, channel, + sizes_of_vht_retes); + + if (rtlphy->num_total_rfpath >= 2) { + _rtl8821ae_phy_set_txpower_level_by_path(hw, ht_rates_2t, path, + channel, + sizes_of_ht_retes_2t); + _rtl8821ae_phy_set_txpower_level_by_path(hw, vht_rates_2t, path, + channel, + sizes_of_vht_retes); + } + + _rtl8821ae_phy_txpower_training_by_path(hw, rtlphy->current_chan_bw, + channel, path); +} + +/*just in case, write txpower in DW, to reduce time*/ +void rtl8821ae_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 path = 0; + + for (path = RF90_PATH_A; path < rtlphy->num_total_rfpath; ++path) + rtl8821ae_phy_set_txpower_level_by_path(hw, channel, path); +} + +static long _rtl8821ae_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, + enum wireless_mode wirelessmode, + u8 txpwridx) +{ + long offset; + long pwrout_dbm; + + switch (wirelessmode) { + case WIRELESS_MODE_B: + offset = -7; + break; + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + offset = -8; + break; + default: + offset = -8; + break; + } + pwrout_dbm = txpwridx / 2 + offset; + return pwrout_dbm; +} + +void rtl8821ae_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + enum io_type iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; + + if (!is_hal_stop(rtlhal)) { + switch (operation) { + case SCAN_OPT_BACKUP_BAND0: + iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_IO_CMD, + (u8 *)&iotype); + + break; + case SCAN_OPT_BACKUP_BAND1: + iotype = IO_CMD_PAUSE_BAND1_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_IO_CMD, + (u8 *)&iotype); + + break; + case SCAN_OPT_RESTORE: + iotype = IO_CMD_RESUME_DM_BY_SCAN; + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_IO_CMD, + (u8 *)&iotype); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Unknown Scan Backup operation.\n"); + break; + } + } +} + +static void _rtl8821ae_phy_set_reg_bw(struct rtl_priv *rtlpriv, u8 bw) +{ + u16 reg_rf_mode_bw, tmp = 0; + + reg_rf_mode_bw = rtl_read_word(rtlpriv, REG_TRXPTCL_CTL); + switch (bw) { + case HT_CHANNEL_WIDTH_20: + rtl_write_word(rtlpriv, REG_TRXPTCL_CTL, reg_rf_mode_bw & 0xFE7F); + break; + case HT_CHANNEL_WIDTH_20_40: + tmp = reg_rf_mode_bw | BIT(7); + rtl_write_word(rtlpriv, REG_TRXPTCL_CTL, tmp & 0xFEFF); + break; + case HT_CHANNEL_WIDTH_80: + tmp = reg_rf_mode_bw | BIT(8); + rtl_write_word(rtlpriv, REG_TRXPTCL_CTL, tmp & 0xFF7F); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "unknown Bandwidth: 0x%x\n", bw); + break; + } +} + +static u8 _rtl8821ae_phy_get_secondary_chnl(struct rtl_priv *rtlpriv) +{ + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_mac *mac = rtl_mac(rtlpriv); + u8 sc_set_40 = 0, sc_set_20 = 0; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) { + if (mac->cur_80_prime_sc == PRIME_CHNL_OFFSET_LOWER) + sc_set_40 = VHT_DATA_SC_40_LOWER_OF_80MHZ; + else if (mac->cur_80_prime_sc == PRIME_CHNL_OFFSET_UPPER) + sc_set_40 = VHT_DATA_SC_40_UPPER_OF_80MHZ; + else + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "SCMapping: Not Correct Primary40MHz Setting\n"); + + if ((mac->cur_40_prime_sc == PRIME_CHNL_OFFSET_LOWER) && + (mac->cur_80_prime_sc == HAL_PRIME_CHNL_OFFSET_LOWER)) + sc_set_20 = VHT_DATA_SC_20_LOWEST_OF_80MHZ; + else if ((mac->cur_40_prime_sc == PRIME_CHNL_OFFSET_UPPER) && + (mac->cur_80_prime_sc == HAL_PRIME_CHNL_OFFSET_LOWER)) + sc_set_20 = VHT_DATA_SC_20_LOWER_OF_80MHZ; + else if ((mac->cur_40_prime_sc == PRIME_CHNL_OFFSET_LOWER) && + (mac->cur_80_prime_sc == HAL_PRIME_CHNL_OFFSET_UPPER)) + sc_set_20 = VHT_DATA_SC_20_UPPER_OF_80MHZ; + else if ((mac->cur_40_prime_sc == PRIME_CHNL_OFFSET_UPPER) && + (mac->cur_80_prime_sc == HAL_PRIME_CHNL_OFFSET_UPPER)) + sc_set_20 = VHT_DATA_SC_20_UPPERST_OF_80MHZ; + else + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "SCMapping: Not Correct Primary40MHz Setting\n"); + } else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + if (mac->cur_40_prime_sc == PRIME_CHNL_OFFSET_UPPER) + sc_set_20 = VHT_DATA_SC_20_UPPER_OF_80MHZ; + else if (mac->cur_40_prime_sc == PRIME_CHNL_OFFSET_LOWER) + sc_set_20 = VHT_DATA_SC_20_LOWER_OF_80MHZ; + else + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "SCMapping: Not Correct Primary40MHz Setting\n"); + } + return (sc_set_40 << 4) | sc_set_20; +} + +void rtl8821ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 sub_chnl = 0; + u8 l1pk_val = 0; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "Switch to %s bandwidth\n", + (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? + "20MHz" : + (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40 ? + "40MHz" : "80MHz"))); + + _rtl8821ae_phy_set_reg_bw(rtlpriv, rtlphy->current_chan_bw); + sub_chnl = _rtl8821ae_phy_get_secondary_chnl(rtlpriv); + rtl_write_byte(rtlpriv, 0x0483, sub_chnl); + + switch (rtlphy->current_chan_bw) { + case HT_CHANNEL_WIDTH_20: + rtl_set_bbreg(hw, RRFMOD, 0x003003C3, 0x00300200); + rtl_set_bbreg(hw, RADC_BUF_CLK, BIT(30), 0); + + if (rtlphy->rf_type == RF_2T2R) + rtl_set_bbreg(hw, RL1PEAKTH, 0x03C00000, 7); + else + rtl_set_bbreg(hw, RL1PEAKTH, 0x03C00000, 8); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_bbreg(hw, RRFMOD, 0x003003C3, 0x00300201); + rtl_set_bbreg(hw, RADC_BUF_CLK, BIT(30), 0); + rtl_set_bbreg(hw, RRFMOD, 0x3C, sub_chnl); + rtl_set_bbreg(hw, RCCAONSEC, 0xf0000000, sub_chnl); + + if (rtlphy->reg_837 & BIT(2)) + l1pk_val = 6; + else { + if (rtlphy->rf_type == RF_2T2R) + l1pk_val = 7; + else + l1pk_val = 8; + } + /* 0x848[25:22] = 0x6 */ + rtl_set_bbreg(hw, RL1PEAKTH, 0x03C00000, l1pk_val); + + if (sub_chnl == VHT_DATA_SC_20_UPPER_OF_80MHZ) + rtl_set_bbreg(hw, RCCK_SYSTEM, BCCK_SYSTEM, 1); + else + rtl_set_bbreg(hw, RCCK_SYSTEM, BCCK_SYSTEM, 0); + break; + + case HT_CHANNEL_WIDTH_80: + /* 0x8ac[21,20,9:6,1,0]=8'b11100010 */ + rtl_set_bbreg(hw, RRFMOD, 0x003003C3, 0x00300202); + /* 0x8c4[30] = 1 */ + rtl_set_bbreg(hw, RADC_BUF_CLK, BIT(30), 1); + rtl_set_bbreg(hw, RRFMOD, 0x3C, sub_chnl); + rtl_set_bbreg(hw, RCCAONSEC, 0xf0000000, sub_chnl); + + if (rtlphy->reg_837 & BIT(2)) + l1pk_val = 5; + else { + if (rtlphy->rf_type == RF_2T2R) + l1pk_val = 6; + else + l1pk_val = 7; + } + rtl_set_bbreg(hw, RL1PEAKTH, 0x03C00000, l1pk_val); + + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); + break; + } + + rtl8812ae_fixspur(hw, rtlphy->current_chan_bw, rtlphy->current_channel); + + rtl8821ae_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); + rtlphy->set_bwmode_inprogress = false; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n"); +} + +void rtl8821ae_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 tmp_bw = rtlphy->current_chan_bw; + + if (rtlphy->set_bwmode_inprogress) + return; + rtlphy->set_bwmode_inprogress = true; + if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) + rtl8821ae_phy_set_bw_mode_callback(hw); + else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "FALSE driver sleep or unload\n"); + rtlphy->set_bwmode_inprogress = false; + rtlphy->current_chan_bw = tmp_bw; + } +} + +void rtl8821ae_phy_sw_chnl_callback(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 channel = rtlphy->current_channel; + u8 path; + u32 data; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "switch to channel%d\n", rtlphy->current_channel); + if (is_hal_stop(rtlhal)) + return; + + if (36 <= channel && channel <= 48) + data = 0x494; + else if (50 <= channel && channel <= 64) + data = 0x453; + else if (100 <= channel && channel <= 116) + data = 0x452; + else if (118 <= channel) + data = 0x412; + else + data = 0x96a; + rtl_set_bbreg(hw, RFC_AREA, 0x1ffe0000, data); + + for (path = RF90_PATH_A; path < rtlphy->num_total_rfpath; path++) { + if (36 <= channel && channel <= 64) + data = 0x101; + else if (100 <= channel && channel <= 140) + data = 0x301; + else if (140 < channel) + data = 0x501; + else + data = 0x000; + rtl8821ae_phy_set_rf_reg(hw, path, RF_CHNLBW, + BIT(18)|BIT(17)|BIT(16)|BIT(9)|BIT(8), data); + + rtl8821ae_phy_set_rf_reg(hw, path, RF_CHNLBW, + BMASKBYTE0, channel); + + if (channel > 14) { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { + if (36 <= channel && channel <= 64) + data = 0x114E9; + else if (100 <= channel && channel <= 140) + data = 0x110E9; + else + data = 0x110E9; + rtl8821ae_phy_set_rf_reg(hw, path, RF_APK, + BRFREGOFFSETMASK, data); + } + } + } + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); +} + +u8 rtl8821ae_phy_sw_chnl(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u32 timeout = 1000, timecount = 0; + u8 channel = rtlphy->current_channel; + + if (rtlphy->sw_chnl_inprogress) + return 0; + if (rtlphy->set_bwmode_inprogress) + return 0; + + if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) { + RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, + "sw_chnl_inprogress false driver sleep or unload\n"); + return 0; + } + while (rtlphy->lck_inprogress && timecount < timeout) { + mdelay(50); + timecount += 50; + } + + if (rtlphy->current_channel > 14 && rtlhal->current_bandtype != BAND_ON_5G) + rtl8821ae_phy_switch_wirelessband(hw, BAND_ON_5G); + else if (rtlphy->current_channel <= 14 && rtlhal->current_bandtype != BAND_ON_2_4G) + rtl8821ae_phy_switch_wirelessband(hw, BAND_ON_2_4G); + + rtlphy->sw_chnl_inprogress = true; + if (channel == 0) + channel = 1; + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, + "switch to channel%d, band type is %d\n", + rtlphy->current_channel, rtlhal->current_bandtype); + + rtl8821ae_phy_sw_chnl_callback(hw); + + rtl8821ae_dm_clear_txpower_tracking_state(hw); + rtl8821ae_phy_set_txpower_level(hw, rtlphy->current_channel); + + RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); + rtlphy->sw_chnl_inprogress = false; + return 1; +} + +u8 _rtl8812ae_get_right_chnl_place_for_iqk(u8 chnl) +{ + u8 channel_all[TARGET_CHNL_NUM_2G_5G_8812] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, + 56, 58, 60, 62, 64, 100, 102, 104, 106, 108, + 110, 112, 114, 116, 118, 120, 122, 124, 126, + 128, 130, 132, 134, 136, 138, 140, 149, 151, + 153, 155, 157, 159, 161, 163, 165}; + u8 place = chnl; + + if (chnl > 14) { + for (place = 14; place < sizeof(channel_all); place++) + if (channel_all[place] == chnl) + return place-13; + } + + return 0; +} + +#define MACBB_REG_NUM 10 +#define AFE_REG_NUM 14 +#define RF_REG_NUM 3 + +static void _rtl8821ae_iqk_backup_macbb(struct ieee80211_hw *hw, + u32 *macbb_backup, + u32 *backup_macbb_reg, u32 mac_bb_num) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /*[31] = 0 --> Page C*/ + /*save MACBB default value*/ + for (i = 0; i < mac_bb_num; i++) + macbb_backup[i] = rtl_read_dword(rtlpriv, backup_macbb_reg[i]); + + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "BackupMacBB Success!!!!\n"); +} + +static void _rtl8821ae_iqk_backup_afe(struct ieee80211_hw *hw, u32 *afe_backup, + u32 *backup_afe_REG, u32 afe_num) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /*[31] = 0 --> Page C*/ + /*Save AFE Parameters */ + for (i = 0; i < afe_num; i++) + afe_backup[i] = rtl_read_dword(rtlpriv, backup_afe_REG[i]); + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "BackupAFE Success!!!!\n"); +} + +static void _rtl8821ae_iqk_backup_rf(struct ieee80211_hw *hw, u32 *rfa_backup, + u32 *rfb_backup, u32 *backup_rf_reg, + u32 rf_num) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /*[31] = 0 --> Page C*/ + /*Save RF Parameters*/ + for (i = 0; i < rf_num; i++) { + rfa_backup[i] = rtl_get_rfreg(hw, RF90_PATH_A, backup_rf_reg[i], + BMASKDWORD); + rfb_backup[i] = rtl_get_rfreg(hw, RF90_PATH_B, backup_rf_reg[i], + BMASKDWORD); + } + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "BackupRF Success!!!!\n"); +} + +static void _rtl8821ae_iqk_configure_mac( + struct ieee80211_hw *hw + ) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + /* ========MAC register setting========*/ + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /*[31] = 0 --> Page C*/ + rtl_write_byte(rtlpriv, 0x522, 0x3f); + rtl_set_bbreg(hw, 0x550, BIT(11) | BIT(3), 0x0); + rtl_write_byte(rtlpriv, 0x808, 0x00); /*RX ante off*/ + rtl_set_bbreg(hw, 0x838, 0xf, 0xc); /*CCA off*/ +} + +static void _rtl8821ae_iqk_tx_fill_iqc(struct ieee80211_hw *hw, + enum radio_path path, u32 tx_x, u32 tx_y) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + switch (path) { + case RF90_PATH_A: + /* [31] = 1 --> Page C1 */ + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); + rtl_write_dword(rtlpriv, 0xc90, 0x00000080); + rtl_write_dword(rtlpriv, 0xcc4, 0x20040000); + rtl_write_dword(rtlpriv, 0xcc8, 0x20000000); + rtl_set_bbreg(hw, 0xccc, 0x000007ff, tx_y); + rtl_set_bbreg(hw, 0xcd4, 0x000007ff, tx_x); + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "TX_X = %x;;TX_Y = %x =====> fill to IQC\n", + tx_x, tx_y); + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "0xcd4 = %x;;0xccc = %x ====>fill to IQC\n", + rtl_get_bbreg(hw, 0xcd4, 0x000007ff), + rtl_get_bbreg(hw, 0xccc, 0x000007ff)); + break; + default: + break; + } +} + +static void _rtl8821ae_iqk_rx_fill_iqc(struct ieee80211_hw *hw, + enum radio_path path, u32 rx_x, u32 rx_y) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + switch (path) { + case RF90_PATH_A: + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ + rtl_set_bbreg(hw, 0xc10, 0x000003ff, rx_x>>1); + rtl_set_bbreg(hw, 0xc10, 0x03ff0000, rx_y>>1); + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "rx_x = %x;;rx_y = %x ====>fill to IQC\n", + rx_x>>1, rx_y>>1); + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "0xc10 = %x ====>fill to IQC\n", + rtl_read_dword(rtlpriv, 0xc10)); + break; + default: + break; + } +} + +#define cal_num 10 + +static void _rtl8821ae_iqk_tx(struct ieee80211_hw *hw, enum radio_path path) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + u32 tx_fail, rx_fail, delay_count, iqk_ready, cal_retry, cal = 0, temp_reg65; + int tx_x = 0, tx_y = 0, rx_x = 0, rx_y = 0, tx_average = 0, rx_average = 0; + int tx_x0[cal_num], tx_y0[cal_num], tx_x0_rxk[cal_num], + tx_y0_rxk[cal_num], rx_x0[cal_num], rx_y0[cal_num]; + bool tx0iqkok = false, rx0iqkok = false; + bool vdf_enable = false; + int i, k, vdf_y[3], vdf_x[3], tx_dt[3], rx_dt[3], + ii, dx = 0, dy = 0, tx_finish = 0, rx_finish = 0; + + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "BandWidth = %d.\n", + rtlphy->current_chan_bw); + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) + vdf_enable = true; + + while (cal < cal_num) { + switch (path) { + case RF90_PATH_A: + temp_reg65 = rtl_get_rfreg(hw, path, 0x65, 0xffffffff); + /* Path-A LOK */ + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /*[31] = 0 --> Page C*/ + /*========Path-A AFE all on========*/ + /*Port 0 DAC/ADC on*/ + rtl_write_dword(rtlpriv, 0xc60, 0x77777777); + rtl_write_dword(rtlpriv, 0xc64, 0x77777777); + rtl_write_dword(rtlpriv, 0xc68, 0x19791979); + rtl_write_dword(rtlpriv, 0xc6c, 0x19791979); + rtl_write_dword(rtlpriv, 0xc70, 0x19791979); + rtl_write_dword(rtlpriv, 0xc74, 0x19791979); + rtl_write_dword(rtlpriv, 0xc78, 0x19791979); + rtl_write_dword(rtlpriv, 0xc7c, 0x19791979); + rtl_write_dword(rtlpriv, 0xc80, 0x19791979); + rtl_write_dword(rtlpriv, 0xc84, 0x19791979); + + rtl_set_bbreg(hw, 0xc00, 0xf, 0x4); /*hardware 3-wire off*/ + + /* LOK Setting */ + /* ====== LOK ====== */ + /*DAC/ADC sampling rate (160 MHz)*/ + rtl_set_bbreg(hw, 0xc5c, BIT(26) | BIT(25) | BIT(24), 0x7); + + /* 2. LoK RF Setting (at BW = 20M) */ + rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x80002); + rtl_set_rfreg(hw, path, 0x18, 0x00c00, 0x3); /* BW 20M */ + rtl_set_rfreg(hw, path, 0x30, RFREG_OFFSET_MASK, 0x20000); + rtl_set_rfreg(hw, path, 0x31, RFREG_OFFSET_MASK, 0x0003f); + rtl_set_rfreg(hw, path, 0x32, RFREG_OFFSET_MASK, 0xf3fc3); + rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, 0x931d5); + rtl_set_rfreg(hw, path, 0x8f, RFREG_OFFSET_MASK, 0x8a001); + rtl_set_bbreg(hw, 0xcb8, 0xf, 0xd); + rtl_write_dword(rtlpriv, 0x90c, 0x00008000); + rtl_write_dword(rtlpriv, 0xb00, 0x03000100); + rtl_set_bbreg(hw, 0xc94, BIT(0), 0x1); + rtl_write_dword(rtlpriv, 0x978, 0x29002000);/* TX (X,Y) */ + rtl_write_dword(rtlpriv, 0x97c, 0xa9002000);/* RX (X,Y) */ + rtl_write_dword(rtlpriv, 0x984, 0x00462910);/* [0]:AGC_en, [15]:idac_K_Mask */ + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ + rtl_write_dword(rtlpriv, 0xc88, 0x821403f4); + + if (rtlhal->current_bandtype) + rtl_write_dword(rtlpriv, 0xc8c, 0x68163e96); + else + rtl_write_dword(rtlpriv, 0xc8c, 0x28163e96); + + rtl_write_dword(rtlpriv, 0xc80, 0x18008c10);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ + rtl_write_dword(rtlpriv, 0xc84, 0x38008c10);/* RX_TONE_idx[9:0], RxK_Mask[29] */ + rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ + rtl_write_dword(rtlpriv, 0x980, 0xfa000000); + rtl_write_dword(rtlpriv, 0x980, 0xf8000000); + + mdelay(10); /* Delay 10ms */ + rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ + rtl_set_rfreg(hw, path, 0x58, 0x7fe00, rtl_get_rfreg(hw, path, 0x8, 0xffc00)); /* Load LOK */ + + switch (rtlphy->current_chan_bw) { + case 1: + rtl_set_rfreg(hw, path, 0x18, 0x00c00, 0x1); + break; + case 2: + rtl_set_rfreg(hw, path, 0x18, 0x00c00, 0x0); + break; + default: + break; + } + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ + + /* 3. TX RF Setting */ + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ + rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x80000); + rtl_set_rfreg(hw, path, 0x30, RFREG_OFFSET_MASK, 0x20000); + rtl_set_rfreg(hw, path, 0x31, RFREG_OFFSET_MASK, 0x0003f); + rtl_set_rfreg(hw, path, 0x32, RFREG_OFFSET_MASK, 0xf3fc3); + rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, 0x931d5); + rtl_set_rfreg(hw, path, 0x8f, RFREG_OFFSET_MASK, 0x8a001); + rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x00000); + /* ODM_SetBBReg(pDM_Odm, 0xcb8, 0xf, 0xd); */ + rtl_write_dword(rtlpriv, 0x90c, 0x00008000); + rtl_write_dword(rtlpriv, 0xb00, 0x03000100); + rtl_set_bbreg(hw, 0xc94, BIT(0), 0x1); + rtl_write_dword(rtlpriv, 0x978, 0x29002000);/* TX (X,Y) */ + rtl_write_dword(rtlpriv, 0x97c, 0xa9002000);/* RX (X,Y) */ + rtl_write_dword(rtlpriv, 0x984, 0x0046a910);/* [0]:AGC_en, [15]:idac_K_Mask */ + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ + rtl_write_dword(rtlpriv, 0xc88, 0x821403f1); + if (rtlhal->current_bandtype) + rtl_write_dword(rtlpriv, 0xc8c, 0x40163e96); + else + rtl_write_dword(rtlpriv, 0xc8c, 0x00163e96); + + if (vdf_enable == 1) { + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "VDF_enable\n"); + for (k = 0; k <= 2; k++) { + switch (k) { + case 0: + rtl_write_dword(rtlpriv, 0xc80, 0x18008c38);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ + rtl_write_dword(rtlpriv, 0xc84, 0x38008c38);/* RX_TONE_idx[9:0], RxK_Mask[29] */ + rtl_set_bbreg(hw, 0xce8, BIT(31), 0x0); + break; + case 1: + rtl_set_bbreg(hw, 0xc80, BIT(28), 0x0); + rtl_set_bbreg(hw, 0xc84, BIT(28), 0x0); + rtl_set_bbreg(hw, 0xce8, BIT(31), 0x0); + break; + case 2: + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "vdf_y[1] = %x;;;vdf_y[0] = %x\n", vdf_y[1]>>21 & 0x00007ff, vdf_y[0]>>21 & 0x00007ff); + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "vdf_x[1] = %x;;;vdf_x[0] = %x\n", vdf_x[1]>>21 & 0x00007ff, vdf_x[0]>>21 & 0x00007ff); + tx_dt[cal] = (vdf_y[1]>>20)-(vdf_y[0]>>20); + tx_dt[cal] = ((16*tx_dt[cal])*10000/15708); + tx_dt[cal] = (tx_dt[cal] >> 1)+(tx_dt[cal] & BIT(0)); + rtl_write_dword(rtlpriv, 0xc80, 0x18008c20);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ + rtl_write_dword(rtlpriv, 0xc84, 0x38008c20);/* RX_TONE_idx[9:0], RxK_Mask[29] */ + rtl_set_bbreg(hw, 0xce8, BIT(31), 0x1); + rtl_set_bbreg(hw, 0xce8, 0x3fff0000, tx_dt[cal] & 0x00003fff); + break; + default: + break; + } + rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ + cal_retry = 0; + while (1) { + /* one shot */ + rtl_write_dword(rtlpriv, 0x980, 0xfa000000); + rtl_write_dword(rtlpriv, 0x980, 0xf8000000); + + mdelay(10); /* Delay 10ms */ + rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); + delay_count = 0; + while (1) { + iqk_ready = rtl_get_bbreg(hw, 0xd00, BIT(10)); + if ((~iqk_ready) || (delay_count > 20)) + break; + else{ + mdelay(1); + delay_count++; + } + } + + if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ + /* ============TXIQK Check============== */ + tx_fail = rtl_get_bbreg(hw, 0xd00, BIT(12)); + + if (~tx_fail) { + rtl_write_dword(rtlpriv, 0xcb8, 0x02000000); + vdf_x[k] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; + rtl_write_dword(rtlpriv, 0xcb8, 0x04000000); + vdf_y[k] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; + tx0iqkok = true; + break; + } else { + rtl_set_bbreg(hw, 0xccc, 0x000007ff, 0x0); + rtl_set_bbreg(hw, 0xcd4, 0x000007ff, 0x200); + tx0iqkok = false; + cal_retry++; + if (cal_retry == 10) + break; + } + } else { + tx0iqkok = false; + cal_retry++; + if (cal_retry == 10) + break; + } + } + } + if (k == 3) { + tx_x0[cal] = vdf_x[k-1]; + tx_y0[cal] = vdf_y[k-1]; + } + } else { + rtl_write_dword(rtlpriv, 0xc80, 0x18008c10);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ + rtl_write_dword(rtlpriv, 0xc84, 0x38008c10);/* RX_TONE_idx[9:0], RxK_Mask[29] */ + rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ + cal_retry = 0; + while (1) { + /* one shot */ + rtl_write_dword(rtlpriv, 0x980, 0xfa000000); + rtl_write_dword(rtlpriv, 0x980, 0xf8000000); + + mdelay(10); /* Delay 10ms */ + rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); + delay_count = 0; + while (1) { + iqk_ready = rtl_get_bbreg(hw, 0xd00, BIT(10)); + if ((~iqk_ready) || (delay_count > 20)) + break; + else{ + mdelay(1); + delay_count++; + } + } + + if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ + /* ============TXIQK Check============== */ + tx_fail = rtl_get_bbreg(hw, 0xd00, BIT(12)); + + if (~tx_fail) { + rtl_write_dword(rtlpriv, 0xcb8, 0x02000000); + tx_x0[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; + rtl_write_dword(rtlpriv, 0xcb8, 0x04000000); + tx_y0[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; + tx0iqkok = true; + break; + } else { + rtl_set_bbreg(hw, 0xccc, 0x000007ff, 0x0); + rtl_set_bbreg(hw, 0xcd4, 0x000007ff, 0x200); + tx0iqkok = false; + cal_retry++; + if (cal_retry == 10) + break; + } + } else { + tx0iqkok = false; + cal_retry++; + if (cal_retry == 10) + break; + } + } + } + + if (tx0iqkok == false) + break; /* TXK fail, Don't do RXK */ + + if (vdf_enable == 1) { + rtl_set_bbreg(hw, 0xce8, BIT(31), 0x0); /* TX VDF Disable */ + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "RXVDF Start\n"); + for (k = 0; k <= 2; k++) { + /* ====== RX mode TXK (RXK Step 1) ====== */ + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ + /* 1. TX RF Setting */ + rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x80000); + rtl_set_rfreg(hw, path, 0x30, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, path, 0x31, RFREG_OFFSET_MASK, 0x00029); + rtl_set_rfreg(hw, path, 0x32, RFREG_OFFSET_MASK, 0xd7ffb); + rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, temp_reg65); + rtl_set_rfreg(hw, path, 0x8f, RFREG_OFFSET_MASK, 0x8a001); + rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x00000); + + rtl_set_bbreg(hw, 0xcb8, 0xf, 0xd); + rtl_write_dword(rtlpriv, 0x978, 0x29002000);/* TX (X,Y) */ + rtl_write_dword(rtlpriv, 0x97c, 0xa9002000);/* RX (X,Y) */ + rtl_write_dword(rtlpriv, 0x984, 0x0046a910);/* [0]:AGC_en, [15]:idac_K_Mask */ + rtl_write_dword(rtlpriv, 0x90c, 0x00008000); + rtl_write_dword(rtlpriv, 0xb00, 0x03000100); + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ + switch (k) { + case 0: + { + rtl_write_dword(rtlpriv, 0xc80, 0x18008c38);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ + rtl_write_dword(rtlpriv, 0xc84, 0x38008c38);/* RX_TONE_idx[9:0], RxK_Mask[29] */ + rtl_set_bbreg(hw, 0xce8, BIT(30), 0x0); + } + break; + case 1: + { + rtl_write_dword(rtlpriv, 0xc80, 0x08008c38);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ + rtl_write_dword(rtlpriv, 0xc84, 0x28008c38);/* RX_TONE_idx[9:0], RxK_Mask[29] */ + rtl_set_bbreg(hw, 0xce8, BIT(30), 0x0); + } + break; + case 2: + { + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "VDF_Y[1] = %x;;;VDF_Y[0] = %x\n", + vdf_y[1]>>21 & 0x00007ff, vdf_y[0]>>21 & 0x00007ff); + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "VDF_X[1] = %x;;;VDF_X[0] = %x\n", + vdf_x[1]>>21 & 0x00007ff, vdf_x[0]>>21 & 0x00007ff); + rx_dt[cal] = (vdf_y[1]>>20)-(vdf_y[0]>>20); + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "Rx_dt = %d\n", rx_dt[cal]); + rx_dt[cal] = ((16*rx_dt[cal])*10000/13823); + rx_dt[cal] = (rx_dt[cal] >> 1)+(rx_dt[cal] & BIT(0)); + rtl_write_dword(rtlpriv, 0xc80, 0x18008c20);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ + rtl_write_dword(rtlpriv, 0xc84, 0x38008c20);/* RX_TONE_idx[9:0], RxK_Mask[29] */ + rtl_set_bbreg(hw, 0xce8, 0x00003fff, rx_dt[cal] & 0x00003fff); + } + break; + default: + break; + } + rtl_write_dword(rtlpriv, 0xc88, 0x821603e0); + rtl_write_dword(rtlpriv, 0xc8c, 0x68163e96); + rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ + cal_retry = 0; + while (1) { + /* one shot */ + rtl_write_dword(rtlpriv, 0x980, 0xfa000000); + rtl_write_dword(rtlpriv, 0x980, 0xf8000000); + + mdelay(10); /* Delay 10ms */ + rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); + delay_count = 0; + while (1) { + iqk_ready = rtl_get_bbreg(hw, 0xd00, BIT(10)); + if ((~iqk_ready) || (delay_count > 20)) + break; + else{ + mdelay(1); + delay_count++; + } + } + + if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ + /* ============TXIQK Check============== */ + tx_fail = rtl_get_bbreg(hw, 0xd00, BIT(12)); + + if (~tx_fail) { + rtl_write_dword(rtlpriv, 0xcb8, 0x02000000); + tx_x0_rxk[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; + rtl_write_dword(rtlpriv, 0xcb8, 0x04000000); + tx_y0_rxk[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; + tx0iqkok = true; + break; + } else{ + tx0iqkok = false; + cal_retry++; + if (cal_retry == 10) + break; + } + } else { + tx0iqkok = false; + cal_retry++; + if (cal_retry == 10) + break; + } + } + + if (tx0iqkok == false) { /* If RX mode TXK fail, then take TXK Result */ + tx_x0_rxk[cal] = tx_x0[cal]; + tx_y0_rxk[cal] = tx_y0[cal]; + tx0iqkok = true; + RT_TRACE(rtlpriv, + COMP_IQK, + DBG_LOUD, + "RXK Step 1 fail\n"); + } + + /* ====== RX IQK ====== */ + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ + /* 1. RX RF Setting */ + rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x80000); + rtl_set_rfreg(hw, path, 0x30, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, path, 0x31, RFREG_OFFSET_MASK, 0x0002f); + rtl_set_rfreg(hw, path, 0x32, RFREG_OFFSET_MASK, 0xfffbb); + rtl_set_rfreg(hw, path, 0x8f, RFREG_OFFSET_MASK, 0x88001); + rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, 0x931d8); + rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x00000); + + rtl_set_bbreg(hw, 0x978, 0x03FF8000, (tx_x0_rxk[cal])>>21&0x000007ff); + rtl_set_bbreg(hw, 0x978, 0x000007FF, (tx_y0_rxk[cal])>>21&0x000007ff); + rtl_set_bbreg(hw, 0x978, BIT(31), 0x1); + rtl_set_bbreg(hw, 0x97c, BIT(31), 0x0); + rtl_set_bbreg(hw, 0xcb8, 0xF, 0xe); + rtl_write_dword(rtlpriv, 0x90c, 0x00008000); + rtl_write_dword(rtlpriv, 0x984, 0x0046a911); + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ + rtl_set_bbreg(hw, 0xc80, BIT(29), 0x1); + rtl_set_bbreg(hw, 0xc84, BIT(29), 0x0); + rtl_write_dword(rtlpriv, 0xc88, 0x02140119); + + rtl_write_dword(rtlpriv, 0xc8c, 0x28160d00); /* pDM_Odm->SupportInterface == 1 */ + + if (k == 2) + rtl_set_bbreg(hw, 0xce8, BIT(30), 0x1); /* RX VDF Enable */ + rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ + + cal_retry = 0; + while (1) { + /* one shot */ + rtl_write_dword(rtlpriv, 0x980, 0xfa000000); + rtl_write_dword(rtlpriv, 0x980, 0xf8000000); + + mdelay(10); /* Delay 10ms */ + rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); + delay_count = 0; + while (1) { + iqk_ready = rtl_get_bbreg(hw, 0xd00, BIT(10)); + if ((~iqk_ready) || (delay_count > 20)) + break; + else{ + mdelay(1); + delay_count++; + } + } + + if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ + /* ============RXIQK Check============== */ + rx_fail = rtl_get_bbreg(hw, 0xd00, BIT(11)); + if (rx_fail == 0) { + rtl_write_dword(rtlpriv, 0xcb8, 0x06000000); + vdf_x[k] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; + rtl_write_dword(rtlpriv, 0xcb8, 0x08000000); + vdf_y[k] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; + rx0iqkok = true; + break; + } else { + rtl_set_bbreg(hw, 0xc10, 0x000003ff, 0x200>>1); + rtl_set_bbreg(hw, 0xc10, 0x03ff0000, 0x0>>1); + rx0iqkok = false; + cal_retry++; + if (cal_retry == 10) + break; + + } + } else{ + rx0iqkok = false; + cal_retry++; + if (cal_retry == 10) + break; + } + } + + } + if (k == 3) { + rx_x0[cal] = vdf_x[k-1]; + rx_y0[cal] = vdf_y[k-1]; + } + rtl_set_bbreg(hw, 0xce8, BIT(31), 0x1); /* TX VDF Enable */ + } + + else{ + /* ====== RX mode TXK (RXK Step 1) ====== */ + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ + /* 1. TX RF Setting */ + rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x80000); + rtl_set_rfreg(hw, path, 0x30, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, path, 0x31, RFREG_OFFSET_MASK, 0x00029); + rtl_set_rfreg(hw, path, 0x32, RFREG_OFFSET_MASK, 0xd7ffb); + rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, temp_reg65); + rtl_set_rfreg(hw, path, 0x8f, RFREG_OFFSET_MASK, 0x8a001); + rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x00000); + rtl_write_dword(rtlpriv, 0x90c, 0x00008000); + rtl_write_dword(rtlpriv, 0xb00, 0x03000100); + rtl_write_dword(rtlpriv, 0x984, 0x0046a910);/* [0]:AGC_en, [15]:idac_K_Mask */ + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ + rtl_write_dword(rtlpriv, 0xc80, 0x18008c10);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ + rtl_write_dword(rtlpriv, 0xc84, 0x38008c10);/* RX_TONE_idx[9:0], RxK_Mask[29] */ + rtl_write_dword(rtlpriv, 0xc88, 0x821603e0); + /* ODM_Write4Byte(pDM_Odm, 0xc8c, 0x68163e96); */ + rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ + cal_retry = 0; + while (1) { + /* one shot */ + rtl_write_dword(rtlpriv, 0x980, 0xfa000000); + rtl_write_dword(rtlpriv, 0x980, 0xf8000000); + + mdelay(10); /* Delay 10ms */ + rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); + delay_count = 0; + while (1) { + iqk_ready = rtl_get_bbreg(hw, 0xd00, BIT(10)); + if ((~iqk_ready) || (delay_count > 20)) + break; + else{ + mdelay(1); + delay_count++; + } + } + + if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ + /* ============TXIQK Check============== */ + tx_fail = rtl_get_bbreg(hw, 0xd00, BIT(12)); + + if (~tx_fail) { + rtl_write_dword(rtlpriv, 0xcb8, 0x02000000); + tx_x0_rxk[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; + rtl_write_dword(rtlpriv, 0xcb8, 0x04000000); + tx_y0_rxk[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; + tx0iqkok = true; + break; + } else { + tx0iqkok = false; + cal_retry++; + if (cal_retry == 10) + break; + } + } else{ + tx0iqkok = false; + cal_retry++; + if (cal_retry == 10) + break; + } + } + + if (tx0iqkok == false) { /* If RX mode TXK fail, then take TXK Result */ + tx_x0_rxk[cal] = tx_x0[cal]; + tx_y0_rxk[cal] = tx_y0[cal]; + tx0iqkok = true; + RT_TRACE(rtlpriv, COMP_IQK, + DBG_LOUD, "1"); + } + + /* ====== RX IQK ====== */ + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ + /* 1. RX RF Setting */ + rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x80000); + rtl_set_rfreg(hw, path, 0x30, RFREG_OFFSET_MASK, 0x30000); + rtl_set_rfreg(hw, path, 0x31, RFREG_OFFSET_MASK, 0x0002f); + rtl_set_rfreg(hw, path, 0x32, RFREG_OFFSET_MASK, 0xfffbb); + rtl_set_rfreg(hw, path, 0x8f, RFREG_OFFSET_MASK, 0x88001); + rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, 0x931d8); + rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x00000); + + rtl_set_bbreg(hw, 0x978, 0x03FF8000, (tx_x0_rxk[cal])>>21&0x000007ff); + rtl_set_bbreg(hw, 0x978, 0x000007FF, (tx_y0_rxk[cal])>>21&0x000007ff); + rtl_set_bbreg(hw, 0x978, BIT(31), 0x1); + rtl_set_bbreg(hw, 0x97c, BIT(31), 0x0); + /* ODM_SetBBReg(pDM_Odm, 0xcb8, 0xF, 0xe); */ + rtl_write_dword(rtlpriv, 0x90c, 0x00008000); + rtl_write_dword(rtlpriv, 0x984, 0x0046a911); + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ + rtl_write_dword(rtlpriv, 0xc80, 0x38008c10);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ + rtl_write_dword(rtlpriv, 0xc84, 0x18008c10);/* RX_TONE_idx[9:0], RxK_Mask[29] */ + rtl_write_dword(rtlpriv, 0xc88, 0x02140119); + + rtl_write_dword(rtlpriv, 0xc8c, 0x28160d00); /*pDM_Odm->SupportInterface == 1*/ + + rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ + + cal_retry = 0; + while (1) { + /* one shot */ + rtl_write_dword(rtlpriv, 0x980, 0xfa000000); + rtl_write_dword(rtlpriv, 0x980, 0xf8000000); + + mdelay(10); /* Delay 10ms */ + rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); + delay_count = 0; + while (1) { + iqk_ready = rtl_get_bbreg(hw, 0xd00, BIT(10)); + if ((~iqk_ready) || (delay_count > 20)) + break; + else{ + mdelay(1); + delay_count++; + } + } + + if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ + /* ============RXIQK Check============== */ + rx_fail = rtl_get_bbreg(hw, 0xd00, BIT(11)); + if (rx_fail == 0) { + rtl_write_dword(rtlpriv, 0xcb8, 0x06000000); + rx_x0[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; + rtl_write_dword(rtlpriv, 0xcb8, 0x08000000); + rx_y0[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; + rx0iqkok = true; + break; + } else{ + rtl_set_bbreg(hw, 0xc10, 0x000003ff, 0x200>>1); + rtl_set_bbreg(hw, 0xc10, 0x03ff0000, 0x0>>1); + rx0iqkok = false; + cal_retry++; + if (cal_retry == 10) + break; + + } + } else{ + rx0iqkok = false; + cal_retry++; + if (cal_retry == 10) + break; + } + } + } + + if (tx0iqkok) + tx_average++; + if (rx0iqkok) + rx_average++; + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ + rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, temp_reg65); + break; + default: + break; + } + cal++; + } + + /* FillIQK Result */ + switch (path) { + case RF90_PATH_A: + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "========Path_A =======\n"); + if (tx_average == 0) + break; + + for (i = 0; i < tx_average; i++) { + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "TX_X0_RXK[%d] = %x ;; TX_Y0_RXK[%d] = %x\n", i, + (tx_x0_rxk[i])>>21&0x000007ff, i, + (tx_y0_rxk[i])>>21&0x000007ff); + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "TX_X0[%d] = %x ;; TX_Y0[%d] = %x\n", i, + (tx_x0[i])>>21&0x000007ff, i, + (tx_y0[i])>>21&0x000007ff); + } + for (i = 0; i < tx_average; i++) { + for (ii = i+1; ii < tx_average; ii++) { + dx = (tx_x0[i]>>21) - (tx_x0[ii]>>21); + if (dx < 3 && dx > -3) { + dy = (tx_y0[i]>>21) - (tx_y0[ii]>>21); + if (dy < 3 && dy > -3) { + tx_x = ((tx_x0[i]>>21) + (tx_x0[ii]>>21))/2; + tx_y = ((tx_y0[i]>>21) + (tx_y0[ii]>>21))/2; + tx_finish = 1; + break; + } + } + } + if (tx_finish == 1) + break; + } + + if (tx_finish == 1) + _rtl8821ae_iqk_tx_fill_iqc(hw, path, tx_x, tx_y); /* ? */ + else + _rtl8821ae_iqk_tx_fill_iqc(hw, path, 0x200, 0x0); + + if (rx_average == 0) + break; + + for (i = 0; i < rx_average; i++) + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "RX_X0[%d] = %x ;; RX_Y0[%d] = %x\n", i, + (rx_x0[i])>>21&0x000007ff, i, + (rx_y0[i])>>21&0x000007ff); + for (i = 0; i < rx_average; i++) { + for (ii = i+1; ii < rx_average; ii++) { + dx = (rx_x0[i]>>21) - (rx_x0[ii]>>21); + if (dx < 4 && dx > -4) { + dy = (rx_y0[i]>>21) - (rx_y0[ii]>>21); + if (dy < 4 && dy > -4) { + rx_x = ((rx_x0[i]>>21) + (rx_x0[ii]>>21))/2; + rx_y = ((rx_y0[i]>>21) + (rx_y0[ii]>>21))/2; + rx_finish = 1; + break; + } + } + } + if (rx_finish == 1) + break; + } + + if (rx_finish == 1) + _rtl8821ae_iqk_rx_fill_iqc(hw, path, rx_x, rx_y); + else + _rtl8821ae_iqk_rx_fill_iqc(hw, path, 0x200, 0x0); + break; + default: + break; + } +} + +static void _rtl8821ae_iqk_restore_rf(struct ieee80211_hw *hw, + enum radio_path path, + u32 *backup_rf_reg, + u32 *rf_backup, u32 rf_reg_num) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 i; + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ + for (i = 0; i < RF_REG_NUM; i++) + rtl_set_rfreg(hw, path, backup_rf_reg[i], RFREG_OFFSET_MASK, + rf_backup[i]); + + switch (path) { + case RF90_PATH_A: + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "RestoreRF Path A Success!!!!\n"); + break; + default: + break; + } +} + +static void _rtl8821ae_iqk_restore_afe(struct ieee80211_hw *hw, + u32 *afe_backup, u32 *backup_afe_reg, + u32 afe_num) +{ + u32 i; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ + /* Reload AFE Parameters */ + for (i = 0; i < afe_num; i++) + rtl_write_dword(rtlpriv, backup_afe_reg[i], afe_backup[i]); + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ + rtl_write_dword(rtlpriv, 0xc80, 0x0); + rtl_write_dword(rtlpriv, 0xc84, 0x0); + rtl_write_dword(rtlpriv, 0xc88, 0x0); + rtl_write_dword(rtlpriv, 0xc8c, 0x3c000000); + rtl_write_dword(rtlpriv, 0xc90, 0x00000080); + rtl_write_dword(rtlpriv, 0xc94, 0x00000000); + rtl_write_dword(rtlpriv, 0xcc4, 0x20040000); + rtl_write_dword(rtlpriv, 0xcc8, 0x20000000); + rtl_write_dword(rtlpriv, 0xcb8, 0x0); + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "RestoreAFE Success!!!!\n"); +} + +static void _rtl8821ae_iqk_restore_macbb(struct ieee80211_hw *hw, + u32 *macbb_backup, + u32 *backup_macbb_reg, + u32 macbb_num) +{ + u32 i; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ + /* Reload MacBB Parameters */ + for (i = 0; i < macbb_num; i++) + rtl_write_dword(rtlpriv, backup_macbb_reg[i], macbb_backup[i]); + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "RestoreMacBB Success!!!!\n"); +} + +#undef MACBB_REG_NUM +#undef AFE_REG_NUM +#undef RF_REG_NUM + +#define MACBB_REG_NUM 11 +#define AFE_REG_NUM 12 +#define RF_REG_NUM 3 + +static void _rtl8821ae_phy_iq_calibrate(struct ieee80211_hw *hw) +{ + u32 macbb_backup[MACBB_REG_NUM]; + u32 afe_backup[AFE_REG_NUM]; + u32 rfa_backup[RF_REG_NUM]; + u32 rfb_backup[RF_REG_NUM]; + u32 backup_macbb_reg[MACBB_REG_NUM] = { + 0xb00, 0x520, 0x550, 0x808, 0x90c, 0xc00, 0xc50, + 0xe00, 0xe50, 0x838, 0x82c + }; + u32 backup_afe_reg[AFE_REG_NUM] = { + 0xc5c, 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70, 0xc74, + 0xc78, 0xc7c, 0xc80, 0xc84, 0xcb8 + }; + u32 backup_rf_reg[RF_REG_NUM] = {0x65, 0x8f, 0x0}; + + _rtl8821ae_iqk_backup_macbb(hw, macbb_backup, backup_macbb_reg, + MACBB_REG_NUM); + _rtl8821ae_iqk_backup_afe(hw, afe_backup, backup_afe_reg, AFE_REG_NUM); + _rtl8821ae_iqk_backup_rf(hw, rfa_backup, rfb_backup, backup_rf_reg, + RF_REG_NUM); + + _rtl8821ae_iqk_configure_mac(hw); + _rtl8821ae_iqk_tx(hw, RF90_PATH_A); + _rtl8821ae_iqk_restore_rf(hw, RF90_PATH_A, backup_rf_reg, rfa_backup, + RF_REG_NUM); + + _rtl8821ae_iqk_restore_afe(hw, afe_backup, backup_afe_reg, AFE_REG_NUM); + _rtl8821ae_iqk_restore_macbb(hw, macbb_backup, backup_macbb_reg, + MACBB_REG_NUM); +} + +static void _rtl8821ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool main) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + /* struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); */ + /* struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); */ + RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); + + if (main) + rtl_set_bbreg(hw, RA_RFE_PINMUX + 4, BIT(29) | BIT(28), 0x1); + else + rtl_set_bbreg(hw, RA_RFE_PINMUX + 4, BIT(29) | BIT(28), 0x2); +} + +#undef IQK_ADDA_REG_NUM +#undef IQK_DELAY_TIME + +void rtl8812ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) +{ +} + +void rtl8812ae_do_iqk(struct ieee80211_hw *hw, u8 delta_thermal_index, + u8 thermal_value, u8 threshold) +{ + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + + rtldm->thermalvalue_iqk = thermal_value; + rtl8812ae_phy_iq_calibrate(hw, false); +} + +void rtl8821ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + if (!rtlphy->lck_inprogress) { + spin_lock(&rtlpriv->locks.iqk_lock); + rtlphy->lck_inprogress = true; + spin_unlock(&rtlpriv->locks.iqk_lock); + + _rtl8821ae_phy_iq_calibrate(hw); + + spin_lock(&rtlpriv->locks.iqk_lock); + rtlphy->lck_inprogress = false; + spin_unlock(&rtlpriv->locks.iqk_lock); + } +} + +void rtl8821ae_reset_iqk_result(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 i; + + RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, + "rtl8812ae_dm_reset_iqk_result:: settings regs %d default regs %d\n", + (int)(sizeof(rtlphy->iqk_matrix) / + sizeof(struct iqk_matrix_regs)), + IQK_MATRIX_SETTINGS_NUM); + + for (i = 0; i < IQK_MATRIX_SETTINGS_NUM; i++) { + rtlphy->iqk_matrix[i].value[0][0] = 0x100; + rtlphy->iqk_matrix[i].value[0][2] = 0x100; + rtlphy->iqk_matrix[i].value[0][4] = 0x100; + rtlphy->iqk_matrix[i].value[0][6] = 0x100; + + rtlphy->iqk_matrix[i].value[0][1] = 0x0; + rtlphy->iqk_matrix[i].value[0][3] = 0x0; + rtlphy->iqk_matrix[i].value[0][5] = 0x0; + rtlphy->iqk_matrix[i].value[0][7] = 0x0; + + rtlphy->iqk_matrix[i].iqk_done = false; + } +} + +void rtl8821ae_do_iqk(struct ieee80211_hw *hw, u8 delta_thermal_index, + u8 thermal_value, u8 threshold) +{ + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + + rtl8821ae_reset_iqk_result(hw); + + rtldm->thermalvalue_iqk = thermal_value; + rtl8821ae_phy_iq_calibrate(hw, false); +} + +void rtl8821ae_phy_lc_calibrate(struct ieee80211_hw *hw) +{ +} + +void rtl8821ae_phy_ap_calibrate(struct ieee80211_hw *hw, char delta) +{ +} + +void rtl8821ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) +{ + _rtl8821ae_phy_set_rfpath_switch(hw, bmain); +} + +bool rtl8821ae_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + bool postprocessing = false; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "-->IO Cmd(%#x), set_io_inprogress(%d)\n", + iotype, rtlphy->set_io_inprogress); + do { + switch (iotype) { + case IO_CMD_RESUME_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Resume DM after scan.\n"); + postprocessing = true; + break; + case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: + case IO_CMD_PAUSE_BAND1_DM_BY_SCAN: + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "[IO CMD] Pause DM before scan.\n"); + postprocessing = true; + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + } while (false); + if (postprocessing && !rtlphy->set_io_inprogress) { + rtlphy->set_io_inprogress = true; + rtlphy->current_io_type = iotype; + } else { + return false; + } + rtl8821ae_phy_set_io(hw); + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); + return true; +} + +static void rtl8821ae_phy_set_io(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct dig_t *dm_digtable = &rtlpriv->dm_digtable; + struct rtl_phy *rtlphy = &rtlpriv->phy; + + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "--->Cmd(%#x), set_io_inprogress(%d)\n", + rtlphy->current_io_type, rtlphy->set_io_inprogress); + switch (rtlphy->current_io_type) { + case IO_CMD_RESUME_DM_BY_SCAN: + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) + _rtl8821ae_resume_tx_beacon(hw); + rtl8821ae_dm_write_dig(hw, rtlphy->initgain_backup.xaagccore1); + rtl8821ae_dm_write_cck_cca_thres(hw, + rtlphy->initgain_backup.cca); + break; + case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: + if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) + _rtl8821ae_stop_tx_beacon(hw); + rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; + rtl8821ae_dm_write_dig(hw, 0x17); + rtlphy->initgain_backup.cca = dm_digtable->cur_cck_cca_thres; + rtl8821ae_dm_write_cck_cca_thres(hw, 0x40); + break; + case IO_CMD_PAUSE_BAND1_DM_BY_SCAN: + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + break; + } + rtlphy->set_io_inprogress = false; + RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, + "(%#x)\n", rtlphy->current_io_type); +} + +static void rtl8821ae_phy_set_rf_on(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); + rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); +} + +static bool _rtl8821ae_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + bool bresult = true; + u8 i, queue_id; + struct rtl8192_tx_ring *ring = NULL; + + switch (rfpwr_state) { + case ERFON: + if ((ppsc->rfpwr_state == ERFOFF) && + RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { + bool rtstatus = false; + u32 initializecount = 0; + + do { + initializecount++; + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic enable\n"); + rtstatus = rtl_ps_enable_nic(hw); + } while (!rtstatus && (initializecount < 10)); + RT_CLEAR_PS_LEVEL(ppsc, + RT_RF_OFF_LEVL_HALT_NIC); + } else { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "Set ERFON sleeped:%d ms\n", + jiffies_to_msecs(jiffies - + ppsc-> + last_sleep_jiffies)); + ppsc->last_awake_jiffies = jiffies; + rtl8821ae_phy_set_rf_on(hw); + } + if (mac->link_state == MAC80211_LINKED) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } + break; + case ERFOFF: + for (queue_id = 0, i = 0; + queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { + ring = &pcipriv->dev.tx_ring[queue_id]; + if (queue_id == BEACON_QUEUE || + skb_queue_len(&ring->queue) == 0) { + queue_id++; + continue; + } else { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", + (i + 1), queue_id, + skb_queue_len(&ring->queue)); + + udelay(10); + i++; + } + if (i >= MAX_DOZE_WAITING_TIMES_9x) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, + "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", + MAX_DOZE_WAITING_TIMES_9x, + queue_id, + skb_queue_len(&ring->queue)); + break; + } + } + + if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { + RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, + "IPS Set eRf nic disable\n"); + rtl_ps_disable_nic(hw); + RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); + } else { + if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_NO_LINK); + } else { + rtlpriv->cfg->ops->led_control(hw, + LED_CTL_POWER_OFF); + } + } + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "switch case not process\n"); + bresult = false; + break; + } + if (bresult) + ppsc->rfpwr_state = rfpwr_state; + return bresult; +} + +bool rtl8821ae_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state) +{ + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + + bool bresult = false; + + if (rfpwr_state == ppsc->rfpwr_state) + return bresult; + bresult = _rtl8821ae_phy_set_rf_power_state(hw, rfpwr_state); + return bresult; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h new file mode 100644 index 000000000000..c411f0a95cc4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.h @@ -0,0 +1,259 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8821AE_PHY_H__ +#define __RTL8821AE_PHY_H__ + +/* MAX_TX_COUNT must always be set to 4, otherwise read + * efuse table sequence will be wrong. + */ +#define MAX_TX_COUNT 4 +#define TX_1S 0 +#define TX_2S 1 +#define TX_3S 2 +#define TX_4S 3 + +#define MAX_POWER_INDEX 0x3F + +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define MAX_DOZE_WAITING_TIMES_9x 64 + +#define RT_CANNOT_IO(hw) false +#define HIGHPOWER_RADIOA_ARRAYLEN 22 + +#define IQK_ADDA_REG_NUM 16 +#define IQK_BB_REG_NUM 9 +#define MAX_TOLERANCE 5 +#define IQK_DELAY_TIME 10 +#define index_mapping_NUM 15 + +#define APK_BB_REG_NUM 5 +#define APK_AFE_REG_NUM 16 +#define APK_CURVE_REG_NUM 4 +#define PATH_NUM 2 + +#define LOOP_LIMIT 5 +#define MAX_STALL_TIME 50 +#define AntennaDiversityValue 0x80 +#define MAX_TXPWR_IDX_NMODE_92S 63 +#define Reset_Cnt_Limit 3 + +#define IQK_ADDA_REG_NUM 16 +#define IQK_MAC_REG_NUM 4 + +#define RF6052_MAX_PATH 2 + +#define CT_OFFSET_MAC_ADDR 0X16 + +#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A +#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 +#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 +#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 +#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C + +#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F +#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 + +#define CT_OFFSET_CHANNEL_PLAH 0x75 +#define CT_OFFSET_THERMAL_METER 0x78 +#define CT_OFFSET_RF_OPTION 0x79 +#define CT_OFFSET_VERSION 0x7E +#define CT_OFFSET_CUSTOMER_ID 0x7F + +#define RTL8821AE_MAX_PATH_NUM 2 + +#define TARGET_CHNL_NUM_2G_5G_8812 59 + +enum swchnlcmd_id { + CMDID_END, + CMDID_SET_TXPOWEROWER_LEVEL, + CMDID_BBREGWRITE10, + CMDID_WRITEPORT_ULONG, + CMDID_WRITEPORT_USHORT, + CMDID_WRITEPORT_UCHAR, + CMDID_RF_WRITEREG, +}; + +struct swchnlcmd { + enum swchnlcmd_id cmdid; + u32 para1; + u32 para2; + u32 msdelay; +}; + +enum hw90_block_e { + HW90_BLOCK_MAC = 0, + HW90_BLOCK_PHY0 = 1, + HW90_BLOCK_PHY1 = 2, + HW90_BLOCK_RF = 3, + HW90_BLOCK_MAXIMUM = 4, +}; + +enum baseband_config_type { + BASEBAND_CONFIG_PHY_REG = 0, + BASEBAND_CONFIG_AGC_TAB = 1, +}; + +enum ra_offset_area { + RA_OFFSET_LEGACY_OFDM1, + RA_OFFSET_LEGACY_OFDM2, + RA_OFFSET_HT_OFDM1, + RA_OFFSET_HT_OFDM2, + RA_OFFSET_HT_OFDM3, + RA_OFFSET_HT_OFDM4, + RA_OFFSET_HT_CCK, +}; + +enum antenna_path { + ANTENNA_NONE, + ANTENNA_D, + ANTENNA_C, + ANTENNA_CD, + ANTENNA_B, + ANTENNA_BD, + ANTENNA_BC, + ANTENNA_BCD, + ANTENNA_A, + ANTENNA_AD, + ANTENNA_AC, + ANTENNA_ACD, + ANTENNA_AB, + ANTENNA_ABD, + ANTENNA_ABC, + ANTENNA_ABCD +}; + +struct r_antenna_select_ofdm { + u32 r_tx_antenna:4; + u32 r_ant_l:4; + u32 r_ant_non_ht:4; + u32 r_ant_ht1:4; + u32 r_ant_ht2:4; + u32 r_ant_ht_s1:4; + u32 r_ant_non_ht_s1:4; + u32 ofdm_txsc:2; + u32 reserved:2; +}; + +struct r_antenna_select_cck { + u8 r_cckrx_enable_2:2; + u8 r_cckrx_enable:2; + u8 r_ccktx_enable:4; +}; + +struct efuse_contents { + u8 mac_addr[ETH_ALEN]; + u8 cck_tx_power_idx[6]; + u8 ht40_1s_tx_power_idx[6]; + u8 ht40_2s_tx_power_idx_diff[3]; + u8 ht20_tx_power_idx_diff[3]; + u8 ofdm_tx_power_idx_diff[3]; + u8 ht40_max_power_offset[3]; + u8 ht20_max_power_offset[3]; + u8 channel_plan; + u8 thermal_meter; + u8 rf_option[5]; + u8 version; + u8 oem_id; + u8 regulatory; +}; + +struct tx_power_struct { + u8 cck[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht40_1s[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht40_2s[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 ht20_diff[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 legacy_ht_diff[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 legacy_ht_txpowerdiff; + u8 groupht20[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 groupht40[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; + u8 pwrgroup_cnt; + u32 mcs_original_offset[4][16]; +}; +enum _ANT_DIV_TYPE { + NO_ANTDIV = 0xFF, + CG_TRX_HW_ANTDIV = 0x01, + CGCS_RX_HW_ANTDIV = 0x02, + FIXED_HW_ANTDIV = 0x03, + CG_TRX_SMART_ANTDIV = 0x04, + CGCS_RX_SW_ANTDIV = 0x05, + +}; + +u32 rtl8821ae_phy_query_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask); +void rtl8821ae_phy_set_bb_reg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask, u32 data); +u32 rtl8821ae_phy_query_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask); +void rtl8821ae_phy_set_rf_reg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask, u32 data); +bool rtl8821ae_phy_mac_config(struct ieee80211_hw *hw); +bool rtl8821ae_phy_bb_config(struct ieee80211_hw *hw); +bool rtl8821ae_phy_rf_config(struct ieee80211_hw *hw); +void rtl8821ae_phy_switch_wirelessband(struct ieee80211_hw *hw, + u8 band); +void rtl8821ae_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +void rtl8821ae_phy_get_txpower_level(struct ieee80211_hw *hw, + long *powerlevel); +void rtl8821ae_phy_set_txpower_level(struct ieee80211_hw *hw, + u8 channel); +void rtl8821ae_phy_scan_operation_backup(struct ieee80211_hw *hw, + u8 operation); +void rtl8821ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw); +void rtl8821ae_phy_set_bw_mode(struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); +void rtl8821ae_phy_sw_chnl_callback(struct ieee80211_hw *hw); +u8 rtl8821ae_phy_sw_chnl(struct ieee80211_hw *hw); +void rtl8821ae_phy_iq_calibrate(struct ieee80211_hw *hw, + bool b_recovery); +void rtl8812ae_phy_iq_calibrate(struct ieee80211_hw *hw, + bool b_recovery); +void rtl8821ae_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); +void rtl8821ae_phy_lc_calibrate(struct ieee80211_hw *hw); +void rtl8821ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); +bool rtl8812ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +bool rtl8821ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, + enum radio_path rfpath); +bool rtl8821ae_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); +bool rtl8821ae_phy_set_rf_power_state(struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); +u8 _rtl8812ae_get_right_chnl_place_for_iqk(u8 chnl); +void rtl8821ae_phy_set_txpower_level_by_path(struct ieee80211_hw *hw, + u8 channel, u8 path); +void rtl8812ae_do_iqk(struct ieee80211_hw *hw, u8 delta_thermal_index, + u8 thermal_value, u8 threshold); +void rtl8821ae_do_iqk(struct ieee80211_hw *hw, u8 delta_thermal_index, + u8 thermal_value, u8 threshold); +void rtl8821ae_reset_iqk_result(struct ieee80211_hw *hw); +u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band, u8 rf_path); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c new file mode 100644 index 000000000000..9ddf78a187dd --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.c @@ -0,0 +1,182 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../pwrseqcmd.h" +#include "pwrseq.h" + +/* drivers should parse below arrays and do the corresponding actions */ +/* 3 Power on Array */ +struct wlan_pwr_cfg rtl8812_power_on_flow[RTL8812_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8812_TRANS_END_STEPS] = { + RTL8812_TRANS_CARDEMU_TO_ACT + RTL8812_TRANS_END +}; + +/* 3Radio off GPIO Array */ +struct wlan_pwr_cfg rtl8812_radio_off_flow[RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8812_TRANS_END_STEPS] = { + RTL8812_TRANS_ACT_TO_CARDEMU + RTL8812_TRANS_END +}; + +/* 3Card Disable Array */ +struct wlan_pwr_cfg rtl8812_card_disable_flow[RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8812_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8812_TRANS_END_STEPS] = { + RTL8812_TRANS_ACT_TO_CARDEMU + RTL8812_TRANS_CARDEMU_TO_CARDDIS + RTL8812_TRANS_END +}; + +/* 3 Card Enable Array */ +struct wlan_pwr_cfg rtl8812_card_enable_flow[RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8812_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8812_TRANS_END_STEPS] = { + RTL8812_TRANS_CARDDIS_TO_CARDEMU + RTL8812_TRANS_CARDEMU_TO_ACT + RTL8812_TRANS_END +}; + +/* 3Suspend Array */ +struct wlan_pwr_cfg rtl8812_suspend_flow[RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8812_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8812_TRANS_END_STEPS] = { + RTL8812_TRANS_ACT_TO_CARDEMU + RTL8812_TRANS_CARDEMU_TO_SUS + RTL8812_TRANS_END +}; + +/* 3 Resume Array */ +struct wlan_pwr_cfg rtl8812_resume_flow[RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8812_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8812_TRANS_END_STEPS] = { + RTL8812_TRANS_SUS_TO_CARDEMU + RTL8812_TRANS_CARDEMU_TO_ACT + RTL8812_TRANS_END +}; + +/* 3HWPDN Array */ +struct wlan_pwr_cfg rtl8812_hwpdn_flow[RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8812_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8812_TRANS_END_STEPS] = { + RTL8812_TRANS_ACT_TO_CARDEMU + RTL8812_TRANS_CARDEMU_TO_PDN + RTL8812_TRANS_END +}; + +/* 3 Enter LPS */ +struct wlan_pwr_cfg rtl8812_enter_lps_flow[RTL8812_TRANS_ACT_TO_LPS_STEPS + + RTL8812_TRANS_END_STEPS] = { + /* FW behavior */ + RTL8812_TRANS_ACT_TO_LPS + RTL8812_TRANS_END +}; + +/* 3 Leave LPS */ +struct wlan_pwr_cfg rtl8812_leave_lps_flow[RTL8812_TRANS_LPS_TO_ACT_STEPS + + RTL8812_TRANS_END_STEPS] = { + /* FW behavior */ + RTL8812_TRANS_LPS_TO_ACT + RTL8812_TRANS_END +}; + +/* drivers should parse below arrays and do the corresponding actions */ +/*3 Power on Array*/ +struct wlan_pwr_cfg rtl8821A_power_on_flow[RTL8821A_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8821A_TRANS_END_STEPS] = { + RTL8821A_TRANS_CARDEMU_TO_ACT + RTL8821A_TRANS_END +}; + +/*3Radio off GPIO Array */ +struct wlan_pwr_cfg rtl8821A_radio_off_flow[RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8821A_TRANS_END_STEPS] = { + RTL8821A_TRANS_ACT_TO_CARDEMU + RTL8821A_TRANS_END +}; + +/*3Card Disable Array*/ +struct wlan_pwr_cfg rtl8821A_card_disable_flow + [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8821A_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8821A_TRANS_END_STEPS] = { + RTL8821A_TRANS_ACT_TO_CARDEMU + RTL8821A_TRANS_CARDEMU_TO_CARDDIS + RTL8821A_TRANS_END +}; + +/*3 Card Enable Array*/ +/*RTL8821A_TRANS_CARDEMU_TO_PDN_STEPS*/ +struct wlan_pwr_cfg rtl8821A_card_enable_flow + [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8821A_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8821A_TRANS_END_STEPS] = { + RTL8821A_TRANS_CARDDIS_TO_CARDEMU + RTL8821A_TRANS_CARDEMU_TO_ACT + RTL8821A_TRANS_END +}; + +/*3Suspend Array*/ +struct wlan_pwr_cfg rtl8821A_suspend_flow[RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8821A_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8821A_TRANS_END_STEPS] = { + RTL8821A_TRANS_ACT_TO_CARDEMU + RTL8821A_TRANS_CARDEMU_TO_SUS + RTL8821A_TRANS_END +}; + +/*3 Resume Array*/ +struct wlan_pwr_cfg rtl8821A_resume_flow[RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8821A_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8821A_TRANS_END_STEPS] = { + RTL8821A_TRANS_SUS_TO_CARDEMU + RTL8821A_TRANS_CARDEMU_TO_ACT + RTL8821A_TRANS_END +}; + +/*3HWPDN Array*/ +struct wlan_pwr_cfg rtl8821A_hwpdn_flow[RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8821A_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8821A_TRANS_END_STEPS] = { + RTL8821A_TRANS_ACT_TO_CARDEMU + RTL8821A_TRANS_CARDEMU_TO_PDN + RTL8821A_TRANS_END +}; + +/*3 Enter LPS */ +struct wlan_pwr_cfg rtl8821A_enter_lps_flow[RTL8821A_TRANS_ACT_TO_LPS_STEPS + + RTL8821A_TRANS_END_STEPS] = { + /*FW behavior*/ + RTL8821A_TRANS_ACT_TO_LPS + RTL8821A_TRANS_END +}; + +/*3 Leave LPS */ +struct wlan_pwr_cfg rtl8821A_leave_lps_flow[RTL8821A_TRANS_LPS_TO_ACT_STEPS + + RTL8821A_TRANS_END_STEPS] = { + /*FW behavior*/ + RTL8821A_TRANS_LPS_TO_ACT + RTL8821A_TRANS_END +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h new file mode 100644 index 000000000000..36b3e91d996e --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h @@ -0,0 +1,738 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8821AE_PWRSEQ_H__ +#define __RTL8821AE_PWRSEQ_H__ + +#include "../pwrseqcmd.h" +#include "../btcoexist/halbt_precomp.h" + +#define RTL8812_TRANS_CARDEMU_TO_ACT_STEPS 15 +#define RTL8812_TRANS_ACT_TO_CARDEMU_STEPS 15 +#define RTL8812_TRANS_CARDEMU_TO_SUS_STEPS 15 +#define RTL8812_TRANS_SUS_TO_CARDEMU_STEPS 15 +#define RTL8812_TRANS_CARDEMU_TO_PDN_STEPS 25 +#define RTL8812_TRANS_PDN_TO_CARDEMU_STEPS 15 +#define RTL8812_TRANS_ACT_TO_LPS_STEPS 15 +#define RTL8812_TRANS_LPS_TO_ACT_STEPS 15 +#define RTL8812_TRANS_END_STEPS 1 + +/* The following macros have the following format: + * { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value + * comments }, + */ +#define RTL8812_TRANS_CARDEMU_TO_ACT \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT2, 0 \ + /* disable SW LPS 0x04[10]=0*/}, \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, BIT1 \ + /* wait till 0x04[17] = 1 power ready*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0 \ + /* disable HWPDN 0x04[15]=0*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3, 0 \ + /* disable WL suspend*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ + /* polling until return 0*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT0, 0}, + +#define RTL8812_TRANS_ACT_TO_CARDEMU \ + {0x0c00, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x04 \ + /* 0xc00[7:0] = 4 turn off 3-wire */}, \ + {0x0e00, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x04 \ + /* 0xe00[7:0] = 4 turn off 3-wire */}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ + /* 0x2[0] = 0 RESET BB, CLOSE RF */}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US \ + /*Delay 1us*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ + /* Whole BB is reset*/}, \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x2A \ + /* 0x07[7:0] = 0x28 sps pwm mode 0x2a for BT coex*/}, \ + {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x02, 0 \ + /*0x8[1] = 0 ANA clk =500k */}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ + /*0x04[9] = 1 turn off MAC by HW state machine*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, 0 \ + /*wait till 0x04[9] = 0 polling until return 0 to disable*/}, + +#define RTL8812_TRANS_CARDEMU_TO_SUS \ + {0x0042, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xF0, 0xc0}, \ + {0x0042, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xF0, 0xE0}, \ + {0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x07 \ + /* gpio11 input mode, gpio10~8 output mode */}, \ + {0x0045, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ + /* gpio 0~7 output same value as input ?? */}, \ + {0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xff \ + /* gpio0~7 output mode */}, \ + {0x0047, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ + /* 0x47[7:0] = 00 gpio mode */}, \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ + /* suspend option all off */}, \ + {0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x80, BIT7 \ + /*0x14[7] = 1 turn on ZCD */}, \ + {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x01, BIT0 \ + /* 0x15[0] =1 trun on ZCD */}, \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x10, BIT4 \ + /*0x23[4] = 1 hpon LDO sleep mode */}, \ + {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x02, 0 \ + /*0x8[1] = 0 ANA clk =500k */}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3, BIT3 \ + /*0x04[11] = 2b'11 enable WL suspend for PCIe*/}, + +#define RTL8812_TRANS_SUS_TO_CARDEMU \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3, 0 \ + /*0x04[11] = 2b'01enable WL suspend*/}, \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x10, 0 \ + /*0x23[4] = 0 hpon LDO sleep mode leave */}, \ + {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x01, 0 \ + /* 0x15[0] =0 trun off ZCD */}, \ + {0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x80, 0 \ + /*0x14[7] = 0 turn off ZCD */}, \ + {0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ + /* gpio0~7 input mode */}, \ + {0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ + /* gpio11 input mode, gpio10~8 input mode */}, + +#define RTL8812_TRANS_CARDEMU_TO_CARDDIS \ + {0x0003, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT2, 0 \ + /*0x03[2] = 0, reset 8051*/}, \ + {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x05 \ + /*0x80=05h if reload fw, fill the default value of host_CPU handshake field*/}, \ + {0x0042, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xF0, 0xcc}, \ + {0x0042, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xF0, 0xEC}, \ + {0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x07 \ + /* gpio11 input mode, gpio10~8 output mode */}, \ + {0x0045, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ + /* gpio 0~7 output same value as input ?? */}, \ + {0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xff \ + /* gpio0~7 output mode */}, \ + {0x0047, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ + /* 0x47[7:0] = 00 gpio mode */}, \ + {0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x80, BIT7 \ + /*0x14[7] = 1 turn on ZCD */}, \ + {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x01, BIT0 \ + /* 0x15[0] =1 trun on ZCD */}, \ + {0x0012, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x01, 0 \ + /*0x12[0] = 0 force PFM mode */}, \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x10, BIT4 \ + /*0x23[4] = 1 hpon LDO sleep mode */}, \ + {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x02, 0 \ + /*0x8[1] = 0 ANA clk =500k */}, \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20 \ + /*0x07=0x20 , SOP option to disable BG/MB*/}, \ + {0x001f, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ + /*0x01f[1]=0 , disable RFC_0 control REG_RF_CTRL_8812 */}, \ + {0x0076, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ + /*0x076[1]=0 , disable RFC_1 control REG_OPT_CTRL_8812 +2 */}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3, BIT3 \ + /*0x04[11] = 2b'01 enable WL suspend*/}, + +#define RTL8812_TRANS_CARDDIS_TO_CARDEMU \ + {0x0012, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ + /*0x12[0] = 1 force PWM mode */}, \ + {0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x80, 0 \ + /*0x14[7] = 0 turn off ZCD */}, \ + {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x01, 0 \ + /* 0x15[0] =0 trun off ZCD */}, \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x10, 0 \ + /*0x23[4] = 0 hpon LDO leave sleep mode */}, \ + {0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ + /* gpio0~7 input mode */}, \ + {0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ + /* gpio11 input mode, gpio10~8 input mode */}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT2, 0 \ + /*0x04[10] = 0, enable SW LPS PCIE only*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3, 0 \ + /*0x04[11] = 2b'01enable WL suspend*/}, \ + {0x0003, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT2, BIT2 \ + /*0x03[2] = 1, enable 8051*/}, \ + {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ + /*PCIe DMA start*/}, + +#define RTL8812_TRANS_CARDEMU_TO_PDN \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, BIT7 \ + /* 0x04[15] = 1*/}, + +#define RTL8812_TRANS_PDN_TO_CARDEMU \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0 \ + /* 0x04[15] = 0*/}, + +#define RTL8812_TRANS_ACT_TO_LPS \ + {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF \ + /*PCIe DMA stop*/}, \ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x7F \ + /*Tx Pause*/}, \ + {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ + /*Should be zero if no packet is transmitting*/}, \ + {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ + /*Should be zero if no packet is transmitting*/}, \ + {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ + /*Should be zero if no packet is transmitting*/}, \ + {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ + /*Should be zero if no packet is transmitting*/}, \ + {0x0c00, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x04 \ + /* 0xc00[7:0] = 4 turn off 3-wire */}, \ + {0x0e00, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x04 \ + /* 0xe00[7:0] = 4 turn off 3-wire */}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ + /*CCK and OFDM are disabled,and clock are gated,and RF closed*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US \ + /*Delay 1us*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ + /* Whole BB is reset*/}, \ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x03 \ + /*Reset MAC TRX*/}, \ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ + /*check if removed later*/}, \ + {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, BIT5 \ + /*Respond TxOK to scheduler*/}, + +#define RTL8812_TRANS_LPS_TO_ACT \ + {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84 \ + /*SDIO RPWM*/}, \ + {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84 \ + /*USB RPWM*/}, \ + {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84 \ + /*PCIe RPWM*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS \ + /*Delay*/}, \ + {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0 \ + /*. 0x08[4] = 0 switch TSF to 40M*/}, \ + {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT7, 0 \ + /*Polling 0x109[7]=0 TSF in 40M*/}, \ + {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT6|BIT7, 0 \ + /*. 0x29[7:6] = 2b'00 enable BB clock*/}, \ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ + /*. 0x101[1] = 1*/}, \ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF \ + /*. 0x100[7:0] = 0xFF enable WMAC TRX*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1|BIT0, BIT1|BIT0 \ + /*. 0x02[1:0] = 2b'11 enable BB macro*/}, \ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ + /*. 0x522 = 0*/}, + +#define RTL8812_TRANS_END \ + {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ + 0, PWR_CMD_END, 0, 0}, + +extern struct wlan_pwr_cfg rtl8812_power_on_flow + [RTL8812_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8812_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8812_radio_off_flow + [RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8812_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8812_card_disable_flow + [RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8812_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8812_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8812_card_enable_flow + [RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8812_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8812_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8812_suspend_flow + [RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8812_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8812_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8812_resume_flow + [RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8812_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8812_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8812_hwpdn_flow + [RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8812_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8812_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8812_enter_lps_flow + [RTL8812_TRANS_ACT_TO_LPS_STEPS + + RTL8812_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8812_leave_lps_flow + [RTL8812_TRANS_LPS_TO_ACT_STEPS + + RTL8812_TRANS_END_STEPS]; + +/* Check document WM-20130516-JackieLau-RTL8821A_Power_Architecture-R10.vsd + * There are 6 HW Power States: + * 0: POFF--Power Off + * 1: PDN--Power Down + * 2: CARDEMU--Card Emulation + * 3: ACT--Active Mode + * 4: LPS--Low Power State + * 5: SUS--Suspend + * + * The transision from different states are defined below + * TRANS_CARDEMU_TO_ACT + * TRANS_ACT_TO_CARDEMU + * TRANS_CARDEMU_TO_SUS + * TRANS_SUS_TO_CARDEMU + * TRANS_CARDEMU_TO_PDN + * TRANS_ACT_TO_LPS + * TRANS_LPS_TO_ACT + * + * TRANS_END + */ +#define RTL8821A_TRANS_CARDEMU_TO_ACT_STEPS 25 +#define RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS 15 +#define RTL8821A_TRANS_CARDEMU_TO_SUS_STEPS 15 +#define RTL8821A_TRANS_SUS_TO_CARDEMU_STEPS 15 +#define RTL8821A_TRANS_CARDDIS_TO_CARDEMU_STEPS 15 +#define RTL8821A_TRANS_CARDEMU_TO_PDN_STEPS 15 +#define RTL8821A_TRANS_PDN_TO_CARDEMU_STEPS 15 +#define RTL8821A_TRANS_ACT_TO_LPS_STEPS 15 +#define RTL8821A_TRANS_LPS_TO_ACT_STEPS 15 +#define RTL8821A_TRANS_END_STEPS 1 + +#define RTL8821A_TRANS_CARDEMU_TO_ACT \ + {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ + /*0x20[0] = 1b'1 enable LDOA12 MACRO block for all interface*/}, \ + {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0 \ + /*0x67[0] = 0 to disable BT_GPS_SEL pins*/}, \ + {0x0001, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_DELAY, 1, PWRSEQ_DELAY_MS \ + /*Delay 1ms*/}, \ + {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, 0 \ + /*0x00[5] = 1b'0 release analog Ips to digital ,1:isolation*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT4|BIT3|BIT2), 0 \ + /* disable SW LPS 0x04[10]=0 and WLSUS_EN 0x04[12:11]=0*/}, \ + {0x0075, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0 , BIT0 \ + /* Disable USB suspend */}, \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, BIT1 \ + /* wait till 0x04[17] = 1 power ready*/}, \ + {0x0075, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0 , 0 \ + /* Enable USB suspend */}, \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ + /* release WLON reset 0x04[16]=1*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0 \ + /* disable HWPDN 0x04[15]=0*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT4|BIT3), 0 \ + /* disable WL suspend*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ + /* polling until return 0*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT0, 0 \ + /**/}, \ + {0x004F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ + /*0x4C[24] = 0x4F[0] = 1, switch DPDT_SEL_P output from WL BB */},\ + {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT5|BIT4), (BIT5|BIT4) \ + /*0x66[13] = 0x67[5] = 1, switch for PAPE_G/PAPE_A \ + from WL BB ; 0x66[12] = 0x67[4] = 1, switch LNAON from WL BB */},\ + {0x0025, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT6, 0 \ + /*anapar_mac<118> , 0x25[6]=0 by wlan single function*/},\ + {0x0049, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ + /*Enable falling edge triggering interrupt*/},\ + {0x0063, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ + /*Enable GPIO9 interrupt mode*/},\ + {0x0062, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ + /*Enable GPIO9 input mode*/},\ + {0x0058, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ + /*Enable HSISR GPIO[C:0] interrupt*/},\ + {0x005A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ + /*Enable HSISR GPIO9 interrupt*/},\ + {0x007A, PWR_CUT_TESTCHIP_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3A \ + /*0x7A = 0x3A start BT*/},\ + {0x002E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF , 0x82 \ + /* 0x2C[23:12]=0x820 ; XTAL trim */}, \ + {0x0010, PWR_CUT_A_MSK , PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT6 , BIT6 \ + /* 0x10[6]=1 */}, + +#define RTL8821A_TRANS_ACT_TO_CARDEMU \ + {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ + /*0x1F[7:0] = 0 turn off RF*/}, \ + {0x004F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ + /*0x4C[24] = 0x4F[0] = 0, switch DPDT_SEL_P output from \ + register 0x65[2] */},\ + {0x0049, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ + /*Enable rising edge triggering interrupt*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ + /*0x04[9] = 1 turn off MAC by HW state machine*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, 0 \ + /*wait till 0x04[9] = 0 polling until return 0 to disable*/}, \ + {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, BIT5 \ + /*0x00[5] = 1b'1 analog Ips to digital ,1:isolation*/}, \ + {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ + /*0x20[0] = 1b'0 disable LDOA12 MACRO block*/}, + +#define RTL8821A_TRANS_CARDEMU_TO_SUS \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4|BIT3, (BIT4|BIT3) \ + /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, BIT3 \ + /*0x04[12:11] = 2b'01 enable WL suspend*/}, \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4 \ + /*0x23[4] = 1b'1 12H LDO enter sleep mode*/}, \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20 \ + /*0x07[7:0] = 0x20 SDIO SOP option to disable BG/MB/ACK/SWR*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, BIT3|BIT4 \ + /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, BIT0 \ + /*Set SDIO suspend local register*/}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, 0 \ + /*wait power state to suspend*/}, + +#define RTL8821A_TRANS_SUS_TO_CARDEMU \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3 | BIT7, 0 \ + /*clear suspend enable and power down enable*/}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, 0 \ + /*Set SDIO suspend local register*/}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, BIT1 \ + /*wait power state to suspend*/},\ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0 \ + /*0x23[4] = 1b'0 12H LDO enter normal mode*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, 0 \ + /*0x04[12:11] = 2b'01enable WL suspend*/}, + +#define RTL8821A_TRANS_CARDEMU_TO_CARDDIS \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20 \ + /*0x07=0x20 , SOP option to disable BG/MB*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, BIT3 \ + /*0x04[12:11] = 2b'01 enable WL suspend*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT2, BIT2 \ + /*0x04[10] = 1, enable SW LPS*/}, \ + {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 1 \ + /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/}, \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4 \ + /*0x23[4] = 1b'1 12H LDO enter sleep mode*/}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, BIT0 \ + /*Set SDIO suspend local register*/}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, 0 \ + /*wait power state to suspend*/}, + +#define RTL8821A_TRANS_CARDDIS_TO_CARDEMU \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3 | BIT7, 0 \ + /*clear suspend enable and power down enable*/}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, 0 \ + /*Set SDIO suspend local register*/}, \ + {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, BIT1 \ + /*wait power state to suspend*/},\ + {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ + /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/}, \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, 0 \ + /*0x04[12:11] = 2b'01enable WL suspend*/},\ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0 \ + /*0x23[4] = 1b'0 12H LDO enter normal mode*/}, \ + {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ + /*PCIe DMA start*/}, + +#define RTL8821A_TRANS_CARDEMU_TO_PDN \ + {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4 \ + /*0x23[4] = 1b'1 12H LDO enter sleep mode*/}, \ + {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ + PWR_INTF_SDIO_MSK|PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20 \ + /*0x07[7:0] = 0x20 SOP option to disable BG/MB/ACK/SWR*/}, \ + {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ + /* 0x04[16] = 0*/},\ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, BIT7 \ + /* 0x04[15] = 1*/}, + +#define RTL8821A_TRANS_PDN_TO_CARDEMU \ + {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0 \ + /* 0x04[15] = 0*/}, + +#define RTL8821A_TRANS_ACT_TO_LPS \ + {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF \ + /*PCIe DMA stop*/}, \ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF \ + /*Tx Pause*/}, \ + {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ + /*Should be zero if no packet is transmitting*/}, \ + {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ + /*Should be zero if no packet is transmitting*/}, \ + {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ + /*Should be zero if no packet is transmitting*/}, \ + {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ + /*Should be zero if no packet is transmitting*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ + /*CCK and OFDM are disabled,and clock are gated*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US \ + /*Delay 1us*/}, \ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ + /*Whole BB is reset*/}, \ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x03 \ + /*Reset MAC TRX*/}, \ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ + /*check if removed later*/}, \ + {0x0093, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ + /*When driver enter Sus/ Disable, enable LOP for BT*/}, \ + {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, BIT5 \ + /*Respond TxOK to scheduler*/}, + +#define RTL8821A_TRANS_LPS_TO_ACT \ + {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ + PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84 \ + /*SDIO RPWM*/},\ + {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84 \ + /*USB RPWM*/},\ + {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84 \ + /*PCIe RPWM*/},\ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS \ + /*Delay*/},\ + {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0 \ + /*. 0x08[4] = 0 switch TSF to 40M*/},\ + {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT7, 0 \ + /*Polling 0x109[7]=0 TSF in 40M*/},\ + {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT6|BIT7, 0 \ + /*. 0x29[7:6] = 2b'00 enable BB clock*/},\ + {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ + /*. 0x101[1] = 1*/},\ + {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF \ + /*. 0x100[7:0] = 0xFF enable WMAC TRX*/},\ + {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1|BIT0, BIT1|BIT0 \ + /*. 0x02[1:0] = 2b'11 enable BB macro*/},\ + {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ + /*. 0x522 = 0*/}, + +#define RTL8821A_TRANS_END \ + {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ + 0, PWR_CMD_END, 0, 0}, + +extern struct wlan_pwr_cfg rtl8821A_power_on_flow + [RTL8821A_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8821A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8821A_radio_off_flow + [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8821A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8821A_card_disable_flow + [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8821A_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8821A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8821A_card_enable_flow + [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8821A_TRANS_CARDEMU_TO_ACT_STEPS + + RTL8821A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8821A_suspend_flow + [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8821A_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8821A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8821A_resume_flow + [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8821A_TRANS_CARDEMU_TO_SUS_STEPS + + RTL8821A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8821A_hwpdn_flow + [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + + RTL8821A_TRANS_CARDEMU_TO_PDN_STEPS + + RTL8821A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8821A_enter_lps_flow + [RTL8821A_TRANS_ACT_TO_LPS_STEPS + + RTL8821A_TRANS_END_STEPS]; +extern struct wlan_pwr_cfg rtl8821A_leave_lps_flow + [RTL8821A_TRANS_LPS_TO_ACT_STEPS + + RTL8821A_TRANS_END_STEPS]; + +/*RTL8812 Power Configuration CMDs for PCIe interface*/ +#define RTL8812_NIC_PWR_ON_FLOW rtl8812_power_on_flow +#define RTL8812_NIC_RF_OFF_FLOW rtl8812_radio_off_flow +#define RTL8812_NIC_DISABLE_FLOW rtl8812_card_disable_flow +#define RTL8812_NIC_ENABLE_FLOW rtl8812_card_enable_flow +#define RTL8812_NIC_SUSPEND_FLOW rtl8812_suspend_flow +#define RTL8812_NIC_RESUME_FLOW rtl8812_resume_flow +#define RTL8812_NIC_PDN_FLOW rtl8812_hwpdn_flow +#define RTL8812_NIC_LPS_ENTER_FLOW rtl8812_enter_lps_flow +#define RTL8812_NIC_LPS_LEAVE_FLOW rtl8812_leave_lps_flow + +/* RTL8821 Power Configuration CMDs for PCIe interface */ +#define RTL8821A_NIC_PWR_ON_FLOW rtl8821A_power_on_flow +#define RTL8821A_NIC_RF_OFF_FLOW rtl8821A_radio_off_flow +#define RTL8821A_NIC_DISABLE_FLOW rtl8821A_card_disable_flow +#define RTL8821A_NIC_ENABLE_FLOW rtl8821A_card_enable_flow +#define RTL8821A_NIC_SUSPEND_FLOW rtl8821A_suspend_flow +#define RTL8821A_NIC_RESUME_FLOW rtl8821A_resume_flow +#define RTL8821A_NIC_PDN_FLOW rtl8821A_hwpdn_flow +#define RTL8821A_NIC_LPS_ENTER_FLOW rtl8821A_enter_lps_flow +#define RTL8821A_NIC_LPS_LEAVE_FLOW rtl8821A_leave_lps_flow + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h new file mode 100644 index 000000000000..1d6110f9c1fb --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/reg.h @@ -0,0 +1,2465 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8821AE_REG_H__ +#define __RTL8821AE_REG_H__ + +#define TXPKT_BUF_SELECT 0x69 +#define RXPKT_BUF_SELECT 0xA5 +#define DISABLE_TRXPKT_BUF_ACCESS 0x0 + +#define REG_SYS_ISO_CTRL 0x0000 +#define REG_SYS_FUNC_EN 0x0002 +#define REG_APS_FSMCO 0x0004 +#define REG_SYS_CLKR 0x0008 +#define REG_9346CR 0x000A +#define REG_EE_VPD 0x000C +#define REG_AFE_MISC 0x0010 +#define REG_SPS0_CTRL 0x0011 +#define REG_SPS_OCP_CFG 0x0018 +#define REG_RSV_CTRL 0x001C +#define REG_RF_CTRL 0x001F +#define REG_LDOA15_CTRL 0x0020 +#define REG_LDOV12D_CTRL 0x0021 +#define REG_LDOHCI12_CTRL 0x0022 +#define REG_LPLDO_CTRL 0x0023 +#define REG_AFE_XTAL_CTRL 0x0024 + /* 1.5v for 8188EE test chip, 1.4v for MP chip */ +#define REG_AFE_LDO_CTRL 0x0027 +#define REG_AFE_PLL_CTRL 0x0028 +#define REG_MAC_PHY_CTRL 0x002c +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define REG_PWR_DATA 0x0038 +#define REG_CAL_TIMER 0x003C +#define REG_ACLK_MON 0x003E +#define REG_GPIO_MUXCFG 0x0040 +#define REG_GPIO_IO_SEL 0x0042 +#define REG_MAC_PINMUX_CFG 0x0043 +#define REG_GPIO_PIN_CTRL 0x0044 +#define REG_GPIO_INTM 0x0048 +#define REG_LEDCFG0 0x004C +#define REG_LEDCFG1 0x004D +#define REG_LEDCFG2 0x004E +#define REG_LEDCFG3 0x004F +#define REG_FSIMR 0x0050 +#define REG_FSISR 0x0054 +#define REG_HSIMR 0x0058 +#define REG_HSISR 0x005c +#define REG_GPIO_PIN_CTRL_2 0x0060 +#define REG_GPIO_IO_SEL_2 0x0062 +#define REG_MULTI_FUNC_CTRL 0x0068 +#define REG_GPIO_OUTPUT 0x006c +#define REG_OPT_CTRL 0x0074 +#define REG_AFE_XTAL_CTRL_EXT 0x0078 +#define REG_XCK_OUT_CTRL 0x007c +#define REG_MCUFWDL 0x0080 +#define REG_WOL_EVENT 0x0081 +#define REG_MCUTSTCFG 0x0084 + +#define REG_HIMR 0x00B0 +#define REG_HISR 0x00B4 +#define REG_HIMRE 0x00B8 +#define REG_HISRE 0x00BC + +#define REG_PMC_DBG_CTRL2 0x00CC + +#define REG_EFUSE_ACCESS 0x00CF + +#define REG_BIST_SCAN 0x00D0 +#define REG_BIST_RPT 0x00D4 +#define REG_BIST_ROM_RPT 0x00D8 +#define REG_USB_SIE_INTF 0x00E0 +#define REG_PCIE_MIO_INTF 0x00E4 +#define REG_PCIE_MIO_INTD 0x00E8 +#define REG_HPON_FSM 0x00EC +#define REG_SYS_CFG 0x00F0 +#define REG_GPIO_OUTSTS 0x00F4 +#define REG_MAC_PHY_CTRL_NORMAL 0x00F8 +#define REG_SYS_CFG1 0x00FC +#define REG_ROM_VERSION 0x00FD + +#define REG_CR 0x0100 +#define REG_PBP 0x0104 +#define REG_PKT_BUFF_ACCESS_CTRL 0x0106 +#define REG_TRXDMA_CTRL 0x010C +#define REG_TRXFF_BNDY 0x0114 +#define REG_TRXFF_STATUS 0x0118 +#define REG_RXFF_PTR 0x011C + +#define REG_CPWM 0x012F +#define REG_FWIMR 0x0130 +#define REG_FWISR 0x0134 +#define REG_FTISR 0x013C +#define REG_PKTBUF_DBG_CTRL 0x0140 +#define REG_PKTBUF_DBG_DATA_L 0x0144 +#define REG_PKTBUF_DBG_DATA_H 0x0148 +#define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL+2) + +#define REG_TC0_CTRL 0x0150 +#define REG_TC1_CTRL 0x0154 +#define REG_TC2_CTRL 0x0158 +#define REG_TC3_CTRL 0x015C +#define REG_TC4_CTRL 0x0160 +#define REG_TCUNIT_BASE 0x0164 +#define REG_MBIST_START 0x0174 +#define REG_MBIST_DONE 0x0178 +#define REG_MBIST_FAIL 0x017C +#define REG_32K_CTRL 0x0194 +#define REG_C2HEVT_MSG_NORMAL 0x01A0 +#define REG_C2HEVT_CLEAR 0x01AF +#define REG_C2HEVT_MSG_TEST 0x01B8 +#define REG_MCUTST_1 0x01c0 +#define REG_MCUTST_WOWLAN 0x01C7 +#define REG_FMETHR 0x01C8 +#define REG_HMETFR 0x01CC +#define REG_HMEBOX_0 0x01D0 +#define REG_HMEBOX_1 0x01D4 +#define REG_HMEBOX_2 0x01D8 +#define REG_HMEBOX_3 0x01DC + +#define REG_LLT_INIT 0x01E0 +#define REG_BB_ACCEESS_CTRL 0x01E8 +#define REG_BB_ACCESS_DATA 0x01EC + +#define REG_HMEBOX_EXT_0 0x01F0 +#define REG_HMEBOX_EXT_1 0x01F4 +#define REG_HMEBOX_EXT_2 0x01F8 +#define REG_HMEBOX_EXT_3 0x01FC + +#define REG_RQPN 0x0200 +#define REG_FIFOPAGE 0x0204 +#define REG_TDECTRL 0x0208 +#define REG_TXDMA_OFFSET_CHK 0x020C +#define REG_TXDMA_STATUS 0x0210 +#define REG_RQPN_NPQ 0x0214 + +#define REG_RXDMA_AGG_PG_TH 0x0280 + /* FW shall update this register before FW write RXPKT_RELEASE_POLL to 1 */ +#define REG_FW_UPD_RDPTR 0x0284 + /* Control the RX DMA.*/ +#define REG_RXDMA_CONTROL 0x0286 +/* The number of packets in RXPKTBUF. */ +#define REG_RXPKT_NUM 0x0287 + +#define REG_PCIE_CTRL_REG 0x0300 +#define REG_INT_MIG 0x0304 +#define REG_BCNQ_DESA 0x0308 +#define REG_HQ_DESA 0x0310 +#define REG_MGQ_DESA 0x0318 +#define REG_VOQ_DESA 0x0320 +#define REG_VIQ_DESA 0x0328 +#define REG_BEQ_DESA 0x0330 +#define REG_BKQ_DESA 0x0338 +#define REG_RX_DESA 0x0340 + +#define REG_DBI_WDATA 0x0348 +#define REG_DBI_RDATA 0x034C +#define REG_DBI_CTRL 0x0350 +#define REG_DBI_ADDR 0x0350 +#define REG_DBI_FLAG 0x0352 +#define REG_MDIO_WDATA 0x0354 +#define REG_MDIO_RDATA 0x0356 +#define REG_MDIO_CTL 0x0358 +#define REG_DBG_SEL 0x0360 +#define REG_PCIE_HRPWM 0x0361 +#define REG_PCIE_HCPWM 0x0363 +#define REG_UART_CTRL 0x0364 +#define REG_WATCH_DOG 0x0368 +#define REG_UART_TX_DESA 0x0370 +#define REG_UART_RX_DESA 0x0378 + +#define REG_HDAQ_DESA_NODEF 0x0000 +#define REG_CMDQ_DESA_NODEF 0x0000 + +#define REG_VOQ_INFORMATION 0x0400 +#define REG_VIQ_INFORMATION 0x0404 +#define REG_BEQ_INFORMATION 0x0408 +#define REG_BKQ_INFORMATION 0x040C +#define REG_MGQ_INFORMATION 0x0410 +#define REG_HGQ_INFORMATION 0x0414 +#define REG_BCNQ_INFORMATION 0x0418 +#define REG_TXPKT_EMPTY 0x041A + +#define REG_CPU_MGQ_INFORMATION 0x041C +#define REG_FWHW_TXQ_CTRL 0x0420 +#define REG_HWSEQ_CTRL 0x0423 +#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 +#define REG_TXPKTBUF_MGQ_BDNY 0x0425 +#define REG_MULTI_BCNQ_EN 0x0426 +#define REG_MULTI_BCNQ_OFFSET 0x0427 +#define REG_SPEC_SIFS 0x0428 +#define REG_RL 0x042A +#define REG_DARFRC 0x0430 +#define REG_RARFRC 0x0438 +#define REG_RRSR 0x0440 +#define REG_ARFR0 0x0444 +#define REG_ARFR1 0x044C +#define REG_CCK_CHECK 0x0454 +#define REG_AMPDU_MAX_TIME 0x0456 +#define REG_AGGLEN_LMT 0x0458 +#define REG_AMPDU_MIN_SPACE 0x045C +#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D +#define REG_FAST_EDCA_CTRL 0x0460 +#define REG_RD_RESP_PKT_TH 0x0463 +#define REG_INIRTS_RATE_SEL 0x0480 +#define REG_INIDATA_RATE_SEL 0x0484 +#define REG_ARFR2 0x048C +#define REG_ARFR3 0x0494 +#define REG_POWER_STATUS 0x04A4 +#define REG_POWER_STAGE1 0x04B4 +#define REG_POWER_STAGE2 0x04B8 +#define REG_PKT_LIFE_TIME 0x04C0 +#define REG_STBC_SETTING 0x04C4 +#define REG_HT_SINGLE_AMPDU 0x04C7 +#define REG_PROT_MODE_CTRL 0x04C8 +#define REG_MAX_AGGR_NUM 0x04CA +#define REG_BAR_MODE_CTRL 0x04CC +#define REG_RA_TRY_RATE_AGG_LMT 0x04CF +#define REG_EARLY_MODE_CONTROL 0x04D0 +#define REG_NQOS_SEQ 0x04DC +#define REG_QOS_SEQ 0x04DE +#define REG_NEED_CPU_HANDLE 0x04E0 +#define REG_PKT_LOSE_RPT 0x04E1 +#define REG_PTCL_ERR_STATUS 0x04E2 +#define REG_TX_RPT_CTRL 0x04EC +#define REG_TX_RPT_TIME 0x04F0 +#define REG_DUMMY 0x04FC + +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050C +#define REG_BCNTCFG 0x0510 +#define REG_PIFS 0x0512 +#define REG_RDG_PIFS 0x0513 +#define REG_SIFS_CTX 0x0514 +#define REG_SIFS_TRX 0x0516 +#define REG_AGGR_BREAK_TIME 0x051A +#define REG_SLOT 0x051B +#define REG_TX_PTCL_CTRL 0x0520 +#define REG_TXPAUSE 0x0522 +#define REG_DIS_TXREQ_CLR 0x0523 +#define REG_RD_CTRL 0x0524 +#define REG_TBTT_PROHIBIT 0x0540 +#define REG_RD_NAV_NXT 0x0544 +#define REG_NAV_PROT_LEN 0x0546 +#define REG_BCN_CTRL 0x0550 +#define REG_USTIME_TSF 0x0551 +#define REG_MBID_NUM 0x0552 +#define REG_DUAL_TSF_RST 0x0553 +#define REG_BCN_INTERVAL 0x0554 +#define REG_MBSSID_BCN_SPACE 0x0554 +#define REG_DRVERLYINT 0x0558 +#define REG_BCNDMATIM 0x0559 +#define REG_ATIMWND 0x055A +#define REG_BCN_MAX_ERR 0x055D +#define REG_RXTSF_OFFSET_CCK 0x055E +#define REG_RXTSF_OFFSET_OFDM 0x055F +#define REG_TSFTR 0x0560 +#define REG_INIT_TSFTR 0x0564 +#define REG_SECONDARY_CCA_CTRL 0x0577 +#define REG_PSTIMER 0x0580 +#define REG_TIMER0 0x0584 +#define REG_TIMER1 0x0588 +#define REG_ACMHWCTRL 0x05C0 +#define REG_ACMRSTCTRL 0x05C1 +#define REG_ACMAVG 0x05C2 +#define REG_VO_ADMTIME 0x05C4 +#define REG_VI_ADMTIME 0x05C6 +#define REG_BE_ADMTIME 0x05C8 +#define REG_EDCA_RANDOM_GEN 0x05CC +#define REG_NOA_DESC_SEL 0x05CF +#define REG_NOA_DESC_DURATION 0x05E0 +#define REG_NOA_DESC_INTERVAL 0x05E4 +#define REG_NOA_DESC_START 0x05E8 +#define REG_NOA_DESC_COUNT 0x05EC +#define REG_SCH_TXCMD 0x05F8 + +#define REG_APSD_CTRL 0x0600 +#define REG_BWOPMODE 0x0603 +#define REG_TCR 0x0604 +#define REG_RCR 0x0608 +#define REG_RX_PKT_LIMIT 0x060C +#define REG_RX_DLK_TIME 0x060D +#define REG_RX_DRVINFO_SZ 0x060F + +#define REG_MACID 0x0610 +#define REG_BSSID 0x0618 +#define REG_MAR 0x0620 +#define REG_MBIDCAMCFG 0x0628 + +#define REG_USTIME_EDCA 0x0638 +#define REG_MAC_SPEC_SIFS 0x063A +#define REG_RESP_SIFS_CCK 0x063C +#define REG_RESP_SIFS_OFDM 0x063E +#define REG_ACKTO 0x0640 +#define REG_CTS2TO 0x0641 +#define REG_EIFS 0x0642 + +#define REG_NAV_CTRL 0x0650 +#define REG_NAV_UPPER 0x0652 +#define REG_BACAMCMD 0x0654 +#define REG_BACAMCONTENT 0x0658 +#define REG_LBDLY 0x0660 +#define REG_FWDLY 0x0661 +#define REG_RXERR_RPT 0x0664 +#define REG_TRXPTCL_CTL 0x0668 + +#define REG_CAMCMD 0x0670 +#define REG_CAMWRITE 0x0674 +#define REG_CAMREAD 0x0678 +#define REG_CAMDBG 0x067C +#define REG_SECCFG 0x0680 + +#define REG_WOW_CTRL 0x0690 +#define REG_PSSTATUS 0x0691 +#define REG_PS_RX_INFO 0x0692 +#define REG_UAPSD_TID 0x0693 +#define REG_LPNAV_CTRL 0x0694 +#define REG_WKFMCAM_NUM 0x0698 +#define REG_WKFMCAM_RWD 0x069C +#define REG_RXFLTMAP0 0x06A0 +#define REG_RXFLTMAP1 0x06A2 +#define REG_RXFLTMAP2 0x06A4 +#define REG_BCN_PSR_RPT 0x06A8 +#define REG_CALB32K_CTRL 0x06AC +#define REG_PKT_MON_CTRL 0x06B4 +#define REG_BT_COEX_TABLE 0x06C0 +#define REG_WMAC_RESP_TXINFO 0x06D8 + +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_TEST_USB_TXQS 0xFE48 +#define REG_TEST_SIE_VID 0xFE60 +#define REG_TEST_SIE_PID 0xFE62 +#define REG_TEST_SIE_OPTIONAL 0xFE64 +#define REG_TEST_SIE_CHIRP_K 0xFE65 +#define REG_TEST_SIE_PHY 0xFE66 +#define REG_TEST_SIE_MAC_ADDR 0xFE70 +#define REG_TEST_SIE_STRING 0xFE80 + +#define REG_NORMAL_SIE_VID 0xFE60 +#define REG_NORMAL_SIE_PID 0xFE62 +#define REG_NORMAL_SIE_OPTIONAL 0xFE64 +#define REG_NORMAL_SIE_EP 0xFE65 +#define REG_NORMAL_SIE_PHY 0xFE68 +#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 +#define REG_NORMAL_SIE_STRING 0xFE80 + +#define CR9346 REG_9346CR +#define MSR (REG_CR + 2) +#define ISR REG_HISR +#define TSFR REG_TSFTR + +#define MACIDR0 REG_MACID +#define MACIDR4 (REG_MACID + 4) + +#define PBP REG_PBP + +#define IDR0 MACIDR0 +#define IDR4 MACIDR4 + +#define UNUSED_REGISTER 0x1BF +#define DCAM UNUSED_REGISTER +#define PSR UNUSED_REGISTER +#define BBADDR UNUSED_REGISTER +#define PHYDATAR UNUSED_REGISTER + +#define INVALID_BBRF_VALUE 0x12345678 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define CMDEEPROM_EN BIT(5) +#define CMDEEPROM_SEL BIT(4) +#define CMD9346CR_9356SEL BIT(4) +#define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL) +#define AUTOLOAD_EFUSE CMDEEPROM_EN + +#define GPIOSEL_GPIO 0 +#define GPIOSEL_ENBT BIT(5) + +#define GPIO_IN REG_GPIO_PIN_CTRL +#define GPIO_OUT (REG_GPIO_PIN_CTRL+1) +#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) +#define GPIO_MOD (REG_GPIO_PIN_CTRL+3) + +/* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */ +#define HSIMR_GPIO12_0_INT_EN BIT(0) +#define HSIMR_SPS_OCP_INT_EN BIT(5) +#define HSIMR_RON_INT_EN BIT(6) +#define HSIMR_PDN_INT_EN BIT(7) +#define HSIMR_GPIO9_INT_EN BIT(25) + +/* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */ +#define HSISR_GPIO12_0_INT BIT(0) +#define HSISR_SPS_OCP_INT BIT(5) +#define HSISR_RON_INT_EN BIT(6) +#define HSISR_PDNINT BIT(7) +#define HSISR_GPIO9_INT BIT(25) + +#define MSR_NOLINK 0x00 +#define MSR_ADHOC 0x01 +#define MSR_INFRA 0x02 +#define MSR_AP 0x03 +#define MSR_MASK 0x03 + +#define RRSR_RSC_OFFSET 21 +#define RRSR_SHORT_OFFSET 23 +#define RRSR_RSC_BW_40M 0x600000 +#define RRSR_RSC_UPSUBCHNL 0x400000 +#define RRSR_RSC_LOWSUBCHNL 0x200000 +#define RRSR_SHORT 0x800000 +#define RRSR_1M BIT(0) +#define RRSR_2M BIT(1) +#define RRSR_5_5M BIT(2) +#define RRSR_11M BIT(3) +#define RRSR_6M BIT(4) +#define RRSR_9M BIT(5) +#define RRSR_12M BIT(6) +#define RRSR_18M BIT(7) +#define RRSR_24M BIT(8) +#define RRSR_36M BIT(9) +#define RRSR_48M BIT(10) +#define RRSR_54M BIT(11) +#define RRSR_MCS0 BIT(12) +#define RRSR_MCS1 BIT(13) +#define RRSR_MCS2 BIT(14) +#define RRSR_MCS3 BIT(15) +#define RRSR_MCS4 BIT(16) +#define RRSR_MCS5 BIT(17) +#define RRSR_MCS6 BIT(18) +#define RRSR_MCS7 BIT(19) +#define BRSR_ACKSHORTPMB BIT(23) + +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 + +#define RATE_1M BIT(0) +#define RATE_2M BIT(1) +#define RATE_5_5M BIT(2) +#define RATE_11M BIT(3) +#define RATE_6M BIT(4) +#define RATE_9M BIT(5) +#define RATE_12M BIT(6) +#define RATE_18M BIT(7) +#define RATE_24M BIT(8) +#define RATE_36M BIT(9) +#define RATE_48M BIT(10) +#define RATE_54M BIT(11) +#define RATE_MCS0 BIT(12) +#define RATE_MCS1 BIT(13) +#define RATE_MCS2 BIT(14) +#define RATE_MCS3 BIT(15) +#define RATE_MCS4 BIT(16) +#define RATE_MCS5 BIT(17) +#define RATE_MCS6 BIT(18) +#define RATE_MCS7 BIT(19) +#define RATE_MCS8 BIT(20) +#define RATE_MCS9 BIT(21) +#define RATE_MCS10 BIT(22) +#define RATE_MCS11 BIT(23) +#define RATE_MCS12 BIT(24) +#define RATE_MCS13 BIT(25) +#define RATE_MCS14 BIT(26) +#define RATE_MCS15 BIT(27) + +#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) +#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\ + RATR_24M | RATR_36M | RATR_48M | RATR_54M) +#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 |\ + RATR_MCS3 | RATR_MCS4 | RATR_MCS5 |\ + RATR_MCS6 | RATR_MCS7) +#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 |\ + RATR_MCS11 | RATR_MCS12 | RATR_MCS13 |\ + RATR_MCS14 | RATR_MCS15) + +#define BW_OPMODE_20MHZ BIT(2) +#define BW_OPMODE_5G BIT(1) +#define BW_OPMODE_11J BIT(0) + +#define CAM_VALID BIT(15) +#define CAM_NOTVALID 0x0000 +#define CAM_USEDK BIT(5) + +#define CAM_NONE 0x0 +#define CAM_WEP40 0x01 +#define CAM_TKIP 0x02 +#define CAM_AES 0x04 +#define CAM_WEP104 0x05 + +#define TOTAL_CAM_ENTRY 32 +#define HALF_CAM_ENTRY 16 + +#define CAM_WRITE BIT(16) +#define CAM_READ 0x00000000 +#define CAM_POLLINIG BIT(31) + +#define SCR_USEDK 0x01 +#define SCR_TXSEC_ENABLE 0x02 +#define SCR_RXSEC_ENABLE 0x04 + +#define WOW_PMEN BIT(0) +#define WOW_WOMEN BIT(1) +#define WOW_MAGIC BIT(2) +#define WOW_UWF BIT(3) + +/********************************************* +* 8188 IMR/ISR bits +**********************************************/ +#define IMR_DISABLED 0x0 +/* IMR DW0(0x0060-0063) Bit 0-31 */ +/* TXRPT interrupt when CCX bit of the packet is set */ +#define IMR_TXCCK BIT(30) +/* Power Save Time Out Interrupt */ +#define IMR_PSTIMEOUT BIT(29) +/* When GTIMER4 expires, this bit is set to 1 */ +#define IMR_GTINT4 BIT(28) +/* When GTIMER3 expires, this bit is set to 1 */ +#define IMR_GTINT3 BIT(27) +/* Transmit Beacon0 Error */ +#define IMR_TBDER BIT(26) +/* Transmit Beacon0 OK */ +#define IMR_TBDOK BIT(25) +/* TSF Timer BIT32 toggle indication interrupt */ +#define IMR_TSF_BIT32_TOGGLE BIT(24) +/* Beacon DMA Interrupt 0 */ +#define IMR_BCNDMAINT0 BIT(20) +/* Beacon Queue DMA OK0 */ +#define IMR_BCNDOK0 BIT(16) +/* HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */ +#define IMR_HSISR_IND_ON_INT BIT(15) +/* Beacon DMA Interrupt Extension for Win7 */ +#define IMR_BCNDMAINT_E BIT(14) +/* CTWidnow End or ATIM Window End */ +#define IMR_ATIMEND BIT(12) +/* HISR1 Indicator (HISR1 & HIMR1 is true, this bit is set to 1)*/ +#define IMR_HISR1_IND_INT BIT(11) +/* CPU to Host Command INT Status, Write 1 clear */ +#define IMR_C2HCMD BIT(10) +/* CPU power Mode exchange INT Status, Write 1 clear */ +#define IMR_CPWM2 BIT(9) +/* CPU power Mode exchange INT Status, Write 1 clear */ +#define IMR_CPWM BIT(8) +/* High Queue DMA OK */ +#define IMR_HIGHDOK BIT(7) +/* Management Queue DMA OK */ +#define IMR_MGNTDOK BIT(6) +/* AC_BK DMA OK */ +#define IMR_BKDOK BIT(5) +/* AC_BE DMA OK */ +#define IMR_BEDOK BIT(4) +/* AC_VI DMA OK */ +#define IMR_VIDOK BIT(3) +/* AC_VO DMA OK */ +#define IMR_VODOK BIT(2) +/* Rx Descriptor Unavailable */ +#define IMR_RDU BIT(1) +#define IMR_ROK BIT(0) /* Receive DMA OK */ + +/* IMR DW1(0x00B4-00B7) Bit 0-31 */ +/* Beacon DMA Interrupt 7 */ +#define IMR_BCNDMAINT7 BIT(27) +/* Beacon DMA Interrupt 6 */ +#define IMR_BCNDMAINT6 BIT(26) +/* Beacon DMA Interrupt 5 */ +#define IMR_BCNDMAINT5 BIT(25) +/* Beacon DMA Interrupt 4 */ +#define IMR_BCNDMAINT4 BIT(24) +/* Beacon DMA Interrupt 3 */ +#define IMR_BCNDMAINT3 BIT(23) +/* Beacon DMA Interrupt 2 */ +#define IMR_BCNDMAINT2 BIT(22) +/* Beacon DMA Interrupt 1 */ +#define IMR_BCNDMAINT1 BIT(21) +/* Beacon Queue DMA OK Interrup 7 */ +#define IMR_BCNDOK7 BIT(20) +/* Beacon Queue DMA OK Interrup 6 */ +#define IMR_BCNDOK6 BIT(19) +/* Beacon Queue DMA OK Interrup 5 */ +#define IMR_BCNDOK5 BIT(18) +/* Beacon Queue DMA OK Interrup 4 */ +#define IMR_BCNDOK4 BIT(17) +/* Beacon Queue DMA OK Interrup 3 */ +#define IMR_BCNDOK3 BIT(16) +/* Beacon Queue DMA OK Interrup 2 */ +#define IMR_BCNDOK2 BIT(15) +/* Beacon Queue DMA OK Interrup 1 */ +#define IMR_BCNDOK1 BIT(14) +/* ATIM Window End Extension for Win7 */ +#define IMR_ATIMEND_E BIT(13) +/* Tx Error Flag Interrupt Status, write 1 clear. */ +#define IMR_TXERR BIT(11) +/* Rx Error Flag INT Status, Write 1 clear */ +#define IMR_RXERR BIT(10) +/* Transmit FIFO Overflow */ +#define IMR_TXFOVW BIT(9) +/* Receive FIFO Overflow */ +#define IMR_RXFOVW BIT(8) + +#define HWSET_MAX_SIZE 512 +#define EFUSE_MAX_SECTION 64 +#define EFUSE_REAL_CONTENT_LEN 256 +/* PG data exclude header, dummy 7 bytes frome CP test and reserved 1byte.*/ +#define EFUSE_OOB_PROTECT_BYTES 18 + +#define EEPROM_DEFAULT_TSSI 0x0 +#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_BOARDTYPE 0x02 +#define EEPROM_DEFAULT_TXPOWER 0x1010 +#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 + +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_THERMALMETER 0x18 +#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 +#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 +#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 +#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 +#define EEPROM_DEFAULT_HT20_DIFF 2 +#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 +#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 +#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 + +#define RF_OPTION1 0x79 +#define RF_OPTION2 0x7A +#define RF_OPTION3 0x7B +#define RF_OPTION4 0xC3 + +#define EEPROM_DEFAULT_PID 0x1234 +#define EEPROM_DEFAULT_VID 0x5678 +#define EEPROM_DEFAULT_CUSTOMERID 0xAB +#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD +#define EEPROM_DEFAULT_VERSION 0 + +#define EEPROM_CHANNEL_PLAN_FCC 0x0 +#define EEPROM_CHANNEL_PLAN_IC 0x1 +#define EEPROM_CHANNEL_PLAN_ETSI 0x2 +#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 +#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 +#define EEPROM_CHANNEL_PLAN_MKK 0x5 +#define EEPROM_CHANNEL_PLAN_MKK1 0x6 +#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 +#define EEPROM_CHANNEL_PLAN_TELEC 0x8 +#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 +#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA +#define EEPROM_CHANNEL_PLAN_NCC 0xB +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + +#define EEPROM_CID_DEFAULT 0x0 +#define EEPROM_CID_TOSHIBA 0x4 +#define EEPROM_CID_CCX 0x10 +#define EEPROM_CID_QMI 0x0D +#define EEPROM_CID_WHQL 0xFE + +#define RTL_EEPROM_ID 0x8129 + +#define EEPROM_HPON 0x02 +#define EEPROM_CLK 0x06 +#define EEPROM_TESTR 0x08 + +#define EEPROM_TXPOWERCCK 0x10 +#define EEPROM_TXPOWERHT40_1S 0x16 +#define EEPROM_TXPOWERHT20DIFF 0x1B +#define EEPROM_TXPOWER_OFDMDIFF 0x1B + +#define EEPROM_TX_PWR_INX 0x10 + +#define EEPROM_CHANNELPLAN 0xB8 +#define EEPROM_XTAL_8821AE 0xB9 +#define EEPROM_THERMAL_METER 0xBA +#define EEPROM_IQK_LCK_88E 0xBB + +#define EEPROM_RF_BOARD_OPTION 0xC1 +#define EEPROM_RF_FEATURE_OPTION_88E 0xC2 +#define EEPROM_RF_BT_SETTING 0xC3 +#define EEPROM_VERSION 0xC4 +#define EEPROM_CUSTOMER_ID 0xC5 +#define EEPROM_RF_ANTENNA_OPT_88E 0xC9 +#define EEPROM_RFE_OPTION 0xCA + +#define EEPROM_MAC_ADDR 0xD0 +#define EEPROM_VID 0xD6 +#define EEPROM_DID 0xD8 +#define EEPROM_SVID 0xDA +#define EEPROM_SMID 0xDC + +#define STOPBECON BIT(6) +#define STOPHIGHT BIT(5) +#define STOPMGT BIT(4) +#define STOPVO BIT(3) +#define STOPVI BIT(2) +#define STOPBE BIT(1) +#define STOPBK BIT(0) + +#define RCR_APPFCS BIT(31) +#define RCR_APP_MIC BIT(30) +#define RCR_APP_ICV BIT(29) +#define RCR_APP_PHYST_RXFF BIT(28) +#define RCR_APP_BA_SSN BIT(27) +#define RCR_NONQOS_VHT BIT(26) +#define RCR_ENMBID BIT(24) +#define RCR_LSIGEN BIT(23) +#define RCR_MFBEN BIT(22) +#define RCR_HTC_LOC_CTRL BIT(14) +#define RCR_AMF BIT(13) +#define RCR_ACF BIT(12) +#define RCR_ADF BIT(11) +#define RCR_AICV BIT(9) +#define RCR_ACRC32 BIT(8) +#define RCR_CBSSID_BCN BIT(7) +#define RCR_CBSSID_DATA BIT(6) +#define RCR_CBSSID RCR_CBSSID_DATA +#define RCR_APWRMGT BIT(5) +#define RCR_ADD3 BIT(4) +#define RCR_AB BIT(3) +#define RCR_AM BIT(2) +#define RCR_APM BIT(1) +#define RCR_AAP BIT(0) +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 + +#define RSV_CTRL 0x001C +#define RD_CTRL 0x0524 + +#define REG_USB_INFO 0xFE17 +#define REG_USB_SPECIAL_OPTION 0xFE55 +#define REG_USB_DMA_AGG_TO 0xFE5B +#define REG_USB_AGG_TO 0xFE5C +#define REG_USB_AGG_TH 0xFE5D + +#define REG_USB_VID 0xFE60 +#define REG_USB_PID 0xFE62 +#define REG_USB_OPTIONAL 0xFE64 +#define REG_USB_CHIRP_K 0xFE65 +#define REG_USB_PHY 0xFE66 +#define REG_USB_MAC_ADDR 0xFE70 +#define REG_USB_HRPWM 0xFE58 +#define REG_USB_HCPWM 0xFE57 + +#define SW18_FPWM BIT(3) + +#define ISO_MD2PP BIT(0) +#define ISO_UA2USB BIT(1) +#define ISO_UD2CORE BIT(2) +#define ISO_PA2PCIE BIT(3) +#define ISO_PD2CORE BIT(4) +#define ISO_IP2MAC BIT(5) +#define ISO_DIOP BIT(6) +#define ISO_DIOE BIT(7) +#define ISO_EB2CORE BIT(8) +#define ISO_DIOR BIT(9) + +#define PWC_EV25V BIT(14) +#define PWC_EV12V BIT(15) + +#define FEN_BBRSTB BIT(0) +#define FEN_BB_GLB_RSTN BIT(1) +#define FEN_USBA BIT(2) +#define FEN_UPLL BIT(3) +#define FEN_USBD BIT(4) +#define FEN_DIO_PCIE BIT(5) +#define FEN_PCIEA BIT(6) +#define FEN_PPLL BIT(7) +#define FEN_PCIED BIT(8) +#define FEN_DIOE BIT(9) +#define FEN_CPUEN BIT(10) +#define FEN_DCORE BIT(11) +#define FEN_ELDR BIT(12) +#define FEN_DIO_RF BIT(13) +#define FEN_HWPDN BIT(14) +#define FEN_MREGEN BIT(15) + +#define PFM_LDALL BIT(0) +#define PFM_ALDN BIT(1) +#define PFM_LDKP BIT(2) +#define PFM_WOWL BIT(3) +#define ENPDN BIT(4) +#define PDN_PL BIT(5) +#define APFM_ONMAC BIT(8) +#define APFM_OFF BIT(9) +#define APFM_RSM BIT(10) +#define AFSM_HSUS BIT(11) +#define AFSM_PCIE BIT(12) +#define APDM_MAC BIT(13) +#define APDM_HOST BIT(14) +#define APDM_HPDN BIT(15) +#define RDY_MACON BIT(16) +#define SUS_HOST BIT(17) +#define ROP_ALD BIT(20) +#define ROP_PWR BIT(21) +#define ROP_SPS BIT(22) +#define SOP_MRST BIT(25) +#define SOP_FUSE BIT(26) +#define SOP_ABG BIT(27) +#define SOP_AMB BIT(28) +#define SOP_RCK BIT(29) +#define SOP_A8M BIT(30) +#define XOP_BTCK BIT(31) + +#define ANAD16V_EN BIT(0) +#define ANA8M BIT(1) +#define MACSLP BIT(4) +#define LOADER_CLK_EN BIT(5) +#define _80M_SSC_DIS BIT(7) +#define _80M_SSC_EN_HO BIT(8) +#define PHY_SSC_RSTB BIT(9) +#define SEC_CLK_EN BIT(10) +#define MAC_CLK_EN BIT(11) +#define SYS_CLK_EN BIT(12) +#define RING_CLK_EN BIT(13) + +#define BOOT_FROM_EEPROM BIT(4) +#define EEPROM_EN BIT(5) + +#define AFE_BGEN BIT(0) +#define AFE_MBEN BIT(1) +#define MAC_ID_EN BIT(7) + +#define WLOCK_ALL BIT(0) +#define WLOCK_00 BIT(1) +#define WLOCK_04 BIT(2) +#define WLOCK_08 BIT(3) +#define WLOCK_40 BIT(4) +#define R_DIS_PRST_0 BIT(5) +#define R_DIS_PRST_1 BIT(6) +#define LOCK_ALL_EN BIT(7) + +#define RF_EN BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + +#define LDA15_EN BIT(0) +#define LDA15_STBY BIT(1) +#define LDA15_OBUF BIT(2) +#define LDA15_REG_VOS BIT(3) +#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) + +#define LDV12_EN BIT(0) +#define LDV12_SDBY BIT(1) +#define LPLDO_HSM BIT(2) +#define LPLDO_LSM_DIS BIT(3) +#define _LDV12_VADJ(x) (((x) & 0xF) << 4) + +#define XTAL_EN BIT(0) +#define XTAL_BSEL BIT(1) +#define _XTAL_BOSC(x) (((x) & 0x3) << 2) +#define _XTAL_CADJ(x) (((x) & 0xF) << 4) +#define XTAL_GATE_USB BIT(8) +#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) +#define XTAL_GATE_AFE BIT(11) +#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) +#define XTAL_RF_GATE BIT(14) +#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) +#define XTAL_GATE_DIG BIT(17) +#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) +#define XTAL_BT_GATE BIT(20) +#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) +#define _XTAL_GPIO(x) (((x) & 0x7) << 23) + +#define CKDLY_AFE BIT(26) +#define CKDLY_USB BIT(27) +#define CKDLY_DIG BIT(28) +#define CKDLY_BT BIT(29) + +#define APLL_EN BIT(0) +#define APLL_320_EN BIT(1) +#define APLL_FREF_SEL BIT(2) +#define APLL_EDGE_SEL BIT(3) +#define APLL_WDOGB BIT(4) +#define APLL_LPFEN BIT(5) + +#define APLL_REF_CLK_13MHZ 0x1 +#define APLL_REF_CLK_19_2MHZ 0x2 +#define APLL_REF_CLK_20MHZ 0x3 +#define APLL_REF_CLK_25MHZ 0x4 +#define APLL_REF_CLK_26MHZ 0x5 +#define APLL_REF_CLK_38_4MHZ 0x6 +#define APLL_REF_CLK_40MHZ 0x7 + +#define APLL_320EN BIT(14) +#define APLL_80EN BIT(15) +#define APLL_1MEN BIT(24) + +#define ALD_EN BIT(18) +#define EF_PD BIT(19) +#define EF_FLAG BIT(31) + +#define EF_TRPT BIT(7) +#define LDOE25_EN BIT(31) + +#define RSM_EN BIT(0) +#define TIMER_EN BIT(4) + +#define TRSW0EN BIT(2) +#define TRSW1EN BIT(3) +#define EROM_EN BIT(4) +#define ENBT BIT(5) +#define ENUART BIT(8) +#define UART_910 BIT(9) +#define ENPMAC BIT(10) +#define SIC_SWRST BIT(11) +#define ENSIC BIT(12) +#define SIC_23 BIT(13) +#define ENHDP BIT(14) +#define SIC_LBK BIT(15) + +#define LED0PL BIT(4) +#define LED1PL BIT(12) +#define LED0DIS BIT(7) + +#define MCUFWDL_EN BIT(0) +#define MCUFWDL_RDY BIT(1) +#define FWDL_CHKSUM_RPT BIT(2) +#define MACINI_RDY BIT(3) +#define BBINI_RDY BIT(4) +#define RFINI_RDY BIT(5) +#define WINTINI_RDY BIT(6) +#define CPRST BIT(23) + +#define XCLK_VLD BIT(0) +#define ACLK_VLD BIT(1) +#define UCLK_VLD BIT(2) +#define PCLK_VLD BIT(3) +#define PCIRSTB BIT(4) +#define V15_VLD BIT(5) +#define TRP_B15V_EN BIT(7) +#define SIC_IDLE BIT(8) +#define BD_MAC2 BIT(9) +#define BD_MAC1 BIT(10) +#define IC_MACPHY_MODE BIT(11) +#define VENDOR_ID BIT(19) +#define PAD_HWPD_IDN BIT(22) +#define TRP_VAUX_EN BIT(23) +#define TRP_BT_EN BIT(24) +#define BD_PKG_SEL BIT(25) +#define BD_HCI_SEL BIT(26) +#define TYPE_ID BIT(27) + +#define CHIP_VER_RTL_MASK 0xF000 +#define CHIP_VER_RTL_SHIFT 12 + +#define REG_LBMODE (REG_CR + 3) + +#define HCI_TXDMA_EN BIT(0) +#define HCI_RXDMA_EN BIT(1) +#define TXDMA_EN BIT(2) +#define RXDMA_EN BIT(3) +#define PROTOCOL_EN BIT(4) +#define SCHEDULE_EN BIT(5) +#define MACTXEN BIT(6) +#define MACRXEN BIT(7) +#define ENSWBCN BIT(8) +#define ENSEC BIT(9) + +#define _NETTYPE(x) (((x) & 0x3) << 16) +#define MASK_NETTYPE 0x30000 +#define NT_NO_LINK 0x0 +#define NT_LINK_AD_HOC 0x1 +#define NT_LINK_AP 0x2 +#define NT_AS_AP 0x3 + +#define _LBMODE(x) (((x) & 0xF) << 24) +#define MASK_LBMODE 0xF000000 +#define LOOPBACK_NORMAL 0x0 +#define LOOPBACK_IMMEDIATELY 0xB +#define LOOPBACK_MAC_DELAY 0x3 +#define LOOPBACK_PHY 0x1 +#define LOOPBACK_DMA 0x7 + +#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) +#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) +#define _PSRX_MASK 0xF +#define _PSTX_MASK 0xF0 +#define _PSRX(x) (x) +#define _PSTX(x) ((x) << 4) + +#define PBP_64 0x0 +#define PBP_128 0x1 +#define PBP_256 0x2 +#define PBP_512 0x3 +#define PBP_1024 0x4 + +#define RXDMA_ARBBW_EN BIT(0) +#define RXSHFT_EN BIT(1) +#define RXDMA_AGG_EN BIT(2) +#define QS_VO_QUEUE BIT(8) +#define QS_VI_QUEUE BIT(9) +#define QS_BE_QUEUE BIT(10) +#define QS_BK_QUEUE BIT(11) +#define QS_MANAGER_QUEUE BIT(12) +#define QS_HIGH_QUEUE BIT(13) + +#define HQSEL_VOQ BIT(0) +#define HQSEL_VIQ BIT(1) +#define HQSEL_BEQ BIT(2) +#define HQSEL_BKQ BIT(3) +#define HQSEL_MGTQ BIT(4) +#define HQSEL_HIQ BIT(5) + +#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) +#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) +#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) +#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) +#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) +#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) + +#define QUEUE_LOW 1 +#define QUEUE_NORMAL 2 +#define QUEUE_HIGH 3 + +#define _LLT_NO_ACTIVE 0x0 +#define _LLT_WRITE_ACCESS 0x1 +#define _LLT_READ_ACCESS 0x2 + +#define _LLT_INIT_DATA(x) ((x) & 0xFF) +#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) +#define _LLT_OP(x) (((x) & 0x3) << 30) +#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) + +#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) +#define BB_WRITE_EN BIT(30) +#define BB_READ_EN BIT(31) + +#define _HPQ(x) ((x) & 0xFF) +#define _LPQ(x) (((x) & 0xFF) << 8) +#define _PUBQ(x) (((x) & 0xFF) << 16) +#define _NPQ(x) ((x) & 0xFF) + +#define HPQ_PUBLIC_DIS BIT(24) +#define LPQ_PUBLIC_DIS BIT(25) +#define LD_RQPN BIT(31) + +#define BCN_VALID BIT(16) +#define BCN_HEAD(x) (((x) & 0xFF) << 8) +#define BCN_HEAD_MASK 0xFF00 + +#define BLK_DESC_NUM_SHIFT 4 +#define BLK_DESC_NUM_MASK 0xF + +#define DROP_DATA_EN BIT(9) + +#define EN_AMPDU_RTY_NEW BIT(7) + +#define _INIRTSMCS_SEL(x) ((x) & 0x3F) + +#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) +#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) + +#define RATE_REG_BITMAP_ALL 0xFFFFF + +#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) + +#define _RRSR_RSC(x) (((x) & 0x3) << 21) +#define RRSR_RSC_RESERVED 0x0 +#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 +#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 +#define RRSR_RSC_DUPLICATE_MODE 0x3 + +#define USE_SHORT_G1 BIT(20) + +#define _AGGLMT_MCS0(x) ((x) & 0xF) +#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) +#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) +#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) +#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) +#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) +#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) +#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) + +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + +#define _DARF_RC1(x) ((x) & 0x1F) +#define _DARF_RC2(x) (((x) & 0x1F) << 8) +#define _DARF_RC3(x) (((x) & 0x1F) << 16) +#define _DARF_RC4(x) (((x) & 0x1F) << 24) +#define _DARF_RC5(x) ((x) & 0x1F) +#define _DARF_RC6(x) (((x) & 0x1F) << 8) +#define _DARF_RC7(x) (((x) & 0x1F) << 16) +#define _DARF_RC8(x) (((x) & 0x1F) << 24) + +#define _RARF_RC1(x) ((x) & 0x1F) +#define _RARF_RC2(x) (((x) & 0x1F) << 8) +#define _RARF_RC3(x) (((x) & 0x1F) << 16) +#define _RARF_RC4(x) (((x) & 0x1F) << 24) +#define _RARF_RC5(x) ((x) & 0x1F) +#define _RARF_RC6(x) (((x) & 0x1F) << 8) +#define _RARF_RC7(x) (((x) & 0x1F) << 16) +#define _RARF_RC8(x) (((x) & 0x1F) << 24) + +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + +#define _AIFS(x) (x) +#define _ECW_MAX_MIN(x) ((x) << 8) +#define _TXOP_LIMIT(x) ((x) << 16) + +#define _BCNIFS(x) ((x) & 0xFF) +#define _BCNECW(x) ((((x) & 0xF)) << 8) + +#define _LRL(x) ((x) & 0x3F) +#define _SRL(x) (((x) & 0x3F) << 8) + +#define _SIFS_CCK_CTX(x) ((x) & 0xFF) +#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8) + +#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) +#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8) + +#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) + +#define DIS_EDCA_CNT_DWN BIT(11) + +#define EN_MBSSID BIT(1) +#define EN_TXBCN_RPT BIT(2) +#define EN_BCN_FUNCTION BIT(3) + +#define TSFTR_RST BIT(0) +#define TSFTR1_RST BIT(1) + +#define STOP_BCNQ BIT(6) + +#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) +#define DIS_TSF_UDT0_TEST_CHIP BIT(5) + +#define ACMHW_HWEN BIT(0) +#define ACMHW_BEQEN BIT(1) +#define ACMHW_VIQEN BIT(2) +#define ACMHW_VOQEN BIT(3) +#define ACMHW_BEQSTATUS BIT(4) +#define ACMHW_VIQSTATUS BIT(5) +#define ACMHW_VOQSTATUS BIT(6) + +#define APSDOFF BIT(6) +#define APSDOFF_STATUS BIT(7) + +#define BW_20MHZ BIT(2) + +#define RATE_BITMAP_ALL 0xFFFFF + +#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 + +#define TSFRST BIT(0) +#define DIS_GCLK BIT(1) +#define PAD_SEL BIT(2) +#define PWR_ST BIT(6) +#define PWRBIT_OW_EN BIT(7) +#define ACRC BIT(8) +#define CFENDFORM BIT(9) +#define ICV BIT(10) + +#define AAP BIT(0) +#define APM BIT(1) +#define AM BIT(2) +#define AB BIT(3) +#define ADD3 BIT(4) +#define APWRMGT BIT(5) +#define CBSSID BIT(6) +#define CBSSID_DATA BIT(6) +#define CBSSID_BCN BIT(7) +#define ACRC32 BIT(8) +#define AICV BIT(9) +#define ADF BIT(11) +#define ACF BIT(12) +#define AMF BIT(13) +#define HTC_LOC_CTRL BIT(14) +#define UC_DATA_EN BIT(16) +#define BM_DATA_EN BIT(17) +#define MFBEN BIT(22) +#define LSIGEN BIT(23) +#define ENMBID BIT(24) +#define APP_BASSN BIT(27) +#define APP_PHYSTS BIT(28) +#define APP_ICV BIT(29) +#define APP_MIC BIT(30) +#define APP_FCS BIT(31) + +#define _MIN_SPACE(x) ((x) & 0x7) +#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) + +#define RXERR_TYPE_OFDM_PPDU 0 +#define RXERR_TYPE_OFDM_FALSE_ALARM 1 +#define RXERR_TYPE_OFDM_MPDU_OK 2 +#define RXERR_TYPE_OFDM_MPDU_FAIL 3 +#define RXERR_TYPE_CCK_PPDU 4 +#define RXERR_TYPE_CCK_FALSE_ALARM 5 +#define RXERR_TYPE_CCK_MPDU_OK 6 +#define RXERR_TYPE_CCK_MPDU_FAIL 7 +#define RXERR_TYPE_HT_PPDU 8 +#define RXERR_TYPE_HT_FALSE_ALARM 9 +#define RXERR_TYPE_HT_MPDU_TOTAL 10 +#define RXERR_TYPE_HT_MPDU_OK 11 +#define RXERR_TYPE_HT_MPDU_FAIL 12 +#define RXERR_TYPE_RX_FULL_DROP 15 + +#define RXERR_COUNTER_MASK 0xFFFFF +#define RXERR_RPT_RST BIT(27) +#define _RXERR_RPT_SEL(type) ((type) << 28) + +#define SCR_TXUSEDK BIT(0) +#define SCR_RXUSEDK BIT(1) +#define SCR_TXENCENABLE BIT(2) +#define SCR_RXDECENABLE BIT(3) +#define SCR_SKBYA2 BIT(4) +#define SCR_NOSKMC BIT(5) +#define SCR_TXBCUSEDK BIT(6) +#define SCR_RXBCUSEDK BIT(7) + +#define XCLK_VLD BIT(0) +#define ACLK_VLD BIT(1) +#define UCLK_VLD BIT(2) +#define PCLK_VLD BIT(3) +#define PCIRSTB BIT(4) +#define V15_VLD BIT(5) +#define TRP_B15V_EN BIT(7) +#define SIC_IDLE BIT(8) +#define BD_MAC2 BIT(9) +#define BD_MAC1 BIT(10) +#define IC_MACPHY_MODE BIT(11) +#define BT_FUNC BIT(16) +#define VENDOR_ID BIT(19) +#define PAD_HWPD_IDN BIT(22) +#define TRP_VAUX_EN BIT(23) +#define TRP_BT_EN BIT(24) +#define BD_PKG_SEL BIT(25) +#define BD_HCI_SEL BIT(26) +#define TYPE_ID BIT(27) + +#define USB_IS_HIGH_SPEED 0 +#define USB_IS_FULL_SPEED 1 +#define USB_SPEED_MASK BIT(5) + +#define USB_NORMAL_SIE_EP_MASK 0xF +#define USB_NORMAL_SIE_EP_SHIFT 4 + +#define USB_TEST_EP_MASK 0x30 +#define USB_TEST_EP_SHIFT 4 + +#define USB_AGG_EN BIT(3) + +#define MAC_ADDR_LEN 6 +#define LAST_ENTRY_OF_TX_PKT_BUFFER 255 + +#define POLLING_LLT_THRESHOLD 20 +#define POLLING_READY_TIMEOUT_COUNT 3000 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) +#define EPROM_CMD_CONFIG 0x3 +#define EPROM_CMD_LOAD 1 + +#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE + +#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) + +#define RA_LSSIWRITE_8821A 0xc90 +#define RB_LSSIWRITE_8821A 0xe90 + +#define RA_PIREAD_8821A 0xd04 +#define RB_PIREAD_8821A 0xd44 +#define RA_SIREAD_8821A 0xd08 +#define RB_SIREAD_8821A 0xd48 + +#define RPMAC_RESET 0x100 +#define RPMAC_TXSTART 0x104 +#define RPMAC_TXLEGACYSIG 0x108 +#define RPMAC_TXHTSIG1 0x10c +#define RPMAC_TXHTSIG2 0x110 +#define RPMAC_PHYDEBUG 0x114 +#define RPMAC_TXPACKETNUM 0x118 +#define RPMAC_TXIDLE 0x11c +#define RPMAC_TXMACHEADER0 0x120 +#define RPMAC_TXMACHEADER1 0x124 +#define RPMAC_TXMACHEADER2 0x128 +#define RPMAC_TXMACHEADER3 0x12c +#define RPMAC_TXMACHEADER4 0x130 +#define RPMAC_TXMACHEADER5 0x134 +#define RPMAC_TXDADATYPE 0x138 +#define RPMAC_TXRANDOMSEED 0x13c +#define RPMAC_CCKPLCPPREAMBLE 0x140 +#define RPMAC_CCKPLCPHEADER 0x144 +#define RPMAC_CCKCRC16 0x148 +#define RPMAC_OFDMRXCRC32OK 0x170 +#define RPMAC_OFDMRXCRC32ER 0x174 +#define RPMAC_OFDMRXPARITYER 0x178 +#define RPMAC_OFDMRXCRC8ER 0x17c +#define RPMAC_CCKCRXRC16ER 0x180 +#define RPMAC_CCKCRXRC32ER 0x184 +#define RPMAC_CCKCRXRC32OK 0x188 +#define RPMAC_TXSTATUS 0x18c + +#define RFPGA0_RFMOD 0x800 + +#define RFPGA0_TXINFO 0x804 +#define RFPGA0_PSDFUNCTION 0x808 + +#define RFPGA0_TXGAINSTAGE 0x80c + +#define RFPGA0_RFTIMING1 0x810 +#define RFPGA0_RFTIMING2 0x814 + +#define RFPGA0_XA_HSSIPARAMETER1 0x820 +#define RFPGA0_XA_HSSIPARAMETER2 0x824 +#define RFPGA0_XB_HSSIPARAMETER1 0x828 +#define RFPGA0_XB_HSSIPARAMETER2 0x82c +#define RCCAONSEC 0x838 + +#define RFPGA0_XA_LSSIPARAMETER 0x840 +#define RFPGA0_XB_LSSIPARAMETER 0x844 +#define RL1PEAKTH 0x848 + +#define RFPGA0_RFWAKEUPPARAMETER 0x850 +#define RFPGA0_RFSLEEPUPPARAMETER 0x854 + +#define RFPGA0_XAB_SWITCHCONTROL 0x858 +#define RFPGA0_XCD_SWITCHCONTROL 0x85c + +#define RFPGA0_XA_RFINTERFACEOE 0x860 +#define RFC_AREA 0x860 +#define RFPGA0_XB_RFINTERFACEOE 0x864 + +#define RFPGA0_XAB_RFINTERFACESW 0x870 +#define RFPGA0_XCD_RFINTERFACESW 0x874 + +#define RFPGA0_XAB_RFPARAMETER 0x878 +#define RFPGA0_XCD_RFPARAMETER 0x87c + +#define RFPGA0_ANALOGPARAMETER1 0x880 +#define RFPGA0_ANALOGPARAMETER2 0x884 +#define RFPGA0_ANALOGPARAMETER3 0x888 +#define RFPGA0_ANALOGPARAMETER4 0x88c + +#define RFPGA0_XA_LSSIREADBACK 0x8a0 +#define RFPGA0_XB_LSSIREADBACK 0x8a4 +#define RFPGA0_XC_LSSIREADBACK 0x8a8 +#define RRFMOD 0x8ac +#define RHSSIREAD_8821AE 0x8b0 + +#define RFPGA0_PSDREPORT 0x8b4 +#define TRANSCEIVEA_HSPI_READBACK 0x8b8 +#define TRANSCEIVEB_HSPI_READBACK 0x8bc +#define RADC_BUF_CLK 0x8c4 +#define RFPGA0_XAB_RFINTERFACERB 0x8e0 +#define RFPGA0_XCD_RFINTERFACERB 0x8e4 + +#define RFPGA1_RFMOD 0x900 + +#define RFPGA1_TXBLOCK 0x904 +#define RFPGA1_DEBUGSELECT 0x908 +#define RFPGA1_TXINFO 0x90c + +#define RCCK_SYSTEM 0xa00 +#define BCCK_SYSTEM 0x10 + +#define RCCK0_AFESETTING 0xa04 +#define RCCK0_CCA 0xa08 + +#define RCCK0_RXAGC1 0xa0c +#define RCCK0_RXAGC2 0xa10 + +#define RCCK0_RXHP 0xa14 + +#define RCCK0_DSPPARAMETER1 0xa18 +#define RCCK0_DSPPARAMETER2 0xa1c + +#define RCCK0_TXFILTER1 0xa20 +#define RCCK0_TXFILTER2 0xa24 +#define RCCK0_DEBUGPORT 0xa28 +#define RCCK0_FALSEALARMREPORT 0xa2c +#define RCCK0_TRSSIREPORT 0xa50 +#define RCCK0_RXREPORT 0xa54 +#define RCCK0_FACOUNTERLOWER 0xa5c +#define RCCK0_FACOUNTERUPPER 0xa58 +#define RCCK0_CCA_CNT 0xa60 + +/* PageB(0xB00) */ +#define RPDP_ANTA 0xb00 +#define RPDP_ANTA_4 0xb04 +#define RPDP_ANTA_8 0xb08 +#define RPDP_ANTA_C 0xb0c +#define RPDP_ANTA_10 0xb10 +#define RPDP_ANTA_14 0xb14 +#define RPDP_ANTA_18 0xb18 +#define RPDP_ANTA_1C 0xb1c +#define RPDP_ANTA_20 0xb20 +#define RPDP_ANTA_24 0xb24 + +#define RCONFIG_PMPD_ANTA 0xb28 +#define RCONFIG_RAM64x16 0xb2c + +#define RBNDA 0xb30 +#define RHSSIPAR 0xb34 + +#define RCONFIG_ANTA 0xb68 +#define RCONFIG_ANTB 0xb6c + +#define RPDP_ANTB 0xb70 +#define RPDP_ANTB_4 0xb74 +#define RPDP_ANTB_8 0xb78 +#define RPDP_ANTB_C 0xb7c +#define RPDP_ANTB_10 0xb80 +#define RPDP_ANTB_14 0xb84 +#define RPDP_ANTB_18 0xb88 +#define RPDP_ANTB_1C 0xb8c +#define RPDP_ANTB_20 0xb90 +#define RPDP_ANTB_24 0xb94 + +#define RCONFIG_PMPD_ANTB 0xb98 + +#define RBNDB 0xba0 + +#define RAPK 0xbd8 +#define RPM_RX0_ANTA 0xbdc +#define RPM_RX1_ANTA 0xbe0 +#define RPM_RX2_ANTA 0xbe4 +#define RPM_RX3_ANTA 0xbe8 +#define RPM_RX0_ANTB 0xbec +#define RPM_RX1_ANTB 0xbf0 +#define RPM_RX2_ANTB 0xbf4 +#define RPM_RX3_ANTB 0xbf8 + +/*RSSI Dump*/ +#define RA_RSSI_DUMP 0xBF0 +#define RB_RSSI_DUMP 0xBF1 +#define RS1_RX_EVM_DUMP 0xBF4 +#define RS2_RX_EVM_DUMP 0xBF5 +#define RA_RX_SNR_DUMP 0xBF6 +#define RB_RX_SNR_DUMP 0xBF7 +#define RA_CFO_SHORT_DUMP 0xBF8 +#define RB_CFO_SHORT_DUMP 0xBFA +#define RA_CFO_LONG_DUMP 0xBEC +#define RB_CFO_LONG_DUMP 0xBEE + +/*Page C*/ +#define ROFDM0_LSTF 0xc00 + +#define ROFDM0_TRXPATHENABLE 0xc04 +#define ROFDM0_TRMUXPAR 0xc08 +#define ROFDM0_TRSWISOLATION 0xc0c + +#define ROFDM0_XARXAFE 0xc10 +#define ROFDM0_XARXIQIMBALANCE 0xc14 +#define ROFDM0_XBRXAFE 0xc18 +#define ROFDM0_XBRXIQIMBALANCE 0xc1c +#define ROFDM0_XCRXAFE 0xc20 +#define ROFDM0_XCRXIQIMBANLANCE 0xc24 +#define ROFDM0_XDRXAFE 0xc28 +#define ROFDM0_XDRXIQIMBALANCE 0xc2c + +#define ROFDM0_RXDETECTOR1 0xc30 +#define ROFDM0_RXDETECTOR2 0xc34 +#define ROFDM0_RXDETECTOR3 0xc38 +#define ROFDM0_RXDETECTOR4 0xc3c + +#define ROFDM0_RXDSP 0xc40 +#define ROFDM0_CFOANDDAGC 0xc44 +#define ROFDM0_CCADROPTHRESHOLD 0xc48 +#define ROFDM0_ECCATHRESHOLD 0xc4c + +#define ROFDM0_XAAGCCORE1 0xc50 +#define ROFDM0_XAAGCCORE2 0xc54 +#define ROFDM0_XBAGCCORE1 0xc58 +#define ROFDM0_XBAGCCORE2 0xc5c +#define ROFDM0_XCAGCCORE1 0xc60 +#define ROFDM0_XCAGCCORE2 0xc64 +#define ROFDM0_XDAGCCORE1 0xc68 +#define ROFDM0_XDAGCCORE2 0xc6c + +#define ROFDM0_AGCPARAMETER1 0xc70 +#define ROFDM0_AGCPARAMETER2 0xc74 +#define ROFDM0_AGCRSSITABLE 0xc78 +#define ROFDM0_HTSTFAGC 0xc7c + +#define ROFDM0_XATXIQIMBALANCE 0xc80 +#define ROFDM0_XATXAFE 0xc84 +#define ROFDM0_XBTXIQIMBALANCE 0xc88 +#define ROFDM0_XBTXAFE 0xc8c +#define ROFDM0_XCTXIQIMBALANCE 0xc90 +#define ROFDM0_XCTXAFE 0xc94 +#define ROFDM0_XDTXIQIMBALANCE 0xc98 +#define ROFDM0_XDTXAFE 0xc9c + +#define ROFDM0_RXIQEXTANTA 0xca0 +#define ROFDM0_TXCOEFF1 0xca4 +#define ROFDM0_TXCOEFF2 0xca8 +#define ROFDM0_TXCOEFF3 0xcac +#define ROFDM0_TXCOEFF4 0xcb0 +#define ROFDM0_TXCOEFF5 0xcb4 +#define ROFDM0_TXCOEFF6 0xcb8 + +/*Path_A RFE cotrol */ +#define RA_RFE_CTRL_8812 0xcb8 +/*Path_B RFE control*/ +#define RB_RFE_CTRL_8812 0xeb8 + +#define ROFDM0_RXHPPARAMETER 0xce0 +#define ROFDM0_TXPSEUDONOISEWGT 0xce4 +#define ROFDM0_FRAMESYNC 0xcf0 +#define ROFDM0_DFSREPORT 0xcf4 + +#define ROFDM1_LSTF 0xd00 +#define ROFDM1_TRXPATHENABLE 0xd04 + +#define ROFDM1_CF0 0xd08 +#define ROFDM1_CSI1 0xd10 +#define ROFDM1_SBD 0xd14 +#define ROFDM1_CSI2 0xd18 +#define ROFDM1_CFOTRACKING 0xd2c +#define ROFDM1_TRXMESAURE1 0xd34 +#define ROFDM1_INTFDET 0xd3c +#define ROFDM1_PSEUDONOISESTATEAB 0xd50 +#define ROFDM1_PSEUDONOISESTATECD 0xd54 +#define ROFDM1_RXPSEUDONOISEWGT 0xd58 + +#define ROFDM_PHYCOUNTER1 0xda0 +#define ROFDM_PHYCOUNTER2 0xda4 +#define ROFDM_PHYCOUNTER3 0xda8 + +#define ROFDM_SHORTCFOAB 0xdac +#define ROFDM_SHORTCFOCD 0xdb0 +#define ROFDM_LONGCFOAB 0xdb4 +#define ROFDM_LONGCFOCD 0xdb8 +#define ROFDM_TAILCF0AB 0xdbc +#define ROFDM_TAILCF0CD 0xdc0 +#define ROFDM_PWMEASURE1 0xdc4 +#define ROFDM_PWMEASURE2 0xdc8 +#define ROFDM_BWREPORT 0xdcc +#define ROFDM_AGCREPORT 0xdd0 +#define ROFDM_RXSNR 0xdd4 +#define ROFDM_RXEVMCSI 0xdd8 +#define ROFDM_SIGREPORT 0xddc + +#define RTXAGC_A_CCK11_CCK1 0xc20 +#define RTXAGC_A_OFDM18_OFDM6 0xc24 +#define RTXAGC_A_OFDM54_OFDM24 0xc28 +#define RTXAGC_A_MCS03_MCS00 0xc2c +#define RTXAGC_A_MCS07_MCS04 0xc30 +#define RTXAGC_A_MCS11_MCS08 0xc34 +#define RTXAGC_A_MCS15_MCS12 0xc38 +#define RTXAGC_A_NSS1INDEX3_NSS1INDEX0 0xc3c +#define RTXAGC_A_NSS1INDEX7_NSS1INDEX4 0xc40 +#define RTXAGC_A_NSS2INDEX1_NSS1INDEX8 0xc44 +#define RTXAGC_A_NSS2INDEX5_NSS2INDEX2 0xc48 +#define RTXAGC_A_NSS2INDEX9_NSS2INDEX6 0xc4c +#define RTXAGC_B_CCK11_CCK1 0xe20 +#define RTXAGC_B_OFDM18_OFDM6 0xe24 +#define RTXAGC_B_OFDM54_OFDM24 0xe28 +#define RTXAGC_B_MCS03_MCS00 0xe2c +#define RTXAGC_B_MCS07_MCS04 0xe30 +#define RTXAGC_B_MCS11_MCS08 0xe34 +#define RTXAGC_B_MCS15_MCS12 0xe38 +#define RTXAGC_B_NSS1INDEX3_NSS1INDEX0 0xe3c +#define RTXAGC_B_NSS1INDEX7_NSS1INDEX4 0xe40 +#define RTXAGC_B_NSS2INDEX1_NSS1INDEX8 0xe44 +#define RTXAGC_B_NSS2INDEX5_NSS2INDEX2 0xe48 +#define RTXAGC_B_NSS2INDEX9_NSS2INDEX6 0xe4c + +#define RA_TXPWRTRAING 0xc54 +#define RB_TXPWRTRAING 0xe54 + +#define RFPGA0_IQK 0xe28 +#define RTX_IQK_TONE_A 0xe30 +#define RRX_IQK_TONE_A 0xe34 +#define RTX_IQK_PI_A 0xe38 +#define RRX_IQK_PI_A 0xe3c + +#define RTX_IQK 0xe40 +#define RRX_IQK 0xe44 +#define RIQK_AGC_PTS 0xe48 +#define RIQK_AGC_RSP 0xe4c +#define RTX_IQK_TONE_B 0xe50 +#define RRX_IQK_TONE_B 0xe54 +#define RTX_IQK_PI_B 0xe58 +#define RRX_IQK_PI_B 0xe5c +#define RIQK_AGC_CONT 0xe60 + +#define RBLUE_TOOTH 0xe6c +#define RRX_WAIT_CCA 0xe70 +#define RTX_CCK_RFON 0xe74 +#define RTX_CCK_BBON 0xe78 +#define RTX_OFDM_RFON 0xe7c +#define RTX_OFDM_BBON 0xe80 +#define RTX_TO_RX 0xe84 +#define RTX_TO_TX 0xe88 +#define RRX_CCK 0xe8c + +#define RTX_POWER_BEFORE_IQK_A 0xe94 +#define RTX_POWER_AFTER_IQK_A 0xe9c + +#define RRX_POWER_BEFORE_IQK_A 0xea0 +#define RRX_POWER_BEFORE_IQK_A_2 0xea4 +#define RRX_POWER_AFTER_IQK_A 0xea8 +#define RRX_POWER_AFTER_IQK_A_2 0xeac + +#define RTX_POWER_BEFORE_IQK_B 0xeb4 +#define RTX_POWER_AFTER_IQK_B 0xebc + +#define RRX_POER_BEFORE_IQK_B 0xec0 +#define RRX_POER_BEFORE_IQK_B_2 0xec4 +#define RRX_POWER_AFTER_IQK_B 0xec8 +#define RRX_POWER_AFTER_IQK_B_2 0xecc + +#define RRX_OFDM 0xed0 +#define RRX_WAIT_RIFS 0xed4 +#define RRX_TO_RX 0xed8 +#define RSTANDBY 0xedc +#define RSLEEP 0xee0 +#define RPMPD_ANAEN 0xeec + +#define RZEBRA1_HSSIENABLE 0x0 +#define RZEBRA1_TRXENABLE1 0x1 +#define RZEBRA1_TRXENABLE2 0x2 +#define RZEBRA1_AGC 0x4 +#define RZEBRA1_CHARGEPUMP 0x5 +#define RZEBRA1_CHANNEL 0x7 + +#define RZEBRA1_TXGAIN 0x8 +#define RZEBRA1_TXLPF 0x9 +#define RZEBRA1_RXLPF 0xb +#define RZEBRA1_RXHPFCORNER 0xc + +#define RGLOBALCTRL 0 +#define RRTL8256_TXLPF 19 +#define RRTL8256_RXLPF 11 +#define RRTL8258_TXLPF 0x11 +#define RRTL8258_RXLPF 0x13 +#define RRTL8258_RSSILPF 0xa + +#define RF_AC 0x00 + +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_POW_TRSW 0x05 + +#define RF_GAIN_RX 0x06 +#define RF_GAIN_TX 0x07 + +#define RF_TXM_IDAC 0x08 +#define RF_BS_IQGEN 0x0F + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 + +#define RF_RX_AGC_HP 0x12 +#define RF_TX_AGC 0x13 +#define RF_BIAS 0x14 +#define RF_IPA 0x15 +#define RF_POW_ABILITY 0x17 +#define RF_MODE_AG 0x18 +#define RRFCHANNEL 0x18 +#define RF_CHNLBW 0x18 +#define RF_TOP 0x19 + +#define RF_RX_G1 0x1A +#define RF_RX_G2 0x1B + +#define RF_RX_BB2 0x1C +#define RF_RX_BB1 0x1D + +#define RF_RCK1 0x1E +#define RF_RCK2 0x1F + +#define RF_TX_G1 0x20 +#define RF_TX_G2 0x21 +#define RF_TX_G3 0x22 + +#define RF_TX_BB1 0x23 +#define RF_T_METER 0x24 +#define RF_T_METER_88E 0x42 +#define RF_T_METER_8812A 0x42 + +#define RF_SYN_G1 0x25 +#define RF_SYN_G2 0x26 +#define RF_SYN_G3 0x27 +#define RF_SYN_G4 0x28 +#define RF_SYN_G5 0x29 +#define RF_SYN_G6 0x2A +#define RF_SYN_G7 0x2B +#define RF_SYN_G8 0x2C + +#define RF_RCK_OS 0x30 +#define RF_TXPA_G1 0x31 +#define RF_TXPA_G2 0x32 +#define RF_TXPA_G3 0x33 + +#define RF_TX_BIAS_A 0x35 +#define RF_TX_BIAS_D 0x36 +#define RF_LOBF_9 0x38 +#define RF_RXRF_A3 0x3C +#define RF_TRSW 0x3F + +#define RF_TXRF_A2 0x41 +#define RF_TXPA_G4 0x46 +#define RF_TXPA_A4 0x4B + +#define RF_APK 0x63 + +#define RF_WE_LUT 0xEF + +#define BBBRESETB 0x100 +#define BGLOBALRESETB 0x200 +#define BOFDMTXSTART 0x4 +#define BCCKTXSTART 0x8 +#define BCRC32DEBUG 0x100 +#define BPMACLOOPBACK 0x10 +#define BTXLSIG 0xffffff +#define BOFDMTXRATE 0xf +#define BOFDMTXRESERVED 0x10 +#define BOFDMTXLENGTH 0x1ffe0 +#define BOFDMTXPARITY 0x20000 +#define BTXHTSIG1 0xffffff +#define BTXHTMCSRATE 0x7f +#define BTXHTBW 0x80 +#define BTXHTLENGTH 0xffff00 +#define BTXHTSIG2 0xffffff +#define BTXHTSMOOTHING 0x1 +#define BTXHTSOUNDING 0x2 +#define BTXHTRESERVED 0x4 +#define BTXHTAGGREATION 0x8 +#define BTXHTSTBC 0x30 +#define BTXHTADVANCECODING 0x40 +#define BTXHTSHORTGI 0x80 +#define BTXHTNUMBERHT_LTF 0x300 +#define BTXHTCRC8 0x3fc00 +#define BCOUNTERRESET 0x10000 +#define BNUMOFOFDMTX 0xffff +#define BNUMOFCCKTX 0xffff0000 +#define BTXIDLEINTERVAL 0xffff +#define BOFDMSERVICE 0xffff0000 +#define BTXMACHEADER 0xffffffff +#define BTXDATAINIT 0xff +#define BTXHTMODE 0x100 +#define BTXDATATYPE 0x30000 +#define BTXRANDOMSEED 0xffffffff +#define BCCKTXPREAMBLE 0x1 +#define BCCKTXSFD 0xffff0000 +#define BCCKTXSIG 0xff +#define BCCKTXSERVICE 0xff00 +#define BCCKLENGTHEXT 0x8000 +#define BCCKTXLENGHT 0xffff0000 +#define BCCKTXCRC16 0xffff +#define BCCKTXSTATUS 0x1 +#define BOFDMTXSTATUS 0x2 +#define IS_BB_REG_OFFSET_92S(__offset) \ + ((__offset >= 0x800) && (__offset <= 0xfff)) + +#define BRFMOD 0x1 +#define BJAPANMODE 0x2 +#define BCCKTXSC 0x30 +/* Block & Path enable*/ +#define ROFDMCCKEN 0x808 +#define BCCKEN 0x10000000 +#define BOFDMEN 0x20000000 +/* Rx antenna*/ +#define RRXPATH 0x808 +#define BRXPATH 0xff +/* Tx antenna*/ +#define RTXPATH 0x80c +#define BTXPATH 0x0fffffff +/* for cck rx path selection*/ +#define RCCK_RX 0xa04 +#define BCCK_RX 0x0c000000 +/* Use LSIG for VHT length*/ +#define RVHTLEN_USE_LSIG 0x8c3 + +#define BOFDMRXADCPHASE 0x10000 +#define BOFDMTXDACPHASE 0x40000 +#define BXATXAGC 0x3f + +#define BXBTXAGC 0xf00 +#define BXCTXAGC 0xf000 +#define BXDTXAGC 0xf0000 + +#define BPASTART 0xf0000000 +#define BTRSTART 0x00f00000 +#define BRFSTART 0x0000f000 +#define BBBSTART 0x000000f0 +#define BBBCCKSTART 0x0000000f +#define BPAEND 0xf +#define BTREND 0x0f000000 +#define BRFEND 0x000f0000 +#define BCCAMASK 0x000000f0 +#define BR2RCCAMASK 0x00000f00 +#define BHSSI_R2TDELAY 0xf8000000 +#define BHSSI_T2RDELAY 0xf80000 +#define BCONTXHSSI 0x400 +#define BIGFROMCCK 0x200 +#define BAGCADDRESS 0x3f +#define BRXHPTX 0x7000 +#define BRXHP2RX 0x38000 +#define BRXHPCCKINI 0xc0000 +#define BAGCTXCODE 0xc00000 +#define BAGCRXCODE 0x300000 + +#define B3WIREDATALENGTH 0x800 +#define B3WIREADDREAALENGTH 0x400 + +#define B3WIRERFPOWERDOWN 0x1 +#define B5GPAPEPOLARITY 0x40000000 +#define B2GPAPEPOLARITY 0x80000000 +#define BRFSW_TXDEFAULTANT 0x3 +#define BRFSW_TXOPTIONANT 0x30 +#define BRFSW_RXDEFAULTANT 0x300 +#define BRFSW_RXOPTIONANT 0x3000 +#define BRFSI_3WIREDATA 0x1 +#define BRFSI_3WIRECLOCK 0x2 +#define BRFSI_3WIRELOAD 0x4 +#define BRFSI_3WIRERW 0x8 +#define BRFSI_3WIRE 0xf + +#define BRFSI_RFENV 0x10 + +#define BRFSI_TRSW 0x20 +#define BRFSI_TRSWB 0x40 +#define BRFSI_ANTSW 0x100 +#define BRFSI_ANTSWB 0x200 +#define BRFSI_PAPE 0x400 +#define BRFSI_PAPE5G 0x800 +#define BBANDSELECT 0x1 +#define BHTSIG2_GI 0x80 +#define BHTSIG2_SMOOTHING 0x01 +#define BHTSIG2_SOUNDING 0x02 +#define BHTSIG2_AGGREATON 0x08 +#define BHTSIG2_STBC 0x30 +#define BHTSIG2_ADVCODING 0x40 +#define BHTSIG2_NUMOFHTLTF 0x300 +#define BHTSIG2_CRC8 0x3fc +#define BHTSIG1_MCS 0x7f +#define BHTSIG1_BANDWIDTH 0x80 +#define BHTSIG1_HTLENGTH 0xffff +#define BLSIG_RATE 0xf +#define BLSIG_RESERVED 0x10 +#define BLSIG_LENGTH 0x1fffe +#define BLSIG_PARITY 0x20 +#define BCCKRXPHASE 0x4 + +#define BLSSIREADADDRESS 0x7f800000 +#define BLSSIREADEDGE 0x80000000 + +#define BLSSIREADBACKDATA 0xfffff + +#define BLSSIREADOKFLAG 0x1000 +#define BCCKSAMPLERATE 0x8 +#define BREGULATOR0STANDBY 0x1 +#define BREGULATORPLLSTANDBY 0x2 +#define BREGULATOR1STANDBY 0x4 +#define BPLLPOWERUP 0x8 +#define BDPLLPOWERUP 0x10 +#define BDA10POWERUP 0x20 +#define BAD7POWERUP 0x200 +#define BDA6POWERUP 0x2000 +#define BXTALPOWERUP 0x4000 +#define B40MDCLKPOWERUP 0x8000 +#define BDA6DEBUGMODE 0x20000 +#define BDA6SWING 0x380000 + +#define BADCLKPHASE 0x4000000 +#define B80MCLKDELAY 0x18000000 +#define BAFEWATCHDOGENABLE 0x20000000 + +#define BXTALCAP01 0xc0000000 +#define BXTALCAP23 0x3 +#define BXTALCAP92X 0x0f000000 +#define BXTALCAP 0x0f000000 + +#define BINTDIFCLKENABLE 0x400 +#define BEXTSIGCLKENABLE 0x800 +#define BBANDGAP_MBIAS_POWERUP 0x10000 +#define BAD11SH_GAIN 0xc0000 +#define BAD11NPUT_RANGE 0x700000 +#define BAD110P_CURRENT 0x3800000 +#define BLPATH_LOOPBACK 0x4000000 +#define BQPATH_LOOPBACK 0x8000000 +#define BAFE_LOOPBACK 0x10000000 +#define BDA10_SWING 0x7e0 +#define BDA10_REVERSE 0x800 +#define BDA_CLK_SOURCE 0x1000 +#define BDA7INPUT_RANGE 0x6000 +#define BDA7_GAIN 0x38000 +#define BDA7OUTPUT_CM_MODE 0x40000 +#define BDA7INPUT_CM_MODE 0x380000 +#define BDA7CURRENT 0xc00000 +#define BREGULATOR_ADJUST 0x7000000 +#define BAD11POWERUP_ATTX 0x1 +#define BDA10PS_ATTX 0x10 +#define BAD11POWERUP_ATRX 0x100 +#define BDA10PS_ATRX 0x1000 +#define BCCKRX_AGC_FORMAT 0x200 +#define BPSDFFT_SAMPLE_POINT 0xc000 +#define BPSD_AVERAGE_NUM 0x3000 +#define BIQPATH_CONTROL 0xc00 +#define BPSD_FREQ 0x3ff +#define BPSD_ANTENNA_PATH 0x30 +#define BPSD_IQ_SWITCH 0x40 +#define BPSD_RX_TRIGGER 0x400000 +#define BPSD_TX_TRIGGER 0x80000000 +#define BPSD_SINE_TONE_SCALE 0x7f000000 +#define BPSD_REPORT 0xffff + +#define BOFDM_TXSC 0x30000000 +#define BCCK_TXON 0x1 +#define BOFDM_TXON 0x2 +#define BDEBUG_PAGE 0xfff +#define BDEBUG_ITEM 0xff +#define BANTL 0x10 +#define BANT_NONHT 0x100 +#define BANT_HT1 0x1000 +#define BANT_HT2 0x10000 +#define BANT_HT1S1 0x100000 +#define BANT_NONHTS1 0x1000000 + +#define BCCK_BBMODE 0x3 +#define BCCK_TXPOWERSAVING 0x80 +#define BCCK_RXPOWERSAVING 0x40 + +#define BCCK_SIDEBAND 0x10 + +#define BCCK_SCRAMBLE 0x8 +#define BCCK_ANTDIVERSITY 0x8000 +#define BCCK_CARRIER_RECOVERY 0x4000 +#define BCCK_TXRATE 0x3000 +#define BCCK_DCCANCEL 0x0800 +#define BCCK_ISICANCEL 0x0400 +#define BCCK_MATCH_FILTER 0x0200 +#define BCCK_EQUALIZER 0x0100 +#define BCCK_PREAMBLE_DETECT 0x800000 +#define BCCK_FAST_FALSECCA 0x400000 +#define BCCK_CH_ESTSTART 0x300000 +#define BCCK_CCA_COUNT 0x080000 +#define BCCK_CS_LIM 0x070000 +#define BCCK_BIST_MODE 0x80000000 +#define BCCK_CCAMASK 0x40000000 +#define BCCK_TX_DAC_PHASE 0x4 +#define BCCK_RX_ADC_PHASE 0x20000000 +#define BCCKR_CP_MODE 0x0100 +#define BCCK_TXDC_OFFSET 0xf0 +#define BCCK_RXDC_OFFSET 0xf +#define BCCK_CCA_MODE 0xc000 +#define BCCK_FALSECS_LIM 0x3f00 +#define BCCK_CS_RATIO 0xc00000 +#define BCCK_CORGBIT_SEL 0x300000 +#define BCCK_PD_LIM 0x0f0000 +#define BCCK_NEWCCA 0x80000000 +#define BCCK_RXHP_OF_IG 0x8000 +#define BCCK_RXIG 0x7f00 +#define BCCK_LNA_POLARITY 0x800000 +#define BCCK_RX1ST_BAIN 0x7f0000 +#define BCCK_RF_EXTEND 0x20000000 +#define BCCK_RXAGC_SATLEVEL 0x1f000000 +#define BCCK_RXAGC_SATCOUNT 0xe0 +#define BCCKRXRFSETTLE 0x1f +#define BCCK_FIXED_RXAGC 0x8000 +#define BCCK_ANTENNA_POLARITY 0x2000 +#define BCCK_TXFILTER_TYPE 0x0c00 +#define BCCK_RXAGC_REPORTTYPE 0x0300 +#define BCCK_RXDAGC_EN 0x80000000 +#define BCCK_RXDAGC_PERIOD 0x20000000 +#define BCCK_RXDAGC_SATLEVEL 0x1f000000 +#define BCCK_TIMING_RECOVERY 0x800000 +#define BCCK_TXC0 0x3f0000 +#define BCCK_TXC1 0x3f000000 +#define BCCK_TXC2 0x3f +#define BCCK_TXC3 0x3f00 +#define BCCK_TXC4 0x3f0000 +#define BCCK_TXC5 0x3f000000 +#define BCCK_TXC6 0x3f +#define BCCK_TXC7 0x3f00 +#define BCCK_DEBUGPORT 0xff0000 +#define BCCK_DAC_DEBUG 0x0f000000 +#define BCCK_FALSEALARM_ENABLE 0x8000 +#define BCCK_FALSEALARM_READ 0x4000 +#define BCCK_TRSSI 0x7f +#define BCCK_RXAGC_REPORT 0xfe +#define BCCK_RXREPORT_ANTSEL 0x80000000 +#define BCCK_RXREPORT_MFOFF 0x40000000 +#define BCCK_RXREPORT_SQLOSS 0x20000000 +#define BCCK_RXREPORT_PKTLOSS 0x10000000 +#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 +#define BCCK_RXREPORT_RATEERROR 0x04000000 +#define BCCK_RXREPORT_RXRATE 0x03000000 +#define BCCK_RXFA_COUNTER_LOWER 0xff +#define BCCK_RXFA_COUNTER_UPPER 0xff000000 +#define BCCK_RXHPAGC_START 0xe000 +#define BCCK_RXHPAGC_FINAL 0x1c00 +#define BCCK_RXFALSEALARM_ENABLE 0x8000 +#define BCCK_FACOUNTER_FREEZE 0x4000 +#define BCCK_TXPATH_SEL 0x10000000 +#define BCCK_DEFAULT_RXPATH 0xc000000 +#define BCCK_OPTION_RXPATH 0x3000000 + +#define BNUM_OFSTF 0x3 +#define BSHIFT_L 0xc0 +#define BGI_TH 0xc +#define BRXPATH_A 0x1 +#define BRXPATH_B 0x2 +#define BRXPATH_C 0x4 +#define BRXPATH_D 0x8 +#define BTXPATH_A 0x1 +#define BTXPATH_B 0x2 +#define BTXPATH_C 0x4 +#define BTXPATH_D 0x8 +#define BTRSSI_FREQ 0x200 +#define BADC_BACKOFF 0x3000 +#define BDFIR_BACKOFF 0xc000 +#define BTRSSI_LATCH_PHASE 0x10000 +#define BRX_LDC_OFFSET 0xff +#define BRX_QDC_OFFSET 0xff00 +#define BRX_DFIR_MODE 0x1800000 +#define BRX_DCNF_TYPE 0xe000000 +#define BRXIQIMB_A 0x3ff +#define BRXIQIMB_B 0xfc00 +#define BRXIQIMB_C 0x3f0000 +#define BRXIQIMB_D 0xffc00000 +#define BDC_DC_NOTCH 0x60000 +#define BRXNB_NOTCH 0x1f000000 +#define BPD_TH 0xf +#define BPD_TH_OPT2 0xc000 +#define BPWED_TH 0x700 +#define BIFMF_WIN_L 0x800 +#define BPD_OPTION 0x1000 +#define BMF_WIN_L 0xe000 +#define BBW_SEARCH_L 0x30000 +#define BWIN_ENH_L 0xc0000 +#define BBW_TH 0x700000 +#define BED_TH2 0x3800000 +#define BBW_OPTION 0x4000000 +#define BRADIO_TH 0x18000000 +#define BWINDOW_L 0xe0000000 +#define BSBD_OPTION 0x1 +#define BFRAME_TH 0x1c +#define BFS_OPTION 0x60 +#define BDC_SLOPE_CHECK 0x80 +#define BFGUARD_COUNTER_DC_L 0xe00 +#define BFRAME_WEIGHT_SHORT 0x7000 +#define BSUB_TUNE 0xe00000 +#define BFRAME_DC_LENGTH 0xe000000 +#define BSBD_START_OFFSET 0x30000000 +#define BFRAME_TH_2 0x7 +#define BFRAME_GI2_TH 0x38 +#define BGI2_SYNC_EN 0x40 +#define BSARCH_SHORT_EARLY 0x300 +#define BSARCH_SHORT_LATE 0xc00 +#define BSARCH_GI2_LATE 0x70000 +#define BCFOANTSUM 0x1 +#define BCFOACC 0x2 +#define BCFOSTARTOFFSET 0xc +#define BCFOLOOPBACK 0x70 +#define BCFOSUMWEIGHT 0x80 +#define BDAGCENABLE 0x10000 +#define BTXIQIMB_A 0x3ff +#define BTXIQIMB_b 0xfc00 +#define BTXIQIMB_C 0x3f0000 +#define BTXIQIMB_D 0xffc00000 +#define BTXIDCOFFSET 0xff +#define BTXIQDCOFFSET 0xff00 +#define BTXDFIRMODE 0x10000 +#define BTXPESUDO_NOISEON 0x4000000 +#define BTXPESUDO_NOISE_A 0xff +#define BTXPESUDO_NOISE_B 0xff00 +#define BTXPESUDO_NOISE_C 0xff0000 +#define BTXPESUDO_NOISE_D 0xff000000 +#define BCCA_DROPOPTION 0x20000 +#define BCCA_DROPTHRES 0xfff00000 +#define BEDCCA_H 0xf +#define BEDCCA_L 0xf0 +#define BLAMBDA_ED 0x300 +#define BRX_INITIALGAIN 0x7f +#define BRX_ANTDIV_EN 0x80 +#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 +#define BRX_HIGHPOWER_FLOW 0x8000 +#define BRX_AGC_FREEZE_THRES 0xc0000 +#define BRX_FREEZESTEP_AGC1 0x300000 +#define BRX_FREEZESTEP_AGC2 0xc00000 +#define BRX_FREEZESTEP_AGC3 0x3000000 +#define BRX_FREEZESTEP_AGC0 0xc000000 +#define BRXRSSI_CMP_EN 0x10000000 +#define BRXQUICK_AGCEN 0x20000000 +#define BRXAGC_FREEZE_THRES_MODE 0x40000000 +#define BRX_OVERFLOW_CHECKTYPE 0x80000000 +#define BRX_AGCSHIFT 0x7f +#define BTRSW_TRI_ONLY 0x80 +#define BPOWER_THRES 0x300 +#define BRXAGC_EN 0x1 +#define BRXAGC_TOGETHER_EN 0x2 +#define BRXAGC_MIN 0x4 +#define BRXHP_INI 0x7 +#define BRXHP_TRLNA 0x70 +#define BRXHP_RSSI 0x700 +#define BRXHP_BBP1 0x7000 +#define BRXHP_BBP2 0x70000 +#define BRXHP_BBP3 0x700000 +#define BRSSI_H 0x7f0000 +#define BRSSI_GEN 0x7f000000 +#define BRXSETTLE_TRSW 0x7 +#define BRXSETTLE_LNA 0x38 +#define BRXSETTLE_RSSI 0x1c0 +#define BRXSETTLE_BBP 0xe00 +#define BRXSETTLE_RXHP 0x7000 +#define BRXSETTLE_ANTSW_RSSI 0x38000 +#define BRXSETTLE_ANTSW 0xc0000 +#define BRXPROCESS_TIME_DAGC 0x300000 +#define BRXSETTLE_HSSI 0x400000 +#define BRXPROCESS_TIME_BBPPW 0x800000 +#define BRXANTENNA_POWER_SHIFT 0x3000000 +#define BRSSI_TABLE_SELECT 0xc000000 +#define BRXHP_FINAL 0x7000000 +#define BRXHPSETTLE_BBP 0x7 +#define BRXHTSETTLE_HSSI 0x8 +#define BRXHTSETTLE_RXHP 0x70 +#define BRXHTSETTLE_BBPPW 0x80 +#define BRXHTSETTLE_IDLE 0x300 +#define BRXHTSETTLE_RESERVED 0x1c00 +#define BRXHT_RXHP_EN 0x8000 +#define BRXAGC_FREEZE_THRES 0x30000 +#define BRXAGC_TOGETHEREN 0x40000 +#define BRXHTAGC_MIN 0x80000 +#define BRXHTAGC_EN 0x100000 +#define BRXHTDAGC_EN 0x200000 +#define BRXHT_RXHP_BBP 0x1c00000 +#define BRXHT_RXHP_FINAL 0xe0000000 +#define BRXPW_RADIO_TH 0x3 +#define BRXPW_RADIO_EN 0x4 +#define BRXMF_HOLD 0x3800 +#define BRXPD_DELAY_TH1 0x38 +#define BRXPD_DELAY_TH2 0x1c0 +#define BRXPD_DC_COUNT_MAX 0x600 +#define BRXPD_DELAY_TH 0x8000 +#define BRXPROCESS_DELAY 0xf0000 +#define BRXSEARCHRANGE_GI2_EARLY 0x700000 +#define BRXFRAME_FUARD_COUNTER_L 0x3800000 +#define BRXSGI_GUARD_L 0xc000000 +#define BRXSGI_SEARCH_L 0x30000000 +#define BRXSGI_TH 0xc0000000 +#define BDFSCNT0 0xff +#define BDFSCNT1 0xff00 +#define BDFSFLAG 0xf0000 +#define BMF_WEIGHT_SUM 0x300000 +#define BMINIDX_TH 0x7f000000 +#define BDAFORMAT 0x40000 +#define BTXCH_EMU_ENABLE 0x01000000 +#define BTRSW_ISOLATION_A 0x7f +#define BTRSW_ISOLATION_B 0x7f00 +#define BTRSW_ISOLATION_C 0x7f0000 +#define BTRSW_ISOLATION_D 0x7f000000 +#define BEXT_LNA_GAIN 0x7c00 + +#define BSTBC_EN 0x4 +#define BANTENNA_MAPPING 0x10 +#define BNSS 0x20 +#define BCFO_ANTSUM_ID 0x200 +#define BPHY_COUNTER_RESET 0x8000000 +#define BCFO_REPORT_GET 0x4000000 +#define BOFDM_CONTINUE_TX 0x10000000 +#define BOFDM_SINGLE_CARRIER 0x20000000 +#define BOFDM_SINGLE_TONE 0x40000000 +#define BHT_DETECT 0x100 +#define BCFOEN 0x10000 +#define BCFOVALUE 0xfff00000 +#define BSIGTONE_RE 0x3f +#define BSIGTONE_IM 0x7f00 +#define BCOUNTER_CCA 0xffff +#define BCOUNTER_PARITYFAIL 0xffff0000 +#define BCOUNTER_RATEILLEGAL 0xffff +#define BCOUNTER_CRC8FAIL 0xffff0000 +#define BCOUNTER_MCSNOSUPPORT 0xffff +#define BCOUNTER_FASTSYNC 0xffff +#define BSHORTCFO 0xfff +#define BSHORTCFOT_LENGTH 12 +#define BSHORTCFOF_LENGTH 11 +#define BLONGCFO 0x7ff +#define BLONGCFOT_LENGTH 11 +#define BLONGCFOF_LENGTH 11 +#define BTAILCFO 0x1fff +#define BTAILCFOT_LENGTH 13 +#define BTAILCFOF_LENGTH 12 +#define BNOISE_EN_PWDB 0xffff +#define BCC_POWER_DB 0xffff0000 +#define BMOISE_PWDB 0xffff +#define BPOWERMEAST_LENGTH 10 +#define BPOWERMEASF_LENGTH 3 +#define BRX_HT_BW 0x1 +#define BRXSC 0x6 +#define BRX_HT 0x8 +#define BNB_INTF_DET_ON 0x1 +#define BINTF_WIN_LEN_CFG 0x30 +#define BNB_INTF_TH_CFG 0x1c0 +#define BRFGAIN 0x3f +#define BTABLESEL 0x40 +#define BTRSW 0x80 +#define BRXSNR_A 0xff +#define BRXSNR_B 0xff00 +#define BRXSNR_C 0xff0000 +#define BRXSNR_D 0xff000000 +#define BSNR_EVMT_LENGTH 8 +#define BSNR_EVMF_LENGTH 1 +#define BCSI1ST 0xff +#define BCSI2ND 0xff00 +#define BRXEVM1ST 0xff0000 +#define BRXEVM2ND 0xff000000 +#define BSIGEVM 0xff +#define BPWDB 0xff00 +#define BSGIEN 0x10000 + +#define BSFACTOR_QMA1 0xf +#define BSFACTOR_QMA2 0xf0 +#define BSFACTOR_QMA3 0xf00 +#define BSFACTOR_QMA4 0xf000 +#define BSFACTOR_QMA5 0xf0000 +#define BSFACTOR_QMA6 0xf0000 +#define BSFACTOR_QMA7 0xf00000 +#define BSFACTOR_QMA8 0xf000000 +#define BSFACTOR_QMA9 0xf0000000 +#define BCSI_SCHEME 0x100000 + +#define BNOISE_LVL_TOP_SET 0x3 +#define BCHSMOOTH 0x4 +#define BCHSMOOTH_CFG1 0x38 +#define BCHSMOOTH_CFG2 0x1c0 +#define BCHSMOOTH_CFG3 0xe00 +#define BCHSMOOTH_CFG4 0x7000 +#define BMRCMODE 0x800000 +#define BTHEVMCFG 0x7000000 + +#define BLOOP_FIT_TYPE 0x1 +#define BUPD_CFO 0x40 +#define BUPD_CFO_OFFDATA 0x80 +#define BADV_UPD_CFO 0x100 +#define BADV_TIME_CTRL 0x800 +#define BUPD_CLKO 0x1000 +#define BFC 0x6000 +#define BTRACKING_MODE 0x8000 +#define BPHCMP_ENABLE 0x10000 +#define BUPD_CLKO_LTF 0x20000 +#define BCOM_CH_CFO 0x40000 +#define BCSI_ESTI_MODE 0x80000 +#define BADV_UPD_EQZ 0x100000 +#define BUCHCFG 0x7000000 +#define BUPDEQZ 0x8000000 + +#define BRX_PESUDO_NOISE_ON 0x20000000 +#define BRX_PESUDO_NOISE_A 0xff +#define BRX_PESUDO_NOISE_B 0xff00 +#define BRX_PESUDO_NOISE_C 0xff0000 +#define BRX_PESUDO_NOISE_D 0xff000000 +#define BRX_PESUDO_NOISESTATE_A 0xffff +#define BRX_PESUDO_NOISESTATE_B 0xffff0000 +#define BRX_PESUDO_NOISESTATE_C 0xffff +#define BRX_PESUDO_NOISESTATE_D 0xffff0000 + +#define BZEBRA1_HSSIENABLE 0x8 +#define BZEBRA1_TRXCONTROL 0xc00 +#define BZEBRA1_TRXGAINSETTING 0x07f +#define BZEBRA1_RXCOUNTER 0xc00 +#define BZEBRA1_TXCHANGEPUMP 0x38 +#define BZEBRA1_RXCHANGEPUMP 0x7 +#define BZEBRA1_CHANNEL_NUM 0xf80 +#define BZEBRA1_TXLPFBW 0x400 +#define BZEBRA1_RXLPFBW 0x600 + +#define BRTL8256REG_MODE_CTRL1 0x100 +#define BRTL8256REG_MODE_CTRL0 0x40 +#define BRTL8256REG_TXLPFBW 0x18 +#define BRTL8256REG_RXLPFBW 0x600 + +#define BRTL8258_TXLPFBW 0xc +#define BRTL8258_RXLPFBW 0xc00 +#define BRTL8258_RSSILPFBW 0xc0 + +#define BBYTE0 0x1 +#define BBYTE1 0x2 +#define BBYTE2 0x4 +#define BBYTE3 0x8 +#define BWORD0 0x3 +#define BWORD1 0xc +#define BWORD 0xf + +#define MASKBYTE0 0xff +#define MASKBYTE1 0xff00 +#define MASKBYTE2 0xff0000 +#define MASKBYTE3 0xff000000 +#define MASKHWORD 0xffff0000 +#define MASKLWORD 0x0000ffff +#define MASKDWORD 0xffffffff +#define MASK12BITS 0xfff +#define MASKH4BITS 0xf0000000 +#define MASKOFDM_D 0xffc00000 +#define MASKCCK 0x3f3f3f3f + +#define MASK4BITS 0x0f +#define MASK20BITS 0xfffff +#define RFREG_OFFSET_MASK 0xfffff + +#define BENABLE 0x1 +#define BDISABLE 0x0 + +#define LEFT_ANTENNA 0x0 +#define RIGHT_ANTENNA 0x1 + +#define TCHECK_TXSTATUS 500 +#define TUPDATE_RXCOUNTER 100 + +#define REG_UN_used_register 0x01bf + +/* Path_A RFE cotrol pinmux*/ +#define RA_RFE_PINMUX 0xcb0 +/* Path_B RFE control pinmux*/ +#define RB_RFE_PINMUX 0xeb0 + +#define RA_RFE_INV 0xcb4 +#define RB_RFE_INV 0xeb4 + +/* RXIQC */ +/*RxIQ imblance matrix coeff. A & B*/ +#define RA_RXIQC_AB 0xc10 +/*RxIQ imblance matrix coeff. C & D*/ +#define RA_RXIQC_CD 0xc14 +/* Pah_A TX scaling factor*/ +#define RA_TXSCALE 0xc1c +/* Path_B TX scaling factor*/ +#define RB_TXSCALE 0xe1c +/*RxIQ imblance matrix coeff. A & B*/ +#define RB_RXIQC_AB 0xe10 +/*RxIQ imblance matrix coeff. C & D*/ +#define RB_RXIQC_CD 0xe14 +/*bit mask for IQC matrix element A & C*/ +#define RXIQC_AC 0x02ff + /*bit mask for IQC matrix element A & C*/ +#define RXIQC_BD 0x02ff0000 + +/* 2 EFUSE_TEST (For RTL8723 partially) */ +#define EFUSE_SEL(x) (((x) & 0x3) << 8) +#define EFUSE_SEL_MASK 0x300 +#define EFUSE_WIFI_SEL_0 0x0 + +/*REG_MULTI_FUNC_CTRL(For RTL8723 Only)*/ +/* Enable GPIO[9] as WiFi HW PDn source*/ +#define WL_HWPDN_EN BIT(0) +/* WiFi HW PDn polarity control*/ +#define WL_HWPDN_SL BIT(1) +/* WiFi function enable */ +#define WL_FUNC_EN BIT(2) +/* Enable GPIO[9] as WiFi RF HW PDn source */ +#define WL_HWROF_EN BIT(3) +/* Enable GPIO[11] as BT HW PDn source */ +#define BT_HWPDN_EN BIT(16) +/* BT HW PDn polarity control */ +#define BT_HWPDN_SL BIT(17) +/* BT function enable */ +#define BT_FUNC_EN BIT(18) +/* Enable GPIO[11] as BT/GPS RF HW PDn source */ +#define BT_HWROF_EN BIT(19) +/* Enable GPIO[10] as GPS HW PDn source */ +#define GPS_HWPDN_EN BIT(20) +/* GPS HW PDn polarity control */ +#define GPS_HWPDN_SL BIT(21) +/* GPS function enable */ +#define GPS_FUNC_EN BIT(22) + +#define BMASKBYTE0 0xff +#define BMASKBYTE1 0xff00 +#define BMASKBYTE2 0xff0000 +#define BMASKBYTE3 0xff000000 +#define BMASKHWORD 0xffff0000 +#define BMASKLWORD 0x0000ffff +#define BMASKDWORD 0xffffffff +#define BMASK12BITS 0xfff +#define BMASKH4BITS 0xf0000000 +#define BMASKOFDM_D 0xffc00000 +#define BMASKCCK 0x3f3f3f3f + +#define BRFREGOFFSETMASK 0xfffff + +#define ODM_REG_CCK_RPT_FORMAT_11AC 0x804 +#define ODM_REG_BB_RX_PATH_11AC 0x808 +/*PAGE 9*/ +#define ODM_REG_OFDM_FA_RST_11AC 0x9A4 +/*PAGE A*/ +#define ODM_REG_CCK_CCA_11AC 0xA0A +#define ODM_REG_CCK_FA_RST_11AC 0xA2C +#define ODM_REG_CCK_FA_11AC 0xA5C +/*PAGE C*/ +#define ODM_REG_IGI_A_11AC 0xC50 +/*PAGE E*/ +#define ODM_REG_IGI_B_11AC 0xE50 +/*PAGE F*/ +#define ODM_REG_OFDM_FA_11AC 0xF48 + +/* 2 MAC REG LIST */ + +/* DIG Related */ +#define ODM_BIT_IGI_11AC 0xFFFFFFFF +#define ODM_BIT_CCK_RPT_FORMAT_11AC BIT16 +#define ODM_BIT_BB_RX_PATH_11AC 0xF + +enum AGGRE_SIZE { + HT_AGG_SIZE_8K = 0, + HT_AGG_SIZE_16K = 1, + HT_AGG_SIZE_32K = 2, + HT_AGG_SIZE_64K = 3, + VHT_AGG_SIZE_128K = 4, + VHT_AGG_SIZE_256K = 5, + VHT_AGG_SIZE_512K = 6, + VHT_AGG_SIZE_1024K = 7, +}; + +#define REG_AMPDU_MAX_LENGTH_8812 0x0458 + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c new file mode 100644 index 000000000000..2922538160e5 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.c @@ -0,0 +1,465 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" + +static bool _rtl8821ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw); + +void rtl8821ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (bandwidth) { + case HT_CHANNEL_WIDTH_20: + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 3); + rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 3); + break; + case HT_CHANNEL_WIDTH_20_40: + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 1); + rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 1); + break; + case HT_CHANNEL_WIDTH_80: + rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 0); + rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 0); + break; + default: + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "unknown bandwidth: %#X\n", bandwidth); + break; + } +} + +void rtl8821ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u32 tx_agc[2] = {0, 0}, tmpval; + bool turbo_scanoff = false; + u8 idx1, idx2; + u8 *ptr; + u8 direction; + u32 pwrtrac_value; + + if (rtlefuse->eeprom_regulatory != 0) + turbo_scanoff = true; + + if (mac->act_scanning) { + tx_agc[RF90_PATH_A] = 0x3f3f3f3f; + tx_agc[RF90_PATH_B] = 0x3f3f3f3f; + + if (turbo_scanoff) { + for (idx1 = RF90_PATH_A; + idx1 <= RF90_PATH_B; + idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + } + } else { + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + tx_agc[idx1] = ppowerlevel[idx1] | + (ppowerlevel[idx1] << 8) | + (ppowerlevel[idx1] << 16) | + (ppowerlevel[idx1] << 24); + } + + if (rtlefuse->eeprom_regulatory == 0) { + tmpval = + (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + + (rtlphy->mcs_txpwrlevel_origoffset[0][7] << + 8); + tx_agc[RF90_PATH_A] += tmpval; + + tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + + (rtlphy->mcs_txpwrlevel_origoffset[0][15] << + 24); + tx_agc[RF90_PATH_B] += tmpval; + } + } + + for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { + ptr = (u8 *)(&tx_agc[idx1]); + for (idx2 = 0; idx2 < 4; idx2++) { + if (*ptr > RF6052_MAX_TX_PWR) + *ptr = RF6052_MAX_TX_PWR; + ptr++; + } + } + rtl8821ae_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); + if (direction == 1) { + tx_agc[0] += pwrtrac_value; + tx_agc[1] += pwrtrac_value; + } else if (direction == 2) { + tx_agc[0] -= pwrtrac_value; + tx_agc[1] -= pwrtrac_value; + } + tmpval = tx_agc[RF90_PATH_A]; + rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, MASKDWORD, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 1~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_A_CCK11_CCK1); + + tmpval = tx_agc[RF90_PATH_B]; + rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, MASKDWORD, tmpval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, + RTXAGC_B_CCK11_CCK1); +} + +static void rtl8821ae_phy_get_power_base(struct ieee80211_hw *hw, + u8 *ppowerlevel_ofdm, + u8 *ppowerlevel_bw20, + u8 *ppowerlevel_bw40, u8 channel, + u32 *ofdmbase, u32 *mcsbase) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u32 powerbase0, powerbase1; + u8 i, powerlevel[2]; + + for (i = 0; i < 2; i++) { + powerbase0 = ppowerlevel_ofdm[i]; + + powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | + (powerbase0 << 8) | powerbase0; + *(ofdmbase + i) = powerbase0; + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [OFDM power base index rf(%c) = 0x%x]\n", + ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)); + } + + for (i = 0; i < 2; i++) { + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) + powerlevel[i] = ppowerlevel_bw20[i]; + else + powerlevel[i] = ppowerlevel_bw40[i]; + + powerbase1 = powerlevel[i]; + powerbase1 = (powerbase1 << 24) | + (powerbase1 << 16) | (powerbase1 << 8) | powerbase1; + + *(mcsbase + i) = powerbase1; + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + " [MCS power base index rf(%c) = 0x%x]\n", + ((i == 0) ? 'A' : 'B'), *(mcsbase + i)); + } +} + +static void get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, + u8 channel, u8 index, + u32 *powerbase0, + u32 *powerbase1, + u32 *p_outwriteval) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff; + u32 writeval, customer_limit, rf; + + for (rf = 0; rf < 2; rf++) { + switch (rtlefuse->eeprom_regulatory) { + case 0: + chnlgroup = 0; + + writeval = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index + + (rf ? 8 : 0)] + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + case 1: + if (rtlphy->pwrgroup_cnt == 1) { + chnlgroup = 0; + } else { + if (channel < 3) + chnlgroup = 0; + else if (channel < 6) + chnlgroup = 1; + else if (channel < 9) + chnlgroup = 2; + else if (channel < 12) + chnlgroup = 3; + else if (channel < 14) + chnlgroup = 4; + else if (channel == 14) + chnlgroup = 5; + } + + writeval = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] + [index + (rf ? 8 : 0)] + ((index < 2) ? + powerbase0[rf] : + powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + + break; + case 2: + writeval = + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Better regulatory, writeval(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + case 3: + chnlgroup = 0; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 40MHz rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), + rtlefuse->pwrgroup_ht40[rf][channel - + 1]); + } else { + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "customer's limit, 20MHz rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), + rtlefuse->pwrgroup_ht20[rf][channel - + 1]); + } + + if (index < 2) + pwr_diff = rtlefuse->txpwr_legacyhtdiff[rf][channel-1]; + else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) + pwr_diff = + rtlefuse->txpwr_ht20diff[rf][channel-1]; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) + customer_pwr_diff = + rtlefuse->pwrgroup_ht40[rf][channel-1]; + else + customer_pwr_diff = + rtlefuse->pwrgroup_ht20[rf][channel-1]; + + if (pwr_diff > customer_pwr_diff) + pwr_diff = 0; + else + pwr_diff = customer_pwr_diff - pwr_diff; + + for (i = 0; i < 4; i++) { + pwr_diff_limit[i] = + (u8)((rtlphy->mcs_txpwrlevel_origoffset + [chnlgroup][index + (rf ? 8 : 0)] & + (0x7f << (i * 8))) >> (i * 8)); + + if (pwr_diff_limit[i] > pwr_diff) + pwr_diff_limit[i] = pwr_diff; + } + + customer_limit = (pwr_diff_limit[3] << 24) | + (pwr_diff_limit[2] << 16) | + (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer's limit rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), customer_limit); + + writeval = customer_limit + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Customer, writeval rf(%c)= 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + default: + chnlgroup = 0; + writeval = + rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] + [index + (rf ? 8 : 0)] + + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "RTK better performance, writeval rf(%c) = 0x%x\n", + ((rf == 0) ? 'A' : 'B'), writeval); + break; + } + + if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) + writeval = writeval - 0x06060606; + else if (rtlpriv->dm.dynamic_txhighpower_lvl == + TXHIGHPWRLEVEL_BT2) + writeval = writeval - 0x0c0c0c0c; + *(p_outwriteval + rf) = writeval; + } +} + +static void _rtl8821ae_write_ofdm_power_reg(struct ieee80211_hw *hw, + u8 index, u32 *pvalue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u16 regoffset_a[6] = { + RTXAGC_A_OFDM18_OFDM6, RTXAGC_A_OFDM54_OFDM24, + RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, + RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 + }; + u16 regoffset_b[6] = { + RTXAGC_B_OFDM18_OFDM6, RTXAGC_B_OFDM54_OFDM24, + RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, + RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 + }; + u8 i, rf, pwr_val[4]; + u32 writeval; + u16 regoffset; + + for (rf = 0; rf < 2; rf++) { + writeval = pvalue[rf]; + for (i = 0; i < 4; i++) { + pwr_val[i] = (u8)((writeval & (0x7f << + (i * 8))) >> (i * 8)); + + if (pwr_val[i] > RF6052_MAX_TX_PWR) + pwr_val[i] = RF6052_MAX_TX_PWR; + } + writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | + (pwr_val[1] << 8) | pwr_val[0]; + + if (rf == 0) + regoffset = regoffset_a[index]; + else + regoffset = regoffset_b[index]; + rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); + + RTPRINT(rtlpriv, FPHY, PHY_TXPWR, + "Set 0x%x = %08x\n", regoffset, writeval); + } +} + +void rtl8821ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel_ofdm, + u8 *ppowerlevel_bw20, + u8 *ppowerlevel_bw40, + u8 channel) +{ + u32 writeval[2], powerbase0[2], powerbase1[2]; + u8 index; + u8 direction; + u32 pwrtrac_value; + + rtl8821ae_phy_get_power_base(hw, ppowerlevel_ofdm, + ppowerlevel_bw20, + ppowerlevel_bw40, + channel, + &powerbase0[0], + &powerbase1[0]); + + rtl8821ae_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); + + for (index = 0; index < 6; index++) { + get_txpower_writeval_by_regulatory(hw, channel, index, + &powerbase0[0], + &powerbase1[0], + &writeval[0]); + if (direction == 1) { + writeval[0] += pwrtrac_value; + writeval[1] += pwrtrac_value; + } else if (direction == 2) { + writeval[0] -= pwrtrac_value; + writeval[1] -= pwrtrac_value; + } + _rtl8821ae_write_ofdm_power_reg(hw, index, &writeval[0]); + } +} + +bool rtl8821ae_phy_rf6052_config(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + + if (rtlphy->rf_type == RF_1T1R) + rtlphy->num_total_rfpath = 1; + else + rtlphy->num_total_rfpath = 2; + + return _rtl8821ae_phy_rf6052_config_parafile(hw); +} + +static bool _rtl8821ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + u8 rfpath; + bool rtstatus = true; + + for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { + switch (rfpath) { + case RF90_PATH_A: { + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtstatus = + rtl8812ae_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + else + rtstatus = + rtl8821ae_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + break; + } + case RF90_PATH_B: + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) + rtstatus = + rtl8812ae_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + else + rtstatus = + rtl8821ae_phy_config_rf_with_headerfile(hw, + (enum radio_path)rfpath); + break; + case RF90_PATH_C: + break; + case RF90_PATH_D: + break; + } + + if (!rtstatus) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "Radio[%d] Fail!!", rfpath); + return false; + } + } + + /*put arrays in dm.c*/ + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); + return rtstatus; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h new file mode 100644 index 000000000000..efd22bd0b139 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/rf.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8821AE_RF_H__ +#define __RTL8821AE_RF_H__ + +#define RF6052_MAX_TX_PWR 0x3F + +void rtl8821ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, + u8 bandwidth); +void rtl8821ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel); +void rtl8821ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, + u8 *ppowerlevel_ofdm, + u8 *ppowerlevel_bw20, + u8 *ppowerlevel_bw40, + u8 channel); +bool rtl8821ae_phy_rf6052_config(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c new file mode 100644 index 000000000000..a4988121e1ab --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c @@ -0,0 +1,458 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../core.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "hw.h" +#include "fw.h" +#include "sw.h" +#include "trx.h" +#include "led.h" +#include "table.h" +#include "../btcoexist/rtl_btc.h" + +#include +#include + +static void rtl8821ae_init_aspm_vars(struct ieee80211_hw *hw) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + + /*close ASPM for AMD defaultly */ + rtlpci->const_amdpci_aspm = 0; + + /** + * ASPM PS mode. + * 0 - Disable ASPM, + * 1 - Enable ASPM without Clock Req, + * 2 - Enable ASPM with Clock Req, + * 3 - Alwyas Enable ASPM with Clock Req, + * 4 - Always Enable ASPM without Clock Req. + * set defult to RTL8192CE:3 RTL8192E:2 + */ + rtlpci->const_pci_aspm = 3; + + /*Setting for PCI-E device */ + rtlpci->const_devicepci_aspm_setting = 0x03; + + /*Setting for PCI-E bridge */ + rtlpci->const_hostpci_aspm_setting = 0x02; + + /** + * In Hw/Sw Radio Off situation. + * 0 - Default, + * 1 - From ASPM setting without low Mac Pwr, + * 2 - From ASPM setting with low Mac Pwr, + * 3 - Bus D3 + * set default to RTL8192CE:0 RTL8192SE:2 + */ + rtlpci->const_hwsw_rfoff_d3 = 0; + + /** + * This setting works for those device with + * backdoor ASPM setting such as EPHY setting. + * 0 - Not support ASPM, + * 1 - Support ASPM, + * 2 - According to chipset. + */ + rtlpci->const_support_pciaspm = 1; +} + +/*InitializeVariables8812E*/ +int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw) +{ + int err = 0; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + + rtl8821ae_bt_reg_init(hw); + rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; + rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); + + rtlpriv->dm.dm_initialgain_enable = 1; + rtlpriv->dm.dm_flag = 0; + rtlpriv->dm.disable_framebursting = 0; + rtlpriv->dm.thermalvalue = 0; + rtlpci->transmit_config = CFENDFORM | BIT(15) | BIT(24) | BIT(25); + + mac->ht_enable = true; + mac->ht_cur_stbc = 0; + mac->ht_stbc_cap = 0; + mac->vht_cur_ldpc = 0; + mac->vht_ldpc_cap = 0; + mac->vht_cur_stbc = 0; + mac->vht_stbc_cap = 0; + + rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; + /*following 2 is for register 5G band, refer to _rtl_init_mac80211()*/ + rtlpriv->rtlhal.bandset = BAND_ON_BOTH; + rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; + + rtlpci->receive_config = (RCR_APPFCS | + RCR_APP_MIC | + RCR_APP_ICV | + RCR_APP_PHYST_RXFF | + RCR_NONQOS_VHT | + RCR_HTC_LOC_CTRL | + RCR_AMF | + RCR_ACF | + /*This bit controls the PS-Poll packet filter.*/ + RCR_ADF | + RCR_AICV | + RCR_ACRC32 | + RCR_AB | + RCR_AM | + RCR_APM | + 0); + + rtlpci->irq_mask[0] = + (u32)(IMR_PSTIMEOUT | + IMR_GTINT3 | + IMR_HSISR_IND_ON_INT | + IMR_C2HCMD | + IMR_HIGHDOK | + IMR_MGNTDOK | + IMR_BKDOK | + IMR_BEDOK | + IMR_VIDOK | + IMR_VODOK | + IMR_RDU | + IMR_ROK | + 0); + + rtlpci->irq_mask[1] = + (u32)(IMR_RXFOVW | + IMR_TXFOVW | + 0); + rtlpci->sys_irq_mask = (u32)(HSIMR_PDN_INT_EN | + HSIMR_RON_INT_EN | + 0); + /* for WOWLAN */ + 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; + rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; + rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; + if (rtlpriv->cfg->mod_params->disable_watchdog) + pr_info("watchdog disabled\n"); + rtlpriv->psc.reg_fwctrl_lps = 3; + rtlpriv->psc.reg_max_lps_awakeintvl = 5; + rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; + + /* for ASPM, you can close aspm through + * set const_support_pciaspm = 0 + */ + rtl8821ae_init_aspm_vars(hw); + + if (rtlpriv->psc.reg_fwctrl_lps == 1) + rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 2) + rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; + else if (rtlpriv->psc.reg_fwctrl_lps == 3) + rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); + if (!rtlpriv->rtlhal.pfirmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't alloc buffer for fw.\n"); + return 1; + } + rtlpriv->rtlhal.wowlan_firmware = vzalloc(0x8000); + if (!rtlpriv->rtlhal.wowlan_firmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't alloc buffer for wowlan fw.\n"); + return 1; + } + + if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { + rtlpriv->cfg->fw_name = "rtlwifi/rtl8812aefw.bin"; + rtlpriv->cfg->wowlan_fw_name = "rtlwifi/rtl8812aefw_wowlan.bin"; + } else { + rtlpriv->cfg->fw_name = "rtlwifi/rtl8821aefw.bin"; + rtlpriv->cfg->wowlan_fw_name = "rtlwifi/rtl8821aefw_wowlan.bin"; + } + + rtlpriv->max_fw_size = 0x8000; + /*load normal firmware*/ + pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); + err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, + rtlpriv->io.dev, GFP_KERNEL, hw, + rtl_fw_cb); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to request normal firmware!\n"); + return 1; + } + /*load wowlan firmware*/ + pr_info("Using firmware %s\n", rtlpriv->cfg->wowlan_fw_name); + err = request_firmware_nowait(THIS_MODULE, 1, + rtlpriv->cfg->wowlan_fw_name, + rtlpriv->io.dev, GFP_KERNEL, hw, + rtl_wowlan_fw_cb); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Failed to request wowlan firmware!\n"); + return 1; + } + return 0; +} + +void rtl8821ae_deinit_sw_vars(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (rtlpriv->rtlhal.pfirmware) { + vfree(rtlpriv->rtlhal.pfirmware); + rtlpriv->rtlhal.pfirmware = NULL; + } +#if (USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN == 1) + if (rtlpriv->rtlhal.wowlan_firmware) { + vfree(rtlpriv->rtlhal.wowlan_firmware); + rtlpriv->rtlhal.wowlan_firmware = NULL; + } +#endif +} + +/* get bt coexist status */ +bool rtl8821ae_get_btc_status(void) +{ + return true; +} + +static struct rtl_hal_ops rtl8821ae_hal_ops = { + .init_sw_vars = rtl8821ae_init_sw_vars, + .deinit_sw_vars = rtl8821ae_deinit_sw_vars, + .read_eeprom_info = rtl8821ae_read_eeprom_info, + .interrupt_recognized = rtl8821ae_interrupt_recognized, + .hw_init = rtl8821ae_hw_init, + .hw_disable = rtl8821ae_card_disable, + .hw_suspend = rtl8821ae_suspend, + .hw_resume = rtl8821ae_resume, + .enable_interrupt = rtl8821ae_enable_interrupt, + .disable_interrupt = rtl8821ae_disable_interrupt, + .set_network_type = rtl8821ae_set_network_type, + .set_chk_bssid = rtl8821ae_set_check_bssid, + .set_qos = rtl8821ae_set_qos, + .set_bcn_reg = rtl8821ae_set_beacon_related_registers, + .set_bcn_intv = rtl8821ae_set_beacon_interval, + .update_interrupt_mask = rtl8821ae_update_interrupt_mask, + .get_hw_reg = rtl8821ae_get_hw_reg, + .set_hw_reg = rtl8821ae_set_hw_reg, + .update_rate_tbl = rtl8821ae_update_hal_rate_tbl, + .fill_tx_desc = rtl8821ae_tx_fill_desc, + .fill_tx_cmddesc = rtl8821ae_tx_fill_cmddesc, + .query_rx_desc = rtl8821ae_rx_query_desc, + .set_channel_access = rtl8821ae_update_channel_access_setting, + .radio_onoff_checking = rtl8821ae_gpio_radio_on_off_checking, + .set_bw_mode = rtl8821ae_phy_set_bw_mode, + .switch_channel = rtl8821ae_phy_sw_chnl, + .dm_watchdog = rtl8821ae_dm_watchdog, + .scan_operation_backup = rtl8821ae_phy_scan_operation_backup, + .set_rf_power_state = rtl8821ae_phy_set_rf_power_state, + .led_control = rtl8821ae_led_control, + .set_desc = rtl8821ae_set_desc, + .get_desc = rtl8821ae_get_desc, + .is_tx_desc_closed = rtl8821ae_is_tx_desc_closed, + .tx_polling = rtl8821ae_tx_polling, + .enable_hw_sec = rtl8821ae_enable_hw_security_config, + .set_key = rtl8821ae_set_key, + .init_sw_leds = rtl8821ae_init_sw_leds, + .get_bbreg = rtl8821ae_phy_query_bb_reg, + .set_bbreg = rtl8821ae_phy_set_bb_reg, + .get_rfreg = rtl8821ae_phy_query_rf_reg, + .set_rfreg = rtl8821ae_phy_set_rf_reg, + .fill_h2c_cmd = rtl8821ae_fill_h2c_cmd, + .get_btc_status = rtl8821ae_get_btc_status, + .rx_command_packet = rtl8821ae_rx_command_packet, + .add_wowlan_pattern = rtl8821ae_add_wowlan_pattern, +}; + +static struct rtl_mod_params rtl8821ae_mod_params = { + .sw_crypto = false, + .inactiveps = true, + .swctrl_lps = false, + .fwctrl_lps = true, + .msi_support = true, + .debug = DBG_EMERG, + .disable_watchdog = 0, +}; + +static struct rtl_hal_cfg rtl8821ae_hal_cfg = { + .bar_id = 2, + .write_readback = true, + .name = "rtl8821ae_pci", + .fw_name = "rtlwifi/rtl8821aefw.bin", + .ops = &rtl8821ae_hal_ops, + .mod_params = &rtl8821ae_mod_params, + .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, + .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, + .maps[SYS_CLK] = REG_SYS_CLKR, + .maps[MAC_RCR_AM] = AM, + .maps[MAC_RCR_AB] = AB, + .maps[MAC_RCR_ACRC32] = ACRC32, + .maps[MAC_RCR_ACF] = ACF, + .maps[MAC_RCR_AAP] = AAP, + .maps[MAC_HIMR] = REG_HIMR, + .maps[MAC_HIMRE] = REG_HIMRE, + + .maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS, + + .maps[EFUSE_TEST] = REG_EFUSE_TEST, + .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_CLK] = 0, + .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, + .maps[EFUSE_PWC_EV12V] = PWC_EV12V, + .maps[EFUSE_FEN_ELDR] = FEN_ELDR, + .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, + .maps[EFUSE_ANA8M] = ANA8M, + .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, + .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, + .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, + .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, + + .maps[RWCAM] = REG_CAMCMD, + .maps[WCAMI] = REG_CAMWRITE, + .maps[RCAMO] = REG_CAMREAD, + .maps[CAMDBG] = REG_CAMDBG, + .maps[SECR] = REG_SECCFG, + .maps[SEC_CAM_NONE] = CAM_NONE, + .maps[SEC_CAM_WEP40] = CAM_WEP40, + .maps[SEC_CAM_TKIP] = CAM_TKIP, + .maps[SEC_CAM_AES] = CAM_AES, + .maps[SEC_CAM_WEP104] = CAM_WEP104, + + .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, + .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, + .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, + .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, + .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, + .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, +/* .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, */ /*need check*/ + .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, + .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, + .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, + .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, + .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, + .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, + .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, +/* .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,*/ +/* .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,*/ + + .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, + .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, + .maps[RTL_IMR_BCNINT] = IMR_BCNDMAINT0, + .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, + .maps[RTL_IMR_RDU] = IMR_RDU, + .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, + .maps[RTL_IMR_BDOK] = IMR_BCNDOK0, + .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, + .maps[RTL_IMR_TBDER] = IMR_TBDER, + .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, + .maps[RTL_IMR_TBDOK] = IMR_TBDOK, + .maps[RTL_IMR_BKDOK] = IMR_BKDOK, + .maps[RTL_IMR_BEDOK] = IMR_BEDOK, + .maps[RTL_IMR_VIDOK] = IMR_VIDOK, + .maps[RTL_IMR_VODOK] = IMR_VODOK, + .maps[RTL_IMR_ROK] = IMR_ROK, + .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER), + + .maps[RTL_RC_CCK_RATE1M] = DESC_RATE1M, + .maps[RTL_RC_CCK_RATE2M] = DESC_RATE2M, + .maps[RTL_RC_CCK_RATE5_5M] = DESC_RATE5_5M, + .maps[RTL_RC_CCK_RATE11M] = DESC_RATE11M, + .maps[RTL_RC_OFDM_RATE6M] = DESC_RATE6M, + .maps[RTL_RC_OFDM_RATE9M] = DESC_RATE9M, + .maps[RTL_RC_OFDM_RATE12M] = DESC_RATE12M, + .maps[RTL_RC_OFDM_RATE18M] = DESC_RATE18M, + .maps[RTL_RC_OFDM_RATE24M] = DESC_RATE24M, + .maps[RTL_RC_OFDM_RATE36M] = DESC_RATE36M, + .maps[RTL_RC_OFDM_RATE48M] = DESC_RATE48M, + .maps[RTL_RC_OFDM_RATE54M] = DESC_RATE54M, + + .maps[RTL_RC_HT_RATEMCS7] = DESC_RATEMCS7, + .maps[RTL_RC_HT_RATEMCS15] = DESC_RATEMCS15, + + /*VHT hightest rate*/ + .maps[RTL_RC_VHT_RATE_1SS_MCS7] = DESC_RATEVHT1SS_MCS7, + .maps[RTL_RC_VHT_RATE_1SS_MCS8] = DESC_RATEVHT1SS_MCS8, + .maps[RTL_RC_VHT_RATE_1SS_MCS9] = DESC_RATEVHT1SS_MCS9, + .maps[RTL_RC_VHT_RATE_2SS_MCS7] = DESC_RATEVHT2SS_MCS7, + .maps[RTL_RC_VHT_RATE_2SS_MCS8] = DESC_RATEVHT2SS_MCS8, + .maps[RTL_RC_VHT_RATE_2SS_MCS9] = DESC_RATEVHT2SS_MCS9, +}; + +static struct pci_device_id rtl8821ae_pci_ids[] = { + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8812, rtl8821ae_hal_cfg)}, + {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8821, rtl8821ae_hal_cfg)}, + {}, +}; + +MODULE_DEVICE_TABLE(pci, rtl8821ae_pci_ids); + +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_LICENSE("GPL"); +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(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); +module_param_named(msi, rtl8821ae_mod_params.msi_support, bool, 0444); +module_param_named(disable_watchdog, rtl8821ae_mod_params.disable_watchdog, + bool, 0444); +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(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(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); + +static struct pci_driver rtl8821ae_driver = { + .name = KBUILD_MODNAME, + .id_table = rtl8821ae_pci_ids, + .probe = rtl_pci_probe, + .remove = rtl_pci_disconnect, + .driver.pm = &rtlwifi_pm_ops, +}; + +module_pci_driver(rtl8821ae_driver); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h new file mode 100644 index 000000000000..d001e7ce3052 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8821AE_SW_H__ +#define __RTL8821AE_SW_H__ + +int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw); +void rtl8821ae_deinit_sw_vars(struct ieee80211_hw *hw); +void rtl8821ae_init_var_map(struct ieee80211_hw *hw); +bool rtl8821ae_get_btc_status(void); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c new file mode 100644 index 000000000000..62a0fb76f080 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c @@ -0,0 +1,4572 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger + * + *****************************************************************************/ + +#include "table.h" +u32 RTL8812AE_PHY_REG_ARRAY[] = { + 0x800, 0x8020D010, + 0x804, 0x080112E0, + 0x808, 0x0E028233, + 0x80C, 0x12131113, + 0x810, 0x20101263, + 0x814, 0x020C3D10, + 0x818, 0x03A00385, + 0x820, 0x00000000, + 0x824, 0x00030FE0, + 0x828, 0x00000000, + 0x82C, 0x002083DD, + 0x830, 0x2AAA6C86, + 0x834, 0x0037A706, + 0x838, 0x06C89B44, + 0x83C, 0x0000095B, + 0x840, 0xC0000001, + 0x844, 0x40003CDE, + 0x848, 0x6210FF8B, + 0x84C, 0x6CFDFFB8, + 0x850, 0x28874706, + 0x854, 0x0001520C, + 0x858, 0x8060E000, + 0x85C, 0x74210168, + 0x860, 0x6929C321, + 0x864, 0x79727432, + 0x868, 0x8CA7A314, + 0x86C, 0x338C2878, + 0x870, 0x03333333, + 0x874, 0x31602C2E, + 0x878, 0x00003152, + 0x87C, 0x000FC000, + 0x8A0, 0x00000013, + 0x8A4, 0x7F7F7F7F, + 0x8A8, 0xA202033E, + 0x8AC, 0x0FF0FA0A, + 0x8B0, 0x00000600, + 0x8B4, 0x000FC080, + 0x8B8, 0x6C0057FF, + 0x8BC, 0x4CA520A3, + 0x8C0, 0x27F00020, + 0x8C4, 0x00000000, + 0x8C8, 0x00013169, + 0x8CC, 0x08248492, + 0x8D0, 0x0000B800, + 0x8DC, 0x00000000, + 0x8D4, 0x940008A0, + 0x8D8, 0x290B5612, + 0x8F8, 0x400002C0, + 0x8FC, 0x00000000, + 0xFF0F07D8, 0xABCD, + 0x900, 0x00000701, + 0xFF0F07D0, 0xCDEF, + 0x900, 0x00000701, + 0xCDCDCDCD, 0xCDCD, + 0x900, 0x00000700, + 0xFF0F07D8, 0xDEAD, + 0x90C, 0x00000000, + 0x910, 0x0000FC00, + 0x914, 0x00000404, + 0x918, 0x1C1028C0, + 0x91C, 0x64B11A1C, + 0x920, 0xE0767233, + 0x924, 0x055AA500, + 0x928, 0x00000004, + 0x92C, 0xFFFE0000, + 0x930, 0xFFFFFFFE, + 0x934, 0x001FFFFF, + 0x960, 0x00000000, + 0x964, 0x00000000, + 0x968, 0x00000000, + 0x96C, 0x00000000, + 0x970, 0x801FFFFF, + 0x978, 0x00000000, + 0x97C, 0x00000000, + 0x980, 0x00000000, + 0x984, 0x00000000, + 0x988, 0x00000000, + 0x990, 0x27100000, + 0x994, 0xFFFF0100, + 0x998, 0xFFFFFF5C, + 0x99C, 0xFFFFFFFF, + 0x9A0, 0x000000FF, + 0x9A4, 0x00080080, + 0x9A8, 0x00000000, + 0x9AC, 0x00000000, + 0x9B0, 0x81081008, + 0x9B4, 0x00000000, + 0x9B8, 0x01081008, + 0x9BC, 0x01081008, + 0x9D0, 0x00000000, + 0x9D4, 0x00000000, + 0x9D8, 0x00000000, + 0x9DC, 0x00000000, + 0x9E4, 0x00000002, + 0x9E8, 0x000002D5, + 0xA00, 0x00D047C8, + 0xA04, 0x01FF000C, + 0xA08, 0x8C838300, + 0xA0C, 0x2E7F000F, + 0xA10, 0x9500BB78, + 0xA14, 0x11144028, + 0xA18, 0x00881117, + 0xA1C, 0x89140F00, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0xA2C, 0x00900000, + 0xA70, 0x101FFF00, + 0xA74, 0x00000008, + 0xA78, 0x00000900, + 0xA7C, 0x225B0606, + 0xA80, 0x218075B2, + 0xA84, 0x001F8C80, + 0xB00, 0x03100000, + 0xB04, 0x0000B000, + 0xB08, 0xAE0201EB, + 0xB0C, 0x01003207, + 0xB10, 0x00009807, + 0xB14, 0x01000000, + 0xB18, 0x00000002, + 0xB1C, 0x00000002, + 0xB20, 0x0000001F, + 0xB24, 0x03020100, + 0xB28, 0x07060504, + 0xB2C, 0x0B0A0908, + 0xB30, 0x0F0E0D0C, + 0xB34, 0x13121110, + 0xB38, 0x17161514, + 0xB3C, 0x0000003A, + 0xB40, 0x00000000, + 0xB44, 0x00000000, + 0xB48, 0x13000032, + 0xB4C, 0x48080000, + 0xB50, 0x00000000, + 0xB54, 0x00000000, + 0xB58, 0x00000000, + 0xB5C, 0x00000000, + 0xC00, 0x00000007, + 0xC04, 0x00042020, + 0xC08, 0x80410231, + 0xC0C, 0x00000000, + 0xC10, 0x00000100, + 0xC14, 0x01000000, + 0xC1C, 0x40000003, + 0xC20, 0x12121212, + 0xC24, 0x12121212, + 0xC28, 0x12121212, + 0xC2C, 0x12121212, + 0xC30, 0x12121212, + 0xC34, 0x12121212, + 0xC38, 0x12121212, + 0xC3C, 0x12121212, + 0xC40, 0x12121212, + 0xC44, 0x12121212, + 0xC48, 0x12121212, + 0xC4C, 0x12121212, + 0xC50, 0x00000020, + 0xC54, 0x0008121C, + 0xC58, 0x30000C1C, + 0xC5C, 0x00000058, + 0xC60, 0x34344443, + 0xC64, 0x07003333, + 0xC68, 0x59791979, + 0xC6C, 0x59795979, + 0xC70, 0x19795979, + 0xC74, 0x19795979, + 0xC78, 0x19791979, + 0xC7C, 0x19791979, + 0xC80, 0x19791979, + 0xC84, 0x19791979, + 0xC94, 0x0100005C, + 0xC98, 0x00000000, + 0xC9C, 0x00000000, + 0xCA0, 0x00000029, + 0xCA4, 0x08040201, + 0xCA8, 0x80402010, + 0xFF0F0740, 0xABCD, + 0xCB0, 0x77547717, + 0xFF0F01C0, 0xCDEF, + 0xCB0, 0x77547717, + 0xFF0F02C0, 0xCDEF, + 0xCB0, 0x77547717, + 0xFF0F07D8, 0xCDEF, + 0xCB0, 0x54547710, + 0xFF0F07D0, 0xCDEF, + 0xCB0, 0x54547710, + 0xCDCDCDCD, 0xCDCD, + 0xCB0, 0x77547777, + 0xFF0F0740, 0xDEAD, + 0xCB4, 0x00000077, + 0xCB8, 0x00508242, + 0xE00, 0x00000007, + 0xE04, 0x00042020, + 0xE08, 0x80410231, + 0xE0C, 0x00000000, + 0xE10, 0x00000100, + 0xE14, 0x01000000, + 0xE1C, 0x40000003, + 0xE20, 0x12121212, + 0xE24, 0x12121212, + 0xE28, 0x12121212, + 0xE2C, 0x12121212, + 0xE30, 0x12121212, + 0xE34, 0x12121212, + 0xE38, 0x12121212, + 0xE3C, 0x12121212, + 0xE40, 0x12121212, + 0xE44, 0x12121212, + 0xE48, 0x12121212, + 0xE4C, 0x12121212, + 0xE50, 0x00000020, + 0xE54, 0x0008121C, + 0xE58, 0x30000C1C, + 0xE5C, 0x00000058, + 0xE60, 0x34344443, + 0xE64, 0x07003333, + 0xE68, 0x59791979, + 0xE6C, 0x59795979, + 0xE70, 0x19795979, + 0xE74, 0x19795979, + 0xE78, 0x19791979, + 0xE7C, 0x19791979, + 0xE80, 0x19791979, + 0xE84, 0x19791979, + 0xE94, 0x0100005C, + 0xE98, 0x00000000, + 0xE9C, 0x00000000, + 0xEA0, 0x00000029, + 0xEA4, 0x08040201, + 0xEA8, 0x80402010, + 0xFF0F0740, 0xABCD, + 0xEB0, 0x77547717, + 0xFF0F01C0, 0xCDEF, + 0xEB0, 0x77547717, + 0xFF0F02C0, 0xCDEF, + 0xEB0, 0x77547717, + 0xFF0F07D8, 0xCDEF, + 0xEB0, 0x54547710, + 0xFF0F07D0, 0xCDEF, + 0xEB0, 0x54547710, + 0xCDCDCDCD, 0xCDCD, + 0xEB0, 0x77547777, + 0xFF0F0740, 0xDEAD, + 0xEB4, 0x00000077, + 0xEB8, 0x00508242, +}; + +u32 RTL8821AE_PHY_REG_ARRAY[] = { + 0x800, 0x0020D090, + 0x804, 0x080112E0, + 0x808, 0x0E028211, + 0x80C, 0x92131111, + 0x810, 0x20101261, + 0x814, 0x020C3D10, + 0x818, 0x03A00385, + 0x820, 0x00000000, + 0x824, 0x00030FE0, + 0x828, 0x00000000, + 0x82C, 0x002081DD, + 0x830, 0x2AAA8E24, + 0x834, 0x0037A706, + 0x838, 0x06489B44, + 0x83C, 0x0000095B, + 0x840, 0xC0000001, + 0x844, 0x40003CDE, + 0x848, 0x62103F8B, + 0x84C, 0x6CFDFFB8, + 0x850, 0x28874706, + 0x854, 0x0001520C, + 0x858, 0x8060E000, + 0x85C, 0x74210168, + 0x860, 0x6929C321, + 0x864, 0x79727432, + 0x868, 0x8CA7A314, + 0x86C, 0x888C2878, + 0x870, 0x08888888, + 0x874, 0x31612C2E, + 0x878, 0x00000152, + 0x87C, 0x000FD000, + 0x8A0, 0x00000013, + 0x8A4, 0x7F7F7F7F, + 0x8A8, 0xA2000338, + 0x8AC, 0x0FF0FA0A, + 0x8B4, 0x000FC080, + 0x8B8, 0x6C10D7FF, + 0x8BC, 0x0CA52090, + 0x8C0, 0x1BF00020, + 0x8C4, 0x00000000, + 0x8C8, 0x00013169, + 0x8CC, 0x08248492, + 0x8D4, 0x940008A0, + 0x8D8, 0x290B5612, + 0x8F8, 0x400002C0, + 0x8FC, 0x00000000, + 0x900, 0x00000700, + 0x90C, 0x00000000, + 0x910, 0x0000FC00, + 0x914, 0x00000404, + 0x918, 0x1C1028C0, + 0x91C, 0x64B11A1C, + 0x920, 0xE0767233, + 0x924, 0x055AA500, + 0x928, 0x00000004, + 0x92C, 0xFFFE0000, + 0x930, 0xFFFFFFFE, + 0x934, 0x001FFFFF, + 0x960, 0x00000000, + 0x964, 0x00000000, + 0x968, 0x00000000, + 0x96C, 0x00000000, + 0x970, 0x801FFFFF, + 0x974, 0x000003FF, + 0x978, 0x00000000, + 0x97C, 0x00000000, + 0x980, 0x00000000, + 0x984, 0x00000000, + 0x988, 0x00000000, + 0x990, 0x27100000, + 0x994, 0xFFFF0100, + 0x998, 0xFFFFFF5C, + 0x99C, 0xFFFFFFFF, + 0x9A0, 0x000000FF, + 0x9A4, 0x00480080, + 0x9A8, 0x00000000, + 0x9AC, 0x00000000, + 0x9B0, 0x81081008, + 0x9B4, 0x01081008, + 0x9B8, 0x01081008, + 0x9BC, 0x01081008, + 0x9D0, 0x00000000, + 0x9D4, 0x00000000, + 0x9D8, 0x00000000, + 0x9DC, 0x00000000, + 0x9E0, 0x00005D00, + 0x9E4, 0x00000002, + 0x9E8, 0x00000001, + 0xA00, 0x00D047C8, + 0xA04, 0x01FF000C, + 0xA08, 0x8C8A8300, + 0xA0C, 0x2E68000F, + 0xA10, 0x9500BB78, + 0xA14, 0x11144028, + 0xA18, 0x00881117, + 0xA1C, 0x89140F00, + 0xA20, 0x1A1B0000, + 0xA24, 0x090E1317, + 0xA28, 0x00000204, + 0xA2C, 0x00900000, + 0xA70, 0x101FFF00, + 0xA74, 0x00000008, + 0xA78, 0x00000900, + 0xA7C, 0x225B0606, + 0xA80, 0x21805490, + 0xA84, 0x001F0000, + 0xB00, 0x03100040, + 0xB04, 0x0000B000, + 0xB08, 0xAE0201EB, + 0xB0C, 0x01003207, + 0xB10, 0x00009807, + 0xB14, 0x01000000, + 0xB18, 0x00000002, + 0xB1C, 0x00000002, + 0xB20, 0x0000001F, + 0xB24, 0x03020100, + 0xB28, 0x07060504, + 0xB2C, 0x0B0A0908, + 0xB30, 0x0F0E0D0C, + 0xB34, 0x13121110, + 0xB38, 0x17161514, + 0xB3C, 0x0000003A, + 0xB40, 0x00000000, + 0xB44, 0x00000000, + 0xB48, 0x13000032, + 0xB4C, 0x48080000, + 0xB50, 0x00000000, + 0xB54, 0x00000000, + 0xB58, 0x00000000, + 0xB5C, 0x00000000, + 0xC00, 0x00000007, + 0xC04, 0x00042020, + 0xC08, 0x80410231, + 0xC0C, 0x00000000, + 0xC10, 0x00000100, + 0xC14, 0x01000000, + 0xC1C, 0x40000003, + 0xC20, 0x2C2C2C2C, + 0xC24, 0x30303030, + 0xC28, 0x30303030, + 0xC2C, 0x2C2C2C2C, + 0xC30, 0x2C2C2C2C, + 0xC34, 0x2C2C2C2C, + 0xC38, 0x2C2C2C2C, + 0xC3C, 0x2A2A2A2A, + 0xC40, 0x2A2A2A2A, + 0xC44, 0x2A2A2A2A, + 0xC48, 0x2A2A2A2A, + 0xC4C, 0x2A2A2A2A, + 0xC50, 0x00000020, + 0xC54, 0x001C1208, + 0xC58, 0x30000C1C, + 0xC5C, 0x00000058, + 0xC60, 0x34344443, + 0xC64, 0x07003333, + 0xC68, 0x19791979, + 0xC6C, 0x19791979, + 0xC70, 0x19791979, + 0xC74, 0x19791979, + 0xC78, 0x19791979, + 0xC7C, 0x19791979, + 0xC80, 0x19791979, + 0xC84, 0x19791979, + 0xC94, 0x0100005C, + 0xC98, 0x00000000, + 0xC9C, 0x00000000, + 0xCA0, 0x00000029, + 0xCA4, 0x08040201, + 0xCA8, 0x80402010, + 0xCB0, 0x77775747, + 0xCB4, 0x10000077, + 0xCB8, 0x00508240, +}; + +u32 RTL8812AE_PHY_REG_ARRAY_PG[] = { + 0, 0, 0, 0x00000c20, 0xffffffff, 0x34363840, + 0, 0, 0, 0x00000c24, 0xffffffff, 0x42424444, + 0, 0, 0, 0x00000c28, 0xffffffff, 0x30323638, + 0, 0, 0, 0x00000c2c, 0xffffffff, 0x40424444, + 0, 0, 0, 0x00000c30, 0xffffffff, 0x28303236, + 0, 0, 1, 0x00000c34, 0xffffffff, 0x38404242, + 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283034, + 0, 0, 0, 0x00000c3c, 0xffffffff, 0x40424444, + 0, 0, 0, 0x00000c40, 0xffffffff, 0x28303236, + 0, 0, 0, 0x00000c44, 0xffffffff, 0x42422426, + 0, 0, 1, 0x00000c48, 0xffffffff, 0x30343840, + 0, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, + 0, 1, 0, 0x00000e20, 0xffffffff, 0x34363840, + 0, 1, 0, 0x00000e24, 0xffffffff, 0x42424444, + 0, 1, 0, 0x00000e28, 0xffffffff, 0x30323638, + 0, 1, 0, 0x00000e2c, 0xffffffff, 0x40424444, + 0, 1, 0, 0x00000e30, 0xffffffff, 0x28303236, + 0, 1, 1, 0x00000e34, 0xffffffff, 0x38404242, + 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283034, + 0, 1, 0, 0x00000e3c, 0xffffffff, 0x40424444, + 0, 1, 0, 0x00000e40, 0xffffffff, 0x28303236, + 0, 1, 0, 0x00000e44, 0xffffffff, 0x42422426, + 0, 1, 1, 0x00000e48, 0xffffffff, 0x30343840, + 0, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, + 1, 0, 0, 0x00000c24, 0xffffffff, 0x42424444, + 1, 0, 0, 0x00000c28, 0xffffffff, 0x30323640, + 1, 0, 0, 0x00000c2c, 0xffffffff, 0x40424444, + 1, 0, 0, 0x00000c30, 0xffffffff, 0x28303236, + 1, 0, 1, 0x00000c34, 0xffffffff, 0x38404242, + 1, 0, 1, 0x00000c38, 0xffffffff, 0x26283034, + 1, 0, 0, 0x00000c3c, 0xffffffff, 0x40424444, + 1, 0, 0, 0x00000c40, 0xffffffff, 0x28303236, + 1, 0, 0, 0x00000c44, 0xffffffff, 0x42422426, + 1, 0, 1, 0x00000c48, 0xffffffff, 0x30343840, + 1, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, + 1, 1, 0, 0x00000e24, 0xffffffff, 0x42424444, + 1, 1, 0, 0x00000e28, 0xffffffff, 0x30323640, + 1, 1, 0, 0x00000e2c, 0xffffffff, 0x40424444, + 1, 1, 0, 0x00000e30, 0xffffffff, 0x28303236, + 1, 1, 1, 0x00000e34, 0xffffffff, 0x38404242, + 1, 1, 1, 0x00000e38, 0xffffffff, 0x26283034, + 1, 1, 0, 0x00000e3c, 0xffffffff, 0x40424444, + 1, 1, 0, 0x00000e40, 0xffffffff, 0x28303236, + 1, 1, 0, 0x00000e44, 0xffffffff, 0x42422426, + 1, 1, 1, 0x00000e48, 0xffffffff, 0x30343840, + 1, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628 +}; + +u32 RTL8821AE_PHY_REG_ARRAY_PG[] = { + 0, 0, 0, 0x00000c20, 0xffffffff, 0x32343638, + 0, 0, 0, 0x00000c24, 0xffffffff, 0x36363838, + 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303234, + 0, 0, 0, 0x00000c2c, 0xffffffff, 0x34363838, + 0, 0, 0, 0x00000c30, 0xffffffff, 0x26283032, + 0, 0, 0, 0x00000c3c, 0xffffffff, 0x32343636, + 0, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, + 0, 0, 0, 0x00000c44, 0x0000ffff, 0x00002022, + 1, 0, 0, 0x00000c24, 0xffffffff, 0x34343636, + 1, 0, 0, 0x00000c28, 0xffffffff, 0x26283032, + 1, 0, 0, 0x00000c2c, 0xffffffff, 0x32343636, + 1, 0, 0, 0x00000c30, 0xffffffff, 0x24262830, + 1, 0, 0, 0x00000c3c, 0xffffffff, 0x32343636, + 1, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, + 1, 0, 0, 0x00000c44, 0x0000ffff, 0x00002022 +}; + +u32 RTL8812AE_RADIOA_ARRAY[] = { + 0x000, 0x00010000, + 0x018, 0x0001712A, + 0x056, 0x00051CF2, + 0x066, 0x00040000, + 0x01E, 0x00080000, + 0x089, 0x00000080, + 0xFF0F0740, 0xABCD, + 0x086, 0x00014B38, + 0xFF0F02C0, 0xCDEF, + 0x086, 0x00014B38, + 0xFF0F01C0, 0xCDEF, + 0x086, 0x00014B38, + 0xFF0F07D8, 0xCDEF, + 0x086, 0x00014B3A, + 0xFF0F07D0, 0xCDEF, + 0x086, 0x00014B3A, + 0xCDCDCDCD, 0xCDCD, + 0x086, 0x00014B38, + 0xFF0F0740, 0xDEAD, + 0x0B1, 0x0001FC1A, + 0x0B3, 0x000F0810, + 0x0B4, 0x0001A78D, + 0x0BA, 0x00086180, + 0x018, 0x00000006, + 0x0EF, 0x00002000, + 0xFF0F07D8, 0xABCD, + 0x03B, 0x0003F218, + 0x03B, 0x00030A58, + 0x03B, 0x0002FA58, + 0x03B, 0x00022590, + 0x03B, 0x0001FA50, + 0x03B, 0x00010248, + 0x03B, 0x00008240, + 0xFF0F07D0, 0xCDEF, + 0x03B, 0x0003F218, + 0x03B, 0x00030A58, + 0x03B, 0x0002FA58, + 0x03B, 0x00022590, + 0x03B, 0x0001FA50, + 0x03B, 0x00010248, + 0x03B, 0x00008240, + 0xCDCDCDCD, 0xCDCD, + 0x03B, 0x00038A58, + 0x03B, 0x00037A58, + 0x03B, 0x0002A590, + 0x03B, 0x00027A50, + 0x03B, 0x00018248, + 0x03B, 0x00010240, + 0x03B, 0x00008240, + 0xFF0F07D8, 0xDEAD, + 0x0EF, 0x00000100, + 0xFF0F07D8, 0xABCD, + 0x034, 0x0000A4EE, + 0x034, 0x00009076, + 0x034, 0x00008073, + 0x034, 0x00007070, + 0x034, 0x0000606D, + 0x034, 0x0000506A, + 0x034, 0x00004049, + 0x034, 0x00003046, + 0x034, 0x00002028, + 0x034, 0x00001025, + 0x034, 0x00000022, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0000ADF4, + 0x034, 0x00009DF1, + 0x034, 0x00008DEE, + 0x034, 0x00007DEB, + 0x034, 0x00006DE8, + 0x034, 0x00005CEC, + 0x034, 0x00004CE9, + 0x034, 0x000034EA, + 0x034, 0x000024E7, + 0x034, 0x0000146B, + 0x034, 0x0000006D, + 0xFF0F07D8, 0xDEAD, + 0x0EF, 0x00000000, + 0x0EF, 0x000020A2, + 0x0DF, 0x00000080, + 0x035, 0x00000192, + 0x035, 0x00008192, + 0x035, 0x00010192, + 0x036, 0x00000024, + 0x036, 0x00008024, + 0x036, 0x00010024, + 0x036, 0x00018024, + 0x0EF, 0x00000000, + 0x051, 0x00000C21, + 0x052, 0x000006D9, + 0x053, 0x000FC649, + 0x054, 0x0000017E, + 0x0EF, 0x00000002, + 0x008, 0x00008400, + 0x018, 0x0001712A, + 0x0EF, 0x00001000, + 0x03A, 0x00000080, + 0x03B, 0x0003A02C, + 0x03C, 0x00004000, + 0x03A, 0x00000400, + 0x03B, 0x0003202C, + 0x03C, 0x00010000, + 0x03A, 0x000000A0, + 0x03B, 0x0002B064, + 0x03C, 0x00004000, + 0x03A, 0x000000D8, + 0x03B, 0x00023070, + 0x03C, 0x00004000, + 0x03A, 0x00000468, + 0x03B, 0x0001B870, + 0x03C, 0x00010000, + 0x03A, 0x00000098, + 0x03B, 0x00012085, + 0x03C, 0x000E4000, + 0x03A, 0x00000418, + 0x03B, 0x0000A080, + 0x03C, 0x000F0000, + 0x03A, 0x00000418, + 0x03B, 0x00002080, + 0x03C, 0x00010000, + 0x03A, 0x00000080, + 0x03B, 0x0007A02C, + 0x03C, 0x00004000, + 0x03A, 0x00000400, + 0x03B, 0x0007202C, + 0x03C, 0x00010000, + 0x03A, 0x000000A0, + 0x03B, 0x0006B064, + 0x03C, 0x00004000, + 0x03A, 0x000000D8, + 0x03B, 0x00023070, + 0x03C, 0x00004000, + 0x03A, 0x00000468, + 0x03B, 0x0005B870, + 0x03C, 0x00010000, + 0x03A, 0x00000098, + 0x03B, 0x00052085, + 0x03C, 0x000E4000, + 0x03A, 0x00000418, + 0x03B, 0x0004A080, + 0x03C, 0x000F0000, + 0x03A, 0x00000418, + 0x03B, 0x00042080, + 0x03C, 0x00010000, + 0x03A, 0x00000080, + 0x03B, 0x000BA02C, + 0x03C, 0x00004000, + 0x03A, 0x00000400, + 0x03B, 0x000B202C, + 0x03C, 0x00010000, + 0x03A, 0x000000A0, + 0x03B, 0x000AB064, + 0x03C, 0x00004000, + 0x03A, 0x000000D8, + 0x03B, 0x000A3070, + 0x03C, 0x00004000, + 0x03A, 0x00000468, + 0x03B, 0x0009B870, + 0x03C, 0x00010000, + 0x03A, 0x00000098, + 0x03B, 0x00092085, + 0x03C, 0x000E4000, + 0x03A, 0x00000418, + 0x03B, 0x0008A080, + 0x03C, 0x000F0000, + 0x03A, 0x00000418, + 0x03B, 0x00082080, + 0x03C, 0x00010000, + 0x0EF, 0x00001100, + 0xFF0F0740, 0xABCD, + 0x034, 0x0004A0B2, + 0x034, 0x000490AF, + 0x034, 0x00048070, + 0x034, 0x0004706D, + 0x034, 0x00046050, + 0x034, 0x0004504D, + 0x034, 0x0004404A, + 0x034, 0x00043047, + 0x034, 0x0004200A, + 0x034, 0x00041007, + 0x034, 0x00040004, + 0xFF0F02C0, 0xCDEF, + 0x034, 0x0004A0B2, + 0x034, 0x000490AF, + 0x034, 0x00048070, + 0x034, 0x0004706D, + 0x034, 0x00046050, + 0x034, 0x0004504D, + 0x034, 0x0004404A, + 0x034, 0x00043047, + 0x034, 0x0004200A, + 0x034, 0x00041007, + 0x034, 0x00040004, + 0xFF0F01C0, 0xCDEF, + 0x034, 0x0004A0B2, + 0x034, 0x000490AF, + 0x034, 0x00048070, + 0x034, 0x0004706D, + 0x034, 0x00046050, + 0x034, 0x0004504D, + 0x034, 0x0004404A, + 0x034, 0x00043047, + 0x034, 0x0004200A, + 0x034, 0x00041007, + 0x034, 0x00040004, + 0xFF0F07D8, 0xCDEF, + 0x034, 0x0004A0B2, + 0x034, 0x000490AF, + 0x034, 0x00048070, + 0x034, 0x0004706D, + 0x034, 0x00046050, + 0x034, 0x0004504D, + 0x034, 0x0004404A, + 0x034, 0x00043047, + 0x034, 0x0004200A, + 0x034, 0x00041007, + 0x034, 0x00040004, + 0xFF0F07D0, 0xCDEF, + 0x034, 0x0004A0B2, + 0x034, 0x000490AF, + 0x034, 0x00048070, + 0x034, 0x0004706D, + 0x034, 0x00046050, + 0x034, 0x0004504D, + 0x034, 0x0004404A, + 0x034, 0x00043047, + 0x034, 0x0004200A, + 0x034, 0x00041007, + 0x034, 0x00040004, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0004ADF5, + 0x034, 0x00049DF2, + 0x034, 0x00048DEF, + 0x034, 0x00047DEC, + 0x034, 0x00046DE9, + 0x034, 0x00045DC9, + 0x034, 0x00044CE8, + 0x034, 0x000438CA, + 0x034, 0x00042889, + 0x034, 0x0004184A, + 0x034, 0x0004044A, + 0xFF0F0740, 0xDEAD, + 0xFF0F0740, 0xABCD, + 0x034, 0x0002A0B2, + 0x034, 0x000290AF, + 0x034, 0x00028070, + 0x034, 0x0002706D, + 0x034, 0x00026050, + 0x034, 0x0002504D, + 0x034, 0x0002404A, + 0x034, 0x00023047, + 0x034, 0x0002200A, + 0x034, 0x00021007, + 0x034, 0x00020004, + 0xFF0F02C0, 0xCDEF, + 0x034, 0x0002A0B2, + 0x034, 0x000290AF, + 0x034, 0x00028070, + 0x034, 0x0002706D, + 0x034, 0x00026050, + 0x034, 0x0002504D, + 0x034, 0x0002404A, + 0x034, 0x00023047, + 0x034, 0x0002200A, + 0x034, 0x00021007, + 0x034, 0x00020004, + 0xFF0F01C0, 0xCDEF, + 0x034, 0x0002A0B2, + 0x034, 0x000290AF, + 0x034, 0x00028070, + 0x034, 0x0002706D, + 0x034, 0x00026050, + 0x034, 0x0002504D, + 0x034, 0x0002404A, + 0x034, 0x00023047, + 0x034, 0x0002200A, + 0x034, 0x00021007, + 0x034, 0x00020004, + 0xFF0F07D8, 0xCDEF, + 0x034, 0x0002A0B2, + 0x034, 0x000290AF, + 0x034, 0x00028070, + 0x034, 0x0002706D, + 0x034, 0x00026050, + 0x034, 0x0002504D, + 0x034, 0x0002404A, + 0x034, 0x00023047, + 0x034, 0x0002200A, + 0x034, 0x00021007, + 0x034, 0x00020004, + 0xFF0F07D0, 0xCDEF, + 0x034, 0x0002A0B2, + 0x034, 0x000290AF, + 0x034, 0x00028070, + 0x034, 0x0002706D, + 0x034, 0x00026050, + 0x034, 0x0002504D, + 0x034, 0x0002404A, + 0x034, 0x00023047, + 0x034, 0x0002200A, + 0x034, 0x00021007, + 0x034, 0x00020004, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0002ADF5, + 0x034, 0x00029DF2, + 0x034, 0x00028DEF, + 0x034, 0x00027DEC, + 0x034, 0x00026DE9, + 0x034, 0x00025DC9, + 0x034, 0x00024CE8, + 0x034, 0x000238CA, + 0x034, 0x00022889, + 0x034, 0x0002184A, + 0x034, 0x0002044A, + 0xFF0F0740, 0xDEAD, + 0xFF0F0740, 0xABCD, + 0x034, 0x0000A0B2, + 0x034, 0x000090AF, + 0x034, 0x00008070, + 0x034, 0x0000706D, + 0x034, 0x00006050, + 0x034, 0x0000504D, + 0x034, 0x0000404A, + 0x034, 0x00003047, + 0x034, 0x0000200A, + 0x034, 0x00001007, + 0x034, 0x00000004, + 0xFF0F02C0, 0xCDEF, + 0x034, 0x0000A0B2, + 0x034, 0x000090AF, + 0x034, 0x00008070, + 0x034, 0x0000706D, + 0x034, 0x00006050, + 0x034, 0x0000504D, + 0x034, 0x0000404A, + 0x034, 0x00003047, + 0x034, 0x0000200A, + 0x034, 0x00001007, + 0x034, 0x00000004, + 0xFF0F01C0, 0xCDEF, + 0x034, 0x0000A0B2, + 0x034, 0x000090AF, + 0x034, 0x00008070, + 0x034, 0x0000706D, + 0x034, 0x00006050, + 0x034, 0x0000504D, + 0x034, 0x0000404A, + 0x034, 0x00003047, + 0x034, 0x0000200A, + 0x034, 0x00001007, + 0x034, 0x00000004, + 0xFF0F07D8, 0xCDEF, + 0x034, 0x0000A0B2, + 0x034, 0x000090AF, + 0x034, 0x00008070, + 0x034, 0x0000706D, + 0x034, 0x00006050, + 0x034, 0x0000504D, + 0x034, 0x0000404A, + 0x034, 0x00003047, + 0x034, 0x0000200A, + 0x034, 0x00001007, + 0x034, 0x00000004, + 0xFF0F07D0, 0xCDEF, + 0x034, 0x0000A0B2, + 0x034, 0x000090AF, + 0x034, 0x00008070, + 0x034, 0x0000706D, + 0x034, 0x00006050, + 0x034, 0x0000504D, + 0x034, 0x0000404A, + 0x034, 0x00003047, + 0x034, 0x0000200A, + 0x034, 0x00001007, + 0x034, 0x00000004, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0000AFF7, + 0x034, 0x00009DF7, + 0x034, 0x00008DF4, + 0x034, 0x00007DF1, + 0x034, 0x00006DEE, + 0x034, 0x00005DCD, + 0x034, 0x00004CEB, + 0x034, 0x000038CC, + 0x034, 0x0000288B, + 0x034, 0x0000184C, + 0x034, 0x0000044C, + 0xFF0F0740, 0xDEAD, + 0x0EF, 0x00000000, + 0xFF0F0740, 0xABCD, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0x035, 0x000001D4, + 0x035, 0x000081D4, + 0x035, 0x000101D4, + 0x035, 0x000201B4, + 0x035, 0x000281B4, + 0x035, 0x000301B4, + 0x035, 0x000401B4, + 0x035, 0x000481B4, + 0x035, 0x000501B4, + 0xFF0F02C0, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0x035, 0x000001D4, + 0x035, 0x000081D4, + 0x035, 0x000101D4, + 0x035, 0x000201B4, + 0x035, 0x000281B4, + 0x035, 0x000301B4, + 0x035, 0x000401B4, + 0x035, 0x000481B4, + 0x035, 0x000501B4, + 0xFF0F01C0, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0x035, 0x000001D4, + 0x035, 0x000081D4, + 0x035, 0x000101D4, + 0x035, 0x000201B4, + 0x035, 0x000281B4, + 0x035, 0x000301B4, + 0x035, 0x000401B4, + 0x035, 0x000481B4, + 0x035, 0x000501B4, + 0xFF0F07D8, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0x035, 0x000001D4, + 0x035, 0x000081D4, + 0x035, 0x000101D4, + 0x035, 0x000201B4, + 0x035, 0x000281B4, + 0x035, 0x000301B4, + 0x035, 0x000401B4, + 0x035, 0x000481B4, + 0x035, 0x000501B4, + 0xFF0F07D0, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0x035, 0x000001D4, + 0x035, 0x000081D4, + 0x035, 0x000101D4, + 0x035, 0x000201B4, + 0x035, 0x000281B4, + 0x035, 0x000301B4, + 0x035, 0x000401B4, + 0x035, 0x000481B4, + 0x035, 0x000501B4, + 0xCDCDCDCD, 0xCDCD, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0x035, 0x00000188, + 0x035, 0x00008147, + 0x035, 0x00010147, + 0x035, 0x000201D7, + 0x035, 0x000281D7, + 0x035, 0x000301D7, + 0x035, 0x000401D8, + 0x035, 0x000481D8, + 0x035, 0x000501D8, + 0xFF0F0740, 0xDEAD, + 0x0EF, 0x00000000, + 0xFF0F0740, 0xABCD, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0x036, 0x00004BFB, + 0x036, 0x0000CBFB, + 0x036, 0x00014BFB, + 0x036, 0x0001CBFB, + 0x036, 0x00024F4B, + 0x036, 0x0002CF4B, + 0x036, 0x00034F4B, + 0x036, 0x0003CF4B, + 0x036, 0x00044F4B, + 0x036, 0x0004CF4B, + 0x036, 0x00054F4B, + 0x036, 0x0005CF4B, + 0xFF0F02C0, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0x036, 0x00004BFB, + 0x036, 0x0000CBFB, + 0x036, 0x00014BFB, + 0x036, 0x0001CBFB, + 0x036, 0x00024F4B, + 0x036, 0x0002CF4B, + 0x036, 0x00034F4B, + 0x036, 0x0003CF4B, + 0x036, 0x00044F4B, + 0x036, 0x0004CF4B, + 0x036, 0x00054F4B, + 0x036, 0x0005CF4B, + 0xFF0F01C0, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0x036, 0x00004BFB, + 0x036, 0x0000CBFB, + 0x036, 0x00014BFB, + 0x036, 0x0001CBFB, + 0x036, 0x00024F4B, + 0x036, 0x0002CF4B, + 0x036, 0x00034F4B, + 0x036, 0x0003CF4B, + 0x036, 0x00044F4B, + 0x036, 0x0004CF4B, + 0x036, 0x00054F4B, + 0x036, 0x0005CF4B, + 0xFF0F07D8, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0x036, 0x00004BFB, + 0x036, 0x0000CBFB, + 0x036, 0x00014BFB, + 0x036, 0x0001CBFB, + 0x036, 0x00024F4B, + 0x036, 0x0002CF4B, + 0x036, 0x00034F4B, + 0x036, 0x0003CF4B, + 0x036, 0x00044F4B, + 0x036, 0x0004CF4B, + 0x036, 0x00054F4B, + 0x036, 0x0005CF4B, + 0xFF0F07D0, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0x036, 0x00004BFB, + 0x036, 0x0000CBFB, + 0x036, 0x00014BFB, + 0x036, 0x0001CBFB, + 0x036, 0x00024F4B, + 0x036, 0x0002CF4B, + 0x036, 0x00034F4B, + 0x036, 0x0003CF4B, + 0x036, 0x00044F4B, + 0x036, 0x0004CF4B, + 0x036, 0x00054F4B, + 0x036, 0x0005CF4B, + 0xCDCDCDCD, 0xCDCD, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0x036, 0x00084EB4, + 0x036, 0x0008CC35, + 0x036, 0x00094C35, + 0x036, 0x0009CC35, + 0x036, 0x000A4935, + 0x036, 0x000ACC35, + 0x036, 0x000B4C35, + 0x036, 0x000BCC35, + 0x036, 0x000C4EB4, + 0x036, 0x000CCEB5, + 0x036, 0x000D4EB5, + 0x036, 0x000DCEB5, + 0xFF0F0740, 0xDEAD, + 0x0EF, 0x00000000, + 0x0EF, 0x00000008, + 0xFF0F0740, 0xABCD, + 0x03C, 0x000002CC, + 0x03C, 0x00000522, + 0x03C, 0x00000902, + 0xFF0F02C0, 0xCDEF, + 0x03C, 0x000002CC, + 0x03C, 0x00000522, + 0x03C, 0x00000902, + 0xFF0F01C0, 0xCDEF, + 0x03C, 0x000002CC, + 0x03C, 0x00000522, + 0x03C, 0x00000902, + 0xFF0F07D8, 0xCDEF, + 0x03C, 0x000002CC, + 0x03C, 0x00000522, + 0x03C, 0x00000902, + 0xFF0F07D0, 0xCDEF, + 0x03C, 0x000002CC, + 0x03C, 0x00000522, + 0x03C, 0x00000902, + 0xCDCDCDCD, 0xCDCD, + 0x03C, 0x000002A8, + 0x03C, 0x000005A2, + 0x03C, 0x00000880, + 0xFF0F0740, 0xDEAD, + 0x0EF, 0x00000000, + 0x018, 0x0001712A, + 0x0EF, 0x00000002, + 0x0DF, 0x00000080, + 0x01F, 0x00040064, + 0xFF0F0740, 0xABCD, + 0x061, 0x000FDD43, + 0x062, 0x00038F4B, + 0x063, 0x00032117, + 0x064, 0x000194AC, + 0x065, 0x000931D1, + 0xFF0F02C0, 0xCDEF, + 0x061, 0x000FDD43, + 0x062, 0x00038F4B, + 0x063, 0x00032117, + 0x064, 0x000194AC, + 0x065, 0x000931D1, + 0xFF0F01C0, 0xCDEF, + 0x061, 0x000FDD43, + 0x062, 0x00038F4B, + 0x063, 0x00032117, + 0x064, 0x000194AC, + 0x065, 0x000931D1, + 0xFF0F07D8, 0xCDEF, + 0x061, 0x000FDD43, + 0x062, 0x00038F4B, + 0x063, 0x00032117, + 0x064, 0x000194AC, + 0x065, 0x000931D1, + 0xFF0F07D0, 0xCDEF, + 0x061, 0x000FDD43, + 0x062, 0x00038F4B, + 0x063, 0x00032117, + 0x064, 0x000194AC, + 0x065, 0x000931D1, + 0xCDCDCDCD, 0xCDCD, + 0x061, 0x000E5D53, + 0x062, 0x00038FCD, + 0x063, 0x000314EB, + 0x064, 0x000196AC, + 0x065, 0x000911D7, + 0xFF0F0740, 0xDEAD, + 0x008, 0x00008400, + 0x01C, 0x000739D2, + 0x0B4, 0x0001E78D, + 0x018, 0x0001F12A, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x0B4, 0x0001A78D, + 0x018, 0x0001712A, + +}; + +u32 RTL8812AE_RADIOB_ARRAY[] = { + 0x056, 0x00051CF2, + 0x066, 0x00040000, + 0x089, 0x00000080, + 0xFF0F0740, 0xABCD, + 0x086, 0x00014B38, + 0xFF0F01C0, 0xCDEF, + 0x086, 0x00014B38, + 0xFF0F02C0, 0xCDEF, + 0x086, 0x00014B38, + 0xFF0F07D8, 0xCDEF, + 0x086, 0x00014B3A, + 0xFF0F07D0, 0xCDEF, + 0x086, 0x00014B3A, + 0xCDCDCDCD, 0xCDCD, + 0x086, 0x00014B38, + 0xFF0F0740, 0xDEAD, + 0x018, 0x00000006, + 0x0EF, 0x00002000, + 0xFF0F07D8, 0xABCD, + 0x03B, 0x0003F218, + 0x03B, 0x00030A58, + 0x03B, 0x0002FA58, + 0x03B, 0x00022590, + 0x03B, 0x0001FA50, + 0x03B, 0x00010248, + 0x03B, 0x00008240, + 0xFF0F07D0, 0xCDEF, + 0x03B, 0x0003F218, + 0x03B, 0x00030A58, + 0x03B, 0x0002FA58, + 0x03B, 0x00022590, + 0x03B, 0x0001FA50, + 0x03B, 0x00010248, + 0x03B, 0x00008240, + 0xCDCDCDCD, 0xCDCD, + 0x03B, 0x00038A58, + 0x03B, 0x00037A58, + 0x03B, 0x0002A590, + 0x03B, 0x00027A50, + 0x03B, 0x00018248, + 0x03B, 0x00010240, + 0x03B, 0x00008240, + 0xFF0F07D8, 0xDEAD, + 0x0EF, 0x00000100, + 0xFF0F07D8, 0xABCD, + 0x034, 0x0000A4EE, + 0x034, 0x00009076, + 0x034, 0x00008073, + 0x034, 0x00007070, + 0x034, 0x0000606D, + 0x034, 0x0000506A, + 0x034, 0x00004049, + 0x034, 0x00003046, + 0x034, 0x00002028, + 0x034, 0x00001025, + 0x034, 0x00000022, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0000ADF4, + 0x034, 0x00009DF1, + 0x034, 0x00008DEE, + 0x034, 0x00007DEB, + 0x034, 0x00006DE8, + 0x034, 0x00005CEC, + 0x034, 0x00004CE9, + 0x034, 0x000034EA, + 0x034, 0x000024E7, + 0x034, 0x0000146B, + 0x034, 0x0000006D, + 0xFF0F07D8, 0xDEAD, + 0x0EF, 0x00000000, + 0x0EF, 0x000020A2, + 0x0DF, 0x00000080, + 0x035, 0x00000192, + 0x035, 0x00008192, + 0x035, 0x00010192, + 0x036, 0x00000024, + 0x036, 0x00008024, + 0x036, 0x00010024, + 0x036, 0x00018024, + 0x0EF, 0x00000000, + 0x051, 0x00000C21, + 0x052, 0x000006D9, + 0x053, 0x000FC649, + 0x054, 0x0000017E, + 0x0EF, 0x00000002, + 0x008, 0x00008400, + 0x018, 0x0001712A, + 0x0EF, 0x00001000, + 0x03A, 0x00000080, + 0x03B, 0x0003A02C, + 0x03C, 0x00004000, + 0x03A, 0x00000400, + 0x03B, 0x0003202C, + 0x03C, 0x00010000, + 0x03A, 0x000000A0, + 0x03B, 0x0002B064, + 0x03C, 0x00004000, + 0x03A, 0x000000D8, + 0x03B, 0x00023070, + 0x03C, 0x00004000, + 0x03A, 0x00000468, + 0x03B, 0x0001B870, + 0x03C, 0x00010000, + 0x03A, 0x00000098, + 0x03B, 0x00012085, + 0x03C, 0x000E4000, + 0x03A, 0x00000418, + 0x03B, 0x0000A080, + 0x03C, 0x000F0000, + 0x03A, 0x00000418, + 0x03B, 0x00002080, + 0x03C, 0x00010000, + 0x03A, 0x00000080, + 0x03B, 0x0007A02C, + 0x03C, 0x00004000, + 0x03A, 0x00000400, + 0x03B, 0x0007202C, + 0x03C, 0x00010000, + 0x03A, 0x000000A0, + 0x03B, 0x0006B064, + 0x03C, 0x00004000, + 0x03A, 0x000000D8, + 0x03B, 0x00063070, + 0x03C, 0x00004000, + 0x03A, 0x00000468, + 0x03B, 0x0005B870, + 0x03C, 0x00010000, + 0x03A, 0x00000098, + 0x03B, 0x00052085, + 0x03C, 0x000E4000, + 0x03A, 0x00000418, + 0x03B, 0x0004A080, + 0x03C, 0x000F0000, + 0x03A, 0x00000418, + 0x03B, 0x00042080, + 0x03C, 0x00010000, + 0x03A, 0x00000080, + 0x03B, 0x000BA02C, + 0x03C, 0x00004000, + 0x03A, 0x00000400, + 0x03B, 0x000B202C, + 0x03C, 0x00010000, + 0x03A, 0x000000A0, + 0x03B, 0x000AB064, + 0x03C, 0x00004000, + 0x03A, 0x000000D8, + 0x03B, 0x000A3070, + 0x03C, 0x00004000, + 0x03A, 0x00000468, + 0x03B, 0x0009B870, + 0x03C, 0x00010000, + 0x03A, 0x00000098, + 0x03B, 0x00092085, + 0x03C, 0x000E4000, + 0x03A, 0x00000418, + 0x03B, 0x0008A080, + 0x03C, 0x000F0000, + 0x03A, 0x00000418, + 0x03B, 0x00082080, + 0x03C, 0x00010000, + 0x0EF, 0x00001100, + 0xFF0F0740, 0xABCD, + 0x034, 0x0004A0B2, + 0x034, 0x000490AF, + 0x034, 0x00048070, + 0x034, 0x0004706D, + 0x034, 0x00046050, + 0x034, 0x0004504D, + 0x034, 0x0004404A, + 0x034, 0x00043047, + 0x034, 0x0004200A, + 0x034, 0x00041007, + 0x034, 0x00040004, + 0xFF0F01C0, 0xCDEF, + 0x034, 0x0004A0B2, + 0x034, 0x000490AF, + 0x034, 0x00048070, + 0x034, 0x0004706D, + 0x034, 0x00046050, + 0x034, 0x0004504D, + 0x034, 0x0004404A, + 0x034, 0x00043047, + 0x034, 0x0004200A, + 0x034, 0x00041007, + 0x034, 0x00040004, + 0xFF0F02C0, 0xCDEF, + 0x034, 0x0004A0B2, + 0x034, 0x000490AF, + 0x034, 0x00048070, + 0x034, 0x0004706D, + 0x034, 0x00046050, + 0x034, 0x0004504D, + 0x034, 0x0004404A, + 0x034, 0x00043047, + 0x034, 0x0004200A, + 0x034, 0x00041007, + 0x034, 0x00040004, + 0xFF0F07D8, 0xCDEF, + 0x034, 0x0004A0B2, + 0x034, 0x000490AF, + 0x034, 0x00048070, + 0x034, 0x0004706D, + 0x034, 0x00046050, + 0x034, 0x0004504D, + 0x034, 0x0004404A, + 0x034, 0x00043047, + 0x034, 0x0004200A, + 0x034, 0x00041007, + 0x034, 0x00040004, + 0xFF0F07D0, 0xCDEF, + 0x034, 0x0004A0B2, + 0x034, 0x000490AF, + 0x034, 0x00048070, + 0x034, 0x0004706D, + 0x034, 0x00046050, + 0x034, 0x0004504D, + 0x034, 0x0004404A, + 0x034, 0x00043047, + 0x034, 0x0004200A, + 0x034, 0x00041007, + 0x034, 0x00040004, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0004ADF5, + 0x034, 0x00049DF2, + 0x034, 0x00048DEF, + 0x034, 0x00047DEC, + 0x034, 0x00046DE9, + 0x034, 0x00045DC9, + 0x034, 0x00044CE8, + 0x034, 0x000438CA, + 0x034, 0x00042889, + 0x034, 0x0004184A, + 0x034, 0x0004044A, + 0xFF0F0740, 0xDEAD, + 0xFF0F0740, 0xABCD, + 0x034, 0x0002A0B2, + 0x034, 0x000290AF, + 0x034, 0x00028070, + 0x034, 0x0002706D, + 0x034, 0x00026050, + 0x034, 0x0002504D, + 0x034, 0x0002404A, + 0x034, 0x00023047, + 0x034, 0x0002200A, + 0x034, 0x00021007, + 0x034, 0x00020004, + 0xFF0F01C0, 0xCDEF, + 0x034, 0x0002A0B2, + 0x034, 0x000290AF, + 0x034, 0x00028070, + 0x034, 0x0002706D, + 0x034, 0x00026050, + 0x034, 0x0002504D, + 0x034, 0x0002404A, + 0x034, 0x00023047, + 0x034, 0x0002200A, + 0x034, 0x00021007, + 0x034, 0x00020004, + 0xFF0F02C0, 0xCDEF, + 0x034, 0x0002A0B2, + 0x034, 0x000290AF, + 0x034, 0x00028070, + 0x034, 0x0002706D, + 0x034, 0x00026050, + 0x034, 0x0002504D, + 0x034, 0x0002404A, + 0x034, 0x00023047, + 0x034, 0x0002200A, + 0x034, 0x00021007, + 0x034, 0x00020004, + 0xFF0F07D8, 0xCDEF, + 0x034, 0x0002A0B2, + 0x034, 0x000290AF, + 0x034, 0x00028070, + 0x034, 0x0002706D, + 0x034, 0x00026050, + 0x034, 0x0002504D, + 0x034, 0x0002404A, + 0x034, 0x00023047, + 0x034, 0x0002200A, + 0x034, 0x00021007, + 0x034, 0x00020004, + 0xFF0F07D0, 0xCDEF, + 0x034, 0x0002A0B2, + 0x034, 0x000290AF, + 0x034, 0x00028070, + 0x034, 0x0002706D, + 0x034, 0x00026050, + 0x034, 0x0002504D, + 0x034, 0x0002404A, + 0x034, 0x00023047, + 0x034, 0x0002200A, + 0x034, 0x00021007, + 0x034, 0x00020004, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0002ADF5, + 0x034, 0x00029DF2, + 0x034, 0x00028DEF, + 0x034, 0x00027DEC, + 0x034, 0x00026DE9, + 0x034, 0x00025DC9, + 0x034, 0x00024CE8, + 0x034, 0x000238CA, + 0x034, 0x00022889, + 0x034, 0x0002184A, + 0x034, 0x0002044A, + 0xFF0F0740, 0xDEAD, + 0xFF0F0740, 0xABCD, + 0x034, 0x0000A0B2, + 0x034, 0x000090AF, + 0x034, 0x00008070, + 0x034, 0x0000706D, + 0x034, 0x00006050, + 0x034, 0x0000504D, + 0x034, 0x0000404A, + 0x034, 0x00003047, + 0x034, 0x0000200A, + 0x034, 0x00001007, + 0x034, 0x00000004, + 0xFF0F01C0, 0xCDEF, + 0x034, 0x0000A0B2, + 0x034, 0x000090AF, + 0x034, 0x00008070, + 0x034, 0x0000706D, + 0x034, 0x00006050, + 0x034, 0x0000504D, + 0x034, 0x0000404A, + 0x034, 0x00003047, + 0x034, 0x0000200A, + 0x034, 0x00001007, + 0x034, 0x00000004, + 0xFF0F02C0, 0xCDEF, + 0x034, 0x0000A0B2, + 0x034, 0x000090AF, + 0x034, 0x00008070, + 0x034, 0x0000706D, + 0x034, 0x00006050, + 0x034, 0x0000504D, + 0x034, 0x0000404A, + 0x034, 0x00003047, + 0x034, 0x0000200A, + 0x034, 0x00001007, + 0x034, 0x00000004, + 0xFF0F07D8, 0xCDEF, + 0x034, 0x0000A0B2, + 0x034, 0x000090AF, + 0x034, 0x00008070, + 0x034, 0x0000706D, + 0x034, 0x00006050, + 0x034, 0x0000504D, + 0x034, 0x0000404A, + 0x034, 0x00003047, + 0x034, 0x0000200A, + 0x034, 0x00001007, + 0x034, 0x00000004, + 0xFF0F07D0, 0xCDEF, + 0x034, 0x0000A0B2, + 0x034, 0x000090AF, + 0x034, 0x00008070, + 0x034, 0x0000706D, + 0x034, 0x00006050, + 0x034, 0x0000504D, + 0x034, 0x0000404A, + 0x034, 0x00003047, + 0x034, 0x0000200A, + 0x034, 0x00001007, + 0x034, 0x00000004, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0000AFF7, + 0x034, 0x00009DF7, + 0x034, 0x00008DF4, + 0x034, 0x00007DF1, + 0x034, 0x00006DEE, + 0x034, 0x00005DCD, + 0x034, 0x00004CEB, + 0x034, 0x000038CC, + 0x034, 0x0000288B, + 0x034, 0x0000184C, + 0x034, 0x0000044C, + 0xFF0F0740, 0xDEAD, + 0x0EF, 0x00000000, + 0xFF0F0740, 0xABCD, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0x035, 0x000001C5, + 0x035, 0x000081C5, + 0x035, 0x000101C5, + 0x035, 0x00020174, + 0x035, 0x00028174, + 0x035, 0x00030174, + 0x035, 0x00040185, + 0x035, 0x00048185, + 0x035, 0x00050185, + 0x0EF, 0x00000000, + 0xFF0F01C0, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0x035, 0x000001C5, + 0x035, 0x000081C5, + 0x035, 0x000101C5, + 0x035, 0x00020174, + 0x035, 0x00028174, + 0x035, 0x00030174, + 0x035, 0x00040185, + 0x035, 0x00048185, + 0x035, 0x00050185, + 0x0EF, 0x00000000, + 0xFF0F02C0, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0x035, 0x000001C5, + 0x035, 0x000081C5, + 0x035, 0x000101C5, + 0x035, 0x00020174, + 0x035, 0x00028174, + 0x035, 0x00030174, + 0x035, 0x00040185, + 0x035, 0x00048185, + 0x035, 0x00050185, + 0x0EF, 0x00000000, + 0xFF0F07D8, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0x035, 0x000001C5, + 0x035, 0x000081C5, + 0x035, 0x000101C5, + 0x035, 0x00020174, + 0x035, 0x00028174, + 0x035, 0x00030174, + 0x035, 0x00040185, + 0x035, 0x00048185, + 0x035, 0x00050185, + 0x0EF, 0x00000000, + 0xFF0F07D0, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0x035, 0x000001C5, + 0x035, 0x000081C5, + 0x035, 0x000101C5, + 0x035, 0x00020174, + 0x035, 0x00028174, + 0x035, 0x00030174, + 0x035, 0x00040185, + 0x035, 0x00048185, + 0x035, 0x00050185, + 0x0EF, 0x00000000, + 0xCDCDCDCD, 0xCDCD, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0x035, 0x00000186, + 0x035, 0x00008186, + 0x035, 0x00010185, + 0x035, 0x000201D5, + 0x035, 0x000281D5, + 0x035, 0x000301D5, + 0x035, 0x000401D5, + 0x035, 0x000481D5, + 0x035, 0x000501D5, + 0x0EF, 0x00000000, + 0xFF0F0740, 0xDEAD, + 0xFF0F0740, 0xABCD, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0x036, 0x00005B8B, + 0x036, 0x0000DB8B, + 0x036, 0x00015B8B, + 0x036, 0x0001DB8B, + 0x036, 0x000262DB, + 0x036, 0x0002E2DB, + 0x036, 0x000362DB, + 0x036, 0x0003E2DB, + 0x036, 0x0004553B, + 0x036, 0x0004D53B, + 0x036, 0x0005553B, + 0x036, 0x0005D53B, + 0xFF0F01C0, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0x036, 0x00005B8B, + 0x036, 0x0000DB8B, + 0x036, 0x00015B8B, + 0x036, 0x0001DB8B, + 0x036, 0x000262DB, + 0x036, 0x0002E2DB, + 0x036, 0x000362DB, + 0x036, 0x0003E2DB, + 0x036, 0x0004553B, + 0x036, 0x0004D53B, + 0x036, 0x0005553B, + 0x036, 0x0005D53B, + 0xFF0F02C0, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0x036, 0x00005B8B, + 0x036, 0x0000DB8B, + 0x036, 0x00015B8B, + 0x036, 0x0001DB8B, + 0x036, 0x000262DB, + 0x036, 0x0002E2DB, + 0x036, 0x000362DB, + 0x036, 0x0003E2DB, + 0x036, 0x0004553B, + 0x036, 0x0004D53B, + 0x036, 0x0005553B, + 0x036, 0x0005D53B, + 0xFF0F07D8, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0x036, 0x00005B8B, + 0x036, 0x0000DB8B, + 0x036, 0x00015B8B, + 0x036, 0x0001DB8B, + 0x036, 0x000262DB, + 0x036, 0x0002E2DB, + 0x036, 0x000362DB, + 0x036, 0x0003E2DB, + 0x036, 0x0004553B, + 0x036, 0x0004D53B, + 0x036, 0x0005553B, + 0x036, 0x0005D53B, + 0xFF0F07D0, 0xCDEF, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0x036, 0x00005B8B, + 0x036, 0x0000DB8B, + 0x036, 0x00015B8B, + 0x036, 0x0001DB8B, + 0x036, 0x000262DB, + 0x036, 0x0002E2DB, + 0x036, 0x000362DB, + 0x036, 0x0003E2DB, + 0x036, 0x0004553B, + 0x036, 0x0004D53B, + 0x036, 0x0005553B, + 0x036, 0x0005D53B, + 0xCDCDCDCD, 0xCDCD, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0x036, 0x00084EB4, + 0x036, 0x0008C9B4, + 0x036, 0x000949B4, + 0x036, 0x0009C9B4, + 0x036, 0x000A4935, + 0x036, 0x000AC935, + 0x036, 0x000B4935, + 0x036, 0x000BC935, + 0x036, 0x000C4EB4, + 0x036, 0x000CCEB4, + 0x036, 0x000D4EB4, + 0x036, 0x000DCEB4, + 0xFF0F0740, 0xDEAD, + 0x0EF, 0x00000000, + 0x0EF, 0x00000008, + 0xFF0F0740, 0xABCD, + 0x03C, 0x000002DC, + 0x03C, 0x00000524, + 0x03C, 0x00000902, + 0xFF0F01C0, 0xCDEF, + 0x03C, 0x000002DC, + 0x03C, 0x00000524, + 0x03C, 0x00000902, + 0xFF0F02C0, 0xCDEF, + 0x03C, 0x000002DC, + 0x03C, 0x00000524, + 0x03C, 0x00000902, + 0xFF0F07D8, 0xCDEF, + 0x03C, 0x000002DC, + 0x03C, 0x00000524, + 0x03C, 0x00000902, + 0xFF0F07D0, 0xCDEF, + 0x03C, 0x000002DC, + 0x03C, 0x00000524, + 0x03C, 0x00000902, + 0xCDCDCDCD, 0xCDCD, + 0x03C, 0x000002AA, + 0x03C, 0x000005A2, + 0x03C, 0x00000880, + 0xFF0F0740, 0xDEAD, + 0x0EF, 0x00000000, + 0x018, 0x0001712A, + 0x0EF, 0x00000002, + 0x0DF, 0x00000080, + 0xFF0F0740, 0xABCD, + 0x061, 0x000EAC43, + 0x062, 0x00038F47, + 0x063, 0x00031157, + 0x064, 0x0001C4AC, + 0x065, 0x000931D1, + 0xFF0F01C0, 0xCDEF, + 0x061, 0x000EAC43, + 0x062, 0x00038F47, + 0x063, 0x00031157, + 0x064, 0x0001C4AC, + 0x065, 0x000931D1, + 0xFF0F02C0, 0xCDEF, + 0x061, 0x000EAC43, + 0x062, 0x00038F47, + 0x063, 0x00031157, + 0x064, 0x0001C4AC, + 0x065, 0x000931D1, + 0xFF0F07D8, 0xCDEF, + 0x061, 0x000EAC43, + 0x062, 0x00038F47, + 0x063, 0x00031157, + 0x064, 0x0001C4AC, + 0x065, 0x000931D1, + 0xFF0F07D0, 0xCDEF, + 0x061, 0x000EAC43, + 0x062, 0x00038F47, + 0x063, 0x00031157, + 0x064, 0x0001C4AC, + 0x065, 0x000931D1, + 0xCDCDCDCD, 0xCDCD, + 0x061, 0x000E5D53, + 0x062, 0x00038FCD, + 0x063, 0x000314EB, + 0x064, 0x000196AC, + 0x065, 0x000931D7, + 0xFF0F0740, 0xDEAD, + 0x008, 0x00008400, + +}; + +u32 RTL8821AE_RADIOA_ARRAY[] = { + 0x018, 0x0001712A, + 0x056, 0x00051CF2, + 0x066, 0x00040000, + 0x000, 0x00010000, + 0x01E, 0x00080000, + 0x082, 0x00000830, + 0x083, 0x00021800, + 0x084, 0x00028000, + 0x085, 0x00048000, + 0x086, 0x00094838, + 0x087, 0x00044980, + 0x088, 0x00048000, + 0x089, 0x0000D480, + 0x08A, 0x00042240, + 0x08B, 0x000F0380, + 0x08C, 0x00090000, + 0x08D, 0x00022852, + 0x08E, 0x00065540, + 0x08F, 0x00088001, + 0x0EF, 0x00020000, + 0x03E, 0x00000380, + 0x03F, 0x00090018, + 0x03E, 0x00020380, + 0x03F, 0x000A0018, + 0x03E, 0x00040308, + 0x03F, 0x000A0018, + 0x03E, 0x00060018, + 0x03F, 0x000A0018, + 0x0EF, 0x00000000, + 0x018, 0x0001712A, + 0x089, 0x00000080, + 0x08B, 0x00080180, + 0x0EF, 0x00001000, + 0x03A, 0x00000244, + 0x03B, 0x00038027, + 0x03C, 0x00082000, + 0x03A, 0x00000244, + 0x03B, 0x00030113, + 0x03C, 0x00082000, + 0x03A, 0x0000014C, + 0x03B, 0x00028027, + 0x03C, 0x00082000, + 0x03A, 0x000000CC, + 0x03B, 0x00027027, + 0x03C, 0x00042000, + 0x03A, 0x0000014C, + 0x03B, 0x0001F913, + 0x03C, 0x00042000, + 0x03A, 0x0000010C, + 0x03B, 0x00017F10, + 0x03C, 0x00012000, + 0x03A, 0x000000D0, + 0x03B, 0x00008027, + 0x03C, 0x000CA000, + 0x03A, 0x00000244, + 0x03B, 0x00078027, + 0x03C, 0x00082000, + 0x03A, 0x00000244, + 0x03B, 0x00070113, + 0x03C, 0x00082000, + 0x03A, 0x0000014C, + 0x03B, 0x00068027, + 0x03C, 0x00082000, + 0x03A, 0x000000CC, + 0x03B, 0x00067027, + 0x03C, 0x00042000, + 0x03A, 0x0000014C, + 0x03B, 0x0005F913, + 0x03C, 0x00042000, + 0x03A, 0x0000010C, + 0x03B, 0x00057F10, + 0x03C, 0x00012000, + 0x03A, 0x000000D0, + 0x03B, 0x00048027, + 0x03C, 0x000CA000, + 0x03A, 0x00000244, + 0x03B, 0x000B8027, + 0x03C, 0x00082000, + 0x03A, 0x00000244, + 0x03B, 0x000B0113, + 0x03C, 0x00082000, + 0x03A, 0x0000014C, + 0x03B, 0x000A8027, + 0x03C, 0x00082000, + 0x03A, 0x000000CC, + 0x03B, 0x000A7027, + 0x03C, 0x00042000, + 0x03A, 0x0000014C, + 0x03B, 0x0009F913, + 0x03C, 0x00042000, + 0x03A, 0x0000010C, + 0x03B, 0x00097F10, + 0x03C, 0x00012000, + 0x03A, 0x000000D0, + 0x03B, 0x00088027, + 0x03C, 0x000CA000, + 0x0EF, 0x00000000, + 0x0EF, 0x00001100, + 0xFF0F0104, 0xABCD, + 0x034, 0x0004ADF3, + 0x034, 0x00049DF0, + 0xFF0F0204, 0xCDEF, + 0x034, 0x0004ADF3, + 0x034, 0x00049DF0, + 0xFF0F0404, 0xCDEF, + 0x034, 0x0004ADF3, + 0x034, 0x00049DF0, + 0xFF0F0200, 0xCDEF, + 0x034, 0x0004ADF5, + 0x034, 0x00049DF2, + 0xFF0F02C0, 0xCDEF, + 0x034, 0x0004A0F3, + 0x034, 0x000490B1, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0004ADF7, + 0x034, 0x00049DF3, + 0xFF0F0104, 0xDEAD, + 0xFF0F0104, 0xABCD, + 0x034, 0x00048DED, + 0x034, 0x00047DEA, + 0x034, 0x00046DE7, + 0x034, 0x00045CE9, + 0x034, 0x00044CE6, + 0x034, 0x000438C6, + 0x034, 0x00042886, + 0x034, 0x00041486, + 0x034, 0x00040447, + 0xFF0F0204, 0xCDEF, + 0x034, 0x00048DED, + 0x034, 0x00047DEA, + 0x034, 0x00046DE7, + 0x034, 0x00045CE9, + 0x034, 0x00044CE6, + 0x034, 0x000438C6, + 0x034, 0x00042886, + 0x034, 0x00041486, + 0x034, 0x00040447, + 0xFF0F0404, 0xCDEF, + 0x034, 0x00048DED, + 0x034, 0x00047DEA, + 0x034, 0x00046DE7, + 0x034, 0x00045CE9, + 0x034, 0x00044CE6, + 0x034, 0x000438C6, + 0x034, 0x00042886, + 0x034, 0x00041486, + 0x034, 0x00040447, + 0xFF0F02C0, 0xCDEF, + 0x034, 0x000480AE, + 0x034, 0x000470AB, + 0x034, 0x0004608B, + 0x034, 0x00045069, + 0x034, 0x00044048, + 0x034, 0x00043045, + 0x034, 0x00042026, + 0x034, 0x00041023, + 0x034, 0x00040002, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x00048DEF, + 0x034, 0x00047DEC, + 0x034, 0x00046DE9, + 0x034, 0x00045CCB, + 0x034, 0x0004488D, + 0x034, 0x0004348D, + 0x034, 0x0004248A, + 0x034, 0x0004108D, + 0x034, 0x0004008A, + 0xFF0F0104, 0xDEAD, + 0xFF0F0200, 0xABCD, + 0x034, 0x0002ADF4, + 0xFF0F02C0, 0xCDEF, + 0x034, 0x0002A0F3, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0002ADF7, + 0xFF0F0200, 0xDEAD, + 0xFF0F0104, 0xABCD, + 0x034, 0x00029DF4, + 0xFF0F0204, 0xCDEF, + 0x034, 0x00029DF4, + 0xFF0F0404, 0xCDEF, + 0x034, 0x00029DF4, + 0xFF0F0200, 0xCDEF, + 0x034, 0x00029DF1, + 0xFF0F02C0, 0xCDEF, + 0x034, 0x000290F0, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x00029DF2, + 0xFF0F0104, 0xDEAD, + 0xFF0F0104, 0xABCD, + 0x034, 0x00028DF1, + 0x034, 0x00027DEE, + 0x034, 0x00026DEB, + 0x034, 0x00025CEC, + 0x034, 0x00024CE9, + 0x034, 0x000238CA, + 0x034, 0x00022889, + 0x034, 0x00021489, + 0x034, 0x0002044A, + 0xFF0F0204, 0xCDEF, + 0x034, 0x00028DF1, + 0x034, 0x00027DEE, + 0x034, 0x00026DEB, + 0x034, 0x00025CEC, + 0x034, 0x00024CE9, + 0x034, 0x000238CA, + 0x034, 0x00022889, + 0x034, 0x00021489, + 0x034, 0x0002044A, + 0xFF0F0404, 0xCDEF, + 0x034, 0x00028DF1, + 0x034, 0x00027DEE, + 0x034, 0x00026DEB, + 0x034, 0x00025CEC, + 0x034, 0x00024CE9, + 0x034, 0x000238CA, + 0x034, 0x00022889, + 0x034, 0x00021489, + 0x034, 0x0002044A, + 0xFF0F02C0, 0xCDEF, + 0x034, 0x000280AF, + 0x034, 0x000270AC, + 0x034, 0x0002608B, + 0x034, 0x00025069, + 0x034, 0x00024048, + 0x034, 0x00023045, + 0x034, 0x00022026, + 0x034, 0x00021023, + 0x034, 0x00020002, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x00028DEE, + 0x034, 0x00027DEB, + 0x034, 0x00026CCD, + 0x034, 0x00025CCA, + 0x034, 0x0002488C, + 0x034, 0x0002384C, + 0x034, 0x00022849, + 0x034, 0x00021449, + 0x034, 0x0002004D, + 0xFF0F0104, 0xDEAD, + 0xFF0F02C0, 0xABCD, + 0x034, 0x0000A0D7, + 0x034, 0x000090D3, + 0x034, 0x000080B1, + 0x034, 0x000070AE, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x0000ADF7, + 0x034, 0x00009DF4, + 0x034, 0x00008DF1, + 0x034, 0x00007DEE, + 0xFF0F02C0, 0xDEAD, + 0xFF0F0104, 0xABCD, + 0x034, 0x00006DEB, + 0x034, 0x00005CEC, + 0x034, 0x00004CE9, + 0x034, 0x000038CA, + 0x034, 0x00002889, + 0x034, 0x00001489, + 0x034, 0x0000044A, + 0xFF0F0204, 0xCDEF, + 0x034, 0x00006DEB, + 0x034, 0x00005CEC, + 0x034, 0x00004CE9, + 0x034, 0x000038CA, + 0x034, 0x00002889, + 0x034, 0x00001489, + 0x034, 0x0000044A, + 0xFF0F0404, 0xCDEF, + 0x034, 0x00006DEB, + 0x034, 0x00005CEC, + 0x034, 0x00004CE9, + 0x034, 0x000038CA, + 0x034, 0x00002889, + 0x034, 0x00001489, + 0x034, 0x0000044A, + 0xFF0F02C0, 0xCDEF, + 0x034, 0x0000608D, + 0x034, 0x0000506B, + 0x034, 0x0000404A, + 0x034, 0x00003047, + 0x034, 0x00002044, + 0x034, 0x00001025, + 0x034, 0x00000004, + 0xCDCDCDCD, 0xCDCD, + 0x034, 0x00006DCD, + 0x034, 0x00005CCD, + 0x034, 0x00004CCA, + 0x034, 0x0000388C, + 0x034, 0x00002888, + 0x034, 0x00001488, + 0x034, 0x00000486, + 0xFF0F0104, 0xDEAD, + 0x0EF, 0x00000000, + 0x018, 0x0001712A, + 0x0EF, 0x00000040, + 0xFF0F0104, 0xABCD, + 0x035, 0x00000187, + 0x035, 0x00008187, + 0x035, 0x00010187, + 0x035, 0x00020188, + 0x035, 0x00028188, + 0x035, 0x00030188, + 0x035, 0x00040188, + 0x035, 0x00048188, + 0x035, 0x00050188, + 0xFF0F0204, 0xCDEF, + 0x035, 0x00000187, + 0x035, 0x00008187, + 0x035, 0x00010187, + 0x035, 0x00020188, + 0x035, 0x00028188, + 0x035, 0x00030188, + 0x035, 0x00040188, + 0x035, 0x00048188, + 0x035, 0x00050188, + 0xFF0F0404, 0xCDEF, + 0x035, 0x00000187, + 0x035, 0x00008187, + 0x035, 0x00010187, + 0x035, 0x00020188, + 0x035, 0x00028188, + 0x035, 0x00030188, + 0x035, 0x00040188, + 0x035, 0x00048188, + 0x035, 0x00050188, + 0xCDCDCDCD, 0xCDCD, + 0x035, 0x00000145, + 0x035, 0x00008145, + 0x035, 0x00010145, + 0x035, 0x00020196, + 0x035, 0x00028196, + 0x035, 0x00030196, + 0x035, 0x000401C7, + 0x035, 0x000481C7, + 0x035, 0x000501C7, + 0xFF0F0104, 0xDEAD, + 0x0EF, 0x00000000, + 0x018, 0x0001712A, + 0x0EF, 0x00000010, + 0xFF0F0104, 0xABCD, + 0x036, 0x00085733, + 0x036, 0x0008D733, + 0x036, 0x00095733, + 0x036, 0x0009D733, + 0x036, 0x000A64B4, + 0x036, 0x000AE4B4, + 0x036, 0x000B64B4, + 0x036, 0x000BE4B4, + 0x036, 0x000C64B4, + 0x036, 0x000CE4B4, + 0x036, 0x000D64B4, + 0x036, 0x000DE4B4, + 0xFF0F0204, 0xCDEF, + 0x036, 0x00085733, + 0x036, 0x0008D733, + 0x036, 0x00095733, + 0x036, 0x0009D733, + 0x036, 0x000A64B4, + 0x036, 0x000AE4B4, + 0x036, 0x000B64B4, + 0x036, 0x000BE4B4, + 0x036, 0x000C64B4, + 0x036, 0x000CE4B4, + 0x036, 0x000D64B4, + 0x036, 0x000DE4B4, + 0xFF0F0404, 0xCDEF, + 0x036, 0x00085733, + 0x036, 0x0008D733, + 0x036, 0x00095733, + 0x036, 0x0009D733, + 0x036, 0x000A64B4, + 0x036, 0x000AE4B4, + 0x036, 0x000B64B4, + 0x036, 0x000BE4B4, + 0x036, 0x000C64B4, + 0x036, 0x000CE4B4, + 0x036, 0x000D64B4, + 0x036, 0x000DE4B4, + 0xCDCDCDCD, 0xCDCD, + 0x036, 0x000056B3, + 0x036, 0x0000D6B3, + 0x036, 0x000156B3, + 0x036, 0x0001D6B3, + 0x036, 0x00026634, + 0x036, 0x0002E634, + 0x036, 0x00036634, + 0x036, 0x0003E634, + 0x036, 0x000467B4, + 0x036, 0x0004E7B4, + 0x036, 0x000567B4, + 0x036, 0x0005E7B4, + 0xFF0F0104, 0xDEAD, + 0x0EF, 0x00000000, + 0x0EF, 0x00000008, + 0xFF0F0104, 0xABCD, + 0x03C, 0x000001C8, + 0x03C, 0x00000492, + 0xFF0F0204, 0xCDEF, + 0x03C, 0x000001C8, + 0x03C, 0x00000492, + 0xFF0F0404, 0xCDEF, + 0x03C, 0x000001C8, + 0x03C, 0x00000492, + 0xCDCDCDCD, 0xCDCD, + 0x03C, 0x0000022A, + 0x03C, 0x00000594, + 0xFF0F0104, 0xDEAD, + 0xFF0F0104, 0xABCD, + 0x03C, 0x00000800, + 0xFF0F0204, 0xCDEF, + 0x03C, 0x00000800, + 0xFF0F0404, 0xCDEF, + 0x03C, 0x00000800, + 0xFF0F02C0, 0xCDEF, + 0x03C, 0x00000820, + 0xCDCDCDCD, 0xCDCD, + 0x03C, 0x00000900, + 0xFF0F0104, 0xDEAD, + 0x0EF, 0x00000000, + 0x018, 0x0001712A, + 0x0EF, 0x00000002, + 0xFF0F0104, 0xABCD, + 0x008, 0x0004E400, + 0xFF0F0204, 0xCDEF, + 0x008, 0x0004E400, + 0xFF0F0404, 0xCDEF, + 0x008, 0x0004E400, + 0xCDCDCDCD, 0xCDCD, + 0x008, 0x00002000, + 0xFF0F0104, 0xDEAD, + 0x0EF, 0x00000000, + 0x0DF, 0x000000C0, + 0x01F, 0x00040064, + 0xFF0F0104, 0xABCD, + 0x058, 0x000A7284, + 0x059, 0x000600EC, + 0xFF0F0204, 0xCDEF, + 0x058, 0x000A7284, + 0x059, 0x000600EC, + 0xFF0F0404, 0xCDEF, + 0x058, 0x000A7284, + 0x059, 0x000600EC, + 0xCDCDCDCD, 0xCDCD, + 0x058, 0x00081184, + 0x059, 0x0006016C, + 0xFF0F0104, 0xDEAD, + 0xFF0F0104, 0xABCD, + 0x061, 0x000E8D73, + 0x062, 0x00093FC5, + 0xFF0F0204, 0xCDEF, + 0x061, 0x000E8D73, + 0x062, 0x00093FC5, + 0xFF0F0404, 0xCDEF, + 0x061, 0x000E8D73, + 0x062, 0x00093FC5, + 0xCDCDCDCD, 0xCDCD, + 0x061, 0x000EAD53, + 0x062, 0x00093BC4, + 0xFF0F0104, 0xDEAD, + 0xFF0F0104, 0xABCD, + 0x063, 0x000110E9, + 0xFF0F0204, 0xCDEF, + 0x063, 0x000110E9, + 0xFF0F0404, 0xCDEF, + 0x063, 0x000110E9, + 0xFF0F0200, 0xCDEF, + 0x063, 0x000710E9, + 0xFF0F02C0, 0xCDEF, + 0x063, 0x000110E9, + 0xCDCDCDCD, 0xCDCD, + 0x063, 0x000714E9, + 0xFF0F0104, 0xDEAD, + 0xFF0F0104, 0xABCD, + 0x064, 0x0001C27C, + 0xFF0F0204, 0xCDEF, + 0x064, 0x0001C27C, + 0xFF0F0404, 0xCDEF, + 0x064, 0x0001C27C, + 0xCDCDCDCD, 0xCDCD, + 0x064, 0x0001C67C, + 0xFF0F0104, 0xDEAD, + 0xFF0F0200, 0xABCD, + 0x065, 0x00093016, + 0xFF0F02C0, 0xCDEF, + 0x065, 0x00093015, + 0xCDCDCDCD, 0xCDCD, + 0x065, 0x00091016, + 0xFF0F0200, 0xDEAD, + 0x018, 0x00000006, + 0x0EF, 0x00002000, + 0x03B, 0x0003824B, + 0x03B, 0x0003024B, + 0x03B, 0x0002844B, + 0x03B, 0x00020F4B, + 0x03B, 0x00018F4B, + 0x03B, 0x000104B2, + 0x03B, 0x00008049, + 0x03B, 0x00000148, + 0x03B, 0x0007824B, + 0x03B, 0x0007024B, + 0x03B, 0x0006824B, + 0x03B, 0x00060F4B, + 0x03B, 0x00058F4B, + 0x03B, 0x000504B2, + 0x03B, 0x00048049, + 0x03B, 0x00040148, + 0x0EF, 0x00000000, + 0x0EF, 0x00000100, + 0x034, 0x0000ADF3, + 0x034, 0x00009DEF, + 0x034, 0x00008DEC, + 0x034, 0x00007DE9, + 0x034, 0x00006CED, + 0x034, 0x00005CE9, + 0x034, 0x000044E9, + 0x034, 0x000034E6, + 0x034, 0x0000246A, + 0x034, 0x00001467, + 0x034, 0x00000068, + 0x0EF, 0x00000000, + 0x0ED, 0x00000010, + 0x044, 0x0000ADF2, + 0x044, 0x00009DEF, + 0x044, 0x00008DEC, + 0x044, 0x00007DE9, + 0x044, 0x00006CEC, + 0x044, 0x00005CE9, + 0x044, 0x000044EC, + 0x044, 0x000034E9, + 0x044, 0x0000246C, + 0x044, 0x00001469, + 0x044, 0x0000006C, + 0x0ED, 0x00000000, + 0x0ED, 0x00000001, + 0x040, 0x00038DA7, + 0x040, 0x000300C2, + 0x040, 0x000288E2, + 0x040, 0x000200B8, + 0x040, 0x000188A5, + 0x040, 0x00010FBC, + 0x040, 0x00008F71, + 0x040, 0x00000240, + 0x0ED, 0x00000000, + 0x0EF, 0x000020A2, + 0x0DF, 0x00000080, + 0x035, 0x00000120, + 0x035, 0x00008120, + 0x035, 0x00010120, + 0x036, 0x00000085, + 0x036, 0x00008085, + 0x036, 0x00010085, + 0x036, 0x00018085, + 0x0EF, 0x00000000, + 0x051, 0x00000C31, + 0x052, 0x00000622, + 0x053, 0x000FC70B, + 0x054, 0x0000017E, + 0x056, 0x00051DF3, + 0x051, 0x00000C01, + 0x052, 0x000006D6, + 0x053, 0x000FC649, + 0x070, 0x00049661, + 0x071, 0x0007843E, + 0x072, 0x00000382, + 0x074, 0x00051400, + 0x035, 0x00000160, + 0x035, 0x00008160, + 0x035, 0x00010160, + 0x036, 0x00000124, + 0x036, 0x00008124, + 0x036, 0x00010124, + 0x036, 0x00018124, + 0x0ED, 0x0000000C, + 0x045, 0x00000140, + 0x045, 0x00008140, + 0x045, 0x00010140, + 0x046, 0x00000124, + 0x046, 0x00008124, + 0x046, 0x00010124, + 0x046, 0x00018124, + 0x0DF, 0x00000088, + 0x0B3, 0x000F0E18, + 0x0B4, 0x0001214C, + 0x0B7, 0x0003000C, + 0x01C, 0x000539D2, + 0x018, 0x0001F12A, + 0x0FE, 0x00000000, + 0x0FE, 0x00000000, + 0x018, 0x0001712A, +}; + +u32 RTL8812AE_MAC_REG_ARRAY[] = { + 0x010, 0x0000000C, + 0xFF0F0180, 0xABCD, + 0x025, 0x0000000F, + 0xFF0F01C0, 0xCDEF, + 0x025, 0x0000000F, + 0xCDCDCDCD, 0xCDCD, + 0x025, 0x0000006F, + 0xFF0F0180, 0xDEAD, + 0x072, 0x00000000, + 0x428, 0x0000000A, + 0x429, 0x00000010, + 0x430, 0x00000000, + 0x431, 0x00000000, + 0x432, 0x00000000, + 0x433, 0x00000001, + 0x434, 0x00000004, + 0x435, 0x00000005, + 0x436, 0x00000007, + 0x437, 0x00000008, + 0x43C, 0x00000004, + 0x43D, 0x00000005, + 0x43E, 0x00000007, + 0x43F, 0x00000008, + 0x440, 0x0000005D, + 0x441, 0x00000001, + 0x442, 0x00000000, + 0x444, 0x00000010, + 0x445, 0x00000000, + 0x446, 0x00000000, + 0x447, 0x00000000, + 0x448, 0x00000000, + 0x449, 0x000000F0, + 0x44A, 0x0000000F, + 0x44B, 0x0000003E, + 0x44C, 0x00000010, + 0x44D, 0x00000000, + 0x44E, 0x00000000, + 0x44F, 0x00000000, + 0x450, 0x00000000, + 0x451, 0x000000F0, + 0x452, 0x0000000F, + 0x453, 0x00000000, + 0x45B, 0x00000080, + 0x460, 0x00000066, + 0x461, 0x00000066, + 0x4C8, 0x000000FF, + 0x4C9, 0x00000008, + 0x4CC, 0x000000FF, + 0x4CD, 0x000000FF, + 0x4CE, 0x00000001, + 0x500, 0x00000026, + 0x501, 0x000000A2, + 0x502, 0x0000002F, + 0x503, 0x00000000, + 0x504, 0x00000028, + 0x505, 0x000000A3, + 0x506, 0x0000005E, + 0x507, 0x00000000, + 0x508, 0x0000002B, + 0x509, 0x000000A4, + 0x50A, 0x0000005E, + 0x50B, 0x00000000, + 0x50C, 0x0000004F, + 0x50D, 0x000000A4, + 0x50E, 0x00000000, + 0x50F, 0x00000000, + 0x512, 0x0000001C, + 0x514, 0x0000000A, + 0x516, 0x0000000A, + 0x525, 0x0000004F, + 0x550, 0x00000010, + 0x551, 0x00000010, + 0x559, 0x00000002, + 0x55C, 0x00000050, + 0x55D, 0x000000FF, + 0x604, 0x00000001, + 0x605, 0x00000030, + 0x607, 0x00000003, + 0x608, 0x0000000E, + 0x609, 0x0000002A, + 0x620, 0x000000FF, + 0x621, 0x000000FF, + 0x622, 0x000000FF, + 0x623, 0x000000FF, + 0x624, 0x000000FF, + 0x625, 0x000000FF, + 0x626, 0x000000FF, + 0x627, 0x000000FF, + 0x638, 0x00000050, + 0x63C, 0x0000000A, + 0x63D, 0x0000000A, + 0x63E, 0x0000000E, + 0x63F, 0x0000000E, + 0x640, 0x00000080, + 0x642, 0x00000040, + 0x643, 0x00000000, + 0x652, 0x000000C8, + 0x66E, 0x00000005, + 0x700, 0x00000021, + 0x701, 0x00000043, + 0x702, 0x00000065, + 0x703, 0x00000087, + 0x708, 0x00000021, + 0x709, 0x00000043, + 0x70A, 0x00000065, + 0x70B, 0x00000087, + 0x718, 0x00000040, + +}; + +u32 RTL8821AE_MAC_REG_ARRAY[] = { + 0x428, 0x0000000A, + 0x429, 0x00000010, + 0x430, 0x00000000, + 0x431, 0x00000000, + 0x432, 0x00000000, + 0x433, 0x00000001, + 0x434, 0x00000004, + 0x435, 0x00000005, + 0x436, 0x00000007, + 0x437, 0x00000008, + 0x43C, 0x00000004, + 0x43D, 0x00000005, + 0x43E, 0x00000007, + 0x43F, 0x00000008, + 0x440, 0x0000005D, + 0x441, 0x00000001, + 0x442, 0x00000000, + 0x444, 0x00000010, + 0x445, 0x00000000, + 0x446, 0x00000000, + 0x447, 0x00000000, + 0x448, 0x00000000, + 0x449, 0x000000F0, + 0x44A, 0x0000000F, + 0x44B, 0x0000003E, + 0x44C, 0x00000010, + 0x44D, 0x00000000, + 0x44E, 0x00000000, + 0x44F, 0x00000000, + 0x450, 0x00000000, + 0x451, 0x000000F0, + 0x452, 0x0000000F, + 0x453, 0x00000000, + 0x456, 0x0000005E, + 0x460, 0x00000066, + 0x461, 0x00000066, + 0x4C8, 0x0000003F, + 0x4C9, 0x000000FF, + 0x4CC, 0x000000FF, + 0x4CD, 0x000000FF, + 0x4CE, 0x00000001, + 0x500, 0x00000026, + 0x501, 0x000000A2, + 0x502, 0x0000002F, + 0x503, 0x00000000, + 0x504, 0x00000028, + 0x505, 0x000000A3, + 0x506, 0x0000005E, + 0x507, 0x00000000, + 0x508, 0x0000002B, + 0x509, 0x000000A4, + 0x50A, 0x0000005E, + 0x50B, 0x00000000, + 0x50C, 0x0000004F, + 0x50D, 0x000000A4, + 0x50E, 0x00000000, + 0x50F, 0x00000000, + 0x512, 0x0000001C, + 0x514, 0x0000000A, + 0x516, 0x0000000A, + 0x525, 0x0000004F, + 0x550, 0x00000010, + 0x551, 0x00000010, + 0x559, 0x00000002, + 0x55C, 0x00000050, + 0x55D, 0x000000FF, + 0x605, 0x00000030, + 0x607, 0x00000007, + 0x608, 0x0000000E, + 0x609, 0x0000002A, + 0x620, 0x000000FF, + 0x621, 0x000000FF, + 0x622, 0x000000FF, + 0x623, 0x000000FF, + 0x624, 0x000000FF, + 0x625, 0x000000FF, + 0x626, 0x000000FF, + 0x627, 0x000000FF, + 0x638, 0x00000050, + 0x63C, 0x0000000A, + 0x63D, 0x0000000A, + 0x63E, 0x0000000E, + 0x63F, 0x0000000E, + 0x640, 0x00000040, + 0x642, 0x00000040, + 0x643, 0x00000000, + 0x652, 0x000000C8, + 0x66E, 0x00000005, + 0x700, 0x00000021, + 0x701, 0x00000043, + 0x702, 0x00000065, + 0x703, 0x00000087, + 0x708, 0x00000021, + 0x709, 0x00000043, + 0x70A, 0x00000065, + 0x70B, 0x00000087, + 0x718, 0x00000040, +}; + +u32 RTL8812AE_AGC_TAB_ARRAY[] = { + 0xFF0F07D8, 0xABCD, + 0x81C, 0xFC000001, + 0x81C, 0xFB020001, + 0x81C, 0xFA040001, + 0x81C, 0xF9060001, + 0x81C, 0xF8080001, + 0x81C, 0xF70A0001, + 0x81C, 0xF60C0001, + 0x81C, 0xF50E0001, + 0x81C, 0xF4100001, + 0x81C, 0xF3120001, + 0x81C, 0xF2140001, + 0x81C, 0xF1160001, + 0x81C, 0xF0180001, + 0x81C, 0xEF1A0001, + 0x81C, 0xEE1C0001, + 0x81C, 0xED1E0001, + 0x81C, 0xEC200001, + 0x81C, 0xEB220001, + 0x81C, 0xEA240001, + 0x81C, 0xCD260001, + 0x81C, 0xCC280001, + 0x81C, 0xCB2A0001, + 0x81C, 0xCA2C0001, + 0x81C, 0xC92E0001, + 0x81C, 0xC8300001, + 0x81C, 0xA6320001, + 0x81C, 0xA5340001, + 0x81C, 0xA4360001, + 0x81C, 0xA3380001, + 0x81C, 0xA23A0001, + 0x81C, 0x883C0001, + 0x81C, 0x873E0001, + 0x81C, 0x86400001, + 0x81C, 0x85420001, + 0x81C, 0x84440001, + 0x81C, 0x83460001, + 0x81C, 0x82480001, + 0x81C, 0x814A0001, + 0x81C, 0x484C0001, + 0x81C, 0x474E0001, + 0x81C, 0x46500001, + 0x81C, 0x45520001, + 0x81C, 0x44540001, + 0x81C, 0x43560001, + 0x81C, 0x42580001, + 0x81C, 0x415A0001, + 0x81C, 0x255C0001, + 0x81C, 0x245E0001, + 0x81C, 0x23600001, + 0x81C, 0x22620001, + 0x81C, 0x21640001, + 0x81C, 0x21660001, + 0x81C, 0x21680001, + 0x81C, 0x216A0001, + 0x81C, 0x216C0001, + 0x81C, 0x216E0001, + 0x81C, 0x21700001, + 0x81C, 0x21720001, + 0x81C, 0x21740001, + 0x81C, 0x21760001, + 0x81C, 0x21780001, + 0x81C, 0x217A0001, + 0x81C, 0x217C0001, + 0x81C, 0x217E0001, + 0xFF0F07D0, 0xCDEF, + 0x81C, 0xF9000001, + 0x81C, 0xF8020001, + 0x81C, 0xF7040001, + 0x81C, 0xF6060001, + 0x81C, 0xF5080001, + 0x81C, 0xF40A0001, + 0x81C, 0xF30C0001, + 0x81C, 0xF20E0001, + 0x81C, 0xF1100001, + 0x81C, 0xF0120001, + 0x81C, 0xEF140001, + 0x81C, 0xEE160001, + 0x81C, 0xED180001, + 0x81C, 0xEC1A0001, + 0x81C, 0xEB1C0001, + 0x81C, 0xEA1E0001, + 0x81C, 0xCD200001, + 0x81C, 0xCC220001, + 0x81C, 0xCB240001, + 0x81C, 0xCA260001, + 0x81C, 0xC9280001, + 0x81C, 0xC82A0001, + 0x81C, 0xC72C0001, + 0x81C, 0xC62E0001, + 0x81C, 0xA5300001, + 0x81C, 0xA4320001, + 0x81C, 0xA3340001, + 0x81C, 0xA2360001, + 0x81C, 0x88380001, + 0x81C, 0x873A0001, + 0x81C, 0x863C0001, + 0x81C, 0x853E0001, + 0x81C, 0x84400001, + 0x81C, 0x83420001, + 0x81C, 0x82440001, + 0x81C, 0x81460001, + 0x81C, 0x48480001, + 0x81C, 0x474A0001, + 0x81C, 0x464C0001, + 0x81C, 0x454E0001, + 0x81C, 0x44500001, + 0x81C, 0x43520001, + 0x81C, 0x42540001, + 0x81C, 0x41560001, + 0x81C, 0x25580001, + 0x81C, 0x245A0001, + 0x81C, 0x235C0001, + 0x81C, 0x225E0001, + 0x81C, 0x21600001, + 0x81C, 0x21620001, + 0x81C, 0x21640001, + 0x81C, 0x21660001, + 0x81C, 0x21680001, + 0x81C, 0x216A0001, + 0x81C, 0x236C0001, + 0x81C, 0x226E0001, + 0x81C, 0x21700001, + 0x81C, 0x21720001, + 0x81C, 0x21740001, + 0x81C, 0x21760001, + 0x81C, 0x21780001, + 0x81C, 0x217A0001, + 0x81C, 0x217C0001, + 0x81C, 0x217E0001, + 0xCDCDCDCD, 0xCDCD, + 0x81C, 0xFF000001, + 0x81C, 0xFF020001, + 0x81C, 0xFF040001, + 0x81C, 0xFF060001, + 0x81C, 0xFF080001, + 0x81C, 0xFE0A0001, + 0x81C, 0xFD0C0001, + 0x81C, 0xFC0E0001, + 0x81C, 0xFB100001, + 0x81C, 0xFA120001, + 0x81C, 0xF9140001, + 0x81C, 0xF8160001, + 0x81C, 0xF7180001, + 0x81C, 0xF61A0001, + 0x81C, 0xF51C0001, + 0x81C, 0xF41E0001, + 0x81C, 0xF3200001, + 0x81C, 0xF2220001, + 0x81C, 0xF1240001, + 0x81C, 0xF0260001, + 0x81C, 0xEF280001, + 0x81C, 0xEE2A0001, + 0x81C, 0xED2C0001, + 0x81C, 0xEC2E0001, + 0x81C, 0xEB300001, + 0x81C, 0xEA320001, + 0x81C, 0xE9340001, + 0x81C, 0xE8360001, + 0x81C, 0xE7380001, + 0x81C, 0xE63A0001, + 0x81C, 0xE53C0001, + 0x81C, 0xC73E0001, + 0x81C, 0xC6400001, + 0x81C, 0xC5420001, + 0x81C, 0xC4440001, + 0x81C, 0xC3460001, + 0x81C, 0xC2480001, + 0x81C, 0xC14A0001, + 0x81C, 0xA74C0001, + 0x81C, 0xA64E0001, + 0x81C, 0xA5500001, + 0x81C, 0xA4520001, + 0x81C, 0xA3540001, + 0x81C, 0xA2560001, + 0x81C, 0xA1580001, + 0x81C, 0x675A0001, + 0x81C, 0x665C0001, + 0x81C, 0x655E0001, + 0x81C, 0x64600001, + 0x81C, 0x63620001, + 0x81C, 0x48640001, + 0x81C, 0x47660001, + 0x81C, 0x46680001, + 0x81C, 0x456A0001, + 0x81C, 0x446C0001, + 0x81C, 0x436E0001, + 0x81C, 0x42700001, + 0x81C, 0x41720001, + 0x81C, 0x41740001, + 0x81C, 0x41760001, + 0x81C, 0x41780001, + 0x81C, 0x417A0001, + 0x81C, 0x417C0001, + 0x81C, 0x417E0001, + 0xFF0F07D8, 0xDEAD, + 0xFF0F0180, 0xABCD, + 0x81C, 0xFC800001, + 0x81C, 0xFB820001, + 0x81C, 0xFA840001, + 0x81C, 0xF9860001, + 0x81C, 0xF8880001, + 0x81C, 0xF78A0001, + 0x81C, 0xF68C0001, + 0x81C, 0xF58E0001, + 0x81C, 0xF4900001, + 0x81C, 0xF3920001, + 0x81C, 0xF2940001, + 0x81C, 0xF1960001, + 0x81C, 0xF0980001, + 0x81C, 0xEF9A0001, + 0x81C, 0xEE9C0001, + 0x81C, 0xED9E0001, + 0x81C, 0xECA00001, + 0x81C, 0xEBA20001, + 0x81C, 0xEAA40001, + 0x81C, 0xE9A60001, + 0x81C, 0xE8A80001, + 0x81C, 0xE7AA0001, + 0x81C, 0xE6AC0001, + 0x81C, 0xE5AE0001, + 0x81C, 0xE4B00001, + 0x81C, 0xE3B20001, + 0x81C, 0xA8B40001, + 0x81C, 0xA7B60001, + 0x81C, 0xA6B80001, + 0x81C, 0xA5BA0001, + 0x81C, 0xA4BC0001, + 0x81C, 0xA3BE0001, + 0x81C, 0xA2C00001, + 0x81C, 0xA1C20001, + 0x81C, 0x68C40001, + 0x81C, 0x67C60001, + 0x81C, 0x66C80001, + 0x81C, 0x65CA0001, + 0x81C, 0x64CC0001, + 0x81C, 0x47CE0001, + 0x81C, 0x46D00001, + 0x81C, 0x45D20001, + 0x81C, 0x44D40001, + 0x81C, 0x43D60001, + 0x81C, 0x42D80001, + 0x81C, 0x08DA0001, + 0x81C, 0x07DC0001, + 0x81C, 0x06DE0001, + 0x81C, 0x05E00001, + 0x81C, 0x04E20001, + 0x81C, 0x03E40001, + 0x81C, 0x02E60001, + 0x81C, 0x01E80001, + 0x81C, 0x01EA0001, + 0x81C, 0x01EC0001, + 0x81C, 0x01EE0001, + 0x81C, 0x01F00001, + 0x81C, 0x01F20001, + 0x81C, 0x01F40001, + 0x81C, 0x01F60001, + 0x81C, 0x01F80001, + 0x81C, 0x01FA0001, + 0x81C, 0x01FC0001, + 0x81C, 0x01FE0001, + 0xFF0F0280, 0xCDEF, + 0x81C, 0xFC800001, + 0x81C, 0xFB820001, + 0x81C, 0xFA840001, + 0x81C, 0xF9860001, + 0x81C, 0xF8880001, + 0x81C, 0xF78A0001, + 0x81C, 0xF68C0001, + 0x81C, 0xF58E0001, + 0x81C, 0xF4900001, + 0x81C, 0xF3920001, + 0x81C, 0xF2940001, + 0x81C, 0xF1960001, + 0x81C, 0xF0980001, + 0x81C, 0xEF9A0001, + 0x81C, 0xEE9C0001, + 0x81C, 0xED9E0001, + 0x81C, 0xECA00001, + 0x81C, 0xEBA20001, + 0x81C, 0xEAA40001, + 0x81C, 0xE9A60001, + 0x81C, 0xE8A80001, + 0x81C, 0xE7AA0001, + 0x81C, 0xE6AC0001, + 0x81C, 0xE5AE0001, + 0x81C, 0xE4B00001, + 0x81C, 0xE3B20001, + 0x81C, 0xA8B40001, + 0x81C, 0xA7B60001, + 0x81C, 0xA6B80001, + 0x81C, 0xA5BA0001, + 0x81C, 0xA4BC0001, + 0x81C, 0xA3BE0001, + 0x81C, 0xA2C00001, + 0x81C, 0xA1C20001, + 0x81C, 0x68C40001, + 0x81C, 0x67C60001, + 0x81C, 0x66C80001, + 0x81C, 0x65CA0001, + 0x81C, 0x64CC0001, + 0x81C, 0x47CE0001, + 0x81C, 0x46D00001, + 0x81C, 0x45D20001, + 0x81C, 0x44D40001, + 0x81C, 0x43D60001, + 0x81C, 0x42D80001, + 0x81C, 0x08DA0001, + 0x81C, 0x07DC0001, + 0x81C, 0x06DE0001, + 0x81C, 0x05E00001, + 0x81C, 0x04E20001, + 0x81C, 0x03E40001, + 0x81C, 0x02E60001, + 0x81C, 0x01E80001, + 0x81C, 0x01EA0001, + 0x81C, 0x01EC0001, + 0x81C, 0x01EE0001, + 0x81C, 0x01F00001, + 0x81C, 0x01F20001, + 0x81C, 0x01F40001, + 0x81C, 0x01F60001, + 0x81C, 0x01F80001, + 0x81C, 0x01FA0001, + 0x81C, 0x01FC0001, + 0x81C, 0x01FE0001, + 0xFF0F01C0, 0xCDEF, + 0x81C, 0xFC800001, + 0x81C, 0xFB820001, + 0x81C, 0xFA840001, + 0x81C, 0xF9860001, + 0x81C, 0xF8880001, + 0x81C, 0xF78A0001, + 0x81C, 0xF68C0001, + 0x81C, 0xF58E0001, + 0x81C, 0xF4900001, + 0x81C, 0xF3920001, + 0x81C, 0xF2940001, + 0x81C, 0xF1960001, + 0x81C, 0xF0980001, + 0x81C, 0xEF9A0001, + 0x81C, 0xEE9C0001, + 0x81C, 0xED9E0001, + 0x81C, 0xECA00001, + 0x81C, 0xEBA20001, + 0x81C, 0xEAA40001, + 0x81C, 0xE9A60001, + 0x81C, 0xE8A80001, + 0x81C, 0xE7AA0001, + 0x81C, 0xE6AC0001, + 0x81C, 0xE5AE0001, + 0x81C, 0xE4B00001, + 0x81C, 0xE3B20001, + 0x81C, 0xA8B40001, + 0x81C, 0xA7B60001, + 0x81C, 0xA6B80001, + 0x81C, 0xA5BA0001, + 0x81C, 0xA4BC0001, + 0x81C, 0xA3BE0001, + 0x81C, 0xA2C00001, + 0x81C, 0xA1C20001, + 0x81C, 0x68C40001, + 0x81C, 0x67C60001, + 0x81C, 0x66C80001, + 0x81C, 0x65CA0001, + 0x81C, 0x64CC0001, + 0x81C, 0x47CE0001, + 0x81C, 0x46D00001, + 0x81C, 0x45D20001, + 0x81C, 0x44D40001, + 0x81C, 0x43D60001, + 0x81C, 0x42D80001, + 0x81C, 0x08DA0001, + 0x81C, 0x07DC0001, + 0x81C, 0x06DE0001, + 0x81C, 0x05E00001, + 0x81C, 0x04E20001, + 0x81C, 0x03E40001, + 0x81C, 0x02E60001, + 0x81C, 0x01E80001, + 0x81C, 0x01EA0001, + 0x81C, 0x01EC0001, + 0x81C, 0x01EE0001, + 0x81C, 0x01F00001, + 0x81C, 0x01F20001, + 0x81C, 0x01F40001, + 0x81C, 0x01F60001, + 0x81C, 0x01F80001, + 0x81C, 0x01FA0001, + 0x81C, 0x01FC0001, + 0x81C, 0x01FE0001, + 0xFF0F02C0, 0xCDEF, + 0x81C, 0xFC800001, + 0x81C, 0xFB820001, + 0x81C, 0xFA840001, + 0x81C, 0xF9860001, + 0x81C, 0xF8880001, + 0x81C, 0xF78A0001, + 0x81C, 0xF68C0001, + 0x81C, 0xF58E0001, + 0x81C, 0xF4900001, + 0x81C, 0xF3920001, + 0x81C, 0xF2940001, + 0x81C, 0xF1960001, + 0x81C, 0xF0980001, + 0x81C, 0xEF9A0001, + 0x81C, 0xEE9C0001, + 0x81C, 0xED9E0001, + 0x81C, 0xECA00001, + 0x81C, 0xEBA20001, + 0x81C, 0xEAA40001, + 0x81C, 0xE9A60001, + 0x81C, 0xE8A80001, + 0x81C, 0xE7AA0001, + 0x81C, 0xE6AC0001, + 0x81C, 0xE5AE0001, + 0x81C, 0xE4B00001, + 0x81C, 0xE3B20001, + 0x81C, 0xA8B40001, + 0x81C, 0xA7B60001, + 0x81C, 0xA6B80001, + 0x81C, 0xA5BA0001, + 0x81C, 0xA4BC0001, + 0x81C, 0xA3BE0001, + 0x81C, 0xA2C00001, + 0x81C, 0xA1C20001, + 0x81C, 0x68C40001, + 0x81C, 0x67C60001, + 0x81C, 0x66C80001, + 0x81C, 0x65CA0001, + 0x81C, 0x64CC0001, + 0x81C, 0x47CE0001, + 0x81C, 0x46D00001, + 0x81C, 0x45D20001, + 0x81C, 0x44D40001, + 0x81C, 0x43D60001, + 0x81C, 0x42D80001, + 0x81C, 0x08DA0001, + 0x81C, 0x07DC0001, + 0x81C, 0x06DE0001, + 0x81C, 0x05E00001, + 0x81C, 0x04E20001, + 0x81C, 0x03E40001, + 0x81C, 0x02E60001, + 0x81C, 0x01E80001, + 0x81C, 0x01EA0001, + 0x81C, 0x01EC0001, + 0x81C, 0x01EE0001, + 0x81C, 0x01F00001, + 0x81C, 0x01F20001, + 0x81C, 0x01F40001, + 0x81C, 0x01F60001, + 0x81C, 0x01F80001, + 0x81C, 0x01FA0001, + 0x81C, 0x01FC0001, + 0x81C, 0x01FE0001, + 0xFF0F07D8, 0xCDEF, + 0x81C, 0xFC800001, + 0x81C, 0xFB820001, + 0x81C, 0xFA840001, + 0x81C, 0xF9860001, + 0x81C, 0xF8880001, + 0x81C, 0xF78A0001, + 0x81C, 0xF68C0001, + 0x81C, 0xF58E0001, + 0x81C, 0xF4900001, + 0x81C, 0xF3920001, + 0x81C, 0xF2940001, + 0x81C, 0xF1960001, + 0x81C, 0xF0980001, + 0x81C, 0xEF9A0001, + 0x81C, 0xEE9C0001, + 0x81C, 0xED9E0001, + 0x81C, 0xECA00001, + 0x81C, 0xEBA20001, + 0x81C, 0xEAA40001, + 0x81C, 0xE9A60001, + 0x81C, 0xE8A80001, + 0x81C, 0xE7AA0001, + 0x81C, 0xE6AC0001, + 0x81C, 0xE5AE0001, + 0x81C, 0xE4B00001, + 0x81C, 0xE3B20001, + 0x81C, 0xA8B40001, + 0x81C, 0xA7B60001, + 0x81C, 0xA6B80001, + 0x81C, 0xA5BA0001, + 0x81C, 0xA4BC0001, + 0x81C, 0xA3BE0001, + 0x81C, 0xA2C00001, + 0x81C, 0xA1C20001, + 0x81C, 0x68C40001, + 0x81C, 0x67C60001, + 0x81C, 0x66C80001, + 0x81C, 0x65CA0001, + 0x81C, 0x64CC0001, + 0x81C, 0x47CE0001, + 0x81C, 0x46D00001, + 0x81C, 0x45D20001, + 0x81C, 0x44D40001, + 0x81C, 0x43D60001, + 0x81C, 0x42D80001, + 0x81C, 0x08DA0001, + 0x81C, 0x07DC0001, + 0x81C, 0x06DE0001, + 0x81C, 0x05E00001, + 0x81C, 0x04E20001, + 0x81C, 0x03E40001, + 0x81C, 0x02E60001, + 0x81C, 0x01E80001, + 0x81C, 0x01EA0001, + 0x81C, 0x01EC0001, + 0x81C, 0x01EE0001, + 0x81C, 0x01F00001, + 0x81C, 0x01F20001, + 0x81C, 0x01F40001, + 0x81C, 0x01F60001, + 0x81C, 0x01F80001, + 0x81C, 0x01FA0001, + 0x81C, 0x01FC0001, + 0x81C, 0x01FE0001, + 0xFF0F07D0, 0xCDEF, + 0x81C, 0xFC800001, + 0x81C, 0xFB820001, + 0x81C, 0xFA840001, + 0x81C, 0xF9860001, + 0x81C, 0xF8880001, + 0x81C, 0xF78A0001, + 0x81C, 0xF68C0001, + 0x81C, 0xF58E0001, + 0x81C, 0xF4900001, + 0x81C, 0xF3920001, + 0x81C, 0xF2940001, + 0x81C, 0xF1960001, + 0x81C, 0xF0980001, + 0x81C, 0xEF9A0001, + 0x81C, 0xEE9C0001, + 0x81C, 0xED9E0001, + 0x81C, 0xECA00001, + 0x81C, 0xEBA20001, + 0x81C, 0xEAA40001, + 0x81C, 0xE9A60001, + 0x81C, 0xE8A80001, + 0x81C, 0xE7AA0001, + 0x81C, 0xE6AC0001, + 0x81C, 0xE5AE0001, + 0x81C, 0xE4B00001, + 0x81C, 0xE3B20001, + 0x81C, 0xA8B40001, + 0x81C, 0xA7B60001, + 0x81C, 0xA6B80001, + 0x81C, 0xA5BA0001, + 0x81C, 0xA4BC0001, + 0x81C, 0xA3BE0001, + 0x81C, 0xA2C00001, + 0x81C, 0xA1C20001, + 0x81C, 0x68C40001, + 0x81C, 0x67C60001, + 0x81C, 0x66C80001, + 0x81C, 0x65CA0001, + 0x81C, 0x64CC0001, + 0x81C, 0x47CE0001, + 0x81C, 0x46D00001, + 0x81C, 0x45D20001, + 0x81C, 0x44D40001, + 0x81C, 0x43D60001, + 0x81C, 0x42D80001, + 0x81C, 0x08DA0001, + 0x81C, 0x07DC0001, + 0x81C, 0x06DE0001, + 0x81C, 0x05E00001, + 0x81C, 0x04E20001, + 0x81C, 0x03E40001, + 0x81C, 0x02E60001, + 0x81C, 0x01E80001, + 0x81C, 0x01EA0001, + 0x81C, 0x01EC0001, + 0x81C, 0x01EE0001, + 0x81C, 0x01F00001, + 0x81C, 0x01F20001, + 0x81C, 0x01F40001, + 0x81C, 0x01F60001, + 0x81C, 0x01F80001, + 0x81C, 0x01FA0001, + 0x81C, 0x01FC0001, + 0x81C, 0x01FE0001, + 0xCDCDCDCD, 0xCDCD, + 0x81C, 0xFF800001, + 0x81C, 0xFF820001, + 0x81C, 0xFF840001, + 0x81C, 0xFE860001, + 0x81C, 0xFD880001, + 0x81C, 0xFC8A0001, + 0x81C, 0xFB8C0001, + 0x81C, 0xFA8E0001, + 0x81C, 0xF9900001, + 0x81C, 0xF8920001, + 0x81C, 0xF7940001, + 0x81C, 0xF6960001, + 0x81C, 0xF5980001, + 0x81C, 0xF49A0001, + 0x81C, 0xF39C0001, + 0x81C, 0xF29E0001, + 0x81C, 0xF1A00001, + 0x81C, 0xF0A20001, + 0x81C, 0xEFA40001, + 0x81C, 0xEEA60001, + 0x81C, 0xEDA80001, + 0x81C, 0xECAA0001, + 0x81C, 0xEBAC0001, + 0x81C, 0xEAAE0001, + 0x81C, 0xE9B00001, + 0x81C, 0xE8B20001, + 0x81C, 0xE7B40001, + 0x81C, 0xE6B60001, + 0x81C, 0xE5B80001, + 0x81C, 0xE4BA0001, + 0x81C, 0xE3BC0001, + 0x81C, 0xA8BE0001, + 0x81C, 0xA7C00001, + 0x81C, 0xA6C20001, + 0x81C, 0xA5C40001, + 0x81C, 0xA4C60001, + 0x81C, 0xA3C80001, + 0x81C, 0xA2CA0001, + 0x81C, 0xA1CC0001, + 0x81C, 0x68CE0001, + 0x81C, 0x67D00001, + 0x81C, 0x66D20001, + 0x81C, 0x65D40001, + 0x81C, 0x64D60001, + 0x81C, 0x47D80001, + 0x81C, 0x46DA0001, + 0x81C, 0x45DC0001, + 0x81C, 0x44DE0001, + 0x81C, 0x43E00001, + 0x81C, 0x42E20001, + 0x81C, 0x08E40001, + 0x81C, 0x07E60001, + 0x81C, 0x06E80001, + 0x81C, 0x05EA0001, + 0x81C, 0x04EC0001, + 0x81C, 0x03EE0001, + 0x81C, 0x02F00001, + 0x81C, 0x01F20001, + 0x81C, 0x01F40001, + 0x81C, 0x01F60001, + 0x81C, 0x01F80001, + 0x81C, 0x01FA0001, + 0x81C, 0x01FC0001, + 0x81C, 0x01FE0001, + 0xFF0F0180, 0xDEAD, + 0xC50, 0x00000022, + 0xC50, 0x00000020, + 0xE50, 0x00000022, + 0xE50, 0x00000020, + +}; + +u32 RTL8821AE_AGC_TAB_ARRAY[] = { + 0x81C, 0xBF000001, + 0x81C, 0xBF020001, + 0x81C, 0xBF040001, + 0x81C, 0xBF060001, + 0x81C, 0xBE080001, + 0x81C, 0xBD0A0001, + 0x81C, 0xBC0C0001, + 0x81C, 0xBA0E0001, + 0x81C, 0xB9100001, + 0x81C, 0xB8120001, + 0x81C, 0xB7140001, + 0x81C, 0xB6160001, + 0x81C, 0xB5180001, + 0x81C, 0xB41A0001, + 0x81C, 0xB31C0001, + 0x81C, 0xB21E0001, + 0x81C, 0xB1200001, + 0x81C, 0xB0220001, + 0x81C, 0xAF240001, + 0x81C, 0xAE260001, + 0x81C, 0xAD280001, + 0x81C, 0xAC2A0001, + 0x81C, 0xAB2C0001, + 0x81C, 0xAA2E0001, + 0x81C, 0xA9300001, + 0x81C, 0xA8320001, + 0x81C, 0xA7340001, + 0x81C, 0xA6360001, + 0x81C, 0xA5380001, + 0x81C, 0xA43A0001, + 0x81C, 0xA33C0001, + 0x81C, 0x673E0001, + 0x81C, 0x66400001, + 0x81C, 0x65420001, + 0x81C, 0x64440001, + 0x81C, 0x63460001, + 0x81C, 0x62480001, + 0x81C, 0x614A0001, + 0x81C, 0x474C0001, + 0x81C, 0x464E0001, + 0x81C, 0x45500001, + 0x81C, 0x44520001, + 0x81C, 0x43540001, + 0x81C, 0x42560001, + 0x81C, 0x41580001, + 0x81C, 0x285A0001, + 0x81C, 0x275C0001, + 0x81C, 0x265E0001, + 0x81C, 0x25600001, + 0x81C, 0x24620001, + 0x81C, 0x0A640001, + 0x81C, 0x09660001, + 0x81C, 0x08680001, + 0x81C, 0x076A0001, + 0x81C, 0x066C0001, + 0x81C, 0x056E0001, + 0x81C, 0x04700001, + 0x81C, 0x03720001, + 0x81C, 0x02740001, + 0x81C, 0x01760001, + 0x81C, 0x01780001, + 0x81C, 0x017A0001, + 0x81C, 0x017C0001, + 0x81C, 0x017E0001, + 0xFF0F02C0, 0xABCD, + 0x81C, 0xFB000101, + 0x81C, 0xFA020101, + 0x81C, 0xF9040101, + 0x81C, 0xF8060101, + 0x81C, 0xF7080101, + 0x81C, 0xF60A0101, + 0x81C, 0xF50C0101, + 0x81C, 0xF40E0101, + 0x81C, 0xF3100101, + 0x81C, 0xF2120101, + 0x81C, 0xF1140101, + 0x81C, 0xF0160101, + 0x81C, 0xEF180101, + 0x81C, 0xEE1A0101, + 0x81C, 0xED1C0101, + 0x81C, 0xEC1E0101, + 0x81C, 0xEB200101, + 0x81C, 0xEA220101, + 0x81C, 0xE9240101, + 0x81C, 0xE8260101, + 0x81C, 0xE7280101, + 0x81C, 0xE62A0101, + 0x81C, 0xE52C0101, + 0x81C, 0xE42E0101, + 0x81C, 0xE3300101, + 0x81C, 0xA5320101, + 0x81C, 0xA4340101, + 0x81C, 0xA3360101, + 0x81C, 0x87380101, + 0x81C, 0x863A0101, + 0x81C, 0x853C0101, + 0x81C, 0x843E0101, + 0x81C, 0x69400101, + 0x81C, 0x68420101, + 0x81C, 0x67440101, + 0x81C, 0x66460101, + 0x81C, 0x49480101, + 0x81C, 0x484A0101, + 0x81C, 0x474C0101, + 0x81C, 0x2A4E0101, + 0x81C, 0x29500101, + 0x81C, 0x28520101, + 0x81C, 0x27540101, + 0x81C, 0x26560101, + 0x81C, 0x25580101, + 0x81C, 0x245A0101, + 0x81C, 0x235C0101, + 0x81C, 0x055E0101, + 0x81C, 0x04600101, + 0x81C, 0x03620101, + 0x81C, 0x02640101, + 0x81C, 0x01660101, + 0x81C, 0x01680101, + 0x81C, 0x016A0101, + 0x81C, 0x016C0101, + 0x81C, 0x016E0101, + 0x81C, 0x01700101, + 0x81C, 0x01720101, + 0xCDCDCDCD, 0xCDCD, + 0x81C, 0xFF000101, + 0x81C, 0xFF020101, + 0x81C, 0xFE040101, + 0x81C, 0xFD060101, + 0x81C, 0xFC080101, + 0x81C, 0xFD0A0101, + 0x81C, 0xFC0C0101, + 0x81C, 0xFB0E0101, + 0x81C, 0xFA100101, + 0x81C, 0xF9120101, + 0x81C, 0xF8140101, + 0x81C, 0xF7160101, + 0x81C, 0xF6180101, + 0x81C, 0xF51A0101, + 0x81C, 0xF41C0101, + 0x81C, 0xF31E0101, + 0x81C, 0xF2200101, + 0x81C, 0xF1220101, + 0x81C, 0xF0240101, + 0x81C, 0xEF260101, + 0x81C, 0xEE280101, + 0x81C, 0xED2A0101, + 0x81C, 0xEC2C0101, + 0x81C, 0xEB2E0101, + 0x81C, 0xEA300101, + 0x81C, 0xE9320101, + 0x81C, 0xE8340101, + 0x81C, 0xE7360101, + 0x81C, 0xE6380101, + 0x81C, 0xE53A0101, + 0x81C, 0xE43C0101, + 0x81C, 0xE33E0101, + 0x81C, 0xA5400101, + 0x81C, 0xA4420101, + 0x81C, 0xA3440101, + 0x81C, 0x87460101, + 0x81C, 0x86480101, + 0x81C, 0x854A0101, + 0x81C, 0x844C0101, + 0x81C, 0x694E0101, + 0x81C, 0x68500101, + 0x81C, 0x67520101, + 0x81C, 0x66540101, + 0x81C, 0x49560101, + 0x81C, 0x48580101, + 0x81C, 0x475A0101, + 0x81C, 0x2A5C0101, + 0x81C, 0x295E0101, + 0x81C, 0x28600101, + 0x81C, 0x27620101, + 0x81C, 0x26640101, + 0x81C, 0x25660101, + 0x81C, 0x24680101, + 0x81C, 0x236A0101, + 0x81C, 0x056C0101, + 0x81C, 0x046E0101, + 0x81C, 0x03700101, + 0x81C, 0x02720101, + 0xFF0F02C0, 0xDEAD, + 0x81C, 0x01740101, + 0x81C, 0x01760101, + 0x81C, 0x01780101, + 0x81C, 0x017A0101, + 0x81C, 0x017C0101, + 0x81C, 0x017E0101, + 0xC50, 0x00000022, + 0xC50, 0x00000020, + +}; + +/****************************************************************************** +* TXPWR_LMT.TXT +******************************************************************************/ + +u8 *RTL8812AE_TXPWR_LMT[] = { + "FCC", "2.4G", "20M", "CCK", "1T", "01", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "01", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "01", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "02", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "02", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "02", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "03", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "03", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "03", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "04", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "04", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "04", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "05", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "05", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "05", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "06", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "06", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "06", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "07", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "07", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "07", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "08", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "08", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "08", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "09", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "09", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "09", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "10", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "10", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "10", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "11", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "11", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "11", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "12", "63", + "ETSI", "2.4G", "20M", "CCK", "1T", "12", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "12", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "13", "63", + "ETSI", "2.4G", "20M", "CCK", "1T", "13", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "13", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "14", "63", + "ETSI", "2.4G", "20M", "CCK", "1T", "14", "63", + "MKK", "2.4G", "20M", "CCK", "1T", "14", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "01", "34", + "ETSI", "2.4G", "20M", "OFDM", "1T", "01", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "01", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "02", "36", + "ETSI", "2.4G", "20M", "OFDM", "1T", "02", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "02", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "03", "36", + "ETSI", "2.4G", "20M", "OFDM", "1T", "03", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "03", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "04", "36", + "ETSI", "2.4G", "20M", "OFDM", "1T", "04", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "04", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "05", "36", + "ETSI", "2.4G", "20M", "OFDM", "1T", "05", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "05", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "06", "36", + "ETSI", "2.4G", "20M", "OFDM", "1T", "06", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "06", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "07", "36", + "ETSI", "2.4G", "20M", "OFDM", "1T", "07", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "07", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "08", "36", + "ETSI", "2.4G", "20M", "OFDM", "1T", "08", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "08", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "09", "36", + "ETSI", "2.4G", "20M", "OFDM", "1T", "09", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "09", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "10", "36", + "ETSI", "2.4G", "20M", "OFDM", "1T", "10", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "10", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "11", "32", + "ETSI", "2.4G", "20M", "OFDM", "1T", "11", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "11", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "12", "63", + "ETSI", "2.4G", "20M", "OFDM", "1T", "12", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "12", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "13", "63", + "ETSI", "2.4G", "20M", "OFDM", "1T", "13", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "13", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "14", "63", + "ETSI", "2.4G", "20M", "OFDM", "1T", "14", "63", + "MKK", "2.4G", "20M", "OFDM", "1T", "14", "63", + "FCC", "2.4G", "20M", "HT", "1T", "01", "34", + "ETSI", "2.4G", "20M", "HT", "1T", "01", "32", + "MKK", "2.4G", "20M", "HT", "1T", "01", "32", + "FCC", "2.4G", "20M", "HT", "1T", "02", "36", + "ETSI", "2.4G", "20M", "HT", "1T", "02", "32", + "MKK", "2.4G", "20M", "HT", "1T", "02", "32", + "FCC", "2.4G", "20M", "HT", "1T", "03", "36", + "ETSI", "2.4G", "20M", "HT", "1T", "03", "32", + "MKK", "2.4G", "20M", "HT", "1T", "03", "32", + "FCC", "2.4G", "20M", "HT", "1T", "04", "36", + "ETSI", "2.4G", "20M", "HT", "1T", "04", "32", + "MKK", "2.4G", "20M", "HT", "1T", "04", "32", + "FCC", "2.4G", "20M", "HT", "1T", "05", "36", + "ETSI", "2.4G", "20M", "HT", "1T", "05", "32", + "MKK", "2.4G", "20M", "HT", "1T", "05", "32", + "FCC", "2.4G", "20M", "HT", "1T", "06", "36", + "ETSI", "2.4G", "20M", "HT", "1T", "06", "32", + "MKK", "2.4G", "20M", "HT", "1T", "06", "32", + "FCC", "2.4G", "20M", "HT", "1T", "07", "36", + "ETSI", "2.4G", "20M", "HT", "1T", "07", "32", + "MKK", "2.4G", "20M", "HT", "1T", "07", "32", + "FCC", "2.4G", "20M", "HT", "1T", "08", "36", + "ETSI", "2.4G", "20M", "HT", "1T", "08", "32", + "MKK", "2.4G", "20M", "HT", "1T", "08", "32", + "FCC", "2.4G", "20M", "HT", "1T", "09", "36", + "ETSI", "2.4G", "20M", "HT", "1T", "09", "32", + "MKK", "2.4G", "20M", "HT", "1T", "09", "32", + "FCC", "2.4G", "20M", "HT", "1T", "10", "36", + "ETSI", "2.4G", "20M", "HT", "1T", "10", "32", + "MKK", "2.4G", "20M", "HT", "1T", "10", "32", + "FCC", "2.4G", "20M", "HT", "1T", "11", "32", + "ETSI", "2.4G", "20M", "HT", "1T", "11", "32", + "MKK", "2.4G", "20M", "HT", "1T", "11", "32", + "FCC", "2.4G", "20M", "HT", "1T", "12", "63", + "ETSI", "2.4G", "20M", "HT", "1T", "12", "32", + "MKK", "2.4G", "20M", "HT", "1T", "12", "32", + "FCC", "2.4G", "20M", "HT", "1T", "13", "63", + "ETSI", "2.4G", "20M", "HT", "1T", "13", "32", + "MKK", "2.4G", "20M", "HT", "1T", "13", "32", + "FCC", "2.4G", "20M", "HT", "1T", "14", "63", + "ETSI", "2.4G", "20M", "HT", "1T", "14", "63", + "MKK", "2.4G", "20M", "HT", "1T", "14", "63", + "FCC", "2.4G", "20M", "HT", "2T", "01", "32", + "ETSI", "2.4G", "20M", "HT", "2T", "01", "32", + "MKK", "2.4G", "20M", "HT", "2T", "01", "32", + "FCC", "2.4G", "20M", "HT", "2T", "02", "34", + "ETSI", "2.4G", "20M", "HT", "2T", "02", "32", + "MKK", "2.4G", "20M", "HT", "2T", "02", "32", + "FCC", "2.4G", "20M", "HT", "2T", "03", "34", + "ETSI", "2.4G", "20M", "HT", "2T", "03", "32", + "MKK", "2.4G", "20M", "HT", "2T", "03", "32", + "FCC", "2.4G", "20M", "HT", "2T", "04", "34", + "ETSI", "2.4G", "20M", "HT", "2T", "04", "32", + "MKK", "2.4G", "20M", "HT", "2T", "04", "32", + "FCC", "2.4G", "20M", "HT", "2T", "05", "34", + "ETSI", "2.4G", "20M", "HT", "2T", "05", "32", + "MKK", "2.4G", "20M", "HT", "2T", "05", "32", + "FCC", "2.4G", "20M", "HT", "2T", "06", "34", + "ETSI", "2.4G", "20M", "HT", "2T", "06", "32", + "MKK", "2.4G", "20M", "HT", "2T", "06", "32", + "FCC", "2.4G", "20M", "HT", "2T", "07", "34", + "ETSI", "2.4G", "20M", "HT", "2T", "07", "32", + "MKK", "2.4G", "20M", "HT", "2T", "07", "32", + "FCC", "2.4G", "20M", "HT", "2T", "08", "34", + "ETSI", "2.4G", "20M", "HT", "2T", "08", "32", + "MKK", "2.4G", "20M", "HT", "2T", "08", "32", + "FCC", "2.4G", "20M", "HT", "2T", "09", "34", + "ETSI", "2.4G", "20M", "HT", "2T", "09", "32", + "MKK", "2.4G", "20M", "HT", "2T", "09", "32", + "FCC", "2.4G", "20M", "HT", "2T", "10", "34", + "ETSI", "2.4G", "20M", "HT", "2T", "10", "32", + "MKK", "2.4G", "20M", "HT", "2T", "10", "32", + "FCC", "2.4G", "20M", "HT", "2T", "11", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "11", "32", + "MKK", "2.4G", "20M", "HT", "2T", "11", "32", + "FCC", "2.4G", "20M", "HT", "2T", "12", "63", + "ETSI", "2.4G", "20M", "HT", "2T", "12", "32", + "MKK", "2.4G", "20M", "HT", "2T", "12", "32", + "FCC", "2.4G", "20M", "HT", "2T", "13", "63", + "ETSI", "2.4G", "20M", "HT", "2T", "13", "32", + "MKK", "2.4G", "20M", "HT", "2T", "13", "32", + "FCC", "2.4G", "20M", "HT", "2T", "14", "63", + "ETSI", "2.4G", "20M", "HT", "2T", "14", "63", + "MKK", "2.4G", "20M", "HT", "2T", "14", "63", + "FCC", "2.4G", "40M", "HT", "1T", "01", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "01", "63", + "MKK", "2.4G", "40M", "HT", "1T", "01", "63", + "FCC", "2.4G", "40M", "HT", "1T", "02", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "02", "63", + "MKK", "2.4G", "40M", "HT", "1T", "02", "63", + "FCC", "2.4G", "40M", "HT", "1T", "03", "32", + "ETSI", "2.4G", "40M", "HT", "1T", "03", "32", + "MKK", "2.4G", "40M", "HT", "1T", "03", "32", + "FCC", "2.4G", "40M", "HT", "1T", "04", "36", + "ETSI", "2.4G", "40M", "HT", "1T", "04", "32", + "MKK", "2.4G", "40M", "HT", "1T", "04", "32", + "FCC", "2.4G", "40M", "HT", "1T", "05", "36", + "ETSI", "2.4G", "40M", "HT", "1T", "05", "32", + "MKK", "2.4G", "40M", "HT", "1T", "05", "32", + "FCC", "2.4G", "40M", "HT", "1T", "06", "36", + "ETSI", "2.4G", "40M", "HT", "1T", "06", "32", + "MKK", "2.4G", "40M", "HT", "1T", "06", "32", + "FCC", "2.4G", "40M", "HT", "1T", "07", "36", + "ETSI", "2.4G", "40M", "HT", "1T", "07", "32", + "MKK", "2.4G", "40M", "HT", "1T", "07", "32", + "FCC", "2.4G", "40M", "HT", "1T", "08", "36", + "ETSI", "2.4G", "40M", "HT", "1T", "08", "32", + "MKK", "2.4G", "40M", "HT", "1T", "08", "32", + "FCC", "2.4G", "40M", "HT", "1T", "09", "36", + "ETSI", "2.4G", "40M", "HT", "1T", "09", "32", + "MKK", "2.4G", "40M", "HT", "1T", "09", "32", + "FCC", "2.4G", "40M", "HT", "1T", "10", "36", + "ETSI", "2.4G", "40M", "HT", "1T", "10", "32", + "MKK", "2.4G", "40M", "HT", "1T", "10", "32", + "FCC", "2.4G", "40M", "HT", "1T", "11", "32", + "ETSI", "2.4G", "40M", "HT", "1T", "11", "32", + "MKK", "2.4G", "40M", "HT", "1T", "11", "32", + "FCC", "2.4G", "40M", "HT", "1T", "12", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "12", "32", + "MKK", "2.4G", "40M", "HT", "1T", "12", "32", + "FCC", "2.4G", "40M", "HT", "1T", "13", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "13", "32", + "MKK", "2.4G", "40M", "HT", "1T", "13", "32", + "FCC", "2.4G", "40M", "HT", "1T", "14", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "14", "63", + "MKK", "2.4G", "40M", "HT", "1T", "14", "63", + "FCC", "2.4G", "40M", "HT", "2T", "01", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "01", "63", + "MKK", "2.4G", "40M", "HT", "2T", "01", "63", + "FCC", "2.4G", "40M", "HT", "2T", "02", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "02", "63", + "MKK", "2.4G", "40M", "HT", "2T", "02", "63", + "FCC", "2.4G", "40M", "HT", "2T", "03", "30", + "ETSI", "2.4G", "40M", "HT", "2T", "03", "30", + "MKK", "2.4G", "40M", "HT", "2T", "03", "30", + "FCC", "2.4G", "40M", "HT", "2T", "04", "34", + "ETSI", "2.4G", "40M", "HT", "2T", "04", "30", + "MKK", "2.4G", "40M", "HT", "2T", "04", "30", + "FCC", "2.4G", "40M", "HT", "2T", "05", "34", + "ETSI", "2.4G", "40M", "HT", "2T", "05", "30", + "MKK", "2.4G", "40M", "HT", "2T", "05", "30", + "FCC", "2.4G", "40M", "HT", "2T", "06", "34", + "ETSI", "2.4G", "40M", "HT", "2T", "06", "30", + "MKK", "2.4G", "40M", "HT", "2T", "06", "30", + "FCC", "2.4G", "40M", "HT", "2T", "07", "34", + "ETSI", "2.4G", "40M", "HT", "2T", "07", "30", + "MKK", "2.4G", "40M", "HT", "2T", "07", "30", + "FCC", "2.4G", "40M", "HT", "2T", "08", "34", + "ETSI", "2.4G", "40M", "HT", "2T", "08", "30", + "MKK", "2.4G", "40M", "HT", "2T", "08", "30", + "FCC", "2.4G", "40M", "HT", "2T", "09", "34", + "ETSI", "2.4G", "40M", "HT", "2T", "09", "30", + "MKK", "2.4G", "40M", "HT", "2T", "09", "30", + "FCC", "2.4G", "40M", "HT", "2T", "10", "34", + "ETSI", "2.4G", "40M", "HT", "2T", "10", "30", + "MKK", "2.4G", "40M", "HT", "2T", "10", "30", + "FCC", "2.4G", "40M", "HT", "2T", "11", "30", + "ETSI", "2.4G", "40M", "HT", "2T", "11", "30", + "MKK", "2.4G", "40M", "HT", "2T", "11", "30", + "FCC", "2.4G", "40M", "HT", "2T", "12", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "12", "32", + "MKK", "2.4G", "40M", "HT", "2T", "12", "32", + "FCC", "2.4G", "40M", "HT", "2T", "13", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "13", "32", + "MKK", "2.4G", "40M", "HT", "2T", "13", "32", + "FCC", "2.4G", "40M", "HT", "2T", "14", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "14", "63", + "MKK", "2.4G", "40M", "HT", "2T", "14", "63", + "FCC", "5G", "20M", "OFDM", "1T", "36", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "36", "32", + "MKK", "5G", "20M", "OFDM", "1T", "36", "32", + "FCC", "5G", "20M", "OFDM", "1T", "40", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "40", "32", + "MKK", "5G", "20M", "OFDM", "1T", "40", "32", + "FCC", "5G", "20M", "OFDM", "1T", "44", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "44", "32", + "MKK", "5G", "20M", "OFDM", "1T", "44", "32", + "FCC", "5G", "20M", "OFDM", "1T", "48", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "48", "32", + "MKK", "5G", "20M", "OFDM", "1T", "48", "32", + "FCC", "5G", "20M", "OFDM", "1T", "52", "36", + "ETSI", "5G", "20M", "OFDM", "1T", "52", "32", + "MKK", "5G", "20M", "OFDM", "1T", "52", "32", + "FCC", "5G", "20M", "OFDM", "1T", "56", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "56", "32", + "MKK", "5G", "20M", "OFDM", "1T", "56", "32", + "FCC", "5G", "20M", "OFDM", "1T", "60", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "60", "32", + "MKK", "5G", "20M", "OFDM", "1T", "60", "32", + "FCC", "5G", "20M", "OFDM", "1T", "64", "28", + "ETSI", "5G", "20M", "OFDM", "1T", "64", "32", + "MKK", "5G", "20M", "OFDM", "1T", "64", "32", + "FCC", "5G", "20M", "OFDM", "1T", "100", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "100", "32", + "MKK", "5G", "20M", "OFDM", "1T", "100", "32", + "FCC", "5G", "20M", "OFDM", "1T", "114", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "114", "32", + "MKK", "5G", "20M", "OFDM", "1T", "114", "32", + "FCC", "5G", "20M", "OFDM", "1T", "108", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "108", "32", + "MKK", "5G", "20M", "OFDM", "1T", "108", "32", + "FCC", "5G", "20M", "OFDM", "1T", "112", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "112", "32", + "MKK", "5G", "20M", "OFDM", "1T", "112", "32", + "FCC", "5G", "20M", "OFDM", "1T", "116", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "116", "32", + "MKK", "5G", "20M", "OFDM", "1T", "116", "32", + "FCC", "5G", "20M", "OFDM", "1T", "120", "36", + "ETSI", "5G", "20M", "OFDM", "1T", "120", "32", + "MKK", "5G", "20M", "OFDM", "1T", "120", "32", + "FCC", "5G", "20M", "OFDM", "1T", "124", "34", + "ETSI", "5G", "20M", "OFDM", "1T", "124", "32", + "MKK", "5G", "20M", "OFDM", "1T", "124", "32", + "FCC", "5G", "20M", "OFDM", "1T", "128", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "128", "32", + "MKK", "5G", "20M", "OFDM", "1T", "128", "32", + "FCC", "5G", "20M", "OFDM", "1T", "132", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "132", "32", + "MKK", "5G", "20M", "OFDM", "1T", "132", "32", + "FCC", "5G", "20M", "OFDM", "1T", "136", "30", + "ETSI", "5G", "20M", "OFDM", "1T", "136", "32", + "MKK", "5G", "20M", "OFDM", "1T", "136", "32", + "FCC", "5G", "20M", "OFDM", "1T", "140", "28", + "ETSI", "5G", "20M", "OFDM", "1T", "140", "32", + "MKK", "5G", "20M", "OFDM", "1T", "140", "32", + "FCC", "5G", "20M", "OFDM", "1T", "149", "36", + "ETSI", "5G", "20M", "OFDM", "1T", "149", "32", + "MKK", "5G", "20M", "OFDM", "1T", "149", "63", + "FCC", "5G", "20M", "OFDM", "1T", "153", "36", + "ETSI", "5G", "20M", "OFDM", "1T", "153", "32", + "MKK", "5G", "20M", "OFDM", "1T", "153", "63", + "FCC", "5G", "20M", "OFDM", "1T", "157", "36", + "ETSI", "5G", "20M", "OFDM", "1T", "157", "32", + "MKK", "5G", "20M", "OFDM", "1T", "157", "63", + "FCC", "5G", "20M", "OFDM", "1T", "161", "36", + "ETSI", "5G", "20M", "OFDM", "1T", "161", "32", + "MKK", "5G", "20M", "OFDM", "1T", "161", "63", + "FCC", "5G", "20M", "OFDM", "1T", "165", "36", + "ETSI", "5G", "20M", "OFDM", "1T", "165", "32", + "MKK", "5G", "20M", "OFDM", "1T", "165", "63", + "FCC", "5G", "20M", "HT", "1T", "36", "30", + "ETSI", "5G", "20M", "HT", "1T", "36", "32", + "MKK", "5G", "20M", "HT", "1T", "36", "32", + "FCC", "5G", "20M", "HT", "1T", "40", "30", + "ETSI", "5G", "20M", "HT", "1T", "40", "32", + "MKK", "5G", "20M", "HT", "1T", "40", "32", + "FCC", "5G", "20M", "HT", "1T", "44", "30", + "ETSI", "5G", "20M", "HT", "1T", "44", "32", + "MKK", "5G", "20M", "HT", "1T", "44", "32", + "FCC", "5G", "20M", "HT", "1T", "48", "30", + "ETSI", "5G", "20M", "HT", "1T", "48", "32", + "MKK", "5G", "20M", "HT", "1T", "48", "32", + "FCC", "5G", "20M", "HT", "1T", "52", "36", + "ETSI", "5G", "20M", "HT", "1T", "52", "32", + "MKK", "5G", "20M", "HT", "1T", "52", "32", + "FCC", "5G", "20M", "HT", "1T", "56", "34", + "ETSI", "5G", "20M", "HT", "1T", "56", "32", + "MKK", "5G", "20M", "HT", "1T", "56", "32", + "FCC", "5G", "20M", "HT", "1T", "60", "32", + "ETSI", "5G", "20M", "HT", "1T", "60", "32", + "MKK", "5G", "20M", "HT", "1T", "60", "32", + "FCC", "5G", "20M", "HT", "1T", "64", "28", + "ETSI", "5G", "20M", "HT", "1T", "64", "32", + "MKK", "5G", "20M", "HT", "1T", "64", "32", + "FCC", "5G", "20M", "HT", "1T", "100", "30", + "ETSI", "5G", "20M", "HT", "1T", "100", "32", + "MKK", "5G", "20M", "HT", "1T", "100", "32", + "FCC", "5G", "20M", "HT", "1T", "114", "30", + "ETSI", "5G", "20M", "HT", "1T", "114", "32", + "MKK", "5G", "20M", "HT", "1T", "114", "32", + "FCC", "5G", "20M", "HT", "1T", "108", "32", + "ETSI", "5G", "20M", "HT", "1T", "108", "32", + "MKK", "5G", "20M", "HT", "1T", "108", "32", + "FCC", "5G", "20M", "HT", "1T", "112", "34", + "ETSI", "5G", "20M", "HT", "1T", "112", "32", + "MKK", "5G", "20M", "HT", "1T", "112", "32", + "FCC", "5G", "20M", "HT", "1T", "116", "34", + "ETSI", "5G", "20M", "HT", "1T", "116", "32", + "MKK", "5G", "20M", "HT", "1T", "116", "32", + "FCC", "5G", "20M", "HT", "1T", "120", "36", + "ETSI", "5G", "20M", "HT", "1T", "120", "32", + "MKK", "5G", "20M", "HT", "1T", "120", "32", + "FCC", "5G", "20M", "HT", "1T", "124", "34", + "ETSI", "5G", "20M", "HT", "1T", "124", "32", + "MKK", "5G", "20M", "HT", "1T", "124", "32", + "FCC", "5G", "20M", "HT", "1T", "128", "32", + "ETSI", "5G", "20M", "HT", "1T", "128", "32", + "MKK", "5G", "20M", "HT", "1T", "128", "32", + "FCC", "5G", "20M", "HT", "1T", "132", "30", + "ETSI", "5G", "20M", "HT", "1T", "132", "32", + "MKK", "5G", "20M", "HT", "1T", "132", "32", + "FCC", "5G", "20M", "HT", "1T", "136", "30", + "ETSI", "5G", "20M", "HT", "1T", "136", "32", + "MKK", "5G", "20M", "HT", "1T", "136", "32", + "FCC", "5G", "20M", "HT", "1T", "140", "28", + "ETSI", "5G", "20M", "HT", "1T", "140", "32", + "MKK", "5G", "20M", "HT", "1T", "140", "32", + "FCC", "5G", "20M", "HT", "1T", "149", "36", + "ETSI", "5G", "20M", "HT", "1T", "149", "32", + "MKK", "5G", "20M", "HT", "1T", "149", "63", + "FCC", "5G", "20M", "HT", "1T", "153", "36", + "ETSI", "5G", "20M", "HT", "1T", "153", "32", + "MKK", "5G", "20M", "HT", "1T", "153", "63", + "FCC", "5G", "20M", "HT", "1T", "157", "36", + "ETSI", "5G", "20M", "HT", "1T", "157", "32", + "MKK", "5G", "20M", "HT", "1T", "157", "63", + "FCC", "5G", "20M", "HT", "1T", "161", "36", + "ETSI", "5G", "20M", "HT", "1T", "161", "32", + "MKK", "5G", "20M", "HT", "1T", "161", "63", + "FCC", "5G", "20M", "HT", "1T", "165", "36", + "ETSI", "5G", "20M", "HT", "1T", "165", "32", + "MKK", "5G", "20M", "HT", "1T", "165", "63", + "FCC", "5G", "20M", "HT", "2T", "36", "28", + "ETSI", "5G", "20M", "HT", "2T", "36", "30", + "MKK", "5G", "20M", "HT", "2T", "36", "30", + "FCC", "5G", "20M", "HT", "2T", "40", "28", + "ETSI", "5G", "20M", "HT", "2T", "40", "30", + "MKK", "5G", "20M", "HT", "2T", "40", "30", + "FCC", "5G", "20M", "HT", "2T", "44", "28", + "ETSI", "5G", "20M", "HT", "2T", "44", "30", + "MKK", "5G", "20M", "HT", "2T", "44", "30", + "FCC", "5G", "20M", "HT", "2T", "48", "28", + "ETSI", "5G", "20M", "HT", "2T", "48", "30", + "MKK", "5G", "20M", "HT", "2T", "48", "30", + "FCC", "5G", "20M", "HT", "2T", "52", "34", + "ETSI", "5G", "20M", "HT", "2T", "52", "30", + "MKK", "5G", "20M", "HT", "2T", "52", "30", + "FCC", "5G", "20M", "HT", "2T", "56", "32", + "ETSI", "5G", "20M", "HT", "2T", "56", "30", + "MKK", "5G", "20M", "HT", "2T", "56", "30", + "FCC", "5G", "20M", "HT", "2T", "60", "30", + "ETSI", "5G", "20M", "HT", "2T", "60", "30", + "MKK", "5G", "20M", "HT", "2T", "60", "30", + "FCC", "5G", "20M", "HT", "2T", "64", "26", + "ETSI", "5G", "20M", "HT", "2T", "64", "30", + "MKK", "5G", "20M", "HT", "2T", "64", "30", + "FCC", "5G", "20M", "HT", "2T", "100", "28", + "ETSI", "5G", "20M", "HT", "2T", "100", "30", + "MKK", "5G", "20M", "HT", "2T", "100", "30", + "FCC", "5G", "20M", "HT", "2T", "114", "28", + "ETSI", "5G", "20M", "HT", "2T", "114", "30", + "MKK", "5G", "20M", "HT", "2T", "114", "30", + "FCC", "5G", "20M", "HT", "2T", "108", "30", + "ETSI", "5G", "20M", "HT", "2T", "108", "30", + "MKK", "5G", "20M", "HT", "2T", "108", "30", + "FCC", "5G", "20M", "HT", "2T", "112", "32", + "ETSI", "5G", "20M", "HT", "2T", "112", "30", + "MKK", "5G", "20M", "HT", "2T", "112", "30", + "FCC", "5G", "20M", "HT", "2T", "116", "32", + "ETSI", "5G", "20M", "HT", "2T", "116", "30", + "MKK", "5G", "20M", "HT", "2T", "116", "30", + "FCC", "5G", "20M", "HT", "2T", "120", "34", + "ETSI", "5G", "20M", "HT", "2T", "120", "30", + "MKK", "5G", "20M", "HT", "2T", "120", "30", + "FCC", "5G", "20M", "HT", "2T", "124", "32", + "ETSI", "5G", "20M", "HT", "2T", "124", "30", + "MKK", "5G", "20M", "HT", "2T", "124", "30", + "FCC", "5G", "20M", "HT", "2T", "128", "30", + "ETSI", "5G", "20M", "HT", "2T", "128", "30", + "MKK", "5G", "20M", "HT", "2T", "128", "30", + "FCC", "5G", "20M", "HT", "2T", "132", "28", + "ETSI", "5G", "20M", "HT", "2T", "132", "30", + "MKK", "5G", "20M", "HT", "2T", "132", "30", + "FCC", "5G", "20M", "HT", "2T", "136", "28", + "ETSI", "5G", "20M", "HT", "2T", "136", "30", + "MKK", "5G", "20M", "HT", "2T", "136", "30", + "FCC", "5G", "20M", "HT", "2T", "140", "26", + "ETSI", "5G", "20M", "HT", "2T", "140", "30", + "MKK", "5G", "20M", "HT", "2T", "140", "30", + "FCC", "5G", "20M", "HT", "2T", "149", "34", + "ETSI", "5G", "20M", "HT", "2T", "149", "30", + "MKK", "5G", "20M", "HT", "2T", "149", "63", + "FCC", "5G", "20M", "HT", "2T", "153", "34", + "ETSI", "5G", "20M", "HT", "2T", "153", "30", + "MKK", "5G", "20M", "HT", "2T", "153", "63", + "FCC", "5G", "20M", "HT", "2T", "157", "34", + "ETSI", "5G", "20M", "HT", "2T", "157", "30", + "MKK", "5G", "20M", "HT", "2T", "157", "63", + "FCC", "5G", "20M", "HT", "2T", "161", "34", + "ETSI", "5G", "20M", "HT", "2T", "161", "30", + "MKK", "5G", "20M", "HT", "2T", "161", "63", + "FCC", "5G", "20M", "HT", "2T", "165", "34", + "ETSI", "5G", "20M", "HT", "2T", "165", "30", + "MKK", "5G", "20M", "HT", "2T", "165", "63", + "FCC", "5G", "40M", "HT", "1T", "38", "30", + "ETSI", "5G", "40M", "HT", "1T", "38", "32", + "MKK", "5G", "40M", "HT", "1T", "38", "32", + "FCC", "5G", "40M", "HT", "1T", "46", "30", + "ETSI", "5G", "40M", "HT", "1T", "46", "32", + "MKK", "5G", "40M", "HT", "1T", "46", "32", + "FCC", "5G", "40M", "HT", "1T", "54", "32", + "ETSI", "5G", "40M", "HT", "1T", "54", "32", + "MKK", "5G", "40M", "HT", "1T", "54", "32", + "FCC", "5G", "40M", "HT", "1T", "62", "32", + "ETSI", "5G", "40M", "HT", "1T", "62", "32", + "MKK", "5G", "40M", "HT", "1T", "62", "32", + "FCC", "5G", "40M", "HT", "1T", "102", "28", + "ETSI", "5G", "40M", "HT", "1T", "102", "32", + "MKK", "5G", "40M", "HT", "1T", "102", "32", + "FCC", "5G", "40M", "HT", "1T", "110", "32", + "ETSI", "5G", "40M", "HT", "1T", "110", "32", + "MKK", "5G", "40M", "HT", "1T", "110", "32", + "FCC", "5G", "40M", "HT", "1T", "118", "36", + "ETSI", "5G", "40M", "HT", "1T", "118", "32", + "MKK", "5G", "40M", "HT", "1T", "118", "32", + "FCC", "5G", "40M", "HT", "1T", "126", "34", + "ETSI", "5G", "40M", "HT", "1T", "126", "32", + "MKK", "5G", "40M", "HT", "1T", "126", "32", + "FCC", "5G", "40M", "HT", "1T", "134", "32", + "ETSI", "5G", "40M", "HT", "1T", "134", "32", + "MKK", "5G", "40M", "HT", "1T", "134", "32", + "FCC", "5G", "40M", "HT", "1T", "151", "36", + "ETSI", "5G", "40M", "HT", "1T", "151", "32", + "MKK", "5G", "40M", "HT", "1T", "151", "63", + "FCC", "5G", "40M", "HT", "1T", "159", "36", + "ETSI", "5G", "40M", "HT", "1T", "159", "32", + "MKK", "5G", "40M", "HT", "1T", "159", "63", + "FCC", "5G", "40M", "HT", "2T", "38", "28", + "ETSI", "5G", "40M", "HT", "2T", "38", "30", + "MKK", "5G", "40M", "HT", "2T", "38", "30", + "FCC", "5G", "40M", "HT", "2T", "46", "28", + "ETSI", "5G", "40M", "HT", "2T", "46", "30", + "MKK", "5G", "40M", "HT", "2T", "46", "30", + "FCC", "5G", "40M", "HT", "2T", "54", "30", + "ETSI", "5G", "40M", "HT", "2T", "54", "30", + "MKK", "5G", "40M", "HT", "2T", "54", "30", + "FCC", "5G", "40M", "HT", "2T", "62", "30", + "ETSI", "5G", "40M", "HT", "2T", "62", "30", + "MKK", "5G", "40M", "HT", "2T", "62", "30", + "FCC", "5G", "40M", "HT", "2T", "102", "26", + "ETSI", "5G", "40M", "HT", "2T", "102", "30", + "MKK", "5G", "40M", "HT", "2T", "102", "30", + "FCC", "5G", "40M", "HT", "2T", "110", "30", + "ETSI", "5G", "40M", "HT", "2T", "110", "30", + "MKK", "5G", "40M", "HT", "2T", "110", "30", + "FCC", "5G", "40M", "HT", "2T", "118", "34", + "ETSI", "5G", "40M", "HT", "2T", "118", "30", + "MKK", "5G", "40M", "HT", "2T", "118", "30", + "FCC", "5G", "40M", "HT", "2T", "126", "32", + "ETSI", "5G", "40M", "HT", "2T", "126", "30", + "MKK", "5G", "40M", "HT", "2T", "126", "30", + "FCC", "5G", "40M", "HT", "2T", "134", "30", + "ETSI", "5G", "40M", "HT", "2T", "134", "30", + "MKK", "5G", "40M", "HT", "2T", "134", "30", + "FCC", "5G", "40M", "HT", "2T", "151", "34", + "ETSI", "5G", "40M", "HT", "2T", "151", "30", + "MKK", "5G", "40M", "HT", "2T", "151", "63", + "FCC", "5G", "40M", "HT", "2T", "159", "34", + "ETSI", "5G", "40M", "HT", "2T", "159", "30", + "MKK", "5G", "40M", "HT", "2T", "159", "63", + "FCC", "5G", "80M", "VHT", "1T", "42", "30", + "ETSI", "5G", "80M", "VHT", "1T", "42", "32", + "MKK", "5G", "80M", "VHT", "1T", "42", "32", + "FCC", "5G", "80M", "VHT", "1T", "58", "28", + "ETSI", "5G", "80M", "VHT", "1T", "58", "32", + "MKK", "5G", "80M", "VHT", "1T", "58", "32", + "FCC", "5G", "80M", "VHT", "1T", "106", "30", + "ETSI", "5G", "80M", "VHT", "1T", "106", "32", + "MKK", "5G", "80M", "VHT", "1T", "106", "32", + "FCC", "5G", "80M", "VHT", "1T", "122", "34", + "ETSI", "5G", "80M", "VHT", "1T", "122", "32", + "MKK", "5G", "80M", "VHT", "1T", "122", "32", + "FCC", "5G", "80M", "VHT", "1T", "155", "36", + "ETSI", "5G", "80M", "VHT", "1T", "155", "32", + "MKK", "5G", "80M", "VHT", "1T", "155", "63", + "FCC", "5G", "80M", "VHT", "2T", "42", "28", + "ETSI", "5G", "80M", "VHT", "2T", "42", "30", + "MKK", "5G", "80M", "VHT", "2T", "42", "30", + "FCC", "5G", "80M", "VHT", "2T", "58", "26", + "ETSI", "5G", "80M", "VHT", "2T", "58", "30", + "MKK", "5G", "80M", "VHT", "2T", "58", "30", + "FCC", "5G", "80M", "VHT", "2T", "106", "28", + "ETSI", "5G", "80M", "VHT", "2T", "106", "30", + "MKK", "5G", "80M", "VHT", "2T", "106", "30", + "FCC", "5G", "80M", "VHT", "2T", "122", "32", + "ETSI", "5G", "80M", "VHT", "2T", "122", "30", + "MKK", "5G", "80M", "VHT", "2T", "122", "30", + "FCC", "5G", "80M", "VHT", "2T", "155", "34", + "ETSI", "5G", "80M", "VHT", "2T", "155", "30", + "MKK", "5G", "80M", "VHT", "2T", "155", "63" +}; + +u8 *RTL8821AE_TXPWR_LMT[] = { + "FCC", "2.4G", "20M", "CCK", "1T", "01", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "01", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "01", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "02", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "02", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "02", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "03", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "03", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "03", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "04", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "04", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "04", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "05", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "05", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "05", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "06", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "06", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "06", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "07", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "07", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "07", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "08", "36", + "ETSI", "2.4G", "20M", "CCK", "1T", "08", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "08", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "09", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "09", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "09", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "10", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "10", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "10", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "11", "32", + "ETSI", "2.4G", "20M", "CCK", "1T", "11", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "11", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "12", "63", + "ETSI", "2.4G", "20M", "CCK", "1T", "12", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "12", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "13", "63", + "ETSI", "2.4G", "20M", "CCK", "1T", "13", "32", + "MKK", "2.4G", "20M", "CCK", "1T", "13", "32", + "FCC", "2.4G", "20M", "CCK", "1T", "14", "63", + "ETSI", "2.4G", "20M", "CCK", "1T", "14", "63", + "MKK", "2.4G", "20M", "CCK", "1T", "14", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "01", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "01", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "01", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "02", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "02", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "02", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "03", "32", + "ETSI", "2.4G", "20M", "OFDM", "1T", "03", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "03", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "04", "32", + "ETSI", "2.4G", "20M", "OFDM", "1T", "04", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "04", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "05", "32", + "ETSI", "2.4G", "20M", "OFDM", "1T", "05", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "05", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "06", "32", + "ETSI", "2.4G", "20M", "OFDM", "1T", "06", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "06", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "07", "32", + "ETSI", "2.4G", "20M", "OFDM", "1T", "07", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "07", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "08", "32", + "ETSI", "2.4G", "20M", "OFDM", "1T", "08", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "08", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "09", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "09", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "09", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "10", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "10", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "10", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "11", "30", + "ETSI", "2.4G", "20M", "OFDM", "1T", "11", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "11", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "12", "63", + "ETSI", "2.4G", "20M", "OFDM", "1T", "12", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "12", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "13", "63", + "ETSI", "2.4G", "20M", "OFDM", "1T", "13", "32", + "MKK", "2.4G", "20M", "OFDM", "1T", "13", "32", + "FCC", "2.4G", "20M", "OFDM", "1T", "14", "63", + "ETSI", "2.4G", "20M", "OFDM", "1T", "14", "63", + "MKK", "2.4G", "20M", "OFDM", "1T", "14", "63", + "FCC", "2.4G", "20M", "HT", "1T", "01", "26", + "ETSI", "2.4G", "20M", "HT", "1T", "01", "32", + "MKK", "2.4G", "20M", "HT", "1T", "01", "32", + "FCC", "2.4G", "20M", "HT", "1T", "02", "26", + "ETSI", "2.4G", "20M", "HT", "1T", "02", "32", + "MKK", "2.4G", "20M", "HT", "1T", "02", "32", + "FCC", "2.4G", "20M", "HT", "1T", "03", "32", + "ETSI", "2.4G", "20M", "HT", "1T", "03", "32", + "MKK", "2.4G", "20M", "HT", "1T", "03", "32", + "FCC", "2.4G", "20M", "HT", "1T", "04", "32", + "ETSI", "2.4G", "20M", "HT", "1T", "04", "32", + "MKK", "2.4G", "20M", "HT", "1T", "04", "32", + "FCC", "2.4G", "20M", "HT", "1T", "05", "32", + "ETSI", "2.4G", "20M", "HT", "1T", "05", "32", + "MKK", "2.4G", "20M", "HT", "1T", "05", "32", + "FCC", "2.4G", "20M", "HT", "1T", "06", "32", + "ETSI", "2.4G", "20M", "HT", "1T", "06", "32", + "MKK", "2.4G", "20M", "HT", "1T", "06", "32", + "FCC", "2.4G", "20M", "HT", "1T", "07", "32", + "ETSI", "2.4G", "20M", "HT", "1T", "07", "32", + "MKK", "2.4G", "20M", "HT", "1T", "07", "32", + "FCC", "2.4G", "20M", "HT", "1T", "08", "32", + "ETSI", "2.4G", "20M", "HT", "1T", "08", "32", + "MKK", "2.4G", "20M", "HT", "1T", "08", "32", + "FCC", "2.4G", "20M", "HT", "1T", "09", "26", + "ETSI", "2.4G", "20M", "HT", "1T", "09", "32", + "MKK", "2.4G", "20M", "HT", "1T", "09", "32", + "FCC", "2.4G", "20M", "HT", "1T", "10", "26", + "ETSI", "2.4G", "20M", "HT", "1T", "10", "32", + "MKK", "2.4G", "20M", "HT", "1T", "10", "32", + "FCC", "2.4G", "20M", "HT", "1T", "11", "26", + "ETSI", "2.4G", "20M", "HT", "1T", "11", "32", + "MKK", "2.4G", "20M", "HT", "1T", "11", "32", + "FCC", "2.4G", "20M", "HT", "1T", "12", "63", + "ETSI", "2.4G", "20M", "HT", "1T", "12", "32", + "MKK", "2.4G", "20M", "HT", "1T", "12", "32", + "FCC", "2.4G", "20M", "HT", "1T", "13", "63", + "ETSI", "2.4G", "20M", "HT", "1T", "13", "32", + "MKK", "2.4G", "20M", "HT", "1T", "13", "32", + "FCC", "2.4G", "20M", "HT", "1T", "14", "63", + "ETSI", "2.4G", "20M", "HT", "1T", "14", "63", + "MKK", "2.4G", "20M", "HT", "1T", "14", "63", + "FCC", "2.4G", "20M", "HT", "2T", "01", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "01", "32", + "MKK", "2.4G", "20M", "HT", "2T", "01", "32", + "FCC", "2.4G", "20M", "HT", "2T", "02", "32", + "ETSI", "2.4G", "20M", "HT", "2T", "02", "32", + "MKK", "2.4G", "20M", "HT", "2T", "02", "32", + "FCC", "2.4G", "20M", "HT", "2T", "03", "32", + "ETSI", "2.4G", "20M", "HT", "2T", "03", "32", + "MKK", "2.4G", "20M", "HT", "2T", "03", "32", + "FCC", "2.4G", "20M", "HT", "2T", "04", "32", + "ETSI", "2.4G", "20M", "HT", "2T", "04", "32", + "MKK", "2.4G", "20M", "HT", "2T", "04", "32", + "FCC", "2.4G", "20M", "HT", "2T", "05", "32", + "ETSI", "2.4G", "20M", "HT", "2T", "05", "32", + "MKK", "2.4G", "20M", "HT", "2T", "05", "32", + "FCC", "2.4G", "20M", "HT", "2T", "06", "32", + "ETSI", "2.4G", "20M", "HT", "2T", "06", "32", + "MKK", "2.4G", "20M", "HT", "2T", "06", "32", + "FCC", "2.4G", "20M", "HT", "2T", "07", "32", + "ETSI", "2.4G", "20M", "HT", "2T", "07", "32", + "MKK", "2.4G", "20M", "HT", "2T", "07", "32", + "FCC", "2.4G", "20M", "HT", "2T", "08", "32", + "ETSI", "2.4G", "20M", "HT", "2T", "08", "32", + "MKK", "2.4G", "20M", "HT", "2T", "08", "32", + "FCC", "2.4G", "20M", "HT", "2T", "09", "32", + "ETSI", "2.4G", "20M", "HT", "2T", "09", "32", + "MKK", "2.4G", "20M", "HT", "2T", "09", "32", + "FCC", "2.4G", "20M", "HT", "2T", "10", "32", + "ETSI", "2.4G", "20M", "HT", "2T", "10", "32", + "MKK", "2.4G", "20M", "HT", "2T", "10", "32", + "FCC", "2.4G", "20M", "HT", "2T", "11", "30", + "ETSI", "2.4G", "20M", "HT", "2T", "11", "32", + "MKK", "2.4G", "20M", "HT", "2T", "11", "32", + "FCC", "2.4G", "20M", "HT", "2T", "12", "63", + "ETSI", "2.4G", "20M", "HT", "2T", "12", "32", + "MKK", "2.4G", "20M", "HT", "2T", "12", "32", + "FCC", "2.4G", "20M", "HT", "2T", "13", "63", + "ETSI", "2.4G", "20M", "HT", "2T", "13", "32", + "MKK", "2.4G", "20M", "HT", "2T", "13", "32", + "FCC", "2.4G", "20M", "HT", "2T", "14", "63", + "ETSI", "2.4G", "20M", "HT", "2T", "14", "63", + "MKK", "2.4G", "20M", "HT", "2T", "14", "63", + "FCC", "2.4G", "40M", "HT", "1T", "01", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "01", "63", + "MKK", "2.4G", "40M", "HT", "1T", "01", "63", + "FCC", "2.4G", "40M", "HT", "1T", "02", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "02", "63", + "MKK", "2.4G", "40M", "HT", "1T", "02", "63", + "FCC", "2.4G", "40M", "HT", "1T", "03", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "03", "32", + "MKK", "2.4G", "40M", "HT", "1T", "03", "32", + "FCC", "2.4G", "40M", "HT", "1T", "04", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "04", "32", + "MKK", "2.4G", "40M", "HT", "1T", "04", "32", + "FCC", "2.4G", "40M", "HT", "1T", "05", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "05", "32", + "MKK", "2.4G", "40M", "HT", "1T", "05", "32", + "FCC", "2.4G", "40M", "HT", "1T", "06", "32", + "ETSI", "2.4G", "40M", "HT", "1T", "06", "32", + "MKK", "2.4G", "40M", "HT", "1T", "06", "32", + "FCC", "2.4G", "40M", "HT", "1T", "07", "32", + "ETSI", "2.4G", "40M", "HT", "1T", "07", "32", + "MKK", "2.4G", "40M", "HT", "1T", "07", "32", + "FCC", "2.4G", "40M", "HT", "1T", "08", "32", + "ETSI", "2.4G", "40M", "HT", "1T", "08", "32", + "MKK", "2.4G", "40M", "HT", "1T", "08", "32", + "FCC", "2.4G", "40M", "HT", "1T", "09", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "09", "32", + "MKK", "2.4G", "40M", "HT", "1T", "09", "32", + "FCC", "2.4G", "40M", "HT", "1T", "10", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "10", "32", + "MKK", "2.4G", "40M", "HT", "1T", "10", "32", + "FCC", "2.4G", "40M", "HT", "1T", "11", "26", + "ETSI", "2.4G", "40M", "HT", "1T", "11", "32", + "MKK", "2.4G", "40M", "HT", "1T", "11", "32", + "FCC", "2.4G", "40M", "HT", "1T", "12", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "12", "32", + "MKK", "2.4G", "40M", "HT", "1T", "12", "32", + "FCC", "2.4G", "40M", "HT", "1T", "13", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "13", "32", + "MKK", "2.4G", "40M", "HT", "1T", "13", "32", + "FCC", "2.4G", "40M", "HT", "1T", "14", "63", + "ETSI", "2.4G", "40M", "HT", "1T", "14", "63", + "MKK", "2.4G", "40M", "HT", "1T", "14", "63", + "FCC", "2.4G", "40M", "HT", "2T", "01", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "01", "63", + "MKK", "2.4G", "40M", "HT", "2T", "01", "63", + "FCC", "2.4G", "40M", "HT", "2T", "02", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "02", "63", + "MKK", "2.4G", "40M", "HT", "2T", "02", "63", + "FCC", "2.4G", "40M", "HT", "2T", "03", "30", + "ETSI", "2.4G", "40M", "HT", "2T", "03", "30", + "MKK", "2.4G", "40M", "HT", "2T", "03", "30", + "FCC", "2.4G", "40M", "HT", "2T", "04", "32", + "ETSI", "2.4G", "40M", "HT", "2T", "04", "30", + "MKK", "2.4G", "40M", "HT", "2T", "04", "30", + "FCC", "2.4G", "40M", "HT", "2T", "05", "32", + "ETSI", "2.4G", "40M", "HT", "2T", "05", "30", + "MKK", "2.4G", "40M", "HT", "2T", "05", "30", + "FCC", "2.4G", "40M", "HT", "2T", "06", "32", + "ETSI", "2.4G", "40M", "HT", "2T", "06", "30", + "MKK", "2.4G", "40M", "HT", "2T", "06", "30", + "FCC", "2.4G", "40M", "HT", "2T", "07", "32", + "ETSI", "2.4G", "40M", "HT", "2T", "07", "30", + "MKK", "2.4G", "40M", "HT", "2T", "07", "30", + "FCC", "2.4G", "40M", "HT", "2T", "08", "32", + "ETSI", "2.4G", "40M", "HT", "2T", "08", "30", + "MKK", "2.4G", "40M", "HT", "2T", "08", "30", + "FCC", "2.4G", "40M", "HT", "2T", "09", "32", + "ETSI", "2.4G", "40M", "HT", "2T", "09", "30", + "MKK", "2.4G", "40M", "HT", "2T", "09", "30", + "FCC", "2.4G", "40M", "HT", "2T", "10", "32", + "ETSI", "2.4G", "40M", "HT", "2T", "10", "30", + "MKK", "2.4G", "40M", "HT", "2T", "10", "30", + "FCC", "2.4G", "40M", "HT", "2T", "11", "30", + "ETSI", "2.4G", "40M", "HT", "2T", "11", "30", + "MKK", "2.4G", "40M", "HT", "2T", "11", "30", + "FCC", "2.4G", "40M", "HT", "2T", "12", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "12", "32", + "MKK", "2.4G", "40M", "HT", "2T", "12", "32", + "FCC", "2.4G", "40M", "HT", "2T", "13", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "13", "32", + "MKK", "2.4G", "40M", "HT", "2T", "13", "32", + "FCC", "2.4G", "40M", "HT", "2T", "14", "63", + "ETSI", "2.4G", "40M", "HT", "2T", "14", "63", + "MKK", "2.4G", "40M", "HT", "2T", "14", "63", + "FCC", "5G", "20M", "OFDM", "1T", "36", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "36", "30", + "MKK", "5G", "20M", "OFDM", "1T", "36", "30", + "FCC", "5G", "20M", "OFDM", "1T", "40", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "40", "30", + "MKK", "5G", "20M", "OFDM", "1T", "40", "30", + "FCC", "5G", "20M", "OFDM", "1T", "44", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "44", "30", + "MKK", "5G", "20M", "OFDM", "1T", "44", "30", + "FCC", "5G", "20M", "OFDM", "1T", "48", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "48", "30", + "MKK", "5G", "20M", "OFDM", "1T", "48", "30", + "FCC", "5G", "20M", "OFDM", "1T", "52", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "52", "30", + "MKK", "5G", "20M", "OFDM", "1T", "52", "30", + "FCC", "5G", "20M", "OFDM", "1T", "56", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "56", "30", + "MKK", "5G", "20M", "OFDM", "1T", "56", "30", + "FCC", "5G", "20M", "OFDM", "1T", "60", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "60", "30", + "MKK", "5G", "20M", "OFDM", "1T", "60", "30", + "FCC", "5G", "20M", "OFDM", "1T", "64", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "64", "30", + "MKK", "5G", "20M", "OFDM", "1T", "64", "30", + "FCC", "5G", "20M", "OFDM", "1T", "100", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "100", "30", + "MKK", "5G", "20M", "OFDM", "1T", "100", "30", + "FCC", "5G", "20M", "OFDM", "1T", "114", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "114", "30", + "MKK", "5G", "20M", "OFDM", "1T", "114", "30", + "FCC", "5G", "20M", "OFDM", "1T", "108", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "108", "30", + "MKK", "5G", "20M", "OFDM", "1T", "108", "30", + "FCC", "5G", "20M", "OFDM", "1T", "112", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "112", "30", + "MKK", "5G", "20M", "OFDM", "1T", "112", "30", + "FCC", "5G", "20M", "OFDM", "1T", "116", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "116", "30", + "MKK", "5G", "20M", "OFDM", "1T", "116", "30", + "FCC", "5G", "20M", "OFDM", "1T", "120", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "120", "30", + "MKK", "5G", "20M", "OFDM", "1T", "120", "30", + "FCC", "5G", "20M", "OFDM", "1T", "124", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "124", "30", + "MKK", "5G", "20M", "OFDM", "1T", "124", "30", + "FCC", "5G", "20M", "OFDM", "1T", "128", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "128", "30", + "MKK", "5G", "20M", "OFDM", "1T", "128", "30", + "FCC", "5G", "20M", "OFDM", "1T", "132", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "132", "30", + "MKK", "5G", "20M", "OFDM", "1T", "132", "30", + "FCC", "5G", "20M", "OFDM", "1T", "136", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "136", "30", + "MKK", "5G", "20M", "OFDM", "1T", "136", "30", + "FCC", "5G", "20M", "OFDM", "1T", "140", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "140", "30", + "MKK", "5G", "20M", "OFDM", "1T", "140", "30", + "FCC", "5G", "20M", "OFDM", "1T", "149", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "149", "30", + "MKK", "5G", "20M", "OFDM", "1T", "149", "63", + "FCC", "5G", "20M", "OFDM", "1T", "153", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "153", "30", + "MKK", "5G", "20M", "OFDM", "1T", "153", "63", + "FCC", "5G", "20M", "OFDM", "1T", "157", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "157", "30", + "MKK", "5G", "20M", "OFDM", "1T", "157", "63", + "FCC", "5G", "20M", "OFDM", "1T", "161", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "161", "30", + "MKK", "5G", "20M", "OFDM", "1T", "161", "63", + "FCC", "5G", "20M", "OFDM", "1T", "165", "32", + "ETSI", "5G", "20M", "OFDM", "1T", "165", "30", + "MKK", "5G", "20M", "OFDM", "1T", "165", "63", + "FCC", "5G", "20M", "HT", "1T", "36", "32", + "ETSI", "5G", "20M", "HT", "1T", "36", "30", + "MKK", "5G", "20M", "HT", "1T", "36", "30", + "FCC", "5G", "20M", "HT", "1T", "40", "32", + "ETSI", "5G", "20M", "HT", "1T", "40", "30", + "MKK", "5G", "20M", "HT", "1T", "40", "30", + "FCC", "5G", "20M", "HT", "1T", "44", "32", + "ETSI", "5G", "20M", "HT", "1T", "44", "30", + "MKK", "5G", "20M", "HT", "1T", "44", "30", + "FCC", "5G", "20M", "HT", "1T", "48", "32", + "ETSI", "5G", "20M", "HT", "1T", "48", "30", + "MKK", "5G", "20M", "HT", "1T", "48", "30", + "FCC", "5G", "20M", "HT", "1T", "52", "32", + "ETSI", "5G", "20M", "HT", "1T", "52", "30", + "MKK", "5G", "20M", "HT", "1T", "52", "30", + "FCC", "5G", "20M", "HT", "1T", "56", "32", + "ETSI", "5G", "20M", "HT", "1T", "56", "30", + "MKK", "5G", "20M", "HT", "1T", "56", "30", + "FCC", "5G", "20M", "HT", "1T", "60", "32", + "ETSI", "5G", "20M", "HT", "1T", "60", "30", + "MKK", "5G", "20M", "HT", "1T", "60", "30", + "FCC", "5G", "20M", "HT", "1T", "64", "32", + "ETSI", "5G", "20M", "HT", "1T", "64", "30", + "MKK", "5G", "20M", "HT", "1T", "64", "30", + "FCC", "5G", "20M", "HT", "1T", "100", "32", + "ETSI", "5G", "20M", "HT", "1T", "100", "30", + "MKK", "5G", "20M", "HT", "1T", "100", "30", + "FCC", "5G", "20M", "HT", "1T", "114", "32", + "ETSI", "5G", "20M", "HT", "1T", "114", "30", + "MKK", "5G", "20M", "HT", "1T", "114", "30", + "FCC", "5G", "20M", "HT", "1T", "108", "32", + "ETSI", "5G", "20M", "HT", "1T", "108", "30", + "MKK", "5G", "20M", "HT", "1T", "108", "30", + "FCC", "5G", "20M", "HT", "1T", "112", "32", + "ETSI", "5G", "20M", "HT", "1T", "112", "30", + "MKK", "5G", "20M", "HT", "1T", "112", "30", + "FCC", "5G", "20M", "HT", "1T", "116", "32", + "ETSI", "5G", "20M", "HT", "1T", "116", "30", + "MKK", "5G", "20M", "HT", "1T", "116", "30", + "FCC", "5G", "20M", "HT", "1T", "120", "32", + "ETSI", "5G", "20M", "HT", "1T", "120", "30", + "MKK", "5G", "20M", "HT", "1T", "120", "30", + "FCC", "5G", "20M", "HT", "1T", "124", "32", + "ETSI", "5G", "20M", "HT", "1T", "124", "30", + "MKK", "5G", "20M", "HT", "1T", "124", "30", + "FCC", "5G", "20M", "HT", "1T", "128", "32", + "ETSI", "5G", "20M", "HT", "1T", "128", "30", + "MKK", "5G", "20M", "HT", "1T", "128", "30", + "FCC", "5G", "20M", "HT", "1T", "132", "32", + "ETSI", "5G", "20M", "HT", "1T", "132", "30", + "MKK", "5G", "20M", "HT", "1T", "132", "30", + "FCC", "5G", "20M", "HT", "1T", "136", "32", + "ETSI", "5G", "20M", "HT", "1T", "136", "30", + "MKK", "5G", "20M", "HT", "1T", "136", "30", + "FCC", "5G", "20M", "HT", "1T", "140", "32", + "ETSI", "5G", "20M", "HT", "1T", "140", "30", + "MKK", "5G", "20M", "HT", "1T", "140", "30", + "FCC", "5G", "20M", "HT", "1T", "149", "32", + "ETSI", "5G", "20M", "HT", "1T", "149", "30", + "MKK", "5G", "20M", "HT", "1T", "149", "63", + "FCC", "5G", "20M", "HT", "1T", "153", "32", + "ETSI", "5G", "20M", "HT", "1T", "153", "30", + "MKK", "5G", "20M", "HT", "1T", "153", "63", + "FCC", "5G", "20M", "HT", "1T", "157", "32", + "ETSI", "5G", "20M", "HT", "1T", "157", "30", + "MKK", "5G", "20M", "HT", "1T", "157", "63", + "FCC", "5G", "20M", "HT", "1T", "161", "32", + "ETSI", "5G", "20M", "HT", "1T", "161", "30", + "MKK", "5G", "20M", "HT", "1T", "161", "63", + "FCC", "5G", "20M", "HT", "1T", "165", "32", + "ETSI", "5G", "20M", "HT", "1T", "165", "30", + "MKK", "5G", "20M", "HT", "1T", "165", "63", + "FCC", "5G", "20M", "HT", "2T", "36", "28", + "ETSI", "5G", "20M", "HT", "2T", "36", "30", + "MKK", "5G", "20M", "HT", "2T", "36", "30", + "FCC", "5G", "20M", "HT", "2T", "40", "28", + "ETSI", "5G", "20M", "HT", "2T", "40", "30", + "MKK", "5G", "20M", "HT", "2T", "40", "30", + "FCC", "5G", "20M", "HT", "2T", "44", "28", + "ETSI", "5G", "20M", "HT", "2T", "44", "30", + "MKK", "5G", "20M", "HT", "2T", "44", "30", + "FCC", "5G", "20M", "HT", "2T", "48", "28", + "ETSI", "5G", "20M", "HT", "2T", "48", "30", + "MKK", "5G", "20M", "HT", "2T", "48", "30", + "FCC", "5G", "20M", "HT", "2T", "52", "34", + "ETSI", "5G", "20M", "HT", "2T", "52", "30", + "MKK", "5G", "20M", "HT", "2T", "52", "30", + "FCC", "5G", "20M", "HT", "2T", "56", "32", + "ETSI", "5G", "20M", "HT", "2T", "56", "30", + "MKK", "5G", "20M", "HT", "2T", "56", "30", + "FCC", "5G", "20M", "HT", "2T", "60", "30", + "ETSI", "5G", "20M", "HT", "2T", "60", "30", + "MKK", "5G", "20M", "HT", "2T", "60", "30", + "FCC", "5G", "20M", "HT", "2T", "64", "26", + "ETSI", "5G", "20M", "HT", "2T", "64", "30", + "MKK", "5G", "20M", "HT", "2T", "64", "30", + "FCC", "5G", "20M", "HT", "2T", "100", "28", + "ETSI", "5G", "20M", "HT", "2T", "100", "30", + "MKK", "5G", "20M", "HT", "2T", "100", "30", + "FCC", "5G", "20M", "HT", "2T", "114", "28", + "ETSI", "5G", "20M", "HT", "2T", "114", "30", + "MKK", "5G", "20M", "HT", "2T", "114", "30", + "FCC", "5G", "20M", "HT", "2T", "108", "30", + "ETSI", "5G", "20M", "HT", "2T", "108", "30", + "MKK", "5G", "20M", "HT", "2T", "108", "30", + "FCC", "5G", "20M", "HT", "2T", "112", "32", + "ETSI", "5G", "20M", "HT", "2T", "112", "30", + "MKK", "5G", "20M", "HT", "2T", "112", "30", + "FCC", "5G", "20M", "HT", "2T", "116", "32", + "ETSI", "5G", "20M", "HT", "2T", "116", "30", + "MKK", "5G", "20M", "HT", "2T", "116", "30", + "FCC", "5G", "20M", "HT", "2T", "120", "34", + "ETSI", "5G", "20M", "HT", "2T", "120", "30", + "MKK", "5G", "20M", "HT", "2T", "120", "30", + "FCC", "5G", "20M", "HT", "2T", "124", "32", + "ETSI", "5G", "20M", "HT", "2T", "124", "30", + "MKK", "5G", "20M", "HT", "2T", "124", "30", + "FCC", "5G", "20M", "HT", "2T", "128", "30", + "ETSI", "5G", "20M", "HT", "2T", "128", "30", + "MKK", "5G", "20M", "HT", "2T", "128", "30", + "FCC", "5G", "20M", "HT", "2T", "132", "28", + "ETSI", "5G", "20M", "HT", "2T", "132", "30", + "MKK", "5G", "20M", "HT", "2T", "132", "30", + "FCC", "5G", "20M", "HT", "2T", "136", "28", + "ETSI", "5G", "20M", "HT", "2T", "136", "30", + "MKK", "5G", "20M", "HT", "2T", "136", "30", + "FCC", "5G", "20M", "HT", "2T", "140", "26", + "ETSI", "5G", "20M", "HT", "2T", "140", "30", + "MKK", "5G", "20M", "HT", "2T", "140", "30", + "FCC", "5G", "20M", "HT", "2T", "149", "34", + "ETSI", "5G", "20M", "HT", "2T", "149", "30", + "MKK", "5G", "20M", "HT", "2T", "149", "63", + "FCC", "5G", "20M", "HT", "2T", "153", "34", + "ETSI", "5G", "20M", "HT", "2T", "153", "30", + "MKK", "5G", "20M", "HT", "2T", "153", "63", + "FCC", "5G", "20M", "HT", "2T", "157", "34", + "ETSI", "5G", "20M", "HT", "2T", "157", "30", + "MKK", "5G", "20M", "HT", "2T", "157", "63", + "FCC", "5G", "20M", "HT", "2T", "161", "34", + "ETSI", "5G", "20M", "HT", "2T", "161", "30", + "MKK", "5G", "20M", "HT", "2T", "161", "63", + "FCC", "5G", "20M", "HT", "2T", "165", "34", + "ETSI", "5G", "20M", "HT", "2T", "165", "30", + "MKK", "5G", "20M", "HT", "2T", "165", "63", + "FCC", "5G", "40M", "HT", "1T", "38", "26", + "ETSI", "5G", "40M", "HT", "1T", "38", "30", + "MKK", "5G", "40M", "HT", "1T", "38", "30", + "FCC", "5G", "40M", "HT", "1T", "46", "32", + "ETSI", "5G", "40M", "HT", "1T", "46", "30", + "MKK", "5G", "40M", "HT", "1T", "46", "30", + "FCC", "5G", "40M", "HT", "1T", "54", "32", + "ETSI", "5G", "40M", "HT", "1T", "54", "30", + "MKK", "5G", "40M", "HT", "1T", "54", "30", + "FCC", "5G", "40M", "HT", "1T", "62", "24", + "ETSI", "5G", "40M", "HT", "1T", "62", "30", + "MKK", "5G", "40M", "HT", "1T", "62", "30", + "FCC", "5G", "40M", "HT", "1T", "102", "24", + "ETSI", "5G", "40M", "HT", "1T", "102", "30", + "MKK", "5G", "40M", "HT", "1T", "102", "30", + "FCC", "5G", "40M", "HT", "1T", "110", "32", + "ETSI", "5G", "40M", "HT", "1T", "110", "30", + "MKK", "5G", "40M", "HT", "1T", "110", "30", + "FCC", "5G", "40M", "HT", "1T", "118", "32", + "ETSI", "5G", "40M", "HT", "1T", "118", "30", + "MKK", "5G", "40M", "HT", "1T", "118", "30", + "FCC", "5G", "40M", "HT", "1T", "126", "32", + "ETSI", "5G", "40M", "HT", "1T", "126", "30", + "MKK", "5G", "40M", "HT", "1T", "126", "30", + "FCC", "5G", "40M", "HT", "1T", "134", "32", + "ETSI", "5G", "40M", "HT", "1T", "134", "30", + "MKK", "5G", "40M", "HT", "1T", "134", "30", + "FCC", "5G", "40M", "HT", "1T", "151", "30", + "ETSI", "5G", "40M", "HT", "1T", "151", "30", + "MKK", "5G", "40M", "HT", "1T", "151", "63", + "FCC", "5G", "40M", "HT", "1T", "159", "32", + "ETSI", "5G", "40M", "HT", "1T", "159", "30", + "MKK", "5G", "40M", "HT", "1T", "159", "63", + "FCC", "5G", "40M", "HT", "2T", "38", "28", + "ETSI", "5G", "40M", "HT", "2T", "38", "30", + "MKK", "5G", "40M", "HT", "2T", "38", "30", + "FCC", "5G", "40M", "HT", "2T", "46", "28", + "ETSI", "5G", "40M", "HT", "2T", "46", "30", + "MKK", "5G", "40M", "HT", "2T", "46", "30", + "FCC", "5G", "40M", "HT", "2T", "54", "30", + "ETSI", "5G", "40M", "HT", "2T", "54", "30", + "MKK", "5G", "40M", "HT", "2T", "54", "30", + "FCC", "5G", "40M", "HT", "2T", "62", "30", + "ETSI", "5G", "40M", "HT", "2T", "62", "30", + "MKK", "5G", "40M", "HT", "2T", "62", "30", + "FCC", "5G", "40M", "HT", "2T", "102", "26", + "ETSI", "5G", "40M", "HT", "2T", "102", "30", + "MKK", "5G", "40M", "HT", "2T", "102", "30", + "FCC", "5G", "40M", "HT", "2T", "110", "30", + "ETSI", "5G", "40M", "HT", "2T", "110", "30", + "MKK", "5G", "40M", "HT", "2T", "110", "30", + "FCC", "5G", "40M", "HT", "2T", "118", "34", + "ETSI", "5G", "40M", "HT", "2T", "118", "30", + "MKK", "5G", "40M", "HT", "2T", "118", "30", + "FCC", "5G", "40M", "HT", "2T", "126", "32", + "ETSI", "5G", "40M", "HT", "2T", "126", "30", + "MKK", "5G", "40M", "HT", "2T", "126", "30", + "FCC", "5G", "40M", "HT", "2T", "134", "30", + "ETSI", "5G", "40M", "HT", "2T", "134", "30", + "MKK", "5G", "40M", "HT", "2T", "134", "30", + "FCC", "5G", "40M", "HT", "2T", "151", "34", + "ETSI", "5G", "40M", "HT", "2T", "151", "30", + "MKK", "5G", "40M", "HT", "2T", "151", "63", + "FCC", "5G", "40M", "HT", "2T", "159", "34", + "ETSI", "5G", "40M", "HT", "2T", "159", "30", + "MKK", "5G", "40M", "HT", "2T", "159", "63", + "FCC", "5G", "80M", "VHT", "1T", "42", "22", + "ETSI", "5G", "80M", "VHT", "1T", "42", "30", + "MKK", "5G", "80M", "VHT", "1T", "42", "30", + "FCC", "5G", "80M", "VHT", "1T", "58", "20", + "ETSI", "5G", "80M", "VHT", "1T", "58", "30", + "MKK", "5G", "80M", "VHT", "1T", "58", "30", + "FCC", "5G", "80M", "VHT", "1T", "106", "20", + "ETSI", "5G", "80M", "VHT", "1T", "106", "30", + "MKK", "5G", "80M", "VHT", "1T", "106", "30", + "FCC", "5G", "80M", "VHT", "1T", "122", "20", + "ETSI", "5G", "80M", "VHT", "1T", "122", "30", + "MKK", "5G", "80M", "VHT", "1T", "122", "30", + "FCC", "5G", "80M", "VHT", "1T", "155", "28", + "ETSI", "5G", "80M", "VHT", "1T", "155", "30", + "MKK", "5G", "80M", "VHT", "1T", "155", "63", + "FCC", "5G", "80M", "VHT", "2T", "42", "28", + "ETSI", "5G", "80M", "VHT", "2T", "42", "30", + "MKK", "5G", "80M", "VHT", "2T", "42", "30", + "FCC", "5G", "80M", "VHT", "2T", "58", "26", + "ETSI", "5G", "80M", "VHT", "2T", "58", "30", + "MKK", "5G", "80M", "VHT", "2T", "58", "30", + "FCC", "5G", "80M", "VHT", "2T", "106", "28", + "ETSI", "5G", "80M", "VHT", "2T", "106", "30", + "MKK", "5G", "80M", "VHT", "2T", "106", "30", + "FCC", "5G", "80M", "VHT", "2T", "122", "32", + "ETSI", "5G", "80M", "VHT", "2T", "122", "30", + "MKK", "5G", "80M", "VHT", "2T", "122", "30", + "FCC", "5G", "80M", "VHT", "2T", "155", "34", + "ETSI", "5G", "80M", "VHT", "2T", "155", "30", + "MKK", "5G", "80M", "VHT", "2T", "155", "63" +}; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h new file mode 100644 index 000000000000..24bcff6bc507 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Created on 2010/ 5/18, 1:41 + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8821AE_TABLE__H_ +#define __RTL8821AE_TABLE__H_ + +#include +#define RTL8821AEPHY_REG_1TARRAYLEN 344 +extern u32 RTL8821AE_PHY_REG_ARRAY[]; +#define RTL8812AEPHY_REG_1TARRAYLEN 490 +extern u32 RTL8812AE_PHY_REG_ARRAY[]; +#define RTL8821AEPHY_REG_ARRAY_PGLEN 90 +extern u32 RTL8821AE_PHY_REG_ARRAY_PG[]; +#define RTL8812AEPHY_REG_ARRAY_PGLEN 276 +extern u32 RTL8812AE_PHY_REG_ARRAY_PG[]; +/* #define RTL8723BE_RADIOA_1TARRAYLEN 206 */ +/* extern u8 *RTL8821AE_TXPWR_LMT_ARRAY[]; */ +#define RTL8812AE_RADIOA_1TARRAYLEN 1264 +extern u32 RTL8812AE_RADIOA_ARRAY[]; +#define RTL8812AE_RADIOB_1TARRAYLEN 1240 +extern u32 RTL8812AE_RADIOB_ARRAY[]; +#define RTL8821AE_RADIOA_1TARRAYLEN 1176 +extern u32 RTL8821AE_RADIOA_ARRAY[]; +#define RTL8821AEMAC_1T_ARRAYLEN 194 +extern u32 RTL8821AE_MAC_REG_ARRAY[]; +#define RTL8812AEMAC_1T_ARRAYLEN 214 +extern u32 RTL8812AE_MAC_REG_ARRAY[]; +#define RTL8821AEAGCTAB_1TARRAYLEN 382 +extern u32 RTL8821AE_AGC_TAB_ARRAY[]; +#define RTL8812AEAGCTAB_1TARRAYLEN 1312 +extern u32 RTL8812AE_AGC_TAB_ARRAY[]; +#define RTL8812AE_TXPWR_LMT_ARRAY_LEN 3948 +extern u8 *RTL8812AE_TXPWR_LMT[]; +#define RTL8821AE_TXPWR_LMT_ARRAY_LEN 3948 +extern u8 *RTL8821AE_TXPWR_LMT[]; +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c new file mode 100644 index 000000000000..174743aef943 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.c @@ -0,0 +1,1024 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "../stats.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "trx.h" +#include "led.h" +#include "dm.h" +#include "phy.h" +#include "fw.h" + +static u8 _rtl8821ae_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) +{ + __le16 fc = rtl_get_fc(skb); + + if (unlikely(ieee80211_is_beacon(fc))) + return QSLT_BEACON; + if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) + return QSLT_MGNT; + + return skb->priority; +} + +static u16 odm_cfo(char value) +{ + int ret_val; + + if (value < 0) { + ret_val = 0 - value; + ret_val = (ret_val << 1) + (ret_val >> 1); + /* set bit12 as 1 for negative cfo */ + ret_val = ret_val | BIT(12); + } else { + ret_val = value; + ret_val = (ret_val << 1) + (ret_val >> 1); + } + return ret_val; +} + +static u8 _rtl8821ae_evm_dbm_jaguar(char value) +{ + char ret_val = value; + + /* -33dB~0dB to 33dB ~ 0dB*/ + if (ret_val == -128) + ret_val = 127; + else if (ret_val < 0) + ret_val = 0 - ret_val; + + ret_val = ret_val >> 1; + return ret_val; +} + +static void query_rxphystatus(struct ieee80211_hw *hw, + struct rtl_stats *pstatus, u8 *pdesc, + struct rx_fwinfo_8821ae *p_drvinfo, + bool bpacket_match_bssid, + bool bpacket_toself, bool packet_beacon) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct phy_status_rpt *p_phystrpt = (struct phy_status_rpt *)p_drvinfo; + struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); + struct rtl_phy *rtlphy = &rtlpriv->phy; + char rx_pwr_all = 0, rx_pwr[4]; + u8 rf_rx_num = 0, evm, evmdbm, pwdb_all; + u8 i, max_spatial_stream; + u32 rssi, total_rssi = 0; + bool is_cck = pstatus->is_cck; + u8 lan_idx, vga_idx; + + /* Record it for next packet processing */ + pstatus->packet_matchbssid = bpacket_match_bssid; + pstatus->packet_toself = bpacket_toself; + pstatus->packet_beacon = packet_beacon; + pstatus->rx_mimo_signalquality[0] = -1; + pstatus->rx_mimo_signalquality[1] = -1; + + if (is_cck) { + u8 cck_highpwr; + u8 cck_agc_rpt; + + cck_agc_rpt = p_phystrpt->cfosho[0]; + + /* (1)Hardware does not provide RSSI for CCK + * (2)PWDB, Average PWDB cacluated by + * hardware (for rate adaptive) + */ + cck_highpwr = (u8)rtlphy->cck_high_power; + + lan_idx = ((cck_agc_rpt & 0xE0) >> 5); + vga_idx = (cck_agc_rpt & 0x1f); + if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE) { + switch (lan_idx) { + case 7: + if (vga_idx <= 27) + /*VGA_idx = 27~2*/ + rx_pwr_all = -100 + 2*(27-vga_idx); + else + rx_pwr_all = -100; + break; + case 6: + /*VGA_idx = 2~0*/ + rx_pwr_all = -48 + 2*(2-vga_idx); + break; + case 5: + /*VGA_idx = 7~5*/ + rx_pwr_all = -42 + 2*(7-vga_idx); + break; + case 4: + /*VGA_idx = 7~4*/ + rx_pwr_all = -36 + 2*(7-vga_idx); + break; + case 3: + /*VGA_idx = 7~0*/ + rx_pwr_all = -24 + 2*(7-vga_idx); + break; + case 2: + if (cck_highpwr) + /*VGA_idx = 5~0*/ + rx_pwr_all = -12 + 2*(5-vga_idx); + else + rx_pwr_all = -6 + 2*(5-vga_idx); + break; + case 1: + rx_pwr_all = 8-2*vga_idx; + break; + case 0: + rx_pwr_all = 14-2*vga_idx; + break; + default: + break; + } + rx_pwr_all += 6; + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + if (!cck_highpwr) { + if (pwdb_all >= 80) + pwdb_all = + ((pwdb_all - 80)<<1) + + ((pwdb_all - 80)>>1) + 80; + else if ((pwdb_all <= 78) && (pwdb_all >= 20)) + pwdb_all += 3; + if (pwdb_all > 100) + pwdb_all = 100; + } + } else { /* 8821 */ + char pout = -6; + + switch (lan_idx) { + case 5: + rx_pwr_all = pout - 32 - (2*vga_idx); + break; + case 4: + rx_pwr_all = pout - 24 - (2*vga_idx); + break; + case 2: + rx_pwr_all = pout - 11 - (2*vga_idx); + break; + case 1: + rx_pwr_all = pout + 5 - (2*vga_idx); + break; + case 0: + rx_pwr_all = pout + 21 - (2*vga_idx); + break; + } + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + } + + pstatus->rx_pwdb_all = pwdb_all; + pstatus->recvsignalpower = rx_pwr_all; + + /* (3) Get Signal Quality (EVM) */ + if (bpacket_match_bssid) { + u8 sq; + + if (pstatus->rx_pwdb_all > 40) { + sq = 100; + } else { + sq = p_phystrpt->pwdb_all; + if (sq > 64) + sq = 0; + else if (sq < 20) + sq = 100; + else + sq = ((64 - sq) * 100) / 44; + } + + pstatus->signalquality = sq; + pstatus->rx_mimo_signalquality[0] = sq; + pstatus->rx_mimo_signalquality[1] = -1; + } + } else { + /* (1)Get RSSI for HT rate */ + for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { + /* we will judge RF RX path now. */ + if (rtlpriv->dm.rfpath_rxenable[i]) + rf_rx_num++; + + rx_pwr[i] = (p_phystrpt->gain_trsw[i] & 0x7f) - 110; + + /* Translate DBM to percentage. */ + rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + + /* Get Rx snr value in DB */ + pstatus->rx_snr[i] = p_phystrpt->rxsnr[i] / 2; + rtlpriv->stats.rx_snr_db[i] = p_phystrpt->rxsnr[i] / 2; + + pstatus->cfo_short[i] = odm_cfo(p_phystrpt->cfosho[i]); + pstatus->cfo_tail[i] = odm_cfo(p_phystrpt->cfotail[i]); + /* Record Signal Strength for next packet */ + pstatus->rx_mimo_signalstrength[i] = (u8)rssi; + } + + /* (2)PWDB, Average PWDB cacluated by + * hardware (for rate adaptive) + */ + rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; + + pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); + pstatus->rx_pwdb_all = pwdb_all; + pstatus->rxpower = rx_pwr_all; + pstatus->recvsignalpower = rx_pwr_all; + + /* (3)EVM of HT rate */ + if ((pstatus->is_ht && pstatus->rate >= DESC_RATEMCS8 && + pstatus->rate <= DESC_RATEMCS15) || + (pstatus->is_vht && + pstatus->rate >= DESC_RATEVHT2SS_MCS0 && + pstatus->rate <= DESC_RATEVHT2SS_MCS9)) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + + for (i = 0; i < max_spatial_stream; i++) { + evm = rtl_evm_db_to_percentage(p_phystrpt->rxevm[i]); + evmdbm = _rtl8821ae_evm_dbm_jaguar(p_phystrpt->rxevm[i]); + + if (bpacket_match_bssid) { + /* Fill value in RFD, Get the first + * spatial stream only + */ + if (i == 0) + pstatus->signalquality = evm; + pstatus->rx_mimo_signalquality[i] = evm; + pstatus->rx_mimo_evm_dbm[i] = evmdbm; + } + } + if (bpacket_match_bssid) { + for (i = RF90_PATH_A; i <= RF90_PATH_B; i++) + rtl_priv(hw)->dm.cfo_tail[i] = + (char)p_phystrpt->cfotail[i]; + + rtl_priv(hw)->dm.packet_count++; + } + } + + /* UI BSS List signal strength(in percentage), + * make it good looking, from 0~100. + */ + if (is_cck) + pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, + pwdb_all)); + else if (rf_rx_num != 0) + pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, + total_rssi /= rf_rx_num)); + /*HW antenna diversity*/ + rtldm->fat_table.antsel_rx_keep_0 = p_phystrpt->antidx_anta; + rtldm->fat_table.antsel_rx_keep_1 = p_phystrpt->antidx_antb; +} + +static void translate_rx_signal_stuff(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct rtl_stats *pstatus, u8 *pdesc, + struct rx_fwinfo_8821ae *p_drvinfo) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); + struct ieee80211_hdr *hdr; + u8 *tmp_buf; + u8 *praddr; + u8 *psaddr; + __le16 fc; + u16 type; + bool packet_matchbssid, packet_toself, packet_beacon; + + tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; + + hdr = (struct ieee80211_hdr *)tmp_buf; + fc = hdr->frame_control; + type = WLAN_FC_GET_TYPE(hdr->frame_control); + praddr = hdr->addr1; + psaddr = ieee80211_get_SA(hdr); + ether_addr_copy(pstatus->psaddr, psaddr); + + packet_matchbssid = (!ieee80211_is_ctl(fc) && + (ether_addr_equal(mac->bssid, + ieee80211_has_tods(fc) ? + hdr->addr1 : + ieee80211_has_fromds(fc) ? + hdr->addr2 : hdr->addr3)) && + (!pstatus->hwerror) && + (!pstatus->crc) && (!pstatus->icv)); + + packet_toself = packet_matchbssid && + (ether_addr_equal(praddr, rtlefuse->dev_addr)); + + if (ieee80211_is_beacon(hdr->frame_control)) + packet_beacon = true; + else + packet_beacon = false; + + if (packet_beacon && packet_matchbssid) + rtl_priv(hw)->dm.dbginfo.num_qry_beacon_pkt++; + + if (packet_matchbssid && + ieee80211_is_data_qos(hdr->frame_control) && + !is_multicast_ether_addr(ieee80211_get_DA(hdr))) { + struct ieee80211_qos_hdr *hdr_qos = + (struct ieee80211_qos_hdr *)tmp_buf; + u16 tid = le16_to_cpu(hdr_qos->qos_ctrl) & 0xf; + + if (tid != 0 && tid != 3) + rtl_priv(hw)->dm.dbginfo.num_non_be_pkt++; + } + + query_rxphystatus(hw, pstatus, pdesc, p_drvinfo, + packet_matchbssid, packet_toself, + packet_beacon); + /*_rtl8821ae_smart_antenna(hw, pstatus); */ + rtl_process_phyinfo(hw, tmp_buf, pstatus); +} + +static void _rtl8821ae_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, + u8 *virtualaddress) +{ + u32 dwtmp = 0; + + memset(virtualaddress, 0, 8); + + SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); + if (ptcb_desc->empkt_num == 1) { + dwtmp = ptcb_desc->empkt_len[0]; + } else { + dwtmp = ptcb_desc->empkt_len[0]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0)+4; + dwtmp += ptcb_desc->empkt_len[1]; + } + SET_EARLYMODE_LEN0(virtualaddress, dwtmp); + + if (ptcb_desc->empkt_num <= 3) { + dwtmp = ptcb_desc->empkt_len[2]; + } else { + dwtmp = ptcb_desc->empkt_len[2]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0)+4; + dwtmp += ptcb_desc->empkt_len[3]; + } + SET_EARLYMODE_LEN1(virtualaddress, dwtmp); + if (ptcb_desc->empkt_num <= 5) { + dwtmp = ptcb_desc->empkt_len[4]; + } else { + dwtmp = ptcb_desc->empkt_len[4]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0)+4; + dwtmp += ptcb_desc->empkt_len[5]; + } + SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF); + SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4); + if (ptcb_desc->empkt_num <= 7) { + dwtmp = ptcb_desc->empkt_len[6]; + } else { + dwtmp = ptcb_desc->empkt_len[6]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0)+4; + dwtmp += ptcb_desc->empkt_len[7]; + } + SET_EARLYMODE_LEN3(virtualaddress, dwtmp); + if (ptcb_desc->empkt_num <= 9) { + dwtmp = ptcb_desc->empkt_len[8]; + } else { + dwtmp = ptcb_desc->empkt_len[8]; + dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0)+4; + dwtmp += ptcb_desc->empkt_len[9]; + } + SET_EARLYMODE_LEN4(virtualaddress, dwtmp); +} + +static bool rtl8821ae_get_rxdesc_is_ht(struct ieee80211_hw *hw, u8 *pdesc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 rx_rate = 0; + + rx_rate = GET_RX_DESC_RXMCS(pdesc); + + RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, "rx_rate=0x%02x.\n", rx_rate); + + if ((rx_rate >= DESC_RATEMCS0) && (rx_rate <= DESC_RATEMCS15)) + return true; + return false; +} + +static bool rtl8821ae_get_rxdesc_is_vht(struct ieee80211_hw *hw, u8 *pdesc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 rx_rate = 0; + + rx_rate = GET_RX_DESC_RXMCS(pdesc); + + RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, "rx_rate=0x%02x.\n", rx_rate); + + if (rx_rate >= DESC_RATEVHT1SS_MCS0) + return true; + return false; +} + +static u8 rtl8821ae_get_rx_vht_nss(struct ieee80211_hw *hw, u8 *pdesc) +{ + u8 rx_rate = 0; + u8 vht_nss = 0; + + rx_rate = GET_RX_DESC_RXMCS(pdesc); + if ((rx_rate >= DESC_RATEVHT1SS_MCS0) && + (rx_rate <= DESC_RATEVHT1SS_MCS9)) + vht_nss = 1; + else if ((rx_rate >= DESC_RATEVHT2SS_MCS0) && + (rx_rate <= DESC_RATEVHT2SS_MCS9)) + vht_nss = 2; + + return vht_nss; +} + +bool rtl8821ae_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *status, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rx_fwinfo_8821ae *p_drvinfo; + struct ieee80211_hdr *hdr; + + u32 phystatus = GET_RX_DESC_PHYST(pdesc); + + status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); + status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * + RX_DRV_INFO_SIZE_UNIT; + status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03); + status->icv = (u16)GET_RX_DESC_ICV(pdesc); + status->crc = (u16)GET_RX_DESC_CRC32(pdesc); + status->hwerror = (status->crc | status->icv); + status->decrypted = !GET_RX_DESC_SWDEC(pdesc); + status->rate = (u8)GET_RX_DESC_RXMCS(pdesc); + status->shortpreamble = (u16)GET_RX_DESC_SPLCP(pdesc); + status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); + status->isfirst_ampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); + status->timestamp_low = GET_RX_DESC_TSFL(pdesc); + status->rx_packet_bw = GET_RX_DESC_BW(pdesc); + status->macid = GET_RX_DESC_MACID(pdesc); + status->is_short_gi = !(bool)GET_RX_DESC_SPLCP(pdesc); + status->is_ht = rtl8821ae_get_rxdesc_is_ht(hw, pdesc); + status->is_vht = rtl8821ae_get_rxdesc_is_vht(hw, pdesc); + status->vht_nss = rtl8821ae_get_rx_vht_nss(hw, pdesc); + status->is_cck = RTL8821AE_RX_HAL_IS_CCK_RATE(status->rate); + + RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, + "rx_packet_bw=%s,is_ht %d, is_vht %d, vht_nss=%d,is_short_gi %d.\n", + (status->rx_packet_bw == 2) ? "80M" : + (status->rx_packet_bw == 1) ? "40M" : "20M", + status->is_ht, status->is_vht, status->vht_nss, + status->is_short_gi); + + if (GET_RX_STATUS_DESC_RPT_SEL(pdesc)) + status->packet_report_type = C2H_PACKET; + else + status->packet_report_type = NORMAL_RX; + + if (GET_RX_STATUS_DESC_PATTERN_MATCH(pdesc)) + status->wake_match = BIT(2); + else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) + status->wake_match = BIT(1); + else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) + status->wake_match = BIT(0); + else + status->wake_match = 0; + + if (status->wake_match) + RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, + "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n", + status->wake_match); + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + + hdr = (struct ieee80211_hdr *)(skb->data + + status->rx_drvinfo_size + status->rx_bufshift); + + if (status->crc) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + + if (status->rx_packet_bw == HT_CHANNEL_WIDTH_20_40) + rx_status->flag |= RX_FLAG_40MHZ; + else if (status->rx_packet_bw == HT_CHANNEL_WIDTH_80) + rx_status->vht_flag |= RX_VHT_FLAG_80MHZ; + if (status->is_ht) + rx_status->flag |= RX_FLAG_HT; + if (status->is_vht) + rx_status->flag |= RX_FLAG_VHT; + + if (status->is_short_gi) + rx_status->flag |= RX_FLAG_SHORT_GI; + + rx_status->vht_nss = status->vht_nss; + rx_status->flag |= RX_FLAG_MACTIME_START; + + /* hw will set status->decrypted true, if it finds the + * frame is open data frame or mgmt frame. + * So hw will not decryption robust managment frame + * for IEEE80211w but still set status->decrypted + * true, so here we should set it back to undecrypted + * for IEEE80211w frame, and mac80211 sw will help + * to decrypt it + */ + if (status->decrypted) { + if ((!_ieee80211_is_robust_mgmt_frame(hdr)) && + (ieee80211_has_protected(hdr->frame_control))) + rx_status->flag |= RX_FLAG_DECRYPTED; + else + rx_status->flag &= ~RX_FLAG_DECRYPTED; + } + + /* rate_idx: index of data rate into band's + * supported rates or MCS index if HT rates + * are use (RX_FLAG_HT) + */ + rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht, + status->is_vht, + status->rate); + + rx_status->mactime = status->timestamp_low; + if (phystatus) { + p_drvinfo = (struct rx_fwinfo_8821ae *)(skb->data + + status->rx_bufshift); + + translate_rx_signal_stuff(hw, skb, status, pdesc, p_drvinfo); + } + rx_status->signal = status->recvsignalpower + 10; + if (status->packet_report_type == TX_REPORT2) { + status->macid_valid_entry[0] = + GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); + status->macid_valid_entry[1] = + GET_RX_RPT2_DESC_MACID_VALID_2(pdesc); + } + return true; +} + +static u8 rtl8821ae_bw_mapping(struct ieee80211_hw *hw, + struct rtl_tcb_desc *ptcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + u8 bw_setting_of_desc = 0; + + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "rtl8821ae_bw_mapping, current_chan_bw %d, packet_bw %d\n", + rtlphy->current_chan_bw, ptcb_desc->packet_bw); + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) { + if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_80) + bw_setting_of_desc = 2; + else if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) + bw_setting_of_desc = 1; + else + bw_setting_of_desc = 0; + } else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + if ((ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) || + (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_80)) + bw_setting_of_desc = 1; + else + bw_setting_of_desc = 0; + } else { + bw_setting_of_desc = 0; + } + return bw_setting_of_desc; +} + +static u8 rtl8821ae_sc_mapping(struct ieee80211_hw *hw, + struct rtl_tcb_desc *ptcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &rtlpriv->phy; + struct rtl_mac *mac = rtl_mac(rtlpriv); + u8 sc_setting_of_desc = 0; + + if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) { + if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_80) { + sc_setting_of_desc = VHT_DATA_SC_DONOT_CARE; + } else if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { + if (mac->cur_80_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) + sc_setting_of_desc = + VHT_DATA_SC_40_LOWER_OF_80MHZ; + else if (mac->cur_80_prime_sc == + HAL_PRIME_CHNL_OFFSET_UPPER) + sc_setting_of_desc = + VHT_DATA_SC_40_UPPER_OF_80MHZ; + else + RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD, + "rtl8821ae_sc_mapping: Not Correct Primary40MHz Setting\n"); + } else { + if ((mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) && + (mac->cur_80_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER)) + sc_setting_of_desc = + VHT_DATA_SC_20_LOWEST_OF_80MHZ; + else if ((mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_UPPER) && + (mac->cur_80_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER)) + sc_setting_of_desc = + VHT_DATA_SC_20_LOWER_OF_80MHZ; + else if ((mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER) && + (mac->cur_80_prime_sc == + HAL_PRIME_CHNL_OFFSET_UPPER)) + sc_setting_of_desc = + VHT_DATA_SC_20_UPPER_OF_80MHZ; + else if ((mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_UPPER) && + (mac->cur_80_prime_sc == + HAL_PRIME_CHNL_OFFSET_UPPER)) + sc_setting_of_desc = + VHT_DATA_SC_20_UPPERST_OF_80MHZ; + else + RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD, + "rtl8821ae_sc_mapping: Not Correct Primary40MHz Setting\n"); + } + } else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { + if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { + sc_setting_of_desc = VHT_DATA_SC_DONOT_CARE; + } else if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20) { + if (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_UPPER) { + sc_setting_of_desc = + VHT_DATA_SC_20_UPPER_OF_80MHZ; + } else if (mac->cur_40_prime_sc == + HAL_PRIME_CHNL_OFFSET_LOWER){ + sc_setting_of_desc = + VHT_DATA_SC_20_LOWER_OF_80MHZ; + } else { + sc_setting_of_desc = VHT_DATA_SC_DONOT_CARE; + } + } + } else { + sc_setting_of_desc = VHT_DATA_SC_DONOT_CARE; + } + + return sc_setting_of_desc; +} + +void rtl8821ae_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, u8 *txbd, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); + u8 *pdesc = (u8 *)pdesc_tx; + u16 seq_number; + __le16 fc = hdr->frame_control; + unsigned int buf_len = 0; + unsigned int skb_len = skb->len; + u8 fw_qsel = _rtl8821ae_map_hwqueue_to_fwqueue(skb, hw_queue); + bool firstseg = ((hdr->seq_ctrl & + cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); + bool lastseg = ((hdr->frame_control & + cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); + dma_addr_t mapping; + u8 short_gi = 0; + + seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); + /* reserve 8 byte for AMPDU early mode */ + if (rtlhal->earlymode_enable) { + skb_push(skb, EM_HDR_LEN); + memset(skb->data, 0, EM_HDR_LEN); + } + buf_len = skb->len; + mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_8821ae)); + if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { + firstseg = true; + lastseg = true; + } + if (firstseg) { + if (rtlhal->earlymode_enable) { + SET_TX_DESC_PKT_OFFSET(pdesc, 1); + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + + EM_HDR_LEN); + if (ptcb_desc->empkt_num) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "Insert 8 byte.pTcb->EMPktNum:%d\n", + ptcb_desc->empkt_num); + _rtl8821ae_insert_emcontent(ptcb_desc, + (u8 *)(skb->data)); + } + } else { + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + } + + /* ptcb_desc->use_driver_rate = true; */ + SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); + if (ptcb_desc->hw_rate > DESC_RATEMCS0) + short_gi = (ptcb_desc->use_shortgi) ? 1 : 0; + else + short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0; + + SET_TX_DESC_DATA_SHORTGI(pdesc, short_gi); + + if (info->flags & IEEE80211_TX_CTL_AMPDU) { + SET_TX_DESC_AGG_ENABLE(pdesc, 1); + SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x1f); + } + SET_TX_DESC_SEQ(pdesc, seq_number); + SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && + !ptcb_desc->cts_enable) ? 1 : 0)); + SET_TX_DESC_HW_RTS_ENABLE(pdesc, 0); + SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); + + SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); + SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); + SET_TX_DESC_RTS_SHORT(pdesc, + ((ptcb_desc->rts_rate <= DESC_RATE54M) ? + (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : + (ptcb_desc->rts_use_shortgi ? 1 : 0))); + + if (ptcb_desc->tx_enable_sw_calc_duration) + SET_TX_DESC_NAV_USE_HDR(pdesc, 1); + + SET_TX_DESC_DATA_BW(pdesc, + rtl8821ae_bw_mapping(hw, ptcb_desc)); + + SET_TX_DESC_TX_SUB_CARRIER(pdesc, + rtl8821ae_sc_mapping(hw, ptcb_desc)); + + SET_TX_DESC_LINIP(pdesc, 0); + SET_TX_DESC_PKT_SIZE(pdesc, (u16)skb_len); + if (sta) { + u8 ampdu_density = sta->ht_cap.ampdu_density; + + SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); + } + if (info->control.hw_key) { + struct ieee80211_key_conf *keyconf = + info->control.hw_key; + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x1); + break; + case WLAN_CIPHER_SUITE_CCMP: + SET_TX_DESC_SEC_TYPE(pdesc, 0x3); + break; + default: + SET_TX_DESC_SEC_TYPE(pdesc, 0x0); + break; + } + } + + SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); + SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); + SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); + SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ? + 1 : 0); + SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); + + if (ieee80211_is_data_qos(fc)) { + if (mac->rdg_en) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "Enable RDG function.\n"); + SET_TX_DESC_RDG_ENABLE(pdesc, 1); + SET_TX_DESC_HTC(pdesc, 1); + } + } + } + + SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); + SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)buf_len); + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + /* if (rtlpriv->dm.useramask) { */ + if (1) { + SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); + } else { + SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); + SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); + } + if (!ieee80211_is_data_qos(fc)) { + SET_TX_DESC_HWSEQ_EN(pdesc, 1); + SET_TX_DESC_HWSEQ_SEL(pdesc, 0); + } + SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { + SET_TX_DESC_BMC(pdesc, 1); + } + + rtl8821ae_dm_set_tx_ant_by_tx_info(hw, pdesc, ptcb_desc->mac_id); + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); +} + +void rtl8821ae_tx_fill_cmddesc(struct ieee80211_hw *hw, + u8 *pdesc, bool firstseg, + bool lastseg, struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + u8 fw_queue = QSLT_BEACON; + + dma_addr_t mapping = pci_map_single(rtlpci->pdev, + skb->data, skb->len, + PCI_DMA_TODEVICE); + + if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, + "DMA mapping error"); + return; + } + CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); + + SET_TX_DESC_FIRST_SEG(pdesc, 1); + SET_TX_DESC_LAST_SEG(pdesc, 1); + + SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len)); + + SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); + + SET_TX_DESC_USE_RATE(pdesc, 1); + SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M); + SET_TX_DESC_DISABLE_FB(pdesc, 1); + + SET_TX_DESC_DATA_BW(pdesc, 0); + + SET_TX_DESC_HWSEQ_EN(pdesc, 1); + + SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); + + SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); + + SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); + + SET_TX_DESC_MACID(pdesc, 0); + + SET_TX_DESC_OWN(pdesc, 1); + + RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, + "H2C Tx Cmd Content\n", + pdesc, TX_DESC_SIZE); +} + +void rtl8821ae_set_desc(struct ieee80211_hw *hw, u8 *pdesc, + bool istx, u8 desc_name, u8 *val) +{ + if (istx) { + switch (desc_name) { + case HW_DESC_OWN: + SET_TX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_TX_NEXTDESC_ADDR: + SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *)val); + break; + default: + RT_ASSERT(false, + "ERR txdesc :%d not process\n", desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_RXOWN: + SET_RX_DESC_OWN(pdesc, 1); + break; + case HW_DESC_RXBUFF_ADDR: + SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *)val); + break; + case HW_DESC_RXPKT_LEN: + SET_RX_DESC_PKT_LEN(pdesc, *(u32 *)val); + break; + case HW_DESC_RXERO: + SET_RX_DESC_EOR(pdesc, 1); + break; + default: + RT_ASSERT(false, + "ERR rxdesc :%d not process\n", desc_name); + break; + } + } +} + +u32 rtl8821ae_get_desc(u8 *pdesc, bool istx, u8 desc_name) +{ + u32 ret = 0; + + if (istx) { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_TX_DESC_OWN(pdesc); + break; + case HW_DESC_TXBUFF_ADDR: + ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc); + break; + default: + RT_ASSERT(false, + "ERR txdesc :%d not process\n", desc_name); + break; + } + } else { + switch (desc_name) { + case HW_DESC_OWN: + ret = GET_RX_DESC_OWN(pdesc); + break; + case HW_DESC_RXPKT_LEN: + ret = GET_RX_DESC_PKT_LEN(pdesc); + break; + case HW_DESC_RXBUFF_ADDR: + ret = GET_RX_DESC_BUFF_ADDR(pdesc); + break; + default: + RT_ASSERT(false, + "ERR rxdesc :%d not process\n", desc_name); + break; + } + } + return ret; +} + +bool rtl8821ae_is_tx_desc_closed(struct ieee80211_hw *hw, + u8 hw_queue, u16 index) +{ + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; + u8 *entry = (u8 *)(&ring->desc[ring->idx]); + u8 own = (u8)rtl8821ae_get_desc(entry, true, HW_DESC_OWN); + + /** + *beacon packet will only use the first + *descriptor defautly,and the own may not + *be cleared by the hardware + */ + if (own) + return false; + return true; +} + +void rtl8821ae_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + if (hw_queue == BEACON_QUEUE) { + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); + } else { + rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, + BIT(0) << (hw_queue)); + } +} + +u32 rtl8821ae_rx_command_packet(struct ieee80211_hw *hw, + struct rtl_stats status, + struct sk_buff *skb) +{ + u32 result = 0; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + switch (status.packet_report_type) { + case NORMAL_RX: + result = 0; + break; + case C2H_PACKET: + rtl8821ae_c2h_packet_handler(hw, skb->data, (u8)skb->len); + result = 1; + RT_TRACE(rtlpriv, COMP_RECV, DBG_LOUD, + "skb->len=%d\n\n", skb->len); + break; + default: + RT_TRACE(rtlpriv, COMP_RECV, DBG_LOUD, + "No this packet type!!\n"); + break; + } + + return result; +} diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h new file mode 100644 index 000000000000..31409042d8dd --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h @@ -0,0 +1,620 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL8821AE_TRX_H__ +#define __RTL8821AE_TRX_H__ + +#define TX_DESC_SIZE 40 +#define TX_DESC_AGGR_SUBFRAME_SIZE 32 + +#define RX_DESC_SIZE 32 +#define RX_DRV_INFO_SIZE_UNIT 8 + +#define TX_DESC_NEXT_DESC_OFFSET 40 +#define USB_HWDESC_HEADER_LEN 40 +#define CRCLENGTH 4 + +#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) +#define SET_TX_DESC_OFFSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) +#define SET_TX_DESC_BMC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) +#define SET_TX_DESC_HTC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) +#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) +#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) +#define SET_TX_DESC_LINIP(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) +#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) +#define SET_TX_DESC_GF(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) +#define SET_TX_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +#define GET_TX_DESC_PKT_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 0, 16) +#define GET_TX_DESC_OFFSET(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 16, 8) +#define GET_TX_DESC_BMC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 24, 1) +#define GET_TX_DESC_HTC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 25, 1) +#define GET_TX_DESC_LAST_SEG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 26, 1) +#define GET_TX_DESC_FIRST_SEG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 27, 1) +#define GET_TX_DESC_LINIP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 28, 1) +#define GET_TX_DESC_NO_ACM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 29, 1) +#define GET_TX_DESC_GF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 30, 1) +#define GET_TX_DESC_OWN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 31, 1) + +#define SET_TX_DESC_MACID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 7, __val) +#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) +#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) +#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) +#define SET_TX_DESC_PIFS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) +#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 5, __val) +#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) +#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) +#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 5, __val) + +#define SET_TX_DESC_PAID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 9, __val) +#define SET_TX_DESC_CCA_RTS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 10, 2, __val) +#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val) +#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val) +#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val) +#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val) +#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) +#define SET_TX_DESC_RAW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) +#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) +#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) +#define SET_TX_DESC_BT_INT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val) +#define SET_TX_DESC_GID(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 6, __val) + +#define SET_TX_DESC_WHEADER_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 4, __val) +#define SET_TX_DESC_CHK_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 4, 1, __val) +#define SET_TX_DESC_EARLY_MODE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 5, 1, __val) +#define SET_TX_DESC_HWSEQ_SEL(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 6, 2, __val) +#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 1, __val) +#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 9, 1, __val) +#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 10, 1, __val) +#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 11, 1, __val) +#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 12, 1, __val) +#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 13, 1, __val) +#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 15, 1, __val) +#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 1, __val) +#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 17, 5, __val) +#define SET_TX_DESC_NDPA(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 22, 2, __val) +#define SET_TX_DESC_AMPDU_MAX_TIME(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+12, 24, 8, __val) +#define SET_TX_DESC_TX_ANT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 4, __val) + +#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 7, __val) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 5, __val) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 4, __val) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 17, 1, __val) +#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 6, __val) +#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 5, __val) + +#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 4, __val) +#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ + SET_BITS_TO_LE_1BYTE(__pdesc+20, 4, 1, __val) +#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 5, 2, __val) +#define SET_TX_DESC_DATA_LDPC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) +#define SET_TX_DESC_DATA_STBC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 2, __val) +#define SET_TX_DESC_CTROL_STBC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 10, 2, __val) +#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 12, 1, __val) +#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) + +#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) + +#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) + +#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+32, 15, 1, __val) + +#define SET_TX_DESC_SEQ(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+36, 12, 12, __val) + +#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) + +#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+40, 0, 32) + +#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+48, 0, 32, __val) + +#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+48, 0, 32) + +#define GET_RX_DESC_PKT_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 0, 14) +#define GET_RX_DESC_CRC32(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 14, 1) +#define GET_RX_DESC_ICV(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 15, 1) +#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 16, 4) +#define GET_RX_DESC_SECURITY(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 20, 3) +#define GET_RX_DESC_QOS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 23, 1) +#define GET_RX_DESC_SHIFT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 24, 2) +#define GET_RX_DESC_PHYST(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 26, 1) +#define GET_RX_DESC_SWDEC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 27, 1) +#define GET_RX_DESC_LS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 28, 1) +#define GET_RX_DESC_FS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 29, 1) +#define GET_RX_DESC_EOR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 30, 1) +#define GET_RX_DESC_OWN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc, 31, 1) + +#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) +#define SET_RX_DESC_EOR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) +#define SET_RX_DESC_OWN(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) + +#define GET_RX_DESC_MACID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 0, 7) +#define GET_RX_DESC_TID(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 8, 4) +#define GET_RX_DESC_AMSDU(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) +#define GET_RX_STATUS_DESC_RXID_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) +#define GET_RX_DESC_PAGGR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) +#define GET_RX_DESC_A1_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) +#define GET_RX_DESC_CHKERR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) +#define GET_RX_DESC_IPVER(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) +#define GET_RX_STATUS_DESC_IS_TCPUDP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 22, 1) +#define GET_RX_STATUS_DESC_CHK_VLD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 23, 1) +#define GET_RX_DESC_PAM(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) +#define GET_RX_DESC_PWR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) +#define GET_RX_DESC_MD(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) +#define GET_RX_DESC_MF(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) +#define GET_RX_DESC_TYPE(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) +#define GET_RX_DESC_MC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) +#define GET_RX_DESC_BC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) + +#define GET_RX_DESC_SEQ(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) +#define GET_RX_DESC_FRAG(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) +#define GET_RX_STATUS_DESC_RX_IS_QOS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 16, 1) +#define GET_RX_STATUS_DESC_WLANHD_IV_LEN(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 18, 6) +#define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+8, 28, 1) + +#define GET_RX_DESC_RXMCS(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 0, 7) +#define GET_RX_DESC_HTC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) +#define GET_RX_STATUS_DESC_EOSP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 11, 1) +#define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 12, 2) + +#define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 29, 1) +#define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 30, 1) +#define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+12, 31, 1) + +#define GET_RX_DESC_SPLCP(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 0, 1) +#define GET_RX_STATUS_DESC_LDPC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 1, 1) +#define GET_RX_STATUS_DESC_STBC(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 2, 1) +#define GET_RX_DESC_BW(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+16, 4, 2) + +#define GET_RX_DESC_TSFL(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) + +#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) +#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ + LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) + +#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) +#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ + SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) + +/* TX report 2 format in Rx desc*/ + +#define GET_RX_RPT2_DESC_PKT_LEN(__status) \ + LE_BITS_TO_4BYTE(__status, 0, 9) +#define GET_RX_RPT2_DESC_MACID_VALID_1(__status) \ + LE_BITS_TO_4BYTE(__status+16, 0, 32) +#define GET_RX_RPT2_DESC_MACID_VALID_2(__status) \ + LE_BITS_TO_4BYTE(__status+20, 0, 32) + +#define SET_EARLYMODE_PKTNUM(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __value) +#define SET_EARLYMODE_LEN0(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr, 4, 12, __value) +#define SET_EARLYMODE_LEN1(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr, 16, 12, __value) +#define SET_EARLYMODE_LEN2_1(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr, 28, 4, __value) +#define SET_EARLYMODE_LEN2_2(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __value) +#define SET_EARLYMODE_LEN3(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 8, 12, __value) +#define SET_EARLYMODE_LEN4(__paddr, __value) \ + SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __value) + +#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ +do { \ + if (_size > TX_DESC_NEXT_DESC_OFFSET) \ + memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ + else \ + memset(__pdesc, 0, _size); \ +} while (0) + +#define RTL8821AE_RX_HAL_IS_CCK_RATE(rxmcs)\ + (rxmcs == DESC_RATE1M ||\ + rxmcs == DESC_RATE2M ||\ + rxmcs == DESC_RATE5_5M ||\ + rxmcs == DESC_RATE11M) + +struct phy_rx_agc_info_t { + #ifdef __LITTLE_ENDIAN + u8 gain:7, trsw:1; + #else + u8 trsw:1, gain:7; + #endif +}; + +struct phy_status_rpt { + /* DWORD 0 */ + u8 gain_trsw[2]; +#ifdef __LITTLE_ENDIAN + u16 chl_num:10; + u16 sub_chnl:4; + u16 r_rfmod:2; +#else /* _BIG_ENDIAN_ */ + u16 r_rfmod:2; + u16 sub_chnl:4; + u16 chl_num:10; +#endif + /* DWORD 1 */ + u8 pwdb_all; + u8 cfosho[4]; /* DW 1 byte 1 DW 2 byte 0 */ + + /* DWORD 2 */ + char cfotail[4]; /* DW 2 byte 1 DW 3 byte 0 */ + + /* DWORD 3 */ + char rxevm[2]; /* DW 3 byte 1 DW 3 byte 2 */ + char rxsnr[2]; /* DW 3 byte 3 DW 4 byte 0 */ + + /* DWORD 4 */ + u8 pcts_msk_rpt[2]; + u8 pdsnr[2]; /* DW 4 byte 3 DW 5 Byte 0 */ + + /* DWORD 5 */ + u8 csi_current[2]; + u8 rx_gain_c; + + /* DWORD 6 */ + u8 rx_gain_d; + u8 sigevm; + u8 resvd_0; + u8 antidx_anta:3; + u8 antidx_antb:3; + u8 resvd_1:2; +} __packed; + +struct rx_fwinfo_8821ae { + u8 gain_trsw[4]; + u8 pwdb_all; + u8 cfosho[4]; + u8 cfotail[4]; + char rxevm[2]; + char rxsnr[4]; + u8 pdsnr[2]; + u8 csi_current[2]; + u8 csi_target[2]; + u8 sigevm; + u8 max_ex_pwr; + u8 ex_intf_flag:1; + u8 sgi_en:1; + u8 rxsc:2; + u8 reserve:4; +} __packed; + +struct tx_desc_8821ae { + u32 pktsize:16; + u32 offset:8; + u32 bmc:1; + u32 htc:1; + u32 lastseg:1; + u32 firstseg:1; + u32 linip:1; + u32 noacm:1; + u32 gf:1; + u32 own:1; + + u32 macid:6; + u32 rsvd0:2; + u32 queuesel:5; + u32 rd_nav_ext:1; + u32 lsig_txop_en:1; + u32 pifs:1; + u32 rateid:4; + u32 nav_usehdr:1; + u32 en_descid:1; + u32 sectype:2; + u32 pktoffset:8; + + u32 rts_rc:6; + u32 data_rc:6; + u32 agg_en:1; + u32 rdg_en:1; + u32 bar_retryht:2; + u32 agg_break:1; + u32 morefrag:1; + u32 raw:1; + u32 ccx:1; + u32 ampdudensity:3; + u32 bt_int:1; + u32 ant_sela:1; + u32 ant_selb:1; + u32 txant_cck:2; + u32 txant_l:2; + u32 txant_ht:2; + + u32 nextheadpage:8; + u32 tailpage:8; + u32 seq:12; + u32 cpu_handle:1; + u32 tag1:1; + u32 trigger_int:1; + u32 hwseq_en:1; + + u32 rtsrate:5; + u32 apdcfe:1; + u32 qos:1; + u32 hwseq_ssn:1; + u32 userrate:1; + u32 dis_rtsfb:1; + u32 dis_datafb:1; + u32 cts2self:1; + u32 rts_en:1; + u32 hwrts_en:1; + u32 portid:1; + u32 pwr_status:3; + u32 waitdcts:1; + u32 cts2ap_en:1; + u32 txsc:2; + u32 stbc:2; + u32 txshort:1; + u32 txbw:1; + u32 rtsshort:1; + u32 rtsbw:1; + u32 rtssc:2; + u32 rtsstbc:2; + + u32 txrate:6; + u32 shortgi:1; + u32 ccxt:1; + u32 txrate_fb_lmt:5; + u32 rtsrate_fb_lmt:4; + u32 retrylmt_en:1; + u32 txretrylmt:6; + u32 usb_txaggnum:8; + + u32 txagca:5; + u32 txagcb:5; + u32 usemaxlen:1; + u32 maxaggnum:5; + u32 mcsg1maxlen:4; + u32 mcsg2maxlen:4; + u32 mcsg3maxlen:4; + u32 mcs7sgimaxlen:4; + + u32 txbuffersize:16; + u32 sw_offset30:8; + u32 sw_offset31:4; + u32 rsvd1:1; + u32 antsel_c:1; + u32 null_0:1; + u32 null_1:1; + + u32 txbuffaddr; + u32 txbufferaddr64; + u32 nextdescaddress; + u32 nextdescaddress64; + + u32 reserve_pass_pcie_mm_limit[4]; +} __packed; + +struct rx_desc_8821ae { + u32 length:14; + u32 crc32:1; + u32 icverror:1; + u32 drv_infosize:4; + u32 security:3; + u32 qos:1; + u32 shift:2; + u32 phystatus:1; + u32 swdec:1; + u32 lastseg:1; + u32 firstseg:1; + u32 eor:1; + u32 own:1; + + u32 macid:6; + u32 tid:4; + u32 hwrsvd:5; + u32 paggr:1; + u32 faggr:1; + u32 a1_fit:4; + u32 a2_fit:4; + u32 pam:1; + u32 pwr:1; + u32 moredata:1; + u32 morefrag:1; + u32 type:2; + u32 mc:1; + u32 bc:1; + + u32 seq:12; + u32 frag:4; + u32 nextpktlen:14; + u32 nextind:1; + u32 rsvd:1; + + u32 rxmcs:6; + u32 rxht:1; + u32 amsdu:1; + u32 splcp:1; + u32 bandwidth:1; + u32 htc:1; + u32 tcpchk_rpt:1; + u32 ipcchk_rpt:1; + u32 tcpchk_valid:1; + u32 hwpcerr:1; + u32 hwpcind:1; + u32 iv0:16; + + u32 iv1; + + u32 tsfl; + + u32 bufferaddress; + u32 bufferaddress64; + +} __packed; + +void rtl8821ae_tx_fill_desc(struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, u8 *txbd, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); +bool rtl8821ae_rx_query_desc(struct ieee80211_hw *hw, + struct rtl_stats *status, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb); +void rtl8821ae_set_desc(struct ieee80211_hw *hw, u8 *pdesc, + bool istx, u8 desc_name, u8 *val); +u32 rtl8821ae_get_desc(u8 *pdesc, bool istx, u8 desc_name); +bool rtl8821ae_is_tx_desc_closed(struct ieee80211_hw *hw, + u8 hw_queue, u16 index); +void rtl8821ae_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); +void rtl8821ae_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, + bool firstseg, bool lastseg, + struct sk_buff *skb); +u32 rtl8821ae_rx_command_packet(struct ieee80211_hw *hw, + struct rtl_stats status, + struct sk_buff *skb); +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/stats.c b/drivers/net/wireless/realtek/rtlwifi/stats.c new file mode 100644 index 000000000000..d8b30690b00d --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/stats.c @@ -0,0 +1,268 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ +#include "wifi.h" +#include "stats.h" +#include + +u8 rtl_query_rxpwrpercentage(char antpower) +{ + if ((antpower <= -100) || (antpower >= 20)) + return 0; + else if (antpower >= 0) + return 100; + else + return 100 + antpower; +} +EXPORT_SYMBOL(rtl_query_rxpwrpercentage); + +u8 rtl_evm_db_to_percentage(char value) +{ + char ret_val = clamp(-value, 0, 33) * 3; + + if (ret_val == 99) + ret_val = 100; + + return ret_val; +} +EXPORT_SYMBOL(rtl_evm_db_to_percentage); + +static long rtl_translate_todbm(struct ieee80211_hw *hw, + u8 signal_strength_index) +{ + long signal_power; + + signal_power = (long)((signal_strength_index + 1) >> 1); + signal_power -= 95; + return signal_power; +} + +long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig) +{ + long retsig; + + if (currsig >= 61 && currsig <= 100) + retsig = 90 + ((currsig - 60) / 4); + else if (currsig >= 41 && currsig <= 60) + retsig = 78 + ((currsig - 40) / 2); + else if (currsig >= 31 && currsig <= 40) + retsig = 66 + (currsig - 30); + else if (currsig >= 21 && currsig <= 30) + retsig = 54 + (currsig - 20); + else if (currsig >= 5 && currsig <= 20) + retsig = 42 + (((currsig - 5) * 2) / 3); + else if (currsig == 4) + retsig = 36; + else if (currsig == 3) + retsig = 27; + else if (currsig == 2) + retsig = 18; + else if (currsig == 1) + retsig = 9; + else + retsig = currsig; + + return retsig; +} +EXPORT_SYMBOL(rtl_signal_scale_mapping); + +static void rtl_process_ui_rssi(struct ieee80211_hw *hw, + struct rtl_stats *pstatus) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_phy *rtlphy = &(rtlpriv->phy); + u8 rfpath; + u32 last_rssi, tmpval; + + if (!pstatus->packet_toself && !pstatus->packet_beacon) + return; + + rtlpriv->stats.pwdb_all_cnt += pstatus->rx_pwdb_all; + rtlpriv->stats.rssi_calculate_cnt++; + + if (rtlpriv->stats.ui_rssi.total_num++ >= PHY_RSSI_SLID_WIN_MAX) { + rtlpriv->stats.ui_rssi.total_num = PHY_RSSI_SLID_WIN_MAX; + last_rssi = rtlpriv->stats.ui_rssi.elements[ + rtlpriv->stats.ui_rssi.index]; + rtlpriv->stats.ui_rssi.total_val -= last_rssi; + } + rtlpriv->stats.ui_rssi.total_val += pstatus->signalstrength; + rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++] = + pstatus->signalstrength; + if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) + rtlpriv->stats.ui_rssi.index = 0; + tmpval = rtlpriv->stats.ui_rssi.total_val / + rtlpriv->stats.ui_rssi.total_num; + rtlpriv->stats.signal_strength = rtl_translate_todbm(hw, + (u8) tmpval); + pstatus->rssi = rtlpriv->stats.signal_strength; + + if (pstatus->is_cck) + return; + + for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; + rfpath++) { + if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { + rtlpriv->stats.rx_rssi_percentage[rfpath] = + pstatus->rx_mimo_signalstrength[rfpath]; + + } + if (pstatus->rx_mimo_signalstrength[rfpath] > + rtlpriv->stats.rx_rssi_percentage[rfpath]) { + rtlpriv->stats.rx_rssi_percentage[rfpath] = + ((rtlpriv->stats.rx_rssi_percentage[rfpath] * + (RX_SMOOTH_FACTOR - 1)) + + (pstatus->rx_mimo_signalstrength[rfpath])) / + (RX_SMOOTH_FACTOR); + rtlpriv->stats.rx_rssi_percentage[rfpath] = + rtlpriv->stats.rx_rssi_percentage[rfpath] + 1; + } else { + rtlpriv->stats.rx_rssi_percentage[rfpath] = + ((rtlpriv->stats.rx_rssi_percentage[rfpath] * + (RX_SMOOTH_FACTOR - 1)) + + (pstatus->rx_mimo_signalstrength[rfpath])) / + (RX_SMOOTH_FACTOR); + } + rtlpriv->stats.rx_snr_db[rfpath] = pstatus->rx_snr[rfpath]; + rtlpriv->stats.rx_evm_dbm[rfpath] = + pstatus->rx_mimo_evm_dbm[rfpath]; + rtlpriv->stats.rx_cfo_short[rfpath] = + pstatus->cfo_short[rfpath]; + rtlpriv->stats.rx_cfo_tail[rfpath] = pstatus->cfo_tail[rfpath]; + } +} + +static void rtl_update_rxsignalstatistics(struct ieee80211_hw *hw, + struct rtl_stats *pstatus) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + int weighting = 0; + + if (rtlpriv->stats.recv_signal_power == 0) + rtlpriv->stats.recv_signal_power = pstatus->recvsignalpower; + if (pstatus->recvsignalpower > rtlpriv->stats.recv_signal_power) + weighting = 5; + else if (pstatus->recvsignalpower < rtlpriv->stats.recv_signal_power) + weighting = (-5); + rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power * + 5 + pstatus->recvsignalpower + weighting) / 6; +} + +static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_sta_info *drv_priv = NULL; + struct ieee80211_sta *sta = NULL; + long undec_sm_pwdb; + + rcu_read_lock(); + if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) + sta = rtl_find_sta(hw, pstatus->psaddr); + + /* adhoc or ap mode */ + if (sta) { + drv_priv = (struct rtl_sta_info *) sta->drv_priv; + undec_sm_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; + } else { + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; + } + + if (undec_sm_pwdb < 0) + undec_sm_pwdb = pstatus->rx_pwdb_all; + if (pstatus->rx_pwdb_all > (u32) undec_sm_pwdb) { + undec_sm_pwdb = (((undec_sm_pwdb) * + (RX_SMOOTH_FACTOR - 1)) + + (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + undec_sm_pwdb = undec_sm_pwdb + 1; + } else { + undec_sm_pwdb = (((undec_sm_pwdb) * + (RX_SMOOTH_FACTOR - 1)) + + (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); + } + + if (sta) { + drv_priv->rssi_stat.undec_sm_pwdb = undec_sm_pwdb; + } else { + rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; + } + rcu_read_unlock(); + + rtl_update_rxsignalstatistics(hw, pstatus); +} + +static void rtl_process_ui_link_quality(struct ieee80211_hw *hw, + struct rtl_stats *pstatus) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u32 last_evm, n_stream, tmpval; + + if (pstatus->signalquality == 0) + return; + + if (rtlpriv->stats.ui_link_quality.total_num++ >= + PHY_LINKQUALITY_SLID_WIN_MAX) { + rtlpriv->stats.ui_link_quality.total_num = + PHY_LINKQUALITY_SLID_WIN_MAX; + last_evm = rtlpriv->stats.ui_link_quality.elements[ + rtlpriv->stats.ui_link_quality.index]; + rtlpriv->stats.ui_link_quality.total_val -= last_evm; + } + rtlpriv->stats.ui_link_quality.total_val += pstatus->signalquality; + rtlpriv->stats.ui_link_quality.elements[ + rtlpriv->stats.ui_link_quality.index++] = + pstatus->signalquality; + if (rtlpriv->stats.ui_link_quality.index >= + PHY_LINKQUALITY_SLID_WIN_MAX) + rtlpriv->stats.ui_link_quality.index = 0; + tmpval = rtlpriv->stats.ui_link_quality.total_val / + rtlpriv->stats.ui_link_quality.total_num; + rtlpriv->stats.signal_quality = tmpval; + rtlpriv->stats.last_sigstrength_inpercent = tmpval; + for (n_stream = 0; n_stream < 2; n_stream++) { + if (pstatus->rx_mimo_sig_qual[n_stream] != -1) { + if (rtlpriv->stats.rx_evm_percentage[n_stream] == 0) { + rtlpriv->stats.rx_evm_percentage[n_stream] = + pstatus->rx_mimo_sig_qual[n_stream]; + } + rtlpriv->stats.rx_evm_percentage[n_stream] = + ((rtlpriv->stats.rx_evm_percentage[n_stream] + * (RX_SMOOTH_FACTOR - 1)) + + (pstatus->rx_mimo_sig_qual[n_stream] * 1)) / + (RX_SMOOTH_FACTOR); + } + } +} + +void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer, + struct rtl_stats *pstatus) +{ + + if (!pstatus->packet_matchbssid) + return; + + rtl_process_ui_rssi(hw, pstatus); + rtl_process_pwdb(hw, pstatus); + rtl_process_ui_link_quality(hw, pstatus); +} +EXPORT_SYMBOL(rtl_process_phyinfo); diff --git a/drivers/net/wireless/realtek/rtlwifi/stats.h b/drivers/net/wireless/realtek/rtlwifi/stats.h new file mode 100644 index 000000000000..2b57dffef572 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/stats.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL_STATS_H__ +#define __RTL_STATS_H__ + +#define PHY_RSSI_SLID_WIN_MAX 100 +#define PHY_LINKQUALITY_SLID_WIN_MAX 20 +#define PHY_BEACON_RSSI_SLID_WIN_MAX 10 + +/* Rx smooth factor */ +#define RX_SMOOTH_FACTOR 20 + +u8 rtl_query_rxpwrpercentage(char antpower); +u8 rtl_evm_db_to_percentage(char value); +long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig); +void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer, + struct rtl_stats *pstatus); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c new file mode 100644 index 000000000000..2721cf89fb16 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -0,0 +1,1188 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + *****************************************************************************/ + +#include "wifi.h" +#include "core.h" +#include "usb.h" +#include "base.h" +#include "ps.h" +#include "rtl8192c/fw_common.h" +#include +#include + +MODULE_AUTHOR("lizhaoming "); +MODULE_AUTHOR("Realtek WlanFAE "); +MODULE_AUTHOR("Larry Finger "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("USB basic driver for rtlwifi"); + +#define REALTEK_USB_VENQT_READ 0xC0 +#define REALTEK_USB_VENQT_WRITE 0x40 +#define REALTEK_USB_VENQT_CMD_REQ 0x05 +#define REALTEK_USB_VENQT_CMD_IDX 0x00 + +#define MAX_USBCTRL_VENDORREQ_TIMES 10 + +static void usbctrl_async_callback(struct urb *urb) +{ + if (urb) { + /* free dr */ + kfree(urb->setup_packet); + /* free databuf */ + kfree(urb->transfer_buffer); + } +} + +static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, + u16 value, u16 index, void *pdata, + u16 len) +{ + int rc; + unsigned int pipe; + u8 reqtype; + struct usb_ctrlrequest *dr; + struct urb *urb; + const u16 databuf_maxlen = REALTEK_USB_VENQT_MAX_BUF_SIZE; + u8 *databuf; + + if (WARN_ON_ONCE(len > databuf_maxlen)) + len = databuf_maxlen; + + pipe = usb_sndctrlpipe(udev, 0); /* write_out */ + reqtype = REALTEK_USB_VENQT_WRITE; + + dr = kzalloc(sizeof(*dr), GFP_ATOMIC); + if (!dr) + return -ENOMEM; + + databuf = kzalloc(databuf_maxlen, GFP_ATOMIC); + if (!databuf) { + kfree(dr); + return -ENOMEM; + } + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + kfree(databuf); + kfree(dr); + return -ENOMEM; + } + + dr->bRequestType = reqtype; + dr->bRequest = request; + dr->wValue = cpu_to_le16(value); + dr->wIndex = cpu_to_le16(index); + dr->wLength = cpu_to_le16(len); + /* data are already in little-endian order */ + memcpy(databuf, pdata, len); + usb_fill_control_urb(urb, udev, pipe, + (unsigned char *)dr, databuf, len, + usbctrl_async_callback, NULL); + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc < 0) { + kfree(databuf); + kfree(dr); + } + usb_free_urb(urb); + return rc; +} + +static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request, + u16 value, u16 index, void *pdata, + u16 len) +{ + unsigned int pipe; + int status; + u8 reqtype; + int vendorreq_times = 0; + static int count; + + pipe = usb_rcvctrlpipe(udev, 0); /* read_in */ + reqtype = REALTEK_USB_VENQT_READ; + + do { + status = usb_control_msg(udev, pipe, request, reqtype, value, + index, pdata, len, 1000); + if (status < 0) { + /* firmware download is checksumed, don't retry */ + if ((value >= FW_8192C_START_ADDRESS && + value <= FW_8192C_END_ADDRESS)) + break; + } else { + break; + } + } while (++vendorreq_times < MAX_USBCTRL_VENDORREQ_TIMES); + + if (status < 0 && count++ < 4) + pr_err("reg 0x%x, usbctrl_vendorreq TimeOut! status:0x%x value=0x%x\n", + value, status, *(u32 *)pdata); + return status; +} + +static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len) +{ + struct device *dev = rtlpriv->io.dev; + struct usb_device *udev = to_usb_device(dev); + u8 request; + u16 wvalue; + u16 index; + __le32 *data; + unsigned long flags; + + spin_lock_irqsave(&rtlpriv->locks.usb_lock, flags); + if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) + rtlpriv->usb_data_index = 0; + data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; + spin_unlock_irqrestore(&rtlpriv->locks.usb_lock, flags); + request = REALTEK_USB_VENQT_CMD_REQ; + index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ + + wvalue = (u16)addr; + _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len); + return le32_to_cpu(*data); +} + +static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr) +{ + return (u8)_usb_read_sync(rtlpriv, addr, 1); +} + +static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr) +{ + return (u16)_usb_read_sync(rtlpriv, addr, 2); +} + +static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr) +{ + return _usb_read_sync(rtlpriv, addr, 4); +} + +static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val, + u16 len) +{ + u8 request; + u16 wvalue; + u16 index; + __le32 data; + + request = REALTEK_USB_VENQT_CMD_REQ; + index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ + wvalue = (u16)(addr&0x0000ffff); + data = cpu_to_le32(val); + _usbctrl_vendorreq_async_write(udev, request, wvalue, index, &data, + len); +} + +static void _usb_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val) +{ + struct device *dev = rtlpriv->io.dev; + + _usb_write_async(to_usb_device(dev), addr, val, 1); +} + +static void _usb_write16_async(struct rtl_priv *rtlpriv, u32 addr, u16 val) +{ + struct device *dev = rtlpriv->io.dev; + + _usb_write_async(to_usb_device(dev), addr, val, 2); +} + +static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val) +{ + struct device *dev = rtlpriv->io.dev; + + _usb_write_async(to_usb_device(dev), addr, val, 4); +} + +static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data, + u16 len) +{ + struct device *dev = rtlpriv->io.dev; + struct usb_device *udev = to_usb_device(dev); + u8 request = REALTEK_USB_VENQT_CMD_REQ; + u8 reqtype = REALTEK_USB_VENQT_WRITE; + u16 wvalue; + u16 index = REALTEK_USB_VENQT_CMD_IDX; + int pipe = usb_sndctrlpipe(udev, 0); /* write_out */ + u8 *buffer; + + wvalue = (u16)(addr & 0x0000ffff); + buffer = kmemdup(data, len, GFP_ATOMIC); + if (!buffer) + return; + usb_control_msg(udev, pipe, request, reqtype, wvalue, + index, buffer, len, 50); + + kfree(buffer); +} + +static void _rtl_usb_io_handler_init(struct device *dev, + struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->io.dev = dev; + mutex_init(&rtlpriv->io.bb_mutex); + rtlpriv->io.write8_async = _usb_write8_async; + rtlpriv->io.write16_async = _usb_write16_async; + rtlpriv->io.write32_async = _usb_write32_async; + rtlpriv->io.read8_sync = _usb_read8_sync; + rtlpriv->io.read16_sync = _usb_read16_sync; + rtlpriv->io.read32_sync = _usb_read32_sync; + rtlpriv->io.writeN_sync = _usb_writeN_sync; +} + +static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw) +{ + struct rtl_priv __maybe_unused *rtlpriv = rtl_priv(hw); + + mutex_destroy(&rtlpriv->io.bb_mutex); +} + +/** + * + * Default aggregation handler. Do nothing and just return the oldest skb. + */ +static struct sk_buff *_none_usb_tx_aggregate_hdl(struct ieee80211_hw *hw, + struct sk_buff_head *list) +{ + return skb_dequeue(list); +} + +#define IS_HIGH_SPEED_USB(udev) \ + ((USB_SPEED_HIGH == (udev)->speed) ? true : false) + +static int _rtl_usb_init_tx(struct ieee80211_hw *hw) +{ + u32 i; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + + rtlusb->max_bulk_out_size = IS_HIGH_SPEED_USB(rtlusb->udev) + ? USB_HIGH_SPEED_BULK_SIZE + : USB_FULL_SPEED_BULK_SIZE; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "USB Max Bulk-out Size=%d\n", + rtlusb->max_bulk_out_size); + + for (i = 0; i < __RTL_TXQ_NUM; i++) { + u32 ep_num = rtlusb->ep_map.ep_mapping[i]; + if (!ep_num) { + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "Invalid endpoint map setting!\n"); + return -EINVAL; + } + } + + rtlusb->usb_tx_post_hdl = + rtlpriv->cfg->usb_interface_cfg->usb_tx_post_hdl; + rtlusb->usb_tx_cleanup = + rtlpriv->cfg->usb_interface_cfg->usb_tx_cleanup; + rtlusb->usb_tx_aggregate_hdl = + (rtlpriv->cfg->usb_interface_cfg->usb_tx_aggregate_hdl) + ? rtlpriv->cfg->usb_interface_cfg->usb_tx_aggregate_hdl + : &_none_usb_tx_aggregate_hdl; + + init_usb_anchor(&rtlusb->tx_submitted); + for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) { + skb_queue_head_init(&rtlusb->tx_skb_queue[i]); + init_usb_anchor(&rtlusb->tx_pending[i]); + } + return 0; +} + +static void _rtl_rx_work(unsigned long param); + +static int _rtl_usb_init_rx(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); + + rtlusb->rx_max_size = rtlpriv->cfg->usb_interface_cfg->rx_max_size; + rtlusb->rx_urb_num = rtlpriv->cfg->usb_interface_cfg->rx_urb_num; + rtlusb->in_ep = rtlpriv->cfg->usb_interface_cfg->in_ep_num; + rtlusb->usb_rx_hdl = rtlpriv->cfg->usb_interface_cfg->usb_rx_hdl; + rtlusb->usb_rx_segregate_hdl = + rtlpriv->cfg->usb_interface_cfg->usb_rx_segregate_hdl; + + pr_info("rx_max_size %d, rx_urb_num %d, in_ep %d\n", + rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep); + init_usb_anchor(&rtlusb->rx_submitted); + init_usb_anchor(&rtlusb->rx_cleanup_urbs); + + skb_queue_head_init(&rtlusb->rx_queue); + rtlusb->rx_work_tasklet.func = _rtl_rx_work; + rtlusb->rx_work_tasklet.data = (unsigned long)rtlusb; + + return 0; +} + +static int _rtl_usb_init(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); + int err; + u8 epidx; + struct usb_interface *usb_intf = rtlusb->intf; + u8 epnums = usb_intf->cur_altsetting->desc.bNumEndpoints; + + rtlusb->out_ep_nums = rtlusb->in_ep_nums = 0; + for (epidx = 0; epidx < epnums; epidx++) { + struct usb_endpoint_descriptor *pep_desc; + pep_desc = &usb_intf->cur_altsetting->endpoint[epidx].desc; + + if (usb_endpoint_dir_in(pep_desc)) + rtlusb->in_ep_nums++; + else if (usb_endpoint_dir_out(pep_desc)) + rtlusb->out_ep_nums++; + + RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, + "USB EP(0x%02x), MaxPacketSize=%d, Interval=%d\n", + pep_desc->bEndpointAddress, pep_desc->wMaxPacketSize, + pep_desc->bInterval); + } + if (rtlusb->in_ep_nums < rtlpriv->cfg->usb_interface_cfg->in_ep_num) { + pr_err("Too few input end points found\n"); + return -EINVAL; + } + if (rtlusb->out_ep_nums == 0) { + pr_err("No output end points found\n"); + return -EINVAL; + } + /* usb endpoint mapping */ + err = rtlpriv->cfg->usb_interface_cfg->usb_endpoint_mapping(hw); + rtlusb->usb_mq_to_hwq = rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq; + _rtl_usb_init_tx(hw); + _rtl_usb_init_rx(hw); + return err; +} + +static void rtl_usb_init_sw(struct ieee80211_hw *hw) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + + rtlhal->hw = hw; + ppsc->inactiveps = false; + ppsc->leisure_ps = false; + ppsc->fwctrl_lps = false; + ppsc->reg_fwctrl_lps = 3; + ppsc->reg_max_lps_awakeintvl = 5; + ppsc->fwctrl_psmode = FW_PS_DTIM_MODE; + + /* IBSS */ + mac->beacon_interval = 100; + + /* AMPDU */ + mac->min_space_cfg = 0; + mac->max_mss_density = 0; + + /* set sane AMPDU defaults */ + mac->current_ampdu_density = 7; + mac->current_ampdu_factor = 3; + + /* QOS */ + rtlusb->acm_method = EACMWAY2_SW; + + /* IRQ */ + /* HIMR - turn all on */ + rtlusb->irq_mask[0] = 0xFFFFFFFF; + /* HIMR_EX - turn all on */ + rtlusb->irq_mask[1] = 0xFFFFFFFF; + rtlusb->disableHWSM = true; +} + +static void _rtl_rx_completed(struct urb *urb); + +static int _rtl_prep_rx_urb(struct ieee80211_hw *hw, struct rtl_usb *rtlusb, + struct urb *urb, gfp_t gfp_mask) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + void *buf; + + buf = usb_alloc_coherent(rtlusb->udev, rtlusb->rx_max_size, gfp_mask, + &urb->transfer_dma); + if (!buf) { + RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, + "Failed to usb_alloc_coherent!!\n"); + return -ENOMEM; + } + + usb_fill_bulk_urb(urb, rtlusb->udev, + usb_rcvbulkpipe(rtlusb->udev, rtlusb->in_ep), + buf, rtlusb->rx_max_size, _rtl_rx_completed, rtlusb); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + return 0; +} + +static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 *rxdesc = skb->data; + struct ieee80211_hdr *hdr; + bool unicast = false; + __le16 fc; + struct ieee80211_rx_status rx_status = {0}; + struct rtl_stats stats = { + .signal = 0, + .rate = 0, + }; + + skb_pull(skb, RTL_RX_DESC_SIZE); + rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb); + skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift)); + hdr = (struct ieee80211_hdr *)(skb->data); + fc = hdr->frame_control; + if (!stats.crc) { + memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); + + if (is_broadcast_ether_addr(hdr->addr1)) { + /*TODO*/; + } else if (is_multicast_ether_addr(hdr->addr1)) { + /*TODO*/ + } else { + unicast = true; + rtlpriv->stats.rxbytesunicast += skb->len; + } + + if (ieee80211_is_data(fc)) { + rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); + + if (unicast) + rtlpriv->link_info.num_rx_inperiod++; + } + /* static bcn for roaming */ + rtl_beacon_statistic(hw, skb); + } +} + +static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + u8 *rxdesc = skb->data; + struct ieee80211_hdr *hdr; + bool unicast = false; + __le16 fc; + struct ieee80211_rx_status rx_status = {0}; + struct rtl_stats stats = { + .signal = 0, + .rate = 0, + }; + + skb_pull(skb, RTL_RX_DESC_SIZE); + rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb); + skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift)); + hdr = (struct ieee80211_hdr *)(skb->data); + fc = hdr->frame_control; + if (!stats.crc) { + memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); + + if (is_broadcast_ether_addr(hdr->addr1)) { + /*TODO*/; + } else if (is_multicast_ether_addr(hdr->addr1)) { + /*TODO*/ + } else { + unicast = true; + rtlpriv->stats.rxbytesunicast += skb->len; + } + + if (ieee80211_is_data(fc)) { + rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); + + if (unicast) + rtlpriv->link_info.num_rx_inperiod++; + } + + /* static bcn for roaming */ + rtl_beacon_statistic(hw, skb); + + if (likely(rtl_action_proc(hw, skb, false))) + ieee80211_rx(hw, skb); + else + dev_kfree_skb_any(skb); + } +} + +static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct sk_buff *_skb; + struct sk_buff_head rx_queue; + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + + skb_queue_head_init(&rx_queue); + if (rtlusb->usb_rx_segregate_hdl) + rtlusb->usb_rx_segregate_hdl(hw, skb, &rx_queue); + WARN_ON(skb_queue_empty(&rx_queue)); + while (!skb_queue_empty(&rx_queue)) { + _skb = skb_dequeue(&rx_queue); + _rtl_usb_rx_process_agg(hw, _skb); + ieee80211_rx(hw, _skb); + } +} + +#define __RX_SKB_MAX_QUEUED 64 + +static void _rtl_rx_work(unsigned long param) +{ + struct rtl_usb *rtlusb = (struct rtl_usb *)param; + struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf); + struct sk_buff *skb; + + while ((skb = skb_dequeue(&rtlusb->rx_queue))) { + if (unlikely(IS_USB_STOP(rtlusb))) { + dev_kfree_skb_any(skb); + continue; + } + + if (likely(!rtlusb->usb_rx_segregate_hdl)) { + _rtl_usb_rx_process_noagg(hw, skb); + } else { + /* TO DO */ + _rtl_rx_pre_process(hw, skb); + pr_err("rx agg not supported\n"); + } + } +} + +static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr, + unsigned int len) +{ +#if NET_IP_ALIGN != 0 + unsigned int padding = 0; +#endif + + /* make function no-op when possible */ + if (NET_IP_ALIGN == 0 || len < sizeof(*hdr)) + return 0; + +#if NET_IP_ALIGN != 0 + /* alignment calculation as in lbtf_rx() / carl9170_rx_copy_data() */ + /* TODO: deduplicate common code, define helper function instead? */ + + if (ieee80211_is_data_qos(hdr->frame_control)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); + + padding ^= NET_IP_ALIGN; + + /* Input might be invalid, avoid accessing memory outside + * the buffer. + */ + if ((unsigned long)qc - (unsigned long)hdr < len && + *qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) + padding ^= NET_IP_ALIGN; + } + + if (ieee80211_has_a4(hdr->frame_control)) + padding ^= NET_IP_ALIGN; + + return padding; +#endif +} + +#define __RADIO_TAP_SIZE_RSV 32 + +static void _rtl_rx_completed(struct urb *_urb) +{ + struct rtl_usb *rtlusb = (struct rtl_usb *)_urb->context; + struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf); + struct rtl_priv *rtlpriv = rtl_priv(hw); + int err = 0; + + if (unlikely(IS_USB_STOP(rtlusb))) + goto free; + + if (likely(0 == _urb->status)) { + unsigned int padding; + struct sk_buff *skb; + unsigned int qlen; + unsigned int size = _urb->actual_length; + struct ieee80211_hdr *hdr; + + if (size < RTL_RX_DESC_SIZE + sizeof(struct ieee80211_hdr)) { + RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, + "Too short packet from bulk IN! (len: %d)\n", + size); + goto resubmit; + } + + qlen = skb_queue_len(&rtlusb->rx_queue); + if (qlen >= __RX_SKB_MAX_QUEUED) { + RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, + "Pending RX skbuff queue full! (qlen: %d)\n", + qlen); + goto resubmit; + } + + hdr = (void *)(_urb->transfer_buffer + RTL_RX_DESC_SIZE); + padding = _rtl_rx_get_padding(hdr, size - RTL_RX_DESC_SIZE); + + skb = dev_alloc_skb(size + __RADIO_TAP_SIZE_RSV + padding); + if (!skb) { + RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, + "Can't allocate skb for bulk IN!\n"); + goto resubmit; + } + + _rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep); + + /* Make sure the payload data is 4 byte aligned. */ + skb_reserve(skb, padding); + + /* reserve some space for mac80211's radiotap */ + skb_reserve(skb, __RADIO_TAP_SIZE_RSV); + + memcpy(skb_put(skb, size), _urb->transfer_buffer, size); + + skb_queue_tail(&rtlusb->rx_queue, skb); + tasklet_schedule(&rtlusb->rx_work_tasklet); + + goto resubmit; + } + + switch (_urb->status) { + /* disconnect */ + case -ENOENT: + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: + goto free; + default: + break; + } + +resubmit: + usb_anchor_urb(_urb, &rtlusb->rx_submitted); + err = usb_submit_urb(_urb, GFP_ATOMIC); + if (unlikely(err)) { + usb_unanchor_urb(_urb); + goto free; + } + return; + +free: + /* On some architectures, usb_free_coherent must not be called from + * hardirq context. Queue urb to cleanup list. + */ + usb_anchor_urb(_urb, &rtlusb->rx_cleanup_urbs); +} + +#undef __RADIO_TAP_SIZE_RSV + +static void _rtl_usb_cleanup_rx(struct ieee80211_hw *hw) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + struct urb *urb; + + 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); + destroy_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); + } +} + +static int _rtl_usb_receive(struct ieee80211_hw *hw) +{ + struct urb *urb; + int err; + int i; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + + WARN_ON(0 == rtlusb->rx_urb_num); + /* 1600 == 1514 + max WLAN header + rtk info */ + WARN_ON(rtlusb->rx_max_size < 1600); + + for (i = 0; i < rtlusb->rx_urb_num; i++) { + err = -ENOMEM; + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, + "Failed to alloc URB!!\n"); + goto err_out; + } + + err = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL); + if (err < 0) { + RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, + "Failed to prep_rx_urb!!\n"); + usb_free_urb(urb); + goto err_out; + } + + usb_anchor_urb(urb, &rtlusb->rx_submitted); + err = usb_submit_urb(urb, GFP_KERNEL); + if (err) + goto err_out; + usb_free_urb(urb); + } + return 0; + +err_out: + usb_kill_anchored_urbs(&rtlusb->rx_submitted); + _rtl_usb_cleanup_rx(hw); + return err; +} + +static int rtl_usb_start(struct ieee80211_hw *hw) +{ + int err; + 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)); + + err = rtlpriv->cfg->ops->hw_init(hw); + if (!err) { + rtl_init_rx_config(hw); + + /* Enable software */ + SET_USB_START(rtlusb); + /* should after adapter start and interrupt enable. */ + set_hal_start(rtlhal); + + /* Start bulk IN */ + err = _rtl_usb_receive(hw); + } + + return err; +} +/** + * + * + */ + +/*======================= tx =========================================*/ +static void rtl_usb_cleanup(struct ieee80211_hw *hw) +{ + u32 i; + struct sk_buff *_skb; + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + struct ieee80211_tx_info *txinfo; + + /* clean up rx stuff. */ + _rtl_usb_cleanup_rx(hw); + + /* clean up tx stuff */ + for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) { + while ((_skb = skb_dequeue(&rtlusb->tx_skb_queue[i]))) { + rtlusb->usb_tx_cleanup(hw, _skb); + txinfo = IEEE80211_SKB_CB(_skb); + ieee80211_tx_info_clear_status(txinfo); + txinfo->flags |= IEEE80211_TX_STAT_ACK; + ieee80211_tx_status_irqsafe(hw, _skb); + } + usb_kill_anchored_urbs(&rtlusb->tx_pending[i]); + } + usb_kill_anchored_urbs(&rtlusb->tx_submitted); +} + +/** + * + * We may add some struct into struct rtl_usb later. Do deinit here. + * + */ +static void rtl_usb_deinit(struct ieee80211_hw *hw) +{ + rtl_usb_cleanup(hw); +} + +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)); + + /* 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); + rtlpriv->cfg->ops->hw_disable(hw); +} + +static void _rtl_submit_tx_urb(struct ieee80211_hw *hw, struct urb *_urb) +{ + int err; + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + + usb_anchor_urb(_urb, &rtlusb->tx_submitted); + err = usb_submit_urb(_urb, GFP_ATOMIC); + if (err < 0) { + struct sk_buff *skb; + + RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, + "Failed to submit urb\n"); + usb_unanchor_urb(_urb); + skb = (struct sk_buff *)_urb->context; + kfree_skb(skb); + } + usb_free_urb(_urb); +} + +static int _usb_tx_post(struct ieee80211_hw *hw, struct urb *urb, + struct sk_buff *skb) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + struct ieee80211_tx_info *txinfo; + + rtlusb->usb_tx_post_hdl(hw, urb, skb); + skb_pull(skb, RTL_TX_HEADER_SIZE); + txinfo = IEEE80211_SKB_CB(skb); + ieee80211_tx_info_clear_status(txinfo); + txinfo->flags |= IEEE80211_TX_STAT_ACK; + + if (urb->status) { + RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, + "Urb has error status 0x%X\n", urb->status); + goto out; + } + /* TODO: statistics */ +out: + ieee80211_tx_status_irqsafe(hw, skb); + return urb->status; +} + +static void _rtl_tx_complete(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *)urb->context; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct rtl_usb *rtlusb = (struct rtl_usb *)info->rate_driver_data[0]; + struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf); + int err; + + if (unlikely(IS_USB_STOP(rtlusb))) + return; + err = _usb_tx_post(hw, urb, skb); + if (err) { + /* Ignore error and keep issuiing other urbs */ + return; + } +} + +static struct urb *_rtl_usb_tx_urb_setup(struct ieee80211_hw *hw, + struct sk_buff *skb, u32 ep_num) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + struct urb *_urb; + + WARN_ON(NULL == skb); + _urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!_urb) { + RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, + "Can't allocate URB for bulk out!\n"); + kfree_skb(skb); + return NULL; + } + _rtl_install_trx_info(rtlusb, skb, ep_num); + usb_fill_bulk_urb(_urb, rtlusb->udev, usb_sndbulkpipe(rtlusb->udev, + ep_num), skb->data, skb->len, _rtl_tx_complete, skb); + _urb->transfer_flags |= URB_ZERO_PACKET; + return _urb; +} + +static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, + enum rtl_txq qnum) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + u32 ep_num; + struct urb *_urb = NULL; + struct sk_buff *_skb = NULL; + + WARN_ON(NULL == rtlusb->usb_tx_aggregate_hdl); + if (unlikely(IS_USB_STOP(rtlusb))) { + RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, + "USB device is stopping...\n"); + kfree_skb(skb); + return; + } + ep_num = rtlusb->ep_map.ep_mapping[qnum]; + _skb = skb; + _urb = _rtl_usb_tx_urb_setup(hw, _skb, ep_num); + if (unlikely(!_urb)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't allocate urb. Drop skb!\n"); + kfree_skb(skb); + return; + } + _rtl_submit_tx_urb(hw, _urb); +} + +static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u16 hw_queue) +{ + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct rtl_tx_desc *pdesc = NULL; + struct rtl_tcb_desc tcb_desc; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + __le16 fc = hdr->frame_control; + u8 *pda_addr = hdr->addr1; + /* ssn */ + u8 *qc = NULL; + u8 tid = 0; + u16 seq_number = 0; + + memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); + if (ieee80211_is_auth(fc)) { + RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n"); + rtl_ips_nic_on(hw); + } + + if (rtlpriv->psc.sw_ps_enabled) { + if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && + !ieee80211_has_pm(fc)) + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); + } + + rtl_action_proc(hw, skb, true); + if (is_multicast_ether_addr(pda_addr)) + rtlpriv->stats.txbytesmulticast += skb->len; + else if (is_broadcast_ether_addr(pda_addr)) + rtlpriv->stats.txbytesbroadcast += skb->len; + else + rtlpriv->stats.txbytesunicast += skb->len; + if (ieee80211_is_data_qos(fc)) { + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; + seq_number = (le16_to_cpu(hdr->seq_ctrl) & + IEEE80211_SCTL_SEQ) >> 4; + seq_number += 1; + seq_number <<= 4; + } + rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, NULL, info, sta, skb, + hw_queue, &tcb_desc); + if (!ieee80211_has_morefrags(hdr->frame_control)) { + if (qc) + mac->tids[tid].seq_number = seq_number; + } + if (ieee80211_is_data(fc)) + rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); +} + +static int rtl_usb_tx(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb, + struct rtl_tcb_desc *dummy) +{ + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + __le16 fc = hdr->frame_control; + u16 hw_queue; + + if (unlikely(is_hal_stop(rtlhal))) + goto err_free; + hw_queue = rtlusb->usb_mq_to_hwq(fc, skb_get_queue_mapping(skb)); + _rtl_usb_tx_preprocess(hw, sta, skb, hw_queue); + _rtl_usb_transmit(hw, skb, hw_queue); + return NETDEV_TX_OK; + +err_free: + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} + +static bool rtl_usb_tx_chk_waitq_insert(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb) +{ + return false; +} + +static void rtl_fill_h2c_cmd_work_callback(struct work_struct *work) +{ + struct rtl_works *rtlworks = + container_of(work, struct rtl_works, fill_h2c_cmd); + struct ieee80211_hw *hw = rtlworks->hw; + struct rtl_priv *rtlpriv = rtl_priv(hw); + + rtlpriv->cfg->ops->fill_h2c_cmd(hw, H2C_RA_MASK, 5, rtlpriv->rate_mask); +} + +static struct rtl_intf_ops rtl_usb_ops = { + .adapter_start = rtl_usb_start, + .adapter_stop = rtl_usb_stop, + .adapter_tx = rtl_usb_tx, + .waitq_insert = rtl_usb_tx_chk_waitq_insert, +}; + +int rtl_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id, + struct rtl_hal_cfg *rtl_hal_cfg) +{ + int err; + struct ieee80211_hw *hw = NULL; + struct rtl_priv *rtlpriv = NULL; + struct usb_device *udev; + struct rtl_usb_priv *usb_priv; + + hw = ieee80211_alloc_hw(sizeof(struct rtl_priv) + + sizeof(struct rtl_usb_priv), &rtl_ops); + if (!hw) { + RT_ASSERT(false, "ieee80211 alloc failed\n"); + return -ENOMEM; + } + rtlpriv = hw->priv; + rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32), + GFP_KERNEL); + if (!rtlpriv->usb_data) + return -ENOMEM; + + /* this spin lock must be initialized early */ + spin_lock_init(&rtlpriv->locks.usb_lock); + INIT_WORK(&rtlpriv->works.fill_h2c_cmd, + rtl_fill_h2c_cmd_work_callback); + INIT_WORK(&rtlpriv->works.lps_change_work, + rtl_lps_change_work_callback); + + rtlpriv->usb_data_index = 0; + init_completion(&rtlpriv->firmware_loading_complete); + SET_IEEE80211_DEV(hw, &intf->dev); + udev = interface_to_usbdev(intf); + usb_get_dev(udev); + usb_priv = rtl_usbpriv(hw); + memset(usb_priv, 0, sizeof(*usb_priv)); + usb_priv->dev.intf = intf; + usb_priv->dev.udev = udev; + usb_set_intfdata(intf, hw); + /* init cfg & intf_ops */ + 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); + /*like read eeprom and so on */ + rtlpriv->cfg->ops->read_eeprom_info(hw); + err = _rtl_usb_init(hw); + if (err) + goto error_out; + rtl_usb_init_sw(hw); + /* Init mac80211 sw */ + err = rtl_init_core(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't allocate sw for mac80211\n"); + goto error_out; + } + if (rtlpriv->cfg->ops->init_sw_vars(hw)) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n"); + goto error_out; + } + rtlpriv->cfg->ops->init_sw_leds(hw); + + err = ieee80211_register_hw(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + "Can't register mac80211 hw.\n"); + err = -ENODEV; + goto error_out; + } + rtlpriv->mac80211.mac80211_registered = 1; + + set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); + return 0; + +error_out: + rtl_deinit_core(hw); + _rtl_usb_io_handler_release(hw); + usb_put_dev(udev); + complete(&rtlpriv->firmware_loading_complete); + return -ENODEV; +} +EXPORT_SYMBOL(rtl_usb_probe); + +void rtl_usb_disconnect(struct usb_interface *intf) +{ + struct ieee80211_hw *hw = usb_get_intfdata(intf); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); + struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); + + if (unlikely(!rtlpriv)) + return; + /* just in case driver is removed before firmware callback */ + wait_for_completion(&rtlpriv->firmware_loading_complete); + clear_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); + /*ieee80211_unregister_hw will call ops_stop */ + if (rtlmac->mac80211_registered == 1) { + ieee80211_unregister_hw(hw); + rtlmac->mac80211_registered = 0; + } else { + rtl_deinit_deferred_work(hw); + rtlpriv->intf_ops->adapter_stop(hw); + } + /*deinit rfkill */ + /* rtl_deinit_rfkill(hw); */ + rtl_usb_deinit(hw); + rtl_deinit_core(hw); + kfree(rtlpriv->usb_data); + rtlpriv->cfg->ops->deinit_sw_leds(hw); + rtlpriv->cfg->ops->deinit_sw_vars(hw); + _rtl_usb_io_handler_release(hw); + usb_put_dev(rtlusb->udev); + usb_set_intfdata(intf, NULL); + ieee80211_free_hw(hw); +} +EXPORT_SYMBOL(rtl_usb_disconnect); + +int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message) +{ + return 0; +} +EXPORT_SYMBOL(rtl_usb_suspend); + +int rtl_usb_resume(struct usb_interface *pusb_intf) +{ + return 0; +} +EXPORT_SYMBOL(rtl_usb_resume); diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.h b/drivers/net/wireless/realtek/rtlwifi/usb.h new file mode 100644 index 000000000000..685273ca9561 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/usb.h @@ -0,0 +1,169 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + *****************************************************************************/ + +#ifndef __RTL_USB_H__ +#define __RTL_USB_H__ + +#include + +#define RTL_RX_DESC_SIZE 24 + +#define RTL_USB_DEVICE(vend, prod, cfg) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \ + .idVendor = (vend), \ + .idProduct = (prod), \ + .driver_info = (kernel_ulong_t)&(cfg) + +#define USB_HIGH_SPEED_BULK_SIZE 512 +#define USB_FULL_SPEED_BULK_SIZE 64 + + +#define RTL_USB_MAX_TXQ_NUM 4 /* max tx queue */ +#define RTL_USB_MAX_EP_NUM 6 /* max ep number */ +#define RTL_USB_MAX_TX_URBS_NUM 8 + +enum rtl_txq { + /* These definitions shall be consistent with value + * returned by skb_get_queue_mapping + *------------------------------------*/ + RTL_TXQ_BK, + RTL_TXQ_BE, + RTL_TXQ_VI, + RTL_TXQ_VO, + /*------------------------------------*/ + RTL_TXQ_BCN, + RTL_TXQ_MGT, + RTL_TXQ_HI, + + /* Must be last */ + __RTL_TXQ_NUM, +}; + +struct rtl_ep_map { + u32 ep_mapping[__RTL_TXQ_NUM]; +}; + +struct _trx_info { + struct rtl_usb *rtlusb; + u32 ep_num; +}; + +static inline void _rtl_install_trx_info(struct rtl_usb *rtlusb, + struct sk_buff *skb, + u32 ep_num) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + info->rate_driver_data[0] = rtlusb; + info->rate_driver_data[1] = (void *)(__kernel_size_t)ep_num; +} + + +/* Add suspend/resume later */ +enum rtl_usb_state { + USB_STATE_STOP = 0, + USB_STATE_START = 1, +}; + +#define IS_USB_STOP(rtlusb_ptr) (USB_STATE_STOP == (rtlusb_ptr)->state) +#define IS_USB_START(rtlusb_ptr) (USB_STATE_START == (rtlusb_ptr)->state) +#define SET_USB_STOP(rtlusb_ptr) \ + do { \ + (rtlusb_ptr)->state = USB_STATE_STOP; \ + } while (0) + +#define SET_USB_START(rtlusb_ptr) \ + do { \ + (rtlusb_ptr)->state = USB_STATE_START; \ + } while (0) + +struct rtl_usb { + struct usb_device *udev; + struct usb_interface *intf; + enum rtl_usb_state state; + + /* Bcn control register setting */ + u32 reg_bcn_ctrl_val; + /* for 88/92cu card disable */ + u8 disableHWSM; + /*QOS & EDCA */ + enum acm_method acm_method; + /* irq . HIMR,HIMR_EX */ + u32 irq_mask[2]; + bool irq_enabled; + + u16 (*usb_mq_to_hwq)(__le16 fc, u16 mac80211_queue_index); + + /* Tx */ + u8 out_ep_nums ; + u8 out_queue_sel; + struct rtl_ep_map ep_map; + + u32 max_bulk_out_size; + u32 tx_submitted_urbs; + struct sk_buff_head tx_skb_queue[RTL_USB_MAX_EP_NUM]; + + struct usb_anchor tx_pending[RTL_USB_MAX_EP_NUM]; + struct usb_anchor tx_submitted; + + struct sk_buff *(*usb_tx_aggregate_hdl)(struct ieee80211_hw *, + struct sk_buff_head *); + int (*usb_tx_post_hdl)(struct ieee80211_hw *, + struct urb *, struct sk_buff *); + void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *); + + /* Rx */ + u8 in_ep_nums; + u32 in_ep; /* Bulk IN endpoint number */ + u32 rx_max_size; /* Bulk IN max buffer size */ + u32 rx_urb_num; /* How many Bulk INs are submitted to host. */ + struct usb_anchor rx_submitted; + struct usb_anchor rx_cleanup_urbs; + struct tasklet_struct rx_work_tasklet; + struct sk_buff_head rx_queue; + void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *, + struct sk_buff_head *); + void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *); +}; + +struct rtl_usb_priv { + struct rtl_usb dev; + struct rtl_led_ctl ledctl; +}; + +#define rtl_usbpriv(hw) (((struct rtl_usb_priv *)(rtl_priv(hw))->priv)) +#define rtl_usbdev(usbpriv) (&((usbpriv)->dev)) + + + +int rtl_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id, + struct rtl_hal_cfg *rtl92cu_hal_cfg); +void rtl_usb_disconnect(struct usb_interface *intf); +int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message); +int rtl_usb_resume(struct usb_interface *pusb_intf); + +#endif diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h new file mode 100644 index 000000000000..b90ca618b123 --- /dev/null +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -0,0 +1,3032 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2012 Realtek Corporation. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger + * + *****************************************************************************/ + +#ifndef __RTL_WIFI_H__ +#define __RTL_WIFI_H__ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include "debug.h" + +#define MASKBYTE0 0xff +#define MASKBYTE1 0xff00 +#define MASKBYTE2 0xff0000 +#define MASKBYTE3 0xff000000 +#define MASKHWORD 0xffff0000 +#define MASKLWORD 0x0000ffff +#define MASKDWORD 0xffffffff +#define MASK12BITS 0xfff +#define MASKH4BITS 0xf0000000 +#define MASKOFDM_D 0xffc00000 +#define MASKCCK 0x3f3f3f3f + +#define MASK4BITS 0x0f +#define MASK20BITS 0xfffff +#define RFREG_OFFSET_MASK 0xfffff + +#define MASKBYTE0 0xff +#define MASKBYTE1 0xff00 +#define MASKBYTE2 0xff0000 +#define MASKBYTE3 0xff000000 +#define MASKHWORD 0xffff0000 +#define MASKLWORD 0x0000ffff +#define MASKDWORD 0xffffffff +#define MASK12BITS 0xfff +#define MASKH4BITS 0xf0000000 +#define MASKOFDM_D 0xffc00000 +#define MASKCCK 0x3f3f3f3f + +#define MASK4BITS 0x0f +#define MASK20BITS 0xfffff +#define RFREG_OFFSET_MASK 0xfffff + +#define RF_CHANGE_BY_INIT 0 +#define RF_CHANGE_BY_IPS BIT(28) +#define RF_CHANGE_BY_PS BIT(29) +#define RF_CHANGE_BY_HW BIT(30) +#define RF_CHANGE_BY_SW BIT(31) + +#define IQK_ADDA_REG_NUM 16 +#define IQK_MAC_REG_NUM 4 +#define IQK_THRESHOLD 8 + +#define MAX_KEY_LEN 61 +#define KEY_BUF_SIZE 5 + +/* QoS related. */ +/*aci: 0x00 Best Effort*/ +/*aci: 0x01 Background*/ +/*aci: 0x10 Video*/ +/*aci: 0x11 Voice*/ +/*Max: define total number.*/ +#define AC0_BE 0 +#define AC1_BK 1 +#define AC2_VI 2 +#define AC3_VO 3 +#define AC_MAX 4 +#define QOS_QUEUE_NUM 4 +#define RTL_MAC80211_NUM_QUEUE 5 +#define REALTEK_USB_VENQT_MAX_BUF_SIZE 254 +#define RTL_USB_MAX_RX_COUNT 100 +#define QBSS_LOAD_SIZE 5 +#define MAX_WMMELE_LENGTH 64 + +#define TOTAL_CAM_ENTRY 32 + +/*slot time for 11g. */ +#define RTL_SLOT_TIME_9 9 +#define RTL_SLOT_TIME_20 20 + +/*related to tcp/ip. */ +#define SNAP_SIZE 6 +#define PROTOC_TYPE_SIZE 2 + +/*related with 802.11 frame*/ +#define MAC80211_3ADDR_LEN 24 +#define MAC80211_4ADDR_LEN 30 + +#define CHANNEL_MAX_NUMBER (14 + 24 + 21) /* 14 is the max channel no */ +#define CHANNEL_MAX_NUMBER_2G 14 +#define CHANNEL_MAX_NUMBER_5G 54 /* Please refer to + *"phy_GetChnlGroup8812A" and + * "Hal_ReadTxPowerInfo8812A" + */ +#define CHANNEL_MAX_NUMBER_5G_80M 7 +#define CHANNEL_GROUP_MAX (3 + 9) /* ch1~3, 4~9, 10~14 = three groups */ +#define CHANNEL_MAX_NUMBER_5G 54 /* Please refer to + *"phy_GetChnlGroup8812A" and + * "Hal_ReadTxPowerInfo8812A" + */ +#define CHANNEL_MAX_NUMBER_5G_80M 7 +#define MAX_PG_GROUP 13 +#define CHANNEL_GROUP_MAX_2G 3 +#define CHANNEL_GROUP_IDX_5GL 3 +#define CHANNEL_GROUP_IDX_5GM 6 +#define CHANNEL_GROUP_IDX_5GH 9 +#define CHANNEL_GROUP_MAX_5G 9 +#define CHANNEL_MAX_NUMBER_2G 14 +#define AVG_THERMAL_NUM 8 +#define AVG_THERMAL_NUM_88E 4 +#define AVG_THERMAL_NUM_8723BE 4 +#define MAX_TID_COUNT 9 + +/* for early mode */ +#define FCS_LEN 4 +#define EM_HDR_LEN 8 + +enum rtl8192c_h2c_cmd { + H2C_AP_OFFLOAD = 0, + H2C_SETPWRMODE = 1, + H2C_JOINBSSRPT = 2, + H2C_RSVDPAGE = 3, + H2C_RSSI_REPORT = 5, + H2C_RA_MASK = 6, + H2C_MACID_PS_MODE = 7, + H2C_P2P_PS_OFFLOAD = 8, + H2C_MAC_MODE_SEL = 9, + H2C_PWRM = 15, + H2C_P2P_PS_CTW_CMD = 24, + MAX_H2CCMD +}; + +#define MAX_TX_COUNT 4 +#define MAX_REGULATION_NUM 4 +#define MAX_RF_PATH_NUM 4 +#define MAX_RATE_SECTION_NUM 6 +#define MAX_2_4G_BANDWITH_NUM 4 +#define MAX_5G_BANDWITH_NUM 4 +#define MAX_RF_PATH 4 +#define MAX_CHNL_GROUP_24G 6 +#define MAX_CHNL_GROUP_5G 14 + +#define TX_PWR_BY_RATE_NUM_BAND 2 +#define TX_PWR_BY_RATE_NUM_RF 4 +#define TX_PWR_BY_RATE_NUM_SECTION 12 +#define MAX_BASE_NUM_IN_PHY_REG_PG_24G 6 +#define MAX_BASE_NUM_IN_PHY_REG_PG_5G 5 + +#define RTL8192EE_SEG_NUM 1 /* 0:2 seg, 1: 4 seg, 2: 8 seg */ + +#define DEL_SW_IDX_SZ 30 +#define BAND_NUM 3 + +/* For now, it's just for 8192ee + * but not OK yet, keep it 0 + */ +#define DMA_IS_64BIT 0 +#define RTL8192EE_SEG_NUM 1 /* 0:2 seg, 1: 4 seg, 2: 8 seg */ + +enum rf_tx_num { + RF_1TX = 0, + RF_2TX, + RF_MAX_TX_NUM, + RF_TX_NUM_NONIMPLEMENT, +}; + +#define PACKET_NORMAL 0 +#define PACKET_DHCP 1 +#define PACKET_ARP 2 +#define PACKET_EAPOL 3 + +#define MAX_SUPPORT_WOL_PATTERN_NUM 16 +#define RSVD_WOL_PATTERN_NUM 1 +#define WKFMCAM_ADDR_NUM 6 +#define WKFMCAM_SIZE 24 + +#define MAX_WOL_BIT_MASK_SIZE 16 +/* MIN LEN keeps 13 here */ +#define MIN_WOL_PATTERN_SIZE 13 +#define MAX_WOL_PATTERN_SIZE 128 + +#define WAKE_ON_MAGIC_PACKET BIT(0) +#define WAKE_ON_PATTERN_MATCH BIT(1) + +#define WOL_REASON_PTK_UPDATE BIT(0) +#define WOL_REASON_GTK_UPDATE BIT(1) +#define WOL_REASON_DISASSOC BIT(2) +#define WOL_REASON_DEAUTH BIT(3) +#define WOL_REASON_AP_LOST BIT(4) +#define WOL_REASON_MAGIC_PKT BIT(5) +#define WOL_REASON_UNICAST_PKT BIT(6) +#define WOL_REASON_PATTERN_PKT BIT(7) +#define WOL_REASON_RTD3_SSID_MATCH BIT(8) +#define WOL_REASON_REALWOW_V2_WAKEUPPKT BIT(9) +#define WOL_REASON_REALWOW_V2_ACKLOST BIT(10) + +struct rtlwifi_firmware_header { + __le16 signature; + u8 category; + u8 function; + __le16 version; + u8 subversion; + u8 rsvd1; + u8 month; + u8 date; + u8 hour; + u8 minute; + __le16 ramcodeSize; + __le16 rsvd2; + __le32 svnindex; + __le32 rsvd3; + __le32 rsvd4; + __le32 rsvd5; +}; + +struct txpower_info_2g { + u8 index_cck_base[MAX_RF_PATH][MAX_CHNL_GROUP_24G]; + u8 index_bw40_base[MAX_RF_PATH][MAX_CHNL_GROUP_24G]; + /*If only one tx, only BW20 and OFDM are used.*/ + u8 cck_diff[MAX_RF_PATH][MAX_TX_COUNT]; + u8 ofdm_diff[MAX_RF_PATH][MAX_TX_COUNT]; + u8 bw20_diff[MAX_RF_PATH][MAX_TX_COUNT]; + u8 bw40_diff[MAX_RF_PATH][MAX_TX_COUNT]; + u8 bw80_diff[MAX_RF_PATH][MAX_TX_COUNT]; + u8 bw160_diff[MAX_RF_PATH][MAX_TX_COUNT]; +}; + +struct txpower_info_5g { + u8 index_bw40_base[MAX_RF_PATH][MAX_CHNL_GROUP_5G]; + /*If only one tx, only BW20, OFDM, BW80 and BW160 are used.*/ + u8 ofdm_diff[MAX_RF_PATH][MAX_TX_COUNT]; + u8 bw20_diff[MAX_RF_PATH][MAX_TX_COUNT]; + u8 bw40_diff[MAX_RF_PATH][MAX_TX_COUNT]; + u8 bw80_diff[MAX_RF_PATH][MAX_TX_COUNT]; + u8 bw160_diff[MAX_RF_PATH][MAX_TX_COUNT]; +}; + +enum rate_section { + CCK = 0, + OFDM, + HT_MCS0_MCS7, + HT_MCS8_MCS15, + VHT_1SSMCS0_1SSMCS9, + VHT_2SSMCS0_2SSMCS9, +}; + +enum intf_type { + INTF_PCI = 0, + INTF_USB = 1, +}; + +enum radio_path { + RF90_PATH_A = 0, + RF90_PATH_B = 1, + RF90_PATH_C = 2, + RF90_PATH_D = 3, +}; + +enum regulation_txpwr_lmt { + TXPWR_LMT_FCC = 0, + TXPWR_LMT_MKK = 1, + TXPWR_LMT_ETSI = 2, + TXPWR_LMT_WW = 3, + + TXPWR_LMT_MAX_REGULATION_NUM = 4 +}; + +enum rt_eeprom_type { + EEPROM_93C46, + EEPROM_93C56, + EEPROM_BOOT_EFUSE, +}; + +enum ttl_status { + RTL_STATUS_INTERFACE_START = 0, +}; + +enum hardware_type { + HARDWARE_TYPE_RTL8192E, + HARDWARE_TYPE_RTL8192U, + HARDWARE_TYPE_RTL8192SE, + HARDWARE_TYPE_RTL8192SU, + HARDWARE_TYPE_RTL8192CE, + HARDWARE_TYPE_RTL8192CU, + HARDWARE_TYPE_RTL8192DE, + HARDWARE_TYPE_RTL8192DU, + HARDWARE_TYPE_RTL8723AE, + HARDWARE_TYPE_RTL8723U, + HARDWARE_TYPE_RTL8188EE, + HARDWARE_TYPE_RTL8723BE, + HARDWARE_TYPE_RTL8192EE, + HARDWARE_TYPE_RTL8821AE, + HARDWARE_TYPE_RTL8812AE, + + /* keep it last */ + HARDWARE_TYPE_NUM +}; + +#define IS_HARDWARE_TYPE_8192SU(rtlhal) \ + (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SU) +#define IS_HARDWARE_TYPE_8192SE(rtlhal) \ + (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) +#define IS_HARDWARE_TYPE_8192CE(rtlhal) \ + (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) +#define IS_HARDWARE_TYPE_8192CU(rtlhal) \ + (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) +#define IS_HARDWARE_TYPE_8192DE(rtlhal) \ + (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) +#define IS_HARDWARE_TYPE_8192DU(rtlhal) \ + (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DU) +#define IS_HARDWARE_TYPE_8723E(rtlhal) \ + (rtlhal->hw_type == HARDWARE_TYPE_RTL8723E) +#define IS_HARDWARE_TYPE_8723U(rtlhal) \ + (rtlhal->hw_type == HARDWARE_TYPE_RTL8723U) +#define IS_HARDWARE_TYPE_8192S(rtlhal) \ +(IS_HARDWARE_TYPE_8192SE(rtlhal) || IS_HARDWARE_TYPE_8192SU(rtlhal)) +#define IS_HARDWARE_TYPE_8192C(rtlhal) \ +(IS_HARDWARE_TYPE_8192CE(rtlhal) || IS_HARDWARE_TYPE_8192CU(rtlhal)) +#define IS_HARDWARE_TYPE_8192D(rtlhal) \ +(IS_HARDWARE_TYPE_8192DE(rtlhal) || IS_HARDWARE_TYPE_8192DU(rtlhal)) +#define IS_HARDWARE_TYPE_8723(rtlhal) \ +(IS_HARDWARE_TYPE_8723E(rtlhal) || IS_HARDWARE_TYPE_8723U(rtlhal)) + +#define RX_HAL_IS_CCK_RATE(rxmcs) \ + ((rxmcs) == DESC_RATE1M || \ + (rxmcs) == DESC_RATE2M || \ + (rxmcs) == DESC_RATE5_5M || \ + (rxmcs) == DESC_RATE11M) + +enum scan_operation_backup_opt { + SCAN_OPT_BACKUP = 0, + SCAN_OPT_BACKUP_BAND0 = 0, + SCAN_OPT_BACKUP_BAND1, + SCAN_OPT_RESTORE, + SCAN_OPT_MAX +}; + +/*RF state.*/ +enum rf_pwrstate { + ERFON, + ERFSLEEP, + ERFOFF +}; + +struct bb_reg_def { + u32 rfintfs; + u32 rfintfi; + u32 rfintfo; + u32 rfintfe; + u32 rf3wire_offset; + u32 rflssi_select; + u32 rftxgain_stage; + u32 rfhssi_para1; + u32 rfhssi_para2; + u32 rfsw_ctrl; + u32 rfagc_control1; + u32 rfagc_control2; + u32 rfrxiq_imbal; + u32 rfrx_afe; + u32 rftxiq_imbal; + u32 rftx_afe; + u32 rf_rb; /* rflssi_readback */ + u32 rf_rbpi; /* rflssi_readbackpi */ +}; + +enum io_type { + IO_CMD_PAUSE_DM_BY_SCAN = 0, + IO_CMD_PAUSE_BAND0_DM_BY_SCAN = 0, + IO_CMD_PAUSE_BAND1_DM_BY_SCAN = 1, + IO_CMD_RESUME_DM_BY_SCAN = 2, +}; + +enum hw_variables { + HW_VAR_ETHER_ADDR, + HW_VAR_MULTICAST_REG, + HW_VAR_BASIC_RATE, + HW_VAR_BSSID, + HW_VAR_MEDIA_STATUS, + HW_VAR_SECURITY_CONF, + HW_VAR_BEACON_INTERVAL, + HW_VAR_ATIM_WINDOW, + HW_VAR_LISTEN_INTERVAL, + HW_VAR_CS_COUNTER, + HW_VAR_DEFAULTKEY0, + HW_VAR_DEFAULTKEY1, + HW_VAR_DEFAULTKEY2, + HW_VAR_DEFAULTKEY3, + HW_VAR_SIFS, + HW_VAR_R2T_SIFS, + HW_VAR_DIFS, + HW_VAR_EIFS, + HW_VAR_SLOT_TIME, + HW_VAR_ACK_PREAMBLE, + HW_VAR_CW_CONFIG, + HW_VAR_CW_VALUES, + HW_VAR_RATE_FALLBACK_CONTROL, + HW_VAR_CONTENTION_WINDOW, + HW_VAR_RETRY_COUNT, + HW_VAR_TR_SWITCH, + HW_VAR_COMMAND, + HW_VAR_WPA_CONFIG, + HW_VAR_AMPDU_MIN_SPACE, + HW_VAR_SHORTGI_DENSITY, + HW_VAR_AMPDU_FACTOR, + HW_VAR_MCS_RATE_AVAILABLE, + HW_VAR_AC_PARAM, + HW_VAR_ACM_CTRL, + HW_VAR_DIS_Req_Qsize, + HW_VAR_CCX_CHNL_LOAD, + HW_VAR_CCX_NOISE_HISTOGRAM, + HW_VAR_CCX_CLM_NHM, + HW_VAR_TxOPLimit, + HW_VAR_TURBO_MODE, + HW_VAR_RF_STATE, + HW_VAR_RF_OFF_BY_HW, + HW_VAR_BUS_SPEED, + HW_VAR_SET_DEV_POWER, + + HW_VAR_RCR, + HW_VAR_RATR_0, + HW_VAR_RRSR, + HW_VAR_CPU_RST, + HW_VAR_CHECK_BSSID, + HW_VAR_LBK_MODE, + HW_VAR_AES_11N_FIX, + HW_VAR_USB_RX_AGGR, + HW_VAR_USER_CONTROL_TURBO_MODE, + HW_VAR_RETRY_LIMIT, + HW_VAR_INIT_TX_RATE, + HW_VAR_TX_RATE_REG, + HW_VAR_EFUSE_USAGE, + HW_VAR_EFUSE_BYTES, + HW_VAR_AUTOLOAD_STATUS, + HW_VAR_RF_2R_DISABLE, + HW_VAR_SET_RPWM, + HW_VAR_H2C_FW_PWRMODE, + HW_VAR_H2C_FW_JOINBSSRPT, + HW_VAR_H2C_FW_MEDIASTATUSRPT, + HW_VAR_H2C_FW_P2P_PS_OFFLOAD, + HW_VAR_FW_PSMODE_STATUS, + HW_VAR_INIT_RTS_RATE, + HW_VAR_RESUME_CLK_ON, + HW_VAR_FW_LPS_ACTION, + HW_VAR_1X1_RECV_COMBINE, + HW_VAR_STOP_SEND_BEACON, + HW_VAR_TSF_TIMER, + HW_VAR_IO_CMD, + + HW_VAR_RF_RECOVERY, + HW_VAR_H2C_FW_UPDATE_GTK, + HW_VAR_WF_MASK, + HW_VAR_WF_CRC, + HW_VAR_WF_IS_MAC_ADDR, + HW_VAR_H2C_FW_OFFLOAD, + HW_VAR_RESET_WFCRC, + + HW_VAR_HANDLE_FW_C2H, + HW_VAR_DL_FW_RSVD_PAGE, + HW_VAR_AID, + HW_VAR_HW_SEQ_ENABLE, + HW_VAR_CORRECT_TSF, + HW_VAR_BCN_VALID, + HW_VAR_FWLPS_RF_ON, + HW_VAR_DUAL_TSF_RST, + HW_VAR_SWITCH_EPHY_WoWLAN, + HW_VAR_INT_MIGRATION, + HW_VAR_INT_AC, + HW_VAR_RF_TIMING, + + HAL_DEF_WOWLAN, + HW_VAR_MRC, + HW_VAR_KEEP_ALIVE, + HW_VAR_NAV_UPPER, + + HW_VAR_MGT_FILTER, + HW_VAR_CTRL_FILTER, + HW_VAR_DATA_FILTER, +}; + +enum rt_media_status { + RT_MEDIA_DISCONNECT = 0, + RT_MEDIA_CONNECT = 1 +}; + +enum rt_oem_id { + RT_CID_DEFAULT = 0, + RT_CID_8187_ALPHA0 = 1, + RT_CID_8187_SERCOMM_PS = 2, + RT_CID_8187_HW_LED = 3, + RT_CID_8187_NETGEAR = 4, + RT_CID_WHQL = 5, + RT_CID_819X_CAMEO = 6, + RT_CID_819X_RUNTOP = 7, + RT_CID_819X_SENAO = 8, + RT_CID_TOSHIBA = 9, + RT_CID_819X_NETCORE = 10, + RT_CID_NETTRONIX = 11, + RT_CID_DLINK = 12, + RT_CID_PRONET = 13, + RT_CID_COREGA = 14, + RT_CID_819X_ALPHA = 15, + RT_CID_819X_SITECOM = 16, + RT_CID_CCX = 17, + RT_CID_819X_LENOVO = 18, + RT_CID_819X_QMI = 19, + RT_CID_819X_EDIMAX_BELKIN = 20, + RT_CID_819X_SERCOMM_BELKIN = 21, + RT_CID_819X_CAMEO1 = 22, + RT_CID_819X_MSI = 23, + RT_CID_819X_ACER = 24, + RT_CID_819X_HP = 27, + RT_CID_819X_CLEVO = 28, + RT_CID_819X_ARCADYAN_BELKIN = 29, + RT_CID_819X_SAMSUNG = 30, + RT_CID_819X_WNC_COREGA = 31, + RT_CID_819X_FOXCOON = 32, + RT_CID_819X_DELL = 33, + RT_CID_819X_PRONETS = 34, + RT_CID_819X_EDIMAX_ASUS = 35, + RT_CID_NETGEAR = 36, + RT_CID_PLANEX = 37, + RT_CID_CC_C = 38, +}; + +enum hw_descs { + HW_DESC_OWN, + HW_DESC_RXOWN, + HW_DESC_TX_NEXTDESC_ADDR, + HW_DESC_TXBUFF_ADDR, + HW_DESC_RXBUFF_ADDR, + HW_DESC_RXPKT_LEN, + HW_DESC_RXERO, + HW_DESC_RX_PREPARE, +}; + +enum prime_sc { + PRIME_CHNL_OFFSET_DONT_CARE = 0, + PRIME_CHNL_OFFSET_LOWER = 1, + PRIME_CHNL_OFFSET_UPPER = 2, +}; + +enum rf_type { + RF_1T1R = 0, + RF_1T2R = 1, + RF_2T2R = 2, + RF_2T2R_GREEN = 3, +}; + +enum ht_channel_width { + HT_CHANNEL_WIDTH_20 = 0, + HT_CHANNEL_WIDTH_20_40 = 1, + HT_CHANNEL_WIDTH_80 = 2, +}; + +/* Ref: 802.11i sepc D10.0 7.3.2.25.1 +Cipher Suites Encryption Algorithms */ +enum rt_enc_alg { + NO_ENCRYPTION = 0, + WEP40_ENCRYPTION = 1, + TKIP_ENCRYPTION = 2, + RSERVED_ENCRYPTION = 3, + AESCCMP_ENCRYPTION = 4, + WEP104_ENCRYPTION = 5, + AESCMAC_ENCRYPTION = 6, /*IEEE802.11w */ +}; + +enum rtl_hal_state { + _HAL_STATE_STOP = 0, + _HAL_STATE_START = 1, +}; + +enum rtl_desc92_rate { + DESC_RATE1M = 0x00, + DESC_RATE2M = 0x01, + DESC_RATE5_5M = 0x02, + DESC_RATE11M = 0x03, + + DESC_RATE6M = 0x04, + DESC_RATE9M = 0x05, + DESC_RATE12M = 0x06, + DESC_RATE18M = 0x07, + DESC_RATE24M = 0x08, + DESC_RATE36M = 0x09, + DESC_RATE48M = 0x0a, + DESC_RATE54M = 0x0b, + + DESC_RATEMCS0 = 0x0c, + DESC_RATEMCS1 = 0x0d, + DESC_RATEMCS2 = 0x0e, + DESC_RATEMCS3 = 0x0f, + DESC_RATEMCS4 = 0x10, + DESC_RATEMCS5 = 0x11, + DESC_RATEMCS6 = 0x12, + DESC_RATEMCS7 = 0x13, + DESC_RATEMCS8 = 0x14, + DESC_RATEMCS9 = 0x15, + DESC_RATEMCS10 = 0x16, + DESC_RATEMCS11 = 0x17, + DESC_RATEMCS12 = 0x18, + DESC_RATEMCS13 = 0x19, + DESC_RATEMCS14 = 0x1a, + DESC_RATEMCS15 = 0x1b, + DESC_RATEMCS15_SG = 0x1c, + DESC_RATEMCS32 = 0x20, + + DESC_RATEVHT1SS_MCS0 = 0x2c, + DESC_RATEVHT1SS_MCS1 = 0x2d, + DESC_RATEVHT1SS_MCS2 = 0x2e, + DESC_RATEVHT1SS_MCS3 = 0x2f, + DESC_RATEVHT1SS_MCS4 = 0x30, + DESC_RATEVHT1SS_MCS5 = 0x31, + DESC_RATEVHT1SS_MCS6 = 0x32, + DESC_RATEVHT1SS_MCS7 = 0x33, + DESC_RATEVHT1SS_MCS8 = 0x34, + DESC_RATEVHT1SS_MCS9 = 0x35, + DESC_RATEVHT2SS_MCS0 = 0x36, + DESC_RATEVHT2SS_MCS1 = 0x37, + DESC_RATEVHT2SS_MCS2 = 0x38, + DESC_RATEVHT2SS_MCS3 = 0x39, + DESC_RATEVHT2SS_MCS4 = 0x3a, + DESC_RATEVHT2SS_MCS5 = 0x3b, + DESC_RATEVHT2SS_MCS6 = 0x3c, + DESC_RATEVHT2SS_MCS7 = 0x3d, + DESC_RATEVHT2SS_MCS8 = 0x3e, + DESC_RATEVHT2SS_MCS9 = 0x3f, +}; + +enum rtl_var_map { + /*reg map */ + SYS_ISO_CTRL = 0, + SYS_FUNC_EN, + SYS_CLK, + MAC_RCR_AM, + MAC_RCR_AB, + MAC_RCR_ACRC32, + MAC_RCR_ACF, + MAC_RCR_AAP, + MAC_HIMR, + MAC_HIMRE, + MAC_HSISR, + + /*efuse map */ + EFUSE_TEST, + EFUSE_CTRL, + EFUSE_CLK, + EFUSE_CLK_CTRL, + EFUSE_PWC_EV12V, + EFUSE_FEN_ELDR, + EFUSE_LOADER_CLK_EN, + EFUSE_ANA8M, + EFUSE_HWSET_MAX_SIZE, + EFUSE_MAX_SECTION_MAP, + EFUSE_REAL_CONTENT_SIZE, + EFUSE_OOB_PROTECT_BYTES_LEN, + EFUSE_ACCESS, + + /*CAM map */ + RWCAM, + WCAMI, + RCAMO, + CAMDBG, + SECR, + SEC_CAM_NONE, + SEC_CAM_WEP40, + SEC_CAM_TKIP, + SEC_CAM_AES, + SEC_CAM_WEP104, + + /*IMR map */ + RTL_IMR_BCNDMAINT6, /*Beacon DMA Interrupt 6 */ + RTL_IMR_BCNDMAINT5, /*Beacon DMA Interrupt 5 */ + RTL_IMR_BCNDMAINT4, /*Beacon DMA Interrupt 4 */ + RTL_IMR_BCNDMAINT3, /*Beacon DMA Interrupt 3 */ + RTL_IMR_BCNDMAINT2, /*Beacon DMA Interrupt 2 */ + RTL_IMR_BCNDMAINT1, /*Beacon DMA Interrupt 1 */ + RTL_IMR_BCNDOK8, /*Beacon Queue DMA OK Interrup 8 */ + RTL_IMR_BCNDOK7, /*Beacon Queue DMA OK Interrup 7 */ + RTL_IMR_BCNDOK6, /*Beacon Queue DMA OK Interrup 6 */ + RTL_IMR_BCNDOK5, /*Beacon Queue DMA OK Interrup 5 */ + RTL_IMR_BCNDOK4, /*Beacon Queue DMA OK Interrup 4 */ + RTL_IMR_BCNDOK3, /*Beacon Queue DMA OK Interrup 3 */ + RTL_IMR_BCNDOK2, /*Beacon Queue DMA OK Interrup 2 */ + RTL_IMR_BCNDOK1, /*Beacon Queue DMA OK Interrup 1 */ + RTL_IMR_TIMEOUT2, /*Timeout interrupt 2 */ + RTL_IMR_TIMEOUT1, /*Timeout interrupt 1 */ + RTL_IMR_TXFOVW, /*Transmit FIFO Overflow */ + RTL_IMR_PSTIMEOUT, /*Power save time out interrupt */ + RTL_IMR_BCNINT, /*Beacon DMA Interrupt 0 */ + RTL_IMR_RXFOVW, /*Receive FIFO Overflow */ + RTL_IMR_RDU, /*Receive Descriptor Unavailable */ + RTL_IMR_ATIMEND, /*For 92C,ATIM Window End Interrupt */ + RTL_IMR_BDOK, /*Beacon Queue DMA OK Interrup */ + RTL_IMR_HIGHDOK, /*High Queue DMA OK Interrupt */ + RTL_IMR_COMDOK, /*Command Queue DMA OK Interrupt*/ + RTL_IMR_TBDOK, /*Transmit Beacon OK interrup */ + RTL_IMR_MGNTDOK, /*Management Queue DMA OK Interrupt */ + RTL_IMR_TBDER, /*For 92C,Transmit Beacon Error Interrupt */ + RTL_IMR_BKDOK, /*AC_BK DMA OK Interrupt */ + RTL_IMR_BEDOK, /*AC_BE DMA OK Interrupt */ + RTL_IMR_VIDOK, /*AC_VI DMA OK Interrupt */ + RTL_IMR_VODOK, /*AC_VO DMA Interrupt */ + RTL_IMR_ROK, /*Receive DMA OK Interrupt */ + RTL_IMR_HSISR_IND, /*HSISR Interrupt*/ + RTL_IBSS_INT_MASKS, /*(RTL_IMR_BCNINT | RTL_IMR_TBDOK | + * RTL_IMR_TBDER) */ + RTL_IMR_C2HCMD, /*fw interrupt*/ + + /*CCK Rates, TxHT = 0 */ + RTL_RC_CCK_RATE1M, + RTL_RC_CCK_RATE2M, + RTL_RC_CCK_RATE5_5M, + RTL_RC_CCK_RATE11M, + + /*OFDM Rates, TxHT = 0 */ + RTL_RC_OFDM_RATE6M, + RTL_RC_OFDM_RATE9M, + RTL_RC_OFDM_RATE12M, + RTL_RC_OFDM_RATE18M, + RTL_RC_OFDM_RATE24M, + RTL_RC_OFDM_RATE36M, + RTL_RC_OFDM_RATE48M, + RTL_RC_OFDM_RATE54M, + + RTL_RC_HT_RATEMCS7, + RTL_RC_HT_RATEMCS15, + + RTL_RC_VHT_RATE_1SS_MCS7, + RTL_RC_VHT_RATE_1SS_MCS8, + RTL_RC_VHT_RATE_1SS_MCS9, + RTL_RC_VHT_RATE_2SS_MCS7, + RTL_RC_VHT_RATE_2SS_MCS8, + RTL_RC_VHT_RATE_2SS_MCS9, + + /*keep it last */ + RTL_VAR_MAP_MAX, +}; + +/*Firmware PS mode for control LPS.*/ +enum _fw_ps_mode { + FW_PS_ACTIVE_MODE = 0, + FW_PS_MIN_MODE = 1, + FW_PS_MAX_MODE = 2, + FW_PS_DTIM_MODE = 3, + FW_PS_VOIP_MODE = 4, + FW_PS_UAPSD_WMM_MODE = 5, + FW_PS_UAPSD_MODE = 6, + FW_PS_IBSS_MODE = 7, + FW_PS_WWLAN_MODE = 8, + FW_PS_PM_Radio_Off = 9, + FW_PS_PM_Card_Disable = 10, +}; + +enum rt_psmode { + EACTIVE, /*Active/Continuous access. */ + EMAXPS, /*Max power save mode. */ + EFASTPS, /*Fast power save mode. */ + EAUTOPS, /*Auto power save mode. */ +}; + +/*LED related.*/ +enum led_ctl_mode { + LED_CTL_POWER_ON = 1, + LED_CTL_LINK = 2, + LED_CTL_NO_LINK = 3, + LED_CTL_TX = 4, + LED_CTL_RX = 5, + LED_CTL_SITE_SURVEY = 6, + LED_CTL_POWER_OFF = 7, + LED_CTL_START_TO_LINK = 8, + LED_CTL_START_WPS = 9, + LED_CTL_STOP_WPS = 10, +}; + +enum rtl_led_pin { + LED_PIN_GPIO0, + LED_PIN_LED0, + LED_PIN_LED1, + LED_PIN_LED2 +}; + +/*QoS related.*/ +/*acm implementation method.*/ +enum acm_method { + eAcmWay0_SwAndHw = 0, + eAcmWay1_HW = 1, + EACMWAY2_SW = 2, +}; + +enum macphy_mode { + SINGLEMAC_SINGLEPHY = 0, + DUALMAC_DUALPHY, + DUALMAC_SINGLEPHY, +}; + +enum band_type { + BAND_ON_2_4G = 0, + BAND_ON_5G, + BAND_ON_BOTH, + BANDMAX +}; + +/*aci/aifsn Field. +Ref: WMM spec 2.2.2: WME Parameter Element, p.12.*/ +union aci_aifsn { + u8 char_data; + + struct { + u8 aifsn:4; + u8 acm:1; + u8 aci:2; + u8 reserved:1; + } f; /* Field */ +}; + +/*mlme related.*/ +enum wireless_mode { + WIRELESS_MODE_UNKNOWN = 0x00, + WIRELESS_MODE_A = 0x01, + WIRELESS_MODE_B = 0x02, + WIRELESS_MODE_G = 0x04, + WIRELESS_MODE_AUTO = 0x08, + WIRELESS_MODE_N_24G = 0x10, + WIRELESS_MODE_N_5G = 0x20, + WIRELESS_MODE_AC_5G = 0x40, + WIRELESS_MODE_AC_24G = 0x80, + WIRELESS_MODE_AC_ONLY = 0x100, + WIRELESS_MODE_MAX = 0x800 +}; + +#define IS_WIRELESS_MODE_A(wirelessmode) \ + (wirelessmode == WIRELESS_MODE_A) +#define IS_WIRELESS_MODE_B(wirelessmode) \ + (wirelessmode == WIRELESS_MODE_B) +#define IS_WIRELESS_MODE_G(wirelessmode) \ + (wirelessmode == WIRELESS_MODE_G) +#define IS_WIRELESS_MODE_N_24G(wirelessmode) \ + (wirelessmode == WIRELESS_MODE_N_24G) +#define IS_WIRELESS_MODE_N_5G(wirelessmode) \ + (wirelessmode == WIRELESS_MODE_N_5G) + +enum ratr_table_mode { + RATR_INX_WIRELESS_NGB = 0, + RATR_INX_WIRELESS_NG = 1, + RATR_INX_WIRELESS_NB = 2, + RATR_INX_WIRELESS_N = 3, + RATR_INX_WIRELESS_GB = 4, + RATR_INX_WIRELESS_G = 5, + RATR_INX_WIRELESS_B = 6, + RATR_INX_WIRELESS_MC = 7, + RATR_INX_WIRELESS_A = 8, + RATR_INX_WIRELESS_AC_5N = 8, + RATR_INX_WIRELESS_AC_24N = 9, +}; + +enum rtl_link_state { + MAC80211_NOLINK = 0, + MAC80211_LINKING = 1, + MAC80211_LINKED = 2, + MAC80211_LINKED_SCANNING = 3, +}; + +enum act_category { + ACT_CAT_QOS = 1, + ACT_CAT_DLS = 2, + ACT_CAT_BA = 3, + ACT_CAT_HT = 7, + ACT_CAT_WMM = 17, +}; + +enum ba_action { + ACT_ADDBAREQ = 0, + ACT_ADDBARSP = 1, + ACT_DELBA = 2, +}; + +enum rt_polarity_ctl { + RT_POLARITY_LOW_ACT = 0, + RT_POLARITY_HIGH_ACT = 1, +}; + +/* After 8188E, we use V2 reason define. 88C/8723A use V1 reason. */ +enum fw_wow_reason_v2 { + FW_WOW_V2_PTK_UPDATE_EVENT = 0x01, + FW_WOW_V2_GTK_UPDATE_EVENT = 0x02, + FW_WOW_V2_DISASSOC_EVENT = 0x04, + FW_WOW_V2_DEAUTH_EVENT = 0x08, + FW_WOW_V2_FW_DISCONNECT_EVENT = 0x10, + FW_WOW_V2_MAGIC_PKT_EVENT = 0x21, + FW_WOW_V2_UNICAST_PKT_EVENT = 0x22, + FW_WOW_V2_PATTERN_PKT_EVENT = 0x23, + FW_WOW_V2_RTD3_SSID_MATCH_EVENT = 0x24, + FW_WOW_V2_REALWOW_V2_WAKEUPPKT = 0x30, + FW_WOW_V2_REALWOW_V2_ACKLOST = 0x31, + FW_WOW_V2_REASON_MAX = 0xff, +}; + +enum wolpattern_type { + UNICAST_PATTERN = 0, + MULTICAST_PATTERN = 1, + BROADCAST_PATTERN = 2, + DONT_CARE_DA = 3, + UNKNOWN_TYPE = 4, +}; + +struct octet_string { + u8 *octet; + u16 length; +}; + +struct rtl_hdr_3addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; +} __packed; + +struct rtl_info_element { + u8 id; + u8 len; + u8 data[0]; +} __packed; + +struct rtl_probe_rsp { + struct rtl_hdr_3addr header; + u32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + /*SSID, supported rates, FH params, DS params, + CF params, IBSS params, TIM (if beacon), RSN */ + struct rtl_info_element info_element[0]; +} __packed; + +/*LED related.*/ +/*ledpin Identify how to implement this SW led.*/ +struct rtl_led { + void *hw; + enum rtl_led_pin ledpin; + bool ledon; +}; + +struct rtl_led_ctl { + bool led_opendrain; + struct rtl_led sw_led0; + struct rtl_led sw_led1; +}; + +struct rtl_qos_parameters { + __le16 cw_min; + __le16 cw_max; + u8 aifs; + u8 flag; + __le16 tx_op; +} __packed; + +struct rt_smooth_data { + u32 elements[100]; /*array to store values */ + u32 index; /*index to current array to store */ + u32 total_num; /*num of valid elements */ + u32 total_val; /*sum of valid elements */ +}; + +struct false_alarm_statistics { + u32 cnt_parity_fail; + u32 cnt_rate_illegal; + u32 cnt_crc8_fail; + u32 cnt_mcs_fail; + u32 cnt_fast_fsync_fail; + u32 cnt_sb_search_fail; + u32 cnt_ofdm_fail; + u32 cnt_cck_fail; + u32 cnt_all; + u32 cnt_ofdm_cca; + u32 cnt_cck_cca; + u32 cnt_cca_all; + u32 cnt_bw_usc; + u32 cnt_bw_lsc; +}; + +struct init_gain { + u8 xaagccore1; + u8 xbagccore1; + u8 xcagccore1; + u8 xdagccore1; + u8 cca; + +}; + +struct wireless_stats { + unsigned long txbytesunicast; + unsigned long txbytesmulticast; + unsigned long txbytesbroadcast; + unsigned long rxbytesunicast; + + long rx_snr_db[4]; + /*Correct smoothed ss in Dbm, only used + in driver to report real power now. */ + long recv_signal_power; + long signal_quality; + long last_sigstrength_inpercent; + + u32 rssi_calculate_cnt; + u32 pwdb_all_cnt; + + /*Transformed, in dbm. Beautified signal + strength for UI, not correct. */ + long signal_strength; + + u8 rx_rssi_percentage[4]; + u8 rx_evm_dbm[4]; + u8 rx_evm_percentage[2]; + + u16 rx_cfo_short[4]; + u16 rx_cfo_tail[4]; + + struct rt_smooth_data ui_rssi; + struct rt_smooth_data ui_link_quality; +}; + +struct rate_adaptive { + u8 rate_adaptive_disabled; + u8 ratr_state; + u16 reserve; + + u32 high_rssi_thresh_for_ra; + u32 high2low_rssi_thresh_for_ra; + u8 low2high_rssi_thresh_for_ra40m; + u32 low_rssi_thresh_for_ra40m; + u8 low2high_rssi_thresh_for_ra20m; + u32 low_rssi_thresh_for_ra20m; + u32 upper_rssi_threshold_ratr; + u32 middleupper_rssi_threshold_ratr; + u32 middle_rssi_threshold_ratr; + u32 middlelow_rssi_threshold_ratr; + u32 low_rssi_threshold_ratr; + u32 ultralow_rssi_threshold_ratr; + u32 low_rssi_threshold_ratr_40m; + u32 low_rssi_threshold_ratr_20m; + u8 ping_rssi_enable; + u32 ping_rssi_ratr; + u32 ping_rssi_thresh_for_ra; + u32 last_ratr; + u8 pre_ratr_state; + u8 ldpc_thres; + bool use_ldpc; + bool lower_rts_rate; + bool is_special_data; +}; + +struct regd_pair_mapping { + u16 reg_dmnenum; + u16 reg_5ghz_ctl; + u16 reg_2ghz_ctl; +}; + +struct dynamic_primary_cca { + u8 pricca_flag; + u8 intf_flag; + u8 intf_type; + u8 dup_rts_flag; + u8 monitor_flag; + u8 ch_offset; + u8 mf_state; +}; + +struct rtl_regulatory { + char alpha2[2]; + u16 country_code; + u16 max_power_level; + u32 tp_scale; + u16 current_rd; + u16 current_rd_ext; + int16_t power_limit; + struct regd_pair_mapping *regpair; +}; + +struct rtl_rfkill { + bool rfkill_state; /*0 is off, 1 is on */ +}; + +/*for P2P PS**/ +#define P2P_MAX_NOA_NUM 2 + +enum p2p_role { + P2P_ROLE_DISABLE = 0, + P2P_ROLE_DEVICE = 1, + P2P_ROLE_CLIENT = 2, + P2P_ROLE_GO = 3 +}; + +enum p2p_ps_state { + P2P_PS_DISABLE = 0, + P2P_PS_ENABLE = 1, + P2P_PS_SCAN = 2, + P2P_PS_SCAN_DONE = 3, + P2P_PS_ALLSTASLEEP = 4, /* for P2P GO */ +}; + +enum p2p_ps_mode { + P2P_PS_NONE = 0, + P2P_PS_CTWINDOW = 1, + P2P_PS_NOA = 2, + P2P_PS_MIX = 3, /* CTWindow and NoA */ +}; + +struct rtl_p2p_ps_info { + enum p2p_ps_mode p2p_ps_mode; /* indicate p2p ps mode */ + enum p2p_ps_state p2p_ps_state; /* indicate p2p ps state */ + u8 noa_index; /* Identifies instance of Notice of Absence timing. */ + /* Client traffic window. A period of time in TU after TBTT. */ + u8 ctwindow; + u8 opp_ps; /* opportunistic power save. */ + u8 noa_num; /* number of NoA descriptor in P2P IE. */ + /* Count for owner, Type of client. */ + u8 noa_count_type[P2P_MAX_NOA_NUM]; + /* Max duration for owner, preferred or min acceptable duration + * for client. + */ + u32 noa_duration[P2P_MAX_NOA_NUM]; + /* Length of interval for owner, preferred or max acceptable intervali + * of client. + */ + u32 noa_interval[P2P_MAX_NOA_NUM]; + /* schedule in terms of the lower 4 bytes of the TSF timer. */ + u32 noa_start_time[P2P_MAX_NOA_NUM]; +}; + +struct p2p_ps_offload_t { + u8 offload_en:1; + u8 role:1; /* 1: Owner, 0: Client */ + u8 ctwindow_en:1; + u8 noa0_en:1; + u8 noa1_en:1; + u8 allstasleep:1; + u8 discovery:1; + u8 reserved:1; +}; + +#define IQK_MATRIX_REG_NUM 8 +#define IQK_MATRIX_SETTINGS_NUM (1 + 24 + 21) + +struct iqk_matrix_regs { + bool iqk_done; + long value[1][IQK_MATRIX_REG_NUM]; +}; + +struct phy_parameters { + u16 length; + u32 *pdata; +}; + +enum hw_param_tab_index { + PHY_REG_2T, + PHY_REG_1T, + PHY_REG_PG, + RADIOA_2T, + RADIOB_2T, + RADIOA_1T, + RADIOB_1T, + MAC_REG, + AGCTAB_2T, + AGCTAB_1T, + MAX_TAB +}; + +struct rtl_phy { + struct bb_reg_def phyreg_def[4]; /*Radio A/B/C/D */ + struct init_gain initgain_backup; + enum io_type current_io_type; + + u8 rf_mode; + u8 rf_type; + u8 current_chan_bw; + u8 set_bwmode_inprogress; + u8 sw_chnl_inprogress; + u8 sw_chnl_stage; + u8 sw_chnl_step; + u8 current_channel; + u8 h2c_box_num; + u8 set_io_inprogress; + u8 lck_inprogress; + + /* record for power tracking */ + s32 reg_e94; + s32 reg_e9c; + s32 reg_ea4; + s32 reg_eac; + s32 reg_eb4; + s32 reg_ebc; + s32 reg_ec4; + s32 reg_ecc; + u8 rfpienable; + u8 reserve_0; + u16 reserve_1; + u32 reg_c04, reg_c08, reg_874; + u32 adda_backup[16]; + u32 iqk_mac_backup[IQK_MAC_REG_NUM]; + u32 iqk_bb_backup[10]; + bool iqk_initialized; + + bool rfpath_rx_enable[MAX_RF_PATH]; + u8 reg_837; + /* Dual mac */ + bool need_iqk; + struct iqk_matrix_regs iqk_matrix[IQK_MATRIX_SETTINGS_NUM]; + + bool rfpi_enable; + bool iqk_in_progress; + + u8 pwrgroup_cnt; + u8 cck_high_power; + /* this is for 88E & 8723A */ + u32 mcs_txpwrlevel_origoffset[MAX_PG_GROUP][16]; + /* MAX_PG_GROUP groups of pwr diff by rates */ + u32 mcs_offset[MAX_PG_GROUP][16]; + u32 tx_power_by_rate_offset[TX_PWR_BY_RATE_NUM_BAND] + [TX_PWR_BY_RATE_NUM_RF] + [TX_PWR_BY_RATE_NUM_RF] + [TX_PWR_BY_RATE_NUM_SECTION]; + u8 txpwr_by_rate_base_24g[TX_PWR_BY_RATE_NUM_RF] + [TX_PWR_BY_RATE_NUM_RF] + [MAX_BASE_NUM_IN_PHY_REG_PG_24G]; + u8 txpwr_by_rate_base_5g[TX_PWR_BY_RATE_NUM_RF] + [TX_PWR_BY_RATE_NUM_RF] + [MAX_BASE_NUM_IN_PHY_REG_PG_5G]; + u8 default_initialgain[4]; + + /* the current Tx power level */ + u8 cur_cck_txpwridx; + u8 cur_ofdm24g_txpwridx; + u8 cur_bw20_txpwridx; + u8 cur_bw40_txpwridx; + + char txpwr_limit_2_4g[MAX_REGULATION_NUM] + [MAX_2_4G_BANDWITH_NUM] + [MAX_RATE_SECTION_NUM] + [CHANNEL_MAX_NUMBER_2G] + [MAX_RF_PATH_NUM]; + char txpwr_limit_5g[MAX_REGULATION_NUM] + [MAX_5G_BANDWITH_NUM] + [MAX_RATE_SECTION_NUM] + [CHANNEL_MAX_NUMBER_5G] + [MAX_RF_PATH_NUM]; + + u32 rfreg_chnlval[2]; + bool apk_done; + u32 reg_rf3c[2]; /* pathA / pathB */ + + u32 backup_rf_0x1a;/*92ee*/ + /* bfsync */ + u8 framesync; + u32 framesync_c34; + + u8 num_total_rfpath; + struct phy_parameters hwparam_tables[MAX_TAB]; + u16 rf_pathmap; + + u8 hw_rof_enable; /*Enable GPIO[9] as WL RF HW PDn source*/ + enum rt_polarity_ctl polarity_ctl; +}; + +#define MAX_TID_COUNT 9 +#define RTL_AGG_STOP 0 +#define RTL_AGG_PROGRESS 1 +#define RTL_AGG_START 2 +#define RTL_AGG_OPERATIONAL 3 +#define RTL_AGG_OFF 0 +#define RTL_AGG_ON 1 +#define RTL_RX_AGG_START 1 +#define RTL_RX_AGG_STOP 0 +#define RTL_AGG_EMPTYING_HW_QUEUE_ADDBA 2 +#define RTL_AGG_EMPTYING_HW_QUEUE_DELBA 3 + +struct rtl_ht_agg { + u16 txq_id; + u16 wait_for_ba; + u16 start_idx; + u64 bitmap; + u32 rate_n_flags; + u8 agg_state; + u8 rx_agg_state; +}; + +struct rssi_sta { + long undec_sm_pwdb; + long undec_sm_cck; +}; + +struct rtl_tid_data { + u16 seq_number; + struct rtl_ht_agg agg; +}; + +struct rtl_sta_info { + struct list_head list; + u8 ratr_index; + u8 wireless_mode; + u8 mimo_ps; + u8 mac_addr[ETH_ALEN]; + struct rtl_tid_data tids[MAX_TID_COUNT]; + + /* just used for ap adhoc or mesh*/ + struct rssi_sta rssi_stat; +} __packed; + +struct rtl_priv; +struct rtl_io { + struct device *dev; + struct mutex bb_mutex; + + /*PCI MEM map */ + unsigned long pci_mem_end; /*shared mem end */ + unsigned long pci_mem_start; /*shared mem start */ + + /*PCI IO map */ + unsigned long pci_base_addr; /*device I/O address */ + + void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val); + void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val); + void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val); + void (*writeN_sync) (struct rtl_priv *rtlpriv, u32 addr, void *buf, + u16 len); + + u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr); + u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr); + u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr); + +}; + +struct rtl_mac { + u8 mac_addr[ETH_ALEN]; + u8 mac80211_registered; + u8 beacon_enabled; + + u32 tx_ss_num; + u32 rx_ss_num; + + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; + struct ieee80211_hw *hw; + struct ieee80211_vif *vif; + enum nl80211_iftype opmode; + + /*Probe Beacon management */ + struct rtl_tid_data tids[MAX_TID_COUNT]; + enum rtl_link_state link_state; + + int n_channels; + int n_bitrates; + + bool offchan_delay; + u8 p2p; /*using p2p role*/ + bool p2p_in_use; + + /*filters */ + u32 rx_conf; + u16 rx_mgt_filter; + u16 rx_ctrl_filter; + u16 rx_data_filter; + + bool act_scanning; + u8 cnt_after_linked; + bool skip_scan; + + /* early mode */ + /* skb wait queue */ + struct sk_buff_head skb_waitq[MAX_TID_COUNT]; + + u8 ht_stbc_cap; + u8 ht_cur_stbc; + + /*vht support*/ + u8 vht_enable; + u8 bw_80; + u8 vht_cur_ldpc; + u8 vht_cur_stbc; + u8 vht_stbc_cap; + u8 vht_ldpc_cap; + + /*RDG*/ + bool rdg_en; + + /*AP*/ + u8 bssid[ETH_ALEN] __aligned(2); + u32 vendor; + u8 mcs[16]; /* 16 bytes mcs for HT rates. */ + u32 basic_rates; /* b/g rates */ + u8 ht_enable; + u8 sgi_40; + u8 sgi_20; + u8 bw_40; + u16 mode; /* wireless mode */ + u8 slot_time; + u8 short_preamble; + u8 use_cts_protect; + u8 cur_40_prime_sc; + u8 cur_40_prime_sc_bk; + u8 cur_80_prime_sc; + u64 tsf; + u8 retry_short; + u8 retry_long; + u16 assoc_id; + bool hiddenssid; + + /*IBSS*/ + int beacon_interval; + + /*AMPDU*/ + u8 min_space_cfg; /*For Min spacing configurations */ + u8 max_mss_density; + u8 current_ampdu_factor; + u8 current_ampdu_density; + + /*QOS & EDCA */ + struct ieee80211_tx_queue_params edca_param[RTL_MAC80211_NUM_QUEUE]; + struct rtl_qos_parameters ac[AC_MAX]; + + /* counters */ + u64 last_txok_cnt; + u64 last_rxok_cnt; + u32 last_bt_edca_ul; + u32 last_bt_edca_dl; +}; + +struct btdm_8723 { + bool all_off; + bool agc_table_en; + bool adc_back_off_on; + bool b2_ant_hid_en; + bool low_penalty_rate_adaptive; + bool rf_rx_lpf_shrink; + bool reject_aggre_pkt; + bool tra_tdma_on; + u8 tra_tdma_nav; + u8 tra_tdma_ant; + bool tdma_on; + u8 tdma_ant; + u8 tdma_nav; + u8 tdma_dac_swing; + u8 fw_dac_swing_lvl; + bool ps_tdma_on; + u8 ps_tdma_byte[5]; + bool pta_on; + u32 val_0x6c0; + u32 val_0x6c8; + u32 val_0x6cc; + bool sw_dac_swing_on; + u32 sw_dac_swing_lvl; + u32 wlan_act_hi; + u32 wlan_act_lo; + u32 bt_retry_index; + bool dec_bt_pwr; + bool ignore_wlan_act; +}; + +struct bt_coexist_8723 { + u32 high_priority_tx; + u32 high_priority_rx; + u32 low_priority_tx; + u32 low_priority_rx; + u8 c2h_bt_info; + bool c2h_bt_info_req_sent; + bool c2h_bt_inquiry_page; + u32 bt_inq_page_start_time; + u8 bt_retry_cnt; + u8 c2h_bt_info_original; + u8 bt_inquiry_page_cnt; + struct btdm_8723 btdm; +}; + +struct rtl_hal { + struct ieee80211_hw *hw; + bool driver_is_goingto_unload; + bool up_first_time; + bool first_init; + bool being_init_adapter; + bool bbrf_ready; + bool mac_func_enable; + bool pre_edcca_enable; + struct bt_coexist_8723 hal_coex_8723; + + enum intf_type interface; + u16 hw_type; /*92c or 92d or 92s and so on */ + u8 ic_class; + u8 oem_id; + u32 version; /*version of chip */ + u8 state; /*stop 0, start 1 */ + u8 board_type; + u8 external_pa; + + u8 pa_mode; + u8 pa_type_2g; + u8 pa_type_5g; + u8 lna_type_2g; + u8 lna_type_5g; + u8 external_pa_2g; + u8 external_lna_2g; + u8 external_pa_5g; + u8 external_lna_5g; + u8 rfe_type; + + /*firmware */ + u32 fwsize; + u8 *pfirmware; + u16 fw_version; + u16 fw_subversion; + bool h2c_setinprogress; + u8 last_hmeboxnum; + bool fw_ready; + /*Reserve page start offset except beacon in TxQ. */ + u8 fw_rsvdpage_startoffset; + u8 h2c_txcmd_seq; + u8 current_ra_rate; + + /* FW Cmd IO related */ + u16 fwcmd_iomap; + u32 fwcmd_ioparam; + bool set_fwcmd_inprogress; + u8 current_fwcmd_io; + + struct p2p_ps_offload_t p2p_ps_offload; + bool fw_clk_change_in_progress; + bool allow_sw_to_change_hwclc; + u8 fw_ps_state; + /**/ + bool driver_going2unload; + + /*AMPDU init min space*/ + u8 minspace_cfg; /*For Min spacing configurations */ + + /* Dual mac */ + enum macphy_mode macphymode; + enum band_type current_bandtype; /* 0:2.4G, 1:5G */ + enum band_type current_bandtypebackup; + enum band_type bandset; + /* dual MAC 0--Mac0 1--Mac1 */ + u32 interfaceindex; + /* just for DualMac S3S4 */ + u8 macphyctl_reg; + bool earlymode_enable; + u8 max_earlymode_num; + /* Dual mac*/ + bool during_mac0init_radiob; + bool during_mac1init_radioa; + bool reloadtxpowerindex; + /* True if IMR or IQK have done + for 2.4G in scan progress */ + bool load_imrandiqk_setting_for2g; + + bool disable_amsdu_8k; + bool master_of_dmsp; + bool slave_of_dmsp; + + u16 rx_tag;/*for 92ee*/ + u8 rts_en; + + /*for wowlan*/ + bool wow_enable; + bool enter_pnp_sleep; + bool wake_from_pnp_sleep; + bool wow_enabled; + __kernel_time_t last_suspend_sec; + u32 wowlan_fwsize; + u8 *wowlan_firmware; + + u8 hw_rof_enable; /*Enable GPIO[9] as WL RF HW PDn source*/ + + bool real_wow_v2_enable; + bool re_init_llt_table; +}; + +struct rtl_security { + /*default 0 */ + bool use_sw_sec; + + bool being_setkey; + bool use_defaultkey; + /*Encryption Algorithm for Unicast Packet */ + enum rt_enc_alg pairwise_enc_algorithm; + /*Encryption Algorithm for Brocast/Multicast */ + enum rt_enc_alg group_enc_algorithm; + /*Cam Entry Bitmap */ + u32 hwsec_cam_bitmap; + u8 hwsec_cam_sta_addr[TOTAL_CAM_ENTRY][ETH_ALEN]; + /*local Key buffer, indx 0 is for + pairwise key 1-4 is for agoup key. */ + u8 key_buf[KEY_BUF_SIZE][MAX_KEY_LEN]; + u8 key_len[KEY_BUF_SIZE]; + + /*The pointer of Pairwise Key, + it always points to KeyBuf[4] */ + u8 *pairwise_key; +}; + +#define ASSOCIATE_ENTRY_NUM 33 + +struct fast_ant_training { + u8 bssid[6]; + u8 antsel_rx_keep_0; + u8 antsel_rx_keep_1; + u8 antsel_rx_keep_2; + u32 ant_sum[7]; + u32 ant_cnt[7]; + u32 ant_ave[7]; + u8 fat_state; + u32 train_idx; + u8 antsel_a[ASSOCIATE_ENTRY_NUM]; + u8 antsel_b[ASSOCIATE_ENTRY_NUM]; + u8 antsel_c[ASSOCIATE_ENTRY_NUM]; + u32 main_ant_sum[ASSOCIATE_ENTRY_NUM]; + u32 aux_ant_sum[ASSOCIATE_ENTRY_NUM]; + u32 main_ant_cnt[ASSOCIATE_ENTRY_NUM]; + u32 aux_ant_cnt[ASSOCIATE_ENTRY_NUM]; + u8 rx_idle_ant; + bool becomelinked; +}; + +struct dm_phy_dbg_info { + char rx_snrdb[4]; + u64 num_qry_phy_status; + u64 num_qry_phy_status_cck; + u64 num_qry_phy_status_ofdm; + u16 num_qry_beacon_pkt; + u16 num_non_be_pkt; + s32 rx_evm[4]; +}; + +struct rtl_dm { + /*PHY status for Dynamic Management */ + long entry_min_undec_sm_pwdb; + long undec_sm_cck; + long undec_sm_pwdb; /*out dm */ + long entry_max_undec_sm_pwdb; + s32 ofdm_pkt_cnt; + bool dm_initialgain_enable; + bool dynamic_txpower_enable; + bool current_turbo_edca; + bool is_any_nonbepkts; /*out dm */ + bool is_cur_rdlstate; + bool txpower_trackinginit; + bool disable_framebursting; + bool cck_inch14; + bool txpower_tracking; + bool useramask; + bool rfpath_rxenable[4]; + bool inform_fw_driverctrldm; + bool current_mrc_switch; + u8 txpowercount; + u8 powerindex_backup[6]; + + u8 thermalvalue_rxgain; + u8 thermalvalue_iqk; + u8 thermalvalue_lck; + u8 thermalvalue; + u8 last_dtp_lvl; + u8 thermalvalue_avg[AVG_THERMAL_NUM]; + u8 thermalvalue_avg_index; + u8 tm_trigger; + bool done_txpower; + u8 dynamic_txhighpower_lvl; /*Tx high power level */ + u8 dm_flag; /*Indicate each dynamic mechanism's status. */ + u8 dm_flag_tmp; + u8 dm_type; + u8 dm_rssi_sel; + u8 txpower_track_control; + bool interrupt_migration; + bool disable_tx_int; + char ofdm_index[MAX_RF_PATH]; + u8 default_ofdm_index; + u8 default_cck_index; + char cck_index; + char delta_power_index[MAX_RF_PATH]; + char delta_power_index_last[MAX_RF_PATH]; + char power_index_offset[MAX_RF_PATH]; + char absolute_ofdm_swing_idx[MAX_RF_PATH]; + char remnant_ofdm_swing_idx[MAX_RF_PATH]; + char remnant_cck_idx; + bool modify_txagc_flag_path_a; + bool modify_txagc_flag_path_b; + + bool one_entry_only; + struct dm_phy_dbg_info dbginfo; + + /* Dynamic ATC switch */ + bool atc_status; + bool large_cfo_hit; + bool is_freeze; + int cfo_tail[2]; + int cfo_ave_pre; + int crystal_cap; + u8 cfo_threshold; + u32 packet_count; + u32 packet_count_pre; + u8 tx_rate; + + /*88e tx power tracking*/ + u8 swing_idx_ofdm[MAX_RF_PATH]; + u8 swing_idx_ofdm_cur; + u8 swing_idx_ofdm_base[MAX_RF_PATH]; + bool swing_flag_ofdm; + u8 swing_idx_cck; + u8 swing_idx_cck_cur; + u8 swing_idx_cck_base; + bool swing_flag_cck; + + char swing_diff_2g; + char swing_diff_5g; + + u8 delta_swing_table_idx_24gccka_p[DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_24gccka_n[DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_24gcckb_p[DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_24gcckb_n[DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_24ga_p[DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_24ga_n[DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_24gb_p[DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_24gb_n[DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_5ga_p[BAND_NUM][DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_5ga_n[BAND_NUM][DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_5gb_p[BAND_NUM][DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_5gb_n[BAND_NUM][DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_24ga_p_8188e[DEL_SW_IDX_SZ]; + u8 delta_swing_table_idx_24ga_n_8188e[DEL_SW_IDX_SZ]; + + /* DMSP */ + bool supp_phymode_switch; + + /* DulMac */ + struct fast_ant_training fat_table; + + u8 resp_tx_path; + u8 path_sel; + u32 patha_sum; + u32 pathb_sum; + u32 patha_cnt; + u32 pathb_cnt; + + u8 pre_channel; + u8 *p_channel; + u8 linked_interval; + + u64 last_tx_ok_cnt; + u64 last_rx_ok_cnt; +}; + +#define EFUSE_MAX_LOGICAL_SIZE 512 + +struct rtl_efuse { + bool autoLoad_ok; + bool bootfromefuse; + u16 max_physical_size; + + u8 efuse_map[2][EFUSE_MAX_LOGICAL_SIZE]; + u16 efuse_usedbytes; + u8 efuse_usedpercentage; +#ifdef EFUSE_REPG_WORKAROUND + bool efuse_re_pg_sec1flag; + u8 efuse_re_pg_data[8]; +#endif + + u8 autoload_failflag; + u8 autoload_status; + + short epromtype; + u16 eeprom_vid; + u16 eeprom_did; + u16 eeprom_svid; + u16 eeprom_smid; + u8 eeprom_oemid; + u16 eeprom_channelplan; + u8 eeprom_version; + u8 board_type; + u8 external_pa; + + u8 dev_addr[6]; + u8 wowlan_enable; + u8 antenna_div_cfg; + u8 antenna_div_type; + + bool txpwr_fromeprom; + u8 eeprom_crystalcap; + u8 eeprom_tssi[2]; + u8 eeprom_tssi_5g[3][2]; /* for 5GL/5GM/5GH band. */ + u8 eeprom_pwrlimit_ht20[CHANNEL_GROUP_MAX]; + u8 eeprom_pwrlimit_ht40[CHANNEL_GROUP_MAX]; + u8 eeprom_chnlarea_txpwr_cck[MAX_RF_PATH][CHANNEL_GROUP_MAX_2G]; + u8 eeprom_chnlarea_txpwr_ht40_1s[MAX_RF_PATH][CHANNEL_GROUP_MAX]; + u8 eprom_chnl_txpwr_ht40_2sdf[MAX_RF_PATH][CHANNEL_GROUP_MAX]; + + u8 internal_pa_5g[2]; /* pathA / pathB */ + u8 eeprom_c9; + u8 eeprom_cc; + + /*For power group */ + u8 eeprom_pwrgroup[2][3]; + u8 pwrgroup_ht20[2][CHANNEL_MAX_NUMBER]; + u8 pwrgroup_ht40[2][CHANNEL_MAX_NUMBER]; + + u8 txpwrlevel_cck[MAX_RF_PATH][CHANNEL_MAX_NUMBER_2G]; + /*For HT 40MHZ pwr */ + u8 txpwrlevel_ht40_1s[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; + /*For HT 40MHZ pwr */ + u8 txpwrlevel_ht40_2s[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; + + /*--------------------------------------------------------* + * 8192CE\8192SE\8192DE\8723AE use the following 4 arrays, + * other ICs (8188EE\8723BE\8192EE\8812AE...) + * define new arrays in Windows code. + * BUT, in linux code, we use the same array for all ICs. + * + * The Correspondance relation between two arrays is: + * txpwr_cckdiff[][] == CCK_24G_Diff[][] + * txpwr_ht20diff[][] == BW20_24G_Diff[][] + * txpwr_ht40diff[][] == BW40_24G_Diff[][] + * txpwr_legacyhtdiff[][] == OFDM_24G_Diff[][] + * + * Sizes of these arrays are decided by the larger ones. + */ + char txpwr_cckdiff[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; + char txpwr_ht20diff[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; + char txpwr_ht40diff[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; + char txpwr_legacyhtdiff[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; + + u8 txpwr_5g_bw40base[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; + u8 txpwr_5g_bw80base[MAX_RF_PATH][CHANNEL_MAX_NUMBER_5G_80M]; + char txpwr_5g_ofdmdiff[MAX_RF_PATH][MAX_TX_COUNT]; + char txpwr_5g_bw20diff[MAX_RF_PATH][MAX_TX_COUNT]; + char txpwr_5g_bw40diff[MAX_RF_PATH][MAX_TX_COUNT]; + char txpwr_5g_bw80diff[MAX_RF_PATH][MAX_TX_COUNT]; + + u8 txpwr_safetyflag; /* Band edge enable flag */ + u16 eeprom_txpowerdiff; + u8 legacy_httxpowerdiff; /* Legacy to HT rate power diff */ + u8 antenna_txpwdiff[3]; + + u8 eeprom_regulatory; + u8 eeprom_thermalmeter; + u8 thermalmeter[2]; /*ThermalMeter, index 0 for RFIC0, 1 for RFIC1 */ + u16 tssi_13dbm; + u8 crystalcap; /* CrystalCap. */ + u8 delta_iqk; + u8 delta_lck; + + u8 legacy_ht_txpowerdiff; /*Legacy to HT rate power diff */ + bool apk_thermalmeterignore; + + bool b1x1_recvcombine; + bool b1ss_support; + + /*channel plan */ + u8 channel_plan; +}; + +struct rtl_ps_ctl { + bool pwrdomain_protect; + bool in_powersavemode; + bool rfchange_inprogress; + bool swrf_processing; + bool hwradiooff; + /* + * just for PCIE ASPM + * If it supports ASPM, Offset[560h] = 0x40, + * otherwise Offset[560h] = 0x00. + * */ + bool support_aspm; + bool support_backdoor; + + /*for LPS */ + enum rt_psmode dot11_psmode; /*Power save mode configured. */ + bool swctrl_lps; + bool leisure_ps; + bool fwctrl_lps; + u8 fwctrl_psmode; + /*For Fw control LPS mode */ + u8 reg_fwctrl_lps; + /*Record Fw PS mode status. */ + bool fw_current_inpsmode; + u8 reg_max_lps_awakeintvl; + bool report_linked; + bool low_power_enable;/*for 32k*/ + + /*for IPS */ + bool inactiveps; + + u32 rfoff_reason; + + /*RF OFF Level */ + u32 cur_ps_level; + u32 reg_rfps_level; + + /*just for PCIE ASPM */ + u8 const_amdpci_aspm; + bool pwrdown_mode; + + enum rf_pwrstate inactive_pwrstate; + enum rf_pwrstate rfpwr_state; /*cur power state */ + + /* for SW LPS*/ + bool sw_ps_enabled; + bool state; + bool state_inap; + bool multi_buffered; + u16 nullfunc_seq; + unsigned int dtim_counter; + unsigned int sleep_ms; + unsigned long last_sleep_jiffies; + unsigned long last_awake_jiffies; + unsigned long last_delaylps_stamp_jiffies; + unsigned long last_dtim; + unsigned long last_beacon; + unsigned long last_action; + unsigned long last_slept; + + /*For P2P PS */ + struct rtl_p2p_ps_info p2p_ps_info; + u8 pwr_mode; + u8 smart_ps; + + /* wake up on line */ + u8 wo_wlan_mode; + u8 arp_offload_enable; + u8 gtk_offload_enable; + /* Used for WOL, indicates the reason for waking event.*/ + u32 wakeup_reason; + /* Record the last waking time for comparison with setting key. */ + u64 last_wakeup_time; +}; + +struct rtl_stats { + u8 psaddr[ETH_ALEN]; + u32 mac_time[2]; + s8 rssi; + u8 signal; + u8 noise; + u8 rate; /* hw desc rate */ + u8 received_channel; + u8 control; + u8 mask; + u8 freq; + u16 len; + u64 tsf; + u32 beacon_time; + u8 nic_type; + u16 length; + u8 signalquality; /*in 0-100 index. */ + /* + * Real power in dBm for this packet, + * no beautification and aggregation. + * */ + s32 recvsignalpower; + s8 rxpower; /*in dBm Translate from PWdB */ + u8 signalstrength; /*in 0-100 index. */ + u16 hwerror:1; + u16 crc:1; + u16 icv:1; + u16 shortpreamble:1; + u16 antenna:1; + u16 decrypted:1; + u16 wakeup:1; + u32 timestamp_low; + u32 timestamp_high; + bool shift; + + u8 rx_drvinfo_size; + u8 rx_bufshift; + bool isampdu; + bool isfirst_ampdu; + bool rx_is40Mhzpacket; + u8 rx_packet_bw; + u32 rx_pwdb_all; + u8 rx_mimo_signalstrength[4]; /*in 0~100 index */ + s8 rx_mimo_signalquality[4]; + u8 rx_mimo_evm_dbm[4]; + u16 cfo_short[4]; /* per-path's Cfo_short */ + u16 cfo_tail[4]; + + s8 rx_mimo_sig_qual[4]; + u8 rx_pwr[4]; /* per-path's pwdb */ + u8 rx_snr[4]; /* per-path's SNR */ + u8 bandwidth; + u8 bt_coex_pwr_adjust; + bool packet_matchbssid; + bool is_cck; + bool is_ht; + bool packet_toself; + bool packet_beacon; /*for rssi */ + char cck_adc_pwdb[4]; /*for rx path selection */ + + bool is_vht; + bool is_short_gi; + u8 vht_nss; + + u8 packet_report_type; + + u32 macid; + u8 wake_match; + u32 bt_rx_rssi_percentage; + u32 macid_valid_entry[2]; +}; + + +struct rt_link_detect { + /* count for roaming */ + u32 bcn_rx_inperiod; + u32 roam_times; + + u32 num_tx_in4period[4]; + u32 num_rx_in4period[4]; + + u32 num_tx_inperiod; + u32 num_rx_inperiod; + + bool busytraffic; + bool tx_busy_traffic; + bool rx_busy_traffic; + bool higher_busytraffic; + bool higher_busyrxtraffic; + + u32 tidtx_in4period[MAX_TID_COUNT][4]; + u32 tidtx_inperiod[MAX_TID_COUNT]; + bool higher_busytxtraffic[MAX_TID_COUNT]; +}; + +struct rtl_tcb_desc { + u8 packet_bw:2; + u8 multicast:1; + u8 broadcast:1; + + u8 rts_stbc:1; + u8 rts_enable:1; + u8 cts_enable:1; + u8 rts_use_shortpreamble:1; + u8 rts_use_shortgi:1; + u8 rts_sc:1; + u8 rts_bw:1; + u8 rts_rate; + + u8 use_shortgi:1; + u8 use_shortpreamble:1; + u8 use_driver_rate:1; + u8 disable_ratefallback:1; + + u8 ratr_index; + u8 mac_id; + u8 hw_rate; + + u8 last_inipkt:1; + u8 cmd_or_init:1; + u8 queue_index; + + /* early mode */ + u8 empkt_num; + /* The max value by HW */ + u32 empkt_len[10]; + bool tx_enable_sw_calc_duration; +}; + +struct rtl_wow_pattern { + u8 type; + u16 crc; + u32 mask[4]; +}; + +struct rtl_hal_ops { + int (*init_sw_vars) (struct ieee80211_hw *hw); + void (*deinit_sw_vars) (struct ieee80211_hw *hw); + void (*read_chip_version)(struct ieee80211_hw *hw); + void (*read_eeprom_info) (struct ieee80211_hw *hw); + void (*interrupt_recognized) (struct ieee80211_hw *hw, + u32 *p_inta, u32 *p_intb); + int (*hw_init) (struct ieee80211_hw *hw); + void (*hw_disable) (struct ieee80211_hw *hw); + void (*hw_suspend) (struct ieee80211_hw *hw); + void (*hw_resume) (struct ieee80211_hw *hw); + void (*enable_interrupt) (struct ieee80211_hw *hw); + void (*disable_interrupt) (struct ieee80211_hw *hw); + int (*set_network_type) (struct ieee80211_hw *hw, + enum nl80211_iftype type); + void (*set_chk_bssid)(struct ieee80211_hw *hw, + bool check_bssid); + void (*set_bw_mode) (struct ieee80211_hw *hw, + enum nl80211_channel_type ch_type); + u8(*switch_channel) (struct ieee80211_hw *hw); + void (*set_qos) (struct ieee80211_hw *hw, int aci); + void (*set_bcn_reg) (struct ieee80211_hw *hw); + void (*set_bcn_intv) (struct ieee80211_hw *hw); + void (*update_interrupt_mask) (struct ieee80211_hw *hw, + u32 add_msr, u32 rm_msr); + void (*get_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); + void (*set_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); + void (*update_rate_tbl) (struct ieee80211_hw *hw, + struct ieee80211_sta *sta, u8 rssi_level); + void (*pre_fill_tx_bd_desc)(struct ieee80211_hw *hw, u8 *tx_bd_desc, + u8 *desc, u8 queue_index, + struct sk_buff *skb, dma_addr_t addr); + void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level); + u16 (*rx_desc_buff_remained_cnt)(struct ieee80211_hw *hw, + u8 queue_index); + void (*rx_check_dma_ok)(struct ieee80211_hw *hw, u8 *header_desc, + u8 queue_index); + void (*fill_tx_desc) (struct ieee80211_hw *hw, + struct ieee80211_hdr *hdr, u8 *pdesc_tx, + u8 *pbd_desc_tx, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, u8 hw_queue, + struct rtl_tcb_desc *ptcb_desc); + void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 *pDesc, + u32 buffer_len, bool bIsPsPoll); + void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc, + bool firstseg, bool lastseg, + struct sk_buff *skb); + bool (*query_rx_desc) (struct ieee80211_hw *hw, + struct rtl_stats *stats, + struct ieee80211_rx_status *rx_status, + u8 *pdesc, struct sk_buff *skb); + void (*set_channel_access) (struct ieee80211_hw *hw); + bool (*radio_onoff_checking) (struct ieee80211_hw *hw, u8 *valid); + void (*dm_watchdog) (struct ieee80211_hw *hw); + void (*scan_operation_backup) (struct ieee80211_hw *hw, u8 operation); + bool (*set_rf_power_state) (struct ieee80211_hw *hw, + enum rf_pwrstate rfpwr_state); + void (*led_control) (struct ieee80211_hw *hw, + enum led_ctl_mode ledaction); + void (*set_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx, + u8 desc_name, u8 *val); + u32 (*get_desc) (u8 *pdesc, bool istx, u8 desc_name); + bool (*is_tx_desc_closed) (struct ieee80211_hw *hw, + u8 hw_queue, u16 index); + void (*tx_polling) (struct ieee80211_hw *hw, u8 hw_queue); + void (*enable_hw_sec) (struct ieee80211_hw *hw); + void (*set_key) (struct ieee80211_hw *hw, u32 key_index, + u8 *macaddr, bool is_group, u8 enc_algo, + bool is_wepkey, bool clear_all); + void (*init_sw_leds) (struct ieee80211_hw *hw); + void (*deinit_sw_leds) (struct ieee80211_hw *hw); + u32 (*get_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); + void (*set_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, + u32 data); + u32 (*get_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask); + void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, + u32 regaddr, u32 bitmask, u32 data); + void (*linked_set_reg) (struct ieee80211_hw *hw); + void (*chk_switch_dmdp) (struct ieee80211_hw *hw); + void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw); + void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw); + bool (*phy_rf6052_config) (struct ieee80211_hw *hw); + void (*phy_rf6052_set_cck_txpower) (struct ieee80211_hw *hw, + u8 *powerlevel); + void (*phy_rf6052_set_ofdm_txpower) (struct ieee80211_hw *hw, + u8 *ppowerlevel, u8 channel); + bool (*config_bb_with_headerfile) (struct ieee80211_hw *hw, + u8 configtype); + bool (*config_bb_with_pgheaderfile) (struct ieee80211_hw *hw, + u8 configtype); + void (*phy_lc_calibrate) (struct ieee80211_hw *hw, bool is2t); + void (*phy_set_bw_mode_callback) (struct ieee80211_hw *hw); + void (*dm_dynamic_txpower) (struct ieee80211_hw *hw); + void (*c2h_command_handle) (struct ieee80211_hw *hw); + void (*bt_wifi_media_status_notify) (struct ieee80211_hw *hw, + bool mstate); + void (*bt_coex_off_before_lps) (struct ieee80211_hw *hw); + void (*fill_h2c_cmd) (struct ieee80211_hw *hw, u8 element_id, + u32 cmd_len, u8 *p_cmdbuffer); + bool (*get_btc_status) (void); + bool (*is_fw_header)(struct rtlwifi_firmware_header *hdr); + u32 (*rx_command_packet)(struct ieee80211_hw *hw, + struct rtl_stats status, struct sk_buff *skb); + void (*add_wowlan_pattern)(struct ieee80211_hw *hw, + struct rtl_wow_pattern *rtl_pattern, + u8 index); + u16 (*get_available_desc)(struct ieee80211_hw *hw, u8 q_idx); +}; + +struct rtl_intf_ops { + /*com */ + void (*read_efuse_byte)(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); + int (*adapter_start) (struct ieee80211_hw *hw); + void (*adapter_stop) (struct ieee80211_hw *hw); + bool (*check_buddy_priv)(struct ieee80211_hw *hw, + struct rtl_priv **buddy_priv); + + int (*adapter_tx) (struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb, + struct rtl_tcb_desc *ptcb_desc); + void (*flush)(struct ieee80211_hw *hw, u32 queues, bool drop); + int (*reset_trx_ring) (struct ieee80211_hw *hw); + bool (*waitq_insert) (struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb); + + /*pci */ + void (*disable_aspm) (struct ieee80211_hw *hw); + void (*enable_aspm) (struct ieee80211_hw *hw); + + /*usb */ +}; + +struct rtl_mod_params { + /* default: 0 = using hardware encryption */ + bool sw_crypto; + + /* default: 0 = DBG_EMERG (0)*/ + int debug; + + /* default: 1 = using no linked power save */ + bool inactiveps; + + /* default: 1 = using linked sw power save */ + bool swctrl_lps; + + /* default: 1 = using linked fw power save */ + bool fwctrl_lps; + + /* default: 0 = not using MSI interrupts mode + * submodules should set their own default value + */ + bool msi_support; + + /* default 0: 1 means disable */ + bool disable_watchdog; +}; + +struct rtl_hal_usbint_cfg { + /* data - rx */ + u32 in_ep_num; + u32 rx_urb_num; + u32 rx_max_size; + + /* op - rx */ + void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *); + void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *, + struct sk_buff_head *); + + /* tx */ + void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *); + int (*usb_tx_post_hdl)(struct ieee80211_hw *, struct urb *, + struct sk_buff *); + struct sk_buff *(*usb_tx_aggregate_hdl)(struct ieee80211_hw *, + struct sk_buff_head *); + + /* endpoint mapping */ + int (*usb_endpoint_mapping)(struct ieee80211_hw *hw); + u16 (*usb_mq_to_hwq)(__le16 fc, u16 mac80211_queue_index); +}; + +struct rtl_hal_cfg { + u8 bar_id; + bool write_readback; + char *name; + char *fw_name; + char *alt_fw_name; + char *wowlan_fw_name; + struct rtl_hal_ops *ops; + struct rtl_mod_params *mod_params; + struct rtl_hal_usbint_cfg *usb_interface_cfg; + + /*this map used for some registers or vars + defined int HAL but used in MAIN */ + u32 maps[RTL_VAR_MAP_MAX]; + +}; + +struct rtl_locks { + /* mutex */ + struct mutex conf_mutex; + struct mutex ps_mutex; + + /*spin lock */ + spinlock_t ips_lock; + spinlock_t irq_th_lock; + spinlock_t irq_pci_lock; + spinlock_t tx_lock; + spinlock_t h2c_lock; + spinlock_t rf_ps_lock; + spinlock_t rf_lock; + spinlock_t lps_lock; + spinlock_t waitq_lock; + spinlock_t entry_list_lock; + spinlock_t usb_lock; + + /*FW clock change */ + spinlock_t fw_ps_lock; + + /*Dual mac*/ + spinlock_t cck_and_rw_pagea_lock; + + /*Easy concurrent*/ + spinlock_t check_sendpkt_lock; + + spinlock_t iqk_lock; +}; + +struct rtl_works { + struct ieee80211_hw *hw; + + /*timer */ + struct timer_list watchdog_timer; + struct timer_list dualmac_easyconcurrent_retrytimer; + struct timer_list fw_clockoff_timer; + struct timer_list fast_antenna_training_timer; + /*task */ + struct tasklet_struct irq_tasklet; + struct tasklet_struct irq_prepare_bcn_tasklet; + + /*work queue */ + struct workqueue_struct *rtl_wq; + struct delayed_work watchdog_wq; + struct delayed_work ips_nic_off_wq; + + /* For SW LPS */ + struct delayed_work ps_work; + struct delayed_work ps_rfon_wq; + struct delayed_work fwevt_wq; + + struct work_struct lps_change_work; + 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 + +struct rtl_dualmac_easy_concurrent_ctl { + enum band_type currentbandtype_backfordmdp; + bool close_bbandrf_for_dmsp; + bool change_to_dmdp; + bool change_to_dmsp; + bool switch_in_process; +}; + +struct rtl_dmsp_ctl { + bool activescan_for_slaveofdmsp; + bool scan_for_anothermac_fordmsp; + bool scan_for_itself_fordmsp; + bool writedig_for_anothermacofdmsp; + u32 curdigvalue_for_anothermacofdmsp; + bool changecckpdstate_for_anothermacofdmsp; + u8 curcckpdstate_for_anothermacofdmsp; + bool changetxhighpowerlvl_for_anothermacofdmsp; + u8 curtxhighlvl_for_anothermacofdmsp; + long rssivalmin_for_anothermacofdmsp; +}; + +struct ps_t { + u8 pre_ccastate; + u8 cur_ccasate; + u8 pre_rfstate; + u8 cur_rfstate; + u8 initialize; + long rssi_val_min; +}; + +struct dig_t { + u32 rssi_lowthresh; + u32 rssi_highthresh; + u32 fa_lowthresh; + u32 fa_highthresh; + long last_min_undec_pwdb_for_dm; + long rssi_highpower_lowthresh; + long rssi_highpower_highthresh; + u32 recover_cnt; + u32 pre_igvalue; + u32 cur_igvalue; + long rssi_val; + u8 dig_enable_flag; + u8 dig_ext_port_stage; + u8 dig_algorithm; + u8 dig_twoport_algorithm; + u8 dig_dbgmode; + u8 dig_slgorithm_switch; + u8 cursta_cstate; + u8 presta_cstate; + u8 curmultista_cstate; + u8 stop_dig; + char back_val; + char back_range_max; + char back_range_min; + u8 rx_gain_max; + u8 rx_gain_min; + u8 min_undec_pwdb_for_dm; + u8 rssi_val_min; + u8 pre_cck_cca_thres; + u8 cur_cck_cca_thres; + u8 pre_cck_pd_state; + u8 cur_cck_pd_state; + u8 pre_cck_fa_state; + u8 cur_cck_fa_state; + u8 pre_ccastate; + u8 cur_ccasate; + u8 large_fa_hit; + u8 forbidden_igi; + u8 dig_state; + u8 dig_highpwrstate; + u8 cur_sta_cstate; + u8 pre_sta_cstate; + u8 cur_ap_cstate; + u8 pre_ap_cstate; + u8 cur_pd_thstate; + u8 pre_pd_thstate; + u8 cur_cs_ratiostate; + u8 pre_cs_ratiostate; + u8 backoff_enable_flag; + char backoffval_range_max; + char backoffval_range_min; + u8 dig_min_0; + u8 dig_min_1; + u8 bt30_cur_igi; + bool media_connect_0; + bool media_connect_1; + + u32 antdiv_rssi_max; + u32 rssi_max; +}; + +struct rtl_global_var { + /* from this list we can get + * other adapter's rtl_priv */ + struct list_head glb_priv_list; + spinlock_t glb_list_lock; +}; + +struct rtl_btc_info { + u8 bt_type; + u8 btcoexist; + u8 ant_num; +}; + +struct bt_coexist_info { + struct rtl_btc_ops *btc_ops; + struct rtl_btc_info btc_info; + /* EEPROM BT info. */ + u8 eeprom_bt_coexist; + u8 eeprom_bt_type; + u8 eeprom_bt_ant_num; + u8 eeprom_bt_ant_isol; + u8 eeprom_bt_radio_shared; + + u8 bt_coexistence; + u8 bt_ant_num; + u8 bt_coexist_type; + u8 bt_state; + u8 bt_cur_state; /* 0:on, 1:off */ + u8 bt_ant_isolation; /* 0:good, 1:bad */ + u8 bt_pape_ctrl; /* 0:SW, 1:SW/HW dynamic */ + u8 bt_service; + u8 bt_radio_shared_type; + u8 bt_rfreg_origin_1e; + u8 bt_rfreg_origin_1f; + u8 bt_rssi_state; + u32 ratio_tx; + u32 ratio_pri; + u32 bt_edca_ul; + u32 bt_edca_dl; + + bool init_set; + bool bt_busy_traffic; + bool bt_traffic_mode_set; + bool bt_non_traffic_mode_set; + + bool fw_coexist_all_off; + bool sw_coexist_all_off; + bool hw_coexist_all_off; + u32 cstate; + u32 previous_state; + u32 cstate_h; + u32 previous_state_h; + + u8 bt_pre_rssi_state; + u8 bt_pre_rssi_state1; + + u8 reg_bt_iso; + u8 reg_bt_sco; + bool balance_on; + u8 bt_active_zero_cnt; + bool cur_bt_disabled; + bool pre_bt_disabled; + + u8 bt_profile_case; + u8 bt_profile_action; + bool bt_busy; + bool hold_for_bt_operation; + u8 lps_counter; +}; + +struct rtl_btc_ops { + void (*btc_init_variables) (struct rtl_priv *rtlpriv); + void (*btc_init_hal_vars) (struct rtl_priv *rtlpriv); + void (*btc_init_hw_config) (struct rtl_priv *rtlpriv); + void (*btc_ips_notify) (struct rtl_priv *rtlpriv, u8 type); + void (*btc_lps_notify)(struct rtl_priv *rtlpriv, u8 type); + void (*btc_scan_notify) (struct rtl_priv *rtlpriv, u8 scantype); + void (*btc_connect_notify) (struct rtl_priv *rtlpriv, u8 action); + void (*btc_mediastatus_notify) (struct rtl_priv *rtlpriv, + enum rt_media_status mstatus); + void (*btc_periodical) (struct rtl_priv *rtlpriv); + void (*btc_halt_notify) (void); + void (*btc_btinfo_notify) (struct rtl_priv *rtlpriv, + u8 *tmp_buf, u8 length); + bool (*btc_is_limited_dig) (struct rtl_priv *rtlpriv); + bool (*btc_is_disable_edca_turbo) (struct rtl_priv *rtlpriv); + bool (*btc_is_bt_disabled) (struct rtl_priv *rtlpriv); + void (*btc_special_packet_notify)(struct rtl_priv *rtlpriv, + u8 pkt_type); +}; + +struct proxim { + bool proxim_on; + + void *proximity_priv; + int (*proxim_rx)(struct ieee80211_hw *hw, struct rtl_stats *status, + struct sk_buff *skb); + u8 (*proxim_get_var)(struct ieee80211_hw *hw, u8 type); +}; + +struct rtl_priv { + struct ieee80211_hw *hw; + struct completion firmware_loading_complete; + struct list_head list; + struct rtl_priv *buddy_priv; + struct rtl_global_var *glb_var; + struct rtl_dualmac_easy_concurrent_ctl easy_concurrent_ctl; + struct rtl_dmsp_ctl dmsp_ctl; + struct rtl_locks locks; + struct rtl_works works; + struct rtl_mac mac80211; + struct rtl_hal rtlhal; + struct rtl_regulatory regd; + struct rtl_rfkill rfkill; + struct rtl_io io; + struct rtl_phy phy; + struct rtl_dm dm; + struct rtl_security sec; + struct rtl_efuse efuse; + + struct rtl_ps_ctl psc; + struct rate_adaptive ra; + struct dynamic_primary_cca primarycca; + struct wireless_stats stats; + struct rt_link_detect link_info; + struct false_alarm_statistics falsealm_cnt; + + struct rtl_rate_priv *rate_priv; + + /* sta entry list for ap adhoc or mesh */ + struct list_head entry_list; + + struct rtl_debug dbg; + int max_fw_size; + + /* + *hal_cfg : for diff cards + *intf_ops : for diff interrface usb/pcie + */ + struct rtl_hal_cfg *cfg; + struct rtl_intf_ops *intf_ops; + + /*this var will be set by set_bit, + and was used to indicate status of + interface or hardware */ + unsigned long status; + + /* tables for dm */ + struct dig_t dm_digtable; + struct ps_t dm_pstable; + + u32 reg_874; + u32 reg_c70; + u32 reg_85c; + u32 reg_a74; + bool reg_init; /* true if regs saved */ + bool bt_operation_on; + __le32 *usb_data; + int usb_data_index; + bool initialized; + bool enter_ps; /* true when entering PS */ + u8 rate_mask[5]; + + /* intel Proximity, should be alloc mem + * in intel Proximity module and can only + * be used in intel Proximity mode + */ + struct proxim proximity; + + /*for bt coexist use*/ + struct bt_coexist_info btcoexist; + + /* separate 92ee from other ICs, + * 92ee use new trx flow. + */ + bool use_new_trx_flow; + +#ifdef CONFIG_PM + struct wiphy_wowlan_support wowlan; +#endif + /*This must be the last item so + that it points to the data allocated + beyond this structure like: + rtl_pci_priv or rtl_usb_priv */ + u8 priv[0] __aligned(sizeof(void *)); +}; + +#define rtl_priv(hw) (((struct rtl_priv *)(hw)->priv)) +#define rtl_mac(rtlpriv) (&((rtlpriv)->mac80211)) +#define rtl_hal(rtlpriv) (&((rtlpriv)->rtlhal)) +#define rtl_efuse(rtlpriv) (&((rtlpriv)->efuse)) +#define rtl_psc(rtlpriv) (&((rtlpriv)->psc)) + + +/*************************************** + Bluetooth Co-existence Related +****************************************/ + +enum bt_ant_num { + ANT_X2 = 0, + ANT_X1 = 1, +}; + +enum bt_co_type { + BT_2WIRE = 0, + BT_ISSC_3WIRE = 1, + BT_ACCEL = 2, + BT_CSR_BC4 = 3, + BT_CSR_BC8 = 4, + BT_RTL8756 = 5, + BT_RTL8723A = 6, + BT_RTL8821A = 7, + BT_RTL8723B = 8, + BT_RTL8192E = 9, + BT_RTL8812A = 11, +}; + +enum bt_total_ant_num { + ANT_TOTAL_X2 = 0, + ANT_TOTAL_X1 = 1 +}; + +enum bt_cur_state { + BT_OFF = 0, + BT_ON = 1, +}; + +enum bt_service_type { + BT_SCO = 0, + BT_A2DP = 1, + BT_HID = 2, + BT_HID_IDLE = 3, + BT_SCAN = 4, + BT_IDLE = 5, + BT_OTHER_ACTION = 6, + BT_BUSY = 7, + BT_OTHERBUSY = 8, + BT_PAN = 9, +}; + +enum bt_radio_shared { + BT_RADIO_SHARED = 0, + BT_RADIO_INDIVIDUAL = 1, +}; + + +/**************************************** + mem access macro define start + Call endian free function when + 1. Read/write packet content. + 2. Before write integer to IO. + 3. After read integer from IO. +****************************************/ +/* Convert little data endian to host ordering */ +#define EF1BYTE(_val) \ + ((u8)(_val)) +#define EF2BYTE(_val) \ + (le16_to_cpu(_val)) +#define EF4BYTE(_val) \ + (le32_to_cpu(_val)) + +/* Read data from memory */ +#define READEF1BYTE(_ptr) \ + EF1BYTE(*((u8 *)(_ptr))) +/* Read le16 data from memory and convert to host ordering */ +#define READEF2BYTE(_ptr) \ + EF2BYTE(*(_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 + * BIT_LEN_MASK_32(1) => 0x00000001 + * BIT_LEN_MASK_32(2) => 0x00000003 + * BIT_LEN_MASK_32(32) => 0xFFFFFFFF + */ +#define BIT_LEN_MASK_32(__bitlen) \ + (0xFFFFFFFF >> (32 - (__bitlen))) +#define BIT_LEN_MASK_16(__bitlen) \ + (0xFFFF >> (16 - (__bitlen))) +#define BIT_LEN_MASK_8(__bitlen) \ + (0xFF >> (8 - (__bitlen))) + +/* Create an offset bit mask + * Examples: + * BIT_OFFSET_LEN_MASK_32(0, 2) => 0x00000003 + * BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000 + */ +#define BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen) \ + (BIT_LEN_MASK_32(__bitlen) << (__bitoffset)) +#define BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen) \ + (BIT_LEN_MASK_16(__bitlen) << (__bitoffset)) +#define BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen) \ + (BIT_LEN_MASK_8(__bitlen) << (__bitoffset)) + +/*Description: + * Return 4-byte value in host byte ordering from + * 4-byte pointer in little-endian system. + */ +#define LE_P4BYTE_TO_HOST_4BYTE(__pstart) \ + (EF4BYTE(*((__le32 *)(__pstart)))) +#define LE_P2BYTE_TO_HOST_2BYTE(__pstart) \ + (EF2BYTE(*((__le16 *)(__pstart)))) +#define LE_P1BYTE_TO_HOST_1BYTE(__pstart) \ + (EF1BYTE(*((u8 *)(__pstart)))) + +/*Description: +Translate subfield (continuous bits in little-endian) of 4-byte +value to host byte ordering.*/ +#define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + (LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \ + BIT_LEN_MASK_32(__bitlen) \ + ) +#define LE_BITS_TO_2BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + (LE_P2BYTE_TO_HOST_2BYTE(__pstart) >> (__bitoffset)) & \ + BIT_LEN_MASK_16(__bitlen) \ + ) +#define LE_BITS_TO_1BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + (LE_P1BYTE_TO_HOST_1BYTE(__pstart) >> (__bitoffset)) & \ + BIT_LEN_MASK_8(__bitlen) \ + ) + +/* Description: + * Mask subfield (continuous bits in little-endian) of 4-byte value + * and return the result in 4-byte value in host byte ordering. + */ +#define LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + LE_P4BYTE_TO_HOST_4BYTE(__pstart) & \ + (~BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen)) \ + ) +#define LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + LE_P2BYTE_TO_HOST_2BYTE(__pstart) & \ + (~BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen)) \ + ) +#define LE_BITS_CLEARED_TO_1BYTE(__pstart, __bitoffset, __bitlen) \ + ( \ + LE_P1BYTE_TO_HOST_1BYTE(__pstart) & \ + (~BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen)) \ + ) + +/* Description: + * Set subfield of little-endian 4-byte value to specified value. + */ +#define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \ + *((u32 *)(__pstart)) = \ + ( \ + 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)) = \ + ( \ + LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \ + ((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \ + ); +#define SET_BITS_TO_LE_1BYTE(__pstart, __bitoffset, __bitlen, __val) \ + *((u8 *)(__pstart)) = EF1BYTE \ + ( \ + LE_BITS_CLEARED_TO_1BYTE(__pstart, __bitoffset, __bitlen) | \ + ((((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset)) \ + ); + +#define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \ + (__value) : (((__value + __aligment - 1) / __aligment) * __aligment)) + +/**************************************** + mem access macro define end +****************************************/ + +#define byte(x, n) ((x >> (8 * n)) & 0xff) + +#define packet_get_type(_packet) (EF1BYTE((_packet).octet[0]) & 0xFC) +#define RTL_WATCH_DOG_TIME 2000 +#define MSECS(t) msecs_to_jiffies(t) +#define WLAN_FC_GET_VERS(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_VERS) +#define WLAN_FC_GET_TYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) +#define WLAN_FC_GET_STYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) +#define WLAN_FC_MORE_DATA(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA) +#define rtl_dm(rtlpriv) (&((rtlpriv)->dm)) + +#define RT_RF_OFF_LEVL_ASPM BIT(0) /*PCI ASPM */ +#define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /*PCI clock request */ +#define RT_RF_OFF_LEVL_PCI_D3 BIT(2) /*PCI D3 mode */ +/*NIC halt, re-initialize hw parameters*/ +#define RT_RF_OFF_LEVL_HALT_NIC BIT(3) +#define RT_RF_OFF_LEVL_FREE_FW BIT(4) /*FW free, re-download the FW */ +#define RT_RF_OFF_LEVL_FW_32K BIT(5) /*FW in 32k */ +/*Always enable ASPM and Clock Req in initialization.*/ +#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT(6) +/* no matter RFOFF or SLEEP we set PS_ASPM_LEVL*/ +#define RT_PS_LEVEL_ASPM BIT(7) +/*When LPS is on, disable 2R if no packet is received or transmittd.*/ +#define RT_RF_LPS_DISALBE_2R BIT(30) +#define RT_RF_LPS_LEVEL_ASPM BIT(31) /*LPS with ASPM */ +#define RT_IN_PS_LEVEL(ppsc, _ps_flg) \ + ((ppsc->cur_ps_level & _ps_flg) ? true : false) +#define RT_CLEAR_PS_LEVEL(ppsc, _ps_flg) \ + (ppsc->cur_ps_level &= (~(_ps_flg))) +#define RT_SET_PS_LEVEL(ppsc, _ps_flg) \ + (ppsc->cur_ps_level |= _ps_flg) + +#define container_of_dwork_rtl(x, y, z) \ + container_of(container_of(x, struct delayed_work, work), y, z) + +#define FILL_OCTET_STRING(_os, _octet, _len) \ + (_os).octet = (u8 *)(_octet); \ + (_os).length = (_len); + +#define CP_MACADDR(des, src) \ + ((des)[0] = (src)[0], (des)[1] = (src)[1],\ + (des)[2] = (src)[2], (des)[3] = (src)[3],\ + (des)[4] = (src)[4], (des)[5] = (src)[5]) + +#define LDPC_HT_ENABLE_RX BIT(0) +#define LDPC_HT_ENABLE_TX BIT(1) +#define LDPC_HT_TEST_TX_ENABLE BIT(2) +#define LDPC_HT_CAP_TX BIT(3) + +#define STBC_HT_ENABLE_RX BIT(0) +#define STBC_HT_ENABLE_TX BIT(1) +#define STBC_HT_TEST_TX_ENABLE BIT(2) +#define STBC_HT_CAP_TX BIT(3) + +#define LDPC_VHT_ENABLE_RX BIT(0) +#define LDPC_VHT_ENABLE_TX BIT(1) +#define LDPC_VHT_TEST_TX_ENABLE BIT(2) +#define LDPC_VHT_CAP_TX BIT(3) + +#define STBC_VHT_ENABLE_RX BIT(0) +#define STBC_VHT_ENABLE_TX BIT(1) +#define STBC_VHT_TEST_TX_ENABLE BIT(2) +#define STBC_VHT_CAP_TX BIT(3) + +static inline u8 rtl_read_byte(struct rtl_priv *rtlpriv, u32 addr) +{ + return rtlpriv->io.read8_sync(rtlpriv, addr); +} + +static inline u16 rtl_read_word(struct rtl_priv *rtlpriv, u32 addr) +{ + return rtlpriv->io.read16_sync(rtlpriv, addr); +} + +static inline u32 rtl_read_dword(struct rtl_priv *rtlpriv, u32 addr) +{ + return rtlpriv->io.read32_sync(rtlpriv, addr); +} + +static inline void rtl_write_byte(struct rtl_priv *rtlpriv, u32 addr, u8 val8) +{ + rtlpriv->io.write8_async(rtlpriv, addr, val8); + + if (rtlpriv->cfg->write_readback) + rtlpriv->io.read8_sync(rtlpriv, addr); +} + +static inline void rtl_write_word(struct rtl_priv *rtlpriv, u32 addr, u16 val16) +{ + rtlpriv->io.write16_async(rtlpriv, addr, val16); + + if (rtlpriv->cfg->write_readback) + rtlpriv->io.read16_sync(rtlpriv, addr); +} + +static inline void rtl_write_dword(struct rtl_priv *rtlpriv, + u32 addr, u32 val32) +{ + rtlpriv->io.write32_async(rtlpriv, addr, val32); + + if (rtlpriv->cfg->write_readback) + rtlpriv->io.read32_sync(rtlpriv, addr); +} + +static inline u32 rtl_get_bbreg(struct ieee80211_hw *hw, + u32 regaddr, u32 bitmask) +{ + struct rtl_priv *rtlpriv = hw->priv; + + return rtlpriv->cfg->ops->get_bbreg(hw, regaddr, bitmask); +} + +static inline void rtl_set_bbreg(struct ieee80211_hw *hw, u32 regaddr, + u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = hw->priv; + + rtlpriv->cfg->ops->set_bbreg(hw, regaddr, bitmask, data); +} + +static inline u32 rtl_get_rfreg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask) +{ + struct rtl_priv *rtlpriv = hw->priv; + + return rtlpriv->cfg->ops->get_rfreg(hw, rfpath, regaddr, bitmask); +} + +static inline void rtl_set_rfreg(struct ieee80211_hw *hw, + enum radio_path rfpath, u32 regaddr, + u32 bitmask, u32 data) +{ + struct rtl_priv *rtlpriv = hw->priv; + + rtlpriv->cfg->ops->set_rfreg(hw, rfpath, regaddr, bitmask, data); +} + +static inline bool is_hal_stop(struct rtl_hal *rtlhal) +{ + return (_HAL_STATE_STOP == rtlhal->state); +} + +static inline void set_hal_start(struct rtl_hal *rtlhal) +{ + rtlhal->state = _HAL_STATE_START; +} + +static inline void set_hal_stop(struct rtl_hal *rtlhal) +{ + rtlhal->state = _HAL_STATE_STOP; +} + +static inline u8 get_rf_type(struct rtl_phy *rtlphy) +{ + return rtlphy->rf_type; +} + +static inline struct ieee80211_hdr *rtl_get_hdr(struct sk_buff *skb) +{ + return (struct ieee80211_hdr *)(skb->data); +} + +static inline __le16 rtl_get_fc(struct sk_buff *skb) +{ + return rtl_get_hdr(skb)->frame_control; +} + +static inline u16 rtl_get_tid_h(struct ieee80211_hdr *hdr) +{ + return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; +} + +static inline u16 rtl_get_tid(struct sk_buff *skb) +{ + return rtl_get_tid_h(rtl_get_hdr(skb)); +} + +static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + const u8 *bssid) +{ + return ieee80211_find_sta(vif, bssid); +} + +static inline struct ieee80211_sta *rtl_find_sta(struct ieee80211_hw *hw, + u8 *mac_addr) +{ + struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); + return ieee80211_find_sta(mac->vif, mac_addr); +} + +#endif diff --git a/drivers/net/wireless/rtl818x/Kconfig b/drivers/net/wireless/rtl818x/Kconfig deleted file mode 100644 index 1ce1d55f0010..000000000000 --- a/drivers/net/wireless/rtl818x/Kconfig +++ /dev/null @@ -1,88 +0,0 @@ -# -# RTL818X Wireless LAN device configuration -# -config RTL8180 - tristate "Realtek 8180/8185/8187SE PCI support" - depends on MAC80211 && PCI - select EEPROM_93CX6 - ---help--- - This is a driver for RTL8180, RTL8185 and RTL8187SE based cards. - These are PCI based chips found in cards such as: - - (RTL8185 802.11g) - A-Link WL54PC - - (RTL8180 802.11b) - Belkin F5D6020 v3 - Belkin F5D6020 v3 - Dlink DWL-610 - Dlink DWL-510 - Netgear MA521 - Level-One WPC-0101 - Acer Aspire 1357 LMi - VCTnet PC-11B1 - Ovislink AirLive WL-1120PCM - Mentor WL-PCI - Linksys WPC11 v4 - TrendNET TEW-288PI - D-Link DWL-520 Rev D - Repotec RP-WP7126 - TP-Link TL-WN250/251 - Zonet ZEW1000 - Longshine LCS-8031-R - HomeLine HLW-PCC200 - GigaFast WF721-AEX - Planet WL-3553 - Encore ENLWI-PCI1-NT - TrendNET TEW-266PC - Gigabyte GN-WLMR101 - Siemens-fujitsu Amilo D1840W - Edimax EW-7126 - PheeNet WL-11PCIR - Tonze PC-2100T - Planet WL-8303 - Dlink DWL-650 v M1 - Edimax EW-7106 - Q-Tec 770WC - Topcom Skyr@cer 4011b - Roper FreeLan 802.11b (edition 2004) - Wistron Neweb Corp CB-200B - Pentagram HorNET - QTec 775WC - TwinMOS Booming B Series - Micronet SP906BB - Sweex LC700010 - Surecom EP-9428 - Safecom SWLCR-1100 - - Thanks to Realtek for their support! - -config RTL8187 - tristate "Realtek 8187 and 8187B USB support" - depends on MAC80211 && USB - select EEPROM_93CX6 - ---help--- - This is a driver for RTL8187 and RTL8187B based cards. - These are USB based chips found in devices such as: - - Netgear WG111v2 - Level 1 WNC-0301USB - Micronet SP907GK V5 - Encore ENUWI-G2 - Trendnet TEW-424UB - ASUS P5B Deluxe/P5K Premium motherboards - Toshiba Satellite Pro series of laptops - Asus Wireless Link - Linksys WUSB54GC-EU v2 - (v1 = rt73usb; v3 is rt2070-based, - use staging/rt3070 or try rt2800usb) - - Thanks to Realtek for their support! - -# If possible, automatically enable LEDs for RTL8187. - -config RTL8187_LEDS - bool - depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187) - default y - diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/rtl818x/Makefile deleted file mode 100644 index 997569076923..000000000000 --- a/drivers/net/wireless/rtl818x/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_RTL8180) += rtl8180/ -obj-$(CONFIG_RTL8187) += rtl8187/ diff --git a/drivers/net/wireless/rtl818x/rtl8180/Makefile b/drivers/net/wireless/rtl818x/rtl8180/Makefile deleted file mode 100644 index 21005bd8b43c..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -rtl818x_pci-objs := dev.o rtl8225.o sa2400.o max2820.o grf5101.o rtl8225se.o - -obj-$(CONFIG_RTL8180) += rtl818x_pci.o - -ccflags-y += -Idrivers/net/wireless/rtl818x diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c deleted file mode 100644 index a43a16fde59d..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ /dev/null @@ -1,1991 +0,0 @@ - -/* Linux device driver for RTL8180 / RTL8185 / RTL8187SE - * - * Copyright 2007 Michael Wu - * Copyright 2007,2014 Andrea Merello - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello , et al. - * - * Thanks to Realtek for their support! - * - ************************************************************************ - * - * The driver was extended to the RTL8187SE in 2014 by - * Andrea Merello - * - * based also on: - * - portions of rtl8187se Linux staging driver, Copyright Realtek corp. - * (available in drivers/staging/rtl8187se directory of Linux 3.14) - * - other GPL, unpublished (until now), Linux driver code, - * Copyright Larry Finger - * - * A huge thanks goes to Sara V. Nari who forgives me when I'm - * sitting in front of my laptop at evening, week-end, night... - * - * A special thanks goes to Antonio Cuni, who helped me with - * some python userspace stuff I used to debug RTL8187SE code, and who - * bought a laptop with an unsupported Wi-Fi card some years ago... - * - * Thanks to Larry Finger for writing some code for rtl8187se and for - * his suggestions. - * - * Thanks to Dan Carpenter for reviewing my initial patch and for his - * suggestions. - * - * Thanks to Bernhard Schiffner for his help in testing and for his - * suggestions. - * - ************************************************************************ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rtl8180.h" -#include "rtl8225.h" -#include "sa2400.h" -#include "max2820.h" -#include "grf5101.h" -#include "rtl8225se.h" - -MODULE_AUTHOR("Michael Wu "); -MODULE_AUTHOR("Andrea Merello "); -MODULE_DESCRIPTION("RTL8180 / RTL8185 / RTL8187SE PCI wireless driver"); -MODULE_LICENSE("GPL"); - -static const struct pci_device_id rtl8180_table[] = { - - /* rtl8187se */ - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8199) }, - - /* rtl8185 */ - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) }, - { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x700f) }, - { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x701f) }, - - /* rtl8180 */ - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8180) }, - { PCI_DEVICE(0x1799, 0x6001) }, - { PCI_DEVICE(0x1799, 0x6020) }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x3300) }, - { PCI_DEVICE(0x1186, 0x3301) }, - { PCI_DEVICE(0x1432, 0x7106) }, - { } -}; - -MODULE_DEVICE_TABLE(pci, rtl8180_table); - -static const struct ieee80211_rate rtl818x_rates[] = { - { .bitrate = 10, .hw_value = 0, }, - { .bitrate = 20, .hw_value = 1, }, - { .bitrate = 55, .hw_value = 2, }, - { .bitrate = 110, .hw_value = 3, }, - { .bitrate = 60, .hw_value = 4, }, - { .bitrate = 90, .hw_value = 5, }, - { .bitrate = 120, .hw_value = 6, }, - { .bitrate = 180, .hw_value = 7, }, - { .bitrate = 240, .hw_value = 8, }, - { .bitrate = 360, .hw_value = 9, }, - { .bitrate = 480, .hw_value = 10, }, - { .bitrate = 540, .hw_value = 11, }, -}; - -static const struct ieee80211_channel rtl818x_channels[] = { - { .center_freq = 2412 }, - { .center_freq = 2417 }, - { .center_freq = 2422 }, - { .center_freq = 2427 }, - { .center_freq = 2432 }, - { .center_freq = 2437 }, - { .center_freq = 2442 }, - { .center_freq = 2447 }, - { .center_freq = 2452 }, - { .center_freq = 2457 }, - { .center_freq = 2462 }, - { .center_freq = 2467 }, - { .center_freq = 2472 }, - { .center_freq = 2484 }, -}; - -/* Queues for rtl8187se card - * - * name | reg | queue - * BC | 7 | 6 - * MG | 1 | 0 - * HI | 6 | 1 - * VO | 5 | 2 - * VI | 4 | 3 - * BE | 3 | 4 - * BK | 2 | 5 - * - * The complete map for DMA kick reg using use all queue is: - * static const int rtl8187se_queues_map[RTL8187SE_NR_TX_QUEUES] = - * {1, 6, 5, 4, 3, 2, 7}; - * - * .. but.. Because for mac80211 4 queues are enough for QoS we use this - * - * name | reg | queue - * BC | 7 | 4 <- currently not used yet - * MG | 1 | x <- Not used - * HI | 6 | x <- Not used - * VO | 5 | 0 <- used - * VI | 4 | 1 <- used - * BE | 3 | 2 <- used - * BK | 2 | 3 <- used - * - * Beacon queue could be used, but this is not finished yet. - * - * I thougth about using the other two queues but I decided not to do this: - * - * - I'm unsure whether the mac80211 will ever try to use more than 4 queues - * by itself. - * - * - I could route MGMT frames (currently sent over VO queue) to the MGMT - * queue but since mac80211 will do not know about it, I will probably gain - * some HW priority whenever the VO queue is not empty, but this gain is - * limited by the fact that I had to stop the mac80211 queue whenever one of - * the VO or MGMT queues is full, stopping also submitting of MGMT frame - * to the driver. - * - * - I don't know how to set in the HW the contention window params for MGMT - * and HI-prio queues. - */ - -static const int rtl8187se_queues_map[RTL8187SE_NR_TX_QUEUES] = {5, 4, 3, 2, 7}; - -/* Queues for rtl8180/rtl8185 cards - * - * name | reg | prio - * BC | 7 | 3 - * HI | 6 | 0 - * NO | 5 | 1 - * LO | 4 | 2 - * - * The complete map for DMA kick reg using all queue is: - * static const int rtl8180_queues_map[RTL8180_NR_TX_QUEUES] = {6, 5, 4, 7}; - * - * .. but .. Because the mac80211 needs at least 4 queues for QoS or - * otherwise QoS can't be done, we use just one. - * Beacon queue could be used, but this is not finished yet. - * Actual map is: - * - * name | reg | prio - * BC | 7 | 1 <- currently not used yet. - * HI | 6 | x <- not used - * NO | 5 | x <- not used - * LO | 4 | 0 <- used - */ - -static const int rtl8180_queues_map[RTL8180_NR_TX_QUEUES] = {4, 7}; - -/* LNA gain table for rtl8187se */ -static const u8 rtl8187se_lna_gain[4] = {02, 17, 29, 39}; - -void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) -{ - struct rtl8180_priv *priv = dev->priv; - int i = 10; - u32 buf; - - buf = (data << 8) | addr; - - rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->PHY[0], buf | 0x80); - while (i--) { - rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->PHY[0], buf); - if (rtl818x_ioread8(priv, &priv->map->PHY[2]) == (data & 0xFF)) - return; - } -} - -static void rtl8180_handle_rx(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - struct rtl818x_rx_cmd_desc *cmd_desc; - unsigned int count = 32; - u8 agc, sq; - s8 signal = 1; - dma_addr_t mapping; - - while (count--) { - void *entry = priv->rx_ring + priv->rx_idx * priv->rx_ring_sz; - struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; - u32 flags, flags2, flags3 = 0; - u64 tsft; - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { - struct rtl8187se_rx_desc *desc = entry; - - flags = le32_to_cpu(desc->flags); - /* if ownership flag is set, then we can trust the - * HW has written other fields. We must not trust - * other descriptor data read before we checked (read) - * the ownership flag - */ - rmb(); - flags3 = le32_to_cpu(desc->flags3); - flags2 = le32_to_cpu(desc->flags2); - tsft = le64_to_cpu(desc->tsft); - } else { - struct rtl8180_rx_desc *desc = entry; - - flags = le32_to_cpu(desc->flags); - /* same as above */ - rmb(); - flags2 = le32_to_cpu(desc->flags2); - tsft = le64_to_cpu(desc->tsft); - } - - if (flags & RTL818X_RX_DESC_FLAG_OWN) - return; - - if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | - RTL818X_RX_DESC_FLAG_FOF | - RTL818X_RX_DESC_FLAG_RX_ERR))) - goto done; - else { - struct ieee80211_rx_status rx_status = {0}; - struct sk_buff *new_skb = dev_alloc_skb(MAX_RX_SIZE); - - if (unlikely(!new_skb)) - goto done; - - mapping = pci_map_single(priv->pdev, - skb_tail_pointer(new_skb), - MAX_RX_SIZE, PCI_DMA_FROMDEVICE); - - if (pci_dma_mapping_error(priv->pdev, mapping)) { - kfree_skb(new_skb); - dev_err(&priv->pdev->dev, "RX DMA map error\n"); - - goto done; - } - - pci_unmap_single(priv->pdev, - *((dma_addr_t *)skb->cb), - MAX_RX_SIZE, PCI_DMA_FROMDEVICE); - skb_put(skb, flags & 0xFFF); - - rx_status.antenna = (flags2 >> 15) & 1; - rx_status.rate_idx = (flags >> 20) & 0xF; - agc = (flags2 >> 17) & 0x7F; - - switch (priv->chip_family) { - case RTL818X_CHIP_FAMILY_RTL8185: - if (rx_status.rate_idx > 3) - signal = -clamp_t(u8, agc, 25, 90) - 9; - else - signal = -clamp_t(u8, agc, 30, 95); - break; - case RTL818X_CHIP_FAMILY_RTL8180: - sq = flags2 & 0xff; - signal = priv->rf->calc_rssi(agc, sq); - break; - case RTL818X_CHIP_FAMILY_RTL8187SE: - /* OFDM measure reported by HW is signed, - * in 0.5dBm unit, with zero centered @ -41dBm - * input signal. - */ - if (rx_status.rate_idx > 3) { - signal = (s8)((flags3 >> 16) & 0xff); - signal = signal / 2 - 41; - } else { - int idx, bb; - - idx = (agc & 0x60) >> 5; - bb = (agc & 0x1F) * 2; - /* bias + BB gain + LNA gain */ - signal = 4 - bb - rtl8187se_lna_gain[idx]; - } - break; - } - rx_status.signal = signal; - rx_status.freq = dev->conf.chandef.chan->center_freq; - rx_status.band = dev->conf.chandef.chan->band; - rx_status.mactime = tsft; - rx_status.flag |= RX_FLAG_MACTIME_START; - if (flags & RTL818X_RX_DESC_FLAG_SPLCP) - rx_status.flag |= RX_FLAG_SHORTPRE; - if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) - rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; - - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - ieee80211_rx_irqsafe(dev, skb); - - skb = new_skb; - priv->rx_buf[priv->rx_idx] = skb; - *((dma_addr_t *) skb->cb) = mapping; - } - - done: - cmd_desc = entry; - cmd_desc->rx_buf = cpu_to_le32(*((dma_addr_t *)skb->cb)); - cmd_desc->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN | - MAX_RX_SIZE); - if (priv->rx_idx == 31) - cmd_desc->flags |= - cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); - priv->rx_idx = (priv->rx_idx + 1) % 32; - } -} - -static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) -{ - struct rtl8180_priv *priv = dev->priv; - struct rtl8180_tx_ring *ring = &priv->tx_ring[prio]; - - while (skb_queue_len(&ring->queue)) { - struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb; - struct ieee80211_tx_info *info; - u32 flags = le32_to_cpu(entry->flags); - - if (flags & RTL818X_TX_DESC_FLAG_OWN) - return; - - ring->idx = (ring->idx + 1) % ring->entries; - skb = __skb_dequeue(&ring->queue); - pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), - skb->len, PCI_DMA_TODEVICE); - - info = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(info); - - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && - (flags & RTL818X_TX_DESC_FLAG_TX_OK)) - info->flags |= IEEE80211_TX_STAT_ACK; - - info->status.rates[0].count = (flags & 0xFF) + 1; - - ieee80211_tx_status_irqsafe(dev, skb); - if (ring->entries - skb_queue_len(&ring->queue) == 2) - ieee80211_wake_queue(dev, prio); - } -} - -static irqreturn_t rtl8187se_interrupt(int irq, void *dev_id) -{ - struct ieee80211_hw *dev = dev_id; - struct rtl8180_priv *priv = dev->priv; - u32 reg; - unsigned long flags; - static int desc_err; - - spin_lock_irqsave(&priv->lock, flags); - /* Note: 32-bit interrupt status */ - reg = rtl818x_ioread32(priv, &priv->map->INT_STATUS_SE); - if (unlikely(reg == 0xFFFFFFFF)) { - spin_unlock_irqrestore(&priv->lock, flags); - return IRQ_HANDLED; - } - - rtl818x_iowrite32(priv, &priv->map->INT_STATUS_SE, reg); - - if (reg & IMR_TIMEOUT1) - rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); - - if (reg & (IMR_TBDOK | IMR_TBDER)) - rtl8180_handle_tx(dev, 4); - - if (reg & (IMR_TVODOK | IMR_TVODER)) - rtl8180_handle_tx(dev, 0); - - if (reg & (IMR_TVIDOK | IMR_TVIDER)) - rtl8180_handle_tx(dev, 1); - - if (reg & (IMR_TBEDOK | IMR_TBEDER)) - rtl8180_handle_tx(dev, 2); - - if (reg & (IMR_TBKDOK | IMR_TBKDER)) - rtl8180_handle_tx(dev, 3); - - if (reg & (IMR_ROK | IMR_RER | RTL818X_INT_SE_RX_DU | IMR_RQOSOK)) - rtl8180_handle_rx(dev); - /* The interface sometimes generates several RX DMA descriptor errors - * at startup. Do not report these. - */ - if ((reg & RTL818X_INT_SE_RX_DU) && desc_err++ > 2) - if (net_ratelimit()) - wiphy_err(dev->wiphy, "No RX DMA Descriptor avail\n"); - - spin_unlock_irqrestore(&priv->lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) -{ - struct ieee80211_hw *dev = dev_id; - struct rtl8180_priv *priv = dev->priv; - u16 reg; - - spin_lock(&priv->lock); - reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); - if (unlikely(reg == 0xFFFF)) { - spin_unlock(&priv->lock); - return IRQ_HANDLED; - } - - rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); - - if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR)) - rtl8180_handle_tx(dev, 1); - - if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR)) - rtl8180_handle_tx(dev, 0); - - if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR)) - rtl8180_handle_rx(dev); - - spin_unlock(&priv->lock); - - return IRQ_HANDLED; -} - -static void rtl8180_tx(struct ieee80211_hw *dev, - struct ieee80211_tx_control *control, - struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct rtl8180_priv *priv = dev->priv; - struct rtl8180_tx_ring *ring; - struct rtl8180_tx_desc *entry; - unsigned long flags; - unsigned int idx, prio, hw_prio; - dma_addr_t mapping; - u32 tx_flags; - u8 rc_flags; - u16 plcp_len = 0; - __le16 rts_duration = 0; - /* do arithmetic and then convert to le16 */ - u16 frame_duration = 0; - - prio = skb_get_queue_mapping(skb); - ring = &priv->tx_ring[prio]; - - mapping = pci_map_single(priv->pdev, skb->data, - skb->len, PCI_DMA_TODEVICE); - - if (pci_dma_mapping_error(priv->pdev, mapping)) { - kfree_skb(skb); - dev_err(&priv->pdev->dev, "TX DMA mapping error\n"); - return; - } - - tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS | - RTL818X_TX_DESC_FLAG_LS | - (ieee80211_get_tx_rate(dev, info)->hw_value << 24) | - skb->len; - - if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) - tx_flags |= RTL818X_TX_DESC_FLAG_DMA | - RTL818X_TX_DESC_FLAG_NO_ENC; - - rc_flags = info->control.rates[0].flags; - - /* HW will perform RTS-CTS when only RTS flags is set. - * HW will perform CTS-to-self when both RTS and CTS flags are set. - * RTS rate and RTS duration will be used also for CTS-to-self. - */ - if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { - tx_flags |= RTL818X_TX_DESC_FLAG_RTS; - tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - rts_duration = ieee80211_rts_duration(dev, priv->vif, - skb->len, info); - } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - tx_flags |= RTL818X_TX_DESC_FLAG_RTS | RTL818X_TX_DESC_FLAG_CTS; - tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - rts_duration = ieee80211_ctstoself_duration(dev, priv->vif, - skb->len, info); - } - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) { - unsigned int remainder; - - plcp_len = DIV_ROUND_UP(16 * (skb->len + 4), - (ieee80211_get_tx_rate(dev, info)->bitrate * 2) / 10); - remainder = (16 * (skb->len + 4)) % - ((ieee80211_get_tx_rate(dev, info)->bitrate * 2) / 10); - if (remainder <= 6) - plcp_len |= 1 << 15; - } - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { - __le16 duration; - /* SIFS time (required by HW) is already included by - * ieee80211_generic_frame_duration - */ - duration = ieee80211_generic_frame_duration(dev, priv->vif, - IEEE80211_BAND_2GHZ, skb->len, - ieee80211_get_tx_rate(dev, info)); - - frame_duration = priv->ack_time + le16_to_cpu(duration); - } - - spin_lock_irqsave(&priv->lock, flags); - - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - priv->seqno += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(priv->seqno); - } - - idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; - entry = &ring->desc[idx]; - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { - entry->frame_duration = cpu_to_le16(frame_duration); - entry->frame_len_se = cpu_to_le16(skb->len); - - /* tpc polarity */ - entry->flags3 = cpu_to_le16(1<<4); - } else - entry->frame_len = cpu_to_le32(skb->len); - - entry->rts_duration = rts_duration; - entry->plcp_len = cpu_to_le16(plcp_len); - entry->tx_buf = cpu_to_le32(mapping); - - entry->retry_limit = info->control.rates[0].count - 1; - - /* We must be sure that tx_flags is written last because the HW - * looks at it to check if the rest of data is valid or not - */ - wmb(); - entry->flags = cpu_to_le32(tx_flags); - /* We must be sure this has been written before followings HW - * register write, because this write will made the HW attempts - * to DMA the just-written data - */ - wmb(); - - __skb_queue_tail(&ring->queue, skb); - if (ring->entries - skb_queue_len(&ring->queue) < 2) - ieee80211_stop_queue(dev, prio); - - spin_unlock_irqrestore(&priv->lock, flags); - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { - /* just poll: rings are stopped with TPPollStop reg */ - hw_prio = rtl8187se_queues_map[prio]; - rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, - (1 << hw_prio)); - } else { - hw_prio = rtl8180_queues_map[prio]; - rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, - (1 << hw_prio) | /* ring to poll */ - (1<<1) | (1<<2));/* stopped rings */ - } -} - -static void rtl8180_set_anaparam3(struct rtl8180_priv *priv, u16 anaparam3) -{ - u8 reg; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - - rtl818x_iowrite16(priv, &priv->map->ANAPARAM3, anaparam3); - - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); -} - -void rtl8180_set_anaparam2(struct rtl8180_priv *priv, u32 anaparam2) -{ - u8 reg; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, anaparam2); - - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); -} - -void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam) -{ - u8 reg; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, anaparam); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); -} - -static void rtl8187se_mac_config(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u8 reg; - - rtl818x_iowrite32(priv, REG_ADDR4(0x1F0), 0); - rtl818x_ioread32(priv, REG_ADDR4(0x1F0)); - rtl818x_iowrite32(priv, REG_ADDR4(0x1F4), 0); - rtl818x_ioread32(priv, REG_ADDR4(0x1F4)); - rtl818x_iowrite8(priv, REG_ADDR1(0x1F8), 0); - rtl818x_ioread8(priv, REG_ADDR1(0x1F8)); - /* Enable DA10 TX power saving */ - reg = rtl818x_ioread8(priv, &priv->map->PHY_PR); - rtl818x_iowrite8(priv, &priv->map->PHY_PR, reg | 0x04); - /* Power */ - rtl818x_iowrite16(priv, PI_DATA_REG, 0x1000); - rtl818x_iowrite16(priv, SI_DATA_REG, 0x1000); - /* AFE - default to power ON */ - rtl818x_iowrite16(priv, REG_ADDR2(0x370), 0x0560); - rtl818x_iowrite16(priv, REG_ADDR2(0x372), 0x0560); - rtl818x_iowrite16(priv, REG_ADDR2(0x374), 0x0DA4); - rtl818x_iowrite16(priv, REG_ADDR2(0x376), 0x0DA4); - rtl818x_iowrite16(priv, REG_ADDR2(0x378), 0x0560); - rtl818x_iowrite16(priv, REG_ADDR2(0x37A), 0x0560); - rtl818x_iowrite16(priv, REG_ADDR2(0x37C), 0x00EC); - rtl818x_iowrite16(priv, REG_ADDR2(0x37E), 0x00EC); - rtl818x_iowrite8(priv, REG_ADDR1(0x24E), 0x01); - /* unknown, needed for suspend to RAM resume */ - rtl818x_iowrite8(priv, REG_ADDR1(0x0A), 0x72); -} - -static void rtl8187se_set_antenna_config(struct ieee80211_hw *dev, u8 def_ant, - bool diversity) -{ - struct rtl8180_priv *priv = dev->priv; - - rtl8225_write_phy_cck(dev, 0x0C, 0x09); - if (diversity) { - if (def_ant == 1) { - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x00); - rtl8225_write_phy_cck(dev, 0x11, 0xBB); - rtl8225_write_phy_cck(dev, 0x01, 0xC7); - rtl8225_write_phy_ofdm(dev, 0x0D, 0x54); - rtl8225_write_phy_ofdm(dev, 0x18, 0xB2); - } else { /* main antenna */ - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); - rtl8225_write_phy_cck(dev, 0x11, 0x9B); - rtl8225_write_phy_cck(dev, 0x01, 0xC7); - rtl8225_write_phy_ofdm(dev, 0x0D, 0x5C); - rtl8225_write_phy_ofdm(dev, 0x18, 0xB2); - } - } else { /* disable antenna diversity */ - if (def_ant == 1) { - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x00); - rtl8225_write_phy_cck(dev, 0x11, 0xBB); - rtl8225_write_phy_cck(dev, 0x01, 0x47); - rtl8225_write_phy_ofdm(dev, 0x0D, 0x54); - rtl8225_write_phy_ofdm(dev, 0x18, 0x32); - } else { /* main antenna */ - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); - rtl8225_write_phy_cck(dev, 0x11, 0x9B); - rtl8225_write_phy_cck(dev, 0x01, 0x47); - rtl8225_write_phy_ofdm(dev, 0x0D, 0x5C); - rtl8225_write_phy_ofdm(dev, 0x18, 0x32); - } - } - /* priv->curr_ant = def_ant; */ -} - -static void rtl8180_int_enable(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { - rtl818x_iowrite32(priv, &priv->map->IMR, - IMR_TBDER | IMR_TBDOK | - IMR_TVODER | IMR_TVODOK | - IMR_TVIDER | IMR_TVIDOK | - IMR_TBEDER | IMR_TBEDOK | - IMR_TBKDER | IMR_TBKDOK | - IMR_RDU | IMR_RER | - IMR_ROK | IMR_RQOSOK); - } else { - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); - } -} - -static void rtl8180_int_disable(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { - rtl818x_iowrite32(priv, &priv->map->IMR, 0); - } else { - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); - } -} - -static void rtl8180_conf_basic_rates(struct ieee80211_hw *dev, - u32 basic_mask) -{ - struct rtl8180_priv *priv = dev->priv; - u16 reg; - u32 resp_mask; - u8 basic_max; - u8 resp_max, resp_min; - - resp_mask = basic_mask; - /* IEEE80211 says the response rate should be equal to the highest basic - * rate that is not faster than received frame. But it says also that if - * the basic rate set does not contains any rate for the current - * modulation class then mandatory rate set must be used for that - * modulation class. Eventually add OFDM mandatory rates.. - */ - if ((resp_mask & 0xf) == resp_mask) - resp_mask |= 0x150; /* 6, 12, 24Mbps */ - - switch (priv->chip_family) { - - case RTL818X_CHIP_FAMILY_RTL8180: - /* in 8180 this is NOT a BITMAP */ - basic_max = fls(basic_mask) - 1; - reg = rtl818x_ioread16(priv, &priv->map->BRSR); - reg &= ~3; - reg |= basic_max; - rtl818x_iowrite16(priv, &priv->map->BRSR, reg); - break; - - case RTL818X_CHIP_FAMILY_RTL8185: - resp_max = fls(resp_mask) - 1; - resp_min = ffs(resp_mask) - 1; - /* in 8185 this is a BITMAP */ - rtl818x_iowrite16(priv, &priv->map->BRSR, basic_mask); - rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (resp_max << 4) | - resp_min); - break; - - case RTL818X_CHIP_FAMILY_RTL8187SE: - /* in 8187se this is a BITMAP. BRSR reg actually sets - * response rates. - */ - rtl818x_iowrite16(priv, &priv->map->BRSR_8187SE, resp_mask); - break; - } -} - -static void rtl8180_config_cardbus(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u16 reg16; - u8 reg8; - - reg8 = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg8 |= 1 << 1; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg8); - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { - rtl818x_iowrite16(priv, FEMR_SE, 0xffff); - } else { - reg16 = rtl818x_ioread16(priv, &priv->map->FEMR); - reg16 |= (1 << 15) | (1 << 14) | (1 << 4); - rtl818x_iowrite16(priv, &priv->map->FEMR, reg16); - } - -} - -static int rtl8180_init_hw(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u16 reg; - u32 reg32; - - rtl818x_iowrite8(priv, &priv->map->CMD, 0); - rtl818x_ioread8(priv, &priv->map->CMD); - msleep(10); - - /* reset */ - rtl8180_int_disable(dev); - rtl818x_ioread8(priv, &priv->map->CMD); - - reg = rtl818x_ioread8(priv, &priv->map->CMD); - reg &= (1 << 1); - reg |= RTL818X_CMD_RESET; - rtl818x_iowrite8(priv, &priv->map->CMD, RTL818X_CMD_RESET); - rtl818x_ioread8(priv, &priv->map->CMD); - msleep(200); - - /* check success of reset */ - if (rtl818x_ioread8(priv, &priv->map->CMD) & RTL818X_CMD_RESET) { - wiphy_err(dev->wiphy, "reset timeout!\n"); - return -ETIMEDOUT; - } - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD); - rtl818x_ioread8(priv, &priv->map->CMD); - msleep(200); - - if (rtl818x_ioread8(priv, &priv->map->CONFIG3) & (1 << 3)) { - rtl8180_config_cardbus(dev); - } - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) - rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_ENEDCA); - else - rtl818x_iowrite8(priv, &priv->map->MSR, 0); - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) - rtl8180_set_anaparam(priv, priv->anaparam); - - rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma); - /* mac80211 queue have higher prio for lower index. The last queue - * (that mac80211 is not aware of) is reserved for beacons (and have - * the highest priority on the NIC) - */ - if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8187SE) { - rtl818x_iowrite32(priv, &priv->map->TBDA, - priv->tx_ring[1].dma); - rtl818x_iowrite32(priv, &priv->map->TLPDA, - priv->tx_ring[0].dma); - } else { - rtl818x_iowrite32(priv, &priv->map->TBDA, - priv->tx_ring[4].dma); - rtl818x_iowrite32(priv, &priv->map->TVODA, - priv->tx_ring[0].dma); - rtl818x_iowrite32(priv, &priv->map->TVIDA, - priv->tx_ring[1].dma); - rtl818x_iowrite32(priv, &priv->map->TBEDA, - priv->tx_ring[2].dma); - rtl818x_iowrite32(priv, &priv->map->TBKDA, - priv->tx_ring[3].dma); - } - - /* TODO: necessary? specs indicate not */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG2); - rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg & ~(1 << 3)); - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) { - reg = rtl818x_ioread8(priv, &priv->map->CONFIG2); - rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg | (1 << 4)); - } - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - /* TODO: set CONFIG5 for calibrating AGC on rtl8180 + philips radio? */ - - /* TODO: turn off hw wep on rtl8180 */ - - rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); - - if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { - rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); - rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0); - } else { - rtl818x_iowrite8(priv, &priv->map->SECURITY, 0); - - rtl818x_iowrite8(priv, &priv->map->PHY_DELAY, 0x6); - rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, 0x4C); - } - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) { - /* TODO: set ClkRun enable? necessary? */ - reg = rtl818x_ioread8(priv, &priv->map->GP_ENABLE); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, reg & ~(1 << 6)); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | (1 << 2)); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - /* fix eccessive IFS after CTS-to-self */ - if (priv->map_pio) { - u8 reg; - - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT); - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1); - rtl818x_iowrite8(priv, REG_ADDR1(0xff), 0x35); - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - } else - rtl818x_iowrite8(priv, REG_ADDR1(0x1ff), 0x35); - } - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { - - /* the set auto rate fallback bitmask from 1M to 54 Mb/s */ - rtl818x_iowrite16(priv, ARFR, 0xFFF); - rtl818x_ioread16(priv, ARFR); - - /* stop unused queus (no dma alloc) */ - rtl818x_iowrite8(priv, &priv->map->TPPOLL_STOP, - RTL818x_TPPOLL_STOP_MG | RTL818x_TPPOLL_STOP_HI); - - rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0x00); - rtl818x_iowrite16(priv, &priv->map->TID_AC_MAP, 0xFA50); - - rtl818x_iowrite16(priv, &priv->map->INT_MIG, 0); - - /* some black magic here.. */ - rtl8187se_mac_config(dev); - - rtl818x_iowrite16(priv, RFSW_CTRL, 0x569A); - rtl818x_ioread16(priv, RFSW_CTRL); - - rtl8180_set_anaparam(priv, RTL8225SE_ANAPARAM_ON); - rtl8180_set_anaparam2(priv, RTL8225SE_ANAPARAM2_ON); - rtl8180_set_anaparam3(priv, RTL8225SE_ANAPARAM3); - - - rtl818x_iowrite8(priv, &priv->map->CONFIG5, - rtl818x_ioread8(priv, &priv->map->CONFIG5) & 0x7F); - - /*probably this switch led on */ - rtl818x_iowrite8(priv, &priv->map->PGSELECT, - rtl818x_ioread8(priv, &priv->map->PGSELECT) | 0x08); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1BFF); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488); - - rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x4003); - - /* the reference code mac hardcode table write - * this reg by doing byte-wide accesses. - * It does it just for lowest and highest byte.. - */ - reg32 = rtl818x_ioread32(priv, &priv->map->RF_PARA); - reg32 &= 0x00ffff00; - reg32 |= 0xb8000054; - rtl818x_iowrite32(priv, &priv->map->RF_PARA, reg32); - } else - /* stop unused queus (no dma alloc) */ - rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, - (1<<1) | (1<<2)); - - priv->rf->init(dev); - - /* default basic rates are 1,2 Mbps for rtl8180. 1,2,6,9,12,18,24 Mbps - * otherwise. bitmask 0x3 and 0x01f3 respectively. - * NOTE: currenty rtl8225 RF code changes basic rates, so we need to do - * this after rf init. - * TODO: try to find out whether RF code really needs to do this.. - */ - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) - rtl8180_conf_basic_rates(dev, 0x3); - else - rtl8180_conf_basic_rates(dev, 0x1f3); - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) - rtl8187se_set_antenna_config(dev, - priv->antenna_diversity_default, - priv->antenna_diversity_en); - return 0; -} - -static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - struct rtl818x_rx_cmd_desc *entry; - int i; - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) - priv->rx_ring_sz = sizeof(struct rtl8187se_rx_desc); - else - priv->rx_ring_sz = sizeof(struct rtl8180_rx_desc); - - priv->rx_ring = pci_zalloc_consistent(priv->pdev, priv->rx_ring_sz * 32, - &priv->rx_ring_dma); - if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) { - wiphy_err(dev->wiphy, "Cannot allocate RX ring\n"); - return -ENOMEM; - } - - priv->rx_idx = 0; - - for (i = 0; i < 32; i++) { - struct sk_buff *skb = dev_alloc_skb(MAX_RX_SIZE); - dma_addr_t *mapping; - entry = priv->rx_ring + priv->rx_ring_sz*i; - if (!skb) { - wiphy_err(dev->wiphy, "Cannot allocate RX skb\n"); - return -ENOMEM; - } - priv->rx_buf[i] = skb; - mapping = (dma_addr_t *)skb->cb; - *mapping = pci_map_single(priv->pdev, skb_tail_pointer(skb), - MAX_RX_SIZE, PCI_DMA_FROMDEVICE); - - if (pci_dma_mapping_error(priv->pdev, *mapping)) { - kfree_skb(skb); - wiphy_err(dev->wiphy, "Cannot map DMA for RX skb\n"); - return -ENOMEM; - } - - entry->rx_buf = cpu_to_le32(*mapping); - entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN | - MAX_RX_SIZE); - } - entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); - return 0; -} - -static void rtl8180_free_rx_ring(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - int i; - - for (i = 0; i < 32; i++) { - struct sk_buff *skb = priv->rx_buf[i]; - if (!skb) - continue; - - pci_unmap_single(priv->pdev, - *((dma_addr_t *)skb->cb), - MAX_RX_SIZE, PCI_DMA_FROMDEVICE); - kfree_skb(skb); - } - - pci_free_consistent(priv->pdev, priv->rx_ring_sz * 32, - priv->rx_ring, priv->rx_ring_dma); - priv->rx_ring = NULL; -} - -static int rtl8180_init_tx_ring(struct ieee80211_hw *dev, - unsigned int prio, unsigned int entries) -{ - struct rtl8180_priv *priv = dev->priv; - struct rtl8180_tx_desc *ring; - dma_addr_t dma; - int i; - - ring = pci_zalloc_consistent(priv->pdev, sizeof(*ring) * entries, - &dma); - if (!ring || (unsigned long)ring & 0xFF) { - wiphy_err(dev->wiphy, "Cannot allocate TX ring (prio = %d)\n", - prio); - return -ENOMEM; - } - - priv->tx_ring[prio].desc = ring; - priv->tx_ring[prio].dma = dma; - priv->tx_ring[prio].idx = 0; - priv->tx_ring[prio].entries = entries; - skb_queue_head_init(&priv->tx_ring[prio].queue); - - for (i = 0; i < entries; i++) - ring[i].next_tx_desc = - cpu_to_le32((u32)dma + ((i + 1) % entries) * sizeof(*ring)); - - return 0; -} - -static void rtl8180_free_tx_ring(struct ieee80211_hw *dev, unsigned int prio) -{ - struct rtl8180_priv *priv = dev->priv; - struct rtl8180_tx_ring *ring = &priv->tx_ring[prio]; - - while (skb_queue_len(&ring->queue)) { - struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb = __skb_dequeue(&ring->queue); - - pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), - skb->len, PCI_DMA_TODEVICE); - kfree_skb(skb); - ring->idx = (ring->idx + 1) % ring->entries; - } - - pci_free_consistent(priv->pdev, sizeof(*ring->desc)*ring->entries, - ring->desc, ring->dma); - ring->desc = NULL; -} - -static int rtl8180_start(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - int ret, i; - u32 reg; - - ret = rtl8180_init_rx_ring(dev); - if (ret) - return ret; - - for (i = 0; i < (dev->queues + 1); i++) - if ((ret = rtl8180_init_tx_ring(dev, i, 16))) - goto err_free_rings; - - ret = rtl8180_init_hw(dev); - if (ret) - goto err_free_rings; - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { - ret = request_irq(priv->pdev->irq, rtl8187se_interrupt, - IRQF_SHARED, KBUILD_MODNAME, dev); - } else { - ret = request_irq(priv->pdev->irq, rtl8180_interrupt, - IRQF_SHARED, KBUILD_MODNAME, dev); - } - - if (ret) { - wiphy_err(dev->wiphy, "failed to register IRQ handler\n"); - goto err_free_rings; - } - - rtl8180_int_enable(dev); - - /* in rtl8187se at MAR regs offset there is the management - * TX descriptor DMA addres.. - */ - if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8187SE) { - rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); - rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); - } - - reg = RTL818X_RX_CONF_ONLYERLPKT | - RTL818X_RX_CONF_RX_AUTORESETPHY | - RTL818X_RX_CONF_MGMT | - RTL818X_RX_CONF_DATA | - (7 << 8 /* MAX RX DMA */) | - RTL818X_RX_CONF_BROADCAST | - RTL818X_RX_CONF_NICMAC; - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) - reg |= RTL818X_RX_CONF_CSDM1 | RTL818X_RX_CONF_CSDM2; - else if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) { - reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE1) - ? RTL818X_RX_CONF_CSDM1 : 0; - reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE2) - ? RTL818X_RX_CONF_CSDM2 : 0; - } else { - reg &= ~(RTL818X_RX_CONF_CSDM1 | RTL818X_RX_CONF_CSDM2); - } - - priv->rx_conf = reg; - rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); - - if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { - reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); - - /* CW is not on per-packet basis. - * in rtl8185 the CW_VALUE reg is used. - * in rtl8187se the AC param regs are used. - */ - reg &= ~RTL818X_CW_CONF_PERPACKET_CW; - /* retry limit IS on per-packet basis. - * the short and long retry limit in TX_CONF - * reg are ignored - */ - reg |= RTL818X_CW_CONF_PERPACKET_RETRY; - rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); - - reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); - /* TX antenna and TX gain are not on per-packet basis. - * TX Antenna is selected by ANTSEL reg (RX in BB regs). - * TX gain is selected with CCK_TX_AGC and OFDM_TX_AGC regs - */ - reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN; - reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL; - reg |= RTL818X_TX_AGC_CTL_FEEDBACK_ANT; - rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); - - /* disable early TX */ - rtl818x_iowrite8(priv, (u8 __iomem *)priv->map + 0xec, 0x3f); - } - - reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); - reg |= (6 << 21 /* MAX TX DMA */) | - RTL818X_TX_CONF_NO_ICV; - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) - reg |= 1<<30; /* "duration procedure mode" */ - - if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) - reg &= ~RTL818X_TX_CONF_PROBE_DTS; - else - reg &= ~RTL818X_TX_CONF_HW_SEQNUM; - - reg &= ~RTL818X_TX_CONF_DISCW; - - /* different meaning, same value on both rtl8185 and rtl8180 */ - reg &= ~RTL818X_TX_CONF_SAT_HWPLCP; - - rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); - - reg = rtl818x_ioread8(priv, &priv->map->CMD); - reg |= RTL818X_CMD_RX_ENABLE; - reg |= RTL818X_CMD_TX_ENABLE; - rtl818x_iowrite8(priv, &priv->map->CMD, reg); - - return 0; - - err_free_rings: - rtl8180_free_rx_ring(dev); - for (i = 0; i < (dev->queues + 1); i++) - if (priv->tx_ring[i].desc) - rtl8180_free_tx_ring(dev, i); - - return ret; -} - -static void rtl8180_stop(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u8 reg; - int i; - - rtl8180_int_disable(dev); - - reg = rtl818x_ioread8(priv, &priv->map->CMD); - reg &= ~RTL818X_CMD_TX_ENABLE; - reg &= ~RTL818X_CMD_RX_ENABLE; - rtl818x_iowrite8(priv, &priv->map->CMD, reg); - - priv->rf->stop(dev); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG4); - rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - free_irq(priv->pdev->irq, dev); - - rtl8180_free_rx_ring(dev); - for (i = 0; i < (dev->queues + 1); i++) - rtl8180_free_tx_ring(dev, i); -} - -static u64 rtl8180_get_tsf(struct ieee80211_hw *dev, - struct ieee80211_vif *vif) -{ - struct rtl8180_priv *priv = dev->priv; - - return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | - (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; -} - -static void rtl8180_beacon_work(struct work_struct *work) -{ - struct rtl8180_vif *vif_priv = - container_of(work, struct rtl8180_vif, beacon_work.work); - struct ieee80211_vif *vif = - container_of((void *)vif_priv, struct ieee80211_vif, drv_priv); - struct ieee80211_hw *dev = vif_priv->dev; - struct ieee80211_mgmt *mgmt; - struct sk_buff *skb; - - /* don't overflow the tx ring */ - if (ieee80211_queue_stopped(dev, 0)) - goto resched; - - /* grab a fresh beacon */ - skb = ieee80211_beacon_get(dev, vif); - if (!skb) - goto resched; - - /* - * update beacon timestamp w/ TSF value - * TODO: make hardware update beacon timestamp - */ - mgmt = (struct ieee80211_mgmt *)skb->data; - mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev, vif)); - - /* TODO: use actual beacon queue */ - skb_set_queue_mapping(skb, 0); - - rtl8180_tx(dev, NULL, skb); - -resched: - /* - * schedule next beacon - * TODO: use hardware support for beacon timing - */ - schedule_delayed_work(&vif_priv->beacon_work, - usecs_to_jiffies(1024 * vif->bss_conf.beacon_int)); -} - -static int rtl8180_add_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif) -{ - struct rtl8180_priv *priv = dev->priv; - struct rtl8180_vif *vif_priv; - - /* - * We only support one active interface at a time. - */ - if (priv->vif) - return -EBUSY; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - break; - default: - return -EOPNOTSUPP; - } - - priv->vif = vif; - - /* Initialize driver private area */ - vif_priv = (struct rtl8180_vif *)&vif->drv_priv; - vif_priv->dev = dev; - INIT_DELAYED_WORK(&vif_priv->beacon_work, rtl8180_beacon_work); - vif_priv->enable_beacon = false; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], - le32_to_cpu(*(__le32 *)vif->addr)); - rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], - le16_to_cpu(*(__le16 *)(vif->addr + 4))); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - return 0; -} - -static void rtl8180_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif) -{ - struct rtl8180_priv *priv = dev->priv; - priv->vif = NULL; -} - -static int rtl8180_config(struct ieee80211_hw *dev, u32 changed) -{ - struct rtl8180_priv *priv = dev->priv; - struct ieee80211_conf *conf = &dev->conf; - - priv->rf->set_chan(dev, conf); - - return 0; -} - -static void rtl8187se_conf_ac_parm(struct ieee80211_hw *dev, u8 queue) -{ - const struct ieee80211_tx_queue_params *params; - struct rtl8180_priv *priv = dev->priv; - - /* hw value */ - u32 ac_param; - - u8 aifs; - u8 txop; - u8 cw_min, cw_max; - - params = &priv->queue_param[queue]; - - cw_min = fls(params->cw_min); - cw_max = fls(params->cw_max); - - aifs = 10 + params->aifs * priv->slot_time; - - /* TODO: check if txop HW is in us (mult by 32) */ - txop = params->txop; - - ac_param = txop << AC_PARAM_TXOP_LIMIT_SHIFT | - cw_max << AC_PARAM_ECW_MAX_SHIFT | - cw_min << AC_PARAM_ECW_MIN_SHIFT | - aifs << AC_PARAM_AIFS_SHIFT; - - switch (queue) { - case IEEE80211_AC_BK: - rtl818x_iowrite32(priv, &priv->map->AC_BK_PARAM, ac_param); - break; - case IEEE80211_AC_BE: - rtl818x_iowrite32(priv, &priv->map->AC_BE_PARAM, ac_param); - break; - case IEEE80211_AC_VI: - rtl818x_iowrite32(priv, &priv->map->AC_VI_PARAM, ac_param); - break; - case IEEE80211_AC_VO: - rtl818x_iowrite32(priv, &priv->map->AC_VO_PARAM, ac_param); - break; - } -} - -static int rtl8180_conf_tx(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct rtl8180_priv *priv = dev->priv; - u8 cw_min, cw_max; - - /* nothing to do ? */ - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) - return 0; - - cw_min = fls(params->cw_min); - cw_max = fls(params->cw_max); - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { - priv->queue_param[queue] = *params; - rtl8187se_conf_ac_parm(dev, queue); - } else - rtl818x_iowrite8(priv, &priv->map->CW_VAL, - (cw_max << 4) | cw_min); - return 0; -} - -static void rtl8180_conf_erp(struct ieee80211_hw *dev, - struct ieee80211_bss_conf *info) -{ - struct rtl8180_priv *priv = dev->priv; - u8 sifs, difs; - int eifs; - u8 hw_eifs; - - /* TODO: should we do something ? */ - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) - return; - - /* I _hope_ this means 10uS for the HW. - * In reference code it is 0x22 for - * both rtl8187L and rtl8187SE - */ - sifs = 0x22; - - if (info->use_short_slot) - priv->slot_time = 9; - else - priv->slot_time = 20; - - /* 10 is SIFS time in uS */ - difs = 10 + 2 * priv->slot_time; - eifs = 10 + difs + priv->ack_time; - - /* HW should use 4uS units for EIFS (I'm sure for rtl8185)*/ - hw_eifs = DIV_ROUND_UP(eifs, 4); - - - rtl818x_iowrite8(priv, &priv->map->SLOT, priv->slot_time); - rtl818x_iowrite8(priv, &priv->map->SIFS, sifs); - rtl818x_iowrite8(priv, &priv->map->DIFS, difs); - - /* from reference code. set ack timeout reg = eifs reg */ - rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, hw_eifs); - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) - rtl818x_iowrite8(priv, &priv->map->EIFS_8187SE, hw_eifs); - else if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8185) { - /* rtl8187/rtl8185 HW bug. After EIFS is elapsed, - * the HW still wait for DIFS. - * HW uses 4uS units for EIFS. - */ - hw_eifs = DIV_ROUND_UP(eifs - difs, 4); - - rtl818x_iowrite8(priv, &priv->map->EIFS, hw_eifs); - } -} - -static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) -{ - struct rtl8180_priv *priv = dev->priv; - struct rtl8180_vif *vif_priv; - int i; - u8 reg; - - vif_priv = (struct rtl8180_vif *)&vif->drv_priv; - - if (changed & BSS_CHANGED_BSSID) { - rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->BSSID[0], - le16_to_cpu(*(__le16 *)info->bssid)); - rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->BSSID[2], - le32_to_cpu(*(__le32 *)(info->bssid + 2))); - - if (is_valid_ether_addr(info->bssid)) { - if (vif->type == NL80211_IFTYPE_ADHOC) - reg = RTL818X_MSR_ADHOC; - else - reg = RTL818X_MSR_INFRA; - } else - reg = RTL818X_MSR_NO_LINK; - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) - reg |= RTL818X_MSR_ENEDCA; - - rtl818x_iowrite8(priv, &priv->map->MSR, reg); - } - - if (changed & BSS_CHANGED_BASIC_RATES) - rtl8180_conf_basic_rates(dev, info->basic_rates); - - if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE)) { - - /* when preamble changes, acktime duration changes, and erp must - * be recalculated. ACK time is calculated at lowest rate. - * Since mac80211 include SIFS time we remove it (-10) - */ - priv->ack_time = - le16_to_cpu(ieee80211_generic_frame_duration(dev, - priv->vif, - IEEE80211_BAND_2GHZ, 10, - &priv->rates[0])) - 10; - - rtl8180_conf_erp(dev, info); - - /* mac80211 supplies aifs_n to driver and calls - * conf_tx callback whether aifs_n changes, NOT - * when aifs changes. - * Aifs should be recalculated if slot changes. - */ - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { - for (i = 0; i < 4; i++) - rtl8187se_conf_ac_parm(dev, i); - } - } - - if (changed & BSS_CHANGED_BEACON_ENABLED) - vif_priv->enable_beacon = info->enable_beacon; - - if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON)) { - cancel_delayed_work_sync(&vif_priv->beacon_work); - if (vif_priv->enable_beacon) - schedule_work(&vif_priv->beacon_work.work); - } -} - -static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, - struct netdev_hw_addr_list *mc_list) -{ - return netdev_hw_addr_list_count(mc_list); -} - -static void rtl8180_configure_filter(struct ieee80211_hw *dev, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct rtl8180_priv *priv = dev->priv; - - if (changed_flags & FIF_FCSFAIL) - priv->rx_conf ^= RTL818X_RX_CONF_FCS; - if (changed_flags & FIF_CONTROL) - priv->rx_conf ^= RTL818X_RX_CONF_CTRL; - if (changed_flags & FIF_OTHER_BSS) - priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; - if (*total_flags & FIF_ALLMULTI || multicast > 0) - priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; - else - priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; - - *total_flags = 0; - - if (priv->rx_conf & RTL818X_RX_CONF_FCS) - *total_flags |= FIF_FCSFAIL; - if (priv->rx_conf & RTL818X_RX_CONF_CTRL) - *total_flags |= FIF_CONTROL; - if (priv->rx_conf & RTL818X_RX_CONF_MONITOR) - *total_flags |= FIF_OTHER_BSS; - if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) - *total_flags |= FIF_ALLMULTI; - - rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); -} - -static const struct ieee80211_ops rtl8180_ops = { - .tx = rtl8180_tx, - .start = rtl8180_start, - .stop = rtl8180_stop, - .add_interface = rtl8180_add_interface, - .remove_interface = rtl8180_remove_interface, - .config = rtl8180_config, - .bss_info_changed = rtl8180_bss_info_changed, - .conf_tx = rtl8180_conf_tx, - .prepare_multicast = rtl8180_prepare_multicast, - .configure_filter = rtl8180_configure_filter, - .get_tsf = rtl8180_get_tsf, -}; - -static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) -{ - struct rtl8180_priv *priv = eeprom->data; - u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - - eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE; - eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ; - eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK; - eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS; -} - -static void rtl8180_eeprom_register_write(struct eeprom_93cx6 *eeprom) -{ - struct rtl8180_priv *priv = eeprom->data; - u8 reg = 2 << 6; - - if (eeprom->reg_data_in) - reg |= RTL818X_EEPROM_CMD_WRITE; - if (eeprom->reg_data_out) - reg |= RTL818X_EEPROM_CMD_READ; - if (eeprom->reg_data_clock) - reg |= RTL818X_EEPROM_CMD_CK; - if (eeprom->reg_chip_select) - reg |= RTL818X_EEPROM_CMD_CS; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(10); -} - -static void rtl8180_eeprom_read(struct rtl8180_priv *priv) -{ - struct eeprom_93cx6 eeprom; - int eeprom_cck_table_adr; - u16 eeprom_val; - int i; - - eeprom.data = priv; - eeprom.register_read = rtl8180_eeprom_register_read; - eeprom.register_write = rtl8180_eeprom_register_write; - if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6)) - eeprom.width = PCI_EEPROM_WIDTH_93C66; - else - eeprom.width = PCI_EEPROM_WIDTH_93C46; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_PROGRAM); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(10); - - eeprom_93cx6_read(&eeprom, 0x06, &eeprom_val); - eeprom_val &= 0xFF; - priv->rf_type = eeprom_val; - - eeprom_93cx6_read(&eeprom, 0x17, &eeprom_val); - priv->csthreshold = eeprom_val >> 8; - - eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)priv->mac_addr, 3); - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) - eeprom_cck_table_adr = 0x30; - else - eeprom_cck_table_adr = 0x10; - - /* CCK TX power */ - for (i = 0; i < 14; i += 2) { - u16 txpwr; - eeprom_93cx6_read(&eeprom, eeprom_cck_table_adr + (i >> 1), - &txpwr); - priv->channels[i].hw_value = txpwr & 0xFF; - priv->channels[i + 1].hw_value = txpwr >> 8; - } - - /* OFDM TX power */ - if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { - for (i = 0; i < 14; i += 2) { - u16 txpwr; - eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr); - priv->channels[i].hw_value |= (txpwr & 0xFF) << 8; - priv->channels[i + 1].hw_value |= txpwr & 0xFF00; - } - } - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) { - __le32 anaparam; - eeprom_93cx6_multiread(&eeprom, 0xD, (__le16 *)&anaparam, 2); - priv->anaparam = le32_to_cpu(anaparam); - eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam); - } - - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { - eeprom_93cx6_read(&eeprom, 0x3F, &eeprom_val); - priv->antenna_diversity_en = !!(eeprom_val & 0x100); - priv->antenna_diversity_default = (eeprom_val & 0xC00) == 0x400; - - eeprom_93cx6_read(&eeprom, 0x7C, &eeprom_val); - priv->xtal_out = eeprom_val & 0xF; - priv->xtal_in = (eeprom_val & 0xF0) >> 4; - priv->xtal_cal = !!(eeprom_val & 0x1000); - priv->thermal_meter_val = (eeprom_val & 0xF00) >> 8; - priv->thermal_meter_en = !!(eeprom_val & 0x2000); - } - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); -} - -static int rtl8180_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - struct ieee80211_hw *dev; - struct rtl8180_priv *priv; - unsigned long mem_addr, mem_len; - unsigned int io_addr, io_len; - int err; - const char *chip_name, *rf_name = NULL; - u32 reg; - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR "%s (rtl8180): Cannot enable new PCI device\n", - pci_name(pdev)); - return err; - } - - err = pci_request_regions(pdev, KBUILD_MODNAME); - if (err) { - printk(KERN_ERR "%s (rtl8180): Cannot obtain PCI resources\n", - pci_name(pdev)); - return err; - } - - io_addr = pci_resource_start(pdev, 0); - io_len = pci_resource_len(pdev, 0); - mem_addr = pci_resource_start(pdev, 1); - mem_len = pci_resource_len(pdev, 1); - - if (mem_len < sizeof(struct rtl818x_csr) || - io_len < sizeof(struct rtl818x_csr)) { - printk(KERN_ERR "%s (rtl8180): Too short PCI resources\n", - pci_name(pdev)); - err = -ENOMEM; - goto err_free_reg; - } - - if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) || - (err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)))) { - printk(KERN_ERR "%s (rtl8180): No suitable DMA available\n", - pci_name(pdev)); - goto err_free_reg; - } - - pci_set_master(pdev); - - dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8180_ops); - if (!dev) { - printk(KERN_ERR "%s (rtl8180): ieee80211 alloc failed\n", - pci_name(pdev)); - err = -ENOMEM; - goto err_free_reg; - } - - priv = dev->priv; - priv->pdev = pdev; - - dev->max_rates = 1; - SET_IEEE80211_DEV(dev, &pdev->dev); - pci_set_drvdata(pdev, dev); - - priv->map_pio = false; - priv->map = pci_iomap(pdev, 1, mem_len); - if (!priv->map) { - priv->map = pci_iomap(pdev, 0, io_len); - priv->map_pio = true; - } - - if (!priv->map) { - dev_err(&pdev->dev, "Cannot map device memory/PIO\n"); - err = -ENOMEM; - goto err_free_dev; - } - - BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels)); - BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates)); - - memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); - memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); - - priv->band.band = IEEE80211_BAND_2GHZ; - priv->band.channels = priv->channels; - priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); - priv->band.bitrates = priv->rates; - priv->band.n_bitrates = 4; - dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; - - ieee80211_hw_set(dev, HOST_BROADCAST_PS_BUFFERING); - ieee80211_hw_set(dev, RX_INCLUDES_FCS); - - dev->vif_data_size = sizeof(struct rtl8180_vif); - dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC); - dev->max_signal = 65; - - reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); - reg &= RTL818X_TX_CONF_HWVER_MASK; - switch (reg) { - case RTL818X_TX_CONF_R8180_ABCD: - chip_name = "RTL8180"; - priv->chip_family = RTL818X_CHIP_FAMILY_RTL8180; - break; - - case RTL818X_TX_CONF_R8180_F: - chip_name = "RTL8180vF"; - priv->chip_family = RTL818X_CHIP_FAMILY_RTL8180; - break; - - case RTL818X_TX_CONF_R8185_ABC: - chip_name = "RTL8185"; - priv->chip_family = RTL818X_CHIP_FAMILY_RTL8185; - break; - - case RTL818X_TX_CONF_R8185_D: - chip_name = "RTL8185vD"; - priv->chip_family = RTL818X_CHIP_FAMILY_RTL8185; - break; - - case RTL818X_TX_CONF_RTL8187SE: - chip_name = "RTL8187SE"; - if (priv->map_pio) { - dev_err(&pdev->dev, - "MMIO failed. PIO not supported on RTL8187SE\n"); - err = -ENOMEM; - goto err_iounmap; - } - priv->chip_family = RTL818X_CHIP_FAMILY_RTL8187SE; - break; - - default: - printk(KERN_ERR "%s (rtl8180): Unknown chip! (0x%x)\n", - pci_name(pdev), reg >> 25); - err = -ENODEV; - goto err_iounmap; - } - - /* we declare to MAC80211 all the queues except for beacon queue - * that will be eventually handled by DRV. - * TX rings are arranged in such a way that lower is the IDX, - * higher is the priority, in order to achieve direct mapping - * with mac80211, however the beacon queue is an exception and it - * is mapped on the highst tx ring IDX. - */ - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) - dev->queues = RTL8187SE_NR_TX_QUEUES - 1; - else - dev->queues = RTL8180_NR_TX_QUEUES - 1; - - if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) { - priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); - pci_try_set_mwi(pdev); - } - - if (priv->chip_family != RTL818X_CHIP_FAMILY_RTL8180) - ieee80211_hw_set(dev, SIGNAL_DBM); - else - ieee80211_hw_set(dev, SIGNAL_UNSPEC); - - rtl8180_eeprom_read(priv); - - switch (priv->rf_type) { - case 1: rf_name = "Intersil"; - break; - case 2: rf_name = "RFMD"; - break; - case 3: priv->rf = &sa2400_rf_ops; - break; - case 4: priv->rf = &max2820_rf_ops; - break; - case 5: priv->rf = &grf5101_rf_ops; - break; - case 9: - if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) - priv->rf = rtl8187se_detect_rf(dev); - else - priv->rf = rtl8180_detect_rf(dev); - break; - case 10: - rf_name = "RTL8255"; - break; - default: - printk(KERN_ERR "%s (rtl8180): Unknown RF! (0x%x)\n", - pci_name(pdev), priv->rf_type); - err = -ENODEV; - goto err_iounmap; - } - - if (!priv->rf) { - printk(KERN_ERR "%s (rtl8180): %s RF frontend not supported!\n", - pci_name(pdev), rf_name); - err = -ENODEV; - goto err_iounmap; - } - - if (!is_valid_ether_addr(priv->mac_addr)) { - printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using" - " randomly generated MAC addr\n", pci_name(pdev)); - eth_random_addr(priv->mac_addr); - } - SET_IEEE80211_PERM_ADDR(dev, priv->mac_addr); - - spin_lock_init(&priv->lock); - - err = ieee80211_register_hw(dev); - if (err) { - printk(KERN_ERR "%s (rtl8180): Cannot register device\n", - pci_name(pdev)); - goto err_iounmap; - } - - wiphy_info(dev->wiphy, "hwaddr %pm, %s + %s\n", - priv->mac_addr, chip_name, priv->rf->name); - - return 0; - - err_iounmap: - pci_iounmap(pdev, priv->map); - - err_free_dev: - ieee80211_free_hw(dev); - - err_free_reg: - pci_release_regions(pdev); - pci_disable_device(pdev); - return err; -} - -static void rtl8180_remove(struct pci_dev *pdev) -{ - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct rtl8180_priv *priv; - - if (!dev) - return; - - ieee80211_unregister_hw(dev); - - priv = dev->priv; - - pci_iounmap(pdev, priv->map); - pci_release_regions(pdev); - pci_disable_device(pdev); - ieee80211_free_hw(dev); -} - -#ifdef CONFIG_PM -static int rtl8180_suspend(struct pci_dev *pdev, pm_message_t state) -{ - pci_save_state(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; -} - -static int rtl8180_resume(struct pci_dev *pdev) -{ - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - return 0; -} - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8180_driver = { - .name = KBUILD_MODNAME, - .id_table = rtl8180_table, - .probe = rtl8180_probe, - .remove = rtl8180_remove, -#ifdef CONFIG_PM - .suspend = rtl8180_suspend, - .resume = rtl8180_resume, -#endif /* CONFIG_PM */ -}; - -module_pci_driver(rtl8180_driver); diff --git a/drivers/net/wireless/rtl818x/rtl8180/grf5101.c b/drivers/net/wireless/rtl818x/rtl8180/grf5101.c deleted file mode 100644 index b1bfee738937..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/grf5101.c +++ /dev/null @@ -1,190 +0,0 @@ - -/* - * Radio tuning for GCT GRF5101 on RTL8180 - * - * Copyright 2007 Andrea Merello - * - * Code from the BSD driver and the rtl8181 project have been - * very useful to understand certain things - * - * I want to thanks the Authors of such projects and the Ndiswrapper - * project Authors. - * - * A special Big Thanks also is for all people who donated me cards, - * making possible the creation of the original rtl8180 driver - * from which this code is derived! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include "rtl8180.h" -#include "grf5101.h" - -static const int grf5101_encode[] = { - 0x0, 0x8, 0x4, 0xC, - 0x2, 0xA, 0x6, 0xE, - 0x1, 0x9, 0x5, 0xD, - 0x3, 0xB, 0x7, 0xF -}; - -static void write_grf5101(struct ieee80211_hw *dev, u8 addr, u32 data) -{ - struct rtl8180_priv *priv = dev->priv; - u32 phy_config; - - phy_config = grf5101_encode[(data >> 8) & 0xF]; - phy_config |= grf5101_encode[(data >> 4) & 0xF] << 4; - phy_config |= grf5101_encode[data & 0xF] << 8; - phy_config |= grf5101_encode[(addr >> 1) & 0xF] << 12; - phy_config |= (addr & 1) << 16; - phy_config |= grf5101_encode[(data & 0xf000) >> 12] << 24; - - /* MAC will bang bits to the chip */ - phy_config |= 0x90000000; - - rtl818x_iowrite32(priv, - (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config); - - msleep(3); -} - -static void grf5101_write_phy_antenna(struct ieee80211_hw *dev, short chan) -{ - struct rtl8180_priv *priv = dev->priv; - u8 ant = GRF5101_ANTENNA; - - if (priv->rfparam & RF_PARAM_ANTBDEFAULT) - ant |= BB_ANTENNA_B; - - if (chan == 14) - ant |= BB_ANTATTEN_CHAN14; - - rtl8180_write_phy(dev, 0x10, ant); -} - -static u8 grf5101_rf_calc_rssi(u8 agc, u8 sq) -{ - if (agc > 60) - return 65; - - /* TODO(?): just return agc (or agc + 5) to avoid mult / div */ - return 65 * agc / 60; -} - -static void grf5101_rf_set_channel(struct ieee80211_hw *dev, - struct ieee80211_conf *conf) -{ - struct rtl8180_priv *priv = dev->priv; - int channel = - ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); - u32 txpw = priv->channels[channel - 1].hw_value & 0xFF; - u32 chan = channel - 1; - - /* set TX power */ - write_grf5101(dev, 0x15, 0x0); - write_grf5101(dev, 0x06, txpw); - write_grf5101(dev, 0x15, 0x10); - write_grf5101(dev, 0x15, 0x0); - - /* set frequency */ - write_grf5101(dev, 0x07, 0x0); - write_grf5101(dev, 0x0B, chan); - write_grf5101(dev, 0x07, 0x1000); - - grf5101_write_phy_antenna(dev, channel); -} - -static void grf5101_rf_stop(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u32 anaparam; - - anaparam = priv->anaparam; - anaparam &= 0x000fffff; - anaparam |= 0x3f900000; - rtl8180_set_anaparam(priv, anaparam); - - write_grf5101(dev, 0x07, 0x0); - write_grf5101(dev, 0x1f, 0x45); - write_grf5101(dev, 0x1f, 0x5); - write_grf5101(dev, 0x00, 0x8e4); -} - -static void grf5101_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - - rtl8180_set_anaparam(priv, priv->anaparam); - - write_grf5101(dev, 0x1f, 0x0); - write_grf5101(dev, 0x1f, 0x0); - write_grf5101(dev, 0x1f, 0x40); - write_grf5101(dev, 0x1f, 0x60); - write_grf5101(dev, 0x1f, 0x61); - write_grf5101(dev, 0x1f, 0x61); - write_grf5101(dev, 0x00, 0xae4); - write_grf5101(dev, 0x1f, 0x1); - write_grf5101(dev, 0x1f, 0x41); - write_grf5101(dev, 0x1f, 0x61); - - write_grf5101(dev, 0x01, 0x1a23); - write_grf5101(dev, 0x02, 0x4971); - write_grf5101(dev, 0x03, 0x41de); - write_grf5101(dev, 0x04, 0x2d80); - write_grf5101(dev, 0x05, 0x68ff); /* 0x61ff original value */ - write_grf5101(dev, 0x06, 0x0); - write_grf5101(dev, 0x07, 0x0); - write_grf5101(dev, 0x08, 0x7533); - write_grf5101(dev, 0x09, 0xc401); - write_grf5101(dev, 0x0a, 0x0); - write_grf5101(dev, 0x0c, 0x1c7); - write_grf5101(dev, 0x0d, 0x29d3); - write_grf5101(dev, 0x0e, 0x2e8); - write_grf5101(dev, 0x10, 0x192); - write_grf5101(dev, 0x11, 0x248); - write_grf5101(dev, 0x12, 0x0); - write_grf5101(dev, 0x13, 0x20c4); - write_grf5101(dev, 0x14, 0xf4fc); - write_grf5101(dev, 0x15, 0x0); - write_grf5101(dev, 0x16, 0x1500); - - write_grf5101(dev, 0x07, 0x1000); - - /* baseband configuration */ - rtl8180_write_phy(dev, 0, 0xa8); - rtl8180_write_phy(dev, 3, 0x0); - rtl8180_write_phy(dev, 4, 0xc0); - rtl8180_write_phy(dev, 5, 0x90); - rtl8180_write_phy(dev, 6, 0x1e); - rtl8180_write_phy(dev, 7, 0x64); - - grf5101_write_phy_antenna(dev, 1); - - rtl8180_write_phy(dev, 0x11, 0x88); - - if (rtl818x_ioread8(priv, &priv->map->CONFIG2) & - RTL818X_CONFIG2_ANTENNA_DIV) - rtl8180_write_phy(dev, 0x12, 0xc0); /* enable ant diversity */ - else - rtl8180_write_phy(dev, 0x12, 0x40); /* disable ant diversity */ - - rtl8180_write_phy(dev, 0x13, 0x90 | priv->csthreshold); - - rtl8180_write_phy(dev, 0x19, 0x0); - rtl8180_write_phy(dev, 0x1a, 0xa0); - rtl8180_write_phy(dev, 0x1b, 0x44); -} - -const struct rtl818x_rf_ops grf5101_rf_ops = { - .name = "GCT", - .init = grf5101_rf_init, - .stop = grf5101_rf_stop, - .set_chan = grf5101_rf_set_channel, - .calc_rssi = grf5101_rf_calc_rssi, -}; diff --git a/drivers/net/wireless/rtl818x/rtl8180/grf5101.h b/drivers/net/wireless/rtl818x/rtl8180/grf5101.h deleted file mode 100644 index 4d80a2785123..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/grf5101.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef RTL8180_GRF5101_H -#define RTL8180_GRF5101_H - -/* - * Radio tuning for GCT GRF5101 on RTL8180 - * - * Copyright 2007 Andrea Merello - * - * Code from the BSD driver and the rtl8181 project have been - * very useful to understand certain things - * - * I want to thanks the Authors of such projects and the Ndiswrapper - * project Authors. - * - * A special Big Thanks also is for all people who donated me cards, - * making possible the creation of the original rtl8180 driver - * from which this code is derived! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define GRF5101_ANTENNA 0xA3 - -extern const struct rtl818x_rf_ops grf5101_rf_ops; - -#endif /* RTL8180_GRF5101_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8180/max2820.c b/drivers/net/wireless/rtl818x/rtl8180/max2820.c deleted file mode 100644 index eebf23976524..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/max2820.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Radio tuning for Maxim max2820 on RTL8180 - * - * Copyright 2007 Andrea Merello - * - * Code from the BSD driver and the rtl8181 project have been - * very useful to understand certain things - * - * I want to thanks the Authors of such projects and the Ndiswrapper - * project Authors. - * - * A special Big Thanks also is for all people who donated me cards, - * making possible the creation of the original rtl8180 driver - * from which this code is derived! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include "rtl8180.h" -#include "max2820.h" - -static const u32 max2820_chan[] = { - 12, /* CH 1 */ - 17, - 22, - 27, - 32, - 37, - 42, - 47, - 52, - 57, - 62, - 67, - 72, - 84, /* CH 14 */ -}; - -static void write_max2820(struct ieee80211_hw *dev, u8 addr, u32 data) -{ - struct rtl8180_priv *priv = dev->priv; - u32 phy_config; - - phy_config = 0x90 + (data & 0xf); - phy_config <<= 16; - phy_config += addr; - phy_config <<= 8; - phy_config += (data >> 4) & 0xff; - - rtl818x_iowrite32(priv, - (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config); - - msleep(1); -} - -static void max2820_write_phy_antenna(struct ieee80211_hw *dev, short chan) -{ - struct rtl8180_priv *priv = dev->priv; - u8 ant; - - ant = MAXIM_ANTENNA; - if (priv->rfparam & RF_PARAM_ANTBDEFAULT) - ant |= BB_ANTENNA_B; - if (chan == 14) - ant |= BB_ANTATTEN_CHAN14; - - rtl8180_write_phy(dev, 0x10, ant); -} - -static u8 max2820_rf_calc_rssi(u8 agc, u8 sq) -{ - bool odd; - - odd = !!(agc & 1); - - agc >>= 1; - if (odd) - agc += 76; - else - agc += 66; - - /* TODO: change addends above to avoid mult / div below */ - return 65 * agc / 100; -} - -static void max2820_rf_set_channel(struct ieee80211_hw *dev, - struct ieee80211_conf *conf) -{ - struct rtl8180_priv *priv = dev->priv; - int channel = conf ? - ieee80211_frequency_to_channel(conf->chandef.chan->center_freq) : 1; - unsigned int chan_idx = channel - 1; - u32 txpw = priv->channels[chan_idx].hw_value & 0xFF; - u32 chan = max2820_chan[chan_idx]; - - /* While philips SA2400 drive the PA bias from - * sa2400, for MAXIM we do this directly from BB */ - rtl8180_write_phy(dev, 3, txpw); - - max2820_write_phy_antenna(dev, channel); - write_max2820(dev, 3, chan); -} - -static void max2820_rf_stop(struct ieee80211_hw *dev) -{ - rtl8180_write_phy(dev, 3, 0x8); - write_max2820(dev, 1, 0); -} - - -static void max2820_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - - /* MAXIM from netbsd driver */ - write_max2820(dev, 0, 0x007); /* test mode as indicated in datasheet */ - write_max2820(dev, 1, 0x01e); /* enable register */ - write_max2820(dev, 2, 0x001); /* synt register */ - - max2820_rf_set_channel(dev, NULL); - - write_max2820(dev, 4, 0x313); /* rx register */ - - /* PA is driven directly by the BB, we keep the MAXIM bias - * at the highest value in case that setting it to lower - * values may introduce some further attenuation somewhere.. - */ - write_max2820(dev, 5, 0x00f); - - /* baseband configuration */ - rtl8180_write_phy(dev, 0, 0x88); /* sys1 */ - rtl8180_write_phy(dev, 3, 0x08); /* txagc */ - rtl8180_write_phy(dev, 4, 0xf8); /* lnadet */ - rtl8180_write_phy(dev, 5, 0x90); /* ifagcinit */ - rtl8180_write_phy(dev, 6, 0x1a); /* ifagclimit */ - rtl8180_write_phy(dev, 7, 0x64); /* ifagcdet */ - - max2820_write_phy_antenna(dev, 1); - - rtl8180_write_phy(dev, 0x11, 0x88); /* trl */ - - if (rtl818x_ioread8(priv, &priv->map->CONFIG2) & - RTL818X_CONFIG2_ANTENNA_DIV) - rtl8180_write_phy(dev, 0x12, 0xc7); - else - rtl8180_write_phy(dev, 0x12, 0x47); - - rtl8180_write_phy(dev, 0x13, 0x9b); - - rtl8180_write_phy(dev, 0x19, 0x0); /* CHESTLIM */ - rtl8180_write_phy(dev, 0x1a, 0x9f); /* CHSQLIM */ - - max2820_rf_set_channel(dev, NULL); -} - -const struct rtl818x_rf_ops max2820_rf_ops = { - .name = "Maxim", - .init = max2820_rf_init, - .stop = max2820_rf_stop, - .set_chan = max2820_rf_set_channel, - .calc_rssi = max2820_rf_calc_rssi, -}; diff --git a/drivers/net/wireless/rtl818x/rtl8180/max2820.h b/drivers/net/wireless/rtl818x/rtl8180/max2820.h deleted file mode 100644 index 8e982b72b690..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/max2820.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef RTL8180_MAX2820_H -#define RTL8180_MAX2820_H - -/* - * Radio tuning for Maxim max2820 on RTL8180 - * - * Copyright 2007 Andrea Merello - * - * Code from the BSD driver and the rtl8181 project have been - * very useful to understand certain things - * - * I want to thanks the Authors of such projects and the Ndiswrapper - * project Authors. - * - * A special Big Thanks also is for all people who donated me cards, - * making possible the creation of the original rtl8180 driver - * from which this code is derived! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define MAXIM_ANTENNA 0xb3 - -extern const struct rtl818x_rf_ops max2820_rf_ops; - -#endif /* RTL8180_MAX2820_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h deleted file mode 100644 index e8243a44d6b6..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8180.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef RTL8180_H -#define RTL8180_H - -#include "rtl818x.h" - -#define MAX_RX_SIZE IEEE80211_MAX_RTS_THRESHOLD - -#define RF_PARAM_ANALOGPHY (1 << 0) -#define RF_PARAM_ANTBDEFAULT (1 << 1) -#define RF_PARAM_CARRIERSENSE1 (1 << 2) -#define RF_PARAM_CARRIERSENSE2 (1 << 3) - -#define BB_ANTATTEN_CHAN14 0x0C -#define BB_ANTENNA_B 0x40 - -#define BB_HOST_BANG (1 << 30) -#define BB_HOST_BANG_EN (1 << 2) -#define BB_HOST_BANG_CLK (1 << 1) -#define BB_HOST_BANG_DATA 1 - -#define ANAPARAM_TXDACOFF_SHIFT 27 -#define ANAPARAM_PWR0_SHIFT 28 -#define ANAPARAM_PWR0_MASK (0x07 << ANAPARAM_PWR0_SHIFT) -#define ANAPARAM_PWR1_SHIFT 20 -#define ANAPARAM_PWR1_MASK (0x7F << ANAPARAM_PWR1_SHIFT) - -/* rtl8180/rtl8185 have 3 queue + beacon queue. - * mac80211 can use just one, + beacon = 2 tot. - */ -#define RTL8180_NR_TX_QUEUES 2 - -/* rtl8187SE have 6 queues + beacon queues - * mac80211 can use 4 QoS data queue, + beacon = 5 tot - */ -#define RTL8187SE_NR_TX_QUEUES 5 - -/* for array static allocation, it is the max of above */ -#define RTL818X_NR_TX_QUEUES 5 - -struct rtl8180_tx_desc { - __le32 flags; - __le16 rts_duration; - __le16 plcp_len; - __le32 tx_buf; - union{ - __le32 frame_len; - struct { - __le16 frame_len_se; - __le16 frame_duration; - } __packed; - } __packed; - __le32 next_tx_desc; - u8 cw; - u8 retry_limit; - u8 agc; - u8 flags2; - /* rsvd for 8180/8185. - * valid for 8187se but we dont use it - */ - u32 reserved; - /* all rsvd for 8180/8185 */ - __le16 flags3; - __le16 frag_qsize; -} __packed; - -struct rtl818x_rx_cmd_desc { - __le32 flags; - u32 reserved; - __le32 rx_buf; -} __packed; - -struct rtl8180_rx_desc { - __le32 flags; - __le32 flags2; - __le64 tsft; - -} __packed; - -struct rtl8187se_rx_desc { - __le32 flags; - __le64 tsft; - __le32 flags2; - __le32 flags3; - u32 reserved[3]; -} __packed; - -struct rtl8180_tx_ring { - struct rtl8180_tx_desc *desc; - dma_addr_t dma; - unsigned int idx; - unsigned int entries; - struct sk_buff_head queue; -}; - -struct rtl8180_vif { - struct ieee80211_hw *dev; - - /* beaconing */ - struct delayed_work beacon_work; - bool enable_beacon; -}; - -struct rtl8180_priv { - /* common between rtl818x drivers */ - struct rtl818x_csr __iomem *map; - const struct rtl818x_rf_ops *rf; - struct ieee80211_vif *vif; - - /* rtl8180 driver specific */ - bool map_pio; - spinlock_t lock; - void *rx_ring; - u8 rx_ring_sz; - dma_addr_t rx_ring_dma; - unsigned int rx_idx; - struct sk_buff *rx_buf[32]; - struct rtl8180_tx_ring tx_ring[RTL818X_NR_TX_QUEUES]; - struct ieee80211_channel channels[14]; - struct ieee80211_rate rates[12]; - struct ieee80211_supported_band band; - struct ieee80211_tx_queue_params queue_param[4]; - struct pci_dev *pdev; - u32 rx_conf; - u8 slot_time; - u16 ack_time; - - enum { - RTL818X_CHIP_FAMILY_RTL8180, - RTL818X_CHIP_FAMILY_RTL8185, - RTL818X_CHIP_FAMILY_RTL8187SE, - } chip_family; - u32 anaparam; - u16 rfparam; - u8 csthreshold; - u8 mac_addr[ETH_ALEN]; - u8 rf_type; - u8 xtal_out; - u8 xtal_in; - u8 xtal_cal; - u8 thermal_meter_val; - u8 thermal_meter_en; - u8 antenna_diversity_en; - u8 antenna_diversity_default; - /* sequence # */ - u16 seqno; -}; - -void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); -void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam); -void rtl8180_set_anaparam2(struct rtl8180_priv *priv, u32 anaparam2); - -static inline u8 rtl818x_ioread8(struct rtl8180_priv *priv, u8 __iomem *addr) -{ - return ioread8(addr); -} - -static inline u16 rtl818x_ioread16(struct rtl8180_priv *priv, __le16 __iomem *addr) -{ - return ioread16(addr); -} - -static inline u32 rtl818x_ioread32(struct rtl8180_priv *priv, __le32 __iomem *addr) -{ - return ioread32(addr); -} - -static inline void rtl818x_iowrite8(struct rtl8180_priv *priv, - u8 __iomem *addr, u8 val) -{ - iowrite8(val, addr); -} - -static inline void rtl818x_iowrite16(struct rtl8180_priv *priv, - __le16 __iomem *addr, u16 val) -{ - iowrite16(val, addr); -} - -static inline void rtl818x_iowrite32(struct rtl8180_priv *priv, - __le32 __iomem *addr, u32 val) -{ - iowrite32(val, addr); -} - -#endif /* RTL8180_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c deleted file mode 100644 index 9bda5bc78eda..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.c +++ /dev/null @@ -1,770 +0,0 @@ - -/* - * Radio tuning for RTL8225 on RTL8180 - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8180 driver, which is: - * Copyright 2005 Andrea Merello , et al. - * - * Thanks to Realtek for their support! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include "rtl8180.h" -#include "rtl8225.h" - -static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data) -{ - struct rtl8180_priv *priv = dev->priv; - u16 reg80, reg84, reg82; - u32 bangdata; - int i; - - bangdata = (data << 4) | (addr & 0xf); - - reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3; - reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7); - - reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7 | 0x400); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(10); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(10); - - for (i = 15; i >= 0; i--) { - u16 reg = reg80; - - if (bangdata & (1 << i)) - reg |= 1; - - if (i & 1) - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); - - if (!(i & 1)) - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(10); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x400); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); -} - -static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr) -{ - struct rtl8180_priv *priv = dev->priv; - u16 reg80, reg82, reg84, out; - int i; - - reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput); - reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); - reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect) | 0x400; - - reg80 &= ~0xF; - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(4); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(5); - - for (i = 4; i >= 0; i--) { - u16 reg = reg80 | ((addr >> i) & 1); - - if (!(i & 1)) { - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(1); - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg | (1 << 1)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg | (1 << 1)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - - if (i & 1) { - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(1); - } - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x000E); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x040E); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - - out = 0; - for (i = 11; i >= 0; i--) { - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(1); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - - if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1)) - out |= 1 << i; - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 2)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0); - - return out; -} - -static const u16 rtl8225bcd_rxgain[] = { - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, - 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, - 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, - 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, - 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, - 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, - 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, - 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, - 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, - 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, - 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, - 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb -}; - -static const u8 rtl8225_agc[] = { - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, - 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, - 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, - 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, - 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, - 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, - 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, - 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, - 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, - 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, - 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, - 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 -}; - -static const u8 rtl8225_gain[] = { - 0x23, 0x88, 0x7c, 0xa5, /* -82dbm */ - 0x23, 0x88, 0x7c, 0xb5, /* -82dbm */ - 0x23, 0x88, 0x7c, 0xc5, /* -82dbm */ - 0x33, 0x80, 0x79, 0xc5, /* -78dbm */ - 0x43, 0x78, 0x76, 0xc5, /* -74dbm */ - 0x53, 0x60, 0x73, 0xc5, /* -70dbm */ - 0x63, 0x58, 0x70, 0xc5, /* -66dbm */ -}; - -static const u8 rtl8225_threshold[] = { - 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd -}; - -static const u8 rtl8225_tx_gain_cck_ofdm[] = { - 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e -}; - -static const u8 rtl8225_tx_power_cck[] = { - 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, - 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, - 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, - 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, - 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, - 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 -}; - -static const u8 rtl8225_tx_power_cck_ch14[] = { - 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, - 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, - 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 rtl8225_tx_power_ofdm[] = { - 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 -}; - -static const u32 rtl8225_chan[] = { - 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c, - 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72 -}; - -static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) -{ - struct rtl8180_priv *priv = dev->priv; - u8 cck_power, ofdm_power; - const u8 *tmp; - u32 reg; - int i; - - cck_power = priv->channels[channel - 1].hw_value & 0xFF; - ofdm_power = priv->channels[channel - 1].hw_value >> 8; - - cck_power = min(cck_power, (u8)35); - ofdm_power = min(ofdm_power, (u8)35); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, - rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1); - - if (channel == 14) - tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8]; - else - tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8]; - - for (i = 0; i < 8; i++) - rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); - - msleep(1); /* FIXME: optional? */ - - /* TODO: use set_anaparam2 dev.c_func*/ - /* anaparam2 on */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, - rtl8225_tx_gain_cck_ofdm[ofdm_power/6] >> 1); - - tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6]; - - rtl8225_write_phy_ofdm(dev, 5, *tmp); - rtl8225_write_phy_ofdm(dev, 7, *tmp); - - msleep(1); -} - -static void rtl8225_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - int i; - - rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON); - - /* host_pci_init */ - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - msleep(200); /* FIXME: ehh?? */ - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6)); - - rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008); - - /* TODO: check if we need really to change BRSR to do RF config */ - rtl818x_ioread16(priv, &priv->map->BRSR); - rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); - rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl8225_write(dev, 0x0, 0x067); - rtl8225_write(dev, 0x1, 0xFE0); - rtl8225_write(dev, 0x2, 0x44D); - rtl8225_write(dev, 0x3, 0x441); - rtl8225_write(dev, 0x4, 0x8BE); - rtl8225_write(dev, 0x5, 0xBF0); /* TODO: minipci */ - rtl8225_write(dev, 0x6, 0xAE6); - rtl8225_write(dev, 0x7, rtl8225_chan[0]); - rtl8225_write(dev, 0x8, 0x01F); - rtl8225_write(dev, 0x9, 0x334); - rtl8225_write(dev, 0xA, 0xFD4); - rtl8225_write(dev, 0xB, 0x391); - rtl8225_write(dev, 0xC, 0x050); - rtl8225_write(dev, 0xD, 0x6DB); - rtl8225_write(dev, 0xE, 0x029); - rtl8225_write(dev, 0xF, 0x914); msleep(1); - - rtl8225_write(dev, 0x2, 0xC4D); msleep(100); - - rtl8225_write(dev, 0x0, 0x127); - - for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) { - rtl8225_write(dev, 0x1, i + 1); - rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]); - } - - rtl8225_write(dev, 0x0, 0x027); - rtl8225_write(dev, 0x0, 0x22F); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - - for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { - rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); - msleep(1); - rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); - msleep(1); - } - - msleep(1); - - rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x06, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x08, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x11, 0x03); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1); - - rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1); - rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1); - rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1); - rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1); - rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1); - rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1); - rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1); - rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1); - rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1); - rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1); - rtl8225_write_phy_cck(dev, 0x13, 0xd0); - rtl8225_write_phy_cck(dev, 0x19, 0x00); - rtl8225_write_phy_cck(dev, 0x1a, 0xa0); - rtl8225_write_phy_cck(dev, 0x1b, 0x08); - rtl8225_write_phy_cck(dev, 0x40, 0x86); - rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1); - rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1); - rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1); - rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1); - rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1); - rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1); - rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1); - rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1); - rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1); - rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1); - rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1); - rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1); - - rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); msleep(1); - - rtl8225_rf_set_tx_power(dev, 1); - - /* RX antenna default to A */ - rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */ - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */ - - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ - msleep(1); - rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - - rtl8225_write(dev, 0x0c, 0x50); - /* set OFDM initial gain */ - rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[4 * 4]); - rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[4 * 4 + 1]); - rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[4 * 4 + 2]); - rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[4 * 4 + 3]); - /* set CCK threshold */ - rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[0]); -} - -static const u8 rtl8225z2_tx_power_cck_ch14[] = { - 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 rtl8225z2_tx_power_cck_B[] = { - 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04 -}; - -static const u8 rtl8225z2_tx_power_cck_A[] = { - 0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04 -}; - -static const u8 rtl8225z2_tx_power_cck[] = { - 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 -}; - -static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) -{ - struct rtl8180_priv *priv = dev->priv; - u8 cck_power, ofdm_power; - const u8 *tmp; - int i; - - cck_power = priv->channels[channel - 1].hw_value & 0xFF; - ofdm_power = priv->channels[channel - 1].hw_value >> 8; - - if (channel == 14) - tmp = rtl8225z2_tx_power_cck_ch14; - else if (cck_power == 12) - tmp = rtl8225z2_tx_power_cck_B; - else if (cck_power == 13) - tmp = rtl8225z2_tx_power_cck_A; - else - tmp = rtl8225z2_tx_power_cck; - - for (i = 0; i < 8; i++) - rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); - - cck_power = min(cck_power, (u8)35); - if (cck_power == 13 || cck_power == 14) - cck_power = 12; - if (cck_power >= 15) - cck_power -= 2; - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, cck_power); - rtl818x_ioread8(priv, &priv->map->TX_GAIN_CCK); - msleep(1); - - ofdm_power = min(ofdm_power, (u8)35); - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, ofdm_power); - - rtl8225_write_phy_ofdm(dev, 2, 0x62); - rtl8225_write_phy_ofdm(dev, 5, 0x00); - rtl8225_write_phy_ofdm(dev, 6, 0x40); - rtl8225_write_phy_ofdm(dev, 7, 0x00); - rtl8225_write_phy_ofdm(dev, 8, 0x40); - - msleep(1); -} - -static const u16 rtl8225z2_rxgain[] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009, - 0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141, - 0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183, - 0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244, - 0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288, - 0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345, - 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389, - 0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393, - 0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, - 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9, - 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, - 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb -}; - -static void rtl8225z2_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - int i; - - rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON); - - /* host_pci_init */ - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - msleep(200); /* FIXME: ehh?? */ - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6)); - - rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00088008); - - /* TODO: check if we need really to change BRSR to do RF config */ - rtl818x_ioread16(priv, &priv->map->BRSR); - rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); - rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - - rtl8225_write(dev, 0x0, 0x0B7); msleep(1); - rtl8225_write(dev, 0x1, 0xEE0); msleep(1); - rtl8225_write(dev, 0x2, 0x44D); msleep(1); - rtl8225_write(dev, 0x3, 0x441); msleep(1); - rtl8225_write(dev, 0x4, 0x8C3); msleep(1); - rtl8225_write(dev, 0x5, 0xC72); msleep(1); - rtl8225_write(dev, 0x6, 0x0E6); msleep(1); - rtl8225_write(dev, 0x7, 0x82A); msleep(1); - rtl8225_write(dev, 0x8, 0x03F); msleep(1); - rtl8225_write(dev, 0x9, 0x335); msleep(1); - rtl8225_write(dev, 0xa, 0x9D4); msleep(1); - rtl8225_write(dev, 0xb, 0x7BB); msleep(1); - rtl8225_write(dev, 0xc, 0x850); msleep(1); - rtl8225_write(dev, 0xd, 0xCDF); msleep(1); - rtl8225_write(dev, 0xe, 0x02B); msleep(1); - rtl8225_write(dev, 0xf, 0x114); msleep(100); - - if (!(rtl8225_read(dev, 6) & (1 << 7))) { - rtl8225_write(dev, 0x02, 0x0C4D); - msleep(200); - rtl8225_write(dev, 0x02, 0x044D); - msleep(100); - /* TODO: readd calibration failure message when the calibration - check works */ - } - - rtl8225_write(dev, 0x0, 0x1B7); - rtl8225_write(dev, 0x3, 0x002); - rtl8225_write(dev, 0x5, 0x004); - - for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { - rtl8225_write(dev, 0x1, i + 1); - rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); - } - - rtl8225_write(dev, 0x0, 0x0B7); msleep(100); - rtl8225_write(dev, 0x2, 0xC4D); - - msleep(200); - rtl8225_write(dev, 0x2, 0x44D); - msleep(100); - - rtl8225_write(dev, 0x00, 0x2BF); - rtl8225_write(dev, 0xFF, 0xFFFF); - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - - for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { - rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); - msleep(1); - rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); - msleep(1); - } - - msleep(1); - - rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0d, 0x43); - rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1b, 0x11); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1e, 0xb3); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); /* FIXME: not needed? */ - rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1); - - rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1); - rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1); - rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1); - rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1); - rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1); - rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1); - rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1); - rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1); - rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1); - rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1); - rtl8225_write_phy_cck(dev, 0x13, 0xd0); - rtl8225_write_phy_cck(dev, 0x19, 0x00); - rtl8225_write_phy_cck(dev, 0x1a, 0xa0); - rtl8225_write_phy_cck(dev, 0x1b, 0x08); - rtl8225_write_phy_cck(dev, 0x40, 0x86); - rtl8225_write_phy_cck(dev, 0x41, 0x8a); msleep(1); - rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1); - rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1); - rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1); - rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1); - rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1); - rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1); - rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1); - rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1); - rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1); - rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1); - rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1); - - rtl818x_iowrite8(priv, (u8 __iomem *)((void __iomem *)priv->map + 0x5B), 0x0D); msleep(1); - - rtl8225z2_rf_set_tx_power(dev, 1); - - /* RX antenna default to A */ - rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */ - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */ - - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ - msleep(1); - rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); -} - -static void rtl8225_rf_stop(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u8 reg; - - rtl8225_write(dev, 0x4, 0x1f); msleep(1); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); -} - -static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, - struct ieee80211_conf *conf) -{ - struct rtl8180_priv *priv = dev->priv; - int chan = - ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); - - if (priv->rf->init == rtl8225_rf_init) - rtl8225_rf_set_tx_power(dev, chan); - else - rtl8225z2_rf_set_tx_power(dev, chan); - - rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); - msleep(10); -} - -static const struct rtl818x_rf_ops rtl8225_ops = { - .name = "rtl8225", - .init = rtl8225_rf_init, - .stop = rtl8225_rf_stop, - .set_chan = rtl8225_rf_set_channel, -}; - -static const struct rtl818x_rf_ops rtl8225z2_ops = { - .name = "rtl8225z2", - .init = rtl8225z2_rf_init, - .stop = rtl8225_rf_stop, - .set_chan = rtl8225_rf_set_channel, -}; - -const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u16 reg8, reg9; - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - msleep(100); - - rtl8225_write(dev, 0, 0x1B7); - - reg8 = rtl8225_read(dev, 8); - reg9 = rtl8225_read(dev, 9); - - rtl8225_write(dev, 0, 0x0B7); - - if (reg8 != 0x588 || reg9 != 0x700) - return &rtl8225_ops; - - return &rtl8225z2_ops; -} diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.h b/drivers/net/wireless/rtl818x/rtl8180/rtl8225.h deleted file mode 100644 index 310013a2d726..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef RTL8180_RTL8225_H -#define RTL8180_RTL8225_H - -#define RTL8225_ANAPARAM_ON 0xa0000b59 -#define RTL8225_ANAPARAM2_ON 0x860dec11 -#define RTL8225_ANAPARAM_OFF 0xa00beb59 -#define RTL8225_ANAPARAM2_OFF 0x840dec11 - -const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *); - -static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev, - u8 addr, u8 data) -{ - rtl8180_write_phy(dev, addr, data); -} - -static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev, - u8 addr, u8 data) -{ - rtl8180_write_phy(dev, addr, data | 0x10000); -} - -#endif /* RTL8180_RTL8225_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c b/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c deleted file mode 100644 index fde89866fa8d..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.c +++ /dev/null @@ -1,475 +0,0 @@ - -/* Radio tuning for RTL8225 on RTL8187SE - * - * Copyright 2009 Larry Finger - * Copyright 2014 Andrea Merello - * - * Based on the r8180 and Realtek r8187se drivers, which are: - * Copyright 2004-2005 Andrea Merello , et al. - * - * Also based on the rtl8187 driver, which is: - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include - -#include "rtl8180.h" -#include "rtl8225se.h" - -#define PFX "rtl8225 (se) " - -static const u32 RF_GAIN_TABLE[] = { - 0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6, - 0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057, - 0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3, - 0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3, - 0x0183, 0x0163, 0x0143, 0x0123, 0x0103 -}; - -static const u8 cck_ofdm_gain_settings[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, - 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, - 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, -}; - -static const u8 rtl8225se_tx_gain_cck_ofdm[] = { - 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e -}; - -static const u8 rtl8225se_tx_power_cck[] = { - 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, - 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, - 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, - 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, - 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, - 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 -}; - -static const u8 rtl8225se_tx_power_cck_ch14[] = { - 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, - 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, - 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 rtl8225se_tx_power_ofdm[] = { - 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 -}; - -static const u32 rtl8225se_chan[] = { - 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, - 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A, -}; - -static const u8 rtl8225sez2_tx_power_cck_ch14[] = { - 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 rtl8225sez2_tx_power_cck_B[] = { - 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04 -}; - -static const u8 rtl8225sez2_tx_power_cck_A[] = { - 0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04 -}; - -static const u8 rtl8225sez2_tx_power_cck[] = { - 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 -}; - -static const u8 ZEBRA_AGC[] = { - 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, - 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, - 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, - 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, - 0x48, 0x47, 0x46, 0x45, 0x44, 0x29, 0x28, 0x27, - 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07, - 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16, - 0x17, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1a, 0x1b, - 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, - 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, - 0x21, 0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x24, - 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, - 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F -}; - -static const u8 OFDM_CONFIG[] = { - 0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50, - 0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, - 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26, - 0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB, - 0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00, - 0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00, - 0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e, - 0xD8, 0x3C, 0x7B, 0x10, 0x10 -}; - -static void rtl8187se_three_wire_io(struct ieee80211_hw *dev, u8 *data, - u8 len, bool write) -{ - struct rtl8180_priv *priv = dev->priv; - int i; - u8 tmp; - - do { - for (i = 0; i < 5; i++) { - tmp = rtl818x_ioread8(priv, SW_3W_CMD1); - if (!(tmp & 0x3)) - break; - udelay(10); - } - if (i == 5) - wiphy_err(dev->wiphy, PFX - "CmdReg: 0x%x RE/WE bits aren't clear\n", tmp); - - tmp = rtl818x_ioread8(priv, &priv->map->rf_sw_config) | 0x02; - rtl818x_iowrite8(priv, &priv->map->rf_sw_config, tmp); - - tmp = rtl818x_ioread8(priv, REG_ADDR1(0x84)) & 0xF7; - rtl818x_iowrite8(priv, REG_ADDR1(0x84), tmp); - if (write) { - if (len == 16) { - rtl818x_iowrite16(priv, SW_3W_DB0, - *(u16 *)data); - } else if (len == 64) { - rtl818x_iowrite32(priv, SW_3W_DB0_4, - *((u32 *)data)); - rtl818x_iowrite32(priv, SW_3W_DB1_4, - *((u32 *)(data + 4))); - } else - wiphy_err(dev->wiphy, PFX - "Unimplemented length\n"); - } else { - rtl818x_iowrite16(priv, SW_3W_DB0, *(u16 *)data); - } - if (write) - tmp = 2; - else - tmp = 1; - rtl818x_iowrite8(priv, SW_3W_CMD1, tmp); - for (i = 0; i < 5; i++) { - tmp = rtl818x_ioread8(priv, SW_3W_CMD1); - if (!(tmp & 0x3)) - break; - udelay(10); - } - rtl818x_iowrite8(priv, SW_3W_CMD1, 0); - if (!write) { - *((u16 *)data) = rtl818x_ioread16(priv, SI_DATA_REG); - *((u16 *)data) &= 0x0FFF; - } - } while (0); -} - -static u32 rtl8187se_rf_readreg(struct ieee80211_hw *dev, u8 addr) -{ - u32 dataread = addr & 0x0F; - rtl8187se_three_wire_io(dev, (u8 *)&dataread, 16, 0); - return dataread; -} - -static void rtl8187se_rf_writereg(struct ieee80211_hw *dev, u8 addr, u32 data) -{ - u32 outdata = (data << 4) | (u32)(addr & 0x0F); - rtl8187se_three_wire_io(dev, (u8 *)&outdata, 16, 1); -} - - -static void rtl8225se_write_zebra_agc(struct ieee80211_hw *dev) -{ - int i; - - for (i = 0; i < 128; i++) { - rtl8225se_write_phy_ofdm(dev, 0xF, ZEBRA_AGC[i]); - rtl8225se_write_phy_ofdm(dev, 0xE, i+0x80); - rtl8225se_write_phy_ofdm(dev, 0xE, 0); - } -} - -static void rtl8187se_write_ofdm_config(struct ieee80211_hw *dev) -{ - /* write OFDM_CONFIG table */ - int i; - - for (i = 0; i < 60; i++) - rtl8225se_write_phy_ofdm(dev, i, OFDM_CONFIG[i]); - -} - -static void rtl8225sez2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) -{ - struct rtl8180_priv *priv = dev->priv; - u8 cck_power, ofdm_power; - - cck_power = priv->channels[channel - 1].hw_value & 0xFF; - if (cck_power > 35) - cck_power = 35; - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, - cck_ofdm_gain_settings[cck_power]); - - usleep_range(1000, 5000); - ofdm_power = priv->channels[channel - 1].hw_value >> 8; - if (ofdm_power > 35) - ofdm_power = 35; - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, - cck_ofdm_gain_settings[ofdm_power]); - if (ofdm_power < 12) { - rtl8225se_write_phy_ofdm(dev, 7, 0x5C); - rtl8225se_write_phy_ofdm(dev, 9, 0x5C); - } - if (ofdm_power < 18) { - rtl8225se_write_phy_ofdm(dev, 7, 0x54); - rtl8225se_write_phy_ofdm(dev, 9, 0x54); - } else { - rtl8225se_write_phy_ofdm(dev, 7, 0x50); - rtl8225se_write_phy_ofdm(dev, 9, 0x50); - } - - usleep_range(1000, 5000); -} - -static void rtl8187se_write_rf_gain(struct ieee80211_hw *dev) -{ - int i; - - for (i = 0; i <= 36; i++) { - rtl8187se_rf_writereg(dev, 0x01, i); mdelay(1); - rtl8187se_rf_writereg(dev, 0x02, RF_GAIN_TABLE[i]); mdelay(1); - } -} - -static void rtl8187se_write_initial_gain(struct ieee80211_hw *dev, - int init_gain) -{ - switch (init_gain) { - default: - rtl8225se_write_phy_ofdm(dev, 0x17, 0x26); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1); - break; - case 2: - rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x05, 0xFA); mdelay(1); - break; - case 3: - rtl8225se_write_phy_ofdm(dev, 0x17, 0x36); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1); - break; - case 4: - rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1); - break; - case 5: - rtl8225se_write_phy_ofdm(dev, 0x17, 0x46); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x05, 0xFB); mdelay(1); - break; - case 6: - rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x24, 0x96); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1); - break; - case 7: - rtl8225se_write_phy_ofdm(dev, 0x17, 0x56); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x24, 0xA6); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1); - break; - case 8: - rtl8225se_write_phy_ofdm(dev, 0x17, 0x66); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x24, 0xB6); mdelay(1); - rtl8225se_write_phy_ofdm(dev, 0x05, 0xFC); mdelay(1); - break; - } -} - -void rtl8225se_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u32 rf23, rf24; - u8 d_cut = 0; - u8 tmp; - - /* Page 1 */ - rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1); - rf23 = rtl8187se_rf_readreg(dev, 0x08); mdelay(1); - rf24 = rtl8187se_rf_readreg(dev, 0x09); mdelay(1); - if (rf23 == 0x0818 && rf24 == 0x070C) - d_cut = 1; - - wiphy_info(dev->wiphy, "RTL8225-SE version %s\n", - d_cut ? "D" : "not-D"); - - /* Page 0: reg 0 - 15 */ - rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1); - rtl8187se_rf_writereg(dev, 0x01, 0x06E0); mdelay(1); - rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1); - rtl8187se_rf_writereg(dev, 0x03, 0x07F1); mdelay(1); - rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(1); - rtl8187se_rf_writereg(dev, 0x05, 0x0C72); mdelay(1); - rtl8187se_rf_writereg(dev, 0x06, 0x0AE6); mdelay(1); - rtl8187se_rf_writereg(dev, 0x07, 0x00CA); mdelay(1); - rtl8187se_rf_writereg(dev, 0x08, 0x0E1C); mdelay(1); - rtl8187se_rf_writereg(dev, 0x09, 0x02F0); mdelay(1); - rtl8187se_rf_writereg(dev, 0x0A, 0x09D0); mdelay(1); - rtl8187se_rf_writereg(dev, 0x0B, 0x01BA); mdelay(1); - rtl8187se_rf_writereg(dev, 0x0C, 0x0640); mdelay(1); - rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1); - rtl8187se_rf_writereg(dev, 0x0E, 0x0020); mdelay(1); - rtl8187se_rf_writereg(dev, 0x0F, 0x0990); mdelay(1); - /* page 1: reg 16-30 */ - rtl8187se_rf_writereg(dev, 0x00, 0x013F); mdelay(1); - rtl8187se_rf_writereg(dev, 0x03, 0x0806); mdelay(1); - rtl8187se_rf_writereg(dev, 0x04, 0x03A7); mdelay(1); - rtl8187se_rf_writereg(dev, 0x05, 0x059B); mdelay(1); - rtl8187se_rf_writereg(dev, 0x06, 0x0081); mdelay(1); - rtl8187se_rf_writereg(dev, 0x07, 0x01A0); mdelay(1); - rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1); - rtl8187se_rf_writereg(dev, 0x0B, 0x0418); mdelay(1); - rtl8187se_rf_writereg(dev, 0x0C, 0x0FBE); mdelay(1); - rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(1); - if (d_cut) - rtl8187se_rf_writereg(dev, 0x0E, 0x0807); - else - rtl8187se_rf_writereg(dev, 0x0E, 0x0806); - mdelay(1); - rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC); mdelay(1); - rtl8187se_rf_writereg(dev, 0x00, 0x01D7); mdelay(1); - rtl8187se_rf_writereg(dev, 0x03, 0x0E00); mdelay(1); - rtl8187se_rf_writereg(dev, 0x04, 0x0E50); mdelay(1); - - rtl8187se_write_rf_gain(dev); - - rtl8187se_rf_writereg(dev, 0x05, 0x0203); mdelay(1); - rtl8187se_rf_writereg(dev, 0x06, 0x0200); mdelay(1); - rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11); - rtl8187se_rf_writereg(dev, 0x0D, 0x0008); mdelay(11); - rtl8187se_rf_writereg(dev, 0x00, 0x0037); mdelay(11); - rtl8187se_rf_writereg(dev, 0x04, 0x0160); mdelay(11); - rtl8187se_rf_writereg(dev, 0x07, 0x0080); mdelay(11); - rtl8187se_rf_writereg(dev, 0x02, 0x088D); mdelay(221); - rtl8187se_rf_writereg(dev, 0x00, 0x0137); mdelay(11); - rtl8187se_rf_writereg(dev, 0x07, 0x0000); mdelay(1); - rtl8187se_rf_writereg(dev, 0x07, 0x0180); mdelay(1); - rtl8187se_rf_writereg(dev, 0x07, 0x0220); mdelay(1); - rtl8187se_rf_writereg(dev, 0x07, 0x03E0); mdelay(1); - rtl8187se_rf_writereg(dev, 0x06, 0x00C1); mdelay(1); - rtl8187se_rf_writereg(dev, 0x0A, 0x0001); mdelay(1); - if (priv->xtal_cal) { - tmp = (priv->xtal_in << 4) | (priv->xtal_out << 1) | - (1 << 11) | (1 << 9); - rtl8187se_rf_writereg(dev, 0x0F, tmp); - wiphy_info(dev->wiphy, "Xtal cal\n"); - mdelay(1); - } else { - wiphy_info(dev->wiphy, "NO Xtal cal\n"); - rtl8187se_rf_writereg(dev, 0x0F, 0x0ACC); - mdelay(1); - } - /* page 0 */ - rtl8187se_rf_writereg(dev, 0x00, 0x00BF); mdelay(1); - rtl8187se_rf_writereg(dev, 0x0D, 0x08DF); mdelay(1); - rtl8187se_rf_writereg(dev, 0x02, 0x004D); mdelay(1); - rtl8187se_rf_writereg(dev, 0x04, 0x0975); mdelay(31); - rtl8187se_rf_writereg(dev, 0x00, 0x0197); mdelay(1); - rtl8187se_rf_writereg(dev, 0x05, 0x05AB); mdelay(1); - - rtl8187se_rf_writereg(dev, 0x00, 0x009F); mdelay(1); - rtl8187se_rf_writereg(dev, 0x01, 0x0000); mdelay(1); - rtl8187se_rf_writereg(dev, 0x02, 0x0000); mdelay(1); - /* power save parameters */ - /* TODO: move to dev.c */ - rtl818x_iowrite8(priv, REG_ADDR1(0x024E), - rtl818x_ioread8(priv, REG_ADDR1(0x24E)) & 0x9F); - rtl8225se_write_phy_cck(dev, 0x00, 0xC8); - rtl8225se_write_phy_cck(dev, 0x06, 0x1C); - rtl8225se_write_phy_cck(dev, 0x10, 0x78); - rtl8225se_write_phy_cck(dev, 0x2E, 0xD0); - rtl8225se_write_phy_cck(dev, 0x2F, 0x06); - rtl8225se_write_phy_cck(dev, 0x01, 0x46); - - /* power control */ - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x10); - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x1B); - - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); - rtl8225se_write_phy_ofdm(dev, 0x00, 0x12); - - rtl8225se_write_zebra_agc(dev); - - rtl8225se_write_phy_ofdm(dev, 0x10, 0x00); - - rtl8187se_write_ofdm_config(dev); - - /* turn on RF */ - rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500); - rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500); - /* turn on RF again */ - rtl8187se_rf_writereg(dev, 0x00, 0x009F); udelay(500); - rtl8187se_rf_writereg(dev, 0x04, 0x0972); udelay(500); - /* turn on BB */ - rtl8225se_write_phy_ofdm(dev, 0x10, 0x40); - rtl8225se_write_phy_ofdm(dev, 0x12, 0x40); - - rtl8187se_write_initial_gain(dev, 4); -} - -void rtl8225se_rf_stop(struct ieee80211_hw *dev) -{ - /* checked for 8187se */ - struct rtl8180_priv *priv = dev->priv; - - /* turn off BB RXIQ matrix to cut off rx signal */ - rtl8225se_write_phy_ofdm(dev, 0x10, 0x00); - rtl8225se_write_phy_ofdm(dev, 0x12, 0x00); - /* turn off RF */ - rtl8187se_rf_writereg(dev, 0x04, 0x0000); - rtl8187se_rf_writereg(dev, 0x00, 0x0000); - - usleep_range(1000, 5000); - /* turn off A/D and D/A */ - rtl8180_set_anaparam(priv, RTL8225SE_ANAPARAM_OFF); - rtl8180_set_anaparam2(priv, RTL8225SE_ANAPARAM2_OFF); -} - -void rtl8225se_rf_set_channel(struct ieee80211_hw *dev, - struct ieee80211_conf *conf) -{ - int chan = - ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); - - rtl8225sez2_rf_set_tx_power(dev, chan); - rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]); - if ((rtl8187se_rf_readreg(dev, 0x7) & 0x0F80) != - rtl8225se_chan[chan - 1]) - rtl8187se_rf_writereg(dev, 0x7, rtl8225se_chan[chan - 1]); - usleep_range(10000, 20000); -} - -static const struct rtl818x_rf_ops rtl8225se_ops = { - .name = "rtl8225-se", - .init = rtl8225se_rf_init, - .stop = rtl8225se_rf_stop, - .set_chan = rtl8225se_rf_set_channel, -}; - -const struct rtl818x_rf_ops *rtl8187se_detect_rf(struct ieee80211_hw *dev) -{ - return &rtl8225se_ops; -} diff --git a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h b/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h deleted file mode 100644 index 229400264088..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/rtl8225se.h +++ /dev/null @@ -1,61 +0,0 @@ - -/* Definitions for RTL8187SE hardware - * - * Copyright 2009 Larry Finger - * Copyright 2014 Andrea Merello - * - * Based on the r8180 and Realtek r8187se drivers, which are: - * Copyright 2004-2005 Andrea Merello , et al. - * - * Also based on the rtl8187 driver, which is: - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef RTL8187SE_RTL8225_H -#define RTL8187SE_RTL8225_H - -#define RTL8225SE_ANAPARAM_ON 0xb0054d00 -#define RTL8225SE_ANAPARAM2_ON 0x000004c6 - -/* all off except PLL */ -#define RTL8225SE_ANAPARAM_OFF 0xb0054dec -/* all on including PLL */ -#define RTL8225SE_ANAPARAM_OFF2 0xb0054dfc - -#define RTL8225SE_ANAPARAM2_OFF 0x00ff04c6 - -#define RTL8225SE_ANAPARAM3 0x10 - -enum rtl8187se_power_state { - RTL8187SE_POWER_ON, - RTL8187SE_POWER_OFF, - RTL8187SE_POWER_SLEEP -}; - -static inline void rtl8225se_write_phy_ofdm(struct ieee80211_hw *dev, - u8 addr, u8 data) -{ - rtl8180_write_phy(dev, addr, data); -} - -static inline void rtl8225se_write_phy_cck(struct ieee80211_hw *dev, - u8 addr, u8 data) -{ - rtl8180_write_phy(dev, addr, data | 0x10000); -} - - -const struct rtl818x_rf_ops *rtl8187se_detect_rf(struct ieee80211_hw *); -void rtl8225se_rf_stop(struct ieee80211_hw *dev); -void rtl8225se_rf_set_channel(struct ieee80211_hw *dev, - struct ieee80211_conf *conf); -void rtl8225se_rf_conf_erp(struct ieee80211_hw *dev, - struct ieee80211_bss_conf *info); -void rtl8225se_rf_init(struct ieee80211_hw *dev); - -#endif /* RTL8187SE_RTL8225_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8180/sa2400.c b/drivers/net/wireless/rtl818x/rtl8180/sa2400.c deleted file mode 100644 index 959b049827de..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/sa2400.c +++ /dev/null @@ -1,228 +0,0 @@ - -/* - * Radio tuning for Philips SA2400 on RTL8180 - * - * Copyright 2007 Andrea Merello - * - * Code from the BSD driver and the rtl8181 project have been - * very useful to understand certain things - * - * I want to thanks the Authors of such projects and the Ndiswrapper - * project Authors. - * - * A special Big Thanks also is for all people who donated me cards, - * making possible the creation of the original rtl8180 driver - * from which this code is derived! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include "rtl8180.h" -#include "sa2400.h" - -static const u32 sa2400_chan[] = { - 0x00096c, /* ch1 */ - 0x080970, - 0x100974, - 0x180978, - 0x000980, - 0x080984, - 0x100988, - 0x18098c, - 0x000994, - 0x080998, - 0x10099c, - 0x1809a0, - 0x0009a8, - 0x0009b4, /* ch 14 */ -}; - -static void write_sa2400(struct ieee80211_hw *dev, u8 addr, u32 data) -{ - struct rtl8180_priv *priv = dev->priv; - u32 phy_config; - - /* MAC will bang bits to the sa2400. sw 3-wire is NOT used */ - phy_config = 0xb0000000; - - phy_config |= ((u32)(addr & 0xf)) << 24; - phy_config |= data & 0xffffff; - - rtl818x_iowrite32(priv, - (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config); - - msleep(3); -} - -static void sa2400_write_phy_antenna(struct ieee80211_hw *dev, short chan) -{ - struct rtl8180_priv *priv = dev->priv; - u8 ant = SA2400_ANTENNA; - - if (priv->rfparam & RF_PARAM_ANTBDEFAULT) - ant |= BB_ANTENNA_B; - - if (chan == 14) - ant |= BB_ANTATTEN_CHAN14; - - rtl8180_write_phy(dev, 0x10, ant); - -} - -static u8 sa2400_rf_rssi_map[] = { - 0x64, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, - 0x5d, 0x5c, 0x5b, 0x5a, 0x57, 0x54, 0x52, 0x50, - 0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x41, 0x3f, - 0x3c, 0x3a, 0x37, 0x36, 0x36, 0x1c, 0x1c, 0x1b, - 0x1b, 0x1a, 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, - 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, - 0x13, 0x12, 0x12, 0x11, 0x11, 0x10, 0x10, 0x0f, - 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, - 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x07, - 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x02, -}; - -static u8 sa2400_rf_calc_rssi(u8 agc, u8 sq) -{ - if (sq == 0x80) - return 1; - - if (sq > 78) - return 32; - - /* TODO: recalc sa2400_rf_rssi_map to avoid mult / div */ - return 65 * sa2400_rf_rssi_map[sq] / 100; -} - -static void sa2400_rf_set_channel(struct ieee80211_hw *dev, - struct ieee80211_conf *conf) -{ - struct rtl8180_priv *priv = dev->priv; - int channel = - ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); - u32 txpw = priv->channels[channel - 1].hw_value & 0xFF; - u32 chan = sa2400_chan[channel - 1]; - - write_sa2400(dev, 7, txpw); - - sa2400_write_phy_antenna(dev, channel); - - write_sa2400(dev, 0, chan); - write_sa2400(dev, 1, 0xbb50); - write_sa2400(dev, 2, 0x80); - write_sa2400(dev, 3, 0); -} - -static void sa2400_rf_stop(struct ieee80211_hw *dev) -{ - write_sa2400(dev, 4, 0); -} - -static void sa2400_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u32 anaparam, txconf; - u8 firdac; - int analogphy = priv->rfparam & RF_PARAM_ANALOGPHY; - - anaparam = priv->anaparam; - anaparam &= ~(1 << ANAPARAM_TXDACOFF_SHIFT); - anaparam &= ~ANAPARAM_PWR1_MASK; - anaparam &= ~ANAPARAM_PWR0_MASK; - - if (analogphy) { - anaparam |= SA2400_ANA_ANAPARAM_PWR1_ON << ANAPARAM_PWR1_SHIFT; - firdac = 0; - } else { - anaparam |= (SA2400_DIG_ANAPARAM_PWR1_ON << ANAPARAM_PWR1_SHIFT); - anaparam |= (SA2400_ANAPARAM_PWR0_ON << ANAPARAM_PWR0_SHIFT); - firdac = 1 << SA2400_REG4_FIRDAC_SHIFT; - } - - rtl8180_set_anaparam(priv, anaparam); - - write_sa2400(dev, 0, sa2400_chan[0]); - write_sa2400(dev, 1, 0xbb50); - write_sa2400(dev, 2, 0x80); - write_sa2400(dev, 3, 0); - write_sa2400(dev, 4, 0x19340 | firdac); - write_sa2400(dev, 5, 0x1dfb | (SA2400_MAX_SENS - 54) << 15); - write_sa2400(dev, 4, 0x19348 | firdac); /* calibrate VCO */ - - if (!analogphy) - write_sa2400(dev, 4, 0x1938c); /*???*/ - - write_sa2400(dev, 4, 0x19340 | firdac); - - write_sa2400(dev, 0, sa2400_chan[0]); - write_sa2400(dev, 1, 0xbb50); - write_sa2400(dev, 2, 0x80); - write_sa2400(dev, 3, 0); - write_sa2400(dev, 4, 0x19344 | firdac); /* calibrate filter */ - - /* new from rtl8180 embedded driver (rtl8181 project) */ - write_sa2400(dev, 6, 0x13ff | (1 << 23)); /* MANRX */ - write_sa2400(dev, 8, 0); /* VCO */ - - if (analogphy) { - rtl8180_set_anaparam(priv, anaparam | - (1 << ANAPARAM_TXDACOFF_SHIFT)); - - txconf = rtl818x_ioread32(priv, &priv->map->TX_CONF); - rtl818x_iowrite32(priv, &priv->map->TX_CONF, - txconf | RTL818X_TX_CONF_LOOPBACK_CONT); - - write_sa2400(dev, 4, 0x19341); /* calibrates DC */ - - /* a 5us sleep is required here, - * we rely on the 3ms delay introduced in write_sa2400 */ - write_sa2400(dev, 4, 0x19345); - - /* a 20us sleep is required here, - * we rely on the 3ms delay introduced in write_sa2400 */ - - rtl818x_iowrite32(priv, &priv->map->TX_CONF, txconf); - - rtl8180_set_anaparam(priv, anaparam); - } - /* end new code */ - - write_sa2400(dev, 4, 0x19341 | firdac); /* RTX MODE */ - - /* baseband configuration */ - rtl8180_write_phy(dev, 0, 0x98); - rtl8180_write_phy(dev, 3, 0x38); - rtl8180_write_phy(dev, 4, 0xe0); - rtl8180_write_phy(dev, 5, 0x90); - rtl8180_write_phy(dev, 6, 0x1a); - rtl8180_write_phy(dev, 7, 0x64); - - sa2400_write_phy_antenna(dev, 1); - - rtl8180_write_phy(dev, 0x11, 0x80); - - if (rtl818x_ioread8(priv, &priv->map->CONFIG2) & - RTL818X_CONFIG2_ANTENNA_DIV) - rtl8180_write_phy(dev, 0x12, 0xc7); /* enable ant diversity */ - else - rtl8180_write_phy(dev, 0x12, 0x47); /* disable ant diversity */ - - rtl8180_write_phy(dev, 0x13, 0x90 | priv->csthreshold); - - rtl8180_write_phy(dev, 0x19, 0x0); - rtl8180_write_phy(dev, 0x1a, 0xa0); -} - -const struct rtl818x_rf_ops sa2400_rf_ops = { - .name = "Philips", - .init = sa2400_rf_init, - .stop = sa2400_rf_stop, - .set_chan = sa2400_rf_set_channel, - .calc_rssi = sa2400_rf_calc_rssi, -}; diff --git a/drivers/net/wireless/rtl818x/rtl8180/sa2400.h b/drivers/net/wireless/rtl818x/rtl8180/sa2400.h deleted file mode 100644 index fb0093f35148..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180/sa2400.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef RTL8180_SA2400_H -#define RTL8180_SA2400_H - -/* - * Radio tuning for Philips SA2400 on RTL8180 - * - * Copyright 2007 Andrea Merello - * - * Code from the BSD driver and the rtl8181 project have been - * very useful to understand certain things - * - * I want to thanks the Authors of such projects and the Ndiswrapper - * project Authors. - * - * A special Big Thanks also is for all people who donated me cards, - * making possible the creation of the original rtl8180 driver - * from which this code is derived! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define SA2400_ANTENNA 0x91 -#define SA2400_DIG_ANAPARAM_PWR1_ON 0x8 -#define SA2400_ANA_ANAPARAM_PWR1_ON 0x28 -#define SA2400_ANAPARAM_PWR0_ON 0x3 - -/* RX sensitivity in dbm */ -#define SA2400_MAX_SENS 85 - -#define SA2400_REG4_FIRDAC_SHIFT 7 - -extern const struct rtl818x_rf_ops sa2400_rf_ops; - -#endif /* RTL8180_SA2400_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8187/Makefile b/drivers/net/wireless/rtl818x/rtl8187/Makefile deleted file mode 100644 index 7b6299268ecf..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -rtl8187-objs := dev.o rtl8225.o leds.o rfkill.o - -obj-$(CONFIG_RTL8187) += rtl8187.o - -ccflags-y += -Idrivers/net/wireless/rtl818x diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c deleted file mode 100644 index b7f72f9c7988..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ /dev/null @@ -1,1684 +0,0 @@ -/* - * Linux device driver for RTL8187 - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8187 driver, which is: - * Copyright 2005 Andrea Merello , et al. - * - * The driver was extended to the RTL8187B in 2008 by: - * Herton Ronaldo Krzesinski - * Hin-Tak Leung - * Larry Finger - * - * Magic delays and register offsets below are taken from the original - * r8187 driver sources. Thanks to Realtek for their support! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "rtl8187.h" -#include "rtl8225.h" -#ifdef CONFIG_RTL8187_LEDS -#include "leds.h" -#endif -#include "rfkill.h" - -MODULE_AUTHOR("Michael Wu "); -MODULE_AUTHOR("Andrea Merello "); -MODULE_AUTHOR("Herton Ronaldo Krzesinski "); -MODULE_AUTHOR("Hin-Tak Leung "); -MODULE_AUTHOR("Larry Finger "); -MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); -MODULE_LICENSE("GPL"); - -static struct usb_device_id rtl8187_table[] = { - /* Asus */ - {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, - /* Belkin */ - {USB_DEVICE(0x050d, 0x705e), .driver_info = DEVICE_RTL8187B}, - /* Realtek */ - {USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187}, - {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, - {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, - {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B}, - /* Surecom */ - {USB_DEVICE(0x0769, 0x11F2), .driver_info = DEVICE_RTL8187}, - /* Logitech */ - {USB_DEVICE(0x0789, 0x010C), .driver_info = DEVICE_RTL8187}, - /* Netgear */ - {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, - {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, - {USB_DEVICE(0x0846, 0x4260), .driver_info = DEVICE_RTL8187B}, - /* HP */ - {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, - /* Sitecom */ - {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, - {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, - {USB_DEVICE(0x0df6, 0x0029), .driver_info = DEVICE_RTL8187B}, - /* Sphairon Access Systems GmbH */ - {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187}, - /* Dick Smith Electronics */ - {USB_DEVICE(0x1371, 0x9401), .driver_info = DEVICE_RTL8187}, - /* Abocom */ - {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, - /* Qcom */ - {USB_DEVICE(0x18E8, 0x6232), .driver_info = DEVICE_RTL8187}, - /* AirLive */ - {USB_DEVICE(0x1b75, 0x8187), .driver_info = DEVICE_RTL8187}, - /* Linksys */ - {USB_DEVICE(0x1737, 0x0073), .driver_info = DEVICE_RTL8187B}, - {} -}; - -MODULE_DEVICE_TABLE(usb, rtl8187_table); - -static const struct ieee80211_rate rtl818x_rates[] = { - { .bitrate = 10, .hw_value = 0, }, - { .bitrate = 20, .hw_value = 1, }, - { .bitrate = 55, .hw_value = 2, }, - { .bitrate = 110, .hw_value = 3, }, - { .bitrate = 60, .hw_value = 4, }, - { .bitrate = 90, .hw_value = 5, }, - { .bitrate = 120, .hw_value = 6, }, - { .bitrate = 180, .hw_value = 7, }, - { .bitrate = 240, .hw_value = 8, }, - { .bitrate = 360, .hw_value = 9, }, - { .bitrate = 480, .hw_value = 10, }, - { .bitrate = 540, .hw_value = 11, }, -}; - -static const struct ieee80211_channel rtl818x_channels[] = { - { .center_freq = 2412 }, - { .center_freq = 2417 }, - { .center_freq = 2422 }, - { .center_freq = 2427 }, - { .center_freq = 2432 }, - { .center_freq = 2437 }, - { .center_freq = 2442 }, - { .center_freq = 2447 }, - { .center_freq = 2452 }, - { .center_freq = 2457 }, - { .center_freq = 2462 }, - { .center_freq = 2467 }, - { .center_freq = 2472 }, - { .center_freq = 2484 }, -}; - -static void rtl8187_iowrite_async_cb(struct urb *urb) -{ - kfree(urb->context); -} - -static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr, - void *data, u16 len) -{ - struct usb_ctrlrequest *dr; - struct urb *urb; - struct rtl8187_async_write_data { - u8 data[4]; - struct usb_ctrlrequest dr; - } *buf; - int rc; - - buf = kmalloc(sizeof(*buf), GFP_ATOMIC); - if (!buf) - return; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - kfree(buf); - return; - } - - dr = &buf->dr; - - dr->bRequestType = RTL8187_REQT_WRITE; - dr->bRequest = RTL8187_REQ_SET_REG; - dr->wValue = addr; - dr->wIndex = 0; - dr->wLength = cpu_to_le16(len); - - memcpy(buf, data, len); - - usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0), - (unsigned char *)dr, buf, len, - rtl8187_iowrite_async_cb, buf); - usb_anchor_urb(urb, &priv->anchored); - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc < 0) { - kfree(buf); - usb_unanchor_urb(urb); - } - usb_free_urb(urb); -} - -static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv, - __le32 *addr, u32 val) -{ - __le32 buf = cpu_to_le32(val); - - rtl8187_iowrite_async(priv, cpu_to_le16((unsigned long)addr), - &buf, sizeof(buf)); -} - -void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) -{ - struct rtl8187_priv *priv = dev->priv; - - data <<= 8; - data |= addr | 0x80; - - rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF); - rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF); - rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF); - rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF); -} - -static void rtl8187_tx_cb(struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *)urb->context; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hw *hw = info->rate_driver_data[0]; - struct rtl8187_priv *priv = hw->priv; - - skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : - sizeof(struct rtl8187_tx_hdr)); - ieee80211_tx_info_clear_status(info); - - if (!(urb->status) && !(info->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (priv->is_rtl8187b) { - skb_queue_tail(&priv->b_tx_status.queue, skb); - - /* queue is "full", discard last items */ - while (skb_queue_len(&priv->b_tx_status.queue) > 5) { - struct sk_buff *old_skb; - - dev_dbg(&priv->udev->dev, - "transmit status queue full\n"); - - old_skb = skb_dequeue(&priv->b_tx_status.queue); - ieee80211_tx_status_irqsafe(hw, old_skb); - } - return; - } else { - info->flags |= IEEE80211_TX_STAT_ACK; - } - } - if (priv->is_rtl8187b) - ieee80211_tx_status_irqsafe(hw, skb); - else { - /* Retry information for the RTI8187 is only available by - * reading a register in the device. We are in interrupt mode - * here, thus queue the skb and finish on a work queue. */ - skb_queue_tail(&priv->b_tx_status.queue, skb); - ieee80211_queue_delayed_work(hw, &priv->work, 0); - } -} - -static void rtl8187_tx(struct ieee80211_hw *dev, - struct ieee80211_tx_control *control, - struct sk_buff *skb) -{ - struct rtl8187_priv *priv = dev->priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *tx_hdr = (struct ieee80211_hdr *)(skb->data); - unsigned int ep; - void *buf; - struct urb *urb; - __le16 rts_dur = 0; - u32 flags; - int rc; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - kfree_skb(skb); - return; - } - - flags = skb->len; - flags |= RTL818X_TX_DESC_FLAG_NO_ENC; - - flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24; - if (ieee80211_has_morefrags(tx_hdr->frame_control)) - flags |= RTL818X_TX_DESC_FLAG_MOREFRAG; - - /* HW will perform RTS-CTS when only RTS flags is set. - * HW will perform CTS-to-self when both RTS and CTS flags are set. - * RTS rate and RTS duration will be used also for CTS-to-self. - */ - if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { - flags |= RTL818X_TX_DESC_FLAG_RTS; - flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - rts_dur = ieee80211_rts_duration(dev, priv->vif, - skb->len, info); - } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - flags |= RTL818X_TX_DESC_FLAG_RTS | RTL818X_TX_DESC_FLAG_CTS; - flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - rts_dur = ieee80211_ctstoself_duration(dev, priv->vif, - skb->len, info); - } - - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - priv->seqno += 0x10; - tx_hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - tx_hdr->seq_ctrl |= cpu_to_le16(priv->seqno); - } - - if (!priv->is_rtl8187b) { - struct rtl8187_tx_hdr *hdr = - (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); - hdr->flags = cpu_to_le32(flags); - hdr->len = 0; - hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); - buf = hdr; - - ep = 2; - } else { - /* fc needs to be calculated before skb_push() */ - unsigned int epmap[4] = { 6, 7, 5, 4 }; - u16 fc = le16_to_cpu(tx_hdr->frame_control); - - struct rtl8187b_tx_hdr *hdr = - (struct rtl8187b_tx_hdr *)skb_push(skb, sizeof(*hdr)); - struct ieee80211_rate *txrate = - ieee80211_get_tx_rate(dev, info); - memset(hdr, 0, sizeof(*hdr)); - hdr->flags = cpu_to_le32(flags); - hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); - hdr->tx_duration = - ieee80211_generic_frame_duration(dev, priv->vif, - info->band, - skb->len, txrate); - buf = hdr; - - if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) - ep = 12; - else - ep = epmap[skb_get_queue_mapping(skb)]; - } - - info->rate_driver_data[0] = dev; - info->rate_driver_data[1] = urb; - - usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep), - buf, skb->len, rtl8187_tx_cb, skb); - urb->transfer_flags |= URB_ZERO_PACKET; - usb_anchor_urb(urb, &priv->anchored); - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc < 0) { - usb_unanchor_urb(urb); - kfree_skb(skb); - } - usb_free_urb(urb); -} - -static void rtl8187_rx_cb(struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *)urb->context; - struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb; - struct ieee80211_hw *dev = info->dev; - struct rtl8187_priv *priv = dev->priv; - struct ieee80211_rx_status rx_status = { 0 }; - int rate, signal; - u32 flags; - unsigned long f; - - spin_lock_irqsave(&priv->rx_queue.lock, f); - __skb_unlink(skb, &priv->rx_queue); - spin_unlock_irqrestore(&priv->rx_queue.lock, f); - skb_put(skb, urb->actual_length); - - if (unlikely(urb->status)) { - dev_kfree_skb_irq(skb); - return; - } - - if (!priv->is_rtl8187b) { - struct rtl8187_rx_hdr *hdr = - (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); - flags = le32_to_cpu(hdr->flags); - /* As with the RTL8187B below, the AGC is used to calculate - * signal strength. In this case, the scaling - * constants are derived from the output of p54usb. - */ - signal = -4 - ((27 * hdr->agc) >> 6); - rx_status.antenna = (hdr->signal >> 7) & 1; - rx_status.mactime = le64_to_cpu(hdr->mac_time); - } else { - struct rtl8187b_rx_hdr *hdr = - (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); - /* The Realtek datasheet for the RTL8187B shows that the RX - * header contains the following quantities: signal quality, - * RSSI, AGC, the received power in dB, and the measured SNR. - * In testing, none of these quantities show qualitative - * agreement with AP signal strength, except for the AGC, - * which is inversely proportional to the strength of the - * signal. In the following, the signal strength - * is derived from the AGC. The arbitrary scaling constants - * are chosen to make the results close to the values obtained - * for a BCM4312 using b43 as the driver. The noise is ignored - * for now. - */ - flags = le32_to_cpu(hdr->flags); - signal = 14 - hdr->agc / 2; - rx_status.antenna = (hdr->rssi >> 7) & 1; - rx_status.mactime = le64_to_cpu(hdr->mac_time); - } - - rx_status.signal = signal; - priv->signal = signal; - rate = (flags >> 20) & 0xF; - skb_trim(skb, flags & 0x0FFF); - rx_status.rate_idx = rate; - rx_status.freq = dev->conf.chandef.chan->center_freq; - rx_status.band = dev->conf.chandef.chan->band; - rx_status.flag |= RX_FLAG_MACTIME_START; - if (flags & RTL818X_RX_DESC_FLAG_SPLCP) - rx_status.flag |= RX_FLAG_SHORTPRE; - if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) - rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - ieee80211_rx_irqsafe(dev, skb); - - skb = dev_alloc_skb(RTL8187_MAX_RX); - if (unlikely(!skb)) { - /* TODO check rx queue length and refill *somewhere* */ - return; - } - - info = (struct rtl8187_rx_info *)skb->cb; - info->urb = urb; - info->dev = dev; - urb->transfer_buffer = skb_tail_pointer(skb); - urb->context = skb; - skb_queue_tail(&priv->rx_queue, skb); - - usb_anchor_urb(urb, &priv->anchored); - if (usb_submit_urb(urb, GFP_ATOMIC)) { - usb_unanchor_urb(urb); - skb_unlink(skb, &priv->rx_queue); - dev_kfree_skb_irq(skb); - } -} - -static int rtl8187_init_urbs(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - struct urb *entry = NULL; - struct sk_buff *skb; - struct rtl8187_rx_info *info; - int ret = 0; - - while (skb_queue_len(&priv->rx_queue) < 32) { - skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL); - if (!skb) { - ret = -ENOMEM; - goto err; - } - entry = usb_alloc_urb(0, GFP_KERNEL); - if (!entry) { - ret = -ENOMEM; - goto err; - } - usb_fill_bulk_urb(entry, priv->udev, - usb_rcvbulkpipe(priv->udev, - priv->is_rtl8187b ? 3 : 1), - skb_tail_pointer(skb), - RTL8187_MAX_RX, rtl8187_rx_cb, skb); - info = (struct rtl8187_rx_info *)skb->cb; - info->urb = entry; - info->dev = dev; - skb_queue_tail(&priv->rx_queue, skb); - usb_anchor_urb(entry, &priv->anchored); - ret = usb_submit_urb(entry, GFP_KERNEL); - usb_put_urb(entry); - if (ret) { - skb_unlink(skb, &priv->rx_queue); - usb_unanchor_urb(entry); - goto err; - } - } - return ret; - -err: - kfree_skb(skb); - usb_kill_anchored_urbs(&priv->anchored); - return ret; -} - -static void rtl8187b_status_cb(struct urb *urb) -{ - struct ieee80211_hw *hw = (struct ieee80211_hw *)urb->context; - struct rtl8187_priv *priv = hw->priv; - u64 val; - unsigned int cmd_type; - - if (unlikely(urb->status)) - return; - - /* - * Read from status buffer: - * - * bits [30:31] = cmd type: - * - 0 indicates tx beacon interrupt - * - 1 indicates tx close descriptor - * - * In the case of tx beacon interrupt: - * [0:9] = Last Beacon CW - * [10:29] = reserved - * [30:31] = 00b - * [32:63] = Last Beacon TSF - * - * If it's tx close descriptor: - * [0:7] = Packet Retry Count - * [8:14] = RTS Retry Count - * [15] = TOK - * [16:27] = Sequence No - * [28] = LS - * [29] = FS - * [30:31] = 01b - * [32:47] = unused (reserved?) - * [48:63] = MAC Used Time - */ - val = le64_to_cpu(priv->b_tx_status.buf); - - cmd_type = (val >> 30) & 0x3; - if (cmd_type == 1) { - unsigned int pkt_rc, seq_no; - bool tok; - struct sk_buff *skb; - struct ieee80211_hdr *ieee80211hdr; - unsigned long flags; - - pkt_rc = val & 0xFF; - tok = val & (1 << 15); - seq_no = (val >> 16) & 0xFFF; - - spin_lock_irqsave(&priv->b_tx_status.queue.lock, flags); - skb_queue_reverse_walk(&priv->b_tx_status.queue, skb) { - ieee80211hdr = (struct ieee80211_hdr *)skb->data; - - /* - * While testing, it was discovered that the seq_no - * doesn't actually contains the sequence number. - * Instead of returning just the 12 bits of sequence - * number, hardware is returning entire sequence control - * (fragment number plus sequence number) in a 12 bit - * only field overflowing after some time. As a - * workaround, just consider the lower bits, and expect - * it's unlikely we wrongly ack some sent data - */ - if ((le16_to_cpu(ieee80211hdr->seq_ctrl) - & 0xFFF) == seq_no) - break; - } - if (skb != (struct sk_buff *) &priv->b_tx_status.queue) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - __skb_unlink(skb, &priv->b_tx_status.queue); - if (tok) - info->flags |= IEEE80211_TX_STAT_ACK; - info->status.rates[0].count = pkt_rc + 1; - - ieee80211_tx_status_irqsafe(hw, skb); - } - spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags); - } - - usb_anchor_urb(urb, &priv->anchored); - if (usb_submit_urb(urb, GFP_ATOMIC)) - usb_unanchor_urb(urb); -} - -static int rtl8187b_init_status_urb(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - struct urb *entry; - int ret = 0; - - entry = usb_alloc_urb(0, GFP_KERNEL); - if (!entry) - return -ENOMEM; - - usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9), - &priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf), - rtl8187b_status_cb, dev); - - usb_anchor_urb(entry, &priv->anchored); - ret = usb_submit_urb(entry, GFP_KERNEL); - if (ret) - usb_unanchor_urb(entry); - usb_free_urb(entry); - - return ret; -} - -static void rtl8187_set_anaparam(struct rtl8187_priv *priv, bool rfon) -{ - u32 anaparam, anaparam2; - u8 anaparam3, reg; - - if (!priv->is_rtl8187b) { - if (rfon) { - anaparam = RTL8187_RTL8225_ANAPARAM_ON; - anaparam2 = RTL8187_RTL8225_ANAPARAM2_ON; - } else { - anaparam = RTL8187_RTL8225_ANAPARAM_OFF; - anaparam2 = RTL8187_RTL8225_ANAPARAM2_OFF; - } - } else { - if (rfon) { - anaparam = RTL8187B_RTL8225_ANAPARAM_ON; - anaparam2 = RTL8187B_RTL8225_ANAPARAM2_ON; - anaparam3 = RTL8187B_RTL8225_ANAPARAM3_ON; - } else { - anaparam = RTL8187B_RTL8225_ANAPARAM_OFF; - anaparam2 = RTL8187B_RTL8225_ANAPARAM2_OFF; - anaparam3 = RTL8187B_RTL8225_ANAPARAM3_OFF; - } - } - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg |= RTL818X_CONFIG3_ANAPARAM_WRITE; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, anaparam); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, anaparam2); - if (priv->is_rtl8187b) - rtl818x_iowrite8(priv, &priv->map->ANAPARAM3A, anaparam3); - reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); -} - -static int rtl8187_cmd_reset(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - u8 reg; - int i; - - reg = rtl818x_ioread8(priv, &priv->map->CMD); - reg &= (1 << 1); - reg |= RTL818X_CMD_RESET; - rtl818x_iowrite8(priv, &priv->map->CMD, reg); - - i = 10; - do { - msleep(2); - if (!(rtl818x_ioread8(priv, &priv->map->CMD) & - RTL818X_CMD_RESET)) - break; - } while (--i); - - if (!i) { - wiphy_err(dev->wiphy, "Reset timeout!\n"); - return -ETIMEDOUT; - } - - /* reload registers from eeprom */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD); - - i = 10; - do { - msleep(4); - if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) & - RTL818X_EEPROM_CMD_CONFIG)) - break; - } while (--i); - - if (!i) { - wiphy_err(dev->wiphy, "eeprom reset timeout!\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static int rtl8187_init_hw(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - u8 reg; - int res; - - /* reset */ - rtl8187_set_anaparam(priv, true); - - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); - - msleep(200); - rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10); - rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11); - rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00); - msleep(200); - - res = rtl8187_cmd_reset(dev); - if (res) - return res; - - rtl8187_set_anaparam(priv, true); - - /* setup card */ - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0); - rtl818x_iowrite8(priv, &priv->map->GPIO0, 0); - - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8)); - rtl818x_iowrite8(priv, &priv->map->GPIO0, 1); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - - rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); - reg &= 0x3F; - reg |= 0x80; - rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); - rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); - rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0); - - // TODO: set RESP_RATE and BRSR properly - rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0); - rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); - - /* host_usb_init */ - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0); - rtl818x_iowrite8(priv, &priv->map->GPIO0, 0); - reg = rtl818x_ioread8(priv, (u8 *)0xFE53); - rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7)); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8)); - rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x20); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80); - msleep(100); - - rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008); - rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); - rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7); - msleep(100); - - priv->rf->init(dev); - - rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~1; - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1); - rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10); - rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80); - rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60); - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - - return 0; -} - -static const u8 rtl8187b_reg_table[][3] = { - {0xF0, 0x32, 0}, {0xF1, 0x32, 0}, {0xF2, 0x00, 0}, {0xF3, 0x00, 0}, - {0xF4, 0x32, 0}, {0xF5, 0x43, 0}, {0xF6, 0x00, 0}, {0xF7, 0x00, 0}, - {0xF8, 0x46, 0}, {0xF9, 0xA4, 0}, {0xFA, 0x00, 0}, {0xFB, 0x00, 0}, - {0xFC, 0x96, 0}, {0xFD, 0xA4, 0}, {0xFE, 0x00, 0}, {0xFF, 0x00, 0}, - - {0x58, 0x4B, 1}, {0x59, 0x00, 1}, {0x5A, 0x4B, 1}, {0x5B, 0x00, 1}, - {0x60, 0x4B, 1}, {0x61, 0x09, 1}, {0x62, 0x4B, 1}, {0x63, 0x09, 1}, - {0xCE, 0x0F, 1}, {0xCF, 0x00, 1}, {0xF0, 0x4E, 1}, {0xF1, 0x01, 1}, - {0xF2, 0x02, 1}, {0xF3, 0x03, 1}, {0xF4, 0x04, 1}, {0xF5, 0x05, 1}, - {0xF6, 0x06, 1}, {0xF7, 0x07, 1}, {0xF8, 0x08, 1}, - - {0x4E, 0x00, 2}, {0x0C, 0x04, 2}, {0x21, 0x61, 2}, {0x22, 0x68, 2}, - {0x23, 0x6F, 2}, {0x24, 0x76, 2}, {0x25, 0x7D, 2}, {0x26, 0x84, 2}, - {0x27, 0x8D, 2}, {0x4D, 0x08, 2}, {0x50, 0x05, 2}, {0x51, 0xF5, 2}, - {0x52, 0x04, 2}, {0x53, 0xA0, 2}, {0x54, 0x1F, 2}, {0x55, 0x23, 2}, - {0x56, 0x45, 2}, {0x57, 0x67, 2}, {0x58, 0x08, 2}, {0x59, 0x08, 2}, - {0x5A, 0x08, 2}, {0x5B, 0x08, 2}, {0x60, 0x08, 2}, {0x61, 0x08, 2}, - {0x62, 0x08, 2}, {0x63, 0x08, 2}, {0x64, 0xCF, 2}, - - {0x5B, 0x40, 0}, {0x84, 0x88, 0}, {0x85, 0x24, 0}, {0x88, 0x54, 0}, - {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, - {0x95, 0x12, 0}, {0x96, 0x00, 0}, {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, - {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, - {0xEE, 0x00, 0}, {0x4C, 0x00, 2}, - - {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, {0x8E, 0x08, 0}, - {0x8F, 0x00, 0} -}; - -static int rtl8187b_init_hw(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - int res, i; - u8 reg; - - rtl8187_set_anaparam(priv, true); - - /* Reset PLL sequence on 8187B. Realtek note: reduces power - * consumption about 30 mA */ - rtl818x_iowrite8(priv, (u8 *)0xFF61, 0x10); - reg = rtl818x_ioread8(priv, (u8 *)0xFF62); - rtl818x_iowrite8(priv, (u8 *)0xFF62, reg & ~(1 << 5)); - rtl818x_iowrite8(priv, (u8 *)0xFF62, reg | (1 << 5)); - - res = rtl8187_cmd_reset(dev); - if (res) - return res; - - rtl8187_set_anaparam(priv, true); - - /* BRSR (Basic Rate Set Register) on 8187B looks to be the same as - * RESP_RATE on 8187L in Realtek sources: each bit should be each - * one of the 12 rates, all are enabled */ - rtl818x_iowrite16(priv, (__le16 *)0xFF34, 0x0FFF); - - reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); - reg |= RTL818X_CW_CONF_PERPACKET_RETRY; - rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); - - /* Auto Rate Fallback Register (ARFR): 1M-54M setting */ - rtl818x_iowrite16_idx(priv, (__le16 *)0xFFE0, 0x0FFF, 1); - rtl818x_iowrite8_idx(priv, (u8 *)0xFFE2, 0x00, 1); - - rtl818x_iowrite16_idx(priv, (__le16 *)0xFFD4, 0xFFFF, 1); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); - rtl818x_iowrite8(priv, &priv->map->CONFIG1, (reg & 0x3F) | 0x80); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); - - rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); - for (i = 0; i < ARRAY_SIZE(rtl8187b_reg_table); i++) { - rtl818x_iowrite8_idx(priv, - (u8 *)(uintptr_t) - (rtl8187b_reg_table[i][0] | 0xFF00), - rtl8187b_reg_table[i][1], - rtl8187b_reg_table[i][2]); - } - - rtl818x_iowrite16(priv, &priv->map->TID_AC_MAP, 0xFA50); - rtl818x_iowrite16(priv, &priv->map->INT_MIG, 0); - - rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF0, 0, 1); - rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF4, 0, 1); - rtl818x_iowrite8_idx(priv, (u8 *)0xFFF8, 0, 1); - - rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00004001); - - /* RFSW_CTRL register */ - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x569A, 2); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - msleep(100); - - priv->rf->init(dev); - - reg = RTL818X_CMD_TX_ENABLE | RTL818X_CMD_RX_ENABLE; - rtl818x_iowrite8(priv, &priv->map->CMD, reg); - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); - - rtl818x_iowrite8(priv, (u8 *)0xFE41, 0xF4); - rtl818x_iowrite8(priv, (u8 *)0xFE40, 0x00); - rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x00); - rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x01); - rtl818x_iowrite8(priv, (u8 *)0xFE40, 0x0F); - rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x00); - rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x01); - - reg = rtl818x_ioread8(priv, (u8 *)0xFFDB); - rtl818x_iowrite8(priv, (u8 *)0xFFDB, reg | (1 << 2)); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x59FA, 3); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF74, 0x59D2, 3); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF76, 0x59D2, 3); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF78, 0x19FA, 3); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF7A, 0x19FA, 3); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF7C, 0x00D0, 3); - rtl818x_iowrite8(priv, (u8 *)0xFF61, 0); - rtl818x_iowrite8_idx(priv, (u8 *)0xFF80, 0x0F, 1); - rtl818x_iowrite8_idx(priv, (u8 *)0xFF83, 0x03, 1); - rtl818x_iowrite8(priv, (u8 *)0xFFDA, 0x10); - rtl818x_iowrite8_idx(priv, (u8 *)0xFF4D, 0x08, 2); - - rtl818x_iowrite32(priv, &priv->map->HSSI_PARA, 0x0600321B); - - rtl818x_iowrite16_idx(priv, (__le16 *)0xFFEC, 0x0800, 1); - - priv->slot_time = 0x9; - priv->aifsn[0] = 2; /* AIFSN[AC_VO] */ - priv->aifsn[1] = 2; /* AIFSN[AC_VI] */ - priv->aifsn[2] = 7; /* AIFSN[AC_BK] */ - priv->aifsn[3] = 3; /* AIFSN[AC_BE] */ - rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0); - - /* ENEDCA flag must always be set, transmit issues? */ - rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_ENEDCA); - - return 0; -} - -static void rtl8187_work(struct work_struct *work) -{ - /* The RTL8187 returns the retry count through register 0xFFFA. In - * addition, it appears to be a cumulative retry count, not the - * value for the current TX packet. When multiple TX entries are - * waiting in the queue, the retry count will be the total for all. - * The "error" may matter for purposes of rate setting, but there is - * no other choice with this hardware. - */ - struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, - work.work); - struct ieee80211_tx_info *info; - struct ieee80211_hw *dev = priv->dev; - static u16 retry; - u16 tmp; - u16 avg_retry; - int length; - - mutex_lock(&priv->conf_mutex); - tmp = rtl818x_ioread16(priv, (__le16 *)0xFFFA); - length = skb_queue_len(&priv->b_tx_status.queue); - if (unlikely(!length)) - length = 1; - if (unlikely(tmp < retry)) - tmp = retry; - avg_retry = (tmp - retry) / length; - while (skb_queue_len(&priv->b_tx_status.queue) > 0) { - struct sk_buff *old_skb; - - old_skb = skb_dequeue(&priv->b_tx_status.queue); - info = IEEE80211_SKB_CB(old_skb); - info->status.rates[0].count = avg_retry + 1; - if (info->status.rates[0].count > RETRY_COUNT) - info->flags &= ~IEEE80211_TX_STAT_ACK; - ieee80211_tx_status_irqsafe(dev, old_skb); - } - retry = tmp; - mutex_unlock(&priv->conf_mutex); -} - -static int rtl8187_start(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - u32 reg; - int ret; - - mutex_lock(&priv->conf_mutex); - - ret = (!priv->is_rtl8187b) ? rtl8187_init_hw(dev) : - rtl8187b_init_hw(dev); - if (ret) - goto rtl8187_start_exit; - - init_usb_anchor(&priv->anchored); - priv->dev = dev; - - if (priv->is_rtl8187b) { - reg = RTL818X_RX_CONF_MGMT | - RTL818X_RX_CONF_DATA | - RTL818X_RX_CONF_BROADCAST | - RTL818X_RX_CONF_NICMAC | - RTL818X_RX_CONF_BSSID | - (7 << 13 /* RX FIFO threshold NONE */) | - (7 << 10 /* MAX RX DMA */) | - RTL818X_RX_CONF_RX_AUTORESETPHY | - RTL818X_RX_CONF_ONLYERLPKT | - RTL818X_RX_CONF_MULTICAST; - priv->rx_conf = reg; - rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); - - reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); - reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN; - reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL; - reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT; - rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); - - rtl818x_iowrite32(priv, &priv->map->TX_CONF, - RTL818X_TX_CONF_HW_SEQNUM | - RTL818X_TX_CONF_DISREQQSIZE | - (RETRY_COUNT << 8 /* short retry limit */) | - (RETRY_COUNT << 0 /* long retry limit */) | - (7 << 21 /* MAX TX DMA */)); - ret = rtl8187_init_urbs(dev); - if (ret) - goto rtl8187_start_exit; - ret = rtl8187b_init_status_urb(dev); - if (ret) - usb_kill_anchored_urbs(&priv->anchored); - goto rtl8187_start_exit; - } - - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); - - rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); - rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); - - ret = rtl8187_init_urbs(dev); - if (ret) - goto rtl8187_start_exit; - - reg = RTL818X_RX_CONF_ONLYERLPKT | - RTL818X_RX_CONF_RX_AUTORESETPHY | - RTL818X_RX_CONF_BSSID | - RTL818X_RX_CONF_MGMT | - RTL818X_RX_CONF_DATA | - (7 << 13 /* RX FIFO threshold NONE */) | - (7 << 10 /* MAX RX DMA */) | - RTL818X_RX_CONF_BROADCAST | - RTL818X_RX_CONF_NICMAC; - - priv->rx_conf = reg; - rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); - - reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); - reg &= ~RTL818X_CW_CONF_PERPACKET_CW; - reg |= RTL818X_CW_CONF_PERPACKET_RETRY; - rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); - - reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); - reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN; - reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL; - reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT; - rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); - - reg = RTL818X_TX_CONF_CW_MIN | - (7 << 21 /* MAX TX DMA */) | - RTL818X_TX_CONF_NO_ICV; - rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); - - reg = rtl818x_ioread8(priv, &priv->map->CMD); - reg |= RTL818X_CMD_TX_ENABLE; - reg |= RTL818X_CMD_RX_ENABLE; - rtl818x_iowrite8(priv, &priv->map->CMD, reg); - INIT_DELAYED_WORK(&priv->work, rtl8187_work); - -rtl8187_start_exit: - mutex_unlock(&priv->conf_mutex); - return ret; -} - -static void rtl8187_stop(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - struct sk_buff *skb; - u32 reg; - - mutex_lock(&priv->conf_mutex); - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); - - reg = rtl818x_ioread8(priv, &priv->map->CMD); - reg &= ~RTL818X_CMD_TX_ENABLE; - reg &= ~RTL818X_CMD_RX_ENABLE; - rtl818x_iowrite8(priv, &priv->map->CMD, reg); - - priv->rf->stop(dev); - rtl8187_set_anaparam(priv, false); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG4); - rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - while ((skb = skb_dequeue(&priv->b_tx_status.queue))) - dev_kfree_skb_any(skb); - - usb_kill_anchored_urbs(&priv->anchored); - mutex_unlock(&priv->conf_mutex); - - if (!priv->is_rtl8187b) - cancel_delayed_work_sync(&priv->work); -} - -static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif) -{ - struct rtl8187_priv *priv = dev->priv; - - return rtl818x_ioread32(priv, &priv->map->TSFT[0]) | - (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32; -} - - -static void rtl8187_beacon_work(struct work_struct *work) -{ - struct rtl8187_vif *vif_priv = - container_of(work, struct rtl8187_vif, beacon_work.work); - struct ieee80211_vif *vif = - container_of((void *)vif_priv, struct ieee80211_vif, drv_priv); - struct ieee80211_hw *dev = vif_priv->dev; - struct ieee80211_mgmt *mgmt; - struct sk_buff *skb; - - /* don't overflow the tx ring */ - if (ieee80211_queue_stopped(dev, 0)) - goto resched; - - /* grab a fresh beacon */ - skb = ieee80211_beacon_get(dev, vif); - if (!skb) - goto resched; - - /* - * update beacon timestamp w/ TSF value - * TODO: make hardware update beacon timestamp - */ - mgmt = (struct ieee80211_mgmt *)skb->data; - mgmt->u.beacon.timestamp = cpu_to_le64(rtl8187_get_tsf(dev, vif)); - - /* TODO: use actual beacon queue */ - skb_set_queue_mapping(skb, 0); - - rtl8187_tx(dev, NULL, skb); - -resched: - /* - * schedule next beacon - * TODO: use hardware support for beacon timing - */ - schedule_delayed_work(&vif_priv->beacon_work, - usecs_to_jiffies(1024 * vif->bss_conf.beacon_int)); -} - - -static int rtl8187_add_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif) -{ - struct rtl8187_priv *priv = dev->priv; - struct rtl8187_vif *vif_priv; - int i; - int ret = -EOPNOTSUPP; - - mutex_lock(&priv->conf_mutex); - if (priv->vif) - goto exit; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - break; - default: - goto exit; - } - - ret = 0; - priv->vif = vif; - - /* Initialize driver private area */ - vif_priv = (struct rtl8187_vif *)&vif->drv_priv; - vif_priv->dev = dev; - INIT_DELAYED_WORK(&vif_priv->beacon_work, rtl8187_beacon_work); - vif_priv->enable_beacon = false; - - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - for (i = 0; i < ETH_ALEN; i++) - rtl818x_iowrite8(priv, &priv->map->MAC[i], - ((u8 *)vif->addr)[i]); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - -exit: - mutex_unlock(&priv->conf_mutex); - return ret; -} - -static void rtl8187_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif) -{ - struct rtl8187_priv *priv = dev->priv; - mutex_lock(&priv->conf_mutex); - priv->vif = NULL; - mutex_unlock(&priv->conf_mutex); -} - -static int rtl8187_config(struct ieee80211_hw *dev, u32 changed) -{ - struct rtl8187_priv *priv = dev->priv; - struct ieee80211_conf *conf = &dev->conf; - u32 reg; - - mutex_lock(&priv->conf_mutex); - reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); - /* Enable TX loopback on MAC level to avoid TX during channel - * changes, as this has be seen to causes problems and the - * card will stop work until next reset - */ - rtl818x_iowrite32(priv, &priv->map->TX_CONF, - reg | RTL818X_TX_CONF_LOOPBACK_MAC); - priv->rf->set_chan(dev, conf); - msleep(10); - rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); - - rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); - rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100); - rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); - rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100); - mutex_unlock(&priv->conf_mutex); - return 0; -} - -/* - * With 8187B, AC_*_PARAM clashes with FEMR definition in struct rtl818x_csr for - * example. Thus we have to use raw values for AC_*_PARAM register addresses. - */ -static __le32 *rtl8187b_ac_addr[4] = { - (__le32 *) 0xFFF0, /* AC_VO */ - (__le32 *) 0xFFF4, /* AC_VI */ - (__le32 *) 0xFFFC, /* AC_BK */ - (__le32 *) 0xFFF8, /* AC_BE */ -}; - -#define SIFS_TIME 0xa - -static void rtl8187_conf_erp(struct rtl8187_priv *priv, bool use_short_slot, - bool use_short_preamble) -{ - if (priv->is_rtl8187b) { - u8 difs, eifs; - u16 ack_timeout; - int queue; - - if (use_short_slot) { - priv->slot_time = 0x9; - difs = 0x1c; - eifs = 0x53; - } else { - priv->slot_time = 0x14; - difs = 0x32; - eifs = 0x5b; - } - rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); - rtl818x_iowrite8(priv, &priv->map->SLOT, priv->slot_time); - rtl818x_iowrite8(priv, &priv->map->DIFS, difs); - - /* - * BRSR+1 on 8187B is in fact EIFS register - * Value in units of 4 us - */ - rtl818x_iowrite8(priv, (u8 *)&priv->map->BRSR + 1, eifs); - - /* - * For 8187B, CARRIER_SENSE_COUNTER is in fact ack timeout - * register. In units of 4 us like eifs register - * ack_timeout = ack duration + plcp + difs + preamble - */ - ack_timeout = 112 + 48 + difs; - if (use_short_preamble) - ack_timeout += 72; - else - ack_timeout += 144; - rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, - DIV_ROUND_UP(ack_timeout, 4)); - - for (queue = 0; queue < 4; queue++) - rtl818x_iowrite8(priv, (u8 *) rtl8187b_ac_addr[queue], - priv->aifsn[queue] * priv->slot_time + - SIFS_TIME); - } else { - rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); - if (use_short_slot) { - rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); - rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); - rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); - } else { - rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); - rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); - rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); - } - } -} - -static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) -{ - struct rtl8187_priv *priv = dev->priv; - struct rtl8187_vif *vif_priv; - int i; - u8 reg; - - vif_priv = (struct rtl8187_vif *)&vif->drv_priv; - - if (changed & BSS_CHANGED_BSSID) { - mutex_lock(&priv->conf_mutex); - for (i = 0; i < ETH_ALEN; i++) - rtl818x_iowrite8(priv, &priv->map->BSSID[i], - info->bssid[i]); - - if (priv->is_rtl8187b) - reg = RTL818X_MSR_ENEDCA; - else - reg = 0; - - if (is_valid_ether_addr(info->bssid)) { - if (vif->type == NL80211_IFTYPE_ADHOC) - reg |= RTL818X_MSR_ADHOC; - else - reg |= RTL818X_MSR_INFRA; - } - else - reg |= RTL818X_MSR_NO_LINK; - - rtl818x_iowrite8(priv, &priv->map->MSR, reg); - - mutex_unlock(&priv->conf_mutex); - } - - if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE)) - rtl8187_conf_erp(priv, info->use_short_slot, - info->use_short_preamble); - - if (changed & BSS_CHANGED_BEACON_ENABLED) - vif_priv->enable_beacon = info->enable_beacon; - - if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON)) { - cancel_delayed_work_sync(&vif_priv->beacon_work); - if (vif_priv->enable_beacon) - schedule_work(&vif_priv->beacon_work.work); - } - -} - -static u64 rtl8187_prepare_multicast(struct ieee80211_hw *dev, - struct netdev_hw_addr_list *mc_list) -{ - return netdev_hw_addr_list_count(mc_list); -} - -static void rtl8187_configure_filter(struct ieee80211_hw *dev, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct rtl8187_priv *priv = dev->priv; - - if (changed_flags & FIF_FCSFAIL) - priv->rx_conf ^= RTL818X_RX_CONF_FCS; - if (changed_flags & FIF_CONTROL) - priv->rx_conf ^= RTL818X_RX_CONF_CTRL; - if (changed_flags & FIF_OTHER_BSS) - priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; - if (*total_flags & FIF_ALLMULTI || multicast > 0) - priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; - else - priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; - - *total_flags = 0; - - if (priv->rx_conf & RTL818X_RX_CONF_FCS) - *total_flags |= FIF_FCSFAIL; - if (priv->rx_conf & RTL818X_RX_CONF_CTRL) - *total_flags |= FIF_CONTROL; - if (priv->rx_conf & RTL818X_RX_CONF_MONITOR) - *total_flags |= FIF_OTHER_BSS; - if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) - *total_flags |= FIF_ALLMULTI; - - rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf); -} - -static int rtl8187_conf_tx(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct rtl8187_priv *priv = dev->priv; - u8 cw_min, cw_max; - - if (queue > 3) - return -EINVAL; - - cw_min = fls(params->cw_min); - cw_max = fls(params->cw_max); - - if (priv->is_rtl8187b) { - priv->aifsn[queue] = params->aifs; - - /* - * This is the structure of AC_*_PARAM registers in 8187B: - * - TXOP limit field, bit offset = 16 - * - ECWmax, bit offset = 12 - * - ECWmin, bit offset = 8 - * - AIFS, bit offset = 0 - */ - rtl818x_iowrite32(priv, rtl8187b_ac_addr[queue], - (params->txop << 16) | (cw_max << 12) | - (cw_min << 8) | (params->aifs * - priv->slot_time + SIFS_TIME)); - } else { - if (queue != 0) - return -EINVAL; - - rtl818x_iowrite8(priv, &priv->map->CW_VAL, - cw_min | (cw_max << 4)); - } - return 0; -} - - -static const struct ieee80211_ops rtl8187_ops = { - .tx = rtl8187_tx, - .start = rtl8187_start, - .stop = rtl8187_stop, - .add_interface = rtl8187_add_interface, - .remove_interface = rtl8187_remove_interface, - .config = rtl8187_config, - .bss_info_changed = rtl8187_bss_info_changed, - .prepare_multicast = rtl8187_prepare_multicast, - .configure_filter = rtl8187_configure_filter, - .conf_tx = rtl8187_conf_tx, - .rfkill_poll = rtl8187_rfkill_poll, - .get_tsf = rtl8187_get_tsf, -}; - -static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) -{ - struct ieee80211_hw *dev = eeprom->data; - struct rtl8187_priv *priv = dev->priv; - u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - - eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE; - eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ; - eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK; - eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS; -} - -static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom) -{ - struct ieee80211_hw *dev = eeprom->data; - struct rtl8187_priv *priv = dev->priv; - u8 reg = RTL818X_EEPROM_CMD_PROGRAM; - - if (eeprom->reg_data_in) - reg |= RTL818X_EEPROM_CMD_WRITE; - if (eeprom->reg_data_out) - reg |= RTL818X_EEPROM_CMD_READ; - if (eeprom->reg_data_clock) - reg |= RTL818X_EEPROM_CMD_CK; - if (eeprom->reg_chip_select) - reg |= RTL818X_EEPROM_CMD_CS; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg); - udelay(10); -} - -static int rtl8187_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct ieee80211_hw *dev; - struct rtl8187_priv *priv; - struct eeprom_93cx6 eeprom; - struct ieee80211_channel *channel; - const char *chip_name; - u16 txpwr, reg; - u16 product_id = le16_to_cpu(udev->descriptor.idProduct); - int err, i; - u8 mac_addr[ETH_ALEN]; - - dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops); - if (!dev) { - printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n"); - return -ENOMEM; - } - - priv = dev->priv; - priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B); - - /* allocate "DMA aware" buffer for register accesses */ - priv->io_dmabuf = kmalloc(sizeof(*priv->io_dmabuf), GFP_KERNEL); - if (!priv->io_dmabuf) { - err = -ENOMEM; - goto err_free_dev; - } - mutex_init(&priv->io_mutex); - - SET_IEEE80211_DEV(dev, &intf->dev); - usb_set_intfdata(intf, dev); - priv->udev = udev; - - usb_get_dev(udev); - - skb_queue_head_init(&priv->rx_queue); - - BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels)); - BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates)); - - memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); - memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); - priv->map = (struct rtl818x_csr *)0xFF00; - - priv->band.band = IEEE80211_BAND_2GHZ; - priv->band.channels = priv->channels; - priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); - priv->band.bitrates = priv->rates; - priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); - dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; - - - ieee80211_hw_set(dev, RX_INCLUDES_FCS); - ieee80211_hw_set(dev, HOST_BROADCAST_PS_BUFFERING); - ieee80211_hw_set(dev, SIGNAL_DBM); - /* Initialize rate-control variables */ - dev->max_rates = 1; - dev->max_rate_tries = RETRY_COUNT; - - eeprom.data = dev; - eeprom.register_read = rtl8187_eeprom_register_read; - eeprom.register_write = rtl8187_eeprom_register_write; - if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6)) - eeprom.width = PCI_EEPROM_WIDTH_93C66; - else - eeprom.width = PCI_EEPROM_WIDTH_93C46; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - udelay(10); - - eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR, - (__le16 __force *)mac_addr, 3); - if (!is_valid_ether_addr(mac_addr)) { - printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly " - "generated MAC address\n"); - eth_random_addr(mac_addr); - } - SET_IEEE80211_PERM_ADDR(dev, mac_addr); - - channel = priv->channels; - for (i = 0; i < 3; i++) { - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i, - &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - (*channel++).hw_value = txpwr >> 8; - } - for (i = 0; i < 2; i++) { - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i, - &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - (*channel++).hw_value = txpwr >> 8; - } - - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE, - &priv->txpwr_base); - - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~1; - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1); - /* 0 means asic B-cut, we should use SW 3 wire - * bit-by-bit banging for radio. 1 means we can use - * USB specific request to write radio registers */ - priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3; - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - if (!priv->is_rtl8187b) { - u32 reg32; - reg32 = rtl818x_ioread32(priv, &priv->map->TX_CONF); - reg32 &= RTL818X_TX_CONF_HWVER_MASK; - switch (reg32) { - case RTL818X_TX_CONF_R8187vD_B: - /* Some RTL8187B devices have a USB ID of 0x8187 - * detect them here */ - chip_name = "RTL8187BvB(early)"; - priv->is_rtl8187b = 1; - priv->hw_rev = RTL8187BvB; - break; - case RTL818X_TX_CONF_R8187vD: - chip_name = "RTL8187vD"; - break; - default: - chip_name = "RTL8187vB (default)"; - } - } else { - /* - * Force USB request to write radio registers for 8187B, Realtek - * only uses it in their sources - */ - /*if (priv->asic_rev == 0) { - printk(KERN_WARNING "rtl8187: Forcing use of USB " - "requests to write to radio registers\n"); - priv->asic_rev = 1; - }*/ - switch (rtl818x_ioread8(priv, (u8 *)0xFFE1)) { - case RTL818X_R8187B_B: - chip_name = "RTL8187BvB"; - priv->hw_rev = RTL8187BvB; - break; - case RTL818X_R8187B_D: - chip_name = "RTL8187BvD"; - priv->hw_rev = RTL8187BvD; - break; - case RTL818X_R8187B_E: - chip_name = "RTL8187BvE"; - priv->hw_rev = RTL8187BvE; - break; - default: - chip_name = "RTL8187BvB (default)"; - priv->hw_rev = RTL8187BvB; - } - } - - if (!priv->is_rtl8187b) { - for (i = 0; i < 2; i++) { - eeprom_93cx6_read(&eeprom, - RTL8187_EEPROM_TXPWR_CHAN_6 + i, - &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - (*channel++).hw_value = txpwr >> 8; - } - } else { - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6, - &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - - eeprom_93cx6_read(&eeprom, 0x0A, &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - - eeprom_93cx6_read(&eeprom, 0x1C, &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - (*channel++).hw_value = txpwr >> 8; - } - /* Handle the differing rfkill GPIO bit in different models */ - priv->rfkill_mask = RFKILL_MASK_8187_89_97; - if (product_id == 0x8197 || product_id == 0x8198) { - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_SELECT_GPIO, ®); - if (reg & 0xFF00) - priv->rfkill_mask = RFKILL_MASK_8198; - } - dev->vif_data_size = sizeof(struct rtl8187_vif); - dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) ; - - if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) - printk(KERN_INFO "rtl8187: inconsistency between id with OEM" - " info!\n"); - - priv->rf = rtl8187_detect_rf(dev); - dev->extra_tx_headroom = (!priv->is_rtl8187b) ? - sizeof(struct rtl8187_tx_hdr) : - sizeof(struct rtl8187b_tx_hdr); - if (!priv->is_rtl8187b) - dev->queues = 1; - else - dev->queues = 4; - - err = ieee80211_register_hw(dev); - if (err) { - printk(KERN_ERR "rtl8187: Cannot register device\n"); - goto err_free_dmabuf; - } - mutex_init(&priv->conf_mutex); - skb_queue_head_init(&priv->b_tx_status.queue); - - wiphy_info(dev->wiphy, "hwaddr %pM, %s V%d + %s, rfkill mask %d\n", - mac_addr, chip_name, priv->asic_rev, priv->rf->name, - priv->rfkill_mask); - -#ifdef CONFIG_RTL8187_LEDS - eeprom_93cx6_read(&eeprom, 0x3F, ®); - reg &= 0xFF; - rtl8187_leds_init(dev, reg); -#endif - rtl8187_rfkill_init(dev); - - return 0; - - err_free_dmabuf: - kfree(priv->io_dmabuf); - usb_set_intfdata(intf, NULL); - usb_put_dev(udev); - err_free_dev: - ieee80211_free_hw(dev); - return err; -} - -static void rtl8187_disconnect(struct usb_interface *intf) -{ - struct ieee80211_hw *dev = usb_get_intfdata(intf); - struct rtl8187_priv *priv; - - if (!dev) - return; - -#ifdef CONFIG_RTL8187_LEDS - rtl8187_leds_exit(dev); -#endif - rtl8187_rfkill_exit(dev); - ieee80211_unregister_hw(dev); - - priv = dev->priv; - usb_reset_device(priv->udev); - usb_put_dev(interface_to_usbdev(intf)); - kfree(priv->io_dmabuf); - ieee80211_free_hw(dev); -} - -static struct usb_driver rtl8187_driver = { - .name = KBUILD_MODNAME, - .id_table = rtl8187_table, - .probe = rtl8187_probe, - .disconnect = rtl8187_disconnect, - .disable_hub_initiated_lpm = 1, -}; - -module_usb_driver(rtl8187_driver); diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/rtl818x/rtl8187/leds.c deleted file mode 100644 index c2d5b495c179..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187/leds.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Linux LED driver for RTL8187 - * - * Copyright 2009 Larry Finger - * - * Based on the LED handling in the r8187 driver, which is: - * Copyright (c) Realtek Semiconductor Corp. All rights reserved. - * - * Thanks to Realtek for their support! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifdef CONFIG_RTL8187_LEDS - -#include -#include -#include - -#include "rtl8187.h" -#include "leds.h" - -static void led_turn_on(struct work_struct *work) -{ - /* As this routine does read/write operations on the hardware, it must - * be run from a work queue. - */ - u8 reg; - struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, - led_on.work); - struct rtl8187_led *led = &priv->led_tx; - - /* Don't change the LED, when the device is down. */ - if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) - return ; - - /* Skip if the LED is not registered. */ - if (!led->dev) - return; - mutex_lock(&priv->conf_mutex); - switch (led->ledpin) { - case LED_PIN_GPIO0: - rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x00); - break; - case LED_PIN_LED0: - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 4); - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - break; - case LED_PIN_LED1: - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 5); - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - break; - case LED_PIN_HW: - default: - break; - } - mutex_unlock(&priv->conf_mutex); -} - -static void led_turn_off(struct work_struct *work) -{ - /* As this routine does read/write operations on the hardware, it must - * be run from a work queue. - */ - u8 reg; - struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, - led_off.work); - struct rtl8187_led *led = &priv->led_tx; - - /* Don't change the LED, when the device is down. */ - if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) - return ; - - /* Skip if the LED is not registered. */ - if (!led->dev) - return; - mutex_lock(&priv->conf_mutex); - switch (led->ledpin) { - case LED_PIN_GPIO0: - rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x01); - break; - case LED_PIN_LED0: - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 4); - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - break; - case LED_PIN_LED1: - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 5); - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - break; - case LED_PIN_HW: - default: - break; - } - mutex_unlock(&priv->conf_mutex); -} - -/* Callback from the LED subsystem. */ -static void rtl8187_led_brightness_set(struct led_classdev *led_dev, - enum led_brightness brightness) -{ - struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led, - led_dev); - struct ieee80211_hw *hw = led->dev; - struct rtl8187_priv *priv; - static bool radio_on; - - if (!hw) - return; - priv = hw->priv; - if (led->is_radio) { - if (brightness == LED_FULL) { - ieee80211_queue_delayed_work(hw, &priv->led_on, 0); - radio_on = true; - } else if (radio_on) { - radio_on = false; - cancel_delayed_work(&priv->led_on); - ieee80211_queue_delayed_work(hw, &priv->led_off, 0); - } - } else if (radio_on) { - if (brightness == LED_OFF) { - ieee80211_queue_delayed_work(hw, &priv->led_off, 0); - /* The LED is off for 1/20 sec - it just blinks. */ - ieee80211_queue_delayed_work(hw, &priv->led_on, - HZ / 20); - } else - ieee80211_queue_delayed_work(hw, &priv->led_on, 0); - } -} - -static int rtl8187_register_led(struct ieee80211_hw *dev, - struct rtl8187_led *led, const char *name, - const char *default_trigger, u8 ledpin, - bool is_radio) -{ - int err; - struct rtl8187_priv *priv = dev->priv; - - if (led->dev) - return -EEXIST; - if (!default_trigger) - return -EINVAL; - led->dev = dev; - led->ledpin = ledpin; - led->is_radio = is_radio; - strncpy(led->name, name, sizeof(led->name)); - - led->led_dev.name = led->name; - led->led_dev.default_trigger = default_trigger; - led->led_dev.brightness_set = rtl8187_led_brightness_set; - - err = led_classdev_register(&priv->udev->dev, &led->led_dev); - if (err) { - printk(KERN_INFO "LEDs: Failed to register %s\n", name); - led->dev = NULL; - return err; - } - return 0; -} - -static void rtl8187_unregister_led(struct rtl8187_led *led) -{ - struct ieee80211_hw *hw = led->dev; - struct rtl8187_priv *priv = hw->priv; - - led_classdev_unregister(&led->led_dev); - flush_delayed_work(&priv->led_off); - led->dev = NULL; -} - -void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid) -{ - struct rtl8187_priv *priv = dev->priv; - char name[RTL8187_LED_MAX_NAME_LEN + 1]; - u8 ledpin; - int err; - - /* According to the vendor driver, the LED operation depends on the - * customer ID encoded in the EEPROM - */ - printk(KERN_INFO "rtl8187: Customer ID is 0x%02X\n", custid); - switch (custid) { - case EEPROM_CID_RSVD0: - case EEPROM_CID_RSVD1: - case EEPROM_CID_SERCOMM_PS: - case EEPROM_CID_QMI: - case EEPROM_CID_DELL: - case EEPROM_CID_TOSHIBA: - ledpin = LED_PIN_GPIO0; - break; - case EEPROM_CID_ALPHA0: - ledpin = LED_PIN_LED0; - break; - case EEPROM_CID_HW: - ledpin = LED_PIN_HW; - break; - default: - ledpin = LED_PIN_GPIO0; - } - - INIT_DELAYED_WORK(&priv->led_on, led_turn_on); - INIT_DELAYED_WORK(&priv->led_off, led_turn_off); - - snprintf(name, sizeof(name), - "rtl8187-%s::radio", wiphy_name(dev->wiphy)); - err = rtl8187_register_led(dev, &priv->led_radio, name, - ieee80211_get_radio_led_name(dev), ledpin, true); - if (err) - return; - - snprintf(name, sizeof(name), - "rtl8187-%s::tx", wiphy_name(dev->wiphy)); - err = rtl8187_register_led(dev, &priv->led_tx, name, - ieee80211_get_tx_led_name(dev), ledpin, false); - if (err) - goto err_tx; - - snprintf(name, sizeof(name), - "rtl8187-%s::rx", wiphy_name(dev->wiphy)); - err = rtl8187_register_led(dev, &priv->led_rx, name, - ieee80211_get_rx_led_name(dev), ledpin, false); - if (!err) - return; - - /* registration of RX LED failed - unregister */ - rtl8187_unregister_led(&priv->led_tx); -err_tx: - rtl8187_unregister_led(&priv->led_radio); -} - -void rtl8187_leds_exit(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - - rtl8187_unregister_led(&priv->led_radio); - rtl8187_unregister_led(&priv->led_rx); - rtl8187_unregister_led(&priv->led_tx); - cancel_delayed_work_sync(&priv->led_off); - cancel_delayed_work_sync(&priv->led_on); -} -#endif /* def CONFIG_RTL8187_LEDS */ - diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.h b/drivers/net/wireless/rtl818x/rtl8187/leds.h deleted file mode 100644 index d743c96d4a20..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187/leds.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Definitions for RTL8187 leds - * - * Copyright 2009 Larry Finger - * - * Based on the LED handling in the r8187 driver, which is: - * Copyright (c) Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef RTL8187_LED_H -#define RTL8187_LED_H - -#ifdef CONFIG_RTL8187_LEDS - -#define RTL8187_LED_MAX_NAME_LEN 21 - -#include -#include - -enum { - LED_PIN_LED0, - LED_PIN_LED1, - LED_PIN_GPIO0, - LED_PIN_HW -}; - -enum { - EEPROM_CID_RSVD0 = 0x00, - EEPROM_CID_RSVD1 = 0xFF, - EEPROM_CID_ALPHA0 = 0x01, - EEPROM_CID_SERCOMM_PS = 0x02, - EEPROM_CID_HW = 0x03, - EEPROM_CID_TOSHIBA = 0x04, - EEPROM_CID_QMI = 0x07, - EEPROM_CID_DELL = 0x08 -}; - -struct rtl8187_led { - struct ieee80211_hw *dev; - /* The LED class device */ - struct led_classdev led_dev; - /* The pin/method used to control the led */ - u8 ledpin; - /* The unique name string for this LED device. */ - char name[RTL8187_LED_MAX_NAME_LEN + 1]; - /* If the LED is radio or tx/rx */ - bool is_radio; -}; - -void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); -void rtl8187_leds_exit(struct ieee80211_hw *dev); - -#endif /* def CONFIG_RTL8187_LEDS */ - -#endif /* RTL8187_LED_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8187/rfkill.c b/drivers/net/wireless/rtl818x/rtl8187/rfkill.c deleted file mode 100644 index 34116719974a..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187/rfkill.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Linux RFKILL support for RTL8187 - * - * Copyright (c) 2009 Herton Ronaldo Krzesinski - * - * Based on the RFKILL handling in the r8187 driver, which is: - * Copyright (c) Realtek Semiconductor Corp. All rights reserved. - * - * Thanks to Realtek for their support! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include "rtl8187.h" -#include "rfkill.h" - -static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv) -{ - u8 gpio; - - gpio = rtl818x_ioread8(priv, &priv->map->GPIO0); - rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~priv->rfkill_mask); - gpio = rtl818x_ioread8(priv, &priv->map->GPIO1); - - return gpio & priv->rfkill_mask; -} - -void rtl8187_rfkill_init(struct ieee80211_hw *hw) -{ - struct rtl8187_priv *priv = hw->priv; - - priv->rfkill_off = rtl8187_is_radio_enabled(priv); - printk(KERN_INFO "rtl8187: wireless switch is %s\n", - priv->rfkill_off ? "on" : "off"); - wiphy_rfkill_set_hw_state(hw->wiphy, !priv->rfkill_off); - wiphy_rfkill_start_polling(hw->wiphy); -} - -void rtl8187_rfkill_poll(struct ieee80211_hw *hw) -{ - bool enabled; - struct rtl8187_priv *priv = hw->priv; - - mutex_lock(&priv->conf_mutex); - enabled = rtl8187_is_radio_enabled(priv); - if (unlikely(enabled != priv->rfkill_off)) { - priv->rfkill_off = enabled; - printk(KERN_INFO "rtl8187: wireless radio switch turned %s\n", - enabled ? "on" : "off"); - wiphy_rfkill_set_hw_state(hw->wiphy, !enabled); - } - mutex_unlock(&priv->conf_mutex); -} - -void rtl8187_rfkill_exit(struct ieee80211_hw *hw) -{ - wiphy_rfkill_stop_polling(hw->wiphy); -} diff --git a/drivers/net/wireless/rtl818x/rtl8187/rfkill.h b/drivers/net/wireless/rtl818x/rtl8187/rfkill.h deleted file mode 100644 index e12575e96d11..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187/rfkill.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef RTL8187_RFKILL_H -#define RTL8187_RFKILL_H - -void rtl8187_rfkill_init(struct ieee80211_hw *hw); -void rtl8187_rfkill_poll(struct ieee80211_hw *hw); -void rtl8187_rfkill_exit(struct ieee80211_hw *hw); - -#endif /* RTL8187_RFKILL_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h deleted file mode 100644 index a6ad79f61bf9..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Definitions for RTL8187 hardware - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8187 driver, which is: - * Copyright 2005 Andrea Merello , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef RTL8187_H -#define RTL8187_H - -#include - -#include "rtl818x.h" -#include "leds.h" - -#define RTL8187_EEPROM_TXPWR_BASE 0x05 -#define RTL8187_EEPROM_MAC_ADDR 0x07 -#define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */ -#define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */ -#define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */ -#define RTL8187_EEPROM_SELECT_GPIO 0x3B - -#define RTL8187_REQT_READ 0xC0 -#define RTL8187_REQT_WRITE 0x40 -#define RTL8187_REQ_GET_REG 0x05 -#define RTL8187_REQ_SET_REG 0x05 - -#define RTL8187_MAX_RX 0x9C4 - -#define RFKILL_MASK_8187_89_97 0x2 -#define RFKILL_MASK_8198 0x4 - -#define RETRY_COUNT 7 - -struct rtl8187_rx_info { - struct urb *urb; - struct ieee80211_hw *dev; -}; - -struct rtl8187_rx_hdr { - __le32 flags; - u8 noise; - u8 signal; - u8 agc; - u8 reserved; - __le64 mac_time; -} __packed; - -struct rtl8187b_rx_hdr { - __le32 flags; - __le64 mac_time; - u8 sq; - u8 rssi; - u8 agc; - u8 flags2; - __le16 snr_long2end; - s8 pwdb_g12; - u8 fot; -} __packed; - -/* {rtl8187,rtl8187b}_tx_info is in skb */ - -struct rtl8187_tx_hdr { - __le32 flags; - __le16 rts_duration; - __le16 len; - __le32 retry; -} __packed; - -struct rtl8187b_tx_hdr { - __le32 flags; - __le16 rts_duration; - __le16 len; - __le32 unused_1; - __le16 unused_2; - __le16 tx_duration; - __le32 unused_3; - __le32 retry; - __le32 unused_4[2]; -} __packed; - -enum { - DEVICE_RTL8187, - DEVICE_RTL8187B -}; - -struct rtl8187_vif { - struct ieee80211_hw *dev; - - /* beaconing */ - struct delayed_work beacon_work; - bool enable_beacon; -}; - -struct rtl8187_priv { - /* common between rtl818x drivers */ - struct rtl818x_csr *map; - const struct rtl818x_rf_ops *rf; - struct ieee80211_vif *vif; - - /* The mutex protects the TX loopback state. - * Any attempt to set channels concurrently locks the device. - */ - struct mutex conf_mutex; - - /* rtl8187 specific */ - struct ieee80211_channel channels[14]; - struct ieee80211_rate rates[12]; - struct ieee80211_supported_band band; - struct usb_device *udev; - u32 rx_conf; - struct usb_anchor anchored; - struct delayed_work work; - struct ieee80211_hw *dev; -#ifdef CONFIG_RTL8187_LEDS - struct rtl8187_led led_radio; - struct rtl8187_led led_tx; - struct rtl8187_led led_rx; - struct delayed_work led_on; - struct delayed_work led_off; -#endif - u16 txpwr_base; - u8 asic_rev; - u8 is_rtl8187b; - enum { - RTL8187BvB, - RTL8187BvD, - RTL8187BvE - } hw_rev; - struct sk_buff_head rx_queue; - u8 signal; - u8 noise; - u8 slot_time; - u8 aifsn[4]; - u8 rfkill_mask; - struct { - union { - __le64 buf; - u8 dummy1[L1_CACHE_BYTES]; - } ____cacheline_aligned; - struct sk_buff_head queue; - } b_tx_status; /* This queue is used by both -b and non-b devices */ - struct mutex io_mutex; - union { - u8 bits8; - __le16 bits16; - __le32 bits32; - u8 dummy2[L1_CACHE_BYTES]; - } *io_dmabuf ____cacheline_aligned; - bool rfkill_off; - u16 seqno; -}; - -void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); - -static inline u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv, - u8 *addr, u8 idx) -{ - u8 val; - - mutex_lock(&priv->io_mutex); - usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), - RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, idx & 0x03, - &priv->io_dmabuf->bits8, sizeof(val), HZ / 2); - - val = priv->io_dmabuf->bits8; - mutex_unlock(&priv->io_mutex); - - return val; -} - -static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr) -{ - return rtl818x_ioread8_idx(priv, addr, 0); -} - -static inline u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv, - __le16 *addr, u8 idx) -{ - __le16 val; - - mutex_lock(&priv->io_mutex); - usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), - RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, idx & 0x03, - &priv->io_dmabuf->bits16, sizeof(val), HZ / 2); - - val = priv->io_dmabuf->bits16; - mutex_unlock(&priv->io_mutex); - - return le16_to_cpu(val); -} - -static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr) -{ - return rtl818x_ioread16_idx(priv, addr, 0); -} - -static inline u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv, - __le32 *addr, u8 idx) -{ - __le32 val; - - mutex_lock(&priv->io_mutex); - usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), - RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, idx & 0x03, - &priv->io_dmabuf->bits32, sizeof(val), HZ / 2); - - val = priv->io_dmabuf->bits32; - mutex_unlock(&priv->io_mutex); - - return le32_to_cpu(val); -} - -static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr) -{ - return rtl818x_ioread32_idx(priv, addr, 0); -} - -static inline void rtl818x_iowrite8_idx(struct rtl8187_priv *priv, - u8 *addr, u8 val, u8 idx) -{ - mutex_lock(&priv->io_mutex); - - priv->io_dmabuf->bits8 = val; - usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), - RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, idx & 0x03, - &priv->io_dmabuf->bits8, sizeof(val), HZ / 2); - - mutex_unlock(&priv->io_mutex); -} - -static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, u8 *addr, u8 val) -{ - rtl818x_iowrite8_idx(priv, addr, val, 0); -} - -static inline void rtl818x_iowrite16_idx(struct rtl8187_priv *priv, - __le16 *addr, u16 val, u8 idx) -{ - mutex_lock(&priv->io_mutex); - - priv->io_dmabuf->bits16 = cpu_to_le16(val); - usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), - RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, idx & 0x03, - &priv->io_dmabuf->bits16, sizeof(val), HZ / 2); - - mutex_unlock(&priv->io_mutex); -} - -static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, __le16 *addr, - u16 val) -{ - rtl818x_iowrite16_idx(priv, addr, val, 0); -} - -static inline void rtl818x_iowrite32_idx(struct rtl8187_priv *priv, - __le32 *addr, u32 val, u8 idx) -{ - mutex_lock(&priv->io_mutex); - - priv->io_dmabuf->bits32 = cpu_to_le32(val); - usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), - RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, idx & 0x03, - &priv->io_dmabuf->bits32, sizeof(val), HZ / 2); - - mutex_unlock(&priv->io_mutex); -} - -static inline void rtl818x_iowrite32(struct rtl8187_priv *priv, __le32 *addr, - u32 val) -{ - rtl818x_iowrite32_idx(priv, addr, val, 0); -} - -#endif /* RTL8187_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c deleted file mode 100644 index 5ecf18ed67b8..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.c +++ /dev/null @@ -1,961 +0,0 @@ -/* - * Radio tuning for RTL8225 on RTL8187 - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8187 driver, which is: - * Copyright 2005 Andrea Merello , et al. - * - * Magic delays, register offsets, and phy value tables below are - * taken from the original r8187 driver sources. Thanks to Realtek - * for their support! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include - -#include "rtl8187.h" -#include "rtl8225.h" - -static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data) -{ - struct rtl8187_priv *priv = dev->priv; - u16 reg80, reg84, reg82; - u32 bangdata; - int i; - - bangdata = (data << 4) | (addr & 0xf); - - reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3; - reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7); - - reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7); - udelay(10); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); - udelay(10); - - for (i = 15; i >= 0; i--) { - u16 reg = reg80 | (bangdata & (1 << i)) >> i; - - if (i & 1) - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); - - if (!(i & 1)) - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - udelay(10); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); -} - -static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data) -{ - struct rtl8187_priv *priv = dev->priv; - u16 reg80, reg82, reg84; - - reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput); - reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); - reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); - - reg80 &= ~(0x3 << 2); - reg84 &= ~0xF; - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007); - udelay(10); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - udelay(2); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); - udelay(10); - - mutex_lock(&priv->io_mutex); - - priv->io_dmabuf->bits16 = data; - usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), - RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data), - HZ / 2); - - mutex_unlock(&priv->io_mutex); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - udelay(10); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); -} - -static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data) -{ - struct rtl8187_priv *priv = dev->priv; - - if (priv->asic_rev) - rtl8225_write_8051(dev, addr, cpu_to_le16(data)); - else - rtl8225_write_bitbang(dev, addr, data); -} - -static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr) -{ - struct rtl8187_priv *priv = dev->priv; - u16 reg80, reg82, reg84, out; - int i; - - reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput); - reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); - reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); - - reg80 &= ~0xF; - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - udelay(4); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); - udelay(5); - - for (i = 4; i >= 0; i--) { - u16 reg = reg80 | ((addr >> i) & 1); - - if (!(i & 1)) { - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - udelay(1); - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg | (1 << 1)); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg | (1 << 1)); - udelay(2); - - if (i & 1) { - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - udelay(1); - } - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - udelay(2); - - out = 0; - for (i = 11; i >= 0; i--) { - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - udelay(1); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - udelay(2); - - if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1)) - out |= 1 << i; - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - udelay(2); - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 2)); - udelay(2); - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0); - - return out; -} - -static const u16 rtl8225bcd_rxgain[] = { - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, - 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, - 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, - 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, - 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, - 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, - 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, - 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, - 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, - 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, - 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, - 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb -}; - -static const u8 rtl8225_agc[] = { - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, - 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, - 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, - 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, - 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, - 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, - 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, - 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, - 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, - 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, - 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, - 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 -}; - -static const u8 rtl8225_gain[] = { - 0x23, 0x88, 0x7c, 0xa5, /* -82dBm */ - 0x23, 0x88, 0x7c, 0xb5, /* -82dBm */ - 0x23, 0x88, 0x7c, 0xc5, /* -82dBm */ - 0x33, 0x80, 0x79, 0xc5, /* -78dBm */ - 0x43, 0x78, 0x76, 0xc5, /* -74dBm */ - 0x53, 0x60, 0x73, 0xc5, /* -70dBm */ - 0x63, 0x58, 0x70, 0xc5, /* -66dBm */ -}; - -static const u8 rtl8225_threshold[] = { - 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd -}; - -static const u8 rtl8225_tx_gain_cck_ofdm[] = { - 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e -}; - -static const u8 rtl8225_tx_power_cck[] = { - 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, - 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, - 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, - 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, - 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, - 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 -}; - -static const u8 rtl8225_tx_power_cck_ch14[] = { - 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, - 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, - 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 rtl8225_tx_power_ofdm[] = { - 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 -}; - -static const u32 rtl8225_chan[] = { - 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c, - 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72 -}; - -static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) -{ - struct rtl8187_priv *priv = dev->priv; - u8 cck_power, ofdm_power; - const u8 *tmp; - u32 reg; - int i; - - cck_power = priv->channels[channel - 1].hw_value & 0xF; - ofdm_power = priv->channels[channel - 1].hw_value >> 4; - - cck_power = min(cck_power, (u8)11); - if (ofdm_power > (u8)15) - ofdm_power = 25; - else - ofdm_power += 10; - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, - rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1); - - if (channel == 14) - tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8]; - else - tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8]; - - for (i = 0; i < 8; i++) - rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); - - msleep(1); // FIXME: optional? - - /* anaparam2 on */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl8225_write_phy_ofdm(dev, 2, 0x42); - rtl8225_write_phy_ofdm(dev, 6, 0x00); - rtl8225_write_phy_ofdm(dev, 8, 0x00); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, - rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1); - - tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6]; - - rtl8225_write_phy_ofdm(dev, 5, *tmp); - rtl8225_write_phy_ofdm(dev, 7, *tmp); - - msleep(1); -} - -static void rtl8225_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - int i; - - rtl8225_write(dev, 0x0, 0x067); - rtl8225_write(dev, 0x1, 0xFE0); - rtl8225_write(dev, 0x2, 0x44D); - rtl8225_write(dev, 0x3, 0x441); - rtl8225_write(dev, 0x4, 0x486); - rtl8225_write(dev, 0x5, 0xBC0); - rtl8225_write(dev, 0x6, 0xAE6); - rtl8225_write(dev, 0x7, 0x82A); - rtl8225_write(dev, 0x8, 0x01F); - rtl8225_write(dev, 0x9, 0x334); - rtl8225_write(dev, 0xA, 0xFD4); - rtl8225_write(dev, 0xB, 0x391); - rtl8225_write(dev, 0xC, 0x050); - rtl8225_write(dev, 0xD, 0x6DB); - rtl8225_write(dev, 0xE, 0x029); - rtl8225_write(dev, 0xF, 0x914); msleep(100); - - rtl8225_write(dev, 0x2, 0xC4D); msleep(200); - rtl8225_write(dev, 0x2, 0x44D); msleep(200); - - if (!(rtl8225_read(dev, 6) & (1 << 7))) { - rtl8225_write(dev, 0x02, 0x0c4d); - msleep(200); - rtl8225_write(dev, 0x02, 0x044d); - msleep(100); - if (!(rtl8225_read(dev, 6) & (1 << 7))) - wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n", - rtl8225_read(dev, 6)); - } - - rtl8225_write(dev, 0x0, 0x127); - - for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) { - rtl8225_write(dev, 0x1, i + 1); - rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]); - } - - rtl8225_write(dev, 0x0, 0x027); - rtl8225_write(dev, 0x0, 0x22F); - - for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { - rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); - rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); - } - - msleep(1); - - rtl8225_write_phy_ofdm(dev, 0x00, 0x01); - rtl8225_write_phy_ofdm(dev, 0x01, 0x02); - rtl8225_write_phy_ofdm(dev, 0x02, 0x42); - rtl8225_write_phy_ofdm(dev, 0x03, 0x00); - rtl8225_write_phy_ofdm(dev, 0x04, 0x00); - rtl8225_write_phy_ofdm(dev, 0x05, 0x00); - rtl8225_write_phy_ofdm(dev, 0x06, 0x40); - rtl8225_write_phy_ofdm(dev, 0x07, 0x00); - rtl8225_write_phy_ofdm(dev, 0x08, 0x40); - rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); - rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); - rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); - rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); - rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); - rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); - rtl8225_write_phy_ofdm(dev, 0x10, 0x84); - rtl8225_write_phy_ofdm(dev, 0x11, 0x06); - rtl8225_write_phy_ofdm(dev, 0x12, 0x20); - rtl8225_write_phy_ofdm(dev, 0x13, 0x20); - rtl8225_write_phy_ofdm(dev, 0x14, 0x00); - rtl8225_write_phy_ofdm(dev, 0x15, 0x40); - rtl8225_write_phy_ofdm(dev, 0x16, 0x00); - rtl8225_write_phy_ofdm(dev, 0x17, 0x40); - rtl8225_write_phy_ofdm(dev, 0x18, 0xef); - rtl8225_write_phy_ofdm(dev, 0x19, 0x19); - rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); - rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); - rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); - rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); - rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); - rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); - rtl8225_write_phy_ofdm(dev, 0x21, 0x27); - rtl8225_write_phy_ofdm(dev, 0x22, 0x16); - rtl8225_write_phy_ofdm(dev, 0x24, 0x46); - rtl8225_write_phy_ofdm(dev, 0x25, 0x20); - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); - rtl8225_write_phy_ofdm(dev, 0x27, 0x88); - - rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]); - rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]); - rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]); - rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]); - - rtl8225_write_phy_cck(dev, 0x00, 0x98); - rtl8225_write_phy_cck(dev, 0x03, 0x20); - rtl8225_write_phy_cck(dev, 0x04, 0x7e); - rtl8225_write_phy_cck(dev, 0x05, 0x12); - rtl8225_write_phy_cck(dev, 0x06, 0xfc); - rtl8225_write_phy_cck(dev, 0x07, 0x78); - rtl8225_write_phy_cck(dev, 0x08, 0x2e); - rtl8225_write_phy_cck(dev, 0x10, 0x9b); - rtl8225_write_phy_cck(dev, 0x11, 0x88); - rtl8225_write_phy_cck(dev, 0x12, 0x47); - rtl8225_write_phy_cck(dev, 0x13, 0xd0); - rtl8225_write_phy_cck(dev, 0x19, 0x00); - rtl8225_write_phy_cck(dev, 0x1a, 0xa0); - rtl8225_write_phy_cck(dev, 0x1b, 0x08); - rtl8225_write_phy_cck(dev, 0x40, 0x86); - rtl8225_write_phy_cck(dev, 0x41, 0x8d); - rtl8225_write_phy_cck(dev, 0x42, 0x15); - rtl8225_write_phy_cck(dev, 0x43, 0x18); - rtl8225_write_phy_cck(dev, 0x44, 0x1f); - rtl8225_write_phy_cck(dev, 0x45, 0x1e); - rtl8225_write_phy_cck(dev, 0x46, 0x1a); - rtl8225_write_phy_cck(dev, 0x47, 0x15); - rtl8225_write_phy_cck(dev, 0x48, 0x10); - rtl8225_write_phy_cck(dev, 0x49, 0x0a); - rtl8225_write_phy_cck(dev, 0x4a, 0x05); - rtl8225_write_phy_cck(dev, 0x4b, 0x02); - rtl8225_write_phy_cck(dev, 0x4c, 0x05); - - rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); - - rtl8225_rf_set_tx_power(dev, 1); - - /* RX antenna default to A */ - rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */ - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */ - - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ - msleep(1); - rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002); - - /* set sensitivity */ - rtl8225_write(dev, 0x0c, 0x50); - rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]); - rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]); - rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]); - rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]); - rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]); -} - -static const u8 rtl8225z2_agc[] = { - 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f, - 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37, - 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f, - 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07, - 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, - 0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 -}; -static const u8 rtl8225z2_ofdm[] = { - 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, - 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26, - 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3, - 0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f, - 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00, - 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e, - 0x6d, 0x3c, 0xfb, 0x07 -}; - -static const u8 rtl8225z2_tx_power_cck_ch14[] = { - 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 rtl8225z2_tx_power_cck[] = { - 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04, - 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03, - 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03, - 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 -}; - -static const u8 rtl8225z2_tx_power_ofdm[] = { - 0x42, 0x00, 0x40, 0x00, 0x40 -}; - -static const u8 rtl8225z2_tx_gain_cck_ofdm[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, - 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, - 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23 -}; - -static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) -{ - struct rtl8187_priv *priv = dev->priv; - u8 cck_power, ofdm_power; - const u8 *tmp; - u32 reg; - int i; - - cck_power = priv->channels[channel - 1].hw_value & 0xF; - ofdm_power = priv->channels[channel - 1].hw_value >> 4; - - cck_power = min(cck_power, (u8)15); - cck_power += priv->txpwr_base & 0xF; - cck_power = min(cck_power, (u8)35); - - if (ofdm_power > (u8)15) - ofdm_power = 25; - else - ofdm_power += 10; - ofdm_power += priv->txpwr_base >> 4; - ofdm_power = min(ofdm_power, (u8)35); - - if (channel == 14) - tmp = rtl8225z2_tx_power_cck_ch14; - else - tmp = rtl8225z2_tx_power_cck; - - for (i = 0; i < 8; i++) - rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, - rtl8225z2_tx_gain_cck_ofdm[cck_power]); - msleep(1); - - /* anaparam2 on */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl8225_write_phy_ofdm(dev, 2, 0x42); - rtl8225_write_phy_ofdm(dev, 5, 0x00); - rtl8225_write_phy_ofdm(dev, 6, 0x40); - rtl8225_write_phy_ofdm(dev, 7, 0x00); - rtl8225_write_phy_ofdm(dev, 8, 0x40); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, - rtl8225z2_tx_gain_cck_ofdm[ofdm_power]); - msleep(1); -} - -static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel) -{ - struct rtl8187_priv *priv = dev->priv; - u8 cck_power, ofdm_power; - const u8 *tmp; - int i; - - cck_power = priv->channels[channel - 1].hw_value & 0xF; - ofdm_power = priv->channels[channel - 1].hw_value >> 4; - - if (cck_power > 15) - cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22; - else - cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7; - cck_power += priv->txpwr_base & 0xF; - cck_power = min(cck_power, (u8)35); - - if (ofdm_power > 15) - ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25; - else - ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10; - ofdm_power += (priv->txpwr_base >> 4) & 0xF; - ofdm_power = min(ofdm_power, (u8)35); - - if (channel == 14) - tmp = rtl8225z2_tx_power_cck_ch14; - else - tmp = rtl8225z2_tx_power_cck; - - if (priv->hw_rev == RTL8187BvB) { - if (cck_power <= 6) - ; /* do nothing */ - else if (cck_power <= 11) - tmp += 8; - else - tmp += 16; - } else { - if (cck_power <= 5) - ; /* do nothing */ - else if (cck_power <= 11) - tmp += 8; - else if (cck_power <= 17) - tmp += 16; - else - tmp += 24; - } - - for (i = 0; i < 8; i++) - rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, - rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1); - msleep(1); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, - rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1); - if (priv->hw_rev == RTL8187BvB) { - if (ofdm_power <= 11) { - rtl8225_write_phy_ofdm(dev, 0x87, 0x60); - rtl8225_write_phy_ofdm(dev, 0x89, 0x60); - } else { - rtl8225_write_phy_ofdm(dev, 0x87, 0x5c); - rtl8225_write_phy_ofdm(dev, 0x89, 0x5c); - } - } else { - if (ofdm_power <= 11) { - rtl8225_write_phy_ofdm(dev, 0x87, 0x5c); - rtl8225_write_phy_ofdm(dev, 0x89, 0x5c); - } else if (ofdm_power <= 17) { - rtl8225_write_phy_ofdm(dev, 0x87, 0x54); - rtl8225_write_phy_ofdm(dev, 0x89, 0x54); - } else { - rtl8225_write_phy_ofdm(dev, 0x87, 0x50); - rtl8225_write_phy_ofdm(dev, 0x89, 0x50); - } - } - msleep(1); -} - -static const u16 rtl8225z2_rxgain[] = { - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, - 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, - 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, - 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, - 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, - 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, - 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, - 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, - 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, - 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, - 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, - 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb -}; - -static const u8 rtl8225z2_gain_bg[] = { - 0x23, 0x15, 0xa5, /* -82-1dBm */ - 0x23, 0x15, 0xb5, /* -82-2dBm */ - 0x23, 0x15, 0xc5, /* -82-3dBm */ - 0x33, 0x15, 0xc5, /* -78dBm */ - 0x43, 0x15, 0xc5, /* -74dBm */ - 0x53, 0x15, 0xc5, /* -70dBm */ - 0x63, 0x15, 0xc5 /* -66dBm */ -}; - -static void rtl8225z2_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - int i; - - rtl8225_write(dev, 0x0, 0x2BF); - rtl8225_write(dev, 0x1, 0xEE0); - rtl8225_write(dev, 0x2, 0x44D); - rtl8225_write(dev, 0x3, 0x441); - rtl8225_write(dev, 0x4, 0x8C3); - rtl8225_write(dev, 0x5, 0xC72); - rtl8225_write(dev, 0x6, 0x0E6); - rtl8225_write(dev, 0x7, 0x82A); - rtl8225_write(dev, 0x8, 0x03F); - rtl8225_write(dev, 0x9, 0x335); - rtl8225_write(dev, 0xa, 0x9D4); - rtl8225_write(dev, 0xb, 0x7BB); - rtl8225_write(dev, 0xc, 0x850); - rtl8225_write(dev, 0xd, 0xCDF); - rtl8225_write(dev, 0xe, 0x02B); - rtl8225_write(dev, 0xf, 0x114); - msleep(100); - - rtl8225_write(dev, 0x0, 0x1B7); - - for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { - rtl8225_write(dev, 0x1, i + 1); - rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); - } - - rtl8225_write(dev, 0x3, 0x080); - rtl8225_write(dev, 0x5, 0x004); - rtl8225_write(dev, 0x0, 0x0B7); - rtl8225_write(dev, 0x2, 0xc4D); - - msleep(200); - rtl8225_write(dev, 0x2, 0x44D); - msleep(100); - - if (!(rtl8225_read(dev, 6) & (1 << 7))) { - rtl8225_write(dev, 0x02, 0x0C4D); - msleep(200); - rtl8225_write(dev, 0x02, 0x044D); - msleep(100); - if (!(rtl8225_read(dev, 6) & (1 << 7))) - wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n", - rtl8225_read(dev, 6)); - } - - msleep(200); - - rtl8225_write(dev, 0x0, 0x2BF); - - for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { - rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); - rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); - } - - msleep(1); - - rtl8225_write_phy_ofdm(dev, 0x00, 0x01); - rtl8225_write_phy_ofdm(dev, 0x01, 0x02); - rtl8225_write_phy_ofdm(dev, 0x02, 0x42); - rtl8225_write_phy_ofdm(dev, 0x03, 0x00); - rtl8225_write_phy_ofdm(dev, 0x04, 0x00); - rtl8225_write_phy_ofdm(dev, 0x05, 0x00); - rtl8225_write_phy_ofdm(dev, 0x06, 0x40); - rtl8225_write_phy_ofdm(dev, 0x07, 0x00); - rtl8225_write_phy_ofdm(dev, 0x08, 0x40); - rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); - rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); - rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); - rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); - rtl8225_write_phy_ofdm(dev, 0x0d, 0x43); - rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); - rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); - rtl8225_write_phy_ofdm(dev, 0x10, 0x84); - rtl8225_write_phy_ofdm(dev, 0x11, 0x07); - rtl8225_write_phy_ofdm(dev, 0x12, 0x20); - rtl8225_write_phy_ofdm(dev, 0x13, 0x20); - rtl8225_write_phy_ofdm(dev, 0x14, 0x00); - rtl8225_write_phy_ofdm(dev, 0x15, 0x40); - rtl8225_write_phy_ofdm(dev, 0x16, 0x00); - rtl8225_write_phy_ofdm(dev, 0x17, 0x40); - rtl8225_write_phy_ofdm(dev, 0x18, 0xef); - rtl8225_write_phy_ofdm(dev, 0x19, 0x19); - rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); - rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); - rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); - rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); - rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); - rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); - rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); - rtl8225_write_phy_ofdm(dev, 0x21, 0x17); - rtl8225_write_phy_ofdm(dev, 0x22, 0x16); - rtl8225_write_phy_ofdm(dev, 0x23, 0x80); - rtl8225_write_phy_ofdm(dev, 0x24, 0x46); - rtl8225_write_phy_ofdm(dev, 0x25, 0x00); - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); - rtl8225_write_phy_ofdm(dev, 0x27, 0x88); - - rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]); - rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]); - rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]); - rtl8225_write_phy_ofdm(dev, 0x21, 0x37); - - rtl8225_write_phy_cck(dev, 0x00, 0x98); - rtl8225_write_phy_cck(dev, 0x03, 0x20); - rtl8225_write_phy_cck(dev, 0x04, 0x7e); - rtl8225_write_phy_cck(dev, 0x05, 0x12); - rtl8225_write_phy_cck(dev, 0x06, 0xfc); - rtl8225_write_phy_cck(dev, 0x07, 0x78); - rtl8225_write_phy_cck(dev, 0x08, 0x2e); - rtl8225_write_phy_cck(dev, 0x10, 0x9b); - rtl8225_write_phy_cck(dev, 0x11, 0x88); - rtl8225_write_phy_cck(dev, 0x12, 0x47); - rtl8225_write_phy_cck(dev, 0x13, 0xd0); - rtl8225_write_phy_cck(dev, 0x19, 0x00); - rtl8225_write_phy_cck(dev, 0x1a, 0xa0); - rtl8225_write_phy_cck(dev, 0x1b, 0x08); - rtl8225_write_phy_cck(dev, 0x40, 0x86); - rtl8225_write_phy_cck(dev, 0x41, 0x8d); - rtl8225_write_phy_cck(dev, 0x42, 0x15); - rtl8225_write_phy_cck(dev, 0x43, 0x18); - rtl8225_write_phy_cck(dev, 0x44, 0x36); - rtl8225_write_phy_cck(dev, 0x45, 0x35); - rtl8225_write_phy_cck(dev, 0x46, 0x2e); - rtl8225_write_phy_cck(dev, 0x47, 0x25); - rtl8225_write_phy_cck(dev, 0x48, 0x1c); - rtl8225_write_phy_cck(dev, 0x49, 0x12); - rtl8225_write_phy_cck(dev, 0x4a, 0x09); - rtl8225_write_phy_cck(dev, 0x4b, 0x04); - rtl8225_write_phy_cck(dev, 0x4c, 0x05); - - rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1); - - rtl8225z2_rf_set_tx_power(dev, 1); - - /* RX antenna default to A */ - rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */ - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */ - - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ - msleep(1); - rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002); -} - -static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - int i; - - rtl8225_write(dev, 0x0, 0x0B7); - rtl8225_write(dev, 0x1, 0xEE0); - rtl8225_write(dev, 0x2, 0x44D); - rtl8225_write(dev, 0x3, 0x441); - rtl8225_write(dev, 0x4, 0x8C3); - rtl8225_write(dev, 0x5, 0xC72); - rtl8225_write(dev, 0x6, 0x0E6); - rtl8225_write(dev, 0x7, 0x82A); - rtl8225_write(dev, 0x8, 0x03F); - rtl8225_write(dev, 0x9, 0x335); - rtl8225_write(dev, 0xa, 0x9D4); - rtl8225_write(dev, 0xb, 0x7BB); - rtl8225_write(dev, 0xc, 0x850); - rtl8225_write(dev, 0xd, 0xCDF); - rtl8225_write(dev, 0xe, 0x02B); - rtl8225_write(dev, 0xf, 0x114); - - rtl8225_write(dev, 0x0, 0x1B7); - - for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { - rtl8225_write(dev, 0x1, i + 1); - rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); - } - - rtl8225_write(dev, 0x3, 0x080); - rtl8225_write(dev, 0x5, 0x004); - rtl8225_write(dev, 0x0, 0x0B7); - - rtl8225_write(dev, 0x2, 0xC4D); - - rtl8225_write(dev, 0x2, 0x44D); - rtl8225_write(dev, 0x0, 0x2BF); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03); - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07); - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); - - rtl8225_write_phy_ofdm(dev, 0x80, 0x12); - for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) { - rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]); - rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i); - rtl8225_write_phy_ofdm(dev, 0xE, 0); - } - rtl8225_write_phy_ofdm(dev, 0x80, 0x10); - - for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++) - rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]); - - rtl8225_write_phy_ofdm(dev, 0x97, 0x46); - rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); - rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); - rtl8225_write_phy_cck(dev, 0xc1, 0x88); -} - -static void rtl8225_rf_stop(struct ieee80211_hw *dev) -{ - rtl8225_write(dev, 0x4, 0x1f); -} - -static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, - struct ieee80211_conf *conf) -{ - struct rtl8187_priv *priv = dev->priv; - int chan = - ieee80211_frequency_to_channel(conf->chandef.chan->center_freq); - - if (priv->rf->init == rtl8225_rf_init) - rtl8225_rf_set_tx_power(dev, chan); - else if (priv->rf->init == rtl8225z2_rf_init) - rtl8225z2_rf_set_tx_power(dev, chan); - else - rtl8225z2_b_rf_set_tx_power(dev, chan); - - rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); - msleep(10); -} - -static const struct rtl818x_rf_ops rtl8225_ops = { - .name = "rtl8225", - .init = rtl8225_rf_init, - .stop = rtl8225_rf_stop, - .set_chan = rtl8225_rf_set_channel -}; - -static const struct rtl818x_rf_ops rtl8225z2_ops = { - .name = "rtl8225z2", - .init = rtl8225z2_rf_init, - .stop = rtl8225_rf_stop, - .set_chan = rtl8225_rf_set_channel -}; - -static const struct rtl818x_rf_ops rtl8225z2_b_ops = { - .name = "rtl8225z2", - .init = rtl8225z2_b_rf_init, - .stop = rtl8225_rf_stop, - .set_chan = rtl8225_rf_set_channel -}; - -const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev) -{ - u16 reg8, reg9; - struct rtl8187_priv *priv = dev->priv; - - if (!priv->is_rtl8187b) { - rtl8225_write(dev, 0, 0x1B7); - - reg8 = rtl8225_read(dev, 8); - reg9 = rtl8225_read(dev, 9); - - rtl8225_write(dev, 0, 0x0B7); - - if (reg8 != 0x588 || reg9 != 0x700) - return &rtl8225_ops; - - return &rtl8225z2_ops; - } else - return &rtl8225z2_b_ops; -} diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8225.h deleted file mode 100644 index 141afb09a5b4..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187/rtl8225.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Radio tuning definitions for RTL8225 on RTL8187 - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8187 driver, which is: - * Copyright 2005 Andrea Merello , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef RTL8187_RTL8225_H -#define RTL8187_RTL8225_H - -#define RTL8187_RTL8225_ANAPARAM_ON 0xa0000a59 -#define RTL8187_RTL8225_ANAPARAM2_ON 0x860c7312 -#define RTL8187_RTL8225_ANAPARAM_OFF 0xa00beb59 -#define RTL8187_RTL8225_ANAPARAM2_OFF 0x840dec11 - -#define RTL8187B_RTL8225_ANAPARAM_ON 0x45090658 -#define RTL8187B_RTL8225_ANAPARAM2_ON 0x727f3f52 -#define RTL8187B_RTL8225_ANAPARAM3_ON 0x00 -#define RTL8187B_RTL8225_ANAPARAM_OFF 0x55480658 -#define RTL8187B_RTL8225_ANAPARAM2_OFF 0x72003f50 -#define RTL8187B_RTL8225_ANAPARAM3_OFF 0x00 - -const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *); - -static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev, - u8 addr, u32 data) -{ - rtl8187_write_phy(dev, addr, data); -} - -static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev, - u8 addr, u32 data) -{ - rtl8187_write_phy(dev, addr, data | 0x10000); -} - -#endif /* RTL8187_RTL8225_H */ diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h deleted file mode 100644 index 7abef95d278b..000000000000 --- a/drivers/net/wireless/rtl818x/rtl818x.h +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Definitions for RTL818x hardware - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8187 driver, which is: - * Copyright 2005 Andrea Merello , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef RTL818X_H -#define RTL818X_H - -struct rtl818x_csr { - - u8 MAC[6]; - u8 reserved_0[2]; - - union { - __le32 MAR[2]; /* 0x8 */ - - struct{ /* rtl8187se */ - u8 rf_sw_config; /* 0x8 */ - u8 reserved_01[3]; - __le32 TMGDA; /* 0xc */ - } __packed; - } __packed; - - union { /* 0x10 */ - struct { - u8 RX_FIFO_COUNT; - u8 reserved_1; - u8 TX_FIFO_COUNT; - u8 BQREQ; - } __packed; - - __le32 TBKDA; /* for 8187se */ - } __packed; - - __le32 TBEDA; /* 0x14 - for rtl8187se */ - - __le32 TSFT[2]; - - union { /* 0x20 */ - __le32 TLPDA; - __le32 TVIDA; /* for 8187se */ - } __packed; - - union { /* 0x24 */ - __le32 TNPDA; - __le32 TVODA; /* for 8187se */ - } __packed; - - /* hi pri ring for all cards */ - __le32 THPDA; /* 0x28 */ - - union { /* 0x2c */ - struct { - u8 reserved_2a; - u8 EIFS_8187SE; - } __packed; - - __le16 BRSR; - } __packed; - - u8 BSSID[6]; /* 0x2e */ - - union { /* 0x34 */ - struct { - u8 RESP_RATE; - u8 EIFS; - } __packed; - __le16 BRSR_8187SE; - } __packed; - - u8 reserved_3[1]; /* 0x36 */ - u8 CMD; /* 0x37 */ -#define RTL818X_CMD_TX_ENABLE (1 << 2) -#define RTL818X_CMD_RX_ENABLE (1 << 3) -#define RTL818X_CMD_RESET (1 << 4) - u8 reserved_4[4]; /* 0x38 */ - union { - struct { - __le16 INT_MASK; - __le16 INT_STATUS; - } __packed; - - __le32 INT_STATUS_SE; /* 0x3c */ - } __packed; -/* status bits for rtl8187 and rtl8180/8185 */ -#define RTL818X_INT_RX_OK (1 << 0) -#define RTL818X_INT_RX_ERR (1 << 1) -#define RTL818X_INT_TXL_OK (1 << 2) -#define RTL818X_INT_TXL_ERR (1 << 3) -#define RTL818X_INT_RX_DU (1 << 4) -#define RTL818X_INT_RX_FO (1 << 5) -#define RTL818X_INT_TXN_OK (1 << 6) -#define RTL818X_INT_TXN_ERR (1 << 7) -#define RTL818X_INT_TXH_OK (1 << 8) -#define RTL818X_INT_TXH_ERR (1 << 9) -#define RTL818X_INT_TXB_OK (1 << 10) -#define RTL818X_INT_TXB_ERR (1 << 11) -#define RTL818X_INT_ATIM (1 << 12) -#define RTL818X_INT_BEACON (1 << 13) -#define RTL818X_INT_TIME_OUT (1 << 14) -#define RTL818X_INT_TX_FO (1 << 15) -/* status bits for rtl8187se */ -#define RTL818X_INT_SE_TIMER3 (1 << 0) -#define RTL818X_INT_SE_TIMER2 (1 << 1) -#define RTL818X_INT_SE_RQ0SOR (1 << 2) -#define RTL818X_INT_SE_TXBED_OK (1 << 3) -#define RTL818X_INT_SE_TXBED_ERR (1 << 4) -#define RTL818X_INT_SE_TXBE_OK (1 << 5) -#define RTL818X_INT_SE_TXBE_ERR (1 << 6) -#define RTL818X_INT_SE_RX_OK (1 << 7) -#define RTL818X_INT_SE_RX_ERR (1 << 8) -#define RTL818X_INT_SE_TXL_OK (1 << 9) -#define RTL818X_INT_SE_TXL_ERR (1 << 10) -#define RTL818X_INT_SE_RX_DU (1 << 11) -#define RTL818X_INT_SE_RX_FIFO (1 << 12) -#define RTL818X_INT_SE_TXN_OK (1 << 13) -#define RTL818X_INT_SE_TXN_ERR (1 << 14) -#define RTL818X_INT_SE_TXH_OK (1 << 15) -#define RTL818X_INT_SE_TXH_ERR (1 << 16) -#define RTL818X_INT_SE_TXB_OK (1 << 17) -#define RTL818X_INT_SE_TXB_ERR (1 << 18) -#define RTL818X_INT_SE_ATIM_TO (1 << 19) -#define RTL818X_INT_SE_BK_TO (1 << 20) -#define RTL818X_INT_SE_TIMER1 (1 << 21) -#define RTL818X_INT_SE_TX_FIFO (1 << 22) -#define RTL818X_INT_SE_WAKEUP (1 << 23) -#define RTL818X_INT_SE_BK_DMA (1 << 24) -#define RTL818X_INT_SE_TMGD_OK (1 << 30) - __le32 TX_CONF; /* 0x40 */ -#define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17) -#define RTL818X_TX_CONF_LOOPBACK_CONT (3 << 17) -#define RTL818X_TX_CONF_NO_ICV (1 << 19) -#define RTL818X_TX_CONF_DISCW (1 << 20) -#define RTL818X_TX_CONF_SAT_HWPLCP (1 << 24) -#define RTL818X_TX_CONF_R8180_ABCD (2 << 25) -#define RTL818X_TX_CONF_R8180_F (3 << 25) -#define RTL818X_TX_CONF_R8185_ABC (4 << 25) -#define RTL818X_TX_CONF_R8185_D (5 << 25) -#define RTL818X_TX_CONF_R8187vD (5 << 25) -#define RTL818X_TX_CONF_R8187vD_B (6 << 25) -#define RTL818X_TX_CONF_RTL8187SE (6 << 25) -#define RTL818X_TX_CONF_HWVER_MASK (7 << 25) -#define RTL818X_TX_CONF_DISREQQSIZE (1 << 28) -#define RTL818X_TX_CONF_PROBE_DTS (1 << 29) -#define RTL818X_TX_CONF_HW_SEQNUM (1 << 30) -#define RTL818X_TX_CONF_CW_MIN (1 << 31) - __le32 RX_CONF; -#define RTL818X_RX_CONF_MONITOR (1 << 0) -#define RTL818X_RX_CONF_NICMAC (1 << 1) -#define RTL818X_RX_CONF_MULTICAST (1 << 2) -#define RTL818X_RX_CONF_BROADCAST (1 << 3) -#define RTL818X_RX_CONF_FCS (1 << 5) -#define RTL818X_RX_CONF_DATA (1 << 18) -#define RTL818X_RX_CONF_CTRL (1 << 19) -#define RTL818X_RX_CONF_MGMT (1 << 20) -#define RTL818X_RX_CONF_ADDR3 (1 << 21) -#define RTL818X_RX_CONF_PM (1 << 22) -#define RTL818X_RX_CONF_BSSID (1 << 23) -#define RTL818X_RX_CONF_RX_AUTORESETPHY (1 << 28) -#define RTL818X_RX_CONF_CSDM1 (1 << 29) -#define RTL818X_RX_CONF_CSDM2 (1 << 30) -#define RTL818X_RX_CONF_ONLYERLPKT (1 << 31) - __le32 INT_TIMEOUT; - __le32 TBDA; - u8 EEPROM_CMD; -#define RTL818X_EEPROM_CMD_READ (1 << 0) -#define RTL818X_EEPROM_CMD_WRITE (1 << 1) -#define RTL818X_EEPROM_CMD_CK (1 << 2) -#define RTL818X_EEPROM_CMD_CS (1 << 3) -#define RTL818X_EEPROM_CMD_NORMAL (0 << 6) -#define RTL818X_EEPROM_CMD_LOAD (1 << 6) -#define RTL818X_EEPROM_CMD_PROGRAM (2 << 6) -#define RTL818X_EEPROM_CMD_CONFIG (3 << 6) - u8 CONFIG0; - u8 CONFIG1; - u8 CONFIG2; -#define RTL818X_CONFIG2_ANTENNA_DIV (1 << 6) - __le32 ANAPARAM; - u8 MSR; -#define RTL818X_MSR_NO_LINK (0 << 2) -#define RTL818X_MSR_ADHOC (1 << 2) -#define RTL818X_MSR_INFRA (2 << 2) -#define RTL818X_MSR_MASTER (3 << 2) -#define RTL818X_MSR_ENEDCA (4 << 2) - u8 CONFIG3; -#define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6) -#define RTL818X_CONFIG3_GNT_SELECT (1 << 7) - u8 CONFIG4; -#define RTL818X_CONFIG4_POWEROFF (1 << 6) -#define RTL818X_CONFIG4_VCOOFF (1 << 7) - u8 TESTR; - u8 reserved_9[2]; - u8 PGSELECT; - u8 SECURITY; - __le32 ANAPARAM2; - u8 reserved_10[8]; - __le32 IMR; /* 0x6c - Interrupt mask reg for 8187se */ -#define IMR_TMGDOK ((1 << 30)) -#define IMR_DOT11HINT ((1 << 25)) /* 802.11h Measurement Interrupt */ -#define IMR_BCNDMAINT ((1 << 24)) /* Beacon DMA Interrupt */ -#define IMR_WAKEINT ((1 << 23)) /* Wake Up Interrupt */ -#define IMR_TXFOVW ((1 << 22)) /* Tx FIFO Overflow */ -#define IMR_TIMEOUT1 ((1 << 21)) /* Time Out Interrupt 1 */ -#define IMR_BCNINT ((1 << 20)) /* Beacon Time out */ -#define IMR_ATIMINT ((1 << 19)) /* ATIM Time Out */ -#define IMR_TBDER ((1 << 18)) /* Tx Beacon Descriptor Error */ -#define IMR_TBDOK ((1 << 17)) /* Tx Beacon Descriptor OK */ -#define IMR_THPDER ((1 << 16)) /* Tx High Priority Descriptor Error */ -#define IMR_THPDOK ((1 << 15)) /* Tx High Priority Descriptor OK */ -#define IMR_TVODER ((1 << 14)) /* Tx AC_VO Descriptor Error Int */ -#define IMR_TVODOK ((1 << 13)) /* Tx AC_VO Descriptor OK Interrupt */ -#define IMR_FOVW ((1 << 12)) /* Rx FIFO Overflow Interrupt */ -#define IMR_RDU ((1 << 11)) /* Rx Descriptor Unavailable */ -#define IMR_TVIDER ((1 << 10)) /* Tx AC_VI Descriptor Error */ -#define IMR_TVIDOK ((1 << 9)) /* Tx AC_VI Descriptor OK Interrupt */ -#define IMR_RER ((1 << 8)) /* Rx Error Interrupt */ -#define IMR_ROK ((1 << 7)) /* Receive OK Interrupt */ -#define IMR_TBEDER ((1 << 6)) /* Tx AC_BE Descriptor Error */ -#define IMR_TBEDOK ((1 << 5)) /* Tx AC_BE Descriptor OK */ -#define IMR_TBKDER ((1 << 4)) /* Tx AC_BK Descriptor Error */ -#define IMR_TBKDOK ((1 << 3)) /* Tx AC_BK Descriptor OK */ -#define IMR_RQOSOK ((1 << 2)) /* Rx QoS OK Interrupt */ -#define IMR_TIMEOUT2 ((1 << 1)) /* Time Out Interrupt 2 */ -#define IMR_TIMEOUT3 ((1 << 0)) /* Time Out Interrupt 3 */ - __le16 BEACON_INTERVAL; /* 0x70 */ - __le16 ATIM_WND; /* 0x72 */ - __le16 BEACON_INTERVAL_TIME; /* 0x74 */ - __le16 ATIMTR_INTERVAL; /* 0x76 */ - u8 PHY_DELAY; /* 0x78 */ - u8 CARRIER_SENSE_COUNTER; /* 0x79 */ - u8 reserved_11[2]; /* 0x7a */ - u8 PHY[4]; /* 0x7c */ - __le16 RFPinsOutput; /* 0x80 */ - __le16 RFPinsEnable; /* 0x82 */ - __le16 RFPinsSelect; /* 0x84 */ - __le16 RFPinsInput; /* 0x86 */ - __le32 RF_PARA; /* 0x88 */ - __le32 RF_TIMING; /* 0x8c */ - u8 GP_ENABLE; /* 0x90 */ - u8 GPIO0; /* 0x91 */ - u8 GPIO1; /* 0x92 */ - u8 TPPOLL_STOP; /* 0x93 - rtl8187se only */ -#define RTL818x_TPPOLL_STOP_BQ (1 << 7) -#define RTL818x_TPPOLL_STOP_VI (1 << 4) -#define RTL818x_TPPOLL_STOP_VO (1 << 5) -#define RTL818x_TPPOLL_STOP_BE (1 << 3) -#define RTL818x_TPPOLL_STOP_BK (1 << 2) -#define RTL818x_TPPOLL_STOP_MG (1 << 1) -#define RTL818x_TPPOLL_STOP_HI (1 << 6) - - __le32 HSSI_PARA; /* 0x94 */ - u8 reserved_13[4]; /* 0x98 */ - u8 TX_AGC_CTL; /* 0x9c */ -#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN (1 << 0) -#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL (1 << 1) -#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT (1 << 2) - u8 TX_GAIN_CCK; - u8 TX_GAIN_OFDM; - u8 TX_ANTENNA; - u8 reserved_14[16]; - u8 WPA_CONF; - u8 reserved_15[3]; - u8 SIFS; - u8 DIFS; - u8 SLOT; - u8 reserved_16[5]; - u8 CW_CONF; -#define RTL818X_CW_CONF_PERPACKET_CW (1 << 0) -#define RTL818X_CW_CONF_PERPACKET_RETRY (1 << 1) - u8 CW_VAL; - u8 RATE_FALLBACK; -#define RTL818X_RATE_FALLBACK_ENABLE (1 << 7) - u8 ACM_CONTROL; - u8 reserved_17[24]; - u8 CONFIG5; - u8 TX_DMA_POLLING; - u8 PHY_PR; - u8 reserved_18; - __le16 CWR; - u8 RETRY_CTR; - u8 reserved_19[3]; - __le16 INT_MIG; -/* RTL818X_R8187B_*: magic numbers from ioregisters */ -#define RTL818X_R8187B_B 0 -#define RTL818X_R8187B_D 1 -#define RTL818X_R8187B_E 2 - __le32 RDSAR; - __le16 TID_AC_MAP; - u8 reserved_20[4]; - union { - __le16 ANAPARAM3; /* 0xee */ - u8 ANAPARAM3A; /* for rtl8187 */ - }; - -#define AC_PARAM_TXOP_LIMIT_SHIFT 16 -#define AC_PARAM_ECW_MAX_SHIFT 12 -#define AC_PARAM_ECW_MIN_SHIFT 8 -#define AC_PARAM_AIFS_SHIFT 0 - - __le32 AC_VO_PARAM; /* 0xf0 */ - - union { /* 0xf4 */ - __le32 AC_VI_PARAM; - __le16 FEMR; - } __packed; - - union{ /* 0xf8 */ - __le32 AC_BE_PARAM; /* rtl8187se */ - struct{ - u8 reserved_21[2]; - __le16 TALLY_CNT; /* 0xfa */ - } __packed; - } __packed; - - union { - u8 TALLY_SEL; /* 0xfc */ - __le32 AC_BK_PARAM; - - } __packed; - -} __packed; - -/* These are addresses with NON-standard usage. - * They have offsets very far from this struct. - * I don't like to introduce a ton of "reserved".. - * They are for RTL8187SE - */ -#define REG_ADDR1(addr) ((u8 __iomem *)priv->map + (addr)) -#define REG_ADDR2(addr) ((__le16 __iomem *)priv->map + ((addr) >> 1)) -#define REG_ADDR4(addr) ((__le32 __iomem *)priv->map + ((addr) >> 2)) - -#define FEMR_SE REG_ADDR2(0x1D4) -#define ARFR REG_ADDR2(0x1E0) -#define RFSW_CTRL REG_ADDR2(0x272) -#define SW_3W_DB0 REG_ADDR2(0x274) -#define SW_3W_DB0_4 REG_ADDR4(0x274) -#define SW_3W_DB1 REG_ADDR2(0x278) -#define SW_3W_DB1_4 REG_ADDR4(0x278) -#define SW_3W_CMD1 REG_ADDR1(0x27D) -#define PI_DATA_REG REG_ADDR2(0x360) -#define SI_DATA_REG REG_ADDR2(0x362) - -struct rtl818x_rf_ops { - char *name; - void (*init)(struct ieee80211_hw *); - void (*stop)(struct ieee80211_hw *); - void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *); - u8 (*calc_rssi)(u8 agc, u8 sq); -}; - -/** - * enum rtl818x_tx_desc_flags - Tx/Rx flags are common between RTL818X chips - * - * @RTL818X_TX_DESC_FLAG_NO_ENC: Disable hardware based encryption. - * @RTL818X_TX_DESC_FLAG_TX_OK: TX frame was ACKed. - * @RTL818X_TX_DESC_FLAG_SPLCP: Use short preamble. - * @RTL818X_TX_DESC_FLAG_MOREFRAG: More fragments follow. - * @RTL818X_TX_DESC_FLAG_CTS: Use CTS-to-self protection. - * @RTL818X_TX_DESC_FLAG_RTS: Use RTS/CTS protection. - * @RTL818X_TX_DESC_FLAG_LS: Last segment of the frame. - * @RTL818X_TX_DESC_FLAG_FS: First segment of the frame. - */ -enum rtl818x_tx_desc_flags { - RTL818X_TX_DESC_FLAG_NO_ENC = (1 << 15), - RTL818X_TX_DESC_FLAG_TX_OK = (1 << 15), - RTL818X_TX_DESC_FLAG_SPLCP = (1 << 16), - RTL818X_TX_DESC_FLAG_RX_UNDER = (1 << 16), - RTL818X_TX_DESC_FLAG_MOREFRAG = (1 << 17), - RTL818X_TX_DESC_FLAG_CTS = (1 << 18), - RTL818X_TX_DESC_FLAG_RTS = (1 << 23), - RTL818X_TX_DESC_FLAG_LS = (1 << 28), - RTL818X_TX_DESC_FLAG_FS = (1 << 29), - RTL818X_TX_DESC_FLAG_DMA = (1 << 30), - RTL818X_TX_DESC_FLAG_OWN = (1 << 31) -}; - -enum rtl818x_rx_desc_flags { - RTL818X_RX_DESC_FLAG_ICV_ERR = (1 << 12), - RTL818X_RX_DESC_FLAG_CRC32_ERR = (1 << 13), - RTL818X_RX_DESC_FLAG_PM = (1 << 14), - RTL818X_RX_DESC_FLAG_RX_ERR = (1 << 15), - RTL818X_RX_DESC_FLAG_BCAST = (1 << 16), - RTL818X_RX_DESC_FLAG_PAM = (1 << 17), - RTL818X_RX_DESC_FLAG_MCAST = (1 << 18), - RTL818X_RX_DESC_FLAG_QOS = (1 << 19), /* RTL8187(B) only */ - RTL818X_RX_DESC_FLAG_TRSW = (1 << 24), /* RTL8187(B) only */ - RTL818X_RX_DESC_FLAG_SPLCP = (1 << 25), - RTL818X_RX_DESC_FLAG_FOF = (1 << 26), - RTL818X_RX_DESC_FLAG_DMA_FAIL = (1 << 27), - RTL818X_RX_DESC_FLAG_LS = (1 << 28), - RTL818X_RX_DESC_FLAG_FS = (1 << 29), - RTL818X_RX_DESC_FLAG_EOR = (1 << 30), - RTL818X_RX_DESC_FLAG_OWN = (1 << 31) -}; - -#endif /* RTL818X_H */ diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig deleted file mode 100644 index 73067cac289c..000000000000 --- a/drivers/net/wireless/rtlwifi/Kconfig +++ /dev/null @@ -1,154 +0,0 @@ -menuconfig RTL_CARDS - tristate "Realtek rtlwifi family of devices" - depends on MAC80211 && (PCI || USB) - default y - ---help--- - This option will enable support for the Realtek mac80211-based - wireless drivers. Drivers rtl8192ce, rtl8192cu, rtl8192se, rtl8192de, - rtl8723ae, rtl8723be, rtl8188ee, rtl8192ee, and rtl8821ae share - some common code. - -if RTL_CARDS - -config RTL8192CE - tristate "Realtek RTL8192CE/RTL8188CE Wireless Network Adapter" - depends on PCI - select RTL8192C_COMMON - select RTLWIFI - select RTLWIFI_PCI - ---help--- - This is the driver for Realtek RTL8192CE/RTL8188CE 802.11n PCIe - wireless network adapters. - - If you choose to build it as a module, it will be called rtl8192ce - -config RTL8192SE - tristate "Realtek RTL8192SE/RTL8191SE PCIe Wireless Network Adapter" - depends on PCI - select RTLWIFI - select RTLWIFI_PCI - ---help--- - This is the driver for Realtek RTL8192SE/RTL8191SE 802.11n PCIe - wireless network adapters. - - If you choose to build it as a module, it will be called rtl8192se - -config RTL8192DE - tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter" - depends on PCI - select RTLWIFI - select RTLWIFI_PCI - ---help--- - This is the driver for Realtek RTL8192DE/RTL8188DE 802.11n PCIe - wireless network adapters. - - If you choose to build it as a module, it will be called rtl8192de - -config RTL8723AE - tristate "Realtek RTL8723AE PCIe Wireless Network Adapter" - depends on PCI - select RTLWIFI - select RTLWIFI_PCI - select RTL8723_COMMON - select RTLBTCOEXIST - ---help--- - This is the driver for Realtek RTL8723AE 802.11n PCIe - wireless network adapters. - - If you choose to build it as a module, it will be called rtl8723ae - -config RTL8723BE - tristate "Realtek RTL8723BE PCIe Wireless Network Adapter" - depends on PCI - select RTLWIFI - select RTLWIFI_PCI - select RTL8723_COMMON - select RTLBTCOEXIST - ---help--- - This is the driver for Realtek RTL8723BE 802.11n PCIe - wireless network adapters. - - If you choose to build it as a module, it will be called rtl8723be - -config RTL8188EE - tristate "Realtek RTL8188EE Wireless Network Adapter" - depends on PCI - select RTLWIFI - select RTLWIFI_PCI - ---help--- - This is the driver for Realtek RTL8188EE 802.11n PCIe - wireless network adapters. - - If you choose to build it as a module, it will be called rtl8188ee - -config RTL8192EE - tristate "Realtek RTL8192EE Wireless Network Adapter" - depends on PCI - select RTLWIFI - select RTLWIFI_PCI - select RTLBTCOEXIST - ---help--- - This is the driver for Realtek RTL8192EE 802.11n PCIe - wireless network adapters. - - If you choose to build it as a module, it will be called rtl8192ee - -config RTL8821AE - tristate "Realtek RTL8821AE/RTL8812AE Wireless Network Adapter" - depends on PCI - select RTLWIFI - select RTLWIFI_PCI - select RTLBTCOEXIST - ---help--- - This is the driver for Realtek RTL8821AE/RTL8812AE 802.11ac PCIe - wireless network adapters. - - If you choose to build it as a module, it will be called rtl8821ae - -config RTL8192CU - tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter" - depends on USB - select RTLWIFI - select RTLWIFI_USB - select RTL8192C_COMMON - ---help--- - This is the driver for Realtek RTL8192CU/RTL8188CU 802.11n USB - wireless network adapters. - - If you choose to build it as a module, it will be called rtl8192cu - -config RTLWIFI - tristate - select FW_LOADER - -config RTLWIFI_PCI - tristate - -config RTLWIFI_USB - tristate - -config RTLWIFI_DEBUG - bool "Debugging output for rtlwifi driver family" - depends on RTLWIFI - default y - ---help--- - To use the module option that sets the dynamic-debugging level for, - the front-end driver, this parameter must be "Y". For memory-limited - systems, choose "N". If in doubt, choose "Y". - -config RTL8192C_COMMON - tristate - depends on RTL8192CE || RTL8192CU - default y - -config RTL8723_COMMON - tristate - depends on RTL8723AE || RTL8723BE - default y - -config RTLBTCOEXIST - tristate - depends on RTL8723AE || RTL8723BE || RTL8821AE || RTL8192EE - default y - -endif diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile deleted file mode 100644 index ad6d3c52ec57..000000000000 --- a/drivers/net/wireless/rtlwifi/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -obj-$(CONFIG_RTLWIFI) += rtlwifi.o -rtlwifi-objs := \ - base.o \ - cam.o \ - core.o \ - debug.o \ - efuse.o \ - ps.o \ - rc.o \ - regd.o \ - stats.o - -rtl8192c_common-objs += \ - -obj-$(CONFIG_RTLWIFI_PCI) += rtl_pci.o -rtl_pci-objs := pci.o - -obj-$(CONFIG_RTLWIFI_USB) += rtl_usb.o -rtl_usb-objs := usb.o - -obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c/ -obj-$(CONFIG_RTL8192CE) += rtl8192ce/ -obj-$(CONFIG_RTL8192CU) += rtl8192cu/ -obj-$(CONFIG_RTL8192SE) += rtl8192se/ -obj-$(CONFIG_RTL8192DE) += rtl8192de/ -obj-$(CONFIG_RTL8723AE) += rtl8723ae/ -obj-$(CONFIG_RTL8723BE) += rtl8723be/ -obj-$(CONFIG_RTL8188EE) += rtl8188ee/ -obj-$(CONFIG_RTLBTCOEXIST) += btcoexist/ -obj-$(CONFIG_RTL8723_COMMON) += rtl8723com/ -obj-$(CONFIG_RTL8821AE) += rtl8821ae/ -obj-$(CONFIG_RTL8192EE) += rtl8192ee/ - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c deleted file mode 100644 index 0517a4f2d3f2..000000000000 --- a/drivers/net/wireless/rtlwifi/base.c +++ /dev/null @@ -1,2176 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "wifi.h" -#include "rc.h" -#include "base.h" -#include "efuse.h" -#include "cam.h" -#include "ps.h" -#include "regd.h" -#include "pci.h" -#include -#include -#include - -/* - *NOTICE!!!: This file will be very big, we should - *keep it clear under following roles: - * - *This file include following parts, so, if you add new - *functions into this file, please check which part it - *should includes. or check if you should add new part - *for this file: - * - *1) mac80211 init functions - *2) tx information functions - *3) functions called by core.c - *4) wq & timer callback functions - *5) frame process functions - *6) IOT functions - *7) sysfs functions - *8) vif functions - *9) ... - */ - -/********************************************************* - * - * mac80211 init functions - * - *********************************************************/ -static struct ieee80211_channel rtl_channeltable_2g[] = { - {.center_freq = 2412, .hw_value = 1,}, - {.center_freq = 2417, .hw_value = 2,}, - {.center_freq = 2422, .hw_value = 3,}, - {.center_freq = 2427, .hw_value = 4,}, - {.center_freq = 2432, .hw_value = 5,}, - {.center_freq = 2437, .hw_value = 6,}, - {.center_freq = 2442, .hw_value = 7,}, - {.center_freq = 2447, .hw_value = 8,}, - {.center_freq = 2452, .hw_value = 9,}, - {.center_freq = 2457, .hw_value = 10,}, - {.center_freq = 2462, .hw_value = 11,}, - {.center_freq = 2467, .hw_value = 12,}, - {.center_freq = 2472, .hw_value = 13,}, - {.center_freq = 2484, .hw_value = 14,}, -}; - -static struct ieee80211_channel rtl_channeltable_5g[] = { - {.center_freq = 5180, .hw_value = 36,}, - {.center_freq = 5200, .hw_value = 40,}, - {.center_freq = 5220, .hw_value = 44,}, - {.center_freq = 5240, .hw_value = 48,}, - {.center_freq = 5260, .hw_value = 52,}, - {.center_freq = 5280, .hw_value = 56,}, - {.center_freq = 5300, .hw_value = 60,}, - {.center_freq = 5320, .hw_value = 64,}, - {.center_freq = 5500, .hw_value = 100,}, - {.center_freq = 5520, .hw_value = 104,}, - {.center_freq = 5540, .hw_value = 108,}, - {.center_freq = 5560, .hw_value = 112,}, - {.center_freq = 5580, .hw_value = 116,}, - {.center_freq = 5600, .hw_value = 120,}, - {.center_freq = 5620, .hw_value = 124,}, - {.center_freq = 5640, .hw_value = 128,}, - {.center_freq = 5660, .hw_value = 132,}, - {.center_freq = 5680, .hw_value = 136,}, - {.center_freq = 5700, .hw_value = 140,}, - {.center_freq = 5745, .hw_value = 149,}, - {.center_freq = 5765, .hw_value = 153,}, - {.center_freq = 5785, .hw_value = 157,}, - {.center_freq = 5805, .hw_value = 161,}, - {.center_freq = 5825, .hw_value = 165,}, -}; - -static struct ieee80211_rate rtl_ratetable_2g[] = { - {.bitrate = 10, .hw_value = 0x00,}, - {.bitrate = 20, .hw_value = 0x01,}, - {.bitrate = 55, .hw_value = 0x02,}, - {.bitrate = 110, .hw_value = 0x03,}, - {.bitrate = 60, .hw_value = 0x04,}, - {.bitrate = 90, .hw_value = 0x05,}, - {.bitrate = 120, .hw_value = 0x06,}, - {.bitrate = 180, .hw_value = 0x07,}, - {.bitrate = 240, .hw_value = 0x08,}, - {.bitrate = 360, .hw_value = 0x09,}, - {.bitrate = 480, .hw_value = 0x0a,}, - {.bitrate = 540, .hw_value = 0x0b,}, -}; - -static struct ieee80211_rate rtl_ratetable_5g[] = { - {.bitrate = 60, .hw_value = 0x04,}, - {.bitrate = 90, .hw_value = 0x05,}, - {.bitrate = 120, .hw_value = 0x06,}, - {.bitrate = 180, .hw_value = 0x07,}, - {.bitrate = 240, .hw_value = 0x08,}, - {.bitrate = 360, .hw_value = 0x09,}, - {.bitrate = 480, .hw_value = 0x0a,}, - {.bitrate = 540, .hw_value = 0x0b,}, -}; - -static const struct ieee80211_supported_band rtl_band_2ghz = { - .band = IEEE80211_BAND_2GHZ, - - .channels = rtl_channeltable_2g, - .n_channels = ARRAY_SIZE(rtl_channeltable_2g), - - .bitrates = rtl_ratetable_2g, - .n_bitrates = ARRAY_SIZE(rtl_ratetable_2g), - - .ht_cap = {0}, -}; - -static struct ieee80211_supported_band rtl_band_5ghz = { - .band = IEEE80211_BAND_5GHZ, - - .channels = rtl_channeltable_5g, - .n_channels = ARRAY_SIZE(rtl_channeltable_5g), - - .bitrates = rtl_ratetable_5g, - .n_bitrates = ARRAY_SIZE(rtl_ratetable_5g), - - .ht_cap = {0}, -}; - -static const u8 tid_to_ac[] = { - 2, /* IEEE80211_AC_BE */ - 3, /* IEEE80211_AC_BK */ - 3, /* IEEE80211_AC_BK */ - 2, /* IEEE80211_AC_BE */ - 1, /* IEEE80211_AC_VI */ - 1, /* IEEE80211_AC_VI */ - 0, /* IEEE80211_AC_VO */ - 0, /* IEEE80211_AC_VO */ -}; - -u8 rtl_tid_to_ac(u8 tid) -{ - return tid_to_ac[tid]; -} -EXPORT_SYMBOL_GPL(rtl_tid_to_ac); - -static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw, - struct ieee80211_sta_ht_cap *ht_cap) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - ht_cap->ht_supported = true; - ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU; - - if (rtlpriv->rtlhal.disable_amsdu_8k) - ht_cap->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; - - /* - *Maximum length of AMPDU that the STA can receive. - *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) - */ - ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - - /*Minimum MPDU start spacing , */ - ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; - - ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - - /*hw->wiphy->bands[IEEE80211_BAND_2GHZ] - *base on ant_num - *rx_mask: RX mask - *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7 - *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15 - *if rx_ant >= 3 rx_mask[2]= 0xff; - *if BW_40 rx_mask[4]= 0x01; - *highest supported RX rate - */ - if (rtlpriv->dm.supp_phymode_switch) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, - "Support phy mode switch\n"); - - ht_cap->mcs.rx_mask[0] = 0xFF; - ht_cap->mcs.rx_mask[1] = 0xFF; - ht_cap->mcs.rx_mask[4] = 0x01; - - ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); - } else { - if (get_rf_type(rtlphy) == RF_1T2R || - get_rf_type(rtlphy) == RF_2T2R) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "1T2R or 2T2R\n"); - ht_cap->mcs.rx_mask[0] = 0xFF; - ht_cap->mcs.rx_mask[1] = 0xFF; - ht_cap->mcs.rx_mask[4] = 0x01; - - ht_cap->mcs.rx_highest = - cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15); - } else if (get_rf_type(rtlphy) == RF_1T1R) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n"); - - ht_cap->mcs.rx_mask[0] = 0xFF; - ht_cap->mcs.rx_mask[1] = 0x00; - ht_cap->mcs.rx_mask[4] = 0x01; - - ht_cap->mcs.rx_highest = - cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7); - } - } -} - -static void _rtl_init_hw_vht_capab(struct ieee80211_hw *hw, - struct ieee80211_sta_vht_cap *vht_cap) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - u16 mcs_map; - - vht_cap->vht_supported = true; - vht_cap->cap = - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 | - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | - IEEE80211_VHT_CAP_SHORT_GI_80 | - IEEE80211_VHT_CAP_TXSTBC | - IEEE80211_VHT_CAP_RXSTBC_1 | - IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | - IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | - IEEE80211_VHT_CAP_HTC_VHT | - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | - IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | - IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | - 0; - - mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | - IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; - - vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); - vht_cap->vht_mcs.rx_highest = - cpu_to_le16(MAX_BIT_RATE_SHORT_GI_2NSS_80MHZ_MCS9); - vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); - vht_cap->vht_mcs.tx_highest = - cpu_to_le16(MAX_BIT_RATE_SHORT_GI_2NSS_80MHZ_MCS9); - } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - u16 mcs_map; - - vht_cap->vht_supported = true; - vht_cap->cap = - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 | - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 | - IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | - IEEE80211_VHT_CAP_SHORT_GI_80 | - IEEE80211_VHT_CAP_TXSTBC | - IEEE80211_VHT_CAP_RXSTBC_1 | - IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | - IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | - IEEE80211_VHT_CAP_HTC_VHT | - IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | - IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | - IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN | - 0; - - mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | - IEEE80211_VHT_MCS_NOT_SUPPORTED << 14; - - vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); - vht_cap->vht_mcs.rx_highest = - cpu_to_le16(MAX_BIT_RATE_SHORT_GI_1NSS_80MHZ_MCS9); - vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); - vht_cap->vht_mcs.tx_highest = - cpu_to_le16(MAX_BIT_RATE_SHORT_GI_1NSS_80MHZ_MCS9); - } -} - -static void _rtl_init_mac80211(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct ieee80211_supported_band *sband; - - if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && - rtlhal->bandset == BAND_ON_BOTH) { - /* 1: 2.4 G bands */ - /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); - - /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] - * to default value(1T1R) */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz, - sizeof(struct ieee80211_supported_band)); - - /* <3> init ht cap base on ant_num */ - _rtl_init_hw_ht_capab(hw, &sband->ht_cap); - - /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; - - /* 2: 5 G bands */ - /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); - - /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] - * to default value(1T1R) */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), &rtl_band_5ghz, - sizeof(struct ieee80211_supported_band)); - - /* <3> init ht cap base on ant_num */ - _rtl_init_hw_ht_capab(hw, &sband->ht_cap); - - _rtl_init_hw_vht_capab(hw, &sband->vht_cap); - /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; - } else { - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]); - - /* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ] - * to default value(1T1R) */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), - &rtl_band_2ghz, - sizeof(struct ieee80211_supported_band)); - - /* <3> init ht cap base on ant_num */ - _rtl_init_hw_ht_capab(hw, &sband->ht_cap); - - /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; - } else if (rtlhal->current_bandtype == BAND_ON_5G) { - /* <1> use mac->bands as mem for hw->wiphy->bands */ - sband = &(rtlmac->bands[IEEE80211_BAND_5GHZ]); - - /* <2> set hw->wiphy->bands[IEEE80211_BAND_5GHZ] - * to default value(1T1R) */ - memcpy(&(rtlmac->bands[IEEE80211_BAND_5GHZ]), - &rtl_band_5ghz, - sizeof(struct ieee80211_supported_band)); - - /* <3> init ht cap base on ant_num */ - _rtl_init_hw_ht_capab(hw, &sband->ht_cap); - - _rtl_init_hw_vht_capab(hw, &sband->vht_cap); - /* <4> set mac->sband to wiphy->sband */ - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Err BAND %d\n", - rtlhal->current_bandtype); - } - } - /* <5> set hw caps */ - ieee80211_hw_set(hw, SIGNAL_DBM); - ieee80211_hw_set(hw, RX_INCLUDES_FCS); - ieee80211_hw_set(hw, AMPDU_AGGREGATION); - ieee80211_hw_set(hw, CONNECTION_MONITOR); - ieee80211_hw_set(hw, MFP_CAPABLE); - ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS); - - /* swlps or hwlps has been set in diff chip in init_sw_vars */ - if (rtlpriv->psc.swctrl_lps) { - ieee80211_hw_set(hw, SUPPORTS_PS); - ieee80211_hw_set(hw, PS_NULLFUNC_STACK); - } - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_MESH_POINT) | - BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO); - hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; - - hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - - hw->wiphy->rts_threshold = 2347; - - hw->queues = AC_MAX; - hw->extra_tx_headroom = RTL_TX_HEADER_SIZE; - - /* TODO: Correct this value for our hw */ - /* TODO: define these hard code value */ - hw->max_listen_interval = 10; - hw->max_rate_tries = 4; - /* hw->max_rates = 1; */ - hw->sta_data_size = sizeof(struct rtl_sta_info); - -/* wowlan is not supported by kernel if CONFIG_PM is not defined */ -#ifdef CONFIG_PM - if (rtlpriv->psc.wo_wlan_mode) { - if (rtlpriv->psc.wo_wlan_mode & WAKE_ON_MAGIC_PACKET) - rtlpriv->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT; - if (rtlpriv->psc.wo_wlan_mode & WAKE_ON_PATTERN_MATCH) { - rtlpriv->wowlan.n_patterns = - MAX_SUPPORT_WOL_PATTERN_NUM; - rtlpriv->wowlan.pattern_min_len = MIN_WOL_PATTERN_SIZE; - rtlpriv->wowlan.pattern_max_len = MAX_WOL_PATTERN_SIZE; - } - hw->wiphy->wowlan = &rtlpriv->wowlan; - } -#endif - - /* <6> mac address */ - if (is_valid_ether_addr(rtlefuse->dev_addr)) { - SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr); - } else { - u8 rtlmac1[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 }; - get_random_bytes((rtlmac1 + (ETH_ALEN - 1)), 1); - SET_IEEE80211_PERM_ADDR(hw, rtlmac1); - } -} - -static void _rtl_init_deferred_work(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /* <1> timer */ - setup_timer(&rtlpriv->works.watchdog_timer, - rtl_watch_dog_timer_callback, (unsigned long)hw); - setup_timer(&rtlpriv->works.dualmac_easyconcurrent_retrytimer, - rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw); - /* <2> work queue */ - rtlpriv->works.hw = hw; - rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name); - INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq, - (void *)rtl_watchdog_wq_callback); - INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, - (void *)rtl_ips_nic_off_wq_callback); - INIT_DELAYED_WORK(&rtlpriv->works.ps_work, - (void *)rtl_swlps_wq_callback); - INIT_DELAYED_WORK(&rtlpriv->works.ps_rfon_wq, - (void *)rtl_swlps_rfon_wq_callback); - INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq, - (void *)rtl_fwevt_wq_callback); - -} - -void rtl_deinit_deferred_work(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - del_timer_sync(&rtlpriv->works.watchdog_timer); - - cancel_delayed_work(&rtlpriv->works.watchdog_wq); - cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); - cancel_delayed_work(&rtlpriv->works.ps_work); - cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); - cancel_delayed_work(&rtlpriv->works.fwevt_wq); -} -EXPORT_SYMBOL_GPL(rtl_deinit_deferred_work); - -void rtl_init_rfkill(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - bool radio_state; - bool blocked; - u8 valid = 0; - - /*set init state to on */ - rtlpriv->rfkill.rfkill_state = true; - wiphy_rfkill_set_hw_state(hw->wiphy, 0); - - radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); - - if (valid) { - pr_info("rtlwifi: wireless switch is %s\n", - rtlpriv->rfkill.rfkill_state ? "on" : "off"); - - rtlpriv->rfkill.rfkill_state = radio_state; - - blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1; - wiphy_rfkill_set_hw_state(hw->wiphy, blocked); - } - - wiphy_rfkill_start_polling(hw->wiphy); -} -EXPORT_SYMBOL(rtl_init_rfkill); - -void rtl_deinit_rfkill(struct ieee80211_hw *hw) -{ - wiphy_rfkill_stop_polling(hw->wiphy); -} -EXPORT_SYMBOL_GPL(rtl_deinit_rfkill); - -int rtl_init_core(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); - - /* <1> init mac80211 */ - _rtl_init_mac80211(hw); - rtlmac->hw = hw; - - /* <2> rate control register */ - hw->rate_control_algorithm = "rtl_rc"; - - /* - * <3> init CRDA must come after init - * mac80211 hw in _rtl_init_mac80211. - */ - if (rtl_regd_init(hw, rtl_reg_notifier)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "REGD init failed\n"); - return 1; - } - - /* <4> locks */ - mutex_init(&rtlpriv->locks.conf_mutex); - spin_lock_init(&rtlpriv->locks.ips_lock); - spin_lock_init(&rtlpriv->locks.irq_th_lock); - spin_lock_init(&rtlpriv->locks.h2c_lock); - spin_lock_init(&rtlpriv->locks.rf_ps_lock); - spin_lock_init(&rtlpriv->locks.rf_lock); - spin_lock_init(&rtlpriv->locks.waitq_lock); - spin_lock_init(&rtlpriv->locks.entry_list_lock); - spin_lock_init(&rtlpriv->locks.cck_and_rw_pagea_lock); - spin_lock_init(&rtlpriv->locks.check_sendpkt_lock); - spin_lock_init(&rtlpriv->locks.fw_ps_lock); - spin_lock_init(&rtlpriv->locks.lps_lock); - spin_lock_init(&rtlpriv->locks.iqk_lock); - /* <5> init list */ - INIT_LIST_HEAD(&rtlpriv->entry_list); - - rtlmac->link_state = MAC80211_NOLINK; - - /* <6> init deferred work */ - _rtl_init_deferred_work(hw); - - return 0; -} -EXPORT_SYMBOL_GPL(rtl_init_core); - -void rtl_deinit_core(struct ieee80211_hw *hw) -{ -} -EXPORT_SYMBOL_GPL(rtl_deinit_core); - -void rtl_init_rx_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf)); -} -EXPORT_SYMBOL_GPL(rtl_init_rx_config); - -/********************************************************* - * - * tx information functions - * - *********************************************************/ -static void _rtl_qurey_shortpreamble_mode(struct ieee80211_hw *hw, - struct rtl_tcb_desc *tcb_desc, - struct ieee80211_tx_info *info) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 rate_flag = info->control.rates[0].flags; - - tcb_desc->use_shortpreamble = false; - - /* 1M can only use Long Preamble. 11B spec */ - if (tcb_desc->hw_rate == rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M]) - return; - else if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - tcb_desc->use_shortpreamble = true; - - return; -} - -static void _rtl_query_shortgi(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - struct rtl_tcb_desc *tcb_desc, - struct ieee80211_tx_info *info) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 rate_flag = info->control.rates[0].flags; - u8 sgi_40 = 0, sgi_20 = 0, bw_40 = 0; - u8 sgi_80 = 0, bw_80 = 0; - tcb_desc->use_shortgi = false; - - if (sta == NULL) - return; - - sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; - sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; - sgi_80 = sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80; - - if ((!sta->ht_cap.ht_supported) && (!sta->vht_cap.vht_supported)) - return; - - if (!sgi_40 && !sgi_20) - return; - - if (mac->opmode == NL80211_IFTYPE_STATION) { - bw_40 = mac->bw_40; - bw_80 = mac->bw_80; - } else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; - bw_80 = sta->vht_cap.vht_supported; - } - - if (bw_80) { - if (sgi_80) - tcb_desc->use_shortgi = true; - else - tcb_desc->use_shortgi = false; - } else { - if (bw_40 && sgi_40) - tcb_desc->use_shortgi = true; - else if (!bw_40 && sgi_20) - tcb_desc->use_shortgi = true; - } - - if (!(rate_flag & IEEE80211_TX_RC_SHORT_GI)) - tcb_desc->use_shortgi = false; -} - -static void _rtl_query_protection_mode(struct ieee80211_hw *hw, - struct rtl_tcb_desc *tcb_desc, - struct ieee80211_tx_info *info) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 rate_flag = info->control.rates[0].flags; - - /* Common Settings */ - tcb_desc->rts_stbc = false; - tcb_desc->cts_enable = false; - tcb_desc->rts_sc = 0; - tcb_desc->rts_bw = false; - tcb_desc->rts_use_shortpreamble = false; - tcb_desc->rts_use_shortgi = false; - - if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT) { - /* Use CTS-to-SELF in protection mode. */ - tcb_desc->rts_enable = true; - tcb_desc->cts_enable = true; - tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; - } else if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) { - /* Use RTS-CTS in protection mode. */ - tcb_desc->rts_enable = true; - tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M]; - } -} - -static void _rtl_txrate_selectmode(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - struct rtl_tcb_desc *tcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - u8 ratr_index = 7; - - if (sta) { - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - ratr_index = sta_entry->ratr_index; - } - if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) { - if (mac->opmode == NL80211_IFTYPE_STATION) { - tcb_desc->ratr_index = 0; - } else if (mac->opmode == NL80211_IFTYPE_ADHOC || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - if (tcb_desc->multicast || tcb_desc->broadcast) { - tcb_desc->hw_rate = - rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M]; - tcb_desc->use_driver_rate = 1; - tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; - } else { - tcb_desc->ratr_index = ratr_index; - } - } else if (mac->opmode == NL80211_IFTYPE_AP) { - tcb_desc->ratr_index = ratr_index; - } - } - - if (rtlpriv->dm.useramask) { - tcb_desc->ratr_index = ratr_index; - /* TODO we will differentiate adhoc and station future */ - if (mac->opmode == NL80211_IFTYPE_STATION || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - tcb_desc->mac_id = 0; - - if (mac->mode == WIRELESS_MODE_AC_5G) - tcb_desc->ratr_index = - RATR_INX_WIRELESS_AC_5N; - else if (mac->mode == WIRELESS_MODE_AC_24G) - tcb_desc->ratr_index = - RATR_INX_WIRELESS_AC_24N; - else if (mac->mode == WIRELESS_MODE_N_24G) - tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB; - else if (mac->mode == WIRELESS_MODE_N_5G) - tcb_desc->ratr_index = RATR_INX_WIRELESS_NG; - else if (mac->mode & WIRELESS_MODE_G) - tcb_desc->ratr_index = RATR_INX_WIRELESS_GB; - else if (mac->mode & WIRELESS_MODE_B) - tcb_desc->ratr_index = RATR_INX_WIRELESS_B; - else if (mac->mode & WIRELESS_MODE_A) - tcb_desc->ratr_index = RATR_INX_WIRELESS_G; - - } else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - if (NULL != sta) { - if (sta->aid > 0) - tcb_desc->mac_id = sta->aid + 1; - else - tcb_desc->mac_id = 1; - } else { - tcb_desc->mac_id = 0; - } - } - } -} - -static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - struct rtl_tcb_desc *tcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - tcb_desc->packet_bw = false; - if (!sta) - return; - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - if (!(sta->ht_cap.ht_supported) || - !(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) - return; - } else if (mac->opmode == NL80211_IFTYPE_STATION) { - if (!mac->bw_40 || !(sta->ht_cap.ht_supported)) - return; - } - if (tcb_desc->multicast || tcb_desc->broadcast) - return; - - /*use legency rate, shall use 20MHz */ - if (tcb_desc->hw_rate <= rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]) - return; - - tcb_desc->packet_bw = HT_CHANNEL_WIDTH_20_40; - - if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE || - rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8821AE) { - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - if (!(sta->vht_cap.vht_supported)) - return; - } else if (mac->opmode == NL80211_IFTYPE_STATION) { - if (!mac->bw_80 || - !(sta->vht_cap.vht_supported)) - return; - } - if (tcb_desc->hw_rate <= - rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15]) - return; - tcb_desc->packet_bw = HT_CHANNEL_WIDTH_80; - } -} - -static u8 _rtl_get_vht_highest_n_rate(struct ieee80211_hw *hw, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u8 hw_rate; - u16 tx_mcs_map = le16_to_cpu(sta->vht_cap.vht_mcs.tx_mcs_map); - - if ((get_rf_type(rtlphy) == RF_2T2R) && - (tx_mcs_map & 0x000c) != 0x000c) { - if ((tx_mcs_map & 0x000c) >> 2 == - IEEE80211_VHT_MCS_SUPPORT_0_7) - hw_rate = - rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS7]; - else if ((tx_mcs_map & 0x000c) >> 2 == - IEEE80211_VHT_MCS_SUPPORT_0_8) - hw_rate = - rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS9]; - else - hw_rate = - rtlpriv->cfg->maps[RTL_RC_VHT_RATE_2SS_MCS9]; - } else { - if ((tx_mcs_map & 0x0003) == - IEEE80211_VHT_MCS_SUPPORT_0_7) - hw_rate = - rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS7]; - else if ((tx_mcs_map & 0x0003) == - IEEE80211_VHT_MCS_SUPPORT_0_8) - hw_rate = - rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS9]; - else - hw_rate = - rtlpriv->cfg->maps[RTL_RC_VHT_RATE_1SS_MCS9]; - } - - return hw_rate; -} - -static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 hw_rate; - - if ((get_rf_type(rtlphy) == RF_2T2R) && - (sta->ht_cap.mcs.rx_mask[1] != 0)) - hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15]; - else - hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS7]; - - return hw_rate; -} - -/* mac80211's rate_idx is like this: - * - * 2.4G band:rx_status->band == IEEE80211_BAND_2GHZ - * - * B/G rate: - * (rx_status->flag & RX_FLAG_HT) = 0, - * DESC_RATE1M-->DESC_RATE54M ==> idx is 0-->11, - * - * N rate: - * (rx_status->flag & RX_FLAG_HT) = 1, - * DESC_RATEMCS0-->DESC_RATEMCS15 ==> idx is 0-->15 - * - * 5G band:rx_status->band == IEEE80211_BAND_5GHZ - * A rate: - * (rx_status->flag & RX_FLAG_HT) = 0, - * DESC_RATE6M-->DESC_RATE54M ==> idx is 0-->7, - * - * N rate: - * (rx_status->flag & RX_FLAG_HT) = 1, - * DESC_RATEMCS0-->DESC_RATEMCS15 ==> idx is 0-->15 - * - * VHT rates: - * DESC_RATEVHT1SS_MCS0-->DESC_RATEVHT1SS_MCS9 ==> idx is 0-->9 - * DESC_RATEVHT2SS_MCS0-->DESC_RATEVHT2SS_MCS9 ==> idx is 0-->9 - */ -int rtlwifi_rate_mapping(struct ieee80211_hw *hw, bool isht, bool isvht, - u8 desc_rate) -{ - int rate_idx; - - if (isvht) { - switch (desc_rate) { - case DESC_RATEVHT1SS_MCS0: - rate_idx = 0; - break; - case DESC_RATEVHT1SS_MCS1: - rate_idx = 1; - break; - case DESC_RATEVHT1SS_MCS2: - rate_idx = 2; - break; - case DESC_RATEVHT1SS_MCS3: - rate_idx = 3; - break; - case DESC_RATEVHT1SS_MCS4: - rate_idx = 4; - break; - case DESC_RATEVHT1SS_MCS5: - rate_idx = 5; - break; - case DESC_RATEVHT1SS_MCS6: - rate_idx = 6; - break; - case DESC_RATEVHT1SS_MCS7: - rate_idx = 7; - break; - case DESC_RATEVHT1SS_MCS8: - rate_idx = 8; - break; - case DESC_RATEVHT1SS_MCS9: - rate_idx = 9; - break; - case DESC_RATEVHT2SS_MCS0: - rate_idx = 0; - break; - case DESC_RATEVHT2SS_MCS1: - rate_idx = 1; - break; - case DESC_RATEVHT2SS_MCS2: - rate_idx = 2; - break; - case DESC_RATEVHT2SS_MCS3: - rate_idx = 3; - break; - case DESC_RATEVHT2SS_MCS4: - rate_idx = 4; - break; - case DESC_RATEVHT2SS_MCS5: - rate_idx = 5; - break; - case DESC_RATEVHT2SS_MCS6: - rate_idx = 6; - break; - case DESC_RATEVHT2SS_MCS7: - rate_idx = 7; - break; - case DESC_RATEVHT2SS_MCS8: - rate_idx = 8; - break; - case DESC_RATEVHT2SS_MCS9: - rate_idx = 9; - break; - default: - rate_idx = 0; - break; - } - return rate_idx; - } - if (false == isht) { - if (IEEE80211_BAND_2GHZ == hw->conf.chandef.chan->band) { - switch (desc_rate) { - case DESC_RATE1M: - rate_idx = 0; - break; - case DESC_RATE2M: - rate_idx = 1; - break; - case DESC_RATE5_5M: - rate_idx = 2; - break; - case DESC_RATE11M: - rate_idx = 3; - break; - case DESC_RATE6M: - rate_idx = 4; - break; - case DESC_RATE9M: - rate_idx = 5; - break; - case DESC_RATE12M: - rate_idx = 6; - break; - case DESC_RATE18M: - rate_idx = 7; - break; - case DESC_RATE24M: - rate_idx = 8; - break; - case DESC_RATE36M: - rate_idx = 9; - break; - case DESC_RATE48M: - rate_idx = 10; - break; - case DESC_RATE54M: - rate_idx = 11; - break; - default: - rate_idx = 0; - break; - } - } else { - switch (desc_rate) { - case DESC_RATE6M: - rate_idx = 0; - break; - case DESC_RATE9M: - rate_idx = 1; - break; - case DESC_RATE12M: - rate_idx = 2; - break; - case DESC_RATE18M: - rate_idx = 3; - break; - case DESC_RATE24M: - rate_idx = 4; - break; - case DESC_RATE36M: - rate_idx = 5; - break; - case DESC_RATE48M: - rate_idx = 6; - break; - case DESC_RATE54M: - rate_idx = 7; - break; - default: - rate_idx = 0; - break; - } - } - } else { - switch (desc_rate) { - case DESC_RATEMCS0: - rate_idx = 0; - break; - case DESC_RATEMCS1: - rate_idx = 1; - break; - case DESC_RATEMCS2: - rate_idx = 2; - break; - case DESC_RATEMCS3: - rate_idx = 3; - break; - case DESC_RATEMCS4: - rate_idx = 4; - break; - case DESC_RATEMCS5: - rate_idx = 5; - break; - case DESC_RATEMCS6: - rate_idx = 6; - break; - case DESC_RATEMCS7: - rate_idx = 7; - break; - case DESC_RATEMCS8: - rate_idx = 8; - break; - case DESC_RATEMCS9: - rate_idx = 9; - break; - case DESC_RATEMCS10: - rate_idx = 10; - break; - case DESC_RATEMCS11: - rate_idx = 11; - break; - case DESC_RATEMCS12: - rate_idx = 12; - break; - case DESC_RATEMCS13: - rate_idx = 13; - break; - case DESC_RATEMCS14: - rate_idx = 14; - break; - case DESC_RATEMCS15: - rate_idx = 15; - break; - default: - rate_idx = 0; - break; - } - } - return rate_idx; -} -EXPORT_SYMBOL(rtlwifi_rate_mapping); - -void rtl_get_tcb_desc(struct ieee80211_hw *hw, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = rtl_get_hdr(skb); - struct ieee80211_rate *txrate; - __le16 fc = rtl_get_fc(skb); - - txrate = ieee80211_get_tx_rate(hw, info); - if (txrate) - tcb_desc->hw_rate = txrate->hw_value; - - if (ieee80211_is_data(fc)) { - /* - *we set data rate INX 0 - *in rtl_rc.c if skb is special data or - *mgt which need low data rate. - */ - - /* - *So tcb_desc->hw_rate is just used for - *special data and mgt frames - */ - if (info->control.rates[0].idx == 0 || - ieee80211_is_nullfunc(fc)) { - tcb_desc->use_driver_rate = true; - tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; - - tcb_desc->disable_ratefallback = 1; - } else { - /* - *because hw will nerver use hw_rate - *when tcb_desc->use_driver_rate = false - *so we never set highest N rate here, - *and N rate will all be controlled by FW - *when tcb_desc->use_driver_rate = false - */ - if (sta && sta->vht_cap.vht_supported) { - tcb_desc->hw_rate = - _rtl_get_vht_highest_n_rate(hw, sta); - } else { - if (sta && (sta->ht_cap.ht_supported)) { - tcb_desc->hw_rate = - _rtl_get_highest_n_rate(hw, sta); - } else { - if (rtlmac->mode == WIRELESS_MODE_B) { - tcb_desc->hw_rate = - rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]; - } else { - tcb_desc->hw_rate = - rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M]; - } - } - } - } - - if (is_multicast_ether_addr(ieee80211_get_DA(hdr))) - tcb_desc->multicast = 1; - else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr))) - tcb_desc->broadcast = 1; - - _rtl_txrate_selectmode(hw, sta, tcb_desc); - _rtl_query_bandwidth_mode(hw, sta, tcb_desc); - _rtl_qurey_shortpreamble_mode(hw, tcb_desc, info); - _rtl_query_shortgi(hw, sta, tcb_desc, info); - _rtl_query_protection_mode(hw, tcb_desc, info); - } else { - tcb_desc->use_driver_rate = true; - tcb_desc->ratr_index = RATR_INX_WIRELESS_MC; - tcb_desc->disable_ratefallback = 1; - tcb_desc->mac_id = 0; - tcb_desc->packet_bw = false; - } -} -EXPORT_SYMBOL(rtl_get_tcb_desc); - -bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - __le16 fc = rtl_get_fc(skb); - - if (rtlpriv->dm.supp_phymode_switch && - mac->link_state < MAC80211_LINKED && - (ieee80211_is_auth(fc) || ieee80211_is_probe_req(fc))) { - if (rtlpriv->cfg->ops->chk_switch_dmdp) - rtlpriv->cfg->ops->chk_switch_dmdp(hw); - } - if (ieee80211_is_auth(fc)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n"); - rtl_ips_nic_on(hw); - - mac->link_state = MAC80211_LINKING; - /* Dul mac */ - rtlpriv->phy.need_iqk = true; - - } - - return true; -} -EXPORT_SYMBOL_GPL(rtl_tx_mgmt_proc); - -struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, u8 *sa, - u8 *bssid, u16 tid); - -static void process_agg_start(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u16 tid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_rx_status rx_status = { 0 }; - struct sk_buff *skb_delba = NULL; - - skb_delba = rtl_make_del_ba(hw, hdr->addr2, hdr->addr3, tid); - if (skb_delba) { - rx_status.freq = hw->conf.chandef.chan->center_freq; - rx_status.band = hw->conf.chandef.chan->band; - rx_status.flag |= RX_FLAG_DECRYPTED; - rx_status.flag |= RX_FLAG_MACTIME_START; - rx_status.rate_idx = 0; - rx_status.signal = 50 + 10; - memcpy(IEEE80211_SKB_RXCB(skb_delba), - &rx_status, sizeof(rx_status)); - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, - "fake del\n", - skb_delba->data, - skb_delba->len); - ieee80211_rx_irqsafe(hw, skb_delba); - } -} - -bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = rtl_get_hdr(skb); - struct rtl_priv *rtlpriv = rtl_priv(hw); - __le16 fc = rtl_get_fc(skb); - u8 *act = (u8 *)(((u8 *)skb->data + MAC80211_3ADDR_LEN)); - u8 category; - - if (!ieee80211_is_action(fc)) - return true; - - category = *act; - act++; - switch (category) { - case ACT_CAT_BA: - switch (*act) { - case ACT_ADDBAREQ: - if (mac->act_scanning) - return false; - - RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, - "%s ACT_ADDBAREQ From :%pM\n", - is_tx ? "Tx" : "Rx", hdr->addr2); - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "req\n", - skb->data, skb->len); - if (!is_tx) { - struct ieee80211_sta *sta = NULL; - struct rtl_sta_info *sta_entry = NULL; - struct rtl_tid_data *tid_data; - struct ieee80211_mgmt *mgmt = (void *)skb->data; - u16 capab = 0, tid = 0; - - rcu_read_lock(); - sta = rtl_find_sta(hw, hdr->addr3); - if (sta == NULL) { - RT_TRACE(rtlpriv, COMP_SEND | COMP_RECV, - DBG_DMESG, "sta is NULL\n"); - rcu_read_unlock(); - return true; - } - - sta_entry = - (struct rtl_sta_info *)sta->drv_priv; - if (!sta_entry) { - rcu_read_unlock(); - return true; - } - capab = - le16_to_cpu(mgmt->u.action.u.addba_req.capab); - tid = (capab & - IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; - tid_data = &sta_entry->tids[tid]; - if (tid_data->agg.rx_agg_state == - RTL_RX_AGG_START) - process_agg_start(hw, hdr, tid); - rcu_read_unlock(); - } - break; - case ACT_ADDBARSP: - RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, - "%s ACT_ADDBARSP From :%pM\n", - is_tx ? "Tx" : "Rx", hdr->addr2); - break; - case ACT_DELBA: - RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, - "ACT_ADDBADEL From :%pM\n", hdr->addr2); - break; - } - break; - default: - break; - } - - return true; -} -EXPORT_SYMBOL_GPL(rtl_action_proc); - -static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc) -{ - rtlpriv->ra.is_special_data = true; - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_special_packet_notify( - rtlpriv, 1); - rtlpriv->enter_ps = false; - schedule_work(&rtlpriv->works.lps_change_work); - ppsc->last_delaylps_stamp_jiffies = jiffies; -} - -/*should call before software enc*/ -u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx, - bool is_enc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - __le16 fc = rtl_get_fc(skb); - u16 ether_type; - u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); - u8 encrypt_header_len = 0; - u8 offset; - const struct iphdr *ip; - - if (!ieee80211_is_data(fc)) - goto end; - - switch (rtlpriv->sec.pairwise_enc_algorithm) { - case WEP40_ENCRYPTION: - case WEP104_ENCRYPTION: - encrypt_header_len = 4;/*WEP_IV_LEN*/ - break; - case TKIP_ENCRYPTION: - encrypt_header_len = 8;/*TKIP_IV_LEN*/ - break; - case AESCCMP_ENCRYPTION: - encrypt_header_len = 8;/*CCMP_HDR_LEN;*/ - break; - default: - break; - } - - offset = mac_hdr_len + SNAP_SIZE; - if (is_enc) - offset += encrypt_header_len; - ether_type = be16_to_cpup((__be16 *)(skb->data + offset)); - - if (ETH_P_IP == ether_type) { - ip = (struct iphdr *)((u8 *)skb->data + offset + - PROTOC_TYPE_SIZE); - if (IPPROTO_UDP == ip->protocol) { - struct udphdr *udp = (struct udphdr *)((u8 *)ip + - (ip->ihl << 2)); - if (((((u8 *)udp)[1] == 68) && - (((u8 *)udp)[3] == 67)) || - ((((u8 *)udp)[1] == 67) && - (((u8 *)udp)[3] == 68))) { - /* 68 : UDP BOOTP client - * 67 : UDP BOOTP server - */ - RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), - DBG_DMESG, "dhcp %s !!\n", - (is_tx) ? "Tx" : "Rx"); - - if (is_tx) - setup_arp_tx(rtlpriv, ppsc); - return true; - } - } - } else if (ETH_P_ARP == ether_type) { - if (is_tx) - setup_arp_tx(rtlpriv, ppsc); - - return true; - } else if (ETH_P_PAE == ether_type) { - RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, - "802.1X %s EAPOL pkt!!\n", (is_tx) ? "Tx" : "Rx"); - - if (is_tx) { - rtlpriv->ra.is_special_data = true; - rtlpriv->enter_ps = false; - schedule_work(&rtlpriv->works.lps_change_work); - ppsc->last_delaylps_stamp_jiffies = jiffies; - } - - return true; - } else if (ETH_P_IPV6 == ether_type) { - /* TODO: Handle any IPv6 cases that need special handling. - * For now, always return false - */ - goto end; - } - -end: - rtlpriv->ra.is_special_data = false; - return false; -} -EXPORT_SYMBOL_GPL(rtl_is_special_data); - -/********************************************************* - * - * functions called by core.c - * - *********************************************************/ -int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u16 tid, u16 *ssn) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_tid_data *tid_data; - struct rtl_sta_info *sta_entry = NULL; - - if (sta == NULL) - return -EINVAL; - - if (unlikely(tid >= MAX_TID_COUNT)) - return -EINVAL; - - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - if (!sta_entry) - return -ENXIO; - tid_data = &sta_entry->tids[tid]; - - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, - "on ra = %pM tid = %d seq:%d\n", sta->addr, tid, - tid_data->seq_number); - - *ssn = tid_data->seq_number; - tid_data->agg.agg_state = RTL_AGG_START; - - ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); - return 0; -} - -int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u16 tid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_tid_data *tid_data; - struct rtl_sta_info *sta_entry = NULL; - - if (sta == NULL) - return -EINVAL; - - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, - "on ra = %pM tid = %d\n", sta->addr, tid); - - if (unlikely(tid >= MAX_TID_COUNT)) - return -EINVAL; - - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - tid_data = &sta_entry->tids[tid]; - sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP; - - ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); - return 0; -} - -int rtl_rx_agg_start(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u16 tid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_tid_data *tid_data; - struct rtl_sta_info *sta_entry = NULL; - - if (sta == NULL) - return -EINVAL; - - if (unlikely(tid >= MAX_TID_COUNT)) - return -EINVAL; - - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - if (!sta_entry) - return -ENXIO; - tid_data = &sta_entry->tids[tid]; - - RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG, - "on ra = %pM tid = %d seq:%d\n", sta->addr, tid, - tid_data->seq_number); - - tid_data->agg.rx_agg_state = RTL_RX_AGG_START; - return 0; -} - -int rtl_rx_agg_stop(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u16 tid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_sta_info *sta_entry = NULL; - - if (sta == NULL) - return -EINVAL; - - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, - "on ra = %pM tid = %d\n", sta->addr, tid); - - if (unlikely(tid >= MAX_TID_COUNT)) - return -EINVAL; - - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - sta_entry->tids[tid].agg.rx_agg_state = RTL_RX_AGG_STOP; - - return 0; -} -int rtl_tx_agg_oper(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u16 tid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_sta_info *sta_entry = NULL; - - if (sta == NULL) - return -EINVAL; - - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, - "on ra = %pM tid = %d\n", sta->addr, tid); - - if (unlikely(tid >= MAX_TID_COUNT)) - return -EINVAL; - - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL; - - return 0; -} - -/********************************************************* - * - * wq & timer callback functions - * - *********************************************************/ -/* this function is used for roaming */ -void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - - if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) - return; - - if (rtlpriv->mac80211.link_state < MAC80211_LINKED) - return; - - /* check if this really is a beacon */ - if (!ieee80211_is_beacon(hdr->frame_control) && - !ieee80211_is_probe_resp(hdr->frame_control)) - return; - - /* min. beacon length + FCS_LEN */ - if (skb->len <= 40 + FCS_LEN) - return; - - /* and only beacons from the associated BSSID, please */ - if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid)) - return; - - rtlpriv->link_info.bcn_rx_inperiod++; -} -EXPORT_SYMBOL_GPL(rtl_beacon_statistic); - -void rtl_watchdog_wq_callback(void *data) -{ - struct rtl_works *rtlworks = container_of_dwork_rtl(data, - struct rtl_works, - watchdog_wq); - struct ieee80211_hw *hw = rtlworks->hw; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - bool busytraffic = false; - bool tx_busy_traffic = false; - bool rx_busy_traffic = false; - bool higher_busytraffic = false; - bool higher_busyrxtraffic = false; - u8 idx, tid; - u32 rx_cnt_inp4eriod = 0; - u32 tx_cnt_inp4eriod = 0; - u32 aver_rx_cnt_inperiod = 0; - u32 aver_tx_cnt_inperiod = 0; - u32 aver_tidtx_inperiod[MAX_TID_COUNT] = {0}; - u32 tidtx_inp4eriod[MAX_TID_COUNT] = {0}; - - if (is_hal_stop(rtlhal)) - return; - - /* <1> Determine if action frame is allowed */ - if (mac->link_state > MAC80211_NOLINK) { - if (mac->cnt_after_linked < 20) - mac->cnt_after_linked++; - } else { - mac->cnt_after_linked = 0; - } - - /* <2> to check if traffic busy, if - * busytraffic we don't change channel - */ - if (mac->link_state >= MAC80211_LINKED) { - - /* (1) get aver_rx_cnt_inperiod & aver_tx_cnt_inperiod */ - for (idx = 0; idx <= 2; idx++) { - rtlpriv->link_info.num_rx_in4period[idx] = - rtlpriv->link_info.num_rx_in4period[idx + 1]; - rtlpriv->link_info.num_tx_in4period[idx] = - rtlpriv->link_info.num_tx_in4period[idx + 1]; - } - rtlpriv->link_info.num_rx_in4period[3] = - rtlpriv->link_info.num_rx_inperiod; - rtlpriv->link_info.num_tx_in4period[3] = - rtlpriv->link_info.num_tx_inperiod; - for (idx = 0; idx <= 3; idx++) { - rx_cnt_inp4eriod += - rtlpriv->link_info.num_rx_in4period[idx]; - tx_cnt_inp4eriod += - rtlpriv->link_info.num_tx_in4period[idx]; - } - aver_rx_cnt_inperiod = rx_cnt_inp4eriod / 4; - aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4; - - /* (2) check traffic busy */ - if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100) { - busytraffic = true; - if (aver_rx_cnt_inperiod > aver_tx_cnt_inperiod) - rx_busy_traffic = true; - else - tx_busy_traffic = false; - } - - /* Higher Tx/Rx data. */ - if (aver_rx_cnt_inperiod > 4000 || - aver_tx_cnt_inperiod > 4000) { - higher_busytraffic = true; - - /* Extremely high Rx data. */ - if (aver_rx_cnt_inperiod > 5000) - higher_busyrxtraffic = true; - } - - /* check every tid's tx traffic */ - for (tid = 0; tid <= 7; tid++) { - for (idx = 0; idx <= 2; idx++) - rtlpriv->link_info.tidtx_in4period[tid][idx] = - rtlpriv->link_info.tidtx_in4period[tid] - [idx + 1]; - rtlpriv->link_info.tidtx_in4period[tid][3] = - rtlpriv->link_info.tidtx_inperiod[tid]; - - for (idx = 0; idx <= 3; idx++) - tidtx_inp4eriod[tid] += - rtlpriv->link_info.tidtx_in4period[tid][idx]; - aver_tidtx_inperiod[tid] = tidtx_inp4eriod[tid] / 4; - if (aver_tidtx_inperiod[tid] > 5000) - rtlpriv->link_info.higher_busytxtraffic[tid] = - true; - else - rtlpriv->link_info.higher_busytxtraffic[tid] = - false; - } - - if (((rtlpriv->link_info.num_rx_inperiod + - rtlpriv->link_info.num_tx_inperiod) > 8) || - (rtlpriv->link_info.num_rx_inperiod > 2)) - rtl_lps_enter(hw); - else - rtl_lps_leave(hw); - } - - rtlpriv->link_info.num_rx_inperiod = 0; - rtlpriv->link_info.num_tx_inperiod = 0; - for (tid = 0; tid <= 7; tid++) - rtlpriv->link_info.tidtx_inperiod[tid] = 0; - - rtlpriv->link_info.busytraffic = busytraffic; - rtlpriv->link_info.higher_busytraffic = higher_busytraffic; - rtlpriv->link_info.rx_busy_traffic = rx_busy_traffic; - rtlpriv->link_info.tx_busy_traffic = tx_busy_traffic; - rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic; - - /* <3> DM */ - if (!rtlpriv->cfg->mod_params->disable_watchdog) - rtlpriv->cfg->ops->dm_watchdog(hw); - - /* <4> roaming */ - if (mac->link_state == MAC80211_LINKED && - mac->opmode == NL80211_IFTYPE_STATION) { - if ((rtlpriv->link_info.bcn_rx_inperiod + - rtlpriv->link_info.num_rx_inperiod) == 0) { - rtlpriv->link_info.roam_times++; - RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, - "AP off for %d s\n", - (rtlpriv->link_info.roam_times * 2)); - - /* if we can't recv beacon for 10s, - * we should reconnect this AP - */ - if (rtlpriv->link_info.roam_times >= 5) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "AP off, try to reconnect now\n"); - rtlpriv->link_info.roam_times = 0; - ieee80211_connection_loss( - rtlpriv->mac80211.vif); - } - } else { - rtlpriv->link_info.roam_times = 0; - } - } - - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_periodical(rtlpriv); - - rtlpriv->link_info.bcn_rx_inperiod = 0; -} - -void rtl_watch_dog_timer_callback(unsigned long data) -{ - struct ieee80211_hw *hw = (struct ieee80211_hw *)data; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - queue_delayed_work(rtlpriv->works.rtl_wq, - &rtlpriv->works.watchdog_wq, 0); - - mod_timer(&rtlpriv->works.watchdog_timer, - jiffies + MSECS(RTL_WATCH_DOG_TIME)); -} -void rtl_fwevt_wq_callback(void *data) -{ - struct rtl_works *rtlworks = - container_of_dwork_rtl(data, struct rtl_works, fwevt_wq); - struct ieee80211_hw *hw = rtlworks->hw; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->cfg->ops->c2h_command_handle(hw); -} -void rtl_easy_concurrent_retrytimer_callback(unsigned long data) -{ - struct ieee80211_hw *hw = (struct ieee80211_hw *)data; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_priv *buddy_priv = rtlpriv->buddy_priv; - - if (buddy_priv == NULL) - return; - - rtlpriv->cfg->ops->dualmac_easy_concurrent(hw); -} -/********************************************************* - * - * frame process functions - * - *********************************************************/ -u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie) -{ - struct ieee80211_mgmt *mgmt = (void *)data; - u8 *pos, *end; - - pos = (u8 *)mgmt->u.beacon.variable; - end = data + len; - while (pos < end) { - if (pos + 2 + pos[1] > end) - return NULL; - - if (pos[0] == ie) - return pos; - - pos += 2 + pos[1]; - } - return NULL; -} - -/* when we use 2 rx ants we send IEEE80211_SMPS_OFF */ -/* when we use 1 rx ant we send IEEE80211_SMPS_STATIC */ -static struct sk_buff *rtl_make_smps_action(struct ieee80211_hw *hw, - enum ieee80211_smps_mode smps, - u8 *da, u8 *bssid) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct sk_buff *skb; - struct ieee80211_mgmt *action_frame; - - /* 27 = header + category + action + smps mode */ - skb = dev_alloc_skb(27 + hw->extra_tx_headroom); - if (!skb) - return NULL; - - skb_reserve(skb, hw->extra_tx_headroom); - action_frame = (void *)skb_put(skb, 27); - memset(action_frame, 0, 27); - memcpy(action_frame->da, da, ETH_ALEN); - memcpy(action_frame->sa, rtlefuse->dev_addr, ETH_ALEN); - memcpy(action_frame->bssid, bssid, ETH_ALEN); - action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); - action_frame->u.action.category = WLAN_CATEGORY_HT; - action_frame->u.action.u.ht_smps.action = WLAN_HT_ACTION_SMPS; - switch (smps) { - case IEEE80211_SMPS_AUTOMATIC:/* 0 */ - case IEEE80211_SMPS_NUM_MODES:/* 4 */ - WARN_ON(1); - /* Here will get a 'MISSING_BREAK' in Coverity Test, just ignore it. - * According to Kernel Code, here is right. - */ - case IEEE80211_SMPS_OFF:/* 1 */ /*MIMO_PS_NOLIMIT*/ - action_frame->u.action.u.ht_smps.smps_control = - WLAN_HT_SMPS_CONTROL_DISABLED;/* 0 */ - break; - case IEEE80211_SMPS_STATIC:/* 2 */ /*MIMO_PS_STATIC*/ - action_frame->u.action.u.ht_smps.smps_control = - WLAN_HT_SMPS_CONTROL_STATIC;/* 1 */ - break; - case IEEE80211_SMPS_DYNAMIC:/* 3 */ /*MIMO_PS_DYNAMIC*/ - action_frame->u.action.u.ht_smps.smps_control = - WLAN_HT_SMPS_CONTROL_DYNAMIC;/* 3 */ - break; - } - - return skb; -} - -int rtl_send_smps_action(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - enum ieee80211_smps_mode smps) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct sk_buff *skb = NULL; - struct rtl_tcb_desc tcb_desc; - u8 bssid[ETH_ALEN] = {0}; - - memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); - - if (rtlpriv->mac80211.act_scanning) - goto err_free; - - if (!sta) - goto err_free; - - if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) - goto err_free; - - if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) - goto err_free; - - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) - memcpy(bssid, rtlpriv->efuse.dev_addr, ETH_ALEN); - else - memcpy(bssid, rtlpriv->mac80211.bssid, ETH_ALEN); - - skb = rtl_make_smps_action(hw, smps, sta->addr, bssid); - /* this is a type = mgmt * stype = action frame */ - if (skb) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct rtl_sta_info *sta_entry = - (struct rtl_sta_info *) sta->drv_priv; - sta_entry->mimo_ps = smps; - /* rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); */ - - info->control.rates[0].idx = 0; - info->band = hw->conf.chandef.chan->band; - rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc); - } - return 1; - -err_free: - return 0; -} -EXPORT_SYMBOL(rtl_send_smps_action); - -void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - enum io_type iotype; - - if (!is_hal_stop(rtlhal)) { - switch (operation) { - case SCAN_OPT_BACKUP: - iotype = IO_CMD_PAUSE_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_IO_CMD, - (u8 *)&iotype); - break; - case SCAN_OPT_RESTORE: - iotype = IO_CMD_RESUME_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_IO_CMD, - (u8 *)&iotype); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Unknown Scan Backup operation.\n"); - break; - } - } -} -EXPORT_SYMBOL(rtl_phy_scan_operation_backup); - -/* because mac80211 have issues when can receive del ba - * so here we just make a fake del_ba if we receive a ba_req - * but rx_agg was opened to let mac80211 release some ba - * related resources, so please this del_ba for tx - */ -struct sk_buff *rtl_make_del_ba(struct ieee80211_hw *hw, - u8 *sa, u8 *bssid, u16 tid) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct sk_buff *skb; - struct ieee80211_mgmt *action_frame; - u16 params; - - /* 27 = header + category + action + smps mode */ - skb = dev_alloc_skb(34 + hw->extra_tx_headroom); - if (!skb) - return NULL; - - skb_reserve(skb, hw->extra_tx_headroom); - action_frame = (void *)skb_put(skb, 34); - memset(action_frame, 0, 34); - memcpy(action_frame->sa, sa, ETH_ALEN); - memcpy(action_frame->da, rtlefuse->dev_addr, ETH_ALEN); - memcpy(action_frame->bssid, bssid, ETH_ALEN); - action_frame->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); - action_frame->u.action.category = WLAN_CATEGORY_BACK; - action_frame->u.action.u.delba.action_code = WLAN_ACTION_DELBA; - params = (u16)(1 << 11); /* bit 11 initiator */ - params |= (u16)(tid << 12); /* bit 15:12 TID number */ - - action_frame->u.action.u.delba.params = cpu_to_le16(params); - action_frame->u.action.u.delba.reason_code = - cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); - - return skb; -} - -/********************************************************* - * - * IOT functions - * - *********************************************************/ -static bool rtl_chk_vendor_ouisub(struct ieee80211_hw *hw, - struct octet_string vendor_ie) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool matched = false; - static u8 athcap_1[] = { 0x00, 0x03, 0x7F }; - static u8 athcap_2[] = { 0x00, 0x13, 0x74 }; - static u8 broadcap_1[] = { 0x00, 0x10, 0x18 }; - static u8 broadcap_2[] = { 0x00, 0x0a, 0xf7 }; - static u8 broadcap_3[] = { 0x00, 0x05, 0xb5 }; - static u8 racap[] = { 0x00, 0x0c, 0x43 }; - static u8 ciscocap[] = { 0x00, 0x40, 0x96 }; - static u8 marvcap[] = { 0x00, 0x50, 0x43 }; - - if (memcmp(vendor_ie.octet, athcap_1, 3) == 0 || - memcmp(vendor_ie.octet, athcap_2, 3) == 0) { - rtlpriv->mac80211.vendor = PEER_ATH; - matched = true; - } else if (memcmp(vendor_ie.octet, broadcap_1, 3) == 0 || - memcmp(vendor_ie.octet, broadcap_2, 3) == 0 || - memcmp(vendor_ie.octet, broadcap_3, 3) == 0) { - rtlpriv->mac80211.vendor = PEER_BROAD; - matched = true; - } else if (memcmp(vendor_ie.octet, racap, 3) == 0) { - rtlpriv->mac80211.vendor = PEER_RAL; - matched = true; - } else if (memcmp(vendor_ie.octet, ciscocap, 3) == 0) { - rtlpriv->mac80211.vendor = PEER_CISCO; - matched = true; - } else if (memcmp(vendor_ie.octet, marvcap, 3) == 0) { - rtlpriv->mac80211.vendor = PEER_MARV; - matched = true; - } - - return matched; -} - -static bool rtl_find_221_ie(struct ieee80211_hw *hw, u8 *data, - unsigned int len) -{ - struct ieee80211_mgmt *mgmt = (void *)data; - struct octet_string vendor_ie; - u8 *pos, *end; - - pos = (u8 *)mgmt->u.beacon.variable; - end = data + len; - while (pos < end) { - if (pos[0] == 221) { - vendor_ie.length = pos[1]; - vendor_ie.octet = &pos[2]; - if (rtl_chk_vendor_ouisub(hw, vendor_ie)) - return true; - } - - if (pos + 2 + pos[1] > end) - return false; - - pos += 2 + pos[1]; - } - return false; -} - -void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = (void *)data; - u32 vendor = PEER_UNKNOWN; - - static u8 ap3_1[3] = { 0x00, 0x14, 0xbf }; - static u8 ap3_2[3] = { 0x00, 0x1a, 0x70 }; - static u8 ap3_3[3] = { 0x00, 0x1d, 0x7e }; - static u8 ap4_1[3] = { 0x00, 0x90, 0xcc }; - static u8 ap4_2[3] = { 0x00, 0x0e, 0x2e }; - static u8 ap4_3[3] = { 0x00, 0x18, 0x02 }; - static u8 ap4_4[3] = { 0x00, 0x17, 0x3f }; - static u8 ap4_5[3] = { 0x00, 0x1c, 0xdf }; - static u8 ap5_1[3] = { 0x00, 0x1c, 0xf0 }; - static u8 ap5_2[3] = { 0x00, 0x21, 0x91 }; - static u8 ap5_3[3] = { 0x00, 0x24, 0x01 }; - static u8 ap5_4[3] = { 0x00, 0x15, 0xe9 }; - static u8 ap5_5[3] = { 0x00, 0x17, 0x9A }; - static u8 ap5_6[3] = { 0x00, 0x18, 0xE7 }; - static u8 ap6_1[3] = { 0x00, 0x17, 0x94 }; - static u8 ap7_1[3] = { 0x00, 0x14, 0xa4 }; - - if (mac->opmode != NL80211_IFTYPE_STATION) - return; - - if (mac->link_state == MAC80211_NOLINK) { - mac->vendor = PEER_UNKNOWN; - return; - } - - if (mac->cnt_after_linked > 2) - return; - - /* check if this really is a beacon */ - if (!ieee80211_is_beacon(hdr->frame_control)) - return; - - /* min. beacon length + FCS_LEN */ - if (len <= 40 + FCS_LEN) - return; - - /* and only beacons from the associated BSSID, please */ - if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid)) - return; - - if (rtl_find_221_ie(hw, data, len)) - vendor = mac->vendor; - - if ((memcmp(mac->bssid, ap5_1, 3) == 0) || - (memcmp(mac->bssid, ap5_2, 3) == 0) || - (memcmp(mac->bssid, ap5_3, 3) == 0) || - (memcmp(mac->bssid, ap5_4, 3) == 0) || - (memcmp(mac->bssid, ap5_5, 3) == 0) || - (memcmp(mac->bssid, ap5_6, 3) == 0) || - vendor == PEER_ATH) { - vendor = PEER_ATH; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ath find\n"); - } else if ((memcmp(mac->bssid, ap4_4, 3) == 0) || - (memcmp(mac->bssid, ap4_5, 3) == 0) || - (memcmp(mac->bssid, ap4_1, 3) == 0) || - (memcmp(mac->bssid, ap4_2, 3) == 0) || - (memcmp(mac->bssid, ap4_3, 3) == 0) || - vendor == PEER_RAL) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ral find\n"); - vendor = PEER_RAL; - } else if (memcmp(mac->bssid, ap6_1, 3) == 0 || - vendor == PEER_CISCO) { - vendor = PEER_CISCO; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>cisco find\n"); - } else if ((memcmp(mac->bssid, ap3_1, 3) == 0) || - (memcmp(mac->bssid, ap3_2, 3) == 0) || - (memcmp(mac->bssid, ap3_3, 3) == 0) || - vendor == PEER_BROAD) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>broad find\n"); - vendor = PEER_BROAD; - } else if (memcmp(mac->bssid, ap7_1, 3) == 0 || - vendor == PEER_MARV) { - vendor = PEER_MARV; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>marv find\n"); - } - - mac->vendor = vendor; -} -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 "); -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_AUTHOR("Larry Finger "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); - -struct rtl_global_var rtl_global_var = {}; -EXPORT_SYMBOL_GPL(rtl_global_var); - -static int __init rtl_core_module_init(void) -{ - if (rtl_rate_control_register()) - pr_err("rtl: Unable to register rtl_rc, use default RC !!\n"); - - /* init some global vars */ - INIT_LIST_HEAD(&rtl_global_var.glb_priv_list); - spin_lock_init(&rtl_global_var.glb_list_lock); - - return 0; -} - -static void __exit rtl_core_module_exit(void) -{ - /*RC*/ - rtl_rate_control_unregister(); -} - -module_init(rtl_core_module_init); -module_exit(rtl_core_module_exit); diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h deleted file mode 100644 index 74233d601a90..000000000000 --- a/drivers/net/wireless/rtlwifi/base.h +++ /dev/null @@ -1,156 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL_BASE_H__ -#define __RTL_BASE_H__ - -enum ap_peer { - PEER_UNKNOWN = 0, - PEER_RTL = 1, - PEER_RTL_92SE = 2, - PEER_BROAD = 3, - PEER_RAL = 4, - PEER_ATH = 5, - PEER_CISCO = 6, - PEER_MARV = 7, - PEER_AIRGO = 9, - PEER_MAX = 10, -}; - -#define RTL_DUMMY_OFFSET 0 -#define RTL_DUMMY_UNIT 8 -#define RTL_TX_DUMMY_SIZE (RTL_DUMMY_OFFSET * RTL_DUMMY_UNIT) -#define RTL_TX_DESC_SIZE 32 -#define RTL_TX_HEADER_SIZE (RTL_TX_DESC_SIZE + RTL_TX_DUMMY_SIZE) - -#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */ -#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */ - -#define MAX_BIT_RATE_SHORT_GI_2NSS_80MHZ_MCS9 867 /* Mbps */ -#define MAX_BIT_RATE_SHORT_GI_2NSS_80MHZ_MCS7 650 /* Mbps */ -#define MAX_BIT_RATE_LONG_GI_2NSS_80MHZ_MCS9 780 /* Mbps */ -#define MAX_BIT_RATE_LONG_GI_2NSS_80MHZ_MCS7 585 /* Mbps */ - -#define MAX_BIT_RATE_SHORT_GI_1NSS_80MHZ_MCS9 434 /* Mbps */ -#define MAX_BIT_RATE_SHORT_GI_1NSS_80MHZ_MCS7 325 /* Mbps */ -#define MAX_BIT_RATE_LONG_GI_1NSS_80MHZ_MCS9 390 /* Mbps */ -#define MAX_BIT_RATE_LONG_GI_1NSS_80MHZ_MCS7 293 /* Mbps */ - -#define FRAME_OFFSET_FRAME_CONTROL 0 -#define FRAME_OFFSET_DURATION 2 -#define FRAME_OFFSET_ADDRESS1 4 -#define FRAME_OFFSET_ADDRESS2 10 -#define FRAME_OFFSET_ADDRESS3 16 -#define FRAME_OFFSET_SEQUENCE 22 -#define FRAME_OFFSET_ADDRESS4 24 - -#define SET_80211_HDR_FRAME_CONTROL(_hdr, _val) \ - WRITEEF2BYTE(_hdr, _val) -#define SET_80211_HDR_TYPE_AND_SUBTYPE(_hdr, _val) \ - WRITEEF1BYTE(_hdr, _val) -#define SET_80211_HDR_PWR_MGNT(_hdr, _val) \ - SET_BITS_TO_LE_2BYTE(_hdr, 12, 1, _val) -#define SET_80211_HDR_TO_DS(_hdr, _val) \ - SET_BITS_TO_LE_2BYTE(_hdr, 8, 1, _val) - -#define SET_80211_PS_POLL_AID(_hdr, _val) \ - (*(u16 *)((u8 *)(_hdr) + 2) = _val) -#define SET_80211_PS_POLL_BSSID(_hdr, _val) \ - ether_addr_copy(((u8 *)(_hdr)) + 4, (u8 *)(_val)) -#define SET_80211_PS_POLL_TA(_hdr, _val) \ - ether_addr_copy(((u8 *)(_hdr))+10, (u8 *)(_val)) - -#define SET_80211_HDR_DURATION(_hdr, _val) \ - (*(u16 *)((u8 *)(_hdr) + FRAME_OFFSET_DURATION) = le16_to_cpu(_val)) -#define SET_80211_HDR_ADDRESS1(_hdr, _val) \ - CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8 *)(_val)) -#define SET_80211_HDR_ADDRESS2(_hdr, _val) \ - CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS2, (u8 *)(_val)) -#define SET_80211_HDR_ADDRESS3(_hdr, _val) \ - CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val)) -#define SET_80211_HDR_FRAGMENT_SEQUENCE(_hdr, _val) \ - WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_SEQUENCE, _val) - -#define SET_BEACON_PROBE_RSP_TIME_STAMP_LOW(__phdr, __val) \ - WRITEEF4BYTE(((u8 *)(__phdr)) + 24, __val) -#define SET_BEACON_PROBE_RSP_TIME_STAMP_HIGH(__phdr, __val) \ - WRITEEF4BYTE(((u8 *)(__phdr)) + 28, __val) -#define SET_BEACON_PROBE_RSP_BEACON_INTERVAL(__phdr, __val) \ - WRITEEF2BYTE(((u8 *)(__phdr)) + 32, __val) -#define GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) \ - READEF2BYTE(((u8 *)(__phdr)) + 34) -#define SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ - WRITEEF2BYTE(((u8 *)(__phdr)) + 34, __val) -#define MASK_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \ - SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, \ - (GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) & (~(__val)))) - -int rtl_init_core(struct ieee80211_hw *hw); -void rtl_deinit_core(struct ieee80211_hw *hw); -void rtl_init_rx_config(struct ieee80211_hw *hw); -void rtl_init_rfkill(struct ieee80211_hw *hw); -void rtl_deinit_rfkill(struct ieee80211_hw *hw); - -void rtl_watch_dog_timer_callback(unsigned long data); -void rtl_deinit_deferred_work(struct ieee80211_hw *hw); - -bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx); -int rtlwifi_rate_mapping(struct ieee80211_hw *hw, bool isht, - bool isvht, u8 desc_rate); -bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb); -u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx, - bool is_enc); - -void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb); -int rtl_tx_agg_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u16 tid, u16 *ssn); -int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u16 tid); -int rtl_tx_agg_oper(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u16 tid); -int rtl_rx_agg_start(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u16 tid); -int rtl_rx_agg_stop(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u16 tid); -void rtl_watchdog_wq_callback(void *data); -void rtl_fwevt_wq_callback(void *data); - -void rtl_get_tcb_desc(struct ieee80211_hw *hw, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc); - -int rtl_send_smps_action(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - enum ieee80211_smps_mode smps); -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); - -#endif diff --git a/drivers/net/wireless/rtlwifi/btcoexist/Makefile b/drivers/net/wireless/rtlwifi/btcoexist/Makefile deleted file mode 100644 index 47ceecfcb7dc..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -btcoexist-objs := halbtc8723b2ant.o \ - halbtcoutsrc.o \ - rtl_btc.o - -obj-$(CONFIG_RTLBTCOEXIST) += btcoexist.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h b/drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h deleted file mode 100644 index 39b9a3309cfd..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbt_precomp.h +++ /dev/null @@ -1,81 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - ******************************************************************************/ - -#ifndef __HALBT_PRECOMP_H__ -#define __HALBT_PRECOMP_H__ -/************************************************************* - * include files - *************************************************************/ -#include "../wifi.h" -#include "../efuse.h" -#include "../base.h" -#include "../regd.h" -#include "../cam.h" -#include "../ps.h" -#include "../pci.h" - -#include "halbtcoutsrc.h" - -#include "halbtc8192e2ant.h" -#include "halbtc8723b1ant.h" -#include "halbtc8723b2ant.h" -#include "halbtc8821a2ant.h" -#include "halbtc8821a1ant.h" - -#define GetDefaultAdapter(padapter) padapter - -#define BIT0 0x00000001 -#define BIT1 0x00000002 -#define BIT2 0x00000004 -#define BIT3 0x00000008 -#define BIT4 0x00000010 -#define BIT5 0x00000020 -#define BIT6 0x00000040 -#define BIT7 0x00000080 -#define BIT8 0x00000100 -#define BIT9 0x00000200 -#define BIT10 0x00000400 -#define BIT11 0x00000800 -#define BIT12 0x00001000 -#define BIT13 0x00002000 -#define BIT14 0x00004000 -#define BIT15 0x00008000 -#define BIT16 0x00010000 -#define BIT17 0x00020000 -#define BIT18 0x00040000 -#define BIT19 0x00080000 -#define BIT20 0x00100000 -#define BIT21 0x00200000 -#define BIT22 0x00400000 -#define BIT23 0x00800000 -#define BIT24 0x01000000 -#define BIT25 0x02000000 -#define BIT26 0x04000000 -#define BIT27 0x08000000 -#define BIT28 0x10000000 -#define BIT29 0x20000000 -#define BIT30 0x40000000 -#define BIT31 0x80000000 - -#endif /* __HALBT_PRECOMP_H__ */ diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c deleted file mode 100644 index 53261d6f8578..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.c +++ /dev/null @@ -1,3849 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -/************************************************************** - * Description: - * - * This file is for RTL8192E Co-exist mechanism - * - * History - * 2012/11/15 Cosa first check in. - * - **************************************************************/ - -/************************************************************** - * include files - **************************************************************/ -#include "halbt_precomp.h" -/************************************************************** - * Global variables, these are static variables - **************************************************************/ -static struct coex_dm_8192e_2ant glcoex_dm_8192e_2ant; -static struct coex_dm_8192e_2ant *coex_dm = &glcoex_dm_8192e_2ant; -static struct coex_sta_8192e_2ant glcoex_sta_8192e_2ant; -static struct coex_sta_8192e_2ant *coex_sta = &glcoex_sta_8192e_2ant; - -static const char *const GLBtInfoSrc8192e2Ant[] = { - "BT Info[wifi fw]", - "BT Info[bt rsp]", - "BT Info[bt auto report]", -}; - -static u32 glcoex_ver_date_8192e_2ant = 20130902; -static u32 glcoex_ver_8192e_2ant = 0x34; - -/************************************************************** - * local function proto type if needed - **************************************************************/ -/************************************************************** - * local function start with halbtc8192e2ant_ - **************************************************************/ -static u8 halbtc8192e2ant_btrssi_state(u8 level_num, u8 rssi_thresh, - u8 rssi_thresh1) -{ - int btrssi = 0; - u8 btrssi_state = coex_sta->pre_bt_rssi_state; - - btrssi = coex_sta->bt_rssi; - - if (level_num == 2) { - if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || - (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi pre state = LOW\n"); - if (btrssi >= (rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { - btrssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state switch to High\n"); - } else { - btrssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state stay at Low\n"); - } - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi pre state = HIGH\n"); - if (btrssi < rssi_thresh) { - btrssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state switch to Low\n"); - } else { - btrssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state stay at High\n"); - } - } - } else if (level_num == 3) { - if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi thresh error!!\n"); - return coex_sta->pre_bt_rssi_state; - } - - if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || - (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi pre state = LOW\n"); - if (btrssi >= (rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { - btrssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state switch to Medium\n"); - } else { - btrssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state stay at Low\n"); - } - } else if ((coex_sta->pre_bt_rssi_state == - BTC_RSSI_STATE_MEDIUM) || - (coex_sta->pre_bt_rssi_state == - BTC_RSSI_STATE_STAY_MEDIUM)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi pre state = MEDIUM\n"); - if (btrssi >= (rssi_thresh1 + - BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { - btrssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state switch to High\n"); - } else if (btrssi < rssi_thresh) { - btrssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state switch to Low\n"); - } else { - btrssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state stay at Medium\n"); - } - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi pre state = HIGH\n"); - if (btrssi < rssi_thresh1) { - btrssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state switch to Medium\n"); - } else { - btrssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "BT Rssi state stay at High\n"); - } - } - } - - coex_sta->pre_bt_rssi_state = btrssi_state; - - return btrssi_state; -} - -static u8 halbtc8192e2ant_wifirssi_state(struct btc_coexist *btcoexist, - u8 index, u8 level_num, u8 rssi_thresh, - u8 rssi_thresh1) -{ - int wifirssi = 0; - u8 wifirssi_state = coex_sta->pre_wifi_rssi_state[index]; - - btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifirssi); - - if (level_num == 2) { - if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_LOW) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_LOW)) { - if (wifirssi >= (rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { - wifirssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state switch to High\n"); - } else { - wifirssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state stay at Low\n"); - } - } else { - if (wifirssi < rssi_thresh) { - wifirssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state switch to Low\n"); - } else { - wifirssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state stay at High\n"); - } - } - } else if (level_num == 3) { - if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, - "wifi RSSI thresh error!!\n"); - return coex_sta->pre_wifi_rssi_state[index]; - } - - if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_LOW) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_LOW)) { - if (wifirssi >= (rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { - wifirssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state switch to Medium\n"); - } else { - wifirssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state stay at Low\n"); - } - } else if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_MEDIUM) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_MEDIUM)) { - if (wifirssi >= (rssi_thresh1 + - BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT)) { - wifirssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state switch to High\n"); - } else if (wifirssi < rssi_thresh) { - wifirssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state switch to Low\n"); - } else { - wifirssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state stay at Medium\n"); - } - } else { - if (wifirssi < rssi_thresh1) { - wifirssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state switch to Medium\n"); - } else { - wifirssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "wifi RSSI state stay at High\n"); - } - } - } - - coex_sta->pre_wifi_rssi_state[index] = wifirssi_state; - - return wifirssi_state; -} - -static void btc8192e2ant_monitor_bt_enable_dis(struct btc_coexist *btcoexist) -{ - static bool pre_bt_disabled; - static u32 bt_disable_cnt; - bool bt_active = true, bt_disabled = false; - - /* This function check if bt is disabled */ - - if (coex_sta->high_priority_tx == 0 && - coex_sta->high_priority_rx == 0 && - coex_sta->low_priority_tx == 0 && - coex_sta->low_priority_rx == 0) - bt_active = false; - - if (coex_sta->high_priority_tx == 0xffff && - coex_sta->high_priority_rx == 0xffff && - coex_sta->low_priority_tx == 0xffff && - coex_sta->low_priority_rx == 0xffff) - bt_active = false; - - if (bt_active) { - bt_disable_cnt = 0; - bt_disabled = false; - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, - &bt_disabled); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is enabled !!\n"); - } else { - bt_disable_cnt++; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], bt all counters = 0, %d times!!\n", - bt_disable_cnt); - if (bt_disable_cnt >= 2) { - bt_disabled = true; - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, - &bt_disabled); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is disabled !!\n"); - } - } - if (pre_bt_disabled != bt_disabled) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is from %s to %s!!\n", - (pre_bt_disabled ? "disabled" : "enabled"), - (bt_disabled ? "disabled" : "enabled")); - pre_bt_disabled = bt_disabled; - } -} - -static u32 halbtc8192e2ant_decidera_mask(struct btc_coexist *btcoexist, - u8 sstype, u32 ra_masktype) -{ - u32 disra_mask = 0x0; - - switch (ra_masktype) { - case 0: /* normal mode */ - if (sstype == 2) - disra_mask = 0x0; /* enable 2ss */ - else - disra_mask = 0xfff00000;/* disable 2ss */ - break; - case 1: /* disable cck 1/2 */ - if (sstype == 2) - disra_mask = 0x00000003;/* enable 2ss */ - else - disra_mask = 0xfff00003;/* disable 2ss */ - break; - case 2: /* disable cck 1/2/5.5, ofdm 6/9/12/18/24, mcs 0/1/2/3/4 */ - if (sstype == 2) - disra_mask = 0x0001f1f7;/* enable 2ss */ - else - disra_mask = 0xfff1f1f7;/* disable 2ss */ - break; - default: - break; - } - - return disra_mask; -} - -static void halbtc8192e2ant_Updatera_mask(struct btc_coexist *btcoexist, - bool force_exec, u32 dis_ratemask) -{ - coex_dm->curra_mask = dis_ratemask; - - if (force_exec || (coex_dm->prera_mask != coex_dm->curra_mask)) - btcoexist->btc_set(btcoexist, BTC_SET_ACT_UPDATE_ra_mask, - &coex_dm->curra_mask); - coex_dm->prera_mask = coex_dm->curra_mask; -} - -static void btc8192e2ant_autorate_fallback_retry(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - bool wifi_under_bmode = false; - - coex_dm->cur_arfrtype = type; - - if (force_exec || (coex_dm->pre_arfrtype != coex_dm->cur_arfrtype)) { - switch (coex_dm->cur_arfrtype) { - case 0: /* normal mode */ - btcoexist->btc_write_4byte(btcoexist, 0x430, - coex_dm->backup_arfr_cnt1); - btcoexist->btc_write_4byte(btcoexist, 0x434, - coex_dm->backup_arfr_cnt2); - break; - case 1: - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_UNDER_B_MODE, - &wifi_under_bmode); - if (wifi_under_bmode) { - btcoexist->btc_write_4byte(btcoexist, 0x430, - 0x0); - btcoexist->btc_write_4byte(btcoexist, 0x434, - 0x01010101); - } else { - btcoexist->btc_write_4byte(btcoexist, 0x430, - 0x0); - btcoexist->btc_write_4byte(btcoexist, 0x434, - 0x04030201); - } - break; - default: - break; - } - } - - coex_dm->pre_arfrtype = coex_dm->cur_arfrtype; -} - -static void halbtc8192e2ant_retrylimit(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - coex_dm->cur_retrylimit_type = type; - - if (force_exec || (coex_dm->pre_retrylimit_type != - coex_dm->cur_retrylimit_type)) { - switch (coex_dm->cur_retrylimit_type) { - case 0: /* normal mode */ - btcoexist->btc_write_2byte(btcoexist, 0x42a, - coex_dm->backup_retrylimit); - break; - case 1: /* retry limit = 8 */ - btcoexist->btc_write_2byte(btcoexist, 0x42a, - 0x0808); - break; - default: - break; - } - } - - coex_dm->pre_retrylimit_type = coex_dm->cur_retrylimit_type; -} - -static void halbtc8192e2ant_ampdu_maxtime(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - coex_dm->cur_ampdutime_type = type; - - if (force_exec || (coex_dm->pre_ampdutime_type != - coex_dm->cur_ampdutime_type)) { - switch (coex_dm->cur_ampdutime_type) { - case 0: /* normal mode */ - btcoexist->btc_write_1byte(btcoexist, 0x456, - coex_dm->backup_ampdu_maxtime); - break; - case 1: /* AMPDU timw = 0x38 * 32us */ - btcoexist->btc_write_1byte(btcoexist, 0x456, 0x38); - break; - default: - break; - } - } - - coex_dm->pre_ampdutime_type = coex_dm->cur_ampdutime_type; -} - -static void halbtc8192e2ant_limited_tx(struct btc_coexist *btcoexist, - bool force_exec, u8 ra_masktype, - u8 arfr_type, u8 retrylimit_type, - u8 ampdutime_type) -{ - u32 disra_mask = 0x0; - - coex_dm->curra_masktype = ra_masktype; - disra_mask = halbtc8192e2ant_decidera_mask(btcoexist, - coex_dm->cur_sstype, - ra_masktype); - halbtc8192e2ant_Updatera_mask(btcoexist, force_exec, disra_mask); -btc8192e2ant_autorate_fallback_retry(btcoexist, force_exec, arfr_type); - halbtc8192e2ant_retrylimit(btcoexist, force_exec, retrylimit_type); - halbtc8192e2ant_ampdu_maxtime(btcoexist, force_exec, ampdutime_type); -} - -static void halbtc8192e2ant_limited_rx(struct btc_coexist *btcoexist, - bool force_exec, bool rej_ap_agg_pkt, - bool bt_ctrl_agg_buf_size, - u8 agg_buf_size) -{ - bool reject_rx_agg = rej_ap_agg_pkt; - bool bt_ctrl_rx_agg_size = bt_ctrl_agg_buf_size; - u8 rx_agg_size = agg_buf_size; - - /********************************************* - * Rx Aggregation related setting - *********************************************/ - btcoexist->btc_set(btcoexist, BTC_SET_BL_TO_REJ_AP_AGG_PKT, - &reject_rx_agg); - /* decide BT control aggregation buf size or not */ - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_CTRL_AGG_SIZE, - &bt_ctrl_rx_agg_size); - /* aggregation buf size, only work - * when BT control Rx aggregation size. - */ - btcoexist->btc_set(btcoexist, BTC_SET_U1_AGG_BUF_SIZE, &rx_agg_size); - /* real update aggregation setting */ - btcoexist->btc_set(btcoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL); -} - -static void halbtc8192e2ant_monitor_bt_ctr(struct btc_coexist *btcoexist) -{ - u32 reg_hp_txrx, reg_lp_txrx, u32tmp; - u32 reg_hp_tx = 0, reg_hp_rx = 0, reg_lp_tx = 0, reg_lp_rx = 0; - - reg_hp_txrx = 0x770; - reg_lp_txrx = 0x774; - - u32tmp = btcoexist->btc_read_4byte(btcoexist, reg_hp_txrx); - reg_hp_tx = u32tmp & MASKLWORD; - reg_hp_rx = (u32tmp & MASKHWORD)>>16; - - u32tmp = btcoexist->btc_read_4byte(btcoexist, reg_lp_txrx); - reg_lp_tx = u32tmp & MASKLWORD; - reg_lp_rx = (u32tmp & MASKHWORD)>>16; - - coex_sta->high_priority_tx = reg_hp_tx; - coex_sta->high_priority_rx = reg_hp_rx; - coex_sta->low_priority_tx = reg_lp_tx; - coex_sta->low_priority_rx = reg_lp_rx; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex] High Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", - reg_hp_txrx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex] Low Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", - reg_lp_txrx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); - - /* reset counter */ - btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); -} - -static void halbtc8192e2ant_querybt_info(struct btc_coexist *btcoexist) -{ - u8 h2c_parameter[1] = {0}; - - coex_sta->c2h_bt_info_req_sent = true; - - h2c_parameter[0] |= BIT0; /* trigger */ - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", - h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); -} - -static void halbtc8192e2ant_update_btlink_info(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool bt_hson = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hson); - - bt_link_info->bt_link_exist = coex_sta->bt_link_exist; - bt_link_info->sco_exist = coex_sta->sco_exist; - bt_link_info->a2dp_exist = coex_sta->a2dp_exist; - bt_link_info->pan_exist = coex_sta->pan_exist; - bt_link_info->hid_exist = coex_sta->hid_exist; - - /* work around for HS mode. */ - if (bt_hson) { - bt_link_info->pan_exist = true; - bt_link_info->bt_link_exist = true; - } - - /* check if Sco only */ - if (bt_link_info->sco_exist && - !bt_link_info->a2dp_exist && - !bt_link_info->pan_exist && - !bt_link_info->hid_exist) - bt_link_info->sco_only = true; - else - bt_link_info->sco_only = false; - - /* check if A2dp only */ - if (!bt_link_info->sco_exist && - bt_link_info->a2dp_exist && - !bt_link_info->pan_exist && - !bt_link_info->hid_exist) - bt_link_info->a2dp_only = true; - else - bt_link_info->a2dp_only = false; - - /* check if Pan only */ - if (!bt_link_info->sco_exist && - !bt_link_info->a2dp_exist && - bt_link_info->pan_exist && - !bt_link_info->hid_exist) - bt_link_info->pan_only = true; - else - bt_link_info->pan_only = false; - - /* check if Hid only */ - if (!bt_link_info->sco_exist && - !bt_link_info->a2dp_exist && - !bt_link_info->pan_exist && - bt_link_info->hid_exist) - bt_link_info->hid_only = true; - else - bt_link_info->hid_only = false; -} - -static u8 halbtc8192e2ant_action_algorithm(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - struct btc_stack_info *stack_info = &btcoexist->stack_info; - bool bt_hson = false; - u8 algorithm = BT_8192E_2ANT_COEX_ALGO_UNDEFINED; - u8 numdiffprofile = 0; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hson); - - if (!bt_link_info->bt_link_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "No BT link exists!!!\n"); - return algorithm; - } - - if (bt_link_info->sco_exist) - numdiffprofile++; - if (bt_link_info->hid_exist) - numdiffprofile++; - if (bt_link_info->pan_exist) - numdiffprofile++; - if (bt_link_info->a2dp_exist) - numdiffprofile++; - - if (numdiffprofile == 1) { - if (bt_link_info->sco_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO only\n"); - algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; - } else { - if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID only\n"); - algorithm = BT_8192E_2ANT_COEX_ALGO_HID; - } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "A2DP only\n"); - algorithm = BT_8192E_2ANT_COEX_ALGO_A2DP; - } else if (bt_link_info->pan_exist) { - if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "PAN(HS) only\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_PANHS; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "PAN(EDR) only\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_PANEDR; - } - } - } - } else if (numdiffprofile == 2) { - if (bt_link_info->sco_exist) { - if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + HID\n"); - algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; - } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + A2DP ==> SCO\n"); - algorithm = BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; - } else if (bt_link_info->pan_exist) { - if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + PAN(HS)\n"); - algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + PAN(EDR)\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_SCO_PAN; - } - } - } else { - if (bt_link_info->hid_exist && - bt_link_info->a2dp_exist) { - if (stack_info->num_of_hid >= 2) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID*2 + A2DP\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_HID_A2DP_PANEDR; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID + A2DP\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_HID_A2DP; - } - } else if (bt_link_info->hid_exist && - bt_link_info->pan_exist) { - if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID + PAN(HS)\n"); - algorithm = BT_8192E_2ANT_COEX_ALGO_HID; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID + PAN(EDR)\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; - } - } else if (bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "A2DP + PAN(HS)\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_A2DP_PANHS; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "A2DP + PAN(EDR)\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_PANEDR_A2DP; - } - } - } - } else if (numdiffprofile == 3) { - if (bt_link_info->sco_exist) { - if (bt_link_info->hid_exist && - bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + HID + A2DP ==> HID\n"); - algorithm = BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; - } else if (bt_link_info->hid_exist && - bt_link_info->pan_exist) { - if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + HID + PAN(HS)\n"); - algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + HID + PAN(EDR)\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_SCO_PAN; - } - } else if (bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + A2DP + PAN(HS)\n"); - algorithm = BT_8192E_2ANT_COEX_ALGO_SCO; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO + A2DP + PAN(EDR)\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; - } - } - } else { - if (bt_link_info->hid_exist && - bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID + A2DP + PAN(HS)\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_HID_A2DP; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "HID + A2DP + PAN(EDR)\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_HID_A2DP_PANEDR; - } - } - } - } else if (numdiffprofile >= 3) { - if (bt_link_info->sco_exist) { - if (bt_link_info->hid_exist && - bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hson) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "ErrorSCO+HID+A2DP+PAN(HS)\n"); - - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "SCO+HID+A2DP+PAN(EDR)\n"); - algorithm = - BT_8192E_2ANT_COEX_ALGO_PANEDR_HID; - } - } - } - } - - return algorithm; -} - -static void halbtc8192e2ant_setfw_dac_swinglevel(struct btc_coexist *btcoexist, - u8 dac_swinglvl) -{ - u8 h2c_parameter[1] = {0}; - - /* There are several type of dacswing - * 0x18/ 0x10/ 0xc/ 0x8/ 0x4/ 0x6 - */ - h2c_parameter[0] = dac_swinglvl; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Set Dac Swing Level = 0x%x\n", dac_swinglvl); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x64 = 0x%x\n", h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x64, 1, h2c_parameter); -} - -static void halbtc8192e2ant_set_fwdec_btpwr(struct btc_coexist *btcoexist, - u8 dec_btpwr_lvl) -{ - u8 h2c_parameter[1] = {0}; - - h2c_parameter[0] = dec_btpwr_lvl; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex] decrease Bt Power level = %d, FW write 0x62 = 0x%x\n", - dec_btpwr_lvl, h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x62, 1, h2c_parameter); -} - -static void halbtc8192e2ant_dec_btpwr(struct btc_coexist *btcoexist, - bool force_exec, u8 dec_btpwr_lvl) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s Dec BT power level = %d\n", - (force_exec ? "force to" : ""), dec_btpwr_lvl); - coex_dm->cur_dec_bt_pwr = dec_btpwr_lvl; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], preBtDecPwrLvl=%d, curBtDecPwrLvl=%d\n", - coex_dm->pre_dec_bt_pwr, coex_dm->cur_dec_bt_pwr); - } - halbtc8192e2ant_set_fwdec_btpwr(btcoexist, coex_dm->cur_dec_bt_pwr); - - coex_dm->pre_dec_bt_pwr = coex_dm->cur_dec_bt_pwr; -} - -static void halbtc8192e2ant_set_bt_autoreport(struct btc_coexist *btcoexist, - bool enable_autoreport) -{ - u8 h2c_parameter[1] = {0}; - - h2c_parameter[0] = 0; - - if (enable_autoreport) - h2c_parameter[0] |= BIT0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], BT FW auto report : %s, FW write 0x68 = 0x%x\n", - (enable_autoreport ? "Enabled!!" : "Disabled!!"), - h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter); -} - -static void halbtc8192e2ant_bt_autoreport(struct btc_coexist *btcoexist, - bool force_exec, - bool enable_autoreport) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s BT Auto report = %s\n", - (force_exec ? "force to" : ""), - ((enable_autoreport) ? "Enabled" : "Disabled")); - coex_dm->cur_bt_auto_report = enable_autoreport; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex] bPreBtAutoReport=%d, bCurBtAutoReport=%d\n", - coex_dm->pre_bt_auto_report, - coex_dm->cur_bt_auto_report); - - if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report) - return; - } - halbtc8192e2ant_set_bt_autoreport(btcoexist, - coex_dm->cur_bt_auto_report); - - coex_dm->pre_bt_auto_report = coex_dm->cur_bt_auto_report; -} - -static void halbtc8192e2ant_fw_dac_swinglvl(struct btc_coexist *btcoexist, - bool force_exec, u8 fw_dac_swinglvl) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s set FW Dac Swing level = %d\n", - (force_exec ? "force to" : ""), fw_dac_swinglvl); - coex_dm->cur_fw_dac_swing_lvl = fw_dac_swinglvl; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex] preFwDacSwingLvl=%d, curFwDacSwingLvl=%d\n", - coex_dm->pre_fw_dac_swing_lvl, - coex_dm->cur_fw_dac_swing_lvl); - - if (coex_dm->pre_fw_dac_swing_lvl == - coex_dm->cur_fw_dac_swing_lvl) - return; - } - - halbtc8192e2ant_setfw_dac_swinglevel(btcoexist, - coex_dm->cur_fw_dac_swing_lvl); - - coex_dm->pre_fw_dac_swing_lvl = coex_dm->cur_fw_dac_swing_lvl; -} - -static void btc8192e2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, - bool rx_rf_shrink_on) -{ - if (rx_rf_shrink_on) { - /* Shrink RF Rx LPF corner */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Shrink RF Rx LPF corner!!\n"); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, - 0xfffff, 0xffffc); - } else { - /* Resume RF Rx LPF corner - * After initialized, we can use coex_dm->btRf0x1eBackup - */ - if (btcoexist->initilized) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Resume RF Rx LPF corner!!\n"); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, - 0xfffff, - coex_dm->bt_rf0x1e_backup); - } - } -} - -static void halbtc8192e2ant_rf_shrink(struct btc_coexist *btcoexist, - bool force_exec, bool rx_rf_shrink_on) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn Rx RF Shrink = %s\n", - (force_exec ? "force to" : ""), - ((rx_rf_shrink_on) ? "ON" : "OFF")); - coex_dm->cur_rf_rx_lpf_shrink = rx_rf_shrink_on; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex]bPreRfRxLpfShrink=%d,bCurRfRxLpfShrink=%d\n", - coex_dm->pre_rf_rx_lpf_shrink, - coex_dm->cur_rf_rx_lpf_shrink); - - if (coex_dm->pre_rf_rx_lpf_shrink == - coex_dm->cur_rf_rx_lpf_shrink) - return; - } - btc8192e2ant_set_sw_rf_rx_lpf_corner(btcoexist, - coex_dm->cur_rf_rx_lpf_shrink); - - coex_dm->pre_rf_rx_lpf_shrink = coex_dm->cur_rf_rx_lpf_shrink; -} - -static void halbtc8192e2ant_set_dac_swingreg(struct btc_coexist *btcoexist, - u32 level) -{ - u8 val = (u8)level; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Write SwDacSwing = 0x%x\n", level); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x883, 0x3e, val); -} - -static void btc8192e2ant_setsw_full_swing(struct btc_coexist *btcoexist, - bool sw_dac_swingon, - u32 sw_dac_swinglvl) -{ - if (sw_dac_swingon) - halbtc8192e2ant_set_dac_swingreg(btcoexist, sw_dac_swinglvl); - else - halbtc8192e2ant_set_dac_swingreg(btcoexist, 0x18); -} - -static void halbtc8192e2ant_DacSwing(struct btc_coexist *btcoexist, - bool force_exec, bool dac_swingon, - u32 dac_swinglvl) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn DacSwing=%s, dac_swinglvl = 0x%x\n", - (force_exec ? "force to" : ""), - ((dac_swingon) ? "ON" : "OFF"), dac_swinglvl); - coex_dm->cur_dac_swing_on = dac_swingon; - coex_dm->cur_dac_swing_lvl = dac_swinglvl; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], bPreDacSwingOn=%d, preDacSwingLvl = 0x%x, ", - coex_dm->pre_dac_swing_on, - coex_dm->pre_dac_swing_lvl); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "bCurDacSwingOn=%d, curDacSwingLvl = 0x%x\n", - coex_dm->cur_dac_swing_on, - coex_dm->cur_dac_swing_lvl); - - if ((coex_dm->pre_dac_swing_on == coex_dm->cur_dac_swing_on) && - (coex_dm->pre_dac_swing_lvl == coex_dm->cur_dac_swing_lvl)) - return; - } - mdelay(30); - btc8192e2ant_setsw_full_swing(btcoexist, dac_swingon, dac_swinglvl); - - coex_dm->pre_dac_swing_on = coex_dm->cur_dac_swing_on; - coex_dm->pre_dac_swing_lvl = coex_dm->cur_dac_swing_lvl; -} - -static void halbtc8192e2ant_set_agc_table(struct btc_coexist *btcoexist, - bool agc_table_en) -{ - /* BB AGC Gain Table */ - if (agc_table_en) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], BB Agc Table On!\n"); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x0a1A0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x091B0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x081C0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x071D0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x061E0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x051F0001); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], BB Agc Table Off!\n"); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xaa1A0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa91B0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa81C0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa71D0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa61E0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa51F0001); - } -} - -static void halbtc8192e2ant_AgcTable(struct btc_coexist *btcoexist, - bool force_exec, bool agc_table_en) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s %s Agc Table\n", - (force_exec ? "force to" : ""), - ((agc_table_en) ? "Enable" : "Disable")); - coex_dm->cur_agc_table_en = agc_table_en; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], bPreAgcTableEn=%d, bCurAgcTableEn=%d\n", - coex_dm->pre_agc_table_en, coex_dm->cur_agc_table_en); - - if (coex_dm->pre_agc_table_en == coex_dm->cur_agc_table_en) - return; - } - halbtc8192e2ant_set_agc_table(btcoexist, agc_table_en); - - coex_dm->pre_agc_table_en = coex_dm->cur_agc_table_en; -} - -static void halbtc8192e2ant_set_coex_table(struct btc_coexist *btcoexist, - u32 val0x6c0, u32 val0x6c4, - u32 val0x6c8, u8 val0x6cc) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); - btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); - btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); - btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); - btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); -} - -static void halbtc8192e2ant_coex_table(struct btc_coexist *btcoexist, - bool force_exec, - u32 val0x6c0, u32 val0x6c4, - u32 val0x6c8, u8 val0x6cc) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, ", - (force_exec ? "force to" : ""), val0x6c0); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", - val0x6c4, val0x6c8, val0x6cc); - coex_dm->cur_val0x6c0 = val0x6c0; - coex_dm->cur_val0x6c4 = val0x6c4; - coex_dm->cur_val0x6c8 = val0x6c8; - coex_dm->cur_val0x6cc = val0x6cc; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], preVal0x6c0 = 0x%x, preVal0x6c4 = 0x%x, ", - coex_dm->pre_val0x6c0, coex_dm->pre_val0x6c4); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "preVal0x6c8 = 0x%x, preVal0x6cc = 0x%x !!\n", - coex_dm->pre_val0x6c8, coex_dm->pre_val0x6cc); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], curVal0x6c0 = 0x%x, curVal0x6c4 = 0x%x,\n", - coex_dm->cur_val0x6c0, coex_dm->cur_val0x6c4); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "curVal0x6c8 = 0x%x, curVal0x6cc = 0x%x !!\n", - coex_dm->cur_val0x6c8, coex_dm->cur_val0x6cc); - - if ((coex_dm->pre_val0x6c0 == coex_dm->cur_val0x6c0) && - (coex_dm->pre_val0x6c4 == coex_dm->cur_val0x6c4) && - (coex_dm->pre_val0x6c8 == coex_dm->cur_val0x6c8) && - (coex_dm->pre_val0x6cc == coex_dm->cur_val0x6cc)) - return; - } - halbtc8192e2ant_set_coex_table(btcoexist, val0x6c0, val0x6c4, - val0x6c8, val0x6cc); - - coex_dm->pre_val0x6c0 = coex_dm->cur_val0x6c0; - coex_dm->pre_val0x6c4 = coex_dm->cur_val0x6c4; - coex_dm->pre_val0x6c8 = coex_dm->cur_val0x6c8; - coex_dm->pre_val0x6cc = coex_dm->cur_val0x6cc; -} - -static void btc8192e2ant_coex_tbl_w_type(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - switch (type) { - case 0: - halbtc8192e2ant_coex_table(btcoexist, force_exec, 0x55555555, - 0x5a5a5a5a, 0xffffff, 0x3); - break; - case 1: - halbtc8192e2ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a, - 0x5a5a5a5a, 0xffffff, 0x3); - break; - case 2: - halbtc8192e2ant_coex_table(btcoexist, force_exec, 0x55555555, - 0x5ffb5ffb, 0xffffff, 0x3); - break; - case 3: - halbtc8192e2ant_coex_table(btcoexist, force_exec, 0xdfffdfff, - 0x5fdb5fdb, 0xffffff, 0x3); - break; - case 4: - halbtc8192e2ant_coex_table(btcoexist, force_exec, 0xdfffdfff, - 0x5ffb5ffb, 0xffffff, 0x3); - break; - default: - break; - } -} - -static void halbtc8192e2ant_set_fw_ignore_wlanact(struct btc_coexist *btcoexist, - bool enable) -{ - u8 h2c_parameter[1] = {0}; - - if (enable) - h2c_parameter[0] |= BIT0; /* function enable */ - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex]set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", - h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); -} - -static void halbtc8192e2ant_IgnoreWlanAct(struct btc_coexist *btcoexist, - bool force_exec, bool enable) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn Ignore WlanAct %s\n", - (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); - coex_dm->cur_ignore_wlan_act = enable; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], bPreIgnoreWlanAct = %d ", - coex_dm->pre_ignore_wlan_act); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "bCurIgnoreWlanAct = %d!!\n", - coex_dm->cur_ignore_wlan_act); - - if (coex_dm->pre_ignore_wlan_act == - coex_dm->cur_ignore_wlan_act) - return; - } - halbtc8192e2ant_set_fw_ignore_wlanact(btcoexist, enable); - - coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; -} - -static void halbtc8192e2ant_SetFwPstdma(struct btc_coexist *btcoexist, u8 byte1, - u8 byte2, u8 byte3, u8 byte4, u8 byte5) -{ - u8 h2c_parameter[5] = {0}; - - h2c_parameter[0] = byte1; - h2c_parameter[1] = byte2; - h2c_parameter[2] = byte3; - h2c_parameter[3] = byte4; - h2c_parameter[4] = byte5; - - coex_dm->ps_tdma_para[0] = byte1; - coex_dm->ps_tdma_para[1] = byte2; - coex_dm->ps_tdma_para[2] = byte3; - coex_dm->ps_tdma_para[3] = byte4; - coex_dm->ps_tdma_para[4] = byte5; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x60(5bytes) = 0x%x%08x\n", - h2c_parameter[0], - h2c_parameter[1] << 24 | h2c_parameter[2] << 16 | - h2c_parameter[3] << 8 | h2c_parameter[4]); - - btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); -} - -static void btc8192e2ant_sw_mec1(struct btc_coexist *btcoexist, - bool shrink_rx_lpf, bool low_penalty_ra, - bool limited_dig, bool btlan_constrain) -{ - halbtc8192e2ant_rf_shrink(btcoexist, NORMAL_EXEC, shrink_rx_lpf); -} - -static void btc8192e2ant_sw_mec2(struct btc_coexist *btcoexist, - bool agc_table_shift, bool adc_backoff, - bool sw_dac_swing, u32 dac_swinglvl) -{ - halbtc8192e2ant_AgcTable(btcoexist, NORMAL_EXEC, agc_table_shift); - halbtc8192e2ant_DacSwing(btcoexist, NORMAL_EXEC, sw_dac_swing, - dac_swinglvl); -} - -static void halbtc8192e2ant_ps_tdma(struct btc_coexist *btcoexist, - bool force_exec, bool turn_on, u8 type) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn %s PS TDMA, type=%d\n", - (force_exec ? "force to" : ""), - (turn_on ? "ON" : "OFF"), type); - coex_dm->cur_ps_tdma_on = turn_on; - coex_dm->cur_ps_tdma = type; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], bPrePsTdmaOn = %d, bCurPsTdmaOn = %d!!\n", - coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], prePsTdma = %d, curPsTdma = %d!!\n", - coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma); - - if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && - (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) - return; - } - if (turn_on) { - switch (type) { - case 1: - default: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0xe1, 0x90); - break; - case 2: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x12, - 0x12, 0xe1, 0x90); - break; - case 3: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1c, - 0x3, 0xf1, 0x90); - break; - case 4: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x10, - 0x3, 0xf1, 0x90); - break; - case 5: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0x60, 0x90); - break; - case 6: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x12, - 0x12, 0x60, 0x90); - break; - case 7: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1c, - 0x3, 0x70, 0x90); - break; - case 8: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xa3, 0x10, - 0x3, 0x70, 0x90); - break; - case 9: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0xe1, 0x10); - break; - case 10: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x12, - 0x12, 0xe1, 0x10); - break; - case 11: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1c, - 0x3, 0xf1, 0x10); - break; - case 12: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x10, - 0x3, 0xf1, 0x10); - break; - case 13: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0xe0, 0x10); - break; - case 14: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x12, - 0x12, 0xe0, 0x10); - break; - case 15: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1c, - 0x3, 0xf0, 0x10); - break; - case 16: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x12, - 0x3, 0xf0, 0x10); - break; - case 17: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0x61, 0x20, - 0x03, 0x10, 0x10); - break; - case 18: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x5, - 0x5, 0xe1, 0x90); - break; - case 19: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x25, - 0x25, 0xe1, 0x90); - break; - case 20: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x25, - 0x25, 0x60, 0x90); - break; - case 21: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x15, - 0x03, 0x70, 0x90); - break; - case 71: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0xe1, 0x90); - break; - } - } else { - /* disable PS tdma */ - switch (type) { - default: - case 0: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0x8, 0x0, 0x0, - 0x0, 0x0); - btcoexist->btc_write_1byte(btcoexist, 0x92c, 0x4); - break; - case 1: - halbtc8192e2ant_SetFwPstdma(btcoexist, 0x0, 0x0, 0x0, - 0x8, 0x0); - mdelay(5); - btcoexist->btc_write_1byte(btcoexist, 0x92c, 0x20); - break; - } - } - - /* update pre state */ - coex_dm->pre_ps_tdma_on = coex_dm->cur_ps_tdma_on; - coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; -} - -static void halbtc8192e2ant_set_switch_sstype(struct btc_coexist *btcoexist, - u8 sstype) -{ - u8 mimops = BTC_MIMO_PS_DYNAMIC; - u32 disra_mask = 0x0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], REAL set SS Type = %d\n", sstype); - - disra_mask = halbtc8192e2ant_decidera_mask(btcoexist, sstype, - coex_dm->curra_masktype); - halbtc8192e2ant_Updatera_mask(btcoexist, FORCE_EXEC, disra_mask); - - if (sstype == 1) { - halbtc8192e2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 1); - /* switch ofdm path */ - btcoexist->btc_write_1byte(btcoexist, 0xc04, 0x11); - btcoexist->btc_write_1byte(btcoexist, 0xd04, 0x1); - btcoexist->btc_write_4byte(btcoexist, 0x90c, 0x81111111); - /* switch cck patch */ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0xe77, 0x4, 0x1); - btcoexist->btc_write_1byte(btcoexist, 0xa07, 0x81); - mimops = BTC_MIMO_PS_STATIC; - } else if (sstype == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0); - btcoexist->btc_write_1byte(btcoexist, 0xc04, 0x33); - btcoexist->btc_write_1byte(btcoexist, 0xd04, 0x3); - btcoexist->btc_write_4byte(btcoexist, 0x90c, 0x81121313); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0xe77, 0x4, 0x0); - btcoexist->btc_write_1byte(btcoexist, 0xa07, 0x41); - mimops = BTC_MIMO_PS_DYNAMIC; - } - /* set rx 1ss or 2ss */ - btcoexist->btc_set(btcoexist, BTC_SET_ACT_SEND_MIMO_PS, &mimops); -} - -static void halbtc8192e2ant_switch_sstype(struct btc_coexist *btcoexist, - bool force_exec, u8 new_sstype) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], %s Switch SS Type = %d\n", - (force_exec ? "force to" : ""), new_sstype); - coex_dm->cur_sstype = new_sstype; - - if (!force_exec) { - if (coex_dm->pre_sstype == coex_dm->cur_sstype) - return; - } - halbtc8192e2ant_set_switch_sstype(btcoexist, coex_dm->cur_sstype); - - coex_dm->pre_sstype = coex_dm->cur_sstype; -} - -static void halbtc8192e2ant_coex_alloff(struct btc_coexist *btcoexist) -{ - /* fw all off */ - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - - /* sw all off */ - btc8192e2ant_sw_mec1(btcoexist, false, false, false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, false, 0x18); - - /* hw all off */ - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 0); -} - -static void halbtc8192e2ant_init_coex_dm(struct btc_coexist *btcoexist) -{ - /* force to reset coex mechanism */ - - halbtc8192e2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 1); - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, FORCE_EXEC, 6); - halbtc8192e2ant_dec_btpwr(btcoexist, FORCE_EXEC, 0); - - btc8192e2ant_coex_tbl_w_type(btcoexist, FORCE_EXEC, 0); - halbtc8192e2ant_switch_sstype(btcoexist, FORCE_EXEC, 2); - - btc8192e2ant_sw_mec1(btcoexist, false, false, false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, false, 0x18); -} - -static void halbtc8192e2ant_action_bt_inquiry(struct btc_coexist *btcoexist) -{ - bool low_pwr_disable = true; - - btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); - - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 2); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - - btc8192e2ant_sw_mec1(btcoexist, false, false, false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, false, 0x18); -} - -static bool halbtc8192e2ant_is_common_action(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool common = false, wifi_connected = false, wifi_busy = false; - bool bt_hson = false, low_pwr_disable = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hson); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - - if (bt_link_info->sco_exist || bt_link_info->hid_exist) - halbtc8192e2ant_limited_tx(btcoexist, NORMAL_EXEC, 1, 0, 0, 0); - else - halbtc8192e2ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); - - if (!wifi_connected) { - low_pwr_disable = false; - btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non-connected idle!!\n"); - - if ((BT_8192E_2ANT_BT_STATUS_NON_CONNECTED_IDLE == - coex_dm->bt_status) || - (BT_8192E_2ANT_BT_STATUS_CONNECTED_IDLE == - coex_dm->bt_status)) { - halbtc8192e2ant_switch_sstype(btcoexist, - NORMAL_EXEC, 2); - btc8192e2ant_coex_tbl_w_type(btcoexist, - NORMAL_EXEC, 1); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 0); - } else { - halbtc8192e2ant_switch_sstype(btcoexist, - NORMAL_EXEC, 1); - btc8192e2ant_coex_tbl_w_type(btcoexist, - NORMAL_EXEC, 0); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 1); - } - - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - - btc8192e2ant_sw_mec1(btcoexist, false, false, false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, false, 0x18); - - common = true; - } else { - if (BT_8192E_2ANT_BT_STATUS_NON_CONNECTED_IDLE == - coex_dm->bt_status) { - low_pwr_disable = false; - btcoexist->btc_set(btcoexist, - BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Wifi connected + BT non connected-idle!!\n"); - - halbtc8192e2ant_switch_sstype(btcoexist, - NORMAL_EXEC, 2); - btc8192e2ant_coex_tbl_w_type(btcoexist, - NORMAL_EXEC, 1); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 0); - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, - NORMAL_EXEC, 6); - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - - btc8192e2ant_sw_mec1(btcoexist, false, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - - common = true; - } else if (BT_8192E_2ANT_BT_STATUS_CONNECTED_IDLE == - coex_dm->bt_status) { - low_pwr_disable = true; - btcoexist->btc_set(btcoexist, - BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - if (bt_hson) - return false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Wifi connected + BT connected-idle!!\n"); - - halbtc8192e2ant_switch_sstype(btcoexist, - NORMAL_EXEC, 2); - btc8192e2ant_coex_tbl_w_type(btcoexist, - NORMAL_EXEC, 1); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 0); - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, - NORMAL_EXEC, 6); - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - - btc8192e2ant_sw_mec1(btcoexist, true, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - - common = true; - } else { - low_pwr_disable = true; - btcoexist->btc_set(btcoexist, - BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - if (wifi_busy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Wifi Connected-Busy + BT Busy!!\n"); - common = false; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Wifi Connected-Idle + BT Busy!!\n"); - - halbtc8192e2ant_switch_sstype(btcoexist, - NORMAL_EXEC, 1); - btc8192e2ant_coex_tbl_w_type(btcoexist, - NORMAL_EXEC, 2); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 21); - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, - NORMAL_EXEC, 6); - halbtc8192e2ant_dec_btpwr(btcoexist, - NORMAL_EXEC, 0); - btc8192e2ant_sw_mec1(btcoexist, false, - false, false, false); - btc8192e2ant_sw_mec2(btcoexist, false, - false, false, 0x18); - common = true; - } - } - } - return common; -} - -static void btc8192e_int1(struct btc_coexist *btcoexist, bool tx_pause, - int result) -{ - if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); - - if (coex_dm->cur_ps_tdma == 71) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - coex_dm->tdma_adj_type = 5; - } else if (coex_dm->cur_ps_tdma == 1) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - coex_dm->tdma_adj_type = 5; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 4) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } - if (coex_dm->cur_ps_tdma == 9) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 13); - coex_dm->tdma_adj_type = 13; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 12) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - - if (result == -1) { - if (coex_dm->cur_ps_tdma == 5) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } else if (coex_dm->cur_ps_tdma == 13) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 8) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - coex_dm->tdma_adj_type = 5; - } else if (coex_dm->cur_ps_tdma == 16) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 13); - coex_dm->tdma_adj_type = 13; - } - } - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); - if (coex_dm->cur_ps_tdma == 5) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 71); - coex_dm->tdma_adj_type = 71; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 8) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } - if (coex_dm->cur_ps_tdma == 13) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 16) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - - if (result == -1) { - if (coex_dm->cur_ps_tdma == 71) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 1); - coex_dm->tdma_adj_type = 1; - } else if (coex_dm->cur_ps_tdma == 1) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } else if (coex_dm->cur_ps_tdma == 9) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 4) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 1); - coex_dm->tdma_adj_type = 1; - } else if (coex_dm->cur_ps_tdma == 1) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 71); - coex_dm->tdma_adj_type = 71; - } else if (coex_dm->cur_ps_tdma == 12) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } - } - } -} - -static void btc8192e_int2(struct btc_coexist *btcoexist, bool tx_pause, - int result) -{ - if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); - if (coex_dm->cur_ps_tdma == 1) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 4) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } - if (coex_dm->cur_ps_tdma == 9) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 12) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - if (result == -1) { - if (coex_dm->cur_ps_tdma == 5) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } else if (coex_dm->cur_ps_tdma == 13) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 8) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 16) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } - } - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); - if (coex_dm->cur_ps_tdma == 5) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 8) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } - if (coex_dm->cur_ps_tdma == 13) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 16) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - if (result == -1) { - if (coex_dm->cur_ps_tdma == 1) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } else if (coex_dm->cur_ps_tdma == 9) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 4) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 12) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } - } - } -} - -static void btc8192e_int3(struct btc_coexist *btcoexist, bool tx_pause, - int result) -{ - if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); - if (coex_dm->cur_ps_tdma == 1) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 4) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } - if (coex_dm->cur_ps_tdma == 9) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 12) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - if (result == -1) { - if (coex_dm->cur_ps_tdma == 5) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } else if (coex_dm->cur_ps_tdma == 13) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 8) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 16) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } - } - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); - if (coex_dm->cur_ps_tdma == 5) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 8) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } - if (coex_dm->cur_ps_tdma == 13) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 16) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - if (result == -1) { - if (coex_dm->cur_ps_tdma == 1) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } else if (coex_dm->cur_ps_tdma == 9) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 4) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 12) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } - } - } -} - -static void halbtc8192e2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, - bool sco_hid, bool tx_pause, - u8 max_interval) -{ - static int up, dn, m, n, wait_cnt; - /* 0: no change, +1: increase WiFi duration, - * -1: decrease WiFi duration - */ - int result; - u8 retry_cnt = 0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], TdmaDurationAdjust()\n"); - - if (!coex_dm->auto_tdma_adjust) { - coex_dm->auto_tdma_adjust = true; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], first run TdmaDurationAdjust()!!\n"); - if (sco_hid) { - if (tx_pause) { - if (max_interval == 1) { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 13); - coex_dm->tdma_adj_type = 13; - } else if (max_interval == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (max_interval == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } - } else { - if (max_interval == 1) { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (max_interval == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (max_interval == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } - } - } else { - if (tx_pause) { - if (max_interval == 1) { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 5); - coex_dm->tdma_adj_type = 5; - } else if (max_interval == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (max_interval == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } - } else { - if (max_interval == 1) { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 1); - coex_dm->tdma_adj_type = 1; - } else if (max_interval == 2) { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (max_interval == 3) { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else { - halbtc8192e2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } - } - } - - up = 0; - dn = 0; - m = 1; - n = 3; - result = 0; - wait_cnt = 0; - } else { - /* accquire the BT TRx retry count from BT_Info byte2 */ - retry_cnt = coex_sta->bt_retry_cnt; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], retry_cnt = %d\n", retry_cnt); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], up=%d, dn=%d, m=%d, n=%d, wait_cnt=%d\n", - up, dn, m, n, wait_cnt); - result = 0; - wait_cnt++; - /* no retry in the last 2-second duration */ - if (retry_cnt == 0) { - up++; - dn--; - - if (dn <= 0) - dn = 0; - - if (up >= n) { - wait_cnt = 0; - n = 3; - up = 0; - dn = 0; - result = 1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex]Increase wifi duration!!\n"); - } - } else if (retry_cnt <= 3) { - up--; - dn++; - - if (up <= 0) - up = 0; - - if (dn == 2) { - if (wait_cnt <= 2) - m++; - else - m = 1; - - if (m >= 20) - m = 20; - - n = 3 * m; - up = 0; - dn = 0; - wait_cnt = 0; - result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "Reduce wifi duration for retry<3\n"); - } - } else { - if (wait_cnt == 1) - m++; - else - m = 1; - - if (m >= 20) - m = 20; - - n = 3*m; - up = 0; - dn = 0; - wait_cnt = 0; - result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "Decrease wifi duration for retryCounter>3!!\n"); - } - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], max Interval = %d\n", max_interval); - if (max_interval == 1) - btc8192e_int1(btcoexist, tx_pause, result); - else if (max_interval == 2) - btc8192e_int2(btcoexist, tx_pause, result); - else if (max_interval == 3) - btc8192e_int3(btcoexist, tx_pause, result); - } - - /* if current PsTdma not match with - * the recorded one (when scan, dhcp...), - * then we have to adjust it back to the previous record one. - */ - if (coex_dm->cur_ps_tdma != coex_dm->tdma_adj_type) { - bool scan = false, link = false, roam = false; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], PsTdma type dismatch!!!, "); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "curPsTdma=%d, recordPsTdma=%d\n", - coex_dm->cur_ps_tdma, coex_dm->tdma_adj_type); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); - - if (!scan && !link && !roam) - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, - coex_dm->tdma_adj_type); - else - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n"); - } -} - -/* SCO only or SCO+PAN(HS) */ -static void halbtc8192e2ant_action_sco(struct btc_coexist *btcoexist) -{ - u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_STAY_LOW; - u32 wifi_bw; - - wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); - - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); - halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); - - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 4); - - btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); - - if ((btrssi_state == BTC_RSSI_STATE_LOW) || - (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13); - } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || - (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9); - } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || - (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9); - } - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, true, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x6); - } else { - btc8192e2ant_sw_mec1(btcoexist, true, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x6); - } - } else { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, false, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x6); - } else { - btc8192e2ant_sw_mec1(btcoexist, false, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x6); - } - } -} - -static void halbtc8192e2ant_action_sco_pan(struct btc_coexist *btcoexist) -{ - u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_STAY_LOW; - u32 wifi_bw; - - wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); - - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); - halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); - - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 4); - - btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); - - if ((btrssi_state == BTC_RSSI_STATE_LOW) || - (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14); - } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || - (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 10); - } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || - (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 10); - } - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, true, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x6); - } else { - btc8192e2ant_sw_mec1(btcoexist, true, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x6); - } - } else { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, false, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x6); - } else { - btc8192e2ant_sw_mec1(btcoexist, false, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x6); - } - } -} - -static void halbtc8192e2ant_action_hid(struct btc_coexist *btcoexist) -{ - u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; - u32 wifi_bw; - - wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); - btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); - - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); - halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); - - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 3); - - if ((btrssi_state == BTC_RSSI_STATE_LOW) || - (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13); - } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || - (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9); - } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || - (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9); - } - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, true, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, true, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, false, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, false, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } -} - -/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */ -static void halbtc8192e2ant_action_a2dp(struct btc_coexist *btcoexist) -{ - u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; - u32 wifi_bw; - bool long_dist = false; - - wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); - btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); - - if ((btrssi_state == BTC_RSSI_STATE_LOW || - btrssi_state == BTC_RSSI_STATE_STAY_LOW) && - (wifirssi_state == BTC_RSSI_STATE_LOW || - wifirssi_state == BTC_RSSI_STATE_STAY_LOW)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], A2dp, wifi/bt rssi both LOW!!\n"); - long_dist = true; - } - if (long_dist) { - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 2); - halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, true, - 0x4); - } else { - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); - halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, - 0x8); - } - - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - - if (long_dist) - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 0); - else - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 2); - - if (long_dist) { - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 17); - coex_dm->auto_tdma_adjust = false; - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - } else { - if ((btrssi_state == BTC_RSSI_STATE_LOW) || - (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { - halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, - true, 1); - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || - (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { - halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, - false, 1); - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); - } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || - (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, - false, 1); - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); - } - } - - /* sw mechanism */ - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, true, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, true, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, false, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, false, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void halbtc8192e2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) -{ - u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; - u32 wifi_bw; - - wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); - btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); - - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); - halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); - - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 2); - - if ((btrssi_state == BTC_RSSI_STATE_LOW) || - (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { - halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, true, 2); - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || - (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { - halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, - false, 2); - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); - } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || - (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, - false, 2); - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); - } - - /* sw mechanism */ - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, true, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - true, 0x6); - } else { - btc8192e2ant_sw_mec1(btcoexist, true, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - true, 0x6); - } - } else { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, false, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - true, 0x6); - } else { - btc8192e2ant_sw_mec1(btcoexist, false, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - true, 0x6); - } - } -} - -static void halbtc8192e2ant_action_pan_edr(struct btc_coexist *btcoexist) -{ - u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; - u32 wifi_bw; - - wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); - btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); - - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); - halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); - - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 2); - - if ((btrssi_state == BTC_RSSI_STATE_LOW) || - (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); - } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || - (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 1); - } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || - (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 1); - } - - /* sw mechanism */ - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, true, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, true, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, false, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, false, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } -} - -/* PAN(HS) only */ -static void halbtc8192e2ant_action_pan_hs(struct btc_coexist *btcoexist) -{ - u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; - u32 wifi_bw; - - wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); - btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); - - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); - halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); - - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 2); - - if ((btrssi_state == BTC_RSSI_STATE_LOW) || - (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || - (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); - } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || - (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); - } - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, true, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, true, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, false, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, false, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } -} - -/* PAN(EDR)+A2DP */ -static void halbtc8192e2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) -{ - u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; - u32 wifi_bw; - - wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); - btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); - - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); - halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); - - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 2); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if ((btrssi_state == BTC_RSSI_STATE_LOW) || - (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, true, 3); - } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || - (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); - halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, - false, 3); - } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || - (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); - halbtc8192e2ant_tdma_duration_adjust(btcoexist, false, - false, 3); - } - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, true, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, true, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, false, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, false, false, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void halbtc8192e2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) -{ - u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; - u32 wifi_bw; - - wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); - btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); - halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); - - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 3); - - if ((btrssi_state == BTC_RSSI_STATE_LOW) || - (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14); - } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || - (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || - (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); - halbtc8192e2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - } - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, true, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, true, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, false, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, false, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } -} - -/* HID+A2DP+PAN(EDR) */ -static void btc8192e2ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) -{ - u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; - u32 wifi_bw; - - wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); - btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); - - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); - halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); - - halbtc8192e2ant_fw_dac_swinglvl(btcoexist, NORMAL_EXEC, 6); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 3); - - if ((btrssi_state == BTC_RSSI_STATE_LOW) || - (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - halbtc8192e2ant_tdma_duration_adjust(btcoexist, true, true, 3); - } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || - (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); - halbtc8192e2ant_tdma_duration_adjust(btcoexist, true, false, 3); - } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || - (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); - halbtc8192e2ant_tdma_duration_adjust(btcoexist, true, false, 3); - } - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, true, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, true, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, false, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, false, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void halbtc8192e2ant_action_hid_a2dp(struct btc_coexist *btcoexist) -{ - u8 wifirssi_state, btrssi_state = BTC_RSSI_STATE_HIGH; - u32 wifi_bw; - - wifirssi_state = halbtc8192e2ant_wifirssi_state(btcoexist, 0, 2, 15, 0); - btrssi_state = halbtc8192e2ant_btrssi_state(3, 34, 42); - - halbtc8192e2ant_switch_sstype(btcoexist, NORMAL_EXEC, 1); - halbtc8192e2ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 0x8); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - btc8192e2ant_coex_tbl_w_type(btcoexist, NORMAL_EXEC, 3); - - if ((btrssi_state == BTC_RSSI_STATE_LOW) || - (btrssi_state == BTC_RSSI_STATE_STAY_LOW)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 0); - halbtc8192e2ant_tdma_duration_adjust(btcoexist, true, true, 2); - } else if ((btrssi_state == BTC_RSSI_STATE_MEDIUM) || - (btrssi_state == BTC_RSSI_STATE_STAY_MEDIUM)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 2); - halbtc8192e2ant_tdma_duration_adjust(btcoexist, true, false, 2); - } else if ((btrssi_state == BTC_RSSI_STATE_HIGH) || - (btrssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8192e2ant_dec_btpwr(btcoexist, NORMAL_EXEC, 4); - halbtc8192e2ant_tdma_duration_adjust(btcoexist, true, false, 2); - } - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, true, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, true, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifirssi_state == BTC_RSSI_STATE_HIGH) || - (wifirssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8192e2ant_sw_mec1(btcoexist, false, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, true, false, - false, 0x18); - } else { - btc8192e2ant_sw_mec1(btcoexist, false, true, - false, false); - btc8192e2ant_sw_mec2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void halbtc8192e2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) -{ - u8 algorithm = 0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism()===>\n"); - - if (btcoexist->manual_control) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], return for Manual CTRL <===\n"); - return; - } - - if (coex_sta->under_ips) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], wifi is under IPS !!!\n"); - return; - } - - algorithm = halbtc8192e2ant_action_algorithm(btcoexist); - if (coex_sta->c2h_bt_inquiry_page && - (BT_8192E_2ANT_COEX_ALGO_PANHS != algorithm)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT is under inquiry/page scan !!\n"); - halbtc8192e2ant_action_bt_inquiry(btcoexist); - return; - } - - coex_dm->cur_algorithm = algorithm; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Algorithm = %d\n", coex_dm->cur_algorithm); - - if (halbtc8192e2ant_is_common_action(btcoexist)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant common.\n"); - coex_dm->auto_tdma_adjust = false; - } else { - if (coex_dm->cur_algorithm != coex_dm->pre_algorithm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex] preAlgorithm=%d, curAlgorithm=%d\n", - coex_dm->pre_algorithm, - coex_dm->cur_algorithm); - coex_dm->auto_tdma_adjust = false; - } - switch (coex_dm->cur_algorithm) { - case BT_8192E_2ANT_COEX_ALGO_SCO: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = SCO.\n"); - halbtc8192e2ant_action_sco(btcoexist); - break; - case BT_8192E_2ANT_COEX_ALGO_SCO_PAN: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = SCO+PAN(EDR).\n"); - halbtc8192e2ant_action_sco_pan(btcoexist); - break; - case BT_8192E_2ANT_COEX_ALGO_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = HID.\n"); - halbtc8192e2ant_action_hid(btcoexist); - break; - case BT_8192E_2ANT_COEX_ALGO_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = A2DP.\n"); - halbtc8192e2ant_action_a2dp(btcoexist); - break; - case BT_8192E_2ANT_COEX_ALGO_A2DP_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = A2DP+PAN(HS).\n"); - halbtc8192e2ant_action_a2dp_pan_hs(btcoexist); - break; - case BT_8192E_2ANT_COEX_ALGO_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = PAN(EDR).\n"); - halbtc8192e2ant_action_pan_edr(btcoexist); - break; - case BT_8192E_2ANT_COEX_ALGO_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = HS mode.\n"); - halbtc8192e2ant_action_pan_hs(btcoexist); - break; - case BT_8192E_2ANT_COEX_ALGO_PANEDR_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = PAN+A2DP.\n"); - halbtc8192e2ant_action_pan_edr_a2dp(btcoexist); - break; - case BT_8192E_2ANT_COEX_ALGO_PANEDR_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = PAN(EDR)+HID.\n"); - halbtc8192e2ant_action_pan_edr_hid(btcoexist); - break; - case BT_8192E_2ANT_COEX_ALGO_HID_A2DP_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = HID+A2DP+PAN.\n"); - btc8192e2ant_action_hid_a2dp_pan_edr(btcoexist); - break; - case BT_8192E_2ANT_COEX_ALGO_HID_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = HID+A2DP.\n"); - halbtc8192e2ant_action_hid_a2dp(btcoexist); - break; - default: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "Action 2-Ant, algorithm = unknown!!\n"); - /* halbtc8192e2ant_coex_alloff(btcoexist); */ - break; - } - coex_dm->pre_algorithm = coex_dm->cur_algorithm; - } -} - -static void halbtc8192e2ant_init_hwconfig(struct btc_coexist *btcoexist, - bool backup) -{ - u16 u16tmp = 0; - u8 u8tmp = 0; - - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], 2Ant Init HW Config!!\n"); - - if (backup) { - /* backup rf 0x1e value */ - coex_dm->bt_rf0x1e_backup = - btcoexist->btc_get_rf_reg(btcoexist, BTC_RF_A, - 0x1e, 0xfffff); - - coex_dm->backup_arfr_cnt1 = btcoexist->btc_read_4byte(btcoexist, - 0x430); - coex_dm->backup_arfr_cnt2 = btcoexist->btc_read_4byte(btcoexist, - 0x434); - coex_dm->backup_retrylimit = btcoexist->btc_read_2byte( - btcoexist, - 0x42a); - coex_dm->backup_ampdu_maxtime = btcoexist->btc_read_1byte( - btcoexist, - 0x456); - } - - /* antenna sw ctrl to bt */ - btcoexist->btc_write_1byte(btcoexist, 0x4f, 0x6); - btcoexist->btc_write_1byte(btcoexist, 0x944, 0x24); - btcoexist->btc_write_4byte(btcoexist, 0x930, 0x700700); - btcoexist->btc_write_1byte(btcoexist, 0x92c, 0x20); - if (btcoexist->chip_interface == BTC_INTF_USB) - btcoexist->btc_write_4byte(btcoexist, 0x64, 0x30430004); - else - btcoexist->btc_write_4byte(btcoexist, 0x64, 0x30030004); - - btc8192e2ant_coex_tbl_w_type(btcoexist, FORCE_EXEC, 0); - - /* antenna switch control parameter */ - btcoexist->btc_write_4byte(btcoexist, 0x858, 0x55555555); - - /* coex parameters */ - btcoexist->btc_write_1byte(btcoexist, 0x778, 0x3); - /* 0x790[5:0] = 0x5 */ - u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x790); - u8tmp &= 0xc0; - u8tmp |= 0x5; - btcoexist->btc_write_1byte(btcoexist, 0x790, u8tmp); - - /* enable counter statistics */ - btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4); - - /* enable PTA */ - btcoexist->btc_write_1byte(btcoexist, 0x40, 0x20); - /* enable mailbox interface */ - u16tmp = btcoexist->btc_read_2byte(btcoexist, 0x40); - u16tmp |= BIT9; - btcoexist->btc_write_2byte(btcoexist, 0x40, u16tmp); - - /* enable PTA I2C mailbox */ - u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x101); - u8tmp |= BIT4; - btcoexist->btc_write_1byte(btcoexist, 0x101, u8tmp); - - /* enable bt clock when wifi is disabled. */ - u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x93); - u8tmp |= BIT0; - btcoexist->btc_write_1byte(btcoexist, 0x93, u8tmp); - /* enable bt clock when suspend. */ - u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x7); - u8tmp |= BIT0; - btcoexist->btc_write_1byte(btcoexist, 0x7, u8tmp); -} - -/************************************************************* - * work around function start with wa_halbtc8192e2ant_ - *************************************************************/ - -/************************************************************ - * extern function start with EXhalbtc8192e2ant_ - ************************************************************/ - -void ex_halbtc8192e2ant_init_hwconfig(struct btc_coexist *btcoexist) -{ - halbtc8192e2ant_init_hwconfig(btcoexist, true); -} - -void ex_halbtc8192e2ant_init_coex_dm(struct btc_coexist *btcoexist) -{ - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Coex Mechanism Init!!\n"); - halbtc8192e2ant_init_coex_dm(btcoexist); -} - -void ex_halbtc8192e2ant_display_coex_info(struct btc_coexist *btcoexist) -{ - struct btc_board_info *board_info = &btcoexist->board_info; - struct btc_stack_info *stack_info = &btcoexist->stack_info; - struct rtl_priv *rtlpriv = btcoexist->adapter; - u8 u8tmp[4], i, bt_info_ext, ps_tdma_case = 0; - u16 u16tmp[4]; - u32 u32tmp[4]; - bool roam = false, scan = false, link = false, wifi_under_5g = false; - bool bt_hson = false, wifi_busy = false; - int wifirssi = 0, bt_hs_rssi = 0; - u32 wifi_bw, wifi_traffic_dir; - u8 wifi_dot11_chnl, wifi_hs_chnl; - u32 fw_ver = 0, bt_patch_ver = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n ============[BT Coexist info]============"); - - if (btcoexist->manual_control) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n ===========[Under Manual Control]==========="); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n =========================================="); - } - - if (!board_info->bt_exist) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n BT not exists !!!"); - return; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d/ %d ", "Ant PG number/ Ant mechanism:", - board_info->pg_ant_num, board_info->btdm_ant_num); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s / %d", - "BT stack/ hci ext ver", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d_%d/ 0x%x/ 0x%x(%d)", - "CoexVer/ FwVer/ PatchVer", - glcoex_ver_date_8192e_2ant, glcoex_ver_8192e_2ant, - fw_ver, bt_patch_ver, bt_patch_ver); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hson); - btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_DOT11_CHNL, - &wifi_dot11_chnl); - btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_HS_CHNL, &wifi_hs_chnl); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d / %d(%d)", - "Dot11 channel / HsMode(HsChnl)", - wifi_dot11_chnl, bt_hson, wifi_hs_chnl); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %02x %02x %02x ", - "H2C Wifi inform bt chnl Info", coex_dm->wifi_chnl_info[0], - coex_dm->wifi_chnl_info[1], coex_dm->wifi_chnl_info[2]); - - btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifirssi); - btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", - "Wifi rssi/ HS rssi", wifirssi, bt_hs_rssi); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d ", - "Wifi link/ roam/ scan", link, roam, scan); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, - &wifi_traffic_dir); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s / %s/ %s ", - "Wifi status", (wifi_under_5g ? "5G" : "2.4G"), - ((BTC_WIFI_BW_LEGACY == wifi_bw) ? "Legacy" : - (((BTC_WIFI_BW_HT40 == wifi_bw) ? "HT40" : "HT20"))), - ((!wifi_busy) ? "idle" : - ((BTC_WIFI_TRAFFIC_TX == wifi_traffic_dir) ? - "uplink" : "downlink"))); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = [%s/ %d/ %d] ", - "BT [status/ rssi/ retryCnt]", - ((btcoexist->bt_info.bt_disabled) ? ("disabled") : - ((coex_sta->c2h_bt_inquiry_page) ? - ("inquiry/page scan") : - ((BT_8192E_2ANT_BT_STATUS_NON_CONNECTED_IDLE == - coex_dm->bt_status) ? "non-connected idle" : - ((BT_8192E_2ANT_BT_STATUS_CONNECTED_IDLE == - coex_dm->bt_status) ? "connected-idle" : "busy")))), - coex_sta->bt_rssi, coex_sta->bt_retry_cnt); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d / %d / %d / %d", - "SCO/HID/PAN/A2DP", stack_info->sco_exist, - stack_info->hid_exist, stack_info->pan_exist, - stack_info->a2dp_exist); - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_BT_LINK_INFO); - - bt_info_ext = coex_sta->bt_info_ext; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s", - "BT Info A2DP rate", - (bt_info_ext&BIT0) ? "Basic rate" : "EDR rate"); - - for (i = 0; i < BT_INFO_SRC_8192E_2ANT_MAX; i++) { - if (coex_sta->bt_info_c2h_cnt[i]) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %02x %02x %02x %02x ", - GLBtInfoSrc8192e2Ant[i], - coex_sta->bt_info_c2h[i][0], - coex_sta->bt_info_c2h[i][1], - coex_sta->bt_info_c2h[i][2], - coex_sta->bt_info_c2h[i][3]); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "%02x %02x %02x(%d)", - coex_sta->bt_info_c2h[i][4], - coex_sta->bt_info_c2h[i][5], - coex_sta->bt_info_c2h[i][6], - coex_sta->bt_info_c2h_cnt[i]); - } - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s/%s", - "PS state, IPS/LPS", - ((coex_sta->under_ips ? "IPS ON" : "IPS OFF")), - ((coex_sta->under_lps ? "LPS ON" : "LPS OFF"))); - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x ", "SS Type", - coex_dm->cur_sstype); - - /* Sw mechanism */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", - "============[Sw mechanism]============"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d ", - "SM1[ShRf/ LpRA/ LimDig]", coex_dm->cur_rf_rx_lpf_shrink, - coex_dm->cur_low_penalty_ra, coex_dm->limited_dig); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d(0x%x) ", - "SM2[AgcT/ AdcB/ SwDacSwing(lvl)]", - coex_dm->cur_agc_table_en, coex_dm->cur_adc_back_off, - coex_dm->cur_dac_swing_on, coex_dm->cur_dac_swing_lvl); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x ", "Rate Mask", - btcoexist->bt_info.ra_mask); - - /* Fw mechanism */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", - "============[Fw mechanism]============"); - - ps_tdma_case = coex_dm->cur_ps_tdma; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", - "PS TDMA", coex_dm->ps_tdma_para[0], - coex_dm->ps_tdma_para[1], coex_dm->ps_tdma_para[2], - coex_dm->ps_tdma_para[3], coex_dm->ps_tdma_para[4], - ps_tdma_case, coex_dm->auto_tdma_adjust); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d ", - "DecBtPwr/ IgnWlanAct", - coex_dm->cur_dec_bt_pwr, coex_dm->cur_ignore_wlan_act); - - /* Hw setting */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", - "============[Hw setting]============"); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x", - "RF-A, 0x1e initVal", coex_dm->bt_rf0x1e_backup); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", - "backup ARFR1/ARFR2/RL/AMaxTime", coex_dm->backup_arfr_cnt1, - coex_dm->backup_arfr_cnt2, coex_dm->backup_retrylimit, - coex_dm->backup_ampdu_maxtime); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x430); - u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x434); - u16tmp[0] = btcoexist->btc_read_2byte(btcoexist, 0x42a); - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x456); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", - "0x430/0x434/0x42a/0x456", - u32tmp[0], u32tmp[1], u16tmp[0], u8tmp[0]); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc04); - u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0xd04); - u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x90c); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "0xc04/ 0xd04/ 0x90c", u32tmp[0], u32tmp[1], u32tmp[2]); - - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x778); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x", "0x778", - u8tmp[0]); - - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x92c); - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x930); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "0x92c/ 0x930", (u8tmp[0]), u32tmp[0]); - - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x40); - u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x4f); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "0x40/ 0x4f", u8tmp[0], u8tmp[1]); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x550); - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x522); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "0x550(bcn ctrl)/0x522", u32tmp[0], u8tmp[0]); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc50); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x", "0xc50(dig)", - u32tmp[0]); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6c0); - u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x6c4); - u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x6c8); - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x6cc); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", - "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)", - u32tmp[0], u32tmp[1], u32tmp[2], u8tmp[0]); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", - "0x770(hp rx[31:16]/tx[15:0])", - coex_sta->high_priority_rx, coex_sta->high_priority_tx); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", - "0x774(lp rx[31:16]/tx[15:0])", - coex_sta->low_priority_rx, coex_sta->low_priority_tx); -#if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 1) - halbtc8192e2ant_monitor_bt_ctr(btcoexist); -#endif - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS); -} - -void ex_halbtc8192e2ant_ips_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (BTC_IPS_ENTER == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS ENTER notify\n"); - coex_sta->under_ips = true; - halbtc8192e2ant_coex_alloff(btcoexist); - } else if (BTC_IPS_LEAVE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS LEAVE notify\n"); - coex_sta->under_ips = false; - } -} - -void ex_halbtc8192e2ant_lps_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (BTC_LPS_ENABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS ENABLE notify\n"); - coex_sta->under_lps = true; - } else if (BTC_LPS_DISABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS DISABLE notify\n"); - coex_sta->under_lps = false; - } -} - -void ex_halbtc8192e2ant_scan_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (BTC_SCAN_START == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN START notify\n"); - else if (BTC_SCAN_FINISH == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN FINISH notify\n"); -} - -void ex_halbtc8192e2ant_connect_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (BTC_ASSOCIATE_START == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT START notify\n"); - else if (BTC_ASSOCIATE_FINISH == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT FINISH notify\n"); -} - -void ex_halbtc8192e2ant_media_status_notify(struct btc_coexist *btcoexist, - u8 type) -{ - u8 h2c_parameter[3] = {0}; - u32 wifi_bw; - u8 wifi_center_chnl; - - if (btcoexist->manual_control || - btcoexist->stop_coex_dm || - btcoexist->bt_info.bt_disabled) - return; - - if (BTC_MEDIA_CONNECT == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA connect notify\n"); - else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA disconnect notify\n"); - - /* only 2.4G we need to inform bt the chnl mask */ - btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, - &wifi_center_chnl); - if ((BTC_MEDIA_CONNECT == type) && - (wifi_center_chnl <= 14)) { - h2c_parameter[0] = 0x1; - h2c_parameter[1] = wifi_center_chnl; - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) - h2c_parameter[2] = 0x30; - else - h2c_parameter[2] = 0x20; - } - - coex_dm->wifi_chnl_info[0] = h2c_parameter[0]; - coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; - coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x66 = 0x%x\n", - h2c_parameter[0] << 16 | h2c_parameter[1] << 8 | - h2c_parameter[2]); - - btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); -} - -void ex_halbtc8192e2ant_special_packet_notify(struct btc_coexist *btcoexist, - u8 type) -{ - if (type == BTC_PACKET_DHCP) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], DHCP Packet notify\n"); -} - -void ex_halbtc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist, - u8 *tmp_buf, u8 length) -{ - u8 bt_info = 0; - u8 i, rsp_source = 0; - bool bt_busy = false, limited_dig = false; - bool wifi_connected = false; - - coex_sta->c2h_bt_info_req_sent = false; - - rsp_source = tmp_buf[0] & 0xf; - if (rsp_source >= BT_INFO_SRC_8192E_2ANT_MAX) - rsp_source = BT_INFO_SRC_8192E_2ANT_WIFI_FW; - coex_sta->bt_info_c2h_cnt[rsp_source]++; - - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Bt info[%d], length=%d, hex data = [", - rsp_source, length); - for (i = 0; i < length; i++) { - coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i]; - if (i == 1) - bt_info = tmp_buf[i]; - if (i == length-1) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x]\n", tmp_buf[i]); - else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x, ", tmp_buf[i]); - } - - if (BT_INFO_SRC_8192E_2ANT_WIFI_FW != rsp_source) { - coex_sta->bt_retry_cnt = /* [3:0] */ - coex_sta->bt_info_c2h[rsp_source][2] & 0xf; - - coex_sta->bt_rssi = - coex_sta->bt_info_c2h[rsp_source][3] * 2 + 10; - - coex_sta->bt_info_ext = - coex_sta->bt_info_c2h[rsp_source][4]; - - /* Here we need to resend some wifi info to BT - * because bt is reset and loss of the info. - */ - if ((coex_sta->bt_info_ext & BIT1)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "bit1, send wifi BW&Chnl to BT!!\n"); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - if (wifi_connected) - ex_halbtc8192e2ant_media_status_notify( - btcoexist, - BTC_MEDIA_CONNECT); - else - ex_halbtc8192e2ant_media_status_notify( - btcoexist, - BTC_MEDIA_DISCONNECT); - } - - if ((coex_sta->bt_info_ext & BIT3)) { - if (!btcoexist->manual_control && - !btcoexist->stop_coex_dm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "bit3, BT NOT ignore Wlan active!\n"); - halbtc8192e2ant_IgnoreWlanAct(btcoexist, - FORCE_EXEC, - false); - } - } else { - /* BT already NOT ignore Wlan active, - * do nothing here. - */ - } - -#if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 0) - if ((coex_sta->bt_info_ext & BIT4)) { - /* BT auto report already enabled, do nothing */ - } else { - halbtc8192e2ant_bt_autoreport(btcoexist, FORCE_EXEC, - true); - } -#endif - } - - /* check BIT2 first ==> check if bt is under inquiry or page scan */ - if (bt_info & BT_INFO_8192E_2ANT_B_INQ_PAGE) - coex_sta->c2h_bt_inquiry_page = true; - else - coex_sta->c2h_bt_inquiry_page = false; - - /* set link exist status */ - if (!(bt_info&BT_INFO_8192E_2ANT_B_CONNECTION)) { - coex_sta->bt_link_exist = false; - coex_sta->pan_exist = false; - coex_sta->a2dp_exist = false; - coex_sta->hid_exist = false; - coex_sta->sco_exist = false; - } else {/* connection exists */ - coex_sta->bt_link_exist = true; - if (bt_info & BT_INFO_8192E_2ANT_B_FTP) - coex_sta->pan_exist = true; - else - coex_sta->pan_exist = false; - if (bt_info & BT_INFO_8192E_2ANT_B_A2DP) - coex_sta->a2dp_exist = true; - else - coex_sta->a2dp_exist = false; - if (bt_info & BT_INFO_8192E_2ANT_B_HID) - coex_sta->hid_exist = true; - else - coex_sta->hid_exist = false; - if (bt_info & BT_INFO_8192E_2ANT_B_SCO_ESCO) - coex_sta->sco_exist = true; - else - coex_sta->sco_exist = false; - } - - halbtc8192e2ant_update_btlink_info(btcoexist); - - if (!(bt_info&BT_INFO_8192E_2ANT_B_CONNECTION)) { - coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_NON_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Non-Connected idle!!!\n"); - } else if (bt_info == BT_INFO_8192E_2ANT_B_CONNECTION) { - coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], bt_infoNotify(), BT Connected-idle!!!\n"); - } else if ((bt_info&BT_INFO_8192E_2ANT_B_SCO_ESCO) || - (bt_info&BT_INFO_8192E_2ANT_B_SCO_BUSY)) { - coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_SCO_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], bt_infoNotify(), BT SCO busy!!!\n"); - } else if (bt_info&BT_INFO_8192E_2ANT_B_ACL_BUSY) { - coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_ACL_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], bt_infoNotify(), BT ACL busy!!!\n"); - } else { - coex_dm->bt_status = BT_8192E_2ANT_BT_STATUS_MAX; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex]bt_infoNotify(), BT Non-Defined state!!!\n"); - } - - if ((BT_8192E_2ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || - (BT_8192E_2ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || - (BT_8192E_2ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) { - bt_busy = true; - limited_dig = true; - } else { - bt_busy = false; - limited_dig = false; - } - - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy); - - coex_dm->limited_dig = limited_dig; - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_LIMITED_DIG, &limited_dig); - - halbtc8192e2ant_run_coexist_mechanism(btcoexist); -} - -void ex_halbtc8192e2ant_stack_operation_notify(struct btc_coexist *btcoexist, - u8 type) -{ -} - -void ex_halbtc8192e2ant_halt_notify(struct btc_coexist *btcoexist) -{ - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "[BTCoex], Halt notify\n"); - - halbtc8192e2ant_IgnoreWlanAct(btcoexist, FORCE_EXEC, true); - ex_halbtc8192e2ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT); -} - -void ex_halbtc8192e2ant_periodical(struct btc_coexist *btcoexist) -{ - static u8 dis_ver_info_cnt; - u32 fw_ver = 0, bt_patch_ver = 0; - struct btc_board_info *board_info = &btcoexist->board_info; - struct btc_stack_info *stack_info = &btcoexist->stack_info; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "=======================Periodical=======================\n"); - if (dis_ver_info_cnt <= 5) { - dis_ver_info_cnt += 1; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "************************************************\n"); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", - board_info->pg_ant_num, board_info->btdm_ant_num, - board_info->btdm_ant_pos); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "BT stack/ hci ext ver = %s / %d\n", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); - btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, - &bt_patch_ver); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", - glcoex_ver_date_8192e_2ant, glcoex_ver_8192e_2ant, - fw_ver, bt_patch_ver, bt_patch_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "************************************************\n"); - } - -#if (BT_AUTO_REPORT_ONLY_8192E_2ANT == 0) - halbtc8192e2ant_querybt_info(btcoexist); - halbtc8192e2ant_monitor_bt_ctr(btcoexist); - btc8192e2ant_monitor_bt_enable_dis(btcoexist); -#else - if (halbtc8192e2ant_iswifi_status_changed(btcoexist) || - coex_dm->auto_tdma_adjust) - halbtc8192e2ant_run_coexist_mechanism(btcoexist); -#endif -} diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.h deleted file mode 100644 index 75e1f7d0db06..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8192e2ant.h +++ /dev/null @@ -1,185 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -/***************************************************************** - * The following is for 8192E 2Ant BT Co-exist definition - *****************************************************************/ -#define BT_AUTO_REPORT_ONLY_8192E_2ANT 0 - -#define BT_INFO_8192E_2ANT_B_FTP BIT7 -#define BT_INFO_8192E_2ANT_B_A2DP BIT6 -#define BT_INFO_8192E_2ANT_B_HID BIT5 -#define BT_INFO_8192E_2ANT_B_SCO_BUSY BIT4 -#define BT_INFO_8192E_2ANT_B_ACL_BUSY BIT3 -#define BT_INFO_8192E_2ANT_B_INQ_PAGE BIT2 -#define BT_INFO_8192E_2ANT_B_SCO_ESCO BIT1 -#define BT_INFO_8192E_2ANT_B_CONNECTION BIT0 - -#define BTC_RSSI_COEX_THRESH_TOL_8192E_2ANT 2 - -enum bt_info_src_8192e_2ant { - BT_INFO_SRC_8192E_2ANT_WIFI_FW = 0x0, - BT_INFO_SRC_8192E_2ANT_BT_RSP = 0x1, - BT_INFO_SRC_8192E_2ANT_BT_ACTIVE_SEND = 0x2, - BT_INFO_SRC_8192E_2ANT_MAX -}; - -enum bt_8192e_2ant_bt_status { - BT_8192E_2ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0, - BT_8192E_2ANT_BT_STATUS_CONNECTED_IDLE = 0x1, - BT_8192E_2ANT_BT_STATUS_INQ_PAGE = 0x2, - BT_8192E_2ANT_BT_STATUS_ACL_BUSY = 0x3, - BT_8192E_2ANT_BT_STATUS_SCO_BUSY = 0x4, - BT_8192E_2ANT_BT_STATUS_ACL_SCO_BUSY = 0x5, - BT_8192E_2ANT_BT_STATUS_MAX -}; - -enum bt_8192e_2ant_coex_algo { - BT_8192E_2ANT_COEX_ALGO_UNDEFINED = 0x0, - BT_8192E_2ANT_COEX_ALGO_SCO = 0x1, - BT_8192E_2ANT_COEX_ALGO_SCO_PAN = 0x2, - BT_8192E_2ANT_COEX_ALGO_HID = 0x3, - BT_8192E_2ANT_COEX_ALGO_A2DP = 0x4, - BT_8192E_2ANT_COEX_ALGO_A2DP_PANHS = 0x5, - BT_8192E_2ANT_COEX_ALGO_PANEDR = 0x6, - BT_8192E_2ANT_COEX_ALGO_PANHS = 0x7, - BT_8192E_2ANT_COEX_ALGO_PANEDR_A2DP = 0x8, - BT_8192E_2ANT_COEX_ALGO_PANEDR_HID = 0x9, - BT_8192E_2ANT_COEX_ALGO_HID_A2DP_PANEDR = 0xa, - BT_8192E_2ANT_COEX_ALGO_HID_A2DP = 0xb, - BT_8192E_2ANT_COEX_ALGO_MAX = 0xc -}; - -struct coex_dm_8192e_2ant { - /* fw mechanism */ - u8 pre_dec_bt_pwr; - u8 cur_dec_bt_pwr; - u8 pre_fw_dac_swing_lvl; - u8 cur_fw_dac_swing_lvl; - bool cur_ignore_wlan_act; - bool pre_ignore_wlan_act; - u8 pre_ps_tdma; - u8 cur_ps_tdma; - u8 ps_tdma_para[5]; - u8 tdma_adj_type; - bool reset_tdma_adjust; - bool auto_tdma_adjust; - bool pre_ps_tdma_on; - bool cur_ps_tdma_on; - bool pre_bt_auto_report; - bool cur_bt_auto_report; - - /* sw mechanism */ - bool pre_rf_rx_lpf_shrink; - bool cur_rf_rx_lpf_shrink; - u32 bt_rf0x1e_backup; - bool pre_low_penalty_ra; - bool cur_low_penalty_ra; - bool pre_dac_swing_on; - u32 pre_dac_swing_lvl; - bool cur_dac_swing_on; - u32 cur_dac_swing_lvl; - bool pre_adc_back_off; - bool cur_adc_back_off; - bool pre_agc_table_en; - bool cur_agc_table_en; - u32 pre_val0x6c0; - u32 cur_val0x6c0; - u32 pre_val0x6c4; - u32 cur_val0x6c4; - u32 pre_val0x6c8; - u32 cur_val0x6c8; - u8 pre_val0x6cc; - u8 cur_val0x6cc; - bool limited_dig; - - u32 backup_arfr_cnt1; /* Auto Rate Fallback Retry cnt */ - u32 backup_arfr_cnt2; /* Auto Rate Fallback Retry cnt */ - u16 backup_retrylimit; - u8 backup_ampdu_maxtime; - - /* algorithm related */ - u8 pre_algorithm; - u8 cur_algorithm; - u8 bt_status; - u8 wifi_chnl_info[3]; - - u8 pre_sstype; - u8 cur_sstype; - - u32 prera_mask; - u32 curra_mask; - u8 curra_masktype; - u8 pre_arfrtype; - u8 cur_arfrtype; - u8 pre_retrylimit_type; - u8 cur_retrylimit_type; - u8 pre_ampdutime_type; - u8 cur_ampdutime_type; -}; - -struct coex_sta_8192e_2ant { - bool bt_link_exist; - bool sco_exist; - bool a2dp_exist; - bool hid_exist; - bool pan_exist; - - bool under_lps; - bool under_ips; - u32 high_priority_tx; - u32 high_priority_rx; - u32 low_priority_tx; - u32 low_priority_rx; - u8 bt_rssi; - u8 pre_bt_rssi_state; - u8 pre_wifi_rssi_state[4]; - bool c2h_bt_info_req_sent; - u8 bt_info_c2h[BT_INFO_SRC_8192E_2ANT_MAX][10]; - u32 bt_info_c2h_cnt[BT_INFO_SRC_8192E_2ANT_MAX]; - bool c2h_bt_inquiry_page; - u8 bt_retry_cnt; - u8 bt_info_ext; -}; - -/**************************************************************** - * The following is interface which will notify coex module. - ****************************************************************/ -void ex_halbtc8192e2ant_init_hwconfig(struct btc_coexist *btcoexist); -void ex_halbtc8192e2ant_init_coex_dm(struct btc_coexist *btcoexist); -void ex_halbtc8192e2ant_ips_notify(struct btc_coexist *btcoexist, u8 type); -void ex_halbtc8192e2ant_lps_notify(struct btc_coexist *btcoexist, u8 type); -void ex_halbtc8192e2ant_scan_notify(struct btc_coexist *btcoexist, u8 type); -void ex_halbtc8192e2ant_connect_notify(struct btc_coexist *btcoexist, u8 type); -void ex_halbtc8192e2ant_media_status_notify(struct btc_coexist *btcoexist, - u8 type); -void ex_halbtc8192e2ant_special_packet_notify(struct btc_coexist *btcoexist, - u8 type); -void ex_halbtc8192e2ant_bt_info_notify(struct btc_coexist *btcoexist, - u8 *tmpbuf, u8 length); -void ex_halbtc8192e2ant_stack_operation_notify(struct btc_coexist *btcoexist, - u8 type); -void ex_halbtc8192e2ant_halt_notify(struct btc_coexist *btcoexist); -void ex_halbtc8192e2ant_periodical(struct btc_coexist *btcoexist); -void ex_halbtc8192e2ant_display_coex_info(struct btc_coexist *btcoexist); diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.c deleted file mode 100644 index c4acd403e5f6..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.c +++ /dev/null @@ -1,3170 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -/*************************************************************** - * Description: - * - * This file is for RTL8723B Co-exist mechanism - * - * History - * 2012/11/15 Cosa first check in. - * - ***************************************************************/ - -/*************************************************************** - * include files - ***************************************************************/ -#include "halbt_precomp.h" -/*************************************************************** - * Global variables, these are static variables - ***************************************************************/ -static struct coex_dm_8723b_1ant glcoex_dm_8723b_1ant; -static struct coex_dm_8723b_1ant *coex_dm = &glcoex_dm_8723b_1ant; -static struct coex_sta_8723b_1ant glcoex_sta_8723b_1ant; -static struct coex_sta_8723b_1ant *coex_sta = &glcoex_sta_8723b_1ant; - -static const char *const GLBtInfoSrc8723b1Ant[] = { - "BT Info[wifi fw]", - "BT Info[bt rsp]", - "BT Info[bt auto report]", -}; - -static u32 glcoex_ver_date_8723b_1ant = 20130918; -static u32 glcoex_ver_8723b_1ant = 0x47; - -/*************************************************************** - * local function proto type if needed - ***************************************************************/ -/*************************************************************** - * local function start with halbtc8723b1ant_ - ***************************************************************/ -static u8 halbtc8723b1ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, - u8 rssi_thresh1) -{ - s32 bt_rssi = 0; - u8 bt_rssi_state = coex_sta->pre_bt_rssi_state; - - bt_rssi = coex_sta->bt_rssi; - - if (level_num == 2) { - if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || - (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { - if (bt_rssi >= rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { - bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to High\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Low\n"); - } - } else { - if (bt_rssi < rssi_thresh) { - bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Low\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at High\n"); - } - } - } else if (level_num == 3) { - if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi thresh error!!\n"); - return coex_sta->pre_bt_rssi_state; - } - - if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || - (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { - if (bt_rssi >= rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { - bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Medium\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Low\n"); - } - } else if ((coex_sta->pre_bt_rssi_state == - BTC_RSSI_STATE_MEDIUM) || - (coex_sta->pre_bt_rssi_state == - BTC_RSSI_STATE_STAY_MEDIUM)) { - if (bt_rssi >= rssi_thresh1 + - BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { - bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to High\n"); - } else if (bt_rssi < rssi_thresh) { - bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Low\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Medium\n"); - } - } else { - if (bt_rssi < rssi_thresh1) { - bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Medium\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at High\n"); - } - } - } - - coex_sta->pre_bt_rssi_state = bt_rssi_state; - - return bt_rssi_state; -} - -static u8 halbtc8723b1ant_wifi_rssi_state(struct btc_coexist *btcoexist, - u8 index, u8 level_num, - u8 rssi_thresh, u8 rssi_thresh1) -{ - s32 wifi_rssi = 0; - u8 wifi_rssi_state = coex_sta->pre_wifi_rssi_state[index]; - - btcoexist->btc_get(btcoexist, - BTC_GET_S4_WIFI_RSSI, &wifi_rssi); - - if (level_num == 2) { - if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_LOW) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_LOW)) { - if (wifi_rssi >= rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { - wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to High\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Low\n"); - } - } else { - if (wifi_rssi < rssi_thresh) { - wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Low\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at High\n"); - } - } - } else if (level_num == 3) { - if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI thresh error!!\n"); - return coex_sta->pre_wifi_rssi_state[index]; - } - - if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_LOW) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_LOW)) { - if (wifi_rssi >= rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { - wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Medium\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Low\n"); - } - } else if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_MEDIUM) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_MEDIUM)) { - if (wifi_rssi >= rssi_thresh1 + - BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT) { - wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to High\n"); - } else if (wifi_rssi < rssi_thresh) { - wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Low\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Medium\n"); - } - } else { - if (wifi_rssi < rssi_thresh1) { - wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Medium\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at High\n"); - } - } - } - - coex_sta->pre_wifi_rssi_state[index] = wifi_rssi_state; - - return wifi_rssi_state; -} - -static void halbtc8723b1ant_updatera_mask(struct btc_coexist *btcoexist, - bool force_exec, u32 dis_rate_mask) -{ - coex_dm->curra_mask = dis_rate_mask; - - if (force_exec || (coex_dm->prera_mask != coex_dm->curra_mask)) - btcoexist->btc_set(btcoexist, BTC_SET_ACT_UPDATE_ra_mask, - &coex_dm->curra_mask); - - coex_dm->prera_mask = coex_dm->curra_mask; -} - -static void btc8723b1ant_auto_rate_fb_retry(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - bool wifi_under_bmode = false; - - coex_dm->cur_arfr_type = type; - - if (force_exec || (coex_dm->pre_arfr_type != coex_dm->cur_arfr_type)) { - switch (coex_dm->cur_arfr_type) { - case 0: /* normal mode */ - btcoexist->btc_write_4byte(btcoexist, 0x430, - coex_dm->backup_arfr_cnt1); - btcoexist->btc_write_4byte(btcoexist, 0x434, - coex_dm->backup_arfr_cnt2); - break; - case 1: - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_UNDER_B_MODE, - &wifi_under_bmode); - if (wifi_under_bmode) { - btcoexist->btc_write_4byte(btcoexist, - 0x430, 0x0); - btcoexist->btc_write_4byte(btcoexist, - 0x434, 0x01010101); - } else { - btcoexist->btc_write_4byte(btcoexist, - 0x430, 0x0); - btcoexist->btc_write_4byte(btcoexist, - 0x434, 0x04030201); - } - break; - default: - break; - } - } - - coex_dm->pre_arfr_type = coex_dm->cur_arfr_type; -} - -static void halbtc8723b1ant_retry_limit(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - coex_dm->cur_retry_limit_type = type; - - if (force_exec || (coex_dm->pre_retry_limit_type != - coex_dm->cur_retry_limit_type)) { - switch (coex_dm->cur_retry_limit_type) { - case 0: /* normal mode */ - btcoexist->btc_write_2byte(btcoexist, 0x42a, - coex_dm->backup_retry_limit); - break; - case 1: /* retry limit = 8 */ - btcoexist->btc_write_2byte(btcoexist, 0x42a, 0x0808); - break; - default: - break; - } - } - - coex_dm->pre_retry_limit_type = coex_dm->cur_retry_limit_type; -} - -static void halbtc8723b1ant_ampdu_maxtime(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - coex_dm->cur_ampdu_time_type = type; - - if (force_exec || (coex_dm->pre_ampdu_time_type != - coex_dm->cur_ampdu_time_type)) { - switch (coex_dm->cur_ampdu_time_type) { - case 0: /* normal mode */ - btcoexist->btc_write_1byte(btcoexist, 0x456, - coex_dm->backup_ampdu_max_time); - break; - case 1: /* AMPDU timw = 0x38 * 32us */ - btcoexist->btc_write_1byte(btcoexist, - 0x456, 0x38); - break; - default: - break; - } - } - - coex_dm->pre_ampdu_time_type = coex_dm->cur_ampdu_time_type; -} - -static void halbtc8723b1ant_limited_tx(struct btc_coexist *btcoexist, - bool force_exec, u8 ra_masktype, - u8 arfr_type, u8 retry_limit_type, - u8 ampdu_time_type) -{ - switch (ra_masktype) { - case 0: /* normal mode */ - halbtc8723b1ant_updatera_mask(btcoexist, force_exec, 0x0); - break; - case 1: /* disable cck 1/2 */ - halbtc8723b1ant_updatera_mask(btcoexist, force_exec, - 0x00000003); - break; - /* disable cck 1/2/5.5, ofdm 6/9/12/18/24, mcs 0/1/2/3/4*/ - case 2: - halbtc8723b1ant_updatera_mask(btcoexist, force_exec, - 0x0001f1f7); - break; - default: - break; - } - - btc8723b1ant_auto_rate_fb_retry(btcoexist, force_exec, arfr_type); - halbtc8723b1ant_retry_limit(btcoexist, force_exec, retry_limit_type); - halbtc8723b1ant_ampdu_maxtime(btcoexist, force_exec, ampdu_time_type); -} - -static void halbtc8723b1ant_limited_rx(struct btc_coexist *btcoexist, - bool force_exec, bool rej_ap_agg_pkt, - bool bt_ctrl_agg_buf_size, - u8 agg_buf_size) -{ - bool reject_rx_agg = rej_ap_agg_pkt; - bool bt_ctrl_rx_agg_size = bt_ctrl_agg_buf_size; - u8 rxaggsize = agg_buf_size; - - /********************************************** - * Rx Aggregation related setting - **********************************************/ - btcoexist->btc_set(btcoexist, BTC_SET_BL_TO_REJ_AP_AGG_PKT, - &reject_rx_agg); - /* decide BT control aggregation buf size or not */ - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_CTRL_AGG_SIZE, - &bt_ctrl_rx_agg_size); - /* aggregation buf size, only work - * when BT control Rx aggregation size. - */ - btcoexist->btc_set(btcoexist, BTC_SET_U1_AGG_BUF_SIZE, &rxaggsize); - /* real update aggregation setting */ - btcoexist->btc_set(btcoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL); -} - -static void halbtc8723b1ant_monitor_bt_ctr(struct btc_coexist *btcoexist) -{ - u32 reg_hp_txrx, reg_lp_txrx, u32tmp; - u32 reg_hp_tx = 0, reg_hp_rx = 0; - u32 reg_lp_tx = 0, reg_lp_rx = 0; - - reg_hp_txrx = 0x770; - reg_lp_txrx = 0x774; - - u32tmp = btcoexist->btc_read_4byte(btcoexist, reg_hp_txrx); - reg_hp_tx = u32tmp & MASKLWORD; - reg_hp_rx = (u32tmp & MASKHWORD) >> 16; - - u32tmp = btcoexist->btc_read_4byte(btcoexist, reg_lp_txrx); - reg_lp_tx = u32tmp & MASKLWORD; - reg_lp_rx = (u32tmp & MASKHWORD) >> 16; - - coex_sta->high_priority_tx = reg_hp_tx; - coex_sta->high_priority_rx = reg_hp_rx; - coex_sta->low_priority_tx = reg_lp_tx; - coex_sta->low_priority_rx = reg_lp_rx; - - /* reset counter */ - btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); -} - -static void halbtc8723b1ant_query_bt_info(struct btc_coexist *btcoexist) -{ - u8 h2c_parameter[1] = {0}; - - coex_sta->c2h_bt_info_req_sent = true; - - h2c_parameter[0] |= BIT0; /* trigger*/ - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", - h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); -} - -static bool btc8723b1ant_is_wifi_status_changed(struct btc_coexist *btcoexist) -{ - static bool pre_wifi_busy; - static bool pre_under_4way, pre_bt_hs_on; - bool wifi_busy = false, under_4way = false, bt_hs_on = false; - bool wifi_connected = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, - &under_4way); - - if (wifi_connected) { - if (wifi_busy != pre_wifi_busy) { - pre_wifi_busy = wifi_busy; - return true; - } - if (under_4way != pre_under_4way) { - pre_under_4way = under_4way; - return true; - } - if (bt_hs_on != pre_bt_hs_on) { - pre_bt_hs_on = bt_hs_on; - return true; - } - } - - return false; -} - -static void halbtc8723b1ant_update_bt_link_info(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool bt_hs_on = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - - bt_link_info->bt_link_exist = coex_sta->bt_link_exist; - bt_link_info->sco_exist = coex_sta->sco_exist; - bt_link_info->a2dp_exist = coex_sta->a2dp_exist; - bt_link_info->pan_exist = coex_sta->pan_exist; - bt_link_info->hid_exist = coex_sta->hid_exist; - - /* work around for HS mode. */ - if (bt_hs_on) { - bt_link_info->pan_exist = true; - bt_link_info->bt_link_exist = true; - } - - /* check if Sco only */ - if (bt_link_info->sco_exist && !bt_link_info->a2dp_exist && - !bt_link_info->pan_exist && !bt_link_info->hid_exist) - bt_link_info->sco_only = true; - else - bt_link_info->sco_only = false; - - /* check if A2dp only */ - if (!bt_link_info->sco_exist && bt_link_info->a2dp_exist && - !bt_link_info->pan_exist && !bt_link_info->hid_exist) - bt_link_info->a2dp_only = true; - else - bt_link_info->a2dp_only = false; - - /* check if Pan only */ - if (!bt_link_info->sco_exist && !bt_link_info->a2dp_exist && - bt_link_info->pan_exist && !bt_link_info->hid_exist) - bt_link_info->pan_only = true; - else - bt_link_info->pan_only = false; - - /* check if Hid only */ - if (!bt_link_info->sco_exist && !bt_link_info->a2dp_exist && - !bt_link_info->pan_exist && bt_link_info->hid_exist) - bt_link_info->hid_only = true; - else - bt_link_info->hid_only = false; -} - -static u8 halbtc8723b1ant_action_algorithm(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool bt_hs_on = false; - u8 algorithm = BT_8723B_1ANT_COEX_ALGO_UNDEFINED; - u8 numdiffprofile = 0; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - - if (!bt_link_info->bt_link_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], No BT link exists!!!\n"); - return algorithm; - } - - if (bt_link_info->sco_exist) - numdiffprofile++; - if (bt_link_info->hid_exist) - numdiffprofile++; - if (bt_link_info->pan_exist) - numdiffprofile++; - if (bt_link_info->a2dp_exist) - numdiffprofile++; - - if (numdiffprofile == 1) { - if (bt_link_info->sco_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO only\n"); - algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; - } else { - if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID only\n"); - algorithm = BT_8723B_1ANT_COEX_ALGO_HID; - } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = A2DP only\n"); - algorithm = BT_8723B_1ANT_COEX_ALGO_A2DP; - } else if (bt_link_info->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = PAN(HS) only\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_PANHS; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = PAN(EDR) only\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_PANEDR; - } - } - } - } else if (numdiffprofile == 2) { - if (bt_link_info->sco_exist) { - if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID\n"); - algorithm = BT_8723B_1ANT_COEX_ALGO_HID; - } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + A2DP ==> SCO\n"); - algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; - } else if (bt_link_info->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + PAN(HS)\n"); - algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + PAN(EDR)\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; - } - } - } else { - if (bt_link_info->hid_exist && - bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + A2DP\n"); - algorithm = BT_8723B_1ANT_COEX_ALGO_HID_A2DP; - } else if (bt_link_info->hid_exist && - bt_link_info->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + PAN(HS)\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_HID_A2DP; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + PAN(EDR)\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; - } - } else if (bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = A2DP + PAN(HS)\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = A2DP + PAN(EDR)\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP; - } - } - } - } else if (numdiffprofile == 3) { - if (bt_link_info->sco_exist) { - if (bt_link_info->hid_exist && - bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + A2DP ==> HID\n"); - algorithm = BT_8723B_1ANT_COEX_ALGO_HID; - } else if (bt_link_info->hid_exist && - bt_link_info->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + PAN(HS)\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_HID_A2DP; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + PAN(EDR)\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; - } - } else if (bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + A2DP + PAN(HS)\n"); - algorithm = BT_8723B_1ANT_COEX_ALGO_SCO; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + A2DP + PAN(EDR) ==> HID\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; - } - } - } else { - if (bt_link_info->hid_exist && - bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + A2DP + PAN(HS)\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_HID_A2DP; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + A2DP + PAN(EDR)\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR; - } - } - } - } else if (numdiffprofile >= 3) { - if (bt_link_info->sco_exist) { - if (bt_link_info->hid_exist && - bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Error!!! BT Profile = SCO + HID + A2DP + PAN(HS)\n"); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); - algorithm = - BT_8723B_1ANT_COEX_ALGO_PANEDR_HID; - } - } - } - } - - return algorithm; -} - -static void btc8723b1ant_set_sw_pen_tx_rate_adapt(struct btc_coexist *btcoexist, - bool low_penalty_ra) -{ - u8 h2c_parameter[6] = {0}; - - h2c_parameter[0] = 0x6; /* opCode, 0x6= Retry_Penalty */ - - if (low_penalty_ra) { - h2c_parameter[1] |= BIT0; - /*normal rate except MCS7/6/5, OFDM54/48/36 */ - h2c_parameter[2] = 0x00; - h2c_parameter[3] = 0xf7; /*MCS7 or OFDM54 */ - h2c_parameter[4] = 0xf8; /*MCS6 or OFDM48 */ - h2c_parameter[5] = 0xf9; /*MCS5 or OFDM36 */ - } - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set WiFi Low-Penalty Retry: %s", - (low_penalty_ra ? "ON!!" : "OFF!!")); - - btcoexist->btc_fill_h2c(btcoexist, 0x69, 6, h2c_parameter); -} - -static void halbtc8723b1ant_low_penalty_ra(struct btc_coexist *btcoexist, - bool force_exec, bool low_penalty_ra) -{ - coex_dm->cur_low_penalty_ra = low_penalty_ra; - - if (!force_exec) { - if (coex_dm->pre_low_penalty_ra == coex_dm->cur_low_penalty_ra) - return; - } - btc8723b1ant_set_sw_pen_tx_rate_adapt(btcoexist, - coex_dm->cur_low_penalty_ra); - - coex_dm->pre_low_penalty_ra = coex_dm->cur_low_penalty_ra; -} - -static void halbtc8723b1ant_set_coex_table(struct btc_coexist *btcoexist, - u32 val0x6c0, u32 val0x6c4, - u32 val0x6c8, u8 val0x6cc) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); - btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); - btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); - btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); - btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); -} - -static void halbtc8723b1ant_coex_table(struct btc_coexist *btcoexist, - bool force_exec, u32 val0x6c0, - u32 val0x6c4, u32 val0x6c8, - u8 val0x6cc) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6cc = 0x%x\n", - (force_exec ? "force to" : ""), - val0x6c0, val0x6c4, val0x6cc); - coex_dm->cur_val0x6c0 = val0x6c0; - coex_dm->cur_val0x6c4 = val0x6c4; - coex_dm->cur_val0x6c8 = val0x6c8; - coex_dm->cur_val0x6cc = val0x6cc; - - if (!force_exec) { - if ((coex_dm->pre_val0x6c0 == coex_dm->cur_val0x6c0) && - (coex_dm->pre_val0x6c4 == coex_dm->cur_val0x6c4) && - (coex_dm->pre_val0x6c8 == coex_dm->cur_val0x6c8) && - (coex_dm->pre_val0x6cc == coex_dm->cur_val0x6cc)) - return; - } - halbtc8723b1ant_set_coex_table(btcoexist, val0x6c0, val0x6c4, - val0x6c8, val0x6cc); - - coex_dm->pre_val0x6c0 = coex_dm->cur_val0x6c0; - coex_dm->pre_val0x6c4 = coex_dm->cur_val0x6c4; - coex_dm->pre_val0x6c8 = coex_dm->cur_val0x6c8; - coex_dm->pre_val0x6cc = coex_dm->cur_val0x6cc; -} - -static void halbtc8723b1ant_coex_table_with_type(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - switch (type) { - case 0: - halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555, - 0x55555555, 0xffffff, 0x3); - break; - case 1: - halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555, - 0x5a5a5a5a, 0xffffff, 0x3); - break; - case 2: - halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a, - 0x5a5a5a5a, 0xffffff, 0x3); - break; - case 3: - halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555, - 0xaaaaaaaa, 0xffffff, 0x3); - break; - case 4: - halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555, - 0x5aaa5aaa, 0xffffff, 0x3); - break; - case 5: - halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a, - 0xaaaa5a5a, 0xffffff, 0x3); - break; - case 6: - halbtc8723b1ant_coex_table(btcoexist, force_exec, 0x55555555, - 0xaaaa5a5a, 0xffffff, 0x3); - break; - case 7: - halbtc8723b1ant_coex_table(btcoexist, force_exec, 0xaaaaaaaa, - 0xaaaaaaaa, 0xffffff, 0x3); - break; - default: - break; - } -} - -static void halbtc8723b1ant_SetFwIgnoreWlanAct(struct btc_coexist *btcoexist, - bool enable) -{ - u8 h2c_parameter[1] = {0}; - - if (enable) - h2c_parameter[0] |= BIT0; /* function enable */ - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", - h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); -} - -static void halbtc8723b1ant_ignore_wlan_act(struct btc_coexist *btcoexist, - bool force_exec, bool enable) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn Ignore WlanAct %s\n", - (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); - coex_dm->cur_ignore_wlan_act = enable; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], bPreIgnoreWlanAct = %d, bCurIgnoreWlanAct = %d!!\n", - coex_dm->pre_ignore_wlan_act, - coex_dm->cur_ignore_wlan_act); - - if (coex_dm->pre_ignore_wlan_act == - coex_dm->cur_ignore_wlan_act) - return; - } - halbtc8723b1ant_SetFwIgnoreWlanAct(btcoexist, enable); - - coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; -} - -static void halbtc8723b1ant_set_fw_ps_tdma(struct btc_coexist *btcoexist, - u8 byte1, u8 byte2, u8 byte3, - u8 byte4, u8 byte5) -{ - u8 h2c_parameter[5] = {0}; - u8 real_byte1 = byte1, real_byte5 = byte5; - bool ap_enable = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, - &ap_enable); - - if (ap_enable) { - if ((byte1 & BIT4) && !(byte1 & BIT5)) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], FW for 1Ant AP mode\n"); - real_byte1 &= ~BIT4; - real_byte1 |= BIT5; - - real_byte5 |= BIT5; - real_byte5 &= ~BIT6; - } - } - - h2c_parameter[0] = real_byte1; - h2c_parameter[1] = byte2; - h2c_parameter[2] = byte3; - h2c_parameter[3] = byte4; - h2c_parameter[4] = real_byte5; - - coex_dm->ps_tdma_para[0] = real_byte1; - coex_dm->ps_tdma_para[1] = byte2; - coex_dm->ps_tdma_para[2] = byte3; - coex_dm->ps_tdma_para[3] = byte4; - coex_dm->ps_tdma_para[4] = real_byte5; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], PS-TDMA H2C cmd =0x%x%08x\n", - h2c_parameter[0], - h2c_parameter[1] << 24 | - h2c_parameter[2] << 16 | - h2c_parameter[3] << 8 | - h2c_parameter[4]); - - btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); -} - -static void halbtc8723b1ant_set_lps_rpwm(struct btc_coexist *btcoexist, - u8 lps_val, u8 rpwm_val) -{ - u8 lps = lps_val; - u8 rpwm = rpwm_val; - - btcoexist->btc_set(btcoexist, BTC_SET_U1_LPS_VAL, &lps); - btcoexist->btc_set(btcoexist, BTC_SET_U1_RPWM_VAL, &rpwm); -} - -static void halbtc8723b1ant_LpsRpwm(struct btc_coexist *btcoexist, - bool force_exec, - u8 lps_val, u8 rpwm_val) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s set lps/rpwm = 0x%x/0x%x\n", - (force_exec ? "force to" : ""), lps_val, rpwm_val); - coex_dm->cur_lps = lps_val; - coex_dm->cur_rpwm = rpwm_val; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], LPS-RxBeaconMode = 0x%x , LPS-RPWM = 0x%x!!\n", - coex_dm->cur_lps, coex_dm->cur_rpwm); - - if ((coex_dm->pre_lps == coex_dm->cur_lps) && - (coex_dm->pre_rpwm == coex_dm->cur_rpwm)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], LPS-RPWM_Last = 0x%x , LPS-RPWM_Now = 0x%x!!\n", - coex_dm->pre_rpwm, coex_dm->cur_rpwm); - - return; - } - } - halbtc8723b1ant_set_lps_rpwm(btcoexist, lps_val, rpwm_val); - - coex_dm->pre_lps = coex_dm->cur_lps; - coex_dm->pre_rpwm = coex_dm->cur_rpwm; -} - -static void halbtc8723b1ant_sw_mechanism(struct btc_coexist *btcoexist, - bool low_penalty_ra) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], SM[LpRA] = %d\n", low_penalty_ra); - - halbtc8723b1ant_low_penalty_ra(btcoexist, NORMAL_EXEC, low_penalty_ra); -} - -static void halbtc8723b1ant_SetAntPath(struct btc_coexist *btcoexist, - u8 ant_pos_type, bool init_hw_cfg, - bool wifi_off) -{ - struct btc_board_info *board_info = &btcoexist->board_info; - u32 fw_ver = 0, u32tmp = 0; - bool pg_ext_switch = false; - bool use_ext_switch = false; - u8 h2c_parameter[2] = {0}; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_EXT_SWITCH, &pg_ext_switch); - /* [31:16] = fw ver, [15:0] = fw sub ver */ - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - - if ((fw_ver < 0xc0000) || pg_ext_switch) - use_ext_switch = true; - - if (init_hw_cfg) { - /*BT select s0/s1 is controlled by WiFi */ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67, 0x20, 0x1); - - /*Force GNT_BT to Normal */ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x0); - } else if (wifi_off) { - /*Force GNT_BT to High */ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x3); - /*BT select s0/s1 is controlled by BT */ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67, 0x20, 0x0); - - /* 0x4c[24:23] = 00, Set Antenna control by BT_RFE_CTRL - * BT Vendor 0xac = 0xf002 - */ - u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); - u32tmp &= ~BIT23; - u32tmp &= ~BIT24; - btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp); - } - - if (use_ext_switch) { - if (init_hw_cfg) { - /* 0x4c[23] = 0, 0x4c[24] = 1 - * Antenna control by WL/BT - */ - u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); - u32tmp &= ~BIT23; - u32tmp |= BIT24; - btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp); - - if (board_info->btdm_ant_pos == - BTC_ANTENNA_AT_MAIN_PORT) { - /* Main Ant to BT for IPS case 0x4c[23] = 1 */ - btcoexist->btc_write_1byte_bitmask(btcoexist, - 0x64, 0x1, - 0x1); - - /*tell firmware "no antenna inverse"*/ - h2c_parameter[0] = 0; - h2c_parameter[1] = 1; /*ext switch type*/ - btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, - h2c_parameter); - } else { - /*Aux Ant to BT for IPS case 0x4c[23] = 1 */ - btcoexist->btc_write_1byte_bitmask(btcoexist, - 0x64, 0x1, - 0x0); - - /*tell firmware "antenna inverse"*/ - h2c_parameter[0] = 1; - h2c_parameter[1] = 1; /*ext switch type*/ - btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, - h2c_parameter); - } - } - - /* fixed internal switch first*/ - /* fixed internal switch S1->WiFi, S0->BT*/ - if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) - btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0); - else/* fixed internal switch S0->WiFi, S1->BT*/ - btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280); - - /* ext switch setting */ - switch (ant_pos_type) { - case BTC_ANT_PATH_WIFI: - if (board_info->btdm_ant_pos == - BTC_ANTENNA_AT_MAIN_PORT) - btcoexist->btc_write_1byte_bitmask(btcoexist, - 0x92c, 0x3, - 0x1); - else - btcoexist->btc_write_1byte_bitmask(btcoexist, - 0x92c, 0x3, - 0x2); - break; - case BTC_ANT_PATH_BT: - if (board_info->btdm_ant_pos == - BTC_ANTENNA_AT_MAIN_PORT) - btcoexist->btc_write_1byte_bitmask(btcoexist, - 0x92c, 0x3, - 0x2); - else - btcoexist->btc_write_1byte_bitmask(btcoexist, - 0x92c, 0x3, - 0x1); - break; - default: - case BTC_ANT_PATH_PTA: - if (board_info->btdm_ant_pos == - BTC_ANTENNA_AT_MAIN_PORT) - btcoexist->btc_write_1byte_bitmask(btcoexist, - 0x92c, 0x3, - 0x1); - else - btcoexist->btc_write_1byte_bitmask(btcoexist, - 0x92c, 0x3, - 0x2); - break; - } - - } else { - if (init_hw_cfg) { - /* 0x4c[23] = 1, 0x4c[24] = 0 Antenna control by 0x64*/ - u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); - u32tmp |= BIT23; - u32tmp &= ~BIT24; - btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp); - - if (board_info->btdm_ant_pos == - BTC_ANTENNA_AT_MAIN_PORT) { - /*Main Ant to WiFi for IPS case 0x4c[23] = 1*/ - btcoexist->btc_write_1byte_bitmask(btcoexist, - 0x64, 0x1, - 0x0); - - /*tell firmware "no antenna inverse"*/ - h2c_parameter[0] = 0; - h2c_parameter[1] = 0; /*internal switch type*/ - btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, - h2c_parameter); - } else { - /*Aux Ant to BT for IPS case 0x4c[23] = 1*/ - btcoexist->btc_write_1byte_bitmask(btcoexist, - 0x64, 0x1, - 0x1); - - /*tell firmware "antenna inverse"*/ - h2c_parameter[0] = 1; - h2c_parameter[1] = 0; /*internal switch type*/ - btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, - h2c_parameter); - } - } - - /* fixed external switch first*/ - /*Main->WiFi, Aux->BT*/ - if (board_info->btdm_ant_pos == - BTC_ANTENNA_AT_MAIN_PORT) - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x92c, - 0x3, 0x1); - else/*Main->BT, Aux->WiFi */ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x92c, - 0x3, 0x2); - - /* internal switch setting*/ - switch (ant_pos_type) { - case BTC_ANT_PATH_WIFI: - if (board_info->btdm_ant_pos == - BTC_ANTENNA_AT_MAIN_PORT) - btcoexist->btc_write_2byte(btcoexist, 0x948, - 0x0); - else - btcoexist->btc_write_2byte(btcoexist, 0x948, - 0x280); - break; - case BTC_ANT_PATH_BT: - if (board_info->btdm_ant_pos == - BTC_ANTENNA_AT_MAIN_PORT) - btcoexist->btc_write_2byte(btcoexist, 0x948, - 0x280); - else - btcoexist->btc_write_2byte(btcoexist, 0x948, - 0x0); - break; - default: - case BTC_ANT_PATH_PTA: - if (board_info->btdm_ant_pos == - BTC_ANTENNA_AT_MAIN_PORT) - btcoexist->btc_write_2byte(btcoexist, 0x948, - 0x200); - else - btcoexist->btc_write_2byte(btcoexist, 0x948, - 0x80); - break; - } - } -} - -static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist, - bool force_exec, bool turn_on, u8 type) -{ - bool wifi_busy = false; - u8 rssi_adjust_val = 0; - - coex_dm->cur_ps_tdma_on = turn_on; - coex_dm->cur_ps_tdma = type; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - - if (!force_exec) { - if (coex_dm->cur_ps_tdma_on) - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], ******** TDMA(on, %d) *********\n", - coex_dm->cur_ps_tdma); - else - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], ******** TDMA(off, %d) ********\n", - coex_dm->cur_ps_tdma); - - if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && - (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) - return; - } - if (turn_on) { - switch (type) { - default: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x1a, - 0x1a, 0x0, 0x50); - break; - case 1: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x3a, - 0x03, 0x10, 0x50); - - rssi_adjust_val = 11; - break; - case 2: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x2b, - 0x03, 0x10, 0x50); - rssi_adjust_val = 14; - break; - case 3: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x1d, - 0x1d, 0x0, 0x52); - break; - case 4: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x15, - 0x3, 0x14, 0x0); - rssi_adjust_val = 17; - break; - case 5: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x15, - 0x3, 0x11, 0x10); - break; - case 6: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x20, - 0x3, 0x11, 0x13); - break; - case 7: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xc, - 0x5, 0x0, 0x0); - break; - case 8: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x25, - 0x3, 0x10, 0x0); - break; - case 9: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x21, - 0x3, 0x10, 0x50); - rssi_adjust_val = 18; - break; - case 10: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xa, - 0xa, 0x0, 0x40); - break; - case 11: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x15, - 0x03, 0x10, 0x50); - rssi_adjust_val = 20; - break; - case 12: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x0a, - 0x0a, 0x0, 0x50); - break; - case 13: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x15, - 0x15, 0x0, 0x50); - break; - case 14: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x21, - 0x3, 0x10, 0x52); - break; - case 15: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x13, 0xa, - 0x3, 0x8, 0x0); - break; - case 16: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x15, - 0x3, 0x10, 0x0); - rssi_adjust_val = 18; - break; - case 18: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x93, 0x25, - 0x3, 0x10, 0x0); - rssi_adjust_val = 14; - break; - case 20: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x35, - 0x03, 0x11, 0x10); - break; - case 21: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x25, - 0x03, 0x11, 0x11); - break; - case 22: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0x25, - 0x03, 0x11, 0x10); - break; - case 23: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x25, - 0x3, 0x31, 0x18); - rssi_adjust_val = 22; - break; - case 24: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x15, - 0x3, 0x31, 0x18); - rssi_adjust_val = 22; - break; - case 25: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0xa, - 0x3, 0x31, 0x18); - rssi_adjust_val = 22; - break; - case 26: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0xa, - 0x3, 0x31, 0x18); - rssi_adjust_val = 22; - break; - case 27: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x25, - 0x3, 0x31, 0x98); - rssi_adjust_val = 22; - break; - case 28: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x69, 0x25, - 0x3, 0x31, 0x0); - break; - case 29: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xab, 0x1a, - 0x1a, 0x1, 0x10); - break; - case 30: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x51, 0x14, - 0x3, 0x10, 0x50); - break; - case 31: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xd3, 0x1a, - 0x1a, 0, 0x58); - break; - case 32: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x61, 0xa, - 0x3, 0x10, 0x0); - break; - case 33: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xa3, 0x25, - 0x3, 0x30, 0x90); - break; - case 34: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x53, 0x1a, - 0x1a, 0x0, 0x10); - break; - case 35: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x63, 0x1a, - 0x1a, 0x0, 0x10); - break; - case 36: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0xd3, 0x12, - 0x3, 0x14, 0x50); - break; - /* SoftAP only with no sta associated,BT disable , - * TDMA mode for power saving - * here softap mode screen off will cost 70-80mA for phone - */ - case 40: - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x23, 0x18, - 0x00, 0x10, 0x24); - break; - } - } else { - switch (type) { - case 8: /*PTA Control */ - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x8, 0x0, - 0x0, 0x0, 0x0); - halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_PTA, - false, false); - break; - case 0: - default: /*Software control, Antenna at BT side */ - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0, - 0x0, 0x0, 0x0); - halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_BT, - false, false); - break; - case 9: /*Software control, Antenna at WiFi side */ - halbtc8723b1ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0, - 0x0, 0x0, 0x0); - halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_WIFI, - false, false); - break; - } - } - rssi_adjust_val = 0; - btcoexist->btc_set(btcoexist, - BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE, - &rssi_adjust_val); - - /* update pre state */ - coex_dm->pre_ps_tdma_on = coex_dm->cur_ps_tdma_on; - coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; -} - -static bool halbtc8723b1ant_is_common_action(struct btc_coexist *btcoexist) -{ - bool commom = false, wifi_connected = false; - bool wifi_busy = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - - if (!wifi_connected && - BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == coex_dm->bt_status) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non connected-idle + BT non connected-idle!!\n"); - halbtc8723b1ant_sw_mechanism(btcoexist, false); - commom = true; - } else if (wifi_connected && - (BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == - coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi connected + BT non connected-idle!!\n"); - halbtc8723b1ant_sw_mechanism(btcoexist, false); - commom = true; - } else if (!wifi_connected && - (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == - coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non connected-idle + BT connected-idle!!\n"); - halbtc8723b1ant_sw_mechanism(btcoexist, false); - commom = true; - } else if (wifi_connected && - (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == - coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi connected + BT connected-idle!!\n"); - halbtc8723b1ant_sw_mechanism(btcoexist, false); - commom = true; - } else if (!wifi_connected && - (BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE != - coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - ("[BTCoex], Wifi non connected-idle + BT Busy!!\n")); - halbtc8723b1ant_sw_mechanism(btcoexist, false); - commom = true; - } else { - if (wifi_busy) - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Connected-Busy + BT Busy!!\n"); - else - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Connected-Idle + BT Busy!!\n"); - - commom = false; - } - - return commom; -} - -static void btc8723b1ant_tdma_dur_adj_for_acl(struct btc_coexist *btcoexist, - u8 wifi_status) -{ - static s32 up, dn, m, n, wait_count; - /* 0: no change, +1: increase WiFi duration, - * -1: decrease WiFi duration - */ - s32 result; - u8 retry_count = 0, bt_info_ext; - bool wifi_busy = false; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], TdmaDurationAdjustForAcl()\n"); - - if (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY == wifi_status) - wifi_busy = true; - else - wifi_busy = false; - - if ((BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN == - wifi_status) || - (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN == wifi_status) || - (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT == wifi_status)) { - if (coex_dm->cur_ps_tdma != 1 && coex_dm->cur_ps_tdma != 2 && - coex_dm->cur_ps_tdma != 3 && coex_dm->cur_ps_tdma != 9) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - - up = 0; - dn = 0; - m = 1; - n = 3; - result = 0; - wait_count = 0; - } - return; - } - - if (!coex_dm->auto_tdma_adjust) { - coex_dm->auto_tdma_adjust = true; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], first run TdmaDurationAdjust()!!\n"); - - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); - coex_dm->tdma_adj_type = 2; - - up = 0; - dn = 0; - m = 1; - n = 3; - result = 0; - wait_count = 0; - } else { - /*accquire the BT TRx retry count from BT_Info byte2 */ - retry_count = coex_sta->bt_retry_cnt; - bt_info_ext = coex_sta->bt_info_ext; - result = 0; - wait_count++; - /* no retry in the last 2-second duration */ - if (retry_count == 0) { - up++; - dn--; - - if (dn <= 0) - dn = 0; - - if (up >= n) { - wait_count = 0; - n = 3; - up = 0; - dn = 0; - result = 1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Increase wifi duration!!\n"); - } - } else if (retry_count <= 3) { - up--; - dn++; - - if (up <= 0) - up = 0; - - if (dn == 2) { - if (wait_count <= 2) - m++; - else - m = 1; - - if (m >= 20) - m = 20; - - n = 3 * m; - up = 0; - dn = 0; - wait_count = 0; - result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration for retryCounter<3!!\n"); - } - } else { - if (wait_count == 1) - m++; - else - m = 1; - - if (m >= 20) - m = 20; - - n = 3 * m; - up = 0; - dn = 0; - wait_count = 0; - result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration for retryCounter>3!!\n"); - } - - if (result == -1) { - if ((BT_INFO_8723B_1ANT_A2DP_BASIC_RATE(bt_info_ext)) && - ((coex_dm->cur_ps_tdma == 1) || - (coex_dm->cur_ps_tdma == 2))) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (coex_dm->cur_ps_tdma == 1) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (coex_dm->cur_ps_tdma == 9) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } - } else if (result == 1) { - if ((BT_INFO_8723B_1ANT_A2DP_BASIC_RATE(bt_info_ext)) && - ((coex_dm->cur_ps_tdma == 1) || - (coex_dm->cur_ps_tdma == 2))) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (coex_dm->cur_ps_tdma == 9) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 1); - coex_dm->tdma_adj_type = 1; - } - } else { /*no change */ - /*if busy / idle change */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex],********* TDMA(on, %d) ********\n", - coex_dm->cur_ps_tdma); - } - - if (coex_dm->cur_ps_tdma != 1 && coex_dm->cur_ps_tdma != 2 && - coex_dm->cur_ps_tdma != 9 && coex_dm->cur_ps_tdma != 11) { - /* recover to previous adjust type */ - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, - coex_dm->tdma_adj_type); - } - } -} - -static void btc8723b1ant_pstdmachkpwrsave(struct btc_coexist *btcoexist, - bool new_ps_state) -{ - u8 lps_mode = 0x0; - - btcoexist->btc_get(btcoexist, BTC_GET_U1_LPS_MODE, &lps_mode); - - if (lps_mode) { /* already under LPS state */ - if (new_ps_state) { - /* keep state under LPS, do nothing. */ - } else { - /* will leave LPS state, turn off psTdma first */ - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 0); - } - } else { /* NO PS state */ - if (new_ps_state) { - /* will enter LPS state, turn off psTdma first */ - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 0); - } else { - /* keep state under NO PS state, do nothing. */ - } - } -} - -static void halbtc8723b1ant_power_save_state(struct btc_coexist *btcoexist, - u8 ps_type, u8 lps_val, - u8 rpwm_val) -{ - bool low_pwr_disable = false; - - switch (ps_type) { - case BTC_PS_WIFI_NATIVE: - /* recover to original 32k low power setting */ - low_pwr_disable = false; - btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - btcoexist->btc_set(btcoexist, BTC_SET_ACT_NORMAL_LPS, NULL); - break; - case BTC_PS_LPS_ON: - btc8723b1ant_pstdmachkpwrsave(btcoexist, true); - halbtc8723b1ant_LpsRpwm(btcoexist, NORMAL_EXEC, lps_val, - rpwm_val); - /* when coex force to enter LPS, do not enter 32k low power. */ - low_pwr_disable = true; - btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - /* power save must executed before psTdma. */ - btcoexist->btc_set(btcoexist, BTC_SET_ACT_ENTER_LPS, NULL); - break; - case BTC_PS_LPS_OFF: - btc8723b1ant_pstdmachkpwrsave(btcoexist, false); - btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS, NULL); - break; - default: - break; - } -} - -/*************************************************** - * - * Software Coex Mechanism start - * - ***************************************************/ -/* SCO only or SCO+PAN(HS) */ -static void halbtc8723b1ant_action_sco(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_sw_mechanism(btcoexist, true); -} - -static void halbtc8723b1ant_action_hid(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_sw_mechanism(btcoexist, true); -} - -/*A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */ -static void halbtc8723b1ant_action_a2dp(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_sw_mechanism(btcoexist, false); -} - -static void halbtc8723b1ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_sw_mechanism(btcoexist, false); -} - -static void halbtc8723b1ant_action_pan_edr(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_sw_mechanism(btcoexist, false); -} - -/* PAN(HS) only */ -static void halbtc8723b1ant_action_pan_hs(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_sw_mechanism(btcoexist, false); -} - -/*PAN(EDR)+A2DP */ -static void halbtc8723b1ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_sw_mechanism(btcoexist, false); -} - -static void halbtc8723b1ant_action_pan_edr_hid(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_sw_mechanism(btcoexist, true); -} - -/* HID+A2DP+PAN(EDR) */ -static void btc8723b1ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_sw_mechanism(btcoexist, true); -} - -static void halbtc8723b1ant_action_hid_a2dp(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_sw_mechanism(btcoexist, true); -} - -/***************************************************** - * - * Non-Software Coex Mechanism start - * - *****************************************************/ -static void halbtc8723b1ant_action_wifi_multiport(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); -} - -static void halbtc8723b1ant_action_hs(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); -} - -static void halbtc8723b1ant_action_bt_inquiry(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool wifi_connected = false, ap_enable = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, - &ap_enable); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - - if (!wifi_connected) { - halbtc8723b1ant_power_save_state(btcoexist, - BTC_PS_WIFI_NATIVE, 0x0, 0x0); - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); - } else if (bt_link_info->sco_exist || bt_link_info->hid_only) { - /* SCO/HID-only busy */ - halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - } else { - if (ap_enable) - halbtc8723b1ant_power_save_state(btcoexist, - BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - else - halbtc8723b1ant_power_save_state(btcoexist, - BTC_PS_LPS_ON, - 0x50, 0x4); - - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 30); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - } -} - -static void btc8723b1ant_act_bt_sco_hid_only_busy(struct btc_coexist *btcoexist, - u8 wifi_status) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool wifi_connected = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - - /* tdma and coex table */ - - if (bt_link_info->sco_exist) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); - } else { /* HID */ - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 6); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 5); - } -} - -static void halbtc8723b1ant_action_wifi_connected_bt_acl_busy( - struct btc_coexist *btcoexist, - u8 wifi_status) -{ - u8 bt_rssi_state; - - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - - bt_rssi_state = halbtc8723b1ant_bt_rssi_state(2, 28, 0); - - if (bt_link_info->hid_only) { /*HID */ - btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist, wifi_status); - coex_dm->auto_tdma_adjust = false; - return; - } else if (bt_link_info->a2dp_only) { /*A2DP */ - if (BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE == wifi_status) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 8); - halbtc8723b1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 2); - coex_dm->auto_tdma_adjust = false; - } else if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b1ant_tdma_dur_adj_for_acl(btcoexist, - wifi_status); - halbtc8723b1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 1); - } else { /*for low BT RSSI */ - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - halbtc8723b1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 1); - coex_dm->auto_tdma_adjust = false; - } - } else if (bt_link_info->hid_exist && - bt_link_info->a2dp_exist) { /*HID+A2DP */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->auto_tdma_adjust = false; - } else { /*for low BT RSSI*/ - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->auto_tdma_adjust = false; - } - - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 6); - /*PAN(OPP,FTP), HID+PAN(OPP,FTP) */ - } else if (bt_link_info->pan_only || - (bt_link_info->hid_exist && bt_link_info->pan_exist)) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 6); - coex_dm->auto_tdma_adjust = false; - /*A2DP+PAN(OPP,FTP), HID+A2DP+PAN(OPP,FTP)*/ - } else if ((bt_link_info->a2dp_exist && bt_link_info->pan_exist) || - (bt_link_info->hid_exist && bt_link_info->a2dp_exist && - bt_link_info->pan_exist)) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - coex_dm->auto_tdma_adjust = false; - } else { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - coex_dm->auto_tdma_adjust = false; - } -} - -static void btc8723b1ant_action_wifi_not_conn(struct btc_coexist *btcoexist) -{ - /* power save state */ - halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - - /* tdma and coex table */ - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0); -} - -static void btc8723b1ant_action_wifi_not_conn_scan(struct btc_coexist *btcoex) -{ - struct btc_bt_link_info *bt_link_info = &btcoex->bt_link_info; - - halbtc8723b1ant_power_save_state(btcoex, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - - /* tdma and coex table */ - if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { - if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) { - halbtc8723b1ant_ps_tdma(btcoex, NORMAL_EXEC, - true, 22); - halbtc8723b1ant_coex_table_with_type(btcoex, - NORMAL_EXEC, 1); - } else if (bt_link_info->pan_only) { - halbtc8723b1ant_ps_tdma(btcoex, NORMAL_EXEC, - true, 20); - halbtc8723b1ant_coex_table_with_type(btcoex, - NORMAL_EXEC, 2); - } else { - halbtc8723b1ant_ps_tdma(btcoex, NORMAL_EXEC, - true, 20); - halbtc8723b1ant_coex_table_with_type(btcoex, - NORMAL_EXEC, 1); - } - } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || - (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == - coex_dm->bt_status)){ - btc8723b1ant_act_bt_sco_hid_only_busy(btcoex, - BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN); - } else { - halbtc8723b1ant_ps_tdma(btcoex, NORMAL_EXEC, false, 8); - halbtc8723b1ant_coex_table_with_type(btcoex, NORMAL_EXEC, 2); - } -} - -static void btc8723b1ant_act_wifi_not_conn_asso_auth(struct btc_coexist *btcoex) -{ - struct btc_bt_link_info *bt_link_info = &btcoex->bt_link_info; - - halbtc8723b1ant_power_save_state(btcoex, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - - if ((BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == coex_dm->bt_status) || - (bt_link_info->sco_exist) || (bt_link_info->hid_only) || - (bt_link_info->a2dp_only) || (bt_link_info->pan_only)) { - halbtc8723b1ant_ps_tdma(btcoex, NORMAL_EXEC, false, 8); - halbtc8723b1ant_coex_table_with_type(btcoex, NORMAL_EXEC, 7); - } else { - halbtc8723b1ant_ps_tdma(btcoex, NORMAL_EXEC, true, 20); - halbtc8723b1ant_coex_table_with_type(btcoex, NORMAL_EXEC, 1); - } -} - -static void btc8723b1ant_action_wifi_conn_scan(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - - halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - - /* tdma and coex table */ - if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { - if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 22); - halbtc8723b1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 1); - } else if (bt_link_info->pan_only) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 20); - halbtc8723b1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 2); - } else { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 20); - halbtc8723b1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 1); - } - } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || - (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == - coex_dm->bt_status)) { - btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist, - BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN); - } else { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); - } -} - -static void halbtc8723b1ant_action_wifi_connected_special_packet( - struct btc_coexist *btcoexist) -{ - bool hs_connecting = false; - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_CONNECTING, &hs_connecting); - - halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - - /* tdma and coex table */ - if ((BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == coex_dm->bt_status) || - (bt_link_info->sco_exist) || (bt_link_info->hid_only) || - (bt_link_info->a2dp_only) || (bt_link_info->pan_only)) { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 7); - } else { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - } -} - -static void halbtc8723b1ant_action_wifi_connected(struct btc_coexist *btcoexist) -{ - bool wifi_busy = false; - bool scan = false, link = false, roam = false; - bool under_4way = false, ap_enable = false; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], CoexForWifiConnect()===>\n"); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, - &under_4way); - if (under_4way) { - halbtc8723b1ant_action_wifi_connected_special_packet(btcoexist); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], CoexForWifiConnect(), return for wifi is under 4way<===\n"); - return; - } - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); - - if (scan || link || roam) { - if (scan) - btc8723b1ant_action_wifi_conn_scan(btcoexist); - else - halbtc8723b1ant_action_wifi_connected_special_packet( - btcoexist); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n"); - return; - } - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, - &ap_enable); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - /* power save state */ - if (!ap_enable && - BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status && - !btcoexist->bt_link_info.hid_only) { - if (!wifi_busy && btcoexist->bt_link_info.a2dp_only) - halbtc8723b1ant_power_save_state(btcoexist, - BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - else - halbtc8723b1ant_power_save_state(btcoexist, - BTC_PS_LPS_ON, - 0x50, 0x4); - } else { - halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - } - /* tdma and coex table */ - if (!wifi_busy) { - if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { - halbtc8723b1ant_action_wifi_connected_bt_acl_busy(btcoexist, - BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE); - } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY == - coex_dm->bt_status) || - (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == - coex_dm->bt_status)) { - btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist, - BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE); - } else { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 8); - halbtc8723b1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 2); - } - } else { - if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { - halbtc8723b1ant_action_wifi_connected_bt_acl_busy(btcoexist, - BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY); - } else if ((BT_8723B_1ANT_BT_STATUS_SCO_BUSY == - coex_dm->bt_status) || - (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == - coex_dm->bt_status)) { - btc8723b1ant_act_bt_sco_hid_only_busy(btcoexist, - BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY); - } else { - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 8); - halbtc8723b1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 2); - } - } -} - -static void btc8723b1ant_run_sw_coex_mech(struct btc_coexist *btcoexist) -{ - u8 algorithm = 0; - - algorithm = halbtc8723b1ant_action_algorithm(btcoexist); - coex_dm->cur_algorithm = algorithm; - - if (!halbtc8723b1ant_is_common_action(btcoexist)) { - switch (coex_dm->cur_algorithm) { - case BT_8723B_1ANT_COEX_ALGO_SCO: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = SCO.\n"); - halbtc8723b1ant_action_sco(btcoexist); - break; - case BT_8723B_1ANT_COEX_ALGO_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HID.\n"); - halbtc8723b1ant_action_hid(btcoexist); - break; - case BT_8723B_1ANT_COEX_ALGO_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = A2DP.\n"); - halbtc8723b1ant_action_a2dp(btcoexist); - break; - case BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = A2DP+PAN(HS).\n"); - halbtc8723b1ant_action_a2dp_pan_hs(btcoexist); - break; - case BT_8723B_1ANT_COEX_ALGO_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = PAN(EDR).\n"); - halbtc8723b1ant_action_pan_edr(btcoexist); - break; - case BT_8723B_1ANT_COEX_ALGO_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HS mode.\n"); - halbtc8723b1ant_action_pan_hs(btcoexist); - break; - case BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = PAN+A2DP.\n"); - halbtc8723b1ant_action_pan_edr_a2dp(btcoexist); - break; - case BT_8723B_1ANT_COEX_ALGO_PANEDR_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = PAN(EDR)+HID.\n"); - halbtc8723b1ant_action_pan_edr_hid(btcoexist); - break; - case BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HID+A2DP+PAN.\n"); - btc8723b1ant_action_hid_a2dp_pan_edr(btcoexist); - break; - case BT_8723B_1ANT_COEX_ALGO_HID_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HID+A2DP.\n"); - halbtc8723b1ant_action_hid_a2dp(btcoexist); - break; - default: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = coexist All Off!!\n"); - break; - } - coex_dm->pre_algorithm = coex_dm->cur_algorithm; - } -} - -static void halbtc8723b1ant_run_coexist_mechanism(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool wifi_connected = false, bt_hs_on = false; - bool increase_scan_dev_num = false; - bool bt_ctrl_agg_buf_size = false; - u8 agg_buf_size = 5; - u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH; - u32 wifi_link_status = 0; - u32 num_of_wifi_link = 0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism()===>\n"); - - if (btcoexist->manual_control) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n"); - return; - } - - if (btcoexist->stop_coex_dm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), return for Stop Coex DM <===\n"); - return; - } - - if (coex_sta->under_ips) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], wifi is under IPS !!!\n"); - return; - } - - if ((BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || - (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || - (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) { - increase_scan_dev_num = true; - } - - btcoexist->btc_set(btcoexist, BTC_SET_BL_INC_SCAN_DEV_NUM, - &increase_scan_dev_num); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS, - &wifi_link_status); - num_of_wifi_link = wifi_link_status >> 16; - if (num_of_wifi_link >= 2) { - halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); - halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false, - bt_ctrl_agg_buf_size, - agg_buf_size); - halbtc8723b1ant_action_wifi_multiport(btcoexist); - return; - } - - if (!bt_link_info->sco_exist && !bt_link_info->hid_exist) { - halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); - } else { - if (wifi_connected) { - wifi_rssi_state = - halbtc8723b1ant_wifi_rssi_state(btcoexist, - 1, 2, 30, 0); - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8723b1ant_limited_tx(btcoexist, - NORMAL_EXEC, - 1, 1, 1, 1); - } else { - halbtc8723b1ant_limited_tx(btcoexist, - NORMAL_EXEC, - 1, 1, 1, 1); - } - } else { - halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, - 0, 0, 0, 0); - } - } - - if (bt_link_info->sco_exist) { - bt_ctrl_agg_buf_size = true; - agg_buf_size = 0x3; - } else if (bt_link_info->hid_exist) { - bt_ctrl_agg_buf_size = true; - agg_buf_size = 0x5; - } else if (bt_link_info->a2dp_exist || bt_link_info->pan_exist) { - bt_ctrl_agg_buf_size = true; - agg_buf_size = 0x8; - } - halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false, - bt_ctrl_agg_buf_size, agg_buf_size); - - btc8723b1ant_run_sw_coex_mech(btcoexist); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - - if (coex_sta->c2h_bt_inquiry_page) { - halbtc8723b1ant_action_bt_inquiry(btcoexist); - return; - } else if (bt_hs_on) { - halbtc8723b1ant_action_hs(btcoexist); - return; - } - - if (!wifi_connected) { - bool scan = false, link = false, roam = false; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], wifi is non connected-idle !!!\n"); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); - - if (scan || link || roam) { - if (scan) - btc8723b1ant_action_wifi_not_conn_scan( - btcoexist); - else - btc8723b1ant_act_wifi_not_conn_asso_auth( - btcoexist); - } else { - btc8723b1ant_action_wifi_not_conn(btcoexist); - } - } else { /* wifi LPS/Busy */ - halbtc8723b1ant_action_wifi_connected(btcoexist); - } -} - -static void halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist) -{ - /* sw all off */ - halbtc8723b1ant_sw_mechanism(btcoexist, false); - - halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8); - halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0); -} - -static void halbtc8723b1ant_init_hw_config(struct btc_coexist *btcoexist, - bool backup) -{ - u32 u32tmp = 0; - u8 u8tmp = 0; - u32 cnt_bt_cal_chk = 0; - - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], 1Ant Init HW Config!!\n"); - - if (backup) {/* backup rf 0x1e value */ - coex_dm->backup_arfr_cnt1 = - btcoexist->btc_read_4byte(btcoexist, 0x430); - coex_dm->backup_arfr_cnt2 = - btcoexist->btc_read_4byte(btcoexist, 0x434); - coex_dm->backup_retry_limit = - btcoexist->btc_read_2byte(btcoexist, 0x42a); - coex_dm->backup_ampdu_max_time = - btcoexist->btc_read_1byte(btcoexist, 0x456); - } - - /* WiFi goto standby while GNT_BT 0-->1 */ - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x780); - /* BT goto standby while GNT_BT 1-->0 */ - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x2, 0xfffff, 0x500); - - btcoexist->btc_write_1byte(btcoexist, 0x974, 0xff); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x944, 0x3, 0x3); - btcoexist->btc_write_1byte(btcoexist, 0x930, 0x77); - - /* BT calibration check */ - while (cnt_bt_cal_chk <= 20) { - u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x49d); - cnt_bt_cal_chk++; - if (u32tmp & BIT0) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ########### BT calibration(cnt=%d) ###########\n", - cnt_bt_cal_chk); - mdelay(50); - } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ********** BT NOT calibration (cnt=%d)**********\n", - cnt_bt_cal_chk); - break; - } - } - - /* 0x790[5:0] = 0x5 */ - u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x790); - u8tmp &= 0xc0; - u8tmp |= 0x5; - btcoexist->btc_write_1byte(btcoexist, 0x790, u8tmp); - - /* Enable counter statistics */ - /*0x76e[3] =1, WLAN_Act control by PTA */ - btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); - btcoexist->btc_write_1byte(btcoexist, 0x778, 0x1); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1); - - /*Antenna config */ - halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_PTA, true, false); - /* PTA parameter */ - halbtc8723b1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0); -} - -static void halbtc8723b1ant_wifi_off_hw_cfg(struct btc_coexist *btcoexist) -{ - /* set wlan_act to low */ - btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4); -} - -/************************************************************** - * work around function start with wa_halbtc8723b1ant_ - **************************************************************/ -/************************************************************** - * extern function start with EXhalbtc8723b1ant_ - **************************************************************/ - -void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist) -{ - halbtc8723b1ant_init_hw_config(btcoexist, true); -} - -void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist) -{ - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Coex Mechanism Init!!\n"); - - btcoexist->stop_coex_dm = false; - - halbtc8723b1ant_init_coex_dm(btcoexist); - - halbtc8723b1ant_query_bt_info(btcoexist); -} - -void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist) -{ - struct btc_board_info *board_info = &btcoexist->board_info; - struct btc_stack_info *stack_info = &btcoexist->stack_info; - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - struct rtl_priv *rtlpriv = btcoexist->adapter; - u8 u8tmp[4], i, bt_info_ext, pstdmacase = 0; - u16 u16tmp[4]; - u32 u32tmp[4]; - bool roam = false, scan = false; - bool link = false, wifi_under_5g = false; - bool bt_hs_on = false, wifi_busy = false; - s32 wifi_rssi = 0, bt_hs_rssi = 0; - u32 wifi_bw, wifi_traffic_dir, fa_ofdm, fa_cck, wifi_link_status; - u8 wifi_dot11_chnl, wifi_hs_chnl; - u32 fw_ver = 0, bt_patch_ver = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n ============[BT Coexist info]============"); - - if (btcoexist->manual_control) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n ============[Under Manual Control]=========="); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n =========================================="); - } - if (btcoexist->stop_coex_dm) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n ============[Coex is STOPPED]============"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n =========================================="); - } - - if (!board_info->bt_exist) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n BT not exists !!!"); - return; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d", - "Ant PG Num/ Ant Mech/ Ant Pos:", - board_info->pg_ant_num, board_info->btdm_ant_num, - board_info->btdm_ant_pos); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s / %d", - "BT stack/ hci ext ver", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d_%x/ 0x%x/ 0x%x(%d)", - "CoexVer/ FwVer/ PatchVer", - glcoex_ver_date_8723b_1ant, glcoex_ver_8723b_1ant, - fw_ver, bt_patch_ver, bt_patch_ver); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_DOT11_CHNL, - &wifi_dot11_chnl); - btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_HS_CHNL, &wifi_hs_chnl); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d / %d(%d)", - "Dot11 channel / HsChnl(HsMode)", - wifi_dot11_chnl, wifi_hs_chnl, bt_hs_on); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %02x %02x %02x ", - "H2C Wifi inform bt chnl Info", - coex_dm->wifi_chnl_info[0], coex_dm->wifi_chnl_info[1], - coex_dm->wifi_chnl_info[2]); - - btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); - btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", - "Wifi rssi/ HS rssi", wifi_rssi, bt_hs_rssi); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d ", - "Wifi link/ roam/ scan", link, roam, scan); - - btcoexist->btc_get(btcoexist , BTC_GET_BL_WIFI_UNDER_5G, - &wifi_under_5g); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, - &wifi_traffic_dir); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s / %s/ %s ", - "Wifi status", (wifi_under_5g ? "5G" : "2.4G"), - ((BTC_WIFI_BW_LEGACY == wifi_bw) ? "Legacy" : - (((BTC_WIFI_BW_HT40 == wifi_bw) ? "HT40" : "HT20"))), - ((!wifi_busy) ? "idle" : - ((BTC_WIFI_TRAFFIC_TX == wifi_traffic_dir) ? - "uplink" : "downlink"))); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS, - &wifi_link_status); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d/ %d/ %d", - "sta/vwifi/hs/p2pGo/p2pGc", - ((wifi_link_status & WIFI_STA_CONNECTED) ? 1 : 0), - ((wifi_link_status & WIFI_AP_CONNECTED) ? 1 : 0), - ((wifi_link_status & WIFI_HS_CONNECTED) ? 1 : 0), - ((wifi_link_status & WIFI_P2P_GO_CONNECTED) ? 1 : 0), - ((wifi_link_status & WIFI_P2P_GC_CONNECTED) ? 1 : 0)); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = [%s/ %d/ %d] ", - "BT [status/ rssi/ retryCnt]", - ((btcoexist->bt_info.bt_disabled) ? ("disabled") : - ((coex_sta->c2h_bt_inquiry_page) ? ("inquiry/page scan") : - ((BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE == - coex_dm->bt_status) ? - "non-connected idle" : - ((BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE == - coex_dm->bt_status) ? - "connected-idle" : "busy")))), - coex_sta->bt_rssi, coex_sta->bt_retry_cnt); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d / %d / %d / %d", - "SCO/HID/PAN/A2DP", bt_link_info->sco_exist, - bt_link_info->hid_exist, bt_link_info->pan_exist, - bt_link_info->a2dp_exist); - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_BT_LINK_INFO); - - bt_info_ext = coex_sta->bt_info_ext; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s", - "BT Info A2DP rate", - (bt_info_ext & BIT0) ? "Basic rate" : "EDR rate"); - - for (i = 0; i < BT_INFO_SRC_8723B_1ANT_MAX; i++) { - if (coex_sta->bt_info_c2h_cnt[i]) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)", - GLBtInfoSrc8723b1Ant[i], - coex_sta->bt_info_c2h[i][0], - coex_sta->bt_info_c2h[i][1], - coex_sta->bt_info_c2h[i][2], - coex_sta->bt_info_c2h[i][3], - coex_sta->bt_info_c2h[i][4], - coex_sta->bt_info_c2h[i][5], - coex_sta->bt_info_c2h[i][6], - coex_sta->bt_info_c2h_cnt[i]); - } - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %s/%s, (0x%x/0x%x)", - "PS state, IPS/LPS, (lps/rpwm)", - ((coex_sta->under_ips ? "IPS ON" : "IPS OFF")), - ((coex_sta->under_lps ? "LPS ON" : "LPS OFF")), - btcoexist->bt_info.lps_val, - btcoexist->bt_info.rpwm_val); - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD); - - if (!btcoexist->manual_control) { - /* Sw mechanism */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", - "============[Sw mechanism]============"); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/", - "SM[LowPenaltyRA]", coex_dm->cur_low_penalty_ra); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s/ %s/ %d ", - "DelBA/ BtCtrlAgg/ AggSize", - (btcoexist->bt_info.reject_agg_pkt ? "Yes" : "No"), - (btcoexist->bt_info.bt_ctrl_buf_size ? "Yes" : "No"), - btcoexist->bt_info.agg_buf_size); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x ", - "Rate Mask", btcoexist->bt_info.ra_mask); - - /* Fw mechanism */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", - "============[Fw mechanism]============"); - - pstdmacase = coex_dm->cur_ps_tdma; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", - "PS TDMA", coex_dm->ps_tdma_para[0], - coex_dm->ps_tdma_para[1], coex_dm->ps_tdma_para[2], - coex_dm->ps_tdma_para[3], coex_dm->ps_tdma_para[4], - pstdmacase, coex_dm->auto_tdma_adjust); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d ", - "IgnWlanAct", coex_dm->cur_ignore_wlan_act); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x ", - "Latest error condition(should be 0)", - coex_dm->error_condition); - } - - /* Hw setting */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", - "============[Hw setting]============"); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", - "backup ARFR1/ARFR2/RL/AMaxTime", coex_dm->backup_arfr_cnt1, - coex_dm->backup_arfr_cnt2, coex_dm->backup_retry_limit, - coex_dm->backup_ampdu_max_time); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x430); - u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x434); - u16tmp[0] = btcoexist->btc_read_2byte(btcoexist, 0x42a); - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x456); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", - "0x430/0x434/0x42a/0x456", - u32tmp[0], u32tmp[1], u16tmp[0], u8tmp[0]); - - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x778); - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6cc); - u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x880); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "0x778/0x6cc/0x880[29:25]", u8tmp[0], u32tmp[0], - (u32tmp[1] & 0x3e000000) >> 25); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x948); - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x67); - u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x765); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "0x948/ 0x67[5] / 0x765", - u32tmp[0], ((u8tmp[0] & 0x20) >> 5), u8tmp[1]); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x92c); - u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x930); - u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x944); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "0x92c[1:0]/ 0x930[7:0]/0x944[1:0]", - u32tmp[0] & 0x3, u32tmp[1] & 0xff, u32tmp[2] & 0x3); - - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x39); - u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x40); - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x4c); - u8tmp[2] = btcoexist->btc_read_1byte(btcoexist, 0x64); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", - "0x38[11]/0x40/0x4c[24:23]/0x64[0]", - ((u8tmp[0] & 0x8)>>3), u8tmp[1], - ((u32tmp[0] & 0x01800000) >> 23), u8tmp[2] & 0x1); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x550); - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x522); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "0x550(bcn ctrl)/0x522", u32tmp[0], u8tmp[0]); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc50); - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x49c); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "0xc50(dig)/0x49c(null-drop)", u32tmp[0] & 0xff, u8tmp[0]); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xda0); - u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0xda4); - u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0xda8); - u32tmp[3] = btcoexist->btc_read_4byte(btcoexist, 0xcf0); - - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xa5b); - u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xa5c); - - fa_ofdm = ((u32tmp[0] & 0xffff0000) >> 16) + - ((u32tmp[1] & 0xffff0000) >> 16) + - (u32tmp[1] & 0xffff) + - (u32tmp[2] & 0xffff) + - ((u32tmp[3] & 0xffff0000) >> 16) + - (u32tmp[3] & 0xffff); - fa_cck = (u8tmp[0] << 8) + u8tmp[1]; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "OFDM-CCA/OFDM-FA/CCK-FA", - u32tmp[0] & 0xffff, fa_ofdm, fa_cck); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6c0); - u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x6c4); - u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x6c8); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "0x6c0/0x6c4/0x6c8(coexTable)", - u32tmp[0], u32tmp[1], u32tmp[2]); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", - "0x770(high-pri rx/tx)", coex_sta->high_priority_rx, - coex_sta->high_priority_tx); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", - "0x774(low-pri rx/tx)", coex_sta->low_priority_rx, - coex_sta->low_priority_tx); -#if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 1) - halbtc8723b1ant_monitor_bt_ctr(btcoexist); -#endif - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS); -} - -void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (btcoexist->manual_control || btcoexist->stop_coex_dm) - return; - - if (BTC_IPS_ENTER == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS ENTER notify\n"); - coex_sta->under_ips = true; - - halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_BT, - false, true); - /* set PTA control */ - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0); - halbtc8723b1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 0); - halbtc8723b1ant_wifi_off_hw_cfg(btcoexist); - } else if (BTC_IPS_LEAVE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS LEAVE notify\n"); - coex_sta->under_ips = false; - - halbtc8723b1ant_init_hw_config(btcoexist, false); - halbtc8723b1ant_init_coex_dm(btcoexist); - halbtc8723b1ant_query_bt_info(btcoexist); - } -} - -void ex_halbtc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (btcoexist->manual_control || btcoexist->stop_coex_dm) - return; - - if (BTC_LPS_ENABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS ENABLE notify\n"); - coex_sta->under_lps = true; - } else if (BTC_LPS_DISABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS DISABLE notify\n"); - coex_sta->under_lps = false; - } -} - -void ex_halbtc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type) -{ - bool wifi_connected = false, bt_hs_on = false; - u32 wifi_link_status = 0; - u32 num_of_wifi_link = 0; - bool bt_ctrl_agg_buf_size = false; - u8 agg_buf_size = 5; - - if (btcoexist->manual_control || btcoexist->stop_coex_dm || - btcoexist->bt_info.bt_disabled) - return; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - - halbtc8723b1ant_query_bt_info(btcoexist); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS, - &wifi_link_status); - num_of_wifi_link = wifi_link_status >> 16; - if (num_of_wifi_link >= 2) { - halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); - halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false, - bt_ctrl_agg_buf_size, agg_buf_size); - halbtc8723b1ant_action_wifi_multiport(btcoexist); - return; - } - - if (coex_sta->c2h_bt_inquiry_page) { - halbtc8723b1ant_action_bt_inquiry(btcoexist); - return; - } else if (bt_hs_on) { - halbtc8723b1ant_action_hs(btcoexist); - return; - } - - if (BTC_SCAN_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN START notify\n"); - if (!wifi_connected) /* non-connected scan */ - btc8723b1ant_action_wifi_not_conn_scan(btcoexist); - else /* wifi is connected */ - btc8723b1ant_action_wifi_conn_scan(btcoexist); - } else if (BTC_SCAN_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN FINISH notify\n"); - if (!wifi_connected) /* non-connected scan */ - btc8723b1ant_action_wifi_not_conn(btcoexist); - else - halbtc8723b1ant_action_wifi_connected(btcoexist); - } -} - -void ex_halbtc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type) -{ - bool wifi_connected = false, bt_hs_on = false; - u32 wifi_link_status = 0; - u32 num_of_wifi_link = 0; - bool bt_ctrl_agg_buf_size = false; - u8 agg_buf_size = 5; - - if (btcoexist->manual_control || btcoexist->stop_coex_dm || - btcoexist->bt_info.bt_disabled) - return; - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS, - &wifi_link_status); - num_of_wifi_link = wifi_link_status>>16; - if (num_of_wifi_link >= 2) { - halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); - halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false, - bt_ctrl_agg_buf_size, agg_buf_size); - halbtc8723b1ant_action_wifi_multiport(btcoexist); - return; - } - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - if (coex_sta->c2h_bt_inquiry_page) { - halbtc8723b1ant_action_bt_inquiry(btcoexist); - return; - } else if (bt_hs_on) { - halbtc8723b1ant_action_hs(btcoexist); - return; - } - - if (BTC_ASSOCIATE_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT START notify\n"); - btc8723b1ant_act_wifi_not_conn_asso_auth(btcoexist); - } else if (BTC_ASSOCIATE_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT FINISH notify\n"); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - if (!wifi_connected) /* non-connected scan */ - btc8723b1ant_action_wifi_not_conn(btcoexist); - else - halbtc8723b1ant_action_wifi_connected(btcoexist); - } -} - -void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist, - u8 type) -{ - u8 h2c_parameter[3] = {0}; - u32 wifi_bw; - u8 wifiCentralChnl; - - if (btcoexist->manual_control || btcoexist->stop_coex_dm || - btcoexist->bt_info.bt_disabled) - return; - - if (BTC_MEDIA_CONNECT == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA connect notify\n"); - else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA disconnect notify\n"); - - /* only 2.4G we need to inform bt the chnl mask */ - btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, - &wifiCentralChnl); - - if ((BTC_MEDIA_CONNECT == type) && - (wifiCentralChnl <= 14)) { - h2c_parameter[0] = 0x0; - h2c_parameter[1] = wifiCentralChnl; - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) - h2c_parameter[2] = 0x30; - else - h2c_parameter[2] = 0x20; - } - - coex_dm->wifi_chnl_info[0] = h2c_parameter[0]; - coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; - coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x66 = 0x%x\n", - h2c_parameter[0] << 16 | h2c_parameter[1] << 8 | - h2c_parameter[2]); - - btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); -} - -void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist, - u8 type) -{ - bool bt_hs_on = false; - u32 wifi_link_status = 0; - u32 num_of_wifi_link = 0; - bool bt_ctrl_agg_buf_size = false; - u8 agg_buf_size = 5; - - if (btcoexist->manual_control || btcoexist->stop_coex_dm || - btcoexist->bt_info.bt_disabled) - return; - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_LINK_STATUS, - &wifi_link_status); - num_of_wifi_link = wifi_link_status >> 16; - if (num_of_wifi_link >= 2) { - halbtc8723b1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); - halbtc8723b1ant_limited_rx(btcoexist, NORMAL_EXEC, false, - bt_ctrl_agg_buf_size, agg_buf_size); - halbtc8723b1ant_action_wifi_multiport(btcoexist); - return; - } - - coex_sta->special_pkt_period_cnt = 0; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - if (coex_sta->c2h_bt_inquiry_page) { - halbtc8723b1ant_action_bt_inquiry(btcoexist); - return; - } else if (bt_hs_on) { - halbtc8723b1ant_action_hs(btcoexist); - return; - } - - if (BTC_PACKET_DHCP == type || - BTC_PACKET_EAPOL == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], special Packet(%d) notify\n", type); - halbtc8723b1ant_action_wifi_connected_special_packet(btcoexist); - } -} - -void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist, - u8 *tmp_buf, u8 length) -{ - u8 bt_info = 0; - u8 i, rsp_source = 0; - bool wifi_connected = false; - bool bt_busy = false; - - coex_sta->c2h_bt_info_req_sent = false; - - rsp_source = tmp_buf[0] & 0xf; - if (rsp_source >= BT_INFO_SRC_8723B_1ANT_MAX) - rsp_source = BT_INFO_SRC_8723B_1ANT_WIFI_FW; - coex_sta->bt_info_c2h_cnt[rsp_source]++; - - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Bt info[%d], length=%d, hex data = [", - rsp_source, length); - for (i = 0; i < length; i++) { - coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i]; - if (i == 1) - bt_info = tmp_buf[i]; - if (i == length - 1) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x]\n", tmp_buf[i]); - else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x, ", tmp_buf[i]); - } - - if (BT_INFO_SRC_8723B_1ANT_WIFI_FW != rsp_source) { - coex_sta->bt_retry_cnt = /* [3:0] */ - coex_sta->bt_info_c2h[rsp_source][2] & 0xf; - - coex_sta->bt_rssi = - coex_sta->bt_info_c2h[rsp_source][3] * 2 + 10; - - coex_sta->bt_info_ext = - coex_sta->bt_info_c2h[rsp_source][4]; - - /* Here we need to resend some wifi info to BT - * because bt is reset and loss of the info. - */ - if (coex_sta->bt_info_ext & BIT1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n"); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - if (wifi_connected) - ex_halbtc8723b1ant_media_status_notify(btcoexist, - BTC_MEDIA_CONNECT); - else - ex_halbtc8723b1ant_media_status_notify(btcoexist, - BTC_MEDIA_DISCONNECT); - } - - if (coex_sta->bt_info_ext & BIT3) { - if (!btcoexist->manual_control && - !btcoexist->stop_coex_dm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit3 check, set BT NOT ignore Wlan active!!\n"); - halbtc8723b1ant_ignore_wlan_act(btcoexist, - FORCE_EXEC, - false); - } - } else { - /* BT already NOT ignore Wlan active, do nothing here.*/ - } -#if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 0) - if (coex_sta->bt_info_ext & BIT4) { - /* BT auto report already enabled, do nothing */ - } else { - halbtc8723b1ant_bt_auto_report(btcoexist, FORCE_EXEC, - true); - } -#endif - } - - /* check BIT2 first ==> check if bt is under inquiry or page scan */ - if (bt_info & BT_INFO_8723B_1ANT_B_INQ_PAGE) - coex_sta->c2h_bt_inquiry_page = true; - else - coex_sta->c2h_bt_inquiry_page = false; - - /* set link exist status */ - if (!(bt_info & BT_INFO_8723B_1ANT_B_CONNECTION)) { - coex_sta->bt_link_exist = false; - coex_sta->pan_exist = false; - coex_sta->a2dp_exist = false; - coex_sta->hid_exist = false; - coex_sta->sco_exist = false; - } else { /* connection exists */ - coex_sta->bt_link_exist = true; - if (bt_info & BT_INFO_8723B_1ANT_B_FTP) - coex_sta->pan_exist = true; - else - coex_sta->pan_exist = false; - if (bt_info & BT_INFO_8723B_1ANT_B_A2DP) - coex_sta->a2dp_exist = true; - else - coex_sta->a2dp_exist = false; - if (bt_info & BT_INFO_8723B_1ANT_B_HID) - coex_sta->hid_exist = true; - else - coex_sta->hid_exist = false; - if (bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO) - coex_sta->sco_exist = true; - else - coex_sta->sco_exist = false; - } - - halbtc8723b1ant_update_bt_link_info(btcoexist); - - if (!(bt_info&BT_INFO_8723B_1ANT_B_CONNECTION)) { - coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Non-Connected idle!\n"); - /* connection exists but no busy */ - } else if (bt_info == BT_INFO_8723B_1ANT_B_CONNECTION) { - coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"); - } else if ((bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO) || - (bt_info & BT_INFO_8723B_1ANT_B_SCO_BUSY)) { - coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_SCO_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"); - } else if (bt_info & BT_INFO_8723B_1ANT_B_ACL_BUSY) { - if (BT_8723B_1ANT_BT_STATUS_ACL_BUSY != coex_dm->bt_status) - coex_dm->auto_tdma_adjust = false; - - coex_dm->bt_status = BT_8723B_1ANT_BT_STATUS_ACL_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"); - } else { - coex_dm->bt_status = - BT_8723B_1ANT_BT_STATUS_MAX; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Non-Defined state!!\n"); - } - - if ((BT_8723B_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || - (BT_8723B_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || - (BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) - bt_busy = true; - else - bt_busy = false; - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy); - - halbtc8723b1ant_run_coexist_mechanism(btcoexist); -} - -void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist) -{ - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "[BTCoex], Halt notify\n"); - - btcoexist->stop_coex_dm = true; - - halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_BT, false, true); - - halbtc8723b1ant_wifi_off_hw_cfg(btcoexist); - halbtc8723b1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); - - halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - halbtc8723b1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0); - - ex_halbtc8723b1ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT); -} - -void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state) -{ - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "[BTCoex], Pnp notify\n"); - - if (BTC_WIFI_PNP_SLEEP == pnp_state) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Pnp notify to SLEEP\n"); - btcoexist->stop_coex_dm = true; - halbtc8723b1ant_SetAntPath(btcoexist, BTC_ANT_PATH_BT, false, - true); - halbtc8723b1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - halbtc8723b1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0); - halbtc8723b1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 2); - halbtc8723b1ant_wifi_off_hw_cfg(btcoexist); - } else if (BTC_WIFI_PNP_WAKE_UP == pnp_state) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Pnp notify to WAKE UP\n"); - btcoexist->stop_coex_dm = false; - halbtc8723b1ant_init_hw_config(btcoexist, false); - halbtc8723b1ant_init_coex_dm(btcoexist); - halbtc8723b1ant_query_bt_info(btcoexist); - } -} - -void ex_halbtc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], *****************Coex DM Reset****************\n"); - - halbtc8723b1ant_init_hw_config(btcoexist, false); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x2, 0xfffff, 0x0); - halbtc8723b1ant_init_coex_dm(btcoexist); -} - -void ex_halbtc8723b1ant_periodical(struct btc_coexist *btcoexist) -{ - struct btc_board_info *board_info = &btcoexist->board_info; - struct btc_stack_info *stack_info = &btcoexist->stack_info; - static u8 dis_ver_info_cnt; - u32 fw_ver = 0, bt_patch_ver = 0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], ==========================Periodical===========================\n"); - - if (dis_ver_info_cnt <= 5) { - dis_ver_info_cnt += 1; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************************************************\n"); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", - board_info->pg_ant_num, board_info->btdm_ant_num, - board_info->btdm_ant_pos); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], BT stack/ hci ext ver = %s / %d\n", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); - btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, - &bt_patch_ver); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", - glcoex_ver_date_8723b_1ant, - glcoex_ver_8723b_1ant, fw_ver, - bt_patch_ver, bt_patch_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************************************************\n"); - } - -#if (BT_AUTO_REPORT_ONLY_8723B_1ANT == 0) - halbtc8723b1ant_query_bt_info(btcoexist); - halbtc8723b1ant_monitor_bt_ctr(btcoexist); - halbtc8723b1ant_monitor_bt_enable_disable(btcoexist); -#else - if (btc8723b1ant_is_wifi_status_changed(btcoexist) || - coex_dm->auto_tdma_adjust) { - halbtc8723b1ant_run_coexist_mechanism(btcoexist); - } - - coex_sta->special_pkt_period_cnt++; -#endif -} diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.h deleted file mode 100644 index 75f8094b7a34..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b1ant.h +++ /dev/null @@ -1,184 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -/********************************************************************** - * The following is for 8723B 1ANT BT Co-exist definition - **********************************************************************/ -#define BT_AUTO_REPORT_ONLY_8723B_1ANT 1 - -#define BT_INFO_8723B_1ANT_B_FTP BIT7 -#define BT_INFO_8723B_1ANT_B_A2DP BIT6 -#define BT_INFO_8723B_1ANT_B_HID BIT5 -#define BT_INFO_8723B_1ANT_B_SCO_BUSY BIT4 -#define BT_INFO_8723B_1ANT_B_ACL_BUSY BIT3 -#define BT_INFO_8723B_1ANT_B_INQ_PAGE BIT2 -#define BT_INFO_8723B_1ANT_B_SCO_ESCO BIT1 -#define BT_INFO_8723B_1ANT_B_CONNECTION BIT0 - -#define BT_INFO_8723B_1ANT_A2DP_BASIC_RATE(_BT_INFO_EXT_) \ - (((_BT_INFO_EXT_&BIT0)) ? true : false) - -#define BTC_RSSI_COEX_THRESH_TOL_8723B_1ANT 2 - -enum _BT_INFO_SRC_8723B_1ANT { - BT_INFO_SRC_8723B_1ANT_WIFI_FW = 0x0, - BT_INFO_SRC_8723B_1ANT_BT_RSP = 0x1, - BT_INFO_SRC_8723B_1ANT_BT_ACTIVE_SEND = 0x2, - BT_INFO_SRC_8723B_1ANT_MAX -}; - -enum _BT_8723B_1ANT_BT_STATUS { - BT_8723B_1ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0, - BT_8723B_1ANT_BT_STATUS_CONNECTED_IDLE = 0x1, - BT_8723B_1ANT_BT_STATUS_INQ_PAGE = 0x2, - BT_8723B_1ANT_BT_STATUS_ACL_BUSY = 0x3, - BT_8723B_1ANT_BT_STATUS_SCO_BUSY = 0x4, - BT_8723B_1ANT_BT_STATUS_ACL_SCO_BUSY = 0x5, - BT_8723B_1ANT_BT_STATUS_MAX -}; - -enum _BT_8723B_1ANT_WIFI_STATUS { - BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_IDLE = 0x0, - BT_8723B_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN = 0x1, - BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SCAN = 0x2, - BT_8723B_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT = 0x3, - BT_8723B_1ANT_WIFI_STATUS_CONNECTED_IDLE = 0x4, - BT_8723B_1ANT_WIFI_STATUS_CONNECTED_BUSY = 0x5, - BT_8723B_1ANT_WIFI_STATUS_MAX -}; - -enum _BT_8723B_1ANT_COEX_ALGO { - BT_8723B_1ANT_COEX_ALGO_UNDEFINED = 0x0, - BT_8723B_1ANT_COEX_ALGO_SCO = 0x1, - BT_8723B_1ANT_COEX_ALGO_HID = 0x2, - BT_8723B_1ANT_COEX_ALGO_A2DP = 0x3, - BT_8723B_1ANT_COEX_ALGO_A2DP_PANHS = 0x4, - BT_8723B_1ANT_COEX_ALGO_PANEDR = 0x5, - BT_8723B_1ANT_COEX_ALGO_PANHS = 0x6, - BT_8723B_1ANT_COEX_ALGO_PANEDR_A2DP = 0x7, - BT_8723B_1ANT_COEX_ALGO_PANEDR_HID = 0x8, - BT_8723B_1ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x9, - BT_8723B_1ANT_COEX_ALGO_HID_A2DP = 0xa, - BT_8723B_1ANT_COEX_ALGO_MAX = 0xb, -}; - -struct coex_dm_8723b_1ant { - /* fw mechanism */ - bool cur_ignore_wlan_act; - bool pre_ignore_wlan_act; - u8 pre_ps_tdma; - u8 cur_ps_tdma; - u8 ps_tdma_para[5]; - u8 tdma_adj_type; - bool auto_tdma_adjust; - bool pre_ps_tdma_on; - bool cur_ps_tdma_on; - bool pre_bt_auto_report; - bool cur_bt_auto_report; - u8 pre_lps; - u8 cur_lps; - u8 pre_rpwm; - u8 cur_rpwm; - - /* sw mechanism */ - bool pre_low_penalty_ra; - bool cur_low_penalty_ra; - u32 pre_val0x6c0; - u32 cur_val0x6c0; - u32 pre_val0x6c4; - u32 cur_val0x6c4; - u32 pre_val0x6c8; - u32 cur_val0x6c8; - u8 pre_val0x6cc; - u8 cur_val0x6cc; - bool limited_dig; - - u32 backup_arfr_cnt1; /* Auto Rate Fallback Retry cnt */ - u32 backup_arfr_cnt2; /* Auto Rate Fallback Retry cnt */ - u16 backup_retry_limit; - u8 backup_ampdu_max_time; - - /* algorithm related */ - u8 pre_algorithm; - u8 cur_algorithm; - u8 bt_status; - u8 wifi_chnl_info[3]; - - u32 prera_mask; - u32 curra_mask; - u8 pre_arfr_type; - u8 cur_arfr_type; - u8 pre_retry_limit_type; - u8 cur_retry_limit_type; - u8 pre_ampdu_time_type; - u8 cur_ampdu_time_type; - - u8 error_condition; -}; - -struct coex_sta_8723b_1ant { - bool bt_link_exist; - bool sco_exist; - bool a2dp_exist; - bool hid_exist; - bool pan_exist; - - bool under_lps; - bool under_ips; - u32 special_pkt_period_cnt; - u32 high_priority_tx; - u32 high_priority_rx; - u32 low_priority_tx; - u32 low_priority_rx; - u8 bt_rssi; - u8 pre_bt_rssi_state; - u8 pre_wifi_rssi_state[4]; - bool c2h_bt_info_req_sent; - u8 bt_info_c2h[BT_INFO_SRC_8723B_1ANT_MAX][10]; - u32 bt_info_c2h_cnt[BT_INFO_SRC_8723B_1ANT_MAX]; - bool c2h_bt_inquiry_page; - u8 bt_retry_cnt; - u8 bt_info_ext; -}; - -/************************************************************************* - * The following is interface which will notify coex module. - *************************************************************************/ -void ex_halbtc8723b1ant_init_hwconfig(struct btc_coexist *btcoexist); -void ex_halbtc8723b1ant_init_coex_dm(struct btc_coexist *btcoexist); -void ex_halbtc8723b1ant_ips_notify(struct btc_coexist *btcoexist, u8 type); -void ex_halbtc8723b1ant_lps_notify(struct btc_coexist *btcoexist, u8 type); -void ex_halbtc8723b1ant_scan_notify(struct btc_coexist *btcoexist, u8 type); -void ex_halbtc8723b1ant_connect_notify(struct btc_coexist *btcoexist, u8 type); -void ex_halbtc8723b1ant_media_status_notify(struct btc_coexist *btcoexist, - u8 type); -void ex_halbtc8723b1ant_special_packet_notify(struct btc_coexist *btcoexist, - u8 type); -void ex_halbtc8723b1ant_bt_info_notify(struct btc_coexist *btcoexist, - u8 *tmpbuf, u8 length); -void ex_halbtc8723b1ant_halt_notify(struct btc_coexist *btcoexist); -void ex_halbtc8723b1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate); -void ex_halbtc8723b1ant_coex_dm_reset(struct btc_coexist *btcoexist); -void ex_halbtc8723b1ant_periodical(struct btc_coexist *btcoexist); -void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist); diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.c deleted file mode 100644 index f2b9d11adc9e..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.c +++ /dev/null @@ -1,3717 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -/*************************************************************** - * Description: - * - * This file is for RTL8723B Co-exist mechanism - * - * History - * 2012/11/15 Cosa first check in. - * - **************************************************************/ -/************************************************************** - * include files - **************************************************************/ -#include "halbt_precomp.h" -/************************************************************** - * Global variables, these are static variables - **************************************************************/ -static struct coex_dm_8723b_2ant glcoex_dm_8723b_2ant; -static struct coex_dm_8723b_2ant *coex_dm = &glcoex_dm_8723b_2ant; -static struct coex_sta_8723b_2ant glcoex_sta_8723b_2ant; -static struct coex_sta_8723b_2ant *coex_sta = &glcoex_sta_8723b_2ant; - -static const char *const glbt_info_src_8723b_2ant[] = { - "BT Info[wifi fw]", - "BT Info[bt rsp]", - "BT Info[bt auto report]", -}; - -static u32 glcoex_ver_date_8723b_2ant = 20131113; -static u32 glcoex_ver_8723b_2ant = 0x3f; - -/************************************************************** - * local function proto type if needed - **************************************************************/ -/************************************************************** - * local function start with btc8723b2ant_ - **************************************************************/ -static u8 btc8723b2ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, - u8 rssi_thresh1) -{ - s32 bt_rssi = 0; - u8 bt_rssi_state = coex_sta->pre_bt_rssi_state; - - bt_rssi = coex_sta->bt_rssi; - - if (level_num == 2) { - if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || - (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { - if (bt_rssi >= rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { - bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "switch to High\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "stay at Low\n"); - } - } else { - if (bt_rssi < rssi_thresh) { - bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "switch to Low\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "stay at High\n"); - } - } - } else if (level_num == 3) { - if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi thresh error!!\n"); - return coex_sta->pre_bt_rssi_state; - } - - if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || - (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { - if (bt_rssi >= rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { - bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "switch to Medium\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "stay at Low\n"); - } - } else if ((coex_sta->pre_bt_rssi_state == - BTC_RSSI_STATE_MEDIUM) || - (coex_sta->pre_bt_rssi_state == - BTC_RSSI_STATE_STAY_MEDIUM)) { - if (bt_rssi >= rssi_thresh1 + - BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { - bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "switch to High\n"); - } else if (bt_rssi < rssi_thresh) { - bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "switch to Low\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "stay at Medium\n"); - } - } else { - if (bt_rssi < rssi_thresh1) { - bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "switch to Medium\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state " - "stay at High\n"); - } - } - } - - coex_sta->pre_bt_rssi_state = bt_rssi_state; - - return bt_rssi_state; -} - -static u8 btc8723b2ant_wifi_rssi_state(struct btc_coexist *btcoexist, - u8 index, u8 level_num, - u8 rssi_thresh, u8 rssi_thresh1) -{ - s32 wifi_rssi = 0; - u8 wifi_rssi_state = coex_sta->pre_wifi_rssi_state[index]; - - btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); - - if (level_num == 2) { - if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_LOW) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_LOW)) { - if (wifi_rssi >= rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { - wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "switch to High\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "stay at Low\n"); - } - } else { - if (wifi_rssi < rssi_thresh) { - wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "switch to Low\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "stay at High\n"); - } - } - } else if (level_num == 3) { - if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI thresh error!!\n"); - return coex_sta->pre_wifi_rssi_state[index]; - } - - if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_LOW) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_LOW)) { - if (wifi_rssi >= rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { - wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "switch to Medium\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "stay at Low\n"); - } - } else if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_MEDIUM) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_MEDIUM)) { - if (wifi_rssi >= rssi_thresh1 + - BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT) { - wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "switch to High\n"); - } else if (wifi_rssi < rssi_thresh) { - wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "switch to Low\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "stay at Medium\n"); - } - } else { - if (wifi_rssi < rssi_thresh1) { - wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "switch to Medium\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state " - "stay at High\n"); - } - } - } - - coex_sta->pre_wifi_rssi_state[index] = wifi_rssi_state; - - return wifi_rssi_state; -} - -static void btc8723b2ant_monitor_bt_ctr(struct btc_coexist *btcoexist) -{ - u32 reg_hp_txrx, reg_lp_txrx, u32tmp; - u32 reg_hp_tx = 0, reg_hp_rx = 0; - u32 reg_lp_tx = 0, reg_lp_rx = 0; - - reg_hp_txrx = 0x770; - reg_lp_txrx = 0x774; - - u32tmp = btcoexist->btc_read_4byte(btcoexist, reg_hp_txrx); - reg_hp_tx = u32tmp & MASKLWORD; - reg_hp_rx = (u32tmp & MASKHWORD) >> 16; - - u32tmp = btcoexist->btc_read_4byte(btcoexist, reg_lp_txrx); - reg_lp_tx = u32tmp & MASKLWORD; - reg_lp_rx = (u32tmp & MASKHWORD) >> 16; - - coex_sta->high_priority_tx = reg_hp_tx; - coex_sta->high_priority_rx = reg_hp_rx; - coex_sta->low_priority_tx = reg_lp_tx; - coex_sta->low_priority_rx = reg_lp_rx; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], High Priority Tx/Rx(reg 0x%x)=0x%x(%d)/0x%x(%d)\n", - reg_hp_txrx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], Low Priority Tx/Rx(reg 0x%x)=0x%x(%d)/0x%x(%d)\n", - reg_lp_txrx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); - - /* reset counter */ - btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); -} - -static void btc8723b2ant_query_bt_info(struct btc_coexist *btcoexist) -{ - u8 h2c_parameter[1] = {0}; - - coex_sta->c2h_bt_info_req_sent = true; - - h2c_parameter[0] |= BIT0; /* trigger */ - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", - h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); -} - -static bool btc8723b2ant_is_wifi_status_changed(struct btc_coexist *btcoexist) -{ - static bool pre_wifi_busy; - static bool pre_under_4way; - static bool pre_bt_hs_on; - bool wifi_busy = false, under_4way = false, bt_hs_on = false; - bool wifi_connected = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, - &under_4way); - - if (wifi_connected) { - if (wifi_busy != pre_wifi_busy) { - pre_wifi_busy = wifi_busy; - return true; - } - - if (under_4way != pre_under_4way) { - pre_under_4way = under_4way; - return true; - } - - if (bt_hs_on != pre_bt_hs_on) { - pre_bt_hs_on = bt_hs_on; - return true; - } - } - - return false; -} - -static void btc8723b2ant_update_bt_link_info(struct btc_coexist *btcoexist) -{ - /*struct btc_stack_info *stack_info = &btcoexist->stack_info;*/ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool bt_hs_on = false; - -#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 1) /* profile from bt patch */ - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - - bt_link_info->bt_link_exist = coex_sta->bt_link_exist; - bt_link_info->sco_exist = coex_sta->sco_exist; - bt_link_info->a2dp_exist = coex_sta->a2dp_exist; - bt_link_info->pan_exist = coex_sta->pan_exist; - bt_link_info->hid_exist = coex_sta->hid_exist; - - /* work around for HS mode. */ - if (bt_hs_on) { - bt_link_info->pan_exist = true; - bt_link_info->bt_link_exist = true; - } -#else /* profile from bt stack */ - bt_link_info->bt_link_exist = stack_info->bt_link_exist; - bt_link_info->sco_exist = stack_info->sco_exist; - bt_link_info->a2dp_exist = stack_info->a2dp_exist; - bt_link_info->pan_exist = stack_info->pan_exist; - bt_link_info->hid_exist = stack_info->hid_exist; - - /*for win-8 stack HID report error*/ - if (!stack_info->hid_exist) - stack_info->hid_exist = coex_sta->hid_exist; - /*sync BTInfo with BT firmware and stack*/ - /* when stack HID report error, here we use the info from bt fw.*/ - if (!stack_info->bt_link_exist) - stack_info->bt_link_exist = coex_sta->bt_link_exist; -#endif - /* check if Sco only */ - if (bt_link_info->sco_exist && !bt_link_info->a2dp_exist && - !bt_link_info->pan_exist && !bt_link_info->hid_exist) - bt_link_info->sco_only = true; - else - bt_link_info->sco_only = false; - - /* check if A2dp only */ - if (!bt_link_info->sco_exist && bt_link_info->a2dp_exist && - !bt_link_info->pan_exist && !bt_link_info->hid_exist) - bt_link_info->a2dp_only = true; - else - bt_link_info->a2dp_only = false; - - /* check if Pan only */ - if (!bt_link_info->sco_exist && !bt_link_info->a2dp_exist && - bt_link_info->pan_exist && !bt_link_info->hid_exist) - bt_link_info->pan_only = true; - else - bt_link_info->pan_only = false; - - /* check if Hid only */ - if (!bt_link_info->sco_exist && !bt_link_info->a2dp_exist && - !bt_link_info->pan_exist && bt_link_info->hid_exist) - bt_link_info->hid_only = true; - else - bt_link_info->hid_only = false; -} - -static u8 btc8723b2ant_action_algorithm(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool bt_hs_on = false; - u8 algorithm = BT_8723B_2ANT_COEX_ALGO_UNDEFINED; - u8 num_of_diff_profile = 0; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - - if (!bt_link_info->bt_link_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], No BT link exists!!!\n"); - return algorithm; - } - - if (bt_link_info->sco_exist) - num_of_diff_profile++; - if (bt_link_info->hid_exist) - num_of_diff_profile++; - if (bt_link_info->pan_exist) - num_of_diff_profile++; - if (bt_link_info->a2dp_exist) - num_of_diff_profile++; - - if (num_of_diff_profile == 1) { - if (bt_link_info->sco_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO only\n"); - algorithm = BT_8723B_2ANT_COEX_ALGO_SCO; - } else { - if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID only\n"); - algorithm = BT_8723B_2ANT_COEX_ALGO_HID; - } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], A2DP only\n"); - algorithm = BT_8723B_2ANT_COEX_ALGO_A2DP; - } else if (bt_link_info->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], PAN(HS) only\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_PANHS; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], PAN(EDR) only\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_PANEDR; - } - } - } - } else if (num_of_diff_profile == 2) { - if (bt_link_info->sco_exist) { - if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID\n"); - algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + A2DP ==> SCO\n"); - algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } else if (bt_link_info->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + PAN(HS)\n"); - algorithm = BT_8723B_2ANT_COEX_ALGO_SCO; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + PAN(EDR)\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } - } - } else { - if (bt_link_info->hid_exist && - bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + A2DP\n"); - algorithm = BT_8723B_2ANT_COEX_ALGO_HID_A2DP; - } else if (bt_link_info->hid_exist && - bt_link_info->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + PAN(HS)\n"); - algorithm = BT_8723B_2ANT_COEX_ALGO_HID; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + PAN(EDR)\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } - } else if (bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], A2DP + PAN(HS)\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex],A2DP + PAN(EDR)\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP; - } - } - } - } else if (num_of_diff_profile == 3) { - if (bt_link_info->sco_exist) { - if (bt_link_info->hid_exist && - bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + A2DP" - " ==> HID\n"); - algorithm = BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } else if (bt_link_info->hid_exist && - bt_link_info->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + " - "PAN(HS)\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + " - "PAN(EDR)\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } - } else if (bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + A2DP + " - "PAN(HS)\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + A2DP + " - "PAN(EDR) ==> HID\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } - } - } else { - if (bt_link_info->hid_exist && - bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + A2DP + " - "PAN(HS)\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_HID_A2DP; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + A2DP + " - "PAN(EDR)\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR; - } - } - } - } else if (num_of_diff_profile >= 3) { - if (bt_link_info->sco_exist) { - if (bt_link_info->hid_exist && - bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Error!!! SCO + HID" - " + A2DP + PAN(HS)\n"); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + A2DP +" - " PAN(EDR)==>PAN(EDR)+HID\n"); - algorithm = - BT_8723B_2ANT_COEX_ALGO_PANEDR_HID; - } - } - } - } - return algorithm; -} - -static bool btc8723b_need_dec_pwr(struct btc_coexist *btcoexist) -{ - bool ret = false; - bool bt_hs_on = false, wifi_connected = false; - s32 bt_hs_rssi = 0; - u8 bt_rssi_state; - - if (!btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on)) - return false; - if (!btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected)) - return false; - if (!btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi)) - return false; - - bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); - - if (wifi_connected) { - if (bt_hs_on) { - if (bt_hs_rssi > 37) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], Need to decrease bt " - "power for HS mode!!\n"); - ret = true; - } - } else { - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], Need to decrease bt " - "power for Wifi is connected!!\n"); - ret = true; - } - } - } - - return ret; -} - -static void btc8723b2ant_set_fw_dac_swing_level(struct btc_coexist *btcoexist, - u8 dac_swing_lvl) -{ - u8 h2c_parameter[1] = {0}; - - /* There are several type of dacswing - * 0x18/ 0x10/ 0xc/ 0x8/ 0x4/ 0x6 - */ - h2c_parameter[0] = dac_swing_lvl; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Set Dac Swing Level=0x%x\n", dac_swing_lvl); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x64=0x%x\n", h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x64, 1, h2c_parameter); -} - -static void btc8723b2ant_set_fw_dec_bt_pwr(struct btc_coexist *btcoexist, - bool dec_bt_pwr) -{ - u8 h2c_parameter[1] = {0}; - - h2c_parameter[0] = 0; - - if (dec_bt_pwr) - h2c_parameter[0] |= BIT1; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], decrease Bt Power : %s, FW write 0x62=0x%x\n", - (dec_bt_pwr ? "Yes!!" : "No!!"), h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x62, 1, h2c_parameter); -} - -static void btc8723b2ant_dec_bt_pwr(struct btc_coexist *btcoexist, - bool force_exec, bool dec_bt_pwr) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s Dec BT power = %s\n", - (force_exec ? "force to" : ""), (dec_bt_pwr ? "ON" : "OFF")); - coex_dm->cur_dec_bt_pwr = dec_bt_pwr; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], bPreDecBtPwr=%d, bCurDecBtPwr=%d\n", - coex_dm->pre_dec_bt_pwr, coex_dm->cur_dec_bt_pwr); - - if (coex_dm->pre_dec_bt_pwr == coex_dm->cur_dec_bt_pwr) - return; - } - btc8723b2ant_set_fw_dec_bt_pwr(btcoexist, coex_dm->cur_dec_bt_pwr); - - coex_dm->pre_dec_bt_pwr = coex_dm->cur_dec_bt_pwr; -} - -static void btc8723b2ant_fw_dac_swing_lvl(struct btc_coexist *btcoexist, - bool force_exec, u8 fw_dac_swing_lvl) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s set FW Dac Swing level = %d\n", - (force_exec ? "force to" : ""), fw_dac_swing_lvl); - coex_dm->cur_fw_dac_swing_lvl = fw_dac_swing_lvl; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], preFwDacSwingLvl=%d, " - "curFwDacSwingLvl=%d\n", - coex_dm->pre_fw_dac_swing_lvl, - coex_dm->cur_fw_dac_swing_lvl); - - if (coex_dm->pre_fw_dac_swing_lvl == - coex_dm->cur_fw_dac_swing_lvl) - return; - } - - btc8723b2ant_set_fw_dac_swing_level(btcoexist, - coex_dm->cur_fw_dac_swing_lvl); - coex_dm->pre_fw_dac_swing_lvl = coex_dm->cur_fw_dac_swing_lvl; -} - -static void btc8723b2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, - bool rx_rf_shrink_on) -{ - if (rx_rf_shrink_on) { - /* Shrink RF Rx LPF corner */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Shrink RF Rx LPF corner!!\n"); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, - 0xfffff, 0xffffc); - } else { - /* Resume RF Rx LPF corner */ - /* After initialized, we can use coex_dm->btRf0x1eBackup */ - if (btcoexist->initilized) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Resume RF Rx LPF corner!!\n"); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, - 0xfffff, - coex_dm->bt_rf0x1e_backup); - } - } -} - -static void btc8723b2ant_rf_shrink(struct btc_coexist *btcoexist, - bool force_exec, bool rx_rf_shrink_on) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn Rx RF Shrink = %s\n", - (force_exec ? "force to" : ""), (rx_rf_shrink_on ? - "ON" : "OFF")); - coex_dm->cur_rf_rx_lpf_shrink = rx_rf_shrink_on; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], bPreRfRxLpfShrink=%d, " - "bCurRfRxLpfShrink=%d\n", - coex_dm->pre_rf_rx_lpf_shrink, - coex_dm->cur_rf_rx_lpf_shrink); - - if (coex_dm->pre_rf_rx_lpf_shrink == - coex_dm->cur_rf_rx_lpf_shrink) - return; - } - btc8723b2ant_set_sw_rf_rx_lpf_corner(btcoexist, - coex_dm->cur_rf_rx_lpf_shrink); - - coex_dm->pre_rf_rx_lpf_shrink = coex_dm->cur_rf_rx_lpf_shrink; -} - -static void btc8723b_set_penalty_txrate(struct btc_coexist *btcoexist, - bool low_penalty_ra) -{ - u8 h2c_parameter[6] = {0}; - - h2c_parameter[0] = 0x6; /* opCode, 0x6= Retry_Penalty*/ - - if (low_penalty_ra) { - h2c_parameter[1] |= BIT0; - /*normal rate except MCS7/6/5, OFDM54/48/36*/ - h2c_parameter[2] = 0x00; - h2c_parameter[3] = 0xf7; /*MCS7 or OFDM54*/ - h2c_parameter[4] = 0xf8; /*MCS6 or OFDM48*/ - h2c_parameter[5] = 0xf9; /*MCS5 or OFDM36*/ - } - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set WiFi Low-Penalty Retry: %s", - (low_penalty_ra ? "ON!!" : "OFF!!")); - - btcoexist->btc_fill_h2c(btcoexist, 0x69, 6, h2c_parameter); -} - -static void btc8723b2ant_low_penalty_ra(struct btc_coexist *btcoexist, - bool force_exec, bool low_penalty_ra) -{ - /*return; */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn LowPenaltyRA = %s\n", - (force_exec ? "force to" : ""), (low_penalty_ra ? - "ON" : "OFF")); - coex_dm->cur_low_penalty_ra = low_penalty_ra; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], bPreLowPenaltyRa=%d, " - "bCurLowPenaltyRa=%d\n", - coex_dm->pre_low_penalty_ra, - coex_dm->cur_low_penalty_ra); - - if (coex_dm->pre_low_penalty_ra == coex_dm->cur_low_penalty_ra) - return; - } - btc8723b_set_penalty_txrate(btcoexist, coex_dm->cur_low_penalty_ra); - - coex_dm->pre_low_penalty_ra = coex_dm->cur_low_penalty_ra; -} - -static void btc8723b2ant_set_dac_swing_reg(struct btc_coexist *btcoexist, - u32 level) -{ - u8 val = (u8) level; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Write SwDacSwing = 0x%x\n", level); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x883, 0x3e, val); -} - -static void btc8723b2ant_set_sw_fulltime_dac_swing(struct btc_coexist *btcoex, - bool sw_dac_swing_on, - u32 sw_dac_swing_lvl) -{ - if (sw_dac_swing_on) - btc8723b2ant_set_dac_swing_reg(btcoex, sw_dac_swing_lvl); - else - btc8723b2ant_set_dac_swing_reg(btcoex, 0x18); -} - -static void btc8723b2ant_dac_swing(struct btc_coexist *btcoexist, - bool force_exec, bool dac_swing_on, - u32 dac_swing_lvl) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn DacSwing=%s, dac_swing_lvl=0x%x\n", - (force_exec ? "force to" : ""), - (dac_swing_on ? "ON" : "OFF"), dac_swing_lvl); - coex_dm->cur_dac_swing_on = dac_swing_on; - coex_dm->cur_dac_swing_lvl = dac_swing_lvl; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], bPreDacSwingOn=%d, preDacSwingLvl=0x%x," - " bCurDacSwingOn=%d, curDacSwingLvl=0x%x\n", - coex_dm->pre_dac_swing_on, coex_dm->pre_dac_swing_lvl, - coex_dm->cur_dac_swing_on, - coex_dm->cur_dac_swing_lvl); - - if ((coex_dm->pre_dac_swing_on == coex_dm->cur_dac_swing_on) && - (coex_dm->pre_dac_swing_lvl == coex_dm->cur_dac_swing_lvl)) - return; - } - mdelay(30); - btc8723b2ant_set_sw_fulltime_dac_swing(btcoexist, dac_swing_on, - dac_swing_lvl); - - coex_dm->pre_dac_swing_on = coex_dm->cur_dac_swing_on; - coex_dm->pre_dac_swing_lvl = coex_dm->cur_dac_swing_lvl; -} - -static void btc8723b2ant_set_agc_table(struct btc_coexist *btcoexist, - bool agc_table_en) -{ - u8 rssi_adjust_val = 0; - - /* BB AGC Gain Table */ - if (agc_table_en) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], BB Agc Table On!\n"); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6e1A0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6d1B0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6c1C0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6b1D0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x6a1E0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x691F0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0x68200001); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], BB Agc Table Off!\n"); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xaa1A0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa91B0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa81C0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa71D0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa61E0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa51F0001); - btcoexist->btc_write_4byte(btcoexist, 0xc78, 0xa4200001); - } - - /* RF Gain */ - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0xef, 0xfffff, 0x02000); - if (agc_table_en) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Agc Table On!\n"); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x3b, - 0xfffff, 0x38fff); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x3b, - 0xfffff, 0x38ffe); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Agc Table Off!\n"); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x3b, - 0xfffff, 0x380c3); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x3b, - 0xfffff, 0x28ce6); - } - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0xef, 0xfffff, 0x0); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0xed, 0xfffff, 0x1); - - if (agc_table_en) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Agc Table On!\n"); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x40, - 0xfffff, 0x38fff); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x40, - 0xfffff, 0x38ffe); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Agc Table Off!\n"); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x40, - 0xfffff, 0x380c3); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x40, - 0xfffff, 0x28ce6); - } - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0xed, 0xfffff, 0x0); - - /* set rssiAdjustVal for wifi module. */ - if (agc_table_en) - rssi_adjust_val = 8; - btcoexist->btc_set(btcoexist, BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON, - &rssi_adjust_val); -} - -static void btc8723b2ant_agc_table(struct btc_coexist *btcoexist, - bool force_exec, bool agc_table_en) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s %s Agc Table\n", - (force_exec ? "force to" : ""), - (agc_table_en ? "Enable" : "Disable")); - coex_dm->cur_agc_table_en = agc_table_en; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], bPreAgcTableEn=%d, bCurAgcTableEn=%d\n", - coex_dm->pre_agc_table_en, coex_dm->cur_agc_table_en); - - if (coex_dm->pre_agc_table_en == coex_dm->cur_agc_table_en) - return; - } - btc8723b2ant_set_agc_table(btcoexist, agc_table_en); - - coex_dm->pre_agc_table_en = coex_dm->cur_agc_table_en; -} - -static void btc8723b2ant_set_coex_table(struct btc_coexist *btcoexist, - u32 val0x6c0, u32 val0x6c4, - u32 val0x6c8, u8 val0x6cc) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c0=0x%x\n", val0x6c0); - btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c4=0x%x\n", val0x6c4); - btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c8=0x%x\n", val0x6c8); - btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6cc=0x%x\n", val0x6cc); - btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); -} - -static void btc8723b2ant_coex_table(struct btc_coexist *btcoexist, - bool force_exec, u32 val0x6c0, - u32 val0x6c4, u32 val0x6c8, - u8 val0x6cc) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s write Coex Table 0x6c0=0x%x," - " 0x6c4=0x%x, 0x6c8=0x%x, 0x6cc=0x%x\n", - (force_exec ? "force to" : ""), val0x6c0, - val0x6c4, val0x6c8, val0x6cc); - coex_dm->cur_val0x6c0 = val0x6c0; - coex_dm->cur_val0x6c4 = val0x6c4; - coex_dm->cur_val0x6c8 = val0x6c8; - coex_dm->cur_val0x6cc = val0x6cc; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], preVal0x6c0=0x%x, " - "preVal0x6c4=0x%x, preVal0x6c8=0x%x, " - "preVal0x6cc=0x%x !!\n", - coex_dm->pre_val0x6c0, coex_dm->pre_val0x6c4, - coex_dm->pre_val0x6c8, coex_dm->pre_val0x6cc); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], curVal0x6c0=0x%x, " - "curVal0x6c4=0x%x, curVal0x6c8=0x%x, " - "curVal0x6cc=0x%x !!\n", - coex_dm->cur_val0x6c0, coex_dm->cur_val0x6c4, - coex_dm->cur_val0x6c8, coex_dm->cur_val0x6cc); - - if ((coex_dm->pre_val0x6c0 == coex_dm->cur_val0x6c0) && - (coex_dm->pre_val0x6c4 == coex_dm->cur_val0x6c4) && - (coex_dm->pre_val0x6c8 == coex_dm->cur_val0x6c8) && - (coex_dm->pre_val0x6cc == coex_dm->cur_val0x6cc)) - return; - } - btc8723b2ant_set_coex_table(btcoexist, val0x6c0, val0x6c4, - val0x6c8, val0x6cc); - - coex_dm->pre_val0x6c0 = coex_dm->cur_val0x6c0; - coex_dm->pre_val0x6c4 = coex_dm->cur_val0x6c4; - coex_dm->pre_val0x6c8 = coex_dm->cur_val0x6c8; - coex_dm->pre_val0x6cc = coex_dm->cur_val0x6cc; -} - -static void btc8723b_coex_tbl_type(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - switch (type) { - case 0: - btc8723b2ant_coex_table(btcoexist, force_exec, 0x55555555, - 0x55555555, 0xffff, 0x3); - break; - case 1: - btc8723b2ant_coex_table(btcoexist, force_exec, 0x55555555, - 0x5afa5afa, 0xffff, 0x3); - break; - case 2: - btc8723b2ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a, - 0x5a5a5a5a, 0xffff, 0x3); - break; - case 3: - btc8723b2ant_coex_table(btcoexist, force_exec, 0xaaaaaaaa, - 0xaaaaaaaa, 0xffff, 0x3); - break; - case 4: - btc8723b2ant_coex_table(btcoexist, force_exec, 0xffffffff, - 0xffffffff, 0xffff, 0x3); - break; - case 5: - btc8723b2ant_coex_table(btcoexist, force_exec, 0x5fff5fff, - 0x5fff5fff, 0xffff, 0x3); - break; - case 6: - btc8723b2ant_coex_table(btcoexist, force_exec, 0x55ff55ff, - 0x5a5a5a5a, 0xffff, 0x3); - break; - case 7: - btc8723b2ant_coex_table(btcoexist, force_exec, 0x55ff55ff, - 0x5afa5afa, 0xffff, 0x3); - break; - case 8: - btc8723b2ant_coex_table(btcoexist, force_exec, 0x5aea5aea, - 0x5aea5aea, 0xffff, 0x3); - break; - case 9: - btc8723b2ant_coex_table(btcoexist, force_exec, 0x55ff55ff, - 0x5aea5aea, 0xffff, 0x3); - break; - case 10: - btc8723b2ant_coex_table(btcoexist, force_exec, 0x55ff55ff, - 0x5aff5aff, 0xffff, 0x3); - break; - case 11: - btc8723b2ant_coex_table(btcoexist, force_exec, 0x55ff55ff, - 0x5a5f5a5f, 0xffff, 0x3); - break; - case 12: - btc8723b2ant_coex_table(btcoexist, force_exec, 0x55ff55ff, - 0x5f5f5f5f, 0xffff, 0x3); - break; - default: - break; - } -} - -static void btc8723b2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, - bool enable) -{ - u8 h2c_parameter[1] = {0}; - - if (enable) - h2c_parameter[0] |= BIT0;/* function enable*/ - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set FW for BT Ignore Wlan_Act, " - "FW write 0x63=0x%x\n", h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); -} - -static void btc8723b2ant_ignore_wlan_act(struct btc_coexist *btcoexist, - bool force_exec, bool enable) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn Ignore WlanAct %s\n", - (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); - coex_dm->cur_ignore_wlan_act = enable; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], bPreIgnoreWlanAct = %d, " - "bCurIgnoreWlanAct = %d!!\n", - coex_dm->pre_ignore_wlan_act, - coex_dm->cur_ignore_wlan_act); - - if (coex_dm->pre_ignore_wlan_act == - coex_dm->cur_ignore_wlan_act) - return; - } - btc8723b2ant_set_fw_ignore_wlan_act(btcoexist, enable); - - coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; -} - -static void btc8723b2ant_set_fw_ps_tdma(struct btc_coexist *btcoexist, u8 byte1, - u8 byte2, u8 byte3, u8 byte4, u8 byte5) -{ - u8 h2c_parameter[5]; - - h2c_parameter[0] = byte1; - h2c_parameter[1] = byte2; - h2c_parameter[2] = byte3; - h2c_parameter[3] = byte4; - h2c_parameter[4] = byte5; - - coex_dm->ps_tdma_para[0] = byte1; - coex_dm->ps_tdma_para[1] = byte2; - coex_dm->ps_tdma_para[2] = byte3; - coex_dm->ps_tdma_para[3] = byte4; - coex_dm->ps_tdma_para[4] = byte5; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x60(5bytes)=0x%x%08x\n", - h2c_parameter[0], - h2c_parameter[1] << 24 | h2c_parameter[2] << 16 | - h2c_parameter[3] << 8 | h2c_parameter[4]); - - btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); -} - -static void btc8723b2ant_sw_mechanism1(struct btc_coexist *btcoexist, - bool shrink_rx_lpf, bool low_penalty_ra, - bool limited_dig, bool bt_lna_constrain) -{ - btc8723b2ant_rf_shrink(btcoexist, NORMAL_EXEC, shrink_rx_lpf); - btc8723b2ant_low_penalty_ra(btcoexist, NORMAL_EXEC, low_penalty_ra); -} - -static void btc8723b2ant_sw_mechanism2(struct btc_coexist *btcoexist, - bool agc_table_shift, bool adc_backoff, - bool sw_dac_swing, u32 dac_swing_lvl) -{ - btc8723b2ant_agc_table(btcoexist, NORMAL_EXEC, agc_table_shift); - btc8723b2ant_dac_swing(btcoexist, NORMAL_EXEC, sw_dac_swing, - dac_swing_lvl); -} - -static void btc8723b2ant_set_ant_path(struct btc_coexist *btcoexist, - u8 antpos_type, bool init_hwcfg, - bool wifi_off) -{ - struct btc_board_info *board_info = &btcoexist->board_info; - u32 fw_ver = 0, u32tmp = 0; - bool pg_ext_switch = false; - bool use_ext_switch = false; - u8 h2c_parameter[2] = {0}; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_EXT_SWITCH, &pg_ext_switch); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - - if ((fw_ver < 0xc0000) || pg_ext_switch) - use_ext_switch = true; - - if (init_hwcfg) { - /* 0x4c[23] = 0, 0x4c[24] = 1 Antenna control by WL/BT */ - u32tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); - u32tmp &= ~BIT23; - u32tmp |= BIT24; - btcoexist->btc_write_4byte(btcoexist, 0x4c, u32tmp); - - btcoexist->btc_write_1byte(btcoexist, 0x974, 0xff); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x944, 0x3, 0x3); - btcoexist->btc_write_1byte(btcoexist, 0x930, 0x77); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67, 0x20, 0x1); - - /* Force GNT_BT to low */ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x0); - btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0); - - if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) { - /* tell firmware "no antenna inverse" */ - h2c_parameter[0] = 0; - h2c_parameter[1] = 1; /* ext switch type */ - btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, - h2c_parameter); - } else { - /* tell firmware "antenna inverse" */ - h2c_parameter[0] = 1; - h2c_parameter[1] = 1; /* ext switch type */ - btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, - h2c_parameter); - } - } - - /* ext switch setting */ - if (use_ext_switch) { - /* fixed internal switch S1->WiFi, S0->BT */ - btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0); - switch (antpos_type) { - case BTC_ANT_WIFI_AT_MAIN: - /* ext switch main at wifi */ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x92c, - 0x3, 0x1); - break; - case BTC_ANT_WIFI_AT_AUX: - /* ext switch aux at wifi */ - btcoexist->btc_write_1byte_bitmask(btcoexist, - 0x92c, 0x3, 0x2); - break; - } - } else { /* internal switch */ - /* fixed ext switch */ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x92c, 0x3, 0x1); - switch (antpos_type) { - case BTC_ANT_WIFI_AT_MAIN: - /* fixed internal switch S1->WiFi, S0->BT */ - btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0); - break; - case BTC_ANT_WIFI_AT_AUX: - /* fixed internal switch S0->WiFi, S1->BT */ - btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280); - break; - } - } -} - -static void btc8723b2ant_ps_tdma(struct btc_coexist *btcoexist, bool force_exec, - bool turn_on, u8 type) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn %s PS TDMA, type=%d\n", - (force_exec ? "force to" : ""), - (turn_on ? "ON" : "OFF"), type); - coex_dm->cur_ps_tdma_on = turn_on; - coex_dm->cur_ps_tdma = type; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], bPrePsTdmaOn = %d, bCurPsTdmaOn = %d!!\n", - coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], prePsTdma = %d, curPsTdma = %d!!\n", - coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma); - - if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && - (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) - return; - } - if (turn_on) { - switch (type) { - case 1: - default: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0xe1, 0x90); - break; - case 2: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x12, - 0x12, 0xe1, 0x90); - break; - case 3: - /* This call breaks BT when wireless is active - - * comment it out for now until a better fix is found: - * btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1c, - * 0x3, 0xf1, 0x90); - */ - break; - case 4: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x10, - 0x03, 0xf1, 0x90); - break; - case 5: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0x60, 0x90); - break; - case 6: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x12, - 0x12, 0x60, 0x90); - break; - case 7: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1c, - 0x3, 0x70, 0x90); - break; - case 8: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xa3, 0x10, - 0x3, 0x70, 0x90); - break; - case 9: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0xe1, 0x90); - break; - case 10: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x12, - 0x12, 0xe1, 0x90); - break; - case 11: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0xa, - 0xa, 0xe1, 0x90); - break; - case 12: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x5, - 0x5, 0xe1, 0x90); - break; - case 13: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0x60, 0x90); - break; - case 14: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x12, - 0x12, 0x60, 0x90); - break; - case 15: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0xa, - 0xa, 0x60, 0x90); - break; - case 16: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x5, - 0x5, 0x60, 0x90); - break; - case 17: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xa3, 0x2f, - 0x2f, 0x60, 0x90); - break; - case 18: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x5, - 0x5, 0xe1, 0x90); - break; - case 19: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x25, - 0x25, 0xe1, 0x90); - break; - case 20: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x25, - 0x25, 0x60, 0x90); - break; - case 21: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x15, - 0x03, 0x70, 0x90); - break; - case 71: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0xe1, 0x90); - break; - } - } else { - /* disable PS tdma */ - switch (type) { - case 0: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0, 0x0, - 0x40, 0x0); - break; - case 1: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0, 0x0, - 0x48, 0x0); - break; - default: - btc8723b2ant_set_fw_ps_tdma(btcoexist, 0x0, 0x0, 0x0, - 0x40, 0x0); - break; - } - } - - /* update pre state */ - coex_dm->pre_ps_tdma_on = coex_dm->cur_ps_tdma_on; - coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; -} - -static void btc8723b2ant_coex_alloff(struct btc_coexist *btcoexist) -{ - /* fw all off */ - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - /* sw all off */ - btc8723b2ant_sw_mechanism1(btcoexist, false, false, false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, false, 0x18); - - /* hw all off */ - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 0); -} - -static void btc8723b2ant_init_coex_dm(struct btc_coexist *btcoexist) -{ - /* force to reset coex mechanism*/ - - btc8723b2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 1); - btc8723b2ant_fw_dac_swing_lvl(btcoexist, FORCE_EXEC, 6); - btc8723b2ant_dec_bt_pwr(btcoexist, FORCE_EXEC, false); - - btc8723b2ant_sw_mechanism1(btcoexist, false, false, false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, false, 0x18); -} - -static void btc8723b2ant_action_bt_inquiry(struct btc_coexist *btcoexist) -{ - bool wifi_connected = false; - bool low_pwr_disable = true; - - btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - - if (wifi_connected) { - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); - } else { - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 0); - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - } - btc8723b2ant_fw_dac_swing_lvl(btcoexist, FORCE_EXEC, 6); - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btc8723b2ant_sw_mechanism1(btcoexist, false, false, false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, false, 0x18); - - coex_dm->need_recover_0x948 = true; - coex_dm->backup_0x948 = btcoexist->btc_read_2byte(btcoexist, 0x948); - - btc8723b2ant_set_ant_path(btcoexist, BTC_ANT_WIFI_AT_AUX, - false, false); -} - -static bool btc8723b2ant_is_common_action(struct btc_coexist *btcoexist) -{ - bool common = false, wifi_connected = false; - bool wifi_busy = false; - bool bt_hs_on = false, low_pwr_disable = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - - if (!wifi_connected) { - low_pwr_disable = false; - btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non-connected idle!!\n"); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, - 0x0); - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 0); - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btc8723b2ant_sw_mechanism1(btcoexist, false, false, false, - false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, false, - 0x18); - - common = true; - } else { - if (BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE == - coex_dm->bt_status) { - low_pwr_disable = false; - btcoexist->btc_set(btcoexist, - BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi connected + " - "BT non connected-idle!!\n"); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, - 0xfffff, 0x0); - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 0); - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, - 0xb); - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, - false); - - btc8723b2ant_sw_mechanism1(btcoexist, false, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - - common = true; - } else if (BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE == - coex_dm->bt_status) { - low_pwr_disable = true; - btcoexist->btc_set(btcoexist, - BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - if (bt_hs_on) - return false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi connected + " - "BT connected-idle!!\n"); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, - 0xfffff, 0x0); - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 0); - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, - 0xb); - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, - false); - - btc8723b2ant_sw_mechanism1(btcoexist, true, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - - common = true; - } else { - low_pwr_disable = true; - btcoexist->btc_set(btcoexist, - BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - if (wifi_busy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Connected-Busy + " - "BT Busy!!\n"); - common = false; - } else { - if (bt_hs_on) - return false; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Connected-Idle + " - "BT Busy!!\n"); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, - 0x1, 0xfffff, 0x0); - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, - 7); - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 21); - btc8723b2ant_fw_dac_swing_lvl(btcoexist, - NORMAL_EXEC, - 0xb); - if (btc8723b_need_dec_pwr(btcoexist)) - btc8723b2ant_dec_bt_pwr(btcoexist, - NORMAL_EXEC, - true); - else - btc8723b2ant_dec_bt_pwr(btcoexist, - NORMAL_EXEC, - false); - btc8723b2ant_sw_mechanism1(btcoexist, false, - false, false, - false); - btc8723b2ant_sw_mechanism2(btcoexist, false, - false, false, - 0x18); - common = true; - } - } - } - - return common; -} - -static void set_tdma_int1(struct btc_coexist *btcoexist, bool tx_pause, - s32 result) -{ - /* Set PS TDMA for max interval == 1 */ - if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); - - if (coex_dm->cur_ps_tdma == 71) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - coex_dm->tdma_adj_type = 5; - } else if (coex_dm->cur_ps_tdma == 1) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - coex_dm->tdma_adj_type = 5; - } else if (coex_dm->cur_ps_tdma == 2) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 3) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 4) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } - - if (coex_dm->cur_ps_tdma == 9) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 13); - coex_dm->tdma_adj_type = 13; - } else if (coex_dm->cur_ps_tdma == 10) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 11) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 12) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - - if (result == -1) { - if (coex_dm->cur_ps_tdma == 5) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 6) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } else if (coex_dm->cur_ps_tdma == 13) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 14) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 8) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 6) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - coex_dm->tdma_adj_type = 5; - } else if (coex_dm->cur_ps_tdma == 16) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 14) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 13); - coex_dm->tdma_adj_type = 13; - } - } - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); - if (coex_dm->cur_ps_tdma == 5) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 71); - coex_dm->tdma_adj_type = 71; - } else if (coex_dm->cur_ps_tdma == 6) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 7) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 8) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 4); - coex_dm->tdma_adj_type = 4; - } - - if (coex_dm->cur_ps_tdma == 13) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9); - coex_dm->tdma_adj_type = 9; - } else if (coex_dm->cur_ps_tdma == 14) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 15) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 16) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 12); - coex_dm->tdma_adj_type = 12; - } - - if (result == -1) { - if (coex_dm->cur_ps_tdma == 71) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 1); - coex_dm->tdma_adj_type = 1; - } else if (coex_dm->cur_ps_tdma == 1) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } else if (coex_dm->cur_ps_tdma == 9) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 10) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 4) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 1); - coex_dm->tdma_adj_type = 1; - } else if (coex_dm->cur_ps_tdma == 1) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 71); - coex_dm->tdma_adj_type = 71; - } else if (coex_dm->cur_ps_tdma == 12) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 10) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } - } - } -} - -static void set_tdma_int2(struct btc_coexist *btcoexist, bool tx_pause, - s32 result) -{ - /* Set PS TDMA for max interval == 2 */ - if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); - if (coex_dm->cur_ps_tdma == 1) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 2) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 3) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 4) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 8); - coex_dm->tdma_adj_type = 8; - } - if (coex_dm->cur_ps_tdma == 9) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 10) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 11) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 12) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 16); - coex_dm->tdma_adj_type = 16; - } - if (result == -1) { - if (coex_dm->cur_ps_tdma == 5) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 6) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } else if (coex_dm->cur_ps_tdma == 13) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 14) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 8) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 6) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 16) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 14) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } - } - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); - if (coex_dm->cur_ps_tdma == 5) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 6) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 7) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 8) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 4); - coex_dm->tdma_adj_type = 4; - } - if (coex_dm->cur_ps_tdma == 13) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 14) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 15) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 16) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 12); - coex_dm->tdma_adj_type = 12; - } - if (result == -1) { - if (coex_dm->cur_ps_tdma == 1) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } else if (coex_dm->cur_ps_tdma == 9) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 10) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 4) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 12) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 10) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } - } - } -} - -static void set_tdma_int3(struct btc_coexist *btcoexist, bool tx_pause, - s32 result) -{ - /* Set PS TDMA for max interval == 3 */ - if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); - if (coex_dm->cur_ps_tdma == 1) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 2) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 3) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 4) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 8); - coex_dm->tdma_adj_type = 8; - } - if (coex_dm->cur_ps_tdma == 9) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 10) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 11) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 12) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 16); - coex_dm->tdma_adj_type = 16; - } - if (result == -1) { - if (coex_dm->cur_ps_tdma == 5) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 6) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } else if (coex_dm->cur_ps_tdma == 13) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 14) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 8) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 6) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 16) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 14) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } - } - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); - if (coex_dm->cur_ps_tdma == 5) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 6) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 7) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 8) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 4); - coex_dm->tdma_adj_type = 4; - } - if (coex_dm->cur_ps_tdma == 13) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 14) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 15) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 16) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 12); - coex_dm->tdma_adj_type = 12; - } - if (result == -1) { - if (coex_dm->cur_ps_tdma == 1) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 2) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } else if (coex_dm->cur_ps_tdma == 9) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 10) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 4) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 2) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 12) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 10) { - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } - } - } -} - -static void btc8723b2ant_tdma_duration_adjust(struct btc_coexist *btcoexist, - bool sco_hid, bool tx_pause, - u8 max_interval) -{ - static s32 up, dn, m, n, wait_count; - /*0: no change, +1: increase WiFi duration, -1: decrease WiFi duration*/ - s32 result; - u8 retry_count = 0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], TdmaDurationAdjust()\n"); - - if (!coex_dm->auto_tdma_adjust) { - coex_dm->auto_tdma_adjust = true; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], first run TdmaDurationAdjust()!!\n"); - if (sco_hid) { - if (tx_pause) { - if (max_interval == 1) { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 13); - coex_dm->tdma_adj_type = 13; - } else if (max_interval == 2) { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (max_interval == 3) { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } - } else { - if (max_interval == 1) { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (max_interval == 2) { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (max_interval == 3) { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } - } - } else { - if (tx_pause) { - if (max_interval == 1) { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 5); - coex_dm->tdma_adj_type = 5; - } else if (max_interval == 2) { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (max_interval == 3) { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } - } else { - if (max_interval == 1) { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 1); - coex_dm->tdma_adj_type = 1; - } else if (max_interval == 2) { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (max_interval == 3) { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else { - btc8723b2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } - } - } - - up = 0; - dn = 0; - m = 1; - n = 3; - result = 0; - wait_count = 0; - } else { - /*accquire the BT TRx retry count from BT_Info byte2*/ - retry_count = coex_sta->bt_retry_cnt; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], retry_count = %d\n", retry_count); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], up=%d, dn=%d, m=%d, n=%d, wait_count=%d\n", - up, dn, m, n, wait_count); - result = 0; - wait_count++; - /* no retry in the last 2-second duration*/ - if (retry_count == 0) { - up++; - dn--; - - if (dn <= 0) - dn = 0; - - if (up >= n) { - wait_count = 0; - n = 3; - up = 0; - dn = 0; - result = 1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Increase wifi " - "duration!!\n"); - } /* <=3 retry in the last 2-second duration*/ - } else if (retry_count <= 3) { - up--; - dn++; - - if (up <= 0) - up = 0; - - if (dn == 2) { - if (wait_count <= 2) - m++; - else - m = 1; - - if (m >= 20) - m = 20; - - n = 3 * m; - up = 0; - dn = 0; - wait_count = 0; - result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration " - "for retry_counter<3!!\n"); - } - } else { - if (wait_count == 1) - m++; - else - m = 1; - - if (m >= 20) - m = 20; - - n = 3 * m; - up = 0; - dn = 0; - wait_count = 0; - result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration " - "for retry_counter>3!!\n"); - } - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], max Interval = %d\n", max_interval); - if (max_interval == 1) - set_tdma_int1(btcoexist, tx_pause, result); - else if (max_interval == 2) - set_tdma_int2(btcoexist, tx_pause, result); - else if (max_interval == 3) - set_tdma_int3(btcoexist, tx_pause, result); - } - - /*if current PsTdma not match with the recorded one (when scan, dhcp..), - *then we have to adjust it back to the previous recorded one. - */ - if (coex_dm->cur_ps_tdma != coex_dm->tdma_adj_type) { - bool scan = false, link = false, roam = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], PsTdma type dismatch!!!, " - "curPsTdma=%d, recordPsTdma=%d\n", - coex_dm->cur_ps_tdma, coex_dm->tdma_adj_type); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); - - if (!scan && !link && !roam) - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, - coex_dm->tdma_adj_type); - else - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], roaming/link/scan is under" - " progress, will adjust next time!!!\n"); - } -} - -/* SCO only or SCO+PAN(HS) */ -static void btc8723b2ant_action_sco(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); - - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 4); - - if (btc8723b_need_dec_pwr(btcoexist)) - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - /*for SCO quality at 11b/g mode*/ - if (BTC_WIFI_BW_LEGACY == wifi_bw) - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 2); - else /*for SCO quality & wifi performance balance at 11n mode*/ - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 8); - - /*for voice quality */ - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 0); - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, true, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - true, 0x4); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, true, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - true, 0x4); - } - } else { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, false, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - true, 0x4); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, false, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - true, 0x4); - } - } -} - -static void btc8723b2ant_action_hid(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); - - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if (btc8723b_need_dec_pwr(btcoexist)) - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (BTC_WIFI_BW_LEGACY == wifi_bw) /*/for HID at 11b/g mode*/ - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); - else /*for HID quality & wifi performance balance at 11n mode*/ - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 9); - - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 9); - else - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13); - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, true, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, true, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, false, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, false, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } -} - -/*A2DP only / PAN(EDR) only/ A2DP+PAN(HS)*/ -static void btc8723b2ant_action_a2dp(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, wifi_rssi_state1, bt_rssi_state; - u32 wifi_bw; - u8 ap_num = 0; - - wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - wifi_rssi_state1 = btc8723b2ant_wifi_rssi_state(btcoexist, - 1, 2, 40, 0); - bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); - - btcoexist->btc_get(btcoexist, BTC_GET_U1_AP_NUM, &ap_num); - - /* define the office environment */ - /* driver don't know AP num in Linux, so we will never enter this if */ - if (ap_num >= 10 && BTC_RSSI_HIGH(wifi_rssi_state1)) { - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, - 0x0); - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 0); - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - - /* sw mechanism */ - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) { - btc8723b2ant_sw_mechanism1(btcoexist, true, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - true, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, false, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - true, 0x18); - } - return; - } - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); - - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if (btc8723b_need_dec_pwr(btcoexist)) - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); - - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) - btc8723b2ant_tdma_duration_adjust(btcoexist, false, - false, 1); - else - btc8723b2ant_tdma_duration_adjust(btcoexist, false, true, 1); - - /* sw mechanism */ - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, true, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, true, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, false, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, false, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void btc8723b2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); - - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if (btc8723b_need_dec_pwr(btcoexist)) - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); - - btc8723b2ant_tdma_duration_adjust(btcoexist, false, true, 2); - - /* sw mechanism */ - btcoexist->btc_get(btcoexist, - BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, true, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, true, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, false, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, false, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void btc8723b2ant_action_pan_edr(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); - - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if (btc8723b_need_dec_pwr(btcoexist)) - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 10); - - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 1); - else - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); - - /* sw mechanism */ - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, true, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, true, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, false, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, false, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } -} - -/*PAN(HS) only*/ -static void btc8723b2ant_action_pan_hs(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); - - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); - - btc8723b2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, true, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, true, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, false, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, false, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } -} - -/*PAN(EDR)+A2DP*/ -static void btc8723b2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); - - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if (btc8723b_need_dec_pwr(btcoexist)) - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 12); - if (BTC_WIFI_BW_HT40 == wifi_bw) - btc8723b2ant_tdma_duration_adjust(btcoexist, false, - true, 3); - else - btc8723b2ant_tdma_duration_adjust(btcoexist, false, - false, 3); - } else { - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); - btc8723b2ant_tdma_duration_adjust(btcoexist, false, true, 3); - } - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, true, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, true, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, false, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, false, false, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void btc8723b2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (btc8723b_need_dec_pwr(btcoexist)) - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - if (BTC_WIFI_BW_HT40 == wifi_bw) { - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, - 3); - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 11); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, - 0xfffff, 0x780); - } else { - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, - 6); - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, - 0xfffff, 0x0); - } - btc8723b2ant_tdma_duration_adjust(btcoexist, true, false, 2); - } else { - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 11); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, - 0x0); - btc8723b2ant_tdma_duration_adjust(btcoexist, true, true, 2); - } - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, true, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, true, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, false, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, false, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } -} - -/* HID+A2DP+PAN(EDR) */ -static void btc8723b2ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); - - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if (btc8723b_need_dec_pwr(btcoexist)) - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); - - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - if (BTC_WIFI_BW_HT40 == wifi_bw) - btc8723b2ant_tdma_duration_adjust(btcoexist, true, - true, 2); - else - btc8723b2ant_tdma_duration_adjust(btcoexist, true, - false, 3); - } else { - btc8723b2ant_tdma_duration_adjust(btcoexist, true, true, 3); - } - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, true, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, true, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, false, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, false, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void btc8723b2ant_action_hid_a2dp(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = btc8723b2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - bt_rssi_state = btc8723b2ant_bt_rssi_state(2, 29, 0); - - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1, 0xfffff, 0x0); - - btc8723b2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if (btc8723b_need_dec_pwr(btcoexist)) - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - btc8723b2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - btc8723b_coex_tbl_type(btcoexist, NORMAL_EXEC, 7); - - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) - btc8723b2ant_tdma_duration_adjust(btcoexist, true, false, 2); - else - btc8723b2ant_tdma_duration_adjust(btcoexist, true, true, 2); - - /* sw mechanism */ - if (BTC_WIFI_BW_HT40 == wifi_bw) { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, true, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, true, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } else { - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8723b2ant_sw_mechanism1(btcoexist, false, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, true, false, - false, 0x18); - } else { - btc8723b2ant_sw_mechanism1(btcoexist, false, true, - false, false); - btc8723b2ant_sw_mechanism2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void btc8723b2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) -{ - u8 algorithm = 0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism()===>\n"); - - if (btcoexist->manual_control) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), " - "return for Manual CTRL <===\n"); - return; - } - - if (coex_sta->under_ips) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], wifi is under IPS !!!\n"); - return; - } - - algorithm = btc8723b2ant_action_algorithm(btcoexist); - if (coex_sta->c2h_bt_inquiry_page && - (BT_8723B_2ANT_COEX_ALGO_PANHS != algorithm)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT is under inquiry/page scan !!\n"); - btc8723b2ant_action_bt_inquiry(btcoexist); - return; - } else { - if (coex_dm->need_recover_0x948) { - coex_dm->need_recover_0x948 = false; - btcoexist->btc_write_2byte(btcoexist, 0x948, - coex_dm->backup_0x948); - } - } - - coex_dm->cur_algorithm = algorithm; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, "[BTCoex], Algorithm = %d\n", - coex_dm->cur_algorithm); - - if (btc8723b2ant_is_common_action(btcoexist)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant common.\n"); - coex_dm->auto_tdma_adjust = false; - } else { - if (coex_dm->cur_algorithm != coex_dm->pre_algorithm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], preAlgorithm=%d, " - "curAlgorithm=%d\n", coex_dm->pre_algorithm, - coex_dm->cur_algorithm); - coex_dm->auto_tdma_adjust = false; - } - switch (coex_dm->cur_algorithm) { - case BT_8723B_2ANT_COEX_ALGO_SCO: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = SCO.\n"); - btc8723b2ant_action_sco(btcoexist); - break; - case BT_8723B_2ANT_COEX_ALGO_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = HID.\n"); - btc8723b2ant_action_hid(btcoexist); - break; - case BT_8723B_2ANT_COEX_ALGO_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = A2DP.\n"); - btc8723b2ant_action_a2dp(btcoexist); - break; - case BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = A2DP+PAN(HS).\n"); - btc8723b2ant_action_a2dp_pan_hs(btcoexist); - break; - case BT_8723B_2ANT_COEX_ALGO_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = PAN(EDR).\n"); - btc8723b2ant_action_pan_edr(btcoexist); - break; - case BT_8723B_2ANT_COEX_ALGO_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = HS mode.\n"); - btc8723b2ant_action_pan_hs(btcoexist); - break; - case BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = PAN+A2DP.\n"); - btc8723b2ant_action_pan_edr_a2dp(btcoexist); - break; - case BT_8723B_2ANT_COEX_ALGO_PANEDR_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = PAN(EDR)+HID.\n"); - btc8723b2ant_action_pan_edr_hid(btcoexist); - break; - case BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = HID+A2DP+PAN.\n"); - btc8723b2ant_action_hid_a2dp_pan_edr(btcoexist); - break; - case BT_8723B_2ANT_COEX_ALGO_HID_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = HID+A2DP.\n"); - btc8723b2ant_action_hid_a2dp(btcoexist); - break; - default: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, " - "algorithm = coexist All Off!!\n"); - btc8723b2ant_coex_alloff(btcoexist); - break; - } - coex_dm->pre_algorithm = coex_dm->cur_algorithm; - } -} - -static void btc8723b2ant_wifioff_hwcfg(struct btc_coexist *btcoexist) -{ - /* set wlan_act to low */ - btcoexist->btc_write_1byte(btcoexist, 0x76e, 0x4); - /* Force GNT_BT to High */ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x3); - /* BT select s0/s1 is controlled by BT */ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x67, 0x20, 0x0); -} - -/********************************************************************* - * work around function start with wa_btc8723b2ant_ - *********************************************************************/ -/********************************************************************* - * extern function start with EXbtc8723b2ant_ - *********************************************************************/ -void ex_btc8723b2ant_init_hwconfig(struct btc_coexist *btcoexist) -{ - u8 u8tmp = 0; - - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], 2Ant Init HW Config!!\n"); - coex_dm->bt_rf0x1e_backup = - btcoexist->btc_get_rf_reg(btcoexist, BTC_RF_A, 0x1e, 0xfffff); - - /* 0x790[5:0] = 0x5 */ - u8tmp = btcoexist->btc_read_1byte(btcoexist, 0x790); - u8tmp &= 0xc0; - u8tmp |= 0x5; - btcoexist->btc_write_1byte(btcoexist, 0x790, u8tmp); - - /*Antenna config */ - btc8723b2ant_set_ant_path(btcoexist, BTC_ANT_WIFI_AT_MAIN, - true, false); - /* PTA parameter */ - btc8723b_coex_tbl_type(btcoexist, FORCE_EXEC, 0); - - /* Enable counter statistics */ - /*0x76e[3] =1, WLAN_Act control by PTA*/ - btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); - btcoexist->btc_write_1byte(btcoexist, 0x778, 0x3); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1); -} - -void ex_btc8723b2ant_init_coex_dm(struct btc_coexist *btcoexist) -{ - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Coex Mechanism Init!!\n"); - btc8723b2ant_init_coex_dm(btcoexist); -} - -void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist) -{ - struct btc_board_info *board_info = &btcoexist->board_info; - struct btc_stack_info *stack_info = &btcoexist->stack_info; - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - struct rtl_priv *rtlpriv = btcoexist->adapter; - u8 u8tmp[4], i, bt_info_ext, ps_tdma_case = 0; - u32 u32tmp[4]; - bool roam = false, scan = false; - bool link = false, wifi_under_5g = false; - bool bt_hs_on = false, wifi_busy = false; - s32 wifi_rssi = 0, bt_hs_rssi = 0; - u32 wifi_bw, wifi_traffic_dir, fa_ofdm, fa_cck; - u8 wifi_dot11_chnl, wifi_hs_chnl; - u32 fw_ver = 0, bt_patch_ver = 0; - u8 ap_num = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n ============[BT Coexist info]============"); - - if (btcoexist->manual_control) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n ==========[Under Manual Control]============"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n =========================================="); - } - - if (!board_info->bt_exist) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n BT not exists !!!"); - return; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d ", - "Ant PG number/ Ant mechanism:", - board_info->pg_ant_num, board_info->btdm_ant_num); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s / %d", - "BT stack/ hci ext ver", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d_%x/ 0x%x/ 0x%x(%d)", - "CoexVer/ FwVer/ PatchVer", - glcoex_ver_date_8723b_2ant, glcoex_ver_8723b_2ant, - fw_ver, bt_patch_ver, bt_patch_ver); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_DOT11_CHNL, - &wifi_dot11_chnl); - btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_HS_CHNL, &wifi_hs_chnl); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d / %d(%d)", - "Dot11 channel / HsChnl(HsMode)", - wifi_dot11_chnl, wifi_hs_chnl, bt_hs_on); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %02x %02x %02x ", - "H2C Wifi inform bt chnl Info", coex_dm->wifi_chnl_info[0], - coex_dm->wifi_chnl_info[1], coex_dm->wifi_chnl_info[2]); - - btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); - btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi); - btcoexist->btc_get(btcoexist, BTC_GET_U1_AP_NUM, &ap_num); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d", - "Wifi rssi/ HS rssi/ AP#", wifi_rssi, bt_hs_rssi, ap_num); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d ", - "Wifi link/ roam/ scan", link, roam, scan); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, - &wifi_traffic_dir); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s / %s/ %s ", - "Wifi status", (wifi_under_5g ? "5G" : "2.4G"), - ((BTC_WIFI_BW_LEGACY == wifi_bw) ? "Legacy" : - (((BTC_WIFI_BW_HT40 == wifi_bw) ? "HT40" : "HT20"))), - ((!wifi_busy) ? "idle" : - ((BTC_WIFI_TRAFFIC_TX == wifi_traffic_dir) ? - "uplink" : "downlink"))); - - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d / %d / %d / %d", - "SCO/HID/PAN/A2DP", - bt_link_info->sco_exist, bt_link_info->hid_exist, - bt_link_info->pan_exist, bt_link_info->a2dp_exist); - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_BT_LINK_INFO); - - bt_info_ext = coex_sta->bt_info_ext; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s", - "BT Info A2DP rate", - (bt_info_ext&BIT0) ? "Basic rate" : "EDR rate"); - - for (i = 0; i < BT_INFO_SRC_8723B_2ANT_MAX; i++) { - if (coex_sta->bt_info_c2h_cnt[i]) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %02x %02x %02x " - "%02x %02x %02x %02x(%d)", - glbt_info_src_8723b_2ant[i], - coex_sta->bt_info_c2h[i][0], - coex_sta->bt_info_c2h[i][1], - coex_sta->bt_info_c2h[i][2], - coex_sta->bt_info_c2h[i][3], - coex_sta->bt_info_c2h[i][4], - coex_sta->bt_info_c2h[i][5], - coex_sta->bt_info_c2h[i][6], - coex_sta->bt_info_c2h_cnt[i]); - } - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s/%s", - "PS state, IPS/LPS", - ((coex_sta->under_ips ? "IPS ON" : "IPS OFF")), - ((coex_sta->under_lps ? "LPS ON" : "LPS OFF"))); - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD); - - /* Sw mechanism */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s", "============[Sw mechanism]============"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d ", - "SM1[ShRf/ LpRA/ LimDig]", coex_dm->cur_rf_rx_lpf_shrink, - coex_dm->cur_low_penalty_ra, coex_dm->limited_dig); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d/ %d(0x%x) ", - "SM2[AgcT/ AdcB/ SwDacSwing(lvl)]", - coex_dm->cur_agc_table_en, coex_dm->cur_adc_back_off, - coex_dm->cur_dac_swing_on, coex_dm->cur_dac_swing_lvl); - - /* Fw mechanism */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", - "============[Fw mechanism]============"); - - ps_tdma_case = coex_dm->cur_ps_tdma; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", - "PS TDMA", coex_dm->ps_tdma_para[0], - coex_dm->ps_tdma_para[1], coex_dm->ps_tdma_para[2], - coex_dm->ps_tdma_para[3], coex_dm->ps_tdma_para[4], - ps_tdma_case, coex_dm->auto_tdma_adjust); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d ", - "DecBtPwr/ IgnWlanAct", coex_dm->cur_dec_bt_pwr, - coex_dm->cur_ignore_wlan_act); - - /* Hw setting */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", - "============[Hw setting]============"); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x", - "RF-A, 0x1e initVal", coex_dm->bt_rf0x1e_backup); - - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x778); - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x880); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "0x778/0x880[29:25]", u8tmp[0], - (u32tmp[0]&0x3e000000) >> 25); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x948); - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x67); - u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x765); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "0x948/ 0x67[5] / 0x765", - u32tmp[0], ((u8tmp[0]&0x20) >> 5), u8tmp[1]); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x92c); - u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x930); - u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x944); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "0x92c[1:0]/ 0x930[7:0]/0x944[1:0]", - u32tmp[0]&0x3, u32tmp[1]&0xff, u32tmp[2]&0x3); - - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x39); - u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x40); - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x4c); - u8tmp[2] = btcoexist->btc_read_1byte(btcoexist, 0x64); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", - "0x38[11]/0x40/0x4c[24:23]/0x64[0]", - ((u8tmp[0] & 0x8)>>3), u8tmp[1], - ((u32tmp[0]&0x01800000)>>23), u8tmp[2]&0x1); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x550); - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x522); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "0x550(bcn ctrl)/0x522", u32tmp[0], u8tmp[0]); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc50); - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x49c); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "0xc50(dig)/0x49c(null-drop)", u32tmp[0]&0xff, u8tmp[0]); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xda0); - u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0xda4); - u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0xda8); - u32tmp[3] = btcoexist->btc_read_4byte(btcoexist, 0xcf0); - - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xa5b); - u8tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xa5c); - - fa_ofdm = ((u32tmp[0]&0xffff0000) >> 16) + - ((u32tmp[1]&0xffff0000) >> 16) + - (u32tmp[1] & 0xffff) + - (u32tmp[2] & 0xffff) + - ((u32tmp[3]&0xffff0000) >> 16) + - (u32tmp[3] & 0xffff); - fa_cck = (u8tmp[0] << 8) + u8tmp[1]; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "OFDM-CCA/OFDM-FA/CCK-FA", - u32tmp[0]&0xffff, fa_ofdm, fa_cck); - - u32tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6c0); - u32tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x6c4); - u32tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x6c8); - u8tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x6cc); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", - "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)", - u32tmp[0], u32tmp[1], u32tmp[2], u8tmp[0]); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", - "0x770(high-pri rx/tx)", - coex_sta->high_priority_rx, coex_sta->high_priority_tx); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", - "0x774(low-pri rx/tx)", coex_sta->low_priority_rx, - coex_sta->low_priority_tx); -#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 1) - btc8723b2ant_monitor_bt_ctr(btcoexist); -#endif - btcoexist->btc_disp_dbg_msg(btcoexist, - BTC_DBG_DISP_COEX_STATISTICS); -} - -void ex_btc8723b2ant_ips_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (BTC_IPS_ENTER == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS ENTER notify\n"); - coex_sta->under_ips = true; - btc8723b2ant_wifioff_hwcfg(btcoexist); - btc8723b2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); - btc8723b2ant_coex_alloff(btcoexist); - } else if (BTC_IPS_LEAVE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS LEAVE notify\n"); - coex_sta->under_ips = false; - ex_btc8723b2ant_init_hwconfig(btcoexist); - btc8723b2ant_init_coex_dm(btcoexist); - btc8723b2ant_query_bt_info(btcoexist); - } -} - -void ex_btc8723b2ant_lps_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (BTC_LPS_ENABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS ENABLE notify\n"); - coex_sta->under_lps = true; - } else if (BTC_LPS_DISABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS DISABLE notify\n"); - coex_sta->under_lps = false; - } -} - -void ex_btc8723b2ant_scan_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (BTC_SCAN_START == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN START notify\n"); - else if (BTC_SCAN_FINISH == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN FINISH notify\n"); -} - -void ex_btc8723b2ant_connect_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (BTC_ASSOCIATE_START == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT START notify\n"); - else if (BTC_ASSOCIATE_FINISH == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT FINISH notify\n"); -} - -void ex_btc8723b2ant_media_status_notify(struct btc_coexist *btcoexist, - u8 type) -{ - u8 h2c_parameter[3] = {0}; - u32 wifi_bw; - u8 wifi_central_chnl; - - if (BTC_MEDIA_CONNECT == type) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA connect notify\n"); - else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA disconnect notify\n"); - - /* only 2.4G we need to inform bt the chnl mask */ - btcoexist->btc_get(btcoexist, - BTC_GET_U1_WIFI_CENTRAL_CHNL, &wifi_central_chnl); - if ((BTC_MEDIA_CONNECT == type) && - (wifi_central_chnl <= 14)) { - h2c_parameter[0] = 0x1; - h2c_parameter[1] = wifi_central_chnl; - btcoexist->btc_get(btcoexist, - BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) - h2c_parameter[2] = 0x30; - else - h2c_parameter[2] = 0x20; - } - - coex_dm->wifi_chnl_info[0] = h2c_parameter[0]; - coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; - coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x66=0x%x\n", - h2c_parameter[0] << 16 | h2c_parameter[1] << 8 | - h2c_parameter[2]); - - btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); -} - -void ex_btc8723b2ant_special_packet_notify(struct btc_coexist *btcoexist, - u8 type) -{ - if (type == BTC_PACKET_DHCP) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], DHCP Packet notify\n"); -} - -void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist, - u8 *tmpbuf, u8 length) -{ - u8 bt_info = 0; - u8 i, rsp_source = 0; - bool bt_busy = false, limited_dig = false; - bool wifi_connected = false; - - coex_sta->c2h_bt_info_req_sent = false; - - rsp_source = tmpbuf[0]&0xf; - if (rsp_source >= BT_INFO_SRC_8723B_2ANT_MAX) - rsp_source = BT_INFO_SRC_8723B_2ANT_WIFI_FW; - coex_sta->bt_info_c2h_cnt[rsp_source]++; - - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Bt info[%d], length=%d, hex data=[", - rsp_source, length); - for (i = 0; i < length; i++) { - coex_sta->bt_info_c2h[rsp_source][i] = tmpbuf[i]; - if (i == 1) - bt_info = tmpbuf[i]; - if (i == length-1) - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x]\n", tmpbuf[i]); - else - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x, ", tmpbuf[i]); - } - - if (btcoexist->manual_control) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), " - "return for Manual CTRL<===\n"); - return; - } - - if (BT_INFO_SRC_8723B_2ANT_WIFI_FW != rsp_source) { - coex_sta->bt_retry_cnt = /* [3:0]*/ - coex_sta->bt_info_c2h[rsp_source][2] & 0xf; - - coex_sta->bt_rssi = - coex_sta->bt_info_c2h[rsp_source][3] * 2 + 10; - - coex_sta->bt_info_ext = - coex_sta->bt_info_c2h[rsp_source][4]; - - /* Here we need to resend some wifi info to BT - because bt is reset and loss of the info. - */ - if ((coex_sta->bt_info_ext & BIT1)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit1 check," - " send wifi BW&Chnl to BT!!\n"); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - if (wifi_connected) - ex_btc8723b2ant_media_status_notify( - btcoexist, - BTC_MEDIA_CONNECT); - else - ex_btc8723b2ant_media_status_notify( - btcoexist, - BTC_MEDIA_DISCONNECT); - } - - if ((coex_sta->bt_info_ext & BIT3)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit3 check, " - "set BT NOT to ignore Wlan active!!\n"); - btc8723b2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, - false); - } else { - /* BT already NOT ignore Wlan active, do nothing here.*/ - } -#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 0) - if ((coex_sta->bt_info_ext & BIT4)) { - /* BT auto report already enabled, do nothing*/ - } else { - btc8723b2ant_bt_auto_report(btcoexist, FORCE_EXEC, - true); - } -#endif - } - - /* check BIT2 first ==> check if bt is under inquiry or page scan*/ - if (bt_info & BT_INFO_8723B_2ANT_B_INQ_PAGE) - coex_sta->c2h_bt_inquiry_page = true; - else - coex_sta->c2h_bt_inquiry_page = false; - - /* set link exist status*/ - if (!(bt_info & BT_INFO_8723B_2ANT_B_CONNECTION)) { - coex_sta->bt_link_exist = false; - coex_sta->pan_exist = false; - coex_sta->a2dp_exist = false; - coex_sta->hid_exist = false; - coex_sta->sco_exist = false; - } else { /* connection exists */ - coex_sta->bt_link_exist = true; - if (bt_info & BT_INFO_8723B_2ANT_B_FTP) - coex_sta->pan_exist = true; - else - coex_sta->pan_exist = false; - if (bt_info & BT_INFO_8723B_2ANT_B_A2DP) - coex_sta->a2dp_exist = true; - else - coex_sta->a2dp_exist = false; - if (bt_info & BT_INFO_8723B_2ANT_B_HID) - coex_sta->hid_exist = true; - else - coex_sta->hid_exist = false; - if (bt_info & BT_INFO_8723B_2ANT_B_SCO_ESCO) - coex_sta->sco_exist = true; - else - coex_sta->sco_exist = false; - } - - btc8723b2ant_update_bt_link_info(btcoexist); - - if (!(bt_info & BT_INFO_8723B_2ANT_B_CONNECTION)) { - coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), " - "BT Non-Connected idle!!!\n"); - /* connection exists but no busy */ - } else if (bt_info == BT_INFO_8723B_2ANT_B_CONNECTION) { - coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"); - } else if ((bt_info & BT_INFO_8723B_2ANT_B_SCO_ESCO) || - (bt_info & BT_INFO_8723B_2ANT_B_SCO_BUSY)) { - coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_SCO_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"); - } else if (bt_info&BT_INFO_8723B_2ANT_B_ACL_BUSY) { - coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_ACL_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"); - } else { - coex_dm->bt_status = BT_8723B_2ANT_BT_STATUS_MAX; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), " - "BT Non-Defined state!!!\n"); - } - - if ((BT_8723B_2ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || - (BT_8723B_2ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || - (BT_8723B_2ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) { - bt_busy = true; - limited_dig = true; - } else { - bt_busy = false; - limited_dig = false; - } - - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy); - - coex_dm->limited_dig = limited_dig; - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_LIMITED_DIG, &limited_dig); - - btc8723b2ant_run_coexist_mechanism(btcoexist); -} - -void ex_btc8723b2ant_halt_notify(struct btc_coexist *btcoexist) -{ - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, "[BTCoex], Halt notify\n"); - - btc8723b2ant_wifioff_hwcfg(btcoexist); - btc8723b2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); - ex_btc8723b2ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT); -} - -void ex_btc8723b2ant_periodical(struct btc_coexist *btcoexist) -{ - struct btc_board_info *board_info = &btcoexist->board_info; - struct btc_stack_info *stack_info = &btcoexist->stack_info; - static u8 dis_ver_info_cnt; - u32 fw_ver = 0, bt_patch_ver = 0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], ==========================" - "Periodical===========================\n"); - - if (dis_ver_info_cnt <= 5) { - dis_ver_info_cnt += 1; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************" - "************************************\n"); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Ant PG Num/ Ant Mech/ " - "Ant Pos = %d/ %d/ %d\n", board_info->pg_ant_num, - board_info->btdm_ant_num, board_info->btdm_ant_pos); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], BT stack/ hci ext ver = %s / %d\n", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); - btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, - &bt_patch_ver); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], CoexVer/ fw_ver/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", - glcoex_ver_date_8723b_2ant, glcoex_ver_8723b_2ant, - fw_ver, bt_patch_ver, bt_patch_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], *****************************" - "***********************************\n"); - } - -#if (BT_AUTO_REPORT_ONLY_8723B_2ANT == 0) - btc8723b2ant_query_bt_info(btcoexist); - btc8723b2ant_monitor_bt_ctr(btcoexist); - btc8723b2ant_monitor_bt_enable_disable(btcoexist); -#else - if (btc8723b2ant_is_wifi_status_changed(btcoexist) || - coex_dm->auto_tdma_adjust) - btc8723b2ant_run_coexist_mechanism(btcoexist); -#endif -} diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h deleted file mode 100644 index 567f354caf95..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8723b2ant.h +++ /dev/null @@ -1,172 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#ifndef _HAL8723B_2_ANT -#define _HAL8723B_2_ANT - -/************************************************************************ - * The following is for 8723B 2Ant BT Co-exist definition - ************************************************************************/ -#define BT_AUTO_REPORT_ONLY_8723B_2ANT 1 - -#define BT_INFO_8723B_2ANT_B_FTP BIT7 -#define BT_INFO_8723B_2ANT_B_A2DP BIT6 -#define BT_INFO_8723B_2ANT_B_HID BIT5 -#define BT_INFO_8723B_2ANT_B_SCO_BUSY BIT4 -#define BT_INFO_8723B_2ANT_B_ACL_BUSY BIT3 -#define BT_INFO_8723B_2ANT_B_INQ_PAGE BIT2 -#define BT_INFO_8723B_2ANT_B_SCO_ESCO BIT1 -#define BT_INFO_8723B_2ANT_B_CONNECTION BIT0 - -#define BTC_RSSI_COEX_THRESH_TOL_8723B_2ANT 2 - -enum BT_INFO_SRC_8723B_2ANT { - BT_INFO_SRC_8723B_2ANT_WIFI_FW = 0x0, - BT_INFO_SRC_8723B_2ANT_BT_RSP = 0x1, - BT_INFO_SRC_8723B_2ANT_BT_ACTIVE_SEND = 0x2, - BT_INFO_SRC_8723B_2ANT_MAX -}; - -enum BT_8723B_2ANT_BT_STATUS { - BT_8723B_2ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0, - BT_8723B_2ANT_BT_STATUS_CONNECTED_IDLE = 0x1, - BT_8723B_2ANT_BT_STATUS_INQ_PAGE = 0x2, - BT_8723B_2ANT_BT_STATUS_ACL_BUSY = 0x3, - BT_8723B_2ANT_BT_STATUS_SCO_BUSY = 0x4, - BT_8723B_2ANT_BT_STATUS_ACL_SCO_BUSY = 0x5, - BT_8723B_2ANT_BT_STATUS_MAX -}; - -enum BT_8723B_2ANT_COEX_ALGO { - BT_8723B_2ANT_COEX_ALGO_UNDEFINED = 0x0, - BT_8723B_2ANT_COEX_ALGO_SCO = 0x1, - BT_8723B_2ANT_COEX_ALGO_HID = 0x2, - BT_8723B_2ANT_COEX_ALGO_A2DP = 0x3, - BT_8723B_2ANT_COEX_ALGO_A2DP_PANHS = 0x4, - BT_8723B_2ANT_COEX_ALGO_PANEDR = 0x5, - BT_8723B_2ANT_COEX_ALGO_PANHS = 0x6, - BT_8723B_2ANT_COEX_ALGO_PANEDR_A2DP = 0x7, - BT_8723B_2ANT_COEX_ALGO_PANEDR_HID = 0x8, - BT_8723B_2ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x9, - BT_8723B_2ANT_COEX_ALGO_HID_A2DP = 0xa, - BT_8723B_2ANT_COEX_ALGO_MAX = 0xb, -}; - -struct coex_dm_8723b_2ant { - /* fw mechanism */ - bool pre_dec_bt_pwr; - bool cur_dec_bt_pwr; - u8 pre_fw_dac_swing_lvl; - u8 cur_fw_dac_swing_lvl; - bool cur_ignore_wlan_act; - bool pre_ignore_wlan_act; - u8 pre_ps_tdma; - u8 cur_ps_tdma; - u8 ps_tdma_para[5]; - u8 tdma_adj_type; - bool reset_tdma_adjust; - bool auto_tdma_adjust; - bool pre_ps_tdma_on; - bool cur_ps_tdma_on; - bool pre_bt_auto_report; - bool cur_bt_auto_report; - - /* sw mechanism */ - bool pre_rf_rx_lpf_shrink; - bool cur_rf_rx_lpf_shrink; - u32 bt_rf0x1e_backup; - bool pre_low_penalty_ra; - bool cur_low_penalty_ra; - bool pre_dac_swing_on; - u32 pre_dac_swing_lvl; - bool cur_dac_swing_on; - u32 cur_dac_swing_lvl; - bool pre_adc_back_off; - bool cur_adc_back_off; - bool pre_agc_table_en; - bool cur_agc_table_en; - u32 pre_val0x6c0; - u32 cur_val0x6c0; - u32 pre_val0x6c4; - u32 cur_val0x6c4; - u32 pre_val0x6c8; - u32 cur_val0x6c8; - u8 pre_val0x6cc; - u8 cur_val0x6cc; - bool limited_dig; - - /* algorithm related */ - u8 pre_algorithm; - u8 cur_algorithm; - u8 bt_status; - u8 wifi_chnl_info[3]; - - bool need_recover_0x948; - u16 backup_0x948; -}; - -struct coex_sta_8723b_2ant { - bool bt_link_exist; - bool sco_exist; - bool a2dp_exist; - bool hid_exist; - bool pan_exist; - - bool under_lps; - bool under_ips; - u32 high_priority_tx; - u32 high_priority_rx; - u32 low_priority_tx; - u32 low_priority_rx; - u8 bt_rssi; - u8 pre_bt_rssi_state; - u8 pre_wifi_rssi_state[4]; - bool c2h_bt_info_req_sent; - u8 bt_info_c2h[BT_INFO_SRC_8723B_2ANT_MAX][10]; - u32 bt_info_c2h_cnt[BT_INFO_SRC_8723B_2ANT_MAX]; - bool c2h_bt_inquiry_page; - u8 bt_retry_cnt; - u8 bt_info_ext; -}; - -/********************************************************************* - * The following is interface which will notify coex module. - *********************************************************************/ -void ex_btc8723b2ant_init_hwconfig(struct btc_coexist *btcoexist); -void ex_btc8723b2ant_init_coex_dm(struct btc_coexist *btcoexist); -void ex_btc8723b2ant_ips_notify(struct btc_coexist *btcoexist, u8 type); -void ex_btc8723b2ant_lps_notify(struct btc_coexist *btcoexist, u8 type); -void ex_btc8723b2ant_scan_notify(struct btc_coexist *btcoexist, u8 type); -void ex_btc8723b2ant_connect_notify(struct btc_coexist *btcoexist, u8 type); -void ex_btc8723b2ant_media_status_notify(struct btc_coexist *btcoexist, - u8 type); -void ex_btc8723b2ant_special_packet_notify(struct btc_coexist *btcoexist, - u8 type); -void ex_btc8723b2ant_bt_info_notify(struct btc_coexist *btcoexist, - u8 *tmpbuf, u8 length); -void ex_btc8723b2ant_halt_notify(struct btc_coexist *btcoexist); -void ex_btc8723b2ant_periodical(struct btc_coexist *btcoexist); -void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist); - -#endif diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.c b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.c deleted file mode 100644 index b72e5377bdbc..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.c +++ /dev/null @@ -1,2970 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -/*============================================================ - * Description: - * - * This file is for RTL8821A Co-exist mechanism - * - * History - * 2012/11/15 Cosa first check in. - * - *============================================================ -*/ -/*============================================================ - * include files - *============================================================ - */ -#include "halbt_precomp.h" -/*============================================================ - * Global variables, these are static variables - *============================================================ - */ -static struct coex_dm_8821a_1ant glcoex_dm_8821a_1ant; -static struct coex_dm_8821a_1ant *coex_dm = &glcoex_dm_8821a_1ant; -static struct coex_sta_8821a_1ant glcoex_sta_8821a_1ant; -static struct coex_sta_8821a_1ant *coex_sta = &glcoex_sta_8821a_1ant; - -static const char *const glbt_info_src_8821a_1ant[] = { - "BT Info[wifi fw]", - "BT Info[bt rsp]", - "BT Info[bt auto report]", -}; - -static u32 glcoex_ver_date_8821a_1ant = 20130816; -static u32 glcoex_ver_8821a_1ant = 0x41; - -/*============================================================ - * local function proto type if needed - * - * local function start with halbtc8821a1ant_ - *============================================================ - */ -static u8 halbtc8821a1ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, - u8 rssi_thresh1) -{ - long bt_rssi = 0; - u8 bt_rssi_state = coex_sta->pre_bt_rssi_state; - - bt_rssi = coex_sta->bt_rssi; - - if (level_num == 2) { - if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || - (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { - if (bt_rssi >= (rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { - bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to High\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Low\n"); - } - } else { - if (bt_rssi < rssi_thresh) { - bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Low\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at High\n"); - } - } - } else if (level_num == 3) { - if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi thresh error!!\n"); - return coex_sta->pre_bt_rssi_state; - } - - if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || - (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { - if (bt_rssi >= (rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { - bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Medium\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Low\n"); - } - } else if ((coex_sta->pre_bt_rssi_state == - BTC_RSSI_STATE_MEDIUM) || - (coex_sta->pre_bt_rssi_state == - BTC_RSSI_STATE_STAY_MEDIUM)) { - if (bt_rssi >= (rssi_thresh1 + - BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { - bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to High\n"); - } else if (bt_rssi < rssi_thresh) { - bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Low\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Medium\n"); - } - } else { - if (bt_rssi < rssi_thresh1) { - bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Medium\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at High\n"); - } - } - } - coex_sta->pre_bt_rssi_state = bt_rssi_state; - - return bt_rssi_state; -} - -static u8 halbtc8821a1ant_WifiRssiState(struct btc_coexist *btcoexist, - u8 index, u8 level_num, u8 rssi_thresh, - u8 rssi_thresh1) -{ - long wifi_rssi = 0; - u8 wifi_rssi_state = coex_sta->pre_wifi_rssi_state[index]; - - btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); - - if (level_num == 2) { - if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_LOW) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_LOW)) { - if (wifi_rssi >= - (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { - wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to High\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Low\n"); - } - } else { - if (wifi_rssi < rssi_thresh) { - wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Low\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at High\n"); - } - } - } else if (level_num == 3) { - if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI thresh error!!\n"); - return coex_sta->pre_wifi_rssi_state[index]; - } - - if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_LOW) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_LOW)) { - if (wifi_rssi >= - (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { - wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Medium\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Low\n"); - } - } else if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_MEDIUM) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_MEDIUM)) { - if (wifi_rssi >= - (rssi_thresh1 + - BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT)) { - wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to High\n"); - } else if (wifi_rssi < rssi_thresh) { - wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Low\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Medium\n"); - } - } else { - if (wifi_rssi < rssi_thresh1) { - wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Medium\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at High\n"); - } - } - } - coex_sta->pre_wifi_rssi_state[index] = wifi_rssi_state; - - return wifi_rssi_state; -} - -static void halbtc8821a1ant_update_ra_mask(struct btc_coexist *btcoexist, - bool force_exec, u32 dis_rate_mask) -{ - coex_dm->cur_ra_mask = dis_rate_mask; - - if (force_exec || - (coex_dm->pre_ra_mask != coex_dm->cur_ra_mask)) { - btcoexist->btc_set(btcoexist, BTC_SET_ACT_UPDATE_ra_mask, - &coex_dm->cur_ra_mask); - } - coex_dm->pre_ra_mask = coex_dm->cur_ra_mask; -} - -static void btc8821a1ant_auto_rate_fb_retry(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - bool wifi_under_b_mode = false; - - coex_dm->cur_arfr_type = type; - - if (force_exec || - (coex_dm->pre_arfr_type != coex_dm->cur_arfr_type)) { - switch (coex_dm->cur_arfr_type) { - case 0: /* normal mode*/ - btcoexist->btc_write_4byte(btcoexist, 0x430, - coex_dm->backup_arfr_cnt1); - btcoexist->btc_write_4byte(btcoexist, 0x434, - coex_dm->backup_arfr_cnt2); - break; - case 1: - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_UNDER_B_MODE, - &wifi_under_b_mode); - if (wifi_under_b_mode) { - btcoexist->btc_write_4byte(btcoexist, 0x430, - 0x0); - btcoexist->btc_write_4byte(btcoexist, 0x434, - 0x01010101); - } else { - btcoexist->btc_write_4byte(btcoexist, 0x430, - 0x0); - btcoexist->btc_write_4byte(btcoexist, 0x434, - 0x04030201); - } - break; - default: - break; - } - } - - coex_dm->pre_arfr_type = coex_dm->cur_arfr_type; -} - -static void halbtc8821a1ant_retry_limit(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - coex_dm->cur_retry_limit_type = type; - - if (force_exec || - (coex_dm->pre_retry_limit_type != coex_dm->cur_retry_limit_type)) { - switch (coex_dm->cur_retry_limit_type) { - case 0: /* normal mode*/ - btcoexist->btc_write_2byte(btcoexist, 0x42a, - coex_dm->backup_retry_limit); - break; - case 1: /* retry limit = 8*/ - btcoexist->btc_write_2byte(btcoexist, 0x42a, 0x0808); - break; - default: - break; - } - } - coex_dm->pre_retry_limit_type = coex_dm->cur_retry_limit_type; -} - -static void halbtc8821a1ant_ampdu_max_time(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - coex_dm->cur_ampdu_time_type = type; - - if (force_exec || - (coex_dm->pre_ampdu_time_type != coex_dm->cur_ampdu_time_type)) { - switch (coex_dm->cur_ampdu_time_type) { - case 0: /* normal mode*/ - btcoexist->btc_write_1byte(btcoexist, 0x456, - coex_dm->backup_ampdu_max_time); - break; - case 1: /* AMPDU timw = 0x38 * 32us*/ - btcoexist->btc_write_1byte(btcoexist, 0x456, 0x38); - break; - default: - break; - } - } - - coex_dm->pre_ampdu_time_type = coex_dm->cur_ampdu_time_type; -} - -static void halbtc8821a1ant_limited_tx(struct btc_coexist *btcoexist, - bool force_exec, u8 ra_mask_type, - u8 arfr_type, u8 retry_limit_type, - u8 ampdu_time_type) -{ - switch (ra_mask_type) { - case 0: /* normal mode*/ - halbtc8821a1ant_update_ra_mask(btcoexist, force_exec, 0x0); - break; - case 1: /* disable cck 1/2*/ - halbtc8821a1ant_update_ra_mask(btcoexist, force_exec, - 0x00000003); - break; - case 2: /* disable cck 1/2/5.5, ofdm 6/9/12/18/24, mcs 0/1/2/3/4*/ - halbtc8821a1ant_update_ra_mask(btcoexist, force_exec, - 0x0001f1f7); - break; - default: - break; - } - - btc8821a1ant_auto_rate_fb_retry(btcoexist, force_exec, arfr_type); - halbtc8821a1ant_retry_limit(btcoexist, force_exec, retry_limit_type); - halbtc8821a1ant_ampdu_max_time(btcoexist, force_exec, ampdu_time_type); -} - -static void halbtc8821a1ant_limited_rx(struct btc_coexist *btcoexist, - bool force_exec, bool rej_ap_agg_pkt, - bool bt_ctrl_agg_buf_size, - u8 agg_buf_size) -{ - bool reject_rx_agg = rej_ap_agg_pkt; - bool bt_ctrl_rx_agg_size = bt_ctrl_agg_buf_size; - u8 rx_agg_size = agg_buf_size; - - /*============================================*/ - /* Rx Aggregation related setting*/ - /*============================================*/ - btcoexist->btc_set(btcoexist, - BTC_SET_BL_TO_REJ_AP_AGG_PKT, &reject_rx_agg); - /* decide BT control aggregation buf size or not*/ - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_CTRL_AGG_SIZE, - &bt_ctrl_rx_agg_size); - /* aggregation buf size, only work when BT control Rx agg size.*/ - btcoexist->btc_set(btcoexist, BTC_SET_U1_AGG_BUF_SIZE, &rx_agg_size); - /* real update aggregation setting*/ - btcoexist->btc_set(btcoexist, BTC_SET_ACT_AGGREGATE_CTRL, NULL); -} - -static void halbtc8821a1ant_monitor_bt_ctr(struct btc_coexist *btcoexist) -{ - u32 reg_hp_tx_rx, reg_lp_tx_rx, u4_tmp; - u32 reg_hp_tx = 0, reg_hp_rx = 0, reg_lp_tx = 0, reg_lp_rx = 0; - - reg_hp_tx_rx = 0x770; - reg_lp_tx_rx = 0x774; - - u4_tmp = btcoexist->btc_read_4byte(btcoexist, reg_hp_tx_rx); - reg_hp_tx = u4_tmp & MASKLWORD; - reg_hp_rx = (u4_tmp & MASKHWORD)>>16; - - u4_tmp = btcoexist->btc_read_4byte(btcoexist, reg_lp_tx_rx); - reg_lp_tx = u4_tmp & MASKLWORD; - reg_lp_rx = (u4_tmp & MASKHWORD)>>16; - - coex_sta->high_priority_tx = reg_hp_tx; - coex_sta->high_priority_rx = reg_hp_rx; - coex_sta->low_priority_tx = reg_lp_tx; - coex_sta->low_priority_rx = reg_lp_rx; - - /* reset counter*/ - btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); -} - -static void halbtc8821a1ant_query_bt_info(struct btc_coexist *btcoexist) -{ - u8 h2c_parameter[1] = {0}; - - coex_sta->c2h_bt_info_req_sent = true; - - h2c_parameter[0] |= BIT0; /* trigger*/ - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", - h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); -} - -static void halbtc8821a1ant_update_bt_link_info(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool bt_hs_on = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - - bt_link_info->bt_link_exist = coex_sta->bt_link_exist; - bt_link_info->sco_exist = coex_sta->sco_exist; - bt_link_info->a2dp_exist = coex_sta->a2dp_exist; - bt_link_info->pan_exist = coex_sta->pan_exist; - bt_link_info->hid_exist = coex_sta->hid_exist; - - /* work around for HS mode.*/ - if (bt_hs_on) { - bt_link_info->pan_exist = true; - bt_link_info->bt_link_exist = true; - } - - /* check if Sco only*/ - if (bt_link_info->sco_exist && - !bt_link_info->a2dp_exist && - !bt_link_info->pan_exist && - !bt_link_info->hid_exist) - bt_link_info->sco_only = true; - else - bt_link_info->sco_only = false; - - /* check if A2dp only*/ - if (!bt_link_info->sco_exist && - bt_link_info->a2dp_exist && - !bt_link_info->pan_exist && - !bt_link_info->hid_exist) - bt_link_info->a2dp_only = true; - else - bt_link_info->a2dp_only = false; - - /* check if Pan only*/ - if (!bt_link_info->sco_exist && - !bt_link_info->a2dp_exist && - bt_link_info->pan_exist && - !bt_link_info->hid_exist) - bt_link_info->pan_only = true; - else - bt_link_info->pan_only = false; - - /* check if Hid only*/ - if (!bt_link_info->sco_exist && - !bt_link_info->a2dp_exist && - !bt_link_info->pan_exist && - bt_link_info->hid_exist) - bt_link_info->hid_only = true; - else - bt_link_info->hid_only = false; -} - -static u8 halbtc8821a1ant_action_algorithm(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool bt_hs_on = false; - u8 algorithm = BT_8821A_1ANT_COEX_ALGO_UNDEFINED; - u8 num_of_diff_profile = 0; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - - if (!bt_link_info->bt_link_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], No BT link exists!!!\n"); - return algorithm; - } - - if (bt_link_info->sco_exist) - num_of_diff_profile++; - if (bt_link_info->hid_exist) - num_of_diff_profile++; - if (bt_link_info->pan_exist) - num_of_diff_profile++; - if (bt_link_info->a2dp_exist) - num_of_diff_profile++; - - if (num_of_diff_profile == 1) { - if (bt_link_info->sco_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO only\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_SCO; - } else { - if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID only\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_HID; - } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = A2DP only\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_A2DP; - } else if (bt_link_info->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = PAN(HS) only\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_PANHS; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = PAN(EDR) only\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR; - } - } - } - } else if (num_of_diff_profile == 2) { - if (bt_link_info->sco_exist) { - if (bt_link_info->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_HID; - } else if (bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + A2DP ==> SCO\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_SCO; - } else if (bt_link_info->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + PAN(HS)\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_SCO; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + PAN(EDR)\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; - } - } - } else { - if (bt_link_info->hid_exist && - bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + A2DP\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP; - } else if (bt_link_info->hid_exist && - bt_link_info->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + PAN(HS)\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + PAN(EDR)\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; - } - } else if (bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = A2DP + PAN(HS)\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_A2DP_PANHS; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = A2DP + PAN(EDR)\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_A2DP; - } - } - } - } else if (num_of_diff_profile == 3) { - if (bt_link_info->sco_exist) { - if (bt_link_info->hid_exist && - bt_link_info->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + A2DP ==> HID\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_HID; - } else if (bt_link_info->hid_exist && - bt_link_info->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + PAN(HS)\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + PAN(EDR)\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; - } - } else if (bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + A2DP + PAN(HS)\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_SCO; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + A2DP + PAN(EDR) ==> HID\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; - } - } - } else { - if (bt_link_info->hid_exist && - bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + A2DP + PAN(HS)\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = HID + A2DP + PAN(EDR)\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_HID_A2DP_PANEDR; - } - } - } - } else if (num_of_diff_profile >= 3) { - if (bt_link_info->sco_exist) { - if (bt_link_info->hid_exist && - bt_link_info->pan_exist && - bt_link_info->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Error!!! BT Profile = SCO + HID + A2DP + PAN(HS)\n"); - - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT Profile = SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); - algorithm = BT_8821A_1ANT_COEX_ALGO_PANEDR_HID; - } - } - } - } - return algorithm; -} - -static void halbtc8821a1ant_set_bt_auto_report(struct btc_coexist *btcoexist, - bool enable_auto_report) -{ - u8 h2c_parameter[1] = {0}; - - h2c_parameter[0] = 0; - - if (enable_auto_report) - h2c_parameter[0] |= BIT0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], BT FW auto report : %s, FW write 0x68 = 0x%x\n", - (enable_auto_report ? "Enabled!!" : "Disabled!!"), - h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter); -} - -static void halbtc8821a1ant_bt_auto_report(struct btc_coexist *btcoexist, - bool force_exec, - bool enable_auto_report) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW, "[BTCoex], %s BT Auto report = %s\n", - (force_exec ? "force to" : ""), ((enable_auto_report) ? - "Enabled" : "Disabled")); - coex_dm->cur_bt_auto_report = enable_auto_report; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_bt_auto_report = %d, cur_bt_auto_report = %d\n", - coex_dm->pre_bt_auto_report, - coex_dm->cur_bt_auto_report); - - if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report) - return; - } - halbtc8821a1ant_set_bt_auto_report(btcoexist, coex_dm->cur_bt_auto_report); - - coex_dm->pre_bt_auto_report = coex_dm->cur_bt_auto_report; -} - -static void btc8821a1ant_set_sw_pen_tx_rate(struct btc_coexist *btcoexist, - bool low_penalty_ra) -{ - u8 h2c_parameter[6] = {0}; - - h2c_parameter[0] = 0x6; /* opCode, 0x6= Retry_Penalty*/ - - if (low_penalty_ra) { - h2c_parameter[1] |= BIT0; - /*normal rate except MCS7/6/5, OFDM54/48/36*/ - h2c_parameter[2] = 0x00; - h2c_parameter[3] = 0xf7; /*MCS7 or OFDM54*/ - h2c_parameter[4] = 0xf8; /*MCS6 or OFDM48*/ - h2c_parameter[5] = 0xf9; /*MCS5 or OFDM36*/ - } - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set WiFi Low-Penalty Retry: %s", - (low_penalty_ra ? "ON!!" : "OFF!!")); - - btcoexist->btc_fill_h2c(btcoexist, 0x69, 6, h2c_parameter); -} - -static void halbtc8821a1ant_low_penalty_ra(struct btc_coexist *btcoexist, - bool force_exec, bool low_penalty_ra) -{ - coex_dm->cur_low_penalty_ra = low_penalty_ra; - - if (!force_exec) { - if (coex_dm->pre_low_penalty_ra == coex_dm->cur_low_penalty_ra) - return; - } - btc8821a1ant_set_sw_pen_tx_rate(btcoexist, coex_dm->cur_low_penalty_ra); - - coex_dm->pre_low_penalty_ra = coex_dm->cur_low_penalty_ra; -} - -static void halbtc8821a1ant_set_coex_table(struct btc_coexist *btcoexist, - u32 val0x6c0, u32 val0x6c4, - u32 val0x6c8, u8 val0x6cc) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); - btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); - btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); - btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); - btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); -} - -static void halbtc8821a1ant_coex_table(struct btc_coexist *btcoexist, - bool force_exec, u32 val0x6c0, - u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", - (force_exec ? "force to" : ""), val0x6c0, val0x6c4, - val0x6c8, val0x6cc); - coex_dm->cur_val_0x6c0 = val0x6c0; - coex_dm->cur_val_0x6c4 = val0x6c4; - coex_dm->cur_val_0x6c8 = val0x6c8; - coex_dm->cur_val_0x6cc = val0x6cc; - - if (!force_exec) { - if ((coex_dm->pre_val_0x6c0 == coex_dm->cur_val_0x6c0) && - (coex_dm->pre_val_0x6c4 == coex_dm->cur_val_0x6c4) && - (coex_dm->pre_val_0x6c8 == coex_dm->cur_val_0x6c8) && - (coex_dm->pre_val_0x6cc == coex_dm->cur_val_0x6cc)) - return; - } - halbtc8821a1ant_set_coex_table(btcoexist, val0x6c0, val0x6c4, - val0x6c8, val0x6cc); - - coex_dm->pre_val_0x6c0 = coex_dm->cur_val_0x6c0; - coex_dm->pre_val_0x6c4 = coex_dm->cur_val_0x6c4; - coex_dm->pre_val_0x6c8 = coex_dm->cur_val_0x6c8; - coex_dm->pre_val_0x6cc = coex_dm->cur_val_0x6cc; -} - -static void halbtc8821a1ant_coex_table_with_type(struct btc_coexist *btcoexist, - bool force_exec, u8 type) -{ - switch (type) { - case 0: - halbtc8821a1ant_coex_table(btcoexist, force_exec, 0x55555555, - 0x55555555, 0xffffff, 0x3); - break; - case 1: - halbtc8821a1ant_coex_table(btcoexist, force_exec, - 0x55555555, 0x5a5a5a5a, - 0xffffff, 0x3); - break; - case 2: - halbtc8821a1ant_coex_table(btcoexist, force_exec, 0x5a5a5a5a, - 0x5a5a5a5a, 0xffffff, 0x3); - break; - case 3: - halbtc8821a1ant_coex_table(btcoexist, force_exec, 0x55555555, - 0xaaaaaaaa, 0xffffff, 0x3); - break; - case 4: - halbtc8821a1ant_coex_table(btcoexist, force_exec, 0xffffffff, - 0xffffffff, 0xffffff, 0x3); - break; - case 5: - halbtc8821a1ant_coex_table(btcoexist, force_exec, 0x5fff5fff, - 0x5fff5fff, 0xffffff, 0x3); - break; - case 6: - halbtc8821a1ant_coex_table(btcoexist, force_exec, 0x55ff55ff, - 0x5a5a5a5a, 0xffffff, 0x3); - break; - case 7: - halbtc8821a1ant_coex_table(btcoexist, force_exec, 0x5afa5afa, - 0x5afa5afa, 0xffffff, 0x3); - break; - default: - break; - } -} - -static void btc8821a1ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoexist, - bool enable) -{ - u8 h2c_parameter[1] = {0}; - - if (enable) - h2c_parameter[0] |= BIT0; /* function enable*/ - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", - h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x63, 1, h2c_parameter); -} - -static void halbtc8821a1ant_ignore_wlan_act(struct btc_coexist *btcoexist, - bool force_exec, bool enable) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn Ignore WlanAct %s\n", - (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); - coex_dm->cur_ignore_wlan_act = enable; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_ignore_wlan_act = %d, cur_ignore_wlan_act = %d!!\n", - coex_dm->pre_ignore_wlan_act, - coex_dm->cur_ignore_wlan_act); - - if (coex_dm->pre_ignore_wlan_act == - coex_dm->cur_ignore_wlan_act) - return; - } - btc8821a1ant_set_fw_ignore_wlan_act(btcoexist, enable); - - coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; -} - -static void halbtc8821a1ant_set_fw_pstdma(struct btc_coexist *btcoexist, - u8 byte1, u8 byte2, u8 byte3, - u8 byte4, u8 byte5) -{ - u8 h2c_parameter[5] = {0}; - - h2c_parameter[0] = byte1; - h2c_parameter[1] = byte2; - h2c_parameter[2] = byte3; - h2c_parameter[3] = byte4; - h2c_parameter[4] = byte5; - - coex_dm->ps_tdma_para[0] = byte1; - coex_dm->ps_tdma_para[1] = byte2; - coex_dm->ps_tdma_para[2] = byte3; - coex_dm->ps_tdma_para[3] = byte4; - coex_dm->ps_tdma_para[4] = byte5; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], PS-TDMA H2C cmd =0x%x%08x\n", - h2c_parameter[0], - h2c_parameter[1]<<24 | - h2c_parameter[2]<<16 | - h2c_parameter[3]<<8 | - h2c_parameter[4]); - btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); -} - -static void halbtc8821a1ant_set_lps_rpwm(struct btc_coexist *btcoexist, - u8 lps_val, u8 rpwm_val) -{ - u8 lps = lps_val; - u8 rpwm = rpwm_val; - - btcoexist->btc_set(btcoexist, BTC_SET_U1_LPS_VAL, &lps); - btcoexist->btc_set(btcoexist, BTC_SET_U1_RPWM_VAL, &rpwm); -} - -static void halbtc8821a1ant_lps_rpwm(struct btc_coexist *btcoexist, - bool force_exec, u8 lps_val, u8 rpwm_val) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s set lps/rpwm = 0x%x/0x%x\n", - (force_exec ? "force to" : ""), lps_val, rpwm_val); - coex_dm->cur_lps = lps_val; - coex_dm->cur_rpwm = rpwm_val; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], LPS-RxBeaconMode = 0x%x, LPS-RPWM = 0x%x!!\n", - coex_dm->cur_lps, coex_dm->cur_rpwm); - - if ((coex_dm->pre_lps == coex_dm->cur_lps) && - (coex_dm->pre_rpwm == coex_dm->cur_rpwm)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], LPS-RPWM_Last = 0x%x, LPS-RPWM_Now = 0x%x!!\n", - coex_dm->pre_rpwm, coex_dm->cur_rpwm); - - return; - } - } - halbtc8821a1ant_set_lps_rpwm(btcoexist, lps_val, rpwm_val); - - coex_dm->pre_lps = coex_dm->cur_lps; - coex_dm->pre_rpwm = coex_dm->cur_rpwm; -} - -static void halbtc8821a1ant_sw_mechanism(struct btc_coexist *btcoexist, - bool low_penalty_ra) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], SM[LpRA] = %d\n", low_penalty_ra); - - halbtc8821a1ant_low_penalty_ra(btcoexist, NORMAL_EXEC, low_penalty_ra); -} - -static void halbtc8821a1ant_set_ant_path(struct btc_coexist *btcoexist, - u8 ant_pos_type, bool init_hw_cfg, - bool wifi_off) -{ - struct btc_board_info *board_info = &btcoexist->board_info; - u32 u4_tmp = 0; - u8 h2c_parameter[2] = {0}; - - if (init_hw_cfg) { - /* 0x4c[23] = 0, 0x4c[24] = 1 Antenna control by WL/BT*/ - u4_tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); - u4_tmp &= ~BIT23; - u4_tmp |= BIT24; - btcoexist->btc_write_4byte(btcoexist, 0x4c, u4_tmp); - - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x975, 0x3, 0x3); - btcoexist->btc_write_1byte(btcoexist, 0xcb4, 0x77); - - if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) { - /*tell firmware "antenna inverse" ==> - * WRONG firmware antenna control code.==>need fw to fix - */ - h2c_parameter[0] = 1; - h2c_parameter[1] = 1; - btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, - h2c_parameter); - /*Main Ant to BT for IPS case 0x4c[23] = 1*/ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x64, - 0x1, 0x1); - } else { - /*tell firmware "no antenna inverse" ==> - * WRONG firmware antenna control code.==>need fw to fix - */ - h2c_parameter[0] = 0; - h2c_parameter[1] = 1; - btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, - h2c_parameter); - /*Aux Ant to BT for IPS case 0x4c[23] = 1*/ - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x64, - 0x1, 0x0); - } - } else if (wifi_off) { - /* 0x4c[24:23] = 00, Set Antenna control - * by BT_RFE_CTRL BT Vendor 0xac = 0xf002 - */ - u4_tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); - u4_tmp &= ~BIT23; - u4_tmp &= ~BIT24; - btcoexist->btc_write_4byte(btcoexist, 0x4c, u4_tmp); - } - - /* ext switch setting*/ - switch (ant_pos_type) { - case BTC_ANT_PATH_WIFI: - if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) - btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, - 0x30, 0x1); - else - btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, - 0x30, 0x2); - break; - case BTC_ANT_PATH_BT: - if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) - btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, - 0x30, 0x2); - else - btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, - 0x30, 0x1); - break; - default: - case BTC_ANT_PATH_PTA: - if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) - btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, - 0x30, 0x1); - else - btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, - 0x30, 0x2); - break; - } -} - -static void halbtc8821a1ant_ps_tdma(struct btc_coexist *btcoexist, - bool force_exec, bool turn_on, u8 type) -{ - u8 rssi_adjust_val = 0; - - coex_dm->cur_ps_tdma_on = turn_on; - coex_dm->cur_ps_tdma = type; - - if (!force_exec) { - if (coex_dm->cur_ps_tdma_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], ********** TDMA(on, %d) **********\n", - coex_dm->cur_ps_tdma); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], ********** TDMA(off, %d) **********\n", - coex_dm->cur_ps_tdma); - } - if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && - (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) - return; - } - if (turn_on) { - switch (type) { - default: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x1a, - 0x1a, 0x0, 0x50); - break; - case 1: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x3a, - 0x03, 0x10, 0x50); - rssi_adjust_val = 11; - break; - case 2: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x2b, - 0x03, 0x10, 0x50); - rssi_adjust_val = 14; - break; - case 3: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x1d, - 0x1d, 0x0, 0x10); - break; - case 4: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x93, 0x15, - 0x3, 0x14, 0x0); - rssi_adjust_val = 17; - break; - case 5: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x61, 0x15, - 0x3, 0x11, 0x10); - break; - case 6: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x13, 0xa, - 0x3, 0x0, 0x0); - break; - case 7: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x13, 0xc, - 0x5, 0x0, 0x0); - break; - case 8: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x93, 0x25, - 0x3, 0x10, 0x0); - break; - case 9: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x21, - 0x3, 0x10, 0x50); - rssi_adjust_val = 18; - break; - case 10: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x13, 0xa, - 0xa, 0x0, 0x40); - break; - case 11: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x14, - 0x03, 0x10, 0x10); - rssi_adjust_val = 20; - break; - case 12: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x0a, - 0x0a, 0x0, 0x50); - break; - case 13: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x18, - 0x18, 0x0, 0x10); - break; - case 14: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x21, - 0x3, 0x10, 0x10); - break; - case 15: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x13, 0xa, - 0x3, 0x8, 0x0); - break; - case 16: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x93, 0x15, - 0x3, 0x10, 0x0); - rssi_adjust_val = 18; - break; - case 18: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x93, 0x25, - 0x3, 0x10, 0x0); - rssi_adjust_val = 14; - break; - case 20: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x61, 0x35, - 0x03, 0x11, 0x10); - break; - case 21: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x61, 0x15, - 0x03, 0x11, 0x10); - break; - case 22: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x61, 0x25, - 0x03, 0x11, 0x10); - break; - case 23: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xe3, 0x25, - 0x3, 0x31, 0x18); - rssi_adjust_val = 22; - break; - case 24: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xe3, 0x15, - 0x3, 0x31, 0x18); - rssi_adjust_val = 22; - break; - case 25: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xe3, 0xa, - 0x3, 0x31, 0x18); - rssi_adjust_val = 22; - break; - case 26: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xe3, 0xa, - 0x3, 0x31, 0x18); - rssi_adjust_val = 22; - break; - case 27: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xe3, 0x25, - 0x3, 0x31, 0x98); - rssi_adjust_val = 22; - break; - case 28: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x69, 0x25, - 0x3, 0x31, 0x0); - break; - case 29: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xab, 0x1a, - 0x1a, 0x1, 0x10); - break; - case 30: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x51, 0x14, - 0x3, 0x10, 0x50); - break; - case 31: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xd3, 0x1a, - 0x1a, 0, 0x58); - break; - case 32: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x61, 0xa, - 0x3, 0x10, 0x0); - break; - case 33: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xa3, 0x25, - 0x3, 0x30, 0x90); - break; - case 34: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x53, 0x1a, - 0x1a, 0x0, 0x10); - break; - case 35: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x63, 0x1a, - 0x1a, 0x0, 0x10); - break; - case 36: - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0xd3, 0x12, - 0x3, 0x14, 0x50); - break; - } - } else { - /* disable PS tdma*/ - switch (type) { - case 8: /*PTA Control*/ - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x8, 0x0, 0x0, - 0x0, 0x0); - halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA, - false, false); - break; - case 0: - default: /*Software control, Antenna at BT side*/ - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x0, 0x0, 0x0, - 0x0, 0x0); - halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, - false, false); - break; - case 9: /*Software control, Antenna at WiFi side*/ - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x0, 0x0, 0x0, - 0x0, 0x0); - halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_WIFI, - false, false); - break; - case 10: /* under 5G*/ - halbtc8821a1ant_set_fw_pstdma(btcoexist, 0x0, 0x0, 0x0, - 0x8, 0x0); - halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, - false, false); - break; - } - } - rssi_adjust_val = 0; - btcoexist->btc_set(btcoexist, - BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE, &rssi_adjust_val); - - /* update pre state*/ - coex_dm->pre_ps_tdma_on = coex_dm->cur_ps_tdma_on; - coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; -} - -static bool halbtc8821a1ant_is_common_action(struct btc_coexist *btcoexist) -{ - bool common = false, wifi_connected = false, wifi_busy = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - - if (!wifi_connected && - BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE == - coex_dm->bt_status) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non connected-idle + BT non connected-idle!!\n"); - halbtc8821a1ant_sw_mechanism(btcoexist, false); - - common = true; - } else if (wifi_connected && - (BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE == - coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi connected + BT non connected-idle!!\n"); - halbtc8821a1ant_sw_mechanism(btcoexist, false); - - common = true; - } else if (!wifi_connected && - (BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE == - coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non connected-idle + BT connected-idle!!\n"); - halbtc8821a1ant_sw_mechanism(btcoexist, false); - - common = true; - } else if (wifi_connected && - (BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE == - coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi connected + BT connected-idle!!\n"); - halbtc8821a1ant_sw_mechanism(btcoexist, false); - - common = true; - } else if (!wifi_connected && - (BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE != - coex_dm->bt_status)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi non connected-idle + BT Busy!!\n"); - halbtc8821a1ant_sw_mechanism(btcoexist, false); - - common = true; - } else { - if (wifi_busy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Connected-Busy + BT Busy!!\n"); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Connected-Idle + BT Busy!!\n"); - } - - common = false; - } - - return common; -} - -static void btc8821a1ant_tdma_dur_adj(struct btc_coexist *btcoexist, - u8 wifi_status) -{ - static long up, dn, m, n, wait_count; - /*0: no change, +1: increase WiFi duration, -1: decrease WiFi duration*/ - long result; - u8 retry_count = 0, bt_info_ext; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], TdmaDurationAdjustForAcl()\n"); - - if ((BT_8821A_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN == - wifi_status) || - (BT_8821A_1ANT_WIFI_STATUS_CONNECTED_SCAN == - wifi_status) || - (BT_8821A_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT == - wifi_status)) { - if (coex_dm->cur_ps_tdma != 1 && - coex_dm->cur_ps_tdma != 2 && - coex_dm->cur_ps_tdma != 3 && - coex_dm->cur_ps_tdma != 9) { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - - up = 0; - dn = 0; - m = 1; - n = 3; - result = 0; - wait_count = 0; - } - return; - } - - if (!coex_dm->auto_tdma_adjust) { - coex_dm->auto_tdma_adjust = true; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], first run TdmaDurationAdjust()!!\n"); - - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 2); - coex_dm->tdma_adj_type = 2; - /*============*/ - up = 0; - dn = 0; - m = 1; - n = 3; - result = 0; - wait_count = 0; - } else { - /*accquire the BT TRx retry count from BT_Info byte2*/ - retry_count = coex_sta->bt_retry_cnt; - bt_info_ext = coex_sta->bt_info_ext; - result = 0; - wait_count++; - - if (retry_count == 0) { - /* no retry in the last 2-second duration*/ - up++; - dn--; - - if (dn <= 0) - dn = 0; - - if (up >= n) { - /* if (retry count == 0) for 2*n seconds , - * make WiFi duration wider - */ - wait_count = 0; - n = 3; - up = 0; - dn = 0; - result = 1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Increase wifi duration!!\n"); - } - } else if (retry_count <= 3) { - /* <=3 retry in the last 2-second duration*/ - up--; - dn++; - - if (up <= 0) - up = 0; - - if (dn == 2) { - /* if retry count< 3 for 2*2 seconds, - * shrink wifi duration - */ - if (wait_count <= 2) - m++; /* avoid bounce in two levels */ - else - m = 1; - - if (m >= 20) { - /* m max value is 20, max time is 120 s, - * recheck if adjust WiFi duration. - */ - m = 20; - } - n = 3*m; - up = 0; - dn = 0; - wait_count = 0; - result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration for retryCounter<3!!\n"); - } - } else { - /* retry count > 3, if retry count > 3 happens once, - * shrink WiFi duration - */ - if (wait_count == 1) - m++; /* avoid bounce in two levels */ - else - m = 1; - /* m max value is 20, max time is 120 second, - * recheck if adjust WiFi duration. - */ - if (m >= 20) - m = 20; - - n = 3*m; - up = 0; - dn = 0; - wait_count = 0; - result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration for retryCounter>3!!\n"); - } - - if (result == -1) { - if ((BT_INFO_8821A_1ANT_A2DP_BASIC_RATE(bt_info_ext)) && - ((coex_dm->cur_ps_tdma == 1) || - (coex_dm->cur_ps_tdma == 2))) { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (coex_dm->cur_ps_tdma == 1) { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (coex_dm->cur_ps_tdma == 9) { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } - } else if (result == 1) { - if ((BT_INFO_8821A_1ANT_A2DP_BASIC_RATE(bt_info_ext)) && - ((coex_dm->cur_ps_tdma == 1) || - (coex_dm->cur_ps_tdma == 2))) { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (coex_dm->cur_ps_tdma == 9) { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 1); - coex_dm->tdma_adj_type = 1; - } - } else { - /*no change*/ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], ********** TDMA(on, %d) **********\n", - coex_dm->cur_ps_tdma); - } - - if (coex_dm->cur_ps_tdma != 1 && - coex_dm->cur_ps_tdma != 2 && - coex_dm->cur_ps_tdma != 9 && - coex_dm->cur_ps_tdma != 11) { - /* recover to previous adjust type*/ - halbtc8821a1ant_ps_tdma(btcoexist, - NORMAL_EXEC, true, - coex_dm->tdma_adj_type); - } - } -} - -static void btc8821a1ant_ps_tdma_check_for_pwr_save(struct btc_coexist *btcoex, - bool new_ps_state) -{ - u8 lps_mode = 0x0; - - btcoex->btc_get(btcoex, BTC_GET_U1_LPS_MODE, &lps_mode); - - if (lps_mode) { - /* already under LPS state*/ - if (new_ps_state) { - /* keep state under LPS, do nothing.*/ - } else { - /* will leave LPS state, turn off psTdma first*/ - halbtc8821a1ant_ps_tdma(btcoex, NORMAL_EXEC, false, 0); - } - } else { - /* NO PS state*/ - if (new_ps_state) { - /* will enter LPS state, turn off psTdma first*/ - halbtc8821a1ant_ps_tdma(btcoex, NORMAL_EXEC, false, 0); - } else { - /* keep state under NO PS state, do nothing.*/ - } - } -} - -static void halbtc8821a1ant_power_save_state(struct btc_coexist *btcoexist, - u8 ps_type, u8 lps_val, - u8 rpwm_val) -{ - bool low_pwr_disable = false; - - switch (ps_type) { - case BTC_PS_WIFI_NATIVE: - /* recover to original 32k low power setting*/ - low_pwr_disable = false; - btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - btcoexist->btc_set(btcoexist, BTC_SET_ACT_NORMAL_LPS, NULL); - break; - case BTC_PS_LPS_ON: - btc8821a1ant_ps_tdma_check_for_pwr_save(btcoexist, - true); - halbtc8821a1ant_lps_rpwm(btcoexist, - NORMAL_EXEC, lps_val, rpwm_val); - /* when coex force to enter LPS, do not enter 32k low power.*/ - low_pwr_disable = true; - btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - /* power save must executed before psTdma.*/ - btcoexist->btc_set(btcoexist, BTC_SET_ACT_ENTER_LPS, NULL); - break; - case BTC_PS_LPS_OFF: - btc8821a1ant_ps_tdma_check_for_pwr_save(btcoexist, false); - btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS, NULL); - break; - default: - break; - } -} - -static void halbtc8821a1ant_coex_under_5g(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - halbtc8821a1ant_ignore_wlan_act(btcoexist, NORMAL_EXEC, true); - - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 10); - - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0); - - halbtc8821a1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); - - halbtc8821a1ant_limited_rx(btcoexist, NORMAL_EXEC, false, false, 5); -} - -static void halbtc8821a1ant_action_wifi_only(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0); - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 9); -} - -static void btc8821a1ant_mon_bt_en_dis(struct btc_coexist *btcoexist) -{ - static bool pre_bt_disabled; - static u32 bt_disable_cnt; - bool bt_active = true, bt_disabled = false; - - /* This function check if bt is disabled*/ - - if (coex_sta->high_priority_tx == 0 && - coex_sta->high_priority_rx == 0 && - coex_sta->low_priority_tx == 0 && - coex_sta->low_priority_rx == 0) { - bt_active = false; - } - if (coex_sta->high_priority_tx == 0xffff && - coex_sta->high_priority_rx == 0xffff && - coex_sta->low_priority_tx == 0xffff && - coex_sta->low_priority_rx == 0xffff) { - bt_active = false; - } - if (bt_active) { - bt_disable_cnt = 0; - bt_disabled = false; - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, - &bt_disabled); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is enabled !!\n"); - } else { - bt_disable_cnt++; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], bt all counters = 0, %d times!!\n", - bt_disable_cnt); - if (bt_disable_cnt >= 2) { - bt_disabled = true; - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, - &bt_disabled); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is disabled !!\n"); - halbtc8821a1ant_action_wifi_only(btcoexist); - } - } - if (pre_bt_disabled != bt_disabled) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is from %s to %s!!\n", - (pre_bt_disabled ? "disabled" : "enabled"), - (bt_disabled ? "disabled" : "enabled")); - pre_bt_disabled = bt_disabled; - if (bt_disabled) { - btcoexist->btc_set(btcoexist, BTC_SET_ACT_LEAVE_LPS, - NULL); - btcoexist->btc_set(btcoexist, BTC_SET_ACT_NORMAL_LPS, - NULL); - } - } -} - -/*=============================================*/ -/**/ -/* Software Coex Mechanism start*/ -/**/ -/*=============================================*/ - -/* SCO only or SCO+PAN(HS)*/ -static void halbtc8821a1ant_action_sco(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_sw_mechanism(btcoexist, true); -} - -static void halbtc8821a1ant_action_hid(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_sw_mechanism(btcoexist, true); -} - -/*A2DP only / PAN(EDR) only/ A2DP+PAN(HS)*/ -static void halbtc8821a1ant_action_a2dp(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_sw_mechanism(btcoexist, false); -} - -static void halbtc8821a1ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_sw_mechanism(btcoexist, false); -} - -static void halbtc8821a1ant_action_pan_edr(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_sw_mechanism(btcoexist, false); -} - -/*PAN(HS) only*/ -static void halbtc8821a1ant_action_pan_hs(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_sw_mechanism(btcoexist, false); -} - -/*PAN(EDR)+A2DP*/ -static void halbtc8821a1ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_sw_mechanism(btcoexist, false); -} - -static void halbtc8821a1ant_action_pan_edr_hid(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_sw_mechanism(btcoexist, true); -} - -/* HID+A2DP+PAN(EDR)*/ -static void btc8821a1ant_action_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_sw_mechanism(btcoexist, true); -} - -static void halbtc8821a1ant_action_hid_a2dp(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_sw_mechanism(btcoexist, true); -} - -/*=============================================*/ -/**/ -/* Non-Software Coex Mechanism start*/ -/**/ -/*=============================================*/ - -static void halbtc8821a1ant_action_hs(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); - halbtc8821a1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 2); -} - -static void halbtc8821a1ant_action_bt_inquiry(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool wifi_connected = false; - - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); - - if (!wifi_connected) { - halbtc8821a1ant_power_save_state(btcoexist, - BTC_PS_WIFI_NATIVE, 0x0, 0x0); - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - } else if ((bt_link_info->sco_exist) || - (bt_link_info->hid_only)) { - /* SCO/HID-only busy*/ - halbtc8821a1ant_power_save_state(btcoexist, - BTC_PS_WIFI_NATIVE, 0x0, 0x0); - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 32); - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - } else { - halbtc8821a1ant_power_save_state(btcoexist, BTC_PS_LPS_ON, - 0x50, 0x4); - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 30); - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - } -} - -static void btc8821a1ant_act_bt_sco_hid_only_busy(struct btc_coexist *btcoexist, - u8 wifi_status) { - /* tdma and coex table*/ - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); - - if (BT_8821A_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN == - wifi_status) - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - else - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); -} - -static void btc8821a1ant_act_wifi_con_bt_acl_busy(struct btc_coexist *btcoexist, - u8 wifi_status) -{ - u8 bt_rssi_state; - - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - - bt_rssi_state = halbtc8821a1ant_bt_rssi_state(2, 28, 0); - - if (bt_link_info->hid_only) { - /*HID*/ - btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist, - wifi_status); - coex_dm->auto_tdma_adjust = false; - return; - } else if (bt_link_info->a2dp_only) { - /*A2DP*/ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a1ant_tdma_dur_adj(btcoexist, wifi_status); - } else { - /*for low BT RSSI*/ - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->auto_tdma_adjust = false; - } - - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - } else if (bt_link_info->hid_exist && bt_link_info->a2dp_exist) { - /*HID+A2DP*/ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->auto_tdma_adjust = false; - } else { - /*for low BT RSSI*/ - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->auto_tdma_adjust = false; - } - - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - } else if ((bt_link_info->pan_only) || - (bt_link_info->hid_exist && bt_link_info->pan_exist)) { - /*PAN(OPP, FTP), HID+PAN(OPP, FTP)*/ - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - coex_dm->auto_tdma_adjust = false; - } else if (((bt_link_info->a2dp_exist) && (bt_link_info->pan_exist)) || - (bt_link_info->hid_exist && bt_link_info->a2dp_exist && - bt_link_info->pan_exist)) { - /*A2DP+PAN(OPP, FTP), HID+A2DP+PAN(OPP, FTP)*/ - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 13); - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - coex_dm->auto_tdma_adjust = false; - } else { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 11); - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - coex_dm->auto_tdma_adjust = false; - } -} - -static void halbtc8821a1ant_action_wifi_not_connected( - struct btc_coexist *btcoexist) -{ - /* power save state*/ - halbtc8821a1ant_power_save_state(btcoexist, - BTC_PS_WIFI_NATIVE, 0x0, 0x0); - - /* tdma and coex table*/ - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 0); -} - -static void btc8821a1ant_act_wifi_not_conn_scan(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_power_save_state(btcoexist, - BTC_PS_WIFI_NATIVE, 0x0, 0x0); - - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 22); - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); -} - -static void halbtc8821a1ant_action_wifi_connected_scan( - struct btc_coexist *btcoexist) { - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - - /* power save state*/ - halbtc8821a1ant_power_save_state(btcoexist, - BTC_PS_WIFI_NATIVE, 0x0, 0x0); - - /* tdma and coex table*/ - if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { - if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 22); - halbtc8821a1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 1); - } else { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20); - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - } - } else if ((BT_8821A_1ANT_BT_STATUS_SCO_BUSY == - coex_dm->bt_status) || - (BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY == - coex_dm->bt_status)) { - btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist, - BT_8821A_1ANT_WIFI_STATUS_CONNECTED_SCAN); - } else { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20); - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - } -} - -static void btc8821a1ant_act_wifi_conn_sp_pkt(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool hs_connecting = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_CONNECTING, &hs_connecting); - - halbtc8821a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - - /* tdma and coex table*/ - if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { - if (bt_link_info->a2dp_exist && bt_link_info->pan_exist) { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 22); - halbtc8821a1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 1); - } else { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 20); - halbtc8821a1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 1); - } - } else { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 20); - halbtc8821a1ant_coex_table_with_type(btcoexist, NORMAL_EXEC, 1); - } -} - -static void halbtc8821a1ant_action_wifi_connected(struct btc_coexist *btcoexist) -{ - bool wifi_busy = false; - bool scan = false, link = false, roam = false; - bool under_4way = false; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], CoexForWifiConnect()===>\n"); - - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_4_WAY_PROGRESS, &under_4way); - if (under_4way) { - btc8821a1ant_act_wifi_conn_sp_pkt(btcoexist); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], CoexForWifiConnect(), return for wifi is under 4way<===\n"); - return; - } - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); - if (scan || link || roam) { - halbtc8821a1ant_action_wifi_connected_scan(btcoexist); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], CoexForWifiConnect(), return for wifi is under scan<===\n"); - return; - } - - /* power save state*/ - if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == - coex_dm->bt_status && !btcoexist->bt_link_info.hid_only) - halbtc8821a1ant_power_save_state(btcoexist, - BTC_PS_LPS_ON, 0x50, 0x4); - else - halbtc8821a1ant_power_save_state(btcoexist, - BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - - /* tdma and coex table*/ - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - if (!wifi_busy) { - if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { - btc8821a1ant_act_wifi_con_bt_acl_busy(btcoexist, - BT_8821A_1ANT_WIFI_STATUS_CONNECTED_IDLE); - } else if ((BT_8821A_1ANT_BT_STATUS_SCO_BUSY == - coex_dm->bt_status) || - (BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY == - coex_dm->bt_status)) { - btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist, - BT_8821A_1ANT_WIFI_STATUS_CONNECTED_IDLE); - } else { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - halbtc8821a1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 2); - } - } else { - if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) { - btc8821a1ant_act_wifi_con_bt_acl_busy(btcoexist, - BT_8821A_1ANT_WIFI_STATUS_CONNECTED_BUSY); - } else if ((BT_8821A_1ANT_BT_STATUS_SCO_BUSY == - coex_dm->bt_status) || - (BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY == - coex_dm->bt_status)) { - btc8821a1ant_act_bt_sco_hid_only_busy(btcoexist, - BT_8821A_1ANT_WIFI_STATUS_CONNECTED_BUSY); - } else { - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - halbtc8821a1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 2); - } - } -} - -static void btc8821a1ant_run_sw_coex_mech(struct btc_coexist *btcoexist) -{ - u8 algorithm = 0; - - algorithm = halbtc8821a1ant_action_algorithm(btcoexist); - coex_dm->cur_algorithm = algorithm; - - if (!halbtc8821a1ant_is_common_action(btcoexist)) { - switch (coex_dm->cur_algorithm) { - case BT_8821A_1ANT_COEX_ALGO_SCO: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = SCO.\n"); - halbtc8821a1ant_action_sco(btcoexist); - break; - case BT_8821A_1ANT_COEX_ALGO_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HID.\n"); - halbtc8821a1ant_action_hid(btcoexist); - break; - case BT_8821A_1ANT_COEX_ALGO_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = A2DP.\n"); - halbtc8821a1ant_action_a2dp(btcoexist); - break; - case BT_8821A_1ANT_COEX_ALGO_A2DP_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = A2DP+PAN(HS).\n"); - halbtc8821a1ant_action_a2dp_pan_hs(btcoexist); - break; - case BT_8821A_1ANT_COEX_ALGO_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = PAN(EDR).\n"); - halbtc8821a1ant_action_pan_edr(btcoexist); - break; - case BT_8821A_1ANT_COEX_ALGO_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HS mode.\n"); - halbtc8821a1ant_action_pan_hs(btcoexist); - break; - case BT_8821A_1ANT_COEX_ALGO_PANEDR_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = PAN+A2DP.\n"); - halbtc8821a1ant_action_pan_edr_a2dp(btcoexist); - break; - case BT_8821A_1ANT_COEX_ALGO_PANEDR_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = PAN(EDR)+HID.\n"); - halbtc8821a1ant_action_pan_edr_hid(btcoexist); - break; - case BT_8821A_1ANT_COEX_ALGO_HID_A2DP_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HID+A2DP+PAN.\n"); - btc8821a1ant_action_hid_a2dp_pan_edr(btcoexist); - break; - case BT_8821A_1ANT_COEX_ALGO_HID_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = HID+A2DP.\n"); - halbtc8821a1ant_action_hid_a2dp(btcoexist); - break; - default: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action algorithm = coexist All Off!!\n"); - /*halbtc8821a1ant_coex_all_off(btcoexist);*/ - break; - } - coex_dm->pre_algorithm = coex_dm->cur_algorithm; - } -} - -static void halbtc8821a1ant_run_coexist_mechanism(struct btc_coexist *btcoexist) -{ - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - bool wifi_connected = false, bt_hs_on = false; - bool increase_scan_dev_num = false; - bool bt_ctrl_agg_buf_size = false; - u8 agg_buf_size = 5; - u8 wifi_rssi_state = BTC_RSSI_STATE_HIGH; - bool wifi_under_5g = false; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism()===>\n"); - - if (btcoexist->manual_control) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), return for Manual CTRL <===\n"); - return; - } - - if (btcoexist->stop_coex_dm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), return for Stop Coex DM <===\n"); - return; - } - - if (coex_sta->under_ips) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], wifi is under IPS !!!\n"); - return; - } - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); - if (wifi_under_5g) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), return for 5G <===\n"); - halbtc8821a1ant_coex_under_5g(btcoexist); - return; - } - - if ((BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || - (BT_8821A_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || - (BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) - increase_scan_dev_num = true; - - btcoexist->btc_set(btcoexist, BTC_SET_BL_INC_SCAN_DEV_NUM, - &increase_scan_dev_num); - - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); - - if (!bt_link_info->sco_exist && !bt_link_info->hid_exist) { - halbtc8821a1ant_limited_tx(btcoexist, NORMAL_EXEC, 0, 0, 0, 0); - } else { - if (wifi_connected) { - wifi_rssi_state = - halbtc8821a1ant_WifiRssiState(btcoexist, 1, 2, - 30, 0); - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a1ant_limited_tx(btcoexist, - NORMAL_EXEC, 1, 1, - 1, 1); - } else { - halbtc8821a1ant_limited_tx(btcoexist, - NORMAL_EXEC, 1, 1, - 1, 1); - } - } else { - halbtc8821a1ant_limited_tx(btcoexist, NORMAL_EXEC, - 0, 0, 0, 0); - } - } - - if (bt_link_info->sco_exist) { - bt_ctrl_agg_buf_size = true; - agg_buf_size = 0x3; - } else if (bt_link_info->hid_exist) { - bt_ctrl_agg_buf_size = true; - agg_buf_size = 0x5; - } else if (bt_link_info->a2dp_exist || bt_link_info->pan_exist) { - bt_ctrl_agg_buf_size = true; - agg_buf_size = 0x8; - } - halbtc8821a1ant_limited_rx(btcoexist, NORMAL_EXEC, false, - bt_ctrl_agg_buf_size, agg_buf_size); - - btc8821a1ant_run_sw_coex_mech(btcoexist); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - if (coex_sta->c2h_bt_inquiry_page) { - halbtc8821a1ant_action_bt_inquiry(btcoexist); - return; - } else if (bt_hs_on) { - halbtc8821a1ant_action_hs(btcoexist); - return; - } - - if (!wifi_connected) { - bool scan = false, link = false, roam = false; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], wifi is non connected-idle !!!\n"); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); - - if (scan || link || roam) - btc8821a1ant_act_wifi_not_conn_scan(btcoexist); - else - halbtc8821a1ant_action_wifi_not_connected(btcoexist); - } else { - /* wifi LPS/Busy*/ - halbtc8821a1ant_action_wifi_connected(btcoexist); - } -} - -static void halbtc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist) -{ - /* force to reset coex mechanism*/ - /* sw all off*/ - halbtc8821a1ant_sw_mechanism(btcoexist, false); - - halbtc8821a1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 8); - halbtc8821a1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0); -} - -static void halbtc8821a1ant_init_hw_config(struct btc_coexist *btcoexist, - bool back_up) -{ - u8 u1_tmp = 0; - bool wifi_under_5g = false; - - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], 1Ant Init HW Config!!\n"); - - if (back_up) { - coex_dm->backup_arfr_cnt1 = btcoexist->btc_read_4byte(btcoexist, - 0x430); - coex_dm->backup_arfr_cnt2 = btcoexist->btc_read_4byte(btcoexist, - 0x434); - coex_dm->backup_retry_limit = - btcoexist->btc_read_2byte(btcoexist, 0x42a); - coex_dm->backup_ampdu_max_time = - btcoexist->btc_read_1byte(btcoexist, 0x456); - } - - /* 0x790[5:0] = 0x5*/ - u1_tmp = btcoexist->btc_read_1byte(btcoexist, 0x790); - u1_tmp &= 0xc0; - u1_tmp |= 0x5; - btcoexist->btc_write_1byte(btcoexist, 0x790, u1_tmp); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); - - /*Antenna config*/ - if (wifi_under_5g) - halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_BT, - true, false); - else - halbtc8821a1ant_set_ant_path(btcoexist, BTC_ANT_PATH_PTA, - true, false); - /* PTA parameter*/ - halbtc8821a1ant_coex_table_with_type(btcoexist, FORCE_EXEC, 0); - - /* Enable counter statistics*/ - /*0x76e[3] =1, WLAN_Act control by PTA*/ - btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); - btcoexist->btc_write_1byte(btcoexist, 0x778, 0x3); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1); -} - -/*============================================================*/ -/* work around function start with wa_halbtc8821a1ant_*/ -/*============================================================*/ -/*============================================================*/ -/* extern function start with EXhalbtc8821a1ant_*/ -/*============================================================*/ -void ex_halbtc8821a1ant_init_hwconfig(struct btc_coexist *btcoexist) -{ - halbtc8821a1ant_init_hw_config(btcoexist, true); -} - -void ex_halbtc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist) -{ - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Coex Mechanism Init!!\n"); - - btcoexist->stop_coex_dm = false; - - halbtc8821a1ant_init_coex_dm(btcoexist); - - halbtc8821a1ant_query_bt_info(btcoexist); -} - -void ex_halbtc8821a1ant_display_coex_info(struct btc_coexist *btcoexist) -{ - struct btc_board_info *board_info = &btcoexist->board_info; - struct btc_stack_info *stack_info = &btcoexist->stack_info; - struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; - struct rtl_priv *rtlpriv = btcoexist->adapter; - u8 u1_tmp[4], i, bt_info_ext, ps_tdma_case = 0; - u16 u2_tmp[4]; - u32 u4_tmp[4]; - bool roam = false, scan = false, link = false, wifi_under_5g = false; - bool bt_hs_on = false, wifi_busy = false; - long wifi_rssi = 0, bt_hs_rssi = 0; - u32 wifi_bw, wifi_traffic_dir; - u8 wifi_dot11_chnl, wifi_hs_chnl; - u32 fw_ver = 0, bt_patch_ver = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n ============[BT Coexist info]============"); - - if (btcoexist->manual_control) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n ============[Under Manual Control]============"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n =========================================="); - } - if (btcoexist->stop_coex_dm) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n ============[Coex is STOPPED]============"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n =========================================="); - } - - if (!board_info->bt_exist) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n BT not exists !!!"); - return; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d/ %d/ %d", - "Ant PG Num/ Ant Mech/ Ant Pos:", - board_info->pg_ant_num, - board_info->btdm_ant_num, - board_info->btdm_ant_pos); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, - &bt_patch_ver); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d_%x/ 0x%x/ 0x%x(%d)", - "CoexVer/ FwVer/ PatchVer", - glcoex_ver_date_8821a_1ant, - glcoex_ver_8821a_1ant, - fw_ver, bt_patch_ver, - bt_patch_ver); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, - &bt_hs_on); - btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_DOT11_CHNL, - &wifi_dot11_chnl); - btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_HS_CHNL, - &wifi_hs_chnl); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d / %d(%d)", - "Dot11 channel / HsChnl(HsMode)", - wifi_dot11_chnl, wifi_hs_chnl, bt_hs_on); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %02x %02x %02x ", - "H2C Wifi inform bt chnl Info", - coex_dm->wifi_chnl_info[0], coex_dm->wifi_chnl_info[1], - coex_dm->wifi_chnl_info[2]); - - btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); - btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d/ %d", "Wifi rssi/ HS rssi", - (int)wifi_rssi, (int)bt_hs_rssi); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d/ %d/ %d ", "Wifi link/ roam/ scan", - link, roam, scan); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, - &wifi_under_5g); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, - &wifi_bw); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, - &wifi_busy); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, - &wifi_traffic_dir); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %s / %s/ %s ", "Wifi status", - (wifi_under_5g ? "5G" : "2.4G"), - ((BTC_WIFI_BW_LEGACY == wifi_bw) ? "Legacy" : - (((BTC_WIFI_BW_HT40 == wifi_bw) ? "HT40" : "HT20"))), - ((!wifi_busy) ? "idle" : - ((BTC_WIFI_TRAFFIC_TX == wifi_traffic_dir) ? - "uplink" : "downlink"))); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = [%s/ %d/ %d] ", "BT [status/ rssi/ retryCnt]", - ((btcoexist->bt_info.bt_disabled) ? ("disabled") : - ((coex_sta->c2h_bt_inquiry_page) ? ("inquiry/page scan") : - ((BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE == - coex_dm->bt_status) ? - "non-connected idle" : - ((BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE == - coex_dm->bt_status) ? - "connected-idle" : "busy")))), - coex_sta->bt_rssi, coex_sta->bt_retry_cnt); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP", - bt_link_info->sco_exist, - bt_link_info->hid_exist, - bt_link_info->pan_exist, - bt_link_info->a2dp_exist); - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_BT_LINK_INFO); - - bt_info_ext = coex_sta->bt_info_ext; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %s", - "BT Info A2DP rate", - (bt_info_ext&BIT0) ? - "Basic rate" : "EDR rate"); - - for (i = 0; i < BT_INFO_SRC_8821A_1ANT_MAX; i++) { - if (coex_sta->bt_info_c2h_cnt[i]) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)", - glbt_info_src_8821a_1ant[i], - coex_sta->bt_info_c2h[i][0], - coex_sta->bt_info_c2h[i][1], - coex_sta->bt_info_c2h[i][2], - coex_sta->bt_info_c2h[i][3], - coex_sta->bt_info_c2h[i][4], - coex_sta->bt_info_c2h[i][5], - coex_sta->bt_info_c2h[i][6], - coex_sta->bt_info_c2h_cnt[i]); - } - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %s/%s, (0x%x/0x%x)", - "PS state, IPS/LPS, (lps/rpwm)", - ((coex_sta->under_ips ? "IPS ON" : "IPS OFF")), - ((coex_sta->under_Lps ? "LPS ON" : "LPS OFF")), - btcoexist->bt_info.lps_val, - btcoexist->bt_info.rpwm_val); - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD); - - if (!btcoexist->manual_control) { - /* Sw mechanism*/ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s", "============[Sw mechanism]============"); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d", "SM[LowPenaltyRA]", - coex_dm->cur_low_penalty_ra); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %s/ %s/ %d ", - "DelBA/ BtCtrlAgg/ AggSize", - (btcoexist->bt_info.reject_agg_pkt ? "Yes" : "No"), - (btcoexist->bt_info.bt_ctrl_buf_size ? "Yes" : "No"), - btcoexist->bt_info.agg_buf_size); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x ", "Rate Mask", - btcoexist->bt_info.ra_mask); - - /* Fw mechanism*/ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", - "============[Fw mechanism]============"); - - ps_tdma_case = coex_dm->cur_ps_tdma; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)", - "PS TDMA", - coex_dm->ps_tdma_para[0], - coex_dm->ps_tdma_para[1], - coex_dm->ps_tdma_para[2], - coex_dm->ps_tdma_para[3], - coex_dm->ps_tdma_para[4], - ps_tdma_case, - coex_dm->auto_tdma_adjust); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x ", - "Latest error condition(should be 0)", - coex_dm->error_condition); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d ", "IgnWlanAct", - coex_dm->cur_ignore_wlan_act); - } - - /* Hw setting*/ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s", "============[Hw setting]============"); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", - "backup ARFR1/ARFR2/RL/AMaxTime", - coex_dm->backup_arfr_cnt1, - coex_dm->backup_arfr_cnt2, - coex_dm->backup_retry_limit, - coex_dm->backup_ampdu_max_time); - - u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x430); - u4_tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x434); - u2_tmp[0] = btcoexist->btc_read_2byte(btcoexist, 0x42a); - u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x456); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x/0x%x/0x%x/0x%x", - "0x430/0x434/0x42a/0x456", - u4_tmp[0], u4_tmp[1], u2_tmp[0], u1_tmp[0]); - - u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x778); - u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc58); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x/ 0x%x", "0x778/ 0xc58[29:25]", - u1_tmp[0], (u4_tmp[0]&0x3e000000) >> 25); - - u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x8db); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x", "0x8db[6:5]", - ((u1_tmp[0]&0x60)>>5)); - - u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x975); - u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xcb4); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "0xcb4[29:28]/0xcb4[7:0]/0x974[9:8]", - (u4_tmp[0] & 0x30000000)>>28, - u4_tmp[0] & 0xff, - u1_tmp[0] & 0x3); - - u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x40); - u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x4c); - u1_tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x64); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "0x40/0x4c[24:23]/0x64[0]", - u1_tmp[0], ((u4_tmp[0]&0x01800000)>>23), u1_tmp[1]&0x1); - - u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x550); - u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x522); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x/ 0x%x", "0x550(bcn ctrl)/0x522", - u4_tmp[0], u1_tmp[0]); - - u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc50); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x", "0xc50(dig)", - u4_tmp[0]&0xff); - - u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xf48); - u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xa5d); - u1_tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xa5c); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x/ 0x%x", "OFDM-FA/ CCK-FA", - u4_tmp[0], (u1_tmp[0]<<8) + u1_tmp[1]); - - u4_tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6c0); - u4_tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x6c4); - u4_tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x6c8); - u1_tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x6cc); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x/ 0x%x/ 0x%x/ 0x%x", - "0x6c0/0x6c4/0x6c8/0x6cc(coexTable)", - u4_tmp[0], u4_tmp[1], u4_tmp[2], u1_tmp[0]); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d/ %d", "0x770(high-pri rx/tx)", - coex_sta->high_priority_rx, coex_sta->high_priority_tx); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d/ %d", "0x774(low-pri rx/tx)", - coex_sta->low_priority_rx, coex_sta->low_priority_tx); -#if (BT_AUTO_REPORT_ONLY_8821A_1ANT == 1) - halbtc8821a1ant_monitor_bt_ctr(btcoexist); -#endif - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS); -} - -void ex_halbtc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (btcoexist->manual_control || btcoexist->stop_coex_dm) - return; - - if (BTC_IPS_ENTER == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS ENTER notify\n"); - coex_sta->under_ips = true; - halbtc8821a1ant_set_ant_path(btcoexist, - BTC_ANT_PATH_BT, false, true); - /*set PTA control*/ - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 8); - halbtc8821a1ant_coex_table_with_type(btcoexist, - NORMAL_EXEC, 0); - } else if (BTC_IPS_LEAVE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS LEAVE notify\n"); - coex_sta->under_ips = false; - - halbtc8821a1ant_run_coexist_mechanism(btcoexist); - } -} - -void ex_halbtc8821a1ant_lps_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (btcoexist->manual_control || btcoexist->stop_coex_dm) - return; - - if (BTC_LPS_ENABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS ENABLE notify\n"); - coex_sta->under_Lps = true; - } else if (BTC_LPS_DISABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS DISABLE notify\n"); - coex_sta->under_Lps = false; - } -} - -void ex_halbtc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type) -{ - bool wifi_connected = false, bt_hs_on = false; - - if (btcoexist->manual_control || - btcoexist->stop_coex_dm || - btcoexist->bt_info.bt_disabled) - return; - - btcoexist->btc_get(btcoexist, - BTC_GET_BL_HS_OPERATION, &bt_hs_on); - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); - - halbtc8821a1ant_query_bt_info(btcoexist); - - if (coex_sta->c2h_bt_inquiry_page) { - halbtc8821a1ant_action_bt_inquiry(btcoexist); - return; - } else if (bt_hs_on) { - halbtc8821a1ant_action_hs(btcoexist); - return; - } - - if (BTC_SCAN_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN START notify\n"); - if (!wifi_connected) { - /* non-connected scan*/ - btc8821a1ant_act_wifi_not_conn_scan(btcoexist); - } else { - /* wifi is connected*/ - halbtc8821a1ant_action_wifi_connected_scan(btcoexist); - } - } else if (BTC_SCAN_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN FINISH notify\n"); - if (!wifi_connected) { - /* non-connected scan*/ - halbtc8821a1ant_action_wifi_not_connected(btcoexist); - } else { - halbtc8821a1ant_action_wifi_connected(btcoexist); - } - } -} - -void ex_halbtc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type) -{ - bool wifi_connected = false, bt_hs_on = false; - - if (btcoexist->manual_control || - btcoexist->stop_coex_dm || - btcoexist->bt_info.bt_disabled) - return; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - if (coex_sta->c2h_bt_inquiry_page) { - halbtc8821a1ant_action_bt_inquiry(btcoexist); - return; - } else if (bt_hs_on) { - halbtc8821a1ant_action_hs(btcoexist); - return; - } - - if (BTC_ASSOCIATE_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT START notify\n"); - btc8821a1ant_act_wifi_not_conn_scan(btcoexist); - } else if (BTC_ASSOCIATE_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT FINISH notify\n"); - - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); - if (!wifi_connected) { - /* non-connected scan*/ - halbtc8821a1ant_action_wifi_not_connected(btcoexist); - } else { - halbtc8821a1ant_action_wifi_connected(btcoexist); - } - } -} - -void ex_halbtc8821a1ant_media_status_notify(struct btc_coexist *btcoexist, - u8 type) -{ - u8 h2c_parameter[3] = {0}; - u32 wifi_bw; - u8 wifi_central_chnl; - - if (btcoexist->manual_control || - btcoexist->stop_coex_dm || - btcoexist->bt_info.bt_disabled) - return; - - if (BTC_MEDIA_CONNECT == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA connect notify\n"); - } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA disconnect notify\n"); - } - - /* only 2.4G we need to inform bt the chnl mask*/ - btcoexist->btc_get(btcoexist, - BTC_GET_U1_WIFI_CENTRAL_CHNL, - &wifi_central_chnl); - if ((BTC_MEDIA_CONNECT == type) && - (wifi_central_chnl <= 14)) { - /*h2c_parameter[0] = 0x1;*/ - h2c_parameter[0] = 0x0; - h2c_parameter[1] = wifi_central_chnl; - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) - h2c_parameter[2] = 0x30; - else - h2c_parameter[2] = 0x20; - } - - coex_dm->wifi_chnl_info[0] = h2c_parameter[0]; - coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; - coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x66 = 0x%x\n", - h2c_parameter[0]<<16|h2c_parameter[1]<<8|h2c_parameter[2]); - - btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); -} - -void ex_halbtc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist, - u8 type) -{ - bool bt_hs_on = false; - - if (btcoexist->manual_control || - btcoexist->stop_coex_dm || - btcoexist->bt_info.bt_disabled) - return; - - coex_sta->special_pkt_period_cnt = 0; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - if (coex_sta->c2h_bt_inquiry_page) { - halbtc8821a1ant_action_bt_inquiry(btcoexist); - return; - } else if (bt_hs_on) { - halbtc8821a1ant_action_hs(btcoexist); - return; - } - - if (BTC_PACKET_DHCP == type || - BTC_PACKET_EAPOL == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], special Packet(%d) notify\n", type); - btc8821a1ant_act_wifi_conn_sp_pkt(btcoexist); - } -} - -void ex_halbtc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist, - u8 *tmp_buf, u8 length) -{ - u8 bt_info = 0; - u8 i, rsp_source = 0; - bool wifi_connected = false; - bool bt_busy = false; - bool wifi_under_5g = false; - - coex_sta->c2h_bt_info_req_sent = false; - - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); - - rsp_source = tmp_buf[0]&0xf; - if (rsp_source >= BT_INFO_SRC_8821A_1ANT_MAX) - rsp_source = BT_INFO_SRC_8821A_1ANT_WIFI_FW; - coex_sta->bt_info_c2h_cnt[rsp_source]++; - - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Bt info[%d], length = %d, hex data = [", - rsp_source, length); - for (i = 0; i < length; i++) { - coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i]; - if (i == 1) - bt_info = tmp_buf[i]; - if (i == length-1) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x]\n", tmp_buf[i]); - } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x, ", tmp_buf[i]); - } - } - - if (BT_INFO_SRC_8821A_1ANT_WIFI_FW != rsp_source) { - coex_sta->bt_retry_cnt = /* [3:0]*/ - coex_sta->bt_info_c2h[rsp_source][2]&0xf; - - coex_sta->bt_rssi = - coex_sta->bt_info_c2h[rsp_source][3]*2+10; - - coex_sta->bt_info_ext = - coex_sta->bt_info_c2h[rsp_source][4]; - - /* Here we need to resend some wifi info to BT*/ - /* because bt is reset and loss of the info.*/ - if (coex_sta->bt_info_ext & BIT1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit1 check, send wifi BW&Chnl to BT!!\n"); - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - if (wifi_connected) { - ex_halbtc8821a1ant_media_status_notify(btcoexist, - BTC_MEDIA_CONNECT); - } else { - ex_halbtc8821a1ant_media_status_notify(btcoexist, - BTC_MEDIA_DISCONNECT); - } - } - - if ((coex_sta->bt_info_ext & BIT3) && !wifi_under_5g) { - if (!btcoexist->manual_control && - !btcoexist->stop_coex_dm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n"); - halbtc8821a1ant_ignore_wlan_act(btcoexist, - FORCE_EXEC, - false); - } - } -#if (BT_AUTO_REPORT_ONLY_8821A_1ANT == 0) - if (!(coex_sta->bt_info_ext & BIT4)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT ext info bit4 check, set BT to enable Auto Report!!\n"); - halbtc8821a1ant_bt_auto_report(btcoexist, - FORCE_EXEC, true); - } -#endif - } - - /* check BIT2 first ==> check if bt is under inquiry or page scan*/ - if (bt_info & BT_INFO_8821A_1ANT_B_INQ_PAGE) - coex_sta->c2h_bt_inquiry_page = true; - else - coex_sta->c2h_bt_inquiry_page = false; - - /* set link exist status*/ - if (!(bt_info&BT_INFO_8821A_1ANT_B_CONNECTION)) { - coex_sta->bt_link_exist = false; - coex_sta->pan_exist = false; - coex_sta->a2dp_exist = false; - coex_sta->hid_exist = false; - coex_sta->sco_exist = false; - } else { - /* connection exists*/ - coex_sta->bt_link_exist = true; - if (bt_info & BT_INFO_8821A_1ANT_B_FTP) - coex_sta->pan_exist = true; - else - coex_sta->pan_exist = false; - if (bt_info & BT_INFO_8821A_1ANT_B_A2DP) - coex_sta->a2dp_exist = true; - else - coex_sta->a2dp_exist = false; - if (bt_info & BT_INFO_8821A_1ANT_B_HID) - coex_sta->hid_exist = true; - else - coex_sta->hid_exist = false; - if (bt_info & BT_INFO_8821A_1ANT_B_SCO_ESCO) - coex_sta->sco_exist = true; - else - coex_sta->sco_exist = false; - } - - halbtc8821a1ant_update_bt_link_info(btcoexist); - - if (!(bt_info&BT_INFO_8821A_1ANT_B_CONNECTION)) { - coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Non-Connected idle!!!\n"); - } else if (bt_info == BT_INFO_8821A_1ANT_B_CONNECTION) { - /* connection exists but no busy*/ - coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Connected-idle!!!\n"); - } else if ((bt_info&BT_INFO_8821A_1ANT_B_SCO_ESCO) || - (bt_info&BT_INFO_8821A_1ANT_B_SCO_BUSY)) { - coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_SCO_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT SCO busy!!!\n"); - } else if (bt_info&BT_INFO_8821A_1ANT_B_ACL_BUSY) { - if (BT_8821A_1ANT_BT_STATUS_ACL_BUSY != coex_dm->bt_status) - coex_dm->auto_tdma_adjust = false; - coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_ACL_BUSY; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT ACL busy!!!\n"); - } else { - coex_dm->bt_status = BT_8821A_1ANT_BT_STATUS_MAX; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BtInfoNotify(), BT Non-Defined state!!!\n"); - } - - if ((BT_8821A_1ANT_BT_STATUS_ACL_BUSY == coex_dm->bt_status) || - (BT_8821A_1ANT_BT_STATUS_SCO_BUSY == coex_dm->bt_status) || - (BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY == coex_dm->bt_status)) - bt_busy = true; - else - bt_busy = false; - btcoexist->btc_set(btcoexist, - BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy); - - halbtc8821a1ant_run_coexist_mechanism(btcoexist); -} - -void ex_halbtc8821a1ant_halt_notify(struct btc_coexist *btcoexist) -{ - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Halt notify\n"); - - btcoexist->stop_coex_dm = true; - - halbtc8821a1ant_set_ant_path(btcoexist, - BTC_ANT_PATH_BT, false, true); - halbtc8821a1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); - - halbtc8821a1ant_power_save_state(btcoexist, - BTC_PS_WIFI_NATIVE, 0x0, 0x0); - halbtc8821a1ant_ps_tdma(btcoexist, FORCE_EXEC, false, 0); - - ex_halbtc8821a1ant_media_status_notify(btcoexist, - BTC_MEDIA_DISCONNECT); -} - -void ex_halbtc8821a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state) -{ - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Pnp notify\n"); - - if (BTC_WIFI_PNP_SLEEP == pnp_state) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Pnp notify to SLEEP\n"); - btcoexist->stop_coex_dm = true; - halbtc8821a1ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); - halbtc8821a1ant_power_save_state(btcoexist, BTC_PS_WIFI_NATIVE, - 0x0, 0x0); - halbtc8821a1ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 9); - } else if (BTC_WIFI_PNP_WAKE_UP == pnp_state) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Pnp notify to WAKE UP\n"); - btcoexist->stop_coex_dm = false; - halbtc8821a1ant_init_hw_config(btcoexist, false); - halbtc8821a1ant_init_coex_dm(btcoexist); - halbtc8821a1ant_query_bt_info(btcoexist); - } -} - -void -ex_halbtc8821a1ant_periodical( - struct btc_coexist *btcoexist) { - static u8 dis_ver_info_cnt; - u32 fw_ver = 0, bt_patch_ver = 0; - struct btc_board_info *board_info = &btcoexist->board_info; - struct btc_stack_info *stack_info = &btcoexist->stack_info; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], ==========================Periodical===========================\n"); - - if (dis_ver_info_cnt <= 5) { - dis_ver_info_cnt += 1; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************************************************\n"); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", - board_info->pg_ant_num, - board_info->btdm_ant_num, - board_info->btdm_ant_pos); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], BT stack/ hci ext ver = %s / %d\n", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); - btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, - &bt_patch_ver); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", - glcoex_ver_date_8821a_1ant, - glcoex_ver_8821a_1ant, - fw_ver, bt_patch_ver, - bt_patch_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************************************************\n"); - } - -#if (BT_AUTO_REPORT_ONLY_8821A_1ANT == 0) - halbtc8821a1ant_query_bt_info(btcoexist); - halbtc8821a1ant_monitor_bt_ctr(btcoexist); - btc8821a1ant_mon_bt_en_dis(btcoexist); -#else - if (halbtc8821a1ant_Is_wifi_status_changed(btcoexist) || - coex_dm->auto_tdma_adjust) { - if (coex_sta->special_pkt_period_cnt > 2) - halbtc8821a1ant_run_coexist_mechanism(btcoexist); - } - - coex_sta->special_pkt_period_cnt++; -#endif -} diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.h deleted file mode 100644 index 20e904890fc2..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a1ant.h +++ /dev/null @@ -1,188 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -/*=========================================== - * The following is for 8821A 1ANT BT Co-exist definition - *=========================================== - */ -#define BT_AUTO_REPORT_ONLY_8821A_1ANT 0 - -#define BT_INFO_8821A_1ANT_B_FTP BIT7 -#define BT_INFO_8821A_1ANT_B_A2DP BIT6 -#define BT_INFO_8821A_1ANT_B_HID BIT5 -#define BT_INFO_8821A_1ANT_B_SCO_BUSY BIT4 -#define BT_INFO_8821A_1ANT_B_ACL_BUSY BIT3 -#define BT_INFO_8821A_1ANT_B_INQ_PAGE BIT2 -#define BT_INFO_8821A_1ANT_B_SCO_ESCO BIT1 -#define BT_INFO_8821A_1ANT_B_CONNECTION BIT0 - -#define BT_INFO_8821A_1ANT_A2DP_BASIC_RATE(_BT_INFO_EXT_) \ - (((_BT_INFO_EXT_&BIT0)) ? true : false) - -#define BTC_RSSI_COEX_THRESH_TOL_8821A_1ANT 2 - -enum _BT_INFO_SRC_8821A_1ANT { - BT_INFO_SRC_8821A_1ANT_WIFI_FW = 0x0, - BT_INFO_SRC_8821A_1ANT_BT_RSP = 0x1, - BT_INFO_SRC_8821A_1ANT_BT_ACTIVE_SEND = 0x2, - BT_INFO_SRC_8821A_1ANT_MAX -}; - -enum _BT_8821A_1ANT_BT_STATUS { - BT_8821A_1ANT_BT_STATUS_NON_CONNECTED_IDLE = 0x0, - BT_8821A_1ANT_BT_STATUS_CONNECTED_IDLE = 0x1, - BT_8821A_1ANT_BT_STATUS_INQ_PAGE = 0x2, - BT_8821A_1ANT_BT_STATUS_ACL_BUSY = 0x3, - BT_8821A_1ANT_BT_STATUS_SCO_BUSY = 0x4, - BT_8821A_1ANT_BT_STATUS_ACL_SCO_BUSY = 0x5, - BT_8821A_1ANT_BT_STATUS_MAX -}; - -enum _BT_8821A_1ANT_WIFI_STATUS { - BT_8821A_1ANT_WIFI_STATUS_NON_CONNECTED_IDLE = 0x0, - BT_8821A_1ANT_WIFI_STATUS_NON_CONNECTED_ASSO_AUTH_SCAN = 0x1, - BT_8821A_1ANT_WIFI_STATUS_CONNECTED_SCAN = 0x2, - BT_8821A_1ANT_WIFI_STATUS_CONNECTED_SPECIAL_PKT = 0x3, - BT_8821A_1ANT_WIFI_STATUS_CONNECTED_IDLE = 0x4, - BT_8821A_1ANT_WIFI_STATUS_CONNECTED_BUSY = 0x5, - BT_8821A_1ANT_WIFI_STATUS_MAX -}; - -enum BT_8821A_1ANT_COEX_ALGO { - BT_8821A_1ANT_COEX_ALGO_UNDEFINED = 0x0, - BT_8821A_1ANT_COEX_ALGO_SCO = 0x1, - BT_8821A_1ANT_COEX_ALGO_HID = 0x2, - BT_8821A_1ANT_COEX_ALGO_A2DP = 0x3, - BT_8821A_1ANT_COEX_ALGO_A2DP_PANHS = 0x4, - BT_8821A_1ANT_COEX_ALGO_PANEDR = 0x5, - BT_8821A_1ANT_COEX_ALGO_PANHS = 0x6, - BT_8821A_1ANT_COEX_ALGO_PANEDR_A2DP = 0x7, - BT_8821A_1ANT_COEX_ALGO_PANEDR_HID = 0x8, - BT_8821A_1ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x9, - BT_8821A_1ANT_COEX_ALGO_HID_A2DP = 0xa, - BT_8821A_1ANT_COEX_ALGO_MAX = 0xb, -}; - -struct coex_dm_8821a_1ant { - /* fw mechanism */ - bool cur_ignore_wlan_act; - bool pre_ignore_wlan_act; - u8 pre_ps_tdma; - u8 cur_ps_tdma; - u8 ps_tdma_para[5]; - u8 tdma_adj_type; - bool auto_tdma_adjust; - bool pre_ps_tdma_on; - bool cur_ps_tdma_on; - bool pre_bt_auto_report; - bool cur_bt_auto_report; - u8 pre_lps; - u8 cur_lps; - u8 pre_rpwm; - u8 cur_rpwm; - - /* sw mechanism */ - bool pre_low_penalty_ra; - bool cur_low_penalty_ra; - u32 pre_val_0x6c0; - u32 cur_val_0x6c0; - u32 pre_val_0x6c4; - u32 cur_val_0x6c4; - u32 pre_val_0x6c8; - u32 cur_val_0x6c8; - u8 pre_val_0x6cc; - u8 cur_val_0x6cc; - /* Auto Rate Fallback Retry cnt */ - u32 backup_arfr_cnt1; - /* Auto Rate Fallback Retry cnt */ - u32 backup_arfr_cnt2; - u16 backup_retry_limit; - u8 backup_ampdu_max_time; - - /* algorithm related */ - u8 pre_algorithm; - u8 cur_algorithm; - u8 bt_status; - u8 wifi_chnl_info[3]; - - u32 pre_ra_mask; - u32 cur_ra_mask; - u8 pre_arfr_type; - u8 cur_arfr_type; - u8 pre_retry_limit_type; - u8 cur_retry_limit_type; - u8 pre_ampdu_time_type; - u8 cur_ampdu_time_type; - - u8 error_condition; -}; - -struct coex_sta_8821a_1ant { - bool bt_link_exist; - bool sco_exist; - bool a2dp_exist; - bool hid_exist; - bool pan_exist; - - bool under_Lps; - bool under_ips; - u32 special_pkt_period_cnt; - u32 high_priority_tx; - u32 high_priority_rx; - u32 low_priority_tx; - u32 low_priority_rx; - u8 bt_rssi; - u8 pre_bt_rssi_state; - u8 pre_wifi_rssi_state[4]; - bool c2h_bt_info_req_sent; - u8 bt_info_c2h[BT_INFO_SRC_8821A_1ANT_MAX][10]; - u32 bt_info_c2h_cnt[BT_INFO_SRC_8821A_1ANT_MAX]; - bool c2h_bt_inquiry_page; - u8 bt_retry_cnt; - u8 bt_info_ext; -}; - -/*=========================================== - * The following is interface which will notify coex module. - *=========================================== - */ -void ex_halbtc8821a1ant_init_hwconfig(struct btc_coexist *btcoexist); -void ex_halbtc8821a1ant_init_coex_dm(struct btc_coexist *btcoexist); -void ex_halbtc8821a1ant_ips_notify(struct btc_coexist *btcoexist, u8 type); -void ex_halbtc8821a1ant_lps_notify(struct btc_coexist *btcoexist, u8 type); -void ex_halbtc8821a1ant_scan_notify(struct btc_coexist *btcoexist, u8 type); -void ex_halbtc8821a1ant_connect_notify(struct btc_coexist *btcoexist, u8 type); -void ex_halbtc8821a1ant_media_status_notify(struct btc_coexist *btcoexist, - u8 type); -void ex_halbtc8821a1ant_special_packet_notify(struct btc_coexist *btcoexist, - u8 type); -void ex_halbtc8821a1ant_bt_info_notify(struct btc_coexist *btcoexist, - u8 *tmpbuf, u8 length); -void ex_halbtc8821a1ant_halt_notify(struct btc_coexist *btcoexist); -void ex_halbtc8821a1ant_pnp_notify(struct btc_coexist *btcoexist, u8 pnpstate); -void ex_halbtc8821a1ant_periodical(struct btc_coexist *btcoexist); -void ex_halbtc8821a1ant_display_coex_info(struct btc_coexist *btcoexist); -void ex_halbtc8821a1ant_dbg_control(struct btc_coexist *btcoexist, u8 op_code, - u8 op_len, u8 *data); diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.c b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.c deleted file mode 100644 index cf819f02ed23..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.c +++ /dev/null @@ -1,3879 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -/*============================================================ - * Description: - * - * This file is for RTL8821A Co-exist mechanism - * - * History - * 2012/08/22 Cosa first check in. - * 2012/11/14 Cosa Revise for 8821A 2Ant out sourcing. - * - *============================================================ - */ - -/*============================================================ - * include files - *============================================================ -*/ -#include "halbt_precomp.h" -/*============================================================ - * Global variables, these are static variables - *============================================================ - */ -static struct coex_dm_8821a_2ant glcoex_dm_8821a_2ant; -static struct coex_dm_8821a_2ant *coex_dm = &glcoex_dm_8821a_2ant; -static struct coex_sta_8821a_2ant glcoex_sta_8821a_2ant; -static struct coex_sta_8821a_2ant *coex_sta = &glcoex_sta_8821a_2ant; - -static const char *const glbt_info_src_8821a_2ant[] = { - "BT Info[wifi fw]", - "BT Info[bt rsp]", - "BT Info[bt auto report]", -}; - -static u32 glcoex_ver_date_8821a_2ant = 20130618; -static u32 glcoex_ver_8821a_2ant = 0x5050; - -/*============================================================ - * local function proto type if needed - *============================================================ - *============================================================ - * local function start with halbtc8821a2ant_ - *============================================================ - */ -static u8 halbtc8821a2ant_bt_rssi_state(u8 level_num, u8 rssi_thresh, - u8 rssi_thresh1) -{ - long bt_rssi = 0; - u8 bt_rssi_state = coex_sta->pre_bt_rssi_state; - - bt_rssi = coex_sta->bt_rssi; - - if (level_num == 2) { - if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || - (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { - long tmp = rssi_thresh + - BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT; - if (bt_rssi >= tmp) { - bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to High\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Low\n"); - } - } else { - if (bt_rssi < rssi_thresh) { - bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Low\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at High\n"); - } - } - } else if (level_num == 3) { - if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi thresh error!!\n"); - return coex_sta->pre_bt_rssi_state; - } - - if ((coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_LOW) || - (coex_sta->pre_bt_rssi_state == BTC_RSSI_STATE_STAY_LOW)) { - if (bt_rssi >= - (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { - bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Medium\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Low\n"); - } - } else if ((coex_sta->pre_bt_rssi_state == - BTC_RSSI_STATE_MEDIUM) || - (coex_sta->pre_bt_rssi_state == - BTC_RSSI_STATE_STAY_MEDIUM)) { - if (bt_rssi >= - (rssi_thresh1 + - BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { - bt_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to High\n"); - } else if (bt_rssi < rssi_thresh) { - bt_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Low\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at Medium\n"); - } - } else { - if (bt_rssi < rssi_thresh1) { - bt_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state switch to Medium\n"); - } else { - bt_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_RSSI_STATE, - "[BTCoex], BT Rssi state stay at High\n"); - } - } - } - - coex_sta->pre_bt_rssi_state = bt_rssi_state; - - return bt_rssi_state; -} - -static u8 halbtc8821a2ant_wifi_rssi_state(struct btc_coexist *btcoexist, - u8 index, u8 level_num, - u8 rssi_thresh, u8 rssi_thresh1) -{ - long wifi_rssi = 0; - u8 wifi_rssi_state = coex_sta->pre_wifi_rssi_state[index]; - - btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); - - if (level_num == 2) { - if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_LOW) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_LOW)) { - if (wifi_rssi >= - (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { - wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to High\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Low\n"); - } - } else { - if (wifi_rssi < rssi_thresh) { - wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Low\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at High\n"); - } - } - } else if (level_num == 3) { - if (rssi_thresh > rssi_thresh1) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI thresh error!!\n"); - return coex_sta->pre_wifi_rssi_state[index]; - } - - if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_LOW) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_LOW)) { - if (wifi_rssi >= - (rssi_thresh+BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { - wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Medium\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Low\n"); - } - } else if ((coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_MEDIUM) || - (coex_sta->pre_wifi_rssi_state[index] == - BTC_RSSI_STATE_STAY_MEDIUM)) { - if (wifi_rssi >= (rssi_thresh1 + - BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT)) { - wifi_rssi_state = BTC_RSSI_STATE_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to High\n"); - } else if (wifi_rssi < rssi_thresh) { - wifi_rssi_state = BTC_RSSI_STATE_LOW; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Low\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at Medium\n"); - } - } else { - if (wifi_rssi < rssi_thresh1) { - wifi_rssi_state = BTC_RSSI_STATE_MEDIUM; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state switch to Medium\n"); - } else { - wifi_rssi_state = BTC_RSSI_STATE_STAY_HIGH; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_WIFI_RSSI_STATE, - "[BTCoex], wifi RSSI state stay at High\n"); - } - } - } - coex_sta->pre_wifi_rssi_state[index] = wifi_rssi_state; - - return wifi_rssi_state; -} - -static void btc8821a2ant_mon_bt_en_dis(struct btc_coexist *btcoexist) -{ - static bool pre_bt_disabled; - static u32 bt_disable_cnt; - bool bt_active = true, bt_disabled = false; - - /* This function check if bt is disabled*/ - - if (coex_sta->high_priority_tx == 0 && - coex_sta->high_priority_rx == 0 && - coex_sta->low_priority_tx == 0 && - coex_sta->low_priority_rx == 0) - bt_active = false; - if (coex_sta->high_priority_tx == 0xffff && - coex_sta->high_priority_rx == 0xffff && - coex_sta->low_priority_tx == 0xffff && - coex_sta->low_priority_rx == 0xffff) - bt_active = false; - if (bt_active) { - bt_disable_cnt = 0; - bt_disabled = false; - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, - &bt_disabled); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is enabled !!\n"); - } else { - bt_disable_cnt++; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], bt all counters = 0, %d times!!\n", - bt_disable_cnt); - if (bt_disable_cnt >= 2) { - bt_disabled = true; - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_DISABLE, - &bt_disabled); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is disabled !!\n"); - } - } - if (pre_bt_disabled != bt_disabled) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], BT is from %s to %s!!\n", - (pre_bt_disabled ? "disabled" : "enabled"), - (bt_disabled ? "disabled" : "enabled")); - pre_bt_disabled = bt_disabled; - } -} - -static void halbtc8821a2ant_monitor_bt_ctr(struct btc_coexist *btcoexist) -{ - u32 reg_hp_txrx, reg_lp_txrx, u4tmp; - u32 reg_hp_tx = 0, reg_hp_rx = 0, reg_lp_tx = 0, reg_lp_rx = 0; - - reg_hp_txrx = 0x770; - reg_lp_txrx = 0x774; - - u4tmp = btcoexist->btc_read_4byte(btcoexist, reg_hp_txrx); - reg_hp_tx = u4tmp & MASKLWORD; - reg_hp_rx = (u4tmp & MASKHWORD)>>16; - - u4tmp = btcoexist->btc_read_4byte(btcoexist, reg_lp_txrx); - reg_lp_tx = u4tmp & MASKLWORD; - reg_lp_rx = (u4tmp & MASKHWORD)>>16; - - coex_sta->high_priority_tx = reg_hp_tx; - coex_sta->high_priority_rx = reg_hp_rx; - coex_sta->low_priority_tx = reg_lp_tx; - coex_sta->low_priority_rx = reg_lp_rx; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], High Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", - reg_hp_txrx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_BT_MONITOR, - "[BTCoex], Low Priority Tx/Rx (reg 0x%x) = 0x%x(%d)/0x%x(%d)\n", - reg_lp_txrx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); - - /* reset counter */ - btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); -} - -static void halbtc8821a2ant_query_bt_info(struct btc_coexist *btcoexist) -{ - u8 h2c_parameter[1] = {0}; - - coex_sta->c2h_bt_info_req_sent = true; - - h2c_parameter[0] |= BIT0; /* trigger */ - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Query Bt Info, FW write 0x61 = 0x%x\n", - h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); -} - -static u8 halbtc8821a2ant_action_algorithm(struct btc_coexist *btcoexist) -{ - struct btc_stack_info *stack_info = &btcoexist->stack_info; - bool bt_hs_on = false; - u8 algorithm = BT_8821A_2ANT_COEX_ALGO_UNDEFINED; - u8 num_of_diff_profile = 0; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - - /*for win-8 stack HID report error*/ - /* sync BTInfo with BT firmware and stack */ - if (!stack_info->hid_exist) - stack_info->hid_exist = coex_sta->hid_exist; - /* when stack HID report error, here we use the info from bt fw. */ - if (!stack_info->bt_link_exist) - stack_info->bt_link_exist = coex_sta->bt_link_exist; - - if (!coex_sta->bt_link_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], No profile exists!!!\n"); - return algorithm; - } - - if (coex_sta->sco_exist) - num_of_diff_profile++; - if (coex_sta->hid_exist) - num_of_diff_profile++; - if (coex_sta->pan_exist) - num_of_diff_profile++; - if (coex_sta->a2dp_exist) - num_of_diff_profile++; - - if (num_of_diff_profile == 1) { - if (coex_sta->sco_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO only\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_SCO; - } else { - if (coex_sta->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID only\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_HID; - } else if (coex_sta->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], A2DP only\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_A2DP; - } else if (coex_sta->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], PAN(HS) only\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANHS; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], PAN(EDR) only\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR; - } - } - } - } else if (num_of_diff_profile == 2) { - if (coex_sta->sco_exist) { - if (coex_sta->hid_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; - } else if (coex_sta->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + A2DP ==> SCO\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; - } else if (coex_sta->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + PAN(HS)\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_SCO; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + PAN(EDR)\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; - } - } - } else { - if (coex_sta->hid_exist && - coex_sta->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + A2DP\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_HID_A2DP; - } else if (coex_sta->hid_exist && - coex_sta->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + PAN(HS)\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_HID; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + PAN(EDR)\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; - } - } else if (coex_sta->pan_exist && - coex_sta->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], A2DP + PAN(HS)\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_A2DP_PANHS; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], A2DP + PAN(EDR)\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_A2DP; - } - } - } - } else if (num_of_diff_profile == 3) { - if (coex_sta->sco_exist) { - if (coex_sta->hid_exist && - coex_sta->a2dp_exist) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + A2DP ==> HID\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; - } else if (coex_sta->hid_exist && - coex_sta->pan_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + PAN(HS)\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + PAN(EDR)\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; - } - } else if (coex_sta->pan_exist && - coex_sta->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + A2DP + PAN(HS)\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + A2DP + PAN(EDR) ==> HID\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; - } - } - } else { - if (coex_sta->hid_exist && - coex_sta->pan_exist && - coex_sta->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + A2DP + PAN(HS)\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_HID_A2DP; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], HID + A2DP + PAN(EDR)\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_HID_A2DP_PANEDR; - } - } - } - } else if (num_of_diff_profile >= 3) { - if (coex_sta->sco_exist) { - if (coex_sta->hid_exist && - coex_sta->pan_exist && - coex_sta->a2dp_exist) { - if (bt_hs_on) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Error!!! SCO + HID + A2DP + PAN(HS)\n"); - - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], SCO + HID + A2DP + PAN(EDR)==>PAN(EDR)+HID\n"); - algorithm = BT_8821A_2ANT_COEX_ALGO_PANEDR_HID; - } - } - } - } - return algorithm; -} - -static bool halbtc8821a2ant_need_to_dec_bt_pwr(struct btc_coexist *btcoexist) -{ - bool ret = false; - bool bt_hs_on = false, wifi_connected = false; - long bt_hs_rssi = 0; - u8 bt_rssi_state; - - if (!btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on)) - return false; - if (!btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected)) - return false; - if (!btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi)) - return false; - - bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); - - if (wifi_connected) { - if (bt_hs_on) { - if (bt_hs_rssi > 37) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], Need to decrease bt power for HS mode!!\n"); - ret = true; - } - } else { - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], Need to decrease bt power for Wifi is connected!!\n"); - ret = true; - } - } - } - return ret; -} - -static void btc8821a2ant_set_fw_dac_swing_lev(struct btc_coexist *btcoexist, - u8 dac_swing_lvl) -{ - u8 h2c_parameter[1] = {0}; - - /* There are several type of dacswing - * 0x18/ 0x10/ 0xc/ 0x8/ 0x4/ 0x6 - */ - h2c_parameter[0] = dac_swing_lvl; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], Set Dac Swing Level = 0x%x\n", dac_swing_lvl); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x64 = 0x%x\n", h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x64, 1, h2c_parameter); -} - -static void halbtc8821a2ant_set_fw_dec_bt_pwr(struct btc_coexist *btcoexist, - bool dec_bt_pwr) -{ - u8 h2c_parameter[1] = {0}; - - h2c_parameter[0] = 0; - - if (dec_bt_pwr) - h2c_parameter[0] |= BIT1; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], decrease Bt Power : %s, FW write 0x62 = 0x%x\n", - (dec_bt_pwr ? "Yes!!" : "No!!"), h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x62, 1, h2c_parameter); -} - -static void halbtc8821a2ant_dec_bt_pwr(struct btc_coexist *btcoexist, - bool force_exec, bool dec_bt_pwr) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s Dec BT power = %s\n", - (force_exec ? "force to" : ""), - ((dec_bt_pwr) ? "ON" : "OFF")); - coex_dm->cur_dec_bt_pwr = dec_bt_pwr; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_dec_bt_pwr = %d, cur_dec_bt_pwr = %d\n", - coex_dm->pre_dec_bt_pwr, coex_dm->cur_dec_bt_pwr); - - if (coex_dm->pre_dec_bt_pwr == coex_dm->cur_dec_bt_pwr) - return; - } - halbtc8821a2ant_set_fw_dec_bt_pwr(btcoexist, coex_dm->cur_dec_bt_pwr); - - coex_dm->pre_dec_bt_pwr = coex_dm->cur_dec_bt_pwr; -} - -static void btc8821a2ant_set_fw_bt_lna_constr(struct btc_coexist *btcoexist, - bool bt_lna_cons_on) -{ - u8 h2c_parameter[2] = {0}; - - h2c_parameter[0] = 0x3; /* opCode, 0x3 = BT_SET_LNA_CONSTRAIN */ - - if (bt_lna_cons_on) - h2c_parameter[1] |= BIT0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set BT LNA Constrain: %s, FW write 0x69 = 0x%x\n", - (bt_lna_cons_on ? "ON!!" : "OFF!!"), - h2c_parameter[0]<<8|h2c_parameter[1]); - - btcoexist->btc_fill_h2c(btcoexist, 0x69, 2, h2c_parameter); -} - -static void btc8821a2_set_bt_lna_const(struct btc_coexist *btcoexist, - bool force_exec, bool bt_lna_cons_on) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s BT Constrain = %s\n", - (force_exec ? "force" : ""), - ((bt_lna_cons_on) ? "ON" : "OFF")); - coex_dm->cur_bt_lna_constrain = bt_lna_cons_on; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_bt_lna_constrain = %d,cur_bt_lna_constrain = %d\n", - coex_dm->pre_bt_lna_constrain, - coex_dm->cur_bt_lna_constrain); - - if (coex_dm->pre_bt_lna_constrain == - coex_dm->cur_bt_lna_constrain) - return; - } - btc8821a2ant_set_fw_bt_lna_constr(btcoexist, - coex_dm->cur_bt_lna_constrain); - - coex_dm->pre_bt_lna_constrain = coex_dm->cur_bt_lna_constrain; -} - -static void halbtc8821a2ant_set_fw_bt_psd_mode(struct btc_coexist *btcoexist, - u8 bt_psd_mode) -{ - u8 h2c_parameter[2] = {0}; - - h2c_parameter[0] = 0x2; /* opCode, 0x2 = BT_SET_PSD_MODE */ - - h2c_parameter[1] = bt_psd_mode; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set BT PSD mode = 0x%x, FW write 0x69 = 0x%x\n", - h2c_parameter[1], - h2c_parameter[0]<<8|h2c_parameter[1]); - - btcoexist->btc_fill_h2c(btcoexist, 0x69, 2, h2c_parameter); -} - -static void halbtc8821a2ant_set_bt_psd_mode(struct btc_coexist *btcoexist, - bool force_exec, u8 bt_psd_mode) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s BT PSD mode = 0x%x\n", - (force_exec ? "force" : ""), bt_psd_mode); - coex_dm->cur_bt_psd_mode = bt_psd_mode; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_bt_psd_mode = 0x%x, cur_bt_psd_mode = 0x%x\n", - coex_dm->pre_bt_psd_mode, coex_dm->cur_bt_psd_mode); - - if (coex_dm->pre_bt_psd_mode == coex_dm->cur_bt_psd_mode) - return; - } - halbtc8821a2ant_set_fw_bt_psd_mode(btcoexist, - coex_dm->cur_bt_psd_mode); - - coex_dm->pre_bt_psd_mode = coex_dm->cur_bt_psd_mode; -} - -static void halbtc8821a2ant_set_bt_auto_report(struct btc_coexist *btcoexist, - bool enable_auto_report) -{ - u8 h2c_parameter[1] = {0}; - - h2c_parameter[0] = 0; - - if (enable_auto_report) - h2c_parameter[0] |= BIT0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], BT FW auto report : %s, FW write 0x68 = 0x%x\n", - (enable_auto_report ? "Enabled!!" : "Disabled!!"), - h2c_parameter[0]); - - btcoexist->btc_fill_h2c(btcoexist, 0x68, 1, h2c_parameter); -} - -static void halbtc8821a2ant_bt_auto_report(struct btc_coexist *btcoexist, - bool force_exec, - bool enable_auto_report) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s BT Auto report = %s\n", - (force_exec ? "force to" : ""), - ((enable_auto_report) ? "Enabled" : "Disabled")); - coex_dm->cur_bt_auto_report = enable_auto_report; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_bt_auto_report = %d, cur_bt_auto_report = %d\n", - coex_dm->pre_bt_auto_report, - coex_dm->cur_bt_auto_report); - - if (coex_dm->pre_bt_auto_report == coex_dm->cur_bt_auto_report) - return; - } - halbtc8821a2ant_set_bt_auto_report(btcoexist, - coex_dm->cur_bt_auto_report); - - coex_dm->pre_bt_auto_report = coex_dm->cur_bt_auto_report; -} - -static void halbtc8821a2ant_fw_dac_swing_lvl(struct btc_coexist *btcoexist, - bool force_exec, - u8 fw_dac_swing_lvl) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s set FW Dac Swing level = %d\n", - (force_exec ? "force to" : ""), fw_dac_swing_lvl); - coex_dm->cur_fw_dac_swing_lvl = fw_dac_swing_lvl; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_fw_dac_swing_lvl = %d, cur_fw_dac_swing_lvl = %d\n", - coex_dm->pre_fw_dac_swing_lvl, - coex_dm->cur_fw_dac_swing_lvl); - - if (coex_dm->pre_fw_dac_swing_lvl == - coex_dm->cur_fw_dac_swing_lvl) - return; - } - - btc8821a2ant_set_fw_dac_swing_lev(btcoexist, - coex_dm->cur_fw_dac_swing_lvl); - - coex_dm->pre_fw_dac_swing_lvl = coex_dm->cur_fw_dac_swing_lvl; -} - -static void btc8821a2ant_set_sw_rf_rx_lpf_corner(struct btc_coexist *btcoexist, - bool rx_rf_shrink_on) -{ - if (rx_rf_shrink_on) { - /* Shrink RF Rx LPF corner */ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Shrink RF Rx LPF corner!!\n"); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, 0x1e, - 0xfffff, 0xffffc); - } else { - /* Resume RF Rx LPF corner - * After initialized, we can use coex_dm->bt_rf0x1e_backup - */ - if (btcoexist->initilized) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Resume RF Rx LPF corner!!\n"); - btcoexist->btc_set_rf_reg(btcoexist, BTC_RF_A, - 0x1e, 0xfffff, - coex_dm->bt_rf0x1e_backup); - } - } -} - -static void halbtc8821a2ant_RfShrink(struct btc_coexist *btcoexist, - bool force_exec, bool rx_rf_shrink_on) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn Rx RF Shrink = %s\n", - (force_exec ? "force to" : ""), - ((rx_rf_shrink_on) ? "ON" : "OFF")); - coex_dm->cur_rf_rx_lpf_shrink = rx_rf_shrink_on; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], pre_rf_rx_lpf_shrink = %d, cur_rf_rx_lpf_shrink = %d\n", - coex_dm->pre_rf_rx_lpf_shrink, - coex_dm->cur_rf_rx_lpf_shrink); - - if (coex_dm->pre_rf_rx_lpf_shrink == - coex_dm->cur_rf_rx_lpf_shrink) - return; - } - btc8821a2ant_set_sw_rf_rx_lpf_corner(btcoexist, - coex_dm->cur_rf_rx_lpf_shrink); - - coex_dm->pre_rf_rx_lpf_shrink = coex_dm->cur_rf_rx_lpf_shrink; -} - -static void btc8821a2ant_SetSwPenTxRateAdapt(struct btc_coexist *btcoexist, - bool low_penalty_ra) -{ - u8 h2c_parameter[6] = {0}; - - h2c_parameter[0] = 0x6; /* opCode, 0x6 = Retry_Penalty */ - - if (low_penalty_ra) { - h2c_parameter[1] |= BIT0; - /*normal rate except MCS7/6/5, OFDM54/48/36 */ - h2c_parameter[2] = 0x00; - /*MCS7 or OFDM54 */ - h2c_parameter[3] = 0xf7; - /*MCS6 or OFDM48 */ - h2c_parameter[4] = 0xf8; - /*MCS5 or OFDM36 */ - h2c_parameter[5] = 0xf9; - } - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set WiFi Low-Penalty Retry: %s", - (low_penalty_ra ? "ON!!" : "OFF!!")); - - btcoexist->btc_fill_h2c(btcoexist, 0x69, 6, h2c_parameter); -} - -static void halbtc8821a2ant_low_penalty_ra(struct btc_coexist *btcoexist, - bool force_exec, bool low_penalty_ra) -{ - /*return;*/ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn LowPenaltyRA = %s\n", - (force_exec ? "force to" : ""), - ((low_penalty_ra) ? "ON" : "OFF")); - coex_dm->cur_low_penalty_ra = low_penalty_ra; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], pre_low_penalty_ra = %d, cur_low_penalty_ra = %d\n", - coex_dm->pre_low_penalty_ra, - coex_dm->cur_low_penalty_ra); - - if (coex_dm->pre_low_penalty_ra == coex_dm->cur_low_penalty_ra) - return; - } - btc8821a2ant_SetSwPenTxRateAdapt(btcoexist, - coex_dm->cur_low_penalty_ra); - - coex_dm->pre_low_penalty_ra = coex_dm->cur_low_penalty_ra; -} - -static void halbtc8821a2ant_set_dac_swing_reg(struct btc_coexist *btcoexist, - u32 level) -{ - u8 val = (u8)level; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], Write SwDacSwing = 0x%x\n", level); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0xc5b, 0x3e, val); -} - -static void btc8821a2ant_set_sw_full_dac_swing(struct btc_coexist *btcoexist, - bool sw_dac_swing_on, - u32 sw_dac_swing_lvl) -{ - if (sw_dac_swing_on) - halbtc8821a2ant_set_dac_swing_reg(btcoexist, sw_dac_swing_lvl); - else - halbtc8821a2ant_set_dac_swing_reg(btcoexist, 0x18); -} - -static void halbtc8821a2ant_dac_swing(struct btc_coexist *btcoexist, - bool force_exec, bool dac_swing_on, - u32 dac_swing_lvl) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn DacSwing = %s, dac_swing_lvl = 0x%x\n", - (force_exec ? "force to" : ""), - ((dac_swing_on) ? "ON" : "OFF"), - dac_swing_lvl); - coex_dm->cur_dac_swing_on = dac_swing_on; - coex_dm->cur_dac_swing_lvl = dac_swing_lvl; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], pre_dac_swing_on = %d, pre_dac_swing_lvl = 0x%x, cur_dac_swing_on = %d, cur_dac_swing_lvl = 0x%x\n", - coex_dm->pre_dac_swing_on, - coex_dm->pre_dac_swing_lvl, - coex_dm->cur_dac_swing_on, - coex_dm->cur_dac_swing_lvl); - - if ((coex_dm->pre_dac_swing_on == coex_dm->cur_dac_swing_on) && - (coex_dm->pre_dac_swing_lvl == - coex_dm->cur_dac_swing_lvl)) - return; - } - mdelay(30); - btc8821a2ant_set_sw_full_dac_swing(btcoexist, dac_swing_on, - dac_swing_lvl); - - coex_dm->pre_dac_swing_on = coex_dm->cur_dac_swing_on; - coex_dm->pre_dac_swing_lvl = coex_dm->cur_dac_swing_lvl; -} - -static void halbtc8821a2ant_set_adc_back_off(struct btc_coexist *btcoexist, - bool adc_back_off) -{ - if (adc_back_off) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], BB BackOff Level On!\n"); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x8db, 0x60, 0x3); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], BB BackOff Level Off!\n"); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x8db, 0x60, 0x1); - } -} - -static void halbtc8821a2ant_adc_back_off(struct btc_coexist *btcoexist, - bool force_exec, bool adc_back_off) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s turn AdcBackOff = %s\n", - (force_exec ? "force to" : ""), - ((adc_back_off) ? "ON" : "OFF")); - coex_dm->cur_adc_back_off = adc_back_off; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], pre_adc_back_off = %d, cur_adc_back_off = %d\n", - coex_dm->pre_adc_back_off, coex_dm->cur_adc_back_off); - - if (coex_dm->pre_adc_back_off == coex_dm->cur_adc_back_off) - return; - } - halbtc8821a2ant_set_adc_back_off(btcoexist, coex_dm->cur_adc_back_off); - - coex_dm->pre_adc_back_off = coex_dm->cur_adc_back_off; -} - -static void halbtc8821a2ant_set_coex_table(struct btc_coexist *btcoexist, - u32 val0x6c0, u32 val0x6c4, - u32 val0x6c8, u8 val0x6cc) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c0 = 0x%x\n", val0x6c0); - btcoexist->btc_write_4byte(btcoexist, 0x6c0, val0x6c0); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c4 = 0x%x\n", val0x6c4); - btcoexist->btc_write_4byte(btcoexist, 0x6c4, val0x6c4); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6c8 = 0x%x\n", val0x6c8); - btcoexist->btc_write_4byte(btcoexist, 0x6c8, val0x6c8); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_EXEC, - "[BTCoex], set coex table, set 0x6cc = 0x%x\n", val0x6cc); - btcoexist->btc_write_1byte(btcoexist, 0x6cc, val0x6cc); -} - -static void halbtc8821a2ant_coex_table(struct btc_coexist *btcoexist, - bool force_exec, u32 val0x6c0, - u32 val0x6c4, u32 val0x6c8, u8 val0x6cc) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW, - "[BTCoex], %s write Coex Table 0x6c0 = 0x%x, 0x6c4 = 0x%x, 0x6c8 = 0x%x, 0x6cc = 0x%x\n", - (force_exec ? "force to" : ""), - val0x6c0, val0x6c4, val0x6c8, val0x6cc); - coex_dm->cur_val0x6c0 = val0x6c0; - coex_dm->cur_val0x6c4 = val0x6c4; - coex_dm->cur_val0x6c8 = val0x6c8; - coex_dm->cur_val0x6cc = val0x6cc; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], pre_val0x6c0 = 0x%x, pre_val0x6c4 = 0x%x, pre_val0x6c8 = 0x%x, pre_val0x6cc = 0x%x !!\n", - coex_dm->pre_val0x6c0, - coex_dm->pre_val0x6c4, - coex_dm->pre_val0x6c8, - coex_dm->pre_val0x6cc); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_SW_DETAIL, - "[BTCoex], cur_val0x6c0 = 0x%x, cur_val0x6c4 = 0x%x, cur_val0x6c8 = 0x%x, cur_val0x6cc = 0x%x !!\n", - coex_dm->cur_val0x6c0, - coex_dm->cur_val0x6c4, - coex_dm->cur_val0x6c8, - coex_dm->cur_val0x6cc); - - if ((coex_dm->pre_val0x6c0 == coex_dm->cur_val0x6c0) && - (coex_dm->pre_val0x6c4 == coex_dm->cur_val0x6c4) && - (coex_dm->pre_val0x6c8 == coex_dm->cur_val0x6c8) && - (coex_dm->pre_val0x6cc == coex_dm->cur_val0x6cc)) - return; - } - halbtc8821a2ant_set_coex_table(btcoexist, val0x6c0, val0x6c4, val0x6c8, - val0x6cc); - - coex_dm->pre_val0x6c0 = coex_dm->cur_val0x6c0; - coex_dm->pre_val0x6c4 = coex_dm->cur_val0x6c4; - coex_dm->pre_val0x6c8 = coex_dm->cur_val0x6c8; - coex_dm->pre_val0x6cc = coex_dm->cur_val0x6cc; -} - -static void halbtc8821a2ant_set_fw_ignore_wlan_act(struct btc_coexist *btcoex, - bool enable) -{ - u8 h2c_parameter[1] = {0}; - - if (enable) - h2c_parameter[0] |= BIT0;/* function enable */ - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], set FW for BT Ignore Wlan_Act, FW write 0x63 = 0x%x\n", - h2c_parameter[0]); - - btcoex->btc_fill_h2c(btcoex, 0x63, 1, h2c_parameter); -} - -static void halbtc8821a2ant_ignore_wlan_act(struct btc_coexist *btcoexist, - bool force_exec, bool enable) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn Ignore WlanAct %s\n", - (force_exec ? "force to" : ""), (enable ? "ON" : "OFF")); - coex_dm->cur_ignore_wlan_act = enable; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_ignore_wlan_act = %d, cur_ignore_wlan_act = %d!!\n", - coex_dm->pre_ignore_wlan_act, - coex_dm->cur_ignore_wlan_act); - - if (coex_dm->pre_ignore_wlan_act == - coex_dm->cur_ignore_wlan_act) - return; - } - halbtc8821a2ant_set_fw_ignore_wlan_act(btcoexist, enable); - - coex_dm->pre_ignore_wlan_act = coex_dm->cur_ignore_wlan_act; -} - -static void halbtc8821a2ant_set_fw_pstdma(struct btc_coexist *btcoexist, - u8 byte1, u8 byte2, u8 byte3, - u8 byte4, u8 byte5) -{ - u8 h2c_parameter[5]; - - h2c_parameter[0] = byte1; - h2c_parameter[1] = byte2; - h2c_parameter[2] = byte3; - h2c_parameter[3] = byte4; - h2c_parameter[4] = byte5; - - coex_dm->ps_tdma_para[0] = byte1; - coex_dm->ps_tdma_para[1] = byte2; - coex_dm->ps_tdma_para[2] = byte3; - coex_dm->ps_tdma_para[3] = byte4; - coex_dm->ps_tdma_para[4] = byte5; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x60(5bytes) = 0x%x%08x\n", - h2c_parameter[0], - h2c_parameter[1]<<24| - h2c_parameter[2]<<16| - h2c_parameter[3]<<8| - h2c_parameter[4]); - - btcoexist->btc_fill_h2c(btcoexist, 0x60, 5, h2c_parameter); -} - -static void btc8821a2ant_sw_mech1(struct btc_coexist *btcoexist, - bool shrink_rx_lpf, - bool low_penalty_ra, bool limited_dig, - bool bt_lna_constrain) -{ - u32 wifi_bw; - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (BTC_WIFI_BW_HT40 != wifi_bw) { - /*only shrink RF Rx LPF for HT40*/ - if (shrink_rx_lpf) - shrink_rx_lpf = false; - } - - halbtc8821a2ant_RfShrink(btcoexist, NORMAL_EXEC, shrink_rx_lpf); - halbtc8821a2ant_low_penalty_ra(btcoexist, - NORMAL_EXEC, low_penalty_ra); - - /* no limited DIG - * btc8821a2_set_bt_lna_const(btcoexist, - NORMAL_EXEC, bBTLNAConstrain); - */ -} - -static void btc8821a2ant_sw_mech2(struct btc_coexist *btcoexist, - bool agc_table_shift, - bool adc_back_off, bool sw_dac_swing, - u32 dac_swing_lvl) -{ - /* halbtc8821a2ant_AgcTable(btcoexist, NORMAL_EXEC, bAGCTableShift); */ - halbtc8821a2ant_adc_back_off(btcoexist, NORMAL_EXEC, adc_back_off); - halbtc8821a2ant_dac_swing(btcoexist, NORMAL_EXEC, sw_dac_swing, - sw_dac_swing); -} - -static void halbtc8821a2ant_set_ant_path(struct btc_coexist *btcoexist, - u8 ant_pos_type, bool init_hw_cfg, - bool wifi_off) -{ - struct btc_board_info *board_info = &btcoexist->board_info; - u32 u4tmp = 0; - u8 h2c_parameter[2] = {0}; - - if (init_hw_cfg) { - /* 0x4c[23] = 0, 0x4c[24] = 1 Antenna control by WL/BT */ - u4tmp = btcoexist->btc_read_4byte(btcoexist, 0x4c); - u4tmp &= ~BIT23; - u4tmp |= BIT24; - btcoexist->btc_write_4byte(btcoexist, 0x4c, u4tmp); - - btcoexist->btc_write_4byte(btcoexist, 0x974, 0x3ff); - btcoexist->btc_write_1byte(btcoexist, 0xcb4, 0x77); - - if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) { - /* tell firmware "antenna inverse" ==> - * WRONG firmware antenna control code. - * ==>need fw to fix - */ - h2c_parameter[0] = 1; - h2c_parameter[1] = 1; - btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, - h2c_parameter); - } else { - /* tell firmware "no antenna inverse" - * ==> WRONG firmware antenna control code. - * ==>need fw to fix - */ - h2c_parameter[0] = 0; - h2c_parameter[1] = 1; - btcoexist->btc_fill_h2c(btcoexist, 0x65, 2, - h2c_parameter); - } - } - - /* ext switch setting */ - switch (ant_pos_type) { - case BTC_ANT_WIFI_AT_MAIN: - btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, 0x30, 0x1); - break; - case BTC_ANT_WIFI_AT_AUX: - btcoexist->btc_write_1byte_bitmask(btcoexist, 0xcb7, 0x30, 0x2); - break; - } -} - -static void halbtc8821a2ant_ps_tdma(struct btc_coexist *btcoexist, - bool force_exec, bool turn_on, u8 type) -{ - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], %s turn %s PS TDMA, type = %d\n", - (force_exec ? "force to" : ""), (turn_on ? "ON" : "OFF"), - type); - coex_dm->cur_ps_tdma_on = turn_on; - coex_dm->cur_ps_tdma = type; - - if (!force_exec) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_ps_tdma_on = %d, cur_ps_tdma_on = %d!!\n", - coex_dm->pre_ps_tdma_on, coex_dm->cur_ps_tdma_on); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], pre_ps_tdma = %d, cur_ps_tdma = %d!!\n", - coex_dm->pre_ps_tdma, coex_dm->cur_ps_tdma); - - if ((coex_dm->pre_ps_tdma_on == coex_dm->cur_ps_tdma_on) && - (coex_dm->pre_ps_tdma == coex_dm->cur_ps_tdma)) - return; - } - if (turn_on) { - switch (type) { - case 1: - default: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0xe1, 0x90); - break; - case 2: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x12, - 0x12, 0xe1, 0x90); - break; - case 3: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1c, - 0x3, 0xf1, 0x90); - break; - case 4: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x10, - 0x03, 0xf1, 0x90); - break; - case 5: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0x60, 0x90); - break; - case 6: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x12, - 0x12, 0x60, 0x90); - break; - case 7: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1c, - 0x3, 0x70, 0x90); - break; - case 8: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xa3, 0x10, - 0x3, 0x70, 0x90); - break; - case 9: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0xe1, 0x90); - break; - case 10: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x12, - 0x12, 0xe1, 0x90); - break; - case 11: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0xa, - 0xa, 0xe1, 0x90); - break; - case 12: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x5, - 0x5, 0xe1, 0x90); - break; - case 13: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0x60, 0x90); - break; - case 14: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, - 0x12, 0x12, 0x60, 0x90); - break; - case 15: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0xa, - 0xa, 0x60, 0x90); - break; - case 16: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x5, - 0x5, 0x60, 0x90); - break; - case 17: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xa3, 0x2f, - 0x2f, 0x60, 0x90); - break; - case 18: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x5, - 0x5, 0xe1, 0x90); - break; - case 19: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x25, - 0x25, 0xe1, 0x90); - break; - case 20: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x25, - 0x25, 0x60, 0x90); - break; - case 21: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x15, - 0x03, 0x70, 0x90); - break; - case 71: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0xe3, 0x1a, - 0x1a, 0xe1, 0x90); - break; - } - } else { - /* disable PS tdma */ - switch (type) { - case 0: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0x0, 0x0, 0x0, - 0x40, 0x0); - break; - case 1: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0x0, 0x0, 0x0, - 0x48, 0x0); - break; - default: - halbtc8821a2ant_set_fw_pstdma(btcoexist, 0x0, 0x0, 0x0, - 0x40, 0x0); - break; - } - } - - /* update pre state */ - coex_dm->pre_ps_tdma_on = coex_dm->cur_ps_tdma_on; - coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; -} - -static void halbtc8821a2ant_coex_all_off(struct btc_coexist *btcoexist) -{ - /* fw all off */ - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - /* sw all off */ - btc8821a2ant_sw_mech1(btcoexist, false, false, false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, false, 0x18); - - /* hw all off */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, - 0x55555555, 0x55555555, 0xffff, 0x3); -} - -static void halbtc8821a2ant_coex_under_5g(struct btc_coexist *btcoexist) -{ - halbtc8821a2ant_coex_all_off(btcoexist); -} - -static void halbtc8821a2ant_init_coex_dm(struct btc_coexist *btcoexist) -{ - /* force to reset coex mechanism */ - halbtc8821a2ant_coex_table(btcoexist, FORCE_EXEC, 0x55555555, - 0x55555555, 0xffff, 0x3); - - halbtc8821a2ant_ps_tdma(btcoexist, FORCE_EXEC, false, 1); - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, FORCE_EXEC, 6); - halbtc8821a2ant_dec_bt_pwr(btcoexist, FORCE_EXEC, false); - - btc8821a2ant_sw_mech1(btcoexist, false, false, false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, false, 0x18); -} - -static void halbtc8821a2ant_bt_inquiry_page(struct btc_coexist *btcoexist) -{ - bool low_pwr_disable = true; - - btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5afa5afa, 0xffff, 0x3); - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 3); -} - -static bool halbtc8821a2ant_is_common_action(struct btc_coexist *btcoexist) -{ - bool common = false, wifi_connected = false, wifi_busy = false; - bool low_pwr_disable = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5afa5afa, 0xffff, 0x3); - - if (!wifi_connected && - BT_8821A_2ANT_BT_STATUS_IDLE == coex_dm->bt_status) { - low_pwr_disable = false; - btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi IPS + BT IPS!!\n"); - - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btc8821a2ant_sw_mech1(btcoexist, false, false, false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, false, 0x18); - - common = true; - } else if (wifi_connected && - (BT_8821A_2ANT_BT_STATUS_IDLE == coex_dm->bt_status)) { - low_pwr_disable = false; - btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - if (wifi_busy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Busy + BT IPS!!\n"); - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 1); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi LPS + BT IPS!!\n"); - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 1); - } - - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btc8821a2ant_sw_mech1(btcoexist, false, false, false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, false, 0x18); - - common = true; - } else if (!wifi_connected && - (BT_8821A_2ANT_BT_STATUS_CON_IDLE == coex_dm->bt_status)) { - low_pwr_disable = true; - btcoexist->btc_set(btcoexist, BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi IPS + BT LPS!!\n"); - - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btc8821a2ant_sw_mech1(btcoexist, false, false, false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, false, 0x18); - common = true; - } else if (wifi_connected && - (BT_8821A_2ANT_BT_STATUS_CON_IDLE == coex_dm->bt_status)) { - low_pwr_disable = true; - btcoexist->btc_set(btcoexist, - BTC_SET_ACT_DISABLE_LOW_POWER, &low_pwr_disable); - - if (wifi_busy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Busy + BT LPS!!\n"); - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 1); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi LPS + BT LPS!!\n"); - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 1); - } - - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btc8821a2ant_sw_mech1(btcoexist, true, true, true, true); - btc8821a2ant_sw_mech2(btcoexist, false, false, false, 0x18); - - common = true; - } else if (!wifi_connected && - (BT_8821A_2ANT_BT_STATUS_NON_IDLE == - coex_dm->bt_status)) { - low_pwr_disable = false; - btcoexist->btc_set(btcoexist, - BTC_SET_ACT_DISABLE_LOW_POWER, &low_pwr_disable); - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi IPS + BT Busy!!\n"); - - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btc8821a2ant_sw_mech1(btcoexist, false, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - - common = true; - } else { - low_pwr_disable = true; - btcoexist->btc_set(btcoexist, - BTC_SET_ACT_DISABLE_LOW_POWER, - &low_pwr_disable); - - if (wifi_busy) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi Busy + BT Busy!!\n"); - common = false; - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Wifi LPS + BT Busy!!\n"); - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, true, 21); - - if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) - halbtc8821a2ant_dec_bt_pwr(btcoexist, - NORMAL_EXEC, true); - else - halbtc8821a2ant_dec_bt_pwr(btcoexist, - NORMAL_EXEC, false); - - common = true; - } - btc8821a2ant_sw_mech1(btcoexist, true, true, true, true); - } - return common; -} - -static void btc8821a2_int1(struct btc_coexist *btcoexist, bool tx_pause, - int result) -{ - if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); - - if (coex_dm->cur_ps_tdma == 71) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - coex_dm->tdma_adj_type = 5; - } else if (coex_dm->cur_ps_tdma == 1) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - coex_dm->tdma_adj_type = 5; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 4) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } - if (coex_dm->cur_ps_tdma == 9) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 13); - coex_dm->tdma_adj_type = 13; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 12) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - - if (result == -1) { - if (coex_dm->cur_ps_tdma == 5) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } else if (coex_dm->cur_ps_tdma == 13) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 8) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - coex_dm->tdma_adj_type = 5; - } else if (coex_dm->cur_ps_tdma == 16) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 13); - coex_dm->tdma_adj_type = 13; - } - } - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); - if (coex_dm->cur_ps_tdma == 5) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 71); - coex_dm->tdma_adj_type = 71; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 8) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } - if (coex_dm->cur_ps_tdma == 13) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 16) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - - if (result == -1) { - if (coex_dm->cur_ps_tdma == 71) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 1); - coex_dm->tdma_adj_type = 1; - } else if (coex_dm->cur_ps_tdma == 1) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } else if (coex_dm->cur_ps_tdma == 9) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 4) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 1); - coex_dm->tdma_adj_type = 1; - } else if (coex_dm->cur_ps_tdma == 1) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 71); - coex_dm->tdma_adj_type = 71; - } else if (coex_dm->cur_ps_tdma == 12) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } - } - } -} - -static void btc8821a2_int2(struct btc_coexist *btcoexist, bool tx_pause, - int result) -{ - if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); - if (coex_dm->cur_ps_tdma == 1) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 4) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } - if (coex_dm->cur_ps_tdma == 9) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 12) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - if (result == -1) { - if (coex_dm->cur_ps_tdma == 5) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } else if (coex_dm->cur_ps_tdma == 13) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 8) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (coex_dm->cur_ps_tdma == 16) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } - } - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); - if (coex_dm->cur_ps_tdma == 5) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 8) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } - if (coex_dm->cur_ps_tdma == 13) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 16) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - if (result == -1) { - if (coex_dm->cur_ps_tdma == 1) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } else if (coex_dm->cur_ps_tdma == 9) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 4) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (coex_dm->cur_ps_tdma == 12) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } - } - } -} - -static void btc8821a2_int3(struct btc_coexist *btcoexist, bool tx_pause, - int result) -{ - if (tx_pause) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 1\n"); - if (coex_dm->cur_ps_tdma == 1) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 4) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } - if (coex_dm->cur_ps_tdma == 9) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 12) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - if (result == -1) { - if (coex_dm->cur_ps_tdma == 5) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 8); - coex_dm->tdma_adj_type = 8; - } else if (coex_dm->cur_ps_tdma == 13) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 16); - coex_dm->tdma_adj_type = 16; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 8) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else if (coex_dm->cur_ps_tdma == 16) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } - } - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], TxPause = 0\n"); - if (coex_dm->cur_ps_tdma == 5) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 6) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 7) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 8) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } - if (coex_dm->cur_ps_tdma == 13) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 14) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 15) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 16) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - if (result == -1) { - if (coex_dm->cur_ps_tdma == 1) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 4); - coex_dm->tdma_adj_type = 4; - } else if (coex_dm->cur_ps_tdma == 9) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 12); - coex_dm->tdma_adj_type = 12; - } - } else if (result == 1) { - if (coex_dm->cur_ps_tdma == 4) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else if (coex_dm->cur_ps_tdma == 12) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 11) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else if (coex_dm->cur_ps_tdma == 10) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } - } - } -} - -static void btc8821a2ant_tdma_dur_adj(struct btc_coexist *btcoexist, - bool sco_hid, bool tx_pause, - u8 max_interval) -{ - static long up, dn, m, n, wait_count; - /* 0: no change, +1: increase WiFi duration, - * -1: decrease WiFi duration - */ - int result; - u8 retry_count = 0; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW, - "[BTCoex], TdmaDurationAdjust()\n"); - - if (coex_dm->reset_tdma_adjust) { - coex_dm->reset_tdma_adjust = false; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], first run TdmaDurationAdjust()!!\n"); - if (sco_hid) { - if (tx_pause) { - if (max_interval == 1) { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 13); - coex_dm->tdma_adj_type = 13; - } else if (max_interval == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 14); - coex_dm->tdma_adj_type = 14; - } else if (max_interval == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } else { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 15); - coex_dm->tdma_adj_type = 15; - } - } else { - if (max_interval == 1) { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 9); - coex_dm->tdma_adj_type = 9; - } else if (max_interval == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 10); - coex_dm->tdma_adj_type = 10; - } else if (max_interval == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } else { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 11); - coex_dm->tdma_adj_type = 11; - } - } - } else { - if (tx_pause) { - if (max_interval == 1) { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 5); - coex_dm->tdma_adj_type = 5; - } else if (max_interval == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 6); - coex_dm->tdma_adj_type = 6; - } else if (max_interval == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } else { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 7); - coex_dm->tdma_adj_type = 7; - } - } else { - if (max_interval == 1) { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 1); - coex_dm->tdma_adj_type = 1; - } else if (max_interval == 2) { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 2); - coex_dm->tdma_adj_type = 2; - } else if (max_interval == 3) { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } else { - halbtc8821a2ant_ps_tdma(btcoexist, - NORMAL_EXEC, - true, 3); - coex_dm->tdma_adj_type = 3; - } - } - } - - up = 0; - dn = 0; - m = 1; - n = 3; - result = 0; - wait_count = 0; - } else { - /* accquire the BT TRx retry count from BT_Info byte2 */ - retry_count = coex_sta->bt_retry_cnt; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], retry_count = %d\n", retry_count); - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], up = %d, dn = %d, m = %d, n = %d, wait_count = %d\n", - (int)up, (int)dn, (int)m, (int)n, (int)wait_count); - result = 0; - wait_count++; - - if (retry_count == 0) { - /* no retry in the last 2-second duration */ - up++; - dn--; - - if (dn <= 0) - dn = 0; - - if (up >= n) { - /* if (retry count == 0) for 2*n seconds, - * make WiFi duration wider - */ - wait_count = 0; - n = 3; - up = 0; - dn = 0; - result = 1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Increase wifi duration!!\n"); - } - } else if (retry_count <= 3) { - /* <=3 retry in the last 2-second duration */ - up--; - dn++; - - if (up <= 0) - up = 0; - - if (dn == 2) { - /* if retry count< 3 for 2*2 seconds, - * shrink wifi duration - */ - if (wait_count <= 2) - m++; /* avoid bounce in two levels */ - else - m = 1; - /* m max value is 20, max time is 120 second, - * recheck if adjust WiFi duration. - */ - if (m >= 20) - m = 20; - - n = 3*m; - up = 0; - dn = 0; - wait_count = 0; - result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, - ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration for retryCounter<3!!\n"); - } - } else { - /* retry count > 3, if retry count > 3 happens once, - * shrink WiFi duration - */ - if (wait_count == 1) - m++; /* avoid bounce in two levels */ - else - m = 1; - /* m max value is 20, max time is 120 second, - * recheck if adjust WiFi duration. - */ - if (m >= 20) - m = 20; - - n = 3*m; - up = 0; - dn = 0; - wait_count = 0; - result = -1; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], Decrease wifi duration for retryCounter>3!!\n"); - } - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], max Interval = %d\n", max_interval); - if (max_interval == 1) - btc8821a2_int1(btcoexist, tx_pause, result); - else if (max_interval == 2) - btc8821a2_int2(btcoexist, tx_pause, result); - else if (max_interval == 3) - btc8821a2_int3(btcoexist, tx_pause, result); - } - - /* if current PsTdma not match with the recorded one - * (when scan, dhcp...), then we have to adjust it back to - * the previous recorded one. - */ - if (coex_dm->cur_ps_tdma != coex_dm->tdma_adj_type) { - bool scan = false, link = false, roam = false; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], PsTdma type dismatch!!!, cur_ps_tdma = %d, recordPsTdma = %d\n", - coex_dm->cur_ps_tdma, coex_dm->tdma_adj_type); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); - - if (!scan && !link && !roam) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, - coex_dm->tdma_adj_type); - } else { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_DETAIL, - "[BTCoex], roaming/link/scan is under progress, will adjust next time!!!\n"); - } - } - - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 0x6); -} - -/* SCO only or SCO+PAN(HS)*/ -static void halbtc8821a2ant_action_sco(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, - 15, 0); - bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); - - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 4); - - if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (BTC_WIFI_BW_LEGACY == wifi_bw) { - /* for SCO quality at 11b/g mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, - 0x5a5a5a5a, 0x5a5a5a5a, 0xffff, 0x3); - } else { - /* for SCO quality & wifi performance balance at 11n mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, - 0x5aea5aea, 0x5aea5aea, 0xffff, 0x3); - } - - if (BTC_WIFI_BW_HT40 == wifi_bw) { - /* fw mechanism - * halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); - */ - - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 0); /*for voice quality*/ - } else { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 0); /*for voice quality*/ - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, true, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, true, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } else { - /* fw mechanism - * halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, true, 5); - */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 0); /*for voice quality*/ - } else { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 0); /*for voice quality*/ - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, false, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, false, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void halbtc8821a2ant_action_hid(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); - - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (BTC_WIFI_BW_LEGACY == wifi_bw) { - /* for HID at 11b/g mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5a5a5a5a, 0xffff, 0x3); - } else { - /* for HID quality & wifi performance balance at 11n mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5aea5aea, 0xffff, 0x3); - } - - if (BTC_WIFI_BW_HT40 == wifi_bw) { - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - } else { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 13); - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, true, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, true, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } else { - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 9); - } else { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 13); - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, false, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, false, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } -} - -/* A2DP only / PAN(EDR) only/ A2DP+PAN(HS) */ -static void halbtc8821a2ant_action_a2dp(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, - 15, 0); - bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); - - /* fw dac swing is called in btc8821a2ant_tdma_dur_adj() - * halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - */ - - if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (BTC_WIFI_BW_HT40 == wifi_bw) { - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_tdma_dur_adj(btcoexist, false, false, 1); - } else { - btc8821a2ant_tdma_dur_adj(btcoexist, false, true, 1); - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, true, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, true, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } else { - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_tdma_dur_adj(btcoexist, false, false, 1); - } else { - btc8821a2ant_tdma_dur_adj(btcoexist, false, true, 1); - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, false, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, false, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void halbtc8821a2ant_action_a2dp_pan_hs(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state, bt_info_ext; - u32 wifi_bw; - - bt_info_ext = coex_sta->bt_info_ext; - wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, - 15, 0); - bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); - - /*fw dac swing is called in btc8821a2ant_tdma_dur_adj() - *halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - */ - - if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (BTC_WIFI_BW_HT40 == wifi_bw) { - /* fw mechanism */ - if (bt_info_ext&BIT0) { - /*a2dp basic rate*/ - btc8821a2ant_tdma_dur_adj(btcoexist, false, true, 2); - } else { - /*a2dp edr rate*/ - btc8821a2ant_tdma_dur_adj(btcoexist, false, true, 1); - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, true, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, true, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } else { - /* fw mechanism */ - if (bt_info_ext&BIT0) { - /* a2dp basic rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, false, true, 2); - } else { - /* a2dp edr rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, false, true, 1); - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, false, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, false, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void halbtc8821a2ant_action_pan_edr(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, - 15, 0); - bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); - - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (BTC_WIFI_BW_LEGACY == wifi_bw) { - /* for HID at 11b/g mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5aff5aff, 0xffff, 0x3); - } else { - /* for HID quality & wifi performance balance at 11n mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5aff5aff, 0xffff, 0x3); - } - - if (BTC_WIFI_BW_HT40 == wifi_bw) { - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 1); - } else { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, true, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, true, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } else { - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 1); - } else { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 5); - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, false, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, false, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } -} - -/* PAN(HS) only */ -static void halbtc8821a2ant_action_pan_hs(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); - - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (BTC_WIFI_BW_HT40 == wifi_bw) { - /* fw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, - true); - } else { - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, - false); - } - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, false, 1); - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, true, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, true, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } else { - /* fw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a2ant_dec_bt_pwr(btcoexist, - NORMAL_EXEC, true); - } else { - halbtc8821a2ant_dec_bt_pwr(btcoexist, - NORMAL_EXEC, false); - } - - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 1); - } else { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - false, 1); - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, false, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, false, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } -} - -/* PAN(EDR)+A2DP */ -static void halbtc8821a2ant_action_pan_edr_a2dp(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state, bt_info_ext; - u32 wifi_bw; - - bt_info_ext = coex_sta->bt_info_ext; - wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, - 15, 0); - bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); - - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (BTC_WIFI_BW_LEGACY == wifi_bw) { - /* for HID at 11b/g mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5afa5afa, 0xffff, 0x3); - } else { - /* for HID quality & wifi performance balance at 11n mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5afa5afa, 0xffff, 0x3); - } - - if (BTC_WIFI_BW_HT40 == wifi_bw) { - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - if (bt_info_ext&BIT0) { - /* a2dp basic rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, false, - false, 3); - } else { - /* a2dp edr rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, false, - false, 3); - } - } else { - if (bt_info_ext&BIT0) { - /* a2dp basic rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, false, - true, 3); - } else { - /* a2dp edr rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, false, - true, 3); - } - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, true, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, true, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - }; - } else { - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - if (bt_info_ext&BIT0) { - /* a2dp basic rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, false, - false, 3); - } else { - /* a2dp edr rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, false, - false, 3); - } - } else { - if (bt_info_ext&BIT0) { - /* a2dp basic rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, false, - true, 3); - } else { - /* a2dp edr rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, false, - true, 3); - } - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, false, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, false, false, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void halbtc8821a2ant_action_pan_edr_hid(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state; - u32 wifi_bw; - - wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, - 15, 0); - bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); - - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (BTC_WIFI_BW_LEGACY == wifi_bw) { - /* for HID at 11b/g mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5a5f5a5f, 0xffff, 0x3); - } else { - /* for HID quality & wifi performance balance at 11n mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5a5f5a5f, 0xffff, 0x3); - } - - if (BTC_WIFI_BW_HT40 == wifi_bw) { - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 3); - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - } else { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, true, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, true, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } else { - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 10); - } else { - halbtc8821a2ant_ps_tdma(btcoexist, NORMAL_EXEC, - true, 14); - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, false, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, false, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } -} - -/* HID+A2DP+PAN(EDR) */ -static void btc8821a2ant_act_hid_a2dp_pan_edr(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state, bt_info_ext; - u32 wifi_bw; - - bt_info_ext = coex_sta->bt_info_ext; - wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, - 0, 2, 15, 0); - bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); - - halbtc8821a2ant_fw_dac_swing_lvl(btcoexist, NORMAL_EXEC, 6); - - if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (BTC_WIFI_BW_LEGACY == wifi_bw) { - /* for HID at 11b/g mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5a5a5a5a, 0xffff, 0x3); - } else { - /* for HID quality & wifi performance balance at 11n mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5a5a5a5a, 0xffff, 0x3); - } - - if (BTC_WIFI_BW_HT40 == wifi_bw) { - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - if (bt_info_ext&BIT0) { - /* a2dp basic rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, true, - true, 3); - } else { - /* a2dp edr rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, true, - true, 3); - } - } else { - if (bt_info_ext&BIT0) { - /* a2dp basic rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, true, - true, 3); - } else { - /* a2dp edr rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, true, - true, 3); - } - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, true, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, true, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } else { - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - if (bt_info_ext&BIT0) { - /* a2dp basic rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, true, - false, 3); - } else { - /* a2dp edr rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, true, - false, 3); - } - } else { - if (bt_info_ext&BIT0) { - /* a2dp basic rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, true, - true, 3); - } else { - /* a2dp edr rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, true, - true, 3); - } - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, false, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, false, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void halbtc8821a2ant_action_hid_a2dp(struct btc_coexist *btcoexist) -{ - u8 wifi_rssi_state, bt_rssi_state, bt_info_ext; - u32 wifi_bw; - - bt_info_ext = coex_sta->bt_info_ext; - wifi_rssi_state = halbtc8821a2ant_wifi_rssi_state(btcoexist, 0, 2, - 15, 0); - bt_rssi_state = halbtc8821a2ant_bt_rssi_state(2, 35, 0); - - if (halbtc8821a2ant_need_to_dec_bt_pwr(btcoexist)) - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, true); - else - halbtc8821a2ant_dec_bt_pwr(btcoexist, NORMAL_EXEC, false); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - - if (BTC_WIFI_BW_LEGACY == wifi_bw) { - /* for HID at 11b/g mode */ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5f5b5f5b, 0xffffff, 0x3); - } else { - /*for HID quality & wifi performance balance at 11n mode*/ - halbtc8821a2ant_coex_table(btcoexist, NORMAL_EXEC, 0x55ff55ff, - 0x5f5b5f5b, 0xffffff, 0x3); - } - - if (BTC_WIFI_BW_HT40 == wifi_bw) { - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - if (bt_info_ext&BIT0) { - /* a2dp basic rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, - true, true, 2); - } else { - /* a2dp edr rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, - true, true, 2); - } - } else { - if (bt_info_ext&BIT0) { - /* a2dp basic rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, - true, true, 2); - } else { - /* a2dp edr rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, - true, true, 2); - } - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, true, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, true, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } else { - /* fw mechanism */ - if ((bt_rssi_state == BTC_RSSI_STATE_HIGH) || - (bt_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - if (bt_info_ext&BIT0) { - /* a2dp basic rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, - true, true, 2); - - } else { - /* a2dp edr rate */ - btc8821a2ant_tdma_dur_adj(btcoexist, - true, true, 2); - } - } else { - if (bt_info_ext&BIT0) { - /*a2dp basic rate*/ - btc8821a2ant_tdma_dur_adj(btcoexist, - true, true, 2); - } else { - /*a2dp edr rate*/ - btc8821a2ant_tdma_dur_adj(btcoexist, - true, true, 2); - } - } - - /* sw mechanism */ - if ((wifi_rssi_state == BTC_RSSI_STATE_HIGH) || - (wifi_rssi_state == BTC_RSSI_STATE_STAY_HIGH)) { - btc8821a2ant_sw_mech1(btcoexist, false, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, true, false, - false, 0x18); - } else { - btc8821a2ant_sw_mech1(btcoexist, false, true, - false, false); - btc8821a2ant_sw_mech2(btcoexist, false, false, - false, 0x18); - } - } -} - -static void halbtc8821a2ant_run_coexist_mechanism(struct btc_coexist *btcoexist) -{ - bool wifi_under_5g = false; - u8 algorithm = 0; - - if (btcoexist->manual_control) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Manual control!!!\n"); - return; - } - - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); - - if (wifi_under_5g) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], RunCoexistMechanism(), run 5G coex setting!!<===\n"); - halbtc8821a2ant_coex_under_5g(btcoexist); - return; - } - - algorithm = halbtc8821a2ant_action_algorithm(btcoexist); - if (coex_sta->c2h_bt_inquiry_page && - (BT_8821A_2ANT_COEX_ALGO_PANHS != algorithm)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], BT is under inquiry/page scan !!\n"); - halbtc8821a2ant_bt_inquiry_page(btcoexist); - return; - } - - coex_dm->cur_algorithm = algorithm; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Algorithm = %d\n", coex_dm->cur_algorithm); - - if (halbtc8821a2ant_is_common_action(btcoexist)) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant common.\n"); - coex_dm->reset_tdma_adjust = true; - } else { - if (coex_dm->cur_algorithm != coex_dm->pre_algorithm) { - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], pre_algorithm = %d, cur_algorithm = %d\n", - coex_dm->pre_algorithm, coex_dm->cur_algorithm); - coex_dm->reset_tdma_adjust = true; - } - switch (coex_dm->cur_algorithm) { - case BT_8821A_2ANT_COEX_ALGO_SCO: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = SCO.\n"); - halbtc8821a2ant_action_sco(btcoexist); - break; - case BT_8821A_2ANT_COEX_ALGO_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = HID.\n"); - halbtc8821a2ant_action_hid(btcoexist); - break; - case BT_8821A_2ANT_COEX_ALGO_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = A2DP.\n"); - halbtc8821a2ant_action_a2dp(btcoexist); - break; - case BT_8821A_2ANT_COEX_ALGO_A2DP_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = A2DP+PAN(HS).\n"); - halbtc8821a2ant_action_a2dp_pan_hs(btcoexist); - break; - case BT_8821A_2ANT_COEX_ALGO_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = PAN(EDR).\n"); - halbtc8821a2ant_action_pan_edr(btcoexist); - break; - case BT_8821A_2ANT_COEX_ALGO_PANHS: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = HS mode.\n"); - halbtc8821a2ant_action_pan_hs(btcoexist); - break; - case BT_8821A_2ANT_COEX_ALGO_PANEDR_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = PAN+A2DP.\n"); - halbtc8821a2ant_action_pan_edr_a2dp(btcoexist); - break; - case BT_8821A_2ANT_COEX_ALGO_PANEDR_HID: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = PAN(EDR)+HID.\n"); - halbtc8821a2ant_action_pan_edr_hid(btcoexist); - break; - case BT_8821A_2ANT_COEX_ALGO_HID_A2DP_PANEDR: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = HID+A2DP+PAN.\n"); - btc8821a2ant_act_hid_a2dp_pan_edr(btcoexist); - break; - case BT_8821A_2ANT_COEX_ALGO_HID_A2DP: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = HID+A2DP.\n"); - halbtc8821a2ant_action_hid_a2dp(btcoexist); - break; - default: - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], Action 2-Ant, algorithm = coexist All Off!!\n"); - halbtc8821a2ant_coex_all_off(btcoexist); - break; - } - coex_dm->pre_algorithm = coex_dm->cur_algorithm; - } -} - -/*============================================================ - *work around function start with wa_halbtc8821a2ant_ - *============================================================ - *============================================================ - * extern function start with EXhalbtc8821a2ant_ - *============================================================ - */ -void ex_halbtc8821a2ant_init_hwconfig(struct btc_coexist *btcoexist) -{ - u8 u1tmp = 0; - - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], 2Ant Init HW Config!!\n"); - - /* backup rf 0x1e value */ - coex_dm->bt_rf0x1e_backup = - btcoexist->btc_get_rf_reg(btcoexist, BTC_RF_A, 0x1e, 0xfffff); - - /* 0x790[5:0] = 0x5 */ - u1tmp = btcoexist->btc_read_1byte(btcoexist, 0x790); - u1tmp &= 0xc0; - u1tmp |= 0x5; - btcoexist->btc_write_1byte(btcoexist, 0x790, u1tmp); - - /*Antenna config */ - halbtc8821a2ant_set_ant_path(btcoexist, - BTC_ANT_WIFI_AT_MAIN, true, false); - - /* PTA parameter */ - halbtc8821a2ant_coex_table(btcoexist, - FORCE_EXEC, 0x55555555, 0x55555555, - 0xffff, 0x3); - - /* Enable counter statistics */ - /*0x76e[3] = 1, WLAN_Act control by PTA*/ - btcoexist->btc_write_1byte(btcoexist, 0x76e, 0xc); - btcoexist->btc_write_1byte(btcoexist, 0x778, 0x3); - btcoexist->btc_write_1byte_bitmask(btcoexist, 0x40, 0x20, 0x1); -} - -void -ex_halbtc8821a2ant_init_coex_dm( - struct btc_coexist *btcoexist - ) -{ - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Coex Mechanism Init!!\n"); - - halbtc8821a2ant_init_coex_dm(btcoexist); -} - -void -ex_halbtc8821a2ant_display_coex_info( - struct btc_coexist *btcoexist - ) -{ - struct btc_board_info *board_info = &btcoexist->board_info; - struct btc_stack_info *stack_info = &btcoexist->stack_info; - struct rtl_priv *rtlpriv = btcoexist->adapter; - u8 u1tmp[4], i, bt_info_ext, ps_tdma_case = 0; - u32 u4tmp[4]; - bool roam = false, scan = false, link = false, wifi_under_5g = false; - bool bt_hs_on = false, wifi_busy = false; - long wifi_rssi = 0, bt_hs_rssi = 0; - u32 wifi_bw, wifi_traffic_dir; - u8 wifi_dot_11_chnl, wifi_hs_chnl; - u32 fw_ver = 0, bt_patch_ver = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n ============[BT Coexist info]============"); - - if (!board_info->bt_exist) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n BT not exists !!!"); - return; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d/ %d ", "Ant PG number/ Ant mechanism:", - board_info->pg_ant_num, board_info->btdm_ant_num); - - if (btcoexist->manual_control) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s", "[Action Manual control]!!"); - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %s / %d", "BT stack/ hci ext ver", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); - - btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, &bt_patch_ver); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d_%d/ 0x%x/ 0x%x(%d)", - "CoexVer/ FwVer/ PatchVer", - glcoex_ver_date_8821a_2ant, glcoex_ver_8821a_2ant, - fw_ver, bt_patch_ver, bt_patch_ver); - - btcoexist->btc_get(btcoexist, - BTC_GET_BL_HS_OPERATION, &bt_hs_on); - btcoexist->btc_get(btcoexist, - BTC_GET_U1_WIFI_DOT11_CHNL, &wifi_dot_11_chnl); - btcoexist->btc_get(btcoexist, - BTC_GET_U1_WIFI_HS_CHNL, &wifi_hs_chnl); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d / %d(%d)", - "Dot11 channel / HsMode(HsChnl)", - wifi_dot_11_chnl, bt_hs_on, wifi_hs_chnl); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %02x %02x %02x ", - "H2C Wifi inform bt chnl Info", - coex_dm->wifi_chnl_info[0], coex_dm->wifi_chnl_info[1], - coex_dm->wifi_chnl_info[2]); - - btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi); - btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %ld/ %ld", "Wifi rssi/ HS rssi", - wifi_rssi, bt_hs_rssi); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_SCAN, &scan); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_LINK, &link); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_ROAM, &roam); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d/ %d/ %d ", "Wifi link/ roam/ scan", - link, roam, scan); - - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); - btcoexist->btc_get(btcoexist, - BTC_GET_U4_WIFI_BW, &wifi_bw); - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_BUSY, &wifi_busy); - btcoexist->btc_get(btcoexist, - BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, &wifi_traffic_dir); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %s / %s/ %s ", "Wifi status", - (wifi_under_5g ? "5G" : "2.4G"), - ((BTC_WIFI_BW_LEGACY == wifi_bw) ? "Legacy" : - (((BTC_WIFI_BW_HT40 == wifi_bw) ? "HT40" : "HT20"))), - ((!wifi_busy) ? "idle" : - ((BTC_WIFI_TRAFFIC_TX == wifi_traffic_dir) ? - "uplink" : "downlink"))); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = [%s/ %d/ %d] ", "BT [status/ rssi/ retryCnt]", - ((coex_sta->c2h_bt_inquiry_page) ? ("inquiry/page scan") : - ((BT_8821A_2ANT_BT_STATUS_IDLE == coex_dm->bt_status) - ? "idle" : ((BT_8821A_2ANT_BT_STATUS_CON_IDLE == - coex_dm->bt_status) ? "connected-idle" : "busy"))), - coex_sta->bt_rssi, coex_sta->bt_retry_cnt); - - if (stack_info->profile_notified) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d / %d / %d / %d", "SCO/HID/PAN/A2DP", - stack_info->sco_exist, stack_info->hid_exist, - stack_info->pan_exist, stack_info->a2dp_exist); - - btcoexist->btc_disp_dbg_msg(btcoexist, - BTC_DBG_DISP_BT_LINK_INFO); - } - - bt_info_ext = coex_sta->bt_info_ext; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s", - "BT Info A2DP rate", - (bt_info_ext&BIT0) ? "Basic rate" : "EDR rate"); - - for (i = 0; i < BT_INFO_SRC_8821A_2ANT_MAX; i++) { - if (coex_sta->bt_info_c2h_cnt[i]) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)", - glbt_info_src_8821a_2ant[i], - coex_sta->bt_info_c2h[i][0], - coex_sta->bt_info_c2h[i][1], - coex_sta->bt_info_c2h[i][2], - coex_sta->bt_info_c2h[i][3], - coex_sta->bt_info_c2h[i][4], - coex_sta->bt_info_c2h[i][5], - coex_sta->bt_info_c2h[i][6], - coex_sta->bt_info_c2h_cnt[i]); - } - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %s/%s", - "PS state, IPS/LPS", - ((coex_sta->under_ips ? "IPS ON" : "IPS OFF")), - ((coex_sta->under_lps ? "LPS ON" : "LPS OFF"))); - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_FW_PWR_MODE_CMD); - - /* Sw mechanism*/ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", - "============[Sw mechanism]============"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d/ %d/ %d/ %d ", - "SM1[ShRf/ LpRA/ LimDig/ btLna]", - coex_dm->cur_rf_rx_lpf_shrink, coex_dm->cur_low_penalty_ra, - coex_dm->limited_dig, coex_dm->cur_bt_lna_constrain); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d/ %d/ %d(0x%x) ", - "SM2[AgcT/ AdcB/ SwDacSwing(lvl)]", - coex_dm->cur_agc_table_en, coex_dm->cur_adc_back_off, - coex_dm->cur_dac_swing_on, coex_dm->cur_dac_swing_lvl); - - /* Fw mechanism*/ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s", - "============[Fw mechanism]============"); - - if (!btcoexist->manual_control) { - ps_tdma_case = coex_dm->cur_ps_tdma; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %02x %02x %02x %02x %02x case-%d", - "PS TDMA", - coex_dm->ps_tdma_para[0], coex_dm->ps_tdma_para[1], - coex_dm->ps_tdma_para[2], coex_dm->ps_tdma_para[3], - coex_dm->ps_tdma_para[4], ps_tdma_case); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = %d/ %d ", "DecBtPwr/ IgnWlanAct", - coex_dm->cur_dec_bt_pwr, - coex_dm->cur_ignore_wlan_act); - } - - /* Hw setting*/ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s", "============[Hw setting]============"); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "\r\n %-35s = 0x%x", "RF-A, 0x1e initVal", - coex_dm->bt_rf0x1e_backup); - - u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x778); - u1tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0x6cc); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x ", - "0x778 (W_Act)/ 0x6cc (CoTab Sel)", - u1tmp[0], u1tmp[1]); - - u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x8db); - u1tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xc5b); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "0x8db(ADC)/0xc5b[29:25](DAC)", - ((u1tmp[0]&0x60)>>5), ((u1tmp[1]&0x3e)>>1)); - - u4tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xcb4); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "0xcb4[7:0](ctrl)/ 0xcb4[29:28](val)", - u4tmp[0]&0xff, ((u4tmp[0]&0x30000000)>>28)); - - u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x40); - u4tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x4c); - u4tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x974); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "0x40/ 0x4c[24:23]/ 0x974", - u1tmp[0], ((u4tmp[0]&0x01800000)>>23), u4tmp[1]); - - u4tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x550); - u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x522); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "0x550(bcn ctrl)/0x522", - u4tmp[0], u1tmp[0]); - - u4tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xc50); - u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xa0a); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "0xc50(DIG)/0xa0a(CCK-TH)", - u4tmp[0], u1tmp[0]); - - u4tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0xf48); - u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0xa5b); - u1tmp[1] = btcoexist->btc_read_1byte(btcoexist, 0xa5c); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x", - "OFDM-FA/ CCK-FA", - u4tmp[0], (u1tmp[0]<<8) + u1tmp[1]); - - u4tmp[0] = btcoexist->btc_read_4byte(btcoexist, 0x6c0); - u4tmp[1] = btcoexist->btc_read_4byte(btcoexist, 0x6c4); - u4tmp[2] = btcoexist->btc_read_4byte(btcoexist, 0x6c8); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x/ 0x%x/ 0x%x", - "0x6c0/0x6c4/0x6c8", - u4tmp[0], u4tmp[1], u4tmp[2]); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", - "0x770 (hi-pri Rx/Tx)", - coex_sta->high_priority_rx, coex_sta->high_priority_tx); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d", - "0x774(low-pri Rx/Tx)", - coex_sta->low_priority_rx, coex_sta->low_priority_tx); - - /* Tx mgnt queue hang or not, 0x41b should = 0xf, ex: 0xd ==>hang*/ - u1tmp[0] = btcoexist->btc_read_1byte(btcoexist, 0x41b); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = 0x%x", - "0x41b (mgntQ hang chk == 0xf)", - u1tmp[0]); - - btcoexist->btc_disp_dbg_msg(btcoexist, BTC_DBG_DISP_COEX_STATISTICS); -} - -void ex_halbtc8821a2ant_ips_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (BTC_IPS_ENTER == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS ENTER notify\n"); - coex_sta->under_ips = true; - halbtc8821a2ant_coex_all_off(btcoexist); - } else if (BTC_IPS_LEAVE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], IPS LEAVE notify\n"); - coex_sta->under_ips = false; - /*halbtc8821a2ant_init_coex_dm(btcoexist);*/ - } -} - -void ex_halbtc8821a2ant_lps_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (BTC_LPS_ENABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS ENABLE notify\n"); - coex_sta->under_lps = true; - } else if (BTC_LPS_DISABLE == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], LPS DISABLE notify\n"); - coex_sta->under_lps = false; - } -} - -void ex_halbtc8821a2ant_scan_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (BTC_SCAN_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN START notify\n"); - } else if (BTC_SCAN_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], SCAN FINISH notify\n"); - } -} - -void ex_halbtc8821a2ant_connect_notify(struct btc_coexist *btcoexist, u8 type) -{ - if (BTC_ASSOCIATE_START == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT START notify\n"); - } else if (BTC_ASSOCIATE_FINISH == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], CONNECT FINISH notify\n"); - } -} - -void ex_halbtc8821a2ant_media_status_notify(struct btc_coexist *btcoexist, - u8 type) -{ - u8 h2c_parameter[3] = {0}; - u32 wifi_bw; - u8 wifi_central_chnl; - - if (BTC_MEDIA_CONNECT == type) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA connect notify\n"); - } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], MEDIA disconnect notify\n"); - } - - /* only 2.4G we need to inform bt the chnl mask*/ - btcoexist->btc_get(btcoexist, BTC_GET_U1_WIFI_CENTRAL_CHNL, - &wifi_central_chnl); - if ((BTC_MEDIA_CONNECT == type) && - (wifi_central_chnl <= 14)) { - h2c_parameter[0] = 0x1; - h2c_parameter[1] = wifi_central_chnl; - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_BW, &wifi_bw); - if (BTC_WIFI_BW_HT40 == wifi_bw) - h2c_parameter[2] = 0x30; - else - h2c_parameter[2] = 0x20; - } - - coex_dm->wifi_chnl_info[0] = h2c_parameter[0]; - coex_dm->wifi_chnl_info[1] = h2c_parameter[1]; - coex_dm->wifi_chnl_info[2] = h2c_parameter[2]; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE_FW_EXEC, - "[BTCoex], FW write 0x66 = 0x%x\n", - h2c_parameter[0]<<16|h2c_parameter[1]<<8|h2c_parameter[2]); - - btcoexist->btc_fill_h2c(btcoexist, 0x66, 3, h2c_parameter); -} - -void ex_halbtc8821a2ant_special_packet_notify(struct btc_coexist *btcoexist, - u8 type) { - if (type == BTC_PACKET_DHCP) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], DHCP Packet notify\n"); - } -} - -void ex_halbtc8821a2ant_bt_info_notify(struct btc_coexist *btcoexist, - u8 *tmp_buf, u8 length) -{ - u8 bt_info = 0; - u8 i, rsp_source = 0; - static u32 set_bt_lna_cnt, set_bt_psd_mode; - bool bt_busy = false, limited_dig = false; - bool wifi_connected = false, bt_hs_on = false; - - coex_sta->c2h_bt_info_req_sent = false; - - rsp_source = tmp_buf[0]&0xf; - if (rsp_source >= BT_INFO_SRC_8821A_2ANT_MAX) - rsp_source = BT_INFO_SRC_8821A_2ANT_WIFI_FW; - coex_sta->bt_info_c2h_cnt[rsp_source]++; - - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Bt info[%d], length = %d, hex data = [", - rsp_source, length); - for (i = 0; i < length; i++) { - coex_sta->bt_info_c2h[rsp_source][i] = tmp_buf[i]; - if (i == 1) - bt_info = tmp_buf[i]; - if (i == length-1) { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x]\n", tmp_buf[i]); - } else { - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "0x%02x, ", tmp_buf[i]); - } - } - - if (BT_INFO_SRC_8821A_2ANT_WIFI_FW != rsp_source) { - coex_sta->bt_retry_cnt = /* [3:0]*/ - coex_sta->bt_info_c2h[rsp_source][2]&0xf; - - coex_sta->bt_rssi = - coex_sta->bt_info_c2h[rsp_source][3]*2+10; - - coex_sta->bt_info_ext = - coex_sta->bt_info_c2h[rsp_source][4]; - - /* Here we need to resend some wifi info to BT*/ - /* because bt is reset and loss of the info.*/ - if ((coex_sta->bt_info_ext & BIT1)) { - btcoexist->btc_get(btcoexist, - BTC_GET_BL_WIFI_CONNECTED, &wifi_connected); - if (wifi_connected) { - ex_halbtc8821a2ant_media_status_notify(btcoexist, - BTC_MEDIA_CONNECT); - } else { - ex_halbtc8821a2ant_media_status_notify(btcoexist, - BTC_MEDIA_DISCONNECT); - } - - set_bt_psd_mode = 0; - } - if (set_bt_psd_mode <= 3) { - halbtc8821a2ant_set_bt_psd_mode(btcoexist, FORCE_EXEC, - 0x0); /*fix CH-BW mode*/ - set_bt_psd_mode++; - } - - if (coex_dm->cur_bt_lna_constrain) { - if (!(coex_sta->bt_info_ext & BIT2)) { - if (set_bt_lna_cnt <= 3) { - btc8821a2_set_bt_lna_const(btcoexist, - FORCE_EXEC, - true); - set_bt_lna_cnt++; - } - } - } else { - set_bt_lna_cnt = 0; - } - - if ((coex_sta->bt_info_ext & BIT3)) { - halbtc8821a2ant_ignore_wlan_act(btcoexist, - FORCE_EXEC, false); - } else { - /* BT already NOT ignore Wlan active, do nothing here.*/ - } - - if ((coex_sta->bt_info_ext & BIT4)) { - /* BT auto report already enabled, do nothing*/ - } else { - halbtc8821a2ant_bt_auto_report(btcoexist, - FORCE_EXEC, true); - } - } - - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - /* check BIT2 first ==> check if bt is under inquiry or page scan*/ - if (bt_info & BT_INFO_8821A_2ANT_B_INQ_PAGE) { - coex_sta->c2h_bt_inquiry_page = true; - coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_NON_IDLE; - } else { - coex_sta->c2h_bt_inquiry_page = false; - if (bt_info == 0x1) { - /* connection exists but not busy*/ - coex_sta->bt_link_exist = true; - coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_CON_IDLE; - } else if (bt_info & BT_INFO_8821A_2ANT_B_CONNECTION) { - /* connection exists and some link is busy*/ - coex_sta->bt_link_exist = true; - if (bt_info & BT_INFO_8821A_2ANT_B_FTP) - coex_sta->pan_exist = true; - else - coex_sta->pan_exist = false; - if (bt_info & BT_INFO_8821A_2ANT_B_A2DP) - coex_sta->a2dp_exist = true; - else - coex_sta->a2dp_exist = false; - if (bt_info & BT_INFO_8821A_2ANT_B_HID) - coex_sta->hid_exist = true; - else - coex_sta->hid_exist = false; - if (bt_info & BT_INFO_8821A_2ANT_B_SCO_ESCO) - coex_sta->sco_exist = true; - else - coex_sta->sco_exist = false; - coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_NON_IDLE; - } else { - coex_sta->bt_link_exist = false; - coex_sta->pan_exist = false; - coex_sta->a2dp_exist = false; - coex_sta->hid_exist = false; - coex_sta->sco_exist = false; - coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_IDLE; - } - - if (bt_hs_on) - coex_dm->bt_status = BT_8821A_2ANT_BT_STATUS_NON_IDLE; - } - - if (BT_8821A_2ANT_BT_STATUS_NON_IDLE == coex_dm->bt_status) - bt_busy = true; - else - bt_busy = false; - btcoexist->btc_set(btcoexist, BTC_SET_BL_BT_TRAFFIC_BUSY, &bt_busy); - - if (BT_8821A_2ANT_BT_STATUS_IDLE != coex_dm->bt_status) - limited_dig = true; - else - limited_dig = false; - coex_dm->limited_dig = limited_dig; - btcoexist->btc_set(btcoexist, - BTC_SET_BL_BT_LIMITED_DIG, &limited_dig); - - halbtc8821a2ant_run_coexist_mechanism(btcoexist); -} - -void ex_halbtc8821a2ant_halt_notify(struct btc_coexist *btcoexist) -{ - BTC_PRINT(BTC_MSG_INTERFACE, INTF_NOTIFY, - "[BTCoex], Halt notify\n"); - - halbtc8821a2ant_ignore_wlan_act(btcoexist, FORCE_EXEC, true); - ex_halbtc8821a2ant_media_status_notify(btcoexist, BTC_MEDIA_DISCONNECT); -} - -void ex_halbtc8821a2ant_periodical(struct btc_coexist *btcoexist) -{ - static u8 dis_ver_info_cnt; - u32 fw_ver = 0, bt_patch_ver = 0; - struct btc_board_info *board_info = &btcoexist->board_info; - struct btc_stack_info *stack_info = &btcoexist->stack_info; - - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "[BTCoex], ==========================Periodical===========================\n"); - - if (dis_ver_info_cnt <= 5) { - dis_ver_info_cnt += 1; - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************************************************\n"); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], Ant PG Num/ Ant Mech/ Ant Pos = %d/ %d/ %d\n", - board_info->pg_ant_num, - board_info->btdm_ant_num, - board_info->btdm_ant_pos); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], BT stack/ hci ext ver = %s / %d\n", - ((stack_info->profile_notified) ? "Yes" : "No"), - stack_info->hci_version); - btcoexist->btc_get(btcoexist, BTC_GET_U4_BT_PATCH_VER, - &bt_patch_ver); - btcoexist->btc_get(btcoexist, BTC_GET_U4_WIFI_FW_VER, &fw_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], CoexVer/ FwVer/ PatchVer = %d_%x/ 0x%x/ 0x%x(%d)\n", - glcoex_ver_date_8821a_2ant, glcoex_ver_8821a_2ant, - fw_ver, bt_patch_ver, bt_patch_ver); - BTC_PRINT(BTC_MSG_INTERFACE, INTF_INIT, - "[BTCoex], ****************************************************************\n"); - } - - halbtc8821a2ant_query_bt_info(btcoexist); - halbtc8821a2ant_monitor_bt_ctr(btcoexist); - btc8821a2ant_mon_bt_en_dis(btcoexist); -} diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.h deleted file mode 100644 index b4cf1f53d510..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtc8821a2ant.h +++ /dev/null @@ -1,205 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -/*=========================================== - * The following is for 8821A 2Ant BT Co-exist definition - *=========================================== -*/ -#define BT_INFO_8821A_2ANT_B_FTP BIT7 -#define BT_INFO_8821A_2ANT_B_A2DP BIT6 -#define BT_INFO_8821A_2ANT_B_HID BIT5 -#define BT_INFO_8821A_2ANT_B_SCO_BUSY BIT4 -#define BT_INFO_8821A_2ANT_B_ACL_BUSY BIT3 -#define BT_INFO_8821A_2ANT_B_INQ_PAGE BIT2 -#define BT_INFO_8821A_2ANT_B_SCO_ESCO BIT1 -#define BT_INFO_8821A_2ANT_B_CONNECTION BIT0 - -#define BTC_RSSI_COEX_THRESH_TOL_8821A_2ANT 2 - -enum _BT_INFO_SRC_8821A_2ANT { - BT_INFO_SRC_8821A_2ANT_WIFI_FW = 0x0, - BT_INFO_SRC_8821A_2ANT_BT_RSP = 0x1, - BT_INFO_SRC_8821A_2ANT_BT_ACTIVE_SEND = 0x2, - BT_INFO_SRC_8821A_2ANT_MAX -}; - -enum _BT_8821A_2ANT_BT_STATUS { - BT_8821A_2ANT_BT_STATUS_IDLE = 0x0, - BT_8821A_2ANT_BT_STATUS_CON_IDLE = 0x1, - BT_8821A_2ANT_BT_STATUS_NON_IDLE = 0x2, - BT_8821A_2ANT_BT_STATUS_MAX -}; - -enum _BT_8821A_2ANT_COEX_ALGO { - BT_8821A_2ANT_COEX_ALGO_UNDEFINED = 0x0, - BT_8821A_2ANT_COEX_ALGO_SCO = 0x1, - BT_8821A_2ANT_COEX_ALGO_HID = 0x2, - BT_8821A_2ANT_COEX_ALGO_A2DP = 0x3, - BT_8821A_2ANT_COEX_ALGO_A2DP_PANHS = 0x4, - BT_8821A_2ANT_COEX_ALGO_PANEDR = 0x5, - BT_8821A_2ANT_COEX_ALGO_PANHS = 0x6, - BT_8821A_2ANT_COEX_ALGO_PANEDR_A2DP = 0x7, - BT_8821A_2ANT_COEX_ALGO_PANEDR_HID = 0x8, - BT_8821A_2ANT_COEX_ALGO_HID_A2DP_PANEDR = 0x9, - BT_8821A_2ANT_COEX_ALGO_HID_A2DP = 0xa, - BT_8821A_2ANT_COEX_ALGO_MAX = 0xb, -}; - -struct coex_dm_8821a_2ant { - /* fw mechanism */ - bool pre_dec_bt_pwr; - bool cur_dec_bt_pwr; - bool pre_bt_lna_constrain; - bool cur_bt_lna_constrain; - u8 pre_bt_psd_mode; - u8 cur_bt_psd_mode; - u8 pre_fw_dac_swing_lvl; - u8 cur_fw_dac_swing_lvl; - bool cur_ignore_wlan_act; - bool pre_ignore_wlan_act; - u8 pre_ps_tdma; - u8 cur_ps_tdma; - u8 ps_tdma_para[5]; - u8 tdma_adj_type; - bool reset_tdma_adjust; - bool pre_ps_tdma_on; - bool cur_ps_tdma_on; - bool pre_bt_auto_report; - bool cur_bt_auto_report; - - /* sw mechanism */ - bool pre_rf_rx_lpf_shrink; - bool cur_rf_rx_lpf_shrink; - u32 bt_rf0x1e_backup; - bool pre_low_penalty_ra; - bool cur_low_penalty_ra; - bool pre_dac_swing_on; - u32 pre_dac_swing_lvl; - bool cur_dac_swing_on; - u32 cur_dac_swing_lvl; - bool pre_adc_back_off; - bool cur_adc_back_off; - bool pre_agc_table_en; - bool cur_agc_table_en; - u32 pre_val0x6c0; - u32 cur_val0x6c0; - u32 pre_val0x6c4; - u32 cur_val0x6c4; - u32 pre_val0x6c8; - u32 cur_val0x6c8; - u8 pre_val0x6cc; - u8 cur_val0x6cc; - bool limited_dig; - - /* algorithm related */ - u8 pre_algorithm; - u8 cur_algorithm; - u8 bt_status; - u8 wifi_chnl_info[3]; -}; - -struct coex_sta_8821a_2ant { - bool bt_link_exist; - bool sco_exist; - bool a2dp_exist; - bool hid_exist; - bool pan_exist; - bool under_lps; - bool under_ips; - u32 high_priority_tx; - u32 high_priority_rx; - u32 low_priority_tx; - u32 low_priority_rx; - u8 bt_rssi; - u8 pre_bt_rssi_state; - u8 pre_wifi_rssi_state[4]; - bool c2h_bt_info_req_sent; - u8 bt_info_c2h[BT_INFO_SRC_8821A_2ANT_MAX][10]; - u32 bt_info_c2h_cnt[BT_INFO_SRC_8821A_2ANT_MAX]; - bool c2h_bt_inquiry_page; - u8 bt_retry_cnt; - u8 bt_info_ext; -}; - -/*=========================================== - * The following is interface which will notify coex module. - *=========================================== - */ -void -ex_halbtc8821a2ant_init_hwconfig( - struct btc_coexist *btcoexist - ); -void -ex_halbtc8821a2ant_init_coex_dm( - struct btc_coexist *btcoexist - ); -void -ex_halbtc8821a2ant_ips_notify( - struct btc_coexist *btcoexist, - u8 type - ); -void -ex_halbtc8821a2ant_lps_notify( - struct btc_coexist *btcoexist, - u8 type - ); -void -ex_halbtc8821a2ant_scan_notify( - struct btc_coexist *btcoexist, - u8 type - ); -void -ex_halbtc8821a2ant_connect_notify( - struct btc_coexist *btcoexist, - u8 type - ); -void -ex_halbtc8821a2ant_media_status_notify( - struct btc_coexist *btcoexist, - u8 type - ); -void -ex_halbtc8821a2ant_special_packet_notify( - struct btc_coexist *btcoexist, - u8 type - ); -void -ex_halbtc8821a2ant_bt_info_notify( - struct btc_coexist *btcoexist, - u8 *tmp_buf, - u8 length - ); -void -ex_halbtc8821a2ant_halt_notify( - struct btc_coexist *btcoexist - ); -void -ex_halbtc8821a2ant_periodical( - struct btc_coexist *btcoexist - ); -void -ex_halbtc8821a2ant_display_coex_info( - struct btc_coexist *btcoexist - ); diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c deleted file mode 100644 index b2791c893417..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c +++ /dev/null @@ -1,987 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - ******************************************************************************/ - -#include "halbt_precomp.h" - -/*********************************************** - * Global variables - ***********************************************/ - -struct btc_coexist gl_bt_coexist; - -u32 btc_dbg_type[BTC_MSG_MAX]; - -/*************************************************** - * Debug related function - ***************************************************/ -static bool halbtc_is_bt_coexist_available(struct btc_coexist *btcoexist) -{ - if (!btcoexist->binded || NULL == btcoexist->adapter) - return false; - - return true; -} - -static bool halbtc_is_wifi_busy(struct rtl_priv *rtlpriv) -{ - if (rtlpriv->link_info.busytraffic) - return true; - else - return false; -} - -static void halbtc_dbg_init(void) -{ - u8 i; - - for (i = 0; i < BTC_MSG_MAX; i++) - btc_dbg_type[i] = 0; - - btc_dbg_type[BTC_MSG_INTERFACE] = -/* INTF_INIT | */ -/* INTF_NOTIFY | */ - 0; - - btc_dbg_type[BTC_MSG_ALGORITHM] = -/* ALGO_BT_RSSI_STATE | */ -/* ALGO_WIFI_RSSI_STATE | */ -/* ALGO_BT_MONITOR | */ -/* ALGO_TRACE | */ -/* ALGO_TRACE_FW | */ -/* ALGO_TRACE_FW_DETAIL | */ -/* ALGO_TRACE_FW_EXEC | */ -/* ALGO_TRACE_SW | */ -/* ALGO_TRACE_SW_DETAIL | */ -/* ALGO_TRACE_SW_EXEC | */ - 0; -} - -static bool halbtc_is_bt40(struct rtl_priv *adapter) -{ - struct rtl_priv *rtlpriv = adapter; - struct rtl_phy *rtlphy = &(rtlpriv->phy); - bool is_ht40 = true; - enum ht_channel_width bw = rtlphy->current_chan_bw; - - if (bw == HT_CHANNEL_WIDTH_20) - is_ht40 = false; - else if (bw == HT_CHANNEL_WIDTH_20_40) - is_ht40 = true; - - return is_ht40; -} - -static bool halbtc_legacy(struct rtl_priv *adapter) -{ - struct rtl_priv *rtlpriv = adapter; - struct rtl_mac *mac = rtl_mac(rtlpriv); - - bool is_legacy = false; - - if ((mac->mode == WIRELESS_MODE_B) || (mac->mode == WIRELESS_MODE_G)) - is_legacy = true; - - return is_legacy; -} - -bool halbtc_is_wifi_uplink(struct rtl_priv *adapter) -{ - struct rtl_priv *rtlpriv = adapter; - - if (rtlpriv->link_info.tx_busy_traffic) - return true; - else - return false; -} - -static u32 halbtc_get_wifi_bw(struct btc_coexist *btcoexist) -{ - struct rtl_priv *rtlpriv = - (struct rtl_priv *)btcoexist->adapter; - u32 wifi_bw = BTC_WIFI_BW_HT20; - - if (halbtc_is_bt40(rtlpriv)) { - wifi_bw = BTC_WIFI_BW_HT40; - } else { - if (halbtc_legacy(rtlpriv)) - wifi_bw = BTC_WIFI_BW_LEGACY; - else - wifi_bw = BTC_WIFI_BW_HT20; - } - return wifi_bw; -} - -static u8 halbtc_get_wifi_central_chnl(struct btc_coexist *btcoexist) -{ - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u8 chnl = 1; - - if (rtlphy->current_channel != 0) - chnl = rtlphy->current_channel; - BTC_PRINT(BTC_MSG_ALGORITHM, ALGO_TRACE, - "static halbtc_get_wifi_central_chnl:%d\n", chnl); - return chnl; -} - -static void halbtc_leave_lps(struct btc_coexist *btcoexist) -{ - struct rtl_priv *rtlpriv; - struct rtl_ps_ctl *ppsc; - bool ap_enable = false; - - rtlpriv = btcoexist->adapter; - ppsc = rtl_psc(rtlpriv); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, - &ap_enable); - - if (ap_enable) { - pr_info("halbtc_leave_lps()<--dont leave lps under AP mode\n"); - return; - } - - btcoexist->bt_info.bt_ctrl_lps = true; - btcoexist->bt_info.bt_lps_on = false; -} - -static void halbtc_enter_lps(struct btc_coexist *btcoexist) -{ - struct rtl_priv *rtlpriv; - struct rtl_ps_ctl *ppsc; - bool ap_enable = false; - - rtlpriv = btcoexist->adapter; - ppsc = rtl_psc(rtlpriv); - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_AP_MODE_ENABLE, - &ap_enable); - - if (ap_enable) { - pr_info("halbtc_enter_lps()<--dont enter lps under AP mode\n"); - return; - } - - btcoexist->bt_info.bt_ctrl_lps = true; - btcoexist->bt_info.bt_lps_on = false; -} - -static void halbtc_normal_lps(struct btc_coexist *btcoexist) -{ - if (btcoexist->bt_info.bt_ctrl_lps) { - btcoexist->bt_info.bt_lps_on = false; - btcoexist->bt_info.bt_ctrl_lps = false; - } -} - -static void halbtc_leave_low_power(void) -{ -} - -static void halbtc_nomal_low_power(void) -{ -} - -static void halbtc_disable_low_power(void) -{ -} - -static void halbtc_aggregation_check(void) -{ -} - -static u32 halbtc_get_bt_patch_version(struct btc_coexist *btcoexist) -{ - return 0; -} - -static s32 halbtc_get_wifi_rssi(struct rtl_priv *adapter) -{ - struct rtl_priv *rtlpriv = adapter; - s32 undec_sm_pwdb = 0; - - if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) - undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; - else /* associated entry pwdb */ - undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; - return undec_sm_pwdb; -} - -static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)void_btcoexist; - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtlpriv); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - bool *bool_tmp = (bool *)out_buf; - int *s32_tmp = (int *)out_buf; - u32 *u32_tmp = (u32 *)out_buf; - u8 *u8_tmp = (u8 *)out_buf; - bool tmp = false; - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return false; - - switch (get_type) { - case BTC_GET_BL_HS_OPERATION: - *bool_tmp = false; - break; - case BTC_GET_BL_HS_CONNECTING: - *bool_tmp = false; - break; - case BTC_GET_BL_WIFI_CONNECTED: - if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) - tmp = true; - *bool_tmp = tmp; - break; - case BTC_GET_BL_WIFI_BUSY: - if (halbtc_is_wifi_busy(rtlpriv)) - *bool_tmp = true; - else - *bool_tmp = false; - break; - case BTC_GET_BL_WIFI_SCAN: - if (mac->act_scanning) - *bool_tmp = true; - else - *bool_tmp = false; - break; - case BTC_GET_BL_WIFI_LINK: - if (mac->link_state == MAC80211_LINKING) - *bool_tmp = true; - else - *bool_tmp = false; - break; - case BTC_GET_BL_WIFI_ROAM: /*TODO*/ - if (mac->link_state == MAC80211_LINKING) - *bool_tmp = true; - else - *bool_tmp = false; - break; - case BTC_GET_BL_WIFI_4_WAY_PROGRESS: /*TODO*/ - *bool_tmp = false; - - break; - case BTC_GET_BL_WIFI_UNDER_5G: - *bool_tmp = false; /*TODO*/ - - case BTC_GET_BL_WIFI_DHCP: /*TODO*/ - break; - case BTC_GET_BL_WIFI_SOFTAP_IDLE: - *bool_tmp = true; - break; - case BTC_GET_BL_WIFI_SOFTAP_LINKING: - *bool_tmp = false; - break; - case BTC_GET_BL_WIFI_IN_EARLY_SUSPEND: - *bool_tmp = false; - break; - case BTC_GET_BL_WIFI_AP_MODE_ENABLE: - *bool_tmp = false; - break; - case BTC_GET_BL_WIFI_ENABLE_ENCRYPTION: - if (NO_ENCRYPTION == rtlpriv->sec.pairwise_enc_algorithm) - *bool_tmp = false; - else - *bool_tmp = true; - break; - case BTC_GET_BL_WIFI_UNDER_B_MODE: - *bool_tmp = false; /*TODO*/ - break; - case BTC_GET_BL_EXT_SWITCH: - *bool_tmp = false; - break; - case BTC_GET_S4_WIFI_RSSI: - *s32_tmp = halbtc_get_wifi_rssi(rtlpriv); - break; - case BTC_GET_S4_HS_RSSI: /*TODO*/ - *s32_tmp = halbtc_get_wifi_rssi(rtlpriv); - break; - case BTC_GET_U4_WIFI_BW: - *u32_tmp = halbtc_get_wifi_bw(btcoexist); - break; - case BTC_GET_U4_WIFI_TRAFFIC_DIRECTION: - if (halbtc_is_wifi_uplink(rtlpriv)) - *u32_tmp = BTC_WIFI_TRAFFIC_TX; - else - *u32_tmp = BTC_WIFI_TRAFFIC_RX; - break; - case BTC_GET_U4_WIFI_FW_VER: - *u32_tmp = rtlhal->fw_version; - break; - case BTC_GET_U4_BT_PATCH_VER: - *u32_tmp = halbtc_get_bt_patch_version(btcoexist); - break; - case BTC_GET_U1_WIFI_DOT11_CHNL: - *u8_tmp = rtlphy->current_channel; - break; - case BTC_GET_U1_WIFI_CENTRAL_CHNL: - *u8_tmp = halbtc_get_wifi_central_chnl(btcoexist); - break; - case BTC_GET_U1_WIFI_HS_CHNL: - *u8_tmp = 1;/*BT_OperateChnl(rtlpriv);*/ - break; - case BTC_GET_U1_MAC_PHY_MODE: - *u8_tmp = BTC_MP_UNKNOWN; - break; - - /************* 1Ant **************/ - case BTC_GET_U1_LPS_MODE: - *u8_tmp = btcoexist->pwr_mode_val[0]; - break; - - default: - break; - } - - return true; -} - -static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)void_btcoexist; - bool *bool_tmp = (bool *)in_buf; - u8 *u8_tmp = (u8 *)in_buf; - u32 *u32_tmp = (u32 *)in_buf; - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return false; - - switch (set_type) { - /* set some bool type variables. */ - case BTC_SET_BL_BT_DISABLE: - btcoexist->bt_info.bt_disabled = *bool_tmp; - break; - case BTC_SET_BL_BT_TRAFFIC_BUSY: - btcoexist->bt_info.bt_busy = *bool_tmp; - break; - case BTC_SET_BL_BT_LIMITED_DIG: - btcoexist->bt_info.limited_dig = *bool_tmp; - break; - case BTC_SET_BL_FORCE_TO_ROAM: - btcoexist->bt_info.force_to_roam = *bool_tmp; - break; - case BTC_SET_BL_TO_REJ_AP_AGG_PKT: - btcoexist->bt_info.reject_agg_pkt = *bool_tmp; - break; - case BTC_SET_BL_BT_CTRL_AGG_SIZE: - btcoexist->bt_info.bt_ctrl_buf_size = *bool_tmp; - break; - case BTC_SET_BL_INC_SCAN_DEV_NUM: - btcoexist->bt_info.increase_scan_dev_num = *bool_tmp; - break; - /* set some u1Byte type variables. */ - case BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON: - btcoexist->bt_info.rssi_adjust_for_agc_table_on = *u8_tmp; - break; - case BTC_SET_U1_AGG_BUF_SIZE: - btcoexist->bt_info.agg_buf_size = *u8_tmp; - break; - /* the following are some action which will be triggered */ - case BTC_SET_ACT_GET_BT_RSSI: - /*BTHCI_SendGetBtRssiEvent(rtlpriv);*/ - break; - case BTC_SET_ACT_AGGREGATE_CTRL: - halbtc_aggregation_check(); - break; - - /* 1Ant */ - case BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE: - btcoexist->bt_info.rssi_adjust_for_1ant_coex_type = *u8_tmp; - break; - case BTC_SET_UI_SCAN_SIG_COMPENSATION: - /* rtlpriv->mlmepriv.scan_compensation = *u8_tmp; */ - break; - case BTC_SET_U1_1ANT_LPS: - btcoexist->bt_info.lps_val = *u8_tmp; - break; - case BTC_SET_U1_1ANT_RPWM: - btcoexist->bt_info.rpwm_val = *u8_tmp; - break; - /* the following are some action which will be triggered */ - case BTC_SET_ACT_LEAVE_LPS: - halbtc_leave_lps(btcoexist); - break; - case BTC_SET_ACT_ENTER_LPS: - halbtc_enter_lps(btcoexist); - break; - case BTC_SET_ACT_NORMAL_LPS: - halbtc_normal_lps(btcoexist); - break; - case BTC_SET_ACT_DISABLE_LOW_POWER: - halbtc_disable_low_power(); - break; - case BTC_SET_ACT_UPDATE_ra_mask: - btcoexist->bt_info.ra_mask = *u32_tmp; - break; - case BTC_SET_ACT_SEND_MIMO_PS: - break; - case BTC_SET_ACT_INC_FORCE_EXEC_PWR_CMD_CNT: - btcoexist->bt_info.force_exec_pwr_cmd_cnt++; - break; - case BTC_SET_ACT_CTRL_BT_INFO: /*wait for 8812/8821*/ - break; - case BTC_SET_ACT_CTRL_BT_COEX: - break; - default: - break; - } - - return true; -} - -static void halbtc_display_coex_statistics(struct btc_coexist *btcoexist) -{ -} - -static void halbtc_display_bt_link_info(struct btc_coexist *btcoexist) -{ -} - -static void halbtc_display_bt_fw_info(struct btc_coexist *btcoexist) -{ -} - -static void halbtc_display_fw_pwr_mode_cmd(struct btc_coexist *btcoexist) -{ -} - -/************************************************************ - * IO related function - ************************************************************/ -static u8 halbtc_read_1byte(void *bt_context, u32 reg_addr) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; - struct rtl_priv *rtlpriv = btcoexist->adapter; - - return rtl_read_byte(rtlpriv, reg_addr); -} - -static u16 halbtc_read_2byte(void *bt_context, u32 reg_addr) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; - struct rtl_priv *rtlpriv = btcoexist->adapter; - - return rtl_read_word(rtlpriv, reg_addr); -} - -static u32 halbtc_read_4byte(void *bt_context, u32 reg_addr) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; - struct rtl_priv *rtlpriv = btcoexist->adapter; - - return rtl_read_dword(rtlpriv, reg_addr); -} - -static void halbtc_write_1byte(void *bt_context, u32 reg_addr, u32 data) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; - struct rtl_priv *rtlpriv = btcoexist->adapter; - - rtl_write_byte(rtlpriv, reg_addr, data); -} - -static void halbtc_bitmask_write_1byte(void *bt_context, u32 reg_addr, - u32 bit_mask, u8 data) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; - struct rtl_priv *rtlpriv = btcoexist->adapter; - u8 original_value, bit_shift = 0; - u8 i; - - if (bit_mask != MASKDWORD) {/*if not "double word" write*/ - original_value = rtl_read_byte(rtlpriv, reg_addr); - for (i = 0; i <= 7; i++) { - if ((bit_mask>>i) & 0x1) - break; - } - bit_shift = i; - data = (original_value & (~bit_mask)) | - ((data << bit_shift) & bit_mask); - } - rtl_write_byte(rtlpriv, reg_addr, data); -} - -static void halbtc_write_2byte(void *bt_context, u32 reg_addr, u16 data) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; - struct rtl_priv *rtlpriv = btcoexist->adapter; - - rtl_write_word(rtlpriv, reg_addr, data); -} - -static void halbtc_write_4byte(void *bt_context, u32 reg_addr, u32 data) -{ - struct btc_coexist *btcoexist = - (struct btc_coexist *)bt_context; - struct rtl_priv *rtlpriv = btcoexist->adapter; - - rtl_write_dword(rtlpriv, reg_addr, data); -} - -static void halbtc_set_bbreg(void *bt_context, u32 reg_addr, u32 bit_mask, - u32 data) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; - struct rtl_priv *rtlpriv = btcoexist->adapter; - - rtl_set_bbreg(rtlpriv->mac80211.hw, reg_addr, bit_mask, data); -} - -static u32 halbtc_get_bbreg(void *bt_context, u32 reg_addr, u32 bit_mask) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; - struct rtl_priv *rtlpriv = btcoexist->adapter; - - return rtl_get_bbreg(rtlpriv->mac80211.hw, reg_addr, bit_mask); -} - -static void halbtc_set_rfreg(void *bt_context, u8 rf_path, u32 reg_addr, - u32 bit_mask, u32 data) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; - struct rtl_priv *rtlpriv = btcoexist->adapter; - - rtl_set_rfreg(rtlpriv->mac80211.hw, rf_path, reg_addr, bit_mask, data); -} - -static u32 halbtc_get_rfreg(void *bt_context, u8 rf_path, u32 reg_addr, - u32 bit_mask) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; - struct rtl_priv *rtlpriv = btcoexist->adapter; - - return rtl_get_rfreg(rtlpriv->mac80211.hw, rf_path, reg_addr, bit_mask); -} - -static void halbtc_fill_h2c_cmd(void *bt_context, u8 element_id, - u32 cmd_len, u8 *cmd_buf) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; - struct rtl_priv *rtlpriv = btcoexist->adapter; - - rtlpriv->cfg->ops->fill_h2c_cmd(rtlpriv->mac80211.hw, element_id, - cmd_len, cmd_buf); -} - -static void halbtc_display_dbg_msg(void *bt_context, u8 disp_type) -{ - struct btc_coexist *btcoexist = (struct btc_coexist *)bt_context; - switch (disp_type) { - case BTC_DBG_DISP_COEX_STATISTICS: - halbtc_display_coex_statistics(btcoexist); - break; - case BTC_DBG_DISP_BT_LINK_INFO: - halbtc_display_bt_link_info(btcoexist); - break; - case BTC_DBG_DISP_BT_FW_VER: - halbtc_display_bt_fw_info(btcoexist); - break; - case BTC_DBG_DISP_FW_PWR_MODE_CMD: - halbtc_display_fw_pwr_mode_cmd(btcoexist); - break; - default: - break; - } -} - -/***************************************************************** - * Extern functions called by other module - *****************************************************************/ -bool exhalbtc_initlize_variables(struct rtl_priv *adapter) -{ - struct btc_coexist *btcoexist = &gl_bt_coexist; - - btcoexist->statistics.cnt_bind++; - - halbtc_dbg_init(); - - if (btcoexist->binded) - return false; - else - btcoexist->binded = true; - - btcoexist->chip_interface = BTC_INTF_UNKNOWN; - - if (NULL == btcoexist->adapter) - btcoexist->adapter = adapter; - - btcoexist->stack_info.profile_notified = false; - - btcoexist->btc_read_1byte = halbtc_read_1byte; - btcoexist->btc_write_1byte = halbtc_write_1byte; - btcoexist->btc_write_1byte_bitmask = halbtc_bitmask_write_1byte; - btcoexist->btc_read_2byte = halbtc_read_2byte; - btcoexist->btc_write_2byte = halbtc_write_2byte; - btcoexist->btc_read_4byte = halbtc_read_4byte; - btcoexist->btc_write_4byte = halbtc_write_4byte; - - btcoexist->btc_set_bb_reg = halbtc_set_bbreg; - btcoexist->btc_get_bb_reg = halbtc_get_bbreg; - - btcoexist->btc_set_rf_reg = halbtc_set_rfreg; - btcoexist->btc_get_rf_reg = halbtc_get_rfreg; - - btcoexist->btc_fill_h2c = halbtc_fill_h2c_cmd; - btcoexist->btc_disp_dbg_msg = halbtc_display_dbg_msg; - - btcoexist->btc_get = halbtc_get; - btcoexist->btc_set = halbtc_set; - - btcoexist->bt_info.bt_ctrl_buf_size = false; - btcoexist->bt_info.agg_buf_size = 5; - - btcoexist->bt_info.increase_scan_dev_num = false; - return true; -} - -void exhalbtc_init_hw_config(struct btc_coexist *btcoexist) -{ - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - - btcoexist->statistics.cnt_init_hw_config++; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) - ex_btc8723b2ant_init_hwconfig(btcoexist); -} - -void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist) -{ - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - - btcoexist->statistics.cnt_init_coex_dm++; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) - ex_btc8723b2ant_init_coex_dm(btcoexist); - - btcoexist->initilized = true; -} - -void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type) -{ - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 ips_type; - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - btcoexist->statistics.cnt_ips_notify++; - if (btcoexist->manual_control) - return; - - if (ERFOFF == type) - ips_type = BTC_IPS_ENTER; - else - ips_type = BTC_IPS_LEAVE; - - halbtc_leave_low_power(); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) - ex_btc8723b2ant_ips_notify(btcoexist, ips_type); - - halbtc_nomal_low_power(); -} - -void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type) -{ - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 lps_type; - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - btcoexist->statistics.cnt_lps_notify++; - if (btcoexist->manual_control) - return; - - if (EACTIVE == type) - lps_type = BTC_LPS_DISABLE; - else - lps_type = BTC_LPS_ENABLE; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) - ex_btc8723b2ant_lps_notify(btcoexist, lps_type); -} - -void exhalbtc_scan_notify(struct btc_coexist *btcoexist, u8 type) -{ - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 scan_type; - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - btcoexist->statistics.cnt_scan_notify++; - if (btcoexist->manual_control) - return; - - if (type) - scan_type = BTC_SCAN_START; - else - scan_type = BTC_SCAN_FINISH; - - halbtc_leave_low_power(); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) - ex_btc8723b2ant_scan_notify(btcoexist, scan_type); - - halbtc_nomal_low_power(); -} - -void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action) -{ - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 asso_type; - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - btcoexist->statistics.cnt_connect_notify++; - if (btcoexist->manual_control) - return; - - if (action) - asso_type = BTC_ASSOCIATE_START; - else - asso_type = BTC_ASSOCIATE_FINISH; - - halbtc_leave_low_power(); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) - ex_btc8723b2ant_connect_notify(btcoexist, asso_type); -} - -void exhalbtc_mediastatus_notify(struct btc_coexist *btcoexist, - enum rt_media_status media_status) -{ - u8 status; - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - btcoexist->statistics.cnt_media_status_notify++; - if (btcoexist->manual_control) - return; - - if (RT_MEDIA_CONNECT == media_status) - status = BTC_MEDIA_CONNECT; - else - status = BTC_MEDIA_DISCONNECT; - - halbtc_leave_low_power(); - - halbtc_nomal_low_power(); -} - -void exhalbtc_special_packet_notify(struct btc_coexist *btcoexist, u8 pkt_type) -{ - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 packet_type; - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - btcoexist->statistics.cnt_special_packet_notify++; - if (btcoexist->manual_control) - return; - - packet_type = BTC_PACKET_DHCP; - - halbtc_leave_low_power(); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) - ex_btc8723b2ant_special_packet_notify(btcoexist, - packet_type); - - halbtc_nomal_low_power(); -} - -void exhalbtc_bt_info_notify(struct btc_coexist *btcoexist, - u8 *tmp_buf, u8 length) -{ - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - btcoexist->statistics.cnt_bt_info_notify++; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) - ex_btc8723b2ant_bt_info_notify(btcoexist, tmp_buf, length); -} - -void exhalbtc_stack_operation_notify(struct btc_coexist *btcoexist, u8 type) -{ - u8 stack_op_type; - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - btcoexist->statistics.cnt_stack_operation_notify++; - if (btcoexist->manual_control) - return; - - stack_op_type = BTC_STACK_OP_NONE; - - halbtc_leave_low_power(); - - halbtc_nomal_low_power(); -} - -void exhalbtc_halt_notify(struct btc_coexist *btcoexist) -{ - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) - ex_btc8723b2ant_halt_notify(btcoexist); -} - -void exhalbtc_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state) -{ - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; -} - -void exhalbtc_periodical(struct btc_coexist *btcoexist) -{ - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - btcoexist->statistics.cnt_periodical++; - - halbtc_leave_low_power(); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) - ex_btc8723b2ant_periodical(btcoexist); - - halbtc_nomal_low_power(); -} - -void exhalbtc_dbg_control(struct btc_coexist *btcoexist, - u8 code, u8 len, u8 *data) -{ - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - btcoexist->statistics.cnt_dbg_ctrl++; -} - -void exhalbtc_stack_update_profile_info(void) -{ -} - -void exhalbtc_update_min_bt_rssi(char bt_rssi) -{ - struct btc_coexist *btcoexist = &gl_bt_coexist; - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - - btcoexist->stack_info.min_bt_rssi = bt_rssi; -} - -void exhalbtc_set_hci_version(u16 hci_version) -{ - struct btc_coexist *btcoexist = &gl_bt_coexist; - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - - btcoexist->stack_info.hci_version = hci_version; -} - -void exhalbtc_set_bt_patch_version(u16 bt_hci_version, u16 bt_patch_version) -{ - struct btc_coexist *btcoexist = &gl_bt_coexist; - - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - - btcoexist->bt_info.bt_real_fw_ver = bt_patch_version; - btcoexist->bt_info.bt_hci_ver = bt_hci_version; -} - -void exhalbtc_set_bt_exist(bool bt_exist) -{ - gl_bt_coexist.board_info.bt_exist = bt_exist; -} - -void exhalbtc_set_chip_type(u8 chip_type) -{ - switch (chip_type) { - default: - case BT_2WIRE: - case BT_ISSC_3WIRE: - case BT_ACCEL: - case BT_RTL8756: - gl_bt_coexist.board_info.bt_chip_type = BTC_CHIP_UNDEF; - break; - case BT_CSR_BC4: - gl_bt_coexist.board_info.bt_chip_type = BTC_CHIP_CSR_BC4; - break; - case BT_CSR_BC8: - gl_bt_coexist.board_info.bt_chip_type = BTC_CHIP_CSR_BC8; - break; - case BT_RTL8723A: - gl_bt_coexist.board_info.bt_chip_type = BTC_CHIP_RTL8723A; - break; - case BT_RTL8821A: - gl_bt_coexist.board_info.bt_chip_type = BTC_CHIP_RTL8821; - break; - case BT_RTL8723B: - gl_bt_coexist.board_info.bt_chip_type = BTC_CHIP_RTL8723B; - break; - } -} - -void exhalbtc_set_ant_num(u8 type, u8 ant_num) -{ - if (BT_COEX_ANT_TYPE_PG == type) { - gl_bt_coexist.board_info.pg_ant_num = ant_num; - gl_bt_coexist.board_info.btdm_ant_num = ant_num; - } else if (BT_COEX_ANT_TYPE_ANTDIV == type) { - gl_bt_coexist.board_info.btdm_ant_num = ant_num; - } -} - -void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist) -{ - struct rtl_priv *rtlpriv = btcoexist->adapter; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - if (!halbtc_is_bt_coexist_available(btcoexist)) - return; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) - ex_btc8723b2ant_display_coex_info(btcoexist); -} diff --git a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h deleted file mode 100644 index 0a903ea179ef..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.h +++ /dev/null @@ -1,545 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#ifndef __HALBTC_OUT_SRC_H__ -#define __HALBTC_OUT_SRC_H__ - -#include "../wifi.h" - -#define NORMAL_EXEC false -#define FORCE_EXEC true - -#define BTC_RF_A RF90_PATH_A -#define BTC_RF_B RF90_PATH_B -#define BTC_RF_C RF90_PATH_C -#define BTC_RF_D RF90_PATH_D - -#define BTC_SMSP SINGLEMAC_SINGLEPHY -#define BTC_DMDP DUALMAC_DUALPHY -#define BTC_DMSP DUALMAC_SINGLEPHY -#define BTC_MP_UNKNOWN 0xff - -#define IN -#define OUT - -#define BT_TMP_BUF_SIZE 100 - -#define BT_COEX_ANT_TYPE_PG 0 -#define BT_COEX_ANT_TYPE_ANTDIV 1 -#define BT_COEX_ANT_TYPE_DETECTED 2 - -#define BTC_MIMO_PS_STATIC 0 -#define BTC_MIMO_PS_DYNAMIC 1 - -#define BTC_RATE_DISABLE 0 -#define BTC_RATE_ENABLE 1 - -/* single Antenna definition */ -#define BTC_ANT_PATH_WIFI 0 -#define BTC_ANT_PATH_BT 1 -#define BTC_ANT_PATH_PTA 2 -/* dual Antenna definition */ -#define BTC_ANT_WIFI_AT_MAIN 0 -#define BTC_ANT_WIFI_AT_AUX 1 -/* coupler Antenna definition */ -#define BTC_ANT_WIFI_AT_CPL_MAIN 0 -#define BTC_ANT_WIFI_AT_CPL_AUX 1 - -enum btc_chip_interface { - BTC_INTF_UNKNOWN = 0, - BTC_INTF_PCI = 1, - BTC_INTF_USB = 2, - BTC_INTF_SDIO = 3, - BTC_INTF_GSPI = 4, - BTC_INTF_MAX -}; - -enum btc_chip_type { - BTC_CHIP_UNDEF = 0, - BTC_CHIP_CSR_BC4 = 1, - BTC_CHIP_CSR_BC8 = 2, - BTC_CHIP_RTL8723A = 3, - BTC_CHIP_RTL8821 = 4, - BTC_CHIP_RTL8723B = 5, - BTC_CHIP_MAX -}; - -enum btc_msg_type { - BTC_MSG_INTERFACE = 0x0, - BTC_MSG_ALGORITHM = 0x1, - BTC_MSG_MAX -}; - -extern u32 btc_dbg_type[]; - -/* following is for BTC_MSG_INTERFACE */ -#define INTF_INIT BIT0 -#define INTF_NOTIFY BIT2 - -/* following is for BTC_ALGORITHM */ -#define ALGO_BT_RSSI_STATE BIT0 -#define ALGO_WIFI_RSSI_STATE BIT1 -#define ALGO_BT_MONITOR BIT2 -#define ALGO_TRACE BIT3 -#define ALGO_TRACE_FW BIT4 -#define ALGO_TRACE_FW_DETAIL BIT5 -#define ALGO_TRACE_FW_EXEC BIT6 -#define ALGO_TRACE_SW BIT7 -#define ALGO_TRACE_SW_DETAIL BIT8 -#define ALGO_TRACE_SW_EXEC BIT9 - -/* following is for wifi link status */ -#define WIFI_STA_CONNECTED BIT0 -#define WIFI_AP_CONNECTED BIT1 -#define WIFI_HS_CONNECTED BIT2 -#define WIFI_P2P_GO_CONNECTED BIT3 -#define WIFI_P2P_GC_CONNECTED BIT4 - -#define BTC_PRINT(dbgtype, dbgflag, printstr, ...) \ - do { \ - if (unlikely(btc_dbg_type[dbgtype] & dbgflag)) {\ - printk(printstr, ##__VA_ARGS__); \ - } \ - } while (0) - -#define BTC_RSSI_HIGH(_rssi_) \ - ((_rssi_ == BTC_RSSI_STATE_HIGH || \ - _rssi_ == BTC_RSSI_STATE_STAY_HIGH) ? true : false) -#define BTC_RSSI_MEDIUM(_rssi_) \ - ((_rssi_ == BTC_RSSI_STATE_MEDIUM || \ - _rssi_ == BTC_RSSI_STATE_STAY_MEDIUM) ? true : false) -#define BTC_RSSI_LOW(_rssi_) \ - ((_rssi_ == BTC_RSSI_STATE_LOW || \ - _rssi_ == BTC_RSSI_STATE_STAY_LOW) ? true : false) - -enum btc_power_save_type { - BTC_PS_WIFI_NATIVE = 0, - BTC_PS_LPS_ON = 1, - BTC_PS_LPS_OFF = 2, - BTC_PS_LPS_MAX -}; - -struct btc_board_info { - /* The following is some board information */ - u8 bt_chip_type; - u8 pg_ant_num; /* pg ant number */ - u8 btdm_ant_num; /* ant number for btdm */ - u8 btdm_ant_pos; - bool bt_exist; -}; - -enum btc_dbg_opcode { - BTC_DBG_SET_COEX_NORMAL = 0x0, - BTC_DBG_SET_COEX_WIFI_ONLY = 0x1, - BTC_DBG_SET_COEX_BT_ONLY = 0x2, - BTC_DBG_MAX -}; - -enum btc_rssi_state { - BTC_RSSI_STATE_HIGH = 0x0, - BTC_RSSI_STATE_MEDIUM = 0x1, - BTC_RSSI_STATE_LOW = 0x2, - BTC_RSSI_STATE_STAY_HIGH = 0x3, - BTC_RSSI_STATE_STAY_MEDIUM = 0x4, - BTC_RSSI_STATE_STAY_LOW = 0x5, - BTC_RSSI_MAX -}; - -enum btc_wifi_role { - BTC_ROLE_STATION = 0x0, - BTC_ROLE_AP = 0x1, - BTC_ROLE_IBSS = 0x2, - BTC_ROLE_HS_MODE = 0x3, - BTC_ROLE_MAX -}; - -enum btc_wifi_bw_mode { - BTC_WIFI_BW_LEGACY = 0x0, - BTC_WIFI_BW_HT20 = 0x1, - BTC_WIFI_BW_HT40 = 0x2, - BTC_WIFI_BW_MAX -}; - -enum btc_wifi_traffic_dir { - BTC_WIFI_TRAFFIC_TX = 0x0, - BTC_WIFI_TRAFFIC_RX = 0x1, - BTC_WIFI_TRAFFIC_MAX -}; - -enum btc_wifi_pnp { - BTC_WIFI_PNP_WAKE_UP = 0x0, - BTC_WIFI_PNP_SLEEP = 0x1, - BTC_WIFI_PNP_MAX -}; - -enum btc_get_type { - /* type bool */ - BTC_GET_BL_HS_OPERATION, - BTC_GET_BL_HS_CONNECTING, - BTC_GET_BL_WIFI_CONNECTED, - BTC_GET_BL_WIFI_BUSY, - BTC_GET_BL_WIFI_SCAN, - BTC_GET_BL_WIFI_LINK, - BTC_GET_BL_WIFI_DHCP, - BTC_GET_BL_WIFI_SOFTAP_IDLE, - BTC_GET_BL_WIFI_SOFTAP_LINKING, - BTC_GET_BL_WIFI_IN_EARLY_SUSPEND, - BTC_GET_BL_WIFI_ROAM, - BTC_GET_BL_WIFI_4_WAY_PROGRESS, - BTC_GET_BL_WIFI_UNDER_5G, - BTC_GET_BL_WIFI_AP_MODE_ENABLE, - BTC_GET_BL_WIFI_ENABLE_ENCRYPTION, - BTC_GET_BL_WIFI_UNDER_B_MODE, - BTC_GET_BL_EXT_SWITCH, - - /* type s4Byte */ - BTC_GET_S4_WIFI_RSSI, - BTC_GET_S4_HS_RSSI, - - /* type u32 */ - BTC_GET_U4_WIFI_BW, - BTC_GET_U4_WIFI_TRAFFIC_DIRECTION, - BTC_GET_U4_WIFI_FW_VER, - BTC_GET_U4_WIFI_LINK_STATUS, - BTC_GET_U4_BT_PATCH_VER, - - /* type u1Byte */ - BTC_GET_U1_WIFI_DOT11_CHNL, - BTC_GET_U1_WIFI_CENTRAL_CHNL, - BTC_GET_U1_WIFI_HS_CHNL, - BTC_GET_U1_MAC_PHY_MODE, - BTC_GET_U1_AP_NUM, - - /* for 1Ant */ - BTC_GET_U1_LPS_MODE, - BTC_GET_BL_BT_SCO_BUSY, - - /* for test mode */ - BTC_GET_DRIVER_TEST_CFG, - BTC_GET_MAX -}; - -enum btc_set_type { - /* type bool */ - BTC_SET_BL_BT_DISABLE, - BTC_SET_BL_BT_TRAFFIC_BUSY, - BTC_SET_BL_BT_LIMITED_DIG, - BTC_SET_BL_FORCE_TO_ROAM, - BTC_SET_BL_TO_REJ_AP_AGG_PKT, - BTC_SET_BL_BT_CTRL_AGG_SIZE, - BTC_SET_BL_INC_SCAN_DEV_NUM, - - /* type u1Byte */ - BTC_SET_U1_RSSI_ADJ_VAL_FOR_AGC_TABLE_ON, - BTC_SET_UI_SCAN_SIG_COMPENSATION, - BTC_SET_U1_AGG_BUF_SIZE, - - /* type trigger some action */ - BTC_SET_ACT_GET_BT_RSSI, - BTC_SET_ACT_AGGREGATE_CTRL, - - /********* for 1Ant **********/ - /* type bool */ - BTC_SET_BL_BT_SCO_BUSY, - /* type u1Byte */ - BTC_SET_U1_RSSI_ADJ_VAL_FOR_1ANT_COEX_TYPE, - BTC_SET_U1_LPS_VAL, - BTC_SET_U1_RPWM_VAL, - BTC_SET_U1_1ANT_LPS, - BTC_SET_U1_1ANT_RPWM, - /* type trigger some action */ - BTC_SET_ACT_LEAVE_LPS, - BTC_SET_ACT_ENTER_LPS, - BTC_SET_ACT_NORMAL_LPS, - BTC_SET_ACT_INC_FORCE_EXEC_PWR_CMD_CNT, - BTC_SET_ACT_DISABLE_LOW_POWER, - BTC_SET_ACT_UPDATE_ra_mask, - BTC_SET_ACT_SEND_MIMO_PS, - /* BT Coex related */ - BTC_SET_ACT_CTRL_BT_INFO, - BTC_SET_ACT_CTRL_BT_COEX, - /***************************/ - BTC_SET_MAX -}; - -enum btc_dbg_disp_type { - BTC_DBG_DISP_COEX_STATISTICS = 0x0, - BTC_DBG_DISP_BT_LINK_INFO = 0x1, - BTC_DBG_DISP_BT_FW_VER = 0x2, - BTC_DBG_DISP_FW_PWR_MODE_CMD = 0x3, - BTC_DBG_DISP_MAX -}; - -enum btc_notify_type_ips { - BTC_IPS_LEAVE = 0x0, - BTC_IPS_ENTER = 0x1, - BTC_IPS_MAX -}; - -enum btc_notify_type_lps { - BTC_LPS_DISABLE = 0x0, - BTC_LPS_ENABLE = 0x1, - BTC_LPS_MAX -}; - -enum btc_notify_type_scan { - BTC_SCAN_FINISH = 0x0, - BTC_SCAN_START = 0x1, - BTC_SCAN_MAX -}; - -enum btc_notify_type_associate { - BTC_ASSOCIATE_FINISH = 0x0, - BTC_ASSOCIATE_START = 0x1, - BTC_ASSOCIATE_MAX -}; - -enum btc_notify_type_media_status { - BTC_MEDIA_DISCONNECT = 0x0, - BTC_MEDIA_CONNECT = 0x1, - BTC_MEDIA_MAX -}; - -enum btc_notify_type_special_packet { - BTC_PACKET_UNKNOWN = 0x0, - BTC_PACKET_DHCP = 0x1, - BTC_PACKET_ARP = 0x2, - BTC_PACKET_EAPOL = 0x3, - BTC_PACKET_MAX -}; - -enum hci_ext_bt_operation { - HCI_BT_OP_NONE = 0x0, - HCI_BT_OP_INQUIRY_START = 0x1, - HCI_BT_OP_INQUIRY_FINISH = 0x2, - HCI_BT_OP_PAGING_START = 0x3, - HCI_BT_OP_PAGING_SUCCESS = 0x4, - HCI_BT_OP_PAGING_UNSUCCESS = 0x5, - HCI_BT_OP_PAIRING_START = 0x6, - HCI_BT_OP_PAIRING_FINISH = 0x7, - HCI_BT_OP_BT_DEV_ENABLE = 0x8, - HCI_BT_OP_BT_DEV_DISABLE = 0x9, - HCI_BT_OP_MAX -}; - -enum btc_notify_type_stack_operation { - BTC_STACK_OP_NONE = 0x0, - BTC_STACK_OP_INQ_PAGE_PAIR_START = 0x1, - BTC_STACK_OP_INQ_PAGE_PAIR_FINISH = 0x2, - BTC_STACK_OP_MAX -}; - -typedef u8 (*bfp_btc_r1)(void *btc_context, u32 reg_addr); - -typedef u16 (*bfp_btc_r2)(void *btc_context, u32 reg_addr); - -typedef u32 (*bfp_btc_r4)(void *btc_context, u32 reg_addr); - -typedef void (*bfp_btc_w1)(void *btc_context, u32 reg_addr, u32 data); - -typedef void (*bfp_btc_w1_bit_mak)(void *btc_context, u32 reg_addr, - u32 bit_mask, u8 data1b); - -typedef void (*bfp_btc_w2)(void *btc_context, u32 reg_addr, u16 data); - -typedef void (*bfp_btc_w4)(void *btc_context, u32 reg_addr, u32 data); - -typedef void (*bfp_btc_wr_1byte_bit_mask)(void *btc_context, u32 reg_addr, - u8 bit_mask, u8 data); - -typedef void (*bfp_btc_set_bb_reg)(void *btc_context, u32 reg_addr, - u32 bit_mask, u32 data); - -typedef u32 (*bfp_btc_get_bb_reg)(void *btc_context, u32 reg_addr, - u32 bit_mask); - -typedef void (*bfp_btc_set_rf_reg)(void *btc_context, u8 rf_path, u32 reg_addr, - u32 bit_mask, u32 data); - -typedef u32 (*bfp_btc_get_rf_reg)(void *btc_context, u8 rf_path, - u32 reg_addr, u32 bit_mask); - -typedef void (*bfp_btc_fill_h2c)(void *btc_context, u8 element_id, - u32 cmd_len, u8 *cmd_buffer); - -typedef bool (*bfp_btc_get)(void *btcoexist, u8 get_type, void *out_buf); - -typedef bool (*bfp_btc_set)(void *btcoexist, u8 set_type, void *in_buf); - -typedef void (*bfp_btc_disp_dbg_msg)(void *btcoexist, u8 disp_type); - -struct btc_bt_info { - bool bt_disabled; - u8 rssi_adjust_for_agc_table_on; - u8 rssi_adjust_for_1ant_coex_type; - bool bt_busy; - u8 agg_buf_size; - bool limited_dig; - bool reject_agg_pkt; - bool bt_ctrl_buf_size; - bool increase_scan_dev_num; - u16 bt_hci_ver; - u16 bt_real_fw_ver; - u8 bt_fw_ver; - - bool bt_disable_low_pwr; - - /* the following is for 1Ant solution */ - bool bt_ctrl_lps; - bool bt_pwr_save_mode; - bool bt_lps_on; - bool force_to_roam; - u8 force_exec_pwr_cmd_cnt; - u8 lps_val; - u8 rpwm_val; - u32 ra_mask; -}; - -struct btc_stack_info { - bool profile_notified; - u16 hci_version; /* stack hci version */ - u8 num_of_link; - bool bt_link_exist; - bool sco_exist; - bool acl_exist; - bool a2dp_exist; - bool hid_exist; - u8 num_of_hid; - bool pan_exist; - bool unknown_acl_exist; - char min_bt_rssi; -}; - -struct btc_statistics { - u32 cnt_bind; - u32 cnt_init_hw_config; - u32 cnt_init_coex_dm; - u32 cnt_ips_notify; - u32 cnt_lps_notify; - u32 cnt_scan_notify; - u32 cnt_connect_notify; - u32 cnt_media_status_notify; - u32 cnt_special_packet_notify; - u32 cnt_bt_info_notify; - u32 cnt_periodical; - u32 cnt_coex_dm_switch; - u32 cnt_stack_operation_notify; - u32 cnt_dbg_ctrl; -}; - -struct btc_bt_link_info { - bool bt_link_exist; - bool sco_exist; - bool sco_only; - bool a2dp_exist; - bool a2dp_only; - bool hid_exist; - bool hid_only; - bool pan_exist; - bool pan_only; -}; - -enum btc_antenna_pos { - BTC_ANTENNA_AT_MAIN_PORT = 0x1, - BTC_ANTENNA_AT_AUX_PORT = 0x2, -}; - -struct btc_coexist { - /* make sure only one adapter can bind the data context */ - bool binded; - /* default adapter */ - void *adapter; - struct btc_board_info board_info; - /* some bt info referenced by non-bt module */ - struct btc_bt_info bt_info; - struct btc_stack_info stack_info; - enum btc_chip_interface chip_interface; - struct btc_bt_link_info bt_link_info; - - bool initilized; - bool stop_coex_dm; - bool manual_control; - struct btc_statistics statistics; - u8 pwr_mode_val[10]; - - /* function pointers - io related */ - bfp_btc_r1 btc_read_1byte; - bfp_btc_w1 btc_write_1byte; - bfp_btc_w1_bit_mak btc_write_1byte_bitmask; - bfp_btc_r2 btc_read_2byte; - bfp_btc_w2 btc_write_2byte; - bfp_btc_r4 btc_read_4byte; - bfp_btc_w4 btc_write_4byte; - - bfp_btc_set_bb_reg btc_set_bb_reg; - bfp_btc_get_bb_reg btc_get_bb_reg; - - bfp_btc_set_rf_reg btc_set_rf_reg; - bfp_btc_get_rf_reg btc_get_rf_reg; - - bfp_btc_fill_h2c btc_fill_h2c; - - bfp_btc_disp_dbg_msg btc_disp_dbg_msg; - - bfp_btc_get btc_get; - bfp_btc_set btc_set; -}; - -bool halbtc_is_wifi_uplink(struct rtl_priv *adapter); - -extern struct btc_coexist gl_bt_coexist; - -bool exhalbtc_initlize_variables(struct rtl_priv *adapter); -void exhalbtc_init_hw_config(struct btc_coexist *btcoexist); -void exhalbtc_init_coex_dm(struct btc_coexist *btcoexist); -void exhalbtc_ips_notify(struct btc_coexist *btcoexist, u8 type); -void exhalbtc_lps_notify(struct btc_coexist *btcoexist, u8 type); -void exhalbtc_scan_notify(struct btc_coexist *btcoexist, u8 type); -void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action); -void exhalbtc_mediastatus_notify(struct btc_coexist *btcoexist, - enum rt_media_status media_status); -void exhalbtc_special_packet_notify(struct btc_coexist *btcoexist, u8 pkt_type); -void exhalbtc_bt_info_notify(struct btc_coexist *btcoexist, u8 *tmp_buf, - u8 length); -void exhalbtc_stack_operation_notify(struct btc_coexist *btcoexist, u8 type); -void exhalbtc_halt_notify(struct btc_coexist *btcoexist); -void exhalbtc_pnp_notify(struct btc_coexist *btcoexist, u8 pnp_state); -void exhalbtc_coex_dm_switch(struct btc_coexist *btcoexist); -void exhalbtc_periodical(struct btc_coexist *btcoexist); -void exhalbtc_dbg_control(struct btc_coexist *btcoexist, u8 code, u8 len, - u8 *data); -void exhalbtc_stack_update_profile_info(void); -void exhalbtc_set_hci_version(u16 hci_version); -void exhalbtc_set_bt_patch_version(u16 bt_hci_version, u16 bt_patch_version); -void exhalbtc_update_min_bt_rssi(char bt_rssi); -void exhalbtc_set_bt_exist(bool bt_exist); -void exhalbtc_set_chip_type(u8 chip_type); -void exhalbtc_set_ant_num(u8 type, u8 ant_num); -void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist); -void exhalbtc_signal_compensation(struct btc_coexist *btcoexist, - u8 *rssi_wifi, u8 *rssi_bt); -void exhalbtc_lps_leave(struct btc_coexist *btcoexist); -void exhalbtc_low_wifi_traffic_notify(struct btc_coexist *btcoexist); - -#endif diff --git a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c deleted file mode 100644 index b9b0cb7af8ea..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.c +++ /dev/null @@ -1,231 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#include "../wifi.h" -#include -#include - -#include "rtl_btc.h" -#include "halbt_precomp.h" - -static struct rtl_btc_ops rtl_btc_operation = { - .btc_init_variables = rtl_btc_init_variables, - .btc_init_hal_vars = rtl_btc_init_hal_vars, - .btc_init_hw_config = rtl_btc_init_hw_config, - .btc_ips_notify = rtl_btc_ips_notify, - .btc_lps_notify = rtl_btc_lps_notify, - .btc_scan_notify = rtl_btc_scan_notify, - .btc_connect_notify = rtl_btc_connect_notify, - .btc_mediastatus_notify = rtl_btc_mediastatus_notify, - .btc_periodical = rtl_btc_periodical, - .btc_halt_notify = rtl_btc_halt_notify, - .btc_btinfo_notify = rtl_btc_btinfo_notify, - .btc_is_limited_dig = rtl_btc_is_limited_dig, - .btc_is_disable_edca_turbo = rtl_btc_is_disable_edca_turbo, - .btc_is_bt_disabled = rtl_btc_is_bt_disabled, - .btc_special_packet_notify = rtl_btc_special_packet_notify, -}; - -void rtl_btc_init_variables(struct rtl_priv *rtlpriv) -{ - exhalbtc_initlize_variables(rtlpriv); -} - -void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv) -{ - u8 ant_num; - u8 bt_exist; - u8 bt_type; - - ant_num = rtl_get_hwpg_ant_num(rtlpriv); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "%s, antNum is %d\n", __func__, ant_num); - - bt_exist = rtl_get_hwpg_bt_exist(rtlpriv); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "%s, bt_exist is %d\n", __func__, bt_exist); - exhalbtc_set_bt_exist(bt_exist); - - bt_type = rtl_get_hwpg_bt_type(rtlpriv); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%s, bt_type is %d\n", - __func__, bt_type); - exhalbtc_set_chip_type(bt_type); - - exhalbtc_set_ant_num(BT_COEX_ANT_TYPE_PG, ant_num); -} - -void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv) -{ - exhalbtc_init_hw_config(&gl_bt_coexist); - exhalbtc_init_coex_dm(&gl_bt_coexist); -} - -void rtl_btc_ips_notify(struct rtl_priv *rtlpriv, u8 type) -{ - exhalbtc_ips_notify(&gl_bt_coexist, type); -} - -void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type) -{ - exhalbtc_lps_notify(&gl_bt_coexist, type); -} - -void rtl_btc_scan_notify(struct rtl_priv *rtlpriv, u8 scantype) -{ - exhalbtc_scan_notify(&gl_bt_coexist, scantype); -} - -void rtl_btc_connect_notify(struct rtl_priv *rtlpriv, u8 action) -{ - exhalbtc_connect_notify(&gl_bt_coexist, action); -} - -void rtl_btc_mediastatus_notify(struct rtl_priv *rtlpriv, - enum rt_media_status mstatus) -{ - exhalbtc_mediastatus_notify(&gl_bt_coexist, mstatus); -} - -void rtl_btc_periodical(struct rtl_priv *rtlpriv) -{ - /*rtl_bt_dm_monitor();*/ - exhalbtc_periodical(&gl_bt_coexist); -} - -void rtl_btc_halt_notify(void) -{ - exhalbtc_halt_notify(&gl_bt_coexist); -} - -void rtl_btc_btinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length) -{ - exhalbtc_bt_info_notify(&gl_bt_coexist, tmp_buf, length); -} - -bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv) -{ - return gl_bt_coexist.bt_info.limited_dig; -} - -bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv) -{ - bool bt_change_edca = false; - u32 cur_edca_val; - u32 edca_bt_hs_uplink = 0x5ea42b, edca_bt_hs_downlink = 0x5ea42b; - u32 edca_hs; - u32 edca_addr = 0x504; - - cur_edca_val = rtl_read_dword(rtlpriv, edca_addr); - if (halbtc_is_wifi_uplink(rtlpriv)) { - if (cur_edca_val != edca_bt_hs_uplink) { - edca_hs = edca_bt_hs_uplink; - bt_change_edca = true; - } - } else { - if (cur_edca_val != edca_bt_hs_downlink) { - edca_hs = edca_bt_hs_downlink; - bt_change_edca = true; - } - } - - if (bt_change_edca) - rtl_write_dword(rtlpriv, edca_addr, edca_hs); - - return true; -} - -bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv) -{ - /* It seems 'bt_disabled' is never be initialized or set. */ - if (gl_bt_coexist.bt_info.bt_disabled) - return true; - else - return false; -} - -void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type) -{ - return exhalbtc_special_packet_notify(&gl_bt_coexist, pkt_type); -} - -struct rtl_btc_ops *rtl_btc_get_ops_pointer(void) -{ - return &rtl_btc_operation; -} -EXPORT_SYMBOL(rtl_btc_get_ops_pointer); - -u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv) -{ - u8 num; - - if (rtlpriv->btcoexist.btc_info.ant_num == ANT_X2) - num = 2; - else - num = 1; - - return num; -} - -enum rt_media_status mgnt_link_status_query(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - enum rt_media_status m_status = RT_MEDIA_DISCONNECT; - - u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0; - - if (bibss || rtlpriv->mac80211.link_state >= MAC80211_LINKED) - m_status = RT_MEDIA_CONNECT; - - return m_status; -} - -u8 rtl_get_hwpg_bt_exist(struct rtl_priv *rtlpriv) -{ - return rtlpriv->btcoexist.btc_info.btcoexist; -} - -u8 rtl_get_hwpg_bt_type(struct rtl_priv *rtlpriv) -{ - return rtlpriv->btcoexist.btc_info.bt_type; -} - -MODULE_AUTHOR("Page He "); -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_AUTHOR("Larry Finger "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core"); - -static int __init rtl_btcoexist_module_init(void) -{ - return 0; -} - -static void __exit rtl_btcoexist_module_exit(void) -{ - return; -} - -module_init(rtl_btcoexist_module_init); -module_exit(rtl_btcoexist_module_exit); diff --git a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h b/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h deleted file mode 100644 index ccd5a0f91e3b..000000000000 --- a/drivers/net/wireless/rtlwifi/btcoexist/rtl_btc.h +++ /dev/null @@ -1,54 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL_BTC_H__ -#define __RTL_BTC_H__ - -#include "halbt_precomp.h" - -void rtl_btc_init_variables(struct rtl_priv *rtlpriv); -void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv); -void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv); -void rtl_btc_ips_notify(struct rtl_priv *rtlpriv, u8 type); -void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type); -void rtl_btc_scan_notify(struct rtl_priv *rtlpriv, u8 scantype); -void rtl_btc_connect_notify(struct rtl_priv *rtlpriv, u8 action); -void rtl_btc_mediastatus_notify(struct rtl_priv *rtlpriv, - enum rt_media_status mstatus); -void rtl_btc_periodical(struct rtl_priv *rtlpriv); -void rtl_btc_halt_notify(void); -void rtl_btc_btinfo_notify(struct rtl_priv *rtlpriv, u8 *tmpbuf, u8 length); -bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv); -bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv); -bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv); -void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type); - -struct rtl_btc_ops *rtl_btc_get_ops_pointer(void); - -u8 rtl_get_hwpg_ant_num(struct rtl_priv *rtlpriv); -u8 rtl_get_hwpg_bt_exist(struct rtl_priv *rtlpriv); -u8 rtl_get_hwpg_bt_type(struct rtl_priv *rtlpriv); -enum rt_media_status mgnt_link_status_query(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c deleted file mode 100644 index 8fe8b4cfae6c..000000000000 --- a/drivers/net/wireless/rtlwifi/cam.c +++ /dev/null @@ -1,347 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#include "wifi.h" -#include "cam.h" -#include - -void rtl_cam_reset_sec_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->sec.use_defaultkey = false; - rtlpriv->sec.pairwise_enc_algorithm = NO_ENCRYPTION; - rtlpriv->sec.group_enc_algorithm = NO_ENCRYPTION; - memset(rtlpriv->sec.key_buf, 0, KEY_BUF_SIZE * MAX_KEY_LEN); - memset(rtlpriv->sec.key_len, 0, KEY_BUF_SIZE); - rtlpriv->sec.pairwise_key = NULL; -} - -static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, - u8 *mac_addr, u8 *key_cont_128, u16 us_config) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - u32 target_command; - u32 target_content = 0; - u8 entry_i; - - RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_DMESG, "Key content :", - key_cont_128, 16); - - for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { - target_command = entry_i + CAM_CONTENT_COUNT * entry_no; - target_command = target_command | BIT(31) | BIT(16); - - if (entry_i == 0) { - target_content = (u32) (*(mac_addr + 0)) << 16 | - (u32) (*(mac_addr + 1)) << 24 | (u32) us_config; - - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], - target_content); - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], - target_command); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "WRITE %x: %x\n", - rtlpriv->cfg->maps[WCAMI], target_content); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "The Key ID is %d\n", entry_no); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "WRITE %x: %x\n", - rtlpriv->cfg->maps[RWCAM], target_command); - - } else if (entry_i == 1) { - - target_content = (u32) (*(mac_addr + 5)) << 24 | - (u32) (*(mac_addr + 4)) << 16 | - (u32) (*(mac_addr + 3)) << 8 | - (u32) (*(mac_addr + 2)); - - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], - target_content); - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], - target_command); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "WRITE A4: %x\n", target_content); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "WRITE A0: %x\n", target_command); - - } else { - - target_content = - (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 3)) << - 24 | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 2)) - << 16 | - (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 1)) << 8 - | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 0)); - - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], - target_content); - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], - target_command); - udelay(100); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "WRITE A4: %x\n", target_content); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "WRITE A0: %x\n", target_command); - } - } - - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "after set key, usconfig:%x\n", us_config); -} - -u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, - u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg, - u32 ul_default_key, u8 *key_content) -{ - u32 us_config; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n", - ul_entry_idx, ul_key_id, ul_enc_alg, - ul_default_key, mac_addr); - - if (ul_key_id == TOTAL_CAM_ENTRY) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "ulKeyId exceed!\n"); - return 0; - } - - if (ul_default_key == 1) - us_config = CFG_VALID | ((u16) (ul_enc_alg) << 2); - else - us_config = CFG_VALID | ((ul_enc_alg) << 2) | ul_key_id; - - rtl_cam_program_entry(hw, ul_entry_idx, mac_addr, - (u8 *)key_content, us_config); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "end\n"); - - return 1; - -} -EXPORT_SYMBOL(rtl_cam_add_one_entry); - -int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, - u8 *mac_addr, u32 ul_key_id) -{ - u32 ul_command; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "key_idx:%d\n", ul_key_id); - - ul_command = ul_key_id * CAM_CONTENT_COUNT; - ul_command = ul_command | BIT(31) | BIT(16); - - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 0); - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "rtl_cam_delete_one_entry(): WRITE A4: %x\n", 0); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "rtl_cam_delete_one_entry(): WRITE A0: %x\n", ul_command); - - return 0; - -} -EXPORT_SYMBOL(rtl_cam_delete_one_entry); - -void rtl_cam_reset_all_entry(struct ieee80211_hw *hw) -{ - u32 ul_command; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - ul_command = BIT(31) | BIT(30); - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); -} -EXPORT_SYMBOL(rtl_cam_reset_all_entry); - -void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - u32 ul_command; - u32 ul_content; - u32 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; - - switch (rtlpriv->sec.pairwise_enc_algorithm) { - case WEP40_ENCRYPTION: - ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP40]; - break; - case WEP104_ENCRYPTION: - ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP104]; - break; - case TKIP_ENCRYPTION: - ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_TKIP]; - break; - case AESCCMP_ENCRYPTION: - ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; - break; - default: - ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES]; - } - - ul_content = (uc_index & 3) | ((u16) (ul_enc_algo) << 2); - - ul_content |= BIT(15); - ul_command = CAM_CONTENT_COUNT * uc_index; - ul_command = ul_command | BIT(31) | BIT(16); - - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content); - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "rtl_cam_mark_invalid(): WRITE A4: %x\n", ul_content); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "rtl_cam_mark_invalid(): WRITE A0: %x\n", ul_command); -} -EXPORT_SYMBOL(rtl_cam_mark_invalid); - -void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - u32 ul_command; - u32 ul_content; - u32 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; - u8 entry_i; - - switch (rtlpriv->sec.pairwise_enc_algorithm) { - case WEP40_ENCRYPTION: - ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP40]; - break; - case WEP104_ENCRYPTION: - ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP104]; - break; - case TKIP_ENCRYPTION: - ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_TKIP]; - break; - case AESCCMP_ENCRYPTION: - ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; - break; - default: - ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES]; - } - - for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { - - if (entry_i == 0) { - ul_content = - (uc_index & 0x03) | ((u16) (ul_encalgo) << 2); - ul_content |= BIT(15); - - } else { - ul_content = 0; - } - - ul_command = CAM_CONTENT_COUNT * uc_index + entry_i; - ul_command = ul_command | BIT(31) | BIT(16); - - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content); - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "rtl_cam_empty_entry(): WRITE A4: %x\n", - ul_content); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "rtl_cam_empty_entry(): WRITE A0: %x\n", - ul_command); - } - -} -EXPORT_SYMBOL(rtl_cam_empty_entry); - -u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> 4; - u8 entry_idx = 0; - u8 i, *addr; - - if (NULL == sta_addr) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, - "sta_addr is NULL.\n"); - return TOTAL_CAM_ENTRY; - } - /* Does STA already exist? */ - for (i = 4; i < TOTAL_CAM_ENTRY; i++) { - addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; - if (ether_addr_equal_unaligned(addr, sta_addr)) - return i; - } - /* Get a free CAM entry. */ - for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY; entry_idx++) { - if ((bitmap & BIT(0)) == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, - "-----hwsec_cam_bitmap: 0x%x entry_idx=%d\n", - rtlpriv->sec.hwsec_cam_bitmap, entry_idx); - rtlpriv->sec.hwsec_cam_bitmap |= BIT(0) << entry_idx; - memcpy(rtlpriv->sec.hwsec_cam_sta_addr[entry_idx], - sta_addr, ETH_ALEN); - return entry_idx; - } - bitmap = bitmap >> 1; - } - return TOTAL_CAM_ENTRY; -} -EXPORT_SYMBOL(rtl_cam_get_free_entry); - -void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 bitmap; - u8 i, *addr; - - if (NULL == sta_addr) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, - "sta_addr is NULL.\n"); - return; - } - - if (is_zero_ether_addr(sta_addr)) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, - "sta_addr is %pM\n", sta_addr); - return; - } - /* Does STA already exist? */ - for (i = 4; i < TOTAL_CAM_ENTRY; i++) { - addr = rtlpriv->sec.hwsec_cam_sta_addr[i]; - bitmap = (rtlpriv->sec.hwsec_cam_bitmap) >> i; - if (((bitmap & BIT(0)) == BIT(0)) && - (ether_addr_equal_unaligned(addr, sta_addr))) { - /* Remove from HW Security CAM */ - eth_zero_addr(rtlpriv->sec.hwsec_cam_sta_addr[i]); - rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "&&&&&&&&&del entry %d\n", i); - } - } - return; -} -EXPORT_SYMBOL(rtl_cam_del_entry); diff --git a/drivers/net/wireless/rtlwifi/cam.h b/drivers/net/wireless/rtlwifi/cam.h deleted file mode 100644 index e2e647d511c1..000000000000 --- a/drivers/net/wireless/rtlwifi/cam.h +++ /dev/null @@ -1,50 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL_CAM_H_ -#define __RTL_CAM_H_ - -#define CAM_CONTENT_COUNT 8 - -#define CFG_VALID BIT(15) - -#define PAIRWISE_KEYIDX 0 -#define CAM_PAIRWISE_KEY_POSITION 4 - -#define CAM_CONFIG_NO_USEDK 0 - -void rtl_cam_reset_all_entry(struct ieee80211_hw *hw); -u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, - u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg, - u32 ul_default_key, u8 *key_content); -int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, u8 *mac_addr, - u32 ul_key_id); -void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index); -void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index); -void rtl_cam_reset_sec_info(struct ieee80211_hw *hw); -u8 rtl_cam_get_free_entry(struct ieee80211_hw *hw, u8 *sta_addr); -void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr); - -#endif diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c deleted file mode 100644 index c925a4dff599..000000000000 --- a/drivers/net/wireless/rtlwifi/core.c +++ /dev/null @@ -1,1924 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "wifi.h" -#include "core.h" -#include "cam.h" -#include "base.h" -#include "ps.h" -#include "pwrseqcmd.h" - -#include "btcoexist/rtl_btc.h" -#include -#include -#include - -void rtl_addr_delay(u32 addr) -{ - if (addr == 0xfe) - mdelay(50); - else if (addr == 0xfd) - mdelay(5); - else if (addr == 0xfc) - mdelay(1); - else if (addr == 0xfb) - udelay(50); - else if (addr == 0xfa) - udelay(5); - else if (addr == 0xf9) - udelay(1); -} -EXPORT_SYMBOL(rtl_addr_delay); - -void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr, - u32 mask, u32 data) -{ - if (addr == 0xfe) { - mdelay(50); - } else if (addr == 0xfd) { - mdelay(5); - } else if (addr == 0xfc) { - mdelay(1); - } else if (addr == 0xfb) { - udelay(50); - } else if (addr == 0xfa) { - udelay(5); - } else if (addr == 0xf9) { - udelay(1); - } else { - rtl_set_rfreg(hw, rfpath, addr, mask, data); - udelay(1); - } -} -EXPORT_SYMBOL(rtl_rfreg_delay); - -void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data) -{ - if (addr == 0xfe) { - mdelay(50); - } else if (addr == 0xfd) { - mdelay(5); - } else if (addr == 0xfc) { - mdelay(1); - } else if (addr == 0xfb) { - udelay(50); - } else if (addr == 0xfa) { - udelay(5); - } else if (addr == 0xf9) { - udelay(1); - } else { - rtl_set_bbreg(hw, addr, MASKDWORD, data); - udelay(1); - } -} -EXPORT_SYMBOL(rtl_bb_delay); - -static void rtl_fw_do_work(const struct firmware *firmware, void *context, - bool is_wow) -{ - struct ieee80211_hw *hw = context; - struct rtl_priv *rtlpriv = rtl_priv(hw); - int err; - - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "Firmware callback routine entered!\n"); - complete(&rtlpriv->firmware_loading_complete); - if (!firmware) { - if (rtlpriv->cfg->alt_fw_name) { - err = request_firmware(&firmware, - rtlpriv->cfg->alt_fw_name, - rtlpriv->io.dev); - pr_info("Loading alternative firmware %s\n", - rtlpriv->cfg->alt_fw_name); - if (!err) - goto found_alt; - } - pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name); - rtlpriv->max_fw_size = 0; - return; - } -found_alt: - if (firmware->size > rtlpriv->max_fw_size) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Firmware is too big!\n"); - release_firmware(firmware); - return; - } - if (!is_wow) { - memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, - firmware->size); - rtlpriv->rtlhal.fwsize = firmware->size; - } else { - memcpy(rtlpriv->rtlhal.wowlan_firmware, firmware->data, - firmware->size); - rtlpriv->rtlhal.wowlan_fwsize = firmware->size; - } - rtlpriv->rtlhal.fwsize = firmware->size; - release_firmware(firmware); -} - -void rtl_fw_cb(const struct firmware *firmware, void *context) -{ - rtl_fw_do_work(firmware, context, false); -} -EXPORT_SYMBOL(rtl_fw_cb); - -void rtl_wowlan_fw_cb(const struct firmware *firmware, void *context) -{ - rtl_fw_do_work(firmware, context, true); -} -EXPORT_SYMBOL(rtl_wowlan_fw_cb); - -/*mutex for start & stop is must here. */ -static int rtl_op_start(struct ieee80211_hw *hw) -{ - int err = 0; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (!is_hal_stop(rtlhal)) - return 0; - if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) - return 0; - mutex_lock(&rtlpriv->locks.conf_mutex); - err = rtlpriv->intf_ops->adapter_start(hw); - if (!err) - rtl_watch_dog_timer_callback((unsigned long)hw); - mutex_unlock(&rtlpriv->locks.conf_mutex); - return err; -} - -static void rtl_op_stop(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool support_remote_wakeup = false; - - if (is_hal_stop(rtlhal)) - return; - - rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, - (u8 *)(&support_remote_wakeup)); - /* here is must, because adhoc do stop and start, - * but stop with RFOFF may cause something wrong, - * like adhoc TP - */ - if (unlikely(ppsc->rfpwr_state == ERFOFF)) - rtl_ips_nic_on(hw); - - mutex_lock(&rtlpriv->locks.conf_mutex); - /* if wowlan supported, DON'T clear connected info */ - if (!(support_remote_wakeup && - rtlhal->enter_pnp_sleep)) { - mac->link_state = MAC80211_NOLINK; - eth_zero_addr(mac->bssid); - mac->vendor = PEER_UNKNOWN; - - /* reset sec info */ - rtl_cam_reset_sec_info(hw); - - rtl_deinit_deferred_work(hw); - } - rtlpriv->intf_ops->adapter_stop(hw); - - mutex_unlock(&rtlpriv->locks.conf_mutex); -} - -static void rtl_op_tx(struct ieee80211_hw *hw, - struct ieee80211_tx_control *control, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_tcb_desc tcb_desc; - memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); - - if (unlikely(is_hal_stop(rtlhal) || ppsc->rfpwr_state != ERFON)) - goto err_free; - - if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) - goto err_free; - - if (!rtlpriv->intf_ops->waitq_insert(hw, control->sta, skb)) - rtlpriv->intf_ops->adapter_tx(hw, control->sta, skb, &tcb_desc); - return; - -err_free: - dev_kfree_skb_any(skb); -} - -static int rtl_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - int err = 0; - - if (mac->vif) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "vif has been set!! mac->vif = 0x%p\n", mac->vif); - return -EOPNOTSUPP; - } - - vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER; - - rtl_ips_nic_on(hw); - - mutex_lock(&rtlpriv->locks.conf_mutex); - switch (ieee80211_vif_type_p2p(vif)) { - case NL80211_IFTYPE_P2P_CLIENT: - mac->p2p = P2P_ROLE_CLIENT; - /*fall through*/ - case NL80211_IFTYPE_STATION: - if (mac->beacon_enabled == 1) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "NL80211_IFTYPE_STATION\n"); - mac->beacon_enabled = 0; - rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, - rtlpriv->cfg->maps[RTL_IBSS_INT_MASKS]); - } - break; - case NL80211_IFTYPE_ADHOC: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "NL80211_IFTYPE_ADHOC\n"); - - mac->link_state = MAC80211_LINKED; - rtlpriv->cfg->ops->set_bcn_reg(hw); - if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) - mac->basic_rates = 0xfff; - else - mac->basic_rates = 0xff0; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, - (u8 *)(&mac->basic_rates)); - - break; - case NL80211_IFTYPE_P2P_GO: - mac->p2p = P2P_ROLE_GO; - /*fall through*/ - case NL80211_IFTYPE_AP: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "NL80211_IFTYPE_AP\n"); - - mac->link_state = MAC80211_LINKED; - rtlpriv->cfg->ops->set_bcn_reg(hw); - if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) - mac->basic_rates = 0xfff; - else - mac->basic_rates = 0xff0; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, - (u8 *)(&mac->basic_rates)); - break; - case NL80211_IFTYPE_MESH_POINT: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "NL80211_IFTYPE_MESH_POINT\n"); - - mac->link_state = MAC80211_LINKED; - rtlpriv->cfg->ops->set_bcn_reg(hw); - if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) - mac->basic_rates = 0xfff; - else - mac->basic_rates = 0xff0; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, - (u8 *)(&mac->basic_rates)); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "operation mode %d is not support!\n", vif->type); - err = -EOPNOTSUPP; - goto out; - } - - if (mac->p2p) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "p2p role %x\n", vif->type); - mac->basic_rates = 0xff0;/*disable cck rate for p2p*/ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, - (u8 *)(&mac->basic_rates)); - } - mac->vif = vif; - mac->opmode = vif->type; - rtlpriv->cfg->ops->set_network_type(hw, vif->type); - memcpy(mac->mac_addr, vif->addr, ETH_ALEN); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); - -out: - mutex_unlock(&rtlpriv->locks.conf_mutex); - return err; -} - -static void rtl_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - mutex_lock(&rtlpriv->locks.conf_mutex); - - /* Free beacon resources */ - if ((vif->type == NL80211_IFTYPE_AP) || - (vif->type == NL80211_IFTYPE_ADHOC) || - (vif->type == NL80211_IFTYPE_MESH_POINT)) { - if (mac->beacon_enabled == 1) { - mac->beacon_enabled = 0; - rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, - rtlpriv->cfg->maps[RTL_IBSS_INT_MASKS]); - } - } - - /* - *Note: We assume NL80211_IFTYPE_UNSPECIFIED as - *NO LINK for our hardware. - */ - mac->p2p = 0; - mac->vif = NULL; - mac->link_state = MAC80211_NOLINK; - eth_zero_addr(mac->bssid); - mac->vendor = PEER_UNKNOWN; - mac->opmode = NL80211_IFTYPE_UNSPECIFIED; - rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); - - mutex_unlock(&rtlpriv->locks.conf_mutex); -} -static int rtl_op_change_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum nl80211_iftype new_type, bool p2p) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int ret; - rtl_op_remove_interface(hw, vif); - - vif->type = new_type; - vif->p2p = p2p; - ret = rtl_op_add_interface(hw, vif); - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "p2p %x\n", p2p); - return ret; -} - -#ifdef CONFIG_PM -static u16 crc16_ccitt(u8 data, u16 crc) -{ - u8 shift_in, data_bit, crc_bit11, crc_bit4, crc_bit15; - u8 i; - u16 result; - - for (i = 0; i < 8; i++) { - crc_bit15 = ((crc & BIT(15)) ? 1 : 0); - data_bit = (data & (BIT(0) << i) ? 1 : 0); - shift_in = crc_bit15 ^ data_bit; - - result = crc << 1; - if (shift_in == 0) - result &= (~BIT(0)); - else - result |= BIT(0); - - crc_bit11 = ((crc & BIT(11)) ? 1 : 0) ^ shift_in; - if (crc_bit11 == 0) - result &= (~BIT(12)); - else - result |= BIT(12); - - crc_bit4 = ((crc & BIT(4)) ? 1 : 0) ^ shift_in; - if (crc_bit4 == 0) - result &= (~BIT(5)); - else - result |= BIT(5); - - crc = result; - } - - return crc; -} - -static u16 _calculate_wol_pattern_crc(u8 *pattern, u16 len) -{ - u16 crc = 0xffff; - u32 i; - - for (i = 0; i < len; i++) - crc = crc16_ccitt(pattern[i], crc); - - crc = ~crc; - - return crc; -} - -static void _rtl_add_wowlan_patterns(struct ieee80211_hw *hw, - struct cfg80211_wowlan *wow) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = &rtlpriv->mac80211; - struct cfg80211_pkt_pattern *patterns = wow->patterns; - struct rtl_wow_pattern rtl_pattern; - const u8 *pattern_os, *mask_os; - u8 mask[MAX_WOL_BIT_MASK_SIZE] = {0}; - u8 content[MAX_WOL_PATTERN_SIZE] = {0}; - u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - u8 multicast_addr1[2] = {0x33, 0x33}; - u8 multicast_addr2[3] = {0x01, 0x00, 0x5e}; - u8 i, mask_len; - u16 j, len; - - for (i = 0; i < wow->n_patterns; i++) { - memset(&rtl_pattern, 0, sizeof(struct rtl_wow_pattern)); - memset(mask, 0, MAX_WOL_BIT_MASK_SIZE); - if (patterns[i].pattern_len > MAX_WOL_PATTERN_SIZE) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_WARNING, - "Pattern[%d] is too long\n", i); - continue; - } - pattern_os = patterns[i].pattern; - mask_len = DIV_ROUND_UP(patterns[i].pattern_len, 8); - mask_os = patterns[i].mask; - RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, - "pattern content\n", pattern_os, - patterns[i].pattern_len); - RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, - "mask content\n", mask_os, mask_len); - /* 1. unicast? multicast? or broadcast? */ - if (memcmp(pattern_os, broadcast_addr, 6) == 0) - rtl_pattern.type = BROADCAST_PATTERN; - else if (memcmp(pattern_os, multicast_addr1, 2) == 0 || - memcmp(pattern_os, multicast_addr2, 3) == 0) - rtl_pattern.type = MULTICAST_PATTERN; - else if (memcmp(pattern_os, mac->mac_addr, 6) == 0) - rtl_pattern.type = UNICAST_PATTERN; - else - rtl_pattern.type = UNKNOWN_TYPE; - - /* 2. translate mask_from_os to mask_for_hw */ - -/****************************************************************************** - * pattern from OS uses 'ethenet frame', like this: - - | 6 | 6 | 2 | 20 | Variable | 4 | - |--------+--------+------+-----------+------------+-----| - | 802.3 Mac Header | IP Header | TCP Packet | FCS | - | DA | SA | Type | - - * BUT, packet catched by our HW is in '802.11 frame', begin from LLC, - - | 24 or 30 | 6 | 2 | 20 | Variable | 4 | - |-------------------+--------+------+-----------+------------+-----| - | 802.11 MAC Header | LLC | IP Header | TCP Packet | FCS | - | Others | Tpye | - - * Therefore, we need translate mask_from_OS to mask_to_hw. - * We should left-shift mask by 6 bits, then set the new bit[0~5] = 0, - * because new mask[0~5] means 'SA', but our HW packet begins from LLC, - * bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match. - ******************************************************************************/ - - /* Shift 6 bits */ - for (j = 0; j < mask_len - 1; j++) { - mask[j] = mask_os[j] >> 6; - mask[j] |= (mask_os[j + 1] & 0x3F) << 2; - } - mask[j] = (mask_os[j] >> 6) & 0x3F; - /* Set bit 0-5 to zero */ - mask[0] &= 0xC0; - - RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, - "mask to hw\n", mask, mask_len); - for (j = 0; j < (MAX_WOL_BIT_MASK_SIZE + 1) / 4; j++) { - rtl_pattern.mask[j] = mask[j * 4]; - rtl_pattern.mask[j] |= (mask[j * 4 + 1] << 8); - rtl_pattern.mask[j] |= (mask[j * 4 + 2] << 16); - rtl_pattern.mask[j] |= (mask[j * 4 + 3] << 24); - } - - /* To get the wake up pattern from the mask. - * We do not count first 12 bits which means - * DA[6] and SA[6] in the pattern to match HW design. - */ - len = 0; - for (j = 12; j < patterns[i].pattern_len; j++) { - if ((mask_os[j / 8] >> (j % 8)) & 0x01) { - content[len] = pattern_os[j]; - len++; - } - } - - RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, - "pattern to hw\n", content, len); - /* 3. calculate crc */ - rtl_pattern.crc = _calculate_wol_pattern_crc(content, len); - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "CRC_Remainder = 0x%x", rtl_pattern.crc); - - /* 4. write crc & mask_for_hw to hw */ - rtlpriv->cfg->ops->add_wowlan_pattern(hw, &rtl_pattern, i); - } - rtl_write_byte(rtlpriv, 0x698, wow->n_patterns); -} - -static int rtl_op_suspend(struct ieee80211_hw *hw, - struct cfg80211_wowlan *wow) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct timeval ts; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n"); - if (WARN_ON(!wow)) - return -EINVAL; - - /* to resolve s4 can not wake up*/ - do_gettimeofday(&ts); - rtlhal->last_suspend_sec = ts.tv_sec; - - if ((ppsc->wo_wlan_mode & WAKE_ON_PATTERN_MATCH) && wow->n_patterns) - _rtl_add_wowlan_patterns(hw, wow); - - rtlhal->driver_is_goingto_unload = true; - rtlhal->enter_pnp_sleep = true; - - rtl_lps_leave(hw); - rtl_op_stop(hw); - device_set_wakeup_enable(wiphy_dev(hw->wiphy), true); - return 0; -} - -static int rtl_op_resume(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct timeval ts; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n"); - rtlhal->driver_is_goingto_unload = false; - rtlhal->enter_pnp_sleep = false; - rtlhal->wake_from_pnp_sleep = true; - - /* to resovle s4 can not wake up*/ - do_gettimeofday(&ts); - if (ts.tv_sec - rtlhal->last_suspend_sec < 5) - return -1; - - rtl_op_start(hw); - device_set_wakeup_enable(wiphy_dev(hw->wiphy), false); - ieee80211_resume_disconnect(mac->vif); - rtlhal->wake_from_pnp_sleep = false; - return 0; -} -#endif - -static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct ieee80211_conf *conf = &hw->conf; - - if (mac->skip_scan) - return 1; - - mutex_lock(&rtlpriv->locks.conf_mutex); - if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { /* BIT(2)*/ - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "IEEE80211_CONF_CHANGE_LISTEN_INTERVAL\n"); - } - - /*For IPS */ - if (changed & IEEE80211_CONF_CHANGE_IDLE) { - if (hw->conf.flags & IEEE80211_CONF_IDLE) - rtl_ips_nic_off(hw); - else - rtl_ips_nic_on(hw); - } else { - /* - *although rfoff may not cause by ips, but we will - *check the reason in set_rf_power_state function - */ - if (unlikely(ppsc->rfpwr_state == ERFOFF)) - rtl_ips_nic_on(hw); - } - - /*For LPS */ - if (changed & IEEE80211_CONF_CHANGE_PS) { - cancel_delayed_work(&rtlpriv->works.ps_work); - cancel_delayed_work(&rtlpriv->works.ps_rfon_wq); - if (conf->flags & IEEE80211_CONF_PS) { - rtlpriv->psc.sw_ps_enabled = true; - /* sleep here is must, or we may recv the beacon and - * cause mac80211 into wrong ps state, this will cause - * power save nullfunc send fail, and further cause - * pkt loss, So sleep must quickly but not immediatly - * because that will cause nullfunc send by mac80211 - * fail, and cause pkt loss, we have tested that 5mA - * is worked very well */ - if (!rtlpriv->psc.multi_buffered) - queue_delayed_work(rtlpriv->works.rtl_wq, - &rtlpriv->works.ps_work, - MSECS(5)); - } else { - rtl_swlps_rf_awake(hw); - rtlpriv->psc.sw_ps_enabled = false; - } - } - - if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n", - hw->conf.long_frame_max_tx_count); - mac->retry_long = hw->conf.long_frame_max_tx_count; - mac->retry_short = hw->conf.long_frame_max_tx_count; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT, - (u8 *)(&hw->conf.long_frame_max_tx_count)); - } - - if (changed & IEEE80211_CONF_CHANGE_CHANNEL && - !rtlpriv->proximity.proxim_on) { - struct ieee80211_channel *channel = hw->conf.chandef.chan; - enum nl80211_chan_width width = hw->conf.chandef.width; - enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; - u8 wide_chan = (u8) channel->hw_value; - - /* channel_type is for 20&40M */ - if (width < NL80211_CHAN_WIDTH_80) - channel_type = - cfg80211_get_chandef_type(&hw->conf.chandef); - if (mac->act_scanning) - mac->n_channels++; - - if (rtlpriv->dm.supp_phymode_switch && - mac->link_state < MAC80211_LINKED && - !mac->act_scanning) { - if (rtlpriv->cfg->ops->chk_switch_dmdp) - rtlpriv->cfg->ops->chk_switch_dmdp(hw); - } - - /* - *because we should back channel to - *current_network.chan in in scanning, - *So if set_chan == current_network.chan - *we should set it. - *because mac80211 tell us wrong bw40 - *info for cisco1253 bw20, so we modify - *it here based on UPPER & LOWER - */ - - if (width >= NL80211_CHAN_WIDTH_80) { - if (width == NL80211_CHAN_WIDTH_80) { - u32 center = hw->conf.chandef.center_freq1; - u32 primary = - (u32)hw->conf.chandef.chan->center_freq; - - rtlphy->current_chan_bw = - HT_CHANNEL_WIDTH_80; - mac->bw_80 = true; - mac->bw_40 = true; - if (center > primary) { - mac->cur_80_prime_sc = - PRIME_CHNL_OFFSET_LOWER; - if (center - primary == 10) { - mac->cur_40_prime_sc = - PRIME_CHNL_OFFSET_UPPER; - - wide_chan += 2; - } else if (center - primary == 30) { - mac->cur_40_prime_sc = - PRIME_CHNL_OFFSET_LOWER; - - wide_chan += 6; - } - } else { - mac->cur_80_prime_sc = - PRIME_CHNL_OFFSET_UPPER; - if (primary - center == 10) { - mac->cur_40_prime_sc = - PRIME_CHNL_OFFSET_LOWER; - - wide_chan -= 2; - } else if (primary - center == 30) { - mac->cur_40_prime_sc = - PRIME_CHNL_OFFSET_UPPER; - - wide_chan -= 6; - } - } - } - } else { - switch (channel_type) { - case NL80211_CHAN_HT20: - case NL80211_CHAN_NO_HT: - /* SC */ - mac->cur_40_prime_sc = - PRIME_CHNL_OFFSET_DONT_CARE; - rtlphy->current_chan_bw = - HT_CHANNEL_WIDTH_20; - mac->bw_40 = false; - mac->bw_80 = false; - break; - case NL80211_CHAN_HT40MINUS: - /* SC */ - mac->cur_40_prime_sc = - PRIME_CHNL_OFFSET_UPPER; - rtlphy->current_chan_bw = - HT_CHANNEL_WIDTH_20_40; - mac->bw_40 = true; - mac->bw_80 = false; - - /*wide channel */ - wide_chan -= 2; - - break; - case NL80211_CHAN_HT40PLUS: - /* SC */ - mac->cur_40_prime_sc = - PRIME_CHNL_OFFSET_LOWER; - rtlphy->current_chan_bw = - HT_CHANNEL_WIDTH_20_40; - mac->bw_40 = true; - mac->bw_80 = false; - - /*wide channel */ - wide_chan += 2; - - break; - default: - mac->bw_40 = false; - mac->bw_80 = false; - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - } - - if (wide_chan <= 0) - wide_chan = 1; - - /* In scanning, when before we offchannel we may send a ps=1 - * null to AP, and then we may send a ps = 0 null to AP quickly, - * but first null may have caused AP to put lots of packet to - * hw tx buffer. These packets must be tx'd before we go off - * channel so we must delay more time to let AP flush these - * packets before going offchannel, or dis-association or - * delete BA will be caused by AP - */ - if (rtlpriv->mac80211.offchan_delay) { - rtlpriv->mac80211.offchan_delay = false; - mdelay(50); - } - - rtlphy->current_channel = wide_chan; - - rtlpriv->cfg->ops->switch_channel(hw); - rtlpriv->cfg->ops->set_channel_access(hw); - rtlpriv->cfg->ops->set_bw_mode(hw, channel_type); - } - - mutex_unlock(&rtlpriv->locks.conf_mutex); - - return 0; -} - -static void rtl_op_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *new_flags, u64 multicast) -{ - bool update_rcr = false; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - *new_flags &= RTL_SUPPORTED_FILTERS; - if (0 == changed_flags) - return; - - /*TODO: we disable broadcase now, so enable here */ - if (changed_flags & FIF_ALLMULTI) { - if (*new_flags & FIF_ALLMULTI) { - mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AM] | - rtlpriv->cfg->maps[MAC_RCR_AB]; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "Enable receive multicast frame\n"); - } else { - mac->rx_conf &= ~(rtlpriv->cfg->maps[MAC_RCR_AM] | - rtlpriv->cfg->maps[MAC_RCR_AB]); - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "Disable receive multicast frame\n"); - } - update_rcr = true; - } - - if (changed_flags & FIF_FCSFAIL) { - if (*new_flags & FIF_FCSFAIL) { - mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACRC32]; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "Enable receive FCS error frame\n"); - } else { - mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACRC32]; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "Disable receive FCS error frame\n"); - } - if (!update_rcr) - update_rcr = true; - } - - /* if ssid not set to hw don't check bssid - * here just used for linked scanning, & linked - * and nolink check bssid is set in set network_type - */ - if ((changed_flags & FIF_BCN_PRBRESP_PROMISC) && - (mac->link_state >= MAC80211_LINKED)) { - if (mac->opmode != NL80211_IFTYPE_AP && - mac->opmode != NL80211_IFTYPE_MESH_POINT) { - if (*new_flags & FIF_BCN_PRBRESP_PROMISC) - rtlpriv->cfg->ops->set_chk_bssid(hw, false); - else - rtlpriv->cfg->ops->set_chk_bssid(hw, true); - if (update_rcr) - update_rcr = false; - } - } - - if (changed_flags & FIF_CONTROL) { - if (*new_flags & FIF_CONTROL) { - mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF]; - - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "Enable receive control frame.\n"); - } else { - mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF]; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "Disable receive control frame.\n"); - } - if (!update_rcr) - update_rcr = true; - } - - if (changed_flags & FIF_OTHER_BSS) { - if (*new_flags & FIF_OTHER_BSS) { - mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AAP]; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "Enable receive other BSS's frame.\n"); - } else { - mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_AAP]; - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "Disable receive other BSS's frame.\n"); - } - if (!update_rcr) - update_rcr = true; - } - - if (update_rcr) - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *)(&mac->rx_conf)); -} -static int rtl_op_sta_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_sta_info *sta_entry; - - if (sta) { - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_add_tail(&sta_entry->list, &rtlpriv->entry_list); - spin_unlock_bh(&rtlpriv->locks.entry_list_lock); - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - sta_entry->wireless_mode = WIRELESS_MODE_G; - if (sta->supp_rates[0] <= 0xf) - sta_entry->wireless_mode = WIRELESS_MODE_B; - if (sta->ht_cap.ht_supported) - sta_entry->wireless_mode = WIRELESS_MODE_N_24G; - - if (vif->type == NL80211_IFTYPE_ADHOC) - sta_entry->wireless_mode = WIRELESS_MODE_G; - } else if (rtlhal->current_bandtype == BAND_ON_5G) { - sta_entry->wireless_mode = WIRELESS_MODE_A; - if (sta->ht_cap.ht_supported) - sta_entry->wireless_mode = WIRELESS_MODE_N_5G; - if (sta->vht_cap.vht_supported) - sta_entry->wireless_mode = WIRELESS_MODE_AC_5G; - - if (vif->type == NL80211_IFTYPE_ADHOC) - sta_entry->wireless_mode = WIRELESS_MODE_A; - } - /*disable cck rate for p2p*/ - if (mac->p2p) - sta->supp_rates[0] &= 0xfffffff0; - - memcpy(sta_entry->mac_addr, sta->addr, ETH_ALEN); - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - "Add sta addr is %pM\n", sta->addr); - rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); - } - - return 0; -} - -static int rtl_op_sta_remove(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_sta_info *sta_entry; - if (sta) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - "Remove sta addr is %pM\n", sta->addr); - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - sta_entry->wireless_mode = 0; - sta_entry->ratr_index = 0; - spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_del(&sta_entry->list); - spin_unlock_bh(&rtlpriv->locks.entry_list_lock); - } - return 0; -} -static int _rtl_get_hal_qnum(u16 queue) -{ - int qnum; - - switch (queue) { - case 0: - qnum = AC3_VO; - break; - case 1: - qnum = AC2_VI; - break; - case 2: - qnum = AC0_BE; - break; - case 3: - qnum = AC1_BK; - break; - default: - qnum = AC0_BE; - break; - } - return qnum; -} - -/* - *for mac80211 VO = 0, VI = 1, BE = 2, BK = 3 - *for rtl819x BE = 0, BK = 1, VI = 2, VO = 3 - */ -static int rtl_op_conf_tx(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, - const struct ieee80211_tx_queue_params *param) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - int aci; - - if (queue >= AC_MAX) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "queue number %d is incorrect!\n", queue); - return -EINVAL; - } - - aci = _rtl_get_hal_qnum(queue); - mac->ac[aci].aifs = param->aifs; - mac->ac[aci].cw_min = cpu_to_le16(param->cw_min); - mac->ac[aci].cw_max = cpu_to_le16(param->cw_max); - mac->ac[aci].tx_op = cpu_to_le16(param->txop); - memcpy(&mac->edca_param[aci], param, sizeof(*param)); - rtlpriv->cfg->ops->set_qos(hw, aci); - return 0; -} - -static void send_beacon_frame(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct sk_buff *skb = ieee80211_beacon_get(hw, vif); - struct rtl_tcb_desc tcb_desc; - - if (skb) { - memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); - rtlpriv->intf_ops->adapter_tx(hw, NULL, skb, &tcb_desc); - } -} - -static void rtl_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changed) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - mutex_lock(&rtlpriv->locks.conf_mutex); - if ((vif->type == NL80211_IFTYPE_ADHOC) || - (vif->type == NL80211_IFTYPE_AP) || - (vif->type == NL80211_IFTYPE_MESH_POINT)) { - if ((changed & BSS_CHANGED_BEACON) || - (changed & BSS_CHANGED_BEACON_ENABLED && - bss_conf->enable_beacon)) { - if (mac->beacon_enabled == 0) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - "BSS_CHANGED_BEACON_ENABLED\n"); - - /*start hw beacon interrupt. */ - /*rtlpriv->cfg->ops->set_bcn_reg(hw); */ - mac->beacon_enabled = 1; - rtlpriv->cfg->ops->update_interrupt_mask(hw, - rtlpriv->cfg->maps - [RTL_IBSS_INT_MASKS], 0); - - if (rtlpriv->cfg->ops->linked_set_reg) - rtlpriv->cfg->ops->linked_set_reg(hw); - send_beacon_frame(hw, vif); - } - } - if ((changed & BSS_CHANGED_BEACON_ENABLED && - !bss_conf->enable_beacon)) { - if (mac->beacon_enabled == 1) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - "ADHOC DISABLE BEACON\n"); - - mac->beacon_enabled = 0; - rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, - rtlpriv->cfg->maps - [RTL_IBSS_INT_MASKS]); - } - } - if (changed & BSS_CHANGED_BEACON_INT) { - RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE, - "BSS_CHANGED_BEACON_INT\n"); - mac->beacon_interval = bss_conf->beacon_int; - rtlpriv->cfg->ops->set_bcn_intv(hw); - } - } - - /*TODO: reference to enum ieee80211_bss_change */ - if (changed & BSS_CHANGED_ASSOC) { - u8 mstatus; - if (bss_conf->assoc) { - struct ieee80211_sta *sta = NULL; - u8 keep_alive = 10; - - mstatus = RT_MEDIA_CONNECT; - /* we should reset all sec info & cam - * before set cam after linked, we should not - * reset in disassoc, that will cause tkip->wep - * fail because some flag will be wrong */ - /* reset sec info */ - rtl_cam_reset_sec_info(hw); - /* reset cam to fix wep fail issue - * when change from wpa to wep */ - rtl_cam_reset_all_entry(hw); - - mac->link_state = MAC80211_LINKED; - mac->cnt_after_linked = 0; - mac->assoc_id = bss_conf->aid; - memcpy(mac->bssid, bss_conf->bssid, ETH_ALEN); - - if (rtlpriv->cfg->ops->linked_set_reg) - rtlpriv->cfg->ops->linked_set_reg(hw); - - rcu_read_lock(); - sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid); - if (!sta) { - rcu_read_unlock(); - goto out; - } - RT_TRACE(rtlpriv, COMP_EASY_CONCURRENT, DBG_LOUD, - "send PS STATIC frame\n"); - if (rtlpriv->dm.supp_phymode_switch) { - if (sta->ht_cap.ht_supported) - rtl_send_smps_action(hw, sta, - IEEE80211_SMPS_STATIC); - } - - if (rtlhal->current_bandtype == BAND_ON_5G) { - mac->mode = WIRELESS_MODE_A; - } else { - if (sta->supp_rates[0] <= 0xf) - mac->mode = WIRELESS_MODE_B; - else - mac->mode = WIRELESS_MODE_G; - } - - if (sta->ht_cap.ht_supported) { - if (rtlhal->current_bandtype == BAND_ON_2_4G) - mac->mode = WIRELESS_MODE_N_24G; - else - mac->mode = WIRELESS_MODE_N_5G; - } - - if (sta->vht_cap.vht_supported) { - if (rtlhal->current_bandtype == BAND_ON_5G) - mac->mode = WIRELESS_MODE_AC_5G; - else - mac->mode = WIRELESS_MODE_AC_24G; - } - - if (vif->type == NL80211_IFTYPE_STATION && sta) - rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); - rcu_read_unlock(); - - /* to avoid AP Disassociation caused by inactivity */ - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_KEEP_ALIVE, - (u8 *)(&keep_alive)); - - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - "BSS_CHANGED_ASSOC\n"); - } else { - mstatus = RT_MEDIA_DISCONNECT; - - if (mac->link_state == MAC80211_LINKED) { - rtlpriv->enter_ps = false; - schedule_work(&rtlpriv->works.lps_change_work); - } - if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE) - rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); - mac->link_state = MAC80211_NOLINK; - eth_zero_addr(mac->bssid); - mac->vendor = PEER_UNKNOWN; - mac->mode = 0; - - if (rtlpriv->dm.supp_phymode_switch) { - if (rtlpriv->cfg->ops->chk_switch_dmdp) - rtlpriv->cfg->ops->chk_switch_dmdp(hw); - } - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - "BSS_CHANGED_UN_ASSOC\n"); - } - rtlpriv->cfg->ops->set_network_type(hw, vif->type); - /* For FW LPS: - * To tell firmware we have connected or disconnected - */ - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_JOINBSSRPT, - (u8 *)(&mstatus)); - ppsc->report_linked = (mstatus == RT_MEDIA_CONNECT) ? - true : false; - - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_mediastatus_notify( - rtlpriv, mstatus); - } - - if (changed & BSS_CHANGED_ERP_CTS_PROT) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, - "BSS_CHANGED_ERP_CTS_PROT\n"); - mac->use_cts_protect = bss_conf->use_cts_prot; - } - - if (changed & BSS_CHANGED_ERP_PREAMBLE) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, - "BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n", - bss_conf->use_short_preamble); - - mac->short_preamble = bss_conf->use_short_preamble; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACK_PREAMBLE, - (u8 *)(&mac->short_preamble)); - } - - if (changed & BSS_CHANGED_ERP_SLOT) { - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, - "BSS_CHANGED_ERP_SLOT\n"); - - if (bss_conf->use_short_slot) - mac->slot_time = RTL_SLOT_TIME_9; - else - mac->slot_time = RTL_SLOT_TIME_20; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, - (u8 *)(&mac->slot_time)); - } - - if (changed & BSS_CHANGED_HT) { - struct ieee80211_sta *sta = NULL; - - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, - "BSS_CHANGED_HT\n"); - - rcu_read_lock(); - sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid); - if (sta) { - if (sta->ht_cap.ampdu_density > - mac->current_ampdu_density) - mac->current_ampdu_density = - sta->ht_cap.ampdu_density; - if (sta->ht_cap.ampdu_factor < - mac->current_ampdu_factor) - mac->current_ampdu_factor = - sta->ht_cap.ampdu_factor; - } - rcu_read_unlock(); - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY, - (u8 *)(&mac->max_mss_density)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_FACTOR, - &mac->current_ampdu_factor); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AMPDU_MIN_SPACE, - &mac->current_ampdu_density); - } - - if (changed & BSS_CHANGED_BSSID) { - u32 basic_rates; - struct ieee80211_sta *sta = NULL; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID, - (u8 *)bss_conf->bssid); - - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG, - "bssid: %pM\n", bss_conf->bssid); - - mac->vendor = PEER_UNKNOWN; - memcpy(mac->bssid, bss_conf->bssid, ETH_ALEN); - - rcu_read_lock(); - sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid); - if (!sta) { - rcu_read_unlock(); - goto out; - } - - if (rtlhal->current_bandtype == BAND_ON_5G) { - mac->mode = WIRELESS_MODE_A; - } else { - if (sta->supp_rates[0] <= 0xf) - mac->mode = WIRELESS_MODE_B; - else - mac->mode = WIRELESS_MODE_G; - } - - if (sta->ht_cap.ht_supported) { - if (rtlhal->current_bandtype == BAND_ON_2_4G) - mac->mode = WIRELESS_MODE_N_24G; - else - mac->mode = WIRELESS_MODE_N_5G; - } - - if (sta->vht_cap.vht_supported) { - if (rtlhal->current_bandtype == BAND_ON_5G) - mac->mode = WIRELESS_MODE_AC_5G; - else - mac->mode = WIRELESS_MODE_AC_24G; - } - - /* just station need it, because ibss & ap mode will - * set in sta_add, and will be NULL here */ - if (vif->type == NL80211_IFTYPE_STATION) { - struct rtl_sta_info *sta_entry; - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - sta_entry->wireless_mode = mac->mode; - } - - if (sta->ht_cap.ht_supported) { - mac->ht_enable = true; - - /* - * for cisco 1252 bw20 it's wrong - * if (ht_cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { - * mac->bw_40 = true; - * } - * */ - } - - if (sta->vht_cap.vht_supported) - mac->vht_enable = true; - - if (changed & BSS_CHANGED_BASIC_RATES) { - /* for 5G must << RATE_6M_INDEX = 4, - * because 5G have no cck rate*/ - if (rtlhal->current_bandtype == BAND_ON_5G) - basic_rates = sta->supp_rates[1] << 4; - else - basic_rates = sta->supp_rates[0]; - - mac->basic_rates = basic_rates; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE, - (u8 *)(&basic_rates)); - } - rcu_read_unlock(); - } -out: - mutex_unlock(&rtlpriv->locks.conf_mutex); -} - -static u64 rtl_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u64 tsf; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *)(&tsf)); - return tsf; -} - -static void rtl_op_set_tsf(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u64 tsf) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0; - - mac->tsf = tsf; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *)(&bibss)); -} - -static void rtl_op_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp = 0; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_DUAL_TSF_RST, (u8 *)(&tmp)); -} - -static void rtl_op_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) -{ - switch (cmd) { - case STA_NOTIFY_SLEEP: - break; - case STA_NOTIFY_AWAKE: - break; - default: - break; - } -} - -static int rtl_op_ampdu_action(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - switch (action) { - case IEEE80211_AMPDU_TX_START: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, - "IEEE80211_AMPDU_TX_START: TID:%d\n", tid); - return rtl_tx_agg_start(hw, vif, sta, tid, ssn); - case IEEE80211_AMPDU_TX_STOP_CONT: - case IEEE80211_AMPDU_TX_STOP_FLUSH: - case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, - "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid); - return rtl_tx_agg_stop(hw, vif, sta, tid); - case IEEE80211_AMPDU_TX_OPERATIONAL: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, - "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid); - rtl_tx_agg_oper(hw, sta, tid); - break; - case IEEE80211_AMPDU_RX_START: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, - "IEEE80211_AMPDU_RX_START:TID:%d\n", tid); - return rtl_rx_agg_start(hw, sta, tid); - case IEEE80211_AMPDU_RX_STOP: - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, - "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid); - return rtl_rx_agg_stop(hw, sta, tid); - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "IEEE80211_AMPDU_ERR!!!!:\n"); - return -EOPNOTSUPP; - } - return 0; -} - -static void rtl_op_sw_scan_start(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - const u8 *mac_addr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); - mac->act_scanning = true; - if (rtlpriv->link_info.higher_busytraffic) { - mac->skip_scan = true; - return; - } - - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_scan_notify(rtlpriv, 1); - - if (rtlpriv->dm.supp_phymode_switch) { - if (rtlpriv->cfg->ops->chk_switch_dmdp) - rtlpriv->cfg->ops->chk_switch_dmdp(hw); - } - - if (mac->link_state == MAC80211_LINKED) { - rtlpriv->enter_ps = false; - schedule_work(&rtlpriv->works.lps_change_work); - mac->link_state = MAC80211_LINKED_SCANNING; - } else { - rtl_ips_nic_on(hw); - } - - /* Dul mac */ - rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; - - rtlpriv->cfg->ops->led_control(hw, LED_CTL_SITE_SURVEY); - rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP_BAND0); -} - -static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n"); - mac->act_scanning = false; - mac->skip_scan = false; - if (rtlpriv->link_info.higher_busytraffic) - return; - - /* p2p will use 1/6/11 to scan */ - if (mac->n_channels == 3) - mac->p2p_in_use = true; - else - mac->p2p_in_use = false; - mac->n_channels = 0; - /* Dul mac */ - rtlpriv->rtlhal.load_imrandiqk_setting_for2g = false; - - if (mac->link_state == MAC80211_LINKED_SCANNING) { - mac->link_state = MAC80211_LINKED; - if (mac->opmode == NL80211_IFTYPE_STATION) { - /* fix fwlps issue */ - rtlpriv->cfg->ops->set_network_type(hw, mac->opmode); - } - } - - rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_RESTORE); - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_scan_notify(rtlpriv, 0); -} - -static int rtl_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 key_type = NO_ENCRYPTION; - u8 key_idx; - bool group_key = false; - bool wep_only = false; - int err = 0; - u8 mac_addr[ETH_ALEN]; - u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "not open hw encryption\n"); - return -ENOSPC; /*User disabled HW-crypto */ - } - /* To support IBSS, use sw-crypto for GTK */ - if (((vif->type == NL80211_IFTYPE_ADHOC) || - (vif->type == NL80211_IFTYPE_MESH_POINT)) && - !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) - return -ENOSPC; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "%s hardware based encryption for keyidx: %d, mac: %pM\n", - cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, - sta ? sta->addr : bcast_addr); - rtlpriv->sec.being_setkey = true; - rtl_ips_nic_on(hw); - mutex_lock(&rtlpriv->locks.conf_mutex); - /* <1> get encryption alg */ - - switch (key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - key_type = WEP40_ENCRYPTION; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP40\n"); - break; - case WLAN_CIPHER_SUITE_WEP104: - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP104\n"); - key_type = WEP104_ENCRYPTION; - break; - case WLAN_CIPHER_SUITE_TKIP: - key_type = TKIP_ENCRYPTION; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:TKIP\n"); - break; - case WLAN_CIPHER_SUITE_CCMP: - key_type = AESCCMP_ENCRYPTION; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n"); - break; - case WLAN_CIPHER_SUITE_AES_CMAC: - /* HW don't support CMAC encryption, - * use software CMAC encryption - */ - key_type = AESCMAC_ENCRYPTION; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n"); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "HW don't support CMAC encrypiton, use software CMAC encrypiton\n"); - err = -EOPNOTSUPP; - goto out_unlock; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "alg_err:%x!!!!:\n", key->cipher); - goto out_unlock; - } - if (key_type == WEP40_ENCRYPTION || - key_type == WEP104_ENCRYPTION || - vif->type == NL80211_IFTYPE_ADHOC) - rtlpriv->sec.use_defaultkey = true; - - /* <2> get key_idx */ - key_idx = (u8) (key->keyidx); - if (key_idx > 3) - goto out_unlock; - /* <3> if pairwise key enable_hw_sec */ - group_key = !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE); - - /* wep always be group key, but there are two conditions: - * 1) wep only: is just for wep enc, in this condition - * rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION - * will be true & enable_hw_sec will be set when wep - * ke setting. - * 2) wep(group) + AES(pairwise): some AP like cisco - * may use it, in this condition enable_hw_sec will not - * be set when wep key setting */ - /* we must reset sec_info after lingked before set key, - * or some flag will be wrong*/ - if (vif->type == NL80211_IFTYPE_AP || - vif->type == NL80211_IFTYPE_MESH_POINT) { - if (!group_key || key_type == WEP40_ENCRYPTION || - key_type == WEP104_ENCRYPTION) { - if (group_key) - wep_only = true; - rtlpriv->cfg->ops->enable_hw_sec(hw); - } - } else { - if ((!group_key) || (vif->type == NL80211_IFTYPE_ADHOC) || - rtlpriv->sec.pairwise_enc_algorithm == NO_ENCRYPTION) { - if (rtlpriv->sec.pairwise_enc_algorithm == - NO_ENCRYPTION && - (key_type == WEP40_ENCRYPTION || - key_type == WEP104_ENCRYPTION)) - wep_only = true; - rtlpriv->sec.pairwise_enc_algorithm = key_type; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1 TKIP:2 AES:4 WEP104:5)\n", - key_type); - rtlpriv->cfg->ops->enable_hw_sec(hw); - } - } - /* <4> set key based on cmd */ - switch (cmd) { - case SET_KEY: - if (wep_only) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set WEP(group/pairwise) key\n"); - /* Pairwise key with an assigned MAC address. */ - rtlpriv->sec.pairwise_enc_algorithm = key_type; - rtlpriv->sec.group_enc_algorithm = key_type; - /*set local buf about wep key. */ - memcpy(rtlpriv->sec.key_buf[key_idx], - key->key, key->keylen); - rtlpriv->sec.key_len[key_idx] = key->keylen; - eth_zero_addr(mac_addr); - } else if (group_key) { /* group key */ - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set group key\n"); - /* group key */ - rtlpriv->sec.group_enc_algorithm = key_type; - /*set local buf about group key. */ - memcpy(rtlpriv->sec.key_buf[key_idx], - key->key, key->keylen); - rtlpriv->sec.key_len[key_idx] = key->keylen; - memcpy(mac_addr, bcast_addr, ETH_ALEN); - } else { /* pairwise key */ - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set pairwise key\n"); - if (!sta) { - RT_ASSERT(false, - "pairwise key without mac_addr\n"); - - err = -EOPNOTSUPP; - goto out_unlock; - } - /* Pairwise key with an assigned MAC address. */ - rtlpriv->sec.pairwise_enc_algorithm = key_type; - /*set local buf about pairwise key. */ - memcpy(rtlpriv->sec.key_buf[PAIRWISE_KEYIDX], - key->key, key->keylen); - rtlpriv->sec.key_len[PAIRWISE_KEYIDX] = key->keylen; - rtlpriv->sec.pairwise_key = - rtlpriv->sec.key_buf[PAIRWISE_KEYIDX]; - memcpy(mac_addr, sta->addr, ETH_ALEN); - } - rtlpriv->cfg->ops->set_key(hw, key_idx, mac_addr, - group_key, key_type, wep_only, - false); - /* <5> tell mac80211 do something: */ - /*must use sw generate IV, or can not work !!!!. */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - key->hw_key_idx = key_idx; - if (key_type == TKIP_ENCRYPTION) - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - /*use software CCMP encryption for management frames (MFP) */ - if (key_type == AESCCMP_ENCRYPTION) - key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; - break; - case DISABLE_KEY: - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "disable key delete one entry\n"); - /*set local buf about wep key. */ - if (vif->type == NL80211_IFTYPE_AP || - vif->type == NL80211_IFTYPE_MESH_POINT) { - if (sta) - rtl_cam_del_entry(hw, sta->addr); - } - memset(rtlpriv->sec.key_buf[key_idx], 0, key->keylen); - rtlpriv->sec.key_len[key_idx] = 0; - eth_zero_addr(mac_addr); - /* - *mac80211 will delete entrys one by one, - *so don't use rtl_cam_reset_all_entry - *or clear all entry here. - */ - rtl_cam_delete_one_entry(hw, mac_addr, key_idx); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "cmd_err:%x!!!!:\n", cmd); - } -out_unlock: - mutex_unlock(&rtlpriv->locks.conf_mutex); - rtlpriv->sec.being_setkey = false; - return err; -} - -static void rtl_op_rfkill_poll(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - bool radio_state; - bool blocked; - u8 valid = 0; - - if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) - return; - - mutex_lock(&rtlpriv->locks.conf_mutex); - - /*if Radio On return true here */ - radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid); - - if (valid) { - if (unlikely(radio_state != rtlpriv->rfkill.rfkill_state)) { - rtlpriv->rfkill.rfkill_state = radio_state; - - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "wireless radio switch turned %s\n", - radio_state ? "on" : "off"); - - blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1; - wiphy_rfkill_set_hw_state(hw->wiphy, blocked); - } - } - - mutex_unlock(&rtlpriv->locks.conf_mutex); -} - -/* this function is called by mac80211 to flush tx buffer - * before switch channle or power save, or tx buffer packet - * maybe send after offchannel or rf sleep, this may cause - * dis-association by AP */ -static void rtl_op_flush(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - u32 queues, - bool drop) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->intf_ops->flush) - rtlpriv->intf_ops->flush(hw, queues, drop); -} - -/* Description: - * This routine deals with the Power Configuration CMD - * parsing for RTL8723/RTL8188E Series IC. - * Assumption: - * We should follow specific format that was released from HW SD. - */ -bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version, - u8 faversion, u8 interface_type, - struct wlan_pwr_cfg pwrcfgcmd[]) -{ - struct wlan_pwr_cfg cfg_cmd = {0}; - bool polling_bit = false; - u32 ary_idx = 0; - u8 value = 0; - u32 offset = 0; - u32 polling_count = 0; - u32 max_polling_cnt = 5000; - - do { - cfg_cmd = pwrcfgcmd[ary_idx]; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "rtl_hal_pwrseqcmdparsing(): offset(%#x),cut_msk(%#x), famsk(%#x), interface_msk(%#x), base(%#x), cmd(%#x), msk(%#x), value(%#x)\n", - GET_PWR_CFG_OFFSET(cfg_cmd), - GET_PWR_CFG_CUT_MASK(cfg_cmd), - GET_PWR_CFG_FAB_MASK(cfg_cmd), - GET_PWR_CFG_INTF_MASK(cfg_cmd), - GET_PWR_CFG_BASE(cfg_cmd), GET_PWR_CFG_CMD(cfg_cmd), - GET_PWR_CFG_MASK(cfg_cmd), GET_PWR_CFG_VALUE(cfg_cmd)); - - if ((GET_PWR_CFG_FAB_MASK(cfg_cmd)&faversion) && - (GET_PWR_CFG_CUT_MASK(cfg_cmd)&cut_version) && - (GET_PWR_CFG_INTF_MASK(cfg_cmd)&interface_type)) { - switch (GET_PWR_CFG_CMD(cfg_cmd)) { - case PWR_CMD_READ: - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "rtl_hal_pwrseqcmdparsing(): PWR_CMD_READ\n"); - break; - case PWR_CMD_WRITE: - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "rtl_hal_pwrseqcmdparsing(): PWR_CMD_WRITE\n"); - offset = GET_PWR_CFG_OFFSET(cfg_cmd); - - /*Read the value from system register*/ - value = rtl_read_byte(rtlpriv, offset); - value &= (~(GET_PWR_CFG_MASK(cfg_cmd))); - value |= (GET_PWR_CFG_VALUE(cfg_cmd) & - GET_PWR_CFG_MASK(cfg_cmd)); - - /*Write the value back to sytem register*/ - rtl_write_byte(rtlpriv, offset, value); - break; - case PWR_CMD_POLLING: - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "rtl_hal_pwrseqcmdparsing(): PWR_CMD_POLLING\n"); - polling_bit = false; - offset = GET_PWR_CFG_OFFSET(cfg_cmd); - - do { - value = rtl_read_byte(rtlpriv, offset); - - value &= GET_PWR_CFG_MASK(cfg_cmd); - if (value == - (GET_PWR_CFG_VALUE(cfg_cmd) & - GET_PWR_CFG_MASK(cfg_cmd))) - polling_bit = true; - else - udelay(10); - - if (polling_count++ > max_polling_cnt) - return false; - } while (!polling_bit); - break; - case PWR_CMD_DELAY: - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "rtl_hal_pwrseqcmdparsing(): PWR_CMD_DELAY\n"); - if (GET_PWR_CFG_VALUE(cfg_cmd) == - PWRSEQ_DELAY_US) - udelay(GET_PWR_CFG_OFFSET(cfg_cmd)); - else - mdelay(GET_PWR_CFG_OFFSET(cfg_cmd)); - break; - case PWR_CMD_END: - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "rtl_hal_pwrseqcmdparsing(): PWR_CMD_END\n"); - return true; - default: - RT_ASSERT(false, - "rtl_hal_pwrseqcmdparsing(): Unknown CMD!!\n"); - break; - } - } - ary_idx++; - } while (1); - - return true; -} -EXPORT_SYMBOL(rtl_hal_pwrseqcmdparsing); - -bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring; - struct rtl_tx_desc *pdesc; - unsigned long flags; - struct sk_buff *pskb = NULL; - - ring = &rtlpci->tx_ring[BEACON_QUEUE]; - - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - pskb = __skb_dequeue(&ring->queue); - if (pskb) - kfree_skb(pskb); - - /*this is wrong, fill_tx_cmddesc needs update*/ - pdesc = &ring->desc[0]; - - rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); - - __skb_queue_tail(&ring->queue, skb); - - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - - rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); - - return true; -} -EXPORT_SYMBOL(rtl_cmd_send_packet); -const struct ieee80211_ops rtl_ops = { - .start = rtl_op_start, - .stop = rtl_op_stop, - .tx = rtl_op_tx, - .add_interface = rtl_op_add_interface, - .remove_interface = rtl_op_remove_interface, - .change_interface = rtl_op_change_interface, -#ifdef CONFIG_PM - .suspend = rtl_op_suspend, - .resume = rtl_op_resume, -#endif - .config = rtl_op_config, - .configure_filter = rtl_op_configure_filter, - .set_key = rtl_op_set_key, - .conf_tx = rtl_op_conf_tx, - .bss_info_changed = rtl_op_bss_info_changed, - .get_tsf = rtl_op_get_tsf, - .set_tsf = rtl_op_set_tsf, - .reset_tsf = rtl_op_reset_tsf, - .sta_notify = rtl_op_sta_notify, - .ampdu_action = rtl_op_ampdu_action, - .sw_scan_start = rtl_op_sw_scan_start, - .sw_scan_complete = rtl_op_sw_scan_complete, - .rfkill_poll = rtl_op_rfkill_poll, - .sta_add = rtl_op_sta_add, - .sta_remove = rtl_op_sta_remove, - .flush = rtl_op_flush, -}; -EXPORT_SYMBOL_GPL(rtl_ops); - -bool rtl_btc_status_false(void) -{ - return false; -} -EXPORT_SYMBOL_GPL(rtl_btc_status_false); - -void rtl_dm_diginit(struct ieee80211_hw *hw, u32 cur_igvalue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - dm_digtable->dig_enable_flag = true; - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; - dm_digtable->cur_igvalue = cur_igvalue; - dm_digtable->pre_igvalue = 0; - dm_digtable->cur_sta_cstate = DIG_STA_DISCONNECT; - dm_digtable->presta_cstate = DIG_STA_DISCONNECT; - dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT; - dm_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW; - dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; - dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; - dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; - dm_digtable->rx_gain_max = DM_DIG_MAX; - dm_digtable->rx_gain_min = DM_DIG_MIN; - dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; - dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; - dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; - dm_digtable->pre_cck_cca_thres = 0xff; - dm_digtable->cur_cck_cca_thres = 0x83; - dm_digtable->forbidden_igi = DM_DIG_MIN; - dm_digtable->large_fa_hit = 0; - dm_digtable->recover_cnt = 0; - dm_digtable->dig_min_0 = 0x25; - dm_digtable->dig_min_1 = 0x25; - dm_digtable->media_connect_0 = false; - dm_digtable->media_connect_1 = false; - rtlpriv->dm.dm_initialgain_enable = true; - dm_digtable->bt30_cur_igi = 0x32; - dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX; - dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_LOWRSSI; -} -EXPORT_SYMBOL(rtl_dm_diginit); diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h deleted file mode 100644 index 782ac2fc4b28..000000000000 --- a/drivers/net/wireless/rtlwifi/core.h +++ /dev/null @@ -1,86 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL_CORE_H__ -#define __RTL_CORE_H__ - -#define RTL_SUPPORTED_FILTERS \ - (FIF_ALLMULTI | FIF_CONTROL | \ - FIF_OTHER_BSS | \ - FIF_FCSFAIL | \ - FIF_BCN_PRBRESP_PROMISC) - -#define DM_DIG_THRESH_HIGH 40 -#define DM_DIG_THRESH_LOW 35 -#define DM_FALSEALARM_THRESH_LOW 400 -#define DM_FALSEALARM_THRESH_HIGH 1000 - -#define DM_DIG_MAX 0x3e -#define DM_DIG_MIN 0x1e -#define DM_DIG_MAX_AP 0x32 -#define DM_DIG_BACKOFF_MAX 12 -#define DM_DIG_BACKOFF_MIN -4 -#define DM_DIG_BACKOFF_DEFAULT 10 - -enum cck_packet_detection_threshold { - CCK_PD_STAGE_LOWRSSI = 0, - CCK_PD_STAGE_HIGHRSSI = 1, - CCK_FA_STAGE_LOW = 2, - CCK_FA_STAGE_HIGH = 3, - CCK_PD_STAGE_MAX = 4, -}; - -enum dm_dig_ext_port_alg_e { - DIG_EXT_PORT_STAGE_0 = 0, - DIG_EXT_PORT_STAGE_1 = 1, - DIG_EXT_PORT_STAGE_2 = 2, - DIG_EXT_PORT_STAGE_3 = 3, - DIG_EXT_PORT_STAGE_MAX = 4, -}; - -enum dm_dig_connect_e { - DIG_STA_DISCONNECT, - DIG_STA_CONNECT, - DIG_STA_BEFORE_CONNECT, - DIG_MULTISTA_DISCONNECT, - DIG_MULTISTA_CONNECT, - DIG_AP_DISCONNECT, - DIG_AP_CONNECT, - DIG_AP_ADD_STATION, - DIG_CONNECT_MAX -}; - -extern const struct ieee80211_ops rtl_ops; -void rtl_fw_cb(const struct firmware *firmware, void *context); -void rtl_wowlan_fw_cb(const struct firmware *firmware, void *context); -void rtl_addr_delay(u32 addr); -void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr, - u32 mask, u32 data); -void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data); -bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); -bool rtl_btc_status_false(void); -void rtl_dm_diginit(struct ieee80211_hw *hw, u32 cur_igval); - -#endif diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/rtlwifi/debug.c deleted file mode 100644 index fd25abad2b9e..000000000000 --- a/drivers/net/wireless/rtlwifi/debug.c +++ /dev/null @@ -1,50 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - *****************************************************************************/ - -#include "wifi.h" - -#include - -void rtl_dbgp_flag_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 i; - - 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; - - - for (i = 0; i < DBGP_TYPE_MAX; i++) - rtlpriv->dbg.dbgp_type[i] = 0; - - /*Init Debug flag enable condition */ -} -EXPORT_SYMBOL_GPL(rtl_dbgp_flag_init); diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h deleted file mode 100644 index fc794b3e9f4a..000000000000 --- a/drivers/net/wireless/rtlwifi/debug.h +++ /dev/null @@ -1,241 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - *****************************************************************************/ - -#ifndef __RTL_DEBUG_H__ -#define __RTL_DEBUG_H__ - -/*-------------------------------------------------------------- - Debug level ---------------------------------------------------------------*/ -/* - *Fatal bug. - *For example, Tx/Rx/IO locked up, - *memory access violation, - *resource allocation failed, - *unexpected HW behavior, HW BUG - *and so on. - */ -#define DBG_EMERG 0 - -/* - *Abnormal, rare, or unexpeted cases. - *For example, Packet/IO Ctl canceled, - *device suprisely unremoved and so on. - */ -#define DBG_WARNING 2 - -/* - *Normal case driver developer should - *open, we can see link status like - *assoc/AddBA/DHCP/adapter start and - *so on basic and useful infromations. - */ -#define DBG_DMESG 3 - -/* - *Normal case with useful information - *about current SW or HW state. - *For example, Tx/Rx descriptor to fill, - *Tx/Rx descriptor completed status, - *SW protocol state change, dynamic - *mechanism state change and so on. - */ -#define DBG_LOUD 4 - -/* - *Normal case with detail execution - *flow or information. - */ -#define DBG_TRACE 5 - -/*-------------------------------------------------------------- - Define the rt_trace components ---------------------------------------------------------------*/ -#define COMP_ERR BIT(0) -#define COMP_FW BIT(1) -#define COMP_INIT BIT(2) /*For init/deinit */ -#define COMP_RECV BIT(3) /*For Rx. */ -#define COMP_SEND BIT(4) /*For Tx. */ -#define COMP_MLME BIT(5) /*For MLME. */ -#define COMP_SCAN BIT(6) /*For Scan. */ -#define COMP_INTR BIT(7) /*For interrupt Related. */ -#define COMP_LED BIT(8) /*For LED. */ -#define COMP_SEC BIT(9) /*For sec. */ -#define COMP_BEACON BIT(10) /*For beacon. */ -#define COMP_RATE BIT(11) /*For rate. */ -#define COMP_RXDESC BIT(12) /*For rx desc. */ -#define COMP_DIG BIT(13) /*For DIG */ -#define COMP_TXAGC BIT(14) /*For Tx power */ -#define COMP_HIPWR BIT(15) /*For High Power Mechanism */ -#define COMP_POWER BIT(16) /*For lps/ips/aspm. */ -#define COMP_POWER_TRACKING BIT(17) /*For TX POWER TRACKING */ -#define COMP_BB_POWERSAVING BIT(18) -#define COMP_SWAS BIT(19) /*For SW Antenna Switch */ -#define COMP_RF BIT(20) /*For RF. */ -#define COMP_TURBO BIT(21) /*For EDCA TURBO. */ -#define COMP_RATR BIT(22) -#define COMP_CMD BIT(23) -#define COMP_EFUSE BIT(24) -#define COMP_QOS BIT(25) -#define COMP_MAC80211 BIT(26) -#define COMP_REGD BIT(27) -#define COMP_CHAN BIT(28) -#define COMP_USB BIT(29) -#define COMP_EASY_CONCURRENT COMP_USB /* reuse of this bit is OK */ -#define COMP_BT_COEXIST BIT(30) -#define COMP_IQK BIT(31) - -/*-------------------------------------------------------------- - Define the rt_print components ---------------------------------------------------------------*/ -/* Define EEPROM and EFUSE check module bit*/ -#define EEPROM_W BIT(0) -#define EFUSE_PG BIT(1) -#define EFUSE_READ_ALL BIT(2) - -/* Define init check for module bit*/ -#define INIT_EEPROM BIT(0) -#define INIT_TXPOWER BIT(1) -#define INIT_IQK BIT(2) -#define INIT_RF BIT(3) - -/* Define PHY-BB/RF/MAC check module bit */ -#define PHY_BBR BIT(0) -#define PHY_BBW BIT(1) -#define PHY_RFR BIT(2) -#define PHY_RFW BIT(3) -#define PHY_MACR BIT(4) -#define PHY_MACW BIT(5) -#define PHY_ALLR BIT(6) -#define PHY_ALLW BIT(7) -#define PHY_TXPWR BIT(8) -#define PHY_PWRDIFF BIT(9) - -/* Define Dynamic Mechanism check module bit --> FDM */ -#define WA_IOT BIT(0) -#define DM_PWDB BIT(1) -#define DM_MONITOR BIT(2) -#define DM_DIG BIT(3) -#define DM_EDCA_TURBO BIT(4) - -#define DM_PWDB BIT(1) - -enum dbgp_flag_e { - FQOS = 0, - FTX = 1, - FRX = 2, - FSEC = 3, - FMGNT = 4, - FMLME = 5, - FRESOURCE = 6, - FBEACON = 7, - FISR = 8, - FPHY = 9, - FMP = 10, - FEEPROM = 11, - FPWR = 12, - FDM = 13, - FDBGCtrl = 14, - FC2H = 15, - FBT = 16, - FINIT = 17, - FIOCTL = 18, - DBGP_TYPE_MAX -}; - -#ifdef CONFIG_RTLWIFI_DEBUG - -#define RT_ASSERT(_exp, fmt, ...) \ -do { \ - if (!(_exp)) { \ - printk(KERN_DEBUG KBUILD_MODNAME ":%s(): " fmt, \ - __func__, ##__VA_ARGS__); \ - } \ -} while (0) - -#define RT_TRACE(rtlpriv, comp, level, fmt, ...) \ -do { \ - if (unlikely(((comp) & rtlpriv->dbg.global_debugcomponents) && \ - ((level) <= rtlpriv->dbg.global_debuglevel))) { \ - printk(KERN_DEBUG KBUILD_MODNAME ":%s():<%lx-%x> " fmt, \ - __func__, in_interrupt(), in_atomic(), \ - ##__VA_ARGS__); \ - } \ -} while (0) - -#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) - -#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) - -#else - -struct rtl_priv; - -__printf(2, 3) -static inline void RT_ASSERT(int exp, const char *fmt, ...) -{ -} - -__printf(4, 5) -static inline void RT_TRACE(struct rtl_priv *rtlpriv, - int comp, int level, - const char *fmt, ...) -{ -} - -__printf(4, 5) -static inline void RTPRINT(struct rtl_priv *rtlpriv, - int dbgtype, int dbgflag, - const char *fmt, ...) -{ -} - -static inline void RT_PRINT_DATA(struct rtl_priv *rtlpriv, - int comp, int level, - const char *titlestring, - const void *hexdata, size_t hexdatalen) -{ -} - -#endif - -void rtl_dbgp_flag_init(struct ieee80211_hw *hw); -#endif diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c deleted file mode 100644 index 0b4082c9272a..000000000000 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ /dev/null @@ -1,1245 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * Tmis 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 - * published by the Free Software Foundation. - * - * Tmis program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * Tme full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#include "wifi.h" -#include "efuse.h" -#include - -static const u8 MAX_PGPKT_SIZE = 9; -static const u8 PGPKT_DATA_SIZE = 8; -static const int EFUSE_MAX_SIZE = 512; - -static const struct efuse_map RTL8712_SDIO_EFUSE_TABLE[] = { - {0, 0, 0, 2}, - {0, 1, 0, 2}, - {0, 2, 0, 2}, - {1, 0, 0, 1}, - {1, 0, 1, 1}, - {1, 1, 0, 1}, - {1, 1, 1, 3}, - {1, 3, 0, 17}, - {3, 3, 1, 48}, - {10, 0, 0, 6}, - {10, 3, 0, 1}, - {10, 3, 1, 1}, - {11, 0, 0, 28} -}; - -static void efuse_shadow_read_1byte(struct ieee80211_hw *hw, u16 offset, - u8 *value); -static void efuse_shadow_read_2byte(struct ieee80211_hw *hw, u16 offset, - u16 *value); -static void efuse_shadow_read_4byte(struct ieee80211_hw *hw, u16 offset, - u32 *value); -static void efuse_shadow_write_1byte(struct ieee80211_hw *hw, u16 offset, - u8 value); -static void efuse_shadow_write_2byte(struct ieee80211_hw *hw, u16 offset, - u16 value); -static void efuse_shadow_write_4byte(struct ieee80211_hw *hw, u16 offset, - u32 value); -static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, - u8 data); -static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse); -static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, - u8 *data); -static int efuse_pg_packet_write(struct ieee80211_hw *hw, u8 offset, - u8 word_en, u8 *data); -static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata, - u8 *targetdata); -static u8 enable_efuse_data_write(struct ieee80211_hw *hw, - u16 efuse_addr, u8 word_en, u8 *data); -static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, - u8 pwrstate); -static u16 efuse_get_current_size(struct ieee80211_hw *hw); -static u8 efuse_calculate_word_cnts(u8 word_en); - -void efuse_initialize(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bytetemp; - u8 temp; - - bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN] + 1); - temp = bytetemp | 0x20; - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN] + 1, temp); - - bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL] + 1); - temp = bytetemp & 0xFE; - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[SYS_ISO_CTRL] + 1, temp); - - bytetemp = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3); - temp = bytetemp | 0x80; - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST] + 3, temp); - - rtl_write_byte(rtlpriv, 0x2F8, 0x3); - - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0x72); - -} - -u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 data; - u8 bytetemp; - u8 temp; - u32 k = 0; - const u32 efuse_len = - rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; - - if (address < efuse_len) { - temp = address & 0xFF; - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, - temp); - bytetemp = rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + 2); - temp = ((address >> 8) & 0x03) | (bytetemp & 0xFC); - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2, - temp); - - bytetemp = rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + 3); - temp = bytetemp & 0x7F; - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, - temp); - - bytetemp = rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + 3); - while (!(bytetemp & 0x80)) { - bytetemp = rtl_read_byte(rtlpriv, - rtlpriv->cfg-> - maps[EFUSE_CTRL] + 3); - k++; - if (k == 1000) { - k = 0; - break; - } - } - data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); - return data; - } else - return 0xFF; - -} -EXPORT_SYMBOL(efuse_read_1byte); - -void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bytetemp; - u8 temp; - u32 k = 0; - const u32 efuse_len = - rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; - - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "Addr=%x Data =%x\n", - address, value); - - if (address < efuse_len) { - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], value); - - temp = address & 0xFF; - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, - temp); - bytetemp = rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + 2); - - temp = ((address >> 8) & 0x03) | (bytetemp & 0xFC); - rtl_write_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + 2, temp); - - bytetemp = rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + 3); - temp = bytetemp | 0x80; - rtl_write_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + 3, temp); - - bytetemp = rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + 3); - - while (bytetemp & 0x80) { - bytetemp = rtl_read_byte(rtlpriv, - rtlpriv->cfg-> - maps[EFUSE_CTRL] + 3); - k++; - if (k == 100) { - k = 0; - break; - } - } - } - -} - -void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 value32; - u8 readbyte; - u16 retry; - - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, - (_offset & 0xff)); - readbyte = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2); - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2, - ((_offset >> 8) & 0x03) | (readbyte & 0xfc)); - - readbyte = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3); - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, - (readbyte & 0x7f)); - - retry = 0; - value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); - while (!(((value32 >> 24) & 0xff) & 0x80) && (retry < 10000)) { - value32 = rtl_read_dword(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL]); - retry++; - } - - udelay(50); - value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); - - *pbuf = (u8) (value32 & 0xff); -} -EXPORT_SYMBOL_GPL(read_efuse_byte); - -void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 *efuse_tbl; - u8 rtemp8[1]; - u16 efuse_addr = 0; - u8 offset, wren; - u8 u1temp = 0; - u16 i; - u16 j; - const u16 efuse_max_section = - rtlpriv->cfg->maps[EFUSE_MAX_SECTION_MAP]; - const u32 efuse_len = - rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; - u16 **efuse_word; - u16 efuse_utilized = 0; - u8 efuse_usage; - - if ((_offset + _size_byte) > rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]) { - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - "read_efuse(): Invalid offset(%#x) with read bytes(%#x)!!\n", - _offset, _size_byte); - return; - } - - /* allocate memory for efuse_tbl and efuse_word */ - efuse_tbl = kzalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE] * - sizeof(u8), GFP_ATOMIC); - if (!efuse_tbl) - return; - efuse_word = kzalloc(EFUSE_MAX_WORD_UNIT * sizeof(u16 *), GFP_ATOMIC); - if (!efuse_word) - goto out; - for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { - efuse_word[i] = kzalloc(efuse_max_section * sizeof(u16), - GFP_ATOMIC); - if (!efuse_word[i]) - goto done; - } - - for (i = 0; i < efuse_max_section; i++) - for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) - efuse_word[j][i] = 0xFFFF; - - read_efuse_byte(hw, efuse_addr, rtemp8); - if (*rtemp8 != 0xFF) { - efuse_utilized++; - RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, - "Addr=%d\n", efuse_addr); - efuse_addr++; - } - - while ((*rtemp8 != 0xFF) && (efuse_addr < efuse_len)) { - /* Check PG header for section num. */ - if ((*rtemp8 & 0x1F) == 0x0F) {/* extended header */ - u1temp = ((*rtemp8 & 0xE0) >> 5); - read_efuse_byte(hw, efuse_addr, rtemp8); - - if ((*rtemp8 & 0x0F) == 0x0F) { - efuse_addr++; - read_efuse_byte(hw, efuse_addr, rtemp8); - - if (*rtemp8 != 0xFF && - (efuse_addr < efuse_len)) { - efuse_addr++; - } - continue; - } else { - offset = ((*rtemp8 & 0xF0) >> 1) | u1temp; - wren = (*rtemp8 & 0x0F); - efuse_addr++; - } - } else { - offset = ((*rtemp8 >> 4) & 0x0f); - wren = (*rtemp8 & 0x0f); - } - - if (offset < efuse_max_section) { - RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, - "offset-%d Worden=%x\n", offset, wren); - - for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { - if (!(wren & 0x01)) { - RTPRINT(rtlpriv, FEEPROM, - EFUSE_READ_ALL, - "Addr=%d\n", efuse_addr); - - read_efuse_byte(hw, efuse_addr, rtemp8); - efuse_addr++; - efuse_utilized++; - efuse_word[i][offset] = - (*rtemp8 & 0xff); - - if (efuse_addr >= efuse_len) - break; - - RTPRINT(rtlpriv, FEEPROM, - EFUSE_READ_ALL, - "Addr=%d\n", efuse_addr); - - read_efuse_byte(hw, efuse_addr, rtemp8); - efuse_addr++; - efuse_utilized++; - efuse_word[i][offset] |= - (((u16)*rtemp8 << 8) & 0xff00); - - if (efuse_addr >= efuse_len) - break; - } - - wren >>= 1; - } - } - - RTPRINT(rtlpriv, FEEPROM, EFUSE_READ_ALL, - "Addr=%d\n", efuse_addr); - read_efuse_byte(hw, efuse_addr, rtemp8); - if (*rtemp8 != 0xFF && (efuse_addr < efuse_len)) { - efuse_utilized++; - efuse_addr++; - } - } - - for (i = 0; i < efuse_max_section; i++) { - for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { - efuse_tbl[(i * 8) + (j * 2)] = - (efuse_word[j][i] & 0xff); - efuse_tbl[(i * 8) + ((j * 2) + 1)] = - ((efuse_word[j][i] >> 8) & 0xff); - } - } - - for (i = 0; i < _size_byte; i++) - pbuf[i] = efuse_tbl[_offset + i]; - - rtlefuse->efuse_usedbytes = efuse_utilized; - efuse_usage = (u8) ((efuse_utilized * 100) / efuse_len); - rtlefuse->efuse_usedpercentage = efuse_usage; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_BYTES, - (u8 *)&efuse_utilized); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_USAGE, - &efuse_usage); -done: - for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) - kfree(efuse_word[i]); - kfree(efuse_word); -out: - kfree(efuse_tbl); -} - -bool efuse_shadow_update_chk(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 section_idx, i, Base; - u16 words_need = 0, hdr_num = 0, totalbytes, efuse_used; - bool wordchanged, result = true; - - for (section_idx = 0; section_idx < 16; section_idx++) { - Base = section_idx * 8; - wordchanged = false; - - for (i = 0; i < 8; i = i + 2) { - if ((rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i] != - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i]) || - (rtlefuse->efuse_map[EFUSE_INIT_MAP][Base + i + 1] != - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][Base + i + - 1])) { - words_need++; - wordchanged = true; - } - } - - if (wordchanged) - hdr_num++; - } - - totalbytes = hdr_num + words_need * 2; - efuse_used = rtlefuse->efuse_usedbytes; - - if ((totalbytes + efuse_used) >= - (EFUSE_MAX_SIZE - rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) - result = false; - - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - "efuse_shadow_update_chk(): totalbytes(%#x), hdr_num(%#x), words_need(%#x), efuse_used(%d)\n", - totalbytes, hdr_num, words_need, efuse_used); - - return result; -} - -void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, - u16 offset, u32 *value) -{ - if (type == 1) - efuse_shadow_read_1byte(hw, offset, (u8 *)value); - else if (type == 2) - efuse_shadow_read_2byte(hw, offset, (u16 *)value); - else if (type == 4) - efuse_shadow_read_4byte(hw, offset, value); - -} -EXPORT_SYMBOL(efuse_shadow_read); - -void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, u16 offset, - u32 value) -{ - if (type == 1) - efuse_shadow_write_1byte(hw, offset, (u8) value); - else if (type == 2) - efuse_shadow_write_2byte(hw, offset, (u16) value); - else if (type == 4) - efuse_shadow_write_4byte(hw, offset, value); - -} - -bool efuse_shadow_update(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u16 i, offset, base; - u8 word_en = 0x0F; - u8 first_pg = false; - - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "\n"); - - if (!efuse_shadow_update_chk(hw)) { - efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); - memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], - &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], - rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); - - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - "efuse out of capacity!!\n"); - return false; - } - efuse_power_switch(hw, true, true); - - for (offset = 0; offset < 16; offset++) { - - word_en = 0x0F; - base = offset * 8; - - for (i = 0; i < 8; i++) { - if (first_pg) { - word_en &= ~(BIT(i / 2)); - - rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] = - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]; - } else { - - if (rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] != - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]) { - word_en &= ~(BIT(i / 2)); - - rtlefuse->efuse_map[EFUSE_INIT_MAP][base + i] = - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base + i]; - } - } - } - - if (word_en != 0x0F) { - u8 tmpdata[8]; - memcpy(tmpdata, - &rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base], - 8); - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, - "U-efuse\n", tmpdata, 8); - - if (!efuse_pg_packet_write(hw, (u8) offset, word_en, - tmpdata)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "PG section(%#x) fail!!\n", offset); - break; - } - } - - } - - efuse_power_switch(hw, true, false); - efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); - - memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], - &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], - rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); - - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "\n"); - return true; -} - -void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - - if (rtlefuse->autoload_failflag) - memset((&rtlefuse->efuse_map[EFUSE_INIT_MAP][0]), - 0xFF, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); - else - efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]); - - memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0], - &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], - rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]); - -} -EXPORT_SYMBOL(rtl_efuse_shadow_map_update); - -void efuse_force_write_vendor_Id(struct ieee80211_hw *hw) -{ - u8 tmpdata[8] = { 0xFF, 0xFF, 0xEC, 0x10, 0xFF, 0xFF, 0xFF, 0xFF }; - - efuse_power_switch(hw, true, true); - - efuse_pg_packet_write(hw, 1, 0xD, tmpdata); - - efuse_power_switch(hw, true, false); - -} - -void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx) -{ -} - -static void efuse_shadow_read_1byte(struct ieee80211_hw *hw, - u16 offset, u8 *value) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset]; -} - -static void efuse_shadow_read_2byte(struct ieee80211_hw *hw, - u16 offset, u16 *value) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - - *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset]; - *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] << 8; - -} - -static void efuse_shadow_read_4byte(struct ieee80211_hw *hw, - u16 offset, u32 *value) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - - *value = rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset]; - *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] << 8; - *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 2] << 16; - *value |= rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 3] << 24; -} - -static void efuse_shadow_write_1byte(struct ieee80211_hw *hw, - u16 offset, u8 value) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = value; -} - -static void efuse_shadow_write_2byte(struct ieee80211_hw *hw, - u16 offset, u16 value) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = value & 0x00FF; - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] = value >> 8; - -} - -static void efuse_shadow_write_4byte(struct ieee80211_hw *hw, - u16 offset, u32 value) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset] = - (u8) (value & 0x000000FF); - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 1] = - (u8) ((value >> 8) & 0x0000FF); - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 2] = - (u8) ((value >> 16) & 0x00FF); - rtlefuse->efuse_map[EFUSE_MODIFY_MAP][offset + 3] = - (u8) ((value >> 24) & 0xFF); - -} - -int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmpidx = 0; - int result; - - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 1, - (u8) (addr & 0xff)); - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2, - ((u8) ((addr >> 8) & 0x03)) | - (rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + 2) & - 0xFC)); - - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0x72); - - while (!(0x80 & rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + 3)) - && (tmpidx < 100)) { - tmpidx++; - } - - if (tmpidx < 100) { - *data = rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL]); - result = true; - } else { - *data = 0xff; - result = false; - } - return result; -} -EXPORT_SYMBOL(efuse_one_byte_read); - -static int efuse_one_byte_write(struct ieee80211_hw *hw, u16 addr, u8 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmpidx = 0; - - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - "Addr = %x Data=%x\n", addr, data); - - rtl_write_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + 1, (u8) (addr & 0xff)); - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 2, - (rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + - 2) & 0xFC) | (u8) ((addr >> 8) & 0x03)); - - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], data); - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL] + 3, 0xF2); - - while ((0x80 & rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_CTRL] + 3)) - && (tmpidx < 100)) { - tmpidx++; - } - - if (tmpidx < 100) - return true; - return false; -} - -static void efuse_read_all_map(struct ieee80211_hw *hw, u8 *efuse) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - efuse_power_switch(hw, false, true); - read_efuse(hw, 0, rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE], efuse); - efuse_power_switch(hw, false, false); -} - -static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, - u8 efuse_data, u8 offset, u8 *tmpdata, - u8 *readstate) -{ - bool dataempty = true; - u8 hoffset; - u8 tmpidx; - u8 hworden; - u8 word_cnts; - - hoffset = (efuse_data >> 4) & 0x0F; - hworden = efuse_data & 0x0F; - word_cnts = efuse_calculate_word_cnts(hworden); - - if (hoffset == offset) { - for (tmpidx = 0; tmpidx < word_cnts * 2; tmpidx++) { - if (efuse_one_byte_read(hw, *efuse_addr + 1 + tmpidx, - &efuse_data)) { - tmpdata[tmpidx] = efuse_data; - if (efuse_data != 0xff) - dataempty = false; - } - } - - if (!dataempty) { - *readstate = PG_STATE_DATA; - } else { - *efuse_addr = *efuse_addr + (word_cnts * 2) + 1; - *readstate = PG_STATE_HEADER; - } - - } else { - *efuse_addr = *efuse_addr + (word_cnts * 2) + 1; - *readstate = PG_STATE_HEADER; - } -} - -static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data) -{ - u8 readstate = PG_STATE_HEADER; - - bool continual = true; - - u8 efuse_data, word_cnts = 0; - u16 efuse_addr = 0; - u8 tmpdata[8]; - - if (data == NULL) - return false; - if (offset > 15) - return false; - - memset(data, 0xff, PGPKT_DATA_SIZE * sizeof(u8)); - memset(tmpdata, 0xff, PGPKT_DATA_SIZE * sizeof(u8)); - - while (continual && (efuse_addr < EFUSE_MAX_SIZE)) { - if (readstate & PG_STATE_HEADER) { - if (efuse_one_byte_read(hw, efuse_addr, &efuse_data) - && (efuse_data != 0xFF)) - efuse_read_data_case1(hw, &efuse_addr, - efuse_data, offset, - tmpdata, &readstate); - else - continual = false; - } else if (readstate & PG_STATE_DATA) { - efuse_word_enable_data_read(0, tmpdata, data); - efuse_addr = efuse_addr + (word_cnts * 2) + 1; - readstate = PG_STATE_HEADER; - } - - } - - if ((data[0] == 0xff) && (data[1] == 0xff) && - (data[2] == 0xff) && (data[3] == 0xff) && - (data[4] == 0xff) && (data[5] == 0xff) && - (data[6] == 0xff) && (data[7] == 0xff)) - return false; - else - return true; - -} - -static void efuse_write_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr, - u8 efuse_data, u8 offset, - int *continual, u8 *write_state, - struct pgpkt_struct *target_pkt, - int *repeat_times, int *result, u8 word_en) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct pgpkt_struct tmp_pkt; - int dataempty = true; - u8 originaldata[8 * sizeof(u8)]; - u8 badworden = 0x0F; - u8 match_word_en, tmp_word_en; - u8 tmpindex; - u8 tmp_header = efuse_data; - u8 tmp_word_cnts; - - tmp_pkt.offset = (tmp_header >> 4) & 0x0F; - tmp_pkt.word_en = tmp_header & 0x0F; - tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en); - - if (tmp_pkt.offset != target_pkt->offset) { - *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; - *write_state = PG_STATE_HEADER; - } else { - for (tmpindex = 0; tmpindex < (tmp_word_cnts * 2); tmpindex++) { - if (efuse_one_byte_read(hw, - (*efuse_addr + 1 + tmpindex), - &efuse_data) && - (efuse_data != 0xFF)) - dataempty = false; - } - - if (!dataempty) { - *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; - *write_state = PG_STATE_HEADER; - } else { - match_word_en = 0x0F; - if (!((target_pkt->word_en & BIT(0)) | - (tmp_pkt.word_en & BIT(0)))) - match_word_en &= (~BIT(0)); - - if (!((target_pkt->word_en & BIT(1)) | - (tmp_pkt.word_en & BIT(1)))) - match_word_en &= (~BIT(1)); - - if (!((target_pkt->word_en & BIT(2)) | - (tmp_pkt.word_en & BIT(2)))) - match_word_en &= (~BIT(2)); - - if (!((target_pkt->word_en & BIT(3)) | - (tmp_pkt.word_en & BIT(3)))) - match_word_en &= (~BIT(3)); - - if ((match_word_en & 0x0F) != 0x0F) { - badworden = - enable_efuse_data_write(hw, - *efuse_addr + 1, - tmp_pkt.word_en, - target_pkt->data); - - if (0x0F != (badworden & 0x0F)) { - u8 reorg_offset = offset; - u8 reorg_worden = badworden; - efuse_pg_packet_write(hw, reorg_offset, - reorg_worden, - originaldata); - } - - tmp_word_en = 0x0F; - if ((target_pkt->word_en & BIT(0)) ^ - (match_word_en & BIT(0))) - tmp_word_en &= (~BIT(0)); - - if ((target_pkt->word_en & BIT(1)) ^ - (match_word_en & BIT(1))) - tmp_word_en &= (~BIT(1)); - - if ((target_pkt->word_en & BIT(2)) ^ - (match_word_en & BIT(2))) - tmp_word_en &= (~BIT(2)); - - if ((target_pkt->word_en & BIT(3)) ^ - (match_word_en & BIT(3))) - tmp_word_en &= (~BIT(3)); - - if ((tmp_word_en & 0x0F) != 0x0F) { - *efuse_addr = efuse_get_current_size(hw); - target_pkt->offset = offset; - target_pkt->word_en = tmp_word_en; - } else { - *continual = false; - } - *write_state = PG_STATE_HEADER; - *repeat_times += 1; - if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { - *continual = false; - *result = false; - } - } else { - *efuse_addr += (2 * tmp_word_cnts) + 1; - target_pkt->offset = offset; - target_pkt->word_en = word_en; - *write_state = PG_STATE_HEADER; - } - } - } - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse PG_STATE_HEADER-1\n"); -} - -static void efuse_write_data_case2(struct ieee80211_hw *hw, u16 *efuse_addr, - int *continual, u8 *write_state, - struct pgpkt_struct target_pkt, - int *repeat_times, int *result) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct pgpkt_struct tmp_pkt; - u8 pg_header; - u8 tmp_header; - u8 originaldata[8 * sizeof(u8)]; - u8 tmp_word_cnts; - u8 badworden = 0x0F; - - pg_header = ((target_pkt.offset << 4) & 0xf0) | target_pkt.word_en; - efuse_one_byte_write(hw, *efuse_addr, pg_header); - efuse_one_byte_read(hw, *efuse_addr, &tmp_header); - - if (tmp_header == pg_header) { - *write_state = PG_STATE_DATA; - } else if (tmp_header == 0xFF) { - *write_state = PG_STATE_HEADER; - *repeat_times += 1; - if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { - *continual = false; - *result = false; - } - } else { - tmp_pkt.offset = (tmp_header >> 4) & 0x0F; - tmp_pkt.word_en = tmp_header & 0x0F; - - tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en); - - memset(originaldata, 0xff, 8 * sizeof(u8)); - - if (efuse_pg_packet_read(hw, tmp_pkt.offset, originaldata)) { - badworden = enable_efuse_data_write(hw, - *efuse_addr + 1, - tmp_pkt.word_en, - originaldata); - - if (0x0F != (badworden & 0x0F)) { - u8 reorg_offset = tmp_pkt.offset; - u8 reorg_worden = badworden; - efuse_pg_packet_write(hw, reorg_offset, - reorg_worden, - originaldata); - *efuse_addr = efuse_get_current_size(hw); - } else { - *efuse_addr = *efuse_addr + - (tmp_word_cnts * 2) + 1; - } - } else { - *efuse_addr = *efuse_addr + (tmp_word_cnts * 2) + 1; - } - - *write_state = PG_STATE_HEADER; - *repeat_times += 1; - if (*repeat_times > EFUSE_REPEAT_THRESHOLD_) { - *continual = false; - *result = false; - } - - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - "efuse PG_STATE_HEADER-2\n"); - } -} - -static int efuse_pg_packet_write(struct ieee80211_hw *hw, - u8 offset, u8 word_en, u8 *data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct pgpkt_struct target_pkt; - u8 write_state = PG_STATE_HEADER; - int continual = true, dataempty = true, result = true; - u16 efuse_addr = 0; - u8 efuse_data; - u8 target_word_cnts = 0; - u8 badworden = 0x0F; - static int repeat_times; - - if (efuse_get_current_size(hw) >= (EFUSE_MAX_SIZE - - rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) { - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - "efuse_pg_packet_write error\n"); - return false; - } - - target_pkt.offset = offset; - target_pkt.word_en = word_en; - - memset(target_pkt.data, 0xFF, 8 * sizeof(u8)); - - efuse_word_enable_data_read(word_en, data, target_pkt.data); - target_word_cnts = efuse_calculate_word_cnts(target_pkt.word_en); - - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, "efuse Power ON\n"); - - while (continual && (efuse_addr < (EFUSE_MAX_SIZE - - rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))) { - - if (write_state == PG_STATE_HEADER) { - dataempty = true; - badworden = 0x0F; - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - "efuse PG_STATE_HEADER\n"); - - if (efuse_one_byte_read(hw, efuse_addr, &efuse_data) && - (efuse_data != 0xFF)) - efuse_write_data_case1(hw, &efuse_addr, - efuse_data, offset, - &continual, - &write_state, - &target_pkt, - &repeat_times, &result, - word_en); - else - efuse_write_data_case2(hw, &efuse_addr, - &continual, - &write_state, - target_pkt, - &repeat_times, - &result); - - } else if (write_state == PG_STATE_DATA) { - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - "efuse PG_STATE_DATA\n"); - badworden = 0x0f; - badworden = - enable_efuse_data_write(hw, efuse_addr + 1, - target_pkt.word_en, - target_pkt.data); - - if ((badworden & 0x0F) == 0x0F) { - continual = false; - } else { - efuse_addr = - efuse_addr + (2 * target_word_cnts) + 1; - - target_pkt.offset = offset; - target_pkt.word_en = badworden; - target_word_cnts = - efuse_calculate_word_cnts(target_pkt. - word_en); - write_state = PG_STATE_HEADER; - repeat_times++; - if (repeat_times > EFUSE_REPEAT_THRESHOLD_) { - continual = false; - result = false; - } - RTPRINT(rtlpriv, FEEPROM, EFUSE_PG, - "efuse PG_STATE_HEADER-3\n"); - } - } - } - - if (efuse_addr >= (EFUSE_MAX_SIZE - - rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) { - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - "efuse_addr(%#x) Out of size!!\n", efuse_addr); - } - - return true; -} - -static void efuse_word_enable_data_read(u8 word_en, u8 *sourdata, - u8 *targetdata) -{ - if (!(word_en & BIT(0))) { - targetdata[0] = sourdata[0]; - targetdata[1] = sourdata[1]; - } - - if (!(word_en & BIT(1))) { - targetdata[2] = sourdata[2]; - targetdata[3] = sourdata[3]; - } - - if (!(word_en & BIT(2))) { - targetdata[4] = sourdata[4]; - targetdata[5] = sourdata[5]; - } - - if (!(word_en & BIT(3))) { - targetdata[6] = sourdata[6]; - targetdata[7] = sourdata[7]; - } -} - -static u8 enable_efuse_data_write(struct ieee80211_hw *hw, - u16 efuse_addr, u8 word_en, u8 *data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 tmpaddr; - u16 start_addr = efuse_addr; - u8 badworden = 0x0F; - u8 tmpdata[8]; - - memset(tmpdata, 0xff, PGPKT_DATA_SIZE); - RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, - "word_en = %x efuse_addr=%x\n", word_en, efuse_addr); - - if (!(word_en & BIT(0))) { - tmpaddr = start_addr; - efuse_one_byte_write(hw, start_addr++, data[0]); - efuse_one_byte_write(hw, start_addr++, data[1]); - - efuse_one_byte_read(hw, tmpaddr, &tmpdata[0]); - efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[1]); - if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) - badworden &= (~BIT(0)); - } - - if (!(word_en & BIT(1))) { - tmpaddr = start_addr; - efuse_one_byte_write(hw, start_addr++, data[2]); - efuse_one_byte_write(hw, start_addr++, data[3]); - - efuse_one_byte_read(hw, tmpaddr, &tmpdata[2]); - efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[3]); - if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) - badworden &= (~BIT(1)); - } - - if (!(word_en & BIT(2))) { - tmpaddr = start_addr; - efuse_one_byte_write(hw, start_addr++, data[4]); - efuse_one_byte_write(hw, start_addr++, data[5]); - - efuse_one_byte_read(hw, tmpaddr, &tmpdata[4]); - efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[5]); - if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) - badworden &= (~BIT(2)); - } - - if (!(word_en & BIT(3))) { - tmpaddr = start_addr; - efuse_one_byte_write(hw, start_addr++, data[6]); - efuse_one_byte_write(hw, start_addr++, data[7]); - - efuse_one_byte_read(hw, tmpaddr, &tmpdata[6]); - efuse_one_byte_read(hw, tmpaddr + 1, &tmpdata[7]); - if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) - badworden &= (~BIT(3)); - } - - return badworden; -} - -static void efuse_power_switch(struct ieee80211_hw *hw, u8 write, u8 pwrstate) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tempval; - u16 tmpV16; - - if (pwrstate && (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)) { - - if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192CE && - rtlhal->hw_type != HARDWARE_TYPE_RTL8192DE) { - rtl_write_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_ACCESS], 0x69); - } else { - tmpV16 = - rtl_read_word(rtlpriv, - rtlpriv->cfg->maps[SYS_ISO_CTRL]); - if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_PWC_EV12V])) { - tmpV16 |= rtlpriv->cfg->maps[EFUSE_PWC_EV12V]; - rtl_write_word(rtlpriv, - rtlpriv->cfg->maps[SYS_ISO_CTRL], - tmpV16); - } - } - tmpV16 = rtl_read_word(rtlpriv, - rtlpriv->cfg->maps[SYS_FUNC_EN]); - if (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_FEN_ELDR])) { - tmpV16 |= rtlpriv->cfg->maps[EFUSE_FEN_ELDR]; - rtl_write_word(rtlpriv, - rtlpriv->cfg->maps[SYS_FUNC_EN], tmpV16); - } - - tmpV16 = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_CLK]); - if ((!(tmpV16 & rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN])) || - (!(tmpV16 & rtlpriv->cfg->maps[EFUSE_ANA8M]))) { - tmpV16 |= (rtlpriv->cfg->maps[EFUSE_LOADER_CLK_EN] | - rtlpriv->cfg->maps[EFUSE_ANA8M]); - rtl_write_word(rtlpriv, - rtlpriv->cfg->maps[SYS_CLK], tmpV16); - } - } - - if (pwrstate) { - if (write) { - tempval = rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_TEST] + - 3); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - tempval &= ~(BIT(3) | BIT(4) | BIT(5) | BIT(6)); - tempval |= (VOLTAGE_V25 << 3); - } else if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) { - tempval &= 0x0F; - tempval |= (VOLTAGE_V25 << 4); - } - - rtl_write_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_TEST] + 3, - (tempval | 0x80)); - } - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK], - 0x03); - } - } else { - if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192CE && - rtlhal->hw_type != HARDWARE_TYPE_RTL8192DE) - rtl_write_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_ACCESS], 0); - - if (write) { - tempval = rtl_read_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_TEST] + - 3); - rtl_write_byte(rtlpriv, - rtlpriv->cfg->maps[EFUSE_TEST] + 3, - (tempval & 0x7F)); - } - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CLK], - 0x02); - } - } -} - -static u16 efuse_get_current_size(struct ieee80211_hw *hw) -{ - int continual = true; - u16 efuse_addr = 0; - u8 hoffset, hworden; - u8 efuse_data, word_cnts; - - while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data) && - (efuse_addr < EFUSE_MAX_SIZE)) { - if (efuse_data != 0xFF) { - hoffset = (efuse_data >> 4) & 0x0F; - hworden = efuse_data & 0x0F; - word_cnts = efuse_calculate_word_cnts(hworden); - efuse_addr = efuse_addr + (word_cnts * 2) + 1; - } else { - continual = false; - } - } - - return efuse_addr; -} - -static u8 efuse_calculate_word_cnts(u8 word_en) -{ - u8 word_cnts = 0; - if (!(word_en & BIT(0))) - word_cnts++; - if (!(word_en & BIT(1))) - word_cnts++; - if (!(word_en & BIT(2))) - word_cnts++; - if (!(word_en & BIT(3))) - word_cnts++; - return word_cnts; -} - diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/rtlwifi/efuse.h deleted file mode 100644 index be02e7894c61..000000000000 --- a/drivers/net/wireless/rtlwifi/efuse.h +++ /dev/null @@ -1,113 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL_EFUSE_H_ -#define __RTL_EFUSE_H_ - -#define EFUSE_IC_ID_OFFSET 506 - -#define EFUSE_MAX_WORD_UNIT 4 - -#define EFUSE_INIT_MAP 0 -#define EFUSE_MODIFY_MAP 1 - -#define PG_STATE_HEADER 0x01 -#define PG_STATE_WORD_0 0x02 -#define PG_STATE_WORD_1 0x04 -#define PG_STATE_WORD_2 0x08 -#define PG_STATE_WORD_3 0x10 -#define PG_STATE_DATA 0x20 - -#define EFUSE_REPEAT_THRESHOLD_ 3 -#define EFUSE_ERROE_HANDLE 1 - -struct efuse_map { - u8 offset; - u8 word_start; - u8 byte_start; - u8 byte_cnts; -}; - -struct pgpkt_struct { - u8 offset; - u8 word_en; - u8 data[8]; -}; - -enum efuse_data_item { - EFUSE_CHIP_ID = 0, - EFUSE_LDO_SETTING, - EFUSE_CLK_SETTING, - EFUSE_SDIO_SETTING, - EFUSE_CCCR, - EFUSE_SDIO_MODE, - EFUSE_OCR, - EFUSE_F0CIS, - EFUSE_F1CIS, - EFUSE_MAC_ADDR, - EFUSE_EEPROM_VER, - EFUSE_CHAN_PLAN, - EFUSE_TXPW_TAB -}; - -enum { - VOLTAGE_V25 = 0x03, - LDOE25_SHIFT = 28, -}; - -struct efuse_priv { - u8 id[2]; - u8 ldo_setting[2]; - u8 clk_setting[2]; - u8 cccr; - u8 sdio_mode; - u8 ocr[3]; - u8 cis0[17]; - u8 cis1[48]; - u8 mac_addr[6]; - u8 eeprom_verno; - u8 channel_plan; - u8 tx_power_b[14]; - u8 tx_power_g[14]; -}; - -void read_efuse_byte(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); -void efuse_initialize(struct ieee80211_hw *hw); -u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address); -int efuse_one_byte_read(struct ieee80211_hw *hw, u16 addr, u8 *data); -void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value); -void read_efuse(struct ieee80211_hw *hw, u16 _offset, - u16 _size_byte, u8 *pbuf); -void efuse_shadow_read(struct ieee80211_hw *hw, u8 type, - u16 offset, u32 *value); -void efuse_shadow_write(struct ieee80211_hw *hw, u8 type, - u16 offset, u32 value); -bool efuse_shadow_update(struct ieee80211_hw *hw); -bool efuse_shadow_update_chk(struct ieee80211_hw *hw); -void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw); -void efuse_force_write_vendor_Id(struct ieee80211_hw *hw); -void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx); - -#endif diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c deleted file mode 100644 index f46c9d7f6528..000000000000 --- a/drivers/net/wireless/rtlwifi/pci.c +++ /dev/null @@ -1,2478 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "wifi.h" -#include "core.h" -#include "pci.h" -#include "base.h" -#include "ps.h" -#include "efuse.h" -#include -#include -#include -#include - -MODULE_AUTHOR("lizhaoming "); -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_AUTHOR("Larry Finger "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("PCI basic driver for rtlwifi"); - -static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { - INTEL_VENDOR_ID, - ATI_VENDOR_ID, - AMD_VENDOR_ID, - SIS_VENDOR_ID -}; - -static const u8 ac_to_hwq[] = { - VO_QUEUE, - VI_QUEUE, - BE_QUEUE, - BK_QUEUE -}; - -static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - __le16 fc = rtl_get_fc(skb); - u8 queue_index = skb_get_queue_mapping(skb); - - if (unlikely(ieee80211_is_beacon(fc))) - return BEACON_QUEUE; - if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) - return MGNT_QUEUE; - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) - if (ieee80211_is_nullfunc(fc)) - return HIGH_QUEUE; - - return ac_to_hwq[queue_index]; -} - -/* Update PCI dependent default settings*/ -static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; - u8 init_aspm; - - ppsc->reg_rfps_level = 0; - ppsc->support_aspm = false; - - /*Update PCI ASPM setting */ - ppsc->const_amdpci_aspm = rtlpci->const_amdpci_aspm; - switch (rtlpci->const_pci_aspm) { - case 0: - /*No ASPM */ - break; - - case 1: - /*ASPM dynamically enabled/disable. */ - ppsc->reg_rfps_level |= RT_RF_LPS_LEVEL_ASPM; - break; - - case 2: - /*ASPM with Clock Req dynamically enabled/disable. */ - ppsc->reg_rfps_level |= (RT_RF_LPS_LEVEL_ASPM | - RT_RF_OFF_LEVL_CLK_REQ); - break; - - case 3: - /* - * Always enable ASPM and Clock Req - * from initialization to halt. - * */ - ppsc->reg_rfps_level &= ~(RT_RF_LPS_LEVEL_ASPM); - ppsc->reg_rfps_level |= (RT_RF_PS_LEVEL_ALWAYS_ASPM | - RT_RF_OFF_LEVL_CLK_REQ); - break; - - case 4: - /* - * Always enable ASPM without Clock Req - * from initialization to halt. - * */ - ppsc->reg_rfps_level &= ~(RT_RF_LPS_LEVEL_ASPM | - RT_RF_OFF_LEVL_CLK_REQ); - ppsc->reg_rfps_level |= RT_RF_PS_LEVEL_ALWAYS_ASPM; - break; - } - - ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_HALT_NIC; - - /*Update Radio OFF setting */ - switch (rtlpci->const_hwsw_rfoff_d3) { - case 1: - if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM) - ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_ASPM; - break; - - case 2: - if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM) - ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_ASPM; - ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_HALT_NIC; - break; - - case 3: - ppsc->reg_rfps_level |= RT_RF_OFF_LEVL_PCI_D3; - break; - } - - /*Set HW definition to determine if it supports ASPM. */ - switch (rtlpci->const_support_pciaspm) { - case 0:{ - /*Not support ASPM. */ - bool support_aspm = false; - ppsc->support_aspm = support_aspm; - break; - } - case 1:{ - /*Support ASPM. */ - bool support_aspm = true; - bool support_backdoor = true; - ppsc->support_aspm = support_aspm; - - /*if (priv->oem_id == RT_CID_TOSHIBA && - !priv->ndis_adapter.amd_l1_patch) - support_backdoor = false; */ - - ppsc->support_backdoor = support_backdoor; - - break; - } - case 2: - /*ASPM value set by chipset. */ - if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) { - bool support_aspm = true; - ppsc->support_aspm = support_aspm; - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - - /* toshiba aspm issue, toshiba will set aspm selfly - * so we should not set aspm in driver */ - pci_read_config_byte(rtlpci->pdev, 0x80, &init_aspm); - if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8192SE && - init_aspm == 0x43) - ppsc->support_aspm = false; -} - -static bool _rtl_pci_platform_switch_device_pci_aspm( - struct ieee80211_hw *hw, - u8 value) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE) - value |= 0x40; - - pci_write_config_byte(rtlpci->pdev, 0x80, value); - - return false; -} - -/*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/ -static void _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - pci_write_config_byte(rtlpci->pdev, 0x81, value); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) - udelay(100); -} - -/*Disable RTL8192SE ASPM & Disable Pci Bridge ASPM*/ -static void rtl_pci_disable_aspm(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; - u8 num4bytes = pcipriv->ndis_adapter.num4bytes; - /*Retrieve original configuration settings. */ - u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg; - u16 pcibridge_linkctrlreg = pcipriv->ndis_adapter. - pcibridge_linkctrlreg; - u16 aspmlevel = 0; - u8 tmp_u1b = 0; - - if (!ppsc->support_aspm) - return; - - if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "PCI(Bridge) UNKNOWN\n"); - - return; - } - - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) { - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ); - _rtl_pci_switch_clk_req(hw, 0x0); - } - - /*for promising device will in L0 state after an I/O. */ - pci_read_config_byte(rtlpci->pdev, 0x80, &tmp_u1b); - - /*Set corresponding value. */ - aspmlevel |= BIT(0) | BIT(1); - linkctrl_reg &= ~aspmlevel; - pcibridge_linkctrlreg &= ~(BIT(0) | BIT(1)); - - _rtl_pci_platform_switch_device_pci_aspm(hw, linkctrl_reg); - udelay(50); - - /*4 Disable Pci Bridge ASPM */ - pci_write_config_byte(rtlpci->pdev, (num4bytes << 2), - pcibridge_linkctrlreg); - - udelay(50); -} - -/* - *Enable RTL8192SE ASPM & Enable Pci Bridge ASPM for - *power saving We should follow the sequence to enable - *RTL8192SE first then enable Pci Bridge ASPM - *or the system will show bluescreen. - */ -static void rtl_pci_enable_aspm(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; - u8 num4bytes = pcipriv->ndis_adapter.num4bytes; - u16 aspmlevel; - u8 u_pcibridge_aspmsetting; - u8 u_device_aspmsetting; - - if (!ppsc->support_aspm) - return; - - if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "PCI(Bridge) UNKNOWN\n"); - return; - } - - /*4 Enable Pci Bridge ASPM */ - - u_pcibridge_aspmsetting = - pcipriv->ndis_adapter.pcibridge_linkctrlreg | - rtlpci->const_hostpci_aspm_setting; - - if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) - u_pcibridge_aspmsetting &= ~BIT(0); - - pci_write_config_byte(rtlpci->pdev, (num4bytes << 2), - u_pcibridge_aspmsetting); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "PlatformEnableASPM(): Write reg[%x] = %x\n", - (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10), - u_pcibridge_aspmsetting); - - udelay(50); - - /*Get ASPM level (with/without Clock Req) */ - aspmlevel = rtlpci->const_devicepci_aspm_setting; - u_device_aspmsetting = pcipriv->ndis_adapter.linkctrl_reg; - - /*_rtl_pci_platform_switch_device_pci_aspm(dev,*/ - /*(priv->ndis_adapter.linkctrl_reg | ASPMLevel)); */ - - u_device_aspmsetting |= aspmlevel; - - _rtl_pci_platform_switch_device_pci_aspm(hw, u_device_aspmsetting); - - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) { - _rtl_pci_switch_clk_req(hw, (ppsc->reg_rfps_level & - RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ); - } - udelay(100); -} - -static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - bool status = false; - u8 offset_e0; - unsigned offset_e4; - - pci_write_config_byte(rtlpci->pdev, 0xe0, 0xa0); - - pci_read_config_byte(rtlpci->pdev, 0xe0, &offset_e0); - - if (offset_e0 == 0xA0) { - pci_read_config_dword(rtlpci->pdev, 0xe4, &offset_e4); - if (offset_e4 & BIT(23)) - status = true; - } - - return status; -} - -static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw, - struct rtl_priv **buddy_priv) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - bool find_buddy_priv = false; - struct rtl_priv *tpriv = NULL; - struct rtl_pci_priv *tpcipriv = NULL; - - if (!list_empty(&rtlpriv->glb_var->glb_priv_list)) { - list_for_each_entry(tpriv, &rtlpriv->glb_var->glb_priv_list, - list) { - if (tpriv) { - tpcipriv = (struct rtl_pci_priv *)tpriv->priv; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "pcipriv->ndis_adapter.funcnumber %x\n", - pcipriv->ndis_adapter.funcnumber); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "tpcipriv->ndis_adapter.funcnumber %x\n", - tpcipriv->ndis_adapter.funcnumber); - - if ((pcipriv->ndis_adapter.busnumber == - tpcipriv->ndis_adapter.busnumber) && - (pcipriv->ndis_adapter.devnumber == - tpcipriv->ndis_adapter.devnumber) && - (pcipriv->ndis_adapter.funcnumber != - tpcipriv->ndis_adapter.funcnumber)) { - find_buddy_priv = true; - break; - } - } - } - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "find_buddy_priv %d\n", find_buddy_priv); - - if (find_buddy_priv) - *buddy_priv = tpriv; - - return find_buddy_priv; -} - -static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); - u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset; - u8 linkctrl_reg; - u8 num4bbytes; - - num4bbytes = (capabilityoffset + 0x10) / 4; - - /*Read Link Control Register */ - pci_read_config_byte(rtlpci->pdev, (num4bbytes << 2), &linkctrl_reg); - - pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg; -} - -static void rtl_pci_parse_configuration(struct pci_dev *pdev, - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - - u8 tmp; - u16 linkctrl_reg; - - /*Link Control Register */ - pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &linkctrl_reg); - pcipriv->ndis_adapter.linkctrl_reg = (u8)linkctrl_reg; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Link Control Register =%x\n", - pcipriv->ndis_adapter.linkctrl_reg); - - pci_read_config_byte(pdev, 0x98, &tmp); - tmp |= BIT(4); - pci_write_config_byte(pdev, 0x98, tmp); - - tmp = 0x17; - pci_write_config_byte(pdev, 0x70f, tmp); -} - -static void rtl_pci_init_aspm(struct ieee80211_hw *hw) -{ - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - _rtl_pci_update_default_setting(hw); - - if (ppsc->reg_rfps_level & RT_RF_PS_LEVEL_ALWAYS_ASPM) { - /*Always enable ASPM & Clock Req. */ - rtl_pci_enable_aspm(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_PS_LEVEL_ALWAYS_ASPM); - } - -} - -static void _rtl_pci_io_handler_init(struct device *dev, - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->io.dev = dev; - - rtlpriv->io.write8_async = pci_write8_async; - rtlpriv->io.write16_async = pci_write16_async; - rtlpriv->io.write32_async = pci_write32_async; - - rtlpriv->io.read8_sync = pci_read8_sync; - rtlpriv->io.read16_sync = pci_read16_sync; - rtlpriv->io.read32_sync = pci_read32_sync; - -} - -static bool _rtl_update_earlymode_info(struct ieee80211_hw *hw, - struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc, u8 tid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct sk_buff *next_skb; - u8 additionlen = FCS_LEN; - - /* here open is 4, wep/tkip is 8, aes is 12*/ - if (info->control.hw_key) - additionlen += info->control.hw_key->icv_len; - - /* The most skb num is 6 */ - tcb_desc->empkt_num = 0; - spin_lock_bh(&rtlpriv->locks.waitq_lock); - skb_queue_walk(&rtlpriv->mac80211.skb_waitq[tid], next_skb) { - struct ieee80211_tx_info *next_info; - - next_info = IEEE80211_SKB_CB(next_skb); - if (next_info->flags & IEEE80211_TX_CTL_AMPDU) { - tcb_desc->empkt_len[tcb_desc->empkt_num] = - next_skb->len + additionlen; - tcb_desc->empkt_num++; - } else { - break; - } - - if (skb_queue_is_last(&rtlpriv->mac80211.skb_waitq[tid], - next_skb)) - break; - - if (tcb_desc->empkt_num >= rtlhal->max_earlymode_num) - break; - } - spin_unlock_bh(&rtlpriv->locks.waitq_lock); - - return true; -} - -/* just for early mode now */ -static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct sk_buff *skb = NULL; - struct ieee80211_tx_info *info = NULL; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - int tid; - - if (!rtlpriv->rtlhal.earlymode_enable) - return; - - if (rtlpriv->dm.supp_phymode_switch && - (rtlpriv->easy_concurrent_ctl.switch_in_process || - (rtlpriv->buddy_priv && - rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process))) - return; - /* we juse use em for BE/BK/VI/VO */ - for (tid = 7; tid >= 0; tid--) { - u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)]; - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; - while (!mac->act_scanning && - rtlpriv->psc.rfpwr_state == ERFON) { - struct rtl_tcb_desc tcb_desc; - memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); - - spin_lock_bh(&rtlpriv->locks.waitq_lock); - if (!skb_queue_empty(&mac->skb_waitq[tid]) && - (ring->entries - skb_queue_len(&ring->queue) > - rtlhal->max_earlymode_num)) { - skb = skb_dequeue(&mac->skb_waitq[tid]); - } else { - spin_unlock_bh(&rtlpriv->locks.waitq_lock); - break; - } - spin_unlock_bh(&rtlpriv->locks.waitq_lock); - - /* Some macaddr can't do early mode. like - * multicast/broadcast/no_qos data */ - info = IEEE80211_SKB_CB(skb); - if (info->flags & IEEE80211_TX_CTL_AMPDU) - _rtl_update_earlymode_info(hw, skb, - &tcb_desc, tid); - - rtlpriv->intf_ops->adapter_tx(hw, NULL, skb, &tcb_desc); - } - } -} - - -static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[prio]; - - while (skb_queue_len(&ring->queue)) { - struct sk_buff *skb; - struct ieee80211_tx_info *info; - __le16 fc; - u8 tid; - u8 *entry; - - if (rtlpriv->use_new_trx_flow) - entry = (u8 *)(&ring->buffer_desc[ring->idx]); - else - entry = (u8 *)(&ring->desc[ring->idx]); - - if (rtlpriv->cfg->ops->get_available_desc && - rtlpriv->cfg->ops->get_available_desc(hw, prio) <= 1) { - RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_DMESG, - "no available desc!\n"); - return; - } - - if (!rtlpriv->cfg->ops->is_tx_desc_closed(hw, prio, ring->idx)) - return; - ring->idx = (ring->idx + 1) % ring->entries; - - skb = __skb_dequeue(&ring->queue); - pci_unmap_single(rtlpci->pdev, - rtlpriv->cfg->ops-> - get_desc((u8 *)entry, true, - HW_DESC_TXBUFF_ADDR), - skb->len, PCI_DMA_TODEVICE); - - /* remove early mode header */ - if (rtlpriv->rtlhal.earlymode_enable) - skb_pull(skb, EM_HDR_LEN); - - RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_TRACE, - "new ring->idx:%d, free: skb_queue_len:%d, free: seq:%x\n", - ring->idx, - skb_queue_len(&ring->queue), - *(u16 *)(skb->data + 22)); - - if (prio == TXCMD_QUEUE) { - dev_kfree_skb(skb); - goto tx_status_ok; - - } - - /* for sw LPS, just after NULL skb send out, we can - * sure AP knows we are sleeping, we should not let - * rf sleep - */ - fc = rtl_get_fc(skb); - if (ieee80211_is_nullfunc(fc)) { - if (ieee80211_has_pm(fc)) { - rtlpriv->mac80211.offchan_delay = true; - rtlpriv->psc.state_inap = true; - } else { - rtlpriv->psc.state_inap = false; - } - } - if (ieee80211_is_action(fc)) { - struct ieee80211_mgmt *action_frame = - (struct ieee80211_mgmt *)skb->data; - if (action_frame->u.action.u.ht_smps.action == - WLAN_HT_ACTION_SMPS) { - dev_kfree_skb(skb); - goto tx_status_ok; - } - } - - /* update tid tx pkt num */ - tid = rtl_get_tid(skb); - if (tid <= 7) - rtlpriv->link_info.tidtx_inperiod[tid]++; - - info = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(info); - - info->flags |= IEEE80211_TX_STAT_ACK; - /*info->status.rates[0].count = 1; */ - - ieee80211_tx_status_irqsafe(hw, skb); - - if ((ring->entries - skb_queue_len(&ring->queue)) <= 4) { - - RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, - "more desc left, wake skb_queue@%d, ring->idx = %d, skb_queue_len = 0x%x\n", - prio, ring->idx, - skb_queue_len(&ring->queue)); - - ieee80211_wake_queue(hw, - skb_get_queue_mapping - (skb)); - } -tx_status_ok: - skb = NULL; - } - - if (((rtlpriv->link_info.num_rx_inperiod + - rtlpriv->link_info.num_tx_inperiod) > 8) || - (rtlpriv->link_info.num_rx_inperiod > 2)) { - rtlpriv->enter_ps = false; - schedule_work(&rtlpriv->works.lps_change_work); - } -} - -static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw, - struct sk_buff *new_skb, u8 *entry, - int rxring_idx, int desc_idx) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u32 bufferaddress; - u8 tmp_one = 1; - struct sk_buff *skb; - - if (likely(new_skb)) { - skb = new_skb; - goto remap; - } - skb = dev_alloc_skb(rtlpci->rxbuffersize); - if (!skb) - return 0; - -remap: - /* just set skb->cb to mapping addr for pci_unmap_single use */ - *((dma_addr_t *)skb->cb) = - pci_map_single(rtlpci->pdev, skb_tail_pointer(skb), - rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); - bufferaddress = *((dma_addr_t *)skb->cb); - if (pci_dma_mapping_error(rtlpci->pdev, bufferaddress)) - return 0; - rtlpci->rx_ring[rxring_idx].rx_buf[desc_idx] = skb; - if (rtlpriv->use_new_trx_flow) { - rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false, - HW_DESC_RX_PREPARE, - (u8 *)&bufferaddress); - } else { - rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false, - HW_DESC_RXBUFF_ADDR, - (u8 *)&bufferaddress); - rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false, - HW_DESC_RXPKT_LEN, - (u8 *)&rtlpci->rxbuffersize); - rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false, - HW_DESC_RXOWN, - (u8 *)&tmp_one); - } - return 1; -} - -/* inorder to receive 8K AMSDU we have set skb to - * 9100bytes in init rx ring, but if this packet is - * not a AMSDU, this large packet will be sent to - * TCP/IP directly, this cause big packet ping fail - * like: "ping -s 65507", so here we will realloc skb - * based on the true size of packet, Mac80211 - * Probably will do it better, but does not yet. - * - * Some platform will fail when alloc skb sometimes. - * in this condition, we will send the old skb to - * mac80211 directly, this will not cause any other - * issues, but only this packet will be lost by TCP/IP - */ -static void _rtl_pci_rx_to_mac80211(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct ieee80211_rx_status rx_status) -{ - if (unlikely(!rtl_action_proc(hw, skb, false))) { - dev_kfree_skb_any(skb); - } else { - struct sk_buff *uskb = NULL; - u8 *pdata; - - uskb = dev_alloc_skb(skb->len + 128); - if (likely(uskb)) { - memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, - sizeof(rx_status)); - pdata = (u8 *)skb_put(uskb, skb->len); - memcpy(pdata, skb->data, skb->len); - dev_kfree_skb_any(skb); - ieee80211_rx_irqsafe(hw, uskb); - } else { - ieee80211_rx_irqsafe(hw, skb); - } - } -} - -/*hsisr interrupt handler*/ -static void _rtl_pci_hs_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[MAC_HSISR], - rtl_read_byte(rtlpriv, rtlpriv->cfg->maps[MAC_HSISR]) | - rtlpci->sys_irq_mask); -} - -static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - int rxring_idx = RTL_PCI_RX_MPDU_QUEUE; - struct ieee80211_rx_status rx_status = { 0 }; - unsigned int count = rtlpci->rxringcount; - u8 own; - u8 tmp_one; - bool unicast = false; - u8 hw_queue = 0; - unsigned int rx_remained_cnt; - struct rtl_stats stats = { - .signal = 0, - .rate = 0, - }; - - /*RX NORMAL PKT */ - while (count--) { - struct ieee80211_hdr *hdr; - __le16 fc; - u16 len; - /*rx buffer descriptor */ - struct rtl_rx_buffer_desc *buffer_desc = NULL; - /*if use new trx flow, it means wifi info */ - struct rtl_rx_desc *pdesc = NULL; - /*rx pkt */ - struct sk_buff *skb = rtlpci->rx_ring[rxring_idx].rx_buf[ - rtlpci->rx_ring[rxring_idx].idx]; - struct sk_buff *new_skb; - - if (rtlpriv->use_new_trx_flow) { - rx_remained_cnt = - rtlpriv->cfg->ops->rx_desc_buff_remained_cnt(hw, - hw_queue); - if (rx_remained_cnt == 0) - return; - - } else { /* rx descriptor */ - pdesc = &rtlpci->rx_ring[rxring_idx].desc[ - rtlpci->rx_ring[rxring_idx].idx]; - - own = (u8)rtlpriv->cfg->ops->get_desc((u8 *)pdesc, - false, - HW_DESC_OWN); - if (own) /* wait data to be filled by hardware */ - return; - } - - /* Reaching this point means: data is filled already - * AAAAAAttention !!! - * We can NOT access 'skb' before 'pci_unmap_single' - */ - pci_unmap_single(rtlpci->pdev, *((dma_addr_t *)skb->cb), - rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); - - /* get a new skb - if fail, old one will be reused */ - new_skb = dev_alloc_skb(rtlpci->rxbuffersize); - if (unlikely(!new_skb)) - goto no_new; - if (rtlpriv->use_new_trx_flow) { - buffer_desc = - &rtlpci->rx_ring[rxring_idx].buffer_desc - [rtlpci->rx_ring[rxring_idx].idx]; - /*means rx wifi info*/ - pdesc = (struct rtl_rx_desc *)skb->data; - } - memset(&rx_status , 0 , sizeof(rx_status)); - rtlpriv->cfg->ops->query_rx_desc(hw, &stats, - &rx_status, (u8 *)pdesc, skb); - - if (rtlpriv->use_new_trx_flow) - rtlpriv->cfg->ops->rx_check_dma_ok(hw, - (u8 *)buffer_desc, - hw_queue); - - len = rtlpriv->cfg->ops->get_desc((u8 *)pdesc, false, - HW_DESC_RXPKT_LEN); - - if (skb->end - skb->tail > len) { - skb_put(skb, len); - if (rtlpriv->use_new_trx_flow) - skb_reserve(skb, stats.rx_drvinfo_size + - stats.rx_bufshift + 24); - else - skb_reserve(skb, stats.rx_drvinfo_size + - stats.rx_bufshift); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "skb->end - skb->tail = %d, len is %d\n", - skb->end - skb->tail, len); - dev_kfree_skb_any(skb); - goto new_trx_end; - } - /* handle command packet here */ - if (rtlpriv->cfg->ops->rx_command_packet && - rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) { - dev_kfree_skb_any(skb); - goto new_trx_end; - } - - /* - * NOTICE This can not be use for mac80211, - * this is done in mac80211 code, - * if done here sec DHCP will fail - * skb_trim(skb, skb->len - 4); - */ - - hdr = rtl_get_hdr(skb); - fc = rtl_get_fc(skb); - - if (!stats.crc && !stats.hwerror) { - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, - sizeof(rx_status)); - - if (is_broadcast_ether_addr(hdr->addr1)) { - ;/*TODO*/ - } else if (is_multicast_ether_addr(hdr->addr1)) { - ;/*TODO*/ - } else { - unicast = true; - rtlpriv->stats.rxbytesunicast += skb->len; - } - rtl_is_special_data(hw, skb, false, true); - - if (ieee80211_is_data(fc)) { - rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); - if (unicast) - rtlpriv->link_info.num_rx_inperiod++; - } - /* static bcn for roaming */ - rtl_beacon_statistic(hw, skb); - rtl_p2p_info(hw, (void *)skb->data, skb->len); - /* for sw lps */ - rtl_swlps_beacon(hw, (void *)skb->data, skb->len); - rtl_recognize_peer(hw, (void *)skb->data, skb->len); - if ((rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) && - (rtlpriv->rtlhal.current_bandtype == - BAND_ON_2_4G) && - (ieee80211_is_beacon(fc) || - ieee80211_is_probe_resp(fc))) { - dev_kfree_skb_any(skb); - } else { - _rtl_pci_rx_to_mac80211(hw, skb, rx_status); - } - } else { - dev_kfree_skb_any(skb); - } -new_trx_end: - if (rtlpriv->use_new_trx_flow) { - rtlpci->rx_ring[hw_queue].next_rx_rp += 1; - rtlpci->rx_ring[hw_queue].next_rx_rp %= - RTL_PCI_MAX_RX_COUNT; - - rx_remained_cnt--; - rtl_write_word(rtlpriv, 0x3B4, - rtlpci->rx_ring[hw_queue].next_rx_rp); - } - if (((rtlpriv->link_info.num_rx_inperiod + - rtlpriv->link_info.num_tx_inperiod) > 8) || - (rtlpriv->link_info.num_rx_inperiod > 2)) { - rtlpriv->enter_ps = false; - schedule_work(&rtlpriv->works.lps_change_work); - } - skb = new_skb; -no_new: - if (rtlpriv->use_new_trx_flow) { - _rtl_pci_init_one_rxdesc(hw, skb, (u8 *)buffer_desc, - rxring_idx, - rtlpci->rx_ring[rxring_idx].idx); - } else { - _rtl_pci_init_one_rxdesc(hw, skb, (u8 *)pdesc, - rxring_idx, - rtlpci->rx_ring[rxring_idx].idx); - if (rtlpci->rx_ring[rxring_idx].idx == - rtlpci->rxringcount - 1) - rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, - false, - HW_DESC_RXERO, - (u8 *)&tmp_one); - } - rtlpci->rx_ring[rxring_idx].idx = - (rtlpci->rx_ring[rxring_idx].idx + 1) % - rtlpci->rxringcount; - } -} - -static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) -{ - struct ieee80211_hw *hw = dev_id; - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - unsigned long flags; - u32 inta = 0; - u32 intb = 0; - irqreturn_t ret = IRQ_HANDLED; - - if (rtlpci->irq_enabled == 0) - return ret; - - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock , flags); - rtlpriv->cfg->ops->disable_interrupt(hw); - - /*read ISR: 4/8bytes */ - rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb); - - /*Shared IRQ or HW disappared */ - if (!inta || inta == 0xffff) - goto done; - - /*<1> beacon related */ - if (inta & rtlpriv->cfg->maps[RTL_IMR_TBDOK]) { - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - "beacon ok interrupt!\n"); - } - - if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_TBDER])) { - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - "beacon err interrupt!\n"); - } - - if (inta & rtlpriv->cfg->maps[RTL_IMR_BDOK]) { - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, "beacon interrupt!\n"); - } - - if (inta & rtlpriv->cfg->maps[RTL_IMR_BCNINT]) { - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - "prepare beacon for interrupt!\n"); - tasklet_schedule(&rtlpriv->works.irq_prepare_bcn_tasklet); - } - - /*<2> Tx related */ - if (unlikely(intb & rtlpriv->cfg->maps[RTL_IMR_TXFOVW])) - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "IMR_TXFOVW!\n"); - - if (inta & rtlpriv->cfg->maps[RTL_IMR_MGNTDOK]) { - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - "Manage ok interrupt!\n"); - _rtl_pci_tx_isr(hw, MGNT_QUEUE); - } - - if (inta & rtlpriv->cfg->maps[RTL_IMR_HIGHDOK]) { - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - "HIGH_QUEUE ok interrupt!\n"); - _rtl_pci_tx_isr(hw, HIGH_QUEUE); - } - - if (inta & rtlpriv->cfg->maps[RTL_IMR_BKDOK]) { - rtlpriv->link_info.num_tx_inperiod++; - - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - "BK Tx OK interrupt!\n"); - _rtl_pci_tx_isr(hw, BK_QUEUE); - } - - if (inta & rtlpriv->cfg->maps[RTL_IMR_BEDOK]) { - rtlpriv->link_info.num_tx_inperiod++; - - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - "BE TX OK interrupt!\n"); - _rtl_pci_tx_isr(hw, BE_QUEUE); - } - - if (inta & rtlpriv->cfg->maps[RTL_IMR_VIDOK]) { - rtlpriv->link_info.num_tx_inperiod++; - - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - "VI TX OK interrupt!\n"); - _rtl_pci_tx_isr(hw, VI_QUEUE); - } - - if (inta & rtlpriv->cfg->maps[RTL_IMR_VODOK]) { - rtlpriv->link_info.num_tx_inperiod++; - - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - "Vo TX OK interrupt!\n"); - _rtl_pci_tx_isr(hw, VO_QUEUE); - } - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) { - if (inta & rtlpriv->cfg->maps[RTL_IMR_COMDOK]) { - rtlpriv->link_info.num_tx_inperiod++; - - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - "CMD TX OK interrupt!\n"); - _rtl_pci_tx_isr(hw, TXCMD_QUEUE); - } - } - - /*<3> Rx related */ - if (inta & rtlpriv->cfg->maps[RTL_IMR_ROK]) { - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, "Rx ok interrupt!\n"); - _rtl_pci_rx_interrupt(hw); - } - - if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_RDU])) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "rx descriptor unavailable!\n"); - _rtl_pci_rx_interrupt(hw); - } - - if (unlikely(intb & rtlpriv->cfg->maps[RTL_IMR_RXFOVW])) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "rx overflow !\n"); - _rtl_pci_rx_interrupt(hw); - } - - /*<4> fw related*/ - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723AE) { - if (inta & rtlpriv->cfg->maps[RTL_IMR_C2HCMD]) { - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - "firmware interrupt!\n"); - queue_delayed_work(rtlpriv->works.rtl_wq, - &rtlpriv->works.fwevt_wq, 0); - } - } - - /*<5> hsisr related*/ - /* Only 8188EE & 8723BE Supported. - * If Other ICs Come in, System will corrupt, - * because maps[RTL_IMR_HSISR_IND] & maps[MAC_HSISR] - * are not initialized - */ - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8188EE || - rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) { - if (unlikely(inta & rtlpriv->cfg->maps[RTL_IMR_HSISR_IND])) { - RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, - "hsisr interrupt!\n"); - _rtl_pci_hs_interrupt(hw); - } - } - - if (rtlpriv->rtlhal.earlymode_enable) - tasklet_schedule(&rtlpriv->works.irq_tasklet); - -done: - rtlpriv->cfg->ops->enable_interrupt(hw); - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - return ret; -} - -static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw) -{ - _rtl_pci_tx_chk_waitq(hw); -} - -static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl8192_tx_ring *ring = NULL; - struct ieee80211_hdr *hdr = NULL; - struct ieee80211_tx_info *info = NULL; - struct sk_buff *pskb = NULL; - struct rtl_tx_desc *pdesc = NULL; - struct rtl_tcb_desc tcb_desc; - /*This is for new trx flow*/ - struct rtl_tx_buffer_desc *pbuffer_desc = NULL; - u8 temp_one = 1; - u8 *entry; - - memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); - ring = &rtlpci->tx_ring[BEACON_QUEUE]; - pskb = __skb_dequeue(&ring->queue); - if (rtlpriv->use_new_trx_flow) - entry = (u8 *)(&ring->buffer_desc[ring->idx]); - else - entry = (u8 *)(&ring->desc[ring->idx]); - if (pskb) { - pci_unmap_single(rtlpci->pdev, - rtlpriv->cfg->ops->get_desc( - (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), - pskb->len, PCI_DMA_TODEVICE); - kfree_skb(pskb); - } - - /*NB: the beacon data buffer must be 32-bit aligned. */ - pskb = ieee80211_beacon_get(hw, mac->vif); - if (pskb == NULL) - return; - hdr = rtl_get_hdr(pskb); - info = IEEE80211_SKB_CB(pskb); - pdesc = &ring->desc[0]; - if (rtlpriv->use_new_trx_flow) - pbuffer_desc = &ring->buffer_desc[0]; - - rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, - (u8 *)pbuffer_desc, info, NULL, pskb, - BEACON_QUEUE, &tcb_desc); - - __skb_queue_tail(&ring->queue, pskb); - - if (rtlpriv->use_new_trx_flow) { - temp_one = 4; - rtlpriv->cfg->ops->set_desc(hw, (u8 *)pbuffer_desc, true, - HW_DESC_OWN, (u8 *)&temp_one); - } else { - rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN, - &temp_one); - } - return; -} - -static void _rtl_pci_init_trx_var(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 i; - u16 desc_num; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) - desc_num = TX_DESC_NUM_92E; - else - desc_num = RT_TXDESC_NUM; - - for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) - rtlpci->txringcount[i] = desc_num; - - /* - *we just alloc 2 desc for beacon queue, - *because we just need first desc in hw beacon. - */ - rtlpci->txringcount[BEACON_QUEUE] = 2; - - /*BE queue need more descriptor for performance - *consideration or, No more tx desc will happen, - *and may cause mac80211 mem leakage. - */ - if (!rtl_priv(hw)->use_new_trx_flow) - rtlpci->txringcount[BE_QUEUE] = RT_TXDESC_NUM_BE_QUEUE; - - rtlpci->rxbuffersize = 9100; /*2048/1024; */ - rtlpci->rxringcount = RTL_PCI_MAX_RX_COUNT; /*64; */ -} - -static void _rtl_pci_init_struct(struct ieee80211_hw *hw, - struct pci_dev *pdev) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - rtlpci->up_first_time = true; - rtlpci->being_init_adapter = false; - - rtlhal->hw = hw; - rtlpci->pdev = pdev; - - /*Tx/Rx related var */ - _rtl_pci_init_trx_var(hw); - - /*IBSS*/ mac->beacon_interval = 100; - - /*AMPDU*/ - mac->min_space_cfg = 0; - mac->max_mss_density = 0; - /*set sane AMPDU defaults */ - mac->current_ampdu_density = 7; - mac->current_ampdu_factor = 3; - - /*QOS*/ - rtlpci->acm_method = EACMWAY2_SW; - - /*task */ - tasklet_init(&rtlpriv->works.irq_tasklet, - (void (*)(unsigned long))_rtl_pci_irq_tasklet, - (unsigned long)hw); - tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet, - (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet, - (unsigned long)hw); - INIT_WORK(&rtlpriv->works.lps_change_work, - rtl_lps_change_work_callback); -} - -static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, - unsigned int prio, unsigned int entries) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_tx_buffer_desc *buffer_desc; - struct rtl_tx_desc *desc; - dma_addr_t buffer_desc_dma, desc_dma; - u32 nextdescaddress; - int i; - - /* alloc tx buffer desc for new trx flow*/ - if (rtlpriv->use_new_trx_flow) { - buffer_desc = - pci_zalloc_consistent(rtlpci->pdev, - sizeof(*buffer_desc) * entries, - &buffer_desc_dma); - - if (!buffer_desc || (unsigned long)buffer_desc & 0xFF) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Cannot allocate TX ring (prio = %d)\n", - prio); - return -ENOMEM; - } - - rtlpci->tx_ring[prio].buffer_desc = buffer_desc; - rtlpci->tx_ring[prio].buffer_desc_dma = buffer_desc_dma; - - rtlpci->tx_ring[prio].cur_tx_rp = 0; - rtlpci->tx_ring[prio].cur_tx_wp = 0; - rtlpci->tx_ring[prio].avl_desc = entries; - } - - /* alloc dma for this ring */ - desc = pci_zalloc_consistent(rtlpci->pdev, - sizeof(*desc) * entries, &desc_dma); - - if (!desc || (unsigned long)desc & 0xFF) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Cannot allocate TX ring (prio = %d)\n", prio); - return -ENOMEM; - } - - rtlpci->tx_ring[prio].desc = desc; - rtlpci->tx_ring[prio].dma = desc_dma; - - rtlpci->tx_ring[prio].idx = 0; - rtlpci->tx_ring[prio].entries = entries; - skb_queue_head_init(&rtlpci->tx_ring[prio].queue); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "queue:%d, ring_addr:%p\n", - prio, desc); - - /* init every desc in this ring */ - if (!rtlpriv->use_new_trx_flow) { - for (i = 0; i < entries; i++) { - nextdescaddress = (u32)desc_dma + - ((i + 1) % entries) * - sizeof(*desc); - - rtlpriv->cfg->ops->set_desc(hw, (u8 *)&desc[i], - true, - HW_DESC_TX_NEXTDESC_ADDR, - (u8 *)&nextdescaddress); - } - } - return 0; -} - -static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw, int rxring_idx) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - int i; - - if (rtlpriv->use_new_trx_flow) { - struct rtl_rx_buffer_desc *entry = NULL; - /* alloc dma for this ring */ - rtlpci->rx_ring[rxring_idx].buffer_desc = - pci_zalloc_consistent(rtlpci->pdev, - sizeof(*rtlpci->rx_ring[rxring_idx]. - buffer_desc) * - rtlpci->rxringcount, - &rtlpci->rx_ring[rxring_idx].dma); - if (!rtlpci->rx_ring[rxring_idx].buffer_desc || - (ulong)rtlpci->rx_ring[rxring_idx].buffer_desc & 0xFF) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Cannot allocate RX ring\n"); - return -ENOMEM; - } - - /* init every desc in this ring */ - rtlpci->rx_ring[rxring_idx].idx = 0; - for (i = 0; i < rtlpci->rxringcount; i++) { - entry = &rtlpci->rx_ring[rxring_idx].buffer_desc[i]; - if (!_rtl_pci_init_one_rxdesc(hw, NULL, (u8 *)entry, - rxring_idx, i)) - return -ENOMEM; - } - } else { - struct rtl_rx_desc *entry = NULL; - u8 tmp_one = 1; - /* alloc dma for this ring */ - rtlpci->rx_ring[rxring_idx].desc = - pci_zalloc_consistent(rtlpci->pdev, - sizeof(*rtlpci->rx_ring[rxring_idx]. - desc) * rtlpci->rxringcount, - &rtlpci->rx_ring[rxring_idx].dma); - if (!rtlpci->rx_ring[rxring_idx].desc || - (unsigned long)rtlpci->rx_ring[rxring_idx].desc & 0xFF) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Cannot allocate RX ring\n"); - return -ENOMEM; - } - - /* init every desc in this ring */ - rtlpci->rx_ring[rxring_idx].idx = 0; - - for (i = 0; i < rtlpci->rxringcount; i++) { - entry = &rtlpci->rx_ring[rxring_idx].desc[i]; - if (!_rtl_pci_init_one_rxdesc(hw, NULL, (u8 *)entry, - rxring_idx, i)) - return -ENOMEM; - } - - rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false, - HW_DESC_RXERO, &tmp_one); - } - return 0; -} - -static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw, - unsigned int prio) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[prio]; - - /* free every desc in this ring */ - while (skb_queue_len(&ring->queue)) { - u8 *entry; - struct sk_buff *skb = __skb_dequeue(&ring->queue); - - if (rtlpriv->use_new_trx_flow) - entry = (u8 *)(&ring->buffer_desc[ring->idx]); - else - entry = (u8 *)(&ring->desc[ring->idx]); - - pci_unmap_single(rtlpci->pdev, - rtlpriv->cfg-> - ops->get_desc((u8 *)entry, true, - HW_DESC_TXBUFF_ADDR), - skb->len, PCI_DMA_TODEVICE); - kfree_skb(skb); - ring->idx = (ring->idx + 1) % ring->entries; - } - - /* free dma of this ring */ - pci_free_consistent(rtlpci->pdev, - sizeof(*ring->desc) * ring->entries, - ring->desc, ring->dma); - ring->desc = NULL; - if (rtlpriv->use_new_trx_flow) { - pci_free_consistent(rtlpci->pdev, - sizeof(*ring->buffer_desc) * ring->entries, - ring->buffer_desc, ring->buffer_desc_dma); - ring->buffer_desc = NULL; - } -} - -static void _rtl_pci_free_rx_ring(struct ieee80211_hw *hw, int rxring_idx) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - int i; - - /* free every desc in this ring */ - for (i = 0; i < rtlpci->rxringcount; i++) { - struct sk_buff *skb = rtlpci->rx_ring[rxring_idx].rx_buf[i]; - - if (!skb) - continue; - pci_unmap_single(rtlpci->pdev, *((dma_addr_t *)skb->cb), - rtlpci->rxbuffersize, PCI_DMA_FROMDEVICE); - kfree_skb(skb); - } - - /* free dma of this ring */ - if (rtlpriv->use_new_trx_flow) { - pci_free_consistent(rtlpci->pdev, - sizeof(*rtlpci->rx_ring[rxring_idx]. - buffer_desc) * rtlpci->rxringcount, - rtlpci->rx_ring[rxring_idx].buffer_desc, - rtlpci->rx_ring[rxring_idx].dma); - rtlpci->rx_ring[rxring_idx].buffer_desc = NULL; - } else { - pci_free_consistent(rtlpci->pdev, - sizeof(*rtlpci->rx_ring[rxring_idx].desc) * - rtlpci->rxringcount, - rtlpci->rx_ring[rxring_idx].desc, - rtlpci->rx_ring[rxring_idx].dma); - rtlpci->rx_ring[rxring_idx].desc = NULL; - } -} - -static int _rtl_pci_init_trx_ring(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - int ret; - int i, rxring_idx; - - /* rxring_idx 0:RX_MPDU_QUEUE - * rxring_idx 1:RX_CMD_QUEUE - */ - for (rxring_idx = 0; rxring_idx < RTL_PCI_MAX_RX_QUEUE; rxring_idx++) { - ret = _rtl_pci_init_rx_ring(hw, rxring_idx); - if (ret) - return ret; - } - - for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) { - ret = _rtl_pci_init_tx_ring(hw, i, - rtlpci->txringcount[i]); - if (ret) - goto err_free_rings; - } - - return 0; - -err_free_rings: - for (rxring_idx = 0; rxring_idx < RTL_PCI_MAX_RX_QUEUE; rxring_idx++) - _rtl_pci_free_rx_ring(hw, rxring_idx); - - for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) - if (rtlpci->tx_ring[i].desc || - rtlpci->tx_ring[i].buffer_desc) - _rtl_pci_free_tx_ring(hw, i); - - return 1; -} - -static int _rtl_pci_deinit_trx_ring(struct ieee80211_hw *hw) -{ - u32 i, rxring_idx; - - /*free rx rings */ - for (rxring_idx = 0; rxring_idx < RTL_PCI_MAX_RX_QUEUE; rxring_idx++) - _rtl_pci_free_rx_ring(hw, rxring_idx); - - /*free tx rings */ - for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) - _rtl_pci_free_tx_ring(hw, i); - - return 0; -} - -int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - int i, rxring_idx; - unsigned long flags; - u8 tmp_one = 1; - u32 bufferaddress; - /* rxring_idx 0:RX_MPDU_QUEUE */ - /* rxring_idx 1:RX_CMD_QUEUE */ - for (rxring_idx = 0; rxring_idx < RTL_PCI_MAX_RX_QUEUE; rxring_idx++) { - /* force the rx_ring[RX_MPDU_QUEUE/ - * RX_CMD_QUEUE].idx to the first one - *new trx flow, do nothing - */ - if (!rtlpriv->use_new_trx_flow && - rtlpci->rx_ring[rxring_idx].desc) { - struct rtl_rx_desc *entry = NULL; - - rtlpci->rx_ring[rxring_idx].idx = 0; - for (i = 0; i < rtlpci->rxringcount; i++) { - entry = &rtlpci->rx_ring[rxring_idx].desc[i]; - bufferaddress = - rtlpriv->cfg->ops->get_desc((u8 *)entry, - false , HW_DESC_RXBUFF_ADDR); - memset((u8 *)entry , 0 , - sizeof(*rtlpci->rx_ring - [rxring_idx].desc));/*clear one entry*/ - if (rtlpriv->use_new_trx_flow) { - rtlpriv->cfg->ops->set_desc(hw, - (u8 *)entry, false, - HW_DESC_RX_PREPARE, - (u8 *)&bufferaddress); - } else { - rtlpriv->cfg->ops->set_desc(hw, - (u8 *)entry, false, - HW_DESC_RXBUFF_ADDR, - (u8 *)&bufferaddress); - rtlpriv->cfg->ops->set_desc(hw, - (u8 *)entry, false, - HW_DESC_RXPKT_LEN, - (u8 *)&rtlpci->rxbuffersize); - rtlpriv->cfg->ops->set_desc(hw, - (u8 *)entry, false, - HW_DESC_RXOWN, - (u8 *)&tmp_one); - } - } - rtlpriv->cfg->ops->set_desc(hw, (u8 *)entry, false, - HW_DESC_RXERO, (u8 *)&tmp_one); - } - rtlpci->rx_ring[rxring_idx].idx = 0; - } - - /* - *after reset, release previous pending packet, - *and force the tx idx to the first one - */ - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - for (i = 0; i < RTL_PCI_MAX_TX_QUEUE_COUNT; i++) { - if (rtlpci->tx_ring[i].desc || - rtlpci->tx_ring[i].buffer_desc) { - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[i]; - - while (skb_queue_len(&ring->queue)) { - u8 *entry; - struct sk_buff *skb = - __skb_dequeue(&ring->queue); - if (rtlpriv->use_new_trx_flow) - entry = (u8 *)(&ring->buffer_desc - [ring->idx]); - else - entry = (u8 *)(&ring->desc[ring->idx]); - - pci_unmap_single(rtlpci->pdev, - rtlpriv->cfg->ops-> - get_desc((u8 *) - entry, - true, - HW_DESC_TXBUFF_ADDR), - skb->len, PCI_DMA_TODEVICE); - kfree_skb(skb); - ring->idx = (ring->idx + 1) % ring->entries; - } - ring->idx = 0; - } - } - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - - return 0; -} - -static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_sta_info *sta_entry = NULL; - u8 tid = rtl_get_tid(skb); - __le16 fc = rtl_get_fc(skb); - - if (!sta) - return false; - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - - if (!rtlpriv->rtlhal.earlymode_enable) - return false; - if (ieee80211_is_nullfunc(fc)) - return false; - if (ieee80211_is_qos_nullfunc(fc)) - return false; - if (ieee80211_is_pspoll(fc)) - return false; - if (sta_entry->tids[tid].agg.agg_state != RTL_AGG_OPERATIONAL) - return false; - if (_rtl_mac_to_hwqueue(hw, skb) > VO_QUEUE) - return false; - if (tid > 7) - return false; - - /* maybe every tid should be checked */ - if (!rtlpriv->link_info.higher_busytxtraffic[tid]) - return false; - - spin_lock_bh(&rtlpriv->locks.waitq_lock); - skb_queue_tail(&rtlpriv->mac80211.skb_waitq[tid], skb); - spin_unlock_bh(&rtlpriv->locks.waitq_lock); - - return true; -} - -static int rtl_pci_tx(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - struct sk_buff *skb, - struct rtl_tcb_desc *ptcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_sta_info *sta_entry = NULL; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct rtl8192_tx_ring *ring; - struct rtl_tx_desc *pdesc; - struct rtl_tx_buffer_desc *ptx_bd_desc = NULL; - u16 idx; - u8 hw_queue = _rtl_mac_to_hwqueue(hw, skb); - unsigned long flags; - struct ieee80211_hdr *hdr = rtl_get_hdr(skb); - __le16 fc = rtl_get_fc(skb); - u8 *pda_addr = hdr->addr1; - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - /*ssn */ - u8 tid = 0; - u16 seq_number = 0; - u8 own; - u8 temp_one = 1; - - if (ieee80211_is_mgmt(fc)) - rtl_tx_mgmt_proc(hw, skb); - - if (rtlpriv->psc.sw_ps_enabled) { - if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && - !ieee80211_has_pm(fc)) - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - } - - rtl_action_proc(hw, skb, true); - - if (is_multicast_ether_addr(pda_addr)) - rtlpriv->stats.txbytesmulticast += skb->len; - else if (is_broadcast_ether_addr(pda_addr)) - rtlpriv->stats.txbytesbroadcast += skb->len; - else - rtlpriv->stats.txbytesunicast += skb->len; - - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - ring = &rtlpci->tx_ring[hw_queue]; - if (hw_queue != BEACON_QUEUE) { - if (rtlpriv->use_new_trx_flow) - idx = ring->cur_tx_wp; - else - idx = (ring->idx + skb_queue_len(&ring->queue)) % - ring->entries; - } else { - idx = 0; - } - - pdesc = &ring->desc[idx]; - if (rtlpriv->use_new_trx_flow) { - ptx_bd_desc = &ring->buffer_desc[idx]; - } else { - own = (u8) rtlpriv->cfg->ops->get_desc((u8 *)pdesc, - true, HW_DESC_OWN); - - if ((own == 1) && (hw_queue != BEACON_QUEUE)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "No more TX desc@%d, ring->idx = %d, idx = %d, skb_queue_len = 0x%x\n", - hw_queue, ring->idx, idx, - skb_queue_len(&ring->queue)); - - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, - flags); - return skb->len; - } - } - - if (rtlpriv->cfg->ops->get_available_desc && - rtlpriv->cfg->ops->get_available_desc(hw, hw_queue) == 0) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "get_available_desc fail\n"); - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, - flags); - return skb->len; - } - - if (ieee80211_is_data_qos(fc)) { - tid = rtl_get_tid(skb); - if (sta) { - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - seq_number = (le16_to_cpu(hdr->seq_ctrl) & - IEEE80211_SCTL_SEQ) >> 4; - seq_number += 1; - - if (!ieee80211_has_morefrags(hdr->frame_control)) - sta_entry->tids[tid].seq_number = seq_number; - } - } - - if (ieee80211_is_data(fc)) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); - - rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, - (u8 *)ptx_bd_desc, info, sta, skb, hw_queue, ptcb_desc); - - __skb_queue_tail(&ring->queue, skb); - - if (rtlpriv->use_new_trx_flow) { - rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, - HW_DESC_OWN, &hw_queue); - } else { - rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, - HW_DESC_OWN, &temp_one); - } - - if ((ring->entries - skb_queue_len(&ring->queue)) < 2 && - hw_queue != BEACON_QUEUE) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "less desc left, stop skb_queue@%d, ring->idx = %d, idx = %d, skb_queue_len = 0x%x\n", - hw_queue, ring->idx, idx, - skb_queue_len(&ring->queue)); - - ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); - } - - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - - rtlpriv->cfg->ops->tx_polling(hw, hw_queue); - - return 0; -} - -static void rtl_pci_flush(struct ieee80211_hw *hw, u32 queues, bool drop) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 i = 0; - int queue_id; - struct rtl8192_tx_ring *ring; - - if (mac->skip_scan) - return; - - for (queue_id = RTL_PCI_MAX_TX_QUEUE_COUNT - 1; queue_id >= 0;) { - u32 queue_len; - - if (((queues >> queue_id) & 0x1) == 0) { - queue_id--; - continue; - } - ring = &pcipriv->dev.tx_ring[queue_id]; - queue_len = skb_queue_len(&ring->queue); - if (queue_len == 0 || queue_id == BEACON_QUEUE || - queue_id == TXCMD_QUEUE) { - queue_id--; - continue; - } else { - msleep(20); - i++; - } - - /* we just wait 1s for all queues */ - if (rtlpriv->psc.rfpwr_state == ERFOFF || - is_hal_stop(rtlhal) || i >= 200) - return; - } -} - -static void rtl_pci_deinit(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - _rtl_pci_deinit_trx_ring(hw); - - synchronize_irq(rtlpci->pdev->irq); - tasklet_kill(&rtlpriv->works.irq_tasklet); - cancel_work_sync(&rtlpriv->works.lps_change_work); - - flush_workqueue(rtlpriv->works.rtl_wq); - destroy_workqueue(rtlpriv->works.rtl_wq); - -} - -static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int err; - - _rtl_pci_init_struct(hw, pdev); - - err = _rtl_pci_init_trx_ring(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "tx ring initialization failed\n"); - return err; - } - - return 0; -} - -static int rtl_pci_start(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - int err; - - rtl_pci_reset_trx_ring(hw); - - rtlpci->driver_is_goingto_unload = false; - if (rtlpriv->cfg->ops->get_btc_status && - rtlpriv->cfg->ops->get_btc_status()) { - rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv); - rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv); - } - err = rtlpriv->cfg->ops->hw_init(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Failed to config hardware!\n"); - return err; - } - - rtlpriv->cfg->ops->enable_interrupt(hw); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "enable_interrupt OK\n"); - - rtl_init_rx_config(hw); - - /*should be after adapter start and interrupt enable. */ - set_hal_start(rtlhal); - - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - - rtlpci->up_first_time = false; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "rtl_pci_start OK\n"); - return 0; -} - -static void rtl_pci_stop(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - unsigned long flags; - u8 RFInProgressTimeOut = 0; - - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_halt_notify(); - - /* - *should be before disable interrupt&adapter - *and will do it immediately. - */ - set_hal_stop(rtlhal); - - rtlpci->driver_is_goingto_unload = true; - rtlpriv->cfg->ops->disable_interrupt(hw); - cancel_work_sync(&rtlpriv->works.lps_change_work); - - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); - while (ppsc->rfchange_inprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); - if (RFInProgressTimeOut > 100) { - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); - break; - } - mdelay(1); - RFInProgressTimeOut++; - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); - } - ppsc->rfchange_inprogress = true; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); - - rtlpriv->cfg->ops->hw_disable(hw); - /* some things are not needed if firmware not available */ - if (!rtlpriv->max_fw_size) - return; - rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); - - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); - - rtl_pci_enable_aspm(hw); -} - -static bool _rtl_pci_find_adapter(struct pci_dev *pdev, - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct pci_dev *bridge_pdev = pdev->bus->self; - u16 venderid; - u16 deviceid; - u8 revisionid; - u16 irqline; - u8 tmp; - - pcipriv->ndis_adapter.pcibridge_vendor = PCI_BRIDGE_VENDOR_UNKNOWN; - venderid = pdev->vendor; - deviceid = pdev->device; - pci_read_config_byte(pdev, 0x8, &revisionid); - pci_read_config_word(pdev, 0x3C, &irqline); - - /* PCI ID 0x10ec:0x8192 occurs for both RTL8192E, which uses - * r8192e_pci, and RTL8192SE, which uses this driver. If the - * revision ID is RTL_PCI_REVISION_ID_8192PCIE (0x01), then - * the correct driver is r8192e_pci, thus this routine should - * return false. - */ - if (deviceid == RTL_PCI_8192SE_DID && - revisionid == RTL_PCI_REVISION_ID_8192PCIE) - return false; - - if (deviceid == RTL_PCI_8192_DID || - deviceid == RTL_PCI_0044_DID || - deviceid == RTL_PCI_0047_DID || - deviceid == RTL_PCI_8192SE_DID || - deviceid == RTL_PCI_8174_DID || - deviceid == RTL_PCI_8173_DID || - deviceid == RTL_PCI_8172_DID || - deviceid == RTL_PCI_8171_DID) { - switch (revisionid) { - case RTL_PCI_REVISION_ID_8192PCIE: - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "8192 PCI-E is found - vid/did=%x/%x\n", - venderid, deviceid); - rtlhal->hw_type = HARDWARE_TYPE_RTL8192E; - return false; - case RTL_PCI_REVISION_ID_8192SE: - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "8192SE is found - vid/did=%x/%x\n", - venderid, deviceid); - rtlhal->hw_type = HARDWARE_TYPE_RTL8192SE; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Err: Unknown device - vid/did=%x/%x\n", - venderid, deviceid); - rtlhal->hw_type = HARDWARE_TYPE_RTL8192SE; - break; - - } - } else if (deviceid == RTL_PCI_8723AE_DID) { - rtlhal->hw_type = HARDWARE_TYPE_RTL8723AE; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "8723AE PCI-E is found - " - "vid/did=%x/%x\n", venderid, deviceid); - } else if (deviceid == RTL_PCI_8192CET_DID || - deviceid == RTL_PCI_8192CE_DID || - deviceid == RTL_PCI_8191CE_DID || - deviceid == RTL_PCI_8188CE_DID) { - rtlhal->hw_type = HARDWARE_TYPE_RTL8192CE; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "8192C PCI-E is found - vid/did=%x/%x\n", - venderid, deviceid); - } else if (deviceid == RTL_PCI_8192DE_DID || - deviceid == RTL_PCI_8192DE_DID2) { - rtlhal->hw_type = HARDWARE_TYPE_RTL8192DE; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "8192D PCI-E is found - vid/did=%x/%x\n", - venderid, deviceid); - } else if (deviceid == RTL_PCI_8188EE_DID) { - rtlhal->hw_type = HARDWARE_TYPE_RTL8188EE; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Find adapter, Hardware type is 8188EE\n"); - } else if (deviceid == RTL_PCI_8723BE_DID) { - rtlhal->hw_type = HARDWARE_TYPE_RTL8723BE; - RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD, - "Find adapter, Hardware type is 8723BE\n"); - } else if (deviceid == RTL_PCI_8192EE_DID) { - rtlhal->hw_type = HARDWARE_TYPE_RTL8192EE; - RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD, - "Find adapter, Hardware type is 8192EE\n"); - } else if (deviceid == RTL_PCI_8821AE_DID) { - rtlhal->hw_type = HARDWARE_TYPE_RTL8821AE; - RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD, - "Find adapter, Hardware type is 8821AE\n"); - } else if (deviceid == RTL_PCI_8812AE_DID) { - rtlhal->hw_type = HARDWARE_TYPE_RTL8812AE; - RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD, - "Find adapter, Hardware type is 8812AE\n"); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Err: Unknown device - vid/did=%x/%x\n", - venderid, deviceid); - - rtlhal->hw_type = RTL_DEFAULT_HARDWARE_TYPE; - } - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) { - if (revisionid == 0 || revisionid == 1) { - if (revisionid == 0) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Find 92DE MAC0\n"); - rtlhal->interfaceindex = 0; - } else if (revisionid == 1) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Find 92DE MAC1\n"); - rtlhal->interfaceindex = 1; - } - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Unknown device - VendorID/DeviceID=%x/%x, Revision=%x\n", - venderid, deviceid, revisionid); - rtlhal->interfaceindex = 0; - } - } - - /* 92ee use new trx flow */ - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192EE) - rtlpriv->use_new_trx_flow = true; - else - rtlpriv->use_new_trx_flow = false; - - /*find bus info */ - pcipriv->ndis_adapter.busnumber = pdev->bus->number; - pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn); - pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn); - - /*find bridge info */ - pcipriv->ndis_adapter.pcibridge_vendor = PCI_BRIDGE_VENDOR_UNKNOWN; - /* some ARM have no bridge_pdev and will crash here - * so we should check if bridge_pdev is NULL - */ - if (bridge_pdev) { - /*find bridge info if available */ - pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor; - for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) { - if (bridge_pdev->vendor == pcibridge_vendors[tmp]) { - pcipriv->ndis_adapter.pcibridge_vendor = tmp; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Pci Bridge Vendor is found index: %d\n", - tmp); - break; - } - } - } - - if (pcipriv->ndis_adapter.pcibridge_vendor != - PCI_BRIDGE_VENDOR_UNKNOWN) { - pcipriv->ndis_adapter.pcibridge_busnum = - bridge_pdev->bus->number; - pcipriv->ndis_adapter.pcibridge_devnum = - PCI_SLOT(bridge_pdev->devfn); - pcipriv->ndis_adapter.pcibridge_funcnum = - PCI_FUNC(bridge_pdev->devfn); - pcipriv->ndis_adapter.pcibridge_pciehdr_offset = - pci_pcie_cap(bridge_pdev); - pcipriv->ndis_adapter.num4bytes = - (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10) / 4; - - rtl_pci_get_linkcontrol_field(hw); - - if (pcipriv->ndis_adapter.pcibridge_vendor == - PCI_BRIDGE_VENDOR_AMD) { - pcipriv->ndis_adapter.amd_l1_patch = - rtl_pci_get_amd_l1_patch(hw); - } - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "pcidev busnumber:devnumber:funcnumber:vendor:link_ctl %d:%d:%d:%x:%x\n", - pcipriv->ndis_adapter.busnumber, - pcipriv->ndis_adapter.devnumber, - pcipriv->ndis_adapter.funcnumber, - pdev->vendor, pcipriv->ndis_adapter.linkctrl_reg); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "pci_bridge busnumber:devnumber:funcnumber:vendor:pcie_cap:link_ctl_reg:amd %d:%d:%d:%x:%x:%x:%x\n", - pcipriv->ndis_adapter.pcibridge_busnum, - pcipriv->ndis_adapter.pcibridge_devnum, - pcipriv->ndis_adapter.pcibridge_funcnum, - pcibridge_vendors[pcipriv->ndis_adapter.pcibridge_vendor], - pcipriv->ndis_adapter.pcibridge_pciehdr_offset, - pcipriv->ndis_adapter.pcibridge_linkctrlreg, - pcipriv->ndis_adapter.amd_l1_patch); - - rtl_pci_parse_configuration(pdev, hw); - list_add_tail(&rtlpriv->list, &rtlpriv->glb_var->glb_priv_list); - - return true; -} - -static int rtl_pci_intr_mode_msi(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); - int ret; - - ret = pci_enable_msi(rtlpci->pdev); - if (ret < 0) - return ret; - - ret = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt, - IRQF_SHARED, KBUILD_MODNAME, hw); - if (ret < 0) { - pci_disable_msi(rtlpci->pdev); - return ret; - } - - rtlpci->using_msi = true; - - RT_TRACE(rtlpriv, COMP_INIT|COMP_INTR, DBG_DMESG, - "MSI Interrupt Mode!\n"); - return 0; -} - -static int rtl_pci_intr_mode_legacy(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); - int ret; - - ret = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt, - IRQF_SHARED, KBUILD_MODNAME, hw); - if (ret < 0) - return ret; - - rtlpci->using_msi = false; - RT_TRACE(rtlpriv, COMP_INIT|COMP_INTR, DBG_DMESG, - "Pin-based Interrupt Mode!\n"); - return 0; -} - -static int rtl_pci_intr_mode_decide(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); - int ret; - - if (rtlpci->msi_support) { - ret = rtl_pci_intr_mode_msi(hw); - if (ret < 0) - ret = rtl_pci_intr_mode_legacy(hw); - } else { - ret = rtl_pci_intr_mode_legacy(hw); - } - return ret; -} - -int rtl_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - struct ieee80211_hw *hw = NULL; - - struct rtl_priv *rtlpriv = NULL; - struct rtl_pci_priv *pcipriv = NULL; - struct rtl_pci *rtlpci; - unsigned long pmem_start, pmem_len, pmem_flags; - int err; - - err = pci_enable_device(pdev); - if (err) { - RT_ASSERT(false, "%s : Cannot enable new PCI device\n", - pci_name(pdev)); - return err; - } - - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { - RT_ASSERT(false, - "Unable to obtain 32bit DMA for consistent allocations\n"); - err = -ENOMEM; - goto fail1; - } - } - - pci_set_master(pdev); - - hw = ieee80211_alloc_hw(sizeof(struct rtl_pci_priv) + - sizeof(struct rtl_priv), &rtl_ops); - if (!hw) { - RT_ASSERT(false, - "%s : ieee80211 alloc failed\n", pci_name(pdev)); - err = -ENOMEM; - goto fail1; - } - - SET_IEEE80211_DEV(hw, &pdev->dev); - pci_set_drvdata(pdev, hw); - - rtlpriv = hw->priv; - rtlpriv->hw = hw; - pcipriv = (void *)rtlpriv->priv; - pcipriv->dev.pdev = pdev; - init_completion(&rtlpriv->firmware_loading_complete); - /*proximity init here*/ - rtlpriv->proximity.proxim_on = false; - - pcipriv = (void *)rtlpriv->priv; - pcipriv->dev.pdev = pdev; - - /* init cfg & intf_ops */ - rtlpriv->rtlhal.interface = INTF_PCI; - rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data); - 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) { - RT_ASSERT(false, "Can't obtain PCI resources\n"); - goto fail1; - } - - pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); - pmem_len = pci_resource_len(pdev, rtlpriv->cfg->bar_id); - pmem_flags = pci_resource_flags(pdev, rtlpriv->cfg->bar_id); - - /*shared mem start */ - rtlpriv->io.pci_mem_start = - (unsigned long)pci_iomap(pdev, - rtlpriv->cfg->bar_id, pmem_len); - if (rtlpriv->io.pci_mem_start == 0) { - RT_ASSERT(false, "Can't map PCI mem\n"); - err = -ENOMEM; - goto fail2; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "mem mapped space: start: 0x%08lx len:%08lx flags:%08lx, after map:0x%08lx\n", - pmem_start, pmem_len, pmem_flags, - rtlpriv->io.pci_mem_start); - - /* Disable Clk Request */ - pci_write_config_byte(pdev, 0x81, 0); - /* leave D3 mode */ - pci_write_config_byte(pdev, 0x44, 0); - pci_write_config_byte(pdev, 0x04, 0x06); - pci_write_config_byte(pdev, 0x04, 0x07); - - /* find adapter */ - if (!_rtl_pci_find_adapter(pdev, hw)) { - err = -ENODEV; - goto fail3; - } - - /* Init IO handler */ - _rtl_pci_io_handler_init(&pdev->dev, hw); - - /*like read eeprom and so on */ - rtlpriv->cfg->ops->read_eeprom_info(hw); - - if (rtlpriv->cfg->ops->init_sw_vars(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n"); - err = -ENODEV; - goto fail3; - } - rtlpriv->cfg->ops->init_sw_leds(hw); - - /*aspm */ - rtl_pci_init_aspm(hw); - - /* Init mac80211 sw */ - err = rtl_init_core(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't allocate sw for mac80211\n"); - goto fail3; - } - - /* Init PCI sw */ - err = rtl_pci_init(hw, pdev); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Failed to init PCI\n"); - goto fail3; - } - - err = ieee80211_register_hw(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't register mac80211 hw.\n"); - err = -ENODEV; - goto fail3; - } - rtlpriv->mac80211.mac80211_registered = 1; - - err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "failed to create sysfs device attributes\n"); - goto fail3; - } - - /*init rfkill */ - rtl_init_rfkill(hw); /* Init PCI sw */ - - rtlpci = rtl_pcidev(pcipriv); - err = rtl_pci_intr_mode_decide(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "%s: failed to register IRQ handler\n", - wiphy_name(hw->wiphy)); - goto fail3; - } - rtlpci->irq_alloc = 1; - - set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); - return 0; - -fail3: - pci_set_drvdata(pdev, NULL); - rtl_deinit_core(hw); - - if (rtlpriv->io.pci_mem_start != 0) - pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); - -fail2: - pci_release_regions(pdev); - complete(&rtlpriv->firmware_loading_complete); - -fail1: - if (hw) - ieee80211_free_hw(hw); - pci_disable_device(pdev); - - return err; - -} -EXPORT_SYMBOL(rtl_pci_probe); - -void rtl_pci_disconnect(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); - struct rtl_mac *rtlmac = rtl_mac(rtlpriv); - - /* just in case driver is removed before firmware callback */ - 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); - rtlmac->mac80211_registered = 0; - } else { - rtl_deinit_deferred_work(hw); - rtlpriv->intf_ops->adapter_stop(hw); - } - rtlpriv->cfg->ops->disable_interrupt(hw); - - /*deinit rfkill */ - rtl_deinit_rfkill(hw); - - rtl_pci_deinit(hw); - rtl_deinit_core(hw); - rtlpriv->cfg->ops->deinit_sw_vars(hw); - - if (rtlpci->irq_alloc) { - synchronize_irq(rtlpci->pdev->irq); - free_irq(rtlpci->pdev->irq, hw); - rtlpci->irq_alloc = 0; - } - - if (rtlpci->using_msi) - pci_disable_msi(rtlpci->pdev); - - list_del(&rtlpriv->list); - if (rtlpriv->io.pci_mem_start != 0) { - pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); - pci_release_regions(pdev); - } - - pci_disable_device(pdev); - - rtl_pci_disable_aspm(hw); - - pci_set_drvdata(pdev, NULL); - - ieee80211_free_hw(hw); -} -EXPORT_SYMBOL(rtl_pci_disconnect); - -#ifdef CONFIG_PM_SLEEP -/*************************************** -kernel pci power state define: -PCI_D0 ((pci_power_t __force) 0) -PCI_D1 ((pci_power_t __force) 1) -PCI_D2 ((pci_power_t __force) 2) -PCI_D3hot ((pci_power_t __force) 3) -PCI_D3cold ((pci_power_t __force) 4) -PCI_UNKNOWN ((pci_power_t __force) 5) - -This function is called when system -goes into suspend state mac80211 will -call rtl_mac_stop() from the mac80211 -suspend function first, So there is -no need to call hw_disable here. -****************************************/ -int rtl_pci_suspend(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->cfg->ops->hw_suspend(hw); - rtl_deinit_rfkill(hw); - - return 0; -} -EXPORT_SYMBOL(rtl_pci_suspend); - -int rtl_pci_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->cfg->ops->hw_resume(hw); - rtl_init_rfkill(hw); - return 0; -} -EXPORT_SYMBOL(rtl_pci_resume); -#endif /* CONFIG_PM_SLEEP */ - -struct rtl_intf_ops rtl_pci_ops = { - .read_efuse_byte = read_efuse_byte, - .adapter_start = rtl_pci_start, - .adapter_stop = rtl_pci_stop, - .check_buddy_priv = rtl_pci_check_buddy_priv, - .adapter_tx = rtl_pci_tx, - .flush = rtl_pci_flush, - .reset_trx_ring = rtl_pci_reset_trx_ring, - .waitq_insert = rtl_pci_tx_chk_waitq_insert, - - .disable_aspm = rtl_pci_disable_aspm, - .enable_aspm = rtl_pci_enable_aspm, -}; diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h deleted file mode 100644 index d4567d12e07e..000000000000 --- a/drivers/net/wireless/rtlwifi/pci.h +++ /dev/null @@ -1,335 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL_PCI_H__ -#define __RTL_PCI_H__ - -#include -/* -1: MSDU packet queue, -2: Rx Command Queue -*/ -#define RTL_PCI_RX_MPDU_QUEUE 0 -#define RTL_PCI_RX_CMD_QUEUE 1 -#define RTL_PCI_MAX_RX_QUEUE 2 - -#define RTL_PCI_MAX_RX_COUNT 512/*64*/ -#define RTL_PCI_MAX_TX_QUEUE_COUNT 9 - -#define RT_TXDESC_NUM 128 -#define TX_DESC_NUM_92E 512 -#define RT_TXDESC_NUM_BE_QUEUE 256 - -#define BK_QUEUE 0 -#define BE_QUEUE 1 -#define VI_QUEUE 2 -#define VO_QUEUE 3 -#define BEACON_QUEUE 4 -#define TXCMD_QUEUE 5 -#define MGNT_QUEUE 6 -#define HIGH_QUEUE 7 -#define HCCA_QUEUE 8 - -#define RTL_PCI_DEVICE(vend, dev, cfg) \ - .vendor = (vend), \ - .device = (dev), \ - .subvendor = PCI_ANY_ID, \ - .subdevice = PCI_ANY_ID,\ - .driver_data = (kernel_ulong_t)&(cfg) - -#define INTEL_VENDOR_ID 0x8086 -#define SIS_VENDOR_ID 0x1039 -#define ATI_VENDOR_ID 0x1002 -#define ATI_DEVICE_ID 0x7914 -#define AMD_VENDOR_ID 0x1022 - -#define PCI_MAX_BRIDGE_NUMBER 255 -#define PCI_MAX_DEVICES 32 -#define PCI_MAX_FUNCTION 8 - -#define PCI_CONF_ADDRESS 0x0CF8 /*PCI Configuration Space Address */ -#define PCI_CONF_DATA 0x0CFC /*PCI Configuration Space Data */ - -#define PCI_CLASS_BRIDGE_DEV 0x06 -#define PCI_SUBCLASS_BR_PCI_TO_PCI 0x04 -#define PCI_CAPABILITY_ID_PCI_EXPRESS 0x10 -#define PCI_CAP_ID_EXP 0x10 - -#define U1DONTCARE 0xFF -#define U2DONTCARE 0xFFFF -#define U4DONTCARE 0xFFFFFFFF - -#define RTL_PCI_8192_DID 0x8192 /*8192 PCI-E */ -#define RTL_PCI_8192SE_DID 0x8192 /*8192 SE */ -#define RTL_PCI_8174_DID 0x8174 /*8192 SE */ -#define RTL_PCI_8173_DID 0x8173 /*8191 SE Crab */ -#define RTL_PCI_8172_DID 0x8172 /*8191 SE RE */ -#define RTL_PCI_8171_DID 0x8171 /*8191 SE Unicron */ -#define RTL_PCI_8723AE_DID 0x8723 /*8723AE */ -#define RTL_PCI_0045_DID 0x0045 /*8190 PCI for Ceraga */ -#define RTL_PCI_0046_DID 0x0046 /*8190 Cardbus for Ceraga */ -#define RTL_PCI_0044_DID 0x0044 /*8192e PCIE for Ceraga */ -#define RTL_PCI_0047_DID 0x0047 /*8192e Express Card for Ceraga */ -#define RTL_PCI_700F_DID 0x700F -#define RTL_PCI_701F_DID 0x701F -#define RTL_PCI_DLINK_DID 0x3304 -#define RTL_PCI_8723AE_DID 0x8723 /*8723e */ -#define RTL_PCI_8192CET_DID 0x8191 /*8192ce */ -#define RTL_PCI_8192CE_DID 0x8178 /*8192ce */ -#define RTL_PCI_8191CE_DID 0x8177 /*8192ce */ -#define RTL_PCI_8188CE_DID 0x8176 /*8192ce */ -#define RTL_PCI_8192CU_DID 0x8191 /*8192ce */ -#define RTL_PCI_8192DE_DID 0x8193 /*8192de */ -#define RTL_PCI_8192DE_DID2 0x002B /*92DE*/ -#define RTL_PCI_8188EE_DID 0x8179 /*8188ee*/ -#define RTL_PCI_8723BE_DID 0xB723 /*8723be*/ -#define RTL_PCI_8192EE_DID 0x818B /*8192ee*/ -#define RTL_PCI_8821AE_DID 0x8821 /*8821ae*/ -#define RTL_PCI_8812AE_DID 0x8812 /*8812ae*/ - -/*8192 support 16 pages of IO registers*/ -#define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000 -#define RTL_MEM_MAPPED_IO_RANGE_8192PCIE 0x4000 -#define RTL_MEM_MAPPED_IO_RANGE_8192SE 0x4000 -#define RTL_MEM_MAPPED_IO_RANGE_8192CE 0x4000 -#define RTL_MEM_MAPPED_IO_RANGE_8192DE 0x4000 - -#define RTL_PCI_REVISION_ID_8190PCI 0x00 -#define RTL_PCI_REVISION_ID_8192PCIE 0x01 -#define RTL_PCI_REVISION_ID_8192SE 0x10 -#define RTL_PCI_REVISION_ID_8192CE 0x1 -#define RTL_PCI_REVISION_ID_8192DE 0x0 - -#define RTL_DEFAULT_HARDWARE_TYPE HARDWARE_TYPE_RTL8192CE - -enum pci_bridge_vendor { - PCI_BRIDGE_VENDOR_INTEL = 0x0, /*0b'0000,0001 */ - PCI_BRIDGE_VENDOR_ATI, /*0b'0000,0010*/ - PCI_BRIDGE_VENDOR_AMD, /*0b'0000,0100*/ - PCI_BRIDGE_VENDOR_SIS, /*0b'0000,1000*/ - PCI_BRIDGE_VENDOR_UNKNOWN, /*0b'0100,0000*/ - PCI_BRIDGE_VENDOR_MAX, -}; - -struct rtl_pci_capabilities_header { - u8 capability_id; - u8 next; -}; - -/* In new TRX flow, Buffer_desc is new concept - * But TX wifi info == TX descriptor in old flow - * RX wifi info == RX descriptor in old flow - */ -struct rtl_tx_buffer_desc { -#if (RTL8192EE_SEG_NUM == 2) - u32 dword[2*(DMA_IS_64BIT + 1)*8]; /*seg = 8*/ -#elif (RTL8192EE_SEG_NUM == 1) - u32 dword[2*(DMA_IS_64BIT + 1)*4]; /*seg = 4*/ -#elif (RTL8192EE_SEG_NUM == 0) - u32 dword[2*(DMA_IS_64BIT + 1)*2]; /*seg = 2*/ -#endif -} __packed; - -struct rtl_tx_desc { - u32 dword[16]; -} __packed; - -struct rtl_rx_buffer_desc { /*rx buffer desc*/ - u32 dword[2]; -} __packed; - -struct rtl_rx_desc { /*old: rx desc new: rx wifi info*/ - u32 dword[8]; -} __packed; - -struct rtl_tx_cmd_desc { - u32 dword[16]; -} __packed; - -struct rtl8192_tx_ring { - struct rtl_tx_desc *desc; - dma_addr_t dma; - unsigned int idx; - unsigned int entries; - struct sk_buff_head queue; - /*add for new trx flow*/ - struct rtl_tx_buffer_desc *buffer_desc; /*tx buffer descriptor*/ - dma_addr_t buffer_desc_dma; /*tx bufferd desc dma memory*/ - u16 avl_desc; /* available_desc_to_write */ - u16 cur_tx_wp; /* current_tx_write_point */ - u16 cur_tx_rp; /* current_tx_read_point */ -}; - -struct rtl8192_rx_ring { - struct rtl_rx_desc *desc; - dma_addr_t dma; - unsigned int idx; - struct sk_buff *rx_buf[RTL_PCI_MAX_RX_COUNT]; - /*add for new trx flow*/ - struct rtl_rx_buffer_desc *buffer_desc; /*rx buffer descriptor*/ - u16 next_rx_rp; /* next_rx_read_point */ -}; - -struct rtl_pci { - struct pci_dev *pdev; - bool irq_enabled; - - bool driver_is_goingto_unload; - bool up_first_time; - bool first_init; - bool being_init_adapter; - bool init_ready; - - /*Tx */ - struct rtl8192_tx_ring tx_ring[RTL_PCI_MAX_TX_QUEUE_COUNT]; - int txringcount[RTL_PCI_MAX_TX_QUEUE_COUNT]; - u32 transmit_config; - - /*Rx */ - struct rtl8192_rx_ring rx_ring[RTL_PCI_MAX_RX_QUEUE]; - int rxringcount; - u16 rxbuffersize; - u32 receive_config; - - /*irq */ - u8 irq_alloc; - u32 irq_mask[2]; - u32 sys_irq_mask; - - /*Bcn control register setting */ - u32 reg_bcn_ctrl_val; - - /*ASPM*/ u8 const_pci_aspm; - u8 const_amdpci_aspm; - u8 const_hwsw_rfoff_d3; - u8 const_support_pciaspm; - /*pci-e bridge */ - u8 const_hostpci_aspm_setting; - /*pci-e device */ - u8 const_devicepci_aspm_setting; - /*If it supports ASPM, Offset[560h] = 0x40, - otherwise Offset[560h] = 0x00. */ - bool support_aspm; - bool support_backdoor; - - /*QOS & EDCA */ - enum acm_method acm_method; - - u16 shortretry_limit; - u16 longretry_limit; - - /* MSI support */ - bool msi_support; - bool using_msi; -}; - -struct mp_adapter { - u8 linkctrl_reg; - - u8 busnumber; - u8 devnumber; - u8 funcnumber; - - u8 pcibridge_busnum; - u8 pcibridge_devnum; - u8 pcibridge_funcnum; - - u8 pcibridge_vendor; - u16 pcibridge_vendorid; - u16 pcibridge_deviceid; - - u8 num4bytes; - - u8 pcibridge_pciehdr_offset; - u8 pcibridge_linkctrlreg; - - bool amd_l1_patch; -}; - -struct rtl_pci_priv { - struct rtl_pci dev; - struct mp_adapter ndis_adapter; - struct rtl_led_ctl ledctl; - struct bt_coexist_info bt_coexist; -}; - -#define rtl_pcipriv(hw) (((struct rtl_pci_priv *)(rtl_priv(hw))->priv)) -#define rtl_pcidev(pcipriv) (&((pcipriv)->dev)) - -int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw); - -extern struct rtl_intf_ops rtl_pci_ops; - -int rtl_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id); -void rtl_pci_disconnect(struct pci_dev *pdev); -#ifdef CONFIG_PM_SLEEP -int rtl_pci_suspend(struct device *dev); -int rtl_pci_resume(struct device *dev); -#endif /* CONFIG_PM_SLEEP */ -static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr) -{ - return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr); -} - -static inline u16 pci_read16_sync(struct rtl_priv *rtlpriv, u32 addr) -{ - return readw((u8 __iomem *) rtlpriv->io.pci_mem_start + addr); -} - -static inline u32 pci_read32_sync(struct rtl_priv *rtlpriv, u32 addr) -{ - return readl((u8 __iomem *) rtlpriv->io.pci_mem_start + addr); -} - -static inline void pci_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val) -{ - writeb(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr); -} - -static inline void pci_write16_async(struct rtl_priv *rtlpriv, - u32 addr, u16 val) -{ - writew(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr); -} - -static inline void pci_write32_async(struct rtl_priv *rtlpriv, - u32 addr, u32 val) -{ - writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr); -} - -static inline u16 calc_fifo_space(u16 rp, u16 wp) -{ - if (rp <= wp) - return RTL_PCI_MAX_RX_COUNT - 1 + rp - wp; - return rp - wp - 1; -} - -#endif diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c deleted file mode 100644 index b69321d45f04..000000000000 --- a/drivers/net/wireless/rtlwifi/ps.c +++ /dev/null @@ -1,1004 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "wifi.h" -#include "base.h" -#include "ps.h" -#include -#include "btcoexist/rtl_btc.h" - -bool rtl_ps_enable_nic(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - /*<1> reset trx ring */ - if (rtlhal->interface == INTF_PCI) - rtlpriv->intf_ops->reset_trx_ring(hw); - - if (is_hal_stop(rtlhal)) - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Driver is already down!\n"); - - /*<2> Enable Adapter */ - if (rtlpriv->cfg->ops->hw_init(hw)) - return false; - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - - /*<3> Enable Interrupt */ - rtlpriv->cfg->ops->enable_interrupt(hw); - - /* */ - rtl_watch_dog_timer_callback((unsigned long)hw); - - return true; -} -EXPORT_SYMBOL(rtl_ps_enable_nic); - -bool rtl_ps_disable_nic(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /*<1> Stop all timer */ - rtl_deinit_deferred_work(hw); - - /*<2> Disable Interrupt */ - rtlpriv->cfg->ops->disable_interrupt(hw); - tasklet_kill(&rtlpriv->works.irq_tasklet); - - /*<3> Disable Adapter */ - rtlpriv->cfg->ops->hw_disable(hw); - - return true; -} -EXPORT_SYMBOL(rtl_ps_disable_nic); - -bool rtl_ps_set_rf_state(struct ieee80211_hw *hw, - enum rf_pwrstate state_toset, - u32 changesource, bool protect_or_not) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - enum rf_pwrstate rtstate; - bool actionallowed = false; - u16 rfwait_cnt = 0; - - if (protect_or_not) - goto no_protect; - - /*Only one thread can change - *the RF state at one time, and others - *should wait to be executed. - */ - while (true) { - spin_lock(&rtlpriv->locks.rf_ps_lock); - if (ppsc->rfchange_inprogress) { - spin_unlock(&rtlpriv->locks.rf_ps_lock); - - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "RF Change in progress! Wait to set..state_toset(%d).\n", - state_toset); - - /* Set RF after the previous action is done. */ - while (ppsc->rfchange_inprogress) { - rfwait_cnt++; - mdelay(1); - /*Wait too long, return false to avoid - *to be stuck here. - */ - if (rfwait_cnt > 100) - return false; - } - } else { - ppsc->rfchange_inprogress = true; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - break; - } - } - -no_protect: - rtstate = ppsc->rfpwr_state; - - switch (state_toset) { - case ERFON: - ppsc->rfoff_reason &= (~changesource); - - if ((changesource == RF_CHANGE_BY_HW) && - (ppsc->hwradiooff)) { - ppsc->hwradiooff = false; - } - - if (!ppsc->rfoff_reason) { - ppsc->rfoff_reason = 0; - actionallowed = true; - } - - break; - - case ERFOFF: - - if ((changesource == RF_CHANGE_BY_HW) && !ppsc->hwradiooff) { - ppsc->hwradiooff = true; - } - - ppsc->rfoff_reason |= changesource; - actionallowed = true; - break; - - case ERFSLEEP: - ppsc->rfoff_reason |= changesource; - actionallowed = true; - break; - - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - - if (actionallowed) - rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset); - - if (!protect_or_not) { - spin_lock(&rtlpriv->locks.rf_ps_lock); - ppsc->rfchange_inprogress = false; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } - - return actionallowed; -} -EXPORT_SYMBOL(rtl_ps_set_rf_state); - -static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - ppsc->swrf_processing = true; - - if (ppsc->inactive_pwrstate == ERFON && - rtlhal->interface == INTF_PCI) { - if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && - RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && - rtlhal->interface == INTF_PCI) { - rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); - } - } - - rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, - RF_CHANGE_BY_IPS, false); - - if (ppsc->inactive_pwrstate == ERFOFF && - rtlhal->interface == INTF_PCI) { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && - !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { - rtlpriv->intf_ops->enable_aspm(hw); - RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); - } - } - - ppsc->swrf_processing = false; -} - -void rtl_ips_nic_off_wq_callback(void *data) -{ - struct rtl_works *rtlworks = - container_of_dwork_rtl(data, struct rtl_works, ips_nic_off_wq); - struct ieee80211_hw *hw = rtlworks->hw; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - enum rf_pwrstate rtstate; - - if (mac->opmode != NL80211_IFTYPE_STATION) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "not station return\n"); - return; - } - - if (mac->p2p_in_use) - return; - - if (mac->link_state > MAC80211_NOLINK) - return; - - if (is_hal_stop(rtlhal)) - return; - - if (rtlpriv->sec.being_setkey) - return; - - if (rtlpriv->cfg->ops->bt_coex_off_before_lps) - rtlpriv->cfg->ops->bt_coex_off_before_lps(hw); - - if (ppsc->inactiveps) { - rtstate = ppsc->rfpwr_state; - - /* - *Do not enter IPS in the following conditions: - *(1) RF is already OFF or Sleep - *(2) swrf_processing (indicates the IPS is still under going) - *(3) Connectted (only disconnected can trigger IPS) - *(4) IBSS (send Beacon) - *(5) AP mode (send Beacon) - *(6) monitor mode (rcv packet) - */ - - if (rtstate == ERFON && - !ppsc->swrf_processing && - (mac->link_state == MAC80211_NOLINK) && - !mac->act_scanning) { - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "IPSEnter(): Turn off RF\n"); - - ppsc->inactive_pwrstate = ERFOFF; - ppsc->in_powersavemode = true; - - /* call before RF off */ - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_ips_notify(rtlpriv, - ppsc->inactive_pwrstate); - - /*rtl_pci_reset_trx_ring(hw); */ - _rtl_ps_inactive_ps(hw); - } - } -} - -void rtl_ips_nic_off(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /* because when link with ap, mac80211 will ask us - * to disable nic quickly after scan before linking, - * this will cause link failed, so we delay 100ms here - */ - queue_delayed_work(rtlpriv->works.rtl_wq, - &rtlpriv->works.ips_nic_off_wq, MSECS(100)); -} - -/* NOTICE: any opmode should exc nic_on, or disable without - * nic_on may something wrong, like adhoc TP - */ -void rtl_ips_nic_on(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - enum rf_pwrstate rtstate; - - cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq); - - spin_lock(&rtlpriv->locks.ips_lock); - if (ppsc->inactiveps) { - rtstate = ppsc->rfpwr_state; - - if (rtstate != ERFON && - !ppsc->swrf_processing && - ppsc->rfoff_reason <= RF_CHANGE_BY_IPS) { - - ppsc->inactive_pwrstate = ERFON; - ppsc->in_powersavemode = false; - _rtl_ps_inactive_ps(hw); - /* call after RF on */ - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_ips_notify(rtlpriv, - ppsc->inactive_pwrstate); - } - } - spin_unlock(&rtlpriv->locks.ips_lock); -} -EXPORT_SYMBOL_GPL(rtl_ips_nic_on); - -/*for FW LPS*/ - -/* - *Determine if we can set Fw into PS mode - *in current condition.Return TRUE if it - *can enter PS mode. - */ -static bool rtl_get_fwlps_doze(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u32 ps_timediff; - - ps_timediff = jiffies_to_msecs(jiffies - - ppsc->last_delaylps_stamp_jiffies); - - if (ps_timediff < 2000) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Delay enter Fw LPS for DHCP, ARP, or EAPOL exchanging state\n"); - return false; - } - - if (mac->link_state != MAC80211_LINKED) - return false; - - if (mac->opmode == NL80211_IFTYPE_ADHOC) - return false; - - return true; -} - -/* Change current and default preamble mode.*/ -void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool enter_fwlps; - - if (mac->opmode == NL80211_IFTYPE_ADHOC) - return; - - if (mac->link_state != MAC80211_LINKED) - return; - - if (ppsc->dot11_psmode == rt_psmode) - return; - - /* Update power save mode configured. */ - ppsc->dot11_psmode = rt_psmode; - - /* - * - *1. Enter PS mode - * Set RPWM to Fw to turn RF off and send H2C fw_pwrmode - * cmd to set Fw into PS mode. - *2. Leave PS mode - * Send H2C fw_pwrmode cmd to Fw to set Fw into Active - * mode and set RPWM to turn RF on. - */ - - if ((ppsc->fwctrl_lps) && ppsc->report_linked) { - if (ppsc->dot11_psmode == EACTIVE) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "FW LPS leave ps_mode:%x\n", - FW_PS_ACTIVE_MODE); - enter_fwlps = false; - ppsc->pwr_mode = FW_PS_ACTIVE_MODE; - ppsc->smart_ps = 0; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_LPS_ACTION, - (u8 *)(&enter_fwlps)); - if (ppsc->p2p_ps_info.opp_ps) - rtl_p2p_ps_cmd(hw , P2P_PS_ENABLE); - - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_lps_notify(rtlpriv, rt_psmode); - } else { - if (rtl_get_fwlps_doze(hw)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "FW LPS enter ps_mode:%x\n", - ppsc->fwctrl_psmode); - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_lps_notify(rtlpriv, rt_psmode); - enter_fwlps = true; - ppsc->pwr_mode = ppsc->fwctrl_psmode; - ppsc->smart_ps = 2; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_FW_LPS_ACTION, - (u8 *)(&enter_fwlps)); - - } else { - /* Reset the power save related parameters. */ - ppsc->dot11_psmode = EACTIVE; - } - } - } -} - -/*Enter the leisure power save mode.*/ -void rtl_lps_enter(struct ieee80211_hw *hw) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - unsigned long flag; - - if (!ppsc->fwctrl_lps) - return; - - if (rtlpriv->sec.being_setkey) - return; - - if (rtlpriv->link_info.busytraffic) - return; - - /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */ - if (mac->cnt_after_linked < 5) - return; - - if (mac->opmode == NL80211_IFTYPE_ADHOC) - return; - - if (mac->link_state != MAC80211_LINKED) - return; - - spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - - /* Idle for a while if we connect to AP a while ago. */ - if (mac->cnt_after_linked >= 2) { - if (ppsc->dot11_psmode == EACTIVE) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Enter 802.11 power save mode...\n"); - - rtl_lps_set_psmode(hw, EAUTOPS); - } - } - - spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); -} -EXPORT_SYMBOL(rtl_lps_enter); - -/*Leave the leisure power save mode.*/ -void rtl_lps_leave(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - unsigned long flag; - - spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - - if (ppsc->fwctrl_lps) { - if (ppsc->dot11_psmode != EACTIVE) { - - /*FIX ME */ - /*rtlpriv->cfg->ops->enable_interrupt(hw); */ - - if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && - RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) && - rtlhal->interface == INTF_PCI) { - rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); - } - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Busy Traffic,Leave 802.11 power save..\n"); - - rtl_lps_set_psmode(hw, EACTIVE); - } - } - spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); -} -EXPORT_SYMBOL(rtl_lps_leave); - -/* For sw LPS*/ -void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = data; - struct ieee80211_tim_ie *tim_ie; - u8 *tim; - u8 tim_len; - bool u_buffed; - bool m_buffed; - - if (mac->opmode != NL80211_IFTYPE_STATION) - return; - - if (!rtlpriv->psc.swctrl_lps) - return; - - if (rtlpriv->mac80211.link_state != MAC80211_LINKED) - return; - - if (!rtlpriv->psc.sw_ps_enabled) - return; - - if (rtlpriv->psc.fwctrl_lps) - return; - - if (likely(!(hw->conf.flags & IEEE80211_CONF_PS))) - return; - - /* check if this really is a beacon */ - if (!ieee80211_is_beacon(hdr->frame_control)) - return; - - /* min. beacon length + FCS_LEN */ - if (len <= 40 + FCS_LEN) - return; - - /* and only beacons from the associated BSSID, please */ - if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid)) - return; - - rtlpriv->psc.last_beacon = jiffies; - - tim = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_TIM); - if (!tim) - return; - - if (tim[1] < sizeof(*tim_ie)) - return; - - tim_len = tim[1]; - tim_ie = (struct ieee80211_tim_ie *) &tim[2]; - - if (!WARN_ON_ONCE(!hw->conf.ps_dtim_period)) - rtlpriv->psc.dtim_counter = tim_ie->dtim_count; - - /* Check whenever the PHY can be turned off again. */ - - /* 1. What about buffered unicast traffic for our AID? */ - u_buffed = ieee80211_check_tim(tim_ie, tim_len, - rtlpriv->mac80211.assoc_id); - - /* 2. Maybe the AP wants to send multicast/broadcast data? */ - m_buffed = tim_ie->bitmap_ctrl & 0x01; - rtlpriv->psc.multi_buffered = m_buffed; - - /* unicast will process by mac80211 through - * set ~IEEE80211_CONF_PS, So we just check - * multicast frames here */ - if (!m_buffed) { - /* back to low-power land. and delay is - * prevent null power save frame tx fail */ - queue_delayed_work(rtlpriv->works.rtl_wq, - &rtlpriv->works.ps_work, MSECS(5)); - } else { - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "u_bufferd: %x, m_buffered: %x\n", u_buffed, m_buffed); - } -} -EXPORT_SYMBOL_GPL(rtl_swlps_beacon); - -void rtl_swlps_rf_awake(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - unsigned long flag; - - if (!rtlpriv->psc.swctrl_lps) - return; - if (mac->link_state != MAC80211_LINKED) - return; - - if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM && - RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { - rtlpriv->intf_ops->disable_aspm(hw); - RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); - } - - spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false); - spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); -} - -void rtl_swlps_rfon_wq_callback(void *data) -{ - struct rtl_works *rtlworks = - container_of_dwork_rtl(data, struct rtl_works, ps_rfon_wq); - struct ieee80211_hw *hw = rtlworks->hw; - - rtl_swlps_rf_awake(hw); -} - -void rtl_swlps_rf_sleep(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - unsigned long flag; - u8 sleep_intv; - - if (!rtlpriv->psc.sw_ps_enabled) - return; - - if ((rtlpriv->sec.being_setkey) || - (mac->opmode == NL80211_IFTYPE_ADHOC)) - return; - - /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */ - if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5)) - return; - - if (rtlpriv->link_info.busytraffic) - return; - - spin_lock(&rtlpriv->locks.rf_ps_lock); - if (rtlpriv->psc.rfchange_inprogress) { - spin_unlock(&rtlpriv->locks.rf_ps_lock); - return; - } - spin_unlock(&rtlpriv->locks.rf_ps_lock); - - spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); - rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS , false); - spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); - - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM && - !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { - rtlpriv->intf_ops->enable_aspm(hw); - RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM); - } - - /* here is power save alg, when this beacon is DTIM - * we will set sleep time to dtim_period * n; - * when this beacon is not DTIM, we will set sleep - * time to sleep_intv = rtlpriv->psc.dtim_counter or - * MAX_SW_LPS_SLEEP_INTV(default set to 5) */ - - if (rtlpriv->psc.dtim_counter == 0) { - if (hw->conf.ps_dtim_period == 1) - sleep_intv = hw->conf.ps_dtim_period * 2; - else - sleep_intv = hw->conf.ps_dtim_period; - } else { - sleep_intv = rtlpriv->psc.dtim_counter; - } - - if (sleep_intv > MAX_SW_LPS_SLEEP_INTV) - sleep_intv = MAX_SW_LPS_SLEEP_INTV; - - /* this print should always be dtim_conter = 0 & - * sleep = dtim_period, that meaons, we should - * awake before every dtim */ - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "dtim_counter:%x will sleep :%d beacon_intv\n", - rtlpriv->psc.dtim_counter, sleep_intv); - - /* we tested that 40ms is enough for sw & hw sw delay */ - queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq, - MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40)); -} - -void rtl_lps_change_work_callback(struct work_struct *work) -{ - struct rtl_works *rtlworks = - container_of(work, struct rtl_works, lps_change_work); - struct ieee80211_hw *hw = rtlworks->hw; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->enter_ps) - rtl_lps_enter(hw); - else - rtl_lps_leave(hw); -} -EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback); - -void rtl_swlps_wq_callback(void *data) -{ - struct rtl_works *rtlworks = container_of_dwork_rtl(data, - struct rtl_works, - ps_work); - struct ieee80211_hw *hw = rtlworks->hw; - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool ps = false; - - ps = (hw->conf.flags & IEEE80211_CONF_PS); - - /* we can sleep after ps null send ok */ - if (rtlpriv->psc.state_inap) { - rtl_swlps_rf_sleep(hw); - - if (rtlpriv->psc.state && !ps) { - rtlpriv->psc.sleep_ms = jiffies_to_msecs(jiffies - - rtlpriv->psc.last_action); - } - - if (ps) - rtlpriv->psc.last_slept = jiffies; - - rtlpriv->psc.last_action = jiffies; - rtlpriv->psc.state = ps; - } -} - -static void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data, - unsigned int len) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_mgmt *mgmt = data; - struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); - u8 *pos, *end, *ie; - u16 noa_len; - static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; - u8 noa_num, index , i, noa_index = 0; - bool find_p2p_ie = false , find_p2p_ps_ie = false; - pos = (u8 *)mgmt->u.beacon.variable; - end = data + len; - ie = NULL; - - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - return; - - if (pos[0] == 221 && pos[1] > 4) { - if (memcmp(&pos[2], p2p_oui_ie_type, 4) == 0) { - ie = pos + 2+4; - break; - } - } - pos += 2 + pos[1]; - } - - if (ie == NULL) - return; - find_p2p_ie = true; - /*to find noa ie*/ - while (ie + 1 < end) { - noa_len = READEF2BYTE((__le16 *)&ie[1]); - if (ie + 3 + ie[1] > end) - return; - - if (ie[0] == 12) { - find_p2p_ps_ie = true; - if ((noa_len - 2) % 13 != 0) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "P2P notice of absence: invalid length.%d\n", - noa_len); - return; - } else { - noa_num = (noa_len - 2) / 13; - } - noa_index = ie[3]; - if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == - P2P_PS_NONE || noa_index != p2pinfo->noa_index) { - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "update NOA ie.\n"); - p2pinfo->noa_index = noa_index; - p2pinfo->opp_ps = (ie[4] >> 7); - p2pinfo->ctwindow = ie[4] & 0x7F; - p2pinfo->noa_num = noa_num; - index = 5; - for (i = 0; i < noa_num; i++) { - p2pinfo->noa_count_type[i] = - READEF1BYTE(ie+index); - index += 1; - p2pinfo->noa_duration[i] = - READEF4BYTE((__le32 *)ie+index); - index += 4; - p2pinfo->noa_interval[i] = - READEF4BYTE((__le32 *)ie+index); - index += 4; - p2pinfo->noa_start_time[i] = - READEF4BYTE((__le32 *)ie+index); - index += 4; - } - - if (p2pinfo->opp_ps == 1) { - p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW; - /* Driver should wait LPS entering - * CTWindow - */ - if (rtlpriv->psc.fw_current_inpsmode) - rtl_p2p_ps_cmd(hw, - P2P_PS_ENABLE); - } else if (p2pinfo->noa_num > 0) { - p2pinfo->p2p_ps_mode = P2P_PS_NOA; - rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); - } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { - rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); - } - } - break; - } - ie += 3 + noa_len; - } - - if (find_p2p_ie == true) { - if ((p2pinfo->p2p_ps_mode > P2P_PS_NONE) && - (find_p2p_ps_ie == false)) - rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); - } -} - -static void rtl_p2p_action_ie(struct ieee80211_hw *hw, void *data, - unsigned int len) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_mgmt *mgmt = data; - struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); - u8 noa_num, index , i , noa_index = 0; - u8 *pos, *end, *ie; - u16 noa_len; - static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09}; - - pos = (u8 *)&mgmt->u.action.category; - end = data + len; - ie = NULL; - - if (pos[0] == 0x7f) { - if (memcmp(&pos[1], p2p_oui_ie_type, 4) == 0) - ie = pos + 3+4; - } - - if (ie == NULL) - return; - - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "action frame find P2P IE.\n"); - /*to find noa ie*/ - while (ie + 1 < end) { - noa_len = READEF2BYTE((__le16 *)&ie[1]); - if (ie + 3 + ie[1] > end) - return; - - if (ie[0] == 12) { - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "find NOA IE.\n"); - RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_LOUD, "noa ie ", - ie, noa_len); - if ((noa_len - 2) % 13 != 0) { - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "P2P notice of absence: invalid length.%d\n", - noa_len); - return; - } else { - noa_num = (noa_len - 2) / 13; - } - noa_index = ie[3]; - if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == - P2P_PS_NONE || noa_index != p2pinfo->noa_index) { - p2pinfo->noa_index = noa_index; - p2pinfo->opp_ps = (ie[4] >> 7); - p2pinfo->ctwindow = ie[4] & 0x7F; - p2pinfo->noa_num = noa_num; - index = 5; - for (i = 0; i < noa_num; i++) { - p2pinfo->noa_count_type[i] = - READEF1BYTE(ie+index); - index += 1; - p2pinfo->noa_duration[i] = - READEF4BYTE((__le32 *)ie+index); - index += 4; - p2pinfo->noa_interval[i] = - READEF4BYTE((__le32 *)ie+index); - index += 4; - p2pinfo->noa_start_time[i] = - READEF4BYTE((__le32 *)ie+index); - index += 4; - } - - if (p2pinfo->opp_ps == 1) { - p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW; - /* Driver should wait LPS entering - * CTWindow - */ - if (rtlpriv->psc.fw_current_inpsmode) - rtl_p2p_ps_cmd(hw, - P2P_PS_ENABLE); - } else if (p2pinfo->noa_num > 0) { - p2pinfo->p2p_ps_mode = P2P_PS_NOA; - rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE); - } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { - rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE); - } - } - break; - } - ie += 3 + noa_len; - } -} - -void rtl_p2p_ps_cmd(struct ieee80211_hw *hw , u8 p2p_ps_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); - struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info); - - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, " p2p state %x\n" , p2p_ps_state); - switch (p2p_ps_state) { - case P2P_PS_DISABLE: - p2pinfo->p2p_ps_state = p2p_ps_state; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, - &p2p_ps_state); - p2pinfo->noa_index = 0; - p2pinfo->ctwindow = 0; - p2pinfo->opp_ps = 0; - p2pinfo->noa_num = 0; - p2pinfo->p2p_ps_mode = P2P_PS_NONE; - if (rtlps->fw_current_inpsmode) { - if (rtlps->smart_ps == 0) { - rtlps->smart_ps = 2; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_PWRMODE, - &rtlps->pwr_mode); - } - - } - break; - case P2P_PS_ENABLE: - if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { - p2pinfo->p2p_ps_state = p2p_ps_state; - - if (p2pinfo->ctwindow > 0) { - if (rtlps->smart_ps != 0) { - rtlps->smart_ps = 0; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_PWRMODE, - &rtlps->pwr_mode); - } - } - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_P2P_PS_OFFLOAD, - &p2p_ps_state); - - } - break; - case P2P_PS_SCAN: - case P2P_PS_SCAN_DONE: - case P2P_PS_ALLSTASLEEP: - if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) { - p2pinfo->p2p_ps_state = p2p_ps_state; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_P2P_PS_OFFLOAD, - &p2p_ps_state); - } - break; - default: - break; - } - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "ctwindow %x oppps %x\n", - p2pinfo->ctwindow , p2pinfo->opp_ps); - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "count %x duration %x index %x interval %x start time %x noa num %x\n", - p2pinfo->noa_count_type[0], - p2pinfo->noa_duration[0], - p2pinfo->noa_index, - p2pinfo->noa_interval[0], - p2pinfo->noa_start_time[0], - p2pinfo->noa_num); - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "end\n"); -} - -void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ieee80211_hdr *hdr = data; - - if (!mac->p2p) - return; - if (mac->link_state != MAC80211_LINKED) - return; - /* min. beacon length + FCS_LEN */ - if (len <= 40 + FCS_LEN) - return; - - /* and only beacons from the associated BSSID, please */ - if (!ether_addr_equal_64bits(hdr->addr3, rtlpriv->mac80211.bssid)) - return; - - /* check if this really is a beacon */ - if (!(ieee80211_is_beacon(hdr->frame_control) || - ieee80211_is_probe_resp(hdr->frame_control) || - ieee80211_is_action(hdr->frame_control))) - return; - - if (ieee80211_is_action(hdr->frame_control)) - rtl_p2p_action_ie(hw , data , len - FCS_LEN); - else - rtl_p2p_noa_ie(hw , data , len - FCS_LEN); -} -EXPORT_SYMBOL_GPL(rtl_p2p_info); diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h deleted file mode 100644 index 29dfc514212d..000000000000 --- a/drivers/net/wireless/rtlwifi/ps.h +++ /dev/null @@ -1,53 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __REALTEK_RTL_PCI_PS_H__ -#define __REALTEK_RTL_PCI_PS_H__ - -#define MAX_SW_LPS_SLEEP_INTV 5 - -bool rtl_ps_set_rf_state(struct ieee80211_hw *hw, - enum rf_pwrstate state_toset, u32 changesource, - bool protect_or_not); -bool rtl_ps_enable_nic(struct ieee80211_hw *hw); -bool rtl_ps_disable_nic(struct ieee80211_hw *hw); -void rtl_ips_nic_off(struct ieee80211_hw *hw); -void rtl_ips_nic_on(struct ieee80211_hw *hw); -void rtl_ips_nic_off_wq_callback(void *data); -void rtl_lps_enter(struct ieee80211_hw *hw); -void rtl_lps_leave(struct ieee80211_hw *hw); - -void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode); - -void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len); -void rtl_swlps_wq_callback(void *data); -void rtl_swlps_rfon_wq_callback(void *data); -void rtl_swlps_rf_awake(struct ieee80211_hw *hw); -void rtl_swlps_rf_sleep(struct ieee80211_hw *hw); -void rtl_p2p_ps_cmd(struct ieee80211_hw *hw , u8 p2p_ps_state); -void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len); -void rtl_lps_change_work_callback(struct work_struct *work); - -#endif diff --git a/drivers/net/wireless/rtlwifi/pwrseqcmd.h b/drivers/net/wireless/rtlwifi/pwrseqcmd.h deleted file mode 100644 index 17ce0cb2c35c..000000000000 --- a/drivers/net/wireless/rtlwifi/pwrseqcmd.h +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_PWRSEQCMD_H__ -#define __RTL8723E_PWRSEQCMD_H__ - -#include "wifi.h" -/*--------------------------------------------- - * 3 The value of cmd: 4 bits - *--------------------------------------------- - */ -#define PWR_CMD_READ 0x00 -#define PWR_CMD_WRITE 0x01 -#define PWR_CMD_POLLING 0x02 -#define PWR_CMD_DELAY 0x03 -#define PWR_CMD_END 0x04 - -/* define the base address of each block */ -#define PWR_BASEADDR_MAC 0x00 -#define PWR_BASEADDR_USB 0x01 -#define PWR_BASEADDR_PCIE 0x02 -#define PWR_BASEADDR_SDIO 0x03 - -#define PWR_INTF_SDIO_MSK BIT(0) -#define PWR_INTF_USB_MSK BIT(1) -#define PWR_INTF_PCI_MSK BIT(2) -#define PWR_INTF_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) - -#define PWR_FAB_TSMC_MSK BIT(0) -#define PWR_FAB_UMC_MSK BIT(1) -#define PWR_FAB_ALL_MSK (BIT(0)|BIT(1)|BIT(2)|BIT(3)) - -#define PWR_CUT_TESTCHIP_MSK BIT(0) -#define PWR_CUT_A_MSK BIT(1) -#define PWR_CUT_B_MSK BIT(2) -#define PWR_CUT_C_MSK BIT(3) -#define PWR_CUT_D_MSK BIT(4) -#define PWR_CUT_E_MSK BIT(5) -#define PWR_CUT_F_MSK BIT(6) -#define PWR_CUT_G_MSK BIT(7) -#define PWR_CUT_ALL_MSK 0xFF - -enum pwrseq_delay_unit { - PWRSEQ_DELAY_US, - PWRSEQ_DELAY_MS, -}; - -struct wlan_pwr_cfg { - u16 offset; - u8 cut_msk; - u8 fab_msk:4; - u8 interface_msk:4; - u8 base:4; - u8 cmd:4; - u8 msk; - u8 value; -}; - -#define GET_PWR_CFG_OFFSET(__PWR_CMD) (__PWR_CMD.offset) -#define GET_PWR_CFG_CUT_MASK(__PWR_CMD) (__PWR_CMD.cut_msk) -#define GET_PWR_CFG_FAB_MASK(__PWR_CMD) (__PWR_CMD.fab_msk) -#define GET_PWR_CFG_INTF_MASK(__PWR_CMD) (__PWR_CMD.interface_msk) -#define GET_PWR_CFG_BASE(__PWR_CMD) (__PWR_CMD.base) -#define GET_PWR_CFG_CMD(__PWR_CMD) (__PWR_CMD.cmd) -#define GET_PWR_CFG_MASK(__PWR_CMD) (__PWR_CMD.msk) -#define GET_PWR_CFG_VALUE(__PWR_CMD) (__PWR_CMD.value) - -bool rtl_hal_pwrseqcmdparsing(struct rtl_priv *rtlpriv, u8 cut_version, - u8 fab_version, u8 interface_type, - struct wlan_pwr_cfg pwrcfgcmd[]); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c deleted file mode 100644 index 74c14ce28238..000000000000 --- a/drivers/net/wireless/rtlwifi/rc.c +++ /dev/null @@ -1,302 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "wifi.h" -#include "base.h" -#include "rc.h" - -/* - *Finds the highest rate index we can use - *if skb is special data like DHCP/EAPOL, we set should - *it to lowest rate CCK_1M, otherwise we set rate to - *highest rate based on wireless mode used for iwconfig - *show Tx rate. - */ -static u8 _rtl_rc_get_highest_rix(struct rtl_priv *rtlpriv, - struct ieee80211_sta *sta, - struct sk_buff *skb, bool not_data) -{ - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_sta_info *sta_entry = NULL; - u8 wireless_mode = 0; - - /* - *this rate is no use for true rate, firmware - *will control rate at all it just used for - *1.show in iwconfig in B/G mode - *2.in rtl_get_tcb_desc when we check rate is - * 1M we will not use FW rate but user rate. - */ - - if (sta) { - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - wireless_mode = sta_entry->wireless_mode; - } - - if (rtl_is_special_data(rtlpriv->mac80211.hw, skb, true, false) || - not_data) { - return 0; - } else { - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - if (wireless_mode == WIRELESS_MODE_B) { - return B_MODE_MAX_RIX; - } else if (wireless_mode == WIRELESS_MODE_G) { - return G_MODE_MAX_RIX; - } else if (wireless_mode == WIRELESS_MODE_N_24G) { - if (get_rf_type(rtlphy) != RF_2T2R) - return N_MODE_MCS7_RIX; - else - return N_MODE_MCS15_RIX; - } else if (wireless_mode == WIRELESS_MODE_AC_24G) { - return AC_MODE_MCS9_RIX; - } - return 0; - } else { - if (wireless_mode == WIRELESS_MODE_A) { - return A_MODE_MAX_RIX; - } else if (wireless_mode == WIRELESS_MODE_N_5G) { - if (get_rf_type(rtlphy) != RF_2T2R) - return N_MODE_MCS7_RIX; - else - return N_MODE_MCS15_RIX; - } else if (wireless_mode == WIRELESS_MODE_AC_5G) { - return AC_MODE_MCS9_RIX; - } - return 0; - } - } -} - -static void _rtl_rc_rate_set_series(struct rtl_priv *rtlpriv, - struct ieee80211_sta *sta, - struct ieee80211_tx_rate *rate, - struct ieee80211_tx_rate_control *txrc, - u8 tries, char rix, int rtsctsenable, - bool not_data) -{ - struct rtl_mac *mac = rtl_mac(rtlpriv); - struct rtl_sta_info *sta_entry = NULL; - u8 wireless_mode = 0; - u8 sgi_20 = 0, sgi_40 = 0, sgi_80 = 0; - - if (sta) { - sgi_20 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; - sgi_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; - sgi_80 = sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80; - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - wireless_mode = sta_entry->wireless_mode; - } - rate->count = tries; - rate->idx = rix >= 0x00 ? rix : 0x00; - if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE && - wireless_mode == WIRELESS_MODE_AC_5G) - rate->idx += 0x10;/*2NSS for 8812AE*/ - - if (!not_data) { - if (txrc->short_preamble) - rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - if (sta && (sta->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40)) - rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (sta && (sta->vht_cap.vht_supported)) - rate->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; - } else { - if (mac->bw_40) - rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (mac->bw_80) - rate->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; - } - - if (sgi_20 || sgi_40 || sgi_80) - rate->flags |= IEEE80211_TX_RC_SHORT_GI; - if (sta && sta->ht_cap.ht_supported && - ((wireless_mode == WIRELESS_MODE_N_5G) || - (wireless_mode == WIRELESS_MODE_N_24G))) - rate->flags |= IEEE80211_TX_RC_MCS; - } -} - -static void rtl_get_rate(void *ppriv, struct ieee80211_sta *sta, - void *priv_sta, - struct ieee80211_tx_rate_control *txrc) -{ - struct rtl_priv *rtlpriv = ppriv; - struct sk_buff *skb = txrc->skb; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rates = tx_info->control.rates; - __le16 fc = rtl_get_fc(skb); - u8 try_per_rate, i, rix; - bool not_data = !ieee80211_is_data(fc); - - if (rate_control_send_low(sta, priv_sta, txrc)) - return; - - rix = _rtl_rc_get_highest_rix(rtlpriv, sta, skb, not_data); - try_per_rate = 1; - _rtl_rc_rate_set_series(rtlpriv, sta, &rates[0], txrc, - try_per_rate, rix, 1, not_data); - - if (!not_data) { - for (i = 1; i < 4; i++) - _rtl_rc_rate_set_series(rtlpriv, sta, &rates[i], - txrc, i, (rix - i), 1, - not_data); - } -} - -static bool _rtl_tx_aggr_check(struct rtl_priv *rtlpriv, - struct rtl_sta_info *sta_entry, u16 tid) -{ - struct rtl_mac *mac = rtl_mac(rtlpriv); - - if (mac->act_scanning) - return false; - - if (mac->opmode == NL80211_IFTYPE_STATION && - mac->cnt_after_linked < 3) - return false; - - if (sta_entry->tids[tid].agg.agg_state == RTL_AGG_STOP) - return true; - - return false; -} - -/*mac80211 Rate Control callbacks*/ -static void rtl_tx_status(void *ppriv, - struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = ppriv; - struct rtl_mac *mac = rtl_mac(rtlpriv); - struct ieee80211_hdr *hdr = rtl_get_hdr(skb); - __le16 fc = rtl_get_fc(skb); - struct rtl_sta_info *sta_entry; - - if (!priv_sta || !ieee80211_is_data(fc)) - return; - - if (rtl_is_special_data(mac->hw, skb, true, true)) - return; - - if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || - is_broadcast_ether_addr(ieee80211_get_DA(hdr))) - return; - - if (sta) { - /* Check if aggregation has to be enabled for this tid */ - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - if ((sta->ht_cap.ht_supported) && - !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { - if (ieee80211_is_data_qos(fc)) { - u8 tid = rtl_get_tid(skb); - if (_rtl_tx_aggr_check(rtlpriv, sta_entry, - tid)) { - sta_entry->tids[tid].agg.agg_state = - RTL_AGG_PROGRESS; - ieee80211_start_tx_ba_session(sta, tid, - 5000); - } - } - } - } -} - -static void rtl_rate_init(void *ppriv, - struct ieee80211_supported_band *sband, - struct cfg80211_chan_def *chandef, - struct ieee80211_sta *sta, void *priv_sta) -{ -} - -static void rtl_rate_update(void *ppriv, - struct ieee80211_supported_band *sband, - struct cfg80211_chan_def *chandef, - struct ieee80211_sta *sta, void *priv_sta, - u32 changed) -{ -} - -static void *rtl_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - return rtlpriv; -} - -static void rtl_rate_free(void *rtlpriv) -{ - return; -} - -static void *rtl_rate_alloc_sta(void *ppriv, - struct ieee80211_sta *sta, gfp_t gfp) -{ - struct rtl_priv *rtlpriv = ppriv; - struct rtl_rate_priv *rate_priv; - - rate_priv = kzalloc(sizeof(struct rtl_rate_priv), gfp); - if (!rate_priv) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Unable to allocate private rc structure\n"); - return NULL; - } - - rtlpriv->rate_priv = rate_priv; - - return rate_priv; -} - -static void rtl_rate_free_sta(void *rtlpriv, - struct ieee80211_sta *sta, void *priv_sta) -{ - struct rtl_rate_priv *rate_priv = priv_sta; - kfree(rate_priv); -} - -static struct rate_control_ops rtl_rate_ops = { - .name = "rtl_rc", - .alloc = rtl_rate_alloc, - .free = rtl_rate_free, - .alloc_sta = rtl_rate_alloc_sta, - .free_sta = rtl_rate_free_sta, - .rate_init = rtl_rate_init, - .rate_update = rtl_rate_update, - .tx_status = rtl_tx_status, - .get_rate = rtl_get_rate, -}; - -int rtl_rate_control_register(void) -{ - return ieee80211_rate_control_register(&rtl_rate_ops); -} - -void rtl_rate_control_unregister(void) -{ - ieee80211_rate_control_unregister(&rtl_rate_ops); -} diff --git a/drivers/net/wireless/rtlwifi/rc.h b/drivers/net/wireless/rtlwifi/rc.h deleted file mode 100644 index f29643d60d6b..000000000000 --- a/drivers/net/wireless/rtlwifi/rc.h +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL_RC_H__ -#define __RTL_RC_H__ - -#define B_MODE_MAX_RIX 3 -#define G_MODE_MAX_RIX 11 -#define A_MODE_MAX_RIX 7 - -/* in mac80211 mcs0-mcs15 is idx0-idx15*/ -#define N_MODE_MCS7_RIX 7 -#define N_MODE_MCS15_RIX 15 - -#define AC_MODE_MCS7_RIX 7 -#define AC_MODE_MCS8_RIX 8 -#define AC_MODE_MCS9_RIX 9 - -struct rtl_rate_priv { - u8 ht_cap; -}; - -int rtl_rate_control_register(void); -void rtl_rate_control_unregister(void); - -#endif diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c deleted file mode 100644 index a62bf0a65c32..000000000000 --- a/drivers/net/wireless/rtlwifi/regd.c +++ /dev/null @@ -1,473 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "wifi.h" -#include "regd.h" - -static struct country_code_to_enum_rd allCountries[] = { - {COUNTRY_CODE_FCC, "US"}, - {COUNTRY_CODE_IC, "US"}, - {COUNTRY_CODE_ETSI, "EC"}, - {COUNTRY_CODE_SPAIN, "EC"}, - {COUNTRY_CODE_FRANCE, "EC"}, - {COUNTRY_CODE_MKK, "JP"}, - {COUNTRY_CODE_MKK1, "JP"}, - {COUNTRY_CODE_ISRAEL, "EC"}, - {COUNTRY_CODE_TELEC, "JP"}, - {COUNTRY_CODE_MIC, "JP"}, - {COUNTRY_CODE_GLOBAL_DOMAIN, "JP"}, - {COUNTRY_CODE_WORLD_WIDE_13, "EC"}, - {COUNTRY_CODE_TELEC_NETGEAR, "EC"}, - {COUNTRY_CODE_WORLD_WIDE_13_5G_ALL, "US"}, -}; - -/* - *Only these channels all allow active - *scan on all world regulatory domains - */ -#define RTL819x_2GHZ_CH01_11 \ - REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) - -/* - *We enable active scan on these a case - *by case basis by regulatory domain - */ -#define RTL819x_2GHZ_CH12_13 \ - REG_RULE(2467-10, 2472+10, 40, 0, 20,\ - NL80211_RRF_PASSIVE_SCAN) - -#define RTL819x_2GHZ_CH14 \ - REG_RULE(2484-10, 2484+10, 40, 0, 20, \ - NL80211_RRF_PASSIVE_SCAN | \ - NL80211_RRF_NO_OFDM) - - -/* 5G chan 36 - chan 64*/ -#define RTL819x_5GHZ_5150_5350 \ - REG_RULE(5150-10, 5350+10, 80, 0, 30, 0) -/* 5G chan 100 - chan 165*/ -#define RTL819x_5GHZ_5470_5850 \ - REG_RULE(5470-10, 5850+10, 80, 0, 30, 0) -/* 5G chan 149 - chan 165*/ -#define RTL819x_5GHZ_5725_5850 \ - REG_RULE(5725-10, 5850+10, 80, 0, 30, 0) - -#define RTL819x_5GHZ_ALL \ - (RTL819x_5GHZ_5150_5350, RTL819x_5GHZ_5470_5850) - -static const struct ieee80211_regdomain rtl_regdom_11 = { - .n_reg_rules = 1, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, - } -}; - -static const struct ieee80211_regdomain rtl_regdom_12_13 = { - .n_reg_rules = 2, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - } -}; - -static const struct ieee80211_regdomain rtl_regdom_no_midband = { - .n_reg_rules = 3, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, - RTL819x_5GHZ_5150_5350, - RTL819x_5GHZ_5725_5850, - } -}; - -static const struct ieee80211_regdomain rtl_regdom_60_64 = { - .n_reg_rules = 3, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - RTL819x_5GHZ_5725_5850, - } -}; - -static const struct ieee80211_regdomain rtl_regdom_14_60_64 = { - .n_reg_rules = 4, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - RTL819x_2GHZ_CH14, - RTL819x_5GHZ_5725_5850, - } -}; - -static const struct ieee80211_regdomain rtl_regdom_12_13_5g_all = { - .n_reg_rules = 4, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - RTL819x_5GHZ_5150_5350, - RTL819x_5GHZ_5470_5850, - } -}; - -static const struct ieee80211_regdomain rtl_regdom_14 = { - .n_reg_rules = 3, - .alpha2 = "99", - .reg_rules = { - RTL819x_2GHZ_CH01_11, - RTL819x_2GHZ_CH12_13, - RTL819x_2GHZ_CH14, - } -}; - -static bool _rtl_is_radar_freq(u16 center_freq) -{ - return center_freq >= 5260 && center_freq <= 5700; -} - -static void _rtl_reg_apply_beaconing_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) -{ - enum ieee80211_band band; - struct ieee80211_supported_band *sband; - const struct ieee80211_reg_rule *reg_rule; - struct ieee80211_channel *ch; - unsigned int i; - - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - - if (!wiphy->bands[band]) - continue; - - sband = wiphy->bands[band]; - - for (i = 0; i < sband->n_channels; i++) { - ch = &sband->channels[i]; - if (_rtl_is_radar_freq(ch->center_freq) || - (ch->flags & IEEE80211_CHAN_RADAR)) - continue; - if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { - reg_rule = freq_reg_info(wiphy, - ch->center_freq); - if (IS_ERR(reg_rule)) - continue; - /* - *If 11d had a rule for this channel ensure - *we enable adhoc/beaconing if it allows us to - *use it. Note that we would have disabled it - *by applying our static world regdomain by - *default during init, prior to calling our - *regulatory_hint(). - */ - - if (!(reg_rule->flags & NL80211_RRF_NO_IBSS)) - ch->flags &= ~IEEE80211_CHAN_NO_IBSS; - if (!(reg_rule->flags & - NL80211_RRF_PASSIVE_SCAN)) - ch->flags &= - ~IEEE80211_CHAN_PASSIVE_SCAN; - } else { - if (ch->beacon_found) - ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN); - } - } - } -} - -/* Allows active scan scan on Ch 12 and 13 */ -static void _rtl_reg_apply_active_scan_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator - initiator) -{ - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - const struct ieee80211_reg_rule *reg_rule; - - if (!wiphy->bands[IEEE80211_BAND_2GHZ]) - return; - sband = wiphy->bands[IEEE80211_BAND_2GHZ]; - - /* - *If no country IE has been received always enable active scan - *on these channels. This is only done for specific regulatory SKUs - */ - if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { - ch = &sband->channels[11]; /* CH 12 */ - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - ch = &sband->channels[12]; /* CH 13 */ - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - return; - } - - /* - *If a country IE has been recieved check its rule for this - *channel first before enabling active scan. The passive scan - *would have been enforced by the initial processing of our - *custom regulatory domain. - */ - - ch = &sband->channels[11]; /* CH 12 */ - reg_rule = freq_reg_info(wiphy, ch->center_freq); - if (!IS_ERR(reg_rule)) { - if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - } - - ch = &sband->channels[12]; /* CH 13 */ - reg_rule = freq_reg_info(wiphy, ch->center_freq); - if (!IS_ERR(reg_rule)) { - if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - } -} - -/* - *Always apply Radar/DFS rules on - *freq range 5260 MHz - 5700 MHz - */ -static void _rtl_reg_apply_radar_flags(struct wiphy *wiphy) -{ - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - unsigned int i; - - if (!wiphy->bands[IEEE80211_BAND_5GHZ]) - return; - - sband = wiphy->bands[IEEE80211_BAND_5GHZ]; - - for (i = 0; i < sband->n_channels; i++) { - ch = &sband->channels[i]; - if (!_rtl_is_radar_freq(ch->center_freq)) - continue; - - /* - *We always enable radar detection/DFS on this - *frequency range. Additionally we also apply on - *this frequency range: - *- If STA mode does not yet have DFS supports disable - * active scanning - *- If adhoc mode does not support DFS yet then disable - * adhoc in the frequency. - *- If AP mode does not yet support radar detection/DFS - *do not allow AP mode - */ - if (!(ch->flags & IEEE80211_CHAN_DISABLED)) - ch->flags |= IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN; - } -} - -static void _rtl_reg_apply_world_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator, - struct rtl_regulatory *reg) -{ - _rtl_reg_apply_beaconing_flags(wiphy, initiator); - _rtl_reg_apply_active_scan_flags(wiphy, initiator); - return; -} - -static void _rtl_dump_channel_map(struct wiphy *wiphy) -{ - enum ieee80211_band band; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - unsigned int i; - - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - if (!wiphy->bands[band]) - continue; - sband = wiphy->bands[band]; - for (i = 0; i < sband->n_channels; i++) - ch = &sband->channels[i]; - } -} - -static int _rtl_reg_notifier_apply(struct wiphy *wiphy, - struct regulatory_request *request, - struct rtl_regulatory *reg) -{ - /* We always apply this */ - _rtl_reg_apply_radar_flags(wiphy); - - switch (request->initiator) { - case NL80211_REGDOM_SET_BY_DRIVER: - case NL80211_REGDOM_SET_BY_CORE: - case NL80211_REGDOM_SET_BY_USER: - break; - case NL80211_REGDOM_SET_BY_COUNTRY_IE: - _rtl_reg_apply_world_flags(wiphy, request->initiator, reg); - break; - } - - _rtl_dump_channel_map(wiphy); - - return 0; -} - -static const struct ieee80211_regdomain *_rtl_regdomain_select( - struct rtl_regulatory *reg) -{ - switch (reg->country_code) { - case COUNTRY_CODE_FCC: - return &rtl_regdom_no_midband; - case COUNTRY_CODE_IC: - return &rtl_regdom_11; - case COUNTRY_CODE_ETSI: - case COUNTRY_CODE_TELEC_NETGEAR: - return &rtl_regdom_60_64; - case COUNTRY_CODE_SPAIN: - case COUNTRY_CODE_FRANCE: - case COUNTRY_CODE_ISRAEL: - case COUNTRY_CODE_WORLD_WIDE_13: - return &rtl_regdom_12_13; - case COUNTRY_CODE_MKK: - case COUNTRY_CODE_MKK1: - case COUNTRY_CODE_TELEC: - case COUNTRY_CODE_MIC: - return &rtl_regdom_14_60_64; - case COUNTRY_CODE_GLOBAL_DOMAIN: - return &rtl_regdom_14; - case COUNTRY_CODE_WORLD_WIDE_13_5G_ALL: - return &rtl_regdom_12_13_5g_all; - default: - return &rtl_regdom_no_midband; - } -} - -static int _rtl_regd_init_wiphy(struct rtl_regulatory *reg, - struct wiphy *wiphy, - void (*reg_notifier)(struct wiphy *wiphy, - struct regulatory_request * - request)) -{ - const struct ieee80211_regdomain *regd; - - wiphy->reg_notifier = reg_notifier; - - wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; - wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG; - wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS; - regd = _rtl_regdomain_select(reg); - wiphy_apply_custom_regulatory(wiphy, regd); - _rtl_reg_apply_radar_flags(wiphy); - _rtl_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); - return 0; -} - -static struct country_code_to_enum_rd *_rtl_regd_find_country(u16 countrycode) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(allCountries); i++) { - if (allCountries[i].countrycode == countrycode) - return &allCountries[i]; - } - return NULL; -} - -static u8 channel_plan_to_country_code(u8 channelplan) -{ - switch (channelplan) { - case 0x20: - case 0x21: - return COUNTRY_CODE_WORLD_WIDE_13; - case 0x22: - return COUNTRY_CODE_IC; - case 0x32: - return COUNTRY_CODE_TELEC_NETGEAR; - case 0x41: - return COUNTRY_CODE_GLOBAL_DOMAIN; - case 0x7f: - return COUNTRY_CODE_WORLD_WIDE_13_5G_ALL; - default: - return COUNTRY_CODE_MAX; /*Error*/ - } -} - -int rtl_regd_init(struct ieee80211_hw *hw, - void (*reg_notifier)(struct wiphy *wiphy, - struct regulatory_request *request)) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct wiphy *wiphy = hw->wiphy; - struct country_code_to_enum_rd *country = NULL; - - if (wiphy == NULL || &rtlpriv->regd == NULL) - return -EINVAL; - - /* init country_code from efuse channel plan */ - rtlpriv->regd.country_code = - channel_plan_to_country_code(rtlpriv->efuse.channel_plan); - - RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG, - "rtl: EEPROM regdomain: 0x%0x conuntry code: %d\n", - rtlpriv->efuse.channel_plan, rtlpriv->regd.country_code); - - if (rtlpriv->regd.country_code >= COUNTRY_CODE_MAX) { - RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG, - "rtl: EEPROM indicates invalid contry code, world wide 13 should be used\n"); - - rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13; - } - - country = _rtl_regd_find_country(rtlpriv->regd.country_code); - - if (country) { - rtlpriv->regd.alpha2[0] = country->iso_name[0]; - rtlpriv->regd.alpha2[1] = country->iso_name[1]; - } else { - rtlpriv->regd.alpha2[0] = '0'; - rtlpriv->regd.alpha2[1] = '0'; - } - - RT_TRACE(rtlpriv, COMP_REGD, DBG_TRACE, - "rtl: Country alpha2 being used: %c%c\n", - rtlpriv->regd.alpha2[0], rtlpriv->regd.alpha2[1]); - - _rtl_regd_init_wiphy(&rtlpriv->regd, wiphy, reg_notifier); - - return 0; -} - -void rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_REGD, DBG_LOUD, "\n"); - - _rtl_reg_notifier_apply(wiphy, request, &rtlpriv->regd); -} diff --git a/drivers/net/wireless/rtlwifi/regd.h b/drivers/net/wireless/rtlwifi/regd.h deleted file mode 100644 index f7f15bce35dd..000000000000 --- a/drivers/net/wireless/rtlwifi/regd.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL_REGD_H__ -#define __RTL_REGD_H__ - -/* for kernel 3.14 , both value are changed to IEEE80211_CHAN_NO_IR*/ -#define IEEE80211_CHAN_NO_IBSS IEEE80211_CHAN_NO_IR -#define IEEE80211_CHAN_PASSIVE_SCAN IEEE80211_CHAN_NO_IR - -struct country_code_to_enum_rd { - u16 countrycode; - const char *iso_name; -}; - -enum country_code_type_t { - COUNTRY_CODE_FCC = 0, - COUNTRY_CODE_IC = 1, - COUNTRY_CODE_ETSI = 2, - COUNTRY_CODE_SPAIN = 3, - COUNTRY_CODE_FRANCE = 4, - COUNTRY_CODE_MKK = 5, - COUNTRY_CODE_MKK1 = 6, - COUNTRY_CODE_ISRAEL = 7, - COUNTRY_CODE_TELEC = 8, - COUNTRY_CODE_MIC = 9, - COUNTRY_CODE_GLOBAL_DOMAIN = 10, - COUNTRY_CODE_WORLD_WIDE_13 = 11, - COUNTRY_CODE_TELEC_NETGEAR = 12, - COUNTRY_CODE_WORLD_WIDE_13_5G_ALL = 13, - - /*add new channel plan above this line */ - COUNTRY_CODE_MAX -}; - -int rtl_regd_init(struct ieee80211_hw *hw, - void (*reg_notifier) (struct wiphy *wiphy, - struct regulatory_request *request)); -void rtl_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile b/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile deleted file mode 100644 index a85419a37651..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -rtl8188ee-objs := \ - dm.o \ - fw.o \ - hw.o \ - led.o \ - phy.o \ - pwrseq.o \ - rf.o \ - sw.o \ - table.o \ - trx.o - -obj-$(CONFIG_RTL8188EE) += rtl8188ee.o - -ccflags-y += -Idrivers/net/wireless/rtlwifi -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/def.h b/drivers/net/wireless/rtlwifi/rtl8188ee/def.h deleted file mode 100644 index 0532b9852444..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/def.h +++ /dev/null @@ -1,269 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_DEF_H__ -#define __RTL92C_DEF_H__ - -#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 -#define HAL_PRIME_CHNL_OFFSET_LOWER 1 -#define HAL_PRIME_CHNL_OFFSET_UPPER 2 - -#define RX_MPDU_QUEUE 0 -#define RX_CMD_QUEUE 1 - -#define C2H_RX_CMD_HDR_LEN 8 -#define GET_C2H_CMD_CMD_LEN(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 0, 16) -#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 16, 8) -#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 24, 7) -#define GET_C2H_CMD_CONTINUE(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 31, 1) -#define GET_C2H_CMD_CONTENT(__prxhdr) \ - ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) - -#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) -#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) -#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) -#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) -#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) -#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) -#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) -#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) -#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) - -#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) - -/* [15:12] IC version(CUT): A-cut=0, B-cut=1, C-cut=2, D-cut=3 - * [7] Manufacturer: TSMC=0, UMC=1 - * [6:4] RF type: 1T1R=0, 1T2R=1, 2T2R=2 - * [3] Chip type: TEST=0, NORMAL=1 - * [2:0] IC type: 81xxC=0, 8723=1, 92D=2 - */ -#define CHIP_8723 BIT(0) -#define CHIP_92D BIT(1) -#define NORMAL_CHIP BIT(3) -#define RF_TYPE_1T1R (~(BIT(4)|BIT(5)|BIT(6))) -#define RF_TYPE_1T2R BIT(4) -#define RF_TYPE_2T2R BIT(5) -#define CHIP_VENDOR_UMC BIT(7) -#define B_CUT_VERSION BIT(12) -#define C_CUT_VERSION BIT(13) -#define D_CUT_VERSION ((BIT(12)|BIT(13))) -#define E_CUT_VERSION BIT(14) - -/* MASK */ -#define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2)) -#define CHIP_TYPE_MASK BIT(3) -#define RF_TYPE_MASK (BIT(4)|BIT(5)|BIT(6)) -#define MANUFACTUER_MASK BIT(7) -#define ROM_VERSION_MASK (BIT(11)|BIT(10)|BIT(9)|BIT(8)) -#define CUT_VERSION_MASK (BIT(15)|BIT(14)|BIT(13)|BIT(12)) - -/* Get element */ -#define GET_CVID_IC_TYPE(version) ((version) & IC_TYPE_MASK) -#define GET_CVID_CHIP_TYPE(version) ((version) & CHIP_TYPE_MASK) -#define GET_CVID_RF_TYPE(version) ((version) & RF_TYPE_MASK) -#define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK) -#define GET_CVID_ROM_VERSION(version) ((version) & ROM_VERSION_MASK) -#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK) - -#define IS_81XXC(version) \ - ((GET_CVID_IC_TYPE(version) == 0) ? true : false) -#define IS_8723_SERIES(version) \ - ((GET_CVID_IC_TYPE(version) == CHIP_8723) ? true : false) -#define IS_92D(version) \ - ((GET_CVID_IC_TYPE(version) == CHIP_92D) ? true : false) - -#define IS_NORMAL_CHIP(version) \ - ((GET_CVID_CHIP_TYPE(version)) ? true : false) -#define IS_NORMAL_CHIP92D(version) \ - ((GET_CVID_CHIP_TYPE(version)) ? true : false) - -#define IS_1T1R(version) \ - ((GET_CVID_RF_TYPE(version)) ? false : true) -#define IS_1T2R(version) \ - ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R) ? true : false) -#define IS_2T2R(version) \ - ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R) ? true : false) -#define IS_CHIP_VENDOR_UMC(version) \ - ((GET_CVID_MANUFACTUER(version)) ? true : false) - -#define IS_92C_SERIAL(version) \ - ((IS_81XXC(version) && IS_2T2R(version)) ? true : false) -#define IS_81xxC_VENDOR_UMC_A_CUT(version) \ - (IS_81XXC(version) ? ((IS_CHIP_VENDOR_UMC(version)) ? \ - ((GET_CVID_CUT_VERSION(version)) ? false : true) : false) : false) -#define IS_81XXC_VENDOR_UMC_B_CUT(version) \ - (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \ - ((GET_CVID_CUT_VERSION(version) == B_CUT_VERSION) ? true \ - : false) : false) : false) - -enum version_8188e { - VERSION_TEST_CHIP_88E = 0x00, - VERSION_NORMAL_CHIP_88E = 0x01, - VERSION_UNKNOWN = 0xFF, -}; - -enum rx_packet_type { - NORMAL_RX, - TX_REPORT1, - TX_REPORT2, - HIS_REPORT, -}; - -enum rtl819x_loopback_e { - RTL819X_NO_LOOPBACK = 0, - RTL819X_MAC_LOOPBACK = 1, - RTL819X_DMA_LOOPBACK = 2, - RTL819X_CCK_LOOPBACK = 3, -}; - -enum rf_optype { - RF_OP_BY_SW_3WIRE = 0, - RF_OP_BY_FW, - RF_OP_MAX -}; - -enum rf_power_state { - RF_ON, - RF_OFF, - RF_SLEEP, - RF_SHUT_DOWN, -}; - -enum power_save_mode { - POWER_SAVE_MODE_ACTIVE, - POWER_SAVE_MODE_SAVE, -}; - -enum power_polocy_config { - POWERCFG_MAX_POWER_SAVINGS, - POWERCFG_GLOBAL_POWER_SAVINGS, - POWERCFG_LOCAL_POWER_SAVINGS, - POWERCFG_LENOVO, -}; - -enum interface_select_pci { - INTF_SEL1_MINICARD = 0, - INTF_SEL0_PCIE = 1, - INTF_SEL2_RSV = 2, - INTF_SEL3_RSV = 3, -}; - -enum hal_fw_c2h_cmd_id { - HAL_FW_C2H_CMD_READ_MACREG = 0, - HAL_FW_C2H_CMD_READ_BBREG = 1, - HAL_FW_C2H_CMD_READ_RFREG = 2, - HAL_FW_C2H_CMD_READ_EEPROM = 3, - HAL_FW_C2H_CMD_READ_EFUSE = 4, - HAL_FW_C2H_CMD_READ_CAM = 5, - HAL_FW_C2H_CMD_GET_BASICRATE = 6, - HAL_FW_C2H_CMD_GET_DATARATE = 7, - HAL_FW_C2H_CMD_SURVEY = 8, - HAL_FW_C2H_CMD_SURVEYDONE = 9, - HAL_FW_C2H_CMD_JOINBSS = 10, - HAL_FW_C2H_CMD_ADDSTA = 11, - HAL_FW_C2H_CMD_DELSTA = 12, - HAL_FW_C2H_CMD_ATIMDONE = 13, - HAL_FW_C2H_CMD_TX_REPORT = 14, - HAL_FW_C2H_CMD_CCX_REPORT = 15, - HAL_FW_C2H_CMD_DTM_REPORT = 16, - HAL_FW_C2H_CMD_TX_RATE_STATISTICS = 17, - HAL_FW_C2H_CMD_C2HLBK = 18, - HAL_FW_C2H_CMD_C2HDBG = 19, - HAL_FW_C2H_CMD_C2HFEEDBACK = 20, - HAL_FW_C2H_CMD_MAX -}; - -enum rtl_desc_qsel { - QSLT_BK = 0x2, - QSLT_BE = 0x0, - QSLT_VI = 0x5, - QSLT_VO = 0x7, - QSLT_BEACON = 0x10, - QSLT_HIGH = 0x11, - QSLT_MGNT = 0x12, - QSLT_CMD = 0x13, -}; - -enum rtl_desc92c_rate { - DESC92C_RATE1M = 0x00, - DESC92C_RATE2M = 0x01, - DESC92C_RATE5_5M = 0x02, - DESC92C_RATE11M = 0x03, - - DESC92C_RATE6M = 0x04, - DESC92C_RATE9M = 0x05, - DESC92C_RATE12M = 0x06, - DESC92C_RATE18M = 0x07, - DESC92C_RATE24M = 0x08, - DESC92C_RATE36M = 0x09, - DESC92C_RATE48M = 0x0a, - DESC92C_RATE54M = 0x0b, - - DESC92C_RATEMCS0 = 0x0c, - DESC92C_RATEMCS1 = 0x0d, - DESC92C_RATEMCS2 = 0x0e, - DESC92C_RATEMCS3 = 0x0f, - DESC92C_RATEMCS4 = 0x10, - DESC92C_RATEMCS5 = 0x11, - DESC92C_RATEMCS6 = 0x12, - DESC92C_RATEMCS7 = 0x13, - DESC92C_RATEMCS8 = 0x14, - DESC92C_RATEMCS9 = 0x15, - DESC92C_RATEMCS10 = 0x16, - DESC92C_RATEMCS11 = 0x17, - DESC92C_RATEMCS12 = 0x18, - DESC92C_RATEMCS13 = 0x19, - DESC92C_RATEMCS14 = 0x1a, - DESC92C_RATEMCS15 = 0x1b, - DESC92C_RATEMCS15_SG = 0x1c, - DESC92C_RATEMCS32 = 0x20, -}; - -struct phy_sts_cck_8192s_t { - u8 adc_pwdb_X[4]; - u8 sq_rpt; - u8 cck_agc_rpt; -}; - -struct h2c_cmd_8192c { - u8 element_id; - u32 cmd_len; - u8 *p_cmdbuffer; -}; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c deleted file mode 100644 index ce4da9d79fbd..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.c +++ /dev/null @@ -1,1805 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../base.h" -#include "../pci.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "fw.h" -#include "trx.h" - -static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { - 0x7f8001fe, /* 0, +6.0dB */ - 0x788001e2, /* 1, +5.5dB */ - 0x71c001c7, /* 2, +5.0dB */ - 0x6b8001ae, /* 3, +4.5dB */ - 0x65400195, /* 4, +4.0dB */ - 0x5fc0017f, /* 5, +3.5dB */ - 0x5a400169, /* 6, +3.0dB */ - 0x55400155, /* 7, +2.5dB */ - 0x50800142, /* 8, +2.0dB */ - 0x4c000130, /* 9, +1.5dB */ - 0x47c0011f, /* 10, +1.0dB */ - 0x43c0010f, /* 11, +0.5dB */ - 0x40000100, /* 12, +0dB */ - 0x3c8000f2, /* 13, -0.5dB */ - 0x390000e4, /* 14, -1.0dB */ - 0x35c000d7, /* 15, -1.5dB */ - 0x32c000cb, /* 16, -2.0dB */ - 0x300000c0, /* 17, -2.5dB */ - 0x2d4000b5, /* 18, -3.0dB */ - 0x2ac000ab, /* 19, -3.5dB */ - 0x288000a2, /* 20, -4.0dB */ - 0x26000098, /* 21, -4.5dB */ - 0x24000090, /* 22, -5.0dB */ - 0x22000088, /* 23, -5.5dB */ - 0x20000080, /* 24, -6.0dB */ - 0x1e400079, /* 25, -6.5dB */ - 0x1c800072, /* 26, -7.0dB */ - 0x1b00006c, /* 27. -7.5dB */ - 0x19800066, /* 28, -8.0dB */ - 0x18000060, /* 29, -8.5dB */ - 0x16c0005b, /* 30, -9.0dB */ - 0x15800056, /* 31, -9.5dB */ - 0x14400051, /* 32, -10.0dB */ - 0x1300004c, /* 33, -10.5dB */ - 0x12000048, /* 34, -11.0dB */ - 0x11000044, /* 35, -11.5dB */ - 0x10000040, /* 36, -12.0dB */ - 0x0f00003c, /* 37, -12.5dB */ - 0x0e400039, /* 38, -13.0dB */ - 0x0d800036, /* 39, -13.5dB */ - 0x0cc00033, /* 40, -14.0dB */ - 0x0c000030, /* 41, -14.5dB */ - 0x0b40002d, /* 42, -15.0dB */ -}; - -static const u8 cck_tbl_ch1_13[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB*/ - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB*/ - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB*/ - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB*/ - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB*/ - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB*/ - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB*/ - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB*/ - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB*/ - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB*/ - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB*/ - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB*/ - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB*/ -}; - -static const u8 cck_tbl_ch14[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */ - {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB*/ - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB*/ - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB*/ - {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB*/ - {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB*/ - {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB*/ - {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB*/ - {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB*/ - {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB*/ - {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB*/ - {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB*/ - {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB*/ - {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB*/ -}; - -#define CAL_SWING_OFF(_off, _dir, _size, _del) \ - do { \ - for (_off = 0; _off < _size; _off++) { \ - if (_del < thermal_threshold[_dir][_off]) { \ - if (_off != 0) \ - _off--; \ - break; \ - } \ - } \ - if (_off >= _size) \ - _off = _size - 1; \ - } while (0) - -static void rtl88e_set_iqk_matrix(struct ieee80211_hw *hw, - u8 ofdm_index, u8 rfpath, - long iqk_result_x, long iqk_result_y) -{ - long ele_a = 0, ele_d, ele_c = 0, value32; - - ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000)>>22; - - if (iqk_result_x != 0) { - if ((iqk_result_x & 0x00000200) != 0) - iqk_result_x = iqk_result_x | 0xFFFFFC00; - ele_a = ((iqk_result_x * ele_d)>>8)&0x000003FF; - - if ((iqk_result_y & 0x00000200) != 0) - iqk_result_y = iqk_result_y | 0xFFFFFC00; - ele_c = ((iqk_result_y * ele_d)>>8)&0x000003FF; - - switch (rfpath) { - case RF90_PATH_A: - value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a; - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, - MASKDWORD, value32); - value32 = (ele_c & 0x000003C0) >> 6; - rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, - value32); - value32 = ((iqk_result_x * ele_d) >> 7) & 0x01; - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), - value32); - break; - case RF90_PATH_B: - value32 = (ele_d << 22)|((ele_c & 0x3F)<<16) | ele_a; - rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, MASKDWORD, - value32); - value32 = (ele_c & 0x000003C0) >> 6; - rtl_set_bbreg(hw, ROFDM0_XDTXAFE, MASKH4BITS, value32); - value32 = ((iqk_result_x * ele_d) >> 7) & 0x01; - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28), - value32); - break; - default: - break; - } - } else { - switch (rfpath) { - case RF90_PATH_A: - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, - MASKDWORD, ofdmswing_table[ofdm_index]); - rtl_set_bbreg(hw, ROFDM0_XCTXAFE, - MASKH4BITS, 0x00); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, - BIT(24), 0x00); - break; - case RF90_PATH_B: - rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, - MASKDWORD, ofdmswing_table[ofdm_index]); - rtl_set_bbreg(hw, ROFDM0_XDTXAFE, - MASKH4BITS, 0x00); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, - BIT(28), 0x00); - break; - default: - break; - } - } -} - -void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw, - u8 type, u8 *pdirection, u32 *poutwrite_val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - u8 pwr_val = 0; - u8 cck_base = rtldm->swing_idx_cck_base; - u8 cck_val = rtldm->swing_idx_cck; - u8 ofdm_base = rtldm->swing_idx_ofdm_base[0]; - u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A]; - - if (type == 0) { - if (ofdm_val <= ofdm_base) { - *pdirection = 1; - pwr_val = ofdm_base - ofdm_val; - } else { - *pdirection = 2; - pwr_val = ofdm_base - ofdm_val; - } - } else if (type == 1) { - if (cck_val <= cck_base) { - *pdirection = 1; - pwr_val = cck_base - cck_val; - } else { - *pdirection = 2; - pwr_val = cck_val - cck_base; - } - } - - if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1)) - pwr_val = TXPWRTRACK_MAX_IDX; - - *poutwrite_val = pwr_val | (pwr_val << 8) | (pwr_val << 16) | - (pwr_val << 24); -} - -static void dm_tx_pwr_track_set_pwr(struct ieee80211_hw *hw, - enum pwr_track_control_method method, - u8 rfpath, u8 channel_mapped_index) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - - if (method == TXAGC) { - if (rtldm->swing_flag_ofdm || - rtldm->swing_flag_cck) { - rtl88e_phy_set_txpower_level(hw, - rtlphy->current_channel); - rtldm->swing_flag_ofdm = false; - rtldm->swing_flag_cck = false; - } - } else if (method == BBSWING) { - if (!rtldm->cck_inch14) { - rtl_write_byte(rtlpriv, 0xa22, - cck_tbl_ch1_13[rtldm->swing_idx_cck][0]); - rtl_write_byte(rtlpriv, 0xa23, - cck_tbl_ch1_13[rtldm->swing_idx_cck][1]); - rtl_write_byte(rtlpriv, 0xa24, - cck_tbl_ch1_13[rtldm->swing_idx_cck][2]); - rtl_write_byte(rtlpriv, 0xa25, - cck_tbl_ch1_13[rtldm->swing_idx_cck][3]); - rtl_write_byte(rtlpriv, 0xa26, - cck_tbl_ch1_13[rtldm->swing_idx_cck][4]); - rtl_write_byte(rtlpriv, 0xa27, - cck_tbl_ch1_13[rtldm->swing_idx_cck][5]); - rtl_write_byte(rtlpriv, 0xa28, - cck_tbl_ch1_13[rtldm->swing_idx_cck][6]); - rtl_write_byte(rtlpriv, 0xa29, - cck_tbl_ch1_13[rtldm->swing_idx_cck][7]); - } else { - rtl_write_byte(rtlpriv, 0xa22, - cck_tbl_ch14[rtldm->swing_idx_cck][0]); - rtl_write_byte(rtlpriv, 0xa23, - cck_tbl_ch14[rtldm->swing_idx_cck][1]); - rtl_write_byte(rtlpriv, 0xa24, - cck_tbl_ch14[rtldm->swing_idx_cck][2]); - rtl_write_byte(rtlpriv, 0xa25, - cck_tbl_ch14[rtldm->swing_idx_cck][3]); - rtl_write_byte(rtlpriv, 0xa26, - cck_tbl_ch14[rtldm->swing_idx_cck][4]); - rtl_write_byte(rtlpriv, 0xa27, - cck_tbl_ch14[rtldm->swing_idx_cck][5]); - rtl_write_byte(rtlpriv, 0xa28, - cck_tbl_ch14[rtldm->swing_idx_cck][6]); - rtl_write_byte(rtlpriv, 0xa29, - cck_tbl_ch14[rtldm->swing_idx_cck][7]); - } - - if (rfpath == RF90_PATH_A) { - rtl88e_set_iqk_matrix(hw, rtldm->swing_idx_ofdm[rfpath], - rfpath, rtlphy->iqk_matrix - [channel_mapped_index]. - value[0][0], - rtlphy->iqk_matrix - [channel_mapped_index]. - value[0][1]); - } else if (rfpath == RF90_PATH_B) { - rtl88e_set_iqk_matrix(hw, rtldm->swing_idx_ofdm[rfpath], - rfpath, rtlphy->iqk_matrix - [channel_mapped_index]. - value[0][4], - rtlphy->iqk_matrix - [channel_mapped_index]. - value[0][5]); - } - } else { - return; - } -} - -static u8 rtl88e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_dig = &rtlpriv->dm_digtable; - long rssi_val_min = 0; - - if ((dm_dig->curmultista_cstate == DIG_MULTISTA_CONNECT) && - (dm_dig->cur_sta_cstate == DIG_STA_CONNECT)) { - if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0) - rssi_val_min = - (rtlpriv->dm.entry_min_undec_sm_pwdb > - rtlpriv->dm.undec_sm_pwdb) ? - rtlpriv->dm.undec_sm_pwdb : - rtlpriv->dm.entry_min_undec_sm_pwdb; - else - rssi_val_min = rtlpriv->dm.undec_sm_pwdb; - } else if (dm_dig->cur_sta_cstate == DIG_STA_CONNECT || - dm_dig->cur_sta_cstate == DIG_STA_BEFORE_CONNECT) { - rssi_val_min = rtlpriv->dm.undec_sm_pwdb; - } else if (dm_dig->curmultista_cstate == - DIG_MULTISTA_CONNECT) { - rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb; - } - - return (u8)rssi_val_min; -} - -static void rtl88e_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) -{ - u32 ret_value; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt; - - rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1); - rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1); - - ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD); - falsealm_cnt->cnt_fast_fsync_fail = (ret_value&0xffff); - falsealm_cnt->cnt_sb_search_fail = ((ret_value&0xffff0000)>>16); - - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); - falsealm_cnt->cnt_ofdm_cca = (ret_value&0xffff); - falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); - - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); - falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); - falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); - - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); - falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); - falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + - falsealm_cnt->cnt_mcs_fail + - falsealm_cnt->cnt_fast_fsync_fail + - falsealm_cnt->cnt_sb_search_fail; - - ret_value = rtl_get_bbreg(hw, REG_SC_CNT, MASKDWORD); - falsealm_cnt->cnt_bw_lsc = (ret_value & 0xffff); - falsealm_cnt->cnt_bw_usc = ((ret_value & 0xffff0000) >> 16); - - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(12), 1); - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1); - - ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); - falsealm_cnt->cnt_cck_fail = ret_value; - - ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3); - falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; - - ret_value = rtl_get_bbreg(hw, RCCK0_CCA_CNT, MASKDWORD); - falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) | - ((ret_value&0xFF00)>>8); - - falsealm_cnt->cnt_all = (falsealm_cnt->cnt_fast_fsync_fail + - falsealm_cnt->cnt_sb_search_fail + - falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + - falsealm_cnt->cnt_mcs_fail + - falsealm_cnt->cnt_cck_fail); - falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca + - falsealm_cnt->cnt_cck_cca; - - rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 1); - rtl_set_bbreg(hw, ROFDM0_TRSWISOLATION, BIT(31), 0); - rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 1); - rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(27), 0); - rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0); - rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0); - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 0); - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(13)|BIT(12), 2); - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 0); - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(15)|BIT(14), 2); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", - falsealm_cnt->cnt_parity_fail, - falsealm_cnt->cnt_rate_illegal, - falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", - falsealm_cnt->cnt_ofdm_fail, - falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all); -} - -static void rtl88e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_dig = &rtlpriv->dm_digtable; - u8 cur_cck_cca_thresh; - - if (dm_dig->cur_sta_cstate == DIG_STA_CONNECT) { - dm_dig->rssi_val_min = rtl88e_dm_initial_gain_min_pwdb(hw); - if (dm_dig->rssi_val_min > 25) { - cur_cck_cca_thresh = 0xcd; - } else if ((dm_dig->rssi_val_min <= 25) && - (dm_dig->rssi_val_min > 10)) { - cur_cck_cca_thresh = 0x83; - } else { - if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) - cur_cck_cca_thresh = 0x83; - else - cur_cck_cca_thresh = 0x40; - } - - } else { - if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) - cur_cck_cca_thresh = 0x83; - else - cur_cck_cca_thresh = 0x40; - } - - if (dm_dig->cur_cck_cca_thres != cur_cck_cca_thresh) - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh); - - dm_dig->cur_cck_cca_thres = cur_cck_cca_thresh; - dm_dig->pre_cck_cca_thres = dm_dig->cur_cck_cca_thres; - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "CCK cca thresh hold =%x\n", dm_dig->cur_cck_cca_thres); -} - -static void rtl88e_dm_dig(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct dig_t *dm_dig = &rtlpriv->dm_digtable; - u8 dig_dynamic_min, dig_maxofmin; - bool bfirstconnect; - u8 dm_dig_max, dm_dig_min; - u8 current_igi = dm_dig->cur_igvalue; - - if (rtlpriv->dm.dm_initialgain_enable == false) - return; - if (dm_dig->dig_enable_flag == false) - return; - if (mac->act_scanning == true) - return; - - if (mac->link_state >= MAC80211_LINKED) - dm_dig->cur_sta_cstate = DIG_STA_CONNECT; - else - dm_dig->cur_sta_cstate = DIG_STA_DISCONNECT; - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || - rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) - dm_dig->cur_sta_cstate = DIG_STA_DISCONNECT; - - dm_dig_max = DM_DIG_MAX; - dm_dig_min = DM_DIG_MIN; - dig_maxofmin = DM_DIG_MAX_AP; - dig_dynamic_min = dm_dig->dig_min_0; - bfirstconnect = ((mac->link_state >= MAC80211_LINKED) ? true : false) && - !dm_dig->media_connect_0; - - dm_dig->rssi_val_min = - rtl88e_dm_initial_gain_min_pwdb(hw); - - if (mac->link_state >= MAC80211_LINKED) { - if ((dm_dig->rssi_val_min + 20) > dm_dig_max) - dm_dig->rx_gain_max = dm_dig_max; - else if ((dm_dig->rssi_val_min + 20) < dm_dig_min) - dm_dig->rx_gain_max = dm_dig_min; - else - dm_dig->rx_gain_max = dm_dig->rssi_val_min + 20; - - if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) { - dig_dynamic_min = dm_dig->antdiv_rssi_max; - } else { - if (dm_dig->rssi_val_min < dm_dig_min) - dig_dynamic_min = dm_dig_min; - else if (dm_dig->rssi_val_min < dig_maxofmin) - dig_dynamic_min = dig_maxofmin; - else - dig_dynamic_min = dm_dig->rssi_val_min; - } - } else { - dm_dig->rx_gain_max = dm_dig_max; - dig_dynamic_min = dm_dig_min; - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n"); - } - - if (rtlpriv->falsealm_cnt.cnt_all > 10000) { - dm_dig->large_fa_hit++; - if (dm_dig->forbidden_igi < current_igi) { - dm_dig->forbidden_igi = current_igi; - dm_dig->large_fa_hit = 1; - } - - if (dm_dig->large_fa_hit >= 3) { - if ((dm_dig->forbidden_igi + 1) > - dm_dig->rx_gain_max) - dm_dig->rx_gain_min = - dm_dig->rx_gain_max; - else - dm_dig->rx_gain_min = - dm_dig->forbidden_igi + 1; - dm_dig->recover_cnt = 3600; - } - } else { - if (dm_dig->recover_cnt != 0) { - dm_dig->recover_cnt--; - } else { - if (dm_dig->large_fa_hit == 0) { - if ((dm_dig->forbidden_igi - 1) < - dig_dynamic_min) { - dm_dig->forbidden_igi = dig_dynamic_min; - dm_dig->rx_gain_min = dig_dynamic_min; - } else { - dm_dig->forbidden_igi--; - dm_dig->rx_gain_min = - dm_dig->forbidden_igi + 1; - } - } else if (dm_dig->large_fa_hit == 3) { - dm_dig->large_fa_hit = 0; - } - } - } - - if (dm_dig->cur_sta_cstate == DIG_STA_CONNECT) { - if (bfirstconnect) { - current_igi = dm_dig->rssi_val_min; - } else { - if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2) - current_igi += 2; - else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1) - current_igi++; - else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) - current_igi--; - } - } else { - if (rtlpriv->falsealm_cnt.cnt_all > 10000) - current_igi += 2; - else if (rtlpriv->falsealm_cnt.cnt_all > 8000) - current_igi++; - else if (rtlpriv->falsealm_cnt.cnt_all < 500) - current_igi--; - } - - if (current_igi > DM_DIG_FA_UPPER) - current_igi = DM_DIG_FA_UPPER; - else if (current_igi < DM_DIG_FA_LOWER) - current_igi = DM_DIG_FA_LOWER; - - if (rtlpriv->falsealm_cnt.cnt_all > 10000) - current_igi = DM_DIG_FA_UPPER; - - dm_dig->cur_igvalue = current_igi; - rtl88e_dm_write_dig(hw); - dm_dig->media_connect_0 = - ((mac->link_state >= MAC80211_LINKED) ? true : false); - dm_dig->dig_min_0 = dig_dynamic_min; - - rtl88e_dm_cck_packet_detection_thresh(hw); -} - -static void rtl88e_dm_init_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.dynamic_txpower_enable = false; - - rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; -} - -static void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long undec_sm_pwdb; - - if (!rtlpriv->dm.dynamic_txpower_enable) - return; - - if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - - if ((mac->link_state < MAC80211_LINKED) && - (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "Not connected to any\n"); - - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - - rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - - if (mac->link_state >= MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - undec_sm_pwdb = - rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Client PWDB = 0x%lx\n", - undec_sm_pwdb); - } else { - undec_sm_pwdb = - rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "STA Default Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - } else { - undec_sm_pwdb = - rtlpriv->dm.entry_min_undec_sm_pwdb; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Ext Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - - if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x0)\n"); - } else if ((undec_sm_pwdb < - (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && - (undec_sm_pwdb >= - TX_POWER_NEAR_FIELD_THRESH_LVL1)) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_LEVEL1 (TxPwr = 0x10)\n"); - } else if (undec_sm_pwdb < - (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_NORMAL\n"); - } - - if ((rtlpriv->dm.dynamic_txhighpower_lvl != - rtlpriv->dm.last_dtp_lvl)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "PHY_SetTxPowerLevel8192S() Channel = %d\n", - rtlphy->current_channel); - rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel); - } - - rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; -} - -void rtl88e_dm_write_dig(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_dig = &rtlpriv->dm_digtable; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "cur_igvalue = 0x%x, pre_igvalue = 0x%x, backoff_val = %d\n", - dm_dig->cur_igvalue, dm_dig->pre_igvalue, - dm_dig->back_val); - - if (dm_dig->cur_igvalue > 0x3f) - dm_dig->cur_igvalue = 0x3f; - if (dm_dig->pre_igvalue != dm_dig->cur_igvalue) { - rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, - dm_dig->cur_igvalue); - - dm_dig->pre_igvalue = dm_dig->cur_igvalue; - } -} - -static void rtl88e_dm_pwdb_monitor(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_sta_info *drv_priv; - static u64 last_record_txok_cnt; - static u64 last_record_rxok_cnt; - long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff; - - if (rtlhal->oem_id == RT_CID_819X_HP) { - u64 cur_txok_cnt = 0; - u64 cur_rxok_cnt = 0; - cur_txok_cnt = rtlpriv->stats.txbytesunicast - - last_record_txok_cnt; - cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - - last_record_rxok_cnt; - last_record_txok_cnt = cur_txok_cnt; - last_record_rxok_cnt = cur_rxok_cnt; - - if (cur_rxok_cnt > (cur_txok_cnt * 6)) - rtl_write_dword(rtlpriv, REG_ARFR0, 0x8f015); - else - rtl_write_dword(rtlpriv, REG_ARFR0, 0xff015); - } - - /* AP & ADHOC & MESH */ - spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { - if (drv_priv->rssi_stat.undec_sm_pwdb < - tmp_entry_min_pwdb) - tmp_entry_min_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; - if (drv_priv->rssi_stat.undec_sm_pwdb > - tmp_entry_max_pwdb) - tmp_entry_max_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; - } - spin_unlock_bh(&rtlpriv->locks.entry_list_lock); - - /* If associated entry is found */ - if (tmp_entry_max_pwdb != 0) { - rtlpriv->dm.entry_max_undec_sm_pwdb = tmp_entry_max_pwdb; - RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMaxPWDB = 0x%lx(%ld)\n", - tmp_entry_max_pwdb, tmp_entry_max_pwdb); - } else { - rtlpriv->dm.entry_max_undec_sm_pwdb = 0; - } - /* If associated entry is found */ - if (tmp_entry_min_pwdb != 0xff) { - rtlpriv->dm.entry_min_undec_sm_pwdb = tmp_entry_min_pwdb; - RTPRINT(rtlpriv, FDM, DM_PWDB, "EntryMinPWDB = 0x%lx(%ld)\n", - tmp_entry_min_pwdb, tmp_entry_min_pwdb); - } else { - rtlpriv->dm.entry_min_undec_sm_pwdb = 0; - } - /* Indicate Rx signal strength to FW. */ - if (rtlpriv->dm.useramask) { - u8 h2c_parameter[3] = { 0 }; - - h2c_parameter[2] = (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF); - h2c_parameter[0] = 0x20; - } else { - rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb); - } -} - -void rtl88e_dm_init_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.current_turbo_edca = false; - rtlpriv->dm.is_any_nonbepkts = false; - rtlpriv->dm.is_cur_rdlstate = false; -} - -static void rtl88e_dm_check_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - static u64 last_txok_cnt; - static u64 last_rxok_cnt; - static u32 last_bt_edca_ul; - static u32 last_bt_edca_dl; - u64 cur_txok_cnt = 0; - u64 cur_rxok_cnt = 0; - u32 edca_be_ul = 0x5ea42b; - u32 edca_be_dl = 0x5ea42b; - bool bt_change_edca = false; - - if ((last_bt_edca_ul != rtlpriv->btcoexist.bt_edca_ul) || - (last_bt_edca_dl != rtlpriv->btcoexist.bt_edca_dl)) { - rtlpriv->dm.current_turbo_edca = false; - last_bt_edca_ul = rtlpriv->btcoexist.bt_edca_ul; - last_bt_edca_dl = rtlpriv->btcoexist.bt_edca_dl; - } - - if (rtlpriv->btcoexist.bt_edca_ul != 0) { - edca_be_ul = rtlpriv->btcoexist.bt_edca_ul; - bt_change_edca = true; - } - - if (rtlpriv->btcoexist.bt_edca_dl != 0) { - edca_be_ul = rtlpriv->btcoexist.bt_edca_dl; - bt_change_edca = true; - } - - if (mac->link_state != MAC80211_LINKED) { - rtlpriv->dm.current_turbo_edca = false; - return; - } - if ((bt_change_edca) || - ((!rtlpriv->dm.is_any_nonbepkts) && - (!rtlpriv->dm.disable_framebursting))) { - - cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; - cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; - - if (cur_rxok_cnt > 4 * cur_txok_cnt) { - if (!rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { - rtl_write_dword(rtlpriv, - REG_EDCA_BE_PARAM, - edca_be_dl); - rtlpriv->dm.is_cur_rdlstate = true; - } - } else { - if (rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { - rtl_write_dword(rtlpriv, - REG_EDCA_BE_PARAM, - edca_be_ul); - rtlpriv->dm.is_cur_rdlstate = false; - } - } - rtlpriv->dm.current_turbo_edca = true; - } else { - if (rtlpriv->dm.current_turbo_edca) { - u8 tmp = AC0_BE; - - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AC_PARAM, - &tmp); - rtlpriv->dm.current_turbo_edca = false; - } - } - - rtlpriv->dm.is_any_nonbepkts = false; - last_txok_cnt = rtlpriv->stats.txbytesunicast; - last_rxok_cnt = rtlpriv->stats.rxbytesunicast; -} - -static void dm_txpower_track_cb_therm(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 thermalvalue = 0, delta, delta_lck, delta_iqk, offset; - u8 thermalvalue_avg_count = 0; - u32 thermalvalue_avg = 0; - long ele_d, temp_cck; - char ofdm_index[2], cck_index = 0, - ofdm_index_old[2] = {0, 0}, cck_index_old = 0; - int i = 0; - /*bool is2t = false;*/ - - u8 ofdm_min_index = 6, rf = 1; - /*u8 index_for_channel;*/ - enum _power_dec_inc {power_dec, power_inc}; - - /*0.1 the following TWO tables decide the - *final index of OFDM/CCK swing table - */ - char delta_swing_table_idx[2][15] = { - {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11}, - {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10} - }; - u8 thermal_threshold[2][15] = { - {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27}, - {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25} - }; - - /*Initilization (7 steps in total) */ - rtlpriv->dm.txpower_trackinginit = true; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "dm_txpower_track_cb_therm\n"); - - thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, - 0xfc00); - if (!thermalvalue) - return; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n", - thermalvalue, rtlpriv->dm.thermalvalue, - rtlefuse->eeprom_thermalmeter); - - /*1. Query OFDM Default Setting: Path A*/ - ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD) & - MASKOFDM_D; - for (i = 0; i < OFDM_TABLE_LENGTH; i++) { - if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { - ofdm_index_old[0] = (u8)i; - rtldm->swing_idx_ofdm_base[RF90_PATH_A] = (u8)i; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index = 0x%x\n", - ROFDM0_XATXIQIMBALANCE, - ele_d, ofdm_index_old[0]); - break; - } - } - - /*2.Query CCK default setting From 0xa24*/ - temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK; - for (i = 0; i < CCK_TABLE_LENGTH; i++) { - if (rtlpriv->dm.cck_inch14) { - if (memcmp(&temp_cck, &cck_tbl_ch14[i][2], 4) == 0) { - cck_index_old = (u8)i; - rtldm->swing_idx_cck_base = (u8)i; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, - DBG_LOUD, - "Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch 14 %d\n", - RCCK0_TXFILTER2, temp_cck, - cck_index_old, - rtlpriv->dm.cck_inch14); - break; - } - } else { - if (memcmp(&temp_cck, &cck_tbl_ch1_13[i][2], 4) == 0) { - cck_index_old = (u8)i; - rtldm->swing_idx_cck_base = (u8)i; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, - DBG_LOUD, - "Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch14 %d\n", - RCCK0_TXFILTER2, temp_cck, - cck_index_old, - rtlpriv->dm.cck_inch14); - break; - } - } - } - - /*3 Initialize ThermalValues of RFCalibrateInfo*/ - if (!rtldm->thermalvalue) { - rtlpriv->dm.thermalvalue = rtlefuse->eeprom_thermalmeter; - rtlpriv->dm.thermalvalue_lck = thermalvalue; - rtlpriv->dm.thermalvalue_iqk = thermalvalue; - for (i = 0; i < rf; i++) - rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; - rtlpriv->dm.cck_index = cck_index_old; - } - - /*4 Calculate average thermal meter*/ - rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue; - rtldm->thermalvalue_avg_index++; - if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_88E) - rtldm->thermalvalue_avg_index = 0; - - for (i = 0; i < AVG_THERMAL_NUM_88E; i++) { - if (rtldm->thermalvalue_avg[i]) { - thermalvalue_avg += rtldm->thermalvalue_avg[i]; - thermalvalue_avg_count++; - } - } - - if (thermalvalue_avg_count) - thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count); - - /* 5 Calculate delta, delta_LCK, delta_IQK.*/ - if (rtlhal->reloadtxpowerindex) { - delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? - (thermalvalue - rtlefuse->eeprom_thermalmeter) : - (rtlefuse->eeprom_thermalmeter - thermalvalue); - rtlhal->reloadtxpowerindex = false; - rtlpriv->dm.done_txpower = false; - } else if (rtlpriv->dm.done_txpower) { - delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? - (thermalvalue - rtlpriv->dm.thermalvalue) : - (rtlpriv->dm.thermalvalue - thermalvalue); - } else { - delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? - (thermalvalue - rtlefuse->eeprom_thermalmeter) : - (rtlefuse->eeprom_thermalmeter - thermalvalue); - } - delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? - (thermalvalue - rtlpriv->dm.thermalvalue_lck) : - (rtlpriv->dm.thermalvalue_lck - thermalvalue); - delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? - (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : - (rtlpriv->dm.thermalvalue_iqk - thermalvalue); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n", - thermalvalue, rtlpriv->dm.thermalvalue, - rtlefuse->eeprom_thermalmeter, delta, delta_lck, - delta_iqk); - /* 6 If necessary, do LCK.*/ - if (delta_lck >= 8) { - rtlpriv->dm.thermalvalue_lck = thermalvalue; - rtl88e_phy_lc_calibrate(hw); - } - - /* 7 If necessary, move the index of - * swing table to adjust Tx power. - */ - if (delta > 0 && rtlpriv->dm.txpower_track_control) { - delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? - (thermalvalue - rtlefuse->eeprom_thermalmeter) : - (rtlefuse->eeprom_thermalmeter - thermalvalue); - - /* 7.1 Get the final CCK_index and OFDM_index for each - * swing table. - */ - if (thermalvalue > rtlefuse->eeprom_thermalmeter) { - CAL_SWING_OFF(offset, power_inc, INDEX_MAPPING_NUM, - delta); - for (i = 0; i < rf; i++) - ofdm_index[i] = - rtldm->ofdm_index[i] + - delta_swing_table_idx[power_inc][offset]; - cck_index = rtldm->cck_index + - delta_swing_table_idx[power_inc][offset]; - } else { - CAL_SWING_OFF(offset, power_dec, INDEX_MAPPING_NUM, - delta); - for (i = 0; i < rf; i++) - ofdm_index[i] = - rtldm->ofdm_index[i] + - delta_swing_table_idx[power_dec][offset]; - cck_index = rtldm->cck_index + - delta_swing_table_idx[power_dec][offset]; - } - - /* 7.2 Handle boundary conditions of index.*/ - for (i = 0; i < rf; i++) { - if (ofdm_index[i] > OFDM_TABLE_SIZE-1) - ofdm_index[i] = OFDM_TABLE_SIZE-1; - else if (rtldm->ofdm_index[i] < ofdm_min_index) - ofdm_index[i] = ofdm_min_index; - } - - if (cck_index > CCK_TABLE_SIZE-1) - cck_index = CCK_TABLE_SIZE-1; - else if (cck_index < 0) - cck_index = 0; - - /*7.3Configure the Swing Table to adjust Tx Power.*/ - if (rtlpriv->dm.txpower_track_control) { - rtldm->done_txpower = true; - rtldm->swing_idx_ofdm[RF90_PATH_A] = - (u8)ofdm_index[RF90_PATH_A]; - rtldm->swing_idx_cck = cck_index; - if (rtldm->swing_idx_ofdm_cur != - rtldm->swing_idx_ofdm[0]) { - rtldm->swing_idx_ofdm_cur = - rtldm->swing_idx_ofdm[0]; - rtldm->swing_flag_ofdm = true; - } - - if (rtldm->swing_idx_cck_cur != rtldm->swing_idx_cck) { - rtldm->swing_idx_cck_cur = rtldm->swing_idx_cck; - rtldm->swing_flag_cck = true; - } - - dm_tx_pwr_track_set_pwr(hw, TXAGC, 0, 0); - } - } - - if (delta_iqk >= 8) { - rtlpriv->dm.thermalvalue_iqk = thermalvalue; - rtl88e_phy_iq_calibrate(hw, false); - } - - if (rtldm->txpower_track_control) - rtldm->thermalvalue = thermalvalue; - rtldm->txpowercount = 0; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n"); -} - -static void rtl88e_dm_init_txpower_tracking(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.txpower_tracking = true; - rtlpriv->dm.txpower_trackinginit = false; - rtlpriv->dm.txpowercount = 0; - rtlpriv->dm.txpower_track_control = true; - - rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] = 12; - rtlpriv->dm.swing_idx_ofdm_cur = 12; - rtlpriv->dm.swing_flag_ofdm = false; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "rtlpriv->dm.txpower_tracking = %d\n", - rtlpriv->dm.txpower_tracking); -} - -void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (!rtlpriv->dm.txpower_tracking) - return; - - if (!rtlpriv->dm.tm_trigger) { - rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17)|BIT(16), - 0x03); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Trigger 88E Thermal Meter!!\n"); - rtlpriv->dm.tm_trigger = 1; - return; - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Schedule TxPowerTracking !!\n"); - dm_txpower_track_cb_therm(hw); - rtlpriv->dm.tm_trigger = 0; - } -} - -void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rate_adaptive *p_ra = &rtlpriv->ra; - - p_ra->ratr_state = DM_RATR_STA_INIT; - p_ra->pre_ratr_state = DM_RATR_STA_INIT; - - if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) - rtlpriv->dm.useramask = true; - else - rtlpriv->dm.useramask = false; -} - -static void rtl88e_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rate_adaptive *p_ra = &rtlpriv->ra; - u32 low_rssithresh_for_ra, high_rssithresh_for_ra; - struct ieee80211_sta *sta = NULL; - - if (is_hal_stop(rtlhal)) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "driver is going to unload\n"); - return; - } - - if (!rtlpriv->dm.useramask) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "driver does not control rate adaptive mask\n"); - return; - } - - if (mac->link_state == MAC80211_LINKED && - mac->opmode == NL80211_IFTYPE_STATION) { - switch (p_ra->pre_ratr_state) { - case DM_RATR_STA_HIGH: - high_rssithresh_for_ra = 50; - low_rssithresh_for_ra = 20; - break; - case DM_RATR_STA_MIDDLE: - high_rssithresh_for_ra = 55; - low_rssithresh_for_ra = 20; - break; - case DM_RATR_STA_LOW: - high_rssithresh_for_ra = 50; - low_rssithresh_for_ra = 25; - break; - default: - high_rssithresh_for_ra = 50; - low_rssithresh_for_ra = 20; - break; - } - - if (rtlpriv->dm.undec_sm_pwdb > - (long)high_rssithresh_for_ra) - p_ra->ratr_state = DM_RATR_STA_HIGH; - else if (rtlpriv->dm.undec_sm_pwdb > - (long)low_rssithresh_for_ra) - p_ra->ratr_state = DM_RATR_STA_MIDDLE; - else - p_ra->ratr_state = DM_RATR_STA_LOW; - - if (p_ra->pre_ratr_state != p_ra->ratr_state) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "RSSI = %ld\n", - rtlpriv->dm.undec_sm_pwdb); - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "RSSI_LEVEL = %d\n", p_ra->ratr_state); - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "PreState = %d, CurState = %d\n", - p_ra->pre_ratr_state, p_ra->ratr_state); - - rcu_read_lock(); - sta = rtl_find_sta(hw, mac->bssid); - if (sta) - rtlpriv->cfg->ops->update_rate_tbl(hw, sta, - p_ra->ratr_state); - rcu_read_unlock(); - - p_ra->pre_ratr_state = p_ra->ratr_state; - } - } -} - -static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ps_t *dm_pstable = &rtlpriv->dm_pstable; - - dm_pstable->pre_ccastate = CCA_MAX; - dm_pstable->cur_ccasate = CCA_MAX; - dm_pstable->pre_rfstate = RF_MAX; - dm_pstable->cur_rfstate = RF_MAX; - dm_pstable->rssi_val_min = 0; -} - -static void rtl88e_dm_update_rx_idle_ant(struct ieee80211_hw *hw, - u8 ant) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct fast_ant_training *pfat_table = &rtldm->fat_table; - u32 default_ant, optional_ant; - - if (pfat_table->rx_idle_ant != ant) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "need to update rx idle ant\n"); - if (ant == MAIN_ANT) { - default_ant = - (pfat_table->rx_idle_ant == CG_TRX_HW_ANTDIV) ? - MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; - optional_ant = - (pfat_table->rx_idle_ant == CG_TRX_HW_ANTDIV) ? - AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; - } else { - default_ant = - (pfat_table->rx_idle_ant == CG_TRX_HW_ANTDIV) ? - AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX; - optional_ant = - (pfat_table->rx_idle_ant == CG_TRX_HW_ANTDIV) ? - MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX; - } - - if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) { - rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, - BIT(5) | BIT(4) | BIT(3), default_ant); - rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, - BIT(8) | BIT(7) | BIT(6), optional_ant); - rtl_set_bbreg(hw, DM_REG_ANTSEL_CTRL_11N, - BIT(14) | BIT(13) | BIT(12), - default_ant); - rtl_set_bbreg(hw, DM_REG_RESP_TX_11N, - BIT(6) | BIT(7), default_ant); - } else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) { - rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, - BIT(5) | BIT(4) | BIT(3), default_ant); - rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, - BIT(8) | BIT(7) | BIT(6), optional_ant); - } - } - pfat_table->rx_idle_ant = ant; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RxIdleAnt %s\n", - (ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT")); -} - -static void rtl88e_dm_update_tx_ant(struct ieee80211_hw *hw, - u8 ant, u32 mac_id) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct fast_ant_training *pfat_table = &rtldm->fat_table; - u8 target_ant; - - if (ant == MAIN_ANT) - target_ant = MAIN_ANT_CG_TRX; - else - target_ant = AUX_ANT_CG_TRX; - - pfat_table->antsel_a[mac_id] = target_ant & BIT(0); - pfat_table->antsel_b[mac_id] = (target_ant & BIT(1)) >> 1; - pfat_table->antsel_c[mac_id] = (target_ant & BIT(2)) >> 2; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "txfrominfo target ant %s\n", - (ant == MAIN_ANT) ? ("MAIN_ANT") : ("AUX_ANT")); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "antsel_tr_mux = 3'b%d%d%d\n", - pfat_table->antsel_c[mac_id], - pfat_table->antsel_b[mac_id], - pfat_table->antsel_a[mac_id]); -} - -static void rtl88e_dm_rx_hw_antena_div_init(struct ieee80211_hw *hw) -{ - u32 value32; - - /*MAC Setting*/ - value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD); - rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, - MASKDWORD, value32 | (BIT(23) | BIT(25))); - /*Pin Setting*/ - rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0); - rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0); - rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 1); - rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1); - /*OFDM Setting*/ - rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); - /*CCK Setting*/ - rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1); - rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); - rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT); - rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201); -} - -static void rtl88e_dm_trx_hw_antenna_div_init(struct ieee80211_hw *hw) -{ - u32 value32; - - /*MAC Setting*/ - value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD); - rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD, - value32 | (BIT(23) | BIT(25))); - /*Pin Setting*/ - rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0); - rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0); - rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0); - rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1); - /*OFDM Setting*/ - rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); - /*CCK Setting*/ - rtl_set_bbreg(hw, DM_REG_BB_PWR_SAV4_11N, BIT(7), 1); - rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1); - /*TX Setting*/ - rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 0); - rtl88e_dm_update_rx_idle_ant(hw, MAIN_ANT); - rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKLWORD, 0x0201); -} - -static void rtl88e_dm_fast_training_init(struct ieee80211_hw *hw) -{ - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct fast_ant_training *pfat_table = &rtldm->fat_table; - u32 ant_combination = 2; - u32 value32, i; - - for (i = 0; i < 6; i++) { - pfat_table->bssid[i] = 0; - pfat_table->ant_sum[i] = 0; - pfat_table->ant_cnt[i] = 0; - pfat_table->ant_ave[i] = 0; - } - pfat_table->train_idx = 0; - pfat_table->fat_state = FAT_NORMAL_STATE; - - /*MAC Setting*/ - value32 = rtl_get_bbreg(hw, DM_REG_ANTSEL_PIN_11N, MASKDWORD); - rtl_set_bbreg(hw, DM_REG_ANTSEL_PIN_11N, - MASKDWORD, value32 | (BIT(23) | BIT(25))); - value32 = rtl_get_bbreg(hw, DM_REG_ANT_TRAIN_PARA2_11N, MASKDWORD); - rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_PARA2_11N, - MASKDWORD, value32 | (BIT(16) | BIT(17))); - rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_PARA2_11N, - MASKLWORD, 0); - rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_PARA1_11N, - MASKDWORD, 0); - - /*Pin Setting*/ - rtl_set_bbreg(hw, DM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0); - rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(10), 0); - rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(22), 0); - rtl_set_bbreg(hw, DM_REG_LNA_SWITCH_11N, BIT(31), 1); - - /*OFDM Setting*/ - rtl_set_bbreg(hw, DM_REG_ANTDIV_PARA1_11N, MASKDWORD, 0x000000a0); - /*antenna mapping table*/ - rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE0, 1); - rtl_set_bbreg(hw, DM_REG_ANT_MAPPING1_11N, MASKBYTE1, 2); - - /*TX Setting*/ - rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, BIT(21), 1); - rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, - BIT(5) | BIT(4) | BIT(3), 0); - rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, - BIT(8) | BIT(7) | BIT(6), 1); - rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, - BIT(2) | BIT(1) | BIT(0), (ant_combination - 1)); - - rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1); -} - -static void rtl88e_dm_antenna_div_init(struct ieee80211_hw *hw) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - - if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) - rtl88e_dm_rx_hw_antena_div_init(hw); - else if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) - rtl88e_dm_trx_hw_antenna_div_init(hw); - else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) - rtl88e_dm_fast_training_init(hw); - -} - -void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, - u8 *pdesc, u32 mac_id) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct fast_ant_training *pfat_table = &rtldm->fat_table; - - if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || - (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV)) { - SET_TX_DESC_ANTSEL_A(pdesc, pfat_table->antsel_a[mac_id]); - SET_TX_DESC_ANTSEL_B(pdesc, pfat_table->antsel_b[mac_id]); - SET_TX_DESC_ANTSEL_C(pdesc, pfat_table->antsel_c[mac_id]); - } -} - -void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw, - u8 antsel_tr_mux, u32 mac_id, - u32 rx_pwdb_all) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct fast_ant_training *pfat_table = &rtldm->fat_table; - - if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) { - if (antsel_tr_mux == MAIN_ANT_CG_TRX) { - pfat_table->main_ant_sum[mac_id] += rx_pwdb_all; - pfat_table->main_ant_cnt[mac_id]++; - } else { - pfat_table->aux_ant_sum[mac_id] += rx_pwdb_all; - pfat_table->aux_ant_cnt[mac_id]++; - } - } else if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) { - if (antsel_tr_mux == MAIN_ANT_CGCS_RX) { - pfat_table->main_ant_sum[mac_id] += rx_pwdb_all; - pfat_table->main_ant_cnt[mac_id]++; - } else { - pfat_table->aux_ant_sum[mac_id] += rx_pwdb_all; - pfat_table->aux_ant_cnt[mac_id]++; - } - } -} - -static void rtl88e_dm_hw_ant_div(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct rtl_sta_info *drv_priv; - struct fast_ant_training *pfat_table = &rtldm->fat_table; - struct dig_t *dm_dig = &rtlpriv->dm_digtable; - u32 i, min_rssi = 0xff, ant_div_max_rssi = 0; - u32 max_rssi = 0, local_min_rssi, local_max_rssi; - u32 main_rssi, aux_rssi; - u8 rx_idle_ant = 0, target_ant = 7; - - /*for sta its self*/ - i = 0; - main_rssi = (pfat_table->main_ant_cnt[i] != 0) ? - (pfat_table->main_ant_sum[i] / pfat_table->main_ant_cnt[i]) : 0; - aux_rssi = (pfat_table->aux_ant_cnt[i] != 0) ? - (pfat_table->aux_ant_sum[i] / pfat_table->aux_ant_cnt[i]) : 0; - target_ant = (main_rssi == aux_rssi) ? - pfat_table->rx_idle_ant : ((main_rssi >= aux_rssi) ? - MAIN_ANT : AUX_ANT); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "main_ant_sum %d main_ant_cnt %d\n", - pfat_table->main_ant_sum[i], - pfat_table->main_ant_cnt[i]); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "aux_ant_sum %d aux_ant_cnt %d\n", - pfat_table->aux_ant_sum[i], pfat_table->aux_ant_cnt[i]); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "main_rssi %d aux_rssi%d\n", - main_rssi, aux_rssi); - local_max_rssi = (main_rssi > aux_rssi) ? main_rssi : aux_rssi; - if ((local_max_rssi > ant_div_max_rssi) && (local_max_rssi < 40)) - ant_div_max_rssi = local_max_rssi; - if (local_max_rssi > max_rssi) - max_rssi = local_max_rssi; - - if ((pfat_table->rx_idle_ant == MAIN_ANT) && (main_rssi == 0)) - main_rssi = aux_rssi; - else if ((pfat_table->rx_idle_ant == AUX_ANT) && (aux_rssi == 0)) - aux_rssi = main_rssi; - - local_min_rssi = (main_rssi > aux_rssi) ? aux_rssi : main_rssi; - if (local_min_rssi < min_rssi) { - min_rssi = local_min_rssi; - rx_idle_ant = target_ant; - } - if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) - rtl88e_dm_update_tx_ant(hw, target_ant, i); - - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || - rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) { - spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { - i++; - main_rssi = (pfat_table->main_ant_cnt[i] != 0) ? - (pfat_table->main_ant_sum[i] / - pfat_table->main_ant_cnt[i]) : 0; - aux_rssi = (pfat_table->aux_ant_cnt[i] != 0) ? - (pfat_table->aux_ant_sum[i] / - pfat_table->aux_ant_cnt[i]) : 0; - target_ant = (main_rssi == aux_rssi) ? - pfat_table->rx_idle_ant : ((main_rssi >= - aux_rssi) ? MAIN_ANT : AUX_ANT); - - local_max_rssi = (main_rssi > aux_rssi) ? - main_rssi : aux_rssi; - if ((local_max_rssi > ant_div_max_rssi) && - (local_max_rssi < 40)) - ant_div_max_rssi = local_max_rssi; - if (local_max_rssi > max_rssi) - max_rssi = local_max_rssi; - - if ((pfat_table->rx_idle_ant == MAIN_ANT) && - (main_rssi == 0)) - main_rssi = aux_rssi; - else if ((pfat_table->rx_idle_ant == AUX_ANT) && - (aux_rssi == 0)) - aux_rssi = main_rssi; - - local_min_rssi = (main_rssi > aux_rssi) ? - aux_rssi : main_rssi; - if (local_min_rssi < min_rssi) { - min_rssi = local_min_rssi; - rx_idle_ant = target_ant; - } - if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) - rtl88e_dm_update_tx_ant(hw, target_ant, i); - } - spin_unlock_bh(&rtlpriv->locks.entry_list_lock); - } - - for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) { - pfat_table->main_ant_sum[i] = 0; - pfat_table->aux_ant_sum[i] = 0; - pfat_table->main_ant_cnt[i] = 0; - pfat_table->aux_ant_cnt[i] = 0; - } - - rtl88e_dm_update_rx_idle_ant(hw, rx_idle_ant); - - dm_dig->antdiv_rssi_max = ant_div_max_rssi; - dm_dig->rssi_max = max_rssi; -} - -static void rtl88e_set_next_mac_address_target(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct rtl_sta_info *drv_priv; - struct fast_ant_training *pfat_table = &rtldm->fat_table; - u32 value32, i, j = 0; - - if (mac->link_state >= MAC80211_LINKED) { - for (i = 0; i < ASSOCIATE_ENTRY_NUM; i++) { - if ((pfat_table->train_idx + 1) == ASSOCIATE_ENTRY_NUM) - pfat_table->train_idx = 0; - else - pfat_table->train_idx++; - - if (pfat_table->train_idx == 0) { - value32 = (mac->mac_addr[5] << 8) | - mac->mac_addr[4]; - rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_PARA2_11N, - MASKLWORD, value32); - - value32 = (mac->mac_addr[3] << 24) | - (mac->mac_addr[2] << 16) | - (mac->mac_addr[1] << 8) | - mac->mac_addr[0]; - rtl_set_bbreg(hw, DM_REG_ANT_TRAIN_PARA1_11N, - MASKDWORD, value32); - break; - } - - if (rtlpriv->mac80211.opmode != - NL80211_IFTYPE_STATION) { - spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_for_each_entry(drv_priv, - &rtlpriv->entry_list, list) { - j++; - if (j != pfat_table->train_idx) - continue; - - value32 = (drv_priv->mac_addr[5] << 8) | - drv_priv->mac_addr[4]; - rtl_set_bbreg(hw, - DM_REG_ANT_TRAIN_PARA2_11N, - MASKLWORD, value32); - - value32 = (drv_priv->mac_addr[3] << 24) | - (drv_priv->mac_addr[2] << 16) | - (drv_priv->mac_addr[1] << 8) | - drv_priv->mac_addr[0]; - rtl_set_bbreg(hw, - DM_REG_ANT_TRAIN_PARA1_11N, - MASKDWORD, value32); - break; - } - spin_unlock_bh(&rtlpriv->locks.entry_list_lock); - /*find entry, break*/ - if (j == pfat_table->train_idx) - break; - } - } - } -} - -static void rtl88e_dm_fast_ant_training(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct fast_ant_training *pfat_table = &rtldm->fat_table; - u32 i, max_rssi = 0; - u8 target_ant = 2; - bool bpkt_filter_match = false; - - if (pfat_table->fat_state == FAT_TRAINING_STATE) { - for (i = 0; i < 7; i++) { - if (pfat_table->ant_cnt[i] == 0) { - pfat_table->ant_ave[i] = 0; - } else { - pfat_table->ant_ave[i] = - pfat_table->ant_sum[i] / - pfat_table->ant_cnt[i]; - bpkt_filter_match = true; - } - - if (pfat_table->ant_ave[i] > max_rssi) { - max_rssi = pfat_table->ant_ave[i]; - target_ant = (u8) i; - } - } - - if (bpkt_filter_match == false) { - rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, - BIT(16), 0); - rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0); - } else { - rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, - BIT(16), 0); - rtl_set_bbreg(hw, DM_REG_RX_ANT_CTRL_11N, BIT(8) | - BIT(7) | BIT(6), target_ant); - rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, - BIT(21), 1); - - pfat_table->antsel_a[pfat_table->train_idx] = - target_ant & BIT(0); - pfat_table->antsel_b[pfat_table->train_idx] = - (target_ant & BIT(1)) >> 1; - pfat_table->antsel_c[pfat_table->train_idx] = - (target_ant & BIT(2)) >> 2; - - if (target_ant == 0) - rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0); - } - - for (i = 0; i < 7; i++) { - pfat_table->ant_sum[i] = 0; - pfat_table->ant_cnt[i] = 0; - } - - pfat_table->fat_state = FAT_NORMAL_STATE; - return; - } - - if (pfat_table->fat_state == FAT_NORMAL_STATE) { - rtl88e_set_next_mac_address_target(hw); - - pfat_table->fat_state = FAT_TRAINING_STATE; - rtl_set_bbreg(hw, DM_REG_TXAGC_A_1_MCS32_11N, BIT(16), 1); - rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1); - - mod_timer(&rtlpriv->works.fast_antenna_training_timer, - jiffies + MSECS(RTL_WATCH_DOG_TIME)); - } -} - -void rtl88e_dm_fast_antenna_training_callback(unsigned long data) -{ - struct ieee80211_hw *hw = (struct ieee80211_hw *)data; - - rtl88e_dm_fast_ant_training(hw); -} - -static void rtl88e_dm_antenna_diversity(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct fast_ant_training *pfat_table = &rtldm->fat_table; - - if (mac->link_state < MAC80211_LINKED) { - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "No Link\n"); - if (pfat_table->becomelinked) { - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "need to turn off HW AntDiv\n"); - rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 0); - rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N, - BIT(15), 0); - if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) - rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, - BIT(21), 0); - pfat_table->becomelinked = - (mac->link_state == MAC80211_LINKED) ? - true : false; - } - return; - } else { - if (!pfat_table->becomelinked) { - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Need to turn on HW AntDiv\n"); - rtl_set_bbreg(hw, DM_REG_IGI_A_11N, BIT(7), 1); - rtl_set_bbreg(hw, DM_REG_CCK_ANTDIV_PARA1_11N, - BIT(15), 1); - if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) - rtl_set_bbreg(hw, DM_REG_TX_ANT_CTRL_11N, - BIT(21), 1); - pfat_table->becomelinked = - (mac->link_state >= MAC80211_LINKED) ? - true : false; - } - } - - if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || - (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)) - rtl88e_dm_hw_ant_div(hw); - else if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) - rtl88e_dm_fast_ant_training(hw); -} - -void rtl88e_dm_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f); - - rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; - rtl_dm_diginit(hw, cur_igvalue); - rtl88e_dm_init_dynamic_txpower(hw); - rtl88e_dm_init_edca_turbo(hw); - rtl88e_dm_init_rate_adaptive_mask(hw); - rtl88e_dm_init_txpower_tracking(hw); - rtl92c_dm_init_dynamic_bb_powersaving(hw); - rtl88e_dm_antenna_div_init(hw); -} - -void rtl88e_dm_watchdog(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool fw_current_inpsmode = false; - bool fw_ps_awake = true; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inpsmode)); - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, - (u8 *)(&fw_ps_awake)); - if (ppsc->p2p_ps_info.p2p_ps_mode) - fw_ps_awake = false; - - if ((ppsc->rfpwr_state == ERFON) && - ((!fw_current_inpsmode) && fw_ps_awake) && - (!ppsc->rfchange_inprogress)) { - rtl88e_dm_pwdb_monitor(hw); - rtl88e_dm_dig(hw); - rtl88e_dm_false_alarm_counter_statistics(hw); - rtl92c_dm_dynamic_txpower(hw); - rtl88e_dm_check_txpower_tracking(hw); - rtl88e_dm_refresh_rate_adaptive_mask(hw); - rtl88e_dm_check_edca_turbo(hw); - rtl88e_dm_antenna_diversity(hw); - } -} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h b/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h deleted file mode 100644 index 071ccee69eae..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/dm.h +++ /dev/null @@ -1,286 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL88E_DM_H__ -#define __RTL88E_DM_H__ - -#define MAIN_ANT 0 -#define AUX_ANT 1 -#define MAIN_ANT_CG_TRX 1 -#define AUX_ANT_CG_TRX 0 -#define MAIN_ANT_CGCS_RX 0 -#define AUX_ANT_CGCS_RX 1 - -/*RF REG LIST*/ -#define DM_REG_RF_MODE_11N 0x00 -#define DM_REG_RF_0B_11N 0x0B -#define DM_REG_CHNBW_11N 0x18 -#define DM_REG_T_METER_11N 0x24 -#define DM_REG_RF_25_11N 0x25 -#define DM_REG_RF_26_11N 0x26 -#define DM_REG_RF_27_11N 0x27 -#define DM_REG_RF_2B_11N 0x2B -#define DM_REG_RF_2C_11N 0x2C -#define DM_REG_RXRF_A3_11N 0x3C -#define DM_REG_T_METER_92D_11N 0x42 -#define DM_REG_T_METER_88E_11N 0x42 - -/*BB REG LIST*/ -/*PAGE 8 */ -#define DM_REG_BB_CTRL_11N 0x800 -#define DM_REG_RF_PIN_11N 0x804 -#define DM_REG_PSD_CTRL_11N 0x808 -#define DM_REG_TX_ANT_CTRL_11N 0x80C -#define DM_REG_BB_PWR_SAV5_11N 0x818 -#define DM_REG_CCK_RPT_FORMAT_11N 0x824 -#define DM_REG_RX_DEFAULT_A_11N 0x858 -#define DM_REG_RX_DEFAULT_B_11N 0x85A -#define DM_REG_BB_PWR_SAV3_11N 0x85C -#define DM_REG_ANTSEL_CTRL_11N 0x860 -#define DM_REG_RX_ANT_CTRL_11N 0x864 -#define DM_REG_PIN_CTRL_11N 0x870 -#define DM_REG_BB_PWR_SAV1_11N 0x874 -#define DM_REG_ANTSEL_PATH_11N 0x878 -#define DM_REG_BB_3WIRE_11N 0x88C -#define DM_REG_SC_CNT_11N 0x8C4 -#define DM_REG_PSD_DATA_11N 0x8B4 -/*PAGE 9*/ -#define DM_REG_ANT_MAPPING1_11N 0x914 -#define DM_REG_ANT_MAPPING2_11N 0x918 -/*PAGE A*/ -#define DM_REG_CCK_ANTDIV_PARA1_11N 0xA00 -#define DM_REG_CCK_CCA_11N 0xA0A -#define DM_REG_CCK_ANTDIV_PARA2_11N 0xA0C -#define DM_REG_CCK_ANTDIV_PARA3_11N 0xA10 -#define DM_REG_CCK_ANTDIV_PARA4_11N 0xA14 -#define DM_REG_CCK_FILTER_PARA1_11N 0xA22 -#define DM_REG_CCK_FILTER_PARA2_11N 0xA23 -#define DM_REG_CCK_FILTER_PARA3_11N 0xA24 -#define DM_REG_CCK_FILTER_PARA4_11N 0xA25 -#define DM_REG_CCK_FILTER_PARA5_11N 0xA26 -#define DM_REG_CCK_FILTER_PARA6_11N 0xA27 -#define DM_REG_CCK_FILTER_PARA7_11N 0xA28 -#define DM_REG_CCK_FILTER_PARA8_11N 0xA29 -#define DM_REG_CCK_FA_RST_11N 0xA2C -#define DM_REG_CCK_FA_MSB_11N 0xA58 -#define DM_REG_CCK_FA_LSB_11N 0xA5C -#define DM_REG_CCK_CCA_CNT_11N 0xA60 -#define DM_REG_BB_PWR_SAV4_11N 0xA74 -/*PAGE B */ -#define DM_REG_LNA_SWITCH_11N 0xB2C -#define DM_REG_PATH_SWITCH_11N 0xB30 -#define DM_REG_RSSI_CTRL_11N 0xB38 -#define DM_REG_CONFIG_ANTA_11N 0xB68 -#define DM_REG_RSSI_BT_11N 0xB9C -/*PAGE C */ -#define DM_REG_OFDM_FA_HOLDC_11N 0xC00 -#define DM_REG_RX_PATH_11N 0xC04 -#define DM_REG_TRMUX_11N 0xC08 -#define DM_REG_OFDM_FA_RSTC_11N 0xC0C -#define DM_REG_RXIQI_MATRIX_11N 0xC14 -#define DM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C -#define DM_REG_IGI_A_11N 0xC50 -#define DM_REG_ANTDIV_PARA2_11N 0xC54 -#define DM_REG_IGI_B_11N 0xC58 -#define DM_REG_ANTDIV_PARA3_11N 0xC5C -#define DM_REG_BB_PWR_SAV2_11N 0xC70 -#define DM_REG_RX_OFF_11N 0xC7C -#define DM_REG_TXIQK_MATRIXA_11N 0xC80 -#define DM_REG_TXIQK_MATRIXB_11N 0xC88 -#define DM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 -#define DM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C -#define DM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 -#define DM_REG_ANTDIV_PARA1_11N 0xCA4 -#define DM_REG_OFDM_FA_TYPE1_11N 0xCF0 -/*PAGE D */ -#define DM_REG_OFDM_FA_RSTD_11N 0xD00 -#define DM_REG_OFDM_FA_TYPE2_11N 0xDA0 -#define DM_REG_OFDM_FA_TYPE3_11N 0xDA4 -#define DM_REG_OFDM_FA_TYPE4_11N 0xDA8 -/*PAGE E */ -#define DM_REG_TXAGC_A_6_18_11N 0xE00 -#define DM_REG_TXAGC_A_24_54_11N 0xE04 -#define DM_REG_TXAGC_A_1_MCS32_11N 0xE08 -#define DM_REG_TXAGC_A_MCS0_3_11N 0xE10 -#define DM_REG_TXAGC_A_MCS4_7_11N 0xE14 -#define DM_REG_TXAGC_A_MCS8_11_11N 0xE18 -#define DM_REG_TXAGC_A_MCS12_15_11N 0xE1C -#define DM_REG_FPGA0_IQK_11N 0xE28 -#define DM_REG_TXIQK_TONE_A_11N 0xE30 -#define DM_REG_RXIQK_TONE_A_11N 0xE34 -#define DM_REG_TXIQK_PI_A_11N 0xE38 -#define DM_REG_RXIQK_PI_A_11N 0xE3C -#define DM_REG_TXIQK_11N 0xE40 -#define DM_REG_RXIQK_11N 0xE44 -#define DM_REG_IQK_AGC_PTS_11N 0xE48 -#define DM_REG_IQK_AGC_RSP_11N 0xE4C -#define DM_REG_BLUETOOTH_11N 0xE6C -#define DM_REG_RX_WAIT_CCA_11N 0xE70 -#define DM_REG_TX_CCK_RFON_11N 0xE74 -#define DM_REG_TX_CCK_BBON_11N 0xE78 -#define DM_REG_OFDM_RFON_11N 0xE7C -#define DM_REG_OFDM_BBON_11N 0xE80 -#define DM_REG_TX2RX_11N 0xE84 -#define DM_REG_TX2TX_11N 0xE88 -#define DM_REG_RX_CCK_11N 0xE8C -#define DM_REG_RX_OFDM_11N 0xED0 -#define DM_REG_RX_WAIT_RIFS_11N 0xED4 -#define DM_REG_RX2RX_11N 0xED8 -#define DM_REG_STANDBY_11N 0xEDC -#define DM_REG_SLEEP_11N 0xEE0 -#define DM_REG_PMPD_ANAEN_11N 0xEEC - -/*MAC REG LIST*/ -#define DM_REG_BB_RST_11N 0x02 -#define DM_REG_ANTSEL_PIN_11N 0x4C -#define DM_REG_EARLY_MODE_11N 0x4D0 -#define DM_REG_RSSI_MONITOR_11N 0x4FE -#define DM_REG_EDCA_VO_11N 0x500 -#define DM_REG_EDCA_VI_11N 0x504 -#define DM_REG_EDCA_BE_11N 0x508 -#define DM_REG_EDCA_BK_11N 0x50C -#define DM_REG_TXPAUSE_11N 0x522 -#define DM_REG_RESP_TX_11N 0x6D8 -#define DM_REG_ANT_TRAIN_PARA1_11N 0x7b0 -#define DM_REG_ANT_TRAIN_PARA2_11N 0x7b4 - - -/*DIG Related*/ -#define DM_BIT_IGI_11N 0x0000007F - -#define HAL_DM_DIG_DISABLE BIT(0) -#define HAL_DM_HIPWR_DISABLE BIT(1) - -#define OFDM_TABLE_LENGTH 43 -#define CCK_TABLE_LENGTH 33 - -#define OFDM_TABLE_SIZE 43 -#define CCK_TABLE_SIZE 33 - -#define BW_AUTO_SWITCH_HIGH_LOW 25 -#define BW_AUTO_SWITCH_LOW_HIGH 30 - -#define DM_DIG_FA_UPPER 0x3e -#define DM_DIG_FA_LOWER 0x1e -#define DM_DIG_FA_TH0 0x200 -#define DM_DIG_FA_TH1 0x300 -#define DM_DIG_FA_TH2 0x400 - -#define RXPATHSELECTION_SS_TH_W 30 -#define RXPATHSELECTION_DIFF_TH 18 - -#define DM_RATR_STA_INIT 0 -#define DM_RATR_STA_HIGH 1 -#define DM_RATR_STA_MIDDLE 2 -#define DM_RATR_STA_LOW 3 - -#define CTS2SELF_THVAL 30 -#define REGC38_TH 20 - -#define WAIOTTHVAL 25 - -#define TXHIGHPWRLEVEL_NORMAL 0 -#define TXHIGHPWRLEVEL_LEVEL1 1 -#define TXHIGHPWRLEVEL_LEVEL2 2 -#define TXHIGHPWRLEVEL_BT1 3 -#define TXHIGHPWRLEVEL_BT2 4 - -#define DM_TYPE_BYFW 0 -#define DM_TYPE_BYDRIVER 1 - -#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 -#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 -#define TXPWRTRACK_MAX_IDX 6 - -struct swat_t { - u8 failure_cnt; - u8 try_flag; - u8 stop_trying; - - long pre_rssi; - long trying_threshold; - u8 cur_antenna; - u8 pre_antenna; - -}; - -enum FAT_STATE { - FAT_NORMAL_STATE = 0, - FAT_TRAINING_STATE = 1, -}; - -enum tag_dynamic_init_gain_operation_type_definition { - DIG_TYPE_THRESH_HIGH = 0, - DIG_TYPE_THRESH_LOW = 1, - DIG_TYPE_BACKOFF = 2, - DIG_TYPE_RX_GAIN_MIN = 3, - DIG_TYPE_RX_GAIN_MAX = 4, - DIG_TYPE_ENABLE = 5, - DIG_TYPE_DISABLE = 6, - DIG_OP_TYPE_MAX -}; - -enum dm_1r_cca_e { - CCA_1R = 0, - CCA_2R = 1, - CCA_MAX = 2, -}; - -enum dm_rf_e { - RF_SAVE = 0, - RF_NORMAL = 1, - RF_MAX = 2, -}; - -enum dm_sw_ant_switch_e { - ANS_ANTENNA_B = 1, - ANS_ANTENNA_A = 2, - ANS_ANTENNA_MAX = 3, -}; - -enum pwr_track_control_method { - BBSWING, - TXAGC -}; - -void rtl88e_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, - u8 *pdesc, u32 mac_id); -void rtl88e_dm_ant_sel_statistics(struct ieee80211_hw *hw, - u8 antsel_tr_mux, u32 mac_id, - u32 rx_pwdb_all); -void rtl88e_dm_fast_antenna_training_callback(unsigned long data); -void rtl88e_dm_init(struct ieee80211_hw *hw); -void rtl88e_dm_watchdog(struct ieee80211_hw *hw); -void rtl88e_dm_write_dig(struct ieee80211_hw *hw); -void rtl88e_dm_init_edca_turbo(struct ieee80211_hw *hw); -void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw); -void rtl88e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); -void rtl88e_dm_txpower_track_adjust(struct ieee80211_hw *hw, - u8 type, u8 *pdirection, u32 *poutwrite_val); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c deleted file mode 100644 index 629125658b87..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.c +++ /dev/null @@ -1,815 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "fw.h" - -static void _rtl88e_enable_fw_download(struct ieee80211_hw *hw, bool enable) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp; - - if (enable) { - tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04); - - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); - rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); - - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); - rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); - } else { - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); - rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); - - rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00); - } -} - -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) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 *bufferptr = (u8 *)buffer; - u32 pagenums, remainsize; - u32 page, offset; - - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size); - - _rtl88e_fill_dummy(bufferptr, &size); - - pagenums = size / FW_8192C_PAGE_SIZE; - remainsize = size % FW_8192C_PAGE_SIZE; - - if (pagenums > 8) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Page numbers should not greater then 8\n"); - } - - for (page = 0; page < pagenums; page++) { - offset = page * FW_8192C_PAGE_SIZE; - _rtl88e_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); - } -} - -static int _rtl88e_fw_free_to_go(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int err = -EIO; - u32 counter = 0; - u32 value32; - - do { - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && - (!(value32 & FWDL_CHKSUM_RPT))); - - if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "chksum report faill ! REG_MCUFWDL:0x%08x .\n", - value32); - goto exit; - } - - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); - - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - value32 |= MCUFWDL_RDY; - value32 &= ~WINTINI_RDY; - rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); - - rtl88e_firmware_selfreset(hw); - counter = 0; - - do { - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - if (value32 & WINTINI_RDY) { - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "Polling FW ready success!! REG_MCUFWDL:0x%08x.\n", - value32); - err = 0; - goto exit; - } - - udelay(FW_8192C_POLLING_DELAY); - - } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT); - - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32); - -exit: - return err; -} - -int rtl88e_download_fw(struct ieee80211_hw *hw, - bool buse_wake_on_wlan_fw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtlwifi_firmware_header *pfwheader; - u8 *pfwdata; - u32 fwsize; - int err; - enum version_8188e version = rtlhal->version; - - if (!rtlhal->pfirmware) - return 1; - - pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; - pfwdata = rtlhal->pfirmware; - fwsize = rtlhal->fwsize; - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "normal Firmware SIZE %d\n", fwsize); - - if (IS_FW_HEADER_EXIST(pfwheader)) { - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "Firmware Version(%d), Signature(%#x), Size(%d)\n", - pfwheader->version, pfwheader->signature, - (int)sizeof(struct rtlwifi_firmware_header)); - - pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); - fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); - } - - if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); - rtl88e_firmware_selfreset(hw); - } - _rtl88e_enable_fw_download(hw, true); - _rtl88e_write_fw(hw, version, pfwdata, fwsize); - _rtl88e_enable_fw_download(hw, false); - - err = _rtl88e_fw_free_to_go(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Firmware is not ready to run!\n"); - } else { - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "Firmware is ready to run!\n"); - } - - return 0; -} - -static bool _rtl88e_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 val_hmetfr; - - val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); - if (((val_hmetfr >> boxnum) & BIT(0)) == 0) - return true; - return false; -} - -static void _rtl88e_fill_h2c_command(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, - u8 *cmd_b) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 boxnum; - u16 box_reg = 0, box_extreg = 0; - u8 u1b_tmp; - bool isfw_read = false; - u8 buf_index = 0; - bool write_sucess = false; - u8 wait_h2c_limmit = 100; - u8 wait_writeh2c_limit = 100; - u8 boxcontent[4], boxextcontent[4]; - u32 h2c_waitcounter = 0; - unsigned long flag; - u8 idx; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); - - while (true) { - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - if (rtlhal->h2c_setinprogress) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C set in progress! Wait to set..element_id(%d).\n", - element_id); - - while (rtlhal->h2c_setinprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, - flag); - h2c_waitcounter++; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Wait 100 us (%d times)...\n", - h2c_waitcounter); - udelay(100); - - if (h2c_waitcounter > 1000) - return; - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, - flag); - } - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - } else { - rtlhal->h2c_setinprogress = true; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - break; - } - } - - while (!write_sucess) { - wait_writeh2c_limit--; - if (wait_writeh2c_limit == 0) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Write H2C fail because no trigger for FW INT!\n"); - break; - } - - boxnum = rtlhal->last_hmeboxnum; - switch (boxnum) { - case 0: - box_reg = REG_HMEBOX_0; - box_extreg = REG_HMEBOX_EXT_0; - break; - case 1: - box_reg = REG_HMEBOX_1; - box_extreg = REG_HMEBOX_EXT_1; - break; - case 2: - box_reg = REG_HMEBOX_2; - box_extreg = REG_HMEBOX_EXT_2; - break; - case 3: - box_reg = REG_HMEBOX_3; - box_extreg = REG_HMEBOX_EXT_3; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); - while (!isfw_read) { - wait_h2c_limmit--; - if (wait_h2c_limmit == 0) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Waiting too long for FW read clear HMEBox(%d)!\n", - boxnum); - break; - } - - udelay(10); - - isfw_read = _rtl88e_check_fw_read_last_h2c(hw, boxnum); - u1b_tmp = rtl_read_byte(rtlpriv, 0x130); - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", - boxnum, u1b_tmp); - } - - if (!isfw_read) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", - boxnum); - break; - } - - memset(boxcontent, 0, sizeof(boxcontent)); - memset(boxextcontent, 0, sizeof(boxextcontent)); - boxcontent[0] = element_id; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Write element_id box_reg(%4x) = %2x\n", - box_reg, element_id); - - switch (cmd_len) { - case 1: - case 2: - case 3: - /*boxcontent[0] &= ~(BIT(7));*/ - memcpy((u8 *)(boxcontent) + 1, - cmd_b + buf_index, cmd_len); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - case 4: - case 5: - case 6: - case 7: - /*boxcontent[0] |= (BIT(7));*/ - memcpy((u8 *)(boxextcontent), - cmd_b + buf_index+3, cmd_len-3); - memcpy((u8 *)(boxcontent) + 1, - cmd_b + buf_index, 3); - - for (idx = 0; idx < 2; idx++) { - rtl_write_byte(rtlpriv, box_extreg + idx, - boxextcontent[idx]); - } - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - - write_sucess = true; - - rtlhal->last_hmeboxnum = boxnum + 1; - if (rtlhal->last_hmeboxnum == 4) - rtlhal->last_hmeboxnum = 0; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "pHalData->last_hmeboxnum = %d\n", - rtlhal->last_hmeboxnum); - } - - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - rtlhal->h2c_setinprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); -} - -void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, u8 *cmdbuffer) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 tmp_cmdbuf[2]; - - if (!rtlhal->fw_ready) { - RT_ASSERT(false, - "return H2C cmd because of Fw download fail!!!\n"); - return; - } - - memset(tmp_cmdbuf, 0, 8); - memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); - _rtl88e_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); - - return; -} - -void rtl88e_firmware_selfreset(struct ieee80211_hw *hw) -{ - u8 u1b_tmp; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2))); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "8051Reset88E(): 8051 reset success\n"); - -} - -void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 u1_h2c_set_pwrmode[H2C_88E_PWEMODE_LENGTH] = { 0 }; - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 rlbm, power_state = 0; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); - - SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); - rlbm = 0;/*YJ, temp, 120316. FW now not support RLBM=2.*/ - SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); - SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, - (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1); - SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, - ppsc->reg_max_lps_awakeintvl); - SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); - if (mode == FW_PS_ACTIVE_MODE) - power_state |= FW_PWR_STATE_ACTIVE; - else - power_state |= FW_PWR_STATE_RF_OFF; - - SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", - u1_h2c_set_pwrmode, H2C_88E_PWEMODE_LENGTH); - rtl88e_fill_h2c_cmd(hw, H2C_88E_SETPWRMODE, - H2C_88E_PWEMODE_LENGTH, u1_h2c_set_pwrmode); -} - -void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) -{ - u8 u1_joinbssrpt_parm[1] = { 0 }; - - SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); - - rtl88e_fill_h2c_cmd(hw, H2C_88E_JOINBSSRPT, 1, u1_joinbssrpt_parm); -} - -void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, - u8 ap_offload_enable) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 u1_apoffload_parm[H2C_88E_AP_OFFLOAD_LENGTH] = { 0 }; - - SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable); - SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid); - SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0); - - rtl88e_fill_h2c_cmd(hw, H2C_88E_AP_OFFLOAD, - H2C_88E_AP_OFFLOAD_LENGTH, u1_apoffload_parm); - -} - -#define BEACON_PG 0 /* ->1 */ -#define PSPOLL_PG 2 -#define NULL_PG 3 -#define PROBERSP_PG 4 /* ->5 */ - -#define TOTAL_RESERVED_PKT_LEN 768 - -static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { - /* page 0 beacon */ - 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, - 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, - 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, - 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, - 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, - 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, - 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 1 beacon */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 2 ps-poll */ - 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 3 null */ - 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 4 probe_resp */ - 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, - 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, - 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, - 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, - 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, - 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, - 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, - 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, - 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 5 probe_resp */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct sk_buff *skb = NULL; - u32 totalpacketlen; - bool rtstatus; - u8 u1rsvdpageloc[5] = { 0 }; - bool b_dlok = false; - u8 *beacon; - u8 *p_pspoll; - u8 *nullfunc; - u8 *p_probersp; - - /*--------------------------------------------------------- - * (1) beacon - *--------------------------------------------------------- - */ - beacon = &reserved_page_packet[BEACON_PG * 128]; - SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); - SET_80211_HDR_ADDRESS3(beacon, mac->bssid); - - /*------------------------------------------------------- - * (2) ps-poll - *-------------------------------------------------------- - */ - p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; - SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); - SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); - SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); - - SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); - - /*-------------------------------------------------------- - * (3) null data - *--------------------------------------------------------- - */ - nullfunc = &reserved_page_packet[NULL_PG * 128]; - SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); - SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); - SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); - - /*--------------------------------------------------------- - * (4) probe response - *---------------------------------------------------------- - */ - p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; - SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); - SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); - SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); - - totalpacketlen = TOTAL_RESERVED_PKT_LEN; - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", - &reserved_page_packet[0], totalpacketlen); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "rtl88e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", - u1rsvdpageloc, 3); - - skb = dev_alloc_skb(totalpacketlen); - memcpy(skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); - - rtstatus = rtl_cmd_send_packet(hw, skb); - - if (rtstatus) - b_dlok = true; - - if (b_dlok) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Set RSVD page location to Fw.\n"); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3); - rtl88e_fill_h2c_cmd(hw, H2C_88E_RSVDPAGE, - sizeof(u1rsvdpageloc), u1rsvdpageloc); - } else - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set RSVD page location to Fw FAIL!!!!!!.\n"); -} - -/*Should check FW support p2p or not.*/ -static void rtl88e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) -{ - u8 u1_ctwindow_period[1] = { ctwindow}; - - rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); - -} - -void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); - struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; - u8 i; - u16 ctwindow; - u32 start_time, tsf_low; - - switch (p2p_ps_state) { - case P2P_PS_DISABLE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); - memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); - break; - case P2P_PS_ENABLE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); - /* update CTWindow value. */ - if (p2pinfo->ctwindow > 0) { - p2p_ps_offload->ctwindow_en = 1; - ctwindow = p2pinfo->ctwindow; - rtl88e_set_p2p_ctw_period_cmd(hw, ctwindow); - } - - /* hw only support 2 set of NoA */ - for (i = 0 ; i < p2pinfo->noa_num; i++) { - /* To control the register setting for which NOA*/ - rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); - if (i == 0) - p2p_ps_offload->noa0_en = 1; - else - p2p_ps_offload->noa1_en = 1; - - /* config P2P NoA Descriptor Register */ - rtl_write_dword(rtlpriv, 0x5E0, - p2pinfo->noa_duration[i]); - rtl_write_dword(rtlpriv, 0x5E4, - p2pinfo->noa_interval[i]); - - /*Get Current TSF value */ - tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - - start_time = p2pinfo->noa_start_time[i]; - if (p2pinfo->noa_count_type[i] != 1) { - while (start_time <= (tsf_low+(50*1024))) { - start_time += p2pinfo->noa_interval[i]; - if (p2pinfo->noa_count_type[i] != 255) - p2pinfo->noa_count_type[i]--; - } - } - rtl_write_dword(rtlpriv, 0x5E8, start_time); - rtl_write_dword(rtlpriv, 0x5EC, - p2pinfo->noa_count_type[i]); - } - - if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { - /* rst p2p circuit */ - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); - - p2p_ps_offload->offload_en = 1; - - if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { - p2p_ps_offload->role = 1; - p2p_ps_offload->allstasleep = -1; - } else { - p2p_ps_offload->role = 0; - } - - p2p_ps_offload->discovery = 0; - } - break; - case P2P_PS_SCAN: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); - p2p_ps_offload->discovery = 1; - break; - case P2P_PS_SCAN_DONE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); - p2p_ps_offload->discovery = 0; - p2pinfo->p2p_ps_state = P2P_PS_ENABLE; - break; - default: - break; - } - - rtl88e_fill_h2c_cmd(hw, H2C_88E_P2P_PS_OFFLOAD, 1, - (u8 *)p2p_ps_offload); - -} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h deleted file mode 100644 index 21bd4a5337ab..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/fw.h +++ /dev/null @@ -1,285 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C__FW__H__ -#define __RTL92C__FW__H__ - -#define FW_8192C_SIZE 0x8000 -#define FW_8192C_START_ADDRESS 0x1000 -#define FW_8192C_END_ADDRESS 0x5FFF -#define FW_8192C_PAGE_SIZE 4096 -#define FW_8192C_POLLING_DELAY 5 -#define FW_8192C_POLLING_TIMEOUT_COUNT 3000 - -#define IS_FW_HEADER_EXIST(_pfwhdr) \ - ((le16_to_cpu(_pfwhdr->signature) & 0xFFFF) == 0x88E1) -#define USE_OLD_WOWLAN_DEBUG_FW 0 - -#define H2C_88E_RSVDPAGE_LOC_LEN 5 -#define H2C_88E_PWEMODE_LENGTH 5 -#define H2C_88E_JOINBSSRPT_LENGTH 1 -#define H2C_88E_AP_OFFLOAD_LENGTH 3 -#define H2C_88E_WOWLAN_LENGTH 3 -#define H2C_88E_KEEP_ALIVE_CTRL_LENGTH 3 -#if (USE_OLD_WOWLAN_DEBUG_FW == 0) -#define H2C_88E_REMOTE_WAKE_CTRL_LEN 1 -#else -#define H2C_88E_REMOTE_WAKE_CTRL_LEN 3 -#endif -#define H2C_88E_AOAC_GLOBAL_INFO_LEN 2 -#define H2C_88E_AOAC_RSVDPAGE_LOC_LEN 7 - -/* Fw PS state for RPWM. -*BIT[2:0] = HW state -*BIT[3] = Protocol PS state, -*1: register active state , 0: register sleep state -*BIT[4] = sub-state -*/ -#define FW_PS_GO_ON BIT(0) -#define FW_PS_TX_NULL BIT(1) -#define FW_PS_RF_ON BIT(2) -#define FW_PS_REGISTER_ACTIVE BIT(3) - -#define FW_PS_DPS BIT(0) -#define FW_PS_LCLK (FW_PS_DPS) -#define FW_PS_RF_OFF BIT(1) -#define FW_PS_ALL_ON BIT(2) -#define FW_PS_ST_ACTIVE BIT(3) -#define FW_PS_ISR_ENABLE BIT(4) -#define FW_PS_IMR_ENABLE BIT(5) - - -#define FW_PS_ACK BIT(6) -#define FW_PS_TOGGLE BIT(7) - - /* 88E RPWM value*/ - /* BIT[0] = 1: 32k, 0: 40M*/ -#define FW_PS_CLOCK_OFF BIT(0) /* 32k*/ -#define FW_PS_CLOCK_ON 0 /*40M*/ - -#define FW_PS_STATE_MASK (0x0F) -#define FW_PS_STATE_HW_MASK (0x07) -/*ISR_ENABLE, IMR_ENABLE, and PS mode should be inherited.*/ -#define FW_PS_STATE_INT_MASK (0x3F) - -#define FW_PS_STATE(x) (FW_PS_STATE_MASK & (x)) -#define FW_PS_STATE_HW(x) (FW_PS_STATE_HW_MASK & (x)) -#define FW_PS_STATE_INT(x) (FW_PS_STATE_INT_MASK & (x)) -#define FW_PS_ISR_VAL(x) ((x) & 0x70) -#define FW_PS_IMR_MASK(x) ((x) & 0xDF) -#define FW_PS_KEEP_IMR(x) ((x) & 0x20) - -#define FW_PS_STATE_S0 (FW_PS_DPS) -#define FW_PS_STATE_S1 (FW_PS_LCLK) -#define FW_PS_STATE_S2 (FW_PS_RF_OFF) -#define FW_PS_STATE_S3 (FW_PS_ALL_ON) -#define FW_PS_STATE_S4 ((FW_PS_ST_ACTIVE) | (FW_PS_ALL_ON)) -/* ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE))*/ -#define FW_PS_STATE_ALL_ON_88E (FW_PS_CLOCK_ON) -/* (FW_PS_RF_ON)*/ -#define FW_PS_STATE_RF_ON_88E (FW_PS_CLOCK_ON) -/* 0x0*/ -#define FW_PS_STATE_RF_OFF_88E (FW_PS_CLOCK_ON) -/* (FW_PS_STATE_RF_OFF)*/ -#define FW_PS_STATE_RF_OFF_LOW_PWR_88E (FW_PS_CLOCK_OFF) - -#define FW_PS_STATE_ALL_ON_92C (FW_PS_STATE_S4) -#define FW_PS_STATE_RF_ON_92C (FW_PS_STATE_S3) -#define FW_PS_STATE_RF_OFF_92C (FW_PS_STATE_S2) -#define FW_PS_STATE_RF_OFF_LOW_PWR_92C (FW_PS_STATE_S1) - -/* For 88E H2C PwrMode Cmd ID 5.*/ -#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) -#define FW_PWR_STATE_RF_OFF 0 - -#define FW_PS_IS_ACK(x) ((x) & FW_PS_ACK) -#define FW_PS_IS_CLK_ON(x) ((x) & (FW_PS_RF_OFF | FW_PS_ALL_ON)) -#define FW_PS_IS_RF_ON(x) ((x) & (FW_PS_ALL_ON)) -#define FW_PS_IS_ACTIVE(x) ((x) & (FW_PS_ST_ACTIVE)) -#define FW_PS_IS_CPWM_INT(x) ((x) & 0x40) - -#define FW_CLR_PS_STATE(x) ((x) = ((x) & (0xF0))) - -#define IS_IN_LOW_POWER_STATE_88E(fwpsstate) \ - (FW_PS_STATE(fwpsstate) == FW_PS_CLOCK_OFF) - -#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) -#define FW_PWR_STATE_RF_OFF 0 - -enum rtl8188e_h2c_cmd { - H2C_88E_RSVDPAGE = 0, - H2C_88E_JOINBSSRPT = 1, - H2C_88E_SCAN = 2, - H2C_88E_KEEP_ALIVE_CTRL = 3, - H2C_88E_DISCONNECT_DECISION = 4, -#if (USE_OLD_WOWLAN_DEBUG_FW == 1) - H2C_88E_WO_WLAN = 5, -#endif - H2C_88E_INIT_OFFLOAD = 6, -#if (USE_OLD_WOWLAN_DEBUG_FW == 1) - H2C_88E_REMOTE_WAKE_CTRL = 7, -#endif - H2C_88E_AP_OFFLOAD = 8, - H2C_88E_BCN_RSVDPAGE = 9, - H2C_88E_PROBERSP_RSVDPAGE = 10, - - H2C_88E_SETPWRMODE = 0x20, - H2C_88E_PS_TUNING_PARA = 0x21, - H2C_88E_PS_TUNING_PARA2 = 0x22, - H2C_88E_PS_LPS_PARA = 0x23, - H2C_88E_P2P_PS_OFFLOAD = 024, - -#if (USE_OLD_WOWLAN_DEBUG_FW == 0) - H2C_88E_WO_WLAN = 0x80, - H2C_88E_REMOTE_WAKE_CTRL = 0x81, - H2C_88E_AOAC_GLOBAL_INFO = 0x82, - H2C_88E_AOAC_RSVDPAGE = 0x83, -#endif - /*Not defined in new 88E H2C CMD Format*/ - H2C_88E_RA_MASK, - H2C_88E_SELECTIVE_SUSPEND_ROF_CMD, - H2C_88E_P2P_PS_MODE, - H2C_88E_PSD_RESULT, - /*Not defined CTW CMD for P2P yet*/ - H2C_88E_P2P_PS_CTW_CMD, - MAX_88E_H2CCMD -}; - -#define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) - -#define SET_88E_H2CCMD_WOWLAN_FUNC_ENABLE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) -#define SET_88E_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) -#define SET_88E_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value) -#define SET_88E_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value) -#define SET_88E_H2CCMD_WOWLAN_ALL_PKT_DROP(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 4, 1, __value) -#define SET_88E_H2CCMD_WOWLAN_GPIO_ACTIVE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 5, 1, __value) -#define SET_88E_H2CCMD_WOWLAN_REKEY_WAKE_UP(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 6, 1, __value) -#define SET_88E_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 7, 1, __value) -#define SET_88E_H2CCMD_WOWLAN_GPIONUM(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) -#define SET_88E_H2CCMD_WOWLAN_GPIO_DURATION(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) - - -#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_RLBM(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 4, __value) -#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 4, 4, __value) -#define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) -#define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) -#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value) -#define GET_88E_H2CCMD_PWRMODE_PARM_MODE(__cmd) \ - LE_BITS_TO_1BYTE(__cmd, 0, 8) - -#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) - -/* AP_OFFLOAD */ -#define SET_H2CCMD_AP_OFFLOAD_ON(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value) -#define SET_H2CCMD_AP_OFFLOAD_HIDDEN(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) -#define SET_H2CCMD_AP_OFFLOAD_DENYANY(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) -#define SET_H2CCMD_AP_OFFLOAD_WAKEUP_EVT_RPT(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) - -/* Keep Alive Control*/ -#define SET_88E_H2CCMD_KEEP_ALIVE_ENABLE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) -#define SET_88E_H2CCMD_KEEP_ALIVE_ACCPEPT_USER_DEFINED(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) -#define SET_88E_H2CCMD_KEEP_ALIVE_PERIOD(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) - -/*REMOTE_WAKE_CTRL */ -#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_EN(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) -#if (USE_OLD_WOWLAN_DEBUG_FW == 0) -#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) -#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_NDP_OFFLOAD_EN(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value) -#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value) -#else -#define SET_88E_H2_REM_WAKE_ENC_ALG(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) -#define SET_88E_H2CCMD_REMOTE_WAKE_CTRL_GROUP_ENC_ALG(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) -#endif - -/* GTK_OFFLOAD */ -#define SET_88E_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value) -#define SET_88E_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) - -/* AOAC_RSVDPAGE_LOC */ -#define SET_88E_H2CCMD_AOAC_RSVD_LOC_REM_WAKE_CTRL_INFO(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd), 0, 8, __value) -#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) -#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) -#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) -#define SET_88E_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value) - -int rtl88e_download_fw(struct ieee80211_hw *hw, - bool buse_wake_on_wlan_fw); -void rtl88e_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *cmdbuffer); -void rtl88e_firmware_selfreset(struct ieee80211_hw *hw); -void rtl88e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); -void rtl88e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); -void rtl88e_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, - u8 ap_offload_enable); -void rtl88e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); -void rtl88e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c deleted file mode 100644 index 8ee83b093c0d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c +++ /dev/null @@ -1,2599 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../efuse.h" -#include "../base.h" -#include "../regd.h" -#include "../cam.h" -#include "../ps.h" -#include "../pci.h" -#include "../pwrseqcmd.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "fw.h" -#include "led.h" -#include "hw.h" -#include "pwrseq.h" - -#define LLT_CONFIG 5 - -static void _rtl88ee_set_bcn_ctrl_reg(struct ieee80211_hw *hw, - u8 set_bits, u8 clear_bits) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpci->reg_bcn_ctrl_val |= set_bits; - rtlpci->reg_bcn_ctrl_val &= ~clear_bits; - - rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); -} - -static void _rtl88ee_stop_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp1byte; - - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); -} - -static void _rtl88ee_resume_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp1byte; - - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte |= BIT(0); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); -} - -static void _rtl88ee_enable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(1)); -} - -static void _rtl88ee_return_beacon_queue_skb(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; - unsigned long flags; - - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - while (skb_queue_len(&ring->queue)) { - struct rtl_tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb = __skb_dequeue(&ring->queue); - - pci_unmap_single(rtlpci->pdev, - rtlpriv->cfg->ops->get_desc( - (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), - skb->len, PCI_DMA_TODEVICE); - kfree_skb(skb); - ring->idx = (ring->idx + 1) % ring->entries; - } - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); -} - -static void _rtl88ee_disable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl88ee_set_bcn_ctrl_reg(hw, BIT(1), 0); -} - -static void _rtl88ee_set_fw_clock_on(struct ieee80211_hw *hw, - u8 rpwm_val, bool b_need_turn_off_ckk) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool b_support_remote_wake_up; - u32 count = 0, isr_regaddr, content; - bool schedule_timer = b_need_turn_off_ckk; - rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, - (u8 *)(&b_support_remote_wake_up)); - - if (!rtlhal->fw_ready) - return; - if (!rtlpriv->psc.fw_current_inpsmode) - return; - - while (1) { - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - if (rtlhal->fw_clk_change_in_progress) { - while (rtlhal->fw_clk_change_in_progress) { - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - count++; - udelay(100); - if (count > 1000) - return; - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - } - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - } else { - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - break; - } - } - - if (IS_IN_LOW_POWER_STATE_88E(rtlhal->fw_ps_state)) { - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, &rpwm_val); - if (FW_PS_IS_ACK(rpwm_val)) { - isr_regaddr = REG_HISR; - content = rtl_read_dword(rtlpriv, isr_regaddr); - while (!(content & IMR_CPWM) && (count < 500)) { - udelay(50); - count++; - content = rtl_read_dword(rtlpriv, isr_regaddr); - } - - if (content & IMR_CPWM) { - rtl_write_word(rtlpriv, isr_regaddr, 0x0100); - rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_88E; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Receive CPWM INT!!! Set pHalData->FwPSState = %X\n", - rtlhal->fw_ps_state); - } - } - - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - if (schedule_timer) { - mod_timer(&rtlpriv->works.fw_clockoff_timer, - jiffies + MSECS(10)); - } - - } else { - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - } -} - -static void _rtl88ee_set_fw_clock_off(struct ieee80211_hw *hw, - u8 rpwm_val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring; - enum rf_pwrstate rtstate; - bool schedule_timer = false; - u8 queue; - - if (!rtlhal->fw_ready) - return; - if (!rtlpriv->psc.fw_current_inpsmode) - return; - if (!rtlhal->allow_sw_to_change_hwclc) - return; - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate)); - if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF) - return; - - for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) { - ring = &rtlpci->tx_ring[queue]; - if (skb_queue_len(&ring->queue)) { - schedule_timer = true; - break; - } - } - - if (schedule_timer) { - mod_timer(&rtlpriv->works.fw_clockoff_timer, - jiffies + MSECS(10)); - return; - } - - if (FW_PS_STATE(rtlhal->fw_ps_state) != - FW_PS_STATE_RF_OFF_LOW_PWR_88E) { - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - if (!rtlhal->fw_clk_change_in_progress) { - rtlhal->fw_clk_change_in_progress = true; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); - rtl_write_word(rtlpriv, REG_HISR, 0x0100); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - &rpwm_val); - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - } else { - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - mod_timer(&rtlpriv->works.fw_clockoff_timer, - jiffies + MSECS(10)); - } - } -} - -static void _rtl88ee_set_fw_ps_rf_on(struct ieee80211_hw *hw) -{ - u8 rpwm_val = 0; - - rpwm_val |= (FW_PS_STATE_RF_OFF_88E | FW_PS_ACK); - _rtl88ee_set_fw_clock_on(hw, rpwm_val, true); -} - -static void _rtl88ee_set_fw_ps_rf_off_low_power(struct ieee80211_hw *hw) -{ - u8 rpwm_val = 0; - rpwm_val |= FW_PS_STATE_RF_OFF_LOW_PWR_88E; - _rtl88ee_set_fw_clock_off(hw, rpwm_val); -} -void rtl88ee_fw_clk_off_timer_callback(unsigned long data) -{ - struct ieee80211_hw *hw = (struct ieee80211_hw *)data; - - _rtl88ee_set_fw_ps_rf_off_low_power(hw); -} - -static void _rtl88ee_fwlps_leave(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool fw_current_inps = false; - u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE; - - if (ppsc->low_power_enable) { - rpwm_val = (FW_PS_STATE_ALL_ON_88E|FW_PS_ACK);/* RF on */ - _rtl88ee_set_fw_clock_on(hw, rpwm_val, false); - rtlhal->allow_sw_to_change_hwclc = false; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - &fw_pwrmode); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - } else { - rpwm_val = FW_PS_STATE_ALL_ON_88E; /* RF on */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, &rpwm_val); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - &fw_pwrmode); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - } -} - -static void _rtl88ee_fwlps_enter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool fw_current_inps = true; - u8 rpwm_val; - - if (ppsc->low_power_enable) { - rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR_88E; /* RF off */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - &ppsc->fwctrl_psmode); - rtlhal->allow_sw_to_change_hwclc = true; - _rtl88ee_set_fw_clock_off(hw, rpwm_val); - } else { - rpwm_val = FW_PS_STATE_RF_OFF_88E; /* RF off */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - &ppsc->fwctrl_psmode); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, &rpwm_val); - } -} - -void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - switch (variable) { - case HW_VAR_RCR: - *((u32 *)(val)) = rtlpci->receive_config; - break; - case HW_VAR_RF_STATE: - *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; - break; - case HW_VAR_FWLPS_RF_ON:{ - enum rf_pwrstate rfstate; - u32 val_rcr; - - rtlpriv->cfg->ops->get_hw_reg(hw, - HW_VAR_RF_STATE, - (u8 *)(&rfstate)); - if (rfstate == ERFOFF) { - *((bool *)(val)) = true; - } else { - val_rcr = rtl_read_dword(rtlpriv, REG_RCR); - val_rcr &= 0x00070000; - if (val_rcr) - *((bool *)(val)) = false; - else - *((bool *)(val)) = true; - } - break; } - case HW_VAR_FW_PSMODE_STATUS: - *((bool *)(val)) = ppsc->fw_current_inpsmode; - break; - case HW_VAR_CORRECT_TSF:{ - u64 tsf; - u32 *ptsf_low = (u32 *)&tsf; - u32 *ptsf_high = ((u32 *)&tsf) + 1; - - *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); - *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - - *((u64 *)(val)) = tsf; - break; } - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process %x\n", variable); - break; - } -} - -void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 idx; - - switch (variable) { - case HW_VAR_ETHER_ADDR: - for (idx = 0; idx < ETH_ALEN; idx++) { - rtl_write_byte(rtlpriv, (REG_MACID + idx), - val[idx]); - } - break; - case HW_VAR_BASIC_RATE:{ - u16 b_rate_cfg = ((u16 *)val)[0]; - u8 rate_index = 0; - b_rate_cfg = b_rate_cfg & 0x15f; - b_rate_cfg |= 0x01; - rtl_write_byte(rtlpriv, REG_RRSR, b_rate_cfg & 0xff); - rtl_write_byte(rtlpriv, REG_RRSR + 1, - (b_rate_cfg >> 8) & 0xff); - while (b_rate_cfg > 0x1) { - b_rate_cfg = (b_rate_cfg >> 1); - rate_index++; - } - rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, - rate_index); - break; - } - case HW_VAR_BSSID: - for (idx = 0; idx < ETH_ALEN; idx++) { - rtl_write_byte(rtlpriv, (REG_BSSID + idx), - val[idx]); - } - break; - case HW_VAR_SIFS: - rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); - rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); - - rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); - rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); - - if (!mac->ht_enable) - rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, - 0x0e0e); - else - rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, - *((u16 *)val)); - break; - case HW_VAR_SLOT_TIME:{ - u8 e_aci; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "HW_VAR_SLOT_TIME %x\n", val[0]); - - rtl_write_byte(rtlpriv, REG_SLOT, val[0]); - - for (e_aci = 0; e_aci < AC_MAX; e_aci++) { - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, - &e_aci); - } - break; - } - case HW_VAR_ACK_PREAMBLE:{ - u8 reg_tmp; - u8 short_preamble = (bool)*val; - reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL+2); - if (short_preamble) { - reg_tmp |= 0x02; - rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + - 2, reg_tmp); - } else { - reg_tmp |= 0xFD; - rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + - 2, reg_tmp); - } - break; } - case HW_VAR_WPA_CONFIG: - rtl_write_byte(rtlpriv, REG_SECCFG, *val); - break; - case HW_VAR_AMPDU_MIN_SPACE:{ - u8 min_spacing_to_set; - u8 sec_min_space; - - min_spacing_to_set = *val; - if (min_spacing_to_set <= 7) { - sec_min_space = 0; - - if (min_spacing_to_set < sec_min_space) - min_spacing_to_set = sec_min_space; - - mac->min_space_cfg = ((mac->min_space_cfg & - 0xf8) | - min_spacing_to_set); - - *val = min_spacing_to_set; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", - mac->min_space_cfg); - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - } - break; } - case HW_VAR_SHORTGI_DENSITY:{ - u8 density_to_set; - - density_to_set = *val; - mac->min_space_cfg |= (density_to_set << 3); - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_SHORTGI_DENSITY: %#x\n", - mac->min_space_cfg); - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - break; - } - case HW_VAR_AMPDU_FACTOR:{ - u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; - u8 factor_toset; - u8 *p_regtoset = NULL; - u8 index = 0; - - p_regtoset = regtoset_normal; - - factor_toset = *val; - if (factor_toset <= 3) { - factor_toset = (1 << (factor_toset + 2)); - if (factor_toset > 0xf) - factor_toset = 0xf; - - for (index = 0; index < 4; index++) { - if ((p_regtoset[index] & 0xf0) > - (factor_toset << 4)) - p_regtoset[index] = - (p_regtoset[index] & 0x0f) | - (factor_toset << 4); - - if ((p_regtoset[index] & 0x0f) > - factor_toset) - p_regtoset[index] = - (p_regtoset[index] & 0xf0) | - (factor_toset); - - rtl_write_byte(rtlpriv, - (REG_AGGLEN_LMT + index), - p_regtoset[index]); - - } - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_FACTOR: %#x\n", - factor_toset); - } - break; } - case HW_VAR_AC_PARAM:{ - u8 e_aci = *val; - rtl88e_dm_init_edca_turbo(hw); - - if (rtlpci->acm_method != EACMWAY2_SW) - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_ACM_CTRL, - &e_aci); - break; } - case HW_VAR_ACM_CTRL:{ - u8 e_aci = *val; - union aci_aifsn *p_aci_aifsn = - (union aci_aifsn *)(&(mac->ac[0].aifs)); - u8 acm = p_aci_aifsn->f.acm; - u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); - - acm_ctrl = acm_ctrl | - ((rtlpci->acm_method == 2) ? 0x0 : 0x1); - - if (acm) { - switch (e_aci) { - case AC0_BE: - acm_ctrl |= ACMHW_BEQEN; - break; - case AC2_VI: - acm_ctrl |= ACMHW_VIQEN; - break; - case AC3_VO: - acm_ctrl |= ACMHW_VOQEN; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", - acm); - break; - } - } else { - switch (e_aci) { - case AC0_BE: - acm_ctrl &= (~ACMHW_BEQEN); - break; - case AC2_VI: - acm_ctrl &= (~ACMHW_VIQEN); - break; - case AC3_VO: - acm_ctrl &= (~ACMHW_VOQEN); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - } - - RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, - "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", - acm_ctrl); - rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); - break; } - case HW_VAR_RCR: - rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); - rtlpci->receive_config = ((u32 *)(val))[0]; - break; - case HW_VAR_RETRY_LIMIT:{ - u8 retry_limit = *val; - - rtl_write_word(rtlpriv, REG_RL, - retry_limit << RETRY_LIMIT_SHORT_SHIFT | - retry_limit << RETRY_LIMIT_LONG_SHIFT); - break; } - case HW_VAR_DUAL_TSF_RST: - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); - break; - case HW_VAR_EFUSE_BYTES: - rtlefuse->efuse_usedbytes = *((u16 *)val); - break; - case HW_VAR_EFUSE_USAGE: - rtlefuse->efuse_usedpercentage = *val; - break; - case HW_VAR_IO_CMD: - rtl88e_phy_set_io_cmd(hw, (*(enum io_type *)val)); - break; - case HW_VAR_SET_RPWM:{ - u8 rpwm_val; - - rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); - udelay(1); - - if (rpwm_val & BIT(7)) { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, *val); - } else { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, *val | BIT(7)); - } - break; } - case HW_VAR_H2C_FW_PWRMODE: - rtl88e_set_fw_pwrmode_cmd(hw, *val); - break; - case HW_VAR_FW_PSMODE_STATUS: - ppsc->fw_current_inpsmode = *((bool *)val); - break; - case HW_VAR_RESUME_CLK_ON: - _rtl88ee_set_fw_ps_rf_on(hw); - break; - case HW_VAR_FW_LPS_ACTION:{ - bool enter_fwlps = *((bool *)val); - - if (enter_fwlps) - _rtl88ee_fwlps_enter(hw); - else - _rtl88ee_fwlps_leave(hw); - - break; } - case HW_VAR_H2C_FW_JOINBSSRPT:{ - u8 mstatus = *val; - u8 tmp_regcr, tmp_reg422, bcnvalid_reg; - u8 count = 0, dlbcn_count = 0; - bool b_recover = false; - - if (mstatus == RT_MEDIA_CONNECT) { - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, - NULL); - - tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, - (tmp_regcr | BIT(0))); - - _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); - _rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0); - - tmp_reg422 = - rtl_read_byte(rtlpriv, - REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, - tmp_reg422 & (~BIT(6))); - if (tmp_reg422 & BIT(6)) - b_recover = true; - - do { - bcnvalid_reg = rtl_read_byte(rtlpriv, - REG_TDECTRL+2); - rtl_write_byte(rtlpriv, REG_TDECTRL+2, - (bcnvalid_reg | BIT(0))); - _rtl88ee_return_beacon_queue_skb(hw); - - rtl88e_set_fw_rsvdpagepkt(hw, 0); - bcnvalid_reg = rtl_read_byte(rtlpriv, - REG_TDECTRL+2); - count = 0; - while (!(bcnvalid_reg & BIT(0)) && count < 20) { - count++; - udelay(10); - bcnvalid_reg = - rtl_read_byte(rtlpriv, REG_TDECTRL+2); - } - dlbcn_count++; - } while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5); - - if (bcnvalid_reg & BIT(0)) - rtl_write_byte(rtlpriv, REG_TDECTRL+2, BIT(0)); - - _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); - _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); - - if (b_recover) { - rtl_write_byte(rtlpriv, - REG_FWHW_TXQ_CTRL + 2, - tmp_reg422); - } - - rtl_write_byte(rtlpriv, REG_CR + 1, - (tmp_regcr & ~(BIT(0)))); - } - rtl88e_set_fw_joinbss_report_cmd(hw, (*(u8 *)val)); - break; } - case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: - rtl88e_set_p2p_ps_offload_cmd(hw, *val); - break; - case HW_VAR_AID:{ - u16 u2btmp; - - u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); - u2btmp &= 0xC000; - rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | - mac->assoc_id)); - break; } - case HW_VAR_CORRECT_TSF:{ - u8 btype_ibss = *val; - - if (btype_ibss) - _rtl88ee_stop_tx_beacon(hw); - - _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); - - rtl_write_dword(rtlpriv, REG_TSFTR, - (u32)(mac->tsf & 0xffffffff)); - rtl_write_dword(rtlpriv, REG_TSFTR + 4, - (u32)((mac->tsf >> 32) & 0xffffffff)); - - _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); - - if (btype_ibss) - _rtl88ee_resume_tx_beacon(hw); - break; } - case HW_VAR_KEEP_ALIVE: { - u8 array[2]; - - array[0] = 0xff; - array[1] = *((u8 *)val); - rtl88e_fill_h2c_cmd(hw, H2C_88E_KEEP_ALIVE_CTRL, - 2, array); - break; } - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process %x\n", variable); - break; - } -} - -static bool _rtl88ee_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool status = true; - long count = 0; - u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | - _LLT_OP(_LLT_WRITE_ACCESS); - - rtl_write_dword(rtlpriv, REG_LLT_INIT, value); - - do { - value = rtl_read_dword(rtlpriv, REG_LLT_INIT); - if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) - break; - - if (count > POLLING_LLT_THRESHOLD) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to polling write LLT done at address %d!\n", - address); - status = false; - break; - } - } while (++count); - - return status; -} - -static bool _rtl88ee_llt_table_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - unsigned short i; - u8 txpktbuf_bndy; - u8 maxpage; - bool status; - - maxpage = 0xAF; - txpktbuf_bndy = 0xAB; - - rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x01); - rtl_write_dword(rtlpriv, REG_RQPN, 0x80730d29); - - /*0x2600 MaxRxBuff=10k-max(TxReportSize(64*8), WOLPattern(16*24)) */ - rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x25FF0000 | txpktbuf_bndy)); - rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_PBP, 0x11); - rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); - - for (i = 0; i < (txpktbuf_bndy - 1); i++) { - status = _rtl88ee_llt_write(hw, i, i + 1); - if (true != status) - return status; - } - - status = _rtl88ee_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); - if (true != status) - return status; - - for (i = txpktbuf_bndy; i < maxpage; i++) { - status = _rtl88ee_llt_write(hw, i, (i + 1)); - if (true != status) - return status; - } - - status = _rtl88ee_llt_write(hw, maxpage, txpktbuf_bndy); - if (true != status) - return status; - - return true; -} - -static void _rtl88ee_gen_refresh_led_state(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); - - if (rtlpriv->rtlhal.up_first_time) - return; - - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtl88ee_sw_led_on(hw, pLed0); - else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - rtl88ee_sw_led_on(hw, pLed0); - else - rtl88ee_sw_led_off(hw, pLed0); -} - -static bool _rtl88ee_init_mac(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - u8 bytetmp; - u16 wordtmp; - - /*Disable XTAL OUTPUT for power saving. YJ,add,111206. */ - bytetmp = rtl_read_byte(rtlpriv, REG_XCK_OUT_CTRL) & (~BIT(0)); - rtl_write_byte(rtlpriv, REG_XCK_OUT_CTRL, bytetmp); - /*Auto Power Down to CHIP-off State*/ - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7)); - rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); - - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); - /* HW Power on sequence */ - if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, - PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, - RTL8188EE_NIC_ENABLE_FLOW)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "init MAC Fail as rtl_hal_pwrseqcmdparsing\n"); - return false; - } - - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4); - rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp); - - bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2); - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+2, bytetmp|BIT(2)); - - bytetmp = rtl_read_byte(rtlpriv, REG_WATCH_DOG+1); - rtl_write_byte(rtlpriv, REG_WATCH_DOG+1, bytetmp|BIT(7)); - - bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL_EXT+1, bytetmp|BIT(1)); - - bytetmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL); - rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, bytetmp|BIT(1)|BIT(0)); - rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL+1, 2); - rtl_write_word(rtlpriv, REG_TX_RPT_TIME, 0xcdf0); - - /*Add for wake up online*/ - bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR); - - rtl_write_byte(rtlpriv, REG_SYS_CLKR, bytetmp|BIT(3)); - bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG+1); - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG+1, (bytetmp & (~BIT(4)))); - rtl_write_byte(rtlpriv, 0x367, 0x80); - - rtl_write_word(rtlpriv, REG_CR, 0x2ff); - rtl_write_byte(rtlpriv, REG_CR+1, 0x06); - rtl_write_byte(rtlpriv, MSR, 0x00); - - if (!rtlhal->mac_func_enable) { - if (_rtl88ee_llt_table_init(hw) == false) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "LLT table init fail\n"); - return false; - } - } - rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); - rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff); - - wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); - wordtmp &= 0xf; - wordtmp |= 0xE771; - rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); - - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xffff); - rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); - - rtl_write_dword(rtlpriv, REG_BCNQ_DESA, - ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_MGQ_DESA, - (u64) rtlpci->tx_ring[MGNT_QUEUE].dma & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VOQ_DESA, - (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VIQ_DESA, - (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_BEQ_DESA, - (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_BKQ_DESA, - (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_HQ_DESA, - (u64) rtlpci->tx_ring[HIGH_QUEUE].dma & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_RX_DESA, - (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma & - DMA_BIT_MASK(32)); - - /* if we want to support 64 bit DMA, we should set it here, - * but now we do not support 64 bit DMA - */ - rtl_write_dword(rtlpriv, REG_INT_MIG, 0); - - rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0);/*Enable RX DMA */ - - if (rtlhal->earlymode_enable) {/*Early mode enable*/ - bytetmp = rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL); - bytetmp |= 0x1f; - rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, bytetmp); - rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL+3, 0x81); - } - _rtl88ee_gen_refresh_led_state(hw); - return true; -} - -static void _rtl88ee_hw_configure(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 reg_bw_opmode; - u32 reg_ratr, reg_prsr; - - reg_bw_opmode = BW_OPMODE_20MHZ; - reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | - RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; - reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - - rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr); - rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); -} - -static void _rtl88ee_enable_aspm_back_door(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 tmp1byte = 0; - u32 tmp4byte = 0, count = 0; - - rtl_write_word(rtlpriv, 0x354, 0x8104); - rtl_write_word(rtlpriv, 0x358, 0x24); - - rtl_write_word(rtlpriv, 0x350, 0x70c); - rtl_write_byte(rtlpriv, 0x352, 0x2); - tmp1byte = rtl_read_byte(rtlpriv, 0x352); - count = 0; - while (tmp1byte && count < 20) { - udelay(10); - tmp1byte = rtl_read_byte(rtlpriv, 0x352); - count++; - } - if (0 == tmp1byte) { - tmp4byte = rtl_read_dword(rtlpriv, 0x34c); - rtl_write_dword(rtlpriv, 0x348, tmp4byte|BIT(31)); - rtl_write_word(rtlpriv, 0x350, 0xf70c); - rtl_write_byte(rtlpriv, 0x352, 0x1); - } - - tmp1byte = rtl_read_byte(rtlpriv, 0x352); - count = 0; - while (tmp1byte && count < 20) { - udelay(10); - tmp1byte = rtl_read_byte(rtlpriv, 0x352); - count++; - } - - rtl_write_word(rtlpriv, 0x350, 0x718); - rtl_write_byte(rtlpriv, 0x352, 0x2); - tmp1byte = rtl_read_byte(rtlpriv, 0x352); - count = 0; - while (tmp1byte && count < 20) { - udelay(10); - tmp1byte = rtl_read_byte(rtlpriv, 0x352); - count++; - } - - if (ppsc->support_backdoor || (0 == tmp1byte)) { - tmp4byte = rtl_read_dword(rtlpriv, 0x34c); - rtl_write_dword(rtlpriv, 0x348, tmp4byte|BIT(11)|BIT(12)); - rtl_write_word(rtlpriv, 0x350, 0xf718); - rtl_write_byte(rtlpriv, 0x352, 0x1); - } - - tmp1byte = rtl_read_byte(rtlpriv, 0x352); - count = 0; - while (tmp1byte && count < 20) { - udelay(10); - tmp1byte = rtl_read_byte(rtlpriv, 0x352); - count++; - } -} - -void rtl88ee_enable_hw_security_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 sec_reg_value; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", - rtlpriv->sec.pairwise_enc_algorithm, - rtlpriv->sec.group_enc_algorithm); - - if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "not open hw encryption\n"); - return; - } - - sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; - - if (rtlpriv->sec.use_defaultkey) { - sec_reg_value |= SCR_TXUSEDK; - sec_reg_value |= SCR_RXUSEDK; - } - - sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); - - rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "The SECR-value %x\n", sec_reg_value); - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); -} - -int rtl88ee_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - bool rtstatus = true; - int err = 0; - u8 tmp_u1b, u1byte; - unsigned long flags; - - rtlpriv->rtlhal.being_init_adapter = true; - /* As this function can take a very long time (up to 350 ms) - * and can be called with irqs disabled, reenable the irqs - * to let the other devices continue being serviced. - * - * It is safe doing so since our own interrupts will only be enabled - * in a subsequent step. - */ - local_save_flags(flags); - local_irq_enable(); - rtlhal->fw_ready = false; - - rtlpriv->intf_ops->disable_aspm(hw); - - tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CLKR+1); - u1byte = rtl_read_byte(rtlpriv, REG_CR); - if ((tmp_u1b & BIT(3)) && (u1byte != 0 && u1byte != 0xEA)) { - rtlhal->mac_func_enable = true; - } else { - rtlhal->mac_func_enable = false; - rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E; - } - - rtstatus = _rtl88ee_init_mac(hw); - if (rtstatus != true) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); - err = 1; - goto exit; - } - - err = rtl88e_download_fw(hw, false); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Failed to download FW. Init HW without FW now..\n"); - err = 1; - goto exit; - } - rtlhal->fw_ready = true; - /*fw related variable initialize */ - rtlhal->last_hmeboxnum = 0; - rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_88E; - rtlhal->fw_clk_change_in_progress = false; - rtlhal->allow_sw_to_change_hwclc = false; - ppsc->fw_current_inpsmode = false; - - rtl88e_phy_mac_config(hw); - /* because last function modify RCR, so we update - * rcr var here, or TP will unstable for receive_config - * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx - * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 - */ - rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - - rtl88e_phy_bb_config(hw); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); - - rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; - rtl88e_phy_rf_config(hw); - - rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtlphy->rfreg_chnlval[0] = rtlphy->rfreg_chnlval[0] & 0xfff00fff; - - _rtl88ee_hw_configure(hw); - rtl_cam_reset_all_entry(hw); - rtl88ee_enable_hw_security_config(hw); - - rtlhal->mac_func_enable = true; - ppsc->rfpwr_state = ERFON; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); - _rtl88ee_enable_aspm_back_door(hw); - rtlpriv->intf_ops->enable_aspm(hw); - - if (ppsc->rfpwr_state == ERFON) { - if ((rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) || - ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) && - (rtlhal->oem_id == RT_CID_819X_HP))) { - rtl88e_phy_set_rfpath_switch(hw, true); - rtlpriv->dm.fat_table.rx_idle_ant = MAIN_ANT; - } else { - rtl88e_phy_set_rfpath_switch(hw, false); - rtlpriv->dm.fat_table.rx_idle_ant = AUX_ANT; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "rx idle ant %s\n", - (rtlpriv->dm.fat_table.rx_idle_ant == MAIN_ANT) ? - ("MAIN_ANT") : ("AUX_ANT")); - - if (rtlphy->iqk_initialized) { - rtl88e_phy_iq_calibrate(hw, true); - } else { - rtl88e_phy_iq_calibrate(hw, false); - rtlphy->iqk_initialized = true; - } - - rtl88e_dm_check_txpower_tracking(hw); - rtl88e_phy_lc_calibrate(hw); - } - - tmp_u1b = efuse_read_1byte(hw, 0x1FA); - if (!(tmp_u1b & BIT(0))) { - rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "PA BIAS path A\n"); - } - - if (!(tmp_u1b & BIT(4))) { - tmp_u1b = rtl_read_byte(rtlpriv, 0x16); - tmp_u1b &= 0x0F; - rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80); - udelay(10); - rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "under 1.5V\n"); - } - rtl_write_byte(rtlpriv, REG_NAV_CTRL+2, ((30000+127)/128)); - rtl88e_dm_init(hw); -exit: - local_irq_restore(flags); - rtlpriv->rtlhal.being_init_adapter = false; - return err; -} - -static enum version_8188e _rtl88ee_read_chip_version(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - enum version_8188e version = VERSION_UNKNOWN; - u32 value32; - - value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); - if (value32 & TRP_VAUX_EN) { - version = (enum version_8188e) VERSION_TEST_CHIP_88E; - } else { - version = NORMAL_CHIP; - version = version | ((value32 & TYPE_ID) ? RF_TYPE_2T2R : 0); - version = version | ((value32 & VENDOR_ID) ? - CHIP_VENDOR_UMC : 0); - } - - rtlphy->rf_type = RF_1T1R; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ? - "RF_2T2R" : "RF_1T1R"); - - return version; -} - -static int _rtl88ee_set_media_status(struct ieee80211_hw *hw, - enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bt_msr = rtl_read_byte(rtlpriv, MSR) & 0xfc; - enum led_ctl_mode ledaction = LED_CTL_NO_LINK; - u8 mode = MSR_NOLINK; - - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - mode = MSR_NOLINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to NO LINK!\n"); - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - mode = MSR_ADHOC; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to Ad Hoc!\n"); - break; - case NL80211_IFTYPE_STATION: - mode = MSR_INFRA; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to STA!\n"); - break; - case NL80211_IFTYPE_AP: - mode = MSR_AP; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to AP!\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Network type %d not support!\n", type); - return 1; - break; - } - - /* MSR_INFRA == Link in infrastructure network; - * MSR_ADHOC == Link in ad hoc network; - * Therefore, check link state is necessary. - * - * MSR_AP == AP mode; link state is not cared here. - */ - if (mode != MSR_AP && rtlpriv->mac80211.link_state < MAC80211_LINKED) { - mode = MSR_NOLINK; - ledaction = LED_CTL_NO_LINK; - } - - if (mode == MSR_NOLINK || mode == MSR_INFRA) { - _rtl88ee_stop_tx_beacon(hw); - _rtl88ee_enable_bcn_sub_func(hw); - } else if (mode == MSR_ADHOC || mode == MSR_AP) { - _rtl88ee_resume_tx_beacon(hw); - _rtl88ee_disable_bcn_sub_func(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", - mode); - } - - rtl_write_byte(rtlpriv, MSR, bt_msr | mode); - rtlpriv->cfg->ops->led_control(hw, ledaction); - if (mode == MSR_AP) - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); - else - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); - return 0; -} - -void rtl88ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u32 reg_rcr = rtlpci->receive_config; - - if (rtlpriv->psc.rfpwr_state != ERFON) - return; - - if (check_bssid == true) { - reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *)(®_rcr)); - _rtl88ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); - } else if (check_bssid == false) { - reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); - _rtl88ee_set_bcn_ctrl_reg(hw, BIT(4), 0); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_RCR, (u8 *)(®_rcr)); - } - -} - -int rtl88ee_set_network_type(struct ieee80211_hw *hw, - enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (_rtl88ee_set_media_status(hw, type)) - return -EOPNOTSUPP; - - if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { - if (type != NL80211_IFTYPE_AP && - type != NL80211_IFTYPE_MESH_POINT) - rtl88ee_set_check_bssid(hw, true); - } else { - rtl88ee_set_check_bssid(hw, false); - } - - return 0; -} - -/* don't set REG_EDCA_BE_PARAM here - * because mac80211 will send pkt when scan - */ -void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - rtl88e_dm_init_edca_turbo(hw); - switch (aci) { - case AC1_BK: - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); - break; - case AC0_BE: - break; - case AC2_VI: - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); - break; - case AC3_VO: - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); - break; - default: - RT_ASSERT(false, "invalid aci: %d !\n", aci); - break; - } -} - -void rtl88ee_enable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, REG_HIMR, - rtlpci->irq_mask[0] & 0xFFFFFFFF); - rtl_write_dword(rtlpriv, REG_HIMRE, - rtlpci->irq_mask[1] & 0xFFFFFFFF); - rtlpci->irq_enabled = true; - /* there are some C2H CMDs have been sent - * before system interrupt is enabled, e.g., C2H, CPWM. - * So we need to clear all C2H events that FW has notified, - * otherwise FW won't schedule any commands anymore. - */ - rtl_write_byte(rtlpriv, REG_C2HEVT_CLEAR, 0); - /*enable system interrupt*/ - rtl_write_dword(rtlpriv, REG_HSIMR, - rtlpci->sys_irq_mask & 0xFFFFFFFF); -} - -void rtl88ee_disable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED); - rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED); - rtlpci->irq_enabled = false; - /*synchronize_irq(rtlpci->pdev->irq);*/ -} - -static void _rtl88ee_poweroff_adapter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 u1b_tmp; - u32 count = 0; - rtlhal->mac_func_enable = false; - rtlpriv->intf_ops->enable_aspm(hw); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "POWER OFF adapter\n"); - u1b_tmp = rtl_read_byte(rtlpriv, REG_TX_RPT_CTRL); - rtl_write_byte(rtlpriv, REG_TX_RPT_CTRL, u1b_tmp & (~BIT(1))); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - while (!(u1b_tmp & BIT(1)) && (count++ < 100)) { - udelay(10); - u1b_tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - count++; - } - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+1, 0xFF); - - rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, - RTL8188EE_NIC_LPS_ENTER_FLOW); - - rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); - - if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready) - rtl88e_firmware_selfreset(hw); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_32K_CTRL); - rtl_write_byte(rtlpriv, REG_32K_CTRL, (u1b_tmp & (~BIT(0)))); - - rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, RTL8188EE_NIC_DISABLE_FLOW); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp & (~BIT(3)))); - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp | BIT(3))); - - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E); - - u1b_tmp = rtl_read_byte(rtlpriv, GPIO_IN); - rtl_write_byte(rtlpriv, GPIO_OUT, u1b_tmp); - rtl_write_byte(rtlpriv, GPIO_IO_SEL, 0x7F); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); - rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL, (u1b_tmp << 4) | u1b_tmp); - u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL+1); - rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL+1, u1b_tmp | 0x0F); - - rtl_write_dword(rtlpriv, REG_GPIO_IO_SEL_2+2, 0x00080808); -} - -void rtl88ee_card_disable(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - enum nl80211_iftype opmode; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RTL8188ee card disable\n"); - - mac->link_state = MAC80211_NOLINK; - opmode = NL80211_IFTYPE_UNSPECIFIED; - - _rtl88ee_set_media_status(hw, opmode); - - if (rtlpriv->rtlhal.driver_is_goingto_unload || - ppsc->rfoff_reason > RF_CHANGE_BY_PS) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); - - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - _rtl88ee_poweroff_adapter(hw); - - /* after power off we should do iqk again */ - rtlpriv->phy.iqk_initialized = false; -} - -void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; - rtl_write_dword(rtlpriv, ISR, *p_inta); - - *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; - rtl_write_dword(rtlpriv, REG_HISRE, *p_intb); - -} - -void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u16 bcn_interval, atim_window; - - bcn_interval = mac->beacon_interval; - atim_window = 2; /*FIX MERGE */ - rtl88ee_disable_interrupt(hw); - rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); - rtl_write_byte(rtlpriv, 0x606, 0x30); - rtlpci->reg_bcn_ctrl_val |= BIT(3); - rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); - /*rtl88ee_enable_interrupt(hw);*/ -} - -void rtl88ee_set_beacon_interval(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval = mac->beacon_interval; - - RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, - "beacon_interval:%d\n", bcn_interval); - /*rtl88ee_disable_interrupt(hw);*/ - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - /*rtl88ee_enable_interrupt(hw);*/ -} - -void rtl88ee_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, - "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); - - if (add_msr) - rtlpci->irq_mask[0] |= add_msr; - if (rm_msr) - rtlpci->irq_mask[0] &= (~rm_msr); - rtl88ee_disable_interrupt(hw); - rtl88ee_enable_interrupt(hw); -} - -static u8 _rtl88e_get_chnl_group(u8 chnl) -{ - u8 group = 0; - - if (chnl < 3) - group = 0; - else if (chnl < 6) - group = 1; - else if (chnl < 9) - group = 2; - else if (chnl < 12) - group = 3; - else if (chnl < 14) - group = 4; - else if (chnl == 14) - group = 5; - - return group; -} - -static void set_24g_base(struct txpower_info_2g *pwrinfo24g, u32 rfpath) -{ - int group, txcnt; - - for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { - pwrinfo24g->index_cck_base[rfpath][group] = 0x2D; - pwrinfo24g->index_bw40_base[rfpath][group] = 0x2D; - } - for (txcnt = 0; txcnt < MAX_TX_COUNT; txcnt++) { - if (txcnt == 0) { - pwrinfo24g->bw20_diff[rfpath][0] = 0x02; - pwrinfo24g->ofdm_diff[rfpath][0] = 0x04; - } else { - pwrinfo24g->bw20_diff[rfpath][txcnt] = 0xFE; - pwrinfo24g->bw40_diff[rfpath][txcnt] = 0xFE; - pwrinfo24g->cck_diff[rfpath][txcnt] = 0xFE; - pwrinfo24g->ofdm_diff[rfpath][txcnt] = 0xFE; - } - } -} - -static void read_power_value_fromprom(struct ieee80211_hw *hw, - struct txpower_info_2g *pwrinfo24g, - struct txpower_info_5g *pwrinfo5g, - bool autoload_fail, u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 rfpath, eeaddr = EEPROM_TX_PWR_INX, group, txcnt = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "hal_ReadPowerValueFromPROM88E():PROMContent[0x%x]=0x%x\n", - (eeaddr+1), hwinfo[eeaddr+1]); - if (0xFF == hwinfo[eeaddr+1]) /*YJ,add,120316*/ - autoload_fail = true; - - if (autoload_fail) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "auto load fail : Use Default value!\n"); - for (rfpath = 0 ; rfpath < MAX_RF_PATH ; rfpath++) { - /* 2.4G default value */ - set_24g_base(pwrinfo24g, rfpath); - } - return; - } - - for (rfpath = 0 ; rfpath < MAX_RF_PATH ; rfpath++) { - /*2.4G default value*/ - for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { - pwrinfo24g->index_cck_base[rfpath][group] = - hwinfo[eeaddr++]; - if (pwrinfo24g->index_cck_base[rfpath][group] == 0xFF) - pwrinfo24g->index_cck_base[rfpath][group] = - 0x2D; - } - for (group = 0 ; group < MAX_CHNL_GROUP_24G-1; group++) { - pwrinfo24g->index_bw40_base[rfpath][group] = - hwinfo[eeaddr++]; - if (pwrinfo24g->index_bw40_base[rfpath][group] == 0xFF) - pwrinfo24g->index_bw40_base[rfpath][group] = - 0x2D; - } - pwrinfo24g->bw40_diff[rfpath][0] = 0; - if (hwinfo[eeaddr] == 0xFF) { - pwrinfo24g->bw20_diff[rfpath][0] = 0x02; - } else { - pwrinfo24g->bw20_diff[rfpath][0] = - (hwinfo[eeaddr]&0xf0)>>4; - /*bit sign number to 8 bit sign number*/ - if (pwrinfo24g->bw20_diff[rfpath][0] & BIT(3)) - pwrinfo24g->bw20_diff[rfpath][0] |= 0xF0; - } - - if (hwinfo[eeaddr] == 0xFF) { - pwrinfo24g->ofdm_diff[rfpath][0] = 0x04; - } else { - pwrinfo24g->ofdm_diff[rfpath][0] = - (hwinfo[eeaddr]&0x0f); - /*bit sign number to 8 bit sign number*/ - if (pwrinfo24g->ofdm_diff[rfpath][0] & BIT(3)) - pwrinfo24g->ofdm_diff[rfpath][0] |= 0xF0; - } - pwrinfo24g->cck_diff[rfpath][0] = 0; - eeaddr++; - for (txcnt = 1; txcnt < MAX_TX_COUNT; txcnt++) { - if (hwinfo[eeaddr] == 0xFF) { - pwrinfo24g->bw40_diff[rfpath][txcnt] = 0xFE; - } else { - pwrinfo24g->bw40_diff[rfpath][txcnt] = - (hwinfo[eeaddr]&0xf0)>>4; - if (pwrinfo24g->bw40_diff[rfpath][txcnt] & - BIT(3)) - pwrinfo24g->bw40_diff[rfpath][txcnt] |= - 0xF0; - } - - if (hwinfo[eeaddr] == 0xFF) { - pwrinfo24g->bw20_diff[rfpath][txcnt] = - 0xFE; - } else { - pwrinfo24g->bw20_diff[rfpath][txcnt] = - (hwinfo[eeaddr]&0x0f); - if (pwrinfo24g->bw20_diff[rfpath][txcnt] & - BIT(3)) - pwrinfo24g->bw20_diff[rfpath][txcnt] |= - 0xF0; - } - eeaddr++; - - if (hwinfo[eeaddr] == 0xFF) { - pwrinfo24g->ofdm_diff[rfpath][txcnt] = 0xFE; - } else { - pwrinfo24g->ofdm_diff[rfpath][txcnt] = - (hwinfo[eeaddr]&0xf0)>>4; - if (pwrinfo24g->ofdm_diff[rfpath][txcnt] & - BIT(3)) - pwrinfo24g->ofdm_diff[rfpath][txcnt] |= - 0xF0; - } - - if (hwinfo[eeaddr] == 0xFF) { - pwrinfo24g->cck_diff[rfpath][txcnt] = 0xFE; - } else { - pwrinfo24g->cck_diff[rfpath][txcnt] = - (hwinfo[eeaddr]&0x0f); - if (pwrinfo24g->cck_diff[rfpath][txcnt] & - BIT(3)) - pwrinfo24g->cck_diff[rfpath][txcnt] |= - 0xF0; - } - eeaddr++; - } - - /*5G default value*/ - for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) { - pwrinfo5g->index_bw40_base[rfpath][group] = - hwinfo[eeaddr++]; - if (pwrinfo5g->index_bw40_base[rfpath][group] == 0xFF) - pwrinfo5g->index_bw40_base[rfpath][group] = - 0xFE; - } - - pwrinfo5g->bw40_diff[rfpath][0] = 0; - - if (hwinfo[eeaddr] == 0xFF) { - pwrinfo5g->bw20_diff[rfpath][0] = 0; - } else { - pwrinfo5g->bw20_diff[rfpath][0] = - (hwinfo[eeaddr]&0xf0)>>4; - if (pwrinfo5g->bw20_diff[rfpath][0] & BIT(3)) - pwrinfo5g->bw20_diff[rfpath][0] |= 0xF0; - } - - if (hwinfo[eeaddr] == 0xFF) { - pwrinfo5g->ofdm_diff[rfpath][0] = 0x04; - } else { - pwrinfo5g->ofdm_diff[rfpath][0] = (hwinfo[eeaddr]&0x0f); - if (pwrinfo5g->ofdm_diff[rfpath][0] & BIT(3)) - pwrinfo5g->ofdm_diff[rfpath][0] |= 0xF0; - } - eeaddr++; - for (txcnt = 1; txcnt < MAX_TX_COUNT; txcnt++) { - if (hwinfo[eeaddr] == 0xFF) { - pwrinfo5g->bw40_diff[rfpath][txcnt] = 0xFE; - } else { - pwrinfo5g->bw40_diff[rfpath][txcnt] = - (hwinfo[eeaddr]&0xf0)>>4; - if (pwrinfo5g->bw40_diff[rfpath][txcnt] & - BIT(3)) - pwrinfo5g->bw40_diff[rfpath][txcnt] |= - 0xF0; - } - - if (hwinfo[eeaddr] == 0xFF) { - pwrinfo5g->bw20_diff[rfpath][txcnt] = 0xFE; - } else { - pwrinfo5g->bw20_diff[rfpath][txcnt] = - (hwinfo[eeaddr]&0x0f); - if (pwrinfo5g->bw20_diff[rfpath][txcnt] & - BIT(3)) - pwrinfo5g->bw20_diff[rfpath][txcnt] |= - 0xF0; - } - eeaddr++; - } - - if (hwinfo[eeaddr] == 0xFF) { - pwrinfo5g->ofdm_diff[rfpath][1] = 0xFE; - pwrinfo5g->ofdm_diff[rfpath][2] = 0xFE; - } else { - pwrinfo5g->ofdm_diff[rfpath][1] = - (hwinfo[eeaddr]&0xf0)>>4; - pwrinfo5g->ofdm_diff[rfpath][2] = - (hwinfo[eeaddr]&0x0f); - } - eeaddr++; - - if (hwinfo[eeaddr] == 0xFF) - pwrinfo5g->ofdm_diff[rfpath][3] = 0xFE; - else - pwrinfo5g->ofdm_diff[rfpath][3] = (hwinfo[eeaddr]&0x0f); - eeaddr++; - - for (txcnt = 1; txcnt < MAX_TX_COUNT; txcnt++) { - if (pwrinfo5g->ofdm_diff[rfpath][txcnt] == 0xFF) - pwrinfo5g->ofdm_diff[rfpath][txcnt] = 0xFE; - else if (pwrinfo5g->ofdm_diff[rfpath][txcnt] & BIT(3)) - pwrinfo5g->ofdm_diff[rfpath][txcnt] |= 0xF0; - } - } -} - -static void _rtl88ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct txpower_info_2g pwrinfo24g; - struct txpower_info_5g pwrinfo5g; - u8 rf_path, index; - u8 i; - - read_power_value_fromprom(hw, &pwrinfo24g, - &pwrinfo5g, autoload_fail, hwinfo); - - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < 14; i++) { - index = _rtl88e_get_chnl_group(i+1); - - rtlefuse->txpwrlevel_cck[rf_path][i] = - pwrinfo24g.index_cck_base[rf_path][index]; - rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = - pwrinfo24g.index_bw40_base[rf_path][index]; - rtlefuse->txpwr_ht20diff[rf_path][i] = - pwrinfo24g.bw20_diff[rf_path][0]; - rtlefuse->txpwr_legacyhtdiff[rf_path][i] = - pwrinfo24g.ofdm_diff[rf_path][0]; - } - - for (i = 0; i < 14; i++) { - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF(%d)-Ch(%d) [CCK / HT40_1S ] = [0x%x / 0x%x ]\n", - rf_path, i, - rtlefuse->txpwrlevel_cck[rf_path][i], - rtlefuse->txpwrlevel_ht40_1s[rf_path][i]); - } - } - - if (!autoload_fail) - rtlefuse->eeprom_thermalmeter = - hwinfo[EEPROM_THERMAL_METER_88E]; - else - rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; - - if (rtlefuse->eeprom_thermalmeter == 0xff || autoload_fail) { - rtlefuse->apk_thermalmeterignore = true; - rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; - } - - rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); - - if (!autoload_fail) { - rtlefuse->eeprom_regulatory = - hwinfo[EEPROM_RF_BOARD_OPTION_88E] & 0x07;/*bit0~2*/ - if (hwinfo[EEPROM_RF_BOARD_OPTION_88E] == 0xFF) - rtlefuse->eeprom_regulatory = 0; - } else { - rtlefuse->eeprom_regulatory = 0; - } - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); -} - -static void _rtl88ee_read_adapter_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u16 i, usvalue; - u8 hwinfo[HWSET_MAX_SIZE]; - u16 eeprom_id; - - if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { - rtl_efuse_shadow_map_update(hw); - - memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], - HWSET_MAX_SIZE); - } else if (rtlefuse->epromtype == EEPROM_93C46) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "RTL819X Not boot from eeprom, check it !!"); - return; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "boot from neither eeprom nor efuse, check it !!"); - return; - } - - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP\n", - hwinfo, HWSET_MAX_SIZE); - - eeprom_id = *((u16 *)&hwinfo[0]); - if (eeprom_id != RTL8188E_EEPROM_ID) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "EEPROM ID(%#x) is invalid!!\n", eeprom_id); - rtlefuse->autoload_failflag = true; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - } - - if (rtlefuse->autoload_failflag == true) - return; - /*VID DID SVID SDID*/ - rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; - rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; - rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; - rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROMId = 0x%4x\n", eeprom_id); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); - /*customer ID*/ - rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; - if (rtlefuse->eeprom_oemid == 0xFF) - rtlefuse->eeprom_oemid = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); - /*EEPROM version*/ - rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; - /*mac address*/ - for (i = 0; i < 6; i += 2) { - usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; - *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "dev_addr: %pM\n", rtlefuse->dev_addr); - /*channel plan */ - rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; - /* set channel plan from efuse */ - rtlefuse->channel_plan = rtlefuse->eeprom_channelplan; - /*tx power*/ - _rtl88ee_read_txpower_info_from_hwpg(hw, - rtlefuse->autoload_failflag, - hwinfo); - rtlefuse->txpwr_fromeprom = true; - - rtl8188ee_read_bt_coexist_info_from_hwpg(hw, - rtlefuse->autoload_failflag, - hwinfo); - - /*board type*/ - rtlefuse->board_type = - ((hwinfo[EEPROM_RF_BOARD_OPTION_88E] & 0xE0) >> 5); - rtlhal->board_type = rtlefuse->board_type; - /*Wake on wlan*/ - rtlefuse->wowlan_enable = - ((hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & 0x40) >> 6); - /*parse xtal*/ - rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_88E]; - if (hwinfo[EEPROM_XTAL_88E]) - rtlefuse->crystalcap = 0x20; - /*antenna diversity*/ - rtlefuse->antenna_div_cfg = - (hwinfo[EEPROM_RF_BOARD_OPTION_88E] & 0x18) >> 3; - if (hwinfo[EEPROM_RF_BOARD_OPTION_88E] == 0xFF) - rtlefuse->antenna_div_cfg = 0; - if (rtlpriv->btcoexist.eeprom_bt_coexist != 0 && - rtlpriv->btcoexist.eeprom_bt_ant_num == ANT_X1) - rtlefuse->antenna_div_cfg = 0; - - rtlefuse->antenna_div_type = hwinfo[EEPROM_RF_ANTENNA_OPT_88E]; - if (rtlefuse->antenna_div_type == 0xFF) - rtlefuse->antenna_div_type = 0x01; - if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV || - rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) - rtlefuse->antenna_div_cfg = 1; - - if (rtlhal->oem_id == RT_CID_DEFAULT) { - switch (rtlefuse->eeprom_oemid) { - case EEPROM_CID_DEFAULT: - if (rtlefuse->eeprom_did == 0x8179) { - if (rtlefuse->eeprom_svid == 0x1025) { - rtlhal->oem_id = RT_CID_819X_ACER; - } else if ((rtlefuse->eeprom_svid == 0x10EC && - rtlefuse->eeprom_smid == 0x0179) || - (rtlefuse->eeprom_svid == 0x17AA && - rtlefuse->eeprom_smid == 0x0179)) { - rtlhal->oem_id = RT_CID_819X_LENOVO; - } else if (rtlefuse->eeprom_svid == 0x103c && - rtlefuse->eeprom_smid == 0x197d) { - rtlhal->oem_id = RT_CID_819X_HP; - } else { - rtlhal->oem_id = RT_CID_DEFAULT; - } - } else { - rtlhal->oem_id = RT_CID_DEFAULT; - } - break; - case EEPROM_CID_TOSHIBA: - rtlhal->oem_id = RT_CID_TOSHIBA; - break; - case EEPROM_CID_QMI: - rtlhal->oem_id = RT_CID_819X_QMI; - break; - case EEPROM_CID_WHQL: - default: - rtlhal->oem_id = RT_CID_DEFAULT; - break; - - } - } -} - -static void _rtl88ee_hal_customized_behavior(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - pcipriv->ledctl.led_opendrain = true; - - switch (rtlhal->oem_id) { - case RT_CID_819X_HP: - pcipriv->ledctl.led_opendrain = true; - break; - case RT_CID_819X_LENOVO: - case RT_CID_DEFAULT: - case RT_CID_TOSHIBA: - case RT_CID_CCX: - case RT_CID_819X_ACER: - case RT_CID_WHQL: - default: - break; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "RT Customized ID: 0x%02X\n", rtlhal->oem_id); -} - -void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_u1b; - - rtlhal->version = _rtl88ee_read_chip_version(hw); - if (get_rf_type(rtlphy) == RF_1T1R) - rtlpriv->dm.rfpath_rxenable[0] = true; - else - rtlpriv->dm.rfpath_rxenable[0] = - rtlpriv->dm.rfpath_rxenable[1] = true; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", - rtlhal->version); - tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); - if (tmp_u1b & BIT(4)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); - rtlefuse->epromtype = EEPROM_93C46; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); - rtlefuse->epromtype = EEPROM_BOOT_EFUSE; - } - if (tmp_u1b & BIT(5)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - _rtl88ee_read_adapter_info(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); - } - _rtl88ee_hal_customized_behavior(hw); -} - -static void rtl88ee_update_hal_rate_table(struct ieee80211_hw *hw, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 ratr_value; - u8 ratr_index = 0; - u8 b_nmode = mac->ht_enable; - /*u8 mimo_ps = IEEE80211_SMPS_OFF;*/ - u16 shortgi_rate; - u32 tmp_ratr_value; - u8 curtxbw_40mhz = mac->bw_40; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = mac->mode; - u32 ratr_mask; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_value = sta->supp_rates[1] << 4; - else - ratr_value = sta->supp_rates[0]; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_value = 0xfff; - ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - if (ratr_value & 0x0000000c) - ratr_value &= 0x0000000d; - else - ratr_value &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_value &= 0x00000FF5; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - b_nmode = 1; - if (get_rf_type(rtlphy) == RF_1T2R || - get_rf_type(rtlphy) == RF_1T1R) - ratr_mask = 0x000ff005; - else - ratr_mask = 0x0f0ff005; - - ratr_value &= ratr_mask; - break; - default: - if (rtlphy->rf_type == RF_1T2R) - ratr_value &= 0x000ff0ff; - else - ratr_value &= 0x0f0ff0ff; - - break; - } - - if ((rtlpriv->btcoexist.bt_coexistence) && - (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4) && - (rtlpriv->btcoexist.bt_cur_state) && - (rtlpriv->btcoexist.bt_ant_isolation) && - ((rtlpriv->btcoexist.bt_service == BT_SCO) || - (rtlpriv->btcoexist.bt_service == BT_BUSY))) - ratr_value &= 0x0fffcfc0; - else - ratr_value &= 0x0FFFFFFF; - - if (b_nmode && - ((curtxbw_40mhz && curshortgi_40mhz) || - (!curtxbw_40mhz && curshortgi_20mhz))) { - ratr_value |= 0x10000000; - tmp_ratr_value = (ratr_value >> 12); - - for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { - if ((1 << shortgi_rate) & tmp_ratr_value) - break; - } - - shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | - (shortgi_rate << 4) | (shortgi_rate); - } - - rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)); -} - -static void rtl88ee_update_hal_rate_mask(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - u32 ratr_bitmap; - u8 ratr_index; - u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) - ? 1 : 0; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = 0; - bool b_shortgi = false; - u8 rate_mask[5]; - u8 macid = 0; - /*u8 mimo_ps = IEEE80211_SMPS_OFF;*/ - - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - wirelessmode = sta_entry->wireless_mode; - if (mac->opmode == NL80211_IFTYPE_STATION || - mac->opmode == NL80211_IFTYPE_MESH_POINT) - curtxbw_40mhz = mac->bw_40; - else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) - macid = sta->aid + 1; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_bitmap = sta->supp_rates[1] << 4; - else - ratr_bitmap = sta->supp_rates[0]; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_bitmap = 0xfff; - ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - ratr_index = RATR_INX_WIRELESS_B; - if (ratr_bitmap & 0x0000000c) - ratr_bitmap &= 0x0000000d; - else - ratr_bitmap &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_index = RATR_INX_WIRELESS_GB; - - if (rssi_level == 1) - ratr_bitmap &= 0x00000f00; - else if (rssi_level == 2) - ratr_bitmap &= 0x00000ff0; - else - ratr_bitmap &= 0x00000ff5; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - ratr_index = RATR_INX_WIRELESS_NGB; - if (rtlphy->rf_type == RF_1T2R || - rtlphy->rf_type == RF_1T1R) { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff005; - } - } else { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x0f8f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0f8ff000; - else - ratr_bitmap &= 0x0f8ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x0f8f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0f8ff000; - else - ratr_bitmap &= 0x0f8ff005; - } - } - /*}*/ - - if ((curtxbw_40mhz && curshortgi_40mhz) || - (!curtxbw_40mhz && curshortgi_20mhz)) { - - if (macid == 0) - b_shortgi = true; - else if (macid == 1) - b_shortgi = false; - } - break; - default: - ratr_index = RATR_INX_WIRELESS_NGB; - - if (rtlphy->rf_type == RF_1T2R) - ratr_bitmap &= 0x000ff0ff; - else - ratr_bitmap &= 0x0f0ff0ff; - break; - } - sta_entry->ratr_index = ratr_index; - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "ratr_bitmap :%x\n", ratr_bitmap); - *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | - (ratr_index << 28); - rate_mask[4] = macid | (b_shortgi ? 0x20 : 0x00) | 0x80; - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n", - ratr_index, ratr_bitmap, - rate_mask[0], rate_mask[1], - rate_mask[2], rate_mask[3], - rate_mask[4]); - rtl88e_fill_h2c_cmd(hw, H2C_88E_RA_MASK, 5, rate_mask); - _rtl88ee_set_bcn_ctrl_reg(hw, BIT(3), 0); -} - -void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->dm.useramask) - rtl88ee_update_hal_rate_mask(hw, sta, rssi_level); - else - rtl88ee_update_hal_rate_table(hw, sta); -} - -void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 sifs_timer; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, &mac->slot_time); - if (!mac->ht_enable) - sifs_timer = 0x0a0a; - else - sifs_timer = 0x0e0e; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); -} - -bool rtl88ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; - u32 u4tmp; - bool b_actuallyset = false; - - if (rtlpriv->rtlhal.being_init_adapter) - return false; - - if (ppsc->swrf_processing) - return false; - - spin_lock(&rtlpriv->locks.rf_ps_lock); - if (ppsc->rfchange_inprogress) { - spin_unlock(&rtlpriv->locks.rf_ps_lock); - return false; - } else { - ppsc->rfchange_inprogress = true; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } - - cur_rfstate = ppsc->rfpwr_state; - - u4tmp = rtl_read_dword(rtlpriv, REG_GPIO_OUTPUT); - e_rfpowerstate_toset = (u4tmp & BIT(31)) ? ERFON : ERFOFF; - - if (ppsc->hwradiooff && (e_rfpowerstate_toset == ERFON)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "GPIOChangeRF - HW Radio ON, RF ON\n"); - - e_rfpowerstate_toset = ERFON; - ppsc->hwradiooff = false; - b_actuallyset = true; - } else if ((!ppsc->hwradiooff) && - (e_rfpowerstate_toset == ERFOFF)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "GPIOChangeRF - HW Radio OFF, RF OFF\n"); - - e_rfpowerstate_toset = ERFOFF; - ppsc->hwradiooff = true; - b_actuallyset = true; - } - - if (b_actuallyset) { - spin_lock(&rtlpriv->locks.rf_ps_lock); - ppsc->rfchange_inprogress = false; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } else { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - - spin_lock(&rtlpriv->locks.rf_ps_lock); - ppsc->rfchange_inprogress = false; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } - - *valid = 1; - return !ppsc->hwradiooff; - -} - -void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 *macaddr = p_macaddr; - u32 entry_id = 0; - bool is_pairwise = false; - static u8 cam_const_addr[4][6] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} - }; - static u8 cam_const_broad[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - - if (clear_all) { - u8 idx = 0; - u8 cam_offset = 0; - u8 clear_number = 5; - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); - - for (idx = 0; idx < clear_number; idx++) { - rtl_cam_mark_invalid(hw, cam_offset + idx); - rtl_cam_empty_entry(hw, cam_offset + idx); - - if (idx < 5) { - memset(rtlpriv->sec.key_buf[idx], 0, - MAX_KEY_LEN); - rtlpriv->sec.key_len[idx] = 0; - } - } - - } else { - switch (enc_algo) { - case WEP40_ENCRYPTION: - enc_algo = CAM_WEP40; - break; - case WEP104_ENCRYPTION: - enc_algo = CAM_WEP104; - break; - case TKIP_ENCRYPTION: - enc_algo = CAM_TKIP; - break; - case AESCCMP_ENCRYPTION: - enc_algo = CAM_AES; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - enc_algo = CAM_TKIP; - break; - } - - if (is_wepkey || rtlpriv->sec.use_defaultkey) { - macaddr = cam_const_addr[key_index]; - entry_id = key_index; - } else { - if (is_group) { - macaddr = cam_const_broad; - entry_id = key_index; - } else { - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - entry_id = - rtl_cam_get_free_entry(hw, p_macaddr); - if (entry_id >= TOTAL_CAM_ENTRY) { - RT_TRACE(rtlpriv, COMP_SEC, - DBG_EMERG, - "Can not find free hw security cam entry\n"); - return; - } - } else { - entry_id = CAM_PAIRWISE_KEY_POSITION; - } - key_index = PAIRWISE_KEYIDX; - is_pairwise = true; - } - } - - if (rtlpriv->sec.key_len[key_index] == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "delete one entry, entry_id is %d\n", - entry_id); - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_MESH_POINT) - rtl_cam_del_entry(hw, p_macaddr); - rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "add one entry\n"); - if (is_pairwise) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set Pairwise key\n"); - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[key_index]); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set group key\n"); - - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - rtl_cam_add_one_entry(hw, - rtlefuse->dev_addr, - PAIRWISE_KEYIDX, - CAM_PAIRWISE_KEY_POSITION, - enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf - [entry_id]); - } - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[entry_id]); - } - - } - } -} - -static void rtl8188ee_bt_var_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->btcoexist.bt_coexistence = - rtlpriv->btcoexist.eeprom_bt_coexist; - rtlpriv->btcoexist.bt_ant_num = rtlpriv->btcoexist.eeprom_bt_ant_num; - rtlpriv->btcoexist.bt_coexist_type = rtlpriv->btcoexist.eeprom_bt_type; - - if (rtlpriv->btcoexist.reg_bt_iso == 2) - rtlpriv->btcoexist.bt_ant_isolation = - rtlpriv->btcoexist.eeprom_bt_ant_isol; - else - rtlpriv->btcoexist.bt_ant_isolation = - rtlpriv->btcoexist.reg_bt_iso; - - rtlpriv->btcoexist.bt_radio_shared_type = - rtlpriv->btcoexist.eeprom_bt_radio_shared; - - if (rtlpriv->btcoexist.bt_coexistence) { - if (rtlpriv->btcoexist.reg_bt_sco == 1) - rtlpriv->btcoexist.bt_service = BT_OTHER_ACTION; - else if (rtlpriv->btcoexist.reg_bt_sco == 2) - rtlpriv->btcoexist.bt_service = BT_SCO; - else if (rtlpriv->btcoexist.reg_bt_sco == 4) - rtlpriv->btcoexist.bt_service = BT_BUSY; - else if (rtlpriv->btcoexist.reg_bt_sco == 5) - rtlpriv->btcoexist.bt_service = BT_OTHERBUSY; - else - rtlpriv->btcoexist.bt_service = BT_IDLE; - - rtlpriv->btcoexist.bt_edca_ul = 0; - rtlpriv->btcoexist.bt_edca_dl = 0; - rtlpriv->btcoexist.bt_rssi_state = 0xff; - } -} - -void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool auto_load_fail, u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value; - - if (!auto_load_fail) { - rtlpriv->btcoexist.eeprom_bt_coexist = - ((hwinfo[EEPROM_RF_FEATURE_OPTION_88E] & 0xe0) >> 5); - if (hwinfo[EEPROM_RF_FEATURE_OPTION_88E] == 0xFF) - rtlpriv->btcoexist.eeprom_bt_coexist = 0; - value = hwinfo[EEPROM_RF_BT_SETTING_88E]; - rtlpriv->btcoexist.eeprom_bt_type = ((value & 0xe) >> 1); - rtlpriv->btcoexist.eeprom_bt_ant_num = (value & 0x1); - rtlpriv->btcoexist.eeprom_bt_ant_isol = ((value & 0x10) >> 4); - rtlpriv->btcoexist.eeprom_bt_radio_shared = - ((value & 0x20) >> 5); - } else { - rtlpriv->btcoexist.eeprom_bt_coexist = 0; - rtlpriv->btcoexist.eeprom_bt_type = BT_2WIRE; - rtlpriv->btcoexist.eeprom_bt_ant_num = ANT_X2; - rtlpriv->btcoexist.eeprom_bt_ant_isol = 0; - rtlpriv->btcoexist.eeprom_bt_radio_shared = BT_RADIO_SHARED; - } - - rtl8188ee_bt_var_init(hw); -} - -void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /* 0:Low, 1:High, 2:From Efuse. */ - rtlpriv->btcoexist.reg_bt_iso = 2; - /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ - rtlpriv->btcoexist.reg_bt_sco = 3; - /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ - rtlpriv->btcoexist.reg_bt_sco = 0; -} - -void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 u1_tmp; - - if (rtlpriv->btcoexist.bt_coexistence && - ((rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4) || - rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC8)) { - if (rtlpriv->btcoexist.bt_ant_isolation) - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); - - u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) & - BIT_OFFSET_LEN_MASK_32(0, 1); - u1_tmp = u1_tmp | - ((rtlpriv->btcoexist.bt_ant_isolation == 1) ? - 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | - ((rtlpriv->btcoexist.bt_service == BT_SCO) ? - 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); - rtl_write_byte(rtlpriv, 0x4fd, u1_tmp); - - rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa); - rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040); - rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010); - - /* Config to 1T1R. */ - if (rtlphy->rf_type == RF_1T1R) { - u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE); - u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); - rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp); - - u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE); - u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); - rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp); - } - } -} - -void rtl88ee_suspend(struct ieee80211_hw *hw) -{ -} - -void rtl88ee_resume(struct ieee80211_hw *hw) -{ -} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h deleted file mode 100644 index 1850fde881b5..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h +++ /dev/null @@ -1,66 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CE_HW_H__ -#define __RTL92CE_HW_H__ - -void rtl88ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl88ee_read_eeprom_info(struct ieee80211_hw *hw); -void rtl88ee_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb); -int rtl88ee_hw_init(struct ieee80211_hw *hw); -void rtl88ee_card_disable(struct ieee80211_hw *hw); -void rtl88ee_enable_interrupt(struct ieee80211_hw *hw); -void rtl88ee_disable_interrupt(struct ieee80211_hw *hw); -int rtl88ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); -void rtl88ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -void rtl88ee_set_qos(struct ieee80211_hw *hw, int aci); -void rtl88ee_set_beacon_related_registers(struct ieee80211_hw *hw); -void rtl88ee_set_beacon_interval(struct ieee80211_hw *hw); -void rtl88ee_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr); -void rtl88ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl88ee_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level); -void rtl88ee_update_channel_access_setting(struct ieee80211_hw *hw); -bool rtl88ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); -void rtl88ee_enable_hw_security_config(struct ieee80211_hw *hw); -void rtl88ee_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all); - -void rtl8188ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, u8 *hwinfo); -void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw); -void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw); -void rtl88ee_suspend(struct ieee80211_hw *hw); -void rtl88ee_resume(struct ieee80211_hw *hw); -void rtl88ee_fw_clk_off_timer_callback(unsigned long data); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.c b/drivers/net/wireless/rtlwifi/rtl8188ee/led.c deleted file mode 100644 index b504bd092fc4..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/led.c +++ /dev/null @@ -1,154 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "reg.h" -#include "led.h" - -static void _rtl88ee_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - u8 ledcfg; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - rtl_write_byte(rtlpriv, - REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6)); - break; - case LED_PIN_LED1: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); - rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - pled->ledon = true; -} - -void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - u8 ledcfg; - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - ledcfg &= 0xf0; - if (pcipriv->ledctl.led_opendrain) { - rtl_write_byte(rtlpriv, REG_LEDCFG2, - (ledcfg | BIT(3) | BIT(5) | BIT(6))); - ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); - rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, - (ledcfg & 0xFE)); - } else - rtl_write_byte(rtlpriv, REG_LEDCFG2, - (ledcfg | BIT(3) | BIT(5) | BIT(6))); - break; - case LED_PIN_LED1: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); - ledcfg &= 0x10; - rtl_write_byte(rtlpriv, REG_LEDCFG1, (ledcfg | BIT(3))); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - pled->ledon = false; -} - -void rtl88ee_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - _rtl88ee_init_led(hw, &pcipriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl88ee_init_led(hw, &pcipriv->ledctl.sw_led1, LED_PIN_LED1); -} - -static void _rtl88ee_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); - switch (ledaction) { - case LED_CTL_POWER_ON: - case LED_CTL_LINK: - case LED_CTL_NO_LINK: - rtl88ee_sw_led_on(hw, pLed0); - break; - case LED_CTL_POWER_OFF: - rtl88ee_sw_led_off(hw, pLed0); - break; - default: - break; - } -} - -void rtl88ee_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && - (ledaction == LED_CTL_TX || - ledaction == LED_CTL_RX || - ledaction == LED_CTL_SITE_SURVEY || - ledaction == LED_CTL_LINK || - ledaction == LED_CTL_NO_LINK || - ledaction == LED_CTL_START_TO_LINK || - ledaction == LED_CTL_POWER_ON)) { - return; - } - RT_TRACE(rtlpriv, COMP_LED, DBG_TRACE, "ledaction %d,\n", - ledaction); - _rtl88ee_sw_led_control(hw, ledaction); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/led.h b/drivers/net/wireless/rtlwifi/rtl8188ee/led.h deleted file mode 100644 index 4b325b75faaf..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/led.h +++ /dev/null @@ -1,34 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CE_LED_H__ -#define __RTL92CE_LED_H__ - -void rtl88ee_init_sw_leds(struct ieee80211_hw *hw); -void rtl88ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl88ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl88ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c deleted file mode 100644 index a2bb02c7b837..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.c +++ /dev/null @@ -1,2343 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../ps.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" -#include "table.h" - -static u32 _rtl88e_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset); -static void _rtl88e_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data); -static u32 _rtl88e_phy_calculate_bit_shift(u32 bitmask); -static bool _rtl88e_phy_bb8188e_config_parafile(struct ieee80211_hw *hw); -static bool _rtl88e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); -static bool phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); -static bool phy_config_bb_with_pghdr(struct ieee80211_hw *hw, - u8 configtype); -static void _rtl88e_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); -static bool _rtl88e_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, u32 cmdtablesz, - enum swchnlcmd_id cmdid, u32 para1, - u32 para2, u32 msdelay); -static bool _rtl88e_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay); - -static long _rtl88e_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - u8 txpwridx); -static void rtl88ee_phy_set_rf_on(struct ieee80211_hw *hw); -static void rtl88e_phy_set_io(struct ieee80211_hw *hw); - -u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 returnvalue, originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask); - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = _rtl88e_phy_calculate_bit_shift(bitmask); - returnvalue = (originalvalue & bitmask) >> bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "BBR MASK=0x%x Addr[0x%x]=0x%x\n", bitmask, - regaddr, originalvalue); - - return returnvalue; - -} - -void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); - - if (bitmask != MASKDWORD) { - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = _rtl88e_phy_calculate_bit_shift(bitmask); - data = ((originalvalue & (~bitmask)) | (data << bitshift)); - } - - rtl_write_dword(rtlpriv, regaddr, data); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); -} - -u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, readback_value, bitshift; - unsigned long flags; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", - regaddr, rfpath, bitmask); - - spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); - - - original_value = _rtl88e_phy_rf_serial_read(hw, rfpath, regaddr); - bitshift = _rtl88e_phy_calculate_bit_shift(bitmask); - readback_value = (original_value & bitmask) >> bitshift; - - spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", - regaddr, rfpath, bitmask, original_value); - return readback_value; -} - -void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, bitshift; - unsigned long flags; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); - - spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); - - if (bitmask != RFREG_OFFSET_MASK) { - original_value = _rtl88e_phy_rf_serial_read(hw, - rfpath, - regaddr); - bitshift = _rtl88e_phy_calculate_bit_shift(bitmask); - data = - ((original_value & (~bitmask)) | - (data << bitshift)); - } - - _rtl88e_phy_rf_serial_write(hw, rfpath, regaddr, data); - - - spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); -} - -static u32 _rtl88e_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - u32 newoffset; - u32 tmplong, tmplong2; - u8 rfpi_enable = 0; - u32 retvalue; - - offset &= 0xff; - newoffset = offset; - if (RT_CANNOT_IO(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n"); - return 0xFFFFFFFF; - } - tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); - if (rfpath == RF90_PATH_A) - tmplong2 = tmplong; - else - tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); - tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | - (newoffset << 23) | BLSSIREADEDGE; - rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, - tmplong & (~BLSSIREADEDGE)); - mdelay(1); - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); - mdelay(2); - if (rfpath == RF90_PATH_A) - rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, - BIT(8)); - else if (rfpath == RF90_PATH_B) - rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, - BIT(8)); - if (rfpi_enable) - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, - BLSSIREADBACKDATA); - else - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, - BLSSIREADBACKDATA); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "RFR-%d Addr[0x%x]=0x%x\n", - rfpath, pphyreg->rf_rb, retvalue); - return retvalue; -} - -static void _rtl88e_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) -{ - u32 data_and_addr; - u32 newoffset; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - - if (RT_CANNOT_IO(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n"); - return; - } - offset &= 0xff; - newoffset = offset; - data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; - rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "RFW-%d Addr[0x%x]=0x%x\n", - rfpath, pphyreg->rf3wire_offset, data_and_addr); -} - -static u32 _rtl88e_phy_calculate_bit_shift(u32 bitmask) -{ - u32 i; - - for (i = 0; i <= 31; i++) { - if (((bitmask >> i) & 0x1) == 1) - break; - } - return i; -} - -bool rtl88e_phy_mac_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool rtstatus = _rtl88e_phy_config_mac_with_headerfile(hw); - - rtl_write_byte(rtlpriv, 0x04CA, 0x0B); - return rtstatus; -} - -bool rtl88e_phy_bb_config(struct ieee80211_hw *hw) -{ - bool rtstatus = true; - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 regval; - u8 b_reg_hwparafile = 1; - u32 tmp; - _rtl88e_phy_init_bb_rf_register_definition(hw); - regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, - regval | BIT(13) | BIT(0) | BIT(1)); - - rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, - FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | - FEN_BB_GLB_RSTN | FEN_BBRSTB); - tmp = rtl_read_dword(rtlpriv, 0x4c); - rtl_write_dword(rtlpriv, 0x4c, tmp | BIT(23)); - if (b_reg_hwparafile == 1) - rtstatus = _rtl88e_phy_bb8188e_config_parafile(hw); - return rtstatus; -} - -bool rtl88e_phy_rf_config(struct ieee80211_hw *hw) -{ - return rtl88e_phy_rf6052_config(hw); -} - -static bool _rtl88e_check_condition(struct ieee80211_hw *hw, - const u32 condition) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 _board = rtlefuse->board_type; /*need efuse define*/ - u32 _interface = rtlhal->interface; - u32 _platform = 0x08;/*SupportPlatform */ - u32 cond = condition; - - if (condition == 0xCDCDCDCD) - return true; - - cond = condition & 0xFF; - if ((_board & cond) == 0 && cond != 0x1F) - return false; - - cond = condition & 0xFF00; - cond = cond >> 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = condition & 0xFF0000; - cond = cond >> 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - return true; -} - -static void _rtl8188e_config_rf_reg(struct ieee80211_hw *hw, u32 addr, - u32 data, enum radio_path rfpath, - u32 regaddr) -{ - if (addr == 0xffe) { - mdelay(50); - } else if (addr == 0xfd) { - mdelay(5); - } else if (addr == 0xfc) { - mdelay(1); - } else if (addr == 0xfb) { - udelay(50); - } else if (addr == 0xfa) { - udelay(5); - } else if (addr == 0xf9) { - udelay(1); - } else { - rtl_set_rfreg(hw, rfpath, regaddr, - RFREG_OFFSET_MASK, - data); - udelay(1); - } -} - -static void _rtl8188e_config_rf_radio_a(struct ieee80211_hw *hw, - u32 addr, u32 data) -{ - u32 content = 0x1000; /*RF Content: radio_a_txt*/ - u32 maskforphyset = (u32)(content & 0xE000); - - _rtl8188e_config_rf_reg(hw, addr, data, RF90_PATH_A, - addr | maskforphyset); -} - -static void _rtl8188e_config_bb_reg(struct ieee80211_hw *hw, - u32 addr, u32 data) -{ - if (addr == 0xfe) { - mdelay(50); - } else if (addr == 0xfd) { - mdelay(5); - } else if (addr == 0xfc) { - mdelay(1); - } else if (addr == 0xfb) { - udelay(50); - } else if (addr == 0xfa) { - udelay(5); - } else if (addr == 0xf9) { - udelay(1); - } else { - rtl_set_bbreg(hw, addr, MASKDWORD, data); - udelay(1); - } -} - -static bool _rtl88e_phy_bb8188e_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - bool rtstatus; - - rtstatus = phy_config_bb_with_headerfile(hw, BASEBAND_CONFIG_PHY_REG); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); - return false; - } - - if (!rtlefuse->autoload_failflag) { - rtlphy->pwrgroup_cnt = 0; - rtstatus = - phy_config_bb_with_pghdr(hw, BASEBAND_CONFIG_PHY_REG); - } - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); - return false; - } - rtstatus = - phy_config_bb_with_headerfile(hw, BASEBAND_CONFIG_AGC_TAB); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); - return false; - } - rtlphy->cck_high_power = - (bool)(rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, 0x200)); - - return true; -} - -static bool _rtl88e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - u32 arraylength; - u32 *ptrarray; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl8188EMACPHY_Array\n"); - arraylength = RTL8188EEMAC_1T_ARRAYLEN; - ptrarray = RTL8188EEMAC_1T_ARRAY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Img:RTL8188EEMAC_1T_ARRAY LEN %d\n", arraylength); - for (i = 0; i < arraylength; i = i + 2) - rtl_write_byte(rtlpriv, ptrarray[i], (u8)ptrarray[i + 1]); - return true; -} - -#define READ_NEXT_PAIR(v1, v2, i) \ - do { \ - i += 2; v1 = array_table[i]; \ - v2 = array_table[i+1]; \ - } while (0) - -static void handle_branch1(struct ieee80211_hw *hw, u16 arraylen, - u32 *array_table) -{ - u32 v1; - u32 v2; - int i; - - for (i = 0; i < arraylen; i = i + 2) { - v1 = array_table[i]; - v2 = array_table[i+1]; - if (v1 < 0xcdcdcdcd) { - _rtl8188e_config_bb_reg(hw, v1, v2); - } else { /*This line is the start line of branch.*/ - /* to protect READ_NEXT_PAIR not overrun */ - if (i >= arraylen - 2) - break; - - if (!_rtl88e_check_condition(hw, array_table[i])) { - /*Discard the following (offset, data) pairs*/ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < arraylen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2*/ - } else { /* Configure matched pairs and skip - * to end of if-else. - */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < arraylen - 2) { - _rtl8188e_config_bb_reg(hw, v1, v2); - READ_NEXT_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < arraylen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } -} - -static void handle_branch2(struct ieee80211_hw *hw, u16 arraylen, - u32 *array_table) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 v1; - u32 v2; - int i; - - for (i = 0; i < arraylen; i = i + 2) { - v1 = array_table[i]; - v2 = array_table[i+1]; - if (v1 < 0xCDCDCDCD) { - rtl_set_bbreg(hw, array_table[i], MASKDWORD, - array_table[i + 1]); - udelay(1); - continue; - } else { /*This line is the start line of branch.*/ - /* to protect READ_NEXT_PAIR not overrun */ - if (i >= arraylen - 2) - break; - - if (!_rtl88e_check_condition(hw, array_table[i])) { - /*Discard the following (offset, data) pairs*/ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < arraylen - 2) - READ_NEXT_PAIR(v1, v2, i); - i -= 2; /* prevent from for-loop += 2*/ - } else { /* Configure matched pairs and skip - * to end of if-else. - */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < arraylen - 2) { - rtl_set_bbreg(hw, array_table[i], - MASKDWORD, - array_table[i + 1]); - udelay(1); - READ_NEXT_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < arraylen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The agctab_array_table[0] is %x Rtl818EEPHY_REGArray[1] is %x\n", - array_table[i], array_table[i + 1]); - } -} - -static bool phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) -{ - u32 *array_table; - u16 arraylen; - - if (configtype == BASEBAND_CONFIG_PHY_REG) { - arraylen = RTL8188EEPHY_REG_1TARRAYLEN; - array_table = RTL8188EEPHY_REG_1TARRAY; - handle_branch1(hw, arraylen, array_table); - } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { - arraylen = RTL8188EEAGCTAB_1TARRAYLEN; - array_table = RTL8188EEAGCTAB_1TARRAY; - handle_branch2(hw, arraylen, array_table); - } - return true; -} - -static void store_pwrindex_rate_offset(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, - u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - int count = rtlphy->pwrgroup_cnt; - - if (regaddr == RTXAGC_A_RATE18_06) { - rtlphy->mcs_txpwrlevel_origoffset[count][0] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][0]); - } - if (regaddr == RTXAGC_A_RATE54_24) { - rtlphy->mcs_txpwrlevel_origoffset[count][1] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][1]); - } - if (regaddr == RTXAGC_A_CCK1_MCS32) { - rtlphy->mcs_txpwrlevel_origoffset[count][6] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][6]); - } - if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { - rtlphy->mcs_txpwrlevel_origoffset[count][7] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][7]); - } - if (regaddr == RTXAGC_A_MCS03_MCS00) { - rtlphy->mcs_txpwrlevel_origoffset[count][2] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][2]); - } - if (regaddr == RTXAGC_A_MCS07_MCS04) { - rtlphy->mcs_txpwrlevel_origoffset[count][3] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][3]); - } - if (regaddr == RTXAGC_A_MCS11_MCS08) { - rtlphy->mcs_txpwrlevel_origoffset[count][4] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][4]); - } - if (regaddr == RTXAGC_A_MCS15_MCS12) { - rtlphy->mcs_txpwrlevel_origoffset[count][5] = data; - if (get_rf_type(rtlphy) == RF_1T1R) { - count++; - rtlphy->pwrgroup_cnt = count; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][5]); - } - if (regaddr == RTXAGC_B_RATE18_06) { - rtlphy->mcs_txpwrlevel_origoffset[count][8] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][8]); - } - if (regaddr == RTXAGC_B_RATE54_24) { - rtlphy->mcs_txpwrlevel_origoffset[count][9] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][9]); - } - if (regaddr == RTXAGC_B_CCK1_55_MCS32) { - rtlphy->mcs_txpwrlevel_origoffset[count][14] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][14]); - } - if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { - rtlphy->mcs_txpwrlevel_origoffset[count][15] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][15]); - } - if (regaddr == RTXAGC_B_MCS03_MCS00) { - rtlphy->mcs_txpwrlevel_origoffset[count][10] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][10]); - } - if (regaddr == RTXAGC_B_MCS07_MCS04) { - rtlphy->mcs_txpwrlevel_origoffset[count][11] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][11]); - } - if (regaddr == RTXAGC_B_MCS11_MCS08) { - rtlphy->mcs_txpwrlevel_origoffset[count][12] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][12]); - } - if (regaddr == RTXAGC_B_MCS15_MCS12) { - rtlphy->mcs_txpwrlevel_origoffset[count][13] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", - count, - rtlphy->mcs_txpwrlevel_origoffset[count][13]); - if (get_rf_type(rtlphy) != RF_1T1R) { - count++; - rtlphy->pwrgroup_cnt = count; - } - } -} - -static bool phy_config_bb_with_pghdr(struct ieee80211_hw *hw, u8 configtype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int i; - u32 *phy_reg_page; - u16 phy_reg_page_len; - u32 v1 = 0, v2 = 0, v3 = 0; - - phy_reg_page_len = RTL8188EEPHY_REG_ARRAY_PGLEN; - phy_reg_page = RTL8188EEPHY_REG_ARRAY_PG; - - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_reg_page_len; i = i + 3) { - v1 = phy_reg_page[i]; - v2 = phy_reg_page[i+1]; - v3 = phy_reg_page[i+2]; - - if (v1 < 0xcdcdcdcd) { - if (phy_reg_page[i] == 0xfe) - mdelay(50); - else if (phy_reg_page[i] == 0xfd) - mdelay(5); - else if (phy_reg_page[i] == 0xfc) - mdelay(1); - else if (phy_reg_page[i] == 0xfb) - udelay(50); - else if (phy_reg_page[i] == 0xfa) - udelay(5); - else if (phy_reg_page[i] == 0xf9) - udelay(1); - - store_pwrindex_rate_offset(hw, phy_reg_page[i], - phy_reg_page[i + 1], - phy_reg_page[i + 2]); - continue; - } else { - if (!_rtl88e_check_condition(hw, - phy_reg_page[i])) { - /*don't need the hw_body*/ - i += 2; /* skip the pair of expression*/ - /* to protect 'i+1' 'i+2' not overrun */ - if (i >= phy_reg_page_len - 2) - break; - - v1 = phy_reg_page[i]; - v2 = phy_reg_page[i+1]; - v3 = phy_reg_page[i+2]; - while (v2 != 0xDEAD && - i < phy_reg_page_len - 5) { - i += 3; - v1 = phy_reg_page[i]; - v2 = phy_reg_page[i+1]; - v3 = phy_reg_page[i+2]; - } - } - } - } - } else { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "configtype != BaseBand_Config_PHY_REG\n"); - } - return true; -} - -#define READ_NEXT_RF_PAIR(v1, v2, i) \ -do { \ - i += 2; \ - v1 = radioa_array_table[i]; \ - v2 = radioa_array_table[i+1]; \ -} while (0) - -static void process_path_a(struct ieee80211_hw *hw, - u16 radioa_arraylen, - u32 *radioa_array_table) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 v1, v2; - int i; - - for (i = 0; i < radioa_arraylen; i = i + 2) { - v1 = radioa_array_table[i]; - v2 = radioa_array_table[i+1]; - if (v1 < 0xcdcdcdcd) { - _rtl8188e_config_rf_radio_a(hw, v1, v2); - } else { /*This line is the start line of branch.*/ - /* to protect READ_NEXT_PAIR not overrun */ - if (i >= radioa_arraylen - 2) - break; - - if (!_rtl88e_check_condition(hw, radioa_array_table[i])) { - /*Discard the following (offset, data) pairs*/ - READ_NEXT_RF_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < radioa_arraylen - 2) { - READ_NEXT_RF_PAIR(v1, v2, i); - } - i -= 2; /* prevent from for-loop += 2*/ - } else { /* Configure matched pairs and - * skip to end of if-else. - */ - READ_NEXT_RF_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < radioa_arraylen - 2) { - _rtl8188e_config_rf_radio_a(hw, v1, v2); - READ_NEXT_RF_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && - i < radioa_arraylen - 2) - READ_NEXT_RF_PAIR(v1, v2, i); - } - } - } - - if (rtlhal->oem_id == RT_CID_819X_HP) - _rtl8188e_config_rf_radio_a(hw, 0x52, 0x7E4BD); -} - -bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool rtstatus = true; - u32 *radioa_array_table; - u16 radioa_arraylen; - - radioa_arraylen = RTL8188EE_RADIOA_1TARRAYLEN; - radioa_array_table = RTL8188EE_RADIOA_1TARRAY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Radio_A:RTL8188EE_RADIOA_1TARRAY %d\n", radioa_arraylen); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); - rtstatus = true; - switch (rfpath) { - case RF90_PATH_A: - process_path_a(hw, radioa_arraylen, radioa_array_table); - break; - case RF90_PATH_B: - case RF90_PATH_C: - case RF90_PATH_D: - break; - } - return true; -} - -void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - rtlphy->default_initialgain[0] = - (u8)rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[1] = - (u8)rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[2] = - (u8)rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[3] = - (u8)rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", - rtlphy->default_initialgain[0], - rtlphy->default_initialgain[1], - rtlphy->default_initialgain[2], - rtlphy->default_initialgain[3]); - - rtlphy->framesync = (u8)rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, - MASKBYTE0); - rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, - MASKDWORD); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default framesync (0x%x) = 0x%x\n", - ROFDM0_RXDETECTOR3, rtlphy->framesync); -} - -static void _rtl88e_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; - rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; - rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; - rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; - - rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = - RFPGA0_XA_LSSIPARAMETER; - rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = - RFPGA0_XB_LSSIPARAMETER; - - rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; - - rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; - rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; - rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; - rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; - - rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; - rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; - - rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; - rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; - - rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = - RFPGA0_XAB_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = - RFPGA0_XAB_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = - RFPGA0_XCD_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = - RFPGA0_XCD_SWITCHCONTROL; - - rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; - - rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; - - rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBANLANCE; - rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; - - rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; - rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; - rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; - rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; - - rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE; - - rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; - rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; - - rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; - - rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK; - rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK; -} - -void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 txpwr_level; - long txpwr_dbm; - - txpwr_level = rtlphy->cur_cck_txpwridx; - txpwr_dbm = _rtl88e_phy_txpwr_idx_to_dbm(hw, - WIRELESS_MODE_B, txpwr_level); - txpwr_level = rtlphy->cur_ofdm24g_txpwridx; - if (_rtl88e_phy_txpwr_idx_to_dbm(hw, - WIRELESS_MODE_G, - txpwr_level) > txpwr_dbm) - txpwr_dbm = - _rtl88e_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, - txpwr_level); - txpwr_level = rtlphy->cur_ofdm24g_txpwridx; - if (_rtl88e_phy_txpwr_idx_to_dbm(hw, - WIRELESS_MODE_N_24G, - txpwr_level) > txpwr_dbm) - txpwr_dbm = - _rtl88e_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, - txpwr_level); - *powerlevel = txpwr_dbm; -} - -static void handle_path_a(struct rtl_efuse *rtlefuse, u8 index, - u8 *cckpowerlevel, u8 *ofdmpowerlevel, - u8 *bw20powerlevel, u8 *bw40powerlevel) -{ - cckpowerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_cck[RF90_PATH_A][index]; - /*-8~7 */ - if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][index] > 0x0f) - bw20powerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index] - - (~(rtlefuse->txpwr_ht20diff[RF90_PATH_A][index]) + 1); - else - bw20powerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index] + - rtlefuse->txpwr_ht20diff[RF90_PATH_A][index]; - if (rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][index] > 0xf) - ofdmpowerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index] - - (~(rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][index])+1); - else - ofdmpowerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index] + - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][index]; - bw40powerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index]; -} - -static void _rtl88e_get_txpower_index(struct ieee80211_hw *hw, u8 channel, - u8 *cckpowerlevel, u8 *ofdmpowerlevel, - u8 *bw20powerlevel, u8 *bw40powerlevel) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 index = (channel - 1); - u8 rf_path = 0; - - for (rf_path = 0; rf_path < 2; rf_path++) { - if (rf_path == RF90_PATH_A) { - handle_path_a(rtlefuse, index, cckpowerlevel, - ofdmpowerlevel, bw20powerlevel, - bw40powerlevel); - } else if (rf_path == RF90_PATH_B) { - cckpowerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_cck[RF90_PATH_B][index]; - bw20powerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index] + - rtlefuse->txpwr_ht20diff[RF90_PATH_B][index]; - ofdmpowerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index] + - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][index]; - bw40powerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index]; - } - } - -} - -static void _rtl88e_ccxpower_index_check(struct ieee80211_hw *hw, - u8 channel, u8 *cckpowerlevel, - u8 *ofdmpowerlevel, u8 *bw20powerlevel, - u8 *bw40powerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; - rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; - rtlphy->cur_bw20_txpwridx = bw20powerlevel[0]; - rtlphy->cur_bw40_txpwridx = bw40powerlevel[0]; - -} - -void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 cckpowerlevel[MAX_TX_COUNT] = {0}; - u8 ofdmpowerlevel[MAX_TX_COUNT] = {0}; - u8 bw20powerlevel[MAX_TX_COUNT] = {0}; - u8 bw40powerlevel[MAX_TX_COUNT] = {0}; - - if (!rtlefuse->txpwr_fromeprom) - return; - _rtl88e_get_txpower_index(hw, channel, - &cckpowerlevel[0], &ofdmpowerlevel[0], - &bw20powerlevel[0], &bw40powerlevel[0]); - _rtl88e_ccxpower_index_check(hw, channel, - &cckpowerlevel[0], &ofdmpowerlevel[0], - &bw20powerlevel[0], &bw40powerlevel[0]); - rtl88e_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]); - rtl88e_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], - &bw20powerlevel[0], - &bw40powerlevel[0], channel); -} - -static long _rtl88e_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - u8 txpwridx) -{ - long offset; - long pwrout_dbm; - - switch (wirelessmode) { - case WIRELESS_MODE_B: - offset = -7; - break; - case WIRELESS_MODE_G: - case WIRELESS_MODE_N_24G: - offset = -8; - break; - default: - offset = -8; - break; - } - pwrout_dbm = txpwridx / 2 + offset; - return pwrout_dbm; -} - -void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - enum io_type iotype; - - if (!is_hal_stop(rtlhal)) { - switch (operation) { - case SCAN_OPT_BACKUP_BAND0: - iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_IO_CMD, - (u8 *)&iotype); - - break; - case SCAN_OPT_RESTORE: - iotype = IO_CMD_RESUME_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_IO_CMD, - (u8 *)&iotype); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Unknown Scan Backup operation.\n"); - break; - } - } -} - -void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 reg_bw_opmode; - u8 reg_prsr_rsc; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "Switch to %s bandwidth\n", - rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? - "20MHz" : "40MHz"); - - if (is_hal_stop(rtlhal)) { - rtlphy->set_bwmode_inprogress = false; - return; - } - - reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); - reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - reg_bw_opmode |= BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - break; - case HT_CHANNEL_WIDTH_20_40: - reg_bw_opmode &= ~BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - reg_prsr_rsc = - (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); - /* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);*/ - break; - case HT_CHANNEL_WIDTH_20_40: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); - - rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, - (mac->cur_40_prime_sc >> 1)); - rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); - /*rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);*/ - - rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), - (mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - rtl88e_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); - rtlphy->set_bwmode_inprogress = false; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n"); -} - -void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_bw = rtlphy->current_chan_bw; - - if (rtlphy->set_bwmode_inprogress) - return; - rtlphy->set_bwmode_inprogress = true; - if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtl88e_phy_set_bw_mode_callback(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "false driver sleep or unload\n"); - rtlphy->set_bwmode_inprogress = false; - rtlphy->current_chan_bw = tmp_bw; - } -} - -void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 delay; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "switch to channel%d\n", rtlphy->current_channel); - if (is_hal_stop(rtlhal)) - return; - do { - if (!rtlphy->sw_chnl_inprogress) - break; - if (!_rtl88e_phy_sw_chnl_step_by_step - (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage, - &rtlphy->sw_chnl_step, &delay)) { - if (delay > 0) - mdelay(delay); - else - continue; - } else { - rtlphy->sw_chnl_inprogress = false; - } - break; - } while (true); - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); -} - -u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (rtlphy->sw_chnl_inprogress) - return 0; - if (rtlphy->set_bwmode_inprogress) - return 0; - RT_ASSERT((rtlphy->current_channel <= 14), - "WIRELESS_MODE_G but channel>14"); - rtlphy->sw_chnl_inprogress = true; - rtlphy->sw_chnl_stage = 0; - rtlphy->sw_chnl_step = 0; - if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtl88e_phy_sw_chnl_callback(hw); - RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false schdule workitem current channel %d\n", - rtlphy->current_channel); - rtlphy->sw_chnl_inprogress = false; - } else { - RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false driver sleep or unload\n"); - rtlphy->sw_chnl_inprogress = false; - } - return 1; -} - -static bool _rtl88e_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; - u32 precommoncmdcnt; - struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; - u32 postcommoncmdcnt; - struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; - u32 rfdependcmdcnt; - struct swchnlcmd *currentcmd = NULL; - u8 rfpath; - u8 num_total_rfpath = rtlphy->num_total_rfpath; - - precommoncmdcnt = 0; - _rtl88e_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, - CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); - _rtl88e_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); - - postcommoncmdcnt = 0; - - _rtl88e_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, - MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); - - rfdependcmdcnt = 0; - - RT_ASSERT((channel >= 1 && channel <= 14), - "illegal channel for Zebra: %d\n", channel); - - _rtl88e_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, - RF_CHNLBW, channel, 10); - - _rtl88e_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, - 0); - - do { - switch (*stage) { - case 0: - currentcmd = &precommoncmd[*step]; - break; - case 1: - currentcmd = &rfdependcmd[*step]; - break; - case 2: - currentcmd = &postcommoncmd[*step]; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Invalid 'stage' = %d, Check it!\n", *stage); - return true; - } - - if (currentcmd->cmdid == CMDID_END) { - if ((*stage) == 2) - return true; - (*stage)++; - (*step) = 0; - continue; - } - - switch (currentcmd->cmdid) { - case CMDID_SET_TXPOWEROWER_LEVEL: - rtl88e_phy_set_txpower_level(hw, channel); - break; - case CMDID_WRITEPORT_ULONG: - rtl_write_dword(rtlpriv, currentcmd->para1, - currentcmd->para2); - break; - case CMDID_WRITEPORT_USHORT: - rtl_write_word(rtlpriv, currentcmd->para1, - (u16)currentcmd->para2); - break; - case CMDID_WRITEPORT_UCHAR: - rtl_write_byte(rtlpriv, currentcmd->para1, - (u8)currentcmd->para2); - break; - case CMDID_RF_WRITEREG: - for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { - rtlphy->rfreg_chnlval[rfpath] = - ((rtlphy->rfreg_chnlval[rfpath] & - 0xfffffc00) | currentcmd->para2); - - rtl_set_rfreg(hw, (enum radio_path)rfpath, - currentcmd->para1, - RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[rfpath]); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - - break; - } while (true); - - (*delay) = currentcmd->msdelay; - (*step)++; - return false; -} - -static bool _rtl88e_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, u32 cmdtablesz, - enum swchnlcmd_id cmdid, - u32 para1, u32 para2, u32 msdelay) -{ - struct swchnlcmd *pcmd; - - if (cmdtable == NULL) { - RT_ASSERT(false, "cmdtable cannot be NULL.\n"); - return false; - } - - if (cmdtableidx >= cmdtablesz) - return false; - - pcmd = cmdtable + cmdtableidx; - pcmd->cmdid = cmdid; - pcmd->para1 = para1; - pcmd->para2 = para2; - pcmd->msdelay = msdelay; - return true; -} - -static u8 _rtl88e_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) -{ - u32 reg_eac, reg_e94, reg_e9c, reg_ea4; - u8 result = 0x00; - - rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1c); - rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x30008c1c); - rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x8214032a); - rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x28160000); - - rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911); - rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); - reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); - reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && - (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - return result; -} - -static u8 _rtl88e_phy_path_b_iqk(struct ieee80211_hw *hw) -{ - u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; - u8 result = 0x00; - - rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002); - rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000); - mdelay(IQK_DELAY_TIME); - reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); - reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); - reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); - reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); - - if (!(reg_eac & BIT(31)) && - (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && - (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else - return result; - if (!(reg_eac & BIT(30)) && - (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && - (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - return result; -} - -static u8 _rtl88e_phy_path_a_rx_iqk(struct ieee80211_hw *hw, bool config_pathb) -{ - u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u32temp; - u8 result = 0x00; - - /*Get TXIMR Setting*/ - /*Modify RX IQK mode table*/ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf117b); - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /*IQK Setting*/ - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x81004800); - - /*path a IQK setting*/ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x10008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x30008c1c); - rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160804); - rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160000); - - /*LO calibration Setting*/ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); - /*one shot,path A LOK & iqk*/ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); - reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); - reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); - - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && - (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else - return result; - - u32temp = 0x80007C00 | (reg_e94&0x3FF0000) | - ((reg_e9c&0x3FF0000) >> 16); - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32temp); - /*RX IQK*/ - /*Modify RX IQK mode table*/ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ffa); - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /*IQK Setting*/ - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - - /*path a IQK setting*/ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x30008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x10008c1c); - rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160c05); - rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160c05); - - /*LO calibration Setting*/ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); - /*one shot,path A LOK & iqk*/ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); - reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); - reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); - reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD); - - if (!(reg_eac & BIT(27)) && - (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && - (((reg_eac & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - return result; -} - -static void _rtl88e_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, - bool iqk_ok, long result[][8], - u8 final_candidate, bool btxonly) -{ - u32 oldval_0, x, tx0_a, reg; - long y, tx0_c; - - if (final_candidate == 0xFF) { - return; - } else if (iqk_ok) { - oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, - MASKDWORD) >> 22) & 0x3FF; - x = result[final_candidate][0]; - if ((x & 0x00000200) != 0) - x = x | 0xFFFFFC00; - tx0_a = (x * oldval_0) >> 8; - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31), - ((x * oldval_0 >> 7) & 0x1)); - y = result[final_candidate][1]; - if ((y & 0x00000200) != 0) - y = y | 0xFFFFFC00; - tx0_c = (y * oldval_0) >> 8; - rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, - ((tx0_c & 0x3C0) >> 6)); - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000, - (tx0_c & 0x3F)); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29), - ((y * oldval_0 >> 7) & 0x1)); - if (btxonly) - return; - reg = result[final_candidate][2]; - rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg); - reg = result[final_candidate][3] & 0x3F; - rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg); - reg = (result[final_candidate][3] >> 6) & 0xF; - rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); - } -} - -static void _rtl88e_phy_save_adda_registers(struct ieee80211_hw *hw, - u32 *addareg, u32 *addabackup, - u32 registernum) -{ - u32 i; - - for (i = 0; i < registernum; i++) - addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD); -} - -static void _rtl88e_phy_save_mac_registers(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) - macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); - macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); -} - -static void _rtl88e_phy_reload_adda_registers(struct ieee80211_hw *hw, - u32 *addareg, u32 *addabackup, - u32 regiesternum) -{ - u32 i; - - for (i = 0; i < regiesternum; i++) - rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]); -} - -static void _rtl88e_phy_reload_mac_registers(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) - rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]); - rtl_write_dword(rtlpriv, macreg[i], macbackup[i]); -} - -static void _rtl88e_phy_path_adda_on(struct ieee80211_hw *hw, - u32 *addareg, bool is_patha_on, bool is2t) -{ - u32 pathon; - u32 i; - - pathon = is_patha_on ? 0x04db25a4 : 0x0b1b25a4; - if (false == is2t) { - pathon = 0x0bdb25a0; - rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0); - } else { - rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon); - } - - for (i = 1; i < IQK_ADDA_REG_NUM; i++) - rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathon); -} - -static void _rtl88e_phy_mac_setting_calibration(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i = 0; - - rtl_write_byte(rtlpriv, macreg[i], 0x3F); - - for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) - rtl_write_byte(rtlpriv, macreg[i], - (u8) (macbackup[i] & (~BIT(3)))); - rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5)))); -} - -static void _rtl88e_phy_path_a_standby(struct ieee80211_hw *hw) -{ - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); - rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); -} - -static void _rtl88e_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode) -{ - u32 mode; - - mode = pi_mode ? 0x01000100 : 0x01000000; - rtl_set_bbreg(hw, 0x820, MASKDWORD, mode); - rtl_set_bbreg(hw, 0x828, MASKDWORD, mode); -} - -static bool _rtl88e_phy_simularity_compare(struct ieee80211_hw *hw, - long result[][8], u8 c1, u8 c2) -{ - u32 i, j, diff, simularity_bitmap, bound; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - u8 final_candidate[2] = { 0xFF, 0xFF }; - bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version); - - if (is2t) - bound = 8; - else - bound = 4; - - simularity_bitmap = 0; - - for (i = 0; i < bound; i++) { - diff = (result[c1][i] > result[c2][i]) ? - (result[c1][i] - result[c2][i]) : - (result[c2][i] - result[c1][i]); - - if (diff > MAX_TOLERANCE) { - if ((i == 2 || i == 6) && !simularity_bitmap) { - if (result[c1][i] + result[c1][i + 1] == 0) - final_candidate[(i / 4)] = c2; - else if (result[c2][i] + result[c2][i + 1] == 0) - final_candidate[(i / 4)] = c1; - else - simularity_bitmap = simularity_bitmap | - (1 << i); - } else - simularity_bitmap = - simularity_bitmap | (1 << i); - } - } - - if (simularity_bitmap == 0) { - for (i = 0; i < (bound / 4); i++) { - if (final_candidate[i] != 0xFF) { - for (j = i * 4; j < (i + 1) * 4 - 2; j++) - result[3][j] = - result[final_candidate[i]][j]; - bresult = false; - } - } - return bresult; - } else if (!(simularity_bitmap & 0x0F)) { - for (i = 0; i < 4; i++) - result[3][i] = result[c1][i]; - return false; - } else if (!(simularity_bitmap & 0xF0) && is2t) { - for (i = 4; i < 8; i++) - result[3][i] = result[c1][i]; - return false; - } else { - return false; - } - -} - -static void _rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, - long result[][8], u8 t, bool is2t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 i; - u8 patha_ok, pathb_ok; - u32 adda_reg[IQK_ADDA_REG_NUM] = { - 0x85c, 0xe6c, 0xe70, 0xe74, - 0xe78, 0xe7c, 0xe80, 0xe84, - 0xe88, 0xe8c, 0xed0, 0xed4, - 0xed8, 0xedc, 0xee0, 0xeec - }; - u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { - 0x522, 0x550, 0x551, 0x040 - }; - u32 iqk_bb_reg[IQK_BB_REG_NUM] = { - ROFDM0_TRXPATHENABLE, ROFDM0_TRMUXPAR, - RFPGA0_XCD_RFINTERFACESW, 0xb68, 0xb6c, - 0x870, 0x860, 0x864, 0x800 - }; - const u32 retrycount = 2; - - if (t == 0) { - _rtl88e_phy_save_adda_registers(hw, adda_reg, - rtlphy->adda_backup, 16); - _rtl88e_phy_save_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - _rtl88e_phy_save_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, - IQK_BB_REG_NUM); - } - _rtl88e_phy_path_adda_on(hw, adda_reg, true, is2t); - if (t == 0) { - rtlphy->rfpi_enable = - (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, BIT(8)); - } - - if (!rtlphy->rfpi_enable) - _rtl88e_phy_pi_mode_switch(hw, true); - /*BB Setting*/ - rtl_set_bbreg(hw, 0x800, BIT(24), 0x00); - rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); - rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); - rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); - - rtl_set_bbreg(hw, 0x870, BIT(10), 0x01); - rtl_set_bbreg(hw, 0x870, BIT(26), 0x01); - rtl_set_bbreg(hw, 0x860, BIT(10), 0x00); - rtl_set_bbreg(hw, 0x864, BIT(10), 0x00); - - if (is2t) { - rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); - rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); - } - _rtl88e_phy_mac_setting_calibration(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x0f600000); - if (is2t) - rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x0f600000); - - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); - rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x81004800); - for (i = 0; i < retrycount; i++) { - patha_ok = _rtl88e_phy_path_a_iqk(hw, is2t); - if (patha_ok == 0x01) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Path A Tx IQK Success!!\n"); - result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & - 0x3FF0000) >> 16; - break; - } - } - - for (i = 0; i < retrycount; i++) { - patha_ok = _rtl88e_phy_path_a_rx_iqk(hw, is2t); - if (patha_ok == 0x03) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Path A Rx IQK Success!!\n"); - result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & - 0x3FF0000) >> 16; - break; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Path a RX iqk fail!!!\n"); - } - } - - if (0 == patha_ok) - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Path A IQK Success!!\n"); - if (is2t) { - _rtl88e_phy_path_a_standby(hw); - _rtl88e_phy_path_adda_on(hw, adda_reg, false, is2t); - for (i = 0; i < retrycount; i++) { - pathb_ok = _rtl88e_phy_path_b_iqk(hw); - if (pathb_ok == 0x03) { - result[t][4] = (rtl_get_bbreg(hw, - 0xeb4, - MASKDWORD) & - 0x3FF0000) >> 16; - result[t][5] = - (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][6] = - (rtl_get_bbreg(hw, 0xec4, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][7] = - (rtl_get_bbreg(hw, 0xecc, MASKDWORD) & - 0x3FF0000) >> 16; - break; - } else if (i == (retrycount - 1) && pathb_ok == 0x01) { - result[t][4] = (rtl_get_bbreg(hw, - 0xeb4, - MASKDWORD) & - 0x3FF0000) >> 16; - } - result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & - 0x3FF0000) >> 16; - } - } - - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); - - if (t != 0) { - if (!rtlphy->rfpi_enable) - _rtl88e_phy_pi_mode_switch(hw, false); - _rtl88e_phy_reload_adda_registers(hw, adda_reg, - rtlphy->adda_backup, 16); - _rtl88e_phy_reload_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - _rtl88e_phy_reload_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, - IQK_BB_REG_NUM); - - rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); - if (is2t) - rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); - rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00); - rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00); - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "88ee IQK Finish!!\n"); -} - -static void _rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) -{ - u8 tmpreg; - u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - tmpreg = rtl_read_byte(rtlpriv, 0xd03); - - if ((tmpreg & 0x70) != 0) - rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); - else - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - - if ((tmpreg & 0x70) != 0) { - rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); - - if (is2t) - rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, - MASK12BITS); - - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, - (rf_a_mode & 0x8FFFF) | 0x10000); - - if (is2t) - rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, - (rf_b_mode & 0x8FFFF) | 0x10000); - } - lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); - - rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); - - mdelay(100); - - if ((tmpreg & 0x70) != 0) { - rtl_write_byte(rtlpriv, 0xd03, tmpreg); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); - - if (is2t) - rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, - rf_b_mode); - } else { - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - } -RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); - -} - -static void _rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, - bool bmain, bool is2t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); - - if (is_hal_stop(rtlhal)) { - u8 u1btmp; - u1btmp = rtl_read_byte(rtlpriv, REG_LEDCFG0); - rtl_write_byte(rtlpriv, REG_LEDCFG0, u1btmp | BIT(7)); - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); - } - if (is2t) { - if (bmain) - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(5) | BIT(6), 0x1); - else - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(5) | BIT(6), 0x2); - } else { - rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(8) | BIT(9), 0); - rtl_set_bbreg(hw, 0x914, MASKLWORD, 0x0201); - - /* We use the RF definition of MAIN and AUX, - * left antenna and right antenna repectively. - * Default output at AUX. - */ - if (bmain) { - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, - BIT(14) | BIT(13) | BIT(12), 0); - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(5) | BIT(4) | BIT(3), 0); - if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) - rtl_set_bbreg(hw, RCONFIG_RAM64x16, BIT(31), 0); - } else { - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, - BIT(14) | BIT(13) | BIT(12), 1); - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(5) | BIT(4) | BIT(3), 1); - if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) - rtl_set_bbreg(hw, RCONFIG_RAM64x16, BIT(31), 1); - } - } -} - -#undef IQK_ADDA_REG_NUM -#undef IQK_DELAY_TIME - -void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - long result[4][8]; - u8 i, final_candidate; - bool b_patha_ok, b_pathb_ok; - long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, - reg_ecc, reg_tmp = 0; - bool is12simular, is13simular, is23simular; - u32 iqk_bb_reg[9] = { - ROFDM0_XARXIQIMBALANCE, - ROFDM0_XBRXIQIMBALANCE, - ROFDM0_ECCATHRESHOLD, - ROFDM0_AGCRSSITABLE, - ROFDM0_XATXIQIMBALANCE, - ROFDM0_XBTXIQIMBALANCE, - ROFDM0_XCTXAFE, - ROFDM0_XDTXAFE, - ROFDM0_RXIQEXTANTA - }; - - if (b_recovery) { - _rtl88e_phy_reload_adda_registers(hw, - iqk_bb_reg, - rtlphy->iqk_bb_backup, 9); - return; - } - - for (i = 0; i < 8; i++) { - result[0][i] = 0; - result[1][i] = 0; - result[2][i] = 0; - result[3][i] = 0; - } - final_candidate = 0xff; - b_patha_ok = false; - b_pathb_ok = false; - is12simular = false; - is23simular = false; - is13simular = false; - for (i = 0; i < 3; i++) { - if (get_rf_type(rtlphy) == RF_2T2R) - _rtl88e_phy_iq_calibrate(hw, result, i, true); - else - _rtl88e_phy_iq_calibrate(hw, result, i, false); - if (i == 1) { - is12simular = - _rtl88e_phy_simularity_compare(hw, result, 0, 1); - if (is12simular) { - final_candidate = 0; - break; - } - } - if (i == 2) { - is13simular = - _rtl88e_phy_simularity_compare(hw, result, 0, 2); - if (is13simular) { - final_candidate = 0; - break; - } - is23simular = - _rtl88e_phy_simularity_compare(hw, result, 1, 2); - if (is23simular) { - final_candidate = 1; - } else { - for (i = 0; i < 8; i++) - reg_tmp += result[3][i]; - - if (reg_tmp != 0) - final_candidate = 3; - else - final_candidate = 0xFF; - } - } - } - for (i = 0; i < 4; i++) { - reg_e94 = result[i][0]; - reg_e9c = result[i][1]; - reg_ea4 = result[i][2]; - reg_eac = result[i][3]; - reg_eb4 = result[i][4]; - reg_ebc = result[i][5]; - reg_ec4 = result[i][6]; - reg_ecc = result[i][7]; - } - if (final_candidate != 0xff) { - reg_e94 = result[final_candidate][0]; - reg_e9c = result[final_candidate][1]; - reg_ea4 = result[final_candidate][2]; - reg_eac = result[final_candidate][3]; - reg_eb4 = result[final_candidate][4]; - reg_ebc = result[final_candidate][5]; - reg_ec4 = result[final_candidate][6]; - reg_ecc = result[final_candidate][7]; - rtlphy->reg_eb4 = reg_eb4; - rtlphy->reg_ebc = reg_ebc; - rtlphy->reg_e94 = reg_e94; - rtlphy->reg_e9c = reg_e9c; - b_patha_ok = true; - b_pathb_ok = true; - } else { - rtlphy->reg_e94 = 0x100; - rtlphy->reg_eb4 = 0x100; - rtlphy->reg_e9c = 0x0; - rtlphy->reg_ebc = 0x0; - } - if (reg_e94 != 0) /*&&(reg_ea4 != 0) */ - _rtl88e_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result, - final_candidate, - (reg_ea4 == 0)); - if (final_candidate != 0xFF) { - for (i = 0; i < IQK_MATRIX_REG_NUM; i++) - rtlphy->iqk_matrix[0].value[0][i] = - result[final_candidate][i]; - rtlphy->iqk_matrix[0].iqk_done = true; - - } - _rtl88e_phy_save_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, 9); -} - -void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = &rtlpriv->rtlhal; - u32 timeout = 2000, timecount = 0; - - while (rtlpriv->mac80211.act_scanning && timecount < timeout) { - udelay(50); - timecount += 50; - } - - rtlphy->lck_inprogress = true; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "LCK:Start!!! currentband %x delay %d ms\n", - rtlhal->current_bandtype, timecount); - - _rtl88e_phy_lc_calibrate(hw, false); - - rtlphy->lck_inprogress = false; -} - -void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) -{ - _rtl88e_phy_set_rfpath_switch(hw, bmain, false); -} - -bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - bool postprocessing = false; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "-->IO Cmd(%#x), set_io_inprogress(%d)\n", - iotype, rtlphy->set_io_inprogress); - do { - switch (iotype) { - case IO_CMD_RESUME_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Resume DM after scan.\n"); - postprocessing = true; - break; - case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Pause DM before scan.\n"); - postprocessing = true; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - } while (false); - if (postprocessing && !rtlphy->set_io_inprogress) { - rtlphy->set_io_inprogress = true; - rtlphy->current_io_type = iotype; - } else { - return false; - } - rtl88e_phy_set_io(hw); - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); - return true; -} - -static void rtl88e_phy_set_io(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "--->Cmd(%#x), set_io_inprogress(%d)\n", - rtlphy->current_io_type, rtlphy->set_io_inprogress); - switch (rtlphy->current_io_type) { - case IO_CMD_RESUME_DM_BY_SCAN: - dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; - /*rtl92c_dm_write_dig(hw);*/ - rtl88e_phy_set_txpower_level(hw, rtlphy->current_channel); - rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x83); - break; - case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: - rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; - dm_digtable->cur_igvalue = 0x17; - rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x40); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - rtlphy->set_io_inprogress = false; - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "(%#x)\n", rtlphy->current_io_type); -} - -static void rtl88ee_phy_set_rf_on(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - /*rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);*/ - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); -} - -static void _rtl88ee_phy_set_rf_sleep(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); -} - -static bool _rtl88ee_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool bresult = true; - u8 i, queue_id; - struct rtl8192_tx_ring *ring = NULL; - - switch (rfpwr_state) { - case ERFON: - if ((ppsc->rfpwr_state == ERFOFF) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { - bool rtstatus; - u32 initializecount = 0; - - do { - initializecount++; - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic enable\n"); - rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && - (initializecount < 10)); - RT_CLEAR_PS_LEVEL(ppsc, - RT_RF_OFF_LEVL_HALT_NIC); - } else { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFON sleeped:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc-> - last_sleep_jiffies)); - ppsc->last_awake_jiffies = jiffies; - rtl88ee_phy_set_rf_on(hw); - } - if (mac->link_state == MAC80211_LINKED) { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_LINK); - } else { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - } - break; - case ERFOFF: - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (queue_id == BEACON_QUEUE || - skb_queue_len(&ring->queue) == 0) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", - (i + 1), queue_id, - skb_queue_len(&ring->queue)); - - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic disable\n"); - rtl_ps_disable_nic(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - } else { - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - } else { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_POWER_OFF); - } - } - break; - case ERFSLEEP:{ - if (ppsc->rfpwr_state == ERFOFF) - break; - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (skb_queue_len(&ring->queue) == 0) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", - (i + 1), queue_id, - skb_queue_len(&ring->queue)); - - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFSLEEP awaked:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc->last_awake_jiffies)); - ppsc->last_sleep_jiffies = jiffies; - _rtl88ee_phy_set_rf_sleep(hw); - break; - } - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - bresult = false; - break; - } - if (bresult) - ppsc->rfpwr_state = rfpwr_state; - return bresult; -} - -bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - bool bresult = false; - - if (rfpwr_state == ppsc->rfpwr_state) - return bresult; - bresult = _rtl88ee_phy_set_rf_power_state(hw, rfpwr_state); - return bresult; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h b/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h deleted file mode 100644 index b29bd77210f4..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/phy.h +++ /dev/null @@ -1,233 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_PHY_H__ -#define __RTL92C_PHY_H__ - -/* MAX_TX_COUNT must always set to 4, otherwise read efuse - * table secquence will be wrong. - */ -#define MAX_TX_COUNT 4 - -#define MAX_PRECMD_CNT 16 -#define MAX_RFDEPENDCMD_CNT 16 -#define MAX_POSTCMD_CNT 16 - -#define MAX_DOZE_WAITING_TIMES_9x 64 - -#define RT_CANNOT_IO(hw) false -#define HIGHPOWER_RADIOA_ARRAYLEN 22 - -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM 9 -#define MAX_TOLERANCE 5 -#define IQK_DELAY_TIME 10 -#define INDEX_MAPPING_NUM 15 - -#define APK_BB_REG_NUM 5 -#define APK_AFE_REG_NUM 16 -#define APK_CURVE_REG_NUM 4 -#define PATH_NUM 2 - -#define LOOP_LIMIT 5 -#define MAX_STALL_TIME 50 -#define ANTENNADIVERSITYVALUE 0x80 -#define MAX_TXPWR_IDX_NMODE_92S 63 -#define RESET_CNT_LIMIT 3 - -#define IQK_ADDA_REG_NUM 16 -#define IQK_MAC_REG_NUM 4 - -#define RF6052_MAX_PATH 2 - -#define CT_OFFSET_MAC_ADDR 0X16 - -#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A -#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 -#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 -#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 -#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C - -#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F -#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 - -#define CT_OFFSET_CHANNEL_PLAH 0x75 -#define CT_OFFSET_THERMAL_METER 0x78 -#define CT_OFFSET_RF_OPTION 0x79 -#define CT_OFFSET_VERSION 0x7E -#define CT_OFFSET_CUSTOMER_ID 0x7F - -#define RTL92C_MAX_PATH_NUM 2 - -enum swchnlcmd_id { - CMDID_END, - CMDID_SET_TXPOWEROWER_LEVEL, - CMDID_BBREGWRITE10, - CMDID_WRITEPORT_ULONG, - CMDID_WRITEPORT_USHORT, - CMDID_WRITEPORT_UCHAR, - CMDID_RF_WRITEREG, -}; - -struct swchnlcmd { - enum swchnlcmd_id cmdid; - u32 para1; - u32 para2; - u32 msdelay; -}; - -enum hw90_block_e { - HW90_BLOCK_MAC = 0, - HW90_BLOCK_PHY0 = 1, - HW90_BLOCK_PHY1 = 2, - HW90_BLOCK_RF = 3, - HW90_BLOCK_MAXIMUM = 4, -}; - -enum baseband_config_type { - BASEBAND_CONFIG_PHY_REG = 0, - BASEBAND_CONFIG_AGC_TAB = 1, -}; - -enum ra_offset_area { - RA_OFFSET_LEGACY_OFDM1, - RA_OFFSET_LEGACY_OFDM2, - RA_OFFSET_HT_OFDM1, - RA_OFFSET_HT_OFDM2, - RA_OFFSET_HT_OFDM3, - RA_OFFSET_HT_OFDM4, - RA_OFFSET_HT_CCK, -}; - -enum antenna_path { - ANTENNA_NONE, - ANTENNA_D, - ANTENNA_C, - ANTENNA_CD, - ANTENNA_B, - ANTENNA_BD, - ANTENNA_BC, - ANTENNA_BCD, - ANTENNA_A, - ANTENNA_AD, - ANTENNA_AC, - ANTENNA_ACD, - ANTENNA_AB, - ANTENNA_ABD, - ANTENNA_ABC, - ANTENNA_ABCD -}; - -struct r_antenna_select_ofdm { - u32 r_tx_antenna:4; - u32 r_ant_l:4; - u32 r_ant_non_ht:4; - u32 r_ant_ht1:4; - u32 r_ant_ht2:4; - u32 r_ant_ht_s1:4; - u32 r_ant_non_ht_s1:4; - u32 ofdm_txsc:2; - u32 reserved:2; -}; - -struct r_antenna_select_cck { - u8 r_cckrx_enable_2:2; - u8 r_cckrx_enable:2; - u8 r_ccktx_enable:4; -}; - -struct efuse_contents { - u8 mac_addr[ETH_ALEN]; - u8 cck_tx_power_idx[6]; - u8 ht40_1s_tx_power_idx[6]; - u8 ht40_2s_tx_power_idx_diff[3]; - u8 ht20_tx_power_idx_diff[3]; - u8 ofdm_tx_power_idx_diff[3]; - u8 ht40_max_power_offset[3]; - u8 ht20_max_power_offset[3]; - u8 channel_plan; - u8 thermal_meter; - u8 rf_option[5]; - u8 version; - u8 oem_id; - u8 regulatory; -}; - -struct tx_power_struct { - u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 legacy_ht_txpowerdiff; - u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 pwrgroup_cnt; - u32 mcs_original_offset[4][16]; -}; - -enum _ANT_DIV_TYPE { - NO_ANTDIV = 0xFF, - CG_TRX_HW_ANTDIV = 0x01, - CGCS_RX_HW_ANTDIV = 0x02, - FIXED_HW_ANTDIV = 0x03, - CG_TRX_SMART_ANTDIV = 0x04, - CGCS_RX_SW_ANTDIV = 0x05, -}; - -u32 rtl88e_phy_query_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask); -void rtl88e_phy_set_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, u32 data); -u32 rtl88e_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask); -void rtl88e_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask, u32 data); -bool rtl88e_phy_mac_config(struct ieee80211_hw *hw); -bool rtl88e_phy_bb_config(struct ieee80211_hw *hw); -bool rtl88e_phy_rf_config(struct ieee80211_hw *hw); -void rtl88e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -void rtl88e_phy_get_txpower_level(struct ieee80211_hw *hw, - long *powerlevel); -void rtl88e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -void rtl88e_phy_scan_operation_backup(struct ieee80211_hw *hw, - u8 operation); -void rtl88e_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -void rtl88e_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); -void rtl88e_phy_sw_chnl_callback(struct ieee80211_hw *hw); -u8 rtl88e_phy_sw_chnl(struct ieee80211_hw *hw); -void rtl88e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -void rtl88e_phy_lc_calibrate(struct ieee80211_hw *hw); -void rtl88e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); -bool rtl88e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -bool rtl88e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); -bool rtl88e_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c deleted file mode 100644 index 02013df968a0..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.c +++ /dev/null @@ -1,105 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../pwrseqcmd.h" -#include "pwrseq.h" - -/* drivers should parse below arrays and do the corresponding actions */ -/*3 Power on Array*/ -struct wlan_pwr_cfg rtl8188ee_power_on_flow[RTL8188EE_TRANS_CARDEMU_TO_ACT_STEPS - + RTL8188EE_TRANS_END_STEPS] = { - RTL8188EE_TRANS_CARDEMU_TO_ACT - RTL8188EE_TRANS_END -}; - -/*3Radio off GPIO Array */ -struct wlan_pwr_cfg rtl8188ee_radio_off_flow[RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8188EE_TRANS_END_STEPS] = { - RTL8188EE_TRANS_ACT_TO_CARDEMU - RTL8188EE_TRANS_END -}; - -/*3Card Disable Array*/ -struct wlan_pwr_cfg rtl8188ee_card_disable_flow - [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8188EE_TRANS_END_STEPS] = { - RTL8188EE_TRANS_ACT_TO_CARDEMU - RTL8188EE_TRANS_CARDEMU_TO_CARDDIS - RTL8188EE_TRANS_END -}; - -/*3 Card Enable Array*/ -struct wlan_pwr_cfg rtl8188ee_card_enable_flow - [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8188EE_TRANS_END_STEPS] = { - RTL8188EE_TRANS_CARDDIS_TO_CARDEMU - RTL8188EE_TRANS_CARDEMU_TO_ACT - RTL8188EE_TRANS_END -}; - -/*3Suspend Array*/ -struct wlan_pwr_cfg rtl8188ee_suspend_flow[RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8188EE_TRANS_CARDEMU_TO_SUS_STEPS - + RTL8188EE_TRANS_END_STEPS] = { - RTL8188EE_TRANS_ACT_TO_CARDEMU - RTL8188EE_TRANS_CARDEMU_TO_SUS - RTL8188EE_TRANS_END -}; - -/*3 Resume Array*/ -struct wlan_pwr_cfg rtl8188ee_resume_flow[RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8188EE_TRANS_CARDEMU_TO_SUS_STEPS - + RTL8188EE_TRANS_END_STEPS] = { - RTL8188EE_TRANS_SUS_TO_CARDEMU - RTL8188EE_TRANS_CARDEMU_TO_ACT - RTL8188EE_TRANS_END -}; - -/*3HWPDN Array*/ -struct wlan_pwr_cfg rtl8188ee_hwpdn_flow[RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS - + RTL8188EE_TRANS_END_STEPS] = { - RTL8188EE_TRANS_ACT_TO_CARDEMU - RTL8188EE_TRANS_CARDEMU_TO_PDN - RTL8188EE_TRANS_END -}; - -/*3 Enter LPS */ -struct wlan_pwr_cfg rtl8188ee_enter_lps_flow[RTL8188EE_TRANS_ACT_TO_LPS_STEPS - + RTL8188EE_TRANS_END_STEPS] = { - /*FW behavior*/ - RTL8188EE_TRANS_ACT_TO_LPS - RTL8188EE_TRANS_END -}; - -/*3 Leave LPS */ -struct wlan_pwr_cfg rtl8188ee_leave_lps_flow[RTL8188EE_TRANS_LPS_TO_ACT_STEPS - + RTL8188EE_TRANS_END_STEPS] = { - /*FW behavior*/ - RTL8188EE_TRANS_LPS_TO_ACT - RTL8188EE_TRANS_END -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h b/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h deleted file mode 100644 index f2d9c6116e5c..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/pwrseq.h +++ /dev/null @@ -1,311 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_PWRSEQ_H__ -#define __RTL8723E_PWRSEQ_H__ - -#include "../pwrseqcmd.h" -/* Check document WM-20110607-Paul-RTL8188EE_Power_Architecture-R02.vsd - * There are 6 HW Power States: - * 0: POFF--Power Off - * 1: PDN--Power Down - * 2: CARDEMU--Card Emulation - * 3: ACT--Active Mode - * 4: LPS--Low Power State - * 5: SUS--Suspend - * - * The transision from different states are defined below - * TRANS_CARDEMU_TO_ACT - * TRANS_ACT_TO_CARDEMU - * TRANS_CARDEMU_TO_SUS - * TRANS_SUS_TO_CARDEMU - * TRANS_CARDEMU_TO_PDN - * TRANS_ACT_TO_LPS - * TRANS_LPS_TO_ACT - * - * TRANS_END - * PWR SEQ Version: rtl8188ee_PwrSeq_V09.h - */ - -#define RTL8188EE_TRANS_CARDEMU_TO_ACT_STEPS 10 -#define RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS 10 -#define RTL8188EE_TRANS_CARDEMU_TO_SUS_STEPS 10 -#define RTL8188EE_TRANS_SUS_TO_CARDEMU_STEPS 10 -#define RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS 10 -#define RTL8188EE_TRANS_PDN_TO_CARDEMU_STEPS 10 -#define RTL8188EE_TRANS_ACT_TO_LPS_STEPS 15 -#define RTL8188EE_TRANS_LPS_TO_ACT_STEPS 15 -#define RTL8188EE_TRANS_END_STEPS 1 - -/* The following macros have the following format: - * { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value - * comments }, - */ -#define RTL8188EE_TRANS_CARDEMU_TO_ACT \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1) \ - /* wait till 0x04[17] = 1 power ready*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0)|BIT(1), 0 \ - /* 0x02[1:0] = 0 reset BB*/}, \ - {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7) \ - /*0x24[23] = 2b'01 schmit trigger */}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0 \ - /* 0x04[15] = 0 disable HWPDN (control by DRV)*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4)|BIT(3), 0 \ - /*0x04[12:11] = 2b'00 disable WL suspend*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0) \ - /*0x04[8] = 1 polling until return 0*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0 \ - /*wait till 0x04[8] = 0*/}, \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0 \ - /*LDO normal mode*/}, \ - {0x0074, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4) \ - /*SDIO Driving*/}, - -#define RTL8188EE_TRANS_ACT_TO_CARDEMU \ - {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ - /*0x1F[7:0] = 0 turn off RF*/}, \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4) \ - /*LDO Sleep mode*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1) \ - /*0x04[9] = 1 turn off MAC by HW state machine*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0 \ - /*wait till 0x04[9] = 0 polling until return 0 to disable*/}, - -#define RTL8188EE_TRANS_CARDEMU_TO_SUS \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3) \ - /*0x04[12:11] = 2b'01enable WL suspend*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)|BIT(4) \ - /*0x04[12:11] = 2b'11enable WL suspend for PCIe*/}, \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, BIT(7) \ - /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */},\ - {0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0 \ - /*Clear SIC_EN register 0x40[12] = 1'b0 */}, \ - {0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4) \ - /*Set USB suspend enable local register 0xfe10[4]=1 */}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0) \ - /*Set SDIO suspend local register*/}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0 \ - /*wait power state to suspend*/}, - -#define RTL8188EE_TRANS_SUS_TO_CARDEMU \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0 \ - /*Set SDIO suspend local register*/}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1) \ - /*wait power state to suspend*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), 0 \ - /*0x04[12:11] = 2b'01enable WL suspend*/}, - -#define RTL8188EE_TRANS_CARDEMU_TO_CARDDIS \ - {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7) \ - /*0x24[23] = 2b'01 schmit trigger */}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3) \ - /*0x04[12:11] = 2b'01 enable WL suspend*/}, \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ - /* 0x04[31:30] = 2b'10 enable enable bandgap mbias in suspend */},\ - {0x0041, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0 \ - /*Clear SIC_EN register 0x40[12] = 1'b0 */}, \ - {0xfe10, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4) \ - /*Set USB suspend enable local register 0xfe10[4]=1 */}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0) \ - /*Set SDIO suspend local register*/}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0 \ - /*wait power state to suspend*/}, - -#define RTL8188EE_TRANS_CARDDIS_TO_CARDEMU \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0 \ - /*Set SDIO suspend local register*/}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1) \ - /*wait power state to suspend*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0 \ - /*0x04[12:11] = 2b'01enable WL suspend*/}, - -#define RTL8188EE_TRANS_CARDEMU_TO_PDN \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0/* 0x04[16] = 0*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7) \ - /* 0x04[15] = 1*/}, - -#define RTL8188EE_TRANS_PDN_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0/* 0x04[15] = 0*/}, - -#define RTL8188EE_TRANS_ACT_TO_LPS \ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x7F \ - /*Tx Pause*/}, \ - {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ - /*Should be zero if no packet is transmitting*/}, \ - {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ - /*Should be zero if no packet is transmitting*/}, \ - {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ - /*Should be zero if no packet is transmitting*/}, \ - {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ - /*Should be zero if no packet is transmitting*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0 \ - /*CCK and OFDM are disabled,and clock are gated*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US \ - /*Delay 1us*/}, \ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3F \ - /*Reset MAC TRX*/}, \ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0 \ - /*check if removed later*/}, \ - {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5) \ - /*Respond TxOK to scheduler*/}, - - -#define RTL8188EE_TRANS_LPS_TO_ACT \ - {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84 \ - /*SDIO RPWM*/}, \ - {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84 \ - /*USB RPWM*/}, \ - {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84 \ - /*PCIe RPWM*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS \ - /*Delay*/}, \ - {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0 \ - /*. 0x08[4] = 0 switch TSF to 40M*/}, \ - {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0 \ - /*Polling 0x109[7]=0 TSF in 40M*/}, \ - {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0 \ - /*. 0x29[7:6] = 2b'00 enable BB clock*/}, \ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1) \ - /*. 0x101[1] = 1*/}, \ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF \ - /*. 0x100[7:0] = 0xFF enable WMAC TRX*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1)|BIT(0), BIT(1)|BIT(0) \ - /*. 0x02[1:0] = 2b'11 enable BB macro*/}, \ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ - /*. 0x522 = 0*/}, - -#define RTL8188EE_TRANS_END \ - {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - 0, PWR_CMD_END, 0, 0} - -extern struct wlan_pwr_cfg rtl8188ee_power_on_flow - [RTL8188EE_TRANS_CARDEMU_TO_ACT_STEPS + - RTL8188EE_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8188ee_radio_off_flow - [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8188EE_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8188ee_card_disable_flow - [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8188EE_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8188ee_card_enable_flow - [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8188EE_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8188ee_suspend_flow - [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8188EE_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8188EE_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8188ee_resume_flow - [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8188EE_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8188EE_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8188ee_hwpdn_flow - [RTL8188EE_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8188EE_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8188EE_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8188ee_enter_lps_flow - [RTL8188EE_TRANS_ACT_TO_LPS_STEPS + - RTL8188EE_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8188ee_leave_lps_flow - [RTL8188EE_TRANS_LPS_TO_ACT_STEPS + - RTL8188EE_TRANS_END_STEPS]; - -/* RTL8723 Power Configuration CMDs for PCIe interface */ -#define RTL8188EE_NIC_PWR_ON_FLOW rtl8188ee_power_on_flow -#define RTL8188EE_NIC_RF_OFF_FLOW rtl8188ee_radio_off_flow -#define RTL8188EE_NIC_DISABLE_FLOW rtl8188ee_card_disable_flow -#define RTL8188EE_NIC_ENABLE_FLOW rtl8188ee_card_enable_flow -#define RTL8188EE_NIC_SUSPEND_FLOW rtl8188ee_suspend_flow -#define RTL8188EE_NIC_RESUME_FLOW rtl8188ee_resume_flow -#define RTL8188EE_NIC_PDN_FLOW rtl8188ee_hwpdn_flow -#define RTL8188EE_NIC_LPS_ENTER_FLOW rtl8188ee_enter_lps_flow -#define RTL8188EE_NIC_LPS_LEAVE_FLOW rtl8188ee_leave_lps_flow - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h b/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h deleted file mode 100644 index 15400ee6c04b..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/reg.h +++ /dev/null @@ -1,2271 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_REG_H__ -#define __RTL92C_REG_H__ - -#define TXPKT_BUF_SELECT 0x69 -#define RXPKT_BUF_SELECT 0xA5 -#define DISABLE_TRXPKT_BUF_ACCESS 0x0 - -#define REG_SYS_ISO_CTRL 0x0000 -#define REG_SYS_FUNC_EN 0x0002 -#define REG_APS_FSMCO 0x0004 -#define REG_SYS_CLKR 0x0008 -#define REG_9346CR 0x000A -#define REG_EE_VPD 0x000C -#define REG_AFE_MISC 0x0010 -#define REG_SPS0_CTRL 0x0011 -#define REG_SPS_OCP_CFG 0x0018 -#define REG_RSV_CTRL 0x001C -#define REG_RF_CTRL 0x001F -#define REG_LDOA15_CTRL 0x0020 -#define REG_LDOV12D_CTRL 0x0021 -#define REG_LDOHCI12_CTRL 0x0022 -#define REG_LPLDO_CTRL 0x0023 -#define REG_AFE_XTAL_CTRL 0x0024 -/* 1.5v for 8188EE test chip, 1.4v for MP chip */ -#define REG_AFE_LDO_CTRL 0x0027 -#define REG_AFE_PLL_CTRL 0x0028 -#define REG_EFUSE_CTRL 0x0030 -#define REG_EFUSE_TEST 0x0034 -#define REG_PWR_DATA 0x0038 -#define REG_CAL_TIMER 0x003C -#define REG_ACLK_MON 0x003E -#define REG_GPIO_MUXCFG 0x0040 -#define REG_GPIO_IO_SEL 0x0042 -#define REG_MAC_PINMUX_CFG 0x0043 -#define REG_GPIO_PIN_CTRL 0x0044 -#define REG_GPIO_INTM 0x0048 -#define REG_LEDCFG0 0x004C -#define REG_LEDCFG1 0x004D -#define REG_LEDCFG2 0x004E -#define REG_LEDCFG3 0x004F -#define REG_FSIMR 0x0050 -#define REG_FSISR 0x0054 -#define REG_HSIMR 0x0058 -#define REG_HSISR 0x005c -#define REG_GPIO_PIN_CTRL_2 0x0060 -#define REG_GPIO_IO_SEL_2 0x0062 -#define REG_GPIO_OUTPUT 0x006c -#define REG_AFE_XTAL_CTRL_EXT 0x0078 -#define REG_XCK_OUT_CTRL 0x007c -#define REG_MCUFWDL 0x0080 -#define REG_WOL_EVENT 0x0081 -#define REG_MCUTSTCFG 0x0084 - -#define REG_HIMR 0x00B0 -#define REG_HISR 0x00B4 -#define REG_HIMRE 0x00B8 -#define REG_HISRE 0x00BC - -#define REG_EFUSE_ACCESS 0x00CF - -#define REG_BIST_SCAN 0x00D0 -#define REG_BIST_RPT 0x00D4 -#define REG_BIST_ROM_RPT 0x00D8 -#define REG_USB_SIE_INTF 0x00E0 -#define REG_PCIE_MIO_INTF 0x00E4 -#define REG_PCIE_MIO_INTD 0x00E8 -#define REG_HPON_FSM 0x00EC -#define REG_SYS_CFG 0x00F0 - -#define REG_CR 0x0100 -#define REG_PBP 0x0104 -#define REG_PKT_BUFF_ACCESS_CTRL 0x0106 -#define REG_TRXDMA_CTRL 0x010C -#define REG_TRXFF_BNDY 0x0114 -#define REG_TRXFF_STATUS 0x0118 -#define REG_RXFF_PTR 0x011C - -#define REG_CPWM 0x012F -#define REG_FWIMR 0x0130 -#define REG_FWISR 0x0134 -#define REG_PKTBUF_DBG_CTRL 0x0140 -#define REG_PKTBUF_DBG_DATA_L 0x0144 -#define REG_PKTBUF_DBG_DATA_H 0x0148 -#define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL+2) - -#define REG_TC0_CTRL 0x0150 -#define REG_TC1_CTRL 0x0154 -#define REG_TC2_CTRL 0x0158 -#define REG_TC3_CTRL 0x015C -#define REG_TC4_CTRL 0x0160 -#define REG_TCUNIT_BASE 0x0164 -#define REG_MBIST_START 0x0174 -#define REG_MBIST_DONE 0x0178 -#define REG_MBIST_FAIL 0x017C -#define REG_32K_CTRL 0x0194 -#define REG_C2HEVT_MSG_NORMAL 0x01A0 -#define REG_C2HEVT_CLEAR 0x01AF -#define REG_C2HEVT_MSG_TEST 0x01B8 -#define REG_MCUTST_1 0x01c0 -#define REG_FMETHR 0x01C8 -#define REG_HMETFR 0x01CC -#define REG_HMEBOX_0 0x01D0 -#define REG_HMEBOX_1 0x01D4 -#define REG_HMEBOX_2 0x01D8 -#define REG_HMEBOX_3 0x01DC - -#define REG_LLT_INIT 0x01E0 -#define REG_BB_ACCEESS_CTRL 0x01E8 -#define REG_BB_ACCESS_DATA 0x01EC - -#define REG_HMEBOX_EXT_0 0x01F0 -#define REG_HMEBOX_EXT_1 0x01F4 -#define REG_HMEBOX_EXT_2 0x01F8 -#define REG_HMEBOX_EXT_3 0x01FC - -#define REG_RQPN 0x0200 -#define REG_FIFOPAGE 0x0204 -#define REG_TDECTRL 0x0208 -#define REG_TXDMA_OFFSET_CHK 0x020C -#define REG_TXDMA_STATUS 0x0210 -#define REG_RQPN_NPQ 0x0214 - -#define REG_RXDMA_AGG_PG_TH 0x0280 -/* FW shall update this register before - * FW write RXPKT_RELEASE_POLL to 1 - */ -#define REG_FW_UPD_RDPTR 0x0284 -/* Control the RX DMA.*/ -#define REG_RXDMA_CONTROL 0x0286 -/* The number of packets in RXPKTBUF. */ -#define REG_RXPKT_NUM 0x0287 - -#define REG_PCIE_CTRL_REG 0x0300 -#define REG_INT_MIG 0x0304 -#define REG_BCNQ_DESA 0x0308 -#define REG_HQ_DESA 0x0310 -#define REG_MGQ_DESA 0x0318 -#define REG_VOQ_DESA 0x0320 -#define REG_VIQ_DESA 0x0328 -#define REG_BEQ_DESA 0x0330 -#define REG_BKQ_DESA 0x0338 -#define REG_RX_DESA 0x0340 - -#define REG_DBI 0x0348 -#define REG_MDIO 0x0354 -#define REG_DBG_SEL 0x0360 -#define REG_PCIE_HRPWM 0x0361 -#define REG_PCIE_HCPWM 0x0363 -#define REG_UART_CTRL 0x0364 -#define REG_WATCH_DOG 0x0368 -#define REG_UART_TX_DESA 0x0370 -#define REG_UART_RX_DESA 0x0378 - -#define REG_HDAQ_DESA_NODEF 0x0000 -#define REG_CMDQ_DESA_NODEF 0x0000 - -#define REG_VOQ_INFORMATION 0x0400 -#define REG_VIQ_INFORMATION 0x0404 -#define REG_BEQ_INFORMATION 0x0408 -#define REG_BKQ_INFORMATION 0x040C -#define REG_MGQ_INFORMATION 0x0410 -#define REG_HGQ_INFORMATION 0x0414 -#define REG_BCNQ_INFORMATION 0x0418 -#define REG_TXPKT_EMPTY 0x041A - -#define REG_CPU_MGQ_INFORMATION 0x041C -#define REG_FWHW_TXQ_CTRL 0x0420 -#define REG_HWSEQ_CTRL 0x0423 -#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 -#define REG_TXPKTBUF_MGQ_BDNY 0x0425 -#define REG_MULTI_BCNQ_EN 0x0426 -#define REG_MULTI_BCNQ_OFFSET 0x0427 -#define REG_SPEC_SIFS 0x0428 -#define REG_RL 0x042A -#define REG_DARFRC 0x0430 -#define REG_RARFRC 0x0438 -#define REG_RRSR 0x0440 -#define REG_ARFR0 0x0444 -#define REG_ARFR1 0x0448 -#define REG_ARFR2 0x044C -#define REG_ARFR3 0x0450 -#define REG_AGGLEN_LMT 0x0458 -#define REG_AMPDU_MIN_SPACE 0x045C -#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D -#define REG_FAST_EDCA_CTRL 0x0460 -#define REG_RD_RESP_PKT_TH 0x0463 -#define REG_INIRTS_RATE_SEL 0x0480 -#define REG_INIDATA_RATE_SEL 0x0484 -#define REG_POWER_STATUS 0x04A4 -#define REG_POWER_STAGE1 0x04B4 -#define REG_POWER_STAGE2 0x04B8 -#define REG_PKT_LIFE_TIME 0x04C0 -#define REG_STBC_SETTING 0x04C4 -#define REG_PROT_MODE_CTRL 0x04C8 -#define REG_BAR_MODE_CTRL 0x04CC -#define REG_RA_TRY_RATE_AGG_LMT 0x04CF -#define REG_EARLY_MODE_CONTROL 0x04D0 -#define REG_NQOS_SEQ 0x04DC -#define REG_QOS_SEQ 0x04DE -#define REG_NEED_CPU_HANDLE 0x04E0 -#define REG_PKT_LOSE_RPT 0x04E1 -#define REG_PTCL_ERR_STATUS 0x04E2 -#define REG_TX_RPT_CTRL 0x04EC -#define REG_TX_RPT_TIME 0x04F0 -#define REG_DUMMY 0x04FC - -#define REG_EDCA_VO_PARAM 0x0500 -#define REG_EDCA_VI_PARAM 0x0504 -#define REG_EDCA_BE_PARAM 0x0508 -#define REG_EDCA_BK_PARAM 0x050C -#define REG_BCNTCFG 0x0510 -#define REG_PIFS 0x0512 -#define REG_RDG_PIFS 0x0513 -#define REG_SIFS_CTX 0x0514 -#define REG_SIFS_TRX 0x0516 -#define REG_AGGR_BREAK_TIME 0x051A -#define REG_SLOT 0x051B -#define REG_TX_PTCL_CTRL 0x0520 -#define REG_TXPAUSE 0x0522 -#define REG_DIS_TXREQ_CLR 0x0523 -#define REG_RD_CTRL 0x0524 -#define REG_TBTT_PROHIBIT 0x0540 -#define REG_RD_NAV_NXT 0x0544 -#define REG_NAV_PROT_LEN 0x0546 -#define REG_BCN_CTRL 0x0550 -#define REG_USTIME_TSF 0x0551 -#define REG_MBID_NUM 0x0552 -#define REG_DUAL_TSF_RST 0x0553 -#define REG_BCN_INTERVAL 0x0554 -#define REG_MBSSID_BCN_SPACE 0x0554 -#define REG_DRVERLYINT 0x0558 -#define REG_BCNDMATIM 0x0559 -#define REG_ATIMWND 0x055A -#define REG_BCN_MAX_ERR 0x055D -#define REG_RXTSF_OFFSET_CCK 0x055E -#define REG_RXTSF_OFFSET_OFDM 0x055F -#define REG_TSFTR 0x0560 -#define REG_INIT_TSFTR 0x0564 -#define REG_PSTIMER 0x0580 -#define REG_TIMER0 0x0584 -#define REG_TIMER1 0x0588 -#define REG_ACMHWCTRL 0x05C0 -#define REG_ACMRSTCTRL 0x05C1 -#define REG_ACMAVG 0x05C2 -#define REG_VO_ADMTIME 0x05C4 -#define REG_VI_ADMTIME 0x05C6 -#define REG_BE_ADMTIME 0x05C8 -#define REG_EDCA_RANDOM_GEN 0x05CC -#define REG_SCH_TXCMD 0x05D0 - -#define REG_APSD_CTRL 0x0600 -#define REG_BWOPMODE 0x0603 -#define REG_TCR 0x0604 -#define REG_RCR 0x0608 -#define REG_RX_PKT_LIMIT 0x060C -#define REG_RX_DLK_TIME 0x060D -#define REG_RX_DRVINFO_SZ 0x060F - -#define REG_MACID 0x0610 -#define REG_BSSID 0x0618 -#define REG_MAR 0x0620 -#define REG_MBIDCAMCFG 0x0628 - -#define REG_USTIME_EDCA 0x0638 -#define REG_MAC_SPEC_SIFS 0x063A -#define REG_RESP_SIFS_CCK 0x063C -#define REG_RESP_SIFS_OFDM 0x063E -#define REG_ACKTO 0x0640 -#define REG_CTS2TO 0x0641 -#define REG_EIFS 0x0642 - -#define REG_NAV_CTRL 0x0650 -#define REG_BACAMCMD 0x0654 -#define REG_BACAMCONTENT 0x0658 -#define REG_LBDLY 0x0660 -#define REG_FWDLY 0x0661 -#define REG_RXERR_RPT 0x0664 -#define REG_TRXPTCL_CTL 0x0668 - -#define REG_CAMCMD 0x0670 -#define REG_CAMWRITE 0x0674 -#define REG_CAMREAD 0x0678 -#define REG_CAMDBG 0x067C -#define REG_SECCFG 0x0680 - -#define REG_WOW_CTRL 0x0690 -#define REG_PSSTATUS 0x0691 -#define REG_PS_RX_INFO 0x0692 -#define REG_UAPSD_TID 0x0693 -#define REG_LPNAV_CTRL 0x0694 -#define REG_WKFMCAM_NUM 0x0698 -#define REG_WKFMCAM_RWD 0x069C -#define REG_RXFLTMAP0 0x06A0 -#define REG_RXFLTMAP1 0x06A2 -#define REG_RXFLTMAP2 0x06A4 -#define REG_BCN_PSR_RPT 0x06A8 -#define REG_CALB32K_CTRL 0x06AC -#define REG_PKT_MON_CTRL 0x06B4 -#define REG_BT_COEX_TABLE 0x06C0 -#define REG_WMAC_RESP_TXINFO 0x06D8 - -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_TEST_USB_TXQS 0xFE48 -#define REG_TEST_SIE_VID 0xFE60 -#define REG_TEST_SIE_PID 0xFE62 -#define REG_TEST_SIE_OPTIONAL 0xFE64 -#define REG_TEST_SIE_CHIRP_K 0xFE65 -#define REG_TEST_SIE_PHY 0xFE66 -#define REG_TEST_SIE_MAC_ADDR 0xFE70 -#define REG_TEST_SIE_STRING 0xFE80 - -#define REG_NORMAL_SIE_VID 0xFE60 -#define REG_NORMAL_SIE_PID 0xFE62 -#define REG_NORMAL_SIE_OPTIONAL 0xFE64 -#define REG_NORMAL_SIE_EP 0xFE65 -#define REG_NORMAL_SIE_PHY 0xFE68 -#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 -#define REG_NORMAL_SIE_STRING 0xFE80 - -#define CR9346 REG_9346CR -#define MSR (REG_CR + 2) -#define ISR REG_HISR -#define TSFR REG_TSFTR - -#define MACIDR0 REG_MACID -#define MACIDR4 (REG_MACID + 4) - -#define PBP REG_PBP - -#define IDR0 MACIDR0 -#define IDR4 MACIDR4 - -#define UNUSED_REGISTER 0x1BF -#define DCAM UNUSED_REGISTER -#define PSR UNUSED_REGISTER -#define BBADDR UNUSED_REGISTER -#define PHYDATAR UNUSED_REGISTER - -#define INVALID_BBRF_VALUE 0x12345678 - -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -#define CMDEEPROM_EN BIT(5) -#define CMDEEPROM_SEL BIT(4) -#define CMD9346CR_9356SEL BIT(4) -#define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL) -#define AUTOLOAD_EFUSE CMDEEPROM_EN - -#define GPIOSEL_GPIO 0 -#define GPIOSEL_ENBT BIT(5) - -#define GPIO_IN REG_GPIO_PIN_CTRL -#define GPIO_OUT (REG_GPIO_PIN_CTRL+1) -#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) -#define GPIO_MOD (REG_GPIO_PIN_CTRL+3) - -/*8723/8188E Host System Interrupt - *Mask Register (offset 0x58, 32 byte) - */ -#define HSIMR_GPIO12_0_INT_EN BIT(0) -#define HSIMR_SPS_OCP_INT_EN BIT(5) -#define HSIMR_RON_INT_EN BIT(6) -#define HSIMR_PDN_INT_EN BIT(7) -#define HSIMR_GPIO9_INT_EN BIT(25) - -/* 8723/8188E Host System Interrupt - * Status Register (offset 0x5C, 32 byte) - */ -#define HSISR_GPIO12_0_INT BIT(0) -#define HSISR_SPS_OCP_INT BIT(5) -#define HSISR_RON_INT_EN BIT(6) -#define HSISR_PDNINT BIT(7) -#define HSISR_GPIO9_INT BIT(25) - -#define MSR_NOLINK 0x00 -#define MSR_ADHOC 0x01 -#define MSR_INFRA 0x02 -#define MSR_AP 0x03 - -#define RRSR_RSC_OFFSET 21 -#define RRSR_SHORT_OFFSET 23 -#define RRSR_RSC_BW_40M 0x600000 -#define RRSR_RSC_UPSUBCHNL 0x400000 -#define RRSR_RSC_LOWSUBCHNL 0x200000 -#define RRSR_SHORT 0x800000 -#define RRSR_1M BIT(0) -#define RRSR_2M BIT(1) -#define RRSR_5_5M BIT(2) -#define RRSR_11M BIT(3) -#define RRSR_6M BIT(4) -#define RRSR_9M BIT(5) -#define RRSR_12M BIT(6) -#define RRSR_18M BIT(7) -#define RRSR_24M BIT(8) -#define RRSR_36M BIT(9) -#define RRSR_48M BIT(10) -#define RRSR_54M BIT(11) -#define RRSR_MCS0 BIT(12) -#define RRSR_MCS1 BIT(13) -#define RRSR_MCS2 BIT(14) -#define RRSR_MCS3 BIT(15) -#define RRSR_MCS4 BIT(16) -#define RRSR_MCS5 BIT(17) -#define RRSR_MCS6 BIT(18) -#define RRSR_MCS7 BIT(19) -#define BRSR_ACKSHORTPMB BIT(23) - -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 -#define RATR_MCS8 0x00100000 -#define RATR_MCS9 0x00200000 -#define RATR_MCS10 0x00400000 -#define RATR_MCS11 0x00800000 -#define RATR_MCS12 0x01000000 -#define RATR_MCS13 0x02000000 -#define RATR_MCS14 0x04000000 -#define RATR_MCS15 0x08000000 - -#define RATE_1M BIT(0) -#define RATE_2M BIT(1) -#define RATE_5_5M BIT(2) -#define RATE_11M BIT(3) -#define RATE_6M BIT(4) -#define RATE_9M BIT(5) -#define RATE_12M BIT(6) -#define RATE_18M BIT(7) -#define RATE_24M BIT(8) -#define RATE_36M BIT(9) -#define RATE_48M BIT(10) -#define RATE_54M BIT(11) -#define RATE_MCS0 BIT(12) -#define RATE_MCS1 BIT(13) -#define RATE_MCS2 BIT(14) -#define RATE_MCS3 BIT(15) -#define RATE_MCS4 BIT(16) -#define RATE_MCS5 BIT(17) -#define RATE_MCS6 BIT(18) -#define RATE_MCS7 BIT(19) -#define RATE_MCS8 BIT(20) -#define RATE_MCS9 BIT(21) -#define RATE_MCS10 BIT(22) -#define RATE_MCS11 BIT(23) -#define RATE_MCS12 BIT(24) -#define RATE_MCS13 BIT(25) -#define RATE_MCS14 BIT(26) -#define RATE_MCS15 BIT(27) - -#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) -#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\ - RATR_24M | RATR_36M | RATR_48M | RATR_54M) -#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 |\ - RATR_MCS3 | RATR_MCS4 | RATR_MCS5 |\ - RATR_MCS6 | RATR_MCS7) -#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 |\ - RATR_MCS11 | RATR_MCS12 | RATR_MCS13 |\ - RATR_MCS14 | RATR_MCS15) - -#define BW_OPMODE_20MHZ BIT(2) -#define BW_OPMODE_5G BIT(1) -#define BW_OPMODE_11J BIT(0) - -#define CAM_VALID BIT(15) -#define CAM_NOTVALID 0x0000 -#define CAM_USEDK BIT(5) - -#define CAM_NONE 0x0 -#define CAM_WEP40 0x01 -#define CAM_TKIP 0x02 -#define CAM_AES 0x04 -#define CAM_WEP104 0x05 - -#define TOTAL_CAM_ENTRY 32 -#define HALF_CAM_ENTRY 16 - -#define CAM_WRITE BIT(16) -#define CAM_READ 0x00000000 -#define CAM_POLLINIG BIT(31) - -#define SCR_USEDK 0x01 -#define SCR_TXSEC_ENABLE 0x02 -#define SCR_RXSEC_ENABLE 0x04 - -#define WOW_PMEN BIT(0) -#define WOW_WOMEN BIT(1) -#define WOW_MAGIC BIT(2) -#define WOW_UWF BIT(3) - -/********************************************* -* 8188 IMR/ISR bits -**********************************************/ -#define IMR_DISABLED 0x0 -/* IMR DW0(0x0060-0063) Bit 0-31 */ -/* TXRPT interrupt when CCX bit of the packet is set */ -#define IMR_TXCCK BIT(30) -/* Power Save Time Out Interrupt */ -#define IMR_PSTIMEOUT BIT(29) -/* When GTIMER4 expires, this bit is set to 1 */ -#define IMR_GTINT4 BIT(28) -/* When GTIMER3 expires, this bit is set to 1 */ -#define IMR_GTINT3 BIT(27) -/* Transmit Beacon0 Error */ -#define IMR_TBDER BIT(26) -/* Transmit Beacon0 OK */ -#define IMR_TBDOK BIT(25) -/* TSF Timer BIT32 toggle indication interrupt */ -#define IMR_TSF_BIT32_TOGGLE BIT(24) -/* Beacon DMA Interrupt 0 */ -#define IMR_BCNDMAINT0 BIT(20) -/* Beacon Queue DMA OK0 */ -#define IMR_BCNDOK0 BIT(16) -/* HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */ -#define IMR_HSISR_IND_ON_INT BIT(15) -/* Beacon DMA Interrupt Extension for Win7 */ -#define IMR_BCNDMAINT_E BIT(14) -/* CTWidnow End or ATIM Window End */ -#define IMR_ATIMEND BIT(12) -/* HISR1 Indicator (HISR1 & HIMR1 is true, this bit is set to 1)*/ -#define IMR_HISR1_IND_INT BIT(11) -/* CPU to Host Command INT Status, Write 1 clear */ -#define IMR_C2HCMD BIT(10) -/* CPU power Mode exchange INT Status, Write 1 clear */ -#define IMR_CPWM2 BIT(9) -/* CPU power Mode exchange INT Status, Write 1 clear */ -#define IMR_CPWM BIT(8) -/* High Queue DMA OK */ -#define IMR_HIGHDOK BIT(7) -/* Management Queue DMA OK */ -#define IMR_MGNTDOK BIT(6) -/* AC_BK DMA OK */ -#define IMR_BKDOK BIT(5) -/* AC_BE DMA OK */ -#define IMR_BEDOK BIT(4) -/* AC_VI DMA OK */ -#define IMR_VIDOK BIT(3) -/* AC_VO DMA OK */ -#define IMR_VODOK BIT(2) -/* Rx Descriptor Unavailable */ -#define IMR_RDU BIT(1) -/* Receive DMA OK */ -#define IMR_ROK BIT(0) - -/* IMR DW1(0x00B4-00B7) Bit 0-31 */ -/* Beacon DMA Interrupt 7 */ -#define IMR_BCNDMAINT7 BIT(27) -/* Beacon DMA Interrupt 6 */ -#define IMR_BCNDMAINT6 BIT(26) -/* Beacon DMA Interrupt 5 */ -#define IMR_BCNDMAINT5 BIT(25) -/* Beacon DMA Interrupt 4 */ -#define IMR_BCNDMAINT4 BIT(24) -/* Beacon DMA Interrupt 3 */ -#define IMR_BCNDMAINT3 BIT(23) -/* Beacon DMA Interrupt 2 */ -#define IMR_BCNDMAINT2 BIT(22) -/* Beacon DMA Interrupt 1 */ -#define IMR_BCNDMAINT1 BIT(21) -/* Beacon Queue DMA OK Interrup 7 */ -#define IMR_BCNDOK7 BIT(20) -/* Beacon Queue DMA OK Interrup 6 */ -#define IMR_BCNDOK6 BIT(19) -/* Beacon Queue DMA OK Interrup 5 */ -#define IMR_BCNDOK5 BIT(18) -/* Beacon Queue DMA OK Interrup 4 */ -#define IMR_BCNDOK4 BIT(17) -/* Beacon Queue DMA OK Interrup 3 */ -#define IMR_BCNDOK3 BIT(16) -/* Beacon Queue DMA OK Interrup 2 */ -#define IMR_BCNDOK2 BIT(15) -/* Beacon Queue DMA OK Interrup 1 */ -#define IMR_BCNDOK1 BIT(14) -/* ATIM Window End Extension for Win7 */ -#define IMR_ATIMEND_E BIT(13) -/* Tx Error Flag Interrupt Status, write 1 clear. */ -#define IMR_TXERR BIT(11) -/* Rx Error Flag INT Status, Write 1 clear */ -#define IMR_RXERR BIT(10) -/* Transmit FIFO Overflow */ -#define IMR_TXFOVW BIT(9) -/* Receive FIFO Overflow */ -#define IMR_RXFOVW BIT(8) - -#define HWSET_MAX_SIZE 512 -#define EFUSE_MAX_SECTION 64 -#define EFUSE_REAL_CONTENT_LEN 256 -/* PG data exclude header, dummy 7 bytes frome CP test and reserved 1byte.*/ -#define EFUSE_OOB_PROTECT_BYTES 18 - -#define EEPROM_DEFAULT_TSSI 0x0 -#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 -#define EEPROM_DEFAULT_CRYSTALCAP 0x5 -#define EEPROM_DEFAULT_BOARDTYPE 0x02 -#define EEPROM_DEFAULT_TXPOWER 0x1010 -#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 - -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 -#define EEPROM_DEFAULT_THERMALMETER 0x18 -#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 -#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 -#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 -#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 -#define EEPROM_DEFAULT_HT20_DIFF 2 -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 -#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 -#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 - -#define RF_OPTION1 0x79 -#define RF_OPTION2 0x7A -#define RF_OPTION3 0x7B -#define RF_OPTION4 0x7C - -#define EEPROM_DEFAULT_PID 0x1234 -#define EEPROM_DEFAULT_VID 0x5678 -#define EEPROM_DEFAULT_CUSTOMERID 0xAB -#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD -#define EEPROM_DEFAULT_VERSION 0 - -#define EEPROM_CHANNEL_PLAN_FCC 0x0 -#define EEPROM_CHANNEL_PLAN_IC 0x1 -#define EEPROM_CHANNEL_PLAN_ETSI 0x2 -#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 -#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 -#define EEPROM_CHANNEL_PLAN_MKK 0x5 -#define EEPROM_CHANNEL_PLAN_MKK1 0x6 -#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 -#define EEPROM_CHANNEL_PLAN_TELEC 0x8 -#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 -#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -#define EEPROM_CHANNEL_PLAN_NCC 0xB -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - -#define EEPROM_CID_DEFAULT 0x0 -#define EEPROM_CID_TOSHIBA 0x4 -#define EEPROM_CID_CCX 0x10 -#define EEPROM_CID_QMI 0x0D -#define EEPROM_CID_WHQL 0xFE - -#define RTL8188E_EEPROM_ID 0x8129 - -#define EEPROM_HPON 0x02 -#define EEPROM_CLK 0x06 -#define EEPROM_TESTR 0x08 - -#define EEPROM_TXPOWERCCK 0x10 -#define EEPROM_TXPOWERHT40_1S 0x16 -#define EEPROM_TXPOWERHT20DIFF 0x1B -#define EEPROM_TXPOWER_OFDMDIFF 0x1B - -#define EEPROM_TX_PWR_INX 0x10 - -#define EEPROM_CHANNELPLAN 0xB8 -#define EEPROM_XTAL_88E 0xB9 -#define EEPROM_THERMAL_METER_88E 0xBA -#define EEPROM_IQK_LCK_88E 0xBB - -#define EEPROM_RF_BOARD_OPTION_88E 0xC1 -#define EEPROM_RF_FEATURE_OPTION_88E 0xC2 -#define EEPROM_RF_BT_SETTING_88E 0xC3 -#define EEPROM_VERSION 0xC4 -#define EEPROM_CUSTOMER_ID 0xC5 -#define EEPROM_RF_ANTENNA_OPT_88E 0xC9 - -#define EEPROM_MAC_ADDR 0xD0 -#define EEPROM_VID 0xD6 -#define EEPROM_DID 0xD8 -#define EEPROM_SVID 0xDA -#define EEPROM_SMID 0xDC - -#define STOPBECON BIT(6) -#define STOPHIGHT BIT(5) -#define STOPMGT BIT(4) -#define STOPVO BIT(3) -#define STOPVI BIT(2) -#define STOPBE BIT(1) -#define STOPBK BIT(0) - -#define RCR_APPFCS BIT(31) -#define RCR_APP_MIC BIT(30) -#define RCR_APP_ICV BIT(29) -#define RCR_APP_PHYST_RXFF BIT(28) -#define RCR_APP_BA_SSN BIT(27) -#define RCR_ENMBID BIT(24) -#define RCR_LSIGEN BIT(23) -#define RCR_MFBEN BIT(22) -#define RCR_HTC_LOC_CTRL BIT(14) -#define RCR_AMF BIT(13) -#define RCR_ACF BIT(12) -#define RCR_ADF BIT(11) -#define RCR_AICV BIT(9) -#define RCR_ACRC32 BIT(8) -#define RCR_CBSSID_BCN BIT(7) -#define RCR_CBSSID_DATA BIT(6) -#define RCR_CBSSID RCR_CBSSID_DATA -#define RCR_APWRMGT BIT(5) -#define RCR_ADD3 BIT(4) -#define RCR_AB BIT(3) -#define RCR_AM BIT(2) -#define RCR_APM BIT(1) -#define RCR_AAP BIT(0) -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - -#define RSV_CTRL 0x001C -#define RD_CTRL 0x0524 - -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_USB_VID 0xFE60 -#define REG_USB_PID 0xFE62 -#define REG_USB_OPTIONAL 0xFE64 -#define REG_USB_CHIRP_K 0xFE65 -#define REG_USB_PHY 0xFE66 -#define REG_USB_MAC_ADDR 0xFE70 -#define REG_USB_HRPWM 0xFE58 -#define REG_USB_HCPWM 0xFE57 - -#define SW18_FPWM BIT(3) - -#define ISO_MD2PP BIT(0) -#define ISO_UA2USB BIT(1) -#define ISO_UD2CORE BIT(2) -#define ISO_PA2PCIE BIT(3) -#define ISO_PD2CORE BIT(4) -#define ISO_IP2MAC BIT(5) -#define ISO_DIOP BIT(6) -#define ISO_DIOE BIT(7) -#define ISO_EB2CORE BIT(8) -#define ISO_DIOR BIT(9) - -#define PWC_EV25V BIT(14) -#define PWC_EV12V BIT(15) - -#define FEN_BBRSTB BIT(0) -#define FEN_BB_GLB_RSTN BIT(1) -#define FEN_USBA BIT(2) -#define FEN_UPLL BIT(3) -#define FEN_USBD BIT(4) -#define FEN_DIO_PCIE BIT(5) -#define FEN_PCIEA BIT(6) -#define FEN_PPLL BIT(7) -#define FEN_PCIED BIT(8) -#define FEN_DIOE BIT(9) -#define FEN_CPUEN BIT(10) -#define FEN_DCORE BIT(11) -#define FEN_ELDR BIT(12) -#define FEN_DIO_RF BIT(13) -#define FEN_HWPDN BIT(14) -#define FEN_MREGEN BIT(15) - -#define PFM_LDALL BIT(0) -#define PFM_ALDN BIT(1) -#define PFM_LDKP BIT(2) -#define PFM_WOWL BIT(3) -#define ENPDN BIT(4) -#define PDN_PL BIT(5) -#define APFM_ONMAC BIT(8) -#define APFM_OFF BIT(9) -#define APFM_RSM BIT(10) -#define AFSM_HSUS BIT(11) -#define AFSM_PCIE BIT(12) -#define APDM_MAC BIT(13) -#define APDM_HOST BIT(14) -#define APDM_HPDN BIT(15) -#define RDY_MACON BIT(16) -#define SUS_HOST BIT(17) -#define ROP_ALD BIT(20) -#define ROP_PWR BIT(21) -#define ROP_SPS BIT(22) -#define SOP_MRST BIT(25) -#define SOP_FUSE BIT(26) -#define SOP_ABG BIT(27) -#define SOP_AMB BIT(28) -#define SOP_RCK BIT(29) -#define SOP_A8M BIT(30) -#define XOP_BTCK BIT(31) - -#define ANAD16V_EN BIT(0) -#define ANA8M BIT(1) -#define MACSLP BIT(4) -#define LOADER_CLK_EN BIT(5) -#define _80M_SSC_DIS BIT(7) -#define _80M_SSC_EN_HO BIT(8) -#define PHY_SSC_RSTB BIT(9) -#define SEC_CLK_EN BIT(10) -#define MAC_CLK_EN BIT(11) -#define SYS_CLK_EN BIT(12) -#define RING_CLK_EN BIT(13) - -#define BOOT_FROM_EEPROM BIT(4) -#define EEPROM_EN BIT(5) - -#define AFE_BGEN BIT(0) -#define AFE_MBEN BIT(1) -#define MAC_ID_EN BIT(7) - -#define WLOCK_ALL BIT(0) -#define WLOCK_00 BIT(1) -#define WLOCK_04 BIT(2) -#define WLOCK_08 BIT(3) -#define WLOCK_40 BIT(4) -#define R_DIS_PRST_0 BIT(5) -#define R_DIS_PRST_1 BIT(6) -#define LOCK_ALL_EN BIT(7) - -#define RF_EN BIT(0) -#define RF_RSTB BIT(1) -#define RF_SDMRSTB BIT(2) - -#define LDA15_EN BIT(0) -#define LDA15_STBY BIT(1) -#define LDA15_OBUF BIT(2) -#define LDA15_REG_VOS BIT(3) -#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) - -#define LDV12_EN BIT(0) -#define LDV12_SDBY BIT(1) -#define LPLDO_HSM BIT(2) -#define LPLDO_LSM_DIS BIT(3) -#define _LDV12_VADJ(x) (((x) & 0xF) << 4) - -#define XTAL_EN BIT(0) -#define XTAL_BSEL BIT(1) -#define _XTAL_BOSC(x) (((x) & 0x3) << 2) -#define _XTAL_CADJ(x) (((x) & 0xF) << 4) -#define XTAL_GATE_USB BIT(8) -#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) -#define XTAL_GATE_AFE BIT(11) -#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) -#define XTAL_RF_GATE BIT(14) -#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) -#define XTAL_GATE_DIG BIT(17) -#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) -#define XTAL_BT_GATE BIT(20) -#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) -#define _XTAL_GPIO(x) (((x) & 0x7) << 23) - -#define CKDLY_AFE BIT(26) -#define CKDLY_USB BIT(27) -#define CKDLY_DIG BIT(28) -#define CKDLY_BT BIT(29) - -#define APLL_EN BIT(0) -#define APLL_320_EN BIT(1) -#define APLL_FREF_SEL BIT(2) -#define APLL_EDGE_SEL BIT(3) -#define APLL_WDOGB BIT(4) -#define APLL_LPFEN BIT(5) - -#define APLL_REF_CLK_13MHZ 0x1 -#define APLL_REF_CLK_19_2MHZ 0x2 -#define APLL_REF_CLK_20MHZ 0x3 -#define APLL_REF_CLK_25MHZ 0x4 -#define APLL_REF_CLK_26MHZ 0x5 -#define APLL_REF_CLK_38_4MHZ 0x6 -#define APLL_REF_CLK_40MHZ 0x7 - -#define APLL_320EN BIT(14) -#define APLL_80EN BIT(15) -#define APLL_1MEN BIT(24) - -#define ALD_EN BIT(18) -#define EF_PD BIT(19) -#define EF_FLAG BIT(31) - -#define EF_TRPT BIT(7) -#define LDOE25_EN BIT(31) - -#define RSM_EN BIT(0) -#define TIMER_EN BIT(4) - -#define TRSW0EN BIT(2) -#define TRSW1EN BIT(3) -#define EROM_EN BIT(4) -#define ENBT BIT(5) -#define ENUART BIT(8) -#define UART_910 BIT(9) -#define ENPMAC BIT(10) -#define SIC_SWRST BIT(11) -#define ENSIC BIT(12) -#define SIC_23 BIT(13) -#define ENHDP BIT(14) -#define SIC_LBK BIT(15) - -#define LED0PL BIT(4) -#define LED1PL BIT(12) -#define LED0DIS BIT(7) - -#define MCUFWDL_EN BIT(0) -#define MCUFWDL_RDY BIT(1) -#define FWDL_CHKSUM_RPT BIT(2) -#define MACINI_RDY BIT(3) -#define BBINI_RDY BIT(4) -#define RFINI_RDY BIT(5) -#define WINTINI_RDY BIT(6) -#define CPRST BIT(23) - -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define TRP_B15V_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define VENDOR_ID BIT(19) -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) - -#define CHIP_VER_RTL_MASK 0xF000 -#define CHIP_VER_RTL_SHIFT 12 - -#define REG_LBMODE (REG_CR + 3) - -#define HCI_TXDMA_EN BIT(0) -#define HCI_RXDMA_EN BIT(1) -#define TXDMA_EN BIT(2) -#define RXDMA_EN BIT(3) -#define PROTOCOL_EN BIT(4) -#define SCHEDULE_EN BIT(5) -#define MACTXEN BIT(6) -#define MACRXEN BIT(7) -#define ENSWBCN BIT(8) -#define ENSEC BIT(9) - -#define _NETTYPE(x) (((x) & 0x3) << 16) -#define MASK_NETTYPE 0x30000 -#define NT_NO_LINK 0x0 -#define NT_LINK_AD_HOC 0x1 -#define NT_LINK_AP 0x2 -#define NT_AS_AP 0x3 - -#define _LBMODE(x) (((x) & 0xF) << 24) -#define MASK_LBMODE 0xF000000 -#define LOOPBACK_NORMAL 0x0 -#define LOOPBACK_IMMEDIATELY 0xB -#define LOOPBACK_MAC_DELAY 0x3 -#define LOOPBACK_PHY 0x1 -#define LOOPBACK_DMA 0x7 - -#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) -#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) -#define _PSRX_MASK 0xF -#define _PSTX_MASK 0xF0 -#define _PSRX(x) (x) -#define _PSTX(x) ((x) << 4) - -#define PBP_64 0x0 -#define PBP_128 0x1 -#define PBP_256 0x2 -#define PBP_512 0x3 -#define PBP_1024 0x4 - -#define RXDMA_ARBBW_EN BIT(0) -#define RXSHFT_EN BIT(1) -#define RXDMA_AGG_EN BIT(2) -#define QS_VO_QUEUE BIT(8) -#define QS_VI_QUEUE BIT(9) -#define QS_BE_QUEUE BIT(10) -#define QS_BK_QUEUE BIT(11) -#define QS_MANAGER_QUEUE BIT(12) -#define QS_HIGH_QUEUE BIT(13) - -#define HQSEL_VOQ BIT(0) -#define HQSEL_VIQ BIT(1) -#define HQSEL_BEQ BIT(2) -#define HQSEL_BKQ BIT(3) -#define HQSEL_MGTQ BIT(4) -#define HQSEL_HIQ BIT(5) - -#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) -#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) -#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) -#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) -#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) -#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) - -#define QUEUE_LOW 1 -#define QUEUE_NORMAL 2 -#define QUEUE_HIGH 3 - -#define _LLT_NO_ACTIVE 0x0 -#define _LLT_WRITE_ACCESS 0x1 -#define _LLT_READ_ACCESS 0x2 - -#define _LLT_INIT_DATA(x) ((x) & 0xFF) -#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) -#define _LLT_OP(x) (((x) & 0x3) << 30) -#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) - -#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) -#define BB_WRITE_EN BIT(30) -#define BB_READ_EN BIT(31) - -#define _HPQ(x) ((x) & 0xFF) -#define _LPQ(x) (((x) & 0xFF) << 8) -#define _PUBQ(x) (((x) & 0xFF) << 16) -#define _NPQ(x) ((x) & 0xFF) - -#define HPQ_PUBLIC_DIS BIT(24) -#define LPQ_PUBLIC_DIS BIT(25) -#define LD_RQPN BIT(31) - -#define BCN_VALID BIT(16) -#define BCN_HEAD(x) (((x) & 0xFF) << 8) -#define BCN_HEAD_MASK 0xFF00 - -#define BLK_DESC_NUM_SHIFT 4 -#define BLK_DESC_NUM_MASK 0xF - -#define DROP_DATA_EN BIT(9) - -#define EN_AMPDU_RTY_NEW BIT(7) - -#define _INIRTSMCS_SEL(x) ((x) & 0x3F) - -#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) -#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) - -#define RATE_REG_BITMAP_ALL 0xFFFFF - -#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) - -#define _RRSR_RSC(x) (((x) & 0x3) << 21) -#define RRSR_RSC_RESERVED 0x0 -#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 -#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 -#define RRSR_RSC_DUPLICATE_MODE 0x3 - -#define USE_SHORT_G1 BIT(20) - -#define _AGGLMT_MCS0(x) ((x) & 0xF) -#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) -#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) -#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) -#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) -#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) -#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) -#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) - -#define RETRY_LIMIT_SHORT_SHIFT 8 -#define RETRY_LIMIT_LONG_SHIFT 0 - -#define _DARF_RC1(x) ((x) & 0x1F) -#define _DARF_RC2(x) (((x) & 0x1F) << 8) -#define _DARF_RC3(x) (((x) & 0x1F) << 16) -#define _DARF_RC4(x) (((x) & 0x1F) << 24) -#define _DARF_RC5(x) ((x) & 0x1F) -#define _DARF_RC6(x) (((x) & 0x1F) << 8) -#define _DARF_RC7(x) (((x) & 0x1F) << 16) -#define _DARF_RC8(x) (((x) & 0x1F) << 24) - -#define _RARF_RC1(x) ((x) & 0x1F) -#define _RARF_RC2(x) (((x) & 0x1F) << 8) -#define _RARF_RC3(x) (((x) & 0x1F) << 16) -#define _RARF_RC4(x) (((x) & 0x1F) << 24) -#define _RARF_RC5(x) ((x) & 0x1F) -#define _RARF_RC6(x) (((x) & 0x1F) << 8) -#define _RARF_RC7(x) (((x) & 0x1F) << 16) -#define _RARF_RC8(x) (((x) & 0x1F) << 24) - -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - -#define _AIFS(x) (x) -#define _ECW_MAX_MIN(x) ((x) << 8) -#define _TXOP_LIMIT(x) ((x) << 16) - -#define _BCNIFS(x) ((x) & 0xFF) -#define _BCNECW(x) ((((x) & 0xF)) << 8) - -#define _LRL(x) ((x) & 0x3F) -#define _SRL(x) (((x) & 0x3F) << 8) - -#define _SIFS_CCK_CTX(x) ((x) & 0xFF) -#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8); - -#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) -#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8); - -#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) - -#define DIS_EDCA_CNT_DWN BIT(11) - -#define EN_MBSSID BIT(1) -#define EN_TXBCN_RPT BIT(2) -#define EN_BCN_FUNCTION BIT(3) - -#define TSFTR_RST BIT(0) -#define TSFTR1_RST BIT(1) - -#define STOP_BCNQ BIT(6) - -#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) -#define DIS_TSF_UDT0_TEST_CHIP BIT(5) - -#define ACMHW_HWEN BIT(0) -#define ACMHW_BEQEN BIT(1) -#define ACMHW_VIQEN BIT(2) -#define ACMHW_VOQEN BIT(3) -#define ACMHW_BEQSTATUS BIT(4) -#define ACMHW_VIQSTATUS BIT(5) -#define ACMHW_VOQSTATUS BIT(6) - -#define APSDOFF BIT(6) -#define APSDOFF_STATUS BIT(7) - -#define BW_20MHZ BIT(2) - -#define RATE_BITMAP_ALL 0xFFFFF - -#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 - -#define TSFRST BIT(0) -#define DIS_GCLK BIT(1) -#define PAD_SEL BIT(2) -#define PWR_ST BIT(6) -#define PWRBIT_OW_EN BIT(7) -#define ACRC BIT(8) -#define CFENDFORM BIT(9) -#define ICV BIT(10) - -#define AAP BIT(0) -#define APM BIT(1) -#define AM BIT(2) -#define AB BIT(3) -#define ADD3 BIT(4) -#define APWRMGT BIT(5) -#define CBSSID BIT(6) -#define CBSSID_DATA BIT(6) -#define CBSSID_BCN BIT(7) -#define ACRC32 BIT(8) -#define AICV BIT(9) -#define ADF BIT(11) -#define ACF BIT(12) -#define AMF BIT(13) -#define HTC_LOC_CTRL BIT(14) -#define UC_DATA_EN BIT(16) -#define BM_DATA_EN BIT(17) -#define MFBEN BIT(22) -#define LSIGEN BIT(23) -#define ENMBID BIT(24) -#define APP_BASSN BIT(27) -#define APP_PHYSTS BIT(28) -#define APP_ICV BIT(29) -#define APP_MIC BIT(30) -#define APP_FCS BIT(31) - -#define _MIN_SPACE(x) ((x) & 0x7) -#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) - -#define RXERR_TYPE_OFDM_PPDU 0 -#define RXERR_TYPE_OFDM_FALSE_ALARM 1 -#define RXERR_TYPE_OFDM_MPDU_OK 2 -#define RXERR_TYPE_OFDM_MPDU_FAIL 3 -#define RXERR_TYPE_CCK_PPDU 4 -#define RXERR_TYPE_CCK_FALSE_ALARM 5 -#define RXERR_TYPE_CCK_MPDU_OK 6 -#define RXERR_TYPE_CCK_MPDU_FAIL 7 -#define RXERR_TYPE_HT_PPDU 8 -#define RXERR_TYPE_HT_FALSE_ALARM 9 -#define RXERR_TYPE_HT_MPDU_TOTAL 10 -#define RXERR_TYPE_HT_MPDU_OK 11 -#define RXERR_TYPE_HT_MPDU_FAIL 12 -#define RXERR_TYPE_RX_FULL_DROP 15 - -#define RXERR_COUNTER_MASK 0xFFFFF -#define RXERR_RPT_RST BIT(27) -#define _RXERR_RPT_SEL(type) ((type) << 28) - -#define SCR_TXUSEDK BIT(0) -#define SCR_RXUSEDK BIT(1) -#define SCR_TXENCENABLE BIT(2) -#define SCR_RXDECENABLE BIT(3) -#define SCR_SKBYA2 BIT(4) -#define SCR_NOSKMC BIT(5) -#define SCR_TXBCUSEDK BIT(6) -#define SCR_RXBCUSEDK BIT(7) - -#define USB_IS_HIGH_SPEED 0 -#define USB_IS_FULL_SPEED 1 -#define USB_SPEED_MASK BIT(5) - -#define USB_NORMAL_SIE_EP_MASK 0xF -#define USB_NORMAL_SIE_EP_SHIFT 4 - -#define USB_TEST_EP_MASK 0x30 -#define USB_TEST_EP_SHIFT 4 - -#define USB_AGG_EN BIT(3) - -#define MAC_ADDR_LEN 6 -#define LAST_ENTRY_OF_TX_PKT_BUFFER 175/*255 88e*/ - -#define POLLING_LLT_THRESHOLD 20 -#define POLLING_READY_TIMEOUT_COUNT 3000 - -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) -#define EPROM_CMD_CONFIG 0x3 -#define EPROM_CMD_LOAD 1 - -#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE - -#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) - -#define RPMAC_RESET 0x100 -#define RPMAC_TXSTART 0x104 -#define RPMAC_TXLEGACYSIG 0x108 -#define RPMAC_TXHTSIG1 0x10c -#define RPMAC_TXHTSIG2 0x110 -#define RPMAC_PHYDEBUG 0x114 -#define RPMAC_TXPACKETNUM 0x118 -#define RPMAC_TXIDLE 0x11c -#define RPMAC_TXMACHEADER0 0x120 -#define RPMAC_TXMACHEADER1 0x124 -#define RPMAC_TXMACHEADER2 0x128 -#define RPMAC_TXMACHEADER3 0x12c -#define RPMAC_TXMACHEADER4 0x130 -#define RPMAC_TXMACHEADER5 0x134 -#define RPMAC_TXDADATYPE 0x138 -#define RPMAC_TXRANDOMSEED 0x13c -#define RPMAC_CCKPLCPPREAMBLE 0x140 -#define RPMAC_CCKPLCPHEADER 0x144 -#define RPMAC_CCKCRC16 0x148 -#define RPMAC_OFDMRXCRC32OK 0x170 -#define RPMAC_OFDMRXCRC32ER 0x174 -#define RPMAC_OFDMRXPARITYER 0x178 -#define RPMAC_OFDMRXCRC8ER 0x17c -#define RPMAC_CCKCRXRC16ER 0x180 -#define RPMAC_CCKCRXRC32ER 0x184 -#define RPMAC_CCKCRXRC32OK 0x188 -#define RPMAC_TXSTATUS 0x18c - -#define RFPGA0_RFMOD 0x800 - -#define RFPGA0_TXINFO 0x804 -#define RFPGA0_PSDFUNCTION 0x808 - -#define RFPGA0_TXGAINSTAGE 0x80c - -#define RFPGA0_RFTIMING1 0x810 -#define RFPGA0_RFTIMING2 0x814 - -#define RFPGA0_XA_HSSIPARAMETER1 0x820 -#define RFPGA0_XA_HSSIPARAMETER2 0x824 -#define RFPGA0_XB_HSSIPARAMETER1 0x828 -#define RFPGA0_XB_HSSIPARAMETER2 0x82c - -#define RFPGA0_XA_LSSIPARAMETER 0x840 -#define RFPGA0_XB_LSSIPARAMETER 0x844 - -#define RFPGA0_RFWAKEUPPARAMETER 0x850 -#define RFPGA0_RFSLEEPUPPARAMETER 0x854 - -#define RFPGA0_XAB_SWITCHCONTROL 0x858 -#define RFPGA0_XCD_SWITCHCONTROL 0x85c - -#define RFPGA0_XA_RFINTERFACEOE 0x860 -#define RFPGA0_XB_RFINTERFACEOE 0x864 - -#define RFPGA0_XAB_RFINTERFACESW 0x870 -#define RFPGA0_XCD_RFINTERFACESW 0x874 - -#define RFPGA0_XAB_RFPARAMETER 0x878 -#define RFPGA0_XCD_RFPARAMETER 0x87c - -#define RFPGA0_ANALOGPARAMETER1 0x880 -#define RFPGA0_ANALOGPARAMETER2 0x884 -#define RFPGA0_ANALOGPARAMETER3 0x888 -#define RFPGA0_ANALOGPARAMETER4 0x88c - -#define RFPGA0_XA_LSSIREADBACK 0x8a0 -#define RFPGA0_XB_LSSIREADBACK 0x8a4 -#define RFPGA0_XC_LSSIREADBACK 0x8a8 -#define RFPGA0_XD_LSSIREADBACK 0x8ac - -#define RFPGA0_PSDREPORT 0x8b4 -#define TRANSCEIVEA_HSPI_READBACK 0x8b8 -#define TRANSCEIVEB_HSPI_READBACK 0x8bc -#define REG_SC_CNT 0x8c4 -#define RFPGA0_XAB_RFINTERFACERB 0x8e0 -#define RFPGA0_XCD_RFINTERFACERB 0x8e4 - -#define RFPGA1_RFMOD 0x900 - -#define RFPGA1_TXBLOCK 0x904 -#define RFPGA1_DEBUGSELECT 0x908 -#define RFPGA1_TXINFO 0x90c - -#define RCCK0_SYSTEM 0xa00 - -#define RCCK0_AFESETTING 0xa04 -#define RCCK0_CCA 0xa08 - -#define RCCK0_RXAGC1 0xa0c -#define RCCK0_RXAGC2 0xa10 - -#define RCCK0_RXHP 0xa14 - -#define RCCK0_DSPPARAMETER1 0xa18 -#define RCCK0_DSPPARAMETER2 0xa1c - -#define RCCK0_TXFILTER1 0xa20 -#define RCCK0_TXFILTER2 0xa24 -#define RCCK0_DEBUGPORT 0xa28 -#define RCCK0_FALSEALARMREPORT 0xa2c -#define RCCK0_TRSSIREPORT 0xa50 -#define RCCK0_RXREPORT 0xa54 -#define RCCK0_FACOUNTERLOWER 0xa5c -#define RCCK0_FACOUNTERUPPER 0xa58 -#define RCCK0_CCA_CNT 0xa60 - -/* PageB(0xB00) */ -#define RPDP_ANTA 0xb00 -#define RPDP_ANTA_4 0xb04 -#define RPDP_ANTA_8 0xb08 -#define RPDP_ANTA_C 0xb0c -#define RPDP_ANTA_10 0xb10 -#define RPDP_ANTA_14 0xb14 -#define RPDP_ANTA_18 0xb18 -#define RPDP_ANTA_1C 0xb1c -#define RPDP_ANTA_20 0xb20 -#define RPDP_ANTA_24 0xb24 - -#define RCONFIG_PMPD_ANTA 0xb28 -#define RCONFIG_RAM64x16 0xb2c - -#define RBNDA 0xb30 -#define RHSSIPAR 0xb34 - -#define RCONFIG_ANTA 0xb68 -#define RCONFIG_ANTB 0xb6c - -#define RPDP_ANTB 0xb70 -#define RPDP_ANTB_4 0xb74 -#define RPDP_ANTB_8 0xb78 -#define RPDP_ANTB_C 0xb7c -#define RPDP_ANTB_10 0xb80 -#define RPDP_ANTB_14 0xb84 -#define RPDP_ANTB_18 0xb88 -#define RPDP_ANTB_1C 0xb8c -#define RPDP_ANTB_20 0xb90 -#define RPDP_ANTB_24 0xb94 - -#define RCONFIG_PMPD_ANTB 0xb98 - -#define RBNDB 0xba0 - -#define RAPK 0xbd8 -#define RPM_RX0_ANTA 0xbdc -#define RPM_RX1_ANTA 0xbe0 -#define RPM_RX2_ANTA 0xbe4 -#define RPM_RX3_ANTA 0xbe8 -#define RPM_RX0_ANTB 0xbec -#define RPM_RX1_ANTB 0xbf0 -#define RPM_RX2_ANTB 0xbf4 -#define RPM_RX3_ANTB 0xbf8 - -/*Page C*/ -#define ROFDM0_LSTF 0xc00 - -#define ROFDM0_TRXPATHENABLE 0xc04 -#define ROFDM0_TRMUXPAR 0xc08 -#define ROFDM0_TRSWISOLATION 0xc0c - -#define ROFDM0_XARXAFE 0xc10 -#define ROFDM0_XARXIQIMBALANCE 0xc14 -#define ROFDM0_XBRXAFE 0xc18 -#define ROFDM0_XBRXIQIMBALANCE 0xc1c -#define ROFDM0_XCRXAFE 0xc20 -#define ROFDM0_XCRXIQIMBANLANCE 0xc24 -#define ROFDM0_XDRXAFE 0xc28 -#define ROFDM0_XDRXIQIMBALANCE 0xc2c - -#define ROFDM0_RXDETECTOR1 0xc30 -#define ROFDM0_RXDETECTOR2 0xc34 -#define ROFDM0_RXDETECTOR3 0xc38 -#define ROFDM0_RXDETECTOR4 0xc3c - -#define ROFDM0_RXDSP 0xc40 -#define ROFDM0_CFOANDDAGC 0xc44 -#define ROFDM0_CCADROPTHRESHOLD 0xc48 -#define ROFDM0_ECCATHRESHOLD 0xc4c - -#define ROFDM0_XAAGCCORE1 0xc50 -#define ROFDM0_XAAGCCORE2 0xc54 -#define ROFDM0_XBAGCCORE1 0xc58 -#define ROFDM0_XBAGCCORE2 0xc5c -#define ROFDM0_XCAGCCORE1 0xc60 -#define ROFDM0_XCAGCCORE2 0xc64 -#define ROFDM0_XDAGCCORE1 0xc68 -#define ROFDM0_XDAGCCORE2 0xc6c - -#define ROFDM0_AGCPARAMETER1 0xc70 -#define ROFDM0_AGCPARAMETER2 0xc74 -#define ROFDM0_AGCRSSITABLE 0xc78 -#define ROFDM0_HTSTFAGC 0xc7c - -#define ROFDM0_XATXIQIMBALANCE 0xc80 -#define ROFDM0_XATXAFE 0xc84 -#define ROFDM0_XBTXIQIMBALANCE 0xc88 -#define ROFDM0_XBTXAFE 0xc8c -#define ROFDM0_XCTXIQIMBALANCE 0xc90 -#define ROFDM0_XCTXAFE 0xc94 -#define ROFDM0_XDTXIQIMBALANCE 0xc98 -#define ROFDM0_XDTXAFE 0xc9c - -#define ROFDM0_RXIQEXTANTA 0xca0 -#define ROFDM0_TXCOEFF1 0xca4 -#define ROFDM0_TXCOEFF2 0xca8 -#define ROFDM0_TXCOEFF3 0xcac -#define ROFDM0_TXCOEFF4 0xcb0 -#define ROFDM0_TXCOEFF5 0xcb4 -#define ROFDM0_TXCOEFF6 0xcb8 - -#define ROFDM0_RXHPPARAMETER 0xce0 -#define ROFDM0_TXPSEUDONOISEWGT 0xce4 -#define ROFDM0_FRAMESYNC 0xcf0 -#define ROFDM0_DFSREPORT 0xcf4 - -#define ROFDM1_LSTF 0xd00 -#define ROFDM1_TRXPATHENABLE 0xd04 - -#define ROFDM1_CF0 0xd08 -#define ROFDM1_CSI1 0xd10 -#define ROFDM1_SBD 0xd14 -#define ROFDM1_CSI2 0xd18 -#define ROFDM1_CFOTRACKING 0xd2c -#define ROFDM1_TRXMESAURE1 0xd34 -#define ROFDM1_INTFDET 0xd3c -#define ROFDM1_PSEUDONOISESTATEAB 0xd50 -#define ROFDM1_PSEUDONOISESTATECD 0xd54 -#define ROFDM1_RXPSEUDONOISEWGT 0xd58 - -#define ROFDM_PHYCOUNTER1 0xda0 -#define ROFDM_PHYCOUNTER2 0xda4 -#define ROFDM_PHYCOUNTER3 0xda8 - -#define ROFDM_SHORTCFOAB 0xdac -#define ROFDM_SHORTCFOCD 0xdb0 -#define ROFDM_LONGCFOAB 0xdb4 -#define ROFDM_LONGCFOCD 0xdb8 -#define ROFDM_TAILCF0AB 0xdbc -#define ROFDM_TAILCF0CD 0xdc0 -#define ROFDM_PWMEASURE1 0xdc4 -#define ROFDM_PWMEASURE2 0xdc8 -#define ROFDM_BWREPORT 0xdcc -#define ROFDM_AGCREPORT 0xdd0 -#define ROFDM_RXSNR 0xdd4 -#define ROFDM_RXEVMCSI 0xdd8 -#define ROFDM_SIGREPORT 0xddc - -#define RTXAGC_A_RATE18_06 0xe00 -#define RTXAGC_A_RATE54_24 0xe04 -#define RTXAGC_A_CCK1_MCS32 0xe08 -#define RTXAGC_A_MCS03_MCS00 0xe10 -#define RTXAGC_A_MCS07_MCS04 0xe14 -#define RTXAGC_A_MCS11_MCS08 0xe18 -#define RTXAGC_A_MCS15_MCS12 0xe1c - -#define RTXAGC_B_RATE18_06 0x830 -#define RTXAGC_B_RATE54_24 0x834 -#define RTXAGC_B_CCK1_55_MCS32 0x838 -#define RTXAGC_B_MCS03_MCS00 0x83c -#define RTXAGC_B_MCS07_MCS04 0x848 -#define RTXAGC_B_MCS11_MCS08 0x84c -#define RTXAGC_B_MCS15_MCS12 0x868 -#define RTXAGC_B_CCK11_A_CCK2_11 0x86c - -#define RFPGA0_IQK 0xe28 -#define RTX_IQK_TONE_A 0xe30 -#define RRX_IQK_TONE_A 0xe34 -#define RTX_IQK_PI_A 0xe38 -#define RRX_IQK_PI_A 0xe3c - -#define RTX_IQK 0xe40 -#define RRX_IQK 0xe44 -#define RIQK_AGC_PTS 0xe48 -#define RIQK_AGC_RSP 0xe4c -#define RTX_IQK_TONE_B 0xe50 -#define RRX_IQK_TONE_B 0xe54 -#define RTX_IQK_PI_B 0xe58 -#define RRX_IQK_PI_B 0xe5c -#define RIQK_AGC_CONT 0xe60 - -#define RBLUE_TOOTH 0xe6c -#define RRX_WAIT_CCA 0xe70 -#define RTX_CCK_RFON 0xe74 -#define RTX_CCK_BBON 0xe78 -#define RTX_OFDM_RFON 0xe7c -#define RTX_OFDM_BBON 0xe80 -#define RTX_TO_RX 0xe84 -#define RTX_TO_TX 0xe88 -#define RRX_CCK 0xe8c - -#define RTX_POWER_BEFORE_IQK_A 0xe94 -#define RTX_POWER_AFTER_IQK_A 0xe9c - -#define RRX_POWER_BEFORE_IQK_A 0xea0 -#define RRX_POWER_BEFORE_IQK_A_2 0xea4 -#define RRX_POWER_AFTER_IQK_A 0xea8 -#define RRX_POWER_AFTER_IQK_A_2 0xeac - -#define RTX_POWER_BEFORE_IQK_B 0xeb4 -#define RTX_POWER_AFTER_IQK_B 0xebc - -#define RRX_POWER_BEFORE_IQK_B 0xec0 -#define RRX_POWER_BEFORE_IQK_B_2 0xec4 -#define RRX_POWER_AFTER_IQK_B 0xec8 -#define RRX_POWER_AFTER_IQK_B_2 0xecc - -#define RRX_OFDM 0xed0 -#define RRX_WAIT_RIFS 0xed4 -#define RRX_TO_RX 0xed8 -#define RSTANDBY 0xedc -#define RSLEEP 0xee0 -#define RPMPD_ANAEN 0xeec - -#define RZEBRA1_HSSIENABLE 0x0 -#define RZEBRA1_TRXENABLE1 0x1 -#define RZEBRA1_TRXENABLE2 0x2 -#define RZEBRA1_AGC 0x4 -#define RZEBRA1_CHARGEPUMP 0x5 -#define RZEBRA1_CHANNEL 0x7 - -#define RZEBRA1_TXGAIN 0x8 -#define RZEBRA1_TXLPF 0x9 -#define RZEBRA1_RXLPF 0xb -#define RZEBRA1_RXHPFCORNER 0xc - -#define RGLOBALCTRL 0 -#define RRTL8256_TXLPF 19 -#define RRTL8256_RXLPF 11 -#define RRTL8258_TXLPF 0x11 -#define RRTL8258_RXLPF 0x13 -#define RRTL8258_RSSILPF 0xa - -#define RF_AC 0x00 - -#define RF_IQADJ_G1 0x01 -#define RF_IQADJ_G2 0x02 -#define RF_POW_TRSW 0x05 - -#define RF_GAIN_RX 0x06 -#define RF_GAIN_TX 0x07 - -#define RF_TXM_IDAC 0x08 -#define RF_BS_IQGEN 0x0F - -#define RF_MODE1 0x10 -#define RF_MODE2 0x11 - -#define RF_RX_AGC_HP 0x12 -#define RF_TX_AGC 0x13 -#define RF_BIAS 0x14 -#define RF_IPA 0x15 -#define RF_POW_ABILITY 0x17 -#define RF_MODE_AG 0x18 -#define RRFCHANNEL 0x18 -#define RF_CHNLBW 0x18 -#define RF_TOP 0x19 - -#define RF_RX_G1 0x1A -#define RF_RX_G2 0x1B - -#define RF_RX_BB2 0x1C -#define RF_RX_BB1 0x1D - -#define RF_RCK1 0x1E -#define RF_RCK2 0x1F - -#define RF_TX_G1 0x20 -#define RF_TX_G2 0x21 -#define RF_TX_G3 0x22 - -#define RF_TX_BB1 0x23 -#define RF_T_METER 0x42 - -#define RF_SYN_G1 0x25 -#define RF_SYN_G2 0x26 -#define RF_SYN_G3 0x27 -#define RF_SYN_G4 0x28 -#define RF_SYN_G5 0x29 -#define RF_SYN_G6 0x2A -#define RF_SYN_G7 0x2B -#define RF_SYN_G8 0x2C - -#define RF_RCK_OS 0x30 -#define RF_TXPA_G1 0x31 -#define RF_TXPA_G2 0x32 -#define RF_TXPA_G3 0x33 - -#define RF_TX_BIAS_A 0x35 -#define RF_TX_BIAS_D 0x36 -#define RF_LOBF_9 0x38 -#define RF_RXRF_A3 0x3C -#define RF_TRSW 0x3F - -#define RF_TXRF_A2 0x41 -#define RF_TXPA_G4 0x46 -#define RF_TXPA_A4 0x4B - -#define RF_WE_LUT 0xEF - -#define BBBRESETB 0x100 -#define BGLOBALRESETB 0x200 -#define BOFDMTXSTART 0x4 -#define BCCKTXSTART 0x8 -#define BCRC32DEBUG 0x100 -#define BPMACLOOPBACK 0x10 -#define BTXLSIG 0xffffff -#define BOFDMTXRATE 0xf -#define BOFDMTXRESERVED 0x10 -#define BOFDMTXLENGTH 0x1ffe0 -#define BOFDMTXPARITY 0x20000 -#define BTXHTSIG1 0xffffff -#define BTXHTMCSRATE 0x7f -#define BTXHTBW 0x80 -#define BTXHTLENGTH 0xffff00 -#define BTXHTSIG2 0xffffff -#define BTXHTSMOOTHING 0x1 -#define BTXHTSOUNDING 0x2 -#define BTXHTRESERVED 0x4 -#define BTXHTAGGREATION 0x8 -#define BTXHTSTBC 0x30 -#define BTXHTADVANCECODING 0x40 -#define BTXHTSHORTGI 0x80 -#define BTXHTNUMBERHT_LTF 0x300 -#define BTXHTCRC8 0x3fc00 -#define BCOUNTERRESET 0x10000 -#define BNUMOFOFDMTX 0xffff -#define BNUMOFCCKTX 0xffff0000 -#define BTXIDLEINTERVAL 0xffff -#define BOFDMSERVICE 0xffff0000 -#define BTXMACHEADER 0xffffffff -#define BTXDATAINIT 0xff -#define BTXHTMODE 0x100 -#define BTXDATATYPE 0x30000 -#define BTXRANDOMSEED 0xffffffff -#define BCCKTXPREAMBLE 0x1 -#define BCCKTXSFD 0xffff0000 -#define BCCKTXSIG 0xff -#define BCCKTXSERVICE 0xff00 -#define BCCKLENGTHEXT 0x8000 -#define BCCKTXLENGHT 0xffff0000 -#define BCCKTXCRC16 0xffff -#define BCCKTXSTATUS 0x1 -#define BOFDMTXSTATUS 0x2 -#define IS_BB_REG_OFFSET_92S(_offset) \ - ((_offset >= 0x800) && (_offset <= 0xfff)) - -#define BRFMOD 0x1 -#define BJAPANMODE 0x2 -#define BCCKTXSC 0x30 -#define BCCKEN 0x1000000 -#define BOFDMEN 0x2000000 - -#define BOFDMRXADCPHASE 0x10000 -#define BOFDMTXDACPHASE 0x40000 -#define BXATXAGC 0x3f - -#define BXBTXAGC 0xf00 -#define BXCTXAGC 0xf000 -#define BXDTXAGC 0xf0000 - -#define BPASTART 0xf0000000 -#define BTRSTART 0x00f00000 -#define BRFSTART 0x0000f000 -#define BBBSTART 0x000000f0 -#define BBBCCKSTART 0x0000000f -#define BPAEND 0xf -#define BTREND 0x0f000000 -#define BRFEND 0x000f0000 -#define BCCAMASK 0x000000f0 -#define BR2RCCAMASK 0x00000f00 -#define BHSSI_R2TDELAY 0xf8000000 -#define BHSSI_T2RDELAY 0xf80000 -#define BCONTXHSSI 0x400 -#define BIGFROMCCK 0x200 -#define BAGCADDRESS 0x3f -#define BRXHPTX 0x7000 -#define BRXHP2RX 0x38000 -#define BRXHPCCKINI 0xc0000 -#define BAGCTXCODE 0xc00000 -#define BAGCRXCODE 0x300000 - -#define B3WIREDATALENGTH 0x800 -#define B3WIREADDREAALENGTH 0x400 - -#define B3WIRERFPOWERDOWN 0x1 -#define B5GPAPEPOLARITY 0x40000000 -#define B2GPAPEPOLARITY 0x80000000 -#define BRFSW_TXDEFAULTANT 0x3 -#define BRFSW_TXOPTIONANT 0x30 -#define BRFSW_RXDEFAULTANT 0x300 -#define BRFSW_RXOPTIONANT 0x3000 -#define BRFSI_3WIREDATA 0x1 -#define BRFSI_3WIRECLOCK 0x2 -#define BRFSI_3WIRELOAD 0x4 -#define BRFSI_3WIRERW 0x8 -#define BRFSI_3WIRE 0xf - -#define BRFSI_RFENV 0x10 - -#define BRFSI_TRSW 0x20 -#define BRFSI_TRSWB 0x40 -#define BRFSI_ANTSW 0x100 -#define BRFSI_ANTSWB 0x200 -#define BRFSI_PAPE 0x400 -#define BRFSI_PAPE5G 0x800 -#define BBANDSELECT 0x1 -#define BHTSIG2_GI 0x80 -#define BHTSIG2_SMOOTHING 0x01 -#define BHTSIG2_SOUNDING 0x02 -#define BHTSIG2_AGGREATON 0x08 -#define BHTSIG2_STBC 0x30 -#define BHTSIG2_ADVCODING 0x40 -#define BHTSIG2_NUMOFHTLTF 0x300 -#define BHTSIG2_CRC8 0x3fc -#define BHTSIG1_MCS 0x7f -#define BHTSIG1_BANDWIDTH 0x80 -#define BHTSIG1_HTLENGTH 0xffff -#define BLSIG_RATE 0xf -#define BLSIG_RESERVED 0x10 -#define BLSIG_LENGTH 0x1fffe -#define BLSIG_PARITY 0x20 -#define BCCKRXPHASE 0x4 - -#define BLSSIREADADDRESS 0x7f800000 -#define BLSSIREADEDGE 0x80000000 - -#define BLSSIREADBACKDATA 0xfffff - -#define BLSSIREADOKFLAG 0x1000 -#define BCCKSAMPLERATE 0x8 -#define BREGULATOR0STANDBY 0x1 -#define BREGULATORPLLSTANDBY 0x2 -#define BREGULATOR1STANDBY 0x4 -#define BPLLPOWERUP 0x8 -#define BDPLLPOWERUP 0x10 -#define BDA10POWERUP 0x20 -#define BAD7POWERUP 0x200 -#define BDA6POWERUP 0x2000 -#define BXTALPOWERUP 0x4000 -#define B40MDCLKPOWERUP 0x8000 -#define BDA6DEBUGMODE 0x20000 -#define BDA6SWING 0x380000 - -#define BADCLKPHASE 0x4000000 -#define B80MCLKDELAY 0x18000000 -#define BAFEWATCHDOGENABLE 0x20000000 - -#define BXTALCAP01 0xc0000000 -#define BXTALCAP23 0x3 -#define BXTALCAP92X 0x0f000000 -#define BXTALCAP 0x0f000000 - -#define BINTDIFCLKENABLE 0x400 -#define BEXTSIGCLKENABLE 0x800 -#define BBANDGAP_MBIAS_POWERUP 0x10000 -#define BAD11SH_GAIN 0xc0000 -#define BAD11NPUT_RANGE 0x700000 -#define BAD110P_CURRENT 0x3800000 -#define BLPATH_LOOPBACK 0x4000000 -#define BQPATH_LOOPBACK 0x8000000 -#define BAFE_LOOPBACK 0x10000000 -#define BDA10_SWING 0x7e0 -#define BDA10_REVERSE 0x800 -#define BDA_CLK_SOURCE 0x1000 -#define BDA7INPUT_RANGE 0x6000 -#define BDA7_GAIN 0x38000 -#define BDA7OUTPUT_CM_MODE 0x40000 -#define BDA7INPUT_CM_MODE 0x380000 -#define BDA7CURRENT 0xc00000 -#define BREGULATOR_ADJUST 0x7000000 -#define BAD11POWERUP_ATTX 0x1 -#define BDA10PS_ATTX 0x10 -#define BAD11POWERUP_ATRX 0x100 -#define BDA10PS_ATRX 0x1000 -#define BCCKRX_AGC_FORMAT 0x200 -#define BPSDFFT_SAMPLE_POINT 0xc000 -#define BPSD_AVERAGE_NUM 0x3000 -#define BIQPATH_CONTROL 0xc00 -#define BPSD_FREQ 0x3ff -#define BPSD_ANTENNA_PATH 0x30 -#define BPSD_IQ_SWITCH 0x40 -#define BPSD_RX_TRIGGER 0x400000 -#define BPSD_TX_TRIGGER 0x80000000 -#define BPSD_SINE_TONE_SCALE 0x7f000000 -#define BPSD_REPORT 0xffff - -#define BOFDM_TXSC 0x30000000 -#define BCCK_TXON 0x1 -#define BOFDM_TXON 0x2 -#define BDEBUG_PAGE 0xfff -#define BDEBUG_ITEM 0xff -#define BANTL 0x10 -#define BANT_NONHT 0x100 -#define BANT_HT1 0x1000 -#define BANT_HT2 0x10000 -#define BANT_HT1S1 0x100000 -#define BANT_NONHTS1 0x1000000 - -#define BCCK_BBMODE 0x3 -#define BCCK_TXPOWERSAVING 0x80 -#define BCCK_RXPOWERSAVING 0x40 - -#define BCCK_SIDEBAND 0x10 - -#define BCCK_SCRAMBLE 0x8 -#define BCCK_ANTDIVERSITY 0x8000 -#define BCCK_CARRIER_RECOVERY 0x4000 -#define BCCK_TXRATE 0x3000 -#define BCCK_DCCANCEL 0x0800 -#define BCCK_ISICANCEL 0x0400 -#define BCCK_MATCH_FILTER 0x0200 -#define BCCK_EQUALIZER 0x0100 -#define BCCK_PREAMBLE_DETECT 0x800000 -#define BCCK_FAST_FALSECCA 0x400000 -#define BCCK_CH_ESTSTART 0x300000 -#define BCCK_CCA_COUNT 0x080000 -#define BCCK_CS_LIM 0x070000 -#define BCCK_BIST_MODE 0x80000000 -#define BCCK_CCAMASK 0x40000000 -#define BCCK_TX_DAC_PHASE 0x4 -#define BCCK_RX_ADC_PHASE 0x20000000 -#define BCCKR_CP_MODE 0x0100 -#define BCCK_TXDC_OFFSET 0xf0 -#define BCCK_RXDC_OFFSET 0xf -#define BCCK_CCA_MODE 0xc000 -#define BCCK_FALSECS_LIM 0x3f00 -#define BCCK_CS_RATIO 0xc00000 -#define BCCK_CORGBIT_SEL 0x300000 -#define BCCK_PD_LIM 0x0f0000 -#define BCCK_NEWCCA 0x80000000 -#define BCCK_RXHP_OF_IG 0x8000 -#define BCCK_RXIG 0x7f00 -#define BCCK_LNA_POLARITY 0x800000 -#define BCCK_RX1ST_BAIN 0x7f0000 -#define BCCK_RF_EXTEND 0x20000000 -#define BCCK_RXAGC_SATLEVEL 0x1f000000 -#define BCCK_RXAGC_SATCOUNT 0xe0 -#define BCCKRXRFSETTLE 0x1f -#define BCCK_FIXED_RXAGC 0x8000 -#define BCCK_ANTENNA_POLARITY 0x2000 -#define BCCK_TXFILTER_TYPE 0x0c00 -#define BCCK_RXAGC_REPORTTYPE 0x0300 -#define BCCK_RXDAGC_EN 0x80000000 -#define BCCK_RXDAGC_PERIOD 0x20000000 -#define BCCK_RXDAGC_SATLEVEL 0x1f000000 -#define BCCK_TIMING_RECOVERY 0x800000 -#define BCCK_TXC0 0x3f0000 -#define BCCK_TXC1 0x3f000000 -#define BCCK_TXC2 0x3f -#define BCCK_TXC3 0x3f00 -#define BCCK_TXC4 0x3f0000 -#define BCCK_TXC5 0x3f000000 -#define BCCK_TXC6 0x3f -#define BCCK_TXC7 0x3f00 -#define BCCK_DEBUGPORT 0xff0000 -#define BCCK_DAC_DEBUG 0x0f000000 -#define BCCK_FALSEALARM_ENABLE 0x8000 -#define BCCK_FALSEALARM_READ 0x4000 -#define BCCK_TRSSI 0x7f -#define BCCK_RXAGC_REPORT 0xfe -#define BCCK_RXREPORT_ANTSEL 0x80000000 -#define BCCK_RXREPORT_MFOFF 0x40000000 -#define BCCK_RXREPORT_SQLOSS 0x20000000 -#define BCCK_RXREPORT_PKTLOSS 0x10000000 -#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 -#define BCCK_RXREPORT_RATEERROR 0x04000000 -#define BCCK_RXREPORT_RXRATE 0x03000000 -#define BCCK_RXFA_COUNTER_LOWER 0xff -#define BCCK_RXFA_COUNTER_UPPER 0xff000000 -#define BCCK_RXHPAGC_START 0xe000 -#define BCCK_RXHPAGC_FINAL 0x1c00 -#define BCCK_RXFALSEALARM_ENABLE 0x8000 -#define BCCK_FACOUNTER_FREEZE 0x4000 -#define BCCK_TXPATH_SEL 0x10000000 -#define BCCK_DEFAULT_RXPATH 0xc000000 -#define BCCK_OPTION_RXPATH 0x3000000 - -#define BNUM_OFSTF 0x3 -#define BSHIFT_L 0xc0 -#define BGI_TH 0xc -#define BRXPATH_A 0x1 -#define BRXPATH_B 0x2 -#define BRXPATH_C 0x4 -#define BRXPATH_D 0x8 -#define BTXPATH_A 0x1 -#define BTXPATH_B 0x2 -#define BTXPATH_C 0x4 -#define BTXPATH_D 0x8 -#define BTRSSI_FREQ 0x200 -#define BADC_BACKOFF 0x3000 -#define BDFIR_BACKOFF 0xc000 -#define BTRSSI_LATCH_PHASE 0x10000 -#define BRX_LDC_OFFSET 0xff -#define BRX_QDC_OFFSET 0xff00 -#define BRX_DFIR_MODE 0x1800000 -#define BRX_DCNF_TYPE 0xe000000 -#define BRXIQIMB_A 0x3ff -#define BRXIQIMB_B 0xfc00 -#define BRXIQIMB_C 0x3f0000 -#define BRXIQIMB_D 0xffc00000 -#define BDC_DC_NOTCH 0x60000 -#define BRXNB_NOTCH 0x1f000000 -#define BPD_TH 0xf -#define BPD_TH_OPT2 0xc000 -#define BPWED_TH 0x700 -#define BIFMF_WIN_L 0x800 -#define BPD_OPTION 0x1000 -#define BMF_WIN_L 0xe000 -#define BBW_SEARCH_L 0x30000 -#define BWIN_ENH_L 0xc0000 -#define BBW_TH 0x700000 -#define BED_TH2 0x3800000 -#define BBW_OPTION 0x4000000 -#define BRADIO_TH 0x18000000 -#define BWINDOW_L 0xe0000000 -#define BSBD_OPTION 0x1 -#define BFRAME_TH 0x1c -#define BFS_OPTION 0x60 -#define BDC_SLOPE_CHECK 0x80 -#define BFGUARD_COUNTER_DC_L 0xe00 -#define BFRAME_WEIGHT_SHORT 0x7000 -#define BSUB_TUNE 0xe00000 -#define BFRAME_DC_LENGTH 0xe000000 -#define BSBD_START_OFFSET 0x30000000 -#define BFRAME_TH_2 0x7 -#define BFRAME_GI2_TH 0x38 -#define BGI2_SYNC_EN 0x40 -#define BSARCH_SHORT_EARLY 0x300 -#define BSARCH_SHORT_LATE 0xc00 -#define BSARCH_GI2_LATE 0x70000 -#define BCFOANTSUM 0x1 -#define BCFOACC 0x2 -#define BCFOSTARTOFFSET 0xc -#define BCFOLOOPBACK 0x70 -#define BCFOSUMWEIGHT 0x80 -#define BDAGCENABLE 0x10000 -#define BTXIQIMB_A 0x3ff -#define BTXIQIMB_b 0xfc00 -#define BTXIQIMB_C 0x3f0000 -#define BTXIQIMB_D 0xffc00000 -#define BTXIDCOFFSET 0xff -#define BTXIQDCOFFSET 0xff00 -#define BTXDFIRMODE 0x10000 -#define BTXPESUDO_NOISEON 0x4000000 -#define BTXPESUDO_NOISE_A 0xff -#define BTXPESUDO_NOISE_B 0xff00 -#define BTXPESUDO_NOISE_C 0xff0000 -#define BTXPESUDO_NOISE_D 0xff000000 -#define BCCA_DROPOPTION 0x20000 -#define BCCA_DROPTHRES 0xfff00000 -#define BEDCCA_H 0xf -#define BEDCCA_L 0xf0 -#define BLAMBDA_ED 0x300 -#define BRX_INITIALGAIN 0x7f -#define BRX_ANTDIV_EN 0x80 -#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 -#define BRX_HIGHPOWER_FLOW 0x8000 -#define BRX_AGC_FREEZE_THRES 0xc0000 -#define BRX_FREEZESTEP_AGC1 0x300000 -#define BRX_FREEZESTEP_AGC2 0xc00000 -#define BRX_FREEZESTEP_AGC3 0x3000000 -#define BRX_FREEZESTEP_AGC0 0xc000000 -#define BRXRSSI_CMP_EN 0x10000000 -#define BRXQUICK_AGCEN 0x20000000 -#define BRXAGC_FREEZE_THRES_MODE 0x40000000 -#define BRX_OVERFLOW_CHECKTYPE 0x80000000 -#define BRX_AGCSHIFT 0x7f -#define BTRSW_TRI_ONLY 0x80 -#define BPOWER_THRES 0x300 -#define BRXAGC_EN 0x1 -#define BRXAGC_TOGETHER_EN 0x2 -#define BRXAGC_MIN 0x4 -#define BRXHP_INI 0x7 -#define BRXHP_TRLNA 0x70 -#define BRXHP_RSSI 0x700 -#define BRXHP_BBP1 0x7000 -#define BRXHP_BBP2 0x70000 -#define BRXHP_BBP3 0x700000 -#define BRSSI_H 0x7f0000 -#define BRSSI_GEN 0x7f000000 -#define BRXSETTLE_TRSW 0x7 -#define BRXSETTLE_LNA 0x38 -#define BRXSETTLE_RSSI 0x1c0 -#define BRXSETTLE_BBP 0xe00 -#define BRXSETTLE_RXHP 0x7000 -#define BRXSETTLE_ANTSW_RSSI 0x38000 -#define BRXSETTLE_ANTSW 0xc0000 -#define BRXPROCESS_TIME_DAGC 0x300000 -#define BRXSETTLE_HSSI 0x400000 -#define BRXPROCESS_TIME_BBPPW 0x800000 -#define BRXANTENNA_POWER_SHIFT 0x3000000 -#define BRSSI_TABLE_SELECT 0xc000000 -#define BRXHP_FINAL 0x7000000 -#define BRXHPSETTLE_BBP 0x7 -#define BRXHTSETTLE_HSSI 0x8 -#define BRXHTSETTLE_RXHP 0x70 -#define BRXHTSETTLE_BBPPW 0x80 -#define BRXHTSETTLE_IDLE 0x300 -#define BRXHTSETTLE_RESERVED 0x1c00 -#define BRXHT_RXHP_EN 0x8000 -#define BRXAGC_FREEZE_THRES 0x30000 -#define BRXAGC_TOGETHEREN 0x40000 -#define BRXHTAGC_MIN 0x80000 -#define BRXHTAGC_EN 0x100000 -#define BRXHTDAGC_EN 0x200000 -#define BRXHT_RXHP_BBP 0x1c00000 -#define BRXHT_RXHP_FINAL 0xe0000000 -#define BRXPW_RADIO_TH 0x3 -#define BRXPW_RADIO_EN 0x4 -#define BRXMF_HOLD 0x3800 -#define BRXPD_DELAY_TH1 0x38 -#define BRXPD_DELAY_TH2 0x1c0 -#define BRXPD_DC_COUNT_MAX 0x600 -#define BRXPD_DELAY_TH 0x8000 -#define BRXPROCESS_DELAY 0xf0000 -#define BRXSEARCHRANGE_GI2_EARLY 0x700000 -#define BRXFRAME_FUARD_COUNTER_L 0x3800000 -#define BRXSGI_GUARD_L 0xc000000 -#define BRXSGI_SEARCH_L 0x30000000 -#define BRXSGI_TH 0xc0000000 -#define BDFSCNT0 0xff -#define BDFSCNT1 0xff00 -#define BDFSFLAG 0xf0000 -#define BMF_WEIGHT_SUM 0x300000 -#define BMINIDX_TH 0x7f000000 -#define BDAFORMAT 0x40000 -#define BTXCH_EMU_ENABLE 0x01000000 -#define BTRSW_ISOLATION_A 0x7f -#define BTRSW_ISOLATION_B 0x7f00 -#define BTRSW_ISOLATION_C 0x7f0000 -#define BTRSW_ISOLATION_D 0x7f000000 -#define BEXT_LNA_GAIN 0x7c00 - -#define BSTBC_EN 0x4 -#define BANTENNA_MAPPING 0x10 -#define BNSS 0x20 -#define BCFO_ANTSUM_ID 0x200 -#define BPHY_COUNTER_RESET 0x8000000 -#define BCFO_REPORT_GET 0x4000000 -#define BOFDM_CONTINUE_TX 0x10000000 -#define BOFDM_SINGLE_CARRIER 0x20000000 -#define BOFDM_SINGLE_TONE 0x40000000 -#define BHT_DETECT 0x100 -#define BCFOEN 0x10000 -#define BCFOVALUE 0xfff00000 -#define BSIGTONE_RE 0x3f -#define BSIGTONE_IM 0x7f00 -#define BCOUNTER_CCA 0xffff -#define BCOUNTER_PARITYFAIL 0xffff0000 -#define BCOUNTER_RATEILLEGAL 0xffff -#define BCOUNTER_CRC8FAIL 0xffff0000 -#define BCOUNTER_MCSNOSUPPORT 0xffff -#define BCOUNTER_FASTSYNC 0xffff -#define BSHORTCFO 0xfff -#define BSHORTCFOT_LENGTH 12 -#define BSHORTCFOF_LENGTH 11 -#define BLONGCFO 0x7ff -#define BLONGCFOT_LENGTH 11 -#define BLONGCFOF_LENGTH 11 -#define BTAILCFO 0x1fff -#define BTAILCFOT_LENGTH 13 -#define BTAILCFOF_LENGTH 12 -#define BNOISE_EN_PWDB 0xffff -#define BCC_POWER_DB 0xffff0000 -#define BMOISE_PWDB 0xffff -#define BPOWERMEAST_LENGTH 10 -#define BPOWERMEASF_LENGTH 3 -#define BRX_HT_BW 0x1 -#define BRXSC 0x6 -#define BRX_HT 0x8 -#define BNB_INTF_DET_ON 0x1 -#define BINTF_WIN_LEN_CFG 0x30 -#define BNB_INTF_TH_CFG 0x1c0 -#define BRFGAIN 0x3f -#define BTABLESEL 0x40 -#define BTRSW 0x80 -#define BRXSNR_A 0xff -#define BRXSNR_B 0xff00 -#define BRXSNR_C 0xff0000 -#define BRXSNR_D 0xff000000 -#define BSNR_EVMT_LENGTH 8 -#define BSNR_EVMF_LENGTH 1 -#define BCSI1ST 0xff -#define BCSI2ND 0xff00 -#define BRXEVM1ST 0xff0000 -#define BRXEVM2ND 0xff000000 -#define BSIGEVM 0xff -#define BPWDB 0xff00 -#define BSGIEN 0x10000 - -#define BSFACTOR_QMA1 0xf -#define BSFACTOR_QMA2 0xf0 -#define BSFACTOR_QMA3 0xf00 -#define BSFACTOR_QMA4 0xf000 -#define BSFACTOR_QMA5 0xf0000 -#define BSFACTOR_QMA6 0xf0000 -#define BSFACTOR_QMA7 0xf00000 -#define BSFACTOR_QMA8 0xf000000 -#define BSFACTOR_QMA9 0xf0000000 -#define BCSI_SCHEME 0x100000 - -#define BNOISE_LVL_TOP_SET 0x3 -#define BCHSMOOTH 0x4 -#define BCHSMOOTH_CFG1 0x38 -#define BCHSMOOTH_CFG2 0x1c0 -#define BCHSMOOTH_CFG3 0xe00 -#define BCHSMOOTH_CFG4 0x7000 -#define BMRCMODE 0x800000 -#define BTHEVMCFG 0x7000000 - -#define BLOOP_FIT_TYPE 0x1 -#define BUPD_CFO 0x40 -#define BUPD_CFO_OFFDATA 0x80 -#define BADV_UPD_CFO 0x100 -#define BADV_TIME_CTRL 0x800 -#define BUPD_CLKO 0x1000 -#define BFC 0x6000 -#define BTRACKING_MODE 0x8000 -#define BPHCMP_ENABLE 0x10000 -#define BUPD_CLKO_LTF 0x20000 -#define BCOM_CH_CFO 0x40000 -#define BCSI_ESTI_MODE 0x80000 -#define BADV_UPD_EQZ 0x100000 -#define BUCHCFG 0x7000000 -#define BUPDEQZ 0x8000000 - -#define BRX_PESUDO_NOISE_ON 0x20000000 -#define BRX_PESUDO_NOISE_A 0xff -#define BRX_PESUDO_NOISE_B 0xff00 -#define BRX_PESUDO_NOISE_C 0xff0000 -#define BRX_PESUDO_NOISE_D 0xff000000 -#define BRX_PESUDO_NOISESTATE_A 0xffff -#define BRX_PESUDO_NOISESTATE_B 0xffff0000 -#define BRX_PESUDO_NOISESTATE_C 0xffff -#define BRX_PESUDO_NOISESTATE_D 0xffff0000 - -#define BZEBRA1_HSSIENABLE 0x8 -#define BZEBRA1_TRXCONTROL 0xc00 -#define BZEBRA1_TRXGAINSETTING 0x07f -#define BZEBRA1_RXCOUNTER 0xc00 -#define BZEBRA1_TXCHANGEPUMP 0x38 -#define BZEBRA1_RXCHANGEPUMP 0x7 -#define BZEBRA1_CHANNEL_NUM 0xf80 -#define BZEBRA1_TXLPFBW 0x400 -#define BZEBRA1_RXLPFBW 0x600 - -#define BRTL8256REG_MODE_CTRL1 0x100 -#define BRTL8256REG_MODE_CTRL0 0x40 -#define BRTL8256REG_TXLPFBW 0x18 -#define BRTL8256REG_RXLPFBW 0x600 - -#define BRTL8258_TXLPFBW 0xc -#define BRTL8258_RXLPFBW 0xc00 -#define BRTL8258_RSSILPFBW 0xc0 - -#define BBYTE0 0x1 -#define BBYTE1 0x2 -#define BBYTE2 0x4 -#define BBYTE3 0x8 -#define BWORD0 0x3 -#define BWORD1 0xc -#define BWORD 0xf - -#define MASKBYTE0 0xff -#define MASKBYTE1 0xff00 -#define MASKBYTE2 0xff0000 -#define MASKBYTE3 0xff000000 -#define MASKHWORD 0xffff0000 -#define MASKLWORD 0x0000ffff -#define MASKDWORD 0xffffffff -#define MASK12BITS 0xfff -#define MASKH4BITS 0xf0000000 -#define MASKOFDM_D 0xffc00000 -#define MASKCCK 0x3f3f3f3f - -#define MASK4BITS 0x0f -#define MASK20BITS 0xfffff -#define RFREG_OFFSET_MASK 0xfffff - -#define BENABLE 0x1 -#define BDISABLE 0x0 - -#define LEFT_ANTENNA 0x0 -#define RIGHT_ANTENNA 0x1 - -#define TCHECK_TXSTATUS 500 -#define TUPDATE_RXCOUNTER 100 - -#define REG_UN_used_register 0x01bf - -/* WOL bit information */ -#define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0) -#define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1) -#define HAL92C_WOL_DISASSOC_EVENT BIT(2) -#define HAL92C_WOL_DEAUTH_EVENT BIT(3) -#define HAL92C_WOL_FW_DISCONNECT_EVENT BIT(4) - -#define WOL_REASON_PTK_UPDATE BIT(0) -#define WOL_REASON_GTK_UPDATE BIT(1) -#define WOL_REASON_DISASSOC BIT(2) -#define WOL_REASON_DEAUTH BIT(3) -#define WOL_REASON_FW_DISCONNECT BIT(4) -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c deleted file mode 100644 index 40893cef7dfe..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.c +++ /dev/null @@ -1,509 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" - -static bool _rtl88e_phy_rf6052_config_parafile(struct ieee80211_hw *hw); - -void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - switch (bandwidth) { - case HT_CHANNEL_WIDTH_20: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff) | BIT(10) | BIT(11)); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - case HT_CHANNEL_WIDTH_20_40: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff) | BIT(10)); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", bandwidth); - break; - } -} - -void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 tx_agc[2] = {0, 0}, tmpval; - bool turbo_scanoff = false; - u8 idx1, idx2; - u8 *ptr; - u8 direction; - u32 pwrtrac_value; - - if (rtlefuse->eeprom_regulatory != 0) - turbo_scanoff = true; - - if (mac->act_scanning == true) { - tx_agc[RF90_PATH_A] = 0x3f3f3f3f; - tx_agc[RF90_PATH_B] = 0x3f3f3f3f; - - if (turbo_scanoff) { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - } - } else { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - - if (rtlefuse->eeprom_regulatory == 0) { - tmpval = - (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + - (rtlphy->mcs_txpwrlevel_origoffset[0][7] << - 8); - tx_agc[RF90_PATH_A] += tmpval; - - tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + - (rtlphy->mcs_txpwrlevel_origoffset[0][15] << - 24); - tx_agc[RF90_PATH_B] += tmpval; - } - } - - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - ptr = (u8 *)(&tx_agc[idx1]); - for (idx2 = 0; idx2 < 4; idx2++) { - if (*ptr > RF6052_MAX_TX_PWR) - *ptr = RF6052_MAX_TX_PWR; - ptr++; - } - } - rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); - if (direction == 1) { - tx_agc[0] += pwrtrac_value; - tx_agc[1] += pwrtrac_value; - } else if (direction == 2) { - tx_agc[0] -= pwrtrac_value; - tx_agc[1] -= pwrtrac_value; - } - tmpval = tx_agc[RF90_PATH_A] & 0xff; - rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_A_CCK1_MCS32); - - tmpval = tx_agc[RF90_PATH_A] >> 8; - - /*tmpval = tmpval & 0xff00ffff;*/ - - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_B_CCK11_A_CCK2_11); - - tmpval = tx_agc[RF90_PATH_B] >> 24; - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_B_CCK11_A_CCK2_11); - - tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; - rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_B_CCK1_55_MCS32); -} - -static void rtl88e_phy_get_power_base(struct ieee80211_hw *hw, - u8 *ppowerlevel_ofdm, - u8 *ppowerlevel_bw20, - u8 *ppowerlevel_bw40, u8 channel, - u32 *ofdmbase, u32 *mcsbase) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 powerbase0, powerbase1; - u8 i, powerlevel[2]; - - for (i = 0; i < 2; i++) { - powerbase0 = ppowerlevel_ofdm[i]; - - powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | - (powerbase0 << 8) | powerbase0; - *(ofdmbase + i) = powerbase0; - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [OFDM power base index rf(%c) = 0x%x]\n", - ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)); - } - - for (i = 0; i < 2; i++) { - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) - powerlevel[i] = ppowerlevel_bw20[i]; - else - powerlevel[i] = ppowerlevel_bw40[i]; - - powerbase1 = powerlevel[i]; - powerbase1 = (powerbase1 << 24) | - (powerbase1 << 16) | (powerbase1 << 8) | powerbase1; - - *(mcsbase + i) = powerbase1; - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [MCS power base index rf(%c) = 0x%x]\n", - ((i == 0) ? 'A' : 'B'), *(mcsbase + i)); - } -} - -static void _rtl88e_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, - u8 channel, u8 index, - u32 *powerbase0, - u32 *powerbase1, - u32 *p_outwriteval) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff; - u32 writeval, customer_limit, rf; - - for (rf = 0; rf < 2; rf++) { - switch (rtlefuse->eeprom_regulatory) { - case 0: - chnlgroup = 0; - - writeval = - rtlphy->mcs_txpwrlevel_origoffset - [chnlgroup][index + (rf ? 8 : 0)] - + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - case 1: - if (rtlphy->pwrgroup_cnt == 1) { - chnlgroup = 0; - } else { - if (channel < 3) - chnlgroup = 0; - else if (channel < 6) - chnlgroup = 1; - else if (channel < 9) - chnlgroup = 2; - else if (channel < 12) - chnlgroup = 3; - else if (channel < 14) - chnlgroup = 4; - else if (channel == 14) - chnlgroup = 5; - } - - writeval = - rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] - [index + (rf ? 8 : 0)] + ((index < 2) ? - powerbase0[rf] : - powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - - break; - case 2: - writeval = - ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Better regulatory, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - case 3: - chnlgroup = 0; - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 40MHz rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), - rtlefuse->pwrgroup_ht40[rf][channel - - 1]); - } else { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 20MHz rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), - rtlefuse->pwrgroup_ht20[rf][channel - - 1]); - } - - if (index < 2) - pwr_diff = - rtlefuse->txpwr_legacyhtdiff[rf][channel-1]; - else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) - pwr_diff = - rtlefuse->txpwr_ht20diff[rf][channel-1]; - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) - customer_pwr_diff = - rtlefuse->pwrgroup_ht40[rf][channel-1]; - else - customer_pwr_diff = - rtlefuse->pwrgroup_ht20[rf][channel-1]; - - if (pwr_diff > customer_pwr_diff) - pwr_diff = 0; - else - pwr_diff = customer_pwr_diff - pwr_diff; - - for (i = 0; i < 4; i++) { - pwr_diff_limit[i] = - (u8)((rtlphy->mcs_txpwrlevel_origoffset - [chnlgroup][index + - (rf ? 8 : 0)] & (0x7f << - (i * 8))) >> (i * 8)); - - if (pwr_diff_limit[i] > pwr_diff) - pwr_diff_limit[i] = pwr_diff; - } - - customer_limit = (pwr_diff_limit[3] << 24) | - (pwr_diff_limit[2] << 16) | - (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer's limit rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), customer_limit); - - writeval = customer_limit + - ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer, writeval rf(%c)= 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - default: - chnlgroup = 0; - writeval = - rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] - [index + (rf ? 8 : 0)] - + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeval rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - } - - if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) - writeval = writeval - 0x06060606; - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_BT2) - writeval = writeval - 0x0c0c0c0c; - *(p_outwriteval + rf) = writeval; - } -} - -static void _rtl88e_write_ofdm_power_reg(struct ieee80211_hw *hw, - u8 index, u32 *value) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 regoffset_a[6] = { - RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, - RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, - RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 - }; - u16 regoffset_b[6] = { - RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, - RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, - RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 - }; - u8 i, rf, pwr_val[4]; - u32 writeval; - u16 regoffset; - - for (rf = 0; rf < 2; rf++) { - writeval = value[rf]; - for (i = 0; i < 4; i++) { - pwr_val[i] = (u8)((writeval & (0x7f << - (i * 8))) >> (i * 8)); - - if (pwr_val[i] > RF6052_MAX_TX_PWR) - pwr_val[i] = RF6052_MAX_TX_PWR; - } - writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | - (pwr_val[1] << 8) | pwr_val[0]; - - if (rf == 0) - regoffset = regoffset_a[index]; - else - regoffset = regoffset_b[index]; - rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Set 0x%x = %08x\n", regoffset, writeval); - } -} - -void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel_ofdm, - u8 *ppowerlevel_bw20, - u8 *ppowerlevel_bw40, u8 channel) -{ - u32 writeval[2], powerbase0[2], powerbase1[2]; - u8 index; - u8 direction; - u32 pwrtrac_value; - - rtl88e_phy_get_power_base(hw, ppowerlevel_ofdm, - ppowerlevel_bw20, ppowerlevel_bw40, - channel, &powerbase0[0], &powerbase1[0]); - - rtl88e_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); - - for (index = 0; index < 6; index++) { - _rtl88e_get_txpower_writeval_by_regulatory(hw, - channel, index, - &powerbase0[0], - &powerbase1[0], - &writeval[0]); - if (direction == 1) { - writeval[0] += pwrtrac_value; - writeval[1] += pwrtrac_value; - } else if (direction == 2) { - writeval[0] -= pwrtrac_value; - writeval[1] -= pwrtrac_value; - } - _rtl88e_write_ofdm_power_reg(hw, index, &writeval[0]); - } -} - -bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - if (rtlphy->rf_type == RF_1T1R) - rtlphy->num_total_rfpath = 1; - else - rtlphy->num_total_rfpath = 2; - - return _rtl88e_phy_rf6052_config_parafile(hw); -} - -static bool _rtl88e_phy_rf6052_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 u4_regvalue = 0; - u8 rfpath; - bool rtstatus = true; - struct bb_reg_def *pphyreg; - - for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { - pphyreg = &rtlphy->phyreg_def[rfpath]; - - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV); - break; - case RF90_PATH_B: - case RF90_PATH_D: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16); - break; - } - - rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, - B3WIREADDREAALENGTH, 0x0); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); - udelay(1); - - switch (rfpath) { - case RF90_PATH_A: - rtstatus = rtl88e_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_B: - rtstatus = rtl88e_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_C: - break; - case RF90_PATH_D: - break; - } - - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - rtl_set_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV, u4_regvalue); - break; - case RF90_PATH_B: - case RF90_PATH_D: - rtl_set_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16, u4_regvalue); - break; - } - - if (rtstatus != true) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio[%d] Fail!!", rfpath); - return false; - } - - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); - return rtstatus; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h b/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h deleted file mode 100644 index 0eca030e3238..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/rf.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_RF_H__ -#define __RTL92C_RF_H__ - -#define RF6052_MAX_TX_PWR 0x3F - -void rtl88e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, - u8 bandwidth); -void rtl88e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -void rtl88e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel_ofdm, - u8 *ppowerlevel_bw20, - u8 *ppowerlevel_bw40, - u8 channel); -bool rtl88e_phy_rf6052_config(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c deleted file mode 100644 index 11344121c55e..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c +++ /dev/null @@ -1,419 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../core.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "hw.h" -#include "sw.h" -#include "trx.h" -#include "led.h" -#include "table.h" - -#include -#include - -static void rtl88e_init_aspm_vars(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - /*close ASPM for AMD defaultly */ - rtlpci->const_amdpci_aspm = 0; - - /* ASPM PS mode. - * 0 - Disable ASPM, - * 1 - Enable ASPM without Clock Req, - * 2 - Enable ASPM with Clock Req, - * 3 - Alwyas Enable ASPM with Clock Req, - * 4 - Always Enable ASPM without Clock Req. - * set defult to RTL8192CE:3 RTL8192E:2 - */ - rtlpci->const_pci_aspm = 3; - - /*Setting for PCI-E device */ - rtlpci->const_devicepci_aspm_setting = 0x03; - - /*Setting for PCI-E bridge */ - rtlpci->const_hostpci_aspm_setting = 0x02; - - /* In Hw/Sw Radio Off situation. - * 0 - Default, - * 1 - From ASPM setting without low Mac Pwr, - * 2 - From ASPM setting with low Mac Pwr, - * 3 - Bus D3 - * set default to RTL8192CE:0 RTL8192SE:2 - */ - rtlpci->const_hwsw_rfoff_d3 = 0; - - /* This setting works for those device with - * backdoor ASPM setting such as EPHY setting. - * 0 - Not support ASPM, - * 1 - Support ASPM, - * 2 - According to chipset. - */ - rtlpci->const_support_pciaspm = 1; -} - -int rtl88e_init_sw_vars(struct ieee80211_hw *hw) -{ - int err = 0; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 tid; - - rtl8188ee_bt_reg_init(hw); - rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; - - rtlpriv->dm.dm_initialgain_enable = 1; - rtlpriv->dm.dm_flag = 0; - rtlpriv->dm.disable_framebursting = 0; - rtlpriv->dm.thermalvalue = 0; - rtlpci->transmit_config = CFENDFORM | BIT(15); - - /* compatible 5G band 88ce just 2.4G band & smsp */ - rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; - rtlpriv->rtlhal.bandset = BAND_ON_2_4G; - rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; - - rtlpci->receive_config = (RCR_APPFCS | - RCR_APP_MIC | - RCR_APP_ICV | - RCR_APP_PHYST_RXFF | - RCR_HTC_LOC_CTRL | - RCR_AMF | - RCR_ACF | - RCR_ADF | - RCR_AICV | - RCR_ACRC32 | - RCR_AB | - RCR_AM | - RCR_APM | - 0); - - rtlpci->irq_mask[0] = - (u32)(IMR_PSTIMEOUT | - IMR_HSISR_IND_ON_INT | - IMR_C2HCMD | - IMR_HIGHDOK | - IMR_MGNTDOK | - IMR_BKDOK | - IMR_BEDOK | - IMR_VIDOK | - IMR_VODOK | - IMR_RDU | - IMR_ROK | - 0); - 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; - rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; - if (rtlpriv->cfg->mod_params->disable_watchdog) - pr_info("watchdog disabled\n"); - if (!rtlpriv->psc.inactiveps) - pr_info("rtl8188ee: Power Save off (module option)\n"); - if (!rtlpriv->psc.fwctrl_lps) - pr_info("rtl8188ee: FW Power Save off (module option)\n"); - rtlpriv->psc.reg_fwctrl_lps = 3; - rtlpriv->psc.reg_max_lps_awakeintvl = 5; - /* for ASPM, you can close aspm through - * set const_support_pciaspm = 0 - */ - rtl88e_init_aspm_vars(hw); - - if (rtlpriv->psc.reg_fwctrl_lps == 1) - rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 2) - rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 3) - rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; - - /* for firmware buf */ - rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); - if (!rtlpriv->rtlhal.pfirmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't alloc buffer for fw.\n"); - return 1; - } - - rtlpriv->cfg->fw_name = "rtlwifi/rtl8188efw.bin"; - rtlpriv->max_fw_size = 0x8000; - pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); - err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, - rtlpriv->io.dev, GFP_KERNEL, hw, - rtl_fw_cb); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to request firmware!\n"); - return 1; - } - - /* for early mode */ - rtlpriv->rtlhal.earlymode_enable = false; - rtlpriv->rtlhal.max_earlymode_num = 10; - for (tid = 0; tid < 8; tid++) - skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); - - /*low power */ - rtlpriv->psc.low_power_enable = false; - if (rtlpriv->psc.low_power_enable) { - init_timer(&rtlpriv->works.fw_clockoff_timer); - setup_timer(&rtlpriv->works.fw_clockoff_timer, - rtl88ee_fw_clk_off_timer_callback, - (unsigned long)hw); - } - - init_timer(&rtlpriv->works.fast_antenna_training_timer); - setup_timer(&rtlpriv->works.fast_antenna_training_timer, - rtl88e_dm_fast_antenna_training_callback, - (unsigned long)hw); - return err; -} - -void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->rtlhal.pfirmware) { - vfree(rtlpriv->rtlhal.pfirmware); - rtlpriv->rtlhal.pfirmware = NULL; - } - - if (rtlpriv->psc.low_power_enable) - del_timer_sync(&rtlpriv->works.fw_clockoff_timer); - - del_timer_sync(&rtlpriv->works.fast_antenna_training_timer); -} - -/* get bt coexist status */ -bool rtl88e_get_btc_status(void) -{ - return false; -} - -static struct rtl_hal_ops rtl8188ee_hal_ops = { - .init_sw_vars = rtl88e_init_sw_vars, - .deinit_sw_vars = rtl88e_deinit_sw_vars, - .read_eeprom_info = rtl88ee_read_eeprom_info, - .interrupt_recognized = rtl88ee_interrupt_recognized,/*need check*/ - .hw_init = rtl88ee_hw_init, - .hw_disable = rtl88ee_card_disable, - .hw_suspend = rtl88ee_suspend, - .hw_resume = rtl88ee_resume, - .enable_interrupt = rtl88ee_enable_interrupt, - .disable_interrupt = rtl88ee_disable_interrupt, - .set_network_type = rtl88ee_set_network_type, - .set_chk_bssid = rtl88ee_set_check_bssid, - .set_qos = rtl88ee_set_qos, - .set_bcn_reg = rtl88ee_set_beacon_related_registers, - .set_bcn_intv = rtl88ee_set_beacon_interval, - .update_interrupt_mask = rtl88ee_update_interrupt_mask, - .get_hw_reg = rtl88ee_get_hw_reg, - .set_hw_reg = rtl88ee_set_hw_reg, - .update_rate_tbl = rtl88ee_update_hal_rate_tbl, - .fill_tx_desc = rtl88ee_tx_fill_desc, - .fill_tx_cmddesc = rtl88ee_tx_fill_cmddesc, - .query_rx_desc = rtl88ee_rx_query_desc, - .set_channel_access = rtl88ee_update_channel_access_setting, - .radio_onoff_checking = rtl88ee_gpio_radio_on_off_checking, - .set_bw_mode = rtl88e_phy_set_bw_mode, - .switch_channel = rtl88e_phy_sw_chnl, - .dm_watchdog = rtl88e_dm_watchdog, - .scan_operation_backup = rtl88e_phy_scan_operation_backup, - .set_rf_power_state = rtl88e_phy_set_rf_power_state, - .led_control = rtl88ee_led_control, - .set_desc = rtl88ee_set_desc, - .get_desc = rtl88ee_get_desc, - .is_tx_desc_closed = rtl88ee_is_tx_desc_closed, - .tx_polling = rtl88ee_tx_polling, - .enable_hw_sec = rtl88ee_enable_hw_security_config, - .set_key = rtl88ee_set_key, - .init_sw_leds = rtl88ee_init_sw_leds, - .get_bbreg = rtl88e_phy_query_bb_reg, - .set_bbreg = rtl88e_phy_set_bb_reg, - .get_rfreg = rtl88e_phy_query_rf_reg, - .set_rfreg = rtl88e_phy_set_rf_reg, - .get_btc_status = rtl88e_get_btc_status, - .rx_command_packet = rtl88ee_rx_command_packet, - -}; - -static struct rtl_mod_params rtl88ee_mod_params = { - .sw_crypto = false, - .inactiveps = false, - .swctrl_lps = false, - .fwctrl_lps = false, - .msi_support = true, - .debug = DBG_EMERG, -}; - -static struct rtl_hal_cfg rtl88ee_hal_cfg = { - .bar_id = 2, - .write_readback = true, - .name = "rtl88e_pci", - .fw_name = "rtlwifi/rtl8188efw.bin", - .ops = &rtl8188ee_hal_ops, - .mod_params = &rtl88ee_mod_params, - - .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, - .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, - .maps[SYS_CLK] = REG_SYS_CLKR, - .maps[MAC_RCR_AM] = AM, - .maps[MAC_RCR_AB] = AB, - .maps[MAC_RCR_ACRC32] = ACRC32, - .maps[MAC_RCR_ACF] = ACF, - .maps[MAC_RCR_AAP] = AAP, - .maps[MAC_HIMR] = REG_HIMR, - .maps[MAC_HIMRE] = REG_HIMRE, - .maps[MAC_HSISR] = REG_HSISR, - - .maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS, - - .maps[EFUSE_TEST] = REG_EFUSE_TEST, - .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_CLK] = 0, - .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_PWC_EV12V] = PWC_EV12V, - .maps[EFUSE_FEN_ELDR] = FEN_ELDR, - .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, - .maps[EFUSE_ANA8M] = ANA8M, - .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, - .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, - .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, - .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, - - .maps[RWCAM] = REG_CAMCMD, - .maps[WCAMI] = REG_CAMWRITE, - .maps[RCAMO] = REG_CAMREAD, - .maps[CAMDBG] = REG_CAMDBG, - .maps[SECR] = REG_SECCFG, - .maps[SEC_CAM_NONE] = CAM_NONE, - .maps[SEC_CAM_WEP40] = CAM_WEP40, - .maps[SEC_CAM_TKIP] = CAM_TKIP, - .maps[SEC_CAM_AES] = CAM_AES, - .maps[SEC_CAM_WEP104] = CAM_WEP104, - - .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, - .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, - .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, - .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, - .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, - .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, -/* .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, */ /*need check*/ - .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, - .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, - .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, - .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, - .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, - .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, - .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, -/* .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,*/ -/* .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,*/ - - .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, - .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, - .maps[RTL_IMR_BCNINT] = IMR_BCNDMAINT0, - .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, - .maps[RTL_IMR_RDU] = IMR_RDU, - .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, - .maps[RTL_IMR_BDOK] = IMR_BCNDOK0, - .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, - .maps[RTL_IMR_TBDER] = IMR_TBDER, - .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, - .maps[RTL_IMR_TBDOK] = IMR_TBDOK, - .maps[RTL_IMR_BKDOK] = IMR_BKDOK, - .maps[RTL_IMR_BEDOK] = IMR_BEDOK, - .maps[RTL_IMR_VIDOK] = IMR_VIDOK, - .maps[RTL_IMR_VODOK] = IMR_VODOK, - .maps[RTL_IMR_ROK] = IMR_ROK, - .maps[RTL_IMR_HSISR_IND] = IMR_HSISR_IND_ON_INT, - .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER), - - .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, -}; - -static struct pci_device_id rtl88ee_pci_ids[] = { - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8179, rtl88ee_hal_cfg)}, - {}, -}; - -MODULE_DEVICE_TABLE(pci, rtl88ee_pci_ids); - -MODULE_AUTHOR("zhiyuan_yang "); -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_AUTHOR("Larry Finger "); -MODULE_LICENSE("GPL"); -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(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); -module_param_named(msi, rtl88ee_mod_params.msi_support, bool, 0444); -module_param_named(disable_watchdog, rtl88ee_mod_params.disable_watchdog, - bool, 0444); -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(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(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); - -static struct pci_driver rtl88ee_driver = { - .name = KBUILD_MODNAME, - .id_table = rtl88ee_pci_ids, - .probe = rtl_pci_probe, - .remove = rtl_pci_disconnect, - .driver.pm = &rtlwifi_pm_ops, -}; - -module_pci_driver(rtl88ee_driver); diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h deleted file mode 100644 index 22398c3753a6..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.h +++ /dev/null @@ -1,34 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CE_SW_H__ -#define __RTL92CE_SW_H__ - -int rtl88e_init_sw_vars(struct ieee80211_hw *hw); -void rtl88e_deinit_sw_vars(struct ieee80211_hw *hw); -bool rtl88e_get_btc_status(void); - - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.c b/drivers/net/wireless/rtlwifi/rtl8188ee/table.c deleted file mode 100644 index 68bcb7fe6a65..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/table.c +++ /dev/null @@ -1,639 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ - -#include "table.h" -u32 RTL8188EEPHY_REG_1TARRAY[] = { - 0x800, 0x80040000, - 0x804, 0x00000003, - 0x808, 0x0000FC00, - 0x80C, 0x0000000A, - 0x810, 0x10001331, - 0x814, 0x020C3D10, - 0x818, 0x02200385, - 0x81C, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390204, - 0x828, 0x00000000, - 0x82C, 0x00000000, - 0x830, 0x00000000, - 0x834, 0x00000000, - 0x838, 0x00000000, - 0x83C, 0x00000000, - 0x840, 0x00010000, - 0x844, 0x00000000, - 0x848, 0x00000000, - 0x84C, 0x00000000, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x569A11A9, - 0x85C, 0x01000014, - 0x860, 0x66F60110, - 0x864, 0x061F0649, - 0x868, 0x00000000, - 0x86C, 0x27272700, - 0x870, 0x07000760, - 0x874, 0x25004000, - 0x878, 0x00000808, - 0x87C, 0x00000000, - 0x880, 0xB0000C1C, - 0x884, 0x00000001, - 0x888, 0x00000000, - 0x88C, 0xCCC000C0, - 0x890, 0x00000800, - 0x894, 0xFFFFFFFE, - 0x898, 0x40302010, - 0x89C, 0x00706050, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90C, 0x81121111, - 0x910, 0x00000002, - 0x914, 0x00000201, - 0xA00, 0x00D047C8, - 0xA04, 0x80FF000C, - 0xA08, 0x8C838300, - 0xA0C, 0x2E7F120F, - 0xA10, 0x9500BB78, - 0xA14, 0x1114D028, - 0xA18, 0x00881117, - 0xA1C, 0x89140F00, - 0xA20, 0x1A1B0000, - 0xA24, 0x090E1317, - 0xA28, 0x00000204, - 0xA2C, 0x00D30000, - 0xA70, 0x101FBF00, - 0xA74, 0x00000007, - 0xA78, 0x00000900, - 0xA7C, 0x225B0606, - 0xA80, 0x218075B1, - 0xB2C, 0x80000000, - 0xC00, 0x48071D40, - 0xC04, 0x03A05611, - 0xC08, 0x000000E4, - 0xC0C, 0x6C6C6C6C, - 0xC10, 0x08800000, - 0xC14, 0x40000100, - 0xC18, 0x08800000, - 0xC1C, 0x40000100, - 0xC20, 0x00000000, - 0xC24, 0x00000000, - 0xC28, 0x00000000, - 0xC2C, 0x00000000, - 0xC30, 0x69E9AC47, - 0xC34, 0x469652AF, - 0xC38, 0x49795994, - 0xC3C, 0x0A97971C, - 0xC40, 0x1F7C403F, - 0xC44, 0x000100B7, - 0xC48, 0xEC020107, - 0xC4C, 0x007F037F, - 0xC50, 0x69553420, - 0xC54, 0x43BC0094, - 0xC58, 0x00013169, - 0xC5C, 0x00250492, - 0xC60, 0x00000000, - 0xC64, 0x7112848B, - 0xC68, 0x47C00BFF, - 0xC6C, 0x00000036, - 0xC70, 0x2C7F000D, - 0xC74, 0x020610DB, - 0xC78, 0x0000001F, - 0xC7C, 0x00B91612, - 0xC80, 0x390000E4, - 0xC84, 0x20F60000, - 0xC88, 0x40000100, - 0xC8C, 0x20200000, - 0xC90, 0x00091521, - 0xC94, 0x00000000, - 0xC98, 0x00121820, - 0xC9C, 0x00007F7F, - 0xCA0, 0x00000000, - 0xCA4, 0x000300A0, - 0xCA8, 0x00000000, - 0xCAC, 0x00000000, - 0xCB0, 0x00000000, - 0xCB4, 0x00000000, - 0xCB8, 0x00000000, - 0xCBC, 0x28000000, - 0xCC0, 0x00000000, - 0xCC4, 0x00000000, - 0xCC8, 0x00000000, - 0xCCC, 0x00000000, - 0xCD0, 0x00000000, - 0xCD4, 0x00000000, - 0xCD8, 0x64B22427, - 0xCDC, 0x00766932, - 0xCE0, 0x00222222, - 0xCE4, 0x00000000, - 0xCE8, 0x37644302, - 0xCEC, 0x2F97D40C, - 0xD00, 0x00000740, - 0xD04, 0x00020401, - 0xD08, 0x0000907F, - 0xD0C, 0x20010201, - 0xD10, 0xA0633333, - 0xD14, 0x3333BC43, - 0xD18, 0x7A8F5B6F, - 0xD2C, 0xCC979975, - 0xD30, 0x00000000, - 0xD34, 0x80608000, - 0xD38, 0x00000000, - 0xD3C, 0x00127353, - 0xD40, 0x00000000, - 0xD44, 0x00000000, - 0xD48, 0x00000000, - 0xD4C, 0x00000000, - 0xD50, 0x6437140A, - 0xD54, 0x00000000, - 0xD58, 0x00000282, - 0xD5C, 0x30032064, - 0xD60, 0x4653DE68, - 0xD64, 0x04518A3C, - 0xD68, 0x00002101, - 0xD6C, 0x2A201C16, - 0xD70, 0x1812362E, - 0xD74, 0x322C2220, - 0xD78, 0x000E3C24, - 0xE00, 0x2D2D2D2D, - 0xE04, 0x2D2D2D2D, - 0xE08, 0x0390272D, - 0xE10, 0x2D2D2D2D, - 0xE14, 0x2D2D2D2D, - 0xE18, 0x2D2D2D2D, - 0xE1C, 0x2D2D2D2D, - 0xE28, 0x00000000, - 0xE30, 0x1000DC1F, - 0xE34, 0x10008C1F, - 0xE38, 0x02140102, - 0xE3C, 0x681604C2, - 0xE40, 0x01007C00, - 0xE44, 0x01004800, - 0xE48, 0xFB000000, - 0xE4C, 0x000028D1, - 0xE50, 0x1000DC1F, - 0xE54, 0x10008C1F, - 0xE58, 0x02140102, - 0xE5C, 0x28160D05, - 0xE60, 0x00000008, - 0xE68, 0x001B25A4, - 0xE6C, 0x00C00014, - 0xE70, 0x00C00014, - 0xE74, 0x01000014, - 0xE78, 0x01000014, - 0xE7C, 0x01000014, - 0xE80, 0x01000014, - 0xE84, 0x00C00014, - 0xE88, 0x01000014, - 0xE8C, 0x00C00014, - 0xED0, 0x00C00014, - 0xED4, 0x00C00014, - 0xED8, 0x00C00014, - 0xEDC, 0x00000014, - 0xEE0, 0x00000014, - 0xEEC, 0x01C00014, - 0xF14, 0x00000003, - 0xF4C, 0x00000000, - 0xF00, 0x00000300, - -}; - -u32 RTL8188EEPHY_REG_ARRAY_PG[] = { - 0xE00, 0xFFFFFFFF, 0x06070809, - 0xE04, 0xFFFFFFFF, 0x02020405, - 0xE08, 0x0000FF00, 0x00000006, - 0x86C, 0xFFFFFF00, 0x00020400, - 0xE10, 0xFFFFFFFF, 0x08090A0B, - 0xE14, 0xFFFFFFFF, 0x01030607, - 0xE18, 0xFFFFFFFF, 0x08090A0B, - 0xE1C, 0xFFFFFFFF, 0x01030607, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x02020202, - 0xE04, 0xFFFFFFFF, 0x00020202, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x04040404, - 0xE14, 0xFFFFFFFF, 0x00020404, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x02020202, - 0xE04, 0xFFFFFFFF, 0x00020202, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x04040404, - 0xE14, 0xFFFFFFFF, 0x00020404, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x02020202, - 0xE04, 0xFFFFFFFF, 0x00020202, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x04040404, - 0xE14, 0xFFFFFFFF, 0x00020404, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - 0xE00, 0xFFFFFFFF, 0x00000000, - 0xE04, 0xFFFFFFFF, 0x00000000, - 0xE08, 0x0000FF00, 0x00000000, - 0x86C, 0xFFFFFF00, 0x00000000, - 0xE10, 0xFFFFFFFF, 0x00000000, - 0xE14, 0xFFFFFFFF, 0x00000000, - 0xE18, 0xFFFFFFFF, 0x00000000, - 0xE1C, 0xFFFFFFFF, 0x00000000, - -}; - -u32 RTL8188EE_RADIOA_1TARRAY[] = { - 0x000, 0x00030000, - 0x008, 0x00084000, - 0x018, 0x00000407, - 0x019, 0x00000012, - 0x01E, 0x00080009, - 0x01F, 0x00000880, - 0x02F, 0x0001A060, - 0x03F, 0x00000000, - 0x042, 0x000060C0, - 0x057, 0x000D0000, - 0x058, 0x000BE180, - 0x067, 0x00001552, - 0x083, 0x00000000, - 0x0B0, 0x000FF8FC, - 0x0B1, 0x00054400, - 0x0B2, 0x000CCC19, - 0x0B4, 0x00043003, - 0x0B6, 0x0004953E, - 0x0B7, 0x0001C718, - 0x0B8, 0x000060FF, - 0x0B9, 0x00080001, - 0x0BA, 0x00040000, - 0x0BB, 0x00000400, - 0x0BF, 0x000C0000, - 0x0C2, 0x00002400, - 0x0C3, 0x00000009, - 0x0C4, 0x00040C91, - 0x0C5, 0x00099999, - 0x0C6, 0x000000A3, - 0x0C7, 0x00088820, - 0x0C8, 0x00076C06, - 0x0C9, 0x00000000, - 0x0CA, 0x00080000, - 0x0DF, 0x00000180, - 0x0EF, 0x000001A0, - 0x051, 0x0006B27D, - 0x052, 0x0007E49D, - 0x053, 0x00000073, - 0x056, 0x00051FF3, - 0x035, 0x00000086, - 0x035, 0x00000186, - 0x035, 0x00000286, - 0x036, 0x00001C25, - 0x036, 0x00009C25, - 0x036, 0x00011C25, - 0x036, 0x00019C25, - 0x0B6, 0x00048538, - 0x018, 0x00000C07, - 0x05A, 0x0004BD00, - 0x019, 0x000739D0, - 0x034, 0x0000ADF3, - 0x034, 0x00009DF0, - 0x034, 0x00008DED, - 0x034, 0x00007DEA, - 0x034, 0x00006DE7, - 0x034, 0x000054EE, - 0x034, 0x000044EB, - 0x034, 0x000034E8, - 0x034, 0x0000246B, - 0x034, 0x00001468, - 0x034, 0x0000006D, - 0x000, 0x00030159, - 0x084, 0x00068200, - 0x086, 0x000000CE, - 0x087, 0x00048A00, - 0x08E, 0x00065540, - 0x08F, 0x00088000, - 0x0EF, 0x000020A0, - 0x03B, 0x000F02B0, - 0x03B, 0x000EF7B0, - 0x03B, 0x000D4FB0, - 0x03B, 0x000CF060, - 0x03B, 0x000B0090, - 0x03B, 0x000A0080, - 0x03B, 0x00090080, - 0x03B, 0x0008F780, - 0x03B, 0x000722B0, - 0x03B, 0x0006F7B0, - 0x03B, 0x00054FB0, - 0x03B, 0x0004F060, - 0x03B, 0x00030090, - 0x03B, 0x00020080, - 0x03B, 0x00010080, - 0x03B, 0x0000F780, - 0x0EF, 0x000000A0, - 0x000, 0x00010159, - 0x018, 0x0000F407, - 0xFFE, 0x00000000, - 0xFFE, 0x00000000, - 0x01F, 0x00080003, - 0xFFE, 0x00000000, - 0xFFE, 0x00000000, - 0x01E, 0x00000001, - 0x01F, 0x00080000, - 0x000, 0x00033E60, - -}; - -u32 RTL8188EEMAC_1T_ARRAY[] = { - 0x026, 0x00000041, - 0x027, 0x00000035, - 0x428, 0x0000000A, - 0x429, 0x00000010, - 0x430, 0x00000000, - 0x431, 0x00000001, - 0x432, 0x00000002, - 0x433, 0x00000004, - 0x434, 0x00000005, - 0x435, 0x00000006, - 0x436, 0x00000007, - 0x437, 0x00000008, - 0x438, 0x00000000, - 0x439, 0x00000000, - 0x43A, 0x00000001, - 0x43B, 0x00000002, - 0x43C, 0x00000004, - 0x43D, 0x00000005, - 0x43E, 0x00000006, - 0x43F, 0x00000007, - 0x440, 0x0000005D, - 0x441, 0x00000001, - 0x442, 0x00000000, - 0x444, 0x00000015, - 0x445, 0x000000F0, - 0x446, 0x0000000F, - 0x447, 0x00000000, - 0x458, 0x00000041, - 0x459, 0x000000A8, - 0x45A, 0x00000072, - 0x45B, 0x000000B9, - 0x460, 0x00000066, - 0x461, 0x00000066, - 0x480, 0x00000008, - 0x4C8, 0x000000FF, - 0x4C9, 0x00000008, - 0x4CC, 0x000000FF, - 0x4CD, 0x000000FF, - 0x4CE, 0x00000001, - 0x4D3, 0x00000001, - 0x500, 0x00000026, - 0x501, 0x000000A2, - 0x502, 0x0000002F, - 0x503, 0x00000000, - 0x504, 0x00000028, - 0x505, 0x000000A3, - 0x506, 0x0000005E, - 0x507, 0x00000000, - 0x508, 0x0000002B, - 0x509, 0x000000A4, - 0x50A, 0x0000005E, - 0x50B, 0x00000000, - 0x50C, 0x0000004F, - 0x50D, 0x000000A4, - 0x50E, 0x00000000, - 0x50F, 0x00000000, - 0x512, 0x0000001C, - 0x514, 0x0000000A, - 0x516, 0x0000000A, - 0x525, 0x0000004F, - 0x550, 0x00000010, - 0x551, 0x00000010, - 0x559, 0x00000002, - 0x55D, 0x000000FF, - 0x605, 0x00000030, - 0x608, 0x0000000E, - 0x609, 0x0000002A, - 0x620, 0x000000FF, - 0x621, 0x000000FF, - 0x622, 0x000000FF, - 0x623, 0x000000FF, - 0x624, 0x000000FF, - 0x625, 0x000000FF, - 0x626, 0x000000FF, - 0x627, 0x000000FF, - 0x652, 0x00000020, - 0x63C, 0x0000000A, - 0x63D, 0x0000000A, - 0x63E, 0x0000000E, - 0x63F, 0x0000000E, - 0x640, 0x00000040, - 0x66E, 0x00000005, - 0x700, 0x00000021, - 0x701, 0x00000043, - 0x702, 0x00000065, - 0x703, 0x00000087, - 0x708, 0x00000021, - 0x709, 0x00000043, - 0x70A, 0x00000065, - 0x70B, 0x00000087, - -}; - -u32 RTL8188EEAGCTAB_1TARRAY[] = { - 0xC78, 0xFB000001, - 0xC78, 0xFB010001, - 0xC78, 0xFB020001, - 0xC78, 0xFB030001, - 0xC78, 0xFB040001, - 0xC78, 0xFB050001, - 0xC78, 0xFA060001, - 0xC78, 0xF9070001, - 0xC78, 0xF8080001, - 0xC78, 0xF7090001, - 0xC78, 0xF60A0001, - 0xC78, 0xF50B0001, - 0xC78, 0xF40C0001, - 0xC78, 0xF30D0001, - 0xC78, 0xF20E0001, - 0xC78, 0xF10F0001, - 0xC78, 0xF0100001, - 0xC78, 0xEF110001, - 0xC78, 0xEE120001, - 0xC78, 0xED130001, - 0xC78, 0xEC140001, - 0xC78, 0xEB150001, - 0xC78, 0xEA160001, - 0xC78, 0xE9170001, - 0xC78, 0xE8180001, - 0xC78, 0xE7190001, - 0xC78, 0xE61A0001, - 0xC78, 0xE51B0001, - 0xC78, 0xE41C0001, - 0xC78, 0xE31D0001, - 0xC78, 0xE21E0001, - 0xC78, 0xE11F0001, - 0xC78, 0x8A200001, - 0xC78, 0x89210001, - 0xC78, 0x88220001, - 0xC78, 0x87230001, - 0xC78, 0x86240001, - 0xC78, 0x85250001, - 0xC78, 0x84260001, - 0xC78, 0x83270001, - 0xC78, 0x82280001, - 0xC78, 0x6B290001, - 0xC78, 0x6A2A0001, - 0xC78, 0x692B0001, - 0xC78, 0x682C0001, - 0xC78, 0x672D0001, - 0xC78, 0x662E0001, - 0xC78, 0x652F0001, - 0xC78, 0x64300001, - 0xC78, 0x63310001, - 0xC78, 0x62320001, - 0xC78, 0x61330001, - 0xC78, 0x46340001, - 0xC78, 0x45350001, - 0xC78, 0x44360001, - 0xC78, 0x43370001, - 0xC78, 0x42380001, - 0xC78, 0x41390001, - 0xC78, 0x403A0001, - 0xC78, 0x403B0001, - 0xC78, 0x403C0001, - 0xC78, 0x403D0001, - 0xC78, 0x403E0001, - 0xC78, 0x403F0001, - 0xC78, 0xFB400001, - 0xC78, 0xFB410001, - 0xC78, 0xFB420001, - 0xC78, 0xFB430001, - 0xC78, 0xFB440001, - 0xC78, 0xFB450001, - 0xC78, 0xFB460001, - 0xC78, 0xFB470001, - 0xC78, 0xFB480001, - 0xC78, 0xFA490001, - 0xC78, 0xF94A0001, - 0xC78, 0xF84B0001, - 0xC78, 0xF74C0001, - 0xC78, 0xF64D0001, - 0xC78, 0xF54E0001, - 0xC78, 0xF44F0001, - 0xC78, 0xF3500001, - 0xC78, 0xF2510001, - 0xC78, 0xF1520001, - 0xC78, 0xF0530001, - 0xC78, 0xEF540001, - 0xC78, 0xEE550001, - 0xC78, 0xED560001, - 0xC78, 0xEC570001, - 0xC78, 0xEB580001, - 0xC78, 0xEA590001, - 0xC78, 0xE95A0001, - 0xC78, 0xE85B0001, - 0xC78, 0xE75C0001, - 0xC78, 0xE65D0001, - 0xC78, 0xE55E0001, - 0xC78, 0xE45F0001, - 0xC78, 0xE3600001, - 0xC78, 0xE2610001, - 0xC78, 0xC3620001, - 0xC78, 0xC2630001, - 0xC78, 0xC1640001, - 0xC78, 0x8B650001, - 0xC78, 0x8A660001, - 0xC78, 0x89670001, - 0xC78, 0x88680001, - 0xC78, 0x87690001, - 0xC78, 0x866A0001, - 0xC78, 0x856B0001, - 0xC78, 0x846C0001, - 0xC78, 0x676D0001, - 0xC78, 0x666E0001, - 0xC78, 0x656F0001, - 0xC78, 0x64700001, - 0xC78, 0x63710001, - 0xC78, 0x62720001, - 0xC78, 0x61730001, - 0xC78, 0x60740001, - 0xC78, 0x46750001, - 0xC78, 0x45760001, - 0xC78, 0x44770001, - 0xC78, 0x43780001, - 0xC78, 0x42790001, - 0xC78, 0x417A0001, - 0xC78, 0x407B0001, - 0xC78, 0x407C0001, - 0xC78, 0x407D0001, - 0xC78, 0x407E0001, - 0xC78, 0x407F0001, - -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/table.h b/drivers/net/wireless/rtlwifi/rtl8188ee/table.h deleted file mode 100644 index 403c4ddd236f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/table.h +++ /dev/null @@ -1,43 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CE_TABLE__H_ -#define __RTL92CE_TABLE__H_ - -#include -#define RTL8188EEPHY_REG_1TARRAYLEN 382 -extern u32 RTL8188EEPHY_REG_1TARRAY[]; -#define RTL8188EEPHY_REG_ARRAY_PGLEN 264 -extern u32 RTL8188EEPHY_REG_ARRAY_PG[]; -#define RTL8188EE_RADIOA_1TARRAYLEN 190 -extern u32 RTL8188EE_RADIOA_1TARRAY[]; -#define RTL8188EEMAC_1T_ARRAYLEN 180 -extern u32 RTL8188EEMAC_1T_ARRAY[]; -#define RTL8188EEAGCTAB_1TARRAYLEN 256 -extern u32 RTL8188EEAGCTAB_1TARRAY[]; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c deleted file mode 100644 index 791efbe6b18c..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c +++ /dev/null @@ -1,858 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../stats.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "trx.h" -#include "led.h" -#include "dm.h" -#include "phy.h" - -static u8 _rtl88ee_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) -{ - __le16 fc = rtl_get_fc(skb); - - if (unlikely(ieee80211_is_beacon(fc))) - return QSLT_BEACON; - if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) - return QSLT_MGNT; - - return skb->priority; -} - -static void _rtl88ee_query_rxphystatus(struct ieee80211_hw *hw, - struct rtl_stats *pstatus, u8 *pdesc, - struct rx_fwinfo_88e *p_drvinfo, - bool bpacket_match_bssid, - bool bpacket_toself, bool packet_beacon) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); - struct phy_sts_cck_8192s_t *cck_buf; - struct phy_status_rpt *phystrpt = - (struct phy_status_rpt *)p_drvinfo; - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - char rx_pwr_all = 0, rx_pwr[4]; - u8 rf_rx_num = 0, evm, pwdb_all; - u8 i, max_spatial_stream; - u32 rssi, total_rssi = 0; - bool is_cck = pstatus->is_cck; - u8 lan_idx, vga_idx; - - /* Record it for next packet processing */ - pstatus->packet_matchbssid = bpacket_match_bssid; - pstatus->packet_toself = bpacket_toself; - pstatus->packet_beacon = packet_beacon; - pstatus->rx_mimo_signalquality[0] = -1; - pstatus->rx_mimo_signalquality[1] = -1; - - if (is_cck) { - u8 cck_highpwr; - u8 cck_agc_rpt; - /* CCK Driver info Structure is not the same as OFDM packet. */ - cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; - cck_agc_rpt = cck_buf->cck_agc_rpt; - - /* (1)Hardware does not provide RSSI for CCK - * (2)PWDB, Average PWDB cacluated by - * hardware (for rate adaptive) - */ - if (ppsc->rfpwr_state == ERFON) - cck_highpwr = - (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, - BIT(9)); - else - cck_highpwr = false; - - lan_idx = ((cck_agc_rpt & 0xE0) >> 5); - vga_idx = (cck_agc_rpt & 0x1f); - switch (lan_idx) { - case 7: - if (vga_idx <= 27) - /*VGA_idx = 27~2*/ - rx_pwr_all = -100 + 2*(27-vga_idx); - else - rx_pwr_all = -100; - break; - case 6: - /*VGA_idx = 2~0*/ - rx_pwr_all = -48 + 2*(2-vga_idx); - break; - case 5: - /*VGA_idx = 7~5*/ - rx_pwr_all = -42 + 2*(7-vga_idx); - break; - case 4: - /*VGA_idx = 7~4*/ - rx_pwr_all = -36 + 2*(7-vga_idx); - break; - case 3: - /*VGA_idx = 7~0*/ - rx_pwr_all = -24 + 2*(7-vga_idx); - break; - case 2: - if (cck_highpwr) - /*VGA_idx = 5~0*/ - rx_pwr_all = -12 + 2*(5-vga_idx); - else - rx_pwr_all = -6 + 2*(5-vga_idx); - break; - case 1: - rx_pwr_all = 8-2*vga_idx; - break; - case 0: - rx_pwr_all = 14-2*vga_idx; - break; - default: - break; - } - rx_pwr_all += 6; - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - /* CCK gain is smaller than OFDM/MCS gain, */ - /* so we add gain diff by experiences, the val is 6 */ - pwdb_all += 6; - if (pwdb_all > 100) - pwdb_all = 100; - /* modify the offset to make the same - * gain index with OFDM. - */ - if (pwdb_all > 34 && pwdb_all <= 42) - pwdb_all -= 2; - else if (pwdb_all > 26 && pwdb_all <= 34) - pwdb_all -= 6; - else if (pwdb_all > 14 && pwdb_all <= 26) - pwdb_all -= 8; - else if (pwdb_all > 4 && pwdb_all <= 14) - pwdb_all -= 4; - if (!cck_highpwr) { - if (pwdb_all >= 80) - pwdb_all = ((pwdb_all-80)<<1) + - ((pwdb_all-80)>>1) + 80; - else if ((pwdb_all <= 78) && (pwdb_all >= 20)) - pwdb_all += 3; - if (pwdb_all > 100) - pwdb_all = 100; - } - - pstatus->rx_pwdb_all = pwdb_all; - pstatus->recvsignalpower = rx_pwr_all; - - /* (3) Get Signal Quality (EVM) */ - if (bpacket_match_bssid) { - u8 sq; - - if (pstatus->rx_pwdb_all > 40) - sq = 100; - else { - sq = cck_buf->sq_rpt; - if (sq > 64) - sq = 0; - else if (sq < 20) - sq = 100; - else - sq = ((64 - sq) * 100) / 44; - } - - pstatus->signalquality = sq; - pstatus->rx_mimo_signalquality[0] = sq; - pstatus->rx_mimo_signalquality[1] = -1; - } - } else { - rtlpriv->dm.rfpath_rxenable[0] = - rtlpriv->dm.rfpath_rxenable[1] = true; - - /* (1)Get RSSI for HT rate */ - for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { - /* we will judge RF RX path now. */ - if (rtlpriv->dm.rfpath_rxenable[i]) - rf_rx_num++; - - rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & - 0x3f) * 2) - 110; - - /* Translate DBM to percentage. */ - rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); - total_rssi += rssi; - - /* Get Rx snr value in DB */ - rtlpriv->stats.rx_snr_db[i] = - (long)(p_drvinfo->rxsnr[i] / 2); - - /* Record Signal Strength for next packet */ - if (bpacket_match_bssid) - pstatus->rx_mimo_signalstrength[i] = (u8)rssi; - } - - /* (2)PWDB, Average PWDB cacluated by - * hardware (for rate adaptive) - */ - rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; - - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - pstatus->rx_pwdb_all = pwdb_all; - pstatus->rxpower = rx_pwr_all; - pstatus->recvsignalpower = rx_pwr_all; - - /* (3)EVM of HT rate */ - if (pstatus->is_ht && pstatus->rate >= DESC92C_RATEMCS8 && - pstatus->rate <= DESC92C_RATEMCS15) - max_spatial_stream = 2; - else - max_spatial_stream = 1; - - for (i = 0; i < max_spatial_stream; i++) { - evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]); - - if (bpacket_match_bssid) { - /* Fill value in RFD, Get the first - * spatial stream onlyi - */ - if (i == 0) - pstatus->signalquality = - (u8)(evm & 0xff); - pstatus->rx_mimo_signalquality[i] = - (u8)(evm & 0xff); - } - } - } - - /* UI BSS List signal strength(in percentage), - * make it good looking, from 0~100. - */ - if (is_cck) - pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, - pwdb_all)); - else if (rf_rx_num != 0) - pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, - total_rssi /= rf_rx_num)); - /*HW antenna diversity*/ - rtldm->fat_table.antsel_rx_keep_0 = phystrpt->ant_sel; - rtldm->fat_table.antsel_rx_keep_1 = phystrpt->ant_sel_b; - rtldm->fat_table.antsel_rx_keep_2 = phystrpt->antsel_rx_keep_2; -} - -static void _rtl88ee_smart_antenna(struct ieee80211_hw *hw, - struct rtl_stats *pstatus) -{ - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 antsel_tr_mux; - struct fast_ant_training *pfat_table = &rtldm->fat_table; - - if (rtlefuse->antenna_div_type == CG_TRX_SMART_ANTDIV) { - if (pfat_table->fat_state == FAT_TRAINING_STATE) { - if (pstatus->packet_toself) { - antsel_tr_mux = - (pfat_table->antsel_rx_keep_2 << 2) | - (pfat_table->antsel_rx_keep_1 << 1) | - pfat_table->antsel_rx_keep_0; - pfat_table->ant_sum[antsel_tr_mux] += - pstatus->rx_pwdb_all; - pfat_table->ant_cnt[antsel_tr_mux]++; - } - } - } else if ((rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) || - (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV)) { - if (pstatus->packet_toself || pstatus->packet_matchbssid) { - antsel_tr_mux = (pfat_table->antsel_rx_keep_2 << 2) | - (pfat_table->antsel_rx_keep_1 << 1) | - pfat_table->antsel_rx_keep_0; - rtl88e_dm_ant_sel_statistics(hw, antsel_tr_mux, 0, - pstatus->rx_pwdb_all); - } - - } -} - -static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct rtl_stats *pstatus, - u8 *pdesc, - struct rx_fwinfo_88e *p_drvinfo) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct ieee80211_hdr *hdr; - u8 *tmp_buf; - u8 *praddr; - u8 *psaddr; - __le16 fc; - bool packet_matchbssid, packet_toself, packet_beacon; - - tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; - - hdr = (struct ieee80211_hdr *)tmp_buf; - fc = hdr->frame_control; - praddr = hdr->addr1; - psaddr = ieee80211_get_SA(hdr); - memcpy(pstatus->psaddr, psaddr, ETH_ALEN); - - packet_matchbssid = ((!ieee80211_is_ctl(fc)) && - (ether_addr_equal(mac->bssid, ieee80211_has_tods(fc) ? - hdr->addr1 : ieee80211_has_fromds(fc) ? - hdr->addr2 : hdr->addr3)) && - (!pstatus->hwerror) && - (!pstatus->crc) && (!pstatus->icv)); - - packet_toself = packet_matchbssid && - (ether_addr_equal(praddr, rtlefuse->dev_addr)); - - if (ieee80211_is_beacon(hdr->frame_control)) - packet_beacon = true; - else - packet_beacon = false; - - _rtl88ee_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo, - packet_matchbssid, packet_toself, - packet_beacon); - _rtl88ee_smart_antenna(hw, pstatus); - rtl_process_phyinfo(hw, tmp_buf, pstatus); -} - -static void _rtl88ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, - u8 *virtualaddress) -{ - u32 dwtmp = 0; - memset(virtualaddress, 0, 8); - - SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); - if (ptcb_desc->empkt_num == 1) { - dwtmp = ptcb_desc->empkt_len[0]; - } else { - dwtmp = ptcb_desc->empkt_len[0]; - dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; - dwtmp += ptcb_desc->empkt_len[1]; - } - SET_EARLYMODE_LEN0(virtualaddress, dwtmp); - - if (ptcb_desc->empkt_num <= 3) { - dwtmp = ptcb_desc->empkt_len[2]; - } else { - dwtmp = ptcb_desc->empkt_len[2]; - dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; - dwtmp += ptcb_desc->empkt_len[3]; - } - SET_EARLYMODE_LEN1(virtualaddress, dwtmp); - if (ptcb_desc->empkt_num <= 5) { - dwtmp = ptcb_desc->empkt_len[4]; - } else { - dwtmp = ptcb_desc->empkt_len[4]; - dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; - dwtmp += ptcb_desc->empkt_len[5]; - } - SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF); - SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4); - if (ptcb_desc->empkt_num <= 7) { - dwtmp = ptcb_desc->empkt_len[6]; - } else { - dwtmp = ptcb_desc->empkt_len[6]; - dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; - dwtmp += ptcb_desc->empkt_len[7]; - } - SET_EARLYMODE_LEN3(virtualaddress, dwtmp); - if (ptcb_desc->empkt_num <= 9) { - dwtmp = ptcb_desc->empkt_len[8]; - } else { - dwtmp = ptcb_desc->empkt_len[8]; - dwtmp += ((dwtmp%4) ? (4-dwtmp%4) : 0)+4; - dwtmp += ptcb_desc->empkt_len[9]; - } - SET_EARLYMODE_LEN4(virtualaddress, dwtmp); -} - -bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *status, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rx_fwinfo_88e *p_drvinfo; - struct ieee80211_hdr *hdr; - - u32 phystatus = GET_RX_DESC_PHYST(pdesc); - status->packet_report_type = (u8)GET_RX_STATUS_DESC_RPT_SEL(pdesc); - if (status->packet_report_type == TX_REPORT2) - status->length = (u16)GET_RX_RPT2_DESC_PKT_LEN(pdesc); - else - status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); - status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * - RX_DRV_INFO_SIZE_UNIT; - status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03); - status->icv = (u16)GET_RX_DESC_ICV(pdesc); - status->crc = (u16)GET_RX_DESC_CRC32(pdesc); - status->hwerror = (status->crc | status->icv); - status->decrypted = !GET_RX_DESC_SWDEC(pdesc); - status->rate = (u8)GET_RX_DESC_RXMCS(pdesc); - status->shortpreamble = (u16)GET_RX_DESC_SPLCP(pdesc); - status->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); - status->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1) && - (GET_RX_DESC_FAGGR(pdesc) == 1)); - if (status->packet_report_type == NORMAL_RX) - status->timestamp_low = GET_RX_DESC_TSFL(pdesc); - status->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); - status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); - - status->is_cck = RTL8188_RX_HAL_IS_CCK_RATE(status->rate); - - status->macid = GET_RX_DESC_MACID(pdesc); - if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(2); - else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(1); - else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) - status->wake_match = BIT(0); - else - status->wake_match = 0; - if (status->wake_match) - RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, - "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n", - status->wake_match); - rx_status->freq = hw->conf.chandef.chan->center_freq; - rx_status->band = hw->conf.chandef.chan->band; - - hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size - + status->rx_bufshift); - - if (status->crc) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - - if (status->rx_is40Mhzpacket) - rx_status->flag |= RX_FLAG_40MHZ; - - if (status->is_ht) - rx_status->flag |= RX_FLAG_HT; - - rx_status->flag |= RX_FLAG_MACTIME_START; - - /* hw will set status->decrypted true, if it finds the - * frame is open data frame or mgmt frame. - * So hw will not decryption robust managment frame - * for IEEE80211w but still set status->decrypted - * true, so here we should set it back to undecrypted - * for IEEE80211w frame, and mac80211 sw will help - * to decrypt it - */ - if (status->decrypted) { - if ((!_ieee80211_is_robust_mgmt_frame(hdr)) && - (ieee80211_has_protected(hdr->frame_control))) - rx_status->flag |= RX_FLAG_DECRYPTED; - else - rx_status->flag &= ~RX_FLAG_DECRYPTED; - } - - /* rate_idx: index of data rate into band's - * supported rates or MCS index if HT rates - * are use (RX_FLAG_HT) - * Notice: this is diff with windows define - */ - rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht, - false, status->rate); - - rx_status->mactime = status->timestamp_low; - if (phystatus == true) { - p_drvinfo = (struct rx_fwinfo_88e *)(skb->data + - status->rx_bufshift); - - _rtl88ee_translate_rx_signal_stuff(hw, - skb, status, pdesc, - p_drvinfo); - } - rx_status->signal = status->recvsignalpower + 10; - if (status->packet_report_type == TX_REPORT2) { - status->macid_valid_entry[0] = - GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); - status->macid_valid_entry[1] = - GET_RX_RPT2_DESC_MACID_VALID_2(pdesc); - } - return true; -} - -void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *txbd, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) - -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 *pdesc = (u8 *)pdesc_tx; - u16 seq_number; - __le16 fc = hdr->frame_control; - unsigned int buf_len = 0; - unsigned int skb_len = skb->len; - u8 fw_qsel = _rtl88ee_map_hwqueue_to_fwqueue(skb, hw_queue); - bool firstseg = ((hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); - bool lastseg = ((hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); - dma_addr_t mapping; - u8 bw_40 = 0; - u8 short_gi = 0; - - if (mac->opmode == NL80211_IFTYPE_STATION) { - bw_40 = mac->bw_40; - } else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - if (sta) - bw_40 = sta->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40; - } - seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); - /* reserve 8 byte for AMPDU early mode */ - if (rtlhal->earlymode_enable) { - skb_push(skb, EM_HDR_LEN); - memset(skb->data, 0, EM_HDR_LEN); - } - buf_len = skb->len; - mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_88e)); - if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { - firstseg = true; - lastseg = true; - } - if (firstseg) { - if (rtlhal->earlymode_enable) { - SET_TX_DESC_PKT_OFFSET(pdesc, 1); - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + - EM_HDR_LEN); - if (ptcb_desc->empkt_num) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "Insert 8 byte.pTcb->EMPktNum:%d\n", - ptcb_desc->empkt_num); - _rtl88ee_insert_emcontent(ptcb_desc, - (u8 *)(skb->data)); - } - } else { - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - } - - ptcb_desc->use_driver_rate = true; - SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); - if (ptcb_desc->hw_rate > DESC92C_RATEMCS0) - short_gi = (ptcb_desc->use_shortgi) ? 1 : 0; - else - short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0; - - SET_TX_DESC_DATA_SHORTGI(pdesc, short_gi); - - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - SET_TX_DESC_AGG_ENABLE(pdesc, 1); - SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); - } - SET_TX_DESC_SEQ(pdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && - !ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(pdesc, 0); - SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); - - SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); - SET_TX_DESC_RTS_BW(pdesc, 0); - SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(pdesc, - ((ptcb_desc->rts_rate <= DESC92C_RATE54M) ? - (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : - (ptcb_desc->rts_use_shortgi ? 1 : 0))); - - if (ptcb_desc->tx_enable_sw_calc_duration) - SET_TX_DESC_NAV_USE_HDR(pdesc, 1); - - if (bw_40) { - if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { - SET_TX_DESC_DATA_BW(pdesc, 1); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, - mac->cur_40_prime_sc); - } - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); - } - - SET_TX_DESC_LINIP(pdesc, 0); - SET_TX_DESC_PKT_SIZE(pdesc, (u16)skb_len); - if (sta) { - u8 ampdu_density = sta->ht_cap.ampdu_density; - SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); - } - if (info->control.hw_key) { - struct ieee80211_key_conf *keyconf; - - keyconf = info->control.hw_key; - switch (keyconf->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - case WLAN_CIPHER_SUITE_TKIP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x1); - break; - case WLAN_CIPHER_SUITE_CCMP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x3); - break; - default: - SET_TX_DESC_SEC_TYPE(pdesc, 0x0); - break; - - } - } - - SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); - SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); - SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); - SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ? - 1 : 0); - SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); - - /*SET_TX_DESC_PWR_STATUS(pdesc, pwr_status);*/ - /* Set TxRate and RTSRate in TxDesc */ - /* This prevent Tx initial rate of new-coming packets */ - /* from being overwritten by retried packet rate.*/ - if (!ptcb_desc->use_driver_rate) { - /*SET_TX_DESC_RTS_RATE(pdesc, 0x08); */ - /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */ - } - if (ieee80211_is_data_qos(fc)) { - if (mac->rdg_en) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "Enable RDG function.\n"); - SET_TX_DESC_RDG_ENABLE(pdesc, 1); - SET_TX_DESC_HTC(pdesc, 1); - } - } - } - - SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); - SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)buf_len); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); - } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); - } - if (ieee80211_is_data_qos(fc)) - SET_TX_DESC_QOS(pdesc, 1); - - if (!ieee80211_is_data_qos(fc)) - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); - if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || - is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { - SET_TX_DESC_BMC(pdesc, 1); - } - - rtl88e_dm_set_tx_ant_by_tx_info(hw, pdesc, ptcb_desc->mac_id); - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); -} - -void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc, bool firstseg, - bool lastseg, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 fw_queue = QSLT_BEACON; - - dma_addr_t mapping = pci_map_single(rtlpci->pdev, - skb->data, skb->len, - PCI_DMA_TODEVICE); - - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - __le16 fc = hdr->frame_control; - - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); - - if (firstseg) - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - - SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); - - SET_TX_DESC_SEQ(pdesc, 0); - - SET_TX_DESC_LINIP(pdesc, 0); - - SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); - - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); - - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - SET_TX_DESC_RATE_ID(pdesc, 7); - SET_TX_DESC_MACID(pdesc, 0); - - SET_TX_DESC_OWN(pdesc, 1); - - SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); - - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - SET_TX_DESC_OFFSET(pdesc, 0x20); - - SET_TX_DESC_USE_RATE(pdesc, 1); - - if (!ieee80211_is_data_qos(fc)) - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C Tx Cmd Content\n", - pdesc, TX_DESC_SIZE); -} - -void rtl88ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, - bool istx, u8 desc_name, u8 *val) -{ - if (istx == true) { - switch (desc_name) { - case HW_DESC_OWN: - SET_TX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_TX_NEXTDESC_ADDR: - SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *)val); - break; - default: - RT_ASSERT(false, "ERR txdesc :%d not process\n", - desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_RXOWN: - SET_RX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_RXBUFF_ADDR: - SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *)val); - break; - case HW_DESC_RXPKT_LEN: - SET_RX_DESC_PKT_LEN(pdesc, *(u32 *)val); - break; - case HW_DESC_RXERO: - SET_RX_DESC_EOR(pdesc, 1); - break; - default: - RT_ASSERT(false, "ERR rxdesc :%d not process\n", - desc_name); - break; - } - } -} - -u32 rtl88ee_get_desc(u8 *pdesc, bool istx, u8 desc_name) -{ - u32 ret = 0; - - if (istx == true) { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_TX_DESC_OWN(pdesc); - break; - case HW_DESC_TXBUFF_ADDR: - ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc); - break; - default: - RT_ASSERT(false, "ERR txdesc :%d not process\n", - desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_RX_DESC_OWN(pdesc); - break; - case HW_DESC_RXPKT_LEN: - ret = GET_RX_DESC_PKT_LEN(pdesc); - break; - case HW_DESC_RXBUFF_ADDR: - ret = GET_RX_DESC_BUFF_ADDR(pdesc); - break; - default: - RT_ASSERT(false, "ERR rxdesc :%d not process\n", - desc_name); - break; - } - } - return ret; -} - -bool rtl88ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; - u8 *entry = (u8 *)(&ring->desc[ring->idx]); - u8 own = (u8)rtl88ee_get_desc(entry, true, HW_DESC_OWN); - - /*beacon packet will only use the first - *descriptor defautly,and the own may not - *be cleared by the hardware - */ - if (own) - return false; - return true; -} - -void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (hw_queue == BEACON_QUEUE) { - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); - } else { - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, - BIT(0) << (hw_queue)); - } -} - -u32 rtl88ee_rx_command_packet(struct ieee80211_hw *hw, - struct rtl_stats status, - struct sk_buff *skb) -{ - return 0; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h deleted file mode 100644 index eab5ae0eb46c..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h +++ /dev/null @@ -1,796 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2013 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CE_TRX_H__ -#define __RTL92CE_TRX_H__ - -#define TX_DESC_SIZE 64 -#define TX_DESC_AGGR_SUBFRAME_SIZE 32 - -#define RX_DESC_SIZE 32 -#define RX_DRV_INFO_SIZE_UNIT 8 - -#define TX_DESC_NEXT_DESC_OFFSET 40 -#define USB_HWDESC_HEADER_LEN 32 -#define CRCLENGTH 4 - -#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) -#define SET_TX_DESC_OFFSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) -#define SET_TX_DESC_BMC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) -#define SET_TX_DESC_HTC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) -#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) -#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) -#define SET_TX_DESC_LINIP(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) -#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) -#define SET_TX_DESC_GF(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) -#define SET_TX_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) - -#define GET_TX_DESC_PKT_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 0, 16) -#define GET_TX_DESC_OFFSET(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 16, 8) -#define GET_TX_DESC_BMC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 24, 1) -#define GET_TX_DESC_HTC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 25, 1) -#define GET_TX_DESC_LAST_SEG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 26, 1) -#define GET_TX_DESC_FIRST_SEG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 27, 1) -#define GET_TX_DESC_LINIP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 28, 1) -#define GET_TX_DESC_NO_ACM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 29, 1) -#define GET_TX_DESC_GF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 30, 1) -#define GET_TX_DESC_OWN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 31, 1) - -#define SET_TX_DESC_MACID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 6, __val) -#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) -#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) -#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) -#define SET_TX_DESC_PIFS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) -#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val) -#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val) -#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) -#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) -#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 26, 5, __val) -#define SET_TX_DESC_PADDING_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val) - -#define GET_TX_DESC_MACID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) -#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 5, 1) -#define GET_TX_DESC_AGG_BREAK(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 6, 1) -#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 7, 1) -#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 8, 5) -#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) -#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) -#define GET_TX_DESC_PIFS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) -#define GET_TX_DESC_RATE_ID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) -#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) -#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) -#define GET_TX_DESC_SEC_TYPE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 22, 2) -#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 24, 8) - -#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val) -#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val) -#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val) -#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val) -#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val) -#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val) -#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) -#define SET_TX_DESC_RAW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) -#define SET_TX_DESC_CCX(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) -#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) -#define SET_TX_DESC_BT_INT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val) -#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val) -#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val) -#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val) -#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val) -#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val) - -#define GET_TX_DESC_RTS_RC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 0, 6) -#define GET_TX_DESC_DATA_RC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 6, 6) -#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 14, 2) -#define GET_TX_DESC_MORE_FRAG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 17, 1) -#define GET_TX_DESC_RAW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 18, 1) -#define GET_TX_DESC_CCX(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 19, 1) -#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 20, 3) -#define GET_TX_DESC_ANTSEL_A(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 24, 1) -#define GET_TX_DESC_ANTSEL_B(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 25, 1) -#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 26, 2) -#define GET_TX_DESC_TX_ANTL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 28, 2) -#define GET_TX_DESC_TX_ANT_HT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 30, 2) - -#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val) -#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val) -#define SET_TX_DESC_SEQ(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val) -#define SET_TX_DESC_CPU_HANDLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 1, __val) -#define SET_TX_DESC_TAG1(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 29, 1, __val) -#define SET_TX_DESC_TRIGGER_INT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 30, 1, __val) -#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 31, 1, __val) - -#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 0, 8) -#define GET_TX_DESC_TAIL_PAGE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 8, 8) -#define GET_TX_DESC_SEQ(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 16, 12) - -#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val) -#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val) -#define SET_TX_DESC_QOS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val) -#define SET_TX_DESC_HWSEQ_SSN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val) -#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val) -#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val) -#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val) -#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val) -#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val) -#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val) -#define SET_TX_DESC_PORT_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val) -#define SET_TX_DESC_PWR_STATUS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 15, 3, __val) -#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val) -#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val) -#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val) -#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val) -#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val) -#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val) -#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val) -#define SET_TX_DESC_RTS_BW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val) -#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val) -#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val) - -#define GET_TX_DESC_RTS_RATE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 0, 5) -#define GET_TX_DESC_AP_DCFE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 5, 1) -#define GET_TX_DESC_QOS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 6, 1) -#define GET_TX_DESC_HWSEQ_EN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 7, 1) -#define GET_TX_DESC_USE_RATE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 8, 1) -#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 9, 1) -#define GET_TX_DESC_DISABLE_FB(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 10, 1) -#define GET_TX_DESC_CTS2SELF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 11, 1) -#define GET_TX_DESC_RTS_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 12, 1) -#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 13, 1) -#define GET_TX_DESC_PORT_ID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 14, 1) -#define GET_TX_DESC_WAIT_DCTS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 18, 1) -#define GET_TX_DESC_CTS2AP_EN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 19, 1) -#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 20, 2) -#define GET_TX_DESC_TX_STBC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 22, 2) -#define GET_TX_DESC_DATA_SHORT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 24, 1) -#define GET_TX_DESC_DATA_BW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 25, 1) -#define GET_TX_DESC_RTS_SHORT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 26, 1) -#define GET_TX_DESC_RTS_BW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 27, 1) -#define GET_TX_DESC_RTS_SC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 28, 2) -#define GET_TX_DESC_RTS_STBC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 30, 2) - -#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val) -#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val) -#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) -#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val) -#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) -#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val) -#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val) -#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val) - -#define GET_TX_DESC_TX_RATE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 0, 6) -#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 6, 1) -#define GET_TX_DESC_CCX_TAG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 7, 1) -#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 8, 5) -#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 13, 4) -#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 17, 1) -#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 18, 6) -#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 24, 8) - -#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val) -#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val) -#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val) -#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val) -#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val) -#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val) -#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val) -#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val) - -#define GET_TX_DESC_TXAGC_A(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 0, 5) -#define GET_TX_DESC_TXAGC_B(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 5, 5) -#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 10, 1) -#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 11, 5) -#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 16, 4) -#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 20, 4) -#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 24, 4) -#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 28, 4) - -#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) -#define SET_TX_DESC_SW_OFFSET30(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 8, __val) -#define SET_TX_DESC_SW_OFFSET31(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val) -#define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 29, 1, __val) -#define SET_TX_DESC_NULL_0(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val) -#define SET_TX_DESC_NULL_1(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 30, 1, __val) - -#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) - -#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val) -#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val) - -#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+32, 0, 32) -#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+36, 0, 32) - -#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) -#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val) - -#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+40, 0, 32) -#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+44, 0, 32) - -#define GET_RX_DESC_PKT_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 0, 14) -#define GET_RX_DESC_CRC32(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 14, 1) -#define GET_RX_DESC_ICV(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 15, 1) -#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 16, 4) -#define GET_RX_DESC_SECURITY(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 20, 3) -#define GET_RX_DESC_QOS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 23, 1) -#define GET_RX_DESC_SHIFT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 24, 2) -#define GET_RX_DESC_PHYST(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 26, 1) -#define GET_RX_DESC_SWDEC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 27, 1) -#define GET_RX_DESC_LS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 28, 1) -#define GET_RX_DESC_FS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 29, 1) -#define GET_RX_DESC_EOR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 30, 1) -#define GET_RX_DESC_OWN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 31, 1) - -#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) -#define SET_RX_DESC_EOR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) -#define SET_RX_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) - -#define GET_RX_DESC_MACID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 0, 6) -#define GET_RX_DESC_PAGGR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) -#define GET_RX_DESC_FAGGR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) -#define GET_RX_DESC_A1_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) -#define GET_RX_DESC_A2_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 20, 4) -#define GET_RX_DESC_PAM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) -#define GET_RX_DESC_PWR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) -#define GET_RX_DESC_MD(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) -#define GET_RX_DESC_MF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) -#define GET_RX_DESC_TYPE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) -#define GET_RX_DESC_MC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) -#define GET_RX_DESC_BC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) -#define GET_RX_DESC_SEQ(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) -#define GET_RX_DESC_FRAG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) - -#define GET_RX_DESC_RXMCS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 0, 6) -#define GET_RX_DESC_RXHT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 6, 1) -#define GET_RX_STATUS_DESC_RX_GF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 7, 1) -#define GET_RX_DESC_SPLCP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 8, 1) -#define GET_RX_DESC_BW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 9, 1) -#define GET_RX_DESC_HTC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) -#define GET_RX_STATUS_DESC_EOSP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 11, 1) -#define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 12, 2) -#define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 14, 2) - -#define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 29, 1) -#define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 30, 1) -#define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 31, 1) - -#define GET_RX_DESC_IV1(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 0, 32) -#define GET_RX_DESC_TSFL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) - -#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) -#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) - -#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) -#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) - -/* TX report 2 format in Rx desc*/ - -#define GET_RX_RPT2_DESC_PKT_LEN(__status) \ - LE_BITS_TO_4BYTE(__status, 0, 9) -#define GET_RX_RPT2_DESC_MACID_VALID_1(__status) \ - LE_BITS_TO_4BYTE(__status+16, 0, 32) -#define GET_RX_RPT2_DESC_MACID_VALID_2(__status) \ - LE_BITS_TO_4BYTE(__status+20, 0, 32) - -#define SET_EARLYMODE_PKTNUM(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __value) -#define SET_EARLYMODE_LEN0(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 4, 12, __value) -#define SET_EARLYMODE_LEN1(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 16, 12, __value) -#define SET_EARLYMODE_LEN2_1(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 28, 4, __value) -#define SET_EARLYMODE_LEN2_2(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __value) -#define SET_EARLYMODE_LEN3(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 8, 12, __value) -#define SET_EARLYMODE_LEN4(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __value) - -#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ -do { \ - if (_size > TX_DESC_NEXT_DESC_OFFSET) \ - memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ - else \ - memset(__pdesc, 0, _size); \ -} while (0) - -#define RTL8188_RX_HAL_IS_CCK_RATE(rxmcs)\ - (rxmcs == DESC92C_RATE1M ||\ - rxmcs == DESC92C_RATE2M ||\ - rxmcs == DESC92C_RATE5_5M ||\ - rxmcs == DESC92C_RATE11M) - -#define IS_LITTLE_ENDIAN 1 - -struct phy_rx_agc_info_t { - #if IS_LITTLE_ENDIAN - u8 gain:7, trsw:1; - #else - u8 trsw:1, gain:7; - #endif -}; -struct phy_status_rpt { - struct phy_rx_agc_info_t path_agc[2]; - u8 ch_corr[2]; - u8 cck_sig_qual_ofdm_pwdb_all; - u8 cck_agc_rpt_ofdm_cfosho_a; - u8 cck_rpt_b_ofdm_cfosho_b; - u8 rsvd_1;/* ch_corr_msb; */ - u8 noise_power_db_msb; - u8 path_cfotail[2]; - u8 pcts_mask[2]; - u8 stream_rxevm[2]; - u8 path_rxsnr[2]; - u8 noise_power_db_lsb; - u8 rsvd_2[3]; - u8 stream_csi[2]; - u8 stream_target_csi[2]; - u8 sig_evm; - u8 rsvd_3; -#if IS_LITTLE_ENDIAN - u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ - u8 sgi_en:1; - u8 rxsc:2; - u8 idle_long:1; - u8 r_ant_train_en:1; - u8 ant_sel_b:1; - u8 ant_sel:1; -#else /* _BIG_ENDIAN_ */ - u8 ant_sel:1; - u8 ant_sel_b:1; - u8 r_ant_train_en:1; - u8 idle_long:1; - u8 rxsc:2; - u8 sgi_en:1; - u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ -#endif -} __packed; - -struct rx_fwinfo_88e { - u8 gain_trsw[4]; - u8 pwdb_all; - u8 cfosho[4]; - u8 cfotail[4]; - char rxevm[2]; - char rxsnr[4]; - u8 pdsnr[2]; - u8 csi_current[2]; - u8 csi_target[2]; - u8 sigevm; - u8 max_ex_pwr; - u8 ex_intf_flag:1; - u8 sgi_en:1; - u8 rxsc:2; - u8 reserve:4; -} __packed; - -struct tx_desc_88e { - u32 pktsize:16; - u32 offset:8; - u32 bmc:1; - u32 htc:1; - u32 lastseg:1; - u32 firstseg:1; - u32 linip:1; - u32 noacm:1; - u32 gf:1; - u32 own:1; - - u32 macid:6; - u32 rsvd0:2; - u32 queuesel:5; - u32 rd_nav_ext:1; - u32 lsig_txop_en:1; - u32 pifs:1; - u32 rateid:4; - u32 nav_usehdr:1; - u32 en_descid:1; - u32 sectype:2; - u32 pktoffset:8; - - u32 rts_rc:6; - u32 data_rc:6; - u32 agg_en:1; - u32 rdg_en:1; - u32 bar_retryht:2; - u32 agg_break:1; - u32 morefrag:1; - u32 raw:1; - u32 ccx:1; - u32 ampdudensity:3; - u32 bt_int:1; - u32 ant_sela:1; - u32 ant_selb:1; - u32 txant_cck:2; - u32 txant_l:2; - u32 txant_ht:2; - - u32 nextheadpage:8; - u32 tailpage:8; - u32 seq:12; - u32 cpu_handle:1; - u32 tag1:1; - u32 trigger_int:1; - u32 hwseq_en:1; - - u32 rtsrate:5; - u32 apdcfe:1; - u32 qos:1; - u32 hwseq_ssn:1; - u32 userrate:1; - u32 dis_rtsfb:1; - u32 dis_datafb:1; - u32 cts2self:1; - u32 rts_en:1; - u32 hwrts_en:1; - u32 portid:1; - u32 pwr_status:3; - u32 waitdcts:1; - u32 cts2ap_en:1; - u32 txsc:2; - u32 stbc:2; - u32 txshort:1; - u32 txbw:1; - u32 rtsshort:1; - u32 rtsbw:1; - u32 rtssc:2; - u32 rtsstbc:2; - - u32 txrate:6; - u32 shortgi:1; - u32 ccxt:1; - u32 txrate_fb_lmt:5; - u32 rtsrate_fb_lmt:4; - u32 retrylmt_en:1; - u32 txretrylmt:6; - u32 usb_txaggnum:8; - - u32 txagca:5; - u32 txagcb:5; - u32 usemaxlen:1; - u32 maxaggnum:5; - u32 mcsg1maxlen:4; - u32 mcsg2maxlen:4; - u32 mcsg3maxlen:4; - u32 mcs7sgimaxlen:4; - - u32 txbuffersize:16; - u32 sw_offset30:8; - u32 sw_offset31:4; - u32 rsvd1:1; - u32 antsel_c:1; - u32 null_0:1; - u32 null_1:1; - - u32 txbuffaddr; - u32 txbufferaddr64; - u32 nextdescaddress; - u32 nextdescaddress64; - - u32 reserve_pass_pcie_mm_limit[4]; -} __packed; - -struct rx_desc_88e { - u32 length:14; - u32 crc32:1; - u32 icverror:1; - u32 drv_infosize:4; - u32 security:3; - u32 qos:1; - u32 shift:2; - u32 phystatus:1; - u32 swdec:1; - u32 lastseg:1; - u32 firstseg:1; - u32 eor:1; - u32 own:1; - - u32 macid:6; - u32 tid:4; - u32 hwrsvd:5; - u32 paggr:1; - u32 faggr:1; - u32 a1_fit:4; - u32 a2_fit:4; - u32 pam:1; - u32 pwr:1; - u32 moredata:1; - u32 morefrag:1; - u32 type:2; - u32 mc:1; - u32 bc:1; - - u32 seq:12; - u32 frag:4; - u32 nextpktlen:14; - u32 nextind:1; - u32 rsvd:1; - - u32 rxmcs:6; - u32 rxht:1; - u32 amsdu:1; - u32 splcp:1; - u32 bandwidth:1; - u32 htc:1; - u32 tcpchk_rpt:1; - u32 ipcchk_rpt:1; - u32 tcpchk_valid:1; - u32 hwpcerr:1; - u32 hwpcind:1; - u32 iv0:16; - - u32 iv1; - - u32 tsfl; - - u32 bufferaddress; - u32 bufferaddress64; - -} __packed; - -void rtl88ee_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *txbd, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); -bool rtl88ee_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *status, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb); -void rtl88ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, - bool istx, u8 desc_name, u8 *val); -u32 rtl88ee_get_desc(u8 *pdesc, bool istx, u8 desc_name); -bool rtl88ee_is_tx_desc_closed(struct ieee80211_hw *hw, - u8 hw_queue, u16 index); -void rtl88ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); -void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, - struct sk_buff *skb); -u32 rtl88ee_rx_command_packet(struct ieee80211_hw *hw, - struct rtl_stats status, - struct sk_buff *skb); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/Makefile b/drivers/net/wireless/rtlwifi/rtl8192c/Makefile deleted file mode 100644 index aee42d7ae8a2..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192c/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -rtl8192c-common-objs := \ - main.o \ - dm_common.o \ - fw_common.o \ - phy_common.o - -obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c-common.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c deleted file mode 100644 index 03cbe4cf110b..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ /dev/null @@ -1,1778 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include -#include "dm_common.h" -#include "phy_common.h" -#include "../pci.h" -#include "../base.h" -#include "../core.h" - -#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1) -#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1) -#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1) -#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1) -#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1) -#define BT_MASK 0x00ffffff - -#define RTLPRIV (struct rtl_priv *) -#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ - ((RTLPRIV(_priv))->mac80211.opmode == \ - NL80211_IFTYPE_ADHOC) ? \ - ((RTLPRIV(_priv))->dm.entry_min_undec_sm_pwdb) : \ - ((RTLPRIV(_priv))->dm.undec_sm_pwdb) - -static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { - 0x7f8001fe, - 0x788001e2, - 0x71c001c7, - 0x6b8001ae, - 0x65400195, - 0x5fc0017f, - 0x5a400169, - 0x55400155, - 0x50800142, - 0x4c000130, - 0x47c0011f, - 0x43c0010f, - 0x40000100, - 0x3c8000f2, - 0x390000e4, - 0x35c000d7, - 0x32c000cb, - 0x300000c0, - 0x2d4000b5, - 0x2ac000ab, - 0x288000a2, - 0x26000098, - 0x24000090, - 0x22000088, - 0x20000080, - 0x1e400079, - 0x1c800072, - 0x1b00006c, - 0x19800066, - 0x18000060, - 0x16c0005b, - 0x15800056, - 0x14400051, - 0x1300004c, - 0x12000048, - 0x11000044, - 0x10000040, -}; - -static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} -}; - -static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, - {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, - {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, - {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, - {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, - {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, - {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, - {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, - {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, - {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, - {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, - {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, - {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} -}; - -static u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a}; - -void dm_restorepowerindex(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 index; - - for (index = 0; index < 6; index++) - rtl_write_byte(rtlpriv, power_index_reg[index], - rtlpriv->dm.powerindex_backup[index]); -} -EXPORT_SYMBOL_GPL(dm_restorepowerindex); - -void dm_writepowerindex(struct ieee80211_hw *hw, u8 value) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 index; - - for (index = 0; index < 6; index++) - rtl_write_byte(rtlpriv, power_index_reg[index], value); -} -EXPORT_SYMBOL_GPL(dm_writepowerindex); - -void dm_savepowerindex(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 index; - u8 tmp; - - for (index = 0; index < 6; index++) { - tmp = rtl_read_byte(rtlpriv, power_index_reg[index]); - rtlpriv->dm.powerindex_backup[index] = tmp; - } -} -EXPORT_SYMBOL_GPL(dm_savepowerindex); - -static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - long rssi_val_min = 0; - - if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) && - (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) { - if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0) - rssi_val_min = - (rtlpriv->dm.entry_min_undec_sm_pwdb > - rtlpriv->dm.undec_sm_pwdb) ? - rtlpriv->dm.undec_sm_pwdb : - rtlpriv->dm.entry_min_undec_sm_pwdb; - else - rssi_val_min = rtlpriv->dm.undec_sm_pwdb; - } else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT || - dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) { - rssi_val_min = rtlpriv->dm.undec_sm_pwdb; - } else if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) { - rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb; - } - - if (rssi_val_min > 100) - rssi_val_min = 100; - return (u8)rssi_val_min; -} - -static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) -{ - u32 ret_value; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); - - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); - falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); - - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); - falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); - falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); - - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); - falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); - - ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD); - falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff); - falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16); - - falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + - falsealm_cnt->cnt_mcs_fail + - falsealm_cnt->cnt_fast_fsync_fail + - falsealm_cnt->cnt_sb_search_fail; - - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1); - ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); - falsealm_cnt->cnt_cck_fail = ret_value; - - ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3); - falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; - falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + - falsealm_cnt->cnt_mcs_fail + - falsealm_cnt->cnt_cck_fail); - - rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1); - rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0); - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0); - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", - falsealm_cnt->cnt_parity_fail, - falsealm_cnt->cnt_rate_illegal, - falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", - falsealm_cnt->cnt_ofdm_fail, - falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all); -} - -static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - u8 value_igi = dm_digtable->cur_igvalue; - - if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) - value_igi--; - else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1) - value_igi += 0; - else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2) - value_igi++; - else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2) - value_igi += 2; - - if (value_igi > DM_DIG_FA_UPPER) - value_igi = DM_DIG_FA_UPPER; - else if (value_igi < DM_DIG_FA_LOWER) - value_igi = DM_DIG_FA_LOWER; - - if (rtlpriv->falsealm_cnt.cnt_all > 10000) - value_igi = DM_DIG_FA_UPPER; - - dm_digtable->cur_igvalue = value_igi; - rtl92c_dm_write_dig(hw); -} - -static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *digtable = &rtlpriv->dm_digtable; - u32 isbt; - - /* modify DIG lower bound, deal with abnormally large false alarm */ - if (rtlpriv->falsealm_cnt.cnt_all > 10000) { - digtable->large_fa_hit++; - if (digtable->forbidden_igi < digtable->cur_igvalue) { - digtable->forbidden_igi = digtable->cur_igvalue; - digtable->large_fa_hit = 1; - } - - if (digtable->large_fa_hit >= 3) { - if ((digtable->forbidden_igi + 1) > - digtable->rx_gain_max) - digtable->rx_gain_min = digtable->rx_gain_max; - else - digtable->rx_gain_min = (digtable->forbidden_igi + 1); - digtable->recover_cnt = 3600; /* 3600=2hr */ - } - } else { - /* Recovery mechanism for IGI lower bound */ - if (digtable->recover_cnt != 0) { - digtable->recover_cnt--; - } else { - if (digtable->large_fa_hit == 0) { - if ((digtable->forbidden_igi-1) < DM_DIG_MIN) { - digtable->forbidden_igi = DM_DIG_MIN; - digtable->rx_gain_min = DM_DIG_MIN; - } else { - digtable->forbidden_igi--; - digtable->rx_gain_min = digtable->forbidden_igi + 1; - } - } else if (digtable->large_fa_hit == 3) { - digtable->large_fa_hit = 0; - } - } - } - if (rtlpriv->falsealm_cnt.cnt_all < 250) { - isbt = rtl_read_byte(rtlpriv, 0x4fd) & 0x01; - - if (!isbt) { - if (rtlpriv->falsealm_cnt.cnt_all > - digtable->fa_lowthresh) { - if ((digtable->back_val - 2) < - digtable->back_range_min) - digtable->back_val = digtable->back_range_min; - else - digtable->back_val -= 2; - } else if (rtlpriv->falsealm_cnt.cnt_all < - digtable->fa_lowthresh) { - if ((digtable->back_val + 2) > - digtable->back_range_max) - digtable->back_val = digtable->back_range_max; - else - digtable->back_val += 2; - } - } else { - digtable->back_val = DM_DIG_BACKOFF_DEFAULT; - } - } else { - /* Adjust initial gain by false alarm */ - if (rtlpriv->falsealm_cnt.cnt_all > 1000) - digtable->cur_igvalue = digtable->pre_igvalue + 2; - else if (rtlpriv->falsealm_cnt.cnt_all > 750) - digtable->cur_igvalue = digtable->pre_igvalue + 1; - else if (rtlpriv->falsealm_cnt.cnt_all < 500) - digtable->cur_igvalue = digtable->pre_igvalue - 1; - } - - /* Check initial gain by upper/lower bound */ - if (digtable->cur_igvalue > digtable->rx_gain_max) - digtable->cur_igvalue = digtable->rx_gain_max; - - if (digtable->cur_igvalue < digtable->rx_gain_min) - digtable->cur_igvalue = digtable->rx_gain_min; - - rtl92c_dm_write_dig(hw); -} - -static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) -{ - static u8 initialized; /* initialized to false */ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb; - bool multi_sta = false; - - if (mac->opmode == NL80211_IFTYPE_ADHOC) - multi_sta = true; - - if (!multi_sta || - dm_digtable->cursta_cstate == DIG_STA_DISCONNECT) { - initialized = false; - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; - return; - } else if (initialized == false) { - initialized = true; - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; - dm_digtable->cur_igvalue = 0x20; - rtl92c_dm_write_dig(hw); - } - - if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) { - if ((rssi_strength < dm_digtable->rssi_lowthresh) && - (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) { - - if (dm_digtable->dig_ext_port_stage == - DIG_EXT_PORT_STAGE_2) { - dm_digtable->cur_igvalue = 0x20; - rtl92c_dm_write_dig(hw); - } - - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1; - } else if (rssi_strength > dm_digtable->rssi_highthresh) { - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2; - rtl92c_dm_ctrl_initgain_by_fa(hw); - } - } else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) { - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; - dm_digtable->cur_igvalue = 0x20; - rtl92c_dm_write_dig(hw); - } - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "curmultista_cstate = %x dig_ext_port_stage %x\n", - dm_digtable->curmultista_cstate, - dm_digtable->dig_ext_port_stage); -} - -static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "presta_cstate = %x, cursta_cstate = %x\n", - dm_digtable->presta_cstate, dm_digtable->cursta_cstate); - if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate || - dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT || - dm_digtable->cursta_cstate == DIG_STA_CONNECT) { - - if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { - dm_digtable->rssi_val_min = - rtl92c_dm_initial_gain_min_pwdb(hw); - if (dm_digtable->rssi_val_min > 100) - dm_digtable->rssi_val_min = 100; - rtl92c_dm_ctrl_initgain_by_rssi(hw); - } - } else { - dm_digtable->rssi_val_min = 0; - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; - dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; - dm_digtable->cur_igvalue = 0x20; - dm_digtable->pre_igvalue = 0; - rtl92c_dm_write_dig(hw); - } -} - -static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) { - dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw); - if (dm_digtable->rssi_val_min > 100) - dm_digtable->rssi_val_min = 100; - - if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { - if (dm_digtable->rssi_val_min <= 25) - dm_digtable->cur_cck_pd_state = - CCK_PD_STAGE_LOWRSSI; - else - dm_digtable->cur_cck_pd_state = - CCK_PD_STAGE_HIGHRSSI; - } else { - if (dm_digtable->rssi_val_min <= 20) - dm_digtable->cur_cck_pd_state = - CCK_PD_STAGE_LOWRSSI; - else - dm_digtable->cur_cck_pd_state = - CCK_PD_STAGE_HIGHRSSI; - } - } else { - dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX; - } - - if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) { - if ((dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) || - (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_MAX)) - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83); - else - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); - - dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state; - } -} - -static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - if (mac->act_scanning) - return; - - if (mac->link_state >= MAC80211_LINKED) - dm_digtable->cursta_cstate = DIG_STA_CONNECT; - else - dm_digtable->cursta_cstate = DIG_STA_DISCONNECT; - - dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT; - - rtl92c_dm_initial_gain_sta(hw); - rtl92c_dm_initial_gain_multi_sta(hw); - rtl92c_dm_cck_packet_detection_thresh(hw); - - dm_digtable->presta_cstate = dm_digtable->cursta_cstate; - -} - -static void rtl92c_dm_dig(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->dm.dm_initialgain_enable == false) - return; - if (!(rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG)) - return; - - rtl92c_dm_ctrl_initgain_by_twoport(hw); -} - -static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->rtlhal.interface == INTF_USB && - rtlpriv->rtlhal.board_type & 0x1) { - dm_savepowerindex(hw); - rtlpriv->dm.dynamic_txpower_enable = true; - } else { - rtlpriv->dm.dynamic_txpower_enable = false; - } - rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; -} - -void rtl92c_dm_write_dig(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n", - dm_digtable->cur_igvalue, dm_digtable->pre_igvalue, - dm_digtable->back_val); - - if (rtlpriv->rtlhal.interface == INTF_USB && - !dm_digtable->dig_enable_flag) { - dm_digtable->pre_igvalue = 0x17; - return; - } - dm_digtable->cur_igvalue -= 1; - if (dm_digtable->cur_igvalue < DM_DIG_MIN) - dm_digtable->cur_igvalue = DM_DIG_MIN; - - if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) { - rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, - dm_digtable->cur_igvalue); - rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, - dm_digtable->cur_igvalue); - - dm_digtable->pre_igvalue = dm_digtable->cur_igvalue; - } - RT_TRACE(rtlpriv, COMP_DIG, DBG_WARNING, - "dig values 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", - dm_digtable->cur_igvalue, dm_digtable->pre_igvalue, - dm_digtable->rssi_val_min, dm_digtable->back_val, - dm_digtable->rx_gain_max, dm_digtable->rx_gain_min, - dm_digtable->large_fa_hit, dm_digtable->forbidden_igi); -} -EXPORT_SYMBOL(rtl92c_dm_write_dig); - -static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff; - - if (mac->link_state != MAC80211_LINKED) - return; - - if (mac->opmode == NL80211_IFTYPE_ADHOC || - mac->opmode == NL80211_IFTYPE_AP) { - /* TODO: Handle ADHOC and AP Mode */ - } - - if (tmpentry_max_pwdb != 0) - rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb; - else - rtlpriv->dm.entry_max_undec_sm_pwdb = 0; - - if (tmpentry_min_pwdb != 0xff) - rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb; - else - rtlpriv->dm.entry_min_undec_sm_pwdb = 0; - -/* TODO: - * if (mac->opmode == NL80211_IFTYPE_STATION) { - * if (rtlpriv->rtlhal.fw_ready) { - * u32 param = (u32)(rtlpriv->dm.undec_sm_pwdb << 16); - * rtl8192c_set_rssi_cmd(hw, param); - * } - * } - */ -} - -void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - rtlpriv->dm.current_turbo_edca = false; - rtlpriv->dm.is_any_nonbepkts = false; - rtlpriv->dm.is_cur_rdlstate = false; -} -EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo); - -static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - static u64 last_txok_cnt; - static u64 last_rxok_cnt; - static u32 last_bt_edca_ul; - static u32 last_bt_edca_dl; - u64 cur_txok_cnt = 0; - u64 cur_rxok_cnt = 0; - u32 edca_be_ul = 0x5ea42b; - u32 edca_be_dl = 0x5ea42b; - bool bt_change_edca = false; - - if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) || - (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) { - rtlpriv->dm.current_turbo_edca = false; - last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul; - last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl; - } - - if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) { - edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul; - bt_change_edca = true; - } - - if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) { - edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl; - bt_change_edca = true; - } - - if (mac->link_state != MAC80211_LINKED) { - rtlpriv->dm.current_turbo_edca = false; - return; - } - - if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) { - if (!(edca_be_ul & 0xffff0000)) - edca_be_ul |= 0x005e0000; - - if (!(edca_be_dl & 0xffff0000)) - edca_be_dl |= 0x005e0000; - } - - if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && - (!rtlpriv->dm.disable_framebursting))) { - - cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; - cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; - - if (cur_rxok_cnt > 4 * cur_txok_cnt) { - if (!rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { - rtl_write_dword(rtlpriv, - REG_EDCA_BE_PARAM, - edca_be_dl); - rtlpriv->dm.is_cur_rdlstate = true; - } - } else { - if (rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { - rtl_write_dword(rtlpriv, - REG_EDCA_BE_PARAM, - edca_be_ul); - rtlpriv->dm.is_cur_rdlstate = false; - } - } - rtlpriv->dm.current_turbo_edca = true; - } else { - if (rtlpriv->dm.current_turbo_edca) { - u8 tmp = AC0_BE; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, - &tmp); - rtlpriv->dm.current_turbo_edca = false; - } - } - - rtlpriv->dm.is_any_nonbepkts = false; - last_txok_cnt = rtlpriv->stats.txbytesunicast; - last_rxok_cnt = rtlpriv->stats.rxbytesunicast; -} - -static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw - *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 thermalvalue, delta, delta_lck, delta_iqk; - long ele_a, ele_d, temp_cck, val_x, value32; - long val_y, ele_c = 0; - u8 ofdm_index[2], ofdm_index_old[2] = {0, 0}, cck_index_old = 0; - s8 cck_index = 0; - int i; - bool is2t = IS_92C_SERIAL(rtlhal->version); - s8 txpwr_level[3] = {0, 0, 0}; - u8 ofdm_min_index = 6, rf; - - rtlpriv->dm.txpower_trackinginit = true; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "rtl92c_dm_txpower_tracking_callback_thermalmeter\n"); - - thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n", - thermalvalue, rtlpriv->dm.thermalvalue, - rtlefuse->eeprom_thermalmeter); - - rtl92c_phy_ap_calibrate(hw, (thermalvalue - - rtlefuse->eeprom_thermalmeter)); - if (is2t) - rf = 2; - else - rf = 1; - - if (thermalvalue) { - ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, - MASKDWORD) & MASKOFDM_D; - - for (i = 0; i < OFDM_TABLE_LENGTH; i++) { - if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { - ofdm_index_old[0] = (u8) i; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n", - ROFDM0_XATXIQIMBALANCE, - ele_d, ofdm_index_old[0]); - break; - } - } - - if (is2t) { - ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, - MASKDWORD) & MASKOFDM_D; - - for (i = 0; i < OFDM_TABLE_LENGTH; i++) { - if (ele_d == (ofdmswing_table[i] & - MASKOFDM_D)) { - ofdm_index_old[1] = (u8) i; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, - DBG_LOUD, - "Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n", - ROFDM0_XBTXIQIMBALANCE, ele_d, - ofdm_index_old[1]); - break; - } - } - } - - temp_cck = - rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK; - - for (i = 0; i < CCK_TABLE_LENGTH; i++) { - if (rtlpriv->dm.cck_inch14) { - if (memcmp((void *)&temp_cck, - (void *)&cckswing_table_ch14[i][2], - 4) == 0) { - cck_index_old = (u8) i; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, - DBG_LOUD, - "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch 14 %d\n", - RCCK0_TXFILTER2, temp_cck, - cck_index_old, - rtlpriv->dm.cck_inch14); - break; - } - } else { - if (memcmp((void *)&temp_cck, - (void *) - &cckswing_table_ch1ch13[i][2], - 4) == 0) { - cck_index_old = (u8) i; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, - DBG_LOUD, - "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch14 %d\n", - RCCK0_TXFILTER2, temp_cck, - cck_index_old, - rtlpriv->dm.cck_inch14); - break; - } - } - } - - if (!rtlpriv->dm.thermalvalue) { - rtlpriv->dm.thermalvalue = - rtlefuse->eeprom_thermalmeter; - rtlpriv->dm.thermalvalue_lck = thermalvalue; - rtlpriv->dm.thermalvalue_iqk = thermalvalue; - for (i = 0; i < rf; i++) - rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; - rtlpriv->dm.cck_index = cck_index_old; - } - /* Handle USB High PA boards */ - - delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? - (thermalvalue - rtlpriv->dm.thermalvalue) : - (rtlpriv->dm.thermalvalue - thermalvalue); - - delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? - (thermalvalue - rtlpriv->dm.thermalvalue_lck) : - (rtlpriv->dm.thermalvalue_lck - thermalvalue); - - delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? - (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : - (rtlpriv->dm.thermalvalue_iqk - thermalvalue); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n", - thermalvalue, rtlpriv->dm.thermalvalue, - rtlefuse->eeprom_thermalmeter, delta, delta_lck, - delta_iqk); - - if (delta_lck > 1) { - rtlpriv->dm.thermalvalue_lck = thermalvalue; - rtl92c_phy_lc_calibrate(hw); - } - - if (delta > 0 && rtlpriv->dm.txpower_track_control) { - if (thermalvalue > rtlpriv->dm.thermalvalue) { - for (i = 0; i < rf; i++) - rtlpriv->dm.ofdm_index[i] -= delta; - rtlpriv->dm.cck_index -= delta; - } else { - for (i = 0; i < rf; i++) - rtlpriv->dm.ofdm_index[i] += delta; - rtlpriv->dm.cck_index += delta; - } - - if (is2t) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n", - rtlpriv->dm.ofdm_index[0], - rtlpriv->dm.ofdm_index[1], - rtlpriv->dm.cck_index); - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "temp OFDM_A_index=0x%x, cck_index=0x%x\n", - rtlpriv->dm.ofdm_index[0], - rtlpriv->dm.cck_index); - } - - if (thermalvalue > rtlefuse->eeprom_thermalmeter) { - for (i = 0; i < rf; i++) - ofdm_index[i] = - rtlpriv->dm.ofdm_index[i] - + 1; - cck_index = rtlpriv->dm.cck_index + 1; - } else { - for (i = 0; i < rf; i++) - ofdm_index[i] = - rtlpriv->dm.ofdm_index[i]; - cck_index = rtlpriv->dm.cck_index; - } - - for (i = 0; i < rf; i++) { - if (txpwr_level[i] >= 0 && - txpwr_level[i] <= 26) { - if (thermalvalue > - rtlefuse->eeprom_thermalmeter) { - if (delta < 5) - ofdm_index[i] -= 1; - - else - ofdm_index[i] -= 2; - } else if (delta > 5 && thermalvalue < - rtlefuse-> - eeprom_thermalmeter) { - ofdm_index[i] += 1; - } - } else if (txpwr_level[i] >= 27 && - txpwr_level[i] <= 32 - && thermalvalue > - rtlefuse->eeprom_thermalmeter) { - if (delta < 5) - ofdm_index[i] -= 1; - - else - ofdm_index[i] -= 2; - } else if (txpwr_level[i] >= 32 && - txpwr_level[i] <= 38 && - thermalvalue > - rtlefuse->eeprom_thermalmeter - && delta > 5) { - ofdm_index[i] -= 1; - } - } - - if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) { - if (thermalvalue > - rtlefuse->eeprom_thermalmeter) { - if (delta < 5) - cck_index -= 1; - - else - cck_index -= 2; - } else if (delta > 5 && thermalvalue < - rtlefuse->eeprom_thermalmeter) { - cck_index += 1; - } - } else if (txpwr_level[i] >= 27 && - txpwr_level[i] <= 32 && - thermalvalue > - rtlefuse->eeprom_thermalmeter) { - if (delta < 5) - cck_index -= 1; - - else - cck_index -= 2; - } else if (txpwr_level[i] >= 32 && - txpwr_level[i] <= 38 && - thermalvalue > rtlefuse->eeprom_thermalmeter - && delta > 5) { - cck_index -= 1; - } - - for (i = 0; i < rf; i++) { - if (ofdm_index[i] > OFDM_TABLE_SIZE - 1) - ofdm_index[i] = OFDM_TABLE_SIZE - 1; - - else if (ofdm_index[i] < ofdm_min_index) - ofdm_index[i] = ofdm_min_index; - } - - if (cck_index > CCK_TABLE_SIZE - 1) - cck_index = CCK_TABLE_SIZE - 1; - else if (cck_index < 0) - cck_index = 0; - - if (is2t) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "new OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n", - ofdm_index[0], ofdm_index[1], - cck_index); - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "new OFDM_A_index=0x%x, cck_index=0x%x\n", - ofdm_index[0], cck_index); - } - } - - if (rtlpriv->dm.txpower_track_control && delta != 0) { - ele_d = - (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22; - val_x = rtlphy->reg_e94; - val_y = rtlphy->reg_e9c; - - if (val_x != 0) { - if ((val_x & 0x00000200) != 0) - val_x = val_x | 0xFFFFFC00; - ele_a = ((val_x * ele_d) >> 8) & 0x000003FF; - - if ((val_y & 0x00000200) != 0) - val_y = val_y | 0xFFFFFC00; - ele_c = ((val_y * ele_d) >> 8) & 0x000003FF; - - value32 = (ele_d << 22) | - ((ele_c & 0x3F) << 16) | ele_a; - - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, - MASKDWORD, value32); - - value32 = (ele_c & 0x000003C0) >> 6; - rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, - value32); - - value32 = ((val_x * ele_d) >> 7) & 0x01; - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, - BIT(31), value32); - - value32 = ((val_y * ele_d) >> 7) & 0x01; - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, - BIT(29), value32); - } else { - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, - MASKDWORD, - ofdmswing_table[ofdm_index[0]]); - - rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, - 0x00); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, - BIT(31) | BIT(29), 0x00); - } - - if (!rtlpriv->dm.cck_inch14) { - rtl_write_byte(rtlpriv, 0xa22, - cckswing_table_ch1ch13[cck_index] - [0]); - rtl_write_byte(rtlpriv, 0xa23, - cckswing_table_ch1ch13[cck_index] - [1]); - rtl_write_byte(rtlpriv, 0xa24, - cckswing_table_ch1ch13[cck_index] - [2]); - rtl_write_byte(rtlpriv, 0xa25, - cckswing_table_ch1ch13[cck_index] - [3]); - rtl_write_byte(rtlpriv, 0xa26, - cckswing_table_ch1ch13[cck_index] - [4]); - rtl_write_byte(rtlpriv, 0xa27, - cckswing_table_ch1ch13[cck_index] - [5]); - rtl_write_byte(rtlpriv, 0xa28, - cckswing_table_ch1ch13[cck_index] - [6]); - rtl_write_byte(rtlpriv, 0xa29, - cckswing_table_ch1ch13[cck_index] - [7]); - } else { - rtl_write_byte(rtlpriv, 0xa22, - cckswing_table_ch14[cck_index] - [0]); - rtl_write_byte(rtlpriv, 0xa23, - cckswing_table_ch14[cck_index] - [1]); - rtl_write_byte(rtlpriv, 0xa24, - cckswing_table_ch14[cck_index] - [2]); - rtl_write_byte(rtlpriv, 0xa25, - cckswing_table_ch14[cck_index] - [3]); - rtl_write_byte(rtlpriv, 0xa26, - cckswing_table_ch14[cck_index] - [4]); - rtl_write_byte(rtlpriv, 0xa27, - cckswing_table_ch14[cck_index] - [5]); - rtl_write_byte(rtlpriv, 0xa28, - cckswing_table_ch14[cck_index] - [6]); - rtl_write_byte(rtlpriv, 0xa29, - cckswing_table_ch14[cck_index] - [7]); - } - - if (is2t) { - ele_d = (ofdmswing_table[ofdm_index[1]] & - 0xFFC00000) >> 22; - - val_x = rtlphy->reg_eb4; - val_y = rtlphy->reg_ebc; - - if (val_x != 0) { - if ((val_x & 0x00000200) != 0) - val_x = val_x | 0xFFFFFC00; - ele_a = ((val_x * ele_d) >> 8) & - 0x000003FF; - - if ((val_y & 0x00000200) != 0) - val_y = val_y | 0xFFFFFC00; - ele_c = ((val_y * ele_d) >> 8) & - 0x00003FF; - - value32 = (ele_d << 22) | - ((ele_c & 0x3F) << 16) | ele_a; - rtl_set_bbreg(hw, - ROFDM0_XBTXIQIMBALANCE, - MASKDWORD, value32); - - value32 = (ele_c & 0x000003C0) >> 6; - rtl_set_bbreg(hw, ROFDM0_XDTXAFE, - MASKH4BITS, value32); - - value32 = ((val_x * ele_d) >> 7) & 0x01; - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, - BIT(27), value32); - - value32 = ((val_y * ele_d) >> 7) & 0x01; - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, - BIT(25), value32); - } else { - rtl_set_bbreg(hw, - ROFDM0_XBTXIQIMBALANCE, - MASKDWORD, - ofdmswing_table[ofdm_index - [1]]); - rtl_set_bbreg(hw, ROFDM0_XDTXAFE, - MASKH4BITS, 0x00); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, - BIT(27) | BIT(25), 0x00); - } - - } - } - - if (delta_iqk > 3) { - rtlpriv->dm.thermalvalue_iqk = thermalvalue; - rtl92c_phy_iq_calibrate(hw, false); - } - - if (rtlpriv->dm.txpower_track_control) - rtlpriv->dm.thermalvalue = thermalvalue; - } - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===\n"); - -} - -static void rtl92c_dm_initialize_txpower_tracking_thermalmeter( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.txpower_tracking = true; - rtlpriv->dm.txpower_trackinginit = false; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pMgntInfo->txpower_tracking = %d\n", - rtlpriv->dm.txpower_tracking); -} - -static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw) -{ - rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw); -} - -static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw) -{ - rtl92c_dm_txpower_tracking_callback_thermalmeter(hw); -} - -static void rtl92c_dm_check_txpower_tracking_thermal_meter( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (!rtlpriv->dm.txpower_tracking) - return; - - if (!rtlpriv->dm.tm_trigger) { - rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK, - 0x60); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Trigger 92S Thermal Meter!!\n"); - rtlpriv->dm.tm_trigger = 1; - return; - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Schedule TxPowerTracking direct call!!\n"); - rtl92c_dm_txpower_tracking_directcall(hw); - rtlpriv->dm.tm_trigger = 0; - } -} - -void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw) -{ - rtl92c_dm_check_txpower_tracking_thermal_meter(hw); -} -EXPORT_SYMBOL(rtl92c_dm_check_txpower_tracking); - -void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rate_adaptive *p_ra = &(rtlpriv->ra); - - p_ra->ratr_state = DM_RATR_STA_INIT; - p_ra->pre_ratr_state = DM_RATR_STA_INIT; - - if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) - rtlpriv->dm.useramask = true; - else - rtlpriv->dm.useramask = false; - -} -EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask); - -static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ps_t *dm_pstable = &rtlpriv->dm_pstable; - - dm_pstable->pre_ccastate = CCA_MAX; - dm_pstable->cur_ccasate = CCA_MAX; - dm_pstable->pre_rfstate = RF_MAX; - dm_pstable->cur_rfstate = RF_MAX; - dm_pstable->rssi_val_min = 0; -} - -void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ps_t *dm_pstable = &rtlpriv->dm_pstable; - - if (!rtlpriv->reg_init) { - rtlpriv->reg_874 = (rtl_get_bbreg(hw, - RFPGA0_XCD_RFINTERFACESW, - MASKDWORD) & 0x1CC000) >> 14; - - rtlpriv->reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1, - MASKDWORD) & BIT(3)) >> 3; - - rtlpriv->reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, - MASKDWORD) & 0xFF000000) >> 24; - - rtlpriv->reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & - 0xF000) >> 12; - - rtlpriv->reg_init = true; - } - - if (!bforce_in_normal) { - if (dm_pstable->rssi_val_min != 0) { - if (dm_pstable->pre_rfstate == RF_NORMAL) { - if (dm_pstable->rssi_val_min >= 30) - dm_pstable->cur_rfstate = RF_SAVE; - else - dm_pstable->cur_rfstate = RF_NORMAL; - } else { - if (dm_pstable->rssi_val_min <= 25) - dm_pstable->cur_rfstate = RF_NORMAL; - else - dm_pstable->cur_rfstate = RF_SAVE; - } - } else { - dm_pstable->cur_rfstate = RF_MAX; - } - } else { - dm_pstable->cur_rfstate = RF_NORMAL; - } - - if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) { - if (dm_pstable->cur_rfstate == RF_SAVE) { - rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, - 0x1C0000, 0x2); - rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0); - rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, - 0xFF000000, 0x63); - rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, - 0xC000, 0x2); - rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3); - rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); - rtl_set_bbreg(hw, 0x818, BIT(28), 0x1); - } else { - rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, - 0x1CC000, rtlpriv->reg_874); - rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), - rtlpriv->reg_c70); - rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000, - rtlpriv->reg_85c); - rtl_set_bbreg(hw, 0xa74, 0xF000, rtlpriv->reg_a74); - rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); - } - - dm_pstable->pre_rfstate = dm_pstable->cur_rfstate; - } -} -EXPORT_SYMBOL(rtl92c_dm_rf_saving); - -static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ps_t *dm_pstable = &rtlpriv->dm_pstable; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - /* Determine the minimum RSSI */ - if (((mac->link_state == MAC80211_NOLINK)) && - (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { - dm_pstable->rssi_val_min = 0; - RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, "Not connected to any\n"); - } - - if (mac->link_state == MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - dm_pstable->rssi_val_min = - rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, - "AP Client PWDB = 0x%lx\n", - dm_pstable->rssi_val_min); - } else { - dm_pstable->rssi_val_min = rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, - "STA Default Port PWDB = 0x%lx\n", - dm_pstable->rssi_val_min); - } - } else { - dm_pstable->rssi_val_min = - rtlpriv->dm.entry_min_undec_sm_pwdb; - - RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, - "AP Ext Port PWDB = 0x%lx\n", - dm_pstable->rssi_val_min); - } - - /* Power Saving for 92C */ - if (IS_92C_SERIAL(rtlhal->version)) - ;/* rtl92c_dm_1r_cca(hw); */ - else - rtl92c_dm_rf_saving(hw, false); -} - -void rtl92c_dm_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; - rtlpriv->dm.dm_flag = DYNAMIC_FUNC_DISABLE | DYNAMIC_FUNC_DIG; - rtlpriv->dm.undec_sm_pwdb = -1; - rtlpriv->dm.undec_sm_cck = -1; - rtlpriv->dm.dm_initialgain_enable = true; - rtl_dm_diginit(hw, 0x20); - - rtlpriv->dm.dm_flag |= HAL_DM_HIPWR_DISABLE; - rtl92c_dm_init_dynamic_txpower(hw); - - rtl92c_dm_init_edca_turbo(hw); - rtl92c_dm_init_rate_adaptive_mask(hw); - rtlpriv->dm.dm_flag |= DYNAMIC_FUNC_SS; - rtl92c_dm_initialize_txpower_tracking(hw); - rtl92c_dm_init_dynamic_bb_powersaving(hw); - - rtlpriv->dm.ofdm_pkt_cnt = 0; - rtlpriv->dm.dm_rssi_sel = RSSI_DEFAULT; -} -EXPORT_SYMBOL(rtl92c_dm_init); - -void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long undec_sm_pwdb; - - if (!rtlpriv->dm.dynamic_txpower_enable) - return; - - if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - - if ((mac->link_state < MAC80211_LINKED) && - (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "Not connected to any\n"); - - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - - rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - - if (mac->link_state >= MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Client PWDB = 0x%lx\n", - undec_sm_pwdb); - } else { - undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "STA Default Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - } else { - undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Ext Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - - if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL2; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); - } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && - (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) { - - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); - } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_NORMAL\n"); - } - - if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "PHY_SetTxPowerLevel8192S() Channel = %d\n", - rtlphy->current_channel); - rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); - if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_NORMAL) - dm_restorepowerindex(hw); - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_LEVEL1) - dm_writepowerindex(hw, 0x14); - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_LEVEL2) - dm_writepowerindex(hw, 0x10); - } - rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; -} - -void rtl92c_dm_watchdog(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool fw_current_inpsmode = false; - bool fw_ps_awake = true; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *) (&fw_current_inpsmode)); - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, - (u8 *) (&fw_ps_awake)); - - if (ppsc->p2p_ps_info.p2p_ps_mode) - fw_ps_awake = false; - - if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) && - fw_ps_awake) - && (!ppsc->rfchange_inprogress)) { - rtl92c_dm_pwdb_monitor(hw); - rtl92c_dm_dig(hw); - rtl92c_dm_false_alarm_counter_statistics(hw); - rtl92c_dm_dynamic_bb_powersaving(hw); - rtl92c_dm_dynamic_txpower(hw); - rtl92c_dm_check_txpower_tracking(hw); - /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */ - rtl92c_dm_bt_coexist(hw); - rtl92c_dm_check_edca_turbo(hw); - } -} -EXPORT_SYMBOL(rtl92c_dm_watchdog); - -u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - long undec_sm_pwdb; - u8 curr_bt_rssi_state = 0x00; - - if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { - undec_sm_pwdb = GET_UNDECORATED_AVERAGE_RSSI(rtlpriv); - } else { - if (rtlpriv->dm.entry_min_undec_sm_pwdb == 0) - undec_sm_pwdb = 100; - else - undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; - } - - /* Check RSSI to determine HighPower/NormalPower state for - * BT coexistence. */ - if (undec_sm_pwdb >= 67) - curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER); - else if (undec_sm_pwdb < 62) - curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER; - - /* Check RSSI to determine AMPDU setting for BT coexistence. */ - if (undec_sm_pwdb >= 40) - curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF); - else if (undec_sm_pwdb <= 32) - curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF; - - /* Marked RSSI state. It will be used to determine BT coexistence - * setting later. */ - if (undec_sm_pwdb < 35) - curr_bt_rssi_state |= BT_RSSI_STATE_SPECIAL_LOW; - else - curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW); - - /* Check BT state related to BT_Idle in B/G mode. */ - if (undec_sm_pwdb < 15) - curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW; - else - curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW); - - if (curr_bt_rssi_state != rtlpcipriv->bt_coexist.bt_rssi_state) { - rtlpcipriv->bt_coexist.bt_rssi_state = curr_bt_rssi_state; - return true; - } else { - return false; - } -} -EXPORT_SYMBOL(rtl92c_bt_rssi_state_change); - -static bool rtl92c_bt_state_change(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - u32 polling, ratio_tx, ratio_pri; - u32 bt_tx, bt_pri; - u8 bt_state; - u8 cur_service_type; - - if (rtlpriv->mac80211.link_state < MAC80211_LINKED) - return false; - - bt_state = rtl_read_byte(rtlpriv, 0x4fd); - bt_tx = rtl_read_dword(rtlpriv, 0x488) & BT_MASK; - bt_pri = rtl_read_dword(rtlpriv, 0x48c) & BT_MASK; - polling = rtl_read_dword(rtlpriv, 0x490); - - if (bt_tx == BT_MASK && bt_pri == BT_MASK && - polling == 0xffffffff && bt_state == 0xff) - return false; - - bt_state &= BIT_OFFSET_LEN_MASK_32(0, 1); - if (bt_state != rtlpcipriv->bt_coexist.bt_cur_state) { - rtlpcipriv->bt_coexist.bt_cur_state = bt_state; - - if (rtlpcipriv->bt_coexist.reg_bt_sco == 3) { - rtlpcipriv->bt_coexist.bt_service = BT_IDLE; - - bt_state = bt_state | - ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? - 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | - BIT_OFFSET_LEN_MASK_32(2, 1); - rtl_write_byte(rtlpriv, 0x4fd, bt_state); - } - return true; - } - - ratio_tx = bt_tx * 1000 / polling; - ratio_pri = bt_pri * 1000 / polling; - rtlpcipriv->bt_coexist.ratio_tx = ratio_tx; - rtlpcipriv->bt_coexist.ratio_pri = ratio_pri; - - if (bt_state && rtlpcipriv->bt_coexist.reg_bt_sco == 3) { - - if ((ratio_tx < 30) && (ratio_pri < 30)) - cur_service_type = BT_IDLE; - else if ((ratio_pri > 110) && (ratio_pri < 250)) - cur_service_type = BT_SCO; - else if ((ratio_tx >= 200) && (ratio_pri >= 200)) - cur_service_type = BT_BUSY; - else if ((ratio_tx >= 350) && (ratio_tx < 500)) - cur_service_type = BT_OTHERBUSY; - else if (ratio_tx >= 500) - cur_service_type = BT_PAN; - else - cur_service_type = BT_OTHER_ACTION; - - if (cur_service_type != rtlpcipriv->bt_coexist.bt_service) { - rtlpcipriv->bt_coexist.bt_service = cur_service_type; - bt_state = bt_state | - ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? - 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | - ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) ? - 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); - - /* Add interrupt migration when bt is not ini - * idle state (no traffic). */ - if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { - rtl_write_word(rtlpriv, 0x504, 0x0ccc); - rtl_write_byte(rtlpriv, 0x506, 0x54); - rtl_write_byte(rtlpriv, 0x507, 0x54); - } else { - rtl_write_byte(rtlpriv, 0x506, 0x00); - rtl_write_byte(rtlpriv, 0x507, 0x00); - } - - rtl_write_byte(rtlpriv, 0x4fd, bt_state); - return true; - } - } - - return false; - -} - -static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - static bool media_connect; - - if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { - media_connect = false; - } else { - if (!media_connect) { - media_connect = true; - return true; - } - media_connect = true; - } - - return false; -} - -static void rtl92c_bt_set_normal(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - - if (rtlpcipriv->bt_coexist.bt_service == BT_OTHERBUSY) { - rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72b; - rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72b; - } else if (rtlpcipriv->bt_coexist.bt_service == BT_BUSY) { - rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82f; - rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82f; - } else if (rtlpcipriv->bt_coexist.bt_service == BT_SCO) { - if (rtlpcipriv->bt_coexist.ratio_tx > 160) { - rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72f; - rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72f; - } else { - rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea32b; - rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea42b; - } - } else { - rtlpcipriv->bt_coexist.bt_edca_ul = 0; - rtlpcipriv->bt_coexist.bt_edca_dl = 0; - } - - if ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) && - (rtlpriv->mac80211.mode == WIRELESS_MODE_G || - (rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) && - (rtlpcipriv->bt_coexist.bt_rssi_state & - BT_RSSI_STATE_BG_EDCA_LOW)) { - rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82b; - rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82b; - } -} - -static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - - /* Only enable HW BT coexist when BT in "Busy" state. */ - if (rtlpriv->mac80211.vendor == PEER_CISCO && - rtlpcipriv->bt_coexist.bt_service == BT_OTHER_ACTION) { - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); - } else { - if ((rtlpcipriv->bt_coexist.bt_service == BT_BUSY) && - (rtlpcipriv->bt_coexist.bt_rssi_state & - BT_RSSI_STATE_NORMAL_POWER)) { - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); - } else if ((rtlpcipriv->bt_coexist.bt_service == - BT_OTHER_ACTION) && (rtlpriv->mac80211.mode < - WIRELESS_MODE_N_24G) && - (rtlpcipriv->bt_coexist.bt_rssi_state & - BT_RSSI_STATE_SPECIAL_LOW)) { - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); - } else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) { - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte); - } else { - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte); - } - } - - if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100); - else - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0); - - if (rtlpcipriv->bt_coexist.bt_rssi_state & - BT_RSSI_STATE_NORMAL_POWER) { - rtl92c_bt_set_normal(hw); - } else { - rtlpcipriv->bt_coexist.bt_edca_ul = 0; - rtlpcipriv->bt_coexist.bt_edca_dl = 0; - } - - if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { - rtlpriv->cfg->ops->set_rfreg(hw, - RF90_PATH_A, - 0x1e, - 0xf0, 0xf); - } else { - rtlpriv->cfg->ops->set_rfreg(hw, - RF90_PATH_A, 0x1e, 0xf0, - rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); - } - - if (!rtlpriv->dm.dynamic_txpower_enable) { - if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) { - if (rtlpcipriv->bt_coexist.bt_rssi_state & - BT_RSSI_STATE_TXPOWER_LOW) { - rtlpriv->dm.dynamic_txhighpower_lvl = - TXHIGHPWRLEVEL_BT2; - } else { - rtlpriv->dm.dynamic_txhighpower_lvl = - TXHIGHPWRLEVEL_BT1; - } - } else { - rtlpriv->dm.dynamic_txhighpower_lvl = - TXHIGHPWRLEVEL_NORMAL; - } - rtl92c_phy_set_txpower_level(hw, - rtlpriv->phy.current_channel); - } -} - -static void rtl92c_check_bt_change(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp1byte = 0; - - if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version) && - rtlpcipriv->bt_coexist.bt_coexistence) - tmp1byte |= BIT(5); - if (rtlpcipriv->bt_coexist.bt_cur_state) { - if (rtlpcipriv->bt_coexist.bt_ant_isolation) - rtl92c_bt_ant_isolation(hw, tmp1byte); - } else { - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte); - rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0, - rtlpcipriv->bt_coexist.bt_rfreg_origin_1e); - - rtlpcipriv->bt_coexist.bt_edca_ul = 0; - rtlpcipriv->bt_coexist.bt_edca_dl = 0; - } -} - -void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - bool wifi_connect_change; - bool bt_state_change; - bool rssi_state_change; - - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) { - - wifi_connect_change = rtl92c_bt_wifi_connect_change(hw); - bt_state_change = rtl92c_bt_state_change(hw); - rssi_state_change = rtl92c_bt_rssi_state_change(hw); - - if (wifi_connect_change || bt_state_change || rssi_state_change) - rtl92c_check_bt_change(hw); - } -} -EXPORT_SYMBOL(rtl92c_dm_bt_coexist); diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h deleted file mode 100644 index 4422e31fedd9..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h +++ /dev/null @@ -1,147 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92COMMON_DM_H__ -#define __RTL92COMMON_DM_H__ - -#include "../wifi.h" -#include "../rtl8192ce/def.h" -#include "../rtl8192ce/reg.h" -#include "fw_common.h" - -#define HAL_DM_DIG_DISABLE BIT(0) -#define HAL_DM_HIPWR_DISABLE BIT(1) - -#define OFDM_TABLE_LENGTH 37 -#define CCK_TABLE_LENGTH 33 - -#define OFDM_TABLE_SIZE 37 -#define CCK_TABLE_SIZE 33 - -#define BW_AUTO_SWITCH_HIGH_LOW 25 -#define BW_AUTO_SWITCH_LOW_HIGH 30 - -#define DM_DIG_FA_UPPER 0x32 -#define DM_DIG_FA_LOWER 0x20 -#define DM_DIG_FA_TH0 0x20 -#define DM_DIG_FA_TH1 0x100 -#define DM_DIG_FA_TH2 0x200 - -#define RXPATHSELECTION_SS_TH_lOW 30 -#define RXPATHSELECTION_DIFF_TH 18 - -#define DM_RATR_STA_INIT 0 -#define DM_RATR_STA_HIGH 1 -#define DM_RATR_STA_MIDDLE 2 -#define DM_RATR_STA_LOW 3 - -#define CTS2SELF_THVAL 30 -#define REGC38_TH 20 - -#define WAIOTTHVal 25 - -#define TXHIGHPWRLEVEL_NORMAL 0 -#define TXHIGHPWRLEVEL_LEVEL1 1 -#define TXHIGHPWRLEVEL_LEVEL2 2 -#define TXHIGHPWRLEVEL_BT1 3 -#define TXHIGHPWRLEVEL_BT2 4 - -#define DM_TYPE_BYFW 0 -#define DM_TYPE_BYDRIVER 1 - -#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 -#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 - -#define DYNAMIC_FUNC_DISABLE 0x0 -#define DYNAMIC_FUNC_DIG BIT(0) -#define DYNAMIC_FUNC_HP BIT(1) -#define DYNAMIC_FUNC_SS BIT(2) /*Tx Power Tracking*/ -#define DYNAMIC_FUNC_BT BIT(3) -#define DYNAMIC_FUNC_ANT_DIV BIT(4) - -#define RSSI_CCK 0 -#define RSSI_OFDM 1 -#define RSSI_DEFAULT 2 - -struct swat_t { - u8 failure_cnt; - u8 try_flag; - u8 stop_trying; - long pre_rssi; - long trying_threshold; - u8 cur_antenna; - u8 pre_antenna; -}; - -enum tag_dynamic_init_gain_operation_type_definition { - DIG_TYPE_THRESH_HIGH = 0, - DIG_TYPE_THRESH_LOW = 1, - DIG_TYPE_BACKOFF = 2, - DIG_TYPE_RX_GAIN_MIN = 3, - DIG_TYPE_RX_GAIN_MAX = 4, - DIG_TYPE_ENABLE = 5, - DIG_TYPE_DISABLE = 6, - DIG_OP_TYPE_MAX -}; - -enum dm_1r_cca_e { - CCA_1R = 0, - CCA_2R = 1, - CCA_MAX = 2, -}; - -enum dm_rf_e { - RF_SAVE = 0, - RF_NORMAL = 1, - RF_MAX = 2, -}; - -enum dm_sw_ant_switch_e { - ANS_ANTENNA_B = 1, - ANS_ANTENNA_A = 2, - ANS_ANTENNA_MAX = 3, -}; - -void rtl92c_dm_init(struct ieee80211_hw *hw); -void rtl92c_dm_watchdog(struct ieee80211_hw *hw); -void rtl92c_dm_write_dig(struct ieee80211_hw *hw); -void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw); -void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw); -void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); -void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); -void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); -void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); -void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery); -void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw); -void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); -void dm_savepowerindex(struct ieee80211_hw *hw); -void dm_writepowerindex(struct ieee80211_hw *hw, u8 value); -void dm_restorepowerindex(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c deleted file mode 100644 index 43fcb25c885f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ /dev/null @@ -1,867 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../core.h" -#include "../rtl8192ce/reg.h" -#include "../rtl8192ce/def.h" -#include "fw_common.h" -#include -#include - -static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) { - u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - if (enable) - value32 |= MCUFWDL_EN; - else - value32 &= ~MCUFWDL_EN; - rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); - } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) { - u8 tmp; - if (enable) { - - tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, - tmp | 0x04); - - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); - rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); - - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); - rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); - } else { - - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); - rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); - - rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00); - } - } -} - -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) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool is_version_b; - u8 *bufferptr = (u8 *)buffer; - - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size); - is_version_b = IS_NORMAL_CHIP(version); - if (is_version_b) { - u32 pageNums, remainsize; - u32 page, offset; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) - _rtl92c_fill_dummy(bufferptr, &size); - - pageNums = size / FW_8192C_PAGE_SIZE; - remainsize = size % FW_8192C_PAGE_SIZE; - - if (pageNums > 4) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Page numbers should not greater then 4\n"); - } - - for (page = 0; page < pageNums; page++) { - offset = page * FW_8192C_PAGE_SIZE; - _rtl92c_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); - } - } else { - _rtl92c_fw_block_write(hw, buffer, size); - } -} - -static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int err = -EIO; - u32 counter = 0; - u32 value32; - - do { - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && - (!(value32 & FWDL_ChkSum_rpt))); - - if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "chksum report faill ! REG_MCUFWDL:0x%08x .\n", - value32); - goto exit; - } - - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); - - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - value32 |= MCUFWDL_RDY; - value32 &= ~WINTINI_RDY; - rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); - - counter = 0; - - do { - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - if (value32 & WINTINI_RDY) { - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n", - value32); - err = 0; - goto exit; - } - - mdelay(FW_8192C_POLLING_DELAY); - - } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT); - - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32); - -exit: - return err; -} - -int rtl92c_download_fw(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtlwifi_firmware_header *pfwheader; - u8 *pfwdata; - u32 fwsize; - int err; - enum version_8192c version = rtlhal->version; - - if (!rtlhal->pfirmware) - return 1; - - pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; - pfwdata = (u8 *)rtlhal->pfirmware; - fwsize = rtlhal->fwsize; - if (IS_FW_HEADER_EXIST(pfwheader)) { - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "Firmware Version(%d), Signature(%#x),Size(%d)\n", - pfwheader->version, pfwheader->signature, - (int)sizeof(struct rtlwifi_firmware_header)); - - rtlhal->fw_version = le16_to_cpu(pfwheader->version); - rtlhal->fw_subversion = pfwheader->subversion; - pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); - fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); - } - - _rtl92c_enable_fw_download(hw, true); - _rtl92c_write_fw(hw, version, pfwdata, fwsize); - _rtl92c_enable_fw_download(hw, false); - - err = _rtl92c_fw_free_to_go(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Firmware is not ready to run!\n"); - } else { - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "Firmware is ready to run!\n"); - } - - return 0; -} -EXPORT_SYMBOL(rtl92c_download_fw); - -static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 val_hmetfr, val_mcutst_1; - bool result = false; - - val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); - val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum)); - - if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0) - result = true; - return result; -} - -static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, u8 *cmdbuffer) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 boxnum; - u16 box_reg = 0, box_extreg = 0; - u8 u1b_tmp; - bool isfw_read = false; - u8 buf_index = 0; - bool bwrite_sucess = false; - u8 wait_h2c_limmit = 100; - u8 wait_writeh2c_limmit = 100; - u8 boxcontent[4], boxextcontent[2]; - u32 h2c_waitcounter = 0; - unsigned long flag; - u8 idx; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); - - while (true) { - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - if (rtlhal->h2c_setinprogress) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C set in progress! Wait to set..element_id(%d).\n", - element_id); - while (rtlhal->h2c_setinprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, - flag); - h2c_waitcounter++; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Wait 100 us (%d times)...\n", - h2c_waitcounter); - udelay(100); - - if (h2c_waitcounter > 1000) - return; - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, - flag); - } - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - } else { - rtlhal->h2c_setinprogress = true; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - break; - } - } - - while (!bwrite_sucess) { - wait_writeh2c_limmit--; - if (wait_writeh2c_limmit == 0) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Write H2C fail because no trigger for FW INT!\n"); - break; - } - - boxnum = rtlhal->last_hmeboxnum; - switch (boxnum) { - case 0: - box_reg = REG_HMEBOX_0; - box_extreg = REG_HMEBOX_EXT_0; - break; - case 1: - box_reg = REG_HMEBOX_1; - box_extreg = REG_HMEBOX_EXT_1; - break; - case 2: - box_reg = REG_HMEBOX_2; - box_extreg = REG_HMEBOX_EXT_2; - break; - case 3: - box_reg = REG_HMEBOX_3; - box_extreg = REG_HMEBOX_EXT_3; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - - isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum); - while (!isfw_read) { - wait_h2c_limmit--; - if (wait_h2c_limmit == 0) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Waiting too long for FW read clear HMEBox(%d)!\n", - boxnum); - break; - } - - udelay(10); - - isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum); - u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF); - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n", - boxnum, u1b_tmp); - } - - if (!isfw_read) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", - boxnum); - break; - } - - memset(boxcontent, 0, sizeof(boxcontent)); - memset(boxextcontent, 0, sizeof(boxextcontent)); - boxcontent[0] = element_id; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Write element_id box_reg(%4x) = %2x\n", - box_reg, element_id); - - switch (cmd_len) { - case 1: - boxcontent[0] &= ~(BIT(7)); - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index, 1); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - case 2: - boxcontent[0] &= ~(BIT(7)); - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index, 2); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - case 3: - boxcontent[0] &= ~(BIT(7)); - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index, 3); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - case 4: - boxcontent[0] |= (BIT(7)); - memcpy((u8 *)(boxextcontent), - cmdbuffer + buf_index, 2); - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index + 2, 2); - - for (idx = 0; idx < 2; idx++) { - rtl_write_byte(rtlpriv, box_extreg + idx, - boxextcontent[idx]); - } - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - case 5: - boxcontent[0] |= (BIT(7)); - memcpy((u8 *)(boxextcontent), - cmdbuffer + buf_index, 2); - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index + 2, 3); - - for (idx = 0; idx < 2; idx++) { - rtl_write_byte(rtlpriv, box_extreg + idx, - boxextcontent[idx]); - } - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - - bwrite_sucess = true; - - rtlhal->last_hmeboxnum = boxnum + 1; - if (rtlhal->last_hmeboxnum == 4) - rtlhal->last_hmeboxnum = 0; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "pHalData->last_hmeboxnum = %d\n", - rtlhal->last_hmeboxnum); - } - - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - rtlhal->h2c_setinprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); -} - -void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, u8 *cmdbuffer) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 tmp_cmdbuf[2]; - - if (!rtlhal->fw_ready) { - RT_ASSERT(false, - "return H2C cmd because of Fw download fail!!!\n"); - return; - } - - memset(tmp_cmdbuf, 0, 8); - memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); - _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); - - return; -} -EXPORT_SYMBOL(rtl92c_fill_h2c_cmd); - -void rtl92c_firmware_selfreset(struct ieee80211_hw *hw) -{ - u8 u1b_tmp; - u8 delay = 100; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20); - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - - while (u1b_tmp & BIT(2)) { - delay--; - if (delay == 0) { - RT_ASSERT(false, "8051 reset fail.\n"); - break; - } - udelay(50); - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - } -} -EXPORT_SYMBOL(rtl92c_firmware_selfreset); - -void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 u1_h2c_set_pwrmode[3] = { 0 }; - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); - - SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); - SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, - (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1); - SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, - ppsc->reg_max_lps_awakeintvl); - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n", - u1_h2c_set_pwrmode, 3); - rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode); -} -EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd); - -#define BEACON_PG 0 /*->1*/ -#define PSPOLL_PG 2 -#define NULL_PG 3 -#define PROBERSP_PG 4 /*->5*/ - -#define TOTAL_RESERVED_PKT_LEN 768 - -static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { - /* page 0 beacon */ - 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, - 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, - 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, - 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, - 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, - 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, - 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 1 beacon */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 2 ps-poll */ - 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 3 null */ - 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 4 probe_resp */ - 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, - 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, - 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, - 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, - 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, - 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, - 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, - 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, - 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 5 probe_resp */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, - bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *)) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct sk_buff *skb = NULL; - - u32 totalpacketlen; - bool rtstatus; - u8 u1rsvdpageloc[3] = { 0 }; - bool b_dlok = false; - - u8 *beacon; - u8 *p_pspoll; - u8 *nullfunc; - u8 *p_probersp; - /*--------------------------------------------------------- - (1) beacon - ---------------------------------------------------------*/ - beacon = &reserved_page_packet[BEACON_PG * 128]; - SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); - SET_80211_HDR_ADDRESS3(beacon, mac->bssid); - - /*------------------------------------------------------- - (2) ps-poll - --------------------------------------------------------*/ - p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; - SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); - SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); - SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); - - SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); - - /*-------------------------------------------------------- - (3) null data - ---------------------------------------------------------*/ - nullfunc = &reserved_page_packet[NULL_PG * 128]; - SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); - SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); - SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); - - /*--------------------------------------------------------- - (4) probe response - ----------------------------------------------------------*/ - p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; - SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); - SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); - SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); - - totalpacketlen = TOTAL_RESERVED_PKT_LEN; - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", - &reserved_page_packet[0], totalpacketlen); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", - u1rsvdpageloc, 3); - - - skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); - - if (cmd_send_packet) - rtstatus = cmd_send_packet(hw, skb); - else - rtstatus = rtl_cmd_send_packet(hw, skb); - - if (rtstatus) - b_dlok = true; - - if (b_dlok) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Set RSVD page location to Fw.\n"); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "H2C_RSVDPAGE:\n", - u1rsvdpageloc, 3); - rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE, - sizeof(u1rsvdpageloc), u1rsvdpageloc); - } else - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set RSVD page location to Fw FAIL!!!!!!.\n"); -} -EXPORT_SYMBOL(rtl92c_set_fw_rsvdpagepkt); - -void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) -{ - u8 u1_joinbssrpt_parm[1] = { 0 }; - - SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); - - rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); -} -EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd); - -static void rtl92c_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) -{ - u8 u1_ctwindow_period[1] = { ctwindow}; - - rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); -} - -/* refactored routine */ -static void set_noa_data(struct rtl_priv *rtlpriv, - struct rtl_p2p_ps_info *p2pinfo, - struct p2p_ps_offload_t *p2p_ps_offload) -{ - int i; - u32 start_time, tsf_low; - - /* hw only support 2 set of NoA */ - for (i = 0 ; i < p2pinfo->noa_num ; i++) { - /* To control the reg setting for which NOA*/ - rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); - if (i == 0) - p2p_ps_offload->noa0_en = 1; - else - p2p_ps_offload->noa1_en = 1; - - /* config P2P NoA Descriptor Register */ - rtl_write_dword(rtlpriv, 0x5E0, - p2pinfo->noa_duration[i]); - rtl_write_dword(rtlpriv, 0x5E4, - p2pinfo->noa_interval[i]); - - /*Get Current TSF value */ - tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - - start_time = p2pinfo->noa_start_time[i]; - if (p2pinfo->noa_count_type[i] != 1) { - while (start_time <= (tsf_low+(50*1024))) { - start_time += p2pinfo->noa_interval[i]; - if (p2pinfo->noa_count_type[i] != 255) - p2pinfo->noa_count_type[i]--; - } - } - rtl_write_dword(rtlpriv, 0x5E8, start_time); - rtl_write_dword(rtlpriv, 0x5EC, - p2pinfo->noa_count_type[i]); - } -} - -void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); - struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; - u16 ctwindow; - - switch (p2p_ps_state) { - case P2P_PS_DISABLE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "P2P_PS_DISABLE\n"); - memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); - break; - case P2P_PS_ENABLE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "P2P_PS_ENABLE\n"); - /* update CTWindow value. */ - if (p2pinfo->ctwindow > 0) { - p2p_ps_offload->ctwindow_en = 1; - ctwindow = p2pinfo->ctwindow; - rtl92c_set_p2p_ctw_period_cmd(hw, ctwindow); - } - /* call refactored routine */ - set_noa_data(rtlpriv, p2pinfo, p2p_ps_offload); - - if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { - /* rst p2p circuit */ - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, - BIT(4)); - - p2p_ps_offload->offload_en = 1; - - if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { - p2p_ps_offload->role = 1; - p2p_ps_offload->allstasleep = 0; - } else { - p2p_ps_offload->role = 0; - } - - p2p_ps_offload->discovery = 0; - } - break; - case P2P_PS_SCAN: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); - p2p_ps_offload->discovery = 1; - break; - case P2P_PS_SCAN_DONE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "P2P_PS_SCAN_DONE\n"); - p2p_ps_offload->discovery = 0; - p2pinfo->p2p_ps_state = P2P_PS_ENABLE; - break; - default: - break; - } - - rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload); - -} -EXPORT_SYMBOL_GPL(rtl92c_set_p2p_ps_offload_cmd); diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h deleted file mode 100644 index 864806c19ca7..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h +++ /dev/null @@ -1,101 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C__FW__COMMON__H__ -#define __RTL92C__FW__COMMON__H__ - -#define FW_8192C_SIZE 0x3000 -#define FW_8192C_START_ADDRESS 0x1000 -#define FW_8192C_END_ADDRESS 0x1FFF -#define FW_8192C_PAGE_SIZE 4096 -#define FW_8192C_POLLING_DELAY 5 -#define FW_8192C_POLLING_TIMEOUT_COUNT 100 -#define NORMAL_CHIP BIT(4) -#define H2C_92C_KEEP_ALIVE_CTRL 48 - -#define IS_FW_HEADER_EXIST(_pfwhdr) \ - ((le16_to_cpu(_pfwhdr->signature)&0xFFF0) == 0x92C0 ||\ - (le16_to_cpu(_pfwhdr->signature)&0xFFF0) == 0x88C0) - -#define CUT_VERSION_MASK (BIT(6)|BIT(7)) -#define CHIP_VENDOR_UMC BIT(5) -#define CHIP_VENDOR_UMC_B_CUT BIT(6) /* Chip version for ECO */ -#define IS_CHIP_VER_B(version) ((version & CHIP_VER_B) ? true : false) -#define RF_TYPE_MASK (BIT(0)|BIT(1)) -#define GET_CVID_RF_TYPE(version) \ - ((version) & RF_TYPE_MASK) -#define GET_CVID_CUT_VERSION(version) \ - ((version) & CUT_VERSION_MASK) -#define IS_NORMAL_CHIP(version) \ - ((version & NORMAL_CHIP) ? true : false) -#define IS_2T2R(version) \ - (((GET_CVID_RF_TYPE(version)) == \ - CHIP_92C_BITMASK) ? true : false) -#define IS_92C_SERIAL(version) \ - ((IS_2T2R(version)) ? true : false) -#define IS_CHIP_VENDOR_UMC(version) \ - ((version & CHIP_VENDOR_UMC) ? true : false) -#define IS_VENDOR_UMC_A_CUT(version) \ - ((IS_CHIP_VENDOR_UMC(version)) ? \ - ((GET_CVID_CUT_VERSION(version)) ? false : true) : false) -#define IS_81XXC_VENDOR_UMC_B_CUT(version) \ - ((IS_CHIP_VENDOR_UMC(version)) ? \ - ((GET_CVID_CUT_VERSION(version) == \ - CHIP_VENDOR_UMC_B_CUT) ? true : false) : false) - -#define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) - -#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) -#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) - -int rtl92c_download_fw(struct ieee80211_hw *hw); -void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *p_cmdbuffer); -void rtl92c_firmware_selfreset(struct ieee80211_hw *hw); -void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); -void rtl92c_set_fw_rsvdpagepkt - (struct ieee80211_hw *hw, - bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *)); -void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); -void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len); -void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/main.c b/drivers/net/wireless/rtlwifi/rtl8192c/main.c deleted file mode 100644 index 918b1d129e77..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192c/main.c +++ /dev/null @@ -1,40 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include - - -MODULE_AUTHOR("lizhaoming "); -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_AUTHOR("Georgia "); -MODULE_AUTHOR("Ziv Huang "); -MODULE_AUTHOR("Larry Finger "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n PCI wireless"); diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c deleted file mode 100644 index 77e61b19bf36..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ /dev/null @@ -1,1659 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../rtl8192ce/reg.h" -#include "../rtl8192ce/def.h" -#include "dm_common.h" -#include "fw_common.h" -#include "phy_common.h" -#include - -u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 returnvalue, originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n", - regaddr, bitmask); - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); - returnvalue = (originalvalue & bitmask) >> bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "BBR MASK=0x%x Addr[0x%x]=0x%x\n", - bitmask, regaddr, originalvalue); - - return returnvalue; -} -EXPORT_SYMBOL(rtl92c_phy_query_bb_reg); - -void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); - - if (bitmask != MASKDWORD) { - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); - data = ((originalvalue & (~bitmask)) | (data << bitshift)); - } - - rtl_write_dword(rtlpriv, regaddr, data); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); -} -EXPORT_SYMBOL(rtl92c_phy_set_bb_reg); - -u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) -{ - RT_ASSERT(false, "deprecated!\n"); - return 0; -} -EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_read); - -void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) -{ - RT_ASSERT(false, "deprecated!\n"); -} -EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_write); - -u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - u32 newoffset; - u32 tmplong, tmplong2; - u8 rfpi_enable = 0; - u32 retvalue; - - offset &= 0x3f; - newoffset = offset; - if (RT_CANNOT_IO(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n"); - return 0xFFFFFFFF; - } - tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); - if (rfpath == RF90_PATH_A) - tmplong2 = tmplong; - else - tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); - tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | - (newoffset << 23) | BLSSIREADEDGE; - rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, - tmplong & (~BLSSIREADEDGE)); - mdelay(1); - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); - mdelay(1); - rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, - tmplong | BLSSIREADEDGE); - mdelay(1); - if (rfpath == RF90_PATH_A) - rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, - BIT(8)); - else if (rfpath == RF90_PATH_B) - rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, - BIT(8)); - if (rfpi_enable) - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, - BLSSIREADBACKDATA); - else - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, - BLSSIREADBACKDATA); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n", - rfpath, pphyreg->rf_rb, - retvalue); - return retvalue; -} -EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read); - -void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) -{ - u32 data_and_addr; - u32 newoffset; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - - if (RT_CANNOT_IO(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n"); - return; - } - offset &= 0x3f; - newoffset = offset; - data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; - rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]=0x%x\n", - rfpath, pphyreg->rf3wire_offset, - data_and_addr); -} -EXPORT_SYMBOL(_rtl92c_phy_rf_serial_write); - -u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask) -{ - u32 i; - - for (i = 0; i <= 31; i++) { - if (((bitmask >> i) & 0x1) == 1) - break; - } - return i; -} -EXPORT_SYMBOL(_rtl92c_phy_calculate_bit_shift); - -static void _rtl92c_phy_bb_config_1t(struct ieee80211_hw *hw) -{ - rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2); - rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022); - rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45); - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23); - rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1); - rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2); - rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2); - rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2); - rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2); - rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2); -} - -bool rtl92c_phy_rf_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - return rtlpriv->cfg->ops->phy_rf6052_config(hw); -} -EXPORT_SYMBOL(rtl92c_phy_rf_config); - -bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - bool rtstatus; - - rtstatus = rtlpriv->cfg->ops->config_bb_with_headerfile(hw, - BASEBAND_CONFIG_PHY_REG); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); - return false; - } - if (rtlphy->rf_type == RF_1T2R) { - _rtl92c_phy_bb_config_1t(hw); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Config to 1T!!\n"); - } - if (rtlefuse->autoload_failflag == false) { - rtlphy->pwrgroup_cnt = 0; - rtstatus = rtlpriv->cfg->ops->config_bb_with_pgheaderfile(hw, - BASEBAND_CONFIG_PHY_REG); - } - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); - return false; - } - rtstatus = rtlpriv->cfg->ops->config_bb_with_headerfile(hw, - BASEBAND_CONFIG_AGC_TAB); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); - return false; - } - rtlphy->cck_high_power = - (bool)(rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, 0x200)); - - return true; -} - -EXPORT_SYMBOL(_rtl92c_phy_bb8192c_config_parafile); - -void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, - u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - if (regaddr == RTXAGC_A_RATE18_06) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][0]); - } - if (regaddr == RTXAGC_A_RATE54_24) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][1]); - } - if (regaddr == RTXAGC_A_CCK1_MCS32) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][6]); - } - if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][7]); - } - if (regaddr == RTXAGC_A_MCS03_MCS00) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][2]); - } - if (regaddr == RTXAGC_A_MCS07_MCS04) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][3]); - } - if (regaddr == RTXAGC_A_MCS11_MCS08) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][4]); - } - if (regaddr == RTXAGC_A_MCS15_MCS12) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][5]); - } - if (regaddr == RTXAGC_B_RATE18_06) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][8]); - } - if (regaddr == RTXAGC_B_RATE54_24) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][9]); - } - if (regaddr == RTXAGC_B_CCK1_55_MCS32) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][14]); - } - if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][15]); - } - if (regaddr == RTXAGC_B_MCS03_MCS00) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][10]); - } - if (regaddr == RTXAGC_B_MCS07_MCS04) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][11]); - } - if (regaddr == RTXAGC_B_MCS11_MCS08) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][12]); - } - if (regaddr == RTXAGC_B_MCS15_MCS12) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][13]); - - rtlphy->pwrgroup_cnt++; - } -} -EXPORT_SYMBOL(_rtl92c_store_pwrIndex_diffrate_offset); - -void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - rtlphy->default_initialgain[0] = - (u8)rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[1] = - (u8)rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[2] = - (u8)rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[3] = - (u8)rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", - rtlphy->default_initialgain[0], - rtlphy->default_initialgain[1], - rtlphy->default_initialgain[2], - rtlphy->default_initialgain[3]); - - rtlphy->framesync = (u8)rtl_get_bbreg(hw, - ROFDM0_RXDETECTOR3, MASKBYTE0); - rtlphy->framesync_c34 = rtl_get_bbreg(hw, - ROFDM0_RXDETECTOR2, MASKDWORD); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default framesync (0x%x) = 0x%x\n", - ROFDM0_RXDETECTOR3, rtlphy->framesync); -} - -void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; - rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; - rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; - rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; - - rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = - RFPGA0_XA_LSSIPARAMETER; - rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = - RFPGA0_XB_LSSIPARAMETER; - - rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = rFPGA0_XAB_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = rFPGA0_XAB_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER; - - rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; - rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; - rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; - rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; - - rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; - rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; - - rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; - rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; - - rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; - - rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; - - rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; - - rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBANLANCE; - rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; - - rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; - rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; - rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; - rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; - - rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE; - - rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; - rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; - rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE; - rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; - - rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK; - - rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK; - rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK; - -} -EXPORT_SYMBOL(_rtl92c_phy_init_bb_rf_register_definition); - -void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 txpwr_level; - long txpwr_dbm; - - txpwr_level = rtlphy->cur_cck_txpwridx; - txpwr_dbm = _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_B, - txpwr_level); - txpwr_level = rtlphy->cur_ofdm24g_txpwridx + - rtlefuse->legacy_ht_txpowerdiff; - if (_rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, - txpwr_level) > txpwr_dbm) - txpwr_dbm = - _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, - txpwr_level); - txpwr_level = rtlphy->cur_ofdm24g_txpwridx; - if (_rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, - txpwr_level) > txpwr_dbm) - txpwr_dbm = - _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, - txpwr_level); - *powerlevel = txpwr_dbm; -} - -static void _rtl92c_get_txpower_index(struct ieee80211_hw *hw, u8 channel, - u8 *cckpowerlevel, u8 *ofdmpowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 index = (channel - 1); - - cckpowerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_cck[RF90_PATH_A][index]; - cckpowerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_cck[RF90_PATH_B][index]; - if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) { - ofdmpowerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index]; - ofdmpowerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index]; - } else if (get_rf_type(rtlphy) == RF_2T2R) { - ofdmpowerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index]; - ofdmpowerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index]; - } -} - -static void _rtl92c_ccxpower_index_check(struct ieee80211_hw *hw, - u8 channel, u8 *cckpowerlevel, - u8 *ofdmpowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; - rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; -} - -void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 cckpowerlevel[2], ofdmpowerlevel[2]; - - if (!rtlefuse->txpwr_fromeprom) - return; - _rtl92c_get_txpower_index(hw, channel, - &cckpowerlevel[0], &ofdmpowerlevel[0]); - _rtl92c_ccxpower_index_check(hw, channel, &cckpowerlevel[0], - &ofdmpowerlevel[0]); - rtlpriv->cfg->ops->phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]); - rtlpriv->cfg->ops->phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], - channel); -} -EXPORT_SYMBOL(rtl92c_phy_set_txpower_level); - -bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 idx; - u8 rf_path; - u8 ccktxpwridx = _rtl92c_phy_dbm_to_txpwr_idx(hw, WIRELESS_MODE_B, - power_indbm); - u8 ofdmtxpwridx = _rtl92c_phy_dbm_to_txpwr_idx(hw, WIRELESS_MODE_N_24G, - power_indbm); - if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0) - ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff; - else - ofdmtxpwridx = 0; - RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE, - "%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n", - power_indbm, ccktxpwridx, ofdmtxpwridx); - for (idx = 0; idx < 14; idx++) { - for (rf_path = 0; rf_path < 2; rf_path++) { - rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx; - rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] = - ofdmtxpwridx; - rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] = - ofdmtxpwridx; - } - } - rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); - return true; -} -EXPORT_SYMBOL(rtl92c_phy_update_txpower_dbm); - -u8 _rtl92c_phy_dbm_to_txpwr_idx(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - long power_indbm) -{ - u8 txpwridx; - long offset; - - switch (wirelessmode) { - case WIRELESS_MODE_B: - offset = -7; - break; - case WIRELESS_MODE_G: - case WIRELESS_MODE_N_24G: - offset = -8; - break; - default: - offset = -8; - break; - } - - if ((power_indbm - offset) > 0) - txpwridx = (u8)((power_indbm - offset) * 2); - else - txpwridx = 0; - - if (txpwridx > MAX_TXPWR_IDX_NMODE_92S) - txpwridx = MAX_TXPWR_IDX_NMODE_92S; - - return txpwridx; -} -EXPORT_SYMBOL(_rtl92c_phy_dbm_to_txpwr_idx); - -long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - u8 txpwridx) -{ - long offset; - long pwrout_dbm; - - switch (wirelessmode) { - case WIRELESS_MODE_B: - offset = -7; - break; - case WIRELESS_MODE_G: - case WIRELESS_MODE_N_24G: - offset = -8; - break; - default: - offset = -8; - break; - } - pwrout_dbm = txpwridx / 2 + offset; - return pwrout_dbm; -} -EXPORT_SYMBOL(_rtl92c_phy_txpwr_idx_to_dbm); - -void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_bw = rtlphy->current_chan_bw; - - if (rtlphy->set_bwmode_inprogress) - return; - rtlphy->set_bwmode_inprogress = true; - if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtlpriv->cfg->ops->phy_set_bw_mode_callback(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "false driver sleep or unload\n"); - rtlphy->set_bwmode_inprogress = false; - rtlphy->current_chan_bw = tmp_bw; - } -} -EXPORT_SYMBOL(rtl92c_phy_set_bw_mode); - -void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 delay; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "switch to channel%d\n", rtlphy->current_channel); - if (is_hal_stop(rtlhal)) - return; - do { - if (!rtlphy->sw_chnl_inprogress) - break; - if (!_rtl92c_phy_sw_chnl_step_by_step - (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage, - &rtlphy->sw_chnl_step, &delay)) { - if (delay > 0) - mdelay(delay); - else - continue; - } else { - rtlphy->sw_chnl_inprogress = false; - } - break; - } while (true); - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); -} -EXPORT_SYMBOL(rtl92c_phy_sw_chnl_callback); - -u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (rtlphy->sw_chnl_inprogress) - return 0; - if (rtlphy->set_bwmode_inprogress) - return 0; - RT_ASSERT((rtlphy->current_channel <= 14), - "WIRELESS_MODE_G but channel>14"); - rtlphy->sw_chnl_inprogress = true; - rtlphy->sw_chnl_stage = 0; - rtlphy->sw_chnl_step = 0; - if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtl92c_phy_sw_chnl_callback(hw); - RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false schdule workitem\n"); - rtlphy->sw_chnl_inprogress = false; - } else { - RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false driver sleep or unload\n"); - rtlphy->sw_chnl_inprogress = false; - } - return 1; -} -EXPORT_SYMBOL(rtl92c_phy_sw_chnl); - -static void _rtl92c_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) { - if (channel == 6 && - rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { - rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, - MASKDWORD, 0x00255); - } else { - u32 backuprf0x1A = - (u32)rtl_get_rfreg(hw, RF90_PATH_A, RF_RX_G1, - RFREG_OFFSET_MASK); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, - backuprf0x1A); - } - } -} - -static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, u32 cmdtablesz, - enum swchnlcmd_id cmdid, - u32 para1, u32 para2, u32 msdelay) -{ - struct swchnlcmd *pcmd; - - if (cmdtable == NULL) { - RT_ASSERT(false, "cmdtable cannot be NULL.\n"); - return false; - } - - if (cmdtableidx >= cmdtablesz) - return false; - - pcmd = cmdtable + cmdtableidx; - pcmd->cmdid = cmdid; - pcmd->para1 = para1; - pcmd->para2 = para2; - pcmd->msdelay = msdelay; - return true; -} - -bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; - u32 precommoncmdcnt; - struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; - u32 postcommoncmdcnt; - struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; - u32 rfdependcmdcnt; - struct swchnlcmd *currentcmd = NULL; - u8 rfpath; - u8 num_total_rfpath = rtlphy->num_total_rfpath; - - precommoncmdcnt = 0; - _rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, - CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); - _rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); - - postcommoncmdcnt = 0; - - _rtl92c_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, - MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); - - rfdependcmdcnt = 0; - - RT_ASSERT((channel >= 1 && channel <= 14), - "illegal channel for Zebra: %d\n", channel); - - _rtl92c_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, - RF_CHNLBW, channel, 10); - - _rtl92c_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, - 0); - - do { - switch (*stage) { - case 0: - currentcmd = &precommoncmd[*step]; - break; - case 1: - currentcmd = &rfdependcmd[*step]; - break; - case 2: - currentcmd = &postcommoncmd[*step]; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Invalid 'stage' = %d, Check it!\n", *stage); - return true; - } - - if (currentcmd->cmdid == CMDID_END) { - if ((*stage) == 2) { - return true; - } else { - (*stage)++; - (*step) = 0; - continue; - } - } - - switch (currentcmd->cmdid) { - case CMDID_SET_TXPOWEROWER_LEVEL: - rtl92c_phy_set_txpower_level(hw, channel); - break; - case CMDID_WRITEPORT_ULONG: - rtl_write_dword(rtlpriv, currentcmd->para1, - currentcmd->para2); - break; - case CMDID_WRITEPORT_USHORT: - rtl_write_word(rtlpriv, currentcmd->para1, - (u16) currentcmd->para2); - break; - case CMDID_WRITEPORT_UCHAR: - rtl_write_byte(rtlpriv, currentcmd->para1, - (u8)currentcmd->para2); - break; - case CMDID_RF_WRITEREG: - for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { - rtlphy->rfreg_chnlval[rfpath] = - ((rtlphy->rfreg_chnlval[rfpath] & - 0xfffffc00) | currentcmd->para2); - - rtl_set_rfreg(hw, (enum radio_path)rfpath, - currentcmd->para1, - RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[rfpath]); - } - _rtl92c_phy_sw_rf_seting(hw, channel); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - - break; - } while (true); - - (*delay) = currentcmd->msdelay; - (*step)++; - return false; -} - -bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath) -{ - return true; -} -EXPORT_SYMBOL(rtl8192_phy_check_is_legal_rfpath); - -static u8 _rtl92c_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) -{ - u32 reg_eac, reg_e94, reg_e9c, reg_ea4; - u8 result = 0x00; - - rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f); - rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f); - rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102); - rtl_set_bbreg(hw, 0xe3c, MASKDWORD, - config_pathb ? 0x28160202 : 0x28160502); - - if (config_pathb) { - rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22); - rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22); - rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102); - rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202); - } - - rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1); - rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); - reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); - reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && - (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else - return result; - - if (!(reg_eac & BIT(27)) && - (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && - (((reg_eac & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - return result; -} - -static u8 _rtl92c_phy_path_b_iqk(struct ieee80211_hw *hw) -{ - u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; - u8 result = 0x00; - - rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002); - rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000); - mdelay(IQK_DELAY_TIME); - reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); - reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); - reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); - reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); - - if (!(reg_eac & BIT(31)) && - (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && - (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else - return result; - if (!(reg_eac & BIT(30)) && - (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && - (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - return result; -} - -static void _rtl92c_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, - bool b_iqk_ok, long result[][8], - u8 final_candidate, bool btxonly) -{ - u32 oldval_0, x, tx0_a, reg; - long y, tx0_c; - - if (final_candidate == 0xFF) { - return; - } else if (b_iqk_ok) { - oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, - MASKDWORD) >> 22) & 0x3FF; - x = result[final_candidate][0]; - if ((x & 0x00000200) != 0) - x = x | 0xFFFFFC00; - tx0_a = (x * oldval_0) >> 8; - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31), - ((x * oldval_0 >> 7) & 0x1)); - y = result[final_candidate][1]; - if ((y & 0x00000200) != 0) - y = y | 0xFFFFFC00; - tx0_c = (y * oldval_0) >> 8; - rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, - ((tx0_c & 0x3C0) >> 6)); - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000, - (tx0_c & 0x3F)); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29), - ((y * oldval_0 >> 7) & 0x1)); - if (btxonly) - return; - reg = result[final_candidate][2]; - rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg); - reg = result[final_candidate][3] & 0x3F; - rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg); - reg = (result[final_candidate][3] >> 6) & 0xF; - rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); - } -} - -static void _rtl92c_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw, - bool b_iqk_ok, long result[][8], - u8 final_candidate, bool btxonly) -{ - u32 oldval_1, x, tx1_a, reg; - long y, tx1_c; - - if (final_candidate == 0xFF) { - return; - } else if (b_iqk_ok) { - oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, - MASKDWORD) >> 22) & 0x3FF; - x = result[final_candidate][4]; - if ((x & 0x00000200) != 0) - x = x | 0xFFFFFC00; - tx1_a = (x * oldval_1) >> 8; - rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x3FF, tx1_a); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(27), - ((x * oldval_1 >> 7) & 0x1)); - y = result[final_candidate][5]; - if ((y & 0x00000200) != 0) - y = y | 0xFFFFFC00; - tx1_c = (y * oldval_1) >> 8; - rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000, - ((tx1_c & 0x3C0) >> 6)); - rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000, - (tx1_c & 0x3F)); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(25), - ((y * oldval_1 >> 7) & 0x1)); - if (btxonly) - return; - reg = result[final_candidate][6]; - rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg); - reg = result[final_candidate][7] & 0x3F; - rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg); - reg = (result[final_candidate][7] >> 6) & 0xF; - rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg); - } -} - -static void _rtl92c_phy_save_adda_registers(struct ieee80211_hw *hw, - u32 *addareg, u32 *addabackup, - u32 registernum) -{ - u32 i; - - for (i = 0; i < registernum; i++) - addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD); -} - -static void _rtl92c_phy_save_mac_registers(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) - macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); - macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); -} - -static void _rtl92c_phy_reload_adda_registers(struct ieee80211_hw *hw, - u32 *addareg, u32 *addabackup, - u32 regiesternum) -{ - u32 i; - - for (i = 0; i < regiesternum; i++) - rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]); -} - -static void _rtl92c_phy_reload_mac_registers(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) - rtl_write_byte(rtlpriv, macreg[i], (u8)macbackup[i]); - rtl_write_dword(rtlpriv, macreg[i], macbackup[i]); -} - -static void _rtl92c_phy_path_adda_on(struct ieee80211_hw *hw, - u32 *addareg, bool is_patha_on, bool is2t) -{ - u32 pathOn; - u32 i; - - pathOn = is_patha_on ? 0x04db25a4 : 0x0b1b25a4; - if (false == is2t) { - pathOn = 0x0bdb25a0; - rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0); - } else { - rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathOn); - } - - for (i = 1; i < IQK_ADDA_REG_NUM; i++) - rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathOn); -} - -static void _rtl92c_phy_mac_setting_calibration(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i = 0; - - rtl_write_byte(rtlpriv, macreg[i], 0x3F); - - for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) - rtl_write_byte(rtlpriv, macreg[i], - (u8)(macbackup[i] & (~BIT(3)))); - rtl_write_byte(rtlpriv, macreg[i], (u8)(macbackup[i] & (~BIT(5)))); -} - -static void _rtl92c_phy_path_a_standby(struct ieee80211_hw *hw) -{ - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); - rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); -} - -static void _rtl92c_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode) -{ - u32 mode; - - mode = pi_mode ? 0x01000100 : 0x01000000; - rtl_set_bbreg(hw, 0x820, MASKDWORD, mode); - rtl_set_bbreg(hw, 0x828, MASKDWORD, mode); -} - -static bool _rtl92c_phy_simularity_compare(struct ieee80211_hw *hw, - long result[][8], u8 c1, u8 c2) -{ - u32 i, j, diff, simularity_bitmap, bound; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - u8 final_candidate[2] = { 0xFF, 0xFF }; - bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version); - - if (is2t) - bound = 8; - else - bound = 4; - - simularity_bitmap = 0; - - for (i = 0; i < bound; i++) { - diff = (result[c1][i] > result[c2][i]) ? - (result[c1][i] - result[c2][i]) : - (result[c2][i] - result[c1][i]); - - if (diff > MAX_TOLERANCE) { - if ((i == 2 || i == 6) && !simularity_bitmap) { - if (result[c1][i] + result[c1][i + 1] == 0) - final_candidate[(i / 4)] = c2; - else if (result[c2][i] + result[c2][i + 1] == 0) - final_candidate[(i / 4)] = c1; - else - simularity_bitmap = simularity_bitmap | - (1 << i); - } else - simularity_bitmap = - simularity_bitmap | (1 << i); - } - } - - if (simularity_bitmap == 0) { - for (i = 0; i < (bound / 4); i++) { - if (final_candidate[i] != 0xFF) { - for (j = i * 4; j < (i + 1) * 4 - 2; j++) - result[3][j] = - result[final_candidate[i]][j]; - bresult = false; - } - } - return bresult; - } else if (!(simularity_bitmap & 0x0F)) { - for (i = 0; i < 4; i++) - result[3][i] = result[c1][i]; - return false; - } else if (!(simularity_bitmap & 0xF0) && is2t) { - for (i = 4; i < 8; i++) - result[3][i] = result[c1][i]; - return false; - } else { - return false; - } -} - -static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, - long result[][8], u8 t, bool is2t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 i; - u8 patha_ok, pathb_ok; - u32 adda_reg[IQK_ADDA_REG_NUM] = { - 0x85c, 0xe6c, 0xe70, 0xe74, - 0xe78, 0xe7c, 0xe80, 0xe84, - 0xe88, 0xe8c, 0xed0, 0xed4, - 0xed8, 0xedc, 0xee0, 0xeec - }; - u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { - 0x522, 0x550, 0x551, 0x040 - }; - const u32 retrycount = 2; - u32 bbvalue; - - if (t == 0) { - bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD); - - _rtl92c_phy_save_adda_registers(hw, adda_reg, - rtlphy->adda_backup, 16); - _rtl92c_phy_save_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - } - _rtl92c_phy_path_adda_on(hw, adda_reg, true, is2t); - if (t == 0) { - rtlphy->rfpi_enable = - (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, - BIT(8)); - } - - if (!rtlphy->rfpi_enable) - _rtl92c_phy_pi_mode_switch(hw, true); - if (t == 0) { - rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD); - rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD); - rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD); - } - rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); - rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); - rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); - if (is2t) { - rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); - rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); - } - _rtl92c_phy_mac_setting_calibration(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000); - if (is2t) - rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); - rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800); - for (i = 0; i < retrycount; i++) { - patha_ok = _rtl92c_phy_path_a_iqk(hw, is2t); - if (patha_ok == 0x03) { - result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & - 0x3FF0000) >> 16; - break; - } else if (i == (retrycount - 1) && patha_ok == 0x01) - - result[t][0] = (rtl_get_bbreg(hw, 0xe94, - MASKDWORD) & 0x3FF0000) >> - 16; - result[t][1] = - (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16; - - } - - if (is2t) { - _rtl92c_phy_path_a_standby(hw); - _rtl92c_phy_path_adda_on(hw, adda_reg, false, is2t); - for (i = 0; i < retrycount; i++) { - pathb_ok = _rtl92c_phy_path_b_iqk(hw); - if (pathb_ok == 0x03) { - result[t][4] = (rtl_get_bbreg(hw, - 0xeb4, - MASKDWORD) & - 0x3FF0000) >> 16; - result[t][5] = - (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][6] = - (rtl_get_bbreg(hw, 0xec4, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][7] = - (rtl_get_bbreg(hw, 0xecc, MASKDWORD) & - 0x3FF0000) >> 16; - break; - } else if (i == (retrycount - 1) && pathb_ok == 0x01) { - result[t][4] = (rtl_get_bbreg(hw, - 0xeb4, - MASKDWORD) & - 0x3FF0000) >> 16; - } - result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & - 0x3FF0000) >> 16; - } - } - rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04); - rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874); - rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); - rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); - if (is2t) - rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); - if (t != 0) { - if (!rtlphy->rfpi_enable) - _rtl92c_phy_pi_mode_switch(hw, false); - _rtl92c_phy_reload_adda_registers(hw, adda_reg, - rtlphy->adda_backup, 16); - _rtl92c_phy_reload_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - } -} - -static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, - char delta, bool is2t) -{ -} - -static void _rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, - bool bmain, bool is2t) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (is_hal_stop(rtlhal)) { - rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01); - rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); - } - if (is2t) { - if (bmain) - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(5) | BIT(6), 0x1); - else - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(5) | BIT(6), 0x2); - } else { - if (bmain) - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2); - else - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1); - } -} - -#undef IQK_ADDA_REG_NUM -#undef IQK_DELAY_TIME - -void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - long result[4][8]; - u8 i, final_candidate; - bool b_patha_ok, b_pathb_ok; - long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, - reg_ecc, reg_tmp = 0; - bool is12simular, is13simular, is23simular; - u32 iqk_bb_reg[10] = { - ROFDM0_XARXIQIMBALANCE, - ROFDM0_XBRXIQIMBALANCE, - ROFDM0_ECCATHRESHOLD, - ROFDM0_AGCRSSITABLE, - ROFDM0_XATXIQIMBALANCE, - ROFDM0_XBTXIQIMBALANCE, - ROFDM0_XCTXIQIMBALANCE, - ROFDM0_XCTXAFE, - ROFDM0_XDTXAFE, - ROFDM0_RXIQEXTANTA - }; - - if (b_recovery) { - _rtl92c_phy_reload_adda_registers(hw, - iqk_bb_reg, - rtlphy->iqk_bb_backup, 10); - return; - } - for (i = 0; i < 8; i++) { - result[0][i] = 0; - result[1][i] = 0; - result[2][i] = 0; - result[3][i] = 0; - } - final_candidate = 0xff; - b_patha_ok = false; - b_pathb_ok = false; - is12simular = false; - is23simular = false; - is13simular = false; - for (i = 0; i < 3; i++) { - if (IS_92C_SERIAL(rtlhal->version)) - _rtl92c_phy_iq_calibrate(hw, result, i, true); - else - _rtl92c_phy_iq_calibrate(hw, result, i, false); - if (i == 1) { - is12simular = _rtl92c_phy_simularity_compare(hw, - result, 0, - 1); - if (is12simular) { - final_candidate = 0; - break; - } - } - if (i == 2) { - is13simular = _rtl92c_phy_simularity_compare(hw, - result, 0, - 2); - if (is13simular) { - final_candidate = 0; - break; - } - is23simular = _rtl92c_phy_simularity_compare(hw, - result, 1, - 2); - if (is23simular) - final_candidate = 1; - else { - for (i = 0; i < 8; i++) - reg_tmp += result[3][i]; - - if (reg_tmp != 0) - final_candidate = 3; - else - final_candidate = 0xFF; - } - } - } - for (i = 0; i < 4; i++) { - reg_e94 = result[i][0]; - reg_e9c = result[i][1]; - reg_ea4 = result[i][2]; - reg_eac = result[i][3]; - reg_eb4 = result[i][4]; - reg_ebc = result[i][5]; - reg_ec4 = result[i][6]; - reg_ecc = result[i][7]; - } - if (final_candidate != 0xff) { - rtlphy->reg_e94 = reg_e94 = result[final_candidate][0]; - rtlphy->reg_e9c = reg_e9c = result[final_candidate][1]; - reg_ea4 = result[final_candidate][2]; - reg_eac = result[final_candidate][3]; - rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4]; - rtlphy->reg_ebc = reg_ebc = result[final_candidate][5]; - reg_ec4 = result[final_candidate][6]; - reg_ecc = result[final_candidate][7]; - b_patha_ok = true; - b_pathb_ok = true; - } else { - rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; - rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0; - } - if (reg_e94 != 0) /*&&(reg_ea4 != 0) */ - _rtl92c_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result, - final_candidate, - (reg_ea4 == 0)); - if (IS_92C_SERIAL(rtlhal->version)) { - if (reg_eb4 != 0) /*&&(reg_ec4 != 0) */ - _rtl92c_phy_path_b_fill_iqk_matrix(hw, b_pathb_ok, - result, - final_candidate, - (reg_ec4 == 0)); - } - _rtl92c_phy_save_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, 10); -} -EXPORT_SYMBOL(rtl92c_phy_iq_calibrate); - -void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (IS_92C_SERIAL(rtlhal->version)) - rtlpriv->cfg->ops->phy_lc_calibrate(hw, true); - else - rtlpriv->cfg->ops->phy_lc_calibrate(hw, false); -} -EXPORT_SYMBOL(rtl92c_phy_lc_calibrate); - -void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (rtlphy->apk_done) - return; - if (IS_92C_SERIAL(rtlhal->version)) - _rtl92c_phy_ap_calibrate(hw, delta, true); - else - _rtl92c_phy_ap_calibrate(hw, delta, false); -} -EXPORT_SYMBOL(rtl92c_phy_ap_calibrate); - -void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (IS_92C_SERIAL(rtlhal->version)) - _rtl92c_phy_set_rfpath_switch(hw, bmain, true); - else - _rtl92c_phy_set_rfpath_switch(hw, bmain, false); -} -EXPORT_SYMBOL(rtl92c_phy_set_rfpath_switch); - -bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - bool postprocessing = false; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "-->IO Cmd(%#x), set_io_inprogress(%d)\n", - iotype, rtlphy->set_io_inprogress); - do { - switch (iotype) { - case IO_CMD_RESUME_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Resume DM after scan.\n"); - postprocessing = true; - break; - case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Pause DM before scan.\n"); - postprocessing = true; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - } while (false); - if (postprocessing && !rtlphy->set_io_inprogress) { - rtlphy->set_io_inprogress = true; - rtlphy->current_io_type = iotype; - } else { - return false; - } - rtl92c_phy_set_io(hw); - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); - return true; -} -EXPORT_SYMBOL(rtl92c_phy_set_io_cmd); - -void rtl92c_phy_set_io(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "--->Cmd(%#x), set_io_inprogress(%d)\n", - rtlphy->current_io_type, rtlphy->set_io_inprogress); - switch (rtlphy->current_io_type) { - case IO_CMD_RESUME_DM_BY_SCAN: - dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; - rtl92c_dm_write_dig(hw); - rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); - break; - case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: - rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; - dm_digtable->cur_igvalue = 0x17; - rtl92c_dm_write_dig(hw); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - rtlphy->set_io_inprogress = false; - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "(%#x)\n", rtlphy->current_io_type); -} -EXPORT_SYMBOL(rtl92c_phy_set_io); - -void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); -} -EXPORT_SYMBOL(rtl92ce_phy_set_rf_on); - -void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw) -{ - u32 u4b_tmp; - u8 delay = 5; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); - u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); - while (u4b_tmp != 0 && delay > 0) { - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); - u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); - delay--; - } - if (delay == 0) { - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "Switch RF timeout !!!.\n"); - return; - } - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); -} -EXPORT_SYMBOL(_rtl92c_phy_set_rf_sleep); diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h deleted file mode 100644 index 64bc49f4dbc6..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h +++ /dev/null @@ -1,254 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_PHY_COMMON_H__ -#define __RTL92C_PHY_COMMON_H__ - -#define MAX_PRECMD_CNT 16 -#define MAX_RFDEPENDCMD_CNT 16 -#define MAX_POSTCMD_CNT 16 - -#define MAX_DOZE_WAITING_TIMES_9x 64 - -#define RT_CANNOT_IO(hw) false -#define HIGHPOWER_RADIOA_ARRAYLEN 22 - -#define MAX_TOLERANCE 5 - -#define APK_BB_REG_NUM 5 -#define APK_AFE_REG_NUM 16 -#define APK_CURVE_REG_NUM 4 -#define PATH_NUM 2 - -#define LOOP_LIMIT 5 -#define MAX_STALL_TIME 50 -#define AntennaDiversityValue 0x80 -#define MAX_TXPWR_IDX_NMODE_92S 63 -#define Reset_Cnt_Limit 3 - -#define IQK_ADDA_REG_NUM 16 -#define IQK_MAC_REG_NUM 4 - -#define IQK_DELAY_TIME 1 -#define RF90_PATH_MAX 2 - -#define CT_OFFSET_MAC_ADDR 0X16 - -#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A -#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 -#define CT_OFFSET_HT402S_TX_PWR_IDX_DIF 0x66 -#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 -#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C - -#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F -#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 - -#define CT_OFFSET_CHANNEL_PLAH 0x75 -#define CT_OFFSET_THERMAL_METER 0x78 -#define CT_OFFSET_RF_OPTION 0x79 -#define CT_OFFSET_VERSION 0x7E -#define CT_OFFSET_CUSTOMER_ID 0x7F - -#define RTL92C_MAX_PATH_NUM 2 -#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 - -enum swchnlcmd_id { - CMDID_END, - CMDID_SET_TXPOWEROWER_LEVEL, - CMDID_BBREGWRITE10, - CMDID_WRITEPORT_ULONG, - CMDID_WRITEPORT_USHORT, - CMDID_WRITEPORT_UCHAR, - CMDID_RF_WRITEREG, -}; - -struct swchnlcmd { - enum swchnlcmd_id cmdid; - u32 para1; - u32 para2; - u32 msdelay; -}; - -enum hw90_block_e { - HW90_BLOCK_MAC = 0, - HW90_BLOCK_PHY0 = 1, - HW90_BLOCK_PHY1 = 2, - HW90_BLOCK_RF = 3, - HW90_BLOCK_MAXIMUM = 4, -}; - -enum baseband_config_type { - BASEBAND_CONFIG_PHY_REG = 0, - BASEBAND_CONFIG_AGC_TAB = 1, -}; - -enum ra_offset_area { - RA_OFFSET_LEGACY_OFDM1, - RA_OFFSET_LEGACY_OFDM2, - RA_OFFSET_HT_OFDM1, - RA_OFFSET_HT_OFDM2, - RA_OFFSET_HT_OFDM3, - RA_OFFSET_HT_OFDM4, - RA_OFFSET_HT_CCK, -}; - -enum antenna_path { - ANTENNA_NONE, - ANTENNA_D, - ANTENNA_C, - ANTENNA_CD, - ANTENNA_B, - ANTENNA_BD, - ANTENNA_BC, - ANTENNA_BCD, - ANTENNA_A, - ANTENNA_AD, - ANTENNA_AC, - ANTENNA_ACD, - ANTENNA_AB, - ANTENNA_ABD, - ANTENNA_ABC, - ANTENNA_ABCD -}; - -struct r_antenna_select_ofdm { - u32 r_tx_antenna:4; - u32 r_ant_l:4; - u32 r_ant_non_ht:4; - u32 r_ant_ht1:4; - u32 r_ant_ht2:4; - u32 r_ant_ht_s1:4; - u32 r_ant_non_ht_s1:4; - u32 ofdm_txsc:2; - u32 reserved:2; -}; - -struct r_antenna_select_cck { - u8 r_cckrx_enable_2:2; - u8 r_cckrx_enable:2; - u8 r_ccktx_enable:4; -}; - -struct efuse_contents { - u8 mac_addr[ETH_ALEN]; - u8 cck_tx_power_idx[6]; - u8 ht40_1s_tx_power_idx[6]; - u8 ht40_2s_tx_power_idx_diff[3]; - u8 ht20_tx_power_idx_diff[3]; - u8 ofdm_tx_power_idx_diff[3]; - u8 ht40_max_power_offset[3]; - u8 ht20_max_power_offset[3]; - u8 channel_plan; - u8 thermal_meter; - u8 rf_option[5]; - u8 version; - u8 oem_id; - u8 regulatory; -}; - -struct tx_power_struct { - u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 legacy_ht_txpowerdiff; - u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 pwrgroup_cnt; - u32 mcs_original_offset[4][16]; -}; - -u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask); -void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, u32 data); -u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask); -bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); -bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); -bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); -bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, - long *powerlevel); -void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, - long power_indbm); -void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); -void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); -u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); -void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, - u16 beaconinterval); -void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); -void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); -void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); -bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, - u32 rfpath); -bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); -void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw); -void rtl92c_phy_set_io(struct ieee80211_hw *hw); -void rtl92c_bb_block_on(struct ieee80211_hw *hw); -u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask); -long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - u8 txpwridx); -u8 _rtl92c_phy_dbm_to_txpwr_idx(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - long power_indbm); -void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); -void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); -bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay); -u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw); -u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset); -void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data); -u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset); -void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data); -bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); -void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, - u32 data); -bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile b/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile deleted file mode 100644 index c0cb0cfe7d37..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -rtl8192ce-objs := \ - dm.o \ - hw.o \ - led.o \ - phy.o \ - rf.o \ - sw.o \ - table.o \ - trx.o - -obj-$(CONFIG_RTL8192CE) += rtl8192ce.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h deleted file mode 100644 index 690a7a1675e2..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ /dev/null @@ -1,197 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_DEF_H__ -#define __RTL92C_DEF_H__ - -#define PHY_RSSI_SLID_WIN_MAX 100 -#define PHY_LINKQUALITY_SLID_WIN_MAX 20 -#define PHY_BEACON_RSSI_SLID_WIN_MAX 10 - -#define RX_SMOOTH_FACTOR 20 - -#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 -#define HAL_PRIME_CHNL_OFFSET_LOWER 1 -#define HAL_PRIME_CHNL_OFFSET_UPPER 2 - -#define RX_MPDU_QUEUE 0 -#define RX_CMD_QUEUE 1 - -#define C2H_RX_CMD_HDR_LEN 8 -#define GET_C2H_CMD_CMD_LEN(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 0, 16) -#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 16, 8) -#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 24, 7) -#define GET_C2H_CMD_CONTINUE(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 31, 1) -#define GET_C2H_CMD_CONTENT(__prxhdr) \ - ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) - -#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) -#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) -#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) -#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) -#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) -#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) -#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) -#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) -#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) -#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32) - -#define CHIP_VER_B BIT(4) -#define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3) -#define CHIP_BONDING_92C_1T2R 0x1 -#define RF_TYPE_1T2R BIT(1) -#define CHIP_92C_BITMASK BIT(0) -#define CHIP_UNKNOWN BIT(7) -#define CHIP_92C_1T2R 0x03 -#define CHIP_92C 0x01 -#define CHIP_88C 0x00 - -enum version_8192c { - VERSION_A_CHIP_92C = 0x01, - VERSION_A_CHIP_88C = 0x00, - VERSION_B_CHIP_92C = 0x11, - VERSION_B_CHIP_88C = 0x10, - VERSION_TEST_CHIP_88C = 0x00, - VERSION_TEST_CHIP_92C = 0x01, - VERSION_NORMAL_TSMC_CHIP_88C = 0x10, - VERSION_NORMAL_TSMC_CHIP_92C = 0x11, - VERSION_NORMAL_TSMC_CHIP_92C_1T2R = 0x13, - VERSION_NORMAL_UMC_CHIP_88C_A_CUT = 0x30, - VERSION_NORMAL_UMC_CHIP_92C_A_CUT = 0x31, - VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT = 0x33, - VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT = 0x34, - VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT = 0x3c, - VERSION_NORMAL_UMC_CHIP_88C_B_CUT = 0x70, - VERSION_NORMAL_UMC_CHIP_92C_B_CUT = 0x71, - VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT = 0x73, - VERSION_UNKNOWN = 0x88, -}; - -enum rtl819x_loopback_e { - RTL819X_NO_LOOPBACK = 0, - RTL819X_MAC_LOOPBACK = 1, - RTL819X_DMA_LOOPBACK = 2, - RTL819X_CCK_LOOPBACK = 3, -}; - -enum rf_optype { - RF_OP_BY_SW_3WIRE = 0, - RF_OP_BY_FW, - RF_OP_MAX -}; - -enum rf_power_state { - RF_ON, - RF_OFF, - RF_SLEEP, - RF_SHUT_DOWN, -}; - -enum power_save_mode { - POWER_SAVE_MODE_ACTIVE, - POWER_SAVE_MODE_SAVE, -}; - -enum power_polocy_config { - POWERCFG_MAX_POWER_SAVINGS, - POWERCFG_GLOBAL_POWER_SAVINGS, - POWERCFG_LOCAL_POWER_SAVINGS, - POWERCFG_LENOVO, -}; - -enum interface_select_pci { - INTF_SEL1_MINICARD = 0, - INTF_SEL0_PCIE = 1, - INTF_SEL2_RSV = 2, - INTF_SEL3_RSV = 3, -}; - -enum hal_fw_c2h_cmd_id { - HAL_FW_C2H_CMD_Read_MACREG = 0, - HAL_FW_C2H_CMD_Read_BBREG = 1, - HAL_FW_C2H_CMD_Read_RFREG = 2, - HAL_FW_C2H_CMD_Read_EEPROM = 3, - HAL_FW_C2H_CMD_Read_EFUSE = 4, - HAL_FW_C2H_CMD_Read_CAM = 5, - HAL_FW_C2H_CMD_Get_BasicRate = 6, - HAL_FW_C2H_CMD_Get_DataRate = 7, - HAL_FW_C2H_CMD_Survey = 8, - HAL_FW_C2H_CMD_SurveyDone = 9, - HAL_FW_C2H_CMD_JoinBss = 10, - HAL_FW_C2H_CMD_AddSTA = 11, - HAL_FW_C2H_CMD_DelSTA = 12, - HAL_FW_C2H_CMD_AtimDone = 13, - HAL_FW_C2H_CMD_TX_Report = 14, - HAL_FW_C2H_CMD_CCX_Report = 15, - HAL_FW_C2H_CMD_DTM_Report = 16, - HAL_FW_C2H_CMD_TX_Rate_Statistics = 17, - HAL_FW_C2H_CMD_C2HLBK = 18, - HAL_FW_C2H_CMD_C2HDBG = 19, - HAL_FW_C2H_CMD_C2HFEEDBACK = 20, - HAL_FW_C2H_CMD_MAX -}; - -enum rtl_desc_qsel { - QSLT_BK = 0x2, - QSLT_BE = 0x0, - QSLT_VI = 0x5, - QSLT_VO = 0x7, - QSLT_BEACON = 0x10, - QSLT_HIGH = 0x11, - QSLT_MGNT = 0x12, - QSLT_CMD = 0x13, -}; - -struct phy_sts_cck_8192s_t { - u8 adc_pwdb_X[4]; - u8 sq_rpt; - u8 cck_agc_rpt; -}; - -struct h2c_cmd_8192c { - u8 element_id; - u32 cmd_len; - u8 *p_cmdbuffer; -}; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c deleted file mode 100644 index 09898cf2e07a..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c +++ /dev/null @@ -1,110 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../base.h" -#include "../pci.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "../rtl8192c/fw_common.h" - -void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long undec_sm_pwdb; - - if (!rtlpriv->dm.dynamic_txpower_enable) - return; - - if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - - if ((mac->link_state < MAC80211_LINKED) && - (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "Not connected to any\n"); - - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - - rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - - if (mac->link_state >= MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Client PWDB = 0x%lx\n", - undec_sm_pwdb); - } else { - undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "STA Default Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - } else { - undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Ext Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - - if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); - } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && - (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) { - - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); - } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_NORMAL\n"); - } - - if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "PHY_SetTxPowerLevel8192S() Channel = %d\n", - rtlphy->current_channel); - rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); - } - - rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h deleted file mode 100644 index 38ba707015f5..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h +++ /dev/null @@ -1,86 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_DM_H__ -#define __RTL92C_DM_H__ - -#define HAL_DM_DIG_DISABLE BIT(0) -#define HAL_DM_HIPWR_DISABLE BIT(1) - -#define OFDM_TABLE_LENGTH 37 -#define CCK_TABLE_LENGTH 33 - -#define OFDM_TABLE_SIZE 37 -#define CCK_TABLE_SIZE 33 - -#define BW_AUTO_SWITCH_HIGH_LOW 25 -#define BW_AUTO_SWITCH_LOW_HIGH 30 - -#define DM_DIG_FA_UPPER 0x32 -#define DM_DIG_FA_LOWER 0x20 -#define DM_DIG_FA_TH0 0x20 -#define DM_DIG_FA_TH1 0x100 -#define DM_DIG_FA_TH2 0x200 - -#define RXPATHSELECTION_SS_TH_lOW 30 -#define RXPATHSELECTION_DIFF_TH 18 - -#define DM_RATR_STA_INIT 0 -#define DM_RATR_STA_HIGH 1 -#define DM_RATR_STA_MIDDLE 2 -#define DM_RATR_STA_LOW 3 - -#define CTS2SELF_THVAL 30 -#define REGC38_TH 20 - -#define WAIOTTHVal 25 - -#define TXHIGHPWRLEVEL_NORMAL 0 -#define TXHIGHPWRLEVEL_LEVEL1 1 -#define TXHIGHPWRLEVEL_LEVEL2 2 -#define TXHIGHPWRLEVEL_BT1 3 -#define TXHIGHPWRLEVEL_BT2 4 - -#define DM_TYPE_BYFW 0 -#define DM_TYPE_BYDRIVER 1 - -#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 -#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 - -void rtl92c_dm_init(struct ieee80211_hw *hw); -void rtl92c_dm_watchdog(struct ieee80211_hw *hw); -void rtl92c_dm_write_dig(struct ieee80211_hw *hw); -void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw); -void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw); -void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); -void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); -void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw); -void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c deleted file mode 100644 index 04eb5c3f8464..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ /dev/null @@ -1,2426 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../efuse.h" -#include "../base.h" -#include "../regd.h" -#include "../cam.h" -#include "../ps.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "../rtl8192c/dm_common.h" -#include "../rtl8192c/fw_common.h" -#include "../rtl8192c/phy_common.h" -#include "dm.h" -#include "led.h" -#include "hw.h" - -#define LLT_CONFIG 5 - -static void _rtl92ce_set_bcn_ctrl_reg(struct ieee80211_hw *hw, - u8 set_bits, u8 clear_bits) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpci->reg_bcn_ctrl_val |= set_bits; - rtlpci->reg_bcn_ctrl_val &= ~clear_bits; - - rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); -} - -static void _rtl92ce_stop_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp1byte; - - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); -} - -static void _rtl92ce_resume_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp1byte; - - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte |= BIT(0); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); -} - -static void _rtl92ce_enable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(1)); -} - -static void _rtl92ce_disable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl92ce_set_bcn_ctrl_reg(hw, BIT(1), 0); -} - -void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - switch (variable) { - case HW_VAR_RCR: - *((u32 *) (val)) = rtlpci->receive_config; - break; - case HW_VAR_RF_STATE: - *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; - break; - case HW_VAR_FWLPS_RF_ON:{ - enum rf_pwrstate rfState; - u32 val_rcr; - - rtlpriv->cfg->ops->get_hw_reg(hw, - HW_VAR_RF_STATE, - (u8 *) (&rfState)); - if (rfState == ERFOFF) { - *((bool *) (val)) = true; - } else { - val_rcr = rtl_read_dword(rtlpriv, REG_RCR); - val_rcr &= 0x00070000; - if (val_rcr) - *((bool *) (val)) = false; - else - *((bool *) (val)) = true; - } - break; - } - case HW_VAR_FW_PSMODE_STATUS: - *((bool *) (val)) = ppsc->fw_current_inpsmode; - break; - case HW_VAR_CORRECT_TSF:{ - u64 tsf; - u32 *ptsf_low = (u32 *)&tsf; - u32 *ptsf_high = ((u32 *)&tsf) + 1; - - *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); - *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - - *((u64 *) (val)) = tsf; - - break; - } - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } -} - -void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 idx; - - switch (variable) { - case HW_VAR_ETHER_ADDR:{ - for (idx = 0; idx < ETH_ALEN; idx++) { - rtl_write_byte(rtlpriv, (REG_MACID + idx), - val[idx]); - } - break; - } - case HW_VAR_BASIC_RATE:{ - u16 rate_cfg = ((u16 *) val)[0]; - u8 rate_index = 0; - rate_cfg &= 0x15f; - rate_cfg |= 0x01; - rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); - rtl_write_byte(rtlpriv, REG_RRSR + 1, - (rate_cfg >> 8) & 0xff); - while (rate_cfg > 0x1) { - rate_cfg = (rate_cfg >> 1); - rate_index++; - } - rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, - rate_index); - break; - } - case HW_VAR_BSSID:{ - for (idx = 0; idx < ETH_ALEN; idx++) { - rtl_write_byte(rtlpriv, (REG_BSSID + idx), - val[idx]); - } - break; - } - case HW_VAR_SIFS:{ - rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); - rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); - - rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); - rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); - - if (!mac->ht_enable) - rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, - 0x0e0e); - else - rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, - *((u16 *) val)); - break; - } - case HW_VAR_SLOT_TIME:{ - u8 e_aci; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "HW_VAR_SLOT_TIME %x\n", val[0]); - - rtl_write_byte(rtlpriv, REG_SLOT, val[0]); - - for (e_aci = 0; e_aci < AC_MAX; e_aci++) { - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AC_PARAM, - &e_aci); - } - break; - } - case HW_VAR_ACK_PREAMBLE:{ - u8 reg_tmp; - u8 short_preamble = (bool)*val; - reg_tmp = (mac->cur_40_prime_sc) << 5; - if (short_preamble) - reg_tmp |= 0x80; - - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp); - break; - } - case HW_VAR_AMPDU_MIN_SPACE:{ - u8 min_spacing_to_set; - u8 sec_min_space; - - min_spacing_to_set = *val; - if (min_spacing_to_set <= 7) { - sec_min_space = 0; - - if (min_spacing_to_set < sec_min_space) - min_spacing_to_set = sec_min_space; - - mac->min_space_cfg = ((mac->min_space_cfg & - 0xf8) | - min_spacing_to_set); - - *val = min_spacing_to_set; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", - mac->min_space_cfg); - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - } - break; - } - case HW_VAR_SHORTGI_DENSITY:{ - u8 density_to_set; - - density_to_set = *val; - mac->min_space_cfg |= (density_to_set << 3); - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_SHORTGI_DENSITY: %#x\n", - mac->min_space_cfg); - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - - break; - } - case HW_VAR_AMPDU_FACTOR:{ - u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9}; - u8 regtoset_bt[4] = {0x31, 0x74, 0x42, 0x97}; - - u8 factor_toset; - u8 *p_regtoset = NULL; - u8 index = 0; - - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - (rtlpcipriv->bt_coexist.bt_coexist_type == - BT_CSR_BC4)) - p_regtoset = regtoset_bt; - else - p_regtoset = regtoset_normal; - - factor_toset = *(val); - if (factor_toset <= 3) { - factor_toset = (1 << (factor_toset + 2)); - if (factor_toset > 0xf) - factor_toset = 0xf; - - for (index = 0; index < 4; index++) { - if ((p_regtoset[index] & 0xf0) > - (factor_toset << 4)) - p_regtoset[index] = - (p_regtoset[index] & 0x0f) | - (factor_toset << 4); - - if ((p_regtoset[index] & 0x0f) > - factor_toset) - p_regtoset[index] = - (p_regtoset[index] & 0xf0) | - (factor_toset); - - rtl_write_byte(rtlpriv, - (REG_AGGLEN_LMT + index), - p_regtoset[index]); - - } - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_FACTOR: %#x\n", - factor_toset); - } - break; - } - case HW_VAR_AC_PARAM:{ - u8 e_aci = *(val); - rtl92c_dm_init_edca_turbo(hw); - - if (rtlpci->acm_method != EACMWAY2_SW) - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_ACM_CTRL, - (&e_aci)); - break; - } - case HW_VAR_ACM_CTRL:{ - u8 e_aci = *(val); - union aci_aifsn *p_aci_aifsn = - (union aci_aifsn *)(&(mac->ac[0].aifs)); - u8 acm = p_aci_aifsn->f.acm; - u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); - - acm_ctrl = - acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); - - if (acm) { - switch (e_aci) { - case AC0_BE: - acm_ctrl |= AcmHw_BeqEn; - break; - case AC2_VI: - acm_ctrl |= AcmHw_ViqEn; - break; - case AC3_VO: - acm_ctrl |= AcmHw_VoqEn; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", - acm); - break; - } - } else { - switch (e_aci) { - case AC0_BE: - acm_ctrl &= (~AcmHw_BeqEn); - break; - case AC2_VI: - acm_ctrl &= (~AcmHw_ViqEn); - break; - case AC3_VO: - acm_ctrl &= (~AcmHw_VoqEn); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - } - - RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, - "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", - acm_ctrl); - rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); - break; - } - case HW_VAR_RCR:{ - rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]); - rtlpci->receive_config = ((u32 *) (val))[0]; - break; - } - case HW_VAR_RETRY_LIMIT:{ - u8 retry_limit = val[0]; - - rtl_write_word(rtlpriv, REG_RL, - retry_limit << RETRY_LIMIT_SHORT_SHIFT | - retry_limit << RETRY_LIMIT_LONG_SHIFT); - break; - } - case HW_VAR_DUAL_TSF_RST: - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); - break; - case HW_VAR_EFUSE_BYTES: - rtlefuse->efuse_usedbytes = *((u16 *) val); - break; - case HW_VAR_EFUSE_USAGE: - rtlefuse->efuse_usedpercentage = *val; - break; - case HW_VAR_IO_CMD: - rtl92c_phy_set_io_cmd(hw, (*(enum io_type *)val)); - break; - case HW_VAR_WPA_CONFIG: - rtl_write_byte(rtlpriv, REG_SECCFG, *val); - break; - case HW_VAR_SET_RPWM:{ - u8 rpwm_val; - - rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); - udelay(1); - - if (rpwm_val & BIT(7)) { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, *val); - } else { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, - *val | BIT(7)); - } - - break; - } - case HW_VAR_H2C_FW_PWRMODE:{ - u8 psmode = *val; - - if ((psmode != FW_PS_ACTIVE_MODE) && - (!IS_92C_SERIAL(rtlhal->version))) { - rtl92c_dm_rf_saving(hw, true); - } - - rtl92c_set_fw_pwrmode_cmd(hw, *val); - break; - } - case HW_VAR_FW_PSMODE_STATUS: - ppsc->fw_current_inpsmode = *((bool *) val); - break; - case HW_VAR_H2C_FW_JOINBSSRPT:{ - u8 mstatus = *val; - u8 tmp_regcr, tmp_reg422; - bool recover = false; - - if (mstatus == RT_MEDIA_CONNECT) { - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, - NULL); - - tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, - (tmp_regcr | BIT(0))); - - _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(3)); - _rtl92ce_set_bcn_ctrl_reg(hw, BIT(4), 0); - - tmp_reg422 = - rtl_read_byte(rtlpriv, - REG_FWHW_TXQ_CTRL + 2); - if (tmp_reg422 & BIT(6)) - recover = true; - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, - tmp_reg422 & (~BIT(6))); - - rtl92c_set_fw_rsvdpagepkt(hw, NULL); - - _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); - _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); - - if (recover) { - rtl_write_byte(rtlpriv, - REG_FWHW_TXQ_CTRL + 2, - tmp_reg422); - } - - rtl_write_byte(rtlpriv, REG_CR + 1, - (tmp_regcr & ~(BIT(0)))); - } - rtl92c_set_fw_joinbss_report_cmd(hw, *val); - - break; - } - case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: - rtl92c_set_p2p_ps_offload_cmd(hw, *val); - break; - case HW_VAR_AID:{ - u16 u2btmp; - u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); - u2btmp &= 0xC000; - rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | - mac->assoc_id)); - - break; - } - case HW_VAR_CORRECT_TSF:{ - u8 btype_ibss = val[0]; - - if (btype_ibss) - _rtl92ce_stop_tx_beacon(hw); - - _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(3)); - - rtl_write_dword(rtlpriv, REG_TSFTR, - (u32) (mac->tsf & 0xffffffff)); - rtl_write_dword(rtlpriv, REG_TSFTR + 4, - (u32) ((mac->tsf >> 32) & 0xffffffff)); - - _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); - - if (btype_ibss) - _rtl92ce_resume_tx_beacon(hw); - - break; - - } - case HW_VAR_FW_LPS_ACTION: { - bool enter_fwlps = *((bool *)val); - u8 rpwm_val, fw_pwrmode; - bool fw_current_inps; - - if (enter_fwlps) { - rpwm_val = 0x02; /* RF off */ - fw_current_inps = true; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_PWRMODE, - &ppsc->fwctrl_psmode); - - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_SET_RPWM, - &rpwm_val); - } else { - rpwm_val = 0x0C; /* RF on */ - fw_pwrmode = FW_PS_ACTIVE_MODE; - fw_current_inps = false; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_SET_RPWM, - &rpwm_val); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_PWRMODE, - &fw_pwrmode); - - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - } - break; } - case HW_VAR_KEEP_ALIVE: { - u8 array[2]; - - array[0] = 0xff; - array[1] = *((u8 *)val); - rtl92c_fill_h2c_cmd(hw, H2C_92C_KEEP_ALIVE_CTRL, 2, array); - break; } - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case %d not processed\n", variable); - break; - } -} - -static bool _rtl92ce_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool status = true; - long count = 0; - u32 value = _LLT_INIT_ADDR(address) | - _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); - - rtl_write_dword(rtlpriv, REG_LLT_INIT, value); - - do { - value = rtl_read_dword(rtlpriv, REG_LLT_INIT); - if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) - break; - - if (count > POLLING_LLT_THRESHOLD) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to polling write LLT done at address %d!\n", - address); - status = false; - break; - } - } while (++count); - - return status; -} - -static bool _rtl92ce_llt_table_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - unsigned short i; - u8 txpktbuf_bndy; - u8 maxPage; - bool status; - -#if LLT_CONFIG == 1 - maxPage = 255; - txpktbuf_bndy = 252; -#elif LLT_CONFIG == 2 - maxPage = 127; - txpktbuf_bndy = 124; -#elif LLT_CONFIG == 3 - maxPage = 255; - txpktbuf_bndy = 174; -#elif LLT_CONFIG == 4 - maxPage = 255; - txpktbuf_bndy = 246; -#elif LLT_CONFIG == 5 - maxPage = 255; - txpktbuf_bndy = 246; -#endif - -#if LLT_CONFIG == 1 - rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x1c); - rtl_write_dword(rtlpriv, REG_RQPN, 0x80a71c1c); -#elif LLT_CONFIG == 2 - rtl_write_dword(rtlpriv, REG_RQPN, 0x845B1010); -#elif LLT_CONFIG == 3 - rtl_write_dword(rtlpriv, REG_RQPN, 0x84838484); -#elif LLT_CONFIG == 4 - rtl_write_dword(rtlpriv, REG_RQPN, 0x80bd1c1c); -#elif LLT_CONFIG == 5 - rtl_write_word(rtlpriv, REG_RQPN_NPQ, 0x0000); - - rtl_write_dword(rtlpriv, REG_RQPN, 0x80b01c29); -#endif - - rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x27FF0000 | txpktbuf_bndy)); - rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_PBP, 0x11); - rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); - - for (i = 0; i < (txpktbuf_bndy - 1); i++) { - status = _rtl92ce_llt_write(hw, i, i + 1); - if (true != status) - return status; - } - - status = _rtl92ce_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); - if (true != status) - return status; - - for (i = txpktbuf_bndy; i < maxPage; i++) { - status = _rtl92ce_llt_write(hw, i, (i + 1)); - if (true != status) - return status; - } - - status = _rtl92ce_llt_write(hw, maxPage, txpktbuf_bndy); - if (true != status) - return status; - - return true; -} - -static void _rtl92ce_gen_refresh_led_state(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); - - if (rtlpci->up_first_time) - return; - - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtl92ce_sw_led_on(hw, pLed0); - else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - rtl92ce_sw_led_on(hw, pLed0); - else - rtl92ce_sw_led_off(hw, pLed0); -} - -static bool _rtl92ce_init_mac(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - unsigned char bytetmp; - unsigned short wordtmp; - u16 retry; - - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); - if (rtlpcipriv->bt_coexist.bt_coexistence) { - u32 value32; - value32 = rtl_read_dword(rtlpriv, REG_APS_FSMCO); - value32 |= (SOP_ABG | SOP_AMB | XOP_BTCK); - rtl_write_dword(rtlpriv, REG_APS_FSMCO, value32); - } - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F); - - if (rtlpcipriv->bt_coexist.bt_coexistence) { - u32 u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); - - u4b_tmp &= (~0x00024800); - rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp); - } - - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0); - udelay(2); - - rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); - udelay(2); - - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); - udelay(2); - - retry = 0; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "reg0xec:%x:%x\n", - rtl_read_dword(rtlpriv, 0xEC), bytetmp); - - while ((bytetmp & BIT(0)) && retry < 1000) { - retry++; - udelay(50); - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "reg0xec:%x:%x\n", - rtl_read_dword(rtlpriv, 0xEC), bytetmp); - udelay(50); - } - - rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x1012); - - rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82); - udelay(2); - - if (rtlpcipriv->bt_coexist.bt_coexistence) { - bytetmp = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2) & 0xfd; - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, bytetmp); - } - - rtl_write_word(rtlpriv, REG_CR, 0x2ff); - - if (!_rtl92ce_llt_table_init(hw)) - return false; - - rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); - rtl_write_byte(rtlpriv, REG_HISRE, 0xff); - - rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x27ff); - - wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); - wordtmp &= 0xf; - wordtmp |= 0xF771; - rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); - - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); - - rtl_write_byte(rtlpriv, 0x4d0, 0x0); - - rtl_write_dword(rtlpriv, REG_BCNQ_DESA, - ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_MGQ_DESA, - (u64) rtlpci->tx_ring[MGNT_QUEUE].dma & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VOQ_DESA, - (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VIQ_DESA, - (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_BEQ_DESA, - (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_BKQ_DESA, - (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_HQ_DESA, - (u64) rtlpci->tx_ring[HIGH_QUEUE].dma & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_RX_DESA, - (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma & - DMA_BIT_MASK(32)); - - if (IS_92C_SERIAL(rtlhal->version)) - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x77); - else - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x22); - - rtl_write_dword(rtlpriv, REG_INT_MIG, 0); - - bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6)); - do { - retry++; - bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); - } while ((retry < 200) && (bytetmp & BIT(7))); - - _rtl92ce_gen_refresh_led_state(hw); - - rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); - - return true; -} - -static void _rtl92ce_hw_configure(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - u8 reg_bw_opmode; - u32 reg_prsr; - - reg_bw_opmode = BW_OPMODE_20MHZ; - reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - - rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8); - - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - - rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr); - - rtl_write_byte(rtlpriv, REG_SLOT, 0x09); - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0); - - rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80); - - rtl_write_word(rtlpriv, REG_RL, 0x0707); - - rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802); - - rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); - - rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); - rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); - - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x97427431); - else - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); - - rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); - - rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff); - - rtlpci->reg_bcn_ctrl_val = 0x1f; - rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); - - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - - rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); - rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); - - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) { - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0402); - } else { - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - } - - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) - rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); - else - rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); - - rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); - - rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010); - rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010); - - rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010); - - rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010); - - rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff); - rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff); - -} - -static void _rtl92ce_enable_aspm_back_door(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - rtl_write_byte(rtlpriv, 0x34b, 0x93); - rtl_write_word(rtlpriv, 0x350, 0x870c); - rtl_write_byte(rtlpriv, 0x352, 0x1); - - if (ppsc->support_backdoor) - rtl_write_byte(rtlpriv, 0x349, 0x1b); - else - rtl_write_byte(rtlpriv, 0x349, 0x03); - - rtl_write_word(rtlpriv, 0x350, 0x2718); - rtl_write_byte(rtlpriv, 0x352, 0x1); -} - -void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 sec_reg_value; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", - rtlpriv->sec.pairwise_enc_algorithm, - rtlpriv->sec.group_enc_algorithm); - - if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "not open hw encryption\n"); - return; - } - - sec_reg_value = SCR_TxEncEnable | SCR_RxDecEnable; - - if (rtlpriv->sec.use_defaultkey) { - sec_reg_value |= SCR_TxUseDK; - sec_reg_value |= SCR_RxUseDK; - } - - sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); - - rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "The SECR-value %x\n", sec_reg_value); - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); - -} - -int rtl92ce_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool rtstatus = true; - bool is92c; - int err; - u8 tmp_u1b; - unsigned long flags; - - rtlpci->being_init_adapter = true; - - /* Since this function can take a very long time (up to 350 ms) - * and can be called with irqs disabled, reenable the irqs - * to let the other devices continue being serviced. - * - * It is safe doing so since our own interrupts will only be enabled - * in a subsequent step. - */ - local_save_flags(flags); - local_irq_enable(); - - rtlhal->fw_ready = false; - rtlpriv->intf_ops->disable_aspm(hw); - rtstatus = _rtl92ce_init_mac(hw); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); - err = 1; - goto exit; - } - - err = rtl92c_download_fw(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Failed to download FW. Init HW without FW now..\n"); - err = 1; - goto exit; - } - - rtlhal->fw_ready = true; - rtlhal->last_hmeboxnum = 0; - rtl92c_phy_mac_config(hw); - /* because last function modify RCR, so we update - * rcr var here, or TP will unstable for receive_config - * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx - * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/ - rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); - rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - rtl92c_phy_bb_config(hw); - rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; - rtl92c_phy_rf_config(hw); - if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && - !IS_92C_SERIAL(rtlhal->version)) { - rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00); - } else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) { - rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE); - rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31); - rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425); - rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201); - } - rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); - _rtl92ce_hw_configure(hw); - rtl_cam_reset_all_entry(hw); - rtl92ce_enable_hw_security_config(hw); - - ppsc->rfpwr_state = ERFON; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); - _rtl92ce_enable_aspm_back_door(hw); - rtlpriv->intf_ops->enable_aspm(hw); - - rtl8192ce_bt_hw_init(hw); - - if (ppsc->rfpwr_state == ERFON) { - rtl92c_phy_set_rfpath_switch(hw, 1); - if (rtlphy->iqk_initialized) { - rtl92c_phy_iq_calibrate(hw, true); - } else { - rtl92c_phy_iq_calibrate(hw, false); - rtlphy->iqk_initialized = true; - } - - rtl92c_dm_check_txpower_tracking(hw); - rtl92c_phy_lc_calibrate(hw); - } - - is92c = IS_92C_SERIAL(rtlhal->version); - tmp_u1b = efuse_read_1byte(hw, 0x1FA); - if (!(tmp_u1b & BIT(0))) { - rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "PA BIAS path A\n"); - } - - if (!(tmp_u1b & BIT(1)) && is92c) { - rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0F, 0x05); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "PA BIAS path B\n"); - } - - if (!(tmp_u1b & BIT(4))) { - tmp_u1b = rtl_read_byte(rtlpriv, 0x16); - tmp_u1b &= 0x0F; - rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80); - udelay(10); - rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n"); - } - rtl92c_dm_init(hw); -exit: - local_irq_restore(flags); - rtlpci->being_init_adapter = false; - return err; -} - -static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - enum version_8192c version = VERSION_UNKNOWN; - u32 value32; - const char *versionid; - - value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); - if (value32 & TRP_VAUX_EN) { - version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C : - VERSION_A_CHIP_88C; - } else { - version = (enum version_8192c) (CHIP_VER_B | - ((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0) | - ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); - if ((!IS_CHIP_VENDOR_UMC(version)) && (value32 & - CHIP_VER_RTL_MASK)) { - version = (enum version_8192c)(version | - ((((value32 & CHIP_VER_RTL_MASK) == BIT(12)) - ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) | - CHIP_VENDOR_UMC)); - } - if (IS_92C_SERIAL(version)) { - value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM); - version = (enum version_8192c)(version | - ((CHIP_BONDING_IDENTIFIER(value32) - == CHIP_BONDING_92C_1T2R) ? - RF_TYPE_1T2R : 0)); - } - } - - switch (version) { - case VERSION_B_CHIP_92C: - versionid = "B_CHIP_92C"; - break; - case VERSION_B_CHIP_88C: - versionid = "B_CHIP_88C"; - break; - case VERSION_A_CHIP_92C: - versionid = "A_CHIP_92C"; - break; - case VERSION_A_CHIP_88C: - versionid = "A_CHIP_88C"; - break; - case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT: - versionid = "A_CUT_92C_1T2R"; - break; - case VERSION_NORMAL_UMC_CHIP_92C_A_CUT: - versionid = "A_CUT_92C"; - break; - case VERSION_NORMAL_UMC_CHIP_88C_A_CUT: - versionid = "A_CUT_88C"; - break; - case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT: - versionid = "B_CUT_92C_1T2R"; - break; - case VERSION_NORMAL_UMC_CHIP_92C_B_CUT: - versionid = "B_CUT_92C"; - break; - case VERSION_NORMAL_UMC_CHIP_88C_B_CUT: - versionid = "B_CUT_88C"; - break; - default: - versionid = "Unknown. Bug?"; - break; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, - "Chip Version ID: %s\n", versionid); - - switch (version & 0x3) { - case CHIP_88C: - rtlphy->rf_type = RF_1T1R; - break; - case CHIP_92C: - rtlphy->rf_type = RF_2T2R; - break; - case CHIP_92C_1T2R: - rtlphy->rf_type = RF_1T2R; - break; - default: - rtlphy->rf_type = RF_1T1R; - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "ERROR RF_Type is set!!\n"); - break; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Chip RF Type: %s\n", - rtlphy->rf_type == RF_2T2R ? "RF_2T2R" : "RF_1T1R"); - - return version; -} - -static int _rtl92ce_set_media_status(struct ieee80211_hw *hw, - enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bt_msr = rtl_read_byte(rtlpriv, MSR); - enum led_ctl_mode ledaction = LED_CTL_NO_LINK; - u8 mode = MSR_NOLINK; - - bt_msr &= 0xfc; - - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - mode = MSR_NOLINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to NO LINK!\n"); - break; - case NL80211_IFTYPE_ADHOC: - mode = MSR_ADHOC; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to Ad Hoc!\n"); - break; - case NL80211_IFTYPE_STATION: - mode = MSR_INFRA; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to STA!\n"); - break; - case NL80211_IFTYPE_AP: - mode = MSR_AP; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to AP!\n"); - break; - case NL80211_IFTYPE_MESH_POINT: - mode = MSR_ADHOC; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to Mesh Point!\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Network type %d not supported!\n", type); - return 1; - - } - - /* MSR_INFRA == Link in infrastructure network; - * MSR_ADHOC == Link in ad hoc network; - * Therefore, check link state is necessary. - * - * MSR_AP == AP mode; link state does not matter here. - */ - if (mode != MSR_AP && - rtlpriv->mac80211.link_state < MAC80211_LINKED) { - mode = MSR_NOLINK; - ledaction = LED_CTL_NO_LINK; - } - if (mode == MSR_NOLINK || mode == MSR_INFRA) { - _rtl92ce_stop_tx_beacon(hw); - _rtl92ce_enable_bcn_sub_func(hw); - } else if (mode == MSR_ADHOC || mode == MSR_AP) { - _rtl92ce_resume_tx_beacon(hw); - _rtl92ce_disable_bcn_sub_func(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", - mode); - } - rtl_write_byte(rtlpriv, MSR, bt_msr | mode); - - rtlpriv->cfg->ops->led_control(hw, ledaction); - if (mode == MSR_AP) - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); - else - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); - return 0; -} - -void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 reg_rcr; - - if (rtlpriv->psc.rfpwr_state != ERFON) - return; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); - - if (check_bssid) { - reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *) (®_rcr)); - _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); - } else if (!check_bssid) { - reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); - _rtl92ce_set_bcn_ctrl_reg(hw, BIT(4), 0); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_RCR, (u8 *) (®_rcr)); - } - -} - -int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (_rtl92ce_set_media_status(hw, type)) - return -EOPNOTSUPP; - - if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { - if (type != NL80211_IFTYPE_AP && - type != NL80211_IFTYPE_MESH_POINT) - rtl92ce_set_check_bssid(hw, true); - } else { - rtl92ce_set_check_bssid(hw, false); - } - - return 0; -} - -/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ -void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - rtl92c_dm_init_edca_turbo(hw); - switch (aci) { - case AC1_BK: - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); - break; - case AC0_BE: - /* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); */ - break; - case AC2_VI: - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); - break; - case AC3_VO: - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); - break; - default: - RT_ASSERT(false, "invalid aci: %d !\n", aci); - break; - } -} - -void rtl92ce_enable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); - rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); - rtlpci->irq_enabled = true; -} - -void rtl92ce_disable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED); - rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); - rtlpci->irq_enabled = false; -} - -static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 u1b_tmp; - u32 u4b_tmp; - - rtlpriv->intf_ops->enable_aspm(hw); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0); - if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) - rtl92c_firmware_selfreset(hw); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51); - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000); - u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL); - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - ((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) || - (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8))) { - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00F30000 | - (u1b_tmp << 8)); - } else { - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00FF0000 | - (u1b_tmp << 8)); - } - rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); - rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); - if (!IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); - if (rtlpcipriv->bt_coexist.bt_coexistence) { - u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); - u4b_tmp |= 0x03824800; - rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, u4b_tmp); - } else { - rtl_write_dword(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); - } - - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); - rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10); -} - -void rtl92ce_card_disable(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - enum nl80211_iftype opmode; - - mac->link_state = MAC80211_NOLINK; - opmode = NL80211_IFTYPE_UNSPECIFIED; - _rtl92ce_set_media_status(hw, opmode); - if (rtlpci->driver_is_goingto_unload || - ppsc->rfoff_reason > RF_CHANGE_BY_PS) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - _rtl92ce_poweroff_adapter(hw); - - /* after power off we should do iqk again */ - rtlpriv->phy.iqk_initialized = false; -} - -void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; - rtl_write_dword(rtlpriv, ISR, *p_inta); - - /* - * *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; - * rtl_write_dword(rtlpriv, ISR + 4, *p_intb); - */ -} - -void rtl92ce_set_beacon_related_registers(struct ieee80211_hw *hw) -{ - - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval, atim_window; - - bcn_interval = mac->beacon_interval; - atim_window = 2; /*FIX MERGE */ - rtl92ce_disable_interrupt(hw); - rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); - rtl_write_byte(rtlpriv, 0x606, 0x30); - rtl92ce_enable_interrupt(hw); -} - -void rtl92ce_set_beacon_interval(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval = mac->beacon_interval; - - RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, - "beacon_interval:%d\n", bcn_interval); - rtl92ce_disable_interrupt(hw); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - rtl92ce_enable_interrupt(hw); -} - -void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, "add_msr:%x, rm_msr:%x\n", - add_msr, rm_msr); - - if (add_msr) - rtlpci->irq_mask[0] |= add_msr; - if (rm_msr) - rtlpci->irq_mask[0] &= (~rm_msr); - rtl92ce_disable_interrupt(hw); - rtl92ce_enable_interrupt(hw); -} - -static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 rf_path, index, tempval; - u16 i; - - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < 3; i++) { - if (!autoload_fail) { - rtlefuse-> - eeprom_chnlarea_txpwr_cck[rf_path][i] = - hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i]; - rtlefuse-> - eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = - hwinfo[EEPROM_TXPOWERHT40_1S + rf_path * 3 + - i]; - } else { - rtlefuse-> - eeprom_chnlarea_txpwr_cck[rf_path][i] = - EEPROM_DEFAULT_TXPOWERLEVEL; - rtlefuse-> - eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = - EEPROM_DEFAULT_TXPOWERLEVEL; - } - } - } - - for (i = 0; i < 3; i++) { - if (!autoload_fail) - tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i]; - else - tempval = EEPROM_DEFAULT_HT40_2SDIFF; - rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] = - (tempval & 0xf); - rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] = - ((tempval & 0xf0) >> 4); - } - - for (rf_path = 0; rf_path < 2; rf_path++) - for (i = 0; i < 3; i++) - RTPRINT(rtlpriv, FINIT, INIT_EEPROM, - "RF(%d) EEPROM CCK Area(%d) = 0x%x\n", - rf_path, i, - rtlefuse-> - eeprom_chnlarea_txpwr_cck[rf_path][i]); - for (rf_path = 0; rf_path < 2; rf_path++) - for (i = 0; i < 3; i++) - RTPRINT(rtlpriv, FINIT, INIT_EEPROM, - "RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n", - rf_path, i, - rtlefuse-> - eeprom_chnlarea_txpwr_ht40_1s[rf_path][i]); - for (rf_path = 0; rf_path < 2; rf_path++) - for (i = 0; i < 3; i++) - RTPRINT(rtlpriv, FINIT, INIT_EEPROM, - "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", - rf_path, i, - rtlefuse-> - eprom_chnl_txpwr_ht40_2sdf[rf_path][i]); - - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < 14; i++) { - index = rtl92c_get_chnl_group((u8)i); - - rtlefuse->txpwrlevel_cck[rf_path][i] = - rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][index]; - rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = - rtlefuse-> - eeprom_chnlarea_txpwr_ht40_1s[rf_path][index]; - - if ((rtlefuse-> - eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] - - rtlefuse-> - eprom_chnl_txpwr_ht40_2sdf[rf_path][index]) - > 0) { - rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = - rtlefuse-> - eeprom_chnlarea_txpwr_ht40_1s[rf_path] - [index] - - rtlefuse-> - eprom_chnl_txpwr_ht40_2sdf[rf_path] - [index]; - } else { - rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0; - } - } - - for (i = 0; i < 14; i++) { - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", - rf_path, i, - rtlefuse->txpwrlevel_cck[rf_path][i], - rtlefuse->txpwrlevel_ht40_1s[rf_path][i], - rtlefuse->txpwrlevel_ht40_2s[rf_path][i]); - } - } - - for (i = 0; i < 3; i++) { - if (!autoload_fail) { - rtlefuse->eeprom_pwrlimit_ht40[i] = - hwinfo[EEPROM_TXPWR_GROUP + i]; - rtlefuse->eeprom_pwrlimit_ht20[i] = - hwinfo[EEPROM_TXPWR_GROUP + 3 + i]; - } else { - rtlefuse->eeprom_pwrlimit_ht40[i] = 0; - rtlefuse->eeprom_pwrlimit_ht20[i] = 0; - } - } - - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < 14; i++) { - index = rtl92c_get_chnl_group((u8)i); - - if (rf_path == RF90_PATH_A) { - rtlefuse->pwrgroup_ht20[rf_path][i] = - (rtlefuse->eeprom_pwrlimit_ht20[index] - & 0xf); - rtlefuse->pwrgroup_ht40[rf_path][i] = - (rtlefuse->eeprom_pwrlimit_ht40[index] - & 0xf); - } else if (rf_path == RF90_PATH_B) { - rtlefuse->pwrgroup_ht20[rf_path][i] = - ((rtlefuse->eeprom_pwrlimit_ht20[index] - & 0xf0) >> 4); - rtlefuse->pwrgroup_ht40[rf_path][i] = - ((rtlefuse->eeprom_pwrlimit_ht40[index] - & 0xf0) >> 4); - } - - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-%d pwrgroup_ht20[%d] = 0x%x\n", - rf_path, i, - rtlefuse->pwrgroup_ht20[rf_path][i]); - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-%d pwrgroup_ht40[%d] = 0x%x\n", - rf_path, i, - rtlefuse->pwrgroup_ht40[rf_path][i]); - } - } - - for (i = 0; i < 14; i++) { - index = rtl92c_get_chnl_group((u8)i); - - if (!autoload_fail) - tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index]; - else - tempval = EEPROM_DEFAULT_HT20_DIFF; - - rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); - rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = - ((tempval >> 4) & 0xF); - - if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] & BIT(3)) - rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] |= 0xF0; - - if (rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] & BIT(3)) - rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] |= 0xF0; - - index = rtl92c_get_chnl_group((u8)i); - - if (!autoload_fail) - tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index]; - else - tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; - - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = (tempval & 0xF); - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = - ((tempval >> 4) & 0xF); - } - - rtlefuse->legacy_ht_txpowerdiff = - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; - - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", - i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", - i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", - i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", - i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); - - if (!autoload_fail) - rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); - else - rtlefuse->eeprom_regulatory = 0; - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); - - if (!autoload_fail) { - rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; - rtlefuse->eeprom_tssi[RF90_PATH_B] = hwinfo[EEPROM_TSSI_B]; - } else { - rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; - rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; - } - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, "TSSI_A = 0x%x, TSSI_B = 0x%x\n", - rtlefuse->eeprom_tssi[RF90_PATH_A], - rtlefuse->eeprom_tssi[RF90_PATH_B]); - - if (!autoload_fail) - tempval = hwinfo[EEPROM_THERMAL_METER]; - else - tempval = EEPROM_DEFAULT_THERMALMETER; - rtlefuse->eeprom_thermalmeter = (tempval & 0x1f); - - if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail) - rtlefuse->apk_thermalmeterignore = true; - - rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); -} - -static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u16 i, usvalue; - u8 hwinfo[HWSET_MAX_SIZE]; - u16 eeprom_id; - - if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { - rtl_efuse_shadow_map_update(hw); - - memcpy((void *)hwinfo, - (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], - HWSET_MAX_SIZE); - } else if (rtlefuse->epromtype == EEPROM_93C46) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "RTL819X Not boot from eeprom, check it !!"); - } - - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP", - hwinfo, HWSET_MAX_SIZE); - - eeprom_id = *((u16 *)&hwinfo[0]); - if (eeprom_id != RTL8190_EEPROM_ID) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "EEPROM ID(%#x) is invalid!!\n", eeprom_id); - rtlefuse->autoload_failflag = true; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - } - - if (rtlefuse->autoload_failflag) - return; - - rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; - rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; - rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; - rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROMId = 0x%4x\n", eeprom_id); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); - - for (i = 0; i < 6; i += 2) { - usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; - *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%pM\n", rtlefuse->dev_addr); - - _rtl92ce_read_txpower_info_from_hwpg(hw, - rtlefuse->autoload_failflag, - hwinfo); - - rtl8192ce_read_bt_coexist_info_from_hwpg(hw, - rtlefuse->autoload_failflag, - hwinfo); - - rtlefuse->eeprom_channelplan = *&hwinfo[EEPROM_CHANNELPLAN]; - rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; - rtlefuse->txpwr_fromeprom = true; - rtlefuse->eeprom_oemid = *&hwinfo[EEPROM_CUSTOMER_ID]; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); - - /* set channel paln to world wide 13 */ - rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; - - if (rtlhal->oem_id == RT_CID_DEFAULT) { - switch (rtlefuse->eeprom_oemid) { - case EEPROM_CID_DEFAULT: - if (rtlefuse->eeprom_did == 0x8176) { - if ((rtlefuse->eeprom_svid == 0x103C && - rtlefuse->eeprom_smid == 0x1629)) - rtlhal->oem_id = RT_CID_819X_HP; - else - rtlhal->oem_id = RT_CID_DEFAULT; - } else { - rtlhal->oem_id = RT_CID_DEFAULT; - } - break; - case EEPROM_CID_TOSHIBA: - rtlhal->oem_id = RT_CID_TOSHIBA; - break; - case EEPROM_CID_QMI: - rtlhal->oem_id = RT_CID_819X_QMI; - break; - case EEPROM_CID_WHQL: - default: - rtlhal->oem_id = RT_CID_DEFAULT; - break; - - } - } - -} - -static void _rtl92ce_hal_customized_behavior(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - switch (rtlhal->oem_id) { - case RT_CID_819X_HP: - pcipriv->ledctl.led_opendrain = true; - break; - case RT_CID_819X_LENOVO: - case RT_CID_DEFAULT: - case RT_CID_TOSHIBA: - case RT_CID_CCX: - case RT_CID_819X_ACER: - case RT_CID_WHQL: - default: - break; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "RT Customized ID: 0x%02X\n", rtlhal->oem_id); -} - -void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_u1b; - - rtlhal->version = _rtl92ce_read_chip_version(hw); - if (get_rf_type(rtlphy) == RF_1T1R) - rtlpriv->dm.rfpath_rxenable[0] = true; - else - rtlpriv->dm.rfpath_rxenable[0] = - rtlpriv->dm.rfpath_rxenable[1] = true; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", - rtlhal->version); - tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); - if (tmp_u1b & BIT(4)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); - rtlefuse->epromtype = EEPROM_93C46; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); - rtlefuse->epromtype = EEPROM_BOOT_EFUSE; - } - if (tmp_u1b & BIT(5)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - _rtl92ce_read_adapter_info(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); - } - _rtl92ce_hal_customized_behavior(hw); -} - -static void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 ratr_value; - u8 ratr_index = 0; - u8 nmode = mac->ht_enable; - u16 shortgi_rate; - u32 tmp_ratr_value; - u8 curtxbw_40mhz = mac->bw_40; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = mac->mode; - u32 ratr_mask; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_value = sta->supp_rates[1] << 4; - else - ratr_value = sta->supp_rates[0]; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_value = 0xfff; - - ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - if (ratr_value & 0x0000000c) - ratr_value &= 0x0000000d; - else - ratr_value &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_value &= 0x00000FF5; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - nmode = 1; - if (get_rf_type(rtlphy) == RF_1T2R || - get_rf_type(rtlphy) == RF_1T1R) - ratr_mask = 0x000ff005; - else - ratr_mask = 0x0f0ff005; - - ratr_value &= ratr_mask; - break; - default: - if (rtlphy->rf_type == RF_1T2R) - ratr_value &= 0x000ff0ff; - else - ratr_value &= 0x0f0ff0ff; - - break; - } - - if ((rtlpcipriv->bt_coexist.bt_coexistence) && - (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) && - (rtlpcipriv->bt_coexist.bt_cur_state) && - (rtlpcipriv->bt_coexist.bt_ant_isolation) && - ((rtlpcipriv->bt_coexist.bt_service == BT_SCO) || - (rtlpcipriv->bt_coexist.bt_service == BT_BUSY))) - ratr_value &= 0x0fffcfc0; - else - ratr_value &= 0x0FFFFFFF; - - if (nmode && ((curtxbw_40mhz && - curshortgi_40mhz) || (!curtxbw_40mhz && - curshortgi_20mhz))) { - - ratr_value |= 0x10000000; - tmp_ratr_value = (ratr_value >> 12); - - for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { - if ((1 << shortgi_rate) & tmp_ratr_value) - break; - } - - shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | - (shortgi_rate << 4) | (shortgi_rate); - } - - rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n", - rtl_read_dword(rtlpriv, REG_ARFR0)); -} - -static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - u32 ratr_bitmap; - u8 ratr_index; - u8 curtxbw_40mhz = (sta->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0; - u8 curshortgi_40mhz = (sta->ht_cap.cap & - IEEE80211_HT_CAP_SGI_40) ? 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = 0; - bool shortgi = false; - u8 rate_mask[5]; - u8 macid = 0; - - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - wirelessmode = sta_entry->wireless_mode; - if (mac->opmode == NL80211_IFTYPE_STATION || - mac->opmode == NL80211_IFTYPE_MESH_POINT) - curtxbw_40mhz = mac->bw_40; - else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) - macid = sta->aid + 1; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_bitmap = sta->supp_rates[1] << 4; - else - ratr_bitmap = sta->supp_rates[0]; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_bitmap = 0xfff; - ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - ratr_index = RATR_INX_WIRELESS_B; - if (ratr_bitmap & 0x0000000c) - ratr_bitmap &= 0x0000000d; - else - ratr_bitmap &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_index = RATR_INX_WIRELESS_GB; - - if (rssi_level == 1) - ratr_bitmap &= 0x00000f00; - else if (rssi_level == 2) - ratr_bitmap &= 0x00000ff0; - else - ratr_bitmap &= 0x00000ff5; - break; - case WIRELESS_MODE_A: - ratr_index = RATR_INX_WIRELESS_A; - ratr_bitmap &= 0x00000ff0; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - ratr_index = RATR_INX_WIRELESS_NGB; - - if (rtlphy->rf_type == RF_1T2R || - rtlphy->rf_type == RF_1T1R) { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff005; - } - } else { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x0f0f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0f0ff000; - else - ratr_bitmap &= 0x0f0ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x0f0f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0f0ff000; - else - ratr_bitmap &= 0x0f0ff005; - } - } - - if ((curtxbw_40mhz && curshortgi_40mhz) || - (!curtxbw_40mhz && curshortgi_20mhz)) { - - if (macid == 0) - shortgi = true; - else if (macid == 1) - shortgi = false; - } - break; - default: - ratr_index = RATR_INX_WIRELESS_NGB; - - if (rtlphy->rf_type == RF_1T2R) - ratr_bitmap &= 0x000ff0ff; - else - ratr_bitmap &= 0x0f0ff0ff; - break; - } - sta_entry->ratr_index = ratr_index; - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "ratr_bitmap :%x\n", ratr_bitmap); - *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | - (ratr_index << 28); - rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "Rate_index:%x, ratr_val:%x, %5phC\n", - ratr_index, ratr_bitmap, rate_mask); - rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); -} - -void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->dm.useramask) - rtl92ce_update_hal_rate_mask(hw, sta, rssi_level); - else - rtl92ce_update_hal_rate_table(hw, sta); -} - -void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 sifs_timer; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, - &mac->slot_time); - if (!mac->ht_enable) - sifs_timer = 0x0a0a; - else - sifs_timer = 0x1010; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); -} - -bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - enum rf_pwrstate e_rfpowerstate_toset; - u8 u1tmp; - bool actuallyset = false; - unsigned long flag; - - if (rtlpci->being_init_adapter) - return false; - - if (ppsc->swrf_processing) - return false; - - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - if (ppsc->rfchange_inprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - return false; - } else { - ppsc->rfchange_inprogress = true; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } - - rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv, - REG_MAC_PINMUX_CFG)&~(BIT(3))); - - u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); - e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF; - - if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "GPIOChangeRF - HW Radio ON, RF ON\n"); - - e_rfpowerstate_toset = ERFON; - ppsc->hwradiooff = false; - actuallyset = true; - } else if (!ppsc->hwradiooff && (e_rfpowerstate_toset == ERFOFF)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "GPIOChangeRF - HW Radio OFF, RF OFF\n"); - - e_rfpowerstate_toset = ERFOFF; - ppsc->hwradiooff = true; - actuallyset = true; - } - - if (actuallyset) { - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } else { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } - - *valid = 1; - return !ppsc->hwradiooff; - -} - -void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 *macaddr = p_macaddr; - u32 entry_id = 0; - bool is_pairwise = false; - - static u8 cam_const_addr[4][6] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} - }; - static u8 cam_const_broad[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - - if (clear_all) { - u8 idx = 0; - u8 cam_offset = 0; - u8 clear_number = 5; - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); - - for (idx = 0; idx < clear_number; idx++) { - rtl_cam_mark_invalid(hw, cam_offset + idx); - rtl_cam_empty_entry(hw, cam_offset + idx); - - if (idx < 5) { - memset(rtlpriv->sec.key_buf[idx], 0, - MAX_KEY_LEN); - rtlpriv->sec.key_len[idx] = 0; - } - } - - } else { - switch (enc_algo) { - case WEP40_ENCRYPTION: - enc_algo = CAM_WEP40; - break; - case WEP104_ENCRYPTION: - enc_algo = CAM_WEP104; - break; - case TKIP_ENCRYPTION: - enc_algo = CAM_TKIP; - break; - case AESCCMP_ENCRYPTION: - enc_algo = CAM_AES; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - enc_algo = CAM_TKIP; - break; - } - - if (is_wepkey || rtlpriv->sec.use_defaultkey) { - macaddr = cam_const_addr[key_index]; - entry_id = key_index; - } else { - if (is_group) { - macaddr = cam_const_broad; - entry_id = key_index; - } else { - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - entry_id = rtl_cam_get_free_entry(hw, - p_macaddr); - if (entry_id >= TOTAL_CAM_ENTRY) { - RT_TRACE(rtlpriv, COMP_SEC, - DBG_EMERG, - "Can not find free hw security cam entry\n"); - return; - } - } else { - entry_id = CAM_PAIRWISE_KEY_POSITION; - } - - key_index = PAIRWISE_KEYIDX; - is_pairwise = true; - } - } - - if (rtlpriv->sec.key_len[key_index] == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "delete one entry, entry_id is %d\n", - entry_id); - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_MESH_POINT) - rtl_cam_del_entry(hw, p_macaddr); - rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "The insert KEY length is %d\n", - rtlpriv->sec.key_len[PAIRWISE_KEYIDX]); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "The insert KEY is %x %x\n", - rtlpriv->sec.key_buf[0][0], - rtlpriv->sec.key_buf[0][1]); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "add one entry\n"); - if (is_pairwise) { - RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, - "Pairwise Key content", - rtlpriv->sec.pairwise_key, - rtlpriv->sec. - key_len[PAIRWISE_KEYIDX]); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set Pairwise key\n"); - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec. - key_buf[key_index]); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set group key\n"); - - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - rtl_cam_add_one_entry(hw, - rtlefuse->dev_addr, - PAIRWISE_KEYIDX, - CAM_PAIRWISE_KEY_POSITION, - enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf - [entry_id]); - } - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[entry_id]); - } - - } - } -} - -static void rtl8192ce_bt_var_init(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - rtlpcipriv->bt_coexist.bt_coexistence = - rtlpcipriv->bt_coexist.eeprom_bt_coexist; - rtlpcipriv->bt_coexist.bt_ant_num = - rtlpcipriv->bt_coexist.eeprom_bt_ant_num; - rtlpcipriv->bt_coexist.bt_coexist_type = - rtlpcipriv->bt_coexist.eeprom_bt_type; - - if (rtlpcipriv->bt_coexist.reg_bt_iso == 2) - rtlpcipriv->bt_coexist.bt_ant_isolation = - rtlpcipriv->bt_coexist.eeprom_bt_ant_isol; - else - rtlpcipriv->bt_coexist.bt_ant_isolation = - rtlpcipriv->bt_coexist.reg_bt_iso; - - rtlpcipriv->bt_coexist.bt_radio_shared_type = - rtlpcipriv->bt_coexist.eeprom_bt_radio_shared; - - if (rtlpcipriv->bt_coexist.bt_coexistence) { - - if (rtlpcipriv->bt_coexist.reg_bt_sco == 1) - rtlpcipriv->bt_coexist.bt_service = BT_OTHER_ACTION; - else if (rtlpcipriv->bt_coexist.reg_bt_sco == 2) - rtlpcipriv->bt_coexist.bt_service = BT_SCO; - else if (rtlpcipriv->bt_coexist.reg_bt_sco == 4) - rtlpcipriv->bt_coexist.bt_service = BT_BUSY; - else if (rtlpcipriv->bt_coexist.reg_bt_sco == 5) - rtlpcipriv->bt_coexist.bt_service = BT_OTHERBUSY; - else - rtlpcipriv->bt_coexist.bt_service = BT_IDLE; - - rtlpcipriv->bt_coexist.bt_edca_ul = 0; - rtlpcipriv->bt_coexist.bt_edca_dl = 0; - rtlpcipriv->bt_coexist.bt_rssi_state = 0xff; - } -} - -void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool auto_load_fail, u8 *hwinfo) -{ - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - u8 val; - - if (!auto_load_fail) { - rtlpcipriv->bt_coexist.eeprom_bt_coexist = - ((hwinfo[RF_OPTION1] & 0xe0) >> 5); - val = hwinfo[RF_OPTION4]; - rtlpcipriv->bt_coexist.eeprom_bt_type = ((val & 0xe) >> 1); - rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (val & 0x1); - rtlpcipriv->bt_coexist.eeprom_bt_ant_isol = ((val & 0x10) >> 4); - rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = - ((val & 0x20) >> 5); - } else { - rtlpcipriv->bt_coexist.eeprom_bt_coexist = 0; - rtlpcipriv->bt_coexist.eeprom_bt_type = BT_2WIRE; - rtlpcipriv->bt_coexist.eeprom_bt_ant_num = ANT_X2; - rtlpcipriv->bt_coexist.eeprom_bt_ant_isol = 0; - rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = BT_RADIO_SHARED; - } - - rtl8192ce_bt_var_init(hw); -} - -void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - /* 0:Low, 1:High, 2:From Efuse. */ - rtlpcipriv->bt_coexist.reg_bt_iso = 2; - /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ - rtlpcipriv->bt_coexist.reg_bt_sco = 3; - /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ - rtlpcipriv->bt_coexist.reg_bt_sco = 0; -} - - -void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - - u8 u1_tmp; - - if (rtlpcipriv->bt_coexist.bt_coexistence && - ((rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4) || - rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC8)) { - - if (rtlpcipriv->bt_coexist.bt_ant_isolation) - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0); - - u1_tmp = rtl_read_byte(rtlpriv, 0x4fd) & - BIT_OFFSET_LEN_MASK_32(0, 1); - u1_tmp = u1_tmp | - ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ? - 0 : BIT_OFFSET_LEN_MASK_32(1, 1)) | - ((rtlpcipriv->bt_coexist.bt_service == BT_SCO) ? - 0 : BIT_OFFSET_LEN_MASK_32(2, 1)); - rtl_write_byte(rtlpriv, 0x4fd, u1_tmp); - - rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+4, 0xaaaa9aaa); - rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+8, 0xffbd0040); - rtl_write_dword(rtlpriv, REG_BT_COEX_TABLE+0xc, 0x40000010); - - /* Config to 1T1R. */ - if (rtlphy->rf_type == RF_1T1R) { - u1_tmp = rtl_read_byte(rtlpriv, ROFDM0_TRXPATHENABLE); - u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); - rtl_write_byte(rtlpriv, ROFDM0_TRXPATHENABLE, u1_tmp); - - u1_tmp = rtl_read_byte(rtlpriv, ROFDM1_TRXPATHENABLE); - u1_tmp &= ~(BIT_OFFSET_LEN_MASK_32(1, 1)); - rtl_write_byte(rtlpriv, ROFDM1_TRXPATHENABLE, u1_tmp); - } - } -} - -void rtl92ce_suspend(struct ieee80211_hw *hw) -{ -} - -void rtl92ce_resume(struct ieee80211_hw *hw) -{ -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h deleted file mode 100644 index 98a086822aac..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h +++ /dev/null @@ -1,80 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CE_HW_H__ -#define __RTL92CE_HW_H__ - -static inline u8 rtl92c_get_chnl_group(u8 chnl) -{ - u8 group; - - if (chnl < 3) - group = 0; - else if (chnl < 9) - group = 1; - else - group = 2; - return group; -} - -void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw); -void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb); -int rtl92ce_hw_init(struct ieee80211_hw *hw); -void rtl92ce_card_disable(struct ieee80211_hw *hw); -void rtl92ce_enable_interrupt(struct ieee80211_hw *hw); -void rtl92ce_disable_interrupt(struct ieee80211_hw *hw); -int rtl92ce_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); -void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci); -void rtl92ce_set_beacon_related_registers(struct ieee80211_hw *hw); -void rtl92ce_set_beacon_interval(struct ieee80211_hw *hw); -void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr); -void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level); -void rtl92ce_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level); -void rtl92ce_update_channel_access_setting(struct ieee80211_hw *hw); -bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); -void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw); -void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all); - -void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, u8 *hwinfo); -void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw); -void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw); -void rtl92ce_suspend(struct ieee80211_hw *hw); -void rtl92ce_resume(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c deleted file mode 100644 index 8283e9b27639..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c +++ /dev/null @@ -1,151 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "reg.h" -#include "led.h" - -static void _rtl92ce_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - u8 ledcfg; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - REG_LEDCFG2, pled->ledpin); - - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - rtl_write_byte(rtlpriv, - REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6)); - break; - case LED_PIN_LED1: - rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - pled->ledon = true; -} - -void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - u8 ledcfg; - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - REG_LEDCFG2, pled->ledpin); - - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg &= 0xf0; - if (pcipriv->ledctl.led_opendrain) - rtl_write_byte(rtlpriv, REG_LEDCFG2, - (ledcfg | BIT(1) | BIT(5) | BIT(6))); - else - rtl_write_byte(rtlpriv, REG_LEDCFG2, - (ledcfg | BIT(3) | BIT(5) | BIT(6))); - break; - case LED_PIN_LED1: - ledcfg &= 0x0f; - rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - pled->ledon = false; -} - -void rtl92ce_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); - _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); -} - -static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); - switch (ledaction) { - case LED_CTL_POWER_ON: - case LED_CTL_LINK: - case LED_CTL_NO_LINK: - rtl92ce_sw_led_on(hw, pLed0); - break; - case LED_CTL_POWER_OFF: - rtl92ce_sw_led_off(hw, pLed0); - break; - default: - break; - } -} - -void rtl92ce_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && - (ledaction == LED_CTL_TX || - ledaction == LED_CTL_RX || - ledaction == LED_CTL_SITE_SURVEY || - ledaction == LED_CTL_LINK || - ledaction == LED_CTL_NO_LINK || - ledaction == LED_CTL_START_TO_LINK || - ledaction == LED_CTL_POWER_ON)) { - return; - } - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d\n", - ledaction); - _rtl92ce_sw_led_control(hw, ledaction); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h b/drivers/net/wireless/rtlwifi/rtl8192ce/led.h deleted file mode 100644 index c5761066d383..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CE_LED_H__ -#define __RTL92CE_LED_H__ - -void rtl92ce_init_sw_leds(struct ieee80211_hw *hw); -void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92ce_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c deleted file mode 100644 index 1ee5a6ae9960..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ /dev/null @@ -1,577 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../ps.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "hw.h" -#include "phy.h" -#include "../rtl8192c/phy_common.h" -#include "rf.h" -#include "dm.h" -#include "../rtl8192c/dm_common.h" -#include "../rtl8192c/fw_common.h" -#include "table.h" - -static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); - -u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, readback_value, bitshift; - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", - regaddr, rfpath, bitmask); - - spin_lock(&rtlpriv->locks.rf_lock); - - if (rtlphy->rf_mode != RF_OP_BY_FW) { - original_value = _rtl92c_phy_rf_serial_read(hw, - rfpath, regaddr); - } else { - original_value = _rtl92c_phy_fw_rf_serial_read(hw, - rfpath, regaddr); - } - - bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); - readback_value = (original_value & bitmask) >> bitshift; - - spin_unlock(&rtlpriv->locks.rf_lock); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", - regaddr, rfpath, bitmask, original_value); - - return readback_value; -} - -bool rtl92c_phy_mac_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool is92c = IS_92C_SERIAL(rtlhal->version); - bool rtstatus = _rtl92c_phy_config_mac_with_headerfile(hw); - - if (is92c) - rtl_write_byte(rtlpriv, 0x14, 0x71); - else - rtl_write_byte(rtlpriv, 0x04CA, 0x0A); - return rtstatus; -} - -bool rtl92c_phy_bb_config(struct ieee80211_hw *hw) -{ - bool rtstatus = true; - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 regval; - u32 regvaldw; - u8 reg_hwparafile = 1; - - _rtl92c_phy_init_bb_rf_register_definition(hw); - regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, - regval | BIT(13) | BIT(0) | BIT(1)); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); - rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, - FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | - FEN_BB_GLB_RSTn | FEN_BBRSTB); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); - regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); - rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); - if (reg_hwparafile == 1) - rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); - return rtstatus; -} - -void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 original_value, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); - - spin_lock(&rtlpriv->locks.rf_lock); - - if (rtlphy->rf_mode != RF_OP_BY_FW) { - if (bitmask != RFREG_OFFSET_MASK) { - original_value = _rtl92c_phy_rf_serial_read(hw, - rfpath, - regaddr); - bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); - data = - ((original_value & (~bitmask)) | - (data << bitshift)); - } - - _rtl92c_phy_rf_serial_write(hw, rfpath, regaddr, data); - } else { - if (bitmask != RFREG_OFFSET_MASK) { - original_value = _rtl92c_phy_fw_rf_serial_read(hw, - rfpath, - regaddr); - bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); - data = - ((original_value & (~bitmask)) | - (data << bitshift)); - } - _rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data); - } - - spin_unlock(&rtlpriv->locks.rf_lock); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); -} - -static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - u32 arraylength; - u32 *ptrarray; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n"); - arraylength = MAC_2T_ARRAYLENGTH; - ptrarray = RTL8192CEMAC_2T_ARRAY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CEMAC_2T_ARRAY\n"); - for (i = 0; i < arraylength; i = i + 2) - rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); - return true; -} - -bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) -{ - int i; - u32 *phy_regarray_table; - u32 *agctab_array_table; - u16 phy_reg_arraylen, agctab_arraylen; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (IS_92C_SERIAL(rtlhal->version)) { - agctab_arraylen = AGCTAB_2TARRAYLENGTH; - agctab_array_table = RTL8192CEAGCTAB_2TARRAY; - phy_reg_arraylen = PHY_REG_2TARRAY_LENGTH; - phy_regarray_table = RTL8192CEPHY_REG_2TARRAY; - } else { - agctab_arraylen = AGCTAB_1TARRAYLENGTH; - agctab_array_table = RTL8192CEAGCTAB_1TARRAY; - phy_reg_arraylen = PHY_REG_1TARRAY_LENGTH; - phy_regarray_table = RTL8192CEPHY_REG_1TARRAY; - } - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_reg_arraylen; i = i + 2) { - rtl_addr_delay(phy_regarray_table[i]); - rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD, - phy_regarray_table[i + 1]); - udelay(1); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", - phy_regarray_table[i], - phy_regarray_table[i + 1]); - } - } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { - for (i = 0; i < agctab_arraylen; i = i + 2) { - rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD, - agctab_array_table[i + 1]); - udelay(1); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", - agctab_array_table[i], - agctab_array_table[i + 1]); - } - } - return true; -} - -bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int i; - u32 *phy_regarray_table_pg; - u16 phy_regarray_pg_len; - - phy_regarray_pg_len = PHY_REG_ARRAY_PGLENGTH; - phy_regarray_table_pg = RTL8192CEPHY_REG_ARRAY_PG; - - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_regarray_pg_len; i = i + 3) { - rtl_addr_delay(phy_regarray_table_pg[i]); - - _rtl92c_store_pwrIndex_diffrate_offset(hw, - phy_regarray_table_pg[i], - phy_regarray_table_pg[i + 1], - phy_regarray_table_pg[i + 2]); - } - } else { - - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "configtype != BaseBand_Config_PHY_REG\n"); - } - return true; -} - -bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath) -{ - - int i; - u32 *radioa_array_table; - u32 *radiob_array_table; - u16 radioa_arraylen, radiob_arraylen; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (IS_92C_SERIAL(rtlhal->version)) { - radioa_arraylen = RADIOA_2TARRAYLENGTH; - radioa_array_table = RTL8192CERADIOA_2TARRAY; - radiob_arraylen = RADIOB_2TARRAYLENGTH; - radiob_array_table = RTL8192CE_RADIOB_2TARRAY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio_A:RTL8192CERADIOA_2TARRAY\n"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio_B:RTL8192CE_RADIOB_2TARRAY\n"); - } else { - radioa_arraylen = RADIOA_1TARRAYLENGTH; - radioa_array_table = RTL8192CE_RADIOA_1TARRAY; - radiob_arraylen = RADIOB_1TARRAYLENGTH; - radiob_array_table = RTL8192CE_RADIOB_1TARRAY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio_A:RTL8192CE_RADIOA_1TARRAY\n"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio_B:RTL8192CE_RADIOB_1TARRAY\n"); - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath); - switch (rfpath) { - case RF90_PATH_A: - for (i = 0; i < radioa_arraylen; i = i + 2) { - rtl_rfreg_delay(hw, rfpath, radioa_array_table[i], - RFREG_OFFSET_MASK, - radioa_array_table[i + 1]); - } - break; - case RF90_PATH_B: - for (i = 0; i < radiob_arraylen; i = i + 2) { - rtl_rfreg_delay(hw, rfpath, radiob_array_table[i], - RFREG_OFFSET_MASK, - radiob_array_table[i + 1]); - } - break; - case RF90_PATH_C: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - case RF90_PATH_D: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - default: - break; - } - return true; -} - -void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 reg_bw_opmode; - u8 reg_prsr_rsc; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n", - rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? - "20MHz" : "40MHz"); - - if (is_hal_stop(rtlhal)) { - rtlphy->set_bwmode_inprogress = false; - return; - } - - reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); - reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - reg_bw_opmode |= BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - break; - case HT_CHANNEL_WIDTH_20_40: - reg_bw_opmode &= ~BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - reg_prsr_rsc = - (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); - break; - case HT_CHANNEL_WIDTH_20_40: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); - - rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, - (mac->cur_40_prime_sc >> 1)); - rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); - - rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), - (mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - rtl92ce_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); - rtlphy->set_bwmode_inprogress = false; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); -} - -void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) -{ - u8 tmpreg; - u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - tmpreg = rtl_read_byte(rtlpriv, 0xd03); - - if ((tmpreg & 0x70) != 0) - rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); - else - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - - if ((tmpreg & 0x70) != 0) { - rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); - - if (is2t) - rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, - MASK12BITS); - - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, - (rf_a_mode & 0x8FFFF) | 0x10000); - - if (is2t) - rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, - (rf_b_mode & 0x8FFFF) | 0x10000); - } - lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); - - rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); - - mdelay(100); - - if ((tmpreg & 0x70) != 0) { - rtl_write_byte(rtlpriv, 0xd03, tmpreg); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); - - if (is2t) - rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, - rf_b_mode); - } else { - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - } -} - -static void _rtl92ce_phy_set_rf_sleep(struct ieee80211_hw *hw) -{ - u32 u4b_tmp; - u8 delay = 5; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); - u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); - while (u4b_tmp != 0 && delay > 0) { - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); - u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); - delay--; - } - if (delay == 0) { - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "Switch RF timeout !!!\n"); - return; - } - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); -} - -static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool bresult = true; - u8 i, queue_id; - struct rtl8192_tx_ring *ring = NULL; - - switch (rfpwr_state) { - case ERFON:{ - if ((ppsc->rfpwr_state == ERFOFF) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { - bool rtstatus; - u32 InitializeCount = 0; - do { - InitializeCount++; - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic enable\n"); - rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && (InitializeCount < 10)); - RT_CLEAR_PS_LEVEL(ppsc, - RT_RF_OFF_LEVL_HALT_NIC); - } else { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFON sleeped:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc-> - last_sleep_jiffies)); - ppsc->last_awake_jiffies = jiffies; - rtl92ce_phy_set_rf_on(hw); - } - if (mac->link_state == MAC80211_LINKED) { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_LINK); - } else { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - } - break; - } - case ERFOFF:{ - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic disable\n"); - rtl_ps_disable_nic(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - } else { - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - } else { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_POWER_OFF); - } - } - break; - } - case ERFSLEEP:{ - if (ppsc->rfpwr_state == ERFOFF) - break; - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (queue_id == BEACON_QUEUE || - skb_queue_len(&ring->queue) == 0) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", - i + 1, queue_id, - skb_queue_len(&ring->queue)); - - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFSLEEP awaked:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc->last_awake_jiffies)); - ppsc->last_sleep_jiffies = jiffies; - _rtl92ce_phy_set_rf_sleep(hw); - break; - } - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - bresult = false; - break; - } - if (bresult) - ppsc->rfpwr_state = rfpwr_state; - return bresult; -} - -bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - bool bresult = false; - - if (rfpwr_state == ppsc->rfpwr_state) - return bresult; - bresult = _rtl92ce_phy_set_rf_power_state(hw, rfpwr_state); - return bresult; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h deleted file mode 100644 index e5e1353a94c3..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h +++ /dev/null @@ -1,143 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_PHY_H__ -#define __RTL92C_PHY_H__ - -#define MAX_PRECMD_CNT 16 -#define MAX_RFDEPENDCMD_CNT 16 -#define MAX_POSTCMD_CNT 16 - -#define MAX_DOZE_WAITING_TIMES_9x 64 - -#define RT_CANNOT_IO(hw) false -#define HIGHPOWER_RADIOA_ARRAYLEN 22 - -#define MAX_TOLERANCE 5 - -#define APK_BB_REG_NUM 5 -#define APK_AFE_REG_NUM 16 -#define APK_CURVE_REG_NUM 4 -#define PATH_NUM 2 - -#define LOOP_LIMIT 5 -#define MAX_STALL_TIME 50 -#define AntennaDiversityValue 0x80 -#define MAX_TXPWR_IDX_NMODE_92S 63 -#define Reset_Cnt_Limit 3 - -#define IQK_ADDA_REG_NUM 16 -#define IQK_MAC_REG_NUM 4 - -#define IQK_DELAY_TIME 1 - -#define RF90_PATH_MAX 2 - -#define CT_OFFSET_MAC_ADDR 0X16 - -#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A -#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 -#define CT_OFFSET_HT402S_TX_PWR_IDX_DIF 0x66 -#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 -#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C - -#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F -#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 - -#define CT_OFFSET_CHANNEL_PLAH 0x75 -#define CT_OFFSET_THERMAL_METER 0x78 -#define CT_OFFSET_RF_OPTION 0x79 -#define CT_OFFSET_VERSION 0x7E -#define CT_OFFSET_CUSTOMER_ID 0x7F - -#define RTL92C_MAX_PATH_NUM 2 - -bool rtl92c_phy_bb_config(struct ieee80211_hw *hw); -u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); -void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, - u32 data); -u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask); -void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data); -bool rtl92c_phy_mac_config(struct ieee80211_hw *hw); -bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw); -bool rtl92c_phy_rf_config(struct ieee80211_hw *hw); -bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel); -void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, - long power_indbm); -void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); -void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw); -u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw); -void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval); -void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); -void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw); -void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); -void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); -bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, - u32 rfpath); -bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); -void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw); -bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); -void rtl92c_phy_set_io(struct ieee80211_hw *hw); -void rtl92c_bb_block_on(struct ieee80211_hw *hw); -u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, enum radio_path rfpath, - u32 offset); -u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset); -u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask); -void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, u32 data); -void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data); -void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, u32 data); -bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); -void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); -bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); -void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw); -bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); -bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); -bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); -void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h deleted file mode 100644 index dc8460c0b32f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h +++ /dev/null @@ -1,2057 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_REG_H__ -#define __RTL92C_REG_H__ - -#define REG_SYS_ISO_CTRL 0x0000 -#define REG_SYS_FUNC_EN 0x0002 -#define REG_APS_FSMCO 0x0004 -#define REG_SYS_CLKR 0x0008 -#define REG_9346CR 0x000A -#define REG_EE_VPD 0x000C -#define REG_AFE_MISC 0x0010 -#define REG_SPS0_CTRL 0x0011 -#define REG_SPS_OCP_CFG 0x0018 -#define REG_RSV_CTRL 0x001C -#define REG_RF_CTRL 0x001F -#define REG_LDOA15_CTRL 0x0020 -#define REG_LDOV12D_CTRL 0x0021 -#define REG_LDOHCI12_CTRL 0x0022 -#define REG_LPLDO_CTRL 0x0023 -#define REG_AFE_XTAL_CTRL 0x0024 -#define REG_AFE_PLL_CTRL 0x0028 -#define REG_EFUSE_CTRL 0x0030 -#define REG_EFUSE_TEST 0x0034 -#define REG_PWR_DATA 0x0038 -#define REG_CAL_TIMER 0x003C -#define REG_ACLK_MON 0x003E -#define REG_GPIO_MUXCFG 0x0040 -#define REG_GPIO_IO_SEL 0x0042 -#define REG_MAC_PINMUX_CFG 0x0043 -#define REG_GPIO_PIN_CTRL 0x0044 -#define REG_GPIO_INTM 0x0048 -#define REG_LEDCFG0 0x004C -#define REG_LEDCFG1 0x004D -#define REG_LEDCFG2 0x004E -#define REG_LEDCFG3 0x004F -#define REG_FSIMR 0x0050 -#define REG_FSISR 0x0054 -#define REG_HSIMR 0x0058 -#define REG_HSISR 0x005c - -/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. */ -#define REG_GPIO_PIN_CTRL_2 0x0060 -/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. */ -#define REG_GPIO_IO_SEL_2 0x0062 -/* RTL8723 WIFI/BT/GPS Multi-Function control source. */ -#define REG_MULTI_FUNC_CTRL 0x0068 - -#define REG_MCUFWDL 0x0080 - -#define REG_HMEBOX_EXT_0 0x0088 -#define REG_HMEBOX_EXT_1 0x008A -#define REG_HMEBOX_EXT_2 0x008C -#define REG_HMEBOX_EXT_3 0x008E - -#define REG_BIST_SCAN 0x00D0 -#define REG_BIST_RPT 0x00D4 -#define REG_BIST_ROM_RPT 0x00D8 -#define REG_USB_SIE_INTF 0x00E0 -#define REG_PCIE_MIO_INTF 0x00E4 -#define REG_PCIE_MIO_INTD 0x00E8 -#define REG_HPON_FSM 0x00EC -#define REG_SYS_CFG 0x00F0 -#define REG_GPIO_OUTSTS 0x00F4 /* For RTL8723 only.*/ - -#define REG_CR 0x0100 -#define REG_PBP 0x0104 -#define REG_TRXDMA_CTRL 0x010C -#define REG_TRXFF_BNDY 0x0114 -#define REG_TRXFF_STATUS 0x0118 -#define REG_RXFF_PTR 0x011C -#define REG_HIMR 0x0120 -#define REG_HISR 0x0124 -#define REG_HIMRE 0x0128 -#define REG_HISRE 0x012C -#define REG_CPWM 0x012F -#define REG_FWIMR 0x0130 -#define REG_FWISR 0x0134 -#define REG_PKTBUF_DBG_CTRL 0x0140 -#define REG_PKTBUF_DBG_DATA_L 0x0144 -#define REG_PKTBUF_DBG_DATA_H 0x0148 - -#define REG_TC0_CTRL 0x0150 -#define REG_TC1_CTRL 0x0154 -#define REG_TC2_CTRL 0x0158 -#define REG_TC3_CTRL 0x015C -#define REG_TC4_CTRL 0x0160 -#define REG_TCUNIT_BASE 0x0164 -#define REG_MBIST_START 0x0174 -#define REG_MBIST_DONE 0x0178 -#define REG_MBIST_FAIL 0x017C -#define REG_C2HEVT_MSG_NORMAL 0x01A0 -#define REG_C2HEVT_MSG_TEST 0x01B8 -#define REG_C2HEVT_CLEAR 0x01BF -#define REG_MCUTST_1 0x01c0 -#define REG_FMETHR 0x01C8 -#define REG_HMETFR 0x01CC -#define REG_HMEBOX_0 0x01D0 -#define REG_HMEBOX_1 0x01D4 -#define REG_HMEBOX_2 0x01D8 -#define REG_HMEBOX_3 0x01DC - -#define REG_LLT_INIT 0x01E0 -#define REG_BB_ACCEESS_CTRL 0x01E8 -#define REG_BB_ACCESS_DATA 0x01EC - -#define REG_RQPN 0x0200 -#define REG_FIFOPAGE 0x0204 -#define REG_TDECTRL 0x0208 -#define REG_TXDMA_OFFSET_CHK 0x020C -#define REG_TXDMA_STATUS 0x0210 -#define REG_RQPN_NPQ 0x0214 - -#define REG_RXDMA_AGG_PG_TH 0x0280 -#define REG_RXPKT_NUM 0x0284 -#define REG_RXDMA_STATUS 0x0288 - -#define REG_PCIE_CTRL_REG 0x0300 -#define REG_INT_MIG 0x0304 -#define REG_BCNQ_DESA 0x0308 -#define REG_HQ_DESA 0x0310 -#define REG_MGQ_DESA 0x0318 -#define REG_VOQ_DESA 0x0320 -#define REG_VIQ_DESA 0x0328 -#define REG_BEQ_DESA 0x0330 -#define REG_BKQ_DESA 0x0338 -#define REG_RX_DESA 0x0340 -#define REG_DBI 0x0348 -#define REG_MDIO 0x0354 -#define REG_DBG_SEL 0x0360 -#define REG_PCIE_HRPWM 0x0361 -#define REG_PCIE_HCPWM 0x0363 -#define REG_UART_CTRL 0x0364 -#define REG_UART_TX_DESA 0x0370 -#define REG_UART_RX_DESA 0x0378 - -#define REG_HDAQ_DESA_NODEF 0x0000 -#define REG_CMDQ_DESA_NODEF 0x0000 - -#define REG_VOQ_INFORMATION 0x0400 -#define REG_VIQ_INFORMATION 0x0404 -#define REG_BEQ_INFORMATION 0x0408 -#define REG_BKQ_INFORMATION 0x040C -#define REG_MGQ_INFORMATION 0x0410 -#define REG_HGQ_INFORMATION 0x0414 -#define REG_BCNQ_INFORMATION 0x0418 - -#define REG_CPU_MGQ_INFORMATION 0x041C -#define REG_FWHW_TXQ_CTRL 0x0420 -#define REG_HWSEQ_CTRL 0x0423 -#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 -#define REG_TXPKTBUF_MGQ_BDNY 0x0425 -#define REG_MULTI_BCNQ_EN 0x0426 -#define REG_MULTI_BCNQ_OFFSET 0x0427 -#define REG_SPEC_SIFS 0x0428 -#define REG_RL 0x042A -#define REG_DARFRC 0x0430 -#define REG_RARFRC 0x0438 -#define REG_RRSR 0x0440 -#define REG_ARFR0 0x0444 -#define REG_ARFR1 0x0448 -#define REG_ARFR2 0x044C -#define REG_ARFR3 0x0450 -#define REG_AGGLEN_LMT 0x0458 -#define REG_AMPDU_MIN_SPACE 0x045C -#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D -#define REG_FAST_EDCA_CTRL 0x0460 -#define REG_RD_RESP_PKT_TH 0x0463 -#define REG_INIRTS_RATE_SEL 0x0480 -#define REG_INIDATA_RATE_SEL 0x0484 -#define REG_POWER_STATUS 0x04A4 -#define REG_POWER_STAGE1 0x04B4 -#define REG_POWER_STAGE2 0x04B8 -#define REG_PKT_LIFE_TIME 0x04C0 -#define REG_STBC_SETTING 0x04C4 -#define REG_PROT_MODE_CTRL 0x04C8 -#define REG_BAR_MODE_CTRL 0x04CC -#define REG_RA_TRY_RATE_AGG_LMT 0x04CF -#define REG_NQOS_SEQ 0x04DC -#define REG_QOS_SEQ 0x04DE -#define REG_NEED_CPU_HANDLE 0x04E0 -#define REG_PKT_LOSE_RPT 0x04E1 -#define REG_PTCL_ERR_STATUS 0x04E2 -#define REG_DUMMY 0x04FC - -#define REG_EDCA_VO_PARAM 0x0500 -#define REG_EDCA_VI_PARAM 0x0504 -#define REG_EDCA_BE_PARAM 0x0508 -#define REG_EDCA_BK_PARAM 0x050C -#define REG_BCNTCFG 0x0510 -#define REG_PIFS 0x0512 -#define REG_RDG_PIFS 0x0513 -#define REG_SIFS_CTX 0x0514 -#define REG_SIFS_TRX 0x0516 -#define REG_SIFS_CCK 0x0514 -#define REG_SIFS_OFDM 0x0516 -#define REG_AGGR_BREAK_TIME 0x051A -#define REG_SLOT 0x051B -#define REG_TX_PTCL_CTRL 0x0520 -#define REG_TXPAUSE 0x0522 -#define REG_DIS_TXREQ_CLR 0x0523 -#define REG_RD_CTRL 0x0524 -#define REG_TBTT_PROHIBIT 0x0540 -#define REG_RD_NAV_NXT 0x0544 -#define REG_NAV_PROT_LEN 0x0546 -#define REG_BCN_CTRL 0x0550 -#define REG_USTIME_TSF 0x0551 -#define REG_MBID_NUM 0x0552 -#define REG_DUAL_TSF_RST 0x0553 -#define REG_BCN_INTERVAL 0x0554 -#define REG_MBSSID_BCN_SPACE 0x0554 -#define REG_DRVERLYINT 0x0558 -#define REG_BCNDMATIM 0x0559 -#define REG_ATIMWND 0x055A -#define REG_BCN_MAX_ERR 0x055D -#define REG_RXTSF_OFFSET_CCK 0x055E -#define REG_RXTSF_OFFSET_OFDM 0x055F -#define REG_TSFTR 0x0560 -#define REG_INIT_TSFTR 0x0564 -#define REG_PSTIMER 0x0580 -#define REG_TIMER0 0x0584 -#define REG_TIMER1 0x0588 -#define REG_ACMHWCTRL 0x05C0 -#define REG_ACMRSTCTRL 0x05C1 -#define REG_ACMAVG 0x05C2 -#define REG_VO_ADMTIME 0x05C4 -#define REG_VI_ADMTIME 0x05C6 -#define REG_BE_ADMTIME 0x05C8 -#define REG_EDCA_RANDOM_GEN 0x05CC -#define REG_SCH_TXCMD 0x05D0 - -#define REG_APSD_CTRL 0x0600 -#define REG_BWOPMODE 0x0603 -#define REG_TCR 0x0604 -#define REG_RCR 0x0608 -#define REG_RX_PKT_LIMIT 0x060C -#define REG_RX_DLK_TIME 0x060D -#define REG_RX_DRVINFO_SZ 0x060F - -#define REG_MACID 0x0610 -#define REG_BSSID 0x0618 -#define REG_MAR 0x0620 -#define REG_MBIDCAMCFG 0x0628 - -#define REG_USTIME_EDCA 0x0638 -#define REG_MAC_SPEC_SIFS 0x063A -#define REG_RESP_SIFS_CCK 0x063C -#define REG_RESP_SIFS_OFDM 0x063E -/* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */ -#define REG_R2T_SIFS 0x063C -/* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */ -#define REG_T2T_SIFS 0x063E -#define REG_ACKTO 0x0640 -#define REG_CTS2TO 0x0641 -#define REG_EIFS 0x0642 - -#define REG_NAV_CTRL 0x0650 -#define REG_BACAMCMD 0x0654 -#define REG_BACAMCONTENT 0x0658 -#define REG_LBDLY 0x0660 -#define REG_FWDLY 0x0661 -#define REG_RXERR_RPT 0x0664 -#define REG_WMAC_TRXPTCL_CTL 0x0668 - -#define REG_CAMCMD 0x0670 -#define REG_CAMWRITE 0x0674 -#define REG_CAMREAD 0x0678 -#define REG_CAMDBG 0x067C -#define REG_SECCFG 0x0680 - -#define REG_WOW_CTRL 0x0690 -#define REG_PSSTATUS 0x0691 -#define REG_PS_RX_INFO 0x0692 -#define REG_LPNAV_CTRL 0x0694 -#define REG_WKFMCAM_CMD 0x0698 -#define REG_WKFMCAM_RWD 0x069C -#define REG_RXFLTMAP0 0x06A0 -#define REG_RXFLTMAP1 0x06A2 -#define REG_RXFLTMAP2 0x06A4 -#define REG_BCN_PSR_RPT 0x06A8 -#define REG_CALB32K_CTRL 0x06AC -#define REG_PKT_MON_CTRL 0x06B4 -#define REG_BT_COEX_TABLE 0x06C0 -#define REG_WMAC_RESP_TXINFO 0x06D8 - -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_TEST_USB_TXQS 0xFE48 -#define REG_TEST_SIE_VID 0xFE60 -#define REG_TEST_SIE_PID 0xFE62 -#define REG_TEST_SIE_OPTIONAL 0xFE64 -#define REG_TEST_SIE_CHIRP_K 0xFE65 -#define REG_TEST_SIE_PHY 0xFE66 -#define REG_TEST_SIE_MAC_ADDR 0xFE70 -#define REG_TEST_SIE_STRING 0xFE80 - -#define REG_NORMAL_SIE_VID 0xFE60 -#define REG_NORMAL_SIE_PID 0xFE62 -#define REG_NORMAL_SIE_OPTIONAL 0xFE64 -#define REG_NORMAL_SIE_EP 0xFE65 -#define REG_NORMAL_SIE_PHY 0xFE68 -#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 -#define REG_NORMAL_SIE_STRING 0xFE80 - -#define CR9346 REG_9346CR -#define MSR (REG_CR + 2) -#define ISR REG_HISR -#define TSFR REG_TSFTR - -#define MACIDR0 REG_MACID -#define MACIDR4 (REG_MACID + 4) - -#define PBP REG_PBP - -#define IDR0 MACIDR0 -#define IDR4 MACIDR4 - -#define UNUSED_REGISTER 0x1BF -#define DCAM UNUSED_REGISTER -#define PSR UNUSED_REGISTER -#define BBADDR UNUSED_REGISTER -#define PHYDATAR UNUSED_REGISTER - -#define INVALID_BBRF_VALUE 0x12345678 - -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -#define CMDEEPROM_EN BIT(5) -#define CMDEEPROM_SEL BIT(4) -#define CMD9346CR_9356SEL BIT(4) -#define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL) -#define AUTOLOAD_EFUSE CMDEEPROM_EN - -#define GPIOSEL_GPIO 0 -#define GPIOSEL_ENBT BIT(5) - -#define GPIO_IN REG_GPIO_PIN_CTRL -#define GPIO_OUT (REG_GPIO_PIN_CTRL+1) -#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) -#define GPIO_MOD (REG_GPIO_PIN_CTRL+3) - -#define MSR_NOLINK 0x00 -#define MSR_ADHOC 0x01 -#define MSR_INFRA 0x02 -#define MSR_AP 0x03 -#define MSR_MASK 0x03 - -#define RRSR_RSC_OFFSET 21 -#define RRSR_SHORT_OFFSET 23 -#define RRSR_RSC_BW_40M 0x600000 -#define RRSR_RSC_UPSUBCHNL 0x400000 -#define RRSR_RSC_LOWSUBCHNL 0x200000 -#define RRSR_SHORT 0x800000 -#define RRSR_1M BIT(0) -#define RRSR_2M BIT(1) -#define RRSR_5_5M BIT(2) -#define RRSR_11M BIT(3) -#define RRSR_6M BIT(4) -#define RRSR_9M BIT(5) -#define RRSR_12M BIT(6) -#define RRSR_18M BIT(7) -#define RRSR_24M BIT(8) -#define RRSR_36M BIT(9) -#define RRSR_48M BIT(10) -#define RRSR_54M BIT(11) -#define RRSR_MCS0 BIT(12) -#define RRSR_MCS1 BIT(13) -#define RRSR_MCS2 BIT(14) -#define RRSR_MCS3 BIT(15) -#define RRSR_MCS4 BIT(16) -#define RRSR_MCS5 BIT(17) -#define RRSR_MCS6 BIT(18) -#define RRSR_MCS7 BIT(19) -#define BRSR_ACKSHORTPMB BIT(23) - -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 -#define RATR_MCS8 0x00100000 -#define RATR_MCS9 0x00200000 -#define RATR_MCS10 0x00400000 -#define RATR_MCS11 0x00800000 -#define RATR_MCS12 0x01000000 -#define RATR_MCS13 0x02000000 -#define RATR_MCS14 0x04000000 -#define RATR_MCS15 0x08000000 - -#define RATE_1M BIT(0) -#define RATE_2M BIT(1) -#define RATE_5_5M BIT(2) -#define RATE_11M BIT(3) -#define RATE_6M BIT(4) -#define RATE_9M BIT(5) -#define RATE_12M BIT(6) -#define RATE_18M BIT(7) -#define RATE_24M BIT(8) -#define RATE_36M BIT(9) -#define RATE_48M BIT(10) -#define RATE_54M BIT(11) -#define RATE_MCS0 BIT(12) -#define RATE_MCS1 BIT(13) -#define RATE_MCS2 BIT(14) -#define RATE_MCS3 BIT(15) -#define RATE_MCS4 BIT(16) -#define RATE_MCS5 BIT(17) -#define RATE_MCS6 BIT(18) -#define RATE_MCS7 BIT(19) -#define RATE_MCS8 BIT(20) -#define RATE_MCS9 BIT(21) -#define RATE_MCS10 BIT(22) -#define RATE_MCS11 BIT(23) -#define RATE_MCS12 BIT(24) -#define RATE_MCS13 BIT(25) -#define RATE_MCS14 BIT(26) -#define RATE_MCS15 BIT(27) - -#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) -#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M \ - | RATR_24M | RATR_36M | RATR_48M | RATR_54M) -#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \ - RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \ - RATR_MCS6 | RATR_MCS7) -#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \ - RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \ - RATR_MCS14 | RATR_MCS15) - -#define BW_OPMODE_20MHZ BIT(2) -#define BW_OPMODE_5G BIT(1) -#define BW_OPMODE_11J BIT(0) - -#define CAM_VALID BIT(15) -#define CAM_NOTVALID 0x0000 -#define CAM_USEDK BIT(5) - -#define CAM_NONE 0x0 -#define CAM_WEP40 0x01 -#define CAM_TKIP 0x02 -#define CAM_AES 0x04 -#define CAM_WEP104 0x05 - -#define TOTAL_CAM_ENTRY 32 -#define HALF_CAM_ENTRY 16 - -#define CAM_WRITE BIT(16) -#define CAM_READ 0x00000000 -#define CAM_POLLINIG BIT(31) - -#define SCR_USEDK 0x01 -#define SCR_TXSEC_ENABLE 0x02 -#define SCR_RXSEC_ENABLE 0x04 - -#define WOW_PMEN BIT(0) -#define WOW_WOMEN BIT(1) -#define WOW_MAGIC BIT(2) -#define WOW_UWF BIT(3) - -#define IMR8190_DISABLED 0x0 -#define IMR_BCNDMAINT6 BIT(31) -#define IMR_BCNDMAINT5 BIT(30) -#define IMR_BCNDMAINT4 BIT(29) -#define IMR_BCNDMAINT3 BIT(28) -#define IMR_BCNDMAINT2 BIT(27) -#define IMR_BCNDMAINT1 BIT(26) -#define IMR_BCNDOK8 BIT(25) -#define IMR_BCNDOK7 BIT(24) -#define IMR_BCNDOK6 BIT(23) -#define IMR_BCNDOK5 BIT(22) -#define IMR_BCNDOK4 BIT(21) -#define IMR_BCNDOK3 BIT(20) -#define IMR_BCNDOK2 BIT(19) -#define IMR_BCNDOK1 BIT(18) -#define IMR_TIMEOUT2 BIT(17) -#define IMR_TIMEOUT1 BIT(16) -#define IMR_TXFOVW BIT(15) -#define IMR_PSTIMEOUT BIT(14) -#define IMR_BCNINT BIT(13) -#define IMR_RXFOVW BIT(12) -#define IMR_RDU BIT(11) -#define IMR_ATIMEND BIT(10) -#define IMR_BDOK BIT(9) -#define IMR_HIGHDOK BIT(8) -#define IMR_TBDOK BIT(7) -#define IMR_MGNTDOK BIT(6) -#define IMR_TBDER BIT(5) -#define IMR_BKDOK BIT(4) -#define IMR_BEDOK BIT(3) -#define IMR_VIDOK BIT(2) -#define IMR_VODOK BIT(1) -#define IMR_ROK BIT(0) - -#define IMR_TXERR BIT(11) -#define IMR_RXERR BIT(10) -#define IMR_C2HCMD BIT(9) -#define IMR_CPWM BIT(8) -#define IMR_OCPINT BIT(1) -#define IMR_WLANOFF BIT(0) - -#define EFUSE_REAL_CONTENT_LEN 512 -#define EFUSE_OOB_PROTECT_BYTES 15 - -#define EEPROM_DEFAULT_TSSI 0x0 -#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 -#define EEPROM_DEFAULT_CRYSTALCAP 0x5 -#define EEPROM_DEFAULT_BOARDTYPE 0x02 -#define EEPROM_DEFAULT_TXPOWER 0x1010 -#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 - -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 -#define EEPROM_DEFAULT_THERMALMETER 0x12 -#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 -#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 -#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 -#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 -#define EEPROM_DEFAULT_HT20_DIFF 2 -#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 -#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 - -#define RF_OPTION1 0x79 -#define RF_OPTION2 0x7A -#define RF_OPTION3 0x7B -#define RF_OPTION4 0x7C - -#define EEPROM_DEFAULT_PID 0x1234 -#define EEPROM_DEFAULT_VID 0x5678 -#define EEPROM_DEFAULT_CUSTOMERID 0xAB -#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD -#define EEPROM_DEFAULT_VERSION 0 - -#define EEPROM_CHANNEL_PLAN_FCC 0x0 -#define EEPROM_CHANNEL_PLAN_IC 0x1 -#define EEPROM_CHANNEL_PLAN_ETSI 0x2 -#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 -#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 -#define EEPROM_CHANNEL_PLAN_MKK 0x5 -#define EEPROM_CHANNEL_PLAN_MKK1 0x6 -#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 -#define EEPROM_CHANNEL_PLAN_TELEC 0x8 -#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 -#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -#define EEPROM_CHANNEL_PLAN_NCC 0xB -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - -#define EEPROM_CID_DEFAULT 0x0 -#define EEPROM_CID_TOSHIBA 0x4 -#define EEPROM_CID_CCX 0x10 -#define EEPROM_CID_QMI 0x0D -#define EEPROM_CID_WHQL 0xFE - -#define RTL8192_EEPROM_ID 0x8129 - -#define RTL8190_EEPROM_ID 0x8129 -#define EEPROM_HPON 0x02 -#define EEPROM_CLK 0x06 -#define EEPROM_TESTR 0x08 - -#define EEPROM_VID 0x0A -#define EEPROM_DID 0x0C -#define EEPROM_SVID 0x0E -#define EEPROM_SMID 0x10 - -#define EEPROM_MAC_ADDR 0x16 - -#define EEPROM_CCK_TX_PWR_INX 0x5A -#define EEPROM_HT40_1S_TX_PWR_INX 0x60 -#define EEPROM_HT40_2S_TX_PWR_INX_DIFF 0x66 -#define EEPROM_HT20_TX_PWR_INX_DIFF 0x69 -#define EEPROM_OFDM_TX_PWR_INX_DIFF 0x6C -#define EEPROM_HT40_MAX_PWR_OFFSET 0x6F -#define EEPROM_HT20_MAX_PWR_OFFSET 0x72 - -#define EEPROM_TSSI_A 0x76 -#define EEPROM_TSSI_B 0x77 -#define EEPROM_THERMAL_METER 0x78 -#define EEPROM_XTAL_K 0x78 -#define EEPROM_RF_OPT1 0x79 -#define EEPROM_RF_OPT2 0x7A -#define EEPROM_RF_OPT3 0x7B -#define EEPROM_RF_OPT4 0x7C -#define EEPROM_CHANNEL_PLAN 0x7D -#define EEPROM_VERSION 0x7E -#define EEPROM_CUSTOMER_ID 0x7F - -#define EEPROM_PWRDIFF 0x54 - -#define EEPROM_TXPOWERCCK 0x5A -#define EEPROM_TXPOWERHT40_1S 0x60 -#define EEPROM_TXPOWERHT40_2SDIFF 0x66 -#define EEPROM_TXPOWERHT20DIFF 0x69 -#define EEPROM_TXPOWER_OFDMDIFF 0x6C - -#define EEPROM_TXPWR_GROUP 0x6F - -#define EEPROM_CHANNELPLAN 0x75 - -#define STOPBECON BIT(6) -#define STOPHIGHT BIT(5) -#define STOPMGT BIT(4) -#define STOPVO BIT(3) -#define STOPVI BIT(2) -#define STOPBE BIT(1) -#define STOPBK BIT(0) - -#define RCR_APPFCS BIT(31) -#define RCR_APP_FCS BIT(31) -#define RCR_APP_MIC BIT(30) -#define RCR_APP_ICV BIT(29) -#define RCR_APP_PHYSTS BIT(28) -#define RCR_APP_PHYST_RXFF BIT(28) -#define RCR_APP_BA_SSN BIT(27) -#define RCR_ENMBID BIT(24) -#define RCR_LSIGEN BIT(23) -#define RCR_MFBEN BIT(22) -#define RCR_HTC_LOC_CTRL BIT(14) -#define RCR_AMF BIT(13) -#define RCR_ACF BIT(12) -#define RCR_ADF BIT(11) -#define RCR_AICV BIT(9) -#define RCR_ACRC32 BIT(8) -#define RCR_CBSSID_BCN BIT(7) -#define RCR_CBSSID_DATA BIT(6) -#define RCR_CBSSID RCR_CBSSID_DATA -#define RCR_APWRMGT BIT(5) -#define RCR_ADD3 BIT(4) -#define RCR_AB BIT(3) -#define RCR_AM BIT(2) -#define RCR_APM BIT(1) -#define RCR_AAP BIT(0) -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - -#define RSV_CTRL 0x001C -#define RD_CTRL 0x0524 - -#define REG_USB_VID 0xFE60 -#define REG_USB_PID 0xFE62 -#define REG_USB_OPTIONAL 0xFE64 -#define REG_USB_CHIRP_K 0xFE65 -#define REG_USB_PHY 0xFE66 -#define REG_USB_MAC_ADDR 0xFE70 -#define REG_USB_HRPWM 0xFE58 -#define REG_USB_HCPWM 0xFE57 - -#define SW18_FPWM BIT(3) - -#define ISO_MD2PP BIT(0) -#define ISO_UA2USB BIT(1) -#define ISO_UD2CORE BIT(2) -#define ISO_PA2PCIE BIT(3) -#define ISO_PD2CORE BIT(4) -#define ISO_IP2MAC BIT(5) -#define ISO_DIOP BIT(6) -#define ISO_DIOE BIT(7) -#define ISO_EB2CORE BIT(8) -#define ISO_DIOR BIT(9) - -#define PWC_EV25V BIT(14) -#define PWC_EV12V BIT(15) - -#define FEN_BBRSTB BIT(0) -#define FEN_BB_GLB_RSTn BIT(1) -#define FEN_USBA BIT(2) -#define FEN_UPLL BIT(3) -#define FEN_USBD BIT(4) -#define FEN_DIO_PCIE BIT(5) -#define FEN_PCIEA BIT(6) -#define FEN_PPLL BIT(7) -#define FEN_PCIED BIT(8) -#define FEN_DIOE BIT(9) -#define FEN_CPUEN BIT(10) -#define FEN_DCORE BIT(11) -#define FEN_ELDR BIT(12) -#define FEN_DIO_RF BIT(13) -#define FEN_HWPDN BIT(14) -#define FEN_MREGEN BIT(15) - -#define PFM_LDALL BIT(0) -#define PFM_ALDN BIT(1) -#define PFM_LDKP BIT(2) -#define PFM_WOWL BIT(3) -#define EnPDN BIT(4) -#define PDN_PL BIT(5) -#define APFM_ONMAC BIT(8) -#define APFM_OFF BIT(9) -#define APFM_RSM BIT(10) -#define AFSM_HSUS BIT(11) -#define AFSM_PCIE BIT(12) -#define APDM_MAC BIT(13) -#define APDM_HOST BIT(14) -#define APDM_HPDN BIT(15) -#define RDY_MACON BIT(16) -#define SUS_HOST BIT(17) -#define ROP_ALD BIT(20) -#define ROP_PWR BIT(21) -#define ROP_SPS BIT(22) -#define SOP_MRST BIT(25) -#define SOP_FUSE BIT(26) -#define SOP_ABG BIT(27) -#define SOP_AMB BIT(28) -#define SOP_RCK BIT(29) -#define SOP_A8M BIT(30) -#define XOP_BTCK BIT(31) - -#define ANAD16V_EN BIT(0) -#define ANA8M BIT(1) -#define MACSLP BIT(4) -#define LOADER_CLK_EN BIT(5) -#define _80M_SSC_DIS BIT(7) -#define _80M_SSC_EN_HO BIT(8) -#define PHY_SSC_RSTB BIT(9) -#define SEC_CLK_EN BIT(10) -#define MAC_CLK_EN BIT(11) -#define SYS_CLK_EN BIT(12) -#define RING_CLK_EN BIT(13) - -#define BOOT_FROM_EEPROM BIT(4) -#define EEPROM_EN BIT(5) - -#define AFE_BGEN BIT(0) -#define AFE_MBEN BIT(1) -#define MAC_ID_EN BIT(7) - -#define WLOCK_ALL BIT(0) -#define WLOCK_00 BIT(1) -#define WLOCK_04 BIT(2) -#define WLOCK_08 BIT(3) -#define WLOCK_40 BIT(4) -#define R_DIS_PRST_0 BIT(5) -#define R_DIS_PRST_1 BIT(6) -#define LOCK_ALL_EN BIT(7) - -#define RF_EN BIT(0) -#define RF_RSTB BIT(1) -#define RF_SDMRSTB BIT(2) - -#define LDA15_EN BIT(0) -#define LDA15_STBY BIT(1) -#define LDA15_OBUF BIT(2) -#define LDA15_REG_VOS BIT(3) -#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) - -#define LDV12_EN BIT(0) -#define LDV12_SDBY BIT(1) -#define LPLDO_HSM BIT(2) -#define LPLDO_LSM_DIS BIT(3) -#define _LDV12_VADJ(x) (((x) & 0xF) << 4) - -#define XTAL_EN BIT(0) -#define XTAL_BSEL BIT(1) -#define _XTAL_BOSC(x) (((x) & 0x3) << 2) -#define _XTAL_CADJ(x) (((x) & 0xF) << 4) -#define XTAL_GATE_USB BIT(8) -#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) -#define XTAL_GATE_AFE BIT(11) -#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) -#define XTAL_RF_GATE BIT(14) -#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) -#define XTAL_GATE_DIG BIT(17) -#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) -#define XTAL_BT_GATE BIT(20) -#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) -#define _XTAL_GPIO(x) (((x) & 0x7) << 23) - -#define CKDLY_AFE BIT(26) -#define CKDLY_USB BIT(27) -#define CKDLY_DIG BIT(28) -#define CKDLY_BT BIT(29) - -#define APLL_EN BIT(0) -#define APLL_320_EN BIT(1) -#define APLL_FREF_SEL BIT(2) -#define APLL_EDGE_SEL BIT(3) -#define APLL_WDOGB BIT(4) -#define APLL_LPFEN BIT(5) - -#define APLL_REF_CLK_13MHZ 0x1 -#define APLL_REF_CLK_19_2MHZ 0x2 -#define APLL_REF_CLK_20MHZ 0x3 -#define APLL_REF_CLK_25MHZ 0x4 -#define APLL_REF_CLK_26MHZ 0x5 -#define APLL_REF_CLK_38_4MHZ 0x6 -#define APLL_REF_CLK_40MHZ 0x7 - -#define APLL_320EN BIT(14) -#define APLL_80EN BIT(15) -#define APLL_1MEN BIT(24) - -#define ALD_EN BIT(18) -#define EF_PD BIT(19) -#define EF_FLAG BIT(31) - -#define EF_TRPT BIT(7) -#define LDOE25_EN BIT(31) - -#define RSM_EN BIT(0) -#define Timer_EN BIT(4) - -#define TRSW0EN BIT(2) -#define TRSW1EN BIT(3) -#define EROM_EN BIT(4) -#define EnBT BIT(5) -#define EnUart BIT(8) -#define Uart_910 BIT(9) -#define EnPMAC BIT(10) -#define SIC_SWRST BIT(11) -#define EnSIC BIT(12) -#define SIC_23 BIT(13) -#define EnHDP BIT(14) -#define SIC_LBK BIT(15) - -#define LED0PL BIT(4) -#define LED1PL BIT(12) -#define LED0DIS BIT(7) - -#define MCUFWDL_EN BIT(0) -#define MCUFWDL_RDY BIT(1) -#define FWDL_ChkSum_rpt BIT(2) -#define MACINI_RDY BIT(3) -#define BBINI_RDY BIT(4) -#define RFINI_RDY BIT(5) -#define WINTINI_RDY BIT(6) -#define CPRST BIT(23) - -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define TRP_B15V_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define BT_FUNC BIT(16) -#define VENDOR_ID BIT(19) -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) -#define RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28)) - -#define CHIP_VER_RTL_MASK 0xF000 -#define CHIP_VER_RTL_SHIFT 12 - -#define REG_LBMODE (REG_CR + 3) - -#define HCI_TXDMA_EN BIT(0) -#define HCI_RXDMA_EN BIT(1) -#define TXDMA_EN BIT(2) -#define RXDMA_EN BIT(3) -#define PROTOCOL_EN BIT(4) -#define SCHEDULE_EN BIT(5) -#define MACTXEN BIT(6) -#define MACRXEN BIT(7) -#define ENSWBCN BIT(8) -#define ENSEC BIT(9) - -#define _NETTYPE(x) (((x) & 0x3) << 16) -#define MASK_NETTYPE 0x30000 -#define NT_NO_LINK 0x0 -#define NT_LINK_AD_HOC 0x1 -#define NT_LINK_AP 0x2 -#define NT_AS_AP 0x3 - -#define _LBMODE(x) (((x) & 0xF) << 24) -#define MASK_LBMODE 0xF000000 -#define LOOPBACK_NORMAL 0x0 -#define LOOPBACK_IMMEDIATELY 0xB -#define LOOPBACK_MAC_DELAY 0x3 -#define LOOPBACK_PHY 0x1 -#define LOOPBACK_DMA 0x7 - -#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) -#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) -#define _PSRX_MASK 0xF -#define _PSTX_MASK 0xF0 -#define _PSRX(x) (x) -#define _PSTX(x) ((x) << 4) - -#define PBP_64 0x0 -#define PBP_128 0x1 -#define PBP_256 0x2 -#define PBP_512 0x3 -#define PBP_1024 0x4 - -#define RXDMA_ARBBW_EN BIT(0) -#define RXSHFT_EN BIT(1) -#define RXDMA_AGG_EN BIT(2) -#define QS_VO_QUEUE BIT(8) -#define QS_VI_QUEUE BIT(9) -#define QS_BE_QUEUE BIT(10) -#define QS_BK_QUEUE BIT(11) -#define QS_MANAGER_QUEUE BIT(12) -#define QS_HIGH_QUEUE BIT(13) - -#define HQSEL_VOQ BIT(0) -#define HQSEL_VIQ BIT(1) -#define HQSEL_BEQ BIT(2) -#define HQSEL_BKQ BIT(3) -#define HQSEL_MGTQ BIT(4) -#define HQSEL_HIQ BIT(5) - -#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) -#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) -#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) -#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) -#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) -#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) - -#define QUEUE_LOW 1 -#define QUEUE_NORMAL 2 -#define QUEUE_HIGH 3 - -#define _LLT_NO_ACTIVE 0x0 -#define _LLT_WRITE_ACCESS 0x1 -#define _LLT_READ_ACCESS 0x2 - -#define _LLT_INIT_DATA(x) ((x) & 0xFF) -#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) -#define _LLT_OP(x) (((x) & 0x3) << 30) -#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) - -#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) -#define BB_WRITE_EN BIT(30) -#define BB_READ_EN BIT(31) - -#define _HPQ(x) ((x) & 0xFF) -#define _LPQ(x) (((x) & 0xFF) << 8) -#define _PUBQ(x) (((x) & 0xFF) << 16) -#define _NPQ(x) ((x) & 0xFF) - -#define HPQ_PUBLIC_DIS BIT(24) -#define LPQ_PUBLIC_DIS BIT(25) -#define LD_RQPN BIT(31) - -#define BCN_VALID BIT(16) -#define BCN_HEAD(x) (((x) & 0xFF) << 8) -#define BCN_HEAD_MASK 0xFF00 - -#define BLK_DESC_NUM_SHIFT 4 -#define BLK_DESC_NUM_MASK 0xF - -#define DROP_DATA_EN BIT(9) - -#define EN_AMPDU_RTY_NEW BIT(7) - -#define _INIRTSMCS_SEL(x) ((x) & 0x3F) - -#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) -#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) - -#define RATE_REG_BITMAP_ALL 0xFFFFF - -#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) - -#define _RRSR_RSC(x) (((x) & 0x3) << 21) -#define RRSR_RSC_RESERVED 0x0 -#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 -#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 -#define RRSR_RSC_DUPLICATE_MODE 0x3 - -#define USE_SHORT_G1 BIT(20) - -#define _AGGLMT_MCS0(x) ((x) & 0xF) -#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) -#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) -#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) -#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) -#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) -#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) -#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) - -#define RETRY_LIMIT_SHORT_SHIFT 8 -#define RETRY_LIMIT_LONG_SHIFT 0 - -#define _DARF_RC1(x) ((x) & 0x1F) -#define _DARF_RC2(x) (((x) & 0x1F) << 8) -#define _DARF_RC3(x) (((x) & 0x1F) << 16) -#define _DARF_RC4(x) (((x) & 0x1F) << 24) -#define _DARF_RC5(x) ((x) & 0x1F) -#define _DARF_RC6(x) (((x) & 0x1F) << 8) -#define _DARF_RC7(x) (((x) & 0x1F) << 16) -#define _DARF_RC8(x) (((x) & 0x1F) << 24) - -#define _RARF_RC1(x) ((x) & 0x1F) -#define _RARF_RC2(x) (((x) & 0x1F) << 8) -#define _RARF_RC3(x) (((x) & 0x1F) << 16) -#define _RARF_RC4(x) (((x) & 0x1F) << 24) -#define _RARF_RC5(x) ((x) & 0x1F) -#define _RARF_RC6(x) (((x) & 0x1F) << 8) -#define _RARF_RC7(x) (((x) & 0x1F) << 16) -#define _RARF_RC8(x) (((x) & 0x1F) << 24) - -#define AC_PARAM_TXOP_OFFSET 16 -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - -#define _AIFS(x) (x) -#define _ECW_MAX_MIN(x) ((x) << 8) -#define _TXOP_LIMIT(x) ((x) << 16) - -#define _BCNIFS(x) ((x) & 0xFF) -#define _BCNECW(x) ((((x) & 0xF)) << 8) - -#define _LRL(x) ((x) & 0x3F) -#define _SRL(x) (((x) & 0x3F) << 8) - -#define _SIFS_CCK_CTX(x) ((x) & 0xFF) -#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8) - -#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) -#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8) - -#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) - -#define DIS_EDCA_CNT_DWN BIT(11) - -#define EN_MBSSID BIT(1) -#define EN_TXBCN_RPT BIT(2) -#define EN_BCN_FUNCTION BIT(3) - -#define TSFTR_RST BIT(0) -#define TSFTR1_RST BIT(1) - -#define STOP_BCNQ BIT(6) - -#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) -#define DIS_TSF_UDT0_TEST_CHIP BIT(5) - -#define AcmHw_HwEn BIT(0) -#define AcmHw_BeqEn BIT(1) -#define AcmHw_ViqEn BIT(2) -#define AcmHw_VoqEn BIT(3) -#define AcmHw_BeqStatus BIT(4) -#define AcmHw_ViqStatus BIT(5) -#define AcmHw_VoqStatus BIT(6) - -#define APSDOFF BIT(6) -#define APSDOFF_STATUS BIT(7) - -#define BW_20MHZ BIT(2) - -#define RATE_BITMAP_ALL 0xFFFFF - -#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 - -#define TSFRST BIT(0) -#define DIS_GCLK BIT(1) -#define PAD_SEL BIT(2) -#define PWR_ST BIT(6) -#define PWRBIT_OW_EN BIT(7) -#define ACRC BIT(8) -#define CFENDFORM BIT(9) -#define ICV BIT(10) - -#define AAP BIT(0) -#define APM BIT(1) -#define AM BIT(2) -#define AB BIT(3) -#define ADD3 BIT(4) -#define APWRMGT BIT(5) -#define CBSSID BIT(6) -#define CBSSID_DATA BIT(6) -#define CBSSID_BCN BIT(7) -#define ACRC32 BIT(8) -#define AICV BIT(9) -#define ADF BIT(11) -#define ACF BIT(12) -#define AMF BIT(13) -#define HTC_LOC_CTRL BIT(14) -#define UC_DATA_EN BIT(16) -#define BM_DATA_EN BIT(17) -#define MFBEN BIT(22) -#define LSIGEN BIT(23) -#define EnMBID BIT(24) -#define APP_BASSN BIT(27) -#define APP_PHYSTS BIT(28) -#define APP_ICV BIT(29) -#define APP_MIC BIT(30) -#define APP_FCS BIT(31) - -#define _MIN_SPACE(x) ((x) & 0x7) -#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) - -#define RXERR_TYPE_OFDM_PPDU 0 -#define RXERR_TYPE_OFDM_FALSE_ALARM 1 -#define RXERR_TYPE_OFDM_MPDU_OK 2 -#define RXERR_TYPE_OFDM_MPDU_FAIL 3 -#define RXERR_TYPE_CCK_PPDU 4 -#define RXERR_TYPE_CCK_FALSE_ALARM 5 -#define RXERR_TYPE_CCK_MPDU_OK 6 -#define RXERR_TYPE_CCK_MPDU_FAIL 7 -#define RXERR_TYPE_HT_PPDU 8 -#define RXERR_TYPE_HT_FALSE_ALARM 9 -#define RXERR_TYPE_HT_MPDU_TOTAL 10 -#define RXERR_TYPE_HT_MPDU_OK 11 -#define RXERR_TYPE_HT_MPDU_FAIL 12 -#define RXERR_TYPE_RX_FULL_DROP 15 - -#define RXERR_COUNTER_MASK 0xFFFFF -#define RXERR_RPT_RST BIT(27) -#define _RXERR_RPT_SEL(type) ((type) << 28) - -#define SCR_TxUseDK BIT(0) -#define SCR_RxUseDK BIT(1) -#define SCR_TxEncEnable BIT(2) -#define SCR_RxDecEnable BIT(3) -#define SCR_SKByA2 BIT(4) -#define SCR_NoSKMC BIT(5) -#define SCR_TXBCUSEDK BIT(6) -#define SCR_RXBCUSEDK BIT(7) - -#define USB_IS_HIGH_SPEED 0 -#define USB_IS_FULL_SPEED 1 -#define USB_SPEED_MASK BIT(5) - -#define USB_NORMAL_SIE_EP_MASK 0xF -#define USB_NORMAL_SIE_EP_SHIFT 4 - -#define USB_TEST_EP_MASK 0x30 -#define USB_TEST_EP_SHIFT 4 - -#define USB_AGG_EN BIT(3) - -#define LAST_ENTRY_OF_TX_PKT_BUFFER 255 - -#define POLLING_LLT_THRESHOLD 20 -#define POLLING_READY_TIMEOUT_COUNT 1000 - -#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) -#define EPROM_CMD_CONFIG 0x3 -#define EPROM_CMD_LOAD 1 - -#define HWSET_MAX_SIZE 128 -#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE -#define EFUSE_MAX_SECTION 16 - -#define WL_HWPDN_EN BIT(0) - -#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) - -#define RPMAC_RESET 0x100 -#define RPMAC_TXSTART 0x104 -#define RPMAC_TXLEGACYSIG 0x108 -#define RPMAC_TXHTSIG1 0x10c -#define RPMAC_TXHTSIG2 0x110 -#define RPMAC_PHYDEBUG 0x114 -#define RPMAC_TXPACKETNUM 0x118 -#define RPMAC_TXIDLE 0x11c -#define RPMAC_TXMACHEADER0 0x120 -#define RPMAC_TXMACHEADER1 0x124 -#define RPMAC_TXMACHEADER2 0x128 -#define RPMAC_TXMACHEADER3 0x12c -#define RPMAC_TXMACHEADER4 0x130 -#define RPMAC_TXMACHEADER5 0x134 -#define RPMAC_TXDADATYPE 0x138 -#define RPMAC_TXRANDOMSEED 0x13c -#define RPMAC_CCKPLCPPREAMBLE 0x140 -#define RPMAC_CCKPLCPHEADER 0x144 -#define RPMAC_CCKCRC16 0x148 -#define RPMAC_OFDMRXCRC32OK 0x170 -#define RPMAC_OFDMRXCRC32Er 0x174 -#define RPMAC_OFDMRXPARITYER 0x178 -#define RPMAC_OFDMRXCRC8ER 0x17c -#define RPMAC_CCKCRXRC16ER 0x180 -#define RPMAC_CCKCRXRC32ER 0x184 -#define RPMAC_CCKCRXRC32OK 0x188 -#define RPMAC_TXSTATUS 0x18c - -#define RFPGA0_RFMOD 0x800 - -#define RFPGA0_TXINFO 0x804 -#define RFPGA0_PSDFUNCTION 0x808 - -#define RFPGA0_TXGAINSTAGE 0x80c - -#define RFPGA0_RFTIMING1 0x810 -#define RFPGA0_RFTIMING2 0x814 - -#define RFPGA0_XA_HSSIPARAMETER1 0x820 -#define RFPGA0_XA_HSSIPARAMETER2 0x824 -#define RFPGA0_XB_HSSIPARAMETER1 0x828 -#define RFPGA0_XB_HSSIPARAMETER2 0x82c - -#define RFPGA0_XA_LSSIPARAMETER 0x840 -#define RFPGA0_XB_LSSIPARAMETER 0x844 - -#define RFPGA0_RFWAKEUPPARAMETER 0x850 -#define RFPGA0_RFSLEEPUPPARAMETER 0x854 - -#define RFPGA0_XAB_SWITCHCONTROL 0x858 -#define RFPGA0_XCD_SWITCHCONTROL 0x85c - -#define RFPGA0_XA_RFINTERFACEOE 0x860 -#define RFPGA0_XB_RFINTERFACEOE 0x864 - -#define RFPGA0_XAB_RFINTERFACESW 0x870 -#define RFPGA0_XCD_RFINTERFACESW 0x874 - -#define rFPGA0_XAB_RFPARAMETER 0x878 -#define rFPGA0_XCD_RFPARAMETER 0x87c - -#define RFPGA0_ANALOGPARAMETER1 0x880 -#define RFPGA0_ANALOGPARAMETER2 0x884 -#define RFPGA0_ANALOGPARAMETER3 0x888 -#define RFPGA0_ANALOGPARAMETER4 0x88c - -#define RFPGA0_XA_LSSIREADBACK 0x8a0 -#define RFPGA0_XB_LSSIREADBACK 0x8a4 -#define RFPGA0_XC_LSSIREADBACK 0x8a8 -#define RFPGA0_XD_LSSIREADBACK 0x8ac - -#define RFPGA0_PSDREPORT 0x8b4 -#define TRANSCEIVEA_HSPI_READBACK 0x8b8 -#define TRANSCEIVEB_HSPI_READBACK 0x8bc -#define RFPGA0_XAB_RFINTERFACERB 0x8e0 -#define RFPGA0_XCD_RFINTERFACERB 0x8e4 - -#define RFPGA1_RFMOD 0x900 - -#define RFPGA1_TXBLOCK 0x904 -#define RFPGA1_DEBUGSELECT 0x908 -#define RFPGA1_TXINFO 0x90c - -#define RCCK0_SYSTEM 0xa00 - -#define RCCK0_AFESETTING 0xa04 -#define RCCK0_CCA 0xa08 - -#define RCCK0_RXAGC1 0xa0c -#define RCCK0_RXAGC2 0xa10 - -#define RCCK0_RXHP 0xa14 - -#define RCCK0_DSPPARAMETER1 0xa18 -#define RCCK0_DSPPARAMETER2 0xa1c - -#define RCCK0_TXFILTER1 0xa20 -#define RCCK0_TXFILTER2 0xa24 -#define RCCK0_DEBUGPORT 0xa28 -#define RCCK0_FALSEALARMREPORT 0xa2c -#define RCCK0_TRSSIREPORT 0xa50 -#define RCCK0_RXREPORT 0xa54 -#define RCCK0_FACOUNTERLOWER 0xa5c -#define RCCK0_FACOUNTERUPPER 0xa58 - -#define ROFDM0_LSTF 0xc00 - -#define ROFDM0_TRXPATHENABLE 0xc04 -#define ROFDM0_TRMUXPAR 0xc08 -#define ROFDM0_TRSWISOLATION 0xc0c - -#define ROFDM0_XARXAFE 0xc10 -#define ROFDM0_XARXIQIMBALANCE 0xc14 -#define ROFDM0_XBRXAFE 0xc18 -#define ROFDM0_XBRXIQIMBALANCE 0xc1c -#define ROFDM0_XCRXAFE 0xc20 -#define ROFDM0_XCRXIQIMBANLANCE 0xc24 -#define ROFDM0_XDRXAFE 0xc28 -#define ROFDM0_XDRXIQIMBALANCE 0xc2c - -#define ROFDM0_RXDETECTOR1 0xc30 -#define ROFDM0_RXDETECTOR2 0xc34 -#define ROFDM0_RXDETECTOR3 0xc38 -#define ROFDM0_RXDETECTOR4 0xc3c - -#define ROFDM0_RXDSP 0xc40 -#define ROFDM0_CFOANDDAGC 0xc44 -#define ROFDM0_CCADROPTHRESHOLD 0xc48 -#define ROFDM0_ECCATHRESHOLD 0xc4c - -#define ROFDM0_XAAGCCORE1 0xc50 -#define ROFDM0_XAAGCCORE2 0xc54 -#define ROFDM0_XBAGCCORE1 0xc58 -#define ROFDM0_XBAGCCORE2 0xc5c -#define ROFDM0_XCAGCCORE1 0xc60 -#define ROFDM0_XCAGCCORE2 0xc64 -#define ROFDM0_XDAGCCORE1 0xc68 -#define ROFDM0_XDAGCCORE2 0xc6c - -#define ROFDM0_AGCPARAMETER1 0xc70 -#define ROFDM0_AGCPARAMETER2 0xc74 -#define ROFDM0_AGCRSSITABLE 0xc78 -#define ROFDM0_HTSTFAGC 0xc7c - -#define ROFDM0_XATXIQIMBALANCE 0xc80 -#define ROFDM0_XATXAFE 0xc84 -#define ROFDM0_XBTXIQIMBALANCE 0xc88 -#define ROFDM0_XBTXAFE 0xc8c -#define ROFDM0_XCTXIQIMBALANCE 0xc90 -#define ROFDM0_XCTXAFE 0xc94 -#define ROFDM0_XDTXIQIMBALANCE 0xc98 -#define ROFDM0_XDTXAFE 0xc9c - -#define ROFDM0_RXIQEXTANTA 0xca0 - -#define ROFDM0_RXHPPARAMETER 0xce0 -#define ROFDM0_TXPSEUDONOISEWGT 0xce4 -#define ROFDM0_FRAMESYNC 0xcf0 -#define ROFDM0_DFSREPORT 0xcf4 -#define ROFDM0_TXCOEFF1 0xca4 -#define ROFDM0_TXCOEFF2 0xca8 -#define ROFDM0_TXCOEFF3 0xcac -#define ROFDM0_TXCOEFF4 0xcb0 -#define ROFDM0_TXCOEFF5 0xcb4 -#define ROFDM0_TXCOEFF6 0xcb8 - -#define ROFDM1_LSTF 0xd00 -#define ROFDM1_TRXPATHENABLE 0xd04 - -#define ROFDM1_CF0 0xd08 -#define ROFDM1_CSI1 0xd10 -#define ROFDM1_SBD 0xd14 -#define ROFDM1_CSI2 0xd18 -#define ROFDM1_CFOTRACKING 0xd2c -#define ROFDM1_TRXMESAURE1 0xd34 -#define ROFDM1_INTFDET 0xd3c -#define ROFDM1_PSEUDONOISESTATEAB 0xd50 -#define ROFDM1_PSEUDONOISESTATECD 0xd54 -#define ROFDM1_RXPSEUDONOISEWGT 0xd58 - -#define ROFDM_PHYCOUNTER1 0xda0 -#define ROFDM_PHYCOUNTER2 0xda4 -#define ROFDM_PHYCOUNTER3 0xda8 - -#define ROFDM_SHORTCFOAB 0xdac -#define ROFDM_SHORTCFOCD 0xdb0 -#define ROFDM_LONGCFOAB 0xdb4 -#define ROFDM_LONGCFOCD 0xdb8 -#define ROFDM_TAILCF0AB 0xdbc -#define ROFDM_TAILCF0CD 0xdc0 -#define ROFDM_PWMEASURE1 0xdc4 -#define ROFDM_PWMEASURE2 0xdc8 -#define ROFDM_BWREPORT 0xdcc -#define ROFDM_AGCREPORT 0xdd0 -#define ROFDM_RXSNR 0xdd4 -#define ROFDM_RXEVMCSI 0xdd8 -#define ROFDM_SIGREPORT 0xddc - -#define RTXAGC_A_RATE18_06 0xe00 -#define RTXAGC_A_RATE54_24 0xe04 -#define RTXAGC_A_CCK1_MCS32 0xe08 -#define RTXAGC_A_MCS03_MCS00 0xe10 -#define RTXAGC_A_MCS07_MCS04 0xe14 -#define RTXAGC_A_MCS11_MCS08 0xe18 -#define RTXAGC_A_MCS15_MCS12 0xe1c - -#define RTXAGC_B_RATE18_06 0x830 -#define RTXAGC_B_RATE54_24 0x834 -#define RTXAGC_B_CCK1_55_MCS32 0x838 -#define RTXAGC_B_MCS03_MCS00 0x83c -#define RTXAGC_B_MCS07_MCS04 0x848 -#define RTXAGC_B_MCS11_MCS08 0x84c -#define RTXAGC_B_MCS15_MCS12 0x868 -#define RTXAGC_B_CCK11_A_CCK2_11 0x86c - -#define RZEBRA1_HSSIENABLE 0x0 -#define RZEBRA1_TRXENABLE1 0x1 -#define RZEBRA1_TRXENABLE2 0x2 -#define RZEBRA1_AGC 0x4 -#define RZEBRA1_CHARGEPUMP 0x5 -#define RZEBRA1_CHANNEL 0x7 - -#define RZEBRA1_TXGAIN 0x8 -#define RZEBRA1_TXLPF 0x9 -#define RZEBRA1_RXLPF 0xb -#define RZEBRA1_RXHPFCORNER 0xc - -#define RGLOBALCTRL 0 -#define RRTL8256_TXLPF 19 -#define RRTL8256_RXLPF 11 -#define RRTL8258_TXLPF 0x11 -#define RRTL8258_RXLPF 0x13 -#define RRTL8258_RSSILPF 0xa - -#define RF_AC 0x00 - -#define RF_IQADJ_G1 0x01 -#define RF_IQADJ_G2 0x02 -#define RF_POW_TRSW 0x05 - -#define RF_GAIN_RX 0x06 -#define RF_GAIN_TX 0x07 - -#define RF_TXM_IDAC 0x08 -#define RF_BS_IQGEN 0x0F - -#define RF_MODE1 0x10 -#define RF_MODE2 0x11 - -#define RF_RX_AGC_HP 0x12 -#define RF_TX_AGC 0x13 -#define RF_BIAS 0x14 -#define RF_IPA 0x15 -#define RF_POW_ABILITY 0x17 -#define RF_MODE_AG 0x18 -#define RRFCHANNEL 0x18 -#define RF_CHNLBW 0x18 -#define RF_TOP 0x19 - -#define RF_RX_G1 0x1A -#define RF_RX_G2 0x1B - -#define RF_RX_BB2 0x1C -#define RF_RX_BB1 0x1D - -#define RF_RCK1 0x1E -#define RF_RCK2 0x1F - -#define RF_TX_G1 0x20 -#define RF_TX_G2 0x21 -#define RF_TX_G3 0x22 - -#define RF_TX_BB1 0x23 -#define RF_T_METER 0x24 - -#define RF_SYN_G1 0x25 -#define RF_SYN_G2 0x26 -#define RF_SYN_G3 0x27 -#define RF_SYN_G4 0x28 -#define RF_SYN_G5 0x29 -#define RF_SYN_G6 0x2A -#define RF_SYN_G7 0x2B -#define RF_SYN_G8 0x2C - -#define RF_RCK_OS 0x30 -#define RF_TXPA_G1 0x31 -#define RF_TXPA_G2 0x32 -#define RF_TXPA_G3 0x33 - -#define BBBRESETB 0x100 -#define BGLOBALRESETB 0x200 -#define BOFDMTXSTART 0x4 -#define BCCKTXSTART 0x8 -#define BCRC32DEBUG 0x100 -#define BPMACLOOPBACK 0x10 -#define BTXLSIG 0xffffff -#define BOFDMTXRATE 0xf -#define BOFDMTXRESERVED 0x10 -#define BOFDMTXLENGTH 0x1ffe0 -#define BOFDMTXPARITY 0x20000 -#define BTXHTSIG1 0xffffff -#define BTXHTMCSRATE 0x7f -#define BTXHTBW 0x80 -#define BTXHTLENGTH 0xffff00 -#define BTXHTSIG2 0xffffff -#define BTXHTSMOOTHING 0x1 -#define BTXHTSOUNDING 0x2 -#define BTXHTRESERVED 0x4 -#define BTXHTAGGREATION 0x8 -#define BTXHTSTBC 0x30 -#define BTXHTADVANCECODING 0x40 -#define BTXHTSHORTGI 0x80 -#define BTXHTNUMBERHT_LTF 0x300 -#define BTXHTCRC8 0x3fc00 -#define BCOUNTERRESET 0x10000 -#define BNUMOFOFDMTX 0xffff -#define BNUMOFCCKTX 0xffff0000 -#define BTXIDLEINTERVAL 0xffff -#define BOFDMSERVICE 0xffff0000 -#define BTXMACHEADER 0xffffffff -#define BTXDATAINIT 0xff -#define BTXHTMODE 0x100 -#define BTXDATATYPE 0x30000 -#define BTXRANDOMSEED 0xffffffff -#define BCCKTXPREAMBLE 0x1 -#define BCCKTXSFD 0xffff0000 -#define BCCKTXSIG 0xff -#define BCCKTXSERVICE 0xff00 -#define BCCKLENGTHEXT 0x8000 -#define BCCKTXLENGHT 0xffff0000 -#define BCCKTXCRC16 0xffff -#define BCCKTXSTATUS 0x1 -#define BOFDMTXSTATUS 0x2 -#define IS_BB_REG_OFFSET_92S(_Offset) \ - ((_Offset >= 0x800) && (_Offset <= 0xfff)) - -#define BRFMOD 0x1 -#define BJAPANMODE 0x2 -#define BCCKTXSC 0x30 -#define BCCKEN 0x1000000 -#define BOFDMEN 0x2000000 - -#define BOFDMRXADCPHASE 0x10000 -#define BOFDMTXDACPHASE 0x40000 -#define BXATXAGC 0x3f - -#define BXBTXAGC 0xf00 -#define BXCTXAGC 0xf000 -#define BXDTXAGC 0xf0000 - -#define BPASTART 0xf0000000 -#define BTRSTART 0x00f00000 -#define BRFSTART 0x0000f000 -#define BBBSTART 0x000000f0 -#define BBBCCKSTART 0x0000000f -#define BPAEND 0xf -#define BTREND 0x0f000000 -#define BRFEND 0x000f0000 -#define BCCAMASK 0x000000f0 -#define BR2RCCAMASK 0x00000f00 -#define BHSSI_R2TDELAY 0xf8000000 -#define BHSSI_T2RDELAY 0xf80000 -#define BCONTXHSSI 0x400 -#define BIGFROMCCK 0x200 -#define BAGCADDRESS 0x3f -#define BRXHPTX 0x7000 -#define BRXHP2RX 0x38000 -#define BRXHPCCKINI 0xc0000 -#define BAGCTXCODE 0xc00000 -#define BAGCRXCODE 0x300000 - -#define B3WIREDATALENGTH 0x800 -#define B3WIREADDREAALENGTH 0x400 - -#define B3WIRERFPOWERDOWN 0x1 -#define B5GPAPEPOLARITY 0x40000000 -#define B2GPAPEPOLARITY 0x80000000 -#define BRFSW_TXDEFAULTANT 0x3 -#define BRFSW_TXOPTIONANT 0x30 -#define BRFSW_RXDEFAULTANT 0x300 -#define BRFSW_RXOPTIONANT 0x3000 -#define BRFSI_3WIREDATA 0x1 -#define BRFSI_3WIRECLOCK 0x2 -#define BRFSI_3WIRELOAD 0x4 -#define BRFSI_3WIRERW 0x8 -#define BRFSI_3WIRE 0xf - -#define BRFSI_RFENV 0x10 - -#define BRFSI_TRSW 0x20 -#define BRFSI_TRSWB 0x40 -#define BRFSI_ANTSW 0x100 -#define BRFSI_ANTSWB 0x200 -#define BRFSI_PAPE 0x400 -#define BRFSI_PAPE5G 0x800 -#define BBANDSELECT 0x1 -#define BHTSIG2_GI 0x80 -#define BHTSIG2_SMOOTHING 0x01 -#define BHTSIG2_SOUNDING 0x02 -#define BHTSIG2_AGGREATON 0x08 -#define BHTSIG2_STBC 0x30 -#define BHTSIG2_ADVCODING 0x40 -#define BHTSIG2_NUMOFHTLTF 0x300 -#define BHTSIG2_CRC8 0x3fc -#define BHTSIG1_MCS 0x7f -#define BHTSIG1_BANDWIDTH 0x80 -#define BHTSIG1_HTLENGTH 0xffff -#define BLSIG_RATE 0xf -#define BLSIG_RESERVED 0x10 -#define BLSIG_LENGTH 0x1fffe -#define BLSIG_PARITY 0x20 -#define BCCKRXPHASE 0x4 - -#define BLSSIREADADDRESS 0x7f800000 -#define BLSSIREADEDGE 0x80000000 - -#define BLSSIREADBACKDATA 0xfffff - -#define BLSSIREADOKFLAG 0x1000 -#define BCCKSAMPLERATE 0x8 -#define BREGULATOR0STANDBY 0x1 -#define BREGULATORPLLSTANDBY 0x2 -#define BREGULATOR1STANDBY 0x4 -#define BPLLPOWERUP 0x8 -#define BDPLLPOWERUP 0x10 -#define BDA10POWERUP 0x20 -#define BAD7POWERUP 0x200 -#define BDA6POWERUP 0x2000 -#define BXTALPOWERUP 0x4000 -#define B40MDCLKPOWERUP 0x8000 -#define BDA6DEBUGMODE 0x20000 -#define BDA6SWING 0x380000 - -#define BADCLKPHASE 0x4000000 -#define B80MCLKDELAY 0x18000000 -#define BAFEWATCHDOGENABLE 0x20000000 - -#define BXTALCAP01 0xc0000000 -#define BXTALCAP23 0x3 -#define BXTALCAP92X 0x0f000000 -#define BXTALCAP 0x0f000000 - -#define BINTDIFCLKENABLE 0x400 -#define BEXTSIGCLKENABLE 0x800 -#define BBANDGAP_MBIAS_POWERUP 0x10000 -#define BAD11SH_GAIN 0xc0000 -#define BAD11NPUT_RANGE 0x700000 -#define BAD110P_CURRENT 0x3800000 -#define BLPATH_LOOPBACK 0x4000000 -#define BQPATH_LOOPBACK 0x8000000 -#define BAFE_LOOPBACK 0x10000000 -#define BDA10_SWING 0x7e0 -#define BDA10_REVERSE 0x800 -#define BDA_CLK_SOURCE 0x1000 -#define BDA7INPUT_RANGE 0x6000 -#define BDA7_GAIN 0x38000 -#define BDA7OUTPUT_CM_MODE 0x40000 -#define BDA7INPUT_CM_MODE 0x380000 -#define BDA7CURRENT 0xc00000 -#define BREGULATOR_ADJUST 0x7000000 -#define BAD11POWERUP_ATTX 0x1 -#define BDA10PS_ATTX 0x10 -#define BAD11POWERUP_ATRX 0x100 -#define BDA10PS_ATRX 0x1000 -#define BCCKRX_AGC_FORMAT 0x200 -#define BPSDFFT_SAMPLE_POINT 0xc000 -#define BPSD_AVERAGE_NUM 0x3000 -#define BIQPATH_CONTROL 0xc00 -#define BPSD_FREQ 0x3ff -#define BPSD_ANTENNA_PATH 0x30 -#define BPSD_IQ_SWITCH 0x40 -#define BPSD_RX_TRIGGER 0x400000 -#define BPSD_TX_TRIGGER 0x80000000 -#define BPSD_SINE_TONE_SCALE 0x7f000000 -#define BPSD_REPORT 0xffff - -#define BOFDM_TXSC 0x30000000 -#define BCCK_TXON 0x1 -#define BOFDM_TXON 0x2 -#define BDEBUG_PAGE 0xfff -#define BDEBUG_ITEM 0xff -#define BANTL 0x10 -#define BANT_NONHT 0x100 -#define BANT_HT1 0x1000 -#define BANT_HT2 0x10000 -#define BANT_HT1S1 0x100000 -#define BANT_NONHTS1 0x1000000 - -#define BCCK_BBMODE 0x3 -#define BCCK_TXPOWERSAVING 0x80 -#define BCCK_RXPOWERSAVING 0x40 - -#define BCCK_SIDEBAND 0x10 - -#define BCCK_SCRAMBLE 0x8 -#define BCCK_ANTDIVERSITY 0x8000 -#define BCCK_CARRIER_RECOVERY 0x4000 -#define BCCK_TXRATE 0x3000 -#define BCCK_DCCANCEL 0x0800 -#define BCCK_ISICANCEL 0x0400 -#define BCCK_MATCH_FILTER 0x0200 -#define BCCK_EQUALIZER 0x0100 -#define BCCK_PREAMBLE_DETECT 0x800000 -#define BCCK_FAST_FALSECCA 0x400000 -#define BCCK_CH_ESTSTART 0x300000 -#define BCCK_CCA_COUNT 0x080000 -#define BCCK_CS_LIM 0x070000 -#define BCCK_BIST_MODE 0x80000000 -#define BCCK_CCAMASK 0x40000000 -#define BCCK_TX_DAC_PHASE 0x4 -#define BCCK_RX_ADC_PHASE 0x20000000 -#define BCCKR_CP_MODE 0x0100 -#define BCCK_TXDC_OFFSET 0xf0 -#define BCCK_RXDC_OFFSET 0xf -#define BCCK_CCA_MODE 0xc000 -#define BCCK_FALSECS_LIM 0x3f00 -#define BCCK_CS_RATIO 0xc00000 -#define BCCK_CORGBIT_SEL 0x300000 -#define BCCK_PD_LIM 0x0f0000 -#define BCCK_NEWCCA 0x80000000 -#define BCCK_RXHP_OF_IG 0x8000 -#define BCCK_RXIG 0x7f00 -#define BCCK_LNA_POLARITY 0x800000 -#define BCCK_RX1ST_BAIN 0x7f0000 -#define BCCK_RF_EXTEND 0x20000000 -#define BCCK_RXAGC_SATLEVEL 0x1f000000 -#define BCCK_RXAGC_SATCOUNT 0xe0 -#define bCCKRxRFSettle 0x1f -#define BCCK_FIXED_RXAGC 0x8000 -#define BCCK_ANTENNA_POLARITY 0x2000 -#define BCCK_TXFILTER_TYPE 0x0c00 -#define BCCK_RXAGC_REPORTTYPE 0x0300 -#define BCCK_RXDAGC_EN 0x80000000 -#define BCCK_RXDAGC_PERIOD 0x20000000 -#define BCCK_RXDAGC_SATLEVEL 0x1f000000 -#define BCCK_TIMING_RECOVERY 0x800000 -#define BCCK_TXC0 0x3f0000 -#define BCCK_TXC1 0x3f000000 -#define BCCK_TXC2 0x3f -#define BCCK_TXC3 0x3f00 -#define BCCK_TXC4 0x3f0000 -#define BCCK_TXC5 0x3f000000 -#define BCCK_TXC6 0x3f -#define BCCK_TXC7 0x3f00 -#define BCCK_DEBUGPORT 0xff0000 -#define BCCK_DAC_DEBUG 0x0f000000 -#define BCCK_FALSEALARM_ENABLE 0x8000 -#define BCCK_FALSEALARM_READ 0x4000 -#define BCCK_TRSSI 0x7f -#define BCCK_RXAGC_REPORT 0xfe -#define BCCK_RXREPORT_ANTSEL 0x80000000 -#define BCCK_RXREPORT_MFOFF 0x40000000 -#define BCCK_RXREPORT_SQLOSS 0x20000000 -#define BCCK_RXREPORT_PKTLOSS 0x10000000 -#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 -#define BCCK_RXREPORT_RATEERROR 0x04000000 -#define BCCK_RXREPORT_RXRATE 0x03000000 -#define BCCK_RXFA_COUNTER_LOWER 0xff -#define BCCK_RXFA_COUNTER_UPPER 0xff000000 -#define BCCK_RXHPAGC_START 0xe000 -#define BCCK_RXHPAGC_FINAL 0x1c00 -#define BCCK_RXFALSEALARM_ENABLE 0x8000 -#define BCCK_FACOUNTER_FREEZE 0x4000 -#define BCCK_TXPATH_SEL 0x10000000 -#define BCCK_DEFAULT_RXPATH 0xc000000 -#define BCCK_OPTION_RXPATH 0x3000000 - -#define BNUM_OFSTF 0x3 -#define BSHIFT_L 0xc0 -#define BGI_TH 0xc -#define BRXPATH_A 0x1 -#define BRXPATH_B 0x2 -#define BRXPATH_C 0x4 -#define BRXPATH_D 0x8 -#define BTXPATH_A 0x1 -#define BTXPATH_B 0x2 -#define BTXPATH_C 0x4 -#define BTXPATH_D 0x8 -#define BTRSSI_FREQ 0x200 -#define BADC_BACKOFF 0x3000 -#define BDFIR_BACKOFF 0xc000 -#define BTRSSI_LATCH_PHASE 0x10000 -#define BRX_LDC_OFFSET 0xff -#define BRX_QDC_OFFSET 0xff00 -#define BRX_DFIR_MODE 0x1800000 -#define BRX_DCNF_TYPE 0xe000000 -#define BRXIQIMB_A 0x3ff -#define BRXIQIMB_B 0xfc00 -#define BRXIQIMB_C 0x3f0000 -#define BRXIQIMB_D 0xffc00000 -#define BDC_DC_NOTCH 0x60000 -#define BRXNB_NOTCH 0x1f000000 -#define BPD_TH 0xf -#define BPD_TH_OPT2 0xc000 -#define BPWED_TH 0x700 -#define BIFMF_WIN_L 0x800 -#define BPD_OPTION 0x1000 -#define BMF_WIN_L 0xe000 -#define BBW_SEARCH_L 0x30000 -#define BWIN_ENH_L 0xc0000 -#define BBW_TH 0x700000 -#define BED_TH2 0x3800000 -#define BBW_OPTION 0x4000000 -#define BRADIO_TH 0x18000000 -#define BWINDOW_L 0xe0000000 -#define BSBD_OPTION 0x1 -#define BFRAME_TH 0x1c -#define BFS_OPTION 0x60 -#define BDC_SLOPE_CHECK 0x80 -#define BFGUARD_COUNTER_DC_L 0xe00 -#define BFRAME_WEIGHT_SHORT 0x7000 -#define BSUB_TUNE 0xe00000 -#define BFRAME_DC_LENGTH 0xe000000 -#define BSBD_START_OFFSET 0x30000000 -#define BFRAME_TH_2 0x7 -#define BFRAME_GI2_TH 0x38 -#define BGI2_SYNC_EN 0x40 -#define BSARCH_SHORT_EARLY 0x300 -#define BSARCH_SHORT_LATE 0xc00 -#define BSARCH_GI2_LATE 0x70000 -#define BCFOANTSUM 0x1 -#define BCFOACC 0x2 -#define BCFOSTARTOFFSET 0xc -#define BCFOLOOPBACK 0x70 -#define BCFOSUMWEIGHT 0x80 -#define BDAGCENABLE 0x10000 -#define BTXIQIMB_A 0x3ff -#define BTXIQIMB_b 0xfc00 -#define BTXIQIMB_C 0x3f0000 -#define BTXIQIMB_D 0xffc00000 -#define BTXIDCOFFSET 0xff -#define BTXIQDCOFFSET 0xff00 -#define BTXDFIRMODE 0x10000 -#define BTXPESUDO_NOISEON 0x4000000 -#define BTXPESUDO_NOISE_A 0xff -#define BTXPESUDO_NOISE_B 0xff00 -#define BTXPESUDO_NOISE_C 0xff0000 -#define BTXPESUDO_NOISE_D 0xff000000 -#define BCCA_DROPOPTION 0x20000 -#define BCCA_DROPTHRES 0xfff00000 -#define BEDCCA_H 0xf -#define BEDCCA_L 0xf0 -#define BLAMBDA_ED 0x300 -#define BRX_INITIALGAIN 0x7f -#define BRX_ANTDIV_EN 0x80 -#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 -#define BRX_HIGHPOWER_FLOW 0x8000 -#define BRX_AGC_FREEZE_THRES 0xc0000 -#define BRX_FREEZESTEP_AGC1 0x300000 -#define BRX_FREEZESTEP_AGC2 0xc00000 -#define BRX_FREEZESTEP_AGC3 0x3000000 -#define BRX_FREEZESTEP_AGC0 0xc000000 -#define BRXRSSI_CMP_EN 0x10000000 -#define BRXQUICK_AGCEN 0x20000000 -#define BRXAGC_FREEZE_THRES_MODE 0x40000000 -#define BRX_OVERFLOW_CHECKTYPE 0x80000000 -#define BRX_AGCSHIFT 0x7f -#define BTRSW_TRI_ONLY 0x80 -#define BPOWER_THRES 0x300 -#define BRXAGC_EN 0x1 -#define BRXAGC_TOGETHER_EN 0x2 -#define BRXAGC_MIN 0x4 -#define BRXHP_INI 0x7 -#define BRXHP_TRLNA 0x70 -#define BRXHP_RSSI 0x700 -#define BRXHP_BBP1 0x7000 -#define BRXHP_BBP2 0x70000 -#define BRXHP_BBP3 0x700000 -#define BRSSI_H 0x7f0000 -#define BRSSI_GEN 0x7f000000 -#define BRXSETTLE_TRSW 0x7 -#define BRXSETTLE_LNA 0x38 -#define BRXSETTLE_RSSI 0x1c0 -#define BRXSETTLE_BBP 0xe00 -#define BRXSETTLE_RXHP 0x7000 -#define BRXSETTLE_ANTSW_RSSI 0x38000 -#define BRXSETTLE_ANTSW 0xc0000 -#define BRXPROCESS_TIME_DAGC 0x300000 -#define BRXSETTLE_HSSI 0x400000 -#define BRXPROCESS_TIME_BBPPW 0x800000 -#define BRXANTENNA_POWER_SHIFT 0x3000000 -#define BRSSI_TABLE_SELECT 0xc000000 -#define BRXHP_FINAL 0x7000000 -#define BRXHPSETTLE_BBP 0x7 -#define BRXHTSETTLE_HSSI 0x8 -#define BRXHTSETTLE_RXHP 0x70 -#define BRXHTSETTLE_BBPPW 0x80 -#define BRXHTSETTLE_IDLE 0x300 -#define BRXHTSETTLE_RESERVED 0x1c00 -#define BRXHT_RXHP_EN 0x8000 -#define BRXAGC_FREEZE_THRES 0x30000 -#define BRXAGC_TOGETHEREN 0x40000 -#define BRXHTAGC_MIN 0x80000 -#define BRXHTAGC_EN 0x100000 -#define BRXHTDAGC_EN 0x200000 -#define BRXHT_RXHP_BBP 0x1c00000 -#define BRXHT_RXHP_FINAL 0xe0000000 -#define BRXPW_RADIO_TH 0x3 -#define BRXPW_RADIO_EN 0x4 -#define BRXMF_HOLD 0x3800 -#define BRXPD_DELAY_TH1 0x38 -#define BRXPD_DELAY_TH2 0x1c0 -#define BRXPD_DC_COUNT_MAX 0x600 -#define BRXPD_DELAY_TH 0x8000 -#define BRXPROCESS_DELAY 0xf0000 -#define BRXSEARCHRANGE_GI2_EARLY 0x700000 -#define BRXFRAME_FUARD_COUNTER_L 0x3800000 -#define BRXSGI_GUARD_L 0xc000000 -#define BRXSGI_SEARCH_L 0x30000000 -#define BRXSGI_TH 0xc0000000 -#define BDFSCNT0 0xff -#define BDFSCNT1 0xff00 -#define BDFSFLAG 0xf0000 -#define BMF_WEIGHT_SUM 0x300000 -#define BMINIDX_TH 0x7f000000 -#define BDAFORMAT 0x40000 -#define BTXCH_EMU_ENABLE 0x01000000 -#define BTRSW_ISOLATION_A 0x7f -#define BTRSW_ISOLATION_B 0x7f00 -#define BTRSW_ISOLATION_C 0x7f0000 -#define BTRSW_ISOLATION_D 0x7f000000 -#define BEXT_LNA_GAIN 0x7c00 - -#define BSTBC_EN 0x4 -#define BANTENNA_MAPPING 0x10 -#define BNSS 0x20 -#define BCFO_ANTSUM_ID 0x200 -#define BPHY_COUNTER_RESET 0x8000000 -#define BCFO_REPORT_GET 0x4000000 -#define BOFDM_CONTINUE_TX 0x10000000 -#define BOFDM_SINGLE_CARRIER 0x20000000 -#define BOFDM_SINGLE_TONE 0x40000000 -#define BHT_DETECT 0x100 -#define BCFOEN 0x10000 -#define BCFOVALUE 0xfff00000 -#define BSIGTONE_RE 0x3f -#define BSIGTONE_IM 0x7f00 -#define BCOUNTER_CCA 0xffff -#define BCOUNTER_PARITYFAIL 0xffff0000 -#define BCOUNTER_RATEILLEGAL 0xffff -#define BCOUNTER_CRC8FAIL 0xffff0000 -#define BCOUNTER_MCSNOSUPPORT 0xffff -#define BCOUNTER_FASTSYNC 0xffff -#define BSHORTCFO 0xfff -#define BSHORTCFOT_LENGTH 12 -#define BSHORTCFOF_LENGTH 11 -#define BLONGCFO 0x7ff -#define BLONGCFOT_LENGTH 11 -#define BLONGCFOF_LENGTH 11 -#define BTAILCFO 0x1fff -#define BTAILCFOT_LENGTH 13 -#define BTAILCFOF_LENGTH 12 -#define BNOISE_EN_PWDB 0xffff -#define BCC_POWER_DB 0xffff0000 -#define BMOISE_PWDB 0xffff -#define BPOWERMEAST_LENGTH 10 -#define BPOWERMEASF_LENGTH 3 -#define BRX_HT_BW 0x1 -#define BRXSC 0x6 -#define BRX_HT 0x8 -#define BNB_INTF_DET_ON 0x1 -#define BINTF_WIN_LEN_CFG 0x30 -#define BNB_INTF_TH_CFG 0x1c0 -#define BRFGAIN 0x3f -#define BTABLESEL 0x40 -#define BTRSW 0x80 -#define BRXSNR_A 0xff -#define BRXSNR_B 0xff00 -#define BRXSNR_C 0xff0000 -#define BRXSNR_D 0xff000000 -#define BSNR_EVMT_LENGTH 8 -#define BSNR_EVMF_LENGTH 1 -#define BCSI1ST 0xff -#define BCSI2ND 0xff00 -#define BRXEVM1ST 0xff0000 -#define BRXEVM2ND 0xff000000 -#define BSIGEVM 0xff -#define BPWDB 0xff00 -#define BSGIEN 0x10000 - -#define BSFACTOR_QMA1 0xf -#define BSFACTOR_QMA2 0xf0 -#define BSFACTOR_QMA3 0xf00 -#define BSFACTOR_QMA4 0xf000 -#define BSFACTOR_QMA5 0xf0000 -#define BSFACTOR_QMA6 0xf0000 -#define BSFACTOR_QMA7 0xf00000 -#define BSFACTOR_QMA8 0xf000000 -#define BSFACTOR_QMA9 0xf0000000 -#define BCSI_SCHEME 0x100000 - -#define BNOISE_LVL_TOP_SET 0x3 -#define BCHSMOOTH 0x4 -#define BCHSMOOTH_CFG1 0x38 -#define BCHSMOOTH_CFG2 0x1c0 -#define BCHSMOOTH_CFG3 0xe00 -#define BCHSMOOTH_CFG4 0x7000 -#define BMRCMODE 0x800000 -#define BTHEVMCFG 0x7000000 - -#define BLOOP_FIT_TYPE 0x1 -#define BUPD_CFO 0x40 -#define BUPD_CFO_OFFDATA 0x80 -#define BADV_UPD_CFO 0x100 -#define BADV_TIME_CTRL 0x800 -#define BUPD_CLKO 0x1000 -#define BFC 0x6000 -#define BTRACKING_MODE 0x8000 -#define BPHCMP_ENABLE 0x10000 -#define BUPD_CLKO_LTF 0x20000 -#define BCOM_CH_CFO 0x40000 -#define BCSI_ESTI_MODE 0x80000 -#define BADV_UPD_EQZ 0x100000 -#define BUCHCFG 0x7000000 -#define BUPDEQZ 0x8000000 - -#define BRX_PESUDO_NOISE_ON 0x20000000 -#define BRX_PESUDO_NOISE_A 0xff -#define BRX_PESUDO_NOISE_B 0xff00 -#define BRX_PESUDO_NOISE_C 0xff0000 -#define BRX_PESUDO_NOISE_D 0xff000000 -#define BRX_PESUDO_NOISESTATE_A 0xffff -#define BRX_PESUDO_NOISESTATE_B 0xffff0000 -#define BRX_PESUDO_NOISESTATE_C 0xffff -#define BRX_PESUDO_NOISESTATE_D 0xffff0000 - -#define BZEBRA1_HSSIENABLE 0x8 -#define BZEBRA1_TRXCONTROL 0xc00 -#define BZEBRA1_TRXGAINSETTING 0x07f -#define BZEBRA1_RXCOUNTER 0xc00 -#define BZEBRA1_TXCHANGEPUMP 0x38 -#define BZEBRA1_RXCHANGEPUMP 0x7 -#define BZEBRA1_CHANNEL_NUM 0xf80 -#define BZEBRA1_TXLPFBW 0x400 -#define BZEBRA1_RXLPFBW 0x600 - -#define BRTL8256REG_MODE_CTRL1 0x100 -#define BRTL8256REG_MODE_CTRL0 0x40 -#define BRTL8256REG_TXLPFBW 0x18 -#define BRTL8256REG_RXLPFBW 0x600 - -#define BRTL8258_TXLPFBW 0xc -#define BRTL8258_RXLPFBW 0xc00 -#define BRTL8258_RSSILPFBW 0xc0 - -#define BBYTE0 0x1 -#define BBYTE1 0x2 -#define BBYTE2 0x4 -#define BBYTE3 0x8 -#define BWORD0 0x3 -#define BWORD1 0xc -#define BWORD 0xf - -#define BENABLE 0x1 -#define BDISABLE 0x0 - -#define LEFT_ANTENNA 0x0 -#define RIGHT_ANTENNA 0x1 - -#define TCHECK_TXSTATUS 500 -#define TUPDATE_RXCOUNTER 100 - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c deleted file mode 100644 index a9c406f33d0a..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c +++ /dev/null @@ -1,509 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" - -static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw); - -void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - switch (bandwidth) { - case HT_CHANNEL_WIDTH_20: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff) | 0x0400); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - case HT_CHANNEL_WIDTH_20_40: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff)); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", bandwidth); - break; - } -} - -void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 tx_agc[2] = {0, 0}, tmpval; - bool turbo_scanoff = false; - u8 idx1, idx2; - u8 *ptr; - - if (rtlefuse->eeprom_regulatory != 0) - turbo_scanoff = true; - - if (mac->act_scanning) { - tx_agc[RF90_PATH_A] = 0x3f3f3f3f; - tx_agc[RF90_PATH_B] = 0x3f3f3f3f; - - if (turbo_scanoff) { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - } - } else { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - - if (rtlefuse->eeprom_regulatory == 0) { - tmpval = (rtlphy->mcs_offset[0][6]) + - (rtlphy->mcs_offset[0][7] << 8); - tx_agc[RF90_PATH_A] += tmpval; - - tmpval = (rtlphy->mcs_offset[0][14]) + - (rtlphy->mcs_offset[0][15] << 24); - tx_agc[RF90_PATH_B] += tmpval; - } - } - - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - ptr = (u8 *) (&(tx_agc[idx1])); - for (idx2 = 0; idx2 < 4; idx2++) { - if (*ptr > RF6052_MAX_TX_PWR) - *ptr = RF6052_MAX_TX_PWR; - ptr++; - } - } - - tmpval = tx_agc[RF90_PATH_A] & 0xff; - rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", - tmpval, RTXAGC_A_CCK1_MCS32); - - tmpval = tx_agc[RF90_PATH_A] >> 8; - - tmpval = tmpval & 0xff00ffff; - - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", - tmpval, RTXAGC_B_CCK11_A_CCK2_11); - - tmpval = tx_agc[RF90_PATH_B] >> 24; - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", - tmpval, RTXAGC_B_CCK11_A_CCK2_11); - - tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; - rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", - tmpval, RTXAGC_B_CCK1_55_MCS32); -} - -static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel, - u32 *ofdmbase, u32 *mcsbase) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 powerBase0, powerBase1; - u8 legacy_pwrdiff, ht20_pwrdiff; - u8 i, powerlevel[2]; - - for (i = 0; i < 2; i++) { - powerlevel[i] = ppowerlevel[i]; - legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; - powerBase0 = powerlevel[i] + legacy_pwrdiff; - - powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | - (powerBase0 << 8) | powerBase0; - *(ofdmbase + i) = powerBase0; - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [OFDM power base index rf(%c) = 0x%x]\n", - i == 0 ? 'A' : 'B', *(ofdmbase + i)); - } - - for (i = 0; i < 2; i++) { - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { - ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1]; - powerlevel[i] += ht20_pwrdiff; - } - powerBase1 = powerlevel[i]; - powerBase1 = (powerBase1 << 24) | - (powerBase1 << 16) | (powerBase1 << 8) | powerBase1; - - *(mcsbase + i) = powerBase1; - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [MCS power base index rf(%c) = 0x%x]\n", - i == 0 ? 'A' : 'B', *(mcsbase + i)); - } -} - -static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, - u8 channel, u8 index, - u32 *powerBase0, - u32 *powerBase1, - u32 *p_outwriteval) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 i, chnlgroup = 0, pwr_diff_limit[4]; - u32 writeVal, customer_limit, rf; - - for (rf = 0; rf < 2; rf++) { - switch (rtlefuse->eeprom_regulatory) { - case 0: - chnlgroup = 0; - - writeVal = rtlphy->mcs_offset[chnlgroup][index + - (rf ? 8 : 0)] - + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); - break; - case 1: - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - writeVal = ((index < 2) ? powerBase0[rf] : - powerBase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Realtek regulatory, 40MHz, writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); - } else { - if (rtlphy->pwrgroup_cnt == 1) - chnlgroup = 0; - if (rtlphy->pwrgroup_cnt >= 3) { - if (channel <= 3) - chnlgroup = 0; - else if (channel >= 4 && channel <= 9) - chnlgroup = 1; - else if (channel > 9) - chnlgroup = 2; - if (rtlphy->pwrgroup_cnt == 4) - chnlgroup++; - } - - writeVal = rtlphy->mcs_offset[chnlgroup] - [index + (rf ? 8 : 0)] + ((index < 2) ? - powerBase0[rf] : - powerBase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); - } - break; - case 2: - writeVal = - ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Better regulatory, writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); - break; - case 3: - chnlgroup = 0; - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 40MHz rf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', - rtlefuse->pwrgroup_ht40[rf][channel - - 1]); - } else { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 20MHz rf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', - rtlefuse->pwrgroup_ht20[rf][channel - - 1]); - } - for (i = 0; i < 4; i++) { - pwr_diff_limit[i] = (u8) ((rtlphy->mcs_offset - [chnlgroup][index + - (rf ? 8 : 0)] & (0x7f << (i * 8))) >> - (i * 8)); - - if (rtlphy->current_chan_bw == - HT_CHANNEL_WIDTH_20_40) { - if (pwr_diff_limit[i] > - rtlefuse-> - pwrgroup_ht40[rf][channel - 1]) - pwr_diff_limit[i] = - rtlefuse->pwrgroup_ht40[rf] - [channel - 1]; - } else { - if (pwr_diff_limit[i] > - rtlefuse-> - pwrgroup_ht20[rf][channel - 1]) - pwr_diff_limit[i] = - rtlefuse->pwrgroup_ht20[rf] - [channel - 1]; - } - } - - customer_limit = (pwr_diff_limit[3] << 24) | - (pwr_diff_limit[2] << 16) | - (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer's limit rf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', customer_limit); - - writeVal = customer_limit + - ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer, writeVal rf(%c)= 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); - break; - default: - chnlgroup = 0; - writeVal = rtlphy->mcs_offset[chnlgroup] - [index + (rf ? 8 : 0)] - + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeVal rf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); - break; - } - - if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) - writeVal = writeVal - 0x06060606; - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_BT2) - writeVal = writeVal - 0x0c0c0c0c; - *(p_outwriteval + rf) = writeVal; - } -} - -static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, - u8 index, u32 *pValue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - u16 regoffset_a[6] = { - RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, - RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, - RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 - }; - u16 regoffset_b[6] = { - RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, - RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, - RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 - }; - u8 i, rf, pwr_val[4]; - u32 writeVal; - u16 regoffset; - - for (rf = 0; rf < 2; rf++) { - writeVal = pValue[rf]; - for (i = 0; i < 4; i++) { - pwr_val[i] = (u8) ((writeVal & (0x7f << - (i * 8))) >> (i * 8)); - - if (pwr_val[i] > RF6052_MAX_TX_PWR) - pwr_val[i] = RF6052_MAX_TX_PWR; - } - writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) | - (pwr_val[1] << 8) | pwr_val[0]; - - if (rf == 0) - regoffset = regoffset_a[index]; - else - regoffset = regoffset_b[index]; - rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Set 0x%x = %08x\n", regoffset, writeVal); - - if (((get_rf_type(rtlphy) == RF_2T2R) && - (regoffset == RTXAGC_A_MCS15_MCS12 || - regoffset == RTXAGC_B_MCS15_MCS12)) || - ((get_rf_type(rtlphy) != RF_2T2R) && - (regoffset == RTXAGC_A_MCS07_MCS04 || - regoffset == RTXAGC_B_MCS07_MCS04))) { - - writeVal = pwr_val[3]; - if (regoffset == RTXAGC_A_MCS15_MCS12 || - regoffset == RTXAGC_A_MCS07_MCS04) - regoffset = 0xc90; - if (regoffset == RTXAGC_B_MCS15_MCS12 || - regoffset == RTXAGC_B_MCS07_MCS04) - regoffset = 0xc98; - - for (i = 0; i < 3; i++) { - writeVal = (writeVal > 6) ? (writeVal - 6) : 0; - rtl_write_byte(rtlpriv, (u32) (regoffset + i), - (u8) writeVal); - } - } - } -} - -void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel) -{ - u32 writeVal[2], powerBase0[2], powerBase1[2]; - u8 index; - - rtl92c_phy_get_power_base(hw, ppowerlevel, - channel, &powerBase0[0], &powerBase1[0]); - - for (index = 0; index < 6; index++) { - _rtl92c_get_txpower_writeval_by_regulatory(hw, - channel, index, - &powerBase0[0], - &powerBase1[0], - &writeVal[0]); - - _rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]); - } -} - -bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - if (rtlphy->rf_type == RF_1T1R) - rtlphy->num_total_rfpath = 1; - else - rtlphy->num_total_rfpath = 2; - - return _rtl92ce_phy_rf6052_config_parafile(hw); - -} - -static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 u4_regvalue = 0; - u8 rfpath; - bool rtstatus = true; - struct bb_reg_def *pphyreg; - - for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { - - pphyreg = &rtlphy->phyreg_def[rfpath]; - - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV); - break; - case RF90_PATH_B: - case RF90_PATH_D: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16); - break; - } - - rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, - B3WIREADDREAALENGTH, 0x0); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); - udelay(1); - - switch (rfpath) { - case RF90_PATH_A: - rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_B: - rtstatus = rtl92c_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_C: - break; - case RF90_PATH_D: - break; - } - - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - rtl_set_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV, u4_regvalue); - break; - case RF90_PATH_B: - case RF90_PATH_D: - rtl_set_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16, u4_regvalue); - break; - } - - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio[%d] Fail!!\n", rfpath); - return false; - } - - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n"); - return rtstatus; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h deleted file mode 100644 index ebd72cae10b6..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_RF_H__ -#define __RTL92C_RF_H__ - -#define RF6052_MAX_TX_PWR 0x3F -#define RF6052_MAX_PATH 2 - -void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth); -void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); -bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c deleted file mode 100644 index de6cb6c3a48c..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ /dev/null @@ -1,394 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../core.h" -#include "../pci.h" -#include "../base.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "../rtl8192c/dm_common.h" -#include "../rtl8192c/fw_common.h" -#include "../rtl8192c/phy_common.h" -#include "hw.h" -#include "rf.h" -#include "sw.h" -#include "trx.h" -#include "led.h" - -#include - -static void rtl92c_init_aspm_vars(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - /*close ASPM for AMD defaultly */ - rtlpci->const_amdpci_aspm = 0; - - /* - * ASPM PS mode. - * 0 - Disable ASPM, - * 1 - Enable ASPM without Clock Req, - * 2 - Enable ASPM with Clock Req, - * 3 - Alwyas Enable ASPM with Clock Req, - * 4 - Always Enable ASPM without Clock Req. - * set defult to RTL8192CE:3 RTL8192E:2 - * */ - rtlpci->const_pci_aspm = 3; - - /*Setting for PCI-E device */ - rtlpci->const_devicepci_aspm_setting = 0x03; - - /*Setting for PCI-E bridge */ - rtlpci->const_hostpci_aspm_setting = 0x02; - - /* - * In Hw/Sw Radio Off situation. - * 0 - Default, - * 1 - From ASPM setting without low Mac Pwr, - * 2 - From ASPM setting with low Mac Pwr, - * 3 - Bus D3 - * set default to RTL8192CE:0 RTL8192SE:2 - */ - rtlpci->const_hwsw_rfoff_d3 = 0; - - /* - * This setting works for those device with - * backdoor ASPM setting such as EPHY setting. - * 0 - Not support ASPM, - * 1 - Support ASPM, - * 2 - According to chipset. - */ - rtlpci->const_support_pciaspm = 1; -} - -int rtl92c_init_sw_vars(struct ieee80211_hw *hw) -{ - int err; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - rtl8192ce_bt_reg_init(hw); - - rtlpriv->dm.dm_initialgain_enable = true; - rtlpriv->dm.dm_flag = 0; - rtlpriv->dm.disable_framebursting = false; - rtlpriv->dm.thermalvalue = 0; - rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13); - - /* compatible 5G band 88ce just 2.4G band & smsp */ - rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; - rtlpriv->rtlhal.bandset = BAND_ON_2_4G; - rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; - - rtlpci->receive_config = (RCR_APPFCS | - RCR_AMF | - RCR_ADF | - RCR_APP_MIC | - RCR_APP_ICV | - RCR_AICV | - RCR_ACRC32 | - RCR_AB | - RCR_AM | - RCR_APM | - RCR_APP_PHYST_RXFF | RCR_HTC_LOC_CTRL | 0); - - rtlpci->irq_mask[0] = - (u32) (IMR_ROK | - IMR_VODOK | - IMR_VIDOK | - IMR_BEDOK | - IMR_BKDOK | - IMR_MGNTDOK | - IMR_HIGHDOK | IMR_BDOK | IMR_RDU | IMR_RXFOVW | 0); - - 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; - rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; - if (!rtlpriv->psc.inactiveps) - pr_info("rtl8192ce: Power Save off (module option)\n"); - if (!rtlpriv->psc.fwctrl_lps) - pr_info("rtl8192ce: FW Power Save off (module option)\n"); - rtlpriv->psc.reg_fwctrl_lps = 3; - rtlpriv->psc.reg_max_lps_awakeintvl = 5; - /* for ASPM, you can close aspm through - * set const_support_pciaspm = 0 */ - rtl92c_init_aspm_vars(hw); - - if (rtlpriv->psc.reg_fwctrl_lps == 1) - rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 2) - rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 3) - rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; - - /* for firmware buf */ - rtlpriv->rtlhal.pfirmware = vzalloc(0x4000); - if (!rtlpriv->rtlhal.pfirmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't alloc buffer for fw\n"); - return 1; - } - - /* request fw */ - if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && - !IS_92C_SERIAL(rtlhal->version)) - rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; - else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) - rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; - - rtlpriv->max_fw_size = 0x4000; - pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); - err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, - rtlpriv->io.dev, GFP_KERNEL, hw, - rtl_fw_cb); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to request firmware!\n"); - return 1; - } - - return 0; -} - -void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->rtlhal.pfirmware) { - vfree(rtlpriv->rtlhal.pfirmware); - rtlpriv->rtlhal.pfirmware = NULL; - } -} - -static struct rtl_hal_ops rtl8192ce_hal_ops = { - .init_sw_vars = rtl92c_init_sw_vars, - .deinit_sw_vars = rtl92c_deinit_sw_vars, - .read_eeprom_info = rtl92ce_read_eeprom_info, - .interrupt_recognized = rtl92ce_interrupt_recognized, - .hw_init = rtl92ce_hw_init, - .hw_disable = rtl92ce_card_disable, - .hw_suspend = rtl92ce_suspend, - .hw_resume = rtl92ce_resume, - .enable_interrupt = rtl92ce_enable_interrupt, - .disable_interrupt = rtl92ce_disable_interrupt, - .set_network_type = rtl92ce_set_network_type, - .set_chk_bssid = rtl92ce_set_check_bssid, - .set_qos = rtl92ce_set_qos, - .set_bcn_reg = rtl92ce_set_beacon_related_registers, - .set_bcn_intv = rtl92ce_set_beacon_interval, - .update_interrupt_mask = rtl92ce_update_interrupt_mask, - .get_hw_reg = rtl92ce_get_hw_reg, - .set_hw_reg = rtl92ce_set_hw_reg, - .update_rate_tbl = rtl92ce_update_hal_rate_tbl, - .fill_tx_desc = rtl92ce_tx_fill_desc, - .fill_tx_cmddesc = rtl92ce_tx_fill_cmddesc, - .query_rx_desc = rtl92ce_rx_query_desc, - .set_channel_access = rtl92ce_update_channel_access_setting, - .radio_onoff_checking = rtl92ce_gpio_radio_on_off_checking, - .set_bw_mode = rtl92c_phy_set_bw_mode, - .switch_channel = rtl92c_phy_sw_chnl, - .dm_watchdog = rtl92c_dm_watchdog, - .scan_operation_backup = rtl_phy_scan_operation_backup, - .set_rf_power_state = rtl92c_phy_set_rf_power_state, - .led_control = rtl92ce_led_control, - .set_desc = rtl92ce_set_desc, - .get_desc = rtl92ce_get_desc, - .is_tx_desc_closed = rtl92ce_is_tx_desc_closed, - .tx_polling = rtl92ce_tx_polling, - .enable_hw_sec = rtl92ce_enable_hw_security_config, - .set_key = rtl92ce_set_key, - .init_sw_leds = rtl92ce_init_sw_leds, - .get_bbreg = rtl92c_phy_query_bb_reg, - .set_bbreg = rtl92c_phy_set_bb_reg, - .set_rfreg = rtl92ce_phy_set_rf_reg, - .get_rfreg = rtl92c_phy_query_rf_reg, - .phy_rf6052_config = rtl92ce_phy_rf6052_config, - .phy_rf6052_set_cck_txpower = rtl92ce_phy_rf6052_set_cck_txpower, - .phy_rf6052_set_ofdm_txpower = rtl92ce_phy_rf6052_set_ofdm_txpower, - .config_bb_with_headerfile = _rtl92ce_phy_config_bb_with_headerfile, - .config_bb_with_pgheaderfile = _rtl92ce_phy_config_bb_with_pgheaderfile, - .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate, - .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback, - .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, - .get_btc_status = rtl_btc_status_false, -}; - -static struct rtl_mod_params rtl92ce_mod_params = { - .sw_crypto = false, - .inactiveps = true, - .swctrl_lps = false, - .fwctrl_lps = true, - .debug = DBG_EMERG, -}; - -static struct rtl_hal_cfg rtl92ce_hal_cfg = { - .bar_id = 2, - .write_readback = true, - .name = "rtl92c_pci", - .fw_name = "rtlwifi/rtl8192cfw.bin", - .ops = &rtl8192ce_hal_ops, - .mod_params = &rtl92ce_mod_params, - - .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, - .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, - .maps[SYS_CLK] = REG_SYS_CLKR, - .maps[MAC_RCR_AM] = AM, - .maps[MAC_RCR_AB] = AB, - .maps[MAC_RCR_ACRC32] = ACRC32, - .maps[MAC_RCR_ACF] = ACF, - .maps[MAC_RCR_AAP] = AAP, - .maps[MAC_HIMR] = REG_HIMR, - .maps[MAC_HIMRE] = REG_HIMRE, - - .maps[EFUSE_TEST] = REG_EFUSE_TEST, - .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_CLK] = 0, - .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_PWC_EV12V] = PWC_EV12V, - .maps[EFUSE_FEN_ELDR] = FEN_ELDR, - .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, - .maps[EFUSE_ANA8M] = EFUSE_ANA8M, - .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, - .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, - .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, - .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, - - .maps[RWCAM] = REG_CAMCMD, - .maps[WCAMI] = REG_CAMWRITE, - .maps[RCAMO] = REG_CAMREAD, - .maps[CAMDBG] = REG_CAMDBG, - .maps[SECR] = REG_SECCFG, - .maps[SEC_CAM_NONE] = CAM_NONE, - .maps[SEC_CAM_WEP40] = CAM_WEP40, - .maps[SEC_CAM_TKIP] = CAM_TKIP, - .maps[SEC_CAM_AES] = CAM_AES, - .maps[SEC_CAM_WEP104] = CAM_WEP104, - - .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, - .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, - .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, - .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, - .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, - .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, - .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, - .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, - .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, - .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, - .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, - .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, - .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, - .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, - .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, - .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, - - .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, - .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, - .maps[RTL_IMR_BCNINT] = IMR_BCNINT, - .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, - .maps[RTL_IMR_RDU] = IMR_RDU, - .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, - .maps[RTL_IMR_BDOK] = IMR_BDOK, - .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, - .maps[RTL_IMR_TBDER] = IMR_TBDER, - .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, - .maps[RTL_IMR_TBDOK] = IMR_TBDOK, - .maps[RTL_IMR_BKDOK] = IMR_BKDOK, - .maps[RTL_IMR_BEDOK] = IMR_BEDOK, - .maps[RTL_IMR_VIDOK] = IMR_VIDOK, - .maps[RTL_IMR_VODOK] = IMR_VODOK, - .maps[RTL_IMR_ROK] = IMR_ROK, - .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), - - .maps[RTL_RC_CCK_RATE1M] = DESC_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC_RATEMCS15, -}; - -static const struct pci_device_id rtl92ce_pci_ids[] = { - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8191, rtl92ce_hal_cfg)}, - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8178, rtl92ce_hal_cfg)}, - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8177, rtl92ce_hal_cfg)}, - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8176, rtl92ce_hal_cfg)}, - {}, -}; - -MODULE_DEVICE_TABLE(pci, rtl92ce_pci_ids); - -MODULE_AUTHOR("lizhaoming "); -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_AUTHOR("Larry Finger "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n PCI wireless"); -MODULE_FIRMWARE("rtlwifi/rtl8192cfw.bin"); -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(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); -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)"); - -static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); - -static struct pci_driver rtl92ce_driver = { - .name = KBUILD_MODNAME, - .id_table = rtl92ce_pci_ids, - .probe = rtl_pci_probe, - .remove = rtl_pci_disconnect, - .driver.pm = &rtlwifi_pm_ops, -}; - -module_pci_driver(rtl92ce_driver); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h deleted file mode 100644 index d2367a5d0cf5..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h +++ /dev/null @@ -1,41 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CE_SW_H__ -#define __RTL92CE_SW_H__ - -int rtl92c_init_sw_vars(struct ieee80211_hw *hw); -void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw); -void rtl92c_init_var_map(struct ieee80211_hw *hw); -bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); -bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/table.c b/drivers/net/wireless/rtlwifi/rtl8192ce/table.c deleted file mode 100644 index 752f943a84ae..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/table.c +++ /dev/null @@ -1,1224 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ - -#include "table.h" - - -u32 RTL8192CEPHY_REG_2TARRAY[PHY_REG_2TARRAY_LENGTH] = { - 0x024, 0x0011800f, - 0x028, 0x00ffdb83, - 0x800, 0x80040002, - 0x804, 0x00000003, - 0x808, 0x0000fc00, - 0x80c, 0x0000000a, - 0x810, 0x10005388, - 0x814, 0x020c3d10, - 0x818, 0x02200385, - 0x81c, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390004, - 0x828, 0x01000100, - 0x82c, 0x00390004, - 0x830, 0x27272727, - 0x834, 0x27272727, - 0x838, 0x27272727, - 0x83c, 0x27272727, - 0x840, 0x00010000, - 0x844, 0x00010000, - 0x848, 0x27272727, - 0x84c, 0x27272727, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x569a569a, - 0x85c, 0x0c1b25a4, - 0x860, 0x66e60230, - 0x864, 0x061f0130, - 0x868, 0x27272727, - 0x86c, 0x2b2b2b27, - 0x870, 0x07000700, - 0x874, 0x22184000, - 0x878, 0x08080808, - 0x87c, 0x00000000, - 0x880, 0xc0083070, - 0x884, 0x000004d5, - 0x888, 0x00000000, - 0x88c, 0xcc0000c0, - 0x890, 0x00000800, - 0x894, 0xfffffffe, - 0x898, 0x40302010, - 0x89c, 0x00706050, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90c, 0x81121313, - 0xa00, 0x00d047c8, - 0xa04, 0x80ff000c, - 0xa08, 0x8c838300, - 0xa0c, 0x2e68120f, - 0xa10, 0x9500bb78, - 0xa14, 0x11144028, - 0xa18, 0x00881117, - 0xa1c, 0x89140f00, - 0xa20, 0x1a1b0000, - 0xa24, 0x090e1317, - 0xa28, 0x00000204, - 0xa2c, 0x00d30000, - 0xa70, 0x101fbf00, - 0xa74, 0x00000007, - 0xc00, 0x48071d40, - 0xc04, 0x03a05633, - 0xc08, 0x000000e4, - 0xc0c, 0x6c6c6c6c, - 0xc10, 0x08800000, - 0xc14, 0x40000100, - 0xc18, 0x08800000, - 0xc1c, 0x40000100, - 0xc20, 0x00000000, - 0xc24, 0x00000000, - 0xc28, 0x00000000, - 0xc2c, 0x00000000, - 0xc30, 0x69e9ac44, - 0xc34, 0x469652cf, - 0xc38, 0x49795994, - 0xc3c, 0x0a97971c, - 0xc40, 0x1f7c403f, - 0xc44, 0x000100b7, - 0xc48, 0xec020107, - 0xc4c, 0x007f037f, - 0xc50, 0x69543420, - 0xc54, 0x43bc0094, - 0xc58, 0x69543420, - 0xc5c, 0x433c0094, - 0xc60, 0x00000000, - 0xc64, 0x5116848b, - 0xc68, 0x47c00bff, - 0xc6c, 0x00000036, - 0xc70, 0x2c7f000d, - 0xc74, 0x018610db, - 0xc78, 0x0000001f, - 0xc7c, 0x00b91612, - 0xc80, 0x40000100, - 0xc84, 0x20f60000, - 0xc88, 0x40000100, - 0xc8c, 0x20200000, - 0xc90, 0x00121820, - 0xc94, 0x00000000, - 0xc98, 0x00121820, - 0xc9c, 0x00007f7f, - 0xca0, 0x00000000, - 0xca4, 0x00000080, - 0xca8, 0x00000000, - 0xcac, 0x00000000, - 0xcb0, 0x00000000, - 0xcb4, 0x00000000, - 0xcb8, 0x00000000, - 0xcbc, 0x28000000, - 0xcc0, 0x00000000, - 0xcc4, 0x00000000, - 0xcc8, 0x00000000, - 0xccc, 0x00000000, - 0xcd0, 0x00000000, - 0xcd4, 0x00000000, - 0xcd8, 0x64b22427, - 0xcdc, 0x00766932, - 0xce0, 0x00222222, - 0xce4, 0x00000000, - 0xce8, 0x37644302, - 0xcec, 0x2f97d40c, - 0xd00, 0x00080740, - 0xd04, 0x00020403, - 0xd08, 0x0000907f, - 0xd0c, 0x20010201, - 0xd10, 0xa0633333, - 0xd14, 0x3333bc43, - 0xd18, 0x7a8f5b6b, - 0xd2c, 0xcc979975, - 0xd30, 0x00000000, - 0xd34, 0x80608000, - 0xd38, 0x00000000, - 0xd3c, 0x00027293, - 0xd40, 0x00000000, - 0xd44, 0x00000000, - 0xd48, 0x00000000, - 0xd4c, 0x00000000, - 0xd50, 0x6437140a, - 0xd54, 0x00000000, - 0xd58, 0x00000000, - 0xd5c, 0x30032064, - 0xd60, 0x4653de68, - 0xd64, 0x04518a3c, - 0xd68, 0x00002101, - 0xd6c, 0x2a201c16, - 0xd70, 0x1812362e, - 0xd74, 0x322c2220, - 0xd78, 0x000e3c24, - 0xe00, 0x2a2a2a2a, - 0xe04, 0x2a2a2a2a, - 0xe08, 0x03902a2a, - 0xe10, 0x2a2a2a2a, - 0xe14, 0x2a2a2a2a, - 0xe18, 0x2a2a2a2a, - 0xe1c, 0x2a2a2a2a, - 0xe28, 0x00000000, - 0xe30, 0x1000dc1f, - 0xe34, 0x10008c1f, - 0xe38, 0x02140102, - 0xe3c, 0x681604c2, - 0xe40, 0x01007c00, - 0xe44, 0x01004800, - 0xe48, 0xfb000000, - 0xe4c, 0x000028d1, - 0xe50, 0x1000dc1f, - 0xe54, 0x10008c1f, - 0xe58, 0x02140102, - 0xe5c, 0x28160d05, - 0xe60, 0x00000010, - 0xe68, 0x001b25a4, - 0xe6c, 0x63db25a4, - 0xe70, 0x63db25a4, - 0xe74, 0x0c1b25a4, - 0xe78, 0x0c1b25a4, - 0xe7c, 0x0c1b25a4, - 0xe80, 0x0c1b25a4, - 0xe84, 0x63db25a4, - 0xe88, 0x0c1b25a4, - 0xe8c, 0x63db25a4, - 0xed0, 0x63db25a4, - 0xed4, 0x63db25a4, - 0xed8, 0x63db25a4, - 0xedc, 0x001b25a4, - 0xee0, 0x001b25a4, - 0xeec, 0x6fdb25a4, - 0xf14, 0x00000003, - 0xf4c, 0x00000000, - 0xf00, 0x00000300, -}; - -u32 RTL8192CEPHY_REG_1TARRAY[PHY_REG_1TARRAY_LENGTH] = { - 0x024, 0x0011800f, - 0x028, 0x00ffdb83, - 0x800, 0x80040000, - 0x804, 0x00000001, - 0x808, 0x0000fc00, - 0x80c, 0x0000000a, - 0x810, 0x10005388, - 0x814, 0x020c3d10, - 0x818, 0x02200385, - 0x81c, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390004, - 0x828, 0x00000000, - 0x82c, 0x00000000, - 0x830, 0x00000000, - 0x834, 0x00000000, - 0x838, 0x00000000, - 0x83c, 0x00000000, - 0x840, 0x00010000, - 0x844, 0x00000000, - 0x848, 0x00000000, - 0x84c, 0x00000000, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x569a569a, - 0x85c, 0x001b25a4, - 0x860, 0x66e60230, - 0x864, 0x061f0130, - 0x868, 0x00000000, - 0x86c, 0x32323200, - 0x870, 0x07000700, - 0x874, 0x22004000, - 0x878, 0x00000808, - 0x87c, 0x00000000, - 0x880, 0xc0083070, - 0x884, 0x000004d5, - 0x888, 0x00000000, - 0x88c, 0xccc000c0, - 0x890, 0x00000800, - 0x894, 0xfffffffe, - 0x898, 0x40302010, - 0x89c, 0x00706050, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90c, 0x81121111, - 0xa00, 0x00d047c8, - 0xa04, 0x80ff000c, - 0xa08, 0x8c838300, - 0xa0c, 0x2e68120f, - 0xa10, 0x9500bb78, - 0xa14, 0x11144028, - 0xa18, 0x00881117, - 0xa1c, 0x89140f00, - 0xa20, 0x1a1b0000, - 0xa24, 0x090e1317, - 0xa28, 0x00000204, - 0xa2c, 0x00d30000, - 0xa70, 0x101fbf00, - 0xa74, 0x00000007, - 0xc00, 0x48071d40, - 0xc04, 0x03a05611, - 0xc08, 0x000000e4, - 0xc0c, 0x6c6c6c6c, - 0xc10, 0x08800000, - 0xc14, 0x40000100, - 0xc18, 0x08800000, - 0xc1c, 0x40000100, - 0xc20, 0x00000000, - 0xc24, 0x00000000, - 0xc28, 0x00000000, - 0xc2c, 0x00000000, - 0xc30, 0x69e9ac44, - 0xc34, 0x469652cf, - 0xc38, 0x49795994, - 0xc3c, 0x0a97971c, - 0xc40, 0x1f7c403f, - 0xc44, 0x000100b7, - 0xc48, 0xec020107, - 0xc4c, 0x007f037f, - 0xc50, 0x69543420, - 0xc54, 0x43bc0094, - 0xc58, 0x69543420, - 0xc5c, 0x433c0094, - 0xc60, 0x00000000, - 0xc64, 0x5116848b, - 0xc68, 0x47c00bff, - 0xc6c, 0x00000036, - 0xc70, 0x2c7f000d, - 0xc74, 0x018610db, - 0xc78, 0x0000001f, - 0xc7c, 0x00b91612, - 0xc80, 0x40000100, - 0xc84, 0x20f60000, - 0xc88, 0x40000100, - 0xc8c, 0x20200000, - 0xc90, 0x00121820, - 0xc94, 0x00000000, - 0xc98, 0x00121820, - 0xc9c, 0x00007f7f, - 0xca0, 0x00000000, - 0xca4, 0x00000080, - 0xca8, 0x00000000, - 0xcac, 0x00000000, - 0xcb0, 0x00000000, - 0xcb4, 0x00000000, - 0xcb8, 0x00000000, - 0xcbc, 0x28000000, - 0xcc0, 0x00000000, - 0xcc4, 0x00000000, - 0xcc8, 0x00000000, - 0xccc, 0x00000000, - 0xcd0, 0x00000000, - 0xcd4, 0x00000000, - 0xcd8, 0x64b22427, - 0xcdc, 0x00766932, - 0xce0, 0x00222222, - 0xce4, 0x00000000, - 0xce8, 0x37644302, - 0xcec, 0x2f97d40c, - 0xd00, 0x00080740, - 0xd04, 0x00020401, - 0xd08, 0x0000907f, - 0xd0c, 0x20010201, - 0xd10, 0xa0633333, - 0xd14, 0x3333bc43, - 0xd18, 0x7a8f5b6b, - 0xd2c, 0xcc979975, - 0xd30, 0x00000000, - 0xd34, 0x80608000, - 0xd38, 0x00000000, - 0xd3c, 0x00027293, - 0xd40, 0x00000000, - 0xd44, 0x00000000, - 0xd48, 0x00000000, - 0xd4c, 0x00000000, - 0xd50, 0x6437140a, - 0xd54, 0x00000000, - 0xd58, 0x00000000, - 0xd5c, 0x30032064, - 0xd60, 0x4653de68, - 0xd64, 0x04518a3c, - 0xd68, 0x00002101, - 0xd6c, 0x2a201c16, - 0xd70, 0x1812362e, - 0xd74, 0x322c2220, - 0xd78, 0x000e3c24, - 0xe00, 0x2a2a2a2a, - 0xe04, 0x2a2a2a2a, - 0xe08, 0x03902a2a, - 0xe10, 0x2a2a2a2a, - 0xe14, 0x2a2a2a2a, - 0xe18, 0x2a2a2a2a, - 0xe1c, 0x2a2a2a2a, - 0xe28, 0x00000000, - 0xe30, 0x1000dc1f, - 0xe34, 0x10008c1f, - 0xe38, 0x02140102, - 0xe3c, 0x681604c2, - 0xe40, 0x01007c00, - 0xe44, 0x01004800, - 0xe48, 0xfb000000, - 0xe4c, 0x000028d1, - 0xe50, 0x1000dc1f, - 0xe54, 0x10008c1f, - 0xe58, 0x02140102, - 0xe5c, 0x28160d05, - 0xe60, 0x00000010, - 0xe68, 0x001b25a4, - 0xe6c, 0x631b25a0, - 0xe70, 0x631b25a0, - 0xe74, 0x081b25a0, - 0xe78, 0x081b25a0, - 0xe7c, 0x081b25a0, - 0xe80, 0x081b25a0, - 0xe84, 0x631b25a0, - 0xe88, 0x081b25a0, - 0xe8c, 0x631b25a0, - 0xed0, 0x631b25a0, - 0xed4, 0x631b25a0, - 0xed8, 0x631b25a0, - 0xedc, 0x001b25a0, - 0xee0, 0x001b25a0, - 0xeec, 0x6b1b25a0, - 0xf14, 0x00000003, - 0xf4c, 0x00000000, - 0xf00, 0x00000300, -}; - -u32 RTL8192CEPHY_REG_ARRAY_PG[PHY_REG_ARRAY_PGLENGTH] = { - 0xe00, 0xffffffff, 0x0a0c0c0c, - 0xe04, 0xffffffff, 0x02040608, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x0a0c0d0e, - 0xe14, 0xffffffff, 0x02040608, - 0xe18, 0xffffffff, 0x0a0c0d0e, - 0xe1c, 0xffffffff, 0x02040608, - 0x830, 0xffffffff, 0x0a0c0c0c, - 0x834, 0xffffffff, 0x02040608, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x0a0c0d0e, - 0x848, 0xffffffff, 0x02040608, - 0x84c, 0xffffffff, 0x0a0c0d0e, - 0x868, 0xffffffff, 0x02040608, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x06060606, - 0xe14, 0xffffffff, 0x00020406, - 0xe18, 0xffffffff, 0x06060606, - 0xe1c, 0xffffffff, 0x00020406, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x06060606, - 0x848, 0xffffffff, 0x00020406, - 0x84c, 0xffffffff, 0x06060606, - 0x868, 0xffffffff, 0x00020406, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, -}; - -u32 RTL8192CERADIOA_2TARRAY[RADIOA_2TARRAYLENGTH] = { - 0x000, 0x00030159, - 0x001, 0x00031284, - 0x002, 0x00098000, - 0x003, 0x00018c63, - 0x004, 0x000210e7, - 0x009, 0x0002044f, - 0x00a, 0x0001adb0, - 0x00b, 0x00054867, - 0x00c, 0x0008992e, - 0x00d, 0x0000e52c, - 0x00e, 0x00039ce7, - 0x00f, 0x00000451, - 0x019, 0x00000000, - 0x01a, 0x00010255, - 0x01b, 0x00060a00, - 0x01c, 0x000fc378, - 0x01d, 0x000a1250, - 0x01e, 0x0004445f, - 0x01f, 0x00080001, - 0x020, 0x0000b614, - 0x021, 0x0006c000, - 0x022, 0x00000000, - 0x023, 0x00001558, - 0x024, 0x00000060, - 0x025, 0x00000483, - 0x026, 0x0004f000, - 0x027, 0x000ec7d9, - 0x028, 0x000977c0, - 0x029, 0x00004783, - 0x02a, 0x00000001, - 0x02b, 0x00021334, - 0x02a, 0x00000000, - 0x02b, 0x00000054, - 0x02a, 0x00000001, - 0x02b, 0x00000808, - 0x02b, 0x00053333, - 0x02c, 0x0000000c, - 0x02a, 0x00000002, - 0x02b, 0x00000808, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000003, - 0x02b, 0x00000808, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000004, - 0x02b, 0x00000808, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000005, - 0x02b, 0x00000808, - 0x02b, 0x00073333, - 0x02c, 0x0000000d, - 0x02a, 0x00000006, - 0x02b, 0x00000709, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000007, - 0x02b, 0x00000709, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000008, - 0x02b, 0x0000060a, - 0x02b, 0x0004b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000009, - 0x02b, 0x0000060a, - 0x02b, 0x00053333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000a, - 0x02b, 0x0000060a, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000b, - 0x02b, 0x0000060a, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000c, - 0x02b, 0x0000060a, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000d, - 0x02b, 0x0000060a, - 0x02b, 0x00073333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000e, - 0x02b, 0x0000050b, - 0x02b, 0x00066666, - 0x02c, 0x0000001a, - 0x02a, 0x000e0000, - 0x010, 0x0004000f, - 0x011, 0x000e31fc, - 0x010, 0x0006000f, - 0x011, 0x000ff9f8, - 0x010, 0x0002000f, - 0x011, 0x000203f9, - 0x010, 0x0003000f, - 0x011, 0x000ff500, - 0x010, 0x00000000, - 0x011, 0x00000000, - 0x010, 0x0008000f, - 0x011, 0x0003f100, - 0x010, 0x0009000f, - 0x011, 0x00023100, - 0x012, 0x00032000, - 0x012, 0x00071000, - 0x012, 0x000b0000, - 0x012, 0x000fc000, - 0x013, 0x000287af, - 0x013, 0x000244b7, - 0x013, 0x000204ab, - 0x013, 0x0001c49f, - 0x013, 0x00018493, - 0x013, 0x00014297, - 0x013, 0x00010295, - 0x013, 0x0000c298, - 0x013, 0x0000819c, - 0x013, 0x000040a8, - 0x013, 0x0000001c, - 0x014, 0x0001944c, - 0x014, 0x00059444, - 0x014, 0x0009944c, - 0x014, 0x000d9444, - 0x015, 0x0000f424, - 0x015, 0x0004f424, - 0x015, 0x0008f424, - 0x015, 0x000cf424, - 0x016, 0x000e0330, - 0x016, 0x000a0330, - 0x016, 0x00060330, - 0x016, 0x00020330, - 0x000, 0x00010159, - 0x018, 0x0000f401, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01f, 0x00080003, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01e, 0x00044457, - 0x01f, 0x00080000, - 0x000, 0x00030159, -}; - -u32 RTL8192CE_RADIOB_2TARRAY[RADIOB_2TARRAYLENGTH] = { - 0x000, 0x00030159, - 0x001, 0x00031284, - 0x002, 0x00098000, - 0x003, 0x00018c63, - 0x004, 0x000210e7, - 0x009, 0x0002044f, - 0x00a, 0x0001adb0, - 0x00b, 0x00054867, - 0x00c, 0x0008992e, - 0x00d, 0x0000e52c, - 0x00e, 0x00039ce7, - 0x00f, 0x00000451, - 0x012, 0x00032000, - 0x012, 0x00071000, - 0x012, 0x000b0000, - 0x012, 0x000fc000, - 0x013, 0x000287af, - 0x013, 0x000244b7, - 0x013, 0x000204ab, - 0x013, 0x0001c49f, - 0x013, 0x00018493, - 0x013, 0x00014297, - 0x013, 0x00010295, - 0x013, 0x0000c298, - 0x013, 0x0000819c, - 0x013, 0x000040a8, - 0x013, 0x0000001c, - 0x014, 0x0001944c, - 0x014, 0x00059444, - 0x014, 0x0009944c, - 0x014, 0x000d9444, - 0x015, 0x0000f424, - 0x015, 0x0004f424, - 0x015, 0x0008f424, - 0x015, 0x000cf424, - 0x016, 0x000e0330, - 0x016, 0x000a0330, - 0x016, 0x00060330, - 0x016, 0x00020330, -}; - -u32 RTL8192CE_RADIOA_1TARRAY[RADIOA_1TARRAYLENGTH] = { - 0x000, 0x00030159, - 0x001, 0x00031284, - 0x002, 0x00098000, - 0x003, 0x00018c63, - 0x004, 0x000210e7, - 0x009, 0x0002044f, - 0x00a, 0x0001adb0, - 0x00b, 0x00054867, - 0x00c, 0x0008992e, - 0x00d, 0x0000e52c, - 0x00e, 0x00039ce7, - 0x00f, 0x00000451, - 0x019, 0x00000000, - 0x01a, 0x00010255, - 0x01b, 0x00060a00, - 0x01c, 0x000fc378, - 0x01d, 0x000a1250, - 0x01e, 0x0004445f, - 0x01f, 0x00080001, - 0x020, 0x0000b614, - 0x021, 0x0006c000, - 0x022, 0x00000000, - 0x023, 0x00001558, - 0x024, 0x00000060, - 0x025, 0x00000483, - 0x026, 0x0004f000, - 0x027, 0x000ec7d9, - 0x028, 0x000977c0, - 0x029, 0x00004783, - 0x02a, 0x00000001, - 0x02b, 0x00021334, - 0x02a, 0x00000000, - 0x02b, 0x00000054, - 0x02a, 0x00000001, - 0x02b, 0x00000808, - 0x02b, 0x00053333, - 0x02c, 0x0000000c, - 0x02a, 0x00000002, - 0x02b, 0x00000808, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000003, - 0x02b, 0x00000808, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000004, - 0x02b, 0x00000808, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000005, - 0x02b, 0x00000808, - 0x02b, 0x00073333, - 0x02c, 0x0000000d, - 0x02a, 0x00000006, - 0x02b, 0x00000709, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000007, - 0x02b, 0x00000709, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000008, - 0x02b, 0x0000060a, - 0x02b, 0x0004b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000009, - 0x02b, 0x0000060a, - 0x02b, 0x00053333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000a, - 0x02b, 0x0000060a, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000b, - 0x02b, 0x0000060a, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000c, - 0x02b, 0x0000060a, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000d, - 0x02b, 0x0000060a, - 0x02b, 0x00073333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000e, - 0x02b, 0x0000050b, - 0x02b, 0x00066666, - 0x02c, 0x0000001a, - 0x02a, 0x000e0000, - 0x010, 0x0004000f, - 0x011, 0x000e31fc, - 0x010, 0x0006000f, - 0x011, 0x000ff9f8, - 0x010, 0x0002000f, - 0x011, 0x000203f9, - 0x010, 0x0003000f, - 0x011, 0x000ff500, - 0x010, 0x00000000, - 0x011, 0x00000000, - 0x010, 0x0008000f, - 0x011, 0x0003f100, - 0x010, 0x0009000f, - 0x011, 0x00023100, - 0x012, 0x00032000, - 0x012, 0x00071000, - 0x012, 0x000b0000, - 0x012, 0x000fc000, - 0x013, 0x000287af, - 0x013, 0x000244b7, - 0x013, 0x000204ab, - 0x013, 0x0001c49f, - 0x013, 0x00018493, - 0x013, 0x00014297, - 0x013, 0x00010295, - 0x013, 0x0000c298, - 0x013, 0x0000819c, - 0x013, 0x000040a8, - 0x013, 0x0000001c, - 0x014, 0x0001944c, - 0x014, 0x00059444, - 0x014, 0x0009944c, - 0x014, 0x000d9444, - 0x015, 0x0000f424, - 0x015, 0x0004f424, - 0x015, 0x0008f424, - 0x015, 0x000cf424, - 0x016, 0x000e0330, - 0x016, 0x000a0330, - 0x016, 0x00060330, - 0x016, 0x00020330, - 0x000, 0x00010159, - 0x018, 0x0000f401, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01f, 0x00080003, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01e, 0x00044457, - 0x01f, 0x00080000, - 0x000, 0x00030159, -}; - -u32 RTL8192CE_RADIOB_1TARRAY[RADIOB_1TARRAYLENGTH] = { - 0x0, -}; - -u32 RTL8192CEMAC_2T_ARRAY[MAC_2T_ARRAYLENGTH] = { - 0x420, 0x00000080, - 0x423, 0x00000000, - 0x430, 0x00000000, - 0x431, 0x00000000, - 0x432, 0x00000000, - 0x433, 0x00000001, - 0x434, 0x00000004, - 0x435, 0x00000005, - 0x436, 0x00000006, - 0x437, 0x00000007, - 0x438, 0x00000000, - 0x439, 0x00000000, - 0x43a, 0x00000000, - 0x43b, 0x00000001, - 0x43c, 0x00000004, - 0x43d, 0x00000005, - 0x43e, 0x00000006, - 0x43f, 0x00000007, - 0x440, 0x0000005d, - 0x441, 0x00000001, - 0x442, 0x00000000, - 0x444, 0x00000015, - 0x445, 0x000000f0, - 0x446, 0x0000000f, - 0x447, 0x00000000, - 0x458, 0x00000041, - 0x459, 0x000000a8, - 0x45a, 0x00000072, - 0x45b, 0x000000b9, - 0x460, 0x00000088, - 0x461, 0x00000088, - 0x462, 0x00000006, - 0x463, 0x00000003, - 0x4c8, 0x00000004, - 0x4c9, 0x00000008, - 0x4cc, 0x00000002, - 0x4cd, 0x00000028, - 0x4ce, 0x00000001, - 0x500, 0x00000026, - 0x501, 0x000000a2, - 0x502, 0x0000002f, - 0x503, 0x00000000, - 0x504, 0x00000028, - 0x505, 0x000000a3, - 0x506, 0x0000005e, - 0x507, 0x00000000, - 0x508, 0x0000002b, - 0x509, 0x000000a4, - 0x50a, 0x0000005e, - 0x50b, 0x00000000, - 0x50c, 0x0000004f, - 0x50d, 0x000000a4, - 0x50e, 0x00000000, - 0x50f, 0x00000000, - 0x512, 0x0000001c, - 0x514, 0x0000000a, - 0x515, 0x00000010, - 0x516, 0x0000000a, - 0x517, 0x00000010, - 0x51a, 0x00000016, - 0x524, 0x0000000f, - 0x525, 0x0000004f, - 0x546, 0x00000020, - 0x547, 0x00000000, - 0x559, 0x00000002, - 0x55a, 0x00000002, - 0x55d, 0x000000ff, - 0x605, 0x00000030, - 0x608, 0x0000000e, - 0x609, 0x0000002a, - 0x652, 0x00000020, - 0x63c, 0x0000000a, - 0x63d, 0x0000000a, - 0x700, 0x00000021, - 0x701, 0x00000043, - 0x702, 0x00000065, - 0x703, 0x00000087, - 0x708, 0x00000021, - 0x709, 0x00000043, - 0x70a, 0x00000065, - 0x70b, 0x00000087, -}; - -u32 RTL8192CEAGCTAB_2TARRAY[AGCTAB_2TARRAYLENGTH] = { - 0xc78, 0x7b000001, - 0xc78, 0x7b010001, - 0xc78, 0x7b020001, - 0xc78, 0x7b030001, - 0xc78, 0x7b040001, - 0xc78, 0x7b050001, - 0xc78, 0x7a060001, - 0xc78, 0x79070001, - 0xc78, 0x78080001, - 0xc78, 0x77090001, - 0xc78, 0x760a0001, - 0xc78, 0x750b0001, - 0xc78, 0x740c0001, - 0xc78, 0x730d0001, - 0xc78, 0x720e0001, - 0xc78, 0x710f0001, - 0xc78, 0x70100001, - 0xc78, 0x6f110001, - 0xc78, 0x6e120001, - 0xc78, 0x6d130001, - 0xc78, 0x6c140001, - 0xc78, 0x6b150001, - 0xc78, 0x6a160001, - 0xc78, 0x69170001, - 0xc78, 0x68180001, - 0xc78, 0x67190001, - 0xc78, 0x661a0001, - 0xc78, 0x651b0001, - 0xc78, 0x641c0001, - 0xc78, 0x631d0001, - 0xc78, 0x621e0001, - 0xc78, 0x611f0001, - 0xc78, 0x60200001, - 0xc78, 0x49210001, - 0xc78, 0x48220001, - 0xc78, 0x47230001, - 0xc78, 0x46240001, - 0xc78, 0x45250001, - 0xc78, 0x44260001, - 0xc78, 0x43270001, - 0xc78, 0x42280001, - 0xc78, 0x41290001, - 0xc78, 0x402a0001, - 0xc78, 0x262b0001, - 0xc78, 0x252c0001, - 0xc78, 0x242d0001, - 0xc78, 0x232e0001, - 0xc78, 0x222f0001, - 0xc78, 0x21300001, - 0xc78, 0x20310001, - 0xc78, 0x06320001, - 0xc78, 0x05330001, - 0xc78, 0x04340001, - 0xc78, 0x03350001, - 0xc78, 0x02360001, - 0xc78, 0x01370001, - 0xc78, 0x00380001, - 0xc78, 0x00390001, - 0xc78, 0x003a0001, - 0xc78, 0x003b0001, - 0xc78, 0x003c0001, - 0xc78, 0x003d0001, - 0xc78, 0x003e0001, - 0xc78, 0x003f0001, - 0xc78, 0x7b400001, - 0xc78, 0x7b410001, - 0xc78, 0x7b420001, - 0xc78, 0x7b430001, - 0xc78, 0x7b440001, - 0xc78, 0x7b450001, - 0xc78, 0x7a460001, - 0xc78, 0x79470001, - 0xc78, 0x78480001, - 0xc78, 0x77490001, - 0xc78, 0x764a0001, - 0xc78, 0x754b0001, - 0xc78, 0x744c0001, - 0xc78, 0x734d0001, - 0xc78, 0x724e0001, - 0xc78, 0x714f0001, - 0xc78, 0x70500001, - 0xc78, 0x6f510001, - 0xc78, 0x6e520001, - 0xc78, 0x6d530001, - 0xc78, 0x6c540001, - 0xc78, 0x6b550001, - 0xc78, 0x6a560001, - 0xc78, 0x69570001, - 0xc78, 0x68580001, - 0xc78, 0x67590001, - 0xc78, 0x665a0001, - 0xc78, 0x655b0001, - 0xc78, 0x645c0001, - 0xc78, 0x635d0001, - 0xc78, 0x625e0001, - 0xc78, 0x615f0001, - 0xc78, 0x60600001, - 0xc78, 0x49610001, - 0xc78, 0x48620001, - 0xc78, 0x47630001, - 0xc78, 0x46640001, - 0xc78, 0x45650001, - 0xc78, 0x44660001, - 0xc78, 0x43670001, - 0xc78, 0x42680001, - 0xc78, 0x41690001, - 0xc78, 0x406a0001, - 0xc78, 0x266b0001, - 0xc78, 0x256c0001, - 0xc78, 0x246d0001, - 0xc78, 0x236e0001, - 0xc78, 0x226f0001, - 0xc78, 0x21700001, - 0xc78, 0x20710001, - 0xc78, 0x06720001, - 0xc78, 0x05730001, - 0xc78, 0x04740001, - 0xc78, 0x03750001, - 0xc78, 0x02760001, - 0xc78, 0x01770001, - 0xc78, 0x00780001, - 0xc78, 0x00790001, - 0xc78, 0x007a0001, - 0xc78, 0x007b0001, - 0xc78, 0x007c0001, - 0xc78, 0x007d0001, - 0xc78, 0x007e0001, - 0xc78, 0x007f0001, - 0xc78, 0x3800001e, - 0xc78, 0x3801001e, - 0xc78, 0x3802001e, - 0xc78, 0x3803001e, - 0xc78, 0x3804001e, - 0xc78, 0x3805001e, - 0xc78, 0x3806001e, - 0xc78, 0x3807001e, - 0xc78, 0x3808001e, - 0xc78, 0x3c09001e, - 0xc78, 0x3e0a001e, - 0xc78, 0x400b001e, - 0xc78, 0x440c001e, - 0xc78, 0x480d001e, - 0xc78, 0x4c0e001e, - 0xc78, 0x500f001e, - 0xc78, 0x5210001e, - 0xc78, 0x5611001e, - 0xc78, 0x5a12001e, - 0xc78, 0x5e13001e, - 0xc78, 0x6014001e, - 0xc78, 0x6015001e, - 0xc78, 0x6016001e, - 0xc78, 0x6217001e, - 0xc78, 0x6218001e, - 0xc78, 0x6219001e, - 0xc78, 0x621a001e, - 0xc78, 0x621b001e, - 0xc78, 0x621c001e, - 0xc78, 0x621d001e, - 0xc78, 0x621e001e, - 0xc78, 0x621f001e, -}; - -u32 RTL8192CEAGCTAB_1TARRAY[AGCTAB_1TARRAYLENGTH] = { - 0xc78, 0x7b000001, - 0xc78, 0x7b010001, - 0xc78, 0x7b020001, - 0xc78, 0x7b030001, - 0xc78, 0x7b040001, - 0xc78, 0x7b050001, - 0xc78, 0x7a060001, - 0xc78, 0x79070001, - 0xc78, 0x78080001, - 0xc78, 0x77090001, - 0xc78, 0x760a0001, - 0xc78, 0x750b0001, - 0xc78, 0x740c0001, - 0xc78, 0x730d0001, - 0xc78, 0x720e0001, - 0xc78, 0x710f0001, - 0xc78, 0x70100001, - 0xc78, 0x6f110001, - 0xc78, 0x6e120001, - 0xc78, 0x6d130001, - 0xc78, 0x6c140001, - 0xc78, 0x6b150001, - 0xc78, 0x6a160001, - 0xc78, 0x69170001, - 0xc78, 0x68180001, - 0xc78, 0x67190001, - 0xc78, 0x661a0001, - 0xc78, 0x651b0001, - 0xc78, 0x641c0001, - 0xc78, 0x631d0001, - 0xc78, 0x621e0001, - 0xc78, 0x611f0001, - 0xc78, 0x60200001, - 0xc78, 0x49210001, - 0xc78, 0x48220001, - 0xc78, 0x47230001, - 0xc78, 0x46240001, - 0xc78, 0x45250001, - 0xc78, 0x44260001, - 0xc78, 0x43270001, - 0xc78, 0x42280001, - 0xc78, 0x41290001, - 0xc78, 0x402a0001, - 0xc78, 0x262b0001, - 0xc78, 0x252c0001, - 0xc78, 0x242d0001, - 0xc78, 0x232e0001, - 0xc78, 0x222f0001, - 0xc78, 0x21300001, - 0xc78, 0x20310001, - 0xc78, 0x06320001, - 0xc78, 0x05330001, - 0xc78, 0x04340001, - 0xc78, 0x03350001, - 0xc78, 0x02360001, - 0xc78, 0x01370001, - 0xc78, 0x00380001, - 0xc78, 0x00390001, - 0xc78, 0x003a0001, - 0xc78, 0x003b0001, - 0xc78, 0x003c0001, - 0xc78, 0x003d0001, - 0xc78, 0x003e0001, - 0xc78, 0x003f0001, - 0xc78, 0x7b400001, - 0xc78, 0x7b410001, - 0xc78, 0x7b420001, - 0xc78, 0x7b430001, - 0xc78, 0x7b440001, - 0xc78, 0x7b450001, - 0xc78, 0x7a460001, - 0xc78, 0x79470001, - 0xc78, 0x78480001, - 0xc78, 0x77490001, - 0xc78, 0x764a0001, - 0xc78, 0x754b0001, - 0xc78, 0x744c0001, - 0xc78, 0x734d0001, - 0xc78, 0x724e0001, - 0xc78, 0x714f0001, - 0xc78, 0x70500001, - 0xc78, 0x6f510001, - 0xc78, 0x6e520001, - 0xc78, 0x6d530001, - 0xc78, 0x6c540001, - 0xc78, 0x6b550001, - 0xc78, 0x6a560001, - 0xc78, 0x69570001, - 0xc78, 0x68580001, - 0xc78, 0x67590001, - 0xc78, 0x665a0001, - 0xc78, 0x655b0001, - 0xc78, 0x645c0001, - 0xc78, 0x635d0001, - 0xc78, 0x625e0001, - 0xc78, 0x615f0001, - 0xc78, 0x60600001, - 0xc78, 0x49610001, - 0xc78, 0x48620001, - 0xc78, 0x47630001, - 0xc78, 0x46640001, - 0xc78, 0x45650001, - 0xc78, 0x44660001, - 0xc78, 0x43670001, - 0xc78, 0x42680001, - 0xc78, 0x41690001, - 0xc78, 0x406a0001, - 0xc78, 0x266b0001, - 0xc78, 0x256c0001, - 0xc78, 0x246d0001, - 0xc78, 0x236e0001, - 0xc78, 0x226f0001, - 0xc78, 0x21700001, - 0xc78, 0x20710001, - 0xc78, 0x06720001, - 0xc78, 0x05730001, - 0xc78, 0x04740001, - 0xc78, 0x03750001, - 0xc78, 0x02760001, - 0xc78, 0x01770001, - 0xc78, 0x00780001, - 0xc78, 0x00790001, - 0xc78, 0x007a0001, - 0xc78, 0x007b0001, - 0xc78, 0x007c0001, - 0xc78, 0x007d0001, - 0xc78, 0x007e0001, - 0xc78, 0x007f0001, - 0xc78, 0x3800001e, - 0xc78, 0x3801001e, - 0xc78, 0x3802001e, - 0xc78, 0x3803001e, - 0xc78, 0x3804001e, - 0xc78, 0x3805001e, - 0xc78, 0x3806001e, - 0xc78, 0x3807001e, - 0xc78, 0x3808001e, - 0xc78, 0x3c09001e, - 0xc78, 0x3e0a001e, - 0xc78, 0x400b001e, - 0xc78, 0x440c001e, - 0xc78, 0x480d001e, - 0xc78, 0x4c0e001e, - 0xc78, 0x500f001e, - 0xc78, 0x5210001e, - 0xc78, 0x5611001e, - 0xc78, 0x5a12001e, - 0xc78, 0x5e13001e, - 0xc78, 0x6014001e, - 0xc78, 0x6015001e, - 0xc78, 0x6016001e, - 0xc78, 0x6217001e, - 0xc78, 0x6218001e, - 0xc78, 0x6219001e, - 0xc78, 0x621a001e, - 0xc78, 0x621b001e, - 0xc78, 0x621c001e, - 0xc78, 0x621d001e, - 0xc78, 0x621e001e, - 0xc78, 0x621f001e, -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/table.h b/drivers/net/wireless/rtlwifi/rtl8192ce/table.h deleted file mode 100644 index 8b79161f71be..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/table.h +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CE_TABLE__H_ -#define __RTL92CE_TABLE__H_ - -#include - -#define PHY_REG_2TARRAY_LENGTH 374 -extern u32 RTL8192CEPHY_REG_2TARRAY[PHY_REG_2TARRAY_LENGTH]; -#define PHY_REG_1TARRAY_LENGTH 374 -extern u32 RTL8192CEPHY_REG_1TARRAY[PHY_REG_1TARRAY_LENGTH]; -#define PHY_REG_ARRAY_PGLENGTH 192 -extern u32 RTL8192CEPHY_REG_ARRAY_PG[PHY_REG_ARRAY_PGLENGTH]; -#define RADIOA_2TARRAYLENGTH 282 -extern u32 RTL8192CERADIOA_2TARRAY[RADIOA_2TARRAYLENGTH]; -#define RADIOB_2TARRAYLENGTH 78 -extern u32 RTL8192CE_RADIOB_2TARRAY[RADIOB_2TARRAYLENGTH]; -#define RADIOA_1TARRAYLENGTH 282 -extern u32 RTL8192CE_RADIOA_1TARRAY[RADIOA_1TARRAYLENGTH]; -#define RADIOB_1TARRAYLENGTH 1 -extern u32 RTL8192CE_RADIOB_1TARRAY[RADIOB_1TARRAYLENGTH]; -#define MAC_2T_ARRAYLENGTH 162 -extern u32 RTL8192CEMAC_2T_ARRAY[MAC_2T_ARRAYLENGTH]; -#define AGCTAB_2TARRAYLENGTH 320 -extern u32 RTL8192CEAGCTAB_2TARRAY[AGCTAB_2TARRAYLENGTH]; -#define AGCTAB_1TARRAYLENGTH 320 -extern u32 RTL8192CEAGCTAB_1TARRAY[AGCTAB_1TARRAYLENGTH]; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c deleted file mode 100644 index 84ddd4d07a1d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ /dev/null @@ -1,768 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../stats.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "trx.h" -#include "led.h" - -static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) -{ - __le16 fc = rtl_get_fc(skb); - - if (unlikely(ieee80211_is_beacon(fc))) - return QSLT_BEACON; - if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) - return QSLT_MGNT; - - return skb->priority; -} - -static u8 _rtl92c_query_rxpwrpercentage(char antpower) -{ - if ((antpower <= -100) || (antpower >= 20)) - return 0; - else if (antpower >= 0) - return 100; - else - return 100 + antpower; -} - -static u8 _rtl92c_evm_db_to_percentage(char value) -{ - char ret_val; - ret_val = value; - - if (ret_val >= 0) - ret_val = 0; - - if (ret_val <= -33) - ret_val = -33; - - ret_val = 0 - ret_val; - ret_val *= 3; - - if (ret_val == 99) - ret_val = 100; - - return ret_val; -} - -static long _rtl92ce_signal_scale_mapping(struct ieee80211_hw *hw, - long currsig) -{ - long retsig; - - if (currsig >= 61 && currsig <= 100) - retsig = 90 + ((currsig - 60) / 4); - else if (currsig >= 41 && currsig <= 60) - retsig = 78 + ((currsig - 40) / 2); - else if (currsig >= 31 && currsig <= 40) - retsig = 66 + (currsig - 30); - else if (currsig >= 21 && currsig <= 30) - retsig = 54 + (currsig - 20); - else if (currsig >= 5 && currsig <= 20) - retsig = 42 + (((currsig - 5) * 2) / 3); - else if (currsig == 4) - retsig = 36; - else if (currsig == 3) - retsig = 27; - else if (currsig == 2) - retsig = 18; - else if (currsig == 1) - retsig = 9; - else - retsig = currsig; - - return retsig; -} - -static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, - struct rtl_stats *pstats, - struct rx_desc_92c *pdesc, - struct rx_fwinfo_92c *p_drvinfo, - bool packet_match_bssid, - bool packet_toself, - bool packet_beacon) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct phy_sts_cck_8192s_t *cck_buf; - struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); - s8 rx_pwr_all = 0, rx_pwr[4]; - u8 evm, pwdb_all, rf_rx_num = 0; - u8 i, max_spatial_stream; - u32 rssi, total_rssi = 0; - bool is_cck_rate; - - is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc->rxmcs); - pstats->packet_matchbssid = packet_match_bssid; - pstats->packet_toself = packet_toself; - pstats->is_cck = is_cck_rate; - pstats->packet_beacon = packet_beacon; - pstats->rx_mimo_sig_qual[0] = -1; - pstats->rx_mimo_sig_qual[1] = -1; - - if (is_cck_rate) { - u8 report, cck_highpwr; - cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; - - if (ppsc->rfpwr_state == ERFON) - cck_highpwr = (u8) rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, - BIT(9)); - else - cck_highpwr = false; - - if (!cck_highpwr) { - u8 cck_agc_rpt = cck_buf->cck_agc_rpt; - report = cck_buf->cck_agc_rpt & 0xc0; - report = report >> 6; - switch (report) { - case 0x3: - rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); - break; - case 0x2: - rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); - break; - case 0x1: - rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); - break; - case 0x0: - rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); - break; - } - } else { - u8 cck_agc_rpt = cck_buf->cck_agc_rpt; - report = p_drvinfo->cfosho[0] & 0x60; - report = report >> 5; - switch (report) { - case 0x3: - rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x2: - rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x1: - rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x0: - rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1); - break; - } - } - - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - /* CCK gain is smaller than OFDM/MCS gain, - * so we add gain diff by experiences, - * the val is 6 - */ - pwdb_all += 6; - if (pwdb_all > 100) - pwdb_all = 100; - /* modify the offset to make the same - * gain index with OFDM. - */ - if (pwdb_all > 34 && pwdb_all <= 42) - pwdb_all -= 2; - else if (pwdb_all > 26 && pwdb_all <= 34) - pwdb_all -= 6; - else if (pwdb_all > 14 && pwdb_all <= 26) - pwdb_all -= 8; - else if (pwdb_all > 4 && pwdb_all <= 14) - pwdb_all -= 4; - - pstats->rx_pwdb_all = pwdb_all; - pstats->recvsignalpower = rx_pwr_all; - - /* (3) Get Signal Quality (EVM) */ - if (packet_match_bssid) { - u8 sq; - if (pstats->rx_pwdb_all > 40) - sq = 100; - else { - sq = cck_buf->sq_rpt; - if (sq > 64) - sq = 0; - else if (sq < 20) - sq = 100; - else - sq = ((64 - sq) * 100) / 44; - } - - pstats->signalquality = sq; - pstats->rx_mimo_sig_qual[0] = sq; - pstats->rx_mimo_sig_qual[1] = -1; - } - } else { - rtlpriv->dm.rfpath_rxenable[0] = - rtlpriv->dm.rfpath_rxenable[1] = true; - /* (1)Get RSSI for HT rate */ - for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { - /* we will judge RF RX path now. */ - if (rtlpriv->dm.rfpath_rxenable[i]) - rf_rx_num++; - - rx_pwr[i] = - ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110; - /* Translate DBM to percentage. */ - rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]); - total_rssi += rssi; - /* Get Rx snr value in DB */ - rtlpriv->stats.rx_snr_db[i] = - (long)(p_drvinfo->rxsnr[i] / 2); - - /* Record Signal Strength for next packet */ - if (packet_match_bssid) - pstats->rx_mimo_signalstrength[i] = (u8) rssi; - } - - /* (2)PWDB, Average PWDB cacluated by - * hardware (for rate adaptive) - */ - rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; - pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); - pstats->rx_pwdb_all = pwdb_all; - pstats->rxpower = rx_pwr_all; - pstats->recvsignalpower = rx_pwr_all; - - /* (3)EVM of HT rate */ - if (pstats->is_ht && pstats->rate >= DESC_RATEMCS8 && - pstats->rate <= DESC_RATEMCS15) - max_spatial_stream = 2; - else - max_spatial_stream = 1; - - for (i = 0; i < max_spatial_stream; i++) { - evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]); - - if (packet_match_bssid) { - /* Fill value in RFD, Get the first - * spatial stream only - */ - if (i == 0) - pstats->signalquality = - (u8) (evm & 0xff); - pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff); - } - } - } - - /* UI BSS List signal strength(in percentage), - * make it good looking, from 0~100. - */ - if (is_cck_rate) - pstats->signalstrength = - (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all)); - else if (rf_rx_num != 0) - pstats->signalstrength = - (u8) (_rtl92ce_signal_scale_mapping - (hw, total_rssi /= rf_rx_num)); -} - -static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct rtl_stats *pstats, - struct rx_desc_92c *pdesc, - struct rx_fwinfo_92c *p_drvinfo) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - - struct ieee80211_hdr *hdr; - u8 *tmp_buf; - u8 *praddr; - __le16 fc; - u16 type, c_fc; - bool packet_matchbssid, packet_toself, packet_beacon = false; - - tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; - - hdr = (struct ieee80211_hdr *)tmp_buf; - fc = hdr->frame_control; - c_fc = le16_to_cpu(fc); - type = WLAN_FC_GET_TYPE(fc); - praddr = hdr->addr1; - - packet_matchbssid = - ((IEEE80211_FTYPE_CTL != type) && - ether_addr_equal(mac->bssid, - (c_fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : - (c_fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : - hdr->addr3) && - (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv)); - - packet_toself = packet_matchbssid && - ether_addr_equal(praddr, rtlefuse->dev_addr); - - if (ieee80211_is_beacon(fc)) - packet_beacon = true; - - _rtl92ce_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, - packet_matchbssid, packet_toself, - packet_beacon); - - rtl_process_phyinfo(hw, tmp_buf, pstats); -} - -bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *stats, - struct ieee80211_rx_status *rx_status, - u8 *p_desc, struct sk_buff *skb) -{ - struct rx_fwinfo_92c *p_drvinfo; - struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; - struct ieee80211_hdr *hdr; - u32 phystatus = GET_RX_DESC_PHYST(pdesc); - stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); - stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * - RX_DRV_INFO_SIZE_UNIT; - stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); - stats->icv = (u16) GET_RX_DESC_ICV(pdesc); - stats->crc = (u16) GET_RX_DESC_CRC32(pdesc); - stats->hwerror = (stats->crc | stats->icv); - stats->decrypted = !GET_RX_DESC_SWDEC(pdesc); - stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc); - stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); - stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); - stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) - && (GET_RX_DESC_FAGGR(pdesc) == 1)); - stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); - stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); - stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); - - stats->is_cck = RX_HAL_IS_CCK_RATE(pdesc->rxmcs); - - rx_status->freq = hw->conf.chandef.chan->center_freq; - rx_status->band = hw->conf.chandef.chan->band; - - hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size - + stats->rx_bufshift); - - if (stats->crc) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - - if (stats->rx_is40Mhzpacket) - rx_status->flag |= RX_FLAG_40MHZ; - - if (stats->is_ht) - rx_status->flag |= RX_FLAG_HT; - - rx_status->flag |= RX_FLAG_MACTIME_START; - - /* hw will set stats->decrypted true, if it finds the - * frame is open data frame or mgmt frame. - * So hw will not decryption robust managment frame - * for IEEE80211w but still set status->decrypted - * true, so here we should set it back to undecrypted - * for IEEE80211w frame, and mac80211 sw will help - * to decrypt it - */ - if (stats->decrypted) { - if ((_ieee80211_is_robust_mgmt_frame(hdr)) && - (ieee80211_has_protected(hdr->frame_control))) - rx_status->flag &= ~RX_FLAG_DECRYPTED; - else - rx_status->flag |= RX_FLAG_DECRYPTED; - } - /* rate_idx: index of data rate into band's - * supported rates or MCS index if HT rates - * are use (RX_FLAG_HT) - * Notice: this is diff with windows define - */ - rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht, - false, stats->rate); - - rx_status->mactime = stats->timestamp_low; - if (phystatus) { - p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + - stats->rx_bufshift); - - _rtl92ce_translate_rx_signal_stuff(hw, - skb, stats, pdesc, - p_drvinfo); - } - - /*rx_status->qual = stats->signal; */ - rx_status->signal = stats->recvsignalpower + 10; - - return true; -} - -void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *pbd_desc_tx, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *tcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool defaultadapter = true; - u8 *pdesc = pdesc_tx; - u16 seq_number; - __le16 fc = hdr->frame_control; - u8 fw_qsel = _rtl92ce_map_hwqueue_to_fwqueue(skb, hw_queue); - bool firstseg = ((hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); - - bool lastseg = ((hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); - - dma_addr_t mapping = pci_map_single(rtlpci->pdev, - skb->data, skb->len, - PCI_DMA_TODEVICE); - - u8 bw_40 = 0; - - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - rcu_read_lock(); - sta = get_sta(hw, mac->vif, mac->bssid); - if (mac->opmode == NL80211_IFTYPE_STATION) { - bw_40 = mac->bw_40; - } else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - if (sta) - bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; - } - - seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - - rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); - - CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c)); - - if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { - firstseg = true; - lastseg = true; - } - if (firstseg) { - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - - SET_TX_DESC_TX_RATE(pdesc, tcb_desc->hw_rate); - - if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) - SET_TX_DESC_DATA_SHORTGI(pdesc, 1); - - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - SET_TX_DESC_AGG_BREAK(pdesc, 1); - SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); - } - SET_TX_DESC_SEQ(pdesc, seq_number); - - SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc->rts_enable && - !tcb_desc-> - cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(pdesc, - ((tcb_desc->rts_enable - || tcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); - - SET_TX_DESC_RTS_RATE(pdesc, tcb_desc->rts_rate); - SET_TX_DESC_RTS_BW(pdesc, 0); - SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(pdesc, - ((tcb_desc->rts_rate <= DESC_RATE54M) ? - (tcb_desc->rts_use_shortpreamble ? 1 : 0) - : (tcb_desc->rts_use_shortgi ? 1 : 0))); - - if (bw_40) { - if (tcb_desc->packet_bw) { - SET_TX_DESC_DATA_BW(pdesc, 1); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, - mac->cur_40_prime_sc); - } - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); - } - - SET_TX_DESC_LINIP(pdesc, 0); - SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); - - if (sta) { - u8 ampdu_density = sta->ht_cap.ampdu_density; - SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); - } - - if (info->control.hw_key) { - struct ieee80211_key_conf *keyconf = - info->control.hw_key; - - switch (keyconf->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - case WLAN_CIPHER_SUITE_TKIP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x1); - break; - case WLAN_CIPHER_SUITE_CCMP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x3); - break; - default: - SET_TX_DESC_SEC_TYPE(pdesc, 0x0); - break; - - } - } - - SET_TX_DESC_PKT_ID(pdesc, 0); - SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); - - SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); - SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); - SET_TX_DESC_DISABLE_FB(pdesc, 0); - SET_TX_DESC_USE_RATE(pdesc, tcb_desc->use_driver_rate ? 1 : 0); - - if (ieee80211_is_data_qos(fc)) { - if (mac->rdg_en) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "Enable RDG function\n"); - SET_TX_DESC_RDG_ENABLE(pdesc, 1); - SET_TX_DESC_HTC(pdesc, 1); - } - } - } - rcu_read_unlock(); - - SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); - SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); - - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); - - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(pdesc, tcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, tcb_desc->mac_id); - } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, tcb_desc->ratr_index); - } - - if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - SET_TX_DESC_PKT_ID(pdesc, 8); - - if (!defaultadapter) - SET_TX_DESC_QOS(pdesc, 1); - } - - SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); - - if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || - is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { - SET_TX_DESC_BMC(pdesc, 1); - } - - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); -} - -void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc, bool firstseg, - bool lastseg, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 fw_queue = QSLT_BEACON; - - dma_addr_t mapping = pci_map_single(rtlpci->pdev, - skb->data, skb->len, - PCI_DMA_TODEVICE); - - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - __le16 fc = hdr->frame_control; - - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); - - if (firstseg) - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - - SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M); - - SET_TX_DESC_SEQ(pdesc, 0); - - SET_TX_DESC_LINIP(pdesc, 0); - - SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); - - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len)); - - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - SET_TX_DESC_RATE_ID(pdesc, 7); - SET_TX_DESC_MACID(pdesc, 0); - - SET_TX_DESC_OWN(pdesc, 1); - - SET_TX_DESC_PKT_SIZE(pdesc, (u16) (skb->len)); - - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - SET_TX_DESC_OFFSET(pdesc, 0x20); - - SET_TX_DESC_USE_RATE(pdesc, 1); - - if (!ieee80211_is_data_qos(fc)) { - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - SET_TX_DESC_PKT_ID(pdesc, 8); - } - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C Tx Cmd Content", pdesc, TX_DESC_SIZE); -} - -void rtl92ce_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, - u8 desc_name, u8 *val) -{ - if (istx) { - switch (desc_name) { - case HW_DESC_OWN: - wmb(); - SET_TX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_TX_NEXTDESC_ADDR: - SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); - break; - default: - RT_ASSERT(false, "ERR txdesc :%d not process\n", - desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_RXOWN: - wmb(); - SET_RX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_RXBUFF_ADDR: - SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val); - break; - case HW_DESC_RXPKT_LEN: - SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val); - break; - case HW_DESC_RXERO: - SET_RX_DESC_EOR(pdesc, 1); - break; - default: - RT_ASSERT(false, "ERR rxdesc :%d not process\n", - desc_name); - break; - } - } -} - -u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name) -{ - u32 ret = 0; - - if (istx) { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_TX_DESC_OWN(p_desc); - break; - case HW_DESC_TXBUFF_ADDR: - ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc); - break; - default: - RT_ASSERT(false, "ERR txdesc :%d not process\n", - desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_RX_DESC_OWN(p_desc); - break; - case HW_DESC_RXPKT_LEN: - ret = GET_RX_DESC_PKT_LEN(p_desc); - break; - case HW_DESC_RXBUFF_ADDR: - ret = GET_RX_DESC_BUFF_ADDR(p_desc); - break; - default: - RT_ASSERT(false, "ERR rxdesc :%d not process\n", - desc_name); - break; - } - } - return ret; -} - -bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw, - u8 hw_queue, u16 index) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; - u8 *entry = (u8 *)(&ring->desc[ring->idx]); - u8 own = (u8)rtl92ce_get_desc(entry, true, HW_DESC_OWN); - - /*beacon packet will only use the first - *descriptor defautly,and the own may not - *be cleared by the hardware - */ - if (own) - return false; - return true; -} - -void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (hw_queue == BEACON_QUEUE) { - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); - } else { - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, - BIT(0) << (hw_queue)); - } -} - diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h deleted file mode 100644 index 4bec4b07e3e0..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h +++ /dev/null @@ -1,732 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CE_TRX_H__ -#define __RTL92CE_TRX_H__ - -#define TX_DESC_SIZE 64 -#define TX_DESC_AGGR_SUBFRAME_SIZE 32 - -#define RX_DESC_SIZE 32 -#define RX_DRV_INFO_SIZE_UNIT 8 - -#define TX_DESC_NEXT_DESC_OFFSET 40 -#define USB_HWDESC_HEADER_LEN 32 -#define CRCLENGTH 4 - -/* 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, __mask) \ - ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ - BIT_LEN_MASK_32(__mask)) - -/* 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/write various fields in RX or TX descriptors */ - -#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val) -#define SET_TX_DESC_OFFSET(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val) -#define SET_TX_DESC_BMC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 24, 1, __val) -#define SET_TX_DESC_HTC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 25, 1, __val) -#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) -#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) -#define SET_TX_DESC_LINIP(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) -#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) -#define SET_TX_DESC_GF(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) -#define SET_TX_DESC_OWN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) - -#define GET_TX_DESC_PKT_SIZE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 0, 16) -#define GET_TX_DESC_OFFSET(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 16, 8) -#define GET_TX_DESC_BMC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 24, 1) -#define GET_TX_DESC_HTC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 25, 1) -#define GET_TX_DESC_LAST_SEG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 26, 1) -#define GET_TX_DESC_FIRST_SEG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 27, 1) -#define GET_TX_DESC_LINIP(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 28, 1) -#define GET_TX_DESC_NO_ACM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 29, 1) -#define GET_TX_DESC_GF(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 30, 1) -#define GET_TX_DESC_OWN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 31, 1) - -#define SET_TX_DESC_MACID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 0, 5, __val) -#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 5, 1, __val) -#define SET_TX_DESC_BK(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 6, 1, __val) -#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 7, 1, __val) -#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 8, 5, __val) -#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 13, 1, __val) -#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 14, 1, __val) -#define SET_TX_DESC_PIFS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 15, 1, __val) -#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 16, 4, __val) -#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 20, 1, __val) -#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 21, 1, __val) -#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 22, 2, __val) -#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 24, 8, __val) - -#define GET_TX_DESC_MACID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 0, 5) -#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 5, 1) -#define GET_TX_DESC_AGG_BREAK(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 6, 1) -#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 7, 1) -#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 8, 5) -#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 13, 1) -#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) -#define GET_TX_DESC_PIFS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) -#define GET_TX_DESC_RATE_ID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 16, 4) -#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 20, 1) -#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 21, 1) -#define GET_TX_DESC_SEC_TYPE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 22, 2) -#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 24, 8) - -#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 0, 6, __val) -#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 6, 6, __val) -#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 14, 2, __val) -#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 17, 1, __val) -#define SET_TX_DESC_RAW(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 18, 1, __val) -#define SET_TX_DESC_CCX(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 19, 1, __val) -#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 20, 3, __val) -#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 24, 1, __val) -#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 25, 1, __val) -#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 26, 2, __val) -#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 28, 2, __val) -#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 30, 2, __val) - -#define GET_TX_DESC_RTS_RC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 0, 6) -#define GET_TX_DESC_DATA_RC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 6, 6) -#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 14, 2) -#define GET_TX_DESC_MORE_FRAG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 17, 1) -#define GET_TX_DESC_RAW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 18, 1) -#define GET_TX_DESC_CCX(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 19, 1) -#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 20, 3) -#define GET_TX_DESC_ANTSEL_A(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 24, 1) -#define GET_TX_DESC_ANTSEL_B(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 25, 1) -#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 26, 2) -#define GET_TX_DESC_TX_ANTL(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 28, 2) -#define GET_TX_DESC_TX_ANT_HT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 30, 2) - -#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+12, 0, 8, __val) -#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+12, 8, 8, __val) -#define SET_TX_DESC_SEQ(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+12, 16, 12, __val) -#define SET_TX_DESC_PKT_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+12, 28, 4, __val) - -#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 0, 8) -#define GET_TX_DESC_TAIL_PAGE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 8, 8) -#define GET_TX_DESC_SEQ(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 16, 12) -#define GET_TX_DESC_PKT_ID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 28, 4) - -#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 0, 5, __val) -#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 5, 1, __val) -#define SET_TX_DESC_QOS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 6, 1, __val) -#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 7, 1, __val) -#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 8, 1, __val) -#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 9, 1, __val) -#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 10, 1, __val) -#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 11, 1, __val) -#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 12, 1, __val) -#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 13, 1, __val) -#define SET_TX_DESC_PORT_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 14, 1, __val) -#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 18, 1, __val) -#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 19, 1, __val) -#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 20, 2, __val) -#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 22, 2, __val) -#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 24, 1, __val) -#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 25, 1, __val) -#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 26, 1, __val) -#define SET_TX_DESC_RTS_BW(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 27, 1, __val) -#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 28, 2, __val) -#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 30, 2, __val) - -#define GET_TX_DESC_RTS_RATE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 0, 5) -#define GET_TX_DESC_AP_DCFE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 5, 1) -#define GET_TX_DESC_QOS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 6, 1) -#define GET_TX_DESC_HWSEQ_EN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 7, 1) -#define GET_TX_DESC_USE_RATE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 8, 1) -#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 9, 1) -#define GET_TX_DESC_DISABLE_FB(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 10, 1) -#define GET_TX_DESC_CTS2SELF(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 11, 1) -#define GET_TX_DESC_RTS_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 12, 1) -#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 13, 1) -#define GET_TX_DESC_PORT_ID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 14, 1) -#define GET_TX_DESC_WAIT_DCTS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 18, 1) -#define GET_TX_DESC_CTS2AP_EN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 19, 1) -#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 20, 2) -#define GET_TX_DESC_TX_STBC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 22, 2) -#define GET_TX_DESC_DATA_SHORT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 24, 1) -#define GET_TX_DESC_DATA_BW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 25, 1) -#define GET_TX_DESC_RTS_SHORT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 26, 1) -#define GET_TX_DESC_RTS_BW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 27, 1) -#define GET_TX_DESC_RTS_SC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 28, 2) -#define GET_TX_DESC_RTS_STBC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 30, 2) - -#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val) -#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val) -#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val) -#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 8, 5, __val) -#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 13, 4, __val) -#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 17, 1, __val) -#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 18, 6, __val) -#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 24, 8, __val) - -#define GET_TX_DESC_TX_RATE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 0, 6) -#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 6, 1) -#define GET_TX_DESC_CCX_TAG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 7, 1) -#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 8, 5) -#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 13, 4) -#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 17, 1) -#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 18, 6) -#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 24, 8) - -#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 0, 5, __val) -#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 5, 5, __val) -#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 10, 1, __val) -#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 11, 5, __val) -#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 16, 4, __val) -#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 20, 4, __val) -#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 24, 4, __val) -#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 28, 4, __val) - -#define GET_TX_DESC_TXAGC_A(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 0, 5) -#define GET_TX_DESC_TXAGC_B(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 5, 5) -#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 10, 1) -#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 11, 5) -#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 16, 4) -#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 20, 4) -#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 24, 4) -#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 28, 4) - -#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 0, 16, __val) -#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 16, 4, __val) -#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 20, 4, __val) -#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 24, 4, __val) -#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 28, 4, __val) - -#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 0, 16) -#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 16, 4) -#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 20, 4) -#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 24, 4) -#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 28, 4) - -#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+32, 0, 32, __val) -#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+36, 0, 32, __val) - -#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+32, 0, 32) -#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+36, 0, 32) - -#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+40, 0, 32, __val) -#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+44, 0, 32, __val) - -#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+40, 0, 32) -#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+44, 0, 32) - -#define GET_RX_DESC_PKT_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 0, 14) -#define GET_RX_DESC_CRC32(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 14, 1) -#define GET_RX_DESC_ICV(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 15, 1) -#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 16, 4) -#define GET_RX_DESC_SECURITY(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 20, 3) -#define GET_RX_DESC_QOS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 23, 1) -#define GET_RX_DESC_SHIFT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 24, 2) -#define GET_RX_DESC_PHYST(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 26, 1) -#define GET_RX_DESC_SWDEC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 27, 1) -#define GET_RX_DESC_LS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 28, 1) -#define GET_RX_DESC_FS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 29, 1) -#define GET_RX_DESC_EOR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 30, 1) -#define GET_RX_DESC_OWN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 31, 1) - -#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val) -#define SET_RX_DESC_EOR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) -#define SET_RX_DESC_OWN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) - -#define GET_RX_DESC_MACID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 0, 5) -#define GET_RX_DESC_TID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 5, 4) -#define GET_RX_DESC_HWRSVD(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 9, 5) -#define GET_RX_DESC_PAGGR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) -#define GET_RX_DESC_FAGGR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) -#define GET_RX_DESC_A1_FIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 16, 4) -#define GET_RX_DESC_A2_FIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 20, 4) -#define GET_RX_DESC_PAM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 24, 1) -#define GET_RX_DESC_PWR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 25, 1) -#define GET_RX_DESC_MD(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 26, 1) -#define GET_RX_DESC_MF(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 27, 1) -#define GET_RX_DESC_TYPE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 28, 2) -#define GET_RX_DESC_MC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 30, 1) -#define GET_RX_DESC_BC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 31, 1) -#define GET_RX_DESC_SEQ(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 0, 12) -#define GET_RX_DESC_FRAG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 12, 4) -#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 16, 14) -#define GET_RX_DESC_NEXT_IND(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 30, 1) -#define GET_RX_DESC_RSVD(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 31, 1) - -#define GET_RX_DESC_RXMCS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 0, 6) -#define GET_RX_DESC_RXHT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 6, 1) -#define GET_RX_DESC_SPLCP(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 8, 1) -#define GET_RX_DESC_BW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 9, 1) -#define GET_RX_DESC_HTC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 10, 1) -#define GET_RX_DESC_HWPC_ERR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 14, 1) -#define GET_RX_DESC_HWPC_IND(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 15, 1) -#define GET_RX_DESC_IV0(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 16, 16) - -#define GET_RX_DESC_IV1(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 0, 32) -#define GET_RX_DESC_TSFL(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 0, 32) - -#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 0, 32) -#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 0, 32) - -#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 0, 32, __val) -#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val) - -#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ - memset(__pdesc, 0, min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) - -struct rx_fwinfo_92c { - u8 gain_trsw[4]; - u8 pwdb_all; - u8 cfosho[4]; - u8 cfotail[4]; - char rxevm[2]; - char rxsnr[4]; - u8 pdsnr[2]; - u8 csi_current[2]; - u8 csi_target[2]; - u8 sigevm; - u8 max_ex_pwr; - u8 ex_intf_flag:1; - u8 sgi_en:1; - u8 rxsc:2; - u8 reserve:4; -} __packed; - -struct tx_desc_92c { - u32 pktsize:16; - u32 offset:8; - u32 bmc:1; - u32 htc:1; - u32 lastseg:1; - u32 firstseg:1; - u32 linip:1; - u32 noacm:1; - u32 gf:1; - u32 own:1; - - u32 macid:5; - u32 agg_en:1; - u32 bk:1; - u32 rdg_en:1; - u32 queuesel:5; - u32 rd_nav_ext:1; - u32 lsig_txop_en:1; - u32 pifs:1; - u32 rateid:4; - u32 nav_usehdr:1; - u32 en_descid:1; - u32 sectype:2; - u32 pktoffset:8; - - u32 rts_rc:6; - u32 data_rc:6; - u32 rsvd0:2; - u32 bar_retryht:2; - u32 rsvd1:1; - u32 morefrag:1; - u32 raw:1; - u32 ccx:1; - u32 ampdudensity:3; - u32 rsvd2:1; - u32 ant_sela:1; - u32 ant_selb:1; - u32 txant_cck:2; - u32 txant_l:2; - u32 txant_ht:2; - - u32 nextheadpage:8; - u32 tailpage:8; - u32 seq:12; - u32 pktid:4; - - u32 rtsrate:5; - u32 apdcfe:1; - u32 qos:1; - u32 hwseq_enable:1; - u32 userrate:1; - u32 dis_rtsfb:1; - u32 dis_datafb:1; - u32 cts2self:1; - u32 rts_en:1; - u32 hwrts_en:1; - u32 portid:1; - u32 rsvd3:3; - u32 waitdcts:1; - u32 cts2ap_en:1; - u32 txsc:2; - u32 stbc:2; - u32 txshort:1; - u32 txbw:1; - u32 rtsshort:1; - u32 rtsbw:1; - u32 rtssc:2; - u32 rtsstbc:2; - - u32 txrate:6; - u32 shortgi:1; - u32 ccxt:1; - u32 txrate_fb_lmt:5; - u32 rtsrate_fb_lmt:4; - u32 retrylmt_en:1; - u32 txretrylmt:6; - u32 usb_txaggnum:8; - - u32 txagca:5; - u32 txagcb:5; - u32 usemaxlen:1; - u32 maxaggnum:5; - u32 mcsg1maxlen:4; - u32 mcsg2maxlen:4; - u32 mcsg3maxlen:4; - u32 mcs7sgimaxlen:4; - - u32 txbuffersize:16; - u32 mcsg4maxlen:4; - u32 mcsg5maxlen:4; - u32 mcsg6maxlen:4; - u32 mcsg15sgimaxlen:4; - - u32 txbuffaddr; - u32 txbufferaddr64; - u32 nextdescaddress; - u32 nextdescaddress64; - - u32 reserve_pass_pcie_mm_limit[4]; -} __packed; - -struct rx_desc_92c { - u32 length:14; - u32 crc32:1; - u32 icverror:1; - u32 drv_infosize:4; - u32 security:3; - u32 qos:1; - u32 shift:2; - u32 phystatus:1; - u32 swdec:1; - u32 lastseg:1; - u32 firstseg:1; - u32 eor:1; - u32 own:1; - - u32 macid:5; - u32 tid:4; - u32 hwrsvd:5; - u32 paggr:1; - u32 faggr:1; - u32 a1_fit:4; - u32 a2_fit:4; - u32 pam:1; - u32 pwr:1; - u32 moredata:1; - u32 morefrag:1; - u32 type:2; - u32 mc:1; - u32 bc:1; - - u32 seq:12; - u32 frag:4; - u32 nextpktlen:14; - u32 nextind:1; - u32 rsvd:1; - - u32 rxmcs:6; - u32 rxht:1; - u32 amsdu:1; - u32 splcp:1; - u32 bandwidth:1; - u32 htc:1; - u32 tcpchk_rpt:1; - u32 ipcchk_rpt:1; - u32 tcpchk_valid:1; - u32 hwpcerr:1; - u32 hwpcind:1; - u32 iv0:16; - - u32 iv1; - - u32 tsfl; - - u32 bufferaddress; - u32 bufferaddress64; - -} __packed; - -void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc, - u8 *pbd_desc_tx, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, u8 hw_queue, - struct rtl_tcb_desc *ptcb_desc); -bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *stats, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb); -void rtl92ce_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, - u8 desc_name, u8 *val); -u32 rtl92ce_get_desc(u8 *pdesc, bool istx, u8 desc_name); -bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw, - u8 hw_queue, u16 index); -void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); -void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool b_firstseg, bool b_lastseg, - struct sk_buff *skb); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile b/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile deleted file mode 100644 index ad2de6b839ef..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -rtl8192cu-objs := \ - dm.o \ - hw.o \ - led.o \ - mac.o \ - phy.o \ - rf.o \ - sw.o \ - table.o \ - trx.o - -obj-$(CONFIG_RTL8192CU) += rtl8192cu.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/def.h b/drivers/net/wireless/rtlwifi/rtl8192cu/def.h deleted file mode 100644 index 74a479ac323d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/def.h +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../rtl8192ce/def.h" - -/*------------------------------------------------------------------------- - * Chip specific - *-------------------------------------------------------------------------*/ -#define NORMAL_CHIP BIT(4) -#define CHIP_VENDOR_UMC BIT(5) -#define CHIP_VENDOR_UMC_B_CUT BIT(6) - -#define IS_92C_1T2R(version) \ - (((version) & CHIP_92C) && ((version) & CHIP_92C_1T2R)) - -#define IS_VENDOR_UMC(version) \ - (((version) & CHIP_VENDOR_UMC) ? true : false) - -#define CHIP_BONDING_92C_1T2R 0x1 -#define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3) diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c deleted file mode 100644 index c16209a336ea..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c +++ /dev/null @@ -1,116 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../base.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" - -void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long undec_sm_pwdb; - - if (!rtlpriv->dm.dynamic_txpower_enable) - return; - - if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - - if ((mac->link_state < MAC80211_LINKED) && - (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "Not connected to any\n"); - - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - - rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - - if (mac->link_state >= MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Client PWDB = 0x%lx\n", - undec_sm_pwdb); - } else { - undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "STA Default Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - } else { - undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Ext Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - - if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); - } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && - (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) { - - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); - } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_NORMAL\n"); - } - - if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "PHY_SetTxPowerLevel8192S() Channel = %d\n", - rtlphy->current_channel); - rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel); - if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_NORMAL) - dm_restorepowerindex(hw); - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_LEVEL1) - dm_writepowerindex(hw, 0x14); - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_LEVEL2) - dm_writepowerindex(hw, 0x10); - } - - rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h deleted file mode 100644 index fafa6bac2a3f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h +++ /dev/null @@ -1,35 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../rtl8192ce/dm.h" - -void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw); -void dm_savepowerindex(struct ieee80211_hw *hw); -void dm_writepowerindex(struct ieee80211_hw *hw, u8 value); -void dm_restorepowerindex(struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c deleted file mode 100644 index 25db369b5d18..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ /dev/null @@ -1,2323 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../efuse.h" -#include "../base.h" -#include "../cam.h" -#include "../ps.h" -#include "../usb.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "../rtl8192c/phy_common.h" -#include "mac.h" -#include "dm.h" -#include "../rtl8192c/dm_common.h" -#include "../rtl8192c/fw_common.h" -#include "hw.h" -#include "../rtl8192ce/hw.h" -#include "trx.h" -#include "led.h" -#include "table.h" - -static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); - - rtlphy->hwparam_tables[MAC_REG].length = RTL8192CUMAC_2T_ARRAYLENGTH; - rtlphy->hwparam_tables[MAC_REG].pdata = RTL8192CUMAC_2T_ARRAY; - if (IS_HIGHT_PA(rtlefuse->board_type)) { - rtlphy->hwparam_tables[PHY_REG_PG].length = - RTL8192CUPHY_REG_Array_PG_HPLength; - rtlphy->hwparam_tables[PHY_REG_PG].pdata = - RTL8192CUPHY_REG_Array_PG_HP; - } else { - rtlphy->hwparam_tables[PHY_REG_PG].length = - RTL8192CUPHY_REG_ARRAY_PGLENGTH; - rtlphy->hwparam_tables[PHY_REG_PG].pdata = - RTL8192CUPHY_REG_ARRAY_PG; - } - /* 2T */ - rtlphy->hwparam_tables[PHY_REG_2T].length = - RTL8192CUPHY_REG_2TARRAY_LENGTH; - rtlphy->hwparam_tables[PHY_REG_2T].pdata = - RTL8192CUPHY_REG_2TARRAY; - rtlphy->hwparam_tables[RADIOA_2T].length = - RTL8192CURADIOA_2TARRAYLENGTH; - rtlphy->hwparam_tables[RADIOA_2T].pdata = - RTL8192CURADIOA_2TARRAY; - rtlphy->hwparam_tables[RADIOB_2T].length = - RTL8192CURADIOB_2TARRAYLENGTH; - rtlphy->hwparam_tables[RADIOB_2T].pdata = - RTL8192CU_RADIOB_2TARRAY; - rtlphy->hwparam_tables[AGCTAB_2T].length = - RTL8192CUAGCTAB_2TARRAYLENGTH; - rtlphy->hwparam_tables[AGCTAB_2T].pdata = - RTL8192CUAGCTAB_2TARRAY; - /* 1T */ - if (IS_HIGHT_PA(rtlefuse->board_type)) { - rtlphy->hwparam_tables[PHY_REG_1T].length = - RTL8192CUPHY_REG_1T_HPArrayLength; - rtlphy->hwparam_tables[PHY_REG_1T].pdata = - RTL8192CUPHY_REG_1T_HPArray; - rtlphy->hwparam_tables[RADIOA_1T].length = - RTL8192CURadioA_1T_HPArrayLength; - rtlphy->hwparam_tables[RADIOA_1T].pdata = - RTL8192CURadioA_1T_HPArray; - rtlphy->hwparam_tables[RADIOB_1T].length = - RTL8192CURADIOB_1TARRAYLENGTH; - rtlphy->hwparam_tables[RADIOB_1T].pdata = - RTL8192CU_RADIOB_1TARRAY; - rtlphy->hwparam_tables[AGCTAB_1T].length = - RTL8192CUAGCTAB_1T_HPArrayLength; - rtlphy->hwparam_tables[AGCTAB_1T].pdata = - Rtl8192CUAGCTAB_1T_HPArray; - } else { - rtlphy->hwparam_tables[PHY_REG_1T].length = - RTL8192CUPHY_REG_1TARRAY_LENGTH; - rtlphy->hwparam_tables[PHY_REG_1T].pdata = - RTL8192CUPHY_REG_1TARRAY; - rtlphy->hwparam_tables[RADIOA_1T].length = - RTL8192CURADIOA_1TARRAYLENGTH; - rtlphy->hwparam_tables[RADIOA_1T].pdata = - RTL8192CU_RADIOA_1TARRAY; - rtlphy->hwparam_tables[RADIOB_1T].length = - RTL8192CURADIOB_1TARRAYLENGTH; - rtlphy->hwparam_tables[RADIOB_1T].pdata = - RTL8192CU_RADIOB_1TARRAY; - rtlphy->hwparam_tables[AGCTAB_1T].length = - RTL8192CUAGCTAB_1TARRAYLENGTH; - rtlphy->hwparam_tables[AGCTAB_1T].pdata = - RTL8192CUAGCTAB_1TARRAY; - } -} - -static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 rf_path, index, tempval; - u16 i; - - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < 3; i++) { - if (!autoload_fail) { - rtlefuse-> - eeprom_chnlarea_txpwr_cck[rf_path][i] = - hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i]; - rtlefuse-> - eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = - hwinfo[EEPROM_TXPOWERHT40_1S + rf_path * 3 + - i]; - } else { - rtlefuse-> - eeprom_chnlarea_txpwr_cck[rf_path][i] = - EEPROM_DEFAULT_TXPOWERLEVEL; - rtlefuse-> - eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = - EEPROM_DEFAULT_TXPOWERLEVEL; - } - } - } - for (i = 0; i < 3; i++) { - if (!autoload_fail) - tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i]; - else - tempval = EEPROM_DEFAULT_HT40_2SDIFF; - rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] = - (tempval & 0xf); - rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] = - ((tempval & 0xf0) >> 4); - } - for (rf_path = 0; rf_path < 2; rf_path++) - for (i = 0; i < 3; i++) - RTPRINT(rtlpriv, FINIT, INIT_EEPROM, - "RF(%d) EEPROM CCK Area(%d) = 0x%x\n", - rf_path, i, - rtlefuse-> - eeprom_chnlarea_txpwr_cck[rf_path][i]); - for (rf_path = 0; rf_path < 2; rf_path++) - for (i = 0; i < 3; i++) - RTPRINT(rtlpriv, FINIT, INIT_EEPROM, - "RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n", - rf_path, i, - rtlefuse-> - eeprom_chnlarea_txpwr_ht40_1s[rf_path][i]); - for (rf_path = 0; rf_path < 2; rf_path++) - for (i = 0; i < 3; i++) - RTPRINT(rtlpriv, FINIT, INIT_EEPROM, - "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", - rf_path, i, - rtlefuse-> - eprom_chnl_txpwr_ht40_2sdf[rf_path][i]); - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < 14; i++) { - index = rtl92c_get_chnl_group((u8)i); - rtlefuse->txpwrlevel_cck[rf_path][i] = - rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][index]; - rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = - rtlefuse-> - eeprom_chnlarea_txpwr_ht40_1s[rf_path][index]; - if ((rtlefuse-> - eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] - - rtlefuse-> - eprom_chnl_txpwr_ht40_2sdf[rf_path][index]) - > 0) { - rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = - rtlefuse-> - eeprom_chnlarea_txpwr_ht40_1s[rf_path] - [index] - rtlefuse-> - eprom_chnl_txpwr_ht40_2sdf[rf_path] - [index]; - } else { - rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0; - } - } - for (i = 0; i < 14; i++) { - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", rf_path, i, - rtlefuse->txpwrlevel_cck[rf_path][i], - rtlefuse->txpwrlevel_ht40_1s[rf_path][i], - rtlefuse->txpwrlevel_ht40_2s[rf_path][i]); - } - } - for (i = 0; i < 3; i++) { - if (!autoload_fail) { - rtlefuse->eeprom_pwrlimit_ht40[i] = - hwinfo[EEPROM_TXPWR_GROUP + i]; - rtlefuse->eeprom_pwrlimit_ht20[i] = - hwinfo[EEPROM_TXPWR_GROUP + 3 + i]; - } else { - rtlefuse->eeprom_pwrlimit_ht40[i] = 0; - rtlefuse->eeprom_pwrlimit_ht20[i] = 0; - } - } - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < 14; i++) { - index = rtl92c_get_chnl_group((u8)i); - if (rf_path == RF90_PATH_A) { - rtlefuse->pwrgroup_ht20[rf_path][i] = - (rtlefuse->eeprom_pwrlimit_ht20[index] - & 0xf); - rtlefuse->pwrgroup_ht40[rf_path][i] = - (rtlefuse->eeprom_pwrlimit_ht40[index] - & 0xf); - } else if (rf_path == RF90_PATH_B) { - rtlefuse->pwrgroup_ht20[rf_path][i] = - ((rtlefuse->eeprom_pwrlimit_ht20[index] - & 0xf0) >> 4); - rtlefuse->pwrgroup_ht40[rf_path][i] = - ((rtlefuse->eeprom_pwrlimit_ht40[index] - & 0xf0) >> 4); - } - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-%d pwrgroup_ht20[%d] = 0x%x\n", - rf_path, i, - rtlefuse->pwrgroup_ht20[rf_path][i]); - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-%d pwrgroup_ht40[%d] = 0x%x\n", - rf_path, i, - rtlefuse->pwrgroup_ht40[rf_path][i]); - } - } - for (i = 0; i < 14; i++) { - index = rtl92c_get_chnl_group((u8)i); - if (!autoload_fail) - tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index]; - else - tempval = EEPROM_DEFAULT_HT20_DIFF; - rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); - rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = - ((tempval >> 4) & 0xF); - if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] & BIT(3)) - rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] |= 0xF0; - if (rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] & BIT(3)) - rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] |= 0xF0; - index = rtl92c_get_chnl_group((u8)i); - if (!autoload_fail) - tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index]; - else - tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = (tempval & 0xF); - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = - ((tempval >> 4) & 0xF); - } - rtlefuse->legacy_ht_txpowerdiff = - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", - i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", - i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", - i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", - i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); - if (!autoload_fail) - rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); - else - rtlefuse->eeprom_regulatory = 0; - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); - if (!autoload_fail) { - rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; - rtlefuse->eeprom_tssi[RF90_PATH_B] = hwinfo[EEPROM_TSSI_B]; - } else { - rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; - rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; - } - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "TSSI_A = 0x%x, TSSI_B = 0x%x\n", - rtlefuse->eeprom_tssi[RF90_PATH_A], - rtlefuse->eeprom_tssi[RF90_PATH_B]); - if (!autoload_fail) - tempval = hwinfo[EEPROM_THERMAL_METER]; - else - tempval = EEPROM_DEFAULT_THERMALMETER; - rtlefuse->eeprom_thermalmeter = (tempval & 0x1f); - if (rtlefuse->eeprom_thermalmeter < 0x06 || - rtlefuse->eeprom_thermalmeter > 0x1c) - rtlefuse->eeprom_thermalmeter = 0x12; - if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail) - rtlefuse->apk_thermalmeterignore = true; - rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); -} - -static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 boardType; - - if (IS_NORMAL_CHIP(rtlhal->version)) { - boardType = ((contents[EEPROM_RF_OPT1]) & - BOARD_TYPE_NORMAL_MASK) >> 5; /*bit[7:5]*/ - } else { - boardType = contents[EEPROM_RF_OPT4]; - boardType &= BOARD_TYPE_TEST_MASK; - } - rtlefuse->board_type = boardType; - if (IS_HIGHT_PA(rtlefuse->board_type)) - rtlefuse->external_pa = 1; - pr_info("Board Type %x\n", rtlefuse->board_type); -} - -static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u16 i, usvalue; - u8 hwinfo[HWSET_MAX_SIZE] = {0}; - u16 eeprom_id; - - if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { - rtl_efuse_shadow_map_update(hw); - memcpy((void *)hwinfo, - (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], - HWSET_MAX_SIZE); - } else if (rtlefuse->epromtype == EEPROM_93C46) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "RTL819X Not boot from eeprom, check it !!\n"); - } - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, "MAP", - hwinfo, HWSET_MAX_SIZE); - eeprom_id = le16_to_cpu(*((__le16 *)&hwinfo[0])); - if (eeprom_id != RTL8190_EEPROM_ID) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "EEPROM ID(%#x) is invalid!!\n", eeprom_id); - rtlefuse->autoload_failflag = true; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - } - if (rtlefuse->autoload_failflag) - return; - for (i = 0; i < 6; i += 2) { - usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; - *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; - } - pr_info("MAC address: %pM\n", rtlefuse->dev_addr); - _rtl92cu_read_txpower_info_from_hwpg(hw, - rtlefuse->autoload_failflag, hwinfo); - rtlefuse->eeprom_vid = le16_to_cpu(*(__le16 *)&hwinfo[EEPROM_VID]); - rtlefuse->eeprom_did = le16_to_cpu(*(__le16 *)&hwinfo[EEPROM_DID]); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, " VID = 0x%02x PID = 0x%02x\n", - rtlefuse->eeprom_vid, rtlefuse->eeprom_did); - rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; - rtlefuse->eeprom_version = - le16_to_cpu(*(__le16 *)&hwinfo[EEPROM_VERSION]); - rtlefuse->txpwr_fromeprom = true; - rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM Customer ID: 0x%2x\n", - rtlefuse->eeprom_oemid); - if (rtlhal->oem_id == RT_CID_DEFAULT) { - switch (rtlefuse->eeprom_oemid) { - case EEPROM_CID_DEFAULT: - if (rtlefuse->eeprom_did == 0x8176) { - if ((rtlefuse->eeprom_svid == 0x103C && - rtlefuse->eeprom_smid == 0x1629)) - rtlhal->oem_id = RT_CID_819X_HP; - else - rtlhal->oem_id = RT_CID_DEFAULT; - } else { - rtlhal->oem_id = RT_CID_DEFAULT; - } - break; - case EEPROM_CID_TOSHIBA: - rtlhal->oem_id = RT_CID_TOSHIBA; - break; - case EEPROM_CID_QMI: - rtlhal->oem_id = RT_CID_819X_QMI; - break; - case EEPROM_CID_WHQL: - default: - rtlhal->oem_id = RT_CID_DEFAULT; - break; - } - } - _rtl92cu_read_board_type(hw, hwinfo); -} - -static void _rtl92cu_hal_customized_behavior(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - switch (rtlhal->oem_id) { - case RT_CID_819X_HP: - usb_priv->ledctl.led_opendrain = true; - break; - case RT_CID_819X_LENOVO: - case RT_CID_DEFAULT: - case RT_CID_TOSHIBA: - case RT_CID_CCX: - case RT_CID_819X_ACER: - case RT_CID_WHQL: - default: - break; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "RT Customized ID: 0x%02X\n", - rtlhal->oem_id); -} - -void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw) -{ - - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_u1b; - - if (!IS_NORMAL_CHIP(rtlhal->version)) - return; - tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); - rtlefuse->epromtype = (tmp_u1b & BOOT_FROM_EEPROM) ? - EEPROM_93C46 : EEPROM_BOOT_EFUSE; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from %s\n", - tmp_u1b & BOOT_FROM_EEPROM ? "EERROM" : "EFUSE"); - rtlefuse->autoload_failflag = (tmp_u1b & EEPROM_EN) ? false : true; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload %s\n", - tmp_u1b & EEPROM_EN ? "OK!!" : "ERR!!"); - _rtl92cu_read_adapter_info(hw); - _rtl92cu_hal_customized_behavior(hw); - return; -} - -static int _rtl92cu_init_power_on(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int status = 0; - u16 value16; - u8 value8; - /* polling autoload done. */ - u32 pollingCount = 0; - - do { - if (rtl_read_byte(rtlpriv, REG_APS_FSMCO) & PFM_ALDN) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Autoload Done!\n"); - break; - } - if (pollingCount++ > 100) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, - "Failed to polling REG_APS_FSMCO[PFM_ALDN] done!\n"); - return -ENODEV; - } - } while (true); - /* 0. RSV_CTRL 0x1C[7:0] = 0 unlock ISO/CLK/Power control register */ - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0); - /* Power on when re-enter from IPS/Radio off/card disable */ - /* enable SPS into PWM mode */ - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); - udelay(100); - value8 = rtl_read_byte(rtlpriv, REG_LDOV12D_CTRL); - if (0 == (value8 & LDV12_EN)) { - value8 |= LDV12_EN; - rtl_write_byte(rtlpriv, REG_LDOV12D_CTRL, value8); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - " power-on :REG_LDOV12D_CTRL Reg0x21:0x%02x\n", - value8); - udelay(100); - value8 = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL); - value8 &= ~ISO_MD2PP; - rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, value8); - } - /* auto enable WLAN */ - pollingCount = 0; - value16 = rtl_read_word(rtlpriv, REG_APS_FSMCO); - value16 |= APFM_ONMAC; - rtl_write_word(rtlpriv, REG_APS_FSMCO, value16); - do { - if (!(rtl_read_word(rtlpriv, REG_APS_FSMCO) & APFM_ONMAC)) { - pr_info("MAC auto ON okay!\n"); - break; - } - if (pollingCount++ > 1000) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, - "Failed to polling REG_APS_FSMCO[APFM_ONMAC] done!\n"); - return -ENODEV; - } - } while (true); - /* Enable Radio ,GPIO ,and LED function */ - rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x0812); - /* release RF digital isolation */ - value16 = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL); - value16 &= ~ISO_DIOR; - rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, value16); - /* Reconsider when to do this operation after asking HWSD. */ - pollingCount = 0; - rtl_write_byte(rtlpriv, REG_APSD_CTRL, (rtl_read_byte(rtlpriv, - REG_APSD_CTRL) & ~BIT(6))); - do { - pollingCount++; - } while ((pollingCount < 200) && - (rtl_read_byte(rtlpriv, REG_APSD_CTRL) & BIT(7))); - /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */ - value16 = rtl_read_word(rtlpriv, REG_CR); - value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN | - PROTOCOL_EN | SCHEDULE_EN | MACTXEN | MACRXEN | ENSEC); - rtl_write_word(rtlpriv, REG_CR, value16); - return status; -} - -static void _rtl92cu_init_queue_reserved_page(struct ieee80211_hw *hw, - bool wmm_enable, - u8 out_ep_num, - u8 queue_sel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool isChipN = IS_NORMAL_CHIP(rtlhal->version); - u32 outEPNum = (u32)out_ep_num; - u32 numHQ = 0; - u32 numLQ = 0; - u32 numNQ = 0; - u32 numPubQ; - u32 value32; - u8 value8; - u32 txQPageNum, txQPageUnit, txQRemainPage; - - if (!wmm_enable) { - numPubQ = (isChipN) ? CHIP_B_PAGE_NUM_PUBQ : - CHIP_A_PAGE_NUM_PUBQ; - txQPageNum = TX_TOTAL_PAGE_NUMBER - numPubQ; - - txQPageUnit = txQPageNum/outEPNum; - txQRemainPage = txQPageNum % outEPNum; - if (queue_sel & TX_SELE_HQ) - numHQ = txQPageUnit; - if (queue_sel & TX_SELE_LQ) - numLQ = txQPageUnit; - /* HIGH priority queue always present in the configuration of - * 2 out-ep. Remainder pages have assigned to High queue */ - if ((outEPNum > 1) && (txQRemainPage)) - numHQ += txQRemainPage; - /* NOTE: This step done before writting REG_RQPN. */ - if (isChipN) { - if (queue_sel & TX_SELE_NQ) - numNQ = txQPageUnit; - value8 = (u8)_NPQ(numNQ); - rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8); - } - } else { - /* for WMM ,number of out-ep must more than or equal to 2! */ - numPubQ = isChipN ? WMM_CHIP_B_PAGE_NUM_PUBQ : - WMM_CHIP_A_PAGE_NUM_PUBQ; - if (queue_sel & TX_SELE_HQ) { - numHQ = isChipN ? WMM_CHIP_B_PAGE_NUM_HPQ : - WMM_CHIP_A_PAGE_NUM_HPQ; - } - if (queue_sel & TX_SELE_LQ) { - numLQ = isChipN ? WMM_CHIP_B_PAGE_NUM_LPQ : - WMM_CHIP_A_PAGE_NUM_LPQ; - } - /* NOTE: This step done before writting REG_RQPN. */ - if (isChipN) { - if (queue_sel & TX_SELE_NQ) - numNQ = WMM_CHIP_B_PAGE_NUM_NPQ; - value8 = (u8)_NPQ(numNQ); - rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8); - } - } - /* TX DMA */ - value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN; - rtl_write_dword(rtlpriv, REG_RQPN, value32); -} - -static void _rtl92c_init_trx_buffer(struct ieee80211_hw *hw, bool wmm_enable) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 txpktbuf_bndy; - u8 value8; - - if (!wmm_enable) - txpktbuf_bndy = TX_PAGE_BOUNDARY; - else /* for WMM */ - txpktbuf_bndy = (IS_NORMAL_CHIP(rtlhal->version)) - ? WMM_CHIP_B_TX_PAGE_BOUNDARY - : WMM_CHIP_A_TX_PAGE_BOUNDARY; - rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_TRXFF_BNDY, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_TDECTRL+1, txpktbuf_bndy); - rtl_write_word(rtlpriv, (REG_TRXFF_BNDY + 2), 0x27FF); - value8 = _PSRX(RX_PAGE_SIZE_REG_VALUE) | _PSTX(PBP_128); - rtl_write_byte(rtlpriv, REG_PBP, value8); -} - -static void _rtl92c_init_chipN_reg_priority(struct ieee80211_hw *hw, u16 beQ, - u16 bkQ, u16 viQ, u16 voQ, - u16 mgtQ, u16 hiQ) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 value16 = (rtl_read_word(rtlpriv, REG_TRXDMA_CTRL) & 0x7); - - value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) | - _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) | - _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ); - rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, value16); -} - -static void _rtl92cu_init_chipN_one_out_ep_priority(struct ieee80211_hw *hw, - bool wmm_enable, - u8 queue_sel) -{ - u16 uninitialized_var(value); - - switch (queue_sel) { - case TX_SELE_HQ: - value = QUEUE_HIGH; - break; - case TX_SELE_LQ: - value = QUEUE_LOW; - break; - case TX_SELE_NQ: - value = QUEUE_NORMAL; - break; - default: - WARN_ON(1); /* Shall not reach here! */ - break; - } - _rtl92c_init_chipN_reg_priority(hw, value, value, value, value, - value, value); - pr_info("Tx queue select: 0x%02x\n", queue_sel); -} - -static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw, - bool wmm_enable, - u8 queue_sel) -{ - u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; - u16 uninitialized_var(valueHi); - u16 uninitialized_var(valueLow); - - switch (queue_sel) { - case (TX_SELE_HQ | TX_SELE_LQ): - valueHi = QUEUE_HIGH; - valueLow = QUEUE_LOW; - break; - case (TX_SELE_NQ | TX_SELE_LQ): - valueHi = QUEUE_NORMAL; - valueLow = QUEUE_LOW; - break; - case (TX_SELE_HQ | TX_SELE_NQ): - valueHi = QUEUE_HIGH; - valueLow = QUEUE_NORMAL; - break; - default: - WARN_ON(1); - break; - } - if (!wmm_enable) { - beQ = valueLow; - bkQ = valueLow; - viQ = valueHi; - voQ = valueHi; - mgtQ = valueHi; - hiQ = valueHi; - } else {/* for WMM ,CONFIG_OUT_EP_WIFI_MODE */ - beQ = valueHi; - bkQ = valueLow; - viQ = valueLow; - voQ = valueHi; - mgtQ = valueHi; - hiQ = valueHi; - } - _rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ); - pr_info("Tx queue select: 0x%02x\n", queue_sel); -} - -static void _rtl92cu_init_chipN_three_out_ep_priority(struct ieee80211_hw *hw, - bool wmm_enable, - u8 queue_sel) -{ - u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (!wmm_enable) { /* typical setting */ - beQ = QUEUE_LOW; - bkQ = QUEUE_LOW; - viQ = QUEUE_NORMAL; - voQ = QUEUE_HIGH; - mgtQ = QUEUE_HIGH; - hiQ = QUEUE_HIGH; - } else { /* for WMM */ - beQ = QUEUE_LOW; - bkQ = QUEUE_NORMAL; - viQ = QUEUE_NORMAL; - voQ = QUEUE_HIGH; - mgtQ = QUEUE_HIGH; - hiQ = QUEUE_HIGH; - } - _rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ); - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Tx queue select :0x%02x..\n", - queue_sel); -} - -static void _rtl92cu_init_chipN_queue_priority(struct ieee80211_hw *hw, - bool wmm_enable, - u8 out_ep_num, - u8 queue_sel) -{ - switch (out_ep_num) { - case 1: - _rtl92cu_init_chipN_one_out_ep_priority(hw, wmm_enable, - queue_sel); - break; - case 2: - _rtl92cu_init_chipN_two_out_ep_priority(hw, wmm_enable, - queue_sel); - break; - case 3: - _rtl92cu_init_chipN_three_out_ep_priority(hw, wmm_enable, - queue_sel); - break; - default: - WARN_ON(1); /* Shall not reach here! */ - break; - } -} - -static void _rtl92cu_init_chipT_queue_priority(struct ieee80211_hw *hw, - bool wmm_enable, - u8 out_ep_num, - u8 queue_sel) -{ - u8 hq_sele = 0; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - switch (out_ep_num) { - case 2: /* (TX_SELE_HQ|TX_SELE_LQ) */ - if (!wmm_enable) /* typical setting */ - hq_sele = HQSEL_VOQ | HQSEL_VIQ | HQSEL_MGTQ | - HQSEL_HIQ; - else /* for WMM */ - hq_sele = HQSEL_VOQ | HQSEL_BEQ | HQSEL_MGTQ | - HQSEL_HIQ; - break; - case 1: - if (TX_SELE_LQ == queue_sel) { - /* map all endpoint to Low queue */ - hq_sele = 0; - } else if (TX_SELE_HQ == queue_sel) { - /* map all endpoint to High queue */ - hq_sele = HQSEL_VOQ | HQSEL_VIQ | HQSEL_BEQ | - HQSEL_BKQ | HQSEL_MGTQ | HQSEL_HIQ; - } - break; - default: - WARN_ON(1); /* Shall not reach here! */ - break; - } - rtl_write_byte(rtlpriv, (REG_TRXDMA_CTRL+1), hq_sele); - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Tx queue select :0x%02x..\n", - hq_sele); -} - -static void _rtl92cu_init_queue_priority(struct ieee80211_hw *hw, - bool wmm_enable, - u8 out_ep_num, - u8 queue_sel) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - if (IS_NORMAL_CHIP(rtlhal->version)) - _rtl92cu_init_chipN_queue_priority(hw, wmm_enable, out_ep_num, - queue_sel); - else - _rtl92cu_init_chipT_queue_priority(hw, wmm_enable, out_ep_num, - queue_sel); -} - -static void _rtl92cu_init_usb_aggregation(struct ieee80211_hw *hw) -{ -} - -static void _rtl92cu_init_wmac_setting(struct ieee80211_hw *hw) -{ - u16 value16; - u32 value32; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - value32 = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APPFCS | - RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL | - RCR_APP_MIC | RCR_APP_PHYSTS | RCR_ACRC32); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&value32)); - /* Accept all multicast address */ - rtl_write_dword(rtlpriv, REG_MAR, 0xFFFFFFFF); - rtl_write_dword(rtlpriv, REG_MAR + 4, 0xFFFFFFFF); - /* Accept all management frames */ - value16 = 0xFFFF; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MGT_FILTER, - (u8 *)(&value16)); - /* Reject all control frame - default value is 0 */ - value16 = 0x0; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CTRL_FILTER, - (u8 *)(&value16)); - /* Accept all data frames */ - value16 = 0xFFFF; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_DATA_FILTER, - (u8 *)(&value16)); -} - -static void _rtl92cu_init_beacon_parameters(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - - rtl_write_word(rtlpriv, REG_BCN_CTRL, 0x1010); - - /* TODO: Remove these magic number */ - rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404); - rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME); - rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); - /* Change beacon AIFS to the largest number - * beacause test chip does not contension before sending beacon. - */ - if (IS_NORMAL_CHIP(rtlhal->version)) - rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F); - else - rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF); -} - -static int _rtl92cu_init_mac(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); - int err = 0; - u32 boundary = 0; - u8 wmm_enable = false; /* TODO */ - u8 out_ep_nums = rtlusb->out_ep_nums; - u8 queue_sel = rtlusb->out_queue_sel; - err = _rtl92cu_init_power_on(hw); - - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to init power on!\n"); - return err; - } - if (!wmm_enable) { - boundary = TX_PAGE_BOUNDARY; - } else { /* for WMM */ - boundary = (IS_NORMAL_CHIP(rtlhal->version)) - ? WMM_CHIP_B_TX_PAGE_BOUNDARY - : WMM_CHIP_A_TX_PAGE_BOUNDARY; - } - if (false == rtl92c_init_llt_table(hw, boundary)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to init LLT Table!\n"); - return -EINVAL; - } - _rtl92cu_init_queue_reserved_page(hw, wmm_enable, out_ep_nums, - queue_sel); - _rtl92c_init_trx_buffer(hw, wmm_enable); - _rtl92cu_init_queue_priority(hw, wmm_enable, out_ep_nums, - queue_sel); - /* Get Rx PHY status in order to report RSSI and others. */ - rtl92c_init_driver_info_size(hw, RTL92C_DRIVER_INFO_SIZE); - rtl92c_init_interrupt(hw); - rtl92c_init_network_type(hw); - _rtl92cu_init_wmac_setting(hw); - rtl92c_init_adaptive_ctrl(hw); - rtl92c_init_edca(hw); - rtl92c_init_rate_fallback(hw); - rtl92c_init_retry_function(hw); - _rtl92cu_init_usb_aggregation(hw); - rtlpriv->cfg->ops->set_bw_mode(hw, NL80211_CHAN_HT20); - rtl92c_set_min_space(hw, IS_92C_SERIAL(rtlhal->version)); - _rtl92cu_init_beacon_parameters(hw); - rtl92c_init_ampdu_aggregation(hw); - rtl92c_init_beacon_max_error(hw); - return err; -} - -void rtl92cu_enable_hw_security_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 sec_reg_value = 0x0; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", - rtlpriv->sec.pairwise_enc_algorithm, - rtlpriv->sec.group_enc_algorithm); - if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "not open sw encryption\n"); - return; - } - sec_reg_value = SCR_TxEncEnable | SCR_RxDecEnable; - if (rtlpriv->sec.use_defaultkey) { - sec_reg_value |= SCR_TxUseDK; - sec_reg_value |= SCR_RxUseDK; - } - if (IS_NORMAL_CHIP(rtlhal->version)) - sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); - rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "The SECR-value %x\n", - sec_reg_value); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); -} - -static void _rtl92cu_hw_configure(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - - /* To Fix MAC loopback mode fail. */ - rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f); - rtl_write_byte(rtlpriv, 0x15, 0xe9); - /* HW SEQ CTRL */ - /* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */ - rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); - /* fixed USB interface interference issue */ - rtl_write_byte(rtlpriv, 0xfe40, 0xe0); - rtl_write_byte(rtlpriv, 0xfe41, 0x8d); - rtl_write_byte(rtlpriv, 0xfe42, 0x80); - rtlusb->reg_bcn_ctrl_val = 0x18; - rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlusb->reg_bcn_ctrl_val); -} - -static void _InitPABias(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 pa_setting; - - /* FIXED PA current issue */ - pa_setting = efuse_read_1byte(hw, 0x1FA); - if (!(pa_setting & BIT(0))) { - rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0x0F406); - rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0x4F406); - rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0x8F406); - rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0xCF406); - } - if (!(pa_setting & BIT(1)) && IS_NORMAL_CHIP(rtlhal->version) && - IS_92C_SERIAL(rtlhal->version)) { - rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0x0F406); - rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0x4F406); - rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0x8F406); - rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0xCF406); - } - if (!(pa_setting & BIT(4))) { - pa_setting = rtl_read_byte(rtlpriv, 0x16); - pa_setting &= 0x0F; - rtl_write_byte(rtlpriv, 0x16, pa_setting | 0x90); - } -} - -int rtl92cu_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - int err = 0; - unsigned long flags; - - /* As this function can take a very long time (up to 350 ms) - * and can be called with irqs disabled, reenable the irqs - * to let the other devices continue being serviced. - * - * It is safe doing so since our own interrupts will only be enabled - * in a subsequent step. - */ - local_save_flags(flags); - local_irq_enable(); - - rtlhal->fw_ready = false; - rtlhal->hw_type = HARDWARE_TYPE_RTL8192CU; - err = _rtl92cu_init_mac(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "init mac failed!\n"); - goto exit; - } - err = rtl92c_download_fw(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Failed to download FW. Init HW without FW now..\n"); - err = 1; - goto exit; - } - - rtlhal->fw_ready = true; - rtlhal->last_hmeboxnum = 0; /* h2c */ - _rtl92cu_phy_param_tab_init(hw); - rtl92cu_phy_mac_config(hw); - rtl92cu_phy_bb_config(hw); - rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; - rtl92c_phy_rf_config(hw); - if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && - !IS_92C_SERIAL(rtlhal->version)) { - rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00); - } - rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtl92cu_bb_block_on(hw); - rtl_cam_reset_all_entry(hw); - rtl92cu_enable_hw_security_config(hw); - ppsc->rfpwr_state = ERFON; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); - if (ppsc->rfpwr_state == ERFON) { - rtl92c_phy_set_rfpath_switch(hw, 1); - if (rtlphy->iqk_initialized) { - rtl92c_phy_iq_calibrate(hw, true); - } else { - rtl92c_phy_iq_calibrate(hw, false); - rtlphy->iqk_initialized = true; - } - rtl92c_dm_check_txpower_tracking(hw); - rtl92c_phy_lc_calibrate(hw); - } - _rtl92cu_hw_configure(hw); - _InitPABias(hw); - rtl92c_dm_init(hw); -exit: - local_irq_restore(flags); - return err; -} - -static void _DisableRFAFEAndResetBB(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); -/************************************** -a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue -b. RF path 0 offset 0x00 = 0x00 disable RF -c. APSD_CTRL 0x600[7:0] = 0x40 -d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine -e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine -***************************************/ - u8 eRFPath = 0, value8 = 0; - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - rtl_set_rfreg(hw, (enum radio_path)eRFPath, 0x0, MASKBYTE0, 0x0); - - value8 |= APSDOFF; - rtl_write_byte(rtlpriv, REG_APSD_CTRL, value8); /*0x40*/ - value8 = 0; - value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, value8);/*0x16*/ - value8 &= (~FEN_BB_GLB_RSTn); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, value8); /*0x14*/ -} - -static void _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (rtlhal->fw_version <= 0x20) { - /***************************** - f. MCUFWDL 0x80[7:0]=0 reset MCU ready status - g. SYS_FUNC_EN 0x02[10]= 0 reset MCU reg, (8051 reset) - h. SYS_FUNC_EN 0x02[15-12]= 5 reset MAC reg, DCORE - i. SYS_FUNC_EN 0x02[10]= 1 enable MCU reg, (8051 enable) - ******************************/ - u16 valu16 = 0; - - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); - valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (valu16 & - (~FEN_CPUEN))); /* reset MCU ,8051 */ - valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN)&0x0FFF; - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (valu16 | - (FEN_HWPDN|FEN_ELDR))); /* reset MAC */ - valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (valu16 | - FEN_CPUEN)); /* enable MCU ,8051 */ - } else { - u8 retry_cnts = 0; - - /* IF fw in RAM code, do reset */ - if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(1)) { - /* reset MCU ready status */ - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); - /* 8051 reset by self */ - rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20); - while ((retry_cnts++ < 100) && - (FEN_CPUEN & rtl_read_word(rtlpriv, - REG_SYS_FUNC_EN))) { - udelay(50); - } - if (retry_cnts >= 100) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "#####=> 8051 reset failed!.........................\n"); - /* if 8051 reset fail, reset MAC. */ - rtl_write_byte(rtlpriv, - REG_SYS_FUNC_EN + 1, - 0x50); - udelay(100); - } - } - /* Reset MAC and Enable 8051 */ - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x54); - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); - } - if (bWithoutHWSM) { - /***************************** - Without HW auto state machine - g.SYS_CLKR 0x08[15:0] = 0x30A3 disable MAC clock - h.AFE_PLL_CTRL 0x28[7:0] = 0x80 disable AFE PLL - i.AFE_XTAL_CTRL 0x24[15:0] = 0x880F gated AFE DIG_CLOCK - j.SYS_ISu_CTRL 0x00[7:0] = 0xF9 isolated digital to PON - ******************************/ - rtl_write_word(rtlpriv, REG_SYS_CLKR, 0x70A3); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); - rtl_write_word(rtlpriv, REG_AFE_XTAL_CTRL, 0x880F); - rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xF9); - } -} - -static void _ResetDigitalProcedure2(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); -/***************************** -k. SYS_FUNC_EN 0x03[7:0] = 0x44 disable ELDR runction -l. SYS_CLKR 0x08[15:0] = 0x3083 disable ELDR clock -m. SYS_ISO_CTRL 0x01[7:0] = 0x83 isolated ELDR to PON -******************************/ - rtl_write_word(rtlpriv, REG_SYS_CLKR, 0x70A3); - rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL+1, 0x82); -} - -static void _DisableGPIO(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); -/*************************************** -j. GPIO_PIN_CTRL 0x44[31:0]=0x000 -k. Value = GPIO_PIN_CTRL[7:0] -l. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); write ext PIN level -m. GPIO_MUXCFG 0x42 [15:0] = 0x0780 -n. LEDCFG 0x4C[15:0] = 0x8080 -***************************************/ - u8 value8; - u16 value16; - u32 value32; - - /* 1. Disable GPIO[7:0] */ - rtl_write_word(rtlpriv, REG_GPIO_PIN_CTRL+2, 0x0000); - value32 = rtl_read_dword(rtlpriv, REG_GPIO_PIN_CTRL) & 0xFFFF00FF; - value8 = (u8)(value32&0x000000FF); - value32 |= ((value8<<8) | 0x00FF0000); - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, value32); - /* 2. Disable GPIO[10:8] */ - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG+3, 0x00); - value16 = rtl_read_word(rtlpriv, REG_GPIO_MUXCFG+2) & 0xFF0F; - value8 = (u8)(value16&0x000F); - value16 |= ((value8<<4) | 0x0780); - rtl_write_word(rtlpriv, REG_GPIO_PIN_CTRL+2, value16); - /* 3. Disable LED0 & 1 */ - rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); -} - -static void _DisableAnalog(struct ieee80211_hw *hw, bool bWithoutHWSM) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 value16 = 0; - u8 value8 = 0; - - if (bWithoutHWSM) { - /***************************** - n. LDOA15_CTRL 0x20[7:0] = 0x04 disable A15 power - o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power - r. When driver call disable, the ASIC will turn off remaining - clock automatically - ******************************/ - rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x04); - value8 = rtl_read_byte(rtlpriv, REG_LDOV12D_CTRL); - value8 &= (~LDV12_EN); - rtl_write_byte(rtlpriv, REG_LDOV12D_CTRL, value8); - } - -/***************************** -h. SPS0_CTRL 0x11[7:0] = 0x23 enter PFM mode -i. APS_FSMCO 0x04[15:0] = 0x4802 set USB suspend -******************************/ - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); - value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN); - rtl_write_word(rtlpriv, REG_APS_FSMCO, (u16)value16); - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E); -} - -static void _CardDisableHWSM(struct ieee80211_hw *hw) -{ - /* ==== RF Off Sequence ==== */ - _DisableRFAFEAndResetBB(hw); - /* ==== Reset digital sequence ====== */ - _ResetDigitalProcedure1(hw, false); - /* ==== Pull GPIO PIN to balance level and LED control ====== */ - _DisableGPIO(hw); - /* ==== Disable analog sequence === */ - _DisableAnalog(hw, false); -} - -static void _CardDisableWithoutHWSM(struct ieee80211_hw *hw) -{ - /*==== RF Off Sequence ==== */ - _DisableRFAFEAndResetBB(hw); - /* ==== Reset digital sequence ====== */ - _ResetDigitalProcedure1(hw, true); - /* ==== Pull GPIO PIN to balance level and LED control ====== */ - _DisableGPIO(hw); - /* ==== Reset digital sequence ====== */ - _ResetDigitalProcedure2(hw); - /* ==== Disable analog sequence === */ - _DisableAnalog(hw, true); -} - -static void _rtl92cu_set_bcn_ctrl_reg(struct ieee80211_hw *hw, - u8 set_bits, u8 clear_bits) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - - rtlusb->reg_bcn_ctrl_val |= set_bits; - rtlusb->reg_bcn_ctrl_val &= ~clear_bits; - rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlusb->reg_bcn_ctrl_val); -} - -static void _rtl92cu_stop_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 tmp1byte = 0; - if (IS_NORMAL_CHIP(rtlhal->version)) { - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, - tmp1byte & (~BIT(6))); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); - } else { - rtl_write_byte(rtlpriv, REG_TXPAUSE, - rtl_read_byte(rtlpriv, REG_TXPAUSE) | BIT(6)); - } -} - -static void _rtl92cu_resume_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 tmp1byte = 0; - - if (IS_NORMAL_CHIP(rtlhal->version)) { - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, - tmp1byte | BIT(6)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte |= BIT(0); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); - } else { - rtl_write_byte(rtlpriv, REG_TXPAUSE, - rtl_read_byte(rtlpriv, REG_TXPAUSE) & (~BIT(6))); - } -} - -static void _rtl92cu_enable_bcn_sub_func(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - - if (IS_NORMAL_CHIP(rtlhal->version)) - _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(1)); - else - _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4)); -} - -static void _rtl92cu_disable_bcn_sub_func(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - - if (IS_NORMAL_CHIP(rtlhal->version)) - _rtl92cu_set_bcn_ctrl_reg(hw, BIT(1), 0); - else - _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0); -} - -static int _rtl92cu_set_media_status(struct ieee80211_hw *hw, - enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bt_msr = rtl_read_byte(rtlpriv, MSR); - enum led_ctl_mode ledaction = LED_CTL_NO_LINK; - - bt_msr &= 0xfc; - if (type == NL80211_IFTYPE_UNSPECIFIED || type == - NL80211_IFTYPE_STATION) { - _rtl92cu_stop_tx_beacon(hw); - _rtl92cu_enable_bcn_sub_func(hw); - } else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP) { - _rtl92cu_resume_tx_beacon(hw); - _rtl92cu_disable_bcn_sub_func(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set HW_VAR_MEDIA_STATUS:No such media status(%x)\n", - type); - } - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - bt_msr |= MSR_NOLINK; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to NO LINK!\n"); - break; - case NL80211_IFTYPE_ADHOC: - bt_msr |= MSR_ADHOC; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to Ad Hoc!\n"); - break; - case NL80211_IFTYPE_STATION: - bt_msr |= MSR_INFRA; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to STA!\n"); - break; - case NL80211_IFTYPE_AP: - bt_msr |= MSR_AP; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to AP!\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Network type %d not supported!\n", type); - goto error_out; - } - rtl_write_byte(rtlpriv, MSR, bt_msr); - rtlpriv->cfg->ops->led_control(hw, ledaction); - if ((bt_msr & MSR_MASK) == MSR_AP) - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); - else - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); - return 0; -error_out: - return 1; -} - -void rtl92cu_card_disable(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - enum nl80211_iftype opmode; - - mac->link_state = MAC80211_NOLINK; - opmode = NL80211_IFTYPE_UNSPECIFIED; - _rtl92cu_set_media_status(hw, opmode); - rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - if (rtlusb->disableHWSM) - _CardDisableHWSM(hw); - else - _CardDisableWithoutHWSM(hw); - - /* after power off we should do iqk again */ - rtlpriv->phy.iqk_initialized = false; -} - -void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u32 reg_rcr; - - if (rtlpriv->psc.rfpwr_state != ERFON) - return; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); - - if (check_bssid) { - u8 tmp; - if (IS_NORMAL_CHIP(rtlhal->version)) { - reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); - tmp = BIT(4); - } else { - reg_rcr |= RCR_CBSSID; - tmp = BIT(4) | BIT(5); - } - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *) (®_rcr)); - _rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp); - } else { - u8 tmp; - if (IS_NORMAL_CHIP(rtlhal->version)) { - reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); - tmp = BIT(4); - } else { - reg_rcr &= ~RCR_CBSSID; - tmp = BIT(4) | BIT(5); - } - reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_RCR, (u8 *) (®_rcr)); - _rtl92cu_set_bcn_ctrl_reg(hw, tmp, 0); - } -} - -/*========================================================================== */ - -int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (_rtl92cu_set_media_status(hw, type)) - return -EOPNOTSUPP; - - if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { - if (type != NL80211_IFTYPE_AP) - rtl92cu_set_check_bssid(hw, true); - } else { - rtl92cu_set_check_bssid(hw, false); - } - - return 0; -} - -static void _beacon_function_enable(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - _rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4) | BIT(3) | BIT(1)), 0x00); - rtl_write_byte(rtlpriv, REG_RD_CTRL+1, 0x6F); -} - -void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw) -{ - - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval, atim_window; - u32 value32; - - bcn_interval = mac->beacon_interval; - atim_window = 2; /*FIX MERGE */ - rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - _rtl92cu_init_beacon_parameters(hw); - rtl_write_byte(rtlpriv, REG_SLOT, 0x09); - /* - * Force beacon frame transmission even after receiving beacon frame - * from other ad hoc STA - * - * - * Reset TSF Timer to zero, added by Roger. 2008.06.24 - */ - value32 = rtl_read_dword(rtlpriv, REG_TCR); - value32 &= ~TSFRST; - rtl_write_dword(rtlpriv, REG_TCR, value32); - value32 |= TSFRST; - rtl_write_dword(rtlpriv, REG_TCR, value32); - RT_TRACE(rtlpriv, COMP_INIT|COMP_BEACON, DBG_LOUD, - "SetBeaconRelatedRegisters8192CUsb(): Set TCR(%x)\n", - value32); - /* TODO: Modify later (Find the right parameters) - * NOTE: Fix test chip's bug (about contention windows's randomness) */ - if ((mac->opmode == NL80211_IFTYPE_ADHOC) || - (mac->opmode == NL80211_IFTYPE_MESH_POINT) || - (mac->opmode == NL80211_IFTYPE_AP)) { - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x50); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x50); - } - _beacon_function_enable(hw); -} - -void rtl92cu_set_beacon_interval(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval = mac->beacon_interval; - - RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, "beacon_interval:%d\n", - bcn_interval); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); -} - -void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr) -{ -} - -void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - switch (variable) { - case HW_VAR_RCR: - *((u32 *)(val)) = mac->rx_conf; - break; - case HW_VAR_RF_STATE: - *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; - break; - case HW_VAR_FWLPS_RF_ON:{ - enum rf_pwrstate rfState; - u32 val_rcr; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, - (u8 *)(&rfState)); - if (rfState == ERFOFF) { - *((bool *) (val)) = true; - } else { - val_rcr = rtl_read_dword(rtlpriv, REG_RCR); - val_rcr &= 0x00070000; - if (val_rcr) - *((bool *) (val)) = false; - else - *((bool *) (val)) = true; - } - break; - } - case HW_VAR_FW_PSMODE_STATUS: - *((bool *) (val)) = ppsc->fw_current_inpsmode; - break; - case HW_VAR_CORRECT_TSF:{ - u64 tsf; - u32 *ptsf_low = (u32 *)&tsf; - u32 *ptsf_high = ((u32 *)&tsf) + 1; - - *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); - *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - *((u64 *)(val)) = tsf; - break; - } - case HW_VAR_MGT_FILTER: - *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP0); - break; - case HW_VAR_CTRL_FILTER: - *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP1); - break; - case HW_VAR_DATA_FILTER: - *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP2); - break; - case HAL_DEF_WOWLAN: - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } -} - -static bool usb_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - /* Currently nothing happens here. - * Traffic stops after some seconds in WPA2 802.11n mode. - * Maybe because rtl8192cu chip should be set from here? - * If I understand correctly, the realtek vendor driver sends some urbs - * if its "here". - * - * This is maybe necessary: - * rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, 1, 1, skb); - */ - return true; -} - -void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - enum wireless_mode wirelessmode = mac->mode; - u8 idx = 0; - - switch (variable) { - case HW_VAR_ETHER_ADDR:{ - for (idx = 0; idx < ETH_ALEN; idx++) { - rtl_write_byte(rtlpriv, (REG_MACID + idx), - val[idx]); - } - break; - } - case HW_VAR_BASIC_RATE:{ - u16 rate_cfg = ((u16 *) val)[0]; - u8 rate_index = 0; - - rate_cfg &= 0x15f; - /* TODO */ - /* if (mac->current_network.vender == HT_IOT_PEER_CISCO - * && ((rate_cfg & 0x150) == 0)) { - * rate_cfg |= 0x010; - * } */ - rate_cfg |= 0x01; - rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); - rtl_write_byte(rtlpriv, REG_RRSR + 1, - (rate_cfg >> 8) & 0xff); - while (rate_cfg > 0x1) { - rate_cfg >>= 1; - rate_index++; - } - rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, - rate_index); - break; - } - case HW_VAR_BSSID:{ - for (idx = 0; idx < ETH_ALEN; idx++) { - rtl_write_byte(rtlpriv, (REG_BSSID + idx), - val[idx]); - } - break; - } - case HW_VAR_SIFS:{ - rtl_write_byte(rtlpriv, REG_SIFS_CCK + 1, val[0]); - rtl_write_byte(rtlpriv, REG_SIFS_OFDM + 1, val[1]); - rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); - rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); - rtl_write_byte(rtlpriv, REG_R2T_SIFS+1, val[0]); - rtl_write_byte(rtlpriv, REG_T2T_SIFS+1, val[0]); - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, "HW_VAR_SIFS\n"); - break; - } - case HW_VAR_SLOT_TIME:{ - u8 e_aci; - u8 QOS_MODE = 1; - - rtl_write_byte(rtlpriv, REG_SLOT, val[0]); - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "HW_VAR_SLOT_TIME %x\n", val[0]); - if (QOS_MODE) { - for (e_aci = 0; e_aci < AC_MAX; e_aci++) - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AC_PARAM, - &e_aci); - } else { - u8 sifstime = 0; - u8 u1bAIFS; - - if (IS_WIRELESS_MODE_A(wirelessmode) || - IS_WIRELESS_MODE_N_24G(wirelessmode) || - IS_WIRELESS_MODE_N_5G(wirelessmode)) - sifstime = 16; - else - sifstime = 10; - u1bAIFS = sifstime + (2 * val[0]); - rtl_write_byte(rtlpriv, REG_EDCA_VO_PARAM, - u1bAIFS); - rtl_write_byte(rtlpriv, REG_EDCA_VI_PARAM, - u1bAIFS); - rtl_write_byte(rtlpriv, REG_EDCA_BE_PARAM, - u1bAIFS); - rtl_write_byte(rtlpriv, REG_EDCA_BK_PARAM, - u1bAIFS); - } - break; - } - case HW_VAR_ACK_PREAMBLE:{ - u8 reg_tmp; - u8 short_preamble = (bool)*val; - reg_tmp = 0; - if (short_preamble) - reg_tmp |= 0x80; - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp); - break; - } - case HW_VAR_AMPDU_MIN_SPACE:{ - u8 min_spacing_to_set; - u8 sec_min_space; - - min_spacing_to_set = *val; - if (min_spacing_to_set <= 7) { - switch (rtlpriv->sec.pairwise_enc_algorithm) { - case NO_ENCRYPTION: - case AESCCMP_ENCRYPTION: - sec_min_space = 0; - break; - case WEP40_ENCRYPTION: - case WEP104_ENCRYPTION: - case TKIP_ENCRYPTION: - sec_min_space = 6; - break; - default: - sec_min_space = 7; - break; - } - if (min_spacing_to_set < sec_min_space) - min_spacing_to_set = sec_min_space; - mac->min_space_cfg = ((mac->min_space_cfg & - 0xf8) | - min_spacing_to_set); - *val = min_spacing_to_set; - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", - mac->min_space_cfg); - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - } - break; - } - case HW_VAR_SHORTGI_DENSITY:{ - u8 density_to_set; - - density_to_set = *val; - density_to_set &= 0x1f; - mac->min_space_cfg &= 0x07; - mac->min_space_cfg |= (density_to_set << 3); - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_SHORTGI_DENSITY: %#x\n", - mac->min_space_cfg); - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - break; - } - case HW_VAR_AMPDU_FACTOR:{ - u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9}; - u8 factor_toset; - u8 *p_regtoset = NULL; - u8 index = 0; - - p_regtoset = regtoset_normal; - factor_toset = *val; - if (factor_toset <= 3) { - factor_toset = (1 << (factor_toset + 2)); - if (factor_toset > 0xf) - factor_toset = 0xf; - for (index = 0; index < 4; index++) { - if ((p_regtoset[index] & 0xf0) > - (factor_toset << 4)) - p_regtoset[index] = - (p_regtoset[index] & 0x0f) - | (factor_toset << 4); - if ((p_regtoset[index] & 0x0f) > - factor_toset) - p_regtoset[index] = - (p_regtoset[index] & 0xf0) - | (factor_toset); - rtl_write_byte(rtlpriv, - (REG_AGGLEN_LMT + index), - p_regtoset[index]); - } - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_FACTOR: %#x\n", - factor_toset); - } - break; - } - case HW_VAR_AC_PARAM:{ - u8 e_aci = *val; - u32 u4b_ac_param; - u16 cw_min = le16_to_cpu(mac->ac[e_aci].cw_min); - u16 cw_max = le16_to_cpu(mac->ac[e_aci].cw_max); - u16 tx_op = le16_to_cpu(mac->ac[e_aci].tx_op); - - u4b_ac_param = (u32) mac->ac[e_aci].aifs; - u4b_ac_param |= (u32) ((cw_min & 0xF) << - AC_PARAM_ECW_MIN_OFFSET); - u4b_ac_param |= (u32) ((cw_max & 0xF) << - AC_PARAM_ECW_MAX_OFFSET); - u4b_ac_param |= (u32) tx_op << AC_PARAM_TXOP_OFFSET; - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "queue:%x, ac_param:%x\n", - e_aci, u4b_ac_param); - switch (e_aci) { - case AC1_BK: - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, - u4b_ac_param); - break; - case AC0_BE: - rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, - u4b_ac_param); - break; - case AC2_VI: - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, - u4b_ac_param); - break; - case AC3_VO: - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, - u4b_ac_param); - break; - default: - RT_ASSERT(false, "invalid aci: %d !\n", - e_aci); - break; - } - break; - } - case HW_VAR_RCR:{ - rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]); - mac->rx_conf = ((u32 *) (val))[0]; - RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG, - "### Set RCR(0x%08x) ###\n", mac->rx_conf); - break; - } - case HW_VAR_RETRY_LIMIT:{ - u8 retry_limit = val[0]; - - rtl_write_word(rtlpriv, REG_RL, - retry_limit << RETRY_LIMIT_SHORT_SHIFT | - retry_limit << RETRY_LIMIT_LONG_SHIFT); - RT_TRACE(rtlpriv, COMP_MLME, DBG_DMESG, - "Set HW_VAR_RETRY_LIMIT(0x%08x)\n", - retry_limit); - break; - } - case HW_VAR_DUAL_TSF_RST: - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); - break; - case HW_VAR_EFUSE_BYTES: - rtlefuse->efuse_usedbytes = *((u16 *) val); - break; - case HW_VAR_EFUSE_USAGE: - rtlefuse->efuse_usedpercentage = *val; - break; - case HW_VAR_IO_CMD: - rtl92c_phy_set_io_cmd(hw, (*(enum io_type *)val)); - break; - case HW_VAR_WPA_CONFIG: - rtl_write_byte(rtlpriv, REG_SECCFG, *val); - break; - case HW_VAR_SET_RPWM:{ - u8 rpwm_val = rtl_read_byte(rtlpriv, REG_USB_HRPWM); - - if (rpwm_val & BIT(7)) - rtl_write_byte(rtlpriv, REG_USB_HRPWM, *val); - else - rtl_write_byte(rtlpriv, REG_USB_HRPWM, - *val | BIT(7)); - break; - } - case HW_VAR_H2C_FW_PWRMODE:{ - u8 psmode = *val; - - if ((psmode != FW_PS_ACTIVE_MODE) && - (!IS_92C_SERIAL(rtlhal->version))) - rtl92c_dm_rf_saving(hw, true); - rtl92c_set_fw_pwrmode_cmd(hw, (*val)); - break; - } - case HW_VAR_FW_PSMODE_STATUS: - ppsc->fw_current_inpsmode = *((bool *) val); - break; - case HW_VAR_H2C_FW_JOINBSSRPT:{ - u8 mstatus = *val; - u8 tmp_reg422; - bool recover = false; - - if (mstatus == RT_MEDIA_CONNECT) { - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AID, NULL); - rtl_write_byte(rtlpriv, REG_CR + 1, 0x03); - _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3)); - _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0); - tmp_reg422 = rtl_read_byte(rtlpriv, - REG_FWHW_TXQ_CTRL + 2); - if (tmp_reg422 & BIT(6)) - recover = true; - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, - tmp_reg422 & (~BIT(6))); - rtl92c_set_fw_rsvdpagepkt(hw, - &usb_cmd_send_packet); - _rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0); - _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4)); - if (recover) - rtl_write_byte(rtlpriv, - REG_FWHW_TXQ_CTRL + 2, - tmp_reg422 | BIT(6)); - rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); - } - rtl92c_set_fw_joinbss_report_cmd(hw, (*val)); - break; - } - case HW_VAR_AID:{ - u16 u2btmp; - - u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); - u2btmp &= 0xC000; - rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, - (u2btmp | mac->assoc_id)); - break; - } - case HW_VAR_CORRECT_TSF:{ - u8 btype_ibss = val[0]; - - if (btype_ibss) - _rtl92cu_stop_tx_beacon(hw); - _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3)); - rtl_write_dword(rtlpriv, REG_TSFTR, (u32)(mac->tsf & - 0xffffffff)); - rtl_write_dword(rtlpriv, REG_TSFTR + 4, - (u32)((mac->tsf >> 32) & 0xffffffff)); - _rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0); - if (btype_ibss) - _rtl92cu_resume_tx_beacon(hw); - break; - } - case HW_VAR_MGT_FILTER: - rtl_write_word(rtlpriv, REG_RXFLTMAP0, *(u16 *)val); - mac->rx_mgt_filter = *(u16 *)val; - break; - case HW_VAR_CTRL_FILTER: - rtl_write_word(rtlpriv, REG_RXFLTMAP1, *(u16 *)val); - mac->rx_ctrl_filter = *(u16 *)val; - break; - case HW_VAR_DATA_FILTER: - rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *)val); - mac->rx_data_filter = *(u16 *)val; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } -} - -static void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 ratr_value; - u8 ratr_index = 0; - u8 nmode = mac->ht_enable; - u8 mimo_ps = IEEE80211_SMPS_OFF; - u16 shortgi_rate; - u32 tmp_ratr_value; - u8 curtxbw_40mhz = mac->bw_40; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = mac->mode; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_value = sta->supp_rates[1] << 4; - else - ratr_value = sta->supp_rates[0]; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_value = 0xfff; - - ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - if (ratr_value & 0x0000000c) - ratr_value &= 0x0000000d; - else - ratr_value &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_value &= 0x00000FF5; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - nmode = 1; - if (mimo_ps == IEEE80211_SMPS_STATIC) { - ratr_value &= 0x0007F005; - } else { - u32 ratr_mask; - - if (get_rf_type(rtlphy) == RF_1T2R || - get_rf_type(rtlphy) == RF_1T1R) - ratr_mask = 0x000ff005; - else - ratr_mask = 0x0f0ff005; - - ratr_value &= ratr_mask; - } - break; - default: - if (rtlphy->rf_type == RF_1T2R) - ratr_value &= 0x000ff0ff; - else - ratr_value &= 0x0f0ff0ff; - - break; - } - - ratr_value &= 0x0FFFFFFF; - - if (nmode && ((curtxbw_40mhz && - curshortgi_40mhz) || (!curtxbw_40mhz && - curshortgi_20mhz))) { - - ratr_value |= 0x10000000; - tmp_ratr_value = (ratr_value >> 12); - - for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { - if ((1 << shortgi_rate) & tmp_ratr_value) - break; - } - - shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | - (shortgi_rate << 4) | (shortgi_rate); - } - - rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n", - rtl_read_dword(rtlpriv, REG_ARFR0)); -} - -static void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - u32 ratr_bitmap; - u8 ratr_index; - u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0; - u8 curshortgi_40mhz = curtxbw_40mhz && - (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = 0; - bool shortgi = false; - u8 rate_mask[5]; - u8 macid = 0; - u8 mimo_ps = IEEE80211_SMPS_OFF; - - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - wirelessmode = sta_entry->wireless_mode; - if (mac->opmode == NL80211_IFTYPE_STATION || - mac->opmode == NL80211_IFTYPE_MESH_POINT) - curtxbw_40mhz = mac->bw_40; - else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) - macid = sta->aid + 1; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_bitmap = sta->supp_rates[1] << 4; - else - ratr_bitmap = sta->supp_rates[0]; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_bitmap = 0xfff; - ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - ratr_index = RATR_INX_WIRELESS_B; - if (ratr_bitmap & 0x0000000c) - ratr_bitmap &= 0x0000000d; - else - ratr_bitmap &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_index = RATR_INX_WIRELESS_GB; - - if (rssi_level == 1) - ratr_bitmap &= 0x00000f00; - else if (rssi_level == 2) - ratr_bitmap &= 0x00000ff0; - else - ratr_bitmap &= 0x00000ff5; - break; - case WIRELESS_MODE_A: - ratr_index = RATR_INX_WIRELESS_A; - ratr_bitmap &= 0x00000ff0; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - ratr_index = RATR_INX_WIRELESS_NGB; - - if (mimo_ps == IEEE80211_SMPS_STATIC) { - if (rssi_level == 1) - ratr_bitmap &= 0x00070000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0007f000; - else - ratr_bitmap &= 0x0007f005; - } else { - if (rtlphy->rf_type == RF_1T2R || - rtlphy->rf_type == RF_1T1R) { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff005; - } - } else { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x0f0f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0f0ff000; - else - ratr_bitmap &= 0x0f0ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x0f0f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0f0ff000; - else - ratr_bitmap &= 0x0f0ff005; - } - } - } - - if ((curtxbw_40mhz && curshortgi_40mhz) || - (!curtxbw_40mhz && curshortgi_20mhz)) { - - if (macid == 0) - shortgi = true; - else if (macid == 1) - shortgi = false; - } - break; - default: - ratr_index = RATR_INX_WIRELESS_NGB; - - if (rtlphy->rf_type == RF_1T2R) - ratr_bitmap &= 0x000ff0ff; - else - ratr_bitmap &= 0x0f0ff0ff; - break; - } - sta_entry->ratr_index = ratr_index; - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "ratr_bitmap :%x\n", ratr_bitmap); - *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | - (ratr_index << 28); - rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "Rate_index:%x, ratr_val:%x, %5phC\n", - ratr_index, ratr_bitmap, rate_mask); - memcpy(rtlpriv->rate_mask, rate_mask, 5); - /* rtl92c_fill_h2c_cmd() does USB I/O and will result in a - * "scheduled while atomic" if called directly */ - schedule_work(&rtlpriv->works.fill_h2c_cmd); - - if (macid != 0) - sta_entry->ratr_index = ratr_index; -} - -void rtl92cu_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->dm.useramask) - rtl92cu_update_hal_rate_mask(hw, sta, rssi_level); - else - rtl92cu_update_hal_rate_table(hw, sta); -} - -void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 sifs_timer; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, - &mac->slot_time); - if (!mac->ht_enable) - sifs_timer = 0x0a0a; - else - sifs_timer = 0x0e0e; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); -} - -bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; - u8 u1tmp = 0; - bool actuallyset = false; - unsigned long flag = 0; - /* to do - usb autosuspend */ - u8 usb_autosuspend = 0; - - if (ppsc->swrf_processing) - return false; - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - if (ppsc->rfchange_inprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - return false; - } else { - ppsc->rfchange_inprogress = true; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } - cur_rfstate = ppsc->rfpwr_state; - if (usb_autosuspend) { - /* to do................... */ - } else { - if (ppsc->pwrdown_mode) { - u1tmp = rtl_read_byte(rtlpriv, REG_HSISR); - e_rfpowerstate_toset = (u1tmp & BIT(7)) ? - ERFOFF : ERFON; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "pwrdown, 0x5c(BIT7)=%02x\n", u1tmp); - } else { - rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, - rtl_read_byte(rtlpriv, - REG_MAC_PINMUX_CFG) & ~(BIT(3))); - u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); - e_rfpowerstate_toset = (u1tmp & BIT(3)) ? - ERFON : ERFOFF; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "GPIO_IN=%02x\n", u1tmp); - } - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "N-SS RF =%x\n", - e_rfpowerstate_toset); - } - if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "GPIOChangeRF - HW Radio ON, RF ON\n"); - ppsc->hwradiooff = false; - actuallyset = true; - } else if ((!ppsc->hwradiooff) && (e_rfpowerstate_toset == - ERFOFF)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "GPIOChangeRF - HW Radio OFF\n"); - ppsc->hwradiooff = true; - actuallyset = true; - } else { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "pHalData->bHwRadioOff and eRfPowerStateToSet do not match: pHalData->bHwRadioOff %x, eRfPowerStateToSet %x\n", - ppsc->hwradiooff, e_rfpowerstate_toset); - } - if (actuallyset) { - ppsc->hwradiooff = true; - if (e_rfpowerstate_toset == ERFON) { - if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); - else if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_PCI_D3) - && RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3)) - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3); - } - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - /* For power down module, we need to enable register block - * contrl reg at 0x1c. Then enable power down control bit - * of register 0x04 BIT4 and BIT15 as 1. - */ - if (ppsc->pwrdown_mode && e_rfpowerstate_toset == ERFOFF) { - /* Enable register area 0x0-0xc. */ - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0); - rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x8812); - } - if (e_rfpowerstate_toset == ERFOFF) { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); - else if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_PCI_D3) - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3); - } - } else if (e_rfpowerstate_toset == ERFOFF || cur_rfstate == ERFOFF) { - /* Enter D3 or ASPM after GPIO had been done. */ - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); - else if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_PCI_D3) - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3); - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } else { - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } - *valid = 1; - return !ppsc->hwradiooff; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h deleted file mode 100644 index 67588083e6cc..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h +++ /dev/null @@ -1,113 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CU_HW_H__ -#define __RTL92CU_HW_H__ - -#define H2C_RA_MASK 6 - -#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 - -#define RX_PAGE_SIZE_REG_VALUE PBP_128 -/* Note: We will divide number of page equally for each queue - * other than public queue! */ -#define TX_TOTAL_PAGE_NUMBER 0xF8 -#define TX_PAGE_BOUNDARY (TX_TOTAL_PAGE_NUMBER + 1) - - -#define CHIP_B_PAGE_NUM_PUBQ 0xE7 - -/* For Test Chip Setting - * (HPQ + LPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */ -#define CHIP_A_PAGE_NUM_PUBQ 0x7E - - -/* For Chip A Setting */ -#define WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER 0xF5 -#define WMM_CHIP_A_TX_PAGE_BOUNDARY \ - (WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */ - -#define WMM_CHIP_A_PAGE_NUM_PUBQ 0xA3 -#define WMM_CHIP_A_PAGE_NUM_HPQ 0x29 -#define WMM_CHIP_A_PAGE_NUM_LPQ 0x29 - - - -/* Note: For Chip B Setting ,modify later */ -#define WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER 0xF5 -#define WMM_CHIP_B_TX_PAGE_BOUNDARY \ - (WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */ - -#define WMM_CHIP_B_PAGE_NUM_PUBQ 0xB0 -#define WMM_CHIP_B_PAGE_NUM_HPQ 0x29 -#define WMM_CHIP_B_PAGE_NUM_LPQ 0x1C -#define WMM_CHIP_B_PAGE_NUM_NPQ 0x1C - -#define BOARD_TYPE_NORMAL_MASK 0xE0 -#define BOARD_TYPE_TEST_MASK 0x0F - -/* should be renamed and moved to another file */ -enum _BOARD_TYPE_8192CUSB { - BOARD_USB_DONGLE = 0, /* USB dongle */ - BOARD_USB_High_PA = 1, /* USB dongle - high power PA */ - BOARD_MINICARD = 2, /* Minicard */ - BOARD_USB_SOLO = 3, /* USB solo-Slim module */ - BOARD_USB_COMBO = 4, /* USB Combo-Slim module */ -}; - -#define IS_HIGHT_PA(boardtype) \ - ((boardtype == BOARD_USB_High_PA) ? true : false) - -#define RTL92C_DRIVER_INFO_SIZE 4 -void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw); -void rtl92cu_enable_hw_security_config(struct ieee80211_hw *hw); -int rtl92cu_hw_init(struct ieee80211_hw *hw); -void rtl92cu_card_disable(struct ieee80211_hw *hw); -int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); -void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw); -void rtl92cu_set_beacon_interval(struct ieee80211_hw *hw); -void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr); -void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); - -void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw); -bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid); -void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -int rtl92c_download_fw(struct ieee80211_hw *hw); -void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); -void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); -void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, u8 *p_cmdbuffer); -bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw); -void rtl92cu_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u8 rssi_level); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c deleted file mode 100644 index 75a2deb23af1..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c +++ /dev/null @@ -1,141 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../usb.h" -#include "reg.h" -#include "led.h" - -static void _rtl92cu_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -static void _rtl92cu_deInit_led(struct rtl_led *pled) -{ -} - -void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - u8 ledcfg; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - REG_LEDCFG2, pled->ledpin); - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - rtl_write_byte(rtlpriv, - REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6)); - break; - case LED_PIN_LED1: - rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - pled->ledon = true; -} - -void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw); - u8 ledcfg; - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - REG_LEDCFG2, pled->ledpin); - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg &= 0xf0; - if (usbpriv->ledctl.led_opendrain) - rtl_write_byte(rtlpriv, REG_LEDCFG2, - (ledcfg | BIT(1) | BIT(5) | BIT(6))); - else - rtl_write_byte(rtlpriv, REG_LEDCFG2, - (ledcfg | BIT(3) | BIT(5) | BIT(6))); - break; - case LED_PIN_LED1: - ledcfg &= 0x0f; - rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - pled->ledon = false; -} - -void rtl92cu_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw); - _rtl92cu_init_led(hw, &(usbpriv->ledctl.sw_led0), LED_PIN_LED0); - _rtl92cu_init_led(hw, &(usbpriv->ledctl.sw_led1), LED_PIN_LED1); -} - -void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw); - _rtl92cu_deInit_led(&(usbpriv->ledctl.sw_led0)); - _rtl92cu_deInit_led(&(usbpriv->ledctl.sw_led1)); -} - -static void _rtl92cu_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ -} - -void rtl92cu_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && - (ledaction == LED_CTL_TX || - ledaction == LED_CTL_RX || - ledaction == LED_CTL_SITE_SURVEY || - ledaction == LED_CTL_LINK || - ledaction == LED_CTL_NO_LINK || - ledaction == LED_CTL_START_TO_LINK || - ledaction == LED_CTL_POWER_ON)) { - return; - } - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d\n", ledaction); - _rtl92cu_sw_led_control(hw, ledaction); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.h b/drivers/net/wireless/rtlwifi/rtl8192cu/led.h deleted file mode 100644 index 0f372278b7af..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/led.h +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - *****************************************************************************/ - -#ifndef __RTL92CU_LED_H__ -#define __RTL92CU_LED_H__ - -void rtl92cu_init_sw_leds(struct ieee80211_hw *hw); -void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw); -void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92cu_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c deleted file mode 100644 index 035713311a4a..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ /dev/null @@ -1,827 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * -****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../usb.h" -#include "../ps.h" -#include "../cam.h" -#include "../stats.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" -#include "mac.h" -#include "trx.h" -#include "../rtl8192c/fw_common.h" - -#include - -/* macro to shorten lines */ - -#define LINK_Q ui_link_quality -#define RX_EVM rx_evm_percentage -#define RX_SIGQ rx_mimo_sig_qual - - -void rtl92c_read_chip_version(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - enum version_8192c chip_version = VERSION_UNKNOWN; - const char *versionid; - u32 value32; - - value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); - if (value32 & TRP_VAUX_EN) { - chip_version = (value32 & TYPE_ID) ? VERSION_TEST_CHIP_92C : - VERSION_TEST_CHIP_88C; - } else { - /* Normal mass production chip. */ - chip_version = NORMAL_CHIP; - chip_version |= ((value32 & TYPE_ID) ? CHIP_92C : 0); - chip_version |= ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0); - if (IS_VENDOR_UMC(chip_version)) - chip_version |= ((value32 & CHIP_VER_RTL_MASK) ? - CHIP_VENDOR_UMC_B_CUT : 0); - if (IS_92C_SERIAL(chip_version)) { - value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM); - chip_version |= ((CHIP_BONDING_IDENTIFIER(value32) == - CHIP_BONDING_92C_1T2R) ? CHIP_92C_1T2R : 0); - } - } - rtlhal->version = (enum version_8192c)chip_version; - pr_info("Chip version 0x%x\n", chip_version); - switch (rtlhal->version) { - case VERSION_NORMAL_TSMC_CHIP_92C_1T2R: - versionid = "NORMAL_B_CHIP_92C"; - break; - case VERSION_NORMAL_TSMC_CHIP_92C: - versionid = "NORMAL_TSMC_CHIP_92C"; - break; - case VERSION_NORMAL_TSMC_CHIP_88C: - versionid = "NORMAL_TSMC_CHIP_88C"; - break; - case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT: - versionid = "NORMAL_UMC_CHIP_i92C_1T2R_A_CUT"; - break; - case VERSION_NORMAL_UMC_CHIP_92C_A_CUT: - versionid = "NORMAL_UMC_CHIP_92C_A_CUT"; - break; - case VERSION_NORMAL_UMC_CHIP_88C_A_CUT: - versionid = "NORMAL_UMC_CHIP_88C_A_CUT"; - break; - case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT: - versionid = "NORMAL_UMC_CHIP_92C_1T2R_B_CUT"; - break; - case VERSION_NORMAL_UMC_CHIP_92C_B_CUT: - versionid = "NORMAL_UMC_CHIP_92C_B_CUT"; - break; - case VERSION_NORMAL_UMC_CHIP_88C_B_CUT: - versionid = "NORMAL_UMC_CHIP_88C_B_CUT"; - break; - case VERSION_TEST_CHIP_92C: - versionid = "TEST_CHIP_92C"; - break; - case VERSION_TEST_CHIP_88C: - versionid = "TEST_CHIP_88C"; - break; - default: - versionid = "UNKNOWN"; - break; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Chip Version ID: %s\n", versionid); - - if (IS_92C_SERIAL(rtlhal->version)) - rtlphy->rf_type = - (IS_92C_1T2R(rtlhal->version)) ? RF_1T2R : RF_2T2R; - else - rtlphy->rf_type = RF_1T1R; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip RF Type: %s\n", - rtlphy->rf_type == RF_2T2R ? "RF_2T2R" : "RF_1T1R"); - if (get_rf_type(rtlphy) == RF_1T1R) - rtlpriv->dm.rfpath_rxenable[0] = true; - else - rtlpriv->dm.rfpath_rxenable[0] = - rtlpriv->dm.rfpath_rxenable[1] = true; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", - rtlhal->version); -} - -/** - * writeLLT - LLT table write access - * @io: io callback - * @address: LLT logical address. - * @data: LLT data content - * - * Realtek hardware access function. - * - */ -bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool status = true; - long count = 0; - u32 value = _LLT_INIT_ADDR(address) | - _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); - - rtl_write_dword(rtlpriv, REG_LLT_INIT, value); - do { - value = rtl_read_dword(rtlpriv, REG_LLT_INIT); - if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) - break; - if (count > POLLING_LLT_THRESHOLD) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to polling write LLT done at address %d! _LLT_OP_VALUE(%x)\n", - address, _LLT_OP_VALUE(value)); - status = false; - break; - } - } while (++count); - return status; -} -/** - * rtl92c_init_LLT_table - Init LLT table - * @io: io callback - * @boundary: - * - * Realtek hardware access function. - * - */ -bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary) -{ - bool rst = true; - u32 i; - - for (i = 0; i < (boundary - 1); i++) { - rst = rtl92c_llt_write(hw, i , i + 1); - if (true != rst) { - pr_err("===> %s #1 fail\n", __func__); - return rst; - } - } - /* end of list */ - rst = rtl92c_llt_write(hw, (boundary - 1), 0xFF); - if (true != rst) { - pr_err("===> %s #2 fail\n", __func__); - return rst; - } - /* Make the other pages as ring buffer - * This ring buffer is used as beacon buffer if we config this MAC - * as two MAC transfer. - * Otherwise used as local loopback buffer. - */ - for (i = boundary; i < LLT_LAST_ENTRY_OF_TX_PKT_BUFFER; i++) { - rst = rtl92c_llt_write(hw, i, (i + 1)); - if (true != rst) { - pr_err("===> %s #3 fail\n", __func__); - return rst; - } - } - /* Let last entry point to the start entry of ring buffer */ - rst = rtl92c_llt_write(hw, LLT_LAST_ENTRY_OF_TX_PKT_BUFFER, boundary); - if (true != rst) { - pr_err("===> %s #4 fail\n", __func__); - return rst; - } - return rst; -} -void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 *macaddr = p_macaddr; - u32 entry_id = 0; - bool is_pairwise = false; - static u8 cam_const_addr[4][6] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} - }; - static u8 cam_const_broad[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - - if (clear_all) { - u8 idx = 0; - u8 cam_offset = 0; - u8 clear_number = 5; - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); - for (idx = 0; idx < clear_number; idx++) { - rtl_cam_mark_invalid(hw, cam_offset + idx); - rtl_cam_empty_entry(hw, cam_offset + idx); - if (idx < 5) { - memset(rtlpriv->sec.key_buf[idx], 0, - MAX_KEY_LEN); - rtlpriv->sec.key_len[idx] = 0; - } - } - } else { - switch (enc_algo) { - case WEP40_ENCRYPTION: - enc_algo = CAM_WEP40; - break; - case WEP104_ENCRYPTION: - enc_algo = CAM_WEP104; - break; - case TKIP_ENCRYPTION: - enc_algo = CAM_TKIP; - break; - case AESCCMP_ENCRYPTION: - enc_algo = CAM_AES; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "illegal switch case\n"); - enc_algo = CAM_TKIP; - break; - } - if (is_wepkey || rtlpriv->sec.use_defaultkey) { - macaddr = cam_const_addr[key_index]; - entry_id = key_index; - } else { - if (is_group) { - macaddr = cam_const_broad; - entry_id = key_index; - } else { - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - entry_id = rtl_cam_get_free_entry(hw, - p_macaddr); - if (entry_id >= TOTAL_CAM_ENTRY) { - RT_TRACE(rtlpriv, COMP_SEC, - DBG_EMERG, - "Can not find free hw security cam entry\n"); - return; - } - } else { - entry_id = CAM_PAIRWISE_KEY_POSITION; - } - - key_index = PAIRWISE_KEYIDX; - is_pairwise = true; - } - } - if (rtlpriv->sec.key_len[key_index] == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "delete one entry\n"); - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_MESH_POINT) - rtl_cam_del_entry(hw, p_macaddr); - rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "The insert KEY length is %d\n", - rtlpriv->sec.key_len[PAIRWISE_KEYIDX]); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "The insert KEY is %x %x\n", - rtlpriv->sec.key_buf[0][0], - rtlpriv->sec.key_buf[0][1]); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "add one entry\n"); - if (is_pairwise) { - RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, - "Pairwise Key content", - rtlpriv->sec.pairwise_key, - rtlpriv->sec. - key_len[PAIRWISE_KEYIDX]); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set Pairwise key\n"); - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec. - key_buf[key_index]); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set group key\n"); - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - rtl_cam_add_one_entry(hw, - rtlefuse->dev_addr, - PAIRWISE_KEYIDX, - CAM_PAIRWISE_KEY_POSITION, - enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf - [entry_id]); - } - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[entry_id]); - } - } - } -} - -u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - return rtl_read_dword(rtlpriv, REG_TXDMA_STATUS); -} - -void rtl92c_enable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - - if (IS_HARDWARE_TYPE_8192CE(rtlhal)) { - rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & - 0xFFFFFFFF); - rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & - 0xFFFFFFFF); - } else { - rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] & - 0xFFFFFFFF); - rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] & - 0xFFFFFFFF); - } -} - -void rtl92c_init_interrupt(struct ieee80211_hw *hw) -{ - rtl92c_enable_interrupt(hw); -} - -void rtl92c_disable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED); - rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); -} - -void rtl92c_set_qos(struct ieee80211_hw *hw, int aci) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl92c_dm_init_edca_turbo(hw); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, (u8 *)&aci); -} - -void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size); -} - -int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) -{ - u8 value; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - value = NT_NO_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Set Network type to NO LINK!\n"); - break; - case NL80211_IFTYPE_ADHOC: - value = NT_LINK_AD_HOC; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Set Network type to Ad Hoc!\n"); - break; - case NL80211_IFTYPE_STATION: - value = NT_LINK_AP; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Set Network type to STA!\n"); - break; - case NL80211_IFTYPE_AP: - value = NT_AS_AP; - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Set Network type to AP!\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Network type %d not supported!\n", type); - return -EOPNOTSUPP; - } - rtl_write_byte(rtlpriv, MSR, value); - return 0; -} - -void rtl92c_init_network_type(struct ieee80211_hw *hw) -{ - rtl92c_set_network_type(hw, NL80211_IFTYPE_UNSPECIFIED); -} - -void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw) -{ - u16 value16; - u32 value32; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /* Response Rate Set */ - value32 = rtl_read_dword(rtlpriv, REG_RRSR); - value32 &= ~RATE_BITMAP_ALL; - value32 |= RATE_RRSR_CCK_ONLY_1M; - rtl_write_dword(rtlpriv, REG_RRSR, value32); - /* SIFS (used in NAV) */ - value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10); - rtl_write_word(rtlpriv, REG_SPEC_SIFS, value16); - /* Retry Limit */ - value16 = _LRL(0x30) | _SRL(0x30); - rtl_write_dword(rtlpriv, REG_RL, value16); -} - -void rtl92c_init_rate_fallback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /* Set Data Auto Rate Fallback Retry Count register. */ - rtl_write_dword(rtlpriv, REG_DARFRC, 0x00000000); - rtl_write_dword(rtlpriv, REG_DARFRC+4, 0x10080404); - rtl_write_dword(rtlpriv, REG_RARFRC, 0x04030201); - rtl_write_dword(rtlpriv, REG_RARFRC+4, 0x08070605); -} - -static void rtl92c_set_cck_sifs(struct ieee80211_hw *hw, u8 trx_sifs, - u8 ctx_sifs) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_SIFS_CCK, trx_sifs); - rtl_write_byte(rtlpriv, (REG_SIFS_CCK + 1), ctx_sifs); -} - -static void rtl92c_set_ofdm_sifs(struct ieee80211_hw *hw, u8 trx_sifs, - u8 ctx_sifs) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_SIFS_OFDM, trx_sifs); - rtl_write_byte(rtlpriv, (REG_SIFS_OFDM + 1), ctx_sifs); -} - -void rtl92c_init_edca_param(struct ieee80211_hw *hw, - u16 queue, u16 txop, u8 cw_min, u8 cw_max, u8 aifs) -{ - /* sequence: VO, VI, BE, BK ==> the same as 92C hardware design. - * referenc : enum nl80211_txq_q or ieee80211_set_wmm_default function. - */ - u32 value; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - value = (u32)aifs; - value |= ((u32)cw_min & 0xF) << 8; - value |= ((u32)cw_max & 0xF) << 12; - value |= (u32)txop << 16; - /* 92C hardware register sequence is the same as queue number. */ - rtl_write_dword(rtlpriv, (REG_EDCA_VO_PARAM + (queue * 4)), value); -} - -void rtl92c_init_edca(struct ieee80211_hw *hw) -{ - u16 value16; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /* disable EDCCA count down, to reduce collison and retry */ - value16 = rtl_read_word(rtlpriv, REG_RD_CTRL); - value16 |= DIS_EDCA_CNT_DWN; - rtl_write_word(rtlpriv, REG_RD_CTRL, value16); - /* Update SIFS timing. ?????????? - * pHalData->SifsTime = 0x0e0e0a0a; */ - rtl92c_set_cck_sifs(hw, 0xa, 0xa); - rtl92c_set_ofdm_sifs(hw, 0xe, 0xe); - /* Set CCK/OFDM SIFS to be 10us. */ - rtl_write_word(rtlpriv, REG_SIFS_CCK, 0x0a0a); - rtl_write_word(rtlpriv, REG_SIFS_OFDM, 0x1010); - rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0204); - rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x014004); - /* TXOP */ - rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, 0x005EA42B); - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0x0000A44F); - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x005EA324); - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x002FA226); - /* PIFS */ - rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); - /* AGGR BREAK TIME Register */ - rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040); - rtl_write_byte(rtlpriv, REG_BCNDMATIM, 0x02); - rtl_write_byte(rtlpriv, REG_ATIMWND, 0x02); -} - -void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x99997631); - rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); - /* init AMPDU aggregation number, tuning for Tx's TP, */ - rtl_write_word(rtlpriv, 0x4CA, 0x0708); -} - -void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xFF); -} - -void rtl92c_init_rdg_setting(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xFF); - rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200); - rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05); -} - -void rtl92c_init_retry_function(struct ieee80211_hw *hw) -{ - u8 value8; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - value8 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL); - value8 |= EN_AMPDU_RTY_NEW; - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL, value8); - /* Set ACK timeout */ - rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); -} - -void rtl92c_disable_fast_edca(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0); -} - -void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value = is2T ? MAX_MSS_DENSITY_2T : MAX_MSS_DENSITY_1T; - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, value); -} - -/*==============================================================*/ - -static u8 _rtl92c_query_rxpwrpercentage(char antpower) -{ - if ((antpower <= -100) || (antpower >= 20)) - return 0; - else if (antpower >= 0) - return 100; - else - return 100 + antpower; -} - -static u8 _rtl92c_evm_db_to_percentage(char value) -{ - char ret_val; - - ret_val = value; - if (ret_val >= 0) - ret_val = 0; - if (ret_val <= -33) - ret_val = -33; - ret_val = 0 - ret_val; - ret_val *= 3; - if (ret_val == 99) - ret_val = 100; - return ret_val; -} - -static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw, - long currsig) -{ - long retsig; - - if (currsig >= 61 && currsig <= 100) - retsig = 90 + ((currsig - 60) / 4); - else if (currsig >= 41 && currsig <= 60) - retsig = 78 + ((currsig - 40) / 2); - else if (currsig >= 31 && currsig <= 40) - retsig = 66 + (currsig - 30); - else if (currsig >= 21 && currsig <= 30) - retsig = 54 + (currsig - 20); - else if (currsig >= 5 && currsig <= 20) - retsig = 42 + (((currsig - 5) * 2) / 3); - else if (currsig == 4) - retsig = 36; - else if (currsig == 3) - retsig = 27; - else if (currsig == 2) - retsig = 18; - else if (currsig == 1) - retsig = 9; - else - retsig = currsig; - return retsig; -} - -static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, - struct rtl_stats *pstats, - struct rx_desc_92c *p_desc, - struct rx_fwinfo_92c *p_drvinfo, - bool packet_match_bssid, - bool packet_toself, - bool packet_beacon) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct phy_sts_cck_8192s_t *cck_buf; - s8 rx_pwr_all = 0, rx_pwr[4]; - u8 rf_rx_num = 0, evm, pwdb_all; - u8 i, max_spatial_stream; - u32 rssi, total_rssi = 0; - bool in_powersavemode = false; - bool is_cck_rate; - u8 *pdesc = (u8 *)p_desc; - - is_cck_rate = RX_HAL_IS_CCK_RATE(p_desc->rxmcs); - pstats->packet_matchbssid = packet_match_bssid; - pstats->packet_toself = packet_toself; - pstats->packet_beacon = packet_beacon; - pstats->is_cck = is_cck_rate; - pstats->RX_SIGQ[0] = -1; - pstats->RX_SIGQ[1] = -1; - if (is_cck_rate) { - u8 report, cck_highpwr; - cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; - if (!in_powersavemode) - cck_highpwr = rtlphy->cck_high_power; - else - cck_highpwr = false; - if (!cck_highpwr) { - u8 cck_agc_rpt = cck_buf->cck_agc_rpt; - report = cck_buf->cck_agc_rpt & 0xc0; - report = report >> 6; - switch (report) { - case 0x3: - rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); - break; - case 0x2: - rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); - break; - case 0x1: - rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); - break; - case 0x0: - rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); - break; - } - } else { - u8 cck_agc_rpt = cck_buf->cck_agc_rpt; - report = p_drvinfo->cfosho[0] & 0x60; - report = report >> 5; - switch (report) { - case 0x3: - rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x2: - rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x1: - rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x0: - rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1); - break; - } - } - pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); - pstats->rx_pwdb_all = pwdb_all; - pstats->recvsignalpower = rx_pwr_all; - if (packet_match_bssid) { - u8 sq; - if (pstats->rx_pwdb_all > 40) - sq = 100; - else { - sq = cck_buf->sq_rpt; - if (sq > 64) - sq = 0; - else if (sq < 20) - sq = 100; - else - sq = ((64 - sq) * 100) / 44; - } - pstats->signalquality = sq; - pstats->RX_SIGQ[0] = sq; - pstats->RX_SIGQ[1] = -1; - } - } else { - rtlpriv->dm.rfpath_rxenable[0] = - rtlpriv->dm.rfpath_rxenable[1] = true; - for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { - if (rtlpriv->dm.rfpath_rxenable[i]) - rf_rx_num++; - rx_pwr[i] = - ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110; - rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]); - total_rssi += rssi; - rtlpriv->stats.rx_snr_db[i] = - (long)(p_drvinfo->rxsnr[i] / 2); - - if (packet_match_bssid) - pstats->rx_mimo_signalstrength[i] = (u8) rssi; - } - rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; - pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all); - pstats->rx_pwdb_all = pwdb_all; - pstats->rxpower = rx_pwr_all; - pstats->recvsignalpower = rx_pwr_all; - if (GET_RX_DESC_RX_MCS(pdesc) && - GET_RX_DESC_RX_MCS(pdesc) >= DESC_RATEMCS8 && - GET_RX_DESC_RX_MCS(pdesc) <= DESC_RATEMCS15) - max_spatial_stream = 2; - else - max_spatial_stream = 1; - for (i = 0; i < max_spatial_stream; i++) { - evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]); - if (packet_match_bssid) { - if (i == 0) - pstats->signalquality = - (u8) (evm & 0xff); - pstats->RX_SIGQ[i] = - (u8) (evm & 0xff); - } - } - } - if (is_cck_rate) - pstats->signalstrength = - (u8) (_rtl92c_signal_scale_mapping(hw, pwdb_all)); - else if (rf_rx_num != 0) - pstats->signalstrength = - (u8) (_rtl92c_signal_scale_mapping - (hw, total_rssi /= rf_rx_num)); -} - -void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct rtl_stats *pstats, - struct rx_desc_92c *pdesc, - struct rx_fwinfo_92c *p_drvinfo) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct ieee80211_hdr *hdr; - u8 *tmp_buf; - u8 *praddr; - __le16 fc; - u16 type, cpu_fc; - bool packet_matchbssid, packet_toself, packet_beacon = false; - - tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; - hdr = (struct ieee80211_hdr *)tmp_buf; - fc = hdr->frame_control; - cpu_fc = le16_to_cpu(fc); - type = WLAN_FC_GET_TYPE(fc); - praddr = hdr->addr1; - packet_matchbssid = - ((IEEE80211_FTYPE_CTL != type) && - ether_addr_equal(mac->bssid, - (cpu_fc & IEEE80211_FCTL_TODS) ? hdr->addr1 : - (cpu_fc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : - hdr->addr3) && - (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv)); - - packet_toself = packet_matchbssid && - ether_addr_equal(praddr, rtlefuse->dev_addr); - if (ieee80211_is_beacon(fc)) - packet_beacon = true; - _rtl92c_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, - packet_matchbssid, packet_toself, - packet_beacon); - rtl_process_phyinfo(hw, tmp_buf, pstats); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h deleted file mode 100644 index 553a4bfac668..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h +++ /dev/null @@ -1,161 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_MAC_H__ -#define __RTL92C_MAC_H__ - -#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER 255 -#define DRIVER_EARLY_INT_TIME 0x05 -#define BCN_DMA_ATIME_INT_TIME 0x02 - -void rtl92c_read_chip_version(struct ieee80211_hw *hw); -bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data); -bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary); -void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all); -void rtl92c_enable_interrupt(struct ieee80211_hw *hw); -void rtl92c_disable_interrupt(struct ieee80211_hw *hw); -void rtl92c_set_qos(struct ieee80211_hw *hw, int aci); - - -/*--------------------------------------------------------------- - * Hardware init functions - *---------------------------------------------------------------*/ -void rtl92c_init_interrupt(struct ieee80211_hw *hw); -void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size); - -int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); -void rtl92c_init_network_type(struct ieee80211_hw *hw); -void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw); -void rtl92c_init_rate_fallback(struct ieee80211_hw *hw); - -void rtl92c_init_edca_param(struct ieee80211_hw *hw, - u16 queue, - u16 txop, - u8 ecwmax, - u8 ecwmin, - u8 aifs); - -void rtl92c_init_edca(struct ieee80211_hw *hw); -void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw); -void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw); -void rtl92c_init_rdg_setting(struct ieee80211_hw *hw); -void rtl92c_init_retry_function(struct ieee80211_hw *hw); - -void rtl92c_disable_fast_edca(struct ieee80211_hw *hw); -void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T); - -u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw); - -struct rx_fwinfo_92c { - u8 gain_trsw[4]; - u8 pwdb_all; - u8 cfosho[4]; - u8 cfotail[4]; - char rxevm[2]; - char rxsnr[4]; - u8 pdsnr[2]; - u8 csi_current[2]; - u8 csi_target[2]; - u8 sigevm; - u8 max_ex_pwr; - u8 ex_intf_flag:1; - u8 sgi_en:1; - u8 rxsc:2; - u8 reserve:4; -} __packed; - -struct rx_desc_92c { - u32 length:14; - u32 crc32:1; - u32 icverror:1; - u32 drv_infosize:4; - u32 security:3; - u32 qos:1; - u32 shift:2; - u32 phystatus:1; - u32 swdec:1; - u32 lastseg:1; - u32 firstseg:1; - u32 eor:1; - u32 own:1; - u32 macid:5; /* word 1 */ - u32 tid:4; - u32 hwrsvd:5; - u32 paggr:1; - u32 faggr:1; - u32 a1_fit:4; - u32 a2_fit:4; - u32 pam:1; - u32 pwr:1; - u32 moredata:1; - u32 morefrag:1; - u32 type:2; - u32 mc:1; - u32 bc:1; - u32 seq:12; /* word 2 */ - u32 frag:4; - u32 nextpktlen:14; - u32 nextind:1; - u32 rsvd:1; - u32 rxmcs:6; /* word 3 */ - u32 rxht:1; - u32 amsdu:1; - u32 splcp:1; - u32 bandwidth:1; - u32 htc:1; - u32 tcpchk_rpt:1; - u32 ipcchk_rpt:1; - u32 tcpchk_valid:1; - u32 hwpcerr:1; - u32 hwpcind:1; - u32 iv0:16; - u32 iv1; /* word 4 */ - u32 tsfl; /* word 5 */ - u32 bufferaddress; /* word 6 */ - u32 bufferaddress64; /* word 7 */ -} __packed; - -enum rtl_desc_qsel rtl92c_map_hwqueue_to_fwqueue(u16 fc, - unsigned int - skb_queue); -void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct rtl_stats *pstats, - struct rx_desc_92c *pdesc, - struct rx_fwinfo_92c *p_drvinfo); - -/*--------------------------------------------------------------- - * Card disable functions - *---------------------------------------------------------------*/ - - - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c deleted file mode 100644 index c972fa50926d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c +++ /dev/null @@ -1,539 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../ps.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "../rtl8192c/phy_common.h" -#include "rf.h" -#include "dm.h" -#include "../rtl8192c/dm_common.h" -#include "../rtl8192c/fw_common.h" -#include "table.h" - -u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, readback_value, bitshift; - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", - regaddr, rfpath, bitmask); - if (rtlphy->rf_mode != RF_OP_BY_FW) { - original_value = _rtl92c_phy_rf_serial_read(hw, - rfpath, regaddr); - } else { - original_value = _rtl92c_phy_fw_rf_serial_read(hw, - rfpath, regaddr); - } - bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); - readback_value = (original_value & bitmask) >> bitshift; - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", - regaddr, rfpath, bitmask, original_value); - return readback_value; -} - -void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 original_value, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); - if (rtlphy->rf_mode != RF_OP_BY_FW) { - if (bitmask != RFREG_OFFSET_MASK) { - original_value = _rtl92c_phy_rf_serial_read(hw, - rfpath, - regaddr); - bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); - data = - ((original_value & (~bitmask)) | - (data << bitshift)); - } - _rtl92c_phy_rf_serial_write(hw, rfpath, regaddr, data); - } else { - if (bitmask != RFREG_OFFSET_MASK) { - original_value = _rtl92c_phy_fw_rf_serial_read(hw, - rfpath, - regaddr); - bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); - data = - ((original_value & (~bitmask)) | - (data << bitshift)); - } - _rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data); - } - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); -} - -bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw) -{ - bool rtstatus; - - rtstatus = _rtl92cu_phy_config_mac_with_headerfile(hw); - return rtstatus; -} - -bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw) -{ - bool rtstatus = true; - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 regval; - u32 regval32; - u8 b_reg_hwparafile = 1; - - _rtl92c_phy_init_bb_rf_register_definition(hw); - regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, regval | BIT(13) | - BIT(0) | BIT(1)); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); - rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD | - FEN_BB_GLB_RSTn | FEN_BBRSTB); - regval32 = rtl_read_dword(rtlpriv, 0x87c); - rtl_write_dword(rtlpriv, 0x87c, regval32 & (~BIT(31))); - rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); - if (b_reg_hwparafile == 1) - rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); - return rtstatus; -} - -bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 i; - u32 arraylength; - u32 *ptrarray; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n"); - arraylength = rtlphy->hwparam_tables[MAC_REG].length ; - ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CUMAC_2T_ARRAY\n"); - for (i = 0; i < arraylength; i = i + 2) - rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); - return true; -} - -bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) -{ - int i; - u32 *phy_regarray_table; - u32 *agctab_array_table; - u16 phy_reg_arraylen, agctab_arraylen; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - if (IS_92C_SERIAL(rtlhal->version)) { - agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_2T].length; - agctab_array_table = rtlphy->hwparam_tables[AGCTAB_2T].pdata; - phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_2T].length; - phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_2T].pdata; - } else { - agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_1T].length; - agctab_array_table = rtlphy->hwparam_tables[AGCTAB_1T].pdata; - phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_1T].length; - phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_1T].pdata; - } - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_reg_arraylen; i = i + 2) { - rtl_addr_delay(phy_regarray_table[i]); - rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD, - phy_regarray_table[i + 1]); - udelay(1); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", - phy_regarray_table[i], - phy_regarray_table[i + 1]); - } - } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { - for (i = 0; i < agctab_arraylen; i = i + 2) { - rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD, - agctab_array_table[i + 1]); - udelay(1); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", - agctab_array_table[i], - agctab_array_table[i + 1]); - } - } - return true; -} - -bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - int i; - u32 *phy_regarray_table_pg; - u16 phy_regarray_pg_len; - - rtlphy->pwrgroup_cnt = 0; - phy_regarray_pg_len = rtlphy->hwparam_tables[PHY_REG_PG].length; - phy_regarray_table_pg = rtlphy->hwparam_tables[PHY_REG_PG].pdata; - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_regarray_pg_len; i = i + 3) { - rtl_addr_delay(phy_regarray_table_pg[i]); - _rtl92c_store_pwrIndex_diffrate_offset(hw, - phy_regarray_table_pg[i], - phy_regarray_table_pg[i + 1], - phy_regarray_table_pg[i + 2]); - } - } else { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "configtype != BaseBand_Config_PHY_REG\n"); - } - return true; -} - -bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath) -{ - int i; - u32 *radioa_array_table; - u32 *radiob_array_table; - u16 radioa_arraylen, radiob_arraylen; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - if (IS_92C_SERIAL(rtlhal->version)) { - radioa_arraylen = rtlphy->hwparam_tables[RADIOA_2T].length; - radioa_array_table = rtlphy->hwparam_tables[RADIOA_2T].pdata; - radiob_arraylen = rtlphy->hwparam_tables[RADIOB_2T].length; - radiob_array_table = rtlphy->hwparam_tables[RADIOB_2T].pdata; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio_A:RTL8192CURADIOA_2TARRAY\n"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio_B:RTL8192CU_RADIOB_2TARRAY\n"); - } else { - radioa_arraylen = rtlphy->hwparam_tables[RADIOA_1T].length; - radioa_array_table = rtlphy->hwparam_tables[RADIOA_1T].pdata; - radiob_arraylen = rtlphy->hwparam_tables[RADIOB_1T].length; - radiob_array_table = rtlphy->hwparam_tables[RADIOB_1T].pdata; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio_A:RTL8192CU_RADIOA_1TARRAY\n"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio_B:RTL8192CU_RADIOB_1TARRAY\n"); - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath); - switch (rfpath) { - case RF90_PATH_A: - for (i = 0; i < radioa_arraylen; i = i + 2) { - rtl_rfreg_delay(hw, rfpath, radioa_array_table[i], - RFREG_OFFSET_MASK, - radioa_array_table[i + 1]); - } - break; - case RF90_PATH_B: - for (i = 0; i < radiob_arraylen; i = i + 2) { - rtl_rfreg_delay(hw, rfpath, radiob_array_table[i], - RFREG_OFFSET_MASK, - radiob_array_table[i + 1]); - } - break; - case RF90_PATH_C: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - case RF90_PATH_D: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - default: - break; - } - return true; -} - -void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 reg_bw_opmode; - u8 reg_prsr_rsc; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n", - rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? - "20MHz" : "40MHz"); - if (is_hal_stop(rtlhal)) { - rtlphy->set_bwmode_inprogress = false; - return; - } - reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); - reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - reg_bw_opmode |= BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - break; - case HT_CHANNEL_WIDTH_20_40: - reg_bw_opmode &= ~BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - reg_prsr_rsc = - (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); - break; - case HT_CHANNEL_WIDTH_20_40: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, - (mac->cur_40_prime_sc >> 1)); - rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); - rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), - (mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - rtl92cu_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); - rtlphy->set_bwmode_inprogress = false; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); -} - -void rtl92cu_bb_block_on(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - mutex_lock(&rtlpriv->io.bb_mutex); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); - mutex_unlock(&rtlpriv->io.bb_mutex); -} - -void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) -{ - u8 tmpreg; - u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - tmpreg = rtl_read_byte(rtlpriv, 0xd03); - - if ((tmpreg & 0x70) != 0) - rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); - else - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - - if ((tmpreg & 0x70) != 0) { - rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); - if (is2t) - rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, - MASK12BITS); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, - (rf_a_mode & 0x8FFFF) | 0x10000); - if (is2t) - rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, - (rf_b_mode & 0x8FFFF) | 0x10000); - } - lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); - rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); - mdelay(100); - if ((tmpreg & 0x70) != 0) { - rtl_write_byte(rtlpriv, 0xd03, tmpreg); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); - if (is2t) - rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, - rf_b_mode); - } else { - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - } -} - -static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool bresult = true; - u8 i, queue_id; - struct rtl8192_tx_ring *ring = NULL; - - switch (rfpwr_state) { - case ERFON: - if ((ppsc->rfpwr_state == ERFOFF) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { - bool rtstatus; - u32 InitializeCount = 0; - - do { - InitializeCount++; - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic enable\n"); - rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && (InitializeCount < 10)); - RT_CLEAR_PS_LEVEL(ppsc, - RT_RF_OFF_LEVL_HALT_NIC); - } else { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFON sleeped:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc->last_sleep_jiffies)); - ppsc->last_awake_jiffies = jiffies; - rtl92ce_phy_set_rf_on(hw); - } - if (mac->link_state == MAC80211_LINKED) { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_LINK); - } else { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - } - break; - case ERFOFF: - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (skb_queue_len(&ring->queue) == 0 || - queue_id == BEACON_QUEUE) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", - i + 1, - queue_id, - skb_queue_len(&ring->queue)); - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "ERFOFF: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic disable\n"); - rtl_ps_disable_nic(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - } else { - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - } else { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_POWER_OFF); - } - } - break; - case ERFSLEEP: - if (ppsc->rfpwr_state == ERFOFF) - return false; - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (skb_queue_len(&ring->queue) == 0) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", - i + 1, queue_id, - skb_queue_len(&ring->queue)); - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFSLEEP awaked:%d ms\n", - jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies)); - ppsc->last_sleep_jiffies = jiffies; - _rtl92c_phy_set_rf_sleep(hw); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - bresult = false; - break; - } - if (bresult) - ppsc->rfpwr_state = rfpwr_state; - return bresult; -} - -bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool bresult = false; - - if (rfpwr_state == ppsc->rfpwr_state) - return bresult; - bresult = _rtl92cu_phy_set_rf_power_state(hw, rfpwr_state); - return bresult; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h deleted file mode 100644 index 42b068660483..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h +++ /dev/null @@ -1,50 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../rtl8192ce/phy.h" - -void rtl92cu_bb_block_on(struct ieee80211_hw *hw); -bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath); -void rtl92c_phy_set_io(struct ieee80211_hw *hw); -bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); -bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw); -u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask); -void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data); -bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw); -bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); -void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); -bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); -void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h b/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h deleted file mode 100644 index 8b81465c629b..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h +++ /dev/null @@ -1,30 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../rtl8192ce/reg.h" diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c deleted file mode 100644 index 5624ade92cc0..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ /dev/null @@ -1,475 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" - -static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw); - -void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - switch (bandwidth) { - case HT_CHANNEL_WIDTH_20: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff) | 0x0400); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - case HT_CHANNEL_WIDTH_20_40: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff)); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", bandwidth); - break; - } -} - -void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 tx_agc[2] = { 0, 0 }, tmpval = 0; - bool turbo_scanoff = false; - u8 idx1, idx2; - u8 *ptr; - - if ((rtlefuse->eeprom_regulatory != 0) || (rtlefuse->external_pa)) - turbo_scanoff = true; - if (mac->act_scanning) { - tx_agc[RF90_PATH_A] = 0x3f3f3f3f; - tx_agc[RF90_PATH_B] = 0x3f3f3f3f; - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - if (tx_agc[idx1] > 0x20 && rtlefuse->external_pa) - tx_agc[idx1] = 0x20; - } - } else { - if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_LEVEL1) { - tx_agc[RF90_PATH_A] = 0x10101010; - tx_agc[RF90_PATH_B] = 0x10101010; - } else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_LEVEL2) { - tx_agc[RF90_PATH_A] = 0x00000000; - tx_agc[RF90_PATH_B] = 0x00000000; - } else { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - if (rtlefuse->eeprom_regulatory == 0) { - tmpval = (rtlphy->mcs_offset[0][6]) + - (rtlphy->mcs_offset[0][7] << 8); - tx_agc[RF90_PATH_A] += tmpval; - tmpval = (rtlphy->mcs_offset[0][14]) + - (rtlphy->mcs_offset[0][15] << 24); - tx_agc[RF90_PATH_B] += tmpval; - } - } - } - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - ptr = (u8 *) (&(tx_agc[idx1])); - for (idx2 = 0; idx2 < 4; idx2++) { - if (*ptr > RF6052_MAX_TX_PWR) - *ptr = RF6052_MAX_TX_PWR; - ptr++; - } - } - tmpval = tx_agc[RF90_PATH_A] & 0xff; - rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", - tmpval, RTXAGC_A_CCK1_MCS32); - - tmpval = tx_agc[RF90_PATH_A] >> 8; - if (mac->mode == WIRELESS_MODE_B) - tmpval = tmpval & 0xff00ffff; - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", - tmpval, RTXAGC_B_CCK11_A_CCK2_11); - tmpval = tx_agc[RF90_PATH_B] >> 24; - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", - tmpval, RTXAGC_B_CCK11_A_CCK2_11); - tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; - rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", - tmpval, RTXAGC_B_CCK1_55_MCS32); -} - -static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel, - u32 *ofdmbase, u32 *mcsbase) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 powerBase0, powerBase1; - u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0; - u8 i, powerlevel[2]; - - for (i = 0; i < 2; i++) { - powerlevel[i] = ppowerlevel[i]; - legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; - powerBase0 = powerlevel[i] + legacy_pwrdiff; - powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) | - (powerBase0 << 8) | powerBase0; - *(ofdmbase + i) = powerBase0; - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [OFDM power base index rf(%c) = 0x%x]\n", - i == 0 ? 'A' : 'B', *(ofdmbase + i)); - } - for (i = 0; i < 2; i++) { - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { - ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1]; - powerlevel[i] += ht20_pwrdiff; - } - powerBase1 = powerlevel[i]; - powerBase1 = (powerBase1 << 24) | - (powerBase1 << 16) | (powerBase1 << 8) | powerBase1; - *(mcsbase + i) = powerBase1; - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [MCS power base index rf(%c) = 0x%x]\n", - i == 0 ? 'A' : 'B', *(mcsbase + i)); - } -} - -static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, - u8 channel, u8 index, - u32 *powerBase0, - u32 *powerBase1, - u32 *p_outwriteval) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 i, chnlgroup = 0, pwr_diff_limit[4]; - u32 writeVal, customer_limit, rf; - - for (rf = 0; rf < 2; rf++) { - switch (rtlefuse->eeprom_regulatory) { - case 0: - chnlgroup = 0; - writeVal = rtlphy->mcs_offset - [chnlgroup][index + (rf ? 8 : 0)] - + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance,writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); - break; - case 1: - if (rtlphy->pwrgroup_cnt == 1) - chnlgroup = 0; - if (rtlphy->pwrgroup_cnt >= 3) { - if (channel <= 3) - chnlgroup = 0; - else if (channel >= 4 && channel <= 9) - chnlgroup = 1; - else if (channel > 9) - chnlgroup = 2; - if (rtlphy->current_chan_bw == - HT_CHANNEL_WIDTH_20) - chnlgroup++; - else - chnlgroup += 4; - } - writeVal = rtlphy->mcs_offset[chnlgroup][index + - (rf ? 8 : 0)] + - ((index < 2) ? powerBase0[rf] : - powerBase1[rf]); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); - break; - case 2: - writeVal = ((index < 2) ? powerBase0[rf] : - powerBase1[rf]); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Better regulatory,writeVal(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); - break; - case 3: - chnlgroup = 0; - if (rtlphy->current_chan_bw == - HT_CHANNEL_WIDTH_20_40) { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 40MHzrf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', - rtlefuse->pwrgroup_ht40[rf] - [channel - 1]); - } else { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 20MHz rf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', - rtlefuse->pwrgroup_ht20[rf] - [channel - 1]); - } - for (i = 0; i < 4; i++) { - pwr_diff_limit[i] = (u8) ((rtlphy->mcs_offset - [chnlgroup][index + (rf ? 8 : 0)] - & (0x7f << (i * 8))) >> (i * 8)); - if (rtlphy->current_chan_bw == - HT_CHANNEL_WIDTH_20_40) { - if (pwr_diff_limit[i] > - rtlefuse->pwrgroup_ht40[rf] - [channel - 1]) - pwr_diff_limit[i] = rtlefuse-> - pwrgroup_ht40[rf] - [channel - 1]; - } else { - if (pwr_diff_limit[i] > - rtlefuse->pwrgroup_ht20[rf] - [channel - 1]) - pwr_diff_limit[i] = - rtlefuse->pwrgroup_ht20[rf] - [channel - 1]; - } - } - customer_limit = (pwr_diff_limit[3] << 24) | - (pwr_diff_limit[2] << 16) | - (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer's limit rf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', customer_limit); - writeVal = customer_limit + ((index < 2) ? - powerBase0[rf] : powerBase1[rf]); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer, writeVal rf(%c)= 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); - break; - default: - chnlgroup = 0; - writeVal = rtlphy->mcs_offset[chnlgroup] - [index + (rf ? 8 : 0)] + ((index < 2) ? - powerBase0[rf] : powerBase1[rf]); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeValrf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeVal); - break; - } - if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_LEVEL1) - writeVal = 0x14141414; - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_LEVEL2) - writeVal = 0x00000000; - if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) - writeVal = writeVal - 0x06060606; - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_BT2) - writeVal = writeVal; - *(p_outwriteval + rf) = writeVal; - } -} - -static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw, - u8 index, u32 *pValue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u16 regoffset_a[6] = { - RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, - RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, - RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 - }; - u16 regoffset_b[6] = { - RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, - RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, - RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 - }; - u8 i, rf, pwr_val[4]; - u32 writeVal; - u16 regoffset; - - for (rf = 0; rf < 2; rf++) { - writeVal = pValue[rf]; - for (i = 0; i < 4; i++) { - pwr_val[i] = (u8)((writeVal & (0x7f << (i * 8))) >> - (i * 8)); - if (pwr_val[i] > RF6052_MAX_TX_PWR) - pwr_val[i] = RF6052_MAX_TX_PWR; - } - writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) | - (pwr_val[1] << 8) | pwr_val[0]; - if (rf == 0) - regoffset = regoffset_a[index]; - else - regoffset = regoffset_b[index]; - rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Set 0x%x = %08x\n", regoffset, writeVal); - if (((get_rf_type(rtlphy) == RF_2T2R) && - (regoffset == RTXAGC_A_MCS15_MCS12 || - regoffset == RTXAGC_B_MCS15_MCS12)) || - ((get_rf_type(rtlphy) != RF_2T2R) && - (regoffset == RTXAGC_A_MCS07_MCS04 || - regoffset == RTXAGC_B_MCS07_MCS04))) { - writeVal = pwr_val[3]; - if (regoffset == RTXAGC_A_MCS15_MCS12 || - regoffset == RTXAGC_A_MCS07_MCS04) - regoffset = 0xc90; - if (regoffset == RTXAGC_B_MCS15_MCS12 || - regoffset == RTXAGC_B_MCS07_MCS04) - regoffset = 0xc98; - for (i = 0; i < 3; i++) { - if (i != 2) - writeVal = (writeVal > 8) ? - (writeVal - 8) : 0; - else - writeVal = (writeVal > 6) ? - (writeVal - 6) : 0; - rtl_write_byte(rtlpriv, (u32)(regoffset + i), - (u8)writeVal); - } - } - } -} - -void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel) -{ - u32 writeVal[2], powerBase0[2], powerBase1[2]; - u8 index = 0; - - rtl92c_phy_get_power_base(hw, ppowerlevel, - channel, &powerBase0[0], &powerBase1[0]); - for (index = 0; index < 6; index++) { - _rtl92c_get_txpower_writeval_by_regulatory(hw, - channel, index, - &powerBase0[0], - &powerBase1[0], - &writeVal[0]); - _rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]); - } -} - -bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - bool rtstatus = true; - u8 b_reg_hwparafile = 1; - - if (rtlphy->rf_type == RF_1T1R) - rtlphy->num_total_rfpath = 1; - else - rtlphy->num_total_rfpath = 2; - if (b_reg_hwparafile == 1) - rtstatus = _rtl92c_phy_rf6052_config_parafile(hw); - return rtstatus; -} - -static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 u4_regvalue = 0; - u8 rfpath; - bool rtstatus = true; - struct bb_reg_def *pphyreg; - - for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { - pphyreg = &rtlphy->phyreg_def[rfpath]; - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV); - break; - case RF90_PATH_B: - case RF90_PATH_D: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16); - break; - } - rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); - udelay(1); - rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); - udelay(1); - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, - B3WIREADDREAALENGTH, 0x0); - udelay(1); - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); - udelay(1); - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_B: - rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw, - (enum radio_path) rfpath); - break; - case RF90_PATH_C: - break; - case RF90_PATH_D: - break; - } - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - rtl_set_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV, u4_regvalue); - break; - case RF90_PATH_B: - case RF90_PATH_D: - rtl_set_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16, u4_regvalue); - break; - } - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio[%d] Fail!!", rfpath); - goto phy_rf_cfg_fail; - } - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n"); -phy_rf_cfg_fail: - return rtstatus; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h deleted file mode 100644 index 6f987de5b441..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CU_RF_H__ -#define __RTL92CU_RF_H__ - -#define RF6052_MAX_TX_PWR 0x3F -#define RF6052_MAX_PATH 2 - -void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth); -void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); -bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw); -bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c deleted file mode 100644 index fd4a5353d216..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ /dev/null @@ -1,412 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../core.h" -#include "../usb.h" -#include "../efuse.h" -#include "../base.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "mac.h" -#include "dm.h" -#include "rf.h" -#include "sw.h" -#include "trx.h" -#include "led.h" -#include "hw.h" -#include "../rtl8192c/fw_common.h" -#include - -MODULE_AUTHOR("Georgia "); -MODULE_AUTHOR("Ziv Huang "); -MODULE_AUTHOR("Larry Finger "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); -MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); -MODULE_FIRMWARE("rtlwifi/rtl8192cufw_A.bin"); -MODULE_FIRMWARE("rtlwifi/rtl8192cufw_B.bin"); -MODULE_FIRMWARE("rtlwifi/rtl8192cufw_TMSC.bin"); - -static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int err; - - rtlpriv->dm.dm_initialgain_enable = true; - rtlpriv->dm.dm_flag = 0; - rtlpriv->dm.disable_framebursting = false; - rtlpriv->dm.thermalvalue = 0; - rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; - - /* for firmware buf */ - rtlpriv->rtlhal.pfirmware = vzalloc(0x4000); - if (!rtlpriv->rtlhal.pfirmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't alloc buffer for fw\n"); - return 1; - } - if (IS_VENDOR_UMC_A_CUT(rtlpriv->rtlhal.version) && - !IS_92C_SERIAL(rtlpriv->rtlhal.version)) { - rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_A.bin"; - } else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlpriv->rtlhal.version)) { - rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_B.bin"; - } else { - rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_TMSC.bin"; - } - /* provide name of alternative file */ - rtlpriv->cfg->alt_fw_name = "rtlwifi/rtl8192cufw.bin"; - pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name); - rtlpriv->max_fw_size = 0x4000; - err = request_firmware_nowait(THIS_MODULE, 1, - rtlpriv->cfg->fw_name, rtlpriv->io.dev, - GFP_KERNEL, hw, rtl_fw_cb); - return err; -} - -static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->rtlhal.pfirmware) { - vfree(rtlpriv->rtlhal.pfirmware); - rtlpriv->rtlhal.pfirmware = NULL; - } -} - -/* get bt coexist status */ -static bool rtl92cu_get_btc_status(void) -{ - return false; -} - -static struct rtl_hal_ops rtl8192cu_hal_ops = { - .init_sw_vars = rtl92cu_init_sw_vars, - .deinit_sw_vars = rtl92cu_deinit_sw_vars, - .read_chip_version = rtl92c_read_chip_version, - .read_eeprom_info = rtl92cu_read_eeprom_info, - .enable_interrupt = rtl92c_enable_interrupt, - .disable_interrupt = rtl92c_disable_interrupt, - .hw_init = rtl92cu_hw_init, - .hw_disable = rtl92cu_card_disable, - .set_network_type = rtl92cu_set_network_type, - .set_chk_bssid = rtl92cu_set_check_bssid, - .set_qos = rtl92c_set_qos, - .set_bcn_reg = rtl92cu_set_beacon_related_registers, - .set_bcn_intv = rtl92cu_set_beacon_interval, - .update_interrupt_mask = rtl92cu_update_interrupt_mask, - .get_hw_reg = rtl92cu_get_hw_reg, - .set_hw_reg = rtl92cu_set_hw_reg, - .update_rate_tbl = rtl92cu_update_hal_rate_tbl, - .fill_tx_desc = rtl92cu_tx_fill_desc, - .fill_fake_txdesc = rtl92cu_fill_fake_txdesc, - .fill_tx_cmddesc = rtl92cu_tx_fill_cmddesc, - .query_rx_desc = rtl92cu_rx_query_desc, - .set_channel_access = rtl92cu_update_channel_access_setting, - .radio_onoff_checking = rtl92cu_gpio_radio_on_off_checking, - .set_bw_mode = rtl92c_phy_set_bw_mode, - .switch_channel = rtl92c_phy_sw_chnl, - .dm_watchdog = rtl92c_dm_watchdog, - .scan_operation_backup = rtl_phy_scan_operation_backup, - .set_rf_power_state = rtl92cu_phy_set_rf_power_state, - .led_control = rtl92cu_led_control, - .enable_hw_sec = rtl92cu_enable_hw_security_config, - .set_key = rtl92c_set_key, - .init_sw_leds = rtl92cu_init_sw_leds, - .deinit_sw_leds = rtl92cu_deinit_sw_leds, - .get_bbreg = rtl92c_phy_query_bb_reg, - .set_bbreg = rtl92c_phy_set_bb_reg, - .get_rfreg = rtl92cu_phy_query_rf_reg, - .set_rfreg = rtl92cu_phy_set_rf_reg, - .phy_rf6052_config = rtl92cu_phy_rf6052_config, - .phy_rf6052_set_cck_txpower = rtl92cu_phy_rf6052_set_cck_txpower, - .phy_rf6052_set_ofdm_txpower = rtl92cu_phy_rf6052_set_ofdm_txpower, - .config_bb_with_headerfile = _rtl92cu_phy_config_bb_with_headerfile, - .config_bb_with_pgheaderfile = _rtl92cu_phy_config_bb_with_pgheaderfile, - .phy_lc_calibrate = _rtl92cu_phy_lc_calibrate, - .phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback, - .dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower, - .fill_h2c_cmd = rtl92c_fill_h2c_cmd, - .get_btc_status = rtl92cu_get_btc_status, -}; - -static struct rtl_mod_params rtl92cu_mod_params = { - .sw_crypto = 0, - .debug = DBG_EMERG, -}; - -module_param_named(swenc, rtl92cu_mod_params.sw_crypto, bool, 0444); -module_param_named(debug, rtl92cu_mod_params.debug, int, 0444); -MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n"); -MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)"); - -static struct rtl_hal_usbint_cfg rtl92cu_interface_cfg = { - /* rx */ - .in_ep_num = RTL92C_USB_BULK_IN_NUM, - .rx_urb_num = RTL92C_NUM_RX_URBS, - .rx_max_size = RTL92C_SIZE_MAX_RX_BUFFER, - .usb_rx_hdl = rtl8192cu_rx_hdl, - .usb_rx_segregate_hdl = NULL, /* rtl8192c_rx_segregate_hdl; */ - /* tx */ - .usb_tx_cleanup = rtl8192c_tx_cleanup, - .usb_tx_post_hdl = rtl8192c_tx_post_hdl, - .usb_tx_aggregate_hdl = rtl8192c_tx_aggregate_hdl, - /* endpoint mapping */ - .usb_endpoint_mapping = rtl8192cu_endpoint_mapping, - .usb_mq_to_hwq = rtl8192cu_mq_to_hwq, -}; - -static struct rtl_hal_cfg rtl92cu_hal_cfg = { - .name = "rtl92c_usb", - .fw_name = "rtlwifi/rtl8192cufw.bin", - .ops = &rtl8192cu_hal_ops, - .mod_params = &rtl92cu_mod_params, - .usb_interface_cfg = &rtl92cu_interface_cfg, - - .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, - .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, - .maps[SYS_CLK] = REG_SYS_CLKR, - .maps[MAC_RCR_AM] = AM, - .maps[MAC_RCR_AB] = AB, - .maps[MAC_RCR_ACRC32] = ACRC32, - .maps[MAC_RCR_ACF] = ACF, - .maps[MAC_RCR_AAP] = AAP, - - .maps[EFUSE_TEST] = REG_EFUSE_TEST, - .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_CLK] = 0, - .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_PWC_EV12V] = PWC_EV12V, - .maps[EFUSE_FEN_ELDR] = FEN_ELDR, - .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, - .maps[EFUSE_ANA8M] = EFUSE_ANA8M, - .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, - .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, - .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, - - .maps[RWCAM] = REG_CAMCMD, - .maps[WCAMI] = REG_CAMWRITE, - .maps[RCAMO] = REG_CAMREAD, - .maps[CAMDBG] = REG_CAMDBG, - .maps[SECR] = REG_SECCFG, - .maps[SEC_CAM_NONE] = CAM_NONE, - .maps[SEC_CAM_WEP40] = CAM_WEP40, - .maps[SEC_CAM_TKIP] = CAM_TKIP, - .maps[SEC_CAM_AES] = CAM_AES, - .maps[SEC_CAM_WEP104] = CAM_WEP104, - - .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, - .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, - .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, - .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, - .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, - .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, - .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, - .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, - .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, - .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, - .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, - .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, - .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, - .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, - .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, - .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, - - .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, - .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, - .maps[RTL_IMR_BCNINT] = IMR_BCNINT, - .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, - .maps[RTL_IMR_RDU] = IMR_RDU, - .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, - .maps[RTL_IMR_BDOK] = IMR_BDOK, - .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, - .maps[RTL_IMR_TBDER] = IMR_TBDER, - .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, - .maps[RTL_IMR_TBDOK] = IMR_TBDOK, - .maps[RTL_IMR_BKDOK] = IMR_BKDOK, - .maps[RTL_IMR_BEDOK] = IMR_BEDOK, - .maps[RTL_IMR_VIDOK] = IMR_VIDOK, - .maps[RTL_IMR_VODOK] = IMR_VODOK, - .maps[RTL_IMR_ROK] = IMR_ROK, - .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), - - .maps[RTL_RC_CCK_RATE1M] = DESC_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC_RATE54M, - .maps[RTL_RC_HT_RATEMCS7] = DESC_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC_RATEMCS15, -}; - -#define USB_VENDER_ID_REALTEK 0x0bda - -/* 2010-10-19 DID_USB_V3.4 */ -static struct usb_device_id rtl8192c_usb_ids[] = { - - /*=== Realtek demoboard ===*/ - /* Default ID */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8191, rtl92cu_hal_cfg)}, - - /****** 8188CU ********/ - /* RTL8188CTV */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x018a, rtl92cu_hal_cfg)}, - /* 8188CE-VAU USB minCard */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8170, rtl92cu_hal_cfg)}, - /* 8188cu 1*1 dongle */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8176, rtl92cu_hal_cfg)}, - /* 8188cu 1*1 dongle, (b/g mode only) */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8177, rtl92cu_hal_cfg)}, - /* 8188cu Slim Solo */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817a, rtl92cu_hal_cfg)}, - /* 8188cu Slim Combo */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817b, rtl92cu_hal_cfg)}, - /* 8188RU High-power USB Dongle */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817d, rtl92cu_hal_cfg)}, - /* 8188CE-VAU USB minCard (b/g mode only) */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817e, rtl92cu_hal_cfg)}, - /* 8188RU in Alfa AWUS036NHR */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)}, - /* RTL8188CUS-VL */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)}, - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x819a, rtl92cu_hal_cfg)}, - /* 8188 Combo for BC4 */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)}, - - /****** 8192CU ********/ - /* 8192cu 2*2 */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8178, rtl92cu_hal_cfg)}, - /* 8192CE-VAU USB minCard */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817c, rtl92cu_hal_cfg)}, - - /*=== Customer ID ===*/ - /****** 8188CU ********/ - {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/ - {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/ - {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ - {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ - {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ - {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/ - {RTL_USB_DEVICE(0x0846, 0x9043, rtl92cu_hal_cfg)}, /*NG WNA1000Mv2*/ - {RTL_USB_DEVICE(0x0b05, 0x17ba, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/ - {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/ - {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ - {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/ - {RTL_USB_DEVICE(0x0df6, 0x0070, rtl92cu_hal_cfg)}, /*Sitecom - 150N */ - {RTL_USB_DEVICE(0x0df6, 0x0077, rtl92cu_hal_cfg)}, /*Sitecom-WLA2100V2*/ - {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/ - {RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/ - /* HP - Lite-On ,8188CUS Slim Combo */ - {RTL_USB_DEVICE(0x103c, 0x1629, rtl92cu_hal_cfg)}, - {RTL_USB_DEVICE(0x13d3, 0x3357, rtl92cu_hal_cfg)}, /* AzureWave */ - {RTL_USB_DEVICE(0x2001, 0x3308, rtl92cu_hal_cfg)}, /*D-Link - Alpha*/ - {RTL_USB_DEVICE(0x2019, 0x4902, rtl92cu_hal_cfg)}, /*Planex - Etop*/ - {RTL_USB_DEVICE(0x2019, 0xab2a, rtl92cu_hal_cfg)}, /*Planex - Abocom*/ - /*SW-WF02-AD15 -Abocom*/ - {RTL_USB_DEVICE(0x2019, 0xab2e, rtl92cu_hal_cfg)}, - {RTL_USB_DEVICE(0x2019, 0xed17, rtl92cu_hal_cfg)}, /*PCI - Edimax*/ - {RTL_USB_DEVICE(0x20f4, 0x648b, rtl92cu_hal_cfg)}, /*TRENDnet - Cameo*/ - {RTL_USB_DEVICE(0x7392, 0x7811, rtl92cu_hal_cfg)}, /*Edimax - Edimax*/ - {RTL_USB_DEVICE(0x13d3, 0x3358, rtl92cu_hal_cfg)}, /*Azwave 8188CE-VAU*/ - /* Russian customer -Azwave (8188CE-VAU b/g mode only) */ - {RTL_USB_DEVICE(0x13d3, 0x3359, rtl92cu_hal_cfg)}, - {RTL_USB_DEVICE(0x4855, 0x0090, rtl92cu_hal_cfg)}, /* Feixun */ - {RTL_USB_DEVICE(0x4855, 0x0091, rtl92cu_hal_cfg)}, /* NetweeN-Feixun */ - {RTL_USB_DEVICE(0x9846, 0x9041, rtl92cu_hal_cfg)}, /* Netgear Cameo */ - - /****** 8188 RU ********/ - /* Netcore */ - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x317f, rtl92cu_hal_cfg)}, - - /****** 8188CUS Slim Solo********/ - {RTL_USB_DEVICE(0x04f2, 0xaff7, rtl92cu_hal_cfg)}, /*Xavi*/ - {RTL_USB_DEVICE(0x04f2, 0xaff9, rtl92cu_hal_cfg)}, /*Xavi*/ - {RTL_USB_DEVICE(0x04f2, 0xaffa, rtl92cu_hal_cfg)}, /*Xavi*/ - - /****** 8188CUS Slim Combo ********/ - {RTL_USB_DEVICE(0x04f2, 0xaff8, rtl92cu_hal_cfg)}, /*Xavi*/ - {RTL_USB_DEVICE(0x04f2, 0xaffb, rtl92cu_hal_cfg)}, /*Xavi*/ - {RTL_USB_DEVICE(0x04f2, 0xaffc, rtl92cu_hal_cfg)}, /*Xavi*/ - {RTL_USB_DEVICE(0x2019, 0x1201, rtl92cu_hal_cfg)}, /*Planex-Vencer*/ - - /****** 8192CU ********/ - {RTL_USB_DEVICE(0x050d, 0x1004, rtl92cu_hal_cfg)}, /*Belcom-SurfN300*/ - {RTL_USB_DEVICE(0x050d, 0x2102, rtl92cu_hal_cfg)}, /*Belcom-Sercomm*/ - {RTL_USB_DEVICE(0x050d, 0x2103, rtl92cu_hal_cfg)}, /*Belcom-Edimax*/ - {RTL_USB_DEVICE(0x0586, 0x341f, rtl92cu_hal_cfg)}, /*Zyxel -Abocom*/ - {RTL_USB_DEVICE(0x07aa, 0x0056, rtl92cu_hal_cfg)}, /*ATKK-Gemtek*/ - {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/ - {RTL_USB_DEVICE(0x0846, 0x9021, rtl92cu_hal_cfg)}, /*Netgear-Sercomm*/ - {RTL_USB_DEVICE(0x0846, 0xf001, rtl92cu_hal_cfg)}, /*On Netwrks N300MA*/ - {RTL_USB_DEVICE(0x0b05, 0x17ab, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/ - {RTL_USB_DEVICE(0x0bda, 0x8186, rtl92cu_hal_cfg)}, /*Realtek 92CE-VAU*/ - {RTL_USB_DEVICE(0x0df6, 0x0061, rtl92cu_hal_cfg)}, /*Sitecom-Edimax*/ - {RTL_USB_DEVICE(0x0e66, 0x0019, rtl92cu_hal_cfg)}, /*Hawking-Edimax*/ - {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/ - {RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ - {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ - {RTL_USB_DEVICE(0x2001, 0x330d, rtl92cu_hal_cfg)}, /*D-Link DWA-131 */ - {RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/ - {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/ - {RTL_USB_DEVICE(0x2357, 0x0100, rtl92cu_hal_cfg)}, /*TP-Link WN8200ND*/ - {RTL_USB_DEVICE(0x7392, 0x7822, rtl92cu_hal_cfg)}, /*Edimax -Edimax*/ - {} -}; - -MODULE_DEVICE_TABLE(usb, rtl8192c_usb_ids); - -static int rtl8192cu_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return rtl_usb_probe(intf, id, &rtl92cu_hal_cfg); -} - -static struct usb_driver rtl8192cu_driver = { - .name = "rtl8192cu", - .probe = rtl8192cu_probe, - .disconnect = rtl_usb_disconnect, - .id_table = rtl8192c_usb_ids, - -#ifdef CONFIG_PM - /* .suspend = rtl_usb_suspend, */ - /* .resume = rtl_usb_resume, */ - /* .reset_resume = rtl8192c_resume, */ -#endif /* CONFIG_PM */ - .disable_hub_initiated_lpm = 1, -}; - -module_usb_driver(rtl8192cu_driver); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h deleted file mode 100644 index a1310abd0d54..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h +++ /dev/null @@ -1,53 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CU_SW_H__ -#define __RTL92CU_SW_H__ - -#define EFUSE_MAX_SECTION 16 - -void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *powerlevel); -void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); -bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); -bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); -void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t); -void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data); -bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); -u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask); -void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/table.c b/drivers/net/wireless/rtlwifi/rtl8192cu/table.c deleted file mode 100644 index 7903c154de00..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/table.c +++ /dev/null @@ -1,1888 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "table.h" - -u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH] = { - 0x024, 0x0011800f, - 0x028, 0x00ffdb83, - 0x800, 0x80040002, - 0x804, 0x00000003, - 0x808, 0x0000fc00, - 0x80c, 0x0000000a, - 0x810, 0x10000330, - 0x814, 0x020c3d10, - 0x818, 0x02200385, - 0x81c, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390004, - 0x828, 0x01000100, - 0x82c, 0x00390004, - 0x830, 0x27272727, - 0x834, 0x27272727, - 0x838, 0x27272727, - 0x83c, 0x27272727, - 0x840, 0x00010000, - 0x844, 0x00010000, - 0x848, 0x27272727, - 0x84c, 0x27272727, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x569a569a, - 0x85c, 0x0c1b25a4, - 0x860, 0x66e60230, - 0x864, 0x061f0130, - 0x868, 0x27272727, - 0x86c, 0x2b2b2b27, - 0x870, 0x07000700, - 0x874, 0x22184000, - 0x878, 0x08080808, - 0x87c, 0x00000000, - 0x880, 0xc0083070, - 0x884, 0x000004d5, - 0x888, 0x00000000, - 0x88c, 0xcc0000c0, - 0x890, 0x00000800, - 0x894, 0xfffffffe, - 0x898, 0x40302010, - 0x89c, 0x00706050, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90c, 0x81121313, - 0xa00, 0x00d047c8, - 0xa04, 0x80ff000c, - 0xa08, 0x8c838300, - 0xa0c, 0x2e68120f, - 0xa10, 0x9500bb78, - 0xa14, 0x11144028, - 0xa18, 0x00881117, - 0xa1c, 0x89140f00, - 0xa20, 0x1a1b0000, - 0xa24, 0x090e1317, - 0xa28, 0x00000204, - 0xa2c, 0x00d30000, - 0xa70, 0x101fbf00, - 0xa74, 0x00000007, - 0xc00, 0x48071d40, - 0xc04, 0x03a05633, - 0xc08, 0x000000e4, - 0xc0c, 0x6c6c6c6c, - 0xc10, 0x08800000, - 0xc14, 0x40000100, - 0xc18, 0x08800000, - 0xc1c, 0x40000100, - 0xc20, 0x00000000, - 0xc24, 0x00000000, - 0xc28, 0x00000000, - 0xc2c, 0x00000000, - 0xc30, 0x69e9ac44, - 0xc34, 0x469652cf, - 0xc38, 0x49795994, - 0xc3c, 0x0a97971c, - 0xc40, 0x1f7c403f, - 0xc44, 0x000100b7, - 0xc48, 0xec020107, - 0xc4c, 0x007f037f, - 0xc50, 0x69543420, - 0xc54, 0x43bc0094, - 0xc58, 0x69543420, - 0xc5c, 0x433c0094, - 0xc60, 0x00000000, - 0xc64, 0x5116848b, - 0xc68, 0x47c00bff, - 0xc6c, 0x00000036, - 0xc70, 0x2c7f000d, - 0xc74, 0x2186115b, - 0xc78, 0x0000001f, - 0xc7c, 0x00b99612, - 0xc80, 0x40000100, - 0xc84, 0x20f60000, - 0xc88, 0x40000100, - 0xc8c, 0xa0e40000, - 0xc90, 0x00121820, - 0xc94, 0x00000000, - 0xc98, 0x00121820, - 0xc9c, 0x00007f7f, - 0xca0, 0x00000000, - 0xca4, 0x00000080, - 0xca8, 0x00000000, - 0xcac, 0x00000000, - 0xcb0, 0x00000000, - 0xcb4, 0x00000000, - 0xcb8, 0x00000000, - 0xcbc, 0x28000000, - 0xcc0, 0x00000000, - 0xcc4, 0x00000000, - 0xcc8, 0x00000000, - 0xccc, 0x00000000, - 0xcd0, 0x00000000, - 0xcd4, 0x00000000, - 0xcd8, 0x64b22427, - 0xcdc, 0x00766932, - 0xce0, 0x00222222, - 0xce4, 0x00000000, - 0xce8, 0x37644302, - 0xcec, 0x2f97d40c, - 0xd00, 0x00080740, - 0xd04, 0x00020403, - 0xd08, 0x0000907f, - 0xd0c, 0x20010201, - 0xd10, 0xa0633333, - 0xd14, 0x3333bc43, - 0xd18, 0x7a8f5b6b, - 0xd2c, 0xcc979975, - 0xd30, 0x00000000, - 0xd34, 0x80608000, - 0xd38, 0x00000000, - 0xd3c, 0x00027293, - 0xd40, 0x00000000, - 0xd44, 0x00000000, - 0xd48, 0x00000000, - 0xd4c, 0x00000000, - 0xd50, 0x6437140a, - 0xd54, 0x00000000, - 0xd58, 0x00000000, - 0xd5c, 0x30032064, - 0xd60, 0x4653de68, - 0xd64, 0x04518a3c, - 0xd68, 0x00002101, - 0xd6c, 0x2a201c16, - 0xd70, 0x1812362e, - 0xd74, 0x322c2220, - 0xd78, 0x000e3c24, - 0xe00, 0x2a2a2a2a, - 0xe04, 0x2a2a2a2a, - 0xe08, 0x03902a2a, - 0xe10, 0x2a2a2a2a, - 0xe14, 0x2a2a2a2a, - 0xe18, 0x2a2a2a2a, - 0xe1c, 0x2a2a2a2a, - 0xe28, 0x00000000, - 0xe30, 0x1000dc1f, - 0xe34, 0x10008c1f, - 0xe38, 0x02140102, - 0xe3c, 0x681604c2, - 0xe40, 0x01007c00, - 0xe44, 0x01004800, - 0xe48, 0xfb000000, - 0xe4c, 0x000028d1, - 0xe50, 0x1000dc1f, - 0xe54, 0x10008c1f, - 0xe58, 0x02140102, - 0xe5c, 0x28160d05, - 0xe60, 0x00000010, - 0xe68, 0x001b25a4, - 0xe6c, 0x63db25a4, - 0xe70, 0x63db25a4, - 0xe74, 0x0c1b25a4, - 0xe78, 0x0c1b25a4, - 0xe7c, 0x0c1b25a4, - 0xe80, 0x0c1b25a4, - 0xe84, 0x63db25a4, - 0xe88, 0x0c1b25a4, - 0xe8c, 0x63db25a4, - 0xed0, 0x63db25a4, - 0xed4, 0x63db25a4, - 0xed8, 0x63db25a4, - 0xedc, 0x001b25a4, - 0xee0, 0x001b25a4, - 0xeec, 0x6fdb25a4, - 0xf14, 0x00000003, - 0xf4c, 0x00000000, - 0xf00, 0x00000300, -}; - -u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = { - 0x024, 0x0011800f, - 0x028, 0x00ffdb83, - 0x800, 0x80040000, - 0x804, 0x00000001, - 0x808, 0x0000fc00, - 0x80c, 0x0000000a, - 0x810, 0x10000330, - 0x814, 0x020c3d10, - 0x818, 0x02200385, - 0x81c, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390004, - 0x828, 0x00000000, - 0x82c, 0x00000000, - 0x830, 0x00000000, - 0x834, 0x00000000, - 0x838, 0x00000000, - 0x83c, 0x00000000, - 0x840, 0x00010000, - 0x844, 0x00000000, - 0x848, 0x00000000, - 0x84c, 0x00000000, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x569a569a, - 0x85c, 0x001b25a4, - 0x860, 0x66e60230, - 0x864, 0x061f0130, - 0x868, 0x00000000, - 0x86c, 0x32323200, - 0x870, 0x07000700, - 0x874, 0x22004000, - 0x878, 0x00000808, - 0x87c, 0x00000000, - 0x880, 0xc0083070, - 0x884, 0x000004d5, - 0x888, 0x00000000, - 0x88c, 0xccc000c0, - 0x890, 0x00000800, - 0x894, 0xfffffffe, - 0x898, 0x40302010, - 0x89c, 0x00706050, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90c, 0x81121111, - 0xa00, 0x00d047c8, - 0xa04, 0x80ff000c, - 0xa08, 0x8c838300, - 0xa0c, 0x2e68120f, - 0xa10, 0x9500bb78, - 0xa14, 0x11144028, - 0xa18, 0x00881117, - 0xa1c, 0x89140f00, - 0xa20, 0x1a1b0000, - 0xa24, 0x090e1317, - 0xa28, 0x00000204, - 0xa2c, 0x00d30000, - 0xa70, 0x101fbf00, - 0xa74, 0x00000007, - 0xc00, 0x48071d40, - 0xc04, 0x03a05611, - 0xc08, 0x000000e4, - 0xc0c, 0x6c6c6c6c, - 0xc10, 0x08800000, - 0xc14, 0x40000100, - 0xc18, 0x08800000, - 0xc1c, 0x40000100, - 0xc20, 0x00000000, - 0xc24, 0x00000000, - 0xc28, 0x00000000, - 0xc2c, 0x00000000, - 0xc30, 0x69e9ac44, - 0xc34, 0x469652cf, - 0xc38, 0x49795994, - 0xc3c, 0x0a97971c, - 0xc40, 0x1f7c403f, - 0xc44, 0x000100b7, - 0xc48, 0xec020107, - 0xc4c, 0x007f037f, - 0xc50, 0x69543420, - 0xc54, 0x43bc0094, - 0xc58, 0x69543420, - 0xc5c, 0x433c0094, - 0xc60, 0x00000000, - 0xc64, 0x5116848b, - 0xc68, 0x47c00bff, - 0xc6c, 0x00000036, - 0xc70, 0x2c7f000d, - 0xc74, 0x018610db, - 0xc78, 0x0000001f, - 0xc7c, 0x00b91612, - 0xc80, 0x40000100, - 0xc84, 0x20f60000, - 0xc88, 0x40000100, - 0xc8c, 0x20200000, - 0xc90, 0x00121820, - 0xc94, 0x00000000, - 0xc98, 0x00121820, - 0xc9c, 0x00007f7f, - 0xca0, 0x00000000, - 0xca4, 0x00000080, - 0xca8, 0x00000000, - 0xcac, 0x00000000, - 0xcb0, 0x00000000, - 0xcb4, 0x00000000, - 0xcb8, 0x00000000, - 0xcbc, 0x28000000, - 0xcc0, 0x00000000, - 0xcc4, 0x00000000, - 0xcc8, 0x00000000, - 0xccc, 0x00000000, - 0xcd0, 0x00000000, - 0xcd4, 0x00000000, - 0xcd8, 0x64b22427, - 0xcdc, 0x00766932, - 0xce0, 0x00222222, - 0xce4, 0x00000000, - 0xce8, 0x37644302, - 0xcec, 0x2f97d40c, - 0xd00, 0x00000740, - 0xd04, 0x00020401, - 0xd08, 0x0000907f, - 0xd0c, 0x20010201, - 0xd10, 0xa0633333, - 0xd14, 0x3333bc43, - 0xd18, 0x7a8f5b6b, - 0xd2c, 0xcc979975, - 0xd30, 0x00000000, - 0xd34, 0x80608000, - 0xd38, 0x00000000, - 0xd3c, 0x00027293, - 0xd40, 0x00000000, - 0xd44, 0x00000000, - 0xd48, 0x00000000, - 0xd4c, 0x00000000, - 0xd50, 0x6437140a, - 0xd54, 0x00000000, - 0xd58, 0x00000000, - 0xd5c, 0x30032064, - 0xd60, 0x4653de68, - 0xd64, 0x04518a3c, - 0xd68, 0x00002101, - 0xd6c, 0x2a201c16, - 0xd70, 0x1812362e, - 0xd74, 0x322c2220, - 0xd78, 0x000e3c24, - 0xe00, 0x2a2a2a2a, - 0xe04, 0x2a2a2a2a, - 0xe08, 0x03902a2a, - 0xe10, 0x2a2a2a2a, - 0xe14, 0x2a2a2a2a, - 0xe18, 0x2a2a2a2a, - 0xe1c, 0x2a2a2a2a, - 0xe28, 0x00000000, - 0xe30, 0x1000dc1f, - 0xe34, 0x10008c1f, - 0xe38, 0x02140102, - 0xe3c, 0x681604c2, - 0xe40, 0x01007c00, - 0xe44, 0x01004800, - 0xe48, 0xfb000000, - 0xe4c, 0x000028d1, - 0xe50, 0x1000dc1f, - 0xe54, 0x10008c1f, - 0xe58, 0x02140102, - 0xe5c, 0x28160d05, - 0xe60, 0x00000008, - 0xe68, 0x001b25a4, - 0xe6c, 0x631b25a0, - 0xe70, 0x631b25a0, - 0xe74, 0x081b25a0, - 0xe78, 0x081b25a0, - 0xe7c, 0x081b25a0, - 0xe80, 0x081b25a0, - 0xe84, 0x631b25a0, - 0xe88, 0x081b25a0, - 0xe8c, 0x631b25a0, - 0xed0, 0x631b25a0, - 0xed4, 0x631b25a0, - 0xed8, 0x631b25a0, - 0xedc, 0x001b25a0, - 0xee0, 0x001b25a0, - 0xeec, 0x6b1b25a0, - 0xf14, 0x00000003, - 0xf4c, 0x00000000, - 0xf00, 0x00000300, -}; - -u32 RTL8192CUPHY_REG_ARRAY_PG[RTL8192CUPHY_REG_ARRAY_PGLENGTH] = { - 0xe00, 0xffffffff, 0x07090c0c, - 0xe04, 0xffffffff, 0x01020405, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x0b0c0c0e, - 0xe14, 0xffffffff, 0x01030506, - 0xe18, 0xffffffff, 0x0b0c0d0e, - 0xe1c, 0xffffffff, 0x01030509, - 0x830, 0xffffffff, 0x07090c0c, - 0x834, 0xffffffff, 0x01020405, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x0b0c0d0e, - 0x848, 0xffffffff, 0x01030509, - 0x84c, 0xffffffff, 0x0b0c0d0e, - 0x868, 0xffffffff, 0x01030509, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x06060606, - 0xe14, 0xffffffff, 0x00020406, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x06060606, - 0x848, 0xffffffff, 0x00020406, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, -}; - -u32 RTL8192CURADIOA_2TARRAY[RTL8192CURADIOA_2TARRAYLENGTH] = { - 0x000, 0x00030159, - 0x001, 0x00031284, - 0x002, 0x00098000, - 0x003, 0x00018c63, - 0x004, 0x000210e7, - 0x009, 0x0002044f, - 0x00a, 0x0001adb1, - 0x00b, 0x00054867, - 0x00c, 0x0008992e, - 0x00d, 0x0000e52c, - 0x00e, 0x00039ce7, - 0x00f, 0x00000451, - 0x019, 0x00000000, - 0x01a, 0x00010255, - 0x01b, 0x00060a00, - 0x01c, 0x000fc378, - 0x01d, 0x000a1250, - 0x01e, 0x0004445f, - 0x01f, 0x00080001, - 0x020, 0x0000b614, - 0x021, 0x0006c000, - 0x022, 0x00000000, - 0x023, 0x00001558, - 0x024, 0x00000060, - 0x025, 0x00000483, - 0x026, 0x0004f000, - 0x027, 0x000ec7d9, - 0x028, 0x000577c0, - 0x029, 0x00004783, - 0x02a, 0x00000001, - 0x02b, 0x00021334, - 0x02a, 0x00000000, - 0x02b, 0x00000054, - 0x02a, 0x00000001, - 0x02b, 0x00000808, - 0x02b, 0x00053333, - 0x02c, 0x0000000c, - 0x02a, 0x00000002, - 0x02b, 0x00000808, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000003, - 0x02b, 0x00000808, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000004, - 0x02b, 0x00000808, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000005, - 0x02b, 0x00000808, - 0x02b, 0x00073333, - 0x02c, 0x0000000d, - 0x02a, 0x00000006, - 0x02b, 0x00000709, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000007, - 0x02b, 0x00000709, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000008, - 0x02b, 0x0000060a, - 0x02b, 0x0004b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000009, - 0x02b, 0x0000060a, - 0x02b, 0x00053333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000a, - 0x02b, 0x0000060a, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000b, - 0x02b, 0x0000060a, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000c, - 0x02b, 0x0000060a, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000d, - 0x02b, 0x0000060a, - 0x02b, 0x00073333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000e, - 0x02b, 0x0000050b, - 0x02b, 0x00066666, - 0x02c, 0x0000001a, - 0x02a, 0x000e0000, - 0x010, 0x0004000f, - 0x011, 0x000e31fc, - 0x010, 0x0006000f, - 0x011, 0x000ff9f8, - 0x010, 0x0002000f, - 0x011, 0x000203f9, - 0x010, 0x0003000f, - 0x011, 0x000ff500, - 0x010, 0x00000000, - 0x011, 0x00000000, - 0x010, 0x0008000f, - 0x011, 0x0003f100, - 0x010, 0x0009000f, - 0x011, 0x00023100, - 0x012, 0x00032000, - 0x012, 0x00071000, - 0x012, 0x000b0000, - 0x012, 0x000fc000, - 0x013, 0x000287b3, - 0x013, 0x000244b7, - 0x013, 0x000204ab, - 0x013, 0x0001c49f, - 0x013, 0x00018493, - 0x013, 0x0001429b, - 0x013, 0x00010299, - 0x013, 0x0000c29c, - 0x013, 0x000081a0, - 0x013, 0x000040ac, - 0x013, 0x00000020, - 0x014, 0x0001944c, - 0x014, 0x00059444, - 0x014, 0x0009944c, - 0x014, 0x000d9444, - 0x015, 0x0000f424, - 0x015, 0x0004f424, - 0x015, 0x0008f424, - 0x015, 0x000cf424, - 0x016, 0x000e0330, - 0x016, 0x000a0330, - 0x016, 0x00060330, - 0x016, 0x00020330, - 0x000, 0x00010159, - 0x018, 0x0000f401, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01f, 0x00080003, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01e, 0x00044457, - 0x01f, 0x00080000, - 0x000, 0x00030159, -}; - -u32 RTL8192CU_RADIOB_2TARRAY[RTL8192CURADIOB_2TARRAYLENGTH] = { - 0x000, 0x00030159, - 0x001, 0x00031284, - 0x002, 0x00098000, - 0x003, 0x00018c63, - 0x004, 0x000210e7, - 0x009, 0x0002044f, - 0x00a, 0x0001adb1, - 0x00b, 0x00054867, - 0x00c, 0x0008992e, - 0x00d, 0x0000e52c, - 0x00e, 0x00039ce7, - 0x00f, 0x00000451, - 0x012, 0x00032000, - 0x012, 0x00071000, - 0x012, 0x000b0000, - 0x012, 0x000fc000, - 0x013, 0x000287af, - 0x013, 0x000244b7, - 0x013, 0x000204ab, - 0x013, 0x0001c49f, - 0x013, 0x00018493, - 0x013, 0x00014297, - 0x013, 0x00010295, - 0x013, 0x0000c298, - 0x013, 0x0000819c, - 0x013, 0x000040a8, - 0x013, 0x0000001c, - 0x014, 0x0001944c, - 0x014, 0x00059444, - 0x014, 0x0009944c, - 0x014, 0x000d9444, - 0x015, 0x0000f424, - 0x015, 0x0004f424, - 0x015, 0x0008f424, - 0x015, 0x000cf424, - 0x016, 0x000e0330, - 0x016, 0x000a0330, - 0x016, 0x00060330, - 0x016, 0x00020330, -}; - -u32 RTL8192CU_RADIOA_1TARRAY[RTL8192CURADIOA_1TARRAYLENGTH] = { - 0x000, 0x00030159, - 0x001, 0x00031284, - 0x002, 0x00098000, - 0x003, 0x00018c63, - 0x004, 0x000210e7, - 0x009, 0x0002044f, - 0x00a, 0x0001adb1, - 0x00b, 0x00054867, - 0x00c, 0x0008992e, - 0x00d, 0x0000e52c, - 0x00e, 0x00039ce7, - 0x00f, 0x00000451, - 0x019, 0x00000000, - 0x01a, 0x00010255, - 0x01b, 0x00060a00, - 0x01c, 0x000fc378, - 0x01d, 0x000a1250, - 0x01e, 0x0004445f, - 0x01f, 0x00080001, - 0x020, 0x0000b614, - 0x021, 0x0006c000, - 0x022, 0x00000000, - 0x023, 0x00001558, - 0x024, 0x00000060, - 0x025, 0x00000483, - 0x026, 0x0004f000, - 0x027, 0x000ec7d9, - 0x028, 0x000577c0, - 0x029, 0x00004783, - 0x02a, 0x00000001, - 0x02b, 0x00021334, - 0x02a, 0x00000000, - 0x02b, 0x00000054, - 0x02a, 0x00000001, - 0x02b, 0x00000808, - 0x02b, 0x00053333, - 0x02c, 0x0000000c, - 0x02a, 0x00000002, - 0x02b, 0x00000808, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000003, - 0x02b, 0x00000808, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000004, - 0x02b, 0x00000808, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000005, - 0x02b, 0x00000808, - 0x02b, 0x00073333, - 0x02c, 0x0000000d, - 0x02a, 0x00000006, - 0x02b, 0x00000709, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000007, - 0x02b, 0x00000709, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000008, - 0x02b, 0x0000060a, - 0x02b, 0x0004b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000009, - 0x02b, 0x0000060a, - 0x02b, 0x00053333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000a, - 0x02b, 0x0000060a, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000b, - 0x02b, 0x0000060a, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000c, - 0x02b, 0x0000060a, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000d, - 0x02b, 0x0000060a, - 0x02b, 0x00073333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000e, - 0x02b, 0x0000050b, - 0x02b, 0x00066666, - 0x02c, 0x0000001a, - 0x02a, 0x000e0000, - 0x010, 0x0004000f, - 0x011, 0x000e31fc, - 0x010, 0x0006000f, - 0x011, 0x000ff9f8, - 0x010, 0x0002000f, - 0x011, 0x000203f9, - 0x010, 0x0003000f, - 0x011, 0x000ff500, - 0x010, 0x00000000, - 0x011, 0x00000000, - 0x010, 0x0008000f, - 0x011, 0x0003f100, - 0x010, 0x0009000f, - 0x011, 0x00023100, - 0x012, 0x00032000, - 0x012, 0x00071000, - 0x012, 0x000b0000, - 0x012, 0x000fc000, - 0x013, 0x000287b3, - 0x013, 0x000244b7, - 0x013, 0x000204ab, - 0x013, 0x0001c49f, - 0x013, 0x00018493, - 0x013, 0x0001429b, - 0x013, 0x00010299, - 0x013, 0x0000c29c, - 0x013, 0x000081a0, - 0x013, 0x000040ac, - 0x013, 0x00000020, - 0x014, 0x0001944c, - 0x014, 0x00059444, - 0x014, 0x0009944c, - 0x014, 0x000d9444, - 0x015, 0x0000f405, - 0x015, 0x0004f405, - 0x015, 0x0008f405, - 0x015, 0x000cf405, - 0x016, 0x000e0330, - 0x016, 0x000a0330, - 0x016, 0x00060330, - 0x016, 0x00020330, - 0x000, 0x00010159, - 0x018, 0x0000f401, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01f, 0x00080003, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01e, 0x00044457, - 0x01f, 0x00080000, - 0x000, 0x00030159, -}; - -u32 RTL8192CU_RADIOB_1TARRAY[RTL8192CURADIOB_1TARRAYLENGTH] = { - 0x0, -}; - -u32 RTL8192CUMAC_2T_ARRAY[RTL8192CUMAC_2T_ARRAYLENGTH] = { - 0x420, 0x00000080, - 0x423, 0x00000000, - 0x430, 0x00000000, - 0x431, 0x00000000, - 0x432, 0x00000000, - 0x433, 0x00000001, - 0x434, 0x00000004, - 0x435, 0x00000005, - 0x436, 0x00000006, - 0x437, 0x00000007, - 0x438, 0x00000000, - 0x439, 0x00000000, - 0x43a, 0x00000000, - 0x43b, 0x00000001, - 0x43c, 0x00000004, - 0x43d, 0x00000005, - 0x43e, 0x00000006, - 0x43f, 0x00000007, - 0x440, 0x0000005d, - 0x441, 0x00000001, - 0x442, 0x00000000, - 0x444, 0x00000015, - 0x445, 0x000000f0, - 0x446, 0x0000000f, - 0x447, 0x00000000, - 0x458, 0x00000041, - 0x459, 0x000000a8, - 0x45a, 0x00000072, - 0x45b, 0x000000b9, - 0x460, 0x00000066, - 0x461, 0x00000066, - 0x462, 0x00000008, - 0x463, 0x00000003, - 0x4c8, 0x000000ff, - 0x4c9, 0x00000008, - 0x4cc, 0x000000ff, - 0x4cd, 0x000000ff, - 0x4ce, 0x00000001, - 0x500, 0x00000026, - 0x501, 0x000000a2, - 0x502, 0x0000002f, - 0x503, 0x00000000, - 0x504, 0x00000028, - 0x505, 0x000000a3, - 0x506, 0x0000005e, - 0x507, 0x00000000, - 0x508, 0x0000002b, - 0x509, 0x000000a4, - 0x50a, 0x0000005e, - 0x50b, 0x00000000, - 0x50c, 0x0000004f, - 0x50d, 0x000000a4, - 0x50e, 0x00000000, - 0x50f, 0x00000000, - 0x512, 0x0000001c, - 0x514, 0x0000000a, - 0x515, 0x00000010, - 0x516, 0x0000000a, - 0x517, 0x00000010, - 0x51a, 0x00000016, - 0x524, 0x0000000f, - 0x525, 0x0000004f, - 0x546, 0x00000040, - 0x547, 0x00000000, - 0x550, 0x00000010, - 0x551, 0x00000010, - 0x559, 0x00000002, - 0x55a, 0x00000002, - 0x55d, 0x000000ff, - 0x605, 0x00000030, - 0x608, 0x0000000e, - 0x609, 0x0000002a, - 0x652, 0x00000020, - 0x63c, 0x00000008, - 0x63d, 0x00000008, - 0x63e, 0x0000000c, - 0x63f, 0x0000000c, - 0x66e, 0x00000005, - 0x700, 0x00000021, - 0x701, 0x00000043, - 0x702, 0x00000065, - 0x703, 0x00000087, - 0x708, 0x00000021, - 0x709, 0x00000043, - 0x70a, 0x00000065, - 0x70b, 0x00000087, -}; - -u32 RTL8192CUAGCTAB_2TARRAY[RTL8192CUAGCTAB_2TARRAYLENGTH] = { - 0xc78, 0x7b000001, - 0xc78, 0x7b010001, - 0xc78, 0x7b020001, - 0xc78, 0x7b030001, - 0xc78, 0x7b040001, - 0xc78, 0x7b050001, - 0xc78, 0x7a060001, - 0xc78, 0x79070001, - 0xc78, 0x78080001, - 0xc78, 0x77090001, - 0xc78, 0x760a0001, - 0xc78, 0x750b0001, - 0xc78, 0x740c0001, - 0xc78, 0x730d0001, - 0xc78, 0x720e0001, - 0xc78, 0x710f0001, - 0xc78, 0x70100001, - 0xc78, 0x6f110001, - 0xc78, 0x6e120001, - 0xc78, 0x6d130001, - 0xc78, 0x6c140001, - 0xc78, 0x6b150001, - 0xc78, 0x6a160001, - 0xc78, 0x69170001, - 0xc78, 0x68180001, - 0xc78, 0x67190001, - 0xc78, 0x661a0001, - 0xc78, 0x651b0001, - 0xc78, 0x641c0001, - 0xc78, 0x631d0001, - 0xc78, 0x621e0001, - 0xc78, 0x611f0001, - 0xc78, 0x60200001, - 0xc78, 0x49210001, - 0xc78, 0x48220001, - 0xc78, 0x47230001, - 0xc78, 0x46240001, - 0xc78, 0x45250001, - 0xc78, 0x44260001, - 0xc78, 0x43270001, - 0xc78, 0x42280001, - 0xc78, 0x41290001, - 0xc78, 0x402a0001, - 0xc78, 0x262b0001, - 0xc78, 0x252c0001, - 0xc78, 0x242d0001, - 0xc78, 0x232e0001, - 0xc78, 0x222f0001, - 0xc78, 0x21300001, - 0xc78, 0x20310001, - 0xc78, 0x06320001, - 0xc78, 0x05330001, - 0xc78, 0x04340001, - 0xc78, 0x03350001, - 0xc78, 0x02360001, - 0xc78, 0x01370001, - 0xc78, 0x00380001, - 0xc78, 0x00390001, - 0xc78, 0x003a0001, - 0xc78, 0x003b0001, - 0xc78, 0x003c0001, - 0xc78, 0x003d0001, - 0xc78, 0x003e0001, - 0xc78, 0x003f0001, - 0xc78, 0x7b400001, - 0xc78, 0x7b410001, - 0xc78, 0x7b420001, - 0xc78, 0x7b430001, - 0xc78, 0x7b440001, - 0xc78, 0x7b450001, - 0xc78, 0x7a460001, - 0xc78, 0x79470001, - 0xc78, 0x78480001, - 0xc78, 0x77490001, - 0xc78, 0x764a0001, - 0xc78, 0x754b0001, - 0xc78, 0x744c0001, - 0xc78, 0x734d0001, - 0xc78, 0x724e0001, - 0xc78, 0x714f0001, - 0xc78, 0x70500001, - 0xc78, 0x6f510001, - 0xc78, 0x6e520001, - 0xc78, 0x6d530001, - 0xc78, 0x6c540001, - 0xc78, 0x6b550001, - 0xc78, 0x6a560001, - 0xc78, 0x69570001, - 0xc78, 0x68580001, - 0xc78, 0x67590001, - 0xc78, 0x665a0001, - 0xc78, 0x655b0001, - 0xc78, 0x645c0001, - 0xc78, 0x635d0001, - 0xc78, 0x625e0001, - 0xc78, 0x615f0001, - 0xc78, 0x60600001, - 0xc78, 0x49610001, - 0xc78, 0x48620001, - 0xc78, 0x47630001, - 0xc78, 0x46640001, - 0xc78, 0x45650001, - 0xc78, 0x44660001, - 0xc78, 0x43670001, - 0xc78, 0x42680001, - 0xc78, 0x41690001, - 0xc78, 0x406a0001, - 0xc78, 0x266b0001, - 0xc78, 0x256c0001, - 0xc78, 0x246d0001, - 0xc78, 0x236e0001, - 0xc78, 0x226f0001, - 0xc78, 0x21700001, - 0xc78, 0x20710001, - 0xc78, 0x06720001, - 0xc78, 0x05730001, - 0xc78, 0x04740001, - 0xc78, 0x03750001, - 0xc78, 0x02760001, - 0xc78, 0x01770001, - 0xc78, 0x00780001, - 0xc78, 0x00790001, - 0xc78, 0x007a0001, - 0xc78, 0x007b0001, - 0xc78, 0x007c0001, - 0xc78, 0x007d0001, - 0xc78, 0x007e0001, - 0xc78, 0x007f0001, - 0xc78, 0x3800001e, - 0xc78, 0x3801001e, - 0xc78, 0x3802001e, - 0xc78, 0x3803001e, - 0xc78, 0x3804001e, - 0xc78, 0x3805001e, - 0xc78, 0x3806001e, - 0xc78, 0x3807001e, - 0xc78, 0x3808001e, - 0xc78, 0x3c09001e, - 0xc78, 0x3e0a001e, - 0xc78, 0x400b001e, - 0xc78, 0x440c001e, - 0xc78, 0x480d001e, - 0xc78, 0x4c0e001e, - 0xc78, 0x500f001e, - 0xc78, 0x5210001e, - 0xc78, 0x5611001e, - 0xc78, 0x5a12001e, - 0xc78, 0x5e13001e, - 0xc78, 0x6014001e, - 0xc78, 0x6015001e, - 0xc78, 0x6016001e, - 0xc78, 0x6217001e, - 0xc78, 0x6218001e, - 0xc78, 0x6219001e, - 0xc78, 0x621a001e, - 0xc78, 0x621b001e, - 0xc78, 0x621c001e, - 0xc78, 0x621d001e, - 0xc78, 0x621e001e, - 0xc78, 0x621f001e, -}; - -u32 RTL8192CUAGCTAB_1TARRAY[RTL8192CUAGCTAB_1TARRAYLENGTH] = { - 0xc78, 0x7b000001, - 0xc78, 0x7b010001, - 0xc78, 0x7b020001, - 0xc78, 0x7b030001, - 0xc78, 0x7b040001, - 0xc78, 0x7b050001, - 0xc78, 0x7a060001, - 0xc78, 0x79070001, - 0xc78, 0x78080001, - 0xc78, 0x77090001, - 0xc78, 0x760a0001, - 0xc78, 0x750b0001, - 0xc78, 0x740c0001, - 0xc78, 0x730d0001, - 0xc78, 0x720e0001, - 0xc78, 0x710f0001, - 0xc78, 0x70100001, - 0xc78, 0x6f110001, - 0xc78, 0x6e120001, - 0xc78, 0x6d130001, - 0xc78, 0x6c140001, - 0xc78, 0x6b150001, - 0xc78, 0x6a160001, - 0xc78, 0x69170001, - 0xc78, 0x68180001, - 0xc78, 0x67190001, - 0xc78, 0x661a0001, - 0xc78, 0x651b0001, - 0xc78, 0x641c0001, - 0xc78, 0x631d0001, - 0xc78, 0x621e0001, - 0xc78, 0x611f0001, - 0xc78, 0x60200001, - 0xc78, 0x49210001, - 0xc78, 0x48220001, - 0xc78, 0x47230001, - 0xc78, 0x46240001, - 0xc78, 0x45250001, - 0xc78, 0x44260001, - 0xc78, 0x43270001, - 0xc78, 0x42280001, - 0xc78, 0x41290001, - 0xc78, 0x402a0001, - 0xc78, 0x262b0001, - 0xc78, 0x252c0001, - 0xc78, 0x242d0001, - 0xc78, 0x232e0001, - 0xc78, 0x222f0001, - 0xc78, 0x21300001, - 0xc78, 0x20310001, - 0xc78, 0x06320001, - 0xc78, 0x05330001, - 0xc78, 0x04340001, - 0xc78, 0x03350001, - 0xc78, 0x02360001, - 0xc78, 0x01370001, - 0xc78, 0x00380001, - 0xc78, 0x00390001, - 0xc78, 0x003a0001, - 0xc78, 0x003b0001, - 0xc78, 0x003c0001, - 0xc78, 0x003d0001, - 0xc78, 0x003e0001, - 0xc78, 0x003f0001, - 0xc78, 0x7b400001, - 0xc78, 0x7b410001, - 0xc78, 0x7b420001, - 0xc78, 0x7b430001, - 0xc78, 0x7b440001, - 0xc78, 0x7b450001, - 0xc78, 0x7a460001, - 0xc78, 0x79470001, - 0xc78, 0x78480001, - 0xc78, 0x77490001, - 0xc78, 0x764a0001, - 0xc78, 0x754b0001, - 0xc78, 0x744c0001, - 0xc78, 0x734d0001, - 0xc78, 0x724e0001, - 0xc78, 0x714f0001, - 0xc78, 0x70500001, - 0xc78, 0x6f510001, - 0xc78, 0x6e520001, - 0xc78, 0x6d530001, - 0xc78, 0x6c540001, - 0xc78, 0x6b550001, - 0xc78, 0x6a560001, - 0xc78, 0x69570001, - 0xc78, 0x68580001, - 0xc78, 0x67590001, - 0xc78, 0x665a0001, - 0xc78, 0x655b0001, - 0xc78, 0x645c0001, - 0xc78, 0x635d0001, - 0xc78, 0x625e0001, - 0xc78, 0x615f0001, - 0xc78, 0x60600001, - 0xc78, 0x49610001, - 0xc78, 0x48620001, - 0xc78, 0x47630001, - 0xc78, 0x46640001, - 0xc78, 0x45650001, - 0xc78, 0x44660001, - 0xc78, 0x43670001, - 0xc78, 0x42680001, - 0xc78, 0x41690001, - 0xc78, 0x406a0001, - 0xc78, 0x266b0001, - 0xc78, 0x256c0001, - 0xc78, 0x246d0001, - 0xc78, 0x236e0001, - 0xc78, 0x226f0001, - 0xc78, 0x21700001, - 0xc78, 0x20710001, - 0xc78, 0x06720001, - 0xc78, 0x05730001, - 0xc78, 0x04740001, - 0xc78, 0x03750001, - 0xc78, 0x02760001, - 0xc78, 0x01770001, - 0xc78, 0x00780001, - 0xc78, 0x00790001, - 0xc78, 0x007a0001, - 0xc78, 0x007b0001, - 0xc78, 0x007c0001, - 0xc78, 0x007d0001, - 0xc78, 0x007e0001, - 0xc78, 0x007f0001, - 0xc78, 0x3800001e, - 0xc78, 0x3801001e, - 0xc78, 0x3802001e, - 0xc78, 0x3803001e, - 0xc78, 0x3804001e, - 0xc78, 0x3805001e, - 0xc78, 0x3806001e, - 0xc78, 0x3807001e, - 0xc78, 0x3808001e, - 0xc78, 0x3c09001e, - 0xc78, 0x3e0a001e, - 0xc78, 0x400b001e, - 0xc78, 0x440c001e, - 0xc78, 0x480d001e, - 0xc78, 0x4c0e001e, - 0xc78, 0x500f001e, - 0xc78, 0x5210001e, - 0xc78, 0x5611001e, - 0xc78, 0x5a12001e, - 0xc78, 0x5e13001e, - 0xc78, 0x6014001e, - 0xc78, 0x6015001e, - 0xc78, 0x6016001e, - 0xc78, 0x6217001e, - 0xc78, 0x6218001e, - 0xc78, 0x6219001e, - 0xc78, 0x621a001e, - 0xc78, 0x621b001e, - 0xc78, 0x621c001e, - 0xc78, 0x621d001e, - 0xc78, 0x621e001e, - 0xc78, 0x621f001e, -}; - -u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength] = { - 0x024, 0x0011800f, - 0x028, 0x00ffdb83, - 0x040, 0x000c0004, - 0x800, 0x80040000, - 0x804, 0x00000001, - 0x808, 0x0000fc00, - 0x80c, 0x0000000a, - 0x810, 0x10005388, - 0x814, 0x020c3d10, - 0x818, 0x02200385, - 0x81c, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390204, - 0x828, 0x00000000, - 0x82c, 0x00000000, - 0x830, 0x00000000, - 0x834, 0x00000000, - 0x838, 0x00000000, - 0x83c, 0x00000000, - 0x840, 0x00010000, - 0x844, 0x00000000, - 0x848, 0x00000000, - 0x84c, 0x00000000, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x569a569a, - 0x85c, 0x001b25a4, - 0x860, 0x66e60230, - 0x864, 0x061f0130, - 0x868, 0x00000000, - 0x86c, 0x20202000, - 0x870, 0x03000300, - 0x874, 0x22004000, - 0x878, 0x00000808, - 0x87c, 0x00ffc3f1, - 0x880, 0xc0083070, - 0x884, 0x000004d5, - 0x888, 0x00000000, - 0x88c, 0xccc000c0, - 0x890, 0x00000800, - 0x894, 0xfffffffe, - 0x898, 0x40302010, - 0x89c, 0x00706050, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90c, 0x81121111, - 0xa00, 0x00d047c8, - 0xa04, 0x80ff000c, - 0xa08, 0x8c838300, - 0xa0c, 0x2e68120f, - 0xa10, 0x9500bb78, - 0xa14, 0x11144028, - 0xa18, 0x00881117, - 0xa1c, 0x89140f00, - 0xa20, 0x15160000, - 0xa24, 0x070b0f12, - 0xa28, 0x00000104, - 0xa2c, 0x00d30000, - 0xa70, 0x101fbf00, - 0xa74, 0x00000007, - 0xc00, 0x48071d40, - 0xc04, 0x03a05611, - 0xc08, 0x000000e4, - 0xc0c, 0x6c6c6c6c, - 0xc10, 0x08800000, - 0xc14, 0x40000100, - 0xc18, 0x08800000, - 0xc1c, 0x40000100, - 0xc20, 0x00000000, - 0xc24, 0x00000000, - 0xc28, 0x00000000, - 0xc2c, 0x00000000, - 0xc30, 0x69e9ac44, - 0xc34, 0x469652cf, - 0xc38, 0x49795994, - 0xc3c, 0x0a97971c, - 0xc40, 0x1f7c403f, - 0xc44, 0x000100b7, - 0xc48, 0xec020107, - 0xc4c, 0x007f037f, - 0xc50, 0x6954342e, - 0xc54, 0x43bc0094, - 0xc58, 0x6954342f, - 0xc5c, 0x433c0094, - 0xc60, 0x00000000, - 0xc64, 0x5116848b, - 0xc68, 0x47c00bff, - 0xc6c, 0x00000036, - 0xc70, 0x2c46000d, - 0xc74, 0x018610db, - 0xc78, 0x0000001f, - 0xc7c, 0x00b91612, - 0xc80, 0x24000090, - 0xc84, 0x20f60000, - 0xc88, 0x24000090, - 0xc8c, 0x20200000, - 0xc90, 0x00121820, - 0xc94, 0x00000000, - 0xc98, 0x00121820, - 0xc9c, 0x00007f7f, - 0xca0, 0x00000000, - 0xca4, 0x00000080, - 0xca8, 0x00000000, - 0xcac, 0x00000000, - 0xcb0, 0x00000000, - 0xcb4, 0x00000000, - 0xcb8, 0x00000000, - 0xcbc, 0x28000000, - 0xcc0, 0x00000000, - 0xcc4, 0x00000000, - 0xcc8, 0x00000000, - 0xccc, 0x00000000, - 0xcd0, 0x00000000, - 0xcd4, 0x00000000, - 0xcd8, 0x64b22427, - 0xcdc, 0x00766932, - 0xce0, 0x00222222, - 0xce4, 0x00000000, - 0xce8, 0x37644302, - 0xcec, 0x2f97d40c, - 0xd00, 0x00080740, - 0xd04, 0x00020401, - 0xd08, 0x0000907f, - 0xd0c, 0x20010201, - 0xd10, 0xa0633333, - 0xd14, 0x3333bc43, - 0xd18, 0x7a8f5b6b, - 0xd2c, 0xcc979975, - 0xd30, 0x00000000, - 0xd34, 0x80608000, - 0xd38, 0x00000000, - 0xd3c, 0x00027293, - 0xd40, 0x00000000, - 0xd44, 0x00000000, - 0xd48, 0x00000000, - 0xd4c, 0x00000000, - 0xd50, 0x6437140a, - 0xd54, 0x00000000, - 0xd58, 0x00000000, - 0xd5c, 0x30032064, - 0xd60, 0x4653de68, - 0xd64, 0x04518a3c, - 0xd68, 0x00002101, - 0xd6c, 0x2a201c16, - 0xd70, 0x1812362e, - 0xd74, 0x322c2220, - 0xd78, 0x000e3c24, - 0xe00, 0x24242424, - 0xe04, 0x24242424, - 0xe08, 0x03902024, - 0xe10, 0x24242424, - 0xe14, 0x24242424, - 0xe18, 0x24242424, - 0xe1c, 0x24242424, - 0xe28, 0x00000000, - 0xe30, 0x1000dc1f, - 0xe34, 0x10008c1f, - 0xe38, 0x02140102, - 0xe3c, 0x681604c2, - 0xe40, 0x01007c00, - 0xe44, 0x01004800, - 0xe48, 0xfb000000, - 0xe4c, 0x000028d1, - 0xe50, 0x1000dc1f, - 0xe54, 0x10008c1f, - 0xe58, 0x02140102, - 0xe5c, 0x28160d05, - 0xe60, 0x00000008, - 0xe68, 0x001b25a4, - 0xe6c, 0x631b25a0, - 0xe70, 0x631b25a0, - 0xe74, 0x081b25a0, - 0xe78, 0x081b25a0, - 0xe7c, 0x081b25a0, - 0xe80, 0x081b25a0, - 0xe84, 0x631b25a0, - 0xe88, 0x081b25a0, - 0xe8c, 0x631b25a0, - 0xed0, 0x631b25a0, - 0xed4, 0x631b25a0, - 0xed8, 0x631b25a0, - 0xedc, 0x001b25a0, - 0xee0, 0x001b25a0, - 0xeec, 0x6b1b25a0, - 0xee8, 0x31555448, - 0xf14, 0x00000003, - 0xf4c, 0x00000000, - 0xf00, 0x00000300, -}; - -u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength] = { - 0xe00, 0xffffffff, 0x06080808, - 0xe04, 0xffffffff, 0x00040406, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x04060608, - 0xe14, 0xffffffff, 0x00020204, - 0xe18, 0xffffffff, 0x04060608, - 0xe1c, 0xffffffff, 0x00020204, - 0x830, 0xffffffff, 0x06080808, - 0x834, 0xffffffff, 0x00040406, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x04060608, - 0x848, 0xffffffff, 0x00020204, - 0x84c, 0xffffffff, 0x04060608, - 0x868, 0xffffffff, 0x00020204, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, -}; - -u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength] = { - 0x000, 0x00030159, - 0x001, 0x00031284, - 0x002, 0x00098000, - 0x003, 0x00018c63, - 0x004, 0x000210e7, - 0x009, 0x0002044f, - 0x00a, 0x0001adb0, - 0x00b, 0x00054867, - 0x00c, 0x0008992e, - 0x00d, 0x0000e529, - 0x00e, 0x00039ce7, - 0x00f, 0x00000451, - 0x019, 0x00000000, - 0x01a, 0x00000255, - 0x01b, 0x00060a00, - 0x01c, 0x000fc378, - 0x01d, 0x000a1250, - 0x01e, 0x0004445f, - 0x01f, 0x00080001, - 0x020, 0x0000b614, - 0x021, 0x0006c000, - 0x022, 0x0000083c, - 0x023, 0x00001558, - 0x024, 0x00000060, - 0x025, 0x00000483, - 0x026, 0x0004f000, - 0x027, 0x000ec7d9, - 0x028, 0x000977c0, - 0x029, 0x00004783, - 0x02a, 0x00000001, - 0x02b, 0x00021334, - 0x02a, 0x00000000, - 0x02b, 0x00000054, - 0x02a, 0x00000001, - 0x02b, 0x00000808, - 0x02b, 0x00053333, - 0x02c, 0x0000000c, - 0x02a, 0x00000002, - 0x02b, 0x00000808, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000003, - 0x02b, 0x00000808, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000004, - 0x02b, 0x00000808, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000005, - 0x02b, 0x00000808, - 0x02b, 0x00073333, - 0x02c, 0x0000000d, - 0x02a, 0x00000006, - 0x02b, 0x00000709, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000007, - 0x02b, 0x00000709, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000008, - 0x02b, 0x0000060a, - 0x02b, 0x0004b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000009, - 0x02b, 0x0000060a, - 0x02b, 0x00053333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000a, - 0x02b, 0x0000060a, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000b, - 0x02b, 0x0000060a, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000c, - 0x02b, 0x0000060a, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000d, - 0x02b, 0x0000060a, - 0x02b, 0x00073333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000e, - 0x02b, 0x0000050b, - 0x02b, 0x00066666, - 0x02c, 0x0000001a, - 0x02a, 0x000e0000, - 0x010, 0x0004000f, - 0x011, 0x000e31fc, - 0x010, 0x0006000f, - 0x011, 0x000ff9f8, - 0x010, 0x0002000f, - 0x011, 0x000203f9, - 0x010, 0x0003000f, - 0x011, 0x000ff500, - 0x010, 0x00000000, - 0x011, 0x00000000, - 0x010, 0x0008000f, - 0x011, 0x0003f100, - 0x010, 0x0009000f, - 0x011, 0x00023100, - 0x012, 0x000d8000, - 0x012, 0x00090000, - 0x012, 0x00051000, - 0x012, 0x00012000, - 0x013, 0x00028fb4, - 0x013, 0x00024fa8, - 0x013, 0x000207a4, - 0x013, 0x0001c798, - 0x013, 0x000183a4, - 0x013, 0x00014398, - 0x013, 0x000101a4, - 0x013, 0x0000c198, - 0x013, 0x000080a4, - 0x013, 0x00004098, - 0x013, 0x00000000, - 0x014, 0x0001944c, - 0x014, 0x00059444, - 0x014, 0x0009944c, - 0x014, 0x000d9444, - 0x015, 0x0000f405, - 0x015, 0x0004f405, - 0x015, 0x0008f405, - 0x015, 0x000cf405, - 0x016, 0x000e0330, - 0x016, 0x000a0330, - 0x016, 0x00060330, - 0x016, 0x00020330, - 0x000, 0x00010159, - 0x018, 0x0000f401, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01f, 0x00080003, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01e, 0x00044457, - 0x01f, 0x00080000, - 0x000, 0x00030159, -}; - -u32 Rtl8192CUAGCTAB_1T_HPArray[RTL8192CUAGCTAB_1T_HPArrayLength] = { - 0xc78, 0x7b000001, - 0xc78, 0x7b010001, - 0xc78, 0x7b020001, - 0xc78, 0x7b030001, - 0xc78, 0x7b040001, - 0xc78, 0x7b050001, - 0xc78, 0x7b060001, - 0xc78, 0x7b070001, - 0xc78, 0x7b080001, - 0xc78, 0x7a090001, - 0xc78, 0x790a0001, - 0xc78, 0x780b0001, - 0xc78, 0x770c0001, - 0xc78, 0x760d0001, - 0xc78, 0x750e0001, - 0xc78, 0x740f0001, - 0xc78, 0x73100001, - 0xc78, 0x72110001, - 0xc78, 0x71120001, - 0xc78, 0x70130001, - 0xc78, 0x6f140001, - 0xc78, 0x6e150001, - 0xc78, 0x6d160001, - 0xc78, 0x6c170001, - 0xc78, 0x6b180001, - 0xc78, 0x6a190001, - 0xc78, 0x691a0001, - 0xc78, 0x681b0001, - 0xc78, 0x671c0001, - 0xc78, 0x661d0001, - 0xc78, 0x651e0001, - 0xc78, 0x641f0001, - 0xc78, 0x63200001, - 0xc78, 0x62210001, - 0xc78, 0x61220001, - 0xc78, 0x60230001, - 0xc78, 0x46240001, - 0xc78, 0x45250001, - 0xc78, 0x44260001, - 0xc78, 0x43270001, - 0xc78, 0x42280001, - 0xc78, 0x41290001, - 0xc78, 0x402a0001, - 0xc78, 0x262b0001, - 0xc78, 0x252c0001, - 0xc78, 0x242d0001, - 0xc78, 0x232e0001, - 0xc78, 0x222f0001, - 0xc78, 0x21300001, - 0xc78, 0x20310001, - 0xc78, 0x06320001, - 0xc78, 0x05330001, - 0xc78, 0x04340001, - 0xc78, 0x03350001, - 0xc78, 0x02360001, - 0xc78, 0x01370001, - 0xc78, 0x00380001, - 0xc78, 0x00390001, - 0xc78, 0x003a0001, - 0xc78, 0x003b0001, - 0xc78, 0x003c0001, - 0xc78, 0x003d0001, - 0xc78, 0x003e0001, - 0xc78, 0x003f0001, - 0xc78, 0x7b400001, - 0xc78, 0x7b410001, - 0xc78, 0x7b420001, - 0xc78, 0x7b430001, - 0xc78, 0x7b440001, - 0xc78, 0x7b450001, - 0xc78, 0x7b460001, - 0xc78, 0x7b470001, - 0xc78, 0x7b480001, - 0xc78, 0x7a490001, - 0xc78, 0x794a0001, - 0xc78, 0x784b0001, - 0xc78, 0x774c0001, - 0xc78, 0x764d0001, - 0xc78, 0x754e0001, - 0xc78, 0x744f0001, - 0xc78, 0x73500001, - 0xc78, 0x72510001, - 0xc78, 0x71520001, - 0xc78, 0x70530001, - 0xc78, 0x6f540001, - 0xc78, 0x6e550001, - 0xc78, 0x6d560001, - 0xc78, 0x6c570001, - 0xc78, 0x6b580001, - 0xc78, 0x6a590001, - 0xc78, 0x695a0001, - 0xc78, 0x685b0001, - 0xc78, 0x675c0001, - 0xc78, 0x665d0001, - 0xc78, 0x655e0001, - 0xc78, 0x645f0001, - 0xc78, 0x63600001, - 0xc78, 0x62610001, - 0xc78, 0x61620001, - 0xc78, 0x60630001, - 0xc78, 0x46640001, - 0xc78, 0x45650001, - 0xc78, 0x44660001, - 0xc78, 0x43670001, - 0xc78, 0x42680001, - 0xc78, 0x41690001, - 0xc78, 0x406a0001, - 0xc78, 0x266b0001, - 0xc78, 0x256c0001, - 0xc78, 0x246d0001, - 0xc78, 0x236e0001, - 0xc78, 0x226f0001, - 0xc78, 0x21700001, - 0xc78, 0x20710001, - 0xc78, 0x06720001, - 0xc78, 0x05730001, - 0xc78, 0x04740001, - 0xc78, 0x03750001, - 0xc78, 0x02760001, - 0xc78, 0x01770001, - 0xc78, 0x00780001, - 0xc78, 0x00790001, - 0xc78, 0x007a0001, - 0xc78, 0x007b0001, - 0xc78, 0x007c0001, - 0xc78, 0x007d0001, - 0xc78, 0x007e0001, - 0xc78, 0x007f0001, - 0xc78, 0x3800001e, - 0xc78, 0x3801001e, - 0xc78, 0x3802001e, - 0xc78, 0x3803001e, - 0xc78, 0x3804001e, - 0xc78, 0x3805001e, - 0xc78, 0x3806001e, - 0xc78, 0x3807001e, - 0xc78, 0x3808001e, - 0xc78, 0x3c09001e, - 0xc78, 0x3e0a001e, - 0xc78, 0x400b001e, - 0xc78, 0x440c001e, - 0xc78, 0x480d001e, - 0xc78, 0x4c0e001e, - 0xc78, 0x500f001e, - 0xc78, 0x5210001e, - 0xc78, 0x5611001e, - 0xc78, 0x5a12001e, - 0xc78, 0x5e13001e, - 0xc78, 0x6014001e, - 0xc78, 0x6015001e, - 0xc78, 0x6016001e, - 0xc78, 0x6217001e, - 0xc78, 0x6218001e, - 0xc78, 0x6219001e, - 0xc78, 0x621a001e, - 0xc78, 0x621b001e, - 0xc78, 0x621c001e, - 0xc78, 0x621d001e, - 0xc78, 0x621e001e, - 0xc78, 0x621f001e, -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/table.h b/drivers/net/wireless/rtlwifi/rtl8192cu/table.h deleted file mode 100644 index 4b020e9e30b1..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/table.h +++ /dev/null @@ -1,71 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CU_TABLE__H_ -#define __RTL92CU_TABLE__H_ - -#include - -#define RTL8192CUPHY_REG_2TARRAY_LENGTH 374 -extern u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH]; -#define RTL8192CUPHY_REG_1TARRAY_LENGTH 374 -extern u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH]; - -#define RTL8192CUPHY_REG_ARRAY_PGLENGTH 336 -extern u32 RTL8192CUPHY_REG_ARRAY_PG[RTL8192CUPHY_REG_ARRAY_PGLENGTH]; - -#define RTL8192CURADIOA_2TARRAYLENGTH 282 -extern u32 RTL8192CURADIOA_2TARRAY[RTL8192CURADIOA_2TARRAYLENGTH]; -#define RTL8192CURADIOB_2TARRAYLENGTH 78 -extern u32 RTL8192CU_RADIOB_2TARRAY[RTL8192CURADIOB_2TARRAYLENGTH]; -#define RTL8192CURADIOA_1TARRAYLENGTH 282 -extern u32 RTL8192CU_RADIOA_1TARRAY[RTL8192CURADIOA_1TARRAYLENGTH]; -#define RTL8192CURADIOB_1TARRAYLENGTH 1 -extern u32 RTL8192CU_RADIOB_1TARRAY[RTL8192CURADIOB_1TARRAYLENGTH]; - -#define RTL8192CUMAC_2T_ARRAYLENGTH 172 -extern u32 RTL8192CUMAC_2T_ARRAY[RTL8192CUMAC_2T_ARRAYLENGTH]; - -#define RTL8192CUAGCTAB_2TARRAYLENGTH 320 -extern u32 RTL8192CUAGCTAB_2TARRAY[RTL8192CUAGCTAB_2TARRAYLENGTH]; -#define RTL8192CUAGCTAB_1TARRAYLENGTH 320 -extern u32 RTL8192CUAGCTAB_1TARRAY[RTL8192CUAGCTAB_1TARRAYLENGTH]; - -#define RTL8192CUPHY_REG_1T_HPArrayLength 378 -extern u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength]; - -#define RTL8192CUPHY_REG_Array_PG_HPLength 336 -extern u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength]; - -#define RTL8192CURadioA_1T_HPArrayLength 282 -extern u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength]; -#define RTL8192CUAGCTAB_1T_HPArrayLength 320 -extern u32 Rtl8192CUAGCTAB_1T_HPArray[RTL8192CUAGCTAB_1T_HPArrayLength]; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c deleted file mode 100644 index 95880fe4106e..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ /dev/null @@ -1,686 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../usb.h" -#include "../ps.h" -#include "../base.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" -#include "mac.h" -#include "trx.h" -#include "../rtl8192c/fw_common.h" - -static int _ConfigVerTOutEP(struct ieee80211_hw *hw) -{ - u8 ep_cfg, txqsele; - u8 ep_nums = 0; - - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); - - rtlusb->out_queue_sel = 0; - ep_cfg = rtl_read_byte(rtlpriv, REG_TEST_SIE_OPTIONAL); - ep_cfg = (ep_cfg & USB_TEST_EP_MASK) >> USB_TEST_EP_SHIFT; - switch (ep_cfg) { - case 0: /* 2 bulk OUT, 1 bulk IN */ - case 3: - rtlusb->out_queue_sel = TX_SELE_HQ | TX_SELE_LQ; - ep_nums = 2; - break; - case 1: /* 1 bulk IN/OUT => map all endpoint to Low queue */ - case 2: /* 1 bulk IN, 1 bulk OUT => map all endpoint to High queue */ - txqsele = rtl_read_byte(rtlpriv, REG_TEST_USB_TXQS); - if (txqsele & 0x0F) /* /map all endpoint to High queue */ - rtlusb->out_queue_sel = TX_SELE_HQ; - else if (txqsele&0xF0) /* map all endpoint to Low queue */ - rtlusb->out_queue_sel = TX_SELE_LQ; - ep_nums = 1; - break; - default: - break; - } - return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; -} - -static int _ConfigVerNOutEP(struct ieee80211_hw *hw) -{ - u8 ep_cfg; - u8 ep_nums = 0; - - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); - - rtlusb->out_queue_sel = 0; - /* Normal and High queue */ - ep_cfg = rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 1)); - if (ep_cfg & USB_NORMAL_SIE_EP_MASK) { - rtlusb->out_queue_sel |= TX_SELE_HQ; - ep_nums++; - } - if ((ep_cfg >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) { - rtlusb->out_queue_sel |= TX_SELE_NQ; - ep_nums++; - } - /* Low queue */ - ep_cfg = rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 2)); - if (ep_cfg & USB_NORMAL_SIE_EP_MASK) { - rtlusb->out_queue_sel |= TX_SELE_LQ; - ep_nums++; - } - return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL; -} - -static void _TwoOutEpMapping(struct ieee80211_hw *hw, bool bIsChipB, - bool bwificfg, struct rtl_ep_map *ep_map) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (bwificfg) { /* for WMM */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "USB Chip-B & WMM Setting.....\n"); - ep_map->ep_mapping[RTL_TXQ_BE] = 2; - ep_map->ep_mapping[RTL_TXQ_BK] = 3; - ep_map->ep_mapping[RTL_TXQ_VI] = 3; - ep_map->ep_mapping[RTL_TXQ_VO] = 2; - ep_map->ep_mapping[RTL_TXQ_MGT] = 2; - ep_map->ep_mapping[RTL_TXQ_BCN] = 2; - ep_map->ep_mapping[RTL_TXQ_HI] = 2; - } else { /* typical setting */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "USB typical Setting.....\n"); - ep_map->ep_mapping[RTL_TXQ_BE] = 3; - ep_map->ep_mapping[RTL_TXQ_BK] = 3; - ep_map->ep_mapping[RTL_TXQ_VI] = 2; - ep_map->ep_mapping[RTL_TXQ_VO] = 2; - ep_map->ep_mapping[RTL_TXQ_MGT] = 2; - ep_map->ep_mapping[RTL_TXQ_BCN] = 2; - ep_map->ep_mapping[RTL_TXQ_HI] = 2; - } -} - -static void _ThreeOutEpMapping(struct ieee80211_hw *hw, bool bwificfg, - struct rtl_ep_map *ep_map) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (bwificfg) { /* for WMM */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "USB 3EP Setting for WMM.....\n"); - ep_map->ep_mapping[RTL_TXQ_BE] = 5; - ep_map->ep_mapping[RTL_TXQ_BK] = 3; - ep_map->ep_mapping[RTL_TXQ_VI] = 3; - ep_map->ep_mapping[RTL_TXQ_VO] = 2; - ep_map->ep_mapping[RTL_TXQ_MGT] = 2; - ep_map->ep_mapping[RTL_TXQ_BCN] = 2; - ep_map->ep_mapping[RTL_TXQ_HI] = 2; - } else { /* typical setting */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "USB 3EP Setting for typical.....\n"); - ep_map->ep_mapping[RTL_TXQ_BE] = 5; - ep_map->ep_mapping[RTL_TXQ_BK] = 5; - ep_map->ep_mapping[RTL_TXQ_VI] = 3; - ep_map->ep_mapping[RTL_TXQ_VO] = 2; - ep_map->ep_mapping[RTL_TXQ_MGT] = 2; - ep_map->ep_mapping[RTL_TXQ_BCN] = 2; - ep_map->ep_mapping[RTL_TXQ_HI] = 2; - } -} - -static void _OneOutEpMapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map) -{ - ep_map->ep_mapping[RTL_TXQ_BE] = 2; - ep_map->ep_mapping[RTL_TXQ_BK] = 2; - ep_map->ep_mapping[RTL_TXQ_VI] = 2; - ep_map->ep_mapping[RTL_TXQ_VO] = 2; - ep_map->ep_mapping[RTL_TXQ_MGT] = 2; - ep_map->ep_mapping[RTL_TXQ_BCN] = 2; - ep_map->ep_mapping[RTL_TXQ_HI] = 2; -} -static int _out_ep_mapping(struct ieee80211_hw *hw) -{ - int err = 0; - bool bIsChipN, bwificfg = false; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); - struct rtl_ep_map *ep_map = &(rtlusb->ep_map); - - bIsChipN = IS_NORMAL_CHIP(rtlhal->version); - switch (rtlusb->out_ep_nums) { - case 2: - _TwoOutEpMapping(hw, bIsChipN, bwificfg, ep_map); - break; - case 3: - /* Test chip doesn't support three out EPs. */ - if (!bIsChipN) { - err = -EINVAL; - goto err_out; - } - _ThreeOutEpMapping(hw, bIsChipN, ep_map); - break; - case 1: - _OneOutEpMapping(hw, ep_map); - break; - default: - err = -EINVAL; - break; - } -err_out: - return err; - -} -/* endpoint mapping */ -int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - int error = 0; - if (likely(IS_NORMAL_CHIP(rtlhal->version))) - error = _ConfigVerNOutEP(hw); - else - error = _ConfigVerTOutEP(hw); - if (error) - goto err_out; - error = _out_ep_mapping(hw); - if (error) - goto err_out; -err_out: - return error; -} - -u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index) -{ - u16 hw_queue_index; - - if (unlikely(ieee80211_is_beacon(fc))) { - hw_queue_index = RTL_TXQ_BCN; - goto out; - } - if (ieee80211_is_mgmt(fc)) { - hw_queue_index = RTL_TXQ_MGT; - goto out; - } - switch (mac80211_queue_index) { - case 0: - hw_queue_index = RTL_TXQ_VO; - break; - case 1: - hw_queue_index = RTL_TXQ_VI; - break; - case 2: - hw_queue_index = RTL_TXQ_BE; - break; - case 3: - hw_queue_index = RTL_TXQ_BK; - break; - default: - hw_queue_index = RTL_TXQ_BE; - RT_ASSERT(false, "QSLT_BE queue, skb_queue:%d\n", - mac80211_queue_index); - break; - } -out: - return hw_queue_index; -} - -static enum rtl_desc_qsel _rtl8192cu_mq_to_descq(struct ieee80211_hw *hw, - __le16 fc, u16 mac80211_queue_index) -{ - enum rtl_desc_qsel qsel; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (unlikely(ieee80211_is_beacon(fc))) { - qsel = QSLT_BEACON; - goto out; - } - if (ieee80211_is_mgmt(fc)) { - qsel = QSLT_MGNT; - goto out; - } - switch (mac80211_queue_index) { - case 0: /* VO */ - qsel = QSLT_VO; - RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, - "VO queue, set qsel = 0x%x\n", QSLT_VO); - break; - case 1: /* VI */ - qsel = QSLT_VI; - RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, - "VI queue, set qsel = 0x%x\n", QSLT_VI); - break; - case 3: /* BK */ - qsel = QSLT_BK; - RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, - "BK queue, set qsel = 0x%x\n", QSLT_BK); - break; - case 2: /* BE */ - default: - qsel = QSLT_BE; - RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG, - "BE queue, set qsel = 0x%x\n", QSLT_BE); - break; - } -out: - return qsel; -} - -/* =============================================================== */ - -/*---------------------------------------------------------------------- - * - * Rx handler - * - *---------------------------------------------------------------------- */ -bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *stats, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb) -{ - struct rx_fwinfo_92c *p_drvinfo; - struct rx_desc_92c *p_desc = (struct rx_desc_92c *)pdesc; - u32 phystatus = GET_RX_DESC_PHY_STATUS(pdesc); - - stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); - stats->rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(pdesc) * - RX_DRV_INFO_SIZE_UNIT; - stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); - stats->icv = (u16) GET_RX_DESC_ICV(pdesc); - stats->crc = (u16) GET_RX_DESC_CRC32(pdesc); - stats->hwerror = (stats->crc | stats->icv); - stats->decrypted = !GET_RX_DESC_SWDEC(pdesc); - stats->rate = (u8) GET_RX_DESC_RX_MCS(pdesc); - stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); - stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); - stats->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1) - && (GET_RX_DESC_FAGGR(pdesc) == 1)); - stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); - stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); - stats->is_ht = (bool)GET_RX_DESC_RX_HT(pdesc); - rx_status->freq = hw->conf.chandef.chan->center_freq; - rx_status->band = hw->conf.chandef.chan->band; - if (GET_RX_DESC_CRC32(pdesc)) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (!GET_RX_DESC_SWDEC(pdesc)) - rx_status->flag |= RX_FLAG_DECRYPTED; - if (GET_RX_DESC_BW(pdesc)) - rx_status->flag |= RX_FLAG_40MHZ; - if (GET_RX_DESC_RX_HT(pdesc)) - rx_status->flag |= RX_FLAG_HT; - rx_status->flag |= RX_FLAG_MACTIME_START; - if (stats->decrypted) - rx_status->flag |= RX_FLAG_DECRYPTED; - rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht, - false, stats->rate); - rx_status->mactime = GET_RX_DESC_TSFL(pdesc); - if (phystatus) { - p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + - stats->rx_bufshift); - rtl92c_translate_rx_signal_stuff(hw, skb, stats, p_desc, - p_drvinfo); - } - /*rx_status->qual = stats->signal; */ - rx_status->signal = stats->recvsignalpower + 10; - return true; -} - -#define RTL_RX_DRV_INFO_UNIT 8 - -static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ieee80211_rx_status *rx_status = - (struct ieee80211_rx_status *)IEEE80211_SKB_RXCB(skb); - u32 skb_len, pkt_len, drvinfo_len; - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 *rxdesc; - struct rtl_stats stats = { - .signal = 0, - .rate = 0, - }; - struct rx_fwinfo_92c *p_drvinfo; - bool bv; - __le16 fc; - struct ieee80211_hdr *hdr; - - memset(rx_status, 0, sizeof(*rx_status)); - rxdesc = skb->data; - skb_len = skb->len; - drvinfo_len = (GET_RX_DESC_DRVINFO_SIZE(rxdesc) * RTL_RX_DRV_INFO_UNIT); - pkt_len = GET_RX_DESC_PKT_LEN(rxdesc); - /* TODO: Error recovery. drop this skb or something. */ - WARN_ON(skb_len < (pkt_len + RTL_RX_DESC_SIZE + drvinfo_len)); - stats.length = (u16) GET_RX_DESC_PKT_LEN(rxdesc); - stats.rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(rxdesc) * - RX_DRV_INFO_SIZE_UNIT; - stats.rx_bufshift = (u8) (GET_RX_DESC_SHIFT(rxdesc) & 0x03); - stats.icv = (u16) GET_RX_DESC_ICV(rxdesc); - stats.crc = (u16) GET_RX_DESC_CRC32(rxdesc); - stats.hwerror = (stats.crc | stats.icv); - stats.decrypted = !GET_RX_DESC_SWDEC(rxdesc); - stats.rate = (u8) GET_RX_DESC_RX_MCS(rxdesc); - stats.shortpreamble = (u16) GET_RX_DESC_SPLCP(rxdesc); - stats.isampdu = (bool) ((GET_RX_DESC_PAGGR(rxdesc) == 1) - && (GET_RX_DESC_FAGGR(rxdesc) == 1)); - stats.timestamp_low = GET_RX_DESC_TSFL(rxdesc); - stats.rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(rxdesc); - stats.is_ht = (bool)GET_RX_DESC_RX_HT(rxdesc); - /* TODO: is center_freq changed when doing scan? */ - /* TODO: Shall we add protection or just skip those two step? */ - rx_status->freq = hw->conf.chandef.chan->center_freq; - rx_status->band = hw->conf.chandef.chan->band; - if (GET_RX_DESC_CRC32(rxdesc)) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (!GET_RX_DESC_SWDEC(rxdesc)) - rx_status->flag |= RX_FLAG_DECRYPTED; - if (GET_RX_DESC_BW(rxdesc)) - rx_status->flag |= RX_FLAG_40MHZ; - if (GET_RX_DESC_RX_HT(rxdesc)) - rx_status->flag |= RX_FLAG_HT; - /* Data rate */ - rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats.is_ht, - false, stats.rate); - /* There is a phy status after this rx descriptor. */ - if (GET_RX_DESC_PHY_STATUS(rxdesc)) { - p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE); - rtl92c_translate_rx_signal_stuff(hw, skb, &stats, - (struct rx_desc_92c *)rxdesc, p_drvinfo); - } - skb_pull(skb, (drvinfo_len + RTL_RX_DESC_SIZE)); - hdr = (struct ieee80211_hdr *)(skb->data); - fc = hdr->frame_control; - bv = ieee80211_is_probe_resp(fc); - if (bv) - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Got probe response frame\n"); - if (ieee80211_is_beacon(fc)) - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Got beacon frame\n"); - if (ieee80211_is_data(fc)) - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Got data frame\n"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Fram: fc = 0x%X addr1 = 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X\n", - fc, - (u32)hdr->addr1[0], (u32)hdr->addr1[1], - (u32)hdr->addr1[2], (u32)hdr->addr1[3], - (u32)hdr->addr1[4], (u32)hdr->addr1[5]); - memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); - ieee80211_rx(hw, skb); -} - -void rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb) -{ - _rtl_rx_process(hw, skb); -} - -void rtl8192c_rx_segregate_hdl( - struct ieee80211_hw *hw, - struct sk_buff *skb, - struct sk_buff_head *skb_list) -{ -} - -/*---------------------------------------------------------------------- - * - * Tx handler - * - *---------------------------------------------------------------------- */ -void rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff *skb) -{ -} - -int rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb, - struct sk_buff *skb) -{ - return 0; -} - -struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *hw, - struct sk_buff_head *list) -{ - return skb_dequeue(list); -} - -/*======================================== trx ===============================*/ - -static void _rtl_fill_usb_tx_desc(u8 *txdesc) -{ - SET_TX_DESC_OWN(txdesc, 1); - SET_TX_DESC_LAST_SEG(txdesc, 1); - SET_TX_DESC_FIRST_SEG(txdesc, 1); -} -/** - * For HW recovery information - */ -static void _rtl_tx_desc_checksum(u8 *txdesc) -{ - u16 *ptr = (u16 *)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)); - SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, checksum); -} - -void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *pbd_desc_tx, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u8 queue_index, - struct rtl_tcb_desc *tcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool defaultadapter = true; - u8 *qc = ieee80211_get_qos_ctl(hdr); - u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - u16 seq_number; - __le16 fc = hdr->frame_control; - u8 rate_flag = info->control.rates[0].flags; - u16 pktlen = skb->len; - enum rtl_desc_qsel fw_qsel = _rtl8192cu_mq_to_descq(hw, fc, - skb_get_queue_mapping(skb)); - u8 *txdesc; - - seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc); - txdesc = (u8 *)skb_push(skb, RTL_TX_HEADER_SIZE); - memset(txdesc, 0, RTL_TX_HEADER_SIZE); - SET_TX_DESC_PKT_SIZE(txdesc, pktlen); - SET_TX_DESC_LINIP(txdesc, 0); - SET_TX_DESC_PKT_OFFSET(txdesc, RTL_DUMMY_OFFSET); - SET_TX_DESC_OFFSET(txdesc, RTL_TX_HEADER_SIZE); - SET_TX_DESC_TX_RATE(txdesc, tcb_desc->hw_rate); - if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble) - SET_TX_DESC_DATA_SHORTGI(txdesc, 1); - if (mac->tids[tid].agg.agg_state == RTL_AGG_ON && - info->flags & IEEE80211_TX_CTL_AMPDU) { - SET_TX_DESC_AGG_ENABLE(txdesc, 1); - SET_TX_DESC_MAX_AGG_NUM(txdesc, 0x14); - } else { - SET_TX_DESC_AGG_BREAK(txdesc, 1); - } - SET_TX_DESC_SEQ(txdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable && - !tcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable || - tcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc->rts_stbc) ? 1 : 0)); - SET_TX_DESC_RTS_RATE(txdesc, tcb_desc->rts_rate); - SET_TX_DESC_RTS_BW(txdesc, 0); - SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(txdesc, - ((tcb_desc->rts_rate <= DESC_RATE54M) ? - (tcb_desc->rts_use_shortpreamble ? 1 : 0) - : (tcb_desc->rts_use_shortgi ? 1 : 0))); - if (mac->bw_40) { - if (rate_flag & IEEE80211_TX_RC_DUP_DATA) { - SET_TX_DESC_DATA_BW(txdesc, 1); - SET_TX_DESC_DATA_SC(txdesc, 3); - } else if(rate_flag & IEEE80211_TX_RC_40_MHZ_WIDTH){ - SET_TX_DESC_DATA_BW(txdesc, 1); - SET_TX_DESC_DATA_SC(txdesc, mac->cur_40_prime_sc); - } else { - SET_TX_DESC_DATA_BW(txdesc, 0); - SET_TX_DESC_DATA_SC(txdesc, 0); - } - } else { - SET_TX_DESC_DATA_BW(txdesc, 0); - SET_TX_DESC_DATA_SC(txdesc, 0); - } - rcu_read_lock(); - sta = ieee80211_find_sta(mac->vif, mac->bssid); - if (sta) { - u8 ampdu_density = sta->ht_cap.ampdu_density; - SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density); - } - rcu_read_unlock(); - if (info->control.hw_key) { - struct ieee80211_key_conf *keyconf = info->control.hw_key; - switch (keyconf->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - case WLAN_CIPHER_SUITE_TKIP: - SET_TX_DESC_SEC_TYPE(txdesc, 0x1); - break; - case WLAN_CIPHER_SUITE_CCMP: - SET_TX_DESC_SEC_TYPE(txdesc, 0x3); - break; - default: - SET_TX_DESC_SEC_TYPE(txdesc, 0x0); - break; - } - } - SET_TX_DESC_PKT_ID(txdesc, 0); - SET_TX_DESC_QUEUE_SEL(txdesc, fw_qsel); - SET_TX_DESC_DATA_RATE_FB_LIMIT(txdesc, 0x1F); - SET_TX_DESC_RTS_RATE_FB_LIMIT(txdesc, 0xF); - SET_TX_DESC_DISABLE_FB(txdesc, 0); - SET_TX_DESC_USE_RATE(txdesc, tcb_desc->use_driver_rate ? 1 : 0); - if (ieee80211_is_data_qos(fc)) { - if (mac->rdg_en) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "Enable RDG function\n"); - SET_TX_DESC_RDG_ENABLE(txdesc, 1); - SET_TX_DESC_HTC(txdesc, 1); - } - } - if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(txdesc, tcb_desc->ratr_index); - SET_TX_DESC_MACID(txdesc, tcb_desc->mac_id); - } else { - SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc->ratr_index); - SET_TX_DESC_MACID(txdesc, tcb_desc->ratr_index); - } - if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps && - ppsc->fwctrl_lps) { - SET_TX_DESC_HWSEQ_EN(txdesc, 1); - SET_TX_DESC_PKT_ID(txdesc, 8); - if (!defaultadapter) - SET_TX_DESC_QOS(txdesc, 1); - } - if (ieee80211_has_morefrags(fc)) - SET_TX_DESC_MORE_FRAG(txdesc, 1); - if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || - is_broadcast_ether_addr(ieee80211_get_DA(hdr))) - SET_TX_DESC_BMC(txdesc, 1); - _rtl_fill_usb_tx_desc(txdesc); - _rtl_tx_desc_checksum(txdesc); - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "==>\n"); -} - -void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, - u32 buffer_len, bool bIsPsPoll) -{ - /* Clear all status */ - memset(pDesc, 0, RTL_TX_HEADER_SIZE); - SET_TX_DESC_FIRST_SEG(pDesc, 1); /* bFirstSeg; */ - SET_TX_DESC_LAST_SEG(pDesc, 1); /* bLastSeg; */ - SET_TX_DESC_OFFSET(pDesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */ - SET_TX_DESC_PKT_SIZE(pDesc, buffer_len); /* Buffer size + command hdr */ - SET_TX_DESC_QUEUE_SEL(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */ - /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error - * vlaue by Hw. */ - if (bIsPsPoll) { - SET_TX_DESC_NAV_USE_HDR(pDesc, 1); - } else { - SET_TX_DESC_HWSEQ_EN(pDesc, 1); /* Hw set sequence number */ - SET_TX_DESC_PKT_ID(pDesc, 0x100); /* set bit3 to 1. */ - } - SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */ - SET_TX_DESC_OWN(pDesc, 1); - SET_TX_DESC_TX_RATE(pDesc, DESC_RATE1M); - _rtl_tx_desc_checksum(pDesc); -} - -void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc, bool firstseg, - bool lastseg, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 fw_queue = QSLT_BEACON; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - __le16 fc = hdr->frame_control; - - memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE); - if (firstseg) - SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); - SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M); - SET_TX_DESC_SEQ(pdesc, 0); - SET_TX_DESC_LINIP(pdesc, 0); - SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - SET_TX_DESC_RATE_ID(pdesc, 7); - SET_TX_DESC_MACID(pdesc, 0); - SET_TX_DESC_OWN(pdesc, 1); - SET_TX_DESC_PKT_SIZE(pdesc, (u16)skb->len); - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - SET_TX_DESC_OFFSET(pdesc, 0x20); - SET_TX_DESC_USE_RATE(pdesc, 1); - if (!ieee80211_is_data_qos(fc)) { - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - SET_TX_DESC_PKT_ID(pdesc, 8); - } - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C Tx Cmd Content", - pdesc, RTL_TX_DESC_SIZE); -} - -bool rtl92cu_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - return true; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h deleted file mode 100644 index fd8051dcd98a..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h +++ /dev/null @@ -1,435 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CU_TRX_H__ -#define __RTL92CU_TRX_H__ - -#define RTL92C_USB_BULK_IN_NUM 1 -#define RTL92C_NUM_RX_URBS 8 -#define RTL92C_NUM_TX_URBS 32 - -#define RTL92C_SIZE_MAX_RX_BUFFER 15360 /* 8192 */ -#define RX_DRV_INFO_SIZE_UNIT 8 - -#define RTL_AGG_ON 1 - -enum usb_rx_agg_mode { - USB_RX_AGG_DISABLE, - USB_RX_AGG_DMA, - USB_RX_AGG_USB, - USB_RX_AGG_DMA_USB -}; - -#define TX_SELE_HQ BIT(0) /* High Queue */ -#define TX_SELE_LQ BIT(1) /* Low Queue */ -#define TX_SELE_NQ BIT(2) /* Normal Queue */ - -#define RTL_USB_TX_AGG_NUM_DESC 5 - -#define RTL_USB_RX_AGG_PAGE_NUM 4 -#define RTL_USB_RX_AGG_PAGE_TIMEOUT 3 - -#define RTL_USB_RX_AGG_BLOCK_NUM 5 -#define RTL_USB_RX_AGG_BLOCK_TIMEOUT 3 - -/*======================== rx status =========================================*/ - -struct rx_drv_info_92c { - /* - * Driver info contain PHY status and other variabel size info - * PHY Status content as below - */ - - /* DWORD 0 */ - u8 gain_trsw[4]; - - /* DWORD 1 */ - u8 pwdb_all; - u8 cfosho[4]; - - /* DWORD 2 */ - u8 cfotail[4]; - - /* DWORD 3 */ - s8 rxevm[2]; - s8 rxsnr[4]; - - /* DWORD 4 */ - u8 pdsnr[2]; - - /* DWORD 5 */ - u8 csi_current[2]; - u8 csi_target[2]; - - /* DWORD 6 */ - u8 sigevm; - u8 max_ex_pwr; - u8 ex_intf_flag:1; - u8 sgi_en:1; - u8 rxsc:2; - 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) -#define GET_RX_DESC_CRC32(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 14, 1) -#define GET_RX_DESC_ICV(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 15, 1) -#define GET_RX_DESC_DRVINFO_SIZE(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 16, 4) -#define GET_RX_DESC_SECURITY(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 20, 3) -#define GET_RX_DESC_QOS(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 23, 1) -#define GET_RX_DESC_SHIFT(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 24, 2) -#define GET_RX_DESC_PHY_STATUS(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 26, 1) -#define GET_RX_DESC_SWDEC(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 27, 1) -#define GET_RX_DESC_LAST_SEG(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 28, 1) -#define GET_RX_DESC_FIRST_SEG(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 29, 1) -#define GET_RX_DESC_EOR(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 30, 1) -#define GET_RX_DESC_OWN(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc, 31, 1) - -/* DWORD 1 */ -#define GET_RX_DESC_MACID(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 0, 5) -#define GET_RX_DESC_TID(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 5, 4) -#define GET_RX_DESC_PAGGR(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 14, 1) -#define GET_RX_DESC_FAGGR(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 15, 1) -#define GET_RX_DESC_A1_FIT(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 16, 4) -#define GET_RX_DESC_A2_FIT(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 20, 4) -#define GET_RX_DESC_PAM(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 24, 1) -#define GET_RX_DESC_PWR(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 25, 1) -#define GET_RX_DESC_MORE_DATA(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 26, 1) -#define GET_RX_DESC_MORE_FRAG(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 27, 1) -#define GET_RX_DESC_TYPE(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 28, 2) -#define GET_RX_DESC_MC(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 30, 1) -#define GET_RX_DESC_BC(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+4, 31, 1) - -/* DWORD 2 */ -#define GET_RX_DESC_SEQ(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+8, 0, 12) -#define GET_RX_DESC_FRAG(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+8, 12, 4) -#define GET_RX_DESC_USB_AGG_PKTNUM(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+8, 16, 8) -#define GET_RX_DESC_NEXT_IND(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+8, 30, 1) - -/* DWORD 3 */ -#define GET_RX_DESC_RX_MCS(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 0, 6) -#define GET_RX_DESC_RX_HT(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 6, 1) -#define GET_RX_DESC_AMSDU(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 7, 1) -#define GET_RX_DESC_SPLCP(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 8, 1) -#define GET_RX_DESC_BW(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 9, 1) -#define GET_RX_DESC_HTC(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 10, 1) -#define GET_RX_DESC_TCP_CHK_RPT(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 11, 1) -#define GET_RX_DESC_IP_CHK_RPT(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 12, 1) -#define GET_RX_DESC_TCP_CHK_VALID(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 13, 1) -#define GET_RX_DESC_HWPC_ERR(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 14, 1) -#define GET_RX_DESC_HWPC_IND(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 15, 1) -#define GET_RX_DESC_IV0(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+12, 16, 16) - -/* DWORD 4 */ -#define GET_RX_DESC_IV1(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+16, 0, 32) - -/* DWORD 5 */ -#define GET_RX_DESC_TSFL(__rxdesc) \ - SHIFT_AND_MASK_LE(__rxdesc+20, 0, 32) - -/*======================= tx desc ============================================*/ - -/* macros to set various fields in TX descriptor */ - -/* Dword 0 */ -#define SET_TX_DESC_PKT_SIZE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 0, 16, __value) -#define SET_TX_DESC_OFFSET(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 16, 8, __value) -#define SET_TX_DESC_BMC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 24, 1, __value) -#define SET_TX_DESC_HTC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 25, 1, __value) -#define SET_TX_DESC_LAST_SEG(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 26, 1, __value) -#define SET_TX_DESC_FIRST_SEG(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 27, 1, __value) -#define SET_TX_DESC_LINIP(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 28, 1, __value) -#define SET_TX_DESC_NO_ACM(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 29, 1, __value) -#define SET_TX_DESC_GF(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 30, 1, __value) -#define SET_TX_DESC_OWN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc, 31, 1, __value) - - -/* Dword 1 */ -#define SET_TX_DESC_MACID(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 0, 5, __value) -#define SET_TX_DESC_AGG_ENABLE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 5, 1, __value) -#define SET_TX_DESC_AGG_BREAK(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 6, 1, __value) -#define SET_TX_DESC_RDG_ENABLE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 7, 1, __value) -#define SET_TX_DESC_QUEUE_SEL(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 8, 5, __value) -#define SET_TX_DESC_RDG_NAV_EXT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 13, 1, __value) -#define SET_TX_DESC_LSIG_TXOP_EN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 14, 1, __value) -#define SET_TX_DESC_PIFS(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 15, 1, __value) -#define SET_TX_DESC_RATE_ID(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 16, 4, __value) -#define SET_TX_DESC_RA_BRSR_ID(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 16, 4, __value) -#define SET_TX_DESC_NAV_USE_HDR(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 20, 1, __value) -#define SET_TX_DESC_EN_DESC_ID(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 21, 1, __value) -#define SET_TX_DESC_SEC_TYPE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 22, 2, __value) -#define SET_TX_DESC_PKT_OFFSET(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+4, 26, 5, __value) - -/* Dword 2 */ -#define SET_TX_DESC_RTS_RC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 0, 6, __value) -#define SET_TX_DESC_DATA_RC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 6, 6, __value) -#define SET_TX_DESC_BAR_RTY_TH(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 14, 2, __value) -#define SET_TX_DESC_MORE_FRAG(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 17, 1, __value) -#define SET_TX_DESC_RAW(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 18, 1, __value) -#define SET_TX_DESC_CCX(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 19, 1, __value) -#define SET_TX_DESC_AMPDU_DENSITY(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 20, 3, __value) -#define SET_TX_DESC_ANTSEL_A(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 24, 1, __value) -#define SET_TX_DESC_ANTSEL_B(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 25, 1, __value) -#define SET_TX_DESC_TX_ANT_CCK(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 26, 2, __value) -#define SET_TX_DESC_TX_ANTL(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+8, 28, 2, __value) -#define SET_TX_DESC_TX_ANT_HT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__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) -#define SET_TX_DESC_TAIL_PAGE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+12, 8, 8, __value) -#define SET_TX_DESC_SEQ(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+12, 16, 12, __value) -#define SET_TX_DESC_PKT_ID(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+12, 28, 4, __value) - -/* Dword 4 */ -#define SET_TX_DESC_RTS_RATE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 0, 5, __value) -#define SET_TX_DESC_AP_DCFE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 5, 1, __value) -#define SET_TX_DESC_QOS(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 6, 1, __value) -#define SET_TX_DESC_HWSEQ_EN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 7, 1, __value) -#define SET_TX_DESC_USE_RATE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 8, 1, __value) -#define SET_TX_DESC_DISABLE_RTS_FB(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 9, 1, __value) -#define SET_TX_DESC_DISABLE_FB(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 10, 1, __value) -#define SET_TX_DESC_CTS2SELF(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 11, 1, __value) -#define SET_TX_DESC_RTS_ENABLE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 12, 1, __value) -#define SET_TX_DESC_HW_RTS_ENABLE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 13, 1, __value) -#define SET_TX_DESC_WAIT_DCTS(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 18, 1, __value) -#define SET_TX_DESC_CTS2AP_EN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 19, 1, __value) -#define SET_TX_DESC_DATA_SC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 20, 2, __value) -#define SET_TX_DESC_DATA_STBC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 22, 2, __value) -#define SET_TX_DESC_DATA_SHORT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 24, 1, __value) -#define SET_TX_DESC_DATA_BW(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 25, 1, __value) -#define SET_TX_DESC_RTS_SHORT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 26, 1, __value) -#define SET_TX_DESC_RTS_BW(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 27, 1, __value) -#define SET_TX_DESC_RTS_SC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 28, 2, __value) -#define SET_TX_DESC_RTS_STBC(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+16, 30, 2, __value) - -/* Dword 5 */ -#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val) -#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val) -#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val) -#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+20, 8, 5, __value) -#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+20, 13, 4, __value) -#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+20, 17, 1, __value) -#define SET_TX_DESC_DATA_RETRY_LIMIT(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+20, 18, 6, __value) -#define SET_TX_DESC_USB_TXAGG_NUM(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+20, 24, 8, __value) - -/* Dword 6 */ -#define SET_TX_DESC_TXAGC_A(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 0, 5, __value) -#define SET_TX_DESC_TXAGC_B(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 5, 5, __value) -#define SET_TX_DESC_USB_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 10, 1, __value) -#define SET_TX_DESC_MAX_AGG_NUM(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 11, 5, __value) -#define SET_TX_DESC_MCSG1_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 16, 4, __value) -#define SET_TX_DESC_MCSG2_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 20, 4, __value) -#define SET_TX_DESC_MCSG3_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+24, 24, 4, __value) -#define SET_TX_DESC_MCSG7_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__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) -#define SET_TX_DESC_MCSG4_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+28, 16, 4, __value) -#define SET_TX_DESC_MCSG5_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+28, 20, 4, __value) -#define SET_TX_DESC_MCSG6_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+28, 24, 4, __value) -#define SET_TX_DESC_MCSG15_MAX_LEN(__txdesc, __value) \ - SET_BITS_OFFSET_LE(__txdesc+28, 28, 4, __value) - - -int rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw); -u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index); -bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *stats, - struct ieee80211_rx_status *rx_status, - u8 *p_desc, struct sk_buff *skb); -void rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb); -void rtl8192c_rx_segregate_hdl(struct ieee80211_hw *, struct sk_buff *, - struct sk_buff_head *); -void rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff *skb); -int rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb, - struct sk_buff *skb); -struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *, - struct sk_buff_head *); -void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *pbd_desc_tx, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u8 queue_index, - struct rtl_tcb_desc *tcb_desc); -void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, - u32 buffer_len, bool bIsPsPoll); -void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc, bool b_firstseg, - bool b_lastseg, struct sk_buff *skb); -bool rtl92cu_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/Makefile b/drivers/net/wireless/rtlwifi/rtl8192de/Makefile deleted file mode 100644 index e3213c8264b6..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -rtl8192de-objs := \ - dm.o \ - fw.o \ - hw.o \ - led.o \ - phy.o \ - rf.o \ - sw.o \ - table.o \ - trx.o - -obj-$(CONFIG_RTL8192DE) += rtl8192de.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/rtlwifi/rtl8192de/def.h deleted file mode 100644 index 0a443ed17cf4..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/def.h +++ /dev/null @@ -1,232 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92D_DEF_H__ -#define __RTL92D_DEF_H__ - -/* Min Spacing related settings. */ -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -#define RF6052_MAX_TX_PWR 0x3F -#define RF6052_MAX_PATH 2 - -#define PHY_RSSI_SLID_WIN_MAX 100 -#define PHY_LINKQUALITY_SLID_WIN_MAX 20 -#define PHY_BEACON_RSSI_SLID_WIN_MAX 10 - -#define RT_AC_INT_MASKS (IMR_VIDOK | IMR_VODOK | IMR_BEDOK|IMR_BKDOK) - -#define RX_SMOOTH_FACTOR 20 - -#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 -#define HAL_PRIME_CHNL_OFFSET_LOWER 1 -#define HAL_PRIME_CHNL_OFFSET_UPPER 2 - -#define RX_MPDU_QUEUE 0 -#define RX_CMD_QUEUE 1 - -#define C2H_RX_CMD_HDR_LEN 8 -#define GET_C2H_CMD_CMD_LEN(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 0, 16) -#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 16, 8) -#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 24, 7) -#define GET_C2H_CMD_CONTINUE(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 31, 1) -#define GET_C2H_CMD_CONTENT(__prxhdr) \ - ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) - -#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) -#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) -#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) -#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) -#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) -#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) -#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) -#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) -#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) - -enum version_8192d { - VERSION_TEST_CHIP_88C = 0x0000, - VERSION_TEST_CHIP_92C = 0x0020, - VERSION_TEST_UMC_CHIP_8723 = 0x0081, - VERSION_NORMAL_TSMC_CHIP_88C = 0x0008, - VERSION_NORMAL_TSMC_CHIP_92C = 0x0028, - VERSION_NORMAL_TSMC_CHIP_92C_1T2R = 0x0018, - VERSION_NORMAL_UMC_CHIP_88C_A_CUT = 0x0088, - VERSION_NORMAL_UMC_CHIP_92C_A_CUT = 0x00a8, - VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT = 0x0098, - VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT = 0x0089, - VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT = 0x1089, - VERSION_NORMAL_UMC_CHIP_88C_B_CUT = 0x1088, - VERSION_NORMAL_UMC_CHIP_92C_B_CUT = 0x10a8, - VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT = 0x1090, - VERSION_TEST_CHIP_92D_SINGLEPHY = 0x0022, - VERSION_TEST_CHIP_92D_DUALPHY = 0x0002, - VERSION_NORMAL_CHIP_92D_SINGLEPHY = 0x002a, - VERSION_NORMAL_CHIP_92D_DUALPHY = 0x000a, - VERSION_NORMAL_CHIP_92D_C_CUT_SINGLEPHY = 0x202a, - VERSION_NORMAL_CHIP_92D_C_CUT_DUALPHY = 0x200a, - VERSION_NORMAL_CHIP_92D_D_CUT_SINGLEPHY = 0x302a, - VERSION_NORMAL_CHIP_92D_D_CUT_DUALPHY = 0x300a, - VERSION_NORMAL_CHIP_92D_E_CUT_SINGLEPHY = 0x402a, - VERSION_NORMAL_CHIP_92D_E_CUT_DUALPHY = 0x400a, -}; - -/* for 92D */ -#define CHIP_92D_SINGLEPHY BIT(9) - -/* Chip specific */ -#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) -#define CHIP_BONDING_92C_1T2R 0x1 -#define CHIP_BONDING_88C_USB_MCARD 0x2 -#define CHIP_BONDING_88C_USB_HP 0x1 - -/* [15:12] IC version(CUT): A-cut=0, B-cut=1, C-cut=2, D-cut=3 */ -/* [7] Manufacturer: TSMC=0, UMC=1 */ -/* [6:4] RF type: 1T1R=0, 1T2R=1, 2T2R=2 */ -/* [3] Chip type: TEST=0, NORMAL=1 */ -/* [2:0] IC type: 81xxC=0, 8723=1, 92D=2 */ -#define CHIP_8723 BIT(0) -#define CHIP_92D BIT(1) -#define NORMAL_CHIP BIT(3) -#define RF_TYPE_1T1R (~(BIT(4)|BIT(5)|BIT(6))) -#define RF_TYPE_1T2R BIT(4) -#define RF_TYPE_2T2R BIT(5) -#define CHIP_VENDOR_UMC BIT(7) -#define CHIP_92D_B_CUT BIT(12) -#define CHIP_92D_C_CUT BIT(13) -#define CHIP_92D_D_CUT (BIT(13)|BIT(12)) -#define CHIP_92D_E_CUT BIT(14) - -/* MASK */ -#define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2)) -#define CHIP_TYPE_MASK BIT(3) -#define RF_TYPE_MASK (BIT(4)|BIT(5)|BIT(6)) -#define MANUFACTUER_MASK BIT(7) -#define ROM_VERSION_MASK (BIT(11)|BIT(10)|BIT(9)|BIT(8)) -#define CUT_VERSION_MASK (BIT(15)|BIT(14)|BIT(13)|BIT(12)) - - -/* Get element */ -#define GET_CVID_IC_TYPE(version) ((version) & IC_TYPE_MASK) -#define GET_CVID_CHIP_TYPE(version) ((version) & CHIP_TYPE_MASK) -#define GET_CVID_RF_TYPE(version) ((version) & RF_TYPE_MASK) -#define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK) -#define GET_CVID_ROM_VERSION(version) ((version) & ROM_VERSION_MASK) -#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK) - -#define IS_1T1R(version) ((GET_CVID_RF_TYPE(version)) ? \ - false : true) -#define IS_1T2R(version) ((GET_CVID_RF_TYPE(version) == \ - RF_TYPE_1T2R) ? true : false) -#define IS_2T2R(version) ((GET_CVID_RF_TYPE(version) == \ - RF_TYPE_2T2R) ? true : false) - -#define IS_92D_SINGLEPHY(version) ((IS_92D(version)) ? \ - (IS_2T2R(version) ? true : false) : false) -#define IS_92D(version) ((GET_CVID_IC_TYPE(version) == \ - CHIP_92D) ? true : false) -#define IS_92D_C_CUT(version) ((IS_92D(version)) ? \ - ((GET_CVID_CUT_VERSION(version) == \ - CHIP_92D_C_CUT) ? true : false) : false) -#define IS_92D_D_CUT(version) ((IS_92D(version)) ? \ - ((GET_CVID_CUT_VERSION(version) == \ - CHIP_92D_D_CUT) ? true : false) : false) -#define IS_92D_E_CUT(version) ((IS_92D(version)) ? \ - ((GET_CVID_CUT_VERSION(version) == \ - CHIP_92D_E_CUT) ? true : false) : false) - -enum rf_optype { - RF_OP_BY_SW_3WIRE = 0, - RF_OP_BY_FW, - RF_OP_MAX -}; - -enum rtl_desc_qsel { - QSLT_BK = 0x2, - QSLT_BE = 0x0, - QSLT_VI = 0x5, - QSLT_VO = 0x7, - QSLT_BEACON = 0x10, - QSLT_HIGH = 0x11, - QSLT_MGNT = 0x12, - QSLT_CMD = 0x13, -}; - -enum channel_plan { - CHPL_FCC = 0, - CHPL_IC = 1, - CHPL_ETSI = 2, - CHPL_SPAIN = 3, - CHPL_FRANCE = 4, - CHPL_MKK = 5, - CHPL_MKK1 = 6, - CHPL_ISRAEL = 7, - CHPL_TELEC = 8, - CHPL_GLOBAL = 9, - CHPL_WORLD = 10, -}; - -struct phy_sts_cck_8192d { - u8 adc_pwdb_X[4]; - u8 sq_rpt; - u8 cck_agc_rpt; -}; - -struct h2c_cmd_8192c { - u8 element_id; - u32 cmd_len; - u8 *p_cmdbuffer; -}; - -struct txpower_info { - u8 cck_index[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; - u8 ht40_1sindex[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; - u8 ht40_2sindexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; - u8 ht20indexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; - u8 ofdmindexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; - u8 ht40maxoffset[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; - u8 ht20maxoffset[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; - u8 tssi_a[3]; /* 5GL/5GM/5GH */ - u8 tssi_b[3]; -}; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c deleted file mode 100644 index 7c1db7e7572d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c +++ /dev/null @@ -1,1316 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../base.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "fw.h" - -#define UNDEC_SM_PWDB entry_min_undec_sm_pwdb - -static const u32 ofdmswing_table[OFDM_TABLE_SIZE_92D] = { - 0x7f8001fe, /* 0, +6.0dB */ - 0x788001e2, /* 1, +5.5dB */ - 0x71c001c7, /* 2, +5.0dB */ - 0x6b8001ae, /* 3, +4.5dB */ - 0x65400195, /* 4, +4.0dB */ - 0x5fc0017f, /* 5, +3.5dB */ - 0x5a400169, /* 6, +3.0dB */ - 0x55400155, /* 7, +2.5dB */ - 0x50800142, /* 8, +2.0dB */ - 0x4c000130, /* 9, +1.5dB */ - 0x47c0011f, /* 10, +1.0dB */ - 0x43c0010f, /* 11, +0.5dB */ - 0x40000100, /* 12, +0dB */ - 0x3c8000f2, /* 13, -0.5dB */ - 0x390000e4, /* 14, -1.0dB */ - 0x35c000d7, /* 15, -1.5dB */ - 0x32c000cb, /* 16, -2.0dB */ - 0x300000c0, /* 17, -2.5dB */ - 0x2d4000b5, /* 18, -3.0dB */ - 0x2ac000ab, /* 19, -3.5dB */ - 0x288000a2, /* 20, -4.0dB */ - 0x26000098, /* 21, -4.5dB */ - 0x24000090, /* 22, -5.0dB */ - 0x22000088, /* 23, -5.5dB */ - 0x20000080, /* 24, -6.0dB */ - 0x1e400079, /* 25, -6.5dB */ - 0x1c800072, /* 26, -7.0dB */ - 0x1b00006c, /* 27. -7.5dB */ - 0x19800066, /* 28, -8.0dB */ - 0x18000060, /* 29, -8.5dB */ - 0x16c0005b, /* 30, -9.0dB */ - 0x15800056, /* 31, -9.5dB */ - 0x14400051, /* 32, -10.0dB */ - 0x1300004c, /* 33, -10.5dB */ - 0x12000048, /* 34, -11.0dB */ - 0x11000044, /* 35, -11.5dB */ - 0x10000040, /* 36, -12.0dB */ - 0x0f00003c, /* 37, -12.5dB */ - 0x0e400039, /* 38, -13.0dB */ - 0x0d800036, /* 39, -13.5dB */ - 0x0cc00033, /* 40, -14.0dB */ - 0x0c000030, /* 41, -14.5dB */ - 0x0b40002d, /* 42, -15.0dB */ -}; - -static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */ - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */ - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */ - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */ - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */ - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */ - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */ - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */ - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */ - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */ - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */ - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */ - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */ -}; - -static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */ - {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */ - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */ - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */ - {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */ - {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */ - {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */ - {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */ - {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */ - {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */ - {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */ - {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */ - {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */ - {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */ -}; - -static void rtl92d_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) -{ - u32 ret_value; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); - unsigned long flag = 0; - - /* hold ofdm counter */ - rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1); /* hold page C counter */ - rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1); /*hold page D counter */ - - ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD); - falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff); - falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16); - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); - falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); - falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); - falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); - falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); - falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + - falsealm_cnt->cnt_mcs_fail + - falsealm_cnt->cnt_fast_fsync_fail + - falsealm_cnt->cnt_sb_search_fail; - - if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) { - /* hold cck counter */ - rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); - ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); - falsealm_cnt->cnt_cck_fail = ret_value; - ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3); - falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; - rtl92d_release_cckandrw_pagea_ctl(hw, &flag); - } else { - falsealm_cnt->cnt_cck_fail = 0; - } - - /* reset false alarm counter registers */ - falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail + - falsealm_cnt->cnt_sb_search_fail + - falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + - falsealm_cnt->cnt_mcs_fail + - falsealm_cnt->cnt_cck_fail; - - rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1); - /* update ofdm counter */ - rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0); - /* update page C counter */ - rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0); - /* update page D counter */ - rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0); - if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) { - /* reset cck counter */ - rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0); - /* enable cck counter */ - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2); - rtl92d_release_cckandrw_pagea_ctl(hw, &flag); - } - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Cnt_Fast_Fsync_fail = %x, Cnt_SB_Search_fail = %x\n", - falsealm_cnt->cnt_fast_fsync_fail, - falsealm_cnt->cnt_sb_search_fail); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Cnt_Parity_Fail = %x, Cnt_Rate_Illegal = %x, Cnt_Crc8_fail = %x, Cnt_Mcs_fail = %x\n", - falsealm_cnt->cnt_parity_fail, - falsealm_cnt->cnt_rate_illegal, - falsealm_cnt->cnt_crc8_fail, - falsealm_cnt->cnt_mcs_fail); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Cnt_Ofdm_fail = %x, Cnt_Cck_fail = %x, Cnt_all = %x\n", - falsealm_cnt->cnt_ofdm_fail, - falsealm_cnt->cnt_cck_fail, - falsealm_cnt->cnt_all); -} - -static void rtl92d_dm_find_minimum_rssi(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *de_digtable = &rtlpriv->dm_digtable; - struct rtl_mac *mac = rtl_mac(rtlpriv); - - /* Determine the minimum RSSI */ - if ((mac->link_state < MAC80211_LINKED) && - (rtlpriv->dm.UNDEC_SM_PWDB == 0)) { - de_digtable->min_undec_pwdb_for_dm = 0; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "Not connected to any\n"); - } - if (mac->link_state >= MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - de_digtable->min_undec_pwdb_for_dm = - rtlpriv->dm.UNDEC_SM_PWDB; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "AP Client PWDB = 0x%lx\n", - rtlpriv->dm.UNDEC_SM_PWDB); - } else { - de_digtable->min_undec_pwdb_for_dm = - rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "STA Default Port PWDB = 0x%x\n", - de_digtable->min_undec_pwdb_for_dm); - } - } else { - de_digtable->min_undec_pwdb_for_dm = rtlpriv->dm.UNDEC_SM_PWDB; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "AP Ext Port or disconnect PWDB = 0x%x\n", - de_digtable->min_undec_pwdb_for_dm); - } - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n", - de_digtable->min_undec_pwdb_for_dm); -} - -static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *de_digtable = &rtlpriv->dm_digtable; - unsigned long flag = 0; - - if (de_digtable->cursta_cstate == DIG_STA_CONNECT) { - if (de_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { - if (de_digtable->min_undec_pwdb_for_dm <= 25) - de_digtable->cur_cck_pd_state = - CCK_PD_STAGE_LOWRSSI; - else - de_digtable->cur_cck_pd_state = - CCK_PD_STAGE_HIGHRSSI; - } else { - if (de_digtable->min_undec_pwdb_for_dm <= 20) - de_digtable->cur_cck_pd_state = - CCK_PD_STAGE_LOWRSSI; - else - de_digtable->cur_cck_pd_state = - CCK_PD_STAGE_HIGHRSSI; - } - } else { - de_digtable->cur_cck_pd_state = CCK_PD_STAGE_LOWRSSI; - } - if (de_digtable->pre_cck_pd_state != de_digtable->cur_cck_pd_state) { - if (de_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { - rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83); - rtl92d_release_cckandrw_pagea_ctl(hw, &flag); - } else { - rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); - rtl92d_release_cckandrw_pagea_ctl(hw, &flag); - } - de_digtable->pre_cck_pd_state = de_digtable->cur_cck_pd_state; - } - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "CurSTAConnectState=%s\n", - de_digtable->cursta_cstate == DIG_STA_CONNECT ? - "DIG_STA_CONNECT " : "DIG_STA_DISCONNECT"); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "CCKPDStage=%s\n", - de_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI ? - "Low RSSI " : "High RSSI "); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "is92d single phy =%x\n", - IS_92D_SINGLEPHY(rtlpriv->rtlhal.version)); - -} - -void rtl92d_dm_write_dig(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *de_digtable = &rtlpriv->dm_digtable; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n", - de_digtable->cur_igvalue, de_digtable->pre_igvalue, - de_digtable->back_val); - if (de_digtable->dig_enable_flag == false) { - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "DIG is disabled\n"); - de_digtable->pre_igvalue = 0x17; - return; - } - if (de_digtable->pre_igvalue != de_digtable->cur_igvalue) { - rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, - de_digtable->cur_igvalue); - rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, - de_digtable->cur_igvalue); - de_digtable->pre_igvalue = de_digtable->cur_igvalue; - } -} - -static void rtl92d_early_mode_enabled(struct rtl_priv *rtlpriv) -{ - struct dig_t *de_digtable = &rtlpriv->dm_digtable; - - if ((rtlpriv->mac80211.link_state >= MAC80211_LINKED) && - (rtlpriv->mac80211.vendor == PEER_CISCO)) { - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "IOT_PEER = CISCO\n"); - if (de_digtable->last_min_undec_pwdb_for_dm >= 50 - && de_digtable->min_undec_pwdb_for_dm < 50) { - rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x00); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Early Mode Off\n"); - } else if (de_digtable->last_min_undec_pwdb_for_dm <= 55 && - de_digtable->min_undec_pwdb_for_dm > 55) { - rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Early Mode On\n"); - } - } else if (!(rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL) & 0xf)) { - rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "Early Mode On\n"); - } -} - -static void rtl92d_dm_dig(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *de_digtable = &rtlpriv->dm_digtable; - u8 value_igi = de_digtable->cur_igvalue; - struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "==>\n"); - if (rtlpriv->rtlhal.earlymode_enable) { - rtl92d_early_mode_enabled(rtlpriv); - de_digtable->last_min_undec_pwdb_for_dm = - de_digtable->min_undec_pwdb_for_dm; - } - if (!rtlpriv->dm.dm_initialgain_enable) - return; - - /* because we will send data pkt when scanning - * this will cause some ap like gear-3700 wep TP - * lower if we return here, this is the diff of - * mac80211 driver vs ieee80211 driver */ - /* if (rtlpriv->mac80211.act_scanning) - * return; */ - - /* Not STA mode return tmp */ - if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) - return; - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "progress\n"); - /* Decide the current status and if modify initial gain or not */ - if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) - de_digtable->cursta_cstate = DIG_STA_CONNECT; - else - de_digtable->cursta_cstate = DIG_STA_DISCONNECT; - - /* adjust initial gain according to false alarm counter */ - if (falsealm_cnt->cnt_all < DM_DIG_FA_TH0) - value_igi--; - else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH1) - value_igi += 0; - else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH2) - value_igi++; - else if (falsealm_cnt->cnt_all >= DM_DIG_FA_TH2) - value_igi += 2; - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "dm_DIG() Before: large_fa_hit=%d, forbidden_igi=%x\n", - de_digtable->large_fa_hit, de_digtable->forbidden_igi); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "dm_DIG() Before: Recover_cnt=%d, rx_gain_min=%x\n", - de_digtable->recover_cnt, de_digtable->rx_gain_min); - - /* deal with abnormally large false alarm */ - if (falsealm_cnt->cnt_all > 10000) { - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "dm_DIG(): Abnormally false alarm case\n"); - - de_digtable->large_fa_hit++; - if (de_digtable->forbidden_igi < de_digtable->cur_igvalue) { - de_digtable->forbidden_igi = de_digtable->cur_igvalue; - de_digtable->large_fa_hit = 1; - } - if (de_digtable->large_fa_hit >= 3) { - if ((de_digtable->forbidden_igi + 1) > DM_DIG_MAX) - de_digtable->rx_gain_min = DM_DIG_MAX; - else - de_digtable->rx_gain_min = - (de_digtable->forbidden_igi + 1); - de_digtable->recover_cnt = 3600; /* 3600=2hr */ - } - } else { - /* Recovery mechanism for IGI lower bound */ - if (de_digtable->recover_cnt != 0) { - de_digtable->recover_cnt--; - } else { - if (de_digtable->large_fa_hit == 0) { - if ((de_digtable->forbidden_igi - 1) < - DM_DIG_FA_LOWER) { - de_digtable->forbidden_igi = - DM_DIG_FA_LOWER; - de_digtable->rx_gain_min = - DM_DIG_FA_LOWER; - - } else { - de_digtable->forbidden_igi--; - de_digtable->rx_gain_min = - (de_digtable->forbidden_igi + 1); - } - } else if (de_digtable->large_fa_hit == 3) { - de_digtable->large_fa_hit = 0; - } - } - } - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "dm_DIG() After: large_fa_hit=%d, forbidden_igi=%x\n", - de_digtable->large_fa_hit, de_digtable->forbidden_igi); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "dm_DIG() After: recover_cnt=%d, rx_gain_min=%x\n", - de_digtable->recover_cnt, de_digtable->rx_gain_min); - - if (value_igi > DM_DIG_MAX) - value_igi = DM_DIG_MAX; - else if (value_igi < de_digtable->rx_gain_min) - value_igi = de_digtable->rx_gain_min; - de_digtable->cur_igvalue = value_igi; - rtl92d_dm_write_dig(hw); - if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) - rtl92d_dm_cck_packet_detection_thresh(hw); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "<<==\n"); -} - -static void rtl92d_dm_init_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.dynamic_txpower_enable = true; - rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; -} - -static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long undec_sm_pwdb; - - if ((!rtlpriv->dm.dynamic_txpower_enable) - || rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - if ((mac->link_state < MAC80211_LINKED) && - (rtlpriv->dm.UNDEC_SM_PWDB == 0)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "Not connected to any\n"); - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - if (mac->link_state >= MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - undec_sm_pwdb = - rtlpriv->dm.UNDEC_SM_PWDB; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "IBSS Client PWDB = 0x%lx\n", - undec_sm_pwdb); - } else { - undec_sm_pwdb = - rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "STA Default Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - } else { - undec_sm_pwdb = - rtlpriv->dm.UNDEC_SM_PWDB; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Ext Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - if (rtlhal->current_bandtype == BAND_ON_5G) { - if (undec_sm_pwdb >= 0x33) { - rtlpriv->dm.dynamic_txhighpower_lvl = - TXHIGHPWRLEVEL_LEVEL2; - RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD, - "5G:TxHighPwrLevel_Level2 (TxPwr=0x0)\n"); - } else if ((undec_sm_pwdb < 0x33) - && (undec_sm_pwdb >= 0x2b)) { - rtlpriv->dm.dynamic_txhighpower_lvl = - TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD, - "5G:TxHighPwrLevel_Level1 (TxPwr=0x10)\n"); - } else if (undec_sm_pwdb < 0x2b) { - rtlpriv->dm.dynamic_txhighpower_lvl = - TXHIGHPWRLEVEL_NORMAL; - RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD, - "5G:TxHighPwrLevel_Normal\n"); - } - } else { - if (undec_sm_pwdb >= - TX_POWER_NEAR_FIELD_THRESH_LVL2) { - rtlpriv->dm.dynamic_txhighpower_lvl = - TXHIGHPWRLEVEL_LEVEL2; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); - } else - if ((undec_sm_pwdb < - (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) - && (undec_sm_pwdb >= - TX_POWER_NEAR_FIELD_THRESH_LVL1)) { - - rtlpriv->dm.dynamic_txhighpower_lvl = - TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); - } else if (undec_sm_pwdb < - (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { - rtlpriv->dm.dynamic_txhighpower_lvl = - TXHIGHPWRLEVEL_NORMAL; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_NORMAL\n"); - } - } - if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "PHY_SetTxPowerLevel8192S() Channel = %d\n", - rtlphy->current_channel); - rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel); - } - rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; -} - -static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /* AP & ADHOC & MESH will return tmp */ - if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) - return; - /* Indicate Rx signal strength to FW. */ - if (rtlpriv->dm.useramask) { - u32 temp = rtlpriv->dm.undec_sm_pwdb; - - temp <<= 16; - temp |= 0x100; - /* fw v12 cmdid 5:use max macid ,for nic , - * default macid is 0 ,max macid is 1 */ - rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *) (&temp)); - } else { - rtl_write_byte(rtlpriv, 0x4fe, - (u8) rtlpriv->dm.undec_sm_pwdb); - } -} - -void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.current_turbo_edca = false; - rtlpriv->dm.is_any_nonbepkts = false; - rtlpriv->dm.is_cur_rdlstate = false; -} - -static void rtl92d_dm_check_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - static u64 last_txok_cnt; - static u64 last_rxok_cnt; - u64 cur_txok_cnt; - u64 cur_rxok_cnt; - u32 edca_be_ul = 0x5ea42b; - u32 edca_be_dl = 0x5ea42b; - - if (mac->link_state != MAC80211_LINKED) { - rtlpriv->dm.current_turbo_edca = false; - goto exit; - } - - /* Enable BEQ TxOP limit configuration in wireless G-mode. */ - /* To check whether we shall force turn on TXOP configuration. */ - if ((!rtlpriv->dm.disable_framebursting) && - (rtlpriv->sec.pairwise_enc_algorithm == WEP40_ENCRYPTION || - rtlpriv->sec.pairwise_enc_algorithm == WEP104_ENCRYPTION || - rtlpriv->sec.pairwise_enc_algorithm == TKIP_ENCRYPTION)) { - /* Force TxOP limit to 0x005e for UL. */ - if (!(edca_be_ul & 0xffff0000)) - edca_be_ul |= 0x005e0000; - /* Force TxOP limit to 0x005e for DL. */ - if (!(edca_be_dl & 0xffff0000)) - edca_be_dl |= 0x005e0000; - } - - if ((!rtlpriv->dm.is_any_nonbepkts) && - (!rtlpriv->dm.disable_framebursting)) { - cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; - cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; - if (cur_rxok_cnt > 4 * cur_txok_cnt) { - if (!rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { - rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, - edca_be_dl); - rtlpriv->dm.is_cur_rdlstate = true; - } - } else { - if (rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { - rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, - edca_be_ul); - rtlpriv->dm.is_cur_rdlstate = false; - } - } - rtlpriv->dm.current_turbo_edca = true; - } else { - if (rtlpriv->dm.current_turbo_edca) { - u8 tmp = AC0_BE; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, - &tmp); - rtlpriv->dm.current_turbo_edca = false; - } - } - -exit: - rtlpriv->dm.is_any_nonbepkts = false; - last_txok_cnt = rtlpriv->stats.txbytesunicast; - last_rxok_cnt = rtlpriv->stats.rxbytesunicast; -} - -static void rtl92d_dm_rxgain_tracking_thermalmeter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 index_mapping[RX_INDEX_MAPPING_NUM] = { - 0x0f, 0x0f, 0x0d, 0x0c, 0x0b, - 0x0a, 0x09, 0x08, 0x07, 0x06, - 0x05, 0x04, 0x04, 0x03, 0x02 - }; - int i; - u32 u4tmp; - - u4tmp = (index_mapping[(rtlpriv->efuse.eeprom_thermalmeter - - rtlpriv->dm.thermalvalue_rxgain)]) << 12; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "===> Rx Gain %x\n", u4tmp); - for (i = RF90_PATH_A; i < rtlpriv->phy.num_total_rfpath; i++) - rtl_set_rfreg(hw, i, 0x3C, RFREG_OFFSET_MASK, - (rtlpriv->phy.reg_rf3c[i] & (~(0xF000))) | u4tmp); -} - -static void rtl92d_bandtype_2_4G(struct ieee80211_hw *hw, long *temp_cckg, - u8 *cck_index_old) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int i; - unsigned long flag = 0; - long temp_cck; - - /* Query CCK default setting From 0xa24 */ - rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); - temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2, - MASKDWORD) & MASKCCK; - rtl92d_release_cckandrw_pagea_ctl(hw, &flag); - for (i = 0; i < CCK_TABLE_LENGTH; i++) { - if (rtlpriv->dm.cck_inch14) { - if (!memcmp((void *)&temp_cck, - (void *)&cckswing_table_ch14[i][2], 4)) { - *cck_index_old = (u8) i; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch 14 %d\n", - RCCK0_TXFILTER2, temp_cck, - *cck_index_old, - rtlpriv->dm.cck_inch14); - break; - } - } else { - if (!memcmp((void *) &temp_cck, - &cckswing_table_ch1ch13[i][2], 4)) { - *cck_index_old = (u8) i; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Initial reg0x%x = 0x%lx, cck_index = 0x%x, ch14 %d\n", - RCCK0_TXFILTER2, temp_cck, - *cck_index_old, - rtlpriv->dm.cck_inch14); - break; - } - } - } - *temp_cckg = temp_cck; -} - -static void rtl92d_bandtype_5G(struct rtl_hal *rtlhal, u8 *ofdm_index, - bool *internal_pa, u8 thermalvalue, u8 delta, - u8 rf, struct rtl_efuse *rtlefuse, - struct rtl_priv *rtlpriv, struct rtl_phy *rtlphy, - u8 index_mapping[5][INDEX_MAPPING_NUM], - u8 index_mapping_pa[8][INDEX_MAPPING_NUM]) -{ - int i; - u8 index; - u8 offset = 0; - - for (i = 0; i < rf; i++) { - if (rtlhal->macphymode == DUALMAC_DUALPHY && - rtlhal->interfaceindex == 1) /* MAC 1 5G */ - *internal_pa = rtlefuse->internal_pa_5g[1]; - else - *internal_pa = rtlefuse->internal_pa_5g[i]; - if (*internal_pa) { - if (rtlhal->interfaceindex == 1 || i == rf) - offset = 4; - else - offset = 0; - if (rtlphy->current_channel >= 100 && - rtlphy->current_channel <= 165) - offset += 2; - } else { - if (rtlhal->interfaceindex == 1 || i == rf) - offset = 2; - else - offset = 0; - } - if (thermalvalue > rtlefuse->eeprom_thermalmeter) - offset++; - if (*internal_pa) { - if (delta > INDEX_MAPPING_NUM - 1) - index = index_mapping_pa[offset] - [INDEX_MAPPING_NUM - 1]; - else - index = - index_mapping_pa[offset][delta]; - } else { - if (delta > INDEX_MAPPING_NUM - 1) - index = - index_mapping[offset][INDEX_MAPPING_NUM - 1]; - else - index = index_mapping[offset][delta]; - } - if (thermalvalue > rtlefuse->eeprom_thermalmeter) { - if (*internal_pa && thermalvalue > 0x12) { - ofdm_index[i] = rtlpriv->dm.ofdm_index[i] - - ((delta / 2) * 3 + (delta % 2)); - } else { - ofdm_index[i] -= index; - } - } else { - ofdm_index[i] += index; - } - } -} - -static void rtl92d_dm_txpower_tracking_callback_thermalmeter( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 thermalvalue, delta, delta_lck, delta_iqk, delta_rxgain; - u8 offset, thermalvalue_avg_count = 0; - u32 thermalvalue_avg = 0; - bool internal_pa = false; - long ele_a = 0, ele_d, temp_cck, val_x, value32; - long val_y, ele_c = 0; - u8 ofdm_index[3]; - s8 cck_index = 0; - u8 ofdm_index_old[3] = {0, 0, 0}; - s8 cck_index_old = 0; - u8 index; - int i; - bool is2t = IS_92D_SINGLEPHY(rtlhal->version); - u8 ofdm_min_index = 6, ofdm_min_index_internal_pa = 3, rf; - u8 indexforchannel = - rtl92d_get_rightchnlplace_for_iqk(rtlphy->current_channel); - u8 index_mapping[5][INDEX_MAPPING_NUM] = { - /* 5G, path A/MAC 0, decrease power */ - {0, 1, 3, 6, 8, 9, 11, 13, 14, 16, 17, 18, 18}, - /* 5G, path A/MAC 0, increase power */ - {0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18}, - /* 5G, path B/MAC 1, decrease power */ - {0, 2, 3, 6, 8, 9, 11, 13, 14, 16, 17, 18, 18}, - /* 5G, path B/MAC 1, increase power */ - {0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18}, - /* 2.4G, for decreas power */ - {0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 10, 10}, - }; - u8 index_mapping_internal_pa[8][INDEX_MAPPING_NUM] = { - /* 5G, path A/MAC 0, ch36-64, decrease power */ - {0, 1, 2, 4, 6, 7, 9, 11, 12, 14, 15, 16, 16}, - /* 5G, path A/MAC 0, ch36-64, increase power */ - {0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18}, - /* 5G, path A/MAC 0, ch100-165, decrease power */ - {0, 1, 2, 3, 5, 6, 8, 10, 11, 13, 14, 15, 15}, - /* 5G, path A/MAC 0, ch100-165, increase power */ - {0, 2, 4, 5, 7, 10, 12, 14, 16, 18, 18, 18, 18}, - /* 5G, path B/MAC 1, ch36-64, decrease power */ - {0, 1, 2, 4, 6, 7, 9, 11, 12, 14, 15, 16, 16}, - /* 5G, path B/MAC 1, ch36-64, increase power */ - {0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18}, - /* 5G, path B/MAC 1, ch100-165, decrease power */ - {0, 1, 2, 3, 5, 6, 8, 9, 10, 12, 13, 14, 14}, - /* 5G, path B/MAC 1, ch100-165, increase power */ - {0, 2, 4, 5, 7, 10, 13, 16, 16, 18, 18, 18, 18}, - }; - - rtlpriv->dm.txpower_trackinginit = true; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "\n"); - thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xf800); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n", - thermalvalue, - rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter); - rtl92d_phy_ap_calibrate(hw, (thermalvalue - - rtlefuse->eeprom_thermalmeter)); - if (is2t) - rf = 2; - else - rf = 1; - if (thermalvalue) { - ele_d = rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE, - MASKDWORD) & MASKOFDM_D; - for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { - if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) { - ofdm_index_old[0] = (u8) i; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n", - ROFDM0_XATxIQIMBALANCE, - ele_d, ofdm_index_old[0]); - break; - } - } - if (is2t) { - ele_d = rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, - MASKDWORD) & MASKOFDM_D; - for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { - if (ele_d == - (ofdmswing_table[i] & MASKOFDM_D)) { - ofdm_index_old[1] = (u8) i; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, - DBG_LOUD, - "Initial pathB ele_d reg 0x%x = 0x%lx, ofdm_index = 0x%x\n", - ROFDM0_XBTxIQIMBALANCE, ele_d, - ofdm_index_old[1]); - break; - } - } - } - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - rtl92d_bandtype_2_4G(hw, &temp_cck, &cck_index_old); - } else { - temp_cck = 0x090e1317; - cck_index_old = 12; - } - - if (!rtlpriv->dm.thermalvalue) { - rtlpriv->dm.thermalvalue = - rtlefuse->eeprom_thermalmeter; - rtlpriv->dm.thermalvalue_lck = thermalvalue; - rtlpriv->dm.thermalvalue_iqk = thermalvalue; - rtlpriv->dm.thermalvalue_rxgain = - rtlefuse->eeprom_thermalmeter; - for (i = 0; i < rf; i++) - rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; - rtlpriv->dm.cck_index = cck_index_old; - } - if (rtlhal->reloadtxpowerindex) { - for (i = 0; i < rf; i++) - rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; - rtlpriv->dm.cck_index = cck_index_old; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "reload ofdm index for band switch\n"); - } - rtlpriv->dm.thermalvalue_avg - [rtlpriv->dm.thermalvalue_avg_index] = thermalvalue; - rtlpriv->dm.thermalvalue_avg_index++; - if (rtlpriv->dm.thermalvalue_avg_index == AVG_THERMAL_NUM) - rtlpriv->dm.thermalvalue_avg_index = 0; - for (i = 0; i < AVG_THERMAL_NUM; i++) { - if (rtlpriv->dm.thermalvalue_avg[i]) { - thermalvalue_avg += - rtlpriv->dm.thermalvalue_avg[i]; - thermalvalue_avg_count++; - } - } - if (thermalvalue_avg_count) - thermalvalue = (u8) (thermalvalue_avg / - thermalvalue_avg_count); - if (rtlhal->reloadtxpowerindex) { - delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? - (thermalvalue - rtlefuse->eeprom_thermalmeter) : - (rtlefuse->eeprom_thermalmeter - thermalvalue); - rtlhal->reloadtxpowerindex = false; - rtlpriv->dm.done_txpower = false; - } else if (rtlpriv->dm.done_txpower) { - delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? - (thermalvalue - rtlpriv->dm.thermalvalue) : - (rtlpriv->dm.thermalvalue - thermalvalue); - } else { - delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? - (thermalvalue - rtlefuse->eeprom_thermalmeter) : - (rtlefuse->eeprom_thermalmeter - thermalvalue); - } - delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? - (thermalvalue - rtlpriv->dm.thermalvalue_lck) : - (rtlpriv->dm.thermalvalue_lck - thermalvalue); - delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? - (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : - (rtlpriv->dm.thermalvalue_iqk - thermalvalue); - delta_rxgain = - (thermalvalue > rtlpriv->dm.thermalvalue_rxgain) ? - (thermalvalue - rtlpriv->dm.thermalvalue_rxgain) : - (rtlpriv->dm.thermalvalue_rxgain - thermalvalue); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n", - thermalvalue, rtlpriv->dm.thermalvalue, - rtlefuse->eeprom_thermalmeter, delta, delta_lck, - delta_iqk); - if ((delta_lck > rtlefuse->delta_lck) && - (rtlefuse->delta_lck != 0)) { - rtlpriv->dm.thermalvalue_lck = thermalvalue; - rtl92d_phy_lc_calibrate(hw); - } - if (delta > 0 && rtlpriv->dm.txpower_track_control) { - rtlpriv->dm.done_txpower = true; - delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? - (thermalvalue - rtlefuse->eeprom_thermalmeter) : - (rtlefuse->eeprom_thermalmeter - thermalvalue); - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - offset = 4; - if (delta > INDEX_MAPPING_NUM - 1) - index = index_mapping[offset] - [INDEX_MAPPING_NUM - 1]; - else - index = index_mapping[offset][delta]; - if (thermalvalue > rtlpriv->dm.thermalvalue) { - for (i = 0; i < rf; i++) - ofdm_index[i] -= delta; - cck_index -= delta; - } else { - for (i = 0; i < rf; i++) - ofdm_index[i] += index; - cck_index += index; - } - } else if (rtlhal->current_bandtype == BAND_ON_5G) { - rtl92d_bandtype_5G(rtlhal, ofdm_index, - &internal_pa, thermalvalue, - delta, rf, rtlefuse, rtlpriv, - rtlphy, index_mapping, - index_mapping_internal_pa); - } - if (is2t) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "temp OFDM_A_index=0x%x, OFDM_B_index = 0x%x,cck_index=0x%x\n", - rtlpriv->dm.ofdm_index[0], - rtlpriv->dm.ofdm_index[1], - rtlpriv->dm.cck_index); - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "temp OFDM_A_index=0x%x,cck_index = 0x%x\n", - rtlpriv->dm.ofdm_index[0], - rtlpriv->dm.cck_index); - } - for (i = 0; i < rf; i++) { - if (ofdm_index[i] > OFDM_TABLE_SIZE_92D - 1) - ofdm_index[i] = OFDM_TABLE_SIZE_92D - 1; - else if (ofdm_index[i] < ofdm_min_index) - ofdm_index[i] = ofdm_min_index; - } - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - if (cck_index > CCK_TABLE_SIZE - 1) { - cck_index = CCK_TABLE_SIZE - 1; - } else if (internal_pa || - rtlhal->current_bandtype == - BAND_ON_2_4G) { - if (ofdm_index[i] < - ofdm_min_index_internal_pa) - ofdm_index[i] = - ofdm_min_index_internal_pa; - } else if (cck_index < 0) { - cck_index = 0; - } - } - if (is2t) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "new OFDM_A_index=0x%x, OFDM_B_index = 0x%x, cck_index=0x%x\n", - ofdm_index[0], ofdm_index[1], - cck_index); - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "new OFDM_A_index=0x%x,cck_index = 0x%x\n", - ofdm_index[0], cck_index); - } - ele_d = (ofdmswing_table[(u8) ofdm_index[0]] & - 0xFFC00000) >> 22; - val_x = rtlphy->iqk_matrix - [indexforchannel].value[0][0]; - val_y = rtlphy->iqk_matrix - [indexforchannel].value[0][1]; - if (val_x != 0) { - if ((val_x & 0x00000200) != 0) - val_x = val_x | 0xFFFFFC00; - ele_a = - ((val_x * ele_d) >> 8) & 0x000003FF; - - /* new element C = element D x Y */ - if ((val_y & 0x00000200) != 0) - val_y = val_y | 0xFFFFFC00; - ele_c = ((val_y * ele_d) >> 8) & 0x000003FF; - - /* wirte new elements A, C, D to regC80 and - * regC94, element B is always 0 */ - value32 = (ele_d << 22) | ((ele_c & 0x3F) << - 16) | ele_a; - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, - MASKDWORD, value32); - - value32 = (ele_c & 0x000003C0) >> 6; - rtl_set_bbreg(hw, ROFDM0_XCTxAFE, MASKH4BITS, - value32); - - value32 = ((val_x * ele_d) >> 7) & 0x01; - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), - value32); - - } else { - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, - MASKDWORD, - ofdmswing_table - [(u8)ofdm_index[0]]); - rtl_set_bbreg(hw, ROFDM0_XCTxAFE, MASKH4BITS, - 0x00); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, - BIT(24), 0x00); - } - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "TxPwrTracking for interface %d path A: X = 0x%lx, Y = 0x%lx ele_A = 0x%lx ele_C = 0x%lx ele_D = 0x%lx 0xe94 = 0x%lx 0xe9c = 0x%lx\n", - rtlhal->interfaceindex, - val_x, val_y, ele_a, ele_c, ele_d, - val_x, val_y); - - if (cck_index >= CCK_TABLE_SIZE) - cck_index = CCK_TABLE_SIZE - 1; - if (cck_index < 0) - cck_index = 0; - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - /* Adjust CCK according to IQK result */ - if (!rtlpriv->dm.cck_inch14) { - rtl_write_byte(rtlpriv, 0xa22, - cckswing_table_ch1ch13 - [(u8)cck_index][0]); - rtl_write_byte(rtlpriv, 0xa23, - cckswing_table_ch1ch13 - [(u8)cck_index][1]); - rtl_write_byte(rtlpriv, 0xa24, - cckswing_table_ch1ch13 - [(u8)cck_index][2]); - rtl_write_byte(rtlpriv, 0xa25, - cckswing_table_ch1ch13 - [(u8)cck_index][3]); - rtl_write_byte(rtlpriv, 0xa26, - cckswing_table_ch1ch13 - [(u8)cck_index][4]); - rtl_write_byte(rtlpriv, 0xa27, - cckswing_table_ch1ch13 - [(u8)cck_index][5]); - rtl_write_byte(rtlpriv, 0xa28, - cckswing_table_ch1ch13 - [(u8)cck_index][6]); - rtl_write_byte(rtlpriv, 0xa29, - cckswing_table_ch1ch13 - [(u8)cck_index][7]); - } else { - rtl_write_byte(rtlpriv, 0xa22, - cckswing_table_ch14 - [(u8)cck_index][0]); - rtl_write_byte(rtlpriv, 0xa23, - cckswing_table_ch14 - [(u8)cck_index][1]); - rtl_write_byte(rtlpriv, 0xa24, - cckswing_table_ch14 - [(u8)cck_index][2]); - rtl_write_byte(rtlpriv, 0xa25, - cckswing_table_ch14 - [(u8)cck_index][3]); - rtl_write_byte(rtlpriv, 0xa26, - cckswing_table_ch14 - [(u8)cck_index][4]); - rtl_write_byte(rtlpriv, 0xa27, - cckswing_table_ch14 - [(u8)cck_index][5]); - rtl_write_byte(rtlpriv, 0xa28, - cckswing_table_ch14 - [(u8)cck_index][6]); - rtl_write_byte(rtlpriv, 0xa29, - cckswing_table_ch14 - [(u8)cck_index][7]); - } - } - if (is2t) { - ele_d = (ofdmswing_table[(u8) ofdm_index[1]] & - 0xFFC00000) >> 22; - val_x = rtlphy->iqk_matrix - [indexforchannel].value[0][4]; - val_y = rtlphy->iqk_matrix - [indexforchannel].value[0][5]; - if (val_x != 0) { - if ((val_x & 0x00000200) != 0) - /* consider minus */ - val_x = val_x | 0xFFFFFC00; - ele_a = ((val_x * ele_d) >> 8) & - 0x000003FF; - /* new element C = element D x Y */ - if ((val_y & 0x00000200) != 0) - val_y = - val_y | 0xFFFFFC00; - ele_c = - ((val_y * - ele_d) >> 8) & 0x00003FF; - /* write new elements A, C, D to regC88 - * and regC9C, element B is always 0 - */ - value32 = (ele_d << 22) | - ((ele_c & 0x3F) << 16) | - ele_a; - rtl_set_bbreg(hw, - ROFDM0_XBTxIQIMBALANCE, - MASKDWORD, value32); - value32 = (ele_c & 0x000003C0) >> 6; - rtl_set_bbreg(hw, ROFDM0_XDTxAFE, - MASKH4BITS, value32); - value32 = ((val_x * ele_d) >> 7) & 0x01; - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, - BIT(28), value32); - } else { - rtl_set_bbreg(hw, - ROFDM0_XBTxIQIMBALANCE, - MASKDWORD, - ofdmswing_table - [(u8) ofdm_index[1]]); - rtl_set_bbreg(hw, ROFDM0_XDTxAFE, - MASKH4BITS, 0x00); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, - BIT(28), 0x00); - } - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "TxPwrTracking path B: X = 0x%lx, Y = 0x%lx ele_A = 0x%lx ele_C = 0x%lx ele_D = 0x%lx 0xeb4 = 0x%lx 0xebc = 0x%lx\n", - val_x, val_y, ele_a, ele_c, - ele_d, val_x, val_y); - } - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "TxPwrTracking 0xc80 = 0x%x, 0xc94 = 0x%x RF 0x24 = 0x%x\n", - rtl_get_bbreg(hw, 0xc80, MASKDWORD), - rtl_get_bbreg(hw, 0xc94, MASKDWORD), - rtl_get_rfreg(hw, RF90_PATH_A, 0x24, - RFREG_OFFSET_MASK)); - } - if ((delta_iqk > rtlefuse->delta_iqk) && - (rtlefuse->delta_iqk != 0)) { - rtl92d_phy_reset_iqk_result(hw); - rtlpriv->dm.thermalvalue_iqk = thermalvalue; - rtl92d_phy_iq_calibrate(hw); - } - if (delta_rxgain > 0 && rtlhal->current_bandtype == BAND_ON_5G - && thermalvalue <= rtlefuse->eeprom_thermalmeter) { - rtlpriv->dm.thermalvalue_rxgain = thermalvalue; - rtl92d_dm_rxgain_tracking_thermalmeter(hw); - } - if (rtlpriv->dm.txpower_track_control) - rtlpriv->dm.thermalvalue = thermalvalue; - } - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===\n"); -} - -static void rtl92d_dm_initialize_txpower_tracking(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.txpower_tracking = true; - rtlpriv->dm.txpower_trackinginit = false; - rtlpriv->dm.txpower_track_control = true; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pMgntInfo->txpower_tracking = %d\n", - rtlpriv->dm.txpower_tracking); -} - -void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (!rtlpriv->dm.txpower_tracking) - return; - - if (!rtlpriv->dm.tm_trigger) { - rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | - BIT(16), 0x03); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Trigger 92S Thermal Meter!!\n"); - rtlpriv->dm.tm_trigger = 1; - return; - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Schedule TxPowerTracking direct call!!\n"); - rtl92d_dm_txpower_tracking_callback_thermalmeter(hw); - rtlpriv->dm.tm_trigger = 0; - } -} - -void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rate_adaptive *ra = &(rtlpriv->ra); - - ra->ratr_state = DM_RATR_STA_INIT; - ra->pre_ratr_state = DM_RATR_STA_INIT; - if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) - rtlpriv->dm.useramask = true; - else - rtlpriv->dm.useramask = false; -} - -void rtl92d_dm_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; - rtl_dm_diginit(hw, 0x20); - rtlpriv->dm_digtable.rx_gain_max = DM_DIG_FA_UPPER; - rtlpriv->dm_digtable.rx_gain_min = DM_DIG_FA_LOWER; - rtl92d_dm_init_dynamic_txpower(hw); - rtl92d_dm_init_edca_turbo(hw); - rtl92d_dm_init_rate_adaptive_mask(hw); - rtl92d_dm_initialize_txpower_tracking(hw); -} - -void rtl92d_dm_watchdog(struct ieee80211_hw *hw) -{ - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool fw_current_inpsmode = false; - bool fwps_awake = true; - - /* 1. RF is OFF. (No need to do DM.) - * 2. Fw is under power saving mode for FwLPS. - * (Prevent from SW/FW I/O racing.) - * 3. IPS workitem is scheduled. (Prevent from IPS sequence - * to be swapped with DM. - * 4. RFChangeInProgress is TRUE. - * (Prevent from broken by IPS/HW/SW Rf off.) */ - - if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) && - fwps_awake) && (!ppsc->rfchange_inprogress)) { - rtl92d_dm_pwdb_monitor(hw); - rtl92d_dm_false_alarm_counter_statistics(hw); - rtl92d_dm_find_minimum_rssi(hw); - rtl92d_dm_dig(hw); - /* rtl92d_dm_dynamic_bb_powersaving(hw); */ - rtl92d_dm_dynamic_txpower(hw); - /* rtl92d_dm_check_txpower_tracking_thermal_meter(hw); */ - /* rtl92d_dm_refresh_rate_adaptive_mask(hw); */ - /* rtl92d_dm_interrupt_migration(hw); */ - rtl92d_dm_check_edca_turbo(hw); - } -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.h b/drivers/net/wireless/rtlwifi/rtl8192de/dm.h deleted file mode 100644 index f2d318ceeb28..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/dm.h +++ /dev/null @@ -1,123 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_DM_H__ -#define __RTL92C_DM_H__ - -#define HAL_DM_DIG_DISABLE BIT(0) -#define HAL_DM_HIPWR_DISABLE BIT(1) - -#define OFDM_TABLE_LENGTH 37 -#define OFDM_TABLE_SIZE_92D 43 -#define CCK_TABLE_LENGTH 33 - -#define CCK_TABLE_SIZE 33 - -#define BW_AUTO_SWITCH_HIGH_LOW 25 -#define BW_AUTO_SWITCH_LOW_HIGH 30 - -#define DM_DIG_FA_UPPER 0x32 -#define DM_DIG_FA_LOWER 0x20 -#define DM_DIG_FA_TH0 0x100 -#define DM_DIG_FA_TH1 0x400 -#define DM_DIG_FA_TH2 0x600 - -#define RXPATHSELECTION_SS_TH_lOW 30 -#define RXPATHSELECTION_DIFF_TH 18 - -#define DM_RATR_STA_INIT 0 -#define DM_RATR_STA_HIGH 1 -#define DM_RATR_STA_MIDDLE 2 -#define DM_RATR_STA_LOW 3 - -#define CTS2SELF_THVAL 30 -#define REGC38_TH 20 - -#define WAIOTTHVAL 25 - -#define TXHIGHPWRLEVEL_NORMAL 0 -#define TXHIGHPWRLEVEL_LEVEL1 1 -#define TXHIGHPWRLEVEL_LEVEL2 2 -#define TXHIGHPWRLEVEL_BT1 3 -#define TXHIGHPWRLEVEL_BT2 4 - -#define DM_TYPE_BYFW 0 -#define DM_TYPE_BYDRIVER 1 - -#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 -#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 -#define INDEX_MAPPING_NUM 13 - -struct swat { - u8 failure_cnt; - u8 try_flag; - u8 stop_trying; - long pre_rssi; - long trying_threshold; - u8 cur_antenna; - u8 pre_antenna; -}; - -enum tag_dynamic_init_gain_operation_type_definition { - DIG_TYPE_THRESH_HIGH = 0, - DIG_TYPE_THRESH_LOW = 1, - DIG_TYPE_BACKOFF = 2, - DIG_TYPE_RX_GAIN_MIN = 3, - DIG_TYPE_RX_GAIN_MAX = 4, - DIG_TYPE_ENABLE = 5, - DIG_TYPE_DISABLE = 6, - DIG_OP_TYPE_MAX -}; - -enum dm_1r_cca { - CCA_1R = 0, - CCA_2R = 1, - CCA_MAX = 2, -}; - -enum dm_rf { - RF_SAVE = 0, - RF_NORMAL = 1, - RF_MAX = 2, -}; - -enum dm_sw_ant_switch { - ANS_ANTENNA_B = 1, - ANS_ANTENNA_A = 2, - ANS_ANTENNA_MAX = 3, -}; - -void rtl92d_dm_init(struct ieee80211_hw *hw); -void rtl92d_dm_watchdog(struct ieee80211_hw *hw); -void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw); -void rtl92d_dm_write_dig(struct ieee80211_hw *hw); -void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw); -void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c deleted file mode 100644 index 62ef8209718f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c +++ /dev/null @@ -1,763 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "reg.h" -#include "def.h" -#include "fw.h" -#include "sw.h" - -static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv) -{ - return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ? - true : false; -} - -static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp; - - if (enable) { - tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04); - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); - rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); - rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); - } else { - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); - rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); - /* Reserved for fw extension. - * 0x81[7] is used for mac0 status , - * so don't write this reg here - * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/ - } -} - -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; - 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); - pagenums = size / FW_8192D_PAGE_SIZE; - remainSize = size % FW_8192D_PAGE_SIZE; - if (pagenums > 8) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "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); - } - if (remainSize) { - offset = pagenums * FW_8192D_PAGE_SIZE; - page = pagenums; - _rtl92d_fw_page_write(hw, page, (bufferPtr + offset), - remainSize); - } -} - -static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 counter = 0; - u32 value32; - - do { - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - } while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) && - (!(value32 & FWDL_ChkSum_rpt))); - if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "chksum report faill ! REG_MCUFWDL:0x%08x\n", - value32); - return -EIO; - } - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "Checksum report OK ! REG_MCUFWDL:0x%08x\n", value32); - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - value32 |= MCUFWDL_RDY; - rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); - return 0; -} - -void rtl92d_firmware_selfreset(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 u1b_tmp; - u8 delay = 100; - - /* Set (REG_HMETFR + 3) to 0x20 is reset 8051 */ - rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20); - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - while (u1b_tmp & BIT(2)) { - delay--; - if (delay == 0) - break; - udelay(50); - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - } - RT_ASSERT((delay > 0), "8051 reset failed!\n"); - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "=====> 8051 reset success (%d)\n", delay); -} - -static int _rtl92d_fw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 counter; - - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, "FW already have download\n"); - /* polling for FW ready */ - counter = 0; - do { - if (rtlhal->interfaceindex == 0) { - if (rtl_read_byte(rtlpriv, FW_MAC0_READY) & - MAC0_READY) { - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "Polling FW ready success!! REG_MCUFWDL: 0x%x\n", - rtl_read_byte(rtlpriv, - FW_MAC0_READY)); - return 0; - } - udelay(5); - } else { - if (rtl_read_byte(rtlpriv, FW_MAC1_READY) & - MAC1_READY) { - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "Polling FW ready success!! REG_MCUFWDL: 0x%x\n", - rtl_read_byte(rtlpriv, - FW_MAC1_READY)); - return 0; - } - udelay(5); - } - } while (counter++ < POLLING_READY_TIMEOUT_COUNT); - - if (rtlhal->interfaceindex == 0) { - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "Polling FW ready fail!! MAC0 FW init not ready: 0x%x\n", - rtl_read_byte(rtlpriv, FW_MAC0_READY)); - } else { - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "Polling FW ready fail!! MAC1 FW init not ready: 0x%x\n", - rtl_read_byte(rtlpriv, FW_MAC1_READY)); - } - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "Polling FW ready fail!! REG_MCUFWDL:0x%08ul\n", - rtl_read_dword(rtlpriv, REG_MCUFWDL)); - return -1; -} - -int rtl92d_download_fw(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 *pfwheader; - u8 *pfwdata; - u32 fwsize; - int err; - enum version_8192d version = rtlhal->version; - u8 value; - u32 count; - bool fw_downloaded = false, fwdl_in_process = false; - unsigned long flags; - - if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) - return 1; - fwsize = rtlhal->fwsize; - pfwheader = rtlhal->pfirmware; - pfwdata = rtlhal->pfirmware; - rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader); - rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "FirmwareVersion(%d), FirmwareSubVersion(%d), Signature(%#x)\n", - rtlhal->fw_version, rtlhal->fw_subversion, - GET_FIRMWARE_HDR_SIGNATURE(pfwheader)); - if (IS_FW_HEADER_EXIST(pfwheader)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Shift 32 bytes for FW header!!\n"); - pfwdata = pfwdata + 32; - fwsize = fwsize - 32; - } - - spin_lock_irqsave(&globalmutex_for_fwdownload, flags); - fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv); - if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5)) - fwdl_in_process = true; - else - fwdl_in_process = false; - if (fw_downloaded) { - spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); - goto exit; - } else if (fwdl_in_process) { - spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); - for (count = 0; count < 5000; count++) { - udelay(500); - spin_lock_irqsave(&globalmutex_for_fwdownload, flags); - fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv); - if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5)) - fwdl_in_process = true; - else - fwdl_in_process = false; - spin_unlock_irqrestore(&globalmutex_for_fwdownload, - flags); - if (fw_downloaded) - goto exit; - else if (!fwdl_in_process) - break; - else - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "Wait for another mac download fw\n"); - } - spin_lock_irqsave(&globalmutex_for_fwdownload, flags); - value = rtl_read_byte(rtlpriv, 0x1f); - value |= BIT(5); - rtl_write_byte(rtlpriv, 0x1f, value); - spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); - } else { - value = rtl_read_byte(rtlpriv, 0x1f); - value |= BIT(5); - rtl_write_byte(rtlpriv, 0x1f, value); - spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); - } - - /* If 8051 is running in RAM code, driver should - * inform Fw to reset by itself, or it will cause - * download Fw fail.*/ - /* 8051 RAM code */ - if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { - rtl92d_firmware_selfreset(hw); - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); - } - _rtl92d_enable_fw_download(hw, true); - _rtl92d_write_fw(hw, version, pfwdata, fwsize); - _rtl92d_enable_fw_download(hw, false); - spin_lock_irqsave(&globalmutex_for_fwdownload, flags); - err = _rtl92d_fw_free_to_go(hw); - /* download fw over,clear 0x1f[5] */ - value = rtl_read_byte(rtlpriv, 0x1f); - value &= (~BIT(5)); - rtl_write_byte(rtlpriv, 0x1f, value); - spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "fw is not ready to run!\n"); - goto exit; - } else { - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "fw is ready to run!\n"); - } -exit: - err = _rtl92d_fw_init(hw); - return err; -} - -static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 val_hmetfr; - bool result = false; - - val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); - if (((val_hmetfr >> boxnum) & BIT(0)) == 0) - result = true; - return result; -} - -static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, u8 *cmdbuffer) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 boxnum; - u16 box_reg = 0, box_extreg = 0; - u8 u1b_tmp; - bool isfw_read = false; - u8 buf_index = 0; - bool bwrite_success = false; - u8 wait_h2c_limmit = 100; - u8 wait_writeh2c_limmit = 100; - u8 boxcontent[4], boxextcontent[2]; - u32 h2c_waitcounter = 0; - unsigned long flag; - u8 idx; - - if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Return as RF is off!!!\n"); - return; - } - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); - while (true) { - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - if (rtlhal->h2c_setinprogress) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C set in progress! Wait to set..element_id(%d)\n", - element_id); - - while (rtlhal->h2c_setinprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, - flag); - h2c_waitcounter++; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Wait 100 us (%d times)...\n", - h2c_waitcounter); - udelay(100); - - if (h2c_waitcounter > 1000) - return; - - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, - flag); - } - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - } else { - rtlhal->h2c_setinprogress = true; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - break; - } - } - while (!bwrite_success) { - wait_writeh2c_limmit--; - if (wait_writeh2c_limmit == 0) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Write H2C fail because no trigger for FW INT!\n"); - break; - } - boxnum = rtlhal->last_hmeboxnum; - switch (boxnum) { - case 0: - box_reg = REG_HMEBOX_0; - box_extreg = REG_HMEBOX_EXT_0; - break; - case 1: - box_reg = REG_HMEBOX_1; - box_extreg = REG_HMEBOX_EXT_1; - break; - case 2: - box_reg = REG_HMEBOX_2; - box_extreg = REG_HMEBOX_EXT_2; - break; - case 3: - box_reg = REG_HMEBOX_3; - box_extreg = REG_HMEBOX_EXT_3; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum); - while (!isfw_read) { - wait_h2c_limmit--; - if (wait_h2c_limmit == 0) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Waiting too long for FW read clear HMEBox(%d)!\n", - boxnum); - break; - } - udelay(10); - isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum); - u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF); - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n", - boxnum, u1b_tmp); - } - if (!isfw_read) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", - boxnum); - break; - } - memset(boxcontent, 0, sizeof(boxcontent)); - memset(boxextcontent, 0, sizeof(boxextcontent)); - boxcontent[0] = element_id; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Write element_id box_reg(%4x) = %2x\n", - box_reg, element_id); - switch (cmd_len) { - case 1: - boxcontent[0] &= ~(BIT(7)); - memcpy(boxcontent + 1, cmdbuffer + buf_index, 1); - for (idx = 0; idx < 4; idx++) - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - break; - case 2: - boxcontent[0] &= ~(BIT(7)); - memcpy(boxcontent + 1, cmdbuffer + buf_index, 2); - for (idx = 0; idx < 4; idx++) - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - break; - case 3: - boxcontent[0] &= ~(BIT(7)); - memcpy(boxcontent + 1, cmdbuffer + buf_index, 3); - for (idx = 0; idx < 4; idx++) - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - break; - case 4: - boxcontent[0] |= (BIT(7)); - memcpy(boxextcontent, cmdbuffer + buf_index, 2); - memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2); - for (idx = 0; idx < 2; idx++) - rtl_write_byte(rtlpriv, box_extreg + idx, - boxextcontent[idx]); - for (idx = 0; idx < 4; idx++) - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - break; - case 5: - boxcontent[0] |= (BIT(7)); - memcpy(boxextcontent, cmdbuffer + buf_index, 2); - memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3); - for (idx = 0; idx < 2; idx++) - rtl_write_byte(rtlpriv, box_extreg + idx, - boxextcontent[idx]); - for (idx = 0; idx < 4; idx++) - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - bwrite_success = true; - rtlhal->last_hmeboxnum = boxnum + 1; - if (rtlhal->last_hmeboxnum == 4) - rtlhal->last_hmeboxnum = 0; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "pHalData->last_hmeboxnum = %d\n", - rtlhal->last_hmeboxnum); - } - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - rtlhal->h2c_setinprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); -} - -void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, u8 *cmdbuffer) -{ - u32 tmp_cmdbuf[2]; - - memset(tmp_cmdbuf, 0, 8); - memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); - _rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); - return; -} - -static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring; - struct rtl_tx_desc *pdesc; - u8 idx = 0; - unsigned long flags; - struct sk_buff *pskb; - - ring = &rtlpci->tx_ring[BEACON_QUEUE]; - pskb = __skb_dequeue(&ring->queue); - kfree_skb(pskb); - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - pdesc = &ring->desc[idx]; - /* discard output from call below */ - rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); - rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); - __skb_queue_tail(&ring->queue, skb); - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); - return true; -} - -#define BEACON_PG 0 /*->1 */ -#define PSPOLL_PG 2 -#define NULL_PG 3 -#define PROBERSP_PG 4 /*->5 */ -#define TOTAL_RESERVED_PKT_LEN 768 - -static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { - /* page 0 beacon */ - 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, - 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, - 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, - 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, - 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, - 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, - 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 1 beacon */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 2 ps-poll */ - 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 3 null */ - 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 4 probe_resp */ - 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, - 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, - 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, - 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, - 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, - 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, - 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, - 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, - 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 5 probe_resp */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct sk_buff *skb = NULL; - u32 totalpacketlen; - bool rtstatus; - u8 u1RsvdPageLoc[3] = { 0 }; - bool dlok = false; - u8 *beacon; - u8 *p_pspoll; - u8 *nullfunc; - u8 *p_probersp; - /*--------------------------------------------------------- - (1) beacon - ---------------------------------------------------------*/ - beacon = &reserved_page_packet[BEACON_PG * 128]; - SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); - SET_80211_HDR_ADDRESS3(beacon, mac->bssid); - /*------------------------------------------------------- - (2) ps-poll - --------------------------------------------------------*/ - p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; - SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); - SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); - SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); - SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); - /*-------------------------------------------------------- - (3) null data - ---------------------------------------------------------*/ - nullfunc = &reserved_page_packet[NULL_PG * 128]; - SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); - SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); - SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); - SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); - /*--------------------------------------------------------- - (4) probe response - ----------------------------------------------------------*/ - p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; - SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); - SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); - SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); - SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG); - totalpacketlen = TOTAL_RESERVED_PKT_LEN; - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL", - &reserved_page_packet[0], totalpacketlen); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL", - u1RsvdPageLoc, 3); - skb = dev_alloc_skb(totalpacketlen); - if (!skb) { - dlok = false; - } else { - memcpy((u8 *) skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); - rtstatus = _rtl92d_cmd_send_packet(hw, skb); - - if (rtstatus) - dlok = true; - } - if (dlok) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Set RSVD page location to Fw\n"); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "H2C_RSVDPAGE", u1RsvdPageLoc, 3); - rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE, - sizeof(u1RsvdPageLoc), u1RsvdPageLoc); - } else - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set RSVD page location to Fw FAIL!!!!!!\n"); -} - -void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) -{ - u8 u1_joinbssrpt_parm[1] = {0}; - - SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); - rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.h b/drivers/net/wireless/rtlwifi/rtl8192de/fw.h deleted file mode 100644 index 8a38daa316cb..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/fw.h +++ /dev/null @@ -1,120 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92D__FW__H__ -#define __RTL92D__FW__H__ - -#define FW_8192D_START_ADDRESS 0x1000 -#define FW_8192D_PAGE_SIZE 4096 -#define FW_8192D_POLLING_TIMEOUT_COUNT 1000 - -#define IS_FW_HEADER_EXIST(_pfwhdr) \ - ((GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFF0) == 0x92C0 || \ - (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFF0) == 0x88C0 || \ - (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D0 || \ - (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D1 || \ - (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D2 || \ - (GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D3) - -/* Define a macro that takes an 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, __mask) \ - ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ - BIT_LEN_MASK_32(__mask)) - -/* Firmware Header(8-byte alinment required) */ -/* --- LONG WORD 0 ---- */ -#define GET_FIRMWARE_HDR_SIGNATURE(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr, 0, 16) -#define GET_FIRMWARE_HDR_CATEGORY(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr, 16, 8) -#define GET_FIRMWARE_HDR_FUNCTION(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr, 24, 8) -#define GET_FIRMWARE_HDR_VERSION(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 4, 0, 16) -#define GET_FIRMWARE_HDR_SUB_VER(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 4, 16, 8) -#define GET_FIRMWARE_HDR_RSVD1(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 4, 24, 8) - -/* --- LONG WORD 1 ---- */ -#define GET_FIRMWARE_HDR_MONTH(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 8, 0, 8) -#define GET_FIRMWARE_HDR_DATE(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 8, 8, 8) -#define GET_FIRMWARE_HDR_HOUR(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 8, 16, 8) -#define GET_FIRMWARE_HDR_MINUTE(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 8, 24, 8) -#define GET_FIRMWARE_HDR_ROMCODE_SIZE(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 12, 0, 16) -#define GET_FIRMWARE_HDR_RSVD2(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 12, 16, 16) - -/* --- LONG WORD 2 ---- */ -#define GET_FIRMWARE_HDR_SVN_IDX(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 16, 0, 32) -#define GET_FIRMWARE_HDR_RSVD3(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 20, 0, 32) - -/* --- LONG WORD 3 ---- */ -#define GET_FIRMWARE_HDR_RSVD4(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 24, 0, 32) -#define GET_FIRMWARE_HDR_RSVD5(__fwhdr) \ - SHIFT_AND_MASK_LE(__fwhdr + 28, 0, 32) - -#define pagenum_128(_len) \ - (u32)(((_len) >> 7) + ((_len) & 0x7F ? 1 : 0)) - -#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val) -#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val) - -int rtl92d_download_fw(struct ieee80211_hw *hw); -void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *p_cmdbuffer); -void rtl92d_firmware_selfreset(struct ieee80211_hw *hw); -void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); -void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c deleted file mode 100644 index f49b60d31450..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c +++ /dev/null @@ -1,2307 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../efuse.h" -#include "../base.h" -#include "../regd.h" -#include "../cam.h" -#include "../ps.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "fw.h" -#include "led.h" -#include "sw.h" -#include "hw.h" - -u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, u8 direct) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 value; - - rtl_write_word(rtlpriv, REG_DBI_CTRL, (offset & 0xFFC)); - rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(1) | direct); - udelay(10); - value = rtl_read_dword(rtlpriv, REG_DBI_RDATA); - return value; -} - -void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, - u16 offset, u32 value, u8 direct) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_word(rtlpriv, REG_DBI_CTRL, ((offset & 0xFFC) | 0xF000)); - rtl_write_dword(rtlpriv, REG_DBI_WDATA, value); - rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(0) | direct); -} - -static void _rtl92de_set_bcn_ctrl_reg(struct ieee80211_hw *hw, - u8 set_bits, u8 clear_bits) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpci->reg_bcn_ctrl_val |= set_bits; - rtlpci->reg_bcn_ctrl_val &= ~clear_bits; - rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); -} - -static void _rtl92de_stop_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp1byte; - - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); - rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); -} - -static void _rtl92de_resume_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp1byte; - - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); - rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte |= BIT(0); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); -} - -static void _rtl92de_enable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(1)); -} - -static void _rtl92de_disable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl92de_set_bcn_ctrl_reg(hw, BIT(1), 0); -} - -void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - switch (variable) { - case HW_VAR_RCR: - *((u32 *) (val)) = rtlpci->receive_config; - break; - case HW_VAR_RF_STATE: - *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; - break; - case HW_VAR_FWLPS_RF_ON:{ - enum rf_pwrstate rfState; - u32 val_rcr; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, - (u8 *) (&rfState)); - if (rfState == ERFOFF) { - *((bool *) (val)) = true; - } else { - val_rcr = rtl_read_dword(rtlpriv, REG_RCR); - val_rcr &= 0x00070000; - if (val_rcr) - *((bool *) (val)) = false; - else - *((bool *) (val)) = true; - } - break; - } - case HW_VAR_FW_PSMODE_STATUS: - *((bool *) (val)) = ppsc->fw_current_inpsmode; - break; - case HW_VAR_CORRECT_TSF:{ - u64 tsf; - u32 *ptsf_low = (u32 *)&tsf; - u32 *ptsf_high = ((u32 *)&tsf) + 1; - - *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); - *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - *((u64 *) (val)) = tsf; - break; - } - case HW_VAR_INT_MIGRATION: - *((bool *)(val)) = rtlpriv->dm.interrupt_migration; - break; - case HW_VAR_INT_AC: - *((bool *)(val)) = rtlpriv->dm.disable_tx_int; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } -} - -void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 idx; - - switch (variable) { - case HW_VAR_ETHER_ADDR: - for (idx = 0; idx < ETH_ALEN; idx++) { - rtl_write_byte(rtlpriv, (REG_MACID + idx), - val[idx]); - } - break; - case HW_VAR_BASIC_RATE: { - u16 rate_cfg = ((u16 *) val)[0]; - u8 rate_index = 0; - - rate_cfg = rate_cfg & 0x15f; - if (mac->vendor == PEER_CISCO && - ((rate_cfg & 0x150) == 0)) - rate_cfg |= 0x01; - rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); - rtl_write_byte(rtlpriv, REG_RRSR + 1, - (rate_cfg >> 8) & 0xff); - while (rate_cfg > 0x1) { - rate_cfg = (rate_cfg >> 1); - rate_index++; - } - if (rtlhal->fw_version > 0xe) - rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, - rate_index); - break; - } - case HW_VAR_BSSID: - for (idx = 0; idx < ETH_ALEN; idx++) { - rtl_write_byte(rtlpriv, (REG_BSSID + idx), - val[idx]); - } - break; - case HW_VAR_SIFS: - rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); - rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); - rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); - rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); - if (!mac->ht_enable) - rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, - 0x0e0e); - else - rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, - *((u16 *) val)); - break; - case HW_VAR_SLOT_TIME: { - u8 e_aci; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "HW_VAR_SLOT_TIME %x\n", val[0]); - rtl_write_byte(rtlpriv, REG_SLOT, val[0]); - for (e_aci = 0; e_aci < AC_MAX; e_aci++) - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AC_PARAM, - (&e_aci)); - break; - } - case HW_VAR_ACK_PREAMBLE: { - u8 reg_tmp; - u8 short_preamble = (bool) (*val); - - reg_tmp = (mac->cur_40_prime_sc) << 5; - if (short_preamble) - reg_tmp |= 0x80; - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp); - break; - } - case HW_VAR_AMPDU_MIN_SPACE: { - u8 min_spacing_to_set; - u8 sec_min_space; - - min_spacing_to_set = *val; - if (min_spacing_to_set <= 7) { - sec_min_space = 0; - if (min_spacing_to_set < sec_min_space) - min_spacing_to_set = sec_min_space; - mac->min_space_cfg = ((mac->min_space_cfg & 0xf8) | - min_spacing_to_set); - *val = min_spacing_to_set; - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", - mac->min_space_cfg); - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - } - break; - } - case HW_VAR_SHORTGI_DENSITY: { - u8 density_to_set; - - density_to_set = *val; - mac->min_space_cfg = rtlpriv->rtlhal.minspace_cfg; - mac->min_space_cfg |= (density_to_set << 3); - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_SHORTGI_DENSITY: %#x\n", - mac->min_space_cfg); - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - break; - } - case HW_VAR_AMPDU_FACTOR: { - u8 factor_toset; - u32 regtoSet; - u8 *ptmp_byte = NULL; - u8 index; - - if (rtlhal->macphymode == DUALMAC_DUALPHY) - regtoSet = 0xb9726641; - else if (rtlhal->macphymode == DUALMAC_SINGLEPHY) - regtoSet = 0x66626641; - else - regtoSet = 0xb972a841; - factor_toset = *val; - if (factor_toset <= 3) { - factor_toset = (1 << (factor_toset + 2)); - if (factor_toset > 0xf) - factor_toset = 0xf; - for (index = 0; index < 4; index++) { - ptmp_byte = (u8 *) (®toSet) + index; - if ((*ptmp_byte & 0xf0) > - (factor_toset << 4)) - *ptmp_byte = (*ptmp_byte & 0x0f) - | (factor_toset << 4); - if ((*ptmp_byte & 0x0f) > factor_toset) - *ptmp_byte = (*ptmp_byte & 0xf0) - | (factor_toset); - } - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, regtoSet); - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_FACTOR: %#x\n", - factor_toset); - } - break; - } - case HW_VAR_AC_PARAM: { - u8 e_aci = *val; - rtl92d_dm_init_edca_turbo(hw); - if (rtlpci->acm_method != EACMWAY2_SW) - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, - &e_aci); - break; - } - case HW_VAR_ACM_CTRL: { - u8 e_aci = *val; - union aci_aifsn *p_aci_aifsn = - (union aci_aifsn *)(&(mac->ac[0].aifs)); - u8 acm = p_aci_aifsn->f.acm; - u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); - - acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); - if (acm) { - switch (e_aci) { - case AC0_BE: - acm_ctrl |= ACMHW_BEQEN; - break; - case AC2_VI: - acm_ctrl |= ACMHW_VIQEN; - break; - case AC3_VO: - acm_ctrl |= ACMHW_VOQEN; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", - acm); - break; - } - } else { - switch (e_aci) { - case AC0_BE: - acm_ctrl &= (~ACMHW_BEQEN); - break; - case AC2_VI: - acm_ctrl &= (~ACMHW_VIQEN); - break; - case AC3_VO: - acm_ctrl &= (~ACMHW_VOQEN); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - } - RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, - "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", - acm_ctrl); - rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); - break; - } - case HW_VAR_RCR: - rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]); - rtlpci->receive_config = ((u32 *) (val))[0]; - break; - case HW_VAR_RETRY_LIMIT: { - u8 retry_limit = val[0]; - - rtl_write_word(rtlpriv, REG_RL, - retry_limit << RETRY_LIMIT_SHORT_SHIFT | - retry_limit << RETRY_LIMIT_LONG_SHIFT); - break; - } - case HW_VAR_DUAL_TSF_RST: - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); - break; - case HW_VAR_EFUSE_BYTES: - rtlefuse->efuse_usedbytes = *((u16 *) val); - break; - case HW_VAR_EFUSE_USAGE: - rtlefuse->efuse_usedpercentage = *val; - break; - case HW_VAR_IO_CMD: - rtl92d_phy_set_io_cmd(hw, (*(enum io_type *)val)); - break; - case HW_VAR_WPA_CONFIG: - rtl_write_byte(rtlpriv, REG_SECCFG, *val); - break; - case HW_VAR_SET_RPWM: - rtl92d_fill_h2c_cmd(hw, H2C_PWRM, 1, (val)); - break; - case HW_VAR_H2C_FW_PWRMODE: - break; - case HW_VAR_FW_PSMODE_STATUS: - ppsc->fw_current_inpsmode = *((bool *) val); - break; - case HW_VAR_H2C_FW_JOINBSSRPT: { - u8 mstatus = (*val); - u8 tmp_regcr, tmp_reg422; - bool recover = false; - - if (mstatus == RT_MEDIA_CONNECT) { - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AID, NULL); - tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, - (tmp_regcr | BIT(0))); - _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3)); - _rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0); - tmp_reg422 = rtl_read_byte(rtlpriv, - REG_FWHW_TXQ_CTRL + 2); - if (tmp_reg422 & BIT(6)) - recover = true; - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, - tmp_reg422 & (~BIT(6))); - rtl92d_set_fw_rsvdpagepkt(hw, 0); - _rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0); - _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4)); - if (recover) - rtl_write_byte(rtlpriv, - REG_FWHW_TXQ_CTRL + 2, - tmp_reg422); - rtl_write_byte(rtlpriv, REG_CR + 1, - (tmp_regcr & ~(BIT(0)))); - } - rtl92d_set_fw_joinbss_report_cmd(hw, (*val)); - break; - } - case HW_VAR_AID: { - u16 u2btmp; - u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); - u2btmp &= 0xC000; - rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | - mac->assoc_id)); - break; - } - case HW_VAR_CORRECT_TSF: { - u8 btype_ibss = val[0]; - - if (btype_ibss) - _rtl92de_stop_tx_beacon(hw); - _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3)); - rtl_write_dword(rtlpriv, REG_TSFTR, - (u32) (mac->tsf & 0xffffffff)); - rtl_write_dword(rtlpriv, REG_TSFTR + 4, - (u32) ((mac->tsf >> 32) & 0xffffffff)); - _rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0); - if (btype_ibss) - _rtl92de_resume_tx_beacon(hw); - - break; - } - case HW_VAR_INT_MIGRATION: { - bool int_migration = *(bool *) (val); - - if (int_migration) { - /* Set interrupt migration timer and - * corresponding Tx/Rx counter. - * timer 25ns*0xfa0=100us for 0xf packets. - * 0x306:Rx, 0x307:Tx */ - rtl_write_dword(rtlpriv, REG_INT_MIG, 0xfe000fa0); - rtlpriv->dm.interrupt_migration = int_migration; - } else { - /* Reset all interrupt migration settings. */ - rtl_write_dword(rtlpriv, REG_INT_MIG, 0); - rtlpriv->dm.interrupt_migration = int_migration; - } - break; - } - case HW_VAR_INT_AC: { - bool disable_ac_int = *((bool *) val); - - /* Disable four ACs interrupts. */ - if (disable_ac_int) { - /* Disable VO, VI, BE and BK four AC interrupts - * to gain more efficient CPU utilization. - * When extremely highly Rx OK occurs, - * we will disable Tx interrupts. - */ - rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, - RT_AC_INT_MASKS); - rtlpriv->dm.disable_tx_int = disable_ac_int; - /* Enable four ACs interrupts. */ - } else { - rtlpriv->cfg->ops->update_interrupt_mask(hw, - RT_AC_INT_MASKS, 0); - rtlpriv->dm.disable_tx_int = disable_ac_int; - } - break; - } - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } -} - -static bool _rtl92de_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool status = true; - long count = 0; - u32 value = _LLT_INIT_ADDR(address) | - _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); - - rtl_write_dword(rtlpriv, REG_LLT_INIT, value); - do { - value = rtl_read_dword(rtlpriv, REG_LLT_INIT); - if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) - break; - if (count > POLLING_LLT_THRESHOLD) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to polling write LLT done at address %d!\n", - address); - status = false; - break; - } - } while (++count); - return status; -} - -static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - unsigned short i; - u8 txpktbuf_bndy; - u8 maxPage; - bool status; - u32 value32; /* High+low page number */ - u8 value8; /* normal page number */ - - if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) { - maxPage = 255; - txpktbuf_bndy = 246; - value8 = 0; - value32 = 0x80bf0d29; - } else { - maxPage = 127; - txpktbuf_bndy = 123; - value8 = 0; - value32 = 0x80750005; - } - - /* Set reserved page for each queue */ - /* 11. RQPN 0x200[31:0] = 0x80BD1C1C */ - /* load RQPN */ - rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8); - rtl_write_dword(rtlpriv, REG_RQPN, value32); - - /* 12. TXRKTBUG_PG_BNDY 0x114[31:0] = 0x27FF00F6 */ - /* TXRKTBUG_PG_BNDY */ - rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, - (rtl_read_word(rtlpriv, REG_TRXFF_BNDY + 2) << 16 | - txpktbuf_bndy)); - - /* 13. TDECTRL[15:8] 0x209[7:0] = 0xF6 */ - /* Beacon Head for TXDMA */ - rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); - - /* 14. BCNQ_PGBNDY 0x424[7:0] = 0xF6 */ - /* BCNQ_PGBNDY */ - rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); - - /* 15. WMAC_LBK_BF_HD 0x45D[7:0] = 0xF6 */ - /* WMAC_LBK_BF_HD */ - rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); - - /* Set Tx/Rx page size (Tx must be 128 Bytes, */ - /* Rx can be 64,128,256,512,1024 bytes) */ - /* 16. PBP [7:0] = 0x11 */ - /* TRX page size */ - rtl_write_byte(rtlpriv, REG_PBP, 0x11); - - /* 17. DRV_INFO_SZ = 0x04 */ - rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); - - /* 18. LLT_table_init(Adapter); */ - for (i = 0; i < (txpktbuf_bndy - 1); i++) { - status = _rtl92de_llt_write(hw, i, i + 1); - if (true != status) - return status; - } - - /* end of list */ - status = _rtl92de_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); - if (true != status) - return status; - - /* Make the other pages as ring buffer */ - /* This ring buffer is used as beacon buffer if we */ - /* config this MAC as two MAC transfer. */ - /* Otherwise used as local loopback buffer. */ - for (i = txpktbuf_bndy; i < maxPage; i++) { - status = _rtl92de_llt_write(hw, i, (i + 1)); - if (true != status) - return status; - } - - /* Let last entry point to the start entry of ring buffer */ - status = _rtl92de_llt_write(hw, maxPage, txpktbuf_bndy); - if (true != status) - return status; - - return true; -} - -static void _rtl92de_gen_refresh_led_state(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); - - if (rtlpci->up_first_time) - return; - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtl92de_sw_led_on(hw, pLed0); - else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - rtl92de_sw_led_on(hw, pLed0); - else - rtl92de_sw_led_off(hw, pLed0); -} - -static bool _rtl92de_init_mac(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - unsigned char bytetmp; - unsigned short wordtmp; - u16 retry; - - rtl92d_phy_set_poweron(hw); - /* Add for resume sequence of power domain according - * to power document V11. Chapter V.11.... */ - /* 0. RSV_CTRL 0x1C[7:0] = 0x00 */ - /* unlock ISO/CLK/Power control register */ - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); - rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x05); - - /* 1. AFE_XTAL_CTRL [7:0] = 0x0F enable XTAL */ - /* 2. SPS0_CTRL 0x11[7:0] = 0x2b enable SPS into PWM mode */ - /* 3. delay (1ms) this is not necessary when initially power on */ - - /* C. Resume Sequence */ - /* a. SPS0_CTRL 0x11[7:0] = 0x2b */ - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); - - /* b. AFE_XTAL_CTRL [7:0] = 0x0F */ - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F); - - /* c. DRV runs power on init flow */ - - /* auto enable WLAN */ - /* 4. APS_FSMCO 0x04[8] = 1; wait till 0x04[8] = 0 */ - /* Power On Reset for MAC Block */ - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0); - udelay(2); - rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); - udelay(2); - - /* 5. Wait while 0x04[8] == 0 goto 2, otherwise goto 1 */ - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); - udelay(50); - retry = 0; - while ((bytetmp & BIT(0)) && retry < 1000) { - retry++; - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); - udelay(50); - } - - /* Enable Radio off, GPIO, and LED function */ - /* 6. APS_FSMCO 0x04[15:0] = 0x0012 when enable HWPDN */ - rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x1012); - - /* release RF digital isolation */ - /* 7. SYS_ISO_CTRL 0x01[1] = 0x0; */ - /*Set REG_SYS_ISO_CTRL 0x1=0x82 to prevent wake# problem. */ - rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82); - udelay(2); - - /* make sure that BB reset OK. */ - /* rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); */ - - /* Disable REG_CR before enable it to assure reset */ - rtl_write_word(rtlpriv, REG_CR, 0x0); - - /* Release MAC IO register reset */ - rtl_write_word(rtlpriv, REG_CR, 0x2ff); - - /* clear stopping tx/rx dma */ - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x0); - - /* rtl_write_word(rtlpriv,REG_CR+2, 0x2); */ - - /* System init */ - /* 18. LLT_table_init(Adapter); */ - if (!_rtl92de_llt_table_init(hw)) - return false; - - /* Clear interrupt and enable interrupt */ - /* 19. HISR 0x124[31:0] = 0xffffffff; */ - /* HISRE 0x12C[7:0] = 0xFF */ - rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); - rtl_write_byte(rtlpriv, REG_HISRE, 0xff); - - /* 20. HIMR 0x120[31:0] |= [enable INT mask bit map]; */ - /* 21. HIMRE 0x128[7:0] = [enable INT mask bit map] */ - /* The IMR should be enabled later after all init sequence - * is finished. */ - - /* 22. PCIE configuration space configuration */ - /* 23. Ensure PCIe Device 0x80[15:0] = 0x0143 (ASPM+CLKREQ), */ - /* and PCIe gated clock function is enabled. */ - /* PCIE configuration space will be written after - * all init sequence.(Or by BIOS) */ - - rtl92d_phy_config_maccoexist_rfpage(hw); - - /* THe below section is not related to power document Vxx . */ - /* This is only useful for driver and OS setting. */ - /* -------------------Software Relative Setting---------------------- */ - wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); - wordtmp &= 0xf; - wordtmp |= 0xF771; - rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); - - /* Reported Tx status from HW for rate adaptive. */ - /* This should be realtive to power on step 14. But in document V11 */ - /* still not contain the description.!!! */ - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); - - /* Set Tx/Rx page size (Tx must be 128 Bytes, - * Rx can be 64,128,256,512,1024 bytes) */ - /* rtl_write_byte(rtlpriv,REG_PBP, 0x11); */ - - /* Set RCR register */ - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - /* rtl_write_byte(rtlpriv,REG_RX_DRVINFO_SZ, 4); */ - - /* Set TCR register */ - rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); - - /* disable earlymode */ - rtl_write_byte(rtlpriv, 0x4d0, 0x0); - - /* Set TX/RX descriptor physical address(from OS API). */ - rtl_write_dword(rtlpriv, REG_BCNQ_DESA, - rtlpci->tx_ring[BEACON_QUEUE].dma); - rtl_write_dword(rtlpriv, REG_MGQ_DESA, rtlpci->tx_ring[MGNT_QUEUE].dma); - rtl_write_dword(rtlpriv, REG_VOQ_DESA, rtlpci->tx_ring[VO_QUEUE].dma); - rtl_write_dword(rtlpriv, REG_VIQ_DESA, rtlpci->tx_ring[VI_QUEUE].dma); - rtl_write_dword(rtlpriv, REG_BEQ_DESA, rtlpci->tx_ring[BE_QUEUE].dma); - rtl_write_dword(rtlpriv, REG_BKQ_DESA, rtlpci->tx_ring[BK_QUEUE].dma); - rtl_write_dword(rtlpriv, REG_HQ_DESA, rtlpci->tx_ring[HIGH_QUEUE].dma); - /* Set RX Desc Address */ - rtl_write_dword(rtlpriv, REG_RX_DESA, - rtlpci->rx_ring[RX_MPDU_QUEUE].dma); - - /* if we want to support 64 bit DMA, we should set it here, - * but now we do not support 64 bit DMA*/ - - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x33); - - /* Reset interrupt migration setting when initialization */ - rtl_write_dword(rtlpriv, REG_INT_MIG, 0); - - /* Reconsider when to do this operation after asking HWSD. */ - bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6)); - do { - retry++; - bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); - } while ((retry < 200) && !(bytetmp & BIT(7))); - - /* After MACIO reset,we must refresh LED state. */ - _rtl92de_gen_refresh_led_state(hw); - - /* Reset H2C protection register */ - rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); - - return true; -} - -static void _rtl92de_hw_configure(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 reg_bw_opmode = BW_OPMODE_20MHZ; - u32 reg_rrsr; - - reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8); - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr); - rtl_write_byte(rtlpriv, REG_SLOT, 0x09); - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0); - rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80); - rtl_write_word(rtlpriv, REG_RL, 0x0707); - rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802); - rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); - rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); - rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); - /* Aggregation threshold */ - if (rtlhal->macphymode == DUALMAC_DUALPHY) - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb9726641); - else if (rtlhal->macphymode == DUALMAC_SINGLEPHY) - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x66626641); - else - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); - rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); - rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a); - rtlpci->reg_bcn_ctrl_val = 0x1f; - rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); - rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - /* For throughput */ - rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0x6666); - /* ACKTO for IOT issue. */ - rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); - /* Set Spec SIFS (used in NAV) */ - rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010); - rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010); - /* Set SIFS for CCK */ - rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010); - /* Set SIFS for OFDM */ - rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010); - /* Set Multicast Address. */ - rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff); - rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff); - switch (rtlpriv->phy.rf_type) { - case RF_1T2R: - case RF_1T1R: - rtlhal->minspace_cfg = (MAX_MSS_DENSITY_1T << 3); - break; - case RF_2T2R: - case RF_2T2R_GREEN: - rtlhal->minspace_cfg = (MAX_MSS_DENSITY_2T << 3); - break; - } -} - -static void _rtl92de_enable_aspm_back_door(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - rtl_write_byte(rtlpriv, 0x34b, 0x93); - rtl_write_word(rtlpriv, 0x350, 0x870c); - rtl_write_byte(rtlpriv, 0x352, 0x1); - if (ppsc->support_backdoor) - rtl_write_byte(rtlpriv, 0x349, 0x1b); - else - rtl_write_byte(rtlpriv, 0x349, 0x03); - rtl_write_word(rtlpriv, 0x350, 0x2718); - rtl_write_byte(rtlpriv, 0x352, 0x1); -} - -void rtl92de_enable_hw_security_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 sec_reg_value; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", - rtlpriv->sec.pairwise_enc_algorithm, - rtlpriv->sec.group_enc_algorithm); - if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "not open hw encryption\n"); - return; - } - sec_reg_value = SCR_TXENCENABLE | SCR_RXENCENABLE; - if (rtlpriv->sec.use_defaultkey) { - sec_reg_value |= SCR_TXUSEDK; - sec_reg_value |= SCR_RXUSEDK; - } - sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); - rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "The SECR-value %x\n", sec_reg_value); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); -} - -int rtl92de_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool rtstatus = true; - u8 tmp_u1b; - int i; - int err; - unsigned long flags; - - rtlpci->being_init_adapter = true; - rtlpci->init_ready = false; - spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags); - /* we should do iqk after disable/enable */ - rtl92d_phy_reset_iqk_result(hw); - /* rtlpriv->intf_ops->disable_aspm(hw); */ - rtstatus = _rtl92de_init_mac(hw); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); - err = 1; - spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags); - return err; - } - err = rtl92d_download_fw(hw); - spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Failed to download FW. Init HW without FW..\n"); - return 1; - } - rtlhal->last_hmeboxnum = 0; - rtlpriv->psc.fw_current_inpsmode = false; - - tmp_u1b = rtl_read_byte(rtlpriv, 0x605); - tmp_u1b = tmp_u1b | 0x30; - rtl_write_byte(rtlpriv, 0x605, tmp_u1b); - - if (rtlhal->earlymode_enable) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EarlyMode Enabled!!!\n"); - - tmp_u1b = rtl_read_byte(rtlpriv, 0x4d0); - tmp_u1b = tmp_u1b | 0x1f; - rtl_write_byte(rtlpriv, 0x4d0, tmp_u1b); - - rtl_write_byte(rtlpriv, 0x4d3, 0x80); - - tmp_u1b = rtl_read_byte(rtlpriv, 0x605); - tmp_u1b = tmp_u1b | 0x40; - rtl_write_byte(rtlpriv, 0x605, tmp_u1b); - } - - if (mac->rdg_en) { - rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xff); - rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200); - rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05); - } - - rtl92d_phy_mac_config(hw); - /* because last function modify RCR, so we update - * rcr var here, or TP will unstable for receive_config - * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx - * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/ - rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); - rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); - - rtl92d_phy_bb_config(hw); - - rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; - /* set before initialize RF */ - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf); - - /* config RF */ - rtl92d_phy_rf_config(hw); - - /* After read predefined TXT, we must set BB/MAC/RF - * register as our requirement */ - /* After load BB,RF params,we need do more for 92D. */ - rtl92d_update_bbrf_configuration(hw); - /* set default value after initialize RF, */ - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0); - rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, - RF_CHNLBW, RFREG_OFFSET_MASK); - - /*---- Set CCK and OFDM Block "ON"----*/ - if (rtlhal->current_bandtype == BAND_ON_2_4G) - rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); - if (rtlhal->interfaceindex == 0) { - /* RFPGA0_ANALOGPARAMETER2: cck clock select, - * set to 20MHz by default */ - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) | - BIT(11), 3); - } else { - /* Mac1 */ - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(11) | - BIT(10), 3); - } - - _rtl92de_hw_configure(hw); - - /* reset hw sec */ - rtl_cam_reset_all_entry(hw); - rtl92de_enable_hw_security_config(hw); - - /* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */ - /* TX power index for different rate set. */ - rtl92d_phy_get_hw_reg_originalvalue(hw); - rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel); - - ppsc->rfpwr_state = ERFON; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); - - _rtl92de_enable_aspm_back_door(hw); - /* rtlpriv->intf_ops->enable_aspm(hw); */ - - rtl92d_dm_init(hw); - rtlpci->being_init_adapter = false; - - if (ppsc->rfpwr_state == ERFON) { - rtl92d_phy_lc_calibrate(hw); - /* 5G and 2.4G must wait sometime to let RF LO ready */ - if (rtlhal->macphymode == DUALMAC_DUALPHY) { - u32 tmp_rega; - for (i = 0; i < 10000; i++) { - udelay(MAX_STALL_TIME); - - tmp_rega = rtl_get_rfreg(hw, - (enum radio_path)RF90_PATH_A, - 0x2a, MASKDWORD); - - if (((tmp_rega & BIT(11)) == BIT(11))) - break; - } - /* check that loop was successful. If not, exit now */ - if (i == 10000) { - rtlpci->init_ready = false; - return 1; - } - } - } - rtlpci->init_ready = true; - return err; -} - -static enum version_8192d _rtl92de_read_chip_version(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - enum version_8192d version = VERSION_NORMAL_CHIP_92D_SINGLEPHY; - u32 value32; - - value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); - if (!(value32 & 0x000f0000)) { - version = VERSION_TEST_CHIP_92D_SINGLEPHY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "TEST CHIP!!!\n"); - } else { - version = VERSION_NORMAL_CHIP_92D_SINGLEPHY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Normal CHIP!!!\n"); - } - return version; -} - -static int _rtl92de_set_media_status(struct ieee80211_hw *hw, - enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bt_msr = rtl_read_byte(rtlpriv, MSR); - enum led_ctl_mode ledaction = LED_CTL_NO_LINK; - u8 bcnfunc_enable; - - bt_msr &= 0xfc; - - if (type == NL80211_IFTYPE_UNSPECIFIED || - type == NL80211_IFTYPE_STATION) { - _rtl92de_stop_tx_beacon(hw); - _rtl92de_enable_bcn_sub_func(hw); - } else if (type == NL80211_IFTYPE_ADHOC || - type == NL80211_IFTYPE_AP) { - _rtl92de_resume_tx_beacon(hw); - _rtl92de_disable_bcn_sub_func(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set HW_VAR_MEDIA_STATUS: No such media status(%x)\n", - type); - } - bcnfunc_enable = rtl_read_byte(rtlpriv, REG_BCN_CTRL); - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - bt_msr |= MSR_NOLINK; - ledaction = LED_CTL_LINK; - bcnfunc_enable &= 0xF7; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to NO LINK!\n"); - break; - case NL80211_IFTYPE_ADHOC: - bt_msr |= MSR_ADHOC; - bcnfunc_enable |= 0x08; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to Ad Hoc!\n"); - break; - case NL80211_IFTYPE_STATION: - bt_msr |= MSR_INFRA; - ledaction = LED_CTL_LINK; - bcnfunc_enable &= 0xF7; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to STA!\n"); - break; - case NL80211_IFTYPE_AP: - bt_msr |= MSR_AP; - bcnfunc_enable |= 0x08; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to AP!\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Network type %d not supported!\n", type); - return 1; - break; - - } - rtl_write_byte(rtlpriv, MSR, bt_msr); - rtlpriv->cfg->ops->led_control(hw, ledaction); - if ((bt_msr & MSR_MASK) == MSR_AP) - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); - else - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); - return 0; -} - -void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 reg_rcr; - - if (rtlpriv->psc.rfpwr_state != ERFON) - return; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); - - if (check_bssid) { - reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); - _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4)); - } else if (!check_bssid) { - reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); - _rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); - } -} - -int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (_rtl92de_set_media_status(hw, type)) - return -EOPNOTSUPP; - - /* check bssid */ - if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { - if (type != NL80211_IFTYPE_AP) - rtl92de_set_check_bssid(hw, true); - } else { - rtl92de_set_check_bssid(hw, false); - } - return 0; -} - -/* do iqk or reload iqk */ -/* windows just rtl92d_phy_reload_iqk_setting in set channel, - * but it's very strict for time sequence so we add - * rtl92d_phy_reload_iqk_setting here */ -void rtl92d_linked_set_reg(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u8 indexforchannel; - u8 channel = rtlphy->current_channel; - - indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); - if (!rtlphy->iqk_matrix[indexforchannel].iqk_done) { - RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_DMESG, - "Do IQK for channel:%d\n", channel); - rtl92d_phy_iq_calibrate(hw); - } -} - -/* don't set REG_EDCA_BE_PARAM here because - * mac80211 will send pkt when scan */ -void rtl92de_set_qos(struct ieee80211_hw *hw, int aci) -{ - rtl92d_dm_init_edca_turbo(hw); -} - -void rtl92de_enable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); - rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); -} - -void rtl92de_disable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED); - rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); - synchronize_irq(rtlpci->pdev->irq); -} - -static void _rtl92de_poweroff_adapter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 u1b_tmp; - unsigned long flags; - - rtlpriv->intf_ops->enable_aspm(hw); - rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); - rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(3), 0); - rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(15), 0); - - /* 0x20:value 05-->04 */ - rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x04); - - /* ==== Reset digital sequence ====== */ - rtl92d_firmware_selfreset(hw); - - /* f. SYS_FUNC_EN 0x03[7:0]=0x51 reset MCU, MAC register, DCORE */ - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51); - - /* g. MCUFWDL 0x80[1:0]=0 reset MCU ready status */ - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); - - /* ==== Pull GPIO PIN to balance level and LED control ====== */ - - /* h. GPIO_PIN_CTRL 0x44[31:0]=0x000 */ - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000); - - /* i. Value = GPIO_PIN_CTRL[7:0] */ - u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL); - - /* j. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); */ - /* write external PIN level */ - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, - 0x00FF0000 | (u1b_tmp << 8)); - - /* k. GPIO_MUXCFG 0x42 [15:0] = 0x0780 */ - rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); - - /* l. LEDCFG 0x4C[15:0] = 0x8080 */ - rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); - - /* ==== Disable analog sequence === */ - - /* m. AFE_PLL_CTRL[7:0] = 0x80 disable PLL */ - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); - - /* n. SPS0_CTRL 0x11[7:0] = 0x22 enter PFM mode */ - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); - - /* o. AFE_XTAL_CTRL 0x24[7:0] = 0x0E disable XTAL, if No BT COEX */ - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); - - /* p. RSV_CTRL 0x1C[7:0] = 0x0E lock ISO/CLK/Power control register */ - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); - - /* ==== interface into suspend === */ - - /* q. APS_FSMCO[15:8] = 0x58 PCIe suspend mode */ - /* According to power document V11, we need to set this */ - /* value as 0x18. Otherwise, we may not L0s sometimes. */ - /* This indluences power consumption. Bases on SD1's test, */ - /* set as 0x00 do not affect power current. And if it */ - /* is set as 0x18, they had ever met auto load fail problem. */ - rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "In PowerOff,reg0x%x=%X\n", - REG_SPS0_CTRL, rtl_read_byte(rtlpriv, REG_SPS0_CTRL)); - /* r. Note: for PCIe interface, PON will not turn */ - /* off m-bias and BandGap in PCIe suspend mode. */ - - /* 0x17[7] 1b': power off in process 0b' : power off over */ - if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) { - spin_lock_irqsave(&globalmutex_power, flags); - u1b_tmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS); - u1b_tmp &= (~BIT(7)); - rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1b_tmp); - spin_unlock_irqrestore(&globalmutex_power, flags); - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "<=======\n"); -} - -void rtl92de_card_disable(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - enum nl80211_iftype opmode; - - mac->link_state = MAC80211_NOLINK; - opmode = NL80211_IFTYPE_UNSPECIFIED; - _rtl92de_set_media_status(hw, opmode); - - if (rtlpci->driver_is_goingto_unload || - ppsc->rfoff_reason > RF_CHANGE_BY_PS) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - /* Power sequence for each MAC. */ - /* a. stop tx DMA */ - /* b. close RF */ - /* c. clear rx buf */ - /* d. stop rx DMA */ - /* e. reset MAC */ - - /* a. stop tx DMA */ - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE); - udelay(50); - - /* b. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue */ - - /* c. ========RF OFF sequence========== */ - /* 0x88c[23:20] = 0xf. */ - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - - /* APSD_CTRL 0x600[7:0] = 0x40 */ - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); - - /* Close antenna 0,0xc04,0xd04 */ - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0); - rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0); - - /* SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB state machine */ - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - - /* Mac0 can not do Global reset. Mac1 can do. */ - /* SYS_FUNC_EN 0x02[7:0] = 0xE0 reset BB state machine */ - if (rtlpriv->rtlhal.interfaceindex == 1) - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0); - udelay(50); - - /* d. stop tx/rx dma before disable REG_CR (0x100) to fix */ - /* dma hang issue when disable/enable device. */ - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xff); - udelay(50); - rtl_write_byte(rtlpriv, REG_CR, 0x0); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "==> Do power off.......\n"); - if (rtl92d_phy_check_poweroff(hw)) - _rtl92de_poweroff_adapter(hw); - return; -} - -void rtl92de_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; - rtl_write_dword(rtlpriv, ISR, *p_inta); - - /* - * *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; - * rtl_write_dword(rtlpriv, ISR + 4, *p_intb); - */ -} - -void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval, atim_window; - - bcn_interval = mac->beacon_interval; - atim_window = 2; - /*rtl92de_disable_interrupt(hw); */ - rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x20); - if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x30); - else - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x20); - rtl_write_byte(rtlpriv, 0x606, 0x30); -} - -void rtl92de_set_beacon_interval(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval = mac->beacon_interval; - - RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, - "beacon_interval:%d\n", bcn_interval); - /* rtl92de_disable_interrupt(hw); */ - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - /* rtl92de_enable_interrupt(hw); */ -} - -void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, "add_msr:%x, rm_msr:%x\n", - add_msr, rm_msr); - if (add_msr) - rtlpci->irq_mask[0] |= add_msr; - if (rm_msr) - rtlpci->irq_mask[0] &= (~rm_msr); - rtl92de_disable_interrupt(hw); - rtl92de_enable_interrupt(hw); -} - -static void _rtl92de_readpowervalue_fromprom(struct txpower_info *pwrinfo, - u8 *rom_content, bool autoLoadfail) -{ - u32 rfpath, eeaddr, group, offset1, offset2; - u8 i; - - memset(pwrinfo, 0, sizeof(struct txpower_info)); - if (autoLoadfail) { - for (group = 0; group < CHANNEL_GROUP_MAX; group++) { - for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { - if (group < CHANNEL_GROUP_MAX_2G) { - pwrinfo->cck_index[rfpath][group] = - EEPROM_DEFAULT_TXPOWERLEVEL_2G; - pwrinfo->ht40_1sindex[rfpath][group] = - EEPROM_DEFAULT_TXPOWERLEVEL_2G; - } else { - pwrinfo->ht40_1sindex[rfpath][group] = - EEPROM_DEFAULT_TXPOWERLEVEL_5G; - } - pwrinfo->ht40_2sindexdiff[rfpath][group] = - EEPROM_DEFAULT_HT40_2SDIFF; - pwrinfo->ht20indexdiff[rfpath][group] = - EEPROM_DEFAULT_HT20_DIFF; - pwrinfo->ofdmindexdiff[rfpath][group] = - EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; - pwrinfo->ht40maxoffset[rfpath][group] = - EEPROM_DEFAULT_HT40_PWRMAXOFFSET; - pwrinfo->ht20maxoffset[rfpath][group] = - EEPROM_DEFAULT_HT20_PWRMAXOFFSET; - } - } - for (i = 0; i < 3; i++) { - pwrinfo->tssi_a[i] = EEPROM_DEFAULT_TSSI; - pwrinfo->tssi_b[i] = EEPROM_DEFAULT_TSSI; - } - return; - } - - /* Maybe autoload OK,buf the tx power index value is not filled. - * If we find it, we set it to default value. */ - for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { - for (group = 0; group < CHANNEL_GROUP_MAX_2G; group++) { - eeaddr = EEPROM_CCK_TX_PWR_INX_2G + (rfpath * 3) - + group; - pwrinfo->cck_index[rfpath][group] = - (rom_content[eeaddr] == 0xFF) ? - (eeaddr > 0x7B ? - EEPROM_DEFAULT_TXPOWERLEVEL_5G : - EEPROM_DEFAULT_TXPOWERLEVEL_2G) : - rom_content[eeaddr]; - } - } - for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { - for (group = 0; group < CHANNEL_GROUP_MAX; group++) { - offset1 = group / 3; - offset2 = group % 3; - eeaddr = EEPROM_HT40_1S_TX_PWR_INX_2G + (rfpath * 3) + - offset2 + offset1 * 21; - pwrinfo->ht40_1sindex[rfpath][group] = - (rom_content[eeaddr] == 0xFF) ? (eeaddr > 0x7B ? - EEPROM_DEFAULT_TXPOWERLEVEL_5G : - EEPROM_DEFAULT_TXPOWERLEVEL_2G) : - rom_content[eeaddr]; - } - } - /* These just for 92D efuse offset. */ - for (group = 0; group < CHANNEL_GROUP_MAX; group++) { - for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { - int base1 = EEPROM_HT40_2S_TX_PWR_INX_DIFF_2G; - - offset1 = group / 3; - offset2 = group % 3; - - if (rom_content[base1 + offset2 + offset1 * 21] != 0xFF) - pwrinfo->ht40_2sindexdiff[rfpath][group] = - (rom_content[base1 + - offset2 + offset1 * 21] >> (rfpath * 4)) - & 0xF; - else - pwrinfo->ht40_2sindexdiff[rfpath][group] = - EEPROM_DEFAULT_HT40_2SDIFF; - if (rom_content[EEPROM_HT20_TX_PWR_INX_DIFF_2G + offset2 - + offset1 * 21] != 0xFF) - pwrinfo->ht20indexdiff[rfpath][group] = - (rom_content[EEPROM_HT20_TX_PWR_INX_DIFF_2G - + offset2 + offset1 * 21] >> (rfpath * 4)) - & 0xF; - else - pwrinfo->ht20indexdiff[rfpath][group] = - EEPROM_DEFAULT_HT20_DIFF; - if (rom_content[EEPROM_OFDM_TX_PWR_INX_DIFF_2G + offset2 - + offset1 * 21] != 0xFF) - pwrinfo->ofdmindexdiff[rfpath][group] = - (rom_content[EEPROM_OFDM_TX_PWR_INX_DIFF_2G - + offset2 + offset1 * 21] >> (rfpath * 4)) - & 0xF; - else - pwrinfo->ofdmindexdiff[rfpath][group] = - EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; - if (rom_content[EEPROM_HT40_MAX_PWR_OFFSET_2G + offset2 - + offset1 * 21] != 0xFF) - pwrinfo->ht40maxoffset[rfpath][group] = - (rom_content[EEPROM_HT40_MAX_PWR_OFFSET_2G - + offset2 + offset1 * 21] >> (rfpath * 4)) - & 0xF; - else - pwrinfo->ht40maxoffset[rfpath][group] = - EEPROM_DEFAULT_HT40_PWRMAXOFFSET; - if (rom_content[EEPROM_HT20_MAX_PWR_OFFSET_2G + offset2 - + offset1 * 21] != 0xFF) - pwrinfo->ht20maxoffset[rfpath][group] = - (rom_content[EEPROM_HT20_MAX_PWR_OFFSET_2G + - offset2 + offset1 * 21] >> (rfpath * 4)) & - 0xF; - else - pwrinfo->ht20maxoffset[rfpath][group] = - EEPROM_DEFAULT_HT20_PWRMAXOFFSET; - } - } - if (rom_content[EEPROM_TSSI_A_5G] != 0xFF) { - /* 5GL */ - pwrinfo->tssi_a[0] = rom_content[EEPROM_TSSI_A_5G] & 0x3F; - pwrinfo->tssi_b[0] = rom_content[EEPROM_TSSI_B_5G] & 0x3F; - /* 5GM */ - pwrinfo->tssi_a[1] = rom_content[EEPROM_TSSI_AB_5G] & 0x3F; - pwrinfo->tssi_b[1] = - (rom_content[EEPROM_TSSI_AB_5G] & 0xC0) >> 6 | - (rom_content[EEPROM_TSSI_AB_5G + 1] & 0x0F) << 2; - /* 5GH */ - pwrinfo->tssi_a[2] = (rom_content[EEPROM_TSSI_AB_5G + 1] & - 0xF0) >> 4 | - (rom_content[EEPROM_TSSI_AB_5G + 2] & 0x03) << 4; - pwrinfo->tssi_b[2] = (rom_content[EEPROM_TSSI_AB_5G + 2] & - 0xFC) >> 2; - } else { - for (i = 0; i < 3; i++) { - pwrinfo->tssi_a[i] = EEPROM_DEFAULT_TSSI; - pwrinfo->tssi_b[i] = EEPROM_DEFAULT_TSSI; - } - } -} - -static void _rtl92de_read_txpower_info(struct ieee80211_hw *hw, - bool autoload_fail, u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct txpower_info pwrinfo; - u8 tempval[2], i, pwr, diff; - u32 ch, rfPath, group; - - _rtl92de_readpowervalue_fromprom(&pwrinfo, hwinfo, autoload_fail); - if (!autoload_fail) { - /* bit0~2 */ - rtlefuse->eeprom_regulatory = (hwinfo[EEPROM_RF_OPT1] & 0x7); - rtlefuse->eeprom_thermalmeter = - hwinfo[EEPROM_THERMAL_METER] & 0x1f; - rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_K]; - tempval[0] = hwinfo[EEPROM_IQK_DELTA] & 0x03; - tempval[1] = (hwinfo[EEPROM_LCK_DELTA] & 0x0C) >> 2; - rtlefuse->txpwr_fromeprom = true; - if (IS_92D_D_CUT(rtlpriv->rtlhal.version) || - IS_92D_E_CUT(rtlpriv->rtlhal.version)) { - rtlefuse->internal_pa_5g[0] = - !((hwinfo[EEPROM_TSSI_A_5G] & BIT(6)) >> 6); - rtlefuse->internal_pa_5g[1] = - !((hwinfo[EEPROM_TSSI_B_5G] & BIT(6)) >> 6); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Is D cut,Internal PA0 %d Internal PA1 %d\n", - rtlefuse->internal_pa_5g[0], - rtlefuse->internal_pa_5g[1]); - } - rtlefuse->eeprom_c9 = hwinfo[EEPROM_RF_OPT6]; - rtlefuse->eeprom_cc = hwinfo[EEPROM_RF_OPT7]; - } else { - rtlefuse->eeprom_regulatory = 0; - rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; - rtlefuse->crystalcap = EEPROM_DEFAULT_CRYSTALCAP; - tempval[0] = tempval[1] = 3; - } - - /* Use default value to fill parameters if - * efuse is not filled on some place. */ - - /* ThermalMeter from EEPROM */ - if (rtlefuse->eeprom_thermalmeter < 0x06 || - rtlefuse->eeprom_thermalmeter > 0x1c) - rtlefuse->eeprom_thermalmeter = 0x12; - rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; - - /* check XTAL_K */ - if (rtlefuse->crystalcap == 0xFF) - rtlefuse->crystalcap = 0; - if (rtlefuse->eeprom_regulatory > 3) - rtlefuse->eeprom_regulatory = 0; - - for (i = 0; i < 2; i++) { - switch (tempval[i]) { - case 0: - tempval[i] = 5; - break; - case 1: - tempval[i] = 4; - break; - case 2: - tempval[i] = 3; - break; - case 3: - default: - tempval[i] = 0; - break; - } - } - - rtlefuse->delta_iqk = tempval[0]; - if (tempval[1] > 0) - rtlefuse->delta_lck = tempval[1] - 1; - if (rtlefuse->eeprom_c9 == 0xFF) - rtlefuse->eeprom_c9 = 0x00; - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, - "EEPROMRegulatory = 0x%x\n", rtlefuse->eeprom_regulatory); - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, - "ThermalMeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, - "CrystalCap = 0x%x\n", rtlefuse->crystalcap); - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, - "Delta_IQK = 0x%x Delta_LCK = 0x%x\n", - rtlefuse->delta_iqk, rtlefuse->delta_lck); - - for (rfPath = 0; rfPath < RF6052_MAX_PATH; rfPath++) { - for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { - group = rtl92d_get_chnlgroup_fromarray((u8) ch); - if (ch < CHANNEL_MAX_NUMBER_2G) - rtlefuse->txpwrlevel_cck[rfPath][ch] = - pwrinfo.cck_index[rfPath][group]; - rtlefuse->txpwrlevel_ht40_1s[rfPath][ch] = - pwrinfo.ht40_1sindex[rfPath][group]; - rtlefuse->txpwr_ht20diff[rfPath][ch] = - pwrinfo.ht20indexdiff[rfPath][group]; - rtlefuse->txpwr_legacyhtdiff[rfPath][ch] = - pwrinfo.ofdmindexdiff[rfPath][group]; - rtlefuse->pwrgroup_ht20[rfPath][ch] = - pwrinfo.ht20maxoffset[rfPath][group]; - rtlefuse->pwrgroup_ht40[rfPath][ch] = - pwrinfo.ht40maxoffset[rfPath][group]; - pwr = pwrinfo.ht40_1sindex[rfPath][group]; - diff = pwrinfo.ht40_2sindexdiff[rfPath][group]; - rtlefuse->txpwrlevel_ht40_2s[rfPath][ch] = - (pwr > diff) ? (pwr - diff) : 0; - } - } -} - -static void _rtl92de_read_macphymode_from_prom(struct ieee80211_hw *hw, - u8 *content) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 macphy_crvalue = content[EEPROM_MAC_FUNCTION]; - - if (macphy_crvalue & BIT(3)) { - rtlhal->macphymode = SINGLEMAC_SINGLEPHY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "MacPhyMode SINGLEMAC_SINGLEPHY\n"); - } else { - rtlhal->macphymode = DUALMAC_DUALPHY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "MacPhyMode DUALMAC_DUALPHY\n"); - } -} - -static void _rtl92de_read_macphymode_and_bandtype(struct ieee80211_hw *hw, - u8 *content) -{ - _rtl92de_read_macphymode_from_prom(hw, content); - rtl92d_phy_config_macphymode(hw); - rtl92d_phy_config_macphymode_info(hw); -} - -static void _rtl92de_efuse_update_chip_version(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - enum version_8192d chipver = rtlpriv->rtlhal.version; - u8 cutvalue[2]; - u16 chipvalue; - - rtlpriv->intf_ops->read_efuse_byte(hw, EEPROME_CHIP_VERSION_H, - &cutvalue[1]); - rtlpriv->intf_ops->read_efuse_byte(hw, EEPROME_CHIP_VERSION_L, - &cutvalue[0]); - chipvalue = (cutvalue[1] << 8) | cutvalue[0]; - switch (chipvalue) { - case 0xAA55: - chipver |= CHIP_92D_C_CUT; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "C-CUT!!!\n"); - break; - case 0x9966: - chipver |= CHIP_92D_D_CUT; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "D-CUT!!!\n"); - break; - case 0xCC33: - chipver |= CHIP_92D_E_CUT; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "E-CUT!!!\n"); - break; - default: - chipver |= CHIP_92D_D_CUT; - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Unknown CUT!\n"); - break; - } - rtlpriv->rtlhal.version = chipver; -} - -static void _rtl92de_read_adapter_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u16 i, usvalue; - u8 hwinfo[HWSET_MAX_SIZE]; - u16 eeprom_id; - unsigned long flags; - - if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { - spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags); - rtl_efuse_shadow_map_update(hw); - _rtl92de_efuse_update_chip_version(hw); - spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags); - memcpy((void *)hwinfo, (void *)&rtlefuse->efuse_map - [EFUSE_INIT_MAP][0], - HWSET_MAX_SIZE); - } else if (rtlefuse->epromtype == EEPROM_93C46) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "RTL819X Not boot from eeprom, check it !!\n"); - } - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP", - hwinfo, HWSET_MAX_SIZE); - - eeprom_id = *((u16 *)&hwinfo[0]); - if (eeprom_id != RTL8190_EEPROM_ID) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "EEPROM ID(%#x) is invalid!!\n", eeprom_id); - rtlefuse->autoload_failflag = true; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - } - if (rtlefuse->autoload_failflag) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "RTL819X Not boot from eeprom, check it !!\n"); - return; - } - rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; - _rtl92de_read_macphymode_and_bandtype(hw, hwinfo); - - /* VID, DID SE 0xA-D */ - rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; - rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; - rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; - rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROMId = 0x%4x\n", eeprom_id); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); - - /* Read Permanent MAC address */ - if (rtlhal->interfaceindex == 0) { - for (i = 0; i < 6; i += 2) { - usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_MAC0_92D + i]; - *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; - } - } else { - for (i = 0; i < 6; i += 2) { - usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_MAC1_92D + i]; - *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; - } - } - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, - rtlefuse->dev_addr); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%pM\n", rtlefuse->dev_addr); - _rtl92de_read_txpower_info(hw, rtlefuse->autoload_failflag, hwinfo); - - /* Read Channel Plan */ - switch (rtlhal->bandset) { - case BAND_ON_2_4G: - rtlefuse->channel_plan = COUNTRY_CODE_TELEC; - break; - case BAND_ON_5G: - rtlefuse->channel_plan = COUNTRY_CODE_FCC; - break; - case BAND_ON_BOTH: - rtlefuse->channel_plan = COUNTRY_CODE_FCC; - break; - default: - rtlefuse->channel_plan = COUNTRY_CODE_FCC; - break; - } - rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; - rtlefuse->txpwr_fromeprom = true; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); -} - -void rtl92de_read_eeprom_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_u1b; - - rtlhal->version = _rtl92de_read_chip_version(hw); - tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); - rtlefuse->autoload_status = tmp_u1b; - if (tmp_u1b & BIT(4)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); - rtlefuse->epromtype = EEPROM_93C46; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); - rtlefuse->epromtype = EEPROM_BOOT_EFUSE; - } - if (tmp_u1b & BIT(5)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - - rtlefuse->autoload_failflag = false; - _rtl92de_read_adapter_info(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); - } - return; -} - -static void rtl92de_update_hal_rate_table(struct ieee80211_hw *hw, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 ratr_value; - u8 ratr_index = 0; - u8 nmode = mac->ht_enable; - u8 mimo_ps = IEEE80211_SMPS_OFF; - u16 shortgi_rate; - u32 tmp_ratr_value; - u8 curtxbw_40mhz = mac->bw_40; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = mac->mode; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_value = sta->supp_rates[1] << 4; - else - ratr_value = sta->supp_rates[0]; - ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_A: - ratr_value &= 0x00000FF0; - break; - case WIRELESS_MODE_B: - if (ratr_value & 0x0000000c) - ratr_value &= 0x0000000d; - else - ratr_value &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_value &= 0x00000FF5; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - nmode = 1; - if (mimo_ps == IEEE80211_SMPS_STATIC) { - ratr_value &= 0x0007F005; - } else { - u32 ratr_mask; - - if (get_rf_type(rtlphy) == RF_1T2R || - get_rf_type(rtlphy) == RF_1T1R) { - ratr_mask = 0x000ff005; - } else { - ratr_mask = 0x0f0ff005; - } - - ratr_value &= ratr_mask; - } - break; - default: - if (rtlphy->rf_type == RF_1T2R) - ratr_value &= 0x000ff0ff; - else - ratr_value &= 0x0f0ff0ff; - - break; - } - ratr_value &= 0x0FFFFFFF; - if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) || - (!curtxbw_40mhz && curshortgi_20mhz))) { - ratr_value |= 0x10000000; - tmp_ratr_value = (ratr_value >> 12); - for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { - if ((1 << shortgi_rate) & tmp_ratr_value) - break; - } - shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | - (shortgi_rate << 4) | (shortgi_rate); - } - rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n", - rtl_read_dword(rtlpriv, REG_ARFR0)); -} - -static void rtl92de_update_hal_rate_mask(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - u32 ratr_bitmap; - u8 ratr_index; - u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = 0; - bool shortgi = false; - u32 value[2]; - u8 macid = 0; - u8 mimo_ps = IEEE80211_SMPS_OFF; - - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - mimo_ps = sta_entry->mimo_ps; - wirelessmode = sta_entry->wireless_mode; - if (mac->opmode == NL80211_IFTYPE_STATION) - curtxbw_40mhz = mac->bw_40; - else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) - macid = sta->aid + 1; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_bitmap = sta->supp_rates[1] << 4; - else - ratr_bitmap = sta->supp_rates[0]; - ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - ratr_index = RATR_INX_WIRELESS_B; - if (ratr_bitmap & 0x0000000c) - ratr_bitmap &= 0x0000000d; - else - ratr_bitmap &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_index = RATR_INX_WIRELESS_GB; - - if (rssi_level == 1) - ratr_bitmap &= 0x00000f00; - else if (rssi_level == 2) - ratr_bitmap &= 0x00000ff0; - else - ratr_bitmap &= 0x00000ff5; - break; - case WIRELESS_MODE_A: - ratr_index = RATR_INX_WIRELESS_G; - ratr_bitmap &= 0x00000ff0; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - if (wirelessmode == WIRELESS_MODE_N_24G) - ratr_index = RATR_INX_WIRELESS_NGB; - else - ratr_index = RATR_INX_WIRELESS_NG; - if (mimo_ps == IEEE80211_SMPS_STATIC) { - if (rssi_level == 1) - ratr_bitmap &= 0x00070000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0007f000; - else - ratr_bitmap &= 0x0007f005; - } else { - if (rtlphy->rf_type == RF_1T2R || - rtlphy->rf_type == RF_1T1R) { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff005; - } - } else { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x0f0f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0f0ff000; - else - ratr_bitmap &= 0x0f0ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x0f0f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0f0ff000; - else - ratr_bitmap &= 0x0f0ff005; - } - } - } - if ((curtxbw_40mhz && curshortgi_40mhz) || - (!curtxbw_40mhz && curshortgi_20mhz)) { - - if (macid == 0) - shortgi = true; - else if (macid == 1) - shortgi = false; - } - break; - default: - ratr_index = RATR_INX_WIRELESS_NGB; - - if (rtlphy->rf_type == RF_1T2R) - ratr_bitmap &= 0x000ff0ff; - else - ratr_bitmap &= 0x0f0ff0ff; - break; - } - - value[0] = (ratr_bitmap & 0x0fffffff) | (ratr_index << 28); - value[1] = macid | (shortgi ? 0x20 : 0x00) | 0x80; - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "ratr_bitmap :%x value0:%x value1:%x\n", - ratr_bitmap, value[0], value[1]); - rtl92d_fill_h2c_cmd(hw, H2C_RA_MASK, 5, (u8 *) value); - if (macid != 0) - sta_entry->ratr_index = ratr_index; -} - -void rtl92de_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->dm.useramask) - rtl92de_update_hal_rate_mask(hw, sta, rssi_level); - else - rtl92de_update_hal_rate_table(hw, sta); -} - -void rtl92de_update_channel_access_setting(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 sifs_timer; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, - &mac->slot_time); - if (!mac->ht_enable) - sifs_timer = 0x0a0a; - else - sifs_timer = 0x1010; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); -} - -bool rtl92de_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - enum rf_pwrstate e_rfpowerstate_toset; - u8 u1tmp; - bool actuallyset = false; - unsigned long flag; - - if (rtlpci->being_init_adapter) - return false; - if (ppsc->swrf_processing) - return false; - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - if (ppsc->rfchange_inprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - return false; - } else { - ppsc->rfchange_inprogress = true; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } - rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv, - REG_MAC_PINMUX_CFG) & ~(BIT(3))); - u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); - e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF; - if (ppsc->hwradiooff && (e_rfpowerstate_toset == ERFON)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "GPIOChangeRF - HW Radio ON, RF ON\n"); - e_rfpowerstate_toset = ERFON; - ppsc->hwradiooff = false; - actuallyset = true; - } else if (!ppsc->hwradiooff && (e_rfpowerstate_toset == ERFOFF)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "GPIOChangeRF - HW Radio OFF, RF OFF\n"); - e_rfpowerstate_toset = ERFOFF; - ppsc->hwradiooff = true; - actuallyset = true; - } - if (actuallyset) { - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } else { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } - *valid = 1; - return !ppsc->hwradiooff; -} - -void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 *macaddr = p_macaddr; - u32 entry_id; - bool is_pairwise = false; - static u8 cam_const_addr[4][6] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} - }; - static u8 cam_const_broad[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - - if (clear_all) { - u8 idx; - u8 cam_offset = 0; - u8 clear_number = 5; - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); - for (idx = 0; idx < clear_number; idx++) { - rtl_cam_mark_invalid(hw, cam_offset + idx); - rtl_cam_empty_entry(hw, cam_offset + idx); - - if (idx < 5) { - memset(rtlpriv->sec.key_buf[idx], 0, - MAX_KEY_LEN); - rtlpriv->sec.key_len[idx] = 0; - } - } - } else { - switch (enc_algo) { - case WEP40_ENCRYPTION: - enc_algo = CAM_WEP40; - break; - case WEP104_ENCRYPTION: - enc_algo = CAM_WEP104; - break; - case TKIP_ENCRYPTION: - enc_algo = CAM_TKIP; - break; - case AESCCMP_ENCRYPTION: - enc_algo = CAM_AES; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - enc_algo = CAM_TKIP; - break; - } - if (is_wepkey || rtlpriv->sec.use_defaultkey) { - macaddr = cam_const_addr[key_index]; - entry_id = key_index; - } else { - if (is_group) { - macaddr = cam_const_broad; - entry_id = key_index; - } else { - if (mac->opmode == NL80211_IFTYPE_AP) { - entry_id = rtl_cam_get_free_entry(hw, - p_macaddr); - if (entry_id >= TOTAL_CAM_ENTRY) { - RT_TRACE(rtlpriv, COMP_SEC, - DBG_EMERG, - "Can not find free hw security cam entry\n"); - return; - } - } else { - entry_id = CAM_PAIRWISE_KEY_POSITION; - } - key_index = PAIRWISE_KEYIDX; - is_pairwise = true; - } - } - if (rtlpriv->sec.key_len[key_index] == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "delete one entry, entry_id is %d\n", - entry_id); - if (mac->opmode == NL80211_IFTYPE_AP) - rtl_cam_del_entry(hw, p_macaddr); - rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "The insert KEY length is %d\n", - rtlpriv->sec.key_len[PAIRWISE_KEYIDX]); - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, - "The insert KEY is %x %x\n", - rtlpriv->sec.key_buf[0][0], - rtlpriv->sec.key_buf[0][1]); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "add one entry\n"); - if (is_pairwise) { - RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, - "Pairwise Key content", - rtlpriv->sec.pairwise_key, - rtlpriv-> - sec.key_len[PAIRWISE_KEYIDX]); - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set Pairwise key\n"); - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv-> - sec.key_buf[key_index]); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set group key\n"); - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - rtl_cam_add_one_entry(hw, - rtlefuse->dev_addr, - PAIRWISE_KEYIDX, - CAM_PAIRWISE_KEY_POSITION, - enc_algo, CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[entry_id]); - } - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf - [entry_id]); - } - } - } -} - -void rtl92de_suspend(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->rtlhal.macphyctl_reg = rtl_read_byte(rtlpriv, - REG_MAC_PHY_CTRL_NORMAL); -} - -void rtl92de_resume(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL, - rtlpriv->rtlhal.macphyctl_reg); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h deleted file mode 100644 index 1bc7b1a96d4a..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h +++ /dev/null @@ -1,65 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92DE_HW_H__ -#define __RTL92DE_HW_H__ - -void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92de_read_eeprom_info(struct ieee80211_hw *hw); -void rtl92de_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb); -int rtl92de_hw_init(struct ieee80211_hw *hw); -void rtl92de_card_disable(struct ieee80211_hw *hw); -void rtl92de_enable_interrupt(struct ieee80211_hw *hw); -void rtl92de_disable_interrupt(struct ieee80211_hw *hw); -int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); -void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -void rtl92de_set_qos(struct ieee80211_hw *hw, int aci); -void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw); -void rtl92de_set_beacon_interval(struct ieee80211_hw *hw); -void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr); -void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92de_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level); -void rtl92de_update_channel_access_setting(struct ieee80211_hw *hw); -bool rtl92de_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); -void rtl92de_enable_hw_security_config(struct ieee80211_hw *hw); -void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all); - -void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, u16 offset, u32 value, - u8 direct); -u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, u8 direct); -void rtl92de_suspend(struct ieee80211_hw *hw); -void rtl92de_resume(struct ieee80211_hw *hw); -void rtl92d_linked_set_reg(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/rtlwifi/rtl8192de/led.c deleted file mode 100644 index 76a57ae4af3e..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/led.c +++ /dev/null @@ -1,159 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "reg.h" -#include "led.h" - -static void _rtl92ce_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - u8 ledcfg; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - REG_LEDCFG2, pled->ledpin); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - - if ((rtlpriv->efuse.eeprom_did == 0x8176) || - (rtlpriv->efuse.eeprom_did == 0x8193)) - /* BIT7 of REG_LEDCFG2 should be set to - * make sure we could emit the led2. */ - rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) | - BIT(7) | BIT(5) | BIT(6)); - else - rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) | - BIT(7) | BIT(5)); - break; - case LED_PIN_LED1: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); - - rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - pled->ledon = true; -} - -void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - u8 ledcfg; - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - REG_LEDCFG2, pled->ledpin); - - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg &= 0xf0; - if (pcipriv->ledctl.led_opendrain) - rtl_write_byte(rtlpriv, REG_LEDCFG2, - (ledcfg | BIT(1) | BIT(5) | BIT(6))); - else - rtl_write_byte(rtlpriv, REG_LEDCFG2, - (ledcfg | BIT(3) | BIT(5) | BIT(6))); - break; - case LED_PIN_LED1: - ledcfg &= 0x0f; - rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - pled->ledon = false; -} - -void rtl92de_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); - _rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); -} - -static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); - switch (ledaction) { - case LED_CTL_POWER_ON: - case LED_CTL_LINK: - case LED_CTL_NO_LINK: - rtl92de_sw_led_on(hw, pLed0); - break; - case LED_CTL_POWER_OFF: - rtl92de_sw_led_off(hw, pLed0); - break; - default: - break; - } -} - -void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && - (ledaction == LED_CTL_TX || - ledaction == LED_CTL_RX || - ledaction == LED_CTL_SITE_SURVEY || - ledaction == LED_CTL_LINK || - ledaction == LED_CTL_NO_LINK || - ledaction == LED_CTL_START_TO_LINK || - ledaction == LED_CTL_POWER_ON)) { - return; - } - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n", ledaction); - - _rtl92ce_sw_led_control(hw, ledaction); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/rtlwifi/rtl8192de/led.h deleted file mode 100644 index a29df30c3025..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/led.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CE_LED_H__ -#define __RTL92CE_LED_H__ - -void rtl92de_init_sw_leds(struct ieee80211_hw *hw); -void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c deleted file mode 100644 index bb06fe836fe7..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +++ /dev/null @@ -1,3609 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../ps.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" -#include "table.h" -#include "sw.h" -#include "hw.h" - -#define MAX_RF_IMR_INDEX 12 -#define MAX_RF_IMR_INDEX_NORMAL 13 -#define RF_REG_NUM_FOR_C_CUT_5G 6 -#define RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA 7 -#define RF_REG_NUM_FOR_C_CUT_2G 5 -#define RF_CHNL_NUM_5G 19 -#define RF_CHNL_NUM_5G_40M 17 -#define TARGET_CHNL_NUM_5G 221 -#define TARGET_CHNL_NUM_2G 14 -#define CV_CURVE_CNT 64 - -static u32 rf_reg_for_5g_swchnl_normal[MAX_RF_IMR_INDEX_NORMAL] = { - 0, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x0 -}; - -static u8 rf_reg_for_c_cut_5g[RF_REG_NUM_FOR_C_CUT_5G] = { - RF_SYN_G1, RF_SYN_G2, RF_SYN_G3, RF_SYN_G4, RF_SYN_G5, RF_SYN_G6 -}; - -static u8 rf_reg_for_c_cut_2g[RF_REG_NUM_FOR_C_CUT_2G] = { - RF_SYN_G1, RF_SYN_G2, RF_SYN_G3, RF_SYN_G7, RF_SYN_G8 -}; - -static u8 rf_for_c_cut_5g_internal_pa[RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA] = { - 0x0B, 0x48, 0x49, 0x4B, 0x03, 0x04, 0x0E -}; - -static u32 rf_reg_mask_for_c_cut_2g[RF_REG_NUM_FOR_C_CUT_2G] = { - BIT(19) | BIT(18) | BIT(17) | BIT(14) | BIT(1), - BIT(10) | BIT(9), - BIT(18) | BIT(17) | BIT(16) | BIT(1), - BIT(2) | BIT(1), - BIT(15) | BIT(14) | BIT(13) | BIT(12) | BIT(11) -}; - -static u8 rf_chnl_5g[RF_CHNL_NUM_5G] = { - 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, - 112, 116, 120, 124, 128, 132, 136, 140 -}; - -static u8 rf_chnl_5g_40m[RF_CHNL_NUM_5G_40M] = { - 38, 42, 46, 50, 54, 58, 62, 102, 106, 110, 114, - 118, 122, 126, 130, 134, 138 -}; -static u32 rf_reg_pram_c_5g[5][RF_REG_NUM_FOR_C_CUT_5G] = { - {0xE43BE, 0xFC638, 0x77C0A, 0xDE471, 0xd7110, 0x8EB04}, - {0xE43BE, 0xFC078, 0xF7C1A, 0xE0C71, 0xD7550, 0xAEB04}, - {0xE43BF, 0xFF038, 0xF7C0A, 0xDE471, 0xE5550, 0xAEB04}, - {0xE43BF, 0xFF079, 0xF7C1A, 0xDE471, 0xE5550, 0xAEB04}, - {0xE43BF, 0xFF038, 0xF7C1A, 0xDE471, 0xd7550, 0xAEB04} -}; - -static u32 rf_reg_param_for_c_cut_2g[3][RF_REG_NUM_FOR_C_CUT_2G] = { - {0x643BC, 0xFC038, 0x77C1A, 0x41289, 0x01840}, - {0x643BC, 0xFC038, 0x07C1A, 0x41289, 0x01840}, - {0x243BC, 0xFC438, 0x07C1A, 0x4128B, 0x0FC41} -}; - -static u32 rf_syn_g4_for_c_cut_2g = 0xD1C31 & 0x7FF; - -static u32 rf_pram_c_5g_int_pa[3][RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA] = { - {0x01a00, 0x40443, 0x00eb5, 0x89bec, 0x94a12, 0x94a12, 0x94a12}, - {0x01800, 0xc0443, 0x00730, 0x896ee, 0x94a52, 0x94a52, 0x94a52}, - {0x01800, 0xc0443, 0x00730, 0x896ee, 0x94a12, 0x94a12, 0x94a12} -}; - -/* [mode][patha+b][reg] */ -static u32 rf_imr_param_normal[1][3][MAX_RF_IMR_INDEX_NORMAL] = { - { - /* channel 1-14. */ - { - 0x70000, 0x00ff0, 0x4400f, 0x00ff0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x64888, 0xe266c, 0x00090, 0x22fff - }, - /* path 36-64 */ - { - 0x70000, 0x22880, 0x4470f, 0x55880, 0x00070, 0x88000, - 0x0, 0x88080, 0x70000, 0x64a82, 0xe466c, 0x00090, - 0x32c9a - }, - /* 100 -165 */ - { - 0x70000, 0x44880, 0x4477f, 0x77880, 0x00070, 0x88000, - 0x0, 0x880b0, 0x0, 0x64b82, 0xe466c, 0x00090, 0x32c9a - } - } -}; - -static u32 curveindex_5g[TARGET_CHNL_NUM_5G] = {0}; - -static u32 curveindex_2g[TARGET_CHNL_NUM_2G] = {0}; - -static u32 targetchnl_5g[TARGET_CHNL_NUM_5G] = { - 25141, 25116, 25091, 25066, 25041, - 25016, 24991, 24966, 24941, 24917, - 24892, 24867, 24843, 24818, 24794, - 24770, 24765, 24721, 24697, 24672, - 24648, 24624, 24600, 24576, 24552, - 24528, 24504, 24480, 24457, 24433, - 24409, 24385, 24362, 24338, 24315, - 24291, 24268, 24245, 24221, 24198, - 24175, 24151, 24128, 24105, 24082, - 24059, 24036, 24013, 23990, 23967, - 23945, 23922, 23899, 23876, 23854, - 23831, 23809, 23786, 23764, 23741, - 23719, 23697, 23674, 23652, 23630, - 23608, 23586, 23564, 23541, 23519, - 23498, 23476, 23454, 23432, 23410, - 23388, 23367, 23345, 23323, 23302, - 23280, 23259, 23237, 23216, 23194, - 23173, 23152, 23130, 23109, 23088, - 23067, 23046, 23025, 23003, 22982, - 22962, 22941, 22920, 22899, 22878, - 22857, 22837, 22816, 22795, 22775, - 22754, 22733, 22713, 22692, 22672, - 22652, 22631, 22611, 22591, 22570, - 22550, 22530, 22510, 22490, 22469, - 22449, 22429, 22409, 22390, 22370, - 22350, 22336, 22310, 22290, 22271, - 22251, 22231, 22212, 22192, 22173, - 22153, 22134, 22114, 22095, 22075, - 22056, 22037, 22017, 21998, 21979, - 21960, 21941, 21921, 21902, 21883, - 21864, 21845, 21826, 21807, 21789, - 21770, 21751, 21732, 21713, 21695, - 21676, 21657, 21639, 21620, 21602, - 21583, 21565, 21546, 21528, 21509, - 21491, 21473, 21454, 21436, 21418, - 21400, 21381, 21363, 21345, 21327, - 21309, 21291, 21273, 21255, 21237, - 21219, 21201, 21183, 21166, 21148, - 21130, 21112, 21095, 21077, 21059, - 21042, 21024, 21007, 20989, 20972, - 25679, 25653, 25627, 25601, 25575, - 25549, 25523, 25497, 25471, 25446, - 25420, 25394, 25369, 25343, 25318, - 25292, 25267, 25242, 25216, 25191, - 25166 -}; - -/* channel 1~14 */ -static u32 targetchnl_2g[TARGET_CHNL_NUM_2G] = { - 26084, 26030, 25976, 25923, 25869, 25816, 25764, - 25711, 25658, 25606, 25554, 25502, 25451, 25328 -}; - -static u32 _rtl92d_phy_calculate_bit_shift(u32 bitmask) -{ - u32 i; - - for (i = 0; i <= 31; i++) { - if (((bitmask >> i) & 0x1) == 1) - break; - } - - return i; -} - -u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u32 returnvalue, originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n", - regaddr, bitmask); - if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob) { - u8 dbi_direct = 0; - - /* mac1 use phy0 read radio_b. */ - /* mac0 use phy1 read radio_b. */ - if (rtlhal->during_mac1init_radioa) - dbi_direct = BIT(3); - else if (rtlhal->during_mac0init_radiob) - dbi_direct = BIT(3) | BIT(2); - originalvalue = rtl92de_read_dword_dbi(hw, (u16)regaddr, - dbi_direct); - } else { - originalvalue = rtl_read_dword(rtlpriv, regaddr); - } - bitshift = _rtl92d_phy_calculate_bit_shift(bitmask); - returnvalue = (originalvalue & bitmask) >> bitshift; - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "BBR MASK=0x%x Addr[0x%x]=0x%x\n", - bitmask, regaddr, originalvalue); - return returnvalue; -} - -void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 dbi_direct = 0; - u32 originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); - if (rtlhal->during_mac1init_radioa) - dbi_direct = BIT(3); - else if (rtlhal->during_mac0init_radiob) - /* mac0 use phy1 write radio_b. */ - dbi_direct = BIT(3) | BIT(2); - if (bitmask != MASKDWORD) { - if (rtlhal->during_mac1init_radioa || - rtlhal->during_mac0init_radiob) - originalvalue = rtl92de_read_dword_dbi(hw, - (u16) regaddr, - dbi_direct); - else - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = _rtl92d_phy_calculate_bit_shift(bitmask); - data = ((originalvalue & (~bitmask)) | (data << bitshift)); - } - if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob) - rtl92de_write_dword_dbi(hw, (u16) regaddr, data, dbi_direct); - else - rtl_write_dword(rtlpriv, regaddr, data); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); -} - -static u32 _rtl92d_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) -{ - - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - u32 newoffset; - u32 tmplong, tmplong2; - u8 rfpi_enable = 0; - u32 retvalue; - - newoffset = offset; - tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); - if (rfpath == RF90_PATH_A) - tmplong2 = tmplong; - else - tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); - tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | - (newoffset << 23) | BLSSIREADEDGE; - rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, - tmplong & (~BLSSIREADEDGE)); - udelay(10); - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); - udelay(50); - udelay(50); - rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, - tmplong | BLSSIREADEDGE); - udelay(10); - if (rfpath == RF90_PATH_A) - rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, - BIT(8)); - else if (rfpath == RF90_PATH_B) - rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, - BIT(8)); - if (rfpi_enable) - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, - BLSSIREADBACKDATA); - else - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, - BLSSIREADBACKDATA); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x] = 0x%x\n", - rfpath, pphyreg->rf_rb, retvalue); - return retvalue; -} - -static void _rtl92d_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 offset, u32 data) -{ - u32 data_and_addr; - u32 newoffset; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - - newoffset = offset; - /* T65 RF */ - data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; - rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]=0x%x\n", - rfpath, pphyreg->rf3wire_offset, data_and_addr); -} - -u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, readback_value, bitshift; - unsigned long flags; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", - regaddr, rfpath, bitmask); - spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); - original_value = _rtl92d_phy_rf_serial_read(hw, rfpath, regaddr); - bitshift = _rtl92d_phy_calculate_bit_shift(bitmask); - readback_value = (original_value & bitmask) >> bitshift; - spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", - regaddr, rfpath, bitmask, original_value); - return readback_value; -} - -void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 original_value, bitshift; - unsigned long flags; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); - if (bitmask == 0) - return; - spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); - if (rtlphy->rf_mode != RF_OP_BY_FW) { - if (bitmask != RFREG_OFFSET_MASK) { - original_value = _rtl92d_phy_rf_serial_read(hw, - rfpath, regaddr); - bitshift = _rtl92d_phy_calculate_bit_shift(bitmask); - data = ((original_value & (~bitmask)) | - (data << bitshift)); - } - _rtl92d_phy_rf_serial_write(hw, rfpath, regaddr, data); - } - spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); -} - -bool rtl92d_phy_mac_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - u32 arraylength; - u32 *ptrarray; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n"); - arraylength = MAC_2T_ARRAYLENGTH; - ptrarray = rtl8192de_mac_2tarray; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:Rtl819XMAC_Array\n"); - for (i = 0; i < arraylength; i = i + 2) - rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); - if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) { - /* improve 2-stream TX EVM */ - /* rtl_write_byte(rtlpriv, 0x14,0x71); */ - /* AMPDU aggregation number 9 */ - /* rtl_write_word(rtlpriv, REG_MAX_AGGR_NUM, MAX_AGGR_NUM); */ - rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x0B); - } else { - /* 92D need to test to decide the num. */ - rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x07); - } - return true; -} - -static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - /* RF Interface Sowrtware Control */ - /* 16 LSBs if read 32-bit from 0x870 */ - rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; - /* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */ - rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; - /* 16 LSBs if read 32-bit from 0x874 */ - rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; - /* 16 MSBs if read 32-bit from 0x874 (16-bit for 0x876) */ - - rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; - /* RF Interface Readback Value */ - /* 16 LSBs if read 32-bit from 0x8E0 */ - rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; - /* 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) */ - rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; - /* 16 LSBs if read 32-bit from 0x8E4 */ - rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; - /* 16 MSBs if read 32-bit from 0x8E4 (16-bit for 0x8E6) */ - rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; - - /* RF Interface Output (and Enable) */ - /* 16 LSBs if read 32-bit from 0x860 */ - rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; - /* 16 LSBs if read 32-bit from 0x864 */ - rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; - - /* RF Interface (Output and) Enable */ - /* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */ - rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; - /* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */ - rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; - - /* Addr of LSSI. Wirte RF register by driver */ - /* LSSI Parameter */ - rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = - RFPGA0_XA_LSSIPARAMETER; - rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = - RFPGA0_XB_LSSIPARAMETER; - - /* RF parameter */ - /* BB Band Select */ - rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; - - /* Tx AGC Gain Stage (same for all path. Should we remove this?) */ - /* Tx gain stage */ - rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; - /* Tx gain stage */ - rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; - /* Tx gain stage */ - rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; - /* Tx gain stage */ - rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; - - /* Tranceiver A~D HSSI Parameter-1 */ - /* wire control parameter1 */ - rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; - /* wire control parameter1 */ - rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; - - /* Tranceiver A~D HSSI Parameter-2 */ - /* wire control parameter2 */ - rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; - /* wire control parameter2 */ - rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; - - /* RF switch Control */ - /* TR/Ant switch control */ - rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; - - /* AGC control 1 */ - rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; - - /* AGC control 2 */ - rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; - - /* RX AFE control 1 */ - rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; - - /*RX AFE control 1 */ - rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; - rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; - rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; - rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; - - /* Tx AFE control 1 */ - rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATxIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTxIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTxIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTxIQIMBALANCE; - - /* Tx AFE control 2 */ - rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATxAFE; - rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTxAFE; - rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTxAFE; - rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTxAFE; - - /* Tranceiver LSSI Readback SI mode */ - rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK; - - /* Tranceiver LSSI Readback PI mode */ - rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVERA_HSPI_READBACK; - rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVERB_HSPI_READBACK; -} - -static bool _rtl92d_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) -{ - int i; - u32 *phy_regarray_table; - u32 *agctab_array_table = NULL; - u32 *agctab_5garray_table; - u16 phy_reg_arraylen, agctab_arraylen = 0, agctab_5garraylen; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - /* Normal chip,Mac0 use AGC_TAB.txt for 2G and 5G band. */ - if (rtlhal->interfaceindex == 0) { - agctab_arraylen = AGCTAB_ARRAYLENGTH; - agctab_array_table = rtl8192de_agctab_array; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - " ===> phy:MAC0, Rtl819XAGCTAB_Array\n"); - } else { - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - agctab_arraylen = AGCTAB_2G_ARRAYLENGTH; - agctab_array_table = rtl8192de_agctab_2garray; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - " ===> phy:MAC1, Rtl819XAGCTAB_2GArray\n"); - } else { - agctab_5garraylen = AGCTAB_5G_ARRAYLENGTH; - agctab_5garray_table = rtl8192de_agctab_5garray; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - " ===> phy:MAC1, Rtl819XAGCTAB_5GArray\n"); - - } - } - phy_reg_arraylen = PHY_REG_2T_ARRAYLENGTH; - phy_regarray_table = rtl8192de_phy_reg_2tarray; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - " ===> phy:Rtl819XPHY_REG_Array_PG\n"); - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_reg_arraylen; i = i + 2) { - rtl_addr_delay(phy_regarray_table[i]); - rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD, - phy_regarray_table[i + 1]); - udelay(1); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", - phy_regarray_table[i], - phy_regarray_table[i + 1]); - } - } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { - if (rtlhal->interfaceindex == 0) { - for (i = 0; i < agctab_arraylen; i = i + 2) { - rtl_set_bbreg(hw, agctab_array_table[i], - MASKDWORD, - agctab_array_table[i + 1]); - /* Add 1us delay between BB/RF register - * setting. */ - udelay(1); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The Rtl819XAGCTAB_Array_Table[0] is %ul Rtl819XPHY_REGArray[1] is %ul\n", - agctab_array_table[i], - agctab_array_table[i + 1]); - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Normal Chip, MAC0, load Rtl819XAGCTAB_Array\n"); - } else { - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - for (i = 0; i < agctab_arraylen; i = i + 2) { - rtl_set_bbreg(hw, agctab_array_table[i], - MASKDWORD, - agctab_array_table[i + 1]); - /* Add 1us delay between BB/RF register - * setting. */ - udelay(1); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The Rtl819XAGCTAB_Array_Table[0] is %ul Rtl819XPHY_REGArray[1] is %ul\n", - agctab_array_table[i], - agctab_array_table[i + 1]); - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Load Rtl819XAGCTAB_2GArray\n"); - } else { - for (i = 0; i < agctab_5garraylen; i = i + 2) { - rtl_set_bbreg(hw, - agctab_5garray_table[i], - MASKDWORD, - agctab_5garray_table[i + 1]); - /* Add 1us delay between BB/RF registeri - * setting. */ - udelay(1); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The Rtl819XAGCTAB_5GArray_Table[0] is %ul Rtl819XPHY_REGArray[1] is %ul\n", - agctab_5garray_table[i], - agctab_5garray_table[i + 1]); - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Load Rtl819XAGCTAB_5GArray\n"); - } - } - } - return true; -} - -static void _rtl92d_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, - u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - int index; - - if (regaddr == RTXAGC_A_RATE18_06) - index = 0; - else if (regaddr == RTXAGC_A_RATE54_24) - index = 1; - else if (regaddr == RTXAGC_A_CCK1_MCS32) - index = 6; - else if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) - index = 7; - else if (regaddr == RTXAGC_A_MCS03_MCS00) - index = 2; - else if (regaddr == RTXAGC_A_MCS07_MCS04) - index = 3; - else if (regaddr == RTXAGC_A_MCS11_MCS08) - index = 4; - else if (regaddr == RTXAGC_A_MCS15_MCS12) - index = 5; - else if (regaddr == RTXAGC_B_RATE18_06) - index = 8; - else if (regaddr == RTXAGC_B_RATE54_24) - index = 9; - else if (regaddr == RTXAGC_B_CCK1_55_MCS32) - index = 14; - else if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) - index = 15; - else if (regaddr == RTXAGC_B_MCS03_MCS00) - index = 10; - else if (regaddr == RTXAGC_B_MCS07_MCS04) - index = 11; - else if (regaddr == RTXAGC_B_MCS11_MCS08) - index = 12; - else if (regaddr == RTXAGC_B_MCS15_MCS12) - index = 13; - else - return; - - rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%x\n", - rtlphy->pwrgroup_cnt, index, - rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index]); - if (index == 13) - rtlphy->pwrgroup_cnt++; -} - -static bool _rtl92d_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int i; - u32 *phy_regarray_table_pg; - u16 phy_regarray_pg_len; - - phy_regarray_pg_len = PHY_REG_ARRAY_PG_LENGTH; - phy_regarray_table_pg = rtl8192de_phy_reg_array_pg; - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_regarray_pg_len; i = i + 3) { - rtl_addr_delay(phy_regarray_table_pg[i]); - _rtl92d_store_pwrindex_diffrate_offset(hw, - phy_regarray_table_pg[i], - phy_regarray_table_pg[i + 1], - phy_regarray_table_pg[i + 2]); - } - } else { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "configtype != BaseBand_Config_PHY_REG\n"); - } - return true; -} - -static bool _rtl92d_phy_bb_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - bool rtstatus = true; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "==>\n"); - rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw, - BASEBAND_CONFIG_PHY_REG); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!\n"); - return false; - } - - /* if (rtlphy->rf_type == RF_1T2R) { - * _rtl92c_phy_bb_config_1t(hw); - * RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Config to 1T!!\n"); - *} */ - - if (rtlefuse->autoload_failflag == false) { - rtlphy->pwrgroup_cnt = 0; - rtstatus = _rtl92d_phy_config_bb_with_pgheaderfile(hw, - BASEBAND_CONFIG_PHY_REG); - } - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!\n"); - return false; - } - rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw, - BASEBAND_CONFIG_AGC_TAB); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); - return false; - } - rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, 0x200)); - - return true; -} - -bool rtl92d_phy_bb_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 regval; - u32 regvaldw; - u8 value; - - _rtl92d_phy_init_bb_rf_register_definition(hw); - regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, - regval | BIT(13) | BIT(0) | BIT(1)); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); - /* 0x1f bit7 bit6 represent for mac0/mac1 driver ready */ - value = rtl_read_byte(rtlpriv, REG_RF_CTRL); - rtl_write_byte(rtlpriv, REG_RF_CTRL, value | RF_EN | RF_RSTB | - RF_SDMRSTB); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA | - FEN_DIO_PCIE | FEN_BB_GLB_RSTn | FEN_BBRSTB); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); - if (!(IS_92D_SINGLEPHY(rtlpriv->rtlhal.version))) { - regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); - rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); - } - - return _rtl92d_phy_bb_config(hw); -} - -bool rtl92d_phy_rf_config(struct ieee80211_hw *hw) -{ - return rtl92d_phy_rf6052_config(hw); -} - -bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum rf_content content, - enum radio_path rfpath) -{ - int i; - u32 *radioa_array_table; - u32 *radiob_array_table; - u16 radioa_arraylen, radiob_arraylen; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - radioa_arraylen = RADIOA_2T_ARRAYLENGTH; - radioa_array_table = rtl8192de_radioa_2tarray; - radiob_arraylen = RADIOB_2T_ARRAYLENGTH; - radiob_array_table = rtl8192de_radiob_2tarray; - if (rtlpriv->efuse.internal_pa_5g[0]) { - radioa_arraylen = RADIOA_2T_INT_PA_ARRAYLENGTH; - radioa_array_table = rtl8192de_radioa_2t_int_paarray; - } - if (rtlpriv->efuse.internal_pa_5g[1]) { - radiob_arraylen = RADIOB_2T_INT_PA_ARRAYLENGTH; - radiob_array_table = rtl8192de_radiob_2t_int_paarray; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "PHY_ConfigRFWithHeaderFile() Radio_A:Rtl819XRadioA_1TArray\n"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "PHY_ConfigRFWithHeaderFile() Radio_B:Rtl819XRadioB_1TArray\n"); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath); - - /* this only happens when DMDP, mac0 start on 2.4G, - * mac1 start on 5G, mac 0 has to set phy0&phy1 - * pathA or mac1 has to set phy0&phy1 pathA */ - if ((content == radiob_txt) && (rfpath == RF90_PATH_A)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - " ===> althougth Path A, we load radiob.txt\n"); - radioa_arraylen = radiob_arraylen; - radioa_array_table = radiob_array_table; - } - switch (rfpath) { - case RF90_PATH_A: - for (i = 0; i < radioa_arraylen; i = i + 2) { - rtl_rfreg_delay(hw, rfpath, radioa_array_table[i], - RFREG_OFFSET_MASK, - radioa_array_table[i + 1]); - } - break; - case RF90_PATH_B: - for (i = 0; i < radiob_arraylen; i = i + 2) { - rtl_rfreg_delay(hw, rfpath, radiob_array_table[i], - RFREG_OFFSET_MASK, - radiob_array_table[i + 1]); - } - break; - case RF90_PATH_C: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - case RF90_PATH_D: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - return true; -} - -void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - rtlphy->default_initialgain[0] = - (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[1] = - (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[2] = - (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[3] = - (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", - rtlphy->default_initialgain[0], - rtlphy->default_initialgain[1], - rtlphy->default_initialgain[2], - rtlphy->default_initialgain[3]); - rtlphy->framesync = (u8)rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, - MASKBYTE0); - rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, - MASKDWORD); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default framesync (0x%x) = 0x%x\n", - ROFDM0_RXDETECTOR3, rtlphy->framesync); -} - -static void _rtl92d_get_txpower_index(struct ieee80211_hw *hw, u8 channel, - u8 *cckpowerlevel, u8 *ofdmpowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 index = (channel - 1); - - /* 1. CCK */ - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - /* RF-A */ - cckpowerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_cck[RF90_PATH_A][index]; - /* RF-B */ - cckpowerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_cck[RF90_PATH_B][index]; - } else { - cckpowerlevel[RF90_PATH_A] = 0; - cckpowerlevel[RF90_PATH_B] = 0; - } - /* 2. OFDM for 1S or 2S */ - if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) { - /* Read HT 40 OFDM TX power */ - ofdmpowerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index]; - ofdmpowerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index]; - } else if (rtlphy->rf_type == RF_2T2R) { - /* Read HT 40 OFDM TX power */ - ofdmpowerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index]; - ofdmpowerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index]; - } -} - -static void _rtl92d_ccxpower_index_check(struct ieee80211_hw *hw, - u8 channel, u8 *cckpowerlevel, u8 *ofdmpowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; - rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; -} - -static u8 _rtl92c_phy_get_rightchnlplace(u8 chnl) -{ - u8 channel_5g[59] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, - 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, - 114, 116, 118, 120, 122, 124, 126, 128, - 130, 132, 134, 136, 138, 140, 149, 151, - 153, 155, 157, 159, 161, 163, 165 - }; - u8 place = chnl; - - if (chnl > 14) { - for (place = 14; place < sizeof(channel_5g); place++) { - if (channel_5g[place] == chnl) { - place++; - break; - } - } - } - return place; -} - -void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 cckpowerlevel[2], ofdmpowerlevel[2]; - - if (!rtlefuse->txpwr_fromeprom) - return; - channel = _rtl92c_phy_get_rightchnlplace(channel); - _rtl92d_get_txpower_index(hw, channel, &cckpowerlevel[0], - &ofdmpowerlevel[0]); - if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) - _rtl92d_ccxpower_index_check(hw, channel, &cckpowerlevel[0], - &ofdmpowerlevel[0]); - if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) - rtl92d_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]); - rtl92d_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel); -} - -void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - unsigned long flag = 0; - u8 reg_prsr_rsc; - u8 reg_bw_opmode; - - if (rtlphy->set_bwmode_inprogress) - return; - if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "FALSE driver sleep or unload\n"); - return; - } - rtlphy->set_bwmode_inprogress = true; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n", - rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? - "20MHz" : "40MHz"); - reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); - reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - reg_bw_opmode |= BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - break; - case HT_CHANNEL_WIDTH_20_40: - reg_bw_opmode &= ~BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - - reg_prsr_rsc = (reg_prsr_rsc & 0x90) | - (mac->cur_40_prime_sc << 5); - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); - /* SET BIT10 BIT11 for receive cck */ - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) | - BIT(11), 3); - break; - case HT_CHANNEL_WIDTH_20_40: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); - /* Set Control channel to upper or lower. - * These settings are required only for 40MHz */ - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); - rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCKSIDEBAND, - (mac->cur_40_prime_sc >> 1)); - rtl92d_release_cckandrw_pagea_ctl(hw, &flag); - } - rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); - /* SET BIT10 BIT11 for receive cck */ - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) | - BIT(11), 0); - rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), - (mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - - } - rtl92d_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); - rtlphy->set_bwmode_inprogress = false; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); -} - -static void _rtl92d_phy_stop_trx_before_changeband(struct ieee80211_hw *hw) -{ - rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0); - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x00); - rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x0); -} - -static void rtl92d_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 value8; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "==>\n"); - rtlhal->bandset = band; - rtlhal->current_bandtype = band; - if (IS_92D_SINGLEPHY(rtlhal->version)) - rtlhal->bandset = BAND_ON_BOTH; - /* stop RX/Tx */ - _rtl92d_phy_stop_trx_before_changeband(hw); - /* reconfig BB/RF according to wireless mode */ - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - /* BB & RF Config */ - RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "====>2.4G\n"); - if (rtlhal->interfaceindex == 1) - _rtl92d_phy_config_bb_with_headerfile(hw, - BASEBAND_CONFIG_AGC_TAB); - } else { - /* 5G band */ - RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "====>5G\n"); - if (rtlhal->interfaceindex == 1) - _rtl92d_phy_config_bb_with_headerfile(hw, - BASEBAND_CONFIG_AGC_TAB); - } - rtl92d_update_bbrf_configuration(hw); - if (rtlhal->current_bandtype == BAND_ON_2_4G) - rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); - - /* 20M BW. */ - /* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); */ - rtlhal->reloadtxpowerindex = true; - /* notice fw know band status 0x81[1]/0x53[1] = 0: 5G, 1: 2G */ - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - value8 = rtl_read_byte(rtlpriv, (rtlhal->interfaceindex == - 0 ? REG_MAC0 : REG_MAC1)); - value8 |= BIT(1); - rtl_write_byte(rtlpriv, (rtlhal->interfaceindex == - 0 ? REG_MAC0 : REG_MAC1), value8); - } else { - value8 = rtl_read_byte(rtlpriv, (rtlhal->interfaceindex == - 0 ? REG_MAC0 : REG_MAC1)); - value8 &= (~BIT(1)); - rtl_write_byte(rtlpriv, (rtlhal->interfaceindex == - 0 ? REG_MAC0 : REG_MAC1), value8); - } - mdelay(1); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "<==Switch Band OK\n"); -} - -static void _rtl92d_phy_reload_imr_setting(struct ieee80211_hw *hw, - u8 channel, u8 rfpath) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 imr_num = MAX_RF_IMR_INDEX; - u32 rfmask = RFREG_OFFSET_MASK; - u8 group, i; - unsigned long flag = 0; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "====>path %d\n", rfpath); - if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "====>5G\n"); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(25) | BIT(24), 0); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf); - /* fc area 0xd2c */ - if (channel > 99) - rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(13) | - BIT(14), 2); - else - rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(13) | - BIT(14), 1); - /* leave 0 for channel1-14. */ - group = channel <= 64 ? 1 : 2; - imr_num = MAX_RF_IMR_INDEX_NORMAL; - for (i = 0; i < imr_num; i++) - rtl_set_rfreg(hw, (enum radio_path)rfpath, - rf_reg_for_5g_swchnl_normal[i], rfmask, - rf_imr_param_normal[0][group][i]); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 1); - } else { - /* G band. */ - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, - "Load RF IMR parameters for G band. IMR already setting %d\n", - rtlpriv->rtlhal.load_imrandiqk_setting_for2g); - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "====>2.4G\n"); - if (!rtlpriv->rtlhal.load_imrandiqk_setting_for2g) { - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, - "Load RF IMR parameters for G band. %d\n", - rfpath); - rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(25) | BIT(24), 0); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, - 0x00f00000, 0xf); - imr_num = MAX_RF_IMR_INDEX_NORMAL; - for (i = 0; i < imr_num; i++) { - rtl_set_rfreg(hw, (enum radio_path)rfpath, - rf_reg_for_5g_swchnl_normal[i], - RFREG_OFFSET_MASK, - rf_imr_param_normal[0][0][i]); - } - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, - 0x00f00000, 0); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN | BCCKEN, 3); - rtl92d_release_cckandrw_pagea_ctl(hw, &flag); - } - } - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "<====\n"); -} - -static void _rtl92d_phy_enable_rf_env(struct ieee80211_hw *hw, - u8 rfpath, u32 *pu4_regval) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "====>\n"); - /*----Store original RFENV control type----*/ - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - *pu4_regval = rtl_get_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV); - break; - case RF90_PATH_B: - case RF90_PATH_D: - *pu4_regval = - rtl_get_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16); - break; - } - /*----Set RF_ENV enable----*/ - rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); - udelay(1); - /*----Set RF_ENV output high----*/ - rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); - udelay(1); - /* Set bit number of Address and Data for RF register */ - /* Set 1 to 4 bits for 8255 */ - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREADDRESSLENGTH, 0x0); - udelay(1); - /*Set 0 to 12 bits for 8255 */ - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); - udelay(1); - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "<====\n"); -} - -static void _rtl92d_phy_restore_rf_env(struct ieee80211_hw *hw, u8 rfpath, - u32 *pu4_regval) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "=====>\n"); - /*----Restore RFENV control type----*/ - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, *pu4_regval); - break; - case RF90_PATH_B: - case RF90_PATH_D: - rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16, - *pu4_regval); - break; - } - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "<=====\n"); -} - -static void _rtl92d_phy_switch_rf_setting(struct ieee80211_hw *hw, u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - u8 path = rtlhal->current_bandtype == - BAND_ON_5G ? RF90_PATH_A : RF90_PATH_B; - u8 index = 0, i = 0, rfpath = RF90_PATH_A; - bool need_pwr_down = false, internal_pa = false; - u32 u4regvalue, mask = 0x1C000, value = 0, u4tmp, u4tmp2; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "====>\n"); - /* config path A for 5G */ - if (rtlhal->current_bandtype == BAND_ON_5G) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "====>5G\n"); - u4tmp = curveindex_5g[channel - 1]; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "ver 1 set RF-A, 5G, 0x28 = 0x%x !!\n", u4tmp); - for (i = 0; i < RF_CHNL_NUM_5G; i++) { - if (channel == rf_chnl_5g[i] && channel <= 140) - index = 0; - } - for (i = 0; i < RF_CHNL_NUM_5G_40M; i++) { - if (channel == rf_chnl_5g_40m[i] && channel <= 140) - index = 1; - } - if (channel == 149 || channel == 155 || channel == 161) - index = 2; - else if (channel == 151 || channel == 153 || channel == 163 - || channel == 165) - index = 3; - else if (channel == 157 || channel == 159) - index = 4; - - if (rtlhal->macphymode == DUALMAC_DUALPHY - && rtlhal->interfaceindex == 1) { - need_pwr_down = rtl92d_phy_enable_anotherphy(hw, false); - rtlhal->during_mac1init_radioa = true; - /* asume no this case */ - if (need_pwr_down) - _rtl92d_phy_enable_rf_env(hw, path, - &u4regvalue); - } - for (i = 0; i < RF_REG_NUM_FOR_C_CUT_5G; i++) { - if (i == 0 && (rtlhal->macphymode == DUALMAC_DUALPHY)) { - rtl_set_rfreg(hw, (enum radio_path)path, - rf_reg_for_c_cut_5g[i], - RFREG_OFFSET_MASK, 0xE439D); - } else if (rf_reg_for_c_cut_5g[i] == RF_SYN_G4) { - u4tmp2 = (rf_reg_pram_c_5g[index][i] & - 0x7FF) | (u4tmp << 11); - if (channel == 36) - u4tmp2 &= ~(BIT(7) | BIT(6)); - rtl_set_rfreg(hw, (enum radio_path)path, - rf_reg_for_c_cut_5g[i], - RFREG_OFFSET_MASK, u4tmp2); - } else { - rtl_set_rfreg(hw, (enum radio_path)path, - rf_reg_for_c_cut_5g[i], - RFREG_OFFSET_MASK, - rf_reg_pram_c_5g[index][i]); - } - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "offset 0x%x value 0x%x path %d index %d readback 0x%x\n", - rf_reg_for_c_cut_5g[i], - rf_reg_pram_c_5g[index][i], - path, index, - rtl_get_rfreg(hw, (enum radio_path)path, - rf_reg_for_c_cut_5g[i], - RFREG_OFFSET_MASK)); - } - if (need_pwr_down) - _rtl92d_phy_restore_rf_env(hw, path, &u4regvalue); - if (rtlhal->during_mac1init_radioa) - rtl92d_phy_powerdown_anotherphy(hw, false); - if (channel < 149) - value = 0x07; - else if (channel >= 149) - value = 0x02; - if (channel >= 36 && channel <= 64) - index = 0; - else if (channel >= 100 && channel <= 140) - index = 1; - else - index = 2; - for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; - rfpath++) { - if (rtlhal->macphymode == DUALMAC_DUALPHY && - rtlhal->interfaceindex == 1) /* MAC 1 5G */ - internal_pa = rtlpriv->efuse.internal_pa_5g[1]; - else - internal_pa = - rtlpriv->efuse.internal_pa_5g[rfpath]; - if (internal_pa) { - for (i = 0; - i < RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA; - i++) { - rtl_set_rfreg(hw, rfpath, - rf_for_c_cut_5g_internal_pa[i], - RFREG_OFFSET_MASK, - rf_pram_c_5g_int_pa[index][i]); - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "offset 0x%x value 0x%x path %d index %d\n", - rf_for_c_cut_5g_internal_pa[i], - rf_pram_c_5g_int_pa[index][i], - rfpath, index); - } - } else { - rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B, - mask, value); - } - } - } else if (rtlhal->current_bandtype == BAND_ON_2_4G) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "====>2.4G\n"); - u4tmp = curveindex_2g[channel - 1]; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n", u4tmp); - if (channel == 1 || channel == 2 || channel == 4 || channel == 9 - || channel == 10 || channel == 11 || channel == 12) - index = 0; - else if (channel == 3 || channel == 13 || channel == 14) - index = 1; - else if (channel >= 5 && channel <= 8) - index = 2; - if (rtlhal->macphymode == DUALMAC_DUALPHY) { - path = RF90_PATH_A; - if (rtlhal->interfaceindex == 0) { - need_pwr_down = - rtl92d_phy_enable_anotherphy(hw, true); - rtlhal->during_mac0init_radiob = true; - - if (need_pwr_down) - _rtl92d_phy_enable_rf_env(hw, path, - &u4regvalue); - } - } - for (i = 0; i < RF_REG_NUM_FOR_C_CUT_2G; i++) { - if (rf_reg_for_c_cut_2g[i] == RF_SYN_G7) - rtl_set_rfreg(hw, (enum radio_path)path, - rf_reg_for_c_cut_2g[i], - RFREG_OFFSET_MASK, - (rf_reg_param_for_c_cut_2g[index][i] | - BIT(17))); - else - rtl_set_rfreg(hw, (enum radio_path)path, - rf_reg_for_c_cut_2g[i], - RFREG_OFFSET_MASK, - rf_reg_param_for_c_cut_2g - [index][i]); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "offset 0x%x value 0x%x mak 0x%x path %d index %d readback 0x%x\n", - rf_reg_for_c_cut_2g[i], - rf_reg_param_for_c_cut_2g[index][i], - rf_reg_mask_for_c_cut_2g[i], path, index, - rtl_get_rfreg(hw, (enum radio_path)path, - rf_reg_for_c_cut_2g[i], - RFREG_OFFSET_MASK)); - } - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "cosa ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n", - rf_syn_g4_for_c_cut_2g | (u4tmp << 11)); - - rtl_set_rfreg(hw, (enum radio_path)path, RF_SYN_G4, - RFREG_OFFSET_MASK, - rf_syn_g4_for_c_cut_2g | (u4tmp << 11)); - if (need_pwr_down) - _rtl92d_phy_restore_rf_env(hw, path, &u4regvalue); - if (rtlhal->during_mac0init_radiob) - rtl92d_phy_powerdown_anotherphy(hw, true); - } - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "<====\n"); -} - -u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl) -{ - u8 channel_all[59] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, - 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, - 114, 116, 118, 120, 122, 124, 126, 128, 130, - 132, 134, 136, 138, 140, 149, 151, 153, 155, - 157, 159, 161, 163, 165 - }; - u8 place = chnl; - - if (chnl > 14) { - for (place = 14; place < sizeof(channel_all); place++) { - if (channel_all[place] == chnl) - return place - 13; - } - } - - return 0; -} - -#define MAX_TOLERANCE 5 -#define IQK_DELAY_TIME 1 /* ms */ -#define MAX_TOLERANCE_92D 3 - -/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ -static u8 _rtl92d_phy_patha_iqk(struct ieee80211_hw *hw, bool configpathb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 regeac, rege94, rege9c, regea4; - u8 result = 0; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A IQK!\n"); - /* path-A IQK setting */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path-A IQK setting!\n"); - if (rtlhal->interfaceindex == 0) { - rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f); - rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f); - } else { - rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c22); - rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c22); - } - rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102); - rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x28160206); - /* path-B IQK setting */ - if (configpathb) { - rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22); - rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22); - rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102); - rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160206); - } - /* LO calibration setting */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, "LO calibration setting!\n"); - rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911); - /* One shot, path A LOK & IQK */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, "One shot, path A LOK & IQK!\n"); - rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); - /* delay x ms */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Delay %d ms for One shot, path A LOK & IQK\n", - IQK_DELAY_TIME); - mdelay(IQK_DELAY_TIME); - /* Check failed */ - regeac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xeac = 0x%x\n", regeac); - rege94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xe94 = 0x%x\n", rege94); - rege9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xe9c = 0x%x\n", rege9c); - regea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xea4 = 0x%x\n", regea4); - if (!(regeac & BIT(28)) && (((rege94 & 0x03FF0000) >> 16) != 0x142) && - (((rege9c & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else /* if Tx not OK, ignore Rx */ - return result; - /* if Tx is OK, check whether Rx is OK */ - if (!(regeac & BIT(27)) && (((regea4 & 0x03FF0000) >> 16) != 0x132) && - (((regeac & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - else - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A Rx IQK fail!!\n"); - return result; -} - -/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ -static u8 _rtl92d_phy_patha_iqk_5g_normal(struct ieee80211_hw *hw, - bool configpathb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 regeac, rege94, rege9c, regea4; - u8 result = 0; - u8 i; - u8 retrycount = 2; - u32 TxOKBit = BIT(28), RxOKBit = BIT(27); - - if (rtlhal->interfaceindex == 1) { /* PHY1 */ - TxOKBit = BIT(31); - RxOKBit = BIT(30); - } - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A IQK!\n"); - /* path-A IQK setting */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path-A IQK setting!\n"); - rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x18008c1f); - rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x18008c1f); - rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140307); - rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x68160960); - /* path-B IQK setting */ - if (configpathb) { - rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x18008c2f); - rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x18008c2f); - rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82110000); - rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x68110000); - } - /* LO calibration setting */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, "LO calibration setting!\n"); - rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911); - /* path-A PA on */ - rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, MASKDWORD, 0x07000f60); - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, MASKDWORD, 0x66e60e30); - for (i = 0; i < retrycount; i++) { - /* One shot, path A LOK & IQK */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "One shot, path A LOK & IQK!\n"); - rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); - /* delay x ms */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Delay %d ms for One shot, path A LOK & IQK.\n", - IQK_DELAY_TIME); - mdelay(IQK_DELAY_TIME * 10); - /* Check failed */ - regeac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xeac = 0x%x\n", regeac); - rege94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xe94 = 0x%x\n", rege94); - rege9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xe9c = 0x%x\n", rege9c); - regea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xea4 = 0x%x\n", regea4); - if (!(regeac & TxOKBit) && - (((rege94 & 0x03FF0000) >> 16) != 0x142)) { - result |= 0x01; - } else { /* if Tx not OK, ignore Rx */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path A Tx IQK fail!!\n"); - continue; - } - - /* if Tx is OK, check whether Rx is OK */ - if (!(regeac & RxOKBit) && - (((regea4 & 0x03FF0000) >> 16) != 0x132)) { - result |= 0x02; - break; - } else { - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path A Rx IQK fail!!\n"); - } - } - /* path A PA off */ - rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, MASKDWORD, - rtlphy->iqk_bb_backup[0]); - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, MASKDWORD, - rtlphy->iqk_bb_backup[1]); - return result; -} - -/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ -static u8 _rtl92d_phy_pathb_iqk(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 regeac, regeb4, regebc, regec4, regecc; - u8 result = 0; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path B IQK!\n"); - /* One shot, path B LOK & IQK */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, "One shot, path A LOK & IQK!\n"); - rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002); - rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000); - /* delay x ms */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Delay %d ms for One shot, path B LOK & IQK\n", IQK_DELAY_TIME); - mdelay(IQK_DELAY_TIME); - /* Check failed */ - regeac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xeac = 0x%x\n", regeac); - regeb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xeb4 = 0x%x\n", regeb4); - regebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xebc = 0x%x\n", regebc); - regec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xec4 = 0x%x\n", regec4); - regecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xecc = 0x%x\n", regecc); - if (!(regeac & BIT(31)) && (((regeb4 & 0x03FF0000) >> 16) != 0x142) && - (((regebc & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else - return result; - if (!(regeac & BIT(30)) && (((regec4 & 0x03FF0000) >> 16) != 0x132) && - (((regecc & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - else - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path B Rx IQK fail!!\n"); - return result; -} - -/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ -static u8 _rtl92d_phy_pathb_iqk_5g_normal(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 regeac, regeb4, regebc, regec4, regecc; - u8 result = 0; - u8 i; - u8 retrycount = 2; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path B IQK!\n"); - /* path-A IQK setting */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path-A IQK setting!\n"); - rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x18008c1f); - rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x18008c1f); - rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82110000); - rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x68110000); - - /* path-B IQK setting */ - rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x18008c2f); - rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x18008c2f); - rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140307); - rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x68160960); - - /* LO calibration setting */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, "LO calibration setting!\n"); - rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911); - - /* path-B PA on */ - rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, MASKDWORD, 0x0f600700); - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, MASKDWORD, 0x061f0d30); - - for (i = 0; i < retrycount; i++) { - /* One shot, path B LOK & IQK */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "One shot, path A LOK & IQK!\n"); - rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xfa000000); - rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); - - /* delay x ms */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Delay %d ms for One shot, path B LOK & IQK.\n", 10); - mdelay(IQK_DELAY_TIME * 10); - - /* Check failed */ - regeac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xeac = 0x%x\n", regeac); - regeb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xeb4 = 0x%x\n", regeb4); - regebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xebc = 0x%x\n", regebc); - regec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xec4 = 0x%x\n", regec4); - regecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xecc = 0x%x\n", regecc); - if (!(regeac & BIT(31)) && - (((regeb4 & 0x03FF0000) >> 16) != 0x142)) - result |= 0x01; - else - continue; - if (!(regeac & BIT(30)) && - (((regec4 & 0x03FF0000) >> 16) != 0x132)) { - result |= 0x02; - break; - } else { - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path B Rx IQK fail!!\n"); - } - } - - /* path B PA off */ - rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, MASKDWORD, - rtlphy->iqk_bb_backup[0]); - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, MASKDWORD, - rtlphy->iqk_bb_backup[2]); - return result; -} - -static void _rtl92d_phy_save_adda_registers(struct ieee80211_hw *hw, - u32 *adda_reg, u32 *adda_backup, - u32 regnum) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Save ADDA parameters.\n"); - for (i = 0; i < regnum; i++) - adda_backup[i] = rtl_get_bbreg(hw, adda_reg[i], MASKDWORD); -} - -static void _rtl92d_phy_save_mac_registers(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Save MAC parameters.\n"); - for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) - macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); - macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); -} - -static void _rtl92d_phy_reload_adda_registers(struct ieee80211_hw *hw, - u32 *adda_reg, u32 *adda_backup, - u32 regnum) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Reload ADDA power saving parameters !\n"); - for (i = 0; i < regnum; i++) - rtl_set_bbreg(hw, adda_reg[i], MASKDWORD, adda_backup[i]); -} - -static void _rtl92d_phy_reload_mac_registers(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Reload MAC parameters !\n"); - for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) - rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]); - rtl_write_byte(rtlpriv, macreg[i], macbackup[i]); -} - -static void _rtl92d_phy_path_adda_on(struct ieee80211_hw *hw, - u32 *adda_reg, bool patha_on, bool is2t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 pathon; - u32 i; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, "ADDA ON.\n"); - pathon = patha_on ? 0x04db25a4 : 0x0b1b25a4; - if (patha_on) - pathon = rtlpriv->rtlhal.interfaceindex == 0 ? - 0x04db25a4 : 0x0b1b25a4; - for (i = 0; i < IQK_ADDA_REG_NUM; i++) - rtl_set_bbreg(hw, adda_reg[i], MASKDWORD, pathon); -} - -static void _rtl92d_phy_mac_setting_calibration(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, "MAC settings for Calibration.\n"); - rtl_write_byte(rtlpriv, macreg[0], 0x3F); - - for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) - rtl_write_byte(rtlpriv, macreg[i], (u8)(macbackup[i] & - (~BIT(3)))); - rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5)))); -} - -static void _rtl92d_phy_patha_standby(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path-A standby mode!\n"); - - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); - rtl_set_bbreg(hw, RFPGA0_XA_LSSIPARAMETER, MASKDWORD, 0x00010000); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); -} - -static void _rtl92d_phy_pimode_switch(struct ieee80211_hw *hw, bool pi_mode) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 mode; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "BB Switch to %s mode!\n", pi_mode ? "PI" : "SI"); - mode = pi_mode ? 0x01000100 : 0x01000000; - rtl_set_bbreg(hw, 0x820, MASKDWORD, mode); - rtl_set_bbreg(hw, 0x828, MASKDWORD, mode); -} - -static void _rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw, long result[][8], - u8 t, bool is2t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 i; - u8 patha_ok, pathb_ok; - static u32 adda_reg[IQK_ADDA_REG_NUM] = { - RFPGA0_XCD_SWITCHCONTROL, 0xe6c, 0xe70, 0xe74, - 0xe78, 0xe7c, 0xe80, 0xe84, - 0xe88, 0xe8c, 0xed0, 0xed4, - 0xed8, 0xedc, 0xee0, 0xeec - }; - static u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { - 0x522, 0x550, 0x551, 0x040 - }; - static u32 iqk_bb_reg[IQK_BB_REG_NUM] = { - RFPGA0_XAB_RFINTERFACESW, RFPGA0_XA_RFINTERFACEOE, - RFPGA0_XB_RFINTERFACEOE, ROFDM0_TRMUXPAR, - RFPGA0_XCD_RFINTERFACESW, ROFDM0_TRXPATHENABLE, - RFPGA0_RFMOD, RFPGA0_ANALOGPARAMETER4, - ROFDM0_XAAGCCORE1, ROFDM0_XBAGCCORE1 - }; - const u32 retrycount = 2; - u32 bbvalue; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, "IQK for 2.4G :Start!!!\n"); - if (t == 0) { - bbvalue = rtl_get_bbreg(hw, RFPGA0_RFMOD, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "==>0x%08x\n", bbvalue); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "IQ Calibration for %s\n", - is2t ? "2T2R" : "1T1R"); - - /* Save ADDA parameters, turn Path A ADDA on */ - _rtl92d_phy_save_adda_registers(hw, adda_reg, - rtlphy->adda_backup, IQK_ADDA_REG_NUM); - _rtl92d_phy_save_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - _rtl92d_phy_save_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, IQK_BB_REG_NUM); - } - _rtl92d_phy_path_adda_on(hw, adda_reg, true, is2t); - if (t == 0) - rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER1, BIT(8)); - - /* Switch BB to PI mode to do IQ Calibration. */ - if (!rtlphy->rfpi_enable) - _rtl92d_phy_pimode_switch(hw, true); - - rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00); - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKDWORD, 0x03a05600); - rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, MASKDWORD, 0x000800e4); - rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, MASKDWORD, 0x22204000); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xf00000, 0x0f); - if (is2t) { - rtl_set_bbreg(hw, RFPGA0_XA_LSSIPARAMETER, MASKDWORD, - 0x00010000); - rtl_set_bbreg(hw, RFPGA0_XB_LSSIPARAMETER, MASKDWORD, - 0x00010000); - } - /* MAC settings */ - _rtl92d_phy_mac_setting_calibration(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - /* Page B init */ - rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x0f600000); - if (is2t) - rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x0f600000); - /* IQ calibration setting */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, "IQK setting!\n"); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); - rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800); - for (i = 0; i < retrycount; i++) { - patha_ok = _rtl92d_phy_patha_iqk(hw, is2t); - if (patha_ok == 0x03) { - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path A IQK Success!!\n"); - result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & - 0x3FF0000) >> 16; - break; - } else if (i == (retrycount - 1) && patha_ok == 0x01) { - /* Tx IQK OK */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path A IQK Only Tx Success!!\n"); - - result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & - 0x3FF0000) >> 16; - } - } - if (0x00 == patha_ok) - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A IQK failed!!\n"); - if (is2t) { - _rtl92d_phy_patha_standby(hw); - /* Turn Path B ADDA on */ - _rtl92d_phy_path_adda_on(hw, adda_reg, false, is2t); - for (i = 0; i < retrycount; i++) { - pathb_ok = _rtl92d_phy_pathb_iqk(hw); - if (pathb_ok == 0x03) { - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path B IQK Success!!\n"); - result[t][4] = (rtl_get_bbreg(hw, 0xeb4, - MASKDWORD) & 0x3FF0000) >> 16; - result[t][5] = (rtl_get_bbreg(hw, 0xebc, - MASKDWORD) & 0x3FF0000) >> 16; - result[t][6] = (rtl_get_bbreg(hw, 0xec4, - MASKDWORD) & 0x3FF0000) >> 16; - result[t][7] = (rtl_get_bbreg(hw, 0xecc, - MASKDWORD) & 0x3FF0000) >> 16; - break; - } else if (i == (retrycount - 1) && pathb_ok == 0x01) { - /* Tx IQK OK */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path B Only Tx IQK Success!!\n"); - result[t][4] = (rtl_get_bbreg(hw, 0xeb4, - MASKDWORD) & 0x3FF0000) >> 16; - result[t][5] = (rtl_get_bbreg(hw, 0xebc, - MASKDWORD) & 0x3FF0000) >> 16; - } - } - if (0x00 == pathb_ok) - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path B IQK failed!!\n"); - } - - /* Back to BB mode, load original value */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "IQK:Back to BB mode, load original value!\n"); - - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); - if (t != 0) { - /* Switch back BB to SI mode after finish IQ Calibration. */ - if (!rtlphy->rfpi_enable) - _rtl92d_phy_pimode_switch(hw, false); - /* Reload ADDA power saving parameters */ - _rtl92d_phy_reload_adda_registers(hw, adda_reg, - rtlphy->adda_backup, IQK_ADDA_REG_NUM); - /* Reload MAC parameters */ - _rtl92d_phy_reload_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - if (is2t) - _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, - IQK_BB_REG_NUM); - else - _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, - IQK_BB_REG_NUM - 1); - /* load 0xe30 IQC default value */ - rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00); - rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00); - } - RTPRINT(rtlpriv, FINIT, INIT_IQK, "<==\n"); -} - -static void _rtl92d_phy_iq_calibrate_5g_normal(struct ieee80211_hw *hw, - long result[][8], u8 t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - u8 patha_ok, pathb_ok; - static u32 adda_reg[IQK_ADDA_REG_NUM] = { - RFPGA0_XCD_SWITCHCONTROL, 0xe6c, 0xe70, 0xe74, - 0xe78, 0xe7c, 0xe80, 0xe84, - 0xe88, 0xe8c, 0xed0, 0xed4, - 0xed8, 0xedc, 0xee0, 0xeec - }; - static u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { - 0x522, 0x550, 0x551, 0x040 - }; - static u32 iqk_bb_reg[IQK_BB_REG_NUM] = { - RFPGA0_XAB_RFINTERFACESW, RFPGA0_XA_RFINTERFACEOE, - RFPGA0_XB_RFINTERFACEOE, ROFDM0_TRMUXPAR, - RFPGA0_XCD_RFINTERFACESW, ROFDM0_TRXPATHENABLE, - RFPGA0_RFMOD, RFPGA0_ANALOGPARAMETER4, - ROFDM0_XAAGCCORE1, ROFDM0_XBAGCCORE1 - }; - u32 bbvalue; - bool is2t = IS_92D_SINGLEPHY(rtlhal->version); - - /* Note: IQ calibration must be performed after loading - * PHY_REG.txt , and radio_a, radio_b.txt */ - - RTPRINT(rtlpriv, FINIT, INIT_IQK, "IQK for 5G NORMAL:Start!!!\n"); - mdelay(IQK_DELAY_TIME * 20); - if (t == 0) { - bbvalue = rtl_get_bbreg(hw, RFPGA0_RFMOD, MASKDWORD); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "==>0x%08x\n", bbvalue); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "IQ Calibration for %s\n", - is2t ? "2T2R" : "1T1R"); - /* Save ADDA parameters, turn Path A ADDA on */ - _rtl92d_phy_save_adda_registers(hw, adda_reg, - rtlphy->adda_backup, - IQK_ADDA_REG_NUM); - _rtl92d_phy_save_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - if (is2t) - _rtl92d_phy_save_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, - IQK_BB_REG_NUM); - else - _rtl92d_phy_save_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, - IQK_BB_REG_NUM - 1); - } - _rtl92d_phy_path_adda_on(hw, adda_reg, true, is2t); - /* MAC settings */ - _rtl92d_phy_mac_setting_calibration(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - if (t == 0) - rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER1, BIT(8)); - /* Switch BB to PI mode to do IQ Calibration. */ - if (!rtlphy->rfpi_enable) - _rtl92d_phy_pimode_switch(hw, true); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00); - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKDWORD, 0x03a05600); - rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, MASKDWORD, 0x000800e4); - rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, MASKDWORD, 0x22208000); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xf00000, 0x0f); - - /* Page B init */ - rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x0f600000); - if (is2t) - rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x0f600000); - /* IQ calibration setting */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, "IQK setting!\n"); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); - rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x10007c00); - rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800); - patha_ok = _rtl92d_phy_patha_iqk_5g_normal(hw, is2t); - if (patha_ok == 0x03) { - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A IQK Success!!\n"); - result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & - 0x3FF0000) >> 16; - } else if (patha_ok == 0x01) { /* Tx IQK OK */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path A IQK Only Tx Success!!\n"); - - result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & - 0x3FF0000) >> 16; - } else { - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path A IQK Fail!!\n"); - } - if (is2t) { - /* _rtl92d_phy_patha_standby(hw); */ - /* Turn Path B ADDA on */ - _rtl92d_phy_path_adda_on(hw, adda_reg, false, is2t); - pathb_ok = _rtl92d_phy_pathb_iqk_5g_normal(hw); - if (pathb_ok == 0x03) { - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path B IQK Success!!\n"); - result[t][4] = (rtl_get_bbreg(hw, 0xeb4, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][6] = (rtl_get_bbreg(hw, 0xec4, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][7] = (rtl_get_bbreg(hw, 0xecc, MASKDWORD) & - 0x3FF0000) >> 16; - } else if (pathb_ok == 0x01) { /* Tx IQK OK */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path B Only Tx IQK Success!!\n"); - result[t][4] = (rtl_get_bbreg(hw, 0xeb4, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & - 0x3FF0000) >> 16; - } else { - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path B IQK failed!!\n"); - } - } - - /* Back to BB mode, load original value */ - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "IQK:Back to BB mode, load original value!\n"); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); - if (t != 0) { - if (is2t) - _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, - IQK_BB_REG_NUM); - else - _rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, - IQK_BB_REG_NUM - 1); - /* Reload MAC parameters */ - _rtl92d_phy_reload_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - /* Switch back BB to SI mode after finish IQ Calibration. */ - if (!rtlphy->rfpi_enable) - _rtl92d_phy_pimode_switch(hw, false); - /* Reload ADDA power saving parameters */ - _rtl92d_phy_reload_adda_registers(hw, adda_reg, - rtlphy->adda_backup, - IQK_ADDA_REG_NUM); - } - RTPRINT(rtlpriv, FINIT, INIT_IQK, "<==\n"); -} - -static bool _rtl92d_phy_simularity_compare(struct ieee80211_hw *hw, - long result[][8], u8 c1, u8 c2) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - u32 i, j, diff, sim_bitmap, bound; - u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */ - bool bresult = true; - bool is2t = IS_92D_SINGLEPHY(rtlhal->version); - - if (is2t) - bound = 8; - else - bound = 4; - sim_bitmap = 0; - for (i = 0; i < bound; i++) { - diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] - - result[c2][i]) : (result[c2][i] - result[c1][i]); - if (diff > MAX_TOLERANCE_92D) { - if ((i == 2 || i == 6) && !sim_bitmap) { - if (result[c1][i] + result[c1][i + 1] == 0) - final_candidate[(i / 4)] = c2; - else if (result[c2][i] + result[c2][i + 1] == 0) - final_candidate[(i / 4)] = c1; - else - sim_bitmap = sim_bitmap | (1 << i); - } else { - sim_bitmap = sim_bitmap | (1 << i); - } - } - } - if (sim_bitmap == 0) { - for (i = 0; i < (bound / 4); i++) { - if (final_candidate[i] != 0xFF) { - for (j = i * 4; j < (i + 1) * 4 - 2; j++) - result[3][j] = - result[final_candidate[i]][j]; - bresult = false; - } - } - return bresult; - } - if (!(sim_bitmap & 0x0F)) { /* path A OK */ - for (i = 0; i < 4; i++) - result[3][i] = result[c1][i]; - } else if (!(sim_bitmap & 0x03)) { /* path A, Tx OK */ - for (i = 0; i < 2; i++) - result[3][i] = result[c1][i]; - } - if (!(sim_bitmap & 0xF0) && is2t) { /* path B OK */ - for (i = 4; i < 8; i++) - result[3][i] = result[c1][i]; - } else if (!(sim_bitmap & 0x30)) { /* path B, Tx OK */ - for (i = 4; i < 6; i++) - result[3][i] = result[c1][i]; - } - return false; -} - -static void _rtl92d_phy_patha_fill_iqk_matrix(struct ieee80211_hw *hw, - bool iqk_ok, long result[][8], - u8 final_candidate, bool txonly) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - u32 oldval_0, val_x, tx0_a, reg; - long val_y, tx0_c; - bool is2t = IS_92D_SINGLEPHY(rtlhal->version) || - rtlhal->macphymode == DUALMAC_DUALPHY; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Path A IQ Calibration %s !\n", iqk_ok ? "Success" : "Failed"); - if (final_candidate == 0xFF) { - return; - } else if (iqk_ok) { - oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE, - MASKDWORD) >> 22) & 0x3FF; /* OFDM0_D */ - val_x = result[final_candidate][0]; - if ((val_x & 0x00000200) != 0) - val_x = val_x | 0xFFFFFC00; - tx0_a = (val_x * oldval_0) >> 8; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "X = 0x%x, tx0_a = 0x%x, oldval_0 0x%x\n", - val_x, tx0_a, oldval_0); - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x3FF, tx0_a); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), - ((val_x * oldval_0 >> 7) & 0x1)); - val_y = result[final_candidate][1]; - if ((val_y & 0x00000200) != 0) - val_y = val_y | 0xFFFFFC00; - /* path B IQK result + 3 */ - if (rtlhal->interfaceindex == 1 && - rtlhal->current_bandtype == BAND_ON_5G) - val_y += 3; - tx0_c = (val_y * oldval_0) >> 8; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "Y = 0x%lx, tx0_c = 0x%lx\n", - val_y, tx0_c); - rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000, - ((tx0_c & 0x3C0) >> 6)); - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x003F0000, - (tx0_c & 0x3F)); - if (is2t) - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(26), - ((val_y * oldval_0 >> 7) & 0x1)); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "0xC80 = 0x%x\n", - rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE, - MASKDWORD)); - if (txonly) { - RTPRINT(rtlpriv, FINIT, INIT_IQK, "only Tx OK\n"); - return; - } - reg = result[final_candidate][2]; - rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg); - reg = result[final_candidate][3] & 0x3F; - rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg); - reg = (result[final_candidate][3] >> 6) & 0xF; - rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); - } -} - -static void _rtl92d_phy_pathb_fill_iqk_matrix(struct ieee80211_hw *hw, - bool iqk_ok, long result[][8], u8 final_candidate, bool txonly) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - u32 oldval_1, val_x, tx1_a, reg; - long val_y, tx1_c; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Path B IQ Calibration %s !\n", - iqk_ok ? "Success" : "Failed"); - if (final_candidate == 0xFF) { - return; - } else if (iqk_ok) { - oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, - MASKDWORD) >> 22) & 0x3FF; - val_x = result[final_candidate][4]; - if ((val_x & 0x00000200) != 0) - val_x = val_x | 0xFFFFFC00; - tx1_a = (val_x * oldval_1) >> 8; - RTPRINT(rtlpriv, FINIT, INIT_IQK, "X = 0x%x, tx1_a = 0x%x\n", - val_x, tx1_a); - rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x3FF, tx1_a); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28), - ((val_x * oldval_1 >> 7) & 0x1)); - val_y = result[final_candidate][5]; - if ((val_y & 0x00000200) != 0) - val_y = val_y | 0xFFFFFC00; - if (rtlhal->current_bandtype == BAND_ON_5G) - val_y += 3; - tx1_c = (val_y * oldval_1) >> 8; - RTPRINT(rtlpriv, FINIT, INIT_IQK, "Y = 0x%lx, tx1_c = 0x%lx\n", - val_y, tx1_c); - rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000, - ((tx1_c & 0x3C0) >> 6)); - rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x003F0000, - (tx1_c & 0x3F)); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30), - ((val_y * oldval_1 >> 7) & 0x1)); - if (txonly) - return; - reg = result[final_candidate][6]; - rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg); - reg = result[final_candidate][7] & 0x3F; - rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg); - reg = (result[final_candidate][7] >> 6) & 0xF; - rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg); - } -} - -void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - long result[4][8]; - u8 i, final_candidate, indexforchannel; - bool patha_ok, pathb_ok; - long rege94, rege9c, regea4, regeac, regeb4; - long regebc, regec4, regecc, regtmp = 0; - bool is12simular, is13simular, is23simular; - unsigned long flag = 0; - - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "IQK:Start!!!channel %d\n", rtlphy->current_channel); - for (i = 0; i < 8; i++) { - result[0][i] = 0; - result[1][i] = 0; - result[2][i] = 0; - result[3][i] = 0; - } - final_candidate = 0xff; - patha_ok = false; - pathb_ok = false; - is12simular = false; - is23simular = false; - is13simular = false; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "IQK !!!currentband %d\n", rtlhal->current_bandtype); - rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); - for (i = 0; i < 3; i++) { - if (rtlhal->current_bandtype == BAND_ON_5G) { - _rtl92d_phy_iq_calibrate_5g_normal(hw, result, i); - } else if (rtlhal->current_bandtype == BAND_ON_2_4G) { - if (IS_92D_SINGLEPHY(rtlhal->version)) - _rtl92d_phy_iq_calibrate(hw, result, i, true); - else - _rtl92d_phy_iq_calibrate(hw, result, i, false); - } - if (i == 1) { - is12simular = _rtl92d_phy_simularity_compare(hw, result, - 0, 1); - if (is12simular) { - final_candidate = 0; - break; - } - } - if (i == 2) { - is13simular = _rtl92d_phy_simularity_compare(hw, result, - 0, 2); - if (is13simular) { - final_candidate = 0; - break; - } - is23simular = _rtl92d_phy_simularity_compare(hw, result, - 1, 2); - if (is23simular) { - final_candidate = 1; - } else { - for (i = 0; i < 8; i++) - regtmp += result[3][i]; - - if (regtmp != 0) - final_candidate = 3; - else - final_candidate = 0xFF; - } - } - } - rtl92d_release_cckandrw_pagea_ctl(hw, &flag); - for (i = 0; i < 4; i++) { - rege94 = result[i][0]; - rege9c = result[i][1]; - regea4 = result[i][2]; - regeac = result[i][3]; - regeb4 = result[i][4]; - regebc = result[i][5]; - regec4 = result[i][6]; - regecc = result[i][7]; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "IQK: rege94=%lx rege9c=%lx regea4=%lx regeac=%lx regeb4=%lx regebc=%lx regec4=%lx regecc=%lx\n", - rege94, rege9c, regea4, regeac, regeb4, regebc, regec4, - regecc); - } - if (final_candidate != 0xff) { - rtlphy->reg_e94 = rege94 = result[final_candidate][0]; - rtlphy->reg_e9c = rege9c = result[final_candidate][1]; - regea4 = result[final_candidate][2]; - regeac = result[final_candidate][3]; - rtlphy->reg_eb4 = regeb4 = result[final_candidate][4]; - rtlphy->reg_ebc = regebc = result[final_candidate][5]; - regec4 = result[final_candidate][6]; - regecc = result[final_candidate][7]; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "IQK: final_candidate is %x\n", final_candidate); - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "IQK: rege94=%lx rege9c=%lx regea4=%lx regeac=%lx regeb4=%lx regebc=%lx regec4=%lx regecc=%lx\n", - rege94, rege9c, regea4, regeac, regeb4, regebc, regec4, - regecc); - patha_ok = pathb_ok = true; - } else { - rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; /* X default value */ - rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0; /* Y default value */ - } - if ((rege94 != 0) /*&&(regea4 != 0) */) - _rtl92d_phy_patha_fill_iqk_matrix(hw, patha_ok, result, - final_candidate, (regea4 == 0)); - if (IS_92D_SINGLEPHY(rtlhal->version)) { - if ((regeb4 != 0) /*&&(regec4 != 0) */) - _rtl92d_phy_pathb_fill_iqk_matrix(hw, pathb_ok, result, - final_candidate, (regec4 == 0)); - } - if (final_candidate != 0xFF) { - indexforchannel = rtl92d_get_rightchnlplace_for_iqk( - rtlphy->current_channel); - - for (i = 0; i < IQK_MATRIX_REG_NUM; i++) - rtlphy->iqk_matrix[indexforchannel]. - value[0][i] = result[final_candidate][i]; - rtlphy->iqk_matrix[indexforchannel].iqk_done = - true; - - RT_TRACE(rtlpriv, COMP_SCAN | COMP_MLME, DBG_LOUD, - "IQK OK indexforchannel %d\n", indexforchannel); - } -} - -void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - u8 indexforchannel; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "channel %d\n", channel); - /*------Do IQK for normal chip and test chip 5G band------- */ - indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "indexforchannel %d done %d\n", - indexforchannel, - rtlphy->iqk_matrix[indexforchannel].iqk_done); - if (0 && !rtlphy->iqk_matrix[indexforchannel].iqk_done && - rtlphy->need_iqk) { - /* Re Do IQK. */ - RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_LOUD, - "Do IQK Matrix reg for channel:%d....\n", channel); - rtl92d_phy_iq_calibrate(hw); - } else { - /* Just load the value. */ - /* 2G band just load once. */ - if (((!rtlhal->load_imrandiqk_setting_for2g) && - indexforchannel == 0) || indexforchannel > 0) { - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, - "Just Read IQK Matrix reg for channel:%d....\n", - channel); - if ((rtlphy->iqk_matrix[indexforchannel]. - value[0] != NULL) - /*&&(regea4 != 0) */) - _rtl92d_phy_patha_fill_iqk_matrix(hw, true, - rtlphy->iqk_matrix[ - indexforchannel].value, 0, - (rtlphy->iqk_matrix[ - indexforchannel].value[0][2] == 0)); - if (IS_92D_SINGLEPHY(rtlhal->version)) { - if ((rtlphy->iqk_matrix[ - indexforchannel].value[0][4] != 0) - /*&&(regec4 != 0) */) - _rtl92d_phy_pathb_fill_iqk_matrix(hw, - true, - rtlphy->iqk_matrix[ - indexforchannel].value, 0, - (rtlphy->iqk_matrix[ - indexforchannel].value[0][6] - == 0)); - } - } - } - rtlphy->need_iqk = false; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "<====\n"); -} - -static u32 _rtl92d_phy_get_abs(u32 val1, u32 val2) -{ - u32 ret; - - if (val1 >= val2) - ret = val1 - val2; - else - ret = val2 - val1; - return ret; -} - -static bool _rtl92d_is_legal_5g_channel(struct ieee80211_hw *hw, u8 channel) -{ - - int i; - u8 channel_5g[45] = { - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, - 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, - 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, - 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, - 161, 163, 165 - }; - - for (i = 0; i < sizeof(channel_5g); i++) - if (channel == channel_5g[i]) - return true; - return false; -} - -static void _rtl92d_phy_calc_curvindex(struct ieee80211_hw *hw, - u32 *targetchnl, u32 * curvecount_val, - bool is5g, u32 *curveindex) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 smallest_abs_val = 0xffffffff, u4tmp; - u8 i, j; - u8 chnl_num = is5g ? TARGET_CHNL_NUM_5G : TARGET_CHNL_NUM_2G; - - for (i = 0; i < chnl_num; i++) { - if (is5g && !_rtl92d_is_legal_5g_channel(hw, i + 1)) - continue; - curveindex[i] = 0; - for (j = 0; j < (CV_CURVE_CNT * 2); j++) { - u4tmp = _rtl92d_phy_get_abs(targetchnl[i], - curvecount_val[j]); - - if (u4tmp < smallest_abs_val) { - curveindex[i] = j; - smallest_abs_val = u4tmp; - } - } - smallest_abs_val = 0xffffffff; - RTPRINT(rtlpriv, FINIT, INIT_IQK, "curveindex[%d] = %x\n", - i, curveindex[i]); - } -} - -static void _rtl92d_phy_reload_lck_setting(struct ieee80211_hw *hw, - u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 erfpath = rtlpriv->rtlhal.current_bandtype == - BAND_ON_5G ? RF90_PATH_A : - IS_92D_SINGLEPHY(rtlpriv->rtlhal.version) ? - RF90_PATH_B : RF90_PATH_A; - u32 u4tmp = 0, u4regvalue = 0; - bool bneed_powerdown_radio = false; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "path %d\n", erfpath); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "band type = %d\n", - rtlpriv->rtlhal.current_bandtype); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "channel = %d\n", channel); - if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) {/* Path-A for 5G */ - u4tmp = curveindex_5g[channel-1]; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "ver 1 set RF-A, 5G, 0x28 = 0x%x !!\n", u4tmp); - if (rtlpriv->rtlhal.macphymode == DUALMAC_DUALPHY && - rtlpriv->rtlhal.interfaceindex == 1) { - bneed_powerdown_radio = - rtl92d_phy_enable_anotherphy(hw, false); - rtlpriv->rtlhal.during_mac1init_radioa = true; - /* asume no this case */ - if (bneed_powerdown_radio) - _rtl92d_phy_enable_rf_env(hw, erfpath, - &u4regvalue); - } - rtl_set_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800, u4tmp); - if (bneed_powerdown_radio) - _rtl92d_phy_restore_rf_env(hw, erfpath, &u4regvalue); - if (rtlpriv->rtlhal.during_mac1init_radioa) - rtl92d_phy_powerdown_anotherphy(hw, false); - } else if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) { - u4tmp = curveindex_2g[channel-1]; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n", u4tmp); - if (rtlpriv->rtlhal.macphymode == DUALMAC_DUALPHY && - rtlpriv->rtlhal.interfaceindex == 0) { - bneed_powerdown_radio = - rtl92d_phy_enable_anotherphy(hw, true); - rtlpriv->rtlhal.during_mac0init_radiob = true; - if (bneed_powerdown_radio) - _rtl92d_phy_enable_rf_env(hw, erfpath, - &u4regvalue); - } - rtl_set_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800, u4tmp); - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n", - rtl_get_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800)); - if (bneed_powerdown_radio) - _rtl92d_phy_restore_rf_env(hw, erfpath, &u4regvalue); - if (rtlpriv->rtlhal.during_mac0init_radiob) - rtl92d_phy_powerdown_anotherphy(hw, true); - } - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "<====\n"); -} - -static void _rtl92d_phy_lc_calibrate_sw(struct ieee80211_hw *hw, bool is2t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 tmpreg, index, rf_mode[2]; - u8 path = is2t ? 2 : 1; - u8 i; - u32 u4tmp, offset; - u32 curvecount_val[CV_CURVE_CNT * 2] = {0}; - u16 timeout = 800, timecount = 0; - - /* Check continuous TX and Packet TX */ - tmpreg = rtl_read_byte(rtlpriv, 0xd03); - /* if Deal with contisuous TX case, disable all continuous TX */ - /* if Deal with Packet TX case, block all queues */ - if ((tmpreg & 0x70) != 0) - rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); - else - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xF00000, 0x0F); - for (index = 0; index < path; index++) { - /* 1. Read original RF mode */ - offset = index == 0 ? ROFDM0_XAAGCCORE1 : ROFDM0_XBAGCCORE1; - rf_mode[index] = rtl_read_byte(rtlpriv, offset); - /* 2. Set RF mode = standby mode */ - rtl_set_rfreg(hw, (enum radio_path)index, RF_AC, - RFREG_OFFSET_MASK, 0x010000); - if (rtlpci->init_ready) { - /* switch CV-curve control by LC-calibration */ - rtl_set_rfreg(hw, (enum radio_path)index, RF_SYN_G7, - BIT(17), 0x0); - /* 4. Set LC calibration begin */ - rtl_set_rfreg(hw, (enum radio_path)index, RF_CHNLBW, - 0x08000, 0x01); - } - u4tmp = rtl_get_rfreg(hw, (enum radio_path)index, RF_SYN_G6, - RFREG_OFFSET_MASK); - while ((!(u4tmp & BIT(11))) && timecount <= timeout) { - mdelay(50); - timecount += 50; - u4tmp = rtl_get_rfreg(hw, (enum radio_path)index, - RF_SYN_G6, RFREG_OFFSET_MASK); - } - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "PHY_LCK finish delay for %d ms=2\n", timecount); - u4tmp = rtl_get_rfreg(hw, index, RF_SYN_G4, RFREG_OFFSET_MASK); - if (index == 0 && rtlhal->interfaceindex == 0) { - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "path-A / 5G LCK\n"); - } else { - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "path-B / 2.4G LCK\n"); - } - memset(&curvecount_val[0], 0, CV_CURVE_CNT * 2); - /* Set LC calibration off */ - rtl_set_rfreg(hw, (enum radio_path)index, RF_CHNLBW, - 0x08000, 0x0); - RTPRINT(rtlpriv, FINIT, INIT_IQK, "set RF 0x18[15] = 0\n"); - /* save Curve-counting number */ - for (i = 0; i < CV_CURVE_CNT; i++) { - u32 readval = 0, readval2 = 0; - rtl_set_rfreg(hw, (enum radio_path)index, 0x3F, - 0x7f, i); - - rtl_set_rfreg(hw, (enum radio_path)index, 0x4D, - RFREG_OFFSET_MASK, 0x0); - readval = rtl_get_rfreg(hw, (enum radio_path)index, - 0x4F, RFREG_OFFSET_MASK); - curvecount_val[2 * i + 1] = (readval & 0xfffe0) >> 5; - /* reg 0x4f [4:0] */ - /* reg 0x50 [19:10] */ - readval2 = rtl_get_rfreg(hw, (enum radio_path)index, - 0x50, 0xffc00); - curvecount_val[2 * i] = (((readval & 0x1F) << 10) | - readval2); - } - if (index == 0 && rtlhal->interfaceindex == 0) - _rtl92d_phy_calc_curvindex(hw, targetchnl_5g, - curvecount_val, - true, curveindex_5g); - else - _rtl92d_phy_calc_curvindex(hw, targetchnl_2g, - curvecount_val, - false, curveindex_2g); - /* switch CV-curve control mode */ - rtl_set_rfreg(hw, (enum radio_path)index, RF_SYN_G7, - BIT(17), 0x1); - } - - /* Restore original situation */ - for (index = 0; index < path; index++) { - offset = index == 0 ? ROFDM0_XAAGCCORE1 : ROFDM0_XBAGCCORE1; - rtl_write_byte(rtlpriv, offset, 0x50); - rtl_write_byte(rtlpriv, offset, rf_mode[index]); - } - if ((tmpreg & 0x70) != 0) - rtl_write_byte(rtlpriv, 0xd03, tmpreg); - else /*Deal with Packet TX case */ - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xF00000, 0x00); - _rtl92d_phy_reload_lck_setting(hw, rtlpriv->phy.current_channel); -} - -static void _rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RTPRINT(rtlpriv, FINIT, INIT_IQK, "cosa PHY_LCK ver=2\n"); - _rtl92d_phy_lc_calibrate_sw(hw, is2t); -} - -void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - u32 timeout = 2000, timecount = 0; - - while (rtlpriv->mac80211.act_scanning && timecount < timeout) { - udelay(50); - timecount += 50; - } - - rtlphy->lck_inprogress = true; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "LCK:Start!!! currentband %x delay %d ms\n", - rtlhal->current_bandtype, timecount); - if (IS_92D_SINGLEPHY(rtlhal->version)) { - _rtl92d_phy_lc_calibrate(hw, true); - } else { - /* For 1T1R */ - _rtl92d_phy_lc_calibrate(hw, false); - } - rtlphy->lck_inprogress = false; - RTPRINT(rtlpriv, FINIT, INIT_IQK, "LCK:Finish!!!\n"); -} - -void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, char delta) -{ - return; -} - -static bool _rtl92d_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, u32 cmdtablesz, enum swchnlcmd_id cmdid, - u32 para1, u32 para2, u32 msdelay) -{ - struct swchnlcmd *pcmd; - - if (cmdtable == NULL) { - RT_ASSERT(false, "cmdtable cannot be NULL\n"); - return false; - } - if (cmdtableidx >= cmdtablesz) - return false; - - pcmd = cmdtable + cmdtableidx; - pcmd->cmdid = cmdid; - pcmd->para1 = para1; - pcmd->para2 = para2; - pcmd->msdelay = msdelay; - return true; -} - -void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u8 i; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "settings regs %d default regs %d\n", - (int)(sizeof(rtlphy->iqk_matrix) / - sizeof(struct iqk_matrix_regs)), - IQK_MATRIX_REG_NUM); - /* 0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc */ - for (i = 0; i < IQK_MATRIX_SETTINGS_NUM; i++) { - rtlphy->iqk_matrix[i].value[0][0] = 0x100; - rtlphy->iqk_matrix[i].value[0][2] = 0x100; - rtlphy->iqk_matrix[i].value[0][4] = 0x100; - rtlphy->iqk_matrix[i].value[0][6] = 0x100; - rtlphy->iqk_matrix[i].value[0][1] = 0x0; - rtlphy->iqk_matrix[i].value[0][3] = 0x0; - rtlphy->iqk_matrix[i].value[0][5] = 0x0; - rtlphy->iqk_matrix[i].value[0][7] = 0x0; - rtlphy->iqk_matrix[i].iqk_done = false; - } -} - -static bool _rtl92d_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; - u32 precommoncmdcnt; - struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; - u32 postcommoncmdcnt; - struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; - u32 rfdependcmdcnt; - struct swchnlcmd *currentcmd = NULL; - u8 rfpath; - u8 num_total_rfpath = rtlphy->num_total_rfpath; - - precommoncmdcnt = 0; - _rtl92d_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, - CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); - _rtl92d_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); - postcommoncmdcnt = 0; - _rtl92d_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, - MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); - rfdependcmdcnt = 0; - _rtl92d_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, - RF_CHNLBW, channel, 0); - _rtl92d_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, CMDID_END, - 0, 0, 0); - - do { - switch (*stage) { - case 0: - currentcmd = &precommoncmd[*step]; - break; - case 1: - currentcmd = &rfdependcmd[*step]; - break; - case 2: - currentcmd = &postcommoncmd[*step]; - break; - } - if (currentcmd->cmdid == CMDID_END) { - if ((*stage) == 2) { - return true; - } else { - (*stage)++; - (*step) = 0; - continue; - } - } - switch (currentcmd->cmdid) { - case CMDID_SET_TXPOWEROWER_LEVEL: - rtl92d_phy_set_txpower_level(hw, channel); - break; - case CMDID_WRITEPORT_ULONG: - rtl_write_dword(rtlpriv, currentcmd->para1, - currentcmd->para2); - break; - case CMDID_WRITEPORT_USHORT: - rtl_write_word(rtlpriv, currentcmd->para1, - (u16)currentcmd->para2); - break; - case CMDID_WRITEPORT_UCHAR: - rtl_write_byte(rtlpriv, currentcmd->para1, - (u8)currentcmd->para2); - break; - case CMDID_RF_WRITEREG: - for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { - rtlphy->rfreg_chnlval[rfpath] = - ((rtlphy->rfreg_chnlval[rfpath] & - 0xffffff00) | currentcmd->para2); - if (rtlpriv->rtlhal.current_bandtype == - BAND_ON_5G) { - if (currentcmd->para2 > 99) - rtlphy->rfreg_chnlval[rfpath] = - rtlphy->rfreg_chnlval - [rfpath] | (BIT(18)); - else - rtlphy->rfreg_chnlval[rfpath] = - rtlphy->rfreg_chnlval - [rfpath] & (~BIT(18)); - rtlphy->rfreg_chnlval[rfpath] |= - (BIT(16) | BIT(8)); - } else { - rtlphy->rfreg_chnlval[rfpath] &= - ~(BIT(8) | BIT(16) | BIT(18)); - } - rtl_set_rfreg(hw, (enum radio_path)rfpath, - currentcmd->para1, - RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[rfpath]); - _rtl92d_phy_reload_imr_setting(hw, channel, - rfpath); - } - _rtl92d_phy_switch_rf_setting(hw, channel); - /* do IQK when all parameters are ready */ - rtl92d_phy_reload_iqk_setting(hw, channel); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - break; - } while (true); - (*delay) = currentcmd->msdelay; - (*step)++; - return false; -} - -u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 delay; - u32 timeout = 1000, timecount = 0; - u8 channel = rtlphy->current_channel; - u32 ret_value; - - if (rtlphy->sw_chnl_inprogress) - return 0; - if (rtlphy->set_bwmode_inprogress) - return 0; - - if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) { - RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false driver sleep or unload\n"); - return 0; - } - while (rtlphy->lck_inprogress && timecount < timeout) { - mdelay(50); - timecount += 50; - } - if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && - rtlhal->bandset == BAND_ON_BOTH) { - ret_value = rtl_get_bbreg(hw, RFPGA0_XAB_RFPARAMETER, - MASKDWORD); - if (rtlphy->current_channel > 14 && !(ret_value & BIT(0))) - rtl92d_phy_switch_wirelessband(hw, BAND_ON_5G); - else if (rtlphy->current_channel <= 14 && (ret_value & BIT(0))) - rtl92d_phy_switch_wirelessband(hw, BAND_ON_2_4G); - } - switch (rtlhal->current_bandtype) { - case BAND_ON_5G: - /* Get first channel error when change between - * 5G and 2.4G band. */ - if (channel <= 14) - return 0; - RT_ASSERT((channel > 14), "5G but channel<=14\n"); - break; - case BAND_ON_2_4G: - /* Get first channel error when change between - * 5G and 2.4G band. */ - if (channel > 14) - return 0; - RT_ASSERT((channel <= 14), "2G but channel>14\n"); - break; - default: - RT_ASSERT(false, "Invalid WirelessMode(%#x)!!\n", - rtlpriv->mac80211.mode); - break; - } - rtlphy->sw_chnl_inprogress = true; - if (channel == 0) - channel = 1; - rtlphy->sw_chnl_stage = 0; - rtlphy->sw_chnl_step = 0; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "switch to channel%d\n", rtlphy->current_channel); - - do { - if (!rtlphy->sw_chnl_inprogress) - break; - if (!_rtl92d_phy_sw_chnl_step_by_step(hw, - rtlphy->current_channel, - &rtlphy->sw_chnl_stage, &rtlphy->sw_chnl_step, &delay)) { - if (delay > 0) - mdelay(delay); - else - continue; - } else { - rtlphy->sw_chnl_inprogress = false; - } - break; - } while (true); - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); - rtlphy->sw_chnl_inprogress = false; - return 1; -} - -static void rtl92d_phy_set_io(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *de_digtable = &rtlpriv->dm_digtable; - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "--->Cmd(%#x), set_io_inprogress(%d)\n", - rtlphy->current_io_type, rtlphy->set_io_inprogress); - switch (rtlphy->current_io_type) { - case IO_CMD_RESUME_DM_BY_SCAN: - de_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; - rtl92d_dm_write_dig(hw); - rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel); - break; - case IO_CMD_PAUSE_DM_BY_SCAN: - rtlphy->initgain_backup.xaagccore1 = de_digtable->cur_igvalue; - de_digtable->cur_igvalue = 0x37; - rtl92d_dm_write_dig(hw); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - rtlphy->set_io_inprogress = false; - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "<---(%#x)\n", - rtlphy->current_io_type); -} - -bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - bool postprocessing = false; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "-->IO Cmd(%#x), set_io_inprogress(%d)\n", - iotype, rtlphy->set_io_inprogress); - do { - switch (iotype) { - case IO_CMD_RESUME_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Resume DM after scan\n"); - postprocessing = true; - break; - case IO_CMD_PAUSE_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Pause DM before scan\n"); - postprocessing = true; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - } while (false); - if (postprocessing && !rtlphy->set_io_inprogress) { - rtlphy->set_io_inprogress = true; - rtlphy->current_io_type = iotype; - } else { - return false; - } - rtl92d_phy_set_io(hw); - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "<--IO Type(%#x)\n", iotype); - return true; -} - -static void _rtl92d_phy_set_rfon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /* a. SYS_CLKR 0x08[11] = 1 restore MAC clock */ - /* b. SPS_CTRL 0x11[7:0] = 0x2b */ - if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); - /* c. For PCIE: SYS_FUNC_EN 0x02[7:0] = 0xE3 enable BB TRX function */ - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - /* RF_ON_EXCEP(d~g): */ - /* d. APSD_CTRL 0x600[7:0] = 0x00 */ - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); - /* e. SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB TRX function again */ - /* f. SYS_FUNC_EN 0x02[7:0] = 0xE3 enable BB TRX function*/ - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - /* g. txpause 0x522[7:0] = 0x00 enable mac tx queue */ - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); -} - -static void _rtl92d_phy_set_rfsleep(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 u4btmp; - u8 delay = 5; - - /* a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue */ - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - /* b. RF path 0 offset 0x00 = 0x00 disable RF */ - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - /* c. APSD_CTRL 0x600[7:0] = 0x40 */ - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); - /* d. APSD_CTRL 0x600[7:0] = 0x00 - * APSD_CTRL 0x600[7:0] = 0x00 - * RF path 0 offset 0x00 = 0x00 - * APSD_CTRL 0x600[7:0] = 0x40 - * */ - u4btmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); - while (u4btmp != 0 && delay > 0) { - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); - u4btmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); - delay--; - } - if (delay == 0) { - /* Jump out the LPS turn off sequence to RF_ON_EXCEP */ - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); - - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Fail !!! Switch RF timeout\n"); - return; - } - /* e. For PCIE: SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB TRX function */ - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - /* f. SPS_CTRL 0x11[7:0] = 0x22 */ - if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); - /* g. SYS_CLKR 0x08[11] = 0 gated MAC clock */ -} - -bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - - bool bresult = true; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 i, queue_id; - struct rtl8192_tx_ring *ring = NULL; - - if (rfpwr_state == ppsc->rfpwr_state) - return false; - switch (rfpwr_state) { - case ERFON: - if ((ppsc->rfpwr_state == ERFOFF) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { - bool rtstatus; - u32 InitializeCount = 0; - do { - InitializeCount++; - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic enable\n"); - rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && (InitializeCount < 10)); - - RT_CLEAR_PS_LEVEL(ppsc, - RT_RF_OFF_LEVL_HALT_NIC); - } else { - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "awake, sleeped:%d ms state_inap:%x\n", - jiffies_to_msecs(jiffies - - ppsc->last_sleep_jiffies), - rtlpriv->psc.state_inap); - ppsc->last_awake_jiffies = jiffies; - _rtl92d_phy_set_rfon(hw); - } - - if (mac->link_state == MAC80211_LINKED) - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_LINK); - else - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - break; - case ERFOFF: - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic disable\n"); - rtl_ps_disable_nic(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - } else { - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - else - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_POWER_OFF); - } - break; - case ERFSLEEP: - if (ppsc->rfpwr_state == ERFOFF) - return false; - - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (skb_queue_len(&ring->queue) == 0 || - queue_id == BEACON_QUEUE) { - queue_id++; - continue; - } else if (rtlpci->pdev->current_state != PCI_D0) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 but lower power state!\n", - i + 1, queue_id); - break; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", - i + 1, queue_id, - skb_queue_len(&ring->queue)); - udelay(10); - i++; - } - - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "ERFOFF: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "Set rfsleep awaked:%d ms\n", - jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies)); - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "sleep awaked:%d ms state_inap:%x\n", - jiffies_to_msecs(jiffies - - ppsc->last_awake_jiffies), - rtlpriv->psc.state_inap); - ppsc->last_sleep_jiffies = jiffies; - _rtl92d_phy_set_rfsleep(hw); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - bresult = false; - break; - } - if (bresult) - ppsc->rfpwr_state = rfpwr_state; - return bresult; -} - -void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 offset = REG_MAC_PHY_CTRL_NORMAL; - - switch (rtlhal->macphymode) { - case DUALMAC_DUALPHY: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "MacPhyMode: DUALMAC_DUALPHY\n"); - rtl_write_byte(rtlpriv, offset, 0xF3); - break; - case SINGLEMAC_SINGLEPHY: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "MacPhyMode: SINGLEMAC_SINGLEPHY\n"); - rtl_write_byte(rtlpriv, offset, 0xF4); - break; - case DUALMAC_SINGLEPHY: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "MacPhyMode: DUALMAC_SINGLEPHY\n"); - rtl_write_byte(rtlpriv, offset, 0xF1); - break; - } -} - -void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - switch (rtlhal->macphymode) { - case DUALMAC_SINGLEPHY: - rtlphy->rf_type = RF_2T2R; - rtlhal->version |= RF_TYPE_2T2R; - rtlhal->bandset = BAND_ON_BOTH; - rtlhal->current_bandtype = BAND_ON_2_4G; - break; - - case SINGLEMAC_SINGLEPHY: - rtlphy->rf_type = RF_2T2R; - rtlhal->version |= RF_TYPE_2T2R; - rtlhal->bandset = BAND_ON_BOTH; - rtlhal->current_bandtype = BAND_ON_2_4G; - break; - - case DUALMAC_DUALPHY: - rtlphy->rf_type = RF_1T1R; - rtlhal->version &= RF_TYPE_1T1R; - /* Now we let MAC0 run on 5G band. */ - if (rtlhal->interfaceindex == 0) { - rtlhal->bandset = BAND_ON_5G; - rtlhal->current_bandtype = BAND_ON_5G; - } else { - rtlhal->bandset = BAND_ON_2_4G; - rtlhal->current_bandtype = BAND_ON_2_4G; - } - break; - default: - break; - } -} - -u8 rtl92d_get_chnlgroup_fromarray(u8 chnl) -{ - u8 group; - u8 channel_info[59] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, - 58, 60, 62, 64, 100, 102, 104, 106, 108, - 110, 112, 114, 116, 118, 120, 122, 124, - 126, 128, 130, 132, 134, 136, 138, 140, - 149, 151, 153, 155, 157, 159, 161, 163, - 165 - }; - - if (channel_info[chnl] <= 3) - group = 0; - else if (channel_info[chnl] <= 9) - group = 1; - else if (channel_info[chnl] <= 14) - group = 2; - else if (channel_info[chnl] <= 44) - group = 3; - else if (channel_info[chnl] <= 54) - group = 4; - else if (channel_info[chnl] <= 64) - group = 5; - else if (channel_info[chnl] <= 112) - group = 6; - else if (channel_info[chnl] <= 126) - group = 7; - else if (channel_info[chnl] <= 140) - group = 8; - else if (channel_info[chnl] <= 153) - group = 9; - else if (channel_info[chnl] <= 159) - group = 10; - else - group = 11; - return group; -} - -void rtl92d_phy_set_poweron(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - unsigned long flags; - u8 value8; - u16 i; - u32 mac_reg = (rtlhal->interfaceindex == 0 ? REG_MAC0 : REG_MAC1); - - /* notice fw know band status 0x81[1]/0x53[1] = 0: 5G, 1: 2G */ - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - value8 = rtl_read_byte(rtlpriv, mac_reg); - value8 |= BIT(1); - rtl_write_byte(rtlpriv, mac_reg, value8); - } else { - value8 = rtl_read_byte(rtlpriv, mac_reg); - value8 &= (~BIT(1)); - rtl_write_byte(rtlpriv, mac_reg, value8); - } - - if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY) { - value8 = rtl_read_byte(rtlpriv, REG_MAC0); - rtl_write_byte(rtlpriv, REG_MAC0, value8 | MAC0_ON); - } else { - spin_lock_irqsave(&globalmutex_power, flags); - if (rtlhal->interfaceindex == 0) { - value8 = rtl_read_byte(rtlpriv, REG_MAC0); - rtl_write_byte(rtlpriv, REG_MAC0, value8 | MAC0_ON); - } else { - value8 = rtl_read_byte(rtlpriv, REG_MAC1); - rtl_write_byte(rtlpriv, REG_MAC1, value8 | MAC1_ON); - } - value8 = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS); - spin_unlock_irqrestore(&globalmutex_power, flags); - for (i = 0; i < 200; i++) { - if ((value8 & BIT(7)) == 0) { - break; - } else { - udelay(500); - spin_lock_irqsave(&globalmutex_power, flags); - value8 = rtl_read_byte(rtlpriv, - REG_POWER_OFF_IN_PROCESS); - spin_unlock_irqrestore(&globalmutex_power, - flags); - } - } - if (i == 200) - RT_ASSERT(false, "Another mac power off over time\n"); - } -} - -void rtl92d_phy_config_maccoexist_rfpage(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - switch (rtlpriv->rtlhal.macphymode) { - case DUALMAC_DUALPHY: - rtl_write_byte(rtlpriv, REG_DMC, 0x0); - rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x08); - rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x13ff); - break; - case DUALMAC_SINGLEPHY: - rtl_write_byte(rtlpriv, REG_DMC, 0xf8); - rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x08); - rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x13ff); - break; - case SINGLEMAC_SINGLEPHY: - rtl_write_byte(rtlpriv, REG_DMC, 0x0); - rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x10); - rtl_write_word(rtlpriv, (REG_TRXFF_BNDY + 2), 0x27FF); - break; - default: - break; - } -} - -void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 rfpath, i; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "==>\n"); - /* r_select_5G for path_A/B 0 for 2.4G, 1 for 5G */ - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - /* r_select_5G for path_A/B,0x878 */ - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(0), 0x0); - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0x0); - if (rtlhal->macphymode != DUALMAC_DUALPHY) { - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(16), 0x0); - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(31), 0x0); - } - /* rssi_table_select:index 0 for 2.4G.1~3 for 5G,0xc78 */ - rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, BIT(6) | BIT(7), 0x0); - /* fc_area 0xd2c */ - rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(14) | BIT(13), 0x0); - /* 5G LAN ON */ - rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0xa); - /* TX BB gain shift*1,Just for testchip,0xc80,0xc88 */ - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, MASKDWORD, - 0x40000100); - rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, MASKDWORD, - 0x40000100); - if (rtlhal->macphymode == DUALMAC_DUALPHY) { - rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, - BIT(10) | BIT(6) | BIT(5), - ((rtlefuse->eeprom_c9 & BIT(3)) >> 3) | - (rtlefuse->eeprom_c9 & BIT(1)) | - ((rtlefuse->eeprom_cc & BIT(1)) << 4)); - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, - BIT(10) | BIT(6) | BIT(5), - ((rtlefuse->eeprom_c9 & BIT(2)) >> 2) | - ((rtlefuse->eeprom_c9 & BIT(0)) << 1) | - ((rtlefuse->eeprom_cc & BIT(0)) << 5)); - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0); - } else { - rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, - BIT(26) | BIT(22) | BIT(21) | BIT(10) | - BIT(6) | BIT(5), - ((rtlefuse->eeprom_c9 & BIT(3)) >> 3) | - (rtlefuse->eeprom_c9 & BIT(1)) | - ((rtlefuse->eeprom_cc & BIT(1)) << 4) | - ((rtlefuse->eeprom_c9 & BIT(7)) << 9) | - ((rtlefuse->eeprom_c9 & BIT(5)) << 12) | - ((rtlefuse->eeprom_cc & BIT(3)) << 18)); - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, - BIT(10) | BIT(6) | BIT(5), - ((rtlefuse->eeprom_c9 & BIT(2)) >> 2) | - ((rtlefuse->eeprom_c9 & BIT(0)) << 1) | - ((rtlefuse->eeprom_cc & BIT(0)) << 5)); - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(10) | BIT(6) | BIT(5), - ((rtlefuse->eeprom_c9 & BIT(6)) >> 6) | - ((rtlefuse->eeprom_c9 & BIT(4)) >> 3) | - ((rtlefuse->eeprom_cc & BIT(2)) << 3)); - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, - BIT(31) | BIT(15), 0); - } - /* 1.5V_LDO */ - } else { - /* r_select_5G for path_A/B */ - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(0), 0x1); - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0x1); - if (rtlhal->macphymode != DUALMAC_DUALPHY) { - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(16), 0x1); - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(31), 0x1); - } - /* rssi_table_select:index 0 for 2.4G.1~3 for 5G */ - rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, BIT(6) | BIT(7), 0x1); - /* fc_area */ - rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(14) | BIT(13), 0x1); - /* 5G LAN ON */ - rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0x0); - /* TX BB gain shift,Just for testchip,0xc80,0xc88 */ - if (rtlefuse->internal_pa_5g[0]) - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, MASKDWORD, - 0x2d4000b5); - else - rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, MASKDWORD, - 0x20000080); - if (rtlefuse->internal_pa_5g[1]) - rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, MASKDWORD, - 0x2d4000b5); - else - rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, MASKDWORD, - 0x20000080); - if (rtlhal->macphymode == DUALMAC_DUALPHY) { - rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, - BIT(10) | BIT(6) | BIT(5), - (rtlefuse->eeprom_cc & BIT(5))); - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10), - ((rtlefuse->eeprom_cc & BIT(4)) >> 4)); - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), - (rtlefuse->eeprom_cc & BIT(4)) >> 4); - } else { - rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, - BIT(26) | BIT(22) | BIT(21) | BIT(10) | - BIT(6) | BIT(5), - (rtlefuse->eeprom_cc & BIT(5)) | - ((rtlefuse->eeprom_cc & BIT(7)) << 14)); - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10), - ((rtlefuse->eeprom_cc & BIT(4)) >> 4)); - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(10), - ((rtlefuse->eeprom_cc & BIT(6)) >> 6)); - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, - BIT(31) | BIT(15), - ((rtlefuse->eeprom_cc & BIT(4)) >> 4) | - ((rtlefuse->eeprom_cc & BIT(6)) << 10)); - } - } - /* update IQK related settings */ - rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, MASKDWORD, 0x40000100); - rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, MASKDWORD, 0x40000100); - rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000, 0x00); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30) | BIT(28) | - BIT(26) | BIT(24), 0x00); - rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000, 0x00); - rtl_set_bbreg(hw, 0xca0, 0xF0000000, 0x00); - rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, 0x00); - - /* Update RF */ - for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; - rfpath++) { - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - /* MOD_AG for RF path_A 0x18 BIT8,BIT16 */ - rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) | BIT(16) | - BIT(18), 0); - /* RF0x0b[16:14] =3b'111 */ - rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B, - 0x1c000, 0x07); - } else { - /* MOD_AG for RF path_A 0x18 BIT8,BIT16 */ - rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) | - BIT(16) | BIT(18), - (BIT(16) | BIT(8)) >> 8); - } - } - /* Update for all band. */ - /* DMDP */ - if (rtlphy->rf_type == RF_1T1R) { - /* Use antenna 0,0xc04,0xd04 */ - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x11); - rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x1); - - /* enable ad/da clock1 for dual-phy reg0x888 */ - if (rtlhal->interfaceindex == 0) { - rtl_set_bbreg(hw, RFPGA0_ADDALLOCKEN, BIT(12) | - BIT(13), 0x3); - } else { - rtl92d_phy_enable_anotherphy(hw, false); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "MAC1 use DBI to update 0x888\n"); - /* 0x888 */ - rtl92de_write_dword_dbi(hw, RFPGA0_ADDALLOCKEN, - rtl92de_read_dword_dbi(hw, - RFPGA0_ADDALLOCKEN, - BIT(3)) | BIT(12) | BIT(13), - BIT(3)); - rtl92d_phy_powerdown_anotherphy(hw, false); - } - } else { - /* Single PHY */ - /* Use antenna 0 & 1,0xc04,0xd04 */ - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x33); - rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x3); - /* disable ad/da clock1,0x888 */ - rtl_set_bbreg(hw, RFPGA0_ADDALLOCKEN, BIT(12) | BIT(13), 0); - } - for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; - rfpath++) { - rtlphy->rfreg_chnlval[rfpath] = rtl_get_rfreg(hw, rfpath, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtlphy->reg_rf3c[rfpath] = rtl_get_rfreg(hw, rfpath, 0x3C, - RFREG_OFFSET_MASK); - } - for (i = 0; i < 2; i++) - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "RF 0x18 = 0x%x\n", - rtlphy->rfreg_chnlval[i]); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "<==\n"); - -} - -bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 u1btmp; - unsigned long flags; - - if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY) { - u1btmp = rtl_read_byte(rtlpriv, REG_MAC0); - rtl_write_byte(rtlpriv, REG_MAC0, u1btmp & (~MAC0_ON)); - return true; - } - spin_lock_irqsave(&globalmutex_power, flags); - if (rtlhal->interfaceindex == 0) { - u1btmp = rtl_read_byte(rtlpriv, REG_MAC0); - rtl_write_byte(rtlpriv, REG_MAC0, u1btmp & (~MAC0_ON)); - u1btmp = rtl_read_byte(rtlpriv, REG_MAC1); - u1btmp &= MAC1_ON; - } else { - u1btmp = rtl_read_byte(rtlpriv, REG_MAC1); - rtl_write_byte(rtlpriv, REG_MAC1, u1btmp & (~MAC1_ON)); - u1btmp = rtl_read_byte(rtlpriv, REG_MAC0); - u1btmp &= MAC0_ON; - } - if (u1btmp) { - spin_unlock_irqrestore(&globalmutex_power, flags); - return false; - } - u1btmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS); - u1btmp |= BIT(7); - rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1btmp); - spin_unlock_irqrestore(&globalmutex_power, flags); - return true; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h deleted file mode 100644 index 48d5c6835b6a..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h +++ /dev/null @@ -1,173 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92D_PHY_H__ -#define __RTL92D_PHY_H__ - -#define MAX_PRECMD_CNT 16 -#define MAX_RFDEPENDCMD_CNT 16 -#define MAX_POSTCMD_CNT 16 - -#define MAX_DOZE_WAITING_TIMES_9x 64 - -#define RT_CANNOT_IO(hw) false -#define HIGHPOWER_RADIOA_ARRAYLEN 22 - -#define MAX_TOLERANCE 5 - -#define APK_BB_REG_NUM 5 -#define APK_AFE_REG_NUM 16 -#define APK_CURVE_REG_NUM 4 -#define PATH_NUM 2 - -#define LOOP_LIMIT 5 -#define MAX_STALL_TIME 50 -#define ANTENNA_DIVERSITY_VALUE 0x80 -#define MAX_TXPWR_IDX_NMODE_92S 63 -#define RESET_CNT_LIMIT 3 - -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM 10 -#define IQK_BB_REG_NUM_test 6 -#define IQK_MAC_REG_NUM 4 -#define RX_INDEX_MAPPING_NUM 15 - -#define IQK_DELAY_TIME 1 - -#define CT_OFFSET_MAC_ADDR 0X16 - -#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A -#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 -#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 -#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 -#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C - -#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F -#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 - -#define CT_OFFSET_CHANNEL_PLAH 0x75 -#define CT_OFFSET_THERMAL_METER 0x78 -#define CT_OFFSET_RF_OPTION 0x79 -#define CT_OFFSET_VERSION 0x7E -#define CT_OFFSET_CUSTOMER_ID 0x7F - -enum swchnlcmd_id { - CMDID_END, - CMDID_SET_TXPOWEROWER_LEVEL, - CMDID_BBREGWRITE10, - CMDID_WRITEPORT_ULONG, - CMDID_WRITEPORT_USHORT, - CMDID_WRITEPORT_UCHAR, - CMDID_RF_WRITEREG, -}; - -struct swchnlcmd { - enum swchnlcmd_id cmdid; - u32 para1; - u32 para2; - u32 msdelay; -}; - -enum baseband_config_type { - BASEBAND_CONFIG_PHY_REG = 0, - BASEBAND_CONFIG_AGC_TAB = 1, -}; - -enum rf_content { - radioa_txt = 0, - radiob_txt = 1, - radioc_txt = 2, - radiod_txt = 3 -}; - -static inline void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw, - unsigned long *flag) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->rtlhal.interfaceindex == 1) - spin_lock_irqsave(&rtlpriv->locks.cck_and_rw_pagea_lock, *flag); -} - -static inline void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw, - unsigned long *flag) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->rtlhal.interfaceindex == 1) - spin_unlock_irqrestore(&rtlpriv->locks.cck_and_rw_pagea_lock, - *flag); -} - -u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask); -void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, u32 data); -u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask); -void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask, u32 data); -bool rtl92d_phy_mac_config(struct ieee80211_hw *hw); -bool rtl92d_phy_bb_config(struct ieee80211_hw *hw); -bool rtl92d_phy_rf_config(struct ieee80211_hw *hw); -bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); -u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw); -bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum rf_content content, - enum radio_path rfpath); -bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); -bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); - -void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw); -void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw); -u8 rtl92d_get_chnlgroup_fromarray(u8 chnl); -void rtl92d_phy_set_poweron(struct ieee80211_hw *hw); -void rtl92d_phy_config_maccoexist_rfpage(struct ieee80211_hw *hw); -bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw); -void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw); -void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw); -void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); -void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw); -void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw); -void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw, - unsigned long *flag); -void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw, - unsigned long *flag); -u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl); -void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h deleted file mode 100644 index 315a298bab06..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h +++ /dev/null @@ -1,1299 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92D_REG_H__ -#define __RTL92D_REG_H__ - -/* ----------------------------------------------------- */ -/* 0x0000h ~ 0x00FFh System Configuration */ -/* ----------------------------------------------------- */ -#define REG_SYS_ISO_CTRL 0x0000 -#define REG_SYS_FUNC_EN 0x0002 -#define REG_APS_FSMCO 0x0004 -#define REG_SYS_CLKR 0x0008 -#define REG_9346CR 0x000A -#define REG_EE_VPD 0x000C -#define REG_AFE_MISC 0x0010 -#define REG_SPS0_CTRL 0x0011 -#define REG_POWER_OFF_IN_PROCESS 0x0017 -#define REG_SPS_OCP_CFG 0x0018 -#define REG_RSV_CTRL 0x001C -#define REG_RF_CTRL 0x001F -#define REG_LDOA15_CTRL 0x0020 -#define REG_LDOV12D_CTRL 0x0021 -#define REG_LDOHCI12_CTRL 0x0022 -#define REG_LPLDO_CTRL 0x0023 -#define REG_AFE_XTAL_CTRL 0x0024 -#define REG_AFE_PLL_CTRL 0x0028 -/* for 92d, DMDP,SMSP,DMSP contrl */ -#define REG_MAC_PHY_CTRL 0x002c -#define REG_EFUSE_CTRL 0x0030 -#define REG_EFUSE_TEST 0x0034 -#define REG_PWR_DATA 0x0038 -#define REG_CAL_TIMER 0x003C -#define REG_ACLK_MON 0x003E -#define REG_GPIO_MUXCFG 0x0040 -#define REG_GPIO_IO_SEL 0x0042 -#define REG_MAC_PINMUX_CFG 0x0043 -#define REG_GPIO_PIN_CTRL 0x0044 -#define REG_GPIO_INTM 0x0048 -#define REG_LEDCFG0 0x004C -#define REG_LEDCFG1 0x004D -#define REG_LEDCFG2 0x004E -#define REG_LEDCFG3 0x004F -#define REG_FSIMR 0x0050 -#define REG_FSISR 0x0054 - -#define REG_MCUFWDL 0x0080 - -#define REG_HMEBOX_EXT_0 0x0088 -#define REG_HMEBOX_EXT_1 0x008A -#define REG_HMEBOX_EXT_2 0x008C -#define REG_HMEBOX_EXT_3 0x008E - -#define REG_BIST_SCAN 0x00D0 -#define REG_BIST_RPT 0x00D4 -#define REG_BIST_ROM_RPT 0x00D8 -#define REG_USB_SIE_INTF 0x00E0 -#define REG_PCIE_MIO_INTF 0x00E4 -#define REG_PCIE_MIO_INTD 0x00E8 -#define REG_HPON_FSM 0x00EC -#define REG_SYS_CFG 0x00F0 -#define REG_MAC_PHY_CTRL_NORMAL 0x00f8 - -#define REG_MAC0 0x0081 -#define REG_MAC1 0x0053 -#define FW_MAC0_READY 0x18 -#define FW_MAC1_READY 0x1A -#define MAC0_ON BIT(7) -#define MAC1_ON BIT(0) -#define MAC0_READY BIT(0) -#define MAC1_READY BIT(0) - -/* ----------------------------------------------------- */ -/* 0x0100h ~ 0x01FFh MACTOP General Configuration */ -/* ----------------------------------------------------- */ -#define REG_CR 0x0100 -#define REG_PBP 0x0104 -#define REG_TRXDMA_CTRL 0x010C -#define REG_TRXFF_BNDY 0x0114 -#define REG_TRXFF_STATUS 0x0118 -#define REG_RXFF_PTR 0x011C -#define REG_HIMR 0x0120 -#define REG_HISR 0x0124 -#define REG_HIMRE 0x0128 -#define REG_HISRE 0x012C -#define REG_CPWM 0x012F -#define REG_FWIMR 0x0130 -#define REG_FWISR 0x0134 -#define REG_PKTBUF_DBG_CTRL 0x0140 -#define REG_PKTBUF_DBG_DATA_L 0x0144 -#define REG_PKTBUF_DBG_DATA_H 0x0148 - -#define REG_TC0_CTRL 0x0150 -#define REG_TC1_CTRL 0x0154 -#define REG_TC2_CTRL 0x0158 -#define REG_TC3_CTRL 0x015C -#define REG_TC4_CTRL 0x0160 -#define REG_TCUNIT_BASE 0x0164 -#define REG_MBIST_START 0x0174 -#define REG_MBIST_DONE 0x0178 -#define REG_MBIST_FAIL 0x017C -#define REG_C2HEVT_MSG_NORMAL 0x01A0 -#define REG_C2HEVT_MSG_TEST 0x01B8 -#define REG_C2HEVT_CLEAR 0x01BF -#define REG_MCUTST_1 0x01c0 -#define REG_FMETHR 0x01C8 -#define REG_HMETFR 0x01CC -#define REG_HMEBOX_0 0x01D0 -#define REG_HMEBOX_1 0x01D4 -#define REG_HMEBOX_2 0x01D8 -#define REG_HMEBOX_3 0x01DC - -#define REG_LLT_INIT 0x01E0 -#define REG_BB_ACCEESS_CTRL 0x01E8 -#define REG_BB_ACCESS_DATA 0x01EC - - -/* ----------------------------------------------------- */ -/* 0x0200h ~ 0x027Fh TXDMA Configuration */ -/* ----------------------------------------------------- */ -#define REG_RQPN 0x0200 -#define REG_FIFOPAGE 0x0204 -#define REG_TDECTRL 0x0208 -#define REG_TXDMA_OFFSET_CHK 0x020C -#define REG_TXDMA_STATUS 0x0210 -#define REG_RQPN_NPQ 0x0214 - -/* ----------------------------------------------------- */ -/* 0x0280h ~ 0x02FFh RXDMA Configuration */ -/* ----------------------------------------------------- */ -#define REG_RXDMA_AGG_PG_TH 0x0280 -#define REG_RXPKT_NUM 0x0284 -#define REG_RXDMA_STATUS 0x0288 - -/* ----------------------------------------------------- */ -/* 0x0300h ~ 0x03FFh PCIe */ -/* ----------------------------------------------------- */ -#define REG_PCIE_CTRL_REG 0x0300 -#define REG_INT_MIG 0x0304 -#define REG_BCNQ_DESA 0x0308 -#define REG_HQ_DESA 0x0310 -#define REG_MGQ_DESA 0x0318 -#define REG_VOQ_DESA 0x0320 -#define REG_VIQ_DESA 0x0328 -#define REG_BEQ_DESA 0x0330 -#define REG_BKQ_DESA 0x0338 -#define REG_RX_DESA 0x0340 -#define REG_DBI 0x0348 -#define REG_DBI_WDATA 0x0348 -#define REG_DBI_RDATA 0x034C -#define REG_DBI_CTRL 0x0350 -#define REG_DBI_FLAG 0x0352 -#define REG_MDIO 0x0354 -#define REG_DBG_SEL 0x0360 -#define REG_PCIE_HRPWM 0x0361 -#define REG_PCIE_HCPWM 0x0363 -#define REG_UART_CTRL 0x0364 -#define REG_UART_TX_DESA 0x0370 -#define REG_UART_RX_DESA 0x0378 - -/* ----------------------------------------------------- */ -/* 0x0400h ~ 0x047Fh Protocol Configuration */ -/* ----------------------------------------------------- */ -#define REG_VOQ_INFORMATION 0x0400 -#define REG_VIQ_INFORMATION 0x0404 -#define REG_BEQ_INFORMATION 0x0408 -#define REG_BKQ_INFORMATION 0x040C -#define REG_MGQ_INFORMATION 0x0410 -#define REG_HGQ_INFORMATION 0x0414 -#define REG_BCNQ_INFORMATION 0x0418 - - -#define REG_CPU_MGQ_INFORMATION 0x041C -#define REG_FWHW_TXQ_CTRL 0x0420 -#define REG_HWSEQ_CTRL 0x0423 -#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 -#define REG_TXPKTBUF_MGQ_BDNY 0x0425 -#define REG_MULTI_BCNQ_EN 0x0426 -#define REG_MULTI_BCNQ_OFFSET 0x0427 -#define REG_SPEC_SIFS 0x0428 -#define REG_RL 0x042A -#define REG_DARFRC 0x0430 -#define REG_RARFRC 0x0438 -#define REG_RRSR 0x0440 -#define REG_ARFR0 0x0444 -#define REG_ARFR1 0x0448 -#define REG_ARFR2 0x044C -#define REG_ARFR3 0x0450 -#define REG_AGGLEN_LMT 0x0458 -#define REG_AMPDU_MIN_SPACE 0x045C -#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D -#define REG_FAST_EDCA_CTRL 0x0460 -#define REG_RD_RESP_PKT_TH 0x0463 -#define REG_INIRTS_RATE_SEL 0x0480 -#define REG_INIDATA_RATE_SEL 0x0484 -#define REG_POWER_STATUS 0x04A4 -#define REG_POWER_STAGE1 0x04B4 -#define REG_POWER_STAGE2 0x04B8 -#define REG_PKT_LIFE_TIME 0x04C0 -#define REG_STBC_SETTING 0x04C4 -#define REG_PROT_MODE_CTRL 0x04C8 -#define REG_MAX_AGGR_NUM 0x04CA -#define REG_RTS_MAX_AGGR_NUM 0x04CB -#define REG_BAR_MODE_CTRL 0x04CC -#define REG_RA_TRY_RATE_AGG_LMT 0x04CF -#define REG_EARLY_MODE_CONTROL 0x4D0 -#define REG_NQOS_SEQ 0x04DC -#define REG_QOS_SEQ 0x04DE -#define REG_NEED_CPU_HANDLE 0x04E0 -#define REG_PKT_LOSE_RPT 0x04E1 -#define REG_PTCL_ERR_STATUS 0x04E2 -#define REG_DUMMY 0x04FC - -/* ----------------------------------------------------- */ -/* 0x0500h ~ 0x05FFh EDCA Configuration */ -/* ----------------------------------------------------- */ -#define REG_EDCA_VO_PARAM 0x0500 -#define REG_EDCA_VI_PARAM 0x0504 -#define REG_EDCA_BE_PARAM 0x0508 -#define REG_EDCA_BK_PARAM 0x050C -#define REG_BCNTCFG 0x0510 -#define REG_PIFS 0x0512 -#define REG_RDG_PIFS 0x0513 -#define REG_SIFS_CTX 0x0514 -#define REG_SIFS_TRX 0x0516 -#define REG_AGGR_BREAK_TIME 0x051A -#define REG_SLOT 0x051B -#define REG_TX_PTCL_CTRL 0x0520 -#define REG_TXPAUSE 0x0522 -#define REG_DIS_TXREQ_CLR 0x0523 -#define REG_RD_CTRL 0x0524 -#define REG_TBTT_PROHIBIT 0x0540 -#define REG_RD_NAV_NXT 0x0544 -#define REG_NAV_PROT_LEN 0x0546 -#define REG_BCN_CTRL 0x0550 -#define REG_USTIME_TSF 0x0551 -#define REG_MBID_NUM 0x0552 -#define REG_DUAL_TSF_RST 0x0553 -#define REG_BCN_INTERVAL 0x0554 -#define REG_MBSSID_BCN_SPACE 0x0554 -#define REG_DRVERLYINT 0x0558 -#define REG_BCNDMATIM 0x0559 -#define REG_ATIMWND 0x055A -#define REG_BCN_MAX_ERR 0x055D -#define REG_RXTSF_OFFSET_CCK 0x055E -#define REG_RXTSF_OFFSET_OFDM 0x055F -#define REG_TSFTR 0x0560 -#define REG_INIT_TSFTR 0x0564 -#define REG_PSTIMER 0x0580 -#define REG_TIMER0 0x0584 -#define REG_TIMER1 0x0588 -#define REG_ACMHWCTRL 0x05C0 -#define REG_ACMRSTCTRL 0x05C1 -#define REG_ACMAVG 0x05C2 -#define REG_VO_ADMTIME 0x05C4 -#define REG_VI_ADMTIME 0x05C6 -#define REG_BE_ADMTIME 0x05C8 -#define REG_EDCA_RANDOM_GEN 0x05CC -#define REG_SCH_TXCMD 0x05D0 - -/* Dual MAC Co-Existence Register */ -#define REG_DMC 0x05F0 - -/* ----------------------------------------------------- */ -/* 0x0600h ~ 0x07FFh WMAC Configuration */ -/* ----------------------------------------------------- */ -#define REG_APSD_CTRL 0x0600 -#define REG_BWOPMODE 0x0603 -#define REG_TCR 0x0604 -#define REG_RCR 0x0608 -#define REG_RX_PKT_LIMIT 0x060C -#define REG_RX_DLK_TIME 0x060D -#define REG_RX_DRVINFO_SZ 0x060F - -#define REG_MACID 0x0610 -#define REG_BSSID 0x0618 -#define REG_MAR 0x0620 -#define REG_MBIDCAMCFG 0x0628 - -#define REG_USTIME_EDCA 0x0638 -#define REG_MAC_SPEC_SIFS 0x063A -#define REG_RESP_SIFS_CCK 0x063C -#define REG_RESP_SIFS_OFDM 0x063E -#define REG_ACKTO 0x0640 -#define REG_CTS2TO 0x0641 -#define REG_EIFS 0x0642 - - -/* WMA, BA, CCX */ -#define REG_NAV_CTRL 0x0650 -#define REG_BACAMCMD 0x0654 -#define REG_BACAMCONTENT 0x0658 -#define REG_LBDLY 0x0660 -#define REG_FWDLY 0x0661 -#define REG_RXERR_RPT 0x0664 -#define REG_WMAC_TRXPTCL_CTL 0x0668 - - -/* Security */ -#define REG_CAMCMD 0x0670 -#define REG_CAMWRITE 0x0674 -#define REG_CAMREAD 0x0678 -#define REG_CAMDBG 0x067C -#define REG_SECCFG 0x0680 - -/* Power */ -#define REG_WOW_CTRL 0x0690 -#define REG_PSSTATUS 0x0691 -#define REG_PS_RX_INFO 0x0692 -#define REG_LPNAV_CTRL 0x0694 -#define REG_WKFMCAM_CMD 0x0698 -#define REG_WKFMCAM_RWD 0x069C -#define REG_RXFLTMAP0 0x06A0 -#define REG_RXFLTMAP1 0x06A2 -#define REG_RXFLTMAP2 0x06A4 -#define REG_BCN_PSR_RPT 0x06A8 -#define REG_CALB32K_CTRL 0x06AC -#define REG_PKT_MON_CTRL 0x06B4 -#define REG_BT_COEX_TABLE 0x06C0 -#define REG_WMAC_RESP_TXINFO 0x06D8 - - -/* ----------------------------------------------------- */ -/* Redifine 8192C register definition for compatibility */ -/* ----------------------------------------------------- */ -#define CR9346 REG_9346CR -#define MSR (REG_CR + 2) -#define ISR REG_HISR -#define TSFR REG_TSFTR - -#define MACIDR0 REG_MACID -#define MACIDR4 (REG_MACID + 4) - -#define PBP REG_PBP - -#define IDR0 MACIDR0 -#define IDR4 MACIDR4 - -/* ----------------------------------------------------- */ -/* 8192C (MSR) Media Status Register(Offset 0x4C, 8 bits)*/ -/* ----------------------------------------------------- */ -#define MSR_NOLINK 0x00 -#define MSR_ADHOC 0x01 -#define MSR_INFRA 0x02 -#define MSR_AP 0x03 -#define MSR_MASK 0x03 - -/* 6. Adaptive Control Registers (Offset: 0x0160 - 0x01CF) */ -/* ----------------------------------------------------- */ -/* 8192C Response Rate Set Register(offset 0x181, 24bits)*/ -/* ----------------------------------------------------- */ -#define RRSR_RSC_OFFSET 21 -#define RRSR_SHORT_OFFSET 23 -#define RRSR_RSC_BW_40M 0x600000 -#define RRSR_RSC_UPSUBCHNL 0x400000 -#define RRSR_RSC_LOWSUBCHNL 0x200000 -#define RRSR_SHORT 0x800000 -#define RRSR_1M BIT0 -#define RRSR_2M BIT1 -#define RRSR_5_5M BIT2 -#define RRSR_11M BIT3 -#define RRSR_6M BIT4 -#define RRSR_9M BIT5 -#define RRSR_12M BIT6 -#define RRSR_18M BIT7 -#define RRSR_24M BIT8 -#define RRSR_36M BIT9 -#define RRSR_48M BIT10 -#define RRSR_54M BIT11 -#define RRSR_MCS0 BIT12 -#define RRSR_MCS1 BIT13 -#define RRSR_MCS2 BIT14 -#define RRSR_MCS3 BIT15 -#define RRSR_MCS4 BIT16 -#define RRSR_MCS5 BIT17 -#define RRSR_MCS6 BIT18 -#define RRSR_MCS7 BIT19 -#define BRSR_ACKSHORTPMB BIT23 - -/* ----------------------------------------------------- */ -/* 8192C Rate Definition */ -/* ----------------------------------------------------- */ -/* CCK */ -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -/* OFDM */ -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -/* MCS 1 Spatial Stream */ -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 -/* MCS 2 Spatial Stream */ -#define RATR_MCS8 0x00100000 -#define RATR_MCS9 0x00200000 -#define RATR_MCS10 0x00400000 -#define RATR_MCS11 0x00800000 -#define RATR_MCS12 0x01000000 -#define RATR_MCS13 0x02000000 -#define RATR_MCS14 0x04000000 -#define RATR_MCS15 0x08000000 - -/* CCK */ -#define RATE_1M BIT(0) -#define RATE_2M BIT(1) -#define RATE_5_5M BIT(2) -#define RATE_11M BIT(3) -/* OFDM */ -#define RATE_6M BIT(4) -#define RATE_9M BIT(5) -#define RATE_12M BIT(6) -#define RATE_18M BIT(7) -#define RATE_24M BIT(8) -#define RATE_36M BIT(9) -#define RATE_48M BIT(10) -#define RATE_54M BIT(11) -/* MCS 1 Spatial Stream */ -#define RATE_MCS0 BIT(12) -#define RATE_MCS1 BIT(13) -#define RATE_MCS2 BIT(14) -#define RATE_MCS3 BIT(15) -#define RATE_MCS4 BIT(16) -#define RATE_MCS5 BIT(17) -#define RATE_MCS6 BIT(18) -#define RATE_MCS7 BIT(19) -/* MCS 2 Spatial Stream */ -#define RATE_MCS8 BIT(20) -#define RATE_MCS9 BIT(21) -#define RATE_MCS10 BIT(22) -#define RATE_MCS11 BIT(23) -#define RATE_MCS12 BIT(24) -#define RATE_MCS13 BIT(25) -#define RATE_MCS14 BIT(26) -#define RATE_MCS15 BIT(27) - -/* ALL CCK Rate */ -#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | \ - RATR_11M) -#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | \ - RATR_18M | RATR_24M | \ - RATR_36M | RATR_48M | RATR_54M) -#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \ - RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \ - RATR_MCS6 | RATR_MCS7) -#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \ - RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \ - RATR_MCS14 | RATR_MCS15) - -/* ----------------------------------------------------- */ -/* 8192C BW_OPMODE bits (Offset 0x203, 8bit) */ -/* ----------------------------------------------------- */ -#define BW_OPMODE_20MHZ BIT(2) -#define BW_OPMODE_5G BIT(1) -#define BW_OPMODE_11J BIT(0) - - -/* ----------------------------------------------------- */ -/* 8192C CAM Config Setting (offset 0x250, 1 byte) */ -/* ----------------------------------------------------- */ -#define CAM_VALID BIT(15) -#define CAM_NOTVALID 0x0000 -#define CAM_USEDK BIT(5) - -#define CAM_NONE 0x0 -#define CAM_WEP40 0x01 -#define CAM_TKIP 0x02 -#define CAM_AES 0x04 -#define CAM_WEP104 0x05 -#define CAM_SMS4 0x6 - - -#define TOTAL_CAM_ENTRY 32 -#define HALF_CAM_ENTRY 16 - -#define CAM_WRITE BIT(16) -#define CAM_READ 0x00000000 -#define CAM_POLLINIG BIT(31) - -/* 10. Power Save Control Registers (Offset: 0x0260 - 0x02DF) */ -#define WOW_PMEN BIT0 /* Power management Enable. */ -#define WOW_WOMEN BIT1 /* WoW function on or off. */ -#define WOW_MAGIC BIT2 /* Magic packet */ -#define WOW_UWF BIT3 /* Unicast Wakeup frame. */ - -/* 12. Host Interrupt Status Registers (Offset: 0x0300 - 0x030F) */ -/* ----------------------------------------------------- */ -/* 8190 IMR/ISR bits (offset 0xfd, 8bits) */ -/* ----------------------------------------------------- */ -#define IMR8190_DISABLED 0x0 -#define IMR_BCNDMAINT6 BIT(31) -#define IMR_BCNDMAINT5 BIT(30) -#define IMR_BCNDMAINT4 BIT(29) -#define IMR_BCNDMAINT3 BIT(28) -#define IMR_BCNDMAINT2 BIT(27) -#define IMR_BCNDMAINT1 BIT(26) -#define IMR_BCNDOK8 BIT(25) -#define IMR_BCNDOK7 BIT(24) -#define IMR_BCNDOK6 BIT(23) -#define IMR_BCNDOK5 BIT(22) -#define IMR_BCNDOK4 BIT(21) -#define IMR_BCNDOK3 BIT(20) -#define IMR_BCNDOK2 BIT(19) -#define IMR_BCNDOK1 BIT(18) -#define IMR_TIMEOUT2 BIT(17) -#define IMR_TIMEOUT1 BIT(16) -#define IMR_TXFOVW BIT(15) -#define IMR_PSTIMEOUT BIT(14) -#define IMR_BCNINT BIT(13) -#define IMR_RXFOVW BIT(12) -#define IMR_RDU BIT(11) -#define IMR_ATIMEND BIT(10) -#define IMR_BDOK BIT(9) -#define IMR_HIGHDOK BIT(8) -#define IMR_TBDOK BIT(7) -#define IMR_MGNTDOK BIT(6) -#define IMR_TBDER BIT(5) -#define IMR_BKDOK BIT(4) -#define IMR_BEDOK BIT(3) -#define IMR_VIDOK BIT(2) -#define IMR_VODOK BIT(1) -#define IMR_ROK BIT(0) - -#define IMR_TXERR BIT(11) -#define IMR_RXERR BIT(10) -#define IMR_C2HCMD BIT(9) -#define IMR_CPWM BIT(8) -#define IMR_OCPINT BIT(1) -#define IMR_WLANOFF BIT(0) - -/* ----------------------------------------------------- */ -/* 8192C EFUSE */ -/* ----------------------------------------------------- */ -#define HWSET_MAX_SIZE 256 -#define EFUSE_MAX_SECTION 32 -#define EFUSE_REAL_CONTENT_LEN 512 - -/* ----------------------------------------------------- */ -/* 8192C EEPROM/EFUSE share register definition. */ -/* ----------------------------------------------------- */ -#define EEPROM_DEFAULT_TSSI 0x0 -#define EEPROM_DEFAULT_CRYSTALCAP 0x0 -#define EEPROM_DEFAULT_THERMALMETER 0x12 - -#define EEPROM_DEFAULT_TXPOWERLEVEL_2G 0x2C -#define EEPROM_DEFAULT_TXPOWERLEVEL_5G 0x22 - -#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 -/* HT20<->40 default Tx Power Index Difference */ -#define EEPROM_DEFAULT_HT20_DIFF 2 -/* OFDM Tx Power index diff */ -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x4 -#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 -#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 - -#define EEPROM_CHANNEL_PLAN_FCC 0x0 -#define EEPROM_CHANNEL_PLAN_IC 0x1 -#define EEPROM_CHANNEL_PLAN_ETSI 0x2 -#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 -#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 -#define EEPROM_CHANNEL_PLAN_MKK 0x5 -#define EEPROM_CHANNEL_PLAN_MKK1 0x6 -#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 -#define EEPROM_CHANNEL_PLAN_TELEC 0x8 -#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 -#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -#define EEPROM_CHANNEL_PLAN_NCC 0xB -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - -#define EEPROM_CID_DEFAULT 0x0 -#define EEPROM_CID_TOSHIBA 0x4 -#define EEPROM_CID_CCX 0x10 -#define EEPROM_CID_QMI 0x0D -#define EEPROM_CID_WHQL 0xFE - - -#define RTL8192_EEPROM_ID 0x8129 -#define EEPROM_WAPI_SUPPORT 0x78 - - -#define RTL8190_EEPROM_ID 0x8129 /* 0-1 */ -#define EEPROM_HPON 0x02 /* LDO settings.2-5 */ -#define EEPROM_CLK 0x06 /* Clock settings.6-7 */ -#define EEPROM_MAC_FUNCTION 0x08 /* SE Test mode.8 */ - -#define EEPROM_VID 0x28 /* SE Vendor ID.A-B */ -#define EEPROM_DID 0x2A /* SE Device ID. C-D */ -#define EEPROM_SVID 0x2C /* SE Vendor ID.E-F */ -#define EEPROM_SMID 0x2E /* SE PCI Subsystem ID. 10-11 */ - -#define EEPROM_MAC_ADDR 0x16 /* SEMAC Address. 12-17 */ -#define EEPROM_MAC_ADDR_MAC0_92D 0x55 -#define EEPROM_MAC_ADDR_MAC1_92D 0x5B - -/* 2.4G band Tx power index setting */ -#define EEPROM_CCK_TX_PWR_INX_2G 0x61 -#define EEPROM_HT40_1S_TX_PWR_INX_2G 0x67 -#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_2G 0x6D -#define EEPROM_HT20_TX_PWR_INX_DIFF_2G 0x70 -#define EEPROM_OFDM_TX_PWR_INX_DIFF_2G 0x73 -#define EEPROM_HT40_MAX_PWR_OFFSET_2G 0x76 -#define EEPROM_HT20_MAX_PWR_OFFSET_2G 0x79 - -/*5GL channel 32-64 */ -#define EEPROM_HT40_1S_TX_PWR_INX_5GL 0x7C -#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GL 0x82 -#define EEPROM_HT20_TX_PWR_INX_DIFF_5GL 0x85 -#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GL 0x88 -#define EEPROM_HT40_MAX_PWR_OFFSET_5GL 0x8B -#define EEPROM_HT20_MAX_PWR_OFFSET_5GL 0x8E - -/* 5GM channel 100-140 */ -#define EEPROM_HT40_1S_TX_PWR_INX_5GM 0x91 -#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GM 0x97 -#define EEPROM_HT20_TX_PWR_INX_DIFF_5GM 0x9A -#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GM 0x9D -#define EEPROM_HT40_MAX_PWR_OFFSET_5GM 0xA0 -#define EEPROM_HT20_MAX_PWR_OFFSET_5GM 0xA3 - -/* 5GH channel 149-165 */ -#define EEPROM_HT40_1S_TX_PWR_INX_5GH 0xA6 -#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GH 0xAC -#define EEPROM_HT20_TX_PWR_INX_DIFF_5GH 0xAF -#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GH 0xB2 -#define EEPROM_HT40_MAX_PWR_OFFSET_5GH 0xB5 -#define EEPROM_HT20_MAX_PWR_OFFSET_5GH 0xB8 - -/* Map of supported channels. */ -#define EEPROM_CHANNEL_PLAN 0xBB -#define EEPROM_IQK_DELTA 0xBC -#define EEPROM_LCK_DELTA 0xBC -#define EEPROM_XTAL_K 0xBD /* [7:5] */ -#define EEPROM_TSSI_A_5G 0xBE -#define EEPROM_TSSI_B_5G 0xBF -#define EEPROM_TSSI_AB_5G 0xC0 -#define EEPROM_THERMAL_METER 0xC3 /* [4:0] */ -#define EEPROM_RF_OPT1 0xC4 -#define EEPROM_RF_OPT2 0xC5 -#define EEPROM_RF_OPT3 0xC6 -#define EEPROM_RF_OPT4 0xC7 -#define EEPROM_RF_OPT5 0xC8 -#define EEPROM_RF_OPT6 0xC9 -#define EEPROM_VERSION 0xCA -#define EEPROM_CUSTOMER_ID 0xCB -#define EEPROM_RF_OPT7 0xCC - -#define EEPROM_DEF_PART_NO 0x3FD /* Byte */ -#define EEPROME_CHIP_VERSION_L 0x3FF -#define EEPROME_CHIP_VERSION_H 0x3FE - -/* - * Current IOREG MAP - * 0x0000h ~ 0x00FFh System Configuration (256 Bytes) - * 0x0100h ~ 0x01FFh MACTOP General Configuration (256 Bytes) - * 0x0200h ~ 0x027Fh TXDMA Configuration (128 Bytes) - * 0x0280h ~ 0x02FFh RXDMA Configuration (128 Bytes) - * 0x0300h ~ 0x03FFh PCIE EMAC Reserved Region (256 Bytes) - * 0x0400h ~ 0x04FFh Protocol Configuration (256 Bytes) - * 0x0500h ~ 0x05FFh EDCA Configuration (256 Bytes) - * 0x0600h ~ 0x07FFh WMAC Configuration (512 Bytes) - * 0x2000h ~ 0x3FFFh 8051 FW Download Region (8196 Bytes) - */ - -/* ----------------------------------------------------- */ -/* 8192C (RCR) (Offset 0x608, 32 bits) */ -/* ----------------------------------------------------- */ -#define RCR_APPFCS BIT(31) -#define RCR_APP_MIC BIT(30) -#define RCR_APP_ICV BIT(29) -#define RCR_APP_PHYST_RXFF BIT(28) -#define RCR_APP_BA_SSN BIT(27) -#define RCR_ENMBID BIT(24) -#define RCR_LSIGEN BIT(23) -#define RCR_MFBEN BIT(22) -#define RCR_HTC_LOC_CTRL BIT(14) -#define RCR_AMF BIT(13) -#define RCR_ACF BIT(12) -#define RCR_ADF BIT(11) -#define RCR_AICV BIT(9) -#define RCR_ACRC32 BIT(8) -#define RCR_CBSSID_BCN BIT(7) -#define RCR_CBSSID_DATA BIT(6) -#define RCR_APWRMGT BIT(5) -#define RCR_ADD3 BIT(4) -#define RCR_AB BIT(3) -#define RCR_AM BIT(2) -#define RCR_APM BIT(1) -#define RCR_AAP BIT(0) -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - -/* ----------------------------------------------------- */ -/* 8192C Regsiter Bit and Content definition */ -/* ----------------------------------------------------- */ -/* ----------------------------------------------------- */ -/* 0x0000h ~ 0x00FFh System Configuration */ -/* ----------------------------------------------------- */ - -/* SPS0_CTRL */ -#define SW18_FPWM BIT(3) - - -/* SYS_ISO_CTRL */ -#define ISO_MD2PP BIT(0) -#define ISO_UA2USB BIT(1) -#define ISO_UD2CORE BIT(2) -#define ISO_PA2PCIE BIT(3) -#define ISO_PD2CORE BIT(4) -#define ISO_IP2MAC BIT(5) -#define ISO_DIOP BIT(6) -#define ISO_DIOE BIT(7) -#define ISO_EB2CORE BIT(8) -#define ISO_DIOR BIT(9) - -#define PWC_EV25V BIT(14) -#define PWC_EV12V BIT(15) - - -/* SYS_FUNC_EN */ -#define FEN_BBRSTB BIT(0) -#define FEN_BB_GLB_RSTn BIT(1) -#define FEN_USBA BIT(2) -#define FEN_UPLL BIT(3) -#define FEN_USBD BIT(4) -#define FEN_DIO_PCIE BIT(5) -#define FEN_PCIEA BIT(6) -#define FEN_PPLL BIT(7) -#define FEN_PCIED BIT(8) -#define FEN_DIOE BIT(9) -#define FEN_CPUEN BIT(10) -#define FEN_DCORE BIT(11) -#define FEN_ELDR BIT(12) -#define FEN_DIO_RF BIT(13) -#define FEN_HWPDN BIT(14) -#define FEN_MREGEN BIT(15) - -/* APS_FSMCO */ -#define PFM_LDALL BIT(0) -#define PFM_ALDN BIT(1) -#define PFM_LDKP BIT(2) -#define PFM_WOWL BIT(3) -#define EnPDN BIT(4) -#define PDN_PL BIT(5) -#define APFM_ONMAC BIT(8) -#define APFM_OFF BIT(9) -#define APFM_RSM BIT(10) -#define AFSM_HSUS BIT(11) -#define AFSM_PCIE BIT(12) -#define APDM_MAC BIT(13) -#define APDM_HOST BIT(14) -#define APDM_HPDN BIT(15) -#define RDY_MACON BIT(16) -#define SUS_HOST BIT(17) -#define ROP_ALD BIT(20) -#define ROP_PWR BIT(21) -#define ROP_SPS BIT(22) -#define SOP_MRST BIT(25) -#define SOP_FUSE BIT(26) -#define SOP_ABG BIT(27) -#define SOP_AMB BIT(28) -#define SOP_RCK BIT(29) -#define SOP_A8M BIT(30) -#define XOP_BTCK BIT(31) - -/* SYS_CLKR */ -#define ANAD16V_EN BIT(0) -#define ANA8M BIT(1) -#define MACSLP BIT(4) -#define LOADER_CLK_EN BIT(5) -#define _80M_SSC_DIS BIT(7) -#define _80M_SSC_EN_HO BIT(8) -#define PHY_SSC_RSTB BIT(9) -#define SEC_CLK_EN BIT(10) -#define MAC_CLK_EN BIT(11) -#define SYS_CLK_EN BIT(12) -#define RING_CLK_EN BIT(13) - - -/* 9346CR */ -#define BOOT_FROM_EEPROM BIT(4) -#define EEPROM_EN BIT(5) - -/* AFE_MISC */ -#define AFE_BGEN BIT(0) -#define AFE_MBEN BIT(1) -#define MAC_ID_EN BIT(7) - -/* RSV_CTRL */ -#define WLOCK_ALL BIT(0) -#define WLOCK_00 BIT(1) -#define WLOCK_04 BIT(2) -#define WLOCK_08 BIT(3) -#define WLOCK_40 BIT(4) -#define R_DIS_PRST_0 BIT(5) -#define R_DIS_PRST_1 BIT(6) -#define LOCK_ALL_EN BIT(7) - -/* RF_CTRL */ -#define RF_EN BIT(0) -#define RF_RSTB BIT(1) -#define RF_SDMRSTB BIT(2) - - - -/* LDOA15_CTRL */ -#define LDA15_EN BIT(0) -#define LDA15_STBY BIT(1) -#define LDA15_OBUF BIT(2) -#define LDA15_REG_VOS BIT(3) -#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) - - - -/* LDOV12D_CTRL */ -#define LDV12_EN BIT(0) -#define LDV12_SDBY BIT(1) -#define LPLDO_HSM BIT(2) -#define LPLDO_LSM_DIS BIT(3) -#define _LDV12_VADJ(x) (((x) & 0xF) << 4) - - -/* AFE_XTAL_CTRL */ -#define XTAL_EN BIT(0) -#define XTAL_BSEL BIT(1) -#define _XTAL_BOSC(x) (((x) & 0x3) << 2) -#define _XTAL_CADJ(x) (((x) & 0xF) << 4) -#define XTAL_GATE_USB BIT(8) -#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) -#define XTAL_GATE_AFE BIT(11) -#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) -#define XTAL_RF_GATE BIT(14) -#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) -#define XTAL_GATE_DIG BIT(17) -#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) -#define XTAL_BT_GATE BIT(20) -#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) -#define _XTAL_GPIO(x) (((x) & 0x7) << 23) - - -#define CKDLY_AFE BIT(26) -#define CKDLY_USB BIT(27) -#define CKDLY_DIG BIT(28) -#define CKDLY_BT BIT(29) - - -/* AFE_PLL_CTRL */ -#define APLL_EN BIT(0) -#define APLL_320_EN BIT(1) -#define APLL_FREF_SEL BIT(2) -#define APLL_EDGE_SEL BIT(3) -#define APLL_WDOGB BIT(4) -#define APLL_LPFEN BIT(5) - -#define APLL_REF_CLK_13MHZ 0x1 -#define APLL_REF_CLK_19_2MHZ 0x2 -#define APLL_REF_CLK_20MHZ 0x3 -#define APLL_REF_CLK_25MHZ 0x4 -#define APLL_REF_CLK_26MHZ 0x5 -#define APLL_REF_CLK_38_4MHZ 0x6 -#define APLL_REF_CLK_40MHZ 0x7 - -#define APLL_320EN BIT(14) -#define APLL_80EN BIT(15) -#define APLL_1MEN BIT(24) - - -/* EFUSE_CTRL */ -#define ALD_EN BIT(18) -#define EF_PD BIT(19) -#define EF_FLAG BIT(31) - -/* EFUSE_TEST */ -#define EF_TRPT BIT(7) -#define LDOE25_EN BIT(31) - -/* MCUFWDL */ -#define MCUFWDL_EN BIT(0) -#define MCUFWDL_RDY BIT(1) -#define FWDL_ChkSum_rpt BIT(2) -#define MACINI_RDY BIT(3) -#define BBINI_RDY BIT(4) -#define RFINI_RDY BIT(5) -#define WINTINI_RDY BIT(6) -#define MAC1_WINTINI_RDY BIT(11) -#define CPRST BIT(23) - -/* REG_SYS_CFG */ -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define TRP_B15V_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) - -/* LLT_INIT */ -#define _LLT_NO_ACTIVE 0x0 -#define _LLT_WRITE_ACCESS 0x1 -#define _LLT_READ_ACCESS 0x2 - -#define _LLT_INIT_DATA(x) ((x) & 0xFF) -#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) -#define _LLT_OP(x) (((x) & 0x3) << 30) -#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) - - -/* ----------------------------------------------------- */ -/* 0x0400h ~ 0x047Fh Protocol Configuration */ -/* ----------------------------------------------------- */ -#define RETRY_LIMIT_SHORT_SHIFT 8 -#define RETRY_LIMIT_LONG_SHIFT 0 - - -/* ----------------------------------------------------- */ -/* 0x0500h ~ 0x05FFh EDCA Configuration */ -/* ----------------------------------------------------- */ -/* EDCA setting */ -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - -/* ACMHWCTRL */ -#define ACMHW_HWEN BIT(0) -#define ACMHW_BEQEN BIT(1) -#define ACMHW_VIQEN BIT(2) -#define ACMHW_VOQEN BIT(3) - -/* ----------------------------------------------------- */ -/* 0x0600h ~ 0x07FFh WMAC Configuration */ -/* ----------------------------------------------------- */ - -/* TCR */ -#define TSFRST BIT(0) -#define DIS_GCLK BIT(1) -#define PAD_SEL BIT(2) -#define PWR_ST BIT(6) -#define PWRBIT_OW_EN BIT(7) -#define ACRC BIT(8) -#define CFENDFORM BIT(9) -#define ICV BIT(10) - -/* SECCFG */ -#define SCR_TXUSEDK BIT(0) -#define SCR_RXUSEDK BIT(1) -#define SCR_TXENCENABLE BIT(2) -#define SCR_RXENCENABLE BIT(3) -#define SCR_SKBYA2 BIT(4) -#define SCR_NOSKMC BIT(5) -#define SCR_TXBCUSEDK BIT(6) -#define SCR_RXBCUSEDK BIT(7) - -/* General definitions */ -#define LAST_ENTRY_OF_TX_PKT_BUFFER 255 -#define LAST_ENTRY_OF_TX_PKT_BUFFER_DUAL_MAC 127 - -#define POLLING_LLT_THRESHOLD 20 -#define POLLING_READY_TIMEOUT_COUNT 1000 - -/* Min Spacing related settings. */ -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - - -/* BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF */ -/* 1. PMAC duplicate register due to connection: */ -/* RF_Mode, TRxRN, NumOf L-STF */ -/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */ -/* 3. RF register 0x00-2E */ -/* 4. Bit Mask for BB/RF register */ -/* 5. Other defintion for BB/RF R/W */ - -/* 3. Page8(0x800) */ -#define RFPGA0_RFMOD 0x800 - -#define RFPGA0_TXINFO 0x804 -#define RFPGA0_PSDFUNCTION 0x808 - -#define RFPGA0_TXGAINSTAGE 0x80c - -#define RFPGA0_RFTIMING1 0x810 -#define RFPGA0_RFTIMING2 0x814 - -#define RFPGA0_XA_HSSIPARAMETER1 0x820 -#define RFPGA0_XA_HSSIPARAMETER2 0x824 -#define RFPGA0_XB_HSSIPARAMETER1 0x828 -#define RFPGA0_XB_HSSIPARAMETER2 0x82c - -#define RFPGA0_XA_LSSIPARAMETER 0x840 -#define RFPGA0_XB_LSSIPARAMETER 0x844 - -#define RFPGA0_RFWAkEUPPARAMETER 0x850 -#define RFPGA0_RFSLEEPUPPARAMETER 0x854 - -#define RFPGA0_XAB_SWITCHCONTROL 0x858 -#define RFPGA0_XCD_SWITCHCONTROL 0x85c - -#define RFPGA0_XA_RFINTERFACEOE 0x860 -#define RFPGA0_XB_RFINTERFACEOE 0x864 - -#define RFPGA0_XAB_RFINTERFACESW 0x870 -#define RFPGA0_XCD_RFINTERFACESW 0x874 - -#define RFPGA0_XAB_RFPARAMETER 0x878 -#define RFPGA0_XCD_RFPARAMETER 0x87c - -#define RFPGA0_ANALOGPARAMETER1 0x880 -#define RFPGA0_ANALOGPARAMETER2 0x884 -#define RFPGA0_ANALOGPARAMETER3 0x888 -#define RFPGA0_ADDALLOCKEN 0x888 -#define RFPGA0_ANALOGPARAMETER4 0x88c - -#define RFPGA0_XA_LSSIREADBACK 0x8a0 -#define RFPGA0_XB_LSSIREADBACK 0x8a4 -#define RFPGA0_XC_LSSIREADBACK 0x8a8 -#define RFPGA0_XD_LSSIREADBACK 0x8ac - -#define RFPGA0_PSDREPORT 0x8b4 -#define TRANSCEIVERA_HSPI_READBACK 0x8b8 -#define TRANSCEIVERB_HSPI_READBACK 0x8bc -#define RFPGA0_XAB_RFINTERFACERB 0x8e0 -#define RFPGA0_XCD_RFINTERFACERB 0x8e4 - -/* 4. Page9(0x900) */ -#define RFPGA1_RFMOD 0x900 - -#define RFPGA1_TXBLOCK 0x904 -#define RFPGA1_DEBUGSELECT 0x908 -#define RFPGA1_TXINFO 0x90c - -/* 5. PageA(0xA00) */ -#define RCCK0_SYSTEM 0xa00 - -#define RCCK0_AFESSTTING 0xa04 -#define RCCK0_CCA 0xa08 - -#define RCCK0_RXAGC1 0xa0c -#define RCCK0_RXAGC2 0xa10 - -#define RCCK0_RXHP 0xa14 - -#define RCCK0_DSPPARAMETER1 0xa18 -#define RCCK0_DSPPARAMETER2 0xa1c - -#define RCCK0_TXFILTER1 0xa20 -#define RCCK0_TXFILTER2 0xa24 -#define RCCK0_DEBUGPORT 0xa28 -#define RCCK0_FALSEALARMREPORT 0xa2c -#define RCCK0_TRSSIREPORT 0xa50 -#define RCCK0_RXREPORT 0xa54 -#define RCCK0_FACOUNTERLOWER 0xa5c -#define RCCK0_FACOUNTERUPPER 0xa58 - -/* 6. PageC(0xC00) */ -#define ROFDM0_LSTF 0xc00 - -#define ROFDM0_TRXPATHENABLE 0xc04 -#define ROFDM0_TRMUXPAR 0xc08 -#define ROFDM0_TRSWISOLATION 0xc0c - -#define ROFDM0_XARXAFE 0xc10 -#define ROFDM0_XARXIQIMBALANCE 0xc14 -#define ROFDM0_XBRXAFE 0xc18 -#define ROFDM0_XBRXIQIMBALANCE 0xc1c -#define ROFDM0_XCRXAFE 0xc20 -#define ROFDM0_XCRXIQIMBALANCE 0xc24 -#define ROFDM0_XDRXAFE 0xc28 -#define ROFDM0_XDRXIQIMBALANCE 0xc2c - -#define ROFDM0_RXDETECTOR1 0xc30 -#define ROFDM0_RXDETECTOR2 0xc34 -#define ROFDM0_RXDETECTOR3 0xc38 -#define ROFDM0_RXDETECTOR4 0xc3c - -#define ROFDM0_RXDSP 0xc40 -#define ROFDM0_CFOANDDAGC 0xc44 -#define ROFDM0_CCADROPTHRESHOLD 0xc48 -#define ROFDM0_ECCATHRESHOLD 0xc4c - -#define ROFDM0_XAAGCCORE1 0xc50 -#define ROFDM0_XAAGCCORE2 0xc54 -#define ROFDM0_XBAGCCORE1 0xc58 -#define ROFDM0_XBAGCCORE2 0xc5c -#define ROFDM0_XCAGCCORE1 0xc60 -#define ROFDM0_XCAGCCORE2 0xc64 -#define ROFDM0_XDAGCCORE1 0xc68 -#define ROFDM0_XDAGCCORE2 0xc6c - -#define ROFDM0_AGCPARAMETER1 0xc70 -#define ROFDM0_AGCPARAMETER2 0xc74 -#define ROFDM0_AGCRSSITABLE 0xc78 -#define ROFDM0_HTSTFAGC 0xc7c - -#define ROFDM0_XATxIQIMBALANCE 0xc80 -#define ROFDM0_XATxAFE 0xc84 -#define ROFDM0_XBTxIQIMBALANCE 0xc88 -#define ROFDM0_XBTxAFE 0xc8c -#define ROFDM0_XCTxIQIMBALANCE 0xc90 -#define ROFDM0_XCTxAFE 0xc94 -#define ROFDM0_XDTxIQIMBALANCE 0xc98 -#define ROFDM0_XDTxAFE 0xc9c - -#define ROFDM0_RXHPPARAMETER 0xce0 -#define ROFDM0_TXPSEUDONOISEWGT 0xce4 -#define ROFDM0_FRAMESYNC 0xcf0 -#define ROFDM0_DFSREPORT 0xcf4 -#define ROFDM0_TXCOEFF1 0xca4 -#define ROFDM0_TXCOEFF2 0xca8 -#define ROFDM0_TXCOEFF3 0xcac -#define ROFDM0_TXCOEFF4 0xcb0 -#define ROFDM0_TXCOEFF5 0xcb4 -#define ROFDM0_TXCOEFF6 0xcb8 - -/* 7. PageD(0xD00) */ -#define ROFDM1_LSTF 0xd00 -#define ROFDM1_TRXPATHENABLE 0xd04 - -#define ROFDM1_CFO 0xd08 -#define ROFDM1_CSI1 0xd10 -#define ROFDM1_SBD 0xd14 -#define ROFDM1_CSI2 0xd18 -#define ROFDM1_CFOTRACKING 0xd2c -#define ROFDM1_TRXMESAURE1 0xd34 -#define ROFDM1_INTFDET 0xd3c -#define ROFDM1_PSEUDONOISESTATEAB 0xd50 -#define ROFDM1_PSEUDONOISESTATECD 0xd54 -#define ROFDM1_RXPSEUDONOISEWGT 0xd58 - -#define ROFDM_PHYCOUNTER1 0xda0 -#define ROFDM_PHYCOUNTER2 0xda4 -#define ROFDM_PHYCOUNTER3 0xda8 - -#define ROFDM_SHORTCFOAB 0xdac -#define ROFDM_SHORTCFOCD 0xdb0 -#define ROFDM_LONGCFOAB 0xdb4 -#define ROFDM_LONGCFOCD 0xdb8 -#define ROFDM_TAILCFOAB 0xdbc -#define ROFDM_TAILCFOCD 0xdc0 -#define ROFDM_PWMEASURE1 0xdc4 -#define ROFDM_PWMEASURE2 0xdc8 -#define ROFDM_BWREPORT 0xdcc -#define ROFDM_AGCREPORT 0xdd0 -#define ROFDM_RXSNR 0xdd4 -#define ROFDM_RXEVMCSI 0xdd8 -#define ROFDM_SIGReport 0xddc - -/* 8. PageE(0xE00) */ -#define RTXAGC_A_RATE18_06 0xe00 -#define RTXAGC_A_RATE54_24 0xe04 -#define RTXAGC_A_CCK1_MCS32 0xe08 -#define RTXAGC_A_MCS03_MCS00 0xe10 -#define RTXAGC_A_MCS07_MCS04 0xe14 -#define RTXAGC_A_MCS11_MCS08 0xe18 -#define RTXAGC_A_MCS15_MCS12 0xe1c - -#define RTXAGC_B_RATE18_06 0x830 -#define RTXAGC_B_RATE54_24 0x834 -#define RTXAGC_B_CCK1_55_MCS32 0x838 -#define RTXAGC_B_MCS03_MCS00 0x83c -#define RTXAGC_B_MCS07_MCS04 0x848 -#define RTXAGC_B_MCS11_MCS08 0x84c -#define RTXAGC_B_MCS15_MCS12 0x868 -#define RTXAGC_B_CCK11_A_CCK2_11 0x86c - -/* RL6052 Register definition */ -#define RF_AC 0x00 - -#define RF_IQADJ_G1 0x01 -#define RF_IQADJ_G2 0x02 -#define RF_POW_TRSW 0x05 - -#define RF_GAIN_RX 0x06 -#define RF_GAIN_TX 0x07 - -#define RF_TXM_IDAC 0x08 -#define RF_BS_IQGEN 0x0F - -#define RF_MODE1 0x10 -#define RF_MODE2 0x11 - -#define RF_RX_AGC_HP 0x12 -#define RF_TX_AGC 0x13 -#define RF_BIAS 0x14 -#define RF_IPA 0x15 -#define RF_POW_ABILITY 0x17 -#define RF_MODE_AG 0x18 -#define rRfChannel 0x18 -#define RF_CHNLBW 0x18 -#define RF_TOP 0x19 - -#define RF_RX_G1 0x1A -#define RF_RX_G2 0x1B - -#define RF_RX_BB2 0x1C -#define RF_RX_BB1 0x1D - -#define RF_RCK1 0x1E -#define RF_RCK2 0x1F - -#define RF_TX_G1 0x20 -#define RF_TX_G2 0x21 -#define RF_TX_G3 0x22 - -#define RF_TX_BB1 0x23 - -#define RF_T_METER 0x42 - -#define RF_SYN_G1 0x25 -#define RF_SYN_G2 0x26 -#define RF_SYN_G3 0x27 -#define RF_SYN_G4 0x28 -#define RF_SYN_G5 0x29 -#define RF_SYN_G6 0x2A -#define RF_SYN_G7 0x2B -#define RF_SYN_G8 0x2C - -#define RF_RCK_OS 0x30 - -#define RF_TXPA_G1 0x31 -#define RF_TXPA_G2 0x32 -#define RF_TXPA_G3 0x33 - -/* Bit Mask */ - -/* 2. Page8(0x800) */ -#define BRFMOD 0x1 -#define BCCKTXSC 0x30 -#define BCCKEN 0x1000000 -#define BOFDMEN 0x2000000 - -#define B3WIREDATALENGTH 0x800 -#define B3WIREADDRESSLENGTH 0x400 - -#define BRFSI_RFENV 0x10 - -#define BLSSIREADADDRESS 0x7f800000 -#define BLSSIREADEDGE 0x80000000 -#define BLSSIREADBACKDATA 0xfffff -/* 4. PageA(0xA00) */ -#define BCCKSIDEBAND 0x10 - -/* Other Definition */ -#define BBYTE0 0x1 -#define BBYTE1 0x2 -#define BBYTE2 0x4 -#define BBYTE3 0x8 -#define BWORD0 0x3 -#define BWORD1 0xc -#define BDWORD 0xf - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c deleted file mode 100644 index 6a6ac540d5b5..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c +++ /dev/null @@ -1,623 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" -#include "hw.h" - -void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u8 rfpath; - - switch (bandwidth) { - case HT_CHANNEL_WIDTH_20: - for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { - rtlphy->rfreg_chnlval[rfpath] = ((rtlphy->rfreg_chnlval - [rfpath] & 0xfffff3ff) | 0x0400); - rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) | - BIT(11), 0x01); - - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "20M RF 0x18 = 0x%x\n", - rtlphy->rfreg_chnlval[rfpath]); - } - - break; - case HT_CHANNEL_WIDTH_20_40: - for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { - rtlphy->rfreg_chnlval[rfpath] = - ((rtlphy->rfreg_chnlval[rfpath] & 0xfffff3ff)); - rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) | BIT(11), - 0x00); - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "40M RF 0x18 = 0x%x\n", - rtlphy->rfreg_chnlval[rfpath]); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", bandwidth); - break; - } -} - -void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 tx_agc[2] = {0, 0}, tmpval; - bool turbo_scanoff = false; - u8 idx1, idx2; - u8 *ptr; - - if (rtlefuse->eeprom_regulatory != 0) - turbo_scanoff = true; - if (mac->act_scanning) { - tx_agc[RF90_PATH_A] = 0x3f3f3f3f; - tx_agc[RF90_PATH_B] = 0x3f3f3f3f; - if (turbo_scanoff) { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - } - } else { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - if (rtlefuse->eeprom_regulatory == 0) { - tmpval = (rtlphy->mcs_offset[0][6]) + - (rtlphy->mcs_offset[0][7] << 8); - tx_agc[RF90_PATH_A] += tmpval; - tmpval = (rtlphy->mcs_offset[0][14]) + - (rtlphy->mcs_offset[0][15] << 24); - tx_agc[RF90_PATH_B] += tmpval; - } - } - - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - ptr = (u8 *) (&(tx_agc[idx1])); - for (idx2 = 0; idx2 < 4; idx2++) { - if (*ptr > RF6052_MAX_TX_PWR) - *ptr = RF6052_MAX_TX_PWR; - ptr++; - } - } - - tmpval = tx_agc[RF90_PATH_A] & 0xff; - rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", - tmpval, RTXAGC_A_CCK1_MCS32); - tmpval = tx_agc[RF90_PATH_A] >> 8; - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", - tmpval, RTXAGC_B_CCK11_A_CCK2_11); - tmpval = tx_agc[RF90_PATH_B] >> 24; - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", - tmpval, RTXAGC_B_CCK11_A_CCK2_11); - tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; - rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", - tmpval, RTXAGC_B_CCK1_55_MCS32); -} - -static void _rtl92d_phy_get_power_base(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel, - u32 *ofdmbase, u32 *mcsbase) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 powerbase0, powerbase1; - u8 legacy_pwrdiff, ht20_pwrdiff; - u8 i, powerlevel[2]; - - for (i = 0; i < 2; i++) { - powerlevel[i] = ppowerlevel[i]; - legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; - powerbase0 = powerlevel[i] + legacy_pwrdiff; - powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | - (powerbase0 << 8) | powerbase0; - *(ofdmbase + i) = powerbase0; - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [OFDM power base index rf(%c) = 0x%x]\n", - i == 0 ? 'A' : 'B', *(ofdmbase + i)); - } - - for (i = 0; i < 2; i++) { - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { - ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1]; - powerlevel[i] += ht20_pwrdiff; - } - powerbase1 = powerlevel[i]; - powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) | - (powerbase1 << 8) | powerbase1; - *(mcsbase + i) = powerbase1; - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [MCS power base index rf(%c) = 0x%x]\n", - i == 0 ? 'A' : 'B', *(mcsbase + i)); - } -} - -static u8 _rtl92d_phy_get_chnlgroup_bypg(u8 chnlindex) -{ - u8 group; - u8 channel_info[59] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, - 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, - 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, - 134, 136, 138, 140, 149, 151, 153, 155, 157, 159, - 161, 163, 165 - }; - - if (channel_info[chnlindex] <= 3) /* Chanel 1-3 */ - group = 0; - else if (channel_info[chnlindex] <= 9) /* Channel 4-9 */ - group = 1; - else if (channel_info[chnlindex] <= 14) /* Channel 10-14 */ - group = 2; - else if (channel_info[chnlindex] <= 64) - group = 6; - else if (channel_info[chnlindex] <= 140) - group = 7; - else - group = 8; - return group; -} - -static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, - u8 channel, u8 index, - u32 *powerbase0, - u32 *powerbase1, - u32 *p_outwriteval) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 i, chnlgroup = 0, pwr_diff_limit[4]; - u32 writeval = 0, customer_limit, rf; - - for (rf = 0; rf < 2; rf++) { - switch (rtlefuse->eeprom_regulatory) { - case 0: - chnlgroup = 0; - writeval = rtlphy->mcs_offset - [chnlgroup][index + - (rf ? 8 : 0)] + ((index < 2) ? - powerbase0[rf] : - powerbase1[rf]); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeval(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeval); - break; - case 1: - if (rtlphy->pwrgroup_cnt == 1) - chnlgroup = 0; - if (rtlphy->pwrgroup_cnt >= MAX_PG_GROUP) { - chnlgroup = _rtl92d_phy_get_chnlgroup_bypg( - channel - 1); - if (rtlphy->current_chan_bw == - HT_CHANNEL_WIDTH_20) - chnlgroup++; - else - chnlgroup += 4; - writeval = rtlphy->mcs_offset - [chnlgroup][index + - (rf ? 8 : 0)] + ((index < 2) ? - powerbase0[rf] : - powerbase1[rf]); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeval); - } - break; - case 2: - writeval = ((index < 2) ? powerbase0[rf] : - powerbase1[rf]); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Better regulatory, writeval(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeval); - break; - case 3: - chnlgroup = 0; - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 40MHz rf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', - rtlefuse->pwrgroup_ht40[rf] - [channel - 1]); - } else { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 20MHz rf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', - rtlefuse->pwrgroup_ht20[rf] - [channel - 1]); - } - for (i = 0; i < 4; i++) { - pwr_diff_limit[i] = (u8)((rtlphy->mcs_offset - [chnlgroup][index + (rf ? 8 : 0)] & - (0x7f << (i * 8))) >> (i * 8)); - if (rtlphy->current_chan_bw == - HT_CHANNEL_WIDTH_20_40) { - if (pwr_diff_limit[i] > - rtlefuse->pwrgroup_ht40[rf] - [channel - 1]) - pwr_diff_limit[i] = - rtlefuse->pwrgroup_ht40 - [rf][channel - 1]; - } else { - if (pwr_diff_limit[i] > - rtlefuse->pwrgroup_ht20[rf][ - channel - 1]) - pwr_diff_limit[i] = - rtlefuse->pwrgroup_ht20[rf] - [channel - 1]; - } - } - customer_limit = (pwr_diff_limit[3] << 24) | - (pwr_diff_limit[2] << 16) | - (pwr_diff_limit[1] << 8) | - (pwr_diff_limit[0]); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer's limit rf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', customer_limit); - writeval = customer_limit + ((index < 2) ? - powerbase0[rf] : powerbase1[rf]); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer, writeval rf(%c)= 0x%x\n", - rf == 0 ? 'A' : 'B', writeval); - break; - default: - chnlgroup = 0; - writeval = rtlphy->mcs_offset[chnlgroup][index + - (rf ? 8 : 0)] + ((index < 2) ? - powerbase0[rf] : powerbase1[rf]); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeval rf(%c) = 0x%x\n", - rf == 0 ? 'A' : 'B', writeval); - break; - } - *(p_outwriteval + rf) = writeval; - } -} - -static void _rtl92d_write_ofdm_power_reg(struct ieee80211_hw *hw, - u8 index, u32 *pvalue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - static u16 regoffset_a[6] = { - RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, - RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, - RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 - }; - static u16 regoffset_b[6] = { - RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, - RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, - RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 - }; - u8 i, rf, pwr_val[4]; - u32 writeval; - u16 regoffset; - - for (rf = 0; rf < 2; rf++) { - writeval = pvalue[rf]; - for (i = 0; i < 4; i++) { - pwr_val[i] = (u8) ((writeval & (0x7f << - (i * 8))) >> (i * 8)); - if (pwr_val[i] > RF6052_MAX_TX_PWR) - pwr_val[i] = RF6052_MAX_TX_PWR; - } - writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | - (pwr_val[1] << 8) | pwr_val[0]; - if (rf == 0) - regoffset = regoffset_a[index]; - else - regoffset = regoffset_b[index]; - rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Set 0x%x = %08x\n", regoffset, writeval); - if (((get_rf_type(rtlphy) == RF_2T2R) && - (regoffset == RTXAGC_A_MCS15_MCS12 || - regoffset == RTXAGC_B_MCS15_MCS12)) || - ((get_rf_type(rtlphy) != RF_2T2R) && - (regoffset == RTXAGC_A_MCS07_MCS04 || - regoffset == RTXAGC_B_MCS07_MCS04))) { - writeval = pwr_val[3]; - if (regoffset == RTXAGC_A_MCS15_MCS12 || - regoffset == RTXAGC_A_MCS07_MCS04) - regoffset = 0xc90; - if (regoffset == RTXAGC_B_MCS15_MCS12 || - regoffset == RTXAGC_B_MCS07_MCS04) - regoffset = 0xc98; - for (i = 0; i < 3; i++) { - if (i != 2) - writeval = (writeval > 8) ? - (writeval - 8) : 0; - else - writeval = (writeval > 6) ? - (writeval - 6) : 0; - rtl_write_byte(rtlpriv, (u32) (regoffset + i), - (u8) writeval); - } - } - } -} - -void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel) -{ - u32 writeval[2], powerbase0[2], powerbase1[2]; - u8 index; - - _rtl92d_phy_get_power_base(hw, ppowerlevel, channel, - &powerbase0[0], &powerbase1[0]); - for (index = 0; index < 6; index++) { - _rtl92d_get_txpower_writeval_by_regulatory(hw, - channel, index, &powerbase0[0], - &powerbase1[0], &writeval[0]); - _rtl92d_write_ofdm_power_reg(hw, index, &writeval[0]); - } -} - -bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - u8 u1btmp; - u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3); - u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0; - u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON; - bool bresult = true; /* true: need to enable BB/RF power */ - - rtlhal->during_mac0init_radiob = false; - rtlhal->during_mac1init_radioa = false; - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "===>\n"); - /* MAC0 Need PHY1 load radio_b.txt . Driver use DBI to write. */ - u1btmp = rtl_read_byte(rtlpriv, mac_reg); - if (!(u1btmp & mac_on_bit)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "enable BB & RF\n"); - /* Enable BB and RF power */ - rtl92de_write_dword_dbi(hw, REG_SYS_ISO_CTRL, - rtl92de_read_dword_dbi(hw, REG_SYS_ISO_CTRL, direct) | - BIT(29) | BIT(16) | BIT(17), direct); - } else { - /* We think if MAC1 is ON,then radio_a.txt - * and radio_b.txt has been load. */ - bresult = false; - } - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "<===\n"); - return bresult; - -} - -void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, bool bmac0) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - u8 u1btmp; - u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3); - u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0; - u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON; - - rtlhal->during_mac0init_radiob = false; - rtlhal->during_mac1init_radioa = false; - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "====>\n"); - /* check MAC0 enable or not again now, if - * enabled, not power down radio A. */ - u1btmp = rtl_read_byte(rtlpriv, mac_reg); - if (!(u1btmp & mac_on_bit)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "power down\n"); - /* power down RF radio A according to YuNan's advice. */ - rtl92de_write_dword_dbi(hw, RFPGA0_XA_LSSIPARAMETER, - 0x00000000, direct); - } - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "<====\n"); -} - -bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - bool rtstatus = true; - struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); - u32 u4_regvalue = 0; - u8 rfpath; - struct bb_reg_def *pphyreg; - bool mac1_initradioa_first = false, mac0_initradiob_first = false; - bool need_pwrdown_radioa = false, need_pwrdown_radiob = false; - bool true_bpath = false; - - if (rtlphy->rf_type == RF_1T1R) - rtlphy->num_total_rfpath = 1; - else - rtlphy->num_total_rfpath = 2; - - /* Single phy mode: use radio_a radio_b config path_A path_B */ - /* seperately by MAC0, and MAC1 needn't configure RF; */ - /* Dual PHY mode:MAC0 use radio_a config 1st phy path_A, */ - /* MAC1 use radio_b config 2nd PHY path_A. */ - /* DMDP,MAC0 on G band,MAC1 on A band. */ - if (rtlhal->macphymode == DUALMAC_DUALPHY) { - if (rtlhal->current_bandtype == BAND_ON_2_4G && - rtlhal->interfaceindex == 0) { - /* MAC0 needs PHY1 load radio_b.txt. - * Driver use DBI to write. */ - if (rtl92d_phy_enable_anotherphy(hw, true)) { - rtlphy->num_total_rfpath = 2; - mac0_initradiob_first = true; - } else { - /* We think if MAC1 is ON,then radio_a.txt and - * radio_b.txt has been load. */ - return rtstatus; - } - } else if (rtlhal->current_bandtype == BAND_ON_5G && - rtlhal->interfaceindex == 1) { - /* MAC1 needs PHY0 load radio_a.txt. - * Driver use DBI to write. */ - if (rtl92d_phy_enable_anotherphy(hw, false)) { - rtlphy->num_total_rfpath = 2; - mac1_initradioa_first = true; - } else { - /* We think if MAC0 is ON,then radio_a.txt and - * radio_b.txt has been load. */ - return rtstatus; - } - } else if (rtlhal->interfaceindex == 1) { - /* MAC0 enabled, only init radia B. */ - true_bpath = true; - } - } - - for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { - /* Mac1 use PHY0 write */ - if (mac1_initradioa_first) { - if (rfpath == RF90_PATH_A) { - rtlhal->during_mac1init_radioa = true; - need_pwrdown_radioa = true; - } else if (rfpath == RF90_PATH_B) { - rtlhal->during_mac1init_radioa = false; - mac1_initradioa_first = false; - rfpath = RF90_PATH_A; - true_bpath = true; - rtlphy->num_total_rfpath = 1; - } - } else if (mac0_initradiob_first) { - /* Mac0 use PHY1 write */ - if (rfpath == RF90_PATH_A) - rtlhal->during_mac0init_radiob = false; - if (rfpath == RF90_PATH_B) { - rtlhal->during_mac0init_radiob = true; - mac0_initradiob_first = false; - need_pwrdown_radiob = true; - rfpath = RF90_PATH_A; - true_bpath = true; - rtlphy->num_total_rfpath = 1; - } - } - pphyreg = &rtlphy->phyreg_def[rfpath]; - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV); - break; - case RF90_PATH_B: - case RF90_PATH_D: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16); - break; - } - rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); - udelay(1); - rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); - udelay(1); - /* Set bit number of Address and Data for RF register */ - /* Set 1 to 4 bits for 8255 */ - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, - B3WIREADDRESSLENGTH, 0x0); - udelay(1); - /* Set 0 to 12 bits for 8255 */ - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); - udelay(1); - switch (rfpath) { - case RF90_PATH_A: - if (true_bpath) - rtstatus = rtl92d_phy_config_rf_with_headerfile( - hw, radiob_txt, - (enum radio_path)rfpath); - else - rtstatus = rtl92d_phy_config_rf_with_headerfile( - hw, radioa_txt, - (enum radio_path)rfpath); - break; - case RF90_PATH_B: - rtstatus = - rtl92d_phy_config_rf_with_headerfile(hw, radiob_txt, - (enum radio_path) rfpath); - break; - case RF90_PATH_C: - break; - case RF90_PATH_D: - break; - } - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, - u4_regvalue); - break; - case RF90_PATH_B: - case RF90_PATH_D: - rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16, - u4_regvalue); - break; - } - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio[%d] Fail!!", rfpath); - goto phy_rf_cfg_fail; - } - - } - - /* check MAC0 enable or not again, if enabled, - * not power down radio A. */ - /* check MAC1 enable or not again, if enabled, - * not power down radio B. */ - if (need_pwrdown_radioa) - rtl92d_phy_powerdown_anotherphy(hw, false); - else if (need_pwrdown_radiob) - rtl92d_phy_powerdown_anotherphy(hw, true); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n"); - return rtstatus; - -phy_rf_cfg_fail: - return rtstatus; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h deleted file mode 100644 index 7303d12c266f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92D_RF_H__ -#define __RTL92D_RF_H__ - -void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth); -void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); -bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw); -bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0); -void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, bool bmac0); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c deleted file mode 100644 index b19d0398215f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ /dev/null @@ -1,419 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../core.h" -#include "../pci.h" -#include "../base.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "hw.h" -#include "sw.h" -#include "trx.h" -#include "led.h" - -#include - -static void rtl92d_init_aspm_vars(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - /*close ASPM for AMD defaultly */ - rtlpci->const_amdpci_aspm = 0; - - /* - * ASPM PS mode. - * 0 - Disable ASPM, - * 1 - Enable ASPM without Clock Req, - * 2 - Enable ASPM with Clock Req, - * 3 - Alwyas Enable ASPM with Clock Req, - * 4 - Always Enable ASPM without Clock Req. - * set defult to RTL8192CE:3 RTL8192E:2 - * */ - rtlpci->const_pci_aspm = 3; - - /*Setting for PCI-E device */ - rtlpci->const_devicepci_aspm_setting = 0x03; - - /*Setting for PCI-E bridge */ - rtlpci->const_hostpci_aspm_setting = 0x02; - - /* - * In Hw/Sw Radio Off situation. - * 0 - Default, - * 1 - From ASPM setting without low Mac Pwr, - * 2 - From ASPM setting with low Mac Pwr, - * 3 - Bus D3 - * set default to RTL8192CE:0 RTL8192SE:2 - */ - rtlpci->const_hwsw_rfoff_d3 = 0; - - /* - * This setting works for those device with - * backdoor ASPM setting such as EPHY setting. - * 0 - Not support ASPM, - * 1 - Support ASPM, - * 2 - According to chipset. - */ - rtlpci->const_support_pciaspm = 1; -} - -static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) -{ - int err; - u8 tid; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtlpriv->dm.dm_initialgain_enable = true; - rtlpriv->dm.dm_flag = 0; - rtlpriv->dm.disable_framebursting = false; - rtlpriv->dm.thermalvalue = 0; - rtlpriv->dm.useramask = true; - - /* dual mac */ - if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) - rtlpriv->phy.current_channel = 36; - else - rtlpriv->phy.current_channel = 1; - - if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) { - rtlpriv->rtlhal.disable_amsdu_8k = true; - /* No long RX - reduce fragmentation */ - rtlpci->rxbuffersize = 4096; - } - - rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13); - - rtlpci->receive_config = ( - RCR_APPFCS - | RCR_AMF - | RCR_ADF - | RCR_APP_MIC - | RCR_APP_ICV - | RCR_AICV - | RCR_ACRC32 - | RCR_AB - | RCR_AM - | RCR_APM - | RCR_APP_PHYST_RXFF - | RCR_HTC_LOC_CTRL - ); - - rtlpci->irq_mask[0] = (u32) ( - IMR_ROK - | IMR_VODOK - | IMR_VIDOK - | IMR_BEDOK - | IMR_BKDOK - | IMR_MGNTDOK - | IMR_HIGHDOK - | IMR_BDOK - | IMR_RDU - | IMR_RXFOVW - ); - - 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; - rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; - if (!rtlpriv->psc.inactiveps) - pr_info("Power Save off (module option)\n"); - if (!rtlpriv->psc.fwctrl_lps) - pr_info("FW Power Save off (module option)\n"); - rtlpriv->psc.reg_fwctrl_lps = 3; - rtlpriv->psc.reg_max_lps_awakeintvl = 5; - /* for ASPM, you can close aspm through - * set const_support_pciaspm = 0 */ - rtl92d_init_aspm_vars(hw); - - if (rtlpriv->psc.reg_fwctrl_lps == 1) - rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 2) - rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 3) - rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; - - /* for early mode */ - rtlpriv->rtlhal.earlymode_enable = false; - for (tid = 0; tid < 8; tid++) - skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); - - /* for firmware buf */ - rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); - if (!rtlpriv->rtlhal.pfirmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't alloc buffer for fw\n"); - return 1; - } - - rtlpriv->max_fw_size = 0x8000; - pr_info("Driver for Realtek RTL8192DE WLAN interface\n"); - pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); - - /* request fw */ - err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, - rtlpriv->io.dev, GFP_KERNEL, hw, - rtl_fw_cb); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to request firmware!\n"); - return 1; - } - - return 0; -} - -static void rtl92d_deinit_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tid; - - if (rtlpriv->rtlhal.pfirmware) { - vfree(rtlpriv->rtlhal.pfirmware); - rtlpriv->rtlhal.pfirmware = NULL; - } - for (tid = 0; tid < 8; tid++) - skb_queue_purge(&rtlpriv->mac80211.skb_waitq[tid]); -} - -static struct rtl_hal_ops rtl8192de_hal_ops = { - .init_sw_vars = rtl92d_init_sw_vars, - .deinit_sw_vars = rtl92d_deinit_sw_vars, - .read_eeprom_info = rtl92de_read_eeprom_info, - .interrupt_recognized = rtl92de_interrupt_recognized, - .hw_init = rtl92de_hw_init, - .hw_disable = rtl92de_card_disable, - .hw_suspend = rtl92de_suspend, - .hw_resume = rtl92de_resume, - .enable_interrupt = rtl92de_enable_interrupt, - .disable_interrupt = rtl92de_disable_interrupt, - .set_network_type = rtl92de_set_network_type, - .set_chk_bssid = rtl92de_set_check_bssid, - .set_qos = rtl92de_set_qos, - .set_bcn_reg = rtl92de_set_beacon_related_registers, - .set_bcn_intv = rtl92de_set_beacon_interval, - .update_interrupt_mask = rtl92de_update_interrupt_mask, - .get_hw_reg = rtl92de_get_hw_reg, - .set_hw_reg = rtl92de_set_hw_reg, - .update_rate_tbl = rtl92de_update_hal_rate_tbl, - .fill_tx_desc = rtl92de_tx_fill_desc, - .fill_tx_cmddesc = rtl92de_tx_fill_cmddesc, - .query_rx_desc = rtl92de_rx_query_desc, - .set_channel_access = rtl92de_update_channel_access_setting, - .radio_onoff_checking = rtl92de_gpio_radio_on_off_checking, - .set_bw_mode = rtl92d_phy_set_bw_mode, - .switch_channel = rtl92d_phy_sw_chnl, - .dm_watchdog = rtl92d_dm_watchdog, - .scan_operation_backup = rtl_phy_scan_operation_backup, - .set_rf_power_state = rtl92d_phy_set_rf_power_state, - .led_control = rtl92de_led_control, - .set_desc = rtl92de_set_desc, - .get_desc = rtl92de_get_desc, - .tx_polling = rtl92de_tx_polling, - .enable_hw_sec = rtl92de_enable_hw_security_config, - .set_key = rtl92de_set_key, - .init_sw_leds = rtl92de_init_sw_leds, - .get_bbreg = rtl92d_phy_query_bb_reg, - .set_bbreg = rtl92d_phy_set_bb_reg, - .get_rfreg = rtl92d_phy_query_rf_reg, - .set_rfreg = rtl92d_phy_set_rf_reg, - .linked_set_reg = rtl92d_linked_set_reg, - .get_btc_status = rtl_btc_status_false, -}; - -static struct rtl_mod_params rtl92de_mod_params = { - .sw_crypto = false, - .inactiveps = true, - .swctrl_lps = true, - .fwctrl_lps = false, - .debug = DBG_EMERG, -}; - -static struct rtl_hal_cfg rtl92de_hal_cfg = { - .bar_id = 2, - .write_readback = true, - .name = "rtl8192de", - .fw_name = "rtlwifi/rtl8192defw.bin", - .ops = &rtl8192de_hal_ops, - .mod_params = &rtl92de_mod_params, - - .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, - .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, - .maps[SYS_CLK] = REG_SYS_CLKR, - .maps[MAC_RCR_AM] = RCR_AM, - .maps[MAC_RCR_AB] = RCR_AB, - .maps[MAC_RCR_ACRC32] = RCR_ACRC32, - .maps[MAC_RCR_ACF] = RCR_ACF, - .maps[MAC_RCR_AAP] = RCR_AAP, - - .maps[EFUSE_TEST] = REG_EFUSE_TEST, - .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_CLK] = 0, /* just for 92se */ - .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_PWC_EV12V] = PWC_EV12V, - .maps[EFUSE_FEN_ELDR] = FEN_ELDR, - .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, - .maps[EFUSE_ANA8M] = 0, /* just for 92se */ - .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, - .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, - .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, - - .maps[RWCAM] = REG_CAMCMD, - .maps[WCAMI] = REG_CAMWRITE, - .maps[RCAMO] = REG_CAMREAD, - .maps[CAMDBG] = REG_CAMDBG, - .maps[SECR] = REG_SECCFG, - .maps[SEC_CAM_NONE] = CAM_NONE, - .maps[SEC_CAM_WEP40] = CAM_WEP40, - .maps[SEC_CAM_TKIP] = CAM_TKIP, - .maps[SEC_CAM_AES] = CAM_AES, - .maps[SEC_CAM_WEP104] = CAM_WEP104, - - .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, - .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, - .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, - .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, - .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, - .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, - .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, - .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, - .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, - .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, - .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, - .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, - .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, - .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, - .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, - .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, - - .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, - .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, - .maps[RTL_IMR_BCNINT] = IMR_BCNINT, - .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, - .maps[RTL_IMR_RDU] = IMR_RDU, - .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, - .maps[RTL_IMR_BDOK] = IMR_BDOK, - .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, - .maps[RTL_IMR_TBDER] = IMR_TBDER, - .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, - .maps[RTL_IMR_TBDOK] = IMR_TBDOK, - .maps[RTL_IMR_BKDOK] = IMR_BKDOK, - .maps[RTL_IMR_BEDOK] = IMR_BEDOK, - .maps[RTL_IMR_VIDOK] = IMR_VIDOK, - .maps[RTL_IMR_VODOK] = IMR_VODOK, - .maps[RTL_IMR_ROK] = IMR_ROK, - .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), - - .maps[RTL_RC_CCK_RATE1M] = DESC_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC_RATEMCS15, -}; - -static struct pci_device_id rtl92de_pci_ids[] = { - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8193, rtl92de_hal_cfg)}, - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x002B, rtl92de_hal_cfg)}, - {}, -}; - -MODULE_DEVICE_TABLE(pci, rtl92de_pci_ids); - -MODULE_AUTHOR("lizhaoming "); -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_AUTHOR("Larry Finger "); -MODULE_LICENSE("GPL"); -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(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_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)"); - -static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); - -static struct pci_driver rtl92de_driver = { - .name = KBUILD_MODNAME, - .id_table = rtl92de_pci_ids, - .probe = rtl_pci_probe, - .remove = rtl_pci_disconnect, - .driver.pm = &rtlwifi_pm_ops, -}; - -/* add global spin lock to solve the problem that - * Dul mac register operation on the same time */ -spinlock_t globalmutex_power; -spinlock_t globalmutex_for_fwdownload; -spinlock_t globalmutex_for_power_and_efuse; - -static int __init rtl92de_module_init(void) -{ - int ret = 0; - - spin_lock_init(&globalmutex_power); - spin_lock_init(&globalmutex_for_fwdownload); - spin_lock_init(&globalmutex_for_power_and_efuse); - - ret = pci_register_driver(&rtl92de_driver); - if (ret) - RT_ASSERT(false, "No device found\n"); - return ret; -} - -static void __exit rtl92de_module_exit(void) -{ - pci_unregister_driver(&rtl92de_driver); -} - -module_init(rtl92de_module_init); -module_exit(rtl92de_module_exit); diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.h b/drivers/net/wireless/rtlwifi/rtl8192de/sw.h deleted file mode 100644 index 0e6035b8fd86..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.h +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92DE_SW_H__ -#define __RTL92DE_SW_H__ - -extern spinlock_t globalmutex_power; -extern spinlock_t globalmutex_for_fwdownload; -extern spinlock_t globalmutex_for_power_and_efuse; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.c b/drivers/net/wireless/rtlwifi/rtl8192de/table.c deleted file mode 100644 index 8ea6f528dfa6..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/table.c +++ /dev/null @@ -1,1690 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - * Created on 2010/12/23, 6:38 - *****************************************************************************/ - -#include - -#include "table.h" - -u32 rtl8192de_phy_reg_2tarray[PHY_REG_2T_ARRAYLENGTH] = { - 0x024, 0x0011800d, - 0x028, 0x00ffdb83, - 0x014, 0x088ba955, - 0x010, 0x49022b03, - 0x800, 0x80040002, - 0x804, 0x00000003, - 0x808, 0x0000fc00, - 0x80c, 0x0000000a, - 0x810, 0x80706388, - 0x814, 0x020c3d10, - 0x818, 0x02200385, - 0x81c, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390004, - 0x828, 0x01000100, - 0x82c, 0x00390004, - 0x830, 0x27272727, - 0x834, 0x27272727, - 0x838, 0x27272727, - 0x83c, 0x27272727, - 0x840, 0x00010000, - 0x844, 0x00010000, - 0x848, 0x27272727, - 0x84c, 0x27272727, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x569a569a, - 0x85c, 0x0c1b25a4, - 0x860, 0x66e60230, - 0x864, 0x061f0130, - 0x868, 0x27272727, - 0x86c, 0x272b2b2b, - 0x870, 0x07000700, - 0x874, 0x22188000, - 0x878, 0x08080808, - 0x87c, 0x00007ff8, - 0x880, 0xc0083070, - 0x884, 0x00000cd5, - 0x888, 0x00000000, - 0x88c, 0xcc0000c0, - 0x890, 0x00000800, - 0x894, 0xfffffffe, - 0x898, 0x40302010, - 0x89c, 0x00706050, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90c, 0x81121313, - 0xa00, 0x00d047c8, - 0xa04, 0x80ff000c, - 0xa08, 0x8c838300, - 0xa0c, 0x2e68120f, - 0xa10, 0x9500bb78, - 0xa14, 0x11144028, - 0xa18, 0x00881117, - 0xa1c, 0x89140f00, - 0xa20, 0x1a1b0000, - 0xa24, 0x090e1317, - 0xa28, 0x00000204, - 0xa2c, 0x00d30000, - 0xa70, 0x101fbf00, - 0xa74, 0x00000007, - 0xc00, 0x40071d40, - 0xc04, 0x03a05633, - 0xc08, 0x001000e4, - 0xc0c, 0x6c6c6c6c, - 0xc10, 0x08800000, - 0xc14, 0x40000100, - 0xc18, 0x08800000, - 0xc1c, 0x40000100, - 0xc20, 0x00000000, - 0xc24, 0x00000000, - 0xc28, 0x00000000, - 0xc2c, 0x00000000, - 0xc30, 0x69e9ac44, - 0xc34, 0x469652cf, - 0xc38, 0x49795994, - 0xc3c, 0x0a979718, - 0xc40, 0x1f7c403f, - 0xc44, 0x000100b7, - 0xc48, 0xec020107, - 0xc4c, 0x007f037f, - 0xc50, 0x69543420, - 0xc54, 0x43bc009e, - 0xc58, 0x69543420, - 0xc5c, 0x433c00a8, - 0xc60, 0x00000000, - 0xc64, 0x5116848b, - 0xc68, 0x47c00bff, - 0xc6c, 0x00000036, - 0xc70, 0x2c7f000d, - 0xc74, 0x058610db, - 0xc78, 0x0000001f, - 0xc7c, 0x40b95612, - 0xc80, 0x40000100, - 0xc84, 0x20f60000, - 0xc88, 0x40000100, - 0xc8c, 0x20e00000, - 0xc90, 0x00121820, - 0xc94, 0x00000007, - 0xc98, 0x00121820, - 0xc9c, 0x00007f7f, - 0xca0, 0x00000000, - 0xca4, 0x00000080, - 0xca8, 0x00000000, - 0xcac, 0x00000000, - 0xcb0, 0x00000000, - 0xcb4, 0x00000000, - 0xcb8, 0x00000000, - 0xcbc, 0x28000000, - 0xcc0, 0x00000000, - 0xcc4, 0x00000000, - 0xcc8, 0x00000000, - 0xccc, 0x00000000, - 0xcd0, 0x00000000, - 0xcd4, 0x00000000, - 0xcd8, 0x64b11e20, - 0xcdc, 0xe8767533, - 0xce0, 0x00222222, - 0xce4, 0x00000000, - 0xce8, 0x37644302, - 0xcec, 0x2f97d40c, - 0xd00, 0x00080740, - 0xd04, 0x00020403, - 0xd08, 0x0000907f, - 0xd0c, 0x20010201, - 0xd10, 0xa0633333, - 0xd14, 0x3333bc43, - 0xd18, 0x7a8f5b6b, - 0xd2c, 0xcc979975, - 0xd30, 0x00000000, - 0xd34, 0x80608404, - 0xd38, 0x00000000, - 0xd3c, 0x00027293, - 0xd40, 0x00000000, - 0xd44, 0x00000000, - 0xd48, 0x00000000, - 0xd4c, 0x00000000, - 0xd50, 0x6437140a, - 0xd54, 0x00000000, - 0xd58, 0x00000000, - 0xd5c, 0x30032064, - 0xd60, 0x4653de68, - 0xd64, 0x04518a3c, - 0xd68, 0x00002101, - 0xd6c, 0x2a201c16, - 0xd70, 0x1812362e, - 0xd74, 0x322c2220, - 0xd78, 0x000e3c24, - 0xe00, 0x2a2a2a2a, - 0xe04, 0x2a2a2a2a, - 0xe08, 0x03902a2a, - 0xe10, 0x2a2a2a2a, - 0xe14, 0x2a2a2a2a, - 0xe18, 0x2a2a2a2a, - 0xe1c, 0x2a2a2a2a, - 0xe28, 0x00000000, - 0xe30, 0x1000dc1f, - 0xe34, 0x10008c1f, - 0xe38, 0x02140102, - 0xe3c, 0x681604c2, - 0xe40, 0x01007c00, - 0xe44, 0x01004800, - 0xe48, 0xfb000000, - 0xe4c, 0x000028d1, - 0xe50, 0x1000dc1f, - 0xe54, 0x10008c1f, - 0xe58, 0x02140102, - 0xe5c, 0x28160d05, - 0xe60, 0x00000010, - 0xe68, 0x001b25a4, - 0xe6c, 0x63db25a4, - 0xe70, 0x63db25a4, - 0xe74, 0x0c126da4, - 0xe78, 0x0c126da4, - 0xe7c, 0x0c126da4, - 0xe80, 0x0c126da4, - 0xe84, 0x63db25a4, - 0xe88, 0x0c126da4, - 0xe8c, 0x63db25a4, - 0xed0, 0x63db25a4, - 0xed4, 0x63db25a4, - 0xed8, 0x63db25a4, - 0xedc, 0x001b25a4, - 0xee0, 0x001b25a4, - 0xeec, 0x6fdb25a4, - 0xf14, 0x00000003, - 0xf1c, 0x00000064, - 0xf4c, 0x00000004, - 0xf00, 0x00000300, -}; - -u32 rtl8192de_phy_reg_array_pg[PHY_REG_ARRAY_PG_LENGTH] = { - 0xe00, 0xffffffff, 0x07090c0c, - 0xe04, 0xffffffff, 0x01020405, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x0b0c0c0e, - 0xe14, 0xffffffff, 0x01030506, - 0xe18, 0xffffffff, 0x0b0c0d0e, - 0xe1c, 0xffffffff, 0x01030509, - 0x830, 0xffffffff, 0x07090c0c, - 0x834, 0xffffffff, 0x01020405, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x0b0c0c0e, - 0x848, 0xffffffff, 0x01030506, - 0x84c, 0xffffffff, 0x0b0c0d0e, - 0x868, 0xffffffff, 0x01030509, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x06060606, - 0xe14, 0xffffffff, 0x00020406, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x06060606, - 0x848, 0xffffffff, 0x00020406, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x08080808, - 0xe14, 0xffffffff, 0x00040408, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x08080808, - 0x848, 0xffffffff, 0x00040408, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x08080808, - 0xe14, 0xffffffff, 0x00040408, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x08080808, - 0x848, 0xffffffff, 0x00040408, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x08080808, - 0xe14, 0xffffffff, 0x00040408, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x08080808, - 0x848, 0xffffffff, 0x00040408, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x08080808, - 0xe14, 0xffffffff, 0x00040408, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x08080808, - 0x848, 0xffffffff, 0x00040408, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x08080808, - 0xe14, 0xffffffff, 0x00040408, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x08080808, - 0x848, 0xffffffff, 0x00040408, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x08080808, - 0xe14, 0xffffffff, 0x00040408, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x08080808, - 0x848, 0xffffffff, 0x00040408, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, -}; - -u32 rtl8192de_radioa_2tarray[RADIOA_2T_ARRAYLENGTH] = { - 0x000, 0x00030000, - 0x001, 0x00030000, - 0x002, 0x00000000, - 0x003, 0x00018c63, - 0x004, 0x00018c63, - 0x008, 0x00084000, - 0x00b, 0x0001c000, - 0x00e, 0x00018c67, - 0x00f, 0x00000851, - 0x014, 0x00021440, - 0x018, 0x00017524, - 0x019, 0x00000000, - 0x01d, 0x000a1290, - 0x023, 0x00001558, - 0x01a, 0x00030a99, - 0x01b, 0x00040b00, - 0x01c, 0x000fc339, - 0x03a, 0x000a57eb, - 0x03b, 0x00020000, - 0x03c, 0x000ff454, - 0x020, 0x0000aa52, - 0x021, 0x00054000, - 0x040, 0x0000aa52, - 0x041, 0x00014000, - 0x025, 0x000803be, - 0x026, 0x000fc638, - 0x027, 0x00077c18, - 0x028, 0x000de471, - 0x029, 0x000d7110, - 0x02a, 0x0008cb04, - 0x02b, 0x0004128b, - 0x02c, 0x00001840, - 0x043, 0x0002444f, - 0x044, 0x0001adb0, - 0x045, 0x00056467, - 0x046, 0x0008992c, - 0x047, 0x0000452c, - 0x048, 0x000f9c43, - 0x049, 0x00002e0c, - 0x04a, 0x000546eb, - 0x04b, 0x0008966c, - 0x04c, 0x0000dde9, - 0x018, 0x00007401, - 0x000, 0x00070000, - 0x012, 0x000dc000, - 0x012, 0x00090000, - 0x012, 0x00051000, - 0x012, 0x00012000, - 0x013, 0x000287b7, - 0x013, 0x000247ab, - 0x013, 0x0002079f, - 0x013, 0x0001c793, - 0x013, 0x0001839b, - 0x013, 0x00014392, - 0x013, 0x0001019a, - 0x013, 0x0000c191, - 0x013, 0x00008194, - 0x013, 0x000040a0, - 0x013, 0x00000018, - 0x015, 0x0000f424, - 0x015, 0x0004f424, - 0x015, 0x0008f424, - 0x016, 0x000e1330, - 0x016, 0x000a1330, - 0x016, 0x00061330, - 0x016, 0x00021330, - 0x018, 0x00017524, - 0x000, 0x00070000, - 0x012, 0x000cf000, - 0x012, 0x000bc000, - 0x012, 0x00078000, - 0x012, 0x00000000, - 0x013, 0x000287bc, - 0x013, 0x000247b0, - 0x013, 0x000203b4, - 0x013, 0x0001c3a8, - 0x013, 0x000181b4, - 0x013, 0x000141a8, - 0x013, 0x000100b0, - 0x013, 0x0000c0a4, - 0x013, 0x0000b02c, - 0x013, 0x00004020, - 0x013, 0x00000014, - 0x015, 0x0000f4c3, - 0x015, 0x0004f4c3, - 0x015, 0x0008f4c3, - 0x016, 0x000e085f, - 0x016, 0x000a085f, - 0x016, 0x0006085f, - 0x016, 0x0002085f, - 0x018, 0x00037524, - 0x000, 0x00070000, - 0x012, 0x000cf000, - 0x012, 0x000bc000, - 0x012, 0x00078000, - 0x012, 0x00000000, - 0x013, 0x000287bc, - 0x013, 0x000247b0, - 0x013, 0x000203b4, - 0x013, 0x0001c3a8, - 0x013, 0x000181b4, - 0x013, 0x000141a8, - 0x013, 0x000100b0, - 0x013, 0x0000c0a4, - 0x013, 0x0000b02c, - 0x013, 0x00004020, - 0x013, 0x00000014, - 0x015, 0x0000f4c3, - 0x015, 0x0004f4c3, - 0x015, 0x0008f4c3, - 0x016, 0x000e085f, - 0x016, 0x000a085f, - 0x016, 0x0006085f, - 0x016, 0x0002085f, - 0x018, 0x00057568, - 0x000, 0x00070000, - 0x012, 0x000cf000, - 0x012, 0x000bc000, - 0x012, 0x00078000, - 0x012, 0x00000000, - 0x013, 0x000287bc, - 0x013, 0x000247b0, - 0x013, 0x000203b4, - 0x013, 0x0001c3a8, - 0x013, 0x000181b4, - 0x013, 0x000141a8, - 0x013, 0x000100b0, - 0x013, 0x0000c0a4, - 0x013, 0x0000b02c, - 0x013, 0x00004020, - 0x013, 0x00000014, - 0x015, 0x0000f4c3, - 0x015, 0x0004f4c3, - 0x015, 0x0008f4c3, - 0x016, 0x000e085f, - 0x016, 0x000a085f, - 0x016, 0x0006085f, - 0x016, 0x0002085f, - 0x030, 0x0004470f, - 0x031, 0x00044ff0, - 0x032, 0x00000070, - 0x033, 0x000dd480, - 0x034, 0x000ffac0, - 0x035, 0x000b80c0, - 0x036, 0x00077000, - 0x037, 0x00064ff2, - 0x038, 0x000e7661, - 0x039, 0x00000e90, - 0x000, 0x00030000, - 0x018, 0x0000f401, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01e, 0x00088009, - 0x01f, 0x00080003, - 0x0fe, 0x00000000, - 0x01e, 0x00088001, - 0x01f, 0x00080000, - 0x0fe, 0x00000000, - 0x018, 0x00097524, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x02b, 0x00041289, - 0x0fe, 0x00000000, - 0x02d, 0x0006aaaa, - 0x02e, 0x000b4d01, - 0x02d, 0x00080000, - 0x02e, 0x00004d02, - 0x02d, 0x00095555, - 0x02e, 0x00054d03, - 0x02d, 0x000aaaaa, - 0x02e, 0x000b4d04, - 0x02d, 0x000c0000, - 0x02e, 0x00004d05, - 0x02d, 0x000d5555, - 0x02e, 0x00054d06, - 0x02d, 0x000eaaaa, - 0x02e, 0x000b4d07, - 0x02d, 0x00000000, - 0x02e, 0x00005108, - 0x02d, 0x00015555, - 0x02e, 0x00055109, - 0x02d, 0x0002aaaa, - 0x02e, 0x000b510a, - 0x02d, 0x00040000, - 0x02e, 0x0000510b, - 0x02d, 0x00055555, - 0x02e, 0x0005510c, -}; - -u32 rtl8192de_radiob_2tarray[RADIOB_2T_ARRAYLENGTH] = { - 0x000, 0x00030000, - 0x001, 0x00030000, - 0x002, 0x00000000, - 0x003, 0x00018c63, - 0x004, 0x00018c63, - 0x008, 0x00084000, - 0x00b, 0x0001c000, - 0x00e, 0x00018c67, - 0x00f, 0x00000851, - 0x014, 0x00021440, - 0x018, 0x00007401, - 0x019, 0x00000060, - 0x01d, 0x000a1290, - 0x023, 0x00001558, - 0x01a, 0x00030a99, - 0x01b, 0x00040b00, - 0x01c, 0x000fc339, - 0x03a, 0x000a57eb, - 0x03b, 0x00020000, - 0x03c, 0x000ff454, - 0x020, 0x0000aa52, - 0x021, 0x00054000, - 0x040, 0x0000aa52, - 0x041, 0x00014000, - 0x025, 0x000803be, - 0x026, 0x000fc638, - 0x027, 0x00077c18, - 0x028, 0x000d1c31, - 0x029, 0x000d7110, - 0x02a, 0x000aeb04, - 0x02b, 0x0004128b, - 0x02c, 0x00001840, - 0x043, 0x0002444f, - 0x044, 0x0001adb0, - 0x045, 0x00056467, - 0x046, 0x0008992c, - 0x047, 0x0000452c, - 0x048, 0x000f9c43, - 0x049, 0x00002e0c, - 0x04a, 0x000546eb, - 0x04b, 0x0008966c, - 0x04c, 0x0000dde9, - 0x018, 0x00007401, - 0x000, 0x00070000, - 0x012, 0x000dc000, - 0x012, 0x00090000, - 0x012, 0x00051000, - 0x012, 0x00012000, - 0x013, 0x000287b7, - 0x013, 0x000247ab, - 0x013, 0x0002079f, - 0x013, 0x0001c793, - 0x013, 0x0001839b, - 0x013, 0x00014392, - 0x013, 0x0001019a, - 0x013, 0x0000c191, - 0x013, 0x00008194, - 0x013, 0x000040a0, - 0x013, 0x00000018, - 0x015, 0x0000f424, - 0x015, 0x0004f424, - 0x015, 0x0008f424, - 0x016, 0x000e1330, - 0x016, 0x000a1330, - 0x016, 0x00061330, - 0x016, 0x00021330, - 0x018, 0x00017524, - 0x000, 0x00070000, - 0x012, 0x000cf000, - 0x012, 0x000bc000, - 0x012, 0x00078000, - 0x012, 0x00000000, - 0x013, 0x000287bc, - 0x013, 0x000247b0, - 0x013, 0x000203b4, - 0x013, 0x0001c3a8, - 0x013, 0x000181b4, - 0x013, 0x000141a8, - 0x013, 0x000100b0, - 0x013, 0x0000c0a4, - 0x013, 0x0000b02c, - 0x013, 0x00004020, - 0x013, 0x00000014, - 0x015, 0x0000f4c3, - 0x015, 0x0004f4c3, - 0x015, 0x0008f4c3, - 0x016, 0x000e085f, - 0x016, 0x000a085f, - 0x016, 0x0006085f, - 0x016, 0x0002085f, - 0x018, 0x00037524, - 0x000, 0x00070000, - 0x012, 0x000cf000, - 0x012, 0x000bc000, - 0x012, 0x00078000, - 0x012, 0x00000000, - 0x013, 0x000287bc, - 0x013, 0x000247b0, - 0x013, 0x000203b4, - 0x013, 0x0001c3a8, - 0x013, 0x000181b4, - 0x013, 0x000141a8, - 0x013, 0x000100b0, - 0x013, 0x0000c0a4, - 0x013, 0x0000b02c, - 0x013, 0x00004020, - 0x013, 0x00000014, - 0x015, 0x0000f4c3, - 0x015, 0x0004f4c3, - 0x015, 0x0008f4c3, - 0x016, 0x000e085f, - 0x016, 0x000a085f, - 0x016, 0x0006085f, - 0x016, 0x0002085f, - 0x018, 0x00057524, - 0x000, 0x00070000, - 0x012, 0x000cf000, - 0x012, 0x000bc000, - 0x012, 0x00078000, - 0x012, 0x00000000, - 0x013, 0x000287bc, - 0x013, 0x000247b0, - 0x013, 0x000203b4, - 0x013, 0x0001c3a8, - 0x013, 0x000181b4, - 0x013, 0x000141a8, - 0x013, 0x000100b0, - 0x013, 0x0000c0a4, - 0x013, 0x0000b02c, - 0x013, 0x00004020, - 0x013, 0x00000014, - 0x015, 0x0000f4c3, - 0x015, 0x0004f4c3, - 0x015, 0x0008f4c3, - 0x016, 0x000e085f, - 0x016, 0x000a085f, - 0x016, 0x0006085f, - 0x016, 0x0002085f, - 0x030, 0x0004470f, - 0x031, 0x00044ff0, - 0x032, 0x00000070, - 0x033, 0x000dd480, - 0x034, 0x000ffac0, - 0x035, 0x000b80c0, - 0x036, 0x00077000, - 0x037, 0x00064ff2, - 0x038, 0x000e7661, - 0x039, 0x00000e90, - 0x000, 0x00030000, - 0x018, 0x0000f401, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01e, 0x00088009, - 0x01f, 0x00080003, - 0x0fe, 0x00000000, - 0x01e, 0x00088001, - 0x01f, 0x00080000, - 0x0fe, 0x00000000, - 0x018, 0x00087401, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x02b, 0x00041289, - 0x0fe, 0x00000000, - 0x02d, 0x00066666, - 0x02e, 0x00064001, - 0x02d, 0x00091111, - 0x02e, 0x00014002, - 0x02d, 0x000bbbbb, - 0x02e, 0x000b4003, - 0x02d, 0x000e6666, - 0x02e, 0x00064004, - 0x02d, 0x00088888, - 0x02e, 0x00084005, - 0x02d, 0x0009dddd, - 0x02e, 0x000d4006, - 0x02d, 0x000b3333, - 0x02e, 0x00034007, - 0x02d, 0x00048888, - 0x02e, 0x00084408, - 0x02d, 0x000bbbbb, - 0x02e, 0x000b4409, - 0x02d, 0x000e6666, - 0x02e, 0x0006440a, - 0x02d, 0x00011111, - 0x02e, 0x0001480b, - 0x02d, 0x0003bbbb, - 0x02e, 0x000b480c, - 0x02d, 0x00066666, - 0x02e, 0x0006480d, - 0x02d, 0x000ccccc, - 0x02e, 0x000c480e, -}; - -u32 rtl8192de_radioa_2t_int_paarray[RADIOA_2T_INT_PA_ARRAYLENGTH] = { - 0x000, 0x00030000, - 0x001, 0x00030000, - 0x002, 0x00000000, - 0x003, 0x00018c63, - 0x004, 0x00018c63, - 0x008, 0x00084000, - 0x00b, 0x0001c000, - 0x00e, 0x00018c67, - 0x00f, 0x00000851, - 0x014, 0x00021440, - 0x018, 0x00017524, - 0x019, 0x00000000, - 0x01d, 0x000a1290, - 0x023, 0x00001558, - 0x01a, 0x00030a99, - 0x01b, 0x00040b00, - 0x01c, 0x000fc339, - 0x03a, 0x000a57eb, - 0x03b, 0x00020000, - 0x03c, 0x000ff454, - 0x020, 0x0000aa52, - 0x021, 0x00054000, - 0x040, 0x0000aa52, - 0x041, 0x00014000, - 0x025, 0x000803be, - 0x026, 0x000fc638, - 0x027, 0x00077c18, - 0x028, 0x000de471, - 0x029, 0x000d7110, - 0x02a, 0x0008eb04, - 0x02b, 0x0004128b, - 0x02c, 0x00001840, - 0x043, 0x0002444f, - 0x044, 0x0001adb0, - 0x045, 0x00056467, - 0x046, 0x0008992c, - 0x047, 0x0000452c, - 0x048, 0x000c0443, - 0x049, 0x00000730, - 0x04a, 0x00050f0f, - 0x04b, 0x000896ee, - 0x04c, 0x0000ddee, - 0x018, 0x00007401, - 0x000, 0x00070000, - 0x012, 0x000dc000, - 0x012, 0x00090000, - 0x012, 0x00051000, - 0x012, 0x00012000, - 0x013, 0x000287b7, - 0x013, 0x000247ab, - 0x013, 0x0002079f, - 0x013, 0x0001c793, - 0x013, 0x0001839b, - 0x013, 0x00014392, - 0x013, 0x0001019a, - 0x013, 0x0000c191, - 0x013, 0x00008194, - 0x013, 0x000040a0, - 0x013, 0x00000018, - 0x015, 0x0000f424, - 0x015, 0x0004f424, - 0x015, 0x0008f424, - 0x016, 0x000e1330, - 0x016, 0x000a1330, - 0x016, 0x00061330, - 0x016, 0x00021330, - 0x018, 0x00017524, - 0x000, 0x00070000, - 0x012, 0x000cf000, - 0x012, 0x000bc000, - 0x012, 0x00078000, - 0x012, 0x00000000, - 0x013, 0x000287bf, - 0x013, 0x000247b3, - 0x013, 0x000207a7, - 0x013, 0x0001c79b, - 0x013, 0x0001839f, - 0x013, 0x00014393, - 0x013, 0x00010399, - 0x013, 0x0000c38d, - 0x013, 0x00008199, - 0x013, 0x0000418d, - 0x013, 0x00000099, - 0x015, 0x0000f495, - 0x015, 0x0004f495, - 0x015, 0x0008f495, - 0x016, 0x000e1874, - 0x016, 0x000a1874, - 0x016, 0x00061874, - 0x016, 0x00021874, - 0x018, 0x00037564, - 0x000, 0x00070000, - 0x012, 0x000cf000, - 0x012, 0x000bc000, - 0x012, 0x00078000, - 0x012, 0x00000000, - 0x013, 0x000287bf, - 0x013, 0x000247b3, - 0x013, 0x000207a7, - 0x013, 0x0001c79b, - 0x013, 0x0001839f, - 0x013, 0x00014393, - 0x013, 0x00010399, - 0x013, 0x0000c38d, - 0x013, 0x00008199, - 0x013, 0x0000418d, - 0x013, 0x00000099, - 0x015, 0x0000f495, - 0x015, 0x0004f495, - 0x015, 0x0008f495, - 0x016, 0x000e1874, - 0x016, 0x000a1874, - 0x016, 0x00061874, - 0x016, 0x00021874, - 0x018, 0x00057595, - 0x000, 0x00070000, - 0x012, 0x000cf000, - 0x012, 0x000bc000, - 0x012, 0x00078000, - 0x012, 0x00000000, - 0x013, 0x000287bf, - 0x013, 0x000247b3, - 0x013, 0x000207a7, - 0x013, 0x0001c79b, - 0x013, 0x0001839f, - 0x013, 0x00014393, - 0x013, 0x00010399, - 0x013, 0x0000c38d, - 0x013, 0x00008199, - 0x013, 0x0000418d, - 0x013, 0x00000099, - 0x015, 0x0000f495, - 0x015, 0x0004f495, - 0x015, 0x0008f495, - 0x016, 0x000e1874, - 0x016, 0x000a1874, - 0x016, 0x00061874, - 0x016, 0x00021874, - 0x030, 0x0004470f, - 0x031, 0x00044ff0, - 0x032, 0x00000070, - 0x033, 0x000dd480, - 0x034, 0x000ffac0, - 0x035, 0x000b80c0, - 0x036, 0x00077000, - 0x037, 0x00064ff2, - 0x038, 0x000e7661, - 0x039, 0x00000e90, - 0x000, 0x00030000, - 0x018, 0x0000f401, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01e, 0x00088009, - 0x01f, 0x00080003, - 0x0fe, 0x00000000, - 0x01e, 0x00088001, - 0x01f, 0x00080000, - 0x0fe, 0x00000000, - 0x018, 0x00097524, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x02b, 0x00041289, - 0x0fe, 0x00000000, - 0x02d, 0x0006aaaa, - 0x02e, 0x000b4d01, - 0x02d, 0x00080000, - 0x02e, 0x00004d02, - 0x02d, 0x00095555, - 0x02e, 0x00054d03, - 0x02d, 0x000aaaaa, - 0x02e, 0x000b4d04, - 0x02d, 0x000c0000, - 0x02e, 0x00004d05, - 0x02d, 0x000d5555, - 0x02e, 0x00054d06, - 0x02d, 0x000eaaaa, - 0x02e, 0x000b4d07, - 0x02d, 0x00000000, - 0x02e, 0x00005108, - 0x02d, 0x00015555, - 0x02e, 0x00055109, - 0x02d, 0x0002aaaa, - 0x02e, 0x000b510a, - 0x02d, 0x00040000, - 0x02e, 0x0000510b, - 0x02d, 0x00055555, - 0x02e, 0x0005510c, -}; - -u32 rtl8192de_radiob_2t_int_paarray[RADIOB_2T_INT_PA_ARRAYLENGTH] = { - 0x000, 0x00030000, - 0x001, 0x00030000, - 0x002, 0x00000000, - 0x003, 0x00018c63, - 0x004, 0x00018c63, - 0x008, 0x00084000, - 0x00b, 0x0001c000, - 0x00e, 0x00018c67, - 0x00f, 0x00000851, - 0x014, 0x00021440, - 0x018, 0x00007401, - 0x019, 0x00000060, - 0x01d, 0x000a1290, - 0x023, 0x00001558, - 0x01a, 0x00030a99, - 0x01b, 0x00040b00, - 0x01c, 0x000fc339, - 0x03a, 0x000a57eb, - 0x03b, 0x00020000, - 0x03c, 0x000ff454, - 0x020, 0x0000aa52, - 0x021, 0x00054000, - 0x040, 0x0000aa52, - 0x041, 0x00014000, - 0x025, 0x000803be, - 0x026, 0x000fc638, - 0x027, 0x00077c18, - 0x028, 0x000d1c31, - 0x029, 0x000d7110, - 0x02a, 0x000aeb04, - 0x02b, 0x0004128b, - 0x02c, 0x00001840, - 0x043, 0x0002444f, - 0x044, 0x0001adb0, - 0x045, 0x00056467, - 0x046, 0x0008992c, - 0x047, 0x0000452c, - 0x048, 0x000c0443, - 0x049, 0x00000730, - 0x04a, 0x00050f0f, - 0x04b, 0x000896ee, - 0x04c, 0x0000ddee, - 0x018, 0x00007401, - 0x000, 0x00070000, - 0x012, 0x000dc000, - 0x012, 0x00090000, - 0x012, 0x00051000, - 0x012, 0x00012000, - 0x013, 0x000287b7, - 0x013, 0x000247ab, - 0x013, 0x0002079f, - 0x013, 0x0001c793, - 0x013, 0x0001839b, - 0x013, 0x00014392, - 0x013, 0x0001019a, - 0x013, 0x0000c191, - 0x013, 0x00008194, - 0x013, 0x000040a0, - 0x013, 0x00000018, - 0x015, 0x0000f424, - 0x015, 0x0004f424, - 0x015, 0x0008f424, - 0x016, 0x000e1330, - 0x016, 0x000a1330, - 0x016, 0x00061330, - 0x016, 0x00021330, - 0x018, 0x00017524, - 0x000, 0x00070000, - 0x012, 0x000cf000, - 0x012, 0x000bc000, - 0x012, 0x00078000, - 0x012, 0x00000000, - 0x013, 0x000287bf, - 0x013, 0x000247b3, - 0x013, 0x000207a7, - 0x013, 0x0001c79b, - 0x013, 0x0001839f, - 0x013, 0x00014393, - 0x013, 0x00010399, - 0x013, 0x0000c38d, - 0x013, 0x00008199, - 0x013, 0x0000418d, - 0x013, 0x00000099, - 0x015, 0x0000f495, - 0x015, 0x0004f495, - 0x015, 0x0008f495, - 0x016, 0x000e1874, - 0x016, 0x000a1874, - 0x016, 0x00061874, - 0x016, 0x00021874, - 0x018, 0x00037564, - 0x000, 0x00070000, - 0x012, 0x000cf000, - 0x012, 0x000bc000, - 0x012, 0x00078000, - 0x012, 0x00000000, - 0x013, 0x000287bf, - 0x013, 0x000247b3, - 0x013, 0x000207a7, - 0x013, 0x0001c79b, - 0x013, 0x0001839f, - 0x013, 0x00014393, - 0x013, 0x00010399, - 0x013, 0x0000c38d, - 0x013, 0x00008199, - 0x013, 0x0000418d, - 0x013, 0x00000099, - 0x015, 0x0000f495, - 0x015, 0x0004f495, - 0x015, 0x0008f495, - 0x016, 0x000e1874, - 0x016, 0x000a1874, - 0x016, 0x00061874, - 0x016, 0x00021874, - 0x018, 0x00057595, - 0x000, 0x00070000, - 0x012, 0x000cf000, - 0x012, 0x000bc000, - 0x012, 0x00078000, - 0x012, 0x00000000, - 0x013, 0x000287bf, - 0x013, 0x000247b3, - 0x013, 0x000207a7, - 0x013, 0x0001c79b, - 0x013, 0x0001839f, - 0x013, 0x00014393, - 0x013, 0x00010399, - 0x013, 0x0000c38d, - 0x013, 0x00008199, - 0x013, 0x0000418d, - 0x013, 0x00000099, - 0x015, 0x0000f495, - 0x015, 0x0004f495, - 0x015, 0x0008f495, - 0x016, 0x000e1874, - 0x016, 0x000a1874, - 0x016, 0x00061874, - 0x016, 0x00021874, - 0x030, 0x0004470f, - 0x031, 0x00044ff0, - 0x032, 0x00000070, - 0x033, 0x000dd480, - 0x034, 0x000ffac0, - 0x035, 0x000b80c0, - 0x036, 0x00077000, - 0x037, 0x00064ff2, - 0x038, 0x000e7661, - 0x039, 0x00000e90, - 0x000, 0x00030000, - 0x018, 0x0000f401, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01e, 0x00088009, - 0x01f, 0x00080003, - 0x0fe, 0x00000000, - 0x01e, 0x00088001, - 0x01f, 0x00080000, - 0x0fe, 0x00000000, - 0x018, 0x00087401, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x02b, 0x00041289, - 0x0fe, 0x00000000, - 0x02d, 0x00066666, - 0x02e, 0x00064001, - 0x02d, 0x00091111, - 0x02e, 0x00014002, - 0x02d, 0x000bbbbb, - 0x02e, 0x000b4003, - 0x02d, 0x000e6666, - 0x02e, 0x00064004, - 0x02d, 0x00088888, - 0x02e, 0x00084005, - 0x02d, 0x0009dddd, - 0x02e, 0x000d4006, - 0x02d, 0x000b3333, - 0x02e, 0x00034007, - 0x02d, 0x00048888, - 0x02e, 0x00084408, - 0x02d, 0x000bbbbb, - 0x02e, 0x000b4409, - 0x02d, 0x000e6666, - 0x02e, 0x0006440a, - 0x02d, 0x00011111, - 0x02e, 0x0001480b, - 0x02d, 0x0003bbbb, - 0x02e, 0x000b480c, - 0x02d, 0x00066666, - 0x02e, 0x0006480d, - 0x02d, 0x000ccccc, - 0x02e, 0x000c480e, -}; - -u32 rtl8192de_mac_2tarray[MAC_2T_ARRAYLENGTH] = { - 0x420, 0x00000080, - 0x423, 0x00000000, - 0x430, 0x00000000, - 0x431, 0x00000000, - 0x432, 0x00000000, - 0x433, 0x00000001, - 0x434, 0x00000004, - 0x435, 0x00000005, - 0x436, 0x00000006, - 0x437, 0x00000007, - 0x438, 0x00000000, - 0x439, 0x00000000, - 0x43a, 0x00000000, - 0x43b, 0x00000001, - 0x43c, 0x00000004, - 0x43d, 0x00000005, - 0x43e, 0x00000006, - 0x43f, 0x00000007, - 0x440, 0x00000050, - 0x441, 0x00000001, - 0x442, 0x00000000, - 0x444, 0x00000015, - 0x445, 0x000000f0, - 0x446, 0x0000000f, - 0x447, 0x00000000, - 0x462, 0x00000008, - 0x463, 0x00000003, - 0x4c8, 0x000000ff, - 0x4c9, 0x00000008, - 0x4cc, 0x000000ff, - 0x4cd, 0x000000ff, - 0x4ce, 0x00000001, - 0x500, 0x00000026, - 0x501, 0x000000a2, - 0x502, 0x0000002f, - 0x503, 0x00000000, - 0x504, 0x00000028, - 0x505, 0x000000a3, - 0x506, 0x0000005e, - 0x507, 0x00000000, - 0x508, 0x0000002b, - 0x509, 0x000000a4, - 0x50a, 0x0000005e, - 0x50b, 0x00000000, - 0x50c, 0x0000004f, - 0x50d, 0x000000a4, - 0x50e, 0x00000000, - 0x50f, 0x00000000, - 0x512, 0x0000001c, - 0x514, 0x0000000a, - 0x515, 0x00000010, - 0x516, 0x0000000a, - 0x517, 0x00000010, - 0x51a, 0x00000016, - 0x524, 0x0000000f, - 0x525, 0x0000004f, - 0x546, 0x00000040, - 0x547, 0x00000000, - 0x550, 0x00000010, - 0x551, 0x00000010, - 0x559, 0x00000002, - 0x55a, 0x00000002, - 0x55d, 0x000000ff, - 0x605, 0x00000030, - 0x608, 0x0000000e, - 0x609, 0x0000002a, - 0x652, 0x00000020, - 0x63c, 0x0000000a, - 0x63d, 0x0000000a, - 0x63e, 0x0000000e, - 0x63f, 0x0000000e, - 0x66e, 0x00000005, - 0x700, 0x00000021, - 0x701, 0x00000043, - 0x702, 0x00000065, - 0x703, 0x00000087, - 0x708, 0x00000021, - 0x709, 0x00000043, - 0x70a, 0x00000065, - 0x70b, 0x00000087, -}; - -u32 rtl8192de_agctab_array[AGCTAB_ARRAYLENGTH] = { - 0xc78, 0x7b000001, - 0xc78, 0x7b010001, - 0xc78, 0x7b020001, - 0xc78, 0x7b030001, - 0xc78, 0x7b040001, - 0xc78, 0x7b050001, - 0xc78, 0x7b060001, - 0xc78, 0x7a070001, - 0xc78, 0x79080001, - 0xc78, 0x78090001, - 0xc78, 0x770a0001, - 0xc78, 0x760b0001, - 0xc78, 0x750c0001, - 0xc78, 0x740d0001, - 0xc78, 0x730e0001, - 0xc78, 0x720f0001, - 0xc78, 0x71100001, - 0xc78, 0x70110001, - 0xc78, 0x6f120001, - 0xc78, 0x6e130001, - 0xc78, 0x6d140001, - 0xc78, 0x6c150001, - 0xc78, 0x6b160001, - 0xc78, 0x6a170001, - 0xc78, 0x69180001, - 0xc78, 0x68190001, - 0xc78, 0x671a0001, - 0xc78, 0x661b0001, - 0xc78, 0x651c0001, - 0xc78, 0x641d0001, - 0xc78, 0x631e0001, - 0xc78, 0x621f0001, - 0xc78, 0x61200001, - 0xc78, 0x60210001, - 0xc78, 0x49220001, - 0xc78, 0x48230001, - 0xc78, 0x47240001, - 0xc78, 0x46250001, - 0xc78, 0x45260001, - 0xc78, 0x44270001, - 0xc78, 0x43280001, - 0xc78, 0x42290001, - 0xc78, 0x412a0001, - 0xc78, 0x402b0001, - 0xc78, 0x262c0001, - 0xc78, 0x252d0001, - 0xc78, 0x242e0001, - 0xc78, 0x232f0001, - 0xc78, 0x22300001, - 0xc78, 0x21310001, - 0xc78, 0x20320001, - 0xc78, 0x06330001, - 0xc78, 0x05340001, - 0xc78, 0x04350001, - 0xc78, 0x03360001, - 0xc78, 0x02370001, - 0xc78, 0x01380001, - 0xc78, 0x00390001, - 0xc78, 0x003a0001, - 0xc78, 0x003b0001, - 0xc78, 0x003c0001, - 0xc78, 0x003d0001, - 0xc78, 0x003e0001, - 0xc78, 0x003f0001, - 0xc78, 0x7b400001, - 0xc78, 0x7b410001, - 0xc78, 0x7a420001, - 0xc78, 0x79430001, - 0xc78, 0x78440001, - 0xc78, 0x77450001, - 0xc78, 0x76460001, - 0xc78, 0x75470001, - 0xc78, 0x74480001, - 0xc78, 0x73490001, - 0xc78, 0x724a0001, - 0xc78, 0x714b0001, - 0xc78, 0x704c0001, - 0xc78, 0x6f4d0001, - 0xc78, 0x6e4e0001, - 0xc78, 0x6d4f0001, - 0xc78, 0x6c500001, - 0xc78, 0x6b510001, - 0xc78, 0x6a520001, - 0xc78, 0x69530001, - 0xc78, 0x68540001, - 0xc78, 0x67550001, - 0xc78, 0x66560001, - 0xc78, 0x65570001, - 0xc78, 0x64580001, - 0xc78, 0x63590001, - 0xc78, 0x625a0001, - 0xc78, 0x615b0001, - 0xc78, 0x605c0001, - 0xc78, 0x485d0001, - 0xc78, 0x475e0001, - 0xc78, 0x465f0001, - 0xc78, 0x45600001, - 0xc78, 0x44610001, - 0xc78, 0x43620001, - 0xc78, 0x42630001, - 0xc78, 0x41640001, - 0xc78, 0x40650001, - 0xc78, 0x27660001, - 0xc78, 0x26670001, - 0xc78, 0x25680001, - 0xc78, 0x24690001, - 0xc78, 0x236a0001, - 0xc78, 0x226b0001, - 0xc78, 0x216c0001, - 0xc78, 0x206d0001, - 0xc78, 0x206e0001, - 0xc78, 0x206f0001, - 0xc78, 0x20700001, - 0xc78, 0x20710001, - 0xc78, 0x20720001, - 0xc78, 0x20730001, - 0xc78, 0x20740001, - 0xc78, 0x20750001, - 0xc78, 0x20760001, - 0xc78, 0x20770001, - 0xc78, 0x20780001, - 0xc78, 0x20790001, - 0xc78, 0x207a0001, - 0xc78, 0x207b0001, - 0xc78, 0x207c0001, - 0xc78, 0x207d0001, - 0xc78, 0x207e0001, - 0xc78, 0x207f0001, - 0xc78, 0x38000002, - 0xc78, 0x38010002, - 0xc78, 0x38020002, - 0xc78, 0x38030002, - 0xc78, 0x38040002, - 0xc78, 0x38050002, - 0xc78, 0x38060002, - 0xc78, 0x38070002, - 0xc78, 0x38080002, - 0xc78, 0x3c090002, - 0xc78, 0x3e0a0002, - 0xc78, 0x400b0002, - 0xc78, 0x440c0002, - 0xc78, 0x480d0002, - 0xc78, 0x4c0e0002, - 0xc78, 0x500f0002, - 0xc78, 0x52100002, - 0xc78, 0x56110002, - 0xc78, 0x5a120002, - 0xc78, 0x5e130002, - 0xc78, 0x60140002, - 0xc78, 0x60150002, - 0xc78, 0x60160002, - 0xc78, 0x62170002, - 0xc78, 0x62180002, - 0xc78, 0x62190002, - 0xc78, 0x621a0002, - 0xc78, 0x621b0002, - 0xc78, 0x621c0002, - 0xc78, 0x621d0002, - 0xc78, 0x621e0002, - 0xc78, 0x621f0002, - 0xc78, 0x32000044, - 0xc78, 0x32010044, - 0xc78, 0x32020044, - 0xc78, 0x32030044, - 0xc78, 0x32040044, - 0xc78, 0x32050044, - 0xc78, 0x32060044, - 0xc78, 0x32070044, - 0xc78, 0x32080044, - 0xc78, 0x34090044, - 0xc78, 0x350a0044, - 0xc78, 0x360b0044, - 0xc78, 0x370c0044, - 0xc78, 0x380d0044, - 0xc78, 0x390e0044, - 0xc78, 0x3a0f0044, - 0xc78, 0x3e100044, - 0xc78, 0x42110044, - 0xc78, 0x44120044, - 0xc78, 0x46130044, - 0xc78, 0x4a140044, - 0xc78, 0x4e150044, - 0xc78, 0x50160044, - 0xc78, 0x55170044, - 0xc78, 0x5a180044, - 0xc78, 0x5e190044, - 0xc78, 0x641a0044, - 0xc78, 0x6e1b0044, - 0xc78, 0x6e1c0044, - 0xc78, 0x6e1d0044, - 0xc78, 0x6e1e0044, - 0xc78, 0x6e1f0044, - 0xc78, 0x6e1f0000, -}; - -u32 rtl8192de_agctab_5garray[AGCTAB_5G_ARRAYLENGTH] = { - 0xc78, 0x7b000001, - 0xc78, 0x7b010001, - 0xc78, 0x7a020001, - 0xc78, 0x79030001, - 0xc78, 0x78040001, - 0xc78, 0x77050001, - 0xc78, 0x76060001, - 0xc78, 0x75070001, - 0xc78, 0x74080001, - 0xc78, 0x73090001, - 0xc78, 0x720a0001, - 0xc78, 0x710b0001, - 0xc78, 0x700c0001, - 0xc78, 0x6f0d0001, - 0xc78, 0x6e0e0001, - 0xc78, 0x6d0f0001, - 0xc78, 0x6c100001, - 0xc78, 0x6b110001, - 0xc78, 0x6a120001, - 0xc78, 0x69130001, - 0xc78, 0x68140001, - 0xc78, 0x67150001, - 0xc78, 0x66160001, - 0xc78, 0x65170001, - 0xc78, 0x64180001, - 0xc78, 0x63190001, - 0xc78, 0x621a0001, - 0xc78, 0x611b0001, - 0xc78, 0x601c0001, - 0xc78, 0x481d0001, - 0xc78, 0x471e0001, - 0xc78, 0x461f0001, - 0xc78, 0x45200001, - 0xc78, 0x44210001, - 0xc78, 0x43220001, - 0xc78, 0x42230001, - 0xc78, 0x41240001, - 0xc78, 0x40250001, - 0xc78, 0x27260001, - 0xc78, 0x26270001, - 0xc78, 0x25280001, - 0xc78, 0x24290001, - 0xc78, 0x232a0001, - 0xc78, 0x222b0001, - 0xc78, 0x212c0001, - 0xc78, 0x202d0001, - 0xc78, 0x202e0001, - 0xc78, 0x202f0001, - 0xc78, 0x20300001, - 0xc78, 0x20310001, - 0xc78, 0x20320001, - 0xc78, 0x20330001, - 0xc78, 0x20340001, - 0xc78, 0x20350001, - 0xc78, 0x20360001, - 0xc78, 0x20370001, - 0xc78, 0x20380001, - 0xc78, 0x20390001, - 0xc78, 0x203a0001, - 0xc78, 0x203b0001, - 0xc78, 0x203c0001, - 0xc78, 0x203d0001, - 0xc78, 0x203e0001, - 0xc78, 0x203f0001, - 0xc78, 0x32000044, - 0xc78, 0x32010044, - 0xc78, 0x32020044, - 0xc78, 0x32030044, - 0xc78, 0x32040044, - 0xc78, 0x32050044, - 0xc78, 0x32060044, - 0xc78, 0x32070044, - 0xc78, 0x32080044, - 0xc78, 0x34090044, - 0xc78, 0x350a0044, - 0xc78, 0x360b0044, - 0xc78, 0x370c0044, - 0xc78, 0x380d0044, - 0xc78, 0x390e0044, - 0xc78, 0x3a0f0044, - 0xc78, 0x3e100044, - 0xc78, 0x42110044, - 0xc78, 0x44120044, - 0xc78, 0x46130044, - 0xc78, 0x4a140044, - 0xc78, 0x4e150044, - 0xc78, 0x50160044, - 0xc78, 0x55170044, - 0xc78, 0x5a180044, - 0xc78, 0x5e190044, - 0xc78, 0x641a0044, - 0xc78, 0x6e1b0044, - 0xc78, 0x6e1c0044, - 0xc78, 0x6e1d0044, - 0xc78, 0x6e1e0044, - 0xc78, 0x6e1f0044, - 0xc78, 0x6e1f0000, -}; - -u32 rtl8192de_agctab_2garray[AGCTAB_2G_ARRAYLENGTH] = { - 0xc78, 0x7b000001, - 0xc78, 0x7b010001, - 0xc78, 0x7b020001, - 0xc78, 0x7b030001, - 0xc78, 0x7b040001, - 0xc78, 0x7b050001, - 0xc78, 0x7b060001, - 0xc78, 0x7a070001, - 0xc78, 0x79080001, - 0xc78, 0x78090001, - 0xc78, 0x770a0001, - 0xc78, 0x760b0001, - 0xc78, 0x750c0001, - 0xc78, 0x740d0001, - 0xc78, 0x730e0001, - 0xc78, 0x720f0001, - 0xc78, 0x71100001, - 0xc78, 0x70110001, - 0xc78, 0x6f120001, - 0xc78, 0x6e130001, - 0xc78, 0x6d140001, - 0xc78, 0x6c150001, - 0xc78, 0x6b160001, - 0xc78, 0x6a170001, - 0xc78, 0x69180001, - 0xc78, 0x68190001, - 0xc78, 0x671a0001, - 0xc78, 0x661b0001, - 0xc78, 0x651c0001, - 0xc78, 0x641d0001, - 0xc78, 0x631e0001, - 0xc78, 0x621f0001, - 0xc78, 0x61200001, - 0xc78, 0x60210001, - 0xc78, 0x49220001, - 0xc78, 0x48230001, - 0xc78, 0x47240001, - 0xc78, 0x46250001, - 0xc78, 0x45260001, - 0xc78, 0x44270001, - 0xc78, 0x43280001, - 0xc78, 0x42290001, - 0xc78, 0x412a0001, - 0xc78, 0x402b0001, - 0xc78, 0x262c0001, - 0xc78, 0x252d0001, - 0xc78, 0x242e0001, - 0xc78, 0x232f0001, - 0xc78, 0x22300001, - 0xc78, 0x21310001, - 0xc78, 0x20320001, - 0xc78, 0x06330001, - 0xc78, 0x05340001, - 0xc78, 0x04350001, - 0xc78, 0x03360001, - 0xc78, 0x02370001, - 0xc78, 0x01380001, - 0xc78, 0x00390001, - 0xc78, 0x003a0001, - 0xc78, 0x003b0001, - 0xc78, 0x003c0001, - 0xc78, 0x003d0001, - 0xc78, 0x003e0001, - 0xc78, 0x003f0001, - 0xc78, 0x38000002, - 0xc78, 0x38010002, - 0xc78, 0x38020002, - 0xc78, 0x38030002, - 0xc78, 0x38040002, - 0xc78, 0x38050002, - 0xc78, 0x38060002, - 0xc78, 0x38070002, - 0xc78, 0x38080002, - 0xc78, 0x3c090002, - 0xc78, 0x3e0a0002, - 0xc78, 0x400b0002, - 0xc78, 0x440c0002, - 0xc78, 0x480d0002, - 0xc78, 0x4c0e0002, - 0xc78, 0x500f0002, - 0xc78, 0x52100002, - 0xc78, 0x56110002, - 0xc78, 0x5a120002, - 0xc78, 0x5e130002, - 0xc78, 0x60140002, - 0xc78, 0x60150002, - 0xc78, 0x60160002, - 0xc78, 0x62170002, - 0xc78, 0x62180002, - 0xc78, 0x62190002, - 0xc78, 0x621a0002, - 0xc78, 0x621b0002, - 0xc78, 0x621c0002, - 0xc78, 0x621d0002, - 0xc78, 0x621e0002, - 0xc78, 0x621f0002, - 0xc78, 0x6e1f0000, -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.h b/drivers/net/wireless/rtlwifi/rtl8192de/table.h deleted file mode 100644 index 8b724a86117a..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/table.h +++ /dev/null @@ -1,57 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - * Created on 2010/ 5/18, 1:41 - *****************************************************************************/ - -#ifndef __RTL92DE_TABLE__H_ -#define __RTL92DE_TABLE__H_ - -/*Created on 2011/ 1/14, 1:35*/ - -#define PHY_REG_2T_ARRAYLENGTH 380 -extern u32 rtl8192de_phy_reg_2tarray[PHY_REG_2T_ARRAYLENGTH]; -#define PHY_REG_ARRAY_PG_LENGTH 624 -extern u32 rtl8192de_phy_reg_array_pg[PHY_REG_ARRAY_PG_LENGTH]; -#define RADIOA_2T_ARRAYLENGTH 378 -extern u32 rtl8192de_radioa_2tarray[RADIOA_2T_ARRAYLENGTH]; -#define RADIOB_2T_ARRAYLENGTH 384 -extern u32 rtl8192de_radiob_2tarray[RADIOB_2T_ARRAYLENGTH]; -#define RADIOA_2T_INT_PA_ARRAYLENGTH 378 -extern u32 rtl8192de_radioa_2t_int_paarray[RADIOA_2T_INT_PA_ARRAYLENGTH]; -#define RADIOB_2T_INT_PA_ARRAYLENGTH 384 -extern u32 rtl8192de_radiob_2t_int_paarray[RADIOB_2T_INT_PA_ARRAYLENGTH]; -#define MAC_2T_ARRAYLENGTH 160 -extern u32 rtl8192de_mac_2tarray[MAC_2T_ARRAYLENGTH]; -#define AGCTAB_ARRAYLENGTH 386 -extern u32 rtl8192de_agctab_array[AGCTAB_ARRAYLENGTH]; -#define AGCTAB_5G_ARRAYLENGTH 194 -extern u32 rtl8192de_agctab_5garray[AGCTAB_5G_ARRAYLENGTH]; -#define AGCTAB_2G_ARRAYLENGTH 194 -extern u32 rtl8192de_agctab_2garray[AGCTAB_2G_ARRAYLENGTH]; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c deleted file mode 100644 index 1feaa629dd4f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c +++ /dev/null @@ -1,871 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "trx.h" -#include "led.h" - -static u8 _rtl92de_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) -{ - __le16 fc = rtl_get_fc(skb); - - if (unlikely(ieee80211_is_beacon(fc))) - return QSLT_BEACON; - if (ieee80211_is_mgmt(fc)) - return QSLT_MGNT; - - return skb->priority; -} - -static u8 _rtl92d_query_rxpwrpercentage(char antpower) -{ - if ((antpower <= -100) || (antpower >= 20)) - return 0; - else if (antpower >= 0) - return 100; - else - return 100 + antpower; -} - -static u8 _rtl92d_evm_db_to_percentage(char value) -{ - char ret_val = value; - - if (ret_val >= 0) - ret_val = 0; - if (ret_val <= -33) - ret_val = -33; - ret_val = 0 - ret_val; - ret_val *= 3; - if (ret_val == 99) - ret_val = 100; - return ret_val; -} - -static long _rtl92de_translate_todbm(struct ieee80211_hw *hw, - u8 signal_strength_index) -{ - long signal_power; - - signal_power = (long)((signal_strength_index + 1) >> 1); - signal_power -= 95; - return signal_power; -} - -static long _rtl92de_signal_scale_mapping(struct ieee80211_hw *hw, long currsig) -{ - long retsig; - - if (currsig >= 61 && currsig <= 100) - retsig = 90 + ((currsig - 60) / 4); - else if (currsig >= 41 && currsig <= 60) - retsig = 78 + ((currsig - 40) / 2); - else if (currsig >= 31 && currsig <= 40) - retsig = 66 + (currsig - 30); - else if (currsig >= 21 && currsig <= 30) - retsig = 54 + (currsig - 20); - else if (currsig >= 5 && currsig <= 20) - retsig = 42 + (((currsig - 5) * 2) / 3); - else if (currsig == 4) - retsig = 36; - else if (currsig == 3) - retsig = 27; - else if (currsig == 2) - retsig = 18; - else if (currsig == 1) - retsig = 9; - else - retsig = currsig; - return retsig; -} - -static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw, - struct rtl_stats *pstats, - struct rx_desc_92d *pdesc, - struct rx_fwinfo_92d *p_drvinfo, - bool packet_match_bssid, - bool packet_toself, - bool packet_beacon) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); - struct phy_sts_cck_8192d *cck_buf; - s8 rx_pwr_all, rx_pwr[4]; - u8 rf_rx_num = 0, evm, pwdb_all; - u8 i, max_spatial_stream; - u32 rssi, total_rssi = 0; - bool is_cck_rate; - - is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc->rxmcs); - pstats->packet_matchbssid = packet_match_bssid; - pstats->packet_toself = packet_toself; - pstats->packet_beacon = packet_beacon; - pstats->is_cck = is_cck_rate; - pstats->rx_mimo_sig_qual[0] = -1; - pstats->rx_mimo_sig_qual[1] = -1; - - if (is_cck_rate) { - u8 report, cck_highpwr; - cck_buf = (struct phy_sts_cck_8192d *)p_drvinfo; - if (ppsc->rfpwr_state == ERFON) - cck_highpwr = (u8) rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, - BIT(9)); - else - cck_highpwr = false; - if (!cck_highpwr) { - u8 cck_agc_rpt = cck_buf->cck_agc_rpt; - report = cck_buf->cck_agc_rpt & 0xc0; - report = report >> 6; - switch (report) { - case 0x3: - rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); - break; - case 0x2: - rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); - break; - case 0x1: - rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); - break; - case 0x0: - rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); - break; - } - } else { - u8 cck_agc_rpt = cck_buf->cck_agc_rpt; - report = p_drvinfo->cfosho[0] & 0x60; - report = report >> 5; - switch (report) { - case 0x3: - rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x2: - rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x1: - rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x0: - rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1); - break; - } - } - pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all); - /* CCK gain is smaller than OFDM/MCS gain, */ - /* so we add gain diff by experiences, the val is 6 */ - pwdb_all += 6; - if (pwdb_all > 100) - pwdb_all = 100; - /* modify the offset to make the same gain index with OFDM. */ - if (pwdb_all > 34 && pwdb_all <= 42) - pwdb_all -= 2; - else if (pwdb_all > 26 && pwdb_all <= 34) - pwdb_all -= 6; - else if (pwdb_all > 14 && pwdb_all <= 26) - pwdb_all -= 8; - else if (pwdb_all > 4 && pwdb_all <= 14) - pwdb_all -= 4; - pstats->rx_pwdb_all = pwdb_all; - pstats->recvsignalpower = rx_pwr_all; - if (packet_match_bssid) { - u8 sq; - if (pstats->rx_pwdb_all > 40) { - sq = 100; - } else { - sq = cck_buf->sq_rpt; - if (sq > 64) - sq = 0; - else if (sq < 20) - sq = 100; - else - sq = ((64 - sq) * 100) / 44; - } - pstats->signalquality = sq; - pstats->rx_mimo_sig_qual[0] = sq; - pstats->rx_mimo_sig_qual[1] = -1; - } - } else { - rtlpriv->dm.rfpath_rxenable[0] = true; - rtlpriv->dm.rfpath_rxenable[1] = true; - for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { - if (rtlpriv->dm.rfpath_rxenable[i]) - rf_rx_num++; - rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - - 110; - rssi = _rtl92d_query_rxpwrpercentage(rx_pwr[i]); - total_rssi += rssi; - rtlpriv->stats.rx_snr_db[i] = - (long)(p_drvinfo->rxsnr[i] / 2); - if (packet_match_bssid) - pstats->rx_mimo_signalstrength[i] = (u8) rssi; - } - rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 106; - pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all); - pstats->rx_pwdb_all = pwdb_all; - pstats->rxpower = rx_pwr_all; - pstats->recvsignalpower = rx_pwr_all; - if (pdesc->rxht && pdesc->rxmcs >= DESC_RATEMCS8 && - pdesc->rxmcs <= DESC_RATEMCS15) - max_spatial_stream = 2; - else - max_spatial_stream = 1; - for (i = 0; i < max_spatial_stream; i++) { - evm = _rtl92d_evm_db_to_percentage(p_drvinfo->rxevm[i]); - if (packet_match_bssid) { - if (i == 0) - pstats->signalquality = - (u8)(evm & 0xff); - pstats->rx_mimo_sig_qual[i] = - (u8)(evm & 0xff); - } - } - } - if (is_cck_rate) - pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw, - pwdb_all)); - else if (rf_rx_num != 0) - pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw, - total_rssi /= rf_rx_num)); -} - -static void rtl92d_loop_over_paths(struct ieee80211_hw *hw, - struct rtl_stats *pstats) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u8 rfpath; - - for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; - rfpath++) { - if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { - rtlpriv->stats.rx_rssi_percentage[rfpath] = - pstats->rx_mimo_signalstrength[rfpath]; - - } - if (pstats->rx_mimo_signalstrength[rfpath] > - rtlpriv->stats.rx_rssi_percentage[rfpath]) { - rtlpriv->stats.rx_rssi_percentage[rfpath] = - ((rtlpriv->stats.rx_rssi_percentage[rfpath] * - (RX_SMOOTH_FACTOR - 1)) + - (pstats->rx_mimo_signalstrength[rfpath])) / - (RX_SMOOTH_FACTOR); - rtlpriv->stats.rx_rssi_percentage[rfpath] = - rtlpriv->stats.rx_rssi_percentage[rfpath] + 1; - } else { - rtlpriv->stats.rx_rssi_percentage[rfpath] = - ((rtlpriv->stats.rx_rssi_percentage[rfpath] * - (RX_SMOOTH_FACTOR - 1)) + - (pstats->rx_mimo_signalstrength[rfpath])) / - (RX_SMOOTH_FACTOR); - } - } -} - -static void _rtl92de_process_ui_rssi(struct ieee80211_hw *hw, - struct rtl_stats *pstats) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 last_rssi, tmpval; - - if (pstats->packet_toself || pstats->packet_beacon) { - rtlpriv->stats.rssi_calculate_cnt++; - if (rtlpriv->stats.ui_rssi.total_num++ >= - PHY_RSSI_SLID_WIN_MAX) { - rtlpriv->stats.ui_rssi.total_num = - PHY_RSSI_SLID_WIN_MAX; - last_rssi = rtlpriv->stats.ui_rssi.elements[ - rtlpriv->stats.ui_rssi.index]; - rtlpriv->stats.ui_rssi.total_val -= last_rssi; - } - rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; - rtlpriv->stats.ui_rssi.elements - [rtlpriv->stats.ui_rssi.index++] = - pstats->signalstrength; - if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) - rtlpriv->stats.ui_rssi.index = 0; - tmpval = rtlpriv->stats.ui_rssi.total_val / - rtlpriv->stats.ui_rssi.total_num; - rtlpriv->stats.signal_strength = _rtl92de_translate_todbm(hw, - (u8) tmpval); - pstats->rssi = rtlpriv->stats.signal_strength; - } - if (!pstats->is_cck && pstats->packet_toself) - rtl92d_loop_over_paths(hw, pstats); -} - -static void _rtl92de_update_rxsignalstatistics(struct ieee80211_hw *hw, - struct rtl_stats *pstats) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int weighting = 0; - - if (rtlpriv->stats.recv_signal_power == 0) - rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; - if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) - weighting = 5; - else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) - weighting = (-5); - rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power * - 5 + pstats->recvsignalpower + weighting) / 6; -} - -static void _rtl92de_process_pwdb(struct ieee80211_hw *hw, - struct rtl_stats *pstats) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long undec_sm_pwdb; - - if (mac->opmode == NL80211_IFTYPE_ADHOC || - mac->opmode == NL80211_IFTYPE_AP) - return; - else - undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; - - if (pstats->packet_toself || pstats->packet_beacon) { - if (undec_sm_pwdb < 0) - undec_sm_pwdb = pstats->rx_pwdb_all; - if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { - undec_sm_pwdb = (((undec_sm_pwdb) * - (RX_SMOOTH_FACTOR - 1)) + - (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); - undec_sm_pwdb = undec_sm_pwdb + 1; - } else { - undec_sm_pwdb = (((undec_sm_pwdb) * - (RX_SMOOTH_FACTOR - 1)) + - (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); - } - rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; - _rtl92de_update_rxsignalstatistics(hw, pstats); - } -} - -static void rtl92d_loop_over_streams(struct ieee80211_hw *hw, - struct rtl_stats *pstats) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int stream; - - for (stream = 0; stream < 2; stream++) { - if (pstats->rx_mimo_sig_qual[stream] != -1) { - if (rtlpriv->stats.rx_evm_percentage[stream] == 0) { - rtlpriv->stats.rx_evm_percentage[stream] = - pstats->rx_mimo_sig_qual[stream]; - } - rtlpriv->stats.rx_evm_percentage[stream] = - ((rtlpriv->stats.rx_evm_percentage[stream] - * (RX_SMOOTH_FACTOR - 1)) + - (pstats->rx_mimo_sig_qual[stream] * 1)) / - (RX_SMOOTH_FACTOR); - } - } -} - -static void _rtl92de_process_ui_link_quality(struct ieee80211_hw *hw, - struct rtl_stats *pstats) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 last_evm, tmpval; - - if (pstats->signalquality == 0) - return; - if (pstats->packet_toself || pstats->packet_beacon) { - if (rtlpriv->stats.ui_link_quality.total_num++ >= - PHY_LINKQUALITY_SLID_WIN_MAX) { - rtlpriv->stats.ui_link_quality.total_num = - PHY_LINKQUALITY_SLID_WIN_MAX; - last_evm = rtlpriv->stats.ui_link_quality.elements[ - rtlpriv->stats.ui_link_quality.index]; - rtlpriv->stats.ui_link_quality.total_val -= last_evm; - } - rtlpriv->stats.ui_link_quality.total_val += - pstats->signalquality; - rtlpriv->stats.ui_link_quality.elements[ - rtlpriv->stats.ui_link_quality.index++] = - pstats->signalquality; - if (rtlpriv->stats.ui_link_quality.index >= - PHY_LINKQUALITY_SLID_WIN_MAX) - rtlpriv->stats.ui_link_quality.index = 0; - tmpval = rtlpriv->stats.ui_link_quality.total_val / - rtlpriv->stats.ui_link_quality.total_num; - rtlpriv->stats.signal_quality = tmpval; - rtlpriv->stats.last_sigstrength_inpercent = tmpval; - rtl92d_loop_over_streams(hw, pstats); - } -} - -static void _rtl92de_process_phyinfo(struct ieee80211_hw *hw, - u8 *buffer, - struct rtl_stats *pcurrent_stats) -{ - - if (!pcurrent_stats->packet_matchbssid && - !pcurrent_stats->packet_beacon) - return; - - _rtl92de_process_ui_rssi(hw, pcurrent_stats); - _rtl92de_process_pwdb(hw, pcurrent_stats); - _rtl92de_process_ui_link_quality(hw, pcurrent_stats); -} - -static void _rtl92de_translate_rx_signal_stuff(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct rtl_stats *pstats, - struct rx_desc_92d *pdesc, - struct rx_fwinfo_92d *p_drvinfo) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct ieee80211_hdr *hdr; - u8 *tmp_buf; - u8 *praddr; - u16 type, cfc; - __le16 fc; - bool packet_matchbssid, packet_toself, packet_beacon = false; - - tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; - hdr = (struct ieee80211_hdr *)tmp_buf; - fc = hdr->frame_control; - cfc = le16_to_cpu(fc); - type = WLAN_FC_GET_TYPE(fc); - praddr = hdr->addr1; - packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && - ether_addr_equal(mac->bssid, - (cfc & IEEE80211_FCTL_TODS) ? hdr->addr1 : - (cfc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : - hdr->addr3) && - (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv)); - packet_toself = packet_matchbssid && - ether_addr_equal(praddr, rtlefuse->dev_addr); - if (ieee80211_is_beacon(fc)) - packet_beacon = true; - _rtl92de_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, - packet_matchbssid, packet_toself, - packet_beacon); - _rtl92de_process_phyinfo(hw, tmp_buf, pstats); -} - -bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, - struct ieee80211_rx_status *rx_status, - u8 *p_desc, struct sk_buff *skb) -{ - struct rx_fwinfo_92d *p_drvinfo; - struct rx_desc_92d *pdesc = (struct rx_desc_92d *)p_desc; - u32 phystatus = GET_RX_DESC_PHYST(pdesc); - - stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); - stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * - RX_DRV_INFO_SIZE_UNIT; - stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); - stats->icv = (u16) GET_RX_DESC_ICV(pdesc); - stats->crc = (u16) GET_RX_DESC_CRC32(pdesc); - stats->hwerror = (stats->crc | stats->icv); - stats->decrypted = !GET_RX_DESC_SWDEC(pdesc); - stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc); - stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); - stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); - stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) - && (GET_RX_DESC_FAGGR(pdesc) == 1)); - stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); - stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); - stats->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); - rx_status->freq = hw->conf.chandef.chan->center_freq; - rx_status->band = hw->conf.chandef.chan->band; - if (GET_RX_DESC_CRC32(pdesc)) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (!GET_RX_DESC_SWDEC(pdesc)) - rx_status->flag |= RX_FLAG_DECRYPTED; - if (GET_RX_DESC_BW(pdesc)) - rx_status->flag |= RX_FLAG_40MHZ; - if (GET_RX_DESC_RXHT(pdesc)) - rx_status->flag |= RX_FLAG_HT; - rx_status->flag |= RX_FLAG_MACTIME_START; - if (stats->decrypted) - rx_status->flag |= RX_FLAG_DECRYPTED; - rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht, - false, stats->rate); - rx_status->mactime = GET_RX_DESC_TSFL(pdesc); - if (phystatus) { - p_drvinfo = (struct rx_fwinfo_92d *)(skb->data + - stats->rx_bufshift); - _rtl92de_translate_rx_signal_stuff(hw, - skb, stats, pdesc, - p_drvinfo); - } - /*rx_status->qual = stats->signal; */ - rx_status->signal = stats->recvsignalpower + 10; - return true; -} - -static void _rtl92de_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, - u8 *virtualaddress) -{ - memset(virtualaddress, 0, 8); - - SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); - SET_EARLYMODE_LEN0(virtualaddress, ptcb_desc->empkt_len[0]); - SET_EARLYMODE_LEN1(virtualaddress, ptcb_desc->empkt_len[1]); - SET_EARLYMODE_LEN2_1(virtualaddress, ptcb_desc->empkt_len[2] & 0xF); - SET_EARLYMODE_LEN2_2(virtualaddress, ptcb_desc->empkt_len[2] >> 4); - SET_EARLYMODE_LEN3(virtualaddress, ptcb_desc->empkt_len[3]); - SET_EARLYMODE_LEN4(virtualaddress, ptcb_desc->empkt_len[4]); -} - -void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *pbd_desc_tx, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 *pdesc = pdesc_tx; - u16 seq_number; - __le16 fc = hdr->frame_control; - unsigned int buf_len = 0; - unsigned int skb_len = skb->len; - u8 fw_qsel = _rtl92de_map_hwqueue_to_fwqueue(skb, hw_queue); - bool firstseg = ((hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); - bool lastseg = ((hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); - dma_addr_t mapping; - u8 bw_40 = 0; - - if (mac->opmode == NL80211_IFTYPE_STATION) { - bw_40 = mac->bw_40; - } else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - if (sta) - bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; - } - seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); - /* reserve 8 byte for AMPDU early mode */ - if (rtlhal->earlymode_enable) { - skb_push(skb, EM_HDR_LEN); - memset(skb->data, 0, EM_HDR_LEN); - } - buf_len = skb->len; - mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92d)); - if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { - firstseg = true; - lastseg = true; - } - if (firstseg) { - if (rtlhal->earlymode_enable) { - SET_TX_DESC_PKT_OFFSET(pdesc, 1); - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + - EM_HDR_LEN); - if (ptcb_desc->empkt_num) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD, - "Insert 8 byte.pTcb->EMPktNum:%d\n", - ptcb_desc->empkt_num); - _rtl92de_insert_emcontent(ptcb_desc, - (u8 *)(skb->data)); - } - } else { - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - } - /* 5G have no CCK rate */ - if (rtlhal->current_bandtype == BAND_ON_5G) - if (ptcb_desc->hw_rate < DESC_RATE6M) - ptcb_desc->hw_rate = DESC_RATE6M; - SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); - if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) - SET_TX_DESC_DATA_SHORTGI(pdesc, 1); - - if (rtlhal->macphymode == DUALMAC_DUALPHY && - ptcb_desc->hw_rate == DESC_RATEMCS7) - SET_TX_DESC_DATA_SHORTGI(pdesc, 1); - - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - SET_TX_DESC_AGG_ENABLE(pdesc, 1); - SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); - } - SET_TX_DESC_SEQ(pdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && - !ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable - || ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); - /* 5G have no CCK rate */ - if (rtlhal->current_bandtype == BAND_ON_5G) - if (ptcb_desc->rts_rate < DESC_RATE6M) - ptcb_desc->rts_rate = DESC_RATE6M; - SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); - SET_TX_DESC_RTS_BW(pdesc, 0); - SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= - DESC_RATE54M) ? - (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : - (ptcb_desc->rts_use_shortgi ? 1 : 0))); - if (bw_40) { - if (ptcb_desc->packet_bw) { - SET_TX_DESC_DATA_BW(pdesc, 1); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, - mac->cur_40_prime_sc); - } - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); - } - SET_TX_DESC_LINIP(pdesc, 0); - SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb_len); - if (sta) { - u8 ampdu_density = sta->ht_cap.ampdu_density; - SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); - } - if (info->control.hw_key) { - struct ieee80211_key_conf *keyconf; - - keyconf = info->control.hw_key; - switch (keyconf->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - case WLAN_CIPHER_SUITE_TKIP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x1); - break; - case WLAN_CIPHER_SUITE_CCMP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x3); - break; - default: - SET_TX_DESC_SEC_TYPE(pdesc, 0x0); - break; - - } - } - SET_TX_DESC_PKT_ID(pdesc, 0); - SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); - SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); - SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); - SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ? - 1 : 0); - SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); - - /* Set TxRate and RTSRate in TxDesc */ - /* This prevent Tx initial rate of new-coming packets */ - /* from being overwritten by retried packet rate.*/ - if (!ptcb_desc->use_driver_rate) { - SET_TX_DESC_RTS_RATE(pdesc, 0x08); - /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */ - } - if (ieee80211_is_data_qos(fc)) { - if (mac->rdg_en) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "Enable RDG function\n"); - SET_TX_DESC_RDG_ENABLE(pdesc, 1); - SET_TX_DESC_HTC(pdesc, 1); - } - } - } - - SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); - SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) buf_len); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); - } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); - } - if (ieee80211_is_data_qos(fc)) - SET_TX_DESC_QOS(pdesc, 1); - - if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - SET_TX_DESC_PKT_ID(pdesc, 8); - } - SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); -} - -void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc, bool firstseg, - bool lastseg, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 fw_queue = QSLT_BEACON; - dma_addr_t mapping = pci_map_single(rtlpci->pdev, - skb->data, skb->len, PCI_DMA_TODEVICE); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - __le16 fc = hdr->frame_control; - - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); - if (firstseg) - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - /* 5G have no CCK rate - * Caution: The macros below are multi-line expansions. - * The braces are needed no matter what checkpatch says - */ - if (rtlhal->current_bandtype == BAND_ON_5G) { - SET_TX_DESC_TX_RATE(pdesc, DESC_RATE6M); - } else { - SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M); - } - SET_TX_DESC_SEQ(pdesc, 0); - SET_TX_DESC_LINIP(pdesc, 0); - SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)skb->len); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - SET_TX_DESC_RATE_ID(pdesc, 7); - SET_TX_DESC_MACID(pdesc, 0); - SET_TX_DESC_PKT_SIZE(pdesc, (u16) (skb->len)); - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - SET_TX_DESC_OFFSET(pdesc, 0x20); - SET_TX_DESC_USE_RATE(pdesc, 1); - - if (!ieee80211_is_data_qos(fc) && ppsc->fwctrl_lps) { - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - SET_TX_DESC_PKT_ID(pdesc, 8); - } - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C Tx Cmd Content", pdesc, TX_DESC_SIZE); - wmb(); - SET_TX_DESC_OWN(pdesc, 1); -} - -void rtl92de_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, - u8 desc_name, u8 *val) -{ - if (istx) { - switch (desc_name) { - case HW_DESC_OWN: - wmb(); - SET_TX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_TX_NEXTDESC_ADDR: - SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); - break; - default: - RT_ASSERT(false, "ERR txdesc :%d not process\n", - desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_RXOWN: - wmb(); - SET_RX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_RXBUFF_ADDR: - SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val); - break; - case HW_DESC_RXPKT_LEN: - SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val); - break; - case HW_DESC_RXERO: - SET_RX_DESC_EOR(pdesc, 1); - break; - default: - RT_ASSERT(false, "ERR rxdesc :%d not process\n", - desc_name); - break; - } - } -} - -u32 rtl92de_get_desc(u8 *p_desc, bool istx, u8 desc_name) -{ - u32 ret = 0; - - if (istx) { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_TX_DESC_OWN(p_desc); - break; - case HW_DESC_TXBUFF_ADDR: - ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc); - break; - default: - RT_ASSERT(false, "ERR txdesc :%d not process\n", - desc_name); - break; - } - } else { - struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_RX_DESC_OWN(pdesc); - break; - case HW_DESC_RXPKT_LEN: - ret = GET_RX_DESC_PKT_LEN(pdesc); - break; - default: - RT_ASSERT(false, "ERR rxdesc :%d not process\n", - desc_name); - break; - } - } - return ret; -} - -void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (hw_queue == BEACON_QUEUE) - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); - else - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, - BIT(0) << (hw_queue)); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h deleted file mode 100644 index fb5cf0634e8d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h +++ /dev/null @@ -1,748 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92DE_TRX_H__ -#define __RTL92DE_TRX_H__ - -#define TX_DESC_SIZE 64 -#define TX_DESC_AGGR_SUBFRAME_SIZE 32 - -#define RX_DESC_SIZE 32 -#define RX_DRV_INFO_SIZE_UNIT 8 - -#define TX_DESC_NEXT_DESC_OFFSET 40 -#define USB_HWDESC_HEADER_LEN 32 -#define CRCLENGTH 4 - -/* 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, __mask) \ - ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ - BIT_LEN_MASK_32(__mask)) - -/* 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/write various fields in RX or TX descriptors */ - -#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val) -#define SET_TX_DESC_OFFSET(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val) -#define SET_TX_DESC_BMC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 24, 1, __val) -#define SET_TX_DESC_HTC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 25, 1, __val) -#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) -#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) -#define SET_TX_DESC_LINIP(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) -#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) -#define SET_TX_DESC_GF(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) -#define SET_TX_DESC_OWN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) - -#define GET_TX_DESC_PKT_SIZE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 0, 16) -#define GET_TX_DESC_OFFSET(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 16, 8) -#define GET_TX_DESC_BMC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 24, 1) -#define GET_TX_DESC_HTC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 25, 1) -#define GET_TX_DESC_LAST_SEG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 26, 1) -#define GET_TX_DESC_FIRST_SEG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 27, 1) -#define GET_TX_DESC_LINIP(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 28, 1) -#define GET_TX_DESC_NO_ACM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 29, 1) -#define GET_TX_DESC_GF(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 30, 1) -#define GET_TX_DESC_OWN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 31, 1) - -#define SET_TX_DESC_MACID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 0, 5, __val) -#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 5, 1, __val) -#define SET_TX_DESC_BK(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 6, 1, __val) -#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 7, 1, __val) -#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 8, 5, __val) -#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 13, 1, __val) -#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 14, 1, __val) -#define SET_TX_DESC_PIFS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 15, 1, __val) -#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 16, 4, __val) -#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 20, 1, __val) -#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 21, 1, __val) -#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 22, 2, __val) -#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+4, 26, 8, __val) - -#define GET_TX_DESC_MACID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 0, 5) -#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 5, 1) -#define GET_TX_DESC_AGG_BREAK(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 6, 1) -#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 7, 1) -#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 8, 5) -#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 13, 1) -#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) -#define GET_TX_DESC_PIFS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) -#define GET_TX_DESC_RATE_ID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 16, 4) -#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 20, 1) -#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 21, 1) -#define GET_TX_DESC_SEC_TYPE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 22, 2) -#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 24, 8) - -#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 0, 6, __val) -#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 6, 6, __val) -#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 14, 2, __val) -#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 17, 1, __val) -#define SET_TX_DESC_RAW(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 18, 1, __val) -#define SET_TX_DESC_CCX(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 19, 1, __val) -#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 20, 3, __val) -#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 24, 1, __val) -#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 25, 1, __val) -#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 26, 2, __val) -#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 28, 2, __val) -#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+8, 30, 2, __val) - -#define GET_TX_DESC_RTS_RC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 0, 6) -#define GET_TX_DESC_DATA_RC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 6, 6) -#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 14, 2) -#define GET_TX_DESC_MORE_FRAG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 17, 1) -#define GET_TX_DESC_RAW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 18, 1) -#define GET_TX_DESC_CCX(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 19, 1) -#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 20, 3) -#define GET_TX_DESC_ANTSEL_A(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 24, 1) -#define GET_TX_DESC_ANTSEL_B(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 25, 1) -#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 26, 2) -#define GET_TX_DESC_TX_ANTL(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 28, 2) -#define GET_TX_DESC_TX_ANT_HT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 30, 2) - -#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+12, 0, 8, __val) -#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+12, 8, 8, __val) -#define SET_TX_DESC_SEQ(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+12, 16, 12, __val) -#define SET_TX_DESC_PKT_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+12, 28, 4, __val) - -#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 0, 8) -#define GET_TX_DESC_TAIL_PAGE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 8, 8) -#define GET_TX_DESC_SEQ(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 16, 12) -#define GET_TX_DESC_PKT_ID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 28, 4) - -#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 0, 5, __val) -#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 5, 1, __val) -#define SET_TX_DESC_QOS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 6, 1, __val) -#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 7, 1, __val) -#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 8, 1, __val) -#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 9, 1, __val) -#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 10, 1, __val) -#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 11, 1, __val) -#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 12, 1, __val) -#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 13, 1, __val) -#define SET_TX_DESC_PORT_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 14, 1, __val) -#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 18, 1, __val) -#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 19, 1, __val) -#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 20, 2, __val) -#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 22, 2, __val) -#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 24, 1, __val) -#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 25, 1, __val) -#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 26, 1, __val) -#define SET_TX_DESC_RTS_BW(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 27, 1, __val) -#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 28, 2, __val) -#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+16, 30, 2, __val) - -#define GET_TX_DESC_RTS_RATE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 0, 5) -#define GET_TX_DESC_AP_DCFE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 5, 1) -#define GET_TX_DESC_QOS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 6, 1) -#define GET_TX_DESC_HWSEQ_EN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 7, 1) -#define GET_TX_DESC_USE_RATE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 8, 1) -#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 9, 1) -#define GET_TX_DESC_DISABLE_FB(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 10, 1) -#define GET_TX_DESC_CTS2SELF(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 11, 1) -#define GET_TX_DESC_RTS_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 12, 1) -#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 13, 1) -#define GET_TX_DESC_PORT_ID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 14, 1) -#define GET_TX_DESC_WAIT_DCTS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 18, 1) -#define GET_TX_DESC_CTS2AP_EN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 19, 1) -#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 20, 2) -#define GET_TX_DESC_TX_STBC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 22, 2) -#define GET_TX_DESC_DATA_SHORT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 24, 1) -#define GET_TX_DESC_DATA_BW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 25, 1) -#define GET_TX_DESC_RTS_SHORT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 26, 1) -#define GET_TX_DESC_RTS_BW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 27, 1) -#define GET_TX_DESC_RTS_SC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 28, 2) -#define GET_TX_DESC_RTS_STBC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 30, 2) - -#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val) -#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val) -#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val) -#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 8, 5, __val) -#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 13, 4, __val) -#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 17, 1, __val) -#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 18, 6, __val) -#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+20, 24, 8, __val) - -#define GET_TX_DESC_TX_RATE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 0, 6) -#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 6, 1) -#define GET_TX_DESC_CCX_TAG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 7, 1) -#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 8, 5) -#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 13, 4) -#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 17, 1) -#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 18, 6) -#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 24, 8) - -#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 0, 5, __val) -#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 5, 5, __val) -#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 10, 1, __val) -#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 11, 5, __val) -#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 16, 4, __val) -#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 20, 4, __val) -#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 24, 4, __val) -#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 28, 4, __val) - -#define GET_TX_DESC_TXAGC_A(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 0, 5) -#define GET_TX_DESC_TXAGC_B(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 5, 5) -#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 10, 1) -#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 11, 5) -#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 16, 4) -#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 20, 4) -#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 24, 4) -#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 28, 4) - -#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 0, 16, __val) -#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 16, 4, __val) -#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 20, 4, __val) -#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 24, 4, __val) -#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 28, 4, __val) - -#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 0, 16) -#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 16, 4) -#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 20, 4) -#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 24, 4) -#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 28, 4) - -#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+32, 0, 32, __val) -#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+36, 0, 32, __val) - -#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+32, 0, 32) -#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+36, 0, 32) - -#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+40, 0, 32, __val) -#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+44, 0, 32, __val) - -#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+40, 0, 32) -#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+44, 0, 32) - -#define GET_RX_DESC_PKT_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 0, 14) -#define GET_RX_DESC_CRC32(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 14, 1) -#define GET_RX_DESC_ICV(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 15, 1) -#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 16, 4) -#define GET_RX_DESC_SECURITY(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 20, 3) -#define GET_RX_DESC_QOS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 23, 1) -#define GET_RX_DESC_SHIFT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 24, 2) -#define GET_RX_DESC_PHYST(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 26, 1) -#define GET_RX_DESC_SWDEC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 27, 1) -#define GET_RX_DESC_LS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 28, 1) -#define GET_RX_DESC_FS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 29, 1) -#define GET_RX_DESC_EOR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 30, 1) -#define GET_RX_DESC_OWN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 31, 1) - -#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val) -#define SET_RX_DESC_EOR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) -#define SET_RX_DESC_OWN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) - -#define GET_RX_DESC_MACID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 0, 5) -#define GET_RX_DESC_TID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 5, 4) -#define GET_RX_DESC_HWRSVD(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 9, 5) -#define GET_RX_DESC_PAGGR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) -#define GET_RX_DESC_FAGGR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) -#define GET_RX_DESC_A1_FIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 16, 4) -#define GET_RX_DESC_A2_FIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 20, 4) -#define GET_RX_DESC_PAM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 24, 1) -#define GET_RX_DESC_PWR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 25, 1) -#define GET_RX_DESC_MD(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 26, 1) -#define GET_RX_DESC_MF(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 27, 1) -#define GET_RX_DESC_TYPE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 28, 2) -#define GET_RX_DESC_MC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 30, 1) -#define GET_RX_DESC_BC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+4, 31, 1) -#define GET_RX_DESC_SEQ(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 0, 12) -#define GET_RX_DESC_FRAG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 12, 4) -#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 16, 14) -#define GET_RX_DESC_NEXT_IND(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 30, 1) -#define GET_RX_DESC_RSVD(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+8, 31, 1) - -#define GET_RX_DESC_RXMCS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 0, 6) -#define GET_RX_DESC_RXHT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 6, 1) -#define GET_RX_DESC_SPLCP(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 8, 1) -#define GET_RX_DESC_BW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 9, 1) -#define GET_RX_DESC_HTC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 10, 1) -#define GET_RX_DESC_HWPC_ERR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 14, 1) -#define GET_RX_DESC_HWPC_IND(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 15, 1) -#define GET_RX_DESC_IV0(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+12, 16, 16) - -#define GET_RX_DESC_IV1(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+16, 0, 32) -#define GET_RX_DESC_TSFL(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+20, 0, 32) - -#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+24, 0, 32) -#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc+28, 0, 32) - -#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+24, 0, 32, __val) -#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val) - -#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ - memset((void *)__pdesc, 0, \ - min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) - -/* For 92D early mode */ -#define SET_EARLYMODE_PKTNUM(__paddr, __value) \ - SET_BITS_OFFSET_LE(__paddr, 0, 3, __value) -#define SET_EARLYMODE_LEN0(__paddr, __value) \ - SET_BITS_OFFSET_LE(__paddr, 4, 12, __value) -#define SET_EARLYMODE_LEN1(__paddr, __value) \ - SET_BITS_OFFSET_LE(__paddr, 16, 12, __value) -#define SET_EARLYMODE_LEN2_1(__paddr, __value) \ - SET_BITS_OFFSET_LE(__paddr, 28, 4, __value) -#define SET_EARLYMODE_LEN2_2(__paddr, __value) \ - SET_BITS_OFFSET_LE(__paddr+4, 0, 8, __value) -#define SET_EARLYMODE_LEN3(__paddr, __value) \ - SET_BITS_OFFSET_LE(__paddr+4, 8, 12, __value) -#define SET_EARLYMODE_LEN4(__paddr, __value) \ - SET_BITS_OFFSET_LE(__paddr+4, 20, 12, __value) - -struct rx_fwinfo_92d { - u8 gain_trsw[4]; - u8 pwdb_all; - u8 cfosho[4]; - u8 cfotail[4]; - char rxevm[2]; - char rxsnr[4]; - u8 pdsnr[2]; - u8 csi_current[2]; - u8 csi_target[2]; - u8 sigevm; - u8 max_ex_pwr; - u8 ex_intf_flag:1; - u8 sgi_en:1; - u8 rxsc:2; - u8 reserve:4; -} __packed; - -struct tx_desc_92d { - u32 pktsize:16; - u32 offset:8; - u32 bmc:1; - u32 htc:1; - u32 lastseg:1; - u32 firstseg:1; - u32 linip:1; - u32 noacm:1; - u32 gf:1; - u32 own:1; - - u32 macid:5; - u32 agg_en:1; - u32 bk:1; - u32 rdg_en:1; - u32 queuesel:5; - u32 rd_nav_ext:1; - u32 lsig_txop_en:1; - u32 pifs:1; - u32 rateid:4; - u32 nav_usehdr:1; - u32 en_descid:1; - u32 sectype:2; - u32 pktoffset:8; - - u32 rts_rc:6; - u32 data_rc:6; - u32 rsvd0:2; - u32 bar_retryht:2; - u32 rsvd1:1; - u32 morefrag:1; - u32 raw:1; - u32 ccx:1; - u32 ampdudensity:3; - u32 rsvd2:1; - u32 ant_sela:1; - u32 ant_selb:1; - u32 txant_cck:2; - u32 txant_l:2; - u32 txant_ht:2; - - u32 nextheadpage:8; - u32 tailpage:8; - u32 seq:12; - u32 pktid:4; - - u32 rtsrate:5; - u32 apdcfe:1; - u32 qos:1; - u32 hwseq_enable:1; - u32 userrate:1; - u32 dis_rtsfb:1; - u32 dis_datafb:1; - u32 cts2self:1; - u32 rts_en:1; - u32 hwrts_en:1; - u32 portid:1; - u32 rsvd3:3; - u32 waitdcts:1; - u32 cts2ap_en:1; - u32 txsc:2; - u32 stbc:2; - u32 txshort:1; - u32 txbw:1; - u32 rtsshort:1; - u32 rtsbw:1; - u32 rtssc:2; - u32 rtsstbc:2; - - u32 txrate:6; - u32 shortgi:1; - u32 ccxt:1; - u32 txrate_fb_lmt:5; - u32 rtsrate_fb_lmt:4; - u32 retrylmt_en:1; - u32 txretrylmt:6; - u32 usb_txaggnum:8; - - u32 txagca:5; - u32 txagcb:5; - u32 usemaxlen:1; - u32 maxaggnum:5; - u32 mcsg1maxlen:4; - u32 mcsg2maxlen:4; - u32 mcsg3maxlen:4; - u32 mcs7sgimaxlen:4; - - u32 txbuffersize:16; - u32 mcsg4maxlen:4; - u32 mcsg5maxlen:4; - u32 mcsg6maxlen:4; - u32 mcsg15sgimaxlen:4; - - u32 txbuffaddr; - u32 txbufferaddr64; - u32 nextdescaddress; - u32 nextdescaddress64; - - u32 reserve_pass_pcie_mm_limit[4]; -} __packed; - -struct rx_desc_92d { - u32 length:14; - u32 crc32:1; - u32 icverror:1; - u32 drv_infosize:4; - u32 security:3; - u32 qos:1; - u32 shift:2; - u32 phystatus:1; - u32 swdec:1; - u32 lastseg:1; - u32 firstseg:1; - u32 eor:1; - u32 own:1; - - u32 macid:5; - u32 tid:4; - u32 hwrsvd:5; - u32 paggr:1; - u32 faggr:1; - u32 a1_fit:4; - u32 a2_fit:4; - u32 pam:1; - u32 pwr:1; - u32 moredata:1; - u32 morefrag:1; - u32 type:2; - u32 mc:1; - u32 bc:1; - - u32 seq:12; - u32 frag:4; - u32 nextpktlen:14; - u32 nextind:1; - u32 rsvd:1; - - u32 rxmcs:6; - u32 rxht:1; - u32 amsdu:1; - u32 splcp:1; - u32 bandwidth:1; - u32 htc:1; - u32 tcpchk_rpt:1; - u32 ipcchk_rpt:1; - u32 tcpchk_valid:1; - u32 hwpcerr:1; - u32 hwpcind:1; - u32 iv0:16; - - u32 iv1; - - u32 tsfl; - - u32 bufferaddress; - u32 bufferaddress64; - -} __packed; - -void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc, - u8 *pbd_desc_tx, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, u8 hw_queue, - struct rtl_tcb_desc *ptcb_desc); -bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *stats, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb); -void rtl92de_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, - u8 desc_name, u8 *val); -u32 rtl92de_get_desc(u8 *pdesc, bool istx, u8 desc_name); -void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); -void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool b_firstseg, bool b_lastseg, - struct sk_buff *skb); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile b/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile deleted file mode 100644 index 0315eeda9b60..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -rtl8192ee-objs := \ - dm.o \ - fw.o \ - hw.o \ - led.o \ - phy.o \ - pwrseq.o \ - rf.o \ - sw.o \ - table.o \ - trx.o \ - - -obj-$(CONFIG_RTL8192EE) += rtl8192ee.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/def.h b/drivers/net/wireless/rtlwifi/rtl8192ee/def.h deleted file mode 100644 index 60f5728b4e2d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/def.h +++ /dev/null @@ -1,101 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92E_DEF_H__ -#define __RTL92E_DEF_H__ - -#define RX_DESC_NUM_92E 512 - -#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 -#define HAL_PRIME_CHNL_OFFSET_LOWER 1 -#define HAL_PRIME_CHNL_OFFSET_UPPER 2 - -#define RX_MPDU_QUEUE 0 - -#define IS_HT_RATE(_rate) \ - (_rate >= DESC92C_RATEMCS0) -#define IS_CCK_RATE(_rate) \ - (_rate >= DESC92C_RATE1M && _rate <= DESC92C_RATE11M) -#define IS_OFDM_RATE(_rate) \ - (_rate >= DESC92C_RATE6M && _rate <= DESC92C_RATE54M) - -enum version_8192e { - VERSION_TEST_CHIP_2T2R_8192E = 0x0024, - VERSION_NORMAL_CHIP_2T2R_8192E = 0x102C, - VERSION_UNKNOWN = 0xFF, -}; - -enum rx_packet_type { - NORMAL_RX, - TX_REPORT1, - TX_REPORT2, - HIS_REPORT, - C2H_PACKET, -}; - -enum rtl_desc_qsel { - QSLT_BK = 0x2, - QSLT_BE = 0x0, - QSLT_VI = 0x5, - QSLT_VO = 0x7, - QSLT_BEACON = 0x10, - QSLT_HIGH = 0x11, - QSLT_MGNT = 0x12, - QSLT_CMD = 0x13, -}; - -enum rtl_desc92c_rate { - DESC92C_RATE1M = 0x00, - DESC92C_RATE2M = 0x01, - DESC92C_RATE5_5M = 0x02, - DESC92C_RATE11M = 0x03, - - DESC92C_RATE6M = 0x04, - DESC92C_RATE9M = 0x05, - DESC92C_RATE12M = 0x06, - DESC92C_RATE18M = 0x07, - DESC92C_RATE24M = 0x08, - DESC92C_RATE36M = 0x09, - DESC92C_RATE48M = 0x0a, - DESC92C_RATE54M = 0x0b, - - DESC92C_RATEMCS0 = 0x0c, - DESC92C_RATEMCS1 = 0x0d, - DESC92C_RATEMCS2 = 0x0e, - DESC92C_RATEMCS3 = 0x0f, - DESC92C_RATEMCS4 = 0x10, - DESC92C_RATEMCS5 = 0x11, - DESC92C_RATEMCS6 = 0x12, - DESC92C_RATEMCS7 = 0x13, - DESC92C_RATEMCS8 = 0x14, - DESC92C_RATEMCS9 = 0x15, - DESC92C_RATEMCS10 = 0x16, - DESC92C_RATEMCS11 = 0x17, - DESC92C_RATEMCS12 = 0x18, - DESC92C_RATEMCS13 = 0x19, - DESC92C_RATEMCS14 = 0x1a, - DESC92C_RATEMCS15 = 0x1b, -}; -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/dm.c b/drivers/net/wireless/rtlwifi/rtl8192ee/dm.c deleted file mode 100644 index 459f3d0efa2f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/dm.c +++ /dev/null @@ -1,1236 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../base.h" -#include "../pci.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "fw.h" -#include "trx.h" - -static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { - 0x7f8001fe, /* 0, +6.0dB */ - 0x788001e2, /* 1, +5.5dB */ - 0x71c001c7, /* 2, +5.0dB */ - 0x6b8001ae, /* 3, +4.5dB */ - 0x65400195, /* 4, +4.0dB */ - 0x5fc0017f, /* 5, +3.5dB */ - 0x5a400169, /* 6, +3.0dB */ - 0x55400155, /* 7, +2.5dB */ - 0x50800142, /* 8, +2.0dB */ - 0x4c000130, /* 9, +1.5dB */ - 0x47c0011f, /* 10, +1.0dB */ - 0x43c0010f, /* 11, +0.5dB */ - 0x40000100, /* 12, +0dB */ - 0x3c8000f2, /* 13, -0.5dB */ - 0x390000e4, /* 14, -1.0dB */ - 0x35c000d7, /* 15, -1.5dB */ - 0x32c000cb, /* 16, -2.0dB */ - 0x300000c0, /* 17, -2.5dB */ - 0x2d4000b5, /* 18, -3.0dB */ - 0x2ac000ab, /* 19, -3.5dB */ - 0x288000a2, /* 20, -4.0dB */ - 0x26000098, /* 21, -4.5dB */ - 0x24000090, /* 22, -5.0dB */ - 0x22000088, /* 23, -5.5dB */ - 0x20000080, /* 24, -6.0dB */ - 0x1e400079, /* 25, -6.5dB */ - 0x1c800072, /* 26, -7.0dB */ - 0x1b00006c, /* 27. -7.5dB */ - 0x19800066, /* 28, -8.0dB */ - 0x18000060, /* 29, -8.5dB */ - 0x16c0005b, /* 30, -9.0dB */ - 0x15800056, /* 31, -9.5dB */ - 0x14400051, /* 32, -10.0dB */ - 0x1300004c, /* 33, -10.5dB */ - 0x12000048, /* 34, -11.0dB */ - 0x11000044, /* 35, -11.5dB */ - 0x10000040, /* 36, -12.0dB */ - 0x0f00003c, /* 37, -12.5dB */ - 0x0e400039, /* 38, -13.0dB */ - 0x0d800036, /* 39, -13.5dB */ - 0x0cc00033, /* 40, -14.0dB */ - 0x0c000030, /* 41, -14.5dB */ - 0x0b40002d, /* 42, -15.0dB */ -}; - -static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */ - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */ - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */ - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */ - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */ - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */ - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */ - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */ - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */ - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */ - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */ - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */ - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */ - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} /* 32, -16.0dB */ -}; - -static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */ - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */ - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */ - {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */ - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */ - {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */ - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */ - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */ - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */ - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */ - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */ - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */ - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */ - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */ - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */ - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */ - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */ - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */ - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */ - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */ - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */ - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */ - {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */ - {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */ - {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */ - {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */ - {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */ - {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */ - {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */ - {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */ - {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */ - {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} /* 32, -16.0dB */ -}; - -static void rtl92ee_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) -{ - u32 ret_value; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt; - - rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); - rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); - - ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD); - falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff); - falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16); - - ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD); - falsealm_cnt->cnt_ofdm_cca = (ret_value & 0xffff); - falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); - - ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD); - falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); - falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); - - ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD); - falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); - - falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + - falsealm_cnt->cnt_mcs_fail + - falsealm_cnt->cnt_fast_fsync_fail + - falsealm_cnt->cnt_sb_search_fail; - - ret_value = rtl_get_bbreg(hw, DM_REG_SC_CNT_11N, MASKDWORD); - falsealm_cnt->cnt_bw_lsc = (ret_value & 0xffff); - falsealm_cnt->cnt_bw_usc = ((ret_value & 0xffff0000) >> 16); - - rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1); - rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1); - - ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_LSB_11N, MASKBYTE0); - falsealm_cnt->cnt_cck_fail = ret_value; - - ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3); - falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; - - ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD); - falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) | - ((ret_value & 0xFF00) >> 8); - - falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail + - falsealm_cnt->cnt_sb_search_fail + - falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + - falsealm_cnt->cnt_mcs_fail + - falsealm_cnt->cnt_cck_fail; - - falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca + - falsealm_cnt->cnt_cck_cca; - - /*reset false alarm counter registers*/ - rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1); - rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0); - rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1); - rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0); - /*update ofdm counter*/ - rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0); - rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0); - /*reset CCK CCA counter*/ - rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0); - rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2); - /*reset CCK FA counter*/ - rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0); - rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", - falsealm_cnt->cnt_parity_fail, - falsealm_cnt->cnt_rate_illegal, - falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", - falsealm_cnt->cnt_ofdm_fail, - falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all); -} - -static void rtl92ee_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_dig = &rtlpriv->dm_digtable; - u8 cur_cck_cca_thresh; - - if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) { - if (dm_dig->rssi_val_min > 25) { - cur_cck_cca_thresh = 0xcd; - } else if ((dm_dig->rssi_val_min <= 25) && - (dm_dig->rssi_val_min > 10)) { - cur_cck_cca_thresh = 0x83; - } else { - if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) - cur_cck_cca_thresh = 0x83; - else - cur_cck_cca_thresh = 0x40; - } - } else { - if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) - cur_cck_cca_thresh = 0x83; - else - cur_cck_cca_thresh = 0x40; - } - rtl92ee_dm_write_cck_cca_thres(hw, cur_cck_cca_thresh); -} - -static void rtl92ee_dm_dig(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct dig_t *dm_dig = &rtlpriv->dm_digtable; - u8 dig_min_0, dig_maxofmin; - bool bfirstconnect , bfirstdisconnect; - u8 dm_dig_max, dm_dig_min; - u8 current_igi = dm_dig->cur_igvalue; - u8 offset; - - /* AP,BT */ - if (mac->act_scanning) - return; - - dig_min_0 = dm_dig->dig_min_0; - bfirstconnect = (mac->link_state >= MAC80211_LINKED) && - !dm_dig->media_connect_0; - bfirstdisconnect = (mac->link_state < MAC80211_LINKED) && - dm_dig->media_connect_0; - - dm_dig_max = 0x5a; - dm_dig_min = DM_DIG_MIN; - dig_maxofmin = DM_DIG_MAX_AP; - - if (mac->link_state >= MAC80211_LINKED) { - if ((dm_dig->rssi_val_min + 10) > dm_dig_max) - dm_dig->rx_gain_max = dm_dig_max; - else if ((dm_dig->rssi_val_min + 10) < dm_dig_min) - dm_dig->rx_gain_max = dm_dig_min; - else - dm_dig->rx_gain_max = dm_dig->rssi_val_min + 10; - - if (rtlpriv->dm.one_entry_only) { - offset = 0; - if (dm_dig->rssi_val_min - offset < dm_dig_min) - dig_min_0 = dm_dig_min; - else if (dm_dig->rssi_val_min - offset > - dig_maxofmin) - dig_min_0 = dig_maxofmin; - else - dig_min_0 = dm_dig->rssi_val_min - offset; - } else { - dig_min_0 = dm_dig_min; - } - - } else { - dm_dig->rx_gain_max = dm_dig_max; - dig_min_0 = dm_dig_min; - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n"); - } - - if (rtlpriv->falsealm_cnt.cnt_all > 10000) { - if (dm_dig->large_fa_hit != 3) - dm_dig->large_fa_hit++; - if (dm_dig->forbidden_igi < current_igi) { - dm_dig->forbidden_igi = current_igi; - dm_dig->large_fa_hit = 1; - } - - if (dm_dig->large_fa_hit >= 3) { - if (dm_dig->forbidden_igi + 1 > dm_dig->rx_gain_max) - dm_dig->rx_gain_min = - dm_dig->rx_gain_max; - else - dm_dig->rx_gain_min = - dm_dig->forbidden_igi + 1; - dm_dig->recover_cnt = 3600; - } - } else { - if (dm_dig->recover_cnt != 0) { - dm_dig->recover_cnt--; - } else { - if (dm_dig->large_fa_hit < 3) { - if ((dm_dig->forbidden_igi - 1) < - dig_min_0) { - dm_dig->forbidden_igi = dig_min_0; - dm_dig->rx_gain_min = - dig_min_0; - } else { - dm_dig->forbidden_igi--; - dm_dig->rx_gain_min = - dm_dig->forbidden_igi + 1; - } - } else { - dm_dig->large_fa_hit = 0; - } - } - } - - if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 5) - dm_dig->rx_gain_min = dm_dig_min; - - if (dm_dig->rx_gain_min > dm_dig->rx_gain_max) - dm_dig->rx_gain_min = dm_dig->rx_gain_max; - - if (mac->link_state >= MAC80211_LINKED) { - if (bfirstconnect) { - if (dm_dig->rssi_val_min <= dig_maxofmin) - current_igi = dm_dig->rssi_val_min; - else - current_igi = dig_maxofmin; - - dm_dig->large_fa_hit = 0; - } else { - if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2) - current_igi += 4; - else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1) - current_igi += 2; - else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) - current_igi -= 2; - - if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 5 && - rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1) - current_igi = dm_dig->rx_gain_min; - } - } else { - if (bfirstdisconnect) { - current_igi = dm_dig->rx_gain_min; - } else { - if (rtlpriv->falsealm_cnt.cnt_all > 10000) - current_igi += 4; - else if (rtlpriv->falsealm_cnt.cnt_all > 8000) - current_igi += 2; - else if (rtlpriv->falsealm_cnt.cnt_all < 500) - current_igi -= 2; - } - } - - if (current_igi > dm_dig->rx_gain_max) - current_igi = dm_dig->rx_gain_max; - if (current_igi < dm_dig->rx_gain_min) - current_igi = dm_dig->rx_gain_min; - - rtl92ee_dm_write_dig(hw , current_igi); - dm_dig->media_connect_0 = ((mac->link_state >= MAC80211_LINKED) ? - true : false); - dm_dig->dig_min_0 = dig_min_0; -} - -void rtl92ee_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 cur_thres) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_dig = &rtlpriv->dm_digtable; - - if (dm_dig->cur_cck_cca_thres != cur_thres) - rtl_write_byte(rtlpriv, DM_REG_CCK_CCA_11N, cur_thres); - - dm_dig->pre_cck_cca_thres = dm_dig->cur_cck_cca_thres; - dm_dig->cur_cck_cca_thres = cur_thres; -} - -void rtl92ee_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_dig = &rtlpriv->dm_digtable; - - if (dm_dig->stop_dig) - return; - - if (dm_dig->cur_igvalue != current_igi) { - rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi); - if (rtlpriv->phy.rf_type != RF_1T1R) - rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, current_igi); - } - dm_dig->pre_igvalue = dm_dig->cur_igvalue; - dm_dig->cur_igvalue = current_igi; -} - -static void rtl92ee_rssi_dump_to_register(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, RA_RSSIDUMP, - rtlpriv->stats.rx_rssi_percentage[0]); - rtl_write_byte(rtlpriv, RB_RSSIDUMP, - rtlpriv->stats.rx_rssi_percentage[1]); - /*It seems the following values are not initialized. - *According to Windows code, - *these value will only be valid with JAGUAR chips - */ - /* Rx EVM */ - rtl_write_byte(rtlpriv, RS1_RXEVMDUMP, rtlpriv->stats.rx_evm_dbm[0]); - rtl_write_byte(rtlpriv, RS2_RXEVMDUMP, rtlpriv->stats.rx_evm_dbm[1]); - /* Rx SNR */ - rtl_write_byte(rtlpriv, RA_RXSNRDUMP, - (u8)(rtlpriv->stats.rx_snr_db[0])); - rtl_write_byte(rtlpriv, RB_RXSNRDUMP, - (u8)(rtlpriv->stats.rx_snr_db[1])); - /* Rx Cfo_Short */ - rtl_write_word(rtlpriv, RA_CFOSHORTDUMP, - rtlpriv->stats.rx_cfo_short[0]); - rtl_write_word(rtlpriv, RB_CFOSHORTDUMP, - rtlpriv->stats.rx_cfo_short[1]); - /* Rx Cfo_Tail */ - rtl_write_word(rtlpriv, RA_CFOLONGDUMP, rtlpriv->stats.rx_cfo_tail[0]); - rtl_write_word(rtlpriv, RB_CFOLONGDUMP, rtlpriv->stats.rx_cfo_tail[1]); -} - -static void rtl92ee_dm_find_minimum_rssi(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable; - struct rtl_mac *mac = rtl_mac(rtlpriv); - - /* Determine the minimum RSSI */ - if ((mac->link_state < MAC80211_LINKED) && - (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { - rtl_dm_dig->min_undec_pwdb_for_dm = 0; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "Not connected to any\n"); - } - if (mac->link_state >= MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - rtl_dm_dig->min_undec_pwdb_for_dm = - rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "AP Client PWDB = 0x%lx\n", - rtlpriv->dm.entry_min_undec_sm_pwdb); - } else { - rtl_dm_dig->min_undec_pwdb_for_dm = - rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "STA Default Port PWDB = 0x%x\n", - rtl_dm_dig->min_undec_pwdb_for_dm); - } - } else { - rtl_dm_dig->min_undec_pwdb_for_dm = - rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "AP Ext Port or disconnet PWDB = 0x%x\n", - rtl_dm_dig->min_undec_pwdb_for_dm); - } - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "MinUndecoratedPWDBForDM =%d\n", - rtl_dm_dig->min_undec_pwdb_for_dm); -} - -static void rtl92ee_dm_check_rssi_monitor(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_dig = &rtlpriv->dm_digtable; - struct rtl_mac *mac = rtl_mac(rtlpriv); - struct rtl_dm *dm = rtl_dm(rtlpriv); - struct rtl_sta_info *drv_priv; - u8 h2c[4] = { 0 }; - long max = 0, min = 0xff; - u8 i = 0; - - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - /* AP & ADHOC & MESH */ - spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { - struct rssi_sta *stat = &drv_priv->rssi_stat; - - if (stat->undec_sm_pwdb < min) - min = stat->undec_sm_pwdb; - if (stat->undec_sm_pwdb > max) - max = stat->undec_sm_pwdb; - - h2c[3] = 0; - h2c[2] = (u8)(dm->undec_sm_pwdb & 0xFF); - h2c[1] = 0x20; - h2c[0] = ++i; - rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSSI_REPORT, 4, h2c); - } - spin_unlock_bh(&rtlpriv->locks.entry_list_lock); - - /* If associated entry is found */ - if (max != 0) { - dm->entry_max_undec_sm_pwdb = max; - RTPRINT(rtlpriv, FDM, DM_PWDB, - "EntryMaxPWDB = 0x%lx(%ld)\n", max, max); - } else { - dm->entry_max_undec_sm_pwdb = 0; - } - /* If associated entry is found */ - if (min != 0xff) { - dm->entry_min_undec_sm_pwdb = min; - RTPRINT(rtlpriv, FDM, DM_PWDB, - "EntryMinPWDB = 0x%lx(%ld)\n", min, min); - } else { - dm->entry_min_undec_sm_pwdb = 0; - } - } - - /* Indicate Rx signal strength to FW. */ - if (dm->useramask) { - h2c[3] = 0; - h2c[2] = (u8)(dm->undec_sm_pwdb & 0xFF); - h2c[1] = 0x20; - h2c[0] = 0; - rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSSI_REPORT, 4, h2c); - } else { - rtl_write_byte(rtlpriv, 0x4fe, dm->undec_sm_pwdb); - } - rtl92ee_rssi_dump_to_register(hw); - rtl92ee_dm_find_minimum_rssi(hw); - dm_dig->rssi_val_min = rtlpriv->dm_digtable.min_undec_pwdb_for_dm; -} - -static void rtl92ee_dm_init_primary_cca_check(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct dynamic_primary_cca *primarycca = &rtlpriv->primarycca; - - rtlhal->rts_en = 0; - primarycca->dup_rts_flag = 0; - primarycca->intf_flag = 0; - primarycca->intf_type = 0; - primarycca->monitor_flag = 0; - primarycca->ch_offset = 0; - primarycca->mf_state = 0; -} - -static bool rtl92ee_dm_is_edca_turbo_disable(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->mac80211.mode == WIRELESS_MODE_B) - return true; - - return false; -} - -void rtl92ee_dm_init_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.current_turbo_edca = false; - rtlpriv->dm.is_cur_rdlstate = false; - rtlpriv->dm.is_any_nonbepkts = false; -} - -static void rtl92ee_dm_check_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - static u64 last_txok_cnt; - static u64 last_rxok_cnt; - u64 cur_txok_cnt = 0; - u64 cur_rxok_cnt = 0; - u32 edca_be_ul = 0x5ea42b; - u32 edca_be_dl = 0x5ea42b; /*not sure*/ - u32 edca_be = 0x5ea42b; - bool is_cur_rdlstate; - bool b_edca_turbo_on = false; - - if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100) - rtlpriv->dm.is_any_nonbepkts = true; - rtlpriv->dm.dbginfo.num_non_be_pkt = 0; - - cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; - cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; - - /*b_bias_on_rx = false;*/ - b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) && - (!rtlpriv->dm.disable_framebursting)) ? - true : false; - - if (rtl92ee_dm_is_edca_turbo_disable(hw)) - goto check_exit; - - if (b_edca_turbo_on) { - is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ? - true : false; - - edca_be = is_cur_rdlstate ? edca_be_dl : edca_be_ul; - rtl_write_dword(rtlpriv , REG_EDCA_BE_PARAM , edca_be); - rtlpriv->dm.is_cur_rdlstate = is_cur_rdlstate; - rtlpriv->dm.current_turbo_edca = true; - } else { - if (rtlpriv->dm.current_turbo_edca) { - u8 tmp = AC0_BE; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, - (u8 *)(&tmp)); - } - rtlpriv->dm.current_turbo_edca = false; - } - -check_exit: - rtlpriv->dm.is_any_nonbepkts = false; - last_txok_cnt = rtlpriv->stats.txbytesunicast; - last_rxok_cnt = rtlpriv->stats.rxbytesunicast; -} - -static void rtl92ee_dm_dynamic_edcca(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 reg_c50 , reg_c58; - bool fw_current_in_ps_mode = false; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_in_ps_mode)); - if (fw_current_in_ps_mode) - return; - - reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); - reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); - - if (reg_c50 > 0x28 && reg_c58 > 0x28) { - if (!rtlpriv->rtlhal.pre_edcca_enable) { - rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03); - rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00); - rtlpriv->rtlhal.pre_edcca_enable = true; - } - } else if (reg_c50 < 0x25 && reg_c58 < 0x25) { - if (rtlpriv->rtlhal.pre_edcca_enable) { - rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f); - rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f); - rtlpriv->rtlhal.pre_edcca_enable = false; - } - } -} - -static void rtl92ee_dm_adaptivity(struct ieee80211_hw *hw) -{ - rtl92ee_dm_dynamic_edcca(hw); -} - -static void rtl92ee_dm_write_dynamic_cca(struct ieee80211_hw *hw, - u8 cur_mf_state) -{ - struct dynamic_primary_cca *primarycca = &rtl_priv(hw)->primarycca; - - if (primarycca->mf_state != cur_mf_state) - rtl_set_bbreg(hw, DM_REG_L1SBD_PD_CH_11N, BIT(8) | BIT(7), - cur_mf_state); - - primarycca->mf_state = cur_mf_state; -} - -static void rtl92ee_dm_dynamic_primary_cca_ckeck(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt; - struct dynamic_primary_cca *primarycca = &rtlpriv->primarycca; - bool is40mhz = false; - u64 ofdm_cca, ofdm_fa, bw_usc_cnt, bw_lsc_cnt; - u8 sec_ch_offset; - u8 cur_mf_state; - static u8 count_down = MONITOR_TIME; - - ofdm_cca = falsealm_cnt->cnt_ofdm_cca; - ofdm_fa = falsealm_cnt->cnt_ofdm_fail; - bw_usc_cnt = falsealm_cnt->cnt_bw_usc; - bw_lsc_cnt = falsealm_cnt->cnt_bw_lsc; - is40mhz = rtlpriv->mac80211.bw_40; - sec_ch_offset = rtlpriv->mac80211.cur_40_prime_sc; - /* NIC: 2: sec is below, 1: sec is above */ - - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) { - cur_mf_state = MF_USC_LSC; - rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); - return; - } - - if (rtlpriv->mac80211.link_state < MAC80211_LINKED) - return; - - if (is40mhz) - return; - - if (primarycca->pricca_flag == 0) { - /* Primary channel is above - * NOTE: duplicate CTS can remove this condition - */ - if (sec_ch_offset == 2) { - if ((ofdm_cca > OFDMCCA_TH) && - (bw_lsc_cnt > (bw_usc_cnt + BW_IND_BIAS)) && - (ofdm_fa > (ofdm_cca >> 1))) { - primarycca->intf_type = 1; - primarycca->intf_flag = 1; - cur_mf_state = MF_USC; - rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); - primarycca->pricca_flag = 1; - } else if ((ofdm_cca > OFDMCCA_TH) && - (bw_lsc_cnt > (bw_usc_cnt + BW_IND_BIAS)) && - (ofdm_fa < (ofdm_cca >> 1))) { - primarycca->intf_type = 2; - primarycca->intf_flag = 1; - cur_mf_state = MF_USC; - rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); - primarycca->pricca_flag = 1; - primarycca->dup_rts_flag = 1; - rtlpriv->rtlhal.rts_en = 1; - } else { - primarycca->intf_type = 0; - primarycca->intf_flag = 0; - cur_mf_state = MF_USC_LSC; - rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); - rtlpriv->rtlhal.rts_en = 0; - primarycca->dup_rts_flag = 0; - } - } else if (sec_ch_offset == 1) { - if ((ofdm_cca > OFDMCCA_TH) && - (bw_usc_cnt > (bw_lsc_cnt + BW_IND_BIAS)) && - (ofdm_fa > (ofdm_cca >> 1))) { - primarycca->intf_type = 1; - primarycca->intf_flag = 1; - cur_mf_state = MF_LSC; - rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); - primarycca->pricca_flag = 1; - } else if ((ofdm_cca > OFDMCCA_TH) && - (bw_usc_cnt > (bw_lsc_cnt + BW_IND_BIAS)) && - (ofdm_fa < (ofdm_cca >> 1))) { - primarycca->intf_type = 2; - primarycca->intf_flag = 1; - cur_mf_state = MF_LSC; - rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); - primarycca->pricca_flag = 1; - primarycca->dup_rts_flag = 1; - rtlpriv->rtlhal.rts_en = 1; - } else { - primarycca->intf_type = 0; - primarycca->intf_flag = 0; - cur_mf_state = MF_USC_LSC; - rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); - rtlpriv->rtlhal.rts_en = 0; - primarycca->dup_rts_flag = 0; - } - } - } else {/* PrimaryCCA->PriCCA_flag==1 */ - count_down--; - if (count_down == 0) { - count_down = MONITOR_TIME; - primarycca->pricca_flag = 0; - cur_mf_state = MF_USC_LSC; - /* default */ - rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state); - rtlpriv->rtlhal.rts_en = 0; - primarycca->dup_rts_flag = 0; - primarycca->intf_type = 0; - primarycca->intf_flag = 0; - } - } -} - -static void rtl92ee_dm_dynamic_atc_switch(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - u8 crystal_cap; - u32 packet_count; - int cfo_khz_a , cfo_khz_b , cfo_ave = 0, adjust_xtal = 0; - int cfo_ave_diff; - - if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { - if (rtldm->atc_status == ATC_STATUS_OFF) { - rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), - ATC_STATUS_ON); - rtldm->atc_status = ATC_STATUS_ON; - } - /* Disable CFO tracking for BT */ - if (rtlpriv->cfg->ops->get_btc_status()) { - if (!rtlpriv->btcoexist.btc_ops-> - btc_is_bt_disabled(rtlpriv)) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, - "odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n"); - return; - } - } - /* Reset Crystal Cap */ - if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) { - rtldm->crystal_cap = rtlpriv->efuse.crystalcap; - crystal_cap = rtldm->crystal_cap & 0x3f; - rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, - (crystal_cap | (crystal_cap << 6))); - } - } else { - cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280; - cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280; - packet_count = rtldm->packet_count; - - if (packet_count == rtldm->packet_count_pre) - return; - - rtldm->packet_count_pre = packet_count; - - if (rtlpriv->phy.rf_type == RF_1T1R) - cfo_ave = cfo_khz_a; - else - cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1; - - cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ? - (rtldm->cfo_ave_pre - cfo_ave) : - (cfo_ave - rtldm->cfo_ave_pre); - - if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) { - rtldm->large_cfo_hit = 1; - return; - } - rtldm->large_cfo_hit = 0; - - rtldm->cfo_ave_pre = cfo_ave; - - if (cfo_ave >= -rtldm->cfo_threshold && - cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) { - if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) { - rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10; - rtldm->is_freeze = 1; - } else { - rtldm->cfo_threshold = CFO_THRESHOLD_XTAL; - } - } - - if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f) - adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1; - else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) && - rtlpriv->dm.crystal_cap > 0) - adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1; - - if (adjust_xtal != 0) { - rtldm->is_freeze = 0; - rtldm->crystal_cap += adjust_xtal; - - if (rtldm->crystal_cap > 0x3f) - rtldm->crystal_cap = 0x3f; - else if (rtldm->crystal_cap < 0) - rtldm->crystal_cap = 0; - - crystal_cap = rtldm->crystal_cap & 0x3f; - rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, - (crystal_cap | (crystal_cap << 6))); - } - - if (cfo_ave < CFO_THRESHOLD_ATC && - cfo_ave > -CFO_THRESHOLD_ATC) { - if (rtldm->atc_status == ATC_STATUS_ON) { - rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), - ATC_STATUS_OFF); - rtldm->atc_status = ATC_STATUS_OFF; - } - } else { - if (rtldm->atc_status == ATC_STATUS_OFF) { - rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), - ATC_STATUS_ON); - rtldm->atc_status = ATC_STATUS_ON; - } - } - } -} - -static void rtl92ee_dm_init_txpower_tracking(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *dm = rtl_dm(rtlpriv); - u8 path; - - dm->txpower_tracking = true; - dm->default_ofdm_index = 30; - dm->default_cck_index = 20; - - dm->swing_idx_cck_base = dm->default_cck_index; - dm->cck_index = dm->default_cck_index; - - for (path = RF90_PATH_A; path < MAX_RF_PATH; path++) { - dm->swing_idx_ofdm_base[path] = dm->default_ofdm_index; - dm->ofdm_index[path] = dm->default_ofdm_index; - dm->delta_power_index[path] = 0; - dm->delta_power_index_last[path] = 0; - dm->power_index_offset[path] = 0; - } -} - -void rtl92ee_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rate_adaptive *p_ra = &rtlpriv->ra; - - p_ra->ratr_state = DM_RATR_STA_INIT; - p_ra->pre_ratr_state = DM_RATR_STA_INIT; - - if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) - rtlpriv->dm.useramask = true; - else - rtlpriv->dm.useramask = false; - - p_ra->ldpc_thres = 35; - p_ra->use_ldpc = false; - p_ra->high_rssi_thresh_for_ra = 50; - p_ra->low_rssi_thresh_for_ra40m = 20; -} - -static bool _rtl92ee_dm_ra_state_check(struct ieee80211_hw *hw, - s32 rssi, u8 *ratr_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rate_adaptive *p_ra = &rtlpriv->ra; - const u8 go_up_gap = 5; - u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra; - u32 low_rssithresh_for_ra = p_ra->low_rssi_thresh_for_ra40m; - u8 state; - - /* Threshold Adjustment: - * when RSSI state trends to go up one or two levels, - * make sure RSSI is high enough. - * Here GoUpGap is added to solve - * the boundary's level alternation issue. - */ - switch (*ratr_state) { - case DM_RATR_STA_INIT: - case DM_RATR_STA_HIGH: - break; - case DM_RATR_STA_MIDDLE: - high_rssithresh_for_ra += go_up_gap; - break; - case DM_RATR_STA_LOW: - high_rssithresh_for_ra += go_up_gap; - low_rssithresh_for_ra += go_up_gap; - break; - default: - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "wrong rssi level setting %d !", *ratr_state); - break; - } - - /* Decide RATRState by RSSI. */ - if (rssi > high_rssithresh_for_ra) - state = DM_RATR_STA_HIGH; - else if (rssi > low_rssithresh_for_ra) - state = DM_RATR_STA_MIDDLE; - else - state = DM_RATR_STA_LOW; - - if (*ratr_state != state) { - *ratr_state = state; - return true; - } - - return false; -} - -static void rtl92ee_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rate_adaptive *p_ra = &rtlpriv->ra; - struct ieee80211_sta *sta = NULL; - - if (is_hal_stop(rtlhal)) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "driver is going to unload\n"); - return; - } - - if (!rtlpriv->dm.useramask) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "driver does not control rate adaptive mask\n"); - return; - } - - if (mac->link_state == MAC80211_LINKED && - mac->opmode == NL80211_IFTYPE_STATION) { - if (rtlpriv->dm.undec_sm_pwdb < p_ra->ldpc_thres) { - p_ra->use_ldpc = true; - p_ra->lower_rts_rate = true; - } else if (rtlpriv->dm.undec_sm_pwdb > - (p_ra->ldpc_thres - 5)) { - p_ra->use_ldpc = false; - p_ra->lower_rts_rate = false; - } - if (_rtl92ee_dm_ra_state_check(hw, rtlpriv->dm.undec_sm_pwdb, - &p_ra->ratr_state)) { - rcu_read_lock(); - sta = rtl_find_sta(hw, mac->bssid); - if (sta) - rtlpriv->cfg->ops->update_rate_tbl(hw, sta, - p_ra->ratr_state); - rcu_read_unlock(); - - p_ra->pre_ratr_state = p_ra->ratr_state; - } - } -} - -static void rtl92ee_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap; - - rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11)); - rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL; -} - -void rtl92ee_dm_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 cur_igvalue = rtl_get_bbreg(hw, DM_REG_IGI_A_11N, DM_BIT_IGI_11N); - - rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; - - rtl_dm_diginit(hw, cur_igvalue); - rtl92ee_dm_init_rate_adaptive_mask(hw); - rtl92ee_dm_init_primary_cca_check(hw); - rtl92ee_dm_init_edca_turbo(hw); - rtl92ee_dm_init_txpower_tracking(hw); - rtl92ee_dm_init_dynamic_atc_switch(hw); -} - -static void rtl92ee_dm_common_info_self_update(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_sta_info *drv_priv; - u8 cnt = 0; - - rtlpriv->dm.one_entry_only = false; - - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION && - rtlpriv->mac80211.link_state >= MAC80211_LINKED) { - rtlpriv->dm.one_entry_only = true; - return; - } - - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || - rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC || - rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) { - spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { - cnt++; - } - spin_unlock_bh(&rtlpriv->locks.entry_list_lock); - - if (cnt == 1) - rtlpriv->dm.one_entry_only = true; - } -} - -void rtl92ee_dm_dynamic_arfb_select(struct ieee80211_hw *hw, - u8 rate, bool collision_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rate >= DESC92C_RATEMCS8 && rate <= DESC92C_RATEMCS12) { - if (collision_state == 1) { - if (rate == DESC92C_RATEMCS12) { - rtl_write_dword(rtlpriv, REG_DARFRC, 0x0); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x07060501); - } else if (rate == DESC92C_RATEMCS11) { - rtl_write_dword(rtlpriv, REG_DARFRC, 0x0); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x07070605); - } else if (rate == DESC92C_RATEMCS10) { - rtl_write_dword(rtlpriv, REG_DARFRC, 0x0); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x08080706); - } else if (rate == DESC92C_RATEMCS9) { - rtl_write_dword(rtlpriv, REG_DARFRC, 0x0); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x08080707); - } else { - rtl_write_dword(rtlpriv, REG_DARFRC, 0x0); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x09090808); - } - } else { /* collision_state == 0 */ - if (rate == DESC92C_RATEMCS12) { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x05010000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x09080706); - } else if (rate == DESC92C_RATEMCS11) { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x06050000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x09080807); - } else if (rate == DESC92C_RATEMCS10) { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x07060000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x0a090908); - } else if (rate == DESC92C_RATEMCS9) { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x07070000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x0a090808); - } else { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x08080000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x0b0a0909); - } - } - } else { /* MCS13~MCS15, 1SS, G-mode */ - if (collision_state == 1) { - if (rate == DESC92C_RATEMCS15) { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x00000000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x05040302); - } else if (rate == DESC92C_RATEMCS14) { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x00000000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x06050302); - } else if (rate == DESC92C_RATEMCS13) { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x00000000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x07060502); - } else { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x00000000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x06050402); - } - } else{ /* collision_state == 0 */ - if (rate == DESC92C_RATEMCS15) { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x03020000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x07060504); - } else if (rate == DESC92C_RATEMCS14) { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x03020000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x08070605); - } else if (rate == DESC92C_RATEMCS13) { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x05020000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x09080706); - } else { - rtl_write_dword(rtlpriv, REG_DARFRC, - 0x04020000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, - 0x08070605); - } - } - } -} - -void rtl92ee_dm_watchdog(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool fw_current_inpsmode = false; - bool fw_ps_awake = true; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inpsmode)); - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, - (u8 *)(&fw_ps_awake)); - if (ppsc->p2p_ps_info.p2p_ps_mode) - fw_ps_awake = false; - - if ((ppsc->rfpwr_state == ERFON) && - ((!fw_current_inpsmode) && fw_ps_awake) && - (!ppsc->rfchange_inprogress)) { - rtl92ee_dm_common_info_self_update(hw); - rtl92ee_dm_false_alarm_counter_statistics(hw); - rtl92ee_dm_check_rssi_monitor(hw); - rtl92ee_dm_dig(hw); - rtl92ee_dm_adaptivity(hw); - rtl92ee_dm_cck_packet_detection_thresh(hw); - rtl92ee_dm_refresh_rate_adaptive_mask(hw); - rtl92ee_dm_check_edca_turbo(hw); - rtl92ee_dm_dynamic_atc_switch(hw); - rtl92ee_dm_dynamic_primary_cca_ckeck(hw); - } -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/dm.h b/drivers/net/wireless/rtlwifi/rtl8192ee/dm.h deleted file mode 100644 index 107d5a488fa8..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/dm.h +++ /dev/null @@ -1,251 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92E_DM_H__ -#define __RTL92E_DM_H__ - -#define OFDMCCA_TH 500 -#define BW_IND_BIAS 500 -#define MF_USC 2 -#define MF_LSC 1 -#define MF_USC_LSC 0 -#define MONITOR_TIME 30 - -#define MAIN_ANT 0 -#define AUX_ANT 1 -#define MAIN_ANT_CG_TRX 1 -#define AUX_ANT_CG_TRX 0 -#define MAIN_ANT_CGCS_RX 0 -#define AUX_ANT_CGCS_RX 1 - -/*RF REG LIST*/ -#define DM_REG_RF_MODE_11N 0x00 -#define DM_REG_RF_0B_11N 0x0B -#define DM_REG_CHNBW_11N 0x18 -#define DM_REG_T_METER_11N 0x24 -#define DM_REG_RF_25_11N 0x25 -#define DM_REG_RF_26_11N 0x26 -#define DM_REG_RF_27_11N 0x27 -#define DM_REG_RF_2B_11N 0x2B -#define DM_REG_RF_2C_11N 0x2C -#define DM_REG_RXRF_A3_11N 0x3C -#define DM_REG_T_METER_92D_11N 0x42 -#define DM_REG_T_METER_92E_11N 0x42 - -/*BB REG LIST*/ -/*PAGE 8 */ -#define DM_REG_BB_CTRL_11N 0x800 -#define DM_REG_RF_PIN_11N 0x804 -#define DM_REG_PSD_CTRL_11N 0x808 -#define DM_REG_TX_ANT_CTRL_11N 0x80C -#define DM_REG_BB_PWR_SAV5_11N 0x818 -#define DM_REG_CCK_RPT_FORMAT_11N 0x824 -#define DM_REG_RX_DEFUALT_A_11N 0x858 -#define DM_REG_RX_DEFUALT_B_11N 0x85A -#define DM_REG_BB_PWR_SAV3_11N 0x85C -#define DM_REG_ANTSEL_CTRL_11N 0x860 -#define DM_REG_RX_ANT_CTRL_11N 0x864 -#define DM_REG_PIN_CTRL_11N 0x870 -#define DM_REG_BB_PWR_SAV1_11N 0x874 -#define DM_REG_ANTSEL_PATH_11N 0x878 -#define DM_REG_BB_3WIRE_11N 0x88C -#define DM_REG_SC_CNT_11N 0x8C4 -#define DM_REG_PSD_DATA_11N 0x8B4 -/*PAGE 9*/ -#define DM_REG_ANT_MAPPING1_11N 0x914 -#define DM_REG_ANT_MAPPING2_11N 0x918 -/*PAGE A*/ -#define DM_REG_CCK_ANTDIV_PARA1_11N 0xA00 -#define DM_REG_CCK_CCA_11N 0xA0A -#define DM_REG_CCK_ANTDIV_PARA2_11N 0xA0C -#define DM_REG_CCK_ANTDIV_PARA3_11N 0xA10 -#define DM_REG_CCK_ANTDIV_PARA4_11N 0xA14 -#define DM_REG_CCK_FILTER_PARA1_11N 0xA22 -#define DM_REG_CCK_FILTER_PARA2_11N 0xA23 -#define DM_REG_CCK_FILTER_PARA3_11N 0xA24 -#define DM_REG_CCK_FILTER_PARA4_11N 0xA25 -#define DM_REG_CCK_FILTER_PARA5_11N 0xA26 -#define DM_REG_CCK_FILTER_PARA6_11N 0xA27 -#define DM_REG_CCK_FILTER_PARA7_11N 0xA28 -#define DM_REG_CCK_FILTER_PARA8_11N 0xA29 -#define DM_REG_CCK_FA_RST_11N 0xA2C -#define DM_REG_CCK_FA_MSB_11N 0xA58 -#define DM_REG_CCK_FA_LSB_11N 0xA5C -#define DM_REG_CCK_CCA_CNT_11N 0xA60 -#define DM_REG_BB_PWR_SAV4_11N 0xA74 -/*PAGE B */ -#define DM_REG_LNA_SWITCH_11N 0xB2C -#define DM_REG_PATH_SWITCH_11N 0xB30 -#define DM_REG_RSSI_CTRL_11N 0xB38 -#define DM_REG_CONFIG_ANTA_11N 0xB68 -#define DM_REG_RSSI_BT_11N 0xB9C -/*PAGE C */ -#define DM_REG_OFDM_FA_HOLDC_11N 0xC00 -#define DM_REG_RX_PATH_11N 0xC04 -#define DM_REG_TRMUX_11N 0xC08 -#define DM_REG_OFDM_FA_RSTC_11N 0xC0C -#define DM_REG_RXIQI_MATRIX_11N 0xC14 -#define DM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C -#define DM_REG_IGI_A_11N 0xC50 -#define DM_REG_ANTDIV_PARA2_11N 0xC54 -#define DM_REG_IGI_B_11N 0xC58 -#define DM_REG_ANTDIV_PARA3_11N 0xC5C -#define DM_REG_L1SBD_PD_CH_11N 0XC6C -#define DM_REG_BB_PWR_SAV2_11N 0xC70 -#define DM_REG_RX_OFF_11N 0xC7C -#define DM_REG_TXIQK_MATRIXA_11N 0xC80 -#define DM_REG_TXIQK_MATRIXB_11N 0xC88 -#define DM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 -#define DM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C -#define DM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 -#define DM_REG_ANTDIV_PARA1_11N 0xCA4 -#define DM_REG_OFDM_FA_TYPE1_11N 0xCF0 -/*PAGE D */ -#define DM_REG_OFDM_FA_RSTD_11N 0xD00 -#define DM_REG_OFDM_FA_TYPE2_11N 0xDA0 -#define DM_REG_OFDM_FA_TYPE3_11N 0xDA4 -#define DM_REG_OFDM_FA_TYPE4_11N 0xDA8 -/*PAGE E */ -#define DM_REG_TXAGC_A_6_18_11N 0xE00 -#define DM_REG_TXAGC_A_24_54_11N 0xE04 -#define DM_REG_TXAGC_A_1_MCS32_11N 0xE08 -#define DM_REG_TXAGC_A_MCS0_3_11N 0xE10 -#define DM_REG_TXAGC_A_MCS4_7_11N 0xE14 -#define DM_REG_TXAGC_A_MCS8_11_11N 0xE18 -#define DM_REG_TXAGC_A_MCS12_15_11N 0xE1C -#define DM_REG_FPGA0_IQK_11N 0xE28 -#define DM_REG_TXIQK_TONE_A_11N 0xE30 -#define DM_REG_RXIQK_TONE_A_11N 0xE34 -#define DM_REG_TXIQK_PI_A_11N 0xE38 -#define DM_REG_RXIQK_PI_A_11N 0xE3C -#define DM_REG_TXIQK_11N 0xE40 -#define DM_REG_RXIQK_11N 0xE44 -#define DM_REG_IQK_AGC_PTS_11N 0xE48 -#define DM_REG_IQK_AGC_RSP_11N 0xE4C -#define DM_REG_BLUETOOTH_11N 0xE6C -#define DM_REG_RX_WAIT_CCA_11N 0xE70 -#define DM_REG_TX_CCK_RFON_11N 0xE74 -#define DM_REG_TX_CCK_BBON_11N 0xE78 -#define DM_REG_OFDM_RFON_11N 0xE7C -#define DM_REG_OFDM_BBON_11N 0xE80 -#define DM_REG_TX2RX_11N 0xE84 -#define DM_REG_TX2TX_11N 0xE88 -#define DM_REG_RX_CCK_11N 0xE8C -#define DM_REG_RX_OFDM_11N 0xED0 -#define DM_REG_RX_WAIT_RIFS_11N 0xED4 -#define DM_REG_RX2RX_11N 0xED8 -#define DM_REG_STANDBY_11N 0xEDC -#define DM_REG_SLEEP_11N 0xEE0 -#define DM_REG_PMPD_ANAEN_11N 0xEEC - -/*MAC REG LIST*/ -#define DM_REG_BB_RST_11N 0x02 -#define DM_REG_ANTSEL_PIN_11N 0x4C -#define DM_REG_EARLY_MODE_11N 0x4D0 -#define DM_REG_RSSI_MONITOR_11N 0x4FE -#define DM_REG_EDCA_VO_11N 0x500 -#define DM_REG_EDCA_VI_11N 0x504 -#define DM_REG_EDCA_BE_11N 0x508 -#define DM_REG_EDCA_BK_11N 0x50C -#define DM_REG_TXPAUSE_11N 0x522 -#define DM_REG_RESP_TX_11N 0x6D8 -#define DM_REG_ANT_TRAIN_PARA1_11N 0x7b0 -#define DM_REG_ANT_TRAIN_PARA2_11N 0x7b4 - -/*DIG Related*/ -#define DM_BIT_IGI_11N 0x0000007F - -#define HAL_DM_DIG_DISABLE BIT(0) -#define HAL_DM_HIPWR_DISABLE BIT(1) - -#define OFDM_TABLE_LENGTH 43 -#define CCK_TABLE_LENGTH 33 - -#define OFDM_TABLE_SIZE 43 -#define CCK_TABLE_SIZE 33 - -#define BW_AUTO_SWITCH_HIGH_LOW 25 -#define BW_AUTO_SWITCH_LOW_HIGH 30 - -#define DM_DIG_FA_UPPER 0x3e -#define DM_DIG_FA_LOWER 0x1e -#define DM_DIG_FA_TH0 0x200 -#define DM_DIG_FA_TH1 0x300 -#define DM_DIG_FA_TH2 0x400 - -#define RXPATHSELECTION_SS_TH_LOW 30 -#define RXPATHSELECTION_DIFF_TH 18 - -#define DM_RATR_STA_INIT 0 -#define DM_RATR_STA_HIGH 1 -#define DM_RATR_STA_MIDDLE 2 -#define DM_RATR_STA_LOW 3 - -#define CTS2SELF_THVAL 30 -#define REGC38_TH 20 - -#define WAIOTTHVAL 25 - -#define TXHIGHPWRLEVEL_NORMAL 0 -#define TXHIGHPWRLEVEL_LEVEL1 1 -#define TXHIGHPWRLEVEL_LEVEL2 2 -#define TXHIGHPWRLEVEL_BT1 3 -#define TXHIGHPWRLEVEL_BT2 4 - -#define DM_TYPE_BYFW 0 -#define DM_TYPE_BYDRIVER 1 - -#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 -#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 -#define TXPWRTRACK_MAX_IDX 6 - -/* Dynamic ATC switch */ -#define ATC_STATUS_OFF 0x0 /* enable */ -#define ATC_STATUS_ON 0x1 /* disable */ -#define CFO_THRESHOLD_XTAL 10 /* kHz */ -#define CFO_THRESHOLD_ATC 80 /* kHz */ - -/* RSSI Dump Message */ -#define RA_RSSIDUMP 0xcb0 -#define RB_RSSIDUMP 0xcb1 -#define RS1_RXEVMDUMP 0xcb2 -#define RS2_RXEVMDUMP 0xcb3 -#define RA_RXSNRDUMP 0xcb4 -#define RB_RXSNRDUMP 0xcb5 -#define RA_CFOSHORTDUMP 0xcb6 -#define RB_CFOSHORTDUMP 0xcb8 -#define RA_CFOLONGDUMP 0xcba -#define RB_CFOLONGDUMP 0xcbc - -void rtl92ee_dm_init(struct ieee80211_hw *hw); -void rtl92ee_dm_watchdog(struct ieee80211_hw *hw); -void rtl92ee_dm_write_cck_cca_thres(struct ieee80211_hw *hw, - u8 cur_thres); -void rtl92ee_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi); -void rtl92ee_dm_init_edca_turbo(struct ieee80211_hw *hw); -void rtl92ee_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); -void rtl92ee_dm_dynamic_arfb_select(struct ieee80211_hw *hw, - u8 rate, bool collision_state); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c deleted file mode 100644 index 0708eedd9671..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.c +++ /dev/null @@ -1,902 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "fw.h" -#include "dm.h" - -static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp; - - if (enable) { - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05); - - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); - rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); - } else { - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); - rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); - } -} - -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) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 *bufferptr = (u8 *)buffer; - u32 pagenums, remainsize; - u32 page, offset; - - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size); - - _rtl92ee_fill_dummy(bufferptr, &size); - - pagenums = size / FW_8192C_PAGE_SIZE; - remainsize = size % FW_8192C_PAGE_SIZE; - - if (pagenums > 8) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Page numbers should not greater then 8\n"); - } - - for (page = 0; page < pagenums; page++) { - offset = page * FW_8192C_PAGE_SIZE; - _rtl92ee_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); - } -} - -static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int err = -EIO; - u32 counter = 0; - u32 value32; - - do { - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) && - (!(value32 & FWDL_CHKSUM_RPT))); - - if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "chksum report faill ! REG_MCUFWDL:0x%08x .\n", - value32); - goto exit; - } - - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); - - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - value32 |= MCUFWDL_RDY; - value32 &= ~WINTINI_RDY; - rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); - - rtl92ee_firmware_selfreset(hw); - counter = 0; - - do { - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - if (value32 & WINTINI_RDY) { - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , - "Polling FW ready success!! REG_MCUFWDL:0x%08x. count = %d\n", - value32, counter); - err = 0; - goto exit; - } - - udelay(FW_8192C_POLLING_DELAY*10); - - } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT); - - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n", - value32, counter); - -exit: - return err; -} - -int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtlwifi_firmware_header *pfwheader; - u8 *pfwdata; - u32 fwsize; - int err; - enum version_8192e version = rtlhal->version; - - if (!rtlhal->pfirmware) - return 1; - - pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; - rtlhal->fw_version = le16_to_cpu(pfwheader->version); - rtlhal->fw_subversion = pfwheader->subversion; - pfwdata = (u8 *)rtlhal->pfirmware; - fwsize = rtlhal->fwsize; - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "normal Firmware SIZE %d\n" , fwsize); - - if (IS_FW_HEADER_EXIST(pfwheader)) { - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "Firmware Version(%d), Signature(%#x),Size(%d)\n", - pfwheader->version, pfwheader->signature, - (int)sizeof(struct rtlwifi_firmware_header)); - - pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); - fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); - } else { - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "Firmware no Header, Signature(%#x)\n", - pfwheader->signature); - } - - if (rtlhal->mac_func_enable) { - if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); - rtl92ee_firmware_selfreset(hw); - } - } - _rtl92ee_enable_fw_download(hw, true); - _rtl92ee_write_fw(hw, version, pfwdata, fwsize); - _rtl92ee_enable_fw_download(hw, false); - - err = _rtl92ee_fw_free_to_go(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Firmware is not ready to run!\n"); - } else { - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , - "Firmware is ready to run!\n"); - } - - return 0; -} - -static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 val_hmetfr; - bool result = false; - - val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); - if (((val_hmetfr >> boxnum) & BIT(0)) == 0) - result = true; - return result; -} - -static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *cmdbuffer) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 boxnum; - u16 box_reg = 0, box_extreg = 0; - u8 u1b_tmp; - bool isfw_read = false; - u8 buf_index = 0; - bool bwrite_sucess = false; - u8 wait_h2c_limmit = 100; - u8 boxcontent[4], boxextcontent[4]; - u32 h2c_waitcounter = 0; - unsigned long flag; - u8 idx; - - if (ppsc->dot11_psmode != EACTIVE || - ppsc->inactive_pwrstate == ERFOFF) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , - "FillH2CCommand8192E(): Return because RF is off!!!\n"); - return; - } - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n"); - - /* 1. Prevent race condition in setting H2C cmd. - * (copy from MgntActSet_RF_State().) - */ - while (true) { - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - if (rtlhal->h2c_setinprogress) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , - "H2C set in progress! Wait to set..element_id(%d).\n", - element_id); - - while (rtlhal->h2c_setinprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, - flag); - h2c_waitcounter++; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , - "Wait 100 us (%d times)...\n", - h2c_waitcounter); - udelay(100); - - if (h2c_waitcounter > 1000) - return; - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, - flag); - } - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - } else { - rtlhal->h2c_setinprogress = true; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - break; - } - } - - while (!bwrite_sucess) { - /* 2. Find the last BOX number which has been writen. */ - boxnum = rtlhal->last_hmeboxnum; - switch (boxnum) { - case 0: - box_reg = REG_HMEBOX_0; - box_extreg = REG_HMEBOX_EXT_0; - break; - case 1: - box_reg = REG_HMEBOX_1; - box_extreg = REG_HMEBOX_EXT_1; - break; - case 2: - box_reg = REG_HMEBOX_2; - box_extreg = REG_HMEBOX_EXT_2; - break; - case 3: - box_reg = REG_HMEBOX_3; - box_extreg = REG_HMEBOX_EXT_3; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - - /* 3. Check if the box content is empty. */ - isfw_read = false; - u1b_tmp = rtl_read_byte(rtlpriv, REG_CR); - - if (u1b_tmp != 0xea) { - isfw_read = true; - } else { - if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea || - rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea) - rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff); - } - - if (isfw_read) { - wait_h2c_limmit = 100; - isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum); - while (!isfw_read) { - wait_h2c_limmit--; - if (wait_h2c_limmit == 0) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , - "Waiting too long for FW read clear HMEBox(%d)!!!\n", - boxnum); - break; - } - udelay(10); - isfw_read = - _rtl92ee_check_fw_read_last_h2c(hw, boxnum); - u1b_tmp = rtl_read_byte(rtlpriv, 0x130); - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , - "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", - boxnum, u1b_tmp); - } - } - - /* If Fw has not read the last - * H2C cmd, break and give up this H2C. - */ - if (!isfw_read) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , - "Write H2C reg BOX[%d] fail,Fw don't read.\n", - boxnum); - break; - } - /* 4. Fill the H2C cmd into box */ - memset(boxcontent, 0, sizeof(boxcontent)); - memset(boxextcontent, 0, sizeof(boxextcontent)); - boxcontent[0] = element_id; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , - "Write element_id box_reg(%4x) = %2x\n", - box_reg, element_id); - - switch (cmd_len) { - case 1: - case 2: - case 3: - /*boxcontent[0] &= ~(BIT(7));*/ - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index, cmd_len); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - case 4: - case 5: - case 6: - case 7: - /*boxcontent[0] |= (BIT(7));*/ - memcpy((u8 *)(boxextcontent), - cmdbuffer + buf_index+3, cmd_len-3); - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index, 3); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_extreg + idx, - boxextcontent[idx]); - } - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - - bwrite_sucess = true; - - rtlhal->last_hmeboxnum = boxnum + 1; - if (rtlhal->last_hmeboxnum == 4) - rtlhal->last_hmeboxnum = 0; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , - "pHalData->last_hmeboxnum = %d\n", - rtlhal->last_hmeboxnum); - } - - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - rtlhal->h2c_setinprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n"); -} - -void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, u8 *cmdbuffer) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 tmp_cmdbuf[2]; - - if (!rtlhal->fw_ready) { - RT_ASSERT(false, - "return H2C cmd because of Fw download fail!!!\n"); - return; - } - - memset(tmp_cmdbuf, 0, 8); - memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); - _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); -} - -void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw) -{ - u8 u1b_tmp; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); - - udelay(50); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0))); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2))); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD , - " _8051Reset92E(): 8051 reset success .\n"); -} - -void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 }; - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 rlbm , power_state = 0; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , "FW LPS mode = %d\n", mode); - - SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); - rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/ - SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); - SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, - (rtlpriv->mac80211.p2p) ? - ppsc->smart_ps : 1); - SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, - ppsc->reg_max_lps_awakeintvl); - SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); - if (mode == FW_PS_ACTIVE_MODE) - power_state |= FW_PWR_STATE_ACTIVE; - else - power_state |= FW_PWR_STATE_RF_OFF; - SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", - u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH); - rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH, - u1_h2c_set_pwrmode); -} - -void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus) -{ - u8 parm[3] = { 0 , 0 , 0 }; - /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect - * bit1=0-->update Media Status to MACID - * bit1=1-->update Media Status from MACID to MACID_End - * parm[1]: MACID, if this is INFRA_STA, MacID = 0 - * parm[2]: MACID_End - */ - - SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); - SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); - - rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm); -} - -#define BEACON_PG 0 /* ->1 */ -#define PSPOLL_PG 2 -#define NULL_PG 3 -#define PROBERSP_PG 4 /* ->5 */ - -#define TOTAL_RESERVED_PKT_LEN 768 - -static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { - /* page 0 beacon */ - 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, - 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65, - 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B, - 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06, - 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, - 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, - 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, - 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, - 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, - 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00, - - /* page 1 beacon */ - 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 2 ps-poll */ - 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B, - 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 3 null */ - 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B, - 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, - 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 4 probe_resp */ - 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, - 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, - 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, - 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, - 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, - 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, - 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, - 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, - 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 5 probe_resp */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct sk_buff *skb = NULL; - - u32 totalpacketlen; - u8 u1rsvdpageloc[5] = { 0 }; - bool b_dlok = false; - - u8 *beacon; - u8 *p_pspoll; - u8 *nullfunc; - u8 *p_probersp; - /*--------------------------------------------------------- - * (1) beacon - *--------------------------------------------------------- - */ - beacon = &reserved_page_packet[BEACON_PG * 128]; - SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); - SET_80211_HDR_ADDRESS3(beacon, mac->bssid); - - /*------------------------------------------------------- - * (2) ps-poll - *-------------------------------------------------------- - */ - p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; - SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); - SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); - SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); - - SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); - - /*-------------------------------------------------------- - * (3) null data - *--------------------------------------------------------- - */ - nullfunc = &reserved_page_packet[NULL_PG * 128]; - SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); - SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); - SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); - - /*--------------------------------------------------------- - * (4) probe response - *---------------------------------------------------------- - */ - p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; - SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); - SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); - SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); - - totalpacketlen = TOTAL_RESERVED_PKT_LEN; - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , - "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", - &reserved_page_packet[0], totalpacketlen); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , - "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", - u1rsvdpageloc, 3); - - skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); - - b_dlok = true; - - if (b_dlok) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , - "Set RSVD page location to Fw.\n"); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD , - "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3); - rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE, - sizeof(u1rsvdpageloc), u1rsvdpageloc); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set RSVD page location to Fw FAIL!!!!!!.\n"); - } -} - -/*Shoud check FW support p2p or not.*/ -static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) -{ - u8 u1_ctwindow_period[1] = {ctwindow}; - - rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); -} - -void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info; - struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; - u8 i; - u16 ctwindow; - u32 start_time, tsf_low; - - switch (p2p_ps_state) { - case P2P_PS_DISABLE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n"); - memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); - break; - case P2P_PS_ENABLE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n"); - /* update CTWindow value. */ - if (p2pinfo->ctwindow > 0) { - p2p_ps_offload->ctwindow_en = 1; - ctwindow = p2pinfo->ctwindow; - rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow); - } - /* hw only support 2 set of NoA */ - for (i = 0 ; i < p2pinfo->noa_num ; i++) { - /* To control the register setting for which NOA*/ - rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); - if (i == 0) - p2p_ps_offload->noa0_en = 1; - else - p2p_ps_offload->noa1_en = 1; - /* config P2P NoA Descriptor Register */ - rtl_write_dword(rtlpriv, 0x5E0, - p2pinfo->noa_duration[i]); - rtl_write_dword(rtlpriv, 0x5E4, - p2pinfo->noa_interval[i]); - - /*Get Current TSF value */ - tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - - start_time = p2pinfo->noa_start_time[i]; - if (p2pinfo->noa_count_type[i] != 1) { - while (start_time <= (tsf_low + (50 * 1024))) { - start_time += p2pinfo->noa_interval[i]; - if (p2pinfo->noa_count_type[i] != 255) - p2pinfo->noa_count_type[i]--; - } - } - rtl_write_dword(rtlpriv, 0x5E8, start_time); - rtl_write_dword(rtlpriv, 0x5EC, - p2pinfo->noa_count_type[i]); - } - if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { - /* rst p2p circuit */ - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); - p2p_ps_offload->offload_en = 1; - - if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { - p2p_ps_offload->role = 1; - p2p_ps_offload->allstasleep = 0; - } else { - p2p_ps_offload->role = 0; - } - p2p_ps_offload->discovery = 0; - } - break; - case P2P_PS_SCAN: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n"); - p2p_ps_offload->discovery = 1; - break; - case P2P_PS_SCAN_DONE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n"); - p2p_ps_offload->discovery = 0; - p2pinfo->p2p_ps_state = P2P_PS_ENABLE; - break; - default: - break; - } - rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1, - (u8 *)p2p_ps_offload); -} - -static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw, - u8 *cmd_buf, u8 cmd_len) -{ - u8 rate = cmd_buf[0] & 0x3F; - bool collision_state = cmd_buf[3] & BIT(0); - - rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state); -} - -static void _rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id, - u8 c2h_cmd_len, u8 *tmp_buf) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - switch (c2h_cmd_id) { - case C2H_8192E_DBG: - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H], C2H_8723BE_DBG!!\n"); - break; - case C2H_8192E_TXBF: - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H], C2H_8192E_TXBF!!\n"); - break; - case C2H_8192E_TX_REPORT: - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE , - "[C2H], C2H_8723BE_TX_REPORT!\n"); - break; - case C2H_8192E_BT_INFO: - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H], C2H_8723BE_BT_INFO!!\n"); - rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf, - c2h_cmd_len); - break; - case C2H_8192E_BT_MP: - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H], C2H_8723BE_BT_MP!!\n"); - break; - case C2H_8192E_RA_RPT: - _rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len); - break; - default: - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id); - break; - } -} - -void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0; - u8 *tmp_buf = NULL; - - c2h_cmd_id = buffer[0]; - c2h_cmd_seq = buffer[1]; - c2h_cmd_len = len - 2; - tmp_buf = buffer + 2; - - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n", - c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len); - - RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len); - - _rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.h b/drivers/net/wireless/rtlwifi/rtl8192ee/fw.h deleted file mode 100644 index 069da1e7e80a..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/fw.h +++ /dev/null @@ -1,189 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92E__FW__H__ -#define __RTL92E__FW__H__ - -#define FW_8192C_SIZE 0x8000 -#define FW_8192C_START_ADDRESS 0x1000 -#define FW_8192C_END_ADDRESS 0x5FFF -#define FW_8192C_PAGE_SIZE 4096 -#define FW_8192C_POLLING_DELAY 5 -#define FW_8192C_POLLING_TIMEOUT_COUNT 3000 - -#define IS_FW_HEADER_EXIST(_pfwhdr) \ - ((le16_to_cpu(_pfwhdr->signature) & 0xFFF0) == 0x92E0) -#define USE_OLD_WOWLAN_DEBUG_FW 0 - -#define H2C_92E_RSVDPAGE_LOC_LEN 5 -#define H2C_92E_PWEMODE_LENGTH 5 -#define H2C_92E_JOINBSSRPT_LENGTH 1 -#define H2C_92E_AP_OFFLOAD_LENGTH 3 -#define H2C_92E_WOWLAN_LENGTH 3 -#define H2C_92E_KEEP_ALIVE_CTRL_LENGTH 3 -#if (USE_OLD_WOWLAN_DEBUG_FW == 0) -#define H2C_92E_REMOTE_WAKE_CTRL_LEN 1 -#else -#define H2C_92E_REMOTE_WAKE_CTRL_LEN 3 -#endif -#define H2C_92E_AOAC_GLOBAL_INFO_LEN 2 -#define H2C_92E_AOAC_RSVDPAGE_LOC_LEN 7 - -/* Fw PS state for RPWM. -*BIT[2:0] = HW state -*BIT[3] = Protocol PS state, 1: register active state, 0: register sleep state -*BIT[4] = sub-state -*/ -#define FW_PS_RF_ON BIT(2) -#define FW_PS_REGISTER_ACTIVE BIT(3) - -#define FW_PS_ACK BIT(6) -#define FW_PS_TOGGLE BIT(7) - - /* 92E RPWM value*/ - /* BIT[0] = 1: 32k, 0: 40M*/ -#define FW_PS_CLOCK_OFF BIT(0) /* 32k */ -#define FW_PS_CLOCK_ON 0 /* 40M */ - -#define FW_PS_STATE_MASK (0x0F) -#define FW_PS_STATE_HW_MASK (0x07) -#define FW_PS_STATE_INT_MASK (0x3F) - -#define FW_PS_STATE(x) (FW_PS_STATE_MASK & (x)) - -#define FW_PS_STATE_ALL_ON_92E (FW_PS_CLOCK_ON) -#define FW_PS_STATE_RF_ON_92E (FW_PS_CLOCK_ON) -#define FW_PS_STATE_RF_OFF_92E (FW_PS_CLOCK_ON) -#define FW_PS_STATE_RF_OFF_LOW_PWR (FW_PS_CLOCK_OFF) - -/* For 92E H2C PwrMode Cmd ID 5.*/ -#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) -#define FW_PWR_STATE_RF_OFF 0 - -#define FW_PS_IS_ACK(x) ((x) & FW_PS_ACK) - -#define IS_IN_LOW_POWER_STATE_92E(__state) \ - (FW_PS_STATE(__state) == FW_PS_CLOCK_OFF) - -#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) -#define FW_PWR_STATE_RF_OFF 0 - -enum rtl8192e_h2c_cmd { - H2C_92E_RSVDPAGE = 0, - H2C_92E_MSRRPT = 1, - H2C_92E_SCAN = 2, - H2C_92E_KEEP_ALIVE_CTRL = 3, - H2C_92E_DISCONNECT_DECISION = 4, -#if (USE_OLD_WOWLAN_DEBUG_FW == 1) - H2C_92E_WO_WLAN = 5, -#endif - H2C_92E_INIT_OFFLOAD = 6, -#if (USE_OLD_WOWLAN_DEBUG_FW == 1) - H2C_92E_REMOTE_WAKE_CTRL = 7, -#endif - H2C_92E_AP_OFFLOAD = 8, - H2C_92E_BCN_RSVDPAGE = 9, - H2C_92E_PROBERSP_RSVDPAGE = 10, - - H2C_92E_SETPWRMODE = 0x20, - H2C_92E_PS_TUNING_PARA = 0x21, - H2C_92E_PS_TUNING_PARA2 = 0x22, - H2C_92E_PS_LPS_PARA = 0x23, - H2C_92E_P2P_PS_OFFLOAD = 024, - -#if (USE_OLD_WOWLAN_DEBUG_FW == 0) - H2C_92E_WO_WLAN = 0x80, - H2C_92E_REMOTE_WAKE_CTRL = 0x81, - H2C_92E_AOAC_GLOBAL_INFO = 0x82, - H2C_92E_AOAC_RSVDPAGE = 0x83, -#endif - H2C_92E_RA_MASK = 0x40, - H2C_92E_RSSI_REPORT = 0x42, - H2C_92E_SELECTIVE_SUSPEND_ROF_CMD, - H2C_92E_P2P_PS_MODE, - H2C_92E_PSD_RESULT, - /*Not defined CTW CMD for P2P yet*/ - H2C_92E_P2P_PS_CTW_CMD, - MAX_92E_H2CCMD -}; - -enum rtl8192e_c2h_evt { - C2H_8192E_DBG = 0, - C2H_8192E_LB = 1, - C2H_8192E_TXBF = 2, - C2H_8192E_TX_REPORT = 3, - C2H_8192E_BT_INFO = 9, - C2H_8192E_BT_MP = 11, - C2H_8192E_RA_RPT = 12, - MAX_8192E_C2HEVENT -}; - -#define pagenum_128(_len) \ - (u32)(((_len) >> 7) + ((_len) & 0x7F ? 1 : 0)) - -#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_RLBM(__cmd, __val) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 4, __val) -#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__cmd, __val) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 4, 4, __val) -#define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__cmd, __val) \ - SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__cmd, __val) \ - SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __val) \ - SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __val) -#define GET_92E_H2CCMD_PWRMODE_PARM_MODE(__cmd) \ - LE_BITS_TO_1BYTE(__cmd, 0, 8) - -#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) - -/* _MEDIA_STATUS_RPT_PARM_CMD1 */ -#define SET_H2CCMD_MSRRPT_PARM_OPMODE(__cmd, __val) \ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __val) -#define SET_H2CCMD_MSRRPT_PARM_MACID_IND(__cmd, __val) \ - SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __val) -#define SET_H2CCMD_MSRRPT_PARM_MACID(__cmd, __val) \ - SET_BITS_TO_LE_1BYTE(__cmd+1, 0, 8, __val) -#define SET_H2CCMD_MSRRPT_PARM_MACID_END(__cmd, __val) \ - SET_BITS_TO_LE_1BYTE(__cmd+2, 0, 8, __val) - -int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw); -void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *cmdbuffer); -void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw); -void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); -void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus); -void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); -void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); -void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c deleted file mode 100644 index 5f14308e8eb3..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c +++ /dev/null @@ -1,2666 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../efuse.h" -#include "../base.h" -#include "../regd.h" -#include "../cam.h" -#include "../ps.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "fw.h" -#include "led.h" -#include "hw.h" -#include "../pwrseqcmd.h" -#include "pwrseq.h" - -#define LLT_CONFIG 5 - -static void _rtl92ee_set_bcn_ctrl_reg(struct ieee80211_hw *hw, - u8 set_bits, u8 clear_bits) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpci->reg_bcn_ctrl_val |= set_bits; - rtlpci->reg_bcn_ctrl_val &= ~clear_bits; - - rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); -} - -static void _rtl92ee_stop_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp; - - tmp = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp & (~BIT(6))); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); - tmp = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp); -} - -static void _rtl92ee_resume_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp; - - tmp = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp | BIT(6)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - tmp = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp |= BIT(0); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp); -} - -static void _rtl92ee_enable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(1)); -} - -static void _rtl92ee_disable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl92ee_set_bcn_ctrl_reg(hw, BIT(1), 0); -} - -static void _rtl92ee_set_fw_clock_on(struct ieee80211_hw *hw, - u8 rpwm_val, bool b_need_turn_off_ckk) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool b_support_remote_wake_up; - u32 count = 0, isr_regaddr, content; - bool b_schedule_timer = b_need_turn_off_ckk; - - rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, - (u8 *)(&b_support_remote_wake_up)); - - if (!rtlhal->fw_ready) - return; - if (!rtlpriv->psc.fw_current_inpsmode) - return; - - while (1) { - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - if (rtlhal->fw_clk_change_in_progress) { - while (rtlhal->fw_clk_change_in_progress) { - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - count++; - udelay(100); - if (count > 1000) - return; - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - } - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - } else { - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - break; - } - } - - if (IS_IN_LOW_POWER_STATE_92E(rtlhal->fw_ps_state)) { - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - if (FW_PS_IS_ACK(rpwm_val)) { - isr_regaddr = REG_HISR; - content = rtl_read_dword(rtlpriv, isr_regaddr); - while (!(content & IMR_CPWM) && (count < 500)) { - udelay(50); - count++; - content = rtl_read_dword(rtlpriv, isr_regaddr); - } - - if (content & IMR_CPWM) { - rtl_write_word(rtlpriv, isr_regaddr, 0x0100); - rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_92E; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Receive CPWM INT!!! PSState = %X\n", - rtlhal->fw_ps_state); - } - } - - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - if (b_schedule_timer) { - mod_timer(&rtlpriv->works.fw_clockoff_timer, - jiffies + MSECS(10)); - } - } else { - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - } -} - -static void _rtl92ee_set_fw_clock_off(struct ieee80211_hw *hw, u8 rpwm_val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring; - enum rf_pwrstate rtstate; - bool b_schedule_timer = false; - u8 queue; - - if (!rtlhal->fw_ready) - return; - if (!rtlpriv->psc.fw_current_inpsmode) - return; - if (!rtlhal->allow_sw_to_change_hwclc) - return; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate)); - if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF) - return; - - for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) { - ring = &rtlpci->tx_ring[queue]; - if (skb_queue_len(&ring->queue)) { - b_schedule_timer = true; - break; - } - } - - if (b_schedule_timer) { - mod_timer(&rtlpriv->works.fw_clockoff_timer, - jiffies + MSECS(10)); - return; - } - - if (FW_PS_STATE(rtlhal->fw_ps_state) != FW_PS_STATE_RF_OFF_LOW_PWR) { - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - if (!rtlhal->fw_clk_change_in_progress) { - rtlhal->fw_clk_change_in_progress = true; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); - rtl_write_word(rtlpriv, REG_HISR, 0x0100); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - } else { - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - mod_timer(&rtlpriv->works.fw_clockoff_timer, - jiffies + MSECS(10)); - } - } -} - -static void _rtl92ee_set_fw_ps_rf_on(struct ieee80211_hw *hw) -{ - u8 rpwm_val = 0; - - rpwm_val |= (FW_PS_STATE_RF_OFF_92E | FW_PS_ACK); - _rtl92ee_set_fw_clock_on(hw, rpwm_val, true); -} - -static void _rtl92ee_set_fw_ps_rf_off_low_power(struct ieee80211_hw *hw) -{ - u8 rpwm_val = 0; - - rpwm_val |= FW_PS_STATE_RF_OFF_LOW_PWR; - _rtl92ee_set_fw_clock_off(hw, rpwm_val); -} - -void rtl92ee_fw_clk_off_timer_callback(unsigned long data) -{ - struct ieee80211_hw *hw = (struct ieee80211_hw *)data; - - _rtl92ee_set_fw_ps_rf_off_low_power(hw); -} - -static void _rtl92ee_fwlps_leave(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool fw_current_inps = false; - u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE; - - if (ppsc->low_power_enable) { - rpwm_val = (FW_PS_STATE_ALL_ON_92E | FW_PS_ACK);/* RF on */ - _rtl92ee_set_fw_clock_on(hw, rpwm_val, false); - rtlhal->allow_sw_to_change_hwclc = false; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - } else { - rpwm_val = FW_PS_STATE_ALL_ON_92E; /* RF on */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - } -} - -static void _rtl92ee_fwlps_enter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool fw_current_inps = true; - u8 rpwm_val; - - if (ppsc->low_power_enable) { - rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR; /* RF off */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); - rtlhal->allow_sw_to_change_hwclc = true; - _rtl92ee_set_fw_clock_off(hw, rpwm_val); - } else { - rpwm_val = FW_PS_STATE_RF_OFF_92E; /* RF off */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - } -} - -void rtl92ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - switch (variable) { - case HW_VAR_RCR: - *((u32 *)(val)) = rtlpci->receive_config; - break; - case HW_VAR_RF_STATE: - *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; - break; - case HW_VAR_FWLPS_RF_ON:{ - enum rf_pwrstate rfstate; - u32 val_rcr; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, - (u8 *)(&rfstate)); - if (rfstate == ERFOFF) { - *((bool *)(val)) = true; - } else { - val_rcr = rtl_read_dword(rtlpriv, REG_RCR); - val_rcr &= 0x00070000; - if (val_rcr) - *((bool *)(val)) = false; - else - *((bool *)(val)) = true; - } - } - break; - case HW_VAR_FW_PSMODE_STATUS: - *((bool *)(val)) = ppsc->fw_current_inpsmode; - break; - case HW_VAR_CORRECT_TSF:{ - u64 tsf; - u32 *ptsf_low = (u32 *)&tsf; - u32 *ptsf_high = ((u32 *)&tsf) + 1; - - *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); - *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - - *((u64 *)(val)) = tsf; - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, - "switch case not process %x\n", variable); - break; - } -} - -static void _rtl92ee_download_rsvd_page(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp_regcr, tmp_reg422; - u8 bcnvalid_reg, txbc_reg; - u8 count = 0, dlbcn_count = 0; - bool b_recover = false; - - /*Set REG_CR bit 8. DMA beacon by SW.*/ - tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, tmp_regcr | BIT(0)); - - /* Disable Hw protection for a time which revserd for Hw sending beacon. - * Fix download reserved page packet fail - * that access collision with the protection time. - * 2010.05.11. Added by tynli. - */ - _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); - _rtl92ee_set_bcn_ctrl_reg(hw, BIT(4), 0); - - /* Set FWHW_TXQ_CTRL 0x422[6]=0 to - * tell Hw the packet is not a real beacon frame. - */ - tmp_reg422 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422 & (~BIT(6))); - - if (tmp_reg422 & BIT(6)) - b_recover = true; - - do { - /* Clear beacon valid check bit */ - bcnvalid_reg = rtl_read_byte(rtlpriv, REG_DWBCN0_CTRL + 2); - rtl_write_byte(rtlpriv, REG_DWBCN0_CTRL + 2, - bcnvalid_reg | BIT(0)); - - /* download rsvd page */ - rtl92ee_set_fw_rsvdpagepkt(hw, false); - - txbc_reg = rtl_read_byte(rtlpriv, REG_MGQ_TXBD_NUM + 3); - count = 0; - while ((txbc_reg & BIT(4)) && count < 20) { - count++; - udelay(10); - txbc_reg = rtl_read_byte(rtlpriv, REG_MGQ_TXBD_NUM + 3); - } - rtl_write_byte(rtlpriv, REG_MGQ_TXBD_NUM + 3, - txbc_reg | BIT(4)); - - /* check rsvd page download OK. */ - bcnvalid_reg = rtl_read_byte(rtlpriv, REG_DWBCN0_CTRL + 2); - count = 0; - while (!(bcnvalid_reg & BIT(0)) && count < 20) { - count++; - udelay(50); - bcnvalid_reg = rtl_read_byte(rtlpriv, - REG_DWBCN0_CTRL + 2); - } - - if (bcnvalid_reg & BIT(0)) - rtl_write_byte(rtlpriv, REG_DWBCN0_CTRL + 2, BIT(0)); - - dlbcn_count++; - } while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5); - - if (!(bcnvalid_reg & BIT(0))) - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Download RSVD page failed!\n"); - - /* Enable Bcn */ - _rtl92ee_set_bcn_ctrl_reg(hw, BIT(3), 0); - _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); - - if (b_recover) - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422); - - tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, tmp_regcr & (~BIT(0))); -} - -void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *efuse = rtl_efuse(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 idx; - - switch (variable) { - case HW_VAR_ETHER_ADDR: - for (idx = 0; idx < ETH_ALEN; idx++) - rtl_write_byte(rtlpriv, (REG_MACID + idx), val[idx]); - break; - case HW_VAR_BASIC_RATE:{ - u16 b_rate_cfg = ((u16 *)val)[0]; - - b_rate_cfg = b_rate_cfg & 0x15f; - b_rate_cfg |= 0x01; - b_rate_cfg = (b_rate_cfg | 0xd) & (~BIT(1)); - rtl_write_byte(rtlpriv, REG_RRSR, b_rate_cfg & 0xff); - rtl_write_byte(rtlpriv, REG_RRSR + 1, (b_rate_cfg >> 8) & 0xff); - break; } - case HW_VAR_BSSID: - for (idx = 0; idx < ETH_ALEN; idx++) - rtl_write_byte(rtlpriv, (REG_BSSID + idx), val[idx]); - break; - case HW_VAR_SIFS: - rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); - rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); - - rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); - rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); - - if (!mac->ht_enable) - rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, 0x0e0e); - else - rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, - *((u16 *)val)); - break; - case HW_VAR_SLOT_TIME:{ - u8 e_aci; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_TRACE, - "HW_VAR_SLOT_TIME %x\n", val[0]); - - rtl_write_byte(rtlpriv, REG_SLOT, val[0]); - - for (e_aci = 0; e_aci < AC_MAX; e_aci++) { - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, - (u8 *)(&e_aci)); - } - break; } - case HW_VAR_ACK_PREAMBLE:{ - u8 reg_tmp; - u8 short_preamble = (bool)(*(u8 *)val); - - reg_tmp = (rtlpriv->mac80211.cur_40_prime_sc) << 5; - if (short_preamble) - reg_tmp |= 0x80; - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp); - rtlpriv->mac80211.short_preamble = short_preamble; - } - break; - case HW_VAR_WPA_CONFIG: - rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); - break; - case HW_VAR_AMPDU_FACTOR:{ - u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; - u8 fac; - u8 *reg = NULL; - u8 i = 0; - - reg = regtoset_normal; - - fac = *((u8 *)val); - if (fac <= 3) { - fac = (1 << (fac + 2)); - if (fac > 0xf) - fac = 0xf; - for (i = 0; i < 4; i++) { - if ((reg[i] & 0xf0) > (fac << 4)) - reg[i] = (reg[i] & 0x0f) | - (fac << 4); - if ((reg[i] & 0x0f) > fac) - reg[i] = (reg[i] & 0xf0) | fac; - rtl_write_byte(rtlpriv, - (REG_AGGLEN_LMT + i), - reg[i]); - } - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_FACTOR:%#x\n", fac); - } - } - break; - case HW_VAR_AC_PARAM:{ - u8 e_aci = *((u8 *)val); - - if (rtlpci->acm_method != EACMWAY2_SW) - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, - (u8 *)(&e_aci)); - } - break; - case HW_VAR_ACM_CTRL:{ - u8 e_aci = *((u8 *)val); - union aci_aifsn *aifs = (union aci_aifsn *)(&mac->ac[0].aifs); - - u8 acm = aifs->f.acm; - u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); - - acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); - - if (acm) { - switch (e_aci) { - case AC0_BE: - acm_ctrl |= ACMHW_BEQEN; - break; - case AC2_VI: - acm_ctrl |= ACMHW_VIQEN; - break; - case AC3_VO: - acm_ctrl |= ACMHW_VOQEN; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", - acm); - break; - } - } else { - switch (e_aci) { - case AC0_BE: - acm_ctrl &= (~ACMHW_BEQEN); - break; - case AC2_VI: - acm_ctrl &= (~ACMHW_VIQEN); - break; - case AC3_VO: - acm_ctrl &= (~ACMHW_VOQEN); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, - "switch case not process\n"); - break; - } - } - - RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, - "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", - acm_ctrl); - rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); - } - break; - case HW_VAR_RCR:{ - rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); - rtlpci->receive_config = ((u32 *)(val))[0]; - } - break; - case HW_VAR_RETRY_LIMIT:{ - u8 retry_limit = ((u8 *)(val))[0]; - - rtl_write_word(rtlpriv, REG_RETRY_LIMIT, - retry_limit << RETRY_LIMIT_SHORT_SHIFT | - retry_limit << RETRY_LIMIT_LONG_SHIFT); - } - break; - case HW_VAR_DUAL_TSF_RST: - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); - break; - case HW_VAR_EFUSE_BYTES: - efuse->efuse_usedbytes = *((u16 *)val); - break; - case HW_VAR_EFUSE_USAGE: - efuse->efuse_usedpercentage = *((u8 *)val); - break; - case HW_VAR_IO_CMD: - rtl92ee_phy_set_io_cmd(hw, (*(enum io_type *)val)); - break; - case HW_VAR_SET_RPWM:{ - u8 rpwm_val; - - rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); - udelay(1); - - if (rpwm_val & BIT(7)) { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, (*(u8 *)val)); - } else { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, - ((*(u8 *)val) | BIT(7))); - } - } - break; - case HW_VAR_H2C_FW_PWRMODE: - rtl92ee_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); - break; - case HW_VAR_FW_PSMODE_STATUS: - ppsc->fw_current_inpsmode = *((bool *)val); - break; - case HW_VAR_RESUME_CLK_ON: - _rtl92ee_set_fw_ps_rf_on(hw); - break; - case HW_VAR_FW_LPS_ACTION:{ - bool b_enter_fwlps = *((bool *)val); - - if (b_enter_fwlps) - _rtl92ee_fwlps_enter(hw); - else - _rtl92ee_fwlps_leave(hw); - } - break; - case HW_VAR_H2C_FW_JOINBSSRPT:{ - u8 mstatus = (*(u8 *)val); - - if (mstatus == RT_MEDIA_CONNECT) { - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL); - _rtl92ee_download_rsvd_page(hw); - } - rtl92ee_set_fw_media_status_rpt_cmd(hw, mstatus); - } - break; - case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: - rtl92ee_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); - break; - case HW_VAR_AID:{ - u16 u2btmp; - - u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); - u2btmp &= 0xC000; - rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, - (u2btmp | mac->assoc_id)); - } - break; - case HW_VAR_CORRECT_TSF:{ - u8 btype_ibss = ((u8 *)(val))[0]; - - if (btype_ibss) - _rtl92ee_stop_tx_beacon(hw); - - _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(3)); - - rtl_write_dword(rtlpriv, REG_TSFTR, - (u32)(mac->tsf & 0xffffffff)); - rtl_write_dword(rtlpriv, REG_TSFTR + 4, - (u32)((mac->tsf >> 32) & 0xffffffff)); - - _rtl92ee_set_bcn_ctrl_reg(hw, BIT(3), 0); - - if (btype_ibss) - _rtl92ee_resume_tx_beacon(hw); - } - break; - case HW_VAR_KEEP_ALIVE: { - u8 array[2]; - - array[0] = 0xff; - array[1] = *((u8 *)val); - rtl92ee_fill_h2c_cmd(hw, H2C_92E_KEEP_ALIVE_CTRL, 2, array); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, - "switch case not process %x\n", variable); - break; - } -} - -static bool _rtl92ee_llt_table_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 txpktbuf_bndy; - u8 u8tmp, testcnt = 0; - - txpktbuf_bndy = 0xFA; - - rtl_write_dword(rtlpriv, REG_RQPN, 0x80E90808); - - rtl_write_byte(rtlpriv, REG_TRXFF_BNDY, txpktbuf_bndy); - rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x3d00 - 1); - - rtl_write_byte(rtlpriv, REG_DWBCN0_CTRL + 1, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_DWBCN1_CTRL + 1, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, REG_BCNQ_BDNY, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_BCNQ1_BDNY, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, REG_MGQ_BDNY, txpktbuf_bndy); - rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, REG_PBP, 0x31); - rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); - - u8tmp = rtl_read_byte(rtlpriv, REG_AUTO_LLT + 2); - rtl_write_byte(rtlpriv, REG_AUTO_LLT + 2, u8tmp | BIT(0)); - - while (u8tmp & BIT(0)) { - u8tmp = rtl_read_byte(rtlpriv, REG_AUTO_LLT + 2); - udelay(10); - testcnt++; - if (testcnt > 10) - break; - } - - return true; -} - -static void _rtl92ee_gen_refresh_led_state(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pled0 = &pcipriv->ledctl.sw_led0; - - if (rtlpriv->rtlhal.up_first_time) - return; - - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtl92ee_sw_led_on(hw, pled0); - else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - rtl92ee_sw_led_on(hw, pled0); - else - rtl92ee_sw_led_off(hw, pled0); -} - -static bool _rtl92ee_init_mac(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - u8 bytetmp; - u16 wordtmp; - u32 dwordtmp; - - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0); - - dwordtmp = rtl_read_dword(rtlpriv, REG_SYS_CFG1); - if (dwordtmp & BIT(24)) { - rtl_write_byte(rtlpriv, 0x7c, 0xc3); - } else { - bytetmp = rtl_read_byte(rtlpriv, 0x16); - rtl_write_byte(rtlpriv, 0x16, bytetmp | BIT(4) | BIT(6)); - rtl_write_byte(rtlpriv, 0x7c, 0x83); - } - /* 1. 40Mhz crystal source*/ - bytetmp = rtl_read_byte(rtlpriv, REG_AFE_CTRL2); - bytetmp &= 0xfb; - rtl_write_byte(rtlpriv, REG_AFE_CTRL2, bytetmp); - - dwordtmp = rtl_read_dword(rtlpriv, REG_AFE_CTRL4); - dwordtmp &= 0xfffffc7f; - rtl_write_dword(rtlpriv, REG_AFE_CTRL4, dwordtmp); - - /* 2. 92E AFE parameter - * MP chip then check version - */ - bytetmp = rtl_read_byte(rtlpriv, REG_AFE_CTRL2); - bytetmp &= 0xbf; - rtl_write_byte(rtlpriv, REG_AFE_CTRL2, bytetmp); - - dwordtmp = rtl_read_dword(rtlpriv, REG_AFE_CTRL4); - dwordtmp &= 0xffdfffff; - rtl_write_dword(rtlpriv, REG_AFE_CTRL4, dwordtmp); - - /* HW Power on sequence */ - if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, - RTL8192E_NIC_ENABLE_FLOW)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "init MAC Fail as rtl_hal_pwrseqcmdparsing\n"); - return false; - } - - /* Release MAC IO register reset */ - bytetmp = rtl_read_byte(rtlpriv, REG_CR); - bytetmp = 0xff; - rtl_write_byte(rtlpriv, REG_CR, bytetmp); - mdelay(2); - bytetmp = 0x7f; - rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, bytetmp); - mdelay(2); - - /* Add for wakeup online */ - bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR); - rtl_write_byte(rtlpriv, REG_SYS_CLKR, bytetmp | BIT(3)); - bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG + 1); - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG + 1, bytetmp & (~BIT(4))); - /* Release MAC IO register reset */ - rtl_write_word(rtlpriv, REG_CR, 0x2ff); - - if (!rtlhal->mac_func_enable) { - if (_rtl92ee_llt_table_init(hw) == false) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "LLT table init fail\n"); - return false; - } - } - - rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); - rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff); - - wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); - wordtmp &= 0xf; - wordtmp |= 0xF5B1; - rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); - /* Reported Tx status from HW for rate adaptive.*/ - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); - - /* Set RCR register */ - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xffff); - - /* Set TCR register */ - rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); - - /* Set TX/RX descriptor physical address(from OS API). */ - rtl_write_dword(rtlpriv, REG_BCNQ_DESA, - ((u64)rtlpci->tx_ring[BEACON_QUEUE].buffer_desc_dma) & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_MGQ_DESA, - (u64)rtlpci->tx_ring[MGNT_QUEUE].buffer_desc_dma & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VOQ_DESA, - (u64)rtlpci->tx_ring[VO_QUEUE].buffer_desc_dma & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VIQ_DESA, - (u64)rtlpci->tx_ring[VI_QUEUE].buffer_desc_dma & - DMA_BIT_MASK(32)); - - rtl_write_dword(rtlpriv, REG_BEQ_DESA, - (u64)rtlpci->tx_ring[BE_QUEUE].buffer_desc_dma & - DMA_BIT_MASK(32)); - - dwordtmp = rtl_read_dword(rtlpriv, REG_BEQ_DESA); - - rtl_write_dword(rtlpriv, REG_BKQ_DESA, - (u64)rtlpci->tx_ring[BK_QUEUE].buffer_desc_dma & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_HQ0_DESA, - (u64)rtlpci->tx_ring[HIGH_QUEUE].buffer_desc_dma & - DMA_BIT_MASK(32)); - - rtl_write_dword(rtlpriv, REG_RX_DESA, - (u64)rtlpci->rx_ring[RX_MPDU_QUEUE].dma & - DMA_BIT_MASK(32)); - - /* if we want to support 64 bit DMA, we should set it here, - * but now we do not support 64 bit DMA - */ - - rtl_write_dword(rtlpriv, REG_TSFTIMER_HCI, 0x3fffffff); - - bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 3); - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, bytetmp | 0xF7); - - rtl_write_dword(rtlpriv, REG_INT_MIG, 0); - - rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); - - rtl_write_word(rtlpriv, REG_MGQ_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_VOQ_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_VIQ_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_BEQ_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_VOQ_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_BKQ_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_HI0Q_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_HI1Q_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_HI2Q_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_HI3Q_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_HI4Q_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_HI5Q_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_HI6Q_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - rtl_write_word(rtlpriv, REG_HI7Q_TXBD_NUM, - TX_DESC_NUM_92E | ((RTL8192EE_SEG_NUM << 12) & 0x3000)); - /*Rx*/ -#if (DMA_IS_64BIT == 1) - rtl_write_word(rtlpriv, REG_RX_RXBD_NUM, - RX_DESC_NUM_92E | - ((RTL8192EE_SEG_NUM << 13) & 0x6000) | 0x8000); -#else - rtl_write_word(rtlpriv, REG_RX_RXBD_NUM, - RX_DESC_NUM_92E | - ((RTL8192EE_SEG_NUM << 13) & 0x6000) | 0x0000); -#endif - - rtl_write_dword(rtlpriv, REG_TSFTIMER_HCI, 0XFFFFFFFF); - - _rtl92ee_gen_refresh_led_state(hw); - return true; -} - -static void _rtl92ee_hw_configure(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u32 reg_rrsr; - - reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - /* Init value for RRSR. */ - rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr); - - /* ARFB table 9 for 11ac 5G 2SS */ - rtl_write_dword(rtlpriv, REG_ARFR0, 0x00000010); - rtl_write_dword(rtlpriv, REG_ARFR0 + 4, 0x3e0ff000); - - /* ARFB table 10 for 11ac 5G 1SS */ - rtl_write_dword(rtlpriv, REG_ARFR1, 0x00000010); - rtl_write_dword(rtlpriv, REG_ARFR1 + 4, 0x000ff000); - - /* Set SLOT time */ - rtl_write_byte(rtlpriv, REG_SLOT, 0x09); - - /* CF-End setting. */ - rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80); - - /* Set retry limit */ - rtl_write_word(rtlpriv, REG_RETRY_LIMIT, 0x0707); - - /* BAR settings */ - rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x0201ffff); - - /* Set Data / Response auto rate fallack retry count */ - rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); - rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); - - /* Beacon related, for rate adaptive */ - rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); - rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff); - - rtlpci->reg_bcn_ctrl_val = 0x1d; - rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); - - /* Marked out by Bruce, 2010-09-09. - * This register is configured for the 2nd Beacon (multiple BSSID). - * We shall disable this register if we only support 1 BSSID. - * vivi guess 92d also need this, also 92d now doesnot set this reg - */ - rtl_write_byte(rtlpriv, REG_BCN_CTRL_1, 0); - - /* TBTT prohibit hold time. Suggested by designer TimChen. */ - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); /* 8 ms */ - - rtl_write_byte(rtlpriv, REG_PIFS, 0); - rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); - - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040); - rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x08ff); - - /* For Rx TP. Suggested by SD1 Richard. Added by tynli. 2010.04.12.*/ - rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); - - /* ACKTO for IOT issue. */ - rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); - - /* Set Spec SIFS (used in NAV) */ - rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x100a); - rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x100a); - - /* Set SIFS for CCK */ - rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x100a); - - /* Set SIFS for OFDM */ - rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x100a); - - /* Note Data sheet don't define */ - rtl_write_word(rtlpriv, 0x4C7, 0x80); - - rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20); - - rtl_write_word(rtlpriv, REG_MAX_AGGR_NUM, 0x1717); - - /* Set Multicast Address. 2009.01.07. by tynli. */ - rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff); - rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff); -} - -static void _rtl92ee_enable_aspm_back_door(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u32 tmp32 = 0, count = 0; - u8 tmp8 = 0; - - rtl_write_word(rtlpriv, REG_BACKDOOR_DBI_DATA, 0x78); - rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2, 0x2); - tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); - count = 0; - while (tmp8 && count < 20) { - udelay(10); - tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); - count++; - } - - if (0 == tmp8) { - tmp32 = rtl_read_dword(rtlpriv, REG_BACKDOOR_DBI_RDATA); - if ((tmp32 & 0xff00) != 0x2000) { - tmp32 &= 0xffff00ff; - rtl_write_dword(rtlpriv, REG_BACKDOOR_DBI_WDATA, - tmp32 | BIT(13)); - rtl_write_word(rtlpriv, REG_BACKDOOR_DBI_DATA, 0xf078); - rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2, 0x1); - - tmp8 = rtl_read_byte(rtlpriv, - REG_BACKDOOR_DBI_DATA + 2); - count = 0; - while (tmp8 && count < 20) { - udelay(10); - tmp8 = rtl_read_byte(rtlpriv, - REG_BACKDOOR_DBI_DATA + 2); - count++; - } - } - } - - rtl_write_word(rtlpriv, REG_BACKDOOR_DBI_DATA, 0x70c); - rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2, 0x2); - tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); - count = 0; - while (tmp8 && count < 20) { - udelay(10); - tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); - count++; - } - if (0 == tmp8) { - tmp32 = rtl_read_dword(rtlpriv, REG_BACKDOOR_DBI_RDATA); - rtl_write_dword(rtlpriv, REG_BACKDOOR_DBI_WDATA, - tmp32 | BIT(31)); - rtl_write_word(rtlpriv, REG_BACKDOOR_DBI_DATA, 0xf70c); - rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2, 0x1); - } - - tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); - count = 0; - while (tmp8 && count < 20) { - udelay(10); - tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); - count++; - } - - rtl_write_word(rtlpriv, REG_BACKDOOR_DBI_DATA, 0x718); - rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2, 0x2); - tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); - count = 0; - while (tmp8 && count < 20) { - udelay(10); - tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); - count++; - } - if (ppsc->support_backdoor || (0 == tmp8)) { - tmp32 = rtl_read_dword(rtlpriv, REG_BACKDOOR_DBI_RDATA); - rtl_write_dword(rtlpriv, REG_BACKDOOR_DBI_WDATA, - tmp32 | BIT(11) | BIT(12)); - rtl_write_word(rtlpriv, REG_BACKDOOR_DBI_DATA, 0xf718); - rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2, 0x1); - } - tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); - count = 0; - while (tmp8 && count < 20) { - udelay(10); - tmp8 = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 2); - count++; - } -} - -void rtl92ee_enable_hw_security_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 sec_reg_value; - u8 tmp; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", - rtlpriv->sec.pairwise_enc_algorithm, - rtlpriv->sec.group_enc_algorithm); - - if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "not open hw encryption\n"); - return; - } - - sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; - - if (rtlpriv->sec.use_defaultkey) { - sec_reg_value |= SCR_TXUSEDK; - sec_reg_value |= SCR_RXUSEDK; - } - - sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); - - tmp = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, tmp | BIT(1)); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "The SECR-value %x\n", sec_reg_value); - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); -} - -static bool _rtl8192ee_check_pcie_dma_hang(struct rtl_priv *rtlpriv) -{ - u8 tmp; - - /* write reg 0x350 Bit[26]=1. Enable debug port. */ - tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3); - if (!(tmp & BIT(2))) { - rtl_write_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3, - tmp | BIT(2)); - mdelay(100); /* Suggested by DD Justin_tsai. */ - } - - /* read reg 0x350 Bit[25] if 1 : RX hang - * read reg 0x350 Bit[24] if 1 : TX hang - */ - tmp = rtl_read_byte(rtlpriv, REG_BACKDOOR_DBI_DATA + 3); - if ((tmp & BIT(0)) || (tmp & BIT(1))) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "CheckPcieDMAHang8192EE(): true!!\n"); - return true; - } - return false; -} - -static void _rtl8192ee_reset_pcie_interface_dma(struct rtl_priv *rtlpriv, - bool mac_power_on) -{ - u8 tmp; - bool release_mac_rx_pause; - u8 backup_pcie_dma_pause; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "ResetPcieInterfaceDMA8192EE()\n"); - - /* Revise Note: Follow the document "PCIe RX DMA Hang Reset Flow_v03" - * released by SD1 Alan. - */ - - /* 1. disable register write lock - * write 0x1C bit[1:0] = 2'h0 - * write 0xCC bit[2] = 1'b1 - */ - tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL); - tmp &= ~(BIT(1) | BIT(0)); - rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp); - tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); - tmp |= BIT(2); - rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); - - /* 2. Check and pause TRX DMA - * write 0x284 bit[18] = 1'b1 - * write 0x301 = 0xFF - */ - tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - if (tmp & BIT(2)) { - /* Already pause before the function for another reason. */ - release_mac_rx_pause = false; - } else { - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2))); - release_mac_rx_pause = true; - } - - backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1); - if (backup_pcie_dma_pause != 0xFF) - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF); - - if (mac_power_on) { - /* 3. reset TRX function - * write 0x100 = 0x00 - */ - rtl_write_byte(rtlpriv, REG_CR, 0); - } - - /* 4. Reset PCIe DMA - * write 0x003 bit[0] = 0 - */ - tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - tmp &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); - - /* 5. Enable PCIe DMA - * write 0x003 bit[0] = 1 - */ - tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - tmp |= BIT(0); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); - - if (mac_power_on) { - /* 6. enable TRX function - * write 0x100 = 0xFF - */ - rtl_write_byte(rtlpriv, REG_CR, 0xFF); - - /* We should init LLT & RQPN and - * prepare Tx/Rx descrptor address later - * because MAC function is reset. - */ - } - - /* 7. Restore PCIe autoload down bit - * write 0xF8 bit[17] = 1'b1 - */ - tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2); - tmp |= BIT(1); - rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp); - - /* In MAC power on state, BB and RF maybe in ON state, - * if we release TRx DMA here - * it will cause packets to be started to Tx/Rx, - * so we release Tx/Rx DMA later. - */ - if (!mac_power_on) { - /* 8. release TRX DMA - * write 0x284 bit[18] = 1'b0 - * write 0x301 = 0x00 - */ - if (release_mac_rx_pause) { - tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, - (tmp & (~BIT(2)))); - } - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, - backup_pcie_dma_pause); - } - - /* 9. lock system register - * write 0xCC bit[2] = 1'b0 - */ - tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); - tmp &= ~(BIT(2)); - rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); -} - -int rtl92ee_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool rtstatus = true; - int err = 0; - u8 tmp_u1b, u1byte; - u32 tmp_u4b; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, " Rtl8192EE hw init\n"); - rtlpriv->rtlhal.being_init_adapter = true; - rtlpriv->intf_ops->disable_aspm(hw); - - tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CLKR+1); - u1byte = rtl_read_byte(rtlpriv, REG_CR); - if ((tmp_u1b & BIT(3)) && (u1byte != 0 && u1byte != 0xEA)) { - rtlhal->mac_func_enable = true; - } else { - rtlhal->mac_func_enable = false; - rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_92E; - } - - if (_rtl8192ee_check_pcie_dma_hang(rtlpriv)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "92ee dma hang!\n"); - _rtl8192ee_reset_pcie_interface_dma(rtlpriv, - rtlhal->mac_func_enable); - rtlhal->mac_func_enable = false; - } - - rtstatus = _rtl92ee_init_mac(hw); - - rtl_write_byte(rtlpriv, 0x577, 0x03); - - /*for Crystal 40 Mhz setting */ - rtl_write_byte(rtlpriv, REG_AFE_CTRL4, 0x2A); - rtl_write_byte(rtlpriv, REG_AFE_CTRL4 + 1, 0x00); - rtl_write_byte(rtlpriv, REG_AFE_CTRL2, 0x83); - - /*Forced the antenna b to wifi */ - if (rtlpriv->btcoexist.btc_info.btcoexist == 1) { - rtl_write_byte(rtlpriv, 0x64, 0); - rtl_write_byte(rtlpriv, 0x65, 1); - } - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); - err = 1; - return err; - } - rtlhal->rx_tag = 0; - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, 0x8000); - err = rtl92ee_download_fw(hw, false); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Failed to download FW. Init HW without FW now..\n"); - err = 1; - rtlhal->fw_ready = false; - return err; - } - rtlhal->fw_ready = true; - /*fw related variable initialize */ - ppsc->fw_current_inpsmode = false; - rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_92E; - rtlhal->fw_clk_change_in_progress = false; - rtlhal->allow_sw_to_change_hwclc = false; - rtlhal->last_hmeboxnum = 0; - - rtl92ee_phy_mac_config(hw); - - rtl92ee_phy_bb_config(hw); - - rtl92ee_phy_rf_config(hw); - - rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, RF90_PATH_A, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, RF90_PATH_B, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtlphy->backup_rf_0x1a = (u32)rtl_get_rfreg(hw, RF90_PATH_A, RF_RX_G1, - RFREG_OFFSET_MASK); - rtlphy->rfreg_chnlval[0] = (rtlphy->rfreg_chnlval[0] & 0xfffff3ff) | - BIT(10) | BIT(11); - - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - - /*---- Set CCK and OFDM Block "ON"----*/ - rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); - - /* Must set this, - * otherwise the rx sensitivity will be very pool. Maddest - */ - rtl_set_rfreg(hw, RF90_PATH_A, 0xB1, RFREG_OFFSET_MASK, 0x54418); - - /*Set Hardware(MAC default setting.)*/ - _rtl92ee_hw_configure(hw); - - rtlhal->mac_func_enable = true; - - rtl_cam_reset_all_entry(hw); - rtl92ee_enable_hw_security_config(hw); - - ppsc->rfpwr_state = ERFON; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); - _rtl92ee_enable_aspm_back_door(hw); - rtlpriv->intf_ops->enable_aspm(hw); - - rtl92ee_bt_hw_init(hw); - - rtlpriv->rtlhal.being_init_adapter = false; - - if (ppsc->rfpwr_state == ERFON) { - if (rtlphy->iqk_initialized) { - rtl92ee_phy_iq_calibrate(hw, true); - } else { - rtl92ee_phy_iq_calibrate(hw, false); - rtlphy->iqk_initialized = true; - } - } - - rtlphy->rfpath_rx_enable[0] = true; - if (rtlphy->rf_type == RF_2T2R) - rtlphy->rfpath_rx_enable[1] = true; - - efuse_one_byte_read(hw, 0x1FA, &tmp_u1b); - if (!(tmp_u1b & BIT(0))) { - rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "PA BIAS path A\n"); - } - - if ((!(tmp_u1b & BIT(1))) && (rtlphy->rf_type == RF_2T2R)) { - rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0F, 0x05); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "PA BIAS path B\n"); - } - - rtl_write_byte(rtlpriv, REG_NAV_UPPER, ((30000 + 127) / 128)); - - /*Fixed LDPC rx hang issue. */ - tmp_u4b = rtl_read_dword(rtlpriv, REG_SYS_SWR_CTRL1); - rtl_write_byte(rtlpriv, REG_SYS_SWR_CTRL2, 0x75); - tmp_u4b = (tmp_u4b & 0xfff00fff) | (0x7E << 12); - rtl_write_dword(rtlpriv, REG_SYS_SWR_CTRL1, tmp_u4b); - - rtl92ee_dm_init(hw); - - rtl_write_dword(rtlpriv, 0x4fc, 0); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "end of Rtl8192EE hw init %x\n", err); - return 0; -} - -static enum version_8192e _rtl92ee_read_chip_version(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - enum version_8192e version = VERSION_UNKNOWN; - u32 value32; - - rtlphy->rf_type = RF_2T2R; - - value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG1); - if (value32 & TRP_VAUX_EN) - version = (enum version_8192e)VERSION_TEST_CHIP_2T2R_8192E; - else - version = (enum version_8192e)VERSION_NORMAL_CHIP_2T2R_8192E; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ? - "RF_2T2R" : "RF_1T1R"); - - return version; -} - -static int _rtl92ee_set_media_status(struct ieee80211_hw *hw, - enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bt_msr = rtl_read_byte(rtlpriv, MSR) & 0xfc; - enum led_ctl_mode ledaction = LED_CTL_NO_LINK; - u8 mode = MSR_NOLINK; - - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - mode = MSR_NOLINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to NO LINK!\n"); - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - mode = MSR_ADHOC; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to Ad Hoc!\n"); - break; - case NL80211_IFTYPE_STATION: - mode = MSR_INFRA; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to STA!\n"); - break; - case NL80211_IFTYPE_AP: - mode = MSR_AP; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to AP!\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Network type %d not support!\n", type); - return 1; - } - - /* MSR_INFRA == Link in infrastructure network; - * MSR_ADHOC == Link in ad hoc network; - * Therefore, check link state is necessary. - * - * MSR_AP == AP mode; link state is not cared here. - */ - if (mode != MSR_AP && rtlpriv->mac80211.link_state < MAC80211_LINKED) { - mode = MSR_NOLINK; - ledaction = LED_CTL_NO_LINK; - } - - if (mode == MSR_NOLINK || mode == MSR_INFRA) { - _rtl92ee_stop_tx_beacon(hw); - _rtl92ee_enable_bcn_sub_func(hw); - } else if (mode == MSR_ADHOC || mode == MSR_AP) { - _rtl92ee_resume_tx_beacon(hw); - _rtl92ee_disable_bcn_sub_func(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", - mode); - } - - rtl_write_byte(rtlpriv, MSR, bt_msr | mode); - rtlpriv->cfg->ops->led_control(hw, ledaction); - if (mode == MSR_AP) - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); - else - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); - return 0; -} - -void rtl92ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u32 reg_rcr = rtlpci->receive_config; - - if (rtlpriv->psc.rfpwr_state != ERFON) - return; - - if (check_bssid) { - reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *)(®_rcr)); - _rtl92ee_set_bcn_ctrl_reg(hw, 0, BIT(4)); - } else { - reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); - _rtl92ee_set_bcn_ctrl_reg(hw, BIT(4), 0); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *)(®_rcr)); - } -} - -int rtl92ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (_rtl92ee_set_media_status(hw, type)) - return -EOPNOTSUPP; - - if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { - if (type != NL80211_IFTYPE_AP && - type != NL80211_IFTYPE_MESH_POINT) - rtl92ee_set_check_bssid(hw, true); - } else { - rtl92ee_set_check_bssid(hw, false); - } - - return 0; -} - -/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ -void rtl92ee_set_qos(struct ieee80211_hw *hw, int aci) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl92ee_dm_init_edca_turbo(hw); - switch (aci) { - case AC1_BK: - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); - break; - case AC0_BE: - /* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); */ - break; - case AC2_VI: - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); - break; - case AC3_VO: - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); - break; - default: - RT_ASSERT(false, "invalid aci: %d !\n", aci); - break; - } -} - -void rtl92ee_enable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); - rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); - rtlpci->irq_enabled = true; -} - -void rtl92ee_disable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED); - rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED); - rtlpci->irq_enabled = false; - /*synchronize_irq(rtlpci->pdev->irq);*/ -} - -static void _rtl92ee_poweroff_adapter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 u1b_tmp; - - rtlhal->mac_func_enable = false; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "POWER OFF adapter\n"); - - /* Run LPS WL RFOFF flow */ - rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, RTL8192E_NIC_LPS_ENTER_FLOW); - /* turn off RF */ - rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); - - /* ==== Reset digital sequence ====== */ - if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready) - rtl92ee_firmware_selfreset(hw); - - /* Reset MCU */ - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); - - /* reset MCU ready status */ - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); - - /* HW card disable configuration. */ - rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, RTL8192E_NIC_DISABLE_FLOW); - - /* Reset MCU IO Wrapper */ - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0))); - - /* lock ISO/CLK/Power control register */ - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E); -} - -void rtl92ee_card_disable(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - enum nl80211_iftype opmode; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "RTL8192ee card disable\n"); - - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - - mac->link_state = MAC80211_NOLINK; - opmode = NL80211_IFTYPE_UNSPECIFIED; - - _rtl92ee_set_media_status(hw, opmode); - - if (rtlpriv->rtlhal.driver_is_goingto_unload || - ppsc->rfoff_reason > RF_CHANGE_BY_PS) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); - - _rtl92ee_poweroff_adapter(hw); - - /* after power off we should do iqk again */ - rtlpriv->phy.iqk_initialized = false; -} - -void rtl92ee_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; - rtl_write_dword(rtlpriv, ISR, *p_inta); - - *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; - rtl_write_dword(rtlpriv, REG_HISRE, *p_intb); -} - -void rtl92ee_set_beacon_related_registers(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u16 bcn_interval, atim_window; - - bcn_interval = mac->beacon_interval; - atim_window = 2; /*FIX MERGE */ - rtl92ee_disable_interrupt(hw); - rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); - rtl_write_byte(rtlpriv, 0x606, 0x30); - rtlpci->reg_bcn_ctrl_val |= BIT(3); - rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); -} - -void rtl92ee_set_beacon_interval(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval = mac->beacon_interval; - - RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, - "beacon_interval:%d\n", bcn_interval); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); -} - -void rtl92ee_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, - "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); - - if (add_msr) - rtlpci->irq_mask[0] |= add_msr; - if (rm_msr) - rtlpci->irq_mask[0] &= (~rm_msr); - rtl92ee_disable_interrupt(hw); - rtl92ee_enable_interrupt(hw); -} - -static u8 _rtl92ee_get_chnl_group(u8 chnl) -{ - u8 group = 0; - - if (chnl <= 14) { - if (1 <= chnl && chnl <= 2) - group = 0; - else if (3 <= chnl && chnl <= 5) - group = 1; - else if (6 <= chnl && chnl <= 8) - group = 2; - else if (9 <= chnl && chnl <= 11) - group = 3; - else if (12 <= chnl && chnl <= 14) - group = 4; - } else { - if (36 <= chnl && chnl <= 42) - group = 0; - else if (44 <= chnl && chnl <= 48) - group = 1; - else if (50 <= chnl && chnl <= 58) - group = 2; - else if (60 <= chnl && chnl <= 64) - group = 3; - else if (100 <= chnl && chnl <= 106) - group = 4; - else if (108 <= chnl && chnl <= 114) - group = 5; - else if (116 <= chnl && chnl <= 122) - group = 6; - else if (124 <= chnl && chnl <= 130) - group = 7; - else if (132 <= chnl && chnl <= 138) - group = 8; - else if (140 <= chnl && chnl <= 144) - group = 9; - else if (149 <= chnl && chnl <= 155) - group = 10; - else if (157 <= chnl && chnl <= 161) - group = 11; - else if (165 <= chnl && chnl <= 171) - group = 12; - else if (173 <= chnl && chnl <= 177) - group = 13; - } - return group; -} - -static void _rtl8192ee_read_power_value_fromprom(struct ieee80211_hw *hw, - struct txpower_info_2g *pwr2g, - struct txpower_info_5g *pwr5g, - bool autoload_fail, u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 rf, addr = EEPROM_TX_PWR_INX, group, i = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "hal_ReadPowerValueFromPROM92E(): PROMContent[0x%x]=0x%x\n", - (addr + 1), hwinfo[addr + 1]); - if (0xFF == hwinfo[addr+1]) /*YJ,add,120316*/ - autoload_fail = true; - - if (autoload_fail) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "auto load fail : Use Default value!\n"); - for (rf = 0 ; rf < MAX_RF_PATH ; rf++) { - /* 2.4G default value */ - for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { - pwr2g->index_cck_base[rf][group] = 0x2D; - pwr2g->index_bw40_base[rf][group] = 0x2D; - } - for (i = 0; i < MAX_TX_COUNT; i++) { - if (i == 0) { - pwr2g->bw20_diff[rf][0] = 0x02; - pwr2g->ofdm_diff[rf][0] = 0x04; - } else { - pwr2g->bw20_diff[rf][i] = 0xFE; - pwr2g->bw40_diff[rf][i] = 0xFE; - pwr2g->cck_diff[rf][i] = 0xFE; - pwr2g->ofdm_diff[rf][i] = 0xFE; - } - } - - /*5G default value*/ - for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) - pwr5g->index_bw40_base[rf][group] = 0x2A; - - for (i = 0; i < MAX_TX_COUNT; i++) { - if (i == 0) { - pwr5g->ofdm_diff[rf][0] = 0x04; - pwr5g->bw20_diff[rf][0] = 0x00; - pwr5g->bw80_diff[rf][0] = 0xFE; - pwr5g->bw160_diff[rf][0] = 0xFE; - } else { - pwr5g->ofdm_diff[rf][0] = 0xFE; - pwr5g->bw20_diff[rf][0] = 0xFE; - pwr5g->bw40_diff[rf][0] = 0xFE; - pwr5g->bw80_diff[rf][0] = 0xFE; - pwr5g->bw160_diff[rf][0] = 0xFE; - } - } - } - return; - } - - rtl_priv(hw)->efuse.txpwr_fromeprom = true; - - for (rf = 0 ; rf < MAX_RF_PATH ; rf++) { - /*2.4G default value*/ - for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { - pwr2g->index_cck_base[rf][group] = hwinfo[addr++]; - if (pwr2g->index_cck_base[rf][group] == 0xFF) - pwr2g->index_cck_base[rf][group] = 0x2D; - } - for (group = 0 ; group < MAX_CHNL_GROUP_24G - 1; group++) { - pwr2g->index_bw40_base[rf][group] = hwinfo[addr++]; - if (pwr2g->index_bw40_base[rf][group] == 0xFF) - pwr2g->index_bw40_base[rf][group] = 0x2D; - } - for (i = 0; i < MAX_TX_COUNT; i++) { - if (i == 0) { - pwr2g->bw40_diff[rf][i] = 0; - if (hwinfo[addr] == 0xFF) { - pwr2g->bw20_diff[rf][i] = 0x02; - } else { - pwr2g->bw20_diff[rf][i] = (hwinfo[addr] - & 0xf0) >> 4; - if (pwr2g->bw20_diff[rf][i] & BIT(3)) - pwr2g->bw20_diff[rf][i] |= 0xF0; - } - - if (hwinfo[addr] == 0xFF) { - pwr2g->ofdm_diff[rf][i] = 0x04; - } else { - pwr2g->ofdm_diff[rf][i] = (hwinfo[addr] - & 0x0f); - if (pwr2g->ofdm_diff[rf][i] & BIT(3)) - pwr2g->ofdm_diff[rf][i] |= 0xF0; - } - pwr2g->cck_diff[rf][i] = 0; - addr++; - } else { - if (hwinfo[addr] == 0xFF) { - pwr2g->bw40_diff[rf][i] = 0xFE; - } else { - pwr2g->bw40_diff[rf][i] = (hwinfo[addr] - & 0xf0) >> 4; - if (pwr2g->bw40_diff[rf][i] & BIT(3)) - pwr2g->bw40_diff[rf][i] |= 0xF0; - } - - if (hwinfo[addr] == 0xFF) { - pwr2g->bw20_diff[rf][i] = 0xFE; - } else { - pwr2g->bw20_diff[rf][i] = (hwinfo[addr] - & 0x0f); - if (pwr2g->bw20_diff[rf][i] & BIT(3)) - pwr2g->bw20_diff[rf][i] |= 0xF0; - } - addr++; - - if (hwinfo[addr] == 0xFF) { - pwr2g->ofdm_diff[rf][i] = 0xFE; - } else { - pwr2g->ofdm_diff[rf][i] = (hwinfo[addr] - & 0xf0) >> 4; - if (pwr2g->ofdm_diff[rf][i] & BIT(3)) - pwr2g->ofdm_diff[rf][i] |= 0xF0; - } - - if (hwinfo[addr] == 0xFF) { - pwr2g->cck_diff[rf][i] = 0xFE; - } else { - pwr2g->cck_diff[rf][i] = (hwinfo[addr] - & 0x0f); - if (pwr2g->cck_diff[rf][i] & BIT(3)) - pwr2g->cck_diff[rf][i] |= 0xF0; - } - addr++; - } - } - - /*5G default value*/ - for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) { - pwr5g->index_bw40_base[rf][group] = hwinfo[addr++]; - if (pwr5g->index_bw40_base[rf][group] == 0xFF) - pwr5g->index_bw40_base[rf][group] = 0xFE; - } - - for (i = 0; i < MAX_TX_COUNT; i++) { - if (i == 0) { - pwr5g->bw40_diff[rf][i] = 0; - - if (hwinfo[addr] == 0xFF) { - pwr5g->bw20_diff[rf][i] = 0; - } else { - pwr5g->bw20_diff[rf][0] = (hwinfo[addr] - & 0xf0) >> 4; - if (pwr5g->bw20_diff[rf][i] & BIT(3)) - pwr5g->bw20_diff[rf][i] |= 0xF0; - } - - if (hwinfo[addr] == 0xFF) { - pwr5g->ofdm_diff[rf][i] = 0x04; - } else { - pwr5g->ofdm_diff[rf][0] = (hwinfo[addr] - & 0x0f); - if (pwr5g->ofdm_diff[rf][i] & BIT(3)) - pwr5g->ofdm_diff[rf][i] |= 0xF0; - } - addr++; - } else { - if (hwinfo[addr] == 0xFF) { - pwr5g->bw40_diff[rf][i] = 0xFE; - } else { - pwr5g->bw40_diff[rf][i] = (hwinfo[addr] - & 0xf0) >> 4; - if (pwr5g->bw40_diff[rf][i] & BIT(3)) - pwr5g->bw40_diff[rf][i] |= 0xF0; - } - - if (hwinfo[addr] == 0xFF) { - pwr5g->bw20_diff[rf][i] = 0xFE; - } else { - pwr5g->bw20_diff[rf][i] = (hwinfo[addr] - & 0x0f); - if (pwr5g->bw20_diff[rf][i] & BIT(3)) - pwr5g->bw20_diff[rf][i] |= 0xF0; - } - addr++; - } - } - - if (hwinfo[addr] == 0xFF) { - pwr5g->ofdm_diff[rf][1] = 0xFE; - pwr5g->ofdm_diff[rf][2] = 0xFE; - } else { - pwr5g->ofdm_diff[rf][1] = (hwinfo[addr] & 0xf0) >> 4; - pwr5g->ofdm_diff[rf][2] = (hwinfo[addr] & 0x0f); - } - addr++; - - if (hwinfo[addr] == 0xFF) - pwr5g->ofdm_diff[rf][3] = 0xFE; - else - pwr5g->ofdm_diff[rf][3] = (hwinfo[addr] & 0x0f); - addr++; - - for (i = 1; i < MAX_TX_COUNT; i++) { - if (pwr5g->ofdm_diff[rf][i] == 0xFF) - pwr5g->ofdm_diff[rf][i] = 0xFE; - else if (pwr5g->ofdm_diff[rf][i] & BIT(3)) - pwr5g->ofdm_diff[rf][i] |= 0xF0; - } - - for (i = 0; i < MAX_TX_COUNT; i++) { - if (hwinfo[addr] == 0xFF) { - pwr5g->bw80_diff[rf][i] = 0xFE; - } else { - pwr5g->bw80_diff[rf][i] = (hwinfo[addr] & 0xf0) - >> 4; - if (pwr5g->bw80_diff[rf][i] & BIT(3)) - pwr5g->bw80_diff[rf][i] |= 0xF0; - } - - if (hwinfo[addr] == 0xFF) { - pwr5g->bw160_diff[rf][i] = 0xFE; - } else { - pwr5g->bw160_diff[rf][i] = - (hwinfo[addr] & 0x0f); - if (pwr5g->bw160_diff[rf][i] & BIT(3)) - pwr5g->bw160_diff[rf][i] |= 0xF0; - } - addr++; - } - } -} - -static void _rtl92ee_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *efu = rtl_efuse(rtl_priv(hw)); - struct txpower_info_2g pwr2g; - struct txpower_info_5g pwr5g; - u8 channel5g[CHANNEL_MAX_NUMBER_5G] = { - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, - 56, 58, 60, 62, 64, 100, 102, 104, 106, - 108, 110, 112, 114, 116, 118, 120, 122, - 124, 126, 128, 130, 132, 134, 136, 138, - 140, 142, 144, 149, 151, 153, 155, 157, - 159, 161, 163, 165, 167, 168, 169, 171, - 173, 175, 177 - }; - u8 channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = { - 42, 58, 106, 122, 138, 155, 171 - }; - u8 rf, idx; - u8 i; - - _rtl8192ee_read_power_value_fromprom(hw, &pwr2g, &pwr5g, - autoload_fail, hwinfo); - - for (rf = 0; rf < MAX_RF_PATH; rf++) { - for (i = 0; i < 14; i++) { - idx = _rtl92ee_get_chnl_group(i + 1); - - if (i == CHANNEL_MAX_NUMBER_2G - 1) { - efu->txpwrlevel_cck[rf][i] = - pwr2g.index_cck_base[rf][5]; - efu->txpwrlevel_ht40_1s[rf][i] = - pwr2g.index_bw40_base[rf][idx]; - } else { - efu->txpwrlevel_cck[rf][i] = - pwr2g.index_cck_base[rf][idx]; - efu->txpwrlevel_ht40_1s[rf][i] = - pwr2g.index_bw40_base[rf][idx]; - } - } - for (i = 0; i < CHANNEL_MAX_NUMBER_5G; i++) { - idx = _rtl92ee_get_chnl_group(channel5g[i]); - efu->txpwr_5g_bw40base[rf][i] = - pwr5g.index_bw40_base[rf][idx]; - } - for (i = 0; i < CHANNEL_MAX_NUMBER_5G_80M; i++) { - u8 upper, lower; - - idx = _rtl92ee_get_chnl_group(channel5g_80m[i]); - upper = pwr5g.index_bw40_base[rf][idx]; - lower = pwr5g.index_bw40_base[rf][idx + 1]; - - efu->txpwr_5g_bw80base[rf][i] = (upper + lower) / 2; - } - for (i = 0; i < MAX_TX_COUNT; i++) { - efu->txpwr_cckdiff[rf][i] = pwr2g.cck_diff[rf][i]; - efu->txpwr_legacyhtdiff[rf][i] = pwr2g.ofdm_diff[rf][i]; - efu->txpwr_ht20diff[rf][i] = pwr2g.bw20_diff[rf][i]; - efu->txpwr_ht40diff[rf][i] = pwr2g.bw40_diff[rf][i]; - - efu->txpwr_5g_ofdmdiff[rf][i] = pwr5g.ofdm_diff[rf][i]; - efu->txpwr_5g_bw20diff[rf][i] = pwr5g.bw20_diff[rf][i]; - efu->txpwr_5g_bw40diff[rf][i] = pwr5g.bw40_diff[rf][i]; - efu->txpwr_5g_bw80diff[rf][i] = pwr5g.bw80_diff[rf][i]; - } - } - - if (!autoload_fail) - efu->eeprom_thermalmeter = hwinfo[EEPROM_THERMAL_METER_92E]; - else - efu->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; - - if (efu->eeprom_thermalmeter == 0xff || autoload_fail) { - efu->apk_thermalmeterignore = true; - efu->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; - } - - efu->thermalmeter[0] = efu->eeprom_thermalmeter; - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "thermalmeter = 0x%x\n", efu->eeprom_thermalmeter); - - if (!autoload_fail) { - efu->eeprom_regulatory = hwinfo[EEPROM_RF_BOARD_OPTION_92E] - & 0x07; - if (hwinfo[EEPROM_RF_BOARD_OPTION_92E] == 0xFF) - efu->eeprom_regulatory = 0; - } else { - efu->eeprom_regulatory = 0; - } - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "eeprom_regulatory = 0x%x\n", efu->eeprom_regulatory); -} - -static void _rtl92ee_read_adapter_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u16 i, usvalue; - u8 hwinfo[HWSET_MAX_SIZE]; - u16 eeprom_id; - - if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { - rtl_efuse_shadow_map_update(hw); - - memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], - HWSET_MAX_SIZE); - } else if (rtlefuse->epromtype == EEPROM_93C46) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "RTL819X Not boot from eeprom, check it !!"); - return; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "boot from neither eeprom nor efuse, check it !!"); - return; - } - - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP\n", - hwinfo, HWSET_MAX_SIZE); - - eeprom_id = *((u16 *)&hwinfo[0]); - if (eeprom_id != RTL8192E_EEPROM_ID) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "EEPROM ID(%#x) is invalid!!\n", eeprom_id); - rtlefuse->autoload_failflag = true; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - } - - if (rtlefuse->autoload_failflag) - return; - /*VID DID SVID SDID*/ - rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; - rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; - rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; - rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROMId = 0x%4x\n", eeprom_id); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); - /*customer ID*/ - rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID]; - if (rtlefuse->eeprom_oemid == 0xFF) - rtlefuse->eeprom_oemid = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); - /*EEPROM version*/ - rtlefuse->eeprom_version = *(u8 *)&hwinfo[EEPROM_VERSION]; - /*mac address*/ - for (i = 0; i < 6; i += 2) { - usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; - *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "dev_addr: %pM\n", rtlefuse->dev_addr); - /*channel plan */ - rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; - /* set channel plan from efuse */ - rtlefuse->channel_plan = rtlefuse->eeprom_channelplan; - /*tx power*/ - _rtl92ee_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, - hwinfo); - - rtl92ee_read_bt_coexist_info_from_hwpg(hw, rtlefuse->autoload_failflag, - hwinfo); - - /*board type*/ - rtlefuse->board_type = (((*(u8 *)&hwinfo[EEPROM_RF_BOARD_OPTION_92E]) - & 0xE0) >> 5); - if ((*(u8 *)&hwinfo[EEPROM_RF_BOARD_OPTION_92E]) == 0xFF) - rtlefuse->board_type = 0; - - rtlhal->board_type = rtlefuse->board_type; - /*parse xtal*/ - rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_92E]; - if (hwinfo[EEPROM_XTAL_92E] == 0xFF) - rtlefuse->crystalcap = 0x20; - - /*antenna diversity*/ - rtlefuse->antenna_div_type = NO_ANTDIV; - rtlefuse->antenna_div_cfg = 0; - - if (rtlhal->oem_id == RT_CID_DEFAULT) { - switch (rtlefuse->eeprom_oemid) { - case EEPROM_CID_DEFAULT: - if (rtlefuse->eeprom_did == 0x818B) { - if ((rtlefuse->eeprom_svid == 0x10EC) && - (rtlefuse->eeprom_smid == 0x001B)) - rtlhal->oem_id = RT_CID_819X_LENOVO; - } else { - rtlhal->oem_id = RT_CID_DEFAULT; - } - break; - default: - rtlhal->oem_id = RT_CID_DEFAULT; - break; - } - } -} - -static void _rtl92ee_hal_customized_behavior(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - pcipriv->ledctl.led_opendrain = true; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "RT Customized ID: 0x%02X\n", rtlhal->oem_id); -} - -void rtl92ee_read_eeprom_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_u1b; - - rtlhal->version = _rtl92ee_read_chip_version(hw); - if (get_rf_type(rtlphy) == RF_1T1R) { - rtlpriv->dm.rfpath_rxenable[0] = true; - } else { - rtlpriv->dm.rfpath_rxenable[0] = true; - rtlpriv->dm.rfpath_rxenable[1] = true; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", - rtlhal->version); - tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); - if (tmp_u1b & BIT(4)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); - rtlefuse->epromtype = EEPROM_93C46; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); - rtlefuse->epromtype = EEPROM_BOOT_EFUSE; - } - if (tmp_u1b & BIT(5)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - _rtl92ee_read_adapter_info(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); - } - _rtl92ee_hal_customized_behavior(hw); - - rtlphy->rfpath_rx_enable[0] = true; - if (rtlphy->rf_type == RF_2T2R) - rtlphy->rfpath_rx_enable[1] = true; -} - -static u8 _rtl92ee_mrate_idx_to_arfr_id(struct ieee80211_hw *hw, u8 rate_index) -{ - u8 ret = 0; - - switch (rate_index) { - case RATR_INX_WIRELESS_NGB: - ret = 0; - break; - case RATR_INX_WIRELESS_N: - case RATR_INX_WIRELESS_NG: - ret = 4; - break; - case RATR_INX_WIRELESS_NB: - ret = 2; - break; - case RATR_INX_WIRELESS_GB: - ret = 6; - break; - case RATR_INX_WIRELESS_G: - ret = 7; - break; - case RATR_INX_WIRELESS_B: - ret = 8; - break; - default: - ret = 0; - break; - } - return ret; -} - -static void rtl92ee_update_hal_rate_mask(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - u32 ratr_bitmap; - u8 ratr_index; - u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) - ? 1 : 0; - u8 b_curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 b_curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = 0; - bool b_shortgi = false; - u8 rate_mask[7] = {0}; - u8 macid = 0; - /*u8 mimo_ps = IEEE80211_SMPS_OFF;*/ - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - wirelessmode = sta_entry->wireless_mode; - if (mac->opmode == NL80211_IFTYPE_STATION || - mac->opmode == NL80211_IFTYPE_MESH_POINT) - curtxbw_40mhz = mac->bw_40; - else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) - macid = sta->aid + 1; - - ratr_bitmap = sta->supp_rates[0]; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_bitmap = 0xfff; - - ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - - switch (wirelessmode) { - case WIRELESS_MODE_B: - ratr_index = RATR_INX_WIRELESS_B; - if (ratr_bitmap & 0x0000000c) - ratr_bitmap &= 0x0000000d; - else - ratr_bitmap &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_index = RATR_INX_WIRELESS_GB; - - if (rssi_level == 1) - ratr_bitmap &= 0x00000f00; - else if (rssi_level == 2) - ratr_bitmap &= 0x00000ff0; - else - ratr_bitmap &= 0x00000ff5; - break; - case WIRELESS_MODE_N_24G: - if (curtxbw_40mhz) - ratr_index = RATR_INX_WIRELESS_NGB; - else - ratr_index = RATR_INX_WIRELESS_NB; - - if (rtlphy->rf_type == RF_1T1R) { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff005; - } - } else { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x0f8f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0ffff000; - else - ratr_bitmap &= 0x0ffff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x0f8f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0ffff000; - else - ratr_bitmap &= 0x0ffff005; - } - } - - if ((curtxbw_40mhz && b_curshortgi_40mhz) || - (!curtxbw_40mhz && b_curshortgi_20mhz)) { - if (macid == 0) - b_shortgi = true; - else if (macid == 1) - b_shortgi = false; - } - break; - default: - ratr_index = RATR_INX_WIRELESS_NGB; - - if (rtlphy->rf_type == RF_1T1R) - ratr_bitmap &= 0x000ff0ff; - else - ratr_bitmap &= 0x0f8ff0ff; - break; - } - ratr_index = _rtl92ee_mrate_idx_to_arfr_id(hw, ratr_index); - sta_entry->ratr_index = ratr_index; - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "ratr_bitmap :%x\n", ratr_bitmap); - *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | - (ratr_index << 28); - rate_mask[0] = macid; - rate_mask[1] = ratr_index | (b_shortgi ? 0x80 : 0x00); - rate_mask[2] = curtxbw_40mhz; - rate_mask[3] = (u8)(ratr_bitmap & 0x000000ff); - rate_mask[4] = (u8)((ratr_bitmap & 0x0000ff00) >> 8); - rate_mask[5] = (u8)((ratr_bitmap & 0x00ff0000) >> 16); - rate_mask[6] = (u8)((ratr_bitmap & 0xff000000) >> 24); - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x:%x:%x\n", - ratr_index, ratr_bitmap, rate_mask[0], rate_mask[1], - rate_mask[2], rate_mask[3], rate_mask[4], - rate_mask[5], rate_mask[6]); - rtl92ee_fill_h2c_cmd(hw, H2C_92E_RA_MASK, 7, rate_mask); - _rtl92ee_set_bcn_ctrl_reg(hw, BIT(3), 0); -} - -void rtl92ee_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->dm.useramask) - rtl92ee_update_hal_rate_mask(hw, sta, rssi_level); -} - -void rtl92ee_update_channel_access_setting(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 sifs_timer; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, - (u8 *)&mac->slot_time); - if (!mac->ht_enable) - sifs_timer = 0x0a0a; - else - sifs_timer = 0x0e0e; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); -} - -bool rtl92ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) -{ - *valid = 1; - return true; -} - -void rtl92ee_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 *macaddr = p_macaddr; - u32 entry_id = 0; - bool is_pairwise = false; - - static u8 cam_const_addr[4][6] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} - }; - static u8 cam_const_broad[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - - if (clear_all) { - u8 idx = 0; - u8 cam_offset = 0; - u8 clear_number = 5; - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); - - for (idx = 0; idx < clear_number; idx++) { - rtl_cam_mark_invalid(hw, cam_offset + idx); - rtl_cam_empty_entry(hw, cam_offset + idx); - - if (idx < 5) { - memset(rtlpriv->sec.key_buf[idx], 0, - MAX_KEY_LEN); - rtlpriv->sec.key_len[idx] = 0; - } - } - - } else { - switch (enc_algo) { - case WEP40_ENCRYPTION: - enc_algo = CAM_WEP40; - break; - case WEP104_ENCRYPTION: - enc_algo = CAM_WEP104; - break; - case TKIP_ENCRYPTION: - enc_algo = CAM_TKIP; - break; - case AESCCMP_ENCRYPTION: - enc_algo = CAM_AES; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, - "switch case not process\n"); - enc_algo = CAM_TKIP; - break; - } - - if (is_wepkey || rtlpriv->sec.use_defaultkey) { - macaddr = cam_const_addr[key_index]; - entry_id = key_index; - } else { - if (is_group) { - macaddr = cam_const_broad; - entry_id = key_index; - } else { - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - entry_id = rtl_cam_get_free_entry(hw, - p_macaddr); - if (entry_id >= TOTAL_CAM_ENTRY) { - RT_TRACE(rtlpriv, COMP_SEC, - DBG_EMERG, - "Can not find free hw security cam entry\n"); - return; - } - } else { - entry_id = CAM_PAIRWISE_KEY_POSITION; - } - - key_index = PAIRWISE_KEYIDX; - is_pairwise = true; - } - } - - if (rtlpriv->sec.key_len[key_index] == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "delete one entry, entry_id is %d\n", - entry_id); - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_MESH_POINT) - rtl_cam_del_entry(hw, p_macaddr); - rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "add one entry\n"); - if (is_pairwise) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set Pairwiase key\n"); - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[key_index]); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set group key\n"); - - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - rtl_cam_add_one_entry(hw, - rtlefuse->dev_addr, - PAIRWISE_KEYIDX, - CAM_PAIRWISE_KEY_POSITION, - enc_algo, CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[entry_id]); - } - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[entry_id]); - } - } - } -} - -void rtl92ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool auto_load_fail, u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value; - - if (!auto_load_fail) { - value = hwinfo[EEPROM_RF_BOARD_OPTION_92E]; - if (((value & 0xe0) >> 5) == 0x1) - rtlpriv->btcoexist.btc_info.btcoexist = 1; - else - rtlpriv->btcoexist.btc_info.btcoexist = 0; - - rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8192E; - rtlpriv->btcoexist.btc_info.ant_num = ANT_TOTAL_X2; - } else { - rtlpriv->btcoexist.btc_info.btcoexist = 1; - rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8192E; - rtlpriv->btcoexist.btc_info.ant_num = ANT_TOTAL_X1; - } -} - -void rtl92ee_bt_reg_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /* 0:Low, 1:High, 2:From Efuse. */ - rtlpriv->btcoexist.reg_bt_iso = 2; - /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ - rtlpriv->btcoexist.reg_bt_sco = 3; - /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ - rtlpriv->btcoexist.reg_bt_sco = 0; -} - -void rtl92ee_bt_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_init_hw_config(rtlpriv); -} - -void rtl92ee_suspend(struct ieee80211_hw *hw) -{ -} - -void rtl92ee_resume(struct ieee80211_hw *hw) -{ -} - -/* Turn on AAP (RCR:bit 0) for promicuous mode. */ -void rtl92ee_allow_all_destaddr(struct ieee80211_hw *hw, - bool allow_all_da, bool write_into_reg) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - if (allow_all_da) /* Set BIT0 */ - rtlpci->receive_config |= RCR_AAP; - else /* Clear BIT0 */ - rtlpci->receive_config &= ~RCR_AAP; - - if (write_into_reg) - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - - RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, - "receive_config=0x%08X, write_into_reg=%d\n", - rtlpci->receive_config, write_into_reg); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.h b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.h deleted file mode 100644 index 05413f189685..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.h +++ /dev/null @@ -1,62 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92E_HW_H__ -#define __RTL92E_HW_H__ - -void rtl92ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92ee_read_eeprom_info(struct ieee80211_hw *hw); -void rtl92ee_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb); -int rtl92ee_hw_init(struct ieee80211_hw *hw); -void rtl92ee_card_disable(struct ieee80211_hw *hw); -void rtl92ee_enable_interrupt(struct ieee80211_hw *hw); -void rtl92ee_disable_interrupt(struct ieee80211_hw *hw); -int rtl92ee_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); -void rtl92ee_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -void rtl92ee_set_qos(struct ieee80211_hw *hw, int aci); -void rtl92ee_set_beacon_related_registers(struct ieee80211_hw *hw); -void rtl92ee_set_beacon_interval(struct ieee80211_hw *hw); -void rtl92ee_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr); -void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl92ee_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level); -void rtl92ee_update_channel_access_setting(struct ieee80211_hw *hw); -bool rtl92ee_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); -void rtl92ee_enable_hw_security_config(struct ieee80211_hw *hw); -void rtl92ee_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all); -void rtl92ee_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, u8 *hwinfo); -void rtl92ee_bt_reg_init(struct ieee80211_hw *hw); -void rtl92ee_bt_hw_init(struct ieee80211_hw *hw); -void rtl92ee_suspend(struct ieee80211_hw *hw); -void rtl92ee_resume(struct ieee80211_hw *hw); -void rtl92ee_allow_all_destaddr(struct ieee80211_hw *hw, bool allow_all_da, - bool write_into_reg); -void rtl92ee_fw_clk_off_timer_callback(unsigned long data); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/led.c b/drivers/net/wireless/rtlwifi/rtl8192ee/led.c deleted file mode 100644 index 8388e371c8e2..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/led.c +++ /dev/null @@ -1,145 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "reg.h" -#include "led.h" - -static void _rtl92ee_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - u32 ledcfg; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg = rtl_read_dword(rtlpriv , REG_GPIO_PIN_CTRL); - ledcfg &= ~BIT(13); - ledcfg |= BIT(21); - ledcfg &= ~BIT(29); - - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, ledcfg); - - break; - case LED_PIN_LED1: - - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - pled->ledon = true; -} - -void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 ledcfg; - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - - ledcfg = rtl_read_dword(rtlpriv , REG_GPIO_PIN_CTRL); - ledcfg |= ~BIT(21); - ledcfg &= ~BIT(29); - rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, ledcfg); - - break; - case LED_PIN_LED1: - - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - pled->ledon = false; -} - -void rtl92ee_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - - _rtl92ee_init_led(hw, &pcipriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl92ee_init_led(hw, &pcipriv->ledctl.sw_led1, LED_PIN_LED1); -} - -static void _rtl92ee_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_led *pLed0 = &pcipriv->ledctl.sw_led0; - - switch (ledaction) { - case LED_CTL_POWER_ON: - case LED_CTL_LINK: - case LED_CTL_NO_LINK: - rtl92ee_sw_led_on(hw, pLed0); - break; - case LED_CTL_POWER_OFF: - rtl92ee_sw_led_off(hw, pLed0); - break; - default: - break; - } -} - -void rtl92ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && - (ledaction == LED_CTL_TX || - ledaction == LED_CTL_RX || - ledaction == LED_CTL_SITE_SURVEY || - ledaction == LED_CTL_LINK || - ledaction == LED_CTL_NO_LINK || - ledaction == LED_CTL_START_TO_LINK || - ledaction == LED_CTL_POWER_ON)) { - return; - } - RT_TRACE(rtlpriv, COMP_LED, DBG_TRACE, "ledaction %d,\n", ledaction); - _rtl92ee_sw_led_control(hw, ledaction); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/led.h b/drivers/net/wireless/rtlwifi/rtl8192ee/led.h deleted file mode 100644 index 8ef640a2ef7f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/led.h +++ /dev/null @@ -1,34 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92E_LED_H__ -#define __RTL92E_LED_H__ - -void rtl92ee_init_sw_leds(struct ieee80211_hw *hw); -void rtl92ee_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92ee_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92ee_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ee/phy.c deleted file mode 100644 index 018340aedf09..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/phy.c +++ /dev/null @@ -1,3219 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../ps.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" -#include "table.h" - -static u32 _rtl92ee_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset); -static void _rtl92ee_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data); -static u32 _rtl92ee_phy_calculate_bit_shift(u32 bitmask); -static bool _rtl92ee_phy_bb8192ee_config_parafile(struct ieee80211_hw *hw); -static bool _rtl92ee_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); -static bool phy_config_bb_with_hdr_file(struct ieee80211_hw *hw, - u8 configtype); -static bool phy_config_bb_with_pghdrfile(struct ieee80211_hw *hw, - u8 configtype); -static void phy_init_bb_rf_register_def(struct ieee80211_hw *hw); -static bool _rtl92ee_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, u32 cmdtablesz, - enum swchnlcmd_id cmdid, - u32 para1, u32 para2, - u32 msdelay); -static bool _rtl92ee_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, - u8 *step, u32 *delay); -static long _rtl92ee_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - u8 txpwridx); -static void rtl92ee_phy_set_rf_on(struct ieee80211_hw *hw); -static void rtl92ee_phy_set_io(struct ieee80211_hw *hw); - -u32 rtl92ee_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 returnvalue, originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask); - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask); - returnvalue = (originalvalue & bitmask) >> bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "BBR MASK=0x%x Addr[0x%x]=0x%x\n", - bitmask, regaddr, originalvalue); - - return returnvalue; -} - -void rtl92ee_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, - u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); - - if (bitmask != MASKDWORD) { - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask); - data = ((originalvalue & (~bitmask)) | (data << bitshift)); - } - - rtl_write_dword(rtlpriv, regaddr, data); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); -} - -u32 rtl92ee_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, readback_value, bitshift; - unsigned long flags; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", - regaddr, rfpath, bitmask); - - spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); - - original_value = _rtl92ee_phy_rf_serial_read(hw , rfpath, regaddr); - bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask); - readback_value = (original_value & bitmask) >> bitshift; - - spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x),rfpath(%#x),bitmask(%#x),original_value(%#x)\n", - regaddr, rfpath, bitmask, original_value); - - return readback_value; -} - -void rtl92ee_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 addr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, bitshift; - unsigned long flags; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - addr, bitmask, data, rfpath); - - spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); - - if (bitmask != RFREG_OFFSET_MASK) { - original_value = _rtl92ee_phy_rf_serial_read(hw, rfpath, addr); - bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask); - data = (original_value & (~bitmask)) | (data << bitshift); - } - - _rtl92ee_phy_rf_serial_write(hw, rfpath, addr, data); - - spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - addr, bitmask, data, rfpath); -} - -static u32 _rtl92ee_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - u32 newoffset; - u32 tmplong, tmplong2; - u8 rfpi_enable = 0; - u32 retvalue; - - offset &= 0xff; - newoffset = offset; - if (RT_CANNOT_IO(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n"); - return 0xFFFFFFFF; - } - tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); - if (rfpath == RF90_PATH_A) - tmplong2 = tmplong; - else - tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); - tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | - (newoffset << 23) | BLSSIREADEDGE; - rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, - tmplong & (~BLSSIREADEDGE)); - mdelay(1); - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); - mdelay(2); - if (rfpath == RF90_PATH_A) - rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, - BIT(8)); - else if (rfpath == RF90_PATH_B) - rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, - BIT(8)); - if (rfpi_enable) - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, - BLSSIREADBACKDATA); - else - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, - BLSSIREADBACKDATA); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "RFR-%d Addr[0x%x]=0x%x\n", - rfpath, pphyreg->rf_rb, retvalue); - return retvalue; -} - -static void _rtl92ee_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) -{ - u32 data_and_addr; - u32 newoffset; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - - if (RT_CANNOT_IO(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n"); - return; - } - offset &= 0xff; - newoffset = offset; - data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; - rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "RFW-%d Addr[0x%x]=0x%x\n", rfpath, - pphyreg->rf3wire_offset, data_and_addr); -} - -static u32 _rtl92ee_phy_calculate_bit_shift(u32 bitmask) -{ - u32 i; - - for (i = 0; i <= 31; i++) { - if (((bitmask >> i) & 0x1) == 1) - break; - } - return i; -} - -bool rtl92ee_phy_mac_config(struct ieee80211_hw *hw) -{ - return _rtl92ee_phy_config_mac_with_headerfile(hw); -} - -bool rtl92ee_phy_bb_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool rtstatus = true; - u16 regval; - u32 tmp; - u8 crystal_cap; - - phy_init_bb_rf_register_def(hw); - regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, - regval | BIT(13) | BIT(0) | BIT(1)); - - rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, - FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | - FEN_BB_GLB_RSTN | FEN_BBRSTB); - - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); - - tmp = rtl_read_dword(rtlpriv, 0x4c); - rtl_write_dword(rtlpriv, 0x4c, tmp | BIT(23)); - - rtstatus = _rtl92ee_phy_bb8192ee_config_parafile(hw); - - crystal_cap = rtlpriv->efuse.eeprom_crystalcap & 0x3F; - rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, - (crystal_cap | (crystal_cap << 6))); - return rtstatus; -} - -bool rtl92ee_phy_rf_config(struct ieee80211_hw *hw) -{ - return rtl92ee_phy_rf6052_config(hw); -} - -static bool _check_condition(struct ieee80211_hw *hw, - const u32 condition) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 _board = rtlefuse->board_type; /*need efuse define*/ - u32 _interface = rtlhal->interface; - u32 _platform = 0x08;/*SupportPlatform */ - u32 cond = condition; - - if (condition == 0xCDCDCDCD) - return true; - - cond = condition & 0xFF; - if ((_board != cond) && (cond != 0xFF)) - return false; - - cond = condition & 0xFF00; - cond = cond >> 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = condition & 0xFF0000; - cond = cond >> 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - - return true; -} - -static void _rtl92ee_config_rf_reg(struct ieee80211_hw *hw, u32 addr, u32 data, - enum radio_path rfpath, u32 regaddr) -{ - if (addr == 0xfe || addr == 0xffe) { - mdelay(50); - } else { - rtl_set_rfreg(hw, rfpath, regaddr, RFREG_OFFSET_MASK, data); - udelay(1); - - if (addr == 0xb6) { - u32 getvalue; - u8 count = 0; - - getvalue = rtl_get_rfreg(hw, rfpath, addr, MASKDWORD); - udelay(1); - - while ((getvalue >> 8) != (data >> 8)) { - count++; - rtl_set_rfreg(hw, rfpath, regaddr, - RFREG_OFFSET_MASK, data); - udelay(1); - getvalue = rtl_get_rfreg(hw, rfpath, addr, - MASKDWORD); - if (count > 5) - break; - } - } - - if (addr == 0xb2) { - u32 getvalue; - u8 count = 0; - - getvalue = rtl_get_rfreg(hw, rfpath, addr, MASKDWORD); - udelay(1); - - while (getvalue != data) { - count++; - rtl_set_rfreg(hw, rfpath, regaddr, - RFREG_OFFSET_MASK, data); - udelay(1); - rtl_set_rfreg(hw, rfpath, 0x18, - RFREG_OFFSET_MASK, 0x0fc07); - udelay(1); - getvalue = rtl_get_rfreg(hw, rfpath, addr, - MASKDWORD); - if (count > 5) - break; - } - } - } -} - -static void _rtl92ee_config_rf_radio_a(struct ieee80211_hw *hw, - u32 addr, u32 data) -{ - u32 content = 0x1000; /*RF Content: radio_a_txt*/ - u32 maskforphyset = (u32)(content & 0xE000); - - _rtl92ee_config_rf_reg(hw, addr, data, RF90_PATH_A, - addr | maskforphyset); -} - -static void _rtl92ee_config_rf_radio_b(struct ieee80211_hw *hw, - u32 addr, u32 data) -{ - u32 content = 0x1001; /*RF Content: radio_b_txt*/ - u32 maskforphyset = (u32)(content & 0xE000); - - _rtl92ee_config_rf_reg(hw, addr, data, RF90_PATH_B, - addr | maskforphyset); -} - -static void _rtl92ee_config_bb_reg(struct ieee80211_hw *hw, - u32 addr, u32 data) -{ - if (addr == 0xfe) - mdelay(50); - else if (addr == 0xfd) - mdelay(5); - else if (addr == 0xfc) - mdelay(1); - else if (addr == 0xfb) - udelay(50); - else if (addr == 0xfa) - udelay(5); - else if (addr == 0xf9) - udelay(1); - else - rtl_set_bbreg(hw, addr, MASKDWORD , data); - - udelay(1); -} - -static void _rtl92ee_phy_init_tx_power_by_rate(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - u8 band = BAND_ON_2_4G, rf = 0, txnum = 0, sec = 0; - - for (; band <= BAND_ON_5G; ++band) - for (; rf < TX_PWR_BY_RATE_NUM_RF; ++rf) - for (; txnum < TX_PWR_BY_RATE_NUM_RF; ++txnum) - for (; sec < TX_PWR_BY_RATE_NUM_SECTION; ++sec) - rtlphy->tx_power_by_rate_offset - [band][rf][txnum][sec] = 0; -} - -static void _rtl92ee_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw, - u8 band, u8 path, - u8 rate_section, u8 txnum, - u8 value) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - if (path > RF90_PATH_D) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid Rf Path %d\n", path); - return; - } - - if (band == BAND_ON_2_4G) { - switch (rate_section) { - case CCK: - rtlphy->txpwr_by_rate_base_24g[path][txnum][0] = value; - break; - case OFDM: - rtlphy->txpwr_by_rate_base_24g[path][txnum][1] = value; - break; - case HT_MCS0_MCS7: - rtlphy->txpwr_by_rate_base_24g[path][txnum][2] = value; - break; - case HT_MCS8_MCS15: - rtlphy->txpwr_by_rate_base_24g[path][txnum][3] = value; - break; - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid RateSection %d in 2.4G,Rf %d,%dTx\n", - rate_section, path, txnum); - break; - } - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid Band %d\n", band); - } -} - -static u8 _rtl92ee_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw, - u8 band, u8 path, u8 txnum, - u8 rate_section) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 value = 0; - - if (path > RF90_PATH_D) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid Rf Path %d\n", path); - return 0; - } - - if (band == BAND_ON_2_4G) { - switch (rate_section) { - case CCK: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][0]; - break; - case OFDM: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][1]; - break; - case HT_MCS0_MCS7: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][2]; - break; - case HT_MCS8_MCS15: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][3]; - break; - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid RateSection %d in 2.4G,Rf %d,%dTx\n", - rate_section, path, txnum); - break; - } - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid Band %d()\n", band); - } - return value; -} - -static void _rtl92ee_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u16 raw = 0; - u8 base = 0, path = 0; - - for (path = RF90_PATH_A; path <= RF90_PATH_B; ++path) { - if (path == RF90_PATH_A) { - raw = (u16)(rtlphy->tx_power_by_rate_offset - [BAND_ON_2_4G][path][RF_1TX][3] >> 24) & - 0xFF; - base = (raw >> 4) * 10 + (raw & 0xF); - _rtl92ee_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, - path, CCK, RF_1TX, - base); - } else if (path == RF90_PATH_B) { - raw = (u16)(rtlphy->tx_power_by_rate_offset - [BAND_ON_2_4G][path][RF_1TX][3] >> 0) & - 0xFF; - base = (raw >> 4) * 10 + (raw & 0xF); - _rtl92ee_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, - path, CCK, RF_1TX, - base); - } - raw = (u16)(rtlphy->tx_power_by_rate_offset - [BAND_ON_2_4G][path][RF_1TX][1] >> 24) & 0xFF; - base = (raw >> 4) * 10 + (raw & 0xF); - _rtl92ee_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, - OFDM, RF_1TX, base); - - raw = (u16)(rtlphy->tx_power_by_rate_offset - [BAND_ON_2_4G][path][RF_1TX][5] >> 24) & 0xFF; - base = (raw >> 4) * 10 + (raw & 0xF); - _rtl92ee_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, - HT_MCS0_MCS7, RF_1TX, - base); - - raw = (u16)(rtlphy->tx_power_by_rate_offset - [BAND_ON_2_4G][path][RF_2TX][7] >> 24) & 0xFF; - base = (raw >> 4) * 10 + (raw & 0xF); - _rtl92ee_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, - HT_MCS8_MCS15, RF_2TX, - base); - } -} - -static void _phy_convert_txpower_dbm_to_relative_value(u32 *data, u8 start, - u8 end, u8 base) -{ - char i = 0; - u8 tmp = 0; - u32 temp_data = 0; - - for (i = 3; i >= 0; --i) { - if (i >= start && i <= end) { - /* Get the exact value */ - tmp = (u8)(*data >> (i * 8)) & 0xF; - tmp += ((u8)((*data >> (i * 8 + 4)) & 0xF)) * 10; - - /* Change the value to a relative value */ - tmp = (tmp > base) ? tmp - base : base - tmp; - } else { - tmp = (u8)(*data >> (i * 8)) & 0xFF; - } - temp_data <<= 8; - temp_data |= tmp; - } - *data = temp_data; -} - -static void phy_convert_txpwr_dbm_to_rel_val(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 base = 0, rf = 0, band = BAND_ON_2_4G; - - for (rf = RF90_PATH_A; rf <= RF90_PATH_B; ++rf) { - if (rf == RF90_PATH_A) { - base = _rtl92ee_phy_get_txpower_by_rate_base(hw, band, - rf, RF_1TX, - CCK); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset - [band][rf][RF_1TX][2], - 1, 1, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset - [band][rf][RF_1TX][3], - 1, 3, base); - } else if (rf == RF90_PATH_B) { - base = _rtl92ee_phy_get_txpower_by_rate_base(hw, band, - rf, RF_1TX, - CCK); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset - [band][rf][RF_1TX][3], - 0, 0, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset - [band][rf][RF_1TX][2], - 1, 3, base); - } - base = _rtl92ee_phy_get_txpower_by_rate_base(hw, band, rf, - RF_1TX, OFDM); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[band][rf][RF_1TX][0], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[band][rf][RF_1TX][1], - 0, 3, base); - - base = _rtl92ee_phy_get_txpower_by_rate_base(hw, band, rf, - RF_1TX, - HT_MCS0_MCS7); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[band][rf][RF_1TX][4], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[band][rf][RF_1TX][5], - 0, 3, base); - - base = _rtl92ee_phy_get_txpower_by_rate_base(hw, band, rf, - RF_2TX, - HT_MCS8_MCS15); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[band][rf][RF_2TX][6], - 0, 3, base); - - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[band][rf][RF_2TX][7], - 0, 3, base); - } - - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "<==phy_convert_txpwr_dbm_to_rel_val()\n"); -} - -static void _rtl92ee_phy_txpower_by_rate_configuration(struct ieee80211_hw *hw) -{ - _rtl92ee_phy_store_txpower_by_rate_base(hw); - phy_convert_txpwr_dbm_to_rel_val(hw); -} - -static bool _rtl92ee_phy_bb8192ee_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - bool rtstatus; - - rtstatus = phy_config_bb_with_hdr_file(hw, BASEBAND_CONFIG_PHY_REG); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); - return false; - } - - _rtl92ee_phy_init_tx_power_by_rate(hw); - if (!rtlefuse->autoload_failflag) { - rtlphy->pwrgroup_cnt = 0; - rtstatus = - phy_config_bb_with_pghdrfile(hw, BASEBAND_CONFIG_PHY_REG); - } - _rtl92ee_phy_txpower_by_rate_configuration(hw); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); - return false; - } - rtstatus = phy_config_bb_with_hdr_file(hw, BASEBAND_CONFIG_AGC_TAB); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); - return false; - } - rtlphy->cck_high_power = (bool)(rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, - 0x200)); - - return true; -} - -static bool _rtl92ee_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - u32 arraylength; - u32 *ptrarray; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl8192EMACPHY_Array\n"); - arraylength = RTL8192EE_MAC_ARRAY_LEN; - ptrarray = RTL8192EE_MAC_ARRAY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Img:RTL8192EE_MAC_ARRAY LEN %d\n" , arraylength); - for (i = 0; i < arraylength; i = i + 2) - rtl_write_byte(rtlpriv, ptrarray[i], (u8)ptrarray[i + 1]); - return true; -} - -#define READ_NEXT_PAIR(v1, v2, i) \ - do { \ - i += 2; \ - v1 = array[i]; \ - v2 = array[i+1]; \ - } while (0) - -static bool phy_config_bb_with_hdr_file(struct ieee80211_hw *hw, - u8 configtype) -{ - int i; - u32 *array; - u16 len; - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 v1 = 0, v2 = 0; - - if (configtype == BASEBAND_CONFIG_PHY_REG) { - len = RTL8192EE_PHY_REG_ARRAY_LEN; - array = RTL8192EE_PHY_REG_ARRAY; - - for (i = 0; i < len; i = i + 2) { - v1 = array[i]; - v2 = array[i+1]; - if (v1 < 0xcdcdcdcd) { - _rtl92ee_config_bb_reg(hw, v1, v2); - } else {/*This line is the start line of branch.*/ - /* to protect READ_NEXT_PAIR not overrun */ - if (i >= len - 2) - break; - - if (!_check_condition(hw , array[i])) { - /*Discard the following pairs*/ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < len - 2) { - READ_NEXT_PAIR(v1, v2, i); - } - i -= 2; /* prevent from for-loop += 2*/ - } else { - /* Configure matched pairs and - * skip to end of if-else. - */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < len - 2) { - _rtl92ee_config_bb_reg(hw, v1, - v2); - READ_NEXT_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < len - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } - } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { - len = RTL8192EE_AGC_TAB_ARRAY_LEN; - array = RTL8192EE_AGC_TAB_ARRAY; - - for (i = 0; i < len; i = i + 2) { - v1 = array[i]; - v2 = array[i+1]; - if (v1 < 0xCDCDCDCD) { - rtl_set_bbreg(hw, array[i], MASKDWORD, - array[i + 1]); - udelay(1); - continue; - } else{/*This line is the start line of branch.*/ - /* to protect READ_NEXT_PAIR not overrun */ - if (i >= len - 2) - break; - - if (!_check_condition(hw , array[i])) { - /*Discard the following pairs*/ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < len - 2) { - READ_NEXT_PAIR(v1, v2, i); - } - i -= 2; /* prevent from for-loop += 2*/ - } else { - /* Configure matched pairs and - * skip to end of if-else. - */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < len - 2) { - rtl_set_bbreg(hw, - array[i], - MASKDWORD, - array[i + 1]); - udelay(1); - READ_NEXT_PAIR(v1 , v2 , i); - } - - while (v2 != 0xDEAD && - i < len - 2) { - READ_NEXT_PAIR(v1 , v2 , i); - } - } - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The agctab_array_table[0] is %x Rtl818EEPHY_REGArray[1] is %x\n", - array[i], - array[i + 1]); - } - } - return true; -} - -static u8 _rtl92ee_get_rate_section_index(u32 regaddr) -{ - u8 index = 0; - - switch (regaddr) { - case RTXAGC_A_RATE18_06: - case RTXAGC_B_RATE18_06: - index = 0; - break; - case RTXAGC_A_RATE54_24: - case RTXAGC_B_RATE54_24: - index = 1; - break; - case RTXAGC_A_CCK1_MCS32: - case RTXAGC_B_CCK1_55_MCS32: - index = 2; - break; - case RTXAGC_B_CCK11_A_CCK2_11: - index = 3; - break; - case RTXAGC_A_MCS03_MCS00: - case RTXAGC_B_MCS03_MCS00: - index = 4; - break; - case RTXAGC_A_MCS07_MCS04: - case RTXAGC_B_MCS07_MCS04: - index = 5; - break; - case RTXAGC_A_MCS11_MCS08: - case RTXAGC_B_MCS11_MCS08: - index = 6; - break; - case RTXAGC_A_MCS15_MCS12: - case RTXAGC_B_MCS15_MCS12: - index = 7; - break; - default: - regaddr &= 0xFFF; - if (regaddr >= 0xC20 && regaddr <= 0xC4C) - index = (u8)((regaddr - 0xC20) / 4); - else if (regaddr >= 0xE20 && regaddr <= 0xE4C) - index = (u8)((regaddr - 0xE20) / 4); - break; - } - return index; -} - -static void _rtl92ee_store_tx_power_by_rate(struct ieee80211_hw *hw, - enum band_type band, - enum radio_path rfpath, - u32 txnum, u32 regaddr, - u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 section = _rtl92ee_get_rate_section_index(regaddr); - - if (band != BAND_ON_2_4G && band != BAND_ON_5G) { - RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, "Invalid Band %d\n", band); - return; - } - - if (rfpath > MAX_RF_PATH - 1) { - RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, - "Invalid RfPath %d\n", rfpath); - return; - } - if (txnum > MAX_RF_PATH - 1) { - RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, "Invalid TxNum %d\n", txnum); - return; - } - - rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][section] = data; -} - -static bool phy_config_bb_with_pghdrfile(struct ieee80211_hw *hw, - u8 configtype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int i; - u32 *phy_regarray_table_pg; - u16 phy_regarray_pg_len; - u32 v1 = 0, v2 = 0, v3 = 0, v4 = 0, v5 = 0, v6 = 0; - - phy_regarray_pg_len = RTL8192EE_PHY_REG_ARRAY_PG_LEN; - phy_regarray_table_pg = RTL8192EE_PHY_REG_ARRAY_PG; - - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_regarray_pg_len; i = i + 6) { - v1 = phy_regarray_table_pg[i]; - v2 = phy_regarray_table_pg[i+1]; - v3 = phy_regarray_table_pg[i+2]; - v4 = phy_regarray_table_pg[i+3]; - v5 = phy_regarray_table_pg[i+4]; - v6 = phy_regarray_table_pg[i+5]; - - if (v1 < 0xcdcdcdcd) { - _rtl92ee_store_tx_power_by_rate(hw, v1, v2, v3, - v4, v5, v6); - continue; - } - } - } else { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "configtype != BaseBand_Config_PHY_REG\n"); - } - return true; -} - -#define READ_NEXT_RF_PAIR(v1, v2, i) \ - do { \ - i += 2; \ - v1 = array[i]; \ - v2 = array[i+1]; \ - } while (0) - -bool rtl92ee_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int i; - u32 *array; - u16 len; - u32 v1 = 0, v2 = 0; - - switch (rfpath) { - case RF90_PATH_A: - len = RTL8192EE_RADIOA_ARRAY_LEN; - array = RTL8192EE_RADIOA_ARRAY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Radio_A:RTL8192EE_RADIOA_ARRAY %d\n" , len); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); - for (i = 0; i < len; i = i + 2) { - v1 = array[i]; - v2 = array[i+1]; - if (v1 < 0xcdcdcdcd) { - _rtl92ee_config_rf_radio_a(hw, v1, v2); - continue; - } else {/*This line is the start line of branch.*/ - /* to protect READ_NEXT_PAIR not overrun */ - if (i >= len - 2) - break; - - if (!_check_condition(hw , array[i])) { - /*Discard the following pairs*/ - READ_NEXT_RF_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < len - 2) { - READ_NEXT_RF_PAIR(v1, v2, i); - } - i -= 2; /* prevent from for-loop += 2*/ - } else { - /* Configure matched pairs and - * skip to end of if-else. - */ - READ_NEXT_RF_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < len - 2) { - _rtl92ee_config_rf_radio_a(hw, - v1, - v2); - READ_NEXT_RF_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < len - 2) - READ_NEXT_RF_PAIR(v1, v2, i); - } - } - } - break; - - case RF90_PATH_B: - len = RTL8192EE_RADIOB_ARRAY_LEN; - array = RTL8192EE_RADIOB_ARRAY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Radio_A:RTL8192EE_RADIOB_ARRAY %d\n" , len); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); - for (i = 0; i < len; i = i + 2) { - v1 = array[i]; - v2 = array[i+1]; - if (v1 < 0xcdcdcdcd) { - _rtl92ee_config_rf_radio_b(hw, v1, v2); - continue; - } else {/*This line is the start line of branch.*/ - /* to protect READ_NEXT_PAIR not overrun */ - if (i >= len - 2) - break; - - if (!_check_condition(hw , array[i])) { - /*Discard the following pairs*/ - READ_NEXT_RF_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < len - 2) { - READ_NEXT_RF_PAIR(v1, v2, i); - } - i -= 2; /* prevent from for-loop += 2*/ - } else { - /* Configure matched pairs and - * skip to end of if-else. - */ - READ_NEXT_RF_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < len - 2) { - _rtl92ee_config_rf_radio_b(hw, - v1, - v2); - READ_NEXT_RF_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < len - 2) - READ_NEXT_RF_PAIR(v1, v2, i); - } - } - } - break; - case RF90_PATH_C: - case RF90_PATH_D: - break; - } - return true; -} - -void rtl92ee_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - rtlphy->default_initialgain[0] = - (u8)rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[1] = - (u8)rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[2] = - (u8)rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[3] = - (u8)rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", - rtlphy->default_initialgain[0], - rtlphy->default_initialgain[1], - rtlphy->default_initialgain[2], - rtlphy->default_initialgain[3]); - - rtlphy->framesync = (u8)rtl_get_bbreg(hw, - ROFDM0_RXDETECTOR3, MASKBYTE0); - rtlphy->framesync_c34 = rtl_get_bbreg(hw, - ROFDM0_RXDETECTOR2, MASKDWORD); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default framesync (0x%x) = 0x%x\n", - ROFDM0_RXDETECTOR3, rtlphy->framesync); -} - -static void phy_init_bb_rf_register_def(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; - - rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = - RFPGA0_XA_LSSIPARAMETER; - rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = - RFPGA0_XB_LSSIPARAMETER; - - rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; - rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; - - rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; - - rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK; - rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK; -} - -void rtl92ee_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 txpwr_level; - long txpwr_dbm; - - txpwr_level = rtlphy->cur_cck_txpwridx; - txpwr_dbm = _rtl92ee_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_B, - txpwr_level); - txpwr_level = rtlphy->cur_ofdm24g_txpwridx; - if (_rtl92ee_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, txpwr_level) > - txpwr_dbm) - txpwr_dbm = _rtl92ee_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, - txpwr_level); - txpwr_level = rtlphy->cur_ofdm24g_txpwridx; - if (_rtl92ee_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, - txpwr_level) > txpwr_dbm) - txpwr_dbm = _rtl92ee_phy_txpwr_idx_to_dbm(hw, - WIRELESS_MODE_N_24G, - txpwr_level); - *powerlevel = txpwr_dbm; -} - -static u8 _rtl92ee_phy_get_ratesection_intxpower_byrate(enum radio_path path, - u8 rate) -{ - u8 rate_section = 0; - - switch (rate) { - case DESC92C_RATE1M: - rate_section = 2; - break; - case DESC92C_RATE2M: - case DESC92C_RATE5_5M: - if (path == RF90_PATH_A) - rate_section = 3; - else if (path == RF90_PATH_B) - rate_section = 2; - break; - case DESC92C_RATE11M: - rate_section = 3; - break; - case DESC92C_RATE6M: - case DESC92C_RATE9M: - case DESC92C_RATE12M: - case DESC92C_RATE18M: - rate_section = 0; - break; - case DESC92C_RATE24M: - case DESC92C_RATE36M: - case DESC92C_RATE48M: - case DESC92C_RATE54M: - rate_section = 1; - break; - case DESC92C_RATEMCS0: - case DESC92C_RATEMCS1: - case DESC92C_RATEMCS2: - case DESC92C_RATEMCS3: - rate_section = 4; - break; - case DESC92C_RATEMCS4: - case DESC92C_RATEMCS5: - case DESC92C_RATEMCS6: - case DESC92C_RATEMCS7: - rate_section = 5; - break; - case DESC92C_RATEMCS8: - case DESC92C_RATEMCS9: - case DESC92C_RATEMCS10: - case DESC92C_RATEMCS11: - rate_section = 6; - break; - case DESC92C_RATEMCS12: - case DESC92C_RATEMCS13: - case DESC92C_RATEMCS14: - case DESC92C_RATEMCS15: - rate_section = 7; - break; - default: - RT_ASSERT(true, "Rate_Section is Illegal\n"); - break; - } - return rate_section; -} - -static u8 _rtl92ee_get_txpower_by_rate(struct ieee80211_hw *hw, - enum band_type band, - enum radio_path rf, u8 rate) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 shift = 0, sec, tx_num; - char diff = 0; - - sec = _rtl92ee_phy_get_ratesection_intxpower_byrate(rf, rate); - tx_num = RF_TX_NUM_NONIMPLEMENT; - - if (tx_num == RF_TX_NUM_NONIMPLEMENT) { - if ((rate >= DESC92C_RATEMCS8 && rate <= DESC92C_RATEMCS15)) - tx_num = RF_2TX; - else - tx_num = RF_1TX; - } - - switch (rate) { - case DESC92C_RATE1M: - case DESC92C_RATE6M: - case DESC92C_RATE24M: - case DESC92C_RATEMCS0: - case DESC92C_RATEMCS4: - case DESC92C_RATEMCS8: - case DESC92C_RATEMCS12: - shift = 0; - break; - case DESC92C_RATE2M: - case DESC92C_RATE9M: - case DESC92C_RATE36M: - case DESC92C_RATEMCS1: - case DESC92C_RATEMCS5: - case DESC92C_RATEMCS9: - case DESC92C_RATEMCS13: - shift = 8; - break; - case DESC92C_RATE5_5M: - case DESC92C_RATE12M: - case DESC92C_RATE48M: - case DESC92C_RATEMCS2: - case DESC92C_RATEMCS6: - case DESC92C_RATEMCS10: - case DESC92C_RATEMCS14: - shift = 16; - break; - case DESC92C_RATE11M: - case DESC92C_RATE18M: - case DESC92C_RATE54M: - case DESC92C_RATEMCS3: - case DESC92C_RATEMCS7: - case DESC92C_RATEMCS11: - case DESC92C_RATEMCS15: - shift = 24; - break; - default: - RT_ASSERT(true, "Rate_Section is Illegal\n"); - break; - } - - diff = (u8)(rtlphy->tx_power_by_rate_offset[band][rf][tx_num][sec] >> - shift) & 0xff; - - return diff; -} - -static u8 _rtl92ee_get_txpower_index(struct ieee80211_hw *hw, - enum radio_path rfpath, u8 rate, - u8 bw, u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); - u8 index = (channel - 1); - u8 tx_power = 0; - u8 diff = 0; - - if (channel < 1 || channel > 14) { - index = 0; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_DMESG, - "Illegal channel!!\n"); - } - - if (IS_CCK_RATE(rate)) - tx_power = rtlefuse->txpwrlevel_cck[rfpath][index]; - else if (DESC92C_RATE6M <= rate) - tx_power = rtlefuse->txpwrlevel_ht40_1s[rfpath][index]; - - /* OFDM-1T*/ - if (DESC92C_RATE6M <= rate && rate <= DESC92C_RATE54M && - !IS_CCK_RATE(rate)) - tx_power += rtlefuse->txpwr_legacyhtdiff[rfpath][TX_1S]; - - /* BW20-1S, BW20-2S */ - if (bw == HT_CHANNEL_WIDTH_20) { - if (DESC92C_RATEMCS0 <= rate && rate <= DESC92C_RATEMCS15) - tx_power += rtlefuse->txpwr_ht20diff[rfpath][TX_1S]; - if (DESC92C_RATEMCS8 <= rate && rate <= DESC92C_RATEMCS15) - tx_power += rtlefuse->txpwr_ht20diff[rfpath][TX_2S]; - } else if (bw == HT_CHANNEL_WIDTH_20_40) {/* BW40-1S, BW40-2S */ - if (DESC92C_RATEMCS0 <= rate && rate <= DESC92C_RATEMCS15) - tx_power += rtlefuse->txpwr_ht40diff[rfpath][TX_1S]; - if (DESC92C_RATEMCS8 <= rate && rate <= DESC92C_RATEMCS15) - tx_power += rtlefuse->txpwr_ht40diff[rfpath][TX_2S]; - } - - if (rtlefuse->eeprom_regulatory != 2) - diff = _rtl92ee_get_txpower_by_rate(hw, BAND_ON_2_4G, - rfpath, rate); - - tx_power += diff; - - if (tx_power > MAX_POWER_INDEX) - tx_power = MAX_POWER_INDEX; - - return tx_power; -} - -static void _rtl92ee_set_txpower_index(struct ieee80211_hw *hw, u8 pwr_idx, - enum radio_path rfpath, u8 rate) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rfpath == RF90_PATH_A) { - switch (rate) { - case DESC92C_RATE1M: - rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATE2M: - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATE5_5M: - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATE11M: - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE3, - pwr_idx); - break; - case DESC92C_RATE6M: - rtl_set_bbreg(hw, RTXAGC_A_RATE18_06, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATE9M: - rtl_set_bbreg(hw, RTXAGC_A_RATE18_06, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATE12M: - rtl_set_bbreg(hw, RTXAGC_A_RATE18_06, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATE18M: - rtl_set_bbreg(hw, RTXAGC_A_RATE18_06, MASKBYTE3, - pwr_idx); - break; - case DESC92C_RATE24M: - rtl_set_bbreg(hw, RTXAGC_A_RATE54_24, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATE36M: - rtl_set_bbreg(hw, RTXAGC_A_RATE54_24, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATE48M: - rtl_set_bbreg(hw, RTXAGC_A_RATE54_24, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATE54M: - rtl_set_bbreg(hw, RTXAGC_A_RATE54_24, MASKBYTE3, - pwr_idx); - break; - case DESC92C_RATEMCS0: - rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATEMCS1: - rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATEMCS2: - rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATEMCS3: - rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, MASKBYTE3, - pwr_idx); - break; - case DESC92C_RATEMCS4: - rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATEMCS5: - rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATEMCS6: - rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATEMCS7: - rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, MASKBYTE3, - pwr_idx); - break; - case DESC92C_RATEMCS8: - rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATEMCS9: - rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATEMCS10: - rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATEMCS11: - rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, MASKBYTE3, - pwr_idx); - break; - case DESC92C_RATEMCS12: - rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATEMCS13: - rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATEMCS14: - rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATEMCS15: - rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, MASKBYTE3, - pwr_idx); - break; - default: - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Invalid Rate!!\n"); - break; - } - } else if (rfpath == RF90_PATH_B) { - switch (rate) { - case DESC92C_RATE1M: - rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATE2M: - rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATE5_5M: - rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, MASKBYTE3, - pwr_idx); - break; - case DESC92C_RATE11M: - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATE6M: - rtl_set_bbreg(hw, RTXAGC_B_RATE18_06, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATE9M: - rtl_set_bbreg(hw, RTXAGC_B_RATE18_06, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATE12M: - rtl_set_bbreg(hw, RTXAGC_B_RATE18_06, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATE18M: - rtl_set_bbreg(hw, RTXAGC_B_RATE18_06, MASKBYTE3, - pwr_idx); - break; - case DESC92C_RATE24M: - rtl_set_bbreg(hw, RTXAGC_B_RATE54_24, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATE36M: - rtl_set_bbreg(hw, RTXAGC_B_RATE54_24, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATE48M: - rtl_set_bbreg(hw, RTXAGC_B_RATE54_24, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATE54M: - rtl_set_bbreg(hw, RTXAGC_B_RATE54_24, MASKBYTE3, - pwr_idx); - break; - case DESC92C_RATEMCS0: - rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATEMCS1: - rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATEMCS2: - rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATEMCS3: - rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, MASKBYTE3, - pwr_idx); - break; - case DESC92C_RATEMCS4: - rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATEMCS5: - rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATEMCS6: - rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATEMCS7: - rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, MASKBYTE3, - pwr_idx); - break; - case DESC92C_RATEMCS8: - rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATEMCS9: - rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATEMCS10: - rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATEMCS11: - rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, MASKBYTE3, - pwr_idx); - break; - case DESC92C_RATEMCS12: - rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, MASKBYTE0, - pwr_idx); - break; - case DESC92C_RATEMCS13: - rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, MASKBYTE1, - pwr_idx); - break; - case DESC92C_RATEMCS14: - rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, MASKBYTE2, - pwr_idx); - break; - case DESC92C_RATEMCS15: - rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, MASKBYTE3, - pwr_idx); - break; - default: - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Invalid Rate!!\n"); - break; - } - } else { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Invalid RFPath!!\n"); - } -} - -static void phy_set_txpower_index_by_rate_array(struct ieee80211_hw *hw, - enum radio_path rfpath, u8 bw, - u8 channel, u8 *rates, u8 size) -{ - u8 i; - u8 power_index; - - for (i = 0; i < size; i++) { - power_index = _rtl92ee_get_txpower_index(hw, rfpath, rates[i], - bw, channel); - _rtl92ee_set_txpower_index(hw, power_index, rfpath, rates[i]); - } -} - -static void phy_set_txpower_index_by_rate_section(struct ieee80211_hw *hw, - enum radio_path rfpath, - u8 channel, - enum rate_section section) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - if (section == CCK) { - u8 cck_rates[] = {DESC92C_RATE1M, DESC92C_RATE2M, - DESC92C_RATE5_5M, DESC92C_RATE11M}; - if (rtlhal->current_bandtype == BAND_ON_2_4G) - phy_set_txpower_index_by_rate_array(hw, rfpath, - rtlphy->current_chan_bw, - channel, cck_rates, 4); - } else if (section == OFDM) { - u8 ofdm_rates[] = {DESC92C_RATE6M, DESC92C_RATE9M, - DESC92C_RATE12M, DESC92C_RATE18M, - DESC92C_RATE24M, DESC92C_RATE36M, - DESC92C_RATE48M, DESC92C_RATE54M}; - phy_set_txpower_index_by_rate_array(hw, rfpath, - rtlphy->current_chan_bw, - channel, ofdm_rates, 8); - } else if (section == HT_MCS0_MCS7) { - u8 ht_rates1t[] = {DESC92C_RATEMCS0, DESC92C_RATEMCS1, - DESC92C_RATEMCS2, DESC92C_RATEMCS3, - DESC92C_RATEMCS4, DESC92C_RATEMCS5, - DESC92C_RATEMCS6, DESC92C_RATEMCS7}; - phy_set_txpower_index_by_rate_array(hw, rfpath, - rtlphy->current_chan_bw, - channel, ht_rates1t, 8); - } else if (section == HT_MCS8_MCS15) { - u8 ht_rates2t[] = {DESC92C_RATEMCS8, DESC92C_RATEMCS9, - DESC92C_RATEMCS10, DESC92C_RATEMCS11, - DESC92C_RATEMCS12, DESC92C_RATEMCS13, - DESC92C_RATEMCS14, DESC92C_RATEMCS15}; - phy_set_txpower_index_by_rate_array(hw, rfpath, - rtlphy->current_chan_bw, - channel, ht_rates2t, 8); - } else - RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, - "Invalid RateSection %d\n", section); -} - -void rtl92ee_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtl_priv(hw)->phy; - enum radio_path rfpath; - - if (!rtlefuse->txpwr_fromeprom) - return; - for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; - rfpath++) { - phy_set_txpower_index_by_rate_section(hw, rfpath, - channel, CCK); - phy_set_txpower_index_by_rate_section(hw, rfpath, - channel, OFDM); - phy_set_txpower_index_by_rate_section(hw, rfpath, - channel, - HT_MCS0_MCS7); - - if (rtlphy->num_total_rfpath >= 2) - phy_set_txpower_index_by_rate_section(hw, - rfpath, channel, - HT_MCS8_MCS15); - } -} - -static long _rtl92ee_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - u8 txpwridx) -{ - long offset; - long pwrout_dbm; - - switch (wirelessmode) { - case WIRELESS_MODE_B: - offset = -7; - break; - case WIRELESS_MODE_G: - case WIRELESS_MODE_N_24G: - offset = -8; - break; - default: - offset = -8; - break; - } - pwrout_dbm = txpwridx / 2 + offset; - return pwrout_dbm; -} - -void rtl92ee_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - enum io_type iotype; - - if (!is_hal_stop(rtlhal)) { - switch (operation) { - case SCAN_OPT_BACKUP_BAND0: - iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, - (u8 *)&iotype); - - break; - case SCAN_OPT_RESTORE: - iotype = IO_CMD_RESUME_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, - (u8 *)&iotype); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Unknown Scan Backup operation.\n"); - break; - } - } -} - -void rtl92ee_phy_set_bw_mode_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 reg_bw_opmode; - u8 reg_prsr_rsc; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "Switch to %s bandwidth\n", - rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? - "20MHz" : "40MHz"); - - if (is_hal_stop(rtlhal)) { - rtlphy->set_bwmode_inprogress = false; - return; - } - - reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); - reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - reg_bw_opmode |= BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - break; - case HT_CHANNEL_WIDTH_20_40: - reg_bw_opmode &= ~BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - reg_prsr_rsc = (reg_prsr_rsc & 0x90) | - (mac->cur_40_prime_sc << 5); - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, ROFDM0_TXPSEUDONOISEWGT, - (BIT(31) | BIT(30)), 0); - break; - case HT_CHANNEL_WIDTH_20_40: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, - (mac->cur_40_prime_sc >> 1)); - rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, - mac->cur_40_prime_sc); - - rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), - (mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - rtl92ee_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); - rtlphy->set_bwmode_inprogress = false; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n"); -} - -void rtl92ee_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_bw = rtlphy->current_chan_bw; - - if (rtlphy->set_bwmode_inprogress) - return; - rtlphy->set_bwmode_inprogress = true; - if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtl92ee_phy_set_bw_mode_callback(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "false driver sleep or unload\n"); - rtlphy->set_bwmode_inprogress = false; - rtlphy->current_chan_bw = tmp_bw; - } -} - -void rtl92ee_phy_sw_chnl_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 delay; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "switch to channel%d\n", rtlphy->current_channel); - if (is_hal_stop(rtlhal)) - return; - do { - if (!rtlphy->sw_chnl_inprogress) - break; - if (!_rtl92ee_phy_sw_chnl_step_by_step - (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage, - &rtlphy->sw_chnl_step, &delay)) { - if (delay > 0) - mdelay(delay); - else - continue; - } else { - rtlphy->sw_chnl_inprogress = false; - } - break; - } while (true); - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); -} - -u8 rtl92ee_phy_sw_chnl(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (rtlphy->sw_chnl_inprogress) - return 0; - if (rtlphy->set_bwmode_inprogress) - return 0; - RT_ASSERT((rtlphy->current_channel <= 14), - "WIRELESS_MODE_G but channel>14"); - rtlphy->sw_chnl_inprogress = true; - rtlphy->sw_chnl_stage = 0; - rtlphy->sw_chnl_step = 0; - if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtl92ee_phy_sw_chnl_callback(hw); - RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false schdule workitem current channel %d\n", - rtlphy->current_channel); - rtlphy->sw_chnl_inprogress = false; - } else { - RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false driver sleep or unload\n"); - rtlphy->sw_chnl_inprogress = false; - } - return 1; -} - -static bool _rtl92ee_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; - u32 precommoncmdcnt; - struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; - u32 postcommoncmdcnt; - struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; - u32 rfdependcmdcnt; - struct swchnlcmd *currentcmd = NULL; - u8 rfpath; - u8 num_total_rfpath = rtlphy->num_total_rfpath; - - precommoncmdcnt = 0; - _rtl92ee_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, - CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); - _rtl92ee_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); - - postcommoncmdcnt = 0; - - _rtl92ee_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, - MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); - - rfdependcmdcnt = 0; - - RT_ASSERT((channel >= 1 && channel <= 14), - "illegal channel for Zebra: %d\n", channel); - - _rtl92ee_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, - CMDID_RF_WRITEREG, - RF_CHNLBW, channel, 10); - - _rtl92ee_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, CMDID_END, - 0, 0, 0); - - do { - switch (*stage) { - case 0: - currentcmd = &precommoncmd[*step]; - break; - case 1: - currentcmd = &rfdependcmd[*step]; - break; - case 2: - currentcmd = &postcommoncmd[*step]; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Invalid 'stage' = %d, Check it!\n" , *stage); - return true; - } - - if (currentcmd->cmdid == CMDID_END) { - if ((*stage) == 2) - return true; - (*stage)++; - (*step) = 0; - continue; - } - - switch (currentcmd->cmdid) { - case CMDID_SET_TXPOWEROWER_LEVEL: - rtl92ee_phy_set_txpower_level(hw, channel); - break; - case CMDID_WRITEPORT_ULONG: - rtl_write_dword(rtlpriv, currentcmd->para1, - currentcmd->para2); - break; - case CMDID_WRITEPORT_USHORT: - rtl_write_word(rtlpriv, currentcmd->para1, - (u16)currentcmd->para2); - break; - case CMDID_WRITEPORT_UCHAR: - rtl_write_byte(rtlpriv, currentcmd->para1, - (u8)currentcmd->para2); - break; - case CMDID_RF_WRITEREG: - for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { - rtlphy->rfreg_chnlval[rfpath] = - ((rtlphy->rfreg_chnlval[rfpath] & - 0xfffff00) | currentcmd->para2); - - rtl_set_rfreg(hw, (enum radio_path)rfpath, - currentcmd->para1, - 0x3ff, - rtlphy->rfreg_chnlval[rfpath]); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - - break; - } while (true); - - (*delay) = currentcmd->msdelay; - (*step)++; - return false; -} - -static bool _rtl92ee_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, u32 cmdtablesz, - enum swchnlcmd_id cmdid, - u32 para1, u32 para2, u32 msdelay) -{ - struct swchnlcmd *pcmd; - - if (cmdtable == NULL) { - RT_ASSERT(false, "cmdtable cannot be NULL.\n"); - return false; - } - - if (cmdtableidx >= cmdtablesz) - return false; - - pcmd = cmdtable + cmdtableidx; - pcmd->cmdid = cmdid; - pcmd->para1 = para1; - pcmd->para2 = para2; - pcmd->msdelay = msdelay; - return true; -} - -static u8 _rtl92ee_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) -{ - u32 reg_eac, reg_e94, reg_e9c; - u8 result = 0x00; - /* path-A IQK setting */ - /* PA/PAD controlled by 0x0 */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x180); - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - - rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82140303); - rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x68160000); - - /*LO calibration setting*/ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x00462911); - - /*One shot, path A LOK & IQK*/ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); - reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && - (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else - return result; - - return result; -} - -static u8 _rtl92ee_phy_path_b_iqk(struct ieee80211_hw *hw) -{ - u32 reg_eac, reg_eb4, reg_ebc; - u8 result = 0x00; - - /* PA/PAD controlled by 0x0 */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - rtl_set_rfreg(hw, RF90_PATH_B, 0xdf, RFREG_OFFSET_MASK, 0x180); - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); - - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x18008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - - rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x821403e2); - rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x68160000); - - /* LO calibration setting */ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x00462911); - - /*One shot, path B LOK & IQK*/ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xfa000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); - reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); - - if (!(reg_eac & BIT(31)) && - (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && - (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else - return result; - - return result; -} - -static u8 _rtl92ee_phy_path_a_rx_iqk(struct ieee80211_hw *hw, bool config_pathb) -{ - u32 reg_eac, reg_e94, reg_e9c, reg_ea4 , u32temp; - u8 result = 0x00; - - /*Get TXIMR Setting*/ - /*Modify RX IQK mode table*/ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - - rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf117b); - - /*PA/PAD control by 0x56, and set = 0x0*/ - rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x980); - rtl_set_rfreg(hw, RF90_PATH_A, 0x56, RFREG_OFFSET_MASK, 0x51000); - - /*enter IQK mode*/ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /*IQK Setting*/ - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - - /*path a IQK setting*/ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - - rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160c1f); - rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x68160c1f); - - /*LO calibration Setting*/ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); - - /*one shot,path A LOK & iqk*/ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xfa000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - /* Check failed */ - reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); - reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); - reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && - (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) { - result |= 0x01; - } else { - /* PA/PAD controlled by 0x0 */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x180); - return result; - } - - u32temp = 0x80007C00 | (reg_e94 & 0x3FF0000) | - ((reg_e9c & 0x3FF0000) >> 16); - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32temp); - /*RX IQK*/ - /*Modify RX IQK mode table*/ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - - rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); - - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ffa); - - /*PA/PAD control by 0x56, and set = 0x0*/ - rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x980); - rtl_set_rfreg(hw, RF90_PATH_A, 0x56, RFREG_OFFSET_MASK, 0x51000); - - /*enter IQK mode*/ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /*IQK Setting*/ - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - - /*path a IQK setting*/ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x18008c1c); - rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - - rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160c1f); - rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160c1f); - - /*LO calibration Setting*/ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a891); - /*one shot,path A LOK & iqk*/ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xfa000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - /*Check failed*/ - reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); - reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD); - - /*PA/PAD controlled by 0x0*/ - /*leave IQK mode*/ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x180); - /*if Tx is OK, check whether Rx is OK*/ - if (!(reg_eac & BIT(27)) && - (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && - (((reg_eac & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - - return result; -} - -static u8 _rtl92ee_phy_path_b_rx_iqk(struct ieee80211_hw *hw, bool config_pathb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 reg_eac, reg_eb4, reg_ebc, reg_ecc, reg_ec4, u32temp; - u8 result = 0x00; - - /*Get TXIMR Setting*/ - /*Modify RX IQK mode table*/ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - - rtl_set_rfreg(hw, RF90_PATH_B, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); - rtl_set_rfreg(hw, RF90_PATH_B, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, RF90_PATH_B, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); - rtl_set_rfreg(hw, RF90_PATH_B, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf117b); - - /*PA/PAD all off*/ - rtl_set_rfreg(hw, RF90_PATH_B, 0xdf, RFREG_OFFSET_MASK, 0x980); - rtl_set_rfreg(hw, RF90_PATH_B, 0x56, RFREG_OFFSET_MASK, 0x51000); - - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /*IQK Setting*/ - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - - /*path a IQK setting*/ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x18008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - - rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82160c1f); - rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x68160c1f); - - /*LO calibration Setting*/ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); - - /*one shot,path A LOK & iqk*/ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xfa000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - /* Check failed */ - reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); - reg_eb4 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_B, MASKDWORD); - reg_ebc = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_B, MASKDWORD); - - if (!(reg_eac & BIT(31)) && - (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && - (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) { - result |= 0x01; - } else { - /* PA/PAD controlled by 0x0 */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - rtl_set_rfreg(hw, RF90_PATH_B, 0xdf, RFREG_OFFSET_MASK, 0x180); - return result; - } - - u32temp = 0x80007C00 | (reg_eb4 & 0x3FF0000) | - ((reg_ebc & 0x3FF0000) >> 16); - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32temp); - /*RX IQK*/ - /*Modify RX IQK mode table*/ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - rtl_set_rfreg(hw, RF90_PATH_B, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); - - rtl_set_rfreg(hw, RF90_PATH_B, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, RF90_PATH_B, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0000f); - rtl_set_rfreg(hw, RF90_PATH_B, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ffa); - - /*PA/PAD all off*/ - rtl_set_rfreg(hw, RF90_PATH_B, 0xdf, RFREG_OFFSET_MASK, 0x980); - rtl_set_rfreg(hw, RF90_PATH_B, 0x56, RFREG_OFFSET_MASK, 0x51000); - - /*enter IQK mode*/ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /*IQK Setting*/ - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - - /*path b IQK setting*/ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x18008c1c); - - rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82160c1f); - rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28160c1f); - - /*LO calibration Setting*/ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a891); - /*one shot,path A LOK & iqk*/ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xfa000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - /*Check failed*/ - reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); - reg_ec4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_B_2, MASKDWORD); - reg_ecc = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_B_2, MASKDWORD); - /*PA/PAD controlled by 0x0*/ - /*leave IQK mode*/ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - rtl_set_rfreg(hw, RF90_PATH_B, 0xdf, RFREG_OFFSET_MASK, 0x180); - /*if Tx is OK, check whether Rx is OK*/ - if (!(reg_eac & BIT(30)) && - (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && - (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - else - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, "Path B Rx IQK fail!!\n"); - - return result; -} - -static void _rtl92ee_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, - bool b_iqk_ok, long result[][8], - u8 final_candidate, - bool btxonly) -{ - u32 oldval_0, x, tx0_a, reg; - long y, tx0_c; - - if (final_candidate == 0xFF) { - return; - } else if (b_iqk_ok) { - oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, - MASKDWORD) >> 22) & 0x3FF; - x = result[final_candidate][0]; - if ((x & 0x00000200) != 0) - x = x | 0xFFFFFC00; - tx0_a = (x * oldval_0) >> 8; - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31), - ((x * oldval_0 >> 7) & 0x1)); - y = result[final_candidate][1]; - if ((y & 0x00000200) != 0) - y = y | 0xFFFFFC00; - tx0_c = (y * oldval_0) >> 8; - rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, - ((tx0_c & 0x3C0) >> 6)); - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000, - (tx0_c & 0x3F)); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29), - ((y * oldval_0 >> 7) & 0x1)); - - if (btxonly) - return; - - reg = result[final_candidate][2]; - rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg); - - reg = result[final_candidate][3] & 0x3F; - rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg); - - reg = (result[final_candidate][3] >> 6) & 0xF; - rtl_set_bbreg(hw, ROFDM0_RXIQEXTANTA, 0xF0000000, reg); - } -} - -static void _rtl92ee_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw, - bool b_iqk_ok, long result[][8], - u8 final_candidate, - bool btxonly) -{ - u32 oldval_1, x, tx1_a, reg; - long y, tx1_c; - - if (final_candidate == 0xFF) { - return; - } else if (b_iqk_ok) { - oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, - MASKDWORD) >> 22) & 0x3FF; - x = result[final_candidate][4]; - if ((x & 0x00000200) != 0) - x = x | 0xFFFFFC00; - tx1_a = (x * oldval_1) >> 8; - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx1_a); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(27), - ((x * oldval_1 >> 7) & 0x1)); - y = result[final_candidate][5]; - if ((y & 0x00000200) != 0) - y = y | 0xFFFFFC00; - tx1_c = (y * oldval_1) >> 8; - rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000, - ((tx1_c & 0x3C0) >> 6)); - rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000, - (tx1_c & 0x3F)); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(25), - ((y * oldval_1 >> 7) & 0x1)); - - if (btxonly) - return; - - reg = result[final_candidate][6]; - rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg); - - reg = result[final_candidate][7] & 0x3F; - rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg); - - reg = (result[final_candidate][7] >> 6) & 0xF; - rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0xF0000000, reg); - } -} - -static void _rtl92ee_phy_save_adda_registers(struct ieee80211_hw *hw, - u32 *addareg, u32 *addabackup, - u32 registernum) -{ - u32 i; - - for (i = 0; i < registernum; i++) - addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD); -} - -static void _rtl92ee_phy_save_mac_registers(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) - macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); - - macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); -} - -static void _rtl92ee_phy_reload_adda_registers(struct ieee80211_hw *hw, - u32 *addareg, u32 *addabackup, - u32 regiesternum) -{ - u32 i; - - for (i = 0; i < regiesternum; i++) - rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]); -} - -static void _rtl92ee_phy_reload_mac_registers(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) - rtl_write_byte(rtlpriv, macreg[i], (u8)macbackup[i]); - rtl_write_dword(rtlpriv, macreg[i], macbackup[i]); -} - -static void _rtl92ee_phy_path_adda_on(struct ieee80211_hw *hw, u32 *addareg, - bool is_patha_on, bool is2t) -{ - u32 pathon; - u32 i; - - pathon = is_patha_on ? 0x0fc01616 : 0x0fc01616; - if (!is2t) { - pathon = 0x0fc01616; - rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0fc01616); - } else { - rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon); - } - - for (i = 1; i < IQK_ADDA_REG_NUM; i++) - rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathon); -} - -static void _rtl92ee_phy_mac_setting_calibration(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - rtl_set_bbreg(hw, 0x520, 0x00ff0000, 0xff); -} - -static void _rtl92ee_phy_path_a_standby(struct ieee80211_hw *hw) -{ - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); - rtl_set_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK, 0x10000); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); -} - -static bool _rtl92ee_phy_simularity_compare(struct ieee80211_hw *hw, - long result[][8], u8 c1, u8 c2) -{ - u32 i, j, diff, simularity_bitmap, bound; - - u8 final_candidate[2] = { 0xFF, 0xFF }; - bool bresult = true/*, is2t = true*/; - s32 tmp1, tmp2; - - bound = 8; - - simularity_bitmap = 0; - - for (i = 0; i < bound; i++) { - if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) { - if ((result[c1][i] & 0x00000200) != 0) - tmp1 = result[c1][i] | 0xFFFFFC00; - else - tmp1 = result[c1][i]; - - if ((result[c2][i] & 0x00000200) != 0) - tmp2 = result[c2][i] | 0xFFFFFC00; - else - tmp2 = result[c2][i]; - } else { - tmp1 = result[c1][i]; - tmp2 = result[c2][i]; - } - - diff = (tmp1 > tmp2) ? (tmp1 - tmp2) : (tmp2 - tmp1); - - if (diff > MAX_TOLERANCE) { - if ((i == 2 || i == 6) && !simularity_bitmap) { - if (result[c1][i] + result[c1][i + 1] == 0) - final_candidate[(i / 4)] = c2; - else if (result[c2][i] + result[c2][i + 1] == 0) - final_candidate[(i / 4)] = c1; - else - simularity_bitmap |= (1 << i); - } else { - simularity_bitmap |= (1 << i); - } - } - } - - if (simularity_bitmap == 0) { - for (i = 0; i < (bound / 4); i++) { - if (final_candidate[i] != 0xFF) { - for (j = i * 4; j < (i + 1) * 4 - 2; j++) - result[3][j] = - result[final_candidate[i]][j]; - bresult = false; - } - } - return bresult; - } - if (!(simularity_bitmap & 0x03)) {/*path A TX OK*/ - for (i = 0; i < 2; i++) - result[3][i] = result[c1][i]; - } - if (!(simularity_bitmap & 0x0c)) {/*path A RX OK*/ - for (i = 2; i < 4; i++) - result[3][i] = result[c1][i]; - } - if (!(simularity_bitmap & 0x30)) {/*path B TX OK*/ - for (i = 4; i < 6; i++) - result[3][i] = result[c1][i]; - } - if (!(simularity_bitmap & 0xc0)) {/*path B RX OK*/ - for (i = 6; i < 8; i++) - result[3][i] = result[c1][i]; - } - return false; -} - -static void _rtl92ee_phy_iq_calibrate(struct ieee80211_hw *hw, - long result[][8], u8 t, bool is2t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 i; - u8 patha_ok, pathb_ok; - u8 tmp_0xc50 = (u8)rtl_get_bbreg(hw, 0xc50, MASKBYTE0); - u8 tmp_0xc58 = (u8)rtl_get_bbreg(hw, 0xc58, MASKBYTE0); - u32 adda_reg[IQK_ADDA_REG_NUM] = { - 0x85c, 0xe6c, 0xe70, 0xe74, - 0xe78, 0xe7c, 0xe80, 0xe84, - 0xe88, 0xe8c, 0xed0, 0xed4, - 0xed8, 0xedc, 0xee0, 0xeec - }; - u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { - 0x522, 0x550, 0x551, 0x040 - }; - u32 iqk_bb_reg[IQK_BB_REG_NUM] = { - ROFDM0_TRXPATHENABLE, ROFDM0_TRMUXPAR, - RFPGA0_XCD_RFINTERFACESW, 0xb68, 0xb6c, - 0x870, 0x860, - 0x864, 0x800 - }; - const u32 retrycount = 2; - - if (t == 0) { - _rtl92ee_phy_save_adda_registers(hw, adda_reg, - rtlphy->adda_backup, - IQK_ADDA_REG_NUM); - _rtl92ee_phy_save_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - _rtl92ee_phy_save_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, - IQK_BB_REG_NUM); - } - - _rtl92ee_phy_path_adda_on(hw, adda_reg, true, is2t); - - /*BB setting*/ - rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00); - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKDWORD, 0x03a05600); - rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, MASKDWORD, 0x000800e4); - rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, MASKDWORD, 0x22208200); - - rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(10), 0x01); - rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(26), 0x01); - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10), 0x01); - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(10), 0x01); - - _rtl92ee_phy_mac_setting_calibration(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - /* Page B init*/ - /* IQ calibration setting*/ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - - for (i = 0 ; i < retrycount ; i++) { - patha_ok = _rtl92ee_phy_path_a_iqk(hw, is2t); - - if (patha_ok == 0x01) { - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "Path A Tx IQK Success!!\n"); - result[t][0] = (rtl_get_bbreg(hw, - RTX_POWER_BEFORE_IQK_A, - MASKDWORD) & 0x3FF0000) - >> 16; - result[t][1] = (rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, - MASKDWORD) & 0x3FF0000) - >> 16; - break; - } - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "Path A Tx IQK Fail!!, ret = 0x%x\n", - patha_ok); - } - - for (i = 0 ; i < retrycount ; i++) { - patha_ok = _rtl92ee_phy_path_a_rx_iqk(hw, is2t); - - if (patha_ok == 0x03) { - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "Path A Rx IQK Success!!\n"); - result[t][2] = (rtl_get_bbreg(hw, - RRX_POWER_BEFORE_IQK_A_2, - MASKDWORD) & 0x3FF0000) - >> 16; - result[t][3] = (rtl_get_bbreg(hw, - RRX_POWER_AFTER_IQK_A_2, - MASKDWORD) & 0x3FF0000) - >> 16; - break; - } - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "Path A Rx IQK Fail!!, ret = 0x%x\n", - patha_ok); - } - - if (0x00 == patha_ok) - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "Path A IQK failed!!, ret = 0\n"); - if (is2t) { - _rtl92ee_phy_path_a_standby(hw); - /* Turn Path B ADDA on */ - _rtl92ee_phy_path_adda_on(hw, adda_reg, false, is2t); - - /* IQ calibration setting */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - - for (i = 0 ; i < retrycount ; i++) { - pathb_ok = _rtl92ee_phy_path_b_iqk(hw); - if (pathb_ok == 0x01) { - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "Path B Tx IQK Success!!\n"); - result[t][4] = (rtl_get_bbreg(hw, - RTX_POWER_BEFORE_IQK_B, - MASKDWORD) & 0x3FF0000) - >> 16; - result[t][5] = (rtl_get_bbreg(hw, - RTX_POWER_AFTER_IQK_B, - MASKDWORD) & 0x3FF0000) - >> 16; - break; - } - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "Path B Tx IQK Fail!!, ret = 0x%x\n", - pathb_ok); - } - - for (i = 0 ; i < retrycount ; i++) { - pathb_ok = _rtl92ee_phy_path_b_rx_iqk(hw, is2t); - if (pathb_ok == 0x03) { - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "Path B Rx IQK Success!!\n"); - result[t][6] = (rtl_get_bbreg(hw, - RRX_POWER_BEFORE_IQK_B_2, - MASKDWORD) & 0x3FF0000) - >> 16; - result[t][7] = (rtl_get_bbreg(hw, - RRX_POWER_AFTER_IQK_B_2, - MASKDWORD) & 0x3FF0000) - >> 16; - break; - } - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "Path B Rx IQK Fail!!, ret = 0x%x\n", - pathb_ok); - } - - if (0x00 == pathb_ok) - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "Path B IQK failed!!, ret = 0\n"); - } - /* Back to BB mode, load original value */ - RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, - "IQK:Back to BB mode, load original value!\n"); - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0); - - if (t != 0) { - /* Reload ADDA power saving parameters */ - _rtl92ee_phy_reload_adda_registers(hw, adda_reg, - rtlphy->adda_backup, - IQK_ADDA_REG_NUM); - - /* Reload MAC parameters */ - _rtl92ee_phy_reload_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - - _rtl92ee_phy_reload_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, - IQK_BB_REG_NUM); - - /* Restore RX initial gain */ - rtl_set_bbreg(hw, 0xc50, MASKBYTE0, 0x50); - rtl_set_bbreg(hw, 0xc50, MASKBYTE0, tmp_0xc50); - if (is2t) { - rtl_set_bbreg(hw, 0xc50, MASKBYTE0, 0x50); - rtl_set_bbreg(hw, 0xc58, MASKBYTE0, tmp_0xc58); - } - - /* load 0xe30 IQC default value */ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x01008c00); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x01008c00); - } -} - -static void _rtl92ee_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) -{ - u8 tmpreg; - u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - tmpreg = rtl_read_byte(rtlpriv, 0xd03); - - if ((tmpreg & 0x70) != 0) - rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); - else - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - - if ((tmpreg & 0x70) != 0) { - rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); - - if (is2t) - rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, - MASK12BITS); - - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, - (rf_a_mode & 0x8FFFF) | 0x10000); - - if (is2t) - rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, - (rf_b_mode & 0x8FFFF) | 0x10000); - } - lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); - - rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); - - mdelay(100); - - if ((tmpreg & 0x70) != 0) { - rtl_write_byte(rtlpriv, 0xd03, tmpreg); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); - - if (is2t) - rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, - rf_b_mode); - } else { - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - } -} - -static void _rtl92ee_phy_set_rfpath_switch(struct ieee80211_hw *hw, - bool bmain, bool is2t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - - RT_TRACE(rtlpriv, COMP_INIT , DBG_LOUD , "\n"); - - if (is_hal_stop(rtlhal)) { - u8 u1btmp; - - u1btmp = rtl_read_byte(rtlpriv, REG_LEDCFG0); - rtl_write_byte(rtlpriv, REG_LEDCFG0, u1btmp | BIT(7)); - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); - } - if (is2t) { - if (bmain) - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(5) | BIT(6), 0x1); - else - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(5) | BIT(6), 0x2); - } else { - rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(8) | BIT(9), 0); - rtl_set_bbreg(hw, 0x914, MASKLWORD, 0x0201); - - /* We use the RF definition of MAIN and AUX, - * left antenna and right antenna repectively. - * Default output at AUX. - */ - if (bmain) { - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, - BIT(14) | BIT(13) | BIT(12), 0); - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(5) | BIT(4) | BIT(3), 0); - if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) - rtl_set_bbreg(hw, RCONFIG_RAM64x16, BIT(31), 0); - } else { - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, - BIT(14) | BIT(13) | BIT(12), 1); - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(5) | BIT(4) | BIT(3), 1); - if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) - rtl_set_bbreg(hw, RCONFIG_RAM64x16, BIT(31), 1); - } - } -} - -#undef IQK_ADDA_REG_NUM -#undef IQK_DELAY_TIME - -static u8 rtl92ee_get_rightchnlplace_for_iqk(u8 chnl) -{ - u8 channel_all[59] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, - 60, 62, 64, 100, 102, 104, 106, 108, 110, 112, - 114, 116, 118, 120, 122, 124, 126, 128, 130, - 132, 134, 136, 138, 140, 149, 151, 153, 155, - 157, 159, 161, 163, 165 - }; - u8 place = chnl; - - if (chnl > 14) { - for (place = 14; place < sizeof(channel_all); place++) { - if (channel_all[place] == chnl) - return place - 13; - } - } - - return 0; -} - -void rtl92ee_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - long result[4][8]; - u8 i, final_candidate; - bool b_patha_ok, b_pathb_ok; - long reg_e94, reg_e9c, reg_ea4, reg_eac; - long reg_eb4, reg_ebc, reg_ec4, reg_ecc; - bool is12simular, is13simular, is23simular; - u8 idx; - u32 iqk_bb_reg[IQK_BB_REG_NUM] = { - ROFDM0_XARXIQIMBALANCE, - ROFDM0_XBRXIQIMBALANCE, - ROFDM0_ECCATHRESHOLD, - ROFDM0_AGCRSSITABLE, - ROFDM0_XATXIQIMBALANCE, - ROFDM0_XBTXIQIMBALANCE, - ROFDM0_XCTXAFE, - ROFDM0_XDTXAFE, - ROFDM0_RXIQEXTANTA - }; - - if (b_recovery) { - _rtl92ee_phy_reload_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, 9); - return; - } - - for (i = 0; i < 8; i++) { - result[0][i] = 0; - result[1][i] = 0; - result[2][i] = 0; - - if ((i == 0) || (i == 2) || (i == 4) || (i == 6)) - result[3][i] = 0x100; - else - result[3][i] = 0; - } - final_candidate = 0xff; - b_patha_ok = false; - b_pathb_ok = false; - is12simular = false; - is23simular = false; - is13simular = false; - for (i = 0; i < 3; i++) { - _rtl92ee_phy_iq_calibrate(hw, result, i, true); - if (i == 1) { - is12simular = _rtl92ee_phy_simularity_compare(hw, - result, - 0, 1); - if (is12simular) { - final_candidate = 0; - break; - } - } - - if (i == 2) { - is13simular = _rtl92ee_phy_simularity_compare(hw, - result, - 0, 2); - if (is13simular) { - final_candidate = 0; - break; - } - is23simular = _rtl92ee_phy_simularity_compare(hw, - result, - 1, 2); - if (is23simular) - final_candidate = 1; - else - final_candidate = 3; - } - } - - for (i = 0; i < 4; i++) { - reg_e94 = result[i][0]; - reg_e9c = result[i][1]; - reg_ea4 = result[i][2]; - reg_eac = result[i][3]; - reg_eb4 = result[i][4]; - reg_ebc = result[i][5]; - reg_ec4 = result[i][6]; - reg_ecc = result[i][7]; - } - - if (final_candidate != 0xff) { - reg_e94 = result[final_candidate][0]; - rtlphy->reg_e94 = reg_e94; - reg_e9c = result[final_candidate][1]; - rtlphy->reg_e9c = reg_e9c; - reg_ea4 = result[final_candidate][2]; - reg_eac = result[final_candidate][3]; - reg_eb4 = result[final_candidate][4]; - rtlphy->reg_eb4 = reg_eb4; - reg_ebc = result[final_candidate][5]; - rtlphy->reg_ebc = reg_ebc; - reg_ec4 = result[final_candidate][6]; - reg_ecc = result[final_candidate][7]; - b_patha_ok = true; - b_pathb_ok = true; - } else { - rtlphy->reg_e94 = 0x100; - rtlphy->reg_eb4 = 0x100; - rtlphy->reg_e9c = 0x0; - rtlphy->reg_ebc = 0x0; - } - - if (reg_e94 != 0) - _rtl92ee_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result, - final_candidate, - (reg_ea4 == 0)); - - _rtl92ee_phy_path_b_fill_iqk_matrix(hw, b_pathb_ok, result, - final_candidate, - (reg_ec4 == 0)); - - idx = rtl92ee_get_rightchnlplace_for_iqk(rtlphy->current_channel); - - /* To Fix BSOD when final_candidate is 0xff */ - if (final_candidate < 4) { - for (i = 0; i < IQK_MATRIX_REG_NUM; i++) - rtlphy->iqk_matrix[idx].value[0][i] = - result[final_candidate][i]; - - rtlphy->iqk_matrix[idx].iqk_done = true; - } - _rtl92ee_phy_save_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, 9); -} - -void rtl92ee_phy_lc_calibrate(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = &rtlpriv->rtlhal; - u32 timeout = 2000, timecount = 0; - - while (rtlpriv->mac80211.act_scanning && timecount < timeout) { - udelay(50); - timecount += 50; - } - - rtlphy->lck_inprogress = true; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "LCK:Start!!! currentband %x delay %d ms\n", - rtlhal->current_bandtype, timecount); - - _rtl92ee_phy_lc_calibrate(hw, false); - - rtlphy->lck_inprogress = false; -} - -void rtl92ee_phy_ap_calibrate(struct ieee80211_hw *hw, char delta) -{ -} - -void rtl92ee_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) -{ - _rtl92ee_phy_set_rfpath_switch(hw, bmain, false); -} - -bool rtl92ee_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - bool postprocessing = false; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "-->IO Cmd(%#x), set_io_inprogress(%d)\n", - iotype, rtlphy->set_io_inprogress); - do { - switch (iotype) { - case IO_CMD_RESUME_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Resume DM after scan.\n"); - postprocessing = true; - break; - case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Pause DM before scan.\n"); - postprocessing = true; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - } while (false); - if (postprocessing && !rtlphy->set_io_inprogress) { - rtlphy->set_io_inprogress = true; - rtlphy->current_io_type = iotype; - } else { - return false; - } - rtl92ee_phy_set_io(hw); - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); - return true; -} - -static void rtl92ee_phy_set_io(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct dig_t *dm_dig = &rtlpriv->dm_digtable; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "--->Cmd(%#x), set_io_inprogress(%d)\n", - rtlphy->current_io_type, rtlphy->set_io_inprogress); - switch (rtlphy->current_io_type) { - case IO_CMD_RESUME_DM_BY_SCAN: - rtl92ee_dm_write_dig(hw, rtlphy->initgain_backup.xaagccore1); - rtl92ee_dm_write_cck_cca_thres(hw, rtlphy->initgain_backup.cca); - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE , "no set txpower\n"); - rtl92ee_phy_set_txpower_level(hw, rtlphy->current_channel); - break; - case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: - /* 8192eebt */ - rtlphy->initgain_backup.xaagccore1 = dm_dig->cur_igvalue; - rtl92ee_dm_write_dig(hw, 0x17); - rtlphy->initgain_backup.cca = dm_dig->cur_cck_cca_thres; - rtl92ee_dm_write_cck_cca_thres(hw, 0x40); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - rtlphy->set_io_inprogress = false; - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "(%#x)\n", rtlphy->current_io_type); -} - -static void rtl92ee_phy_set_rf_on(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - /*rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);*/ - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); -} - -static void _rtl92ee_phy_set_rf_sleep(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); -} - -static bool _rtl92ee_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool bresult = true; - u8 i, queue_id; - struct rtl8192_tx_ring *ring = NULL; - - switch (rfpwr_state) { - case ERFON: - if ((ppsc->rfpwr_state == ERFOFF) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { - bool rtstatus; - u32 initializecount = 0; - - do { - initializecount++; - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic enable\n"); - rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && (initializecount < 10)); - RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - } else { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFON sleeping:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc->last_sleep_jiffies)); - ppsc->last_awake_jiffies = jiffies; - rtl92ee_phy_set_rf_on(hw); - } - if (mac->link_state == MAC80211_LINKED) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_LINK); - else - rtlpriv->cfg->ops->led_control(hw, LED_CTL_NO_LINK); - break; - case ERFOFF: - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (queue_id == BEACON_QUEUE || - skb_queue_len(&ring->queue) == 0) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", - (i + 1), queue_id, - skb_queue_len(&ring->queue)); - - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic disable\n"); - rtl_ps_disable_nic(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - } else { - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - } else { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_POWER_OFF); - } - } - break; - case ERFSLEEP: - if (ppsc->rfpwr_state == ERFOFF) - break; - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (skb_queue_len(&ring->queue) == 0) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", - (i + 1), queue_id, - skb_queue_len(&ring->queue)); - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFSLEEP awaked:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc->last_awake_jiffies)); - ppsc->last_sleep_jiffies = jiffies; - _rtl92ee_phy_set_rf_sleep(hw); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - bresult = false; - break; - } - if (bresult) - ppsc->rfpwr_state = rfpwr_state; - return bresult; -} - -bool rtl92ee_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - bool bresult = false; - - if (rfpwr_state == ppsc->rfpwr_state) - return bresult; - bresult = _rtl92ee_phy_set_rf_power_state(hw, rfpwr_state); - return bresult; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/phy.h b/drivers/net/wireless/rtlwifi/rtl8192ee/phy.h deleted file mode 100644 index c6e97c8df54c..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/phy.h +++ /dev/null @@ -1,153 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92E_PHY_H__ -#define __RTL92E_PHY_H__ - -/* MAX_TX_COUNT must always set to 4, otherwise read efuse table sequence - * will be wrong. - */ -#define MAX_TX_COUNT 4 -#define TX_1S 0 -#define TX_2S 1 -#define TX_3S 2 -#define TX_4S 3 - -#define MAX_POWER_INDEX 0x3f - -#define MAX_PRECMD_CNT 16 -#define MAX_RFDEPENDCMD_CNT 16 -#define MAX_POSTCMD_CNT 16 - -#define MAX_DOZE_WAITING_TIMES_9x 64 - -#define RT_CANNOT_IO(hw) false -#define HIGHPOWER_RADIOA_ARRAYLEN 22 - -#define IQK_ADDA_REG_NUM 16 -#define IQK_MAC_REG_NUM 4 -#define IQK_BB_REG_NUM 9 -#define MAX_TOLERANCE 5 -#define IQK_DELAY_TIME 10 -#define index_mapping_NUM 15 - -#define APK_BB_REG_NUM 5 -#define APK_AFE_REG_NUM 16 -#define APK_CURVE_REG_NUM 4 -#define PATH_NUM 2 - -#define LOOP_LIMIT 5 -#define MAX_STALL_TIME 50 -#define ANTENNADIVERSITYVALUE 0x80 -#define MAX_TXPWR_IDX_NMODE_92S 63 -#define RESET_CNT_LIMIT 3 - -#define RF6052_MAX_PATH 2 - -#define CT_OFFSET_MAC_ADDR 0X16 - -#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A -#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 -#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 -#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 -#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C - -#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F -#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 - -#define CT_OFFSET_CHANNEL_PLAH 0x75 -#define CT_OFFSET_THERMAL_METER 0x78 -#define CT_OFFSET_RF_OPTION 0x79 -#define CT_OFFSET_VERSION 0x7E -#define CT_OFFSET_CUSTOMER_ID 0x7F - -#define RTL92C_MAX_PATH_NUM 2 - -enum swchnlcmd_id { - CMDID_END, - CMDID_SET_TXPOWEROWER_LEVEL, - CMDID_BBREGWRITE10, - CMDID_WRITEPORT_ULONG, - CMDID_WRITEPORT_USHORT, - CMDID_WRITEPORT_UCHAR, - CMDID_RF_WRITEREG, -}; - -struct swchnlcmd { - enum swchnlcmd_id cmdid; - u32 para1; - u32 para2; - u32 msdelay; -}; - -enum baseband_config_type { - BASEBAND_CONFIG_PHY_REG = 0, - BASEBAND_CONFIG_AGC_TAB = 1, -}; - -enum ant_div_type { - NO_ANTDIV = 0xFF, - CG_TRX_HW_ANTDIV = 0x01, - CGCS_RX_HW_ANTDIV = 0x02, - FIXED_HW_ANTDIV = 0x03, - CG_TRX_SMART_ANTDIV = 0x04, - CGCS_RX_SW_ANTDIV = 0x05, -}; - -u32 rtl92ee_phy_query_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask); -void rtl92ee_phy_set_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, u32 data); -u32 rtl92ee_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask); -void rtl92ee_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask, u32 data); -bool rtl92ee_phy_mac_config(struct ieee80211_hw *hw); -bool rtl92ee_phy_bb_config(struct ieee80211_hw *hw); -bool rtl92ee_phy_rf_config(struct ieee80211_hw *hw); -void rtl92ee_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -void rtl92ee_phy_get_txpower_level(struct ieee80211_hw *hw, - long *powerlevel); -void rtl92ee_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -void rtl92ee_phy_scan_operation_backup(struct ieee80211_hw *hw, - u8 operation); -void rtl92ee_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -void rtl92ee_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); -void rtl92ee_phy_sw_chnl_callback(struct ieee80211_hw *hw); -u8 rtl92ee_phy_sw_chnl(struct ieee80211_hw *hw); -void rtl92ee_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -void rtl92ee_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); -void rtl92ee_phy_lc_calibrate(struct ieee80211_hw *hw); -void rtl92ee_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); -bool rtl92ee_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -bool rtl92ee_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); -bool rtl92ee_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.c b/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.c deleted file mode 100644 index 1a701d007f0c..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.c +++ /dev/null @@ -1,112 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "pwrseq.h" - -/* drivers should parse below arrays and do the corresponding actions */ - -/*3 Power on Array*/ -struct wlan_pwr_cfg rtl8192E_power_on_flow - [RTL8192E_TRANS_CARDEMU_TO_ACT_STEPS + - RTL8192E_TRANS_END_STEPS] = { - RTL8192E_TRANS_CARDEMU_TO_ACT - RTL8192E_TRANS_END -}; - -/*3Radio off GPIO Array */ -struct wlan_pwr_cfg rtl8192E_radio_off_flow - [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8192E_TRANS_END_STEPS] = { - RTL8192E_TRANS_ACT_TO_CARDEMU - RTL8192E_TRANS_END -}; - -/*3Card Disable Array*/ -struct wlan_pwr_cfg rtl8192E_card_disable_flow - [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8192E_TRANS_END_STEPS] = { - RTL8192E_TRANS_ACT_TO_CARDEMU - RTL8192E_TRANS_CARDEMU_TO_CARDDIS - RTL8192E_TRANS_END -}; - -/*3 Card Enable Array*/ -struct wlan_pwr_cfg rtl8192E_card_enable_flow - [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8192E_TRANS_END_STEPS] = { - RTL8192E_TRANS_CARDDIS_TO_CARDEMU - RTL8192E_TRANS_CARDEMU_TO_ACT - RTL8192E_TRANS_END -}; - -/*3Suspend Array*/ -struct wlan_pwr_cfg rtl8192E_suspend_flow - [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8192E_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8192E_TRANS_END_STEPS] = { - RTL8192E_TRANS_ACT_TO_CARDEMU - RTL8192E_TRANS_CARDEMU_TO_SUS - RTL8192E_TRANS_END -}; - -/*3 Resume Array*/ -struct wlan_pwr_cfg rtl8192E_resume_flow - [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8192E_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8192E_TRANS_END_STEPS] = { - RTL8192E_TRANS_SUS_TO_CARDEMU - RTL8192E_TRANS_CARDEMU_TO_ACT - RTL8192E_TRANS_END -}; - -/*3HWPDN Array*/ -struct wlan_pwr_cfg rtl8192E_hwpdn_flow - [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8192E_TRANS_END_STEPS] = { - RTL8192E_TRANS_ACT_TO_CARDEMU - RTL8192E_TRANS_CARDEMU_TO_PDN - RTL8192E_TRANS_END -}; - -/*3 Enter LPS */ -struct wlan_pwr_cfg rtl8192E_enter_lps_flow - [RTL8192E_TRANS_ACT_TO_LPS_STEPS + - RTL8192E_TRANS_END_STEPS] = { - /*FW behavior*/ - RTL8192E_TRANS_ACT_TO_LPS - RTL8192E_TRANS_END -}; - -/*3 Leave LPS */ -struct wlan_pwr_cfg rtl8192E_leave_lps_flow - [RTL8192E_TRANS_LPS_TO_ACT_STEPS + - RTL8192E_TRANS_END_STEPS] = { - /*FW behavior*/ - RTL8192E_TRANS_LPS_TO_ACT - RTL8192E_TRANS_END -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.h b/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.h deleted file mode 100644 index 781eeaa6af49..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/pwrseq.h +++ /dev/null @@ -1,340 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92E_PWRSEQ_H__ -#define __RTL92E_PWRSEQ_H__ - -#include "../pwrseqcmd.h" -/** - * Check document WM-20110607-Paul-RTL8192E_Power_Architecture-R02.vsd - * There are 6 HW Power States: - * 0: POFF--Power Off - * 1: PDN--Power Down - * 2: CARDEMU--Card Emulation - * 3: ACT--Active Mode - * 4: LPS--Low Power State - * 5: SUS--Suspend - * - * The transision from different states are defined below - * TRANS_CARDEMU_TO_ACT - * TRANS_ACT_TO_CARDEMU - * TRANS_CARDEMU_TO_SUS - * TRANS_SUS_TO_CARDEMU - * TRANS_CARDEMU_TO_PDN - * TRANS_ACT_TO_LPS - * TRANS_LPS_TO_ACT - * - * TRANS_END - * PWR SEQ Version: rtl8192E_PwrSeq_V09.h - */ - -#define RTL8192E_TRANS_CARDEMU_TO_ACT_STEPS 18 -#define RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS 18 -#define RTL8192E_TRANS_CARDEMU_TO_SUS_STEPS 18 -#define RTL8192E_TRANS_SUS_TO_CARDEMU_STEPS 18 -#define RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS 18 -#define RTL8192E_TRANS_PDN_TO_CARDEMU_STEPS 18 -#define RTL8192E_TRANS_ACT_TO_LPS_STEPS 23 -#define RTL8192E_TRANS_LPS_TO_ACT_STEPS 23 -#define RTL8192E_TRANS_END_STEPS 1 - -#define RTL8192E_TRANS_CARDEMU_TO_ACT \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ - /* disable HWPDN 0x04[15]=0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(7), 0}, \ - /* disable SW LPS 0x04[10]=0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(2), 0}, \ - /* disable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, (BIT(4)|BIT(3)), 0}, \ - /* wait till 0x04[17] = 1 power ready*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_POLLING, BIT(1), BIT(1)}, \ - /* release WLON reset 0x04[16]=1*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(0), BIT(0)}, \ - /* polling until return 0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(0), BIT(0)}, \ - /**/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_POLLING, BIT(0), 0}, - -#define RTL8192E_TRANS_ACT_TO_CARDEMU \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ - /*0x1F[7:0] = 0 turn off RF*/ \ - {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0}, \ - /*0x4C[23]=0x4E[7]=0, switch DPDT_SEL_P output from register 0x65[2] */\ - {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(7), 0}, \ - /*0x04[9] = 1 turn off MAC by HW state machine*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(1), BIT(1)}, \ - /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_POLLING, BIT(1), 0}, - -#define RTL8192E_TRANS_CARDEMU_TO_SUS \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ - /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(4) | BIT(3), (BIT(4) | BIT(3))},\ - /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \ - PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \ - /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3) | BIT(4)},\ - /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO , PWR_CMD_WRITE, BIT(0), BIT(0)}, \ - /*wait power state to suspend*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO , PWR_CMD_POLLING, BIT(1), 0}, - -#define RTL8192E_TRANS_SUS_TO_CARDEMU \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ - /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO , PWR_CMD_WRITE, BIT(0), 0}, \ - /*wait power state to suspend*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO , PWR_CMD_POLLING, BIT(1), BIT(1)}, \ - /*0x04[12:11] = 2b'01enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, - -#define RTL8192E_TRANS_CARDEMU_TO_CARDDIS \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ - /*0x07=0x20 , SOP option to disable BG/MB*/ \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0x20}, \ - /*Unlock small LDO Register*/ \ - {0x00CC, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(2), BIT(2)}, \ - /*Disable small LDO*/ \ - {0x0011, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(0), 0}, \ - /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \ - PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \ - /*0x04[10] = 1, enable SW LPS*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(2), BIT(2)}, \ - /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO , PWR_CMD_WRITE, BIT(0), BIT(0)}, \ - /*wait power state to suspend*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO , PWR_CMD_POLLING, BIT(1), 0}, - -#define RTL8192E_TRANS_CARDDIS_TO_CARDEMU \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ - /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO , PWR_CMD_WRITE, BIT(0), 0}, \ - /*wait power state to suspend*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO , PWR_CMD_POLLING, BIT(1), BIT(1)}, \ - /*Enable small LDO*/ \ - {0x0011, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(0), BIT(0)}, \ - /*Lock small LDO Register*/ \ - {0x00CC, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(2), 0}, \ - /*0x04[12:11] = 2b'01enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, - -#define RTL8192E_TRANS_CARDEMU_TO_PDN \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ - /* 0x04[16] = 0*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(0), 0}, \ - /* 0x04[15] = 1*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(7), BIT(7)}, - -#define RTL8192E_TRANS_PDN_TO_CARDEMU \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ - /* 0x04[15] = 0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(7), 0}, - -#define RTL8192E_TRANS_ACT_TO_LPS \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ - /*PCIe DMA stop*/ \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0xFF}, \ - /*Tx Pause*/ \ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0xFF}, \ - /*Should be zero if no packet is transmitting*/ \ - {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_POLLING, 0xFF, 0}, \ - /*Should be zero if no packet is transmitting*/ \ - {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_POLLING, 0xFF, 0}, \ - /*Should be zero if no packet is transmitting*/ \ - {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_POLLING, 0xFF, 0}, \ - /*Should be zero if no packet is transmitting*/ \ - {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_POLLING, 0xFF, 0}, \ - /*CCK and OFDM are disabled,and clock are gated*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(0), 0}, \ - /*Delay 1us*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US}, \ - /*Whole BB is reset*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(1), 0}, \ - /*Reset MAC TRX*/ \ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0x03}, \ - /*check if removed later*/ \ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(1), 0}, \ - /*When driver enter Sus/ Disable, enable LOP for BT*/ \ - {0x0093, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0x00}, \ - /*Respond TxOK to scheduler*/ \ - {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(5), BIT(5)}, - -#define RTL8192E_TRANS_LPS_TO_ACT \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ - /*SDIO RPWM, For Repeatly In and out, Taggle bit should be changed*/\ - {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO , PWR_CMD_WRITE, 0xFF, 0x84}, \ - /*USB RPWM*/ \ - {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0x84}, \ - /*PCIe RPWM*/ \ - {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0x84}, \ - /*Delay*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, \ - /*0x08[4] = 0 switch TSF to 40M*/ \ - {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(4), 0}, \ - /*Polling 0x109[7]=0 TSF in 40M*/ \ - {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_POLLING, BIT(7), 0}, \ - /*0x101[1] = 1*/ \ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(1), BIT(1)}, \ - /*0x100[7:0] = 0xFF enable WMAC TRX*/ \ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0xFF}, \ - /* 0x02[1:0] = 2b'11 enable BB macro*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(1) | BIT(0), BIT(1) | BIT(0)},\ - /*0x522 = 0*/ \ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0}, \ - /*Clear ISR*/ \ - {0x013D, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC , PWR_CMD_WRITE, 0xFF, 0xFF}, - -#define RTL8192E_TRANS_END \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ - {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - 0, PWR_CMD_END, 0, 0}, - -extern struct wlan_pwr_cfg rtl8192E_power_on_flow - [RTL8192E_TRANS_CARDEMU_TO_ACT_STEPS + - RTL8192E_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8192E_radio_off_flow - [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8192E_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8192E_card_disable_flow - [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8192E_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8192E_card_enable_flow - [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8192E_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8192E_suspend_flow - [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8192E_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8192E_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8192E_resume_flow - [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8192E_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8192E_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8192E_hwpdn_flow - [RTL8192E_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8192E_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8192E_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8192E_enter_lps_flow - [RTL8192E_TRANS_ACT_TO_LPS_STEPS + - RTL8192E_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8192E_leave_lps_flow - [RTL8192E_TRANS_LPS_TO_ACT_STEPS + - RTL8192E_TRANS_END_STEPS]; - -/* RTL8192EE Power Configuration CMDs for PCIe interface */ -#define RTL8192E_NIC_PWR_ON_FLOW rtl8192E_power_on_flow -#define RTL8192E_NIC_RF_OFF_FLOW rtl8192E_radio_off_flow -#define RTL8192E_NIC_DISABLE_FLOW rtl8192E_card_disable_flow -#define RTL8192E_NIC_ENABLE_FLOW rtl8192E_card_enable_flow -#define RTL8192E_NIC_SUSPEND_FLOW rtl8192E_suspend_flow -#define RTL8192E_NIC_RESUME_FLOW rtl8192E_resume_flow -#define RTL8192E_NIC_PDN_FLOW rtl8192E_hwpdn_flow -#define RTL8192E_NIC_LPS_ENTER_FLOW rtl8192E_enter_lps_flow -#define RTL8192E_NIC_LPS_LEAVE_FLOW rtl8192E_leave_lps_flow - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h deleted file mode 100644 index 1eaa1fab550d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/reg.h +++ /dev/null @@ -1,2233 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92E_REG_H__ -#define __RTL92E_REG_H__ - -#define TXPKT_BUF_SELECT 0x69 -#define RXPKT_BUF_SELECT 0xA5 -#define DISABLE_TRXPKT_BUF_ACCESS 0x0 - -#define REG_SYS_ISO_CTRL 0x0000 -#define REG_SYS_FUNC_EN 0x0002 -#define REG_APS_FSMCO 0x0004 -#define REG_SYS_CLKR 0x0008 -#define REG_9346CR 0x000A -#define REG_EE_VPD 0x000C -#define REG_SYS_SWR_CTRL1 0x0010 -#define REG_SPS0_CTRL 0x0011 -#define REG_SYS_SWR_CTRL2 0x0014 -#define REG_SYS_SWR_CTRL3 0x0018 -#define REG_RSV_CTRL 0x001C -#define REG_RF_CTRL 0x001F -#define REG_LPLDO_CTRL 0x0023 -#define REG_AFE_CTRL1 0x0024 -#define REG_AFE_XTAL_CTRL 0x0024 -#define REG_AFE_CTRL2 0x0028 -#define REG_MAC_PHY_CTRL 0x002c -#define REG_AFE_CTRL3 0x002c -#define REG_EFUSE_CTRL 0x0030 -#define REG_EFUSE_TEST 0x0034 -#define REG_PWR_DATA 0x0038 -#define REG_CAL_TIMER 0x003C -#define REG_ACLK_MON 0x003E -#define REG_GPIO_MUXCFG 0x0040 -#define REG_GPIO_IO_SEL 0x0042 -#define REG_MAC_PINMUX_CFG 0x0043 -#define REG_GPIO_PIN_CTRL 0x0044 -#define REG_GPIO_INTM 0x0048 -#define REG_LEDCFG0 0x004C -#define REG_LEDCFG1 0x004D -#define REG_LEDCFG2 0x004E -#define REG_LEDCFG3 0x004F -#define REG_FSIMR 0x0050 -#define REG_FSISR 0x0054 -#define REG_HSIMR 0x0058 -#define REG_HSISR 0x005c -#define REG_SDIO_CTRL 0x0070 -#define REG_OPT_CTRL 0x0074 -#define REG_GPIO_OUTPUT 0x006c -#define REG_AFE_CTRL4 0x0078 -#define REG_MCUFWDL 0x0080 - -#define REG_HIMR 0x00B0 -#define REG_HISR 0x00B4 -#define REG_HIMRE 0x00B8 -#define REG_HISRE 0x00BC - -#define REG_PMC_DBG_CTRL2 0x00CC -#define REG_EFUSE_ACCESS 0x00CF -#define REG_HPON_FSM 0x00EC -#define REG_SYS_CFG1 0x00F0 -#define REG_MAC_PHY_CTRL_NORMAL 0x00F8 -#define REG_SYS_CFG2 0x00FC - -#define REG_CR 0x0100 -#define REG_PBP 0x0104 -#define REG_PKT_BUFF_ACCESS_CTRL 0x0106 -#define REG_TRXDMA_CTRL 0x010C -#define REG_TRXFF_BNDY 0x0114 -#define REG_TRXFF_STATUS 0x0118 -#define REG_RXFF_PTR 0x011C - -#define REG_CPWM 0x012F -#define REG_FWIMR 0x0130 -#define REG_FWISR 0x0134 -#define REG_PKTBUF_DBG_CTRL 0x0140 -#define REG_RXPKTBUF_CTRL 0x0142 -#define REG_PKTBUF_DBG_DATA_L 0x0144 -#define REG_PKTBUF_DBG_DATA_H 0x0148 - -#define REG_TC0_CTRL 0x0150 -#define REG_TC1_CTRL 0x0154 -#define REG_TC2_CTRL 0x0158 -#define REG_TC3_CTRL 0x015C -#define REG_TC4_CTRL 0x0160 -#define REG_TCUNIT_BASE 0x0164 -#define REG_RSVD3 0x0168 -#define REG_C2HEVT_MSG_NORMAL 0x01A0 -#define REG_C2HEVT_CLEAR 0x01AF -#define REG_MCUTST_1 0x01c0 -#define REG_MCUTST_WOWLAN 0x01C7 -#define REG_FMETHR 0x01C8 -#define REG_HMETFR 0x01CC -#define REG_HMEBOX_0 0x01D0 -#define REG_HMEBOX_1 0x01D4 -#define REG_HMEBOX_2 0x01D8 -#define REG_HMEBOX_3 0x01DC - -#define REG_LLT_INIT 0x01E0 - -#define REG_HMEBOX_EXT_0 0x01F0 -#define REG_HMEBOX_EXT_1 0x01F4 -#define REG_HMEBOX_EXT_2 0x01F8 -#define REG_HMEBOX_EXT_3 0x01FC - -/*----------------------------------------------------- - * - * 0x0200h ~ 0x027Fh TXDMA Configuration - * - *----------------------------------------------------- - */ -#define REG_RQPN 0x0200 -#define REG_FIFOPAGE 0x0204 -#define REG_DWBCN0_CTRL 0x0208 -#define REG_TXDMA_OFFSET_CHK 0x020C -#define REG_TXDMA_STATUS 0x0210 -#define REG_RQPN_NPQ 0x0214 -#define REG_AUTO_LLT 0x0224 -#define REG_DWBCN1_CTRL 0x0228 - -/*----------------------------------------------------- - * - * 0x0280h ~ 0x02FFh RXDMA Configuration - * - *----------------------------------------------------- - */ -#define REG_RXDMA_AGG_PG_TH 0x0280 -#define REG_FW_UPD_RDPTR 0x0284 -#define REG_RXDMA_CONTROL 0x0286 -#define REG_RXPKT_NUM 0x0287 -#define REG_RXDMA_STATUS 0x0288 -#define REG_RXDMA_PRO 0x0290 -#define REG_EARLY_MODE_CONTROL 0x02BC -#define REG_RSVD5 0x02F0 -#define REG_RSVD6 0x02F4 - -/*----------------------------------------------------- - * - * 0x0300h ~ 0x03FFh PCIe - * - *----------------------------------------------------- - */ -#define REG_PCIE_CTRL_REG 0x0300 -#define REG_INT_MIG 0x0304 -#define REG_BCNQ_DESA 0x0308 -#define REG_MGQ_DESA 0x0310 -#define REG_VOQ_DESA 0x0318 -#define REG_VIQ_DESA 0x0320 -#define REG_BEQ_DESA 0x0328 -#define REG_BKQ_DESA 0x0330 -#define REG_RX_DESA 0x0338 -#define REG_HQ0_DESA 0x0340 -#define REG_HQ1_DESA 0x0348 -#define REG_HQ2_DESA 0x0350 -#define REG_HQ3_DESA 0x0358 -#define REG_HQ4_DESA 0x0360 -#define REG_HQ5_DESA 0x0368 -#define REG_HQ6_DESA 0x0370 -#define REG_HQ7_DESA 0x0378 -#define REG_MGQ_TXBD_NUM 0x0380 -#define REG_RX_RXBD_NUM 0x0382 -#define REG_VOQ_TXBD_NUM 0x0384 -#define REG_VIQ_TXBD_NUM 0x0386 -#define REG_BEQ_TXBD_NUM 0x0388 -#define REG_BKQ_TXBD_NUM 0x038A -#define REG_HI0Q_TXBD_NUM 0x038C -#define REG_HI1Q_TXBD_NUM 0x038E -#define REG_HI2Q_TXBD_NUM 0x0390 -#define REG_HI3Q_TXBD_NUM 0x0392 -#define REG_HI4Q_TXBD_NUM 0x0394 -#define REG_HI5Q_TXBD_NUM 0x0396 -#define REG_HI6Q_TXBD_NUM 0x0398 -#define REG_HI7Q_TXBD_NUM 0x039A -#define REG_TSFTIMER_HCI 0x039C -/*Read Write Point*/ -#define REG_VOQ_TXBD_IDX 0x03A0 -#define REG_VIQ_TXBD_IDX 0x03A4 -#define REG_BEQ_TXBD_IDX 0x03A8 -#define REG_BKQ_TXBD_IDX 0x03AC -#define REG_MGQ_TXBD_IDX 0x03B0 -#define REG_RXQ_TXBD_IDX 0x03B4 - -#define REG_HI0Q_TXBD_IDX 0x03B8 -#define REG_HI1Q_TXBD_IDX 0x03BC -#define REG_HI2Q_TXBD_IDX 0x03C0 -#define REG_HI3Q_TXBD_IDX 0x03C4 - -#define REG_HI4Q_TXBD_IDX 0x03C8 -#define REG_HI5Q_TXBD_IDX 0x03CC -#define REG_HI6Q_TXBD_IDX 0x03D0 -#define REG_HI7Q_TXBD_IDX 0x03D4 -#define REG_PCIE_HCPWM 0x03D8 -#define REG_PCIE_CTRL2 0x03DB -#define REG_PCIE_HRPWM 0x03DC -#define REG_H2C_MSG_DRV2FW_INFO 0x03E0 -#define REG_PCIE_C2H_MSG_REQUEST 0x03E4 -#define REG_BACKDOOR_DBI_WDATA 0x03E8 -#define REG_BACKDOOR_DBI_RDATA 0x03EC -#define REG_BACKDOOR_DBI_DATA 0x03F0 -#define REG_MDIO 0x03F4 -#define REG_MDIO_DATA 0x03F8 - -#define REG_HDAQ_DESA_NODEF 0x0000 -#define REG_CMDQ_DESA_NODEF 0x0000 -/* spec version 11 - *----------------------------------------------------- - * - * 0x0400h ~ 0x047Fh Protocol Configuration - * - *----------------------------------------------------- - */ -#define REG_VOQ_INFORMATION 0x0400 -#define REG_VIQ_INFORMATION 0x0404 -#define REG_BEQ_INFORMATION 0x0408 -#define REG_BKQ_INFORMATION 0x040C -#define REG_MGQ_INFORMATION 0x0410 -#define REG_HGQ_INFORMATION 0x0414 -#define REG_BCNQ_INFORMATION 0x0418 -#define REG_TXPKT_EMPTY 0x041A - -#define REG_FWHW_TXQ_CTRL 0x0420 -#define REG_HWSEQ_CTRL 0x0423 -#define REG_BCNQ_BDNY 0x0424 -#define REG_MGQ_BDNY 0x0425 -#define REG_LIFECTRL_CTRL 0x0426 -#define REG_MULTI_BCNQ_OFFSET 0x0427 -#define REG_SPEC_SIFS 0x0428 -#define REG_RETRY_LIMIT 0x042A -#define REG_TXBF_CTRL 0x042C -#define REG_DARFRC 0x0430 -#define REG_RARFRC 0x0438 -#define REG_RRSR 0x0440 -#define REG_ARFR0 0x0444 -#define REG_ARFR1 0x044C -#define REG_AMPDU_MAX_TIME 0x0456 -#define REG_BCNQ1_BDNY 0x0457 -#define REG_AGGLEN_LMT 0x0458 -#define REG_AMPDU_MIN_SPACE 0x045C -#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D -#define REG_NDPA_OPT_CTRL 0x045F -#define REG_FAST_EDCA_CTRL 0x0460 -#define REG_RD_RESP_PKT_TH 0x0463 -#define REG_POWER_STAGE1 0x04B4 -#define REG_POWER_STAGE2 0x04B8 -#define REG_AMPDU_BURST_MODE 0x04BC -#define REG_PKT_VO_VI_LIFE_TIME 0x04C0 -#define REG_PKT_BE_BK_LIFE_TIME 0x04C2 -#define REG_STBC_SETTING 0x04C4 -#define REG_PROT_MODE_CTRL 0x04C8 -#define REG_MAX_AGGR_NUM 0x04CA -#define REG_RTS_MAX_AGGR_NUM 0x04CB -#define REG_BAR_MODE_CTRL 0x04CC -#define REG_RA_TRY_RATE_AGG_LMT 0x04CF -#define REG_MACID_PKT_DROP0 0x04D0 - -/*----------------------------------------------------- - * - * 0x0500h ~ 0x05FFh EDCA Configuration - * - *----------------------------------------------------- - */ -#define REG_EDCA_VO_PARAM 0x0500 -#define REG_EDCA_VI_PARAM 0x0504 -#define REG_EDCA_BE_PARAM 0x0508 -#define REG_EDCA_BK_PARAM 0x050C -#define REG_BCNTCFG 0x0510 -#define REG_PIFS 0x0512 -#define REG_RDG_PIFS 0x0513 -#define REG_SIFS_CTX 0x0514 -#define REG_SIFS_TRX 0x0516 -#define REG_AGGR_BREAK_TIME 0x051A -#define REG_SLOT 0x051B -#define REG_TX_PTCL_CTRL 0x0520 -#define REG_TXPAUSE 0x0522 -#define REG_DIS_TXREQ_CLR 0x0523 -#define REG_RD_CTRL 0x0524 - -#define REG_TBTT_PROHIBIT 0x0540 -#define REG_RD_NAV_NXT 0x0544 -#define REG_NAV_PROT_LEN 0x0546 -#define REG_BCN_CTRL 0x0550 -#define REG_BCN_CTRL_1 0x0551 -#define REG_MBID_NUM 0x0552 -#define REG_DUAL_TSF_RST 0x0553 -#define REG_BCN_INTERVAL 0x0554 -#define REG_DRVERLYINT 0x0558 -#define REG_BCNDMATIM 0x0559 -#define REG_ATIMWND 0x055A -#define REG_BCN_MAX_ERR 0x055D -#define REG_RXTSF_OFFSET_CCK 0x055E -#define REG_RXTSF_OFFSET_OFDM 0x055F -#define REG_TSFTR 0x0560 -#define REG_CTWND 0x0572 -#define REG_PSTIMER 0x0580 -#define REG_TIMER0 0x0584 -#define REG_TIMER1 0x0588 -#define REG_BCN_PREDL_ITV 0x058F -#define REG_ACMHWCTRL 0x05C0 - -/*----------------------------------------------------- - * - * 0x0600h ~ 0x07FFh WMAC Configuration - * - *----------------------------------------------------- - */ -#define REG_MAC_CR 0x0600 -#define REG_BWOPMODE 0x0603 -#define REG_TCR 0x0604 -#define REG_RCR 0x0608 -#define REG_RX_PKT_LIMIT 0x060C -#define REG_RX_DLK_TIME 0x060D -#define REG_RX_DRVINFO_SZ 0x060F - -#define REG_MACID 0x0610 -#define REG_BSSID 0x0618 -#define REG_MAR 0x0620 -#define REG_MBIDCAMCFG 0x0628 - -#define REG_USTIME_EDCA 0x0638 -#define REG_MAC_SPEC_SIFS 0x063A -#define REG_RESP_SIFS_CCK 0x063C -#define REG_RESP_SIFS_OFDM 0x063E -#define REG_ACKTO 0x0640 -#define REG_CTS2TO 0x0641 -#define REG_EIFS 0x0642 - -#define REG_NAV_UPPER 0x0652 - -/* Security*/ -#define REG_CAMCMD 0x0670 -#define REG_CAMWRITE 0x0674 -#define REG_CAMREAD 0x0678 -#define REG_CAMDBG 0x067C -#define REG_SECCFG 0x0680 - -/* Power*/ -#define REG_WOW_CTRL 0x0690 -#define REG_PS_RX_INFO 0x0692 -#define REG_UAPSD_TID 0x0693 -#define REG_WKFMCAM_NUM 0x0698 -#define REG_WKFMCAM_RWD 0x069C -#define REG_RXFLTMAP0 0x06A0 -#define REG_RXFLTMAP1 0x06A2 -#define REG_RXFLTMAP2 0x06A4 -#define REG_BCN_PSR_RPT 0x06A8 -#define REG_BT_COEX_TABLE 0x06C0 -#define REG_BFMER0_INFO 0x06E4 -#define REG_BFMER1_INFO 0x06EC -#define REG_CSI_RPT_PARAM_BW20 0x06F4 -#define REG_CSI_RPT_PARAM_BW40 0x06F8 -#define REG_CSI_RPT_PARAM_BW80 0x06FC -/* Hardware Port 2*/ -#define REG_MACID1 0x0700 -#define REG_BSSID1 0x0708 -#define REG_BFMEE_SEL 0x0714 -#define REG_SND_PTCL_CTRL 0x0718 - -#define CR9346 REG_9346CR -#define MSR (REG_CR + 2) -#define ISR REG_HISR -#define TSFR REG_TSFTR - -#define MACIDR0 REG_MACID -#define MACIDR4 (REG_MACID + 4) - -#define PBP REG_PBP - -#define IDR0 MACIDR0 -#define IDR4 MACIDR4 - -#define UNUSED_REGISTER 0x1BF -#define DCAM UNUSED_REGISTER -#define PSR UNUSED_REGISTER -#define BBADDR UNUSED_REGISTER -#define PHYDATAR UNUSED_REGISTER - -#define INVALID_BBRF_VALUE 0x12345678 - -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -#define CMDEEPROM_EN BIT(5) -#define CMDEEPROM_SEL BIT(4) -#define CMD9346CR_9356SEL BIT(4) -#define AUTOLOAD_EEPROM (CMDEEPROM_EN | CMDEEPROM_SEL) -#define AUTOLOAD_EFUSE CMDEEPROM_EN - -#define GPIOSEL_GPIO 0 -#define GPIOSEL_ENBT BIT(5) - -#define GPIO_IN REG_GPIO_PIN_CTRL -#define GPIO_OUT (REG_GPIO_PIN_CTRL + 1) -#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL + 2) -#define GPIO_MOD (REG_GPIO_PIN_CTRL + 3) - -#define MSR_NOLINK 0x00 -#define MSR_ADHOC 0x01 -#define MSR_INFRA 0x02 -#define MSR_AP 0x03 - -#define RRSR_RSC_OFFSET 21 -#define RRSR_SHORT_OFFSET 23 -#define RRSR_RSC_BW_40M 0x600000 -#define RRSR_RSC_UPSUBCHNL 0x400000 -#define RRSR_RSC_LOWSUBCHNL 0x200000 -#define RRSR_SHORT 0x800000 -#define RRSR_1M BIT(0) -#define RRSR_2M BIT(1) -#define RRSR_5_5M BIT(2) -#define RRSR_11M BIT(3) -#define RRSR_6M BIT(4) -#define RRSR_9M BIT(5) -#define RRSR_12M BIT(6) -#define RRSR_18M BIT(7) -#define RRSR_24M BIT(8) -#define RRSR_36M BIT(9) -#define RRSR_48M BIT(10) -#define RRSR_54M BIT(11) -#define RRSR_MCS0 BIT(12) -#define RRSR_MCS1 BIT(13) -#define RRSR_MCS2 BIT(14) -#define RRSR_MCS3 BIT(15) -#define RRSR_MCS4 BIT(16) -#define RRSR_MCS5 BIT(17) -#define RRSR_MCS6 BIT(18) -#define RRSR_MCS7 BIT(19) -#define BRSR_ACKSHORTPMB BIT(23) - -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 -#define RATR_MCS8 0x00100000 -#define RATR_MCS9 0x00200000 -#define RATR_MCS10 0x00400000 -#define RATR_MCS11 0x00800000 -#define RATR_MCS12 0x01000000 -#define RATR_MCS13 0x02000000 -#define RATR_MCS14 0x04000000 -#define RATR_MCS15 0x08000000 - -#define RATE_1M BIT(0) -#define RATE_2M BIT(1) -#define RATE_5_5M BIT(2) -#define RATE_11M BIT(3) -#define RATE_6M BIT(4) -#define RATE_9M BIT(5) -#define RATE_12M BIT(6) -#define RATE_18M BIT(7) -#define RATE_24M BIT(8) -#define RATE_36M BIT(9) -#define RATE_48M BIT(10) -#define RATE_54M BIT(11) -#define RATE_MCS0 BIT(12) -#define RATE_MCS1 BIT(13) -#define RATE_MCS2 BIT(14) -#define RATE_MCS3 BIT(15) -#define RATE_MCS4 BIT(16) -#define RATE_MCS5 BIT(17) -#define RATE_MCS6 BIT(18) -#define RATE_MCS7 BIT(19) -#define RATE_MCS8 BIT(20) -#define RATE_MCS9 BIT(21) -#define RATE_MCS10 BIT(22) -#define RATE_MCS11 BIT(23) -#define RATE_MCS12 BIT(24) -#define RATE_MCS13 BIT(25) -#define RATE_MCS14 BIT(26) -#define RATE_MCS15 BIT(27) - -#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) -#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\ - RATR_24M | RATR_36M | RATR_48M | RATR_54M) -#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 |\ - RATR_MCS3 | RATR_MCS4 | RATR_MCS5 |\ - RATR_MCS6 | RATR_MCS7) -#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 |\ - RATR_MCS11 | RATR_MCS12 | RATR_MCS13 |\ - RATR_MCS14 | RATR_MCS15) - -#define BW_OPMODE_20MHZ BIT(2) -#define BW_OPMODE_5G BIT(1) -#define CAM_VALID BIT(15) -#define CAM_NOTVALID 0x0000 -#define CAM_USEDK BIT(5) - -#define CAM_NONE 0x0 -#define CAM_WEP40 0x01 -#define CAM_TKIP 0x02 -#define CAM_AES 0x04 -#define CAM_WEP104 0x05 - -#define TOTAL_CAM_ENTRY 32 -#define HALF_CAM_ENTRY 16 - -#define CAM_WRITE BIT(16) -#define CAM_READ 0x00000000 -#define CAM_POLLINIG BIT(31) - -#define SCR_USEDK 0x01 -#define SCR_TXSEC_ENABLE 0x02 -#define SCR_RXSEC_ENABLE 0x04 - -/********************************************* -* 8192EE IMR/ISR bits -**********************************************/ -#define IMR_DISABLED 0x0 -/* IMR DW0(0x0060-0063) Bit 0-31 */ -#define IMR_TIMER2 BIT(31) -#define IMR_TIMER1 BIT(30) -#define IMR_PSTIMEOUT BIT(29) -#define IMR_GTINT4 BIT(28) -#define IMR_GTINT3 BIT(27) -#define IMR_TBDER BIT(26) -#define IMR_TBDOK BIT(25) -#define IMR_TSF_BIT32_TOGGLE BIT(24) -#define IMR_BCNDMAINT0 BIT(20) -#define IMR_BCNDOK0 BIT(16) -#define IMR_BCNDMAINT_E BIT(14) -#define IMR_ATIMEND BIT(12) -#define IMR_HISR1_IND_INT BIT(11) -#define IMR_C2HCMD BIT(10) -#define IMR_CPWM2 BIT(9) -#define IMR_CPWM BIT(8) -#define IMR_HIGHDOK BIT(7) -#define IMR_MGNTDOK BIT(6) -#define IMR_BKDOK BIT(5) -#define IMR_BEDOK BIT(4) -#define IMR_VIDOK BIT(3) -#define IMR_VODOK BIT(2) -#define IMR_RDU BIT(1) -#define IMR_ROK BIT(0) - -/* IMR DW1(0x00B4-00B7) Bit 0-31 */ -#define IMR_MCUERR BIT(28) -#define IMR_BCNDMAINT7 BIT(27) -#define IMR_BCNDMAINT6 BIT(26) -#define IMR_BCNDMAINT5 BIT(25) -#define IMR_BCNDMAINT4 BIT(24) -#define IMR_BCNDMAINT3 BIT(23) -#define IMR_BCNDMAINT2 BIT(22) -#define IMR_BCNDMAINT1 BIT(21) -#define IMR_BCNDOK7 BIT(20) -#define IMR_BCNDOK6 BIT(19) -#define IMR_BCNDOK5 BIT(18) -#define IMR_BCNDOK4 BIT(17) -#define IMR_BCNDOK3 BIT(16) -#define IMR_BCNDOK2 BIT(15) -#define IMR_BCNDOK1 BIT(14) -#define IMR_ATIMEND_E BIT(13) -#define IMR_TXERR BIT(11) -#define IMR_RXERR BIT(10) -#define IMR_TXFOVW BIT(9) -#define IMR_RXFOVW BIT(8) - -#define HWSET_MAX_SIZE 512 -#define EFUSE_MAX_SECTION 64 -#define EFUSE_REAL_CONTENT_LEN 256 -#define EFUSE_OOB_PROTECT_BYTES 18 - -#define EEPROM_DEFAULT_TSSI 0x0 -#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 -#define EEPROM_DEFAULT_CRYSTALCAP 0x5 -#define EEPROM_DEFAULT_BOARDTYPE 0x02 -#define EEPROM_DEFAULT_TXPOWER 0x1010 -#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 - -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 -#define EEPROM_DEFAULT_THERMALMETER 0x1A -#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 -#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 -#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 -#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 -#define EEPROM_DEFAULT_HT20_DIFF 2 -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 -#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 -#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 - -#define RF_OPTION1 0x79 -#define RF_OPTION2 0x7A -#define RF_OPTION3 0x7B -#define RF_OPTION4 0x7C - -#define EEPROM_DEFAULT_PID 0x1234 -#define EEPROM_DEFAULT_VID 0x5678 -#define EEPROM_DEFAULT_CUSTOMERID 0xAB -#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD -#define EEPROM_DEFAULT_VERSION 0 - -#define EEPROM_CHANNEL_PLAN_FCC 0x0 -#define EEPROM_CHANNEL_PLAN_IC 0x1 -#define EEPROM_CHANNEL_PLAN_ETSI 0x2 -#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 -#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 -#define EEPROM_CHANNEL_PLAN_MKK 0x5 -#define EEPROM_CHANNEL_PLAN_MKK1 0x6 -#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 -#define EEPROM_CHANNEL_PLAN_TELEC 0x8 -#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 -#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -#define EEPROM_CHANNEL_PLAN_NCC 0xB -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - -#define EEPROM_CID_DEFAULT 0x0 -#define EEPROM_CID_TOSHIBA 0x4 -#define EEPROM_CID_CCX 0x10 -#define EEPROM_CID_QMI 0x0D -#define EEPROM_CID_WHQL 0xFE - -#define RTL8192E_EEPROM_ID 0x8129 - -#define EEPROM_HPON 0x02 -#define EEPROM_CLK 0x06 -#define EEPROM_TESTR 0x08 - -#define EEPROM_TXPOWERCCK 0x10 -#define EEPROM_TXPOWERHT40_1S 0x16 -#define EEPROM_TXPOWERHT20DIFF 0x1B -#define EEPROM_TXPOWER_OFDMDIFF 0x1B - -#define EEPROM_TX_PWR_INX 0x10 - -#define EEPROM_CHANNELPLAN 0xB8 -#define EEPROM_XTAL_92E 0xB9 -#define EEPROM_THERMAL_METER_92E 0xBA -#define EEPROM_IQK_LCK_92E 0xBB - -#define EEPROM_RF_BOARD_OPTION_92E 0xC1 -#define EEPROM_RF_FEATURE_OPTION_92E 0xC2 -#define EEPROM_RF_BT_SETTING_92E 0xC3 -#define EEPROM_VERSION 0xC4 -#define EEPROM_CUSTOMER_ID 0xC5 -#define EEPROM_RF_ANTENNA_OPT_92E 0xC9 - -#define EEPROM_MAC_ADDR 0xD0 -#define EEPROM_VID 0xD6 -#define EEPROM_DID 0xD8 -#define EEPROM_SVID 0xDA -#define EEPROM_SMID 0xDC - -#define STOPBECON BIT(6) -#define STOPHIGHT BIT(5) -#define STOPMGT BIT(4) -#define STOPVO BIT(3) -#define STOPVI BIT(2) -#define STOPBE BIT(1) -#define STOPBK BIT(0) - -#define RCR_APPFCS BIT(31) -#define RCR_APP_MIC BIT(30) -#define RCR_APP_ICV BIT(29) -#define RCR_APP_PHYST_RXFF BIT(28) -#define RCR_APP_BA_SSN BIT(27) -#define RCR_ENMBID BIT(24) -#define RCR_LSIGEN BIT(23) -#define RCR_MFBEN BIT(22) -#define RCR_HTC_LOC_CTRL BIT(14) -#define RCR_AMF BIT(13) -#define RCR_ACF BIT(12) -#define RCR_ADF BIT(11) -#define RCR_AICV BIT(9) -#define RCR_ACRC32 BIT(8) -#define RCR_CBSSID_BCN BIT(7) -#define RCR_CBSSID_DATA BIT(6) -#define RCR_CBSSID RCR_CBSSID_DATA -#define RCR_APWRMGT BIT(5) -#define RCR_ADD3 BIT(4) -#define RCR_AB BIT(3) -#define RCR_AM BIT(2) -#define RCR_APM BIT(1) -#define RCR_AAP BIT(0) -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - -#define RSV_CTRL 0x001C -#define RD_CTRL 0x0524 - -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_USB_VID 0xFE60 -#define REG_USB_PID 0xFE62 -#define REG_USB_OPTIONAL 0xFE64 -#define REG_USB_CHIRP_K 0xFE65 -#define REG_USB_PHY 0xFE66 -#define REG_USB_MAC_ADDR 0xFE70 -#define REG_USB_HRPWM 0xFE58 -#define REG_USB_HCPWM 0xFE57 - -#define SW18_FPWM BIT(3) - -#define ISO_MD2PP BIT(0) -#define ISO_UA2USB BIT(1) -#define ISO_UD2CORE BIT(2) -#define ISO_PA2PCIE BIT(3) -#define ISO_PD2CORE BIT(4) -#define ISO_IP2MAC BIT(5) -#define ISO_DIOP BIT(6) -#define ISO_DIOE BIT(7) -#define ISO_EB2CORE BIT(8) -#define ISO_DIOR BIT(9) - -#define PWC_EV25V BIT(14) -#define PWC_EV12V BIT(15) - -#define FEN_BBRSTB BIT(0) -#define FEN_BB_GLB_RSTN BIT(1) -#define FEN_USBA BIT(2) -#define FEN_UPLL BIT(3) -#define FEN_USBD BIT(4) -#define FEN_DIO_PCIE BIT(5) -#define FEN_PCIEA BIT(6) -#define FEN_PPLL BIT(7) -#define FEN_PCIED BIT(8) -#define FEN_DIOE BIT(9) -#define FEN_CPUEN BIT(10) -#define FEN_DCORE BIT(11) -#define FEN_ELDR BIT(12) -#define FEN_DIO_RF BIT(13) -#define FEN_HWPDN BIT(14) -#define FEN_MREGEN BIT(15) - -#define PFM_LDALL BIT(0) -#define PFM_ALDN BIT(1) -#define PFM_LDKP BIT(2) -#define PFM_WOWL BIT(3) -#define ENPDN BIT(4) -#define PDN_PL BIT(5) -#define APFM_ONMAC BIT(8) -#define APFM_OFF BIT(9) -#define APFM_RSM BIT(10) -#define AFSM_HSUS BIT(11) -#define AFSM_PCIE BIT(12) -#define APDM_MAC BIT(13) -#define APDM_HOST BIT(14) -#define APDM_HPDN BIT(15) -#define RDY_MACON BIT(16) -#define SUS_HOST BIT(17) -#define ROP_ALD BIT(20) -#define ROP_PWR BIT(21) -#define ROP_SPS BIT(22) -#define SOP_MRST BIT(25) -#define SOP_FUSE BIT(26) -#define SOP_ABG BIT(27) -#define SOP_AMB BIT(28) -#define SOP_RCK BIT(29) -#define SOP_A8M BIT(30) -#define XOP_BTCK BIT(31) - -#define ANAD16V_EN BIT(0) -#define ANA8M BIT(1) -#define MACSLP BIT(4) -#define LOADER_CLK_EN BIT(5) -#define _80M_SSC_DIS BIT(7) -#define _80M_SSC_EN_HO BIT(8) -#define PHY_SSC_RSTB BIT(9) -#define SEC_CLK_EN BIT(10) -#define MAC_CLK_EN BIT(11) -#define SYS_CLK_EN BIT(12) -#define RING_CLK_EN BIT(13) - -#define BOOT_FROM_EEPROM BIT(4) -#define EEPROM_EN BIT(5) - -#define AFE_BGEN BIT(0) -#define AFE_MBEN BIT(1) -#define MAC_ID_EN BIT(7) - -#define WLOCK_ALL BIT(0) -#define WLOCK_00 BIT(1) -#define WLOCK_04 BIT(2) -#define WLOCK_08 BIT(3) -#define WLOCK_40 BIT(4) -#define R_DIS_PRST_0 BIT(5) -#define R_DIS_PRST_1 BIT(6) -#define LOCK_ALL_EN BIT(7) - -#define RF_EN BIT(0) -#define RF_RSTB BIT(1) -#define RF_SDMRSTB BIT(2) - -#define LDA15_EN BIT(0) -#define LDA15_STBY BIT(1) -#define LDA15_OBUF BIT(2) -#define LDA15_REG_VOS BIT(3) -#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) - -#define LDV12_EN BIT(0) -#define LDV12_SDBY BIT(1) -#define LPLDO_HSM BIT(2) -#define LPLDO_LSM_DIS BIT(3) -#define _LDV12_VADJ(x) (((x) & 0xF) << 4) - -#define XTAL_EN BIT(0) -#define XTAL_BSEL BIT(1) -#define _XTAL_BOSC(x) (((x) & 0x3) << 2) -#define _XTAL_CADJ(x) (((x) & 0xF) << 4) -#define XTAL_GATE_USB BIT(8) -#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) -#define XTAL_GATE_AFE BIT(11) -#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) -#define XTAL_RF_GATE BIT(14) -#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) -#define XTAL_GATE_DIG BIT(17) -#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) -#define XTAL_BT_GATE BIT(20) -#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) -#define _XTAL_GPIO(x) (((x) & 0x7) << 23) - -#define CKDLY_AFE BIT(26) -#define CKDLY_USB BIT(27) -#define CKDLY_DIG BIT(28) -#define CKDLY_BT BIT(29) - -#define APLL_EN BIT(0) -#define APLL_320_EN BIT(1) -#define APLL_FREF_SEL BIT(2) -#define APLL_EDGE_SEL BIT(3) -#define APLL_WDOGB BIT(4) -#define APLL_LPFEN BIT(5) - -#define APLL_REF_CLK_13MHZ 0x1 -#define APLL_REF_CLK_19_2MHZ 0x2 -#define APLL_REF_CLK_20MHZ 0x3 -#define APLL_REF_CLK_25MHZ 0x4 -#define APLL_REF_CLK_26MHZ 0x5 -#define APLL_REF_CLK_38_4MHZ 0x6 -#define APLL_REF_CLK_40MHZ 0x7 - -#define APLL_320EN BIT(14) -#define APLL_80EN BIT(15) -#define APLL_1MEN BIT(24) - -#define ALD_EN BIT(18) -#define EF_PD BIT(19) -#define EF_FLAG BIT(31) - -#define EF_TRPT BIT(7) -#define LDOE25_EN BIT(31) - -#define RSM_EN BIT(0) -#define TIMER_EN BIT(4) - -#define TRSW0EN BIT(2) -#define TRSW1EN BIT(3) -#define EROM_EN BIT(4) -#define ENBT BIT(5) -#define ENUART BIT(8) -#define UART_910 BIT(9) -#define ENPMAC BIT(10) -#define SIC_SWRST BIT(11) -#define ENSIC BIT(12) -#define SIC_23 BIT(13) -#define ENHDP BIT(14) -#define SIC_LBK BIT(15) - -#define LED0PL BIT(4) -#define LED1PL BIT(12) -#define LED0DIS BIT(7) - -#define MCUFWDL_EN BIT(0) -#define MCUFWDL_RDY BIT(1) -#define FWDL_CHKSUM_RPT BIT(2) -#define MACINI_RDY BIT(3) -#define BBINI_RDY BIT(4) -#define RFINI_RDY BIT(5) -#define WINTINI_RDY BIT(6) -#define CPRST BIT(23) - -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define TRP_B15V_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define VENDOR_ID BIT(19) -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) - -#define CHIP_VER_RTL_MASK 0xF000 -#define CHIP_VER_RTL_SHIFT 12 - -#define REG_LBMODE (REG_CR + 3) - -#define HCI_TXDMA_EN BIT(0) -#define HCI_RXDMA_EN BIT(1) -#define TXDMA_EN BIT(2) -#define RXDMA_EN BIT(3) -#define PROTOCOL_EN BIT(4) -#define SCHEDULE_EN BIT(5) -#define MACTXEN BIT(6) -#define MACRXEN BIT(7) -#define ENSWBCN BIT(8) -#define ENSEC BIT(9) - -#define _NETTYPE(x) (((x) & 0x3) << 16) -#define MASK_NETTYPE 0x30000 -#define NT_NO_LINK 0x0 -#define NT_LINK_AD_HOC 0x1 -#define NT_LINK_AP 0x2 -#define NT_AS_AP 0x3 - -#define _LBMODE(x) (((x) & 0xF) << 24) -#define MASK_LBMODE 0xF000000 -#define LOOPBACK_NORMAL 0x0 -#define LOOPBACK_IMMEDIATELY 0xB -#define LOOPBACK_MAC_DELAY 0x3 -#define LOOPBACK_PHY 0x1 -#define LOOPBACK_DMA 0x7 - -#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) -#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) -#define _PSRX_MASK 0xF -#define _PSTX_MASK 0xF0 -#define _PSRX(x) (x) -#define _PSTX(x) ((x) << 4) - -#define PBP_64 0x0 -#define PBP_128 0x1 -#define PBP_256 0x2 -#define PBP_512 0x3 -#define PBP_1024 0x4 - -#define RXDMA_ARBBW_EN BIT(0) -#define RXSHFT_EN BIT(1) -#define RXDMA_AGG_EN BIT(2) -#define QS_VO_QUEUE BIT(8) -#define QS_VI_QUEUE BIT(9) -#define QS_BE_QUEUE BIT(10) -#define QS_BK_QUEUE BIT(11) -#define QS_MANAGER_QUEUE BIT(12) -#define QS_HIGH_QUEUE BIT(13) - -#define HQSEL_VOQ BIT(0) -#define HQSEL_VIQ BIT(1) -#define HQSEL_BEQ BIT(2) -#define HQSEL_BKQ BIT(3) -#define HQSEL_MGTQ BIT(4) -#define HQSEL_HIQ BIT(5) - -#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) -#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) -#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) -#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) -#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) -#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) - -#define QUEUE_LOW 1 -#define QUEUE_NORMAL 2 -#define QUEUE_HIGH 3 - -#define _LLT_NO_ACTIVE 0x0 -#define _LLT_WRITE_ACCESS 0x1 -#define _LLT_READ_ACCESS 0x2 - -#define _LLT_INIT_DATA(x) ((x) & 0xFF) -#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) -#define _LLT_OP(x) (((x) & 0x3) << 30) -#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) - -#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) -#define BB_WRITE_EN BIT(30) -#define BB_READ_EN BIT(31) - -#define _HPQ(x) ((x) & 0xFF) -#define _LPQ(x) (((x) & 0xFF) << 8) -#define _PUBQ(x) (((x) & 0xFF) << 16) -#define _NPQ(x) ((x) & 0xFF) - -#define HPQ_PUBLIC_DIS BIT(24) -#define LPQ_PUBLIC_DIS BIT(25) -#define LD_RQPN BIT(31) - -#define BCN_VALID BIT(16) -#define BCN_HEAD(x) (((x) & 0xFF) << 8) -#define BCN_HEAD_MASK 0xFF00 - -#define BLK_DESC_NUM_SHIFT 4 -#define BLK_DESC_NUM_MASK 0xF - -#define DROP_DATA_EN BIT(9) - -#define EN_AMPDU_RTY_NEW BIT(7) - -#define _INIRTSMCS_SEL(x) ((x) & 0x3F) - -#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) -#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) - -#define RATE_REG_BITMAP_ALL 0xFFFFF - -#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) - -#define _RRSR_RSC(x) (((x) & 0x3) << 21) -#define RRSR_RSC_RESERVED 0x0 -#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 -#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 -#define RRSR_RSC_DUPLICATE_MODE 0x3 - -#define USE_SHORT_G1 BIT(20) - -#define _AGGLMT_MCS0(x) ((x) & 0xF) -#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) -#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) -#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) -#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) -#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) -#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) -#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) - -#define RETRY_LIMIT_SHORT_SHIFT 8 -#define RETRY_LIMIT_LONG_SHIFT 0 - -#define _DARF_RC1(x) ((x) & 0x1F) -#define _DARF_RC2(x) (((x) & 0x1F) << 8) -#define _DARF_RC3(x) (((x) & 0x1F) << 16) -#define _DARF_RC4(x) (((x) & 0x1F) << 24) -#define _DARF_RC5(x) ((x) & 0x1F) -#define _DARF_RC6(x) (((x) & 0x1F) << 8) -#define _DARF_RC7(x) (((x) & 0x1F) << 16) -#define _DARF_RC8(x) (((x) & 0x1F) << 24) - -#define _RARF_RC1(x) ((x) & 0x1F) -#define _RARF_RC2(x) (((x) & 0x1F) << 8) -#define _RARF_RC3(x) (((x) & 0x1F) << 16) -#define _RARF_RC4(x) (((x) & 0x1F) << 24) -#define _RARF_RC5(x) ((x) & 0x1F) -#define _RARF_RC6(x) (((x) & 0x1F) << 8) -#define _RARF_RC7(x) (((x) & 0x1F) << 16) -#define _RARF_RC8(x) (((x) & 0x1F) << 24) - -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - -#define _AIFS(x) (x) -#define _ECW_MAX_MIN(x) ((x) << 8) -#define _TXOP_LIMIT(x) ((x) << 16) - -#define _BCNIFS(x) ((x) & 0xFF) -#define _BCNECW(x) ((((x) & 0xF)) << 8) - -#define _LRL(x) ((x) & 0x3F) -#define _SRL(x) (((x) & 0x3F) << 8) - -#define _SIFS_CCK_CTX(x) ((x) & 0xFF) -#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8) - -#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) -#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8) - -#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) - -#define DIS_EDCA_CNT_DWN BIT(11) - -#define EN_MBSSID BIT(1) -#define EN_TXBCN_RPT BIT(2) -#define EN_BCN_FUNCTION BIT(3) - -#define TSFTR_RST BIT(0) -#define TSFTR1_RST BIT(1) - -#define STOP_BCNQ BIT(6) - -#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) -#define DIS_TSF_UDT0_TEST_CHIP BIT(5) - -#define ACMHW_HWEN BIT(0) -#define ACMHW_BEQEN BIT(1) -#define ACMHW_VIQEN BIT(2) -#define ACMHW_VOQEN BIT(3) -#define ACMHW_BEQSTATUS BIT(4) -#define ACMHW_VIQSTATUS BIT(5) -#define ACMHW_VOQSTATUS BIT(6) - -#define APSDOFF BIT(6) -#define APSDOFF_STATUS BIT(7) - -#define BW_20MHZ BIT(2) - -#define RATE_BITMAP_ALL 0xFFFFF - -#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 - -#define TSFRST BIT(0) -#define DIS_GCLK BIT(1) -#define PAD_SEL BIT(2) -#define PWR_ST BIT(6) -#define PWRBIT_OW_EN BIT(7) -#define ACRC BIT(8) -#define CFENDFORM BIT(9) -#define ICV BIT(10) - -#define AAP BIT(0) -#define APM BIT(1) -#define AM BIT(2) -#define AB BIT(3) -#define ADD3 BIT(4) -#define APWRMGT BIT(5) -#define CBSSID BIT(6) -#define CBSSID_DATA BIT(6) -#define CBSSID_BCN BIT(7) -#define ACRC32 BIT(8) -#define AICV BIT(9) -#define ADF BIT(11) -#define ACF BIT(12) -#define AMF BIT(13) -#define HTC_LOC_CTRL BIT(14) -#define UC_DATA_EN BIT(16) -#define BM_DATA_EN BIT(17) -#define MFBEN BIT(22) -#define LSIGEN BIT(23) -#define ENMBID BIT(24) -#define APP_BASSN BIT(27) -#define APP_PHYSTS BIT(28) -#define APP_ICV BIT(29) -#define APP_MIC BIT(30) -#define APP_FCS BIT(31) - -#define _MIN_SPACE(x) ((x) & 0x7) -#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) - -#define RXERR_TYPE_OFDM_PPDU 0 -#define RXERR_TYPE_OFDM_FALSE_ALARM 1 -#define RXERR_TYPE_OFDM_MPDU_OK 2 -#define RXERR_TYPE_OFDM_MPDU_FAIL 3 -#define RXERR_TYPE_CCK_PPDU 4 -#define RXERR_TYPE_CCK_FALSE_ALARM 5 -#define RXERR_TYPE_CCK_MPDU_OK 6 -#define RXERR_TYPE_CCK_MPDU_FAIL 7 -#define RXERR_TYPE_HT_PPDU 8 -#define RXERR_TYPE_HT_FALSE_ALARM 9 -#define RXERR_TYPE_HT_MPDU_TOTAL 10 -#define RXERR_TYPE_HT_MPDU_OK 11 -#define RXERR_TYPE_HT_MPDU_FAIL 12 -#define RXERR_TYPE_RX_FULL_DROP 15 - -#define RXERR_COUNTER_MASK 0xFFFFF -#define RXERR_RPT_RST BIT(27) -#define _RXERR_RPT_SEL(type) ((type) << 28) - -#define SCR_TXUSEDK BIT(0) -#define SCR_RXUSEDK BIT(1) -#define SCR_TXENCENABLE BIT(2) -#define SCR_RXDECENABLE BIT(3) -#define SCR_SKBYA2 BIT(4) -#define SCR_NOSKMC BIT(5) -#define SCR_TXBCUSEDK BIT(6) -#define SCR_RXBCUSEDK BIT(7) - -#define USB_IS_HIGH_SPEED 0 -#define USB_IS_FULL_SPEED 1 -#define USB_SPEED_MASK BIT(5) - -#define USB_NORMAL_SIE_EP_MASK 0xF -#define USB_NORMAL_SIE_EP_SHIFT 4 - -#define USB_TEST_EP_MASK 0x30 -#define USB_TEST_EP_SHIFT 4 - -#define USB_AGG_EN BIT(3) - -#define MAC_ADDR_LEN 6 -#define LAST_ENTRY_OF_TX_PKT_BUFFER 175 - -#define POLLING_LLT_THRESHOLD 20 -#define POLLING_READY_TIMEOUT_COUNT 3000 - -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -#define EPROM_CMD_OPERATING_MODE_MASK ((1 << 7) | (1 << 6)) -#define EPROM_CMD_CONFIG 0x3 -#define EPROM_CMD_LOAD 1 - -#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE - -#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) - -#define RPMAC_RESET 0x100 -#define RPMAC_TXSTART 0x104 -#define RPMAC_TXLEGACYSIG 0x108 -#define RPMAC_TXHTSIG1 0x10c -#define RPMAC_TXHTSIG2 0x110 -#define RPMAC_PHYDEBUG 0x114 -#define RPMAC_TXPACKETNUM 0x118 -#define RPMAC_TXIDLE 0x11c -#define RPMAC_TXMACHEADER0 0x120 -#define RPMAC_TXMACHEADER1 0x124 -#define RPMAC_TXMACHEADER2 0x128 -#define RPMAC_TXMACHEADER3 0x12c -#define RPMAC_TXMACHEADER4 0x130 -#define RPMAC_TXMACHEADER5 0x134 -#define RPMAC_TXDADATYPE 0x138 -#define RPMAC_TXRANDOMSEED 0x13c -#define RPMAC_CCKPLCPPREAMBLE 0x140 -#define RPMAC_CCKPLCPHEADER 0x144 -#define RPMAC_CCKCRC16 0x148 -#define RPMAC_OFDMRXCRC32OK 0x170 -#define RPMAC_OFDMRXCRC32ER 0x174 -#define RPMAC_OFDMRXPARITYER 0x178 -#define RPMAC_OFDMRXCRC8ER 0x17c -#define RPMAC_CCKCRXRC16ER 0x180 -#define RPMAC_CCKCRXRC32ER 0x184 -#define RPMAC_CCKCRXRC32OK 0x188 -#define RPMAC_TXSTATUS 0x18c - -#define RFPGA0_RFMOD 0x800 - -#define RFPGA0_TXINFO 0x804 -#define RFPGA0_PSDFUNCTION 0x808 - -#define RFPGA0_TXGAINSTAGE 0x80c - -#define RFPGA0_RFTIMING1 0x810 -#define RFPGA0_RFTIMING2 0x814 - -#define RFPGA0_XA_HSSIPARAMETER1 0x820 -#define RFPGA0_XA_HSSIPARAMETER2 0x824 -#define RFPGA0_XB_HSSIPARAMETER1 0x828 -#define RFPGA0_XB_HSSIPARAMETER2 0x82c - -#define RFPGA0_XA_LSSIPARAMETER 0x840 -#define RFPGA0_XB_LSSIPARAMETER 0x844 - -#define RFPGA0_RFWAKEUPPARAMETER 0x850 -#define RFPGA0_RFSLEEPUPPARAMETER 0x854 - -#define RFPGA0_XAB_SWITCHCONTROL 0x858 -#define RFPGA0_XCD_SWITCHCONTROL 0x85c - -#define RFPGA0_XA_RFINTERFACEOE 0x860 -#define RFPGA0_XB_RFINTERFACEOE 0x864 - -#define RFPGA0_XAB_RFINTERFACESW 0x870 -#define RFPGA0_XCD_RFINTERFACESW 0x874 - -#define RFPGA0_XAB_RFPARAMETER 0x878 -#define RFPGA0_XCD_RFPARAMETER 0x87c - -#define RFPGA0_ANALOGPARAMETER1 0x880 -#define RFPGA0_ANALOGPARAMETER2 0x884 -#define RFPGA0_ANALOGPARAMETER3 0x888 -#define RFPGA0_ANALOGPARAMETER4 0x88c - -#define RFPGA0_XA_LSSIREADBACK 0x8a0 -#define RFPGA0_XB_LSSIREADBACK 0x8a4 -#define RFPGA0_XC_LSSIREADBACK 0x8a8 -#define RFPGA0_XD_LSSIREADBACK 0x8ac - -#define RFPGA0_PSDREPORT 0x8b4 -#define TRANSCEIVEA_HSPI_READBACK 0x8b8 -#define TRANSCEIVEB_HSPI_READBACK 0x8bc -#define REG_SC_CNT 0x8c4 -#define RFPGA0_XAB_RFINTERFACERB 0x8e0 -#define RFPGA0_XCD_RFINTERFACERB 0x8e4 - -#define RFPGA1_RFMOD 0x900 - -#define RFPGA1_TXBLOCK 0x904 -#define RFPGA1_DEBUGSELECT 0x908 -#define RFPGA1_TXINFO 0x90c - -#define RCCK0_SYSTEM 0xa00 - -#define RCCK0_AFESETTING 0xa04 -#define RCCK0_CCA 0xa08 - -#define RCCK0_RXAGC1 0xa0c -#define RCCK0_RXAGC2 0xa10 - -#define RCCK0_RXHP 0xa14 - -#define RCCK0_DSPPARAMETER1 0xa18 -#define RCCK0_DSPPARAMETER2 0xa1c - -#define RCCK0_TXFILTER1 0xa20 -#define RCCK0_TXFILTER2 0xa24 -#define RCCK0_DEBUGPORT 0xa28 -#define RCCK0_FALSEALARMREPORT 0xa2c -#define RCCK0_TRSSIREPORT 0xa50 -#define RCCK0_RXREPORT 0xa54 -#define RCCK0_FACOUNTERLOWER 0xa5c -#define RCCK0_FACOUNTERUPPER 0xa58 -#define RCCK0_CCA_CNT 0xa60 - -/* PageB(0xB00) */ -#define RPDP_ANTA 0xb00 -#define RPDP_ANTA_4 0xb04 -#define RPDP_ANTA_8 0xb08 -#define RPDP_ANTA_C 0xb0c -#define RPDP_ANTA_10 0xb10 -#define RPDP_ANTA_14 0xb14 -#define RPDP_ANTA_18 0xb18 -#define RPDP_ANTA_1C 0xb1c -#define RPDP_ANTA_20 0xb20 -#define RPDP_ANTA_24 0xb24 - -#define RCONFIG_PMPD_ANTA 0xb28 -#define RCONFIG_RAM64x16 0xb2c - -#define RBNDA 0xb30 -#define RHSSIPAR 0xb34 - -#define RCONFIG_ANTA 0xb68 -#define RCONFIG_ANTB 0xb6c - -#define RPDP_ANTB 0xb70 -#define RPDP_ANTB_4 0xb74 -#define RPDP_ANTB_8 0xb78 -#define RPDP_ANTB_C 0xb7c -#define RPDP_ANTB_10 0xb80 -#define RPDP_ANTB_14 0xb84 -#define RPDP_ANTB_18 0xb88 -#define RPDP_ANTB_1C 0xb8c -#define RPDP_ANTB_20 0xb90 -#define RPDP_ANTB_24 0xb94 - -#define RCONFIG_PMPD_ANTB 0xb98 - -#define RBNDB 0xba0 - -#define RAPK 0xbd8 -#define RPM_RX0_ANTA 0xbdc -#define RPM_RX1_ANTA 0xbe0 -#define RPM_RX2_ANTA 0xbe4 -#define RPM_RX3_ANTA 0xbe8 -#define RPM_RX0_ANTB 0xbec -#define RPM_RX1_ANTB 0xbf0 -#define RPM_RX2_ANTB 0xbf4 -#define RPM_RX3_ANTB 0xbf8 - -/*Page C*/ -#define ROFDM0_LSTF 0xc00 - -#define ROFDM0_TRXPATHENABLE 0xc04 -#define ROFDM0_TRMUXPAR 0xc08 -#define ROFDM0_TRSWISOLATION 0xc0c - -#define ROFDM0_XARXAFE 0xc10 -#define ROFDM0_XARXIQIMBALANCE 0xc14 -#define ROFDM0_XBRXAFE 0xc18 -#define ROFDM0_XBRXIQIMBALANCE 0xc1c -#define ROFDM0_XCRXAFE 0xc20 -#define ROFDM0_XCRXIQIMBANLANCE 0xc24 -#define ROFDM0_XDRXAFE 0xc28 -#define ROFDM0_XDRXIQIMBALANCE 0xc2c - -#define ROFDM0_RXDETECTOR1 0xc30 -#define ROFDM0_RXDETECTOR2 0xc34 -#define ROFDM0_RXDETECTOR3 0xc38 -#define ROFDM0_RXDETECTOR4 0xc3c - -#define ROFDM0_RXDSP 0xc40 -#define ROFDM0_CFOANDDAGC 0xc44 -#define ROFDM0_CCADROPTHRESHOLD 0xc48 -#define ROFDM0_ECCATHRESHOLD 0xc4c - -#define ROFDM0_XAAGCCORE1 0xc50 -#define ROFDM0_XAAGCCORE2 0xc54 -#define ROFDM0_XBAGCCORE1 0xc58 -#define ROFDM0_XBAGCCORE2 0xc5c -#define ROFDM0_XCAGCCORE1 0xc60 -#define ROFDM0_XCAGCCORE2 0xc64 -#define ROFDM0_XDAGCCORE1 0xc68 -#define ROFDM0_XDAGCCORE2 0xc6c - -#define ROFDM0_AGCPARAMETER1 0xc70 -#define ROFDM0_AGCPARAMETER2 0xc74 -#define ROFDM0_AGCRSSITABLE 0xc78 -#define ROFDM0_HTSTFAGC 0xc7c - -#define ROFDM0_XATXIQIMBALANCE 0xc80 -#define ROFDM0_XATXAFE 0xc84 -#define ROFDM0_XBTXIQIMBALANCE 0xc88 -#define ROFDM0_XBTXAFE 0xc8c -#define ROFDM0_XCTXIQIMBALANCE 0xc90 -#define ROFDM0_XCTXAFE 0xc94 -#define ROFDM0_XDTXIQIMBALANCE 0xc98 -#define ROFDM0_XDTXAFE 0xc9c - -#define ROFDM0_RXIQEXTANTA 0xca0 -#define ROFDM0_TXCOEFF1 0xca4 -#define ROFDM0_TXCOEFF2 0xca8 -#define ROFDM0_TXCOEFF3 0xcac -#define ROFDM0_TXCOEFF4 0xcb0 -#define ROFDM0_TXCOEFF5 0xcb4 -#define ROFDM0_TXCOEFF6 0xcb8 - -#define ROFDM0_RXHPPARAMETER 0xce0 -#define ROFDM0_TXPSEUDONOISEWGT 0xce4 -#define ROFDM0_FRAMESYNC 0xcf0 -#define ROFDM0_DFSREPORT 0xcf4 - -#define ROFDM1_LSTF 0xd00 -#define ROFDM1_TRXPATHENABLE 0xd04 - -#define ROFDM1_CF0 0xd08 -#define ROFDM1_CSI1 0xd10 -#define ROFDM1_SBD 0xd14 -#define ROFDM1_CSI2 0xd18 -#define ROFDM1_CFOTRACKING 0xd2c -#define ROFDM1_TRXMESAURE1 0xd34 -#define ROFDM1_INTFDET 0xd3c -#define ROFDM1_PSEUDONOISESTATEAB 0xd50 -#define ROFDM1_PSEUDONOISESTATECD 0xd54 -#define ROFDM1_RXPSEUDONOISEWGT 0xd58 - -#define ROFDM_PHYCOUNTER1 0xda0 -#define ROFDM_PHYCOUNTER2 0xda4 -#define ROFDM_PHYCOUNTER3 0xda8 - -#define ROFDM_SHORTCFOAB 0xdac -#define ROFDM_SHORTCFOCD 0xdb0 -#define ROFDM_LONGCFOAB 0xdb4 -#define ROFDM_LONGCFOCD 0xdb8 -#define ROFDM_TAILCF0AB 0xdbc -#define ROFDM_TAILCF0CD 0xdc0 -#define ROFDM_PWMEASURE1 0xdc4 -#define ROFDM_PWMEASURE2 0xdc8 -#define ROFDM_BWREPORT 0xdcc -#define ROFDM_AGCREPORT 0xdd0 -#define ROFDM_RXSNR 0xdd4 -#define ROFDM_RXEVMCSI 0xdd8 -#define ROFDM_SIGREPORT 0xddc - -#define RTXAGC_A_RATE18_06 0xe00 -#define RTXAGC_A_RATE54_24 0xe04 -#define RTXAGC_A_CCK1_MCS32 0xe08 -#define RTXAGC_A_MCS03_MCS00 0xe10 -#define RTXAGC_A_MCS07_MCS04 0xe14 -#define RTXAGC_A_MCS11_MCS08 0xe18 -#define RTXAGC_A_MCS15_MCS12 0xe1c - -#define RTXAGC_B_RATE18_06 0x830 -#define RTXAGC_B_RATE54_24 0x834 -#define RTXAGC_B_CCK1_55_MCS32 0x838 -#define RTXAGC_B_MCS03_MCS00 0x83c -#define RTXAGC_B_MCS07_MCS04 0x848 -#define RTXAGC_B_MCS11_MCS08 0x84c -#define RTXAGC_B_MCS15_MCS12 0x868 -#define RTXAGC_B_CCK11_A_CCK2_11 0x86c - -#define RFPGA0_IQK 0xe28 -#define RTX_IQK_TONE_A 0xe30 -#define RRX_IQK_TONE_A 0xe34 -#define RTX_IQK_PI_A 0xe38 -#define RRX_IQK_PI_A 0xe3c - -#define RTX_IQK 0xe40 -#define RRX_IQK 0xe44 -#define RIQK_AGC_PTS 0xe48 -#define RIQK_AGC_RSP 0xe4c -#define RTX_IQK_TONE_B 0xe50 -#define RRX_IQK_TONE_B 0xe54 -#define RTX_IQK_PI_B 0xe58 -#define RRX_IQK_PI_B 0xe5c -#define RIQK_AGC_CONT 0xe60 - -#define RBLUE_TOOTH 0xe6c -#define RRX_WAIT_CCA 0xe70 -#define RTX_CCK_RFON 0xe74 -#define RTX_CCK_BBON 0xe78 -#define RTX_OFDM_RFON 0xe7c -#define RTX_OFDM_BBON 0xe80 -#define RTX_TO_RX 0xe84 -#define RTX_TO_TX 0xe88 -#define RRX_CCK 0xe8c - -#define RTX_POWER_BEFORE_IQK_A 0xe94 -#define RTX_POWER_AFTER_IQK_A 0xe9c - -#define RRX_POWER_BEFORE_IQK_A 0xea0 -#define RRX_POWER_BEFORE_IQK_A_2 0xea4 -#define RRX_POWER_AFTER_IQK_A 0xea8 -#define RRX_POWER_AFTER_IQK_A_2 0xeac - -#define RTX_POWER_BEFORE_IQK_B 0xeb4 -#define RTX_POWER_AFTER_IQK_B 0xebc - -#define RRX_POWER_BEFORE_IQK_B 0xec0 -#define RRX_POWER_BEFORE_IQK_B_2 0xec4 -#define RRX_POWER_AFTER_IQK_B 0xec8 -#define RRX_POWER_AFTER_IQK_B_2 0xecc - -#define RRX_OFDM 0xed0 -#define RRX_WAIT_RIFS 0xed4 -#define RRX_TO_RX 0xed8 -#define RSTANDBY 0xedc -#define RSLEEP 0xee0 -#define RPMPD_ANAEN 0xeec - -#define RZEBRA1_HSSIENABLE 0x0 -#define RZEBRA1_TRXENABLE1 0x1 -#define RZEBRA1_TRXENABLE2 0x2 -#define RZEBRA1_AGC 0x4 -#define RZEBRA1_CHARGEPUMP 0x5 -#define RZEBRA1_CHANNEL 0x7 - -#define RZEBRA1_TXGAIN 0x8 -#define RZEBRA1_TXLPF 0x9 -#define RZEBRA1_RXLPF 0xb -#define RZEBRA1_RXHPFCORNER 0xc - -#define RGLOBALCTRL 0 -#define RRTL8256_TXLPF 19 -#define RRTL8256_RXLPF 11 -#define RRTL8258_TXLPF 0x11 -#define RRTL8258_RXLPF 0x13 -#define RRTL8258_RSSILPF 0xa - -#define RF_AC 0x00 - -#define RF_IQADJ_G1 0x01 -#define RF_IQADJ_G2 0x02 -#define RF_POW_TRSW 0x05 - -#define RF_GAIN_RX 0x06 -#define RF_GAIN_TX 0x07 - -#define RF_TXM_IDAC 0x08 -#define RF_BS_IQGEN 0x0F - -#define RF_MODE1 0x10 -#define RF_MODE2 0x11 - -#define RF_RX_AGC_HP 0x12 -#define RF_TX_AGC 0x13 -#define RF_BIAS 0x14 -#define RF_IPA 0x15 -#define RF_POW_ABILITY 0x17 -#define RF_MODE_AG 0x18 -#define RRFCHANNEL 0x18 -#define RF_CHNLBW 0x18 -#define RF_TOP 0x19 - -#define RF_RX_G1 0x1A -#define RF_RX_G2 0x1B - -#define RF_RX_BB2 0x1C -#define RF_RX_BB1 0x1D - -#define RF_RCK1 0x1E -#define RF_RCK2 0x1F - -#define RF_TX_G1 0x20 -#define RF_TX_G2 0x21 -#define RF_TX_G3 0x22 - -#define RF_TX_BB1 0x23 -#define RF_T_METER 0x42 - -#define RF_SYN_G1 0x25 -#define RF_SYN_G2 0x26 -#define RF_SYN_G3 0x27 -#define RF_SYN_G4 0x28 -#define RF_SYN_G5 0x29 -#define RF_SYN_G6 0x2A -#define RF_SYN_G7 0x2B -#define RF_SYN_G8 0x2C - -#define RF_RCK_OS 0x30 -#define RF_TXPA_G1 0x31 -#define RF_TXPA_G2 0x32 -#define RF_TXPA_G3 0x33 - -#define RF_TX_BIAS_A 0x35 -#define RF_TX_BIAS_D 0x36 -#define RF_LOBF_9 0x38 -#define RF_RXRF_A3 0x3C -#define RF_TRSW 0x3F - -#define RF_TXRF_A2 0x41 -#define RF_TXPA_G4 0x46 -#define RF_TXPA_A4 0x4B - -#define RF_WE_LUT 0xEF - -#define BBBRESETB 0x100 -#define BGLOBALRESETB 0x200 -#define BOFDMTXSTART 0x4 -#define BCCKTXSTART 0x8 -#define BCRC32DEBUG 0x100 -#define BPMACLOOPBACK 0x10 -#define BTXLSIG 0xffffff -#define BOFDMTXRATE 0xf -#define BOFDMTXRESERVED 0x10 -#define BOFDMTXLENGTH 0x1ffe0 -#define BOFDMTXPARITY 0x20000 -#define BTXHTSIG1 0xffffff -#define BTXHTMCSRATE 0x7f -#define BTXHTBW 0x80 -#define BTXHTLENGTH 0xffff00 -#define BTXHTSIG2 0xffffff -#define BTXHTSMOOTHING 0x1 -#define BTXHTSOUNDING 0x2 -#define BTXHTRESERVED 0x4 -#define BTXHTAGGREATION 0x8 -#define BTXHTSTBC 0x30 -#define BTXHTADVANCECODING 0x40 -#define BTXHTSHORTGI 0x80 -#define BTXHTNUMBERHT_LTF 0x300 -#define BTXHTCRC8 0x3fc00 -#define BCOUNTERRESET 0x10000 -#define BNUMOFOFDMTX 0xffff -#define BNUMOFCCKTX 0xffff0000 -#define BTXIDLEINTERVAL 0xffff -#define BOFDMSERVICE 0xffff0000 -#define BTXMACHEADER 0xffffffff -#define BTXDATAINIT 0xff -#define BTXHTMODE 0x100 -#define BTXDATATYPE 0x30000 -#define BTXRANDOMSEED 0xffffffff -#define BCCKTXPREAMBLE 0x1 -#define BCCKTXSFD 0xffff0000 -#define BCCKTXSIG 0xff -#define BCCKTXSERVICE 0xff00 -#define BCCKLENGTHEXT 0x8000 -#define BCCKTXLENGHT 0xffff0000 -#define BCCKTXCRC16 0xffff -#define BCCKTXSTATUS 0x1 -#define BOFDMTXSTATUS 0x2 -#define IS_BB_REG_OFFSET_92S(_offset) \ - ((_offset >= 0x800) && (_offset <= 0xfff)) - -#define BRFMOD 0x1 -#define BJAPANMODE 0x2 -#define BCCKTXSC 0x30 -#define BCCKEN 0x1000000 -#define BOFDMEN 0x2000000 - -#define BOFDMRXADCPHASE 0x10000 -#define BOFDMTXDACPHASE 0x40000 -#define BXATXAGC 0x3f - -#define BXBTXAGC 0xf00 -#define BXCTXAGC 0xf000 -#define BXDTXAGC 0xf0000 - -#define BPASTART 0xf0000000 -#define BTRSTART 0x00f00000 -#define BRFSTART 0x0000f000 -#define BBBSTART 0x000000f0 -#define BBBCCKSTART 0x0000000f -#define BPAEND 0xf -#define BTREND 0x0f000000 -#define BRFEND 0x000f0000 -#define BCCAMASK 0x000000f0 -#define BR2RCCAMASK 0x00000f00 -#define BHSSI_R2TDELAY 0xf8000000 -#define BHSSI_T2RDELAY 0xf80000 -#define BCONTXHSSI 0x400 -#define BIGFROMCCK 0x200 -#define BAGCADDRESS 0x3f -#define BRXHPTX 0x7000 -#define BRXHP2RX 0x38000 -#define BRXHPCCKINI 0xc0000 -#define BAGCTXCODE 0xc00000 -#define BAGCRXCODE 0x300000 - -#define B3WIREDATALENGTH 0x800 -#define B3WIREADDREAALENGTH 0x400 - -#define B3WIRERFPOWERDOWN 0x1 -#define B5GPAPEPOLARITY 0x40000000 -#define B2GPAPEPOLARITY 0x80000000 -#define BRFSW_TXDEFAULTANT 0x3 -#define BRFSW_TXOPTIONANT 0x30 -#define BRFSW_RXDEFAULTANT 0x300 -#define BRFSW_RXOPTIONANT 0x3000 -#define BRFSI_3WIREDATA 0x1 -#define BRFSI_3WIRECLOCK 0x2 -#define BRFSI_3WIRELOAD 0x4 -#define BRFSI_3WIRERW 0x8 -#define BRFSI_3WIRE 0xf - -#define BRFSI_RFENV 0x10 - -#define BRFSI_TRSW 0x20 -#define BRFSI_TRSWB 0x40 -#define BRFSI_ANTSW 0x100 -#define BRFSI_ANTSWB 0x200 -#define BRFSI_PAPE 0x400 -#define BRFSI_PAPE5G 0x800 -#define BBANDSELECT 0x1 -#define BHTSIG2_GI 0x80 -#define BHTSIG2_SMOOTHING 0x01 -#define BHTSIG2_SOUNDING 0x02 -#define BHTSIG2_AGGREATON 0x08 -#define BHTSIG2_STBC 0x30 -#define BHTSIG2_ADVCODING 0x40 -#define BHTSIG2_NUMOFHTLTF 0x300 -#define BHTSIG2_CRC8 0x3fc -#define BHTSIG1_MCS 0x7f -#define BHTSIG1_BANDWIDTH 0x80 -#define BHTSIG1_HTLENGTH 0xffff -#define BLSIG_RATE 0xf -#define BLSIG_RESERVED 0x10 -#define BLSIG_LENGTH 0x1fffe -#define BLSIG_PARITY 0x20 -#define BCCKRXPHASE 0x4 - -#define BLSSIREADADDRESS 0x7f800000 -#define BLSSIREADEDGE 0x80000000 - -#define BLSSIREADBACKDATA 0xfffff - -#define BLSSIREADOKFLAG 0x1000 -#define BCCKSAMPLERATE 0x8 -#define BREGULATOR0STANDBY 0x1 -#define BREGULATORPLLSTANDBY 0x2 -#define BREGULATOR1STANDBY 0x4 -#define BPLLPOWERUP 0x8 -#define BDPLLPOWERUP 0x10 -#define BDA10POWERUP 0x20 -#define BAD7POWERUP 0x200 -#define BDA6POWERUP 0x2000 -#define BXTALPOWERUP 0x4000 -#define B40MDCLKPOWERUP 0x8000 -#define BDA6DEBUGMODE 0x20000 -#define BDA6SWING 0x380000 - -#define BADCLKPHASE 0x4000000 -#define B80MCLKDELAY 0x18000000 -#define BAFEWATCHDOGENABLE 0x20000000 - -#define BXTALCAP01 0xc0000000 -#define BXTALCAP23 0x3 -#define BXTALCAP92X 0x0f000000 -#define BXTALCAP 0x0f000000 - -#define BINTDIFCLKENABLE 0x400 -#define BEXTSIGCLKENABLE 0x800 -#define BBANDGAP_MBIAS_POWERUP 0x10000 -#define BAD11SH_GAIN 0xc0000 -#define BAD11NPUT_RANGE 0x700000 -#define BAD110P_CURRENT 0x3800000 -#define BLPATH_LOOPBACK 0x4000000 -#define BQPATH_LOOPBACK 0x8000000 -#define BAFE_LOOPBACK 0x10000000 -#define BDA10_SWING 0x7e0 -#define BDA10_REVERSE 0x800 -#define BDA_CLK_SOURCE 0x1000 -#define BDA7INPUT_RANGE 0x6000 -#define BDA7_GAIN 0x38000 -#define BDA7OUTPUT_CM_MODE 0x40000 -#define BDA7INPUT_CM_MODE 0x380000 -#define BDA7CURRENT 0xc00000 -#define BREGULATOR_ADJUST 0x7000000 -#define BAD11POWERUP_ATTX 0x1 -#define BDA10PS_ATTX 0x10 -#define BAD11POWERUP_ATRX 0x100 -#define BDA10PS_ATRX 0x1000 -#define BCCKRX_AGC_FORMAT 0x200 -#define BPSDFFT_SAMPLE_POINT 0xc000 -#define BPSD_AVERAGE_NUM 0x3000 -#define BIQPATH_CONTROL 0xc00 -#define BPSD_FREQ 0x3ff -#define BPSD_ANTENNA_PATH 0x30 -#define BPSD_IQ_SWITCH 0x40 -#define BPSD_RX_TRIGGER 0x400000 -#define BPSD_TX_TRIGGER 0x80000000 -#define BPSD_SINE_TONE_SCALE 0x7f000000 -#define BPSD_REPORT 0xffff - -#define BOFDM_TXSC 0x30000000 -#define BCCK_TXON 0x1 -#define BOFDM_TXON 0x2 -#define BDEBUG_PAGE 0xfff -#define BDEBUG_ITEM 0xff -#define BANTL 0x10 -#define BANT_NONHT 0x100 -#define BANT_HT1 0x1000 -#define BANT_HT2 0x10000 -#define BANT_HT1S1 0x100000 -#define BANT_NONHTS1 0x1000000 - -#define BCCK_BBMODE 0x3 -#define BCCK_TXPOWERSAVING 0x80 -#define BCCK_RXPOWERSAVING 0x40 - -#define BCCK_SIDEBAND 0x10 - -#define BCCK_SCRAMBLE 0x8 -#define BCCK_ANTDIVERSITY 0x8000 -#define BCCK_CARRIER_RECOVERY 0x4000 -#define BCCK_TXRATE 0x3000 -#define BCCK_DCCANCEL 0x0800 -#define BCCK_ISICANCEL 0x0400 -#define BCCK_MATCH_FILTER 0x0200 -#define BCCK_EQUALIZER 0x0100 -#define BCCK_PREAMBLE_DETECT 0x800000 -#define BCCK_FAST_FALSECCA 0x400000 -#define BCCK_CH_ESTSTART 0x300000 -#define BCCK_CCA_COUNT 0x080000 -#define BCCK_CS_LIM 0x070000 -#define BCCK_BIST_MODE 0x80000000 -#define BCCK_CCAMASK 0x40000000 -#define BCCK_TX_DAC_PHASE 0x4 -#define BCCK_RX_ADC_PHASE 0x20000000 -#define BCCKR_CP_MODE 0x0100 -#define BCCK_TXDC_OFFSET 0xf0 -#define BCCK_RXDC_OFFSET 0xf -#define BCCK_CCA_MODE 0xc000 -#define BCCK_FALSECS_LIM 0x3f00 -#define BCCK_CS_RATIO 0xc00000 -#define BCCK_CORGBIT_SEL 0x300000 -#define BCCK_PD_LIM 0x0f0000 -#define BCCK_NEWCCA 0x80000000 -#define BCCK_RXHP_OF_IG 0x8000 -#define BCCK_RXIG 0x7f00 -#define BCCK_LNA_POLARITY 0x800000 -#define BCCK_RX1ST_BAIN 0x7f0000 -#define BCCK_RF_EXTEND 0x20000000 -#define BCCK_RXAGC_SATLEVEL 0x1f000000 -#define BCCK_RXAGC_SATCOUNT 0xe0 -#define BCCKRXRFSETTLE 0x1f -#define BCCK_FIXED_RXAGC 0x8000 -#define BCCK_ANTENNA_POLARITY 0x2000 -#define BCCK_TXFILTER_TYPE 0x0c00 -#define BCCK_RXAGC_REPORTTYPE 0x0300 -#define BCCK_RXDAGC_EN 0x80000000 -#define BCCK_RXDAGC_PERIOD 0x20000000 -#define BCCK_RXDAGC_SATLEVEL 0x1f000000 -#define BCCK_TIMING_RECOVERY 0x800000 -#define BCCK_TXC0 0x3f0000 -#define BCCK_TXC1 0x3f000000 -#define BCCK_TXC2 0x3f -#define BCCK_TXC3 0x3f00 -#define BCCK_TXC4 0x3f0000 -#define BCCK_TXC5 0x3f000000 -#define BCCK_TXC6 0x3f -#define BCCK_TXC7 0x3f00 -#define BCCK_DEBUGPORT 0xff0000 -#define BCCK_DAC_DEBUG 0x0f000000 -#define BCCK_FALSEALARM_ENABLE 0x8000 -#define BCCK_FALSEALARM_READ 0x4000 -#define BCCK_TRSSI 0x7f -#define BCCK_RXAGC_REPORT 0xfe -#define BCCK_RXREPORT_ANTSEL 0x80000000 -#define BCCK_RXREPORT_MFOFF 0x40000000 -#define BCCK_RXREPORT_SQLOSS 0x20000000 -#define BCCK_RXREPORT_PKTLOSS 0x10000000 -#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 -#define BCCK_RXREPORT_RATEERROR 0x04000000 -#define BCCK_RXREPORT_RXRATE 0x03000000 -#define BCCK_RXFA_COUNTER_LOWER 0xff -#define BCCK_RXFA_COUNTER_UPPER 0xff000000 -#define BCCK_RXHPAGC_START 0xe000 -#define BCCK_RXHPAGC_FINAL 0x1c00 -#define BCCK_RXFALSEALARM_ENABLE 0x8000 -#define BCCK_FACOUNTER_FREEZE 0x4000 -#define BCCK_TXPATH_SEL 0x10000000 -#define BCCK_DEFAULT_RXPATH 0xc000000 -#define BCCK_OPTION_RXPATH 0x3000000 - -#define BNUM_OFSTF 0x3 -#define BSHIFT_L 0xc0 -#define BGI_TH 0xc -#define BRXPATH_A 0x1 -#define BRXPATH_B 0x2 -#define BRXPATH_C 0x4 -#define BRXPATH_D 0x8 -#define BTXPATH_A 0x1 -#define BTXPATH_B 0x2 -#define BTXPATH_C 0x4 -#define BTXPATH_D 0x8 -#define BTRSSI_FREQ 0x200 -#define BADC_BACKOFF 0x3000 -#define BDFIR_BACKOFF 0xc000 -#define BTRSSI_LATCH_PHASE 0x10000 -#define BRX_LDC_OFFSET 0xff -#define BRX_QDC_OFFSET 0xff00 -#define BRX_DFIR_MODE 0x1800000 -#define BRX_DCNF_TYPE 0xe000000 -#define BRXIQIMB_A 0x3ff -#define BRXIQIMB_B 0xfc00 -#define BRXIQIMB_C 0x3f0000 -#define BRXIQIMB_D 0xffc00000 -#define BDC_DC_NOTCH 0x60000 -#define BRXNB_NOTCH 0x1f000000 -#define BPD_TH 0xf -#define BPD_TH_OPT2 0xc000 -#define BPWED_TH 0x700 -#define BIFMF_WIN_L 0x800 -#define BPD_OPTION 0x1000 -#define BMF_WIN_L 0xe000 -#define BBW_SEARCH_L 0x30000 -#define BWIN_ENH_L 0xc0000 -#define BBW_TH 0x700000 -#define BED_TH2 0x3800000 -#define BBW_OPTION 0x4000000 -#define BRADIO_TH 0x18000000 -#define BWINDOW_L 0xe0000000 -#define BSBD_OPTION 0x1 -#define BFRAME_TH 0x1c -#define BFS_OPTION 0x60 -#define BDC_SLOPE_CHECK 0x80 -#define BFGUARD_COUNTER_DC_L 0xe00 -#define BFRAME_WEIGHT_SHORT 0x7000 -#define BSUB_TUNE 0xe00000 -#define BFRAME_DC_LENGTH 0xe000000 -#define BSBD_START_OFFSET 0x30000000 -#define BFRAME_TH_2 0x7 -#define BFRAME_GI2_TH 0x38 -#define BGI2_SYNC_EN 0x40 -#define BSARCH_SHORT_EARLY 0x300 -#define BSARCH_SHORT_LATE 0xc00 -#define BSARCH_GI2_LATE 0x70000 -#define BCFOANTSUM 0x1 -#define BCFOACC 0x2 -#define BCFOSTARTOFFSET 0xc -#define BCFOLOOPBACK 0x70 -#define BCFOSUMWEIGHT 0x80 -#define BDAGCENABLE 0x10000 -#define BTXIQIMB_A 0x3ff -#define BTXIQIMB_b 0xfc00 -#define BTXIQIMB_C 0x3f0000 -#define BTXIQIMB_D 0xffc00000 -#define BTXIDCOFFSET 0xff -#define BTXIQDCOFFSET 0xff00 -#define BTXDFIRMODE 0x10000 -#define BTXPESUDO_NOISEON 0x4000000 -#define BTXPESUDO_NOISE_A 0xff -#define BTXPESUDO_NOISE_B 0xff00 -#define BTXPESUDO_NOISE_C 0xff0000 -#define BTXPESUDO_NOISE_D 0xff000000 -#define BCCA_DROPOPTION 0x20000 -#define BCCA_DROPTHRES 0xfff00000 -#define BEDCCA_H 0xf -#define BEDCCA_L 0xf0 -#define BLAMBDA_ED 0x300 -#define BRX_INITIALGAIN 0x7f -#define BRX_ANTDIV_EN 0x80 -#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 -#define BRX_HIGHPOWER_FLOW 0x8000 -#define BRX_AGC_FREEZE_THRES 0xc0000 -#define BRX_FREEZESTEP_AGC1 0x300000 -#define BRX_FREEZESTEP_AGC2 0xc00000 -#define BRX_FREEZESTEP_AGC3 0x3000000 -#define BRX_FREEZESTEP_AGC0 0xc000000 -#define BRXRSSI_CMP_EN 0x10000000 -#define BRXQUICK_AGCEN 0x20000000 -#define BRXAGC_FREEZE_THRES_MODE 0x40000000 -#define BRX_OVERFLOW_CHECKTYPE 0x80000000 -#define BRX_AGCSHIFT 0x7f -#define BTRSW_TRI_ONLY 0x80 -#define BPOWER_THRES 0x300 -#define BRXAGC_EN 0x1 -#define BRXAGC_TOGETHER_EN 0x2 -#define BRXAGC_MIN 0x4 -#define BRXHP_INI 0x7 -#define BRXHP_TRLNA 0x70 -#define BRXHP_RSSI 0x700 -#define BRXHP_BBP1 0x7000 -#define BRXHP_BBP2 0x70000 -#define BRXHP_BBP3 0x700000 -#define BRSSI_H 0x7f0000 -#define BRSSI_GEN 0x7f000000 -#define BRXSETTLE_TRSW 0x7 -#define BRXSETTLE_LNA 0x38 -#define BRXSETTLE_RSSI 0x1c0 -#define BRXSETTLE_BBP 0xe00 -#define BRXSETTLE_RXHP 0x7000 -#define BRXSETTLE_ANTSW_RSSI 0x38000 -#define BRXSETTLE_ANTSW 0xc0000 -#define BRXPROCESS_TIME_DAGC 0x300000 -#define BRXSETTLE_HSSI 0x400000 -#define BRXPROCESS_TIME_BBPPW 0x800000 -#define BRXANTENNA_POWER_SHIFT 0x3000000 -#define BRSSI_TABLE_SELECT 0xc000000 -#define BRXHP_FINAL 0x7000000 -#define BRXHPSETTLE_BBP 0x7 -#define BRXHTSETTLE_HSSI 0x8 -#define BRXHTSETTLE_RXHP 0x70 -#define BRXHTSETTLE_BBPPW 0x80 -#define BRXHTSETTLE_IDLE 0x300 -#define BRXHTSETTLE_RESERVED 0x1c00 -#define BRXHT_RXHP_EN 0x8000 -#define BRXAGC_FREEZE_THRES 0x30000 -#define BRXAGC_TOGETHEREN 0x40000 -#define BRXHTAGC_MIN 0x80000 -#define BRXHTAGC_EN 0x100000 -#define BRXHTDAGC_EN 0x200000 -#define BRXHT_RXHP_BBP 0x1c00000 -#define BRXHT_RXHP_FINAL 0xe0000000 -#define BRXPW_RADIO_TH 0x3 -#define BRXPW_RADIO_EN 0x4 -#define BRXMF_HOLD 0x3800 -#define BRXPD_DELAY_TH1 0x38 -#define BRXPD_DELAY_TH2 0x1c0 -#define BRXPD_DC_COUNT_MAX 0x600 -#define BRXPD_DELAY_TH 0x8000 -#define BRXPROCESS_DELAY 0xf0000 -#define BRXSEARCHRANGE_GI2_EARLY 0x700000 -#define BRXFRAME_FUARD_COUNTER_L 0x3800000 -#define BRXSGI_GUARD_L 0xc000000 -#define BRXSGI_SEARCH_L 0x30000000 -#define BRXSGI_TH 0xc0000000 -#define BDFSCNT0 0xff -#define BDFSCNT1 0xff00 -#define BDFSFLAG 0xf0000 -#define BMF_WEIGHT_SUM 0x300000 -#define BMINIDX_TH 0x7f000000 -#define BDAFORMAT 0x40000 -#define BTXCH_EMU_ENABLE 0x01000000 -#define BTRSW_ISOLATION_A 0x7f -#define BTRSW_ISOLATION_B 0x7f00 -#define BTRSW_ISOLATION_C 0x7f0000 -#define BTRSW_ISOLATION_D 0x7f000000 -#define BEXT_LNA_GAIN 0x7c00 - -#define BSTBC_EN 0x4 -#define BANTENNA_MAPPING 0x10 -#define BNSS 0x20 -#define BCFO_ANTSUM_ID 0x200 -#define BPHY_COUNTER_RESET 0x8000000 -#define BCFO_REPORT_GET 0x4000000 -#define BOFDM_CONTINUE_TX 0x10000000 -#define BOFDM_SINGLE_CARRIER 0x20000000 -#define BOFDM_SINGLE_TONE 0x40000000 -#define BHT_DETECT 0x100 -#define BCFOEN 0x10000 -#define BCFOVALUE 0xfff00000 -#define BSIGTONE_RE 0x3f -#define BSIGTONE_IM 0x7f00 -#define BCOUNTER_CCA 0xffff -#define BCOUNTER_PARITYFAIL 0xffff0000 -#define BCOUNTER_RATEILLEGAL 0xffff -#define BCOUNTER_CRC8FAIL 0xffff0000 -#define BCOUNTER_MCSNOSUPPORT 0xffff -#define BCOUNTER_FASTSYNC 0xffff -#define BSHORTCFO 0xfff -#define BSHORTCFOT_LENGTH 12 -#define BSHORTCFOF_LENGTH 11 -#define BLONGCFO 0x7ff -#define BLONGCFOT_LENGTH 11 -#define BLONGCFOF_LENGTH 11 -#define BTAILCFO 0x1fff -#define BTAILCFOT_LENGTH 13 -#define BTAILCFOF_LENGTH 12 -#define BNOISE_EN_PWDB 0xffff -#define BCC_POWER_DB 0xffff0000 -#define BMOISE_PWDB 0xffff -#define BPOWERMEAST_LENGTH 10 -#define BPOWERMEASF_LENGTH 3 -#define BRX_HT_BW 0x1 -#define BRXSC 0x6 -#define BRX_HT 0x8 -#define BNB_INTF_DET_ON 0x1 -#define BINTF_WIN_LEN_CFG 0x30 -#define BNB_INTF_TH_CFG 0x1c0 -#define BRFGAIN 0x3f -#define BTABLESEL 0x40 -#define BTRSW 0x80 -#define BRXSNR_A 0xff -#define BRXSNR_B 0xff00 -#define BRXSNR_C 0xff0000 -#define BRXSNR_D 0xff000000 -#define BSNR_EVMT_LENGTH 8 -#define BSNR_EVMF_LENGTH 1 -#define BCSI1ST 0xff -#define BCSI2ND 0xff00 -#define BRXEVM1ST 0xff0000 -#define BRXEVM2ND 0xff000000 -#define BSIGEVM 0xff -#define BPWDB 0xff00 -#define BSGIEN 0x10000 - -#define BSFACTOR_QMA1 0xf -#define BSFACTOR_QMA2 0xf0 -#define BSFACTOR_QMA3 0xf00 -#define BSFACTOR_QMA4 0xf000 -#define BSFACTOR_QMA5 0xf0000 -#define BSFACTOR_QMA6 0xf0000 -#define BSFACTOR_QMA7 0xf00000 -#define BSFACTOR_QMA8 0xf000000 -#define BSFACTOR_QMA9 0xf0000000 -#define BCSI_SCHEME 0x100000 - -#define BNOISE_LVL_TOP_SET 0x3 -#define BCHSMOOTH 0x4 -#define BCHSMOOTH_CFG1 0x38 -#define BCHSMOOTH_CFG2 0x1c0 -#define BCHSMOOTH_CFG3 0xe00 -#define BCHSMOOTH_CFG4 0x7000 -#define BMRCMODE 0x800000 -#define BTHEVMCFG 0x7000000 - -#define BLOOP_FIT_TYPE 0x1 -#define BUPD_CFO 0x40 -#define BUPD_CFO_OFFDATA 0x80 -#define BADV_UPD_CFO 0x100 -#define BADV_TIME_CTRL 0x800 -#define BUPD_CLKO 0x1000 -#define BFC 0x6000 -#define BTRACKING_MODE 0x8000 -#define BPHCMP_ENABLE 0x10000 -#define BUPD_CLKO_LTF 0x20000 -#define BCOM_CH_CFO 0x40000 -#define BCSI_ESTI_MODE 0x80000 -#define BADV_UPD_EQZ 0x100000 -#define BUCHCFG 0x7000000 -#define BUPDEQZ 0x8000000 - -#define BRX_PESUDO_NOISE_ON 0x20000000 -#define BRX_PESUDO_NOISE_A 0xff -#define BRX_PESUDO_NOISE_B 0xff00 -#define BRX_PESUDO_NOISE_C 0xff0000 -#define BRX_PESUDO_NOISE_D 0xff000000 -#define BRX_PESUDO_NOISESTATE_A 0xffff -#define BRX_PESUDO_NOISESTATE_B 0xffff0000 -#define BRX_PESUDO_NOISESTATE_C 0xffff -#define BRX_PESUDO_NOISESTATE_D 0xffff0000 - -#define BZEBRA1_HSSIENABLE 0x8 -#define BZEBRA1_TRXCONTROL 0xc00 -#define BZEBRA1_TRXGAINSETTING 0x07f -#define BZEBRA1_RXCOUNTER 0xc00 -#define BZEBRA1_TXCHANGEPUMP 0x38 -#define BZEBRA1_RXCHANGEPUMP 0x7 -#define BZEBRA1_CHANNEL_NUM 0xf80 -#define BZEBRA1_TXLPFBW 0x400 -#define BZEBRA1_RXLPFBW 0x600 - -#define BRTL8256REG_MODE_CTRL1 0x100 -#define BRTL8256REG_MODE_CTRL0 0x40 -#define BRTL8256REG_TXLPFBW 0x18 -#define BRTL8256REG_RXLPFBW 0x600 - -#define BRTL8258_TXLPFBW 0xc -#define BRTL8258_RXLPFBW 0xc00 -#define BRTL8258_RSSILPFBW 0xc0 - -#define BBYTE0 0x1 -#define BBYTE1 0x2 -#define BBYTE2 0x4 -#define BBYTE3 0x8 -#define BWORD0 0x3 -#define BWORD1 0xc -#define BWORD 0xf - -#define MASKBYTE0 0xff -#define MASKBYTE1 0xff00 -#define MASKBYTE2 0xff0000 -#define MASKBYTE3 0xff000000 -#define MASKHWORD 0xffff0000 -#define MASKLWORD 0x0000ffff -#define MASKDWORD 0xffffffff -#define MASK12BITS 0xfff -#define MASKH4BITS 0xf0000000 -#define MASKOFDM_D 0xffc00000 -#define MASKCCK 0x3f3f3f3f - -#define MASK4BITS 0x0f -#define MASK20BITS 0xfffff -#define RFREG_OFFSET_MASK 0xfffff - -#define BENABLE 0x1 -#define BDISABLE 0x0 - -#define LEFT_ANTENNA 0x0 -#define RIGHT_ANTENNA 0x1 - -#define TCHECK_TXSTATUS 500 -#define TUPDATE_RXCOUNTER 100 - -#define REG_UN_used_register 0x01bf - -/* WOL bit information */ -#define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0) -#define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1) -#define HAL92C_WOL_DISASSOC_EVENT BIT(2) -#define HAL92C_WOL_DEAUTH_EVENT BIT(3) -#define HAL92C_WOL_FW_DISCONNECT_EVENT BIT(4) - -#define WOL_REASON_PTK_UPDATE BIT(0) -#define WOL_REASON_GTK_UPDATE BIT(1) -#define WOL_REASON_DISASSOC BIT(2) -#define WOL_REASON_DEAUTH BIT(3) -#define WOL_REASON_FW_DISCONNECT BIT(4) -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ee/rf.c deleted file mode 100644 index c9bc33cd1090..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/rf.c +++ /dev/null @@ -1,152 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" - -static bool _rtl92ee_phy_rf6052_config_parafile(struct ieee80211_hw *hw); - -void rtl92ee_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - switch (bandwidth) { - case HT_CHANNEL_WIDTH_20: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff) | BIT(10) | BIT(11)); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - case HT_CHANNEL_WIDTH_20_40: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff) | BIT(10)); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", bandwidth); - break; - } -} - -bool rtl92ee_phy_rf6052_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - if (rtlphy->rf_type == RF_1T1R) - rtlphy->num_total_rfpath = 1; - else - rtlphy->num_total_rfpath = 2; - - return _rtl92ee_phy_rf6052_config_parafile(hw); -} - -static bool _rtl92ee_phy_rf6052_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 u4_regvalue = 0; - u8 rfpath; - bool rtstatus = true; - struct bb_reg_def *pphyreg; - - for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { - pphyreg = &rtlphy->phyreg_def[rfpath]; - - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV); - break; - case RF90_PATH_B: - case RF90_PATH_D: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16); - break; - } - - rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, - B3WIREADDREAALENGTH, 0x0); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); - udelay(1); - - switch (rfpath) { - case RF90_PATH_A: - rtstatus = rtl92ee_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_B: - rtstatus = rtl92ee_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_C: - break; - case RF90_PATH_D: - break; - } - - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - rtl_set_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV, u4_regvalue); - break; - case RF90_PATH_B: - case RF90_PATH_D: - rtl_set_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16, u4_regvalue); - break; - } - - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio[%d] Fail!!", rfpath); - return false; - } - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); - return rtstatus; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/rf.h b/drivers/net/wireless/rtlwifi/rtl8192ee/rf.h deleted file mode 100644 index 039c0133ad6b..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/rf.h +++ /dev/null @@ -1,35 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92E_RF_H__ -#define __RTL92E_RF_H__ - -#define RF6052_MAX_TX_PWR 0x3F - -void rtl92ee_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, - u8 bandwidth); -bool rtl92ee_phy_rf6052_config(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c deleted file mode 100644 index c31c6bfb536d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.c +++ /dev/null @@ -1,398 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../core.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "hw.h" -#include "sw.h" -#include "fw.h" -#include "trx.h" -#include "led.h" -#include "table.h" - -#include "../btcoexist/rtl_btc.h" - -#include -#include - -static void rtl92ee_init_aspm_vars(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - /*close ASPM for AMD defaultly */ - rtlpci->const_amdpci_aspm = 0; - - /** - * ASPM PS mode. - * 0 - Disable ASPM, - * 1 - Enable ASPM without Clock Req, - * 2 - Enable ASPM with Clock Req, - * 3 - Alwyas Enable ASPM with Clock Req, - * 4 - Always Enable ASPM without Clock Req. - * set defult to RTL8192CE:3 RTL8192E:2 - */ - rtlpci->const_pci_aspm = 3; - - /*Setting for PCI-E device */ - rtlpci->const_devicepci_aspm_setting = 0x03; - - /*Setting for PCI-E bridge */ - rtlpci->const_hostpci_aspm_setting = 0x02; - - /** - * In Hw/Sw Radio Off situation. - * 0 - Default, - * 1 - From ASPM setting without low Mac Pwr, - * 2 - From ASPM setting with low Mac Pwr, - * 3 - Bus D3 - * set default to RTL8192CE:0 RTL8192SE:2 - */ - rtlpci->const_hwsw_rfoff_d3 = 0; - - /** - * This setting works for those device with - * backdoor ASPM setting such as EPHY setting. - * 0 - Not support ASPM, - * 1 - Support ASPM, - * 2 - According to chipset. - */ - rtlpci->const_support_pciaspm = 1; -} - -int rtl92ee_init_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - int err = 0; - - rtl92ee_bt_reg_init(hw); - rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; - rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); - - rtlpriv->dm.dm_initialgain_enable = 1; - rtlpriv->dm.dm_flag = 0; - rtlpriv->dm.disable_framebursting = 0; - rtlpci->transmit_config = CFENDFORM | BIT(15); - - /*just 2.4G band*/ - rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; - rtlpriv->rtlhal.bandset = BAND_ON_2_4G; - rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; - - rtlpci->receive_config = (RCR_APPFCS | - RCR_APP_MIC | - RCR_APP_ICV | - RCR_APP_PHYST_RXFF | - RCR_HTC_LOC_CTRL | - RCR_AMF | - RCR_ACF | - RCR_ACRC32 | - RCR_AB | - RCR_AM | - RCR_APM | - 0); - - rtlpci->irq_mask[0] = (u32)(IMR_PSTIMEOUT | - IMR_C2HCMD | - IMR_HIGHDOK | - IMR_MGNTDOK | - IMR_BKDOK | - IMR_BEDOK | - IMR_VIDOK | - IMR_VODOK | - IMR_RDU | - IMR_ROK | - 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; - rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; - rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; - if (rtlpriv->cfg->mod_params->disable_watchdog) - pr_info("watchdog disabled\n"); - rtlpriv->psc.reg_fwctrl_lps = 3; - rtlpriv->psc.reg_max_lps_awakeintvl = 5; - /* for ASPM, you can close aspm through - * set const_support_pciaspm = 0 - */ - rtl92ee_init_aspm_vars(hw); - - if (rtlpriv->psc.reg_fwctrl_lps == 1) - rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 2) - rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 3) - rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; - - /* for early mode */ - rtlpriv->rtlhal.earlymode_enable = false; - - /*low power */ - rtlpriv->psc.low_power_enable = false; - - /* for firmware buf */ - rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); - if (!rtlpriv->rtlhal.pfirmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't alloc buffer for fw\n"); - return 1; - } - - /* request fw */ - rtlpriv->cfg->fw_name = "rtlwifi/rtl8192eefw.bin"; - - rtlpriv->max_fw_size = 0x8000; - pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); - err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, - rtlpriv->io.dev, GFP_KERNEL, hw, - rtl_fw_cb); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to request firmware!\n"); - return 1; - } - - return 0; -} - -void rtl92ee_deinit_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->rtlhal.pfirmware) { - vfree(rtlpriv->rtlhal.pfirmware); - rtlpriv->rtlhal.pfirmware = NULL; - } -} - -/* get bt coexist status */ -bool rtl92ee_get_btc_status(void) -{ - return true; -} - -static struct rtl_hal_ops rtl8192ee_hal_ops = { - .init_sw_vars = rtl92ee_init_sw_vars, - .deinit_sw_vars = rtl92ee_deinit_sw_vars, - .read_eeprom_info = rtl92ee_read_eeprom_info, - .interrupt_recognized = rtl92ee_interrupt_recognized,/*need check*/ - .hw_init = rtl92ee_hw_init, - .hw_disable = rtl92ee_card_disable, - .hw_suspend = rtl92ee_suspend, - .hw_resume = rtl92ee_resume, - .enable_interrupt = rtl92ee_enable_interrupt, - .disable_interrupt = rtl92ee_disable_interrupt, - .set_network_type = rtl92ee_set_network_type, - .set_chk_bssid = rtl92ee_set_check_bssid, - .set_qos = rtl92ee_set_qos, - .set_bcn_reg = rtl92ee_set_beacon_related_registers, - .set_bcn_intv = rtl92ee_set_beacon_interval, - .update_interrupt_mask = rtl92ee_update_interrupt_mask, - .get_hw_reg = rtl92ee_get_hw_reg, - .set_hw_reg = rtl92ee_set_hw_reg, - .update_rate_tbl = rtl92ee_update_hal_rate_tbl, - .pre_fill_tx_bd_desc = rtl92ee_pre_fill_tx_bd_desc, - .rx_desc_buff_remained_cnt = rtl92ee_rx_desc_buff_remained_cnt, - .rx_check_dma_ok = rtl92ee_rx_check_dma_ok, - .fill_tx_desc = rtl92ee_tx_fill_desc, - .fill_tx_cmddesc = rtl92ee_tx_fill_cmddesc, - .query_rx_desc = rtl92ee_rx_query_desc, - .set_channel_access = rtl92ee_update_channel_access_setting, - .radio_onoff_checking = rtl92ee_gpio_radio_on_off_checking, - .set_bw_mode = rtl92ee_phy_set_bw_mode, - .switch_channel = rtl92ee_phy_sw_chnl, - .dm_watchdog = rtl92ee_dm_watchdog, - .scan_operation_backup = rtl92ee_phy_scan_operation_backup, - .set_rf_power_state = rtl92ee_phy_set_rf_power_state, - .led_control = rtl92ee_led_control, - .set_desc = rtl92ee_set_desc, - .get_desc = rtl92ee_get_desc, - .is_tx_desc_closed = rtl92ee_is_tx_desc_closed, - .get_available_desc = rtl92ee_get_available_desc, - .tx_polling = rtl92ee_tx_polling, - .enable_hw_sec = rtl92ee_enable_hw_security_config, - .set_key = rtl92ee_set_key, - .init_sw_leds = rtl92ee_init_sw_leds, - .get_bbreg = rtl92ee_phy_query_bb_reg, - .set_bbreg = rtl92ee_phy_set_bb_reg, - .get_rfreg = rtl92ee_phy_query_rf_reg, - .set_rfreg = rtl92ee_phy_set_rf_reg, - .fill_h2c_cmd = rtl92ee_fill_h2c_cmd, - .get_btc_status = rtl92ee_get_btc_status, - .rx_command_packet = rtl92ee_rx_command_packet, -}; - -static struct rtl_mod_params rtl92ee_mod_params = { - .sw_crypto = false, - .inactiveps = false, - .swctrl_lps = false, - .fwctrl_lps = true, - .msi_support = true, - .debug = DBG_EMERG, -}; - -static struct rtl_hal_cfg rtl92ee_hal_cfg = { - .bar_id = 2, - .write_readback = true, - .name = "rtl92ee_pci", - .fw_name = "rtlwifi/rtl8192eefw.bin", - .ops = &rtl8192ee_hal_ops, - .mod_params = &rtl92ee_mod_params, - - .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, - .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, - .maps[SYS_CLK] = REG_SYS_CLKR, - .maps[MAC_RCR_AM] = AM, - .maps[MAC_RCR_AB] = AB, - .maps[MAC_RCR_ACRC32] = ACRC32, - .maps[MAC_RCR_ACF] = ACF, - .maps[MAC_RCR_AAP] = AAP, - .maps[MAC_HIMR] = REG_HIMR, - .maps[MAC_HIMRE] = REG_HIMRE, - - .maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS, - - .maps[EFUSE_TEST] = REG_EFUSE_TEST, - .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_CLK] = 0, - .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_PWC_EV12V] = PWC_EV12V, - .maps[EFUSE_FEN_ELDR] = FEN_ELDR, - .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, - .maps[EFUSE_ANA8M] = ANA8M, - .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, - .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, - .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, - .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, - - .maps[RWCAM] = REG_CAMCMD, - .maps[WCAMI] = REG_CAMWRITE, - .maps[RCAMO] = REG_CAMREAD, - .maps[CAMDBG] = REG_CAMDBG, - .maps[SECR] = REG_SECCFG, - .maps[SEC_CAM_NONE] = CAM_NONE, - .maps[SEC_CAM_WEP40] = CAM_WEP40, - .maps[SEC_CAM_TKIP] = CAM_TKIP, - .maps[SEC_CAM_AES] = CAM_AES, - .maps[SEC_CAM_WEP104] = CAM_WEP104, - - .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, - .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, - .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, - .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, - .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, - .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, - .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, - .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, - .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, - .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, - .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, - .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, - .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, - - .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, - .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, - .maps[RTL_IMR_BCNINT] = IMR_BCNDMAINT0, - .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, - .maps[RTL_IMR_RDU] = IMR_RDU, - .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, - .maps[RTL_IMR_BDOK] = IMR_BCNDOK0, - .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, - .maps[RTL_IMR_TBDER] = IMR_TBDER, - .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, - .maps[RTL_IMR_TBDOK] = IMR_TBDOK, - .maps[RTL_IMR_BKDOK] = IMR_BKDOK, - .maps[RTL_IMR_BEDOK] = IMR_BEDOK, - .maps[RTL_IMR_VIDOK] = IMR_VIDOK, - .maps[RTL_IMR_VODOK] = IMR_VODOK, - .maps[RTL_IMR_ROK] = IMR_ROK, - .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER), - - .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, -}; - -static struct pci_device_id rtl92ee_pci_ids[] = { - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x818B, rtl92ee_hal_cfg)}, - {}, -}; - -MODULE_DEVICE_TABLE(pci, rtl92ee_pci_ids); - -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_AUTHOR("Larry Finger "); -MODULE_LICENSE("GPL"); -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(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); -module_param_named(msi, rtl92ee_mod_params.msi_support, bool, 0444); -module_param_named(disable_watchdog, rtl92ee_mod_params.disable_watchdog, - bool, 0444); -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(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(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); - -static struct pci_driver rtl92ee_driver = { - .name = KBUILD_MODNAME, - .id_table = rtl92ee_pci_ids, - .probe = rtl_pci_probe, - .remove = rtl_pci_disconnect, - .driver.pm = &rtlwifi_pm_ops, -}; - -module_pci_driver(rtl92ee_driver); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.h b/drivers/net/wireless/rtlwifi/rtl8192ee/sw.h deleted file mode 100644 index 21433d0332d0..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/sw.h +++ /dev/null @@ -1,33 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92E_SW_H__ -#define __RTL92E_SW_H__ - -int rtl92ee_init_sw_vars(struct ieee80211_hw *hw); -void rtl92ee_deinit_sw_vars(struct ieee80211_hw *hw); -bool rtl92ee_get_btc_status(void); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/table.c b/drivers/net/wireless/rtlwifi/rtl8192ee/table.c deleted file mode 100644 index abcdd0670fd8..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/table.c +++ /dev/null @@ -1,882 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ - -#include "table.h" -u32 RTL8192EE_PHY_REG_ARRAY[] = { - 0x800, 0x80040000, - 0x804, 0x00000003, - 0x808, 0x0000FC00, - 0x80C, 0x0000000A, - 0x810, 0x10001331, - 0x814, 0x020C3D10, - 0x818, 0x02220385, - 0x81C, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390204, - 0x828, 0x01000100, - 0x82C, 0x00390204, - 0x830, 0x32323232, - 0x834, 0x30303030, - 0x838, 0x30303030, - 0x83C, 0x30303030, - 0x840, 0x00010000, - 0x844, 0x00010000, - 0x848, 0x28282828, - 0x84C, 0x28282828, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x009A009A, - 0x85C, 0x01000014, - 0x860, 0x66F60000, - 0x864, 0x061F0000, - 0x868, 0x30303030, - 0x86C, 0x30303030, - 0x870, 0x00000000, - 0x874, 0x55004200, - 0x878, 0x08080808, - 0x87C, 0x00000000, - 0x880, 0xB0000C1C, - 0x884, 0x00000001, - 0x888, 0x00000000, - 0x88C, 0xCC0000C0, - 0x890, 0x00000800, - 0x894, 0xFFFFFFFE, - 0x898, 0x40302010, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90C, 0x81121313, - 0x910, 0x806C0001, - 0x914, 0x00000001, - 0x918, 0x00000000, - 0x91C, 0x00010000, - 0x924, 0x00000001, - 0x928, 0x00000000, - 0x92C, 0x00000000, - 0x930, 0x00000000, - 0x934, 0x00000000, - 0x938, 0x00000000, - 0x93C, 0x00000000, - 0x940, 0x00000000, - 0x944, 0x00000000, - 0x94C, 0x00000008, - 0xA00, 0x00D0C7C8, - 0xA04, 0x81FF000C, - 0xA08, 0x8C838300, - 0xA0C, 0x2E68120F, - 0xA10, 0x95009B78, - 0xA14, 0x1114D028, - 0xA18, 0x00881117, - 0xA1C, 0x89140F00, - 0xA20, 0x1A1B0000, - 0xA24, 0x090E1317, - 0xA28, 0x00000204, - 0xA2C, 0x00D30000, - 0xA70, 0x101FBF00, - 0xA74, 0x00000007, - 0xA78, 0x00000900, - 0xA7C, 0x225B0606, - 0xA80, 0x218075B1, - 0xB38, 0x00000000, - 0xC00, 0x48071D40, - 0xC04, 0x03A05633, - 0xC08, 0x000000E4, - 0xC0C, 0x6C6C6C6C, - 0xC10, 0x08800000, - 0xC14, 0x40000100, - 0xC18, 0x08800000, - 0xC1C, 0x40000100, - 0xC20, 0x00000000, - 0xC24, 0x00000000, - 0xC28, 0x00000000, - 0xC2C, 0x00000000, - 0xC30, 0x69E9AC47, - 0xC34, 0x469652AF, - 0xC38, 0x49795994, - 0xC3C, 0x0A97971C, - 0xC40, 0x1F7C403F, - 0xC44, 0x000100B7, - 0xC48, 0xEC020107, - 0xC4C, 0x007F037F, - 0xFF010718, 0xABCD, - 0xC50, 0x00340220, - 0xCDCDCDCD, 0xCDCD, - 0xC50, 0x00340020, - 0xFF010718, 0xDEAD, - 0xC54, 0x0080801F, - 0xFF010718, 0xABCD, - 0xC58, 0x00000220, - 0xCDCDCDCD, 0xCDCD, - 0xC58, 0x00000020, - 0xFF010718, 0xDEAD, - 0xC5C, 0x00248492, - 0xC60, 0x00000000, - 0xC64, 0x7112848B, - 0xC68, 0x47C00BFF, - 0xC6C, 0x00000036, - 0xC70, 0x00000600, - 0xC74, 0x02013169, - 0xC78, 0x0000001F, - 0xC7C, 0x00B91612, - 0xFF010718, 0xABCD, - 0xC80, 0x2D4000B5, - 0xCDCDCDCD, 0xCDCD, - 0xC80, 0x40000100, - 0xFF010718, 0xDEAD, - 0xC84, 0x21F60000, - 0xFF010718, 0xABCD, - 0xC88, 0x2D4000B5, - 0xCDCDCDCD, 0xCDCD, - 0xC88, 0x40000100, - 0xFF010718, 0xDEAD, - 0xC8C, 0xA0E40000, - 0xC90, 0x00121820, - 0xC94, 0x00000000, - 0xC98, 0x00121820, - 0xC9C, 0x00007F7F, - 0xCA0, 0x00000000, - 0xCA4, 0x000300A0, - 0xCA8, 0x00000000, - 0xCAC, 0x00000000, - 0xCB0, 0x00000000, - 0xCB4, 0x00000000, - 0xCB8, 0x00000000, - 0xCBC, 0x28000000, - 0xCC0, 0x00000000, - 0xCC4, 0x00000000, - 0xCC8, 0x00000000, - 0xCCC, 0x00000000, - 0xCD0, 0x00000000, - 0xCD4, 0x00000000, - 0xCD8, 0x64B22427, - 0xCDC, 0x00766932, - 0xCE0, 0x00222222, - 0xCE4, 0x00040000, - 0xCE8, 0x77644302, - 0xCEC, 0x2F97D40C, - 0xD00, 0x00080740, - 0xD04, 0x00020403, - 0xD08, 0x0000907F, - 0xD0C, 0x20010201, - 0xD10, 0xA0633333, - 0xD14, 0x3333BC43, - 0xD18, 0x7A8F5B6B, - 0xD1C, 0x0000007F, - 0xD2C, 0xCC979975, - 0xD30, 0x00000000, - 0xD34, 0x80608000, - 0xD38, 0x00000000, - 0xD3C, 0x00127353, - 0xD40, 0x00000000, - 0xD44, 0x00000000, - 0xD48, 0x00000000, - 0xD4C, 0x00000000, - 0xD50, 0x6437140A, - 0xD54, 0x00000000, - 0xD58, 0x00000282, - 0xD5C, 0x30032064, - 0xD60, 0x4653DE68, - 0xD64, 0x04518A3C, - 0xD68, 0x00002101, - 0xD6C, 0x2A201C16, - 0xD70, 0x1812362E, - 0xD74, 0x322C2220, - 0xD78, 0x000E3C24, - 0xD80, 0x01081008, - 0xD84, 0x00000800, - 0xD88, 0xF0B50000, - 0xE00, 0x30303030, - 0xE04, 0x30303030, - 0xE08, 0x03903030, - 0xE10, 0x30303030, - 0xE14, 0x30303030, - 0xE18, 0x30303030, - 0xE1C, 0x30303030, - 0xE28, 0x00000000, - 0xE30, 0x1000DC1F, - 0xE34, 0x10008C1F, - 0xE38, 0x02140102, - 0xE3C, 0x681604C2, - 0xE40, 0x01007C00, - 0xE44, 0x01004800, - 0xE48, 0xFB000000, - 0xE4C, 0x000028D1, - 0xE50, 0x1000DC1F, - 0xE54, 0x10008C1F, - 0xE58, 0x02140102, - 0xE5C, 0x28160D05, - 0xE60, 0x00000008, - 0xE68, 0x0FC05656, - 0xE6C, 0x03C09696, - 0xE70, 0x03C09696, - 0xE74, 0x0C005656, - 0xE78, 0x0C005656, - 0xE7C, 0x0C005656, - 0xE80, 0x0C005656, - 0xE84, 0x03C09696, - 0xE88, 0x0C005656, - 0xE8C, 0x03C09696, - 0xED0, 0x03C09696, - 0xED4, 0x03C09696, - 0xED8, 0x03C09696, - 0xEDC, 0x0000D6D6, - 0xEE0, 0x0000D6D6, - 0xEEC, 0x0FC01616, - 0xEE4, 0xB0000C1C, - 0xEE8, 0x00000001, - 0xF14, 0x00000003, - 0xF4C, 0x00000000, - 0xF00, 0x00000300, -}; - -u32 RTL8192EE_PHY_REG_ARRAY_PG[] = { - 0, 0, 0, 0x00000e08, 0x0000ff00, 0x00003200, - 0, 0, 1, 0x00000e08, 0x0000ff00, 0x00003200, - 0, 0, 0, 0x0000086c, 0xffffff00, 0x32323200, - 0, 0, 1, 0x0000086c, 0xffffff00, 0x32323200, - 0, 0, 0, 0x00000e00, 0xffffffff, 0x34343636, - 0, 0, 1, 0x00000e00, 0xffffffff, 0x34343636, - 0, 0, 0, 0x00000e04, 0xffffffff, 0x28283032, - 0, 0, 1, 0x00000e04, 0xffffffff, 0x28283032, - 0, 0, 0, 0x00000e10, 0xffffffff, 0x34363840, - 0, 0, 1, 0x00000e10, 0xffffffff, 0x34363840, - 0, 0, 0, 0x00000e14, 0xffffffff, 0x26283032, - 0, 0, 1, 0x00000e14, 0xffffffff, 0x26283032, - 0, 0, 1, 0x00000e18, 0xffffffff, 0x36384040, - 0, 0, 1, 0x00000e1c, 0xffffffff, 0x24262832, - 0, 1, 0, 0x00000838, 0xffffff00, 0x32323200, - 0, 1, 1, 0x00000838, 0xffffff00, 0x32323200, - 0, 1, 0, 0x0000086c, 0x000000ff, 0x00000032, - 0, 1, 1, 0x0000086c, 0x000000ff, 0x00000032, - 0, 1, 0, 0x00000830, 0xffffffff, 0x34343636, - 0, 1, 1, 0x00000830, 0xffffffff, 0x34343636, - 0, 1, 0, 0x00000834, 0xffffffff, 0x28283032, - 0, 1, 1, 0x00000834, 0xffffffff, 0x28283032, - 0, 1, 0, 0x0000083c, 0xffffffff, 0x34363840, - 0, 1, 1, 0x0000083c, 0xffffffff, 0x34363840, - 0, 1, 0, 0x00000848, 0xffffffff, 0x26283032, - 0, 1, 1, 0x00000848, 0xffffffff, 0x26283032, - 0, 1, 1, 0x0000084c, 0xffffffff, 0x36384040, - 0, 1, 1, 0x00000868, 0xffffffff, 0x24262832 -}; - -u32 RTL8192EE_RADIOA_ARRAY[] = { - 0x07F, 0x00000082, - 0x081, 0x0003FC00, - 0x000, 0x00030000, - 0x008, 0x00008400, - 0x018, 0x00000407, - 0x019, 0x00000012, - 0x01B, 0x00000064, - 0x01E, 0x00080009, - 0x01F, 0x00000880, - 0x02F, 0x0001A060, - 0x03F, 0x00000000, - 0x042, 0x000060C0, - 0x057, 0x000D0000, - 0x058, 0x000BE180, - 0x067, 0x00001552, - 0x083, 0x00000000, - 0x0B0, 0x000FF9F1, - 0x0B1, 0x00055418, - 0x0B2, 0x0008CC00, - 0x0B4, 0x00043083, - 0x0B5, 0x00008166, - 0x0B6, 0x0000803E, - 0x0B7, 0x0001C69F, - 0x0B8, 0x0000407F, - 0x0B9, 0x00080001, - 0x0BA, 0x00040001, - 0x0BB, 0x00000400, - 0x0BF, 0x000C0000, - 0x0C2, 0x00002400, - 0x0C3, 0x00000009, - 0x0C4, 0x00040C91, - 0x0C5, 0x00099999, - 0x0C6, 0x000000A3, - 0x0C7, 0x00088820, - 0x0C8, 0x00076C06, - 0x0C9, 0x00000000, - 0x0CA, 0x00080000, - 0x0DF, 0x00000180, - 0x0EF, 0x000001A0, - 0x051, 0x00069545, - 0x052, 0x0007E45E, - 0x053, 0x00000071, - 0x056, 0x00051FF3, - 0x035, 0x000000A8, - 0x035, 0x000001E2, - 0x035, 0x000002A8, - 0x036, 0x00001C24, - 0x036, 0x00009C24, - 0x036, 0x00011C24, - 0x036, 0x00019C24, - 0x018, 0x00000C07, - 0x05A, 0x00048000, - 0x019, 0x000739D0, - 0xFF010718, 0xABCD, - 0x034, 0x0000A093, - 0x034, 0x0000908F, - 0x034, 0x0000808C, - 0x034, 0x0000704D, - 0x034, 0x0000604A, - 0x034, 0x00005047, - 0x034, 0x0000400A, - 0x034, 0x00003007, - 0x034, 0x00002004, - 0x034, 0x00001001, - 0x034, 0x00000000, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0000ADD7, - 0x034, 0x00009DD4, - 0x034, 0x00008DD1, - 0x034, 0x00007DCE, - 0x034, 0x00006DCB, - 0x034, 0x00005DC8, - 0x034, 0x00004DC5, - 0x034, 0x000034CC, - 0x034, 0x0000244F, - 0x034, 0x0000144C, - 0x034, 0x00000014, - 0xFF010718, 0xDEAD, - 0x000, 0x00030159, - 0x084, 0x00068180, - 0x086, 0x0000014E, - 0x087, 0x00048E00, - 0x08E, 0x00065540, - 0x08F, 0x00088000, - 0x0EF, 0x000020A0, - 0xFF010718, 0xABCD, - 0x03B, 0x000F07B0, - 0xCDCDCDCD, 0xCDCD, - 0x03B, 0x000F02B0, - 0xFF010718, 0xDEAD, - 0x03B, 0x000EF7B0, - 0x03B, 0x000D4FB0, - 0x03B, 0x000CF060, - 0x03B, 0x000B0090, - 0x03B, 0x000A0080, - 0x03B, 0x00090080, - 0x03B, 0x0008F780, - 0xFF010718, 0xABCD, - 0x03B, 0x000787B0, - 0xCDCDCDCD, 0xCDCD, - 0x03B, 0x00078730, - 0xFF010718, 0xDEAD, - 0x03B, 0x00060FB0, - 0x03B, 0x0005FFA0, - 0x03B, 0x00040620, - 0x03B, 0x00037090, - 0x03B, 0x00020080, - 0x03B, 0x0001F060, - 0x03B, 0x0000FFB0, - 0x0EF, 0x000000A0, - 0x0FE, 0x00000000, - 0x018, 0x0000FC07, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x01E, 0x00000001, - 0x01F, 0x00080000, - 0x000, 0x00033E70, -}; - -u32 RTL8192EE_RADIOB_ARRAY[] = { - 0x07F, 0x00000082, - 0x081, 0x0003FC00, - 0x000, 0x00030000, - 0x008, 0x00008400, - 0x018, 0x00000407, - 0x019, 0x00000012, - 0x01B, 0x00000064, - 0x01E, 0x00080009, - 0x01F, 0x00000880, - 0x02F, 0x0001A060, - 0x03F, 0x00000000, - 0x042, 0x000060C0, - 0x057, 0x000D0000, - 0x058, 0x000BE180, - 0x067, 0x00001552, - 0x07F, 0x00000082, - 0x081, 0x0003F000, - 0x083, 0x00000000, - 0x0DF, 0x00000180, - 0x0EF, 0x000001A0, - 0x051, 0x00069545, - 0x052, 0x0007E42E, - 0x053, 0x00000071, - 0x056, 0x00051FF3, - 0x035, 0x000000A8, - 0x035, 0x000001E0, - 0x035, 0x000002A8, - 0x036, 0x00001CA8, - 0x036, 0x00009C24, - 0x036, 0x00011C24, - 0x036, 0x00019C24, - 0x018, 0x00000C07, - 0x05A, 0x00048000, - 0x019, 0x000739D0, - 0xFF010718, 0xABCD, - 0x034, 0x0000A093, - 0x034, 0x0000908F, - 0x034, 0x0000808C, - 0x034, 0x0000704D, - 0x034, 0x0000604A, - 0x034, 0x00005047, - 0x034, 0x0000400A, - 0x034, 0x00003007, - 0x034, 0x00002004, - 0x034, 0x00001001, - 0x034, 0x00000000, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0000ADD7, - 0x034, 0x00009DD4, - 0x034, 0x00008DD1, - 0x034, 0x00007DCE, - 0x034, 0x00006DCB, - 0x034, 0x00005DC8, - 0x034, 0x00004DC5, - 0x034, 0x000034CC, - 0x034, 0x0000244F, - 0x034, 0x0000144C, - 0x034, 0x00000014, - 0xFF010718, 0xDEAD, - 0x000, 0x00030159, - 0x084, 0x00068180, - 0x086, 0x000000CE, - 0x087, 0x00048A00, - 0x08E, 0x00065540, - 0x08F, 0x00088000, - 0x0EF, 0x000020A0, - 0xFF010718, 0xABCD, - 0x03B, 0x000F07B0, - 0xCDCDCDCD, 0xCDCD, - 0x03B, 0x000F02B0, - 0xFF010718, 0xDEAD, - 0x03B, 0x000EF7B0, - 0x03B, 0x000D4FB0, - 0x03B, 0x000CF060, - 0x03B, 0x000B0090, - 0x03B, 0x000A0080, - 0x03B, 0x00090080, - 0x03B, 0x0008F780, - 0xFF010718, 0xABCD, - 0x03B, 0x000787B0, - 0xCDCDCDCD, 0xCDCD, - 0x03B, 0x00078730, - 0xFF010718, 0xDEAD, - 0x03B, 0x00060FB0, - 0x03B, 0x0005FFA0, - 0x03B, 0x00040620, - 0x03B, 0x00037090, - 0x03B, 0x00020080, - 0x03B, 0x0001F060, - 0x03B, 0x0000FFB0, - 0x0EF, 0x000000A0, - 0x000, 0x00010159, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x01E, 0x00000001, - 0x01F, 0x00080000, - 0x000, 0x00033E70, -}; - -u32 RTL8192EE_MAC_ARRAY[] = { - 0x011, 0x000000EB, - 0x012, 0x00000007, - 0x014, 0x00000075, - 0x303, 0x000000A7, - 0x428, 0x0000000A, - 0x429, 0x00000010, - 0x430, 0x00000000, - 0x431, 0x00000000, - 0x432, 0x00000000, - 0x433, 0x00000001, - 0x434, 0x00000004, - 0x435, 0x00000005, - 0x436, 0x00000007, - 0x437, 0x00000008, - 0x43C, 0x00000004, - 0x43D, 0x00000005, - 0x43E, 0x00000007, - 0x43F, 0x00000008, - 0x440, 0x0000005D, - 0x441, 0x00000001, - 0x442, 0x00000000, - 0x444, 0x00000010, - 0x445, 0x00000000, - 0x446, 0x00000000, - 0x447, 0x00000000, - 0x448, 0x00000000, - 0x449, 0x000000F0, - 0x44A, 0x0000000F, - 0x44B, 0x0000003E, - 0x44C, 0x00000010, - 0x44D, 0x00000000, - 0x44E, 0x00000000, - 0x44F, 0x00000000, - 0x450, 0x00000000, - 0x451, 0x000000F0, - 0x452, 0x0000000F, - 0x453, 0x00000000, - 0x456, 0x0000005E, - 0x460, 0x00000066, - 0x461, 0x00000066, - 0x4C8, 0x000000FF, - 0x4C9, 0x00000008, - 0x4CC, 0x000000FF, - 0x4CD, 0x000000FF, - 0x4CE, 0x00000001, - 0x500, 0x00000026, - 0x501, 0x000000A2, - 0x502, 0x0000002F, - 0x503, 0x00000000, - 0x504, 0x00000028, - 0x505, 0x000000A3, - 0x506, 0x0000005E, - 0x507, 0x00000000, - 0x508, 0x0000002B, - 0x509, 0x000000A4, - 0x50A, 0x0000005E, - 0x50B, 0x00000000, - 0x50C, 0x0000004F, - 0x50D, 0x000000A4, - 0x50E, 0x00000000, - 0x50F, 0x00000000, - 0x512, 0x0000001C, - 0x514, 0x0000000A, - 0x516, 0x0000000A, - 0x525, 0x0000004F, - 0x540, 0x00000012, - 0x541, 0x00000064, - 0x550, 0x00000010, - 0x551, 0x00000010, - 0x559, 0x00000002, - 0x55C, 0x00000050, - 0x55D, 0x000000FF, - 0x605, 0x00000030, - 0x608, 0x0000000E, - 0x609, 0x0000002A, - 0x620, 0x000000FF, - 0x621, 0x000000FF, - 0x622, 0x000000FF, - 0x623, 0x000000FF, - 0x624, 0x000000FF, - 0x625, 0x000000FF, - 0x626, 0x000000FF, - 0x627, 0x000000FF, - 0x638, 0x00000050, - 0x63C, 0x0000000A, - 0x63D, 0x0000000A, - 0x63E, 0x0000000E, - 0x63F, 0x0000000E, - 0x640, 0x00000040, - 0x642, 0x00000040, - 0x643, 0x00000000, - 0x652, 0x000000C8, - 0x66E, 0x00000005, - 0x700, 0x00000021, - 0x701, 0x00000043, - 0x702, 0x00000065, - 0x703, 0x00000087, - 0x708, 0x00000021, - 0x709, 0x00000043, - 0x70A, 0x00000065, - 0x70B, 0x00000087, -}; - -u32 RTL8192EE_AGC_TAB_ARRAY[] = { - 0xFF010718, 0xABCD, - 0xC78, 0xFA000001, - 0xC78, 0xF9010001, - 0xC78, 0xF8020001, - 0xC78, 0xF7030001, - 0xC78, 0xF6040001, - 0xC78, 0xF5050001, - 0xC78, 0xF4060001, - 0xC78, 0xF3070001, - 0xC78, 0xF2080001, - 0xC78, 0xF1090001, - 0xC78, 0xF00A0001, - 0xC78, 0xEF0B0001, - 0xC78, 0xEE0C0001, - 0xC78, 0xED0D0001, - 0xC78, 0xEC0E0001, - 0xC78, 0xEB0F0001, - 0xC78, 0xEA100001, - 0xC78, 0xE9110001, - 0xC78, 0xE8120001, - 0xC78, 0xE7130001, - 0xC78, 0xE6140001, - 0xC78, 0xE5150001, - 0xC78, 0xE4160001, - 0xC78, 0xE3170001, - 0xC78, 0xE2180001, - 0xC78, 0xE1190001, - 0xC78, 0x8A1A0001, - 0xC78, 0x891B0001, - 0xC78, 0x881C0001, - 0xC78, 0x871D0001, - 0xC78, 0x861E0001, - 0xC78, 0x851F0001, - 0xC78, 0x84200001, - 0xC78, 0x83210001, - 0xC78, 0x82220001, - 0xC78, 0x6A230001, - 0xC78, 0x69240001, - 0xC78, 0x68250001, - 0xC78, 0x67260001, - 0xC78, 0x66270001, - 0xC78, 0x65280001, - 0xC78, 0x64290001, - 0xC78, 0x632A0001, - 0xC78, 0x622B0001, - 0xC78, 0x612C0001, - 0xC78, 0x602D0001, - 0xC78, 0x472E0001, - 0xC78, 0x462F0001, - 0xC78, 0x45300001, - 0xC78, 0x44310001, - 0xC78, 0x43320001, - 0xC78, 0x42330001, - 0xC78, 0x41340001, - 0xC78, 0x40350001, - 0xC78, 0x40360001, - 0xC78, 0x40370001, - 0xC78, 0x40380001, - 0xC78, 0x40390001, - 0xC78, 0x403A0001, - 0xC78, 0x403B0001, - 0xC78, 0x403C0001, - 0xC78, 0x403D0001, - 0xC78, 0x403E0001, - 0xC78, 0x403F0001, - 0xCDCDCDCD, 0xCDCD, - 0xC78, 0xFB000001, - 0xC78, 0xFB010001, - 0xC78, 0xFB020001, - 0xC78, 0xFB030001, - 0xC78, 0xFB040001, - 0xC78, 0xFB050001, - 0xC78, 0xFA060001, - 0xC78, 0xF9070001, - 0xC78, 0xF8080001, - 0xC78, 0xF7090001, - 0xC78, 0xF60A0001, - 0xC78, 0xF50B0001, - 0xC78, 0xF40C0001, - 0xC78, 0xF30D0001, - 0xC78, 0xF20E0001, - 0xC78, 0xF10F0001, - 0xC78, 0xF0100001, - 0xC78, 0xEF110001, - 0xC78, 0xEE120001, - 0xC78, 0xED130001, - 0xC78, 0xEC140001, - 0xC78, 0xEB150001, - 0xC78, 0xEA160001, - 0xC78, 0xE9170001, - 0xC78, 0xE8180001, - 0xC78, 0xE7190001, - 0xC78, 0xC81A0001, - 0xC78, 0xC71B0001, - 0xC78, 0xC61C0001, - 0xC78, 0x071D0001, - 0xC78, 0x061E0001, - 0xC78, 0x051F0001, - 0xC78, 0x04200001, - 0xC78, 0x03210001, - 0xC78, 0xAA220001, - 0xC78, 0xA9230001, - 0xC78, 0xA8240001, - 0xC78, 0xA7250001, - 0xC78, 0xA6260001, - 0xC78, 0x85270001, - 0xC78, 0x84280001, - 0xC78, 0x83290001, - 0xC78, 0x252A0001, - 0xC78, 0x242B0001, - 0xC78, 0x232C0001, - 0xC78, 0x222D0001, - 0xC78, 0x672E0001, - 0xC78, 0x662F0001, - 0xC78, 0x65300001, - 0xC78, 0x64310001, - 0xC78, 0x63320001, - 0xC78, 0x62330001, - 0xC78, 0x61340001, - 0xC78, 0x45350001, - 0xC78, 0x44360001, - 0xC78, 0x43370001, - 0xC78, 0x42380001, - 0xC78, 0x41390001, - 0xC78, 0x403A0001, - 0xC78, 0x403B0001, - 0xC78, 0x403C0001, - 0xC78, 0x403D0001, - 0xC78, 0x403E0001, - 0xC78, 0x403F0001, - 0xFF010718, 0xDEAD, - 0xFF010718, 0xABCD, - 0xC78, 0xFA400001, - 0xC78, 0xF9410001, - 0xC78, 0xF8420001, - 0xC78, 0xF7430001, - 0xC78, 0xF6440001, - 0xC78, 0xF5450001, - 0xC78, 0xF4460001, - 0xC78, 0xF3470001, - 0xC78, 0xF2480001, - 0xC78, 0xF1490001, - 0xC78, 0xF04A0001, - 0xC78, 0xEF4B0001, - 0xC78, 0xEE4C0001, - 0xC78, 0xED4D0001, - 0xC78, 0xEC4E0001, - 0xC78, 0xEB4F0001, - 0xC78, 0xEA500001, - 0xC78, 0xE9510001, - 0xC78, 0xE8520001, - 0xC78, 0xE7530001, - 0xC78, 0xE6540001, - 0xC78, 0xE5550001, - 0xC78, 0xE4560001, - 0xC78, 0xE3570001, - 0xC78, 0xE2580001, - 0xC78, 0xE1590001, - 0xC78, 0x8A5A0001, - 0xC78, 0x895B0001, - 0xC78, 0x885C0001, - 0xC78, 0x875D0001, - 0xC78, 0x865E0001, - 0xC78, 0x855F0001, - 0xC78, 0x84600001, - 0xC78, 0x83610001, - 0xC78, 0x82620001, - 0xC78, 0x6A630001, - 0xC78, 0x69640001, - 0xC78, 0x68650001, - 0xC78, 0x67660001, - 0xC78, 0x66670001, - 0xC78, 0x65680001, - 0xC78, 0x64690001, - 0xC78, 0x636A0001, - 0xC78, 0x626B0001, - 0xC78, 0x616C0001, - 0xC78, 0x606D0001, - 0xC78, 0x476E0001, - 0xC78, 0x466F0001, - 0xC78, 0x45700001, - 0xC78, 0x44710001, - 0xC78, 0x43720001, - 0xC78, 0x42730001, - 0xC78, 0x41740001, - 0xC78, 0x40750001, - 0xC78, 0x40760001, - 0xC78, 0x40770001, - 0xC78, 0x40780001, - 0xC78, 0x40790001, - 0xC78, 0x407A0001, - 0xC78, 0x407B0001, - 0xC78, 0x407C0001, - 0xC78, 0x407D0001, - 0xC78, 0x407E0001, - 0xC78, 0x407F0001, - 0xC50, 0x00040222, - 0xC50, 0x00040220, - 0xCDCDCDCD, 0xCDCD, - 0xC78, 0xFB400001, - 0xC78, 0xFB410001, - 0xC78, 0xFB420001, - 0xC78, 0xFB430001, - 0xC78, 0xFB440001, - 0xC78, 0xFB450001, - 0xC78, 0xFA460001, - 0xC78, 0xF9470001, - 0xC78, 0xF8480001, - 0xC78, 0xF7490001, - 0xC78, 0xF64A0001, - 0xC78, 0xF54B0001, - 0xC78, 0xF44C0001, - 0xC78, 0xF34D0001, - 0xC78, 0xF24E0001, - 0xC78, 0xF14F0001, - 0xC78, 0xF0500001, - 0xC78, 0xEF510001, - 0xC78, 0xEE520001, - 0xC78, 0xED530001, - 0xC78, 0xEC540001, - 0xC78, 0xEB550001, - 0xC78, 0xEA560001, - 0xC78, 0xE9570001, - 0xC78, 0xE8580001, - 0xC78, 0xE7590001, - 0xC78, 0xE65A0001, - 0xC78, 0xE55B0001, - 0xC78, 0xE45C0001, - 0xC78, 0xE35D0001, - 0xC78, 0xE25E0001, - 0xC78, 0xE15F0001, - 0xC78, 0x8A600001, - 0xC78, 0x89610001, - 0xC78, 0x88620001, - 0xC78, 0x87630001, - 0xC78, 0x86640001, - 0xC78, 0x85650001, - 0xC78, 0x84660001, - 0xC78, 0x83670001, - 0xC78, 0x82680001, - 0xC78, 0x6B690001, - 0xC78, 0x6A6A0001, - 0xC78, 0x696B0001, - 0xC78, 0x686C0001, - 0xC78, 0x676D0001, - 0xC78, 0x666E0001, - 0xC78, 0x656F0001, - 0xC78, 0x64700001, - 0xC78, 0x63710001, - 0xC78, 0x62720001, - 0xC78, 0x61730001, - 0xC78, 0x49740001, - 0xC78, 0x48750001, - 0xC78, 0x47760001, - 0xC78, 0x46770001, - 0xC78, 0x45780001, - 0xC78, 0x44790001, - 0xC78, 0x437A0001, - 0xC78, 0x427B0001, - 0xC78, 0x417C0001, - 0xC78, 0x407D0001, - 0xC78, 0x407E0001, - 0xC78, 0x407F0001, - 0xC50, 0x00040022, - 0xC50, 0x00040020, - 0xFF010718, 0xDEAD, -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/table.h b/drivers/net/wireless/rtlwifi/rtl8192ee/table.h deleted file mode 100644 index bff9df88815d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/table.h +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92E_TABLE__H_ -#define __RTL92E_TABLE__H_ - -#include -#define RTL8192EE_PHY_REG_ARRAY_LEN 448 -extern u32 RTL8192EE_PHY_REG_ARRAY[]; -#define RTL8192EE_PHY_REG_ARRAY_PG_LEN 168 -extern u32 RTL8192EE_PHY_REG_ARRAY_PG[]; -#define RTL8192EE_RADIOA_ARRAY_LEN 238 -extern u32 RTL8192EE_RADIOA_ARRAY[]; -#define RTL8192EE_RADIOB_ARRAY_LEN 198 -extern u32 RTL8192EE_RADIOB_ARRAY[]; -#define RTL8192EE_MAC_ARRAY_LEN 202 -extern u32 RTL8192EE_MAC_ARRAY[]; -#define RTL8192EE_AGC_TAB_ARRAY_LEN 532 -extern u32 RTL8192EE_AGC_TAB_ARRAY[]; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c deleted file mode 100644 index d39ee67f6113..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.c +++ /dev/null @@ -1,1129 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../stats.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "trx.h" -#include "led.h" -#include "dm.h" -#include "fw.h" - -static u8 _rtl92ee_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) -{ - __le16 fc = rtl_get_fc(skb); - - if (unlikely(ieee80211_is_beacon(fc))) - return QSLT_BEACON; - if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) - return QSLT_MGNT; - - return skb->priority; -} - -static void _rtl92ee_query_rxphystatus(struct ieee80211_hw *hw, - struct rtl_stats *pstatus, u8 *pdesc, - struct rx_fwinfo *p_drvinfo, - bool bpacket_match_bssid, - bool bpacket_toself, - bool packet_beacon) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct phy_status_rpt *p_phystrpt = (struct phy_status_rpt *)p_drvinfo; - char rx_pwr_all = 0, rx_pwr[4]; - u8 rf_rx_num = 0, evm, pwdb_all; - u8 i, max_spatial_stream; - u32 rssi, total_rssi = 0; - bool is_cck = pstatus->is_cck; - u8 lan_idx, vga_idx; - - /* Record it for next packet processing */ - pstatus->packet_matchbssid = bpacket_match_bssid; - pstatus->packet_toself = bpacket_toself; - pstatus->packet_beacon = packet_beacon; - pstatus->rx_mimo_signalquality[0] = -1; - pstatus->rx_mimo_signalquality[1] = -1; - - if (is_cck) { - u8 cck_highpwr; - u8 cck_agc_rpt; - /* CCK Driver info Structure is not the same as OFDM packet. */ - cck_agc_rpt = p_phystrpt->cck_agc_rpt_ofdm_cfosho_a; - - /* (1)Hardware does not provide RSSI for CCK - * (2)PWDB, Average PWDB cacluated by - * hardware (for rate adaptive) - */ - cck_highpwr = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, - BIT(9)); - - lan_idx = ((cck_agc_rpt & 0xE0) >> 5); - vga_idx = (cck_agc_rpt & 0x1f); - switch (lan_idx) { - case 7: /*VGA_idx = 27~2*/ - if (vga_idx <= 27) - rx_pwr_all = -100 + 2 * (27 - vga_idx); - else - rx_pwr_all = -100; - break; - case 6: /*VGA_idx = 2~0*/ - rx_pwr_all = -48 + 2 * (2 - vga_idx); - break; - case 5: /*VGA_idx = 7~5*/ - rx_pwr_all = -42 + 2 * (7 - vga_idx); - break; - case 4: /*VGA_idx = 7~4*/ - rx_pwr_all = -36 + 2 * (7 - vga_idx); - break; - case 3: /*VGA_idx = 7~0*/ - rx_pwr_all = -24 + 2 * (7 - vga_idx); - break; - case 2: /*VGA_idx = 5~0*/ - if (cck_highpwr) - rx_pwr_all = -12 + 2 * (5 - vga_idx); - else - rx_pwr_all = -6 + 2 * (5 - vga_idx); - break; - case 1: - rx_pwr_all = 8 - 2 * vga_idx; - break; - case 0: - rx_pwr_all = 14 - 2 * vga_idx; - break; - default: - break; - } - rx_pwr_all += 16; - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - - if (!cck_highpwr) { - if (pwdb_all >= 80) - pwdb_all = ((pwdb_all - 80) << 1) + - ((pwdb_all - 80) >> 1) + 80; - else if ((pwdb_all <= 78) && (pwdb_all >= 20)) - pwdb_all += 3; - if (pwdb_all > 100) - pwdb_all = 100; - } - - pstatus->rx_pwdb_all = pwdb_all; - pstatus->bt_rx_rssi_percentage = pwdb_all; - pstatus->recvsignalpower = rx_pwr_all; - - /* (3) Get Signal Quality (EVM) */ - if (bpacket_match_bssid) { - u8 sq, sq_rpt; - - if (pstatus->rx_pwdb_all > 40) { - sq = 100; - } else { - sq_rpt = p_phystrpt->cck_sig_qual_ofdm_pwdb_all; - if (sq_rpt > 64) - sq = 0; - else if (sq_rpt < 20) - sq = 100; - else - sq = ((64 - sq_rpt) * 100) / 44; - } - - pstatus->signalquality = sq; - pstatus->rx_mimo_signalquality[0] = sq; - pstatus->rx_mimo_signalquality[1] = -1; - } - } else { - /* (1)Get RSSI for HT rate */ - for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { - /* we will judge RF RX path now. */ - if (rtlpriv->dm.rfpath_rxenable[i]) - rf_rx_num++; - - rx_pwr[i] = ((p_phystrpt->path_agc[i].gain & 0x3f) * 2) - - 110; - - pstatus->rx_pwr[i] = rx_pwr[i]; - /* Translate DBM to percentage. */ - rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); - total_rssi += rssi; - - pstatus->rx_mimo_signalstrength[i] = (u8)rssi; - } - - /* (2)PWDB, Average PWDB cacluated by - * hardware (for rate adaptive) - */ - rx_pwr_all = ((p_phystrpt->cck_sig_qual_ofdm_pwdb_all >> 1) - & 0x7f) - 110; - - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - pstatus->rx_pwdb_all = pwdb_all; - pstatus->bt_rx_rssi_percentage = pwdb_all; - pstatus->rxpower = rx_pwr_all; - pstatus->recvsignalpower = rx_pwr_all; - - /* (3)EVM of HT rate */ - if (pstatus->rate >= DESC_RATEMCS8 && - pstatus->rate <= DESC_RATEMCS15) - max_spatial_stream = 2; - else - max_spatial_stream = 1; - - for (i = 0; i < max_spatial_stream; i++) { - evm = rtl_evm_db_to_percentage( - p_phystrpt->stream_rxevm[i]); - - if (bpacket_match_bssid) { - /* Fill value in RFD, Get the first - * spatial stream only - */ - if (i == 0) - pstatus->signalquality = (u8)(evm & - 0xff); - pstatus->rx_mimo_signalquality[i] = (u8)(evm & - 0xff); - } - } - - if (bpacket_match_bssid) { - for (i = RF90_PATH_A; i <= RF90_PATH_B; i++) - rtl_priv(hw)->dm.cfo_tail[i] = - (int)p_phystrpt->path_cfotail[i]; - - if (rtl_priv(hw)->dm.packet_count == 0xffffffff) - rtl_priv(hw)->dm.packet_count = 0; - else - rtl_priv(hw)->dm.packet_count++; - } - } - - /* UI BSS List signal strength(in percentage), - * make it good looking, from 0~100. - */ - if (is_cck) - pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, - pwdb_all)); - else if (rf_rx_num != 0) - pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, - total_rssi /= rf_rx_num)); -} - -static void _rtl92ee_translate_rx_signal_stuff(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct rtl_stats *pstatus, - u8 *pdesc, - struct rx_fwinfo *p_drvinfo) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct ieee80211_hdr *hdr; - u8 *tmp_buf; - u8 *praddr; - u8 *psaddr; - __le16 fc; - bool packet_matchbssid, packet_toself, packet_beacon; - - tmp_buf = skb->data + pstatus->rx_drvinfo_size + - pstatus->rx_bufshift + 24; - - hdr = (struct ieee80211_hdr *)tmp_buf; - fc = hdr->frame_control; - praddr = hdr->addr1; - psaddr = ieee80211_get_SA(hdr); - ether_addr_copy(pstatus->psaddr, psaddr); - - packet_matchbssid = (!ieee80211_is_ctl(fc) && - (ether_addr_equal(mac->bssid, - ieee80211_has_tods(fc) ? - hdr->addr1 : - ieee80211_has_fromds(fc) ? - hdr->addr2 : hdr->addr3)) && - (!pstatus->hwerror) && (!pstatus->crc) && - (!pstatus->icv)); - - packet_toself = packet_matchbssid && - (ether_addr_equal(praddr, rtlefuse->dev_addr)); - - if (ieee80211_is_beacon(fc)) - packet_beacon = true; - else - packet_beacon = false; - - if (packet_beacon && packet_matchbssid) - rtl_priv(hw)->dm.dbginfo.num_qry_beacon_pkt++; - - if (packet_matchbssid && ieee80211_is_data_qos(hdr->frame_control) && - !is_multicast_ether_addr(ieee80211_get_DA(hdr))) { - struct ieee80211_qos_hdr *hdr_qos = - (struct ieee80211_qos_hdr *)tmp_buf; - u16 tid = le16_to_cpu(hdr_qos->qos_ctrl) & 0xf; - - if (tid != 0 && tid != 3) - rtl_priv(hw)->dm.dbginfo.num_non_be_pkt++; - } - - _rtl92ee_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo, - packet_matchbssid, packet_toself, - packet_beacon); - rtl_process_phyinfo(hw, tmp_buf, pstatus); -} - -static void _rtl92ee_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, - u8 *virtualaddress) -{ - u32 dwtmp = 0; - - memset(virtualaddress, 0, 8); - - SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); - if (ptcb_desc->empkt_num == 1) { - dwtmp = ptcb_desc->empkt_len[0]; - } else { - dwtmp = ptcb_desc->empkt_len[0]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; - dwtmp += ptcb_desc->empkt_len[1]; - } - SET_EARLYMODE_LEN0(virtualaddress, dwtmp); - - if (ptcb_desc->empkt_num <= 3) { - dwtmp = ptcb_desc->empkt_len[2]; - } else { - dwtmp = ptcb_desc->empkt_len[2]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; - dwtmp += ptcb_desc->empkt_len[3]; - } - SET_EARLYMODE_LEN1(virtualaddress, dwtmp); - if (ptcb_desc->empkt_num <= 5) { - dwtmp = ptcb_desc->empkt_len[4]; - } else { - dwtmp = ptcb_desc->empkt_len[4]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; - dwtmp += ptcb_desc->empkt_len[5]; - } - SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF); - SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4); - if (ptcb_desc->empkt_num <= 7) { - dwtmp = ptcb_desc->empkt_len[6]; - } else { - dwtmp = ptcb_desc->empkt_len[6]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; - dwtmp += ptcb_desc->empkt_len[7]; - } - SET_EARLYMODE_LEN3(virtualaddress, dwtmp); - if (ptcb_desc->empkt_num <= 9) { - dwtmp = ptcb_desc->empkt_len[8]; - } else { - dwtmp = ptcb_desc->empkt_len[8]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; - dwtmp += ptcb_desc->empkt_len[9]; - } - SET_EARLYMODE_LEN4(virtualaddress, dwtmp); -} - -bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *status, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rx_fwinfo *p_drvinfo; - struct ieee80211_hdr *hdr; - u32 phystatus = GET_RX_DESC_PHYST(pdesc); - - if (GET_RX_STATUS_DESC_RPT_SEL(pdesc) == 0) - status->packet_report_type = NORMAL_RX; - else - status->packet_report_type = C2H_PACKET; - status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); - status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * - RX_DRV_INFO_SIZE_UNIT; - status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03); - status->icv = (u16)GET_RX_DESC_ICV(pdesc); - status->crc = (u16)GET_RX_DESC_CRC32(pdesc); - status->hwerror = (status->crc | status->icv); - status->decrypted = !GET_RX_DESC_SWDEC(pdesc); - status->rate = (u8)GET_RX_DESC_RXMCS(pdesc); - status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); - status->timestamp_low = GET_RX_DESC_TSFL(pdesc); - status->is_cck = RTL92EE_RX_HAL_IS_CCK_RATE(status->rate); - - status->macid = GET_RX_DESC_MACID(pdesc); - if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(2); - else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(1); - else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) - status->wake_match = BIT(0); - else - status->wake_match = 0; - if (status->wake_match) - RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, - "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n", - status->wake_match); - rx_status->freq = hw->conf.chandef.chan->center_freq; - rx_status->band = hw->conf.chandef.chan->band; - - hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size + - status->rx_bufshift + 24); - - if (status->crc) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - - if (status->rx_is40Mhzpacket) - rx_status->flag |= RX_FLAG_40MHZ; - - if (status->is_ht) - rx_status->flag |= RX_FLAG_HT; - - rx_status->flag |= RX_FLAG_MACTIME_START; - - /* hw will set status->decrypted true, if it finds the - * frame is open data frame or mgmt frame. - * So hw will not decryption robust managment frame - * for IEEE80211w but still set status->decrypted - * true, so here we should set it back to undecrypted - * for IEEE80211w frame, and mac80211 sw will help - * to decrypt it - */ - if (status->decrypted) { - if ((!_ieee80211_is_robust_mgmt_frame(hdr)) && - (ieee80211_has_protected(hdr->frame_control))) - rx_status->flag |= RX_FLAG_DECRYPTED; - else - rx_status->flag &= ~RX_FLAG_DECRYPTED; - } - - /* rate_idx: index of data rate into band's - * supported rates or MCS index if HT rates - * are use (RX_FLAG_HT) - * Notice: this is diff with windows define - */ - rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht, - false, status->rate); - - rx_status->mactime = status->timestamp_low; - if (phystatus) { - p_drvinfo = (struct rx_fwinfo *)(skb->data + - status->rx_bufshift + 24); - - _rtl92ee_translate_rx_signal_stuff(hw, skb, status, pdesc, - p_drvinfo); - } - rx_status->signal = status->recvsignalpower + 10; - if (status->packet_report_type == TX_REPORT2) { - status->macid_valid_entry[0] = - GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); - status->macid_valid_entry[1] = - GET_RX_RPT2_DESC_MACID_VALID_2(pdesc); - } - return true; -} - -/*in Windows, this == Rx_92EE_Interrupt*/ -void rtl92ee_rx_check_dma_ok(struct ieee80211_hw *hw, u8 *header_desc, - u8 queue_index) -{ - u8 first_seg = 0; - u8 last_seg = 0; - u16 total_len = 0; - u16 read_cnt = 0; - - if (header_desc == NULL) - return; - - total_len = (u16)GET_RX_BUFFER_DESC_TOTAL_LENGTH(header_desc); - - first_seg = (u8)GET_RX_BUFFER_DESC_FS(header_desc); - - last_seg = (u8)GET_RX_BUFFER_DESC_LS(header_desc); - - while (total_len == 0 && first_seg == 0 && last_seg == 0) { - read_cnt++; - total_len = (u16)GET_RX_BUFFER_DESC_TOTAL_LENGTH(header_desc); - first_seg = (u8)GET_RX_BUFFER_DESC_FS(header_desc); - last_seg = (u8)GET_RX_BUFFER_DESC_LS(header_desc); - - if (read_cnt > 20) - break; - } -} - -u16 rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, u8 queue_index) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 read_point = 0, write_point = 0, remind_cnt = 0; - u32 tmp_4byte = 0; - static u16 last_read_point; - static bool start_rx; - - tmp_4byte = rtl_read_dword(rtlpriv, REG_RXQ_TXBD_IDX); - read_point = (u16)((tmp_4byte>>16) & 0x7ff); - write_point = (u16)(tmp_4byte & 0x7ff); - - if (write_point != rtlpci->rx_ring[queue_index].next_rx_rp) { - RT_TRACE(rtlpriv, COMP_RXDESC, DBG_DMESG, - "!!!write point is 0x%x, reg 0x3B4 value is 0x%x\n", - write_point, tmp_4byte); - tmp_4byte = rtl_read_dword(rtlpriv, REG_RXQ_TXBD_IDX); - read_point = (u16)((tmp_4byte>>16) & 0x7ff); - write_point = (u16)(tmp_4byte & 0x7ff); - } - - if (read_point > 0) - start_rx = true; - if (!start_rx) - return 0; - - remind_cnt = calc_fifo_space(read_point, write_point); - - if (remind_cnt == 0) - return 0; - - rtlpci->rx_ring[queue_index].next_rx_rp = write_point; - - last_read_point = read_point; - return remind_cnt; -} - -static u16 get_desc_addr_fr_q_idx(u16 queue_index) -{ - u16 desc_address = REG_BEQ_TXBD_IDX; - - switch (queue_index) { - case BK_QUEUE: - desc_address = REG_BKQ_TXBD_IDX; - break; - case BE_QUEUE: - desc_address = REG_BEQ_TXBD_IDX; - break; - case VI_QUEUE: - desc_address = REG_VIQ_TXBD_IDX; - break; - case VO_QUEUE: - desc_address = REG_VOQ_TXBD_IDX; - break; - case BEACON_QUEUE: - desc_address = REG_BEQ_TXBD_IDX; - break; - case TXCMD_QUEUE: - desc_address = REG_BEQ_TXBD_IDX; - break; - case MGNT_QUEUE: - desc_address = REG_MGQ_TXBD_IDX; - break; - case HIGH_QUEUE: - desc_address = REG_HI0Q_TXBD_IDX; - break; - case HCCA_QUEUE: - desc_address = REG_BEQ_TXBD_IDX; - break; - default: - break; - } - return desc_address; -} - -u16 rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 q_idx) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 point_diff = 0; - u16 current_tx_read_point = 0, current_tx_write_point = 0; - u32 tmp_4byte; - - tmp_4byte = rtl_read_dword(rtlpriv, - get_desc_addr_fr_q_idx(q_idx)); - current_tx_read_point = (u16)((tmp_4byte >> 16) & 0x0fff); - current_tx_write_point = (u16)((tmp_4byte) & 0x0fff); - - point_diff = calc_fifo_space(current_tx_read_point, - current_tx_write_point); - - rtlpci->tx_ring[q_idx].avl_desc = point_diff; - return point_diff; -} - -void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, - u8 *tx_bd_desc, u8 *desc, u8 queue_index, - struct sk_buff *skb, dma_addr_t addr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u32 pkt_len = skb->len; - u16 desc_size = 40; /*tx desc size*/ - u32 psblen = 0; - u16 tx_page_size = 0; - u32 total_packet_size = 0; - u16 current_bd_desc; - u8 i = 0; - u16 real_desc_size = 0x28; - u16 append_early_mode_size = 0; -#if (RTL8192EE_SEG_NUM == 0) - u8 segmentnum = 2; -#elif (RTL8192EE_SEG_NUM == 1) - u8 segmentnum = 4; -#elif (RTL8192EE_SEG_NUM == 2) - u8 segmentnum = 8; -#endif - - tx_page_size = 2; - current_bd_desc = rtlpci->tx_ring[queue_index].cur_tx_wp; - - total_packet_size = desc_size+pkt_len; - - if (rtlpriv->rtlhal.earlymode_enable) { - if (queue_index < BEACON_QUEUE) { - append_early_mode_size = 8; - total_packet_size += append_early_mode_size; - } - } - - if (tx_page_size > 0) { - psblen = (pkt_len + real_desc_size + append_early_mode_size) / - (tx_page_size * 128); - - if (psblen * (tx_page_size * 128) < total_packet_size) - psblen += 1; - } - - /* Reset */ - SET_TX_BUFF_DESC_LEN_0(tx_bd_desc, 0); - SET_TX_BUFF_DESC_PSB(tx_bd_desc, 0); - SET_TX_BUFF_DESC_OWN(tx_bd_desc, 0); - - for (i = 1; i < segmentnum; i++) { - SET_TXBUFFER_DESC_LEN_WITH_OFFSET(tx_bd_desc, i, 0); - SET_TXBUFFER_DESC_AMSDU_WITH_OFFSET(tx_bd_desc, i, 0); - SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(tx_bd_desc, i, 0); -#if (DMA_IS_64BIT == 1) - SET_TXBUFFER_DESC_ADD_HIGT_WITH_OFFSET(tx_bd_desc, i, 0); -#endif - } - SET_TX_BUFF_DESC_LEN_1(tx_bd_desc, 0); - SET_TX_BUFF_DESC_AMSDU_1(tx_bd_desc, 0); - - SET_TX_BUFF_DESC_LEN_2(tx_bd_desc, 0); - SET_TX_BUFF_DESC_AMSDU_2(tx_bd_desc, 0); - SET_TX_BUFF_DESC_LEN_3(tx_bd_desc, 0); - SET_TX_BUFF_DESC_AMSDU_3(tx_bd_desc, 0); - /* Clear all status */ - CLEAR_PCI_TX_DESC_CONTENT(desc, TX_DESC_SIZE); - - if (rtlpriv->rtlhal.earlymode_enable) { - if (queue_index < BEACON_QUEUE) { - /* This if needs braces */ - SET_TX_BUFF_DESC_LEN_0(tx_bd_desc, desc_size + 8); - } else { - SET_TX_BUFF_DESC_LEN_0(tx_bd_desc, desc_size); - } - } else { - SET_TX_BUFF_DESC_LEN_0(tx_bd_desc, desc_size); - } - SET_TX_BUFF_DESC_PSB(tx_bd_desc, psblen); - SET_TX_BUFF_DESC_ADDR_LOW_0(tx_bd_desc, - rtlpci->tx_ring[queue_index].dma + - (current_bd_desc * TX_DESC_SIZE)); - - SET_TXBUFFER_DESC_LEN_WITH_OFFSET(tx_bd_desc, 1, pkt_len); - /* don't using extendsion mode. */ - SET_TXBUFFER_DESC_AMSDU_WITH_OFFSET(tx_bd_desc, 1, 0); - SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(tx_bd_desc, 1, addr); - - SET_TX_DESC_PKT_SIZE(desc, (u16)(pkt_len)); - SET_TX_DESC_TX_BUFFER_SIZE(desc, (u16)(pkt_len)); -} - -void rtl92ee_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *pbd_desc_tx, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 *pdesc = (u8 *)pdesc_tx; - u16 seq_number; - __le16 fc = hdr->frame_control; - unsigned int buf_len = 0; - u8 fw_qsel = _rtl92ee_map_hwqueue_to_fwqueue(skb, hw_queue); - bool firstseg = ((hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); - bool lastseg = ((hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); - dma_addr_t mapping; - u8 bw_40 = 0; - u8 short_gi = 0; - - if (mac->opmode == NL80211_IFTYPE_STATION) { - bw_40 = mac->bw_40; - } else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - if (sta) - bw_40 = sta->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40; - } - seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); - /* reserve 8 byte for AMPDU early mode */ - if (rtlhal->earlymode_enable) { - skb_push(skb, EM_HDR_LEN); - memset(skb->data, 0, EM_HDR_LEN); - } - buf_len = skb->len; - mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - - if (pbd_desc_tx != NULL) - rtl92ee_pre_fill_tx_bd_desc(hw, pbd_desc_tx, pdesc, hw_queue, - skb, mapping); - - if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { - firstseg = true; - lastseg = true; - } - if (firstseg) { - if (rtlhal->earlymode_enable) { - SET_TX_DESC_PKT_OFFSET(pdesc, 1); - SET_TX_DESC_OFFSET(pdesc, - USB_HWDESC_HEADER_LEN + EM_HDR_LEN); - if (ptcb_desc->empkt_num) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "Insert 8 byte.pTcb->EMPktNum:%d\n", - ptcb_desc->empkt_num); - _rtl92ee_insert_emcontent(ptcb_desc, - (u8 *)(skb->data)); - } - } else { - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - } - - SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); - - if (ieee80211_is_mgmt(fc)) { - ptcb_desc->use_driver_rate = true; - } else { - if (rtlpriv->ra.is_special_data) { - ptcb_desc->use_driver_rate = true; - SET_TX_DESC_TX_RATE(pdesc, DESC_RATE11M); - } else { - ptcb_desc->use_driver_rate = false; - } - } - - if (ptcb_desc->hw_rate > DESC_RATEMCS0) - short_gi = (ptcb_desc->use_shortgi) ? 1 : 0; - else - short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0; - - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - SET_TX_DESC_AGG_ENABLE(pdesc, 1); - SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); - } - SET_TX_DESC_SEQ(pdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(pdesc, - ((ptcb_desc->rts_enable && - !ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(pdesc, 0); - SET_TX_DESC_CTS2SELF(pdesc, - ((ptcb_desc->cts_enable) ? 1 : 0)); - - SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); - SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(pdesc, - ((ptcb_desc->rts_rate <= DESC_RATE54M) ? - (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : - (ptcb_desc->rts_use_shortgi ? 1 : 0))); - - if (ptcb_desc->tx_enable_sw_calc_duration) - SET_TX_DESC_NAV_USE_HDR(pdesc, 1); - - if (bw_40) { - if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { - SET_TX_DESC_DATA_BW(pdesc, 1); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, - mac->cur_40_prime_sc); - } - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); - } - - SET_TX_DESC_LINIP(pdesc, 0); - if (sta) { - u8 ampdu_density = sta->ht_cap.ampdu_density; - - SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); - } - if (info->control.hw_key) { - struct ieee80211_key_conf *key = info->control.hw_key; - - switch (key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - case WLAN_CIPHER_SUITE_TKIP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x1); - break; - case WLAN_CIPHER_SUITE_CCMP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x3); - break; - default: - SET_TX_DESC_SEC_TYPE(pdesc, 0x0); - break; - } - } - - SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); - SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); - SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); - SET_TX_DESC_DISABLE_FB(pdesc, - ptcb_desc->disable_ratefallback ? 1 : 0); - SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); - - /*SET_TX_DESC_PWR_STATUS(pdesc, pwr_status);*/ - /* Set TxRate and RTSRate in TxDesc */ - /* This prevent Tx initial rate of new-coming packets */ - /* from being overwritten by retried packet rate.*/ - if (!ptcb_desc->use_driver_rate) { - /*SET_TX_DESC_RTS_RATE(pdesc, 0x08); */ - /* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */ - } - if (ieee80211_is_data_qos(fc)) { - if (mac->rdg_en) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "Enable RDG function.\n"); - SET_TX_DESC_RDG_ENABLE(pdesc, 1); - SET_TX_DESC_HTC(pdesc, 1); - } - } - } - - SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); - SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); - } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); - } - - SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); - if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || - is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { - SET_TX_DESC_BMC(pdesc, 1); - } - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); -} - -void rtl92ee_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc, bool firstseg, - bool lastseg, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 fw_queue = QSLT_BEACON; - dma_addr_t mapping = pci_map_single(rtlpci->pdev, - skb->data, skb->len, - PCI_DMA_TODEVICE); - u8 txdesc_len = 40; - - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, txdesc_len); - - if (firstseg) - SET_TX_DESC_OFFSET(pdesc, txdesc_len); - - SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M); - - SET_TX_DESC_SEQ(pdesc, 0); - - SET_TX_DESC_LINIP(pdesc, 0); - - SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); - - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); - - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - SET_TX_DESC_RATE_ID(pdesc, 7); - SET_TX_DESC_MACID(pdesc, 0); - - SET_TX_DESC_OWN(pdesc, 1); - - SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len)); - - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - SET_TX_DESC_OFFSET(pdesc, 40); - - SET_TX_DESC_USE_RATE(pdesc, 1); - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C Tx Cmd Content\n", pdesc, txdesc_len); -} - -void rtl92ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, - u8 desc_name, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 cur_tx_rp = 0; - u16 cur_tx_wp = 0; - static u16 last_txw_point; - static bool over_run; - u32 tmp = 0; - u8 q_idx = *val; - - if (istx) { - switch (desc_name) { - case HW_DESC_TX_NEXTDESC_ADDR: - SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *)val); - break; - case HW_DESC_OWN:{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[q_idx]; - u16 max_tx_desc = ring->entries; - - if (q_idx == BEACON_QUEUE) { - ring->cur_tx_wp = 0; - ring->cur_tx_rp = 0; - SET_TX_BUFF_DESC_OWN(pdesc, 1); - return; - } - - ring->cur_tx_wp = ((ring->cur_tx_wp + 1) % max_tx_desc); - - if (over_run) { - ring->cur_tx_wp = 0; - over_run = false; - } - if (ring->avl_desc > 1) { - ring->avl_desc--; - - rtl_write_word(rtlpriv, - get_desc_addr_fr_q_idx(q_idx), - ring->cur_tx_wp); - - if (q_idx == 1) - last_txw_point = cur_tx_wp; - } - - if (ring->avl_desc < (max_tx_desc - 15)) { - u16 point_diff = 0; - - tmp = - rtl_read_dword(rtlpriv, - get_desc_addr_fr_q_idx(q_idx)); - cur_tx_rp = (u16)((tmp >> 16) & 0x0fff); - cur_tx_wp = (u16)(tmp & 0x0fff); - - ring->cur_tx_wp = cur_tx_wp; - ring->cur_tx_rp = cur_tx_rp; - point_diff = ((cur_tx_rp > cur_tx_wp) ? - (cur_tx_rp - cur_tx_wp) : - (TX_DESC_NUM_92E - 1 - - cur_tx_wp + cur_tx_rp)); - - ring->avl_desc = point_diff; - } - } - break; - } - } else { - switch (desc_name) { - case HW_DESC_RX_PREPARE: - SET_RX_BUFFER_DESC_LS(pdesc, 0); - SET_RX_BUFFER_DESC_FS(pdesc, 0); - SET_RX_BUFFER_DESC_TOTAL_LENGTH(pdesc, 0); - - SET_RX_BUFFER_DESC_DATA_LENGTH(pdesc, - MAX_RECEIVE_BUFFER_SIZE + - RX_DESC_SIZE); - - SET_RX_BUFFER_PHYSICAL_LOW(pdesc, *(u32 *)val); - break; - case HW_DESC_RXERO: - SET_RX_DESC_EOR(pdesc, 1); - break; - default: - RT_ASSERT(false, - "ERR rxdesc :%d not process\n", desc_name); - break; - } - } -} - -u32 rtl92ee_get_desc(u8 *pdesc, bool istx, u8 desc_name) -{ - u32 ret = 0; - - if (istx) { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_TX_DESC_OWN(pdesc); - break; - case HW_DESC_TXBUFF_ADDR: - ret = GET_TXBUFFER_DESC_ADDR_LOW(pdesc, 1); - break; - default: - RT_ASSERT(false, - "ERR txdesc :%d not process\n", desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_RX_DESC_OWN(pdesc); - break; - case HW_DESC_RXPKT_LEN: - ret = GET_RX_DESC_PKT_LEN(pdesc); - break; - case HW_DESC_RXBUFF_ADDR: - ret = GET_RX_DESC_BUFF_ADDR(pdesc); - break; - default: - RT_ASSERT(false, - "ERR rxdesc :%d not process\n", desc_name); - break; - } - } - return ret; -} - -bool rtl92ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 read_point, write_point, available_desc_num; - bool ret = false; - static u8 stop_report_cnt; - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; - - { - u16 point_diff = 0; - u16 cur_tx_rp, cur_tx_wp; - u32 tmpu32 = 0; - - tmpu32 = - rtl_read_dword(rtlpriv, - get_desc_addr_fr_q_idx(hw_queue)); - cur_tx_rp = (u16)((tmpu32 >> 16) & 0x0fff); - cur_tx_wp = (u16)(tmpu32 & 0x0fff); - - ring->cur_tx_wp = cur_tx_wp; - ring->cur_tx_rp = cur_tx_rp; - point_diff = ((cur_tx_rp > cur_tx_wp) ? - (cur_tx_rp - cur_tx_wp) : - (TX_DESC_NUM_92E - cur_tx_wp + cur_tx_rp)); - - ring->avl_desc = point_diff; - } - - read_point = ring->cur_tx_rp; - write_point = ring->cur_tx_wp; - available_desc_num = ring->avl_desc; - - if (write_point > read_point) { - if (index < write_point && index >= read_point) - ret = false; - else - ret = true; - } else if (write_point < read_point) { - if (index > write_point && index < read_point) - ret = true; - else - ret = false; - } else { - if (index != read_point) - ret = true; - } - - if (hw_queue == BEACON_QUEUE) - ret = true; - - if (rtlpriv->rtlhal.driver_is_goingto_unload || - rtlpriv->psc.rfoff_reason > RF_CHANGE_BY_PS) - ret = true; - - if (hw_queue < BEACON_QUEUE) { - if (!ret) - stop_report_cnt++; - else - stop_report_cnt = 0; - } - - return ret; -} - -void rtl92ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) -{ -} - -u32 rtl92ee_rx_command_packet(struct ieee80211_hw *hw, - struct rtl_stats status, - struct sk_buff *skb) -{ - u32 result = 0; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - switch (status.packet_report_type) { - case NORMAL_RX: - result = 0; - break; - case C2H_PACKET: - rtl92ee_c2h_packet_handler(hw, skb->data, (u8)skb->len); - result = 1; - break; - default: - RT_TRACE(rtlpriv, COMP_RECV, DBG_TRACE, - "Unknown packet type %d\n", status.packet_report_type); - break; - } - - return result; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h deleted file mode 100644 index 8f78ac9e6040..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/trx.h +++ /dev/null @@ -1,862 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92E_TRX_H__ -#define __RTL92E_TRX_H__ - -#if (DMA_IS_64BIT == 1) -#if (RTL8192EE_SEG_NUM == 2) -#define TX_BD_DESC_SIZE 128 -#elif (RTL8192EE_SEG_NUM == 1) -#define TX_BD_DESC_SIZE 64 -#elif (RTL8192EE_SEG_NUM == 0) -#define TX_BD_DESC_SIZE 32 -#endif -#else -#if (RTL8192EE_SEG_NUM == 2) -#define TX_BD_DESC_SIZE 64 -#elif (RTL8192EE_SEG_NUM == 1) -#define TX_BD_DESC_SIZE 32 -#elif (RTL8192EE_SEG_NUM == 0) -#define TX_BD_DESC_SIZE 16 -#endif -#endif - -#define TX_DESC_SIZE 64 - -#define RX_DRV_INFO_SIZE_UNIT 8 - -#define TX_DESC_NEXT_DESC_OFFSET 40 -#define USB_HWDESC_HEADER_LEN 40 - -#define RX_DESC_SIZE 24 -#define MAX_RECEIVE_BUFFER_SIZE 8192 - -#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) -#define SET_TX_DESC_OFFSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) -#define SET_TX_DESC_BMC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) -#define SET_TX_DESC_HTC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) -#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) -#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) -#define SET_TX_DESC_LINIP(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) -#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) -#define SET_TX_DESC_GF(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) -#define SET_TX_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) - -#define GET_TX_DESC_PKT_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 0, 16) -#define GET_TX_DESC_OFFSET(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 16, 8) -#define GET_TX_DESC_BMC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 24, 1) -#define GET_TX_DESC_HTC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 25, 1) -#define GET_TX_DESC_LAST_SEG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 26, 1) -#define GET_TX_DESC_FIRST_SEG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 27, 1) -#define GET_TX_DESC_LINIP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 28, 1) -#define GET_TX_DESC_NO_ACM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 29, 1) -#define GET_TX_DESC_GF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 30, 1) -#define GET_TX_DESC_OWN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 31, 1) - -#define SET_TX_DESC_MACID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 7, __val) -#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) -#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) -#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) -#define SET_TX_DESC_PIFS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) -#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 5, __val) -#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) -#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) -#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 5, __val) -#define SET_TX_DESC_MORE_DATA(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 29, 1, __val) -#define SET_TX_DESC_TXOP_PS_CAP(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 30, 1, __val) -#define SET_TX_DESC_TXOP_PS_MODE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 31, 1, __val) - -#define GET_TX_DESC_MACID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) -#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 5, 1) -#define GET_TX_DESC_AGG_BREAK(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 6, 1) -#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 7, 1) -#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 8, 5) -#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) -#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) -#define GET_TX_DESC_PIFS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) -#define GET_TX_DESC_RATE_ID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) -#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) -#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) -#define GET_TX_DESC_SEC_TYPE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 22, 2) -#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 24, 5) - -#define SET_TX_DESC_PAID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 9, __val) -#define SET_TX_DESC_CCA_RTS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 10, 2, __val) -#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val) -#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val) -#define SET_TX_DESC_NULL_0(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 1, __val) -#define SET_TX_DESC_NULL_1(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 15, 1, __val) -#define SET_TX_DESC_BK(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val) -#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) -#define SET_TX_DESC_RAW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) -#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) -#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) -#define SET_TX_DESC_BT_NULL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val) -#define SET_TX_DESC_GID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 6, __val) - -#define SET_TX_DESC_WHEADER_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 4, __val) -#define SET_TX_DESC_CHK_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 4, 1, __val) -#define SET_TX_DESC_EARLY_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 5, 1, __val) -#define SET_TX_DESC_HWSEQ_SEL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 6, 2, __val) -#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 1, __val) -#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 9, 1, __val) -#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 10, 1, __val) -#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 11, 1, __val) -#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 12, 1, __val) -#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 13, 1, __val) -#define SET_TX_DESC_HW_PORT_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 14, 1, __val) -#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 15, 1, __val) -#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 1, __val) -#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 17, 5, __val) -#define SET_TX_DESC_NDPA(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 22, 2, __val) -#define SET_TX_DESC_AMPDU_MAX_TIME(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 24, 8, __val) - -/* Dword 4 */ -#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 7, __val) -#define SET_TX_DESC_TRY_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val) -#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 5, __val) -#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 4, __val) -#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 17, 1, __val) -#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 6, __val) -#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 5, __val) -#define SET_TX_DESC_PCTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 29, 1, __val) -#define SET_TX_DESC_PCTS_MASK_IDX(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val) - -/* Dword 5 */ -#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 4, __val) -#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 4, 1, __val) -#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 5, 2, __val) -#define SET_TX_DESC_DATA_LDPC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) -#define SET_TX_DESC_DATA_STBC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 2, __val) -#define SET_TX_DESC_VCS_STBC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 10, 2, __val) -#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 12, 1, __val) -#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) -#define SET_TX_DESC_TX_ANT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 4, __val) -#define SET_TX_DESC_TX_POWER_0_PSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 28, 3, __val) - -/* Dword 6 */ -#define SET_TX_DESC_SW_DEFINE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 12, __val) -#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 3, __val) -#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 19, 3, __val) -#define SET_TX_DESC_ANTSEL_C(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 22, 3, __val) -#define SET_TX_DESC_ANTSEL_D(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 25, 3, __val) - -/* Dword 7 */ -#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) -#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 8, __val) - -/* Dword 8 */ -#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 6, __val) -#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 6, 2, __val) -#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 8, 6, __val) -#define SET_TX_DESC_ENABLE_HW_SELECT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 15, 1, __val) -#define SET_TX_DESC_NEXT_HEAD_PAGE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 16, 8, __val) -#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 24, 8, __val) - -/* Dword 9 */ -#define SET_TX_DESC_PADDING_LENGTH(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 11, __val) -#define SET_TX_DESC_TXBF_PATH(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+36, 11, 1, __val) -#define SET_TX_DESC_SEQ(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+36, 12, 12, __val) -#define SET_TX_DESC_FINAL_DATA_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+36, 24, 8, __val) - -/* Dword 10 */ -#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) - -/* Dword 11*/ -#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+48, 0, 32, __val) - -#define SET_EARLYMODE_PKTNUM(__paddr, __val) \ - SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __val) -#define SET_EARLYMODE_LEN0(__paddr, __val) \ - SET_BITS_TO_LE_4BYTE(__paddr, 4, 15, __val) -#define SET_EARLYMODE_LEN1(__paddr, __val) \ - SET_BITS_TO_LE_4BYTE(__paddr, 16, 2, __val) -#define SET_EARLYMODE_LEN1_1(__paddr, __val) \ - SET_BITS_TO_LE_4BYTE(__paddr, 19, 13, __val) -#define SET_EARLYMODE_LEN1_2(__paddr, __val) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 2, __val) -#define SET_EARLYMODE_LEN2(__paddr, __val) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 2, 15, __val) -#define SET_EARLYMODE_LEN2_1(__paddr, __val) \ - SET_BITS_TO_LE_4BYTE(__paddr, 2, 4, __val) -#define SET_EARLYMODE_LEN2_2(__paddr, __val) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __val) -#define SET_EARLYMODE_LEN3(__paddr, __val) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 17, 15, __val) -#define SET_EARLYMODE_LEN4(__paddr, __val) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __val) - -/* TX/RX buffer descriptor */ - -#define SET_TX_EXTBUFF_DESC_LEN(__pdesc, __val, __set) \ - SET_BITS_TO_LE_4BYTE(__pdesc+(__set*16), 0, 16, __val) -#define SET_TX_EXTBUFF_DESC_ADDR_LOW(__pdesc, __val, __set)\ - SET_BITS_TO_LE_4BYTE(__pdesc+(__set*16)+4, 0, 32, __val) -#define SET_TX_EXTBUFF_DESC_ADDR_HIGH(__pdesc, __val, __set)\ - SET_BITS_TO_LE_4BYTE(__pdesc+(__set*16)+8, 0, 32, __val) - -/* for Txfilldescroptor92ee, fill the desc content. */ -#if (DMA_IS_64BIT == 1) -#define SET_TXBUFFER_DESC_LEN_WITH_OFFSET(__pdesc, __offset, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*16), 0, 16, __val) -#define SET_TXBUFFER_DESC_AMSDU_WITH_OFFSET(__pdesc, __offset, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*16), 31, 1, __val) -#define SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(__pdesc, __offset, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*16)+4, 0, 32, __val) -#define SET_TXBUFFER_DESC_ADD_HIGT_WITH_OFFSET(__pdesc, __offset, __val)\ - SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*16)+8, 0, 32, __val) -#define GET_TXBUFFER_DESC_ADDR_LOW(__pdesc, __offset) \ - LE_BITS_TO_4BYTE(__pdesc+(__offset*16)+4, 0, 32) -#else -#define SET_TXBUFFER_DESC_LEN_WITH_OFFSET(__pdesc, __offset, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*8), 0, 16, __val) -#define SET_TXBUFFER_DESC_AMSDU_WITH_OFFSET(__pdesc, __offset, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*8), 31, 1, __val) -#define SET_TXBUFFER_DESC_ADD_LOW_WITH_OFFSET(__pdesc, __offset, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+(__offset*8)+4, 0, 32, __val) -#define SET_TXBUFFER_DESC_ADD_HIGT_WITH_OFFSET(__pdesc, __offset, __val) -#define GET_TXBUFFER_DESC_ADDR_LOW(__pdesc, __offset) \ - LE_BITS_TO_4BYTE(__pdesc+(__offset*8)+4, 0, 32) -#endif - -/* Dword 0 */ -#define SET_TX_BUFF_DESC_LEN_0(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) -#define SET_TX_BUFF_DESC_PSB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 16, 15, __val) -#define SET_TX_BUFF_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) - -/* Dword 1 */ -#define SET_TX_BUFF_DESC_ADDR_LOW_0(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 32, __val) -#if (DMA_IS_64BIT == 1) -/* Dword 2 */ -#define SET_TX_BUFF_DESC_ADDR_HIGH_0(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 32, __val) -/* Dword 3 / RESERVED 0 */ -/* Dword 4 */ -#define SET_TX_BUFF_DESC_LEN_1(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 16, __val) -#define SET_TX_BUFF_DESC_AMSDU_1(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 31, 1, __val) -/* Dword 5 */ -#define SET_TX_BUFF_DESC_ADDR_LOW_1(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 32, __val) -/* Dword 6 */ -#define SET_TX_BUFF_DESC_ADDR_HIGH_1(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) -/* Dword 7 / RESERVED 0 */ -/* Dword 8 */ -#define SET_TX_BUFF_DESC_LEN_2(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 16, __val) -#define SET_TX_BUFF_DESC_AMSDU_2(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 31, 1, __val) -/* Dword 9 */ -#define SET_TX_BUFF_DESC_ADDR_LOW_2(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val) -/* Dword 10 */ -#define SET_TX_BUFF_DESC_ADDR_HIGH_2(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) -/* Dword 11 / RESERVED 0 */ -/* Dword 12 */ -#define SET_TX_BUFF_DESC_LEN_3(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+48, 0, 16, __val) -#define SET_TX_BUFF_DESC_AMSDU_3(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+48, 31, 1, __val) -/* Dword 13 */ -#define SET_TX_BUFF_DESC_ADDR_LOW_3(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+52, 0, 32, __val) -/* Dword 14 */ -#define SET_TX_BUFF_DESC_ADDR_HIGH_3(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+56, 0, 32, __val) -/* Dword 15 / RESERVED 0 */ -#else -#define SET_TX_BUFF_DESC_ADDR_HIGH_0(__pdesc, __val) -/* Dword 2 */ -#define SET_TX_BUFF_DESC_LEN_1(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 16, __val) -#define SET_TX_BUFF_DESC_AMSDU_1(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 31, 1, __val) -/* Dword 3 */ -#define SET_TX_BUFF_DESC_ADDR_LOW_1(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 32, __val) -#define SET_TX_BUFF_DESC_ADDR_HIGH_1(__pdesc, __val) -/* Dword 4 */ -#define SET_TX_BUFF_DESC_LEN_2(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 16, __val) -#define SET_TX_BUFF_DESC_AMSDU_2(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 31, 1, __val) -/* Dword 5 */ -#define SET_TX_BUFF_DESC_ADDR_LOW_2(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 32, __val) -#define SET_TX_BUFF_DESC_ADDR_HIGH_2(__pdesc, __val) -/* Dword 6 */ -#define SET_TX_BUFF_DESC_LEN_3(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 16, __val) -#define SET_TX_BUFF_DESC_AMSDU_3(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 31, 1, __val) -/* Dword 7 */ -#define SET_TX_BUFF_DESC_ADDR_LOW_3(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) -#define SET_TX_BUFF_DESC_ADDR_HIGH_3(__pdesc, __val) -#endif - -/* RX buffer */ - -/* DWORD 0 */ -#define SET_RX_BUFFER_DESC_DATA_LENGTH(__status, __val) \ - SET_BITS_TO_LE_4BYTE(__status, 0, 14, __val) -#define SET_RX_BUFFER_DESC_LS(__status, __val) \ - SET_BITS_TO_LE_4BYTE(__status, 15, 1, __val) -#define SET_RX_BUFFER_DESC_FS(__status, __val) \ - SET_BITS_TO_LE_4BYTE(__status, 16, 1, __val) -#define SET_RX_BUFFER_DESC_TOTAL_LENGTH(__status, __val) \ - SET_BITS_TO_LE_4BYTE(__status, 16, 15, __val) - -#define GET_RX_BUFFER_DESC_OWN(__status) \ - LE_BITS_TO_4BYTE(__status, 31, 1) -#define GET_RX_BUFFER_DESC_LS(__status) \ - LE_BITS_TO_4BYTE(__status, 15, 1) -#define GET_RX_BUFFER_DESC_FS(__status) \ - LE_BITS_TO_4BYTE(__status, 16, 1) -#define GET_RX_BUFFER_DESC_TOTAL_LENGTH(__status) \ - LE_BITS_TO_4BYTE(__status, 16, 15) - -/* DWORD 1 */ -#define SET_RX_BUFFER_PHYSICAL_LOW(__status, __val) \ - SET_BITS_TO_LE_4BYTE(__status+4, 0, 32, __val) - -/* DWORD 2 */ -#define SET_RX_BUFFER_PHYSICAL_HIGH(__status, __val) \ - SET_BITS_TO_LE_4BYTE(__status+8, 0, 32, __val) - -#define GET_RX_DESC_PKT_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 0, 14) -#define GET_RX_DESC_CRC32(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 14, 1) -#define GET_RX_DESC_ICV(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 15, 1) -#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 16, 4) -#define GET_RX_DESC_SECURITY(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 20, 3) -#define GET_RX_DESC_QOS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 23, 1) -#define GET_RX_DESC_SHIFT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 24, 2) -#define GET_RX_DESC_PHYST(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 26, 1) -#define GET_RX_DESC_SWDEC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 27, 1) -#define GET_RX_DESC_LS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 28, 1) -#define GET_RX_DESC_FS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 29, 1) -#define GET_RX_DESC_EOR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 30, 1) -#define GET_RX_DESC_OWN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 31, 1) - -#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) -#define SET_RX_DESC_EOR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) -#define SET_RX_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) - -#define GET_RX_DESC_MACID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 0, 7) -#define GET_RX_DESC_TID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 8, 4) -#define GET_RX_DESC_MACID_VLD(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 12, 1) -#define GET_RX_DESC_AMSDU(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) -#define GET_RX_DESC_RXID_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) -#define GET_RX_DESC_PAGGR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) -#define GET_RX_DESC_A1_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) -#define GET_RX_DESC_TCPOFFLOAD_CHKERR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) -#define GET_RX_DESC_TCPOFFLOAD_IPVER(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) -#define GET_RX_DESC_TCPOFFLOAD_IS_TCPUDP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 22, 1) -#define GET_RX_DESC_TCPOFFLOAD_CHK_VLD(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 23, 1) -#define GET_RX_DESC_PAM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) -#define GET_RX_DESC_PWR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) -#define GET_RX_DESC_MD(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) -#define GET_RX_DESC_MF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) -#define GET_RX_DESC_TYPE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) -#define GET_RX_DESC_MC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) -#define GET_RX_DESC_BC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) -#define GET_RX_DESC_SEQ(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) -#define GET_RX_DESC_FRAG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) -#define GET_RX_DESC_RX_IS_QOS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 16, 1) -#define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 28, 1) - -#define GET_RX_DESC_RXMCS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 0, 7) -#define GET_RX_DESC_HTC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) -#define GET_RX_STATUS_DESC_EOSP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 11, 1) -#define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 12, 2) -#define GET_RX_STATUS_DESC_DMA_AGG_NUM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 16, 8) -#define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 29, 1) -#define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 30, 1) -#define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 31, 1) - -#define GET_RX_DESC_TSFL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) - -#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) -#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) - -#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) -#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) - -/* TX report 2 format in Rx desc*/ - -#define GET_RX_RPT2_DESC_PKT_LEN(__status) \ - LE_BITS_TO_4BYTE(__status, 0, 9) -#define GET_RX_RPT2_DESC_MACID_VALID_1(__status) \ - LE_BITS_TO_4BYTE(__status+16, 0, 32) -#define GET_RX_RPT2_DESC_MACID_VALID_2(__status) \ - LE_BITS_TO_4BYTE(__status+20, 0, 32) - -#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ -do { \ - if (_size > TX_DESC_NEXT_DESC_OFFSET) \ - memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ - else \ - memset(__pdesc, 0, _size); \ -} while (0) - -#define RTL92EE_RX_HAL_IS_CCK_RATE(rxmcs)\ - (rxmcs == DESC_RATE1M ||\ - rxmcs == DESC_RATE2M ||\ - rxmcs == DESC_RATE5_5M ||\ - rxmcs == DESC_RATE11M) - -#define IS_LITTLE_ENDIAN 1 - -struct phy_rx_agc_info_t { - #if IS_LITTLE_ENDIAN - u8 gain:7, trsw:1; - #else - u8 trsw:1, gain:7; - #endif -}; - -struct phy_status_rpt { - struct phy_rx_agc_info_t path_agc[2]; - u8 ch_corr[2]; - u8 cck_sig_qual_ofdm_pwdb_all; - u8 cck_agc_rpt_ofdm_cfosho_a; - u8 cck_rpt_b_ofdm_cfosho_b; - u8 rsvd_1; - u8 noise_power_db_msb; - u8 path_cfotail[2]; - u8 pcts_mask[2]; - u8 stream_rxevm[2]; - u8 path_rxsnr[2]; - u8 noise_power_db_lsb; - u8 rsvd_2[3]; - u8 stream_csi[2]; - u8 stream_target_csi[2]; - u8 sig_evm; - u8 rsvd_3; -#if IS_LITTLE_ENDIAN - u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ - u8 sgi_en:1; - u8 rxsc:2; - u8 idle_long:1; - u8 r_ant_train_en:1; - u8 ant_sel_b:1; - u8 ant_sel:1; -#else /* _BIG_ENDIAN_ */ - u8 ant_sel:1; - u8 ant_sel_b:1; - u8 r_ant_train_en:1; - u8 idle_long:1; - u8 rxsc:2; - u8 sgi_en:1; - u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ -#endif -} __packed; - -struct rx_fwinfo { - u8 gain_trsw[4]; - u8 pwdb_all; - u8 cfosho[4]; - u8 cfotail[4]; - char rxevm[2]; - char rxsnr[4]; - u8 pdsnr[2]; - u8 csi_current[2]; - u8 csi_target[2]; - u8 sigevm; - u8 max_ex_pwr; - u8 ex_intf_flag:1; - u8 sgi_en:1; - u8 rxsc:2; - u8 reserve:4; -} __packed; - -struct tx_desc { - u32 pktsize:16; - u32 offset:8; - u32 bmc:1; - u32 htc:1; - u32 lastseg:1; - u32 firstseg:1; - u32 linip:1; - u32 noacm:1; - u32 gf:1; - u32 own:1; - - u32 macid:6; - u32 rsvd0:2; - u32 queuesel:5; - u32 rd_nav_ext:1; - u32 lsig_txop_en:1; - u32 pifs:1; - u32 rateid:4; - u32 nav_usehdr:1; - u32 en_descid:1; - u32 sectype:2; - u32 pktoffset:8; - - u32 rts_rc:6; - u32 data_rc:6; - u32 agg_en:1; - u32 rdg_en:1; - u32 bar_retryht:2; - u32 agg_break:1; - u32 morefrag:1; - u32 raw:1; - u32 ccx:1; - u32 ampdudensity:3; - u32 bt_int:1; - u32 ant_sela:1; - u32 ant_selb:1; - u32 txant_cck:2; - u32 txant_l:2; - u32 txant_ht:2; - - u32 nextheadpage:8; - u32 tailpage:8; - u32 seq:12; - u32 cpu_handle:1; - u32 tag1:1; - u32 trigger_int:1; - u32 hwseq_en:1; - - u32 rtsrate:5; - u32 apdcfe:1; - u32 qos:1; - u32 hwseq_ssn:1; - u32 userrate:1; - u32 dis_rtsfb:1; - u32 dis_datafb:1; - u32 cts2self:1; - u32 rts_en:1; - u32 hwrts_en:1; - u32 portid:1; - u32 pwr_status:3; - u32 waitdcts:1; - u32 cts2ap_en:1; - u32 txsc:2; - u32 stbc:2; - u32 txshort:1; - u32 txbw:1; - u32 rtsshort:1; - u32 rtsbw:1; - u32 rtssc:2; - u32 rtsstbc:2; - - u32 txrate:6; - u32 shortgi:1; - u32 ccxt:1; - u32 txrate_fb_lmt:5; - u32 rtsrate_fb_lmt:4; - u32 retrylmt_en:1; - u32 txretrylmt:6; - u32 usb_txaggnum:8; - - u32 txagca:5; - u32 txagcb:5; - u32 usemaxlen:1; - u32 maxaggnum:5; - u32 mcsg1maxlen:4; - u32 mcsg2maxlen:4; - u32 mcsg3maxlen:4; - u32 mcs7sgimaxlen:4; - - u32 txbuffersize:16; - u32 sw_offset30:8; - u32 sw_offset31:4; - u32 rsvd1:1; - u32 antsel_c:1; - u32 null_0:1; - u32 null_1:1; - - u32 txbuffaddr; - u32 txbufferaddr64; - u32 nextdescaddress; - u32 nextdescaddress64; - - u32 reserve_pass_pcie_mm_limit[4]; -} __packed; - -struct rx_desc { - u32 length:14; - u32 crc32:1; - u32 icverror:1; - u32 drv_infosize:4; - u32 security:3; - u32 qos:1; - u32 shift:2; - u32 phystatus:1; - u32 swdec:1; - u32 lastseg:1; - u32 firstseg:1; - u32 eor:1; - u32 own:1; - - u32 macid:6; - u32 tid:4; - u32 hwrsvd:5; - u32 paggr:1; - u32 faggr:1; - u32 a1_fit:4; - u32 a2_fit:4; - u32 pam:1; - u32 pwr:1; - u32 moredata:1; - u32 morefrag:1; - u32 type:2; - u32 mc:1; - u32 bc:1; - - u32 seq:12; - u32 frag:4; - u32 nextpktlen:14; - u32 nextind:1; - u32 rsvd:1; - - u32 rxmcs:6; - u32 rxht:1; - u32 amsdu:1; - u32 splcp:1; - u32 bandwidth:1; - u32 htc:1; - u32 tcpchk_rpt:1; - u32 ipcchk_rpt:1; - u32 tcpchk_valid:1; - u32 hwpcerr:1; - u32 hwpcind:1; - u32 iv0:16; - - u32 iv1; - - u32 tsfl; - - u32 bufferaddress; - u32 bufferaddress64; - -} __packed; - -void rtl92ee_rx_check_dma_ok(struct ieee80211_hw *hw, u8 *header_desc, - u8 queue_index); -u16 rtl92ee_rx_desc_buff_remained_cnt(struct ieee80211_hw *hw, - u8 queue_index); -u16 rtl92ee_get_available_desc(struct ieee80211_hw *hw, u8 queue_index); -void rtl92ee_pre_fill_tx_bd_desc(struct ieee80211_hw *hw, - u8 *tx_bd_desc, u8 *desc, u8 queue_index, - struct sk_buff *skb, dma_addr_t addr); - -void rtl92ee_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *pbd_desc_tx, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); -bool rtl92ee_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *status, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb); -void rtl92ee_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, - u8 desc_name, u8 *val); - -u32 rtl92ee_get_desc(u8 *pdesc, bool istx, u8 desc_name); -bool rtl92ee_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, u16 index); -void rtl92ee_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); -void rtl92ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, - struct sk_buff *skb); -u32 rtl92ee_rx_command_packet(struct ieee80211_hw *hw, - struct rtl_stats status, - struct sk_buff *skb); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/Makefile b/drivers/net/wireless/rtlwifi/rtl8192se/Makefile deleted file mode 100644 index b7eb13819cbc..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -rtl8192se-objs := \ - dm.o \ - fw.o \ - hw.o \ - led.o \ - phy.o \ - rf.o \ - sw.o \ - table.o \ - trx.o - -obj-$(CONFIG_RTL8192SE) += rtl8192se.o - -ccflags-y += -D__CHECK_ENDIAN__ - diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h deleted file mode 100644 index 41466f957cdc..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h +++ /dev/null @@ -1,555 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#ifndef __REALTEK_92S_DEF_H__ -#define __REALTEK_92S_DEF_H__ - -#define RX_MPDU_QUEUE 0 -#define RX_CMD_QUEUE 1 - -#define SHORT_SLOT_TIME 9 -#define NON_SHORT_SLOT_TIME 20 - -/* Queue Select Value in TxDesc */ -#define QSLT_BK 0x2 -#define QSLT_BE 0x0 -#define QSLT_VI 0x5 -#define QSLT_VO 0x6 -#define QSLT_BEACON 0x10 -#define QSLT_HIGH 0x11 -#define QSLT_MGNT 0x12 -#define QSLT_CMD 0x13 - -/* Tx Desc */ -#define TX_DESC_SIZE_RTL8192S (16 * 4) -#define TX_CMDDESC_SIZE_RTL8192S (16 * 4) - -/* 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, __mask) \ - ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ - BIT_LEN_MASK_32(__mask)) - -/* 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/write various fields in RX or TX descriptors */ - -/* Dword 0 */ -#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val) -#define SET_TX_DESC_OFFSET(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val) -#define SET_TX_DESC_TYPE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 24, 2, __val) -#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) -#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) -#define SET_TX_DESC_LINIP(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) -#define SET_TX_DESC_AMSDU(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) -#define SET_TX_DESC_GREEN_FIELD(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) -#define SET_TX_DESC_OWN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) - -#define GET_TX_DESC_OWN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 31, 1) - -/* Dword 1 */ -#define SET_TX_DESC_MACID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 0, 5, __val) -#define SET_TX_DESC_MORE_DATA(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 5, 1, __val) -#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 6, 1, __val) -#define SET_TX_DESC_PIFS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 7, 1, __val) -#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 8, 5, __val) -#define SET_TX_DESC_ACK_POLICY(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 13, 2, __val) -#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 15, 1, __val) -#define SET_TX_DESC_NON_QOS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 16, 1, __val) -#define SET_TX_DESC_KEY_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 17, 2, __val) -#define SET_TX_DESC_OUI(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 19, 1, __val) -#define SET_TX_DESC_PKT_TYPE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 20, 1, __val) -#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 21, 1, __val) -#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 22, 2, __val) -#define SET_TX_DESC_WDS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 24, 1, __val) -#define SET_TX_DESC_HTC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 25, 1, __val) -#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 26, 5, __val) -#define SET_TX_DESC_HWPC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 27, 1, __val) - -/* Dword 2 */ -#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 8, 0, 6, __val) -#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 8, 6, 1, __val) -#define SET_TX_DESC_TSFL(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 8, 7, 5, __val) -#define SET_TX_DESC_RTS_RETRY_COUNT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 8, 12, 6, __val) -#define SET_TX_DESC_DATA_RETRY_COUNT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 8, 18, 6, __val) -#define SET_TX_DESC_RSVD_MACID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(((__pdesc) + 8), 24, 5, __val) -#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 8, 29, 1, __val) -#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 8, 30, 1, __val) -#define SET_TX_DESC_OWN_MAC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 8, 31, 1, __val) - -/* Dword 3 */ -#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 0, 8, __val) -#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 8, 8, __val) -#define SET_TX_DESC_SEQ(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 16, 12, __val) -#define SET_TX_DESC_FRAG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 28, 4, __val) - -/* Dword 4 */ -#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 0, 6, __val) -#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 6, 1, __val) -#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 7, 4, __val) -#define SET_TX_DESC_CTS_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 11, 1, __val) -#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 12, 1, __val) -#define SET_TX_DESC_RA_BRSR_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 13, 3, __val) -#define SET_TX_DESC_TXHT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 16, 1, __val) -#define SET_TX_DESC_TX_SHORT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 17, 1, __val) -#define SET_TX_DESC_TX_BANDWIDTH(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 18, 1, __val) -#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 19, 2, __val) -#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 21, 2, __val) -#define SET_TX_DESC_TX_REVERSE_DIRECTION(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 23, 1, __val) -#define SET_TX_DESC_RTS_HT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 24, 1, __val) -#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 25, 1, __val) -#define SET_TX_DESC_RTS_BANDWIDTH(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 26, 1, __val) -#define SET_TX_DESC_RTS_SUB_CARRIER(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 27, 2, __val) -#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 29, 2, __val) -#define SET_TX_DESC_USER_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 31, 1, __val) - -/* Dword 5 */ -#define SET_TX_DESC_PACKET_ID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 20, 0, 9, __val) -#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 20, 9, 6, __val) -#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 20, 15, 1, __val) -#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 20, 16, 5, __val) -#define SET_TX_DESC_TX_AGC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 20, 21, 11, __val) - -/* Dword 6 */ -#define SET_TX_DESC_IP_CHECK_SUM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 24, 0, 16, __val) -#define SET_TX_DESC_TCP_CHECK_SUM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 24, 16, 16, __val) - -/* Dword 7 */ -#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 28, 0, 16, __val) -#define SET_TX_DESC_IP_HEADER_OFFSET(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 28, 16, 8, __val) -#define SET_TX_DESC_TCP_ENABLE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 28, 31, 1, __val) - -/* Dword 8 */ -#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 32, 0, 32, __val) -#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 32, 0, 32) - -/* Dword 9 */ -#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 36, 0, 32, __val) - -/* Because the PCI Tx descriptors are chaied at the - * initialization and all the NextDescAddresses in - * these descriptors cannot not be cleared (,or - * driver/HW cannot find the next descriptor), the - * offset 36 (NextDescAddresses) is reserved when - * the desc is cleared. */ -#define TX_DESC_NEXT_DESC_OFFSET 36 -#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ - memset(__pdesc, 0, min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) - -/* Rx Desc */ -#define RX_STATUS_DESC_SIZE 24 -#define RX_DRV_INFO_SIZE_UNIT 8 - -/* DWORD 0 */ -#define SET_RX_STATUS_DESC_PKT_LEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val) -#define SET_RX_STATUS_DESC_CRC32(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 14, 1, __val) -#define SET_RX_STATUS_DESC_ICV(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 15, 1, __val) -#define SET_RX_STATUS_DESC_DRVINFO_SIZE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 16, 4, __val) -#define SET_RX_STATUS_DESC_SECURITY(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 20, 3, __val) -#define SET_RX_STATUS_DESC_QOS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 23, 1, __val) -#define SET_RX_STATUS_DESC_SHIFT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 24, 2, __val) -#define SET_RX_STATUS_DESC_PHY_STATUS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) -#define SET_RX_STATUS_DESC_SWDEC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) -#define SET_RX_STATUS_DESC_LAST_SEG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) -#define SET_RX_STATUS_DESC_FIRST_SEG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) -#define SET_RX_STATUS_DESC_EOR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) -#define SET_RX_STATUS_DESC_OWN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) - -#define GET_RX_STATUS_DESC_PKT_LEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 0, 14) -#define GET_RX_STATUS_DESC_CRC32(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 14, 1) -#define GET_RX_STATUS_DESC_ICV(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 15, 1) -#define GET_RX_STATUS_DESC_DRVINFO_SIZE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 16, 4) -#define GET_RX_STATUS_DESC_SECURITY(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 20, 3) -#define GET_RX_STATUS_DESC_QOS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 23, 1) -#define GET_RX_STATUS_DESC_SHIFT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 24, 2) -#define GET_RX_STATUS_DESC_PHY_STATUS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 26, 1) -#define GET_RX_STATUS_DESC_SWDEC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 27, 1) -#define GET_RX_STATUS_DESC_LAST_SEG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 28, 1) -#define GET_RX_STATUS_DESC_FIRST_SEG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 29, 1) -#define GET_RX_STATUS_DESC_EOR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 30, 1) -#define GET_RX_STATUS_DESC_OWN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc, 31, 1) - -/* DWORD 1 */ -#define SET_RX_STATUS_DESC_MACID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 0, 5, __val) -#define SET_RX_STATUS_DESC_TID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 5, 4, __val) -#define SET_RX_STATUS_DESC_PAGGR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 14, 1, __val) -#define SET_RX_STATUS_DESC_FAGGR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 15, 1, __val) -#define SET_RX_STATUS_DESC_A1_FIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 16, 4, __val) -#define SET_RX_STATUS_DESC_A2_FIT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 20, 4, __val) -#define SET_RX_STATUS_DESC_PAM(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 24, 1, __val) -#define SET_RX_STATUS_DESC_PWR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 25, 1, __val) -#define SET_RX_STATUS_DESC_MOREDATA(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 26, 1, __val) -#define SET_RX_STATUS_DESC_MOREFRAG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 27, 1, __val) -#define SET_RX_STATUS_DESC_TYPE(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 28, 2, __val) -#define SET_RX_STATUS_DESC_MC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 30, 1, __val) -#define SET_RX_STATUS_DESC_BC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 4, 31, 1, __val) - -#define GET_RX_STATUS_DEC_MACID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 0, 5) -#define GET_RX_STATUS_DESC_TID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 5, 4) -#define GET_RX_STATUS_DESC_PAGGR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 14, 1) -#define GET_RX_STATUS_DESC_FAGGR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 15, 1) -#define GET_RX_STATUS_DESC_A1_FIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 16, 4) -#define GET_RX_STATUS_DESC_A2_FIT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 20, 4) -#define GET_RX_STATUS_DESC_PAM(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 24, 1) -#define GET_RX_STATUS_DESC_PWR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 25, 1) -#define GET_RX_STATUS_DESC_MORE_DATA(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 26, 1) -#define GET_RX_STATUS_DESC_MORE_FRAG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 27, 1) -#define GET_RX_STATUS_DESC_TYPE(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 28, 2) -#define GET_RX_STATUS_DESC_MC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 30, 1) -#define GET_RX_STATUS_DESC_BC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 4, 31, 1) - -/* DWORD 2 */ -#define SET_RX_STATUS_DESC_SEQ(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 8, 0, 12, __val) -#define SET_RX_STATUS_DESC_FRAG(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 8, 12, 4, __val) -#define SET_RX_STATUS_DESC_NEXT_PKTLEN(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 8, 16, 8, __val) -#define SET_RX_STATUS_DESC_NEXT_IND(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 8, 30, 1, __val) - -#define GET_RX_STATUS_DESC_SEQ(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 8, 0, 12) -#define GET_RX_STATUS_DESC_FRAG(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 8, 12, 4) -#define GET_RX_STATUS_DESC_NEXT_PKTLEN(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 8, 16, 8) -#define GET_RX_STATUS_DESC_NEXT_IND(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 8, 30, 1) - -/* DWORD 3 */ -#define SET_RX_STATUS_DESC_RX_MCS(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 0, 6, __val) -#define SET_RX_STATUS_DESC_RX_HT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 6, 1, __val) -#define SET_RX_STATUS_DESC_AMSDU(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 7, 1, __val) -#define SET_RX_STATUS_DESC_SPLCP(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 8, 1, __val) -#define SET_RX_STATUS_DESC_BW(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 9, 1, __val) -#define SET_RX_STATUS_DESC_HTC(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 10, 1, __val) -#define SET_RX_STATUS_DESC_TCP_CHK_RPT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 11, 1, __val) -#define SET_RX_STATUS_DESC_IP_CHK_RPT(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 12, 1, __val) -#define SET_RX_STATUS_DESC_TCP_CHK_VALID(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 13, 1, __val) -#define SET_RX_STATUS_DESC_HWPC_ERR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 14, 1, __val) -#define SET_RX_STATUS_DESC_HWPC_IND(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 15, 1, __val) -#define SET_RX_STATUS_DESC_IV0(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 12, 16, 16, __val) - -#define GET_RX_STATUS_DESC_RX_MCS(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 12, 0, 6) -#define GET_RX_STATUS_DESC_RX_HT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 12, 6, 1) -#define GET_RX_STATUS_DESC_AMSDU(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 12, 7, 1) -#define GET_RX_STATUS_DESC_SPLCP(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 12, 8, 1) -#define GET_RX_STATUS_DESC_BW(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 12, 9, 1) -#define GET_RX_STATUS_DESC_HTC(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 12, 10, 1) -#define GET_RX_STATUS_DESC_TCP_CHK_RPT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 12, 11, 1) -#define GET_RX_STATUS_DESC_IP_CHK_RPT(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 12, 12, 1) -#define GET_RX_STATUS_DESC_TCP_CHK_VALID(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 12, 13, 1) -#define GET_RX_STATUS_DESC_HWPC_ERR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 12, 14, 1) -#define GET_RX_STATUS_DESC_HWPC_IND(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 12, 15, 1) -#define GET_RX_STATUS_DESC_IV0(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 12, 16, 16) - -/* DWORD 4 */ -#define SET_RX_STATUS_DESC_IV1(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 16, 0, 32, __val) -#define GET_RX_STATUS_DESC_IV1(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 16, 0, 32) - -/* DWORD 5 */ -#define SET_RX_STATUS_DESC_TSFL(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 20, 0, 32, __val) -#define GET_RX_STATUS_DESC_TSFL(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 20, 0, 32) - -/* DWORD 6 */ -#define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \ - SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val) -#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc) \ - SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32) - -#define SE_RX_HAL_IS_CCK_RATE(_pdesc)\ - (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC_RATE1M || \ - GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC_RATE2M || \ - GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC_RATE5_5M ||\ - GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC_RATE11M) - -enum rf_optype { - RF_OP_BY_SW_3WIRE = 0, - RF_OP_BY_FW, - RF_OP_MAX -}; - -enum ic_inferiority { - IC_INFERIORITY_A = 0, - IC_INFERIORITY_B = 1, -}; - -enum fwcmd_iotype { - /* For DIG DM */ - FW_CMD_DIG_ENABLE = 0, - FW_CMD_DIG_DISABLE = 1, - FW_CMD_DIG_HALT = 2, - FW_CMD_DIG_RESUME = 3, - /* For High Power DM */ - FW_CMD_HIGH_PWR_ENABLE = 4, - FW_CMD_HIGH_PWR_DISABLE = 5, - /* For Rate adaptive DM */ - FW_CMD_RA_RESET = 6, - FW_CMD_RA_ACTIVE = 7, - FW_CMD_RA_REFRESH_N = 8, - FW_CMD_RA_REFRESH_BG = 9, - FW_CMD_RA_INIT = 10, - /* For FW supported IQK */ - FW_CMD_IQK_INIT = 11, - /* Tx power tracking switch, - * MP driver only */ - FW_CMD_TXPWR_TRACK_ENABLE = 12, - /* Tx power tracking switch, - * MP driver only */ - FW_CMD_TXPWR_TRACK_DISABLE = 13, - /* Tx power tracking with thermal - * indication, for Normal driver */ - FW_CMD_TXPWR_TRACK_THERMAL = 14, - FW_CMD_PAUSE_DM_BY_SCAN = 15, - FW_CMD_RESUME_DM_BY_SCAN = 16, - FW_CMD_RA_REFRESH_N_COMB = 17, - FW_CMD_RA_REFRESH_BG_COMB = 18, - FW_CMD_ANTENNA_SW_ENABLE = 19, - FW_CMD_ANTENNA_SW_DISABLE = 20, - /* Tx Status report for CCX from FW */ - FW_CMD_TX_FEEDBACK_CCX_ENABLE = 21, - /* Indifate firmware that driver - * enters LPS, For PS-Poll issue */ - FW_CMD_LPS_ENTER = 22, - /* Indicate firmware that driver - * leave LPS*/ - FW_CMD_LPS_LEAVE = 23, - /* Set DIG mode to signal strength */ - FW_CMD_DIG_MODE_SS = 24, - /* Set DIG mode to false alarm. */ - FW_CMD_DIG_MODE_FA = 25, - FW_CMD_ADD_A2_ENTRY = 26, - FW_CMD_CTRL_DM_BY_DRIVER = 27, - FW_CMD_CTRL_DM_BY_DRIVER_NEW = 28, - FW_CMD_PAPE_CONTROL = 29, - FW_CMD_IQK_ENABLE = 30, -}; - -/* Driver info contain PHY status - * and other variabel size info - * PHY Status content as below - */ -struct rx_fwinfo { - /* DWORD 0 */ - u8 gain_trsw[4]; - /* DWORD 1 */ - u8 pwdb_all; - u8 cfosho[4]; - /* DWORD 2 */ - u8 cfotail[4]; - /* DWORD 3 */ - s8 rxevm[2]; - s8 rxsnr[4]; - /* DWORD 4 */ - u8 pdsnr[2]; - /* DWORD 5 */ - u8 csi_current[2]; - u8 csi_target[2]; - /* DWORD 6 */ - u8 sigevm; - u8 max_ex_pwr; - u8 ex_intf_flag:1; - u8 sgi_en:1; - u8 rxsc:2; - u8 reserve:4; -}; - -struct phy_sts_cck_8192s_t { - u8 adc_pwdb_x[4]; - u8 sq_rpt; - u8 cck_agc_rpt; -}; - -#endif - diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c deleted file mode 100644 index 9bae5a92e30f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c +++ /dev/null @@ -1,742 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../base.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "fw.h" - -static const u32 edca_setting_dl[PEER_MAX] = { - 0xa44f, /* 0 UNKNOWN */ - 0x5ea44f, /* 1 REALTEK_90 */ - 0x5ea44f, /* 2 REALTEK_92SE */ - 0xa630, /* 3 BROAD */ - 0xa44f, /* 4 RAL */ - 0xa630, /* 5 ATH */ - 0xa630, /* 6 CISCO */ - 0xa42b, /* 7 MARV */ -}; - -static const u32 edca_setting_dl_gmode[PEER_MAX] = { - 0x4322, /* 0 UNKNOWN */ - 0xa44f, /* 1 REALTEK_90 */ - 0x5ea44f, /* 2 REALTEK_92SE */ - 0xa42b, /* 3 BROAD */ - 0x5e4322, /* 4 RAL */ - 0x4322, /* 5 ATH */ - 0xa430, /* 6 CISCO */ - 0x5ea44f, /* 7 MARV */ -}; - -static const u32 edca_setting_ul[PEER_MAX] = { - 0x5e4322, /* 0 UNKNOWN */ - 0xa44f, /* 1 REALTEK_90 */ - 0x5ea44f, /* 2 REALTEK_92SE */ - 0x5ea322, /* 3 BROAD */ - 0x5ea422, /* 4 RAL */ - 0x5ea322, /* 5 ATH */ - 0x3ea44f, /* 6 CISCO */ - 0x5ea44f, /* 7 MARV */ -}; - -static void _rtl92s_dm_check_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - static u64 last_txok_cnt; - static u64 last_rxok_cnt; - u64 cur_txok_cnt = 0; - u64 cur_rxok_cnt = 0; - - u32 edca_be_ul = edca_setting_ul[mac->vendor]; - u32 edca_be_dl = edca_setting_dl[mac->vendor]; - u32 edca_gmode = edca_setting_dl_gmode[mac->vendor]; - - if (mac->link_state != MAC80211_LINKED) { - rtlpriv->dm.current_turbo_edca = false; - goto dm_checkedcaturbo_exit; - } - - if ((!rtlpriv->dm.is_any_nonbepkts) && - (!rtlpriv->dm.disable_framebursting)) { - cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; - cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; - - if (rtlpriv->phy.rf_type == RF_1T2R) { - if (cur_txok_cnt > 4 * cur_rxok_cnt) { - /* Uplink TP is present. */ - if (rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { - rtl_write_dword(rtlpriv, EDCAPARA_BE, - edca_be_ul); - rtlpriv->dm.is_cur_rdlstate = false; - } - } else {/* Balance TP is present. */ - if (!rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { - if (mac->mode == WIRELESS_MODE_G || - mac->mode == WIRELESS_MODE_B) - rtl_write_dword(rtlpriv, - EDCAPARA_BE, - edca_gmode); - else - rtl_write_dword(rtlpriv, - EDCAPARA_BE, - edca_be_dl); - rtlpriv->dm.is_cur_rdlstate = true; - } - } - rtlpriv->dm.current_turbo_edca = true; - } else { - if (cur_rxok_cnt > 4 * cur_txok_cnt) { - if (!rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { - if (mac->mode == WIRELESS_MODE_G || - mac->mode == WIRELESS_MODE_B) - rtl_write_dword(rtlpriv, - EDCAPARA_BE, - edca_gmode); - else - rtl_write_dword(rtlpriv, - EDCAPARA_BE, - edca_be_dl); - rtlpriv->dm.is_cur_rdlstate = true; - } - } else { - if (rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { - rtl_write_dword(rtlpriv, EDCAPARA_BE, - edca_be_ul); - rtlpriv->dm.is_cur_rdlstate = false; - } - } - rtlpriv->dm.current_turbo_edca = true; - } - } else { - if (rtlpriv->dm.current_turbo_edca) { - u8 tmp = AC0_BE; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, - &tmp); - rtlpriv->dm.current_turbo_edca = false; - } - } - -dm_checkedcaturbo_exit: - rtlpriv->dm.is_any_nonbepkts = false; - last_txok_cnt = rtlpriv->stats.txbytesunicast; - last_rxok_cnt = rtlpriv->stats.rxbytesunicast; -} - -static void _rtl92s_dm_txpowertracking_callback_thermalmeter( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 thermalvalue = 0; - u32 fw_cmd = 0; - - rtlpriv->dm.txpower_trackinginit = true; - - thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermal meter 0x%x\n", - thermalvalue, - rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter); - - if (thermalvalue) { - rtlpriv->dm.thermalvalue = thermalvalue; - if (hal_get_firmwareversion(rtlpriv) >= 0x35) { - rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL); - } else { - fw_cmd = (FW_TXPWR_TRACK_THERMAL | - (rtlpriv->efuse.thermalmeter[0] << 8) | - (thermalvalue << 16)); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Write to FW Thermal Val = 0x%x\n", fw_cmd); - - rtl_write_dword(rtlpriv, WFM5, fw_cmd); - rtl92s_phy_chk_fwcmd_iodone(hw); - } - } - - rtlpriv->dm.txpowercount = 0; -} - -static void _rtl92s_dm_check_txpowertracking_thermalmeter( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u8 tx_power_checkcnt = 5; - - /* 2T2R TP issue */ - if (rtlphy->rf_type == RF_2T2R) - return; - - if (!rtlpriv->dm.txpower_tracking) - return; - - if (rtlpriv->dm.txpowercount <= tx_power_checkcnt) { - rtlpriv->dm.txpowercount++; - return; - } - - if (!rtlpriv->dm.tm_trigger) { - rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, - RFREG_OFFSET_MASK, 0x60); - rtlpriv->dm.tm_trigger = 1; - } else { - _rtl92s_dm_txpowertracking_callback_thermalmeter(hw); - rtlpriv->dm.tm_trigger = 0; - } -} - -static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rate_adaptive *ra = &(rtlpriv->ra); - struct ieee80211_sta *sta = NULL; - u32 low_rssi_thresh = 0; - u32 middle_rssi_thresh = 0; - u32 high_rssi_thresh = 0; - - if (is_hal_stop(rtlhal)) - return; - - if (!rtlpriv->dm.useramask) - return; - - if (hal_get_firmwareversion(rtlpriv) >= 61 && - !rtlpriv->dm.inform_fw_driverctrldm) { - rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER); - rtlpriv->dm.inform_fw_driverctrldm = true; - } - - if ((mac->link_state == MAC80211_LINKED) && - (mac->opmode == NL80211_IFTYPE_STATION)) { - switch (ra->pre_ratr_state) { - case DM_RATR_STA_HIGH: - high_rssi_thresh = 40; - middle_rssi_thresh = 30; - low_rssi_thresh = 20; - break; - case DM_RATR_STA_MIDDLE: - high_rssi_thresh = 44; - middle_rssi_thresh = 30; - low_rssi_thresh = 20; - break; - case DM_RATR_STA_LOW: - high_rssi_thresh = 44; - middle_rssi_thresh = 34; - low_rssi_thresh = 20; - break; - case DM_RATR_STA_ULTRALOW: - high_rssi_thresh = 44; - middle_rssi_thresh = 34; - low_rssi_thresh = 24; - break; - default: - high_rssi_thresh = 44; - middle_rssi_thresh = 34; - low_rssi_thresh = 24; - break; - } - - if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) { - ra->ratr_state = DM_RATR_STA_HIGH; - } else if (rtlpriv->dm.undec_sm_pwdb > - (long)middle_rssi_thresh) { - ra->ratr_state = DM_RATR_STA_LOW; - } else if (rtlpriv->dm.undec_sm_pwdb > - (long)low_rssi_thresh) { - ra->ratr_state = DM_RATR_STA_LOW; - } else { - ra->ratr_state = DM_RATR_STA_ULTRALOW; - } - - if (ra->pre_ratr_state != ra->ratr_state) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n", - rtlpriv->dm.undec_sm_pwdb, ra->ratr_state, - ra->pre_ratr_state, ra->ratr_state); - - rcu_read_lock(); - sta = rtl_find_sta(hw, mac->bssid); - if (sta) - rtlpriv->cfg->ops->update_rate_tbl(hw, sta, - ra->ratr_state); - rcu_read_unlock(); - - ra->pre_ratr_state = ra->ratr_state; - } - } -} - -static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - bool current_mrc; - bool enable_mrc = true; - long tmpentry_maxpwdb = 0; - u8 rssi_a = 0; - u8 rssi_b = 0; - - if (is_hal_stop(rtlhal)) - return; - - if ((rtlphy->rf_type == RF_1T1R) || (rtlphy->rf_type == RF_2T2R)) - return; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(¤t_mrc)); - - if (mac->link_state >= MAC80211_LINKED) { - if (rtlpriv->dm.undec_sm_pwdb > tmpentry_maxpwdb) { - rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A]; - rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B]; - } - } - - /* MRC settings would NOT affect TP on Wireless B mode. */ - if (mac->mode != WIRELESS_MODE_B) { - if ((rssi_a == 0) && (rssi_b == 0)) { - enable_mrc = true; - } else if (rssi_b > 30) { - /* Turn on B-Path */ - enable_mrc = true; - } else if (rssi_b < 5) { - /* Turn off B-path */ - enable_mrc = false; - /* Take care of RSSI differentiation. */ - } else if (rssi_a > 15 && (rssi_a >= rssi_b)) { - if ((rssi_a - rssi_b) > 15) - /* Turn off B-path */ - enable_mrc = false; - else if ((rssi_a - rssi_b) < 10) - /* Turn on B-Path */ - enable_mrc = true; - else - enable_mrc = current_mrc; - } else { - /* Turn on B-Path */ - enable_mrc = true; - } - } - - /* Update MRC settings if needed. */ - if (enable_mrc != current_mrc) - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC, - (u8 *)&enable_mrc); - -} - -void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.current_turbo_edca = false; - rtlpriv->dm.is_any_nonbepkts = false; - rtlpriv->dm.is_cur_rdlstate = false; -} - -static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rate_adaptive *ra = &(rtlpriv->ra); - - ra->ratr_state = DM_RATR_STA_MAX; - ra->pre_ratr_state = DM_RATR_STA_MAX; - - if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER && - hal_get_firmwareversion(rtlpriv) >= 60) - rtlpriv->dm.useramask = true; - else - rtlpriv->dm.useramask = false; - - rtlpriv->dm.useramask = false; - rtlpriv->dm.inform_fw_driverctrldm = false; -} - -static void _rtl92s_dm_init_txpowertracking_thermalmeter( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.txpower_tracking = true; - rtlpriv->dm.txpowercount = 0; - rtlpriv->dm.txpower_trackinginit = false; -} - -static void _rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); - u32 ret_value; - - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); - falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); - - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); - falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); - falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); - falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); - - falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + falsealm_cnt->cnt_crc8_fail + - falsealm_cnt->cnt_mcs_fail; - - /* read CCK false alarm */ - ret_value = rtl_get_bbreg(hw, 0xc64, MASKDWORD); - falsealm_cnt->cnt_cck_fail = (ret_value & 0xffff); - falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail + - falsealm_cnt->cnt_cck_fail; -} - -static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *digtable = &rtlpriv->dm_digtable; - struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); - - if (falsealm_cnt->cnt_all > digtable->fa_highthresh) { - if ((digtable->back_val - 6) < - digtable->backoffval_range_min) - digtable->back_val = digtable->backoffval_range_min; - else - digtable->back_val -= 6; - } else if (falsealm_cnt->cnt_all < digtable->fa_lowthresh) { - if ((digtable->back_val + 6) > - digtable->backoffval_range_max) - digtable->back_val = - digtable->backoffval_range_max; - else - digtable->back_val += 6; - } -} - -static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *digtable = &rtlpriv->dm_digtable; - struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); - static u8 initialized, force_write; - u8 initial_gain = 0; - - if ((digtable->pre_sta_cstate == digtable->cur_sta_cstate) || - (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT)) { - if (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT) { - if (rtlpriv->psc.rfpwr_state != ERFON) - return; - - if (digtable->backoff_enable_flag) - rtl92s_backoff_enable_flag(hw); - else - digtable->back_val = DM_DIG_BACKOFF_MAX; - - if ((digtable->rssi_val + 10 - digtable->back_val) > - digtable->rx_gain_max) - digtable->cur_igvalue = - digtable->rx_gain_max; - else if ((digtable->rssi_val + 10 - digtable->back_val) - < digtable->rx_gain_min) - digtable->cur_igvalue = - digtable->rx_gain_min; - else - digtable->cur_igvalue = digtable->rssi_val + 10 - - digtable->back_val; - - if (falsealm_cnt->cnt_all > 10000) - digtable->cur_igvalue = - (digtable->cur_igvalue > 0x33) ? - digtable->cur_igvalue : 0x33; - - if (falsealm_cnt->cnt_all > 16000) - digtable->cur_igvalue = - digtable->rx_gain_max; - /* connected -> connected or disconnected -> disconnected */ - } else { - /* Firmware control DIG, do nothing in driver dm */ - return; - } - /* disconnected -> connected or connected -> - * disconnected or beforeconnect->(dis)connected */ - } else { - /* Enable FW DIG */ - digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; - rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE); - - digtable->back_val = DM_DIG_BACKOFF_MAX; - digtable->cur_igvalue = rtlpriv->phy.default_initialgain[0]; - digtable->pre_igvalue = 0; - return; - } - - /* Forced writing to prevent from fw-dig overwriting. */ - if (digtable->pre_igvalue != rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, - MASKBYTE0)) - force_write = 1; - - if ((digtable->pre_igvalue != digtable->cur_igvalue) || - !initialized || force_write) { - /* Disable FW DIG */ - rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_DISABLE); - - initial_gain = (u8)digtable->cur_igvalue; - - /* Set initial gain. */ - rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, initial_gain); - rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, initial_gain); - digtable->pre_igvalue = digtable->cur_igvalue; - initialized = 1; - force_write = 0; - } -} - -static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dig = &rtlpriv->dm_digtable; - - if (rtlpriv->mac80211.act_scanning) - return; - - /* Decide the current status and if modify initial gain or not */ - if (rtlpriv->mac80211.link_state >= MAC80211_LINKED || - rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) - dig->cur_sta_cstate = DIG_STA_CONNECT; - else - dig->cur_sta_cstate = DIG_STA_DISCONNECT; - - dig->rssi_val = rtlpriv->dm.undec_sm_pwdb; - - /* Change dig mode to rssi */ - if (dig->cur_sta_cstate != DIG_STA_DISCONNECT) { - if (dig->dig_twoport_algorithm == - DIG_TWO_PORT_ALGO_FALSE_ALARM) { - dig->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; - rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS); - } - } - - _rtl92s_dm_false_alarm_counter_statistics(hw); - _rtl92s_dm_initial_gain_sta_beforeconnect(hw); - - dig->pre_sta_cstate = dig->cur_sta_cstate; -} - -static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct dig_t *digtable = &rtlpriv->dm_digtable; - - /* 2T2R TP issue */ - if (rtlphy->rf_type == RF_2T2R) - return; - - if (!rtlpriv->dm.dm_initialgain_enable) - return; - - if (digtable->dig_enable_flag == false) - return; - - _rtl92s_dm_ctrl_initgain_bytwoport(hw); -} - -static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long undec_sm_pwdb; - long txpwr_threshold_lv1, txpwr_threshold_lv2; - - /* 2T2R TP issue */ - if (rtlphy->rf_type == RF_2T2R) - return; - - if (!rtlpriv->dm.dynamic_txpower_enable || - rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { - rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; - return; - } - - if ((mac->link_state < MAC80211_LINKED) && - (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "Not connected to any\n"); - - rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; - - rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; - return; - } - - if (mac->link_state >= MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Client PWDB = 0x%lx\n", - undec_sm_pwdb); - } else { - undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "STA Default Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - } else { - undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Ext Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - - txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2; - txpwr_threshold_lv1 = TX_POWER_NEAR_FIELD_THRESH_LVL1; - - if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1) - rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; - else if (undec_sm_pwdb >= txpwr_threshold_lv2) - rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2; - else if ((undec_sm_pwdb < (txpwr_threshold_lv2 - 3)) && - (undec_sm_pwdb >= txpwr_threshold_lv1)) - rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1; - else if (undec_sm_pwdb < (txpwr_threshold_lv1 - 3)) - rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; - - if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) - rtl92s_phy_set_txpower(hw, rtlphy->current_channel); - - rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; -} - -static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *digtable = &rtlpriv->dm_digtable; - - /* Disable DIG scheme now.*/ - digtable->dig_enable_flag = true; - digtable->backoff_enable_flag = true; - - if ((rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) && - (hal_get_firmwareversion(rtlpriv) >= 0x3c)) - digtable->dig_algorithm = DIG_ALGO_BY_TOW_PORT; - else - digtable->dig_algorithm = - DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM; - - digtable->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; - digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; - /* off=by real rssi value, on=by digtable->rssi_val for new dig */ - digtable->dig_dbgmode = DM_DBG_OFF; - digtable->dig_slgorithm_switch = 0; - - /* 2007/10/04 MH Define init gain threshol. */ - digtable->dig_state = DM_STA_DIG_MAX; - digtable->dig_highpwrstate = DM_STA_DIG_MAX; - - digtable->cur_sta_cstate = DIG_STA_DISCONNECT; - digtable->pre_sta_cstate = DIG_STA_DISCONNECT; - digtable->cur_ap_cstate = DIG_AP_DISCONNECT; - digtable->pre_ap_cstate = DIG_AP_DISCONNECT; - - digtable->rssi_lowthresh = DM_DIG_THRESH_LOW; - digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; - - digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; - digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; - - digtable->rssi_highpower_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW; - digtable->rssi_highpower_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH; - - /* for dig debug rssi value */ - digtable->rssi_val = 50; - digtable->back_val = DM_DIG_BACKOFF_MAX; - digtable->rx_gain_max = DM_DIG_MAX; - - digtable->rx_gain_min = DM_DIG_MIN; - - digtable->backoffval_range_max = DM_DIG_BACKOFF_MAX; - digtable->backoffval_range_min = DM_DIG_BACKOFF_MIN; -} - -static void _rtl92s_dm_init_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if ((hal_get_firmwareversion(rtlpriv) >= 60) && - (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)) - rtlpriv->dm.dynamic_txpower_enable = true; - else - rtlpriv->dm.dynamic_txpower_enable = false; - - rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; - rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; -} - -void rtl92s_dm_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; - rtlpriv->dm.undec_sm_pwdb = -1; - - _rtl92s_dm_init_dynamic_txpower(hw); - rtl92s_dm_init_edca_turbo(hw); - _rtl92s_dm_init_rate_adaptive_mask(hw); - _rtl92s_dm_init_txpowertracking_thermalmeter(hw); - _rtl92s_dm_init_dig(hw); - - rtl_write_dword(rtlpriv, WFM5, FW_CCA_CHK_ENABLE); -} - -void rtl92s_dm_watchdog(struct ieee80211_hw *hw) -{ - _rtl92s_dm_check_edca_turbo(hw); - _rtl92s_dm_check_txpowertracking_thermalmeter(hw); - _rtl92s_dm_ctrl_initgain_byrssi(hw); - _rtl92s_dm_dynamic_txpower(hw); - _rtl92s_dm_refresh_rateadaptive_mask(hw); - _rtl92s_dm_switch_baseband_mrc(hw); -} - diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.h b/drivers/net/wireless/rtlwifi/rtl8192se/dm.h deleted file mode 100644 index de6ac796c74d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.h +++ /dev/null @@ -1,92 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#ifndef __RTL_92S_DM_H__ -#define __RTL_92S_DM_H__ - -enum dm_dig_alg { - DIG_ALGO_BY_FALSE_ALARM = 0, - DIG_ALGO_BY_RSSI = 1, - DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM = 2, - DIG_ALGO_BY_TOW_PORT = 3, - DIG_ALGO_MAX -}; - -enum dm_dig_two_port_alg { - DIG_TWO_PORT_ALGO_RSSI = 0, - DIG_TWO_PORT_ALGO_FALSE_ALARM = 1, -}; - -enum dm_dig_dbg { - DM_DBG_OFF = 0, - DM_DBG_ON = 1, - DM_DBG_MAX -}; - -enum dm_dig_sta { - DM_STA_DIG_OFF = 0, - DM_STA_DIG_ON, - DM_STA_DIG_MAX -}; - -enum dm_ratr_sta { - DM_RATR_STA_HIGH = 0, - DM_RATR_STA_MIDDLEHIGH = 1, - DM_RATR_STA_MIDDLE = 2, - DM_RATR_STA_MIDDLELOW = 3, - DM_RATR_STA_LOW = 4, - DM_RATR_STA_ULTRALOW = 5, - DM_RATR_STA_MAX -}; - -#define DM_TYPE_BYFW 0 -#define DM_TYPE_BYDRIVER 1 - -#define TX_HIGH_PWR_LEVEL_NORMAL 0 -#define TX_HIGH_PWR_LEVEL_LEVEL1 1 -#define TX_HIGH_PWR_LEVEL_LEVEL2 2 - -#define HAL_DM_DIG_DISABLE BIT(0) /* Disable Dig */ -#define HAL_DM_HIPWR_DISABLE BIT(1) /* Disable High Power */ - -#define TX_HIGHPWR_LEVEL_NORMAL 0 -#define TX_HIGHPWR_LEVEL_NORMAL1 1 -#define TX_HIGHPWR_LEVEL_NORMAL2 2 - -#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 -#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 - -#define DM_DIG_HIGH_PWR_THRESH_HIGH 75 -#define DM_DIG_HIGH_PWR_THRESH_LOW 70 -#define DM_DIG_MIN_Netcore 0x12 - -void rtl92s_dm_watchdog(struct ieee80211_hw *hw); -void rtl92s_dm_init(struct ieee80211_hw *hw); -void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c deleted file mode 100644 index 331b1584a1a2..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c +++ /dev/null @@ -1,652 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "reg.h" -#include "def.h" -#include "fw.h" - -static void _rtl92s_fw_set_rqpn(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_dword(rtlpriv, RQPN, 0xffffffff); - rtl_write_dword(rtlpriv, RQPN + 4, 0xffffffff); - rtl_write_byte(rtlpriv, RQPN + 8, 0xff); - rtl_write_byte(rtlpriv, RQPN + 0xB, 0x80); -} - -static bool _rtl92s_firmware_enable_cpu(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 ichecktime = 200; - u16 tmpu2b; - u8 tmpu1b, cpustatus = 0; - - _rtl92s_fw_set_rqpn(hw); - - /* Enable CPU. */ - tmpu1b = rtl_read_byte(rtlpriv, SYS_CLKR); - /* AFE source */ - rtl_write_byte(rtlpriv, SYS_CLKR, (tmpu1b | SYS_CPU_CLKSEL)); - - tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | FEN_CPUEN)); - - /* Polling IMEM Ready after CPU has refilled. */ - do { - cpustatus = rtl_read_byte(rtlpriv, TCR); - if (cpustatus & IMEM_RDY) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "IMEM Ready after CPU has refilled\n"); - break; - } - - udelay(100); - } while (ichecktime--); - - if (!(cpustatus & IMEM_RDY)) - return false; - - return true; -} - -static enum fw_status _rtl92s_firmware_get_nextstatus( - enum fw_status fw_currentstatus) -{ - enum fw_status next_fwstatus = 0; - - switch (fw_currentstatus) { - case FW_STATUS_INIT: - next_fwstatus = FW_STATUS_LOAD_IMEM; - break; - case FW_STATUS_LOAD_IMEM: - next_fwstatus = FW_STATUS_LOAD_EMEM; - break; - case FW_STATUS_LOAD_EMEM: - next_fwstatus = FW_STATUS_LOAD_DMEM; - break; - case FW_STATUS_LOAD_DMEM: - next_fwstatus = FW_STATUS_READY; - break; - default: - break; - } - - return next_fwstatus; -} - -static u8 _rtl92s_firmware_header_map_rftype(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - switch (rtlphy->rf_type) { - case RF_1T1R: - return 0x11; - case RF_1T2R: - return 0x12; - case RF_2T2R: - return 0x22; - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "Unknown RF type(%x)\n", - rtlphy->rf_type); - break; - } - return 0x22; -} - -static void _rtl92s_firmwareheader_priveupdate(struct ieee80211_hw *hw, - struct fw_priv *pfw_priv) -{ - /* Update RF types for RATR settings. */ - pfw_priv->rf_config = _rtl92s_firmware_header_map_rftype(hw); -} - - - -static bool _rtl92s_cmd_send_packet(struct ieee80211_hw *hw, - struct sk_buff *skb, u8 last) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring; - struct rtl_tx_desc *pdesc; - unsigned long flags; - u8 idx = 0; - - ring = &rtlpci->tx_ring[TXCMD_QUEUE]; - - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - - idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; - pdesc = &ring->desc[idx]; - rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); - __skb_queue_tail(&ring->queue, skb); - - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - - return true; -} - -static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw, - u8 *code_virtual_address, u32 buffer_len) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct sk_buff *skb; - struct rtl_tcb_desc *tcb_desc; - unsigned char *seg_ptr; - u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE; - u16 frag_length, frag_offset = 0; - u16 extra_descoffset = 0; - u8 last_inipkt = 0; - - _rtl92s_fw_set_rqpn(hw); - - if (buffer_len >= MAX_FIRMWARE_CODE_SIZE) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Size over FIRMWARE_CODE_SIZE!\n"); - - return false; - } - - extra_descoffset = 0; - - do { - if ((buffer_len - frag_offset) > frag_threshold) { - frag_length = frag_threshold + extra_descoffset; - } else { - frag_length = (u16)(buffer_len - frag_offset + - extra_descoffset); - last_inipkt = 1; - } - - /* Allocate skb buffer to contain firmware */ - /* info and tx descriptor info. */ - skb = dev_alloc_skb(frag_length); - if (!skb) - return false; - skb_reserve(skb, extra_descoffset); - seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length - - extra_descoffset)); - memcpy(seg_ptr, code_virtual_address + frag_offset, - (u32)(frag_length - extra_descoffset)); - - tcb_desc = (struct rtl_tcb_desc *)(skb->cb); - tcb_desc->queue_index = TXCMD_QUEUE; - tcb_desc->cmd_or_init = DESC_PACKET_TYPE_INIT; - tcb_desc->last_inipkt = last_inipkt; - - _rtl92s_cmd_send_packet(hw, skb, last_inipkt); - - frag_offset += (frag_length - extra_descoffset); - - } while (frag_offset < buffer_len); - - rtl_write_byte(rtlpriv, TP_POLL, TPPOLL_CQ); - - return true ; -} - -static bool _rtl92s_firmware_checkready(struct ieee80211_hw *hw, - u8 loadfw_status) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rt_firmware *firmware = (struct rt_firmware *)rtlhal->pfirmware; - u32 tmpu4b; - u8 cpustatus = 0; - short pollingcnt = 1000; - bool rtstatus = true; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "LoadStaus(%d)\n", loadfw_status); - - firmware->fwstatus = (enum fw_status)loadfw_status; - - switch (loadfw_status) { - case FW_STATUS_LOAD_IMEM: - /* Polling IMEM code done. */ - do { - cpustatus = rtl_read_byte(rtlpriv, TCR); - if (cpustatus & IMEM_CODE_DONE) - break; - udelay(5); - } while (pollingcnt--); - - if (!(cpustatus & IMEM_CHK_RPT) || (pollingcnt <= 0)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\n", - cpustatus); - goto status_check_fail; - } - break; - - case FW_STATUS_LOAD_EMEM: - /* Check Put Code OK and Turn On CPU */ - /* Polling EMEM code done. */ - do { - cpustatus = rtl_read_byte(rtlpriv, TCR); - if (cpustatus & EMEM_CODE_DONE) - break; - udelay(5); - } while (pollingcnt--); - - if (!(cpustatus & EMEM_CHK_RPT) || (pollingcnt <= 0)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\n", - cpustatus); - goto status_check_fail; - } - - /* Turn On CPU */ - rtstatus = _rtl92s_firmware_enable_cpu(hw); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Enable CPU fail!\n"); - goto status_check_fail; - } - break; - - case FW_STATUS_LOAD_DMEM: - /* Polling DMEM code done */ - do { - cpustatus = rtl_read_byte(rtlpriv, TCR); - if (cpustatus & DMEM_CODE_DONE) - break; - udelay(5); - } while (pollingcnt--); - - if (!(cpustatus & DMEM_CODE_DONE) || (pollingcnt <= 0)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Polling DMEM code done fail ! cpustatus(%#x)\n", - cpustatus); - goto status_check_fail; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "DMEM code download success, cpustatus(%#x)\n", - cpustatus); - - /* Prevent Delay too much and being scheduled out */ - /* Polling Load Firmware ready */ - pollingcnt = 2000; - do { - cpustatus = rtl_read_byte(rtlpriv, TCR); - if (cpustatus & FWRDY) - break; - udelay(40); - } while (pollingcnt--); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Polling Load Firmware ready, cpustatus(%x)\n", - cpustatus); - - if (((cpustatus & LOAD_FW_READY) != LOAD_FW_READY) || - (pollingcnt <= 0)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Polling Load Firmware ready fail ! cpustatus(%x)\n", - cpustatus); - goto status_check_fail; - } - - /* If right here, we can set TCR/RCR to desired value */ - /* and config MAC lookback mode to normal mode */ - tmpu4b = rtl_read_dword(rtlpriv, TCR); - rtl_write_dword(rtlpriv, TCR, (tmpu4b & (~TCR_ICV))); - - tmpu4b = rtl_read_dword(rtlpriv, RCR); - rtl_write_dword(rtlpriv, RCR, (tmpu4b | RCR_APPFCS | - RCR_APP_ICV | RCR_APP_MIC)); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Current RCR settings(%#x)\n", tmpu4b); - - /* Set to normal mode. */ - rtl_write_byte(rtlpriv, LBKMD_SEL, LBK_NORMAL); - break; - - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, - "Unknown status check!\n"); - rtstatus = false; - break; - } - -status_check_fail: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "loadfw_status(%d), rtstatus(%x)\n", - loadfw_status, rtstatus); - return rtstatus; -} - -int rtl92s_download_fw(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rt_firmware *firmware = NULL; - struct fw_hdr *pfwheader; - struct fw_priv *pfw_priv = NULL; - u8 *puc_mappedfile = NULL; - u32 ul_filelength = 0; - u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE; - u8 fwstatus = FW_STATUS_INIT; - bool rtstatus = true; - - if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) - return 1; - - firmware = (struct rt_firmware *)rtlhal->pfirmware; - firmware->fwstatus = FW_STATUS_INIT; - - puc_mappedfile = firmware->sz_fw_tmpbuffer; - - /* 1. Retrieve FW header. */ - firmware->pfwheader = (struct fw_hdr *) puc_mappedfile; - pfwheader = firmware->pfwheader; - firmware->firmwareversion = byte(pfwheader->version, 0); - firmware->pfwheader->fwpriv.hci_sel = 1;/* pcie */ - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", - pfwheader->signature, - pfwheader->version, pfwheader->dmem_size, - pfwheader->img_imem_size, pfwheader->img_sram_size); - - /* 2. Retrieve IMEM image. */ - if ((pfwheader->img_imem_size == 0) || (pfwheader->img_imem_size > - sizeof(firmware->fw_imem))) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "memory for data image is less than IMEM required\n"); - goto fail; - } else { - puc_mappedfile += fwhdr_size; - - memcpy(firmware->fw_imem, puc_mappedfile, - pfwheader->img_imem_size); - firmware->fw_imem_len = pfwheader->img_imem_size; - } - - /* 3. Retriecve EMEM image. */ - if (pfwheader->img_sram_size > sizeof(firmware->fw_emem)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "memory for data image is less than EMEM required\n"); - goto fail; - } else { - puc_mappedfile += firmware->fw_imem_len; - - memcpy(firmware->fw_emem, puc_mappedfile, - pfwheader->img_sram_size); - firmware->fw_emem_len = pfwheader->img_sram_size; - } - - /* 4. download fw now */ - fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus); - while (fwstatus != FW_STATUS_READY) { - /* Image buffer redirection. */ - switch (fwstatus) { - case FW_STATUS_LOAD_IMEM: - puc_mappedfile = firmware->fw_imem; - ul_filelength = firmware->fw_imem_len; - break; - case FW_STATUS_LOAD_EMEM: - puc_mappedfile = firmware->fw_emem; - ul_filelength = firmware->fw_emem_len; - break; - case FW_STATUS_LOAD_DMEM: - /* Partial update the content of header private. */ - pfwheader = firmware->pfwheader; - pfw_priv = &pfwheader->fwpriv; - _rtl92s_firmwareheader_priveupdate(hw, pfw_priv); - puc_mappedfile = (u8 *)(firmware->pfwheader) + - RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; - ul_filelength = fwhdr_size - - RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Unexpected Download step!!\n"); - goto fail; - } - - /* <2> Download image file */ - rtstatus = _rtl92s_firmware_downloadcode(hw, puc_mappedfile, - ul_filelength); - - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "fail!\n"); - goto fail; - } - - /* <3> Check whether load FW process is ready */ - rtstatus = _rtl92s_firmware_checkready(hw, fwstatus); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "fail!\n"); - goto fail; - } - - fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus); - } - - return rtstatus; -fail: - return 0; -} - -static u32 _rtl92s_fill_h2c_cmd(struct sk_buff *skb, u32 h2cbufferlen, - u32 cmd_num, u32 *pelement_id, u32 *pcmd_len, - u8 **pcmb_buffer, u8 *cmd_start_seq) -{ - u32 totallen = 0, len = 0, tx_desclen = 0; - u32 pre_continueoffset = 0; - u8 *ph2c_buffer; - u8 i = 0; - - do { - /* 8 - Byte aligment */ - len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); - - /* Buffer length is not enough */ - if (h2cbufferlen < totallen + len + tx_desclen) - break; - - /* Clear content */ - ph2c_buffer = (u8 *)skb_put(skb, (u32)len); - memset((ph2c_buffer + totallen + tx_desclen), 0, len); - - /* CMD len */ - SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), - 0, 16, pcmd_len[i]); - - /* CMD ID */ - SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), - 16, 8, pelement_id[i]); - - /* CMD Sequence */ - *cmd_start_seq = *cmd_start_seq % 0x80; - SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), - 24, 7, *cmd_start_seq); - ++*cmd_start_seq; - - /* Copy memory */ - memcpy((ph2c_buffer + totallen + tx_desclen + - H2C_TX_CMD_HDR_LEN), pcmb_buffer[i], pcmd_len[i]); - - /* CMD continue */ - /* set the continue in prevoius cmd. */ - if (i < cmd_num - 1) - SET_BITS_TO_LE_4BYTE((ph2c_buffer + pre_continueoffset), - 31, 1, 1); - - pre_continueoffset = totallen; - - totallen += len; - } while (++i < cmd_num); - - return totallen; -} - -static u32 _rtl92s_get_h2c_cmdlen(u32 h2cbufferlen, u32 cmd_num, u32 *pcmd_len) -{ - u32 totallen = 0, len = 0, tx_desclen = 0; - u8 i = 0; - - do { - /* 8 - Byte aligment */ - len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); - - /* Buffer length is not enough */ - if (h2cbufferlen < totallen + len + tx_desclen) - break; - - totallen += len; - } while (++i < cmd_num); - - return totallen + tx_desclen; -} - -static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd, - u8 *pcmd_buffer) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_tcb_desc *cb_desc; - struct sk_buff *skb; - u32 element_id = 0; - u32 cmd_len = 0; - u32 len; - - switch (h2c_cmd) { - case FW_H2C_SETPWRMODE: - element_id = H2C_SETPWRMODE_CMD ; - cmd_len = sizeof(struct h2c_set_pwrmode_parm); - break; - case FW_H2C_JOINBSSRPT: - element_id = H2C_JOINBSSRPT_CMD; - cmd_len = sizeof(struct h2c_joinbss_rpt_parm); - break; - case FW_H2C_WOWLAN_UPDATE_GTK: - element_id = H2C_WOWLAN_UPDATE_GTK_CMD; - cmd_len = sizeof(struct h2c_wpa_two_way_parm); - break; - case FW_H2C_WOWLAN_UPDATE_IV: - element_id = H2C_WOWLAN_UPDATE_IV_CMD; - cmd_len = sizeof(unsigned long long); - break; - case FW_H2C_WOWLAN_OFFLOAD: - element_id = H2C_WOWLAN_FW_OFFLOAD; - cmd_len = sizeof(u8); - break; - default: - break; - } - - len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len); - skb = dev_alloc_skb(len); - if (!skb) - return false; - cb_desc = (struct rtl_tcb_desc *)(skb->cb); - cb_desc->queue_index = TXCMD_QUEUE; - cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL; - cb_desc->last_inipkt = false; - - _rtl92s_fill_h2c_cmd(skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &element_id, - &cmd_len, &pcmd_buffer, &rtlhal->h2c_txcmd_seq); - _rtl92s_cmd_send_packet(hw, skb, false); - rtlpriv->cfg->ops->tx_polling(hw, TXCMD_QUEUE); - - return true; -} - -void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 Mode) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct h2c_set_pwrmode_parm pwrmode; - u16 max_wakeup_period = 0; - - pwrmode.mode = Mode; - pwrmode.flag_low_traffic_en = 0; - pwrmode.flag_lpnav_en = 0; - pwrmode.flag_rf_low_snr_en = 0; - pwrmode.flag_dps_en = 0; - pwrmode.bcn_rx_en = 0; - pwrmode.bcn_to = 0; - SET_BITS_TO_LE_2BYTE((u8 *)(&pwrmode) + 8, 0, 16, - mac->vif->bss_conf.beacon_int); - pwrmode.app_itv = 0; - pwrmode.awake_bcn_itvl = ppsc->reg_max_lps_awakeintvl; - pwrmode.smart_ps = 1; - pwrmode.bcn_pass_period = 10; - - /* Set beacon pass count */ - if (pwrmode.mode == FW_PS_MIN_MODE) - max_wakeup_period = mac->vif->bss_conf.beacon_int; - else if (pwrmode.mode == FW_PS_MAX_MODE) - max_wakeup_period = mac->vif->bss_conf.beacon_int * - mac->vif->bss_conf.dtim_period; - - if (max_wakeup_period >= 500) - pwrmode.bcn_pass_cnt = 1; - else if ((max_wakeup_period >= 300) && (max_wakeup_period < 500)) - pwrmode.bcn_pass_cnt = 2; - else if ((max_wakeup_period >= 200) && (max_wakeup_period < 300)) - pwrmode.bcn_pass_cnt = 3; - else if ((max_wakeup_period >= 20) && (max_wakeup_period < 200)) - pwrmode.bcn_pass_cnt = 5; - else - pwrmode.bcn_pass_cnt = 1; - - _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_SETPWRMODE, (u8 *)&pwrmode); - -} - -void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, - u8 mstatus, u8 ps_qosinfo) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct h2c_joinbss_rpt_parm joinbss_rpt; - - joinbss_rpt.opmode = mstatus; - joinbss_rpt.ps_qos_info = ps_qosinfo; - joinbss_rpt.bssid[0] = mac->bssid[0]; - joinbss_rpt.bssid[1] = mac->bssid[1]; - joinbss_rpt.bssid[2] = mac->bssid[2]; - joinbss_rpt.bssid[3] = mac->bssid[3]; - joinbss_rpt.bssid[4] = mac->bssid[4]; - joinbss_rpt.bssid[5] = mac->bssid[5]; - SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 8, 0, 16, - mac->vif->bss_conf.beacon_int); - SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 10, 0, 16, mac->assoc_id); - - _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_JOINBSSRPT, (u8 *)&joinbss_rpt); -} - diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.h b/drivers/net/wireless/rtlwifi/rtl8192se/fw.h deleted file mode 100644 index b1e44b86e8ed..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.h +++ /dev/null @@ -1,375 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#ifndef __REALTEK_FIRMWARE92S_H__ -#define __REALTEK_FIRMWARE92S_H__ - -#define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000 -#define RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE 90000 -#define RTL8190_CPU_START_OFFSET 0x80 -/* Firmware Local buffer size. 64k */ -#define MAX_FIRMWARE_CODE_SIZE 0xFF00 - -#define RT_8192S_FIRMWARE_HDR_SIZE 80 -#define RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE 32 - -/* support till 64 bit bus width OS */ -#define MAX_DEV_ADDR_SIZE 8 -#define MAX_FIRMWARE_INFORMATION_SIZE 32 -#define MAX_802_11_HEADER_LENGTH (40 + \ - MAX_FIRMWARE_INFORMATION_SIZE) -#define ENCRYPTION_MAX_OVERHEAD 128 -#define MAX_FRAGMENT_COUNT 8 -#define MAX_TRANSMIT_BUFFER_SIZE (1600 + \ - (MAX_802_11_HEADER_LENGTH + \ - ENCRYPTION_MAX_OVERHEAD) *\ - MAX_FRAGMENT_COUNT) - -#define H2C_TX_CMD_HDR_LEN 8 - -/* The following DM control code are for Reg0x364, */ -#define FW_DIG_ENABLE_CTL BIT(0) -#define FW_HIGH_PWR_ENABLE_CTL BIT(1) -#define FW_SS_CTL BIT(2) -#define FW_RA_INIT_CTL BIT(3) -#define FW_RA_BG_CTL BIT(4) -#define FW_RA_N_CTL BIT(5) -#define FW_PWR_TRK_CTL BIT(6) -#define FW_IQK_CTL BIT(7) -#define FW_FA_CTL BIT(8) -#define FW_DRIVER_CTRL_DM_CTL BIT(9) -#define FW_PAPE_CTL_BY_SW_HW BIT(10) -#define FW_DISABLE_ALL_DM 0 -#define FW_PWR_TRK_PARAM_CLR 0x0000ffff -#define FW_RA_PARAM_CLR 0xffff0000 - -enum desc_packet_type { - DESC_PACKET_TYPE_INIT = 0, - DESC_PACKET_TYPE_NORMAL = 1, -}; - -/* 8-bytes alignment required */ -struct fw_priv { - /* --- long word 0 ---- */ - /* 0x12: CE product, 0x92: IT product */ - u8 signature_0; - /* 0x87: CE product, 0x81: IT product */ - u8 signature_1; - /* 0x81: PCI-AP, 01:PCIe, 02: 92S-U, - * 0x82: USB-AP, 0x12: 72S-U, 03:SDIO */ - u8 hci_sel; - /* the same value as reigster value */ - u8 chip_version; - /* customer ID low byte */ - u8 customer_id_0; - /* customer ID high byte */ - u8 customer_id_1; - /* 0x11: 1T1R, 0x12: 1T2R, - * 0x92: 1T2R turbo, 0x22: 2T2R */ - u8 rf_config; - /* 4: 4EP, 6: 6EP, 11: 11EP */ - u8 usb_ep_num; - - /* --- long word 1 ---- */ - /* regulatory class bit map 0 */ - u8 regulatory_class_0; - /* regulatory class bit map 1 */ - u8 regulatory_class_1; - /* regulatory class bit map 2 */ - u8 regulatory_class_2; - /* regulatory class bit map 3 */ - u8 regulatory_class_3; - /* 0:SWSI, 1:HWSI, 2:HWPI */ - u8 rfintfs; - u8 def_nettype; - u8 rsvd010; - u8 rsvd011; - - /* --- long word 2 ---- */ - /* 0x00: normal, 0x03: MACLBK, 0x01: PHYLBK */ - u8 lbk_mode; - /* 1: for MP use, 0: for normal - * driver (to be discussed) */ - u8 mp_mode; - u8 rsvd020; - u8 rsvd021; - u8 rsvd022; - u8 rsvd023; - u8 rsvd024; - u8 rsvd025; - - /* --- long word 3 ---- */ - /* QoS enable */ - u8 qos_en; - /* 40MHz BW enable */ - /* 4181 convert AMSDU to AMPDU, 0: disable */ - u8 bw_40mhz_en; - u8 amsdu2ampdu_en; - /* 11n AMPDU enable */ - u8 ampdu_en; - /* FW offloads, 0: driver handles */ - u8 rate_control_offload; - /* FW offloads, 0: driver handles */ - u8 aggregation_offload; - u8 rsvd030; - u8 rsvd031; - - /* --- long word 4 ---- */ - /* 1. FW offloads, 0: driver handles */ - u8 beacon_offload; - /* 2. FW offloads, 0: driver handles */ - u8 mlme_offload; - /* 3. FW offloads, 0: driver handles */ - u8 hwpc_offload; - /* 4. FW offloads, 0: driver handles */ - u8 tcp_checksum_offload; - /* 5. FW offloads, 0: driver handles */ - u8 tcp_offload; - /* 6. FW offloads, 0: driver handles */ - u8 ps_control_offload; - /* 7. FW offloads, 0: driver handles */ - u8 wwlan_offload; - u8 rsvd040; - - /* --- long word 5 ---- */ - /* tcp tx packet length low byte */ - u8 tcp_tx_frame_len_L; - /* tcp tx packet length high byte */ - u8 tcp_tx_frame_len_H; - /* tcp rx packet length low byte */ - u8 tcp_rx_frame_len_L; - /* tcp rx packet length high byte */ - u8 tcp_rx_frame_len_H; - u8 rsvd050; - u8 rsvd051; - u8 rsvd052; - u8 rsvd053; -}; - -/* 8-byte alinment required */ -struct fw_hdr { - - /* --- LONG WORD 0 ---- */ - u16 signature; - /* 0x8000 ~ 0x8FFF for FPGA version, - * 0x0000 ~ 0x7FFF for ASIC version, */ - u16 version; - /* define the size of boot loader */ - u32 dmem_size; - - - /* --- LONG WORD 1 ---- */ - /* define the size of FW in IMEM */ - u32 img_imem_size; - /* define the size of FW in SRAM */ - u32 img_sram_size; - - /* --- LONG WORD 2 ---- */ - /* define the size of DMEM variable */ - u32 fw_priv_size; - u32 rsvd0; - - /* --- LONG WORD 3 ---- */ - u32 rsvd1; - u32 rsvd2; - - struct fw_priv fwpriv; - -} ; - -enum fw_status { - FW_STATUS_INIT = 0, - FW_STATUS_LOAD_IMEM = 1, - FW_STATUS_LOAD_EMEM = 2, - FW_STATUS_LOAD_DMEM = 3, - FW_STATUS_READY = 4, -}; - -struct rt_firmware { - struct fw_hdr *pfwheader; - enum fw_status fwstatus; - u16 firmwareversion; - u8 fw_imem[RTL8190_MAX_FIRMWARE_CODE_SIZE]; - u8 fw_emem[RTL8190_MAX_FIRMWARE_CODE_SIZE]; - u32 fw_imem_len; - u32 fw_emem_len; - u8 sz_fw_tmpbuffer[RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE]; - u32 sz_fw_tmpbufferlen; - u16 cmdpacket_fragthresold; -}; - -struct h2c_set_pwrmode_parm { - u8 mode; - u8 flag_low_traffic_en; - u8 flag_lpnav_en; - u8 flag_rf_low_snr_en; - /* 1: dps, 0: 32k */ - u8 flag_dps_en; - u8 bcn_rx_en; - u8 bcn_pass_cnt; - /* beacon TO (ms). ¡§=0¡¨ no limit. */ - u8 bcn_to; - u16 bcn_itv; - /* only for VOIP mode. */ - u8 app_itv; - u8 awake_bcn_itvl; - u8 smart_ps; - /* unit: 100 ms */ - u8 bcn_pass_period; -}; - -struct h2c_joinbss_rpt_parm { - u8 opmode; - u8 ps_qos_info; - u8 bssid[6]; - u16 bcnitv; - u16 aid; -} ; - -struct h2c_wpa_ptk { - /* EAPOL-Key Key Confirmation Key (KCK) */ - u8 kck[16]; - /* EAPOL-Key Key Encryption Key (KEK) */ - u8 kek[16]; - /* Temporal Key 1 (TK1) */ - u8 tk1[16]; - union { - /* Temporal Key 2 (TK2) */ - u8 tk2[16]; - struct { - u8 tx_mic_key[8]; - u8 rx_mic_key[8]; - } athu; - } u; -}; - -struct h2c_wpa_two_way_parm { - /* algorithm TKIP or AES */ - u8 pairwise_en_alg; - u8 group_en_alg; - struct h2c_wpa_ptk wpa_ptk_value; -} ; - -enum h2c_cmd { - FW_H2C_SETPWRMODE = 0, - FW_H2C_JOINBSSRPT = 1, - FW_H2C_WOWLAN_UPDATE_GTK = 2, - FW_H2C_WOWLAN_UPDATE_IV = 3, - FW_H2C_WOWLAN_OFFLOAD = 4, -}; - -enum fw_h2c_cmd { - H2C_READ_MACREG_CMD, /*0*/ - H2C_WRITE_MACREG_CMD, - H2C_READBB_CMD, - H2C_WRITEBB_CMD, - H2C_READRF_CMD, - H2C_WRITERF_CMD, /*5*/ - H2C_READ_EEPROM_CMD, - H2C_WRITE_EEPROM_CMD, - H2C_READ_EFUSE_CMD, - H2C_WRITE_EFUSE_CMD, - H2C_READ_CAM_CMD, /*10*/ - H2C_WRITE_CAM_CMD, - H2C_SETBCNITV_CMD, - H2C_SETMBIDCFG_CMD, - H2C_JOINBSS_CMD, - H2C_DISCONNECT_CMD, /*15*/ - H2C_CREATEBSS_CMD, - H2C_SETOPMode_CMD, - H2C_SITESURVEY_CMD, - H2C_SETAUTH_CMD, - H2C_SETKEY_CMD, /*20*/ - H2C_SETSTAKEY_CMD, - H2C_SETASSOCSTA_CMD, - H2C_DELASSOCSTA_CMD, - H2C_SETSTAPWRSTATE_CMD, - H2C_SETBASICRATE_CMD, /*25*/ - H2C_GETBASICRATE_CMD, - H2C_SETDATARATE_CMD, - H2C_GETDATARATE_CMD, - H2C_SETPHYINFO_CMD, - H2C_GETPHYINFO_CMD, /*30*/ - H2C_SETPHY_CMD, - H2C_GETPHY_CMD, - H2C_READRSSI_CMD, - H2C_READGAIN_CMD, - H2C_SETATIM_CMD, /*35*/ - H2C_SETPWRMODE_CMD, - H2C_JOINBSSRPT_CMD, - H2C_SETRATABLE_CMD, - H2C_GETRATABLE_CMD, - H2C_GETCCXREPORT_CMD, /*40*/ - H2C_GETDTMREPORT_CMD, - H2C_GETTXRATESTATICS_CMD, - H2C_SETUSBSUSPEND_CMD, - H2C_SETH2CLBK_CMD, - H2C_TMP1, /*45*/ - H2C_WOWLAN_UPDATE_GTK_CMD, - H2C_WOWLAN_FW_OFFLOAD, - H2C_TMP2, - H2C_TMP3, - H2C_WOWLAN_UPDATE_IV_CMD, /*50*/ - H2C_TMP4, -}; - -/* The following macros are used for FW - * CMD map and parameter updated. */ -#define FW_CMD_IO_CLR(rtlpriv, _Bit) \ - do { \ - udelay(1000); \ - rtlpriv->rtlhal.fwcmd_iomap &= (~_Bit); \ - } while (0) - -#define FW_CMD_IO_UPDATE(rtlpriv, _val) \ - rtlpriv->rtlhal.fwcmd_iomap = _val; - -#define FW_CMD_IO_SET(rtlpriv, _val) \ - do { \ - rtl_write_word(rtlpriv, LBUS_MON_ADDR, (u16)_val); \ - FW_CMD_IO_UPDATE(rtlpriv, _val); \ - } while (0) - -#define FW_CMD_PARA_SET(rtlpriv, _val) \ - do { \ - rtl_write_dword(rtlpriv, LBUS_ADDR_MASK, _val); \ - rtlpriv->rtlhal.fwcmd_ioparam = _val; \ - } while (0) - -#define FW_CMD_IO_QUERY(rtlpriv) \ - (u16)(rtlpriv->rtlhal.fwcmd_iomap) -#define FW_CMD_IO_PARA_QUERY(rtlpriv) \ - ((u32)(rtlpriv->rtlhal.fwcmd_ioparam)) - -int rtl92s_download_fw(struct ieee80211_hw *hw); -void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); -void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, - u8 mstatus, u8 ps_qosinfo); - -#endif - diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c deleted file mode 100644 index 12b0978ba4fa..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ /dev/null @@ -1,2548 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../efuse.h" -#include "../base.h" -#include "../regd.h" -#include "../cam.h" -#include "../ps.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "fw.h" -#include "led.h" -#include "hw.h" - -void rtl92se_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - switch (variable) { - case HW_VAR_RCR: { - *((u32 *) (val)) = rtlpci->receive_config; - break; - } - case HW_VAR_RF_STATE: { - *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; - break; - } - case HW_VAR_FW_PSMODE_STATUS: { - *((bool *) (val)) = ppsc->fw_current_inpsmode; - break; - } - case HW_VAR_CORRECT_TSF: { - u64 tsf; - u32 *ptsf_low = (u32 *)&tsf; - u32 *ptsf_high = ((u32 *)&tsf) + 1; - - *ptsf_high = rtl_read_dword(rtlpriv, (TSFR + 4)); - *ptsf_low = rtl_read_dword(rtlpriv, TSFR); - - *((u64 *) (val)) = tsf; - - break; - } - case HW_VAR_MRC: { - *((bool *)(val)) = rtlpriv->dm.current_mrc_switch; - break; - } - default: { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - } -} - -void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - switch (variable) { - case HW_VAR_ETHER_ADDR:{ - rtl_write_dword(rtlpriv, IDR0, ((u32 *)(val))[0]); - rtl_write_word(rtlpriv, IDR4, ((u16 *)(val + 4))[0]); - break; - } - case HW_VAR_BASIC_RATE:{ - u16 rate_cfg = ((u16 *) val)[0]; - u8 rate_index = 0; - - if (rtlhal->version == VERSION_8192S_ACUT) - rate_cfg = rate_cfg & 0x150; - else - rate_cfg = rate_cfg & 0x15f; - - rate_cfg |= 0x01; - - rtl_write_byte(rtlpriv, RRSR, rate_cfg & 0xff); - rtl_write_byte(rtlpriv, RRSR + 1, - (rate_cfg >> 8) & 0xff); - - while (rate_cfg > 0x1) { - rate_cfg = (rate_cfg >> 1); - rate_index++; - } - rtl_write_byte(rtlpriv, INIRTSMCS_SEL, rate_index); - - break; - } - case HW_VAR_BSSID:{ - rtl_write_dword(rtlpriv, BSSIDR, ((u32 *)(val))[0]); - rtl_write_word(rtlpriv, BSSIDR + 4, - ((u16 *)(val + 4))[0]); - break; - } - case HW_VAR_SIFS:{ - rtl_write_byte(rtlpriv, SIFS_OFDM, val[0]); - rtl_write_byte(rtlpriv, SIFS_OFDM + 1, val[1]); - break; - } - case HW_VAR_SLOT_TIME:{ - u8 e_aci; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "HW_VAR_SLOT_TIME %x\n", val[0]); - - rtl_write_byte(rtlpriv, SLOT_TIME, val[0]); - - for (e_aci = 0; e_aci < AC_MAX; e_aci++) { - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AC_PARAM, - (&e_aci)); - } - break; - } - case HW_VAR_ACK_PREAMBLE:{ - u8 reg_tmp; - u8 short_preamble = (bool) (*val); - reg_tmp = (mac->cur_40_prime_sc) << 5; - if (short_preamble) - reg_tmp |= 0x80; - - rtl_write_byte(rtlpriv, RRSR + 2, reg_tmp); - break; - } - case HW_VAR_AMPDU_MIN_SPACE:{ - u8 min_spacing_to_set; - u8 sec_min_space; - - min_spacing_to_set = *val; - if (min_spacing_to_set <= 7) { - if (rtlpriv->sec.pairwise_enc_algorithm == - NO_ENCRYPTION) - sec_min_space = 0; - else - sec_min_space = 1; - - if (min_spacing_to_set < sec_min_space) - min_spacing_to_set = sec_min_space; - if (min_spacing_to_set > 5) - min_spacing_to_set = 5; - - mac->min_space_cfg = - ((mac->min_space_cfg & 0xf8) | - min_spacing_to_set); - - *val = min_spacing_to_set; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", - mac->min_space_cfg); - - rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, - mac->min_space_cfg); - } - break; - } - case HW_VAR_SHORTGI_DENSITY:{ - u8 density_to_set; - - density_to_set = *val; - mac->min_space_cfg = rtlpriv->rtlhal.minspace_cfg; - mac->min_space_cfg |= (density_to_set << 3); - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_SHORTGI_DENSITY: %#x\n", - mac->min_space_cfg); - - rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, - mac->min_space_cfg); - - break; - } - case HW_VAR_AMPDU_FACTOR:{ - u8 factor_toset; - u8 regtoset; - u8 factorlevel[18] = { - 2, 4, 4, 7, 7, 13, 13, - 13, 2, 7, 7, 13, 13, - 15, 15, 15, 15, 0}; - u8 index = 0; - - factor_toset = *val; - if (factor_toset <= 3) { - factor_toset = (1 << (factor_toset + 2)); - if (factor_toset > 0xf) - factor_toset = 0xf; - - for (index = 0; index < 17; index++) { - if (factorlevel[index] > factor_toset) - factorlevel[index] = - factor_toset; - } - - for (index = 0; index < 8; index++) { - regtoset = ((factorlevel[index * 2]) | - (factorlevel[index * - 2 + 1] << 4)); - rtl_write_byte(rtlpriv, - AGGLEN_LMT_L + index, - regtoset); - } - - regtoset = ((factorlevel[16]) | - (factorlevel[17] << 4)); - rtl_write_byte(rtlpriv, AGGLEN_LMT_H, regtoset); - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_FACTOR: %#x\n", - factor_toset); - } - break; - } - case HW_VAR_AC_PARAM:{ - u8 e_aci = *val; - rtl92s_dm_init_edca_turbo(hw); - - if (rtlpci->acm_method != EACMWAY2_SW) - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_ACM_CTRL, - &e_aci); - break; - } - case HW_VAR_ACM_CTRL:{ - u8 e_aci = *val; - union aci_aifsn *p_aci_aifsn = (union aci_aifsn *)(&( - mac->ac[0].aifs)); - u8 acm = p_aci_aifsn->f.acm; - u8 acm_ctrl = rtl_read_byte(rtlpriv, AcmHwCtrl); - - acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? - 0x0 : 0x1); - - if (acm) { - switch (e_aci) { - case AC0_BE: - acm_ctrl |= AcmHw_BeqEn; - break; - case AC2_VI: - acm_ctrl |= AcmHw_ViqEn; - break; - case AC3_VO: - acm_ctrl |= AcmHw_VoqEn; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", - acm); - break; - } - } else { - switch (e_aci) { - case AC0_BE: - acm_ctrl &= (~AcmHw_BeqEn); - break; - case AC2_VI: - acm_ctrl &= (~AcmHw_ViqEn); - break; - case AC3_VO: - acm_ctrl &= (~AcmHw_VoqEn); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - } - - RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, - "HW_VAR_ACM_CTRL Write 0x%X\n", acm_ctrl); - rtl_write_byte(rtlpriv, AcmHwCtrl, acm_ctrl); - break; - } - case HW_VAR_RCR:{ - rtl_write_dword(rtlpriv, RCR, ((u32 *) (val))[0]); - rtlpci->receive_config = ((u32 *) (val))[0]; - break; - } - case HW_VAR_RETRY_LIMIT:{ - u8 retry_limit = val[0]; - - rtl_write_word(rtlpriv, RETRY_LIMIT, - retry_limit << RETRY_LIMIT_SHORT_SHIFT | - retry_limit << RETRY_LIMIT_LONG_SHIFT); - break; - } - case HW_VAR_DUAL_TSF_RST: { - break; - } - case HW_VAR_EFUSE_BYTES: { - rtlefuse->efuse_usedbytes = *((u16 *) val); - break; - } - case HW_VAR_EFUSE_USAGE: { - rtlefuse->efuse_usedpercentage = *val; - break; - } - case HW_VAR_IO_CMD: { - break; - } - case HW_VAR_WPA_CONFIG: { - rtl_write_byte(rtlpriv, REG_SECR, *val); - break; - } - case HW_VAR_SET_RPWM:{ - break; - } - case HW_VAR_H2C_FW_PWRMODE:{ - break; - } - case HW_VAR_FW_PSMODE_STATUS: { - ppsc->fw_current_inpsmode = *((bool *) val); - break; - } - case HW_VAR_H2C_FW_JOINBSSRPT:{ - break; - } - case HW_VAR_AID:{ - break; - } - case HW_VAR_CORRECT_TSF:{ - break; - } - case HW_VAR_MRC: { - bool bmrc_toset = *((bool *)val); - u8 u1bdata = 0; - - if (bmrc_toset) { - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, - MASKBYTE0, 0x33); - u1bdata = (u8)rtl_get_bbreg(hw, - ROFDM1_TRXPATHENABLE, - MASKBYTE0); - rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, - MASKBYTE0, - ((u1bdata & 0xf0) | 0x03)); - u1bdata = (u8)rtl_get_bbreg(hw, - ROFDM0_TRXPATHENABLE, - MASKBYTE1); - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, - MASKBYTE1, - (u1bdata | 0x04)); - - /* Update current settings. */ - rtlpriv->dm.current_mrc_switch = bmrc_toset; - } else { - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, - MASKBYTE0, 0x13); - u1bdata = (u8)rtl_get_bbreg(hw, - ROFDM1_TRXPATHENABLE, - MASKBYTE0); - rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, - MASKBYTE0, - ((u1bdata & 0xf0) | 0x01)); - u1bdata = (u8)rtl_get_bbreg(hw, - ROFDM0_TRXPATHENABLE, - MASKBYTE1); - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, - MASKBYTE1, (u1bdata & 0xfb)); - - /* Update current settings. */ - rtlpriv->dm.current_mrc_switch = bmrc_toset; - } - - break; - } - case HW_VAR_FW_LPS_ACTION: { - bool enter_fwlps = *((bool *)val); - u8 rpwm_val, fw_pwrmode; - bool fw_current_inps; - - if (enter_fwlps) { - rpwm_val = 0x02; /* RF off */ - fw_current_inps = true; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_PWRMODE, - &ppsc->fwctrl_psmode); - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - &rpwm_val); - } else { - rpwm_val = 0x0C; /* RF on */ - fw_pwrmode = FW_PS_ACTIVE_MODE; - fw_current_inps = false; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - &rpwm_val); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - &fw_pwrmode); - - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - } - break; } - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - -} - -void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 sec_reg_value = 0x0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", - rtlpriv->sec.pairwise_enc_algorithm, - rtlpriv->sec.group_enc_algorithm); - - if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "not open hw encryption\n"); - return; - } - - sec_reg_value = SCR_TXENCENABLE | SCR_RXENCENABLE; - - if (rtlpriv->sec.use_defaultkey) { - sec_reg_value |= SCR_TXUSEDK; - sec_reg_value |= SCR_RXUSEDK; - } - - RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "The SECR-value %x\n", - sec_reg_value); - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); - -} - -static u8 _rtl92se_halset_sysclk(struct ieee80211_hw *hw, u8 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 waitcount = 100; - bool bresult = false; - u8 tmpvalue; - - rtl_write_byte(rtlpriv, SYS_CLKR + 1, data); - - /* Wait the MAC synchronized. */ - udelay(400); - - /* Check if it is set ready. */ - tmpvalue = rtl_read_byte(rtlpriv, SYS_CLKR + 1); - bresult = ((tmpvalue & BIT(7)) == (data & BIT(7))); - - if ((data & (BIT(6) | BIT(7))) == false) { - waitcount = 100; - tmpvalue = 0; - - while (1) { - waitcount--; - - tmpvalue = rtl_read_byte(rtlpriv, SYS_CLKR + 1); - if ((tmpvalue & BIT(6))) - break; - - pr_err("wait for BIT(6) return value %x\n", tmpvalue); - if (waitcount == 0) - break; - - udelay(10); - } - - if (waitcount == 0) - bresult = false; - else - bresult = true; - } - - return bresult; -} - -void rtl8192se_gpiobit3_cfg_inputmode(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 u1tmp; - - /* The following config GPIO function */ - rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); - u1tmp = rtl_read_byte(rtlpriv, GPIO_IO_SEL); - - /* config GPIO3 to input */ - u1tmp &= HAL_8192S_HW_GPIO_OFF_MASK; - rtl_write_byte(rtlpriv, GPIO_IO_SEL, u1tmp); - -} - -static u8 _rtl92se_rf_onoff_detect(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 u1tmp; - u8 retval = ERFON; - - /* The following config GPIO function */ - rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); - u1tmp = rtl_read_byte(rtlpriv, GPIO_IO_SEL); - - /* config GPIO3 to input */ - u1tmp &= HAL_8192S_HW_GPIO_OFF_MASK; - rtl_write_byte(rtlpriv, GPIO_IO_SEL, u1tmp); - - /* On some of the platform, driver cannot read correct - * value without delay between Write_GPIO_SEL and Read_GPIO_IN */ - mdelay(10); - - /* check GPIO3 */ - u1tmp = rtl_read_byte(rtlpriv, GPIO_IN_SE); - retval = (u1tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? ERFON : ERFOFF; - - return retval; -} - -static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - u8 i; - u8 tmpu1b; - u16 tmpu2b; - u8 pollingcnt = 20; - - if (rtlpci->first_init) { - /* Reset PCIE Digital */ - tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - tmpu1b &= 0xFE; - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b); - udelay(1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b | BIT(0)); - } - - /* Switch to SW IO control */ - tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); - if (tmpu1b & BIT(7)) { - tmpu1b &= ~(BIT(6) | BIT(7)); - - /* Set failed, return to prevent hang. */ - if (!_rtl92se_halset_sysclk(hw, tmpu1b)) - return; - } - - rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x0); - udelay(50); - rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); - udelay(50); - - /* Clear FW RPWM for FW control LPS.*/ - rtl_write_byte(rtlpriv, RPWM, 0x0); - - /* Reset MAC-IO and CPU and Core Digital BIT(10)/11/15 */ - tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - tmpu1b &= 0x73; - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b); - /* wait for BIT 10/11/15 to pull high automatically!! */ - mdelay(1); - - rtl_write_byte(rtlpriv, CMDR, 0); - rtl_write_byte(rtlpriv, TCR, 0); - - /* Data sheet not define 0x562!!! Copy from WMAC!!!!! */ - tmpu1b = rtl_read_byte(rtlpriv, 0x562); - tmpu1b |= 0x08; - rtl_write_byte(rtlpriv, 0x562, tmpu1b); - tmpu1b &= ~(BIT(3)); - rtl_write_byte(rtlpriv, 0x562, tmpu1b); - - /* Enable AFE clock source */ - tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL); - rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, (tmpu1b | 0x01)); - /* Delay 1.5ms */ - mdelay(2); - tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL + 1); - rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, (tmpu1b & 0xfb)); - - /* Enable AFE Macro Block's Bandgap */ - tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); - rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | BIT(0))); - mdelay(1); - - /* Enable AFE Mbias */ - tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); - rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | 0x02)); - mdelay(1); - - /* Enable LDOA15 block */ - tmpu1b = rtl_read_byte(rtlpriv, LDOA15_CTRL); - rtl_write_byte(rtlpriv, LDOA15_CTRL, (tmpu1b | BIT(0))); - - /* Set Digital Vdd to Retention isolation Path. */ - tmpu2b = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL); - rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, (tmpu2b | BIT(11))); - - /* For warm reboot NIC disappera bug. */ - tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(13))); - - rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x68); - - /* Enable AFE PLL Macro Block */ - /* We need to delay 100u before enabling PLL. */ - udelay(200); - tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL); - rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); - - /* for divider reset */ - udelay(100); - rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | - BIT(4) | BIT(6))); - udelay(10); - rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); - udelay(10); - - /* Enable MAC 80MHZ clock */ - tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL + 1); - rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, (tmpu1b | BIT(0))); - mdelay(1); - - /* Release isolation AFE PLL & MD */ - rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xA6); - - /* Enable MAC clock */ - tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); - rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b | BIT(12) | BIT(11))); - - /* Enable Core digital and enable IOREG R/W */ - tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11))); - - tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b & ~(BIT(7))); - - /* enable REG_EN */ - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15))); - - /* Switch the control path. */ - tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); - rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b & (~BIT(2)))); - - tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); - tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); - if (!_rtl92se_halset_sysclk(hw, tmpu1b)) - return; /* Set failed, return to prevent hang. */ - - rtl_write_word(rtlpriv, CMDR, 0x07FC); - - /* MH We must enable the section of code to prevent load IMEM fail. */ - /* Load MAC register from WMAc temporarily We simulate macreg. */ - /* txt HW will provide MAC txt later */ - rtl_write_byte(rtlpriv, 0x6, 0x30); - rtl_write_byte(rtlpriv, 0x49, 0xf0); - - rtl_write_byte(rtlpriv, 0x4b, 0x81); - - rtl_write_byte(rtlpriv, 0xb5, 0x21); - - rtl_write_byte(rtlpriv, 0xdc, 0xff); - rtl_write_byte(rtlpriv, 0xdd, 0xff); - rtl_write_byte(rtlpriv, 0xde, 0xff); - rtl_write_byte(rtlpriv, 0xdf, 0xff); - - rtl_write_byte(rtlpriv, 0x11a, 0x00); - rtl_write_byte(rtlpriv, 0x11b, 0x00); - - for (i = 0; i < 32; i++) - rtl_write_byte(rtlpriv, INIMCS_SEL + i, 0x1b); - - rtl_write_byte(rtlpriv, 0x236, 0xff); - - rtl_write_byte(rtlpriv, 0x503, 0x22); - - if (ppsc->support_aspm && !ppsc->support_backdoor) - rtl_write_byte(rtlpriv, 0x560, 0x40); - else - rtl_write_byte(rtlpriv, 0x560, 0x00); - - rtl_write_byte(rtlpriv, DBG_PORT, 0x91); - - /* Set RX Desc Address */ - rtl_write_dword(rtlpriv, RDQDA, rtlpci->rx_ring[RX_MPDU_QUEUE].dma); - rtl_write_dword(rtlpriv, RCDA, rtlpci->rx_ring[RX_CMD_QUEUE].dma); - - /* Set TX Desc Address */ - rtl_write_dword(rtlpriv, TBKDA, rtlpci->tx_ring[BK_QUEUE].dma); - rtl_write_dword(rtlpriv, TBEDA, rtlpci->tx_ring[BE_QUEUE].dma); - rtl_write_dword(rtlpriv, TVIDA, rtlpci->tx_ring[VI_QUEUE].dma); - rtl_write_dword(rtlpriv, TVODA, rtlpci->tx_ring[VO_QUEUE].dma); - rtl_write_dword(rtlpriv, TBDA, rtlpci->tx_ring[BEACON_QUEUE].dma); - rtl_write_dword(rtlpriv, TCDA, rtlpci->tx_ring[TXCMD_QUEUE].dma); - rtl_write_dword(rtlpriv, TMDA, rtlpci->tx_ring[MGNT_QUEUE].dma); - rtl_write_dword(rtlpriv, THPDA, rtlpci->tx_ring[HIGH_QUEUE].dma); - rtl_write_dword(rtlpriv, HDA, rtlpci->tx_ring[HCCA_QUEUE].dma); - - rtl_write_word(rtlpriv, CMDR, 0x37FC); - - /* To make sure that TxDMA can ready to download FW. */ - /* We should reset TxDMA if IMEM RPT was not ready. */ - do { - tmpu1b = rtl_read_byte(rtlpriv, TCR); - if ((tmpu1b & TXDMA_INIT_VALUE) == TXDMA_INIT_VALUE) - break; - - udelay(5); - } while (pollingcnt--); - - if (pollingcnt <= 0) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Polling TXDMA_INIT_VALUE timeout!! Current TCR(%#x)\n", - tmpu1b); - tmpu1b = rtl_read_byte(rtlpriv, CMDR); - rtl_write_byte(rtlpriv, CMDR, tmpu1b & (~TXDMA_EN)); - udelay(2); - /* Reset TxDMA */ - rtl_write_byte(rtlpriv, CMDR, tmpu1b | TXDMA_EN); - } - - /* After MACIO reset,we must refresh LED state. */ - if ((ppsc->rfoff_reason == RF_CHANGE_BY_IPS) || - (ppsc->rfoff_reason == 0)) { - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); - enum rf_pwrstate rfpwr_state_toset; - rfpwr_state_toset = _rtl92se_rf_onoff_detect(hw); - - if (rfpwr_state_toset == ERFON) - rtl92se_sw_led_on(hw, pLed0); - } -} - -static void _rtl92se_macconfig_after_fwdownload(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 i; - u16 tmpu2b; - - /* 1. System Configure Register (Offset: 0x0000 - 0x003F) */ - - /* 2. Command Control Register (Offset: 0x0040 - 0x004F) */ - /* Turn on 0x40 Command register */ - rtl_write_word(rtlpriv, CMDR, (BBRSTN | BB_GLB_RSTN | - SCHEDULE_EN | MACRXEN | MACTXEN | DDMA_EN | FW2HW_EN | - RXDMA_EN | TXDMA_EN | HCI_RXDMA_EN | HCI_TXDMA_EN)); - - /* Set TCR TX DMA pre 2 FULL enable bit */ - rtl_write_dword(rtlpriv, TCR, rtl_read_dword(rtlpriv, TCR) | - TXDMAPRE2FULL); - - /* Set RCR */ - rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config); - - /* 3. MACID Setting Register (Offset: 0x0050 - 0x007F) */ - - /* 4. Timing Control Register (Offset: 0x0080 - 0x009F) */ - /* Set CCK/OFDM SIFS */ - /* CCK SIFS shall always be 10us. */ - rtl_write_word(rtlpriv, SIFS_CCK, 0x0a0a); - rtl_write_word(rtlpriv, SIFS_OFDM, 0x1010); - - /* Set AckTimeout */ - rtl_write_byte(rtlpriv, ACK_TIMEOUT, 0x40); - - /* Beacon related */ - rtl_write_word(rtlpriv, BCN_INTERVAL, 100); - rtl_write_word(rtlpriv, ATIMWND, 2); - - /* 5. FIFO Control Register (Offset: 0x00A0 - 0x015F) */ - /* 5.1 Initialize Number of Reserved Pages in Firmware Queue */ - /* Firmware allocate now, associate with FW internal setting.!!! */ - - /* 5.2 Setting TX/RX page size 0/1/2/3/4=64/128/256/512/1024 */ - /* 5.3 Set driver info, we only accept PHY status now. */ - /* 5.4 Set RXDMA arbitration to control RXDMA/MAC/FW R/W for RXFIFO */ - rtl_write_byte(rtlpriv, RXDMA, rtl_read_byte(rtlpriv, RXDMA) | BIT(6)); - - /* 6. Adaptive Control Register (Offset: 0x0160 - 0x01CF) */ - /* Set RRSR to all legacy rate and HT rate - * CCK rate is supported by default. - * CCK rate will be filtered out only when associated - * AP does not support it. - * Only enable ACK rate to OFDM 24M - * Disable RRSR for CCK rate in A-Cut */ - - if (rtlhal->version == VERSION_8192S_ACUT) - rtl_write_byte(rtlpriv, RRSR, 0xf0); - else if (rtlhal->version == VERSION_8192S_BCUT) - rtl_write_byte(rtlpriv, RRSR, 0xff); - rtl_write_byte(rtlpriv, RRSR + 1, 0x01); - rtl_write_byte(rtlpriv, RRSR + 2, 0x00); - - /* A-Cut IC do not support CCK rate. We forbid ARFR to */ - /* fallback to CCK rate */ - for (i = 0; i < 8; i++) { - /*Disable RRSR for CCK rate in A-Cut */ - if (rtlhal->version == VERSION_8192S_ACUT) - rtl_write_dword(rtlpriv, ARFR0 + i * 4, 0x1f0ff0f0); - } - - /* Different rate use different AMPDU size */ - /* MCS32/ MCS15_SG use max AMPDU size 15*2=30K */ - rtl_write_byte(rtlpriv, AGGLEN_LMT_H, 0x0f); - /* MCS0/1/2/3 use max AMPDU size 4*2=8K */ - rtl_write_word(rtlpriv, AGGLEN_LMT_L, 0x7442); - /* MCS4/5 use max AMPDU size 8*2=16K 6/7 use 10*2=20K */ - rtl_write_word(rtlpriv, AGGLEN_LMT_L + 2, 0xddd7); - /* MCS8/9 use max AMPDU size 8*2=16K 10/11 use 10*2=20K */ - rtl_write_word(rtlpriv, AGGLEN_LMT_L + 4, 0xd772); - /* MCS12/13/14/15 use max AMPDU size 15*2=30K */ - rtl_write_word(rtlpriv, AGGLEN_LMT_L + 6, 0xfffd); - - /* Set Data / Response auto rate fallack retry count */ - rtl_write_dword(rtlpriv, DARFRC, 0x04010000); - rtl_write_dword(rtlpriv, DARFRC + 4, 0x09070605); - rtl_write_dword(rtlpriv, RARFRC, 0x04010000); - rtl_write_dword(rtlpriv, RARFRC + 4, 0x09070605); - - /* 7. EDCA Setting Register (Offset: 0x01D0 - 0x01FF) */ - /* Set all rate to support SG */ - rtl_write_word(rtlpriv, SG_RATE, 0xFFFF); - - /* 8. WMAC, BA, and CCX related Register (Offset: 0x0200 - 0x023F) */ - /* Set NAV protection length */ - rtl_write_word(rtlpriv, NAV_PROT_LEN, 0x0080); - /* CF-END Threshold */ - rtl_write_byte(rtlpriv, CFEND_TH, 0xFF); - /* Set AMPDU minimum space */ - rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, 0x07); - /* Set TXOP stall control for several queue/HI/BCN/MGT/ */ - rtl_write_byte(rtlpriv, TXOP_STALL_CTRL, 0x00); - - /* 9. Security Control Register (Offset: 0x0240 - 0x025F) */ - /* 10. Power Save Control Register (Offset: 0x0260 - 0x02DF) */ - /* 11. General Purpose Register (Offset: 0x02E0 - 0x02FF) */ - /* 12. Host Interrupt Status Register (Offset: 0x0300 - 0x030F) */ - /* 13. Test Mode and Debug Control Register (Offset: 0x0310 - 0x034F) */ - - /* 14. Set driver info, we only accept PHY status now. */ - rtl_write_byte(rtlpriv, RXDRVINFO_SZ, 4); - - /* 15. For EEPROM R/W Workaround */ - /* 16. For EFUSE to share REG_SYS_FUNC_EN with EEPROM!!! */ - tmpu2b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, tmpu2b | BIT(13)); - tmpu2b = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL); - rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, tmpu2b & (~BIT(8))); - - /* 17. For EFUSE */ - /* We may R/W EFUSE in EEPROM mode */ - if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { - u8 tempval; - - tempval = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL + 1); - tempval &= 0xFE; - rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, tempval); - - /* Change Program timing */ - rtl_write_byte(rtlpriv, REG_EFUSE_CTRL + 3, 0x72); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "EFUSE CONFIG OK\n"); - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "OK\n"); - -} - -static void _rtl92se_hw_configure(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - u8 reg_bw_opmode = 0; - u32 reg_rrsr = 0; - u8 regtmp = 0; - - reg_bw_opmode = BW_OPMODE_20MHZ; - reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - - regtmp = rtl_read_byte(rtlpriv, INIRTSMCS_SEL); - reg_rrsr = ((reg_rrsr & 0x000fffff) << 8) | regtmp; - rtl_write_dword(rtlpriv, INIRTSMCS_SEL, reg_rrsr); - rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); - - /* Set Retry Limit here */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT, - (u8 *)(&rtlpci->shortretry_limit)); - - rtl_write_byte(rtlpriv, MLT, 0x8f); - - /* For Min Spacing configuration. */ - switch (rtlphy->rf_type) { - case RF_1T2R: - case RF_1T1R: - rtlhal->minspace_cfg = (MAX_MSS_DENSITY_1T << 3); - break; - case RF_2T2R: - case RF_2T2R_GREEN: - rtlhal->minspace_cfg = (MAX_MSS_DENSITY_2T << 3); - break; - } - rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, rtlhal->minspace_cfg); -} - -int rtl92se_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 tmp_byte = 0; - unsigned long flags; - bool rtstatus = true; - u8 tmp_u1b; - int err = false; - u8 i; - int wdcapra_add[] = { - EDCAPARA_BE, EDCAPARA_BK, - EDCAPARA_VI, EDCAPARA_VO}; - u8 secr_value = 0x0; - - rtlpci->being_init_adapter = true; - - /* As this function can take a very long time (up to 350 ms) - * and can be called with irqs disabled, reenable the irqs - * to let the other devices continue being serviced. - * - * It is safe doing so since our own interrupts will only be enabled - * in a subsequent step. - */ - local_save_flags(flags); - local_irq_enable(); - - rtlpriv->intf_ops->disable_aspm(hw); - - /* 1. MAC Initialize */ - /* Before FW download, we have to set some MAC register */ - _rtl92se_macconfig_before_fwdownload(hw); - - rtlhal->version = (enum version_8192s)((rtl_read_dword(rtlpriv, - PMC_FSM) >> 16) & 0xF); - - rtl8192se_gpiobit3_cfg_inputmode(hw); - - /* 2. download firmware */ - rtstatus = rtl92s_download_fw(hw); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Failed to download FW. Init HW without FW now... " - "Please copy FW into /lib/firmware/rtlwifi\n"); - err = 1; - goto exit; - } - - /* After FW download, we have to reset MAC register */ - _rtl92se_macconfig_after_fwdownload(hw); - - /*Retrieve default FW Cmd IO map. */ - rtlhal->fwcmd_iomap = rtl_read_word(rtlpriv, LBUS_MON_ADDR); - rtlhal->fwcmd_ioparam = rtl_read_dword(rtlpriv, LBUS_ADDR_MASK); - - /* 3. Initialize MAC/PHY Config by MACPHY_reg.txt */ - if (!rtl92s_phy_mac_config(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "MAC Config failed\n"); - err = rtstatus; - goto exit; - } - - /* because last function modify RCR, so we update - * rcr var here, or TP will unstable for receive_config - * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx - * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 - */ - rtlpci->receive_config = rtl_read_dword(rtlpriv, RCR); - rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); - rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config); - - /* Make sure BB/RF write OK. We should prevent enter IPS. radio off. */ - /* We must set flag avoid BB/RF config period later!! */ - rtl_write_dword(rtlpriv, CMDR, 0x37FC); - - /* 4. Initialize BB After MAC Config PHY_reg.txt, AGC_Tab.txt */ - if (!rtl92s_phy_bb_config(hw)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, "BB Config failed\n"); - err = rtstatus; - goto exit; - } - - /* 5. Initiailze RF RAIO_A.txt RF RAIO_B.txt */ - /* Before initalizing RF. We can not use FW to do RF-R/W. */ - - rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; - - /* Before RF-R/W we must execute the IO from Scott's suggestion. */ - rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, 0xDB); - if (rtlhal->version == VERSION_8192S_ACUT) - rtl_write_byte(rtlpriv, SPS1_CTRL + 3, 0x07); - else - rtl_write_byte(rtlpriv, RF_CTRL, 0x07); - - if (!rtl92s_phy_rf_config(hw)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "RF Config failed\n"); - err = rtstatus; - goto exit; - } - - /* After read predefined TXT, we must set BB/MAC/RF - * register as our requirement */ - - rtlphy->rfreg_chnlval[0] = rtl92s_phy_query_rf_reg(hw, - (enum radio_path)0, - RF_CHNLBW, - RFREG_OFFSET_MASK); - rtlphy->rfreg_chnlval[1] = rtl92s_phy_query_rf_reg(hw, - (enum radio_path)1, - RF_CHNLBW, - RFREG_OFFSET_MASK); - - /*---- Set CCK and OFDM Block "ON"----*/ - rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); - - /*3 Set Hardware(Do nothing now) */ - _rtl92se_hw_configure(hw); - - /* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */ - /* TX power index for different rate set. */ - /* Get original hw reg values */ - rtl92s_phy_get_hw_reg_originalvalue(hw); - /* Write correct tx power index */ - rtl92s_phy_set_txpower(hw, rtlphy->current_channel); - - /* We must set MAC address after firmware download. */ - for (i = 0; i < 6; i++) - rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]); - - /* EEPROM R/W workaround */ - tmp_u1b = rtl_read_byte(rtlpriv, MAC_PINMUX_CFG); - rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, tmp_u1b & (~BIT(3))); - - rtl_write_byte(rtlpriv, 0x4d, 0x0); - - if (hal_get_firmwareversion(rtlpriv) >= 0x49) { - tmp_byte = rtl_read_byte(rtlpriv, FW_RSVD_PG_CRTL) & (~BIT(4)); - tmp_byte = tmp_byte | BIT(5); - rtl_write_byte(rtlpriv, FW_RSVD_PG_CRTL, tmp_byte); - rtl_write_dword(rtlpriv, TXDESC_MSK, 0xFFFFCFFF); - } - - /* We enable high power and RA related mechanism after NIC - * initialized. */ - if (hal_get_firmwareversion(rtlpriv) >= 0x35) { - /* Fw v.53 and later. */ - rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT); - } else if (hal_get_firmwareversion(rtlpriv) == 0x34) { - /* Fw v.52. */ - rtl_write_dword(rtlpriv, WFM5, FW_RA_INIT); - rtl92s_phy_chk_fwcmd_iodone(hw); - } else { - /* Compatible earlier FW version. */ - rtl_write_dword(rtlpriv, WFM5, FW_RA_RESET); - rtl92s_phy_chk_fwcmd_iodone(hw); - rtl_write_dword(rtlpriv, WFM5, FW_RA_ACTIVE); - rtl92s_phy_chk_fwcmd_iodone(hw); - rtl_write_dword(rtlpriv, WFM5, FW_RA_REFRESH); - rtl92s_phy_chk_fwcmd_iodone(hw); - } - - /* Add to prevent ASPM bug. */ - /* Always enable hst and NIC clock request. */ - rtl92s_phy_switch_ephy_parameter(hw); - - /* Security related - * 1. Clear all H/W keys. - * 2. Enable H/W encryption/decryption. */ - rtl_cam_reset_all_entry(hw); - secr_value |= SCR_TXENCENABLE; - secr_value |= SCR_RXENCENABLE; - secr_value |= SCR_NOSKMC; - rtl_write_byte(rtlpriv, REG_SECR, secr_value); - - for (i = 0; i < 4; i++) - rtl_write_dword(rtlpriv, wdcapra_add[i], 0x5e4322); - - if (rtlphy->rf_type == RF_1T2R) { - bool mrc2set = true; - /* Turn on B-Path */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC, (u8 *)&mrc2set); - } - - rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_ON); - rtl92s_dm_init(hw); -exit: - local_irq_restore(flags); - rtlpci->being_init_adapter = false; - return err; -} - -void rtl92se_set_mac_addr(struct rtl_io *io, const u8 *addr) -{ - /* This is a stub. */ -} - -void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 reg_rcr; - - if (rtlpriv->psc.rfpwr_state != ERFON) - return; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); - - if (check_bssid) { - reg_rcr |= (RCR_CBSSID); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); - } else if (!check_bssid) { - reg_rcr &= (~RCR_CBSSID); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); - } - -} - -static int _rtl92se_set_media_status(struct ieee80211_hw *hw, - enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bt_msr = rtl_read_byte(rtlpriv, MSR); - u32 temp; - bt_msr &= ~MSR_LINK_MASK; - - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - bt_msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to NO LINK!\n"); - break; - case NL80211_IFTYPE_ADHOC: - bt_msr |= (MSR_LINK_ADHOC << MSR_LINK_SHIFT); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to Ad Hoc!\n"); - break; - case NL80211_IFTYPE_STATION: - bt_msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to STA!\n"); - break; - case NL80211_IFTYPE_AP: - bt_msr |= (MSR_LINK_MASTER << MSR_LINK_SHIFT); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to AP!\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Network type %d not supported!\n", type); - return 1; - - } - - if (type != NL80211_IFTYPE_AP && - rtlpriv->mac80211.link_state < MAC80211_LINKED) - bt_msr = rtl_read_byte(rtlpriv, MSR) & ~MSR_LINK_MASK; - rtl_write_byte(rtlpriv, MSR, bt_msr); - - temp = rtl_read_dword(rtlpriv, TCR); - rtl_write_dword(rtlpriv, TCR, temp & (~BIT(8))); - rtl_write_dword(rtlpriv, TCR, temp | BIT(8)); - - - return 0; -} - -/* HW_VAR_MEDIA_STATUS & HW_VAR_CECHK_BSSID */ -int rtl92se_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (_rtl92se_set_media_status(hw, type)) - return -EOPNOTSUPP; - - if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { - if (type != NL80211_IFTYPE_AP) - rtl92se_set_check_bssid(hw, true); - } else { - rtl92se_set_check_bssid(hw, false); - } - - return 0; -} - -/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ -void rtl92se_set_qos(struct ieee80211_hw *hw, int aci) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - rtl92s_dm_init_edca_turbo(hw); - - switch (aci) { - case AC1_BK: - rtl_write_dword(rtlpriv, EDCAPARA_BK, 0xa44f); - break; - case AC0_BE: - /* rtl_write_dword(rtlpriv, EDCAPARA_BE, u4b_ac_param); */ - break; - case AC2_VI: - rtl_write_dword(rtlpriv, EDCAPARA_VI, 0x5e4322); - break; - case AC3_VO: - rtl_write_dword(rtlpriv, EDCAPARA_VO, 0x2f3222); - break; - default: - RT_ASSERT(false, "invalid aci: %d !\n", aci); - break; - } -} - -void rtl92se_enable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]); - /* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */ - rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F); - rtlpci->irq_enabled = true; -} - -void rtl92se_disable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv; - struct rtl_pci *rtlpci; - - rtlpriv = rtl_priv(hw); - /* if firmware not available, no interrupts */ - if (!rtlpriv || !rtlpriv->max_fw_size) - return; - rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - rtl_write_dword(rtlpriv, INTA_MASK, 0); - rtl_write_dword(rtlpriv, INTA_MASK + 4, 0); - rtlpci->irq_enabled = false; -} - -static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 waitcnt = 100; - bool result = false; - u8 tmp; - - rtl_write_byte(rtlpriv, SYS_CLKR + 1, data); - - /* Wait the MAC synchronized. */ - udelay(400); - - /* Check if it is set ready. */ - tmp = rtl_read_byte(rtlpriv, SYS_CLKR + 1); - result = ((tmp & BIT(7)) == (data & BIT(7))); - - if ((data & (BIT(6) | BIT(7))) == false) { - waitcnt = 100; - tmp = 0; - - while (1) { - waitcnt--; - tmp = rtl_read_byte(rtlpriv, SYS_CLKR + 1); - - if ((tmp & BIT(6))) - break; - - pr_err("wait for BIT(6) return value %x\n", tmp); - - if (waitcnt == 0) - break; - udelay(10); - } - - if (waitcnt == 0) - result = false; - else - result = true; - } - - return result; -} - -static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 u1btmp; - - if (rtlhal->driver_going2unload) - rtl_write_byte(rtlpriv, 0x560, 0x0); - - /* Power save for BB/RF */ - u1btmp = rtl_read_byte(rtlpriv, LDOV12D_CTRL); - u1btmp |= BIT(0); - rtl_write_byte(rtlpriv, LDOV12D_CTRL, u1btmp); - rtl_write_byte(rtlpriv, SPS1_CTRL, 0x0); - rtl_write_byte(rtlpriv, TXPAUSE, 0xFF); - rtl_write_word(rtlpriv, CMDR, 0x57FC); - udelay(100); - rtl_write_word(rtlpriv, CMDR, 0x77FC); - rtl_write_byte(rtlpriv, PHY_CCA, 0x0); - udelay(10); - rtl_write_word(rtlpriv, CMDR, 0x37FC); - udelay(10); - rtl_write_word(rtlpriv, CMDR, 0x77FC); - udelay(10); - rtl_write_word(rtlpriv, CMDR, 0x57FC); - rtl_write_word(rtlpriv, CMDR, 0x0000); - - if (rtlhal->driver_going2unload) { - u1btmp = rtl_read_byte(rtlpriv, (REG_SYS_FUNC_EN + 1)); - u1btmp &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1btmp); - } - - u1btmp = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); - - /* Add description. After switch control path. register - * after page1 will be invisible. We can not do any IO - * for register>0x40. After resume&MACIO reset, we need - * to remember previous reg content. */ - if (u1btmp & BIT(7)) { - u1btmp &= ~(BIT(6) | BIT(7)); - if (!_rtl92s_set_sysclk(hw, u1btmp)) { - pr_err("Switch ctrl path fail\n"); - return; - } - } - - /* Power save for MAC */ - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS && - !rtlhal->driver_going2unload) { - /* enable LED function */ - rtl_write_byte(rtlpriv, 0x03, 0xF9); - /* SW/HW radio off or halt adapter!! For example S3/S4 */ - } else { - /* LED function disable. Power range is about 8mA now. */ - /* if write 0xF1 disconnet_pci power - * ifconfig wlan0 down power are both high 35:70 */ - /* if write oxF9 disconnet_pci power - * ifconfig wlan0 down power are both low 12:45*/ - rtl_write_byte(rtlpriv, 0x03, 0xF9); - } - - rtl_write_byte(rtlpriv, SYS_CLKR + 1, 0x70); - rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, 0x68); - rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x00); - rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); - rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, 0x0E); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - -} - -static void _rtl92se_gen_refreshledstate(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); - - if (rtlpci->up_first_time == 1) - return; - - if (rtlpriv->psc.rfoff_reason == RF_CHANGE_BY_IPS) - rtl92se_sw_led_on(hw, pLed0); - else - rtl92se_sw_led_off(hw, pLed0); -} - - -static void _rtl92se_power_domain_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 tmpu2b; - u8 tmpu1b; - - rtlpriv->psc.pwrdomain_protect = true; - - tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); - if (tmpu1b & BIT(7)) { - tmpu1b &= ~(BIT(6) | BIT(7)); - if (!_rtl92s_set_sysclk(hw, tmpu1b)) { - rtlpriv->psc.pwrdomain_protect = false; - return; - } - } - - rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x0); - rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); - - /* Reset MAC-IO and CPU and Core Digital BIT10/11/15 */ - tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - - /* If IPS we need to turn LED on. So we not - * not disable BIT 3/7 of reg3. */ - if (rtlpriv->psc.rfoff_reason & (RF_CHANGE_BY_IPS | RF_CHANGE_BY_HW)) - tmpu1b &= 0xFB; - else - tmpu1b &= 0x73; - - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b); - /* wait for BIT 10/11/15 to pull high automatically!! */ - mdelay(1); - - rtl_write_byte(rtlpriv, CMDR, 0); - rtl_write_byte(rtlpriv, TCR, 0); - - /* Data sheet not define 0x562!!! Copy from WMAC!!!!! */ - tmpu1b = rtl_read_byte(rtlpriv, 0x562); - tmpu1b |= 0x08; - rtl_write_byte(rtlpriv, 0x562, tmpu1b); - tmpu1b &= ~(BIT(3)); - rtl_write_byte(rtlpriv, 0x562, tmpu1b); - - /* Enable AFE clock source */ - tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL); - rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, (tmpu1b | 0x01)); - /* Delay 1.5ms */ - udelay(1500); - tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL + 1); - rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, (tmpu1b & 0xfb)); - - /* Enable AFE Macro Block's Bandgap */ - tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); - rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | BIT(0))); - mdelay(1); - - /* Enable AFE Mbias */ - tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); - rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | 0x02)); - mdelay(1); - - /* Enable LDOA15 block */ - tmpu1b = rtl_read_byte(rtlpriv, LDOA15_CTRL); - rtl_write_byte(rtlpriv, LDOA15_CTRL, (tmpu1b | BIT(0))); - - /* Set Digital Vdd to Retention isolation Path. */ - tmpu2b = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL); - rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, (tmpu2b | BIT(11))); - - - /* For warm reboot NIC disappera bug. */ - tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(13))); - - rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x68); - - /* Enable AFE PLL Macro Block */ - tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL); - rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); - /* Enable MAC 80MHZ clock */ - tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL + 1); - rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, (tmpu1b | BIT(0))); - mdelay(1); - - /* Release isolation AFE PLL & MD */ - rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xA6); - - /* Enable MAC clock */ - tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); - rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b | BIT(12) | BIT(11))); - - /* Enable Core digital and enable IOREG R/W */ - tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11))); - /* enable REG_EN */ - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15))); - - /* Switch the control path. */ - tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); - rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b & (~BIT(2)))); - - tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); - tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); - if (!_rtl92s_set_sysclk(hw, tmpu1b)) { - rtlpriv->psc.pwrdomain_protect = false; - return; - } - - rtl_write_word(rtlpriv, CMDR, 0x37FC); - - /* After MACIO reset,we must refresh LED state. */ - _rtl92se_gen_refreshledstate(hw); - - rtlpriv->psc.pwrdomain_protect = false; -} - -void rtl92se_card_disable(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - enum nl80211_iftype opmode; - u8 wait = 30; - - rtlpriv->intf_ops->enable_aspm(hw); - - if (rtlpci->driver_is_goingto_unload || - ppsc->rfoff_reason > RF_CHANGE_BY_PS) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); - - /* we should chnge GPIO to input mode - * this will drop away current about 25mA*/ - rtl8192se_gpiobit3_cfg_inputmode(hw); - - /* this is very important for ips power save */ - while (wait-- >= 10 && rtlpriv->psc.pwrdomain_protect) { - if (rtlpriv->psc.pwrdomain_protect) - mdelay(20); - else - break; - } - - mac->link_state = MAC80211_NOLINK; - opmode = NL80211_IFTYPE_UNSPECIFIED; - _rtl92se_set_media_status(hw, opmode); - - _rtl92s_phy_set_rfhalt(hw); - udelay(100); -} - -void rtl92se_interrupt_recognized(struct ieee80211_hw *hw, u32 *p_inta, - u32 *p_intb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; - rtl_write_dword(rtlpriv, ISR, *p_inta); - - *p_intb = rtl_read_dword(rtlpriv, ISR + 4) & rtlpci->irq_mask[1]; - rtl_write_dword(rtlpriv, ISR + 4, *p_intb); -} - -void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcntime_cfg = 0; - u16 bcn_cw = 6, bcn_ifs = 0xf; - u16 atim_window = 2; - - /* ATIM Window (in unit of TU). */ - rtl_write_word(rtlpriv, ATIMWND, atim_window); - - /* Beacon interval (in unit of TU). */ - rtl_write_word(rtlpriv, BCN_INTERVAL, mac->beacon_interval); - - /* DrvErlyInt (in unit of TU). (Time to send - * interrupt to notify driver to change - * beacon content) */ - rtl_write_word(rtlpriv, BCN_DRV_EARLY_INT, 10 << 4); - - /* BcnDMATIM(in unit of us). Indicates the - * time before TBTT to perform beacon queue DMA */ - rtl_write_word(rtlpriv, BCN_DMATIME, 256); - - /* Force beacon frame transmission even - * after receiving beacon frame from - * other ad hoc STA */ - rtl_write_byte(rtlpriv, BCN_ERR_THRESH, 100); - - /* Beacon Time Configuration */ - if (mac->opmode == NL80211_IFTYPE_ADHOC) - bcntime_cfg |= (bcn_cw << BCN_TCFG_CW_SHIFT); - - /* TODO: bcn_ifs may required to be changed on ASIC */ - bcntime_cfg |= bcn_ifs << BCN_TCFG_IFS; - - /*for beacon changed */ - rtl92s_phy_set_beacon_hwreg(hw, mac->beacon_interval); -} - -void rtl92se_set_beacon_interval(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval = mac->beacon_interval; - - /* Beacon interval (in unit of TU). */ - rtl_write_word(rtlpriv, BCN_INTERVAL, bcn_interval); - /* 2008.10.24 added by tynli for beacon changed. */ - rtl92s_phy_set_beacon_hwreg(hw, bcn_interval); -} - -void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, "add_msr:%x, rm_msr:%x\n", - add_msr, rm_msr); - - if (add_msr) - rtlpci->irq_mask[0] |= add_msr; - - if (rm_msr) - rtlpci->irq_mask[0] &= (~rm_msr); - - rtl92se_disable_interrupt(hw); - rtl92se_enable_interrupt(hw); -} - -static void _rtl8192se_get_IC_Inferiority(struct ieee80211_hw *hw) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 efuse_id; - - rtlhal->ic_class = IC_INFERIORITY_A; - - /* Only retrieving while using EFUSE. */ - if ((rtlefuse->epromtype == EEPROM_BOOT_EFUSE) && - !rtlefuse->autoload_failflag) { - efuse_id = efuse_read_1byte(hw, EFUSE_IC_ID_OFFSET); - - if (efuse_id == 0xfe) - rtlhal->ic_class = IC_INFERIORITY_B; - } -} - -static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u16 i, usvalue; - u16 eeprom_id; - u8 tempval; - u8 hwinfo[HWSET_MAX_SIZE_92S]; - u8 rf_path, index; - - if (rtlefuse->epromtype == EEPROM_93C46) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "RTL819X Not boot from eeprom, check it !!\n"); - } else if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { - rtl_efuse_shadow_map_update(hw); - - memcpy((void *)hwinfo, (void *) - &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], - HWSET_MAX_SIZE_92S); - } - - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP", - hwinfo, HWSET_MAX_SIZE_92S); - - eeprom_id = *((u16 *)&hwinfo[0]); - if (eeprom_id != RTL8190_EEPROM_ID) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "EEPROM ID(%#x) is invalid!!\n", eeprom_id); - rtlefuse->autoload_failflag = true; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - } - - if (rtlefuse->autoload_failflag) - return; - - _rtl8192se_get_IC_Inferiority(hw); - - /* Read IC Version && Channel Plan */ - /* VID, DID SE 0xA-D */ - rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; - rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; - rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; - rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; - rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROMId = 0x%4x\n", eeprom_id); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); - - for (i = 0; i < 6; i += 2) { - usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; - *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; - } - - for (i = 0; i < 6; i++) - rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%pM\n", rtlefuse->dev_addr); - - /* Get Tx Power Level by Channel */ - /* Read Tx power of Channel 1 ~ 14 from EEPROM. */ - /* 92S suupport RF A & B */ - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < 3; i++) { - /* Read CCK RF A & B Tx power */ - rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][i] = - hwinfo[EEPROM_TXPOWERBASE + rf_path * 3 + i]; - - /* Read OFDM RF A & B Tx power for 1T */ - rtlefuse->eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = - hwinfo[EEPROM_TXPOWERBASE + 6 + rf_path * 3 + i]; - - /* Read OFDM RF A & B Tx power for 2T */ - rtlefuse->eprom_chnl_txpwr_ht40_2sdf[rf_path][i] - = hwinfo[EEPROM_TXPOWERBASE + 12 + - rf_path * 3 + i]; - } - } - - for (rf_path = 0; rf_path < 2; rf_path++) - for (i = 0; i < 3; i++) - RTPRINT(rtlpriv, FINIT, INIT_EEPROM, - "RF(%d) EEPROM CCK Area(%d) = 0x%x\n", - rf_path, i, - rtlefuse->eeprom_chnlarea_txpwr_cck - [rf_path][i]); - for (rf_path = 0; rf_path < 2; rf_path++) - for (i = 0; i < 3; i++) - RTPRINT(rtlpriv, FINIT, INIT_EEPROM, - "RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n", - rf_path, i, - rtlefuse->eeprom_chnlarea_txpwr_ht40_1s - [rf_path][i]); - for (rf_path = 0; rf_path < 2; rf_path++) - for (i = 0; i < 3; i++) - RTPRINT(rtlpriv, FINIT, INIT_EEPROM, - "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", - rf_path, i, - rtlefuse->eprom_chnl_txpwr_ht40_2sdf - [rf_path][i]); - - for (rf_path = 0; rf_path < 2; rf_path++) { - - /* Assign dedicated channel tx power */ - for (i = 0; i < 14; i++) { - /* channel 1~3 use the same Tx Power Level. */ - if (i < 3) - index = 0; - /* Channel 4-8 */ - else if (i < 8) - index = 1; - /* Channel 9-14 */ - else - index = 2; - - /* Record A & B CCK /OFDM - 1T/2T Channel area - * tx power */ - rtlefuse->txpwrlevel_cck[rf_path][i] = - rtlefuse->eeprom_chnlarea_txpwr_cck - [rf_path][index]; - rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = - rtlefuse->eeprom_chnlarea_txpwr_ht40_1s - [rf_path][index]; - rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = - rtlefuse->eprom_chnl_txpwr_ht40_2sdf - [rf_path][index]; - } - - for (i = 0; i < 14; i++) { - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", - rf_path, i, - rtlefuse->txpwrlevel_cck[rf_path][i], - rtlefuse->txpwrlevel_ht40_1s[rf_path][i], - rtlefuse->txpwrlevel_ht40_2s[rf_path][i]); - } - } - - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < 3; i++) { - /* Read Power diff limit. */ - rtlefuse->eeprom_pwrgroup[rf_path][i] = - hwinfo[EEPROM_TXPWRGROUP + rf_path * 3 + i]; - } - } - - for (rf_path = 0; rf_path < 2; rf_path++) { - /* Fill Pwr group */ - for (i = 0; i < 14; i++) { - /* Chanel 1-3 */ - if (i < 3) - index = 0; - /* Channel 4-8 */ - else if (i < 8) - index = 1; - /* Channel 9-13 */ - else - index = 2; - - rtlefuse->pwrgroup_ht20[rf_path][i] = - (rtlefuse->eeprom_pwrgroup[rf_path][index] & - 0xf); - rtlefuse->pwrgroup_ht40[rf_path][i] = - ((rtlefuse->eeprom_pwrgroup[rf_path][index] & - 0xf0) >> 4); - - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-%d pwrgroup_ht20[%d] = 0x%x\n", - rf_path, i, - rtlefuse->pwrgroup_ht20[rf_path][i]); - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-%d pwrgroup_ht40[%d] = 0x%x\n", - rf_path, i, - rtlefuse->pwrgroup_ht40[rf_path][i]); - } - } - - for (i = 0; i < 14; i++) { - /* Read tx power difference between HT OFDM 20/40 MHZ */ - /* channel 1-3 */ - if (i < 3) - index = 0; - /* Channel 4-8 */ - else if (i < 8) - index = 1; - /* Channel 9-14 */ - else - index = 2; - - tempval = hwinfo[EEPROM_TX_PWR_HT20_DIFF + index] & 0xff; - rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); - rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = - ((tempval >> 4) & 0xF); - - /* Read OFDM<->HT tx power diff */ - /* Channel 1-3 */ - if (i < 3) - index = 0; - /* Channel 4-8 */ - else if (i < 8) - index = 0x11; - /* Channel 9-14 */ - else - index = 1; - - tempval = hwinfo[EEPROM_TX_PWR_OFDM_DIFF + index] & 0xff; - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = - (tempval & 0xF); - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = - ((tempval >> 4) & 0xF); - - tempval = hwinfo[TX_PWR_SAFETY_CHK]; - rtlefuse->txpwr_safetyflag = (tempval & 0x01); - } - - rtlefuse->eeprom_regulatory = 0; - if (rtlefuse->eeprom_version >= 2) { - /* BIT(0)~2 */ - if (rtlefuse->eeprom_version >= 4) - rtlefuse->eeprom_regulatory = - (hwinfo[EEPROM_REGULATORY] & 0x7); - else /* BIT(0) */ - rtlefuse->eeprom_regulatory = - (hwinfo[EEPROM_REGULATORY] & 0x1); - } - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); - - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", - i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", - i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", - i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", - i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); - - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "TxPwrSafetyFlag = %d\n", rtlefuse->txpwr_safetyflag); - - /* Read RF-indication and Tx Power gain - * index diff of legacy to HT OFDM rate. */ - tempval = hwinfo[EEPROM_RFIND_POWERDIFF] & 0xff; - rtlefuse->eeprom_txpowerdiff = tempval; - rtlefuse->legacy_httxpowerdiff = - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][0]; - - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "TxPowerDiff = %#x\n", rtlefuse->eeprom_txpowerdiff); - - /* Get TSSI value for each path. */ - usvalue = *(u16 *)&hwinfo[EEPROM_TSSI_A]; - rtlefuse->eeprom_tssi[RF90_PATH_A] = (u8)((usvalue & 0xff00) >> 8); - usvalue = hwinfo[EEPROM_TSSI_B]; - rtlefuse->eeprom_tssi[RF90_PATH_B] = (u8)(usvalue & 0xff); - - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, "TSSI_A = 0x%x, TSSI_B = 0x%x\n", - rtlefuse->eeprom_tssi[RF90_PATH_A], - rtlefuse->eeprom_tssi[RF90_PATH_B]); - - /* Read antenna tx power offset of B/C/D to A from EEPROM */ - /* and read ThermalMeter from EEPROM */ - tempval = hwinfo[EEPROM_THERMALMETER]; - rtlefuse->eeprom_thermalmeter = tempval; - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); - - /* ThermalMeter, BIT(0)~3 for RFIC1, BIT(4)~7 for RFIC2 */ - rtlefuse->thermalmeter[0] = (rtlefuse->eeprom_thermalmeter & 0x1f); - rtlefuse->tssi_13dbm = rtlefuse->eeprom_thermalmeter * 100; - - /* Read CrystalCap from EEPROM */ - tempval = hwinfo[EEPROM_CRYSTALCAP] >> 4; - rtlefuse->eeprom_crystalcap = tempval; - /* CrystalCap, BIT(12)~15 */ - rtlefuse->crystalcap = rtlefuse->eeprom_crystalcap; - - /* Read IC Version && Channel Plan */ - /* Version ID, Channel plan */ - rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; - rtlefuse->txpwr_fromeprom = true; - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "EEPROM ChannelPlan = 0x%4x\n", rtlefuse->eeprom_channelplan); - - /* Read Customer ID or Board Type!!! */ - tempval = hwinfo[EEPROM_BOARDTYPE]; - /* Change RF type definition */ - if (tempval == 0) - rtlphy->rf_type = RF_2T2R; - else if (tempval == 1) - rtlphy->rf_type = RF_1T2R; - else if (tempval == 2) - rtlphy->rf_type = RF_1T2R; - else if (tempval == 3) - rtlphy->rf_type = RF_1T1R; - - /* 1T2R but 1SS (1x1 receive combining) */ - rtlefuse->b1x1_recvcombine = false; - if (rtlphy->rf_type == RF_1T2R) { - tempval = rtl_read_byte(rtlpriv, 0x07); - if (!(tempval & BIT(0))) { - rtlefuse->b1x1_recvcombine = true; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "RF_TYPE=1T2R but only 1SS\n"); - } - } - rtlefuse->b1ss_support = rtlefuse->b1x1_recvcombine; - rtlefuse->eeprom_oemid = *&hwinfo[EEPROM_CUSTOMID]; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM Customer ID: 0x%2x", - rtlefuse->eeprom_oemid); - - /* set channel paln to world wide 13 */ - rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; -} - -void rtl92se_read_eeprom_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 tmp_u1b = 0; - - tmp_u1b = rtl_read_byte(rtlpriv, EPROM_CMD); - - if (tmp_u1b & BIT(4)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); - rtlefuse->epromtype = EEPROM_93C46; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); - rtlefuse->epromtype = EEPROM_BOOT_EFUSE; - } - - if (tmp_u1b & BIT(5)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - _rtl92se_read_adapter_info(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); - rtlefuse->autoload_failflag = true; - } -} - -static void rtl92se_update_hal_rate_table(struct ieee80211_hw *hw, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 ratr_value; - u8 ratr_index = 0; - u8 nmode = mac->ht_enable; - u8 mimo_ps = IEEE80211_SMPS_OFF; - u16 shortgi_rate = 0; - u32 tmp_ratr_value = 0; - u8 curtxbw_40mhz = mac->bw_40; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = mac->mode; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_value = sta->supp_rates[1] << 4; - else - ratr_value = sta->supp_rates[0]; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_value = 0xfff; - ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - ratr_value &= 0x0000000D; - break; - case WIRELESS_MODE_G: - ratr_value &= 0x00000FF5; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - nmode = 1; - if (mimo_ps == IEEE80211_SMPS_STATIC) { - ratr_value &= 0x0007F005; - } else { - u32 ratr_mask; - - if (get_rf_type(rtlphy) == RF_1T2R || - get_rf_type(rtlphy) == RF_1T1R) { - if (curtxbw_40mhz) - ratr_mask = 0x000ff015; - else - ratr_mask = 0x000ff005; - } else { - if (curtxbw_40mhz) - ratr_mask = 0x0f0ff015; - else - ratr_mask = 0x0f0ff005; - } - - ratr_value &= ratr_mask; - } - break; - default: - if (rtlphy->rf_type == RF_1T2R) - ratr_value &= 0x000ff0ff; - else - ratr_value &= 0x0f0ff0ff; - - break; - } - - if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) - ratr_value &= 0x0FFFFFFF; - else if (rtlpriv->rtlhal.version == VERSION_8192S_ACUT) - ratr_value &= 0x0FFFFFF0; - - if (nmode && ((curtxbw_40mhz && - curshortgi_40mhz) || (!curtxbw_40mhz && - curshortgi_20mhz))) { - - ratr_value |= 0x10000000; - tmp_ratr_value = (ratr_value >> 12); - - for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { - if ((1 << shortgi_rate) & tmp_ratr_value) - break; - } - - shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | - (shortgi_rate << 4) | (shortgi_rate); - - rtl_write_byte(rtlpriv, SG_RATE, shortgi_rate); - } - - rtl_write_dword(rtlpriv, ARFR0 + ratr_index * 4, ratr_value); - if (ratr_value & 0xfffff000) - rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_REFRESH_N); - else - rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_REFRESH_BG); - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n", - rtl_read_dword(rtlpriv, ARFR0)); -} - -static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - u32 ratr_bitmap; - u8 ratr_index = 0; - u8 curtxbw_40mhz = (sta->bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = 0; - bool shortgi = false; - u32 ratr_value = 0; - u8 shortgi_rate = 0; - u32 mask = 0; - u32 band = 0; - bool bmulticast = false; - u8 macid = 0; - u8 mimo_ps = IEEE80211_SMPS_OFF; - - sta_entry = (struct rtl_sta_info *) sta->drv_priv; - wirelessmode = sta_entry->wireless_mode; - if (mac->opmode == NL80211_IFTYPE_STATION) - curtxbw_40mhz = mac->bw_40; - else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) - macid = sta->aid + 1; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_bitmap = sta->supp_rates[1] << 4; - else - ratr_bitmap = sta->supp_rates[0]; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_bitmap = 0xfff; - ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - band |= WIRELESS_11B; - ratr_index = RATR_INX_WIRELESS_B; - if (ratr_bitmap & 0x0000000c) - ratr_bitmap &= 0x0000000d; - else - ratr_bitmap &= 0x0000000f; - break; - case WIRELESS_MODE_G: - band |= (WIRELESS_11G | WIRELESS_11B); - ratr_index = RATR_INX_WIRELESS_GB; - - if (rssi_level == 1) - ratr_bitmap &= 0x00000f00; - else if (rssi_level == 2) - ratr_bitmap &= 0x00000ff0; - else - ratr_bitmap &= 0x00000ff5; - break; - case WIRELESS_MODE_A: - band |= WIRELESS_11A; - ratr_index = RATR_INX_WIRELESS_A; - ratr_bitmap &= 0x00000ff0; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - band |= (WIRELESS_11N | WIRELESS_11G | WIRELESS_11B); - ratr_index = RATR_INX_WIRELESS_NGB; - - if (mimo_ps == IEEE80211_SMPS_STATIC) { - if (rssi_level == 1) - ratr_bitmap &= 0x00070000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0007f000; - else - ratr_bitmap &= 0x0007f005; - } else { - if (rtlphy->rf_type == RF_1T2R || - rtlphy->rf_type == RF_1T1R) { - if (rssi_level == 1) { - ratr_bitmap &= 0x000f0000; - } else if (rssi_level == 3) { - ratr_bitmap &= 0x000fc000; - } else if (rssi_level == 5) { - ratr_bitmap &= 0x000ff000; - } else { - if (curtxbw_40mhz) - ratr_bitmap &= 0x000ff015; - else - ratr_bitmap &= 0x000ff005; - } - } else { - if (rssi_level == 1) { - ratr_bitmap &= 0x0f8f0000; - } else if (rssi_level == 3) { - ratr_bitmap &= 0x0f8fc000; - } else if (rssi_level == 5) { - ratr_bitmap &= 0x0f8ff000; - } else { - if (curtxbw_40mhz) - ratr_bitmap &= 0x0f8ff015; - else - ratr_bitmap &= 0x0f8ff005; - } - } - } - - if ((curtxbw_40mhz && curshortgi_40mhz) || - (!curtxbw_40mhz && curshortgi_20mhz)) { - if (macid == 0) - shortgi = true; - else if (macid == 1) - shortgi = false; - } - break; - default: - band |= (WIRELESS_11N | WIRELESS_11G | WIRELESS_11B); - ratr_index = RATR_INX_WIRELESS_NGB; - - if (rtlphy->rf_type == RF_1T2R) - ratr_bitmap &= 0x000ff0ff; - else - ratr_bitmap &= 0x0f8ff0ff; - break; - } - sta_entry->ratr_index = ratr_index; - - if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) - ratr_bitmap &= 0x0FFFFFFF; - else if (rtlpriv->rtlhal.version == VERSION_8192S_ACUT) - ratr_bitmap &= 0x0FFFFFF0; - - if (shortgi) { - ratr_bitmap |= 0x10000000; - /* Get MAX MCS available. */ - ratr_value = (ratr_bitmap >> 12); - for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { - if ((1 << shortgi_rate) & ratr_value) - break; - } - - shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | - (shortgi_rate << 4) | (shortgi_rate); - rtl_write_byte(rtlpriv, SG_RATE, shortgi_rate); - } - - mask |= (bmulticast ? 1 : 0) << 9 | (macid & 0x1f) << 4 | (band & 0xf); - - RT_TRACE(rtlpriv, COMP_RATR, DBG_TRACE, "mask = %x, bitmap = %x\n", - mask, ratr_bitmap); - rtl_write_dword(rtlpriv, 0x2c4, ratr_bitmap); - rtl_write_dword(rtlpriv, WFM5, (FW_RA_UPDATE_MASK | (mask << 8))); - - if (macid != 0) - sta_entry->ratr_index = ratr_index; -} - -void rtl92se_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->dm.useramask) - rtl92se_update_hal_rate_mask(hw, sta, rssi_level); - else - rtl92se_update_hal_rate_table(hw, sta); -} - -void rtl92se_update_channel_access_setting(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 sifs_timer; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, - &mac->slot_time); - sifs_timer = 0x0e0e; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); - -} - -/* this ifunction is for RFKILL, it's different with windows, - * because UI will disable wireless when GPIO Radio Off. - * And here we not check or Disable/Enable ASPM like windows*/ -bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - enum rf_pwrstate rfpwr_toset /*, cur_rfstate */; - unsigned long flag = 0; - bool actuallyset = false; - bool turnonbypowerdomain = false; - - /* just 8191se can check gpio before firstup, 92c/92d have fixed it */ - if ((rtlpci->up_first_time == 1) || (rtlpci->being_init_adapter)) - return false; - - if (ppsc->swrf_processing) - return false; - - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - if (ppsc->rfchange_inprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - return false; - } else { - ppsc->rfchange_inprogress = true; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } - - /* cur_rfstate = ppsc->rfpwr_state;*/ - - /* because after _rtl92s_phy_set_rfhalt, all power - * closed, so we must open some power for GPIO check, - * or we will always check GPIO RFOFF here, - * And we should close power after GPIO check */ - if (RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { - _rtl92se_power_domain_init(hw); - turnonbypowerdomain = true; - } - - rfpwr_toset = _rtl92se_rf_onoff_detect(hw); - - if ((ppsc->hwradiooff) && (rfpwr_toset == ERFON)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "RFKILL-HW Radio ON, RF ON\n"); - - rfpwr_toset = ERFON; - ppsc->hwradiooff = false; - actuallyset = true; - } else if ((!ppsc->hwradiooff) && (rfpwr_toset == ERFOFF)) { - RT_TRACE(rtlpriv, COMP_RF, - DBG_DMESG, "RFKILL-HW Radio OFF, RF OFF\n"); - - rfpwr_toset = ERFOFF; - ppsc->hwradiooff = true; - actuallyset = true; - } - - if (actuallyset) { - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - - /* this not include ifconfig wlan0 down case */ - /* } else if (rfpwr_toset == ERFOFF || cur_rfstate == ERFOFF) { */ - } else { - /* because power_domain_init may be happen when - * _rtl92s_phy_set_rfhalt, this will open some powers - * and cause current increasing about 40 mA for ips, - * rfoff and ifconfig down, so we set - * _rtl92s_phy_set_rfhalt again here */ - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC && - turnonbypowerdomain) { - _rtl92s_phy_set_rfhalt(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - } - - spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); - ppsc->rfchange_inprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - } - - *valid = 1; - return !ppsc->hwradiooff; - -} - -/* Is_wepkey just used for WEP used as group & pairwise key - * if pairwise is AES ang group is WEP Is_wepkey == false.*/ -void rtl92se_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr, - bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 *macaddr = p_macaddr; - - u32 entry_id = 0; - bool is_pairwise = false; - - static u8 cam_const_addr[4][6] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} - }; - static u8 cam_const_broad[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - - if (clear_all) { - u8 idx = 0; - u8 cam_offset = 0; - u8 clear_number = 5; - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); - - for (idx = 0; idx < clear_number; idx++) { - rtl_cam_mark_invalid(hw, cam_offset + idx); - rtl_cam_empty_entry(hw, cam_offset + idx); - - if (idx < 5) { - memset(rtlpriv->sec.key_buf[idx], 0, - MAX_KEY_LEN); - rtlpriv->sec.key_len[idx] = 0; - } - } - - } else { - switch (enc_algo) { - case WEP40_ENCRYPTION: - enc_algo = CAM_WEP40; - break; - case WEP104_ENCRYPTION: - enc_algo = CAM_WEP104; - break; - case TKIP_ENCRYPTION: - enc_algo = CAM_TKIP; - break; - case AESCCMP_ENCRYPTION: - enc_algo = CAM_AES; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - enc_algo = CAM_TKIP; - break; - } - - if (is_wepkey || rtlpriv->sec.use_defaultkey) { - macaddr = cam_const_addr[key_index]; - entry_id = key_index; - } else { - if (is_group) { - macaddr = cam_const_broad; - entry_id = key_index; - } else { - if (mac->opmode == NL80211_IFTYPE_AP) { - entry_id = rtl_cam_get_free_entry(hw, - p_macaddr); - if (entry_id >= TOTAL_CAM_ENTRY) { - RT_TRACE(rtlpriv, - COMP_SEC, DBG_EMERG, - "Can not find free hw security cam entry\n"); - return; - } - } else { - entry_id = CAM_PAIRWISE_KEY_POSITION; - } - - key_index = PAIRWISE_KEYIDX; - is_pairwise = true; - } - } - - if (rtlpriv->sec.key_len[key_index] == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "delete one entry, entry_id is %d\n", - entry_id); - if (mac->opmode == NL80211_IFTYPE_AP) - rtl_cam_del_entry(hw, p_macaddr); - rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "add one entry\n"); - if (is_pairwise) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set Pairwise key\n"); - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[key_index]); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set group key\n"); - - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - rtl_cam_add_one_entry(hw, - rtlefuse->dev_addr, - PAIRWISE_KEYIDX, - CAM_PAIRWISE_KEY_POSITION, - enc_algo, CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[entry_id]); - } - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[entry_id]); - } - - } - } -} - -void rtl92se_suspend(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtlpci->up_first_time = true; -} - -void rtl92se_resume(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u32 val; - - pci_read_config_dword(rtlpci->pdev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(rtlpci->pdev, 0x40, - val & 0xffff00ff); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h deleted file mode 100644 index 4cacee10f31e..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h +++ /dev/null @@ -1,78 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#ifndef __REALTEK_PCI92SE_HW_H__ -#define __REALTEK_PCI92SE_HW_H__ - -#define MSR_LINK_MANAGED 2 -#define MSR_LINK_NONE 0 -#define MSR_LINK_SHIFT 0 -#define MSR_LINK_ADHOC 1 -#define MSR_LINK_MASTER 3 - -enum WIRELESS_NETWORK_TYPE { - WIRELESS_11B = 1, - WIRELESS_11G = 2, - WIRELESS_11A = 4, - WIRELESS_11N = 8 -}; - -void rtl92se_get_hw_reg(struct ieee80211_hw *hw, - u8 variable, u8 *val); -void rtl92se_read_eeprom_info(struct ieee80211_hw *hw); -void rtl92se_interrupt_recognized(struct ieee80211_hw *hw, - u32 *inta, u32 *intb); -int rtl92se_hw_init(struct ieee80211_hw *hw); -void rtl92se_card_disable(struct ieee80211_hw *hw); -void rtl92se_enable_interrupt(struct ieee80211_hw *hw); -void rtl92se_disable_interrupt(struct ieee80211_hw *hw); -int rtl92se_set_network_type(struct ieee80211_hw *hw, - enum nl80211_iftype type); -void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -void rtl92se_set_mac_addr(struct rtl_io *io, const u8 *addr); -void rtl92se_set_qos(struct ieee80211_hw *hw, int aci); -void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw); -void rtl92se_set_beacon_interval(struct ieee80211_hw *hw); -void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr); -void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, - u8 *val); -void rtl92se_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level); -void rtl92se_update_channel_access_setting(struct ieee80211_hw *hw); -bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, - u8 *valid); -void rtl8192se_gpiobit3_cfg_inputmode(struct ieee80211_hw *hw); -void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw); -void rtl92se_set_key(struct ieee80211_hw *hw, - u32 key_index, u8 *macaddr, bool is_group, - u8 enc_algo, bool is_wepkey, bool clear_all); -void rtl92se_suspend(struct ieee80211_hw *hw); -void rtl92se_resume(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/rtlwifi/rtl8192se/led.c deleted file mode 100644 index 44949b5cbb87..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/led.c +++ /dev/null @@ -1,151 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "reg.h" -#include "led.h" - -static void _rtl92se_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl92se_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - _rtl92se_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); - _rtl92se_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); -} - -void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - u8 ledcfg; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - LEDCFG, pled->ledpin); - - ledcfg = rtl_read_byte(rtlpriv, LEDCFG); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0xf0); - break; - case LED_PIN_LED1: - rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0x0f); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - pled->ledon = true; -} - -void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - struct rtl_priv *rtlpriv; - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - u8 ledcfg; - - rtlpriv = rtl_priv(hw); - if (!rtlpriv || rtlpriv->max_fw_size) - return; - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", - LEDCFG, pled->ledpin); - - ledcfg = rtl_read_byte(rtlpriv, LEDCFG); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg &= 0xf0; - if (pcipriv->ledctl.led_opendrain) - rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(1))); - else - rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3))); - break; - case LED_PIN_LED1: - ledcfg &= 0x0f; - rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3))); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - pled->ledon = false; -} - -static void _rtl92se_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); - switch (ledaction) { - case LED_CTL_POWER_ON: - case LED_CTL_LINK: - case LED_CTL_NO_LINK: - rtl92se_sw_led_on(hw, pLed0); - break; - case LED_CTL_POWER_OFF: - rtl92se_sw_led_off(hw, pLed0); - break; - default: - break; - } -} - -void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && - (ledaction == LED_CTL_TX || - ledaction == LED_CTL_RX || - ledaction == LED_CTL_SITE_SURVEY || - ledaction == LED_CTL_LINK || - ledaction == LED_CTL_NO_LINK || - ledaction == LED_CTL_START_TO_LINK || - ledaction == LED_CTL_POWER_ON)) { - return; - } - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d\n", ledaction); - - _rtl92se_sw_led_control(hw, ledaction); -} - diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.h b/drivers/net/wireless/rtlwifi/rtl8192se/led.h deleted file mode 100644 index 2182dbeb5f32..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/led.h +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#ifndef __REALTEK_PCI92SE_LED_H__ -#define __REALTEK_PCI92SE_LED_H__ - -void rtl92se_init_sw_leds(struct ieee80211_hw *hw); -void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c deleted file mode 100644 index 4b4612fe2fdb..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ /dev/null @@ -1,1658 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../ps.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" -#include "fw.h" -#include "hw.h" -#include "table.h" - -static u32 _rtl92s_phy_calculate_bit_shift(u32 bitmask) -{ - u32 i; - - for (i = 0; i <= 31; i++) { - if (((bitmask >> i) & 0x1) == 1) - break; - } - - return i; -} - -u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 returnvalue = 0, originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n", - regaddr, bitmask); - - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); - returnvalue = (originalvalue & bitmask) >> bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "BBR MASK=0x%x Addr[0x%x]=0x%x\n", - bitmask, regaddr, originalvalue); - - return returnvalue; - -} - -void rtl92s_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, - u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); - - if (bitmask != MASKDWORD) { - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); - data = ((originalvalue & (~bitmask)) | (data << bitshift)); - } - - rtl_write_dword(rtlpriv, regaddr, data); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); - -} - -static u32 _rtl92s_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) -{ - - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - u32 newoffset; - u32 tmplong, tmplong2; - u8 rfpi_enable = 0; - u32 retvalue = 0; - - offset &= 0x3f; - newoffset = offset; - - tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); - - if (rfpath == RF90_PATH_A) - tmplong2 = tmplong; - else - tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); - - tmplong2 = (tmplong2 & (~BLSSI_READADDRESS)) | (newoffset << 23) | - BLSSI_READEDGE; - - rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, - tmplong & (~BLSSI_READEDGE)); - - mdelay(1); - - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); - mdelay(1); - - rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, tmplong | - BLSSI_READEDGE); - mdelay(1); - - if (rfpath == RF90_PATH_A) - rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, - BIT(8)); - else if (rfpath == RF90_PATH_B) - rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, - BIT(8)); - - if (rfpi_enable) - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, - BLSSI_READBACK_DATA); - else - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, - BLSSI_READBACK_DATA); - - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, - BLSSI_READBACK_DATA); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n", - rfpath, pphyreg->rf_rb, retvalue); - - return retvalue; - -} - -static void _rtl92s_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - u32 data_and_addr = 0; - u32 newoffset; - - offset &= 0x3f; - newoffset = offset; - - data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; - rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]=0x%x\n", - rfpath, pphyreg->rf3wire_offset, data_and_addr); -} - - -u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, readback_value, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", - regaddr, rfpath, bitmask); - - spin_lock(&rtlpriv->locks.rf_lock); - - original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr); - - bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); - readback_value = (original_value & bitmask) >> bitshift; - - spin_unlock(&rtlpriv->locks.rf_lock); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", - regaddr, rfpath, bitmask, original_value); - - return readback_value; -} - -void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 original_value, bitshift; - - if (!((rtlphy->rf_pathmap >> rfpath) & 0x1)) - return; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); - - spin_lock(&rtlpriv->locks.rf_lock); - - if (bitmask != RFREG_OFFSET_MASK) { - original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, - regaddr); - bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); - data = ((original_value & (~bitmask)) | (data << bitshift)); - } - - _rtl92s_phy_rf_serial_write(hw, rfpath, regaddr, data); - - spin_unlock(&rtlpriv->locks.rf_lock); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); - -} - -void rtl92s_phy_scan_operation_backup(struct ieee80211_hw *hw, - u8 operation) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (!is_hal_stop(rtlhal)) { - switch (operation) { - case SCAN_OPT_BACKUP: - rtl92s_phy_set_fw_cmd(hw, FW_CMD_PAUSE_DM_BY_SCAN); - break; - case SCAN_OPT_RESTORE: - rtl92s_phy_set_fw_cmd(hw, FW_CMD_RESUME_DM_BY_SCAN); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Unknown operation\n"); - break; - } - } -} - -void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 reg_bw_opmode; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n", - rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? - "20MHz" : "40MHz"); - - if (rtlphy->set_bwmode_inprogress) - return; - if (is_hal_stop(rtlhal)) - return; - - rtlphy->set_bwmode_inprogress = true; - - reg_bw_opmode = rtl_read_byte(rtlpriv, BW_OPMODE); - /* dummy read */ - rtl_read_byte(rtlpriv, RRSR + 2); - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - reg_bw_opmode |= BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); - break; - case HT_CHANNEL_WIDTH_20_40: - reg_bw_opmode &= ~BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); - - if (rtlhal->version >= VERSION_8192S_BCUT) - rtl_write_byte(rtlpriv, RFPGA0_ANALOGPARAMETER2, 0x58); - break; - case HT_CHANNEL_WIDTH_20_40: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); - - rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, - (mac->cur_40_prime_sc >> 1)); - rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); - - if (rtlhal->version >= VERSION_8192S_BCUT) - rtl_write_byte(rtlpriv, RFPGA0_ANALOGPARAMETER2, 0x18); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - - rtl92s_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); - rtlphy->set_bwmode_inprogress = false; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); -} - -static bool _rtl92s_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, u32 cmdtablesz, enum swchnlcmd_id cmdid, - u32 para1, u32 para2, u32 msdelay) -{ - struct swchnlcmd *pcmd; - - if (cmdtable == NULL) { - RT_ASSERT(false, "cmdtable cannot be NULL\n"); - return false; - } - - if (cmdtableidx >= cmdtablesz) - return false; - - pcmd = cmdtable + cmdtableidx; - pcmd->cmdid = cmdid; - pcmd->para1 = para1; - pcmd->para2 = para2; - pcmd->msdelay = msdelay; - - return true; -} - -static bool _rtl92s_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, u32 *delay) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; - u32 precommoncmdcnt; - struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; - u32 postcommoncmdcnt; - struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; - u32 rfdependcmdcnt; - struct swchnlcmd *currentcmd = NULL; - u8 rfpath; - u8 num_total_rfpath = rtlphy->num_total_rfpath; - - precommoncmdcnt = 0; - _rtl92s_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); - _rtl92s_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); - - postcommoncmdcnt = 0; - - _rtl92s_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, - MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); - - rfdependcmdcnt = 0; - - RT_ASSERT((channel >= 1 && channel <= 14), - "invalid channel for Zebra: %d\n", channel); - - _rtl92s_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, - RF_CHNLBW, channel, 10); - - _rtl92s_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, 0); - - do { - switch (*stage) { - case 0: - currentcmd = &precommoncmd[*step]; - break; - case 1: - currentcmd = &rfdependcmd[*step]; - break; - case 2: - currentcmd = &postcommoncmd[*step]; - break; - default: - return true; - } - - if (currentcmd->cmdid == CMDID_END) { - if ((*stage) == 2) { - return true; - } else { - (*stage)++; - (*step) = 0; - continue; - } - } - - switch (currentcmd->cmdid) { - case CMDID_SET_TXPOWEROWER_LEVEL: - rtl92s_phy_set_txpower(hw, channel); - break; - case CMDID_WRITEPORT_ULONG: - rtl_write_dword(rtlpriv, currentcmd->para1, - currentcmd->para2); - break; - case CMDID_WRITEPORT_USHORT: - rtl_write_word(rtlpriv, currentcmd->para1, - (u16)currentcmd->para2); - break; - case CMDID_WRITEPORT_UCHAR: - rtl_write_byte(rtlpriv, currentcmd->para1, - (u8)currentcmd->para2); - break; - case CMDID_RF_WRITEREG: - for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { - rtlphy->rfreg_chnlval[rfpath] = - ((rtlphy->rfreg_chnlval[rfpath] & - 0xfffffc00) | currentcmd->para2); - rtl_set_rfreg(hw, (enum radio_path)rfpath, - currentcmd->para1, - RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[rfpath]); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - break; - } - - break; - } while (true); - - (*delay) = currentcmd->msdelay; - (*step)++; - return false; -} - -u8 rtl92s_phy_sw_chnl(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 delay; - bool ret; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "switch to channel%d\n", - rtlphy->current_channel); - - if (rtlphy->sw_chnl_inprogress) - return 0; - - if (rtlphy->set_bwmode_inprogress) - return 0; - - if (is_hal_stop(rtlhal)) - return 0; - - rtlphy->sw_chnl_inprogress = true; - rtlphy->sw_chnl_stage = 0; - rtlphy->sw_chnl_step = 0; - - do { - if (!rtlphy->sw_chnl_inprogress) - break; - - ret = _rtl92s_phy_sw_chnl_step_by_step(hw, - rtlphy->current_channel, - &rtlphy->sw_chnl_stage, - &rtlphy->sw_chnl_step, &delay); - if (!ret) { - if (delay > 0) - mdelay(delay); - else - continue; - } else { - rtlphy->sw_chnl_inprogress = false; - } - break; - } while (true); - - rtlphy->sw_chnl_inprogress = false; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); - - return 1; -} - -static void _rtl92se_phy_set_rf_sleep(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 u1btmp; - - u1btmp = rtl_read_byte(rtlpriv, LDOV12D_CTRL); - u1btmp |= BIT(0); - - rtl_write_byte(rtlpriv, LDOV12D_CTRL, u1btmp); - rtl_write_byte(rtlpriv, SPS1_CTRL, 0x0); - rtl_write_byte(rtlpriv, TXPAUSE, 0xFF); - rtl_write_word(rtlpriv, CMDR, 0x57FC); - udelay(100); - - rtl_write_word(rtlpriv, CMDR, 0x77FC); - rtl_write_byte(rtlpriv, PHY_CCA, 0x0); - udelay(10); - - rtl_write_word(rtlpriv, CMDR, 0x37FC); - udelay(10); - - rtl_write_word(rtlpriv, CMDR, 0x77FC); - udelay(10); - - rtl_write_word(rtlpriv, CMDR, 0x57FC); - - /* we should chnge GPIO to input mode - * this will drop away current about 25mA*/ - rtl8192se_gpiobit3_cfg_inputmode(hw); -} - -bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool bresult = true; - u8 i, queue_id; - struct rtl8192_tx_ring *ring = NULL; - - if (rfpwr_state == ppsc->rfpwr_state) - return false; - - switch (rfpwr_state) { - case ERFON:{ - if ((ppsc->rfpwr_state == ERFOFF) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { - - bool rtstatus; - u32 InitializeCount = 0; - do { - InitializeCount++; - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic enable\n"); - rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && (InitializeCount < 10)); - - RT_CLEAR_PS_LEVEL(ppsc, - RT_RF_OFF_LEVL_HALT_NIC); - } else { - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "awake, sleeped:%d ms state_inap:%x\n", - jiffies_to_msecs(jiffies - - ppsc-> - last_sleep_jiffies), - rtlpriv->psc.state_inap); - ppsc->last_awake_jiffies = jiffies; - rtl_write_word(rtlpriv, CMDR, 0x37FC); - rtl_write_byte(rtlpriv, TXPAUSE, 0x00); - rtl_write_byte(rtlpriv, PHY_CCA, 0x3); - } - - if (mac->link_state == MAC80211_LINKED) - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_LINK); - else - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - break; - } - case ERFOFF:{ - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic disable\n"); - rtl_ps_disable_nic(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - } else { - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - else - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_POWER_OFF); - } - break; - } - case ERFSLEEP: - if (ppsc->rfpwr_state == ERFOFF) - return false; - - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (skb_queue_len(&ring->queue) == 0 || - queue_id == BEACON_QUEUE) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] = %d before doze!\n", - i + 1, queue_id, - skb_queue_len(&ring->queue)); - - udelay(10); - i++; - } - - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "ERFOFF: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "Set ERFSLEEP awaked:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc->last_awake_jiffies)); - - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "sleep awaked:%d ms state_inap:%x\n", - jiffies_to_msecs(jiffies - - ppsc->last_awake_jiffies), - rtlpriv->psc.state_inap); - ppsc->last_sleep_jiffies = jiffies; - _rtl92se_phy_set_rf_sleep(hw); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not processed\n"); - bresult = false; - break; - } - - if (bresult) - ppsc->rfpwr_state = rfpwr_state; - - return bresult; -} - -static bool _rtl92s_phy_config_rfpa_bias_current(struct ieee80211_hw *hw, - enum radio_path rfpath) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool rtstatus = true; - u32 tmpval = 0; - - /* If inferiority IC, we have to increase the PA bias current */ - if (rtlhal->ic_class != IC_INFERIORITY_A) { - tmpval = rtl92s_phy_query_rf_reg(hw, rfpath, RF_IPA, 0xf); - rtl92s_phy_set_rf_reg(hw, rfpath, RF_IPA, 0xf, tmpval + 1); - } - - return rtstatus; -} - -static void _rtl92s_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, - u32 reg_addr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - int index; - - if (reg_addr == RTXAGC_RATE18_06) - index = 0; - else if (reg_addr == RTXAGC_RATE54_24) - index = 1; - else if (reg_addr == RTXAGC_CCK_MCS32) - index = 6; - else if (reg_addr == RTXAGC_MCS03_MCS00) - index = 2; - else if (reg_addr == RTXAGC_MCS07_MCS04) - index = 3; - else if (reg_addr == RTXAGC_MCS11_MCS08) - index = 4; - else if (reg_addr == RTXAGC_MCS15_MCS12) - index = 5; - else - return; - - rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data; - if (index == 5) - rtlphy->pwrgroup_cnt++; -} - -static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - /*RF Interface Sowrtware Control */ - rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; - - /* RF Interface Readback Value */ - rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; - rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; - rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; - rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; - - /* RF Interface Output (and Enable) */ - rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_C].rfintfo = RFPGA0_XC_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_D].rfintfo = RFPGA0_XD_RFINTERFACEOE; - - /* RF Interface (Output and) Enable */ - rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_C].rfintfe = RFPGA0_XC_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_D].rfintfe = RFPGA0_XD_RFINTERFACEOE; - - /* Addr of LSSI. Wirte RF register by driver */ - rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = - RFPGA0_XA_LSSIPARAMETER; - rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = - RFPGA0_XB_LSSIPARAMETER; - rtlphy->phyreg_def[RF90_PATH_C].rf3wire_offset = - RFPGA0_XC_LSSIPARAMETER; - rtlphy->phyreg_def[RF90_PATH_D].rf3wire_offset = - RFPGA0_XD_LSSIPARAMETER; - - /* RF parameter */ - rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; - - /* Tx AGC Gain Stage (same for all path. Should we remove this?) */ - rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; - rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; - rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; - rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; - - /* Tranceiver A~D HSSI Parameter-1 */ - rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; - rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; - rtlphy->phyreg_def[RF90_PATH_C].rfhssi_para1 = RFPGA0_XC_HSSIPARAMETER1; - rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para1 = RFPGA0_XD_HSSIPARAMETER1; - - /* Tranceiver A~D HSSI Parameter-2 */ - rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; - rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; - rtlphy->phyreg_def[RF90_PATH_C].rfhssi_para2 = RFPGA0_XC_HSSIPARAMETER2; - rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para2 = RFPGA0_XD_HSSIPARAMETER2; - - /* RF switch Control */ - rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; - - /* AGC control 1 */ - rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; - - /* AGC control 2 */ - rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; - - /* RX AFE control 1 */ - rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; - - /* RX AFE control 1 */ - rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; - rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; - rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; - rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; - - /* Tx AFE control 1 */ - rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE; - - /* Tx AFE control 2 */ - rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; - rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; - rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE; - rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; - - /* Tranceiver LSSI Readback */ - rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK; - - /* Tranceiver LSSI Readback PI mode */ - rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVERA_HSPI_READBACK; - rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVERB_HSPI_READBACK; -} - - -static bool _rtl92s_phy_config_bb(struct ieee80211_hw *hw, u8 configtype) -{ - int i; - u32 *phy_reg_table; - u32 *agc_table; - u16 phy_reg_len, agc_len; - - agc_len = AGCTAB_ARRAYLENGTH; - agc_table = rtl8192seagctab_array; - /* Default RF_type: 2T2R */ - phy_reg_len = PHY_REG_2T2RARRAYLENGTH; - phy_reg_table = rtl8192sephy_reg_2t2rarray; - - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_reg_len; i = i + 2) { - rtl_addr_delay(phy_reg_table[i]); - - /* Add delay for ECS T20 & LG malow platform, */ - udelay(1); - - rtl92s_phy_set_bb_reg(hw, phy_reg_table[i], MASKDWORD, - phy_reg_table[i + 1]); - } - } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { - for (i = 0; i < agc_len; i = i + 2) { - rtl92s_phy_set_bb_reg(hw, agc_table[i], MASKDWORD, - agc_table[i + 1]); - - /* Add delay for ECS T20 & LG malow platform */ - udelay(1); - } - } - - return true; -} - -static bool _rtl92s_phy_set_bb_to_diff_rf(struct ieee80211_hw *hw, - u8 configtype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 *phy_regarray2xtxr_table; - u16 phy_regarray2xtxr_len; - int i; - - if (rtlphy->rf_type == RF_1T1R) { - phy_regarray2xtxr_table = rtl8192sephy_changeto_1t1rarray; - phy_regarray2xtxr_len = PHY_CHANGETO_1T1RARRAYLENGTH; - } else if (rtlphy->rf_type == RF_1T2R) { - phy_regarray2xtxr_table = rtl8192sephy_changeto_1t2rarray; - phy_regarray2xtxr_len = PHY_CHANGETO_1T2RARRAYLENGTH; - } else { - return false; - } - - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_regarray2xtxr_len; i = i + 3) { - rtl_addr_delay(phy_regarray2xtxr_table[i]); - - rtl92s_phy_set_bb_reg(hw, phy_regarray2xtxr_table[i], - phy_regarray2xtxr_table[i + 1], - phy_regarray2xtxr_table[i + 2]); - } - } - - return true; -} - -static bool _rtl92s_phy_config_bb_with_pg(struct ieee80211_hw *hw, - u8 configtype) -{ - int i; - u32 *phy_table_pg; - u16 phy_pg_len; - - phy_pg_len = PHY_REG_ARRAY_PGLENGTH; - phy_table_pg = rtl8192sephy_reg_array_pg; - - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_pg_len; i = i + 3) { - rtl_addr_delay(phy_table_pg[i]); - - _rtl92s_store_pwrindex_diffrate_offset(hw, - phy_table_pg[i], - phy_table_pg[i + 1], - phy_table_pg[i + 2]); - rtl92s_phy_set_bb_reg(hw, phy_table_pg[i], - phy_table_pg[i + 1], - phy_table_pg[i + 2]); - } - } - - return true; -} - -static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - bool rtstatus = true; - - /* 1. Read PHY_REG.TXT BB INIT!! */ - /* We will separate as 1T1R/1T2R/1T2R_GREEN/2T2R */ - if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_2T2R || - rtlphy->rf_type == RF_1T1R || rtlphy->rf_type == RF_2T2R_GREEN) { - rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_PHY_REG); - - if (rtlphy->rf_type != RF_2T2R && - rtlphy->rf_type != RF_2T2R_GREEN) - /* so we should reconfig BB reg with the right - * PHY parameters. */ - rtstatus = _rtl92s_phy_set_bb_to_diff_rf(hw, - BASEBAND_CONFIG_PHY_REG); - } else { - rtstatus = false; - } - - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, - "Write BB Reg Fail!!\n"); - goto phy_BB8190_Config_ParaFile_Fail; - } - - /* 2. If EEPROM or EFUSE autoload OK, We must config by - * PHY_REG_PG.txt */ - if (rtlefuse->autoload_failflag == false) { - rtlphy->pwrgroup_cnt = 0; - - rtstatus = _rtl92s_phy_config_bb_with_pg(hw, - BASEBAND_CONFIG_PHY_REG); - } - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, - "_rtl92s_phy_bb_config_parafile(): BB_PG Reg Fail!!\n"); - goto phy_BB8190_Config_ParaFile_Fail; - } - - /* 3. BB AGC table Initialization */ - rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_AGC_TAB); - - if (!rtstatus) { - pr_err("%s(): AGC Table Fail\n", __func__); - goto phy_BB8190_Config_ParaFile_Fail; - } - - /* Check if the CCK HighPower is turned ON. */ - /* This is used to calculate PWDB. */ - rtlphy->cck_high_power = (bool)(rtl92s_phy_query_bb_reg(hw, - RFPGA0_XA_HSSIPARAMETER2, 0x200)); - -phy_BB8190_Config_ParaFile_Fail: - return rtstatus; -} - -u8 rtl92s_phy_config_rf(struct ieee80211_hw *hw, enum radio_path rfpath) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - int i; - bool rtstatus = true; - u32 *radio_a_table; - u32 *radio_b_table; - u16 radio_a_tblen, radio_b_tblen; - - radio_a_tblen = RADIOA_1T_ARRAYLENGTH; - radio_a_table = rtl8192seradioa_1t_array; - - /* Using Green mode array table for RF_2T2R_GREEN */ - if (rtlphy->rf_type == RF_2T2R_GREEN) { - radio_b_table = rtl8192seradiob_gm_array; - radio_b_tblen = RADIOB_GM_ARRAYLENGTH; - } else { - radio_b_table = rtl8192seradiob_array; - radio_b_tblen = RADIOB_ARRAYLENGTH; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); - rtstatus = true; - - switch (rfpath) { - case RF90_PATH_A: - for (i = 0; i < radio_a_tblen; i = i + 2) { - rtl_rfreg_delay(hw, rfpath, radio_a_table[i], - MASK20BITS, radio_a_table[i + 1]); - - } - - /* PA Bias current for inferiority IC */ - _rtl92s_phy_config_rfpa_bias_current(hw, rfpath); - break; - case RF90_PATH_B: - for (i = 0; i < radio_b_tblen; i = i + 2) { - rtl_rfreg_delay(hw, rfpath, radio_b_table[i], - MASK20BITS, radio_b_table[i + 1]); - } - break; - case RF90_PATH_C: - ; - break; - case RF90_PATH_D: - ; - break; - default: - break; - } - - return rtstatus; -} - - -bool rtl92s_phy_mac_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - u32 arraylength; - u32 *ptraArray; - - arraylength = MAC_2T_ARRAYLENGTH; - ptraArray = rtl8192semac_2t_array; - - for (i = 0; i < arraylength; i = i + 2) - rtl_write_byte(rtlpriv, ptraArray[i], (u8)ptraArray[i + 1]); - - return true; -} - - -bool rtl92s_phy_bb_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - bool rtstatus = true; - u8 pathmap, index, rf_num = 0; - u8 path1, path2; - - _rtl92s_phy_init_register_definition(hw); - - /* Config BB and AGC */ - rtstatus = _rtl92s_phy_bb_config_parafile(hw); - - - /* Check BB/RF confiuration setting. */ - /* We only need to configure RF which is turned on. */ - path1 = (u8)(rtl92s_phy_query_bb_reg(hw, RFPGA0_TXINFO, 0xf)); - mdelay(10); - path2 = (u8)(rtl92s_phy_query_bb_reg(hw, ROFDM0_TRXPATHENABLE, 0xf)); - pathmap = path1 | path2; - - rtlphy->rf_pathmap = pathmap; - for (index = 0; index < 4; index++) { - if ((pathmap >> index) & 0x1) - rf_num++; - } - - if ((rtlphy->rf_type == RF_1T1R && rf_num != 1) || - (rtlphy->rf_type == RF_1T2R && rf_num != 2) || - (rtlphy->rf_type == RF_2T2R && rf_num != 2) || - (rtlphy->rf_type == RF_2T2R_GREEN && rf_num != 2)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, - "RF_Type(%x) does not match RF_Num(%x)!!\n", - rtlphy->rf_type, rf_num); - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, - "path1 0x%x, path2 0x%x, pathmap 0x%x\n", - path1, path2, pathmap); - } - - return rtstatus; -} - -bool rtl92s_phy_rf_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - /* Initialize general global value */ - if (rtlphy->rf_type == RF_1T1R) - rtlphy->num_total_rfpath = 1; - else - rtlphy->num_total_rfpath = 2; - - /* Config BB and RF */ - return rtl92s_phy_rf6052_config(hw); -} - -void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - /* read rx initial gain */ - rtlphy->default_initialgain[0] = rtl_get_bbreg(hw, - ROFDM0_XAAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[1] = rtl_get_bbreg(hw, - ROFDM0_XBAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[2] = rtl_get_bbreg(hw, - ROFDM0_XCAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[3] = rtl_get_bbreg(hw, - ROFDM0_XDAGCCORE1, MASKBYTE0); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n", - rtlphy->default_initialgain[0], - rtlphy->default_initialgain[1], - rtlphy->default_initialgain[2], - rtlphy->default_initialgain[3]); - - /* read framesync */ - rtlphy->framesync = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, MASKBYTE0); - rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, - MASKDWORD); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Default framesync (0x%x) = 0x%x\n", - ROFDM0_RXDETECTOR3, rtlphy->framesync); - -} - -static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel, - u8 *cckpowerlevel, u8 *ofdmpowerLevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 index = (channel - 1); - - /* 1. CCK */ - /* RF-A */ - cckpowerlevel[0] = rtlefuse->txpwrlevel_cck[0][index]; - /* RF-B */ - cckpowerlevel[1] = rtlefuse->txpwrlevel_cck[1][index]; - - /* 2. OFDM for 1T or 2T */ - if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) { - /* Read HT 40 OFDM TX power */ - ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_1s[0][index]; - ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_1s[1][index]; - } else if (rtlphy->rf_type == RF_2T2R) { - /* Read HT 40 OFDM TX power */ - ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index]; - ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index]; - } else { - ofdmpowerLevel[0] = 0; - ofdmpowerLevel[1] = 0; - } -} - -static void _rtl92s_phy_ccxpower_indexcheck(struct ieee80211_hw *hw, - u8 channel, u8 *cckpowerlevel, u8 *ofdmpowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; - rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; -} - -void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - /* [0]:RF-A, [1]:RF-B */ - u8 cckpowerlevel[2], ofdmpowerLevel[2]; - - if (!rtlefuse->txpwr_fromeprom) - return; - - /* Mainly we use RF-A Tx Power to write the Tx Power registers, - * but the RF-B Tx Power must be calculated by the antenna diff. - * So we have to rewrite Antenna gain offset register here. - * Please refer to BB register 0x80c - * 1. For CCK. - * 2. For OFDM 1T or 2T */ - _rtl92s_phy_get_txpower_index(hw, channel, &cckpowerlevel[0], - &ofdmpowerLevel[0]); - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Channel-%d, cckPowerLevel (A / B) = 0x%x / 0x%x, ofdmPowerLevel (A / B) = 0x%x / 0x%x\n", - channel, cckpowerlevel[0], cckpowerlevel[1], - ofdmpowerLevel[0], ofdmpowerLevel[1]); - - _rtl92s_phy_ccxpower_indexcheck(hw, channel, &cckpowerlevel[0], - &ofdmpowerLevel[0]); - - rtl92s_phy_rf6052_set_ccktxpower(hw, cckpowerlevel[0]); - rtl92s_phy_rf6052_set_ofdmtxpower(hw, &ofdmpowerLevel[0], channel); - -} - -void rtl92s_phy_chk_fwcmd_iodone(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 pollingcnt = 10000; - u32 tmpvalue; - - /* Make sure that CMD IO has be accepted by FW. */ - do { - udelay(10); - - tmpvalue = rtl_read_dword(rtlpriv, WFM5); - if (tmpvalue == 0) - break; - } while (--pollingcnt); - - if (pollingcnt == 0) - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Set FW Cmd fail!!\n"); -} - - -static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 input, current_aid = 0; - - if (is_hal_stop(rtlhal)) - return; - - if (hal_get_firmwareversion(rtlpriv) < 0x34) - goto skip; - /* We re-map RA related CMD IO to combinational ones */ - /* if FW version is v.52 or later. */ - switch (rtlhal->current_fwcmd_io) { - case FW_CMD_RA_REFRESH_N: - rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_N_COMB; - break; - case FW_CMD_RA_REFRESH_BG: - rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_BG_COMB; - break; - default: - break; - } - -skip: - switch (rtlhal->current_fwcmd_io) { - case FW_CMD_RA_RESET: - RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_RESET\n"); - rtl_write_dword(rtlpriv, WFM5, FW_RA_RESET); - rtl92s_phy_chk_fwcmd_iodone(hw); - break; - case FW_CMD_RA_ACTIVE: - RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_ACTIVE\n"); - rtl_write_dword(rtlpriv, WFM5, FW_RA_ACTIVE); - rtl92s_phy_chk_fwcmd_iodone(hw); - break; - case FW_CMD_RA_REFRESH_N: - RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_REFRESH_N\n"); - input = FW_RA_REFRESH; - rtl_write_dword(rtlpriv, WFM5, input); - rtl92s_phy_chk_fwcmd_iodone(hw); - rtl_write_dword(rtlpriv, WFM5, FW_RA_ENABLE_RSSI_MASK); - rtl92s_phy_chk_fwcmd_iodone(hw); - break; - case FW_CMD_RA_REFRESH_BG: - RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, - "FW_CMD_RA_REFRESH_BG\n"); - rtl_write_dword(rtlpriv, WFM5, FW_RA_REFRESH); - rtl92s_phy_chk_fwcmd_iodone(hw); - rtl_write_dword(rtlpriv, WFM5, FW_RA_DISABLE_RSSI_MASK); - rtl92s_phy_chk_fwcmd_iodone(hw); - break; - case FW_CMD_RA_REFRESH_N_COMB: - RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, - "FW_CMD_RA_REFRESH_N_COMB\n"); - input = FW_RA_IOT_N_COMB; - rtl_write_dword(rtlpriv, WFM5, input); - rtl92s_phy_chk_fwcmd_iodone(hw); - break; - case FW_CMD_RA_REFRESH_BG_COMB: - RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, - "FW_CMD_RA_REFRESH_BG_COMB\n"); - input = FW_RA_IOT_BG_COMB; - rtl_write_dword(rtlpriv, WFM5, input); - rtl92s_phy_chk_fwcmd_iodone(hw); - break; - case FW_CMD_IQK_ENABLE: - RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_IQK_ENABLE\n"); - rtl_write_dword(rtlpriv, WFM5, FW_IQK_ENABLE); - rtl92s_phy_chk_fwcmd_iodone(hw); - break; - case FW_CMD_PAUSE_DM_BY_SCAN: - /* Lower initial gain */ - rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, 0x17); - rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, 0x17); - /* CCA threshold */ - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x40); - break; - case FW_CMD_RESUME_DM_BY_SCAN: - /* CCA threshold */ - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); - rtl92s_phy_set_txpower(hw, rtlphy->current_channel); - break; - case FW_CMD_HIGH_PWR_DISABLE: - if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) - break; - - /* Lower initial gain */ - rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, 0x17); - rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, 0x17); - /* CCA threshold */ - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x40); - break; - case FW_CMD_HIGH_PWR_ENABLE: - if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) || - rtlpriv->dm.dynamic_txpower_enable) - break; - - /* CCA threshold */ - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); - break; - case FW_CMD_LPS_ENTER: - RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_LPS_ENTER\n"); - current_aid = rtlpriv->mac80211.assoc_id; - rtl_write_dword(rtlpriv, WFM5, (FW_LPS_ENTER | - ((current_aid | 0xc000) << 8))); - rtl92s_phy_chk_fwcmd_iodone(hw); - /* FW set TXOP disable here, so disable EDCA - * turbo mode until driver leave LPS */ - break; - case FW_CMD_LPS_LEAVE: - RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_LPS_LEAVE\n"); - rtl_write_dword(rtlpriv, WFM5, FW_LPS_LEAVE); - rtl92s_phy_chk_fwcmd_iodone(hw); - break; - case FW_CMD_ADD_A2_ENTRY: - RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_ADD_A2_ENTRY\n"); - rtl_write_dword(rtlpriv, WFM5, FW_ADD_A2_ENTRY); - rtl92s_phy_chk_fwcmd_iodone(hw); - break; - case FW_CMD_CTRL_DM_BY_DRIVER: - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "FW_CMD_CTRL_DM_BY_DRIVER\n"); - rtl_write_dword(rtlpriv, WFM5, FW_CTRL_DM_BY_DRIVER); - rtl92s_phy_chk_fwcmd_iodone(hw); - break; - - default: - break; - } - - rtl92s_phy_chk_fwcmd_iodone(hw); - - /* Clear FW CMD operation flag. */ - rtlhal->set_fwcmd_inprogress = false; -} - -bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *digtable = &rtlpriv->dm_digtable; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 fw_param = FW_CMD_IO_PARA_QUERY(rtlpriv); - u16 fw_cmdmap = FW_CMD_IO_QUERY(rtlpriv); - bool postprocessing = false; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n", - fw_cmdio, rtlhal->set_fwcmd_inprogress); - - do { - /* We re-map to combined FW CMD ones if firmware version */ - /* is v.53 or later. */ - if (hal_get_firmwareversion(rtlpriv) >= 0x35) { - switch (fw_cmdio) { - case FW_CMD_RA_REFRESH_N: - fw_cmdio = FW_CMD_RA_REFRESH_N_COMB; - break; - case FW_CMD_RA_REFRESH_BG: - fw_cmdio = FW_CMD_RA_REFRESH_BG_COMB; - break; - default: - break; - } - } else { - if ((fw_cmdio == FW_CMD_IQK_ENABLE) || - (fw_cmdio == FW_CMD_RA_REFRESH_N) || - (fw_cmdio == FW_CMD_RA_REFRESH_BG)) { - postprocessing = true; - break; - } - } - - /* If firmware version is v.62 or later, - * use FW_CMD_IO_SET for FW_CMD_CTRL_DM_BY_DRIVER */ - if (hal_get_firmwareversion(rtlpriv) >= 0x3E) { - if (fw_cmdio == FW_CMD_CTRL_DM_BY_DRIVER) - fw_cmdio = FW_CMD_CTRL_DM_BY_DRIVER_NEW; - } - - - /* We shall revise all FW Cmd IO into Reg0x364 - * DM map table in the future. */ - switch (fw_cmdio) { - case FW_CMD_RA_INIT: - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "RA init!!\n"); - fw_cmdmap |= FW_RA_INIT_CTL; - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - /* Clear control flag to sync with FW. */ - FW_CMD_IO_CLR(rtlpriv, FW_RA_INIT_CTL); - break; - case FW_CMD_DIG_DISABLE: - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Set DIG disable!!\n"); - fw_cmdmap &= ~FW_DIG_ENABLE_CTL; - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - break; - case FW_CMD_DIG_ENABLE: - case FW_CMD_DIG_RESUME: - if (!(rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE)) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Set DIG enable or resume!!\n"); - fw_cmdmap |= (FW_DIG_ENABLE_CTL | FW_SS_CTL); - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - } - break; - case FW_CMD_DIG_HALT: - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Set DIG halt!!\n"); - fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | FW_SS_CTL); - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - break; - case FW_CMD_TXPWR_TRACK_THERMAL: { - u8 thermalval = 0; - fw_cmdmap |= FW_PWR_TRK_CTL; - - /* Clear FW parameter in terms of thermal parts. */ - fw_param &= FW_PWR_TRK_PARAM_CLR; - - thermalval = rtlpriv->dm.thermalvalue; - fw_param |= ((thermalval << 24) | - (rtlefuse->thermalmeter[0] << 16)); - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Set TxPwr tracking!! FwCmdMap(%#x), FwParam(%#x)\n", - fw_cmdmap, fw_param); - - FW_CMD_PARA_SET(rtlpriv, fw_param); - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - - /* Clear control flag to sync with FW. */ - FW_CMD_IO_CLR(rtlpriv, FW_PWR_TRK_CTL); - } - break; - /* The following FW CMDs are only compatible to - * v.53 or later. */ - case FW_CMD_RA_REFRESH_N_COMB: - fw_cmdmap |= FW_RA_N_CTL; - - /* Clear RA BG mode control. */ - fw_cmdmap &= ~(FW_RA_BG_CTL | FW_RA_INIT_CTL); - - /* Clear FW parameter in terms of RA parts. */ - fw_param &= FW_RA_PARAM_CLR; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "[FW CMD] [New Version] Set RA/IOT Comb in n mode!! FwCmdMap(%#x), FwParam(%#x)\n", - fw_cmdmap, fw_param); - - FW_CMD_PARA_SET(rtlpriv, fw_param); - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - - /* Clear control flag to sync with FW. */ - FW_CMD_IO_CLR(rtlpriv, FW_RA_N_CTL); - break; - case FW_CMD_RA_REFRESH_BG_COMB: - fw_cmdmap |= FW_RA_BG_CTL; - - /* Clear RA n-mode control. */ - fw_cmdmap &= ~(FW_RA_N_CTL | FW_RA_INIT_CTL); - /* Clear FW parameter in terms of RA parts. */ - fw_param &= FW_RA_PARAM_CLR; - - FW_CMD_PARA_SET(rtlpriv, fw_param); - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - - /* Clear control flag to sync with FW. */ - FW_CMD_IO_CLR(rtlpriv, FW_RA_BG_CTL); - break; - case FW_CMD_IQK_ENABLE: - fw_cmdmap |= FW_IQK_CTL; - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - /* Clear control flag to sync with FW. */ - FW_CMD_IO_CLR(rtlpriv, FW_IQK_CTL); - break; - /* The following FW CMD is compatible to v.62 or later. */ - case FW_CMD_CTRL_DM_BY_DRIVER_NEW: - fw_cmdmap |= FW_DRIVER_CTRL_DM_CTL; - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - break; - /* The followed FW Cmds needs post-processing later. */ - case FW_CMD_RESUME_DM_BY_SCAN: - fw_cmdmap |= (FW_DIG_ENABLE_CTL | - FW_HIGH_PWR_ENABLE_CTL | - FW_SS_CTL); - - if (rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE || - !digtable->dig_enable_flag) - fw_cmdmap &= ~FW_DIG_ENABLE_CTL; - - if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) || - rtlpriv->dm.dynamic_txpower_enable) - fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; - - if ((digtable->dig_ext_port_stage == - DIG_EXT_PORT_STAGE_0) || - (digtable->dig_ext_port_stage == - DIG_EXT_PORT_STAGE_1)) - fw_cmdmap &= ~FW_DIG_ENABLE_CTL; - - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - postprocessing = true; - break; - case FW_CMD_PAUSE_DM_BY_SCAN: - fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | - FW_HIGH_PWR_ENABLE_CTL | - FW_SS_CTL); - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - postprocessing = true; - break; - case FW_CMD_HIGH_PWR_DISABLE: - fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - postprocessing = true; - break; - case FW_CMD_HIGH_PWR_ENABLE: - if (!(rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) && - !rtlpriv->dm.dynamic_txpower_enable) { - fw_cmdmap |= (FW_HIGH_PWR_ENABLE_CTL | - FW_SS_CTL); - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - postprocessing = true; - } - break; - case FW_CMD_DIG_MODE_FA: - fw_cmdmap |= FW_FA_CTL; - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - break; - case FW_CMD_DIG_MODE_SS: - fw_cmdmap &= ~FW_FA_CTL; - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - break; - case FW_CMD_PAPE_CONTROL: - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "[FW CMD] Set PAPE Control\n"); - fw_cmdmap &= ~FW_PAPE_CTL_BY_SW_HW; - - FW_CMD_IO_SET(rtlpriv, fw_cmdmap); - break; - default: - /* Pass to original FW CMD processing callback - * routine. */ - postprocessing = true; - break; - } - } while (false); - - /* We shall post processing these FW CMD if - * variable postprocessing is set. - */ - if (postprocessing && !rtlhal->set_fwcmd_inprogress) { - rtlhal->set_fwcmd_inprogress = true; - /* Update current FW Cmd for callback use. */ - rtlhal->current_fwcmd_io = fw_cmdio; - } else { - return false; - } - - _rtl92s_phy_set_fwcmd_io(hw); - return true; -} - -static void _rtl92s_phy_check_ephy_switchready(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 delay = 100; - u8 regu1; - - regu1 = rtl_read_byte(rtlpriv, 0x554); - while ((regu1 & BIT(5)) && (delay > 0)) { - regu1 = rtl_read_byte(rtlpriv, 0x554); - delay--; - /* We delay only 50us to prevent - * being scheduled out. */ - udelay(50); - } -} - -void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - /* The way to be capable to switch clock request - * when the PG setting does not support clock request. - * This is the backdoor solution to switch clock - * request before ASPM or D3. */ - rtl_write_dword(rtlpriv, 0x540, 0x73c11); - rtl_write_dword(rtlpriv, 0x548, 0x2407c); - - /* Switch EPHY parameter!!!! */ - rtl_write_word(rtlpriv, 0x550, 0x1000); - rtl_write_byte(rtlpriv, 0x554, 0x20); - _rtl92s_phy_check_ephy_switchready(hw); - - rtl_write_word(rtlpriv, 0x550, 0xa0eb); - rtl_write_byte(rtlpriv, 0x554, 0x3e); - _rtl92s_phy_check_ephy_switchready(hw); - - rtl_write_word(rtlpriv, 0x550, 0xff80); - rtl_write_byte(rtlpriv, 0x554, 0x39); - _rtl92s_phy_check_ephy_switchready(hw); - - /* Delay L1 enter time */ - if (ppsc->support_aspm && !ppsc->support_backdoor) - rtl_write_byte(rtlpriv, 0x560, 0x40); - else - rtl_write_byte(rtlpriv, 0x560, 0x00); - -} - -void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 beaconinterval) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 new_bcn_num = 0; - - if (hal_get_firmwareversion(rtlpriv) >= 0x33) { - /* Fw v.51 and later. */ - rtl_write_dword(rtlpriv, WFM5, 0xF1000000 | - (beaconinterval << 8)); - } else { - new_bcn_num = beaconinterval * 32 - 64; - rtl_write_dword(rtlpriv, WFM3 + 4, new_bcn_num); - rtl_write_dword(rtlpriv, WFM3, 0xB026007C); - } -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h b/drivers/net/wireless/rtlwifi/rtl8192se/phy.h deleted file mode 100644 index 8acf4765a7a6..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h +++ /dev/null @@ -1,102 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#ifndef __RTL92S_PHY_H__ -#define __RTL92S_PHY_H__ - -#define MAX_TXPWR_IDX_NMODE_92S 63 -#define MAX_DOZE_WAITING_TIMES_9x 64 - -/* Channel switch:The size of - * command tables for switch channel */ -#define MAX_PRECMD_CNT 16 -#define MAX_RFDEPENDCMD_CNT 16 -#define MAX_POSTCMD_CNT 16 - -#define RF90_PATH_MAX 4 -#define RF6052_MAX_PATH 2 - -enum version_8192s { - VERSION_8192S_ACUT, - VERSION_8192S_BCUT, - VERSION_8192S_CCUT -}; - -enum swchnlcmd_id { - CMDID_END, - CMDID_SET_TXPOWEROWER_LEVEL, - CMDID_BBREGWRITE10, - CMDID_WRITEPORT_ULONG, - CMDID_WRITEPORT_USHORT, - CMDID_WRITEPORT_UCHAR, - CMDID_RF_WRITEREG, -}; - -struct swchnlcmd { - enum swchnlcmd_id cmdid; - u32 para1; - u32 para2; - u32 msdelay; -}; - -enum baseband_config_type { - /* Radio Path A */ - BASEBAND_CONFIG_PHY_REG = 0, - /* Radio Path B */ - BASEBAND_CONFIG_AGC_TAB = 1, -}; - -#define hal_get_firmwareversion(rtlpriv) \ - (((struct rt_firmware *)(rtlpriv->rtlhal.pfirmware))->firmwareversion) - -u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); -void rtl92s_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, - u32 data); -void rtl92s_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); -u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask); -void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data); -void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); -u8 rtl92s_phy_sw_chnl(struct ieee80211_hw *hw); -bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpower_state); -bool rtl92s_phy_mac_config(struct ieee80211_hw *hw); -void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw); -bool rtl92s_phy_bb_config(struct ieee80211_hw *hw); -bool rtl92s_phy_rf_config(struct ieee80211_hw *hw); -void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel); -bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fwcmd_io); -void rtl92s_phy_chk_fwcmd_iodone(struct ieee80211_hw *hw); -void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 beaconinterval); -u8 rtl92s_phy_config_rf(struct ieee80211_hw *hw, enum radio_path rfpath) ; - -#endif - diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h deleted file mode 100644 index e13043479b71..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h +++ /dev/null @@ -1,1168 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#ifndef __REALTEK_92S_REG_H__ -#define __REALTEK_92S_REG_H__ - -/* 1. System Configuration Registers */ -#define REG_SYS_ISO_CTRL 0x0000 -#define REG_SYS_FUNC_EN 0x0002 -#define PMC_FSM 0x0004 -#define SYS_CLKR 0x0008 -#define EPROM_CMD 0x000A -#define EE_VPD 0x000C -#define AFE_MISC 0x0010 -#define SPS0_CTRL 0x0011 -#define SPS1_CTRL 0x0018 -#define RF_CTRL 0x001F -#define LDOA15_CTRL 0x0020 -#define LDOV12D_CTRL 0x0021 -#define LDOHCI12_CTRL 0x0022 -#define LDO_USB_SDIO 0x0023 -#define LPLDO_CTRL 0x0024 -#define AFE_XTAL_CTRL 0x0026 -#define AFE_PLL_CTRL 0x0028 -#define REG_EFUSE_CTRL 0x0030 -#define REG_EFUSE_TEST 0x0034 -#define PWR_DATA 0x0038 -#define DBG_PORT 0x003A -#define DPS_TIMER 0x003C -#define RCLK_MON 0x003E - -/* 2. Command Control Registers */ -#define CMDR 0x0040 -#define TXPAUSE 0x0042 -#define LBKMD_SEL 0x0043 -#define TCR 0x0044 -#define RCR 0x0048 -#define MSR 0x004C -#define SYSF_CFG 0x004D -#define RX_PKY_LIMIT 0x004E -#define MBIDCTRL 0x004F - -/* 3. MACID Setting Registers */ -#define MACIDR 0x0050 -#define MACIDR0 0x0050 -#define MACIDR4 0x0054 -#define BSSIDR 0x0058 -#define HWVID 0x005E -#define MAR 0x0060 -#define MBIDCAMCONTENT 0x0068 -#define MBIDCAMCFG 0x0070 -#define BUILDTIME 0x0074 -#define BUILDUSER 0x0078 - -#define IDR0 MACIDR0 -#define IDR4 MACIDR4 - -/* 4. Timing Control Registers */ -#define TSFR 0x0080 -#define SLOT_TIME 0x0089 -#define USTIME 0x008A -#define SIFS_CCK 0x008C -#define SIFS_OFDM 0x008E -#define PIFS_TIME 0x0090 -#define ACK_TIMEOUT 0x0091 -#define EIFSTR 0x0092 -#define BCN_INTERVAL 0x0094 -#define ATIMWND 0x0096 -#define BCN_DRV_EARLY_INT 0x0098 -#define BCN_DMATIME 0x009A -#define BCN_ERR_THRESH 0x009C -#define MLT 0x009D -#define RSVD_MAC_TUNE_US 0x009E - -/* 5. FIFO Control Registers */ -#define RQPN 0x00A0 -#define RQPN1 0x00A0 -#define RQPN2 0x00A1 -#define RQPN3 0x00A2 -#define RQPN4 0x00A3 -#define RQPN5 0x00A4 -#define RQPN6 0x00A5 -#define RQPN7 0x00A6 -#define RQPN8 0x00A7 -#define RQPN9 0x00A8 -#define RQPN10 0x00A9 -#define LD_RQPN 0x00AB -#define RXFF_BNDY 0x00AC -#define RXRPT_BNDY 0x00B0 -#define TXPKTBUF_PGBNDY 0x00B4 -#define PBP 0x00B5 -#define RXDRVINFO_SZ 0x00B6 -#define TXFF_STATUS 0x00B7 -#define RXFF_STATUS 0x00B8 -#define TXFF_EMPTY_TH 0x00B9 -#define SDIO_RX_BLKSZ 0x00BC -#define RXDMA 0x00BD -#define RXPKT_NUM 0x00BE -#define C2HCMD_UDT_SIZE 0x00C0 -#define C2HCMD_UDT_ADDR 0x00C2 -#define FIFOPAGE1 0x00C4 -#define FIFOPAGE2 0x00C8 -#define FIFOPAGE3 0x00CC -#define FIFOPAGE4 0x00D0 -#define FIFOPAGE5 0x00D4 -#define FW_RSVD_PG_CRTL 0x00D8 -#define RXDMA_AGG_PG_TH 0x00D9 -#define TXDESC_MSK 0x00DC -#define TXRPTFF_RDPTR 0x00E0 -#define TXRPTFF_WTPTR 0x00E4 -#define C2HFF_RDPTR 0x00E8 -#define C2HFF_WTPTR 0x00EC -#define RXFF0_RDPTR 0x00F0 -#define RXFF0_WTPTR 0x00F4 -#define RXFF1_RDPTR 0x00F8 -#define RXFF1_WTPTR 0x00FC -#define RXRPT0_RDPTR 0x0100 -#define RXRPT0_WTPTR 0x0104 -#define RXRPT1_RDPTR 0x0108 -#define RXRPT1_WTPTR 0x010C -#define RX0_UDT_SIZE 0x0110 -#define RX1PKTNUM 0x0114 -#define RXFILTERMAP 0x0116 -#define RXFILTERMAP_GP1 0x0118 -#define RXFILTERMAP_GP2 0x011A -#define RXFILTERMAP_GP3 0x011C -#define BCNQ_CTRL 0x0120 -#define MGTQ_CTRL 0x0124 -#define HIQ_CTRL 0x0128 -#define VOTID7_CTRL 0x012c -#define VOTID6_CTRL 0x0130 -#define VITID5_CTRL 0x0134 -#define VITID4_CTRL 0x0138 -#define BETID3_CTRL 0x013c -#define BETID0_CTRL 0x0140 -#define BKTID2_CTRL 0x0144 -#define BKTID1_CTRL 0x0148 -#define CMDQ_CTRL 0x014c -#define TXPKT_NUM_CTRL 0x0150 -#define TXQ_PGADD 0x0152 -#define TXFF_PG_NUM 0x0154 -#define TRXDMA_STATUS 0x0156 - -/* 6. Adaptive Control Registers */ -#define INIMCS_SEL 0x0160 -#define TX_RATE_REG INIMCS_SEL -#define INIRTSMCS_SEL 0x0180 -#define RRSR 0x0181 -#define ARFR0 0x0184 -#define ARFR1 0x0188 -#define ARFR2 0x018C -#define ARFR3 0x0190 -#define ARFR4 0x0194 -#define ARFR5 0x0198 -#define ARFR6 0x019C -#define ARFR7 0x01A0 -#define AGGLEN_LMT_H 0x01A7 -#define AGGLEN_LMT_L 0x01A8 -#define DARFRC 0x01B0 -#define RARFRC 0x01B8 -#define MCS_TXAGC 0x01C0 -#define CCK_TXAGC 0x01C8 - -/* 7. EDCA Setting Registers */ -#define EDCAPARA_VO 0x01D0 -#define EDCAPARA_VI 0x01D4 -#define EDCAPARA_BE 0x01D8 -#define EDCAPARA_BK 0x01DC -#define BCNTCFG 0x01E0 -#define CWRR 0x01E2 -#define ACMAVG 0x01E4 -#define AcmHwCtrl 0x01E7 -#define VO_ADMTM 0x01E8 -#define VI_ADMTM 0x01EC -#define BE_ADMTM 0x01F0 -#define RETRY_LIMIT 0x01F4 -#define SG_RATE 0x01F6 - -/* 8. WMAC, BA and CCX related Register. */ -#define NAV_CTRL 0x0200 -#define BW_OPMODE 0x0203 -#define BACAMCMD 0x0204 -#define BACAMCONTENT 0x0208 - -/* the 0x2xx register WMAC definition */ -#define LBDLY 0x0210 -#define FWDLY 0x0211 -#define HWPC_RX_CTRL 0x0218 -#define MQIR 0x0220 -#define MAIR 0x0222 -#define MSIR 0x0224 -#define CLM_RESULT 0x0227 -#define NHM_RPI_CNT 0x0228 -#define RXERR_RPT 0x0230 -#define NAV_PROT_LEN 0x0234 -#define CFEND_TH 0x0236 -#define AMPDU_MIN_SPACE 0x0237 -#define TXOP_STALL_CTRL 0x0238 - -/* 9. Security Control Registers */ -#define REG_RWCAM 0x0240 -#define REG_WCAMI 0x0244 -#define REG_RCAMO 0x0248 -#define REG_CAMDBG 0x024C -#define REG_SECR 0x0250 - -/* 10. Power Save Control Registers */ -#define WOW_CTRL 0x0260 -#define PSSTATUS 0x0261 -#define PSSWITCH 0x0262 -#define MIMOPS_WAIT_PERIOD 0x0263 -#define LPNAV_CTRL 0x0264 -#define WFM0 0x0270 -#define WFM1 0x0280 -#define WFM2 0x0290 -#define WFM3 0x02A0 -#define WFM4 0x02B0 -#define WFM5 0x02C0 -#define WFCRC 0x02D0 -#define FW_RPT_REG 0x02c4 - -/* 11. General Purpose Registers */ -#define PSTIME 0x02E0 -#define TIMER0 0x02E4 -#define TIMER1 0x02E8 -#define GPIO_IN_SE 0x02EC -#define GPIO_IO_SEL 0x02EE -#define MAC_PINMUX_CFG 0x02F1 -#define LEDCFG 0x02F2 -#define PHY_REG 0x02F3 -#define PHY_REG_DATA 0x02F4 -#define REG_EFUSE_CLK 0x02F8 - -/* 12. Host Interrupt Status Registers */ -#define INTA_MASK 0x0300 -#define ISR 0x0308 - -/* 13. Test Mode and Debug Control Registers */ -#define DBG_PORT_SWITCH 0x003A -#define BIST 0x0310 -#define DBS 0x0314 -#define CPUINST 0x0318 -#define CPUCAUSE 0x031C -#define LBUS_ERR_ADDR 0x0320 -#define LBUS_ERR_CMD 0x0324 -#define LBUS_ERR_DATA_L 0x0328 -#define LBUS_ERR_DATA_H 0x032C -#define LX_EXCEPTION_ADDR 0x0330 -#define WDG_CTRL 0x0334 -#define INTMTU 0x0338 -#define INTM 0x033A -#define FDLOCKTURN0 0x033C -#define FDLOCKTURN1 0x033D -#define TRXPKTBUF_DBG_DATA 0x0340 -#define TRXPKTBUF_DBG_CTRL 0x0348 -#define DPLL 0x034A -#define CBUS_ERR_ADDR 0x0350 -#define CBUS_ERR_CMD 0x0354 -#define CBUS_ERR_DATA_L 0x0358 -#define CBUS_ERR_DATA_H 0x035C -#define USB_SIE_INTF_ADDR 0x0360 -#define USB_SIE_INTF_WD 0x0361 -#define USB_SIE_INTF_RD 0x0362 -#define USB_SIE_INTF_CTRL 0x0363 -#define LBUS_MON_ADDR 0x0364 -#define LBUS_ADDR_MASK 0x0368 - -/* Boundary is 0x37F */ - -/* 14. PCIE config register */ -#define TP_POLL 0x0500 -#define PM_CTRL 0x0502 -#define PCIF 0x0503 - -#define THPDA 0x0514 -#define TMDA 0x0518 -#define TCDA 0x051C -#define HDA 0x0520 -#define TVODA 0x0524 -#define TVIDA 0x0528 -#define TBEDA 0x052C -#define TBKDA 0x0530 -#define TBDA 0x0534 -#define RCDA 0x0538 -#define RDQDA 0x053C -#define DBI_WDATA 0x0540 -#define DBI_RDATA 0x0544 -#define DBI_CTRL 0x0548 -#define MDIO_DATA 0x0550 -#define MDIO_CTRL 0x0554 -#define PCI_RPWM 0x0561 -#define PCI_CPWM 0x0563 - -/* Config register (Offset 0x800-) */ -#define PHY_CCA 0x803 - -/* Min Spacing related settings. */ -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -/* Rx DMA Control related settings */ -#define RXDMA_AGG_EN BIT(7) - -#define RPWM PCI_RPWM - -/* Regsiter Bit and Content definition */ - -#define ISO_MD2PP BIT(0) -#define ISO_PA2PCIE BIT(3) -#define ISO_PLL2MD BIT(4) -#define ISO_PWC_DV2RP BIT(11) -#define ISO_PWC_RV2RP BIT(12) - - -#define FEN_MREGEN BIT(15) -#define FEN_DCORE BIT(11) -#define FEN_CPUEN BIT(10) - -#define PAD_HWPD_IDN BIT(22) - -#define SYS_CLKSEL_80M BIT(0) -#define SYS_PS_CLKSEL BIT(1) -#define SYS_CPU_CLKSEL BIT(2) -#define SYS_MAC_CLK_EN BIT(11) -#define SYS_SWHW_SEL BIT(14) -#define SYS_FWHW_SEL BIT(15) - -#define CmdEEPROM_En BIT(5) -#define CmdEERPOMSEL BIT(4) -#define Cmd9346CR_9356SEL BIT(4) - -#define AFE_MBEN BIT(1) -#define AFE_BGEN BIT(0) - -#define SPS1_SWEN BIT(1) -#define SPS1_LDEN BIT(0) - -#define RF_EN BIT(0) -#define RF_RSTB BIT(1) -#define RF_SDMRSTB BIT(2) - -#define LDA15_EN BIT(0) - -#define LDV12_EN BIT(0) -#define LDV12_SDBY BIT(1) - -#define XTAL_GATE_AFE BIT(10) - -#define APLL_EN BIT(0) - -#define AFR_CardBEn BIT(0) -#define AFR_CLKRUN_SEL BIT(1) -#define AFR_FuncRegEn BIT(2) - -#define APSDOFF_STATUS BIT(15) -#define APSDOFF BIT(14) -#define BBRSTN BIT(13) -#define BB_GLB_RSTN BIT(12) -#define SCHEDULE_EN BIT(10) -#define MACRXEN BIT(9) -#define MACTXEN BIT(8) -#define DDMA_EN BIT(7) -#define FW2HW_EN BIT(6) -#define RXDMA_EN BIT(5) -#define TXDMA_EN BIT(4) -#define HCI_RXDMA_EN BIT(3) -#define HCI_TXDMA_EN BIT(2) - -#define StopHCCA BIT(6) -#define StopHigh BIT(5) -#define StopMgt BIT(4) -#define StopVO BIT(3) -#define StopVI BIT(2) -#define StopBE BIT(1) -#define StopBK BIT(0) - -#define LBK_NORMAL 0x00 -#define LBK_MAC_LB (BIT(0) | BIT(1) | BIT(3)) -#define LBK_MAC_DLB (BIT(0) | BIT(1)) -#define LBK_DMA_LB (BIT(0) | BIT(1) | BIT(2)) - -#define TCP_OFDL_EN BIT(25) -#define HWPC_TX_EN BIT(24) -#define TXDMAPRE2FULL BIT(23) -#define DISCW BIT(20) -#define TCRICV BIT(19) -#define CfendForm BIT(17) -#define TCRCRC BIT(16) -#define FAKE_IMEM_EN BIT(15) -#define TSFRST BIT(9) -#define TSFEN BIT(8) -#define FWALLRDY (BIT(0) | BIT(1) | BIT(2) | \ - BIT(3) | BIT(4) | BIT(5) | \ - BIT(6) | BIT(7)) -#define FWRDY BIT(7) -#define BASECHG BIT(6) -#define IMEM BIT(5) -#define DMEM_CODE_DONE BIT(4) -#define EXT_IMEM_CHK_RPT BIT(3) -#define EXT_IMEM_CODE_DONE BIT(2) -#define IMEM_CHK_RPT BIT(1) -#define IMEM_CODE_DONE BIT(0) -#define EMEM_CODE_DONE BIT(2) -#define EMEM_CHK_RPT BIT(3) -#define IMEM_RDY BIT(5) -#define LOAD_FW_READY (IMEM_CODE_DONE | \ - IMEM_CHK_RPT | \ - EMEM_CODE_DONE | \ - EMEM_CHK_RPT | \ - DMEM_CODE_DONE | \ - IMEM_RDY | \ - BASECHG | \ - FWRDY) -#define TCR_TSFEN BIT(8) -#define TCR_TSFRST BIT(9) -#define TCR_FAKE_IMEM_EN BIT(15) -#define TCR_CRC BIT(16) -#define TCR_ICV BIT(19) -#define TCR_DISCW BIT(20) -#define TCR_HWPC_TX_EN BIT(24) -#define TCR_TCP_OFDL_EN BIT(25) -#define TXDMA_INIT_VALUE (IMEM_CHK_RPT | \ - EXT_IMEM_CHK_RPT) - -#define RCR_APPFCS BIT(31) -#define RCR_DIS_ENC_2BYTE BIT(30) -#define RCR_DIS_AES_2BYTE BIT(29) -#define RCR_HTC_LOC_CTRL BIT(28) -#define RCR_ENMBID BIT(27) -#define RCR_RX_TCPOFDL_EN BIT(26) -#define RCR_APP_PHYST_RXFF BIT(25) -#define RCR_APP_PHYST_STAFF BIT(24) -#define RCR_CBSSID BIT(23) -#define RCR_APWRMGT BIT(22) -#define RCR_ADD3 BIT(21) -#define RCR_AMF BIT(20) -#define RCR_ACF BIT(19) -#define RCR_ADF BIT(18) -#define RCR_APP_MIC BIT(17) -#define RCR_APP_ICV BIT(16) -#define RCR_RXFTH BIT(13) -#define RCR_AICV BIT(12) -#define RCR_RXDESC_LK_EN BIT(11) -#define RCR_APP_BA_SSN BIT(6) -#define RCR_ACRC32 BIT(5) -#define RCR_RXSHFT_EN BIT(4) -#define RCR_AB BIT(3) -#define RCR_AM BIT(2) -#define RCR_APM BIT(1) -#define RCR_AAP BIT(0) -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - - -#define MSR_LINK_MASK ((1 << 0) | (1 << 1)) -#define MSR_LINK_MANAGED 2 -#define MSR_LINK_NONE 0 -#define MSR_LINK_SHIFT 0 -#define MSR_LINK_ADHOC 1 -#define MSR_LINK_MASTER 3 -#define MSR_NOLINK 0x00 -#define MSR_ADHOC 0x01 -#define MSR_INFRA 0x02 -#define MSR_AP 0x03 - -#define ENUART BIT(7) -#define ENJTAG BIT(3) -#define BTMODE (BIT(2) | BIT(1)) -#define ENBT BIT(0) - -#define ENMBID BIT(7) -#define BCNUM (BIT(6) | BIT(5) | BIT(4)) - -#define USTIME_EDCA 0xFF00 -#define USTIME_TSF 0x00FF - -#define SIFS_TRX 0xFF00 -#define SIFS_CTX 0x00FF - -#define ENSWBCN BIT(15) -#define DRVERLY_TU 0x0FF0 -#define DRVERLY_US 0x000F -#define BCN_TCFG_CW_SHIFT 8 -#define BCN_TCFG_IFS 0 - -#define RRSR_RSC_OFFSET 21 -#define RRSR_SHORT_OFFSET 23 -#define RRSR_RSC_BW_40M 0x600000 -#define RRSR_RSC_UPSUBCHNL 0x400000 -#define RRSR_RSC_LOWSUBCHNL 0x200000 -#define RRSR_SHORT 0x800000 -#define RRSR_1M BIT(0) -#define RRSR_2M BIT(1) -#define RRSR_5_5M BIT(2) -#define RRSR_11M BIT(3) -#define RRSR_6M BIT(4) -#define RRSR_9M BIT(5) -#define RRSR_12M BIT(6) -#define RRSR_18M BIT(7) -#define RRSR_24M BIT(8) -#define RRSR_36M BIT(9) -#define RRSR_48M BIT(10) -#define RRSR_54M BIT(11) -#define RRSR_MCS0 BIT(12) -#define RRSR_MCS1 BIT(13) -#define RRSR_MCS2 BIT(14) -#define RRSR_MCS3 BIT(15) -#define RRSR_MCS4 BIT(16) -#define RRSR_MCS5 BIT(17) -#define RRSR_MCS6 BIT(18) -#define RRSR_MCS7 BIT(19) -#define BRSR_AckShortPmb BIT(23) - -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 -#define RATR_MCS8 0x00100000 -#define RATR_MCS9 0x00200000 -#define RATR_MCS10 0x00400000 -#define RATR_MCS11 0x00800000 -#define RATR_MCS12 0x01000000 -#define RATR_MCS13 0x02000000 -#define RATR_MCS14 0x04000000 -#define RATR_MCS15 0x08000000 - -#define RATE_ALL_CCK (RATR_1M | RATR_2M | \ - RATR_55M | RATR_11M) -#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | \ - RATR_12M | RATR_18M | \ - RATR_24M | RATR_36M | \ - RATR_48M | RATR_54M) -#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | \ - RATR_MCS2 | RATR_MCS3 | \ - RATR_MCS4 | RATR_MCS5 | \ - RATR_MCS6 | RATR_MCS7) -#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | \ - RATR_MCS10 | RATR_MCS11 | \ - RATR_MCS12 | RATR_MCS13 | \ - RATR_MCS14 | RATR_MCS15) - -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - -#define AcmHw_HwEn BIT(0) -#define AcmHw_BeqEn BIT(1) -#define AcmHw_ViqEn BIT(2) -#define AcmHw_VoqEn BIT(3) -#define AcmHw_BeqStatus BIT(4) -#define AcmHw_ViqStatus BIT(5) -#define AcmHw_VoqStatus BIT(6) - -#define RETRY_LIMIT_SHORT_SHIFT 8 -#define RETRY_LIMIT_LONG_SHIFT 0 - -#define NAV_UPPER_EN BIT(16) -#define NAV_UPPER 0xFF00 -#define NAV_RTSRST 0xFF - -#define BW_OPMODE_20MHZ BIT(2) -#define BW_OPMODE_5G BIT(1) -#define BW_OPMODE_11J BIT(0) - -#define RXERR_RPT_RST BIT(27) -#define RXERR_OFDM_PPDU 0 -#define RXERR_OFDM_FALSE_ALARM 1 -#define RXERR_OFDM_MPDU_OK 2 -#define RXERR_OFDM_MPDU_FAIL 3 -#define RXERR_CCK_PPDU 4 -#define RXERR_CCK_FALSE_ALARM 5 -#define RXERR_CCK_MPDU_OK 6 -#define RXERR_CCK_MPDU_FAIL 7 -#define RXERR_HT_PPDU 8 -#define RXERR_HT_FALSE_ALARM 9 -#define RXERR_HT_MPDU_TOTAL 10 -#define RXERR_HT_MPDU_OK 11 -#define RXERR_HT_MPDU_FAIL 12 -#define RXERR_RX_FULL_DROP 15 - -#define SCR_TXUSEDK BIT(0) -#define SCR_RXUSEDK BIT(1) -#define SCR_TXENCENABLE BIT(2) -#define SCR_RXENCENABLE BIT(3) -#define SCR_SKBYA2 BIT(4) -#define SCR_NOSKMC BIT(5) - -#define CAM_VALID BIT(15) -#define CAM_NOTVALID 0x0000 -#define CAM_USEDK BIT(5) - -#define CAM_NONE 0x0 -#define CAM_WEP40 0x01 -#define CAM_TKIP 0x02 -#define CAM_AES 0x04 -#define CAM_WEP104 0x05 - -#define TOTAL_CAM_ENTRY 32 -#define HALF_CAM_ENTRY 16 - -#define CAM_WRITE BIT(16) -#define CAM_READ 0x00000000 -#define CAM_POLLINIG BIT(31) - -#define WOW_PMEN BIT(0) -#define WOW_WOMEN BIT(1) -#define WOW_MAGIC BIT(2) -#define WOW_UWF BIT(3) - -#define GPIOMUX_EN BIT(3) -#define GPIOSEL_GPIO 0 -#define GPIOSEL_PHYDBG 1 -#define GPIOSEL_BT 2 -#define GPIOSEL_WLANDBG 3 -#define GPIOSEL_GPIO_MASK (~(BIT(0)|BIT(1))) - -#define HST_RDBUSY BIT(0) -#define CPU_WTBUSY BIT(1) - -#define IMR8190_DISABLED 0x0 -#define IMR_CPUERR BIT(5) -#define IMR_ATIMEND BIT(4) -#define IMR_TBDOK BIT(3) -#define IMR_TBDER BIT(2) -#define IMR_BCNDMAINT8 BIT(1) -#define IMR_BCNDMAINT7 BIT(0) -#define IMR_BCNDMAINT6 BIT(31) -#define IMR_BCNDMAINT5 BIT(30) -#define IMR_BCNDMAINT4 BIT(29) -#define IMR_BCNDMAINT3 BIT(28) -#define IMR_BCNDMAINT2 BIT(27) -#define IMR_BCNDMAINT1 BIT(26) -#define IMR_BCNDOK8 BIT(25) -#define IMR_BCNDOK7 BIT(24) -#define IMR_BCNDOK6 BIT(23) -#define IMR_BCNDOK5 BIT(22) -#define IMR_BCNDOK4 BIT(21) -#define IMR_BCNDOK3 BIT(20) -#define IMR_BCNDOK2 BIT(19) -#define IMR_BCNDOK1 BIT(18) -#define IMR_TIMEOUT2 BIT(17) -#define IMR_TIMEOUT1 BIT(16) -#define IMR_TXFOVW BIT(15) -#define IMR_PSTIMEOUT BIT(14) -#define IMR_BCNINT BIT(13) -#define IMR_RXFOVW BIT(12) -#define IMR_RDU BIT(11) -#define IMR_RXCMDOK BIT(10) -#define IMR_BDOK BIT(9) -#define IMR_HIGHDOK BIT(8) -#define IMR_COMDOK BIT(7) -#define IMR_MGNTDOK BIT(6) -#define IMR_HCCADOK BIT(5) -#define IMR_BKDOK BIT(4) -#define IMR_BEDOK BIT(3) -#define IMR_VIDOK BIT(2) -#define IMR_VODOK BIT(1) -#define IMR_ROK BIT(0) - -#define TPPOLL_BKQ BIT(0) -#define TPPOLL_BEQ BIT(1) -#define TPPOLL_VIQ BIT(2) -#define TPPOLL_VOQ BIT(3) -#define TPPOLL_BQ BIT(4) -#define TPPOLL_CQ BIT(5) -#define TPPOLL_MQ BIT(6) -#define TPPOLL_HQ BIT(7) -#define TPPOLL_HCCAQ BIT(8) -#define TPPOLL_STOPBK BIT(9) -#define TPPOLL_STOPBE BIT(10) -#define TPPOLL_STOPVI BIT(11) -#define TPPOLL_STOPVO BIT(12) -#define TPPOLL_STOPMGT BIT(13) -#define TPPOLL_STOPHIGH BIT(14) -#define TPPOLL_STOPHCCA BIT(15) -#define TPPOLL_SHIFT 8 - -#define CCX_CMD_CLM_ENABLE BIT(0) -#define CCX_CMD_NHM_ENABLE BIT(1) -#define CCX_CMD_FUNCTION_ENABLE BIT(8) -#define CCX_CMD_IGNORE_CCA BIT(9) -#define CCX_CMD_IGNORE_TXON BIT(10) -#define CCX_CLM_RESULT_READY BIT(16) -#define CCX_NHM_RESULT_READY BIT(16) -#define CCX_CMD_RESET 0x0 - - -#define HWSET_MAX_SIZE_92S 128 -#define EFUSE_MAX_SECTION 16 -#define EFUSE_REAL_CONTENT_LEN 512 -#define EFUSE_OOB_PROTECT_BYTES 15 - -#define RTL8190_EEPROM_ID 0x8129 -#define EEPROM_HPON 0x02 -#define EEPROM_CLK 0x06 -#define EEPROM_TESTR 0x08 - -#define EEPROM_VID 0x0A -#define EEPROM_DID 0x0C -#define EEPROM_SVID 0x0E -#define EEPROM_SMID 0x10 - -#define EEPROM_MAC_ADDR 0x12 -#define EEPROM_NODE_ADDRESS_BYTE_0 0x12 - -#define EEPROM_PWDIFF 0x54 - -#define EEPROM_TXPOWERBASE 0x50 -#define EEPROM_TX_PWR_INDEX_RANGE 28 - -#define EEPROM_TX_PWR_HT20_DIFF 0x62 -#define DEFAULT_HT20_TXPWR_DIFF 2 -#define EEPROM_TX_PWR_OFDM_DIFF 0x65 - -#define EEPROM_TXPWRGROUP 0x67 -#define EEPROM_REGULATORY 0x6D - -#define TX_PWR_SAFETY_CHK 0x6D -#define EEPROM_TXPWINDEX_CCK_24G 0x5D -#define EEPROM_TXPWINDEX_OFDM_24G 0x6B -#define EEPROM_HT2T_CH1_A 0x6c -#define EEPROM_HT2T_CH7_A 0x6d -#define EEPROM_HT2T_CH13_A 0x6e -#define EEPROM_HT2T_CH1_B 0x6f -#define EEPROM_HT2T_CH7_B 0x70 -#define EEPROM_HT2T_CH13_B 0x71 - -#define EEPROM_TSSI_A 0x74 -#define EEPROM_TSSI_B 0x75 - -#define EEPROM_RFIND_POWERDIFF 0x76 -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 - -#define EEPROM_THERMALMETER 0x77 -#define EEPROM_BLUETOOTH_COEXIST 0x78 -#define EEPROM_BLUETOOTH_TYPE 0x4f - -#define EEPROM_OPTIONAL 0x78 -#define EEPROM_WOWLAN 0x78 - -#define EEPROM_CRYSTALCAP 0x79 -#define EEPROM_CHANNELPLAN 0x7B -#define EEPROM_VERSION 0x7C -#define EEPROM_CUSTOMID 0x7A -#define EEPROM_BOARDTYPE 0x7E - -#define EEPROM_CHANNEL_PLAN_FCC 0x0 -#define EEPROM_CHANNEL_PLAN_IC 0x1 -#define EEPROM_CHANNEL_PLAN_ETSI 0x2 -#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 -#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 -#define EEPROM_CHANNEL_PLAN_MKK 0x5 -#define EEPROM_CHANNEL_PLAN_MKK1 0x6 -#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 -#define EEPROM_CHANNEL_PLAN_TELEC 0x8 -#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 -#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -#define EEPROM_CHANNEL_PLAN_NCC 0xB -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - -#define FW_DIG_DISABLE 0xfd00cc00 -#define FW_DIG_ENABLE 0xfd000000 -#define FW_DIG_HALT 0xfd000001 -#define FW_DIG_RESUME 0xfd000002 -#define FW_HIGH_PWR_DISABLE 0xfd000008 -#define FW_HIGH_PWR_ENABLE 0xfd000009 -#define FW_ADD_A2_ENTRY 0xfd000016 -#define FW_TXPWR_TRACK_ENABLE 0xfd000017 -#define FW_TXPWR_TRACK_DISABLE 0xfd000018 -#define FW_TXPWR_TRACK_THERMAL 0xfd000019 -#define FW_TXANT_SWITCH_ENABLE 0xfd000023 -#define FW_TXANT_SWITCH_DISABLE 0xfd000024 -#define FW_RA_INIT 0xfd000026 -#define FW_CTRL_DM_BY_DRIVER 0Xfd00002a -#define FW_RA_IOT_BG_COMB 0xfd000030 -#define FW_RA_IOT_N_COMB 0xfd000031 -#define FW_RA_REFRESH 0xfd0000a0 -#define FW_RA_UPDATE_MASK 0xfd0000a2 -#define FW_RA_DISABLE 0xfd0000a4 -#define FW_RA_ACTIVE 0xfd0000a6 -#define FW_RA_DISABLE_RSSI_MASK 0xfd0000ac -#define FW_RA_ENABLE_RSSI_MASK 0xfd0000ad -#define FW_RA_RESET 0xfd0000af -#define FW_DM_DISABLE 0xfd00aa00 -#define FW_IQK_ENABLE 0xf0000020 -#define FW_IQK_SUCCESS 0x0000dddd -#define FW_IQK_FAIL 0x0000ffff -#define FW_OP_FAILURE 0xffffffff -#define FW_TX_FEEDBACK_NONE 0xfb000000 -#define FW_TX_FEEDBACK_DTM_ENABLE (FW_TX_FEEDBACK_NONE | 0x1) -#define FW_TX_FEEDBACK_CCX_ENABL (FW_TX_FEEDBACK_NONE | 0x2) -#define FW_BB_RESET_ENABLE 0xff00000d -#define FW_BB_RESET_DISABLE 0xff00000e -#define FW_CCA_CHK_ENABLE 0xff000011 -#define FW_CCK_RESET_CNT 0xff000013 -#define FW_LPS_ENTER 0xfe000010 -#define FW_LPS_LEAVE 0xfe000011 -#define FW_INDIRECT_READ 0xf2000000 -#define FW_INDIRECT_WRITE 0xf2000001 -#define FW_CHAN_SET 0xf3000001 - -#define RFPC 0x5F -#define RCR_9356SEL BIT(6) -#define TCR_LRL_OFFSET 0 -#define TCR_SRL_OFFSET 8 -#define TCR_MXDMA_OFFSET 21 -#define TCR_SAT BIT(24) -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 -#define RCR_OnlyErlPkt BIT(31) -#define CWR 0xDC -#define RETRYCTR 0xDE - -#define CPU_GEN_SYSTEM_RESET 0x00000001 - -#define CCX_COMMAND_REG 0x890 -#define CLM_PERIOD_REG 0x894 -#define NHM_PERIOD_REG 0x896 - -#define NHM_THRESHOLD0 0x898 -#define NHM_THRESHOLD1 0x899 -#define NHM_THRESHOLD2 0x89A -#define NHM_THRESHOLD3 0x89B -#define NHM_THRESHOLD4 0x89C -#define NHM_THRESHOLD5 0x89D -#define NHM_THRESHOLD6 0x89E -#define CLM_RESULT_REG 0x8D0 -#define NHM_RESULT_REG 0x8D4 -#define NHM_RPI_COUNTER0 0x8D8 -#define NHM_RPI_COUNTER1 0x8D9 -#define NHM_RPI_COUNTER2 0x8DA -#define NHM_RPI_COUNTER3 0x8DB -#define NHM_RPI_COUNTER4 0x8DC -#define NHM_RPI_COUNTER5 0x8DD -#define NHM_RPI_COUNTER6 0x8DE -#define NHM_RPI_COUNTER7 0x8DF - -#define HAL_8192S_HW_GPIO_OFF_BIT BIT(3) -#define HAL_8192S_HW_GPIO_OFF_MASK 0xF7 -#define HAL_8192S_HW_GPIO_WPS_BIT BIT(4) - -#define RPMAC_RESET 0x100 -#define RPMAC_TXSTART 0x104 -#define RPMAC_TXLEGACYSIG 0x108 -#define RPMAC_TXHTSIG1 0x10c -#define RPMAC_TXHTSIG2 0x110 -#define RPMAC_PHYDEBUG 0x114 -#define RPMAC_TXPACKETNNM 0x118 -#define RPMAC_TXIDLE 0x11c -#define RPMAC_TXMACHEADER0 0x120 -#define RPMAC_TXMACHEADER1 0x124 -#define RPMAC_TXMACHEADER2 0x128 -#define RPMAC_TXMACHEADER3 0x12c -#define RPMAC_TXMACHEADER4 0x130 -#define RPMAC_TXMACHEADER5 0x134 -#define RPMAC_TXDATATYPE 0x138 -#define RPMAC_TXRANDOMSEED 0x13c -#define RPMAC_CCKPLCPPREAMBLE 0x140 -#define RPMAC_CCKPLCPHEADER 0x144 -#define RPMAC_CCKCRC16 0x148 -#define RPMAC_OFDMRXCRC32OK 0x170 -#define RPMAC_OFDMRXCRC32ER 0x174 -#define RPMAC_OFDMRXPARITYER 0x178 -#define RPMAC_OFDMRXCRC8ER 0x17c -#define RPMAC_CCKCRXRC16ER 0x180 -#define RPMAC_CCKCRXRC32ER 0x184 -#define RPMAC_CCKCRXRC32OK 0x188 -#define RPMAC_TXSTATUS 0x18c - -#define RF_BB_CMD_ADDR 0x02c0 -#define RF_BB_CMD_DATA 0x02c4 - -#define RFPGA0_RFMOD 0x800 - -#define RFPGA0_TXINFO 0x804 -#define RFPGA0_PSDFUNCTION 0x808 - -#define RFPGA0_TXGAINSTAGE 0x80c - -#define RFPGA0_RFTIMING1 0x810 -#define RFPGA0_RFTIMING2 0x814 -#define RFPGA0_XA_HSSIPARAMETER1 0x820 -#define RFPGA0_XA_HSSIPARAMETER2 0x824 -#define RFPGA0_XB_HSSIPARAMETER1 0x828 -#define RFPGA0_XB_HSSIPARAMETER2 0x82c -#define RFPGA0_XC_HSSIPARAMETER1 0x830 -#define RFPGA0_XC_HSSIPARAMETER2 0x834 -#define RFPGA0_XD_HSSIPARAMETER1 0x838 -#define RFPGA0_XD_HSSIPARAMETER2 0x83c -#define RFPGA0_XA_LSSIPARAMETER 0x840 -#define RFPGA0_XB_LSSIPARAMETER 0x844 -#define RFPGA0_XC_LSSIPARAMETER 0x848 -#define RFPGA0_XD_LSSIPARAMETER 0x84c - -#define RFPGA0_RFWAKEUP_PARAMETER 0x850 -#define RFPGA0_RFSLEEPUP_PARAMETER 0x854 - -#define RFPGA0_XAB_SWITCHCONTROL 0x858 -#define RFPGA0_XCD_SWITCHCONTROL 0x85c - -#define RFPGA0_XA_RFINTERFACEOE 0x860 -#define RFPGA0_XB_RFINTERFACEOE 0x864 -#define RFPGA0_XC_RFINTERFACEOE 0x868 -#define RFPGA0_XD_RFINTERFACEOE 0x86c - -#define RFPGA0_XAB_RFINTERFACESW 0x870 -#define RFPGA0_XCD_RFINTERFACESW 0x874 - -#define RFPGA0_XAB_RFPARAMETER 0x878 -#define RFPGA0_XCD_RFPARAMETER 0x87c - -#define RFPGA0_ANALOGPARAMETER1 0x880 -#define RFPGA0_ANALOGPARAMETER2 0x884 -#define RFPGA0_ANALOGPARAMETER3 0x888 -#define RFPGA0_ANALOGPARAMETER4 0x88c - -#define RFPGA0_XA_LSSIREADBACK 0x8a0 -#define RFPGA0_XB_LSSIREADBACK 0x8a4 -#define RFPGA0_XC_LSSIREADBACK 0x8a8 -#define RFPGA0_XD_LSSIREADBACK 0x8ac - -#define RFPGA0_PSDREPORT 0x8b4 -#define TRANSCEIVERA_HSPI_READBACK 0x8b8 -#define TRANSCEIVERB_HSPI_READBACK 0x8bc -#define RFPGA0_XAB_RFINTERFACERB 0x8e0 -#define RFPGA0_XCD_RFINTERFACERB 0x8e4 -#define RFPGA1_RFMOD 0x900 - -#define RFPGA1_TXBLOCK 0x904 -#define RFPGA1_DEBUGSELECT 0x908 -#define RFPGA1_TXINFO 0x90c - -#define RCCK0_SYSTEM 0xa00 - -#define RCCK0_AFESETTING 0xa04 -#define RCCK0_CCA 0xa08 - -#define RCCK0_RXAGC1 0xa0c -#define RCCK0_RXAGC2 0xa10 - -#define RCCK0_RXHP 0xa14 - -#define RCCK0_DSPPARAMETER1 0xa18 -#define RCCK0_DSPPARAMETER2 0xa1c - -#define RCCK0_TXFILTER1 0xa20 -#define RCCK0_TXFILTER2 0xa24 -#define RCCK0_DEBUGPORT 0xa28 -#define RCCK0_FALSEALARMREPORT 0xa2c -#define RCCK0_TRSSIREPORT 0xa50 -#define RCCK0_RXREPORT 0xa54 -#define RCCK0_FACOUNTERLOWER 0xa5c -#define RCCK0_FACOUNTERUPPER 0xa58 - -#define ROFDM0_LSTF 0xc00 - -#define ROFDM0_TRXPATHENABLE 0xc04 -#define ROFDM0_TRMUXPAR 0xc08 -#define ROFDM0_TRSWISOLATION 0xc0c - -#define ROFDM0_XARXAFE 0xc10 -#define ROFDM0_XARXIQIMBALANCE 0xc14 -#define ROFDM0_XBRXAFE 0xc18 -#define ROFDM0_XBRXIQIMBALANCE 0xc1c -#define ROFDM0_XCRXAFE 0xc20 -#define ROFDM0_XCRXIQIMBALANCE 0xc24 -#define ROFDM0_XDRXAFE 0xc28 -#define ROFDM0_XDRXIQIMBALANCE 0xc2c - -#define ROFDM0_RXDETECTOR1 0xc30 -#define ROFDM0_RXDETECTOR2 0xc34 -#define ROFDM0_RXDETECTOR3 0xc38 -#define ROFDM0_RXDETECTOR4 0xc3c - -#define ROFDM0_RXDSP 0xc40 -#define ROFDM0_CFO_AND_DAGC 0xc44 -#define ROFDM0_CCADROP_THRESHOLD 0xc48 -#define ROFDM0_ECCA_THRESHOLD 0xc4c - -#define ROFDM0_XAAGCCORE1 0xc50 -#define ROFDM0_XAAGCCORE2 0xc54 -#define ROFDM0_XBAGCCORE1 0xc58 -#define ROFDM0_XBAGCCORE2 0xc5c -#define ROFDM0_XCAGCCORE1 0xc60 -#define ROFDM0_XCAGCCORE2 0xc64 -#define ROFDM0_XDAGCCORE1 0xc68 -#define ROFDM0_XDAGCCORE2 0xc6c - -#define ROFDM0_AGCPARAMETER1 0xc70 -#define ROFDM0_AGCPARAMETER2 0xc74 -#define ROFDM0_AGCRSSITABLE 0xc78 -#define ROFDM0_HTSTFAGC 0xc7c - -#define ROFDM0_XATXIQIMBALANCE 0xc80 -#define ROFDM0_XATXAFE 0xc84 -#define ROFDM0_XBTXIQIMBALANCE 0xc88 -#define ROFDM0_XBTXAFE 0xc8c -#define ROFDM0_XCTXIQIMBALANCE 0xc90 -#define ROFDM0_XCTXAFE 0xc94 -#define ROFDM0_XDTXIQIMBALANCE 0xc98 -#define ROFDM0_XDTXAFE 0xc9c - -#define ROFDM0_RXHP_PARAMETER 0xce0 -#define ROFDM0_TXPSEUDO_NOISE_WGT 0xce4 -#define ROFDM0_FRAME_SYNC 0xcf0 -#define ROFDM0_DFSREPORT 0xcf4 -#define ROFDM0_TXCOEFF1 0xca4 -#define ROFDM0_TXCOEFF2 0xca8 -#define ROFDM0_TXCOEFF3 0xcac -#define ROFDM0_TXCOEFF4 0xcb0 -#define ROFDM0_TXCOEFF5 0xcb4 -#define ROFDM0_TXCOEFF6 0xcb8 - - -#define ROFDM1_LSTF 0xd00 -#define ROFDM1_TRXPATHENABLE 0xd04 - -#define ROFDM1_CFO 0xd08 -#define ROFDM1_CSI1 0xd10 -#define ROFDM1_SBD 0xd14 -#define ROFDM1_CSI2 0xd18 -#define ROFDM1_CFOTRACKING 0xd2c -#define ROFDM1_TRXMESAURE1 0xd34 -#define ROFDM1_INTF_DET 0xd3c -#define ROFDM1_PSEUDO_NOISESTATEAB 0xd50 -#define ROFDM1_PSEUDO_NOISESTATECD 0xd54 -#define ROFDM1_RX_PSEUDO_NOISE_WGT 0xd58 - -#define ROFDM_PHYCOUNTER1 0xda0 -#define ROFDM_PHYCOUNTER2 0xda4 -#define ROFDM_PHYCOUNTER3 0xda8 - -#define ROFDM_SHORT_CFOAB 0xdac -#define ROFDM_SHORT_CFOCD 0xdb0 -#define ROFDM_LONG_CFOAB 0xdb4 -#define ROFDM_LONG_CFOCD 0xdb8 -#define ROFDM_TAIL_CFOAB 0xdbc -#define ROFDM_TAIL_CFOCD 0xdc0 -#define ROFDM_PW_MEASURE1 0xdc4 -#define ROFDM_PW_MEASURE2 0xdc8 -#define ROFDM_BW_REPORT 0xdcc -#define ROFDM_AGC_REPORT 0xdd0 -#define ROFDM_RXSNR 0xdd4 -#define ROFDM_RXEVMCSI 0xdd8 -#define ROFDM_SIG_REPORT 0xddc - - -#define RTXAGC_RATE18_06 0xe00 -#define RTXAGC_RATE54_24 0xe04 -#define RTXAGC_CCK_MCS32 0xe08 -#define RTXAGC_MCS03_MCS00 0xe10 -#define RTXAGC_MCS07_MCS04 0xe14 -#define RTXAGC_MCS11_MCS08 0xe18 -#define RTXAGC_MCS15_MCS12 0xe1c - - -#define RF_AC 0x00 -#define RF_IQADJ_G1 0x01 -#define RF_IQADJ_G2 0x02 -#define RF_POW_TRSW 0x05 -#define RF_GAIN_RX 0x06 -#define RF_GAIN_TX 0x07 -#define RF_TXM_IDAC 0x08 -#define RF_BS_IQGEN 0x0F - -#define RF_MODE1 0x10 -#define RF_MODE2 0x11 -#define RF_RX_AGC_HP 0x12 -#define RF_TX_AGC 0x13 -#define RF_BIAS 0x14 -#define RF_IPA 0x15 -#define RF_POW_ABILITY 0x17 -#define RF_MODE_AG 0x18 -#define RF_CHANNEL 0x18 -#define RF_CHNLBW 0x18 -#define RF_TOP 0x19 -#define RF_RX_G1 0x1A -#define RF_RX_G2 0x1B -#define RF_RX_BB2 0x1C -#define RF_RX_BB1 0x1D -#define RF_RCK1 0x1E -#define RF_RCK2 0x1F - -#define RF_TX_G1 0x20 -#define RF_TX_G2 0x21 -#define RF_TX_G3 0x22 -#define RF_TX_BB1 0x23 -#define RF_T_METER 0x24 -#define RF_SYN_G1 0x25 -#define RF_SYN_G2 0x26 -#define RF_SYN_G3 0x27 -#define RF_SYN_G4 0x28 -#define RF_SYN_G5 0x29 -#define RF_SYN_G6 0x2A -#define RF_SYN_G7 0x2B -#define RF_SYN_G8 0x2C - -#define RF_RCK_OS 0x30 -#define RF_TXPA_G1 0x31 -#define RF_TXPA_G2 0x32 -#define RF_TXPA_G3 0x33 - -#define BRFMOD 0x1 -#define BCCKEN 0x1000000 -#define BOFDMEN 0x2000000 - -#define BXBTXAGC 0xf00 -#define BXCTXAGC 0xf000 -#define BXDTXAGC 0xf0000 - -#define B3WIRE_DATALENGTH 0x800 -#define B3WIRE_ADDRESSLENGTH 0x400 - -#define BRFSI_RFENV 0x10 - -#define BLSSI_READADDRESS 0x7f800000 -#define BLSSI_READEDGE 0x80000000 -#define BLSSI_READBACK_DATA 0xfffff - -#define BADCLKPHASE 0x4000000 - -#define BCCK_SIDEBAND 0x10 - -#define BTX_AGCRATECCK 0x7f00 - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c deleted file mode 100644 index 78a81c1e390b..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c +++ /dev/null @@ -1,535 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" - - -static void _rtl92s_get_powerbase(struct ieee80211_hw *hw, u8 *p_pwrlevel, - u8 chnl, u32 *ofdmbase, u32 *mcsbase, - u8 *p_final_pwridx) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 pwrbase0, pwrbase1; - u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0; - u8 i, pwrlevel[4]; - - for (i = 0; i < 2; i++) - pwrlevel[i] = p_pwrlevel[i]; - - /* We only care about the path A for legacy. */ - if (rtlefuse->eeprom_version < 2) { - pwrbase0 = pwrlevel[0] + (rtlefuse->legacy_httxpowerdiff & 0xf); - } else { - legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff - [RF90_PATH_A][chnl - 1]; - - /* For legacy OFDM, tx pwr always > HT OFDM pwr. - * We do not care Path B - * legacy OFDM pwr diff. NO BB register - * to notify HW. */ - pwrbase0 = pwrlevel[0] + legacy_pwrdiff; - } - - pwrbase0 = (pwrbase0 << 24) | (pwrbase0 << 16) | (pwrbase0 << 8) | - pwrbase0; - *ofdmbase = pwrbase0; - - /* MCS rates */ - if (rtlefuse->eeprom_version >= 2) { - /* Check HT20 to HT40 diff */ - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { - for (i = 0; i < 2; i++) { - /* rf-A, rf-B */ - /* HT 20<->40 pwr diff */ - ht20_pwrdiff = rtlefuse->txpwr_ht20diff - [i][chnl - 1]; - - if (ht20_pwrdiff < 8) /* 0~+7 */ - pwrlevel[i] += ht20_pwrdiff; - else /* index8-15=-8~-1 */ - pwrlevel[i] -= (16 - ht20_pwrdiff); - } - } - } - - /* use index of rf-A */ - pwrbase1 = pwrlevel[0]; - pwrbase1 = (pwrbase1 << 24) | (pwrbase1 << 16) | (pwrbase1 << 8) | - pwrbase1; - *mcsbase = pwrbase1; - - /* The following is for Antenna - * diff from Ant-B to Ant-A */ - p_final_pwridx[0] = pwrlevel[0]; - p_final_pwridx[1] = pwrlevel[1]; - - switch (rtlefuse->eeprom_regulatory) { - case 3: - /* The following is for calculation - * of the power diff for Ant-B to Ant-A. */ - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - p_final_pwridx[0] += rtlefuse->pwrgroup_ht40 - [RF90_PATH_A][ - chnl - 1]; - p_final_pwridx[1] += rtlefuse->pwrgroup_ht40 - [RF90_PATH_B][ - chnl - 1]; - } else { - p_final_pwridx[0] += rtlefuse->pwrgroup_ht20 - [RF90_PATH_A][ - chnl - 1]; - p_final_pwridx[1] += rtlefuse->pwrgroup_ht20 - [RF90_PATH_B][ - chnl - 1]; - } - break; - default: - break; - } - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "40MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n", - p_final_pwridx[0], p_final_pwridx[1]); - } else { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "20MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n", - p_final_pwridx[0], p_final_pwridx[1]); - } -} - -static void _rtl92s_set_antennadiff(struct ieee80211_hw *hw, - u8 *p_final_pwridx) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - char ant_pwr_diff = 0; - u32 u4reg_val = 0; - - if (rtlphy->rf_type == RF_2T2R) { - ant_pwr_diff = p_final_pwridx[1] - p_final_pwridx[0]; - - /* range is from 7~-8, - * index = 0x0~0xf */ - if (ant_pwr_diff > 7) - ant_pwr_diff = 7; - if (ant_pwr_diff < -8) - ant_pwr_diff = -8; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Antenna Diff from RF-B to RF-A = %d (0x%x)\n", - ant_pwr_diff, ant_pwr_diff & 0xf); - - ant_pwr_diff &= 0xf; - } - - /* Antenna TX power difference */ - rtlefuse->antenna_txpwdiff[2] = 0;/* RF-D, don't care */ - rtlefuse->antenna_txpwdiff[1] = 0;/* RF-C, don't care */ - rtlefuse->antenna_txpwdiff[0] = (u8)(ant_pwr_diff); /* RF-B */ - - u4reg_val = rtlefuse->antenna_txpwdiff[2] << 8 | - rtlefuse->antenna_txpwdiff[1] << 4 | - rtlefuse->antenna_txpwdiff[0]; - - rtl_set_bbreg(hw, RFPGA0_TXGAINSTAGE, (BXBTXAGC | BXCTXAGC | BXDTXAGC), - u4reg_val); - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Write BCD-Diff(0x%x) = 0x%x\n", - RFPGA0_TXGAINSTAGE, u4reg_val); -} - -static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw, - u8 chnl, u8 index, - u32 pwrbase0, - u32 pwrbase1, - u32 *p_outwrite_val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 i, chnlgroup, pwrdiff_limit[4]; - u32 writeval, customer_limit; - - /* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */ - switch (rtlefuse->eeprom_regulatory) { - case 0: - /* Realtek better performance increase power diff - * defined by Realtek for large power */ - chnlgroup = 0; - - writeval = rtlphy->mcs_offset[chnlgroup][index] + - ((index < 2) ? pwrbase0 : pwrbase1); - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "RTK better performance, writeval = 0x%x\n", writeval); - break; - case 1: - /* Realtek regulatory increase power diff defined - * by Realtek for regulatory */ - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - writeval = ((index < 2) ? pwrbase0 : pwrbase1); - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Realtek regulatory, 40MHz, writeval = 0x%x\n", - writeval); - } else { - if (rtlphy->pwrgroup_cnt == 1) - chnlgroup = 0; - - if (rtlphy->pwrgroup_cnt >= 3) { - if (chnl <= 3) - chnlgroup = 0; - else if (chnl >= 4 && chnl <= 8) - chnlgroup = 1; - else if (chnl > 8) - chnlgroup = 2; - if (rtlphy->pwrgroup_cnt == 4) - chnlgroup++; - } - - writeval = rtlphy->mcs_offset[chnlgroup][index] - + ((index < 2) ? - pwrbase0 : pwrbase1); - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Realtek regulatory, 20MHz, writeval = 0x%x\n", - writeval); - } - break; - case 2: - /* Better regulatory don't increase any power diff */ - writeval = ((index < 2) ? pwrbase0 : pwrbase1); - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Better regulatory, writeval = 0x%x\n", writeval); - break; - case 3: - /* Customer defined power diff. increase power diff - defined by customer. */ - chnlgroup = 0; - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "customer's limit, 40MHz = 0x%x\n", - rtlefuse->pwrgroup_ht40 - [RF90_PATH_A][chnl - 1]); - } else { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "customer's limit, 20MHz = 0x%x\n", - rtlefuse->pwrgroup_ht20 - [RF90_PATH_A][chnl - 1]); - } - - for (i = 0; i < 4; i++) { - pwrdiff_limit[i] = (u8)((rtlphy->mcs_offset - [chnlgroup][index] & (0x7f << (i * 8))) - >> (i * 8)); - - if (rtlphy->current_chan_bw == - HT_CHANNEL_WIDTH_20_40) { - if (pwrdiff_limit[i] > - rtlefuse->pwrgroup_ht40 - [RF90_PATH_A][chnl - 1]) { - pwrdiff_limit[i] = - rtlefuse->pwrgroup_ht40 - [RF90_PATH_A][chnl - 1]; - } - } else { - if (pwrdiff_limit[i] > - rtlefuse->pwrgroup_ht20 - [RF90_PATH_A][chnl - 1]) { - pwrdiff_limit[i] = - rtlefuse->pwrgroup_ht20 - [RF90_PATH_A][chnl - 1]; - } - } - } - - customer_limit = (pwrdiff_limit[3] << 24) | - (pwrdiff_limit[2] << 16) | - (pwrdiff_limit[1] << 8) | - (pwrdiff_limit[0]); - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Customer's limit = 0x%x\n", customer_limit); - - writeval = customer_limit + ((index < 2) ? - pwrbase0 : pwrbase1); - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Customer, writeval = 0x%x\n", writeval); - break; - default: - chnlgroup = 0; - writeval = rtlphy->mcs_offset[chnlgroup][index] + - ((index < 2) ? pwrbase0 : pwrbase1); - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "RTK better performance, writeval = 0x%x\n", writeval); - break; - } - - if (rtlpriv->dm.dynamic_txhighpower_lvl == TX_HIGH_PWR_LEVEL_LEVEL1) - writeval = 0x10101010; - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TX_HIGH_PWR_LEVEL_LEVEL2) - writeval = 0x0; - - *p_outwrite_val = writeval; - -} - -static void _rtl92s_write_ofdm_powerreg(struct ieee80211_hw *hw, - u8 index, u32 val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u16 regoffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c}; - u8 i, rfa_pwr[4]; - u8 rfa_lower_bound = 0, rfa_upper_bound = 0, rf_pwr_diff = 0; - u32 writeval = val; - - /* If path A and Path B coexist, we must limit Path A tx power. - * Protect Path B pwr over or under flow. We need to calculate - * upper and lower bound of path A tx power. */ - if (rtlphy->rf_type == RF_2T2R) { - rf_pwr_diff = rtlefuse->antenna_txpwdiff[0]; - - /* Diff=-8~-1 */ - if (rf_pwr_diff >= 8) { - /* Prevent underflow!! */ - rfa_lower_bound = 0x10 - rf_pwr_diff; - /* if (rf_pwr_diff >= 0) Diff = 0-7 */ - } else { - rfa_upper_bound = RF6052_MAX_TX_PWR - rf_pwr_diff; - } - } - - for (i = 0; i < 4; i++) { - rfa_pwr[i] = (u8)((writeval & (0x7f << (i * 8))) >> (i * 8)); - if (rfa_pwr[i] > RF6052_MAX_TX_PWR) - rfa_pwr[i] = RF6052_MAX_TX_PWR; - - /* If path A and Path B coexist, we must limit Path A tx power. - * Protect Path B pwr over or under flow. We need to calculate - * upper and lower bound of path A tx power. */ - if (rtlphy->rf_type == RF_2T2R) { - /* Diff=-8~-1 */ - if (rf_pwr_diff >= 8) { - /* Prevent underflow!! */ - if (rfa_pwr[i] < rfa_lower_bound) - rfa_pwr[i] = rfa_lower_bound; - /* Diff = 0-7 */ - } else if (rf_pwr_diff >= 1) { - /* Prevent overflow */ - if (rfa_pwr[i] > rfa_upper_bound) - rfa_pwr[i] = rfa_upper_bound; - } - } - - } - - writeval = (rfa_pwr[3] << 24) | (rfa_pwr[2] << 16) | (rfa_pwr[1] << 8) | - rfa_pwr[0]; - - rtl_set_bbreg(hw, regoffset[index], 0x7f7f7f7f, writeval); -} - -void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw, - u8 *p_pwrlevel, u8 chnl) -{ - u32 writeval, pwrbase0, pwrbase1; - u8 index = 0; - u8 finalpwr_idx[4]; - - _rtl92s_get_powerbase(hw, p_pwrlevel, chnl, &pwrbase0, &pwrbase1, - &finalpwr_idx[0]); - _rtl92s_set_antennadiff(hw, &finalpwr_idx[0]); - - for (index = 0; index < 6; index++) { - _rtl92s_get_txpower_writeval_byregulatory(hw, chnl, index, - pwrbase0, pwrbase1, &writeval); - - _rtl92s_write_ofdm_powerreg(hw, index, writeval); - } -} - -void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 txagc = 0; - bool dont_inc_cck_or_turboscanoff = false; - - if (((rtlefuse->eeprom_version >= 2) && - (rtlefuse->txpwr_safetyflag == 1)) || - ((rtlefuse->eeprom_version >= 2) && - (rtlefuse->eeprom_regulatory != 0))) - dont_inc_cck_or_turboscanoff = true; - - if (mac->act_scanning) { - txagc = 0x3f; - if (dont_inc_cck_or_turboscanoff) - txagc = pwrlevel; - } else { - txagc = pwrlevel; - - if (rtlpriv->dm.dynamic_txhighpower_lvl == - TX_HIGH_PWR_LEVEL_LEVEL1) - txagc = 0x10; - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TX_HIGH_PWR_LEVEL_LEVEL2) - txagc = 0x0; - } - - if (txagc > RF6052_MAX_TX_PWR) - txagc = RF6052_MAX_TX_PWR; - - rtl_set_bbreg(hw, RTXAGC_CCK_MCS32, BTX_AGCRATECCK, txagc); - -} - -bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 u4reg_val = 0; - u8 rfpath; - bool rtstatus = true; - struct bb_reg_def *pphyreg; - - /* Initialize RF */ - for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { - - pphyreg = &rtlphy->phyreg_def[rfpath]; - - /* Store original RFENV control type */ - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - u4reg_val = rtl92s_phy_query_bb_reg(hw, - pphyreg->rfintfs, - BRFSI_RFENV); - break; - case RF90_PATH_B: - case RF90_PATH_D: - u4reg_val = rtl92s_phy_query_bb_reg(hw, - pphyreg->rfintfs, - BRFSI_RFENV << 16); - break; - } - - /* Set RF_ENV enable */ - rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfe, - BRFSI_RFENV << 16, 0x1); - - /* Set RF_ENV output high */ - rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); - - /* Set bit number of Address and Data for RF register */ - rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2, - B3WIRE_ADDRESSLENGTH, 0x0); - rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2, - B3WIRE_DATALENGTH, 0x0); - - /* Initialize RF fom connfiguration file */ - switch (rfpath) { - case RF90_PATH_A: - rtstatus = rtl92s_phy_config_rf(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_B: - rtstatus = rtl92s_phy_config_rf(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_C: - break; - case RF90_PATH_D: - break; - } - - /* Restore RFENV control type */ - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, BRFSI_RFENV, - u4reg_val); - break; - case RF90_PATH_B: - case RF90_PATH_D: - rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16, - u4reg_val); - break; - } - - if (!rtstatus) { - pr_err("Radio[%d] Fail!!\n", rfpath); - goto fail; - } - - } - - return rtstatus; - -fail: - return rtstatus; -} - -void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - switch (bandwidth) { - case HT_CHANNEL_WIDTH_20: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff) | 0x0400); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - case HT_CHANNEL_WIDTH_20_40: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff)); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", bandwidth); - break; - } -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.h b/drivers/net/wireless/rtlwifi/rtl8192se/rf.h deleted file mode 100644 index 8a29eb94ab17..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.h +++ /dev/null @@ -1,43 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#ifndef __INC_RTL92S_RF_H -#define __INC_RTL92S_RF_H - -#define RF6052_MAX_TX_PWR 0x3F - -void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, - u8 bandwidth); -bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw) ; -void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, - u8 powerlevel); -void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw, - u8 *p_pwrlevel, u8 chnl); - -#endif - diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c deleted file mode 100644 index e1fd27c888bf..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ /dev/null @@ -1,442 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../core.h" -#include "../base.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "fw.h" -#include "hw.h" -#include "sw.h" -#include "trx.h" -#include "led.h" - -#include - -static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - /*close ASPM for AMD defaultly */ - rtlpci->const_amdpci_aspm = 0; - - /* ASPM PS mode. - * 0 - Disable ASPM, - * 1 - Enable ASPM without Clock Req, - * 2 - Enable ASPM with Clock Req, - * 3 - Alwyas Enable ASPM with Clock Req, - * 4 - Always Enable ASPM without Clock Req. - * set defult to RTL8192CE:3 RTL8192E:2 - * */ - rtlpci->const_pci_aspm = 2; - - /*Setting for PCI-E device */ - rtlpci->const_devicepci_aspm_setting = 0x03; - - /*Setting for PCI-E bridge */ - rtlpci->const_hostpci_aspm_setting = 0x02; - - /* In Hw/Sw Radio Off situation. - * 0 - Default, - * 1 - From ASPM setting without low Mac Pwr, - * 2 - From ASPM setting with low Mac Pwr, - * 3 - Bus D3 - * set default to RTL8192CE:0 RTL8192SE:2 - */ - rtlpci->const_hwsw_rfoff_d3 = 2; - - /* This setting works for those device with - * backdoor ASPM setting such as EPHY setting. - * 0 - Not support ASPM, - * 1 - Support ASPM, - * 2 - According to chipset. - */ - rtlpci->const_support_pciaspm = 2; -} - -static void rtl92se_fw_cb(const struct firmware *firmware, void *context) -{ - struct ieee80211_hw *hw = context; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rt_firmware *pfirmware = NULL; - - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "Firmware callback routine entered!\n"); - complete(&rtlpriv->firmware_loading_complete); - if (!firmware) { - pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name); - rtlpriv->max_fw_size = 0; - return; - } - if (firmware->size > rtlpriv->max_fw_size) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Firmware is too big!\n"); - rtlpriv->max_fw_size = 0; - release_firmware(firmware); - return; - } - pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware; - memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size); - pfirmware->sz_fw_tmpbufferlen = firmware->size; - release_firmware(firmware); -} - -static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - int err = 0; - u16 earlyrxthreshold = 7; - - rtlpriv->dm.dm_initialgain_enable = true; - rtlpriv->dm.dm_flag = 0; - rtlpriv->dm.disable_framebursting = false; - rtlpriv->dm.thermalvalue = 0; - rtlpriv->dm.useramask = true; - - /* compatible 5G band 91se just 2.4G band & smsp */ - rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; - rtlpriv->rtlhal.bandset = BAND_ON_2_4G; - rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; - - rtlpci->transmit_config = 0; - - rtlpci->receive_config = - RCR_APPFCS | - RCR_APWRMGT | - /*RCR_ADD3 |*/ - RCR_AMF | - RCR_ADF | - RCR_APP_MIC | - RCR_APP_ICV | - RCR_AICV | - /* Accept ICV error, CRC32 Error */ - RCR_ACRC32 | - RCR_AB | - /* Accept Broadcast, Multicast */ - RCR_AM | - /* Accept Physical match */ - RCR_APM | - /* Accept Destination Address packets */ - /*RCR_AAP |*/ - RCR_APP_PHYST_STAFF | - /* Accept PHY status */ - RCR_APP_PHYST_RXFF | - (earlyrxthreshold << RCR_FIFO_OFFSET); - - rtlpci->irq_mask[0] = (u32) - (IMR_ROK | - IMR_VODOK | - IMR_VIDOK | - IMR_BEDOK | - IMR_BKDOK | - IMR_HCCADOK | - IMR_MGNTDOK | - IMR_COMDOK | - IMR_HIGHDOK | - IMR_BDOK | - IMR_RXCMDOK | - /*IMR_TIMEOUT0 |*/ - IMR_RDU | - IMR_RXFOVW | - IMR_BCNINT - /*| IMR_TXFOVW*/ - /*| IMR_TBDOK | - IMR_TBDER*/); - - rtlpci->irq_mask[1] = (u32) 0; - - rtlpci->shortretry_limit = 0x30; - rtlpci->longretry_limit = 0x30; - - 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; - rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; - if (!rtlpriv->psc.inactiveps) - pr_info("Power Save off (module option)\n"); - if (!rtlpriv->psc.fwctrl_lps) - pr_info("FW Power Save off (module option)\n"); - rtlpriv->psc.reg_fwctrl_lps = 3; - rtlpriv->psc.reg_max_lps_awakeintvl = 5; - /* for ASPM, you can close aspm through - * set const_support_pciaspm = 0 */ - rtl92s_init_aspm_vars(hw); - - if (rtlpriv->psc.reg_fwctrl_lps == 1) - rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 2) - rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 3) - rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; - - /* for firmware buf */ - rtlpriv->rtlhal.pfirmware = vzalloc(sizeof(struct rt_firmware)); - if (!rtlpriv->rtlhal.pfirmware) - return 1; - - rtlpriv->max_fw_size = RTL8190_MAX_FIRMWARE_CODE_SIZE*2 + - sizeof(struct fw_hdr); - pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n" - "Loading firmware %s\n", rtlpriv->cfg->fw_name); - /* request fw */ - err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, - rtlpriv->io.dev, GFP_KERNEL, hw, - rtl92se_fw_cb); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to request firmware!\n"); - return 1; - } - - return err; -} - -static void rtl92s_deinit_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->rtlhal.pfirmware) { - vfree(rtlpriv->rtlhal.pfirmware); - rtlpriv->rtlhal.pfirmware = NULL; - } -} - -static bool rtl92se_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, - u16 index) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; - u8 *entry = (u8 *)(&ring->desc[ring->idx]); - u8 own = (u8)rtl92se_get_desc(entry, true, HW_DESC_OWN); - - if (own) - return false; - return true; -} - -static struct rtl_hal_ops rtl8192se_hal_ops = { - .init_sw_vars = rtl92s_init_sw_vars, - .deinit_sw_vars = rtl92s_deinit_sw_vars, - .read_eeprom_info = rtl92se_read_eeprom_info, - .interrupt_recognized = rtl92se_interrupt_recognized, - .hw_init = rtl92se_hw_init, - .hw_disable = rtl92se_card_disable, - .hw_suspend = rtl92se_suspend, - .hw_resume = rtl92se_resume, - .enable_interrupt = rtl92se_enable_interrupt, - .disable_interrupt = rtl92se_disable_interrupt, - .set_network_type = rtl92se_set_network_type, - .set_chk_bssid = rtl92se_set_check_bssid, - .set_qos = rtl92se_set_qos, - .set_bcn_reg = rtl92se_set_beacon_related_registers, - .set_bcn_intv = rtl92se_set_beacon_interval, - .update_interrupt_mask = rtl92se_update_interrupt_mask, - .get_hw_reg = rtl92se_get_hw_reg, - .set_hw_reg = rtl92se_set_hw_reg, - .update_rate_tbl = rtl92se_update_hal_rate_tbl, - .fill_tx_desc = rtl92se_tx_fill_desc, - .fill_tx_cmddesc = rtl92se_tx_fill_cmddesc, - .query_rx_desc = rtl92se_rx_query_desc, - .set_channel_access = rtl92se_update_channel_access_setting, - .radio_onoff_checking = rtl92se_gpio_radio_on_off_checking, - .set_bw_mode = rtl92s_phy_set_bw_mode, - .switch_channel = rtl92s_phy_sw_chnl, - .dm_watchdog = rtl92s_dm_watchdog, - .scan_operation_backup = rtl92s_phy_scan_operation_backup, - .set_rf_power_state = rtl92s_phy_set_rf_power_state, - .led_control = rtl92se_led_control, - .set_desc = rtl92se_set_desc, - .get_desc = rtl92se_get_desc, - .is_tx_desc_closed = rtl92se_is_tx_desc_closed, - .tx_polling = rtl92se_tx_polling, - .enable_hw_sec = rtl92se_enable_hw_security_config, - .set_key = rtl92se_set_key, - .init_sw_leds = rtl92se_init_sw_leds, - .get_bbreg = rtl92s_phy_query_bb_reg, - .set_bbreg = rtl92s_phy_set_bb_reg, - .get_rfreg = rtl92s_phy_query_rf_reg, - .set_rfreg = rtl92s_phy_set_rf_reg, - .get_btc_status = rtl_btc_status_false, -}; - -static struct rtl_mod_params rtl92se_mod_params = { - .sw_crypto = false, - .inactiveps = true, - .swctrl_lps = true, - .fwctrl_lps = false, - .debug = DBG_EMERG, -}; - -/* Because memory R/W bursting will cause system hang/crash - * for 92se, so we don't read back after every write action */ -static struct rtl_hal_cfg rtl92se_hal_cfg = { - .bar_id = 1, - .write_readback = false, - .name = "rtl92s_pci", - .fw_name = "rtlwifi/rtl8192sefw.bin", - .ops = &rtl8192se_hal_ops, - .mod_params = &rtl92se_mod_params, - - .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, - .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, - .maps[SYS_CLK] = SYS_CLKR, - .maps[MAC_RCR_AM] = RCR_AM, - .maps[MAC_RCR_AB] = RCR_AB, - .maps[MAC_RCR_ACRC32] = RCR_ACRC32, - .maps[MAC_RCR_ACF] = RCR_ACF, - .maps[MAC_RCR_AAP] = RCR_AAP, - .maps[MAC_HIMR] = INTA_MASK, - .maps[MAC_HIMRE] = INTA_MASK + 4, - - .maps[EFUSE_TEST] = REG_EFUSE_TEST, - .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_CLK] = REG_EFUSE_CLK, - .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_PWC_EV12V] = 0, /* nouse for 8192se */ - .maps[EFUSE_FEN_ELDR] = 0, /* nouse for 8192se */ - .maps[EFUSE_LOADER_CLK_EN] = 0,/* nouse for 8192se */ - .maps[EFUSE_ANA8M] = EFUSE_ANA8M, - .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE_92S, - .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, - .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, - .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, - - .maps[RWCAM] = REG_RWCAM, - .maps[WCAMI] = REG_WCAMI, - .maps[RCAMO] = REG_RCAMO, - .maps[CAMDBG] = REG_CAMDBG, - .maps[SECR] = REG_SECR, - .maps[SEC_CAM_NONE] = CAM_NONE, - .maps[SEC_CAM_WEP40] = CAM_WEP40, - .maps[SEC_CAM_TKIP] = CAM_TKIP, - .maps[SEC_CAM_AES] = CAM_AES, - .maps[SEC_CAM_WEP104] = CAM_WEP104, - - .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, - .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, - .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, - .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, - .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, - .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, - .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, - .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, - .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, - .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, - .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, - .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, - .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, - .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, - .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, - .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, - - .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, - .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, - .maps[RTL_IMR_BCNINT] = IMR_BCNINT, - .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, - .maps[RTL_IMR_RDU] = IMR_RDU, - .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, - .maps[RTL_IMR_BDOK] = IMR_BDOK, - .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, - .maps[RTL_IMR_TBDER] = IMR_TBDER, - .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, - .maps[RTL_IMR_COMDOK] = IMR_COMDOK, - .maps[RTL_IMR_TBDOK] = IMR_TBDOK, - .maps[RTL_IMR_BKDOK] = IMR_BKDOK, - .maps[RTL_IMR_BEDOK] = IMR_BEDOK, - .maps[RTL_IMR_VIDOK] = IMR_VIDOK, - .maps[RTL_IMR_VODOK] = IMR_VODOK, - .maps[RTL_IMR_ROK] = IMR_ROK, - .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), - - .maps[RTL_RC_CCK_RATE1M] = DESC_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC_RATEMCS15, -}; - -static struct pci_device_id rtl92se_pci_ids[] = { - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8192, rtl92se_hal_cfg)}, - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8171, rtl92se_hal_cfg)}, - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8172, rtl92se_hal_cfg)}, - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8173, rtl92se_hal_cfg)}, - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8174, rtl92se_hal_cfg)}, - {}, -}; - -MODULE_DEVICE_TABLE(pci, rtl92se_pci_ids); - -MODULE_AUTHOR("lizhaoming "); -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_AUTHOR("Larry Finger "); -MODULE_LICENSE("GPL"); -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(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); -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)"); - -static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume); - -static struct pci_driver rtl92se_driver = { - .name = KBUILD_MODNAME, - .id_table = rtl92se_pci_ids, - .probe = rtl_pci_probe, - .remove = rtl_pci_disconnect, - .driver.pm = &rtlwifi_pm_ops, -}; - -module_pci_driver(rtl92se_driver); diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.h b/drivers/net/wireless/rtlwifi/rtl8192se/sw.h deleted file mode 100644 index 2eb88862ebe4..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.h +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - *****************************************************************************/ -#ifndef __REALTEK_PCI92SE_SW_H__ -#define __REALTEK_PCI92SE_SW_H__ - -#define EFUSE_MAX_SECTION 16 - -int rtl92se_init_sw(struct ieee80211_hw *hw); -void rtl92se_deinit_sw(struct ieee80211_hw *hw); -void rtl92se_init_var_map(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/table.c b/drivers/net/wireless/rtlwifi/rtl8192se/table.c deleted file mode 100644 index f1a73f75127e..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/table.c +++ /dev/null @@ -1,634 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - * Created on 2010/ 5/18, 1:41 - *****************************************************************************/ - -#include "table.h" - -u32 rtl8192sephy_reg_2t2rarray[PHY_REG_2T2RARRAYLENGTH] = { - 0x01c, 0x07000000, - 0x800, 0x00040000, - 0x804, 0x00008003, - 0x808, 0x0000fc00, - 0x80c, 0x0000000a, - 0x810, 0x10005088, - 0x814, 0x020c3d10, - 0x818, 0x00200185, - 0x81c, 0x00000000, - 0x820, 0x01000000, - 0x824, 0x00390004, - 0x828, 0x01000000, - 0x82c, 0x00390004, - 0x830, 0x00000004, - 0x834, 0x00690200, - 0x838, 0x00000004, - 0x83c, 0x00690200, - 0x840, 0x00010000, - 0x844, 0x00010000, - 0x848, 0x00000000, - 0x84c, 0x00000000, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x48484848, - 0x85c, 0x65a965a9, - 0x860, 0x0f7f0130, - 0x864, 0x0f7f0130, - 0x868, 0x0f7f0130, - 0x86c, 0x0f7f0130, - 0x870, 0x03000700, - 0x874, 0x03000300, - 0x878, 0x00020002, - 0x87c, 0x004f0201, - 0x880, 0xa8300ac1, - 0x884, 0x00000058, - 0x888, 0x00000008, - 0x88c, 0x00000004, - 0x890, 0x00000000, - 0x894, 0xfffffffe, - 0x898, 0x40302010, - 0x89c, 0x00706050, - 0x8b0, 0x00000000, - 0x8e0, 0x00000000, - 0x8e4, 0x00000000, - 0xe00, 0x30333333, - 0xe04, 0x2a2d2e2f, - 0xe08, 0x00003232, - 0xe10, 0x30333333, - 0xe14, 0x2a2d2e2f, - 0xe18, 0x30333333, - 0xe1c, 0x2a2d2e2f, - 0xe30, 0x01007c00, - 0xe34, 0x01004800, - 0xe38, 0x1000dc1f, - 0xe3c, 0x10008c1f, - 0xe40, 0x021400a0, - 0xe44, 0x281600a0, - 0xe48, 0xf8000001, - 0xe4c, 0x00002910, - 0xe50, 0x01007c00, - 0xe54, 0x01004800, - 0xe58, 0x1000dc1f, - 0xe5c, 0x10008c1f, - 0xe60, 0x021400a0, - 0xe64, 0x281600a0, - 0xe6c, 0x00002910, - 0xe70, 0x31ed92fb, - 0xe74, 0x361536fb, - 0xe78, 0x361536fb, - 0xe7c, 0x361536fb, - 0xe80, 0x361536fb, - 0xe84, 0x000d92fb, - 0xe88, 0x000d92fb, - 0xe8c, 0x31ed92fb, - 0xed0, 0x31ed92fb, - 0xed4, 0x31ed92fb, - 0xed8, 0x000d92fb, - 0xedc, 0x000d92fb, - 0xee0, 0x000d92fb, - 0xee4, 0x015e5448, - 0xee8, 0x21555448, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90c, 0x01121313, - 0xa00, 0x00d047c8, - 0xa04, 0x80ff0008, - 0xa08, 0x8ccd8300, - 0xa0c, 0x2e62120f, - 0xa10, 0x9500bb78, - 0xa14, 0x11144028, - 0xa18, 0x00881117, - 0xa1c, 0x89140f00, - 0xa20, 0x1a1b0000, - 0xa24, 0x090e1317, - 0xa28, 0x00000204, - 0xa2c, 0x10d30000, - 0xc00, 0x40071d40, - 0xc04, 0x00a05633, - 0xc08, 0x000000e4, - 0xc0c, 0x6c6c6c6c, - 0xc10, 0x08800000, - 0xc14, 0x40000100, - 0xc18, 0x08000000, - 0xc1c, 0x40000100, - 0xc20, 0x08000000, - 0xc24, 0x40000100, - 0xc28, 0x08000000, - 0xc2c, 0x40000100, - 0xc30, 0x6de9ac44, - 0xc34, 0x469652cf, - 0xc38, 0x49795994, - 0xc3c, 0x0a979764, - 0xc40, 0x1f7c403f, - 0xc44, 0x000100b7, - 0xc48, 0xec020000, - 0xc4c, 0x007f037f, - 0xc50, 0x69543420, - 0xc54, 0x433c0094, - 0xc58, 0x69543420, - 0xc5c, 0x433c0094, - 0xc60, 0x69543420, - 0xc64, 0x433c0094, - 0xc68, 0x69543420, - 0xc6c, 0x433c0094, - 0xc70, 0x2c7f000d, - 0xc74, 0x0186155b, - 0xc78, 0x0000001f, - 0xc7c, 0x00b91612, - 0xc80, 0x40000100, - 0xc84, 0x20f60000, - 0xc88, 0x20000080, - 0xc8c, 0x20200000, - 0xc90, 0x40000100, - 0xc94, 0x00000000, - 0xc98, 0x40000100, - 0xc9c, 0x00000000, - 0xca0, 0x00492492, - 0xca4, 0x00000000, - 0xca8, 0x00000000, - 0xcac, 0x00000000, - 0xcb0, 0x00000000, - 0xcb4, 0x00000000, - 0xcb8, 0x00000000, - 0xcbc, 0x28000000, - 0xcc0, 0x00000000, - 0xcc4, 0x00000000, - 0xcc8, 0x00000000, - 0xccc, 0x00000000, - 0xcd0, 0x00000000, - 0xcd4, 0x00000000, - 0xcd8, 0x64b22427, - 0xcdc, 0x00766932, - 0xce0, 0x00222222, - 0xce4, 0x00000000, - 0xce8, 0x37644302, - 0xcec, 0x2f97d40c, - 0xd00, 0x00000750, - 0xd04, 0x00000403, - 0xd08, 0x0000907f, - 0xd0c, 0x00000001, - 0xd10, 0xa0633333, - 0xd14, 0x33333c63, - 0xd18, 0x6a8f5b6b, - 0xd1c, 0x00000000, - 0xd20, 0x00000000, - 0xd24, 0x00000000, - 0xd28, 0x00000000, - 0xd2c, 0xcc979975, - 0xd30, 0x00000000, - 0xd34, 0x00000000, - 0xd38, 0x00000000, - 0xd3c, 0x00027293, - 0xd40, 0x00000000, - 0xd44, 0x00000000, - 0xd48, 0x00000000, - 0xd50, 0x6437140a, - 0xd54, 0x024dbd02, - 0xd58, 0x00000000, - 0xd5c, 0x30032064, - 0xd60, 0x4653de68, - 0xd64, 0x00518a3c, - 0xd68, 0x00002101, - 0xf14, 0x00000003, - 0xf4c, 0x00000000, - 0xf00, 0x00000300, -}; - -u32 rtl8192sephy_changeto_1t1rarray[PHY_CHANGETO_1T1RARRAYLENGTH] = { - 0x844, 0xffffffff, 0x00010000, - 0x804, 0x0000000f, 0x00000001, - 0x824, 0x00f0000f, 0x00300004, - 0x82c, 0x00f0000f, 0x00100002, - 0x870, 0x04000000, 0x00000001, - 0x864, 0x00000400, 0x00000000, - 0x878, 0x000f000f, 0x00000002, - 0xe74, 0x0f000000, 0x00000002, - 0xe78, 0x0f000000, 0x00000002, - 0xe7c, 0x0f000000, 0x00000002, - 0xe80, 0x0f000000, 0x00000002, - 0x90c, 0x000000ff, 0x00000011, - 0xc04, 0x000000ff, 0x00000011, - 0xd04, 0x0000000f, 0x00000001, - 0x1f4, 0xffff0000, 0x00007777, - 0x234, 0xf8000000, 0x0000000a, -}; - -u32 rtl8192sephy_changeto_1t2rarray[PHY_CHANGETO_1T2RARRAYLENGTH] = { - 0x804, 0x0000000f, 0x00000003, - 0x824, 0x00f0000f, 0x00300004, - 0x82c, 0x00f0000f, 0x00300002, - 0x870, 0x04000000, 0x00000001, - 0x864, 0x00000400, 0x00000000, - 0x878, 0x000f000f, 0x00000002, - 0xe74, 0x0f000000, 0x00000002, - 0xe78, 0x0f000000, 0x00000002, - 0xe7c, 0x0f000000, 0x00000002, - 0xe80, 0x0f000000, 0x00000002, - 0x90c, 0x000000ff, 0x00000011, - 0xc04, 0x000000ff, 0x00000033, - 0xd04, 0x0000000f, 0x00000003, - 0x1f4, 0xffff0000, 0x00007777, - 0x234, 0xf8000000, 0x0000000a, -}; - -u32 rtl8192sephy_reg_array_pg[PHY_REG_ARRAY_PGLENGTH] = { - 0xe00, 0xffffffff, 0x06090909, - 0xe04, 0xffffffff, 0x00030406, - 0xe08, 0x0000ff00, 0x00000000, - 0xe10, 0xffffffff, 0x0a0c0d0e, - 0xe14, 0xffffffff, 0x04070809, - 0xe18, 0xffffffff, 0x0a0c0d0e, - 0xe1c, 0xffffffff, 0x04070809, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0xe10, 0xffffffff, 0x02040404, - 0xe14, 0xffffffff, 0x00000002, - 0xe18, 0xffffffff, 0x02040404, - 0xe1c, 0xffffffff, 0x00000002, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0xe10, 0xffffffff, 0x02040404, - 0xe14, 0xffffffff, 0x00000002, - 0xe18, 0xffffffff, 0x02040404, - 0xe1c, 0xffffffff, 0x00000002, - 0xe00, 0xffffffff, 0x02020202, - 0xe04, 0xffffffff, 0x00020202, - 0xe08, 0x0000ff00, 0x00000000, - 0xe10, 0xffffffff, 0x02020202, - 0xe14, 0xffffffff, 0x00000002, - 0xe18, 0xffffffff, 0x02020202, - 0xe1c, 0xffffffff, 0x00000002, -}; - -u32 rtl8192seradioa_1t_array[RADIOA_1T_ARRAYLENGTH] = { - 0x000, 0x00030159, - 0x001, 0x00030250, - 0x002, 0x00010000, - 0x010, 0x0008000f, - 0x011, 0x000231fc, - 0x010, 0x000c000f, - 0x011, 0x0003f9f8, - 0x010, 0x0002000f, - 0x011, 0x00020101, - 0x014, 0x0001093e, - 0x014, 0x0009093e, - 0x015, 0x0000f8f4, - 0x017, 0x000f6500, - 0x01a, 0x00013056, - 0x01b, 0x00060000, - 0x01c, 0x00000300, - 0x01e, 0x00031059, - 0x021, 0x00054000, - 0x022, 0x0000083c, - 0x023, 0x00001558, - 0x024, 0x00000060, - 0x025, 0x00022583, - 0x026, 0x0000f200, - 0x027, 0x000eacf1, - 0x028, 0x0009bd54, - 0x029, 0x00004582, - 0x02a, 0x00000001, - 0x02b, 0x00021334, - 0x02a, 0x00000000, - 0x02b, 0x0000000a, - 0x02a, 0x00000001, - 0x02b, 0x00000808, - 0x02b, 0x00053333, - 0x02c, 0x0000000c, - 0x02a, 0x00000002, - 0x02b, 0x00000808, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000003, - 0x02b, 0x00000808, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000004, - 0x02b, 0x00000808, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000005, - 0x02b, 0x00000709, - 0x02b, 0x00053333, - 0x02c, 0x0000000d, - 0x02a, 0x00000006, - 0x02b, 0x00000709, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000007, - 0x02b, 0x00000709, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000008, - 0x02b, 0x00000709, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000009, - 0x02b, 0x0000060a, - 0x02b, 0x00053333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000a, - 0x02b, 0x0000060a, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000b, - 0x02b, 0x0000060a, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000c, - 0x02b, 0x0000060a, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000d, - 0x02b, 0x0000050b, - 0x02b, 0x00053333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000e, - 0x02b, 0x0000050b, - 0x02b, 0x00066623, - 0x02c, 0x0000001a, - 0x02a, 0x000e4000, - 0x030, 0x00020000, - 0x031, 0x000b9631, - 0x032, 0x0000130d, - 0x033, 0x00000187, - 0x013, 0x00019e6c, - 0x013, 0x00015e94, - 0x000, 0x00010159, - 0x018, 0x0000f401, - 0x0fe, 0x00000000, - 0x01e, 0x0003105b, - 0x0fe, 0x00000000, - 0x000, 0x00030159, - 0x010, 0x0004000f, - 0x011, 0x000203f9, -}; - -u32 rtl8192seradiob_array[RADIOB_ARRAYLENGTH] = { - 0x000, 0x00030159, - 0x001, 0x00001041, - 0x002, 0x00011000, - 0x005, 0x00080fc0, - 0x007, 0x000fc803, - 0x013, 0x00017cb0, - 0x013, 0x00011cc0, - 0x013, 0x0000dc60, - 0x013, 0x00008c60, - 0x013, 0x00004450, - 0x013, 0x00000020, -}; - -u32 rtl8192seradiob_gm_array[RADIOB_GM_ARRAYLENGTH] = { - 0x000, 0x00030159, - 0x001, 0x00001041, - 0x002, 0x00011000, - 0x005, 0x00080fc0, - 0x007, 0x000fc803, -}; - -u32 rtl8192semac_2t_array[MAC_2T_ARRAYLENGTH] = { - 0x020, 0x00000035, - 0x048, 0x0000000e, - 0x049, 0x000000f0, - 0x04a, 0x00000077, - 0x04b, 0x00000083, - 0x0b5, 0x00000021, - 0x0dc, 0x000000ff, - 0x0dd, 0x000000ff, - 0x0de, 0x000000ff, - 0x0df, 0x000000ff, - 0x116, 0x00000000, - 0x117, 0x00000000, - 0x118, 0x00000000, - 0x119, 0x00000000, - 0x11a, 0x00000000, - 0x11b, 0x00000000, - 0x11c, 0x00000000, - 0x11d, 0x00000000, - 0x160, 0x0000000b, - 0x161, 0x0000000b, - 0x162, 0x0000000b, - 0x163, 0x0000000b, - 0x164, 0x0000000b, - 0x165, 0x0000000b, - 0x166, 0x0000000b, - 0x167, 0x0000000b, - 0x168, 0x0000000b, - 0x169, 0x0000000b, - 0x16a, 0x0000000b, - 0x16b, 0x0000000b, - 0x16c, 0x0000000b, - 0x16d, 0x0000000b, - 0x16e, 0x0000000b, - 0x16f, 0x0000000b, - 0x170, 0x0000000b, - 0x171, 0x0000000b, - 0x172, 0x0000000b, - 0x173, 0x0000000b, - 0x174, 0x0000000b, - 0x175, 0x0000000b, - 0x176, 0x0000000b, - 0x177, 0x0000000b, - 0x178, 0x0000000b, - 0x179, 0x0000000b, - 0x17a, 0x0000000b, - 0x17b, 0x0000000b, - 0x17c, 0x0000000b, - 0x17d, 0x0000000b, - 0x17e, 0x0000000b, - 0x17f, 0x0000000b, - 0x236, 0x0000000c, - 0x503, 0x00000022, - 0x560, 0x00000000, -}; - -u32 rtl8192seagctab_array[AGCTAB_ARRAYLENGTH] = { - 0xc78, 0x7f000001, - 0xc78, 0x7f010001, - 0xc78, 0x7e020001, - 0xc78, 0x7d030001, - 0xc78, 0x7c040001, - 0xc78, 0x7b050001, - 0xc78, 0x7a060001, - 0xc78, 0x79070001, - 0xc78, 0x78080001, - 0xc78, 0x77090001, - 0xc78, 0x760a0001, - 0xc78, 0x750b0001, - 0xc78, 0x740c0001, - 0xc78, 0x730d0001, - 0xc78, 0x720e0001, - 0xc78, 0x710f0001, - 0xc78, 0x70100001, - 0xc78, 0x6f110001, - 0xc78, 0x6f120001, - 0xc78, 0x6e130001, - 0xc78, 0x6d140001, - 0xc78, 0x6d150001, - 0xc78, 0x6c160001, - 0xc78, 0x6b170001, - 0xc78, 0x6a180001, - 0xc78, 0x6a190001, - 0xc78, 0x691a0001, - 0xc78, 0x681b0001, - 0xc78, 0x671c0001, - 0xc78, 0x661d0001, - 0xc78, 0x651e0001, - 0xc78, 0x641f0001, - 0xc78, 0x63200001, - 0xc78, 0x4c210001, - 0xc78, 0x4b220001, - 0xc78, 0x4a230001, - 0xc78, 0x49240001, - 0xc78, 0x48250001, - 0xc78, 0x47260001, - 0xc78, 0x46270001, - 0xc78, 0x45280001, - 0xc78, 0x44290001, - 0xc78, 0x2c2a0001, - 0xc78, 0x2b2b0001, - 0xc78, 0x2a2c0001, - 0xc78, 0x292d0001, - 0xc78, 0x282e0001, - 0xc78, 0x272f0001, - 0xc78, 0x26300001, - 0xc78, 0x25310001, - 0xc78, 0x24320001, - 0xc78, 0x23330001, - 0xc78, 0x22340001, - 0xc78, 0x09350001, - 0xc78, 0x08360001, - 0xc78, 0x07370001, - 0xc78, 0x06380001, - 0xc78, 0x05390001, - 0xc78, 0x043a0001, - 0xc78, 0x033b0001, - 0xc78, 0x023c0001, - 0xc78, 0x013d0001, - 0xc78, 0x003e0001, - 0xc78, 0x003f0001, - 0xc78, 0x7f400001, - 0xc78, 0x7f410001, - 0xc78, 0x7e420001, - 0xc78, 0x7d430001, - 0xc78, 0x7c440001, - 0xc78, 0x7b450001, - 0xc78, 0x7a460001, - 0xc78, 0x79470001, - 0xc78, 0x78480001, - 0xc78, 0x77490001, - 0xc78, 0x764a0001, - 0xc78, 0x754b0001, - 0xc78, 0x744c0001, - 0xc78, 0x734d0001, - 0xc78, 0x724e0001, - 0xc78, 0x714f0001, - 0xc78, 0x70500001, - 0xc78, 0x6f510001, - 0xc78, 0x6f520001, - 0xc78, 0x6e530001, - 0xc78, 0x6d540001, - 0xc78, 0x6d550001, - 0xc78, 0x6c560001, - 0xc78, 0x6b570001, - 0xc78, 0x6a580001, - 0xc78, 0x6a590001, - 0xc78, 0x695a0001, - 0xc78, 0x685b0001, - 0xc78, 0x675c0001, - 0xc78, 0x665d0001, - 0xc78, 0x655e0001, - 0xc78, 0x645f0001, - 0xc78, 0x63600001, - 0xc78, 0x4c610001, - 0xc78, 0x4b620001, - 0xc78, 0x4a630001, - 0xc78, 0x49640001, - 0xc78, 0x48650001, - 0xc78, 0x47660001, - 0xc78, 0x46670001, - 0xc78, 0x45680001, - 0xc78, 0x44690001, - 0xc78, 0x2c6a0001, - 0xc78, 0x2b6b0001, - 0xc78, 0x2a6c0001, - 0xc78, 0x296d0001, - 0xc78, 0x286e0001, - 0xc78, 0x276f0001, - 0xc78, 0x26700001, - 0xc78, 0x25710001, - 0xc78, 0x24720001, - 0xc78, 0x23730001, - 0xc78, 0x22740001, - 0xc78, 0x09750001, - 0xc78, 0x08760001, - 0xc78, 0x07770001, - 0xc78, 0x06780001, - 0xc78, 0x05790001, - 0xc78, 0x047a0001, - 0xc78, 0x037b0001, - 0xc78, 0x027c0001, - 0xc78, 0x017d0001, - 0xc78, 0x007e0001, - 0xc78, 0x007f0001, - 0xc78, 0x3000001e, - 0xc78, 0x3001001e, - 0xc78, 0x3002001e, - 0xc78, 0x3003001e, - 0xc78, 0x3004001e, - 0xc78, 0x3405001e, - 0xc78, 0x3806001e, - 0xc78, 0x3e07001e, - 0xc78, 0x3e08001e, - 0xc78, 0x4409001e, - 0xc78, 0x460a001e, - 0xc78, 0x480b001e, - 0xc78, 0x480c001e, - 0xc78, 0x4e0d001e, - 0xc78, 0x560e001e, - 0xc78, 0x5a0f001e, - 0xc78, 0x5e10001e, - 0xc78, 0x6211001e, - 0xc78, 0x6c12001e, - 0xc78, 0x7213001e, - 0xc78, 0x7214001e, - 0xc78, 0x7215001e, - 0xc78, 0x7216001e, - 0xc78, 0x7217001e, - 0xc78, 0x7218001e, - 0xc78, 0x7219001e, - 0xc78, 0x721a001e, - 0xc78, 0x721b001e, - 0xc78, 0x721c001e, - 0xc78, 0x721d001e, - 0xc78, 0x721e001e, - 0xc78, 0x721f001e, -}; - diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/table.h b/drivers/net/wireless/rtlwifi/rtl8192se/table.h deleted file mode 100644 index 2feb73b71a4f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/table.h +++ /dev/null @@ -1,49 +0,0 @@ -/****************************************************************************** - * Copyright(c) 2008 - 2012 Realtek Corporation. All rights reserved. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * - * Larry Finger - * - ******************************************************************************/ -#ifndef __INC_HAL8192SE_FW_IMG_H -#define __INC_HAL8192SE_FW_IMG_H - -#include - -/*Created on 2010/ 4/12, 5:56*/ - -#define PHY_REG_2T2RARRAYLENGTH 372 -extern u32 rtl8192sephy_reg_2t2rarray[PHY_REG_2T2RARRAYLENGTH]; -#define PHY_CHANGETO_1T1RARRAYLENGTH 48 -extern u32 rtl8192sephy_changeto_1t1rarray[PHY_CHANGETO_1T1RARRAYLENGTH]; -#define PHY_CHANGETO_1T2RARRAYLENGTH 45 -extern u32 rtl8192sephy_changeto_1t2rarray[PHY_CHANGETO_1T2RARRAYLENGTH]; -#define PHY_REG_ARRAY_PGLENGTH 84 -extern u32 rtl8192sephy_reg_array_pg[PHY_REG_ARRAY_PGLENGTH]; -#define RADIOA_1T_ARRAYLENGTH 202 -extern u32 rtl8192seradioa_1t_array[RADIOA_1T_ARRAYLENGTH]; -#define RADIOB_ARRAYLENGTH 22 -extern u32 rtl8192seradiob_array[RADIOB_ARRAYLENGTH]; -#define RADIOB_GM_ARRAYLENGTH 10 -extern u32 rtl8192seradiob_gm_array[RADIOB_GM_ARRAYLENGTH]; -#define MAC_2T_ARRAYLENGTH 106 -extern u32 rtl8192semac_2t_array[MAC_2T_ARRAYLENGTH]; -#define AGCTAB_ARRAYLENGTH 320 -extern u32 rtl8192seagctab_array[AGCTAB_ARRAYLENGTH]; - -#endif - diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c deleted file mode 100644 index 125b29bd2f93..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ /dev/null @@ -1,658 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../stats.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "fw.h" -#include "trx.h" -#include "led.h" - -static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) -{ - __le16 fc = rtl_get_fc(skb); - - if (unlikely(ieee80211_is_beacon(fc))) - return QSLT_BEACON; - if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) - return QSLT_MGNT; - if (ieee80211_is_nullfunc(fc)) - return QSLT_HIGH; - - /* Kernel commit 1bf4bbb4024dcdab changed EAPOL packets to use - * queue V0 at priority 7; however, the RTL8192SE appears to have - * that queue at priority 6 - */ - if (skb->priority == 7) - return QSLT_VO; - return skb->priority; -} - -static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, - struct rtl_stats *pstats, u8 *pdesc, - struct rx_fwinfo *p_drvinfo, - bool packet_match_bssid, - bool packet_toself, - bool packet_beacon) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct phy_sts_cck_8192s_t *cck_buf; - struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); - s8 rx_pwr_all = 0, rx_pwr[4]; - u8 rf_rx_num = 0, evm, pwdb_all; - u8 i, max_spatial_stream; - u32 rssi, total_rssi = 0; - bool is_cck = pstats->is_cck; - - pstats->packet_matchbssid = packet_match_bssid; - pstats->packet_toself = packet_toself; - pstats->packet_beacon = packet_beacon; - pstats->rx_mimo_sig_qual[0] = -1; - pstats->rx_mimo_sig_qual[1] = -1; - - if (is_cck) { - u8 report, cck_highpwr; - cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; - - if (ppsc->rfpwr_state == ERFON) - cck_highpwr = (u8) rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, - 0x200); - else - cck_highpwr = false; - - if (!cck_highpwr) { - u8 cck_agc_rpt = cck_buf->cck_agc_rpt; - report = cck_buf->cck_agc_rpt & 0xc0; - report = report >> 6; - switch (report) { - case 0x3: - rx_pwr_all = -40 - (cck_agc_rpt & 0x3e); - break; - case 0x2: - rx_pwr_all = -20 - (cck_agc_rpt & 0x3e); - break; - case 0x1: - rx_pwr_all = -2 - (cck_agc_rpt & 0x3e); - break; - case 0x0: - rx_pwr_all = 14 - (cck_agc_rpt & 0x3e); - break; - } - } else { - u8 cck_agc_rpt = cck_buf->cck_agc_rpt; - report = p_drvinfo->cfosho[0] & 0x60; - report = report >> 5; - switch (report) { - case 0x3: - rx_pwr_all = -40 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x2: - rx_pwr_all = -20 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x1: - rx_pwr_all = -2 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x0: - rx_pwr_all = 14 - ((cck_agc_rpt & 0x1f) << 1); - break; - } - } - - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - - /* CCK gain is smaller than OFDM/MCS gain, */ - /* so we add gain diff by experiences, the val is 6 */ - pwdb_all += 6; - if (pwdb_all > 100) - pwdb_all = 100; - /* modify the offset to make the same gain index with OFDM. */ - if (pwdb_all > 34 && pwdb_all <= 42) - pwdb_all -= 2; - else if (pwdb_all > 26 && pwdb_all <= 34) - pwdb_all -= 6; - else if (pwdb_all > 14 && pwdb_all <= 26) - pwdb_all -= 8; - else if (pwdb_all > 4 && pwdb_all <= 14) - pwdb_all -= 4; - - pstats->rx_pwdb_all = pwdb_all; - pstats->recvsignalpower = rx_pwr_all; - - if (packet_match_bssid) { - u8 sq; - if (pstats->rx_pwdb_all > 40) { - sq = 100; - } else { - sq = cck_buf->sq_rpt; - if (sq > 64) - sq = 0; - else if (sq < 20) - sq = 100; - else - sq = ((64 - sq) * 100) / 44; - } - - pstats->signalquality = sq; - pstats->rx_mimo_sig_qual[0] = sq; - pstats->rx_mimo_sig_qual[1] = -1; - } - } else { - rtlpriv->dm.rfpath_rxenable[0] = - rtlpriv->dm.rfpath_rxenable[1] = true; - for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { - if (rtlpriv->dm.rfpath_rxenable[i]) - rf_rx_num++; - - rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & - 0x3f) * 2) - 110; - rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); - total_rssi += rssi; - rtlpriv->stats.rx_snr_db[i] = - (long)(p_drvinfo->rxsnr[i] / 2); - - if (packet_match_bssid) - pstats->rx_mimo_signalstrength[i] = (u8) rssi; - } - - rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - pstats->rx_pwdb_all = pwdb_all; - pstats->rxpower = rx_pwr_all; - pstats->recvsignalpower = rx_pwr_all; - - if (pstats->is_ht && pstats->rate >= DESC_RATEMCS8 && - pstats->rate <= DESC_RATEMCS15) - max_spatial_stream = 2; - else - max_spatial_stream = 1; - - for (i = 0; i < max_spatial_stream; i++) { - evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]); - - if (packet_match_bssid) { - if (i == 0) - pstats->signalquality = (u8)(evm & - 0xff); - pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff); - } - } - } - - if (is_cck) - pstats->signalstrength = (u8)(rtl_signal_scale_mapping(hw, - pwdb_all)); - else if (rf_rx_num != 0) - pstats->signalstrength = (u8) (rtl_signal_scale_mapping(hw, - total_rssi /= rf_rx_num)); -} - -static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, - struct sk_buff *skb, struct rtl_stats *pstats, - u8 *pdesc, struct rx_fwinfo *p_drvinfo) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - - struct ieee80211_hdr *hdr; - u8 *tmp_buf; - u8 *praddr; - __le16 fc; - u16 type, cfc; - bool packet_matchbssid, packet_toself, packet_beacon = false; - - tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; - - hdr = (struct ieee80211_hdr *)tmp_buf; - fc = hdr->frame_control; - cfc = le16_to_cpu(fc); - type = WLAN_FC_GET_TYPE(fc); - praddr = hdr->addr1; - - packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && - ether_addr_equal(mac->bssid, - (cfc & IEEE80211_FCTL_TODS) ? hdr->addr1 : - (cfc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 : - hdr->addr3) && - (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv)); - - packet_toself = packet_matchbssid && - ether_addr_equal(praddr, rtlefuse->dev_addr); - - if (ieee80211_is_beacon(fc)) - packet_beacon = true; - - _rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, - packet_matchbssid, packet_toself, packet_beacon); - rtl_process_phyinfo(hw, tmp_buf, pstats); -} - -bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, - struct ieee80211_rx_status *rx_status, u8 *pdesc, - struct sk_buff *skb) -{ - struct rx_fwinfo *p_drvinfo; - u32 phystatus = (u32)GET_RX_STATUS_DESC_PHY_STATUS(pdesc); - struct ieee80211_hdr *hdr; - - stats->length = (u16)GET_RX_STATUS_DESC_PKT_LEN(pdesc); - stats->rx_drvinfo_size = (u8)GET_RX_STATUS_DESC_DRVINFO_SIZE(pdesc) * 8; - stats->rx_bufshift = (u8)(GET_RX_STATUS_DESC_SHIFT(pdesc) & 0x03); - stats->icv = (u16)GET_RX_STATUS_DESC_ICV(pdesc); - stats->crc = (u16)GET_RX_STATUS_DESC_CRC32(pdesc); - stats->hwerror = (u16)(stats->crc | stats->icv); - stats->decrypted = !GET_RX_STATUS_DESC_SWDEC(pdesc); - - stats->rate = (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc); - stats->shortpreamble = (u16)GET_RX_STATUS_DESC_SPLCP(pdesc); - stats->isampdu = (bool)(GET_RX_STATUS_DESC_PAGGR(pdesc) == 1); - stats->isfirst_ampdu = (bool) ((GET_RX_STATUS_DESC_PAGGR(pdesc) == 1) - && (GET_RX_STATUS_DESC_FAGGR(pdesc) == 1)); - stats->timestamp_low = GET_RX_STATUS_DESC_TSFL(pdesc); - stats->rx_is40Mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc); - stats->is_ht = (bool)GET_RX_STATUS_DESC_RX_HT(pdesc); - stats->is_cck = SE_RX_HAL_IS_CCK_RATE(pdesc); - - if (stats->hwerror) - return false; - - rx_status->freq = hw->conf.chandef.chan->center_freq; - rx_status->band = hw->conf.chandef.chan->band; - - if (stats->crc) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - - if (stats->rx_is40Mhzpacket) - rx_status->flag |= RX_FLAG_40MHZ; - - if (stats->is_ht) - rx_status->flag |= RX_FLAG_HT; - - rx_status->flag |= RX_FLAG_MACTIME_START; - - /* hw will set stats->decrypted true, if it finds the - * frame is open data frame or mgmt frame, - * hw will not decrypt robust managment frame - * for IEEE80211w but still set stats->decrypted - * true, so here we should set it back to undecrypted - * for IEEE80211w frame, and mac80211 sw will help - * to decrypt it */ - if (stats->decrypted) { - hdr = (struct ieee80211_hdr *)(skb->data + - stats->rx_drvinfo_size + stats->rx_bufshift); - - if ((_ieee80211_is_robust_mgmt_frame(hdr)) && - (ieee80211_has_protected(hdr->frame_control))) - rx_status->flag &= ~RX_FLAG_DECRYPTED; - else - rx_status->flag |= RX_FLAG_DECRYPTED; - } - - rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht, - false, stats->rate); - - rx_status->mactime = stats->timestamp_low; - if (phystatus) { - p_drvinfo = (struct rx_fwinfo *)(skb->data + - stats->rx_bufshift); - _rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc, - p_drvinfo); - } - - /*rx_status->qual = stats->signal; */ - rx_status->signal = stats->recvsignalpower + 10; - - return true; -} - -void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *pbd_desc_tx, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 *pdesc = pdesc_tx; - u16 seq_number; - __le16 fc = hdr->frame_control; - u8 reserved_macid = 0; - u8 fw_qsel = _rtl92se_map_hwqueue_to_fwqueue(skb, hw_queue); - bool firstseg = (!(hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG))); - bool lastseg = (!(hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_MOREFRAGS))); - dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - u8 bw_40 = 0; - - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - if (mac->opmode == NL80211_IFTYPE_STATION) { - bw_40 = mac->bw_40; - } else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - if (sta) - bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40; - } - - seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - - rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); - - CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S); - - if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { - firstseg = true; - lastseg = true; - } - - if (firstseg) { - if (rtlpriv->dm.useramask) { - /* set txdesc macId */ - if (ptcb_desc->mac_id < 32) { - SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); - reserved_macid |= ptcb_desc->mac_id; - } - } - SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid); - - SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >= - DESC_RATEMCS0) ? 1 : 0)); - - if (rtlhal->version == VERSION_8192S_ACUT) { - if (ptcb_desc->hw_rate == DESC_RATE1M || - ptcb_desc->hw_rate == DESC_RATE2M || - ptcb_desc->hw_rate == DESC_RATE5_5M || - ptcb_desc->hw_rate == DESC_RATE11M) { - ptcb_desc->hw_rate = DESC_RATE12M; - } - } - - SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); - - if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) - SET_TX_DESC_TX_SHORT(pdesc, 0); - - /* Aggregation related */ - if (info->flags & IEEE80211_TX_CTL_AMPDU) - SET_TX_DESC_AGG_ENABLE(pdesc, 1); - - /* For AMPDU, we must insert SSN into TX_DESC */ - SET_TX_DESC_SEQ(pdesc, seq_number); - - /* Protection mode related */ - /* For 92S, if RTS/CTS are set, HW will execute RTS. */ - /* We choose only one protection mode to execute */ - SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && - !ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS_ENABLE(pdesc, ((ptcb_desc->cts_enable) ? - 1 : 0)); - SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); - - SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); - SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0); - SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= - DESC_RATE54M) ? - (ptcb_desc->rts_use_shortpreamble ? 1 : 0) - : (ptcb_desc->rts_use_shortgi ? 1 : 0))); - - - /* Set Bandwidth and sub-channel settings. */ - if (bw_40) { - if (ptcb_desc->packet_bw) { - SET_TX_DESC_TX_BANDWIDTH(pdesc, 1); - /* use duplicated mode */ - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); - } else { - SET_TX_DESC_TX_BANDWIDTH(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, - mac->cur_40_prime_sc); - } - } else { - SET_TX_DESC_TX_BANDWIDTH(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); - } - - /* 3 Fill necessary field in First Descriptor */ - /*DWORD 0*/ - SET_TX_DESC_LINIP(pdesc, 0); - SET_TX_DESC_OFFSET(pdesc, 32); - SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); - - /*DWORD 1*/ - SET_TX_DESC_RA_BRSR_ID(pdesc, ptcb_desc->ratr_index); - - /* Fill security related */ - if (info->control.hw_key) { - struct ieee80211_key_conf *keyconf; - - keyconf = info->control.hw_key; - switch (keyconf->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - SET_TX_DESC_SEC_TYPE(pdesc, 0x1); - break; - case WLAN_CIPHER_SUITE_TKIP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x2); - break; - case WLAN_CIPHER_SUITE_CCMP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x3); - break; - default: - SET_TX_DESC_SEC_TYPE(pdesc, 0x0); - break; - - } - } - - /* Set Packet ID */ - SET_TX_DESC_PACKET_ID(pdesc, 0); - - /* We will assign magement queue to BK. */ - SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); - - /* Alwasy enable all rate fallback range */ - SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); - - /* Fix: I don't kown why hw use 6.5M to tx when set it */ - SET_TX_DESC_USER_RATE(pdesc, - ptcb_desc->use_driver_rate ? 1 : 0); - - /* Set NON_QOS bit. */ - if (!ieee80211_is_data_qos(fc)) - SET_TX_DESC_NON_QOS(pdesc, 1); - - } - - /* Fill fields that are required to be initialized - * in all of the descriptors */ - /*DWORD 0 */ - SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); - SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); - - /* DWORD 7 */ - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); - - /* DOWRD 8 */ - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); -} - -void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb); - - dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - /* Clear all status */ - CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S); - - /* This bit indicate this packet is used for FW download. */ - if (tcb_desc->cmd_or_init == DESC_PACKET_TYPE_INIT) { - /* For firmware downlaod we only need to set LINIP */ - SET_TX_DESC_LINIP(pdesc, tcb_desc->last_inipkt); - - /* 92SE must set as 1 for firmware download HW DMA error */ - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - /* 92SE need not to set TX packet size when firmware download */ - SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - wmb(); - SET_TX_DESC_OWN(pdesc, 1); - } else { /* H2C Command Desc format (Host TXCMD) */ - /* 92SE must set as 1 for firmware download HW DMA error */ - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - SET_TX_DESC_OFFSET(pdesc, 0x20); - - /* Buffer size + command header */ - SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); - /* Fixed queue of H2C command */ - SET_TX_DESC_QUEUE_SEL(pdesc, 0x13); - - SET_BITS_TO_LE_4BYTE(skb->data, 24, 7, rtlhal->h2c_txcmd_seq); - - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - wmb(); - SET_TX_DESC_OWN(pdesc, 1); - - } -} - -void rtl92se_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, - u8 desc_name, u8 *val) -{ - if (istx) { - switch (desc_name) { - case HW_DESC_OWN: - wmb(); - SET_TX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_TX_NEXTDESC_ADDR: - SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); - break; - default: - RT_ASSERT(false, "ERR txdesc :%d not process\n", - desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_RXOWN: - wmb(); - SET_RX_STATUS_DESC_OWN(pdesc, 1); - break; - case HW_DESC_RXBUFF_ADDR: - SET_RX_STATUS__DESC_BUFF_ADDR(pdesc, *(u32 *) val); - break; - case HW_DESC_RXPKT_LEN: - SET_RX_STATUS_DESC_PKT_LEN(pdesc, *(u32 *) val); - break; - case HW_DESC_RXERO: - SET_RX_STATUS_DESC_EOR(pdesc, 1); - break; - default: - RT_ASSERT(false, "ERR rxdesc :%d not process\n", - desc_name); - break; - } - } -} - -u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name) -{ - u32 ret = 0; - - if (istx) { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_TX_DESC_OWN(desc); - break; - case HW_DESC_TXBUFF_ADDR: - ret = GET_TX_DESC_TX_BUFFER_ADDRESS(desc); - break; - default: - RT_ASSERT(false, "ERR txdesc :%d not process\n", - desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_RX_STATUS_DESC_OWN(desc); - break; - case HW_DESC_RXPKT_LEN: - ret = GET_RX_STATUS_DESC_PKT_LEN(desc); - break; - case HW_DESC_RXBUFF_ADDR: - ret = GET_RX_STATUS_DESC_BUFF_ADDR(desc); - break; - default: - RT_ASSERT(false, "ERR rxdesc :%d not process\n", - desc_name); - break; - } - } - return ret; -} - -void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - rtl_write_word(rtlpriv, TP_POLL, BIT(0) << (hw_queue)); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.h b/drivers/net/wireless/rtlwifi/rtl8192se/trx.h deleted file mode 100644 index 5a13f17e3b41..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.h +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#ifndef __REALTEK_PCI92SE_TRX_H__ -#define __REALTEK_PCI92SE_TRX_H__ - -void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc, - u8 *pbd_desc_tx, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, u8 hw_queue, - struct rtl_tcb_desc *ptcb_desc); -void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, - bool lastseg, struct sk_buff *skb); -bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, - struct ieee80211_rx_status *rx_status, u8 *pdesc, - struct sk_buff *skb); -void rtl92se_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx, - u8 desc_name, u8 *val); -u32 rtl92se_get_desc(u8 *pdesc, bool istx, u8 desc_name); -void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile b/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile deleted file mode 100644 index 6220672a96f4..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -rtl8723ae-objs := \ - dm.o \ - fw.o \ - hal_btc.o \ - hal_bt_coexist.o\ - hw.o \ - led.o \ - phy.o \ - pwrseq.o \ - rf.o \ - sw.o \ - table.o \ - trx.o \ - - -obj-$(CONFIG_RTL8723AE) += rtl8723ae.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h b/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h deleted file mode 100644 index 06c448c010fd..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/btc.h +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - ** - ** Copyright(c) 2009-2012 Realtek Corporation. - ** - ** 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 - ** published by the Free Software Foundation. - ** - ** This program is distributed in the hope that it will be useful, but WITHOUT - ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - ** more details. - ** - ** The full GNU General Public License is included in this distribution in the - ** file called LICENSE. - ** - ** Contact Information: - ** wlanfae - ** Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - ** Hsinchu 300, Taiwan. - ** Larry Finger - ** - ******************************************************************************/ - -#ifndef __RTL8723E_BTC_H__ -#define __RTL8723E_BTC_H__ - -#include "../wifi.h" -#include "hal_bt_coexist.h" - -struct bt_coexist_c2h_info { - u8 no_parse_c2h; - u8 has_c2h; -}; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/def.h b/drivers/net/wireless/rtlwifi/rtl8723ae/def.h deleted file mode 100644 index bcdf2273688e..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/def.h +++ /dev/null @@ -1,238 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_DEF_H__ -#define __RTL8723E_DEF_H__ - -#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 -#define HAL_PRIME_CHNL_OFFSET_LOWER 1 -#define HAL_PRIME_CHNL_OFFSET_UPPER 2 - -#define RX_MPDU_QUEUE 0 -#define RX_CMD_QUEUE 1 - -#define C2H_RX_CMD_HDR_LEN 8 -#define GET_C2H_CMD_CMD_LEN(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 0, 16) -#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 16, 8) -#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 24, 7) -#define GET_C2H_CMD_CONTINUE(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 31, 1) -#define GET_C2H_CMD_CONTENT(__prxhdr) \ - ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) - -#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) -#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) -#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) -#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) -#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) -#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) -#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) -#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) -#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) - -#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) -#define CHIP_BONDING_92C_1T2R 0x1 - -#define CHIP_8723 BIT(0) -#define NORMAL_CHIP BIT(3) -#define RF_TYPE_1T1R (~(BIT(4)|BIT(5)|BIT(6))) -#define RF_TYPE_1T2R BIT(4) -#define RF_TYPE_2T2R BIT(5) -#define CHIP_VENDOR_UMC BIT(7) -#define B_CUT_VERSION BIT(12) -#define C_CUT_VERSION BIT(13) -#define D_CUT_VERSION ((BIT(12)|BIT(13))) -#define E_CUT_VERSION BIT(14) -#define RF_RL_ID (BIT(31)|BIT(30)|BIT(29)|BIT(28)) - -/* MASK */ -#define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2)) -#define CHIP_TYPE_MASK BIT(3) -#define RF_TYPE_MASK (BIT(4)|BIT(5)|BIT(6)) -#define MANUFACTUER_MASK BIT(7) -#define ROM_VERSION_MASK (BIT(11)|BIT(10)|BIT(9)|BIT(8)) -#define CUT_VERSION_MASK (BIT(15)|BIT(14)|BIT(13)|BIT(12)) - -/* Get element */ -#define GET_CVID_IC_TYPE(version) ((version) & IC_TYPE_MASK) -#define GET_CVID_CHIP_TYPE(version) ((version) & CHIP_TYPE_MASK) -#define GET_CVID_RF_TYPE(version) ((version) & RF_TYPE_MASK) -#define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK) -#define GET_CVID_ROM_VERSION(version) ((version) & ROM_VERSION_MASK) -#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK) - -#define IS_81XXC(version) ((GET_CVID_IC_TYPE(version) == 0) ?\ - true : false) -#define IS_8723_SERIES(version) ((GET_CVID_IC_TYPE(version) == CHIP_8723) ? \ - true : false) -#define IS_1T1R(version) ((GET_CVID_RF_TYPE(version)) ? false : true) -#define IS_1T2R(version) ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R)\ - ? true : false) -#define IS_2T2R(version) ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R)\ - ? true : false) -#define IS_CHIP_VENDOR_UMC(version) ((GET_CVID_MANUFACTUER(version)) ? \ - true : false) - -#define IS_VENDOR_UMC_A_CUT(version) ((IS_CHIP_VENDOR_UMC(version))\ - ? ((GET_CVID_CUT_VERSION(version)) ? \ - false : true) : false) -#define IS_VENDOR_8723_A_CUT(version) ((IS_8723_SERIES(version))\ - ? ((GET_CVID_CUT_VERSION(version)) ? \ - false : true) : false) -#define IS_VENDOR_8723A_B_CUT(version) ((IS_8723_SERIES(version))\ - ? ((GET_CVID_CUT_VERSION(version) == \ - B_CUT_VERSION) ? true : false) : false) -#define IS_81xxC_VENDOR_UMC_B_CUT(version) ((IS_CHIP_VENDOR_UMC(version))\ - ? ((GET_CVID_CUT_VERSION(version) == \ - B_CUT_VERSION) ? true : false) : false) - -enum rf_optype { - RF_OP_BY_SW_3WIRE = 0, - RF_OP_BY_FW, - RF_OP_MAX -}; - -enum rf_power_state { - RF_ON, - RF_OFF, - RF_SLEEP, - RF_SHUT_DOWN, -}; - -enum power_save_mode { - POWER_SAVE_MODE_ACTIVE, - POWER_SAVE_MODE_SAVE, -}; - -enum power_policy_config { - POWERCFG_MAX_POWER_SAVINGS, - POWERCFG_GLOBAL_POWER_SAVINGS, - POWERCFG_LOCAL_POWER_SAVINGS, - POWERCFG_LENOVO, -}; - -enum interface_select_pci { - INTF_SEL1_MINICARD = 0, - INTF_SEL0_PCIE = 1, - INTF_SEL2_RSV = 2, - INTF_SEL3_RSV = 3, -}; - -enum hal_fw_c2h_cmd_id { - HAL_FW_C2H_CMD_Read_MACREG = 0, - HAL_FW_C2H_CMD_Read_BBREG = 1, - HAL_FW_C2H_CMD_Read_RFREG = 2, - HAL_FW_C2H_CMD_Read_EEPROM = 3, - HAL_FW_C2H_CMD_Read_EFUSE = 4, - HAL_FW_C2H_CMD_Read_CAM = 5, - HAL_FW_C2H_CMD_Get_BasicRate = 6, - HAL_FW_C2H_CMD_Get_DataRate = 7, - HAL_FW_C2H_CMD_Survey = 8, - HAL_FW_C2H_CMD_SurveyDone = 9, - HAL_FW_C2H_CMD_JoinBss = 10, - HAL_FW_C2H_CMD_AddSTA = 11, - HAL_FW_C2H_CMD_DelSTA = 12, - HAL_FW_C2H_CMD_AtimDone = 13, - HAL_FW_C2H_CMD_TX_Report = 14, - HAL_FW_C2H_CMD_CCX_Report = 15, - HAL_FW_C2H_CMD_DTM_Report = 16, - HAL_FW_C2H_CMD_TX_Rate_Statistics = 17, - HAL_FW_C2H_CMD_C2HLBK = 18, - HAL_FW_C2H_CMD_C2HDBG = 19, - HAL_FW_C2H_CMD_C2HFEEDBACK = 20, - HAL_FW_C2H_CMD_MAX -}; - -enum rtl_desc_qsel { - QSLT_BK = 0x2, - QSLT_BE = 0x0, - QSLT_VI = 0x5, - QSLT_VO = 0x7, - QSLT_BEACON = 0x10, - QSLT_HIGH = 0x11, - QSLT_MGNT = 0x12, - QSLT_CMD = 0x13, -}; - -enum rtl_desc8723e_rate { - DESC92C_RATE1M = 0x00, - DESC92C_RATE2M = 0x01, - DESC92C_RATE5_5M = 0x02, - DESC92C_RATE11M = 0x03, - - DESC92C_RATE6M = 0x04, - DESC92C_RATE9M = 0x05, - DESC92C_RATE12M = 0x06, - DESC92C_RATE18M = 0x07, - DESC92C_RATE24M = 0x08, - DESC92C_RATE36M = 0x09, - DESC92C_RATE48M = 0x0a, - DESC92C_RATE54M = 0x0b, - - DESC92C_RATEMCS0 = 0x0c, - DESC92C_RATEMCS1 = 0x0d, - DESC92C_RATEMCS2 = 0x0e, - DESC92C_RATEMCS3 = 0x0f, - DESC92C_RATEMCS4 = 0x10, - DESC92C_RATEMCS5 = 0x11, - DESC92C_RATEMCS6 = 0x12, - DESC92C_RATEMCS7 = 0x13, - DESC92C_RATEMCS8 = 0x14, - DESC92C_RATEMCS9 = 0x15, - DESC92C_RATEMCS10 = 0x16, - DESC92C_RATEMCS11 = 0x17, - DESC92C_RATEMCS12 = 0x18, - DESC92C_RATEMCS13 = 0x19, - DESC92C_RATEMCS14 = 0x1a, - DESC92C_RATEMCS15 = 0x1b, - DESC92C_RATEMCS15_SG = 0x1c, - DESC92C_RATEMCS32 = 0x20, -}; - -struct phy_sts_cck_8723e_t { - u8 adc_pwdb_X[4]; - u8 sq_rpt; - u8 cck_agc_rpt; -}; - -struct h2c_cmd_8723e { - u8 element_id; - u32 cmd_len; - u8 *p_cmdbuffer; -}; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c deleted file mode 100644 index 4c1c96c96a5a..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.c +++ /dev/null @@ -1,881 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../base.h" -#include "../pci.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "../rtl8723com/dm_common.h" -#include "fw.h" -#include "hal_btc.h" - -static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { - 0x7f8001fe, - 0x788001e2, - 0x71c001c7, - 0x6b8001ae, - 0x65400195, - 0x5fc0017f, - 0x5a400169, - 0x55400155, - 0x50800142, - 0x4c000130, - 0x47c0011f, - 0x43c0010f, - 0x40000100, - 0x3c8000f2, - 0x390000e4, - 0x35c000d7, - 0x32c000cb, - 0x300000c0, - 0x2d4000b5, - 0x2ac000ab, - 0x288000a2, - 0x26000098, - 0x24000090, - 0x22000088, - 0x20000080, - 0x1e400079, - 0x1c800072, - 0x1b00006c, - 0x19800066, - 0x18000060, - 0x16c0005b, - 0x15800056, - 0x14400051, - 0x1300004c, - 0x12000048, - 0x11000044, - 0x10000040, -}; - -static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} -}; - -static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, - {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, - {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, - {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, - {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, - {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, - {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, - {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, - {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, - {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, - {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, - {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, - {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} -}; - -static u8 rtl8723e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - long rssi_val_min = 0; - - if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) && - (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) { - if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0) - rssi_val_min = - (rtlpriv->dm.entry_min_undec_sm_pwdb > - rtlpriv->dm.undec_sm_pwdb) ? - rtlpriv->dm.undec_sm_pwdb : - rtlpriv->dm.entry_min_undec_sm_pwdb; - else - rssi_val_min = rtlpriv->dm.undec_sm_pwdb; - } else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT || - dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) { - rssi_val_min = rtlpriv->dm.undec_sm_pwdb; - } else if (dm_digtable->curmultista_cstate == - DIG_MULTISTA_CONNECT) { - rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb; - } - - return (u8) rssi_val_min; -} - -static void rtl8723e_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) -{ - u32 ret_value; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); - - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); - falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); - - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); - falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); - falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); - - ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); - falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); - falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail; - - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1); - ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0); - falsealm_cnt->cnt_cck_fail = ret_value; - - ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3); - falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; - falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + - falsealm_cnt->cnt_mcs_fail + - falsealm_cnt->cnt_cck_fail); - - rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1); - rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0); - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0); - rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", - falsealm_cnt->cnt_parity_fail, - falsealm_cnt->cnt_rate_illegal, - falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", - falsealm_cnt->cnt_ofdm_fail, - falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all); -} - -static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - u8 value_igi = dm_digtable->cur_igvalue; - - if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) - value_igi--; - else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1) - value_igi += 0; - else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2) - value_igi++; - else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2) - value_igi += 2; - if (value_igi > DM_DIG_FA_UPPER) - value_igi = DM_DIG_FA_UPPER; - else if (value_igi < DM_DIG_FA_LOWER) - value_igi = DM_DIG_FA_LOWER; - if (rtlpriv->falsealm_cnt.cnt_all > 10000) - value_igi = 0x32; - - dm_digtable->cur_igvalue = value_igi; - rtl8723e_dm_write_dig(hw); -} - -static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable->fa_highthresh) { - if ((dm_digtable->back_val - 2) < - dm_digtable->back_range_min) - dm_digtable->back_val = - dm_digtable->back_range_min; - else - dm_digtable->back_val -= 2; - } else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable->fa_lowthresh) { - if ((dm_digtable->back_val + 2) > - dm_digtable->back_range_max) - dm_digtable->back_val = - dm_digtable->back_range_max; - else - dm_digtable->back_val += 2; - } - - if ((dm_digtable->rssi_val_min + 10 - dm_digtable->back_val) > - dm_digtable->rx_gain_max) - dm_digtable->cur_igvalue = dm_digtable->rx_gain_max; - else if ((dm_digtable->rssi_val_min + 10 - - dm_digtable->back_val) < dm_digtable->rx_gain_min) - dm_digtable->cur_igvalue = dm_digtable->rx_gain_min; - else - dm_digtable->cur_igvalue = dm_digtable->rssi_val_min + 10 - - dm_digtable->back_val; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "rssi_val_min = %x back_val %x\n", - dm_digtable->rssi_val_min, dm_digtable->back_val); - - rtl8723e_dm_write_dig(hw); -} - -static void rtl8723e_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) -{ - static u8 binitialized; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb; - bool multi_sta = false; - - if (mac->opmode == NL80211_IFTYPE_ADHOC) - multi_sta = true; - - if (!multi_sta || (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT)) { - binitialized = false; - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; - return; - } else if (!binitialized) { - binitialized = true; - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; - dm_digtable->cur_igvalue = 0x20; - rtl8723e_dm_write_dig(hw); - } - - if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) { - if ((rssi_strength < dm_digtable->rssi_lowthresh) && - (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) { - - if (dm_digtable->dig_ext_port_stage == - DIG_EXT_PORT_STAGE_2) { - dm_digtable->cur_igvalue = 0x20; - rtl8723e_dm_write_dig(hw); - } - - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1; - } else if (rssi_strength > dm_digtable->rssi_highthresh) { - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2; - rtl92c_dm_ctrl_initgain_by_fa(hw); - } - } else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) { - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0; - dm_digtable->cur_igvalue = 0x20; - rtl8723e_dm_write_dig(hw); - } - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "curmultista_cstate = %x dig_ext_port_stage %x\n", - dm_digtable->curmultista_cstate, - dm_digtable->dig_ext_port_stage); -} - -static void rtl8723e_dm_initial_gain_sta(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "presta_cstate = %x, cursta_cstate = %x\n", - dm_digtable->presta_cstate, - dm_digtable->cursta_cstate); - - if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate || - dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT || - dm_digtable->cursta_cstate == DIG_STA_CONNECT) { - if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { - dm_digtable->rssi_val_min = - rtl8723e_dm_initial_gain_min_pwdb(hw); - rtl92c_dm_ctrl_initgain_by_rssi(hw); - } - } else { - dm_digtable->rssi_val_min = 0; - dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; - dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; - dm_digtable->cur_igvalue = 0x20; - dm_digtable->pre_igvalue = 0; - rtl8723e_dm_write_dig(hw); - } -} - -static void rtl8723e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) { - dm_digtable->rssi_val_min = rtl8723e_dm_initial_gain_min_pwdb(hw); - - if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { - if (dm_digtable->rssi_val_min <= 25) - dm_digtable->cur_cck_pd_state = - CCK_PD_STAGE_LOWRSSI; - else - dm_digtable->cur_cck_pd_state = - CCK_PD_STAGE_HIGHRSSI; - } else { - if (dm_digtable->rssi_val_min <= 20) - dm_digtable->cur_cck_pd_state = - CCK_PD_STAGE_LOWRSSI; - else - dm_digtable->cur_cck_pd_state = - CCK_PD_STAGE_HIGHRSSI; - } - } else { - dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX; - } - - if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) { - if (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { - if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800) - dm_digtable->cur_cck_fa_state = - CCK_FA_STAGE_HIGH; - else - dm_digtable->cur_cck_fa_state = - CCK_FA_STAGE_LOW; - if (dm_digtable->pre_cck_fa_state != - dm_digtable->cur_cck_fa_state) { - if (dm_digtable->cur_cck_fa_state == - CCK_FA_STAGE_LOW) - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, - 0x83); - else - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, - 0xcd); - - dm_digtable->pre_cck_fa_state = - dm_digtable->cur_cck_fa_state; - } - - rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40); - - } else { - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); - rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47); - - } - dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state; - } - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "CCKPDStage=%x\n", dm_digtable->cur_cck_pd_state); - -} - -static void rtl8723e_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - if (mac->act_scanning) - return; - - if (mac->link_state >= MAC80211_LINKED) - dm_digtable->cursta_cstate = DIG_STA_CONNECT; - else - dm_digtable->cursta_cstate = DIG_STA_DISCONNECT; - - rtl8723e_dm_initial_gain_sta(hw); - rtl8723e_dm_initial_gain_multi_sta(hw); - rtl8723e_dm_cck_packet_detection_thresh(hw); - - dm_digtable->presta_cstate = dm_digtable->cursta_cstate; - -} - -static void rtl8723e_dm_dig(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - if (!rtlpriv->dm.dm_initialgain_enable) - return; - if (!dm_digtable->dig_enable_flag) - return; - - rtl8723e_dm_ctrl_initgain_by_twoport(hw); - -} - -static void rtl8723e_dm_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - long undec_sm_pwdb; - - if (!rtlpriv->dm.dynamic_txpower_enable) - return; - - if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - - if ((mac->link_state < MAC80211_LINKED) && - (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "Not connected to any\n"); - - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - - rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; - return; - } - - if (mac->link_state >= MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - undec_sm_pwdb = - rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Client PWDB = 0x%lx\n", - undec_sm_pwdb); - } else { - undec_sm_pwdb = - rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "STA Default Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - } else { - undec_sm_pwdb = - rtlpriv->dm.entry_min_undec_sm_pwdb; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "AP Ext Port PWDB = 0x%lx\n", - undec_sm_pwdb); - } - - if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); - } else if ((undec_sm_pwdb < - (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && - (undec_sm_pwdb >= - TX_POWER_NEAR_FIELD_THRESH_LVL1)) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); - } else if (undec_sm_pwdb < - (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "TXHIGHPWRLEVEL_NORMAL\n"); - } - - if (rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "PHY_SetTxPowerLevel8192S() Channel = %d\n", - rtlphy->current_channel); - rtl8723e_phy_set_txpower_level(hw, rtlphy->current_channel); - } - - rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; -} - -void rtl8723e_dm_write_dig(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n", - dm_digtable->cur_igvalue, dm_digtable->pre_igvalue, - dm_digtable->back_val); - - if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) { - rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, - dm_digtable->cur_igvalue); - rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, - dm_digtable->cur_igvalue); - - dm_digtable->pre_igvalue = dm_digtable->cur_igvalue; - } -} - -static void rtl8723e_dm_pwdb_monitor(struct ieee80211_hw *hw) -{ -} - -static void rtl8723e_dm_check_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - static u64 last_txok_cnt; - static u64 last_rxok_cnt; - static u32 last_bt_edca_ul; - static u32 last_bt_edca_dl; - u64 cur_txok_cnt = 0; - u64 cur_rxok_cnt = 0; - u32 edca_be_ul = 0x5ea42b; - u32 edca_be_dl = 0x5ea42b; - bool bt_change_edca = false; - - if ((last_bt_edca_ul != rtlpriv->btcoexist.bt_edca_ul) || - (last_bt_edca_dl != rtlpriv->btcoexist.bt_edca_dl)) { - rtlpriv->dm.current_turbo_edca = false; - last_bt_edca_ul = rtlpriv->btcoexist.bt_edca_ul; - last_bt_edca_dl = rtlpriv->btcoexist.bt_edca_dl; - } - - if (rtlpriv->btcoexist.bt_edca_ul != 0) { - edca_be_ul = rtlpriv->btcoexist.bt_edca_ul; - bt_change_edca = true; - } - - if (rtlpriv->btcoexist.bt_edca_dl != 0) { - edca_be_ul = rtlpriv->btcoexist.bt_edca_dl; - bt_change_edca = true; - } - - if (mac->link_state != MAC80211_LINKED) { - rtlpriv->dm.current_turbo_edca = false; - return; - } - if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) && - (!rtlpriv->dm.disable_framebursting))) { - - cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; - cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; - - if (cur_rxok_cnt > 4 * cur_txok_cnt) { - if (!rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { - rtl_write_dword(rtlpriv, - REG_EDCA_BE_PARAM, - edca_be_dl); - rtlpriv->dm.is_cur_rdlstate = true; - } - } else { - if (rtlpriv->dm.is_cur_rdlstate || - !rtlpriv->dm.current_turbo_edca) { - rtl_write_dword(rtlpriv, - REG_EDCA_BE_PARAM, - edca_be_ul); - rtlpriv->dm.is_cur_rdlstate = false; - } - } - rtlpriv->dm.current_turbo_edca = true; - } else { - if (rtlpriv->dm.current_turbo_edca) { - u8 tmp = AC0_BE; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AC_PARAM, - (u8 *)(&tmp)); - rtlpriv->dm.current_turbo_edca = false; - } - } - - rtlpriv->dm.is_any_nonbepkts = false; - last_txok_cnt = rtlpriv->stats.txbytesunicast; - last_rxok_cnt = rtlpriv->stats.rxbytesunicast; -} - -static void rtl8723e_dm_initialize_txpower_tracking_thermalmeter( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.txpower_tracking = true; - rtlpriv->dm.txpower_trackinginit = false; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pMgntInfo->txpower_tracking = %d\n", - rtlpriv->dm.txpower_tracking); -} - -static void rtl8723e_dm_initialize_txpower_tracking(struct ieee80211_hw *hw) -{ - rtl8723e_dm_initialize_txpower_tracking_thermalmeter(hw); -} - -void rtl8723e_dm_check_txpower_tracking(struct ieee80211_hw *hw) -{ - return; -} - -void rtl8723e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rate_adaptive *p_ra = &(rtlpriv->ra); - - p_ra->ratr_state = DM_RATR_STA_INIT; - p_ra->pre_ratr_state = DM_RATR_STA_INIT; - - if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) - rtlpriv->dm.useramask = true; - else - rtlpriv->dm.useramask = false; - -} - -void rtl8723e_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ps_t *dm_pstable = &rtlpriv->dm_pstable; - static u8 initialize; - static u32 reg_874, reg_c70, reg_85c, reg_a74; - - if (initialize == 0) { - reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, - MASKDWORD) & 0x1CC000) >> 14; - - reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1, - MASKDWORD) & BIT(3)) >> 3; - - reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, - MASKDWORD) & 0xFF000000) >> 24; - - reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12; - - initialize = 1; - } - - if (!bforce_in_normal) { - if (dm_pstable->rssi_val_min != 0) { - if (dm_pstable->pre_rfstate == RF_NORMAL) { - if (dm_pstable->rssi_val_min >= 30) - dm_pstable->cur_rfstate = RF_SAVE; - else - dm_pstable->cur_rfstate = RF_NORMAL; - } else { - if (dm_pstable->rssi_val_min <= 25) - dm_pstable->cur_rfstate = RF_NORMAL; - else - dm_pstable->cur_rfstate = RF_SAVE; - } - } else { - dm_pstable->cur_rfstate = RF_MAX; - } - } else { - dm_pstable->cur_rfstate = RF_NORMAL; - } - - if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) { - if (dm_pstable->cur_rfstate == RF_SAVE) { - rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, - BIT(5), 0x1); - rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, - 0x1C0000, 0x2); - rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0); - rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, - 0xFF000000, 0x63); - rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, - 0xC000, 0x2); - rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3); - rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); - rtl_set_bbreg(hw, 0x818, BIT(28), 0x1); - } else { - rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, - 0x1CC000, reg_874); - rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), - reg_c70); - rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000, - reg_85c); - rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74); - rtl_set_bbreg(hw, 0x818, BIT(28), 0x0); - rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, - BIT(5), 0x0); - } - - dm_pstable->pre_rfstate = dm_pstable->cur_rfstate; - } -} - -static void rtl8723e_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ps_t *dm_pstable = &rtlpriv->dm_pstable; - - if (((mac->link_state == MAC80211_NOLINK)) && - (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { - dm_pstable->rssi_val_min = 0; - RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, - "Not connected to any\n"); - } - - if (mac->link_state == MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - dm_pstable->rssi_val_min = - rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, - "AP Client PWDB = 0x%lx\n", - dm_pstable->rssi_val_min); - } else { - dm_pstable->rssi_val_min = - rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, - "STA Default Port PWDB = 0x%lx\n", - dm_pstable->rssi_val_min); - } - } else { - dm_pstable->rssi_val_min = - rtlpriv->dm.entry_min_undec_sm_pwdb; - - RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, - "AP Ext Port PWDB = 0x%lx\n", - dm_pstable->rssi_val_min); - } - - rtl8723e_dm_rf_saving(hw, false); -} - -void rtl8723e_dm_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; - rtl_dm_diginit(hw, 0x20); - rtl8723_dm_init_dynamic_txpower(hw); - rtl8723_dm_init_edca_turbo(hw); - rtl8723e_dm_init_rate_adaptive_mask(hw); - rtl8723e_dm_initialize_txpower_tracking(hw); - rtl8723_dm_init_dynamic_bb_powersaving(hw); -} - -void rtl8723e_dm_watchdog(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool fw_current_inpsmode = false; - bool fw_ps_awake = true; - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inpsmode)); - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, - (u8 *)(&fw_ps_awake)); - - if (ppsc->p2p_ps_info.p2p_ps_mode) - fw_ps_awake = false; - - if ((ppsc->rfpwr_state == ERFON) && - ((!fw_current_inpsmode) && fw_ps_awake) && - (!ppsc->rfchange_inprogress)) { - rtl8723e_dm_pwdb_monitor(hw); - rtl8723e_dm_dig(hw); - rtl8723e_dm_false_alarm_counter_statistics(hw); - rtl8723e_dm_dynamic_bb_powersaving(hw); - rtl8723e_dm_dynamic_txpower(hw); - rtl8723e_dm_check_txpower_tracking(hw); - /* rtl92c_dm_refresh_rate_adaptive_mask(hw); */ - rtl8723e_dm_bt_coexist(hw); - rtl8723e_dm_check_edca_turbo(hw); - } - if (rtlpriv->btcoexist.init_set) - rtl_write_byte(rtlpriv, 0x76e, 0xc); -} - -static void rtl8723e_dm_init_bt_coexist(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->btcoexist.bt_rfreg_origin_1e - = rtl_get_rfreg(hw, (enum radio_path)0, RF_RCK1, 0xfffff); - rtlpriv->btcoexist.bt_rfreg_origin_1f - = rtl_get_rfreg(hw, (enum radio_path)0, RF_RCK2, 0xf0); - - rtlpriv->btcoexist.cstate = 0; - rtlpriv->btcoexist.previous_state = 0; - rtlpriv->btcoexist.cstate_h = 0; - rtlpriv->btcoexist.previous_state_h = 0; - rtlpriv->btcoexist.lps_counter = 0; - - /* Enable counter statistics */ - rtl_write_byte(rtlpriv, 0x76e, 0x4); - rtl_write_byte(rtlpriv, 0x778, 0x3); - rtl_write_byte(rtlpriv, 0x40, 0x20); - - rtlpriv->btcoexist.init_set = true; -} - -void rtl8723e_dm_bt_coexist(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp_byte = 0; - if (!rtlpriv->btcoexist.bt_coexistence) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, - "[DM]{BT], BT not exist!!\n"); - return; - } - - if (!rtlpriv->btcoexist.init_set) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, - "[DM][BT], rtl8723e_dm_bt_coexist()\n"); - rtl8723e_dm_init_bt_coexist(hw); - } - - tmp_byte = rtl_read_byte(rtlpriv, 0x40); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, - "[DM][BT], 0x40 is 0x%x", tmp_byte); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[DM][BT], bt_dm_coexist start"); - rtl8723e_dm_bt_coexist_8723(hw); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h b/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h deleted file mode 100644 index 57111052e86b..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/dm.h +++ /dev/null @@ -1,136 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_DM_H__ -#define __RTL8723E_DM_H__ - -#define HAL_DM_DIG_DISABLE BIT(0) -#define HAL_DM_HIPWR_DISABLE BIT(1) - -#define OFDM_TABLE_LENGTH 37 -#define CCK_TABLE_LENGTH 33 - -#define OFDM_TABLE_SIZE 37 -#define CCK_TABLE_SIZE 33 - -#define BW_AUTO_SWITCH_HIGH_LOW 25 -#define BW_AUTO_SWITCH_LOW_HIGH 30 - -#define DM_DIG_FA_UPPER 0x32 -#define DM_DIG_FA_LOWER 0x20 -#define DM_DIG_FA_TH0 0x20 -#define DM_DIG_FA_TH1 0x100 -#define DM_DIG_FA_TH2 0x200 - -#define RXPATHSELECTION_SS_TH_LOW 30 -#define RXPATHSELECTION_DIFF_TH 18 - -#define DM_RATR_STA_INIT 0 -#define DM_RATR_STA_HIGH 1 -#define DM_RATR_STA_MIDDLE 2 -#define DM_RATR_STA_LOW 3 - -#define CTS2SELF_THVAL 30 -#define REGC38_TH 20 - -#define WAIOTTHVAL 25 - -#define TXHIGHPWRLEVEL_NORMAL 0 -#define TXHIGHPWRLEVEL_LEVEL1 1 -#define TXHIGHPWRLEVEL_LEVEL2 2 -#define TXHIGHPWRLEVEL_BT1 3 -#define TXHIGHPWRLEVEL_BT2 4 - -#define DM_TYPE_BYFW 0 -#define DM_TYPE_BYDRIVER 1 - -#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 -#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 - -struct swat_t { - u8 failure_cnt; - u8 try_flag; - u8 stop_trying; - long pre_rssi; - long trying_threshold; - u8 cur_antenna; - u8 pre_antenna; - -}; - -enum tag_dynamic_init_gain_operation_type_definition { - DIG_TYPE_THRESH_HIGH = 0, - DIG_TYPE_THRESH_LOW = 1, - DIG_TYPE_BACKOFF = 2, - DIG_TYPE_RX_GAIN_MIN = 3, - DIG_TYPE_RX_GAIN_MAX = 4, - DIG_TYPE_ENABLE = 5, - DIG_TYPE_DISABLE = 6, - DIG_OP_TYPE_MAX -}; - -enum dm_1r_cca_e { - CCA_1R = 0, - CCA_2R = 1, - CCA_MAX = 2, -}; - -enum dm_rf_e { - RF_SAVE = 0, - RF_NORMAL = 1, - RF_MAX = 2, -}; - -enum dm_sw_ant_switch_e { - ANS_ANTENNA_B = 1, - ANS_ANTENNA_A = 2, - ANS_ANTENNA_MAX = 3, -}; - -#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1) -#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1) -#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1) -#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1) -#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1) -#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ - ( \ - (((struct rtl_priv *)(_priv))->mac80211.opmode == \ - NL80211_IFTYPE_ADHOC) ? \ - (((struct rtl_priv *)(_priv))->dm.entry_min_undec_sm_pwdb) : \ - (((struct rtl_priv *)(_priv))->dm.undec_sm_pwdb) \ - ) - -void rtl8723e_dm_init(struct ieee80211_hw *hw); -void rtl8723e_dm_watchdog(struct ieee80211_hw *hw); -void rtl8723e_dm_write_dig(struct ieee80211_hw *hw); -void rtl8723e_dm_check_txpower_tracking(struct ieee80211_hw *hw); -void rtl8723e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); -void rtl8723e_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal); -void rtl8723e_dm_bt_coexist(struct ieee80211_hw *hw); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c deleted file mode 100644 index b7c0d38ee5b5..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c +++ /dev/null @@ -1,603 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "fw.h" -#include "../rtl8723com/fw_common.h" - -static bool _rtl8723e_check_fw_read_last_h2c(struct ieee80211_hw *hw, - u8 boxnum) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 val_hmetfr, val_mcutst_1; - bool result = false; - - val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); - val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum)); - - if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0) - result = true; - return result; -} - -static void _rtl8723e_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *cmdbuffer) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 boxnum; - u16 box_reg = 0, box_extreg = 0; - u8 u1b_tmp; - bool isfw_read = false; - u8 buf_index = 0; - bool bwrite_sucess = false; - u8 wait_h2c_limmit = 100; - u8 wait_writeh2c_limmit = 100; - u8 boxcontent[4], boxextcontent[2]; - u32 h2c_waitcounter = 0; - unsigned long flag; - u8 idx; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); - - while (true) { - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - if (rtlhal->h2c_setinprogress) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C set in progress! Wait to set..element_id(%d).\n", - element_id); - - while (rtlhal->h2c_setinprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, - flag); - h2c_waitcounter++; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Wait 100 us (%d times)...\n", - h2c_waitcounter); - udelay(100); - - if (h2c_waitcounter > 1000) - return; - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, - flag); - } - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - } else { - rtlhal->h2c_setinprogress = true; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - break; - } - } - - while (!bwrite_sucess) { - wait_writeh2c_limmit--; - if (wait_writeh2c_limmit == 0) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Write H2C fail because no trigger for FW INT!\n"); - break; - } - - boxnum = rtlhal->last_hmeboxnum; - switch (boxnum) { - case 0: - box_reg = REG_HMEBOX_0; - box_extreg = REG_HMEBOX_EXT_0; - break; - case 1: - box_reg = REG_HMEBOX_1; - box_extreg = REG_HMEBOX_EXT_1; - break; - case 2: - box_reg = REG_HMEBOX_2; - box_extreg = REG_HMEBOX_EXT_2; - break; - case 3: - box_reg = REG_HMEBOX_3; - box_extreg = REG_HMEBOX_EXT_3; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - - isfw_read = _rtl8723e_check_fw_read_last_h2c(hw, boxnum); - while (!isfw_read) { - - wait_h2c_limmit--; - if (wait_h2c_limmit == 0) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Wating too long for FW read clear HMEBox(%d)!\n", - boxnum); - break; - } - - udelay(10); - - isfw_read = _rtl8723e_check_fw_read_last_h2c(hw, - boxnum); - u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF); - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n", - boxnum, u1b_tmp); - } - - if (!isfw_read) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", - boxnum); - break; - } - - memset(boxcontent, 0, sizeof(boxcontent)); - memset(boxextcontent, 0, sizeof(boxextcontent)); - boxcontent[0] = element_id; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Write element_id box_reg(%4x) = %2x\n", - box_reg, element_id); - - switch (cmd_len) { - case 1: - boxcontent[0] &= ~(BIT(7)); - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index, 1); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - case 2: - boxcontent[0] &= ~(BIT(7)); - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index, 2); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - case 3: - boxcontent[0] &= ~(BIT(7)); - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index, 3); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - case 4: - boxcontent[0] |= (BIT(7)); - memcpy((u8 *)(boxextcontent), - cmdbuffer + buf_index, 2); - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index + 2, 2); - - for (idx = 0; idx < 2; idx++) { - rtl_write_byte(rtlpriv, box_extreg + idx, - boxextcontent[idx]); - } - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - case 5: - boxcontent[0] |= (BIT(7)); - memcpy((u8 *)(boxextcontent), - cmdbuffer + buf_index, 2); - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index + 2, 3); - - for (idx = 0; idx < 2; idx++) { - rtl_write_byte(rtlpriv, box_extreg + idx, - boxextcontent[idx]); - } - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - - bwrite_sucess = true; - - rtlhal->last_hmeboxnum = boxnum + 1; - if (rtlhal->last_hmeboxnum == 4) - rtlhal->last_hmeboxnum = 0; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "pHalData->last_hmeboxnum = %d\n", - rtlhal->last_hmeboxnum); - } - - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - rtlhal->h2c_setinprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); -} - -void rtl8723e_fill_h2c_cmd(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, u8 *cmdbuffer) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 tmp_cmdbuf[2]; - - if (!rtlhal->fw_ready) { - RT_ASSERT(false, - "return H2C cmd because of Fw download fail!!!\n"); - return; - } - memset(tmp_cmdbuf, 0, 8); - memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); - _rtl8723e_fill_h2c_command(hw, element_id, cmd_len, - (u8 *)&tmp_cmdbuf); -} - -void rtl8723e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 u1_h2c_set_pwrmode[3] = { 0 }; - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); - - SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); - SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, - (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1); - SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, - ppsc->reg_max_lps_awakeintvl); - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "rtl8723e_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n", - u1_h2c_set_pwrmode, 3); - rtl8723e_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode); -} - -#define BEACON_PG 0 /* ->1 */ -#define PSPOLL_PG 2 -#define NULL_PG 3 -#define PROBERSP_PG 4 /* ->5 */ - -#define TOTAL_RESERVED_PKT_LEN 768 - -static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { - /* page 0 beacon */ - 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, - 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, - 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, - 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, - 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, - 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, - 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 1 beacon */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 2 ps-poll */ - 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 3 null */ - 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 4 probe_resp */ - 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, - 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, - 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, - 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, - 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, - 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, - 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, - 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, - 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 5 probe_resp */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct sk_buff *skb = NULL; - u32 totalpacketlen; - bool rtstatus; - u8 u1rsvdpageloc[3] = { 0 }; - bool b_dlok = false; - u8 *beacon; - u8 *p_pspoll; - u8 *nullfunc; - u8 *p_probersp; - - /*--------------------------------------------------------- - * (1) beacon - *--------------------------------------------------------- - */ - beacon = &reserved_page_packet[BEACON_PG * 128]; - SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); - SET_80211_HDR_ADDRESS3(beacon, mac->bssid); - - /*------------------------------------------------------- - * (2) ps-poll - *-------------------------------------------------------- - */ - p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; - SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); - SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); - SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); - - SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); - - /*-------------------------------------------------------- - * (3) null data - *--------------------------------------------------------- - */ - nullfunc = &reserved_page_packet[NULL_PG * 128]; - SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); - SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); - SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); - - /*--------------------------------------------------------- - * (4) probe response - *---------------------------------------------------------- - */ - p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; - SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); - SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); - SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); - - totalpacketlen = TOTAL_RESERVED_PKT_LEN; - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", - &reserved_page_packet[0], totalpacketlen); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "rtl8723e_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", - u1rsvdpageloc, 3); - - skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); - - rtstatus = rtl_cmd_send_packet(hw, skb); - - if (rtstatus) - b_dlok = true; - - if (b_dlok) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Set RSVD page location to Fw.\n"); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "H2C_RSVDPAGE:\n", - u1rsvdpageloc, 3); - rtl8723e_fill_h2c_cmd(hw, H2C_RSVDPAGE, - sizeof(u1rsvdpageloc), u1rsvdpageloc); - } else - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set RSVD page location to Fw FAIL!!!!!!.\n"); -} - -void rtl8723e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) -{ - u8 u1_joinbssrpt_parm[1] = { 0 }; - - SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); - - rtl8723e_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); -} - -static void rtl8723e_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, - u8 ctwindow) -{ - u8 u1_ctwindow_period[1] = { ctwindow}; - - rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period); - -} - -void rtl8723e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); - struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; - u8 i; - u16 ctwindow; - u32 start_time, tsf_low; - - switch (p2p_ps_state) { - case P2P_PS_DISABLE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); - memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); - break; - case P2P_PS_ENABLE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); - /* update CTWindow value. */ - if (p2pinfo->ctwindow > 0) { - p2p_ps_offload->ctwindow_en = 1; - ctwindow = p2pinfo->ctwindow; - rtl8723e_set_p2p_ctw_period_cmd(hw, ctwindow); - } - - /* hw only support 2 set of NoA */ - for (i = 0 ; i < p2pinfo->noa_num ; i++) { - /* To control the register setting for which NOA*/ - rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); - if (i == 0) - p2p_ps_offload->noa0_en = 1; - else - p2p_ps_offload->noa1_en = 1; - - /* config P2P NoA Descriptor Register */ - rtl_write_dword(rtlpriv, 0x5E0, - p2pinfo->noa_duration[i]); - rtl_write_dword(rtlpriv, 0x5E4, - p2pinfo->noa_interval[i]); - - /*Get Current TSF value */ - tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - - start_time = p2pinfo->noa_start_time[i]; - if (p2pinfo->noa_count_type[i] != 1) { - while (start_time <= - (tsf_low+(50*1024))) { - start_time += - p2pinfo->noa_interval[i]; - if (p2pinfo->noa_count_type[i] != 255) - p2pinfo->noa_count_type[i]--; - } - } - rtl_write_dword(rtlpriv, 0x5E8, start_time); - rtl_write_dword(rtlpriv, 0x5EC, - p2pinfo->noa_count_type[i]); - - } - - if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { - /* rst p2p circuit */ - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); - - p2p_ps_offload->offload_en = 1; - - if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { - p2p_ps_offload->role = 1; - p2p_ps_offload->allstasleep = 0; - } else { - p2p_ps_offload->role = 0; - } - - p2p_ps_offload->discovery = 0; - } - break; - case P2P_PS_SCAN: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); - p2p_ps_offload->discovery = 1; - break; - case P2P_PS_SCAN_DONE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); - p2p_ps_offload->discovery = 0; - p2pinfo->p2p_ps_state = P2P_PS_ENABLE; - break; - default: - break; - } - - rtl8723e_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload); - -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h deleted file mode 100644 index 9d1fe25db953..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/fw.h +++ /dev/null @@ -1,66 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C__FW__H__ -#define __RTL92C__FW__H__ - -#define FW_8192C_SIZE 0x3000 -#define FW_8192C_START_ADDRESS 0x1000 -#define FW_8192C_END_ADDRESS 0x3FFF -#define FW_8192C_PAGE_SIZE 4096 -#define FW_8192C_POLLING_DELAY 5 - -#define IS_FW_HEADER_EXIST(_pfwhdr) \ - ((_pfwhdr->signature&0xFFFF) == 0x2300 ||\ - (_pfwhdr->signature&0xFFFF) == 0x2301 ||\ - (_pfwhdr->signature&0xFFFF) == 0x2302) - -#define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) - -#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) -#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) - -void rtl8723e_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *p_cmdbuffer); -void rtl8723e_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); -void rtl8723e_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); -void rtl8723e_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); -void rtl8723e_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c deleted file mode 100644 index 5aac45d5a974..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c +++ /dev/null @@ -1,537 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "hal_bt_coexist.h" -#include "../pci.h" -#include "dm.h" -#include "fw.h" -#include "phy.h" -#include "reg.h" -#include "hal_btc.h" - -static bool bt_operation_on; - -void rtl8723e_dm_bt_reject_ap_aggregated_packet(struct ieee80211_hw *hw, - bool b_reject) -{ -} - -void _rtl8723_dm_bt_check_wifi_state(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - if (rtlpriv->link_info.busytraffic) { - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_IDLE; - - if (rtlpriv->link_info.tx_busy_traffic) - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_WIFI_UPLINK; - else - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_UPLINK; - - if (rtlpriv->link_info.rx_busy_traffic) - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_WIFI_DOWNLINK; - else - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_DOWNLINK; - } else { - rtlpriv->btcoexist.cstate |= BT_COEX_STATE_WIFI_IDLE; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_UPLINK; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_DOWNLINK; - } - - if (rtlpriv->mac80211.mode == WIRELESS_MODE_G || - rtlpriv->mac80211.mode == WIRELESS_MODE_B) { - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_WIFI_LEGACY; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_HT20; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_HT40; - } else { - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_LEGACY; - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_WIFI_HT40; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_HT20; - } else { - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_WIFI_HT20; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_HT40; - } - } - - if (bt_operation_on) - rtlpriv->btcoexist.cstate |= BT_COEX_STATE_BT30; - else - rtlpriv->btcoexist.cstate &= ~BT_COEX_STATE_BT30; -} - -u8 rtl8723e_dm_bt_check_coex_rssi_state1(struct ieee80211_hw *hw, - u8 level_num, u8 rssi_thresh, - u8 rssi_thresh1) - -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - long undecoratedsmoothed_pwdb; - u8 bt_rssi_state = 0; - - undecoratedsmoothed_pwdb = rtl8723e_dm_bt_get_rx_ss(hw); - - if (level_num == 2) { - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - - if ((rtlpriv->btcoexist.bt_pre_rssi_state == - BT_RSSI_STATE_LOW) || - (rtlpriv->btcoexist.bt_pre_rssi_state == - BT_RSSI_STATE_STAY_LOW)) { - if (undecoratedsmoothed_pwdb >= - (rssi_thresh + BT_FW_COEX_THRESH_TOL)) { - bt_rssi_state = BT_RSSI_STATE_HIGH; - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_WIFI_RSSI_1_HIGH; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_RSSI_1_LOW; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI_1 state switch to High\n"); - } else { - bt_rssi_state = BT_RSSI_STATE_STAY_LOW; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI_1 state stay at Low\n"); - } - } else { - if (undecoratedsmoothed_pwdb < rssi_thresh) { - bt_rssi_state = BT_RSSI_STATE_LOW; - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_WIFI_RSSI_1_LOW; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI_1 state switch to Low\n"); - } else { - bt_rssi_state = BT_RSSI_STATE_STAY_HIGH; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI_1 state stay at High\n"); - } - } - } else if (level_num == 3) { - if (rssi_thresh > rssi_thresh1) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI_1 thresh error!!\n"); - return rtlpriv->btcoexist.bt_pre_rssi_state; - } - - if ((rtlpriv->btcoexist.bt_pre_rssi_state == - BT_RSSI_STATE_LOW) || - (rtlpriv->btcoexist.bt_pre_rssi_state == - BT_RSSI_STATE_STAY_LOW)) { - if (undecoratedsmoothed_pwdb >= - (rssi_thresh+BT_FW_COEX_THRESH_TOL)) { - bt_rssi_state = BT_RSSI_STATE_MEDIUM; - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_RSSI_1_LOW; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI_1 state switch to Medium\n"); - } else { - bt_rssi_state = BT_RSSI_STATE_STAY_LOW; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI_1 state stay at Low\n"); - } - } else if ((rtlpriv->btcoexist.bt_pre_rssi_state == - BT_RSSI_STATE_MEDIUM) || - (rtlpriv->btcoexist.bt_pre_rssi_state == - BT_RSSI_STATE_STAY_MEDIUM)) { - if (undecoratedsmoothed_pwdb >= - (rssi_thresh1 + BT_FW_COEX_THRESH_TOL)) { - bt_rssi_state = BT_RSSI_STATE_HIGH; - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_WIFI_RSSI_1_HIGH; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_RSSI_1_LOW; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI_1 state switch to High\n"); - } else if (undecoratedsmoothed_pwdb < rssi_thresh) { - bt_rssi_state = BT_RSSI_STATE_LOW; - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_WIFI_RSSI_1_LOW; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI_1 state switch to Low\n"); - } else { - bt_rssi_state = BT_RSSI_STATE_STAY_MEDIUM; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI_1 state stay at Medium\n"); - } - } else { - if (undecoratedsmoothed_pwdb < rssi_thresh1) { - bt_rssi_state = BT_RSSI_STATE_MEDIUM; - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_WIFI_RSSI_1_MEDIUM; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_RSSI_1_HIGH; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_RSSI_1_LOW; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI_1 state switch to Medium\n"); - } else { - bt_rssi_state = BT_RSSI_STATE_STAY_HIGH; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI_1 state stay at High\n"); - } - } - } - rtlpriv->btcoexist.bt_pre_rssi_state1 = bt_rssi_state; - - return bt_rssi_state; -} - -u8 rtl8723e_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw, - u8 level_num, - u8 rssi_thresh, - u8 rssi_thresh1) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - long undecoratedsmoothed_pwdb = 0; - u8 bt_rssi_state = 0; - - undecoratedsmoothed_pwdb = rtl8723e_dm_bt_get_rx_ss(hw); - - if (level_num == 2) { - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_WIFI_RSSI_MEDIUM; - - if ((rtlpriv->btcoexist.bt_pre_rssi_state == - BT_RSSI_STATE_LOW) || - (rtlpriv->btcoexist.bt_pre_rssi_state == - BT_RSSI_STATE_STAY_LOW)) { - if (undecoratedsmoothed_pwdb >= - (rssi_thresh + BT_FW_COEX_THRESH_TOL)) { - bt_rssi_state = BT_RSSI_STATE_HIGH; - rtlpriv->btcoexist.cstate - |= BT_COEX_STATE_WIFI_RSSI_HIGH; - rtlpriv->btcoexist.cstate - &= ~BT_COEX_STATE_WIFI_RSSI_LOW; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI state switch to High\n"); - } else { - bt_rssi_state = BT_RSSI_STATE_STAY_LOW; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI state stay at Low\n"); - } - } else { - if (undecoratedsmoothed_pwdb < rssi_thresh) { - bt_rssi_state = BT_RSSI_STATE_LOW; - rtlpriv->btcoexist.cstate - |= BT_COEX_STATE_WIFI_RSSI_LOW; - rtlpriv->btcoexist.cstate - &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI state switch to Low\n"); - } else { - bt_rssi_state = BT_RSSI_STATE_STAY_HIGH; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI state stay at High\n"); - } - } - } else if (level_num == 3) { - if (rssi_thresh > rssi_thresh1) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI thresh error!!\n"); - return rtlpriv->btcoexist.bt_pre_rssi_state; - } - if ((rtlpriv->btcoexist.bt_pre_rssi_state == - BT_RSSI_STATE_LOW) || - (rtlpriv->btcoexist.bt_pre_rssi_state == - BT_RSSI_STATE_STAY_LOW)) { - if (undecoratedsmoothed_pwdb >= - (rssi_thresh + BT_FW_COEX_THRESH_TOL)) { - bt_rssi_state = BT_RSSI_STATE_MEDIUM; - rtlpriv->btcoexist.cstate - |= BT_COEX_STATE_WIFI_RSSI_MEDIUM; - rtlpriv->btcoexist.cstate - &= ~BT_COEX_STATE_WIFI_RSSI_LOW; - rtlpriv->btcoexist.cstate - &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI state switch to Medium\n"); - } else { - bt_rssi_state = BT_RSSI_STATE_STAY_LOW; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI state stay at Low\n"); - } - } else if ((rtlpriv->btcoexist.bt_pre_rssi_state == - BT_RSSI_STATE_MEDIUM) || - (rtlpriv->btcoexist.bt_pre_rssi_state == - BT_RSSI_STATE_STAY_MEDIUM)) { - if (undecoratedsmoothed_pwdb >= - (rssi_thresh1 + BT_FW_COEX_THRESH_TOL)) { - bt_rssi_state = BT_RSSI_STATE_HIGH; - rtlpriv->btcoexist.cstate - |= BT_COEX_STATE_WIFI_RSSI_HIGH; - rtlpriv->btcoexist.cstate - &= ~BT_COEX_STATE_WIFI_RSSI_LOW; - rtlpriv->btcoexist.cstate - &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI state switch to High\n"); - } else if (undecoratedsmoothed_pwdb < rssi_thresh) { - bt_rssi_state = BT_RSSI_STATE_LOW; - rtlpriv->btcoexist.cstate - |= BT_COEX_STATE_WIFI_RSSI_LOW; - rtlpriv->btcoexist.cstate - &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; - rtlpriv->btcoexist.cstate - &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI state switch to Low\n"); - } else { - bt_rssi_state = BT_RSSI_STATE_STAY_MEDIUM; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI state stay at Medium\n"); - } - } else { - if (undecoratedsmoothed_pwdb < rssi_thresh1) { - bt_rssi_state = BT_RSSI_STATE_MEDIUM; - rtlpriv->btcoexist.cstate - |= BT_COEX_STATE_WIFI_RSSI_MEDIUM; - rtlpriv->btcoexist.cstate - &= ~BT_COEX_STATE_WIFI_RSSI_HIGH; - rtlpriv->btcoexist.cstate - &= ~BT_COEX_STATE_WIFI_RSSI_LOW; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI state switch to Medium\n"); - } else { - bt_rssi_state = BT_RSSI_STATE_STAY_HIGH; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], RSSI state stay at High\n"); - } - } - } - rtlpriv->btcoexist.bt_pre_rssi_state = bt_rssi_state; - return bt_rssi_state; -} - -long rtl8723e_dm_bt_get_rx_ss(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - long undecoratedsmoothed_pwdb = 0; - - if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) { - undecoratedsmoothed_pwdb = - GET_UNDECORATED_AVERAGE_RSSI(rtlpriv); - } else { - undecoratedsmoothed_pwdb - = rtlpriv->dm.entry_min_undec_sm_pwdb; - } - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "rtl8723e_dm_bt_get_rx_ss() = %ld\n", - undecoratedsmoothed_pwdb); - - return undecoratedsmoothed_pwdb; -} - -void rtl8723e_dm_bt_balance(struct ieee80211_hw *hw, - bool balance_on, u8 ms0, u8 ms1) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 h2c_parameter[3] = {0}; - - if (balance_on) { - h2c_parameter[2] = 1; - h2c_parameter[1] = ms1; - h2c_parameter[0] = ms0; - rtlpriv->btcoexist.fw_coexist_all_off = false; - } else { - h2c_parameter[2] = 0; - h2c_parameter[1] = 0; - h2c_parameter[0] = 0; - } - rtlpriv->btcoexist.balance_on = balance_on; - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[DM][BT], Balance=[%s:%dms:%dms], write 0xc=0x%x\n", - balance_on ? "ON" : "OFF", ms0, ms1, h2c_parameter[0]<<16 | - h2c_parameter[1]<<8 | h2c_parameter[2]); - - rtl8723e_fill_h2c_cmd(hw, 0xc, 3, h2c_parameter); -} - - -void rtl8723e_dm_bt_agc_table(struct ieee80211_hw *hw, u8 type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (type == BT_AGCTABLE_OFF) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BT]AGCTable Off!\n"); - rtl_write_dword(rtlpriv, 0xc78, 0x641c0001); - rtl_write_dword(rtlpriv, 0xc78, 0x631d0001); - rtl_write_dword(rtlpriv, 0xc78, 0x621e0001); - rtl_write_dword(rtlpriv, 0xc78, 0x611f0001); - rtl_write_dword(rtlpriv, 0xc78, 0x60200001); - - rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, - RF_RX_AGC_HP, 0xfffff, 0x32000); - rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, - RF_RX_AGC_HP, 0xfffff, 0x71000); - rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, - RF_RX_AGC_HP, 0xfffff, 0xb0000); - rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, - RF_RX_AGC_HP, 0xfffff, 0xfc000); - rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, - RF_RX_G1, 0xfffff, 0x30355); - } else if (type == BT_AGCTABLE_ON) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BT]AGCTable On!\n"); - rtl_write_dword(rtlpriv, 0xc78, 0x4e1c0001); - rtl_write_dword(rtlpriv, 0xc78, 0x4d1d0001); - rtl_write_dword(rtlpriv, 0xc78, 0x4c1e0001); - rtl_write_dword(rtlpriv, 0xc78, 0x4b1f0001); - rtl_write_dword(rtlpriv, 0xc78, 0x4a200001); - - rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, - RF_RX_AGC_HP, 0xfffff, 0xdc000); - rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, - RF_RX_AGC_HP, 0xfffff, 0x90000); - rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, - RF_RX_AGC_HP, 0xfffff, 0x51000); - rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, - RF_RX_AGC_HP, 0xfffff, 0x12000); - rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, - RF_RX_G1, 0xfffff, 0x00355); - - rtlpriv->btcoexist.sw_coexist_all_off = false; - } -} - -void rtl8723e_dm_bt_bb_back_off_level(struct ieee80211_hw *hw, u8 type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (type == BT_BB_BACKOFF_OFF) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BT]BBBackOffLevel Off!\n"); - rtl_write_dword(rtlpriv, 0xc04, 0x3a05611); - } else if (type == BT_BB_BACKOFF_ON) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BT]BBBackOffLevel On!\n"); - rtl_write_dword(rtlpriv, 0xc04, 0x3a07611); - rtlpriv->btcoexist.sw_coexist_all_off = false; - } -} - -void rtl8723e_dm_bt_fw_coex_all_off(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "rtl8723e_dm_bt_fw_coex_all_off()\n"); - - if (rtlpriv->btcoexist.fw_coexist_all_off) - return; - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "rtl8723e_dm_bt_fw_coex_all_off(), real Do\n"); - rtl8723e_dm_bt_fw_coex_all_off_8723a(hw); - rtlpriv->btcoexist.fw_coexist_all_off = true; -} - -void rtl8723e_dm_bt_sw_coex_all_off(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "rtl8723e_dm_bt_sw_coex_all_off()\n"); - - if (rtlpriv->btcoexist.sw_coexist_all_off) - return; - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "rtl8723e_dm_bt_sw_coex_all_off(), real Do\n"); - rtl8723e_dm_bt_sw_coex_all_off_8723a(hw); - rtlpriv->btcoexist.sw_coexist_all_off = true; -} - -void rtl8723e_dm_bt_hw_coex_all_off(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "rtl8723e_dm_bt_hw_coex_all_off()\n"); - - if (rtlpriv->btcoexist.hw_coexist_all_off) - return; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "rtl8723e_dm_bt_hw_coex_all_off(), real Do\n"); - - rtl8723e_dm_bt_hw_coex_all_off_8723a(hw); - - rtlpriv->btcoexist.hw_coexist_all_off = true; -} - -void rtl8723e_btdm_coex_all_off(struct ieee80211_hw *hw) -{ - rtl8723e_dm_bt_fw_coex_all_off(hw); - rtl8723e_dm_bt_sw_coex_all_off(hw); - rtl8723e_dm_bt_hw_coex_all_off(hw); -} - -bool rtl8723e_dm_bt_is_coexist_state_changed(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if ((rtlpriv->btcoexist.previous_state == rtlpriv->btcoexist.cstate) && - (rtlpriv->btcoexist.previous_state_h == - rtlpriv->btcoexist.cstate_h)) - return false; - return true; -} - -bool rtl8723e_dm_bt_is_wifi_up_link(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->link_info.tx_busy_traffic) - return true; - return false; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h deleted file mode 100644 index bcd64a22acc0..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h +++ /dev/null @@ -1,158 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_HAL_BT_COEXIST_H__ -#define __RTL8723E_HAL_BT_COEXIST_H__ - -#include "../wifi.h" - -/* The reg define is for 8723 */ -#define REG_HIGH_PRIORITY_TXRX 0x770 -#define REG_LOW_PRIORITY_TXRX 0x774 - -#define BT_FW_COEX_THRESH_TOL 6 -#define BT_FW_COEX_THRESH_20 20 -#define BT_FW_COEX_THRESH_23 23 -#define BT_FW_COEX_THRESH_25 25 -#define BT_FW_COEX_THRESH_30 30 -#define BT_FW_COEX_THRESH_35 35 -#define BT_FW_COEX_THRESH_40 40 -#define BT_FW_COEX_THRESH_45 45 -#define BT_FW_COEX_THRESH_47 47 -#define BT_FW_COEX_THRESH_50 50 -#define BT_FW_COEX_THRESH_55 55 - -#define BT_COEX_STATE_BT30 BIT(0) -#define BT_COEX_STATE_WIFI_HT20 BIT(1) -#define BT_COEX_STATE_WIFI_HT40 BIT(2) -#define BT_COEX_STATE_WIFI_LEGACY BIT(3) - -#define BT_COEX_STATE_WIFI_RSSI_LOW BIT(4) -#define BT_COEX_STATE_WIFI_RSSI_MEDIUM BIT(5) -#define BT_COEX_STATE_WIFI_RSSI_HIGH BIT(6) -#define BT_COEX_STATE_DEC_BT_POWER BIT(7) - -#define BT_COEX_STATE_WIFI_IDLE BIT(8) -#define BT_COEX_STATE_WIFI_UPLINK BIT(9) -#define BT_COEX_STATE_WIFI_DOWNLINK BIT(10) - -#define BT_COEX_STATE_BT_INQ_PAGE BIT(11) -#define BT_COEX_STATE_BT_IDLE BIT(12) -#define BT_COEX_STATE_BT_UPLINK BIT(13) -#define BT_COEX_STATE_BT_DOWNLINK BIT(14) - -#define BT_COEX_STATE_HOLD_FOR_BT_OPERATION BIT(15) -#define BT_COEX_STATE_BT_RSSI_LOW BIT(19) - -#define BT_COEX_STATE_PROFILE_HID BIT(20) -#define BT_COEX_STATE_PROFILE_A2DP BIT(21) -#define BT_COEX_STATE_PROFILE_PAN BIT(22) -#define BT_COEX_STATE_PROFILE_SCO BIT(23) - -#define BT_COEX_STATE_WIFI_RSSI_1_LOW BIT(24) -#define BT_COEX_STATE_WIFI_RSSI_1_MEDIUM BIT(25) -#define BT_COEX_STATE_WIFI_RSSI_1_HIGH BIT(26) - -#define BT_COEX_STATE_BTINFO_COMMON BIT(30) -#define BT_COEX_STATE_BTINFO_B_HID_SCOESCO BIT(31) -#define BT_COEX_STATE_BTINFO_B_FTP_A2DP BIT(29) - -#define BT_COEX_STATE_BT_CNT_LEVEL_0 BIT(0) -#define BT_COEX_STATE_BT_CNT_LEVEL_1 BIT(1) -#define BT_COEX_STATE_BT_CNT_LEVEL_2 BIT(2) -#define BT_COEX_STATE_BT_CNT_LEVEL_3 BIT(3) - -#define BT_RSSI_STATE_HIGH 0 -#define BT_RSSI_STATE_MEDIUM 1 -#define BT_RSSI_STATE_LOW 2 -#define BT_RSSI_STATE_STAY_HIGH 3 -#define BT_RSSI_STATE_STAY_MEDIUM 4 -#define BT_RSSI_STATE_STAY_LOW 5 - -#define BT_AGCTABLE_OFF 0 -#define BT_AGCTABLE_ON 1 -#define BT_BB_BACKOFF_OFF 0 -#define BT_BB_BACKOFF_ON 1 -#define BT_FW_NAV_OFF 0 -#define BT_FW_NAV_ON 1 - -#define BT_COEX_MECH_NONE 0 -#define BT_COEX_MECH_SCO 1 -#define BT_COEX_MECH_HID 2 -#define BT_COEX_MECH_A2DP 3 -#define BT_COEX_MECH_PAN 4 -#define BT_COEX_MECH_HID_A2DP 5 -#define BT_COEX_MECH_HID_PAN 6 -#define BT_COEX_MECH_PAN_A2DP 7 -#define BT_COEX_MECH_HID_SCO_ESCO 8 -#define BT_COEX_MECH_FTP_A2DP 9 -#define BT_COEX_MECH_COMMON 10 -#define BT_COEX_MECH_MAX 11 - -#define BT_DBG_PROFILE_NONE 0 -#define BT_DBG_PROFILE_SCO 1 -#define BT_DBG_PROFILE_HID 2 -#define BT_DBG_PROFILE_A2DP 3 -#define BT_DBG_PROFILE_PAN 4 -#define BT_DBG_PROFILE_HID_A2DP 5 -#define BT_DBG_PROFILE_HID_PAN 6 -#define BT_DBG_PROFILE_PAN_A2DP 7 -#define BT_DBG_PROFILE_MAX 9 - -#define BTINFO_B_FTP BIT(7) -#define BTINFO_B_A2DP BIT(6) -#define BTINFO_B_HID BIT(5) -#define BTINFO_B_SCO_BUSY BIT(4) -#define BTINFO_B_ACL_BUSY BIT(3) -#define BTINFO_B_INQ_PAGE BIT(2) -#define BTINFO_B_SCO_ESCO BIT(1) -#define BTINFO_B_CONNECTION BIT(0) - -void rtl8723e_btdm_coex_all_off(struct ieee80211_hw *hw); -void rtl8723e_dm_bt_fw_coex_all_off(struct ieee80211_hw *hw); - -void rtl8723e_dm_bt_sw_coex_all_off(struct ieee80211_hw *hw); -void rtl8723e_dm_bt_hw_coex_all_off(struct ieee80211_hw *hw); -long rtl8723e_dm_bt_get_rx_ss(struct ieee80211_hw *hw); -void rtl8723e_dm_bt_balance(struct ieee80211_hw *hw, - bool balance_on, u8 ms0, u8 ms1); -void rtl8723e_dm_bt_agc_table(struct ieee80211_hw *hw, u8 tyep); -void rtl8723e_dm_bt_bb_back_off_level(struct ieee80211_hw *hw, u8 type); -u8 rtl8723e_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw, - u8 level_num, u8 rssi_thresh, - u8 rssi_thresh1); -u8 rtl8723e_dm_bt_check_coex_rssi_state1(struct ieee80211_hw *hw, - u8 level_num, u8 rssi_thresh, - u8 rssi_thresh1); -void _rtl8723_dm_bt_check_wifi_state(struct ieee80211_hw *hw); -void rtl8723e_dm_bt_reject_ap_aggregated_packet(struct ieee80211_hw *hw, - bool b_reject); -bool rtl8723e_dm_bt_is_coexist_state_changed(struct ieee80211_hw *hw); -bool rtl8723e_dm_bt_is_wifi_up_link(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c deleted file mode 100644 index 00a0531cc5f4..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c +++ /dev/null @@ -1,1780 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#include "hal_btc.h" -#include "../pci.h" -#include "phy.h" -#include "fw.h" -#include "reg.h" -#include "def.h" -#include "../rtl8723com/phy_common.h" - -static struct bt_coexist_8723 hal_coex_8723; - -void rtl8723e_dm_bt_turn_off_bt_coexist_before_enter_lps(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - if (!rtlpriv->btcoexist.bt_coexistence) - return; - - if (ppsc->inactiveps) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BT][DM], Before enter IPS, turn off all Coexist DM\n"); - rtlpriv->btcoexist.cstate = 0; - rtlpriv->btcoexist.previous_state = 0; - rtlpriv->btcoexist.cstate_h = 0; - rtlpriv->btcoexist.previous_state_h = 0; - rtl8723e_btdm_coex_all_off(hw); - } -} - -static enum rt_media_status mgnt_link_status_query(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - enum rt_media_status m_status = RT_MEDIA_DISCONNECT; - u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0; - if (bibss || rtlpriv->mac80211.link_state >= MAC80211_LINKED) - m_status = RT_MEDIA_CONNECT; - - return m_status; -} - -void rtl_8723e_bt_wifi_media_status_notify(struct ieee80211_hw *hw, - bool mstatus) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u8 h2c_parameter[3] = {0}; - u8 chnl; - - if (!rtlpriv->btcoexist.bt_coexistence) - return; - - if (RT_MEDIA_CONNECT == mstatus) - h2c_parameter[0] = 0x1; /* 0: disconnected, 1:connected */ - else - h2c_parameter[0] = 0x0; - - if (mgnt_link_status_query(hw)) { - chnl = rtlphy->current_channel; - h2c_parameter[1] = chnl; - } - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) - h2c_parameter[2] = 0x30; - else - h2c_parameter[2] = 0x20; - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], FW write 0x19=0x%x\n", - h2c_parameter[0]<<16|h2c_parameter[1]<<8|h2c_parameter[2]); - - rtl8723e_fill_h2c_cmd(hw, 0x19, 3, h2c_parameter); -} - -static bool rtl8723e_dm_bt_is_wifi_busy(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (rtlpriv->link_info.busytraffic || - rtlpriv->link_info.rx_busy_traffic || - rtlpriv->link_info.tx_busy_traffic) - return true; - else - return false; -} - -static void rtl8723e_dm_bt_set_fw_3a(struct ieee80211_hw *hw, - u8 byte1, u8 byte2, u8 byte3, u8 byte4, - u8 byte5) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 h2c_parameter[5]; - - h2c_parameter[0] = byte1; - h2c_parameter[1] = byte2; - h2c_parameter[2] = byte3; - h2c_parameter[3] = byte4; - h2c_parameter[4] = byte5; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], FW write 0x3a(4bytes)=0x%x%8x\n", - h2c_parameter[0], h2c_parameter[1]<<24 | - h2c_parameter[2]<<16 | h2c_parameter[3]<<8 | - h2c_parameter[4]); - rtl8723e_fill_h2c_cmd(hw, 0x3a, 5, h2c_parameter); -} - -static bool rtl8723e_dm_bt_need_to_dec_bt_pwr(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (mgnt_link_status_query(hw) == RT_MEDIA_CONNECT) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Need to decrease bt power\n"); - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_DEC_BT_POWER; - return true; - } - - rtlpriv->btcoexist.cstate &= ~BT_COEX_STATE_DEC_BT_POWER; - return false; -} - -static bool rtl8723e_dm_bt_is_same_coexist_state(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if ((rtlpriv->btcoexist.previous_state == - rtlpriv->btcoexist.cstate) && - (rtlpriv->btcoexist.previous_state_h == - rtlpriv->btcoexist.cstate_h)) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[DM][BT], Coexist state do not chang!!\n"); - return true; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[DM][BT], Coexist state changed!!\n"); - return false; - } -} - -static void rtl8723e_dm_bt_set_coex_table(struct ieee80211_hw *hw, - u32 val_0x6c0, u32 val_0x6c8, - u32 val_0x6cc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "set coex table, set 0x6c0=0x%x\n", val_0x6c0); - rtl_write_dword(rtlpriv, 0x6c0, val_0x6c0); - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "set coex table, set 0x6c8=0x%x\n", val_0x6c8); - rtl_write_dword(rtlpriv, 0x6c8, val_0x6c8); - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "set coex table, set 0x6cc=0x%x\n", val_0x6cc); - rtl_write_byte(rtlpriv, 0x6cc, val_0x6cc); -} - -static void rtl8723e_dm_bt_set_hw_pta_mode(struct ieee80211_hw *hw, bool b_mode) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (BT_PTA_MODE_ON == b_mode) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, "PTA mode on, "); - /* Enable GPIO 0/1/2/3/8 pins for bt */ - rtl_write_byte(rtlpriv, 0x40, 0x20); - rtlpriv->btcoexist.hw_coexist_all_off = false; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, "PTA mode off\n"); - rtl_write_byte(rtlpriv, 0x40, 0x0); - } -} - -static void rtl8723e_dm_bt_set_sw_rf_rx_lpf_corner(struct ieee80211_hw *hw, - u8 type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (BT_RF_RX_LPF_CORNER_SHRINK == type) { - /* Shrink RF Rx LPF corner, 0x1e[7:4]=1111 ==> [11:4] */ - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "Shrink RF Rx LPF corner!!\n"); - rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, 0x1e, - 0xfffff, 0xf0ff7); - rtlpriv->btcoexist.sw_coexist_all_off = false; - } else if (BT_RF_RX_LPF_CORNER_RESUME == type) { - /*Resume RF Rx LPF corner*/ - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "Resume RF Rx LPF corner!!\n"); - rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A, 0x1e, 0xfffff, - rtlpriv->btcoexist.bt_rfreg_origin_1e); - } -} - -static void dm_bt_set_sw_penalty_tx_rate_adapt(struct ieee80211_hw *hw, - u8 ra_type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp_u1; - - tmp_u1 = rtl_read_byte(rtlpriv, 0x4fd); - tmp_u1 |= BIT(0); - if (BT_TX_RATE_ADAPTIVE_LOW_PENALTY == ra_type) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "Tx rate adaptive, set low penalty!!\n"); - tmp_u1 &= ~BIT(2); - rtlpriv->btcoexist.sw_coexist_all_off = false; - } else if (BT_TX_RATE_ADAPTIVE_NORMAL == ra_type) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "Tx rate adaptive, set normal!!\n"); - tmp_u1 |= BIT(2); - } - - rtl_write_byte(rtlpriv, 0x4fd, tmp_u1); -} - -static void rtl8723e_dm_bt_btdm_structure_reload(struct ieee80211_hw *hw, - struct btdm_8723 *btdm) -{ - btdm->all_off = false; - btdm->agc_table_en = false; - btdm->adc_back_off_on = false; - btdm->b2_ant_hid_en = false; - btdm->low_penalty_rate_adaptive = false; - btdm->rf_rx_lpf_shrink = false; - btdm->reject_aggre_pkt = false; - - btdm->tdma_on = false; - btdm->tdma_ant = TDMA_2ANT; - btdm->tdma_nav = TDMA_NAV_OFF; - btdm->tdma_dac_swing = TDMA_DAC_SWING_OFF; - btdm->fw_dac_swing_lvl = 0x20; - - btdm->tra_tdma_on = false; - btdm->tra_tdma_ant = TDMA_2ANT; - btdm->tra_tdma_nav = TDMA_NAV_OFF; - btdm->ignore_wlan_act = false; - - btdm->ps_tdma_on = false; - btdm->ps_tdma_byte[0] = 0x0; - btdm->ps_tdma_byte[1] = 0x0; - btdm->ps_tdma_byte[2] = 0x0; - btdm->ps_tdma_byte[3] = 0x8; - btdm->ps_tdma_byte[4] = 0x0; - - btdm->pta_on = true; - btdm->val_0x6c0 = 0x5a5aaaaa; - btdm->val_0x6c8 = 0xcc; - btdm->val_0x6cc = 0x3; - - btdm->sw_dac_swing_on = false; - btdm->sw_dac_swing_lvl = 0xc0; - btdm->wlan_act_hi = 0x20; - btdm->wlan_act_lo = 0x10; - btdm->bt_retry_index = 2; - - btdm->dec_bt_pwr = false; -} - -static void rtl8723e_dm_bt_btdm_structure_reload_all_off(struct ieee80211_hw *hw, - struct btdm_8723 *btdm) -{ - rtl8723e_dm_bt_btdm_structure_reload(hw, btdm); - btdm->all_off = true; - btdm->pta_on = false; - btdm->wlan_act_hi = 0x10; -} - -static bool rtl8723e_dm_bt_is_2_ant_common_action(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct btdm_8723 btdm8723; - bool b_common = false; - - rtl8723e_dm_bt_btdm_structure_reload(hw, &btdm8723); - - if (!rtl8723e_dm_bt_is_wifi_busy(hw) && - !rtlpriv->btcoexist.bt_busy) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi idle + Bt idle, bt coex mechanism always off!!\n"); - rtl8723e_dm_bt_btdm_structure_reload_all_off(hw, &btdm8723); - b_common = true; - } else if (rtl8723e_dm_bt_is_wifi_busy(hw) && - !rtlpriv->btcoexist.bt_busy) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi non-idle + Bt disabled/idle!!\n"); - btdm8723.low_penalty_rate_adaptive = true; - btdm8723.rf_rx_lpf_shrink = false; - btdm8723.reject_aggre_pkt = false; - - /* sw mechanism */ - btdm8723.agc_table_en = false; - btdm8723.adc_back_off_on = false; - btdm8723.sw_dac_swing_on = false; - - btdm8723.pta_on = true; - btdm8723.val_0x6c0 = 0x5a5aaaaa; - btdm8723.val_0x6c8 = 0xcccc; - btdm8723.val_0x6cc = 0x3; - - btdm8723.tdma_on = false; - btdm8723.tdma_dac_swing = TDMA_DAC_SWING_OFF; - btdm8723.b2_ant_hid_en = false; - - b_common = true; - } else if (rtlpriv->btcoexist.bt_busy) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Bt non-idle!\n"); - if (mgnt_link_status_query(hw) == RT_MEDIA_CONNECT) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi connection exist\n"); - b_common = false; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "No Wifi connection!\n"); - btdm8723.rf_rx_lpf_shrink = true; - btdm8723.low_penalty_rate_adaptive = false; - btdm8723.reject_aggre_pkt = false; - - /* sw mechanism */ - btdm8723.agc_table_en = false; - btdm8723.adc_back_off_on = false; - btdm8723.sw_dac_swing_on = false; - - btdm8723.pta_on = true; - btdm8723.val_0x6c0 = 0x55555555; - btdm8723.val_0x6c8 = 0x0000ffff; - btdm8723.val_0x6cc = 0x3; - - btdm8723.tdma_on = false; - btdm8723.tdma_dac_swing = TDMA_DAC_SWING_OFF; - btdm8723.b2_ant_hid_en = false; - - b_common = true; - } - } - - if (rtl8723e_dm_bt_need_to_dec_bt_pwr(hw)) - btdm8723.dec_bt_pwr = true; - - if (b_common) - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_BTINFO_COMMON; - - if (b_common && rtl8723e_dm_bt_is_coexist_state_changed(hw)) - rtl8723e_dm_bt_set_bt_dm(hw, &btdm8723); - - return b_common; -} - -static void rtl8723e_dm_bt_set_sw_full_time_dac_swing( - struct ieee80211_hw *hw, - bool sw_dac_swing_on, - u32 sw_dac_swing_lvl) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (sw_dac_swing_on) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], SwDacSwing = 0x%x\n", sw_dac_swing_lvl); - rtl8723_phy_set_bb_reg(hw, 0x880, 0xff000000, - sw_dac_swing_lvl); - rtlpriv->btcoexist.sw_coexist_all_off = false; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], SwDacSwing Off!\n"); - rtl8723_phy_set_bb_reg(hw, 0x880, 0xff000000, 0xc0); - } -} - -static void rtl8723e_dm_bt_set_fw_dec_bt_pwr( - struct ieee80211_hw *hw, bool dec_bt_pwr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 h2c_parameter[1] = {0}; - - h2c_parameter[0] = 0; - - if (dec_bt_pwr) { - h2c_parameter[0] |= BIT(1); - rtlpriv->btcoexist.fw_coexist_all_off = false; - } - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], decrease Bt Power : %s, write 0x21=0x%x\n", - (dec_bt_pwr ? "Yes!!" : "No!!"), h2c_parameter[0]); - - rtl8723e_fill_h2c_cmd(hw, 0x21, 1, h2c_parameter); -} - -static void rtl8723e_dm_bt_set_fw_2_ant_hid(struct ieee80211_hw *hw, - bool b_enable, bool b_dac_swing_on) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 h2c_parameter[1] = {0}; - - if (b_enable) { - h2c_parameter[0] |= BIT(0); - rtlpriv->btcoexist.fw_coexist_all_off = false; - } - if (b_dac_swing_on) - h2c_parameter[0] |= BIT(1); /* Dac Swing default enable */ - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], turn 2-Ant+HID mode %s, DACSwing:%s, write 0x15=0x%x\n", - (b_enable ? "ON!!" : "OFF!!"), (b_dac_swing_on ? "ON" : "OFF"), - h2c_parameter[0]); - - rtl8723e_fill_h2c_cmd(hw, 0x15, 1, h2c_parameter); -} - -static void rtl8723e_dm_bt_set_fw_tdma_ctrl(struct ieee80211_hw *hw, - bool b_enable, u8 ant_num, - u8 nav_en, u8 dac_swing_en) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 h2c_parameter[1] = {0}; - u8 h2c_parameter1[1] = {0}; - - h2c_parameter[0] = 0; - h2c_parameter1[0] = 0; - - if (b_enable) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], set BT PTA update manager to trigger update!!\n"); - h2c_parameter1[0] |= BIT(0); - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], turn TDMA mode ON!!\n"); - h2c_parameter[0] |= BIT(0); /* function enable */ - if (TDMA_1ANT == ant_num) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], TDMA_1ANT\n"); - h2c_parameter[0] |= BIT(1); - } else if (TDMA_2ANT == ant_num) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], TDMA_2ANT\n"); - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], Unknown Ant\n"); - } - - if (TDMA_NAV_OFF == nav_en) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], TDMA_NAV_OFF\n"); - } else if (TDMA_NAV_ON == nav_en) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], TDMA_NAV_ON\n"); - h2c_parameter[0] |= BIT(2); - } - - if (TDMA_DAC_SWING_OFF == dac_swing_en) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], TDMA_DAC_SWING_OFF\n"); - } else if (TDMA_DAC_SWING_ON == dac_swing_en) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], TDMA_DAC_SWING_ON\n"); - h2c_parameter[0] |= BIT(4); - } - rtlpriv->btcoexist.fw_coexist_all_off = false; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], set BT PTA update manager to no update!!\n"); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], turn TDMA mode OFF!!\n"); - } - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], FW2AntTDMA, write 0x26=0x%x\n", - h2c_parameter1[0]); - rtl8723e_fill_h2c_cmd(hw, 0x26, 1, h2c_parameter1); - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], FW2AntTDMA, write 0x14=0x%x\n", - h2c_parameter[0]); - rtl8723e_fill_h2c_cmd(hw, 0x14, 1, h2c_parameter); -} - -static void rtl8723e_dm_bt_set_fw_ignore_wlan_act(struct ieee80211_hw *hw, - bool b_enable) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 h2c_parameter[1] = {0}; - - if (b_enable) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], BT Ignore Wlan_Act !!\n"); - h2c_parameter[0] |= BIT(0); /* function enable */ - rtlpriv->btcoexist.fw_coexist_all_off = false; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], BT don't ignore Wlan_Act !!\n"); - } - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], set FW for BT Ignore Wlan_Act, write 0x25=0x%x\n", - h2c_parameter[0]); - - rtl8723e_fill_h2c_cmd(hw, 0x25, 1, h2c_parameter); -} - -static void rtl8723e_dm_bt_set_fw_tra_tdma_ctrl(struct ieee80211_hw *hw, - bool b_enable, u8 ant_num, - u8 nav_en) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - u8 h2c_parameter[2] = {0}; - - /* Only 8723 B cut should do this */ - if (IS_VENDOR_8723_A_CUT(rtlhal->version)) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], not 8723B cut, don't set Traditional TDMA!!\n"); - return; - } - - if (b_enable) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], turn TTDMA mode ON!!\n"); - h2c_parameter[0] |= BIT(0); /* function enable */ - if (TDMA_1ANT == ant_num) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], TTDMA_1ANT\n"); - h2c_parameter[0] |= BIT(1); - } else if (TDMA_2ANT == ant_num) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], TTDMA_2ANT\n"); - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], Unknown Ant\n"); - } - - if (TDMA_NAV_OFF == nav_en) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], TTDMA_NAV_OFF\n"); - } else if (TDMA_NAV_ON == nav_en) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], TTDMA_NAV_ON\n"); - h2c_parameter[1] |= BIT(0); - } - - rtlpriv->btcoexist.fw_coexist_all_off = false; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], turn TTDMA mode OFF!!\n"); - } - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], FW Traditional TDMA, write 0x33=0x%x\n", - h2c_parameter[0] << 8 | h2c_parameter[1]); - - rtl8723e_fill_h2c_cmd(hw, 0x33, 2, h2c_parameter); -} - -static void rtl8723e_dm_bt_set_fw_dac_swing_level(struct ieee80211_hw *hw, - u8 dac_swing_lvl) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 h2c_parameter[1] = {0}; - h2c_parameter[0] = dac_swing_lvl; - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], Set Dac Swing Level=0x%x\n", dac_swing_lvl); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], write 0x29=0x%x\n", h2c_parameter[0]); - - rtl8723e_fill_h2c_cmd(hw, 0x29, 1, h2c_parameter); -} - -static void rtl8723e_dm_bt_set_fw_bt_hid_info(struct ieee80211_hw *hw, - bool b_enable) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 h2c_parameter[1] = {0}; - h2c_parameter[0] = 0; - - if (b_enable) { - h2c_parameter[0] |= BIT(0); - rtlpriv->btcoexist.fw_coexist_all_off = false; - } - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], Set BT HID information=0x%x\n", b_enable); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], write 0x24=0x%x\n", h2c_parameter[0]); - - rtl8723e_fill_h2c_cmd(hw, 0x24, 1, h2c_parameter); -} - -static void rtl8723e_dm_bt_set_fw_bt_retry_index(struct ieee80211_hw *hw, - u8 retry_index) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 h2c_parameter[1] = {0}; - h2c_parameter[0] = retry_index; - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], Set BT Retry Index=%d\n", retry_index); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], write 0x23=0x%x\n", h2c_parameter[0]); - - rtl8723e_fill_h2c_cmd(hw, 0x23, 1, h2c_parameter); -} - -static void rtl8723e_dm_bt_set_fw_wlan_act(struct ieee80211_hw *hw, - u8 wlan_act_hi, u8 wlan_act_lo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 h2c_parameter_hi[1] = {0}; - u8 h2c_parameter_lo[1] = {0}; - h2c_parameter_hi[0] = wlan_act_hi; - h2c_parameter_lo[0] = wlan_act_lo; - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], Set WLAN_ACT Hi:Lo=0x%x/0x%x\n", - wlan_act_hi, wlan_act_lo); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], write 0x22=0x%x\n", h2c_parameter_hi[0]); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], write 0x11=0x%x\n", h2c_parameter_lo[0]); - - /* WLAN_ACT = High duration, unit:ms */ - rtl8723e_fill_h2c_cmd(hw, 0x22, 1, h2c_parameter_hi); - /* WLAN_ACT = Low duration, unit:3*625us */ - rtl8723e_fill_h2c_cmd(hw, 0x11, 1, h2c_parameter_lo); -} - -void rtl8723e_dm_bt_set_bt_dm(struct ieee80211_hw *hw, - struct btdm_8723 *btdm) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct btdm_8723 *btdm_8723 = &hal_coex_8723.btdm; - u8 i; - - bool fw_current_inpsmode = false; - bool fw_ps_awake = true; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inpsmode)); - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, - (u8 *)(&fw_ps_awake)); - - /* check new setting is different with the old one, */ - /* if all the same, don't do the setting again. */ - if (memcmp(btdm_8723, btdm, sizeof(struct btdm_8723)) == 0) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], the same coexist setting, return!!\n"); - return; - } else { /* save the new coexist setting */ - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], UPDATE TO NEW COEX SETTING!!\n"); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new bAllOff=0x%x/ 0x%x\n", - btdm_8723->all_off, btdm->all_off); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new agc_table_en=0x%x/ 0x%x\n", - btdm_8723->agc_table_en, btdm->agc_table_en); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new adc_back_off_on=0x%x/ 0x%x\n", - btdm_8723->adc_back_off_on, - btdm->adc_back_off_on); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new b2_ant_hid_en=0x%x/ 0x%x\n", - btdm_8723->b2_ant_hid_en, btdm->b2_ant_hid_en); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new bLowPenaltyRateAdaptive=0x%x/ 0x%x\n", - btdm_8723->low_penalty_rate_adaptive, - btdm->low_penalty_rate_adaptive); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new bRfRxLpfShrink=0x%x/ 0x%x\n", - btdm_8723->rf_rx_lpf_shrink, - btdm->rf_rx_lpf_shrink); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new bRejectAggrePkt=0x%x/ 0x%x\n", - btdm_8723->reject_aggre_pkt, - btdm->reject_aggre_pkt); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new tdma_on=0x%x/ 0x%x\n", - btdm_8723->tdma_on, btdm->tdma_on); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new tdmaAnt=0x%x/ 0x%x\n", - btdm_8723->tdma_ant, btdm->tdma_ant); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new tdmaNav=0x%x/ 0x%x\n", - btdm_8723->tdma_nav, btdm->tdma_nav); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new tdma_dac_swing=0x%x/ 0x%x\n", - btdm_8723->tdma_dac_swing, btdm->tdma_dac_swing); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new fw_dac_swing_lvl=0x%x/ 0x%x\n", - btdm_8723->fw_dac_swing_lvl, - btdm->fw_dac_swing_lvl); - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new bTraTdmaOn=0x%x/ 0x%x\n", - btdm_8723->tra_tdma_on, btdm->tra_tdma_on); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new traTdmaAnt=0x%x/ 0x%x\n", - btdm_8723->tra_tdma_ant, btdm->tra_tdma_ant); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new traTdmaNav=0x%x/ 0x%x\n", - btdm_8723->tra_tdma_nav, btdm->tra_tdma_nav); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new bPsTdmaOn=0x%x/ 0x%x\n", - btdm_8723->ps_tdma_on, btdm->ps_tdma_on); - for (i = 0; i < 5; i++) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new psTdmaByte[i]=0x%x/ 0x%x\n", - btdm_8723->ps_tdma_byte[i], - btdm->ps_tdma_byte[i]); - } - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new bIgnoreWlanAct=0x%x/ 0x%x\n", - btdm_8723->ignore_wlan_act, - btdm->ignore_wlan_act); - - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new bPtaOn=0x%x/ 0x%x\n", - btdm_8723->pta_on, btdm->pta_on); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new val_0x6c0=0x%x/ 0x%x\n", - btdm_8723->val_0x6c0, btdm->val_0x6c0); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new val_0x6c8=0x%x/ 0x%x\n", - btdm_8723->val_0x6c8, btdm->val_0x6c8); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new val_0x6cc=0x%x/ 0x%x\n", - btdm_8723->val_0x6cc, btdm->val_0x6cc); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new sw_dac_swing_on=0x%x/ 0x%x\n", - btdm_8723->sw_dac_swing_on, - btdm->sw_dac_swing_on); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new sw_dac_swing_lvl=0x%x/ 0x%x\n", - btdm_8723->sw_dac_swing_lvl, - btdm->sw_dac_swing_lvl); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new wlanActHi=0x%x/ 0x%x\n", - btdm_8723->wlan_act_hi, btdm->wlan_act_hi); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new wlanActLo=0x%x/ 0x%x\n", - btdm_8723->wlan_act_lo, btdm->wlan_act_lo); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], original/new btRetryIndex=0x%x/ 0x%x\n", - btdm_8723->bt_retry_index, btdm->bt_retry_index); - - memcpy(btdm_8723, btdm, sizeof(struct btdm_8723)); - } - /* Here we only consider when Bt Operation - * inquiry/paging/pairing is ON - * we only need to turn off TDMA - */ - - if (rtlpriv->btcoexist.hold_for_bt_operation) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], set to ignore wlanAct for BT OP!!\n"); - rtl8723e_dm_bt_set_fw_ignore_wlan_act(hw, true); - return; - } - - if (btdm->all_off) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], disable all coexist mechanism !!\n"); - rtl8723e_btdm_coex_all_off(hw); - return; - } - - rtl8723e_dm_bt_reject_ap_aggregated_packet(hw, btdm->reject_aggre_pkt); - - if (btdm->low_penalty_rate_adaptive) - dm_bt_set_sw_penalty_tx_rate_adapt(hw, BT_TX_RATE_ADAPTIVE_LOW_PENALTY); - else - dm_bt_set_sw_penalty_tx_rate_adapt(hw, - BT_TX_RATE_ADAPTIVE_NORMAL); - - if (btdm->rf_rx_lpf_shrink) - rtl8723e_dm_bt_set_sw_rf_rx_lpf_corner(hw, - BT_RF_RX_LPF_CORNER_SHRINK); - else - rtl8723e_dm_bt_set_sw_rf_rx_lpf_corner(hw, - BT_RF_RX_LPF_CORNER_RESUME); - - if (btdm->agc_table_en) - rtl8723e_dm_bt_agc_table(hw, BT_AGCTABLE_ON); - else - rtl8723e_dm_bt_agc_table(hw, BT_AGCTABLE_OFF); - - if (btdm->adc_back_off_on) - rtl8723e_dm_bt_bb_back_off_level(hw, BT_BB_BACKOFF_ON); - else - rtl8723e_dm_bt_bb_back_off_level(hw, BT_BB_BACKOFF_OFF); - - rtl8723e_dm_bt_set_fw_bt_retry_index(hw, btdm->bt_retry_index); - - rtl8723e_dm_bt_set_fw_dac_swing_level(hw, btdm->fw_dac_swing_lvl); - rtl8723e_dm_bt_set_fw_wlan_act(hw, btdm->wlan_act_hi, - btdm->wlan_act_lo); - - rtl8723e_dm_bt_set_coex_table(hw, btdm->val_0x6c0, - btdm->val_0x6c8, btdm->val_0x6cc); - rtl8723e_dm_bt_set_hw_pta_mode(hw, btdm->pta_on); - - /* Note: There is a constraint between TDMA and 2AntHID - * Only one of 2AntHid and tdma can be turn on - * We should turn off those mechanisms should be turned off first - * and then turn on those mechanisms should be turned on. - */ - if (btdm->b2_ant_hid_en) { - /* turn off tdma */ - rtl8723e_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on, - btdm->tra_tdma_ant, - btdm->tra_tdma_nav); - rtl8723e_dm_bt_set_fw_tdma_ctrl(hw, false, btdm->tdma_ant, - btdm->tdma_nav, - btdm->tdma_dac_swing); - - /* turn off Pstdma */ - rtl8723e_dm_bt_set_fw_ignore_wlan_act(hw, - btdm->ignore_wlan_act); - /* Antenna control by PTA, 0x870 = 0x300. */ - rtl8723e_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0); - - /* turn on 2AntHid */ - rtl8723e_dm_bt_set_fw_bt_hid_info(hw, true); - rtl8723e_dm_bt_set_fw_2_ant_hid(hw, true, true); - } else if (btdm->tdma_on) { - /* turn off 2AntHid */ - rtl8723e_dm_bt_set_fw_bt_hid_info(hw, false); - rtl8723e_dm_bt_set_fw_2_ant_hid(hw, false, false); - - /* turn off pstdma */ - rtl8723e_dm_bt_set_fw_ignore_wlan_act(hw, - btdm->ignore_wlan_act); - /* Antenna control by PTA, 0x870 = 0x300. */ - rtl8723e_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0); - - /* turn on tdma */ - rtl8723e_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on, - btdm->tra_tdma_ant, - btdm->tra_tdma_nav); - rtl8723e_dm_bt_set_fw_tdma_ctrl(hw, true, btdm->tdma_ant, - btdm->tdma_nav, - btdm->tdma_dac_swing); - } else if (btdm->ps_tdma_on) { - /* turn off 2AntHid */ - rtl8723e_dm_bt_set_fw_bt_hid_info(hw, false); - rtl8723e_dm_bt_set_fw_2_ant_hid(hw, false, false); - - /* turn off tdma */ - rtl8723e_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on, - btdm->tra_tdma_ant, - btdm->tra_tdma_nav); - rtl8723e_dm_bt_set_fw_tdma_ctrl(hw, false, btdm->tdma_ant, - btdm->tdma_nav, - btdm->tdma_dac_swing); - - /* turn on pstdma */ - rtl8723e_dm_bt_set_fw_ignore_wlan_act(hw, - btdm->ignore_wlan_act); - rtl8723e_dm_bt_set_fw_3a(hw, btdm->ps_tdma_byte[0], - btdm->ps_tdma_byte[1], - btdm->ps_tdma_byte[2], - btdm->ps_tdma_byte[3], - btdm->ps_tdma_byte[4]); - } else { - /* turn off 2AntHid */ - rtl8723e_dm_bt_set_fw_bt_hid_info(hw, false); - rtl8723e_dm_bt_set_fw_2_ant_hid(hw, false, false); - - /* turn off tdma */ - rtl8723e_dm_bt_set_fw_tra_tdma_ctrl(hw, btdm->tra_tdma_on, - btdm->tra_tdma_ant, - btdm->tra_tdma_nav); - rtl8723e_dm_bt_set_fw_tdma_ctrl(hw, false, btdm->tdma_ant, - btdm->tdma_nav, - btdm->tdma_dac_swing); - - /* turn off pstdma */ - rtl8723e_dm_bt_set_fw_ignore_wlan_act(hw, - btdm->ignore_wlan_act); - /* Antenna control by PTA, 0x870 = 0x300. */ - rtl8723e_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0); - } - - /* Note: - * We should add delay for making sure - * sw DacSwing can be set sucessfully. - * because of that rtl8723e_dm_bt_set_fw_2_ant_hid() - * and rtl8723e_dm_bt_set_fw_tdma_ctrl() - * will overwrite the reg 0x880. - */ - mdelay(30); - rtl8723e_dm_bt_set_sw_full_time_dac_swing(hw, btdm->sw_dac_swing_on, - btdm->sw_dac_swing_lvl); - rtl8723e_dm_bt_set_fw_dec_bt_pwr(hw, btdm->dec_bt_pwr); -} - -/* ============================================================ */ -/* extern function start with BTDM_ */ -/* ============================================================i - */ -static u32 rtl8723e_dm_bt_tx_rx_couter_h(struct ieee80211_hw *hw) -{ - u32 counters = 0; - - counters = hal_coex_8723.high_priority_tx + - hal_coex_8723.high_priority_rx; - return counters; -} - -static u32 rtl8723e_dm_bt_tx_rx_couter_l(struct ieee80211_hw *hw) -{ - u32 counters = 0; - - counters = hal_coex_8723.low_priority_tx + - hal_coex_8723.low_priority_rx; - return counters; -} - -static u8 rtl8723e_dm_bt_bt_tx_rx_counter_level(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 bt_tx_rx_cnt = 0; - u8 bt_tx_rx_cnt_lvl = 0; - - bt_tx_rx_cnt = rtl8723e_dm_bt_tx_rx_couter_h(hw) - + rtl8723e_dm_bt_tx_rx_couter_l(hw); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters = %d\n", bt_tx_rx_cnt); - - rtlpriv->btcoexist.cstate_h &= ~ - (BT_COEX_STATE_BT_CNT_LEVEL_0 | BT_COEX_STATE_BT_CNT_LEVEL_1| - BT_COEX_STATE_BT_CNT_LEVEL_2); - - if (bt_tx_rx_cnt >= BT_TXRX_CNT_THRES_3) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters at level 3\n"); - bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_3; - rtlpriv->btcoexist.cstate_h |= - BT_COEX_STATE_BT_CNT_LEVEL_3; - } else if (bt_tx_rx_cnt >= BT_TXRX_CNT_THRES_2) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters at level 2\n"); - bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_2; - rtlpriv->btcoexist.cstate_h |= - BT_COEX_STATE_BT_CNT_LEVEL_2; - } else if (bt_tx_rx_cnt >= BT_TXRX_CNT_THRES_1) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters at level 1\n"); - bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_1; - rtlpriv->btcoexist.cstate_h |= - BT_COEX_STATE_BT_CNT_LEVEL_1; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters at level 0\n"); - bt_tx_rx_cnt_lvl = BT_TXRX_CNT_LEVEL_0; - rtlpriv->btcoexist.cstate_h |= - BT_COEX_STATE_BT_CNT_LEVEL_0; - } - return bt_tx_rx_cnt_lvl; -} - -static void rtl8723e_dm_bt_2_ant_hid_sco_esco(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct btdm_8723 btdm8723; - u8 bt_rssi_state, bt_rssi_state1; - u8 bt_tx_rx_cnt_lvl = 0; - - rtl8723e_dm_bt_btdm_structure_reload(hw, &btdm8723); - - btdm8723.rf_rx_lpf_shrink = true; - btdm8723.low_penalty_rate_adaptive = true; - btdm8723.reject_aggre_pkt = false; - - bt_tx_rx_cnt_lvl = rtl8723e_dm_bt_bt_tx_rx_counter_level(hw); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters = %d\n", bt_tx_rx_cnt_lvl); - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, "HT40\n"); - /* coex table */ - btdm8723.val_0x6c0 = 0x55555555; - btdm8723.val_0x6c8 = 0xffff; - btdm8723.val_0x6cc = 0x3; - - /* sw mechanism */ - btdm8723.agc_table_en = false; - btdm8723.adc_back_off_on = false; - btdm8723.sw_dac_swing_on = false; - - /* fw mechanism */ - btdm8723.ps_tdma_on = true; - if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0x5; - btdm8723.ps_tdma_byte[2] = 0x5; - btdm8723.ps_tdma_byte[3] = 0x2; - btdm8723.ps_tdma_byte[4] = 0x80; - } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xa; - btdm8723.ps_tdma_byte[2] = 0xa; - btdm8723.ps_tdma_byte[3] = 0x2; - btdm8723.ps_tdma_byte[4] = 0x80; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters < 1200\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xf; - btdm8723.ps_tdma_byte[2] = 0xf; - btdm8723.ps_tdma_byte[3] = 0x2; - btdm8723.ps_tdma_byte[4] = 0x80; - } - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "HT20 or Legacy\n"); - bt_rssi_state = - rtl8723e_dm_bt_check_coex_rssi_state(hw, 2, 47, 0); - bt_rssi_state1 = - rtl8723e_dm_bt_check_coex_rssi_state1(hw, 2, 27, 0); - - /* coex table */ - btdm8723.val_0x6c0 = 0x55555555; - btdm8723.val_0x6c8 = 0xffff; - btdm8723.val_0x6cc = 0x3; - - /* sw mechanism */ - if ((bt_rssi_state == BT_RSSI_STATE_HIGH) || - (bt_rssi_state == BT_RSSI_STATE_STAY_HIGH)) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi rssi high\n"); - btdm8723.agc_table_en = true; - btdm8723.adc_back_off_on = true; - btdm8723.sw_dac_swing_on = false; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi rssi low\n"); - btdm8723.agc_table_en = false; - btdm8723.adc_back_off_on = false; - btdm8723.sw_dac_swing_on = false; - } - - /* fw mechanism */ - btdm8723.ps_tdma_on = true; - if ((bt_rssi_state1 == BT_RSSI_STATE_HIGH) || - (bt_rssi_state1 == BT_RSSI_STATE_STAY_HIGH)) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi rssi-1 high\n"); - /* only rssi high we need to do this, */ - /* when rssi low, the value will modified by fw */ - rtl_write_byte(rtlpriv, 0x883, 0x40); - if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0x5; - btdm8723.ps_tdma_byte[2] = 0x5; - btdm8723.ps_tdma_byte[3] = 0x83; - btdm8723.ps_tdma_byte[4] = 0x80; - } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters>= 1200 && < 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xa; - btdm8723.ps_tdma_byte[2] = 0xa; - btdm8723.ps_tdma_byte[3] = 0x83; - btdm8723.ps_tdma_byte[4] = 0x80; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters < 1200\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xf; - btdm8723.ps_tdma_byte[2] = 0xf; - btdm8723.ps_tdma_byte[3] = 0x83; - btdm8723.ps_tdma_byte[4] = 0x80; - } - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi rssi-1 low\n"); - if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0x5; - btdm8723.ps_tdma_byte[2] = 0x5; - btdm8723.ps_tdma_byte[3] = 0x2; - btdm8723.ps_tdma_byte[4] = 0x80; - } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xa; - btdm8723.ps_tdma_byte[2] = 0xa; - btdm8723.ps_tdma_byte[3] = 0x2; - btdm8723.ps_tdma_byte[4] = 0x80; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters < 1200\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xf; - btdm8723.ps_tdma_byte[2] = 0xf; - btdm8723.ps_tdma_byte[3] = 0x2; - btdm8723.ps_tdma_byte[4] = 0x80; - } - } - } - - if (rtl8723e_dm_bt_need_to_dec_bt_pwr(hw)) - btdm8723.dec_bt_pwr = true; - - /* Always ignore WlanAct if bHid|bSCOBusy|bSCOeSCO */ - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT btInqPageStartTime = 0x%x, btTxRxCntLvl = %d\n", - hal_coex_8723.bt_inq_page_start_time, bt_tx_rx_cnt_lvl); - if ((hal_coex_8723.bt_inq_page_start_time) || - (BT_TXRX_CNT_LEVEL_3 == bt_tx_rx_cnt_lvl)) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], Set BT inquiry / page scan 0x3a setting\n"); - btdm8723.ps_tdma_on = true; - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0x5; - btdm8723.ps_tdma_byte[2] = 0x5; - btdm8723.ps_tdma_byte[3] = 0x2; - btdm8723.ps_tdma_byte[4] = 0x80; - } - - if (rtl8723e_dm_bt_is_coexist_state_changed(hw)) - rtl8723e_dm_bt_set_bt_dm(hw, &btdm8723); - -} - -static void rtl8723e_dm_bt_2_ant_ftp_a2dp(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct btdm_8723 btdm8723; - - u8 bt_rssi_state, bt_rssi_state1; - u32 bt_tx_rx_cnt_lvl = 0; - - rtl8723e_dm_bt_btdm_structure_reload(hw, &btdm8723); - - btdm8723.rf_rx_lpf_shrink = true; - btdm8723.low_penalty_rate_adaptive = true; - btdm8723.reject_aggre_pkt = false; - - bt_tx_rx_cnt_lvl = rtl8723e_dm_bt_bt_tx_rx_counter_level(hw); - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters = %d\n", bt_tx_rx_cnt_lvl); - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, "HT40\n"); - bt_rssi_state = - rtl8723e_dm_bt_check_coex_rssi_state(hw, 2, 37, 0); - - /* coex table */ - btdm8723.val_0x6c0 = 0x55555555; - btdm8723.val_0x6c8 = 0xffff; - btdm8723.val_0x6cc = 0x3; - - /* sw mechanism */ - btdm8723.agc_table_en = false; - btdm8723.adc_back_off_on = true; - btdm8723.sw_dac_swing_on = false; - - /* fw mechanism */ - btdm8723.ps_tdma_on = true; - if ((bt_rssi_state == BT_RSSI_STATE_HIGH) || - (bt_rssi_state == BT_RSSI_STATE_STAY_HIGH)) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi rssi high\n"); - if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0x5; - btdm8723.ps_tdma_byte[2] = 0x5; - btdm8723.ps_tdma_byte[3] = 0x81; - btdm8723.ps_tdma_byte[4] = 0x80; - } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xa; - btdm8723.ps_tdma_byte[2] = 0xa; - btdm8723.ps_tdma_byte[3] = 0x81; - btdm8723.ps_tdma_byte[4] = 0x80; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters < 1200\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xf; - btdm8723.ps_tdma_byte[2] = 0xf; - btdm8723.ps_tdma_byte[3] = 0x81; - btdm8723.ps_tdma_byte[4] = 0x80; - } - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi rssi low\n"); - if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0x5; - btdm8723.ps_tdma_byte[2] = 0x5; - btdm8723.ps_tdma_byte[3] = 0x0; - btdm8723.ps_tdma_byte[4] = 0x80; - } else if (bt_tx_rx_cnt_lvl == - BT_TXRX_CNT_LEVEL_1) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xa; - btdm8723.ps_tdma_byte[2] = 0xa; - btdm8723.ps_tdma_byte[3] = 0x0; - btdm8723.ps_tdma_byte[4] = 0x80; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters < 1200\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xf; - btdm8723.ps_tdma_byte[2] = 0xf; - btdm8723.ps_tdma_byte[3] = 0x0; - btdm8723.ps_tdma_byte[4] = 0x80; - } - } - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "HT20 or Legacy\n"); - bt_rssi_state = - rtl8723e_dm_bt_check_coex_rssi_state(hw, 2, 47, 0); - bt_rssi_state1 = - rtl8723e_dm_bt_check_coex_rssi_state1(hw, 2, 27, 0); - - /* coex table */ - btdm8723.val_0x6c0 = 0x55555555; - btdm8723.val_0x6c8 = 0xffff; - btdm8723.val_0x6cc = 0x3; - - /* sw mechanism */ - if ((bt_rssi_state == BT_RSSI_STATE_HIGH) || - (bt_rssi_state == BT_RSSI_STATE_STAY_HIGH)) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi rssi high\n"); - btdm8723.agc_table_en = true; - btdm8723.adc_back_off_on = true; - btdm8723.sw_dac_swing_on = false; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi rssi low\n"); - btdm8723.agc_table_en = false; - btdm8723.adc_back_off_on = false; - btdm8723.sw_dac_swing_on = false; - } - - /* fw mechanism */ - btdm8723.ps_tdma_on = true; - if ((bt_rssi_state1 == BT_RSSI_STATE_HIGH) || - (bt_rssi_state1 == BT_RSSI_STATE_STAY_HIGH)) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi rssi-1 high\n"); - /* only rssi high we need to do this, */ - /* when rssi low, the value will modified by fw */ - rtl_write_byte(rtlpriv, 0x883, 0x40); - if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0x5; - btdm8723.ps_tdma_byte[2] = 0x5; - btdm8723.ps_tdma_byte[3] = 0x81; - btdm8723.ps_tdma_byte[4] = 0x80; - } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xa; - btdm8723.ps_tdma_byte[2] = 0xa; - btdm8723.ps_tdma_byte[3] = 0x81; - btdm8723.ps_tdma_byte[4] = 0x80; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters < 1200\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xf; - btdm8723.ps_tdma_byte[2] = 0xf; - btdm8723.ps_tdma_byte[3] = 0x81; - btdm8723.ps_tdma_byte[4] = 0x80; - } - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Wifi rssi-1 low\n"); - if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_2) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0x5; - btdm8723.ps_tdma_byte[2] = 0x5; - btdm8723.ps_tdma_byte[3] = 0x0; - btdm8723.ps_tdma_byte[4] = 0x80; - } else if (bt_tx_rx_cnt_lvl == BT_TXRX_CNT_LEVEL_1) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters >= 1200 && < 1400\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xa; - btdm8723.ps_tdma_byte[2] = 0xa; - btdm8723.ps_tdma_byte[3] = 0x0; - btdm8723.ps_tdma_byte[4] = 0x80; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT TxRx Counters < 1200\n"); - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0xf; - btdm8723.ps_tdma_byte[2] = 0xf; - btdm8723.ps_tdma_byte[3] = 0x0; - btdm8723.ps_tdma_byte[4] = 0x80; - } - } - } - - if (rtl8723e_dm_bt_need_to_dec_bt_pwr(hw)) - btdm8723.dec_bt_pwr = true; - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT btInqPageStartTime = 0x%x, btTxRxCntLvl = %d\n", - hal_coex_8723.bt_inq_page_start_time, bt_tx_rx_cnt_lvl); - - if ((hal_coex_8723.bt_inq_page_start_time) || - (BT_TXRX_CNT_LEVEL_3 == bt_tx_rx_cnt_lvl)) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], Set BT inquiry / page scan 0x3a setting\n"); - btdm8723.ps_tdma_on = true; - btdm8723.ps_tdma_byte[0] = 0xa3; - btdm8723.ps_tdma_byte[1] = 0x5; - btdm8723.ps_tdma_byte[2] = 0x5; - btdm8723.ps_tdma_byte[3] = 0x83; - btdm8723.ps_tdma_byte[4] = 0x80; - } - - if (rtl8723e_dm_bt_is_coexist_state_changed(hw)) - rtl8723e_dm_bt_set_bt_dm(hw, &btdm8723); - -} - -static void rtl8723e_dm_bt_inq_page_monitor(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 cur_time; - - cur_time = jiffies; - if (hal_coex_8723.c2h_bt_inquiry_page) { - /* bt inquiry or page is started. */ - if (hal_coex_8723.bt_inq_page_start_time == 0) { - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_BT_INQ_PAGE; - hal_coex_8723.bt_inq_page_start_time = cur_time; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT Inquiry/page is started at time : 0x%x\n", - hal_coex_8723.bt_inq_page_start_time); - } - } - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT Inquiry/page started time : 0x%x, cur_time : 0x%x\n", - hal_coex_8723.bt_inq_page_start_time, cur_time); - - if (hal_coex_8723.bt_inq_page_start_time) { - if ((((long)cur_time - - (long)hal_coex_8723.bt_inq_page_start_time) / HZ) - >= 10) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BT Inquiry/page >= 10sec!!!"); - hal_coex_8723.bt_inq_page_start_time = 0; - rtlpriv->btcoexist.cstate &= - ~BT_COEX_STATE_BT_INQ_PAGE; - } - } -} - -static void rtl8723e_dm_bt_reset_action_profile_state(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->btcoexist.cstate &= ~ - (BT_COEX_STATE_PROFILE_HID | BT_COEX_STATE_PROFILE_A2DP| - BT_COEX_STATE_PROFILE_PAN | BT_COEX_STATE_PROFILE_SCO); - - rtlpriv->btcoexist.cstate &= ~ - (BT_COEX_STATE_BTINFO_COMMON | - BT_COEX_STATE_BTINFO_B_HID_SCOESCO| - BT_COEX_STATE_BTINFO_B_FTP_A2DP); -} - -static void _rtl8723e_dm_bt_coexist_2_ant(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bt_retry_cnt; - u8 bt_info_original; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex] Get bt info by fw!!\n"); - - _rtl8723_dm_bt_check_wifi_state(hw); - - if (hal_coex_8723.c2h_bt_info_req_sent) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex] c2h for bt_info not rcvd yet!!\n"); - } - - bt_retry_cnt = hal_coex_8723.bt_retry_cnt; - bt_info_original = hal_coex_8723.c2h_bt_info_original; - - /* when bt inquiry or page scan, we have to set h2c 0x25 */ - /* ignore wlanact for continuous 4x2secs */ - rtl8723e_dm_bt_inq_page_monitor(hw); - rtl8723e_dm_bt_reset_action_profile_state(hw); - - if (rtl8723e_dm_bt_is_2_ant_common_action(hw)) { - rtlpriv->btcoexist.bt_profile_case = BT_COEX_MECH_COMMON; - rtlpriv->btcoexist.bt_profile_action = BT_COEX_MECH_COMMON; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Action 2-Ant common.\n"); - } else { - if ((bt_info_original & BTINFO_B_HID) || - (bt_info_original & BTINFO_B_SCO_BUSY) || - (bt_info_original & BTINFO_B_SCO_ESCO)) { - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_BTINFO_B_HID_SCOESCO; - rtlpriv->btcoexist.bt_profile_case = - BT_COEX_MECH_HID_SCO_ESCO; - rtlpriv->btcoexist.bt_profile_action = - BT_COEX_MECH_HID_SCO_ESCO; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BTInfo: bHid|bSCOBusy|bSCOeSCO\n"); - rtl8723e_dm_bt_2_ant_hid_sco_esco(hw); - } else if ((bt_info_original & BTINFO_B_FTP) || - (bt_info_original & BTINFO_B_A2DP)) { - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_BTINFO_B_FTP_A2DP; - rtlpriv->btcoexist.bt_profile_case = - BT_COEX_MECH_FTP_A2DP; - rtlpriv->btcoexist.bt_profile_action = - BT_COEX_MECH_FTP_A2DP; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "BTInfo: bFTP|bA2DP\n"); - rtl8723e_dm_bt_2_ant_ftp_a2dp(hw); - } else { - rtlpriv->btcoexist.cstate |= - BT_COEX_STATE_BTINFO_B_HID_SCOESCO; - rtlpriv->btcoexist.bt_profile_case = - BT_COEX_MECH_NONE; - rtlpriv->btcoexist.bt_profile_action = - BT_COEX_MECH_NONE; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], BTInfo: undefined case!!!!\n"); - rtl8723e_dm_bt_2_ant_hid_sco_esco(hw); - } - } -} - -static void _rtl8723e_dm_bt_coexist_1_ant(struct ieee80211_hw *hw) -{ - return; -} - -void rtl8723e_dm_bt_hw_coex_all_off_8723a(struct ieee80211_hw *hw) -{ - rtl8723e_dm_bt_set_coex_table(hw, 0x5a5aaaaa, 0xcc, 0x3); - rtl8723e_dm_bt_set_hw_pta_mode(hw, true); -} - -void rtl8723e_dm_bt_fw_coex_all_off_8723a(struct ieee80211_hw *hw) -{ - rtl8723e_dm_bt_set_fw_ignore_wlan_act(hw, false); - rtl8723e_dm_bt_set_fw_3a(hw, 0x0, 0x0, 0x0, 0x8, 0x0); - rtl8723e_dm_bt_set_fw_2_ant_hid(hw, false, false); - rtl8723e_dm_bt_set_fw_tra_tdma_ctrl(hw, false, TDMA_2ANT, - TDMA_NAV_OFF); - rtl8723e_dm_bt_set_fw_tdma_ctrl(hw, false, TDMA_2ANT, TDMA_NAV_OFF, - TDMA_DAC_SWING_OFF); - rtl8723e_dm_bt_set_fw_dac_swing_level(hw, 0); - rtl8723e_dm_bt_set_fw_bt_hid_info(hw, false); - rtl8723e_dm_bt_set_fw_bt_retry_index(hw, 2); - rtl8723e_dm_bt_set_fw_wlan_act(hw, 0x10, 0x10); - rtl8723e_dm_bt_set_fw_dec_bt_pwr(hw, false); -} - -void rtl8723e_dm_bt_sw_coex_all_off_8723a(struct ieee80211_hw *hw) -{ - rtl8723e_dm_bt_agc_table(hw, BT_AGCTABLE_OFF); - rtl8723e_dm_bt_bb_back_off_level(hw, BT_BB_BACKOFF_OFF); - rtl8723e_dm_bt_reject_ap_aggregated_packet(hw, false); - - dm_bt_set_sw_penalty_tx_rate_adapt(hw, BT_TX_RATE_ADAPTIVE_NORMAL); - rtl8723e_dm_bt_set_sw_rf_rx_lpf_corner(hw, BT_RF_RX_LPF_CORNER_RESUME); - rtl8723e_dm_bt_set_sw_full_time_dac_swing(hw, false, 0xc0); -} - -static void rtl8723e_dm_bt_query_bt_information(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 h2c_parameter[1] = {0}; - - hal_coex_8723.c2h_bt_info_req_sent = true; - - h2c_parameter[0] |= BIT(0); - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "Query Bt information, write 0x38=0x%x\n", h2c_parameter[0]); - - rtl8723e_fill_h2c_cmd(hw, 0x38, 1, h2c_parameter); -} - -static void rtl8723e_dm_bt_bt_hw_counters_monitor(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 reg_hp_tx_rx, reg_lp_tx_rx, u32_tmp; - u32 reg_hp_tx = 0, reg_hp_rx = 0, reg_lp_tx = 0, reg_lp_rx = 0; - - reg_hp_tx_rx = REG_HIGH_PRIORITY_TXRX; - reg_lp_tx_rx = REG_LOW_PRIORITY_TXRX; - - u32_tmp = rtl_read_dword(rtlpriv, reg_hp_tx_rx); - reg_hp_tx = u32_tmp & MASKLWORD; - reg_hp_rx = (u32_tmp & MASKHWORD)>>16; - - u32_tmp = rtl_read_dword(rtlpriv, reg_lp_tx_rx); - reg_lp_tx = u32_tmp & MASKLWORD; - reg_lp_rx = (u32_tmp & MASKHWORD)>>16; - - if (rtlpriv->btcoexist.lps_counter > 1) { - reg_hp_tx %= rtlpriv->btcoexist.lps_counter; - reg_hp_rx %= rtlpriv->btcoexist.lps_counter; - reg_lp_tx %= rtlpriv->btcoexist.lps_counter; - reg_lp_rx %= rtlpriv->btcoexist.lps_counter; - } - - hal_coex_8723.high_priority_tx = reg_hp_tx; - hal_coex_8723.high_priority_rx = reg_hp_rx; - hal_coex_8723.low_priority_tx = reg_lp_tx; - hal_coex_8723.low_priority_rx = reg_lp_rx; - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "High Priority Tx/Rx (reg 0x%x)=%x(%d)/%x(%d)\n", - reg_hp_tx_rx, reg_hp_tx, reg_hp_tx, reg_hp_rx, reg_hp_rx); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "Low Priority Tx/Rx (reg 0x%x)=%x(%d)/%x(%d)\n", - reg_lp_tx_rx, reg_lp_tx, reg_lp_tx, reg_lp_rx, reg_lp_rx); - rtlpriv->btcoexist.lps_counter = 0; - /* rtl_write_byte(rtlpriv, 0x76e, 0xc); */ -} - -static void rtl8723e_dm_bt_bt_enable_disable_check(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool bt_alife = true; - - if (hal_coex_8723.high_priority_tx == 0 && - hal_coex_8723.high_priority_rx == 0 && - hal_coex_8723.low_priority_tx == 0 && - hal_coex_8723.low_priority_rx == 0) { - bt_alife = false; - } - if (hal_coex_8723.high_priority_tx == 0xeaea && - hal_coex_8723.high_priority_rx == 0xeaea && - hal_coex_8723.low_priority_tx == 0xeaea && - hal_coex_8723.low_priority_rx == 0xeaea) { - bt_alife = false; - } - if (hal_coex_8723.high_priority_tx == 0xffff && - hal_coex_8723.high_priority_rx == 0xffff && - hal_coex_8723.low_priority_tx == 0xffff && - hal_coex_8723.low_priority_rx == 0xffff) { - bt_alife = false; - } - if (bt_alife) { - rtlpriv->btcoexist.bt_active_zero_cnt = 0; - rtlpriv->btcoexist.cur_bt_disabled = false; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "8723A BT is enabled !!\n"); - } else { - rtlpriv->btcoexist.bt_active_zero_cnt++; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "8723A bt all counters=0, %d times!!\n", - rtlpriv->btcoexist.bt_active_zero_cnt); - if (rtlpriv->btcoexist.bt_active_zero_cnt >= 2) { - rtlpriv->btcoexist.cur_bt_disabled = true; - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "8723A BT is disabled !!\n"); - } - } - if (rtlpriv->btcoexist.pre_bt_disabled != - rtlpriv->btcoexist.cur_bt_disabled) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, - DBG_TRACE, "8723A BT is from %s to %s!!\n", - (rtlpriv->btcoexist.pre_bt_disabled ? - "disabled" : "enabled"), - (rtlpriv->btcoexist.cur_bt_disabled ? - "disabled" : "enabled")); - rtlpriv->btcoexist.pre_bt_disabled - = rtlpriv->btcoexist.cur_bt_disabled; - } -} - - -void rtl8723e_dm_bt_coexist_8723(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl8723e_dm_bt_query_bt_information(hw); - rtl8723e_dm_bt_bt_hw_counters_monitor(hw); - rtl8723e_dm_bt_bt_enable_disable_check(hw); - - if (rtlpriv->btcoexist.bt_ant_num == ANT_X2) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], 2 Ant mechanism\n"); - _rtl8723e_dm_bt_coexist_2_ant(hw); - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "[BTCoex], 1 Ant mechanism\n"); - _rtl8723e_dm_bt_coexist_1_ant(hw); - } - - if (!rtl8723e_dm_bt_is_same_coexist_state(hw)) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTCoex], Coexist State[bitMap] change from 0x%x%8x to 0x%x%8x\n", - rtlpriv->btcoexist.previous_state_h, - rtlpriv->btcoexist.previous_state, - rtlpriv->btcoexist.cstate_h, - rtlpriv->btcoexist.cstate); - rtlpriv->btcoexist.previous_state - = rtlpriv->btcoexist.cstate; - rtlpriv->btcoexist.previous_state_h - = rtlpriv->btcoexist.cstate_h; - } -} - -static void rtl8723e_dm_bt_parse_bt_info(struct ieee80211_hw *hw, - u8 *tmp_buf, u8 len) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bt_info; - u8 i; - - hal_coex_8723.c2h_bt_info_req_sent = false; - hal_coex_8723.bt_retry_cnt = 0; - for (i = 0; i < len; i++) { - if (i == 0) - hal_coex_8723.c2h_bt_info_original = tmp_buf[i]; - else if (i == 1) - hal_coex_8723.bt_retry_cnt = tmp_buf[i]; - if (i == len-1) - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "0x%2x]", tmp_buf[i]); - else - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "0x%2x, ", tmp_buf[i]); - - } - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "BT info bt_info (Data)= 0x%x\n", - hal_coex_8723.c2h_bt_info_original); - bt_info = hal_coex_8723.c2h_bt_info_original; - - if (bt_info & BIT(2)) - hal_coex_8723.c2h_bt_inquiry_page = true; - else - hal_coex_8723.c2h_bt_inquiry_page = false; - - - if (bt_info & BTINFO_B_CONNECTION) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTC2H], BTInfo: bConnect=true\n"); - rtlpriv->btcoexist.bt_busy = true; - rtlpriv->btcoexist.cstate &= ~BT_COEX_STATE_BT_IDLE; - } else { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, - "[BTC2H], BTInfo: bConnect=false\n"); - rtlpriv->btcoexist.bt_busy = false; - rtlpriv->btcoexist.cstate |= BT_COEX_STATE_BT_IDLE; - } -} -void rtl_8723e_c2h_command_handle(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct c2h_evt_hdr c2h_event; - u8 *ptmp_buf = NULL; - u8 index = 0; - u8 u1b_tmp = 0; - memset(&c2h_event, 0, sizeof(c2h_event)); - u1b_tmp = rtl_read_byte(rtlpriv, REG_C2HEVT_MSG_NORMAL); - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "&&&&&&: REG_C2HEVT_MSG_NORMAL is 0x%x\n", u1b_tmp); - c2h_event.cmd_id = u1b_tmp & 0xF; - c2h_event.cmd_len = (u1b_tmp & 0xF0) >> 4; - c2h_event.cmd_seq = rtl_read_byte(rtlpriv, REG_C2HEVT_MSG_NORMAL + 1); - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "cmd_id: %d, cmd_len: %d, cmd_seq: %d\n", - c2h_event.cmd_id , c2h_event.cmd_len, c2h_event.cmd_seq); - u1b_tmp = rtl_read_byte(rtlpriv, 0x01AF); - if (u1b_tmp == C2H_EVT_HOST_CLOSE) { - return; - } else if (u1b_tmp != C2H_EVT_FW_CLOSE) { - rtl_write_byte(rtlpriv, 0x1AF, 0x00); - return; - } - ptmp_buf = kzalloc(c2h_event.cmd_len, GFP_KERNEL); - if (ptmp_buf == NULL) { - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "malloc cmd buf failed\n"); - return; - } - - /* Read the content */ - for (index = 0; index < c2h_event.cmd_len; index++) - ptmp_buf[index] = rtl_read_byte(rtlpriv, - REG_C2HEVT_MSG_NORMAL + 2 + index); - - - switch (c2h_event.cmd_id) { - case C2H_BT_RSSI: - break; - - case C2H_BT_OP_MODE: - break; - - case BT_INFO: - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "BT info Byte[0] (ID) is 0x%x\n", - c2h_event.cmd_id); - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "BT info Byte[1] (Seq) is 0x%x\n", - c2h_event.cmd_seq); - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "BT info Byte[2] (Data)= 0x%x\n", ptmp_buf[0]); - - rtl8723e_dm_bt_parse_bt_info(hw, ptmp_buf, c2h_event.cmd_len); - - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_periodical(rtlpriv); - - break; - default: - break; - } - kfree(ptmp_buf); - - rtl_write_byte(rtlpriv, 0x01AF, C2H_EVT_HOST_CLOSE); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h deleted file mode 100644 index 3723d7476717..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h +++ /dev/null @@ -1,159 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_HAL_BTC_H__ -#define __RTL8723E_HAL_BTC_H__ - -#include "../wifi.h" -#include "btc.h" -#include "hal_bt_coexist.h" - -#define BT_TXRX_CNT_THRES_1 1200 -#define BT_TXRX_CNT_THRES_2 1400 -#define BT_TXRX_CNT_THRES_3 3000 -/* < 1200 */ -#define BT_TXRX_CNT_LEVEL_0 0 -/* >= 1200 && < 1400 */ -#define BT_TXRX_CNT_LEVEL_1 1 -/* >= 1400 */ -#define BT_TXRX_CNT_LEVEL_2 2 -#define BT_TXRX_CNT_LEVEL_3 3 - -#define BT_COEX_DISABLE 0 -#define BT_Q_PKT_OFF 0 -#define BT_Q_PKT_ON 1 - -#define BT_TX_PWR_OFF 0 -#define BT_TX_PWR_ON 1 - -/* TDMA mode definition */ -#define TDMA_2ANT 0 -#define TDMA_1ANT 1 -#define TDMA_NAV_OFF 0 -#define TDMA_NAV_ON 1 -#define TDMA_DAC_SWING_OFF 0 -#define TDMA_DAC_SWING_ON 1 - -/* PTA mode related definition */ -#define BT_PTA_MODE_OFF 0 -#define BT_PTA_MODE_ON 1 - -/* Penalty Tx Rate Adaptive */ -#define BT_TX_RATE_ADAPTIVE_NORMAL 0 -#define BT_TX_RATE_ADAPTIVE_LOW_PENALTY 1 - -/* RF Corner */ -#define BT_RF_RX_LPF_CORNER_RESUME 0 -#define BT_RF_RX_LPF_CORNER_SHRINK 1 - -#define C2H_EVT_HOST_CLOSE 0x00 -#define C2H_EVT_FW_CLOSE 0xFF - -enum bt_traffic_mode { - BT_MOTOR_EXT_BE = 0x00, - BT_MOTOR_EXT_GUL = 0x01, - BT_MOTOR_EXT_GUB = 0x02, - BT_MOTOR_EXT_GULB = 0x03 -}; - -enum bt_traffic_mode_profile { - BT_PROFILE_NONE, - BT_PROFILE_A2DP, - BT_PROFILE_PAN, - BT_PROFILE_HID, - BT_PROFILE_SCO -}; - -/* -enum hci_ext_bt_operation { - HCI_BT_OP_NONE = 0x0, - HCI_BT_OP_INQUIRE_START = 0x1, - HCI_BT_OP_INQUIRE_FINISH = 0x2, - HCI_BT_OP_PAGING_START = 0x3, - HCI_BT_OP_PAGING_SUCCESS = 0x4, - HCI_BT_OP_PAGING_UNSUCCESS = 0x5, - HCI_BT_OP_PAIRING_START = 0x6, - HCI_BT_OP_PAIRING_FINISH = 0x7, - HCI_BT_OP_BT_DEV_ENABLE = 0x8, - HCI_BT_OP_BT_DEV_DISABLE = 0x9, - HCI_BT_OP_MAX, -}; -*/ - -enum bt_spec { - BT_SPEC_1_0_b = 0x00, - BT_SPEC_1_1 = 0x01, - BT_SPEC_1_2 = 0x02, - BT_SPEC_2_0_EDR = 0x03, - BT_SPEC_2_1_EDR = 0x04, - BT_SPEC_3_0_HS = 0x05, - BT_SPEC_4_0 = 0x06 -}; - -struct c2h_evt_hdr { - u8 cmd_id; - u8 cmd_len; - u8 cmd_seq; -}; - -enum bt_state { - BT_INFO_STATE_DISABLED = 0, - BT_INFO_STATE_NO_CONNECTION = 1, - BT_INFO_STATE_CONNECT_IDLE = 2, - BT_INFO_STATE_INQ_OR_PAG = 3, - BT_INFO_STATE_ACL_ONLY_BUSY = 4, - BT_INFO_STATE_SCO_ONLY_BUSY = 5, - BT_INFO_STATE_ACL_SCO_BUSY = 6, - BT_INFO_STATE_HID_BUSY = 7, - BT_INFO_STATE_HID_SCO_BUSY = 8, - BT_INFO_STATE_MAX = 7 -}; - -enum rtl8723e_c2h_evt { - C2H_DBG = 0, - C2H_TSF = 1, - C2H_AP_RPT_RSP = 2, - /* The FW notify the report of the specific tx packet. */ - C2H_CCX_TX_RPT = 3, - C2H_BT_RSSI = 4, - C2H_BT_OP_MODE = 5, - C2H_HW_INFO_EXCH = 10, - C2H_C2H_H2C_TEST = 11, - BT_INFO = 12, - MAX_C2HEVENT -}; - -void rtl8723e_dm_bt_fw_coex_all_off_8723a(struct ieee80211_hw *hw); -void rtl8723e_dm_bt_sw_coex_all_off_8723a(struct ieee80211_hw *hw); -void rtl8723e_dm_bt_hw_coex_all_off_8723a(struct ieee80211_hw *hw); -void rtl8723e_dm_bt_coexist_8723(struct ieee80211_hw *hw); -void rtl8723e_dm_bt_set_bt_dm(struct ieee80211_hw *hw, - struct btdm_8723 *p_btdm); -void rtl_8723e_c2h_command_handle(struct ieee80211_hw *hw); -void rtl_8723e_bt_wifi_media_status_notify(struct ieee80211_hw *hw, - bool mstatus); -void rtl8723e_dm_bt_turn_off_bt_coexist_before_enter_lps( - struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c deleted file mode 100644 index a4b7eac6856f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c +++ /dev/null @@ -1,2482 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../efuse.h" -#include "../base.h" -#include "../regd.h" -#include "../cam.h" -#include "../ps.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "../rtl8723com/phy_common.h" -#include "dm.h" -#include "../rtl8723com/dm_common.h" -#include "fw.h" -#include "../rtl8723com/fw_common.h" -#include "led.h" -#include "hw.h" -#include "../pwrseqcmd.h" -#include "pwrseq.h" -#include "btc.h" - -#define LLT_CONFIG 5 - -static void _rtl8723e_set_bcn_ctrl_reg(struct ieee80211_hw *hw, - u8 set_bits, u8 clear_bits) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpci->reg_bcn_ctrl_val |= set_bits; - rtlpci->reg_bcn_ctrl_val &= ~clear_bits; - - rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); -} - -static void _rtl8723e_stop_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp1byte; - - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); -} - -static void _rtl8723e_resume_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp1byte; - - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte |= BIT(1); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); -} - -static void _rtl8723e_enable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl8723e_set_bcn_ctrl_reg(hw, 0, BIT(1)); -} - -static void _rtl8723e_disable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl8723e_set_bcn_ctrl_reg(hw, BIT(1), 0); -} - -void rtl8723e_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - switch (variable) { - case HW_VAR_RCR: - *((u32 *)(val)) = rtlpci->receive_config; - break; - case HW_VAR_RF_STATE: - *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; - break; - case HW_VAR_FWLPS_RF_ON:{ - enum rf_pwrstate rfstate; - u32 val_rcr; - - rtlpriv->cfg->ops->get_hw_reg(hw, - HW_VAR_RF_STATE, - (u8 *)(&rfstate)); - if (rfstate == ERFOFF) { - *((bool *)(val)) = true; - } else { - val_rcr = rtl_read_dword(rtlpriv, REG_RCR); - val_rcr &= 0x00070000; - if (val_rcr) - *((bool *)(val)) = false; - else - *((bool *)(val)) = true; - } - break; - } - case HW_VAR_FW_PSMODE_STATUS: - *((bool *)(val)) = ppsc->fw_current_inpsmode; - break; - case HW_VAR_CORRECT_TSF:{ - u64 tsf; - u32 *ptsf_low = (u32 *)&tsf; - u32 *ptsf_high = ((u32 *)&tsf) + 1; - - *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); - *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - - *((u64 *)(val)) = tsf; - - break; - } - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } -} - -void rtl8723e_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 idx; - - switch (variable) { - case HW_VAR_ETHER_ADDR:{ - for (idx = 0; idx < ETH_ALEN; idx++) { - rtl_write_byte(rtlpriv, (REG_MACID + idx), - val[idx]); - } - break; - } - case HW_VAR_BASIC_RATE:{ - u16 b_rate_cfg = ((u16 *)val)[0]; - u8 rate_index = 0; - - b_rate_cfg = b_rate_cfg & 0x15f; - b_rate_cfg |= 0x01; - rtl_write_byte(rtlpriv, REG_RRSR, b_rate_cfg & 0xff); - rtl_write_byte(rtlpriv, REG_RRSR + 1, - (b_rate_cfg >> 8) & 0xff); - while (b_rate_cfg > 0x1) { - b_rate_cfg = (b_rate_cfg >> 1); - rate_index++; - } - rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, - rate_index); - break; - } - case HW_VAR_BSSID:{ - for (idx = 0; idx < ETH_ALEN; idx++) { - rtl_write_byte(rtlpriv, (REG_BSSID + idx), - val[idx]); - } - break; - } - case HW_VAR_SIFS:{ - rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); - rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); - - rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); - rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); - - if (!mac->ht_enable) - rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, - 0x0e0e); - else - rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, - *((u16 *)val)); - break; - } - case HW_VAR_SLOT_TIME:{ - u8 e_aci; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "HW_VAR_SLOT_TIME %x\n", val[0]); - - rtl_write_byte(rtlpriv, REG_SLOT, val[0]); - - for (e_aci = 0; e_aci < AC_MAX; e_aci++) { - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AC_PARAM, - (u8 *)(&e_aci)); - } - break; - } - case HW_VAR_ACK_PREAMBLE:{ - u8 reg_tmp; - u8 short_preamble = (bool)(*(u8 *)val); - - reg_tmp = (mac->cur_40_prime_sc) << 5; - if (short_preamble) - reg_tmp |= 0x80; - - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp); - break; - } - case HW_VAR_AMPDU_MIN_SPACE:{ - u8 min_spacing_to_set; - u8 sec_min_space; - - min_spacing_to_set = *((u8 *)val); - if (min_spacing_to_set <= 7) { - sec_min_space = 0; - - if (min_spacing_to_set < sec_min_space) - min_spacing_to_set = sec_min_space; - - mac->min_space_cfg = ((mac->min_space_cfg & - 0xf8) | - min_spacing_to_set); - - *val = min_spacing_to_set; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", - mac->min_space_cfg); - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - } - break; - } - case HW_VAR_SHORTGI_DENSITY:{ - u8 density_to_set; - - density_to_set = *((u8 *)val); - mac->min_space_cfg |= (density_to_set << 3); - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_SHORTGI_DENSITY: %#x\n", - mac->min_space_cfg); - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - - break; - } - case HW_VAR_AMPDU_FACTOR:{ - u8 regtoset_normal[4] = { 0x41, 0xa8, 0x72, 0xb9 }; - u8 regtoset_bt[4] = {0x31, 0x74, 0x42, 0x97}; - u8 factor_toset; - u8 *p_regtoset = NULL; - u8 index = 0; - - if ((rtlpriv->btcoexist.bt_coexistence) && - (rtlpriv->btcoexist.bt_coexist_type == - BT_CSR_BC4)) - p_regtoset = regtoset_bt; - else - p_regtoset = regtoset_normal; - - factor_toset = *((u8 *)val); - if (factor_toset <= 3) { - factor_toset = (1 << (factor_toset + 2)); - if (factor_toset > 0xf) - factor_toset = 0xf; - - for (index = 0; index < 4; index++) { - if ((p_regtoset[index] & 0xf0) > - (factor_toset << 4)) - p_regtoset[index] = - (p_regtoset[index] & 0x0f) | - (factor_toset << 4); - - if ((p_regtoset[index] & 0x0f) > - factor_toset) - p_regtoset[index] = - (p_regtoset[index] & 0xf0) | - (factor_toset); - - rtl_write_byte(rtlpriv, - (REG_AGGLEN_LMT + index), - p_regtoset[index]); - } - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_FACTOR: %#x\n", - factor_toset); - } - break; - } - case HW_VAR_AC_PARAM:{ - u8 e_aci = *((u8 *)val); - - rtl8723_dm_init_edca_turbo(hw); - - if (rtlpci->acm_method != EACMWAY2_SW) - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_ACM_CTRL, - (u8 *)(&e_aci)); - break; - } - case HW_VAR_ACM_CTRL:{ - u8 e_aci = *((u8 *)val); - union aci_aifsn *p_aci_aifsn = - (union aci_aifsn *)(&mac->ac[0].aifs); - u8 acm = p_aci_aifsn->f.acm; - u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); - - acm_ctrl = - acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); - - if (acm) { - switch (e_aci) { - case AC0_BE: - acm_ctrl |= ACMHW_BEQEN; - break; - case AC2_VI: - acm_ctrl |= ACMHW_VIQEN; - break; - case AC3_VO: - acm_ctrl |= ACMHW_VOQEN; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", - acm); - break; - } - } else { - switch (e_aci) { - case AC0_BE: - acm_ctrl &= (~ACMHW_BEQEN); - break; - case AC2_VI: - acm_ctrl &= (~ACMHW_VIQEN); - break; - case AC3_VO: - acm_ctrl &= (~ACMHW_VOQEN); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - } - - RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, - "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", - acm_ctrl); - rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); - break; - } - case HW_VAR_RCR:{ - rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); - rtlpci->receive_config = ((u32 *)(val))[0]; - break; - } - case HW_VAR_RETRY_LIMIT:{ - u8 retry_limit = ((u8 *)(val))[0]; - - rtl_write_word(rtlpriv, REG_RL, - retry_limit << RETRY_LIMIT_SHORT_SHIFT | - retry_limit << RETRY_LIMIT_LONG_SHIFT); - break; - } - case HW_VAR_DUAL_TSF_RST: - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); - break; - case HW_VAR_EFUSE_BYTES: - rtlefuse->efuse_usedbytes = *((u16 *)val); - break; - case HW_VAR_EFUSE_USAGE: - rtlefuse->efuse_usedpercentage = *((u8 *)val); - break; - case HW_VAR_IO_CMD: - rtl8723e_phy_set_io_cmd(hw, (*(enum io_type *)val)); - break; - case HW_VAR_WPA_CONFIG: - rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); - break; - case HW_VAR_SET_RPWM:{ - u8 rpwm_val; - - rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); - udelay(1); - - if (rpwm_val & BIT(7)) { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, - (*(u8 *)val)); - } else { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, - ((*(u8 *)val) | BIT(7))); - } - - break; - } - case HW_VAR_H2C_FW_PWRMODE:{ - u8 psmode = (*(u8 *)val); - - if (psmode != FW_PS_ACTIVE_MODE) - rtl8723e_dm_rf_saving(hw, true); - - rtl8723e_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); - break; - } - case HW_VAR_FW_PSMODE_STATUS: - ppsc->fw_current_inpsmode = *((bool *)val); - break; - case HW_VAR_H2C_FW_JOINBSSRPT:{ - u8 mstatus = (*(u8 *)val); - u8 tmp_regcr, tmp_reg422; - bool b_recover = false; - - if (mstatus == RT_MEDIA_CONNECT) { - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, - NULL); - - tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, - (tmp_regcr | BIT(0))); - - _rtl8723e_set_bcn_ctrl_reg(hw, 0, BIT(3)); - _rtl8723e_set_bcn_ctrl_reg(hw, BIT(4), 0); - - tmp_reg422 = - rtl_read_byte(rtlpriv, - REG_FWHW_TXQ_CTRL + 2); - if (tmp_reg422 & BIT(6)) - b_recover = true; - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, - tmp_reg422 & (~BIT(6))); - - rtl8723e_set_fw_rsvdpagepkt(hw, 0); - - _rtl8723e_set_bcn_ctrl_reg(hw, BIT(3), 0); - _rtl8723e_set_bcn_ctrl_reg(hw, 0, BIT(4)); - - if (b_recover) { - rtl_write_byte(rtlpriv, - REG_FWHW_TXQ_CTRL + 2, - tmp_reg422); - } - - rtl_write_byte(rtlpriv, REG_CR + 1, - (tmp_regcr & ~(BIT(0)))); - } - rtl8723e_set_fw_joinbss_report_cmd(hw, (*(u8 *)val)); - - break; - } - case HW_VAR_H2C_FW_P2P_PS_OFFLOAD:{ - rtl8723e_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); - break; - } - case HW_VAR_AID:{ - u16 u2btmp; - - u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); - u2btmp &= 0xC000; - rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, - (u2btmp | mac->assoc_id)); - - break; - } - case HW_VAR_CORRECT_TSF:{ - u8 btype_ibss = ((u8 *)(val))[0]; - - if (btype_ibss) - _rtl8723e_stop_tx_beacon(hw); - - _rtl8723e_set_bcn_ctrl_reg(hw, 0, BIT(3)); - - rtl_write_dword(rtlpriv, REG_TSFTR, - (u32)(mac->tsf & 0xffffffff)); - rtl_write_dword(rtlpriv, REG_TSFTR + 4, - (u32)((mac->tsf >> 32) & 0xffffffff)); - - _rtl8723e_set_bcn_ctrl_reg(hw, BIT(3), 0); - - if (btype_ibss) - _rtl8723e_resume_tx_beacon(hw); - - break; - } - case HW_VAR_FW_LPS_ACTION:{ - bool b_enter_fwlps = *((bool *)val); - u8 rpwm_val, fw_pwrmode; - bool fw_current_inps; - - if (b_enter_fwlps) { - rpwm_val = 0x02; /* RF off */ - fw_current_inps = true; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); - - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - } else { - rpwm_val = 0x0C; /* RF on */ - fw_pwrmode = FW_PS_ACTIVE_MODE; - fw_current_inps = false; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); - - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - } - break; - } - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } -} - -static bool _rtl8723e_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool status = true; - long count = 0; - u32 value = _LLT_INIT_ADDR(address) | - _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); - - rtl_write_dword(rtlpriv, REG_LLT_INIT, value); - - do { - value = rtl_read_dword(rtlpriv, REG_LLT_INIT); - if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) - break; - - if (count > POLLING_LLT_THRESHOLD) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to polling write LLT done at address %d!\n", - address); - status = false; - break; - } - } while (++count); - - return status; -} - -static bool _rtl8723e_llt_table_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - unsigned short i; - u8 txpktbuf_bndy; - u8 maxpage; - bool status; - u8 ubyte; - -#if LLT_CONFIG == 1 - maxpage = 255; - txpktbuf_bndy = 252; -#elif LLT_CONFIG == 2 - maxpage = 127; - txpktbuf_bndy = 124; -#elif LLT_CONFIG == 3 - maxpage = 255; - txpktbuf_bndy = 174; -#elif LLT_CONFIG == 4 - maxpage = 255; - txpktbuf_bndy = 246; -#elif LLT_CONFIG == 5 - maxpage = 255; - txpktbuf_bndy = 246; -#endif - - rtl_write_byte(rtlpriv, REG_CR, 0x8B); - -#if LLT_CONFIG == 1 - rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x1c); - rtl_write_dword(rtlpriv, REG_RQPN, 0x80a71c1c); -#elif LLT_CONFIG == 2 - rtl_write_dword(rtlpriv, REG_RQPN, 0x845B1010); -#elif LLT_CONFIG == 3 - rtl_write_dword(rtlpriv, REG_RQPN, 0x84838484); -#elif LLT_CONFIG == 4 - rtl_write_dword(rtlpriv, REG_RQPN, 0x80bd1c1c); -#elif LLT_CONFIG == 5 - rtl_write_word(rtlpriv, REG_RQPN_NPQ, 0x0000); - - rtl_write_dword(rtlpriv, REG_RQPN, 0x80ac1c29); - rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x03); -#endif - - rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (0x27FF0000 | txpktbuf_bndy)); - rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_PBP, 0x11); - rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); - - for (i = 0; i < (txpktbuf_bndy - 1); i++) { - status = _rtl8723e_llt_write(hw, i, i + 1); - if (true != status) - return status; - } - - status = _rtl8723e_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); - if (true != status) - return status; - - for (i = txpktbuf_bndy; i < maxpage; i++) { - status = _rtl8723e_llt_write(hw, i, (i + 1)); - if (true != status) - return status; - } - - status = _rtl8723e_llt_write(hw, maxpage, txpktbuf_bndy); - if (true != status) - return status; - - rtl_write_byte(rtlpriv, REG_CR, 0xff); - ubyte = rtl_read_byte(rtlpriv, REG_RQPN + 3); - rtl_write_byte(rtlpriv, REG_RQPN + 3, ubyte | BIT(7)); - - return true; -} - -static void _rtl8723e_gen_refresh_led_state(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pled0 = &pcipriv->ledctl.sw_led0; - - if (rtlpriv->rtlhal.up_first_time) - return; - - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtl8723e_sw_led_on(hw, pled0); - else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - rtl8723e_sw_led_on(hw, pled0); - else - rtl8723e_sw_led_off(hw, pled0); -} - -static bool _rtl8712e_init_mac(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - unsigned char bytetmp; - unsigned short wordtmp; - u16 retry = 0; - u16 tmpu2b; - bool mac_func_enable; - - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); - bytetmp = rtl_read_byte(rtlpriv, REG_CR); - if (bytetmp == 0xFF) - mac_func_enable = true; - else - mac_func_enable = false; - - /* HW Power on sequence */ - if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, Rtl8723_NIC_ENABLE_FLOW)) - return false; - - bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG+2); - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG+2, bytetmp | BIT(4)); - - /* eMAC time out function enable, 0x369[7]=1 */ - bytetmp = rtl_read_byte(rtlpriv, 0x369); - rtl_write_byte(rtlpriv, 0x369, bytetmp | BIT(7)); - - /* ePHY reg 0x1e bit[4]=1 using MDIO interface, - * we should do this before Enabling ASPM backdoor. - */ - do { - rtl_write_word(rtlpriv, 0x358, 0x5e); - udelay(100); - rtl_write_word(rtlpriv, 0x356, 0xc280); - rtl_write_word(rtlpriv, 0x354, 0xc290); - rtl_write_word(rtlpriv, 0x358, 0x3e); - udelay(100); - rtl_write_word(rtlpriv, 0x358, 0x5e); - udelay(100); - tmpu2b = rtl_read_word(rtlpriv, 0x356); - retry++; - } while (tmpu2b != 0xc290 && retry < 100); - - if (retry >= 100) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "InitMAC(): ePHY configure fail!!!\n"); - return false; - } - - rtl_write_word(rtlpriv, REG_CR, 0x2ff); - rtl_write_word(rtlpriv, REG_CR + 1, 0x06); - - if (!mac_func_enable) { - if (!_rtl8723e_llt_table_init(hw)) - return false; - } - - rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); - rtl_write_byte(rtlpriv, REG_HISRE, 0xff); - - rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x27ff); - - wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); - wordtmp &= 0xf; - wordtmp |= 0xF771; - rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); - - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xFFFF); - rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); - - rtl_write_byte(rtlpriv, 0x4d0, 0x0); - - rtl_write_dword(rtlpriv, REG_BCNQ_DESA, - ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_MGQ_DESA, - (u64) rtlpci->tx_ring[MGNT_QUEUE].dma & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VOQ_DESA, - (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VIQ_DESA, - (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_BEQ_DESA, - (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_BKQ_DESA, - (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_HQ_DESA, - (u64) rtlpci->tx_ring[HIGH_QUEUE].dma & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_RX_DESA, - (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma & - DMA_BIT_MASK(32)); - - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x74); - - rtl_write_dword(rtlpriv, REG_INT_MIG, 0); - - bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6)); - do { - retry++; - bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); - } while ((retry < 200) && (bytetmp & BIT(7))); - - _rtl8723e_gen_refresh_led_state(hw); - - rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); - - return true; -} - -static void _rtl8723e_hw_configure(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 reg_bw_opmode; - u32 reg_ratr, reg_prsr; - - reg_bw_opmode = BW_OPMODE_20MHZ; - reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | - RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; - reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - - rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8); - - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - - rtl_write_dword(rtlpriv, REG_RRSR, reg_prsr); - - rtl_write_byte(rtlpriv, REG_SLOT, 0x09); - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0); - - rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80); - - rtl_write_word(rtlpriv, REG_RL, 0x0707); - - rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802); - - rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); - - rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); - rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); - - if ((rtlpriv->btcoexist.bt_coexistence) && - (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4)) - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x97427431); - else - rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); - - rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); - - rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff); - - rtlpci->reg_bcn_ctrl_val = 0x1f; - rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); - - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - - rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); - rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); - - if ((rtlpriv->btcoexist.bt_coexistence) && - (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4)) { - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0402); - } else { - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); - } - - if ((rtlpriv->btcoexist.bt_coexistence) && - (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4)) - rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); - else - rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x086666); - - rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); - - rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010); - rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010); - - rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010); - - rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010); - - rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff); - rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff); - - rtl_write_dword(rtlpriv, 0x394, 0x1); -} - -static void _rtl8723e_enable_aspm_back_door(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - rtl_write_byte(rtlpriv, 0x34b, 0x93); - rtl_write_word(rtlpriv, 0x350, 0x870c); - rtl_write_byte(rtlpriv, 0x352, 0x1); - - if (ppsc->support_backdoor) - rtl_write_byte(rtlpriv, 0x349, 0x1b); - else - rtl_write_byte(rtlpriv, 0x349, 0x03); - - rtl_write_word(rtlpriv, 0x350, 0x2718); - rtl_write_byte(rtlpriv, 0x352, 0x1); -} - -void rtl8723e_enable_hw_security_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 sec_reg_value; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", - rtlpriv->sec.pairwise_enc_algorithm, - rtlpriv->sec.group_enc_algorithm); - - if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "not open hw encryption\n"); - return; - } - - sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; - - if (rtlpriv->sec.use_defaultkey) { - sec_reg_value |= SCR_TXUSEDK; - sec_reg_value |= SCR_RXUSEDK; - } - - sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); - - rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "The SECR-value %x\n", sec_reg_value); - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); - -} - -int rtl8723e_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - bool rtstatus = true; - int err; - u8 tmp_u1b; - unsigned long flags; - - rtlpriv->rtlhal.being_init_adapter = true; - /* As this function can take a very long time (up to 350 ms) - * and can be called with irqs disabled, reenable the irqs - * to let the other devices continue being serviced. - * - * It is safe doing so since our own interrupts will only be enabled - * in a subsequent step. - */ - local_save_flags(flags); - local_irq_enable(); - rtlhal->fw_ready = false; - - rtlpriv->intf_ops->disable_aspm(hw); - rtstatus = _rtl8712e_init_mac(hw); - if (rtstatus != true) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); - err = 1; - goto exit; - } - - err = rtl8723_download_fw(hw, false, FW_8723A_POLLING_TIMEOUT_COUNT); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Failed to download FW. Init HW without FW now..\n"); - err = 1; - goto exit; - } - rtlhal->fw_ready = true; - - rtlhal->last_hmeboxnum = 0; - rtl8723e_phy_mac_config(hw); - /* because last function modify RCR, so we update - * rcr var here, or TP will unstable for receive_config - * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx - * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 - */ - rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); - rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - - rtl8723e_phy_bb_config(hw); - rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; - rtl8723e_phy_rf_config(hw); - if (IS_VENDOR_UMC_A_CUT(rtlhal->version)) { - rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00); - } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { - rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE); - rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31); - rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425); - rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201); - } - rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); - rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); - _rtl8723e_hw_configure(hw); - rtl_cam_reset_all_entry(hw); - rtl8723e_enable_hw_security_config(hw); - - ppsc->rfpwr_state = ERFON; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); - _rtl8723e_enable_aspm_back_door(hw); - rtlpriv->intf_ops->enable_aspm(hw); - - rtl8723e_bt_hw_init(hw); - - if (ppsc->rfpwr_state == ERFON) { - rtl8723e_phy_set_rfpath_switch(hw, 1); - if (rtlphy->iqk_initialized) { - rtl8723e_phy_iq_calibrate(hw, true); - } else { - rtl8723e_phy_iq_calibrate(hw, false); - rtlphy->iqk_initialized = true; - } - - rtl8723e_dm_check_txpower_tracking(hw); - rtl8723e_phy_lc_calibrate(hw); - } - - tmp_u1b = efuse_read_1byte(hw, 0x1FA); - if (!(tmp_u1b & BIT(0))) { - rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0F, 0x05); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "PA BIAS path A\n"); - } - - if (!(tmp_u1b & BIT(4))) { - tmp_u1b = rtl_read_byte(rtlpriv, 0x16); - tmp_u1b &= 0x0F; - rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x80); - udelay(10); - rtl_write_byte(rtlpriv, 0x16, tmp_u1b | 0x90); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "under 1.5V\n"); - } - rtl8723e_dm_init(hw); -exit: - local_irq_restore(flags); - rtlpriv->rtlhal.being_init_adapter = false; - return err; -} - -static enum version_8723e _rtl8723e_read_chip_version(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - enum version_8723e version = 0x0000; - u32 value32; - - value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); - if (value32 & TRP_VAUX_EN) { - version = (enum version_8723e)(version | - ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); - /* RTL8723 with BT function. */ - version = (enum version_8723e)(version | - ((value32 & BT_FUNC) ? CHIP_8723 : 0)); - - } else { - /* Normal mass production chip. */ - version = (enum version_8723e) NORMAL_CHIP; - version = (enum version_8723e)(version | - ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); - /* RTL8723 with BT function. */ - version = (enum version_8723e)(version | - ((value32 & BT_FUNC) ? CHIP_8723 : 0)); - if (IS_CHIP_VENDOR_UMC(version)) - version = (enum version_8723e)(version | - ((value32 & CHIP_VER_RTL_MASK)));/* IC version (CUT) */ - if (IS_8723_SERIES(version)) { - value32 = rtl_read_dword(rtlpriv, REG_GPIO_OUTSTS); - /* ROM code version. */ - version = (enum version_8723e)(version | - ((value32 & RF_RL_ID)>>20)); - } - } - - if (IS_8723_SERIES(version)) { - value32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL); - rtlphy->polarity_ctl = ((value32 & WL_HWPDN_SL) ? - RT_POLARITY_HIGH_ACT : - RT_POLARITY_LOW_ACT); - } - switch (version) { - case VERSION_TEST_UMC_CHIP_8723: - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Chip Version ID: VERSION_TEST_UMC_CHIP_8723.\n"); - break; - case VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT: - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Chip Version ID: VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT.\n"); - break; - case VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT: - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Chip Version ID: VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT.\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Chip Version ID: Unknown. Bug?\n"); - break; - } - - if (IS_8723_SERIES(version)) - rtlphy->rf_type = RF_1T1R; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Chip RF Type: %s\n", - (rtlphy->rf_type == RF_2T2R) ? "RF_2T2R" : "RF_1T1R"); - - return version; -} - -static int _rtl8723e_set_media_status(struct ieee80211_hw *hw, - enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bt_msr = rtl_read_byte(rtlpriv, MSR) & 0xfc; - enum led_ctl_mode ledaction = LED_CTL_NO_LINK; - u8 mode = MSR_NOLINK; - - rtl_write_dword(rtlpriv, REG_BCN_CTRL, 0); - RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD, - "clear 0x550 when set HW_VAR_MEDIA_STATUS\n"); - - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - mode = MSR_NOLINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to NO LINK!\n"); - break; - case NL80211_IFTYPE_ADHOC: - mode = MSR_ADHOC; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to Ad Hoc!\n"); - break; - case NL80211_IFTYPE_STATION: - mode = MSR_INFRA; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to STA!\n"); - break; - case NL80211_IFTYPE_AP: - mode = MSR_AP; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to AP!\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Network type %d not support!\n", type); - return 1; - break; - } - - /* MSR_INFRA == Link in infrastructure network; - * MSR_ADHOC == Link in ad hoc network; - * Therefore, check link state is necessary. - * - * MSR_AP == AP mode; link state is not cared here. - */ - if (mode != MSR_AP && - rtlpriv->mac80211.link_state < MAC80211_LINKED) { - mode = MSR_NOLINK; - ledaction = LED_CTL_NO_LINK; - } - if (mode == MSR_NOLINK || mode == MSR_INFRA) { - _rtl8723e_stop_tx_beacon(hw); - _rtl8723e_enable_bcn_sub_func(hw); - } else if (mode == MSR_ADHOC || mode == MSR_AP) { - _rtl8723e_resume_tx_beacon(hw); - _rtl8723e_disable_bcn_sub_func(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", - mode); - } - - rtl_write_byte(rtlpriv, MSR, bt_msr | mode); - rtlpriv->cfg->ops->led_control(hw, ledaction); - if (mode == MSR_AP) - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); - else - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); - return 0; -} - -void rtl8723e_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u32 reg_rcr = rtlpci->receive_config; - - if (rtlpriv->psc.rfpwr_state != ERFON) - return; - - if (check_bssid) { - reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *)(®_rcr)); - _rtl8723e_set_bcn_ctrl_reg(hw, 0, BIT(4)); - } else if (!check_bssid) { - reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); - _rtl8723e_set_bcn_ctrl_reg(hw, BIT(4), 0); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_RCR, (u8 *)(®_rcr)); - } -} - -int rtl8723e_set_network_type(struct ieee80211_hw *hw, - enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (_rtl8723e_set_media_status(hw, type)) - return -EOPNOTSUPP; - - if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { - if (type != NL80211_IFTYPE_AP) - rtl8723e_set_check_bssid(hw, true); - } else { - rtl8723e_set_check_bssid(hw, false); - } - - return 0; -} - -/* don't set REG_EDCA_BE_PARAM here - * because mac80211 will send pkt when scan - */ -void rtl8723e_set_qos(struct ieee80211_hw *hw, int aci) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl8723_dm_init_edca_turbo(hw); - switch (aci) { - case AC1_BK: - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); - break; - case AC0_BE: - break; - case AC2_VI: - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); - break; - case AC3_VO: - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); - break; - default: - RT_ASSERT(false, "invalid aci: %d !\n", aci); - break; - } -} - -void rtl8723e_enable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, 0x3a8, rtlpci->irq_mask[0] & 0xFFFFFFFF); - rtl_write_dword(rtlpriv, 0x3ac, rtlpci->irq_mask[1] & 0xFFFFFFFF); - rtlpci->irq_enabled = true; -} - -void rtl8723e_disable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - rtl_write_dword(rtlpriv, 0x3a8, IMR8190_DISABLED); - rtl_write_dword(rtlpriv, 0x3ac, IMR8190_DISABLED); - rtlpci->irq_enabled = false; - /*synchronize_irq(rtlpci->pdev->irq);*/ -} - -static void _rtl8723e_poweroff_adapter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 u1b_tmp; - - /* Combo (PCIe + USB) Card and PCIe-MF Card */ - /* 1. Run LPS WL RFOFF flow */ - rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, Rtl8723_NIC_LPS_ENTER_FLOW); - - /* 2. 0x1F[7:0] = 0 */ - /* turn off RF */ - rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); - if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && - rtlhal->fw_ready) { - rtl8723ae_firmware_selfreset(hw); - } - - /* Reset MCU. Suggested by Filen. */ - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); - - /* g. MCUFWDL 0x80[1:0]=0 */ - /* reset MCU ready status */ - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); - - /* HW card disable configuration. */ - rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, Rtl8723_NIC_DISABLE_FLOW); - - /* Reset MCU IO Wrapper */ - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, u1b_tmp | BIT(0)); - - /* 7. RSV_CTRL 0x1C[7:0] = 0x0E */ - /* lock ISO/CLK/Power control register */ - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); -} - -void rtl8723e_card_disable(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - enum nl80211_iftype opmode; - - mac->link_state = MAC80211_NOLINK; - opmode = NL80211_IFTYPE_UNSPECIFIED; - _rtl8723e_set_media_status(hw, opmode); - if (rtlpriv->rtlhal.driver_is_goingto_unload || - ppsc->rfoff_reason > RF_CHANGE_BY_PS) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - _rtl8723e_poweroff_adapter(hw); - - /* after power off we should do iqk again */ - rtlpriv->phy.iqk_initialized = false; -} - -void rtl8723e_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - *p_inta = rtl_read_dword(rtlpriv, 0x3a0) & rtlpci->irq_mask[0]; - rtl_write_dword(rtlpriv, 0x3a0, *p_inta); -} - -void rtl8723e_set_beacon_related_registers(struct ieee80211_hw *hw) -{ - - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval, atim_window; - - bcn_interval = mac->beacon_interval; - atim_window = 2; /*FIX MERGE */ - rtl8723e_disable_interrupt(hw); - rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); - rtl_write_byte(rtlpriv, 0x606, 0x30); - rtl8723e_enable_interrupt(hw); -} - -void rtl8723e_set_beacon_interval(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval = mac->beacon_interval; - - RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, - "beacon_interval:%d\n", bcn_interval); - rtl8723e_disable_interrupt(hw); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - rtl8723e_enable_interrupt(hw); -} - -void rtl8723e_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, - "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); - - if (add_msr) - rtlpci->irq_mask[0] |= add_msr; - if (rm_msr) - rtlpci->irq_mask[0] &= (~rm_msr); - rtl8723e_disable_interrupt(hw); - rtl8723e_enable_interrupt(hw); -} - -static u8 _rtl8723e_get_chnl_group(u8 chnl) -{ - u8 group; - - if (chnl < 3) - group = 0; - else if (chnl < 9) - group = 1; - else - group = 2; - return group; -} - -static void _rtl8723e_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 rf_path, index, tempval; - u16 i; - - for (rf_path = 0; rf_path < 1; rf_path++) { - for (i = 0; i < 3; i++) { - if (!autoload_fail) { - rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][i] = - hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i]; - rtlefuse->eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = - hwinfo[EEPROM_TXPOWERHT40_1S + rf_path * 3 + i]; - } else { - rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][i] = - EEPROM_DEFAULT_TXPOWERLEVEL; - rtlefuse->eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = - EEPROM_DEFAULT_TXPOWERLEVEL; - } - } - } - - for (i = 0; i < 3; i++) { - if (!autoload_fail) - tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i]; - else - tempval = EEPROM_DEFAULT_HT40_2SDIFF; - rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] = - (tempval & 0xf); - rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] = - ((tempval & 0xf0) >> 4); - } - - for (rf_path = 0; rf_path < 2; rf_path++) - for (i = 0; i < 3; i++) - RTPRINT(rtlpriv, FINIT, INIT_EEPROM, - "RF(%d) EEPROM CCK Area(%d) = 0x%x\n", rf_path, - i, rtlefuse->eeprom_chnlarea_txpwr_cck - [rf_path][i]); - for (rf_path = 0; rf_path < 2; rf_path++) - for (i = 0; i < 3; i++) - RTPRINT(rtlpriv, FINIT, INIT_EEPROM, - "RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n", - rf_path, i, - rtlefuse->eeprom_chnlarea_txpwr_ht40_1s - [rf_path][i]); - for (rf_path = 0; rf_path < 2; rf_path++) - for (i = 0; i < 3; i++) - RTPRINT(rtlpriv, FINIT, INIT_EEPROM, - "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", - rf_path, i, - rtlefuse->eprom_chnl_txpwr_ht40_2sdf - [rf_path][i]); - - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < 14; i++) { - index = _rtl8723e_get_chnl_group((u8)i); - - rtlefuse->txpwrlevel_cck[rf_path][i] = - rtlefuse->eeprom_chnlarea_txpwr_cck - [rf_path][index]; - rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = - rtlefuse->eeprom_chnlarea_txpwr_ht40_1s - [rf_path][index]; - - if ((rtlefuse->eeprom_chnlarea_txpwr_ht40_1s - [rf_path][index] - - rtlefuse->eprom_chnl_txpwr_ht40_2sdf - [rf_path][index]) > 0) { - rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = - rtlefuse->eeprom_chnlarea_txpwr_ht40_1s - [rf_path][index] - - rtlefuse->eprom_chnl_txpwr_ht40_2sdf - [rf_path][index]; - } else { - rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0; - } - } - - for (i = 0; i < 14; i++) { - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n", - rf_path, i, - rtlefuse->txpwrlevel_cck[rf_path][i], - rtlefuse->txpwrlevel_ht40_1s[rf_path][i], - rtlefuse->txpwrlevel_ht40_2s[rf_path][i]); - } - } - - for (i = 0; i < 3; i++) { - if (!autoload_fail) { - rtlefuse->eeprom_pwrlimit_ht40[i] = - hwinfo[EEPROM_TXPWR_GROUP + i]; - rtlefuse->eeprom_pwrlimit_ht20[i] = - hwinfo[EEPROM_TXPWR_GROUP + 3 + i]; - } else { - rtlefuse->eeprom_pwrlimit_ht40[i] = 0; - rtlefuse->eeprom_pwrlimit_ht20[i] = 0; - } - } - - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < 14; i++) { - index = _rtl8723e_get_chnl_group((u8)i); - - if (rf_path == RF90_PATH_A) { - rtlefuse->pwrgroup_ht20[rf_path][i] = - (rtlefuse->eeprom_pwrlimit_ht20[index] & 0xf); - rtlefuse->pwrgroup_ht40[rf_path][i] = - (rtlefuse->eeprom_pwrlimit_ht40[index] & 0xf); - } else if (rf_path == RF90_PATH_B) { - rtlefuse->pwrgroup_ht20[rf_path][i] = - ((rtlefuse->eeprom_pwrlimit_ht20[index] & - 0xf0) >> 4); - rtlefuse->pwrgroup_ht40[rf_path][i] = - ((rtlefuse->eeprom_pwrlimit_ht40[index] & - 0xf0) >> 4); - } - - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-%d pwrgroup_ht20[%d] = 0x%x\n", rf_path, i, - rtlefuse->pwrgroup_ht20[rf_path][i]); - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-%d pwrgroup_ht40[%d] = 0x%x\n", rf_path, i, - rtlefuse->pwrgroup_ht40[rf_path][i]); - } - } - - for (i = 0; i < 14; i++) { - index = _rtl8723e_get_chnl_group((u8)i); - - if (!autoload_fail) - tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index]; - else - tempval = EEPROM_DEFAULT_HT20_DIFF; - - rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); - rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = - ((tempval >> 4) & 0xF); - - if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] & BIT(3)) - rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] |= 0xF0; - - if (rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] & BIT(3)) - rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] |= 0xF0; - - index = _rtl8723e_get_chnl_group((u8)i); - - if (!autoload_fail) - tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index]; - else - tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; - - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = (tempval & 0xF); - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = - ((tempval >> 4) & 0xF); - } - - rtlefuse->legacy_ht_txpowerdiff = - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; - - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i, - rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i, - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i, - rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); - for (i = 0; i < 14; i++) - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i, - rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); - - if (!autoload_fail) - rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); - else - rtlefuse->eeprom_regulatory = 0; - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); - - if (!autoload_fail) - rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; - else - rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; - - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "TSSI_A = 0x%x, TSSI_B = 0x%x\n", - rtlefuse->eeprom_tssi[RF90_PATH_A], - rtlefuse->eeprom_tssi[RF90_PATH_B]); - - if (!autoload_fail) - tempval = hwinfo[EEPROM_THERMAL_METER]; - else - tempval = EEPROM_DEFAULT_THERMALMETER; - rtlefuse->eeprom_thermalmeter = (tempval & 0x1f); - - if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail) - rtlefuse->apk_thermalmeterignore = true; - - rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); -} - -static void _rtl8723e_read_adapter_info(struct ieee80211_hw *hw, - bool b_pseudo_test) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u16 i, usvalue; - u8 hwinfo[HWSET_MAX_SIZE]; - u16 eeprom_id; - - if (b_pseudo_test) { - /* need add */ - return; - } - if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { - rtl_efuse_shadow_map_update(hw); - - memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], - HWSET_MAX_SIZE); - } else if (rtlefuse->epromtype == EEPROM_93C46) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "RTL819X Not boot from eeprom, check it !!"); - } - - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP\n", - hwinfo, HWSET_MAX_SIZE); - - eeprom_id = *((u16 *)&hwinfo[0]); - if (eeprom_id != RTL8190_EEPROM_ID) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "EEPROM ID(%#x) is invalid!!\n", eeprom_id); - rtlefuse->autoload_failflag = true; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - } - - if (rtlefuse->autoload_failflag) - return; - - rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; - rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; - rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; - rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROMId = 0x%4x\n", eeprom_id); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); - - for (i = 0; i < 6; i += 2) { - usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; - *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "dev_addr: %pM\n", rtlefuse->dev_addr); - - _rtl8723e_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, - hwinfo); - - rtl8723e_read_bt_coexist_info_from_hwpg(hw, - rtlefuse->autoload_failflag, hwinfo); - - rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; - rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; - rtlefuse->txpwr_fromeprom = true; - rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); - - /* set channel paln to world wide 13 */ - rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; - - if (rtlhal->oem_id == RT_CID_DEFAULT) { - switch (rtlefuse->eeprom_oemid) { - case EEPROM_CID_DEFAULT: - if (rtlefuse->eeprom_did == 0x8176) { - if (CHK_SVID_SMID(0x10EC, 0x6151) || - CHK_SVID_SMID(0x10EC, 0x6152) || - CHK_SVID_SMID(0x10EC, 0x6154) || - CHK_SVID_SMID(0x10EC, 0x6155) || - CHK_SVID_SMID(0x10EC, 0x6177) || - CHK_SVID_SMID(0x10EC, 0x6178) || - CHK_SVID_SMID(0x10EC, 0x6179) || - CHK_SVID_SMID(0x10EC, 0x6180) || - CHK_SVID_SMID(0x10EC, 0x7151) || - CHK_SVID_SMID(0x10EC, 0x7152) || - CHK_SVID_SMID(0x10EC, 0x7154) || - CHK_SVID_SMID(0x10EC, 0x7155) || - CHK_SVID_SMID(0x10EC, 0x7177) || - CHK_SVID_SMID(0x10EC, 0x7178) || - CHK_SVID_SMID(0x10EC, 0x7179) || - CHK_SVID_SMID(0x10EC, 0x7180) || - CHK_SVID_SMID(0x10EC, 0x8151) || - CHK_SVID_SMID(0x10EC, 0x8152) || - CHK_SVID_SMID(0x10EC, 0x8154) || - CHK_SVID_SMID(0x10EC, 0x8155) || - CHK_SVID_SMID(0x10EC, 0x8181) || - CHK_SVID_SMID(0x10EC, 0x8182) || - CHK_SVID_SMID(0x10EC, 0x8184) || - CHK_SVID_SMID(0x10EC, 0x8185) || - CHK_SVID_SMID(0x10EC, 0x9151) || - CHK_SVID_SMID(0x10EC, 0x9152) || - CHK_SVID_SMID(0x10EC, 0x9154) || - CHK_SVID_SMID(0x10EC, 0x9155) || - CHK_SVID_SMID(0x10EC, 0x9181) || - CHK_SVID_SMID(0x10EC, 0x9182) || - CHK_SVID_SMID(0x10EC, 0x9184) || - CHK_SVID_SMID(0x10EC, 0x9185)) - rtlhal->oem_id = RT_CID_TOSHIBA; - else if (rtlefuse->eeprom_svid == 0x1025) - rtlhal->oem_id = RT_CID_819X_ACER; - else if (CHK_SVID_SMID(0x10EC, 0x6191) || - CHK_SVID_SMID(0x10EC, 0x6192) || - CHK_SVID_SMID(0x10EC, 0x6193) || - CHK_SVID_SMID(0x10EC, 0x7191) || - CHK_SVID_SMID(0x10EC, 0x7192) || - CHK_SVID_SMID(0x10EC, 0x7193) || - CHK_SVID_SMID(0x10EC, 0x8191) || - CHK_SVID_SMID(0x10EC, 0x8192) || - CHK_SVID_SMID(0x10EC, 0x8193) || - CHK_SVID_SMID(0x10EC, 0x9191) || - CHK_SVID_SMID(0x10EC, 0x9192) || - CHK_SVID_SMID(0x10EC, 0x9193)) - rtlhal->oem_id = RT_CID_819X_SAMSUNG; - else if (CHK_SVID_SMID(0x10EC, 0x8195) || - CHK_SVID_SMID(0x10EC, 0x9195) || - CHK_SVID_SMID(0x10EC, 0x7194) || - CHK_SVID_SMID(0x10EC, 0x8200) || - CHK_SVID_SMID(0x10EC, 0x8201) || - CHK_SVID_SMID(0x10EC, 0x8202) || - CHK_SVID_SMID(0x10EC, 0x9200)) - rtlhal->oem_id = RT_CID_819X_LENOVO; - else if (CHK_SVID_SMID(0x10EC, 0x8197) || - CHK_SVID_SMID(0x10EC, 0x9196)) - rtlhal->oem_id = RT_CID_819X_CLEVO; - else if (CHK_SVID_SMID(0x1028, 0x8194) || - CHK_SVID_SMID(0x1028, 0x8198) || - CHK_SVID_SMID(0x1028, 0x9197) || - CHK_SVID_SMID(0x1028, 0x9198)) - rtlhal->oem_id = RT_CID_819X_DELL; - else if (CHK_SVID_SMID(0x103C, 0x1629)) - rtlhal->oem_id = RT_CID_819X_HP; - else if (CHK_SVID_SMID(0x1A32, 0x2315)) - rtlhal->oem_id = RT_CID_819X_QMI; - else if (CHK_SVID_SMID(0x10EC, 0x8203)) - rtlhal->oem_id = RT_CID_819X_PRONETS; - else if (CHK_SVID_SMID(0x1043, 0x84B5)) - rtlhal->oem_id = - RT_CID_819X_EDIMAX_ASUS; - else - rtlhal->oem_id = RT_CID_DEFAULT; - } else if (rtlefuse->eeprom_did == 0x8178) { - if (CHK_SVID_SMID(0x10EC, 0x6181) || - CHK_SVID_SMID(0x10EC, 0x6182) || - CHK_SVID_SMID(0x10EC, 0x6184) || - CHK_SVID_SMID(0x10EC, 0x6185) || - CHK_SVID_SMID(0x10EC, 0x7181) || - CHK_SVID_SMID(0x10EC, 0x7182) || - CHK_SVID_SMID(0x10EC, 0x7184) || - CHK_SVID_SMID(0x10EC, 0x7185) || - CHK_SVID_SMID(0x10EC, 0x8181) || - CHK_SVID_SMID(0x10EC, 0x8182) || - CHK_SVID_SMID(0x10EC, 0x8184) || - CHK_SVID_SMID(0x10EC, 0x8185) || - CHK_SVID_SMID(0x10EC, 0x9181) || - CHK_SVID_SMID(0x10EC, 0x9182) || - CHK_SVID_SMID(0x10EC, 0x9184) || - CHK_SVID_SMID(0x10EC, 0x9185)) - rtlhal->oem_id = RT_CID_TOSHIBA; - else if (rtlefuse->eeprom_svid == 0x1025) - rtlhal->oem_id = RT_CID_819X_ACER; - else if (CHK_SVID_SMID(0x10EC, 0x8186)) - rtlhal->oem_id = RT_CID_819X_PRONETS; - else if (CHK_SVID_SMID(0x1043, 0x8486)) - rtlhal->oem_id = - RT_CID_819X_EDIMAX_ASUS; - else - rtlhal->oem_id = RT_CID_DEFAULT; - } else { - rtlhal->oem_id = RT_CID_DEFAULT; - } - break; - case EEPROM_CID_TOSHIBA: - rtlhal->oem_id = RT_CID_TOSHIBA; - break; - case EEPROM_CID_CCX: - rtlhal->oem_id = RT_CID_CCX; - break; - case EEPROM_CID_QMI: - rtlhal->oem_id = RT_CID_819X_QMI; - break; - case EEPROM_CID_WHQL: - break; - default: - rtlhal->oem_id = RT_CID_DEFAULT; - break; - - } - } -} - -static void _rtl8723e_hal_customized_behavior(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - pcipriv->ledctl.led_opendrain = true; - switch (rtlhal->oem_id) { - case RT_CID_819X_HP: - pcipriv->ledctl.led_opendrain = true; - break; - case RT_CID_819X_LENOVO: - case RT_CID_DEFAULT: - case RT_CID_TOSHIBA: - case RT_CID_CCX: - case RT_CID_819X_ACER: - case RT_CID_WHQL: - default: - break; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "RT Customized ID: 0x%02X\n", rtlhal->oem_id); -} - -void rtl8723e_read_eeprom_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_u1b; - u32 value32; - - value32 = rtl_read_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST]); - value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0); - rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[EFUSE_TEST], value32); - - rtlhal->version = _rtl8723e_read_chip_version(hw); - - if (get_rf_type(rtlphy) == RF_1T1R) - rtlpriv->dm.rfpath_rxenable[0] = true; - else - rtlpriv->dm.rfpath_rxenable[0] = - rtlpriv->dm.rfpath_rxenable[1] = true; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", - rtlhal->version); - - tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); - if (tmp_u1b & BIT(4)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); - rtlefuse->epromtype = EEPROM_93C46; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); - rtlefuse->epromtype = EEPROM_BOOT_EFUSE; - } - if (tmp_u1b & BIT(5)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - _rtl8723e_read_adapter_info(hw, false); - } else { - rtlefuse->autoload_failflag = true; - _rtl8723e_read_adapter_info(hw, false); - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); - } - _rtl8723e_hal_customized_behavior(hw); -} - -static void rtl8723e_update_hal_rate_table(struct ieee80211_hw *hw, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 ratr_value; - u8 ratr_index = 0; - u8 b_nmode = mac->ht_enable; - u16 shortgi_rate; - u32 tmp_ratr_value; - u8 curtxbw_40mhz = mac->bw_40; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = mac->mode; - u32 ratr_mask; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_value = sta->supp_rates[1] << 4; - else - ratr_value = sta->supp_rates[0]; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_value = 0xfff; - ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - if (ratr_value & 0x0000000c) - ratr_value &= 0x0000000d; - else - ratr_value &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_value &= 0x00000FF5; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - b_nmode = 1; - if (get_rf_type(rtlphy) == RF_1T2R || - get_rf_type(rtlphy) == RF_1T1R) - ratr_mask = 0x000ff005; - else - ratr_mask = 0x0f0ff005; - - ratr_value &= ratr_mask; - break; - default: - if (rtlphy->rf_type == RF_1T2R) - ratr_value &= 0x000ff0ff; - else - ratr_value &= 0x0f0ff0ff; - - break; - } - - if ((rtlpriv->btcoexist.bt_coexistence) && - (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4) && - (rtlpriv->btcoexist.bt_cur_state) && - (rtlpriv->btcoexist.bt_ant_isolation) && - ((rtlpriv->btcoexist.bt_service == BT_SCO) || - (rtlpriv->btcoexist.bt_service == BT_BUSY))) - ratr_value &= 0x0fffcfc0; - else - ratr_value &= 0x0FFFFFFF; - - if (b_nmode && - ((curtxbw_40mhz && curshortgi_40mhz) || - (!curtxbw_40mhz && curshortgi_20mhz))) { - ratr_value |= 0x10000000; - tmp_ratr_value = (ratr_value >> 12); - - for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { - if ((1 << shortgi_rate) & tmp_ratr_value) - break; - } - - shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | - (shortgi_rate << 4) | (shortgi_rate); - } - - rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)); -} - -static void rtl8723e_update_hal_rate_mask(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - u32 ratr_bitmap; - u8 ratr_index; - u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) - ? 1 : 0; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = 0; - bool shortgi = false; - u8 rate_mask[5]; - u8 macid = 0; - /*u8 mimo_ps = IEEE80211_SMPS_OFF;*/ - - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - wirelessmode = sta_entry->wireless_mode; - if (mac->opmode == NL80211_IFTYPE_STATION) - curtxbw_40mhz = mac->bw_40; - else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) - macid = sta->aid + 1; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_bitmap = sta->supp_rates[1] << 4; - else - ratr_bitmap = sta->supp_rates[0]; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_bitmap = 0xfff; - ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - ratr_index = RATR_INX_WIRELESS_B; - if (ratr_bitmap & 0x0000000c) - ratr_bitmap &= 0x0000000d; - else - ratr_bitmap &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_index = RATR_INX_WIRELESS_GB; - - if (rssi_level == 1) - ratr_bitmap &= 0x00000f00; - else if (rssi_level == 2) - ratr_bitmap &= 0x00000ff0; - else - ratr_bitmap &= 0x00000ff5; - break; - case WIRELESS_MODE_A: - ratr_index = RATR_INX_WIRELESS_G; - ratr_bitmap &= 0x00000ff0; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - ratr_index = RATR_INX_WIRELESS_NGB; - if (rtlphy->rf_type == RF_1T2R || - rtlphy->rf_type == RF_1T1R) { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff005; - } - } else { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x0f0f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0f0ff000; - else - ratr_bitmap &= 0x0f0ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x0f0f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0f0ff000; - else - ratr_bitmap &= 0x0f0ff005; - } - } - - if ((curtxbw_40mhz && curshortgi_40mhz) || - (!curtxbw_40mhz && curshortgi_20mhz)) { - if (macid == 0) - shortgi = true; - else if (macid == 1) - shortgi = false; - } - break; - default: - ratr_index = RATR_INX_WIRELESS_NGB; - - if (rtlphy->rf_type == RF_1T2R) - ratr_bitmap &= 0x000ff0ff; - else - ratr_bitmap &= 0x0f0ff0ff; - break; - } - sta_entry->ratr_index = ratr_index; - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "ratr_bitmap :%x\n", ratr_bitmap); - *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | - (ratr_index << 28); - rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n", - ratr_index, ratr_bitmap, - rate_mask[0], rate_mask[1], - rate_mask[2], rate_mask[3], - rate_mask[4]); - rtl8723e_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); -} - -void rtl8723e_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->dm.useramask) - rtl8723e_update_hal_rate_mask(hw, sta, rssi_level); - else - rtl8723e_update_hal_rate_table(hw, sta); -} - -void rtl8723e_update_channel_access_setting(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 sifs_timer; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, &mac->slot_time); - if (!mac->ht_enable) - sifs_timer = 0x0a0a; - else - sifs_timer = 0x1010; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); -} - -bool rtl8723e_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; - u8 u1tmp; - bool b_actuallyset = false; - - if (rtlpriv->rtlhal.being_init_adapter) - return false; - - if (ppsc->swrf_processing) - return false; - - spin_lock(&rtlpriv->locks.rf_ps_lock); - if (ppsc->rfchange_inprogress) { - spin_unlock(&rtlpriv->locks.rf_ps_lock); - return false; - } else { - ppsc->rfchange_inprogress = true; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } - - cur_rfstate = ppsc->rfpwr_state; - - rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL_2, - rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL_2)&~(BIT(1))); - - u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL_2); - - if (rtlphy->polarity_ctl) - e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFOFF : ERFON; - else - e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFON : ERFOFF; - - if (ppsc->hwradiooff && (e_rfpowerstate_toset == ERFON)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "GPIOChangeRF - HW Radio ON, RF ON\n"); - - e_rfpowerstate_toset = ERFON; - ppsc->hwradiooff = false; - b_actuallyset = true; - } else if (!ppsc->hwradiooff && (e_rfpowerstate_toset == ERFOFF)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "GPIOChangeRF - HW Radio OFF, RF OFF\n"); - - e_rfpowerstate_toset = ERFOFF; - ppsc->hwradiooff = true; - b_actuallyset = true; - } - - if (b_actuallyset) { - spin_lock(&rtlpriv->locks.rf_ps_lock); - ppsc->rfchange_inprogress = false; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } else { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - - spin_lock(&rtlpriv->locks.rf_ps_lock); - ppsc->rfchange_inprogress = false; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } - - *valid = 1; - return !ppsc->hwradiooff; - -} - -void rtl8723e_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 *macaddr = p_macaddr; - u32 entry_id = 0; - bool is_pairwise = false; - - static u8 cam_const_addr[4][6] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} - }; - static u8 cam_const_broad[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - - if (clear_all) { - u8 idx = 0; - u8 cam_offset = 0; - u8 clear_number = 5; - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); - - for (idx = 0; idx < clear_number; idx++) { - rtl_cam_mark_invalid(hw, cam_offset + idx); - rtl_cam_empty_entry(hw, cam_offset + idx); - - if (idx < 5) { - memset(rtlpriv->sec.key_buf[idx], 0, - MAX_KEY_LEN); - rtlpriv->sec.key_len[idx] = 0; - } - } - - } else { - switch (enc_algo) { - case WEP40_ENCRYPTION: - enc_algo = CAM_WEP40; - break; - case WEP104_ENCRYPTION: - enc_algo = CAM_WEP104; - break; - case TKIP_ENCRYPTION: - enc_algo = CAM_TKIP; - break; - case AESCCMP_ENCRYPTION: - enc_algo = CAM_AES; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - enc_algo = CAM_TKIP; - break; - } - - if (is_wepkey || rtlpriv->sec.use_defaultkey) { - macaddr = cam_const_addr[key_index]; - entry_id = key_index; - } else { - if (is_group) { - macaddr = cam_const_broad; - entry_id = key_index; - } else { - if (mac->opmode == NL80211_IFTYPE_AP) { - entry_id = - rtl_cam_get_free_entry(hw, p_macaddr); - if (entry_id >= TOTAL_CAM_ENTRY) { - RT_TRACE(rtlpriv, COMP_SEC, - DBG_EMERG, - "Can not find free hw security cam entry\n"); - return; - } - } else { - entry_id = CAM_PAIRWISE_KEY_POSITION; - } - - key_index = PAIRWISE_KEYIDX; - is_pairwise = true; - } - } - - if (rtlpriv->sec.key_len[key_index] == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "delete one entry, entry_id is %d\n", - entry_id); - if (mac->opmode == NL80211_IFTYPE_AP) - rtl_cam_del_entry(hw, p_macaddr); - rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "add one entry\n"); - if (is_pairwise) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set Pairwiase key\n"); - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[key_index]); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set group key\n"); - - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - rtl_cam_add_one_entry(hw, - rtlefuse->dev_addr, - PAIRWISE_KEYIDX, - CAM_PAIRWISE_KEY_POSITION, - enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf - [entry_id]); - } - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[entry_id]); - } - - } - } -} - -static void rtl8723e_bt_var_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->btcoexist.bt_coexistence = - rtlpriv->btcoexist.eeprom_bt_coexist; - rtlpriv->btcoexist.bt_ant_num = - rtlpriv->btcoexist.eeprom_bt_ant_num; - rtlpriv->btcoexist.bt_coexist_type = - rtlpriv->btcoexist.eeprom_bt_type; - - rtlpriv->btcoexist.bt_ant_isolation = - rtlpriv->btcoexist.eeprom_bt_ant_isol; - - rtlpriv->btcoexist.bt_radio_shared_type = - rtlpriv->btcoexist.eeprom_bt_radio_shared; - - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "BT Coexistance = 0x%x\n", - rtlpriv->btcoexist.bt_coexistence); - - if (rtlpriv->btcoexist.bt_coexistence) { - rtlpriv->btcoexist.bt_busy_traffic = false; - rtlpriv->btcoexist.bt_traffic_mode_set = false; - rtlpriv->btcoexist.bt_non_traffic_mode_set = false; - - rtlpriv->btcoexist.cstate = 0; - rtlpriv->btcoexist.previous_state = 0; - - if (rtlpriv->btcoexist.bt_ant_num == ANT_X2) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "BlueTooth BT_Ant_Num = Antx2\n"); - } else if (rtlpriv->btcoexist.bt_ant_num == ANT_X1) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "BlueTooth BT_Ant_Num = Antx1\n"); - } - switch (rtlpriv->btcoexist.bt_coexist_type) { - case BT_2WIRE: - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "BlueTooth BT_CoexistType = BT_2Wire\n"); - break; - case BT_ISSC_3WIRE: - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "BlueTooth BT_CoexistType = BT_ISSC_3Wire\n"); - break; - case BT_ACCEL: - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "BlueTooth BT_CoexistType = BT_ACCEL\n"); - break; - case BT_CSR_BC4: - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "BlueTooth BT_CoexistType = BT_CSR_BC4\n"); - break; - case BT_CSR_BC8: - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "BlueTooth BT_CoexistType = BT_CSR_BC8\n"); - break; - case BT_RTL8756: - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "BlueTooth BT_CoexistType = BT_RTL8756\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "BlueTooth BT_CoexistType = Unknown\n"); - break; - } - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "BlueTooth BT_Ant_isolation = %d\n", - rtlpriv->btcoexist.bt_ant_isolation); - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_TRACE, - "BT_RadioSharedType = 0x%x\n", - rtlpriv->btcoexist.bt_radio_shared_type); - rtlpriv->btcoexist.bt_active_zero_cnt = 0; - rtlpriv->btcoexist.cur_bt_disabled = false; - rtlpriv->btcoexist.pre_bt_disabled = false; - } -} - -void rtl8723e_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool auto_load_fail, u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value; - u32 tmpu_32; - - if (!auto_load_fail) { - tmpu_32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL); - if (tmpu_32 & BIT(18)) - rtlpriv->btcoexist.eeprom_bt_coexist = 1; - else - rtlpriv->btcoexist.eeprom_bt_coexist = 0; - value = hwinfo[RF_OPTION4]; - rtlpriv->btcoexist.eeprom_bt_type = BT_RTL8723A; - rtlpriv->btcoexist.eeprom_bt_ant_num = (value & 0x1); - rtlpriv->btcoexist.eeprom_bt_ant_isol = ((value & 0x10) >> 4); - rtlpriv->btcoexist.eeprom_bt_radio_shared = - ((value & 0x20) >> 5); - } else { - rtlpriv->btcoexist.eeprom_bt_coexist = 0; - rtlpriv->btcoexist.eeprom_bt_type = BT_RTL8723A; - rtlpriv->btcoexist.eeprom_bt_ant_num = ANT_X2; - rtlpriv->btcoexist.eeprom_bt_ant_isol = 0; - rtlpriv->btcoexist.eeprom_bt_radio_shared = BT_RADIO_SHARED; - } - - rtl8723e_bt_var_init(hw); -} - -void rtl8723e_bt_reg_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /* 0:Low, 1:High, 2:From Efuse. */ - rtlpriv->btcoexist.reg_bt_iso = 2; - /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ - rtlpriv->btcoexist.reg_bt_sco = 3; - /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ - rtlpriv->btcoexist.reg_bt_sco = 0; -} - -void rtl8723e_bt_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_init_hw_config(rtlpriv); -} - -void rtl8723e_suspend(struct ieee80211_hw *hw) -{ -} - -void rtl8723e_resume(struct ieee80211_hw *hw) -{ -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h deleted file mode 100644 index 32c1ace97c3f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h +++ /dev/null @@ -1,67 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_HW_H__ -#define __RTL8723E_HW_H__ - -#define CHK_SVID_SMID(_val1, _val2) \ - ((rtlefuse->eeprom_svid == (_val1)) && \ - (rtlefuse->eeprom_smid == (_val2))) - -void rtl8723e_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl8723e_read_eeprom_info(struct ieee80211_hw *hw); - -void rtl8723e_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb); -int rtl8723e_hw_init(struct ieee80211_hw *hw); -void rtl8723e_card_disable(struct ieee80211_hw *hw); -void rtl8723e_enable_interrupt(struct ieee80211_hw *hw); -void rtl8723e_disable_interrupt(struct ieee80211_hw *hw); -int rtl8723e_set_network_type(struct ieee80211_hw *hw, - enum nl80211_iftype type); -void rtl8723e_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -void rtl8723e_set_qos(struct ieee80211_hw *hw, int aci); -void rtl8723e_set_beacon_related_registers(struct ieee80211_hw *hw); -void rtl8723e_set_beacon_interval(struct ieee80211_hw *hw); -void rtl8723e_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr); -void rtl8723e_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl8723e_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level); -void rtl8723e_update_channel_access_setting(struct ieee80211_hw *hw); -bool rtl8723e_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); -void rtl8723e_enable_hw_security_config(struct ieee80211_hw *hw); -void rtl8723e_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all); - -void rtl8723e_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, u8 *hwinfo); -void rtl8723e_bt_reg_init(struct ieee80211_hw *hw); -void rtl8723e_bt_hw_init(struct ieee80211_hw *hw); -void rtl8723e_suspend(struct ieee80211_hw *hw); -void rtl8723e_resume(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c b/drivers/net/wireless/rtlwifi/rtl8723ae/led.c deleted file mode 100644 index 13173351cbfd..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/led.c +++ /dev/null @@ -1,159 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "reg.h" -#include "led.h" - -static void _rtl8723e_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - u8 ledcfg; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - ledcfg &= ~BIT(6); - rtl_write_byte(rtlpriv, - REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5)); - break; - case LED_PIN_LED1: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); - rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - pled->ledon = true; -} - -void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - u8 ledcfg; - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); - - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg &= 0xf0; - if (pcipriv->ledctl.led_opendrain) { - ledcfg &= 0x90; /* Set to software control. */ - rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3))); - ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); - ledcfg &= 0xFE; - rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg); - } else { - ledcfg &= ~BIT(6); - rtl_write_byte(rtlpriv, REG_LEDCFG2, - (ledcfg | BIT(3) | BIT(5))); - } - break; - case LED_PIN_LED1: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); - ledcfg &= 0x10; /* Set to software control. */ - rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg|BIT(3)); - - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - pled->ledon = false; -} - -void rtl8723e_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - _rtl8723e_init_led(hw, &pcipriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl8723e_init_led(hw, &pcipriv->ledctl.sw_led1, LED_PIN_LED1); -} - -static void _rtl8723e_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); - switch (ledaction) { - case LED_CTL_POWER_ON: - case LED_CTL_LINK: - case LED_CTL_NO_LINK: - rtl8723e_sw_led_on(hw, pLed0); - break; - case LED_CTL_POWER_OFF: - rtl8723e_sw_led_off(hw, pLed0); - break; - default: - break; - } -} - -void rtl8723e_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && - (ledaction == LED_CTL_TX || - ledaction == LED_CTL_RX || - ledaction == LED_CTL_SITE_SURVEY || - ledaction == LED_CTL_LINK || - ledaction == LED_CTL_NO_LINK || - ledaction == LED_CTL_START_TO_LINK || - ledaction == LED_CTL_POWER_ON)) { - return; - } - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n", - ledaction); - _rtl8723e_sw_led_control(hw, ledaction); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/led.h b/drivers/net/wireless/rtlwifi/rtl8723ae/led.h deleted file mode 100644 index c22b19f542a6..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/led.h +++ /dev/null @@ -1,34 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92CE_LED_H__ -#define __RTL92CE_LED_H__ - -void rtl8723e_init_sw_leds(struct ieee80211_hw *hw); -void rtl8723e_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8723e_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8723e_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c deleted file mode 100644 index d367097f490b..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c +++ /dev/null @@ -1,1705 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../ps.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" -#include "table.h" -#include "../rtl8723com/phy_common.h" - -static void _rtl8723e_phy_fw_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data); -static bool _rtl8723e_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); -static bool _rtl8723e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); -static bool _rtl8723e_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); -static bool _rtl8723e_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); -static bool _rtl8723e_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay); -static u8 _rtl8723e_phy_dbm_to_txpwr_idx(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - long power_indbm); -static void rtl8723e_phy_set_rf_on(struct ieee80211_hw *hw); -static void rtl8723e_phy_set_io(struct ieee80211_hw *hw); - -u32 rtl8723e_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value = 0, readback_value, bitshift; - struct rtl_phy *rtlphy = &rtlpriv->phy; - unsigned long flags; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", - regaddr, rfpath, bitmask); - - spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); - - if (rtlphy->rf_mode != RF_OP_BY_FW) { - original_value = rtl8723_phy_rf_serial_read(hw, - rfpath, regaddr); - } - - bitshift = rtl8723_phy_calculate_bit_shift(bitmask); - readback_value = (original_value & bitmask) >> bitshift; - - spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", - regaddr, rfpath, bitmask, original_value); - - return readback_value; -} - -void rtl8723e_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 original_value = 0, bitshift; - unsigned long flags; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); - - spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); - - if (rtlphy->rf_mode != RF_OP_BY_FW) { - if (bitmask != RFREG_OFFSET_MASK) { - original_value = rtl8723_phy_rf_serial_read(hw, - rfpath, - regaddr); - bitshift = rtl8723_phy_calculate_bit_shift(bitmask); - data = - ((original_value & (~bitmask)) | - (data << bitshift)); - } - - rtl8723_phy_rf_serial_write(hw, rfpath, regaddr, data); - } else { - if (bitmask != RFREG_OFFSET_MASK) { - bitshift = rtl8723_phy_calculate_bit_shift(bitmask); - data = - ((original_value & (~bitmask)) | - (data << bitshift)); - } - _rtl8723e_phy_fw_rf_serial_write(hw, rfpath, regaddr, data); - } - - spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); - -} - -static void _rtl8723e_phy_fw_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) -{ - RT_ASSERT(false, "deprecated!\n"); -} - -static void _rtl8723e_phy_bb_config_1t(struct ieee80211_hw *hw) -{ - rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2); - rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022); - rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45); - rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23); - rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1); - rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2); - rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2); - rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2); - rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2); - rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2); -} - -bool rtl8723e_phy_mac_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool rtstatus = _rtl8723e_phy_config_mac_with_headerfile(hw); - rtl_write_byte(rtlpriv, 0x04CA, 0x0A); - return rtstatus; -} - -bool rtl8723e_phy_bb_config(struct ieee80211_hw *hw) -{ - bool rtstatus = true; - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmpu1b; - u8 b_reg_hwparafile = 1; - - rtl8723_phy_init_bb_rf_reg_def(hw); - - /* 1. 0x28[1] = 1 */ - tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_PLL_CTRL); - udelay(2); - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, (tmpu1b|BIT(1))); - udelay(2); - /* 2. 0x29[7:0] = 0xFF */ - rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL+1, 0xff); - udelay(2); - - /* 3. 0x02[1:0] = 2b'11 */ - tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, - (tmpu1b | FEN_BB_GLB_RSTN | FEN_BBRSTB)); - - /* 4. 0x25[6] = 0 */ - tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+1); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+1, (tmpu1b & (~BIT(6)))); - - /* 5. 0x24[20] = 0 //Advised by SD3 Alex Wang. 2011.02.09. */ - tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2); - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, (tmpu1b & (~BIT(4)))); - - /* 6. 0x1f[7:0] = 0x07 */ - rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x07); - - if (b_reg_hwparafile == 1) - rtstatus = _rtl8723e_phy_bb8192c_config_parafile(hw); - return rtstatus; -} - -bool rtl8723e_phy_rf_config(struct ieee80211_hw *hw) -{ - return rtl8723e_phy_rf6052_config(hw); -} - -static bool _rtl8723e_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - bool rtstatus; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); - rtstatus = _rtl8723e_phy_config_bb_with_headerfile(hw, - BASEBAND_CONFIG_PHY_REG); - if (rtstatus != true) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); - return false; - } - - if (rtlphy->rf_type == RF_1T2R) { - _rtl8723e_phy_bb_config_1t(hw); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Config to 1T!!\n"); - } - if (rtlefuse->autoload_failflag == false) { - rtlphy->pwrgroup_cnt = 0; - rtstatus = _rtl8723e_phy_config_bb_with_pgheaderfile(hw, - BASEBAND_CONFIG_PHY_REG); - } - if (rtstatus != true) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); - return false; - } - rtstatus = - _rtl8723e_phy_config_bb_with_headerfile(hw, BASEBAND_CONFIG_AGC_TAB); - if (rtstatus != true) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); - return false; - } - rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, - 0x200)); - - return true; -} - -static bool _rtl8723e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - u32 arraylength; - u32 *ptrarray; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl723MACPHY_Array\n"); - arraylength = RTL8723E_MACARRAYLENGTH; - ptrarray = RTL8723EMAC_ARRAY; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Img:RTL8192CEMAC_2T_ARRAY\n"); - for (i = 0; i < arraylength; i = i + 2) - rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); - return true; -} - -static bool _rtl8723e_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) -{ - int i; - u32 *phy_regarray_table; - u32 *agctab_array_table; - u16 phy_reg_arraylen, agctab_arraylen; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - agctab_arraylen = RTL8723E_AGCTAB_1TARRAYLENGTH; - agctab_array_table = RTL8723EAGCTAB_1TARRAY; - phy_reg_arraylen = RTL8723E_PHY_REG_1TARRAY_LENGTH; - phy_regarray_table = RTL8723EPHY_REG_1TARRAY; - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_reg_arraylen; i = i + 2) { - if (phy_regarray_table[i] == 0xfe) - mdelay(50); - else if (phy_regarray_table[i] == 0xfd) - mdelay(5); - else if (phy_regarray_table[i] == 0xfc) - mdelay(1); - else if (phy_regarray_table[i] == 0xfb) - udelay(50); - else if (phy_regarray_table[i] == 0xfa) - udelay(5); - else if (phy_regarray_table[i] == 0xf9) - udelay(1); - rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD, - phy_regarray_table[i + 1]); - udelay(1); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", - phy_regarray_table[i], - phy_regarray_table[i + 1]); - } - } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { - for (i = 0; i < agctab_arraylen; i = i + 2) { - rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD, - agctab_array_table[i + 1]); - udelay(1); - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", - agctab_array_table[i], - agctab_array_table[i + 1]); - } - } - return true; -} - -static void store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, - u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - if (regaddr == RTXAGC_A_RATE18_06) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][0]); - } - if (regaddr == RTXAGC_A_RATE54_24) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][1]); - } - if (regaddr == RTXAGC_A_CCK1_MCS32) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][6]); - } - if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][7]); - } - if (regaddr == RTXAGC_A_MCS03_MCS00) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][2]); - } - if (regaddr == RTXAGC_A_MCS07_MCS04) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][3]); - } - if (regaddr == RTXAGC_A_MCS11_MCS08) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][4]); - } - if (regaddr == RTXAGC_A_MCS15_MCS12) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][5]); - } - if (regaddr == RTXAGC_B_RATE18_06) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][8]); - } - if (regaddr == RTXAGC_B_RATE54_24) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][9]); - } - if (regaddr == RTXAGC_B_CCK1_55_MCS32) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][14]); - } - if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][15]); - } - if (regaddr == RTXAGC_B_MCS03_MCS00) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][10]); - } - if (regaddr == RTXAGC_B_MCS07_MCS04) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][11]); - } - if (regaddr == RTXAGC_B_MCS11_MCS08) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][12]); - } - if (regaddr == RTXAGC_B_MCS15_MCS12) { - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] = - data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", - rtlphy->pwrgroup_cnt, - rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> - pwrgroup_cnt][13]); - - rtlphy->pwrgroup_cnt++; - } -} - -static bool _rtl8723e_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int i; - u32 *phy_regarray_table_pg; - u16 phy_regarray_pg_len; - - phy_regarray_pg_len = RTL8723E_PHY_REG_ARRAY_PGLENGTH; - phy_regarray_table_pg = RTL8723EPHY_REG_ARRAY_PG; - - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_regarray_pg_len; i = i + 3) { - if (phy_regarray_table_pg[i] == 0xfe) - mdelay(50); - else if (phy_regarray_table_pg[i] == 0xfd) - mdelay(5); - else if (phy_regarray_table_pg[i] == 0xfc) - mdelay(1); - else if (phy_regarray_table_pg[i] == 0xfb) - udelay(50); - else if (phy_regarray_table_pg[i] == 0xfa) - udelay(5); - else if (phy_regarray_table_pg[i] == 0xf9) - udelay(1); - - store_pwrindex_diffrate_offset(hw, - phy_regarray_table_pg[i], - phy_regarray_table_pg[i + 1], - phy_regarray_table_pg[i + 2]); - } - } else { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "configtype != BaseBand_Config_PHY_REG\n"); - } - return true; -} - -bool rtl8723e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath) -{ - int i; - bool rtstatus = true; - u32 *radioa_array_table; - u32 *radiob_array_table; - u16 radioa_arraylen, radiob_arraylen; - - radioa_arraylen = RTL8723ERADIOA_1TARRAYLENGTH; - radioa_array_table = RTL8723E_RADIOA_1TARRAY; - radiob_arraylen = RTL8723E_RADIOB_1TARRAYLENGTH; - radiob_array_table = RTL8723E_RADIOB_1TARRAY; - - rtstatus = true; - - switch (rfpath) { - case RF90_PATH_A: - for (i = 0; i < radioa_arraylen; i = i + 2) { - if (radioa_array_table[i] == 0xfe) { - mdelay(50); - } else if (radioa_array_table[i] == 0xfd) { - mdelay(5); - } else if (radioa_array_table[i] == 0xfc) { - mdelay(1); - } else if (radioa_array_table[i] == 0xfb) { - udelay(50); - } else if (radioa_array_table[i] == 0xfa) { - udelay(5); - } else if (radioa_array_table[i] == 0xf9) { - udelay(1); - } else { - rtl_set_rfreg(hw, rfpath, radioa_array_table[i], - RFREG_OFFSET_MASK, - radioa_array_table[i + 1]); - udelay(1); - } - } - break; - case RF90_PATH_B: - case RF90_PATH_C: - case RF90_PATH_D: - break; - } - return true; -} - -void rtl8723e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - rtlphy->default_initialgain[0] = - (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[1] = - (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[2] = - (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[3] = - (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", - rtlphy->default_initialgain[0], - rtlphy->default_initialgain[1], - rtlphy->default_initialgain[2], - rtlphy->default_initialgain[3]); - - rtlphy->framesync = (u8) rtl_get_bbreg(hw, - ROFDM0_RXDETECTOR3, MASKBYTE0); - rtlphy->framesync_c34 = rtl_get_bbreg(hw, - ROFDM0_RXDETECTOR2, MASKDWORD); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default framesync (0x%x) = 0x%x\n", - ROFDM0_RXDETECTOR3, rtlphy->framesync); -} - -void rtl8723e_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 txpwr_level; - long txpwr_dbm; - - txpwr_level = rtlphy->cur_cck_txpwridx; - txpwr_dbm = rtl8723_phy_txpwr_idx_to_dbm(hw, - WIRELESS_MODE_B, txpwr_level); - txpwr_level = rtlphy->cur_ofdm24g_txpwridx + - rtlefuse->legacy_ht_txpowerdiff; - if (rtl8723_phy_txpwr_idx_to_dbm(hw, - WIRELESS_MODE_G, - txpwr_level) > txpwr_dbm) - txpwr_dbm = - rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, - txpwr_level); - txpwr_level = rtlphy->cur_ofdm24g_txpwridx; - if (rtl8723_phy_txpwr_idx_to_dbm(hw, - WIRELESS_MODE_N_24G, - txpwr_level) > txpwr_dbm) - txpwr_dbm = - rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, - txpwr_level); - *powerlevel = txpwr_dbm; -} - -static void _rtl8723e_get_txpower_index(struct ieee80211_hw *hw, u8 channel, - u8 *cckpowerlevel, u8 *ofdmpowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 index = (channel - 1); - - cckpowerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_cck[RF90_PATH_A][index]; - cckpowerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_cck[RF90_PATH_B][index]; - if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) { - ofdmpowerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index]; - ofdmpowerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index]; - } else if (get_rf_type(rtlphy) == RF_2T2R) { - ofdmpowerlevel[RF90_PATH_A] = - rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index]; - ofdmpowerlevel[RF90_PATH_B] = - rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index]; - } -} - -static void _rtl8723e_ccxpower_index_check(struct ieee80211_hw *hw, - u8 channel, u8 *cckpowerlevel, - u8 *ofdmpowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; - rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; - -} - -void rtl8723e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 cckpowerlevel[2], ofdmpowerlevel[2]; - - if (rtlefuse->txpwr_fromeprom == false) - return; - _rtl8723e_get_txpower_index(hw, channel, - &cckpowerlevel[0], &ofdmpowerlevel[0]); - _rtl8723e_ccxpower_index_check(hw, - channel, &cckpowerlevel[0], - &ofdmpowerlevel[0]); - rtl8723e_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]); - rtl8723e_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel); -} - -bool rtl8723e_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 idx; - u8 rf_path; - u8 ccktxpwridx = _rtl8723e_phy_dbm_to_txpwr_idx(hw, - WIRELESS_MODE_B, - power_indbm); - u8 ofdmtxpwridx = _rtl8723e_phy_dbm_to_txpwr_idx(hw, - WIRELESS_MODE_N_24G, - power_indbm); - if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0) - ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff; - else - ofdmtxpwridx = 0; - RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE, - "%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n", - power_indbm, ccktxpwridx, ofdmtxpwridx); - for (idx = 0; idx < 14; idx++) { - for (rf_path = 0; rf_path < 2; rf_path++) { - rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx; - rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] = - ofdmtxpwridx; - rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] = - ofdmtxpwridx; - } - } - rtl8723e_phy_set_txpower_level(hw, rtlphy->current_channel); - return true; -} - -static u8 _rtl8723e_phy_dbm_to_txpwr_idx(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - long power_indbm) -{ - u8 txpwridx; - long offset; - - switch (wirelessmode) { - case WIRELESS_MODE_B: - offset = -7; - break; - case WIRELESS_MODE_G: - case WIRELESS_MODE_N_24G: - offset = -8; - break; - default: - offset = -8; - break; - } - - if ((power_indbm - offset) > 0) - txpwridx = (u8)((power_indbm - offset) * 2); - else - txpwridx = 0; - - if (txpwridx > MAX_TXPWR_IDX_NMODE_92S) - txpwridx = MAX_TXPWR_IDX_NMODE_92S; - - return txpwridx; -} - -void rtl8723e_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - enum io_type iotype; - - if (!is_hal_stop(rtlhal)) { - switch (operation) { - case SCAN_OPT_BACKUP_BAND0: - iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_IO_CMD, - (u8 *)&iotype); - - break; - case SCAN_OPT_RESTORE: - iotype = IO_CMD_RESUME_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_IO_CMD, - (u8 *)&iotype); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Unknown Scan Backup operation.\n"); - break; - } - } -} - -void rtl8723e_phy_set_bw_mode_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 reg_bw_opmode; - u8 reg_prsr_rsc; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "Switch to %s bandwidth\n", - rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? - "20MHz" : "40MHz"); - - if (is_hal_stop(rtlhal)) { - rtlphy->set_bwmode_inprogress = false; - return; - } - - reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); - reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - reg_bw_opmode |= BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - break; - case HT_CHANNEL_WIDTH_20_40: - reg_bw_opmode &= ~BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - reg_prsr_rsc = - (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); - break; - case HT_CHANNEL_WIDTH_20_40: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); - - rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, - (mac->cur_40_prime_sc >> 1)); - rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); - rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); - - rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), - (mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - rtl8723e_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); - rtlphy->set_bwmode_inprogress = false; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); -} - -void rtl8723e_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_bw = rtlphy->current_chan_bw; - - if (rtlphy->set_bwmode_inprogress) - return; - rtlphy->set_bwmode_inprogress = true; - if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtl8723e_phy_set_bw_mode_callback(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "false driver sleep or unload\n"); - rtlphy->set_bwmode_inprogress = false; - rtlphy->current_chan_bw = tmp_bw; - } -} - -void rtl8723e_phy_sw_chnl_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 delay; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "switch to channel%d\n", rtlphy->current_channel); - if (is_hal_stop(rtlhal)) - return; - do { - if (!rtlphy->sw_chnl_inprogress) - break; - if (!_rtl8723e_phy_sw_chnl_step_by_step - (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage, - &rtlphy->sw_chnl_step, &delay)) { - if (delay > 0) - mdelay(delay); - else - continue; - } else { - rtlphy->sw_chnl_inprogress = false; - } - break; - } while (true); - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); -} - -u8 rtl8723e_phy_sw_chnl(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (rtlphy->sw_chnl_inprogress) - return 0; - if (rtlphy->set_bwmode_inprogress) - return 0; - RT_ASSERT((rtlphy->current_channel <= 14), - "WIRELESS_MODE_G but channel>14"); - rtlphy->sw_chnl_inprogress = true; - rtlphy->sw_chnl_stage = 0; - rtlphy->sw_chnl_step = 0; - if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtl8723e_phy_sw_chnl_callback(hw); - RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false schdule workitem\n"); - rtlphy->sw_chnl_inprogress = false; - } else { - RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false driver sleep or unload\n"); - rtlphy->sw_chnl_inprogress = false; - } - return 1; -} - -static void _rtl8723e_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { - if (channel == 6 && rtlphy->current_chan_bw == - HT_CHANNEL_WIDTH_20) - rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, - MASKDWORD, 0x00255); - else{ - u32 backuprf0x1a = (u32)rtl_get_rfreg(hw, - RF90_PATH_A, RF_RX_G1, - RFREG_OFFSET_MASK); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, - MASKDWORD, backuprf0x1a); - } - } -} - -static bool _rtl8723e_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, u8 *step, - u32 *delay) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; - u32 precommoncmdcnt; - struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; - u32 postcommoncmdcnt; - struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; - u32 rfdependcmdcnt; - struct swchnlcmd *currentcmd = NULL; - u8 rfpath; - u8 num_total_rfpath = rtlphy->num_total_rfpath; - - precommoncmdcnt = 0; - rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, - CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); - rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); - - postcommoncmdcnt = 0; - - rtl8723_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, - MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); - - rfdependcmdcnt = 0; - - RT_ASSERT((channel >= 1 && channel <= 14), - "illegal channel for Zebra: %d\n", channel); - - rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, - RF_CHNLBW, channel, 10); - - rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, - 0); - - do { - switch (*stage) { - case 0: - currentcmd = &precommoncmd[*step]; - break; - case 1: - currentcmd = &rfdependcmd[*step]; - break; - case 2: - currentcmd = &postcommoncmd[*step]; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Invalid 'stage' = %d, Check it!\n", *stage); - return true; - } - - if (currentcmd->cmdid == CMDID_END) { - if ((*stage) == 2) { - return true; - } else { - (*stage)++; - (*step) = 0; - continue; - } - } - - switch (currentcmd->cmdid) { - case CMDID_SET_TXPOWEROWER_LEVEL: - rtl8723e_phy_set_txpower_level(hw, channel); - break; - case CMDID_WRITEPORT_ULONG: - rtl_write_dword(rtlpriv, currentcmd->para1, - currentcmd->para2); - break; - case CMDID_WRITEPORT_USHORT: - rtl_write_word(rtlpriv, currentcmd->para1, - (u16) currentcmd->para2); - break; - case CMDID_WRITEPORT_UCHAR: - rtl_write_byte(rtlpriv, currentcmd->para1, - (u8) currentcmd->para2); - break; - case CMDID_RF_WRITEREG: - for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { - rtlphy->rfreg_chnlval[rfpath] = - ((rtlphy->rfreg_chnlval[rfpath] & - 0xfffffc00) | currentcmd->para2); - - rtl_set_rfreg(hw, (enum radio_path)rfpath, - currentcmd->para1, - RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[rfpath]); - } - _rtl8723e_phy_sw_rf_seting(hw, channel); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - - break; - } while (true); - - (*delay) = currentcmd->msdelay; - (*step)++; - return false; -} - -static u8 _rtl8723e_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) -{ - u32 reg_eac, reg_e94, reg_e9c, reg_ea4; - u8 result = 0x00; - - rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f); - rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f); - rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102); - rtl_set_bbreg(hw, 0xe3c, MASKDWORD, - config_pathb ? 0x28160202 : 0x28160502); - - if (config_pathb) { - rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22); - rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22); - rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102); - rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202); - } - - rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1); - rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); - reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); - reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && - (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else - return result; - - if (!(reg_eac & BIT(27)) && - (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && - (((reg_eac & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - return result; -} - -static u8 _rtl8723e_phy_path_b_iqk(struct ieee80211_hw *hw) -{ - u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; - u8 result = 0x00; - - rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002); - rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000); - mdelay(IQK_DELAY_TIME); - reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); - reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); - reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); - reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); - - if (!(reg_eac & BIT(31)) && - (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && - (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else - return result; - if (!(reg_eac & BIT(30)) && - (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && - (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - return result; -} - -static bool _rtl8723e_phy_simularity_compare(struct ieee80211_hw *hw, - long result[][8], u8 c1, u8 c2) -{ - u32 i, j, diff, simularity_bitmap, bound; - - u8 final_candidate[2] = { 0xFF, 0xFF }; - bool bresult = true; - - bound = 4; - - simularity_bitmap = 0; - - for (i = 0; i < bound; i++) { - diff = (result[c1][i] > result[c2][i]) ? - (result[c1][i] - result[c2][i]) : - (result[c2][i] - result[c1][i]); - - if (diff > MAX_TOLERANCE) { - if ((i == 2 || i == 6) && !simularity_bitmap) { - if (result[c1][i] + result[c1][i + 1] == 0) - final_candidate[(i / 4)] = c2; - else if (result[c2][i] + result[c2][i + 1] == 0) - final_candidate[(i / 4)] = c1; - else - simularity_bitmap = simularity_bitmap | - (1 << i); - } else - simularity_bitmap = - simularity_bitmap | (1 << i); - } - } - - if (simularity_bitmap == 0) { - for (i = 0; i < (bound / 4); i++) { - if (final_candidate[i] != 0xFF) { - for (j = i * 4; j < (i + 1) * 4 - 2; j++) - result[3][j] = - result[final_candidate[i]][j]; - bresult = false; - } - } - return bresult; - } else if (!(simularity_bitmap & 0x0F)) { - for (i = 0; i < 4; i++) - result[3][i] = result[c1][i]; - return false; - } else { - return false; - } - -} - -static void _rtl8723e_phy_iq_calibrate(struct ieee80211_hw *hw, - long result[][8], u8 t, bool is2t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 i; - u8 patha_ok, pathb_ok; - u32 adda_reg[IQK_ADDA_REG_NUM] = { - 0x85c, 0xe6c, 0xe70, 0xe74, - 0xe78, 0xe7c, 0xe80, 0xe84, - 0xe88, 0xe8c, 0xed0, 0xed4, - 0xed8, 0xedc, 0xee0, 0xeec - }; - - u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { - 0x522, 0x550, 0x551, 0x040 - }; - - const u32 retrycount = 2; - - u32 bbvalue; - - if (t == 0) { - bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD); - - rtl8723_save_adda_registers(hw, adda_reg, - rtlphy->adda_backup, 16); - rtl8723_phy_save_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - } - rtl8723_phy_path_adda_on(hw, adda_reg, true, is2t); - if (t == 0) { - rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER1, - BIT(8)); - } - - if (!rtlphy->rfpi_enable) - rtl8723_phy_pi_mode_switch(hw, true); - if (t == 0) { - rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD); - rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD); - rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD); - } - rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); - rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); - rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); - if (is2t) { - rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); - rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); - } - rtl8723_phy_mac_setting_calibration(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000); - if (is2t) - rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); - rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800); - for (i = 0; i < retrycount; i++) { - patha_ok = _rtl8723e_phy_path_a_iqk(hw, is2t); - if (patha_ok == 0x03) { - result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & - 0x3FF0000) >> 16; - break; - } else if (i == (retrycount - 1) && patha_ok == 0x01) - - result[t][0] = (rtl_get_bbreg(hw, 0xe94, - MASKDWORD) & 0x3FF0000) >> - 16; - result[t][1] = - (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16; - - } - - if (is2t) { - rtl8723_phy_path_a_standby(hw); - rtl8723_phy_path_adda_on(hw, adda_reg, false, is2t); - for (i = 0; i < retrycount; i++) { - pathb_ok = _rtl8723e_phy_path_b_iqk(hw); - if (pathb_ok == 0x03) { - result[t][4] = (rtl_get_bbreg(hw, - 0xeb4, - MASKDWORD) & - 0x3FF0000) >> 16; - result[t][5] = - (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][6] = - (rtl_get_bbreg(hw, 0xec4, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][7] = - (rtl_get_bbreg(hw, 0xecc, MASKDWORD) & - 0x3FF0000) >> 16; - break; - } else if (i == (retrycount - 1) && pathb_ok == 0x01) { - result[t][4] = (rtl_get_bbreg(hw, - 0xeb4, - MASKDWORD) & - 0x3FF0000) >> 16; - } - result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & - 0x3FF0000) >> 16; - } - } - rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04); - rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874); - rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); - rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); - if (is2t) - rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); - if (t != 0) { - if (!rtlphy->rfpi_enable) - rtl8723_phy_pi_mode_switch(hw, false); - rtl8723_phy_reload_adda_registers(hw, adda_reg, - rtlphy->adda_backup, 16); - rtl8723_phy_reload_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - } -} - -static void _rtl8723e_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) -{ - u8 tmpreg; - u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - tmpreg = rtl_read_byte(rtlpriv, 0xd03); - - if ((tmpreg & 0x70) != 0) - rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); - else - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - - if ((tmpreg & 0x70) != 0) { - rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); - - if (is2t) - rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, - MASK12BITS); - - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, - (rf_a_mode & 0x8FFFF) | 0x10000); - - if (is2t) - rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, - (rf_b_mode & 0x8FFFF) | 0x10000); - } - lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); - - rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); - - mdelay(100); - - if ((tmpreg & 0x70) != 0) { - rtl_write_byte(rtlpriv, 0xd03, tmpreg); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); - - if (is2t) - rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, - rf_b_mode); - } else { - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - } -} - -static void _rtl8723e_phy_set_rfpath_switch(struct ieee80211_hw *hw, - bool bmain, bool is2t) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (is_hal_stop(rtlhal)) { - rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01); - rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); - } - if (is2t) { - if (bmain) - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(5) | BIT(6), 0x1); - else - rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, - BIT(5) | BIT(6), 0x2); - } else { - if (bmain) - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2); - else - rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1); - - } - -} - -#undef IQK_ADDA_REG_NUM -#undef IQK_DELAY_TIME - -void rtl8723e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - long result[4][8]; - u8 i, final_candidate; - bool b_patha_ok, b_pathb_ok; - long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, - reg_ecc, reg_tmp = 0; - bool is12simular, is13simular, is23simular; - u32 iqk_bb_reg[10] = { - ROFDM0_XARXIQIMBALANCE, - ROFDM0_XBRXIQIMBALANCE, - ROFDM0_ECCATHRESHOLD, - ROFDM0_AGCRSSITABLE, - ROFDM0_XATXIQIMBALANCE, - ROFDM0_XBTXIQIMBALANCE, - ROFDM0_XCTXIQIMBALANCE, - ROFDM0_XCTXAFE, - ROFDM0_XDTXAFE, - ROFDM0_RXIQEXTANTA - }; - - if (b_recovery) { - rtl8723_phy_reload_adda_registers(hw, - iqk_bb_reg, - rtlphy->iqk_bb_backup, 10); - return; - } - for (i = 0; i < 8; i++) { - result[0][i] = 0; - result[1][i] = 0; - result[2][i] = 0; - result[3][i] = 0; - } - final_candidate = 0xff; - b_patha_ok = false; - b_pathb_ok = false; - is12simular = false; - is23simular = false; - is13simular = false; - for (i = 0; i < 3; i++) { - _rtl8723e_phy_iq_calibrate(hw, result, i, false); - if (i == 1) { - is12simular = - _rtl8723e_phy_simularity_compare(hw, result, 0, 1); - if (is12simular) { - final_candidate = 0; - break; - } - } - if (i == 2) { - is13simular = - _rtl8723e_phy_simularity_compare(hw, result, 0, 2); - if (is13simular) { - final_candidate = 0; - break; - } - is23simular = - _rtl8723e_phy_simularity_compare(hw, result, 1, 2); - if (is23simular) - final_candidate = 1; - else { - for (i = 0; i < 8; i++) - reg_tmp += result[3][i]; - - if (reg_tmp != 0) - final_candidate = 3; - else - final_candidate = 0xFF; - } - } - } - for (i = 0; i < 4; i++) { - reg_e94 = result[i][0]; - reg_e9c = result[i][1]; - reg_ea4 = result[i][2]; - reg_eac = result[i][3]; - reg_eb4 = result[i][4]; - reg_ebc = result[i][5]; - reg_ec4 = result[i][6]; - reg_ecc = result[i][7]; - } - if (final_candidate != 0xff) { - rtlphy->reg_e94 = reg_e94 = result[final_candidate][0]; - rtlphy->reg_e9c = reg_e9c = result[final_candidate][1]; - reg_ea4 = result[final_candidate][2]; - reg_eac = result[final_candidate][3]; - rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4]; - rtlphy->reg_ebc = reg_ebc = result[final_candidate][5]; - reg_ec4 = result[final_candidate][6]; - reg_ecc = result[final_candidate][7]; - b_patha_ok = true; - b_pathb_ok = true; - } else { - rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; - rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0; - } - if (reg_e94 != 0) - rtl8723_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result, - final_candidate, - (reg_ea4 == 0)); - rtl8723_save_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, 10); -} - -void rtl8723e_phy_lc_calibrate(struct ieee80211_hw *hw) -{ - _rtl8723e_phy_lc_calibrate(hw, false); -} - -void rtl8723e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) -{ - _rtl8723e_phy_set_rfpath_switch(hw, bmain, false); -} - -bool rtl8723e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - bool postprocessing = false; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "-->IO Cmd(%#x), set_io_inprogress(%d)\n", - iotype, rtlphy->set_io_inprogress); - do { - switch (iotype) { - case IO_CMD_RESUME_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Resume DM after scan.\n"); - postprocessing = true; - break; - case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Pause DM before scan.\n"); - postprocessing = true; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - } while (false); - if (postprocessing && !rtlphy->set_io_inprogress) { - rtlphy->set_io_inprogress = true; - rtlphy->current_io_type = iotype; - } else { - return false; - } - rtl8723e_phy_set_io(hw); - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); - return true; -} - -static void rtl8723e_phy_set_io(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "--->Cmd(%#x), set_io_inprogress(%d)\n", - rtlphy->current_io_type, rtlphy->set_io_inprogress); - switch (rtlphy->current_io_type) { - case IO_CMD_RESUME_DM_BY_SCAN: - dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; - rtl8723e_dm_write_dig(hw); - rtl8723e_phy_set_txpower_level(hw, rtlphy->current_channel); - break; - case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: - rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; - dm_digtable->cur_igvalue = 0x17; - rtl8723e_dm_write_dig(hw); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - rtlphy->set_io_inprogress = false; - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "(%#x)\n", rtlphy->current_io_type); -} - -static void rtl8723e_phy_set_rf_on(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); -} - -static void _rtl8723e_phy_set_rf_sleep(struct ieee80211_hw *hw) -{ - u32 u4b_tmp; - u8 delay = 5; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); - u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); - while (u4b_tmp != 0 && delay > 0) { - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); - u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); - delay--; - } - if (delay == 0) { - rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "Switch RF timeout !!!.\n"); - return; - } - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); -} - -static bool _rtl8723e_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool bresult = true; - u8 i, queue_id; - struct rtl8192_tx_ring *ring = NULL; - - switch (rfpwr_state) { - case ERFON: - if ((ppsc->rfpwr_state == ERFOFF) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { - bool rtstatus; - u32 initializecount = 0; - - do { - initializecount++; - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic enable\n"); - rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && (initializecount < 10)); - RT_CLEAR_PS_LEVEL(ppsc, - RT_RF_OFF_LEVL_HALT_NIC); - } else { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFON sleeped:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc-> - last_sleep_jiffies)); - ppsc->last_awake_jiffies = jiffies; - rtl8723e_phy_set_rf_on(hw); - } - if (mac->link_state == MAC80211_LINKED) { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_LINK); - } else { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - } - break; - case ERFOFF: - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic disable\n"); - rtl_ps_disable_nic(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - } else { - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - } else { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_POWER_OFF); - } - } - break; - case ERFSLEEP: - if (ppsc->rfpwr_state == ERFOFF) - break; - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (queue_id == BEACON_QUEUE || - skb_queue_len(&ring->queue) == 0) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", - (i + 1), queue_id, - skb_queue_len(&ring->queue)); - - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFSLEEP awaked:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc->last_awake_jiffies)); - ppsc->last_sleep_jiffies = jiffies; - _rtl8723e_phy_set_rf_sleep(hw); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - bresult = false; - break; - } - if (bresult) - ppsc->rfpwr_state = rfpwr_state; - return bresult; -} - -bool rtl8723e_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - bool bresult = false; - - if (rfpwr_state == ppsc->rfpwr_state) - return bresult; - bresult = _rtl8723e_phy_set_rf_power_state(hw, rfpwr_state); - return bresult; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h deleted file mode 100644 index b85f5c7c5c01..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.h +++ /dev/null @@ -1,202 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL92C_PHY_H__ -#define __RTL92C_PHY_H__ - -#define MAX_PRECMD_CNT 16 -#define MAX_RFDEPENDCMD_CNT 16 -#define MAX_POSTCMD_CNT 16 - -#define MAX_DOZE_WAITING_TIMES_9x 64 - -#define RT_CANNOT_IO(hw) false -#define HIGHPOWER_RADIOA_ARRAYLEN 22 - -#define IQK_ADDA_REG_NUM 16 -#define MAX_TOLERANCE 5 -#define IQK_DELAY_TIME 1 - -#define APK_BB_REG_NUM 5 -#define APK_AFE_REG_NUM 16 -#define APK_CURVE_REG_NUM 4 -#define PATH_NUM 2 - -#define LOOP_LIMIT 5 -#define MAX_STALL_TIME 50 -#define ANTENNADIVERSITYVALUE 0x80 -#define MAX_TXPWR_IDX_NMODE_92S 63 -#define Reset_Cnt_Limit 3 - -#define IQK_ADDA_REG_NUM 16 -#define IQK_MAC_REG_NUM 4 - -#define IQK_DELAY_TIME 1 - -#define RF6052_MAX_PATH 2 - -#define CT_OFFSET_MAC_ADDR 0X16 - -#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A -#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 -#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 -#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 -#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C - -#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F -#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 - -#define CT_OFFSET_CHANNEL_PLAH 0x75 -#define CT_OFFSET_THERMAL_METER 0x78 -#define CT_OFFSET_RF_OPTION 0x79 -#define CT_OFFSET_VERSION 0x7E -#define CT_OFFSET_CUSTOMER_ID 0x7F - -#define RTL92C_MAX_PATH_NUM 2 - -enum hw90_block_e { - HW90_BLOCK_MAC = 0, - HW90_BLOCK_PHY0 = 1, - HW90_BLOCK_PHY1 = 2, - HW90_BLOCK_RF = 3, - HW90_BLOCK_MAXIMUM = 4, -}; - -enum baseband_config_type { - BASEBAND_CONFIG_PHY_REG = 0, - BASEBAND_CONFIG_AGC_TAB = 1, -}; - -enum ra_offset_area { - RA_OFFSET_LEGACY_OFDM1, - RA_OFFSET_LEGACY_OFDM2, - RA_OFFSET_HT_OFDM1, - RA_OFFSET_HT_OFDM2, - RA_OFFSET_HT_OFDM3, - RA_OFFSET_HT_OFDM4, - RA_OFFSET_HT_CCK, -}; - -enum antenna_path { - ANTENNA_NONE, - ANTENNA_D, - ANTENNA_C, - ANTENNA_CD, - ANTENNA_B, - ANTENNA_BD, - ANTENNA_BC, - ANTENNA_BCD, - ANTENNA_A, - ANTENNA_AD, - ANTENNA_AC, - ANTENNA_ACD, - ANTENNA_AB, - ANTENNA_ABD, - ANTENNA_ABC, - ANTENNA_ABCD -}; - -struct r_antenna_select_ofdm { - u32 r_tx_antenna:4; - u32 r_ant_l:4; - u32 r_ant_non_ht:4; - u32 r_ant_ht1:4; - u32 r_ant_ht2:4; - u32 r_ant_ht_s1:4; - u32 r_ant_non_ht_s1:4; - u32 ofdm_txsc:2; - u32 reserved:2; -}; - -struct r_antenna_select_cck { - u8 r_cckrx_enable_2:2; - u8 r_cckrx_enable:2; - u8 r_ccktx_enable:4; -}; - -struct efuse_contents { - u8 mac_addr[ETH_ALEN]; - u8 cck_tx_power_idx[6]; - u8 ht40_1s_tx_power_idx[6]; - u8 ht40_2s_tx_power_idx_diff[3]; - u8 ht20_tx_power_idx_diff[3]; - u8 ofdm_tx_power_idx_diff[3]; - u8 ht40_max_power_offset[3]; - u8 ht20_max_power_offset[3]; - u8 channel_plan; - u8 thermal_meter; - u8 rf_option[5]; - u8 version; - u8 oem_id; - u8 regulatory; -}; - -struct tx_power_struct { - u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 legacy_ht_txpowerdiff; - u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 pwrgroup_cnt; - u32 mcs_original_offset[4][16]; -}; - -u32 rtl8723e_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask); -void rtl8723e_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask, u32 data); -bool rtl8723e_phy_mac_config(struct ieee80211_hw *hw); -bool rtl8723e_phy_bb_config(struct ieee80211_hw *hw); -bool rtl8723e_phy_rf_config(struct ieee80211_hw *hw); -bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -void rtl8723e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -void rtl8723e_phy_get_txpower_level(struct ieee80211_hw *hw, - long *powerlevel); -void rtl8723e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); -bool rtl8723e_phy_update_txpower_dbm(struct ieee80211_hw *hw, - long power_indbm); -void rtl8723e_phy_scan_operation_backup(struct ieee80211_hw *hw, - u8 operation); -void rtl8723e_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -void rtl8723e_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); -void rtl8723e_phy_sw_chnl_callback(struct ieee80211_hw *hw); -u8 rtl8723e_phy_sw_chnl(struct ieee80211_hw *hw); -void rtl8723e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery); -void rtl8723e_phy_lc_calibrate(struct ieee80211_hw *hw); -void rtl8723e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); -bool rtl8723e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -bool rtl8723e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); -bool rtl8723e_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c deleted file mode 100644 index 2f7f81af8a55..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c +++ /dev/null @@ -1,112 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../pwrseqcmd.h" -#include "pwrseq.h" - -/* drivers should parse below arrays and do the corresponding actions */ -/*3 Power on Array*/ -struct wlan_pwr_cfg rtl8723A_power_on_flow - [RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS + - RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_CARDEMU_TO_ACT - RTL8723A_TRANS_END -}; - -/*3Radio off GPIO Array */ -struct wlan_pwr_cfg rtl8723A_radio_off_flow - [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_ACT_TO_CARDEMU - RTL8723A_TRANS_END -}; - -/*3Card Disable Array*/ -struct wlan_pwr_cfg rtl8723A_card_disable_flow - [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_ACT_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_CARDDIS - RTL8723A_TRANS_END -}; - -/*3 Card Enable Array*/ -struct wlan_pwr_cfg rtl8723A_card_enable_flow - [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_CARDDIS_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_ACT - RTL8723A_TRANS_END -}; - -/*3Suspend Array*/ -struct wlan_pwr_cfg rtl8723A_suspend_flow - [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_ACT_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_SUS - RTL8723A_TRANS_END -}; - -/*3 Resume Array*/ -struct wlan_pwr_cfg rtl8723A_resume_flow - [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_SUS_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_ACT - RTL8723A_TRANS_END -}; - -/*3HWPDN Array*/ -struct wlan_pwr_cfg rtl8723A_hwpdn_flow - [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8723A_TRANS_END_STEPS] = { - RTL8723A_TRANS_ACT_TO_CARDEMU - RTL8723A_TRANS_CARDEMU_TO_PDN - RTL8723A_TRANS_END -}; - -/*3 Enter LPS */ -struct wlan_pwr_cfg rtl8723A_enter_lps_flow - [RTL8723A_TRANS_ACT_TO_LPS_STEPS + - RTL8723A_TRANS_END_STEPS] = { - /*FW behavior*/ - RTL8723A_TRANS_ACT_TO_LPS - RTL8723A_TRANS_END -}; - -/*3 Leave LPS */ -struct wlan_pwr_cfg rtl8723A_leave_lps_flow - [RTL8723A_TRANS_LPS_TO_ACT_STEPS + - RTL8723A_TRANS_END_STEPS] = { - /*FW behavior*/ - RTL8723A_TRANS_LPS_TO_ACT - RTL8723A_TRANS_END -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h b/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h deleted file mode 100644 index 4ac7db526f15..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h +++ /dev/null @@ -1,340 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_PWRSEQ_H__ -#define __RTL8723E_PWRSEQ_H__ - -#include "../pwrseqcmd.h" -/* - * Check document WM-20110607-Paul-RTL8723A_Power_Architecture-R02.vsd - * There are 6 HW Power States: - * 0: POFF--Power Off - * 1: PDN--Power Down - * 2: CARDEMU--Card Emulation - * 3: ACT--Active Mode - * 4: LPS--Low Power State - * 5: SUS--Suspend - * - * The transision from different states are defined below - * TRANS_CARDEMU_TO_ACT - * TRANS_ACT_TO_CARDEMU - * TRANS_CARDEMU_TO_SUS - * TRANS_SUS_TO_CARDEMU - * TRANS_CARDEMU_TO_PDN - * TRANS_ACT_TO_LPS - * TRANS_LPS_TO_ACT - * - * TRANS_END - */ - -#define RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS 10 -#define RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS 10 -#define RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS 10 -#define RTL8723A_TRANS_SUS_TO_CARDEMU_STEPS 10 -#define RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS 10 -#define RTL8723A_TRANS_PDN_TO_CARDEMU_STEPS 10 -#define RTL8723A_TRANS_ACT_TO_LPS_STEPS 15 -#define RTL8723A_TRANS_LPS_TO_ACT_STEPS 15 -#define RTL8723A_TRANS_END_STEPS 1 - -/* format */ -/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }*/ - -#define RTL8723A_TRANS_CARDEMU_TO_ACT \ - /* disable SW LPS 0x04[10]=0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), 0},\ - /* wait till 0x04[17] = 1 power ready*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)},\ - /* release WLON reset 0x04[16]=1*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},\ - /* disable HWPDN 0x04[15]=0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},\ - /* disable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT(4)|BIT(3)), 0},\ - /* polling until return 0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)},\ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0}, - -/* format */ -/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ - -#define RTL8723A_TRANS_ACT_TO_CARDEMU \ - /*0x1F[7:0] = 0 turn off RF*/ \ - {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, \ - {0x004E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0},\ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, - -/* format */ -/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/ -#define RTL8723A_TRANS_CARDEMU_TO_SUS \ - /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, \ - BIT(4)|BIT(3), (BIT(4)|BIT(3))},\ -/*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK| \ - PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, \ - PWR_CMD_WRITE, \ - BIT(3)|BIT(4), BIT(3)}, \ -/*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC, \ - PWR_CMD_WRITE, BIT(3)|BIT(4), \ - BIT(3)|BIT(4)}, \ -/*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ - PWR_CMD_WRITE, BIT(0), BIT(0)}, \ -/*wait power state to suspend*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ - PWR_CMD_POLLING, BIT(1), 0}, - -/* format */ -/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ - -#define RTL8723A_TRANS_SUS_TO_CARDEMU \ - /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0},\ - /*wait power state to suspend*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)},\ - /*0x04[12:11] = 2b'01enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, - -/* format */ -/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ - -#define RTL8723A_TRANS_CARDEMU_TO_CARDDIS \ - /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \ -/*0x04[10] = 1, enable SW LPS*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(2), BIT(2)}, \ -/*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ - PWR_CMD_WRITE, BIT(0), BIT(0)}, \ - /*wait power state to suspend*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ - PWR_CMD_POLLING, BIT(1), 0}, - -/* format */ -/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ - -#define RTL8723A_TRANS_CARDDIS_TO_CARDEMU\ -/*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ - PWR_CMD_WRITE, BIT(0), 0}, \ - /*wait power state to suspend*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ - PWR_CMD_POLLING, BIT(1), BIT(1)},\ - /*0x04[12:11] = 2b'00enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(3)|BIT(4), 0},\ -/*PCIe DMA start*/ \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, 0xFF, 0}, - -/* format */ -/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ -#define RTL8723A_TRANS_CARDEMU_TO_PDN \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(0), 0},/* 0x04[16] = 0*/\ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(7), BIT(7)},/* 0x04[15] = 1*/ - -/* format */ -/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ -#define RTL8723A_TRANS_PDN_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(7), 0},/* 0x04[15] = 0*/ - -/* format */ -/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ - -#define RTL8723A_TRANS_ACT_TO_LPS \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, 0xFF, 0xFF},/*PCIe DMA stop*/ \ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, 0xFF, 0x7F},/*Tx Pause*/ \ - /*Should be zero if no packet is transmitting*/ \ - {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_POLLING, 0xFF, 0},\ - /*Should be zero if no packet is transmitting*/ \ - {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_POLLING, 0xFF, 0},\ - /*Should be zero if no packet is transmitting*/ \ - {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_POLLING, 0xFF, 0},\ - /*Should be zero if no packet is transmitting*/ \ - {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_POLLING, 0xFF, 0},\ - /*CCK and OFDM are disabled,and clock are gated*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(0), 0},\ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US},/*Delay 1us*/\ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(1), 0},/*Whole BB is reset*/ \ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, 0xFF, 0x3F},/*Reset MAC TRX*/ \ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(1), 0},/*check if removed later*/ \ - /*Respond TxOK to scheduler*/ \ - {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(5), BIT(5)},\ - -#define RTL8723A_TRANS_LPS_TO_ACT\ -/* format */ \ -/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ \ - {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ - PWR_CMD_WRITE, 0xFF, 0x84}, /*SDIO RPWM*/\ - {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, 0xFF, 0x84}, /*USB RPWM*/\ - {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_PCI_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, 0xFF, 0x84}, /*PCIe RPWM*/\ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, /*Delay*/\ - /*. 0x08[4] = 0 switch TSF to 40M*/\ - {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(4), 0}, \ - /*Polling 0x109[7]=0 TSF in 40M*/\ - {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_POLLING, BIT(7), 0}, \ - /*. 0x29[7:6] = 2b'00 enable BB clock*/\ - {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(6)|BIT(7), 0},\ - /*. 0x101[1] = 1*/\ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(1), BIT(1)},\ - /*. 0x100[7:0] = 0xFF enable WMAC TRX*/\ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, 0xFF, 0xFF},\ - /*. 0x02[1:0] = 2b'11 enable BB macro*/\ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, BIT(1)|BIT(0), BIT(1)|BIT(0)},\ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ - PWR_CMD_WRITE, 0xFF, 0}, /*. 0x522 = 0*/ - -/* format */ -/* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */ - -#define RTL8723A_TRANS_END \ - {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - 0, PWR_CMD_END, 0, 0} - -extern struct wlan_pwr_cfg rtl8723A_power_on_flow - [RTL8723A_TRANS_CARDEMU_TO_ACT_STEPS + - RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723A_radio_off_flow - [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723A_card_disable_flow - [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723A_card_enable_flow - [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723A_suspend_flow - [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723A_resume_flow - [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723A_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723A_hwpdn_flow - [RTL8723A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723A_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723A_enter_lps_flow - [RTL8723A_TRANS_ACT_TO_LPS_STEPS + RTL8723A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723A_leave_lps_flow - [RTL8723A_TRANS_LPS_TO_ACT_STEPS + RTL8723A_TRANS_END_STEPS]; - -/* RTL8723 Power Configuration CMDs for PCIe interface */ -#define Rtl8723_NIC_PWR_ON_FLOW rtl8723A_power_on_flow -#define Rtl8723_NIC_RF_OFF_FLOW rtl8723A_radio_off_flow -#define Rtl8723_NIC_DISABLE_FLOW rtl8723A_card_disable_flow -#define Rtl8723_NIC_ENABLE_FLOW rtl8723A_card_enable_flow -#define Rtl8723_NIC_SUSPEND_FLOW rtl8723A_suspend_flow -#define Rtl8723_NIC_RESUME_FLOW rtl8723A_resume_flow -#define Rtl8723_NIC_PDN_FLOW rtl8723A_hwpdn_flow -#define Rtl8723_NIC_LPS_ENTER_FLOW rtl8723A_enter_lps_flow -#define Rtl8723_NIC_LPS_LEAVE_FLOW rtl8723A_leave_lps_flow - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h b/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h deleted file mode 100644 index 306059f9b9cc..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/reg.h +++ /dev/null @@ -1,2120 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_REG_H__ -#define __RTL8723E_REG_H__ - -#define REG_SYS_ISO_CTRL 0x0000 -#define REG_SYS_FUNC_EN 0x0002 -#define REG_APS_FSMCO 0x0004 -#define REG_SYS_CLKR 0x0008 -#define REG_9346CR 0x000A -#define REG_EE_VPD 0x000C -#define REG_AFE_MISC 0x0010 -#define REG_SPS0_CTRL 0x0011 -#define REG_SPS_OCP_CFG 0x0018 -#define REG_RSV_CTRL 0x001C -#define REG_RF_CTRL 0x001F -#define REG_LDOA15_CTRL 0x0020 -#define REG_LDOV12D_CTRL 0x0021 -#define REG_LDOHCI12_CTRL 0x0022 -#define REG_LPLDO_CTRL 0x0023 -#define REG_AFE_XTAL_CTRL 0x0024 -#define REG_AFE_PLL_CTRL 0x0028 -#define REG_EFUSE_CTRL 0x0030 -#define REG_EFUSE_TEST 0x0034 -#define REG_PWR_DATA 0x0038 -#define REG_CAL_TIMER 0x003C -#define REG_ACLK_MON 0x003E -#define REG_GPIO_MUXCFG 0x0040 -#define REG_GPIO_IO_SEL 0x0042 -#define REG_MAC_PINMUX_CFG 0x0043 -#define REG_GPIO_PIN_CTRL 0x0044 -#define REG_GPIO_INTM 0x0048 -#define REG_LEDCFG0 0x004C -#define REG_LEDCFG1 0x004D -#define REG_LEDCFG2 0x004E -#define REG_LEDCFG3 0x004F -#define REG_FSIMR 0x0050 -#define REG_FSISR 0x0054 -#define REG_GPIO_PIN_CTRL_2 0x0060 -#define REG_GPIO_IO_SEL_2 0x0062 -#define REG_MULTI_FUNC_CTRL 0x0068 - -#define REG_MCUFWDL 0x0080 - -#define REG_HMEBOX_EXT_0 0x0088 -#define REG_HMEBOX_EXT_1 0x008A -#define REG_HMEBOX_EXT_2 0x008C -#define REG_HMEBOX_EXT_3 0x008E - -#define REG_BIST_SCAN 0x00D0 -#define REG_BIST_RPT 0x00D4 -#define REG_BIST_ROM_RPT 0x00D8 -#define REG_USB_SIE_INTF 0x00E0 -#define REG_PCIE_MIO_INTF 0x00E4 -#define REG_PCIE_MIO_INTD 0x00E8 -#define REG_SYS_CFG 0x00F0 -#define REG_GPIO_OUTSTS 0x00F4 - -#define REG_CR 0x0100 -#define REG_PBP 0x0104 -#define REG_TRXDMA_CTRL 0x010C -#define REG_TRXFF_BNDY 0x0114 -#define REG_TRXFF_STATUS 0x0118 -#define REG_RXFF_PTR 0x011C -#define REG_HIMR 0x0120 -#define REG_HISR 0x0124 -#define REG_HIMRE 0x0128 -#define REG_HISRE 0x012C -#define REG_CPWM 0x012F -#define REG_FWIMR 0x0130 -#define REG_FWISR 0x0134 -#define REG_PKTBUF_DBG_CTRL 0x0140 -#define REG_PKTBUF_DBG_DATA_L 0x0144 -#define REG_PKTBUF_DBG_DATA_H 0x0148 - -#define REG_TC0_CTRL 0x0150 -#define REG_TC1_CTRL 0x0154 -#define REG_TC2_CTRL 0x0158 -#define REG_TC3_CTRL 0x015C -#define REG_TC4_CTRL 0x0160 -#define REG_TCUNIT_BASE 0x0164 -#define REG_MBIST_START 0x0174 -#define REG_MBIST_DONE 0x0178 -#define REG_MBIST_FAIL 0x017C -#define REG_C2HEVT_MSG_NORMAL 0x01A0 -#define REG_C2HEVT_MSG_TEST 0x01B8 -#define REG_MCUTST_1 0x01c0 -#define REG_FMETHR 0x01C8 -#define REG_HMETFR 0x01CC -#define REG_HMEBOX_0 0x01D0 -#define REG_HMEBOX_1 0x01D4 -#define REG_HMEBOX_2 0x01D8 -#define REG_HMEBOX_3 0x01DC - -#define REG_LLT_INIT 0x01E0 -#define REG_BB_ACCEESS_CTRL 0x01E8 -#define REG_BB_ACCESS_DATA 0x01EC - -#define REG_RQPN 0x0200 -#define REG_FIFOPAGE 0x0204 -#define REG_TDECTRL 0x0208 -#define REG_TXDMA_OFFSET_CHK 0x020C -#define REG_TXDMA_STATUS 0x0210 -#define REG_RQPN_NPQ 0x0214 - -#define REG_RXDMA_AGG_PG_TH 0x0280 -#define REG_RXPKT_NUM 0x0284 -#define REG_RXDMA_STATUS 0x0288 - -#define REG_PCIE_CTRL_REG 0x0300 -#define REG_INT_MIG 0x0304 -#define REG_BCNQ_DESA 0x0308 -#define REG_HQ_DESA 0x0310 -#define REG_MGQ_DESA 0x0318 -#define REG_VOQ_DESA 0x0320 -#define REG_VIQ_DESA 0x0328 -#define REG_BEQ_DESA 0x0330 -#define REG_BKQ_DESA 0x0338 -#define REG_RX_DESA 0x0340 -#define REG_DBI 0x0348 -#define REG_MDIO 0x0354 -#define REG_DBG_SEL 0x0360 -#define REG_PCIE_HRPWM 0x0361 -#define REG_PCIE_HCPWM 0x0363 -#define REG_UART_CTRL 0x0364 -#define REG_UART_TX_DESA 0x0370 -#define REG_UART_RX_DESA 0x0378 - -#define REG_HDAQ_DESA_NODEF 0x0000 -#define REG_CMDQ_DESA_NODEF 0x0000 - -#define REG_VOQ_INFORMATION 0x0400 -#define REG_VIQ_INFORMATION 0x0404 -#define REG_BEQ_INFORMATION 0x0408 -#define REG_BKQ_INFORMATION 0x040C -#define REG_MGQ_INFORMATION 0x0410 -#define REG_HGQ_INFORMATION 0x0414 -#define REG_BCNQ_INFORMATION 0x0418 - -#define REG_CPU_MGQ_INFORMATION 0x041C -#define REG_FWHW_TXQ_CTRL 0x0420 -#define REG_HWSEQ_CTRL 0x0423 -#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 -#define REG_TXPKTBUF_MGQ_BDNY 0x0425 -#define REG_MULTI_BCNQ_EN 0x0426 -#define REG_MULTI_BCNQ_OFFSET 0x0427 -#define REG_SPEC_SIFS 0x0428 -#define REG_RL 0x042A -#define REG_DARFRC 0x0430 -#define REG_RARFRC 0x0438 -#define REG_RRSR 0x0440 -#define REG_ARFR0 0x0444 -#define REG_ARFR1 0x0448 -#define REG_ARFR2 0x044C -#define REG_ARFR3 0x0450 -#define REG_AGGLEN_LMT 0x0458 -#define REG_AMPDU_MIN_SPACE 0x045C -#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D -#define REG_FAST_EDCA_CTRL 0x0460 -#define REG_RD_RESP_PKT_TH 0x0463 -#define REG_INIRTS_RATE_SEL 0x0480 -#define REG_INIDATA_RATE_SEL 0x0484 -#define REG_POWER_STATUS 0x04A4 -#define REG_POWER_STAGE1 0x04B4 -#define REG_POWER_STAGE2 0x04B8 -#define REG_PKT_LIFE_TIME 0x04C0 -#define REG_STBC_SETTING 0x04C4 -#define REG_PROT_MODE_CTRL 0x04C8 -#define REG_BAR_MODE_CTRL 0x04CC -#define REG_RA_TRY_RATE_AGG_LMT 0x04CF -#define REG_NQOS_SEQ 0x04DC -#define REG_QOS_SEQ 0x04DE -#define REG_NEED_CPU_HANDLE 0x04E0 -#define REG_PKT_LOSE_RPT 0x04E1 -#define REG_PTCL_ERR_STATUS 0x04E2 -#define REG_DUMMY 0x04FC - -#define REG_EDCA_VO_PARAM 0x0500 -#define REG_EDCA_VI_PARAM 0x0504 -#define REG_EDCA_BE_PARAM 0x0508 -#define REG_EDCA_BK_PARAM 0x050C -#define REG_BCNTCFG 0x0510 -#define REG_PIFS 0x0512 -#define REG_RDG_PIFS 0x0513 -#define REG_SIFS_CTX 0x0514 -#define REG_SIFS_TRX 0x0516 -#define REG_AGGR_BREAK_TIME 0x051A -#define REG_SLOT 0x051B -#define REG_TX_PTCL_CTRL 0x0520 -#define REG_TXPAUSE 0x0522 -#define REG_DIS_TXREQ_CLR 0x0523 -#define REG_RD_CTRL 0x0524 -#define REG_TBTT_PROHIBIT 0x0540 -#define REG_RD_NAV_NXT 0x0544 -#define REG_NAV_PROT_LEN 0x0546 -#define REG_BCN_CTRL 0x0550 -#define REG_USTIME_TSF 0x0551 -#define REG_MBID_NUM 0x0552 -#define REG_DUAL_TSF_RST 0x0553 -#define REG_BCN_INTERVAL 0x0554 -#define REG_MBSSID_BCN_SPACE 0x0554 -#define REG_DRVERLYINT 0x0558 -#define REG_BCNDMATIM 0x0559 -#define REG_ATIMWND 0x055A -#define REG_BCN_MAX_ERR 0x055D -#define REG_RXTSF_OFFSET_CCK 0x055E -#define REG_RXTSF_OFFSET_OFDM 0x055F -#define REG_TSFTR 0x0560 -#define REG_INIT_TSFTR 0x0564 -#define REG_PSTIMER 0x0580 -#define REG_TIMER0 0x0584 -#define REG_TIMER1 0x0588 -#define REG_ACMHWCTRL 0x05C0 -#define REG_ACMRSTCTRL 0x05C1 -#define REG_ACMAVG 0x05C2 -#define REG_VO_ADMTIME 0x05C4 -#define REG_VI_ADMTIME 0x05C6 -#define REG_BE_ADMTIME 0x05C8 -#define REG_EDCA_RANDOM_GEN 0x05CC -#define REG_SCH_TXCMD 0x05D0 - -#define REG_APSD_CTRL 0x0600 -#define REG_BWOPMODE 0x0603 -#define REG_TCR 0x0604 -#define REG_RCR 0x0608 -#define REG_RX_PKT_LIMIT 0x060C -#define REG_RX_DLK_TIME 0x060D -#define REG_RX_DRVINFO_SZ 0x060F - -#define REG_MACID 0x0610 -#define REG_BSSID 0x0618 -#define REG_MAR 0x0620 -#define REG_MBIDCAMCFG 0x0628 - -#define REG_USTIME_EDCA 0x0638 -#define REG_MAC_SPEC_SIFS 0x063A -#define REG_RESP_SIFS_CCK 0x063C -#define REG_RESP_SIFS_OFDM 0x063E -#define REG_ACKTO 0x0640 -#define REG_CTS2TO 0x0641 -#define REG_EIFS 0x0642 - -#define REG_NAV_CTRL 0x0650 -#define REG_BACAMCMD 0x0654 -#define REG_BACAMCONTENT 0x0658 -#define REG_LBDLY 0x0660 -#define REG_FWDLY 0x0661 -#define REG_RXERR_RPT 0x0664 -#define REG_WMAC_TRXPTCL_CTL 0x0668 - -#define REG_CAMCMD 0x0670 -#define REG_CAMWRITE 0x0674 -#define REG_CAMREAD 0x0678 -#define REG_CAMDBG 0x067C -#define REG_SECCFG 0x0680 - -#define REG_WOW_CTRL 0x0690 -#define REG_PSSTATUS 0x0691 -#define REG_PS_RX_INFO 0x0692 -#define REG_LPNAV_CTRL 0x0694 -#define REG_WKFMCAM_CMD 0x0698 -#define REG_WKFMCAM_RWD 0x069C -#define REG_RXFLTMAP0 0x06A0 -#define REG_RXFLTMAP1 0x06A2 -#define REG_RXFLTMAP2 0x06A4 -#define REG_BCN_PSR_RPT 0x06A8 -#define REG_CALB32K_CTRL 0x06AC -#define REG_PKT_MON_CTRL 0x06B4 -#define REG_BT_COEX_TABLE 0x06C0 -#define REG_WMAC_RESP_TXINFO 0x06D8 - -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_TEST_USB_TXQS 0xFE48 -#define REG_TEST_SIE_VID 0xFE60 -#define REG_TEST_SIE_PID 0xFE62 -#define REG_TEST_SIE_OPTIONAL 0xFE64 -#define REG_TEST_SIE_CHIRP_K 0xFE65 -#define REG_TEST_SIE_PHY 0xFE66 -#define REG_TEST_SIE_MAC_ADDR 0xFE70 -#define REG_TEST_SIE_STRING 0xFE80 - -#define REG_NORMAL_SIE_VID 0xFE60 -#define REG_NORMAL_SIE_PID 0xFE62 -#define REG_NORMAL_SIE_OPTIONAL 0xFE64 -#define REG_NORMAL_SIE_EP 0xFE65 -#define REG_NORMAL_SIE_PHY 0xFE68 -#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 -#define REG_NORMAL_SIE_STRING 0xFE80 - -#define CR9346 REG_9346CR -#define MSR (REG_CR + 2) -#define ISR REG_HISR -#define TSFR REG_TSFTR - -#define MACIDR0 REG_MACID -#define MACIDR4 (REG_MACID + 4) - -#define PBP REG_PBP - -#define IDR0 MACIDR0 -#define IDR4 MACIDR4 - -#define UNUSED_REGISTER 0x1BF -#define DCAM UNUSED_REGISTER -#define PSR UNUSED_REGISTER -#define BBADDR UNUSED_REGISTER -#define PHYDATAR UNUSED_REGISTER - -#define INVALID_BBRF_VALUE 0x12345678 - -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -#define CMDEEPROM_EN BIT(5) -#define CMDEEPROM_SEL BIT(4) -#define CMD9346CR_9356SEL BIT(4) -#define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL) -#define AUTOLOAD_EFUSE CMDEEPROM_EN - -#define GPIOSEL_GPIO 0 -#define GPIOSEL_ENBT BIT(5) - -#define GPIO_IN REG_GPIO_PIN_CTRL -#define GPIO_OUT (REG_GPIO_PIN_CTRL+1) -#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) -#define GPIO_MOD (REG_GPIO_PIN_CTRL+3) - -#define MSR_NOLINK 0x00 -#define MSR_ADHOC 0x01 -#define MSR_INFRA 0x02 -#define MSR_AP 0x03 - -#define RRSR_RSC_OFFSET 21 -#define RRSR_SHORT_OFFSET 23 -#define RRSR_RSC_BW_40M 0x600000 -#define RRSR_RSC_UPSUBCHNL 0x400000 -#define RRSR_RSC_LOWSUBCHNL 0x200000 -#define RRSR_SHORT 0x800000 -#define RRSR_1M BIT(0) -#define RRSR_2M BIT(1) -#define RRSR_5_5M BIT(2) -#define RRSR_11M BIT(3) -#define RRSR_6M BIT(4) -#define RRSR_9M BIT(5) -#define RRSR_12M BIT(6) -#define RRSR_18M BIT(7) -#define RRSR_24M BIT(8) -#define RRSR_36M BIT(9) -#define RRSR_48M BIT(10) -#define RRSR_54M BIT(11) -#define RRSR_MCS0 BIT(12) -#define RRSR_MCS1 BIT(13) -#define RRSR_MCS2 BIT(14) -#define RRSR_MCS3 BIT(15) -#define RRSR_MCS4 BIT(16) -#define RRSR_MCS5 BIT(17) -#define RRSR_MCS6 BIT(18) -#define RRSR_MCS7 BIT(19) -#define BRSR_ACKSHORTPMB BIT(23) - -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 -#define RATR_MCS8 0x00100000 -#define RATR_MCS9 0x00200000 -#define RATR_MCS10 0x00400000 -#define RATR_MCS11 0x00800000 -#define RATR_MCS12 0x01000000 -#define RATR_MCS13 0x02000000 -#define RATR_MCS14 0x04000000 -#define RATR_MCS15 0x08000000 - -#define RATE_1M BIT(0) -#define RATE_2M BIT(1) -#define RATE_5_5M BIT(2) -#define RATE_11M BIT(3) -#define RATE_6M BIT(4) -#define RATE_9M BIT(5) -#define RATE_12M BIT(6) -#define RATE_18M BIT(7) -#define RATE_24M BIT(8) -#define RATE_36M BIT(9) -#define RATE_48M BIT(10) -#define RATE_54M BIT(11) -#define RATE_MCS0 BIT(12) -#define RATE_MCS1 BIT(13) -#define RATE_MCS2 BIT(14) -#define RATE_MCS3 BIT(15) -#define RATE_MCS4 BIT(16) -#define RATE_MCS5 BIT(17) -#define RATE_MCS6 BIT(18) -#define RATE_MCS7 BIT(19) -#define RATE_MCS8 BIT(20) -#define RATE_MCS9 BIT(21) -#define RATE_MCS10 BIT(22) -#define RATE_MCS11 BIT(23) -#define RATE_MCS12 BIT(24) -#define RATE_MCS13 BIT(25) -#define RATE_MCS14 BIT(26) -#define RATE_MCS15 BIT(27) - -#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) -#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\ - RATR_24M | RATR_36M | RATR_48M | RATR_54M) -#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 |\ - RATR_MCS3 | RATR_MCS4 | RATR_MCS5 |\ - RATR_MCS6 | RATR_MCS7) -#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 |\ - RATR_MCS11 | RATR_MCS12 | RATR_MCS13 |\ - RATR_MCS14 | RATR_MCS15) - -#define BW_OPMODE_20MHZ BIT(2) -#define BW_OPMODE_5G BIT(1) -#define BW_OPMODE_11J BIT(0) - -#define CAM_VALID BIT(15) -#define CAM_NOTVALID 0x0000 -#define CAM_USEDK BIT(5) - -#define CAM_NONE 0x0 -#define CAM_WEP40 0x01 -#define CAM_TKIP 0x02 -#define CAM_AES 0x04 -#define CAM_WEP104 0x05 - -#define TOTAL_CAM_ENTRY 32 -#define HALF_CAM_ENTRY 16 - -#define CAM_WRITE BIT(16) -#define CAM_READ 0x00000000 -#define CAM_POLLINIG BIT(31) - -#define SCR_USEDK 0x01 -#define SCR_TXSEC_ENABLE 0x02 -#define SCR_RXSEC_ENABLE 0x04 - -#define WOW_PMEN BIT(0) -#define WOW_WOMEN BIT(1) -#define WOW_MAGIC BIT(2) -#define WOW_UWF BIT(3) - -#define IMR8190_DISABLED 0x0 -#define IMR_BCNDMAINT6 BIT(31) -#define IMR_BCNDMAINT5 BIT(30) -#define IMR_BCNDMAINT4 BIT(29) -#define IMR_BCNDMAINT3 BIT(28) -#define IMR_BCNDMAINT2 BIT(27) -#define IMR_BCNDMAINT1 BIT(26) -#define IMR_BCNDOK8 BIT(25) -#define IMR_BCNDOK7 BIT(24) -#define IMR_BCNDOK6 BIT(23) -#define IMR_BCNDOK5 BIT(22) -#define IMR_BCNDOK4 BIT(21) -#define IMR_BCNDOK3 BIT(20) -#define IMR_BCNDOK2 BIT(19) -#define IMR_BCNDOK1 BIT(18) -#define IMR_TIMEOUT2 BIT(17) -#define IMR_TIMEOUT1 BIT(16) -#define IMR_TXFOVW BIT(15) -#define IMR_PSTIMEOUT BIT(14) -#define IMR_BCNINT BIT(13) -#define IMR_RXFOVW BIT(12) -#define IMR_RDU BIT(11) -#define IMR_ATIMEND BIT(10) -#define IMR_BDOK BIT(9) -#define IMR_HIGHDOK BIT(8) -#define IMR_TBDOK BIT(7) -#define IMR_MGNTDOK BIT(6) -#define IMR_TBDER BIT(5) -#define IMR_BKDOK BIT(4) -#define IMR_BEDOK BIT(3) -#define IMR_VIDOK BIT(2) -#define IMR_VODOK BIT(1) -#define IMR_ROK BIT(0) - -#define IMR_TXERR BIT(11) -#define IMR_RXERR BIT(10) -#define IMR_CPWM BIT(8) -#define IMR_OCPINT BIT(1) -#define IMR_WLANOFF BIT(0) - -/* 8723E series PCIE Host IMR/ISR bit */ -/* IMR DW0 Bit 0-31 */ -#define PHIMR_TIMEOUT2 BIT(31) -#define PHIMR_TIMEOUT1 BIT(30) -#define PHIMR_PSTIMEOUT BIT(29) -#define PHIMR_GTINT4 BIT(28) -#define PHIMR_GTINT3 BIT(27) -#define PHIMR_TXBCNERR BIT(26) -#define PHIMR_TXBCNOK BIT(25) -#define PHIMR_TSF_BIT32_TOGGLE BIT(24) -#define PHIMR_BCNDMAINT3 BIT(23) -#define PHIMR_BCNDMAINT2 BIT(22) -#define PHIMR_BCNDMAINT1 BIT(21) -#define PHIMR_BCNDMAINT0 BIT(20) -#define PHIMR_BCNDOK3 BIT(19) -#define PHIMR_BCNDOK2 BIT(18) -#define PHIMR_BCNDOK1 BIT(17) -#define PHIMR_BCNDOK0 BIT(16) -#define PHIMR_HSISR_IND_ON BIT(15) -#define PHIMR_BCNDMAINT_E BIT(14) -#define PHIMR_ATIMEND_E BIT(13) -#define PHIMR_ATIM_CTW_END BIT(12) -#define PHIMR_HISRE_IND BIT(11) -#define PHIMR_C2HCMD BIT(10) -#define PHIMR_CPWM2 BIT(9) -#define PHIMR_CPWM BIT(8) -#define PHIMR_HIGHDOK BIT(7) -#define PHIMR_MGNTDOK BIT(6) -#define PHIMR_BKDOK BIT(5) -#define PHIMR_BEDOK BIT(4) -#define PHIMR_VIDOK BIT(3) -#define PHIMR_VODOK BIT(2) -#define PHIMR_RDU BIT(1) -#define PHIMR_ROK BIT(0) - -/* PCIE Host Interrupt Status Extension bit */ -#define PHIMR_BCNDMAINT7 BIT(23) -#define PHIMR_BCNDMAINT6 BIT(22) -#define PHIMR_BCNDMAINT5 BIT(21) -#define PHIMR_BCNDMAINT4 BIT(20) -#define PHIMR_BCNDOK7 BIT(19) -#define PHIMR_BCNDOK6 BIT(18) -#define PHIMR_BCNDOK5 BIT(17) -#define PHIMR_BCNDOK4 BIT(16) -/* bit12-15: RSVD */ -#define PHIMR_TXERR BIT(11) -#define PHIMR_RXERR BIT(10) -#define PHIMR_TXFOVW BIT(9) -#define PHIMR_RXFOVW BIT(8) -/* bit2-7: RSVD */ -#define PHIMR_OCPINT BIT(1) - -#define HWSET_MAX_SIZE 256 -#define EFUSE_MAX_SECTION 32 -#define EFUSE_REAL_CONTENT_LEN 512 -#define EFUSE_OOB_PROTECT_BYTES 15 - -#define EEPROM_DEFAULT_TSSI 0x0 -#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 -#define EEPROM_DEFAULT_CRYSTALCAP 0x5 -#define EEPROM_DEFAULT_BOARDTYPE 0x02 -#define EEPROM_DEFAULT_TXPOWER 0x1010 -#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 - -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 -#define EEPROM_DEFAULT_THERMALMETER 0x12 -#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 -#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 -#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 -#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 -#define EEPROM_DEFAULT_HT20_DIFF 2 -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 -#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 -#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 - -#define EEPROM_DEFAULT_PID 0x1234 -#define EEPROM_DEFAULT_VID 0x5678 -#define EEPROM_DEFAULT_CUSTOMERID 0xAB -#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD -#define EEPROM_DEFAULT_VERSION 0 - -#define EEPROM_CHANNEL_PLAN_FCC 0x0 -#define EEPROM_CHANNEL_PLAN_IC 0x1 -#define EEPROM_CHANNEL_PLAN_ETSI 0x2 -#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 -#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 -#define EEPROM_CHANNEL_PLAN_MKK 0x5 -#define EEPROM_CHANNEL_PLAN_MKK1 0x6 -#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 -#define EEPROM_CHANNEL_PLAN_TELEC 0x8 -#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 -#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -#define EEPROM_CHANNEL_PLAN_NCC 0xB -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - -#define EEPROM_CID_DEFAULT 0x0 -#define EEPROM_CID_TOSHIBA 0x4 -#define EEPROM_CID_CCX 0x10 -#define EEPROM_CID_QMI 0x0D -#define EEPROM_CID_WHQL 0xFE - -#define RTL8192_EEPROM_ID 0x8129 - -#define RTL8190_EEPROM_ID 0x8129 -#define EEPROM_HPON 0x02 -#define EEPROM_CLK 0x06 -#define EEPROM_TESTR 0x08 - -#define EEPROM_VID 0x49 -#define EEPROM_DID 0x4B -#define EEPROM_SVID 0x4D -#define EEPROM_SMID 0x4F - -#define EEPROM_MAC_ADDR 0x67 - -#define EEPROM_CCK_TX_PWR_INX 0x5A -#define EEPROM_HT40_1S_TX_PWR_INX 0x60 -#define EEPROM_HT40_2S_TX_PWR_INX_DIFF 0x66 -#define EEPROM_HT20_TX_PWR_INX_DIFF 0x69 -#define EEPROM_OFDM_TX_PWR_INX_DIFF 0x6C -#define EEPROM_HT40_MAX_PWR_OFFSET 0x25 -#define EEPROM_HT20_MAX_PWR_OFFSET 0x22 - -#define EEPROM_THERMAL_METER 0x2a -#define EEPROM_XTAL_K 0x78 -#define EEPROM_RF_OPT1 0x79 -#define EEPROM_RF_OPT2 0x7A -#define EEPROM_RF_OPT3 0x7B -#define EEPROM_RF_OPT4 0x7C -#define EEPROM_CHANNEL_PLAN 0x28 -#define EEPROM_VERSION 0x30 -#define EEPROM_CUSTOMER_ID 0x31 - -#define EEPROM_PWRDIFF 0x54 - -#define EEPROM_TXPOWERCCK 0x10 -#define EEPROM_TXPOWERHT40_1S 0x16 -#define EEPROM_TXPOWERHT40_2SDIFF 0x66 -#define EEPROM_TXPOWERHT20DIFF 0x1C -#define EEPROM_TXPOWER_OFDMDIFF 0x1F - -#define EEPROM_TXPWR_GROUP 0x22 - -#define EEPROM_TSSI_A 0x29 -#define EEPROM_TSSI_B 0x77 - -#define EEPROM_CHANNELPLAN 0x28 - -#define RF_OPTION1 0x2B -#define RF_OPTION2 0x2C -#define RF_OPTION3 0x2D -#define RF_OPTION4 0x2E - -#define STOPBECON BIT(6) -#define STOPHIGHT BIT(5) -#define STOPMGT BIT(4) -#define STOPVO BIT(3) -#define STOPVI BIT(2) -#define STOPBE BIT(1) -#define STOPBK BIT(0) - -#define RCR_APPFCS BIT(31) -#define RCR_APP_MIC BIT(30) -#define RCR_APP_ICV BIT(29) -#define RCR_APP_PHYST_RXFF BIT(28) -#define RCR_APP_BA_SSN BIT(27) -#define RCR_ENMBID BIT(24) -#define RCR_LSIGEN BIT(23) -#define RCR_MFBEN BIT(22) -#define RCR_HTC_LOC_CTRL BIT(14) -#define RCR_AMF BIT(13) -#define RCR_ACF BIT(12) -#define RCR_ADF BIT(11) -#define RCR_AICV BIT(9) -#define RCR_ACRC32 BIT(8) -#define RCR_CBSSID_BCN BIT(7) -#define RCR_CBSSID_DATA BIT(6) -#define RCR_CBSSID RCR_CBSSID_DATA -#define RCR_APWRMGT BIT(5) -#define RCR_ADD3 BIT(4) -#define RCR_AB BIT(3) -#define RCR_AM BIT(2) -#define RCR_APM BIT(1) -#define RCR_AAP BIT(0) -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - -#define RSV_CTRL 0x001C -#define RD_CTRL 0x0524 - -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_USB_VID 0xFE60 -#define REG_USB_PID 0xFE62 -#define REG_USB_OPTIONAL 0xFE64 -#define REG_USB_CHIRP_K 0xFE65 -#define REG_USB_PHY 0xFE66 -#define REG_USB_MAC_ADDR 0xFE70 -#define REG_USB_HRPWM 0xFE58 -#define REG_USB_HCPWM 0xFE57 - -#define SW18_FPWM BIT(3) - -#define ISO_MD2PP BIT(0) -#define ISO_UA2USB BIT(1) -#define ISO_UD2CORE BIT(2) -#define ISO_PA2PCIE BIT(3) -#define ISO_PD2CORE BIT(4) -#define ISO_IP2MAC BIT(5) -#define ISO_DIOP BIT(6) -#define ISO_DIOE BIT(7) -#define ISO_EB2CORE BIT(8) -#define ISO_DIOR BIT(9) - -#define PWC_EV25V BIT(14) -#define PWC_EV12V BIT(15) - -#define FEN_BBRSTB BIT(0) -#define FEN_BB_GLB_RSTN BIT(1) -#define FEN_USBA BIT(2) -#define FEN_UPLL BIT(3) -#define FEN_USBD BIT(4) -#define FEN_DIO_PCIE BIT(5) -#define FEN_PCIEA BIT(6) -#define FEN_PPLL BIT(7) -#define FEN_PCIED BIT(8) -#define FEN_DIOE BIT(9) -#define FEN_CPUEN BIT(10) -#define FEN_DCORE BIT(11) -#define FEN_ELDR BIT(12) -#define FEN_DIO_RF BIT(13) -#define FEN_HWPDN BIT(14) -#define FEN_MREGEN BIT(15) - -#define PFM_LDALL BIT(0) -#define PFM_ALDN BIT(1) -#define PFM_LDKP BIT(2) -#define PFM_WOWL BIT(3) -#define ENPDN BIT(4) -#define PDN_PL BIT(5) -#define APFM_ONMAC BIT(8) -#define APFM_OFF BIT(9) -#define APFM_RSM BIT(10) -#define AFSM_HSUS BIT(11) -#define AFSM_PCIE BIT(12) -#define APDM_MAC BIT(13) -#define APDM_HOST BIT(14) -#define APDM_HPDN BIT(15) -#define RDY_MACON BIT(16) -#define SUS_HOST BIT(17) -#define ROP_ALD BIT(20) -#define ROP_PWR BIT(21) -#define ROP_SPS BIT(22) -#define SOP_MRST BIT(25) -#define SOP_FUSE BIT(26) -#define SOP_ABG BIT(27) -#define SOP_AMB BIT(28) -#define SOP_RCK BIT(29) -#define SOP_A8M BIT(30) -#define XOP_BTCK BIT(31) - -#define ANAD16V_EN BIT(0) -#define ANA8M BIT(1) -#define MACSLP BIT(4) -#define LOADER_CLK_EN BIT(5) -#define _80M_SSC_DIS BIT(7) -#define _80M_SSC_EN_HO BIT(8) -#define PHY_SSC_RSTB BIT(9) -#define SEC_CLK_EN BIT(10) -#define MAC_CLK_EN BIT(11) -#define SYS_CLK_EN BIT(12) -#define RING_CLK_EN BIT(13) - -#define BOOT_FROM_EEPROM BIT(4) -#define EEPROM_EN BIT(5) - -#define AFE_BGEN BIT(0) -#define AFE_MBEN BIT(1) -#define MAC_ID_EN BIT(7) - -#define WLOCK_ALL BIT(0) -#define WLOCK_00 BIT(1) -#define WLOCK_04 BIT(2) -#define WLOCK_08 BIT(3) -#define WLOCK_40 BIT(4) -#define R_DIS_PRST_0 BIT(5) -#define R_DIS_PRST_1 BIT(6) -#define LOCK_ALL_EN BIT(7) - -#define RF_EN BIT(0) -#define RF_RSTB BIT(1) -#define RF_SDMRSTB BIT(2) - -#define LDA15_EN BIT(0) -#define LDA15_STBY BIT(1) -#define LDA15_OBUF BIT(2) -#define LDA15_REG_VOS BIT(3) -#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) - -#define LDV12_EN BIT(0) -#define LDV12_SDBY BIT(1) -#define LPLDO_HSM BIT(2) -#define LPLDO_LSM_DIS BIT(3) -#define _LDV12_VADJ(x) (((x) & 0xF) << 4) - -#define XTAL_EN BIT(0) -#define XTAL_BSEL BIT(1) -#define _XTAL_BOSC(x) (((x) & 0x3) << 2) -#define _XTAL_CADJ(x) (((x) & 0xF) << 4) -#define XTAL_GATE_USB BIT(8) -#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) -#define XTAL_GATE_AFE BIT(11) -#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) -#define XTAL_RF_GATE BIT(14) -#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) -#define XTAL_GATE_DIG BIT(17) -#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) -#define XTAL_BT_GATE BIT(20) -#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) -#define _XTAL_GPIO(x) (((x) & 0x7) << 23) - -#define CKDLY_AFE BIT(26) -#define CKDLY_USB BIT(27) -#define CKDLY_DIG BIT(28) -#define CKDLY_BT BIT(29) - -#define APLL_EN BIT(0) -#define APLL_320_EN BIT(1) -#define APLL_FREF_SEL BIT(2) -#define APLL_EDGE_SEL BIT(3) -#define APLL_WDOGB BIT(4) -#define APLL_LPFEN BIT(5) - -#define APLL_REF_CLK_13MHZ 0x1 -#define APLL_REF_CLK_19_2MHZ 0x2 -#define APLL_REF_CLK_20MHZ 0x3 -#define APLL_REF_CLK_25MHZ 0x4 -#define APLL_REF_CLK_26MHZ 0x5 -#define APLL_REF_CLK_38_4MHZ 0x6 -#define APLL_REF_CLK_40MHZ 0x7 - -#define APLL_320EN BIT(14) -#define APLL_80EN BIT(15) -#define APLL_1MEN BIT(24) - -#define ALD_EN BIT(18) -#define EF_PD BIT(19) -#define EF_FLAG BIT(31) - -#define EF_TRPT BIT(7) -#define LDOE25_EN BIT(31) - -#define RSM_EN BIT(0) -#define TIMER_EN BIT(4) - -#define TRSW0EN BIT(2) -#define TRSW1EN BIT(3) -#define EROM_EN BIT(4) -#define ENBT BIT(5) -#define ENUART BIT(8) -#define UART_910 BIT(9) -#define ENPMAC BIT(10) -#define SIC_SWRST BIT(11) -#define ENSIC BIT(12) -#define SIC_23 BIT(13) -#define ENHDP BIT(14) -#define SIC_LBK BIT(15) - -#define LED0PL BIT(4) -#define LED1PL BIT(12) -#define LED0DIS BIT(7) - -#define MCUFWDL_EN BIT(0) -#define MCUFWDL_RDY BIT(1) -#define FWDL_CHKSUM_RPT BIT(2) -#define MACINI_RDY BIT(3) -#define BBINI_RDY BIT(4) -#define RFINI_RDY BIT(5) -#define WINTINI_RDY BIT(6) -#define CPRST BIT(23) - -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define TRP_B15V_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define BT_FUNC BIT(16) -#define VENDOR_ID BIT(19) -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) - -#define CHIP_VER_RTL_MASK 0xF000 -#define CHIP_VER_RTL_SHIFT 12 - -#define REG_LBMODE (REG_CR + 3) - -#define HCI_TXDMA_EN BIT(0) -#define HCI_RXDMA_EN BIT(1) -#define TXDMA_EN BIT(2) -#define RXDMA_EN BIT(3) -#define PROTOCOL_EN BIT(4) -#define SCHEDULE_EN BIT(5) -#define MACTXEN BIT(6) -#define MACRXEN BIT(7) -#define ENSWBCN BIT(8) -#define ENSEC BIT(9) - -#define _NETTYPE(x) (((x) & 0x3) << 16) -#define MASK_NETTYPE 0x30000 -#define NT_NO_LINK 0x0 -#define NT_LINK_AD_HOC 0x1 -#define NT_LINK_AP 0x2 -#define NT_AS_AP 0x3 - -#define _LBMODE(x) (((x) & 0xF) << 24) -#define MASK_LBMODE 0xF000000 -#define LOOPBACK_NORMAL 0x0 -#define LOOPBACK_IMMEDIATELY 0xB -#define LOOPBACK_MAC_DELAY 0x3 -#define LOOPBACK_PHY 0x1 -#define LOOPBACK_DMA 0x7 - -#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) -#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) -#define _PSRX_MASK 0xF -#define _PSTX_MASK 0xF0 -#define _PSRX(x) (x) -#define _PSTX(x) ((x) << 4) - -#define PBP_64 0x0 -#define PBP_128 0x1 -#define PBP_256 0x2 -#define PBP_512 0x3 -#define PBP_1024 0x4 - -#define RXDMA_ARBBW_EN BIT(0) -#define RXSHFT_EN BIT(1) -#define RXDMA_AGG_EN BIT(2) -#define QS_VO_QUEUE BIT(8) -#define QS_VI_QUEUE BIT(9) -#define QS_BE_QUEUE BIT(10) -#define QS_BK_QUEUE BIT(11) -#define QS_MANAGER_QUEUE BIT(12) -#define QS_HIGH_QUEUE BIT(13) - -#define HQSEL_VOQ BIT(0) -#define HQSEL_VIQ BIT(1) -#define HQSEL_BEQ BIT(2) -#define HQSEL_BKQ BIT(3) -#define HQSEL_MGTQ BIT(4) -#define HQSEL_HIQ BIT(5) - -#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) -#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) -#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) -#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) -#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) -#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) - -#define QUEUE_LOW 1 -#define QUEUE_NORMAL 2 -#define QUEUE_HIGH 3 - -#define _LLT_NO_ACTIVE 0x0 -#define _LLT_WRITE_ACCESS 0x1 -#define _LLT_READ_ACCESS 0x2 - -#define _LLT_INIT_DATA(x) ((x) & 0xFF) -#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) -#define _LLT_OP(x) (((x) & 0x3) << 30) -#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) - -#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) -#define BB_WRITE_EN BIT(30) -#define BB_READ_EN BIT(31) - -#define _HPQ(x) ((x) & 0xFF) -#define _LPQ(x) (((x) & 0xFF) << 8) -#define _PUBQ(x) (((x) & 0xFF) << 16) -#define _NPQ(x) ((x) & 0xFF) - -#define HPQ_PUBLIC_DIS BIT(24) -#define LPQ_PUBLIC_DIS BIT(25) -#define LD_RQPN BIT(31) - -#define BCN_VALID BIT(16) -#define BCN_HEAD(x) (((x) & 0xFF) << 8) -#define BCN_HEAD_MASK 0xFF00 - -#define BLK_DESC_NUM_SHIFT 4 -#define BLK_DESC_NUM_MASK 0xF - -#define DROP_DATA_EN BIT(9) - -#define EN_AMPDU_RTY_NEW BIT(7) - -#define _INIRTSMCS_SEL(x) ((x) & 0x3F) - -#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) -#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) - -#define RATE_REG_BITMAP_ALL 0xFFFFF - -#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) - -#define _RRSR_RSC(x) (((x) & 0x3) << 21) -#define RRSR_RSC_RESERVED 0x0 -#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 -#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 -#define RRSR_RSC_DUPLICATE_MODE 0x3 - -#define USE_SHORT_G1 BIT(20) - -#define _AGGLMT_MCS0(x) ((x) & 0xF) -#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) -#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) -#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) -#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) -#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) -#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) -#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) - -#define RETRY_LIMIT_SHORT_SHIFT 8 -#define RETRY_LIMIT_LONG_SHIFT 0 - -#define _DARF_RC1(x) ((x) & 0x1F) -#define _DARF_RC2(x) (((x) & 0x1F) << 8) -#define _DARF_RC3(x) (((x) & 0x1F) << 16) -#define _DARF_RC4(x) (((x) & 0x1F) << 24) -#define _DARF_RC5(x) ((x) & 0x1F) -#define _DARF_RC6(x) (((x) & 0x1F) << 8) -#define _DARF_RC7(x) (((x) & 0x1F) << 16) -#define _DARF_RC8(x) (((x) & 0x1F) << 24) - -#define _RARF_RC1(x) ((x) & 0x1F) -#define _RARF_RC2(x) (((x) & 0x1F) << 8) -#define _RARF_RC3(x) (((x) & 0x1F) << 16) -#define _RARF_RC4(x) (((x) & 0x1F) << 24) -#define _RARF_RC5(x) ((x) & 0x1F) -#define _RARF_RC6(x) (((x) & 0x1F) << 8) -#define _RARF_RC7(x) (((x) & 0x1F) << 16) -#define _RARF_RC8(x) (((x) & 0x1F) << 24) - -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - -#define _AIFS(x) (x) -#define _ECW_MAX_MIN(x) ((x) << 8) -#define _TXOP_LIMIT(x) ((x) << 16) - -#define _BCNIFS(x) ((x) & 0xFF) -#define _BCNECW(x) ((((x) & 0xF)) << 8) - -#define _LRL(x) ((x) & 0x3F) -#define _SRL(x) (((x) & 0x3F) << 8) - -#define _SIFS_CCK_CTX(x) ((x) & 0xFF) -#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8) - -#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) -#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8) - -#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) - -#define DIS_EDCA_CNT_DWN BIT(11) - -#define EN_MBSSID BIT(1) -#define EN_TXBCN_RPT BIT(2) -#define EN_BCN_FUNCTION BIT(3) - -#define TSFTR_RST BIT(0) -#define TSFTR1_RST BIT(1) - -#define STOP_BCNQ BIT(6) - -#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) -#define DIS_TSF_UDT0_TEST_CHIP BIT(5) - -#define ACMHW_HWEN BIT(0) -#define ACMHW_BEQEN BIT(1) -#define ACMHW_VIQEN BIT(2) -#define ACMHW_VOQEN BIT(3) -#define ACMHW_BEQSTATUS BIT(4) -#define ACMHW_VIQSTATUS BIT(5) -#define ACMHW_VOQSTATUS BIT(6) - -#define APSDOFF BIT(6) -#define APSDOFF_STATUS BIT(7) - -#define BW_20MHZ BIT(2) - -#define RATE_BITMAP_ALL 0xFFFFF - -#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 - -#define TSFRST BIT(0) -#define DIS_GCLK BIT(1) -#define PAD_SEL BIT(2) -#define PWR_ST BIT(6) -#define PWRBIT_OW_EN BIT(7) -#define ACRC BIT(8) -#define CFENDFORM BIT(9) -#define ICV BIT(10) - -#define AAP BIT(0) -#define APM BIT(1) -#define AM BIT(2) -#define AB BIT(3) -#define ADD3 BIT(4) -#define APWRMGT BIT(5) -#define CBSSID BIT(6) -#define CBSSID_DATA BIT(6) -#define CBSSID_BCN BIT(7) -#define ACRC32 BIT(8) -#define AICV BIT(9) -#define ADF BIT(11) -#define ACF BIT(12) -#define AMF BIT(13) -#define HTC_LOC_CTRL BIT(14) -#define UC_DATA_EN BIT(16) -#define BM_DATA_EN BIT(17) -#define MFBEN BIT(22) -#define LSIGEN BIT(23) -#define ENMBID BIT(24) -#define APP_BASSN BIT(27) -#define APP_PHYSTS BIT(28) -#define APP_ICV BIT(29) -#define APP_MIC BIT(30) -#define APP_FCS BIT(31) - -#define _MIN_SPACE(x) ((x) & 0x7) -#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) - -#define RXERR_TYPE_OFDM_PPDU 0 -#define RXERR_TYPE_OFDM_FALSE_ALARM 1 -#define RXERR_TYPE_OFDM_MPDU_OK 2 -#define RXERR_TYPE_OFDM_MPDU_FAIL 3 -#define RXERR_TYPE_CCK_PPDU 4 -#define RXERR_TYPE_CCK_FALSE_ALARM 5 -#define RXERR_TYPE_CCK_MPDU_OK 6 -#define RXERR_TYPE_CCK_MPDU_FAIL 7 -#define RXERR_TYPE_HT_PPDU 8 -#define RXERR_TYPE_HT_FALSE_ALARM 9 -#define RXERR_TYPE_HT_MPDU_TOTAL 10 -#define RXERR_TYPE_HT_MPDU_OK 11 -#define RXERR_TYPE_HT_MPDU_FAIL 12 -#define RXERR_TYPE_RX_FULL_DROP 15 - -#define RXERR_COUNTER_MASK 0xFFFFF -#define RXERR_RPT_RST BIT(27) -#define _RXERR_RPT_SEL(type) ((type) << 28) - -#define SCR_TXUSEDK BIT(0) -#define SCR_RXUSEDK BIT(1) -#define SCR_TXENCENABLE BIT(2) -#define SCR_RXDECENABLE BIT(3) -#define SCR_SKBYA2 BIT(4) -#define SCR_NOSKMC BIT(5) -#define SCR_TXBCUSEDK BIT(6) -#define SCR_RXBCUSEDK BIT(7) - -#define USB_IS_HIGH_SPEED 0 -#define USB_IS_FULL_SPEED 1 -#define USB_SPEED_MASK BIT(5) - -#define USB_NORMAL_SIE_EP_MASK 0xF -#define USB_NORMAL_SIE_EP_SHIFT 4 - -#define USB_TEST_EP_MASK 0x30 -#define USB_TEST_EP_SHIFT 4 - -#define USB_AGG_EN BIT(3) - -#define MAC_ADDR_LEN 6 -#define LAST_ENTRY_OF_TX_PKT_BUFFER 255 - -#define POLLING_LLT_THRESHOLD 20 -#define POLLING_READY_TIMEOUT_COUNT 1000 - -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) -#define EPROM_CMD_CONFIG 0x3 -#define EPROM_CMD_LOAD 1 - -#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE - -#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) - -#define RPMAC_RESET 0x100 -#define RPMAC_TXSTART 0x104 -#define RPMAC_TXLEGACYSIG 0x108 -#define RPMAC_TXHTSIG1 0x10c -#define RPMAC_TXHTSIG2 0x110 -#define RPMAC_PHYDEBUG 0x114 -#define RPMAC_TXPACKETNUM 0x118 -#define RPMAC_TXIDLE 0x11c -#define RPMAC_TXMACHEADER0 0x120 -#define RPMAC_TXMACHEADER1 0x124 -#define RPMAC_TXMACHEADER2 0x128 -#define RPMAC_TXMACHEADER3 0x12c -#define RPMAC_TXMACHEADER4 0x130 -#define RPMAC_TXMACHEADER5 0x134 -#define RPMAC_TXDADATYPE 0x138 -#define RPMAC_TXRANDOMSEED 0x13c -#define RPMAC_CCKPLCPPREAMBLE 0x140 -#define RPMAC_CCKPLCPHEADER 0x144 -#define RPMAC_CCKCRC16 0x148 -#define RPMAC_OFDMRXCRC32OK 0x170 -#define RPMAC_OFDMRXCRC32ER 0x174 -#define RPMAC_OFDMRXPARITYER 0x178 -#define RPMAC_OFDMRXCRC8ER 0x17c -#define RPMAC_CCKCRXRC16ER 0x180 -#define RPMAC_CCKCRXRC32ER 0x184 -#define RPMAC_CCKCRXRC32OK 0x188 -#define RPMAC_TXSTATUS 0x18c - -#define RFPGA0_RFMOD 0x800 - -#define RFPGA0_TXINFO 0x804 -#define RFPGA0_PSDFUNCTION 0x808 - -#define RFPGA0_TXGAINSTAGE 0x80c - -#define RFPGA0_RFTIMING1 0x810 -#define RFPGA0_RFTIMING2 0x814 - -#define RFPGA0_XA_HSSIPARAMETER1 0x820 -#define RFPGA0_XA_HSSIPARAMETER2 0x824 -#define RFPGA0_XB_HSSIPARAMETER1 0x828 -#define RFPGA0_XB_HSSIPARAMETER2 0x82c - -#define RFPGA0_XA_LSSIPARAMETER 0x840 -#define RFPGA0_XB_LSSIPARAMETER 0x844 - -#define RFPGA0_RFWAKEUPPARAMETER 0x850 -#define RFPGA0_RFSLEEPUPPARAMETER 0x854 - -#define RFPGA0_XAB_SWITCHCONTROL 0x858 -#define RFPGA0_XCD_SWITCHCONTROL 0x85c - -#define RFPGA0_XA_RFINTERFACEOE 0x860 -#define RFPGA0_XB_RFINTERFACEOE 0x864 - -#define RFPGA0_XAB_RFINTERFACESW 0x870 -#define RFPGA0_XCD_RFINTERFACESW 0x874 - -#define RFPGA0_XAB_RFPARAMETER 0x878 -#define RFPGA0_XCD_RFPARAMETER 0x87c - -#define RFPGA0_ANALOGPARAMETER1 0x880 -#define RFPGA0_ANALOGPARAMETER2 0x884 -#define RFPGA0_ANALOGPARAMETER3 0x888 -#define RFPGA0_ANALOGPARAMETER4 0x88c - -#define RFPGA0_XA_LSSIREADBACK 0x8a0 -#define RFPGA0_XB_LSSIREADBACK 0x8a4 -#define RFPGA0_XC_LSSIREADBACK 0x8a8 -#define RFPGA0_XD_LSSIREADBACK 0x8ac - -#define RFPGA0_PSDREPORT 0x8b4 -#define TRANSCEIVEA_HSPI_READBACK 0x8b8 -#define TRANSCEIVEB_HSPI_READBACK 0x8bc -#define RFPGA0_XAB_RFINTERFACERB 0x8e0 -#define RFPGA0_XCD_RFINTERFACERB 0x8e4 - -#define RFPGA1_RFMOD 0x900 - -#define RFPGA1_TXBLOCK 0x904 -#define RFPGA1_DEBUGSELECT 0x908 -#define RFPGA1_TXINFO 0x90c - -#define RCCK0_SYSTEM 0xa00 - -#define RCCK0_AFESETTING 0xa04 -#define RCCK0_CCA 0xa08 - -#define RCCK0_RXAGC1 0xa0c -#define RCCK0_RXAGC2 0xa10 - -#define RCCK0_RXHP 0xa14 - -#define RCCK0_DSPPARAMETER1 0xa18 -#define RCCK0_DSPPARAMETER2 0xa1c - -#define RCCK0_TXFILTER1 0xa20 -#define RCCK0_TXFILTER2 0xa24 -#define RCCK0_DEBUGPORT 0xa28 -#define RCCK0_FALSEALARMREPORT 0xa2c -#define RCCK0_TRSSIREPORT 0xa50 -#define RCCK0_RXREPORT 0xa54 -#define RCCK0_FACOUNTERLOWER 0xa5c -#define RCCK0_FACOUNTERUPPER 0xa58 - -#define ROFDM0_LSTF 0xc00 - -#define ROFDM0_TRXPATHENABLE 0xc04 -#define ROFDM0_TRMUXPAR 0xc08 -#define ROFDM0_TRSWISOLATION 0xc0c - -#define ROFDM0_XARXAFE 0xc10 -#define ROFDM0_XARXIQIMBALANCE 0xc14 -#define ROFDM0_XBRXAFE 0xc18 -#define ROFDM0_XBRXIQIMBALANCE 0xc1c -#define ROFDM0_XCRXAFE 0xc20 -#define ROFDM0_XCRXIQIMBANLANCE 0xc24 -#define ROFDM0_XDRXAFE 0xc28 -#define ROFDM0_XDRXIQIMBALANCE 0xc2c - -#define ROFDM0_RXDETECTOR1 0xc30 -#define ROFDM0_RXDETECTOR2 0xc34 -#define ROFDM0_RXDETECTOR3 0xc38 -#define ROFDM0_RXDETECTOR4 0xc3c - -#define ROFDM0_RXDSP 0xc40 -#define ROFDM0_CFOANDDAGC 0xc44 -#define ROFDM0_CCADROPTHRESHOLD 0xc48 -#define ROFDM0_ECCATHRESHOLD 0xc4c - -#define ROFDM0_XAAGCCORE1 0xc50 -#define ROFDM0_XAAGCCORE2 0xc54 -#define ROFDM0_XBAGCCORE1 0xc58 -#define ROFDM0_XBAGCCORE2 0xc5c -#define ROFDM0_XCAGCCORE1 0xc60 -#define ROFDM0_XCAGCCORE2 0xc64 -#define ROFDM0_XDAGCCORE1 0xc68 -#define ROFDM0_XDAGCCORE2 0xc6c - -#define ROFDM0_AGCPARAMETER1 0xc70 -#define ROFDM0_AGCPARAMETER2 0xc74 -#define ROFDM0_AGCRSSITABLE 0xc78 -#define ROFDM0_HTSTFAGC 0xc7c - -#define ROFDM0_XATXIQIMBALANCE 0xc80 -#define ROFDM0_XATXAFE 0xc84 -#define ROFDM0_XBTXIQIMBALANCE 0xc88 -#define ROFDM0_XBTXAFE 0xc8c -#define ROFDM0_XCTXIQIMBALANCE 0xc90 -#define ROFDM0_XCTXAFE 0xc94 -#define ROFDM0_XDTXIQIMBALANCE 0xc98 -#define ROFDM0_XDTXAFE 0xc9c - -#define ROFDM0_RXIQEXTANTA 0xca0 - -#define ROFDM0_RXHPPARAMETER 0xce0 -#define ROFDM0_TXPSEUDONOISEWGT 0xce4 -#define ROFDM0_FRAMESYNC 0xcf0 -#define ROFDM0_DFSREPORT 0xcf4 -#define ROFDM0_TXCOEFF1 0xca4 -#define ROFDM0_TXCOEFF2 0xca8 -#define ROFDM0_TXCOEFF3 0xcac -#define ROFDM0_TXCOEFF4 0xcb0 -#define ROFDM0_TXCOEFF5 0xcb4 -#define ROFDM0_TXCOEFF6 0xcb8 - -#define ROFDM1_LSTF 0xd00 -#define ROFDM1_TRXPATHENABLE 0xd04 - -#define ROFDM1_CF0 0xd08 -#define ROFDM1_CSI1 0xd10 -#define ROFDM1_SBD 0xd14 -#define ROFDM1_CSI2 0xd18 -#define ROFDM1_CFOTRACKING 0xd2c -#define ROFDM1_TRXMESAURE1 0xd34 -#define ROFDM1_INTFDET 0xd3c -#define ROFDM1_PSEUDONOISESTATEAB 0xd50 -#define ROFDM1_PSEUDONOISESTATECD 0xd54 -#define ROFDM1_RXPSEUDONOISEWGT 0xd58 - -#define ROFDM_PHYCOUNTER1 0xda0 -#define ROFDM_PHYCOUNTER2 0xda4 -#define ROFDM_PHYCOUNTER3 0xda8 - -#define ROFDM_SHORTCFOAB 0xdac -#define ROFDM_SHORTCFOCD 0xdb0 -#define ROFDM_LONGCFOAB 0xdb4 -#define ROFDM_LONGCFOCD 0xdb8 -#define ROFDM_TAILCF0AB 0xdbc -#define ROFDM_TAILCF0CD 0xdc0 -#define ROFDM_PWMEASURE1 0xdc4 -#define ROFDM_PWMEASURE2 0xdc8 -#define ROFDM_BWREPORT 0xdcc -#define ROFDM_AGCREPORT 0xdd0 -#define ROFDM_RXSNR 0xdd4 -#define ROFDM_RXEVMCSI 0xdd8 -#define ROFDM_SIGREPORT 0xddc - -#define RTXAGC_A_RATE18_06 0xe00 -#define RTXAGC_A_RATE54_24 0xe04 -#define RTXAGC_A_CCK1_MCS32 0xe08 -#define RTXAGC_A_MCS03_MCS00 0xe10 -#define RTXAGC_A_MCS07_MCS04 0xe14 -#define RTXAGC_A_MCS11_MCS08 0xe18 -#define RTXAGC_A_MCS15_MCS12 0xe1c - -#define RTXAGC_B_RATE18_06 0x830 -#define RTXAGC_B_RATE54_24 0x834 -#define RTXAGC_B_CCK1_55_MCS32 0x838 -#define RTXAGC_B_MCS03_MCS00 0x83c -#define RTXAGC_B_MCS07_MCS04 0x848 -#define RTXAGC_B_MCS11_MCS08 0x84c -#define RTXAGC_B_MCS15_MCS12 0x868 -#define RTXAGC_B_CCK11_A_CCK2_11 0x86c - -#define RZEBRA1_HSSIENABLE 0x0 -#define RZEBRA1_TRXENABLE1 0x1 -#define RZEBRA1_TRXENABLE2 0x2 -#define RZEBRA1_AGC 0x4 -#define RZEBRA1_CHARGEPUMP 0x5 -#define RZEBRA1_CHANNEL 0x7 - -#define RZEBRA1_TXGAIN 0x8 -#define RZEBRA1_TXLPF 0x9 -#define RZEBRA1_RXLPF 0xb -#define RZEBRA1_RXHPFCORNER 0xc - -#define RGLOBALCTRL 0 -#define RRTL8256_TXLPF 19 -#define RRTL8256_RXLPF 11 -#define RRTL8258_TXLPF 0x11 -#define RRTL8258_RXLPF 0x13 -#define RRTL8258_RSSILPF 0xa - -#define RF_AC 0x00 - -#define RF_IQADJ_G1 0x01 -#define RF_IQADJ_G2 0x02 -#define RF_POW_TRSW 0x05 - -#define RF_GAIN_RX 0x06 -#define RF_GAIN_TX 0x07 - -#define RF_TXM_IDAC 0x08 -#define RF_BS_IQGEN 0x0F - -#define RF_MODE1 0x10 -#define RF_MODE2 0x11 - -#define RF_RX_AGC_HP 0x12 -#define RF_TX_AGC 0x13 -#define RF_BIAS 0x14 -#define RF_IPA 0x15 -#define RF_POW_ABILITY 0x17 -#define RF_MODE_AG 0x18 -#define RRFCHANNEL 0x18 -#define RF_CHNLBW 0x18 -#define RF_TOP 0x19 - -#define RF_RX_G1 0x1A -#define RF_RX_G2 0x1B - -#define RF_RX_BB2 0x1C -#define RF_RX_BB1 0x1D - -#define RF_RCK1 0x1E -#define RF_RCK2 0x1F - -#define RF_TX_G1 0x20 -#define RF_TX_G2 0x21 -#define RF_TX_G3 0x22 - -#define RF_TX_BB1 0x23 -#define RF_T_METER 0x24 - -#define RF_SYN_G1 0x25 -#define RF_SYN_G2 0x26 -#define RF_SYN_G3 0x27 -#define RF_SYN_G4 0x28 -#define RF_SYN_G5 0x29 -#define RF_SYN_G6 0x2A -#define RF_SYN_G7 0x2B -#define RF_SYN_G8 0x2C - -#define RF_RCK_OS 0x30 -#define RF_TXPA_G1 0x31 -#define RF_TXPA_G2 0x32 -#define RF_TXPA_G3 0x33 - -#define BBBRESETB 0x100 -#define BGLOBALRESETB 0x200 -#define BOFDMTXSTART 0x4 -#define BCCKTXSTART 0x8 -#define BCRC32DEBUG 0x100 -#define BPMACLOOPBACK 0x10 -#define BTXLSIG 0xffffff -#define BOFDMTXRATE 0xf -#define BOFDMTXRESERVED 0x10 -#define BOFDMTXLENGTH 0x1ffe0 -#define BOFDMTXPARITY 0x20000 -#define BTXHTSIG1 0xffffff -#define BTXHTMCSRATE 0x7f -#define BTXHTBW 0x80 -#define BTXHTLENGTH 0xffff00 -#define BTXHTSIG2 0xffffff -#define BTXHTSMOOTHING 0x1 -#define BTXHTSOUNDING 0x2 -#define BTXHTRESERVED 0x4 -#define BTXHTAGGREATION 0x8 -#define BTXHTSTBC 0x30 -#define BTXHTADVANCECODING 0x40 -#define BTXHTSHORTGI 0x80 -#define BTXHTNUMBERHT_LTF 0x300 -#define BTXHTCRC8 0x3fc00 -#define BCOUNTERRESET 0x10000 -#define BNUMOFOFDMTX 0xffff -#define BNUMOFCCKTX 0xffff0000 -#define BTXIDLEINTERVAL 0xffff -#define BOFDMSERVICE 0xffff0000 -#define BTXMACHEADER 0xffffffff -#define BTXDATAINIT 0xff -#define BTXHTMODE 0x100 -#define BTXDATATYPE 0x30000 -#define BTXRANDOMSEED 0xffffffff -#define BCCKTXPREAMBLE 0x1 -#define BCCKTXSFD 0xffff0000 -#define BCCKTXSIG 0xff -#define BCCKTXSERVICE 0xff00 -#define BCCKLENGTHEXT 0x8000 -#define BCCKTXLENGHT 0xffff0000 -#define BCCKTXCRC16 0xffff -#define BCCKTXSTATUS 0x1 -#define BOFDMTXSTATUS 0x2 -#define IS_BB_REG_OFFSET_92S(_offset) \ - ((_offset >= 0x800) && (_offset <= 0xfff)) - -#define BRFMOD 0x1 -#define BJAPANMODE 0x2 -#define BCCKTXSC 0x30 -#define BCCKEN 0x1000000 -#define BOFDMEN 0x2000000 - -#define BOFDMRXADCPHASE 0x10000 -#define BOFDMTXDACPHASE 0x40000 -#define BXATXAGC 0x3f - -#define BXBTXAGC 0xf00 -#define BXCTXAGC 0xf000 -#define BXDTXAGC 0xf0000 - -#define BPASTART 0xf0000000 -#define BTRSTART 0x00f00000 -#define BRFSTART 0x0000f000 -#define BBBSTART 0x000000f0 -#define BBBCCKSTART 0x0000000f -#define BPAEND 0xf -#define BTREND 0x0f000000 -#define BRFEND 0x000f0000 -#define BCCAMASK 0x000000f0 -#define BR2RCCAMASK 0x00000f00 -#define BHSSI_R2TDELAY 0xf8000000 -#define BHSSI_T2RDELAY 0xf80000 -#define BCONTXHSSI 0x400 -#define BIGFROMCCK 0x200 -#define BAGCADDRESS 0x3f -#define BRXHPTX 0x7000 -#define BRXHP2RX 0x38000 -#define BRXHPCCKINI 0xc0000 -#define BAGCTXCODE 0xc00000 -#define BAGCRXCODE 0x300000 - -#define B3WIREDATALENGTH 0x800 -#define B3WIREADDREAALENGTH 0x400 - -#define B3WIRERFPOWERDOWN 0x1 -#define B5GPAPEPOLARITY 0x40000000 -#define B2GPAPEPOLARITY 0x80000000 -#define BRFSW_TXDEFAULTANT 0x3 -#define BRFSW_TXOPTIONANT 0x30 -#define BRFSW_RXDEFAULTANT 0x300 -#define BRFSW_RXOPTIONANT 0x3000 -#define BRFSI_3WIREDATA 0x1 -#define BRFSI_3WIRECLOCK 0x2 -#define BRFSI_3WIRELOAD 0x4 -#define BRFSI_3WIRERW 0x8 -#define BRFSI_3WIRE 0xf - -#define BRFSI_RFENV 0x10 - -#define BRFSI_TRSW 0x20 -#define BRFSI_TRSWB 0x40 -#define BRFSI_ANTSW 0x100 -#define BRFSI_ANTSWB 0x200 -#define BRFSI_PAPE 0x400 -#define BRFSI_PAPE5G 0x800 -#define BBANDSELECT 0x1 -#define BHTSIG2_GI 0x80 -#define BHTSIG2_SMOOTHING 0x01 -#define BHTSIG2_SOUNDING 0x02 -#define BHTSIG2_AGGREATON 0x08 -#define BHTSIG2_STBC 0x30 -#define BHTSIG2_ADVCODING 0x40 -#define BHTSIG2_NUMOFHTLTF 0x300 -#define BHTSIG2_CRC8 0x3fc -#define BHTSIG1_MCS 0x7f -#define BHTSIG1_BANDWIDTH 0x80 -#define BHTSIG1_HTLENGTH 0xffff -#define BLSIG_RATE 0xf -#define BLSIG_RESERVED 0x10 -#define BLSIG_LENGTH 0x1fffe -#define BLSIG_PARITY 0x20 -#define BCCKRXPHASE 0x4 - -#define BLSSIREADADDRESS 0x7f800000 -#define BLSSIREADEDGE 0x80000000 - -#define BLSSIREADBACKDATA 0xfffff - -#define BLSSIREADOKFLAG 0x1000 -#define BCCKSAMPLERATE 0x8 -#define BREGULATOR0STANDBY 0x1 -#define BREGULATORPLLSTANDBY 0x2 -#define BREGULATOR1STANDBY 0x4 -#define BPLLPOWERUP 0x8 -#define BDPLLPOWERUP 0x10 -#define BDA10POWERUP 0x20 -#define BAD7POWERUP 0x200 -#define BDA6POWERUP 0x2000 -#define BXTALPOWERUP 0x4000 -#define B40MDCLKPOWERUP 0x8000 -#define BDA6DEBUGMODE 0x20000 -#define BDA6SWING 0x380000 - -#define BADCLKPHASE 0x4000000 -#define B80MCLKDELAY 0x18000000 -#define BAFEWATCHDOGENABLE 0x20000000 - -#define BXTALCAP01 0xc0000000 -#define BXTALCAP23 0x3 -#define BXTALCAP92X 0x0f000000 -#define BXTALCAP 0x0f000000 - -#define BINTDIFCLKENABLE 0x400 -#define BEXTSIGCLKENABLE 0x800 -#define BBANDGAP_MBIAS_POWERUP 0x10000 -#define BAD11SH_GAIN 0xc0000 -#define BAD11NPUT_RANGE 0x700000 -#define BAD110P_CURRENT 0x3800000 -#define BLPATH_LOOPBACK 0x4000000 -#define BQPATH_LOOPBACK 0x8000000 -#define BAFE_LOOPBACK 0x10000000 -#define BDA10_SWING 0x7e0 -#define BDA10_REVERSE 0x800 -#define BDA_CLK_SOURCE 0x1000 -#define BDA7INPUT_RANGE 0x6000 -#define BDA7_GAIN 0x38000 -#define BDA7OUTPUT_CM_MODE 0x40000 -#define BDA7INPUT_CM_MODE 0x380000 -#define BDA7CURRENT 0xc00000 -#define BREGULATOR_ADJUST 0x7000000 -#define BAD11POWERUP_ATTX 0x1 -#define BDA10PS_ATTX 0x10 -#define BAD11POWERUP_ATRX 0x100 -#define BDA10PS_ATRX 0x1000 -#define BCCKRX_AGC_FORMAT 0x200 -#define BPSDFFT_SAMPLE_POINT 0xc000 -#define BPSD_AVERAGE_NUM 0x3000 -#define BIQPATH_CONTROL 0xc00 -#define BPSD_FREQ 0x3ff -#define BPSD_ANTENNA_PATH 0x30 -#define BPSD_IQ_SWITCH 0x40 -#define BPSD_RX_TRIGGER 0x400000 -#define BPSD_TX_TRIGGER 0x80000000 -#define BPSD_SINE_TONE_SCALE 0x7f000000 -#define BPSD_REPORT 0xffff - -#define BOFDM_TXSC 0x30000000 -#define BCCK_TXON 0x1 -#define BOFDM_TXON 0x2 -#define BDEBUG_PAGE 0xfff -#define BDEBUG_ITEM 0xff -#define BANTL 0x10 -#define BANT_NONHT 0x100 -#define BANT_HT1 0x1000 -#define BANT_HT2 0x10000 -#define BANT_HT1S1 0x100000 -#define BANT_NONHTS1 0x1000000 - -#define BCCK_BBMODE 0x3 -#define BCCK_TXPOWERSAVING 0x80 -#define BCCK_RXPOWERSAVING 0x40 - -#define BCCK_SIDEBAND 0x10 - -#define BCCK_SCRAMBLE 0x8 -#define BCCK_ANTDIVERSITY 0x8000 -#define BCCK_CARRIER_RECOVERY 0x4000 -#define BCCK_TXRATE 0x3000 -#define BCCK_DCCANCEL 0x0800 -#define BCCK_ISICANCEL 0x0400 -#define BCCK_MATCH_FILTER 0x0200 -#define BCCK_EQUALIZER 0x0100 -#define BCCK_PREAMBLE_DETECT 0x800000 -#define BCCK_FAST_FALSECCA 0x400000 -#define BCCK_CH_ESTSTART 0x300000 -#define BCCK_CCA_COUNT 0x080000 -#define BCCK_CS_LIM 0x070000 -#define BCCK_BIST_MODE 0x80000000 -#define BCCK_CCAMASK 0x40000000 -#define BCCK_TX_DAC_PHASE 0x4 -#define BCCK_RX_ADC_PHASE 0x20000000 -#define BCCKR_CP_MODE 0x0100 -#define BCCK_TXDC_OFFSET 0xf0 -#define BCCK_RXDC_OFFSET 0xf -#define BCCK_CCA_MODE 0xc000 -#define BCCK_FALSECS_LIM 0x3f00 -#define BCCK_CS_RATIO 0xc00000 -#define BCCK_CORGBIT_SEL 0x300000 -#define BCCK_PD_LIM 0x0f0000 -#define BCCK_NEWCCA 0x80000000 -#define BCCK_RXHP_OF_IG 0x8000 -#define BCCK_RXIG 0x7f00 -#define BCCK_LNA_POLARITY 0x800000 -#define BCCK_RX1ST_BAIN 0x7f0000 -#define BCCK_RF_EXTEND 0x20000000 -#define BCCK_RXAGC_SATLEVEL 0x1f000000 -#define BCCK_RXAGC_SATCOUNT 0xe0 -#define BCCKRXRFSETTLE 0x1f -#define BCCK_FIXED_RXAGC 0x8000 -#define BCCK_ANTENNA_POLARITY 0x2000 -#define BCCK_TXFILTER_TYPE 0x0c00 -#define BCCK_RXAGC_REPORTTYPE 0x0300 -#define BCCK_RXDAGC_EN 0x80000000 -#define BCCK_RXDAGC_PERIOD 0x20000000 -#define BCCK_RXDAGC_SATLEVEL 0x1f000000 -#define BCCK_TIMING_RECOVERY 0x800000 -#define BCCK_TXC0 0x3f0000 -#define BCCK_TXC1 0x3f000000 -#define BCCK_TXC2 0x3f -#define BCCK_TXC3 0x3f00 -#define BCCK_TXC4 0x3f0000 -#define BCCK_TXC5 0x3f000000 -#define BCCK_TXC6 0x3f -#define BCCK_TXC7 0x3f00 -#define BCCK_DEBUGPORT 0xff0000 -#define BCCK_DAC_DEBUG 0x0f000000 -#define BCCK_FALSEALARM_ENABLE 0x8000 -#define BCCK_FALSEALARM_READ 0x4000 -#define BCCK_TRSSI 0x7f -#define BCCK_RXAGC_REPORT 0xfe -#define BCCK_RXREPORT_ANTSEL 0x80000000 -#define BCCK_RXREPORT_MFOFF 0x40000000 -#define BCCK_RXREPORT_SQLOSS 0x20000000 -#define BCCK_RXREPORT_PKTLOSS 0x10000000 -#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 -#define BCCK_RXREPORT_RATEERROR 0x04000000 -#define BCCK_RXREPORT_RXRATE 0x03000000 -#define BCCK_RXFA_COUNTER_LOWER 0xff -#define BCCK_RXFA_COUNTER_UPPER 0xff000000 -#define BCCK_RXHPAGC_START 0xe000 -#define BCCK_RXHPAGC_FINAL 0x1c00 -#define BCCK_RXFALSEALARM_ENABLE 0x8000 -#define BCCK_FACOUNTER_FREEZE 0x4000 -#define BCCK_TXPATH_SEL 0x10000000 -#define BCCK_DEFAULT_RXPATH 0xc000000 -#define BCCK_OPTION_RXPATH 0x3000000 - -#define BNUM_OFSTF 0x3 -#define BSHIFT_L 0xc0 -#define BGI_TH 0xc -#define BRXPATH_A 0x1 -#define BRXPATH_B 0x2 -#define BRXPATH_C 0x4 -#define BRXPATH_D 0x8 -#define BTXPATH_A 0x1 -#define BTXPATH_B 0x2 -#define BTXPATH_C 0x4 -#define BTXPATH_D 0x8 -#define BTRSSI_FREQ 0x200 -#define BADC_BACKOFF 0x3000 -#define BDFIR_BACKOFF 0xc000 -#define BTRSSI_LATCH_PHASE 0x10000 -#define BRX_LDC_OFFSET 0xff -#define BRX_QDC_OFFSET 0xff00 -#define BRX_DFIR_MODE 0x1800000 -#define BRX_DCNF_TYPE 0xe000000 -#define BRXIQIMB_A 0x3ff -#define BRXIQIMB_B 0xfc00 -#define BRXIQIMB_C 0x3f0000 -#define BRXIQIMB_D 0xffc00000 -#define BDC_DC_NOTCH 0x60000 -#define BRXNB_NOTCH 0x1f000000 -#define BPD_TH 0xf -#define BPD_TH_OPT2 0xc000 -#define BPWED_TH 0x700 -#define BIFMF_WIN_L 0x800 -#define BPD_OPTION 0x1000 -#define BMF_WIN_L 0xe000 -#define BBW_SEARCH_L 0x30000 -#define BWIN_ENH_L 0xc0000 -#define BBW_TH 0x700000 -#define BED_TH2 0x3800000 -#define BBW_OPTION 0x4000000 -#define BRADIO_TH 0x18000000 -#define BWINDOW_L 0xe0000000 -#define BSBD_OPTION 0x1 -#define BFRAME_TH 0x1c -#define BFS_OPTION 0x60 -#define BDC_SLOPE_CHECK 0x80 -#define BFGUARD_COUNTER_DC_L 0xe00 -#define BFRAME_WEIGHT_SHORT 0x7000 -#define BSUB_TUNE 0xe00000 -#define BFRAME_DC_LENGTH 0xe000000 -#define BSBD_START_OFFSET 0x30000000 -#define BFRAME_TH_2 0x7 -#define BFRAME_GI2_TH 0x38 -#define BGI2_SYNC_EN 0x40 -#define BSARCH_SHORT_EARLY 0x300 -#define BSARCH_SHORT_LATE 0xc00 -#define BSARCH_GI2_LATE 0x70000 -#define BCFOANTSUM 0x1 -#define BCFOACC 0x2 -#define BCFOSTARTOFFSET 0xc -#define BCFOLOOPBACK 0x70 -#define BCFOSUMWEIGHT 0x80 -#define BDAGCENABLE 0x10000 -#define BTXIQIMB_A 0x3ff -#define BTXIQIMB_b 0xfc00 -#define BTXIQIMB_C 0x3f0000 -#define BTXIQIMB_D 0xffc00000 -#define BTXIDCOFFSET 0xff -#define BTXIQDCOFFSET 0xff00 -#define BTXDFIRMODE 0x10000 -#define BTXPESUDO_NOISEON 0x4000000 -#define BTXPESUDO_NOISE_A 0xff -#define BTXPESUDO_NOISE_B 0xff00 -#define BTXPESUDO_NOISE_C 0xff0000 -#define BTXPESUDO_NOISE_D 0xff000000 -#define BCCA_DROPOPTION 0x20000 -#define BCCA_DROPTHRES 0xfff00000 -#define BEDCCA_H 0xf -#define BEDCCA_L 0xf0 -#define BLAMBDA_ED 0x300 -#define BRX_INITIALGAIN 0x7f -#define BRX_ANTDIV_EN 0x80 -#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 -#define BRX_HIGHPOWER_FLOW 0x8000 -#define BRX_AGC_FREEZE_THRES 0xc0000 -#define BRX_FREEZESTEP_AGC1 0x300000 -#define BRX_FREEZESTEP_AGC2 0xc00000 -#define BRX_FREEZESTEP_AGC3 0x3000000 -#define BRX_FREEZESTEP_AGC0 0xc000000 -#define BRXRSSI_CMP_EN 0x10000000 -#define BRXQUICK_AGCEN 0x20000000 -#define BRXAGC_FREEZE_THRES_MODE 0x40000000 -#define BRX_OVERFLOW_CHECKTYPE 0x80000000 -#define BRX_AGCSHIFT 0x7f -#define BTRSW_TRI_ONLY 0x80 -#define BPOWER_THRES 0x300 -#define BRXAGC_EN 0x1 -#define BRXAGC_TOGETHER_EN 0x2 -#define BRXAGC_MIN 0x4 -#define BRXHP_INI 0x7 -#define BRXHP_TRLNA 0x70 -#define BRXHP_RSSI 0x700 -#define BRXHP_BBP1 0x7000 -#define BRXHP_BBP2 0x70000 -#define BRXHP_BBP3 0x700000 -#define BRSSI_H 0x7f0000 -#define BRSSI_GEN 0x7f000000 -#define BRXSETTLE_TRSW 0x7 -#define BRXSETTLE_LNA 0x38 -#define BRXSETTLE_RSSI 0x1c0 -#define BRXSETTLE_BBP 0xe00 -#define BRXSETTLE_RXHP 0x7000 -#define BRXSETTLE_ANTSW_RSSI 0x38000 -#define BRXSETTLE_ANTSW 0xc0000 -#define BRXPROCESS_TIME_DAGC 0x300000 -#define BRXSETTLE_HSSI 0x400000 -#define BRXPROCESS_TIME_BBPPW 0x800000 -#define BRXANTENNA_POWER_SHIFT 0x3000000 -#define BRSSI_TABLE_SELECT 0xc000000 -#define BRXHP_FINAL 0x7000000 -#define BRXHPSETTLE_BBP 0x7 -#define BRXHTSETTLE_HSSI 0x8 -#define BRXHTSETTLE_RXHP 0x70 -#define BRXHTSETTLE_BBPPW 0x80 -#define BRXHTSETTLE_IDLE 0x300 -#define BRXHTSETTLE_RESERVED 0x1c00 -#define BRXHT_RXHP_EN 0x8000 -#define BRXAGC_FREEZE_THRES 0x30000 -#define BRXAGC_TOGETHEREN 0x40000 -#define BRXHTAGC_MIN 0x80000 -#define BRXHTAGC_EN 0x100000 -#define BRXHTDAGC_EN 0x200000 -#define BRXHT_RXHP_BBP 0x1c00000 -#define BRXHT_RXHP_FINAL 0xe0000000 -#define BRXPW_RADIO_TH 0x3 -#define BRXPW_RADIO_EN 0x4 -#define BRXMF_HOLD 0x3800 -#define BRXPD_DELAY_TH1 0x38 -#define BRXPD_DELAY_TH2 0x1c0 -#define BRXPD_DC_COUNT_MAX 0x600 -#define BRXPD_DELAY_TH 0x8000 -#define BRXPROCESS_DELAY 0xf0000 -#define BRXSEARCHRANGE_GI2_EARLY 0x700000 -#define BRXFRAME_FUARD_COUNTER_L 0x3800000 -#define BRXSGI_GUARD_L 0xc000000 -#define BRXSGI_SEARCH_L 0x30000000 -#define BRXSGI_TH 0xc0000000 -#define BDFSCNT0 0xff -#define BDFSCNT1 0xff00 -#define BDFSFLAG 0xf0000 -#define BMF_WEIGHT_SUM 0x300000 -#define BMINIDX_TH 0x7f000000 -#define BDAFORMAT 0x40000 -#define BTXCH_EMU_ENABLE 0x01000000 -#define BTRSW_ISOLATION_A 0x7f -#define BTRSW_ISOLATION_B 0x7f00 -#define BTRSW_ISOLATION_C 0x7f0000 -#define BTRSW_ISOLATION_D 0x7f000000 -#define BEXT_LNA_GAIN 0x7c00 - -#define BSTBC_EN 0x4 -#define BANTENNA_MAPPING 0x10 -#define BNSS 0x20 -#define BCFO_ANTSUM_ID 0x200 -#define BPHY_COUNTER_RESET 0x8000000 -#define BCFO_REPORT_GET 0x4000000 -#define BOFDM_CONTINUE_TX 0x10000000 -#define BOFDM_SINGLE_CARRIER 0x20000000 -#define BOFDM_SINGLE_TONE 0x40000000 -#define BHT_DETECT 0x100 -#define BCFOEN 0x10000 -#define BCFOVALUE 0xfff00000 -#define BSIGTONE_RE 0x3f -#define BSIGTONE_IM 0x7f00 -#define BCOUNTER_CCA 0xffff -#define BCOUNTER_PARITYFAIL 0xffff0000 -#define BCOUNTER_RATEILLEGAL 0xffff -#define BCOUNTER_CRC8FAIL 0xffff0000 -#define BCOUNTER_MCSNOSUPPORT 0xffff -#define BCOUNTER_FASTSYNC 0xffff -#define BSHORTCFO 0xfff -#define BSHORTCFOT_LENGTH 12 -#define BSHORTCFOF_LENGTH 11 -#define BLONGCFO 0x7ff -#define BLONGCFOT_LENGTH 11 -#define BLONGCFOF_LENGTH 11 -#define BTAILCFO 0x1fff -#define BTAILCFOT_LENGTH 13 -#define BTAILCFOF_LENGTH 12 -#define BNOISE_EN_PWDB 0xffff -#define BCC_POWER_DB 0xffff0000 -#define BMOISE_PWDB 0xffff -#define BPOWERMEAST_LENGTH 10 -#define BPOWERMEASF_LENGTH 3 -#define BRX_HT_BW 0x1 -#define BRXSC 0x6 -#define BRX_HT 0x8 -#define BNB_INTF_DET_ON 0x1 -#define BINTF_WIN_LEN_CFG 0x30 -#define BNB_INTF_TH_CFG 0x1c0 -#define BRFGAIN 0x3f -#define BTABLESEL 0x40 -#define BTRSW 0x80 -#define BRXSNR_A 0xff -#define BRXSNR_B 0xff00 -#define BRXSNR_C 0xff0000 -#define BRXSNR_D 0xff000000 -#define BSNR_EVMT_LENGTH 8 -#define BSNR_EVMF_LENGTH 1 -#define BCSI1ST 0xff -#define BCSI2ND 0xff00 -#define BRXEVM1ST 0xff0000 -#define BRXEVM2ND 0xff000000 -#define BSIGEVM 0xff -#define BPWDB 0xff00 -#define BSGIEN 0x10000 - -#define BSFACTOR_QMA1 0xf -#define BSFACTOR_QMA2 0xf0 -#define BSFACTOR_QMA3 0xf00 -#define BSFACTOR_QMA4 0xf000 -#define BSFACTOR_QMA5 0xf0000 -#define BSFACTOR_QMA6 0xf0000 -#define BSFACTOR_QMA7 0xf00000 -#define BSFACTOR_QMA8 0xf000000 -#define BSFACTOR_QMA9 0xf0000000 -#define BCSI_SCHEME 0x100000 - -#define BNOISE_LVL_TOP_SET 0x3 -#define BCHSMOOTH 0x4 -#define BCHSMOOTH_CFG1 0x38 -#define BCHSMOOTH_CFG2 0x1c0 -#define BCHSMOOTH_CFG3 0xe00 -#define BCHSMOOTH_CFG4 0x7000 -#define BMRCMODE 0x800000 -#define BTHEVMCFG 0x7000000 - -#define BLOOP_FIT_TYPE 0x1 -#define BUPD_CFO 0x40 -#define BUPD_CFO_OFFDATA 0x80 -#define BADV_UPD_CFO 0x100 -#define BADV_TIME_CTRL 0x800 -#define BUPD_CLKO 0x1000 -#define BFC 0x6000 -#define BTRACKING_MODE 0x8000 -#define BPHCMP_ENABLE 0x10000 -#define BUPD_CLKO_LTF 0x20000 -#define BCOM_CH_CFO 0x40000 -#define BCSI_ESTI_MODE 0x80000 -#define BADV_UPD_EQZ 0x100000 -#define BUCHCFG 0x7000000 -#define BUPDEQZ 0x8000000 - -#define BRX_PESUDO_NOISE_ON 0x20000000 -#define BRX_PESUDO_NOISE_A 0xff -#define BRX_PESUDO_NOISE_B 0xff00 -#define BRX_PESUDO_NOISE_C 0xff0000 -#define BRX_PESUDO_NOISE_D 0xff000000 -#define BRX_PESUDO_NOISESTATE_A 0xffff -#define BRX_PESUDO_NOISESTATE_B 0xffff0000 -#define BRX_PESUDO_NOISESTATE_C 0xffff -#define BRX_PESUDO_NOISESTATE_D 0xffff0000 - -#define BZEBRA1_HSSIENABLE 0x8 -#define BZEBRA1_TRXCONTROL 0xc00 -#define BZEBRA1_TRXGAINSETTING 0x07f -#define BZEBRA1_RXCOUNTER 0xc00 -#define BZEBRA1_TXCHANGEPUMP 0x38 -#define BZEBRA1_RXCHANGEPUMP 0x7 -#define BZEBRA1_CHANNEL_NUM 0xf80 -#define BZEBRA1_TXLPFBW 0x400 -#define BZEBRA1_RXLPFBW 0x600 - -#define BRTL8256REG_MODE_CTRL1 0x100 -#define BRTL8256REG_MODE_CTRL0 0x40 -#define BRTL8256REG_TXLPFBW 0x18 -#define BRTL8256REG_RXLPFBW 0x600 - -#define BRTL8258_TXLPFBW 0xc -#define BRTL8258_RXLPFBW 0xc00 -#define BRTL8258_RSSILPFBW 0xc0 - -#define BBYTE0 0x1 -#define BBYTE1 0x2 -#define BBYTE2 0x4 -#define BBYTE3 0x8 -#define BWORD0 0x3 -#define BWORD1 0xc -#define BWORD 0xf - -#define MASKBYTE0 0xff -#define MASKBYTE1 0xff00 -#define MASKBYTE2 0xff0000 -#define MASKBYTE3 0xff000000 -#define MASKHWORD 0xffff0000 -#define MASKLWORD 0x0000ffff -#define MASKDWORD 0xffffffff -#define MASK12BITS 0xfff -#define MASKH4BITS 0xf0000000 -#define MASKOFDM_D 0xffc00000 -#define MASKCCK 0x3f3f3f3f - -#define MASK4BITS 0x0f -#define MASK20BITS 0xfffff -#define RFREG_OFFSET_MASK 0xfffff - -#define BENABLE 0x1 -#define BDISABLE 0x0 - -#define LEFT_ANTENNA 0x0 -#define RIGHT_ANTENNA 0x1 - -#define TCHECK_TXSTATUS 500 -#define TUPDATE_RXCOUNTER 100 - -/* 2 EFUSE_TEST (For RTL8723 partially) */ -#define EFUSE_SEL(x) (((x) & 0x3) << 8) -#define EFUSE_SEL_MASK 0x300 -#define EFUSE_WIFI_SEL_0 0x0 -/* Enable GPIO[9] as WiFi HW PDn source*/ -#define WL_HWPDN_EN BIT(0) -/* WiFi HW PDn polarity control*/ -#define WL_HWPDN_SL BIT(1) - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c deleted file mode 100644 index 9ebc8281ff99..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.c +++ /dev/null @@ -1,514 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" - -static bool _rtl8723e_phy_rf6052_config_parafile(struct ieee80211_hw *hw); - -void rtl8723e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - switch (bandwidth) { - case HT_CHANNEL_WIDTH_20: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff) | 0x0400); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - case HT_CHANNEL_WIDTH_20_40: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff)); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", bandwidth); - break; - } -} - -void rtl8723e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 tx_agc[2] = {0, 0}, tmpval; - bool turbo_scanoff = false; - u8 idx1, idx2; - u8 *ptr; - - if (rtlefuse->eeprom_regulatory != 0) - turbo_scanoff = true; - - if (mac->act_scanning == true) { - tx_agc[RF90_PATH_A] = 0x3f3f3f3f; - tx_agc[RF90_PATH_B] = 0x3f3f3f3f; - - if (turbo_scanoff) { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; - idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - } - } else { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - - if (rtlefuse->eeprom_regulatory == 0) { - tmpval = - (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + - (rtlphy->mcs_txpwrlevel_origoffset[0][7] << - 8); - tx_agc[RF90_PATH_A] += tmpval; - - tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + - (rtlphy->mcs_txpwrlevel_origoffset[0][15] << - 24); - tx_agc[RF90_PATH_B] += tmpval; - } - } - - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - ptr = (u8 *)&tx_agc[idx1]; - for (idx2 = 0; idx2 < 4; idx2++) { - if (*ptr > RF6052_MAX_TX_PWR) - *ptr = RF6052_MAX_TX_PWR; - ptr++; - } - } - - tmpval = tx_agc[RF90_PATH_A] & 0xff; - rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_A_CCK1_MCS32); - - tmpval = tx_agc[RF90_PATH_A] >> 8; - - tmpval = tmpval & 0xff00ffff; - - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_B_CCK11_A_CCK2_11); - - tmpval = tx_agc[RF90_PATH_B] >> 24; - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_B_CCK11_A_CCK2_11); - - tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; - rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_B_CCK1_55_MCS32); -} - -static void rtl8723e_phy_get_power_base(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel, - u32 *ofdmbase, u32 *mcsbase) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 powerbase0, powerbase1; - u8 legacy_pwrdiff, ht20_pwrdiff; - u8 i, powerlevel[2]; - - for (i = 0; i < 2; i++) { - powerlevel[i] = ppowerlevel[i]; - legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; - powerbase0 = powerlevel[i] + legacy_pwrdiff; - - powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | - (powerbase0 << 8) | powerbase0; - *(ofdmbase + i) = powerbase0; - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [OFDM power base index rf(%c) = 0x%x]\n", - ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)); - } - - for (i = 0; i < 2; i++) { - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { - ht20_pwrdiff = - rtlefuse->txpwr_ht20diff[i][channel - 1]; - powerlevel[i] += ht20_pwrdiff; - } - powerbase1 = powerlevel[i]; - powerbase1 = (powerbase1 << 24) | - (powerbase1 << 16) | (powerbase1 << 8) | powerbase1; - - *(mcsbase + i) = powerbase1; - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [MCS power base index rf(%c) = 0x%x]\n", - ((i == 0) ? 'A' : 'B'), *(mcsbase + i)); - } -} - -static void get_txpower_writeval_by_reg(struct ieee80211_hw *hw, - u8 channel, u8 index, - u32 *powerbase0, - u32 *powerbase1, - u32 *p_outwriteval) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 i, chnlgroup = 0, pwr_diff_limit[4]; - u32 writeval, customer_limit, rf; - - for (rf = 0; rf < 2; rf++) { - switch (rtlefuse->eeprom_regulatory) { - case 0: - chnlgroup = 0; - - writeval = - rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index + - (rf ? 8 : 0)] - + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - case 1: - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - writeval = ((index < 2) ? powerbase0[rf] : - powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Realtek regulatory, 40MHz, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - } else { - if (rtlphy->pwrgroup_cnt == 1) - chnlgroup = 0; - if (rtlphy->pwrgroup_cnt >= 3) { - if (channel <= 3) - chnlgroup = 0; - else if (channel >= 4 && channel <= 9) - chnlgroup = 1; - else if (channel > 9) - chnlgroup = 2; - if (rtlphy->current_chan_bw == - HT_CHANNEL_WIDTH_20) - chnlgroup++; - else - chnlgroup += 4; - } - - writeval = - rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] - [index + (rf ? 8 : 0)] + ((index < 2) ? - powerbase0[rf] : - powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - } - break; - case 2: - writeval = - ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Better regulatory, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - case 3: - chnlgroup = 0; - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 40MHz rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), - rtlefuse->pwrgroup_ht40[rf][channel - - 1]); - } else { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 20MHz rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), - rtlefuse->pwrgroup_ht20[rf][channel - - 1]); - } - for (i = 0; i < 4; i++) { - pwr_diff_limit[i] = - (u8)((rtlphy->mcs_txpwrlevel_origoffset - [chnlgroup][index + - (rf ? 8 : 0)] & (0x7f << - (i * 8))) >> (i * 8)); - - if (rtlphy->current_chan_bw == - HT_CHANNEL_WIDTH_20_40) { - if (pwr_diff_limit[i] > - rtlefuse-> - pwrgroup_ht40[rf][channel - 1]) - pwr_diff_limit[i] = - rtlefuse->pwrgroup_ht40[rf] - [channel - 1]; - } else { - if (pwr_diff_limit[i] > - rtlefuse-> - pwrgroup_ht20[rf][channel - 1]) - pwr_diff_limit[i] = - rtlefuse->pwrgroup_ht20[rf] - [channel - 1]; - } - } - - customer_limit = (pwr_diff_limit[3] << 24) | - (pwr_diff_limit[2] << 16) | - (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer's limit rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), customer_limit); - - writeval = customer_limit + - ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer, writeval rf(%c)= 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - default: - chnlgroup = 0; - writeval = - rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] - [index + (rf ? 8 : 0)] - + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeval rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - } - - if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) - writeval = writeval - 0x06060606; - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_BT2) - writeval = writeval - 0x0c0c0c0c; - *(p_outwriteval + rf) = writeval; - } -} - -static void _rtl8723e_write_ofdm_power_reg(struct ieee80211_hw *hw, - u8 index, u32 *pvalue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - u16 regoffset_a[6] = { - RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, - RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, - RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 - }; - u16 regoffset_b[6] = { - RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, - RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, - RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 - }; - u8 i, rf, pwr_val[4]; - u32 writeval; - u16 regoffset; - - for (rf = 0; rf < 2; rf++) { - writeval = pvalue[rf]; - for (i = 0; i < 4; i++) { - pwr_val[i] = (u8)((writeval & (0x7f << - (i * 8))) >> (i * 8)); - - if (pwr_val[i] > RF6052_MAX_TX_PWR) - pwr_val[i] = RF6052_MAX_TX_PWR; - } - writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | - (pwr_val[1] << 8) | pwr_val[0]; - - if (rf == 0) - regoffset = regoffset_a[index]; - else - regoffset = regoffset_b[index]; - rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Set 0x%x = %08x\n", regoffset, writeval); - - if (((get_rf_type(rtlphy) == RF_2T2R) && - (regoffset == RTXAGC_A_MCS15_MCS12 || - regoffset == RTXAGC_B_MCS15_MCS12)) || - ((get_rf_type(rtlphy) != RF_2T2R) && - (regoffset == RTXAGC_A_MCS07_MCS04 || - regoffset == RTXAGC_B_MCS07_MCS04))) { - - writeval = pwr_val[3]; - if (regoffset == RTXAGC_A_MCS15_MCS12 || - regoffset == RTXAGC_A_MCS07_MCS04) - regoffset = 0xc90; - if (regoffset == RTXAGC_B_MCS15_MCS12 || - regoffset == RTXAGC_B_MCS07_MCS04) - regoffset = 0xc98; - - for (i = 0; i < 3; i++) { - writeval = (writeval > 6) ? (writeval - 6) : 0; - rtl_write_byte(rtlpriv, (u32) (regoffset + i), - (u8)writeval); - } - } - } -} - -void rtl8723e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel) -{ - u32 writeval[2], powerbase0[2], powerbase1[2]; - u8 index; - - rtl8723e_phy_get_power_base(hw, ppowerlevel, - channel, &powerbase0[0], &powerbase1[0]); - - for (index = 0; index < 6; index++) { - get_txpower_writeval_by_reg(hw, channel, index, &powerbase0[0], - &powerbase1[0], - &writeval[0]); - - _rtl8723e_write_ofdm_power_reg(hw, index, &writeval[0]); - } -} - -bool rtl8723e_phy_rf6052_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - if (rtlphy->rf_type == RF_1T1R) - rtlphy->num_total_rfpath = 1; - else - rtlphy->num_total_rfpath = 2; - - return _rtl8723e_phy_rf6052_config_parafile(hw); -} - -static bool _rtl8723e_phy_rf6052_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 u4_regvalue = 0; - u8 rfpath; - bool rtstatus = true; - struct bb_reg_def *pphyreg; - - for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { - - pphyreg = &rtlphy->phyreg_def[rfpath]; - - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV); - break; - case RF90_PATH_B: - case RF90_PATH_D: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16); - break; - } - - rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, - B3WIREADDREAALENGTH, 0x0); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); - udelay(1); - - switch (rfpath) { - case RF90_PATH_A: - rtstatus = rtl8723e_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_B: - rtstatus = - rtl8723e_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_C: - break; - case RF90_PATH_D: - break; - } - - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - rtl_set_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV, u4_regvalue); - break; - case RF90_PATH_B: - case RF90_PATH_D: - rtl_set_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16, u4_regvalue); - break; - } - - if (rtstatus != true) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio[%d] Fail!!", rfpath); - return false; - } - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); - return rtstatus; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h b/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h deleted file mode 100644 index 7b44ebc0fac9..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/rf.h +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_RF_H__ -#define __RTL8723E_RF_H__ - -#define RF6052_MAX_TX_PWR 0x3F - -void rtl8723e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, - u8 bandwidth); -void rtl8723e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -void rtl8723e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); -bool rtl8723e_phy_rf6052_config(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c deleted file mode 100644 index 3859b3e3d158..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c +++ /dev/null @@ -1,405 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../core.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "fw.h" -#include "../rtl8723com/fw_common.h" -#include "hw.h" -#include "sw.h" -#include "trx.h" -#include "led.h" -#include "table.h" -#include "hal_btc.h" -#include "../btcoexist/rtl_btc.h" -#include "../rtl8723com/phy_common.h" - -#include -#include - -static void rtl8723e_init_aspm_vars(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - /*close ASPM for AMD defaultly */ - rtlpci->const_amdpci_aspm = 0; - - /** - * ASPM PS mode. - * 0 - Disable ASPM, - * 1 - Enable ASPM without Clock Req, - * 2 - Enable ASPM with Clock Req, - * 3 - Alwyas Enable ASPM with Clock Req, - * 4 - Always Enable ASPM without Clock Req. - * set defult to RTL8192CE:3 RTL8192E:2 - */ - rtlpci->const_pci_aspm = 3; - - /*Setting for PCI-E device */ - rtlpci->const_devicepci_aspm_setting = 0x03; - - /*Setting for PCI-E bridge */ - rtlpci->const_hostpci_aspm_setting = 0x02; - - /** - * In Hw/Sw Radio Off situation. - * 0 - Default, - * 1 - From ASPM setting without low Mac Pwr, - * 2 - From ASPM setting with low Mac Pwr, - * 3 - Bus D3 - * set default to RTL8192CE:0 RTL8192SE:2 - */ - rtlpci->const_hwsw_rfoff_d3 = 0; - - /** - * This setting works for those device with - * backdoor ASPM setting such as EPHY setting. - * 0 - Not support ASPM, - * 1 - Support ASPM, - * 2 - According to chipset. - */ - rtlpci->const_support_pciaspm = 1; -} - -int rtl8723e_init_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - int err = 0; - - rtl8723e_bt_reg_init(hw); - - rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); - - rtlpriv->dm.dm_initialgain_enable = 1; - rtlpriv->dm.dm_flag = 0; - rtlpriv->dm.disable_framebursting = 0; - rtlpriv->dm.thermalvalue = 0; - rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13); - - /* compatible 5G band 88ce just 2.4G band & smsp */ - rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; - rtlpriv->rtlhal.bandset = BAND_ON_2_4G; - rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; - - rtlpci->receive_config = (RCR_APPFCS | - RCR_APP_MIC | - RCR_APP_ICV | - RCR_APP_PHYST_RXFF | - RCR_HTC_LOC_CTRL | - RCR_AMF | - RCR_ACF | - RCR_ADF | - RCR_AICV | - RCR_AB | - RCR_AM | - RCR_APM | - 0); - - rtlpci->irq_mask[0] = - (u32) (PHIMR_ROK | - PHIMR_RDU | - PHIMR_VODOK | - PHIMR_VIDOK | - PHIMR_BEDOK | - PHIMR_BKDOK | - PHIMR_MGNTDOK | - PHIMR_HIGHDOK | - PHIMR_C2HCMD | - PHIMR_HISRE_IND | - PHIMR_TSF_BIT32_TOGGLE | - PHIMR_TXBCNOK | - PHIMR_PSTIMEOUT | - 0); - - rtlpci->irq_mask[1] = - (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; - rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; - if (rtlpriv->cfg->mod_params->disable_watchdog) - pr_info("watchdog disabled\n"); - rtlpriv->psc.reg_fwctrl_lps = 3; - rtlpriv->psc.reg_max_lps_awakeintvl = 5; - rtl8723e_init_aspm_vars(hw); - - if (rtlpriv->psc.reg_fwctrl_lps == 1) - rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 2) - rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 3) - rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; - - /* for firmware buf */ - rtlpriv->rtlhal.pfirmware = vzalloc(0x6000); - if (!rtlpriv->rtlhal.pfirmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't alloc buffer for fw.\n"); - return 1; - } - - if (IS_VENDOR_8723_A_CUT(rtlhal->version)) - rtlpriv->cfg->fw_name = "rtlwifi/rtl8723fw.bin"; - else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) - rtlpriv->cfg->fw_name = "rtlwifi/rtl8723fw_B.bin"; - - rtlpriv->max_fw_size = 0x6000; - pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); - err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, - rtlpriv->io.dev, GFP_KERNEL, hw, - rtl_fw_cb); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to request firmware!\n"); - return 1; - } - return 0; -} - -void rtl8723e_deinit_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->rtlhal.pfirmware) { - vfree(rtlpriv->rtlhal.pfirmware); - rtlpriv->rtlhal.pfirmware = NULL; - } -} - -/* get bt coexist status */ -bool rtl8723e_get_btc_status(void) -{ - return true; -} - -static bool is_fw_header(struct rtlwifi_firmware_header *hdr) -{ - return (le16_to_cpu(hdr->signature) & 0xfff0) == 0x2300; -} - -static struct rtl_hal_ops rtl8723e_hal_ops = { - .init_sw_vars = rtl8723e_init_sw_vars, - .deinit_sw_vars = rtl8723e_deinit_sw_vars, - .read_eeprom_info = rtl8723e_read_eeprom_info, - .interrupt_recognized = rtl8723e_interrupt_recognized, - .hw_init = rtl8723e_hw_init, - .hw_disable = rtl8723e_card_disable, - .hw_suspend = rtl8723e_suspend, - .hw_resume = rtl8723e_resume, - .enable_interrupt = rtl8723e_enable_interrupt, - .disable_interrupt = rtl8723e_disable_interrupt, - .set_network_type = rtl8723e_set_network_type, - .set_chk_bssid = rtl8723e_set_check_bssid, - .set_qos = rtl8723e_set_qos, - .set_bcn_reg = rtl8723e_set_beacon_related_registers, - .set_bcn_intv = rtl8723e_set_beacon_interval, - .update_interrupt_mask = rtl8723e_update_interrupt_mask, - .get_hw_reg = rtl8723e_get_hw_reg, - .set_hw_reg = rtl8723e_set_hw_reg, - .update_rate_tbl = rtl8723e_update_hal_rate_tbl, - .fill_tx_desc = rtl8723e_tx_fill_desc, - .fill_tx_cmddesc = rtl8723e_tx_fill_cmddesc, - .query_rx_desc = rtl8723e_rx_query_desc, - .set_channel_access = rtl8723e_update_channel_access_setting, - .radio_onoff_checking = rtl8723e_gpio_radio_on_off_checking, - .set_bw_mode = rtl8723e_phy_set_bw_mode, - .switch_channel = rtl8723e_phy_sw_chnl, - .dm_watchdog = rtl8723e_dm_watchdog, - .scan_operation_backup = rtl8723e_phy_scan_operation_backup, - .set_rf_power_state = rtl8723e_phy_set_rf_power_state, - .led_control = rtl8723e_led_control, - .set_desc = rtl8723e_set_desc, - .get_desc = rtl8723e_get_desc, - .is_tx_desc_closed = rtl8723e_is_tx_desc_closed, - .tx_polling = rtl8723e_tx_polling, - .enable_hw_sec = rtl8723e_enable_hw_security_config, - .set_key = rtl8723e_set_key, - .init_sw_leds = rtl8723e_init_sw_leds, - .get_bbreg = rtl8723_phy_query_bb_reg, - .set_bbreg = rtl8723_phy_set_bb_reg, - .get_rfreg = rtl8723e_phy_query_rf_reg, - .set_rfreg = rtl8723e_phy_set_rf_reg, - .c2h_command_handle = rtl_8723e_c2h_command_handle, - .bt_wifi_media_status_notify = rtl_8723e_bt_wifi_media_status_notify, - .bt_coex_off_before_lps = - rtl8723e_dm_bt_turn_off_bt_coexist_before_enter_lps, - .get_btc_status = rtl8723e_get_btc_status, - .rx_command_packet = rtl8723e_rx_command_packet, - .is_fw_header = is_fw_header, -}; - -static struct rtl_mod_params rtl8723e_mod_params = { - .sw_crypto = false, - .inactiveps = true, - .swctrl_lps = false, - .fwctrl_lps = true, - .debug = DBG_EMERG, -}; - -static struct rtl_hal_cfg rtl8723e_hal_cfg = { - .bar_id = 2, - .write_readback = true, - .name = "rtl8723e_pci", - .fw_name = "rtlwifi/rtl8723efw.bin", - .ops = &rtl8723e_hal_ops, - .mod_params = &rtl8723e_mod_params, - .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, - .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, - .maps[SYS_CLK] = REG_SYS_CLKR, - .maps[MAC_RCR_AM] = AM, - .maps[MAC_RCR_AB] = AB, - .maps[MAC_RCR_ACRC32] = ACRC32, - .maps[MAC_RCR_ACF] = ACF, - .maps[MAC_RCR_AAP] = AAP, - .maps[MAC_HIMR] = REG_HIMR, - .maps[MAC_HIMRE] = REG_HIMRE, - .maps[EFUSE_TEST] = REG_EFUSE_TEST, - .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_CLK] = 0, - .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_PWC_EV12V] = PWC_EV12V, - .maps[EFUSE_FEN_ELDR] = FEN_ELDR, - .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, - .maps[EFUSE_ANA8M] = ANA8M, - .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, - .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, - .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, - .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, - - .maps[RWCAM] = REG_CAMCMD, - .maps[WCAMI] = REG_CAMWRITE, - .maps[RCAMO] = REG_CAMREAD, - .maps[CAMDBG] = REG_CAMDBG, - .maps[SECR] = REG_SECCFG, - .maps[SEC_CAM_NONE] = CAM_NONE, - .maps[SEC_CAM_WEP40] = CAM_WEP40, - .maps[SEC_CAM_TKIP] = CAM_TKIP, - .maps[SEC_CAM_AES] = CAM_AES, - .maps[SEC_CAM_WEP104] = CAM_WEP104, - - .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, - .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, - .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, - .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, - .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, - .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, - .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, - .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, - .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, - .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, - .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, - .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, - .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, - .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, - .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, - .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, - - .maps[RTL_IMR_TXFOVW] = PHIMR_TXFOVW, - .maps[RTL_IMR_PSTIMEOUT] = PHIMR_PSTIMEOUT, - .maps[RTL_IMR_BCNINT] = PHIMR_BCNDMAINT0, - .maps[RTL_IMR_RXFOVW] = PHIMR_RXFOVW, - .maps[RTL_IMR_RDU] = PHIMR_RDU, - .maps[RTL_IMR_ATIMEND] = PHIMR_ATIMEND_E, - .maps[RTL_IMR_BDOK] = PHIMR_BCNDOK0, - .maps[RTL_IMR_MGNTDOK] = PHIMR_MGNTDOK, - .maps[RTL_IMR_TBDER] = PHIMR_TXBCNERR, - .maps[RTL_IMR_HIGHDOK] = PHIMR_HIGHDOK, - .maps[RTL_IMR_TBDOK] = PHIMR_TXBCNOK, - .maps[RTL_IMR_BKDOK] = PHIMR_BKDOK, - .maps[RTL_IMR_BEDOK] = PHIMR_BEDOK, - .maps[RTL_IMR_VIDOK] = PHIMR_VIDOK, - .maps[RTL_IMR_VODOK] = PHIMR_VODOK, - .maps[RTL_IMR_ROK] = PHIMR_ROK, - .maps[RTL_IBSS_INT_MASKS] = - (PHIMR_BCNDMAINT0 | PHIMR_TXBCNOK | PHIMR_TXBCNERR), - .maps[RTL_IMR_C2HCMD] = PHIMR_C2HCMD, - - - .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, -}; - -static struct pci_device_id rtl8723e_pci_ids[] = { - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8723, rtl8723e_hal_cfg)}, - {}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8723e_pci_ids); - -MODULE_AUTHOR("lizhaoming "); -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_LICENSE("GPL"); -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(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); -module_param_named(disable_watchdog, rtl8723e_mod_params.disable_watchdog, - bool, 0444); -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(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); - -static struct pci_driver rtl8723e_driver = { - .name = KBUILD_MODNAME, - .id_table = rtl8723e_pci_ids, - .probe = rtl_pci_probe, - .remove = rtl_pci_disconnect, - .driver.pm = &rtlwifi_pm_ops, -}; - -module_pci_driver(rtl8723e_driver); diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h deleted file mode 100644 index 46478780d262..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.h +++ /dev/null @@ -1,35 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_SW_H__ -#define __RTL8723E_SW_H__ - -int rtl8723e_init_sw_vars(struct ieee80211_hw *hw); -void rtl8723e_deinit_sw_vars(struct ieee80211_hw *hw); -void rtl8723e_init_var_map(struct ieee80211_hw *hw); -bool rtl8723e_get_btc_status(void); - - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/table.c b/drivers/net/wireless/rtlwifi/rtl8723ae/table.c deleted file mode 100644 index 61e86045f15c..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/table.c +++ /dev/null @@ -1,732 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ - -#include "table.h" - -u32 RTL8723EPHY_REG_1TARRAY[RTL8723E_PHY_REG_1TARRAY_LENGTH] = { - 0x800, 0x80040000, - 0x804, 0x00000003, - 0x808, 0x0000fc00, - 0x80c, 0x0000000a, - 0x810, 0x10005388, - 0x814, 0x020c3d10, - 0x818, 0x02200385, - 0x81c, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390004, - 0x828, 0x00000000, - 0x82c, 0x00000000, - 0x830, 0x00000000, - 0x834, 0x00000000, - 0x838, 0x00000000, - 0x83c, 0x00000000, - 0x840, 0x00010000, - 0x844, 0x00000000, - 0x848, 0x00000000, - 0x84c, 0x00000000, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x569a569a, - 0x85c, 0x001b25a4, - 0x860, 0x66f60110, - 0x864, 0x061f0130, - 0x868, 0x00000000, - 0x86c, 0x32323200, - 0x870, 0x07000760, - 0x874, 0x22004000, - 0x878, 0x00000808, - 0x87c, 0x00000000, - 0x880, 0xc0083070, - 0x884, 0x000004d5, - 0x888, 0x00000000, - 0x88c, 0xccc000c0, - 0x890, 0x00000800, - 0x894, 0xfffffffe, - 0x898, 0x40302010, - 0x89c, 0x00706050, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90c, 0x81121111, - 0xa00, 0x00d047c8, - 0xa04, 0x80ff000c, - 0xa08, 0x8c838300, - 0xa0c, 0x2e68120f, - 0xa10, 0x9500bb78, - 0xa14, 0x11144028, - 0xa18, 0x00881117, - 0xa1c, 0x89140f00, - 0xa20, 0x1a1b0000, - 0xa24, 0x090e1317, - 0xa28, 0x00000204, - 0xa2c, 0x00d30000, - 0xa70, 0x101fbf00, - 0xa74, 0x00000007, - 0xa78, 0x00000900, - 0xc00, 0x48071d40, - 0xc04, 0x03a05611, - 0xc08, 0x000000e4, - 0xc0c, 0x6c6c6c6c, - 0xc10, 0x08800000, - 0xc14, 0x40000100, - 0xc18, 0x08800000, - 0xc1c, 0x40000100, - 0xc20, 0x00000000, - 0xc24, 0x00000000, - 0xc28, 0x00000000, - 0xc2c, 0x00000000, - 0xc30, 0x69e9ac44, - 0xc34, 0x469652cf, - 0xc38, 0x49795994, - 0xc3c, 0x0a97971c, - 0xc40, 0x1f7c403f, - 0xc44, 0x000100b7, - 0xc48, 0xec020107, - 0xc4c, 0x007f037f, - 0xc50, 0x69543420, - 0xc54, 0x43bc0094, - 0xc58, 0x69543420, - 0xc5c, 0x433c0094, - 0xc60, 0x00000000, - 0xc64, 0x7116848b, - 0xc68, 0x47c00bff, - 0xc6c, 0x00000036, - 0xc70, 0x2c7f000d, - 0xc74, 0x018610db, - 0xc78, 0x0000001f, - 0xc7c, 0x00b91612, - 0xc80, 0x40000100, - 0xc84, 0x20f60000, - 0xc88, 0x40000100, - 0xc8c, 0x20200000, - 0xc90, 0x00121820, - 0xc94, 0x00000000, - 0xc98, 0x00121820, - 0xc9c, 0x00007f7f, - 0xca0, 0x00000000, - 0xca4, 0x00000080, - 0xca8, 0x00000000, - 0xcac, 0x00000000, - 0xcb0, 0x00000000, - 0xcb4, 0x00000000, - 0xcb8, 0x00000000, - 0xcbc, 0x28000000, - 0xcc0, 0x00000000, - 0xcc4, 0x00000000, - 0xcc8, 0x00000000, - 0xccc, 0x00000000, - 0xcd0, 0x00000000, - 0xcd4, 0x00000000, - 0xcd8, 0x64b22427, - 0xcdc, 0x00766932, - 0xce0, 0x00222222, - 0xce4, 0x00000000, - 0xce8, 0x37644302, - 0xcec, 0x2f97d40c, - 0xd00, 0x00080740, - 0xd04, 0x00020401, - 0xd08, 0x0000907f, - 0xd0c, 0x20010201, - 0xd10, 0xa0633333, - 0xd14, 0x3333bc43, - 0xd18, 0x7a8f5b6b, - 0xd2c, 0xcc979975, - 0xd30, 0x00000000, - 0xd34, 0x80608000, - 0xd38, 0x00000000, - 0xd3c, 0x00027293, - 0xd40, 0x00000000, - 0xd44, 0x00000000, - 0xd48, 0x00000000, - 0xd4c, 0x00000000, - 0xd50, 0x6437140a, - 0xd54, 0x00000000, - 0xd58, 0x00000000, - 0xd5c, 0x30032064, - 0xd60, 0x4653de68, - 0xd64, 0x04518a3c, - 0xd68, 0x00002101, - 0xd6c, 0x2a201c16, - 0xd70, 0x1812362e, - 0xd74, 0x322c2220, - 0xd78, 0x000e3c24, - 0xe00, 0x2a2a2a2a, - 0xe04, 0x2a2a2a2a, - 0xe08, 0x03902a2a, - 0xe10, 0x2a2a2a2a, - 0xe14, 0x2a2a2a2a, - 0xe18, 0x2a2a2a2a, - 0xe1c, 0x2a2a2a2a, - 0xe28, 0x00000000, - 0xe30, 0x1000dc1f, - 0xe34, 0x10008c1f, - 0xe38, 0x02140102, - 0xe3c, 0x681604c2, - 0xe40, 0x01007c00, - 0xe44, 0x01004800, - 0xe48, 0xfb000000, - 0xe4c, 0x000028d1, - 0xe50, 0x1000dc1f, - 0xe54, 0x10008c1f, - 0xe58, 0x02140102, - 0xe5c, 0x28160d05, - 0xe60, 0x00000008, - 0xe68, 0x001b25a4, - 0xe6c, 0x631b25a0, - 0xe70, 0x631b25a0, - 0xe74, 0x081b25a0, - 0xe78, 0x081b25a0, - 0xe7c, 0x081b25a0, - 0xe80, 0x081b25a0, - 0xe84, 0x631b25a0, - 0xe88, 0x081b25a0, - 0xe8c, 0x631b25a0, - 0xed0, 0x631b25a0, - 0xed4, 0x631b25a0, - 0xed8, 0x631b25a0, - 0xedc, 0x001b25a0, - 0xee0, 0x001b25a0, - 0xeec, 0x6b1b25a0, - 0xf14, 0x00000003, - 0xf4c, 0x00000000, - 0xf00, 0x00000300, -}; - -u32 RTL8723EPHY_REG_ARRAY_PG[RTL8723E_PHY_REG_ARRAY_PGLENGTH] = { - 0xe00, 0xffffffff, 0x0a0c0c0c, - 0xe04, 0xffffffff, 0x02040608, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x0a0c0d0e, - 0xe14, 0xffffffff, 0x02040608, - 0xe18, 0xffffffff, 0x0a0c0d0e, - 0xe1c, 0xffffffff, 0x02040608, - 0x830, 0xffffffff, 0x0a0c0c0c, - 0x834, 0xffffffff, 0x02040608, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x0a0c0d0e, - 0x848, 0xffffffff, 0x02040608, - 0x84c, 0xffffffff, 0x0a0c0d0e, - 0x868, 0xffffffff, 0x02040608, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x06060606, - 0xe14, 0xffffffff, 0x00020406, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x06060606, - 0x848, 0xffffffff, 0x00020406, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x04040404, - 0xe04, 0xffffffff, 0x00020204, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x04040404, - 0x834, 0xffffffff, 0x00020204, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, - 0xe00, 0xffffffff, 0x00000000, - 0xe04, 0xffffffff, 0x00000000, - 0xe08, 0x0000ff00, 0x00000000, - 0x86c, 0xffffff00, 0x00000000, - 0xe10, 0xffffffff, 0x00000000, - 0xe14, 0xffffffff, 0x00000000, - 0xe18, 0xffffffff, 0x00000000, - 0xe1c, 0xffffffff, 0x00000000, - 0x830, 0xffffffff, 0x00000000, - 0x834, 0xffffffff, 0x00000000, - 0x838, 0xffffff00, 0x00000000, - 0x86c, 0x000000ff, 0x00000000, - 0x83c, 0xffffffff, 0x00000000, - 0x848, 0xffffffff, 0x00000000, - 0x84c, 0xffffffff, 0x00000000, - 0x868, 0xffffffff, 0x00000000, -}; - -u32 RTL8723E_RADIOA_1TARRAY[RTL8723ERADIOA_1TARRAYLENGTH] = { - 0x000, 0x00030159, - 0x001, 0x00031284, - 0x002, 0x00098000, - 0x003, 0x00018c63, - 0x004, 0x000210e7, - 0x009, 0x0002044f, - 0x00a, 0x0001a3f1, - 0x00b, 0x00014787, - 0x00c, 0x000896fe, - 0x00d, 0x0000e02c, - 0x00e, 0x00039ce7, - 0x00f, 0x00000451, - 0x019, 0x00000000, - 0x01a, 0x00030355, - 0x01b, 0x00060a00, - 0x01c, 0x000fc378, - 0x01d, 0x000a1250, - 0x01e, 0x0004445f, - 0x01f, 0x00080001, - 0x020, 0x0000b614, - 0x021, 0x0006c000, - 0x022, 0x00000000, - 0x023, 0x00001558, - 0x024, 0x00000060, - 0x025, 0x00000483, - 0x026, 0x0004f000, - 0x027, 0x000ec7d9, - 0x028, 0x00057730, - 0x029, 0x00004783, - 0x02a, 0x00000001, - 0x02b, 0x00021334, - 0x02a, 0x00000000, - 0x02b, 0x00000054, - 0x02a, 0x00000001, - 0x02b, 0x00000808, - 0x02b, 0x00053333, - 0x02c, 0x0000000c, - 0x02a, 0x00000002, - 0x02b, 0x00000808, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000003, - 0x02b, 0x00000808, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000004, - 0x02b, 0x00000808, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000005, - 0x02b, 0x00000808, - 0x02b, 0x00073333, - 0x02c, 0x0000000d, - 0x02a, 0x00000006, - 0x02b, 0x00000709, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000007, - 0x02b, 0x00000709, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x00000008, - 0x02b, 0x0000060a, - 0x02b, 0x0004b333, - 0x02c, 0x0000000d, - 0x02a, 0x00000009, - 0x02b, 0x0000060a, - 0x02b, 0x00053333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000a, - 0x02b, 0x0000060a, - 0x02b, 0x0005b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000b, - 0x02b, 0x0000060a, - 0x02b, 0x00063333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000c, - 0x02b, 0x0000060a, - 0x02b, 0x0006b333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000d, - 0x02b, 0x0000060a, - 0x02b, 0x00073333, - 0x02c, 0x0000000d, - 0x02a, 0x0000000e, - 0x02b, 0x0000050b, - 0x02b, 0x00066666, - 0x02c, 0x0000001a, - 0x02a, 0x000e0000, - 0x010, 0x0004000f, - 0x011, 0x000e31fc, - 0x010, 0x0006000f, - 0x011, 0x000ff9f8, - 0x010, 0x0002000f, - 0x011, 0x000203f9, - 0x010, 0x0003000f, - 0x011, 0x000ff500, - 0x010, 0x00000000, - 0x011, 0x00000000, - 0x010, 0x0008000f, - 0x011, 0x0003f100, - 0x010, 0x0009000f, - 0x011, 0x00023100, - 0x012, 0x00032000, - 0x012, 0x00071000, - 0x012, 0x000b0000, - 0x012, 0x000fc000, - 0x013, 0x000287b3, - 0x013, 0x000244b7, - 0x013, 0x000204ab, - 0x013, 0x0001c49f, - 0x013, 0x00018493, - 0x013, 0x0001429b, - 0x013, 0x00010299, - 0x013, 0x0000c29c, - 0x013, 0x000081a0, - 0x013, 0x000040ac, - 0x013, 0x00000020, - 0x014, 0x0001944c, - 0x014, 0x00059444, - 0x014, 0x0009944c, - 0x014, 0x000d9444, - 0x015, 0x0000f424, - 0x015, 0x0004f407, - 0x015, 0x0008f424, - 0x015, 0x000cf424, - 0x016, 0x00000339, - 0x016, 0x00040339, - 0x016, 0x00080339, - 0x016, 0x000c0336, - 0x000, 0x00010159, - 0x018, 0x0000f401, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01f, 0x00080003, - 0x0fe, 0x00000000, - 0x0fe, 0x00000000, - 0x01e, 0x00044457, - 0x01f, 0x00080000, - 0x000, 0x00030159, -}; - -u32 RTL8723E_RADIOB_1TARRAY[RTL8723E_RADIOB_1TARRAYLENGTH] = { - 0x0, -}; - -u32 RTL8723EMAC_ARRAY[RTL8723E_MACARRAYLENGTH] = { - 0x420, 0x00000080, - 0x423, 0x00000000, - 0x430, 0x00000000, - 0x431, 0x00000000, - 0x432, 0x00000000, - 0x433, 0x00000001, - 0x434, 0x00000004, - 0x435, 0x00000005, - 0x436, 0x00000006, - 0x437, 0x00000007, - 0x438, 0x00000000, - 0x439, 0x00000000, - 0x43a, 0x00000000, - 0x43b, 0x00000001, - 0x43c, 0x00000004, - 0x43d, 0x00000005, - 0x43e, 0x00000006, - 0x43f, 0x00000007, - 0x440, 0x0000005d, - 0x441, 0x00000001, - 0x442, 0x00000000, - 0x444, 0x00000015, - 0x445, 0x000000f0, - 0x446, 0x0000000f, - 0x447, 0x00000000, - 0x458, 0x00000041, - 0x459, 0x000000a8, - 0x45a, 0x00000072, - 0x45b, 0x000000b9, - 0x460, 0x00000066, - 0x461, 0x00000066, - 0x462, 0x00000008, - 0x463, 0x00000003, - 0x4c8, 0x000000ff, - 0x4c9, 0x00000008, - 0x4cc, 0x000000ff, - 0x4cd, 0x000000ff, - 0x4ce, 0x00000001, - 0x500, 0x00000026, - 0x501, 0x000000a2, - 0x502, 0x0000002f, - 0x503, 0x00000000, - 0x504, 0x00000028, - 0x505, 0x000000a3, - 0x506, 0x0000005e, - 0x507, 0x00000000, - 0x508, 0x0000002b, - 0x509, 0x000000a4, - 0x50a, 0x0000005e, - 0x50b, 0x00000000, - 0x50c, 0x0000004f, - 0x50d, 0x000000a4, - 0x50e, 0x00000000, - 0x50f, 0x00000000, - 0x512, 0x0000001c, - 0x514, 0x0000000a, - 0x515, 0x00000010, - 0x516, 0x0000000a, - 0x517, 0x00000010, - 0x51a, 0x00000016, - 0x524, 0x0000000f, - 0x525, 0x0000004f, - 0x546, 0x00000040, - 0x547, 0x00000000, - 0x550, 0x00000010, - 0x551, 0x00000010, - 0x559, 0x00000002, - 0x55a, 0x00000002, - 0x55d, 0x000000ff, - 0x605, 0x00000030, - 0x608, 0x0000000e, - 0x609, 0x0000002a, - 0x652, 0x00000020, - 0x63c, 0x0000000a, - 0x63d, 0x0000000e, - 0x63e, 0x0000000a, - 0x63f, 0x0000000e, - 0x66e, 0x00000005, - 0x700, 0x00000021, - 0x701, 0x00000043, - 0x702, 0x00000065, - 0x703, 0x00000087, - 0x708, 0x00000021, - 0x709, 0x00000043, - 0x70a, 0x00000065, - 0x70b, 0x00000087, -}; - -u32 RTL8723EAGCTAB_1TARRAY[RTL8723E_AGCTAB_1TARRAYLENGTH] = { - 0xc78, 0x7b000001, - 0xc78, 0x7b010001, - 0xc78, 0x7b020001, - 0xc78, 0x7b030001, - 0xc78, 0x7b040001, - 0xc78, 0x7b050001, - 0xc78, 0x7a060001, - 0xc78, 0x79070001, - 0xc78, 0x78080001, - 0xc78, 0x77090001, - 0xc78, 0x760a0001, - 0xc78, 0x750b0001, - 0xc78, 0x740c0001, - 0xc78, 0x730d0001, - 0xc78, 0x720e0001, - 0xc78, 0x710f0001, - 0xc78, 0x70100001, - 0xc78, 0x6f110001, - 0xc78, 0x6e120001, - 0xc78, 0x6d130001, - 0xc78, 0x6c140001, - 0xc78, 0x6b150001, - 0xc78, 0x6a160001, - 0xc78, 0x69170001, - 0xc78, 0x68180001, - 0xc78, 0x67190001, - 0xc78, 0x661a0001, - 0xc78, 0x651b0001, - 0xc78, 0x641c0001, - 0xc78, 0x631d0001, - 0xc78, 0x621e0001, - 0xc78, 0x611f0001, - 0xc78, 0x60200001, - 0xc78, 0x49210001, - 0xc78, 0x48220001, - 0xc78, 0x47230001, - 0xc78, 0x46240001, - 0xc78, 0x45250001, - 0xc78, 0x44260001, - 0xc78, 0x43270001, - 0xc78, 0x42280001, - 0xc78, 0x41290001, - 0xc78, 0x402a0001, - 0xc78, 0x262b0001, - 0xc78, 0x252c0001, - 0xc78, 0x242d0001, - 0xc78, 0x232e0001, - 0xc78, 0x222f0001, - 0xc78, 0x21300001, - 0xc78, 0x20310001, - 0xc78, 0x06320001, - 0xc78, 0x05330001, - 0xc78, 0x04340001, - 0xc78, 0x03350001, - 0xc78, 0x02360001, - 0xc78, 0x01370001, - 0xc78, 0x00380001, - 0xc78, 0x00390001, - 0xc78, 0x003a0001, - 0xc78, 0x003b0001, - 0xc78, 0x003c0001, - 0xc78, 0x003d0001, - 0xc78, 0x003e0001, - 0xc78, 0x003f0001, - 0xc78, 0x7b400001, - 0xc78, 0x7b410001, - 0xc78, 0x7b420001, - 0xc78, 0x7b430001, - 0xc78, 0x7b440001, - 0xc78, 0x7b450001, - 0xc78, 0x7a460001, - 0xc78, 0x79470001, - 0xc78, 0x78480001, - 0xc78, 0x77490001, - 0xc78, 0x764a0001, - 0xc78, 0x754b0001, - 0xc78, 0x744c0001, - 0xc78, 0x734d0001, - 0xc78, 0x724e0001, - 0xc78, 0x714f0001, - 0xc78, 0x70500001, - 0xc78, 0x6f510001, - 0xc78, 0x6e520001, - 0xc78, 0x6d530001, - 0xc78, 0x6c540001, - 0xc78, 0x6b550001, - 0xc78, 0x6a560001, - 0xc78, 0x69570001, - 0xc78, 0x68580001, - 0xc78, 0x67590001, - 0xc78, 0x665a0001, - 0xc78, 0x655b0001, - 0xc78, 0x645c0001, - 0xc78, 0x635d0001, - 0xc78, 0x625e0001, - 0xc78, 0x615f0001, - 0xc78, 0x60600001, - 0xc78, 0x49610001, - 0xc78, 0x48620001, - 0xc78, 0x47630001, - 0xc78, 0x46640001, - 0xc78, 0x45650001, - 0xc78, 0x44660001, - 0xc78, 0x43670001, - 0xc78, 0x42680001, - 0xc78, 0x41690001, - 0xc78, 0x406a0001, - 0xc78, 0x266b0001, - 0xc78, 0x256c0001, - 0xc78, 0x246d0001, - 0xc78, 0x236e0001, - 0xc78, 0x226f0001, - 0xc78, 0x21700001, - 0xc78, 0x20710001, - 0xc78, 0x06720001, - 0xc78, 0x05730001, - 0xc78, 0x04740001, - 0xc78, 0x03750001, - 0xc78, 0x02760001, - 0xc78, 0x01770001, - 0xc78, 0x00780001, - 0xc78, 0x00790001, - 0xc78, 0x007a0001, - 0xc78, 0x007b0001, - 0xc78, 0x007c0001, - 0xc78, 0x007d0001, - 0xc78, 0x007e0001, - 0xc78, 0x007f0001, - 0xc78, 0x3800001e, - 0xc78, 0x3801001e, - 0xc78, 0x3802001e, - 0xc78, 0x3803001e, - 0xc78, 0x3804001e, - 0xc78, 0x3805001e, - 0xc78, 0x3806001e, - 0xc78, 0x3807001e, - 0xc78, 0x3808001e, - 0xc78, 0x3c09001e, - 0xc78, 0x3e0a001e, - 0xc78, 0x400b001e, - 0xc78, 0x440c001e, - 0xc78, 0x480d001e, - 0xc78, 0x4c0e001e, - 0xc78, 0x500f001e, - 0xc78, 0x5210001e, - 0xc78, 0x5611001e, - 0xc78, 0x5a12001e, - 0xc78, 0x5e13001e, - 0xc78, 0x6014001e, - 0xc78, 0x6015001e, - 0xc78, 0x6016001e, - 0xc78, 0x6217001e, - 0xc78, 0x6218001e, - 0xc78, 0x6219001e, - 0xc78, 0x621a001e, - 0xc78, 0x621b001e, - 0xc78, 0x621c001e, - 0xc78, 0x621d001e, - 0xc78, 0x621e001e, - 0xc78, 0x621f001e, -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/table.h b/drivers/net/wireless/rtlwifi/rtl8723ae/table.h deleted file mode 100644 index 57a548ceba7d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/table.h +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_TABLE__H_ -#define __RTL8723E_TABLE__H_ - -#include - -#define RTL8723E_PHY_REG_1TARRAY_LENGTH 372 -extern u32 RTL8723EPHY_REG_1TARRAY[RTL8723E_PHY_REG_1TARRAY_LENGTH]; -#define RTL8723E_PHY_REG_ARRAY_PGLENGTH 336 -extern u32 RTL8723EPHY_REG_ARRAY_PG[RTL8723E_PHY_REG_ARRAY_PGLENGTH]; -#define RTL8723ERADIOA_1TARRAYLENGTH 282 -extern u32 RTL8723E_RADIOA_1TARRAY[RTL8723ERADIOA_1TARRAYLENGTH]; -#define RTL8723E_RADIOB_1TARRAYLENGTH 1 -extern u32 RTL8723E_RADIOB_1TARRAY[RTL8723E_RADIOB_1TARRAYLENGTH]; -#define RTL8723E_MACARRAYLENGTH 172 -extern u32 RTL8723EMAC_ARRAY[RTL8723E_MACARRAYLENGTH]; -#define RTL8723E_AGCTAB_1TARRAYLENGTH 320 -extern u32 RTL8723EAGCTAB_1TARRAY[RTL8723E_AGCTAB_1TARRAYLENGTH]; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c deleted file mode 100644 index 2f7c144d7980..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +++ /dev/null @@ -1,717 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../stats.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "trx.h" -#include "led.h" - -static u8 _rtl8723e_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) -{ - __le16 fc = rtl_get_fc(skb); - - if (unlikely(ieee80211_is_beacon(fc))) - return QSLT_BEACON; - if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) - return QSLT_MGNT; - - return skb->priority; -} - -static void _rtl8723e_query_rxphystatus(struct ieee80211_hw *hw, - struct rtl_stats *pstatus, u8 *pdesc, - struct rx_fwinfo_8723e *p_drvinfo, - bool bpacket_match_bssid, - bool bpacket_toself, bool packet_beacon) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); - struct phy_sts_cck_8723e_t *cck_buf; - s8 rx_pwr_all = 0, rx_pwr[4]; - u8 rf_rx_num = 0, evm, pwdb_all; - u8 i, max_spatial_stream; - u32 rssi, total_rssi = 0; - bool is_cck = pstatus->is_cck; - - /* Record it for next packet processing */ - pstatus->packet_matchbssid = bpacket_match_bssid; - pstatus->packet_toself = bpacket_toself; - pstatus->packet_beacon = packet_beacon; - pstatus->rx_mimo_signalquality[0] = -1; - pstatus->rx_mimo_signalquality[1] = -1; - - if (is_cck) { - u8 report, cck_highpwr; - - /* CCK Driver info Structure is not the same as OFDM packet. */ - cck_buf = (struct phy_sts_cck_8723e_t *)p_drvinfo; - - /* (1)Hardware does not provide RSSI for CCK */ - /* (2)PWDB, Average PWDB cacluated by - * hardware (for rate adaptive) - */ - if (ppsc->rfpwr_state == ERFON) - cck_highpwr = (u8)rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, - BIT(9)); - else - cck_highpwr = false; - - if (!cck_highpwr) { - u8 cck_agc_rpt = cck_buf->cck_agc_rpt; - report = cck_buf->cck_agc_rpt & 0xc0; - report = report >> 6; - switch (report) { - case 0x3: - rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); - break; - case 0x2: - rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); - break; - case 0x1: - rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); - break; - case 0x0: - rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); - break; - } - } else { - u8 cck_agc_rpt = cck_buf->cck_agc_rpt; - report = p_drvinfo->cfosho[0] & 0x60; - report = report >> 5; - switch (report) { - case 0x3: - rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x2: - rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x1: - rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1); - break; - case 0x0: - rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1); - break; - } - } - - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - /* CCK gain is smaller than OFDM/MCS gain, */ - /* so we add gain diff by experiences, - * the val is 6 - */ - pwdb_all += 6; - if (pwdb_all > 100) - pwdb_all = 100; - /* modify the offset to make the same - * gain index with OFDM. - */ - if (pwdb_all > 34 && pwdb_all <= 42) - pwdb_all -= 2; - else if (pwdb_all > 26 && pwdb_all <= 34) - pwdb_all -= 6; - else if (pwdb_all > 14 && pwdb_all <= 26) - pwdb_all -= 8; - else if (pwdb_all > 4 && pwdb_all <= 14) - pwdb_all -= 4; - - pstatus->rx_pwdb_all = pwdb_all; - pstatus->recvsignalpower = rx_pwr_all; - - /* (3) Get Signal Quality (EVM) */ - if (bpacket_match_bssid) { - u8 sq; - - if (pstatus->rx_pwdb_all > 40) - sq = 100; - else { - sq = cck_buf->sq_rpt; - if (sq > 64) - sq = 0; - else if (sq < 20) - sq = 100; - else - sq = ((64 - sq) * 100) / 44; - } - - pstatus->signalquality = sq; - pstatus->rx_mimo_signalquality[0] = sq; - pstatus->rx_mimo_signalquality[1] = -1; - } - } else { - rtlpriv->dm.rfpath_rxenable[0] = - rtlpriv->dm.rfpath_rxenable[1] = true; - - /* (1)Get RSSI for HT rate */ - for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { - - /* we will judge RF RX path now. */ - if (rtlpriv->dm.rfpath_rxenable[i]) - rf_rx_num++; - - rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & - 0x3f) * 2) - 110; - - /* Translate DBM to percentage. */ - rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); - total_rssi += rssi; - - /* Get Rx snr value in DB */ - rtlpriv->stats.rx_snr_db[i] = - (long)(p_drvinfo->rxsnr[i] / 2); - - /* Record Signal Strength for next packet */ - if (bpacket_match_bssid) - pstatus->rx_mimo_signalstrength[i] = (u8)rssi; - } - - /* (2)PWDB, Average PWDB cacluated by - * hardware (for rate adaptive) - */ - rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; - - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - pstatus->rx_pwdb_all = pwdb_all; - pstatus->rxpower = rx_pwr_all; - pstatus->recvsignalpower = rx_pwr_all; - - /* (3)EVM of HT rate */ - if (pstatus->is_ht && pstatus->rate >= DESC92C_RATEMCS8 && - pstatus->rate <= DESC92C_RATEMCS15) - max_spatial_stream = 2; - else - max_spatial_stream = 1; - - for (i = 0; i < max_spatial_stream; i++) { - evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]); - - if (bpacket_match_bssid) { - /* Fill value in RFD, Get the first - * spatial stream only - */ - if (i == 0) - pstatus->signalquality = - (u8)(evm & 0xff); - pstatus->rx_mimo_signalquality[i] = - (u8)(evm & 0xff); - } - } - } - - /* UI BSS List signal strength(in percentage), - * make it good looking, from 0~100. - */ - if (is_cck) - pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, - pwdb_all)); - else if (rf_rx_num != 0) - pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, - total_rssi /= rf_rx_num)); -} - -static void translate_rx_signal_stuff(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct rtl_stats *pstatus, u8 *pdesc, - struct rx_fwinfo_8723e *p_drvinfo) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct ieee80211_hdr *hdr; - u8 *tmp_buf; - u8 *praddr; - /*u8 *psaddr;*/ - u16 fc, type; - bool packet_matchbssid, packet_toself, packet_beacon; - - tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; - - hdr = (struct ieee80211_hdr *)tmp_buf; - fc = le16_to_cpu(hdr->frame_control); - type = WLAN_FC_GET_TYPE(hdr->frame_control); - praddr = hdr->addr1; - - packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && - (ether_addr_equal(mac->bssid, (fc & IEEE80211_FCTL_TODS) ? - hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? - hdr->addr2 : hdr->addr3)) && - (!pstatus->hwerror) && - (!pstatus->crc) && (!pstatus->icv)); - - packet_toself = packet_matchbssid && - (ether_addr_equal(praddr, rtlefuse->dev_addr)); - - if (ieee80211_is_beacon(hdr->frame_control)) - packet_beacon = true; - else - packet_beacon = false; - - _rtl8723e_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo, - packet_matchbssid, packet_toself, - packet_beacon); - - rtl_process_phyinfo(hw, tmp_buf, pstatus); -} - -bool rtl8723e_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *status, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb) -{ - struct rx_fwinfo_8723e *p_drvinfo; - struct ieee80211_hdr *hdr; - u32 phystatus = GET_RX_DESC_PHYST(pdesc); - - status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); - status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * - RX_DRV_INFO_SIZE_UNIT; - status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03); - status->icv = (u16)GET_RX_DESC_ICV(pdesc); - status->crc = (u16)GET_RX_DESC_CRC32(pdesc); - status->hwerror = (status->crc | status->icv); - status->decrypted = !GET_RX_DESC_SWDEC(pdesc); - status->rate = (u8)GET_RX_DESC_RXMCS(pdesc); - status->shortpreamble = (u16)GET_RX_DESC_SPLCP(pdesc); - status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); - status->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1) && - (GET_RX_DESC_FAGGR(pdesc) == 1)); - status->timestamp_low = GET_RX_DESC_TSFL(pdesc); - status->rx_is40Mhzpacket = (bool)GET_RX_DESC_BW(pdesc); - status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); - - status->is_cck = RX_HAL_IS_CCK_RATE(status->rate); - - rx_status->freq = hw->conf.chandef.chan->center_freq; - rx_status->band = hw->conf.chandef.chan->band; - - hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size - + status->rx_bufshift); - - if (status->crc) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - - if (status->rx_is40Mhzpacket) - rx_status->flag |= RX_FLAG_40MHZ; - - if (status->is_ht) - rx_status->flag |= RX_FLAG_HT; - - rx_status->flag |= RX_FLAG_MACTIME_START; - - /* hw will set status->decrypted true, if it finds the - * frame is open data frame or mgmt frame. - * So hw will not decryption robust managment frame - * for IEEE80211w but still set status->decrypted - * true, so here we should set it back to undecrypted - * for IEEE80211w frame, and mac80211 sw will help - * to decrypt it - */ - if (status->decrypted) { - if ((!_ieee80211_is_robust_mgmt_frame(hdr)) && - (ieee80211_has_protected(hdr->frame_control))) - rx_status->flag |= RX_FLAG_DECRYPTED; - else - rx_status->flag &= ~RX_FLAG_DECRYPTED; - } - - /* rate_idx: index of data rate into band's - * supported rates or MCS index if HT rates - * are use (RX_FLAG_HT) - * Notice: this is diff with windows define - */ - rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht, - false, status->rate); - - rx_status->mactime = status->timestamp_low; - if (phystatus == true) { - p_drvinfo = (struct rx_fwinfo_8723e *)(skb->data + - status->rx_bufshift); - - translate_rx_signal_stuff(hw, skb, status, pdesc, p_drvinfo); - } - rx_status->signal = status->recvsignalpower + 10; - return true; -} - -void rtl8723e_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *txbd, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool b_defaultadapter = true; - /* bool b_trigger_ac = false; */ - u8 *pdesc = (u8 *)pdesc_tx; - u16 seq_number; - __le16 fc = hdr->frame_control; - u8 fw_qsel = _rtl8723e_map_hwqueue_to_fwqueue(skb, hw_queue); - bool firstseg = ((hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); - - bool lastseg = ((hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); - - dma_addr_t mapping = pci_map_single(rtlpci->pdev, - skb->data, skb->len, - PCI_DMA_TODEVICE); - u8 bw_40 = 0; - - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - if (mac->opmode == NL80211_IFTYPE_STATION) { - bw_40 = mac->bw_40; - } else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - if (sta) - bw_40 = sta->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40; - } - - seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - - rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); - - CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_8723e)); - - if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { - firstseg = true; - lastseg = true; - } - - if (firstseg) { - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - - SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); - - if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) - SET_TX_DESC_DATA_SHORTGI(pdesc, 1); - - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - SET_TX_DESC_AGG_BREAK(pdesc, 1); - SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); - } - SET_TX_DESC_SEQ(pdesc, seq_number); - - SET_TX_DESC_RTS_ENABLE(pdesc, - ((ptcb_desc->rts_enable && - !ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(pdesc, - ((ptcb_desc->rts_enable || - ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_CTS2SELF(pdesc, - ((ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_RTS_STBC(pdesc, - ((ptcb_desc->rts_stbc) ? 1 : 0)); - - SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); - SET_TX_DESC_RTS_BW(pdesc, 0); - SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(pdesc, - ((ptcb_desc->rts_rate <= DESC92C_RATE54M) ? - (ptcb_desc->rts_use_shortpreamble ? 1 : 0) - : (ptcb_desc->rts_use_shortgi ? 1 : 0))); - - if (bw_40) { - if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { - SET_TX_DESC_DATA_BW(pdesc, 1); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, - mac->cur_40_prime_sc); - } - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); - } - - SET_TX_DESC_LINIP(pdesc, 0); - SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); - - if (sta) { - u8 ampdu_density = sta->ht_cap.ampdu_density; - SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); - } - - if (info->control.hw_key) { - struct ieee80211_key_conf *keyconf = - info->control.hw_key; - - switch (keyconf->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - case WLAN_CIPHER_SUITE_TKIP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x1); - break; - case WLAN_CIPHER_SUITE_CCMP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x3); - break; - default: - SET_TX_DESC_SEC_TYPE(pdesc, 0x0); - break; - - } - } - - SET_TX_DESC_PKT_ID(pdesc, 0); - SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); - - SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); - SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); - SET_TX_DESC_DISABLE_FB(pdesc, 0); - SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); - - if (ieee80211_is_data_qos(fc)) { - if (mac->rdg_en) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "Enable RDG function.\n"); - SET_TX_DESC_RDG_ENABLE(pdesc, 1); - SET_TX_DESC_HTC(pdesc, 1); - } - } - } - - SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); - SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); - - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); - - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - if (rtlpriv->dm.useramask) { - SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); - } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); - } - - if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { - SET_TX_DESC_HWSEQ_EN_8723(pdesc, 1); - /* SET_TX_DESC_HWSEQ_EN(pdesc, 1); */ - /* SET_TX_DESC_PKT_ID(pdesc, 8); */ - - if (!b_defaultadapter) - SET_TX_DESC_HWSEQ_SEL_8723(pdesc, 1); - /* SET_TX_DESC_QOS(pdesc, 1); */ - } - - SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); - - if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || - is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { - SET_TX_DESC_BMC(pdesc, 1); - } - - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); -} - -void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc, bool firstseg, - bool lastseg, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 fw_queue = QSLT_BEACON; - - dma_addr_t mapping = pci_map_single(rtlpci->pdev, - skb->data, skb->len, - PCI_DMA_TODEVICE); - - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - __le16 fc = hdr->frame_control; - - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); - - if (firstseg) - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - - SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); - - SET_TX_DESC_SEQ(pdesc, 0); - - SET_TX_DESC_LINIP(pdesc, 0); - - SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); - - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len)); - - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - SET_TX_DESC_RATE_ID(pdesc, 7); - SET_TX_DESC_MACID(pdesc, 0); - - SET_TX_DESC_OWN(pdesc, 1); - - SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len)); - - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - SET_TX_DESC_OFFSET(pdesc, 0x20); - - SET_TX_DESC_USE_RATE(pdesc, 1); - - if (!ieee80211_is_data_qos(fc)) { - SET_TX_DESC_HWSEQ_EN_8723(pdesc, 1); - /* SET_TX_DESC_HWSEQ_EN(pdesc, 1); */ - /* SET_TX_DESC_PKT_ID(pdesc, 8); */ - } - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C Tx Cmd Content\n", - pdesc, TX_DESC_SIZE); -} - -void rtl8723e_set_desc(struct ieee80211_hw *hw, u8 *pdesc, - bool istx, u8 desc_name, u8 *val) -{ - if (istx == true) { - switch (desc_name) { - case HW_DESC_OWN: - SET_TX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_TX_NEXTDESC_ADDR: - SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); - break; - default: - RT_ASSERT(false, "ERR txdesc :%d not process\n", - desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_RXOWN: - SET_RX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_RXBUFF_ADDR: - SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val); - break; - case HW_DESC_RXPKT_LEN: - SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val); - break; - case HW_DESC_RXERO: - SET_RX_DESC_EOR(pdesc, 1); - break; - default: - RT_ASSERT(false, "ERR rxdesc :%d not process\n", - desc_name); - break; - } - } -} - -u32 rtl8723e_get_desc(u8 *pdesc, bool istx, u8 desc_name) -{ - u32 ret = 0; - - if (istx == true) { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_TX_DESC_OWN(pdesc); - break; - case HW_DESC_TXBUFF_ADDR: - ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc); - break; - default: - RT_ASSERT(false, "ERR txdesc :%d not process\n", - desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_RX_DESC_OWN(pdesc); - break; - case HW_DESC_RXPKT_LEN: - ret = GET_RX_DESC_PKT_LEN(pdesc); - break; - case HW_DESC_RXBUFF_ADDR: - ret = GET_RX_DESC_BUFF_ADDR(pdesc); - break; - default: - RT_ASSERT(false, "ERR rxdesc :%d not process\n", - desc_name); - break; - } - } - return ret; -} - -bool rtl8723e_is_tx_desc_closed(struct ieee80211_hw *hw, - u8 hw_queue, u16 index) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; - u8 *entry = (u8 *)(&ring->desc[ring->idx]); - u8 own = (u8)rtl8723e_get_desc(entry, true, HW_DESC_OWN); - - /** - *beacon packet will only use the first - *descriptor defautly,and the own may not - *be cleared by the hardware - */ - if (own) - return false; - return true; -} - -void rtl8723e_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (hw_queue == BEACON_QUEUE) { - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); - } else { - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, - BIT(0) << (hw_queue)); - } -} - -u32 rtl8723e_rx_command_packet(struct ieee80211_hw *hw, - struct rtl_stats status, - struct sk_buff *skb) -{ - return 0; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h deleted file mode 100644 index 017da7e194d8..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.h +++ /dev/null @@ -1,721 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723E_TRX_H__ -#define __RTL8723E_TRX_H__ - -#define TX_DESC_SIZE 64 -#define TX_DESC_AGGR_SUBFRAME_SIZE 32 - -#define RX_DESC_SIZE 32 -#define RX_DRV_INFO_SIZE_UNIT 8 - -#define TX_DESC_NEXT_DESC_OFFSET 40 -#define USB_HWDESC_HEADER_LEN 32 -#define CRCLENGTH 4 - -#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) -#define SET_TX_DESC_OFFSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) -#define SET_TX_DESC_BMC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) -#define SET_TX_DESC_HTC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) -#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) -#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) -#define SET_TX_DESC_LINIP(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) -#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) -#define SET_TX_DESC_GF(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) -#define SET_TX_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) - -#define GET_TX_DESC_PKT_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 0, 16) -#define GET_TX_DESC_OFFSET(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 16, 8) -#define GET_TX_DESC_BMC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 24, 1) -#define GET_TX_DESC_HTC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 25, 1) -#define GET_TX_DESC_LAST_SEG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 26, 1) -#define GET_TX_DESC_FIRST_SEG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 27, 1) -#define GET_TX_DESC_LINIP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 28, 1) -#define GET_TX_DESC_NO_ACM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 29, 1) -#define GET_TX_DESC_GF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 30, 1) -#define GET_TX_DESC_OWN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 31, 1) - -#define SET_TX_DESC_MACID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 5, __val) -#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 5, 1, __val) -#define SET_TX_DESC_BK(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 6, 1, __val) -#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 7, 1, __val) -#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) -#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) -#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) -#define SET_TX_DESC_PIFS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) -#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val) -#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val) -#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) -#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) -#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val) - -#define GET_TX_DESC_MACID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) -#define GET_TX_DESC_AGG_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 5, 1) -#define GET_TX_DESC_AGG_BREAK(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 6, 1) -#define GET_TX_DESC_RDG_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 7, 1) -#define GET_TX_DESC_QUEUE_SEL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 8, 5) -#define GET_TX_DESC_RDG_NAV_EXT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) -#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) -#define GET_TX_DESC_PIFS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) -#define GET_TX_DESC_RATE_ID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) -#define GET_TX_DESC_NAV_USE_HDR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) -#define GET_TX_DESC_EN_DESC_ID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) -#define GET_TX_DESC_SEC_TYPE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 22, 2) -#define GET_TX_DESC_PKT_OFFSET(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 24, 8) - -#define SET_TX_DESC_RTS_RC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val) -#define SET_TX_DESC_DATA_RC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val) -#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val) -#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) -#define SET_TX_DESC_RAW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) -#define SET_TX_DESC_CCX(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) -#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) -#define SET_TX_DESC_ANTSEL_A(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val) -#define SET_TX_DESC_ANTSEL_B(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val) -#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val) -#define SET_TX_DESC_TX_ANTL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val) -#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val) - -#define GET_TX_DESC_RTS_RC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 0, 6) -#define GET_TX_DESC_DATA_RC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 6, 6) -#define GET_TX_DESC_BAR_RTY_TH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 14, 2) -#define GET_TX_DESC_MORE_FRAG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 17, 1) -#define GET_TX_DESC_RAW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 18, 1) -#define GET_TX_DESC_CCX(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 19, 1) -#define GET_TX_DESC_AMPDU_DENSITY(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 20, 3) -#define GET_TX_DESC_ANTSEL_A(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 24, 1) -#define GET_TX_DESC_ANTSEL_B(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 25, 1) -#define GET_TX_DESC_TX_ANT_CCK(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 26, 2) -#define GET_TX_DESC_TX_ANTL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 28, 2) -#define GET_TX_DESC_TX_ANT_HT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 30, 2) - -#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val) -#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val) -#define SET_TX_DESC_SEQ(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val) -#define SET_TX_DESC_PKT_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 4, __val) - -#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 0, 8) -#define GET_TX_DESC_TAIL_PAGE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 8, 8) -#define GET_TX_DESC_SEQ(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 16, 12) -#define GET_TX_DESC_PKT_ID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 28, 4) - -/* For RTL8723 */ -#define SET_TX_DESC_TRIGGER_INT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 30, 1, __val) -#define SET_TX_DESC_HWSEQ_EN_8723(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 31, 1, __val) -#define SET_TX_DESC_HWSEQ_SEL_8723(__txdesc, __value) \ - SET_BITS_TO_LE_4BYTE(__txdesc+16, 6, 2, __value) - -#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val) -#define SET_TX_DESC_AP_DCFE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val) -#define SET_TX_DESC_QOS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val) -#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val) -#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val) -#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val) -#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val) -#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val) -#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val) -#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val) -#define SET_TX_DESC_PORT_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val) -#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val) -#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val) -#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val) -#define SET_TX_DESC_TX_STBC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val) -#define SET_TX_DESC_DATA_SHORT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val) -#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val) -#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val) -#define SET_TX_DESC_RTS_BW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val) -#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val) -#define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val) - -#define GET_TX_DESC_RTS_RATE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 0, 5) -#define GET_TX_DESC_AP_DCFE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 5, 1) -#define GET_TX_DESC_QOS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 6, 1) -#define GET_TX_DESC_HWSEQ_EN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 7, 1) -#define GET_TX_DESC_USE_RATE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 8, 1) -#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 9, 1) -#define GET_TX_DESC_DISABLE_FB(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 10, 1) -#define GET_TX_DESC_CTS2SELF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 11, 1) -#define GET_TX_DESC_RTS_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 12, 1) -#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 13, 1) -#define GET_TX_DESC_PORT_ID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 14, 1) -#define GET_TX_DESC_WAIT_DCTS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 18, 1) -#define GET_TX_DESC_CTS2AP_EN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 19, 1) -#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 20, 2) -#define GET_TX_DESC_TX_STBC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 22, 2) -#define GET_TX_DESC_DATA_SHORT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 24, 1) -#define GET_TX_DESC_DATA_BW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 25, 1) -#define GET_TX_DESC_RTS_SHORT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 26, 1) -#define GET_TX_DESC_RTS_BW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 27, 1) -#define GET_TX_DESC_RTS_SC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 28, 2) -#define GET_TX_DESC_RTS_STBC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 30, 2) - -#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val) -#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val) -#define SET_TX_DESC_CCX_TAG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) -#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val) -#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) -#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val) -#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val) -#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val) - -#define GET_TX_DESC_TX_RATE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 0, 6) -#define GET_TX_DESC_DATA_SHORTGI(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 6, 1) -#define GET_TX_DESC_CCX_TAG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 7, 1) -#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 8, 5) -#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 13, 4) -#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 17, 1) -#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 18, 6) -#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 24, 8) - -#define SET_TX_DESC_TXAGC_A(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val) -#define SET_TX_DESC_TXAGC_B(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val) -#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val) -#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val) -#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val) -#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val) -#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val) -#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val)\ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val) - -#define GET_TX_DESC_TXAGC_A(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 0, 5) -#define GET_TX_DESC_TXAGC_B(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 5, 5) -#define GET_TX_DESC_USE_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 10, 1) -#define GET_TX_DESC_MAX_AGG_NUM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 11, 5) -#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 16, 4) -#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 20, 4) -#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 24, 4) -#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 28, 4) - -#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) -#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 4, __val) -#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 20, 4, __val) -#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val) -#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 28, 4, __val) - -#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) -#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 16, 4) -#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 20, 4) -#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 24, 4) -#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 28, 4) - -#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val) -#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val) - -#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+32, 0, 32) -#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+36, 0, 32) - -#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) -#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val) - -#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+40, 0, 32) -#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+44, 0, 32) - -#define GET_RX_DESC_PKT_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 0, 14) -#define GET_RX_DESC_CRC32(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 14, 1) -#define GET_RX_DESC_ICV(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 15, 1) -#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 16, 4) -#define GET_RX_DESC_SECURITY(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 20, 3) -#define GET_RX_DESC_QOS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 23, 1) -#define GET_RX_DESC_SHIFT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 24, 2) -#define GET_RX_DESC_PHYST(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 26, 1) -#define GET_RX_DESC_SWDEC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 27, 1) -#define GET_RX_DESC_LS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 28, 1) -#define GET_RX_DESC_FS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 29, 1) -#define GET_RX_DESC_EOR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 30, 1) -#define GET_RX_DESC_OWN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 31, 1) - -#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) -#define SET_RX_DESC_EOR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) -#define SET_RX_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) - -#define GET_RX_DESC_MACID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 0, 5) -#define GET_RX_DESC_TID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 5, 4) -#define GET_RX_DESC_HWRSVD(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 9, 5) -#define GET_RX_DESC_PAGGR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) -#define GET_RX_DESC_FAGGR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) -#define GET_RX_DESC_A1_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) -#define GET_RX_DESC_A2_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 20, 4) -#define GET_RX_DESC_PAM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) -#define GET_RX_DESC_PWR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) -#define GET_RX_DESC_MD(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) -#define GET_RX_DESC_MF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) -#define GET_RX_DESC_TYPE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) -#define GET_RX_DESC_MC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) -#define GET_RX_DESC_BC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) -#define GET_RX_DESC_SEQ(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) -#define GET_RX_DESC_FRAG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) -#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 16, 14) -#define GET_RX_DESC_NEXT_IND(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 30, 1) -#define GET_RX_DESC_RSVD(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 31, 1) - -#define GET_RX_DESC_RXMCS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 0, 6) -#define GET_RX_DESC_RXHT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 6, 1) -#define GET_RX_DESC_SPLCP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 8, 1) -#define GET_RX_DESC_BW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 9, 1) -#define GET_RX_DESC_HTC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) -#define GET_RX_DESC_HWPC_ERR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 14, 1) -#define GET_RX_DESC_HWPC_IND(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 15, 1) -#define GET_RX_DESC_IV0(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 16, 16) - -#define GET_RX_DESC_IV1(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 0, 32) -#define GET_RX_DESC_TSFL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) - -#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) -#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) - -#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) -#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) - -#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ -do { \ - if (_size > TX_DESC_NEXT_DESC_OFFSET) \ - memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ - else \ - memset(__pdesc, 0, _size); \ -} while (0) - -struct rx_fwinfo_8723e { - u8 gain_trsw[4]; - u8 pwdb_all; - u8 cfosho[4]; - u8 cfotail[4]; - char rxevm[2]; - char rxsnr[4]; - u8 pdsnr[2]; - u8 csi_current[2]; - u8 csi_target[2]; - u8 sigevm; - u8 max_ex_pwr; - u8 ex_intf_flag:1; - u8 sgi_en:1; - u8 rxsc:2; - u8 reserve:4; -} __packed; - -struct tx_desc_8723e { - u32 pktsize:16; - u32 offset:8; - u32 bmc:1; - u32 htc:1; - u32 lastseg:1; - u32 firstseg:1; - u32 linip:1; - u32 noacm:1; - u32 gf:1; - u32 own:1; - - u32 macid:5; - u32 agg_en:1; - u32 bk:1; - u32 rdg_en:1; - u32 queuesel:5; - u32 rd_nav_ext:1; - u32 lsig_txop_en:1; - u32 pifs:1; - u32 rateid:4; - u32 nav_usehdr:1; - u32 en_descid:1; - u32 sectype:2; - u32 pktoffset:8; - - u32 rts_rc:6; - u32 data_rc:6; - u32 rsvd0:2; - u32 bar_retryht:2; - u32 rsvd1:1; - u32 morefrag:1; - u32 raw:1; - u32 ccx:1; - u32 ampdudensity:3; - u32 rsvd2:1; - u32 ant_sela:1; - u32 ant_selb:1; - u32 txant_cck:2; - u32 txant_l:2; - u32 txant_ht:2; - - u32 nextheadpage:8; - u32 tailpage:8; - u32 seq:12; - u32 pktid:4; - - u32 rtsrate:5; - u32 apdcfe:1; - u32 qos:1; - u32 hwseq_enable:1; - u32 userrate:1; - u32 dis_rtsfb:1; - u32 dis_datafb:1; - u32 cts2self:1; - u32 rts_en:1; - u32 hwrts_en:1; - u32 portid:1; - u32 rsvd3:3; - u32 waitdcts:1; - u32 cts2ap_en:1; - u32 txsc:2; - u32 stbc:2; - u32 txshort:1; - u32 txbw:1; - u32 rtsshort:1; - u32 rtsbw:1; - u32 rtssc:2; - u32 rtsstbc:2; - - u32 txrate:6; - u32 shortgi:1; - u32 ccxt:1; - u32 txrate_fb_lmt:5; - u32 rtsrate_fb_lmt:4; - u32 retrylmt_en:1; - u32 txretrylmt:6; - u32 usb_txaggnum:8; - - u32 txagca:5; - u32 txagcb:5; - u32 usemaxlen:1; - u32 maxaggnum:5; - u32 mcsg1maxlen:4; - u32 mcsg2maxlen:4; - u32 mcsg3maxlen:4; - u32 mcs7sgimaxlen:4; - - u32 txbuffersize:16; - u32 mcsg4maxlen:4; - u32 mcsg5maxlen:4; - u32 mcsg6maxlen:4; - u32 mcsg15sgimaxlen:4; - - u32 txbuffaddr; - u32 txbufferaddr64; - u32 nextdescaddress; - u32 nextdescaddress64; - - u32 reserve_pass_pcie_mm_limit[4]; -} __packed; - -struct rx_desc_8723e { - u32 length:14; - u32 crc32:1; - u32 icverror:1; - u32 drv_infosize:4; - u32 security:3; - u32 qos:1; - u32 shift:2; - u32 phystatus:1; - u32 swdec:1; - u32 lastseg:1; - u32 firstseg:1; - u32 eor:1; - u32 own:1; - - u32 macid:5; - u32 tid:4; - u32 hwrsvd:5; - u32 paggr:1; - u32 faggr:1; - u32 a1_fit:4; - u32 a2_fit:4; - u32 pam:1; - u32 pwr:1; - u32 moredata:1; - u32 morefrag:1; - u32 type:2; - u32 mc:1; - u32 bc:1; - - u32 seq:12; - u32 frag:4; - u32 nextpktlen:14; - u32 nextind:1; - u32 rsvd:1; - - u32 rxmcs:6; - u32 rxht:1; - u32 amsdu:1; - u32 splcp:1; - u32 bandwidth:1; - u32 htc:1; - u32 tcpchk_rpt:1; - u32 ipcchk_rpt:1; - u32 tcpchk_valid:1; - u32 hwpcerr:1; - u32 hwpcind:1; - u32 iv0:16; - - u32 iv1; - - u32 tsfl; - - u32 bufferaddress; - u32 bufferaddress64; - -} __packed; - -void rtl8723e_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, - u8 *pdesc, u8 *txbd, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, u8 hw_queue, - struct rtl_tcb_desc *ptcb_desc); -bool rtl8723e_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *status, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb); -void rtl8723e_set_desc(struct ieee80211_hw *hw, - u8 *pdesc, bool istx, u8 desc_name, u8 *val); -u32 rtl8723e_get_desc(u8 *pdesc, bool istx, u8 desc_name); -bool rtl8723e_is_tx_desc_closed(struct ieee80211_hw *hw, - u8 hw_queue, u16 index); -void rtl8723e_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); -void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, - struct sk_buff *skb); -u32 rtl8723e_rx_command_packet(struct ieee80211_hw *hw, - struct rtl_stats status, - struct sk_buff *skb); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/Makefile b/drivers/net/wireless/rtlwifi/rtl8723be/Makefile deleted file mode 100644 index a77c34102792..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -rtl8723be-objs := \ - dm.o \ - fw.o \ - hw.o \ - led.o \ - phy.o \ - pwrseq.o \ - rf.o \ - sw.o \ - table.o \ - trx.o \ - - -obj-$(CONFIG_RTL8723BE) += rtl8723be.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/def.h b/drivers/net/wireless/rtlwifi/rtl8723be/def.h deleted file mode 100644 index 025ea5c0f3f6..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/def.h +++ /dev/null @@ -1,92 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723BE_DEF_H__ -#define __RTL8723BE_DEF_H__ - -#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 -#define HAL_PRIME_CHNL_OFFSET_LOWER 1 -#define HAL_PRIME_CHNL_OFFSET_UPPER 2 - - -#define RX_MPDU_QUEUE 0 -#define CHIP_8723B (BIT(1) | BIT(2)) -#define NORMAL_CHIP BIT(3) -#define CHIP_VENDOR_SMIC BIT(8) -/* Currently only for RTL8723B */ -#define EXT_VENDOR_ID (BIT(18) | BIT(19)) - -enum rx_packet_type { - NORMAL_RX, - TX_REPORT1, - TX_REPORT2, - HIS_REPORT, - C2H_PACKET, -}; - -enum rtl_desc_qsel { - QSLT_BK = 0x2, - QSLT_BE = 0x0, - QSLT_VI = 0x5, - QSLT_VO = 0x7, - QSLT_BEACON = 0x10, - QSLT_HIGH = 0x11, - QSLT_MGNT = 0x12, - QSLT_CMD = 0x13, -}; - -enum rtl_desc8723e_rate { - DESC92C_RATE1M = 0x00, - DESC92C_RATE2M = 0x01, - DESC92C_RATE5_5M = 0x02, - DESC92C_RATE11M = 0x03, - - DESC92C_RATE6M = 0x04, - DESC92C_RATE9M = 0x05, - DESC92C_RATE12M = 0x06, - DESC92C_RATE18M = 0x07, - DESC92C_RATE24M = 0x08, - DESC92C_RATE36M = 0x09, - DESC92C_RATE48M = 0x0a, - DESC92C_RATE54M = 0x0b, - - DESC92C_RATEMCS0 = 0x0c, - DESC92C_RATEMCS1 = 0x0d, - DESC92C_RATEMCS2 = 0x0e, - DESC92C_RATEMCS3 = 0x0f, - DESC92C_RATEMCS4 = 0x10, - DESC92C_RATEMCS5 = 0x11, - DESC92C_RATEMCS6 = 0x12, - DESC92C_RATEMCS7 = 0x13, - DESC92C_RATEMCS8 = 0x14, - DESC92C_RATEMCS9 = 0x15, - DESC92C_RATEMCS10 = 0x16, - DESC92C_RATEMCS11 = 0x17, - DESC92C_RATEMCS12 = 0x18, - DESC92C_RATEMCS13 = 0x19, - DESC92C_RATEMCS14 = 0x1a, - DESC92C_RATEMCS15 = 0x1b, -}; -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/dm.c b/drivers/net/wireless/rtlwifi/rtl8723be/dm.c deleted file mode 100644 index 3a81cdba8ca3..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/dm.c +++ /dev/null @@ -1,1298 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../base.h" -#include "../pci.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "../rtl8723com/dm_common.h" -#include "fw.h" -#include "trx.h" -#include "../btcoexist/rtl_btc.h" - -static const u32 ofdmswing_table[] = { - 0x0b40002d, /* 0, -15.0dB */ - 0x0c000030, /* 1, -14.5dB */ - 0x0cc00033, /* 2, -14.0dB */ - 0x0d800036, /* 3, -13.5dB */ - 0x0e400039, /* 4, -13.0dB */ - 0x0f00003c, /* 5, -12.5dB */ - 0x10000040, /* 6, -12.0dB */ - 0x11000044, /* 7, -11.5dB */ - 0x12000048, /* 8, -11.0dB */ - 0x1300004c, /* 9, -10.5dB */ - 0x14400051, /* 10, -10.0dB */ - 0x15800056, /* 11, -9.5dB */ - 0x16c0005b, /* 12, -9.0dB */ - 0x18000060, /* 13, -8.5dB */ - 0x19800066, /* 14, -8.0dB */ - 0x1b00006c, /* 15, -7.5dB */ - 0x1c800072, /* 16, -7.0dB */ - 0x1e400079, /* 17, -6.5dB */ - 0x20000080, /* 18, -6.0dB */ - 0x22000088, /* 19, -5.5dB */ - 0x24000090, /* 20, -5.0dB */ - 0x26000098, /* 21, -4.5dB */ - 0x288000a2, /* 22, -4.0dB */ - 0x2ac000ab, /* 23, -3.5dB */ - 0x2d4000b5, /* 24, -3.0dB */ - 0x300000c0, /* 25, -2.5dB */ - 0x32c000cb, /* 26, -2.0dB */ - 0x35c000d7, /* 27, -1.5dB */ - 0x390000e4, /* 28, -1.0dB */ - 0x3c8000f2, /* 29, -0.5dB */ - 0x40000100, /* 30, +0dB */ - 0x43c0010f, /* 31, +0.5dB */ - 0x47c0011f, /* 32, +1.0dB */ - 0x4c000130, /* 33, +1.5dB */ - 0x50800142, /* 34, +2.0dB */ - 0x55400155, /* 35, +2.5dB */ - 0x5a400169, /* 36, +3.0dB */ - 0x5fc0017f, /* 37, +3.5dB */ - 0x65400195, /* 38, +4.0dB */ - 0x6b8001ae, /* 39, +4.5dB */ - 0x71c001c7, /* 40, +5.0dB */ - 0x788001e2, /* 41, +5.5dB */ - 0x7f8001fe /* 42, +6.0dB */ -}; - -static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /* 0, -16.0dB */ - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 1, -15.5dB */ - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 2, -15.0dB */ - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 3, -14.5dB */ - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 4, -14.0dB */ - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 5, -13.5dB */ - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 6, -13.0dB */ - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 7, -12.5dB */ - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 8, -12.0dB */ - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 9, -11.5dB */ - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */ - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */ - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */ - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */ - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */ - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */ - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */ - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */ - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */ - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */ - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */ - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */ - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */ - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */ - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */ - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */ - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */ - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */ - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */ - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */ - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */ - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04} /* 32, +0dB */ -}; - -static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { - {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /* 0, -16.0dB */ - {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 1, -15.5dB */ - {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 2, -15.0dB */ - {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 3, -14.5dB */ - {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 4, -14.0dB */ - {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 5, -13.5dB */ - {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 6, -13.0dB */ - {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 7, -12.5dB */ - {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 8, -12.0dB */ - {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 9, -11.5dB */ - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */ - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */ - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */ - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */ - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */ - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */ - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */ - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */ - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */ - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */ - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */ - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */ - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */ - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */ - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */ - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */ - {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */ - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */ - {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */ - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */ - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */ - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00} /* 32, +0dB */ -}; - -static const u32 edca_setting_dl[PEER_MAX] = { - 0xa44f, /* 0 UNKNOWN */ - 0x5ea44f, /* 1 REALTEK_90 */ - 0x5e4322, /* 2 REALTEK_92SE */ - 0x5ea42b, /* 3 BROAD */ - 0xa44f, /* 4 RAL */ - 0xa630, /* 5 ATH */ - 0x5ea630, /* 6 CISCO */ - 0x5ea42b, /* 7 MARVELL */ -}; - -static const u32 edca_setting_ul[PEER_MAX] = { - 0x5e4322, /* 0 UNKNOWN */ - 0xa44f, /* 1 REALTEK_90 */ - 0x5ea44f, /* 2 REALTEK_92SE */ - 0x5ea32b, /* 3 BROAD */ - 0x5ea422, /* 4 RAL */ - 0x5ea322, /* 5 ATH */ - 0x3ea430, /* 6 CISCO */ - 0x5ea44f, /* 7 MARV */ -}; - -void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw *hw, u8 type, - u8 *pdirection, u32 *poutwrite_val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - u8 pwr_val = 0; - u8 ofdm_base = rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A]; - u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A]; - u8 cck_base = rtldm->swing_idx_cck_base; - u8 cck_val = rtldm->swing_idx_cck; - - if (type == 0) { - if (ofdm_val <= ofdm_base) { - *pdirection = 1; - pwr_val = ofdm_base - ofdm_val; - } else { - *pdirection = 2; - pwr_val = ofdm_val - ofdm_base; - } - } else if (type == 1) { - if (cck_val <= cck_base) { - *pdirection = 1; - pwr_val = cck_base - cck_val; - } else { - *pdirection = 2; - pwr_val = cck_val - cck_base; - } - } - - if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1)) - pwr_val = TXPWRTRACK_MAX_IDX; - - *poutwrite_val = pwr_val | (pwr_val << 8) | - (pwr_val << 16) | (pwr_val << 24); -} - -void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rate_adaptive *p_ra = &rtlpriv->ra; - - p_ra->ratr_state = DM_RATR_STA_INIT; - p_ra->pre_ratr_state = DM_RATR_STA_INIT; - - if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) - rtlpriv->dm.useramask = true; - else - rtlpriv->dm.useramask = false; - - p_ra->high_rssi_thresh_for_ra = 50; - p_ra->low_rssi_thresh_for_ra40m = 20; -} - -static void rtl8723be_dm_init_txpower_tracking(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.txpower_tracking = true; - rtlpriv->dm.txpower_track_control = true; - rtlpriv->dm.thermalvalue = 0; - - rtlpriv->dm.ofdm_index[0] = 30; - rtlpriv->dm.cck_index = 20; - - rtlpriv->dm.swing_idx_cck_base = rtlpriv->dm.cck_index; - - rtlpriv->dm.swing_idx_ofdm_base[0] = rtlpriv->dm.ofdm_index[0]; - rtlpriv->dm.delta_power_index[RF90_PATH_A] = 0; - rtlpriv->dm.delta_power_index_last[RF90_PATH_A] = 0; - rtlpriv->dm.power_index_offset[RF90_PATH_A] = 0; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - " rtlpriv->dm.txpower_tracking = %d\n", - rtlpriv->dm.txpower_tracking); -} - -static void rtl8723be_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap; - - rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, 0x800); - rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL; -} - -void rtl8723be_dm_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f); - - rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; - rtl_dm_diginit(hw, cur_igvalue); - rtl8723be_dm_init_rate_adaptive_mask(hw); - rtl8723_dm_init_edca_turbo(hw); - rtl8723_dm_init_dynamic_bb_powersaving(hw); - rtl8723_dm_init_dynamic_txpower(hw); - rtl8723be_dm_init_txpower_tracking(hw); - rtl8723be_dm_init_dynamic_atc_switch(hw); -} - -static void rtl8723be_dm_find_minimum_rssi(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable; - struct rtl_mac *mac = rtl_mac(rtlpriv); - - /* Determine the minimum RSSI */ - if ((mac->link_state < MAC80211_LINKED) && - (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { - rtl_dm_dig->min_undec_pwdb_for_dm = 0; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "Not connected to any\n"); - } - if (mac->link_state >= MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - rtl_dm_dig->min_undec_pwdb_for_dm = - rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "AP Client PWDB = 0x%lx\n", - rtlpriv->dm.entry_min_undec_sm_pwdb); - } else { - rtl_dm_dig->min_undec_pwdb_for_dm = - rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "STA Default Port PWDB = 0x%x\n", - rtl_dm_dig->min_undec_pwdb_for_dm); - } - } else { - rtl_dm_dig->min_undec_pwdb_for_dm = - rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "AP Ext Port or disconnect PWDB = 0x%x\n", - rtl_dm_dig->min_undec_pwdb_for_dm); - } - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n", - rtl_dm_dig->min_undec_pwdb_for_dm); -} - -static void rtl8723be_dm_check_rssi_monitor(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - struct rtl_sta_info *drv_priv; - u8 h2c_parameter[3] = { 0 }; - long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff; - - /* AP & ADHOC & MESH */ - spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { - if (drv_priv->rssi_stat.undec_sm_pwdb < - tmp_entry_min_pwdb) - tmp_entry_min_pwdb = - drv_priv->rssi_stat.undec_sm_pwdb; - if (drv_priv->rssi_stat.undec_sm_pwdb > - tmp_entry_max_pwdb) - tmp_entry_max_pwdb = - drv_priv->rssi_stat.undec_sm_pwdb; - } - spin_unlock_bh(&rtlpriv->locks.entry_list_lock); - - /* If associated entry is found */ - if (tmp_entry_max_pwdb != 0) { - rtlpriv->dm.entry_max_undec_sm_pwdb = - tmp_entry_max_pwdb; - RTPRINT(rtlpriv, FDM, DM_PWDB, - "EntryMaxPWDB = 0x%lx(%ld)\n", - tmp_entry_max_pwdb, tmp_entry_max_pwdb); - } else { - rtlpriv->dm.entry_max_undec_sm_pwdb = 0; - } - /* If associated entry is found */ - if (tmp_entry_min_pwdb != 0xff) { - rtlpriv->dm.entry_min_undec_sm_pwdb = - tmp_entry_min_pwdb; - RTPRINT(rtlpriv, FDM, DM_PWDB, - "EntryMinPWDB = 0x%lx(%ld)\n", - tmp_entry_min_pwdb, tmp_entry_min_pwdb); - } else { - rtlpriv->dm.entry_min_undec_sm_pwdb = 0; - } - /* Indicate Rx signal strength to FW. */ - if (rtlpriv->dm.useramask) { - h2c_parameter[2] = - (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF); - h2c_parameter[1] = 0x20; - h2c_parameter[0] = 0; - rtl8723be_fill_h2c_cmd(hw, H2C_RSSIBE_REPORT, 3, h2c_parameter); - } else { - rtl_write_byte(rtlpriv, 0x4fe, - rtlpriv->dm.undec_sm_pwdb); - } - rtl8723be_dm_find_minimum_rssi(hw); - dm_digtable->rssi_val_min = - rtlpriv->dm_digtable.min_undec_pwdb_for_dm; -} - -void rtl8723be_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - if (dm_digtable->stop_dig) - return; - - if (dm_digtable->cur_igvalue != current_igi) { - rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi); - if (rtlpriv->phy.rf_type != RF_1T1R) - rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, - 0x7f, current_igi); - } - dm_digtable->pre_igvalue = dm_digtable->cur_igvalue; - dm_digtable->cur_igvalue = current_igi; -} - -static void rtl8723be_dm_dig(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 dig_min_0, dig_maxofmin; - bool bfirstconnect, bfirstdisconnect; - u8 dm_dig_max, dm_dig_min; - u8 current_igi = dm_digtable->cur_igvalue; - u8 offset; - - /* AP,BT */ - if (mac->act_scanning) - return; - - dig_min_0 = dm_digtable->dig_min_0; - bfirstconnect = (mac->link_state >= MAC80211_LINKED) && - !dm_digtable->media_connect_0; - bfirstdisconnect = (mac->link_state < MAC80211_LINKED) && - (dm_digtable->media_connect_0); - - dm_dig_max = 0x5a; - dm_dig_min = DM_DIG_MIN; - dig_maxofmin = DM_DIG_MAX_AP; - - if (mac->link_state >= MAC80211_LINKED) { - if ((dm_digtable->rssi_val_min + 10) > dm_dig_max) - dm_digtable->rx_gain_max = dm_dig_max; - else if ((dm_digtable->rssi_val_min + 10) < dm_dig_min) - dm_digtable->rx_gain_max = dm_dig_min; - else - dm_digtable->rx_gain_max = - dm_digtable->rssi_val_min + 10; - - if (rtlpriv->dm.one_entry_only) { - offset = 12; - if (dm_digtable->rssi_val_min - offset < dm_dig_min) - dig_min_0 = dm_dig_min; - else if (dm_digtable->rssi_val_min - offset > - dig_maxofmin) - dig_min_0 = dig_maxofmin; - else - dig_min_0 = - dm_digtable->rssi_val_min - offset; - } else { - dig_min_0 = dm_dig_min; - } - - } else { - dm_digtable->rx_gain_max = dm_dig_max; - dig_min_0 = dm_dig_min; - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n"); - } - - if (rtlpriv->falsealm_cnt.cnt_all > 10000) { - if (dm_digtable->large_fa_hit != 3) - dm_digtable->large_fa_hit++; - if (dm_digtable->forbidden_igi < current_igi) { - dm_digtable->forbidden_igi = current_igi; - dm_digtable->large_fa_hit = 1; - } - - if (dm_digtable->large_fa_hit >= 3) { - if ((dm_digtable->forbidden_igi + 1) > - dm_digtable->rx_gain_max) - dm_digtable->rx_gain_min = - dm_digtable->rx_gain_max; - else - dm_digtable->rx_gain_min = - dm_digtable->forbidden_igi + 1; - dm_digtable->recover_cnt = 3600; - } - } else { - if (dm_digtable->recover_cnt != 0) { - dm_digtable->recover_cnt--; - } else { - if (dm_digtable->large_fa_hit < 3) { - if ((dm_digtable->forbidden_igi - 1) < - dig_min_0) { - dm_digtable->forbidden_igi = - dig_min_0; - dm_digtable->rx_gain_min = - dig_min_0; - } else { - dm_digtable->forbidden_igi--; - dm_digtable->rx_gain_min = - dm_digtable->forbidden_igi + 1; - } - } else { - dm_digtable->large_fa_hit = 0; - } - } - } - if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max) - dm_digtable->rx_gain_min = dm_digtable->rx_gain_max; - - if (mac->link_state >= MAC80211_LINKED) { - if (bfirstconnect) { - if (dm_digtable->rssi_val_min <= dig_maxofmin) - current_igi = dm_digtable->rssi_val_min; - else - current_igi = dig_maxofmin; - - dm_digtable->large_fa_hit = 0; - } else { - if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2) - current_igi += 4; - else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1) - current_igi += 2; - else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) - current_igi -= 2; - } - } else { - if (bfirstdisconnect) { - current_igi = dm_digtable->rx_gain_min; - } else { - if (rtlpriv->falsealm_cnt.cnt_all > 10000) - current_igi += 4; - else if (rtlpriv->falsealm_cnt.cnt_all > 8000) - current_igi += 2; - else if (rtlpriv->falsealm_cnt.cnt_all < 500) - current_igi -= 2; - } - } - - if (current_igi > dm_digtable->rx_gain_max) - current_igi = dm_digtable->rx_gain_max; - else if (current_igi < dm_digtable->rx_gain_min) - current_igi = dm_digtable->rx_gain_min; - - rtl8723be_dm_write_dig(hw, current_igi); - dm_digtable->media_connect_0 = - ((mac->link_state >= MAC80211_LINKED) ? true : false); - dm_digtable->dig_min_0 = dig_min_0; -} - -static void rtl8723be_dm_false_alarm_counter_statistics( - struct ieee80211_hw *hw) -{ - u32 ret_value; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt; - - rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); - rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); - - ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD); - falsealm_cnt->cnt_fast_fsync_fail = ret_value & 0xffff; - falsealm_cnt->cnt_sb_search_fail = (ret_value & 0xffff0000) >> 16; - - ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD); - falsealm_cnt->cnt_ofdm_cca = ret_value & 0xffff; - falsealm_cnt->cnt_parity_fail = (ret_value & 0xffff0000) >> 16; - - ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD); - falsealm_cnt->cnt_rate_illegal = ret_value & 0xffff; - falsealm_cnt->cnt_crc8_fail = (ret_value & 0xffff0000) >> 16; - - ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD); - falsealm_cnt->cnt_mcs_fail = ret_value & 0xffff; - - falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + - falsealm_cnt->cnt_mcs_fail + - falsealm_cnt->cnt_fast_fsync_fail + - falsealm_cnt->cnt_sb_search_fail; - - rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1); - rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1); - - ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_RST_11N, MASKBYTE0); - falsealm_cnt->cnt_cck_fail = ret_value; - - ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3); - falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; - - ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD); - falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) | - ((ret_value & 0xff00) >> 8); - - falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail + - falsealm_cnt->cnt_sb_search_fail + - falsealm_cnt->cnt_parity_fail + - falsealm_cnt->cnt_rate_illegal + - falsealm_cnt->cnt_crc8_fail + - falsealm_cnt->cnt_mcs_fail + - falsealm_cnt->cnt_cck_fail; - - falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca + - falsealm_cnt->cnt_cck_cca; - - rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1); - rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0); - rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1); - rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0); - - rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0); - rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0); - - rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0); - rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2); - - rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0); - rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", - falsealm_cnt->cnt_parity_fail, - falsealm_cnt->cnt_rate_illegal, - falsealm_cnt->cnt_crc8_fail, - falsealm_cnt->cnt_mcs_fail); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", - falsealm_cnt->cnt_ofdm_fail, - falsealm_cnt->cnt_cck_fail, - falsealm_cnt->cnt_all); -} - -static void rtl8723be_dm_dynamic_txpower(struct ieee80211_hw *hw) -{ - /* 8723BE does not support ODM_BB_DYNAMIC_TXPWR*/ - return; -} - -static void rtl8723be_set_iqk_matrix(struct ieee80211_hw *hw, u8 ofdm_index, - u8 rfpath, long iqk_result_x, - long iqk_result_y) -{ - long ele_a = 0, ele_d, ele_c = 0, value32; - - if (ofdm_index >= 43) - ofdm_index = 43 - 1; - - ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000) >> 22; - - if (iqk_result_x != 0) { - if ((iqk_result_x & 0x00000200) != 0) - iqk_result_x = iqk_result_x | 0xFFFFFC00; - ele_a = ((iqk_result_x * ele_d) >> 8) & 0x000003FF; - - if ((iqk_result_y & 0x00000200) != 0) - iqk_result_y = iqk_result_y | 0xFFFFFC00; - ele_c = ((iqk_result_y * ele_d) >> 8) & 0x000003FF; - - switch (rfpath) { - case RF90_PATH_A: - value32 = (ele_d << 22) | - ((ele_c & 0x3F) << 16) | ele_a; - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD, - value32); - value32 = (ele_c & 0x000003C0) >> 6; - rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32); - value32 = ((iqk_result_x * ele_d) >> 7) & 0x01; - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), - value32); - break; - default: - break; - } - } else { - switch (rfpath) { - case RF90_PATH_A: - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD, - ofdmswing_table[ofdm_index]); - rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 0x00); - break; - default: - break; - } - } -} - -static void rtl8723be_dm_tx_power_track_set_power(struct ieee80211_hw *hw, - enum pwr_track_control_method method, - u8 rfpath, u8 idx) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - u8 swing_idx_ofdm_limit = 36; - - if (method == TXAGC) { - rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel); - } else if (method == BBSWING) { - if (rtldm->swing_idx_cck >= CCK_TABLE_SIZE) - rtldm->swing_idx_cck = CCK_TABLE_SIZE - 1; - - if (!rtldm->cck_inch14) { - rtl_write_byte(rtlpriv, 0xa22, - cckswing_table_ch1ch13[rtldm->swing_idx_cck][0]); - rtl_write_byte(rtlpriv, 0xa23, - cckswing_table_ch1ch13[rtldm->swing_idx_cck][1]); - rtl_write_byte(rtlpriv, 0xa24, - cckswing_table_ch1ch13[rtldm->swing_idx_cck][2]); - rtl_write_byte(rtlpriv, 0xa25, - cckswing_table_ch1ch13[rtldm->swing_idx_cck][3]); - rtl_write_byte(rtlpriv, 0xa26, - cckswing_table_ch1ch13[rtldm->swing_idx_cck][4]); - rtl_write_byte(rtlpriv, 0xa27, - cckswing_table_ch1ch13[rtldm->swing_idx_cck][5]); - rtl_write_byte(rtlpriv, 0xa28, - cckswing_table_ch1ch13[rtldm->swing_idx_cck][6]); - rtl_write_byte(rtlpriv, 0xa29, - cckswing_table_ch1ch13[rtldm->swing_idx_cck][7]); - } else { - rtl_write_byte(rtlpriv, 0xa22, - cckswing_table_ch14[rtldm->swing_idx_cck][0]); - rtl_write_byte(rtlpriv, 0xa23, - cckswing_table_ch14[rtldm->swing_idx_cck][1]); - rtl_write_byte(rtlpriv, 0xa24, - cckswing_table_ch14[rtldm->swing_idx_cck][2]); - rtl_write_byte(rtlpriv, 0xa25, - cckswing_table_ch14[rtldm->swing_idx_cck][3]); - rtl_write_byte(rtlpriv, 0xa26, - cckswing_table_ch14[rtldm->swing_idx_cck][4]); - rtl_write_byte(rtlpriv, 0xa27, - cckswing_table_ch14[rtldm->swing_idx_cck][5]); - rtl_write_byte(rtlpriv, 0xa28, - cckswing_table_ch14[rtldm->swing_idx_cck][6]); - rtl_write_byte(rtlpriv, 0xa29, - cckswing_table_ch14[rtldm->swing_idx_cck][7]); - } - - if (rfpath == RF90_PATH_A) { - if (rtldm->swing_idx_ofdm[RF90_PATH_A] < - swing_idx_ofdm_limit) - swing_idx_ofdm_limit = - rtldm->swing_idx_ofdm[RF90_PATH_A]; - - rtl8723be_set_iqk_matrix(hw, - rtldm->swing_idx_ofdm[rfpath], rfpath, - rtlphy->iqk_matrix[idx].value[0][0], - rtlphy->iqk_matrix[idx].value[0][1]); - } else if (rfpath == RF90_PATH_B) { - if (rtldm->swing_idx_ofdm[RF90_PATH_B] < - swing_idx_ofdm_limit) - swing_idx_ofdm_limit = - rtldm->swing_idx_ofdm[RF90_PATH_B]; - - rtl8723be_set_iqk_matrix(hw, - rtldm->swing_idx_ofdm[rfpath], rfpath, - rtlphy->iqk_matrix[idx].value[0][4], - rtlphy->iqk_matrix[idx].value[0][5]); - } - } else { - return; - } -} - -static void rtl8723be_dm_txpower_tracking_callback_thermalmeter( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - u8 thermalvalue = 0, delta, delta_lck, delta_iqk; - u8 thermalvalue_avg_count = 0; - u32 thermalvalue_avg = 0; - int i = 0; - - u8 ofdm_min_index = 6; - u8 index_for_channel = 0; - - char delta_swing_table_idx_tup_a[TXSCALE_TABLE_SIZE] = { - 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5, - 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10, - 10, 11, 11, 12, 12, 13, 14, 15}; - char delta_swing_table_idx_tdown_a[TXSCALE_TABLE_SIZE] = { - 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5, - 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 9, - 9, 10, 10, 11, 12, 13, 14, 15}; - - /*Initilization ( 7 steps in total )*/ - rtlpriv->dm.txpower_trackinginit = true; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "rtl8723be_dm_txpower_tracking_callback_thermalmeter\n"); - - thermalvalue = (u8)rtl_get_rfreg(hw, - RF90_PATH_A, RF_T_METER, 0xfc00); - if (!rtlpriv->dm.txpower_track_control || thermalvalue == 0 || - rtlefuse->eeprom_thermalmeter == 0xFF) - return; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n", - thermalvalue, rtldm->thermalvalue, - rtlefuse->eeprom_thermalmeter); - /*3 Initialize ThermalValues of RFCalibrateInfo*/ - if (!rtldm->thermalvalue) { - rtlpriv->dm.thermalvalue_lck = thermalvalue; - rtlpriv->dm.thermalvalue_iqk = thermalvalue; - } - - /*4 Calculate average thermal meter*/ - rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue; - rtldm->thermalvalue_avg_index++; - if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8723BE) - rtldm->thermalvalue_avg_index = 0; - - for (i = 0; i < AVG_THERMAL_NUM_8723BE; i++) { - if (rtldm->thermalvalue_avg[i]) { - thermalvalue_avg += rtldm->thermalvalue_avg[i]; - thermalvalue_avg_count++; - } - } - - if (thermalvalue_avg_count) - thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count); - - /* 5 Calculate delta, delta_LCK, delta_IQK.*/ - delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? - (thermalvalue - rtlpriv->dm.thermalvalue) : - (rtlpriv->dm.thermalvalue - thermalvalue); - delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? - (thermalvalue - rtlpriv->dm.thermalvalue_lck) : - (rtlpriv->dm.thermalvalue_lck - thermalvalue); - delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? - (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : - (rtlpriv->dm.thermalvalue_iqk - thermalvalue); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n", - thermalvalue, rtlpriv->dm.thermalvalue, - rtlefuse->eeprom_thermalmeter, delta, delta_lck, delta_iqk); - /* 6 If necessary, do LCK.*/ - if (delta_lck >= IQK_THRESHOLD) { - rtlpriv->dm.thermalvalue_lck = thermalvalue; - rtl8723be_phy_lc_calibrate(hw); - } - - /* 7 If necessary, move the index of - * swing table to adjust Tx power. - */ - if (delta > 0 && rtlpriv->dm.txpower_track_control) { - delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? - (thermalvalue - rtlefuse->eeprom_thermalmeter) : - (rtlefuse->eeprom_thermalmeter - thermalvalue); - - if (delta >= TXSCALE_TABLE_SIZE) - delta = TXSCALE_TABLE_SIZE - 1; - /* 7.1 Get the final CCK_index and - * OFDM_index for each swing table. - */ - if (thermalvalue > rtlefuse->eeprom_thermalmeter) { - rtldm->delta_power_index_last[RF90_PATH_A] = - rtldm->delta_power_index[RF90_PATH_A]; - rtldm->delta_power_index[RF90_PATH_A] = - delta_swing_table_idx_tup_a[delta]; - } else { - rtldm->delta_power_index_last[RF90_PATH_A] = - rtldm->delta_power_index[RF90_PATH_A]; - rtldm->delta_power_index[RF90_PATH_A] = - -1 * delta_swing_table_idx_tdown_a[delta]; - } - - /* 7.2 Handle boundary conditions of index.*/ - if (rtldm->delta_power_index[RF90_PATH_A] == - rtldm->delta_power_index_last[RF90_PATH_A]) - rtldm->power_index_offset[RF90_PATH_A] = 0; - else - rtldm->power_index_offset[RF90_PATH_A] = - rtldm->delta_power_index[RF90_PATH_A] - - rtldm->delta_power_index_last[RF90_PATH_A]; - - rtldm->ofdm_index[0] = - rtldm->swing_idx_ofdm_base[RF90_PATH_A] + - rtldm->power_index_offset[RF90_PATH_A]; - rtldm->cck_index = rtldm->swing_idx_cck_base + - rtldm->power_index_offset[RF90_PATH_A]; - - rtldm->swing_idx_cck = rtldm->cck_index; - rtldm->swing_idx_ofdm[0] = rtldm->ofdm_index[0]; - - if (rtldm->ofdm_index[0] > OFDM_TABLE_SIZE - 1) - rtldm->ofdm_index[0] = OFDM_TABLE_SIZE - 1; - else if (rtldm->ofdm_index[0] < ofdm_min_index) - rtldm->ofdm_index[0] = ofdm_min_index; - - if (rtldm->cck_index > CCK_TABLE_SIZE - 1) - rtldm->cck_index = CCK_TABLE_SIZE - 1; - else if (rtldm->cck_index < 0) - rtldm->cck_index = 0; - } else { - rtldm->power_index_offset[RF90_PATH_A] = 0; - } - - if ((rtldm->power_index_offset[RF90_PATH_A] != 0) && - (rtldm->txpower_track_control)) { - rtldm->done_txpower = true; - if (thermalvalue > rtlefuse->eeprom_thermalmeter) - rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0, - index_for_channel); - else - rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0, - index_for_channel); - - rtldm->swing_idx_cck_base = rtldm->swing_idx_cck; - rtldm->swing_idx_ofdm_base[RF90_PATH_A] = - rtldm->swing_idx_ofdm[0]; - rtldm->thermalvalue = thermalvalue; - } - - if (delta_iqk >= IQK_THRESHOLD) { - rtldm->thermalvalue_iqk = thermalvalue; - rtl8723be_phy_iq_calibrate(hw, false); - } - - rtldm->txpowercount = 0; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n"); - -} - -void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (!rtlpriv->dm.txpower_tracking) - return; - - if (!rtlpriv->dm.tm_trigger) { - rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16), - 0x03); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Trigger 8723be Thermal Meter!!\n"); - rtlpriv->dm.tm_trigger = 1; - return; - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Schedule TxPowerTracking !!\n"); - rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw); - rtlpriv->dm.tm_trigger = 0; - } -} - -static void rtl8723be_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rate_adaptive *p_ra = &rtlpriv->ra; - u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m; - u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra; - u8 go_up_gap = 5; - struct ieee80211_sta *sta = NULL; - - if (is_hal_stop(rtlhal)) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "driver is going to unload\n"); - return; - } - - if (!rtlpriv->dm.useramask) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "driver does not control rate adaptive mask\n"); - return; - } - - if (mac->link_state == MAC80211_LINKED && - mac->opmode == NL80211_IFTYPE_STATION) { - switch (p_ra->pre_ratr_state) { - case DM_RATR_STA_MIDDLE: - high_rssithresh_for_ra += go_up_gap; - break; - case DM_RATR_STA_LOW: - high_rssithresh_for_ra += go_up_gap; - low_rssithresh_for_ra += go_up_gap; - break; - default: - break; - } - - if (rtlpriv->dm.undec_sm_pwdb > - (long)high_rssithresh_for_ra) - p_ra->ratr_state = DM_RATR_STA_HIGH; - else if (rtlpriv->dm.undec_sm_pwdb > - (long)low_rssithresh_for_ra) - p_ra->ratr_state = DM_RATR_STA_MIDDLE; - else - p_ra->ratr_state = DM_RATR_STA_LOW; - - if (p_ra->pre_ratr_state != p_ra->ratr_state) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "RSSI = %ld\n", - rtlpriv->dm.undec_sm_pwdb); - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "RSSI_LEVEL = %d\n", p_ra->ratr_state); - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "PreState = %d, CurState = %d\n", - p_ra->pre_ratr_state, p_ra->ratr_state); - - rcu_read_lock(); - sta = rtl_find_sta(hw, mac->bssid); - if (sta) - rtlpriv->cfg->ops->update_rate_tbl(hw, sta, - p_ra->ratr_state); - rcu_read_unlock(); - - p_ra->pre_ratr_state = p_ra->ratr_state; - } - } -} - -static bool rtl8723be_dm_is_edca_turbo_disable(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->mac80211.mode == WIRELESS_MODE_B) - return true; - - return false; -} - -static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - static u64 last_txok_cnt; - static u64 last_rxok_cnt; - u64 cur_txok_cnt = 0; - u64 cur_rxok_cnt = 0; - u32 edca_be_ul = 0x6ea42b; - u32 edca_be_dl = 0x6ea42b;/*not sure*/ - u32 edca_be = 0x5ea42b; - u32 iot_peer = 0; - bool b_is_cur_rdlstate; - bool b_last_is_cur_rdlstate = false; - bool b_bias_on_rx = false; - bool b_edca_turbo_on = false; - - b_last_is_cur_rdlstate = rtlpriv->dm.is_cur_rdlstate; - - cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; - cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; - - iot_peer = rtlpriv->mac80211.vendor; - b_bias_on_rx = (iot_peer == PEER_RAL || iot_peer == PEER_ATH) ? - true : false; - b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) && - (!rtlpriv->dm.disable_framebursting)) ? - true : false; - - if ((iot_peer == PEER_CISCO) && - (mac->mode == WIRELESS_MODE_N_24G)) { - edca_be_dl = edca_setting_dl[iot_peer]; - edca_be_ul = edca_setting_ul[iot_peer]; - } - if (rtl8723be_dm_is_edca_turbo_disable(hw)) - goto exit; - - if (b_edca_turbo_on) { - if (b_bias_on_rx) - b_is_cur_rdlstate = (cur_txok_cnt > cur_rxok_cnt * 4) ? - false : true; - else - b_is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ? - true : false; - - edca_be = (b_is_cur_rdlstate) ? edca_be_dl : edca_be_ul; - rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, edca_be); - rtlpriv->dm.is_cur_rdlstate = b_is_cur_rdlstate; - rtlpriv->dm.current_turbo_edca = true; - } else { - if (rtlpriv->dm.current_turbo_edca) { - u8 tmp = AC0_BE; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, - (u8 *)(&tmp)); - } - rtlpriv->dm.current_turbo_edca = false; - } - -exit: - rtlpriv->dm.is_any_nonbepkts = false; - last_txok_cnt = rtlpriv->stats.txbytesunicast; - last_rxok_cnt = rtlpriv->stats.rxbytesunicast; -} - -static void rtl8723be_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - u8 cur_cck_cca_thresh; - - if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) { - if (dm_digtable->rssi_val_min > 25) { - cur_cck_cca_thresh = 0xcd; - } else if ((dm_digtable->rssi_val_min <= 25) && - (dm_digtable->rssi_val_min > 10)) { - cur_cck_cca_thresh = 0x83; - } else { - if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) - cur_cck_cca_thresh = 0x83; - else - cur_cck_cca_thresh = 0x40; - } - } else { - if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) - cur_cck_cca_thresh = 0x83; - else - cur_cck_cca_thresh = 0x40; - } - - if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh) - rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh); - - dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres; - dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh; - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres); -} - -static void rtl8723be_dm_dynamic_edcca(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 reg_c50, reg_c58; - bool fw_current_in_ps_mode = false; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_in_ps_mode)); - if (fw_current_in_ps_mode) - return; - - reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); - reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); - - if (reg_c50 > 0x28 && reg_c58 > 0x28) { - if (!rtlpriv->rtlhal.pre_edcca_enable) { - rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03); - rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00); - } - } else if (reg_c50 < 0x25 && reg_c58 < 0x25) { - if (rtlpriv->rtlhal.pre_edcca_enable) { - rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f); - rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f); - } - } -} - -static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - u8 crystal_cap; - u32 packet_count; - int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0; - int cfo_ave_diff; - - if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { - if (rtldm->atc_status == ATC_STATUS_OFF) { - rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), - ATC_STATUS_ON); - rtldm->atc_status = ATC_STATUS_ON; - } - if (rtlpriv->cfg->ops->get_btc_status()) { - if (!rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(rtlpriv)) { - RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, - "odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n"); - return; - } - } - - if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) { - rtldm->crystal_cap = rtlpriv->efuse.crystalcap; - crystal_cap = rtldm->crystal_cap & 0x3f; - rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, - (crystal_cap | (crystal_cap << 6))); - } - } else { - cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280; - cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280; - packet_count = rtldm->packet_count; - - if (packet_count == rtldm->packet_count_pre) - return; - - rtldm->packet_count_pre = packet_count; - - if (rtlpriv->phy.rf_type == RF_1T1R) - cfo_ave = cfo_khz_a; - else - cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1; - - cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ? - (rtldm->cfo_ave_pre - cfo_ave) : - (cfo_ave - rtldm->cfo_ave_pre); - - if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) { - rtldm->large_cfo_hit = 1; - return; - } else - rtldm->large_cfo_hit = 0; - - rtldm->cfo_ave_pre = cfo_ave; - - if (cfo_ave >= -rtldm->cfo_threshold && - cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) { - if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) { - rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10; - rtldm->is_freeze = 1; - } else { - rtldm->cfo_threshold = CFO_THRESHOLD_XTAL; - } - } - - if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f) - adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 1) + 1; - else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) && - rtlpriv->dm.crystal_cap > 0) - adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 1) - 1; - - if (adjust_xtal != 0) { - rtldm->is_freeze = 0; - rtldm->crystal_cap += adjust_xtal; - - if (rtldm->crystal_cap > 0x3f) - rtldm->crystal_cap = 0x3f; - else if (rtldm->crystal_cap < 0) - rtldm->crystal_cap = 0; - - crystal_cap = rtldm->crystal_cap & 0x3f; - rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, - (crystal_cap | (crystal_cap << 6))); - } - - if (cfo_ave < CFO_THRESHOLD_ATC && - cfo_ave > -CFO_THRESHOLD_ATC) { - if (rtldm->atc_status == ATC_STATUS_ON) { - rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), - ATC_STATUS_OFF); - rtldm->atc_status = ATC_STATUS_OFF; - } - } else { - if (rtldm->atc_status == ATC_STATUS_OFF) { - rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), - ATC_STATUS_ON); - rtldm->atc_status = ATC_STATUS_ON; - } - } - } -} - -static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 cnt = 0; - struct rtl_sta_info *drv_priv; - - rtlpriv->dm.one_entry_only = false; - - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION && - rtlpriv->mac80211.link_state >= MAC80211_LINKED) { - rtlpriv->dm.one_entry_only = true; - return; - } - - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || - rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC || - rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) { - spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { - cnt++; - } - spin_unlock_bh(&rtlpriv->locks.entry_list_lock); - - if (cnt == 1) - rtlpriv->dm.one_entry_only = true; - } -} - -void rtl8723be_dm_watchdog(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool fw_current_inpsmode = false; - bool fw_ps_awake = true; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inpsmode)); - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, - (u8 *)(&fw_ps_awake)); - - if (ppsc->p2p_ps_info.p2p_ps_mode) - fw_ps_awake = false; - - if ((ppsc->rfpwr_state == ERFON) && - ((!fw_current_inpsmode) && fw_ps_awake) && - (!ppsc->rfchange_inprogress)) { - rtl8723be_dm_common_info_self_update(hw); - rtl8723be_dm_false_alarm_counter_statistics(hw); - rtl8723be_dm_check_rssi_monitor(hw); - rtl8723be_dm_dig(hw); - rtl8723be_dm_dynamic_edcca(hw); - rtl8723be_dm_cck_packet_detection_thresh(hw); - rtl8723be_dm_refresh_rate_adaptive_mask(hw); - rtl8723be_dm_check_edca_turbo(hw); - rtl8723be_dm_dynamic_atc_switch(hw); - rtl8723be_dm_check_txpower_tracking(hw); - rtl8723be_dm_dynamic_txpower(hw); - } - rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/dm.h b/drivers/net/wireless/rtlwifi/rtl8723be/dm.h deleted file mode 100644 index f752a2cad63d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/dm.h +++ /dev/null @@ -1,267 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723BE_DM_H__ -#define __RTL8723BE_DM_H__ - -#define MAIN_ANT 0 -#define AUX_ANT 1 -#define MAIN_ANT_CG_TRX 1 -#define AUX_ANT_CG_TRX 0 -#define MAIN_ANT_CGCS_RX 0 -#define AUX_ANT_CGCS_RX 1 - -#define TXSCALE_TABLE_SIZE 30 - -/*RF REG LIST*/ -#define DM_REG_RF_MODE_11N 0x00 -#define DM_REG_RF_0B_11N 0x0B -#define DM_REG_CHNBW_11N 0x18 -#define DM_REG_T_METER_11N 0x24 -#define DM_REG_RF_25_11N 0x25 -#define DM_REG_RF_26_11N 0x26 -#define DM_REG_RF_27_11N 0x27 -#define DM_REG_RF_2B_11N 0x2B -#define DM_REG_RF_2C_11N 0x2C -#define DM_REG_RXRF_A3_11N 0x3C -#define DM_REG_T_METER_92D_11N 0x42 -#define DM_REG_T_METER_88E_11N 0x42 - -/*BB REG LIST*/ -/*PAGE 8 */ -#define DM_REG_BB_CTRL_11N 0x800 -#define DM_REG_RF_PIN_11N 0x804 -#define DM_REG_PSD_CTRL_11N 0x808 -#define DM_REG_TX_ANT_CTRL_11N 0x80C -#define DM_REG_BB_PWR_SAV5_11N 0x818 -#define DM_REG_CCK_RPT_FORMAT_11N 0x824 -#define DM_REG_RX_DEFUALT_A_11N 0x858 -#define DM_REG_RX_DEFUALT_B_11N 0x85A -#define DM_REG_BB_PWR_SAV3_11N 0x85C -#define DM_REG_ANTSEL_CTRL_11N 0x860 -#define DM_REG_RX_ANT_CTRL_11N 0x864 -#define DM_REG_PIN_CTRL_11N 0x870 -#define DM_REG_BB_PWR_SAV1_11N 0x874 -#define DM_REG_ANTSEL_PATH_11N 0x878 -#define DM_REG_BB_3WIRE_11N 0x88C -#define DM_REG_SC_CNT_11N 0x8C4 -#define DM_REG_PSD_DATA_11N 0x8B4 -/*PAGE 9*/ -#define DM_REG_ANT_MAPPING1_11N 0x914 -#define DM_REG_ANT_MAPPING2_11N 0x918 -/*PAGE A*/ -#define DM_REG_CCK_ANTDIV_PARA1_11N 0xA00 -#define DM_REG_CCK_CCA_11N 0xA0A -#define DM_REG_CCK_ANTDIV_PARA2_11N 0xA0C -#define DM_REG_CCK_ANTDIV_PARA3_11N 0xA10 -#define DM_REG_CCK_ANTDIV_PARA4_11N 0xA14 -#define DM_REG_CCK_FILTER_PARA1_11N 0xA22 -#define DM_REG_CCK_FILTER_PARA2_11N 0xA23 -#define DM_REG_CCK_FILTER_PARA3_11N 0xA24 -#define DM_REG_CCK_FILTER_PARA4_11N 0xA25 -#define DM_REG_CCK_FILTER_PARA5_11N 0xA26 -#define DM_REG_CCK_FILTER_PARA6_11N 0xA27 -#define DM_REG_CCK_FILTER_PARA7_11N 0xA28 -#define DM_REG_CCK_FILTER_PARA8_11N 0xA29 -#define DM_REG_CCK_FA_RST_11N 0xA2C -#define DM_REG_CCK_FA_MSB_11N 0xA58 -#define DM_REG_CCK_FA_LSB_11N 0xA5C -#define DM_REG_CCK_CCA_CNT_11N 0xA60 -#define DM_REG_BB_PWR_SAV4_11N 0xA74 -/*PAGE B */ -#define DM_REG_LNA_SWITCH_11N 0xB2C -#define DM_REG_PATH_SWITCH_11N 0xB30 -#define DM_REG_RSSI_CTRL_11N 0xB38 -#define DM_REG_CONFIG_ANTA_11N 0xB68 -#define DM_REG_RSSI_BT_11N 0xB9C -/*PAGE C */ -#define DM_REG_OFDM_FA_HOLDC_11N 0xC00 -#define DM_REG_RX_PATH_11N 0xC04 -#define DM_REG_TRMUX_11N 0xC08 -#define DM_REG_OFDM_FA_RSTC_11N 0xC0C -#define DM_REG_RXIQI_MATRIX_11N 0xC14 -#define DM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C -#define DM_REG_IGI_A_11N 0xC50 -#define DM_REG_ANTDIV_PARA2_11N 0xC54 -#define DM_REG_IGI_B_11N 0xC58 -#define DM_REG_ANTDIV_PARA3_11N 0xC5C -#define DM_REG_BB_PWR_SAV2_11N 0xC70 -#define DM_REG_RX_OFF_11N 0xC7C -#define DM_REG_TXIQK_MATRIXA_11N 0xC80 -#define DM_REG_TXIQK_MATRIXB_11N 0xC88 -#define DM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 -#define DM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C -#define DM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 -#define DM_REG_ANTDIV_PARA1_11N 0xCA4 -#define DM_REG_OFDM_FA_TYPE1_11N 0xCF0 -/*PAGE D */ -#define DM_REG_OFDM_FA_RSTD_11N 0xD00 -#define DM_REG_OFDM_FA_TYPE2_11N 0xDA0 -#define DM_REG_OFDM_FA_TYPE3_11N 0xDA4 -#define DM_REG_OFDM_FA_TYPE4_11N 0xDA8 -/*PAGE E */ -#define DM_REG_TXAGC_A_6_18_11N 0xE00 -#define DM_REG_TXAGC_A_24_54_11N 0xE04 -#define DM_REG_TXAGC_A_1_MCS32_11N 0xE08 -#define DM_REG_TXAGC_A_MCS0_3_11N 0xE10 -#define DM_REG_TXAGC_A_MCS4_7_11N 0xE14 -#define DM_REG_TXAGC_A_MCS8_11_11N 0xE18 -#define DM_REG_TXAGC_A_MCS12_15_11N 0xE1C -#define DM_REG_FPGA0_IQK_11N 0xE28 -#define DM_REG_TXIQK_TONE_A_11N 0xE30 -#define DM_REG_RXIQK_TONE_A_11N 0xE34 -#define DM_REG_TXIQK_PI_A_11N 0xE38 -#define DM_REG_RXIQK_PI_A_11N 0xE3C -#define DM_REG_TXIQK_11N 0xE40 -#define DM_REG_RXIQK_11N 0xE44 -#define DM_REG_IQK_AGC_PTS_11N 0xE48 -#define DM_REG_IQK_AGC_RSP_11N 0xE4C -#define DM_REG_BLUETOOTH_11N 0xE6C -#define DM_REG_RX_WAIT_CCA_11N 0xE70 -#define DM_REG_TX_CCK_RFON_11N 0xE74 -#define DM_REG_TX_CCK_BBON_11N 0xE78 -#define DM_REG_OFDM_RFON_11N 0xE7C -#define DM_REG_OFDM_BBON_11N 0xE80 -#define DM_REG_TX2RX_11N 0xE84 -#define DM_REG_TX2TX_11N 0xE88 -#define DM_REG_RX_CCK_11N 0xE8C -#define DM_REG_RX_OFDM_11N 0xED0 -#define DM_REG_RX_WAIT_RIFS_11N 0xED4 -#define DM_REG_RX2RX_11N 0xED8 -#define DM_REG_STANDBY_11N 0xEDC -#define DM_REG_SLEEP_11N 0xEE0 -#define DM_REG_PMPD_ANAEN_11N 0xEEC - -/*MAC REG LIST*/ -#define DM_REG_BB_RST_11N 0x02 -#define DM_REG_ANTSEL_PIN_11N 0x4C -#define DM_REG_EARLY_MODE_11N 0x4D0 -#define DM_REG_RSSI_MONITOR_11N 0x4FE -#define DM_REG_EDCA_VO_11N 0x500 -#define DM_REG_EDCA_VI_11N 0x504 -#define DM_REG_EDCA_BE_11N 0x508 -#define DM_REG_EDCA_BK_11N 0x50C -#define DM_REG_TXPAUSE_11N 0x522 -#define DM_REG_RESP_TX_11N 0x6D8 -#define DM_REG_ANT_TRAIN_PARA1_11N 0x7b0 -#define DM_REG_ANT_TRAIN_PARA2_11N 0x7b4 - -/*DIG Related*/ -#define DM_BIT_IGI_11N 0x0000007F - -#define HAL_DM_DIG_DISABLE BIT(0) -#define HAL_DM_HIPWR_DISABLE BIT(1) - -#define OFDM_TABLE_LENGTH 43 -#define CCK_TABLE_LENGTH 33 - -#define OFDM_TABLE_SIZE 37 -#define CCK_TABLE_SIZE 33 - -#define BW_AUTO_SWITCH_HIGH_LOW 25 -#define BW_AUTO_SWITCH_LOW_HIGH 30 - -#define DM_DIG_FA_UPPER 0x3e -#define DM_DIG_FA_LOWER 0x1e -#define DM_DIG_FA_TH0 0x200 -#define DM_DIG_FA_TH1 0x300 -#define DM_DIG_FA_TH2 0x400 - -#define RXPATHSELECTION_SS_TH_LOW 30 -#define RXPATHSELECTION_DIFF_TH 18 - -#define DM_RATR_STA_INIT 0 -#define DM_RATR_STA_HIGH 1 -#define DM_RATR_STA_MIDDLE 2 -#define DM_RATR_STA_LOW 3 - -#define CTS2SELF_THVAL 30 -#define REGC38_TH 20 - -#define WAIOTTHVAL 25 - -#define TXHIGHPWRLEVEL_NORMAL 0 -#define TXHIGHPWRLEVEL_LEVEL1 1 -#define TXHIGHPWRLEVEL_LEVEL2 2 -#define TXHIGHPWRLEVEL_BT1 3 -#define TXHIGHPWRLEVEL_BT2 4 - -#define DM_TYPE_BYFW 0 -#define DM_TYPE_BYDRIVER 1 - -#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 -#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 -#define TXPWRTRACK_MAX_IDX 6 - -/* Dynamic ATC switch */ -#define ATC_STATUS_OFF 0x0 /* enable */ -#define ATC_STATUS_ON 0x1 /* disable */ -#define CFO_THRESHOLD_XTAL 10 /* kHz */ -#define CFO_THRESHOLD_ATC 80 /* kHz */ - -enum dm_1r_cca_e { - CCA_1R = 0, - CCA_2R = 1, - CCA_MAX = 2, -}; - -enum dm_rf_e { - RF_SAVE = 0, - RF_NORMAL = 1, - RF_MAX = 2, -}; - -enum dm_sw_ant_switch_e { - ANS_ANTENNA_B = 1, - ANS_ANTENNA_A = 2, - ANS_ANTENNA_MAX = 3, -}; - -enum pwr_track_control_method { - BBSWING, - TXAGC -}; - -#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1) -#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1) -#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1) -#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1) -#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1) -#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ - ((((struct rtl_priv *)(_priv))->mac80211.opmode == \ - NL80211_IFTYPE_ADHOC) ? \ - (((struct rtl_priv *)(_priv))->dm.entry_min_undecoratedsmoothed_pwdb) :\ - (((struct rtl_priv *)(_priv))->dm.undecorated_smoothed_pwdb)) - -void rtl8723be_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, u8 *pdesc, - u32 mac_id); -void rtl8723be_dm_ant_sel_statistics(struct ieee80211_hw *hw, u8 antsel_tr_mux, - u32 mac_id, u32 rx_pwdb_all); -void rtl8723be_dm_fast_antenna_training_callback(unsigned long data); -void rtl8723be_dm_init(struct ieee80211_hw *hw); -void rtl8723be_dm_watchdog(struct ieee80211_hw *hw); -void rtl8723be_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi); -void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw); -void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); -void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw *hw, u8 type, - u8 *pdirection, u32 *poutwrite_val); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/fw.c b/drivers/net/wireless/rtlwifi/rtl8723be/fw.c deleted file mode 100644 index d5da0f3c1217..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/fw.c +++ /dev/null @@ -1,640 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "fw.h" -#include "../rtl8723com/fw_common.h" - -static bool _rtl8723be_check_fw_read_last_h2c(struct ieee80211_hw *hw, - u8 boxnum) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 val_hmetfr; - bool result = false; - - val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); - if (((val_hmetfr >> boxnum) & BIT(0)) == 0) - result = true; - return result; -} - -static void _rtl8723be_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *p_cmdbuffer) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 boxnum; - u16 box_reg = 0, box_extreg = 0; - u8 u1b_tmp; - bool isfw_read = false; - u8 buf_index = 0; - bool bwrite_sucess = false; - u8 wait_h2c_limmit = 100; - u8 wait_writeh2c_limmit = 100; - u8 boxcontent[4], boxextcontent[4]; - u32 h2c_waitcounter = 0; - unsigned long flag; - u8 idx; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); - - while (true) { - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - if (rtlhal->h2c_setinprogress) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C set in progress! Wait to set..element_id(%d).\n", - element_id); - - while (rtlhal->h2c_setinprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, - flag); - h2c_waitcounter++; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Wait 100 us (%d times)...\n", - h2c_waitcounter); - udelay(100); - - if (h2c_waitcounter > 1000) - return; - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, - flag); - } - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - } else { - rtlhal->h2c_setinprogress = true; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - break; - } - } - - while (!bwrite_sucess) { - wait_writeh2c_limmit--; - if (wait_writeh2c_limmit == 0) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Write H2C fail because no trigger for FW INT!\n"); - break; - } - - boxnum = rtlhal->last_hmeboxnum; - switch (boxnum) { - case 0: - box_reg = REG_HMEBOX_0; - box_extreg = REG_HMEBOX_EXT_0; - break; - case 1: - box_reg = REG_HMEBOX_1; - box_extreg = REG_HMEBOX_EXT_1; - break; - case 2: - box_reg = REG_HMEBOX_2; - box_extreg = REG_HMEBOX_EXT_2; - break; - case 3: - box_reg = REG_HMEBOX_3; - box_extreg = REG_HMEBOX_EXT_3; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - - isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, boxnum); - while (!isfw_read) { - wait_h2c_limmit--; - if (wait_h2c_limmit == 0) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Waiting too long for FW read clear HMEBox(%d)!\n", - boxnum); - break; - } - - udelay(10); - - isfw_read = _rtl8723be_check_fw_read_last_h2c(hw, - boxnum); - u1b_tmp = rtl_read_byte(rtlpriv, 0x130); - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", - boxnum, u1b_tmp); - } - - if (!isfw_read) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", - boxnum); - break; - } - - memset(boxcontent, 0, sizeof(boxcontent)); - memset(boxextcontent, 0, sizeof(boxextcontent)); - boxcontent[0] = element_id; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Write element_id box_reg(%4x) = %2x\n", - box_reg, element_id); - - switch (cmd_len) { - case 1: - case 2: - case 3: - /*boxcontent[0] &= ~(BIT(7));*/ - memcpy((u8 *)(boxcontent) + 1, - p_cmdbuffer + buf_index, cmd_len); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - case 4: - case 5: - case 6: - case 7: - /*boxcontent[0] |= (BIT(7));*/ - memcpy((u8 *)(boxextcontent), - p_cmdbuffer + buf_index+3, cmd_len-3); - memcpy((u8 *)(boxcontent) + 1, - p_cmdbuffer + buf_index, 3); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_extreg + idx, - boxextcontent[idx]); - } - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - - bwrite_sucess = true; - - rtlhal->last_hmeboxnum = boxnum + 1; - if (rtlhal->last_hmeboxnum == 4) - rtlhal->last_hmeboxnum = 0; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "pHalData->last_hmeboxnum = %d\n", - rtlhal->last_hmeboxnum); - } - - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - rtlhal->h2c_setinprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); -} - -void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *p_cmdbuffer) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 tmp_cmdbuf[2]; - - if (!rtlhal->fw_ready) { - RT_ASSERT(false, - "return H2C cmd because of Fw download fail!!!\n"); - return; - } - - memset(tmp_cmdbuf, 0, 8); - memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len); - _rtl8723be_fill_h2c_command(hw, element_id, cmd_len, - (u8 *)&tmp_cmdbuf); - return; -} - -void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 }; - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 rlbm, power_state = 0; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); - - SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); - rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/ - SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); - SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, - (rtlpriv->mac80211.p2p) ? - ppsc->smart_ps : 1); - SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, - ppsc->reg_max_lps_awakeintvl); - SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); - if (mode == FW_PS_ACTIVE_MODE) - power_state |= FW_PWR_STATE_ACTIVE; - else - power_state |= FW_PWR_STATE_RF_OFF; - SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", - u1_h2c_set_pwrmode, H2C_PWEMODE_LENGTH); - rtl8723be_fill_h2c_cmd(hw, H2C_8723B_SETPWRMODE, H2C_PWEMODE_LENGTH, - u1_h2c_set_pwrmode); -} - -void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus) -{ - u8 parm[3] = { 0, 0, 0 }; - /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect - * bit1=0-->update Media Status to MACID - * bit1=1-->update Media Status from MACID to MACID_End - * parm[1]: MACID, if this is INFRA_STA, MacID = 0 - * parm[2]: MACID_End - */ - SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); - SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); - - rtl8723be_fill_h2c_cmd(hw, H2C_8723B_MSRRPT, 3, parm); -} - -#define BEACON_PG 0 /* ->1 */ -#define PSPOLL_PG 2 -#define NULL_PG 3 -#define PROBERSP_PG 4 /* ->5 */ - -#define TOTAL_RESERVED_PKT_LEN 768 - -static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { - /* page 0 beacon */ - 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, - 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65, - 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B, - 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06, - 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, - 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, - 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, - 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, - 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, - 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00, - - /* page 1 beacon */ - 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 2 ps-poll */ - 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B, - 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 3 null */ - 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B, - 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78, - 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 4 probe_resp */ - 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, - 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, - 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, - 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, - 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, - 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, - 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, - 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, - 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, - 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, - 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - /* page 5 probe_resp */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, - bool b_dl_finished) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct sk_buff *skb = NULL; - - u32 totalpacketlen; - bool rtstatus; - u8 u1rsvdpageloc[5] = { 0 }; - bool b_dlok = false; - - u8 *beacon; - u8 *p_pspoll; - u8 *nullfunc; - u8 *p_probersp; - /*--------------------------------------------------------- - * (1) beacon - *--------------------------------------------------------- - */ - beacon = &reserved_page_packet[BEACON_PG * 128]; - SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); - SET_80211_HDR_ADDRESS3(beacon, mac->bssid); - - /*------------------------------------------------------- - * (2) ps-poll - *------------------------------------------------------- - */ - p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; - SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); - SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); - SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); - - SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG); - - /*-------------------------------------------------------- - * (3) null data - *-------------------------------------------------------- - */ - nullfunc = &reserved_page_packet[NULL_PG * 128]; - SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); - SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); - SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG); - - /*--------------------------------------------------------- - * (4) probe response - *--------------------------------------------------------- - */ - p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; - SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); - SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); - SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG); - - totalpacketlen = TOTAL_RESERVED_PKT_LEN; - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", - &reserved_page_packet[0], totalpacketlen); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "rtl8723be_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", - u1rsvdpageloc, 3); - - skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet, totalpacketlen); - - rtstatus = rtl_cmd_send_packet(hw, skb); - - if (rtstatus) - b_dlok = true; - - if (b_dlok) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Set RSVD page location to Fw.\n"); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, "H2C_RSVDPAGE:\n", - u1rsvdpageloc, 3); - rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RSVDPAGE, - sizeof(u1rsvdpageloc), u1rsvdpageloc); - } else - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set RSVD page location to Fw FAIL!!!!!!.\n"); -} - -/*Should check FW support p2p or not.*/ -static void rtl8723be_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, - u8 ctwindow) -{ - u8 u1_ctwindow_period[1] = { ctwindow}; - - rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_CTW_CMD, 1, - u1_ctwindow_period); -} - -void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, - u8 p2p_ps_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info); - struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; - u8 i; - u16 ctwindow; - u32 start_time, tsf_low; - - switch (p2p_ps_state) { - case P2P_PS_DISABLE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); - memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); - break; - case P2P_PS_ENABLE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); - /* update CTWindow value. */ - if (p2pinfo->ctwindow > 0) { - p2p_ps_offload->ctwindow_en = 1; - ctwindow = p2pinfo->ctwindow; - rtl8723be_set_p2p_ctw_period_cmd(hw, ctwindow); - } - /* hw only support 2 set of NoA */ - for (i = 0 ; i < p2pinfo->noa_num ; i++) { - /* To control the register setting - * for which NOA - */ - rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); - if (i == 0) - p2p_ps_offload->noa0_en = 1; - else - p2p_ps_offload->noa1_en = 1; - - /* config P2P NoA Descriptor Register */ - rtl_write_dword(rtlpriv, 0x5E0, - p2pinfo->noa_duration[i]); - rtl_write_dword(rtlpriv, 0x5E4, - p2pinfo->noa_interval[i]); - - /*Get Current TSF value */ - tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - - start_time = p2pinfo->noa_start_time[i]; - if (p2pinfo->noa_count_type[i] != 1) { - while (start_time <= (tsf_low + (50 * 1024))) { - start_time += p2pinfo->noa_interval[i]; - if (p2pinfo->noa_count_type[i] != 255) - p2pinfo->noa_count_type[i]--; - } - } - rtl_write_dword(rtlpriv, 0x5E8, start_time); - rtl_write_dword(rtlpriv, 0x5EC, - p2pinfo->noa_count_type[i]); - } - - if ((p2pinfo->opp_ps == 1) || - (p2pinfo->noa_num > 0)) { - /* rst p2p circuit */ - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); - - p2p_ps_offload->offload_en = 1; - - if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { - p2p_ps_offload->role = 1; - p2p_ps_offload->allstasleep = 0; - } else { - p2p_ps_offload->role = 0; - } - p2p_ps_offload->discovery = 0; - } - break; - case P2P_PS_SCAN: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); - p2p_ps_offload->discovery = 1; - break; - case P2P_PS_SCAN_DONE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); - p2p_ps_offload->discovery = 0; - p2pinfo->p2p_ps_state = P2P_PS_ENABLE; - break; - default: - break; - } - - rtl8723be_fill_h2c_cmd(hw, H2C_8723B_P2P_PS_OFFLOAD, 1, - (u8 *)p2p_ps_offload); -} - -static void _rtl8723be_c2h_content_parsing(struct ieee80211_hw *hw, - u8 c2h_cmd_id, - u8 c2h_cmd_len, u8 *tmp_buf) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - switch (c2h_cmd_id) { - case C2H_8723B_DBG: - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H], C2H_8723BE_DBG!!\n"); - break; - case C2H_8723B_TX_REPORT: - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H], C2H_8723BE_TX_REPORT!\n"); - break; - case C2H_8723B_BT_INFO: - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H], C2H_8723BE_BT_INFO!!\n"); - rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf, - c2h_cmd_len); - break; - case C2H_8723B_BT_MP: - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H], C2H_8723BE_BT_MP!!\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id); - break; - } -} - -void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0; - u8 *tmp_buf = NULL; - - c2h_cmd_id = buffer[0]; - c2h_cmd_seq = buffer[1]; - c2h_cmd_len = len - 2; - tmp_buf = buffer + 2; - - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n", - c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len); - - RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE, - "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len); - - _rtl8723be_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/fw.h b/drivers/net/wireless/rtlwifi/rtl8723be/fw.h deleted file mode 100644 index 067429669bda..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/fw.h +++ /dev/null @@ -1,152 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723BE__FW__H__ -#define __RTL8723BE__FW__H__ - -#define FW_8192C_SIZE 0x8000 -#define FW_8192C_START_ADDRESS 0x1000 -#define FW_8192C_END_ADDRESS 0x5FFF -#define FW_8192C_PAGE_SIZE 4096 -#define FW_8192C_POLLING_DELAY 5 - -#define USE_OLD_WOWLAN_DEBUG_FW 0 - -#define H2C_PWEMODE_LENGTH 5 - -/* Fw PS state for RPWM. -*BIT[2:0] = HW state -*BIT[3] = Protocol PS state, 1: register active state , 0: register sleep state -*BIT[4] = sub-state -*/ -#define FW_PS_RF_ON BIT(2) -#define FW_PS_REGISTER_ACTIVE BIT(3) - -#define FW_PS_ACK BIT(6) -#define FW_PS_TOGGLE BIT(7) - - /* 8723BE RPWM value*/ - /* BIT[0] = 1: 32k, 0: 40M*/ -#define FW_PS_CLOCK_OFF BIT(0) /* 32k*/ -#define FW_PS_CLOCK_ON 0 /*40M*/ - -#define FW_PS_STATE_MASK (0x0F) -#define FW_PS_STATE_HW_MASK (0x07) -/*ISR_ENABLE, IMR_ENABLE, and PS mode should be inherited.*/ -#define FW_PS_STATE_INT_MASK (0x3F) - -#define FW_PS_STATE(x) (FW_PS_STATE_MASK & (x)) - -/* ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE))*/ -#define FW_PS_STATE_ALL_ON (FW_PS_CLOCK_ON) -/* (FW_PS_RF_ON)*/ -#define FW_PS_STATE_RF_ON (FW_PS_CLOCK_ON) -/* 0x0*/ -#define FW_PS_STATE_RF_OFF (FW_PS_CLOCK_ON) -/* (FW_PS_STATE_RF_OFF)*/ -#define FW_PS_STATE_RF_OFF_LOW_PWR (FW_PS_CLOCK_OFF) - - -/* For 8723BE H2C PwrMode Cmd ID 5.*/ -#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) -#define FW_PWR_STATE_RF_OFF 0 - -#define FW_PS_IS_ACK(x) ((x) & FW_PS_ACK) - -#define IS_IN_LOW_POWER_STATE(__fwpsstate) \ - (FW_PS_STATE(__fwpsstate) == FW_PS_CLOCK_OFF) - -#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) -#define FW_PWR_STATE_RF_OFF 0 - -enum rtl8723b_h2c_cmd { - H2C_8723B_RSVDPAGE = 0, - H2C_8723B_MSRRPT = 1, - H2C_8723B_SCAN = 2, - H2C_8723B_KEEP_ALIVE_CTRL = 3, - H2C_8723B_DISCONNECT_DECISION = 4, - H2C_8723B_BCN_RSVDPAGE = 9, - H2C_8723B_PROBERSP_RSVDPAGE = 10, - - H2C_8723B_SETPWRMODE = 0x20, - H2C_8723B_PS_LPS_PARA = 0x23, - H2C_8723B_P2P_PS_OFFLOAD = 0x24, - - H2C_8723B_RA_MASK = 0x40, - H2C_RSSIBE_REPORT = 0x42, - /*Not defined CTW CMD for P2P yet*/ - H2C_8723B_P2P_PS_CTW_CMD, - MAX_8723B_H2CCMD -}; - -enum rtl8723b_c2h_evt { - C2H_8723B_DBG = 0, - C2H_8723B_LB = 1, - C2H_8723B_TXBF = 2, - C2H_8723B_TX_REPORT = 3, - C2H_8723B_BT_INFO = 9, - C2H_8723B_BT_MP = 11, - MAX_8723B_C2HEVENT -}; - -#define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) - - -#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_RLBM(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 4, __val) -#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 4, 4, __val) -#define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+3, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+4, 0, 8, __val) -#define GET_88E_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd) \ - LE_BITS_TO_1BYTE(__ph2ccmd, 0, 8) - -#define SET_H2CCMD_MSRRPT_PARM_OPMODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 1, __val) -#define SET_H2CCMD_MSRRPT_PARM_MACID_IND(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 1, 1, __val) - -#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) - - -void rtl8723be_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *p_cmdbuffer); -void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); -void rtl8723be_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus); -void rtl8723be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); -void rtl8723be_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); -void rtl8723be_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/rtlwifi/rtl8723be/hw.c deleted file mode 100644 index c983d2fe147f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c +++ /dev/null @@ -1,2734 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../efuse.h" -#include "../base.h" -#include "../regd.h" -#include "../cam.h" -#include "../ps.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "../rtl8723com/phy_common.h" -#include "dm.h" -#include "../rtl8723com/dm_common.h" -#include "fw.h" -#include "../rtl8723com/fw_common.h" -#include "led.h" -#include "hw.h" -#include "../pwrseqcmd.h" -#include "pwrseq.h" -#include "../btcoexist/rtl_btc.h" - -#define LLT_CONFIG 5 - -static void _rtl8723be_return_beacon_queue_skb(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; - unsigned long flags; - - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - while (skb_queue_len(&ring->queue)) { - struct rtl_tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb = __skb_dequeue(&ring->queue); - - pci_unmap_single(rtlpci->pdev, - rtlpriv->cfg->ops->get_desc( - (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), - skb->len, PCI_DMA_TODEVICE); - kfree_skb(skb); - ring->idx = (ring->idx + 1) % ring->entries; - } - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); -} - -static void _rtl8723be_set_bcn_ctrl_reg(struct ieee80211_hw *hw, - u8 set_bits, u8 clear_bits) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpci->reg_bcn_ctrl_val |= set_bits; - rtlpci->reg_bcn_ctrl_val &= ~clear_bits; - - rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); -} - -static void _rtl8723be_stop_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp1byte; - - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); -} - -static void _rtl8723be_resume_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp1byte; - - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte |= BIT(1); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); -} - -static void _rtl8723be_enable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(1)); -} - -static void _rtl8723be_disable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl8723be_set_bcn_ctrl_reg(hw, BIT(1), 0); -} - -static void _rtl8723be_set_fw_clock_on(struct ieee80211_hw *hw, u8 rpwm_val, - bool b_need_turn_off_ckk) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool b_support_remote_wake_up; - u32 count = 0, isr_regaddr, content; - bool b_schedule_timer = b_need_turn_off_ckk; - rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, - (u8 *)(&b_support_remote_wake_up)); - - if (!rtlhal->fw_ready) - return; - if (!rtlpriv->psc.fw_current_inpsmode) - return; - - while (1) { - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - if (rtlhal->fw_clk_change_in_progress) { - while (rtlhal->fw_clk_change_in_progress) { - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - count++; - udelay(100); - if (count > 1000) - return; - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - } - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - } else { - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - break; - } - } - - if (IS_IN_LOW_POWER_STATE(rtlhal->fw_ps_state)) { - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - if (FW_PS_IS_ACK(rpwm_val)) { - isr_regaddr = REG_HISR; - content = rtl_read_dword(rtlpriv, isr_regaddr); - while (!(content & IMR_CPWM) && (count < 500)) { - udelay(50); - count++; - content = rtl_read_dword(rtlpriv, isr_regaddr); - } - - if (content & IMR_CPWM) { - rtl_write_word(rtlpriv, isr_regaddr, 0x0100); - rtlhal->fw_ps_state = FW_PS_STATE_RF_ON; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Receive CPWM INT!!! Set pHalData->FwPSState = %X\n", - rtlhal->fw_ps_state); - } - } - - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - if (b_schedule_timer) - mod_timer(&rtlpriv->works.fw_clockoff_timer, - jiffies + MSECS(10)); - } else { - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - } -} - -static void _rtl8723be_set_fw_clock_off(struct ieee80211_hw *hw, u8 rpwm_val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring; - enum rf_pwrstate rtstate; - bool b_schedule_timer = false; - u8 queue; - - if (!rtlhal->fw_ready) - return; - if (!rtlpriv->psc.fw_current_inpsmode) - return; - if (!rtlhal->allow_sw_to_change_hwclc) - return; - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate)); - if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF) - return; - - for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) { - ring = &rtlpci->tx_ring[queue]; - if (skb_queue_len(&ring->queue)) { - b_schedule_timer = true; - break; - } - } - - if (b_schedule_timer) { - mod_timer(&rtlpriv->works.fw_clockoff_timer, - jiffies + MSECS(10)); - return; - } - - if (FW_PS_STATE(rtlhal->fw_ps_state) != FW_PS_STATE_RF_OFF_LOW_PWR) { - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - if (!rtlhal->fw_clk_change_in_progress) { - rtlhal->fw_clk_change_in_progress = true; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); - rtl_write_word(rtlpriv, REG_HISR, 0x0100); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - } else { - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - mod_timer(&rtlpriv->works.fw_clockoff_timer, - jiffies + MSECS(10)); - } - } - -} - -static void _rtl8723be_set_fw_ps_rf_on(struct ieee80211_hw *hw) -{ - u8 rpwm_val = 0; - rpwm_val |= (FW_PS_STATE_RF_OFF | FW_PS_ACK); - _rtl8723be_set_fw_clock_on(hw, rpwm_val, true); -} - -static void _rtl8723be_fwlps_leave(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool fw_current_inps = false; - u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE; - - if (ppsc->low_power_enable) { - rpwm_val = (FW_PS_STATE_ALL_ON | FW_PS_ACK);/* RF on */ - _rtl8723be_set_fw_clock_on(hw, rpwm_val, false); - rtlhal->allow_sw_to_change_hwclc = false; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - } else { - rpwm_val = FW_PS_STATE_ALL_ON; /* RF on */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - } - -} - -static void _rtl8723be_fwlps_enter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool fw_current_inps = true; - u8 rpwm_val; - - if (ppsc->low_power_enable) { - rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR; /* RF off */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); - rtlhal->allow_sw_to_change_hwclc = true; - _rtl8723be_set_fw_clock_off(hw, rpwm_val); - } else { - rpwm_val = FW_PS_STATE_RF_OFF; /* RF off */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - } - -} - -void rtl8723be_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - switch (variable) { - case HW_VAR_RCR: - *((u32 *)(val)) = rtlpci->receive_config; - break; - case HW_VAR_RF_STATE: - *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; - break; - case HW_VAR_FWLPS_RF_ON:{ - enum rf_pwrstate rfState; - u32 val_rcr; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, - (u8 *)(&rfState)); - if (rfState == ERFOFF) { - *((bool *)(val)) = true; - } else { - val_rcr = rtl_read_dword(rtlpriv, REG_RCR); - val_rcr &= 0x00070000; - if (val_rcr) - *((bool *)(val)) = false; - else - *((bool *)(val)) = true; - } - } - break; - case HW_VAR_FW_PSMODE_STATUS: - *((bool *)(val)) = ppsc->fw_current_inpsmode; - break; - case HW_VAR_CORRECT_TSF:{ - u64 tsf; - u32 *ptsf_low = (u32 *)&tsf; - u32 *ptsf_high = ((u32 *)&tsf) + 1; - - *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); - *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - - *((u64 *)(val)) = tsf; - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process %x\n", variable); - break; - } -} - -static void _rtl8723be_download_rsvd_page(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp_regcr, tmp_reg422, bcnvalid_reg; - u8 count = 0, dlbcn_count = 0; - bool b_recover = false; - - tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, - (tmp_regcr | BIT(0))); - - _rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(3)); - _rtl8723be_set_bcn_ctrl_reg(hw, BIT(4), 0); - - tmp_reg422 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422 & (~BIT(6))); - if (tmp_reg422 & BIT(6)) - b_recover = true; - - do { - bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); - rtl_write_byte(rtlpriv, REG_TDECTRL + 2, - (bcnvalid_reg | BIT(0))); - _rtl8723be_return_beacon_queue_skb(hw); - - rtl8723be_set_fw_rsvdpagepkt(hw, 0); - bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); - count = 0; - while (!(bcnvalid_reg & BIT(0)) && count < 20) { - count++; - udelay(10); - bcnvalid_reg = rtl_read_byte(rtlpriv, - REG_TDECTRL + 2); - } - dlbcn_count++; - } while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5); - - if (bcnvalid_reg & BIT(0)) - rtl_write_byte(rtlpriv, REG_TDECTRL + 2, BIT(0)); - - _rtl8723be_set_bcn_ctrl_reg(hw, BIT(3), 0); - _rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(4)); - - if (b_recover) - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422); - - tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr & ~(BIT(0)))); -} - -void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 idx; - - switch (variable) { - case HW_VAR_ETHER_ADDR: - for (idx = 0; idx < ETH_ALEN; idx++) - rtl_write_byte(rtlpriv, (REG_MACID + idx), val[idx]); - break; - case HW_VAR_BASIC_RATE:{ - u16 b_rate_cfg = ((u16 *)val)[0]; - u8 rate_index = 0; - b_rate_cfg = b_rate_cfg & 0x15f; - b_rate_cfg |= 0x01; - rtl_write_byte(rtlpriv, REG_RRSR, b_rate_cfg & 0xff); - rtl_write_byte(rtlpriv, REG_RRSR + 1, (b_rate_cfg >> 8) & 0xff); - while (b_rate_cfg > 0x1) { - b_rate_cfg = (b_rate_cfg >> 1); - rate_index++; - } - rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, rate_index); - } - break; - case HW_VAR_BSSID: - for (idx = 0; idx < ETH_ALEN; idx++) - rtl_write_byte(rtlpriv, (REG_BSSID + idx), val[idx]); - - break; - case HW_VAR_SIFS: - rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); - rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); - - rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); - rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); - - if (!mac->ht_enable) - rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, 0x0e0e); - else - rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, - *((u16 *)val)); - break; - case HW_VAR_SLOT_TIME:{ - u8 e_aci; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "HW_VAR_SLOT_TIME %x\n", val[0]); - - rtl_write_byte(rtlpriv, REG_SLOT, val[0]); - - for (e_aci = 0; e_aci < AC_MAX; e_aci++) { - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, - (u8 *)(&e_aci)); - } - } - break; - case HW_VAR_ACK_PREAMBLE:{ - u8 reg_tmp; - u8 short_preamble = (bool)(*(u8 *)val); - reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL + 2); - if (short_preamble) { - reg_tmp |= 0x02; - rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp); - } else { - reg_tmp &= 0xFD; - rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, reg_tmp); - } - } - break; - case HW_VAR_WPA_CONFIG: - rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); - break; - case HW_VAR_AMPDU_MIN_SPACE:{ - u8 min_spacing_to_set; - u8 sec_min_space; - - min_spacing_to_set = *((u8 *)val); - if (min_spacing_to_set <= 7) { - sec_min_space = 0; - - if (min_spacing_to_set < sec_min_space) - min_spacing_to_set = sec_min_space; - - mac->min_space_cfg = ((mac->min_space_cfg & 0xf8) | - min_spacing_to_set); - - *val = min_spacing_to_set; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", - mac->min_space_cfg); - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - } - } - break; - case HW_VAR_SHORTGI_DENSITY:{ - u8 density_to_set; - - density_to_set = *((u8 *)val); - mac->min_space_cfg |= (density_to_set << 3); - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_SHORTGI_DENSITY: %#x\n", - mac->min_space_cfg); - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - } - break; - case HW_VAR_AMPDU_FACTOR:{ - u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9}; - u8 factor_toset; - u8 *p_regtoset = NULL; - u8 index = 0; - - p_regtoset = regtoset_normal; - - factor_toset = *((u8 *)val); - if (factor_toset <= 3) { - factor_toset = (1 << (factor_toset + 2)); - if (factor_toset > 0xf) - factor_toset = 0xf; - - for (index = 0; index < 4; index++) { - if ((p_regtoset[index] & 0xf0) > - (factor_toset << 4)) - p_regtoset[index] = - (p_regtoset[index] & 0x0f) | - (factor_toset << 4); - - if ((p_regtoset[index] & 0x0f) > factor_toset) - p_regtoset[index] = - (p_regtoset[index] & 0xf0) | - (factor_toset); - - rtl_write_byte(rtlpriv, - (REG_AGGLEN_LMT + index), - p_regtoset[index]); - - } - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_FACTOR: %#x\n", - factor_toset); - } - } - break; - case HW_VAR_AC_PARAM:{ - u8 e_aci = *((u8 *)val); - rtl8723_dm_init_edca_turbo(hw); - - if (rtlpci->acm_method != EACMWAY2_SW) - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, - (u8 *)(&e_aci)); - } - break; - case HW_VAR_ACM_CTRL:{ - u8 e_aci = *((u8 *)val); - union aci_aifsn *p_aci_aifsn = - (union aci_aifsn *)(&(mac->ac[0].aifs)); - u8 acm = p_aci_aifsn->f.acm; - u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); - - acm_ctrl = - acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); - - if (acm) { - switch (e_aci) { - case AC0_BE: - acm_ctrl |= ACMHW_BEQEN; - break; - case AC2_VI: - acm_ctrl |= ACMHW_VIQEN; - break; - case AC3_VO: - acm_ctrl |= ACMHW_VOQEN; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", - acm); - break; - } - } else { - switch (e_aci) { - case AC0_BE: - acm_ctrl &= (~ACMHW_BEQEN); - break; - case AC2_VI: - acm_ctrl &= (~ACMHW_VIQEN); - break; - case AC3_VO: - acm_ctrl &= (~ACMHW_VOQEN); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - } - - RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, - "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", - acm_ctrl); - rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); - } - break; - case HW_VAR_RCR: - rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); - rtlpci->receive_config = ((u32 *)(val))[0]; - break; - case HW_VAR_RETRY_LIMIT:{ - u8 retry_limit = ((u8 *)(val))[0]; - - rtl_write_word(rtlpriv, REG_RL, - retry_limit << RETRY_LIMIT_SHORT_SHIFT | - retry_limit << RETRY_LIMIT_LONG_SHIFT); - } - break; - case HW_VAR_DUAL_TSF_RST: - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); - break; - case HW_VAR_EFUSE_BYTES: - rtlefuse->efuse_usedbytes = *((u16 *)val); - break; - case HW_VAR_EFUSE_USAGE: - rtlefuse->efuse_usedpercentage = *((u8 *)val); - break; - case HW_VAR_IO_CMD: - rtl8723be_phy_set_io_cmd(hw, (*(enum io_type *)val)); - break; - case HW_VAR_SET_RPWM:{ - u8 rpwm_val; - - rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); - udelay(1); - - if (rpwm_val & BIT(7)) { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, (*(u8 *)val)); - } else { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, - ((*(u8 *)val) | BIT(7))); - } - } - break; - case HW_VAR_H2C_FW_PWRMODE: - rtl8723be_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); - break; - case HW_VAR_FW_PSMODE_STATUS: - ppsc->fw_current_inpsmode = *((bool *)val); - break; - case HW_VAR_RESUME_CLK_ON: - _rtl8723be_set_fw_ps_rf_on(hw); - break; - case HW_VAR_FW_LPS_ACTION:{ - bool b_enter_fwlps = *((bool *)val); - - if (b_enter_fwlps) - _rtl8723be_fwlps_enter(hw); - else - _rtl8723be_fwlps_leave(hw); - } - break; - case HW_VAR_H2C_FW_JOINBSSRPT:{ - u8 mstatus = (*(u8 *)val); - - if (mstatus == RT_MEDIA_CONNECT) { - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL); - _rtl8723be_download_rsvd_page(hw); - } - rtl8723be_set_fw_media_status_rpt_cmd(hw, mstatus); - } - break; - case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: - rtl8723be_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); - break; - case HW_VAR_AID:{ - u16 u2btmp; - u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); - u2btmp &= 0xC000; - rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, - (u2btmp | mac->assoc_id)); - } - break; - case HW_VAR_CORRECT_TSF:{ - u8 btype_ibss = ((u8 *)(val))[0]; - - if (btype_ibss) - _rtl8723be_stop_tx_beacon(hw); - - _rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(3)); - - rtl_write_dword(rtlpriv, REG_TSFTR, - (u32) (mac->tsf & 0xffffffff)); - rtl_write_dword(rtlpriv, REG_TSFTR + 4, - (u32) ((mac->tsf >> 32) & 0xffffffff)); - - _rtl8723be_set_bcn_ctrl_reg(hw, BIT(3), 0); - - if (btype_ibss) - _rtl8723be_resume_tx_beacon(hw); - } - break; - case HW_VAR_KEEP_ALIVE:{ - u8 array[2]; - array[0] = 0xff; - array[1] = *((u8 *)val); - rtl8723be_fill_h2c_cmd(hw, H2C_8723B_KEEP_ALIVE_CTRL, 2, array); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process %x\n", - variable); - break; - } -} - -static bool _rtl8723be_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool status = true; - long count = 0; - u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | - _LLT_OP(_LLT_WRITE_ACCESS); - - rtl_write_dword(rtlpriv, REG_LLT_INIT, value); - - do { - value = rtl_read_dword(rtlpriv, REG_LLT_INIT); - if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) - break; - - if (count > POLLING_LLT_THRESHOLD) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to polling write LLT done at address %d!\n", - address); - status = false; - break; - } - } while (++count); - - return status; -} - -static bool _rtl8723be_llt_table_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - unsigned short i; - u8 txpktbuf_bndy; - u8 maxPage; - bool status; - - maxPage = 255; - txpktbuf_bndy = 245; - - rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, - (0x27FF0000 | txpktbuf_bndy)); - rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_PBP, 0x31); - rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); - - for (i = 0; i < (txpktbuf_bndy - 1); i++) { - status = _rtl8723be_llt_write(hw, i, i + 1); - if (!status) - return status; - } - - status = _rtl8723be_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); - - if (!status) - return status; - - for (i = txpktbuf_bndy; i < maxPage; i++) { - status = _rtl8723be_llt_write(hw, i, (i + 1)); - if (!status) - return status; - } - - status = _rtl8723be_llt_write(hw, maxPage, txpktbuf_bndy); - if (!status) - return status; - - rtl_write_dword(rtlpriv, REG_RQPN, 0x80e40808); - rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x00); - - return true; -} - -static void _rtl8723be_gen_refresh_led_state(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pled0 = &(pcipriv->ledctl.sw_led0); - - if (rtlpriv->rtlhal.up_first_time) - return; - - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - rtl8723be_sw_led_on(hw, pled0); - else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - rtl8723be_sw_led_on(hw, pled0); - else - rtl8723be_sw_led_off(hw, pled0); -} - -static bool _rtl8723be_init_mac(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - unsigned char bytetmp; - unsigned short wordtmp; - - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); - - /*Auto Power Down to CHIP-off State*/ - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7)); - rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); - - /* HW Power on sequence */ - if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, - PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, - RTL8723_NIC_ENABLE_FLOW)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "init MAC Fail as power on failure\n"); - return false; - } - - bytetmp = rtl_read_byte(rtlpriv, REG_MULTI_FUNC_CTRL); - rtl_write_byte(rtlpriv, REG_MULTI_FUNC_CTRL, bytetmp | BIT(3)); - - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4); - rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp); - - bytetmp = rtl_read_byte(rtlpriv, REG_CR); - bytetmp = 0xff; - rtl_write_byte(rtlpriv, REG_CR, bytetmp); - mdelay(2); - - bytetmp = rtl_read_byte(rtlpriv, REG_HWSEQ_CTRL); - bytetmp |= 0x7f; - rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, bytetmp); - mdelay(2); - - bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CFG + 3); - if (bytetmp & BIT(0)) { - bytetmp = rtl_read_byte(rtlpriv, 0x7c); - rtl_write_byte(rtlpriv, 0x7c, bytetmp | BIT(6)); - } - - bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR); - rtl_write_byte(rtlpriv, REG_SYS_CLKR, bytetmp | BIT(3)); - bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG + 1); - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG + 1, bytetmp & (~BIT(4))); - - rtl_write_word(rtlpriv, REG_CR, 0x2ff); - - if (!rtlhal->mac_func_enable) { - if (_rtl8723be_llt_table_init(hw) == false) - return false; - } - - rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); - rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff); - - /* Enable FW Beamformer Interrupt */ - bytetmp = rtl_read_byte(rtlpriv, REG_FWIMR + 3); - rtl_write_byte(rtlpriv, REG_FWIMR + 3, bytetmp | BIT(6)); - - wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); - wordtmp &= 0xf; - wordtmp |= 0xF5B1; - rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); - - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xFFFF); - rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); - - rtl_write_dword(rtlpriv, REG_BCNQ_DESA, - ((u64) rtlpci->tx_ring[BEACON_QUEUE].dma) & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_MGQ_DESA, - (u64) rtlpci->tx_ring[MGNT_QUEUE].dma & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VOQ_DESA, - (u64) rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VIQ_DESA, - (u64) rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_BEQ_DESA, - (u64) rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_BKQ_DESA, - (u64) rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_HQ_DESA, - (u64) rtlpci->tx_ring[HIGH_QUEUE].dma & - DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_RX_DESA, - (u64) rtlpci->rx_ring[RX_MPDU_QUEUE].dma & - DMA_BIT_MASK(32)); - - bytetmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 3); - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, bytetmp | 0x77); - - rtl_write_dword(rtlpriv, REG_INT_MIG, 0); - - rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); - - rtl_write_byte(rtlpriv, REG_SECONDARY_CCA_CTRL, 0x3); - - /* <20130114, Kordan> The following setting is - * only for DPDT and Fixed board type. - * TODO: A better solution is configure it - * according EFUSE during the run-time. - */ - rtl_set_bbreg(hw, 0x64, BIT(20), 0x0);/* 0x66[4]=0 */ - rtl_set_bbreg(hw, 0x64, BIT(24), 0x0);/* 0x66[8]=0 */ - rtl_set_bbreg(hw, 0x40, BIT(4), 0x0)/* 0x40[4]=0 */; - rtl_set_bbreg(hw, 0x40, BIT(3), 0x1)/* 0x40[3]=1 */; - rtl_set_bbreg(hw, 0x4C, BIT(24) | BIT(23), 0x2)/* 0x4C[24:23]=10 */; - rtl_set_bbreg(hw, 0x944, BIT(1) | BIT(0), 0x3)/* 0x944[1:0]=11 */; - rtl_set_bbreg(hw, 0x930, MASKBYTE0, 0x77)/* 0x930[7:0]=77 */; - rtl_set_bbreg(hw, 0x38, BIT(11), 0x1)/* 0x38[11]=1 */; - - bytetmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, bytetmp & (~BIT(2))); - - _rtl8723be_gen_refresh_led_state(hw); - return true; -} - -static void _rtl8723be_hw_configure(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u32 reg_rrsr; - - reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - /* Init value for RRSR. */ - rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr); - - /* ARFB table 9 for 11ac 5G 2SS */ - rtl_write_dword(rtlpriv, REG_ARFR0 + 4, 0xfffff000); - - /* ARFB table 10 for 11ac 5G 1SS */ - rtl_write_dword(rtlpriv, REG_ARFR1 + 4, 0x003ff000); - - /* CF-End setting. */ - rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F00); - - /* 0x456 = 0x70, sugguested by Zhilin */ - rtl_write_byte(rtlpriv, REG_AMPDU_MAX_TIME, 0x70); - - /* Set retry limit */ - rtl_write_word(rtlpriv, REG_RL, 0x0707); - - /* Set Data / Response auto rate fallack retry count */ - rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); - rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); - - rtlpci->reg_bcn_ctrl_val = 0x1d; - rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); - - /* TBTT prohibit hold time. Suggested by designer TimChen. */ - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); /* 8 ms */ - - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040); - - /*For Rx TP. Suggested by SD1 Richard. Added by tynli. 2010.04.12.*/ - rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); - - rtl_write_byte(rtlpriv, REG_HT_SINGLE_AMPDU, 0x80); - - rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20); - - rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x1F); -} - -static u8 _rtl8723be_dbi_read(struct rtl_priv *rtlpriv, u16 addr) -{ - u16 read_addr = addr & 0xfffc; - u8 ret = 0, tmp = 0, count = 0; - - rtl_write_word(rtlpriv, REG_DBI_ADDR, read_addr); - rtl_write_byte(rtlpriv, REG_DBI_FLAG, 0x2); - tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); - count = 0; - while (tmp && count < 20) { - udelay(10); - tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); - count++; - } - if (0 == tmp) { - read_addr = REG_DBI_RDATA + addr % 4; - ret = rtl_read_byte(rtlpriv, read_addr); - } - - return ret; -} - -static void _rtl8723be_dbi_write(struct rtl_priv *rtlpriv, u16 addr, u8 data) -{ - u8 tmp = 0, count = 0; - u16 write_addr = 0, remainder = addr % 4; - - /* Write DBI 1Byte Data */ - write_addr = REG_DBI_WDATA + remainder; - rtl_write_byte(rtlpriv, write_addr, data); - - /* Write DBI 2Byte Address & Write Enable */ - write_addr = (addr & 0xfffc) | (BIT(0) << (remainder + 12)); - rtl_write_word(rtlpriv, REG_DBI_ADDR, write_addr); - - /* Write DBI Write Flag */ - rtl_write_byte(rtlpriv, REG_DBI_FLAG, 0x1); - - tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); - count = 0; - while (tmp && count < 20) { - udelay(10); - tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); - count++; - } -} - -static u16 _rtl8723be_mdio_read(struct rtl_priv *rtlpriv, u8 addr) -{ - u16 ret = 0; - u8 tmp = 0, count = 0; - - rtl_write_byte(rtlpriv, REG_MDIO_CTL, addr | BIT(6)); - tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(6); - count = 0; - while (tmp && count < 20) { - udelay(10); - tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(6); - count++; - } - - if (0 == tmp) - ret = rtl_read_word(rtlpriv, REG_MDIO_RDATA); - - return ret; -} - -static void _rtl8723be_mdio_write(struct rtl_priv *rtlpriv, u8 addr, u16 data) -{ - u8 tmp = 0, count = 0; - - rtl_write_word(rtlpriv, REG_MDIO_WDATA, data); - rtl_write_byte(rtlpriv, REG_MDIO_CTL, addr | BIT(5)); - tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(5); - count = 0; - while (tmp && count < 20) { - udelay(10); - tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(5); - count++; - } -} - -static void _rtl8723be_enable_aspm_back_door(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp8 = 0; - u16 tmp16 = 0; - - /* Overwrite following ePHY parameter for - * some platform compatibility issue, - * especially when CLKReq is enabled, 2012.11.09. - */ - tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x01); - if (tmp16 != 0x0663) - _rtl8723be_mdio_write(rtlpriv, 0x01, 0x0663); - - tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x04); - if (tmp16 != 0x7544) - _rtl8723be_mdio_write(rtlpriv, 0x04, 0x7544); - - tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x06); - if (tmp16 != 0xB880) - _rtl8723be_mdio_write(rtlpriv, 0x06, 0xB880); - - tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x07); - if (tmp16 != 0x4000) - _rtl8723be_mdio_write(rtlpriv, 0x07, 0x4000); - - tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x08); - if (tmp16 != 0x9003) - _rtl8723be_mdio_write(rtlpriv, 0x08, 0x9003); - - tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x09); - if (tmp16 != 0x0D03) - _rtl8723be_mdio_write(rtlpriv, 0x09, 0x0D03); - - tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x0A); - if (tmp16 != 0x4037) - _rtl8723be_mdio_write(rtlpriv, 0x0A, 0x4037); - - tmp16 = _rtl8723be_mdio_read(rtlpriv, 0x0B); - if (tmp16 != 0x0070) - _rtl8723be_mdio_write(rtlpriv, 0x0B, 0x0070); - - /* Configuration Space offset 0x70f BIT7 is used to control L0S */ - tmp8 = _rtl8723be_dbi_read(rtlpriv, 0x70f); - _rtl8723be_dbi_write(rtlpriv, 0x70f, tmp8 | BIT(7)); - - /* Configuration Space offset 0x719 Bit3 is for L1 - * BIT4 is for clock request - */ - tmp8 = _rtl8723be_dbi_read(rtlpriv, 0x719); - _rtl8723be_dbi_write(rtlpriv, 0x719, tmp8 | BIT(3) | BIT(4)); -} - -void rtl8723be_enable_hw_security_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 sec_reg_value; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", - rtlpriv->sec.pairwise_enc_algorithm, - rtlpriv->sec.group_enc_algorithm); - - if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "not open hw encryption\n"); - return; - } - - sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; - - if (rtlpriv->sec.use_defaultkey) { - sec_reg_value |= SCR_TXUSEDK; - sec_reg_value |= SCR_RXUSEDK; - } - - sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); - - rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "The SECR-value %x\n", sec_reg_value); - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); -} - -static void _rtl8723be_poweroff_adapter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 u1b_tmp; - - rtlhal->mac_func_enable = false; - /* Combo (PCIe + USB) Card and PCIe-MF Card */ - /* 1. Run LPS WL RFOFF flow */ - rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, RTL8723_NIC_LPS_ENTER_FLOW); - - /* 2. 0x1F[7:0] = 0 */ - /* turn off RF */ - /* rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); */ - if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && - rtlhal->fw_ready) { - rtl8723be_firmware_selfreset(hw); - } - - /* Reset MCU. Suggested by Filen. */ - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); - - /* g. MCUFWDL 0x80[1:0]=0 */ - /* reset MCU ready status */ - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); - - /* HW card disable configuration. */ - rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, RTL8723_NIC_DISABLE_FLOW); - - /* Reset MCU IO Wrapper */ - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, u1b_tmp | BIT(0)); - - /* 7. RSV_CTRL 0x1C[7:0] = 0x0E */ - /* lock ISO/CLK/Power control register */ - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); -} - -static bool _rtl8723be_check_pcie_dma_hang(struct rtl_priv *rtlpriv) -{ - u8 tmp; - - /* write reg 0x350 Bit[26]=1. Enable debug port. */ - tmp = rtl_read_byte(rtlpriv, REG_DBI_CTRL + 3); - if (!(tmp & BIT(2))) { - rtl_write_byte(rtlpriv, REG_DBI_CTRL + 3, (tmp | BIT(2))); - mdelay(100); /* Suggested by DD Justin_tsai. */ - } - - /* read reg 0x350 Bit[25] if 1 : RX hang - * read reg 0x350 Bit[24] if 1 : TX hang - */ - tmp = rtl_read_byte(rtlpriv, REG_DBI_CTRL + 3); - if ((tmp & BIT(0)) || (tmp & BIT(1))) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "CheckPcieDMAHang8723BE(): true!!\n"); - return true; - } - return false; -} - -static void _rtl8723be_reset_pcie_interface_dma(struct rtl_priv *rtlpriv, - bool mac_power_on) -{ - u8 tmp; - bool release_mac_rx_pause; - u8 backup_pcie_dma_pause; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "ResetPcieInterfaceDMA8723BE()\n"); - - /* Revise Note: Follow the document "PCIe RX DMA Hang Reset Flow_v03" - * released by SD1 Alan. - * 2013.05.07, by tynli. - */ - - /* 1. disable register write lock - * write 0x1C bit[1:0] = 2'h0 - * write 0xCC bit[2] = 1'b1 - */ - tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL); - tmp &= ~(BIT(1) | BIT(0)); - rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp); - tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); - tmp |= BIT(2); - rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); - - /* 2. Check and pause TRX DMA - * write 0x284 bit[18] = 1'b1 - * write 0x301 = 0xFF - */ - tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - if (tmp & BIT(2)) { - /* Already pause before the function for another purpose. */ - release_mac_rx_pause = false; - } else { - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2))); - release_mac_rx_pause = true; - } - - backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1); - if (backup_pcie_dma_pause != 0xFF) - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF); - - if (mac_power_on) { - /* 3. reset TRX function - * write 0x100 = 0x00 - */ - rtl_write_byte(rtlpriv, REG_CR, 0); - } - - /* 4. Reset PCIe DMA - * write 0x003 bit[0] = 0 - */ - tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - tmp &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); - - /* 5. Enable PCIe DMA - * write 0x003 bit[0] = 1 - */ - tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - tmp |= BIT(0); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); - - if (mac_power_on) { - /* 6. enable TRX function - * write 0x100 = 0xFF - */ - rtl_write_byte(rtlpriv, REG_CR, 0xFF); - - /* We should init LLT & RQPN and - * prepare Tx/Rx descrptor address later - * because MAC function is reset. - */ - } - - /* 7. Restore PCIe autoload down bit - * write 0xF8 bit[17] = 1'b1 - */ - tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2); - tmp |= BIT(1); - rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp); - - /* In MAC power on state, BB and RF maybe in ON state, - * if we release TRx DMA here - * it will cause packets to be started to Tx/Rx, - * so we release Tx/Rx DMA later. - */ - if (!mac_power_on) { - /* 8. release TRX DMA - * write 0x284 bit[18] = 1'b0 - * write 0x301 = 0x00 - */ - if (release_mac_rx_pause) { - tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, - (tmp & (~BIT(2)))); - } - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, - backup_pcie_dma_pause); - } - - /* 9. lock system register - * write 0xCC bit[2] = 1'b0 - */ - tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); - tmp &= ~(BIT(2)); - rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); -} - -int rtl8723be_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - bool rtstatus = true; - int err; - u8 tmp_u1b; - unsigned long flags; - - /* reenable interrupts to not interfere with other devices */ - local_save_flags(flags); - local_irq_enable(); - - rtlhal->fw_ready = false; - rtlpriv->rtlhal.being_init_adapter = true; - rtlpriv->intf_ops->disable_aspm(hw); - - tmp_u1b = rtl_read_byte(rtlpriv, REG_CR); - if (tmp_u1b != 0 && tmp_u1b != 0xea) { - rtlhal->mac_func_enable = true; - } else { - rtlhal->mac_func_enable = false; - rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON; - } - - if (_rtl8723be_check_pcie_dma_hang(rtlpriv)) { - _rtl8723be_reset_pcie_interface_dma(rtlpriv, - rtlhal->mac_func_enable); - rtlhal->mac_func_enable = false; - } - if (rtlhal->mac_func_enable) { - _rtl8723be_poweroff_adapter(hw); - rtlhal->mac_func_enable = false; - } - rtstatus = _rtl8723be_init_mac(hw); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); - err = 1; - goto exit; - } - - tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CFG); - rtl_write_byte(rtlpriv, REG_SYS_CFG, tmp_u1b & 0x7F); - - err = rtl8723_download_fw(hw, true, FW_8723B_POLLING_TIMEOUT_COUNT); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Failed to download FW. Init HW without FW now..\n"); - err = 1; - goto exit; - } - rtlhal->fw_ready = true; - - rtlhal->last_hmeboxnum = 0; - rtl8723be_phy_mac_config(hw); - /* because last function modify RCR, so we update - * rcr var here, or TP will unstable for receive_config - * is wrong, RX RCR_ACRC32 will cause TP unstable & Rx - * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 - */ - rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); - rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - - rtl8723be_phy_bb_config(hw); - rtl8723be_phy_rf_config(hw); - - rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, - RF_CHNLBW, RFREG_OFFSET_MASK); - rtlphy->rfreg_chnlval[0] &= 0xFFF03FF; - rtlphy->rfreg_chnlval[0] |= (BIT(10) | BIT(11)); - - _rtl8723be_hw_configure(hw); - rtlhal->mac_func_enable = true; - rtl_cam_reset_all_entry(hw); - rtl8723be_enable_hw_security_config(hw); - - ppsc->rfpwr_state = ERFON; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); - _rtl8723be_enable_aspm_back_door(hw); - rtlpriv->intf_ops->enable_aspm(hw); - - rtl8723be_bt_hw_init(hw); - - if (ppsc->rfpwr_state == ERFON) { - rtl8723be_phy_set_rfpath_switch(hw, 1); - /* when use 1ant NIC, iqk will disturb BT music - * root cause is not clear now, is something - * related with 'mdelay' and Reg[0x948] - */ - if (rtlpriv->btcoexist.btc_info.ant_num == ANT_X2 || - !rtlpriv->cfg->ops->get_btc_status()) { - rtl8723be_phy_iq_calibrate(hw, false); - rtlphy->iqk_initialized = true; - } - rtl8723be_dm_check_txpower_tracking(hw); - rtl8723be_phy_lc_calibrate(hw); - } - rtl_write_byte(rtlpriv, REG_NAV_UPPER, ((30000 + 127) / 128)); - - /* Release Rx DMA. */ - tmp_u1b = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - if (tmp_u1b & BIT(2)) { - /* Release Rx DMA if needed */ - tmp_u1b &= (~BIT(2)); - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, tmp_u1b); - } - /* Release Tx/Rx PCIE DMA. */ - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0); - - rtl8723be_dm_init(hw); -exit: - local_irq_restore(flags); - rtlpriv->rtlhal.being_init_adapter = false; - return err; -} - -static enum version_8723e _rtl8723be_read_chip_version(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - enum version_8723e version = VERSION_UNKNOWN; - u32 value32; - - value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG1); - if ((value32 & (CHIP_8723B)) != CHIP_8723B) - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "unkown chip version\n"); - else - version = (enum version_8723e)CHIP_8723B; - - rtlphy->rf_type = RF_1T1R; - - /* treat rtl8723be chip as MP version in default */ - version = (enum version_8723e)(version | NORMAL_CHIP); - - value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); - /* cut version */ - version |= (enum version_8723e)(value32 & CHIP_VER_RTL_MASK); - /* Manufacture */ - if (((value32 & EXT_VENDOR_ID) >> 18) == 0x01) - version = (enum version_8723e)(version | CHIP_VENDOR_SMIC); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ? - "RF_2T2R" : "RF_1T1R"); - - return version; -} - -static int _rtl8723be_set_media_status(struct ieee80211_hw *hw, - enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bt_msr = rtl_read_byte(rtlpriv, MSR) & 0xfc; - enum led_ctl_mode ledaction = LED_CTL_NO_LINK; - u8 mode = MSR_NOLINK; - - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - mode = MSR_NOLINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to NO LINK!\n"); - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - mode = MSR_ADHOC; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to Ad Hoc!\n"); - break; - case NL80211_IFTYPE_STATION: - mode = MSR_INFRA; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to STA!\n"); - break; - case NL80211_IFTYPE_AP: - mode = MSR_AP; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to AP!\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Network type %d not support!\n", type); - return 1; - } - - /* MSR_INFRA == Link in infrastructure network; - * MSR_ADHOC == Link in ad hoc network; - * Therefore, check link state is necessary. - * - * MSR_AP == AP mode; link state is not cared here. - */ - if (mode != MSR_AP && rtlpriv->mac80211.link_state < MAC80211_LINKED) { - mode = MSR_NOLINK; - ledaction = LED_CTL_NO_LINK; - } - - if (mode == MSR_NOLINK || mode == MSR_INFRA) { - _rtl8723be_stop_tx_beacon(hw); - _rtl8723be_enable_bcn_sub_func(hw); - } else if (mode == MSR_ADHOC || mode == MSR_AP) { - _rtl8723be_resume_tx_beacon(hw); - _rtl8723be_disable_bcn_sub_func(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", - mode); - } - - rtl_write_byte(rtlpriv, MSR, bt_msr | mode); - rtlpriv->cfg->ops->led_control(hw, ledaction); - if (mode == MSR_AP) - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); - else - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); - return 0; -} - -void rtl8723be_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u32 reg_rcr = rtlpci->receive_config; - - if (rtlpriv->psc.rfpwr_state != ERFON) - return; - - if (check_bssid) { - reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *)(®_rcr)); - _rtl8723be_set_bcn_ctrl_reg(hw, 0, BIT(4)); - } else if (!check_bssid) { - reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); - _rtl8723be_set_bcn_ctrl_reg(hw, BIT(4), 0); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *)(®_rcr)); - } - -} - -int rtl8723be_set_network_type(struct ieee80211_hw *hw, - enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (_rtl8723be_set_media_status(hw, type)) - return -EOPNOTSUPP; - - if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { - if (type != NL80211_IFTYPE_AP) - rtl8723be_set_check_bssid(hw, true); - } else { - rtl8723be_set_check_bssid(hw, false); - } - - return 0; -} - -/* don't set REG_EDCA_BE_PARAM here - * because mac80211 will send pkt when scan - */ -void rtl8723be_set_qos(struct ieee80211_hw *hw, int aci) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl8723_dm_init_edca_turbo(hw); - switch (aci) { - case AC1_BK: - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); - break; - case AC0_BE: - break; - case AC2_VI: - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); - break; - case AC3_VO: - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); - break; - default: - RT_ASSERT(false, "invalid aci: %d !\n", aci); - break; - } -} - -void rtl8723be_enable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); - rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); - rtlpci->irq_enabled = true; - - /*enable system interrupt*/ - rtl_write_dword(rtlpriv, REG_HSIMR, rtlpci->sys_irq_mask & 0xFFFFFFFF); -} - -void rtl8723be_disable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED); - rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED); - rtlpci->irq_enabled = false; - /*synchronize_irq(rtlpci->pdev->irq);*/ -} - -void rtl8723be_card_disable(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - enum nl80211_iftype opmode; - - mac->link_state = MAC80211_NOLINK; - opmode = NL80211_IFTYPE_UNSPECIFIED; - _rtl8723be_set_media_status(hw, opmode); - if (rtlpriv->rtlhal.driver_is_goingto_unload || - ppsc->rfoff_reason > RF_CHANGE_BY_PS) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - _rtl8723be_poweroff_adapter(hw); - - /* after power off we should do iqk again */ - rtlpriv->phy.iqk_initialized = false; -} - -void rtl8723be_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; - rtl_write_dword(rtlpriv, ISR, *p_inta); - - *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & - rtlpci->irq_mask[1]; - rtl_write_dword(rtlpriv, REG_HISRE, *p_intb); -} - -void rtl8723be_set_beacon_related_registers(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval, atim_window; - - bcn_interval = mac->beacon_interval; - atim_window = 2; /*FIX MERGE */ - rtl8723be_disable_interrupt(hw); - rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); - rtl_write_byte(rtlpriv, 0x606, 0x30); - rtl8723be_enable_interrupt(hw); -} - -void rtl8723be_set_beacon_interval(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval = mac->beacon_interval; - - RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, - "beacon_interval:%d\n", bcn_interval); - rtl8723be_disable_interrupt(hw); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - rtl8723be_enable_interrupt(hw); -} - -void rtl8723be_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, - "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); - - if (add_msr) - rtlpci->irq_mask[0] |= add_msr; - if (rm_msr) - rtlpci->irq_mask[0] &= (~rm_msr); - rtl8723be_disable_interrupt(hw); - rtl8723be_enable_interrupt(hw); -} - -static u8 _rtl8723be_get_chnl_group(u8 chnl) -{ - u8 group; - - if (chnl < 3) - group = 0; - else if (chnl < 9) - group = 1; - else - group = 2; - return group; -} - -static void _rtl8723be_read_power_value_fromprom(struct ieee80211_hw *hw, - struct txpower_info_2g *pw2g, - struct txpower_info_5g *pw5g, - bool autoload_fail, u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 path, addr = EEPROM_TX_PWR_INX, group, cnt = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "hal_ReadPowerValueFromPROM8723BE(): PROMContent[0x%x]=0x%x\n", - (addr + 1), hwinfo[addr + 1]); - if (0xFF == hwinfo[addr + 1]) /*YJ,add,120316*/ - autoload_fail = true; - - if (autoload_fail) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "auto load fail : Use Default value!\n"); - for (path = 0; path < MAX_RF_PATH; path++) { - /* 2.4G default value */ - for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { - pw2g->index_cck_base[path][group] = 0x2D; - pw2g->index_bw40_base[path][group] = 0x2D; - } - for (cnt = 0; cnt < MAX_TX_COUNT; cnt++) { - if (cnt == 0) { - pw2g->bw20_diff[path][0] = 0x02; - pw2g->ofdm_diff[path][0] = 0x04; - } else { - pw2g->bw20_diff[path][cnt] = 0xFE; - pw2g->bw40_diff[path][cnt] = 0xFE; - pw2g->cck_diff[path][cnt] = 0xFE; - pw2g->ofdm_diff[path][cnt] = 0xFE; - } - } - } - return; - } - - for (path = 0; path < MAX_RF_PATH; path++) { - /*2.4G default value*/ - for (group = 0; group < MAX_CHNL_GROUP_24G; group++) { - pw2g->index_cck_base[path][group] = hwinfo[addr++]; - if (pw2g->index_cck_base[path][group] == 0xFF) - pw2g->index_cck_base[path][group] = 0x2D; - - } - for (group = 0; group < MAX_CHNL_GROUP_24G - 1; group++) { - pw2g->index_bw40_base[path][group] = hwinfo[addr++]; - if (pw2g->index_bw40_base[path][group] == 0xFF) - pw2g->index_bw40_base[path][group] = 0x2D; - } - for (cnt = 0; cnt < MAX_TX_COUNT; cnt++) { - if (cnt == 0) { - pw2g->bw40_diff[path][cnt] = 0; - if (hwinfo[addr] == 0xFF) { - pw2g->bw20_diff[path][cnt] = 0x02; - } else { - pw2g->bw20_diff[path][cnt] = - (hwinfo[addr] & 0xf0) >> 4; - /*bit sign number to 8 bit sign number*/ - if (pw2g->bw20_diff[path][cnt] & BIT(3)) - pw2g->bw20_diff[path][cnt] |= - 0xF0; - } - - if (hwinfo[addr] == 0xFF) { - pw2g->ofdm_diff[path][cnt] = 0x04; - } else { - pw2g->ofdm_diff[path][cnt] = - (hwinfo[addr] & 0x0f); - /*bit sign number to 8 bit sign number*/ - if (pw2g->ofdm_diff[path][cnt] & BIT(3)) - pw2g->ofdm_diff[path][cnt] |= - 0xF0; - } - pw2g->cck_diff[path][cnt] = 0; - addr++; - } else { - if (hwinfo[addr] == 0xFF) { - pw2g->bw40_diff[path][cnt] = 0xFE; - } else { - pw2g->bw40_diff[path][cnt] = - (hwinfo[addr] & 0xf0) >> 4; - if (pw2g->bw40_diff[path][cnt] & BIT(3)) - pw2g->bw40_diff[path][cnt] |= - 0xF0; - } - - if (hwinfo[addr] == 0xFF) { - pw2g->bw20_diff[path][cnt] = 0xFE; - } else { - pw2g->bw20_diff[path][cnt] = - (hwinfo[addr] & 0x0f); - if (pw2g->bw20_diff[path][cnt] & BIT(3)) - pw2g->bw20_diff[path][cnt] |= - 0xF0; - } - addr++; - - if (hwinfo[addr] == 0xFF) { - pw2g->ofdm_diff[path][cnt] = 0xFE; - } else { - pw2g->ofdm_diff[path][cnt] = - (hwinfo[addr] & 0xf0) >> 4; - if (pw2g->ofdm_diff[path][cnt] & BIT(3)) - pw2g->ofdm_diff[path][cnt] |= - 0xF0; - } - - if (hwinfo[addr] == 0xFF) - pw2g->cck_diff[path][cnt] = 0xFE; - else { - pw2g->cck_diff[path][cnt] = - (hwinfo[addr] & 0x0f); - if (pw2g->cck_diff[path][cnt] & BIT(3)) - pw2g->cck_diff[path][cnt] |= - 0xF0; - } - addr++; - } - } - - /*5G default value*/ - for (group = 0; group < MAX_CHNL_GROUP_5G; group++) { - pw5g->index_bw40_base[path][group] = hwinfo[addr++]; - if (pw5g->index_bw40_base[path][group] == 0xFF) - pw5g->index_bw40_base[path][group] = 0xFE; - } - - for (cnt = 0; cnt < MAX_TX_COUNT; cnt++) { - if (cnt == 0) { - pw5g->bw40_diff[path][cnt] = 0; - - if (hwinfo[addr] == 0xFF) { - pw5g->bw20_diff[path][cnt] = 0; - } else { - pw5g->bw20_diff[path][0] = - (hwinfo[addr] & 0xf0) >> 4; - if (pw5g->bw20_diff[path][cnt] & BIT(3)) - pw5g->bw20_diff[path][cnt] |= - 0xF0; - } - - if (hwinfo[addr] == 0xFF) - pw5g->ofdm_diff[path][cnt] = 0x04; - else { - pw5g->ofdm_diff[path][0] = - (hwinfo[addr] & 0x0f); - if (pw5g->ofdm_diff[path][cnt] & BIT(3)) - pw5g->ofdm_diff[path][cnt] |= - 0xF0; - } - addr++; - } else { - if (hwinfo[addr] == 0xFF) { - pw5g->bw40_diff[path][cnt] = 0xFE; - } else { - pw5g->bw40_diff[path][cnt] = - (hwinfo[addr] & 0xf0) >> 4; - if (pw5g->bw40_diff[path][cnt] & BIT(3)) - pw5g->bw40_diff[path][cnt] |= 0xF0; - } - - if (hwinfo[addr] == 0xFF) { - pw5g->bw20_diff[path][cnt] = 0xFE; - } else { - pw5g->bw20_diff[path][cnt] = - (hwinfo[addr] & 0x0f); - if (pw5g->bw20_diff[path][cnt] & BIT(3)) - pw5g->bw20_diff[path][cnt] |= 0xF0; - } - addr++; - } - } - - if (hwinfo[addr] == 0xFF) { - pw5g->ofdm_diff[path][1] = 0xFE; - pw5g->ofdm_diff[path][2] = 0xFE; - } else { - pw5g->ofdm_diff[path][1] = (hwinfo[addr] & 0xf0) >> 4; - pw5g->ofdm_diff[path][2] = (hwinfo[addr] & 0x0f); - } - addr++; - - if (hwinfo[addr] == 0xFF) - pw5g->ofdm_diff[path][3] = 0xFE; - else - pw5g->ofdm_diff[path][3] = (hwinfo[addr] & 0x0f); - addr++; - - for (cnt = 1; cnt < MAX_TX_COUNT; cnt++) { - if (pw5g->ofdm_diff[path][cnt] == 0xFF) - pw5g->ofdm_diff[path][cnt] = 0xFE; - else if (pw5g->ofdm_diff[path][cnt] & BIT(3)) - pw5g->ofdm_diff[path][cnt] |= 0xF0; - } - } -} - -static void _rtl8723be_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct txpower_info_2g pw2g; - struct txpower_info_5g pw5g; - u8 rf_path, index; - u8 i; - - _rtl8723be_read_power_value_fromprom(hw, &pw2g, &pw5g, autoload_fail, - hwinfo); - - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < 14; i++) { - index = _rtl8723be_get_chnl_group(i+1); - - rtlefuse->txpwrlevel_cck[rf_path][i] = - pw2g.index_cck_base[rf_path][index]; - rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = - pw2g.index_bw40_base[rf_path][index]; - } - for (i = 0; i < MAX_TX_COUNT; i++) { - rtlefuse->txpwr_ht20diff[rf_path][i] = - pw2g.bw20_diff[rf_path][i]; - rtlefuse->txpwr_ht40diff[rf_path][i] = - pw2g.bw40_diff[rf_path][i]; - rtlefuse->txpwr_legacyhtdiff[rf_path][i] = - pw2g.ofdm_diff[rf_path][i]; - } - - for (i = 0; i < 14; i++) { - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "RF(%d)-Ch(%d) [CCK / HT40_1S ] = [0x%x / 0x%x ]\n", - rf_path, i, - rtlefuse->txpwrlevel_cck[rf_path][i], - rtlefuse->txpwrlevel_ht40_1s[rf_path][i]); - } - } - - if (!autoload_fail) - rtlefuse->eeprom_thermalmeter = - hwinfo[EEPROM_THERMAL_METER_88E]; - else - rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; - - if (rtlefuse->eeprom_thermalmeter == 0xff || autoload_fail) { - rtlefuse->apk_thermalmeterignore = true; - rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; - } - - rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); - - if (!autoload_fail) { - rtlefuse->eeprom_regulatory = - hwinfo[EEPROM_RF_BOARD_OPTION_88E] & 0x07;/*bit0~2*/ - if (hwinfo[EEPROM_RF_BOARD_OPTION_88E] == 0xFF) - rtlefuse->eeprom_regulatory = 0; - } else { - rtlefuse->eeprom_regulatory = 0; - } - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); -} - -static void _rtl8723be_read_adapter_info(struct ieee80211_hw *hw, - bool pseudo_test) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u16 i, usvalue; - u8 hwinfo[HWSET_MAX_SIZE]; - u16 eeprom_id; - bool is_toshiba_smid1 = false; - bool is_toshiba_smid2 = false; - bool is_samsung_smid = false; - bool is_lenovo_smid = false; - u16 toshiba_smid1[] = { - 0x6151, 0x6152, 0x6154, 0x6155, 0x6177, 0x6178, 0x6179, 0x6180, - 0x7151, 0x7152, 0x7154, 0x7155, 0x7177, 0x7178, 0x7179, 0x7180, - 0x8151, 0x8152, 0x8154, 0x8155, 0x8181, 0x8182, 0x8184, 0x8185, - 0x9151, 0x9152, 0x9154, 0x9155, 0x9181, 0x9182, 0x9184, 0x9185 - }; - u16 toshiba_smid2[] = { - 0x6181, 0x6184, 0x6185, 0x7181, 0x7182, 0x7184, 0x7185, 0x8181, - 0x8182, 0x8184, 0x8185, 0x9181, 0x9182, 0x9184, 0x9185 - }; - u16 samsung_smid[] = { - 0x6191, 0x6192, 0x6193, 0x7191, 0x7192, 0x7193, 0x8191, 0x8192, - 0x8193, 0x9191, 0x9192, 0x9193 - }; - u16 lenovo_smid[] = { - 0x8195, 0x9195, 0x7194, 0x8200, 0x8201, 0x8202, 0x9199, 0x9200 - }; - - if (pseudo_test) { - /* needs to be added */ - return; - } - if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { - rtl_efuse_shadow_map_update(hw); - - memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], - HWSET_MAX_SIZE); - } else if (rtlefuse->epromtype == EEPROM_93C46) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "RTL819X Not boot from eeprom, check it !!"); - } - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), - hwinfo, HWSET_MAX_SIZE); - - eeprom_id = *((u16 *)&hwinfo[0]); - if (eeprom_id != RTL8723BE_EEPROM_ID) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "EEPROM ID(%#x) is invalid!!\n", eeprom_id); - rtlefuse->autoload_failflag = true; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - } - - if (rtlefuse->autoload_failflag) - return; - - rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; - rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; - rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; - rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROMId = 0x%4x\n", eeprom_id); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); - - for (i = 0; i < 6; i += 2) { - usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; - *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "dev_addr: %pM\n", - rtlefuse->dev_addr); - - /*parse xtal*/ - rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_8723BE]; - if (rtlefuse->crystalcap == 0xFF) - rtlefuse->crystalcap = 0x20; - - _rtl8723be_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, - hwinfo); - - rtl8723be_read_bt_coexist_info_from_hwpg(hw, - rtlefuse->autoload_failflag, - hwinfo); - - rtlefuse->eeprom_channelplan = hwinfo[EEPROM_CHANNELPLAN]; - rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; - rtlefuse->txpwr_fromeprom = true; - rtlefuse->eeprom_oemid = hwinfo[EEPROM_CUSTOMER_ID]; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); - - /* set channel plan from efuse */ - rtlefuse->channel_plan = rtlefuse->eeprom_channelplan; - - if (rtlhal->oem_id == RT_CID_DEFAULT) { - /* Does this one have a Toshiba SMID from group 1? */ - for (i = 0; i < sizeof(toshiba_smid1) / sizeof(u16); i++) { - if (rtlefuse->eeprom_smid == toshiba_smid1[i]) { - is_toshiba_smid1 = true; - break; - } - } - /* Does this one have a Toshiba SMID from group 2? */ - for (i = 0; i < sizeof(toshiba_smid2) / sizeof(u16); i++) { - if (rtlefuse->eeprom_smid == toshiba_smid2[i]) { - is_toshiba_smid2 = true; - break; - } - } - /* Does this one have a Samsung SMID? */ - for (i = 0; i < sizeof(samsung_smid) / sizeof(u16); i++) { - if (rtlefuse->eeprom_smid == samsung_smid[i]) { - is_samsung_smid = true; - break; - } - } - /* Does this one have a Lenovo SMID? */ - for (i = 0; i < sizeof(lenovo_smid) / sizeof(u16); i++) { - if (rtlefuse->eeprom_smid == lenovo_smid[i]) { - is_lenovo_smid = true; - break; - } - } - switch (rtlefuse->eeprom_oemid) { - case EEPROM_CID_DEFAULT: - if (rtlefuse->eeprom_did == 0x8176) { - if (rtlefuse->eeprom_svid == 0x10EC && - is_toshiba_smid1) { - rtlhal->oem_id = RT_CID_TOSHIBA; - } else if (rtlefuse->eeprom_svid == 0x1025) { - rtlhal->oem_id = RT_CID_819X_ACER; - } else if (rtlefuse->eeprom_svid == 0x10EC && - is_samsung_smid) { - rtlhal->oem_id = RT_CID_819X_SAMSUNG; - } else if (rtlefuse->eeprom_svid == 0x10EC && - is_lenovo_smid) { - rtlhal->oem_id = RT_CID_819X_LENOVO; - } else if ((rtlefuse->eeprom_svid == 0x10EC && - rtlefuse->eeprom_smid == 0x8197) || - (rtlefuse->eeprom_svid == 0x10EC && - rtlefuse->eeprom_smid == 0x9196)) { - rtlhal->oem_id = RT_CID_819X_CLEVO; - } else if ((rtlefuse->eeprom_svid == 0x1028 && - rtlefuse->eeprom_smid == 0x8194) || - (rtlefuse->eeprom_svid == 0x1028 && - rtlefuse->eeprom_smid == 0x8198) || - (rtlefuse->eeprom_svid == 0x1028 && - rtlefuse->eeprom_smid == 0x9197) || - (rtlefuse->eeprom_svid == 0x1028 && - rtlefuse->eeprom_smid == 0x9198)) { - rtlhal->oem_id = RT_CID_819X_DELL; - } else if ((rtlefuse->eeprom_svid == 0x103C && - rtlefuse->eeprom_smid == 0x1629)) { - rtlhal->oem_id = RT_CID_819X_HP; - } else if ((rtlefuse->eeprom_svid == 0x1A32 && - rtlefuse->eeprom_smid == 0x2315)) { - rtlhal->oem_id = RT_CID_819X_QMI; - } else if ((rtlefuse->eeprom_svid == 0x10EC && - rtlefuse->eeprom_smid == 0x8203)) { - rtlhal->oem_id = RT_CID_819X_PRONETS; - } else if ((rtlefuse->eeprom_svid == 0x1043 && - rtlefuse->eeprom_smid == 0x84B5)) { - rtlhal->oem_id = RT_CID_819X_EDIMAX_ASUS; - } else { - rtlhal->oem_id = RT_CID_DEFAULT; - } - } else if (rtlefuse->eeprom_did == 0x8178) { - if (rtlefuse->eeprom_svid == 0x10EC && - is_toshiba_smid2) - rtlhal->oem_id = RT_CID_TOSHIBA; - else if (rtlefuse->eeprom_svid == 0x1025) - rtlhal->oem_id = RT_CID_819X_ACER; - else if ((rtlefuse->eeprom_svid == 0x10EC && - rtlefuse->eeprom_smid == 0x8186)) - rtlhal->oem_id = RT_CID_819X_PRONETS; - else if ((rtlefuse->eeprom_svid == 0x1043 && - rtlefuse->eeprom_smid == 0x84B6)) - rtlhal->oem_id = - RT_CID_819X_EDIMAX_ASUS; - else - rtlhal->oem_id = RT_CID_DEFAULT; - } else { - rtlhal->oem_id = RT_CID_DEFAULT; - } - break; - case EEPROM_CID_TOSHIBA: - rtlhal->oem_id = RT_CID_TOSHIBA; - break; - case EEPROM_CID_CCX: - rtlhal->oem_id = RT_CID_CCX; - break; - case EEPROM_CID_QMI: - rtlhal->oem_id = RT_CID_819X_QMI; - break; - case EEPROM_CID_WHQL: - break; - default: - rtlhal->oem_id = RT_CID_DEFAULT; - break; - } - } -} - -static void _rtl8723be_hal_customized_behavior(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - pcipriv->ledctl.led_opendrain = true; - switch (rtlhal->oem_id) { - case RT_CID_819X_HP: - pcipriv->ledctl.led_opendrain = true; - break; - case RT_CID_819X_LENOVO: - case RT_CID_DEFAULT: - case RT_CID_TOSHIBA: - case RT_CID_CCX: - case RT_CID_819X_ACER: - case RT_CID_WHQL: - default: - break; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "RT Customized ID: 0x%02X\n", rtlhal->oem_id); -} - -void rtl8723be_read_eeprom_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_u1b; - - rtlhal->version = _rtl8723be_read_chip_version(hw); - if (get_rf_type(rtlphy) == RF_1T1R) - rtlpriv->dm.rfpath_rxenable[0] = true; - else - rtlpriv->dm.rfpath_rxenable[0] = - rtlpriv->dm.rfpath_rxenable[1] = true; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", - rtlhal->version); - tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); - if (tmp_u1b & BIT(4)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); - rtlefuse->epromtype = EEPROM_93C46; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); - rtlefuse->epromtype = EEPROM_BOOT_EFUSE; - } - if (tmp_u1b & BIT(5)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - _rtl8723be_read_adapter_info(hw, false); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); - } - _rtl8723be_hal_customized_behavior(hw); -} - -static u8 _rtl8723be_mrate_idx_to_arfr_id(struct ieee80211_hw *hw, - u8 rate_index) -{ - u8 ret = 0; - switch (rate_index) { - case RATR_INX_WIRELESS_NGB: - ret = 1; - break; - case RATR_INX_WIRELESS_N: - case RATR_INX_WIRELESS_NG: - ret = 5; - break; - case RATR_INX_WIRELESS_NB: - ret = 3; - break; - case RATR_INX_WIRELESS_GB: - ret = 6; - break; - case RATR_INX_WIRELESS_G: - ret = 7; - break; - case RATR_INX_WIRELESS_B: - ret = 8; - break; - default: - ret = 0; - break; - } - return ret; -} - -static void rtl8723be_update_hal_rate_mask(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - u32 ratr_bitmap; - u8 ratr_index; - u8 curtxbw_40mhz = (sta->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0; - u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = 0; - bool shortgi = false; - u8 rate_mask[7]; - u8 macid = 0; - - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - wirelessmode = sta_entry->wireless_mode; - if (mac->opmode == NL80211_IFTYPE_STATION || - mac->opmode == NL80211_IFTYPE_MESH_POINT) - curtxbw_40mhz = mac->bw_40; - else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) - macid = sta->aid + 1; - - ratr_bitmap = sta->supp_rates[0]; - - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_bitmap = 0xfff; - - ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - ratr_index = RATR_INX_WIRELESS_B; - if (ratr_bitmap & 0x0000000c) - ratr_bitmap &= 0x0000000d; - else - ratr_bitmap &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_index = RATR_INX_WIRELESS_GB; - - if (rssi_level == 1) - ratr_bitmap &= 0x00000f00; - else if (rssi_level == 2) - ratr_bitmap &= 0x00000ff0; - else - ratr_bitmap &= 0x00000ff5; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - ratr_index = RATR_INX_WIRELESS_NGB; - if (rtlphy->rf_type == RF_1T1R) { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff005; - } - } else { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x0f8f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0f8ff000; - else - ratr_bitmap &= 0x0f8ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x0f8f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0f8ff000; - else - ratr_bitmap &= 0x0f8ff005; - } - } - if ((curtxbw_40mhz && curshortgi_40mhz) || - (!curtxbw_40mhz && curshortgi_20mhz)) { - if (macid == 0) - shortgi = true; - else if (macid == 1) - shortgi = false; - } - break; - default: - ratr_index = RATR_INX_WIRELESS_NGB; - - if (rtlphy->rf_type == RF_1T2R) - ratr_bitmap &= 0x000ff0ff; - else - ratr_bitmap &= 0x0f0ff0ff; - break; - } - - sta_entry->ratr_index = ratr_index; - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "ratr_bitmap :%x\n", ratr_bitmap); - *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | - (ratr_index << 28); - rate_mask[0] = macid; - rate_mask[1] = _rtl8723be_mrate_idx_to_arfr_id(hw, ratr_index) | - (shortgi ? 0x80 : 0x00); - rate_mask[2] = curtxbw_40mhz; - - rate_mask[3] = (u8)(ratr_bitmap & 0x000000ff); - rate_mask[4] = (u8)((ratr_bitmap & 0x0000ff00) >> 8); - rate_mask[5] = (u8)((ratr_bitmap & 0x00ff0000) >> 16); - rate_mask[6] = (u8)((ratr_bitmap & 0xff000000) >> 24); - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x:%x:%x\n", - ratr_index, ratr_bitmap, - rate_mask[0], rate_mask[1], - rate_mask[2], rate_mask[3], - rate_mask[4], rate_mask[5], - rate_mask[6]); - rtl8723be_fill_h2c_cmd(hw, H2C_8723B_RA_MASK, 7, rate_mask); - _rtl8723be_set_bcn_ctrl_reg(hw, BIT(3), 0); -} - -void rtl8723be_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (rtlpriv->dm.useramask) - rtl8723be_update_hal_rate_mask(hw, sta, rssi_level); -} - -void rtl8723be_update_channel_access_setting(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 sifs_timer; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, &mac->slot_time); - if (!mac->ht_enable) - sifs_timer = 0x0a0a; - else - sifs_timer = 0x0e0e; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); -} - -bool rtl8723be_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; - u8 u1tmp; - bool b_actuallyset = false; - - if (rtlpriv->rtlhal.being_init_adapter) - return false; - - if (ppsc->swrf_processing) - return false; - - spin_lock(&rtlpriv->locks.rf_ps_lock); - if (ppsc->rfchange_inprogress) { - spin_unlock(&rtlpriv->locks.rf_ps_lock); - return false; - } else { - ppsc->rfchange_inprogress = true; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } - - cur_rfstate = ppsc->rfpwr_state; - - rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL_2, - rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL_2) & ~(BIT(1))); - - u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL_2); - - if (rtlphy->polarity_ctl) - e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFOFF : ERFON; - else - e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFON : ERFOFF; - - if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "GPIOChangeRF - HW Radio ON, RF ON\n"); - - e_rfpowerstate_toset = ERFON; - ppsc->hwradiooff = false; - b_actuallyset = true; - } else if (!ppsc->hwradiooff && (e_rfpowerstate_toset == ERFOFF)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "GPIOChangeRF - HW Radio OFF, RF OFF\n"); - - e_rfpowerstate_toset = ERFOFF; - ppsc->hwradiooff = true; - b_actuallyset = true; - } - - if (b_actuallyset) { - spin_lock(&rtlpriv->locks.rf_ps_lock); - ppsc->rfchange_inprogress = false; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } else { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - - spin_lock(&rtlpriv->locks.rf_ps_lock); - ppsc->rfchange_inprogress = false; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } - - *valid = 1; - return !ppsc->hwradiooff; - -} - -void rtl8723be_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 *macaddr = p_macaddr; - u32 entry_id = 0; - bool is_pairwise = false; - - static u8 cam_const_addr[4][6] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} - }; - static u8 cam_const_broad[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - - if (clear_all) { - u8 idx = 0; - u8 cam_offset = 0; - u8 clear_number = 5; - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); - - for (idx = 0; idx < clear_number; idx++) { - rtl_cam_mark_invalid(hw, cam_offset + idx); - rtl_cam_empty_entry(hw, cam_offset + idx); - - if (idx < 5) { - memset(rtlpriv->sec.key_buf[idx], 0, - MAX_KEY_LEN); - rtlpriv->sec.key_len[idx] = 0; - } - } - - } else { - switch (enc_algo) { - case WEP40_ENCRYPTION: - enc_algo = CAM_WEP40; - break; - case WEP104_ENCRYPTION: - enc_algo = CAM_WEP104; - break; - case TKIP_ENCRYPTION: - enc_algo = CAM_TKIP; - break; - case AESCCMP_ENCRYPTION: - enc_algo = CAM_AES; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - enc_algo = CAM_TKIP; - break; - } - - if (is_wepkey || rtlpriv->sec.use_defaultkey) { - macaddr = cam_const_addr[key_index]; - entry_id = key_index; - } else { - if (is_group) { - macaddr = cam_const_broad; - entry_id = key_index; - } else { - if (mac->opmode == NL80211_IFTYPE_AP) { - entry_id = rtl_cam_get_free_entry(hw, - p_macaddr); - if (entry_id >= TOTAL_CAM_ENTRY) { - RT_TRACE(rtlpriv, COMP_SEC, - DBG_EMERG, - "Can not find free hw security cam entry\n"); - return; - } - } else { - entry_id = CAM_PAIRWISE_KEY_POSITION; - } - - key_index = PAIRWISE_KEYIDX; - is_pairwise = true; - } - } - - if (rtlpriv->sec.key_len[key_index] == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "delete one entry, entry_id is %d\n", - entry_id); - if (mac->opmode == NL80211_IFTYPE_AP) - rtl_cam_del_entry(hw, p_macaddr); - rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "add one entry\n"); - if (is_pairwise) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set Pairwiase key\n"); - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[key_index]); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set group key\n"); - - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - rtl_cam_add_one_entry(hw, - rtlefuse->dev_addr, - PAIRWISE_KEYIDX, - CAM_PAIRWISE_KEY_POSITION, - enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf - [entry_id]); - } - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[entry_id]); - } - } - } -} - -void rtl8723be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool auto_load_fail, u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value; - u32 tmpu_32; - - if (!auto_load_fail) { - tmpu_32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL); - if (tmpu_32 & BIT(18)) - rtlpriv->btcoexist.btc_info.btcoexist = 1; - else - rtlpriv->btcoexist.btc_info.btcoexist = 0; - value = hwinfo[EEPROM_RF_BT_SETTING_8723B]; - rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8723B; - rtlpriv->btcoexist.btc_info.ant_num = (value & 0x1); - } else { - rtlpriv->btcoexist.btc_info.btcoexist = 0; - rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8723B; - rtlpriv->btcoexist.btc_info.ant_num = ANT_X2; - } - -} - -void rtl8723be_bt_reg_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /* 0:Low, 1:High, 2:From Efuse. */ - rtlpriv->btcoexist.reg_bt_iso = 2; - /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ - rtlpriv->btcoexist.reg_bt_sco = 3; - /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ - rtlpriv->btcoexist.reg_bt_sco = 0; -} - -void rtl8723be_bt_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_init_hw_config(rtlpriv); - -} - -void rtl8723be_suspend(struct ieee80211_hw *hw) -{ -} - -void rtl8723be_resume(struct ieee80211_hw *hw) -{ -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.h b/drivers/net/wireless/rtlwifi/rtl8723be/hw.h deleted file mode 100644 index eae863d08de8..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723BE_HW_H__ -#define __RTL8723BE_HW_H__ - -void rtl8723be_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl8723be_read_eeprom_info(struct ieee80211_hw *hw); - -void rtl8723be_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb); -int rtl8723be_hw_init(struct ieee80211_hw *hw); -void rtl8723be_card_disable(struct ieee80211_hw *hw); -void rtl8723be_enable_interrupt(struct ieee80211_hw *hw); -void rtl8723be_disable_interrupt(struct ieee80211_hw *hw); -int rtl8723be_set_network_type(struct ieee80211_hw *hw, - enum nl80211_iftype type); -void rtl8723be_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -void rtl8723be_set_qos(struct ieee80211_hw *hw, int aci); -void rtl8723be_set_beacon_related_registers(struct ieee80211_hw *hw); -void rtl8723be_set_beacon_interval(struct ieee80211_hw *hw); -void rtl8723be_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr); -void rtl8723be_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl8723be_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u8 rssi_level); -void rtl8723be_update_channel_access_setting(struct ieee80211_hw *hw); -bool rtl8723be_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); -void rtl8723be_enable_hw_security_config(struct ieee80211_hw *hw); -void rtl8723be_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all); -void rtl8723be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, u8 *hwinfo); -void rtl8723be_bt_reg_init(struct ieee80211_hw *hw); -void rtl8723be_bt_hw_init(struct ieee80211_hw *hw); -void rtl8723be_suspend(struct ieee80211_hw *hw); -void rtl8723be_resume(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/led.c b/drivers/net/wireless/rtlwifi/rtl8723be/led.c deleted file mode 100644 index 4196efb723a2..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/led.c +++ /dev/null @@ -1,153 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "reg.h" -#include "led.h" - -static void _rtl8723be_init_led(struct ieee80211_hw *hw, struct rtl_led *pled, - enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - u8 ledcfg; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - ledcfg &= ~BIT(6); - rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5)); - break; - case LED_PIN_LED1: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); - rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - pled->ledon = true; -} - -void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - u8 ledcfg; - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); - - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg &= 0xf0; - if (pcipriv->ledctl.led_opendrain) { - ledcfg &= 0x90; /* Set to software control. */ - rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3))); - ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); - ledcfg &= 0xFE; - rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg); - } else { - ledcfg &= ~BIT(6); - rtl_write_byte(rtlpriv, REG_LEDCFG2, - (ledcfg | BIT(3) | BIT(5))); - } - break; - case LED_PIN_LED1: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); - ledcfg &= 0x10; /* Set to software control. */ - rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg|BIT(3)); - - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - pled->ledon = false; -} - -void rtl8723be_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - _rtl8723be_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); - _rtl8723be_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); -} - -static void _rtl8723be_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_led *pled0 = &(pcipriv->ledctl.sw_led0); - switch (ledaction) { - case LED_CTL_POWER_ON: - case LED_CTL_LINK: - case LED_CTL_NO_LINK: - rtl8723be_sw_led_on(hw, pled0); - break; - case LED_CTL_POWER_OFF: - rtl8723be_sw_led_off(hw, pled0); - break; - default: - break; - } -} - -void rtl8723be_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && - (ledaction == LED_CTL_TX || - ledaction == LED_CTL_RX || - ledaction == LED_CTL_SITE_SURVEY || - ledaction == LED_CTL_LINK || - ledaction == LED_CTL_NO_LINK || - ledaction == LED_CTL_START_TO_LINK || - ledaction == LED_CTL_POWER_ON)) { - return; - } - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n", ledaction); - _rtl8723be_sw_led_control(hw, ledaction); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/led.h b/drivers/net/wireless/rtlwifi/rtl8723be/led.h deleted file mode 100644 index c57de379ee8d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/led.h +++ /dev/null @@ -1,35 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723BE_LED_H__ -#define __RTL8723BE_LED_H__ - -void rtl8723be_init_sw_leds(struct ieee80211_hw *hw); -void rtl8723be_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8723be_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8723be_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/phy.c b/drivers/net/wireless/rtlwifi/rtl8723be/phy.c deleted file mode 100644 index b7b73cbe346d..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/phy.c +++ /dev/null @@ -1,2730 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../ps.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "../rtl8723com/phy_common.h" -#include "rf.h" -#include "dm.h" -#include "../rtl8723com/dm_common.h" -#include "table.h" -#include "trx.h" - -static bool _rtl8723be_phy_bb8723b_config_parafile(struct ieee80211_hw *hw); -static bool _rtl8723be_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); -static bool _rtl8723be_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); -static bool _rtl8723be_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); -static bool _rtl8723be_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, - u8 *step, u32 *delay); - -static void rtl8723be_phy_set_rf_on(struct ieee80211_hw *hw); -static void rtl8723be_phy_set_io(struct ieee80211_hw *hw); - -u32 rtl8723be_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, readback_value, bitshift; - unsigned long flags; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", - regaddr, rfpath, bitmask); - - spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); - - original_value = rtl8723_phy_rf_serial_read(hw, rfpath, regaddr); - bitshift = rtl8723_phy_calculate_bit_shift(bitmask); - readback_value = (original_value & bitmask) >> bitshift; - - spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", - regaddr, rfpath, bitmask, original_value); - - return readback_value; -} - -void rtl8723be_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path path, - u32 regaddr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, bitshift; - unsigned long flags; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, path); - - spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); - - if (bitmask != RFREG_OFFSET_MASK) { - original_value = rtl8723_phy_rf_serial_read(hw, path, - regaddr); - bitshift = rtl8723_phy_calculate_bit_shift(bitmask); - data = ((original_value & (~bitmask)) | - (data << bitshift)); - } - - rtl8723_phy_rf_serial_write(hw, path, regaddr, data); - - spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, path); - -} - -bool rtl8723be_phy_mac_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool rtstatus = _rtl8723be_phy_config_mac_with_headerfile(hw); - - rtl_write_byte(rtlpriv, 0x04CA, 0x0B); - return rtstatus; -} - -bool rtl8723be_phy_bb_config(struct ieee80211_hw *hw) -{ - bool rtstatus = true; - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 regval; - u8 b_reg_hwparafile = 1; - u32 tmp; - u8 crystalcap = rtlpriv->efuse.crystalcap; - rtl8723_phy_init_bb_rf_reg_def(hw); - regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, - regval | BIT(13) | BIT(0) | BIT(1)); - - rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, - FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | - FEN_BB_GLB_RSTN | FEN_BBRSTB); - tmp = rtl_read_dword(rtlpriv, 0x4c); - rtl_write_dword(rtlpriv, 0x4c, tmp | BIT(23)); - - rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); - - if (b_reg_hwparafile == 1) - rtstatus = _rtl8723be_phy_bb8723b_config_parafile(hw); - - crystalcap = crystalcap & 0x3F; - rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, - (crystalcap | crystalcap << 6)); - - return rtstatus; -} - -bool rtl8723be_phy_rf_config(struct ieee80211_hw *hw) -{ - return rtl8723be_phy_rf6052_config(hw); -} - -static bool _rtl8723be_check_condition(struct ieee80211_hw *hw, - const u32 condition) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 _board = rtlefuse->board_type; /*need efuse define*/ - u32 _interface = rtlhal->interface; - u32 _platform = 0x08;/*SupportPlatform */ - u32 cond = condition; - - if (condition == 0xCDCDCDCD) - return true; - - cond = condition & 0xFF; - if ((_board & cond) == 0 && cond != 0x1F) - return false; - - cond = condition & 0xFF00; - cond = cond >> 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = condition & 0xFF0000; - cond = cond >> 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - return true; -} - -static void _rtl8723be_config_rf_reg(struct ieee80211_hw *hw, u32 addr, - u32 data, enum radio_path rfpath, - u32 regaddr) -{ - if (addr == 0xfe || addr == 0xffe) { - /* In order not to disturb BT music - * when wifi init.(1ant NIC only) - */ - mdelay(50); - } else { - rtl_set_rfreg(hw, rfpath, regaddr, RFREG_OFFSET_MASK, data); - udelay(1); - } -} -static void _rtl8723be_config_rf_radio_a(struct ieee80211_hw *hw, - u32 addr, u32 data) -{ - u32 content = 0x1000; /*RF Content: radio_a_txt*/ - u32 maskforphyset = (u32)(content & 0xE000); - - _rtl8723be_config_rf_reg(hw, addr, data, RF90_PATH_A, - addr | maskforphyset); - -} - -static void _rtl8723be_phy_init_tx_power_by_rate(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - u8 band, path, txnum, section; - - for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band) - for (path = 0; path < TX_PWR_BY_RATE_NUM_RF; ++path) - for (txnum = 0; txnum < TX_PWR_BY_RATE_NUM_RF; ++txnum) - for (section = 0; - section < TX_PWR_BY_RATE_NUM_SECTION; - ++section) - rtlphy->tx_power_by_rate_offset - [band][path][txnum][section] = 0; -} - -static void _rtl8723be_config_bb_reg(struct ieee80211_hw *hw, - u32 addr, u32 data) -{ - if (addr == 0xfe) { - mdelay(50); - } else if (addr == 0xfd) { - mdelay(5); - } else if (addr == 0xfc) { - mdelay(1); - } else if (addr == 0xfb) { - udelay(50); - } else if (addr == 0xfa) { - udelay(5); - } else if (addr == 0xf9) { - udelay(1); - } else { - rtl_set_bbreg(hw, addr, MASKDWORD, data); - udelay(1); - } -} - -static void _rtl8723be_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw, - u8 band, - u8 path, u8 rate_section, - u8 txnum, u8 value) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - if (path > RF90_PATH_D) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid Rf Path %d in phy_SetTxPowerByRatBase()\n", - path); - return; - } - - if (band == BAND_ON_2_4G) { - switch (rate_section) { - case CCK: - rtlphy->txpwr_by_rate_base_24g[path][txnum][0] = value; - break; - case OFDM: - rtlphy->txpwr_by_rate_base_24g[path][txnum][1] = value; - break; - case HT_MCS0_MCS7: - rtlphy->txpwr_by_rate_base_24g[path][txnum][2] = value; - break; - case HT_MCS8_MCS15: - rtlphy->txpwr_by_rate_base_24g[path][txnum][3] = value; - break; - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", - rate_section, path, txnum); - break; - }; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid Band %d in PHY_SetTxPowerByRateBase()\n", - band); - } - -} - -static u8 _rtl8723be_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw, - u8 band, u8 path, u8 txnum, - u8 rate_section) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 value = 0; - if (path > RF90_PATH_D) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid Rf Path %d in PHY_GetTxPowerByRateBase()\n", - path); - return 0; - } - - if (band == BAND_ON_2_4G) { - switch (rate_section) { - case CCK: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][0]; - break; - case OFDM: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][1]; - break; - case HT_MCS0_MCS7: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][2]; - break; - case HT_MCS8_MCS15: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][3]; - break; - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", - rate_section, path, txnum); - break; - }; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid Band %d in PHY_GetTxPowerByRateBase()\n", - band); - } - - return value; -} - -static void _rtl8723be_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u16 rawvalue = 0; - u8 base = 0, path = 0; - - for (path = RF90_PATH_A; path <= RF90_PATH_B; ++path) { - if (path == RF90_PATH_A) { - rawvalue = (u16)(rtlphy->tx_power_by_rate_offset - [BAND_ON_2_4G][path][RF_1TX][3] >> 24) & 0xFF; - base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); - _rtl8723be_phy_set_txpower_by_rate_base(hw, - BAND_ON_2_4G, path, CCK, RF_1TX, base); - } else if (path == RF90_PATH_B) { - rawvalue = (u16)(rtlphy->tx_power_by_rate_offset - [BAND_ON_2_4G][path][RF_1TX][3] >> 0) & 0xFF; - base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); - _rtl8723be_phy_set_txpower_by_rate_base(hw, - BAND_ON_2_4G, - path, CCK, - RF_1TX, base); - } - rawvalue = (u16)(rtlphy->tx_power_by_rate_offset - [BAND_ON_2_4G][path][RF_1TX][1] >> 24) & 0xFF; - base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); - _rtl8723be_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, - path, OFDM, RF_1TX, - base); - - rawvalue = (u16)(rtlphy->tx_power_by_rate_offset - [BAND_ON_2_4G][path][RF_1TX][5] >> 24) & 0xFF; - base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); - _rtl8723be_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, - path, HT_MCS0_MCS7, - RF_1TX, base); - - rawvalue = (u16)(rtlphy->tx_power_by_rate_offset - [BAND_ON_2_4G][path][RF_2TX][7] >> 24) & 0xFF; - base = (rawvalue >> 4) * 10 + (rawvalue & 0xF); - _rtl8723be_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, - path, HT_MCS8_MCS15, - RF_2TX, base); - } -} - -static void _phy_convert_txpower_dbm_to_relative_value(u32 *data, u8 start, - u8 end, u8 base_val) -{ - char i = 0; - u8 temp_value = 0; - u32 temp_data = 0; - - for (i = 3; i >= 0; --i) { - if (i >= start && i <= end) { - /* Get the exact value */ - temp_value = (u8)(*data >> (i * 8)) & 0xF; - temp_value += ((u8)((*data >> (i*8 + 4)) & 0xF)) * 10; - - /* Change the value to a relative value */ - temp_value = (temp_value > base_val) ? - temp_value - base_val : - base_val - temp_value; - } else { - temp_value = (u8)(*data >> (i * 8)) & 0xFF; - } - temp_data <<= 8; - temp_data |= temp_value; - } - *data = temp_data; -} - -static void _rtl8723be_phy_convert_txpower_dbm_to_relative_value( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 base = 0, rfpath = RF90_PATH_A; - - base = _rtl8723be_phy_get_txpower_by_rate_base(hw, - BAND_ON_2_4G, rfpath, RF_1TX, CCK); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][2], - 1, 1, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][3], - 1, 3, base); - - base = _rtl8723be_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath, - RF_1TX, OFDM); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][0], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][1], - 0, 3, base); - - base = _rtl8723be_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, - rfpath, RF_1TX, HT_MCS0_MCS7); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][4], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][5], - 0, 3, base); - - base = _rtl8723be_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, - rfpath, RF_2TX, - HT_MCS8_MCS15); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][6], - 0, 3, base); - - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][7], - 0, 3, base); - - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "<===_rtl8723be_phy_convert_txpower_dbm_to_relative_value()\n"); -} - -static void phy_txpower_by_rate_config(struct ieee80211_hw *hw) -{ - _rtl8723be_phy_store_txpower_by_rate_base(hw); - _rtl8723be_phy_convert_txpower_dbm_to_relative_value(hw); -} - -static bool _rtl8723be_phy_bb8723b_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - bool rtstatus; - - rtstatus = _rtl8723be_phy_config_bb_with_headerfile(hw, - BASEBAND_CONFIG_PHY_REG); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); - return false; - } - _rtl8723be_phy_init_tx_power_by_rate(hw); - if (!rtlefuse->autoload_failflag) { - rtlphy->pwrgroup_cnt = 0; - rtstatus = _rtl8723be_phy_config_bb_with_pgheaderfile(hw, - BASEBAND_CONFIG_PHY_REG); - } - phy_txpower_by_rate_config(hw); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); - return false; - } - rtstatus = _rtl8723be_phy_config_bb_with_headerfile(hw, - BASEBAND_CONFIG_AGC_TAB); - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); - return false; - } - rtlphy->cck_high_power = (bool)(rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, - 0x200)); - return true; -} - -static bool _rtl8723be_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - u32 arraylength; - u32 *ptrarray; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read rtl8723beMACPHY_Array\n"); - arraylength = RTL8723BEMAC_1T_ARRAYLEN; - ptrarray = RTL8723BEMAC_1T_ARRAY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Img:RTL8723bEMAC_1T_ARRAY LEN %d\n", arraylength); - for (i = 0; i < arraylength; i = i + 2) - rtl_write_byte(rtlpriv, ptrarray[i], (u8)ptrarray[i + 1]); - return true; -} - -static bool _rtl8723be_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) -{ - #define READ_NEXT_PAIR(v1, v2, i) \ - do { \ - i += 2; \ - v1 = array_table[i];\ - v2 = array_table[i+1]; \ - } while (0) - - int i; - u32 *array_table; - u16 arraylen; - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 v1 = 0, v2 = 0; - - if (configtype == BASEBAND_CONFIG_PHY_REG) { - arraylen = RTL8723BEPHY_REG_1TARRAYLEN; - array_table = RTL8723BEPHY_REG_1TARRAY; - - for (i = 0; i < arraylen; i = i + 2) { - v1 = array_table[i]; - v2 = array_table[i+1]; - if (v1 < 0xcdcdcdcd) { - _rtl8723be_config_bb_reg(hw, v1, v2); - } else {/*This line is the start line of branch.*/ - /* to protect READ_NEXT_PAIR not overrun */ - if (i >= arraylen - 2) - break; - - if (!_rtl8723be_check_condition(hw, - array_table[i])) { - /*Discard the following - *(offset, data) pairs - */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < arraylen - 2) { - READ_NEXT_PAIR(v1, v2, i); - } - i -= 2; /* prevent from for-loop += 2*/ - /*Configure matched pairs and - *skip to end of if-else. - */ - } else { - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < arraylen - 2) { - _rtl8723be_config_bb_reg(hw, - v1, v2); - READ_NEXT_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < arraylen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - } - } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { - arraylen = RTL8723BEAGCTAB_1TARRAYLEN; - array_table = RTL8723BEAGCTAB_1TARRAY; - - for (i = 0; i < arraylen; i = i + 2) { - v1 = array_table[i]; - v2 = array_table[i+1]; - if (v1 < 0xCDCDCDCD) { - rtl_set_bbreg(hw, array_table[i], - MASKDWORD, - array_table[i + 1]); - udelay(1); - continue; - } else {/*This line is the start line of branch.*/ - /* to protect READ_NEXT_PAIR not overrun */ - if (i >= arraylen - 2) - break; - - if (!_rtl8723be_check_condition(hw, - array_table[i])) { - /*Discard the following - *(offset, data) pairs - */ - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < arraylen - 2) { - READ_NEXT_PAIR(v1, v2, i); - } - i -= 2; /* prevent from for-loop += 2*/ - /*Configure matched pairs and - *skip to end of if-else. - */ - } else { - READ_NEXT_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < arraylen - 2) { - rtl_set_bbreg(hw, array_table[i], - MASKDWORD, - array_table[i + 1]); - udelay(1); - READ_NEXT_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < arraylen - 2) - READ_NEXT_PAIR(v1, v2, i); - } - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The agctab_array_table[0] is %x Rtl818EEPHY_REGArray[1] is %x\n", - array_table[i], array_table[i + 1]); - } - } - return true; -} - -static u8 _rtl8723be_get_rate_section_index(u32 regaddr) -{ - u8 index = 0; - - switch (regaddr) { - case RTXAGC_A_RATE18_06: - index = 0; - break; - case RTXAGC_A_RATE54_24: - index = 1; - break; - case RTXAGC_A_CCK1_MCS32: - index = 2; - break; - case RTXAGC_B_CCK11_A_CCK2_11: - index = 3; - break; - case RTXAGC_A_MCS03_MCS00: - index = 4; - break; - case RTXAGC_A_MCS07_MCS04: - index = 5; - break; - case RTXAGC_A_MCS11_MCS08: - index = 6; - break; - case RTXAGC_A_MCS15_MCS12: - index = 7; - break; - case RTXAGC_B_RATE18_06: - index = 0; - break; - case RTXAGC_B_RATE54_24: - index = 1; - break; - case RTXAGC_B_CCK1_55_MCS32: - index = 2; - break; - case RTXAGC_B_MCS03_MCS00: - index = 4; - break; - case RTXAGC_B_MCS07_MCS04: - index = 5; - break; - case RTXAGC_B_MCS11_MCS08: - index = 6; - break; - case RTXAGC_B_MCS15_MCS12: - index = 7; - break; - default: - regaddr &= 0xFFF; - if (regaddr >= 0xC20 && regaddr <= 0xC4C) - index = (u8)((regaddr - 0xC20) / 4); - else if (regaddr >= 0xE20 && regaddr <= 0xE4C) - index = (u8)((regaddr - 0xE20) / 4); - break; - }; - return index; -} - -static void _rtl8723be_store_tx_power_by_rate(struct ieee80211_hw *hw, - u32 band, u32 rfpath, - u32 txnum, u32 regaddr, - u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 rate_section = _rtl8723be_get_rate_section_index(regaddr); - - if (band != BAND_ON_2_4G && band != BAND_ON_5G) { - RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, "Invalid Band %d\n", band); - return; - } - if (rfpath > MAX_RF_PATH - 1) { - RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, - "Invalid RfPath %d\n", rfpath); - return; - } - if (txnum > MAX_RF_PATH - 1) { - RT_TRACE(rtlpriv, FPHY, PHY_TXPWR, "Invalid TxNum %d\n", txnum); - return; - } - - rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = - data; - -} - -static bool _rtl8723be_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int i; - u32 *phy_regarray_table_pg; - u16 phy_regarray_pg_len; - u32 v1 = 0, v2 = 0, v3 = 0, v4 = 0, v5 = 0, v6 = 0; - - phy_regarray_pg_len = RTL8723BEPHY_REG_ARRAY_PGLEN; - phy_regarray_table_pg = RTL8723BEPHY_REG_ARRAY_PG; - - if (configtype == BASEBAND_CONFIG_PHY_REG) { - for (i = 0; i < phy_regarray_pg_len; i = i + 6) { - v1 = phy_regarray_table_pg[i]; - v2 = phy_regarray_table_pg[i+1]; - v3 = phy_regarray_table_pg[i+2]; - v4 = phy_regarray_table_pg[i+3]; - v5 = phy_regarray_table_pg[i+4]; - v6 = phy_regarray_table_pg[i+5]; - - if (v1 < 0xcdcdcdcd) { - if (phy_regarray_table_pg[i] == 0xfe || - phy_regarray_table_pg[i] == 0xffe) - mdelay(50); - else - _rtl8723be_store_tx_power_by_rate(hw, - v1, v2, v3, v4, v5, v6); - continue; - } - } - } else { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "configtype != BaseBand_Config_PHY_REG\n"); - } - return true; -} - -bool rtl8723be_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath) -{ - #define READ_NEXT_RF_PAIR(v1, v2, i) \ - do { \ - i += 2; \ - v1 = radioa_array_table[i]; \ - v2 = radioa_array_table[i+1]; \ - } while (0) - - int i; - bool rtstatus = true; - u32 *radioa_array_table; - u16 radioa_arraylen; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 v1 = 0, v2 = 0; - - radioa_arraylen = RTL8723BE_RADIOA_1TARRAYLEN; - radioa_array_table = RTL8723BE_RADIOA_1TARRAY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Radio_A:RTL8723BE_RADIOA_1TARRAY %d\n", radioa_arraylen); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); - rtstatus = true; - switch (rfpath) { - case RF90_PATH_A: - for (i = 0; i < radioa_arraylen; i = i + 2) { - v1 = radioa_array_table[i]; - v2 = radioa_array_table[i+1]; - if (v1 < 0xcdcdcdcd) { - _rtl8723be_config_rf_radio_a(hw, v1, v2); - } else {/*This line is the start line of branch.*/ - /* to protect READ_NEXT_PAIR not overrun */ - if (i >= radioa_arraylen - 2) - break; - - if (!_rtl8723be_check_condition(hw, - radioa_array_table[i])) { - /*Discard the following - *(offset, data) pairs - */ - READ_NEXT_RF_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < radioa_arraylen - 2) { - READ_NEXT_RF_PAIR(v1, v2, i); - } - i -= 2; /* prevent from for-loop += 2*/ - } else { - /*Configure matched pairs - *and skip to end of if-else. - */ - READ_NEXT_RF_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < radioa_arraylen - 2) { - _rtl8723be_config_rf_radio_a(hw, - v1, v2); - READ_NEXT_RF_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && - i < radioa_arraylen - 2) { - READ_NEXT_RF_PAIR(v1, v2, i); - } - } - } - } - - if (rtlhal->oem_id == RT_CID_819X_HP) - _rtl8723be_config_rf_radio_a(hw, 0x52, 0x7E4BD); - break; - case RF90_PATH_B: - case RF90_PATH_C: - break; - case RF90_PATH_D: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - return true; -} - -void rtl8723be_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - rtlphy->default_initialgain[0] = - (u8)rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[1] = - (u8)rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[2] = - (u8)rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[3] = - (u8)rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", - rtlphy->default_initialgain[0], - rtlphy->default_initialgain[1], - rtlphy->default_initialgain[2], - rtlphy->default_initialgain[3]); - - rtlphy->framesync = (u8)rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, - MASKBYTE0); - rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, - MASKDWORD); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default framesync (0x%x) = 0x%x\n", - ROFDM0_RXDETECTOR3, rtlphy->framesync); -} - -static u8 _rtl8723be_phy_get_ratesection_intxpower_byrate(enum radio_path path, - u8 rate) -{ - u8 rate_section = 0; - - switch (rate) { - case DESC92C_RATE1M: - rate_section = 2; - break; - - case DESC92C_RATE2M: - case DESC92C_RATE5_5M: - if (path == RF90_PATH_A) - rate_section = 3; - else if (path == RF90_PATH_B) - rate_section = 2; - break; - - case DESC92C_RATE11M: - rate_section = 3; - break; - - case DESC92C_RATE6M: - case DESC92C_RATE9M: - case DESC92C_RATE12M: - case DESC92C_RATE18M: - rate_section = 0; - break; - - case DESC92C_RATE24M: - case DESC92C_RATE36M: - case DESC92C_RATE48M: - case DESC92C_RATE54M: - rate_section = 1; - break; - - case DESC92C_RATEMCS0: - case DESC92C_RATEMCS1: - case DESC92C_RATEMCS2: - case DESC92C_RATEMCS3: - rate_section = 4; - break; - - case DESC92C_RATEMCS4: - case DESC92C_RATEMCS5: - case DESC92C_RATEMCS6: - case DESC92C_RATEMCS7: - rate_section = 5; - break; - - case DESC92C_RATEMCS8: - case DESC92C_RATEMCS9: - case DESC92C_RATEMCS10: - case DESC92C_RATEMCS11: - rate_section = 6; - break; - - case DESC92C_RATEMCS12: - case DESC92C_RATEMCS13: - case DESC92C_RATEMCS14: - case DESC92C_RATEMCS15: - rate_section = 7; - break; - - default: - RT_ASSERT(true, "Rate_Section is Illegal\n"); - break; - } - - return rate_section; -} - -static u8 _rtl8723be_get_txpower_by_rate(struct ieee80211_hw *hw, - enum band_type band, - enum radio_path rfpath, u8 rate) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 shift = 0, rate_section, tx_num; - char tx_pwr_diff = 0; - - rate_section = _rtl8723be_phy_get_ratesection_intxpower_byrate(rfpath, - rate); - tx_num = RF_TX_NUM_NONIMPLEMENT; - - if (tx_num == RF_TX_NUM_NONIMPLEMENT) { - if (rate >= DESC92C_RATEMCS8 && rate <= DESC92C_RATEMCS15) - tx_num = RF_2TX; - else - tx_num = RF_1TX; - } - - switch (rate) { - case DESC92C_RATE6M: - case DESC92C_RATE24M: - case DESC92C_RATEMCS0: - case DESC92C_RATEMCS4: - case DESC92C_RATEMCS8: - case DESC92C_RATEMCS12: - shift = 0; - break; - case DESC92C_RATE1M: - case DESC92C_RATE2M: - case DESC92C_RATE9M: - case DESC92C_RATE36M: - case DESC92C_RATEMCS1: - case DESC92C_RATEMCS5: - case DESC92C_RATEMCS9: - case DESC92C_RATEMCS13: - shift = 8; - break; - case DESC92C_RATE5_5M: - case DESC92C_RATE12M: - case DESC92C_RATE48M: - case DESC92C_RATEMCS2: - case DESC92C_RATEMCS6: - case DESC92C_RATEMCS10: - case DESC92C_RATEMCS14: - shift = 16; - break; - case DESC92C_RATE11M: - case DESC92C_RATE18M: - case DESC92C_RATE54M: - case DESC92C_RATEMCS3: - case DESC92C_RATEMCS7: - case DESC92C_RATEMCS11: - case DESC92C_RATEMCS15: - shift = 24; - break; - default: - RT_ASSERT(true, "Rate_Section is Illegal\n"); - break; - } - tx_pwr_diff = (u8)(rtlphy->tx_power_by_rate_offset[band][rfpath][tx_num] - [rate_section] >> shift) & 0xff; - - return tx_pwr_diff; -} - -static u8 _rtl8723be_get_txpower_index(struct ieee80211_hw *hw, u8 path, - u8 rate, u8 bandwidth, u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 index = (channel - 1); - u8 txpower; - u8 power_diff_byrate = 0; - - if (channel > 14 || channel < 1) { - index = 0; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Illegal channel!\n"); - } - if (RX_HAL_IS_CCK_RATE(rate)) - txpower = rtlefuse->txpwrlevel_cck[path][index]; - else if (DESC92C_RATE6M <= rate) - txpower = rtlefuse->txpwrlevel_ht40_1s[path][index]; - else - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "invalid rate\n"); - - if (DESC92C_RATE6M <= rate && rate <= DESC92C_RATE54M && - !RX_HAL_IS_CCK_RATE(rate)) - txpower += rtlefuse->txpwr_legacyhtdiff[0][TX_1S]; - - if (bandwidth == HT_CHANNEL_WIDTH_20) { - if (DESC92C_RATEMCS0 <= rate && rate <= DESC92C_RATEMCS15) - txpower += rtlefuse->txpwr_ht20diff[0][TX_1S]; - if (DESC92C_RATEMCS8 <= rate && rate <= DESC92C_RATEMCS15) - txpower += rtlefuse->txpwr_ht20diff[0][TX_2S]; - } else if (bandwidth == HT_CHANNEL_WIDTH_20_40) { - if (DESC92C_RATEMCS0 <= rate && rate <= DESC92C_RATEMCS15) - txpower += rtlefuse->txpwr_ht40diff[0][TX_1S]; - if (DESC92C_RATEMCS8 <= rate && rate <= DESC92C_RATEMCS15) - txpower += rtlefuse->txpwr_ht40diff[0][TX_2S]; - } - - if (rtlefuse->eeprom_regulatory != 2) - power_diff_byrate = _rtl8723be_get_txpower_by_rate(hw, - BAND_ON_2_4G, - path, rate); - - txpower += power_diff_byrate; - - if (txpower > MAX_POWER_INDEX) - txpower = MAX_POWER_INDEX; - - return txpower; -} - -static void _rtl8723be_phy_set_txpower_index(struct ieee80211_hw *hw, - u8 power_index, u8 path, u8 rate) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (path == RF90_PATH_A) { - switch (rate) { - case DESC92C_RATE1M: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_CCK1_MCS32, - MASKBYTE1, power_index); - break; - case DESC92C_RATE2M: - rtl8723_phy_set_bb_reg(hw, RTXAGC_B_CCK11_A_CCK2_11, - MASKBYTE1, power_index); - break; - case DESC92C_RATE5_5M: - rtl8723_phy_set_bb_reg(hw, RTXAGC_B_CCK11_A_CCK2_11, - MASKBYTE2, power_index); - break; - case DESC92C_RATE11M: - rtl8723_phy_set_bb_reg(hw, RTXAGC_B_CCK11_A_CCK2_11, - MASKBYTE3, power_index); - break; - - case DESC92C_RATE6M: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06, - MASKBYTE0, power_index); - break; - case DESC92C_RATE9M: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06, - MASKBYTE1, power_index); - break; - case DESC92C_RATE12M: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06, - MASKBYTE2, power_index); - break; - case DESC92C_RATE18M: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06, - MASKBYTE3, power_index); - break; - - case DESC92C_RATE24M: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24, - MASKBYTE0, power_index); - break; - case DESC92C_RATE36M: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24, - MASKBYTE1, power_index); - break; - case DESC92C_RATE48M: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24, - MASKBYTE2, power_index); - break; - case DESC92C_RATE54M: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24, - MASKBYTE3, power_index); - break; - - case DESC92C_RATEMCS0: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00, - MASKBYTE0, power_index); - break; - case DESC92C_RATEMCS1: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00, - MASKBYTE1, power_index); - break; - case DESC92C_RATEMCS2: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00, - MASKBYTE2, power_index); - break; - case DESC92C_RATEMCS3: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00, - MASKBYTE3, power_index); - break; - - case DESC92C_RATEMCS4: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04, - MASKBYTE0, power_index); - break; - case DESC92C_RATEMCS5: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04, - MASKBYTE1, power_index); - break; - case DESC92C_RATEMCS6: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04, - MASKBYTE2, power_index); - break; - case DESC92C_RATEMCS7: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04, - MASKBYTE3, power_index); - break; - - case DESC92C_RATEMCS8: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08, - MASKBYTE0, power_index); - break; - case DESC92C_RATEMCS9: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08, - MASKBYTE1, power_index); - break; - case DESC92C_RATEMCS10: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08, - MASKBYTE2, power_index); - break; - case DESC92C_RATEMCS11: - rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08, - MASKBYTE3, power_index); - break; - - default: - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Invalid Rate!!\n"); - break; - } - } else { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Invalid RFPath!!\n"); - } -} - -void rtl8723be_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 cck_rates[] = {DESC92C_RATE1M, DESC92C_RATE2M, - DESC92C_RATE5_5M, DESC92C_RATE11M}; - u8 ofdm_rates[] = {DESC92C_RATE6M, DESC92C_RATE9M, - DESC92C_RATE12M, DESC92C_RATE18M, - DESC92C_RATE24M, DESC92C_RATE36M, - DESC92C_RATE48M, DESC92C_RATE54M}; - u8 ht_rates_1t[] = {DESC92C_RATEMCS0, DESC92C_RATEMCS1, - DESC92C_RATEMCS2, DESC92C_RATEMCS3, - DESC92C_RATEMCS4, DESC92C_RATEMCS5, - DESC92C_RATEMCS6, DESC92C_RATEMCS7}; - u8 i, size; - u8 power_index; - - if (!rtlefuse->txpwr_fromeprom) - return; - - size = sizeof(cck_rates) / sizeof(u8); - for (i = 0; i < size; i++) { - power_index = _rtl8723be_get_txpower_index(hw, RF90_PATH_A, - cck_rates[i], - rtl_priv(hw)->phy.current_chan_bw, - channel); - _rtl8723be_phy_set_txpower_index(hw, power_index, RF90_PATH_A, - cck_rates[i]); - } - size = sizeof(ofdm_rates) / sizeof(u8); - for (i = 0; i < size; i++) { - power_index = _rtl8723be_get_txpower_index(hw, RF90_PATH_A, - ofdm_rates[i], - rtl_priv(hw)->phy.current_chan_bw, - channel); - _rtl8723be_phy_set_txpower_index(hw, power_index, RF90_PATH_A, - ofdm_rates[i]); - } - size = sizeof(ht_rates_1t) / sizeof(u8); - for (i = 0; i < size; i++) { - power_index = _rtl8723be_get_txpower_index(hw, RF90_PATH_A, - ht_rates_1t[i], - rtl_priv(hw)->phy.current_chan_bw, - channel); - _rtl8723be_phy_set_txpower_index(hw, power_index, RF90_PATH_A, - ht_rates_1t[i]); - } -} - -void rtl8723be_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - enum io_type iotype; - - if (!is_hal_stop(rtlhal)) { - switch (operation) { - case SCAN_OPT_BACKUP_BAND0: - iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, - (u8 *)&iotype); - - break; - case SCAN_OPT_RESTORE: - iotype = IO_CMD_RESUME_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, - (u8 *)&iotype); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Unknown Scan Backup operation.\n"); - break; - } - } -} - -void rtl8723be_phy_set_bw_mode_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 reg_bw_opmode; - u8 reg_prsr_rsc; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "Switch to %s bandwidth\n", - rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? - "20MHz" : "40MHz"); - - if (is_hal_stop(rtlhal)) { - rtlphy->set_bwmode_inprogress = false; - return; - } - - reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); - reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - reg_bw_opmode |= BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - break; - case HT_CHANNEL_WIDTH_20_40: - reg_bw_opmode &= ~BW_OPMODE_20MHZ; - rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); - reg_prsr_rsc = (reg_prsr_rsc & 0x90) | - (mac->cur_40_prime_sc << 5); - rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); - /* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);*/ - break; - case HT_CHANNEL_WIDTH_20_40: - rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); - rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); - - rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, - (mac->cur_40_prime_sc >> 1)); - rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); - /*rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);*/ - - rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), - (mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - rtl8723be_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); - rtlphy->set_bwmode_inprogress = false; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n"); -} - -void rtl8723be_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_bw = rtlphy->current_chan_bw; - - if (rtlphy->set_bwmode_inprogress) - return; - rtlphy->set_bwmode_inprogress = true; - if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtl8723be_phy_set_bw_mode_callback(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "false driver sleep or unload\n"); - rtlphy->set_bwmode_inprogress = false; - rtlphy->current_chan_bw = tmp_bw; - } -} - -void rtl8723be_phy_sw_chnl_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 delay; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "switch to channel%d\n", rtlphy->current_channel); - if (is_hal_stop(rtlhal)) - return; - do { - if (!rtlphy->sw_chnl_inprogress) - break; - if (!_rtl8723be_phy_sw_chnl_step_by_step(hw, - rtlphy->current_channel, - &rtlphy->sw_chnl_stage, - &rtlphy->sw_chnl_step, - &delay)) { - if (delay > 0) - mdelay(delay); - else - continue; - } else { - rtlphy->sw_chnl_inprogress = false; - } - break; - } while (true); - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); -} - -u8 rtl8723be_phy_sw_chnl(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (rtlphy->sw_chnl_inprogress) - return 0; - if (rtlphy->set_bwmode_inprogress) - return 0; - RT_ASSERT((rtlphy->current_channel <= 14), - "WIRELESS_MODE_G but channel>14"); - rtlphy->sw_chnl_inprogress = true; - rtlphy->sw_chnl_stage = 0; - rtlphy->sw_chnl_step = 0; - if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { - rtl8723be_phy_sw_chnl_callback(hw); - RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false schdule workitem current channel %d\n", - rtlphy->current_channel); - rtlphy->sw_chnl_inprogress = false; - } else { - RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false driver sleep or unload\n"); - rtlphy->sw_chnl_inprogress = false; - } - return 1; -} - -static bool _rtl8723be_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, - u8 channel, u8 *stage, - u8 *step, u32 *delay) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; - u32 precommoncmdcnt; - struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; - u32 postcommoncmdcnt; - struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; - u32 rfdependcmdcnt; - struct swchnlcmd *currentcmd = NULL; - u8 rfpath; - u8 num_total_rfpath = rtlphy->num_total_rfpath; - - precommoncmdcnt = 0; - rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, - CMDID_SET_TXPOWEROWER_LEVEL, - 0, 0, 0); - rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, - MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); - - postcommoncmdcnt = 0; - - rtl8723_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, - MAX_POSTCMD_CNT, CMDID_END, - 0, 0, 0); - - rfdependcmdcnt = 0; - - RT_ASSERT((channel >= 1 && channel <= 14), - "illegal channel for Zebra: %d\n", channel); - - rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, - CMDID_RF_WRITEREG, - RF_CHNLBW, channel, 10); - - rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, - MAX_RFDEPENDCMD_CNT, - CMDID_END, 0, 0, 0); - - do { - switch (*stage) { - case 0: - currentcmd = &precommoncmd[*step]; - break; - case 1: - currentcmd = &rfdependcmd[*step]; - break; - case 2: - currentcmd = &postcommoncmd[*step]; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Invalid 'stage' = %d, Check it!\n", *stage); - return true; - } - - if (currentcmd->cmdid == CMDID_END) { - if ((*stage) == 2) { - return true; - } else { - (*stage)++; - (*step) = 0; - continue; - } - } - - switch (currentcmd->cmdid) { - case CMDID_SET_TXPOWEROWER_LEVEL: - rtl8723be_phy_set_txpower_level(hw, channel); - break; - case CMDID_WRITEPORT_ULONG: - rtl_write_dword(rtlpriv, currentcmd->para1, - currentcmd->para2); - break; - case CMDID_WRITEPORT_USHORT: - rtl_write_word(rtlpriv, currentcmd->para1, - (u16)currentcmd->para2); - break; - case CMDID_WRITEPORT_UCHAR: - rtl_write_byte(rtlpriv, currentcmd->para1, - (u8)currentcmd->para2); - break; - case CMDID_RF_WRITEREG: - for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { - rtlphy->rfreg_chnlval[rfpath] = - ((rtlphy->rfreg_chnlval[rfpath] & - 0xfffffc00) | currentcmd->para2); - - rtl_set_rfreg(hw, (enum radio_path)rfpath, - currentcmd->para1, - RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[rfpath]); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - - break; - } while (true); - - (*delay) = currentcmd->msdelay; - (*step)++; - return false; -} - -static u8 _rtl8723be_phy_path_a_iqk(struct ieee80211_hw *hw) -{ - u32 reg_eac, reg_e94, reg_e9c, tmp; - u8 result = 0x00; - - /* leave IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - /* switch to path A */ - rtl_set_bbreg(hw, 0x948, MASKDWORD, 0x00000000); - /* enable path A PA in TXIQK mode */ - rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x20000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0003f); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xc7f87); - - /* 1. TX IQK */ - /* path-A IQK setting */ - /* IQK setting */ - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - /* path-A IQK setting */ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - - rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x821403ea); - rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160000); - rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000); - rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000); - /* LO calibration setting */ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x00462911); - /* enter IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /* One shot, path A LOK & IQK */ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - /* leave IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - - /* Check failed */ - reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); - reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); - reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && - (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else /* if Tx not OK, ignore Rx */ - return result; - - /* Allen 20131125 */ - tmp = (reg_e9c & 0x03FF0000) >> 16; - if ((tmp & 0x200) > 0) - tmp = 0x400 - tmp; - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) < 0x110) && - (((reg_e94 & 0x03FF0000) >> 16) > 0xf0) && - (tmp < 0xf)) - result |= 0x01; - else /* if Tx not OK, ignore Rx */ - return result; - - return result; -} - -/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ -static u8 _rtl8723be_phy_path_a_rx_iqk(struct ieee80211_hw *hw) -{ - u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u32tmp, tmp; - u8 result = 0x00; - - /* leave IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - - /* switch to path A */ - rtl_set_bbreg(hw, 0x948, MASKDWORD, 0x00000000); - - /* 1 Get TXIMR setting */ - /* modify RXIQK mode table */ - rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, 0x80000, 0x1); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0001f); - /* LNA2 off, PA on for Dcut */ - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7fb7); - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /* IQK setting */ - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - - /* path-A IQK setting */ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - - rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160ff0); - rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28110000); - rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000); - rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000); - - /* LO calibration setting */ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); - - /* enter IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /* One shot, path A LOK & IQK */ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - /* leave IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - - /* Check failed */ - reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); - reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); - reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && - (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else /* if Tx not OK, ignore Rx */ - return result; - - /* Allen 20131125 */ - tmp = (reg_e9c & 0x03FF0000) >> 16; - if ((tmp & 0x200) > 0) - tmp = 0x400 - tmp; - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) < 0x110) && - (((reg_e94 & 0x03FF0000) >> 16) > 0xf0) && - (tmp < 0xf)) - result |= 0x01; - else /* if Tx not OK, ignore Rx */ - return result; - - u32tmp = 0x80007C00 | (reg_e94 & 0x3FF0000) | - ((reg_e9c & 0x3FF0000) >> 16); - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32tmp); - - /* 1 RX IQK */ - /* modify RXIQK mode table */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, 0x80000, 0x1); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0001f); - /* LAN2 on, PA off for Dcut */ - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7d77); - - /* PA, PAD setting */ - rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0xf80); - rtl_set_rfreg(hw, RF90_PATH_A, 0x55, RFREG_OFFSET_MASK, 0x4021f); - - /* IQK setting */ - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - - /* path-A IQK setting */ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x18008c1c); - rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - - rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82110000); - rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x2816001f); - rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000); - rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000); - - /* LO calibration setting */ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a8d1); - - /* enter IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /* One shot, path A LOK & IQK */ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - /* leave IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - - /* Check failed */ - reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); - reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD); - - /* leave IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x780); - - /* Allen 20131125 */ - tmp = (reg_eac & 0x03FF0000) >> 16; - if ((tmp & 0x200) > 0) - tmp = 0x400 - tmp; - /* if Tx is OK, check whether Rx is OK */ - if (!(reg_eac & BIT(27)) && - (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && - (((reg_eac & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - else if (!(reg_eac & BIT(27)) && - (((reg_ea4 & 0x03FF0000) >> 16) < 0x110) && - (((reg_ea4 & 0x03FF0000) >> 16) > 0xf0) && - (tmp < 0xf)) - result |= 0x02; - - return result; -} - -static u8 _rtl8723be_phy_path_b_iqk(struct ieee80211_hw *hw) -{ - u32 reg_eac, reg_e94, reg_e9c, tmp; - u8 result = 0x00; - - /* leave IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - /* switch to path B */ - rtl_set_bbreg(hw, 0x948, MASKDWORD, 0x00000280); - - /* enable path B PA in TXIQK mode */ - rtl_set_rfreg(hw, RF90_PATH_A, 0xed, RFREG_OFFSET_MASK, 0x00020); - rtl_set_rfreg(hw, RF90_PATH_A, 0x43, RFREG_OFFSET_MASK, 0x40fc1); - - /* 1 Tx IQK */ - /* IQK setting */ - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - /* path-A IQK setting */ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - - rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x821403ea); - rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28110000); - rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000); - rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000); - - /* LO calibration setting */ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x00462911); - - /* enter IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /* One shot, path B LOK & IQK */ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - /* leave IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - - /* Check failed */ - reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); - reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); - reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && - (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else - return result; - - /* Allen 20131125 */ - tmp = (reg_e9c & 0x03FF0000) >> 16; - if ((tmp & 0x200) > 0) - tmp = 0x400 - tmp; - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) < 0x110) && - (((reg_e94 & 0x03FF0000) >> 16) > 0xf0) && - (tmp < 0xf)) - result |= 0x01; - else - return result; - - return result; -} - -/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ -static u8 _rtl8723be_phy_path_b_rx_iqk(struct ieee80211_hw *hw) -{ - u32 reg_e94, reg_e9c, reg_ea4, reg_eac, u32tmp, tmp; - u8 result = 0x00; - - /* leave IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - /* switch to path B */ - rtl_set_bbreg(hw, 0x948, MASKDWORD, 0x00000280); - - /* 1 Get TXIMR setting */ - /* modify RXIQK mode table */ - rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0001f); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ff7); - - /* open PA S1 & SMIXER */ - rtl_set_rfreg(hw, RF90_PATH_A, 0xed, RFREG_OFFSET_MASK, 0x00020); - rtl_set_rfreg(hw, RF90_PATH_A, 0x43, RFREG_OFFSET_MASK, 0x60fed); - - /* IQK setting */ - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00); - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - - /* path-B IQK setting */ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - - rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160ff0); - rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28110000); - rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000); - rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000); - - /* LO calibration setting */ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911); - /* enter IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /* One shot, path B TXIQK @ RXIQK */ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - /* leave IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - /* Check failed */ - reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); - reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD); - reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD); - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && - (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) - result |= 0x01; - else /* if Tx not OK, ignore Rx */ - return result; - - /* Allen 20131125 */ - tmp = (reg_e9c & 0x03FF0000) >> 16; - if ((tmp & 0x200) > 0) - tmp = 0x400 - tmp; - - if (!(reg_eac & BIT(28)) && - (((reg_e94 & 0x03FF0000) >> 16) < 0x110) && - (((reg_e94 & 0x03FF0000) >> 16) > 0xf0) && - (tmp < 0xf)) - result |= 0x01; - else - return result; - - u32tmp = 0x80007C00 | (reg_e94 & 0x3FF0000) | - ((reg_e9c & 0x3FF0000) >> 16); - rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32tmp); - - /* 1 RX IQK */ - - /* <20121009, Kordan> RF Mode = 3 */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, 0x80000, 0x1); - rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0001f); - rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7d77); - rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, 0x80000, 0x0); - - /* open PA S1 & close SMIXER */ - rtl_set_rfreg(hw, RF90_PATH_A, 0xed, RFREG_OFFSET_MASK, 0x00020); - rtl_set_rfreg(hw, RF90_PATH_A, 0x43, RFREG_OFFSET_MASK, 0x60fbd); - - /* IQK setting */ - rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800); - - /* path-B IQK setting */ - rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x18008c1c); - rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c); - - rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82110000); - rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x2816001f); - rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000); - rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000); - - /* LO calibration setting */ - rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a8d1); - /* enter IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000); - - /* One shot, path B LOK & IQK */ - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000); - rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000); - - mdelay(IQK_DELAY_TIME); - - /* leave IQK mode */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000); - /* Check failed */ - reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD); - reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD); - - /* Allen 20131125 */ - tmp = (reg_eac & 0x03FF0000) >> 16; - if ((tmp & 0x200) > 0) - tmp = 0x400 - tmp; - - /* if Tx is OK, check whether Rx is OK */ - if (!(reg_eac & BIT(27)) && - (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && - (((reg_eac & 0x03FF0000) >> 16) != 0x36)) - result |= 0x02; - else if (!(reg_eac & BIT(27)) && - (((reg_ea4 & 0x03FF0000) >> 16) < 0x110) && - (((reg_ea4 & 0x03FF0000) >> 16) > 0xf0) && - (tmp < 0xf)) - result |= 0x02; - else - return result; - - return result; -} - -static void _rtl8723be_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw, - bool b_iqk_ok, - long result[][8], - u8 final_candidate, - bool btxonly) -{ - u32 oldval_1, x, tx1_a, reg; - long y, tx1_c; - - if (final_candidate == 0xFF) { - return; - } else if (b_iqk_ok) { - oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, - MASKDWORD) >> 22) & 0x3FF; - x = result[final_candidate][4]; - if ((x & 0x00000200) != 0) - x = x | 0xFFFFFC00; - tx1_a = (x * oldval_1) >> 8; - rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x3FF, tx1_a); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(27), - ((x * oldval_1 >> 7) & 0x1)); - y = result[final_candidate][5]; - if ((y & 0x00000200) != 0) - y = y | 0xFFFFFC00; - tx1_c = (y * oldval_1) >> 8; - rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000, - ((tx1_c & 0x3C0) >> 6)); - rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000, - (tx1_c & 0x3F)); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(25), - ((y * oldval_1 >> 7) & 0x1)); - if (btxonly) - return; - reg = result[final_candidate][6]; - rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg); - reg = result[final_candidate][7] & 0x3F; - rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg); - reg = (result[final_candidate][7] >> 6) & 0xF; - /* rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); */ - } -} - -static bool _rtl8723be_phy_simularity_compare(struct ieee80211_hw *hw, - long result[][8], u8 c1, u8 c2) -{ - u32 i, j, diff, simularity_bitmap, bound = 0; - - u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */ - bool bresult = true; /* is2t = true*/ - s32 tmp1 = 0, tmp2 = 0; - - bound = 8; - - simularity_bitmap = 0; - - for (i = 0; i < bound; i++) { - if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) { - if ((result[c1][i] & 0x00000200) != 0) - tmp1 = result[c1][i] | 0xFFFFFC00; - else - tmp1 = result[c1][i]; - - if ((result[c2][i] & 0x00000200) != 0) - tmp2 = result[c2][i] | 0xFFFFFC00; - else - tmp2 = result[c2][i]; - } else { - tmp1 = result[c1][i]; - tmp2 = result[c2][i]; - } - - diff = (tmp1 > tmp2) ? (tmp1 - tmp2) : (tmp2 - tmp1); - - if (diff > MAX_TOLERANCE) { - if ((i == 2 || i == 6) && !simularity_bitmap) { - if (result[c1][i] + result[c1][i + 1] == 0) - final_candidate[(i / 4)] = c2; - else if (result[c2][i] + result[c2][i + 1] == 0) - final_candidate[(i / 4)] = c1; - else - simularity_bitmap |= (1 << i); - } else - simularity_bitmap |= (1 << i); - } - } - - if (simularity_bitmap == 0) { - for (i = 0; i < (bound / 4); i++) { - if (final_candidate[i] != 0xFF) { - for (j = i * 4; j < (i + 1) * 4 - 2; j++) - result[3][j] = - result[final_candidate[i]][j]; - bresult = false; - } - } - return bresult; - } else { - if (!(simularity_bitmap & 0x03)) { /* path A TX OK */ - for (i = 0; i < 2; i++) - result[3][i] = result[c1][i]; - } - if (!(simularity_bitmap & 0x0c)) { /* path A RX OK */ - for (i = 2; i < 4; i++) - result[3][i] = result[c1][i]; - } - if (!(simularity_bitmap & 0x30)) { /* path B TX OK */ - for (i = 4; i < 6; i++) - result[3][i] = result[c1][i]; - } - if (!(simularity_bitmap & 0xc0)) { /* path B RX OK */ - for (i = 6; i < 8; i++) - result[3][i] = result[c1][i]; - } - return false; - } -} - -static void _rtl8723be_phy_iq_calibrate(struct ieee80211_hw *hw, - long result[][8], u8 t, bool is2t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 i; - u8 patha_ok, pathb_ok; - u32 adda_reg[IQK_ADDA_REG_NUM] = { - 0x85c, 0xe6c, 0xe70, 0xe74, - 0xe78, 0xe7c, 0xe80, 0xe84, - 0xe88, 0xe8c, 0xed0, 0xed4, - 0xed8, 0xedc, 0xee0, 0xeec - }; - - u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { - 0x522, 0x550, 0x551, 0x040 - }; - u32 iqk_bb_reg[IQK_BB_REG_NUM] = { - ROFDM0_TRXPATHENABLE, ROFDM0_TRMUXPAR, - RFPGA0_XCD_RFINTERFACESW, 0xb68, 0xb6c, - 0x870, 0x860, - 0x864, 0xa04 - }; - const u32 retrycount = 2; - - u32 path_sel_bb;/* path_sel_rf */ - - u8 tmp_reg_c50, tmp_reg_c58; - - tmp_reg_c50 = rtl_get_bbreg(hw, 0xc50, MASKBYTE0); - tmp_reg_c58 = rtl_get_bbreg(hw, 0xc58, MASKBYTE0); - - if (t == 0) { - rtl8723_save_adda_registers(hw, adda_reg, - rtlphy->adda_backup, 16); - rtl8723_phy_save_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - rtl8723_save_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, - IQK_BB_REG_NUM); - } - rtl8723_phy_path_adda_on(hw, adda_reg, true, is2t); - if (t == 0) { - rtlphy->rfpi_enable = (u8)rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER1, - BIT(8)); - } - - path_sel_bb = rtl_get_bbreg(hw, 0x948, MASKDWORD); - - rtl8723_phy_mac_setting_calibration(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - /*BB Setting*/ - rtl_set_bbreg(hw, 0xa04, 0x0f000000, 0xf); - rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); - rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); - rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); - - /* path A TX IQK */ - for (i = 0; i < retrycount; i++) { - patha_ok = _rtl8723be_phy_path_a_iqk(hw); - if (patha_ok == 0x01) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Path A Tx IQK Success!!\n"); - result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & - 0x3FF0000) >> 16; - break; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Path A Tx IQK Fail!!\n"); - } - } - /* path A RX IQK */ - for (i = 0; i < retrycount; i++) { - patha_ok = _rtl8723be_phy_path_a_rx_iqk(hw); - if (patha_ok == 0x03) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Path A Rx IQK Success!!\n"); - result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & - 0x3FF0000) >> 16; - result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & - 0x3FF0000) >> 16; - break; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Path A Rx IQK Fail!!\n"); - } - - if (0x00 == patha_ok) - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Path A IQK Fail!!\n"); - - if (is2t) { - /* path B TX IQK */ - for (i = 0; i < retrycount; i++) { - pathb_ok = _rtl8723be_phy_path_b_iqk(hw); - if (pathb_ok == 0x01) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Path B Tx IQK Success!!\n"); - result[t][4] = (rtl_get_bbreg(hw, 0xe94, - MASKDWORD) & - 0x3FF0000) >> 16; - result[t][5] = (rtl_get_bbreg(hw, 0xe9c, - MASKDWORD) & - 0x3FF0000) >> 16; - break; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Path B Tx IQK Fail!!\n"); - } - /* path B RX IQK */ - for (i = 0; i < retrycount; i++) { - pathb_ok = _rtl8723be_phy_path_b_rx_iqk(hw); - if (pathb_ok == 0x03) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Path B Rx IQK Success!!\n"); - result[t][6] = (rtl_get_bbreg(hw, 0xea4, - MASKDWORD) & - 0x3FF0000) >> 16; - result[t][7] = (rtl_get_bbreg(hw, 0xeac, - MASKDWORD) & - 0x3FF0000) >> 16; - break; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Path B Rx IQK Fail!!\n"); - } - } - - /* Back to BB mode, load original value */ - rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0); - - if (t != 0) { - rtl8723_phy_reload_adda_registers(hw, adda_reg, - rtlphy->adda_backup, 16); - rtl8723_phy_reload_mac_registers(hw, iqk_mac_reg, - rtlphy->iqk_mac_backup); - rtl8723_phy_reload_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, - IQK_BB_REG_NUM); - - rtl_set_bbreg(hw, 0x948, MASKDWORD, path_sel_bb); - /*rtl_set_rfreg(hw, RF90_PATH_B, 0xb0, 0xfffff, path_sel_rf);*/ - - rtl_set_bbreg(hw, 0xc50, MASKBYTE0, 0x50); - rtl_set_bbreg(hw, 0xc50, MASKBYTE0, tmp_reg_c50); - if (is2t) { - rtl_set_bbreg(hw, 0xc58, MASKBYTE0, 0x50); - rtl_set_bbreg(hw, 0xc58, MASKBYTE0, tmp_reg_c58); - } - rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00); - rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00); - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "8723be IQK Finish!!\n"); -} - -static u8 _get_right_chnl_place_for_iqk(u8 chnl) -{ - u8 channel_all[TARGET_CHNL_NUM_2G_5G] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 36, 38, 40, 42, 44, 46, - 48, 50, 52, 54, 56, 58, 60, 62, 64, - 100, 102, 104, 106, 108, 110, - 112, 114, 116, 118, 120, 122, - 124, 126, 128, 130, 132, 134, 136, - 138, 140, 149, 151, 153, 155, 157, - 159, 161, 163, 165}; - u8 place = chnl; - - if (chnl > 14) { - for (place = 14; place < sizeof(channel_all); place++) { - if (channel_all[place] == chnl) - return place - 13; - } - } - return 0; -} - -static void _rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) -{ - u8 tmpreg; - u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - tmpreg = rtl_read_byte(rtlpriv, 0xd03); - - if ((tmpreg & 0x70) != 0) - rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); - else - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - - if ((tmpreg & 0x70) != 0) { - rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); - - if (is2t) - rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, - MASK12BITS); - - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, - (rf_a_mode & 0x8FFFF) | 0x10000); - - if (is2t) - rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, - (rf_b_mode & 0x8FFFF) | 0x10000); - } - lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); - - rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, RFREG_OFFSET_MASK, 0xdfbe0); - rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, 0x8c0a); - - /* In order not to disturb BT music when wifi init.(1ant NIC only) */ - /*mdelay(100);*/ - /* In order not to disturb BT music when wifi init.(1ant NIC only) */ - mdelay(50); - - rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, RFREG_OFFSET_MASK, 0xdffe0); - - if ((tmpreg & 0x70) != 0) { - rtl_write_byte(rtlpriv, 0xd03, tmpreg); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); - - if (is2t) - rtl_set_rfreg(hw, RF90_PATH_B, 0x00, - MASK12BITS, rf_b_mode); - } else { - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - } -RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); - -} - -static void _rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw *hw, - bool bmain, bool is2t) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); - - if (bmain) /* left antenna */ - rtl_set_bbreg(hw, 0x92C, MASKDWORD, 0x1); - else - rtl_set_bbreg(hw, 0x92C, MASKDWORD, 0x2); -} - -#undef IQK_ADDA_REG_NUM -#undef IQK_DELAY_TIME -/* IQK is merge from Merge Temp */ -void rtl8723be_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - long result[4][8]; - u8 i, final_candidate, idx; - bool b_patha_ok, b_pathb_ok; - long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4; - long reg_ecc, reg_tmp = 0; - bool is12simular, is13simular, is23simular; - u32 iqk_bb_reg[9] = { - ROFDM0_XARXIQIMBALANCE, - ROFDM0_XBRXIQIMBALANCE, - ROFDM0_ECCATHRESHOLD, - ROFDM0_AGCRSSITABLE, - ROFDM0_XATXIQIMBALANCE, - ROFDM0_XBTXIQIMBALANCE, - ROFDM0_XCTXAFE, - ROFDM0_XDTXAFE, - ROFDM0_RXIQEXTANTA - }; - u32 path_sel_bb = 0; /* path_sel_rf = 0 */ - - if (rtlphy->lck_inprogress) - return; - - spin_lock(&rtlpriv->locks.iqk_lock); - rtlphy->lck_inprogress = true; - spin_unlock(&rtlpriv->locks.iqk_lock); - - if (b_recovery) { - rtl8723_phy_reload_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, 9); - return; - } - /* Save RF Path */ - path_sel_bb = rtl_get_bbreg(hw, 0x948, MASKDWORD); - /* path_sel_rf = rtl_get_rfreg(hw, RF90_PATH_A, 0xb0, 0xfffff); */ - - for (i = 0; i < 8; i++) { - result[0][i] = 0; - result[1][i] = 0; - result[2][i] = 0; - result[3][i] = 0; - } - final_candidate = 0xff; - b_patha_ok = false; - b_pathb_ok = false; - is12simular = false; - is23simular = false; - is13simular = false; - for (i = 0; i < 3; i++) { - _rtl8723be_phy_iq_calibrate(hw, result, i, true); - if (i == 1) { - is12simular = _rtl8723be_phy_simularity_compare(hw, - result, - 0, 1); - if (is12simular) { - final_candidate = 0; - break; - } - } - if (i == 2) { - is13simular = _rtl8723be_phy_simularity_compare(hw, - result, - 0, 2); - if (is13simular) { - final_candidate = 0; - break; - } - is23simular = _rtl8723be_phy_simularity_compare(hw, - result, - 1, 2); - if (is23simular) { - final_candidate = 1; - } else { - for (i = 0; i < 8; i++) - reg_tmp += result[3][i]; - - if (reg_tmp != 0) - final_candidate = 3; - else - final_candidate = 0xFF; - } - } - } - for (i = 0; i < 4; i++) { - reg_e94 = result[i][0]; - reg_e9c = result[i][1]; - reg_ea4 = result[i][2]; - reg_eac = result[i][3]; - reg_eb4 = result[i][4]; - reg_ebc = result[i][5]; - reg_ec4 = result[i][6]; - reg_ecc = result[i][7]; - } - if (final_candidate != 0xff) { - reg_e94 = result[final_candidate][0]; - rtlphy->reg_e94 = reg_e94; - reg_e9c = result[final_candidate][1]; - rtlphy->reg_e9c = reg_e9c; - reg_ea4 = result[final_candidate][2]; - reg_eac = result[final_candidate][3]; - reg_eb4 = result[final_candidate][4]; - rtlphy->reg_eb4 = reg_eb4; - reg_ebc = result[final_candidate][5]; - rtlphy->reg_ebc = reg_ebc; - reg_ec4 = result[final_candidate][6]; - reg_ecc = result[final_candidate][7]; - b_patha_ok = true; - b_pathb_ok = true; - } else { - rtlphy->reg_e94 = 0x100; - rtlphy->reg_eb4 = 0x100; - rtlphy->reg_e9c = 0x0; - rtlphy->reg_ebc = 0x0; - } - if (reg_e94 != 0) - rtl8723_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result, - final_candidate, - (reg_ea4 == 0)); - if (reg_eb4 != 0) - _rtl8723be_phy_path_b_fill_iqk_matrix(hw, b_pathb_ok, result, - final_candidate, - (reg_ec4 == 0)); - - idx = _get_right_chnl_place_for_iqk(rtlphy->current_channel); - - if (final_candidate < 4) { - for (i = 0; i < IQK_MATRIX_REG_NUM; i++) - rtlphy->iqk_matrix[idx].value[0][i] = - result[final_candidate][i]; - rtlphy->iqk_matrix[idx].iqk_done = true; - - } - rtl8723_save_adda_registers(hw, iqk_bb_reg, - rtlphy->iqk_bb_backup, 9); - - rtl_set_bbreg(hw, 0x948, MASKDWORD, path_sel_bb); - /* rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, 0xfffff, path_sel_rf); */ - - spin_lock(&rtlpriv->locks.iqk_lock); - rtlphy->lck_inprogress = false; - spin_unlock(&rtlpriv->locks.iqk_lock); -} - -void rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = &rtlpriv->rtlhal; - u32 timeout = 2000, timecount = 0; - - while (rtlpriv->mac80211.act_scanning && timecount < timeout) { - udelay(50); - timecount += 50; - } - - rtlphy->lck_inprogress = true; - RTPRINT(rtlpriv, FINIT, INIT_IQK, - "LCK:Start!!! currentband %x delay %d ms\n", - rtlhal->current_bandtype, timecount); - - _rtl8723be_phy_lc_calibrate(hw, false); - - rtlphy->lck_inprogress = false; -} - -void rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) -{ - _rtl8723be_phy_set_rfpath_switch(hw, bmain, true); -} - -bool rtl8723be_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - bool b_postprocessing = false; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "-->IO Cmd(%#x), set_io_inprogress(%d)\n", - iotype, rtlphy->set_io_inprogress); - do { - switch (iotype) { - case IO_CMD_RESUME_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Resume DM after scan.\n"); - b_postprocessing = true; - break; - case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Pause DM before scan.\n"); - b_postprocessing = true; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - } while (false); - if (b_postprocessing && !rtlphy->set_io_inprogress) { - rtlphy->set_io_inprogress = true; - rtlphy->current_io_type = iotype; - } else { - return false; - } - rtl8723be_phy_set_io(hw); - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); - return true; -} - -static void rtl8723be_phy_set_io(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - struct rtl_phy *rtlphy = &rtlpriv->phy; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "--->Cmd(%#x), set_io_inprogress(%d)\n", - rtlphy->current_io_type, rtlphy->set_io_inprogress); - switch (rtlphy->current_io_type) { - case IO_CMD_RESUME_DM_BY_SCAN: - dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; - /*rtl92c_dm_write_dig(hw);*/ - rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel); - rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x83); - break; - case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: - rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; - dm_digtable->cur_igvalue = 0x17; - rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x40); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - rtlphy->set_io_inprogress = false; - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "(%#x)\n", rtlphy->current_io_type); -} - -static void rtl8723be_phy_set_rf_on(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); -} - -static void _rtl8723be_phy_set_rf_sleep(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); -} - -static bool _rtl8723be_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool bresult = true; - u8 i, queue_id; - struct rtl8192_tx_ring *ring = NULL; - - switch (rfpwr_state) { - case ERFON: - if ((ppsc->rfpwr_state == ERFOFF) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { - bool rtstatus; - u32 initializecount = 0; - do { - initializecount++; - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic enable\n"); - rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && (initializecount < 10)); - RT_CLEAR_PS_LEVEL(ppsc, - RT_RF_OFF_LEVL_HALT_NIC); - } else { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFON sleeped:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc->last_sleep_jiffies)); - ppsc->last_awake_jiffies = jiffies; - rtl8723be_phy_set_rf_on(hw); - } - if (mac->link_state == MAC80211_LINKED) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_LINK); - else - rtlpriv->cfg->ops->led_control(hw, LED_CTL_NO_LINK); - - break; - - case ERFOFF: - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - /* Don't check BEACON Q. - * BEACON Q is always not empty, - * because '_rtl8723be_cmd_send_packet' - */ - if (queue_id == BEACON_QUEUE || - skb_queue_len(&ring->queue) == 0) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", - (i + 1), queue_id, - skb_queue_len(&ring->queue)); - - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic disable\n"); - rtl_ps_disable_nic(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - } else { - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - } else { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_POWER_OFF); - } - } - break; - - case ERFSLEEP: - if (ppsc->rfpwr_state == ERFOFF) - break; - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (skb_queue_len(&ring->queue) == 0) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", - (i + 1), queue_id, - skb_queue_len(&ring->queue)); - - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFSLEEP awaked:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc->last_awake_jiffies)); - ppsc->last_sleep_jiffies = jiffies; - _rtl8723be_phy_set_rf_sleep(hw); - break; - - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - bresult = false; - break; - } - if (bresult) - ppsc->rfpwr_state = rfpwr_state; - return bresult; -} - -bool rtl8723be_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - bool bresult = false; - - if (rfpwr_state == ppsc->rfpwr_state) - return bresult; - bresult = _rtl8723be_phy_set_rf_power_state(hw, rfpwr_state); - return bresult; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/phy.h b/drivers/net/wireless/rtlwifi/rtl8723be/phy.h deleted file mode 100644 index 9021d4745ab7..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/phy.h +++ /dev/null @@ -1,135 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723BE_PHY_H__ -#define __RTL8723BE_PHY_H__ - -/* MAX_TX_COUNT must always set to 4, otherwise read efuse table sequence - * will be wrong. - */ -#define MAX_TX_COUNT 4 -#define TX_1S 0 -#define TX_2S 1 -#define TX_3S 2 -#define TX_4S 3 - -#define MAX_POWER_INDEX 0x3F - -#define MAX_PRECMD_CNT 16 -#define MAX_RFDEPENDCMD_CNT 16 -#define MAX_POSTCMD_CNT 16 - -#define MAX_DOZE_WAITING_TIMES_9x 64 - -#define RT_CANNOT_IO(hw) false -#define HIGHPOWER_RADIOA_ARRAYLEN 22 - -#define TARGET_CHNL_NUM_2G_5G 59 - -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM 9 -#define MAX_TOLERANCE 5 -#define IQK_DELAY_TIME 10 -#define index_mapping_NUM 15 - -#define APK_BB_REG_NUM 5 -#define APK_AFE_REG_NUM 16 -#define APK_CURVE_REG_NUM 4 -#define PATH_NUM 1 - -#define LOOP_LIMIT 5 -#define MAX_STALL_TIME 50 -#define ANTENNADIVERSITYVALUE 0x80 -#define MAX_TXPWR_IDX_NMODE_92S 63 -#define RESET_CNT_LIMIT 3 - -#define IQK_ADDA_REG_NUM 16 -#define IQK_MAC_REG_NUM 4 - -#define RF6052_MAX_PATH 2 - -#define CT_OFFSET_MAC_ADDR 0X16 - -#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A -#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 -#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 -#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 -#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C - -#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F -#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 - -#define CT_OFFSET_CHANNEL_PLAH 0x75 -#define CT_OFFSET_THERMAL_METER 0x78 -#define CT_OFFSET_RF_OPTION 0x79 -#define CT_OFFSET_VERSION 0x7E -#define CT_OFFSET_CUSTOMER_ID 0x7F - -#define RTL92C_MAX_PATH_NUM 2 - -enum baseband_config_type { - BASEBAND_CONFIG_PHY_REG = 0, - BASEBAND_CONFIG_AGC_TAB = 1, -}; - -enum ant_div_type { - NO_ANTDIV = 0xFF, - CG_TRX_HW_ANTDIV = 0x01, - CGCS_RX_HW_ANTDIV = 0x02, - FIXED_HW_ANTDIV = 0x03, - CG_TRX_SMART_ANTDIV = 0x04, - CGCS_RX_SW_ANTDIV = 0x05, - -}; - -u32 rtl8723be_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask); -void rtl8723be_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data); -bool rtl8723be_phy_mac_config(struct ieee80211_hw *hw); -bool rtl8723be_phy_bb_config(struct ieee80211_hw *hw); -bool rtl8723be_phy_rf_config(struct ieee80211_hw *hw); -void rtl8723be_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -void rtl8723be_phy_set_txpower_level(struct ieee80211_hw *hw, - u8 channel); -void rtl8723be_phy_scan_operation_backup(struct ieee80211_hw *hw, - u8 operation); -void rtl8723be_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -void rtl8723be_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); -void rtl8723be_phy_sw_chnl_callback(struct ieee80211_hw *hw); -u8 rtl8723be_phy_sw_chnl(struct ieee80211_hw *hw); -void rtl8723be_phy_iq_calibrate(struct ieee80211_hw *hw, - bool b_recovery); -void rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw); -void rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); -bool rtl8723be_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -bool rtl8723be_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); -bool rtl8723be_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.c b/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.c deleted file mode 100644 index a1bb1f6116fb..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.c +++ /dev/null @@ -1,106 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../pwrseqcmd.h" -#include "pwrseq.h" - - -/* drivers should parse below arrays and do the corresponding actions */ -/*3 Power on Array*/ -struct wlan_pwr_cfg rtl8723B_power_on_flow[RTL8723B_TRANS_CARDEMU_TO_ACT_STEPS + - RTL8723B_TRANS_END_STEPS] = { - RTL8723B_TRANS_CARDEMU_TO_ACT - RTL8723B_TRANS_END -}; - -/*3Radio off GPIO Array */ -struct wlan_pwr_cfg rtl8723B_radio_off_flow[RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8723B_TRANS_END_STEPS] = { - RTL8723B_TRANS_ACT_TO_CARDEMU - RTL8723B_TRANS_END -}; - -/*3Card Disable Array*/ -struct wlan_pwr_cfg rtl8723B_card_disable_flow - [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8723B_TRANS_END_STEPS] = { - RTL8723B_TRANS_ACT_TO_CARDEMU - RTL8723B_TRANS_CARDEMU_TO_CARDDIS - RTL8723B_TRANS_END -}; - -/*3 Card Enable Array*/ -struct wlan_pwr_cfg rtl8723B_card_enable_flow - [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8723B_TRANS_END_STEPS] = { - RTL8723B_TRANS_CARDDIS_TO_CARDEMU - RTL8723B_TRANS_CARDEMU_TO_ACT - RTL8723B_TRANS_END -}; - -/*3Suspend Array*/ -struct wlan_pwr_cfg rtl8723B_suspend_flow[RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8723B_TRANS_END_STEPS] = { - RTL8723B_TRANS_ACT_TO_CARDEMU - RTL8723B_TRANS_CARDEMU_TO_SUS - RTL8723B_TRANS_END -}; - -/*3 Resume Array*/ -struct wlan_pwr_cfg rtl8723B_resume_flow[RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8723B_TRANS_END_STEPS] = { - RTL8723B_TRANS_SUS_TO_CARDEMU - RTL8723B_TRANS_CARDEMU_TO_ACT - RTL8723B_TRANS_END -}; - -/*3HWPDN Array*/ -struct wlan_pwr_cfg rtl8723B_hwpdn_flow[RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8723B_TRANS_END_STEPS] = { - RTL8723B_TRANS_ACT_TO_CARDEMU - RTL8723B_TRANS_CARDEMU_TO_PDN - RTL8723B_TRANS_END -}; - -/*3 Enter LPS */ -struct wlan_pwr_cfg rtl8723B_enter_lps_flow[RTL8723B_TRANS_ACT_TO_LPS_STEPS + - RTL8723B_TRANS_END_STEPS] = { - /*FW behavior*/ - RTL8723B_TRANS_ACT_TO_LPS - RTL8723B_TRANS_END -}; - -/*3 Leave LPS */ -struct wlan_pwr_cfg rtl8723B_leave_lps_flow[RTL8723B_TRANS_LPS_TO_ACT_STEPS + - RTL8723B_TRANS_END_STEPS] = { - /*FW behavior*/ - RTL8723B_TRANS_LPS_TO_ACT - RTL8723B_TRANS_END -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.h b/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.h deleted file mode 100644 index 0fee5e0e55c2..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/pwrseq.h +++ /dev/null @@ -1,423 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723BE_PWRSEQ_H__ -#define __RTL8723BE_PWRSEQ_H__ - -#include "../pwrseqcmd.h" -/** - * Check document WM-20130425-JackieLau-RTL8723B_Power_Architecture v05.vsd - * There are 6 HW Power States: - * 0: POFF--Power Off - * 1: PDN--Power Down - * 2: CARDEMU--Card Emulation - * 3: ACT--Active Mode - * 4: LPS--Low Power State - * 5: SUS--Suspend - * - * The transision from different states are defined below - * TRANS_CARDEMU_TO_ACT - * TRANS_ACT_TO_CARDEMU - * TRANS_CARDEMU_TO_SUS - * TRANS_SUS_TO_CARDEMU - * TRANS_CARDEMU_TO_PDN - * TRANS_ACT_TO_LPS - * TRANS_LPS_TO_ACT - * - * TRANS_END - */ -#define RTL8723B_TRANS_CARDEMU_TO_ACT_STEPS 23 -#define RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS 15 -#define RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS 15 -#define RTL8723B_TRANS_SUS_TO_CARDEMU_STEPS 15 -#define RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS 15 -#define RTL8723B_TRANS_PDN_TO_CARDEMU_STEPS 15 -#define RTL8723B_TRANS_ACT_TO_LPS_STEPS 15 -#define RTL8723B_TRANS_LPS_TO_ACT_STEPS 15 -#define RTL8723B_TRANS_END_STEPS 1 - -#define RTL8723B_TRANS_CARDEMU_TO_ACT \ - /* format */ \ - /* comments here */ \ - /* {offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value}, */\ - /*0x20[0] = 1b'1 enable LDOA12 MACRO block for all interface*/ \ - {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ - /*0x67[0] = 0 to disable BT_GPS_SEL pins*/ \ - {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ - /*Delay 1ms*/ \ - {0x0001, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_DELAY, 1, PWRSEQ_DELAY_MS}, \ - /*0x00[5] = 1b'0 release analog Ips to digital ,1:isolation*/ \ - {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), 0}, \ - /* disable SW LPS 0x04[10]=0 and WLSUS_EN 0x04[11]=0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT(4)|BIT(3)|BIT(2)), 0}, \ - /* Disable USB suspend */ \ - {0x0075, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0) , BIT(0)}, \ - /* wait till 0x04[17] = 1 power ready*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), BIT(1)}, \ - /* Enable USB suspend */ \ - {0x0075, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0) , 0}, \ - /* release WLON reset 0x04[16]=1*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ - /* disable HWPDN 0x04[15]=0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}, \ - /* disable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT(4)|BIT(3)), 0}, \ - /* polling until return 0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(0), 0}, \ - /* Enable WL control XTAL setting*/ \ - {0x0010, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6), BIT(6)}, \ - /*Enable falling edge triggering interrupt*/ \ - {0x0049, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ - /*Enable GPIO9 interrupt mode*/ \ - {0x0063, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ - /*Enable GPIO9 input mode*/ \ - {0x0062, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \ - /*Enable HSISR GPIO[C:0] interrupt*/ \ - {0x0058, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ - /*Enable HSISR GPIO9 interrupt*/ \ - {0x005A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ - /*For GPIO9 internal pull high setting by test chip*/ \ - {0x0068, PWR_CUT_TESTCHIP_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3), BIT(3)}, \ - /*For GPIO9 internal pull high setting*/ \ - {0x0069, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6), BIT(6)}, - -#define RTL8723B_TRANS_ACT_TO_CARDEMU \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ - /*0x1F[7:0] = 0 turn off RF*/ \ - {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, \ - /*0x4C[24] = 0x4F[0] = 0, */ \ - /*switch DPDT_SEL_P output from register 0x65[2] */ \ - {0x004F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \ - /*Enable rising edge triggering interrupt*/ \ - {0x0049, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \ - /*0x04[9] = 1 turn off MAC by HW state machine*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ - /*wait till 0x04[9] = 0 polling until return 0 to disable*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(1), 0}, \ - /* Enable BT control XTAL setting*/ \ - {0x0010, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6), 0}, \ - /*0x00[5] = 1b'1 analog Ips to digital ,1:isolation*/ \ - {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \ - PWR_CMD_WRITE, BIT(5), BIT(5)}, \ - /*0x20[0] = 1b'0 disable LDOA12 MACRO block*/ \ - {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \ - PWR_CMD_WRITE, BIT(0), 0}, - -#define RTL8723B_TRANS_CARDEMU_TO_SUS \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value },*/\ - /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4) | BIT(3), (BIT(4) | BIT(3))}, \ - /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, PWR_BASEADDR_MAC, \ - PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)}, \ - /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \ - /*0x07[7:0] = 0x20 SDIO SOP option to disable BG/MB/ACK/SWR*/ \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, \ - /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3) | BIT(4)},\ - /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ - /*wait power state to suspend*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, - -#define RTL8723B_TRANS_SUS_TO_CARDEMU \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ - /*clear suspend enable and power down enable*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, \ - /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, \ - /*wait power state to suspend*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, \ - /*0x23[4] = 1b'0 12H LDO enter normal mode*/ \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ - /*0x04[12:11] = 2b'01enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, - -#define RTL8723B_TRANS_CARDEMU_TO_CARDDIS \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ - /*0x07=0x20 , SOP option to disable BG/MB*/ \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20}, \ - /*0x04[12:11] = 2b'01 enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK | PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), BIT(3)}, \ - /*0x04[10] = 1, enable SW LPS*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(2), BIT(2)}, \ - /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/ \ - {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 1}, \ - /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \ - /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), BIT(0)}, \ - /*wait power state to suspend*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), 0}, - -#define RTL8723B_TRANS_CARDDIS_TO_CARDEMU \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ - /*clear suspend enable and power down enable*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(7), 0}, \ - /*Set SDIO suspend local register*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT(0), 0}, \ - /*wait power state to suspend*/ \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)}, \ - /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ \ - {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \ - /*0x04[12:11] = 2b'01enable WL suspend*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, \ - /*0x23[4] = 1b'0 12H LDO enter normal mode*/ \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ - /*PCIe DMA start*/ \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, - -#define RTL8723B_TRANS_CARDEMU_TO_PDN \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ - /*0x23[4] = 1b'1 12H LDO enter sleep mode*/ \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), BIT(4)}, \ - /*0x07[7:0] = 0x20 SOP option to disable BG/MB/ACK/SWR*/ \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_SDIO_MSK | PWR_INTF_USB_MSK, PWR_BASEADDR_MAC, \ - PWR_CMD_WRITE, 0xFF, 0x20}, \ - /* 0x04[16] = 0*/ \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \ - /* 0x04[15] = 1*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), BIT(7)}, - -#define RTL8723B_TRANS_PDN_TO_CARDEMU \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ - /* 0x04[15] = 0*/ \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(7), 0}, - -#define RTL8723B_TRANS_ACT_TO_LPS \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ - /*PCIe DMA stop*/ \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, \ - /*Tx Pause*/ \ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, \ - /*Should be zero if no packet is transmitting*/ \ - {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ - /*Should be zero if no packet is transmitting*/ \ - {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ - /*Should be zero if no packet is transmitting*/ \ - {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ - /*Should be zero if no packet is transmitting*/ \ - {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0}, \ - /*CCK and OFDM are disabled,and clock are gated*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \ - /*Delay 1us*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US}, \ - /*Whole BB is reset*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \ - /*Reset MAC TRX*/ \ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x03}, \ - /*check if removed later*/ \ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), 0}, \ - /*When driver enter Sus/ Disable, enable LOP for BT*/ \ - {0x0093, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00}, \ - /*Respond TxOK to scheduler*/ \ - {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(5), BIT(5)}, - -#define RTL8723B_TRANS_LPS_TO_ACT \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ - /*SDIO RPWM*/ \ - {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84}, \ - /*USB RPWM*/ \ - {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, \ - /*PCIe RPWM*/ \ - {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84}, \ - /*Delay*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS}, \ - /*. 0x08[4] = 0 switch TSF to 40M*/ \ - {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ - /*Polling 0x109[7]=0 TSF in 40M*/ \ - {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT(7), 0}, \ - /*. 0x29[7:6] = 2b'00 enable BB clock*/ \ - {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(6)|BIT(7), 0}, \ - /*. 0x101[1] = 1*/ \ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1), BIT(1)}, \ - /*. 0x100[7:0] = 0xFF enable WMAC TRX*/ \ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF}, \ - /*. 0x02[1:0] = 2b'11 enable BB macro*/ \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(1) | BIT(0), BIT(1) | BIT(0)}, \ - /*. 0x522 = 0*/ \ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0}, - -#define RTL8723B_TRANS_END \ - /* format */ \ - /* comments here */ \ - /* { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value }, */\ - {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, 0, \ - PWR_CMD_END, 0, 0}, - -extern struct wlan_pwr_cfg rtl8723B_power_on_flow - [RTL8723B_TRANS_CARDEMU_TO_ACT_STEPS + - RTL8723B_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723B_radio_off_flow - [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723B_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723B_card_disable_flow - [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8723B_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723B_card_enable_flow - [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8723B_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723B_suspend_flow - [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8723B_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723B_resume_flow - [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723B_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8723B_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723B_hwpdn_flow - [RTL8723B_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8723B_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8723B_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723B_enter_lps_flow - [RTL8723B_TRANS_ACT_TO_LPS_STEPS + - RTL8723B_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8723B_leave_lps_flow - [RTL8723B_TRANS_LPS_TO_ACT_STEPS + - RTL8723B_TRANS_END_STEPS]; - -/* RTL8723 Power Configuration CMDs for PCIe interface */ -#define RTL8723_NIC_PWR_ON_FLOW rtl8723B_power_on_flow -#define RTL8723_NIC_RF_OFF_FLOW rtl8723B_radio_off_flow -#define RTL8723_NIC_DISABLE_FLOW rtl8723B_card_disable_flow -#define RTL8723_NIC_ENABLE_FLOW rtl8723B_card_enable_flow -#define RTL8723_NIC_SUSPEND_FLOW rtl8723B_suspend_flow -#define RTL8723_NIC_RESUME_FLOW rtl8723B_resume_flow -#define RTL8723_NIC_PDN_FLOW rtl8723B_hwpdn_flow -#define RTL8723_NIC_LPS_ENTER_FLOW rtl8723B_enter_lps_flow -#define RTL8723_NIC_LPS_LEAVE_FLOW rtl8723B_leave_lps_flow - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/reg.h b/drivers/net/wireless/rtlwifi/rtl8723be/reg.h deleted file mode 100644 index 03581d2a5da0..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/reg.h +++ /dev/null @@ -1,2295 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723BE_REG_H__ -#define __RTL8723BE_REG_H__ - -#define TXPKT_BUF_SELECT 0x69 -#define RXPKT_BUF_SELECT 0xA5 -#define DISABLE_TRXPKT_BUF_ACCESS 0x0 - -#define REG_SYS_ISO_CTRL 0x0000 -#define REG_SYS_FUNC_EN 0x0002 -#define REG_APS_FSMCO 0x0004 -#define REG_SYS_CLKR 0x0008 -#define REG_9346CR 0x000A -#define REG_EE_VPD 0x000C -#define REG_AFE_MISC 0x0010 -#define REG_SPS0_CTRL 0x0011 -#define REG_SPS_OCP_CFG 0x0018 -#define REG_RSV_CTRL 0x001C -#define REG_RF_CTRL 0x001F -#define REG_LDOA15_CTRL 0x0020 -#define REG_LDOV12D_CTRL 0x0021 -#define REG_LDOHCI12_CTRL 0x0022 -#define REG_LPLDO_CTRL 0x0023 -#define REG_AFE_XTAL_CTRL 0x0024 -/* 1.5v for 8188EE test chip, 1.4v for MP chip */ -#define REG_AFE_LDO_CTRL 0x0027 -#define REG_AFE_PLL_CTRL 0x0028 -#define REG_MAC_PHY_CTRL 0x002c -#define REG_EFUSE_CTRL 0x0030 -#define REG_EFUSE_TEST 0x0034 -#define REG_PWR_DATA 0x0038 -#define REG_CAL_TIMER 0x003C -#define REG_ACLK_MON 0x003E -#define REG_GPIO_MUXCFG 0x0040 -#define REG_GPIO_IO_SEL 0x0042 -#define REG_MAC_PINMUX_CFG 0x0043 -#define REG_GPIO_PIN_CTRL 0x0044 -#define REG_GPIO_INTM 0x0048 -#define REG_LEDCFG0 0x004C -#define REG_LEDCFG1 0x004D -#define REG_LEDCFG2 0x004E -#define REG_LEDCFG3 0x004F -#define REG_FSIMR 0x0050 -#define REG_FSISR 0x0054 -#define REG_HSIMR 0x0058 -#define REG_HSISR 0x005c -#define REG_GPIO_PIN_CTRL_2 0x0060 -#define REG_GPIO_IO_SEL_2 0x0062 -#define REG_MULTI_FUNC_CTRL 0x0068 -#define REG_GPIO_OUTPUT 0x006c -#define REG_AFE_XTAL_CTRL_EXT 0x0078 -#define REG_XCK_OUT_CTRL 0x007c -#define REG_MCUFWDL 0x0080 -#define REG_WOL_EVENT 0x0081 -#define REG_MCUTSTCFG 0x0084 - -#define REG_HIMR 0x00B0 -#define REG_HISR 0x00B4 -#define REG_HIMRE 0x00B8 -#define REG_HISRE 0x00BC -#define REG_PMC_DBG_CTRL2 0x00CC - -#define REG_EFUSE_ACCESS 0x00CF - -#define REG_BIST_SCAN 0x00D0 -#define REG_BIST_RPT 0x00D4 -#define REG_BIST_ROM_RPT 0x00D8 -#define REG_USB_SIE_INTF 0x00E0 -#define REG_PCIE_MIO_INTF 0x00E4 -#define REG_PCIE_MIO_INTD 0x00E8 -#define REG_HPON_FSM 0x00EC -#define REG_SYS_CFG 0x00F0 -#define REG_GPIO_OUTSTS 0x00F4 -#define REG_MAC_PHY_CTRL_NORMAL 0x00F8 -#define REG_SYS_CFG1 0x00FC -#define REG_ROM_VERSION 0x00FD - -#define REG_CR 0x0100 -#define REG_PBP 0x0104 -#define REG_PKT_BUFF_ACCESS_CTRL 0x0106 -#define REG_TRXDMA_CTRL 0x010C -#define REG_TRXFF_BNDY 0x0114 -#define REG_TRXFF_STATUS 0x0118 -#define REG_RXFF_PTR 0x011C - -#define REG_CPWM 0x012F -#define REG_FWIMR 0x0130 -#define REG_FWISR 0x0134 -#define REG_PKTBUF_DBG_CTRL 0x0140 -#define REG_PKTBUF_DBG_DATA_L 0x0144 -#define REG_PKTBUF_DBG_DATA_H 0x0148 -#define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL + 2) - -#define REG_TC0_CTRL 0x0150 -#define REG_TC1_CTRL 0x0154 -#define REG_TC2_CTRL 0x0158 -#define REG_TC3_CTRL 0x015C -#define REG_TC4_CTRL 0x0160 -#define REG_TCUNIT_BASE 0x0164 -#define REG_MBIST_START 0x0174 -#define REG_MBIST_DONE 0x0178 -#define REG_MBIST_FAIL 0x017C -#define REG_32K_CTRL 0x0194 -#define REG_C2HEVT_MSG_NORMAL 0x01A0 -#define REG_C2HEVT_CLEAR 0x01AF -#define REG_C2HEVT_MSG_TEST 0x01B8 -#define REG_MCUTST_1 0x01c0 -#define REG_FMETHR 0x01C8 -#define REG_HMETFR 0x01CC -#define REG_HMEBOX_0 0x01D0 -#define REG_HMEBOX_1 0x01D4 -#define REG_HMEBOX_2 0x01D8 -#define REG_HMEBOX_3 0x01DC - -#define REG_LLT_INIT 0x01E0 -#define REG_BB_ACCEESS_CTRL 0x01E8 -#define REG_BB_ACCESS_DATA 0x01EC - -#define REG_HMEBOX_EXT_0 0x01F0 -#define REG_HMEBOX_EXT_1 0x01F4 -#define REG_HMEBOX_EXT_2 0x01F8 -#define REG_HMEBOX_EXT_3 0x01FC - -#define REG_RQPN 0x0200 -#define REG_FIFOPAGE 0x0204 -#define REG_TDECTRL 0x0208 -#define REG_TXDMA_OFFSET_CHK 0x020C -#define REG_TXDMA_STATUS 0x0210 -#define REG_RQPN_NPQ 0x0214 - -#define REG_RXDMA_AGG_PG_TH 0x0280 -/* FW shall update this register before FW write RXPKT_RELEASE_POLL to 1 */ -#define REG_FW_UPD_RDPTR 0x0284 -/* Control the RX DMA.*/ -#define REG_RXDMA_CONTROL 0x0286 -/* The number of packets in RXPKTBUF. */ -#define REG_RXPKT_NUM 0x0287 - -#define REG_PCIE_CTRL_REG 0x0300 -#define REG_INT_MIG 0x0304 -#define REG_BCNQ_DESA 0x0308 -#define REG_HQ_DESA 0x0310 -#define REG_MGQ_DESA 0x0318 -#define REG_VOQ_DESA 0x0320 -#define REG_VIQ_DESA 0x0328 -#define REG_BEQ_DESA 0x0330 -#define REG_BKQ_DESA 0x0338 -#define REG_RX_DESA 0x0340 - -#define REG_DBI_WDATA 0x0348 -#define REG_DBI_RDATA 0x034C -#define REG_DBI_CTRL 0x0350 -#define REG_DBI_ADDR 0x0350 -#define REG_DBI_FLAG 0x0352 -#define REG_MDIO_WDATA 0x0354 -#define REG_MDIO_RDATA 0x0356 -#define REG_MDIO_CTL 0x0358 -#define REG_DBG_SEL 0x0360 -#define REG_PCIE_HRPWM 0x0361 -#define REG_PCIE_HCPWM 0x0363 -#define REG_UART_CTRL 0x0364 -#define REG_WATCH_DOG 0x0368 -#define REG_UART_TX_DESA 0x0370 -#define REG_UART_RX_DESA 0x0378 - -#define REG_HDAQ_DESA_NODEF 0x0000 -#define REG_CMDQ_DESA_NODEF 0x0000 - -#define REG_VOQ_INFORMATION 0x0400 -#define REG_VIQ_INFORMATION 0x0404 -#define REG_BEQ_INFORMATION 0x0408 -#define REG_BKQ_INFORMATION 0x040C -#define REG_MGQ_INFORMATION 0x0410 -#define REG_HGQ_INFORMATION 0x0414 -#define REG_BCNQ_INFORMATION 0x0418 -#define REG_TXPKT_EMPTY 0x041A - -#define REG_CPU_MGQ_INFORMATION 0x041C -#define REG_FWHW_TXQ_CTRL 0x0420 -#define REG_HWSEQ_CTRL 0x0423 -#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 -#define REG_TXPKTBUF_MGQ_BDNY 0x0425 -#define REG_MULTI_BCNQ_EN 0x0426 -#define REG_MULTI_BCNQ_OFFSET 0x0427 -#define REG_SPEC_SIFS 0x0428 -#define REG_RL 0x042A -#define REG_DARFRC 0x0430 -#define REG_RARFRC 0x0438 -#define REG_RRSR 0x0440 -#define REG_ARFR0 0x0444 -#define REG_ARFR1 0x044C -#define REG_AMPDU_MAX_TIME 0x0456 -#define REG_AGGLEN_LMT 0x0458 -#define REG_AMPDU_MIN_SPACE 0x045C -#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D -#define REG_FAST_EDCA_CTRL 0x0460 -#define REG_RD_RESP_PKT_TH 0x0463 -#define REG_INIRTS_RATE_SEL 0x0480 -#define REG_INIDATA_RATE_SEL 0x0484 -#define REG_POWER_STATUS 0x04A4 -#define REG_POWER_STAGE1 0x04B4 -#define REG_POWER_STAGE2 0x04B8 -#define REG_PKT_LIFE_TIME 0x04C0 -#define REG_STBC_SETTING 0x04C4 -#define REG_HT_SINGLE_AMPDU 0x04C7 - -#define REG_PROT_MODE_CTRL 0x04C8 -#define REG_MAX_AGGR_NUM 0x04CA -#define REG_BAR_MODE_CTRL 0x04CC -#define REG_RA_TRY_RATE_AGG_LMT 0x04CF -#define REG_EARLY_MODE_CONTROL 0x04D0 -#define REG_NQOS_SEQ 0x04DC -#define REG_QOS_SEQ 0x04DE -#define REG_NEED_CPU_HANDLE 0x04E0 -#define REG_PKT_LOSE_RPT 0x04E1 -#define REG_PTCL_ERR_STATUS 0x04E2 -#define REG_TX_RPT_CTRL 0x04EC -#define REG_TX_RPT_TIME 0x04F0 -#define REG_DUMMY 0x04FC - -#define REG_EDCA_VO_PARAM 0x0500 -#define REG_EDCA_VI_PARAM 0x0504 -#define REG_EDCA_BE_PARAM 0x0508 -#define REG_EDCA_BK_PARAM 0x050C -#define REG_BCNTCFG 0x0510 -#define REG_PIFS 0x0512 -#define REG_RDG_PIFS 0x0513 -#define REG_SIFS_CTX 0x0514 -#define REG_SIFS_TRX 0x0516 -#define REG_AGGR_BREAK_TIME 0x051A -#define REG_SLOT 0x051B -#define REG_TX_PTCL_CTRL 0x0520 -#define REG_TXPAUSE 0x0522 -#define REG_DIS_TXREQ_CLR 0x0523 -#define REG_RD_CTRL 0x0524 -#define REG_TBTT_PROHIBIT 0x0540 -#define REG_RD_NAV_NXT 0x0544 -#define REG_NAV_PROT_LEN 0x0546 -#define REG_BCN_CTRL 0x0550 -#define REG_USTIME_TSF 0x0551 -#define REG_MBID_NUM 0x0552 -#define REG_DUAL_TSF_RST 0x0553 -#define REG_BCN_INTERVAL 0x0554 -#define REG_MBSSID_BCN_SPACE 0x0554 -#define REG_DRVERLYINT 0x0558 -#define REG_BCNDMATIM 0x0559 -#define REG_ATIMWND 0x055A -#define REG_BCN_MAX_ERR 0x055D -#define REG_RXTSF_OFFSET_CCK 0x055E -#define REG_RXTSF_OFFSET_OFDM 0x055F -#define REG_TSFTR 0x0560 -#define REG_INIT_TSFTR 0x0564 -#define REG_SECONDARY_CCA_CTRL 0x0577 -#define REG_PSTIMER 0x0580 -#define REG_TIMER0 0x0584 -#define REG_TIMER1 0x0588 -#define REG_ACMHWCTRL 0x05C0 -#define REG_ACMRSTCTRL 0x05C1 -#define REG_ACMAVG 0x05C2 -#define REG_VO_ADMTIME 0x05C4 -#define REG_VI_ADMTIME 0x05C6 -#define REG_BE_ADMTIME 0x05C8 -#define REG_EDCA_RANDOM_GEN 0x05CC -#define REG_SCH_TXCMD 0x05D0 - -#define REG_APSD_CTRL 0x0600 -#define REG_BWOPMODE 0x0603 -#define REG_TCR 0x0604 -#define REG_RCR 0x0608 -#define REG_RX_PKT_LIMIT 0x060C -#define REG_RX_DLK_TIME 0x060D -#define REG_RX_DRVINFO_SZ 0x060F - -#define REG_MACID 0x0610 -#define REG_BSSID 0x0618 -#define REG_MAR 0x0620 -#define REG_MBIDCAMCFG 0x0628 - -#define REG_USTIME_EDCA 0x0638 -#define REG_MAC_SPEC_SIFS 0x063A -#define REG_RESP_SIFS_CCK 0x063C -#define REG_RESP_SIFS_OFDM 0x063E -#define REG_ACKTO 0x0640 -#define REG_CTS2TO 0x0641 -#define REG_EIFS 0x0642 - -#define REG_NAV_CTRL 0x0650 -#define REG_NAV_UPPER 0x0652 -#define REG_BACAMCMD 0x0654 -#define REG_BACAMCONTENT 0x0658 -#define REG_LBDLY 0x0660 -#define REG_FWDLY 0x0661 -#define REG_RXERR_RPT 0x0664 -#define REG_TRXPTCL_CTL 0x0668 - -#define REG_CAMCMD 0x0670 -#define REG_CAMWRITE 0x0674 -#define REG_CAMREAD 0x0678 -#define REG_CAMDBG 0x067C -#define REG_SECCFG 0x0680 - -#define REG_WOW_CTRL 0x0690 -#define REG_PSSTATUS 0x0691 -#define REG_PS_RX_INFO 0x0692 -#define REG_UAPSD_TID 0x0693 -#define REG_LPNAV_CTRL 0x0694 -#define REG_WKFMCAM_NUM 0x0698 -#define REG_WKFMCAM_RWD 0x069C -#define REG_RXFLTMAP0 0x06A0 -#define REG_RXFLTMAP1 0x06A2 -#define REG_RXFLTMAP2 0x06A4 -#define REG_BCN_PSR_RPT 0x06A8 -#define REG_CALB32K_CTRL 0x06AC -#define REG_PKT_MON_CTRL 0x06B4 -#define REG_BT_COEX_TABLE 0x06C0 -#define REG_WMAC_RESP_TXINFO 0x06D8 - -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_TEST_USB_TXQS 0xFE48 -#define REG_TEST_SIE_VID 0xFE60 -#define REG_TEST_SIE_PID 0xFE62 -#define REG_TEST_SIE_OPTIONAL 0xFE64 -#define REG_TEST_SIE_CHIRP_K 0xFE65 -#define REG_TEST_SIE_PHY 0xFE66 -#define REG_TEST_SIE_MAC_ADDR 0xFE70 -#define REG_TEST_SIE_STRING 0xFE80 - -#define REG_NORMAL_SIE_VID 0xFE60 -#define REG_NORMAL_SIE_PID 0xFE62 -#define REG_NORMAL_SIE_OPTIONAL 0xFE64 -#define REG_NORMAL_SIE_EP 0xFE65 -#define REG_NORMAL_SIE_PHY 0xFE68 -#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 -#define REG_NORMAL_SIE_STRING 0xFE80 - -#define CR9346 REG_9346CR -#define MSR (REG_CR + 2) -#define ISR REG_HISR -#define TSFR REG_TSFTR - -#define MACIDR0 REG_MACID -#define MACIDR4 (REG_MACID + 4) - -#define PBP REG_PBP - -#define IDR0 MACIDR0 -#define IDR4 MACIDR4 - -#define UNUSED_REGISTER 0x1BF -#define DCAM UNUSED_REGISTER -#define PSR UNUSED_REGISTER -#define BBADDR UNUSED_REGISTER -#define PHYDATAR UNUSED_REGISTER - -#define INVALID_BBRF_VALUE 0x12345678 - -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -#define CMDEEPROM_EN BIT(5) -#define CMDEEPROM_SEL BIT(4) -#define CMD9346CR_9356SEL BIT(4) -#define AUTOLOAD_EEPROM (CMDEEPROM_EN | CMDEEPROM_SEL) -#define AUTOLOAD_EFUSE CMDEEPROM_EN - -#define GPIOSEL_GPIO 0 -#define GPIOSEL_ENBT BIT(5) - -#define GPIO_IN REG_GPIO_PIN_CTRL -#define GPIO_OUT (REG_GPIO_PIN_CTRL + 1) -#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL + 2) -#define GPIO_MOD (REG_GPIO_PIN_CTRL + 3) - -/* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */ -#define HSIMR_GPIO12_0_INT_EN BIT(0) -#define HSIMR_SPS_OCP_INT_EN BIT(5) -#define HSIMR_RON_INT_EN BIT(6) -#define HSIMR_PDN_INT_EN BIT(7) -#define HSIMR_GPIO9_INT_EN BIT(25) - -/* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */ -#define HSISR_GPIO12_0_INT BIT(0) -#define HSISR_SPS_OCP_INT BIT(5) -#define HSISR_RON_INT_EN BIT(6) -#define HSISR_PDNINT BIT(7) -#define HSISR_GPIO9_INT BIT(25) - -#define MSR_NOLINK 0x00 -#define MSR_ADHOC 0x01 -#define MSR_INFRA 0x02 -#define MSR_AP 0x03 - -#define RRSR_RSC_OFFSET 21 -#define RRSR_SHORT_OFFSET 23 -#define RRSR_RSC_BW_40M 0x600000 -#define RRSR_RSC_UPSUBCHNL 0x400000 -#define RRSR_RSC_LOWSUBCHNL 0x200000 -#define RRSR_SHORT 0x800000 -#define RRSR_1M BIT(0) -#define RRSR_2M BIT(1) -#define RRSR_5_5M BIT(2) -#define RRSR_11M BIT(3) -#define RRSR_6M BIT(4) -#define RRSR_9M BIT(5) -#define RRSR_12M BIT(6) -#define RRSR_18M BIT(7) -#define RRSR_24M BIT(8) -#define RRSR_36M BIT(9) -#define RRSR_48M BIT(10) -#define RRSR_54M BIT(11) -#define RRSR_MCS0 BIT(12) -#define RRSR_MCS1 BIT(13) -#define RRSR_MCS2 BIT(14) -#define RRSR_MCS3 BIT(15) -#define RRSR_MCS4 BIT(16) -#define RRSR_MCS5 BIT(17) -#define RRSR_MCS6 BIT(18) -#define RRSR_MCS7 BIT(19) -#define BRSR_ACKSHORTPMB BIT(23) - -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 -#define RATR_MCS8 0x00100000 -#define RATR_MCS9 0x00200000 -#define RATR_MCS10 0x00400000 -#define RATR_MCS11 0x00800000 -#define RATR_MCS12 0x01000000 -#define RATR_MCS13 0x02000000 -#define RATR_MCS14 0x04000000 -#define RATR_MCS15 0x08000000 - -#define RATE_1M BIT(0) -#define RATE_2M BIT(1) -#define RATE_5_5M BIT(2) -#define RATE_11M BIT(3) -#define RATE_6M BIT(4) -#define RATE_9M BIT(5) -#define RATE_12M BIT(6) -#define RATE_18M BIT(7) -#define RATE_24M BIT(8) -#define RATE_36M BIT(9) -#define RATE_48M BIT(10) -#define RATE_54M BIT(11) -#define RATE_MCS0 BIT(12) -#define RATE_MCS1 BIT(13) -#define RATE_MCS2 BIT(14) -#define RATE_MCS3 BIT(15) -#define RATE_MCS4 BIT(16) -#define RATE_MCS5 BIT(17) -#define RATE_MCS6 BIT(18) -#define RATE_MCS7 BIT(19) -#define RATE_MCS8 BIT(20) -#define RATE_MCS9 BIT(21) -#define RATE_MCS10 BIT(22) -#define RATE_MCS11 BIT(23) -#define RATE_MCS12 BIT(24) -#define RATE_MCS13 BIT(25) -#define RATE_MCS14 BIT(26) -#define RATE_MCS15 BIT(27) - -#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) -#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\ - RATR_24M | RATR_36M | RATR_48M | RATR_54M) -#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 |\ - RATR_MCS3 | RATR_MCS4 | RATR_MCS5 |\ - RATR_MCS6 | RATR_MCS7) -#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 |\ - RATR_MCS11 | RATR_MCS12 | RATR_MCS13 |\ - RATR_MCS14 | RATR_MCS15) - -#define BW_OPMODE_20MHZ BIT(2) -#define BW_OPMODE_5G BIT(1) -#define BW_OPMODE_11J BIT(0) - -#define CAM_VALID BIT(15) -#define CAM_NOTVALID 0x0000 -#define CAM_USEDK BIT(5) - -#define CAM_NONE 0x0 -#define CAM_WEP40 0x01 -#define CAM_TKIP 0x02 -#define CAM_AES 0x04 -#define CAM_WEP104 0x05 - -#define TOTAL_CAM_ENTRY 32 -#define HALF_CAM_ENTRY 16 - -#define CAM_WRITE BIT(16) -#define CAM_READ 0x00000000 -#define CAM_POLLINIG BIT(31) - -#define SCR_USEDK 0x01 -#define SCR_TXSEC_ENABLE 0x02 -#define SCR_RXSEC_ENABLE 0x04 - -#define WOW_PMEN BIT(0) -#define WOW_WOMEN BIT(1) -#define WOW_MAGIC BIT(2) -#define WOW_UWF BIT(3) - -/********************************************* -* 8723BE IMR/ISR bits -********************************************* -*/ -#define IMR_DISABLED 0x0 -/* IMR DW0(0x0060-0063) Bit 0-31 */ -#define IMR_TXCCK BIT(30) /* TXRPT interrupt when - * CCX bit of the packet is set - */ -#define IMR_PSTIMEOUT BIT(29) /* Power Save Time Out Interrupt */ -#define IMR_GTINT4 BIT(28) /* When GTIMER4 expires, - * this bit is set to 1 - */ -#define IMR_GTINT3 BIT(27) /* When GTIMER3 expires, - * this bit is set to 1 - */ -#define IMR_TBDER BIT(26) /* Transmit Beacon0 Error */ -#define IMR_TBDOK BIT(25) /* Transmit Beacon0 OK */ -#define IMR_TSF_BIT32_TOGGLE BIT(24) /* TSF Timer BIT32 toggle - * indication interrupt - */ -#define IMR_BCNDMAINT0 BIT(20) /* Beacon DMA Interrupt 0 */ -#define IMR_BCNDOK0 BIT(16) /* Beacon Queue DMA OK0 */ -#define IMR_HSISR_IND_ON_INT BIT(15) /* HSISR Indicator (HSIMR & HSISR is - * true, this bit is set to 1) - */ -#define IMR_BCNDMAINT_E BIT(14) /* Beacon DMA Interrupt - * Extension for Win7 - */ -#define IMR_ATIMEND BIT(12) /* CTWidnow End or ATIM Window End */ -#define IMR_HISR1_IND_INT BIT(11) /* HISR1 Indicator (HISR1 & HIMR1 is - * true, this bit is set to 1) - */ -#define IMR_C2HCMD BIT(10) /* CPU to Host Command INT Status, - * Write 1 clear - */ -#define IMR_CPWM2 BIT(9) /* CPU power Mode exchange INT Status, - * Write 1 clear - */ -#define IMR_CPWM BIT(8) /* CPU power Mode exchange INT Status, - * Write 1 clear - */ -#define IMR_HIGHDOK BIT(7) /* High Queue DMA OK */ -#define IMR_MGNTDOK BIT(6) /* Management Queue DMA OK */ -#define IMR_BKDOK BIT(5) /* AC_BK DMA OK */ -#define IMR_BEDOK BIT(4) /* AC_BE DMA OK */ -#define IMR_VIDOK BIT(3) /* AC_VI DMA OK */ -#define IMR_VODOK BIT(2) /* AC_VO DMA OK */ -#define IMR_RDU BIT(1) /* Rx Descriptor Unavailable */ -#define IMR_ROK BIT(0) /* Receive DMA OK */ - -/* IMR DW1(0x00B4-00B7) Bit 0-31 */ -#define IMR_BCNDMAINT7 BIT(27) /* Beacon DMA Interrupt 7 */ -#define IMR_BCNDMAINT6 BIT(26) /* Beacon DMA Interrupt 6 */ -#define IMR_BCNDMAINT5 BIT(25) /* Beacon DMA Interrupt 5 */ -#define IMR_BCNDMAINT4 BIT(24) /* Beacon DMA Interrupt 4 */ -#define IMR_BCNDMAINT3 BIT(23) /* Beacon DMA Interrupt 3 */ -#define IMR_BCNDMAINT2 BIT(22) /* Beacon DMA Interrupt 2 */ -#define IMR_BCNDMAINT1 BIT(21) /* Beacon DMA Interrupt 1 */ -#define IMR_BCNDOK7 BIT(20) /* Beacon Queue DMA OK Interrup 7 */ -#define IMR_BCNDOK6 BIT(19) /* Beacon Queue DMA OK Interrup 6 */ -#define IMR_BCNDOK5 BIT(18) /* Beacon Queue DMA OK Interrup 5 */ -#define IMR_BCNDOK4 BIT(17) /* Beacon Queue DMA OK Interrup 4 */ -#define IMR_BCNDOK3 BIT(16) /* Beacon Queue DMA OK Interrup 3 */ -#define IMR_BCNDOK2 BIT(15) /* Beacon Queue DMA OK Interrup 2 */ -#define IMR_BCNDOK1 BIT(14) /* Beacon Queue DMA OK Interrup 1 */ -#define IMR_ATIMEND_E BIT(13) /* ATIM Window End Extension for Win7 */ -#define IMR_TXERR BIT(11) /* Tx Error Flag Interrupt Status, - * write 1 clear. - */ -#define IMR_RXERR BIT(10) /* Rx Error Flag INT Status, - * Write 1 clear - */ -#define IMR_TXFOVW BIT(9) /* Transmit FIFO Overflow */ -#define IMR_RXFOVW BIT(8) /* Receive FIFO Overflow */ - -#define HWSET_MAX_SIZE 512 -#define EFUSE_MAX_SECTION 64 -#define EFUSE_REAL_CONTENT_LEN 256 -#define EFUSE_OOB_PROTECT_BYTES 18 /* PG data exclude header, - * dummy 7 bytes frome CP test - * and reserved 1byte. - */ - -#define EEPROM_DEFAULT_TSSI 0x0 -#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 -#define EEPROM_DEFAULT_CRYSTALCAP 0x5 -#define EEPROM_DEFAULT_BOARDTYPE 0x02 -#define EEPROM_DEFAULT_TXPOWER 0x1010 -#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 - -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 -#define EEPROM_DEFAULT_THERMALMETER 0x18 -#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 -#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 -#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 -#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 -#define EEPROM_DEFAULT_HT20_DIFF 2 -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 -#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 -#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 - -#define RF_OPTION1 0x79 -#define RF_OPTION2 0x7A -#define RF_OPTION3 0x7B -#define EEPROM_RF_BT_SETTING_8723B 0xC3 - -#define EEPROM_DEFAULT_PID 0x1234 -#define EEPROM_DEFAULT_VID 0x5678 -#define EEPROM_DEFAULT_CUSTOMERID 0xAB -#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD -#define EEPROM_DEFAULT_VERSION 0 - -#define EEPROM_CHANNEL_PLAN_FCC 0x0 -#define EEPROM_CHANNEL_PLAN_IC 0x1 -#define EEPROM_CHANNEL_PLAN_ETSI 0x2 -#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 -#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 -#define EEPROM_CHANNEL_PLAN_MKK 0x5 -#define EEPROM_CHANNEL_PLAN_MKK1 0x6 -#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 -#define EEPROM_CHANNEL_PLAN_TELEC 0x8 -#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 -#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -#define EEPROM_CHANNEL_PLAN_NCC 0xB -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - -#define EEPROM_CID_DEFAULT 0x0 -#define EEPROM_CID_TOSHIBA 0x4 -#define EEPROM_CID_CCX 0x10 -#define EEPROM_CID_QMI 0x0D -#define EEPROM_CID_WHQL 0xFE - -#define RTL8723BE_EEPROM_ID 0x8129 - -#define EEPROM_HPON 0x02 -#define EEPROM_CLK 0x06 -#define EEPROM_TESTR 0x08 - -#define EEPROM_TXPOWERCCK 0x10 -#define EEPROM_TXPOWERHT40_1S 0x16 -#define EEPROM_TXPOWERHT20DIFF 0x1B -#define EEPROM_TXPOWER_OFDMDIFF 0x1B - -#define EEPROM_TX_PWR_INX 0x10 - -#define EEPROM_CHANNELPLAN 0xB8 -#define EEPROM_XTAL_8723BE 0xB9 -#define EEPROM_THERMAL_METER_88E 0xBA -#define EEPROM_IQK_LCK_88E 0xBB - -#define EEPROM_RF_BOARD_OPTION_88E 0xC1 -#define EEPROM_RF_FEATURE_OPTION_88E 0xC2 -#define EEPROM_RF_BT_SETTING_88E 0xC3 -#define EEPROM_VERSION 0xC4 -#define EEPROM_CUSTOMER_ID 0xC5 -#define EEPROM_RF_ANTENNA_OPT_88E 0xC9 - -#define EEPROM_MAC_ADDR 0xD0 -#define EEPROM_VID 0xD6 -#define EEPROM_DID 0xD8 -#define EEPROM_SVID 0xDA -#define EEPROM_SMID 0xDC - -#define STOPBECON BIT(6) -#define STOPHIGHT BIT(5) -#define STOPMGT BIT(4) -#define STOPVO BIT(3) -#define STOPVI BIT(2) -#define STOPBE BIT(1) -#define STOPBK BIT(0) - -#define RCR_APPFCS BIT(31) -#define RCR_APP_MIC BIT(30) -#define RCR_APP_ICV BIT(29) -#define RCR_APP_PHYST_RXFF BIT(28) -#define RCR_APP_BA_SSN BIT(27) -#define RCR_ENMBID BIT(24) -#define RCR_LSIGEN BIT(23) -#define RCR_MFBEN BIT(22) -#define RCR_HTC_LOC_CTRL BIT(14) -#define RCR_AMF BIT(13) -#define RCR_ACF BIT(12) -#define RCR_ADF BIT(11) -#define RCR_AICV BIT(9) -#define RCR_ACRC32 BIT(8) -#define RCR_CBSSID_BCN BIT(7) -#define RCR_CBSSID_DATA BIT(6) -#define RCR_CBSSID RCR_CBSSID_DATA -#define RCR_APWRMGT BIT(5) -#define RCR_ADD3 BIT(4) -#define RCR_AB BIT(3) -#define RCR_AM BIT(2) -#define RCR_APM BIT(1) -#define RCR_AAP BIT(0) -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - -#define RSV_CTRL 0x001C -#define RD_CTRL 0x0524 - -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_USB_VID 0xFE60 -#define REG_USB_PID 0xFE62 -#define REG_USB_OPTIONAL 0xFE64 -#define REG_USB_CHIRP_K 0xFE65 -#define REG_USB_PHY 0xFE66 -#define REG_USB_MAC_ADDR 0xFE70 -#define REG_USB_HRPWM 0xFE58 -#define REG_USB_HCPWM 0xFE57 - -#define SW18_FPWM BIT(3) - -#define ISO_MD2PP BIT(0) -#define ISO_UA2USB BIT(1) -#define ISO_UD2CORE BIT(2) -#define ISO_PA2PCIE BIT(3) -#define ISO_PD2CORE BIT(4) -#define ISO_IP2MAC BIT(5) -#define ISO_DIOP BIT(6) -#define ISO_DIOE BIT(7) -#define ISO_EB2CORE BIT(8) -#define ISO_DIOR BIT(9) - -#define PWC_EV25V BIT(14) -#define PWC_EV12V BIT(15) - -#define FEN_BBRSTB BIT(0) -#define FEN_BB_GLB_RSTN BIT(1) -#define FEN_USBA BIT(2) -#define FEN_UPLL BIT(3) -#define FEN_USBD BIT(4) -#define FEN_DIO_PCIE BIT(5) -#define FEN_PCIEA BIT(6) -#define FEN_PPLL BIT(7) -#define FEN_PCIED BIT(8) -#define FEN_DIOE BIT(9) -#define FEN_CPUEN BIT(10) -#define FEN_DCORE BIT(11) -#define FEN_ELDR BIT(12) -#define FEN_DIO_RF BIT(13) -#define FEN_HWPDN BIT(14) -#define FEN_MREGEN BIT(15) - -#define PFM_LDALL BIT(0) -#define PFM_ALDN BIT(1) -#define PFM_LDKP BIT(2) -#define PFM_WOWL BIT(3) -#define ENPDN BIT(4) -#define PDN_PL BIT(5) -#define APFM_ONMAC BIT(8) -#define APFM_OFF BIT(9) -#define APFM_RSM BIT(10) -#define AFSM_HSUS BIT(11) -#define AFSM_PCIE BIT(12) -#define APDM_MAC BIT(13) -#define APDM_HOST BIT(14) -#define APDM_HPDN BIT(15) -#define RDY_MACON BIT(16) -#define SUS_HOST BIT(17) -#define ROP_ALD BIT(20) -#define ROP_PWR BIT(21) -#define ROP_SPS BIT(22) -#define SOP_MRST BIT(25) -#define SOP_FUSE BIT(26) -#define SOP_ABG BIT(27) -#define SOP_AMB BIT(28) -#define SOP_RCK BIT(29) -#define SOP_A8M BIT(30) -#define XOP_BTCK BIT(31) - -#define ANAD16V_EN BIT(0) -#define ANA8M BIT(1) -#define MACSLP BIT(4) -#define LOADER_CLK_EN BIT(5) -#define _80M_SSC_DIS BIT(7) -#define _80M_SSC_EN_HO BIT(8) -#define PHY_SSC_RSTB BIT(9) -#define SEC_CLK_EN BIT(10) -#define MAC_CLK_EN BIT(11) -#define SYS_CLK_EN BIT(12) -#define RING_CLK_EN BIT(13) - -#define BOOT_FROM_EEPROM BIT(4) -#define EEPROM_EN BIT(5) - -#define AFE_BGEN BIT(0) -#define AFE_MBEN BIT(1) -#define MAC_ID_EN BIT(7) - -#define WLOCK_ALL BIT(0) -#define WLOCK_00 BIT(1) -#define WLOCK_04 BIT(2) -#define WLOCK_08 BIT(3) -#define WLOCK_40 BIT(4) -#define R_DIS_PRST_0 BIT(5) -#define R_DIS_PRST_1 BIT(6) -#define LOCK_ALL_EN BIT(7) - -#define RF_EN BIT(0) -#define RF_RSTB BIT(1) -#define RF_SDMRSTB BIT(2) - -#define LDA15_EN BIT(0) -#define LDA15_STBY BIT(1) -#define LDA15_OBUF BIT(2) -#define LDA15_REG_VOS BIT(3) -#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) - -#define LDV12_EN BIT(0) -#define LDV12_SDBY BIT(1) -#define LPLDO_HSM BIT(2) -#define LPLDO_LSM_DIS BIT(3) -#define _LDV12_VADJ(x) (((x) & 0xF) << 4) - -#define XTAL_EN BIT(0) -#define XTAL_BSEL BIT(1) -#define _XTAL_BOSC(x) (((x) & 0x3) << 2) -#define _XTAL_CADJ(x) (((x) & 0xF) << 4) -#define XTAL_GATE_USB BIT(8) -#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) -#define XTAL_GATE_AFE BIT(11) -#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) -#define XTAL_RF_GATE BIT(14) -#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) -#define XTAL_GATE_DIG BIT(17) -#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) -#define XTAL_BT_GATE BIT(20) -#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) -#define _XTAL_GPIO(x) (((x) & 0x7) << 23) - -#define CKDLY_AFE BIT(26) -#define CKDLY_USB BIT(27) -#define CKDLY_DIG BIT(28) -#define CKDLY_BT BIT(29) - -#define APLL_EN BIT(0) -#define APLL_320_EN BIT(1) -#define APLL_FREF_SEL BIT(2) -#define APLL_EDGE_SEL BIT(3) -#define APLL_WDOGB BIT(4) -#define APLL_LPFEN BIT(5) - -#define APLL_REF_CLK_13MHZ 0x1 -#define APLL_REF_CLK_19_2MHZ 0x2 -#define APLL_REF_CLK_20MHZ 0x3 -#define APLL_REF_CLK_25MHZ 0x4 -#define APLL_REF_CLK_26MHZ 0x5 -#define APLL_REF_CLK_38_4MHZ 0x6 -#define APLL_REF_CLK_40MHZ 0x7 - -#define APLL_320EN BIT(14) -#define APLL_80EN BIT(15) -#define APLL_1MEN BIT(24) - -#define ALD_EN BIT(18) -#define EF_PD BIT(19) -#define EF_FLAG BIT(31) - -#define EF_TRPT BIT(7) -#define LDOE25_EN BIT(31) - -#define RSM_EN BIT(0) -#define TIMER_EN BIT(4) - -#define TRSW0EN BIT(2) -#define TRSW1EN BIT(3) -#define EROM_EN BIT(4) -#define ENBT BIT(5) -#define ENUART BIT(8) -#define UART_910 BIT(9) -#define ENPMAC BIT(10) -#define SIC_SWRST BIT(11) -#define ENSIC BIT(12) -#define SIC_23 BIT(13) -#define ENHDP BIT(14) -#define SIC_LBK BIT(15) - -#define LED0PL BIT(4) -#define LED1PL BIT(12) -#define LED0DIS BIT(7) - -#define MCUFWDL_EN BIT(0) -#define MCUFWDL_RDY BIT(1) -#define FWDL_CHKSUM_RPT BIT(2) -#define MACINI_RDY BIT(3) -#define BBINI_RDY BIT(4) -#define RFINI_RDY BIT(5) -#define WINTINI_RDY BIT(6) -#define CPRST BIT(23) - -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define TRP_B15V_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define VENDOR_ID BIT(19) -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) - -#define CHIP_VER_RTL_MASK 0xF000 -#define CHIP_VER_RTL_SHIFT 12 - -#define REG_LBMODE (REG_CR + 3) - -#define HCI_TXDMA_EN BIT(0) -#define HCI_RXDMA_EN BIT(1) -#define TXDMA_EN BIT(2) -#define RXDMA_EN BIT(3) -#define PROTOCOL_EN BIT(4) -#define SCHEDULE_EN BIT(5) -#define MACTXEN BIT(6) -#define MACRXEN BIT(7) -#define ENSWBCN BIT(8) -#define ENSEC BIT(9) - -#define _NETTYPE(x) (((x) & 0x3) << 16) -#define MASK_NETTYPE 0x30000 -#define NT_NO_LINK 0x0 -#define NT_LINK_AD_HOC 0x1 -#define NT_LINK_AP 0x2 -#define NT_AS_AP 0x3 - -#define _LBMODE(x) (((x) & 0xF) << 24) -#define MASK_LBMODE 0xF000000 -#define LOOPBACK_NORMAL 0x0 -#define LOOPBACK_IMMEDIATELY 0xB -#define LOOPBACK_MAC_DELAY 0x3 -#define LOOPBACK_PHY 0x1 -#define LOOPBACK_DMA 0x7 - -#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) -#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) -#define _PSRX_MASK 0xF -#define _PSTX_MASK 0xF0 -#define _PSRX(x) (x) -#define _PSTX(x) ((x) << 4) - -#define PBP_64 0x0 -#define PBP_128 0x1 -#define PBP_256 0x2 -#define PBP_512 0x3 -#define PBP_1024 0x4 - -#define RXDMA_ARBBW_EN BIT(0) -#define RXSHFT_EN BIT(1) -#define RXDMA_AGG_EN BIT(2) -#define QS_VO_QUEUE BIT(8) -#define QS_VI_QUEUE BIT(9) -#define QS_BE_QUEUE BIT(10) -#define QS_BK_QUEUE BIT(11) -#define QS_MANAGER_QUEUE BIT(12) -#define QS_HIGH_QUEUE BIT(13) - -#define HQSEL_VOQ BIT(0) -#define HQSEL_VIQ BIT(1) -#define HQSEL_BEQ BIT(2) -#define HQSEL_BKQ BIT(3) -#define HQSEL_MGTQ BIT(4) -#define HQSEL_HIQ BIT(5) - -#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) -#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) -#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) -#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) -#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) -#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) - -#define QUEUE_LOW 1 -#define QUEUE_NORMAL 2 -#define QUEUE_HIGH 3 - -#define _LLT_NO_ACTIVE 0x0 -#define _LLT_WRITE_ACCESS 0x1 -#define _LLT_READ_ACCESS 0x2 - -#define _LLT_INIT_DATA(x) ((x) & 0xFF) -#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) -#define _LLT_OP(x) (((x) & 0x3) << 30) -#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) - -#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) -#define BB_WRITE_EN BIT(30) -#define BB_READ_EN BIT(31) - -#define _HPQ(x) ((x) & 0xFF) -#define _LPQ(x) (((x) & 0xFF) << 8) -#define _PUBQ(x) (((x) & 0xFF) << 16) -#define _NPQ(x) ((x) & 0xFF) - -#define HPQ_PUBLIC_DIS BIT(24) -#define LPQ_PUBLIC_DIS BIT(25) -#define LD_RQPN BIT(31) - -#define BCN_VALID BIT(16) -#define BCN_HEAD(x) (((x) & 0xFF) << 8) -#define BCN_HEAD_MASK 0xFF00 - -#define BLK_DESC_NUM_SHIFT 4 -#define BLK_DESC_NUM_MASK 0xF - -#define DROP_DATA_EN BIT(9) - -#define EN_AMPDU_RTY_NEW BIT(7) - -#define _INIRTSMCS_SEL(x) ((x) & 0x3F) - -#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) -#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) - -#define RATE_REG_BITMAP_ALL 0xFFFFF - -#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) - -#define _RRSR_RSC(x) (((x) & 0x3) << 21) -#define RRSR_RSC_RESERVED 0x0 -#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 -#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 -#define RRSR_RSC_DUPLICATE_MODE 0x3 - -#define USE_SHORT_G1 BIT(20) - -#define _AGGLMT_MCS0(x) ((x) & 0xF) -#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) -#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) -#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) -#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) -#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) -#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) -#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) - -#define RETRY_LIMIT_SHORT_SHIFT 8 -#define RETRY_LIMIT_LONG_SHIFT 0 - -#define _DARF_RC1(x) ((x) & 0x1F) -#define _DARF_RC2(x) (((x) & 0x1F) << 8) -#define _DARF_RC3(x) (((x) & 0x1F) << 16) -#define _DARF_RC4(x) (((x) & 0x1F) << 24) -#define _DARF_RC5(x) ((x) & 0x1F) -#define _DARF_RC6(x) (((x) & 0x1F) << 8) -#define _DARF_RC7(x) (((x) & 0x1F) << 16) -#define _DARF_RC8(x) (((x) & 0x1F) << 24) - -#define _RARF_RC1(x) ((x) & 0x1F) -#define _RARF_RC2(x) (((x) & 0x1F) << 8) -#define _RARF_RC3(x) (((x) & 0x1F) << 16) -#define _RARF_RC4(x) (((x) & 0x1F) << 24) -#define _RARF_RC5(x) ((x) & 0x1F) -#define _RARF_RC6(x) (((x) & 0x1F) << 8) -#define _RARF_RC7(x) (((x) & 0x1F) << 16) -#define _RARF_RC8(x) (((x) & 0x1F) << 24) - -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - -#define _AIFS(x) (x) -#define _ECW_MAX_MIN(x) ((x) << 8) -#define _TXOP_LIMIT(x) ((x) << 16) - -#define _BCNIFS(x) ((x) & 0xFF) -#define _BCNECW(x) ((((x) & 0xF)) << 8) - -#define _LRL(x) ((x) & 0x3F) -#define _SRL(x) (((x) & 0x3F) << 8) - -#define _SIFS_CCK_CTX(x) ((x) & 0xFF) -#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8) - -#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) -#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8) - -#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) - -#define DIS_EDCA_CNT_DWN BIT(11) - -#define EN_MBSSID BIT(1) -#define EN_TXBCN_RPT BIT(2) -#define EN_BCN_FUNCTION BIT(3) - -#define TSFTR_RST BIT(0) -#define TSFTR1_RST BIT(1) - -#define STOP_BCNQ BIT(6) - -#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) -#define DIS_TSF_UDT0_TEST_CHIP BIT(5) - -#define ACMHW_HWEN BIT(0) -#define ACMHW_BEQEN BIT(1) -#define ACMHW_VIQEN BIT(2) -#define ACMHW_VOQEN BIT(3) -#define ACMHW_BEQSTATUS BIT(4) -#define ACMHW_VIQSTATUS BIT(5) -#define ACMHW_VOQSTATUS BIT(6) - -#define APSDOFF BIT(6) -#define APSDOFF_STATUS BIT(7) - -#define BW_20MHZ BIT(2) - -#define RATE_BITMAP_ALL 0xFFFFF - -#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 - -#define TSFRST BIT(0) -#define DIS_GCLK BIT(1) -#define PAD_SEL BIT(2) -#define PWR_ST BIT(6) -#define PWRBIT_OW_EN BIT(7) -#define ACRC BIT(8) -#define CFENDFORM BIT(9) -#define ICV BIT(10) - -#define AAP BIT(0) -#define APM BIT(1) -#define AM BIT(2) -#define AB BIT(3) -#define ADD3 BIT(4) -#define APWRMGT BIT(5) -#define CBSSID BIT(6) -#define CBSSID_DATA BIT(6) -#define CBSSID_BCN BIT(7) -#define ACRC32 BIT(8) -#define AICV BIT(9) -#define ADF BIT(11) -#define ACF BIT(12) -#define AMF BIT(13) -#define HTC_LOC_CTRL BIT(14) -#define UC_DATA_EN BIT(16) -#define BM_DATA_EN BIT(17) -#define MFBEN BIT(22) -#define LSIGEN BIT(23) -#define ENMBID BIT(24) -#define APP_BASSN BIT(27) -#define APP_PHYSTS BIT(28) -#define APP_ICV BIT(29) -#define APP_MIC BIT(30) -#define APP_FCS BIT(31) - -#define _MIN_SPACE(x) ((x) & 0x7) -#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) - -#define RXERR_TYPE_OFDM_PPDU 0 -#define RXERR_TYPE_OFDM_FALSE_ALARM 1 -#define RXERR_TYPE_OFDM_MPDU_OK 2 -#define RXERR_TYPE_OFDM_MPDU_FAIL 3 -#define RXERR_TYPE_CCK_PPDU 4 -#define RXERR_TYPE_CCK_FALSE_ALARM 5 -#define RXERR_TYPE_CCK_MPDU_OK 6 -#define RXERR_TYPE_CCK_MPDU_FAIL 7 -#define RXERR_TYPE_HT_PPDU 8 -#define RXERR_TYPE_HT_FALSE_ALARM 9 -#define RXERR_TYPE_HT_MPDU_TOTAL 10 -#define RXERR_TYPE_HT_MPDU_OK 11 -#define RXERR_TYPE_HT_MPDU_FAIL 12 -#define RXERR_TYPE_RX_FULL_DROP 15 - -#define RXERR_COUNTER_MASK 0xFFFFF -#define RXERR_RPT_RST BIT(27) -#define _RXERR_RPT_SEL(type) ((type) << 28) - -#define SCR_TXUSEDK BIT(0) -#define SCR_RXUSEDK BIT(1) -#define SCR_TXENCENABLE BIT(2) -#define SCR_RXDECENABLE BIT(3) -#define SCR_SKBYA2 BIT(4) -#define SCR_NOSKMC BIT(5) -#define SCR_TXBCUSEDK BIT(6) -#define SCR_RXBCUSEDK BIT(7) - -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define TRP_B15V_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define BT_FUNC BIT(16) -#define VENDOR_ID BIT(19) -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) - -#define USB_IS_HIGH_SPEED 0 -#define USB_IS_FULL_SPEED 1 -#define USB_SPEED_MASK BIT(5) - -#define USB_NORMAL_SIE_EP_MASK 0xF -#define USB_NORMAL_SIE_EP_SHIFT 4 - -#define USB_TEST_EP_MASK 0x30 -#define USB_TEST_EP_SHIFT 4 - -#define USB_AGG_EN BIT(3) - -#define MAC_ADDR_LEN 6 -#define LAST_ENTRY_OF_TX_PKT_BUFFER 175/*255 88e*/ - -#define POLLING_LLT_THRESHOLD 20 -#define POLLING_READY_TIMEOUT_COUNT 3000 - -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) -#define EPROM_CMD_CONFIG 0x3 -#define EPROM_CMD_LOAD 1 - -#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE - -#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) - -#define RPMAC_RESET 0x100 -#define RPMAC_TXSTART 0x104 -#define RPMAC_TXLEGACYSIG 0x108 -#define RPMAC_TXHTSIG1 0x10c -#define RPMAC_TXHTSIG2 0x110 -#define RPMAC_PHYDEBUG 0x114 -#define RPMAC_TXPACKETNUM 0x118 -#define RPMAC_TXIDLE 0x11c -#define RPMAC_TXMACHEADER0 0x120 -#define RPMAC_TXMACHEADER1 0x124 -#define RPMAC_TXMACHEADER2 0x128 -#define RPMAC_TXMACHEADER3 0x12c -#define RPMAC_TXMACHEADER4 0x130 -#define RPMAC_TXMACHEADER5 0x134 -#define RPMAC_TXDADATYPE 0x138 -#define RPMAC_TXRANDOMSEED 0x13c -#define RPMAC_CCKPLCPPREAMBLE 0x140 -#define RPMAC_CCKPLCPHEADER 0x144 -#define RPMAC_CCKCRC16 0x148 -#define RPMAC_OFDMRXCRC32OK 0x170 -#define RPMAC_OFDMRXCRC32ER 0x174 -#define RPMAC_OFDMRXPARITYER 0x178 -#define RPMAC_OFDMRXCRC8ER 0x17c -#define RPMAC_CCKCRXRC16ER 0x180 -#define RPMAC_CCKCRXRC32ER 0x184 -#define RPMAC_CCKCRXRC32OK 0x188 -#define RPMAC_TXSTATUS 0x18c - -#define RFPGA0_RFMOD 0x800 - -#define RFPGA0_TXINFO 0x804 -#define RFPGA0_PSDFUNCTION 0x808 - -#define RFPGA0_TXGAINSTAGE 0x80c - -#define RFPGA0_RFTIMING1 0x810 -#define RFPGA0_RFTIMING2 0x814 - -#define RFPGA0_XA_HSSIPARAMETER1 0x820 -#define RFPGA0_XA_HSSIPARAMETER2 0x824 -#define RFPGA0_XB_HSSIPARAMETER1 0x828 -#define RFPGA0_XB_HSSIPARAMETER2 0x82c - -#define RFPGA0_XA_LSSIPARAMETER 0x840 -#define RFPGA0_XB_LSSIPARAMETER 0x844 - -#define RFPGA0_RFWAKEUPPARAMETER 0x850 -#define RFPGA0_RFSLEEPUPPARAMETER 0x854 - -#define RFPGA0_XAB_SWITCHCONTROL 0x858 -#define RFPGA0_XCD_SWITCHCONTROL 0x85c - -#define RFPGA0_XA_RFINTERFACEOE 0x860 -#define RFPGA0_XB_RFINTERFACEOE 0x864 - -#define RFPGA0_XAB_RFINTERFACESW 0x870 -#define RFPGA0_XCD_RFINTERFACESW 0x874 - -#define RFPGA0_XAB_RFPARAMETER 0x878 -#define RFPGA0_XCD_RFPARAMETER 0x87c - -#define RFPGA0_ANALOGPARAMETER1 0x880 -#define RFPGA0_ANALOGPARAMETER2 0x884 -#define RFPGA0_ANALOGPARAMETER3 0x888 -#define RFPGA0_ANALOGPARAMETER4 0x88c - -#define RFPGA0_XA_LSSIREADBACK 0x8a0 -#define RFPGA0_XB_LSSIREADBACK 0x8a4 -#define RFPGA0_XC_LSSIREADBACK 0x8a8 -#define RFPGA0_XD_LSSIREADBACK 0x8ac - -#define RFPGA0_PSDREPORT 0x8b4 -#define TRANSCEIVEA_HSPI_READBACK 0x8b8 -#define TRANSCEIVEB_HSPI_READBACK 0x8bc -#define REG_SC_CNT 0x8c4 -#define RFPGA0_XAB_RFINTERFACERB 0x8e0 -#define RFPGA0_XCD_RFINTERFACERB 0x8e4 - -#define RFPGA1_RFMOD 0x900 - -#define RFPGA1_TXBLOCK 0x904 -#define RFPGA1_DEBUGSELECT 0x908 -#define RFPGA1_TXINFO 0x90c - -#define RCCK0_SYSTEM 0xa00 - -#define RCCK0_AFESETTING 0xa04 -#define RCCK0_CCA 0xa08 - -#define RCCK0_RXAGC1 0xa0c -#define RCCK0_RXAGC2 0xa10 - -#define RCCK0_RXHP 0xa14 - -#define RCCK0_DSPPARAMETER1 0xa18 -#define RCCK0_DSPPARAMETER2 0xa1c - -#define RCCK0_TXFILTER1 0xa20 -#define RCCK0_TXFILTER2 0xa24 -#define RCCK0_DEBUGPORT 0xa28 -#define RCCK0_FALSEALARMREPORT 0xa2c -#define RCCK0_TRSSIREPORT 0xa50 -#define RCCK0_RXREPORT 0xa54 -#define RCCK0_FACOUNTERLOWER 0xa5c -#define RCCK0_FACOUNTERUPPER 0xa58 -#define RCCK0_CCA_CNT 0xa60 - -/* PageB(0xB00) */ -#define RPDP_ANTA 0xb00 -#define RPDP_ANTA_4 0xb04 -#define RPDP_ANTA_8 0xb08 -#define RPDP_ANTA_C 0xb0c -#define RPDP_ANTA_10 0xb10 -#define RPDP_ANTA_14 0xb14 -#define RPDP_ANTA_18 0xb18 -#define RPDP_ANTA_1C 0xb1c -#define RPDP_ANTA_20 0xb20 -#define RPDP_ANTA_24 0xb24 - -#define RCONFIG_PMPD_ANTA 0xb28 -#define RCONFIG_ram64x16 0xb2c - -#define RBNDA 0xb30 -#define RHSSIPAR 0xb34 - -#define RCONFIG_ANTA 0xb68 -#define RCONFIG_ANTB 0xb6c - -#define RPDP_ANTB 0xb70 -#define RPDP_ANTB_4 0xb74 -#define RPDP_ANTB_8 0xb78 -#define RPDP_ANTB_C 0xb7c -#define RPDP_ANTB_10 0xb80 -#define RPDP_ANTB_14 0xb84 -#define RPDP_ANTB_18 0xb88 -#define RPDP_ANTB_1C 0xb8c -#define RPDP_ANTB_20 0xb90 -#define RPDP_ANTB_24 0xb94 - -#define RCONFIG_PMPD_ANTB 0xb98 - -#define RBNDB 0xba0 - -#define RAPK 0xbd8 -#define RPM_RX0_ANTA 0xbdc -#define RPM_RX1_ANTA 0xbe0 -#define RPM_RX2_ANTA 0xbe4 -#define RPM_RX3_ANTA 0xbe8 -#define RPM_RX0_ANTB 0xbec -#define RPM_RX1_ANTB 0xbf0 -#define RPM_RX2_ANTB 0xbf4 -#define RPM_RX3_ANTB 0xbf8 - -/*Page C*/ -#define ROFDM0_LSTF 0xc00 - -#define ROFDM0_TRXPATHENABLE 0xc04 -#define ROFDM0_TRMUXPAR 0xc08 -#define ROFDM0_TRSWISOLATION 0xc0c - -#define ROFDM0_XARXAFE 0xc10 -#define ROFDM0_XARXIQIMBALANCE 0xc14 -#define ROFDM0_XBRXAFE 0xc18 -#define ROFDM0_XBRXIQIMBALANCE 0xc1c -#define ROFDM0_XCRXAFE 0xc20 -#define ROFDM0_XCRXIQIMBANLANCE 0xc24 -#define ROFDM0_XDRXAFE 0xc28 -#define ROFDM0_XDRXIQIMBALANCE 0xc2c - -#define ROFDM0_RXDETECTOR1 0xc30 -#define ROFDM0_RXDETECTOR2 0xc34 -#define ROFDM0_RXDETECTOR3 0xc38 -#define ROFDM0_RXDETECTOR4 0xc3c - -#define ROFDM0_RXDSP 0xc40 -#define ROFDM0_CFOANDDAGC 0xc44 -#define ROFDM0_CCADROPTHRESHOLD 0xc48 -#define ROFDM0_ECCATHRESHOLD 0xc4c - -#define ROFDM0_XAAGCCORE1 0xc50 -#define ROFDM0_XAAGCCORE2 0xc54 -#define ROFDM0_XBAGCCORE1 0xc58 -#define ROFDM0_XBAGCCORE2 0xc5c -#define ROFDM0_XCAGCCORE1 0xc60 -#define ROFDM0_XCAGCCORE2 0xc64 -#define ROFDM0_XDAGCCORE1 0xc68 -#define ROFDM0_XDAGCCORE2 0xc6c - -#define ROFDM0_AGCPARAMETER1 0xc70 -#define ROFDM0_AGCPARAMETER2 0xc74 -#define ROFDM0_AGCRSSITABLE 0xc78 -#define ROFDM0_HTSTFAGC 0xc7c - -#define ROFDM0_XATXIQIMBALANCE 0xc80 -#define ROFDM0_XATXAFE 0xc84 -#define ROFDM0_XBTXIQIMBALANCE 0xc88 -#define ROFDM0_XBTXAFE 0xc8c -#define ROFDM0_XCTXIQIMBALANCE 0xc90 -#define ROFDM0_XCTXAFE 0xc94 -#define ROFDM0_XDTXIQIMBALANCE 0xc98 -#define ROFDM0_XDTXAFE 0xc9c - -#define ROFDM0_RXIQEXTANTA 0xca0 -#define ROFDM0_TXCOEFF1 0xca4 -#define ROFDM0_TXCOEFF2 0xca8 -#define ROFDM0_TXCOEFF3 0xcac -#define ROFDM0_TXCOEFF4 0xcb0 -#define ROFDM0_TXCOEFF5 0xcb4 -#define ROFDM0_TXCOEFF6 0xcb8 - -#define ROFDM0_RXHPPARAMETER 0xce0 -#define ROFDM0_TXPSEUDONOISEWGT 0xce4 -#define ROFDM0_FRAMESYNC 0xcf0 -#define ROFDM0_DFSREPORT 0xcf4 - -#define ROFDM1_LSTF 0xd00 -#define ROFDM1_TRXPATHENABLE 0xd04 - -#define ROFDM1_CF0 0xd08 -#define ROFDM1_CSI1 0xd10 -#define ROFDM1_SBD 0xd14 -#define ROFDM1_CSI2 0xd18 -#define ROFDM1_CFOTRACKING 0xd2c -#define ROFDM1_TRXMESAURE1 0xd34 -#define ROFDM1_INTFDET 0xd3c -#define ROFDM1_PSEUDONOISESTATEAB 0xd50 -#define ROFDM1_PSEUDONOISESTATECD 0xd54 -#define ROFDM1_RXPSEUDONOISEWGT 0xd58 - -#define ROFDM_PHYCOUNTER1 0xda0 -#define ROFDM_PHYCOUNTER2 0xda4 -#define ROFDM_PHYCOUNTER3 0xda8 - -#define ROFDM_SHORTCFOAB 0xdac -#define ROFDM_SHORTCFOCD 0xdb0 -#define ROFDM_LONGCFOAB 0xdb4 -#define ROFDM_LONGCFOCD 0xdb8 -#define ROFDM_TAILCF0AB 0xdbc -#define ROFDM_TAILCF0CD 0xdc0 -#define ROFDM_PWMEASURE1 0xdc4 -#define ROFDM_PWMEASURE2 0xdc8 -#define ROFDM_BWREPORT 0xdcc -#define ROFDM_AGCREPORT 0xdd0 -#define ROFDM_RXSNR 0xdd4 -#define ROFDM_RXEVMCSI 0xdd8 -#define ROFDM_SIGREPORT 0xddc - -#define RTXAGC_A_RATE18_06 0xe00 -#define RTXAGC_A_RATE54_24 0xe04 -#define RTXAGC_A_CCK1_MCS32 0xe08 -#define RTXAGC_A_MCS03_MCS00 0xe10 -#define RTXAGC_A_MCS07_MCS04 0xe14 -#define RTXAGC_A_MCS11_MCS08 0xe18 -#define RTXAGC_A_MCS15_MCS12 0xe1c - -#define RTXAGC_B_RATE18_06 0x830 -#define RTXAGC_B_RATE54_24 0x834 -#define RTXAGC_B_CCK1_55_MCS32 0x838 -#define RTXAGC_B_MCS03_MCS00 0x83c -#define RTXAGC_B_MCS07_MCS04 0x848 -#define RTXAGC_B_MCS11_MCS08 0x84c -#define RTXAGC_B_MCS15_MCS12 0x868 -#define RTXAGC_B_CCK11_A_CCK2_11 0x86c - -#define RFPGA0_IQK 0xe28 -#define RTX_IQK_TONE_A 0xe30 -#define RRX_IQK_TONE_A 0xe34 -#define RTX_IQK_PI_A 0xe38 -#define RRX_IQK_PI_A 0xe3c - -#define RTX_IQK 0xe40 -#define RRX_IQK 0xe44 -#define RIQK_AGC_PTS 0xe48 -#define RIQK_AGC_RSP 0xe4c -#define RTX_IQK_TONE_B 0xe50 -#define RRX_IQK_TONE_B 0xe54 -#define RTX_IQK_PI_B 0xe58 -#define RRX_IQK_PI_B 0xe5c -#define RIQK_AGC_CONT 0xe60 - -#define RBLUE_TOOTH 0xe6c -#define RRX_WAIT_CCA 0xe70 -#define RTX_CCK_RFON 0xe74 -#define RTX_CCK_BBON 0xe78 -#define RTX_OFDM_RFON 0xe7c -#define RTX_OFDM_BBON 0xe80 -#define RTX_TO_RX 0xe84 -#define RTX_TO_TX 0xe88 -#define RRX_CCK 0xe8c - -#define RTX_POWER_BEFORE_IQK_A 0xe94 -#define RTX_POWER_AFTER_IQK_A 0xe9c - -#define RRX_POWER_BEFORE_IQK_A 0xea0 -#define RRX_POWER_BEFORE_IQK_A_2 0xea4 -#define RRX_POWER_AFTER_IQK_A 0xea8 -#define RRX_POWER_AFTER_IQK_A_2 0xeac - -#define RTX_POWER_BEFORE_IQK_B 0xeb4 -#define RTX_POWER_AFTER_IQK_B 0xebc - -#define RRX_POWER_BEFORE_IQK_B 0xec0 -#define RRX_POWER_BEFORE_IQK_B_2 0xec4 -#define RRX_POWER_AFTER_IQK_B 0xec8 -#define RRX_POWER_AFTER_IQK_B_2 0xecc - -#define RRX_OFDM 0xed0 -#define RRX_WAIT_RIFS 0xed4 -#define RRX_TO_RX 0xed8 -#define RSTANDBY 0xedc -#define RSLEEP 0xee0 -#define RPMPD_ANAEN 0xeec - -#define RZEBRA1_HSSIENABLE 0x0 -#define RZEBRA1_TRXENABLE1 0x1 -#define RZEBRA1_TRXENABLE2 0x2 -#define RZEBRA1_AGC 0x4 -#define RZEBRA1_CHARGEPUMP 0x5 -#define RZEBRA1_CHANNEL 0x7 - -#define RZEBRA1_TXGAIN 0x8 -#define RZEBRA1_TXLPF 0x9 -#define RZEBRA1_RXLPF 0xb -#define RZEBRA1_RXHPFCORNER 0xc - -#define RGLOBALCTRL 0 -#define RRTL8256_TXLPF 19 -#define RRTL8256_RXLPF 11 -#define RRTL8258_TXLPF 0x11 -#define RRTL8258_RXLPF 0x13 -#define RRTL8258_RSSILPF 0xa - -#define RF_AC 0x00 - -#define RF_IQADJ_G1 0x01 -#define RF_IQADJ_G2 0x02 -#define RF_POW_TRSW 0x05 - -#define RF_GAIN_RX 0x06 -#define RF_GAIN_TX 0x07 - -#define RF_TXM_IDAC 0x08 -#define RF_BS_IQGEN 0x0F - -#define RF_MODE1 0x10 -#define RF_MODE2 0x11 - -#define RF_RX_AGC_HP 0x12 -#define RF_TX_AGC 0x13 -#define RF_BIAS 0x14 -#define RF_IPA 0x15 -#define RF_POW_ABILITY 0x17 -#define RF_MODE_AG 0x18 -#define RRFCHANNEL 0x18 -#define RF_CHNLBW 0x18 -#define RF_TOP 0x19 - -#define RF_RX_G1 0x1A -#define RF_RX_G2 0x1B - -#define RF_RX_BB2 0x1C -#define RF_RX_BB1 0x1D - -#define RF_RCK1 0x1E -#define RF_RCK2 0x1F - -#define RF_TX_G1 0x20 -#define RF_TX_G2 0x21 -#define RF_TX_G3 0x22 - -#define RF_TX_BB1 0x23 -#define RF_T_METER 0x42 - -#define RF_SYN_G1 0x25 -#define RF_SYN_G2 0x26 -#define RF_SYN_G3 0x27 -#define RF_SYN_G4 0x28 -#define RF_SYN_G5 0x29 -#define RF_SYN_G6 0x2A -#define RF_SYN_G7 0x2B -#define RF_SYN_G8 0x2C - -#define RF_RCK_OS 0x30 -#define RF_TXPA_G1 0x31 -#define RF_TXPA_G2 0x32 -#define RF_TXPA_G3 0x33 - -#define RF_TX_BIAS_A 0x35 -#define RF_TX_BIAS_D 0x36 -#define RF_LOBF_9 0x38 -#define RF_RXRF_A3 0x3C -#define RF_TRSW 0x3F - -#define RF_TXRF_A2 0x41 -#define RF_TXPA_G4 0x46 -#define RF_TXPA_A4 0x4B - -#define RF_WE_LUT 0xEF - -#define BBBRESETB 0x100 -#define BGLOBALRESETB 0x200 -#define BOFDMTXSTART 0x4 -#define BCCKTXSTART 0x8 -#define BCRC32DEBUG 0x100 -#define BPMACLOOPBACK 0x10 -#define BTXLSIG 0xffffff -#define BOFDMTXRATE 0xf -#define BOFDMTXRESERVED 0x10 -#define BOFDMTXLENGTH 0x1ffe0 -#define BOFDMTXPARITY 0x20000 -#define BTXHTSIG1 0xffffff -#define BTXHTMCSRATE 0x7f -#define BTXHTBW 0x80 -#define BTXHTLENGTH 0xffff00 -#define BTXHTSIG2 0xffffff -#define BTXHTSMOOTHING 0x1 -#define BTXHTSOUNDING 0x2 -#define BTXHTRESERVED 0x4 -#define BTXHTAGGREATION 0x8 -#define BTXHTSTBC 0x30 -#define BTXHTADVANCECODING 0x40 -#define BTXHTSHORTGI 0x80 -#define BTXHTNUMBERHT_LTF 0x300 -#define BTXHTCRC8 0x3fc00 -#define BCOUNTERRESET 0x10000 -#define BNUMOFOFDMTX 0xffff -#define BNUMOFCCKTX 0xffff0000 -#define BTXIDLEINTERVAL 0xffff -#define BOFDMSERVICE 0xffff0000 -#define BTXMACHEADER 0xffffffff -#define BTXDATAINIT 0xff -#define BTXHTMODE 0x100 -#define BTXDATATYPE 0x30000 -#define BTXRANDOMSEED 0xffffffff -#define BCCKTXPREAMBLE 0x1 -#define BCCKTXSFD 0xffff0000 -#define BCCKTXSIG 0xff -#define BCCKTXSERVICE 0xff00 -#define BCCKLENGTHEXT 0x8000 -#define BCCKTXLENGHT 0xffff0000 -#define BCCKTXCRC16 0xffff -#define BCCKTXSTATUS 0x1 -#define BOFDMTXSTATUS 0x2 -#define IS_BB_REG_OFFSET_92S(_offset) \ - ((_offset >= 0x800) && (_offset <= 0xfff)) - -#define BRFMOD 0x1 -#define BJAPANMODE 0x2 -#define BCCKTXSC 0x30 -#define BCCKEN 0x1000000 -#define BOFDMEN 0x2000000 - -#define BOFDMRXADCPHASE 0x10000 -#define BOFDMTXDACPHASE 0x40000 -#define BXATXAGC 0x3f - -#define BXBTXAGC 0xf00 -#define BXCTXAGC 0xf000 -#define BXDTXAGC 0xf0000 - -#define BPASTART 0xf0000000 -#define BTRSTART 0x00f00000 -#define BRFSTART 0x0000f000 -#define BBBSTART 0x000000f0 -#define BBBCCKSTART 0x0000000f -#define BPAEND 0xf -#define BTREND 0x0f000000 -#define BRFEND 0x000f0000 -#define BCCAMASK 0x000000f0 -#define BR2RCCAMASK 0x00000f00 -#define BHSSI_R2TDELAY 0xf8000000 -#define BHSSI_T2RDELAY 0xf80000 -#define BCONTXHSSI 0x400 -#define BIGFROMCCK 0x200 -#define BAGCADDRESS 0x3f -#define BRXHPTX 0x7000 -#define BRXHP2RX 0x38000 -#define BRXHPCCKINI 0xc0000 -#define BAGCTXCODE 0xc00000 -#define BAGCRXCODE 0x300000 - -#define B3WIREDATALENGTH 0x800 -#define B3WIREADDREAALENGTH 0x400 - -#define B3WIRERFPOWERDOWN 0x1 -#define B5GPAPEPOLARITY 0x40000000 -#define B2GPAPEPOLARITY 0x80000000 -#define BRFSW_TXDEFAULTANT 0x3 -#define BRFSW_TXOPTIONANT 0x30 -#define BRFSW_RXDEFAULTANT 0x300 -#define BRFSW_RXOPTIONANT 0x3000 -#define BRFSI_3WIREDATA 0x1 -#define BRFSI_3WIRECLOCK 0x2 -#define BRFSI_3WIRELOAD 0x4 -#define BRFSI_3WIRERW 0x8 -#define BRFSI_3WIRE 0xf - -#define BRFSI_RFENV 0x10 - -#define BRFSI_TRSW 0x20 -#define BRFSI_TRSWB 0x40 -#define BRFSI_ANTSW 0x100 -#define BRFSI_ANTSWB 0x200 -#define BRFSI_PAPE 0x400 -#define BRFSI_PAPE5G 0x800 -#define BBANDSELECT 0x1 -#define BHTSIG2_GI 0x80 -#define BHTSIG2_SMOOTHING 0x01 -#define BHTSIG2_SOUNDING 0x02 -#define BHTSIG2_AGGREATON 0x08 -#define BHTSIG2_STBC 0x30 -#define BHTSIG2_ADVCODING 0x40 -#define BHTSIG2_NUMOFHTLTF 0x300 -#define BHTSIG2_CRC8 0x3fc -#define BHTSIG1_MCS 0x7f -#define BHTSIG1_BANDWIDTH 0x80 -#define BHTSIG1_HTLENGTH 0xffff -#define BLSIG_RATE 0xf -#define BLSIG_RESERVED 0x10 -#define BLSIG_LENGTH 0x1fffe -#define BLSIG_PARITY 0x20 -#define BCCKRXPHASE 0x4 - -#define BLSSIREADADDRESS 0x7f800000 -#define BLSSIREADEDGE 0x80000000 - -#define BLSSIREADBACKDATA 0xfffff - -#define BLSSIREADOKFLAG 0x1000 -#define BCCKSAMPLERATE 0x8 -#define BREGULATOR0STANDBY 0x1 -#define BREGULATORPLLSTANDBY 0x2 -#define BREGULATOR1STANDBY 0x4 -#define BPLLPOWERUP 0x8 -#define BDPLLPOWERUP 0x10 -#define BDA10POWERUP 0x20 -#define BAD7POWERUP 0x200 -#define BDA6POWERUP 0x2000 -#define BXTALPOWERUP 0x4000 -#define B40MDCLKPOWERUP 0x8000 -#define BDA6DEBUGMODE 0x20000 -#define BDA6SWING 0x380000 - -#define BADCLKPHASE 0x4000000 -#define B80MCLKDELAY 0x18000000 -#define BAFEWATCHDOGENABLE 0x20000000 - -#define BXTALCAP01 0xc0000000 -#define BXTALCAP23 0x3 -#define BXTALCAP92X 0x0f000000 -#define BXTALCAP 0x0f000000 - -#define BINTDIFCLKENABLE 0x400 -#define BEXTSIGCLKENABLE 0x800 -#define BBANDGAP_MBIAS_POWERUP 0x10000 -#define BAD11SH_GAIN 0xc0000 -#define BAD11NPUT_RANGE 0x700000 -#define BAD110P_CURRENT 0x3800000 -#define BLPATH_LOOPBACK 0x4000000 -#define BQPATH_LOOPBACK 0x8000000 -#define BAFE_LOOPBACK 0x10000000 -#define BDA10_SWING 0x7e0 -#define BDA10_REVERSE 0x800 -#define BDA_CLK_SOURCE 0x1000 -#define BDA7INPUT_RANGE 0x6000 -#define BDA7_GAIN 0x38000 -#define BDA7OUTPUT_CM_MODE 0x40000 -#define BDA7INPUT_CM_MODE 0x380000 -#define BDA7CURRENT 0xc00000 -#define BREGULATOR_ADJUST 0x7000000 -#define BAD11POWERUP_ATTX 0x1 -#define BDA10PS_ATTX 0x10 -#define BAD11POWERUP_ATRX 0x100 -#define BDA10PS_ATRX 0x1000 -#define BCCKRX_AGC_FORMAT 0x200 -#define BPSDFFT_SAMPLE_POINT 0xc000 -#define BPSD_AVERAGE_NUM 0x3000 -#define BIQPATH_CONTROL 0xc00 -#define BPSD_FREQ 0x3ff -#define BPSD_ANTENNA_PATH 0x30 -#define BPSD_IQ_SWITCH 0x40 -#define BPSD_RX_TRIGGER 0x400000 -#define BPSD_TX_TRIGGER 0x80000000 -#define BPSD_SINE_TONE_SCALE 0x7f000000 -#define BPSD_REPORT 0xffff - -#define BOFDM_TXSC 0x30000000 -#define BCCK_TXON 0x1 -#define BOFDM_TXON 0x2 -#define BDEBUG_PAGE 0xfff -#define BDEBUG_ITEM 0xff -#define BANTL 0x10 -#define BANT_NONHT 0x100 -#define BANT_HT1 0x1000 -#define BANT_HT2 0x10000 -#define BANT_HT1S1 0x100000 -#define BANT_NONHTS1 0x1000000 - -#define BCCK_BBMODE 0x3 -#define BCCK_TXPOWERSAVING 0x80 -#define BCCK_RXPOWERSAVING 0x40 - -#define BCCK_SIDEBAND 0x10 - -#define BCCK_SCRAMBLE 0x8 -#define BCCK_ANTDIVERSITY 0x8000 -#define BCCK_CARRIER_RECOVERY 0x4000 -#define BCCK_TXRATE 0x3000 -#define BCCK_DCCANCEL 0x0800 -#define BCCK_ISICANCEL 0x0400 -#define BCCK_MATCH_FILTER 0x0200 -#define BCCK_EQUALIZER 0x0100 -#define BCCK_PREAMBLE_DETECT 0x800000 -#define BCCK_FAST_FALSECCA 0x400000 -#define BCCK_CH_ESTSTART 0x300000 -#define BCCK_CCA_COUNT 0x080000 -#define BCCK_CS_LIM 0x070000 -#define BCCK_BIST_MODE 0x80000000 -#define BCCK_CCAMASK 0x40000000 -#define BCCK_TX_DAC_PHASE 0x4 -#define BCCK_RX_ADC_PHASE 0x20000000 -#define BCCKR_CP_MODE 0x0100 -#define BCCK_TXDC_OFFSET 0xf0 -#define BCCK_RXDC_OFFSET 0xf -#define BCCK_CCA_MODE 0xc000 -#define BCCK_FALSECS_LIM 0x3f00 -#define BCCK_CS_RATIO 0xc00000 -#define BCCK_CORGBIT_SEL 0x300000 -#define BCCK_PD_LIM 0x0f0000 -#define BCCK_NEWCCA 0x80000000 -#define BCCK_RXHP_OF_IG 0x8000 -#define BCCK_RXIG 0x7f00 -#define BCCK_LNA_POLARITY 0x800000 -#define BCCK_RX1ST_BAIN 0x7f0000 -#define BCCK_RF_EXTEND 0x20000000 -#define BCCK_RXAGC_SATLEVEL 0x1f000000 -#define BCCK_RXAGC_SATCOUNT 0xe0 -#define BCCKRXRFSETTLE 0x1f -#define BCCK_FIXED_RXAGC 0x8000 -#define BCCK_ANTENNA_POLARITY 0x2000 -#define BCCK_TXFILTER_TYPE 0x0c00 -#define BCCK_RXAGC_REPORTTYPE 0x0300 -#define BCCK_RXDAGC_EN 0x80000000 -#define BCCK_RXDAGC_PERIOD 0x20000000 -#define BCCK_RXDAGC_SATLEVEL 0x1f000000 -#define BCCK_TIMING_RECOVERY 0x800000 -#define BCCK_TXC0 0x3f0000 -#define BCCK_TXC1 0x3f000000 -#define BCCK_TXC2 0x3f -#define BCCK_TXC3 0x3f00 -#define BCCK_TXC4 0x3f0000 -#define BCCK_TXC5 0x3f000000 -#define BCCK_TXC6 0x3f -#define BCCK_TXC7 0x3f00 -#define BCCK_DEBUGPORT 0xff0000 -#define BCCK_DAC_DEBUG 0x0f000000 -#define BCCK_FALSEALARM_ENABLE 0x8000 -#define BCCK_FALSEALARM_READ 0x4000 -#define BCCK_TRSSI 0x7f -#define BCCK_RXAGC_REPORT 0xfe -#define BCCK_RXREPORT_ANTSEL 0x80000000 -#define BCCK_RXREPORT_MFOFF 0x40000000 -#define BCCK_RXREPORT_SQLOSS 0x20000000 -#define BCCK_RXREPORT_PKTLOSS 0x10000000 -#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 -#define BCCK_RXREPORT_RATEERROR 0x04000000 -#define BCCK_RXREPORT_RXRATE 0x03000000 -#define BCCK_RXFA_COUNTER_LOWER 0xff -#define BCCK_RXFA_COUNTER_UPPER 0xff000000 -#define BCCK_RXHPAGC_START 0xe000 -#define BCCK_RXHPAGC_FINAL 0x1c00 -#define BCCK_RXFALSEALARM_ENABLE 0x8000 -#define BCCK_FACOUNTER_FREEZE 0x4000 -#define BCCK_TXPATH_SEL 0x10000000 -#define BCCK_DEFAULT_RXPATH 0xc000000 -#define BCCK_OPTION_RXPATH 0x3000000 - -#define BNUM_OFSTF 0x3 -#define BSHIFT_L 0xc0 -#define BGI_TH 0xc -#define BRXPATH_A 0x1 -#define BRXPATH_B 0x2 -#define BRXPATH_C 0x4 -#define BRXPATH_D 0x8 -#define BTXPATH_A 0x1 -#define BTXPATH_B 0x2 -#define BTXPATH_C 0x4 -#define BTXPATH_D 0x8 -#define BTRSSI_FREQ 0x200 -#define BADC_BACKOFF 0x3000 -#define BDFIR_BACKOFF 0xc000 -#define BTRSSI_LATCH_PHASE 0x10000 -#define BRX_LDC_OFFSET 0xff -#define BRX_QDC_OFFSET 0xff00 -#define BRX_DFIR_MODE 0x1800000 -#define BRX_DCNF_TYPE 0xe000000 -#define BRXIQIMB_A 0x3ff -#define BRXIQIMB_B 0xfc00 -#define BRXIQIMB_C 0x3f0000 -#define BRXIQIMB_D 0xffc00000 -#define BDC_DC_NOTCH 0x60000 -#define BRXNB_NOTCH 0x1f000000 -#define BPD_TH 0xf -#define BPD_TH_OPT2 0xc000 -#define BPWED_TH 0x700 -#define BIFMF_WIN_L 0x800 -#define BPD_OPTION 0x1000 -#define BMF_WIN_L 0xe000 -#define BBW_SEARCH_L 0x30000 -#define BWIN_ENH_L 0xc0000 -#define BBW_TH 0x700000 -#define BED_TH2 0x3800000 -#define BBW_OPTION 0x4000000 -#define BRADIO_TH 0x18000000 -#define BWINDOW_L 0xe0000000 -#define BSBD_OPTION 0x1 -#define BFRAME_TH 0x1c -#define BFS_OPTION 0x60 -#define BDC_SLOPE_CHECK 0x80 -#define BFGUARD_COUNTER_DC_L 0xe00 -#define BFRAME_WEIGHT_SHORT 0x7000 -#define BSUB_TUNE 0xe00000 -#define BFRAME_DC_LENGTH 0xe000000 -#define BSBD_START_OFFSET 0x30000000 -#define BFRAME_TH_2 0x7 -#define BFRAME_GI2_TH 0x38 -#define BGI2_SYNC_EN 0x40 -#define BSARCH_SHORT_EARLY 0x300 -#define BSARCH_SHORT_LATE 0xc00 -#define BSARCH_GI2_LATE 0x70000 -#define BCFOANTSUM 0x1 -#define BCFOACC 0x2 -#define BCFOSTARTOFFSET 0xc -#define BCFOLOOPBACK 0x70 -#define BCFOSUMWEIGHT 0x80 -#define BDAGCENABLE 0x10000 -#define BTXIQIMB_A 0x3ff -#define BTXIQIMB_b 0xfc00 -#define BTXIQIMB_C 0x3f0000 -#define BTXIQIMB_D 0xffc00000 -#define BTXIDCOFFSET 0xff -#define BTXIQDCOFFSET 0xff00 -#define BTXDFIRMODE 0x10000 -#define BTXPESUDO_NOISEON 0x4000000 -#define BTXPESUDO_NOISE_A 0xff -#define BTXPESUDO_NOISE_B 0xff00 -#define BTXPESUDO_NOISE_C 0xff0000 -#define BTXPESUDO_NOISE_D 0xff000000 -#define BCCA_DROPOPTION 0x20000 -#define BCCA_DROPTHRES 0xfff00000 -#define BEDCCA_H 0xf -#define BEDCCA_L 0xf0 -#define BLAMBDA_ED 0x300 -#define BRX_INITIALGAIN 0x7f -#define BRX_ANTDIV_EN 0x80 -#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 -#define BRX_HIGHPOWER_FLOW 0x8000 -#define BRX_AGC_FREEZE_THRES 0xc0000 -#define BRX_FREEZESTEP_AGC1 0x300000 -#define BRX_FREEZESTEP_AGC2 0xc00000 -#define BRX_FREEZESTEP_AGC3 0x3000000 -#define BRX_FREEZESTEP_AGC0 0xc000000 -#define BRXRSSI_CMP_EN 0x10000000 -#define BRXQUICK_AGCEN 0x20000000 -#define BRXAGC_FREEZE_THRES_MODE 0x40000000 -#define BRX_OVERFLOW_CHECKTYPE 0x80000000 -#define BRX_AGCSHIFT 0x7f -#define BTRSW_TRI_ONLY 0x80 -#define BPOWER_THRES 0x300 -#define BRXAGC_EN 0x1 -#define BRXAGC_TOGETHER_EN 0x2 -#define BRXAGC_MIN 0x4 -#define BRXHP_INI 0x7 -#define BRXHP_TRLNA 0x70 -#define BRXHP_RSSI 0x700 -#define BRXHP_BBP1 0x7000 -#define BRXHP_BBP2 0x70000 -#define BRXHP_BBP3 0x700000 -#define BRSSI_H 0x7f0000 -#define BRSSI_GEN 0x7f000000 -#define BRXSETTLE_TRSW 0x7 -#define BRXSETTLE_LNA 0x38 -#define BRXSETTLE_RSSI 0x1c0 -#define BRXSETTLE_BBP 0xe00 -#define BRXSETTLE_RXHP 0x7000 -#define BRXSETTLE_ANTSW_RSSI 0x38000 -#define BRXSETTLE_ANTSW 0xc0000 -#define BRXPROCESS_TIME_DAGC 0x300000 -#define BRXSETTLE_HSSI 0x400000 -#define BRXPROCESS_TIME_BBPPW 0x800000 -#define BRXANTENNA_POWER_SHIFT 0x3000000 -#define BRSSI_TABLE_SELECT 0xc000000 -#define BRXHP_FINAL 0x7000000 -#define BRXHPSETTLE_BBP 0x7 -#define BRXHTSETTLE_HSSI 0x8 -#define BRXHTSETTLE_RXHP 0x70 -#define BRXHTSETTLE_BBPPW 0x80 -#define BRXHTSETTLE_IDLE 0x300 -#define BRXHTSETTLE_RESERVED 0x1c00 -#define BRXHT_RXHP_EN 0x8000 -#define BRXAGC_FREEZE_THRES 0x30000 -#define BRXAGC_TOGETHEREN 0x40000 -#define BRXHTAGC_MIN 0x80000 -#define BRXHTAGC_EN 0x100000 -#define BRXHTDAGC_EN 0x200000 -#define BRXHT_RXHP_BBP 0x1c00000 -#define BRXHT_RXHP_FINAL 0xe0000000 -#define BRXPW_RADIO_TH 0x3 -#define BRXPW_RADIO_EN 0x4 -#define BRXMF_HOLD 0x3800 -#define BRXPD_DELAY_TH1 0x38 -#define BRXPD_DELAY_TH2 0x1c0 -#define BRXPD_DC_COUNT_MAX 0x600 -#define BRXPD_DELAY_TH 0x8000 -#define BRXPROCESS_DELAY 0xf0000 -#define BRXSEARCHRANGE_GI2_EARLY 0x700000 -#define BRXFRAME_FUARD_COUNTER_L 0x3800000 -#define BRXSGI_GUARD_L 0xc000000 -#define BRXSGI_SEARCH_L 0x30000000 -#define BRXSGI_TH 0xc0000000 -#define BDFSCNT0 0xff -#define BDFSCNT1 0xff00 -#define BDFSFLAG 0xf0000 -#define BMF_WEIGHT_SUM 0x300000 -#define BMINIDX_TH 0x7f000000 -#define BDAFORMAT 0x40000 -#define BTXCH_EMU_ENABLE 0x01000000 -#define BTRSW_ISOLATION_A 0x7f -#define BTRSW_ISOLATION_B 0x7f00 -#define BTRSW_ISOLATION_C 0x7f0000 -#define BTRSW_ISOLATION_D 0x7f000000 -#define BEXT_LNA_GAIN 0x7c00 - -#define BSTBC_EN 0x4 -#define BANTENNA_MAPPING 0x10 -#define BNSS 0x20 -#define BCFO_ANTSUM_ID 0x200 -#define BPHY_COUNTER_RESET 0x8000000 -#define BCFO_REPORT_GET 0x4000000 -#define BOFDM_CONTINUE_TX 0x10000000 -#define BOFDM_SINGLE_CARRIER 0x20000000 -#define BOFDM_SINGLE_TONE 0x40000000 -#define BHT_DETECT 0x100 -#define BCFOEN 0x10000 -#define BCFOVALUE 0xfff00000 -#define BSIGTONE_RE 0x3f -#define BSIGTONE_IM 0x7f00 -#define BCOUNTER_CCA 0xffff -#define BCOUNTER_PARITYFAIL 0xffff0000 -#define BCOUNTER_RATEILLEGAL 0xffff -#define BCOUNTER_CRC8FAIL 0xffff0000 -#define BCOUNTER_MCSNOSUPPORT 0xffff -#define BCOUNTER_FASTSYNC 0xffff -#define BSHORTCFO 0xfff -#define BSHORTCFOT_LENGTH 12 -#define BSHORTCFOF_LENGTH 11 -#define BLONGCFO 0x7ff -#define BLONGCFOT_LENGTH 11 -#define BLONGCFOF_LENGTH 11 -#define BTAILCFO 0x1fff -#define BTAILCFOT_LENGTH 13 -#define BTAILCFOF_LENGTH 12 -#define BNOISE_EN_PWDB 0xffff -#define BCC_POWER_DB 0xffff0000 -#define BMOISE_PWDB 0xffff -#define BPOWERMEAST_LENGTH 10 -#define BPOWERMEASF_LENGTH 3 -#define BRX_HT_BW 0x1 -#define BRXSC 0x6 -#define BRX_HT 0x8 -#define BNB_INTF_DET_ON 0x1 -#define BINTF_WIN_LEN_CFG 0x30 -#define BNB_INTF_TH_CFG 0x1c0 -#define BRFGAIN 0x3f -#define BTABLESEL 0x40 -#define BTRSW 0x80 -#define BRXSNR_A 0xff -#define BRXSNR_B 0xff00 -#define BRXSNR_C 0xff0000 -#define BRXSNR_D 0xff000000 -#define BSNR_EVMT_LENGTH 8 -#define BSNR_EVMF_LENGTH 1 -#define BCSI1ST 0xff -#define BCSI2ND 0xff00 -#define BRXEVM1ST 0xff0000 -#define BRXEVM2ND 0xff000000 -#define BSIGEVM 0xff -#define BPWDB 0xff00 -#define BSGIEN 0x10000 - -#define BSFACTOR_QMA1 0xf -#define BSFACTOR_QMA2 0xf0 -#define BSFACTOR_QMA3 0xf00 -#define BSFACTOR_QMA4 0xf000 -#define BSFACTOR_QMA5 0xf0000 -#define BSFACTOR_QMA6 0xf0000 -#define BSFACTOR_QMA7 0xf00000 -#define BSFACTOR_QMA8 0xf000000 -#define BSFACTOR_QMA9 0xf0000000 -#define BCSI_SCHEME 0x100000 - -#define BNOISE_LVL_TOP_SET 0x3 -#define BCHSMOOTH 0x4 -#define BCHSMOOTH_CFG1 0x38 -#define BCHSMOOTH_CFG2 0x1c0 -#define BCHSMOOTH_CFG3 0xe00 -#define BCHSMOOTH_CFG4 0x7000 -#define BMRCMODE 0x800000 -#define BTHEVMCFG 0x7000000 - -#define BLOOP_FIT_TYPE 0x1 -#define BUPD_CFO 0x40 -#define BUPD_CFO_OFFDATA 0x80 -#define BADV_UPD_CFO 0x100 -#define BADV_TIME_CTRL 0x800 -#define BUPD_CLKO 0x1000 -#define BFC 0x6000 -#define BTRACKING_MODE 0x8000 -#define BPHCMP_ENABLE 0x10000 -#define BUPD_CLKO_LTF 0x20000 -#define BCOM_CH_CFO 0x40000 -#define BCSI_ESTI_MODE 0x80000 -#define BADV_UPD_EQZ 0x100000 -#define BUCHCFG 0x7000000 -#define BUPDEQZ 0x8000000 - -#define BRX_PESUDO_NOISE_ON 0x20000000 -#define BRX_PESUDO_NOISE_A 0xff -#define BRX_PESUDO_NOISE_B 0xff00 -#define BRX_PESUDO_NOISE_C 0xff0000 -#define BRX_PESUDO_NOISE_D 0xff000000 -#define BRX_PESUDO_NOISESTATE_A 0xffff -#define BRX_PESUDO_NOISESTATE_B 0xffff0000 -#define BRX_PESUDO_NOISESTATE_C 0xffff -#define BRX_PESUDO_NOISESTATE_D 0xffff0000 - -#define BZEBRA1_HSSIENABLE 0x8 -#define BZEBRA1_TRXCONTROL 0xc00 -#define BZEBRA1_TRXGAINSETTING 0x07f -#define BZEBRA1_RXCOUNTER 0xc00 -#define BZEBRA1_TXCHANGEPUMP 0x38 -#define BZEBRA1_RXCHANGEPUMP 0x7 -#define BZEBRA1_CHANNEL_NUM 0xf80 -#define BZEBRA1_TXLPFBW 0x400 -#define BZEBRA1_RXLPFBW 0x600 - -#define BRTL8256REG_MODE_CTRL1 0x100 -#define BRTL8256REG_MODE_CTRL0 0x40 -#define BRTL8256REG_TXLPFBW 0x18 -#define BRTL8256REG_RXLPFBW 0x600 - -#define BRTL8258_TXLPFBW 0xc -#define BRTL8258_RXLPFBW 0xc00 -#define BRTL8258_RSSILPFBW 0xc0 - -#define BBYTE0 0x1 -#define BBYTE1 0x2 -#define BBYTE2 0x4 -#define BBYTE3 0x8 -#define BWORD0 0x3 -#define BWORD1 0xc -#define BWORD 0xf - -#define MASKBYTE0 0xff -#define MASKBYTE1 0xff00 -#define MASKBYTE2 0xff0000 -#define MASKBYTE3 0xff000000 -#define MASKHWORD 0xffff0000 -#define MASKLWORD 0x0000ffff -#define MASKDWORD 0xffffffff -#define MASK12BITS 0xfff -#define MASKH4BITS 0xf0000000 -#define MASKOFDM_D 0xffc00000 -#define MASKCCK 0x3f3f3f3f - -#define MASK4BITS 0x0f -#define MASK20BITS 0xfffff -#define RFREG_OFFSET_MASK 0xfffff - -#define BENABLE 0x1 -#define BDISABLE 0x0 - -#define LEFT_ANTENNA 0x0 -#define RIGHT_ANTENNA 0x1 - -#define TCHECK_TXSTATUS 500 -#define TUPDATE_RXCOUNTER 100 - -#define REG_UN_used_register 0x01bf - -/* WOL bit information */ -#define HAL92C_WOL_PTK_UPDATE_EVENT BIT(0) -#define HAL92C_WOL_GTK_UPDATE_EVENT BIT(1) -#define HAL92C_WOL_DISASSOC_EVENT BIT(2) -#define HAL92C_WOL_DEAUTH_EVENT BIT(3) -#define HAL92C_WOL_FW_DISCONNECT_EVENT BIT(4) - -#define WOL_REASON_PTK_UPDATE BIT(0) -#define WOL_REASON_GTK_UPDATE BIT(1) -#define WOL_REASON_DISASSOC BIT(2) -#define WOL_REASON_DEAUTH BIT(3) -#define WOL_REASON_FW_DISCONNECT BIT(4) - -/* 2 EFUSE_TEST (For RTL8723 partially) */ -#define EFUSE_SEL(x) (((x) & 0x3) << 8) -#define EFUSE_SEL_MASK 0x300 -#define EFUSE_WIFI_SEL_0 0x0 - -#define WL_HWPDN_EN BIT(0) /* Enable GPIO[9] as WiFi HW PDn source*/ -#define WL_HWPDN_SL BIT(1) /* WiFi HW PDn polarity control*/ - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/rf.c b/drivers/net/wireless/rtlwifi/rtl8723be/rf.c deleted file mode 100644 index 5ed4492d3c80..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/rf.c +++ /dev/null @@ -1,512 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" - -static bool _rtl8723be_phy_rf6052_config_parafile(struct ieee80211_hw *hw); - -void rtl8723be_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - switch (bandwidth) { - case HT_CHANNEL_WIDTH_20: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff) | BIT(10) | BIT(11)); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - case HT_CHANNEL_WIDTH_20_40: - rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & - 0xfffff3ff) | BIT(10)); - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, - rtlphy->rfreg_chnlval[0]); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", bandwidth); - break; - } -} - -void rtl8723be_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 tx_agc[2] = {0, 0}, tmpval; - bool turbo_scanoff = false; - u8 idx1, idx2; - u8 *ptr; - u8 direction; - u32 pwrtrac_value; - - if (rtlefuse->eeprom_regulatory != 0) - turbo_scanoff = true; - - if (mac->act_scanning) { - tx_agc[RF90_PATH_A] = 0x3f3f3f3f; - tx_agc[RF90_PATH_B] = 0x3f3f3f3f; - - if (turbo_scanoff) { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - } - } else { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - - if (rtlefuse->eeprom_regulatory == 0) { - tmpval = - (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + - (rtlphy->mcs_txpwrlevel_origoffset[0][7] << 8); - tx_agc[RF90_PATH_A] += tmpval; - - tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + - (rtlphy->mcs_txpwrlevel_origoffset[0][15] << - 24); - tx_agc[RF90_PATH_B] += tmpval; - } - } - - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - ptr = (u8 *)(&(tx_agc[idx1])); - for (idx2 = 0; idx2 < 4; idx2++) { - if (*ptr > RF6052_MAX_TX_PWR) - *ptr = RF6052_MAX_TX_PWR; - ptr++; - } - } - rtl8723be_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); - if (direction == 1) { - tx_agc[0] += pwrtrac_value; - tx_agc[1] += pwrtrac_value; - } else if (direction == 2) { - tx_agc[0] -= pwrtrac_value; - tx_agc[1] -= pwrtrac_value; - } - tmpval = tx_agc[RF90_PATH_A] & 0xff; - rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_A_CCK1_MCS32); - - tmpval = tx_agc[RF90_PATH_A] >> 8; - - /*tmpval = tmpval & 0xff00ffff;*/ - - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_B_CCK11_A_CCK2_11); - - tmpval = tx_agc[RF90_PATH_B] >> 24; - rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_B_CCK11_A_CCK2_11); - - tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; - rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_B_CCK1_55_MCS32); -} - -static void rtl8723be_phy_get_power_base(struct ieee80211_hw *hw, - u8 *ppowerlevel_ofdm, - u8 *ppowerlevel_bw20, - u8 *ppowerlevel_bw40, - u8 channel, u32 *ofdmbase, - u32 *mcsbase) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 powerbase0, powerbase1; - u8 i, powerlevel[2]; - - for (i = 0; i < 2; i++) { - powerbase0 = ppowerlevel_ofdm[i]; - - powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | - (powerbase0 << 8) | powerbase0; - *(ofdmbase + i) = powerbase0; - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [OFDM power base index rf(%c) = 0x%x]\n", - ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)); - } - - for (i = 0; i < 2; i++) { - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) - powerlevel[i] = ppowerlevel_bw20[i]; - else - powerlevel[i] = ppowerlevel_bw40[i]; - - powerbase1 = powerlevel[i]; - powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) | - (powerbase1 << 8) | powerbase1; - - *(mcsbase + i) = powerbase1; - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [MCS power base index rf(%c) = 0x%x]\n", - ((i == 0) ? 'A' : 'B'), *(mcsbase + i)); - } -} - -static void _rtl8723be_get_txpower_writeval_by_regulatory( - struct ieee80211_hw *hw, - u8 channel, u8 index, - u32 *powerbase0, - u32 *powerbase1, - u32 *p_outwriteval) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff; - u32 writeval, customer_limit, rf; - - for (rf = 0; rf < 2; rf++) { - switch (rtlefuse->eeprom_regulatory) { - case 0: - chnlgroup = 0; - - writeval = - rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index + - (rf ? 8 : 0)] - + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - case 1: - if (rtlphy->pwrgroup_cnt == 1) { - chnlgroup = 0; - } else { - if (channel < 3) - chnlgroup = 0; - else if (channel < 6) - chnlgroup = 1; - else if (channel < 9) - chnlgroup = 2; - else if (channel < 12) - chnlgroup = 3; - else if (channel < 14) - chnlgroup = 4; - else if (channel == 14) - chnlgroup = 5; - } - - writeval = - rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] - [index + (rf ? 8 : 0)] + ((index < 2) ? - powerbase0[rf] : - powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - - break; - case 2: - writeval = - ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Better regulatory, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - case 3: - chnlgroup = 0; - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 40MHz rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), - rtlefuse->pwrgroup_ht40 - [rf][channel - 1]); - } else { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 20MHz rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), - rtlefuse->pwrgroup_ht20 - [rf][channel - 1]); - } - - if (index < 2) - pwr_diff = - rtlefuse->txpwr_legacyhtdiff[rf][channel-1]; - else if (rtlphy->current_chan_bw == - HT_CHANNEL_WIDTH_20) - pwr_diff = - rtlefuse->txpwr_ht20diff[rf][channel-1]; - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) - customer_pwr_diff = - rtlefuse->pwrgroup_ht40[rf][channel-1]; - else - customer_pwr_diff = - rtlefuse->pwrgroup_ht20[rf][channel-1]; - - if (pwr_diff > customer_pwr_diff) - pwr_diff = 0; - else - pwr_diff = customer_pwr_diff - pwr_diff; - - for (i = 0; i < 4; i++) { - pwr_diff_limit[i] = - (u8)((rtlphy->mcs_txpwrlevel_origoffset - [chnlgroup][index + (rf ? 8 : 0)] & - (0x7f << (i * 8))) >> (i * 8)); - - if (pwr_diff_limit[i] > pwr_diff) - pwr_diff_limit[i] = pwr_diff; - } - - customer_limit = (pwr_diff_limit[3] << 24) | - (pwr_diff_limit[2] << 16) | - (pwr_diff_limit[1] << 8) | - (pwr_diff_limit[0]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer's limit rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), customer_limit); - - writeval = customer_limit + ((index < 2) ? - powerbase0[rf] : - powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer, writeval rf(%c)= 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - default: - chnlgroup = 0; - writeval = - rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] - [index + (rf ? 8 : 0)] - + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeval rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - } - - if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) - writeval = writeval - 0x06060606; - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_BT2) - writeval = writeval - 0x0c0c0c0c; - *(p_outwriteval + rf) = writeval; - } -} - -static void _rtl8723be_write_ofdm_power_reg(struct ieee80211_hw *hw, - u8 index, u32 *pvalue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 regoffset_a[6] = { - RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, - RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, - RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 - }; - u16 regoffset_b[6] = { - RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, - RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, - RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 - }; - u8 i, rf, pwr_val[4]; - u32 writeval; - u16 regoffset; - - for (rf = 0; rf < 2; rf++) { - writeval = pvalue[rf]; - for (i = 0; i < 4; i++) { - pwr_val[i] = (u8)((writeval & (0x7f << - (i * 8))) >> (i * 8)); - - if (pwr_val[i] > RF6052_MAX_TX_PWR) - pwr_val[i] = RF6052_MAX_TX_PWR; - } - writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | - (pwr_val[1] << 8) | pwr_val[0]; - - if (rf == 0) - regoffset = regoffset_a[index]; - else - regoffset = regoffset_b[index]; - rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Set 0x%x = %08x\n", regoffset, writeval); - } -} - -void rtl8723be_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel_ofdm, - u8 *ppowerlevel_bw20, - u8 *ppowerlevel_bw40, u8 channel) -{ - u32 writeval[2], powerbase0[2], powerbase1[2]; - u8 index; - u8 direction; - u32 pwrtrac_value; - - rtl8723be_phy_get_power_base(hw, ppowerlevel_ofdm, ppowerlevel_bw20, - ppowerlevel_bw40, channel, - &powerbase0[0], &powerbase1[0]); - - rtl8723be_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); - - for (index = 0; index < 6; index++) { - _rtl8723be_get_txpower_writeval_by_regulatory(hw, - channel, index, - &powerbase0[0], - &powerbase1[0], - &writeval[0]); - if (direction == 1) { - writeval[0] += pwrtrac_value; - writeval[1] += pwrtrac_value; - } else if (direction == 2) { - writeval[0] -= pwrtrac_value; - writeval[1] -= pwrtrac_value; - } - _rtl8723be_write_ofdm_power_reg(hw, index, &writeval[0]); - } -} - -bool rtl8723be_phy_rf6052_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - if (rtlphy->rf_type == RF_1T1R) - rtlphy->num_total_rfpath = 1; - else - rtlphy->num_total_rfpath = 2; - - return _rtl8723be_phy_rf6052_config_parafile(hw); - -} - -static bool _rtl8723be_phy_rf6052_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u32 u4_regvalue = 0; - u8 rfpath; - bool rtstatus = true; - struct bb_reg_def *pphyreg; - - for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { - pphyreg = &rtlphy->phyreg_def[rfpath]; - - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV); - break; - case RF90_PATH_B: - case RF90_PATH_D: - u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16); - break; - } - - rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, - B3WIREADDREAALENGTH, 0x0); - udelay(1); - - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); - udelay(1); - - switch (rfpath) { - case RF90_PATH_A: - rtstatus = rtl8723be_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_B: - rtstatus = rtl8723be_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_C: - break; - case RF90_PATH_D: - break; - } - - switch (rfpath) { - case RF90_PATH_A: - case RF90_PATH_C: - rtl_set_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV, u4_regvalue); - break; - case RF90_PATH_B: - case RF90_PATH_D: - rtl_set_bbreg(hw, pphyreg->rfintfs, - BRFSI_RFENV << 16, u4_regvalue); - break; - } - - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio[%d] Fail!!", rfpath); - return false; - } - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); - return rtstatus; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/rf.h b/drivers/net/wireless/rtlwifi/rtl8723be/rf.h deleted file mode 100644 index f423e157020f..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/rf.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723BE_RF_H__ -#define __RTL8723BE_RF_H__ - -#define RF6052_MAX_TX_PWR 0x3F - -void rtl8723be_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, - u8 bandwidth); -void rtl8723be_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -void rtl8723be_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel_ofdm, - u8 *ppowerlevel_bw20, - u8 *ppowerlevel_bw40, - u8 channel); -bool rtl8723be_phy_rf6052_config(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/rtlwifi/rtl8723be/sw.c deleted file mode 100644 index d091f1d5f91e..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c +++ /dev/null @@ -1,410 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../core.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "../rtl8723com/phy_common.h" -#include "dm.h" -#include "../rtl8723com/dm_common.h" -#include "hw.h" -#include "fw.h" -#include "../rtl8723com/fw_common.h" -#include "sw.h" -#include "trx.h" -#include "led.h" -#include "table.h" -#include "../btcoexist/rtl_btc.h" - -#include -#include - -static void rtl8723be_init_aspm_vars(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - /*close ASPM for AMD defaultly */ - rtlpci->const_amdpci_aspm = 0; - - /* ASPM PS mode. - * 0 - Disable ASPM, - * 1 - Enable ASPM without Clock Req, - * 2 - Enable ASPM with Clock Req, - * 3 - Alwyas Enable ASPM with Clock Req, - * 4 - Always Enable ASPM without Clock Req. - * set defult to RTL8192CE:3 RTL8192E:2 - */ - rtlpci->const_pci_aspm = 3; - - /*Setting for PCI-E device */ - rtlpci->const_devicepci_aspm_setting = 0x03; - - /*Setting for PCI-E bridge */ - rtlpci->const_hostpci_aspm_setting = 0x02; - - /* In Hw/Sw Radio Off situation. - * 0 - Default, - * 1 - From ASPM setting without low Mac Pwr, - * 2 - From ASPM setting with low Mac Pwr, - * 3 - Bus D3 - * set default to RTL8192CE:0 RTL8192SE:2 - */ - rtlpci->const_hwsw_rfoff_d3 = 0; - - /* This setting works for those device with - * backdoor ASPM setting such as EPHY setting. - * 0 - Not support ASPM, - * 1 - Support ASPM, - * 2 - According to chipset. - */ - rtlpci->const_support_pciaspm = 1; -} - -int rtl8723be_init_sw_vars(struct ieee80211_hw *hw) -{ - int err = 0; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - rtl8723be_bt_reg_init(hw); - rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; - rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); - - rtlpriv->dm.dm_initialgain_enable = 1; - rtlpriv->dm.dm_flag = 0; - rtlpriv->dm.disable_framebursting = 0; - rtlpriv->dm.thermalvalue = 0; - rtlpci->transmit_config = CFENDFORM | BIT(15) | BIT(24) | BIT(25); - - rtlpriv->phy.lck_inprogress = false; - - mac->ht_enable = true; - - /* compatible 5G band 88ce just 2.4G band & smsp */ - rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; - rtlpriv->rtlhal.bandset = BAND_ON_2_4G; - rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; - - rtlpci->receive_config = (RCR_APPFCS | - RCR_APP_MIC | - RCR_APP_ICV | - RCR_APP_PHYST_RXFF | - RCR_HTC_LOC_CTRL | - RCR_AMF | - RCR_ACF | - RCR_ADF | - RCR_AICV | - RCR_AB | - RCR_AM | - RCR_APM | - 0); - - rtlpci->irq_mask[0] = (u32) (IMR_PSTIMEOUT | - IMR_HSISR_IND_ON_INT | - IMR_C2HCMD | - IMR_HIGHDOK | - IMR_MGNTDOK | - IMR_BKDOK | - IMR_BEDOK | - IMR_VIDOK | - IMR_VODOK | - IMR_RDU | - IMR_ROK | - 0); - - rtlpci->irq_mask[1] = (u32)(IMR_RXFOVW | 0); - - rtlpci->sys_irq_mask = (u32)(HSIMR_PDN_INT_EN | - 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; - rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; - rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; - if (rtlpriv->cfg->mod_params->disable_watchdog) - pr_info("watchdog disabled\n"); - rtlpriv->psc.reg_fwctrl_lps = 3; - rtlpriv->psc.reg_max_lps_awakeintvl = 5; - /* for ASPM, you can close aspm through - * set const_support_pciaspm = 0 - */ - rtl8723be_init_aspm_vars(hw); - - if (rtlpriv->psc.reg_fwctrl_lps == 1) - rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 2) - rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 3) - rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; - - /*low power: Disable 32k */ - rtlpriv->psc.low_power_enable = false; - - rtlpriv->rtlhal.earlymode_enable = false; - - /* for firmware buf */ - rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); - if (!rtlpriv->rtlhal.pfirmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't alloc buffer for fw.\n"); - return 1; - } - - rtlpriv->max_fw_size = 0x8000; - pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); - err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, - rtlpriv->io.dev, GFP_KERNEL, hw, - rtl_fw_cb); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to request firmware!\n"); - return 1; - } - return 0; -} - -void rtl8723be_deinit_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->rtlhal.pfirmware) { - vfree(rtlpriv->rtlhal.pfirmware); - rtlpriv->rtlhal.pfirmware = NULL; - } -} - -/* get bt coexist status */ -bool rtl8723be_get_btc_status(void) -{ - return true; -} - -static bool is_fw_header(struct rtlwifi_firmware_header *hdr) -{ - return (le16_to_cpu(hdr->signature) & 0xfff0) == 0x5300; -} - -static struct rtl_hal_ops rtl8723be_hal_ops = { - .init_sw_vars = rtl8723be_init_sw_vars, - .deinit_sw_vars = rtl8723be_deinit_sw_vars, - .read_eeprom_info = rtl8723be_read_eeprom_info, - .interrupt_recognized = rtl8723be_interrupt_recognized, - .hw_init = rtl8723be_hw_init, - .hw_disable = rtl8723be_card_disable, - .hw_suspend = rtl8723be_suspend, - .hw_resume = rtl8723be_resume, - .enable_interrupt = rtl8723be_enable_interrupt, - .disable_interrupt = rtl8723be_disable_interrupt, - .set_network_type = rtl8723be_set_network_type, - .set_chk_bssid = rtl8723be_set_check_bssid, - .set_qos = rtl8723be_set_qos, - .set_bcn_reg = rtl8723be_set_beacon_related_registers, - .set_bcn_intv = rtl8723be_set_beacon_interval, - .update_interrupt_mask = rtl8723be_update_interrupt_mask, - .get_hw_reg = rtl8723be_get_hw_reg, - .set_hw_reg = rtl8723be_set_hw_reg, - .update_rate_tbl = rtl8723be_update_hal_rate_tbl, - .fill_tx_desc = rtl8723be_tx_fill_desc, - .fill_tx_cmddesc = rtl8723be_tx_fill_cmddesc, - .query_rx_desc = rtl8723be_rx_query_desc, - .set_channel_access = rtl8723be_update_channel_access_setting, - .radio_onoff_checking = rtl8723be_gpio_radio_on_off_checking, - .set_bw_mode = rtl8723be_phy_set_bw_mode, - .switch_channel = rtl8723be_phy_sw_chnl, - .dm_watchdog = rtl8723be_dm_watchdog, - .scan_operation_backup = rtl8723be_phy_scan_operation_backup, - .set_rf_power_state = rtl8723be_phy_set_rf_power_state, - .led_control = rtl8723be_led_control, - .set_desc = rtl8723be_set_desc, - .get_desc = rtl8723be_get_desc, - .is_tx_desc_closed = rtl8723be_is_tx_desc_closed, - .tx_polling = rtl8723be_tx_polling, - .enable_hw_sec = rtl8723be_enable_hw_security_config, - .set_key = rtl8723be_set_key, - .init_sw_leds = rtl8723be_init_sw_leds, - .get_bbreg = rtl8723_phy_query_bb_reg, - .set_bbreg = rtl8723_phy_set_bb_reg, - .get_rfreg = rtl8723be_phy_query_rf_reg, - .set_rfreg = rtl8723be_phy_set_rf_reg, - .fill_h2c_cmd = rtl8723be_fill_h2c_cmd, - .get_btc_status = rtl8723be_get_btc_status, - .rx_command_packet = rtl8723be_rx_command_packet, - .is_fw_header = is_fw_header, -}; - -static struct rtl_mod_params rtl8723be_mod_params = { - .sw_crypto = false, - .inactiveps = true, - .swctrl_lps = false, - .fwctrl_lps = true, -}; - -static struct rtl_hal_cfg rtl8723be_hal_cfg = { - .bar_id = 2, - .write_readback = true, - .name = "rtl8723be_pci", - .fw_name = "rtlwifi/rtl8723befw.bin", - .ops = &rtl8723be_hal_ops, - .mod_params = &rtl8723be_mod_params, - .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, - .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, - .maps[SYS_CLK] = REG_SYS_CLKR, - .maps[MAC_RCR_AM] = AM, - .maps[MAC_RCR_AB] = AB, - .maps[MAC_RCR_ACRC32] = ACRC32, - .maps[MAC_RCR_ACF] = ACF, - .maps[MAC_RCR_AAP] = AAP, - .maps[MAC_HIMR] = REG_HIMR, - .maps[MAC_HIMRE] = REG_HIMRE, - .maps[MAC_HSISR] = REG_HSISR, - - .maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS, - - .maps[EFUSE_TEST] = REG_EFUSE_TEST, - .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_CLK] = 0, - .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_PWC_EV12V] = PWC_EV12V, - .maps[EFUSE_FEN_ELDR] = FEN_ELDR, - .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, - .maps[EFUSE_ANA8M] = ANA8M, - .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, - .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, - .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, - .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, - - .maps[RWCAM] = REG_CAMCMD, - .maps[WCAMI] = REG_CAMWRITE, - .maps[RCAMO] = REG_CAMREAD, - .maps[CAMDBG] = REG_CAMDBG, - .maps[SECR] = REG_SECCFG, - .maps[SEC_CAM_NONE] = CAM_NONE, - .maps[SEC_CAM_WEP40] = CAM_WEP40, - .maps[SEC_CAM_TKIP] = CAM_TKIP, - .maps[SEC_CAM_AES] = CAM_AES, - .maps[SEC_CAM_WEP104] = CAM_WEP104, - - .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, - .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, - .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, - .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, - .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, - .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, -/* .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, */ /*need check*/ - .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, - .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, - .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, - .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, - .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, - .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, - .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, -/* .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,*/ -/* .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,*/ - - .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, - .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, - .maps[RTL_IMR_BCNINT] = IMR_BCNDMAINT0, - .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, - .maps[RTL_IMR_RDU] = IMR_RDU, - .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, - .maps[RTL_IMR_BDOK] = IMR_BCNDOK0, - .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, - .maps[RTL_IMR_TBDER] = IMR_TBDER, - .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, - .maps[RTL_IMR_TBDOK] = IMR_TBDOK, - .maps[RTL_IMR_BKDOK] = IMR_BKDOK, - .maps[RTL_IMR_BEDOK] = IMR_BEDOK, - .maps[RTL_IMR_VIDOK] = IMR_VIDOK, - .maps[RTL_IMR_VODOK] = IMR_VODOK, - .maps[RTL_IMR_ROK] = IMR_ROK, - .maps[RTL_IMR_HSISR_IND] = IMR_HSISR_IND_ON_INT, - .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER), - - .maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, -}; - -static struct pci_device_id rtl8723be_pci_ids[] = { - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xB723, rtl8723be_hal_cfg)}, - {}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8723be_pci_ids); - -MODULE_AUTHOR("PageHe "); -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_LICENSE("GPL"); -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(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); -module_param_named(msi, rtl8723be_mod_params.msi_support, bool, 0444); -module_param_named(disable_watchdog, rtl8723be_mod_params.disable_watchdog, - bool, 0444); -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(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(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); - -static struct pci_driver rtl8723be_driver = { - .name = KBUILD_MODNAME, - .id_table = rtl8723be_pci_ids, - .probe = rtl_pci_probe, - .remove = rtl_pci_disconnect, - .driver.pm = &rtlwifi_pm_ops, -}; - -module_pci_driver(rtl8723be_driver); diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/sw.h b/drivers/net/wireless/rtlwifi/rtl8723be/sw.h deleted file mode 100644 index a7b25e769950..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/sw.h +++ /dev/null @@ -1,35 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723BE_SW_H__ -#define __RTL8723BE_SW_H__ - -int rtl8723be_init_sw_vars(struct ieee80211_hw *hw); -void rtl8723be_deinit_sw_vars(struct ieee80211_hw *hw); -void rtl8723be_init_var_map(struct ieee80211_hw *hw); -bool rtl8723be_get_btc_status(void); - - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/table.c b/drivers/net/wireless/rtlwifi/rtl8723be/table.c deleted file mode 100644 index a180761e8810..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/table.c +++ /dev/null @@ -1,577 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ - -#include "table.h" -u32 RTL8723BEPHY_REG_1TARRAY[] = { - 0x800, 0x80040000, - 0x804, 0x00000003, - 0x808, 0x0000FC00, - 0x80C, 0x0000000A, - 0x810, 0x10001331, - 0x814, 0x020C3D10, - 0x818, 0x02200385, - 0x81C, 0x00000000, - 0x820, 0x01000100, - 0x824, 0x00390204, - 0x828, 0x00000000, - 0x82C, 0x00000000, - 0x830, 0x00000000, - 0x834, 0x00000000, - 0x838, 0x00000000, - 0x83C, 0x00000000, - 0x840, 0x00010000, - 0x844, 0x00000000, - 0x848, 0x00000000, - 0x84C, 0x00000000, - 0x850, 0x00000000, - 0x854, 0x00000000, - 0x858, 0x569A11A9, - 0x85C, 0x01000014, - 0x860, 0x66F60110, - 0x864, 0x061F0649, - 0x868, 0x00000000, - 0x86C, 0x27272700, - 0x870, 0x07000760, - 0x874, 0x25004000, - 0x878, 0x00000808, - 0x87C, 0x00000000, - 0x880, 0xB0000C1C, - 0x884, 0x00000001, - 0x888, 0x00000000, - 0x88C, 0xCCC000C0, - 0x890, 0x00000800, - 0x894, 0xFFFFFFFE, - 0x898, 0x40302010, - 0x89C, 0x00706050, - 0x900, 0x00000000, - 0x904, 0x00000023, - 0x908, 0x00000000, - 0x90C, 0x81121111, - 0x910, 0x00000002, - 0x914, 0x00000201, - 0x948, 0x00000280, - 0xA00, 0x00D047C8, - 0xA04, 0x80FF000C, - 0xA08, 0x8C838300, - 0xA0C, 0x2E7F120F, - 0xA10, 0x9500BB78, - 0xA14, 0x1114D028, - 0xA18, 0x00881117, - 0xA1C, 0x89140F00, - 0xA20, 0x1A1B0000, - 0xA24, 0x090E1317, - 0xA28, 0x00000204, - 0xA2C, 0x00D30000, - 0xA70, 0x101FBF00, - 0xA74, 0x00000007, - 0xA78, 0x00000900, - 0xA7C, 0x225B0606, - 0xA80, 0x21806490, - 0xB2C, 0x00000000, - 0xC00, 0x48071D40, - 0xC04, 0x03A05611, - 0xC08, 0x000000E4, - 0xC0C, 0x6C6C6C6C, - 0xC10, 0x08800000, - 0xC14, 0x40000100, - 0xC18, 0x08800000, - 0xC1C, 0x40000100, - 0xC20, 0x00000000, - 0xC24, 0x00000000, - 0xC28, 0x00000000, - 0xC2C, 0x00000000, - 0xC30, 0x69E9AC44, - 0xC34, 0x469652AF, - 0xC38, 0x49795994, - 0xC3C, 0x0A97971C, - 0xC40, 0x1F7C403F, - 0xC44, 0x000100B7, - 0xC48, 0xEC020107, - 0xC4C, 0x007F037F, - 0xC50, 0x69553420, - 0xC54, 0x43BC0094, - 0xC58, 0x00023169, - 0xC5C, 0x00250492, - 0xC60, 0x00000000, - 0xC64, 0x7112848B, - 0xC68, 0x47C00BFF, - 0xC6C, 0x00000036, - 0xC70, 0x2C7F000D, - 0xC74, 0x020610DB, - 0xC78, 0x0000001F, - 0xC7C, 0x00B91612, - 0xC80, 0x390000E4, - 0xC84, 0x20F60000, - 0xC88, 0x40000100, - 0xC8C, 0x20200000, - 0xC90, 0x00020E1A, - 0xC94, 0x00000000, - 0xC98, 0x00020E1A, - 0xC9C, 0x00007F7F, - 0xCA0, 0x00000000, - 0xCA4, 0x000300A0, - 0xCA8, 0x00000000, - 0xCAC, 0x00000000, - 0xCB0, 0x00000000, - 0xCB4, 0x00000000, - 0xCB8, 0x00000000, - 0xCBC, 0x28000000, - 0xCC0, 0x00000000, - 0xCC4, 0x00000000, - 0xCC8, 0x00000000, - 0xCCC, 0x00000000, - 0xCD0, 0x00000000, - 0xCD4, 0x00000000, - 0xCD8, 0x64B22427, - 0xCDC, 0x00766932, - 0xCE0, 0x00222222, - 0xCE4, 0x00000000, - 0xCE8, 0x37644302, - 0xCEC, 0x2F97D40C, - 0xD00, 0x00000740, - 0xD04, 0x40020401, - 0xD08, 0x0000907F, - 0xD0C, 0x20010201, - 0xD10, 0xA0633333, - 0xD14, 0x3333BC53, - 0xD18, 0x7A8F5B6F, - 0xD2C, 0xCC979975, - 0xD30, 0x00000000, - 0xD34, 0x80608000, - 0xD38, 0x00000000, - 0xD3C, 0x00127353, - 0xD40, 0x00000000, - 0xD44, 0x00000000, - 0xD48, 0x00000000, - 0xD4C, 0x00000000, - 0xD50, 0x6437140A, - 0xD54, 0x00000000, - 0xD58, 0x00000282, - 0xD5C, 0x30032064, - 0xD60, 0x4653DE68, - 0xD64, 0x04518A3C, - 0xD68, 0x00002101, - 0xD6C, 0x2A201C16, - 0xD70, 0x1812362E, - 0xD74, 0x322C2220, - 0xD78, 0x000E3C24, - 0xE00, 0x2D2D2D2D, - 0xE04, 0x2D2D2D2D, - 0xE08, 0x0390272D, - 0xE10, 0x2D2D2D2D, - 0xE14, 0x2D2D2D2D, - 0xE18, 0x2D2D2D2D, - 0xE1C, 0x2D2D2D2D, - 0xE28, 0x00000000, - 0xE30, 0x1000DC1F, - 0xE34, 0x10008C1F, - 0xE38, 0x02140102, - 0xE3C, 0x681604C2, - 0xE40, 0x01007C00, - 0xE44, 0x01004800, - 0xE48, 0xFB000000, - 0xE4C, 0x000028D1, - 0xE50, 0x1000DC1F, - 0xE54, 0x10008C1F, - 0xE58, 0x02140102, - 0xE5C, 0x28160D05, - 0xE60, 0x00000008, - 0xE68, 0x001B2556, - 0xE6C, 0x00C00096, - 0xE70, 0x00C00096, - 0xE74, 0x01000056, - 0xE78, 0x01000014, - 0xE7C, 0x01000056, - 0xE80, 0x01000014, - 0xE84, 0x00C00096, - 0xE88, 0x01000056, - 0xE8C, 0x00C00096, - 0xED0, 0x00C00096, - 0xED4, 0x00C00096, - 0xED8, 0x00C00096, - 0xEDC, 0x000000D6, - 0xEE0, 0x000000D6, - 0xEEC, 0x01C00016, - 0xF14, 0x00000003, - 0xF4C, 0x00000000, - 0xF00, 0x00000300, - 0x820, 0x01000100, - 0x800, 0x83040000, - -}; - -u32 RTL8723BEPHY_REG_ARRAY_PG[] = { - 0, 0, 0, 0x00000e08, 0x0000ff00, 0x00004000, - 0, 0, 0, 0x0000086c, 0xffffff00, 0x34363800, - 0, 0, 0, 0x00000e00, 0xffffffff, 0x42444646, - 0, 0, 0, 0x00000e04, 0xffffffff, 0x30343840, - 0, 0, 0, 0x00000e10, 0xffffffff, 0x38404244, - 0, 0, 0, 0x00000e14, 0xffffffff, 0x26303436 -}; - -u32 RTL8723BE_RADIOA_1TARRAY[] = { - 0x000, 0x00010000, - 0x0B0, 0x000DFFE0, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x0B1, 0x00000018, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x0B2, 0x00084C00, - 0x0B5, 0x0000D2CC, - 0x0B6, 0x000925AA, - 0x0B7, 0x00000010, - 0x0B8, 0x0000907F, - 0x05C, 0x00000002, - 0x07C, 0x00000002, - 0x07E, 0x00000005, - 0x08B, 0x0006FC00, - 0x0B0, 0x000FF9F0, - 0x01C, 0x000739D2, - 0x01E, 0x00000000, - 0x0DF, 0x00000780, - 0x050, 0x00067435, - 0x051, 0x0006B04E, - 0x052, 0x000007D2, - 0x053, 0x00000000, - 0x054, 0x00050400, - 0x055, 0x0004026E, - 0x0DD, 0x0000004C, - 0x070, 0x00067435, - 0x071, 0x0006B04E, - 0x072, 0x000007D2, - 0x073, 0x00000000, - 0x074, 0x00050400, - 0x075, 0x0004026E, - 0x0EF, 0x00000100, - 0x034, 0x0000ADD7, - 0x035, 0x00005C00, - 0x034, 0x00009DD4, - 0x035, 0x00005000, - 0x034, 0x00008DD1, - 0x035, 0x00004400, - 0x034, 0x00007DCE, - 0x035, 0x00003800, - 0x034, 0x00006CD1, - 0x035, 0x00004400, - 0x034, 0x00005CCE, - 0x035, 0x00003800, - 0x034, 0x000048CE, - 0x035, 0x00004400, - 0x034, 0x000034CE, - 0x035, 0x00003800, - 0x034, 0x00002451, - 0x035, 0x00004400, - 0x034, 0x0000144E, - 0x035, 0x00003800, - 0x034, 0x00000051, - 0x035, 0x00004400, - 0x0EF, 0x00000000, - 0x0EF, 0x00000100, - 0x0ED, 0x00000010, - 0x044, 0x0000ADD7, - 0x044, 0x00009DD4, - 0x044, 0x00008DD1, - 0x044, 0x00007DCE, - 0x044, 0x00006CC1, - 0x044, 0x00005CCE, - 0x044, 0x000044D1, - 0x044, 0x000034CE, - 0x044, 0x00002451, - 0x044, 0x0000144E, - 0x044, 0x00000051, - 0x0EF, 0x00000000, - 0x0ED, 0x00000000, - 0x0EF, 0x00002000, - 0x03B, 0x000380EF, - 0x03B, 0x000302FE, - 0x03B, 0x00028CE6, - 0x03B, 0x000200BC, - 0x03B, 0x000188A5, - 0x03B, 0x00010FBC, - 0x03B, 0x00008F71, - 0x03B, 0x00000900, - 0x0EF, 0x00000000, - 0x0ED, 0x00000001, - 0x040, 0x000380EF, - 0x040, 0x000302FE, - 0x040, 0x00028CE6, - 0x040, 0x000200BC, - 0x040, 0x000188A5, - 0x040, 0x00010FBC, - 0x040, 0x00008F71, - 0x040, 0x00000900, - 0x0ED, 0x00000000, - 0x082, 0x00080000, - 0x083, 0x00008000, - 0x084, 0x00048D80, - 0x085, 0x00068000, - 0x0A2, 0x00080000, - 0x0A3, 0x00008000, - 0x0A4, 0x00048D80, - 0x0A5, 0x00068000, - 0x000, 0x00033D80, - -}; - -u32 RTL8723BEMAC_1T_ARRAY[] = { - 0x02F, 0x00000030, - 0x035, 0x00000000, - 0x067, 0x00000020, - 0x428, 0x0000000A, - 0x429, 0x00000010, - 0x430, 0x00000000, - 0x431, 0x00000000, - 0x432, 0x00000000, - 0x433, 0x00000001, - 0x434, 0x00000004, - 0x435, 0x00000005, - 0x436, 0x00000007, - 0x437, 0x00000008, - 0x43C, 0x00000004, - 0x43D, 0x00000005, - 0x43E, 0x00000007, - 0x43F, 0x00000008, - 0x440, 0x0000005D, - 0x441, 0x00000001, - 0x442, 0x00000000, - 0x444, 0x00000010, - 0x445, 0x00000000, - 0x446, 0x00000000, - 0x447, 0x00000000, - 0x448, 0x00000000, - 0x449, 0x000000F0, - 0x44A, 0x0000000F, - 0x44B, 0x0000003E, - 0x44C, 0x00000010, - 0x44D, 0x00000000, - 0x44E, 0x00000000, - 0x44F, 0x00000000, - 0x450, 0x00000000, - 0x451, 0x000000F0, - 0x452, 0x0000000F, - 0x453, 0x00000000, - 0x456, 0x0000005E, - 0x460, 0x00000066, - 0x461, 0x00000066, - 0x4C8, 0x000000FF, - 0x4C9, 0x00000008, - 0x4CC, 0x000000FF, - 0x4CD, 0x000000FF, - 0x4CE, 0x00000001, - 0x500, 0x00000026, - 0x501, 0x000000A2, - 0x502, 0x0000002F, - 0x503, 0x00000000, - 0x504, 0x00000028, - 0x505, 0x000000A3, - 0x506, 0x0000005E, - 0x507, 0x00000000, - 0x508, 0x0000002B, - 0x509, 0x000000A4, - 0x50A, 0x0000005E, - 0x50B, 0x00000000, - 0x50C, 0x0000004F, - 0x50D, 0x000000A4, - 0x50E, 0x00000000, - 0x50F, 0x00000000, - 0x512, 0x0000001C, - 0x514, 0x0000000A, - 0x516, 0x0000000A, - 0x525, 0x0000004F, - 0x550, 0x00000010, - 0x551, 0x00000010, - 0x559, 0x00000002, - 0x55C, 0x00000050, - 0x55D, 0x000000FF, - 0x605, 0x00000030, - 0x608, 0x0000000E, - 0x609, 0x0000002A, - 0x620, 0x000000FF, - 0x621, 0x000000FF, - 0x622, 0x000000FF, - 0x623, 0x000000FF, - 0x624, 0x000000FF, - 0x625, 0x000000FF, - 0x626, 0x000000FF, - 0x627, 0x000000FF, - 0x638, 0x00000050, - 0x63C, 0x0000000A, - 0x63D, 0x0000000A, - 0x63E, 0x0000000E, - 0x63F, 0x0000000E, - 0x640, 0x00000040, - 0x642, 0x00000040, - 0x643, 0x00000000, - 0x652, 0x000000C8, - 0x66E, 0x00000005, - 0x700, 0x00000021, - 0x701, 0x00000043, - 0x702, 0x00000065, - 0x703, 0x00000087, - 0x708, 0x00000021, - 0x709, 0x00000043, - 0x70A, 0x00000065, - 0x70B, 0x00000087, - -}; - -u32 RTL8723BEAGCTAB_1TARRAY[] = { - 0xC78, 0xFD000001, - 0xC78, 0xFC010001, - 0xC78, 0xFB020001, - 0xC78, 0xFA030001, - 0xC78, 0xF9040001, - 0xC78, 0xF8050001, - 0xC78, 0xF7060001, - 0xC78, 0xF6070001, - 0xC78, 0xF5080001, - 0xC78, 0xF4090001, - 0xC78, 0xF30A0001, - 0xC78, 0xF20B0001, - 0xC78, 0xF10C0001, - 0xC78, 0xF00D0001, - 0xC78, 0xEF0E0001, - 0xC78, 0xEE0F0001, - 0xC78, 0xED100001, - 0xC78, 0xEC110001, - 0xC78, 0xEB120001, - 0xC78, 0xEA130001, - 0xC78, 0xE9140001, - 0xC78, 0xE8150001, - 0xC78, 0xE7160001, - 0xC78, 0xAA170001, - 0xC78, 0xA9180001, - 0xC78, 0xA8190001, - 0xC78, 0xA71A0001, - 0xC78, 0xA61B0001, - 0xC78, 0xA51C0001, - 0xC78, 0xA41D0001, - 0xC78, 0xA31E0001, - 0xC78, 0x671F0001, - 0xC78, 0x66200001, - 0xC78, 0x65210001, - 0xC78, 0x64220001, - 0xC78, 0x63230001, - 0xC78, 0x62240001, - 0xC78, 0x61250001, - 0xC78, 0x47260001, - 0xC78, 0x46270001, - 0xC78, 0x45280001, - 0xC78, 0x44290001, - 0xC78, 0x432A0001, - 0xC78, 0x422B0001, - 0xC78, 0x292C0001, - 0xC78, 0x282D0001, - 0xC78, 0x272E0001, - 0xC78, 0x262F0001, - 0xC78, 0x25300001, - 0xC78, 0x24310001, - 0xC78, 0x09320001, - 0xC78, 0x08330001, - 0xC78, 0x07340001, - 0xC78, 0x06350001, - 0xC78, 0x05360001, - 0xC78, 0x04370001, - 0xC78, 0x03380001, - 0xC78, 0x02390001, - 0xC78, 0x013A0001, - 0xC78, 0x003B0001, - 0xC78, 0x003C0001, - 0xC78, 0x003D0001, - 0xC78, 0x003E0001, - 0xC78, 0x003F0001, - 0xC78, 0xFC400001, - 0xC78, 0xFB410001, - 0xC78, 0xFA420001, - 0xC78, 0xF9430001, - 0xC78, 0xF8440001, - 0xC78, 0xF7450001, - 0xC78, 0xF6460001, - 0xC78, 0xF5470001, - 0xC78, 0xF4480001, - 0xC78, 0xF3490001, - 0xC78, 0xF24A0001, - 0xC78, 0xF14B0001, - 0xC78, 0xF04C0001, - 0xC78, 0xEF4D0001, - 0xC78, 0xEE4E0001, - 0xC78, 0xED4F0001, - 0xC78, 0xEC500001, - 0xC78, 0xEB510001, - 0xC78, 0xEA520001, - 0xC78, 0xE9530001, - 0xC78, 0xE8540001, - 0xC78, 0xE7550001, - 0xC78, 0xE6560001, - 0xC78, 0xE5570001, - 0xC78, 0xAA580001, - 0xC78, 0xA9590001, - 0xC78, 0xA85A0001, - 0xC78, 0xA75B0001, - 0xC78, 0xA65C0001, - 0xC78, 0xA55D0001, - 0xC78, 0xA45E0001, - 0xC78, 0x675F0001, - 0xC78, 0x66600001, - 0xC78, 0x65610001, - 0xC78, 0x64620001, - 0xC78, 0x63630001, - 0xC78, 0x62640001, - 0xC78, 0x61650001, - 0xC78, 0x47660001, - 0xC78, 0x46670001, - 0xC78, 0x45680001, - 0xC78, 0x44690001, - 0xC78, 0x436A0001, - 0xC78, 0x426B0001, - 0xC78, 0x296C0001, - 0xC78, 0x286D0001, - 0xC78, 0x276E0001, - 0xC78, 0x266F0001, - 0xC78, 0x25700001, - 0xC78, 0x24710001, - 0xC78, 0x09720001, - 0xC78, 0x08730001, - 0xC78, 0x07740001, - 0xC78, 0x06750001, - 0xC78, 0x05760001, - 0xC78, 0x04770001, - 0xC78, 0x03780001, - 0xC78, 0x02790001, - 0xC78, 0x017A0001, - 0xC78, 0x007B0001, - 0xC78, 0x007C0001, - 0xC78, 0x007D0001, - 0xC78, 0x007E0001, - 0xC78, 0x007F0001, - 0xC50, 0x69553422, - 0xC50, 0x69553420, - -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/table.h b/drivers/net/wireless/rtlwifi/rtl8723be/table.h deleted file mode 100644 index dc17001632f7..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/table.h +++ /dev/null @@ -1,43 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723BE_TABLE__H_ -#define __RTL8723BE_TABLE__H_ - -#include -#define RTL8723BEPHY_REG_1TARRAYLEN 388 -extern u32 RTL8723BEPHY_REG_1TARRAY[]; -#define RTL8723BEPHY_REG_ARRAY_PGLEN 36 -extern u32 RTL8723BEPHY_REG_ARRAY_PG[]; -#define RTL8723BE_RADIOA_1TARRAYLEN 206 -extern u32 RTL8723BE_RADIOA_1TARRAY[]; -#define RTL8723BEMAC_1T_ARRAYLEN 196 -extern u32 RTL8723BEMAC_1T_ARRAY[]; -#define RTL8723BEAGCTAB_1TARRAYLEN 260 -extern u32 RTL8723BEAGCTAB_1TARRAY[]; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/rtlwifi/rtl8723be/trx.c deleted file mode 100644 index 338ec9a9d09b..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/trx.c +++ /dev/null @@ -1,783 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../stats.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "trx.h" -#include "led.h" -#include "dm.h" -#include "fw.h" - -static u8 _rtl8723be_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) -{ - __le16 fc = rtl_get_fc(skb); - - if (unlikely(ieee80211_is_beacon(fc))) - return QSLT_BEACON; - if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) - return QSLT_MGNT; - - return skb->priority; -} - -static void _rtl8723be_query_rxphystatus(struct ieee80211_hw *hw, - struct rtl_stats *pstatus, u8 *pdesc, - struct rx_fwinfo_8723be *p_drvinfo, - bool bpacket_match_bssid, - bool bpacket_toself, - bool packet_beacon) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct phy_status_rpt *p_phystrpt = (struct phy_status_rpt *)p_drvinfo; - char rx_pwr_all = 0, rx_pwr[4]; - u8 rf_rx_num = 0, evm, pwdb_all, pwdb_all_bt = 0; - u8 i, max_spatial_stream; - u32 rssi, total_rssi = 0; - bool is_cck = pstatus->is_cck; - u8 lan_idx, vga_idx; - - /* Record it for next packet processing */ - pstatus->packet_matchbssid = bpacket_match_bssid; - pstatus->packet_toself = bpacket_toself; - pstatus->packet_beacon = packet_beacon; - pstatus->rx_mimo_signalquality[0] = -1; - pstatus->rx_mimo_signalquality[1] = -1; - - if (is_cck) { - u8 cck_highpwr; - u8 cck_agc_rpt; - - cck_agc_rpt = p_phystrpt->cck_agc_rpt_ofdm_cfosho_a; - - /* (1)Hardware does not provide RSSI for CCK */ - /* (2)PWDB, Average PWDB cacluated by - * hardware (for rate adaptive) - */ - cck_highpwr = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, - BIT(9)); - - lan_idx = ((cck_agc_rpt & 0xE0) >> 5); - vga_idx = (cck_agc_rpt & 0x1f); - - switch (lan_idx) { - /* 46 53 73 95 201301231630 */ - /* 46 53 77 99 201301241630 */ - case 6: - rx_pwr_all = -34 - (2 * vga_idx); - break; - case 4: - rx_pwr_all = -14 - (2 * vga_idx); - break; - case 1: - rx_pwr_all = 6 - (2 * vga_idx); - break; - case 0: - rx_pwr_all = 16 - (2 * vga_idx); - break; - default: - break; - } - - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - if (pwdb_all > 100) - pwdb_all = 100; - - pstatus->rx_pwdb_all = pwdb_all; - pstatus->bt_rx_rssi_percentage = pwdb_all; - pstatus->recvsignalpower = rx_pwr_all; - - /* (3) Get Signal Quality (EVM) */ - if (bpacket_match_bssid) { - u8 sq, sq_rpt; - if (pstatus->rx_pwdb_all > 40) { - sq = 100; - } else { - sq_rpt = p_phystrpt->cck_sig_qual_ofdm_pwdb_all; - if (sq_rpt > 64) - sq = 0; - else if (sq_rpt < 20) - sq = 100; - else - sq = ((64 - sq_rpt) * 100) / 44; - } - pstatus->signalquality = sq; - pstatus->rx_mimo_signalquality[0] = sq; - pstatus->rx_mimo_signalquality[1] = -1; - } - } else { - /* (1)Get RSSI for HT rate */ - for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { - /* we will judge RF RX path now. */ - if (rtlpriv->dm.rfpath_rxenable[i]) - rf_rx_num++; - - rx_pwr[i] = ((p_phystrpt->path_agc[i].gain & 0x3f) * 2) - - 110; - - pstatus->rx_pwr[i] = rx_pwr[i]; - /* Translate DBM to percentage. */ - rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); - total_rssi += rssi; - - pstatus->rx_mimo_signalstrength[i] = (u8)rssi; - } - - /* (2)PWDB, Average PWDB cacluated by - * hardware (for rate adaptive) - */ - rx_pwr_all = ((p_phystrpt->cck_sig_qual_ofdm_pwdb_all >> 1) & - 0x7f) - 110; - - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - pwdb_all_bt = pwdb_all; - pstatus->rx_pwdb_all = pwdb_all; - pstatus->bt_rx_rssi_percentage = pwdb_all_bt; - pstatus->rxpower = rx_pwr_all; - pstatus->recvsignalpower = rx_pwr_all; - - /* (3)EVM of HT rate */ - if (pstatus->rate >= DESC92C_RATEMCS8 && - pstatus->rate <= DESC92C_RATEMCS15) - max_spatial_stream = 2; - else - max_spatial_stream = 1; - - for (i = 0; i < max_spatial_stream; i++) { - evm = rtl_evm_db_to_percentage( - p_phystrpt->stream_rxevm[i]); - - if (bpacket_match_bssid) { - /* Fill value in RFD, Get the first - * spatial stream only - */ - if (i == 0) - pstatus->signalquality = - (u8)(evm & 0xff); - pstatus->rx_mimo_signalquality[i] = - (u8)(evm & 0xff); - } - } - - if (bpacket_match_bssid) { - for (i = RF90_PATH_A; i <= RF90_PATH_B; i++) - rtl_priv(hw)->dm.cfo_tail[i] = - (int)p_phystrpt->path_cfotail[i]; - - if (rtl_priv(hw)->dm.packet_count == 0xffffffff) - rtl_priv(hw)->dm.packet_count = 0; - else - rtl_priv(hw)->dm.packet_count++; - } - } - - /* UI BSS List signal strength(in percentage), - * make it good looking, from 0~100. - */ - if (is_cck) - pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, - pwdb_all)); - else if (rf_rx_num != 0) - pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, - total_rssi /= rf_rx_num)); -} - -static void _rtl8723be_translate_rx_signal_stuff(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct rtl_stats *pstatus, - u8 *pdesc, - struct rx_fwinfo_8723be *p_drvinfo) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct ieee80211_hdr *hdr; - u8 *tmp_buf; - u8 *praddr; - u8 *psaddr; - u16 fc, type; - bool packet_matchbssid, packet_toself, packet_beacon; - - tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; - - hdr = (struct ieee80211_hdr *)tmp_buf; - fc = le16_to_cpu(hdr->frame_control); - type = WLAN_FC_GET_TYPE(hdr->frame_control); - praddr = hdr->addr1; - psaddr = ieee80211_get_SA(hdr); - memcpy(pstatus->psaddr, psaddr, ETH_ALEN); - - packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && - (ether_addr_equal(mac->bssid, (fc & IEEE80211_FCTL_TODS) ? - hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ? - hdr->addr2 : hdr->addr3)) && - (!pstatus->hwerror) && - (!pstatus->crc) && (!pstatus->icv)); - - packet_toself = packet_matchbssid && - (ether_addr_equal(praddr, rtlefuse->dev_addr)); - - /* YP: packet_beacon is not initialized, - * this assignment is neccesary, - * otherwise it counld be true in this case - * the situation is much worse in Kernel 3.10 - */ - if (ieee80211_is_beacon(hdr->frame_control)) - packet_beacon = true; - else - packet_beacon = false; - - if (packet_beacon && packet_matchbssid) - rtl_priv(hw)->dm.dbginfo.num_qry_beacon_pkt++; - - _rtl8723be_query_rxphystatus(hw, pstatus, pdesc, p_drvinfo, - packet_matchbssid, - packet_toself, - packet_beacon); - - rtl_process_phyinfo(hw, tmp_buf, pstatus); -} - -static void _rtl8723be_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, - u8 *virtualaddress) -{ - u32 dwtmp = 0; - memset(virtualaddress, 0, 8); - - SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); - if (ptcb_desc->empkt_num == 1) { - dwtmp = ptcb_desc->empkt_len[0]; - } else { - dwtmp = ptcb_desc->empkt_len[0]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; - dwtmp += ptcb_desc->empkt_len[1]; - } - SET_EARLYMODE_LEN0(virtualaddress, dwtmp); - - if (ptcb_desc->empkt_num <= 3) { - dwtmp = ptcb_desc->empkt_len[2]; - } else { - dwtmp = ptcb_desc->empkt_len[2]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; - dwtmp += ptcb_desc->empkt_len[3]; - } - SET_EARLYMODE_LEN1(virtualaddress, dwtmp); - if (ptcb_desc->empkt_num <= 5) { - dwtmp = ptcb_desc->empkt_len[4]; - } else { - dwtmp = ptcb_desc->empkt_len[4]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; - dwtmp += ptcb_desc->empkt_len[5]; - } - SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF); - SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4); - if (ptcb_desc->empkt_num <= 7) { - dwtmp = ptcb_desc->empkt_len[6]; - } else { - dwtmp = ptcb_desc->empkt_len[6]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; - dwtmp += ptcb_desc->empkt_len[7]; - } - SET_EARLYMODE_LEN3(virtualaddress, dwtmp); - if (ptcb_desc->empkt_num <= 9) { - dwtmp = ptcb_desc->empkt_len[8]; - } else { - dwtmp = ptcb_desc->empkt_len[8]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0) + 4; - dwtmp += ptcb_desc->empkt_len[9]; - } - SET_EARLYMODE_LEN4(virtualaddress, dwtmp); -} - -bool rtl8723be_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *status, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rx_fwinfo_8723be *p_drvinfo; - struct ieee80211_hdr *hdr; - - u32 phystatus = GET_RX_DESC_PHYST(pdesc); - - status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); - status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * - RX_DRV_INFO_SIZE_UNIT; - status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03); - status->icv = (u16) GET_RX_DESC_ICV(pdesc); - status->crc = (u16) GET_RX_DESC_CRC32(pdesc); - status->hwerror = (status->crc | status->icv); - status->decrypted = !GET_RX_DESC_SWDEC(pdesc); - status->rate = (u8)GET_RX_DESC_RXMCS(pdesc); - status->shortpreamble = (u16)GET_RX_DESC_SPLCP(pdesc); - status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); - status->isfirst_ampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); - status->timestamp_low = GET_RX_DESC_TSFL(pdesc); - status->rx_is40Mhzpacket = (bool)GET_RX_DESC_BW(pdesc); - status->bandwidth = (u8)GET_RX_DESC_BW(pdesc); - status->macid = GET_RX_DESC_MACID(pdesc); - status->is_ht = (bool)GET_RX_DESC_RXHT(pdesc); - - status->is_cck = RX_HAL_IS_CCK_RATE(status->rate); - - if (GET_RX_STATUS_DESC_RPT_SEL(pdesc)) - status->packet_report_type = C2H_PACKET; - else - status->packet_report_type = NORMAL_RX; - - - if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(2); - else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(1); - else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) - status->wake_match = BIT(0); - else - status->wake_match = 0; - if (status->wake_match) - RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, - "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n", - status->wake_match); - rx_status->freq = hw->conf.chandef.chan->center_freq; - rx_status->band = hw->conf.chandef.chan->band; - - hdr = (struct ieee80211_hdr *)(skb->data + status->rx_drvinfo_size + - status->rx_bufshift); - - if (status->crc) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - - if (status->rx_is40Mhzpacket) - rx_status->flag |= RX_FLAG_40MHZ; - - if (status->is_ht) - rx_status->flag |= RX_FLAG_HT; - - rx_status->flag |= RX_FLAG_MACTIME_START; - - /* hw will set status->decrypted true, if it finds the - * frame is open data frame or mgmt frame. - * So hw will not decryption robust managment frame - * for IEEE80211w but still set status->decrypted - * true, so here we should set it back to undecrypted - * for IEEE80211w frame, and mac80211 sw will help - * to decrypt it - */ - if (status->decrypted) { - if ((!_ieee80211_is_robust_mgmt_frame(hdr)) && - (ieee80211_has_protected(hdr->frame_control))) - rx_status->flag |= RX_FLAG_DECRYPTED; - else - rx_status->flag &= ~RX_FLAG_DECRYPTED; - } - - /* rate_idx: index of data rate into band's - * supported rates or MCS index if HT rates - * are use (RX_FLAG_HT) - */ - rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht, - false, status->rate); - - rx_status->mactime = status->timestamp_low; - if (phystatus) { - p_drvinfo = (struct rx_fwinfo_8723be *)(skb->data + - status->rx_bufshift); - - _rtl8723be_translate_rx_signal_stuff(hw, skb, status, - pdesc, p_drvinfo); - } - rx_status->signal = status->recvsignalpower + 10; - if (status->packet_report_type == TX_REPORT2) { - status->macid_valid_entry[0] = - GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); - status->macid_valid_entry[1] = - GET_RX_RPT2_DESC_MACID_VALID_2(pdesc); - } - return true; -} - -void rtl8723be_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *txbd, struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 *pdesc = (u8 *)pdesc_tx; - u16 seq_number; - __le16 fc = hdr->frame_control; - unsigned int buf_len = 0; - unsigned int skb_len = skb->len; - u8 fw_qsel = _rtl8723be_map_hwqueue_to_fwqueue(skb, hw_queue); - bool firstseg = ((hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); - bool lastseg = ((hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); - dma_addr_t mapping; - u8 bw_40 = 0; - u8 short_gi = 0; - - if (mac->opmode == NL80211_IFTYPE_STATION) { - bw_40 = mac->bw_40; - } else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - if (sta) - bw_40 = sta->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40; - } - seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); - /* reserve 8 byte for AMPDU early mode */ - if (rtlhal->earlymode_enable) { - skb_push(skb, EM_HDR_LEN); - memset(skb->data, 0, EM_HDR_LEN); - } - buf_len = skb->len; - mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "DMA mapping error"); - return; - } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_8723be)); - if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { - firstseg = true; - lastseg = true; - } - if (firstseg) { - if (rtlhal->earlymode_enable) { - SET_TX_DESC_PKT_OFFSET(pdesc, 1); - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + - EM_HDR_LEN); - if (ptcb_desc->empkt_num) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "Insert 8 byte.pTcb->EMPktNum:%d\n", - ptcb_desc->empkt_num); - _rtl8723be_insert_emcontent(ptcb_desc, - (u8 *)(skb->data)); - } - } else { - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - } - - /* ptcb_desc->use_driver_rate = true; */ - SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); - if (ptcb_desc->hw_rate > DESC92C_RATEMCS0) - short_gi = (ptcb_desc->use_shortgi) ? 1 : 0; - else - short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0; - - SET_TX_DESC_DATA_SHORTGI(pdesc, short_gi); - - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - SET_TX_DESC_AGG_ENABLE(pdesc, 1); - SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); - } - SET_TX_DESC_SEQ(pdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && - !ptcb_desc->cts_enable) ? - 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(pdesc, 0); - SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? - 1 : 0)); - - SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); - - SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(pdesc, - ((ptcb_desc->rts_rate <= DESC92C_RATE54M) ? - (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : - (ptcb_desc->rts_use_shortgi ? 1 : 0))); - - if (ptcb_desc->tx_enable_sw_calc_duration) - SET_TX_DESC_NAV_USE_HDR(pdesc, 1); - - if (bw_40) { - if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { - SET_TX_DESC_DATA_BW(pdesc, 1); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, mac->cur_40_prime_sc); - } - } else { - SET_TX_DESC_DATA_BW(pdesc, 0); - SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); - } - - SET_TX_DESC_LINIP(pdesc, 0); - SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb_len); - if (sta) { - u8 ampdu_density = sta->ht_cap.ampdu_density; - SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); - } - if (info->control.hw_key) { - struct ieee80211_key_conf *keyconf = - info->control.hw_key; - switch (keyconf->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - case WLAN_CIPHER_SUITE_TKIP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x1); - break; - case WLAN_CIPHER_SUITE_CCMP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x3); - break; - default: - SET_TX_DESC_SEC_TYPE(pdesc, 0x0); - break; - } - } - - SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); - SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); - SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); - SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ? - 1 : 0); - SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); - - /* Set TxRate and RTSRate in TxDesc */ - /* This prevent Tx initial rate of new-coming packets */ - /* from being overwritten by retried packet rate.*/ - if (ieee80211_is_data_qos(fc)) { - if (mac->rdg_en) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "Enable RDG function.\n"); - SET_TX_DESC_RDG_ENABLE(pdesc, 1); - SET_TX_DESC_HTC(pdesc, 1); - } - } - } - - SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); - SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) buf_len); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - /* if (rtlpriv->dm.useramask) { */ - if (1) { - SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); - } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); - } - if (!ieee80211_is_data_qos(fc)) { - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - SET_TX_DESC_HWSEQ_SEL(pdesc, 0); - } - SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); - if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || - is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { - SET_TX_DESC_BMC(pdesc, 1); - } - - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); -} - -void rtl8723be_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 fw_queue = QSLT_BEACON; - - dma_addr_t mapping = pci_map_single(rtlpci->pdev, - skb->data, skb->len, - PCI_DMA_TODEVICE); - - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); - - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - - SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); - - SET_TX_DESC_SEQ(pdesc, 0); - - SET_TX_DESC_LINIP(pdesc, 0); - - SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); - - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); - - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - SET_TX_DESC_RATE_ID(pdesc, 0); - SET_TX_DESC_MACID(pdesc, 0); - - SET_TX_DESC_OWN(pdesc, 1); - - SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len)); - - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - SET_TX_DESC_USE_RATE(pdesc, 1); - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C Tx Cmd Content\n", pdesc, TX_DESC_SIZE); -} - -void rtl8723be_set_desc(struct ieee80211_hw *hw, u8 *pdesc, - bool istx, u8 desc_name, u8 *val) -{ - if (istx) { - switch (desc_name) { - case HW_DESC_OWN: - SET_TX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_TX_NEXTDESC_ADDR: - SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *)val); - break; - default: - RT_ASSERT(false, "ERR txdesc :%d not process\n", - desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_RXOWN: - SET_RX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_RXBUFF_ADDR: - SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *)val); - break; - case HW_DESC_RXPKT_LEN: - SET_RX_DESC_PKT_LEN(pdesc, *(u32 *)val); - break; - case HW_DESC_RXERO: - SET_RX_DESC_EOR(pdesc, 1); - break; - default: - RT_ASSERT(false, "ERR rxdesc :%d not process\n", - desc_name); - break; - } - } -} - -u32 rtl8723be_get_desc(u8 *pdesc, bool istx, u8 desc_name) -{ - u32 ret = 0; - - if (istx) { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_TX_DESC_OWN(pdesc); - break; - case HW_DESC_TXBUFF_ADDR: - ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc); - break; - default: - RT_ASSERT(false, "ERR txdesc :%d not process\n", - desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_RX_DESC_OWN(pdesc); - break; - case HW_DESC_RXPKT_LEN: - ret = GET_RX_DESC_PKT_LEN(pdesc); - break; - case HW_DESC_RXBUFF_ADDR: - ret = GET_RX_DESC_BUFF_ADDR(pdesc); - break; - default: - RT_ASSERT(false, "ERR rxdesc :%d not process\n", - desc_name); - break; - } - } - return ret; -} - -bool rtl8723be_is_tx_desc_closed(struct ieee80211_hw *hw, - u8 hw_queue, u16 index) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; - u8 *entry = (u8 *)(&ring->desc[ring->idx]); - u8 own = (u8)rtl8723be_get_desc(entry, true, HW_DESC_OWN); - - /*beacon packet will only use the first - *descriptor defautly,and the own may not - *be cleared by the hardware - */ - if (own) - return false; - return true; -} - -void rtl8723be_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (hw_queue == BEACON_QUEUE) { - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); - } else { - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, - BIT(0) << (hw_queue)); - } -} - -u32 rtl8723be_rx_command_packet(struct ieee80211_hw *hw, - struct rtl_stats status, - struct sk_buff *skb) -{ - u32 result = 0; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - switch (status.packet_report_type) { - case NORMAL_RX: - result = 0; - break; - case C2H_PACKET: - rtl8723be_c2h_packet_handler(hw, skb->data, - (u8)skb->len); - result = 1; - break; - default: - RT_TRACE(rtlpriv, COMP_RECV, DBG_TRACE, - "No this packet type!!\n"); - break; - } - - return result; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/trx.h b/drivers/net/wireless/rtlwifi/rtl8723be/trx.h deleted file mode 100644 index 45949ac4854c..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723be/trx.h +++ /dev/null @@ -1,625 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8723BE_TRX_H__ -#define __RTL8723BE_TRX_H__ - -#define TX_DESC_SIZE 40 -#define TX_DESC_AGGR_SUBFRAME_SIZE 32 - -#define RX_DESC_SIZE 32 -#define RX_DRV_INFO_SIZE_UNIT 8 - -#define TX_DESC_NEXT_DESC_OFFSET 40 -#define USB_HWDESC_HEADER_LEN 40 -#define CRCLENGTH 4 - -#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) -#define SET_TX_DESC_OFFSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) -#define SET_TX_DESC_BMC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) -#define SET_TX_DESC_HTC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) -#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) -#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) -#define SET_TX_DESC_LINIP(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) -#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) -#define SET_TX_DESC_GF(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) -#define SET_TX_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) - -#define GET_TX_DESC_PKT_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 0, 16) -#define GET_TX_DESC_OFFSET(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 16, 8) -#define GET_TX_DESC_BMC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 24, 1) -#define GET_TX_DESC_HTC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 25, 1) -#define GET_TX_DESC_LAST_SEG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 26, 1) -#define GET_TX_DESC_FIRST_SEG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 27, 1) -#define GET_TX_DESC_LINIP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 28, 1) -#define GET_TX_DESC_NO_ACM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 29, 1) -#define GET_TX_DESC_GF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 30, 1) -#define GET_TX_DESC_OWN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 31, 1) - -#define SET_TX_DESC_MACID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 7, __val) -#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) -#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) -#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) -#define SET_TX_DESC_PIFS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) -#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 5, __val) -#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) -#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) -#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 5, __val) - - -#define SET_TX_DESC_PAID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 9, __val) -#define SET_TX_DESC_CCA_RTS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 10, 2, __val) -#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val) -#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val) -#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val) -#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val) -#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) -#define SET_TX_DESC_RAW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) -#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) -#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) -#define SET_TX_DESC_BT_INT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val) -#define SET_TX_DESC_GID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 6, __val) - - -#define SET_TX_DESC_WHEADER_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 4, __val) -#define SET_TX_DESC_CHK_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 4, 1, __val) -#define SET_TX_DESC_EARLY_MODE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 5, 1, __val) -#define SET_TX_DESC_HWSEQ_SEL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 6, 2, __val) -#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 1, __val) -#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 9, 1, __val) -#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 10, 1, __val) -#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 11, 1, __val) -#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 12, 1, __val) -#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 13, 1, __val) -#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 15, 1, __val) -#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 1, __val) -#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 17, 5, __val) -#define SET_TX_DESC_NDPA(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 22, 2, __val) -#define SET_TX_DESC_AMPDU_MAX_TIME(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 24, 8, __val) - - -#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 7, __val) -#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 5, __val) -#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 4, __val) -#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 17, 1, __val) -#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 6, __val) -#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 5, __val) - - -#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 4, __val) -#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 4, 1, __val) -#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 5, 2, __val) -#define SET_TX_DESC_DATA_LDPC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) -#define SET_TX_DESC_DATA_STBC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 2, __val) -#define SET_TX_DESC_CTROL_STBC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 10, 2, __val) -#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 12, 1, __val) -#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) - - -#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) - -#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) - -#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 15, 1, __val) - -#define SET_TX_DESC_SEQ(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+36, 12, 12, __val) - -#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) - -#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+40, 0, 32) - - -#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+48, 0, 32, __val) - -#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+48, 0, 32) - -#define GET_RX_DESC_PKT_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 0, 14) -#define GET_RX_DESC_CRC32(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 14, 1) -#define GET_RX_DESC_ICV(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 15, 1) -#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 16, 4) -#define GET_RX_DESC_SECURITY(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 20, 3) -#define GET_RX_DESC_QOS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 23, 1) -#define GET_RX_DESC_SHIFT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 24, 2) -#define GET_RX_DESC_PHYST(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 26, 1) -#define GET_RX_DESC_SWDEC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 27, 1) -#define GET_RX_DESC_LS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 28, 1) -#define GET_RX_DESC_FS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 29, 1) -#define GET_RX_DESC_EOR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 30, 1) -#define GET_RX_DESC_OWN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 31, 1) - -#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) -#define SET_RX_DESC_EOR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) -#define SET_RX_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) - -#define GET_RX_DESC_MACID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 0, 7) -#define GET_RX_DESC_TID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 8, 4) -#define GET_RX_DESC_AMSDU(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) -#define GET_RX_STATUS_DESC_RXID_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) -#define GET_RX_DESC_PAGGR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) -#define GET_RX_DESC_A1_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) -#define GET_RX_DESC_CHKERR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) -#define GET_RX_DESC_IPVER(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) -#define GET_RX_STATUS_DESC_IS_TCPUDP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 22, 1) -#define GET_RX_STATUS_DESC_CHK_VLD(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 23, 1) -#define GET_RX_DESC_PAM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) -#define GET_RX_DESC_PWR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) -#define GET_RX_DESC_MD(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) -#define GET_RX_DESC_MF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) -#define GET_RX_DESC_TYPE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) -#define GET_RX_DESC_MC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) -#define GET_RX_DESC_BC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) - - -#define GET_RX_DESC_SEQ(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) -#define GET_RX_DESC_FRAG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) -#define GET_RX_STATUS_DESC_RX_IS_QOS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 16, 1) -#define GET_RX_STATUS_DESC_WLANHD_IV_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 18, 6) -#define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 28, 1) - - -#define GET_RX_DESC_RXMCS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 0, 7) -#define GET_RX_DESC_RXHT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 6, 1) -#define GET_RX_STATUS_DESC_RX_GF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 7, 1) -#define GET_RX_DESC_HTC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) -#define GET_RX_STATUS_DESC_EOSP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 11, 1) -#define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 12, 2) - -#define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 29, 1) -#define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 30, 1) -#define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 31, 1) - -#define GET_RX_DESC_SPLCP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 0, 1) -#define GET_RX_STATUS_DESC_LDPC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 1, 1) -#define GET_RX_STATUS_DESC_STBC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 2, 1) -#define GET_RX_DESC_BW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 4, 2) - -#define GET_RX_DESC_TSFL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) - -#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) -#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) - -#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) -#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) - - -/* TX report 2 format in Rx desc*/ - -#define GET_RX_RPT2_DESC_PKT_LEN(__rxstatusdesc) \ - LE_BITS_TO_4BYTE(__rxstatusdesc, 0, 9) -#define GET_RX_RPT2_DESC_MACID_VALID_1(__rxstatusdesc) \ - LE_BITS_TO_4BYTE(__rxstatusdesc+16, 0, 32) -#define GET_RX_RPT2_DESC_MACID_VALID_2(__rxstatusdesc) \ - LE_BITS_TO_4BYTE(__rxstatusdesc+20, 0, 32) - -#define SET_EARLYMODE_PKTNUM(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __value) -#define SET_EARLYMODE_LEN0(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 4, 12, __value) -#define SET_EARLYMODE_LEN1(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 16, 12, __value) -#define SET_EARLYMODE_LEN2_1(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 28, 4, __value) -#define SET_EARLYMODE_LEN2_2(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __value) -#define SET_EARLYMODE_LEN3(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 8, 12, __value) -#define SET_EARLYMODE_LEN4(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __value) - -#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ -do { \ - if (_size > TX_DESC_NEXT_DESC_OFFSET) \ - memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ - else \ - memset(__pdesc, 0, _size); \ -} while (0) - -struct phy_rx_agc_info_t { - #ifdef __LITTLE_ENDIAN - u8 gain:7, trsw:1; - #else - u8 trsw:1, gain:7; - #endif -}; -struct phy_status_rpt { - struct phy_rx_agc_info_t path_agc[2]; - u8 ch_corr[2]; - u8 cck_sig_qual_ofdm_pwdb_all; - u8 cck_agc_rpt_ofdm_cfosho_a; - u8 cck_rpt_b_ofdm_cfosho_b; - u8 rsvd_1;/* ch_corr_msb; */ - u8 noise_power_db_msb; - char path_cfotail[2]; - u8 pcts_mask[2]; - char stream_rxevm[2]; - u8 path_rxsnr[2]; - u8 noise_power_db_lsb; - u8 rsvd_2[3]; - u8 stream_csi[2]; - u8 stream_target_csi[2]; - u8 sig_evm; - u8 rsvd_3; -#ifdef __LITTLE_ENDIAN - u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ - u8 sgi_en:1; - u8 rxsc:2; - u8 idle_long:1; - u8 r_ant_train_en:1; - u8 ant_sel_b:1; - u8 ant_sel:1; -#else /* _BIG_ENDIAN_ */ - u8 ant_sel:1; - u8 ant_sel_b:1; - u8 r_ant_train_en:1; - u8 idle_long:1; - u8 rxsc:2; - u8 sgi_en:1; - u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ -#endif -} __packed; - -struct rx_fwinfo_8723be { - u8 gain_trsw[2]; - u16 chl_num:10; - u16 sub_chnl:4; - u16 r_rfmod:2; - u8 pwdb_all; - u8 cfosho[4]; - u8 cfotail[4]; - char rxevm[2]; - char rxsnr[2]; - u8 pcts_msk_rpt[2]; - u8 pdsnr[2]; - u8 csi_current[2]; - u8 rx_gain_c; - u8 rx_gain_d; - u8 sigevm; - u8 resvd_0; - u8 antidx_anta:3; - u8 antidx_antb:3; - u8 resvd_1:2; -} __packed; - -struct tx_desc_8723be { - u32 pktsize:16; - u32 offset:8; - u32 bmc:1; - u32 htc:1; - u32 lastseg:1; - u32 firstseg:1; - u32 linip:1; - u32 noacm:1; - u32 gf:1; - u32 own:1; - - u32 macid:6; - u32 rsvd0:2; - u32 queuesel:5; - u32 rd_nav_ext:1; - u32 lsig_txop_en:1; - u32 pifs:1; - u32 rateid:4; - u32 nav_usehdr:1; - u32 en_descid:1; - u32 sectype:2; - u32 pktoffset:8; - - u32 rts_rc:6; - u32 data_rc:6; - u32 agg_en:1; - u32 rdg_en:1; - u32 bar_retryht:2; - u32 agg_break:1; - u32 morefrag:1; - u32 raw:1; - u32 ccx:1; - u32 ampdudensity:3; - u32 bt_int:1; - u32 ant_sela:1; - u32 ant_selb:1; - u32 txant_cck:2; - u32 txant_l:2; - u32 txant_ht:2; - - u32 nextheadpage:8; - u32 tailpage:8; - u32 seq:12; - u32 cpu_handle:1; - u32 tag1:1; - u32 trigger_int:1; - u32 hwseq_en:1; - - u32 rtsrate:5; - u32 apdcfe:1; - u32 qos:1; - u32 hwseq_ssn:1; - u32 userrate:1; - u32 dis_rtsfb:1; - u32 dis_datafb:1; - u32 cts2self:1; - u32 rts_en:1; - u32 hwrts_en:1; - u32 portid:1; - u32 pwr_status:3; - u32 waitdcts:1; - u32 cts2ap_en:1; - u32 txsc:2; - u32 stbc:2; - u32 txshort:1; - u32 txbw:1; - u32 rtsshort:1; - u32 rtsbw:1; - u32 rtssc:2; - u32 rtsstbc:2; - - u32 txrate:6; - u32 shortgi:1; - u32 ccxt:1; - u32 txrate_fb_lmt:5; - u32 rtsrate_fb_lmt:4; - u32 retrylmt_en:1; - u32 txretrylmt:6; - u32 usb_txaggnum:8; - - u32 txagca:5; - u32 txagcb:5; - u32 usemaxlen:1; - u32 maxaggnum:5; - u32 mcsg1maxlen:4; - u32 mcsg2maxlen:4; - u32 mcsg3maxlen:4; - u32 mcs7sgimaxlen:4; - - u32 txbuffersize:16; - u32 sw_offset30:8; - u32 sw_offset31:4; - u32 rsvd1:1; - u32 antsel_c:1; - u32 null_0:1; - u32 null_1:1; - - u32 txbuffaddr; - u32 txbufferaddr64; - u32 nextdescaddress; - u32 nextdescaddress64; - - u32 reserve_pass_pcie_mm_limit[4]; -} __packed; - -struct rx_desc_8723be { - u32 length:14; - u32 crc32:1; - u32 icverror:1; - u32 drv_infosize:4; - u32 security:3; - u32 qos:1; - u32 shift:2; - u32 phystatus:1; - u32 swdec:1; - u32 lastseg:1; - u32 firstseg:1; - u32 eor:1; - u32 own:1; - - u32 macid:6; - u32 tid:4; - u32 hwrsvd:5; - u32 paggr:1; - u32 faggr:1; - u32 a1_fit:4; - u32 a2_fit:4; - u32 pam:1; - u32 pwr:1; - u32 moredata:1; - u32 morefrag:1; - u32 type:2; - u32 mc:1; - u32 bc:1; - - u32 seq:12; - u32 frag:4; - u32 nextpktlen:14; - u32 nextind:1; - u32 rsvd:1; - - u32 rxmcs:6; - u32 rxht:1; - u32 amsdu:1; - u32 splcp:1; - u32 bandwidth:1; - u32 htc:1; - u32 tcpchk_rpt:1; - u32 ipcchk_rpt:1; - u32 tcpchk_valid:1; - u32 hwpcerr:1; - u32 hwpcind:1; - u32 iv0:16; - - u32 iv1; - - u32 tsfl; - - u32 bufferaddress; - u32 bufferaddress64; - -} __packed; - -void rtl8723be_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, - u8 *pdesc_tx, u8 *txbd, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); -bool rtl8723be_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *status, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb); -void rtl8723be_set_desc(struct ieee80211_hw *hw, u8 *pdesc, - bool istx, u8 desc_name, u8 *val); -u32 rtl8723be_get_desc(u8 *pdesc, bool istx, u8 desc_name); -bool rtl8723be_is_tx_desc_closed(struct ieee80211_hw *hw, - u8 hw_queue, u16 index); -void rtl8723be_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); -void rtl8723be_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, - struct sk_buff *skb); -u32 rtl8723be_rx_command_packet(struct ieee80211_hw *hw, - struct rtl_stats status, - struct sk_buff *skb); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/Makefile b/drivers/net/wireless/rtlwifi/rtl8723com/Makefile deleted file mode 100644 index 345a68adcf38..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723com/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -rtl8723-common-objs := \ - main.o \ - dm_common.o \ - fw_common.o \ - phy_common.o - -obj-$(CONFIG_RTL8723_COMMON) += rtl8723-common.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.c deleted file mode 100644 index 064340641913..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.c +++ /dev/null @@ -1,65 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "dm_common.h" -#include "../rtl8723ae/dm.h" -#include - -/* These routines are common to RTL8723AE and RTL8723bE */ - -void rtl8723_dm_init_dynamic_txpower(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.dynamic_txpower_enable = false; - - rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; - rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; -} -EXPORT_SYMBOL_GPL(rtl8723_dm_init_dynamic_txpower); - -void rtl8723_dm_init_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - rtlpriv->dm.current_turbo_edca = false; - rtlpriv->dm.is_any_nonbepkts = false; - rtlpriv->dm.is_cur_rdlstate = false; -} -EXPORT_SYMBOL_GPL(rtl8723_dm_init_edca_turbo); - -void rtl8723_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ps_t *dm_pstable = &rtlpriv->dm_pstable; - - dm_pstable->pre_ccastate = CCA_MAX; - dm_pstable->cur_ccasate = CCA_MAX; - dm_pstable->pre_rfstate = RF_MAX; - dm_pstable->cur_rfstate = RF_MAX; - dm_pstable->rssi_val_min = 0; - dm_pstable->initialize = 0; -} -EXPORT_SYMBOL_GPL(rtl8723_dm_init_dynamic_bb_powersaving); diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.h b/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.h deleted file mode 100644 index 5c1b94ce2f86..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723com/dm_common.h +++ /dev/null @@ -1,33 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __DM_COMMON_H__ -#define __DM_COMMON_H__ - -void rtl8723_dm_init_dynamic_txpower(struct ieee80211_hw *hw); -void rtl8723_dm_init_edca_turbo(struct ieee80211_hw *hw); -void rtl8723_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c deleted file mode 100644 index a2f5e89bedfe..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.c +++ /dev/null @@ -1,339 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "fw_common.h" -#include - -void rtl8723_enable_fw_download(struct ieee80211_hw *hw, bool enable) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp; - - if (enable) { - tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, - tmp | 0x04); - - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); - rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); - - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); - rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); - } else { - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); - rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); - - rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00); - } -} -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) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 *bufferptr = buffer; - u32 page_nums, remain_size; - u32 page, offset; - - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size); - - rtl8723_fill_dummy(bufferptr, &size); - - page_nums = size / FW_8192C_PAGE_SIZE; - remain_size = size % FW_8192C_PAGE_SIZE; - - if (page_nums > max_page) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Page numbers should not greater than %d\n", max_page); - } - 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); - } - - if (remain_size) { - offset = page_nums * FW_8192C_PAGE_SIZE; - page = page_nums; - rtl8723_fw_page_write(hw, page, (bufferptr + offset), - remain_size); - } - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW write done.\n"); -} -EXPORT_SYMBOL_GPL(rtl8723_write_fw); - -void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw) -{ - u8 u1b_tmp; - u8 delay = 100; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20); - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - - while (u1b_tmp & BIT(2)) { - delay--; - if (delay == 0) - break; - udelay(50); - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - } - if (delay == 0) { - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, - u1b_tmp&(~BIT(2))); - } -} -EXPORT_SYMBOL_GPL(rtl8723ae_firmware_selfreset); - -void rtl8723be_firmware_selfreset(struct ieee80211_hw *hw) -{ - u8 u1b_tmp; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); - udelay(50); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0))); - - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2))); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - " _8051Reset8723be(): 8051 reset success .\n"); -} -EXPORT_SYMBOL_GPL(rtl8723be_firmware_selfreset); - -int rtl8723_fw_free_to_go(struct ieee80211_hw *hw, bool is_8723be, - int max_count) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int err = -EIO; - u32 counter = 0; - u32 value32; - - do { - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - } while ((counter++ < max_count) && - (!(value32 & FWDL_CHKSUM_RPT))); - - if (counter >= max_count) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "chksum report fail ! REG_MCUFWDL:0x%08x .\n", - value32); - goto exit; - } - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); - - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL) | MCUFWDL_RDY; - value32 &= ~WINTINI_RDY; - rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); - - if (is_8723be) - rtl8723be_firmware_selfreset(hw); - counter = 0; - - do { - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - if (value32 & WINTINI_RDY) { - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n", - value32); - err = 0; - goto exit; - } - - mdelay(FW_8192C_POLLING_DELAY); - - } while (counter++ < max_count); - - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", - value32); - -exit: - return err; -} -EXPORT_SYMBOL_GPL(rtl8723_fw_free_to_go); - -int rtl8723_download_fw(struct ieee80211_hw *hw, - bool is_8723be, int max_count) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtlwifi_firmware_header *pfwheader; - u8 *pfwdata; - u32 fwsize; - int err; - enum version_8723e version = rtlhal->version; - int max_page; - - if (!rtlhal->pfirmware) - return 1; - - pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; - pfwdata = rtlhal->pfirmware; - fwsize = rtlhal->fwsize; - - if (!is_8723be) - max_page = 6; - else - max_page = 8; - if (rtlpriv->cfg->ops->is_fw_header(pfwheader)) { - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "Firmware Version(%d), Signature(%#x), Size(%d)\n", - pfwheader->version, pfwheader->signature, - (int)sizeof(struct rtlwifi_firmware_header)); - - pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); - fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); - } - - if (rtl_read_byte(rtlpriv, REG_MCUFWDL)&BIT(7)) { - if (is_8723be) - rtl8723be_firmware_selfreset(hw); - else - rtl8723ae_firmware_selfreset(hw); - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); - } - rtl8723_enable_fw_download(hw, true); - rtl8723_write_fw(hw, version, pfwdata, fwsize, max_page); - rtl8723_enable_fw_download(hw, false); - - err = rtl8723_fw_free_to_go(hw, is_8723be, max_count); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Firmware is not ready to run!\n"); - } else { - RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, - "Firmware is ready to run!\n"); - } - return 0; -} -EXPORT_SYMBOL_GPL(rtl8723_download_fw); - -bool rtl8723_cmd_send_packet(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring; - struct rtl_tx_desc *pdesc; - struct sk_buff *pskb = NULL; - u8 own; - unsigned long flags; - - ring = &rtlpci->tx_ring[BEACON_QUEUE]; - - pskb = __skb_dequeue(&ring->queue); - if (pskb) - kfree_skb(pskb); - - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - - pdesc = &ring->desc[0]; - own = (u8) rtlpriv->cfg->ops->get_desc((u8 *)pdesc, true, HW_DESC_OWN); - - rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); - - __skb_queue_tail(&ring->queue, skb); - - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - - rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); - - return true; -} -EXPORT_SYMBOL_GPL(rtl8723_cmd_send_packet); diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.h deleted file mode 100644 index 8ea372d1626e..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723com/fw_common.h +++ /dev/null @@ -1,100 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __FW_COMMON_H__ -#define __FW_COMMON_H__ - -#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 -#define FW_8192C_POLLING_DELAY 5 - -#define MCUFWDL_RDY BIT(1) -#define FWDL_CHKSUM_RPT BIT(2) -#define WINTINI_RDY BIT(6) - -#define REG_RSV_CTRL 0x001C -#define REG_HMETFR 0x01CC - -enum version_8723e { - VERSION_TEST_UMC_CHIP_8723 = 0x0081, - VERSION_NORMAL_UMC_CHIP_8723_1T1R_A_CUT = 0x0089, - VERSION_NORMAL_UMC_CHIP_8723_1T1R_B_CUT = 0x1089, - VERSION_TEST_CHIP_1T1R_8723B = 0x0106, - VERSION_NORMAL_SMIC_CHIP_1T1R_8723B = 0x010E, - VERSION_UNKNOWN = 0xFF, -}; - -enum rtl8723be_cmd { - H2C_8723BE_RSVDPAGE = 0, - H2C_8723BE_JOINBSSRPT = 1, - H2C_8723BE_SCAN = 2, - H2C_8723BE_KEEP_ALIVE_CTRL = 3, - H2C_8723BE_DISCONNECT_DECISION = 4, - H2C_8723BE_INIT_OFFLOAD = 6, - H2C_8723BE_AP_OFFLOAD = 8, - H2C_8723BE_BCN_RSVDPAGE = 9, - H2C_8723BE_PROBERSP_RSVDPAGE = 10, - - H2C_8723BE_SETPWRMODE = 0x20, - H2C_8723BE_PS_TUNING_PARA = 0x21, - H2C_8723BE_PS_TUNING_PARA2 = 0x22, - H2C_8723BE_PS_LPS_PARA = 0x23, - H2C_8723BE_P2P_PS_OFFLOAD = 0x24, - - H2C_8723BE_WO_WLAN = 0x80, - H2C_8723BE_REMOTE_WAKE_CTRL = 0x81, - H2C_8723BE_AOAC_GLOBAL_INFO = 0x82, - H2C_8723BE_AOAC_RSVDPAGE = 0x83, - H2C_8723BE_RSSI_REPORT = 0x42, - H2C_8723BE_RA_MASK = 0x40, - H2C_8723BE_SELECTIVE_SUSPEND_ROF_CMD, - H2C_8723BE_P2P_PS_MODE, - H2C_8723BE_PSD_RESULT, - /*Not defined CTW CMD for P2P yet*/ - H2C_8723BE_P2P_PS_CTW_CMD, - MAX_8723BE_H2CCMD -}; - -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); -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/rtlwifi/rtl8723com/main.c b/drivers/net/wireless/rtlwifi/rtl8723com/main.c deleted file mode 100644 index 9014a94fac6a..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723com/main.c +++ /dev/null @@ -1,33 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include - - -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_AUTHOR("Larry Finger "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Realtek RTL8723AE/RTL8723BE 802.11n PCI wireless common routines"); diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.c deleted file mode 100644 index 75cbd1509b52..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.c +++ /dev/null @@ -1,447 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "phy_common.h" -#include "../rtl8723ae/reg.h" -#include - -/* These routines are common to RTL8723AE and RTL8723bE */ - -u32 rtl8723_phy_query_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 returnvalue, originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask); - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = rtl8723_phy_calculate_bit_shift(bitmask); - returnvalue = (originalvalue & bitmask) >> bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "BBR MASK=0x%x Addr[0x%x]=0x%x\n", bitmask, - regaddr, originalvalue); - return returnvalue; -} -EXPORT_SYMBOL_GPL(rtl8723_phy_query_bb_reg); - -void rtl8723_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, - u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", regaddr, bitmask, - data); - - if (bitmask != MASKDWORD) { - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = rtl8723_phy_calculate_bit_shift(bitmask); - data = ((originalvalue & (~bitmask)) | (data << bitshift)); - } - - rtl_write_dword(rtlpriv, regaddr, data); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); -} -EXPORT_SYMBOL_GPL(rtl8723_phy_set_bb_reg); - -u32 rtl8723_phy_calculate_bit_shift(u32 bitmask) -{ - u32 i; - - for (i = 0; i <= 31; i++) { - if (((bitmask >> i) & 0x1) == 1) - break; - } - return i; -} -EXPORT_SYMBOL_GPL(rtl8723_phy_calculate_bit_shift); - -u32 rtl8723_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - u32 newoffset; - u32 tmplong, tmplong2; - u8 rfpi_enable = 0; - u32 retvalue; - - offset &= 0xff; - newoffset = offset; - if (RT_CANNOT_IO(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n"); - return 0xFFFFFFFF; - } - tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); - if (rfpath == RF90_PATH_A) - tmplong2 = tmplong; - else - tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); - tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | - (newoffset << 23) | BLSSIREADEDGE; - rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, - tmplong & (~BLSSIREADEDGE)); - mdelay(1); - rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); - mdelay(1); - rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, - tmplong | BLSSIREADEDGE); - mdelay(1); - if (rfpath == RF90_PATH_A) - rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, - BIT(8)); - else if (rfpath == RF90_PATH_B) - rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, - BIT(8)); - if (rfpi_enable) - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, - BLSSIREADBACKDATA); - else - retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, - BLSSIREADBACKDATA); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "RFR-%d Addr[0x%x]=0x%x\n", - rfpath, pphyreg->rf_rb, retvalue); - return retvalue; -} -EXPORT_SYMBOL_GPL(rtl8723_phy_rf_serial_read); - -void rtl8723_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 offset, u32 data) -{ - u32 data_and_addr; - u32 newoffset; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - - if (RT_CANNOT_IO(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n"); - return; - } - offset &= 0xff; - newoffset = offset; - data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; - rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "RFW-%d Addr[0x%x]=0x%x\n", - rfpath, pphyreg->rf3wire_offset, - data_and_addr); -} -EXPORT_SYMBOL_GPL(rtl8723_phy_rf_serial_write); - -long rtl8723_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - u8 txpwridx) -{ - long offset; - long pwrout_dbm; - - switch (wirelessmode) { - case WIRELESS_MODE_B: - offset = -7; - break; - case WIRELESS_MODE_G: - case WIRELESS_MODE_N_24G: - offset = -8; - break; - default: - offset = -8; - break; - } - pwrout_dbm = txpwridx / 2 + offset; - return pwrout_dbm; -} -EXPORT_SYMBOL_GPL(rtl8723_phy_txpwr_idx_to_dbm); - -void rtl8723_phy_init_bb_rf_reg_def(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - - rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; - rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; - rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; - rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; - - rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = - RFPGA0_XA_LSSIPARAMETER; - rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = - RFPGA0_XB_LSSIPARAMETER; - - rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; - rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; - - rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; - rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; - rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; - rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; - - rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; - rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; - - rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; - rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; - - rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; - rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; - - rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; - rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; - - rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; - rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; - - rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBANLANCE; - rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; - - rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; - rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; - rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; - rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; - - rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE; - rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE; - - rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; - rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; - rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE; - rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; - - rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK; - rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK; - - rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK; - rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK; - -} -EXPORT_SYMBOL_GPL(rtl8723_phy_init_bb_rf_reg_def); - -bool rtl8723_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, - u32 cmdtablesz, - enum swchnlcmd_id cmdid, - u32 para1, u32 para2, - u32 msdelay) -{ - struct swchnlcmd *pcmd; - - if (cmdtable == NULL) { - RT_ASSERT(false, "cmdtable cannot be NULL.\n"); - return false; - } - - if (cmdtableidx >= cmdtablesz) - return false; - - pcmd = cmdtable + cmdtableidx; - pcmd->cmdid = cmdid; - pcmd->para1 = para1; - pcmd->para2 = para2; - pcmd->msdelay = msdelay; - return true; -} -EXPORT_SYMBOL_GPL(rtl8723_phy_set_sw_chnl_cmdarray); - -void rtl8723_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, - bool iqk_ok, - long result[][8], - u8 final_candidate, - bool btxonly) -{ - u32 oldval_0, x, tx0_a, reg; - long y, tx0_c; - - if (final_candidate == 0xFF) { - return; - } else if (iqk_ok) { - oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE, - MASKDWORD) >> 22) & 0x3FF; - x = result[final_candidate][0]; - if ((x & 0x00000200) != 0) - x = x | 0xFFFFFC00; - tx0_a = (x * oldval_0) >> 8; - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31), - ((x * oldval_0 >> 7) & 0x1)); - y = result[final_candidate][1]; - if ((y & 0x00000200) != 0) - y = y | 0xFFFFFC00; - tx0_c = (y * oldval_0) >> 8; - rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000, - ((tx0_c & 0x3C0) >> 6)); - rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000, - (tx0_c & 0x3F)); - rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29), - ((y * oldval_0 >> 7) & 0x1)); - if (btxonly) - return; - reg = result[final_candidate][2]; - rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg); - reg = result[final_candidate][3] & 0x3F; - rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg); - reg = (result[final_candidate][3] >> 6) & 0xF; - rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); - } -} -EXPORT_SYMBOL_GPL(rtl8723_phy_path_a_fill_iqk_matrix); - -void rtl8723_save_adda_registers(struct ieee80211_hw *hw, u32 *addareg, - u32 *addabackup, u32 registernum) -{ - u32 i; - - for (i = 0; i < registernum; i++) - addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD); -} -EXPORT_SYMBOL_GPL(rtl8723_save_adda_registers); - -void rtl8723_phy_save_mac_registers(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) - macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); - macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); -} -EXPORT_SYMBOL_GPL(rtl8723_phy_save_mac_registers); - -void rtl8723_phy_reload_adda_registers(struct ieee80211_hw *hw, - u32 *addareg, u32 *addabackup, - u32 regiesternum) -{ - u32 i; - - for (i = 0; i < regiesternum; i++) - rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]); -} -EXPORT_SYMBOL_GPL(rtl8723_phy_reload_adda_registers); - -void rtl8723_phy_reload_mac_registers(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) - rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]); - rtl_write_dword(rtlpriv, macreg[i], macbackup[i]); -} -EXPORT_SYMBOL_GPL(rtl8723_phy_reload_mac_registers); - -void rtl8723_phy_path_adda_on(struct ieee80211_hw *hw, u32 *addareg, - bool is_patha_on, bool is2t) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 pathon; - u32 i; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723AE) { - pathon = is_patha_on ? 0x04db25a4 : 0x0b1b25a4; - if (!is2t) { - pathon = 0x0bdb25a0; - rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0); - } else { - rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon); - } - } else { - /* rtl8723be */ - pathon = 0x01c00014; - rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathon); - } - - for (i = 1; i < IQK_ADDA_REG_NUM; i++) - rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathon); -} -EXPORT_SYMBOL_GPL(rtl8723_phy_path_adda_on); - -void rtl8723_phy_mac_setting_calibration(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i = 0; - - rtl_write_byte(rtlpriv, macreg[i], 0x3F); - - for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) - rtl_write_byte(rtlpriv, macreg[i], - (u8) (macbackup[i] & (~BIT(3)))); - rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5)))); -} -EXPORT_SYMBOL_GPL(rtl8723_phy_mac_setting_calibration); - -void rtl8723_phy_path_a_standby(struct ieee80211_hw *hw) -{ - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0); - rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); - rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); -} -EXPORT_SYMBOL_GPL(rtl8723_phy_path_a_standby); - -void rtl8723_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode) -{ - u32 mode; - - mode = pi_mode ? 0x01000100 : 0x01000000; - rtl_set_bbreg(hw, 0x820, MASKDWORD, mode); - rtl_set_bbreg(hw, 0x828, MASKDWORD, mode); -} -EXPORT_SYMBOL_GPL(rtl8723_phy_pi_mode_switch); diff --git a/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.h b/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.h deleted file mode 100644 index 83b891a9adb8..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8723com/phy_common.h +++ /dev/null @@ -1,89 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2014 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __PHY_COMMON__ -#define __PHY_COMMON__ - -#define RT_CANNOT_IO(hw) false - -enum swchnlcmd_id { - CMDID_END, - CMDID_SET_TXPOWEROWER_LEVEL, - CMDID_BBREGWRITE10, - CMDID_WRITEPORT_ULONG, - CMDID_WRITEPORT_USHORT, - CMDID_WRITEPORT_UCHAR, - CMDID_RF_WRITEREG, -}; - -struct swchnlcmd { - enum swchnlcmd_id cmdid; - u32 para1; - u32 para2; - u32 msdelay; -}; - -u32 rtl8723_phy_query_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask); -void rtl8723_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, - u32 bitmask, u32 data); -u32 rtl8723_phy_calculate_bit_shift(u32 bitmask); -u32 rtl8723_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset); -void rtl8723_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 offset, u32 data); -long rtl8723_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - u8 txpwridx); -void rtl8723_phy_init_bb_rf_reg_def(struct ieee80211_hw *hw); -bool rtl8723_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, - u32 cmdtableidx, - u32 cmdtablesz, - enum swchnlcmd_id cmdid, - u32 para1, u32 para2, - u32 msdelay); -void rtl8723_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw, - bool iqk_ok, - long result[][8], - u8 final_candidate, - bool btxonly); -void rtl8723_save_adda_registers(struct ieee80211_hw *hw, u32 *addareg, - u32 *addabackup, u32 registernum); -void rtl8723_phy_save_mac_registers(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup); -void rtl8723_phy_reload_adda_registers(struct ieee80211_hw *hw, - u32 *addareg, u32 *addabackup, - u32 regiesternum); -void rtl8723_phy_reload_mac_registers(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup); -void rtl8723_phy_path_adda_on(struct ieee80211_hw *hw, u32 *addareg, - bool is_patha_on, bool is2t); -void rtl8723_phy_mac_setting_calibration(struct ieee80211_hw *hw, - u32 *macreg, u32 *macbackup); -void rtl8723_phy_path_a_standby(struct ieee80211_hw *hw); -void rtl8723_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile b/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile deleted file mode 100644 index f7a26f71197e..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -rtl8821ae-objs := \ - dm.o \ - fw.o \ - hw.o \ - led.o \ - phy.o \ - pwrseq.o \ - rf.o \ - sw.o \ - table.o \ - trx.o \ - - -obj-$(CONFIG_RTL8821AE) += rtl8821ae.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/def.h b/drivers/net/wireless/rtlwifi/rtl8821ae/def.h deleted file mode 100644 index dfbdf539de1a..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/def.h +++ /dev/null @@ -1,355 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8821AE_DEF_H__ -#define __RTL8821AE_DEF_H__ - -/*--------------------------Define -------------------------------------------*/ -#define USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN 1 - -/* BIT 7 HT Rate*/ -/*TxHT = 0*/ -#define MGN_1M 0x02 -#define MGN_2M 0x04 -#define MGN_5_5M 0x0b -#define MGN_11M 0x16 - -#define MGN_6M 0x0c -#define MGN_9M 0x12 -#define MGN_12M 0x18 -#define MGN_18M 0x24 -#define MGN_24M 0x30 -#define MGN_36M 0x48 -#define MGN_48M 0x60 -#define MGN_54M 0x6c - -/* TxHT = 1 */ -#define MGN_MCS0 0x80 -#define MGN_MCS1 0x81 -#define MGN_MCS2 0x82 -#define MGN_MCS3 0x83 -#define MGN_MCS4 0x84 -#define MGN_MCS5 0x85 -#define MGN_MCS6 0x86 -#define MGN_MCS7 0x87 -#define MGN_MCS8 0x88 -#define MGN_MCS9 0x89 -#define MGN_MCS10 0x8a -#define MGN_MCS11 0x8b -#define MGN_MCS12 0x8c -#define MGN_MCS13 0x8d -#define MGN_MCS14 0x8e -#define MGN_MCS15 0x8f -/* VHT rate */ -#define MGN_VHT1SS_MCS0 0x90 -#define MGN_VHT1SS_MCS1 0x91 -#define MGN_VHT1SS_MCS2 0x92 -#define MGN_VHT1SS_MCS3 0x93 -#define MGN_VHT1SS_MCS4 0x94 -#define MGN_VHT1SS_MCS5 0x95 -#define MGN_VHT1SS_MCS6 0x96 -#define MGN_VHT1SS_MCS7 0x97 -#define MGN_VHT1SS_MCS8 0x98 -#define MGN_VHT1SS_MCS9 0x99 -#define MGN_VHT2SS_MCS0 0x9a -#define MGN_VHT2SS_MCS1 0x9b -#define MGN_VHT2SS_MCS2 0x9c -#define MGN_VHT2SS_MCS3 0x9d -#define MGN_VHT2SS_MCS4 0x9e -#define MGN_VHT2SS_MCS5 0x9f -#define MGN_VHT2SS_MCS6 0xa0 -#define MGN_VHT2SS_MCS7 0xa1 -#define MGN_VHT2SS_MCS8 0xa2 -#define MGN_VHT2SS_MCS9 0xa3 - -#define MGN_VHT3SS_MCS0 0xa4 -#define MGN_VHT3SS_MCS1 0xa5 -#define MGN_VHT3SS_MCS2 0xa6 -#define MGN_VHT3SS_MCS3 0xa7 -#define MGN_VHT3SS_MCS4 0xa8 -#define MGN_VHT3SS_MCS5 0xa9 -#define MGN_VHT3SS_MCS6 0xaa -#define MGN_VHT3SS_MCS7 0xab -#define MGN_VHT3SS_MCS8 0xac -#define MGN_VHT3SS_MCS9 0xad - -#define MGN_MCS0_SG 0xc0 -#define MGN_MCS1_SG 0xc1 -#define MGN_MCS2_SG 0xc2 -#define MGN_MCS3_SG 0xc3 -#define MGN_MCS4_SG 0xc4 -#define MGN_MCS5_SG 0xc5 -#define MGN_MCS6_SG 0xc6 -#define MGN_MCS7_SG 0xc7 -#define MGN_MCS8_SG 0xc8 -#define MGN_MCS9_SG 0xc9 -#define MGN_MCS10_SG 0xca -#define MGN_MCS11_SG 0xcb -#define MGN_MCS12_SG 0xcc -#define MGN_MCS13_SG 0xcd -#define MGN_MCS14_SG 0xce -#define MGN_MCS15_SG 0xcf - -#define MGN_UNKNOWN 0xff - -/* 30 ms */ -#define WIFI_NAV_UPPER_US 30000 -#define HAL_92C_NAV_UPPER_UNIT 128 - -#define MAX_RX_DMA_BUFFER_SIZE 0x3E80 - -#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 -#define HAL_PRIME_CHNL_OFFSET_LOWER 1 -#define HAL_PRIME_CHNL_OFFSET_UPPER 2 - -#define RX_MPDU_QUEUE 0 -#define RX_CMD_QUEUE 1 - -#define MAX_RX_DMA_BUFFER_SIZE_8812 0x3E80 - -#define C2H_RX_CMD_HDR_LEN 8 -#define GET_C2H_CMD_CMD_LEN(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 0, 16) -#define GET_C2H_CMD_ELEMENT_ID(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 16, 8) -#define GET_C2H_CMD_CMD_SEQ(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 24, 7) -#define GET_C2H_CMD_CONTINUE(__prxhdr) \ - LE_BITS_TO_4BYTE((__prxhdr), 31, 1) -#define GET_C2H_CMD_CONTENT(__prxhdr) \ - ((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) - -#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) -#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) -#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) -#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) -#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) -#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) -#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) -#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) -#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ - LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) - -#define CHIP_BONDING_IDENTIFIER(_value) (((_value)>>22)&0x3) - -#define CHIP_8812 BIT(2) -#define CHIP_8821 (BIT(0)|BIT(2)) - -#define CHIP_8821A (BIT(0)|BIT(2)) -#define NORMAL_CHIP BIT(3) -#define RF_TYPE_1T1R (~(BIT(4)|BIT(5)|BIT(6))) -#define RF_TYPE_1T2R BIT(4) -#define RF_TYPE_2T2R BIT(5) -#define CHIP_VENDOR_UMC BIT(7) -#define B_CUT_VERSION BIT(12) -#define C_CUT_VERSION BIT(13) -#define D_CUT_VERSION ((BIT(12)|BIT(13))) -#define E_CUT_VERSION BIT(14) -#define RF_RL_ID (BIT(31)|BIT(30)|BIT(29)|BIT(28)) - -enum version_8821ae { - VERSION_TEST_CHIP_1T1R_8812 = 0x0004, - VERSION_TEST_CHIP_2T2R_8812 = 0x0024, - VERSION_NORMAL_TSMC_CHIP_1T1R_8812 = 0x100c, - VERSION_NORMAL_TSMC_CHIP_2T2R_8812 = 0x102c, - VERSION_NORMAL_TSMC_CHIP_1T1R_8812_C_CUT = 0x200c, - VERSION_NORMAL_TSMC_CHIP_2T2R_8812_C_CUT = 0x202c, - VERSION_TEST_CHIP_8821 = 0x0005, - VERSION_NORMAL_TSMC_CHIP_8821 = 0x000d, - VERSION_NORMAL_TSMC_CHIP_8821_B_CUT = 0x100d, - VERSION_UNKNOWN = 0xFF, -}; - -enum vht_data_sc { - VHT_DATA_SC_DONOT_CARE = 0, - VHT_DATA_SC_20_UPPER_OF_80MHZ = 1, - VHT_DATA_SC_20_LOWER_OF_80MHZ = 2, - VHT_DATA_SC_20_UPPERST_OF_80MHZ = 3, - VHT_DATA_SC_20_LOWEST_OF_80MHZ = 4, - VHT_DATA_SC_20_RECV1 = 5, - VHT_DATA_SC_20_RECV2 = 6, - VHT_DATA_SC_20_RECV3 = 7, - VHT_DATA_SC_20_RECV4 = 8, - VHT_DATA_SC_40_UPPER_OF_80MHZ = 9, - VHT_DATA_SC_40_LOWER_OF_80MHZ = 10, -}; - -/* MASK */ -#define IC_TYPE_MASK (BIT(0)|BIT(1)|BIT(2)) -#define CHIP_TYPE_MASK BIT(3) -#define RF_TYPE_MASK (BIT(4)|BIT(5)|BIT(6)) -#define MANUFACTUER_MASK BIT(7) -#define ROM_VERSION_MASK (BIT(11)|BIT(10)|BIT(9)|BIT(8)) -#define CUT_VERSION_MASK (BIT(15)|BIT(14)|BIT(13)|BIT(12)) - -/* Get element */ -#define GET_CVID_IC_TYPE(version) ((version) & IC_TYPE_MASK) -#define GET_CVID_CHIP_TYPE(version) ((version) & CHIP_TYPE_MASK) -#define GET_CVID_RF_TYPE(version) ((version) & RF_TYPE_MASK) -#define GET_CVID_MANUFACTUER(version) ((version) & MANUFACTUER_MASK) -#define GET_CVID_ROM_VERSION(version) ((version) & ROM_VERSION_MASK) -#define GET_CVID_CUT_VERSION(version) ((version) & CUT_VERSION_MASK) - -#define IS_1T1R(version) ((GET_CVID_RF_TYPE(version)) ? false : true) -#define IS_1T2R(version) ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R)\ - ? true : false) -#define IS_2T2R(version) ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R)\ - ? true : false) - -#define IS_8812_SERIES(version) ((GET_CVID_IC_TYPE(version) == CHIP_8812) ? \ - true : false) -#define IS_8821_SERIES(version) ((GET_CVID_IC_TYPE(version) == CHIP_8821) ? \ - true : false) - -#define IS_VENDOR_8812A_TEST_CHIP(version) ((IS_8812_SERIES(version)) ? \ - ((IS_NORMAL_CHIP(version)) ? \ - false : true) : false) -#define IS_VENDOR_8812A_MP_CHIP(version) ((IS_8812_SERIES(version)) ? \ - ((IS_NORMAL_CHIP(version)) ? \ - true : false) : false) -#define IS_VENDOR_8812A_C_CUT(version) ((IS_8812_SERIES(version)) ? \ - ((GET_CVID_CUT_VERSION(version) == \ - C_CUT_VERSION) ? \ - true : false) : false) - -#define IS_VENDOR_8821A_TEST_CHIP(version) ((IS_8821_SERIES(version)) ? \ - ((IS_NORMAL_CHIP(version)) ? \ - false : true) : false) -#define IS_VENDOR_8821A_MP_CHIP(version) ((IS_8821_SERIES(version)) ? \ - ((IS_NORMAL_CHIP(version)) ? \ - true : false) : false) -#define IS_VENDOR_8821A_B_CUT(version) ((IS_8821_SERIES(version)) ? \ - ((GET_CVID_CUT_VERSION(version) == \ - B_CUT_VERSION) ? \ - true : false) : false) -enum board_type { - ODM_BOARD_DEFAULT = 0, /* The DEFAULT case. */ - ODM_BOARD_MINICARD = BIT(0), /* 0 = non-mini card, 1 = mini card. */ - ODM_BOARD_SLIM = BIT(1), /* 0 = non-slim card, 1 = slim card */ - ODM_BOARD_BT = BIT(2), /* 0 = without BT card, 1 = with BT */ - ODM_BOARD_EXT_PA = BIT(3), /* 1 = existing 2G ext-PA */ - ODM_BOARD_EXT_LNA = BIT(4), /* 1 = existing 2G ext-LNA */ - ODM_BOARD_EXT_TRSW = BIT(5), /* 1 = existing ext-TRSW */ - ODM_BOARD_EXT_PA_5G = BIT(6), /* 1 = existing 5G ext-PA */ - ODM_BOARD_EXT_LNA_5G = BIT(7), /* 1 = existing 5G ext-LNA */ -}; - -enum rf_optype { - RF_OP_BY_SW_3WIRE = 0, - RF_OP_BY_FW, - RF_OP_MAX -}; - -enum rf_power_state { - RF_ON, - RF_OFF, - RF_SLEEP, - RF_SHUT_DOWN, -}; - -enum power_save_mode { - POWER_SAVE_MODE_ACTIVE, - POWER_SAVE_MODE_SAVE, -}; - -enum power_polocy_config { - POWERCFG_MAX_POWER_SAVINGS, - POWERCFG_GLOBAL_POWER_SAVINGS, - POWERCFG_LOCAL_POWER_SAVINGS, - POWERCFG_LENOVO, -}; - -enum interface_select_pci { - INTF_SEL1_MINICARD = 0, - INTF_SEL0_PCIE = 1, - INTF_SEL2_RSV = 2, - INTF_SEL3_RSV = 3, -}; - -enum hal_fw_c2h_cmd_id { - HAL_FW_C2H_CMD_READ_MACREG = 0, - HAL_FW_C2H_CMD_READ_BBREG = 1, - HAL_FW_C2H_CMD_READ_RFREG = 2, - HAL_FW_C2H_CMD_READ_EEPROM = 3, - HAL_FW_C2H_CMD_READ_EFUSE = 4, - HAL_FW_C2H_CMD_READ_CAM = 5, - HAL_FW_C2H_CMD_GET_BASICRATE = 6, - HAL_FW_C2H_CMD_GET_DATARATE = 7, - HAL_FW_C2H_CMD_SURVEY = 8, - HAL_FW_C2H_CMD_SURVEYDONE = 9, - HAL_FW_C2H_CMD_JOINBSS = 10, - HAL_FW_C2H_CMD_ADDSTA = 11, - HAL_FW_C2H_CMD_DELSTA = 12, - HAL_FW_C2H_CMD_ATIMDONE = 13, - HAL_FW_C2H_CMD_TX_REPORT = 14, - HAL_FW_C2H_CMD_CCX_REPORT = 15, - HAL_FW_C2H_CMD_DTM_REPORT = 16, - HAL_FW_C2H_CMD_TX_RATE_STATISTICS = 17, - HAL_FW_C2H_CMD_C2HLBK = 18, - HAL_FW_C2H_CMD_C2HDBG = 19, - HAL_FW_C2H_CMD_C2HFEEDBACK = 20, - HAL_FW_C2H_CMD_MAX -}; - -enum rtl_desc_qsel { - QSLT_BK = 0x2, - QSLT_BE = 0x0, - QSLT_VI = 0x5, - QSLT_VO = 0x7, - QSLT_BEACON = 0x10, - QSLT_HIGH = 0x11, - QSLT_MGNT = 0x12, - QSLT_CMD = 0x13, -}; - -enum rx_packet_type { - NORMAL_RX, - TX_REPORT1, - TX_REPORT2, - HIS_REPORT, - C2H_PACKET, -}; - -struct phy_sts_cck_8821ae_t { - u8 adc_pwdb_X[4]; - u8 sq_rpt; - u8 cck_agc_rpt; -}; - -struct h2c_cmd_8821ae { - u8 element_id; - u32 cmd_len; - u8 *p_cmdbuffer; -}; - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c deleted file mode 100644 index b57cfd965196..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c +++ /dev/null @@ -1,2988 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../base.h" -#include "../pci.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "fw.h" -#include "trx.h" -#include "../btcoexist/rtl_btc.h" - -static const u32 txscaling_tbl[TXSCALE_TABLE_SIZE] = { - 0x081, /* 0, -12.0dB */ - 0x088, /* 1, -11.5dB */ - 0x090, /* 2, -11.0dB */ - 0x099, /* 3, -10.5dB */ - 0x0A2, /* 4, -10.0dB */ - 0x0AC, /* 5, -9.5dB */ - 0x0B6, /* 6, -9.0dB */ - 0x0C0, /* 7, -8.5dB */ - 0x0CC, /* 8, -8.0dB */ - 0x0D8, /* 9, -7.5dB */ - 0x0E5, /* 10, -7.0dB */ - 0x0F2, /* 11, -6.5dB */ - 0x101, /* 12, -6.0dB */ - 0x110, /* 13, -5.5dB */ - 0x120, /* 14, -5.0dB */ - 0x131, /* 15, -4.5dB */ - 0x143, /* 16, -4.0dB */ - 0x156, /* 17, -3.5dB */ - 0x16A, /* 18, -3.0dB */ - 0x180, /* 19, -2.5dB */ - 0x197, /* 20, -2.0dB */ - 0x1AF, /* 21, -1.5dB */ - 0x1C8, /* 22, -1.0dB */ - 0x1E3, /* 23, -0.5dB */ - 0x200, /* 24, +0 dB */ - 0x21E, /* 25, +0.5dB */ - 0x23E, /* 26, +1.0dB */ - 0x261, /* 27, +1.5dB */ - 0x285, /* 28, +2.0dB */ - 0x2AB, /* 29, +2.5dB */ - 0x2D3, /* 30, +3.0dB */ - 0x2FE, /* 31, +3.5dB */ - 0x32B, /* 32, +4.0dB */ - 0x35C, /* 33, +4.5dB */ - 0x38E, /* 34, +5.0dB */ - 0x3C4, /* 35, +5.5dB */ - 0x3FE /* 36, +6.0dB */ -}; - -static const u32 rtl8821ae_txscaling_table[TXSCALE_TABLE_SIZE] = { - 0x081, /* 0, -12.0dB */ - 0x088, /* 1, -11.5dB */ - 0x090, /* 2, -11.0dB */ - 0x099, /* 3, -10.5dB */ - 0x0A2, /* 4, -10.0dB */ - 0x0AC, /* 5, -9.5dB */ - 0x0B6, /* 6, -9.0dB */ - 0x0C0, /* 7, -8.5dB */ - 0x0CC, /* 8, -8.0dB */ - 0x0D8, /* 9, -7.5dB */ - 0x0E5, /* 10, -7.0dB */ - 0x0F2, /* 11, -6.5dB */ - 0x101, /* 12, -6.0dB */ - 0x110, /* 13, -5.5dB */ - 0x120, /* 14, -5.0dB */ - 0x131, /* 15, -4.5dB */ - 0x143, /* 16, -4.0dB */ - 0x156, /* 17, -3.5dB */ - 0x16A, /* 18, -3.0dB */ - 0x180, /* 19, -2.5dB */ - 0x197, /* 20, -2.0dB */ - 0x1AF, /* 21, -1.5dB */ - 0x1C8, /* 22, -1.0dB */ - 0x1E3, /* 23, -0.5dB */ - 0x200, /* 24, +0 dB */ - 0x21E, /* 25, +0.5dB */ - 0x23E, /* 26, +1.0dB */ - 0x261, /* 27, +1.5dB */ - 0x285, /* 28, +2.0dB */ - 0x2AB, /* 29, +2.5dB */ - 0x2D3, /* 30, +3.0dB */ - 0x2FE, /* 31, +3.5dB */ - 0x32B, /* 32, +4.0dB */ - 0x35C, /* 33, +4.5dB */ - 0x38E, /* 34, +5.0dB */ - 0x3C4, /* 35, +5.5dB */ - 0x3FE /* 36, +6.0dB */ -}; - -static const u32 ofdmswing_table[] = { - 0x0b40002d, /* 0, -15.0dB */ - 0x0c000030, /* 1, -14.5dB */ - 0x0cc00033, /* 2, -14.0dB */ - 0x0d800036, /* 3, -13.5dB */ - 0x0e400039, /* 4, -13.0dB */ - 0x0f00003c, /* 5, -12.5dB */ - 0x10000040, /* 6, -12.0dB */ - 0x11000044, /* 7, -11.5dB */ - 0x12000048, /* 8, -11.0dB */ - 0x1300004c, /* 9, -10.5dB */ - 0x14400051, /* 10, -10.0dB */ - 0x15800056, /* 11, -9.5dB */ - 0x16c0005b, /* 12, -9.0dB */ - 0x18000060, /* 13, -8.5dB */ - 0x19800066, /* 14, -8.0dB */ - 0x1b00006c, /* 15, -7.5dB */ - 0x1c800072, /* 16, -7.0dB */ - 0x1e400079, /* 17, -6.5dB */ - 0x20000080, /* 18, -6.0dB */ - 0x22000088, /* 19, -5.5dB */ - 0x24000090, /* 20, -5.0dB */ - 0x26000098, /* 21, -4.5dB */ - 0x288000a2, /* 22, -4.0dB */ - 0x2ac000ab, /* 23, -3.5dB */ - 0x2d4000b5, /* 24, -3.0dB */ - 0x300000c0, /* 25, -2.5dB */ - 0x32c000cb, /* 26, -2.0dB */ - 0x35c000d7, /* 27, -1.5dB */ - 0x390000e4, /* 28, -1.0dB */ - 0x3c8000f2, /* 29, -0.5dB */ - 0x40000100, /* 30, +0dB */ - 0x43c0010f, /* 31, +0.5dB */ - 0x47c0011f, /* 32, +1.0dB */ - 0x4c000130, /* 33, +1.5dB */ - 0x50800142, /* 34, +2.0dB */ - 0x55400155, /* 35, +2.5dB */ - 0x5a400169, /* 36, +3.0dB */ - 0x5fc0017f, /* 37, +3.5dB */ - 0x65400195, /* 38, +4.0dB */ - 0x6b8001ae, /* 39, +4.5dB */ - 0x71c001c7, /* 40, +5.0dB */ - 0x788001e2, /* 41, +5.5dB */ - 0x7f8001fe /* 42, +6.0dB */ -}; - -static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { - {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /* 0, -16.0dB */ - {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 1, -15.5dB */ - {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 2, -15.0dB */ - {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 3, -14.5dB */ - {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 4, -14.0dB */ - {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 5, -13.5dB */ - {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 6, -13.0dB */ - {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 7, -12.5dB */ - {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 8, -12.0dB */ - {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 9, -11.5dB */ - {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */ - {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */ - {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */ - {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */ - {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */ - {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */ - {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ - {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */ - {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */ - {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */ - {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */ - {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */ - {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */ - {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */ - {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */ - {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */ - {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */ - {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */ - {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */ - {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */ - {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */ - {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */ - {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04} /* 32, +0dB */ -}; - -static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { - {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /* 0, -16.0dB */ - {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 1, -15.5dB */ - {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 2, -15.0dB */ - {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 3, -14.5dB */ - {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 4, -14.0dB */ - {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 5, -13.5dB */ - {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 6, -13.0dB */ - {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 7, -12.5dB */ - {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 8, -12.0dB */ - {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 9, -11.5dB */ - {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */ - {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */ - {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */ - {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */ - {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */ - {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */ - {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ - {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */ - {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */ - {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */ - {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */ - {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */ - {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */ - {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */ - {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */ - {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */ - {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */ - {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */ - {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */ - {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */ - {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */ - {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */ - {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00} /* 32, +0dB */ -}; - -static const u32 edca_setting_dl[PEER_MAX] = { - 0xa44f, /* 0 UNKNOWN */ - 0x5ea44f, /* 1 REALTEK_90 */ - 0x5e4322, /* 2 REALTEK_92SE */ - 0x5ea42b, /* 3 BROAD */ - 0xa44f, /* 4 RAL */ - 0xa630, /* 5 ATH */ - 0x5ea630, /* 6 CISCO */ - 0x5ea42b, /* 7 MARVELL */ -}; - -static const u32 edca_setting_ul[PEER_MAX] = { - 0x5e4322, /* 0 UNKNOWN */ - 0xa44f, /* 1 REALTEK_90 */ - 0x5ea44f, /* 2 REALTEK_92SE */ - 0x5ea32b, /* 3 BROAD */ - 0x5ea422, /* 4 RAL */ - 0x5ea322, /* 5 ATH */ - 0x3ea430, /* 6 CISCO */ - 0x5ea44f, /* 7 MARV */ -}; - -static u8 rtl8818e_delta_swing_table_idx_24gb_p[] = { - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, - 4, 4, 4, 5, 5, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9}; - -static u8 rtl8818e_delta_swing_table_idx_24gb_n[] = { - 0, 0, 0, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, - 7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11}; - -static u8 rtl8812ae_delta_swing_table_idx_24gb_n[] = { - 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, - 6, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11}; - -static u8 rtl8812ae_delta_swing_table_idx_24gb_p[] = { - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, - 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9}; - -static u8 rtl8812ae_delta_swing_table_idx_24ga_n[] = { - 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, - 6, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11}; - -static u8 rtl8812ae_delta_swing_table_idx_24ga_p[] = { - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, - 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9}; - -static u8 rtl8812ae_delta_swing_table_idx_24gcckb_n[] = { - 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, - 6, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11}; - -static u8 rtl8812ae_delta_swing_table_idx_24gcckb_p[] = { - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, - 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9}; - -static u8 rtl8812ae_delta_swing_table_idx_24gccka_n[] = { - 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, - 6, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11}; - -static u8 rtl8812ae_delta_swing_table_idx_24gccka_p[] = { - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, - 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9}; - -static u8 rtl8812ae_delta_swing_table_idx_5gb_n[][DEL_SW_IDX_SZ] = { - {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, - 7, 8, 8, 9, 9, 9, 10, 10, 11, 11, 12, 12, 13}, - {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, - 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13}, - {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, - 12, 12, 13, 14, 14, 14, 15, 16, 17, 17, 17, 18, 18, 18}, -}; - -static u8 rtl8812ae_delta_swing_table_idx_5gb_p[][DEL_SW_IDX_SZ] = { - {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, - 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11}, - {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, - 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11}, - {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9, - 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}, -}; - -static u8 rtl8812ae_delta_swing_table_idx_5ga_n[][DEL_SW_IDX_SZ] = { - {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, - 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13}, - {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, - 9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13}, - {0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, - 12, 13, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 18, 18}, -}; - -static u8 rtl8812ae_delta_swing_table_idx_5ga_p[][DEL_SW_IDX_SZ] = { - {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, 7, 8, - 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11}, - {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, - 9, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}, - {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 9, - 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}, -}; - -static u8 rtl8821ae_delta_swing_table_idx_24gb_n[] = { - 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, - 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10}; - -static u8 rtl8821ae_delta_swing_table_idx_24gb_p[] = { - 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, - 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12}; - -static u8 rtl8821ae_delta_swing_table_idx_24ga_n[] = { - 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, - 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10}; - -static u8 rtl8821ae_delta_swing_table_idx_24ga_p[] = { - 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, - 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12}; - -static u8 rtl8821ae_delta_swing_table_idx_24gcckb_n[] = { - 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, - 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10}; - -static u8 rtl8821ae_delta_swing_table_idx_24gcckb_p[] = { - 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, - 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12}; - -static u8 rtl8821ae_delta_swing_table_idx_24gccka_n[] = { - 0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, - 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10}; - -static u8 rtl8821ae_delta_swing_table_idx_24gccka_p[] = { - 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, - 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12}; - -static u8 rtl8821ae_delta_swing_table_idx_5gb_n[][DEL_SW_IDX_SZ] = { - {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, - 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, - {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, - 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, - {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, - 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, -}; - -static u8 rtl8821ae_delta_swing_table_idx_5gb_p[][DEL_SW_IDX_SZ] = { - {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, - 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, - {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, - 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, - {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, - 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, -}; - -static u8 rtl8821ae_delta_swing_table_idx_5ga_n[][DEL_SW_IDX_SZ] = { - {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, - 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, - {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, - 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, - {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, - 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, -}; - -static u8 rtl8821ae_delta_swing_table_idx_5ga_p[][DEL_SW_IDX_SZ] = { - {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, - 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, - {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, - 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, - {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, - 12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16}, -}; - -void rtl8821ae_dm_txpower_track_adjust(struct ieee80211_hw *hw, - u8 type, u8 *pdirection, - u32 *poutwrite_val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - u8 pwr_val = 0; - - if (type == 0) { - if (rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] <= - rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A]) { - *pdirection = 1; - pwr_val = rtldm->swing_idx_ofdm_base[RF90_PATH_A] - - rtldm->swing_idx_ofdm[RF90_PATH_A]; - } else { - *pdirection = 2; - pwr_val = rtldm->swing_idx_ofdm[RF90_PATH_A] - - rtldm->swing_idx_ofdm_base[RF90_PATH_A]; - } - } else if (type == 1) { - if (rtldm->swing_idx_cck <= rtldm->swing_idx_cck_base) { - *pdirection = 1; - pwr_val = rtldm->swing_idx_cck_base - - rtldm->swing_idx_cck; - } else { - *pdirection = 2; - pwr_val = rtldm->swing_idx_cck - - rtldm->swing_idx_cck_base; - } - } - - if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1)) - pwr_val = TXPWRTRACK_MAX_IDX; - - *poutwrite_val = pwr_val | (pwr_val << 8)| - (pwr_val << 16)| - (pwr_val << 24); -} - -void rtl8821ae_dm_clear_txpower_tracking_state(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtlpriv); - struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); - u8 p = 0; - - rtldm->swing_idx_cck_base = rtldm->default_cck_index; - rtldm->swing_idx_cck = rtldm->default_cck_index; - rtldm->cck_index = 0; - - for (p = RF90_PATH_A; p <= RF90_PATH_B; ++p) { - rtldm->swing_idx_ofdm_base[p] = rtldm->default_ofdm_index; - rtldm->swing_idx_ofdm[p] = rtldm->default_ofdm_index; - rtldm->ofdm_index[p] = rtldm->default_ofdm_index; - - rtldm->power_index_offset[p] = 0; - rtldm->delta_power_index[p] = 0; - rtldm->delta_power_index_last[p] = 0; - /*Initial Mix mode power tracking*/ - rtldm->absolute_ofdm_swing_idx[p] = 0; - rtldm->remnant_ofdm_swing_idx[p] = 0; - } - /*Initial at Modify Tx Scaling Mode*/ - rtldm->modify_txagc_flag_path_a = false; - /*Initial at Modify Tx Scaling Mode*/ - rtldm->modify_txagc_flag_path_b = false; - rtldm->remnant_cck_idx = 0; - rtldm->thermalvalue = rtlefuse->eeprom_thermalmeter; - rtldm->thermalvalue_iqk = rtlefuse->eeprom_thermalmeter; - rtldm->thermalvalue_lck = rtlefuse->eeprom_thermalmeter; -} - -static u8 rtl8821ae_dm_get_swing_index(struct ieee80211_hw *hw) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 i = 0; - u32 bb_swing; - - bb_swing = phy_get_tx_swing_8812A(hw, rtlhal->current_bandtype, - RF90_PATH_A); - - for (i = 0; i < TXSCALE_TABLE_SIZE; ++i) - if (bb_swing == rtl8821ae_txscaling_table[i]) - break; - - return i; -} - -void rtl8821ae_dm_initialize_txpower_tracking_thermalmeter( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtlpriv); - struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); - u8 default_swing_index = 0; - u8 p = 0; - - rtlpriv->dm.txpower_track_control = true; - rtldm->thermalvalue = rtlefuse->eeprom_thermalmeter; - rtldm->thermalvalue_iqk = rtlefuse->eeprom_thermalmeter; - rtldm->thermalvalue_lck = rtlefuse->eeprom_thermalmeter; - default_swing_index = rtl8821ae_dm_get_swing_index(hw); - - rtldm->default_ofdm_index = - (default_swing_index == TXSCALE_TABLE_SIZE) ? - 24 : default_swing_index; - rtldm->default_cck_index = 24; - - rtldm->swing_idx_cck_base = rtldm->default_cck_index; - rtldm->cck_index = rtldm->default_cck_index; - - for (p = RF90_PATH_A; p < MAX_RF_PATH; ++p) { - rtldm->swing_idx_ofdm_base[p] = - rtldm->default_ofdm_index; - rtldm->ofdm_index[p] = rtldm->default_ofdm_index; - rtldm->delta_power_index[p] = 0; - rtldm->power_index_offset[p] = 0; - rtldm->delta_power_index_last[p] = 0; - } -} - -void rtl8821ae_dm_init_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.current_turbo_edca = false; - rtlpriv->dm.is_any_nonbepkts = false; - rtlpriv->dm.is_cur_rdlstate = false; -} - -void rtl8821ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rate_adaptive *p_ra = &rtlpriv->ra; - - p_ra->ratr_state = DM_RATR_STA_INIT; - p_ra->pre_ratr_state = DM_RATR_STA_INIT; - - rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; - if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) - rtlpriv->dm.useramask = true; - else - rtlpriv->dm.useramask = false; - - p_ra->high_rssi_thresh_for_ra = 50; - p_ra->low_rssi_thresh_for_ra40m = 20; -} - -static void rtl8821ae_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap; - - rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11)); - rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL; -} - -static void rtl8821ae_dm_common_info_self_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 tmp; - - rtlphy->cck_high_power = - (bool)rtl_get_bbreg(hw, ODM_REG_CCK_RPT_FORMAT_11AC, - ODM_BIT_CCK_RPT_FORMAT_11AC); - - tmp = (u8)rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC, - ODM_BIT_BB_RX_PATH_11AC); - if (tmp & BIT(0)) - rtlpriv->dm.rfpath_rxenable[0] = true; - if (tmp & BIT(1)) - rtlpriv->dm.rfpath_rxenable[1] = true; -} - -void rtl8821ae_dm_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f); - - spin_lock(&rtlpriv->locks.iqk_lock); - rtlphy->lck_inprogress = false; - spin_unlock(&rtlpriv->locks.iqk_lock); - - rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; - rtl8821ae_dm_common_info_self_init(hw); - rtl_dm_diginit(hw, cur_igvalue); - rtl8821ae_dm_init_rate_adaptive_mask(hw); - rtl8821ae_dm_init_edca_turbo(hw); - rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(hw); - rtl8821ae_dm_init_dynamic_atc_switch(hw); -} - -static void rtl8821ae_dm_find_minimum_rssi(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable; - struct rtl_mac *mac = rtl_mac(rtlpriv); - - /* Determine the minimum RSSI */ - if ((mac->link_state < MAC80211_LINKED) && - (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { - rtl_dm_dig->min_undec_pwdb_for_dm = 0; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "Not connected to any\n"); - } - if (mac->link_state >= MAC80211_LINKED) { - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) { - rtl_dm_dig->min_undec_pwdb_for_dm = - rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "AP Client PWDB = 0x%lx\n", - rtlpriv->dm.entry_min_undec_sm_pwdb); - } else { - rtl_dm_dig->min_undec_pwdb_for_dm = - rtlpriv->dm.undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "STA Default Port PWDB = 0x%x\n", - rtl_dm_dig->min_undec_pwdb_for_dm); - } - } else { - rtl_dm_dig->min_undec_pwdb_for_dm = - rtlpriv->dm.entry_min_undec_sm_pwdb; - RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "AP Ext Port or disconnet PWDB = 0x%x\n", - rtl_dm_dig->min_undec_pwdb_for_dm); - } - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "MinUndecoratedPWDBForDM =%d\n", - rtl_dm_dig->min_undec_pwdb_for_dm); -} - -static void rtl8812ae_dm_rssi_dump_to_register(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, RA_RSSI_DUMP, - rtlpriv->stats.rx_rssi_percentage[0]); - rtl_write_byte(rtlpriv, RB_RSSI_DUMP, - rtlpriv->stats.rx_rssi_percentage[1]); - - /* Rx EVM*/ - rtl_write_byte(rtlpriv, RS1_RX_EVM_DUMP, - rtlpriv->stats.rx_evm_dbm[0]); - rtl_write_byte(rtlpriv, RS2_RX_EVM_DUMP, - rtlpriv->stats.rx_evm_dbm[1]); - - /*Rx SNR*/ - rtl_write_byte(rtlpriv, RA_RX_SNR_DUMP, - (u8)(rtlpriv->stats.rx_snr_db[0])); - rtl_write_byte(rtlpriv, RB_RX_SNR_DUMP, - (u8)(rtlpriv->stats.rx_snr_db[1])); - - /*Rx Cfo_Short*/ - rtl_write_word(rtlpriv, RA_CFO_SHORT_DUMP, - rtlpriv->stats.rx_cfo_short[0]); - rtl_write_word(rtlpriv, RB_CFO_SHORT_DUMP, - rtlpriv->stats.rx_cfo_short[1]); - - /*Rx Cfo_Tail*/ - rtl_write_word(rtlpriv, RA_CFO_LONG_DUMP, - rtlpriv->stats.rx_cfo_tail[0]); - rtl_write_word(rtlpriv, RB_CFO_LONG_DUMP, - rtlpriv->stats.rx_cfo_tail[1]); -} - -static void rtl8821ae_dm_check_rssi_monitor(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_sta_info *drv_priv; - u8 h2c_parameter[4] = { 0 }; - long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff; - u8 stbc_tx = 0; - u64 cur_txokcnt = 0, cur_rxokcnt = 0; - static u64 last_txokcnt = 0, last_rxokcnt; - - cur_txokcnt = rtlpriv->stats.txbytesunicast - last_txokcnt; - cur_rxokcnt = rtlpriv->stats.rxbytesunicast - last_rxokcnt; - last_txokcnt = rtlpriv->stats.txbytesunicast; - last_rxokcnt = rtlpriv->stats.rxbytesunicast; - if (cur_rxokcnt > (last_txokcnt * 6)) - h2c_parameter[3] = 0x01; - else - h2c_parameter[3] = 0x00; - - /* AP & ADHOC & MESH */ - if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { - if (drv_priv->rssi_stat.undec_sm_pwdb < - tmp_entry_min_pwdb) - tmp_entry_min_pwdb = - drv_priv->rssi_stat.undec_sm_pwdb; - if (drv_priv->rssi_stat.undec_sm_pwdb > - tmp_entry_max_pwdb) - tmp_entry_max_pwdb = - drv_priv->rssi_stat.undec_sm_pwdb; - } - spin_unlock_bh(&rtlpriv->locks.entry_list_lock); - - /* If associated entry is found */ - if (tmp_entry_max_pwdb != 0) { - rtlpriv->dm.entry_max_undec_sm_pwdb = - tmp_entry_max_pwdb; - RTPRINT(rtlpriv, FDM, DM_PWDB, - "EntryMaxPWDB = 0x%lx(%ld)\n", - tmp_entry_max_pwdb, tmp_entry_max_pwdb); - } else { - rtlpriv->dm.entry_max_undec_sm_pwdb = 0; - } - /* If associated entry is found */ - if (tmp_entry_min_pwdb != 0xff) { - rtlpriv->dm.entry_min_undec_sm_pwdb = - tmp_entry_min_pwdb; - RTPRINT(rtlpriv, FDM, DM_PWDB, - "EntryMinPWDB = 0x%lx(%ld)\n", - tmp_entry_min_pwdb, tmp_entry_min_pwdb); - } else { - rtlpriv->dm.entry_min_undec_sm_pwdb = 0; - } - } - /* Indicate Rx signal strength to FW. */ - if (rtlpriv->dm.useramask) { - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - if (mac->mode == WIRELESS_MODE_AC_24G || - mac->mode == WIRELESS_MODE_AC_5G || - mac->mode == WIRELESS_MODE_AC_ONLY) - stbc_tx = (mac->vht_cur_stbc & - STBC_VHT_ENABLE_TX) ? 1 : 0; - else - stbc_tx = (mac->ht_cur_stbc & - STBC_HT_ENABLE_TX) ? 1 : 0; - h2c_parameter[3] |= stbc_tx << 1; - } - h2c_parameter[2] = - (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF); - h2c_parameter[1] = 0x20; - h2c_parameter[0] = 0; - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 4, - h2c_parameter); - else - rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 3, - h2c_parameter); - } else { - rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb); - } - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_dm_rssi_dump_to_register(hw); - rtl8821ae_dm_find_minimum_rssi(hw); - dm_digtable->rssi_val_min = rtlpriv->dm_digtable.min_undec_pwdb_for_dm; -} - -void rtl8821ae_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 current_cca) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - if (dm_digtable->cur_cck_cca_thres != current_cca) - rtl_write_byte(rtlpriv, DM_REG_CCK_CCA_11AC, current_cca); - - dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres; - dm_digtable->cur_cck_cca_thres = current_cca; -} - -void rtl8821ae_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - - if (dm_digtable->stop_dig) - return; - - if (dm_digtable->cur_igvalue != current_igi) { - rtl_set_bbreg(hw, DM_REG_IGI_A_11AC, - DM_BIT_IGI_11AC, current_igi); - if (rtlpriv->phy.rf_type != RF_1T1R) - rtl_set_bbreg(hw, DM_REG_IGI_B_11AC, - DM_BIT_IGI_11AC, current_igi); - } - dm_digtable->cur_igvalue = current_igi; -} - -static void rtl8821ae_dm_dig(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 dig_min_0; - u8 dig_max_of_min; - bool first_connect, first_disconnect; - u8 dm_dig_max, dm_dig_min, offset; - u8 current_igi = dm_digtable->cur_igvalue; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "\n"); - - if (mac->act_scanning) { - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Return: In Scan Progress\n"); - return; - } - - /*add by Neil Chen to avoid PSD is processing*/ - dig_min_0 = dm_digtable->dig_min_0; - first_connect = (mac->link_state >= MAC80211_LINKED) && - (!dm_digtable->media_connect_0); - first_disconnect = (mac->link_state < MAC80211_LINKED) && - (dm_digtable->media_connect_0); - - /*1 Boundary Decision*/ - - dm_dig_max = 0x5A; - - if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE) - dm_dig_min = DM_DIG_MIN; - else - dm_dig_min = 0x1C; - - dig_max_of_min = DM_DIG_MAX_AP; - - if (mac->link_state >= MAC80211_LINKED) { - if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE) - offset = 20; - else - offset = 10; - - if ((dm_digtable->rssi_val_min + offset) > dm_dig_max) - dm_digtable->rx_gain_max = dm_dig_max; - else if ((dm_digtable->rssi_val_min + offset) < dm_dig_min) - dm_digtable->rx_gain_max = dm_dig_min; - else - dm_digtable->rx_gain_max = - dm_digtable->rssi_val_min + offset; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "dm_digtable->rssi_val_min=0x%x,dm_digtable->rx_gain_max = 0x%x", - dm_digtable->rssi_val_min, - dm_digtable->rx_gain_max); - if (rtlpriv->dm.one_entry_only) { - offset = 0; - - if (dm_digtable->rssi_val_min - offset < dm_dig_min) - dig_min_0 = dm_dig_min; - else if (dm_digtable->rssi_val_min - - offset > dig_max_of_min) - dig_min_0 = dig_max_of_min; - else - dig_min_0 = - dm_digtable->rssi_val_min - offset; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "bOneEntryOnly=TRUE, dig_min_0=0x%x\n", - dig_min_0); - } else { - dig_min_0 = dm_dig_min; - } - } else { - dm_digtable->rx_gain_max = dm_dig_max; - dig_min_0 = dm_dig_min; - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "No Link\n"); - } - - if (rtlpriv->falsealm_cnt.cnt_all > 10000) { - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Abnormally false alarm case.\n"); - - if (dm_digtable->large_fa_hit != 3) - dm_digtable->large_fa_hit++; - if (dm_digtable->forbidden_igi < current_igi) { - dm_digtable->forbidden_igi = current_igi; - dm_digtable->large_fa_hit = 1; - } - - if (dm_digtable->large_fa_hit >= 3) { - if ((dm_digtable->forbidden_igi + 1) > - dm_digtable->rx_gain_max) - dm_digtable->rx_gain_min = - dm_digtable->rx_gain_max; - else - dm_digtable->rx_gain_min = - (dm_digtable->forbidden_igi + 1); - dm_digtable->recover_cnt = 3600; - } - } else { - /*Recovery mechanism for IGI lower bound*/ - if (dm_digtable->recover_cnt != 0) { - dm_digtable->recover_cnt--; - } else { - if (dm_digtable->large_fa_hit < 3) { - if ((dm_digtable->forbidden_igi - 1) < - dig_min_0) { - dm_digtable->forbidden_igi = - dig_min_0; - dm_digtable->rx_gain_min = - dig_min_0; - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Normal Case: At Lower Bound\n"); - } else { - dm_digtable->forbidden_igi--; - dm_digtable->rx_gain_min = - (dm_digtable->forbidden_igi + 1); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Normal Case: Approach Lower Bound\n"); - } - } else { - dm_digtable->large_fa_hit = 0; - } - } - } - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "pDM_DigTable->LargeFAHit=%d\n", - dm_digtable->large_fa_hit); - - if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10) - dm_digtable->rx_gain_min = dm_dig_min; - - if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max) - dm_digtable->rx_gain_min = dm_digtable->rx_gain_max; - - /*Adjust initial gain by false alarm*/ - if (mac->link_state >= MAC80211_LINKED) { - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "DIG AfterLink\n"); - if (first_connect) { - if (dm_digtable->rssi_val_min <= dig_max_of_min) - current_igi = dm_digtable->rssi_val_min; - else - current_igi = dig_max_of_min; - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "First Connect\n"); - } else { - if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2) - current_igi = current_igi + 4; - else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1) - current_igi = current_igi + 2; - else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) - current_igi = current_igi - 2; - - if ((rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10) && - (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)) { - current_igi = dm_digtable->rx_gain_min; - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Beacon is less than 10 and FA is less than 768, IGI GOES TO 0x1E!!!!!!!!!!!!\n"); - } - } - } else { - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "DIG BeforeLink\n"); - if (first_disconnect) { - current_igi = dm_digtable->rx_gain_min; - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "First DisConnect\n"); - } else { - /* 2012.03.30 LukeLee: enable DIG before - * link but with very high thresholds - */ - if (rtlpriv->falsealm_cnt.cnt_all > 2000) - current_igi = current_igi + 4; - else if (rtlpriv->falsealm_cnt.cnt_all > 600) - current_igi = current_igi + 2; - else if (rtlpriv->falsealm_cnt.cnt_all < 300) - current_igi = current_igi - 2; - - if (current_igi >= 0x3e) - current_igi = 0x3e; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "England DIG\n"); - } - } - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "DIG End Adjust IGI\n"); - /* Check initial gain by upper/lower bound*/ - - if (current_igi > dm_digtable->rx_gain_max) - current_igi = dm_digtable->rx_gain_max; - if (current_igi < dm_digtable->rx_gain_min) - current_igi = dm_digtable->rx_gain_min; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "rx_gain_max=0x%x, rx_gain_min=0x%x\n", - dm_digtable->rx_gain_max, dm_digtable->rx_gain_min); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "TotalFA=%d\n", rtlpriv->falsealm_cnt.cnt_all); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "CurIGValue=0x%x\n", current_igi); - - rtl8821ae_dm_write_dig(hw, current_igi); - dm_digtable->media_connect_0 = - ((mac->link_state >= MAC80211_LINKED) ? true : false); - dm_digtable->dig_min_0 = dig_min_0; -} - -static void rtl8821ae_dm_common_info_self_update(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 cnt = 0; - struct rtl_sta_info *drv_priv; - - rtlpriv->dm.tx_rate = 0xff; - - rtlpriv->dm.one_entry_only = false; - - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION && - rtlpriv->mac80211.link_state >= MAC80211_LINKED) { - rtlpriv->dm.one_entry_only = true; - return; - } - - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || - rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC || - rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) { - spin_lock_bh(&rtlpriv->locks.entry_list_lock); - list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) - cnt++; - spin_unlock_bh(&rtlpriv->locks.entry_list_lock); - - if (cnt == 1) - rtlpriv->dm.one_entry_only = true; - } -} - -static void rtl8821ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt; - u32 cck_enable = 0; - - /*read OFDM FA counter*/ - falsealm_cnt->cnt_ofdm_fail = - rtl_get_bbreg(hw, ODM_REG_OFDM_FA_11AC, BMASKLWORD); - falsealm_cnt->cnt_cck_fail = - rtl_get_bbreg(hw, ODM_REG_CCK_FA_11AC, BMASKLWORD); - - cck_enable = rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC, BIT(28)); - if (cck_enable) /*if(pDM_Odm->pBandType == ODM_BAND_2_4G)*/ - falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail + - falsealm_cnt->cnt_cck_fail; - else - falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail; - - /*reset OFDM FA coutner*/ - rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1); - rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0); - /* reset CCK FA counter*/ - rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 0); - rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 1); - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "Cnt_Cck_fail=%d\n", - falsealm_cnt->cnt_cck_fail); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "cnt_ofdm_fail=%d\n", - falsealm_cnt->cnt_ofdm_fail); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "Total False Alarm=%d\n", - falsealm_cnt->cnt_all); -} - -static void rtl8812ae_dm_check_txpower_tracking_thermalmeter( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (!rtlpriv->dm.tm_trigger) { - rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, - BIT(17) | BIT(16), 0x03); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Trigger 8812 Thermal Meter!!\n"); - rtlpriv->dm.tm_trigger = 1; - return; - } - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Schedule TxPowerTracking direct call!!\n"); - rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw); -} - -static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (mac->link_state >= MAC80211_LINKED) { - if (rtldm->linked_interval < 3) - rtldm->linked_interval++; - - if (rtldm->linked_interval == 2) { - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_phy_iq_calibrate(hw, false); - else - rtl8821ae_phy_iq_calibrate(hw, false); - } - } else { - rtldm->linked_interval = 0; - } -} - -static void rtl8812ae_get_delta_swing_table(struct ieee80211_hw *hw, - u8 **up_a, u8 **down_a, - u8 **up_b, u8 **down_b) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - u8 channel = rtlphy->current_channel; - u8 rate = rtldm->tx_rate; - - if (1 <= channel && channel <= 14) { - if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) { - *up_a = rtl8812ae_delta_swing_table_idx_24gccka_p; - *down_a = rtl8812ae_delta_swing_table_idx_24gccka_n; - *up_b = rtl8812ae_delta_swing_table_idx_24gcckb_p; - *down_b = rtl8812ae_delta_swing_table_idx_24gcckb_n; - } else { - *up_a = rtl8812ae_delta_swing_table_idx_24ga_p; - *down_a = rtl8812ae_delta_swing_table_idx_24ga_n; - *up_b = rtl8812ae_delta_swing_table_idx_24gb_p; - *down_b = rtl8812ae_delta_swing_table_idx_24gb_n; - } - } else if (36 <= channel && channel <= 64) { - *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[0]; - *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[0]; - *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[0]; - *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[0]; - } else if (100 <= channel && channel <= 140) { - *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[1]; - *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[1]; - *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[1]; - *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[1]; - } else if (149 <= channel && channel <= 173) { - *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[2]; - *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[2]; - *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[2]; - *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[2]; - } else { - *up_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p; - *down_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n; - *up_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p; - *down_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n; - } -} - -void rtl8821ae_dm_update_init_rate(struct ieee80211_hw *hw, u8 rate) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 p = 0; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Get C2H Command! Rate=0x%x\n", rate); - - rtldm->tx_rate = rate; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - rtl8821ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, RF90_PATH_A, 0); - } else { - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) - rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, p, 0); - } -} - -u8 rtl8821ae_hw_rate_to_mrate(struct ieee80211_hw *hw, u8 rate) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 ret_rate = MGN_1M; - - switch (rate) { - case DESC_RATE1M: - ret_rate = MGN_1M; - break; - case DESC_RATE2M: - ret_rate = MGN_2M; - break; - case DESC_RATE5_5M: - ret_rate = MGN_5_5M; - break; - case DESC_RATE11M: - ret_rate = MGN_11M; - break; - case DESC_RATE6M: - ret_rate = MGN_6M; - break; - case DESC_RATE9M: - ret_rate = MGN_9M; - break; - case DESC_RATE12M: - ret_rate = MGN_12M; - break; - case DESC_RATE18M: - ret_rate = MGN_18M; - break; - case DESC_RATE24M: - ret_rate = MGN_24M; - break; - case DESC_RATE36M: - ret_rate = MGN_36M; - break; - case DESC_RATE48M: - ret_rate = MGN_48M; - break; - case DESC_RATE54M: - ret_rate = MGN_54M; - break; - case DESC_RATEMCS0: - ret_rate = MGN_MCS0; - break; - case DESC_RATEMCS1: - ret_rate = MGN_MCS1; - break; - case DESC_RATEMCS2: - ret_rate = MGN_MCS2; - break; - case DESC_RATEMCS3: - ret_rate = MGN_MCS3; - break; - case DESC_RATEMCS4: - ret_rate = MGN_MCS4; - break; - case DESC_RATEMCS5: - ret_rate = MGN_MCS5; - break; - case DESC_RATEMCS6: - ret_rate = MGN_MCS6; - break; - case DESC_RATEMCS7: - ret_rate = MGN_MCS7; - break; - case DESC_RATEMCS8: - ret_rate = MGN_MCS8; - break; - case DESC_RATEMCS9: - ret_rate = MGN_MCS9; - break; - case DESC_RATEMCS10: - ret_rate = MGN_MCS10; - break; - case DESC_RATEMCS11: - ret_rate = MGN_MCS11; - break; - case DESC_RATEMCS12: - ret_rate = MGN_MCS12; - break; - case DESC_RATEMCS13: - ret_rate = MGN_MCS13; - break; - case DESC_RATEMCS14: - ret_rate = MGN_MCS14; - break; - case DESC_RATEMCS15: - ret_rate = MGN_MCS15; - break; - case DESC_RATEVHT1SS_MCS0: - ret_rate = MGN_VHT1SS_MCS0; - break; - case DESC_RATEVHT1SS_MCS1: - ret_rate = MGN_VHT1SS_MCS1; - break; - case DESC_RATEVHT1SS_MCS2: - ret_rate = MGN_VHT1SS_MCS2; - break; - case DESC_RATEVHT1SS_MCS3: - ret_rate = MGN_VHT1SS_MCS3; - break; - case DESC_RATEVHT1SS_MCS4: - ret_rate = MGN_VHT1SS_MCS4; - break; - case DESC_RATEVHT1SS_MCS5: - ret_rate = MGN_VHT1SS_MCS5; - break; - case DESC_RATEVHT1SS_MCS6: - ret_rate = MGN_VHT1SS_MCS6; - break; - case DESC_RATEVHT1SS_MCS7: - ret_rate = MGN_VHT1SS_MCS7; - break; - case DESC_RATEVHT1SS_MCS8: - ret_rate = MGN_VHT1SS_MCS8; - break; - case DESC_RATEVHT1SS_MCS9: - ret_rate = MGN_VHT1SS_MCS9; - break; - case DESC_RATEVHT2SS_MCS0: - ret_rate = MGN_VHT2SS_MCS0; - break; - case DESC_RATEVHT2SS_MCS1: - ret_rate = MGN_VHT2SS_MCS1; - break; - case DESC_RATEVHT2SS_MCS2: - ret_rate = MGN_VHT2SS_MCS2; - break; - case DESC_RATEVHT2SS_MCS3: - ret_rate = MGN_VHT2SS_MCS3; - break; - case DESC_RATEVHT2SS_MCS4: - ret_rate = MGN_VHT2SS_MCS4; - break; - case DESC_RATEVHT2SS_MCS5: - ret_rate = MGN_VHT2SS_MCS5; - break; - case DESC_RATEVHT2SS_MCS6: - ret_rate = MGN_VHT2SS_MCS6; - break; - case DESC_RATEVHT2SS_MCS7: - ret_rate = MGN_VHT2SS_MCS7; - break; - case DESC_RATEVHT2SS_MCS8: - ret_rate = MGN_VHT2SS_MCS8; - break; - case DESC_RATEVHT2SS_MCS9: - ret_rate = MGN_VHT2SS_MCS9; - break; - default: - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "HwRateToMRate8812(): Non supported Rate [%x]!!!\n", - rate); - break; - } - return ret_rate; -} - -/*----------------------------------------------------------------------------- - * Function: odm_TxPwrTrackSetPwr88E() - * - * Overview: 88E change all channel tx power accordign to flag. - * OFDM & CCK are all different. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 04/23/2012 MHC Create Version 0. - * - *--------------------------------------------------------------------------- - */ -void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw, - enum pwr_track_control_method method, - u8 rf_path, u8 channel_mapped_index) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 final_swing_idx[2]; - u8 pwr_tracking_limit = 26; /*+1.0dB*/ - u8 tx_rate = 0xFF; - char final_ofdm_swing_index = 0; - - if (rtldm->tx_rate != 0xFF) - tx_rate = - rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "===>rtl8812ae_dm_txpwr_track_set_pwr\n"); - /*20130429 Mimic Modify High Rate BBSwing Limit.*/ - if (tx_rate != 0xFF) { - /*CCK*/ - if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M)) - pwr_tracking_limit = 32; /*+4dB*/ - /*OFDM*/ - else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M)) - pwr_tracking_limit = 30; /*+3dB*/ - else if (tx_rate == MGN_54M) - pwr_tracking_limit = 28; /*+2dB*/ - /*HT*/ - /*QPSK/BPSK*/ - else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2)) - pwr_tracking_limit = 34; /*+5dB*/ - /*16QAM*/ - else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4)) - pwr_tracking_limit = 30; /*+3dB*/ - /*64QAM*/ - else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7)) - pwr_tracking_limit = 28; /*+2dB*/ - /*QPSK/BPSK*/ - else if ((tx_rate >= MGN_MCS8) && (tx_rate <= MGN_MCS10)) - pwr_tracking_limit = 34; /*+5dB*/ - /*16QAM*/ - else if ((tx_rate >= MGN_MCS11) && (tx_rate <= MGN_MCS12)) - pwr_tracking_limit = 30; /*+3dB*/ - /*64QAM*/ - else if ((tx_rate >= MGN_MCS13) && (tx_rate <= MGN_MCS15)) - pwr_tracking_limit = 28; /*+2dB*/ - - /*2 VHT*/ - /*QPSK/BPSK*/ - else if ((tx_rate >= MGN_VHT1SS_MCS0) && - (tx_rate <= MGN_VHT1SS_MCS2)) - pwr_tracking_limit = 34; /*+5dB*/ - /*16QAM*/ - else if ((tx_rate >= MGN_VHT1SS_MCS3) && - (tx_rate <= MGN_VHT1SS_MCS4)) - pwr_tracking_limit = 30; /*+3dB*/ - /*64QAM*/ - else if ((tx_rate >= MGN_VHT1SS_MCS5) && - (tx_rate <= MGN_VHT1SS_MCS6)) - pwr_tracking_limit = 28; /*+2dB*/ - else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/ - pwr_tracking_limit = 26; /*+1dB*/ - else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/ - pwr_tracking_limit = 24; /*+0dB*/ - else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/ - pwr_tracking_limit = 22; /*-1dB*/ - /*QPSK/BPSK*/ - else if ((tx_rate >= MGN_VHT2SS_MCS0) && - (tx_rate <= MGN_VHT2SS_MCS2)) - pwr_tracking_limit = 34; /*+5dB*/ - /*16QAM*/ - else if ((tx_rate >= MGN_VHT2SS_MCS3) && - (tx_rate <= MGN_VHT2SS_MCS4)) - pwr_tracking_limit = 30; /*+3dB*/ - /*64QAM*/ - else if ((tx_rate >= MGN_VHT2SS_MCS5) && - (tx_rate <= MGN_VHT2SS_MCS6)) - pwr_tracking_limit = 28; /*+2dB*/ - else if (tx_rate == MGN_VHT2SS_MCS7) /*64QAM*/ - pwr_tracking_limit = 26; /*+1dB*/ - else if (tx_rate == MGN_VHT2SS_MCS8) /*256QAM*/ - pwr_tracking_limit = 24; /*+0dB*/ - else if (tx_rate == MGN_VHT2SS_MCS9) /*256QAM*/ - pwr_tracking_limit = 22; /*-1dB*/ - else - pwr_tracking_limit = 24; - } - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "TxRate=0x%x, PwrTrackingLimit=%d\n", - tx_rate, pwr_tracking_limit); - - if (method == BBSWING) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "===>rtl8812ae_dm_txpwr_track_set_pwr\n"); - - if (rf_path == RF90_PATH_A) { - u32 tmp; - - final_swing_idx[RF90_PATH_A] = - (rtldm->ofdm_index[RF90_PATH_A] > - pwr_tracking_limit) ? - pwr_tracking_limit : - rtldm->ofdm_index[RF90_PATH_A]; - tmp = final_swing_idx[RF90_PATH_A]; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n", - rtldm->ofdm_index[RF90_PATH_A], - final_swing_idx[RF90_PATH_A]); - - rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, - txscaling_tbl[tmp]); - } else { - u32 tmp; - - final_swing_idx[RF90_PATH_B] = - rtldm->ofdm_index[RF90_PATH_B] > - pwr_tracking_limit ? - pwr_tracking_limit : - rtldm->ofdm_index[RF90_PATH_B]; - tmp = final_swing_idx[RF90_PATH_B]; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_B]=%d, pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_B]=%d\n", - rtldm->ofdm_index[RF90_PATH_B], - final_swing_idx[RF90_PATH_B]); - - rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000, - txscaling_tbl[tmp]); - } - } else if (method == MIX_MODE) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pDM_Odm->DefaultOfdmIndex=%d, pDM_Odm->Aboslute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n", - rtldm->default_ofdm_index, - rtldm->absolute_ofdm_swing_idx[rf_path], - rf_path); - - final_ofdm_swing_index = rtldm->default_ofdm_index + - rtldm->absolute_ofdm_swing_idx[rf_path]; - - if (rf_path == RF90_PATH_A) { - /*BBSwing higher then Limit*/ - if (final_ofdm_swing_index > pwr_tracking_limit) { - rtldm->remnant_cck_idx = - final_ofdm_swing_index - - pwr_tracking_limit; - /* CCK Follow the same compensation value - * as Path A - */ - rtldm->remnant_ofdm_swing_idx[rf_path] = - final_ofdm_swing_index - - pwr_tracking_limit; - - rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, - txscaling_tbl[pwr_tracking_limit]); - - rtldm->modify_txagc_flag_path_a = true; - - /*Set TxAGC Page C{};*/ - rtl8821ae_phy_set_txpower_level_by_path(hw, - rtlphy->current_channel, - RF90_PATH_A); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Path_A Over BBSwing Limit ,PwrTrackingLimit = %d ,Remnant TxAGC Value = %d\n", - pwr_tracking_limit, - rtldm->remnant_ofdm_swing_idx[rf_path]); - } else if (final_ofdm_swing_index < 0) { - rtldm->remnant_cck_idx = final_ofdm_swing_index; - /* CCK Follow the same compensate value as Path A*/ - rtldm->remnant_ofdm_swing_idx[rf_path] = - final_ofdm_swing_index; - - rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, - txscaling_tbl[0]); - - rtldm->modify_txagc_flag_path_a = true; - - /*Set TxAGC Page C{};*/ - rtl8821ae_phy_set_txpower_level_by_path(hw, - rtlphy->current_channel, RF90_PATH_A); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Path_A Lower then BBSwing lower bound 0 , Remnant TxAGC Value = %d\n", - rtldm->remnant_ofdm_swing_idx[rf_path]); - } else { - rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, - txscaling_tbl[(u8)final_ofdm_swing_index]); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Path_A Compensate with BBSwing, Final_OFDM_Swing_Index = %d\n", - final_ofdm_swing_index); - /*If TxAGC has changed, reset TxAGC again*/ - if (rtldm->modify_txagc_flag_path_a) { - rtldm->remnant_cck_idx = 0; - rtldm->remnant_ofdm_swing_idx[rf_path] = 0; - - /*Set TxAGC Page C{};*/ - rtl8821ae_phy_set_txpower_level_by_path(hw, - rtlphy->current_channel, RF90_PATH_A); - rtldm->modify_txagc_flag_path_a = false; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, - DBG_LOUD, - "******Path_A pDM_Odm->Modify_TxAGC_Flag = FALSE\n"); - } - } - } - /*BBSwing higher then Limit*/ - if (rf_path == RF90_PATH_B) { - if (final_ofdm_swing_index > pwr_tracking_limit) { - rtldm->remnant_ofdm_swing_idx[rf_path] = - final_ofdm_swing_index - - pwr_tracking_limit; - - rtl_set_bbreg(hw, RB_TXSCALE, - 0xFFE00000, - txscaling_tbl[pwr_tracking_limit]); - - rtldm->modify_txagc_flag_path_b = true; - - /*Set TxAGC Page E{};*/ - rtl8821ae_phy_set_txpower_level_by_path(hw, - rtlphy->current_channel, RF90_PATH_B); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Path_B Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n", - pwr_tracking_limit, - rtldm->remnant_ofdm_swing_idx[rf_path]); - } else if (final_ofdm_swing_index < 0) { - rtldm->remnant_ofdm_swing_idx[rf_path] = - final_ofdm_swing_index; - - rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000, - txscaling_tbl[0]); - - rtldm->modify_txagc_flag_path_b = true; - - /*Set TxAGC Page E{};*/ - rtl8821ae_phy_set_txpower_level_by_path(hw, - rtlphy->current_channel, RF90_PATH_B); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Path_B Lower then BBSwing lower bound 0 , Remnant TxAGC Value = %d\n", - rtldm->remnant_ofdm_swing_idx[rf_path]); - } else { - rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000, - txscaling_tbl[(u8)final_ofdm_swing_index]); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Path_B Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n", - final_ofdm_swing_index); - /*If TxAGC has changed, reset TxAGC again*/ - if (rtldm->modify_txagc_flag_path_b) { - rtldm->remnant_ofdm_swing_idx[rf_path] = 0; - - /*Set TxAGC Page E{};*/ - rtl8821ae_phy_set_txpower_level_by_path(hw, - rtlphy->current_channel, RF90_PATH_B); - - rtldm->modify_txagc_flag_path_b = - false; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE\n"); - } - } - } - } else { - return; - } -} - -void rtl8812ae_dm_txpower_tracking_callback_thermalmeter( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0; - u8 thermal_value_avg_count = 0; - u32 thermal_value_avg = 0; - /* OFDM BB Swing should be less than +3.0dB, */ - u8 ofdm_min_index = 6; - /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/ - u8 index_for_channel = 0; - /* 1. The following TWO tables decide - * the final index of OFDM/CCK swing table. - */ - u8 *delta_swing_table_idx_tup_a; - u8 *delta_swing_table_idx_tdown_a; - u8 *delta_swing_table_idx_tup_b; - u8 *delta_swing_table_idx_tdown_b; - - /*2. Initilization ( 7 steps in total )*/ - rtl8812ae_get_delta_swing_table(hw, - (u8 **)&delta_swing_table_idx_tup_a, - (u8 **)&delta_swing_table_idx_tdown_a, - (u8 **)&delta_swing_table_idx_tup_b, - (u8 **)&delta_swing_table_idx_tdown_b); - - rtldm->txpower_trackinginit = true; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pDM_Odm->BbSwingIdxCckBase: %d, pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n", - rtldm->swing_idx_cck_base, - rtldm->swing_idx_ofdm_base[RF90_PATH_A], - rtldm->default_ofdm_index); - - thermal_value = (u8)rtl_get_rfreg(hw, RF90_PATH_A, - /*0x42: RF Reg[15:10] 88E*/ - RF_T_METER_8812A, 0xfc00); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n", - thermal_value, rtlefuse->eeprom_thermalmeter); - if (!rtldm->txpower_track_control || - rtlefuse->eeprom_thermalmeter == 0 || - rtlefuse->eeprom_thermalmeter == 0xFF) - return; - - /* 3. Initialize ThermalValues of RFCalibrateInfo*/ - - if (rtlhal->reloadtxpowerindex) - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "reload ofdm index for band switch\n"); - - /*4. Calculate average thermal meter*/ - rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value; - rtldm->thermalvalue_avg_index++; - if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A) - /*Average times = c.AverageThermalNum*/ - rtldm->thermalvalue_avg_index = 0; - - for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) { - if (rtldm->thermalvalue_avg[i]) { - thermal_value_avg += rtldm->thermalvalue_avg[i]; - thermal_value_avg_count++; - } - } - /*Calculate Average ThermalValue after average enough times*/ - if (thermal_value_avg_count) { - thermal_value = (u8)(thermal_value_avg / - thermal_value_avg_count); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n", - thermal_value, rtlefuse->eeprom_thermalmeter); - } - - /*5. Calculate delta, delta_LCK, delta_IQK. - *"delta" here is used to determine whether - *thermal value changes or not. - */ - delta = (thermal_value > rtldm->thermalvalue) ? - (thermal_value - rtldm->thermalvalue) : - (rtldm->thermalvalue - thermal_value); - delta_lck = (thermal_value > rtldm->thermalvalue_lck) ? - (thermal_value - rtldm->thermalvalue_lck) : - (rtldm->thermalvalue_lck - thermal_value); - delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ? - (thermal_value - rtldm->thermalvalue_iqk) : - (rtldm->thermalvalue_iqk - thermal_value); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n", - delta, delta_lck, delta_iqk); - - /* 6. If necessary, do LCK. - * Delta temperature is equal to or larger than 20 centigrade. - */ - if (delta_lck >= IQK_THRESHOLD) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "delta_LCK(%d) >= Threshold_IQK(%d)\n", - delta_lck, IQK_THRESHOLD); - rtldm->thermalvalue_lck = thermal_value; - rtl8821ae_phy_lc_calibrate(hw); - } - - /*7. If necessary, move the index of swing table to adjust Tx power.*/ - - if (delta > 0 && rtldm->txpower_track_control) { - /* "delta" here is used to record the - * absolute value of differrence. - */ - delta = thermal_value > rtlefuse->eeprom_thermalmeter ? - (thermal_value - rtlefuse->eeprom_thermalmeter) : - (rtlefuse->eeprom_thermalmeter - thermal_value); - - if (delta >= TXPWR_TRACK_TABLE_SIZE) - delta = TXPWR_TRACK_TABLE_SIZE - 1; - - /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/ - - if (thermal_value > rtlefuse->eeprom_thermalmeter) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "delta_swing_table_idx_tup_a[%d] = %d\n", - delta, delta_swing_table_idx_tup_a[delta]); - rtldm->delta_power_index_last[RF90_PATH_A] = - rtldm->delta_power_index[RF90_PATH_A]; - rtldm->delta_power_index[RF90_PATH_A] = - delta_swing_table_idx_tup_a[delta]; - - rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] = - delta_swing_table_idx_tup_a[delta]; - /*Record delta swing for mix mode power tracking*/ - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", - rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "delta_swing_table_idx_tup_b[%d] = %d\n", - delta, delta_swing_table_idx_tup_b[delta]); - rtldm->delta_power_index_last[RF90_PATH_B] = - rtldm->delta_power_index[RF90_PATH_B]; - rtldm->delta_power_index[RF90_PATH_B] = - delta_swing_table_idx_tup_b[delta]; - - rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] = - delta_swing_table_idx_tup_b[delta]; - /*Record delta swing for mix mode power tracking*/ - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", - rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]); - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "delta_swing_table_idx_tdown_a[%d] = %d\n", - delta, delta_swing_table_idx_tdown_a[delta]); - - rtldm->delta_power_index_last[RF90_PATH_A] = - rtldm->delta_power_index[RF90_PATH_A]; - rtldm->delta_power_index[RF90_PATH_A] = - -1 * delta_swing_table_idx_tdown_a[delta]; - - rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] = - -1 * delta_swing_table_idx_tdown_a[delta]; - /* Record delta swing for mix mode power tracking*/ - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", - rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "deltaSwingTableIdx_TDOWN_B[%d] = %d\n", - delta, delta_swing_table_idx_tdown_b[delta]); - - rtldm->delta_power_index_last[RF90_PATH_B] = - rtldm->delta_power_index[RF90_PATH_B]; - rtldm->delta_power_index[RF90_PATH_B] = - -1 * delta_swing_table_idx_tdown_b[delta]; - - rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] = - -1 * delta_swing_table_idx_tdown_b[delta]; - /*Record delta swing for mix mode power tracking*/ - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", - rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]); - } - - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "============================= [Path-%c]Calculating PowerIndexOffset =============================\n", - (p == RF90_PATH_A ? 'A' : 'B')); - - if (rtldm->delta_power_index[p] == - rtldm->delta_power_index_last[p]) - /*If Thermal value changes but lookup - table value still the same*/ - rtldm->power_index_offset[p] = 0; - else - rtldm->power_index_offset[p] = - rtldm->delta_power_index[p] - - rtldm->delta_power_index_last[p]; - /* Power Index Diff between 2 - * times Power Tracking - */ - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "[Path-%c] PowerIndexOffset(%d) =DeltaPowerIndex(%d) -DeltaPowerIndexLast(%d)\n", - (p == RF90_PATH_A ? 'A' : 'B'), - rtldm->power_index_offset[p], - rtldm->delta_power_index[p] , - rtldm->delta_power_index_last[p]); - - rtldm->ofdm_index[p] = - rtldm->swing_idx_ofdm_base[p] + - rtldm->power_index_offset[p]; - rtldm->cck_index = - rtldm->swing_idx_cck_base + - rtldm->power_index_offset[p]; - - rtldm->swing_idx_cck = rtldm->cck_index; - rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p]; - - /****Print BB Swing Base and Index Offset */ - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n", - rtldm->swing_idx_cck, - rtldm->swing_idx_cck_base, - rtldm->power_index_offset[p]); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n", - rtldm->swing_idx_ofdm[p], - (p == RF90_PATH_A ? 'A' : 'B'), - rtldm->swing_idx_ofdm_base[p], - rtldm->power_index_offset[p]); - - /*7.1 Handle boundary conditions of index.*/ - - if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1) - rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1; - else if (rtldm->ofdm_index[p] < ofdm_min_index) - rtldm->ofdm_index[p] = ofdm_min_index; - } - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "\n\n====================================================================================\n"); - if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1) - rtldm->cck_index = TXSCALE_TABLE_SIZE - 1; - else if (rtldm->cck_index < 0) - rtldm->cck_index = 0; - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "The thermal meter is unchanged or TxPowerTracking OFF(%d): ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n", - rtldm->txpower_track_control, - thermal_value, - rtldm->thermalvalue); - - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) - rtldm->power_index_offset[p] = 0; - } - /*Print Swing base & current*/ - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "TxPowerTracking: [CCK] Swing Current Index: %d,Swing Base Index: %d\n", - rtldm->cck_index, rtldm->swing_idx_cck_base); - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "TxPowerTracking: [OFDM] Swing Current Index: %d,Swing Base Index[%c]: %d\n", - rtldm->ofdm_index[p], - (p == RF90_PATH_A ? 'A' : 'B'), - rtldm->swing_idx_ofdm_base[p]); - } - - if ((rtldm->power_index_offset[RF90_PATH_A] != 0 || - rtldm->power_index_offset[RF90_PATH_B] != 0) && - rtldm->txpower_track_control) { - /*7.2 Configure the Swing Table to adjust Tx Power. - *Always TRUE after Tx Power is adjusted by power tracking. - * - *2012/04/23 MH According to Luke's suggestion, - *we can not write BB digital - *to increase TX power. Otherwise, EVM will be bad. - * - *2012/04/25 MH Add for tx power tracking to set - *tx power in tx agc for 88E. - */ - if (thermal_value > rtldm->thermalvalue) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Temperature Increasing(A): delta_pi: %d , delta_t: %d, Now_t: %d,EFUSE_t: %d, Last_t: %d\n", - rtldm->power_index_offset[RF90_PATH_A], - delta, thermal_value, - rtlefuse->eeprom_thermalmeter, - rtldm->thermalvalue); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Temperature Increasing(B): delta_pi: %d ,delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", - rtldm->power_index_offset[RF90_PATH_B], - delta, thermal_value, - rtlefuse->eeprom_thermalmeter, - rtldm->thermalvalue); - } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/ - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", - rtldm->power_index_offset[RF90_PATH_A], - delta, thermal_value, - rtlefuse->eeprom_thermalmeter, - rtldm->thermalvalue); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Temperature Decreasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", - rtldm->power_index_offset[RF90_PATH_B], - delta, thermal_value, - rtlefuse->eeprom_thermalmeter, - rtldm->thermalvalue); - } - - if (thermal_value > rtlefuse->eeprom_thermalmeter) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Temperature(%d) higher than PG value(%d)\n", - thermal_value, rtlefuse->eeprom_thermalmeter); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "**********Enter POWER Tracking MIX_MODE**********\n"); - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) - rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, - p, 0); - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Temperature(%d) lower than PG value(%d)\n", - thermal_value, rtlefuse->eeprom_thermalmeter); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "**********Enter POWER Tracking MIX_MODE**********\n"); - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) - rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, - p, index_for_channel); - } - /*Record last time Power Tracking result as base.*/ - rtldm->swing_idx_cck_base = rtldm->swing_idx_cck; - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) - rtldm->swing_idx_ofdm_base[p] = - rtldm->swing_idx_ofdm[p]; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pDM_Odm->RFCalibrateInfo.ThermalValue =%d ThermalValue= %d\n", - rtldm->thermalvalue, thermal_value); - /*Record last Power Tracking Thermal Value*/ - rtldm->thermalvalue = thermal_value; - } - /*Delta temperature is equal to or larger than - 20 centigrade (When threshold is 8).*/ - if (delta_iqk >= IQK_THRESHOLD) - rtl8812ae_do_iqk(hw, delta_iqk, thermal_value, 8); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "<===rtl8812ae_dm_txpower_tracking_callback_thermalmeter\n"); -} - -static void rtl8821ae_get_delta_swing_table(struct ieee80211_hw *hw, u8 **up_a, - u8 **down_a, u8 **up_b, u8 **down_b) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - u8 channel = rtlphy->current_channel; - u8 rate = rtldm->tx_rate; - - if (1 <= channel && channel <= 14) { - if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) { - *up_a = rtl8821ae_delta_swing_table_idx_24gccka_p; - *down_a = rtl8821ae_delta_swing_table_idx_24gccka_n; - *up_b = rtl8821ae_delta_swing_table_idx_24gcckb_p; - *down_b = rtl8821ae_delta_swing_table_idx_24gcckb_n; - } else { - *up_a = rtl8821ae_delta_swing_table_idx_24ga_p; - *down_a = rtl8821ae_delta_swing_table_idx_24ga_n; - *up_b = rtl8821ae_delta_swing_table_idx_24gb_p; - *down_b = rtl8821ae_delta_swing_table_idx_24gb_n; - } - } else if (36 <= channel && channel <= 64) { - *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[0]; - *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[0]; - *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[0]; - *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[0]; - } else if (100 <= channel && channel <= 140) { - *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[1]; - *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[1]; - *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[1]; - *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[1]; - } else if (149 <= channel && channel <= 173) { - *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[2]; - *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[2]; - *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[2]; - *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[2]; - } else { - *up_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p; - *down_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n; - *up_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p; - *down_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n; - } - return; -} - -/*----------------------------------------------------------------------------- - * Function: odm_TxPwrTrackSetPwr88E() - * - * Overview: 88E change all channel tx power accordign to flag. - * OFDM & CCK are all different. - * - * Input: NONE - * - * Output: NONE - * - * Return: NONE - * - * Revised History: - * When Who Remark - * 04/23/2012 MHC Create Version 0. - * - *--------------------------------------------------------------------------- - */ -void rtl8821ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw, - enum pwr_track_control_method method, - u8 rf_path, u8 channel_mapped_index) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 final_swing_idx[1]; - u8 pwr_tracking_limit = 26; /*+1.0dB*/ - u8 tx_rate = 0xFF; - char final_ofdm_swing_index = 0; - - if (rtldm->tx_rate != 0xFF) - tx_rate = rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "===>%s\n", __func__); - - if (tx_rate != 0xFF) { /* Mimic Modify High Rate BBSwing Limit.*/ - /*CCK*/ - if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M)) - pwr_tracking_limit = 32; /*+4dB*/ - /*OFDM*/ - else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M)) - pwr_tracking_limit = 30; /*+3dB*/ - else if (tx_rate == MGN_54M) - pwr_tracking_limit = 28; /*+2dB*/ - /*HT*/ - /*QPSK/BPSK*/ - else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2)) - pwr_tracking_limit = 34; /*+5dB*/ - /*16QAM*/ - else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4)) - pwr_tracking_limit = 30; /*+3dB*/ - /*64QAM*/ - else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7)) - pwr_tracking_limit = 28; /*+2dB*/ - /*2 VHT*/ - /*QPSK/BPSK*/ - else if ((tx_rate >= MGN_VHT1SS_MCS0) && - (tx_rate <= MGN_VHT1SS_MCS2)) - pwr_tracking_limit = 34; /*+5dB*/ - /*16QAM*/ - else if ((tx_rate >= MGN_VHT1SS_MCS3) && - (tx_rate <= MGN_VHT1SS_MCS4)) - pwr_tracking_limit = 30; /*+3dB*/ - /*64QAM*/ - else if ((tx_rate >= MGN_VHT1SS_MCS5) && - (tx_rate <= MGN_VHT1SS_MCS6)) - pwr_tracking_limit = 28; /*+2dB*/ - else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/ - pwr_tracking_limit = 26; /*+1dB*/ - else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/ - pwr_tracking_limit = 24; /*+0dB*/ - else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/ - pwr_tracking_limit = 22; /*-1dB*/ - else - pwr_tracking_limit = 24; - } - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "TxRate=0x%x, PwrTrackingLimit=%d\n", - tx_rate, pwr_tracking_limit); - - if (method == BBSWING) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "===>%s\n", __func__); - if (rf_path == RF90_PATH_A) { - final_swing_idx[RF90_PATH_A] = - (rtldm->ofdm_index[RF90_PATH_A] > - pwr_tracking_limit) ? - pwr_tracking_limit : - rtldm->ofdm_index[RF90_PATH_A]; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n", - rtldm->ofdm_index[RF90_PATH_A], - final_swing_idx[RF90_PATH_A]); - - rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, - txscaling_tbl[final_swing_idx[RF90_PATH_A]]); - } - } else if (method == MIX_MODE) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pDM_Odm->DefaultOfdmIndex=%d,pDM_Odm->Aboslute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n", - rtldm->default_ofdm_index, - rtldm->absolute_ofdm_swing_idx[rf_path], - rf_path); - - final_ofdm_swing_index = - rtldm->default_ofdm_index + - rtldm->absolute_ofdm_swing_idx[rf_path]; - /*BBSwing higher then Limit*/ - if (rf_path == RF90_PATH_A) { - if (final_ofdm_swing_index > pwr_tracking_limit) { - rtldm->remnant_cck_idx = - final_ofdm_swing_index - - pwr_tracking_limit; - /* CCK Follow the same compensate value as Path A*/ - rtldm->remnant_ofdm_swing_idx[rf_path] = - final_ofdm_swing_index - - pwr_tracking_limit; - - rtl_set_bbreg(hw, RA_TXSCALE, - 0xFFE00000, - txscaling_tbl[pwr_tracking_limit]); - - rtldm->modify_txagc_flag_path_a = true; - - /*Set TxAGC Page C{};*/ - rtl8821ae_phy_set_txpower_level_by_path(hw, - rtlphy->current_channel, - RF90_PATH_A); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - " ******Path_A Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n", - pwr_tracking_limit, - rtldm->remnant_ofdm_swing_idx[rf_path]); - } else if (final_ofdm_swing_index < 0) { - rtldm->remnant_cck_idx = final_ofdm_swing_index; - /* CCK Follow the same compensate value as Path A*/ - rtldm->remnant_ofdm_swing_idx[rf_path] = - final_ofdm_swing_index; - - rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, - txscaling_tbl[0]); - - rtldm->modify_txagc_flag_path_a = true; - - /*Set TxAGC Page C{};*/ - rtl8821ae_phy_set_txpower_level_by_path(hw, - rtlphy->current_channel, RF90_PATH_A); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Path_A Lower then BBSwing lower bound 0 , Remnant TxAGC Value = %d\n", - rtldm->remnant_ofdm_swing_idx[rf_path]); - } else { - rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, - txscaling_tbl[(u8)final_ofdm_swing_index]); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Path_A Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n", - final_ofdm_swing_index); - /*If TxAGC has changed, reset TxAGC again*/ - if (rtldm->modify_txagc_flag_path_a) { - rtldm->remnant_cck_idx = 0; - rtldm->remnant_ofdm_swing_idx[rf_path] = 0; - - /*Set TxAGC Page C{};*/ - rtl8821ae_phy_set_txpower_level_by_path(hw, - rtlphy->current_channel, RF90_PATH_A); - - rtldm->modify_txagc_flag_path_a = false; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, - DBG_LOUD, - "******Path_A pDM_Odm->Modify_TxAGC_Flag= FALSE\n"); - } - } - } - } else { - return; - } -} - -void rtl8821ae_dm_txpower_tracking_callback_thermalmeter( - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0; - u8 thermal_value_avg_count = 0; - u32 thermal_value_avg = 0; - - u8 ofdm_min_index = 6; /*OFDM BB Swing should be less than +3.0dB */ - /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/ - u8 index_for_channel = 0; - - /* 1. The following TWO tables decide the final - * index of OFDM/CCK swing table. - */ - u8 *delta_swing_table_idx_tup_a; - u8 *delta_swing_table_idx_tdown_a; - u8 *delta_swing_table_idx_tup_b; - u8 *delta_swing_table_idx_tdown_b; - - /*2. Initilization ( 7 steps in total )*/ - rtl8821ae_get_delta_swing_table(hw, (u8 **)&delta_swing_table_idx_tup_a, - (u8 **)&delta_swing_table_idx_tdown_a, - (u8 **)&delta_swing_table_idx_tup_b, - (u8 **)&delta_swing_table_idx_tdown_b); - - rtldm->txpower_trackinginit = true; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "===>%s,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n", - __func__, - rtldm->swing_idx_cck_base, - rtldm->swing_idx_ofdm_base[RF90_PATH_A], - rtldm->default_ofdm_index); - /*0x42: RF Reg[15:10] 88E*/ - thermal_value = (u8)rtl_get_rfreg(hw, - RF90_PATH_A, RF_T_METER_8812A, 0xfc00); - if (!rtldm->txpower_track_control || - rtlefuse->eeprom_thermalmeter == 0 || - rtlefuse->eeprom_thermalmeter == 0xFF) - return; - - /* 3. Initialize ThermalValues of RFCalibrateInfo*/ - - if (rtlhal->reloadtxpowerindex) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "reload ofdm index for band switch\n"); - } - - /*4. Calculate average thermal meter*/ - rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value; - rtldm->thermalvalue_avg_index++; - if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A) - /*Average times = c.AverageThermalNum*/ - rtldm->thermalvalue_avg_index = 0; - - for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) { - if (rtldm->thermalvalue_avg[i]) { - thermal_value_avg += rtldm->thermalvalue_avg[i]; - thermal_value_avg_count++; - } - } - /*Calculate Average ThermalValue after average enough times*/ - if (thermal_value_avg_count) { - thermal_value = (u8)(thermal_value_avg / - thermal_value_avg_count); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n", - thermal_value, rtlefuse->eeprom_thermalmeter); - } - - /*5. Calculate delta, delta_LCK, delta_IQK. - *"delta" here is used to determine whether - * thermal value changes or not. - */ - delta = (thermal_value > rtldm->thermalvalue) ? - (thermal_value - rtldm->thermalvalue) : - (rtldm->thermalvalue - thermal_value); - delta_lck = (thermal_value > rtldm->thermalvalue_lck) ? - (thermal_value - rtldm->thermalvalue_lck) : - (rtldm->thermalvalue_lck - thermal_value); - delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ? - (thermal_value - rtldm->thermalvalue_iqk) : - (rtldm->thermalvalue_iqk - thermal_value); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n", - delta, delta_lck, delta_iqk); - - /* 6. If necessary, do LCK. */ - /*Delta temperature is equal to or larger than 20 centigrade.*/ - if (delta_lck >= IQK_THRESHOLD) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "delta_LCK(%d) >= Threshold_IQK(%d)\n", - delta_lck, IQK_THRESHOLD); - rtldm->thermalvalue_lck = thermal_value; - rtl8821ae_phy_lc_calibrate(hw); - } - - /*7. If necessary, move the index of swing table to adjust Tx power.*/ - - if (delta > 0 && rtldm->txpower_track_control) { - /*"delta" here is used to record the - * absolute value of differrence. - */ - delta = thermal_value > rtlefuse->eeprom_thermalmeter ? - (thermal_value - rtlefuse->eeprom_thermalmeter) : - (rtlefuse->eeprom_thermalmeter - thermal_value); - - if (delta >= TXSCALE_TABLE_SIZE) - delta = TXSCALE_TABLE_SIZE - 1; - - /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/ - - if (thermal_value > rtlefuse->eeprom_thermalmeter) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "delta_swing_table_idx_tup_a[%d] = %d\n", - delta, delta_swing_table_idx_tup_a[delta]); - rtldm->delta_power_index_last[RF90_PATH_A] = - rtldm->delta_power_index[RF90_PATH_A]; - rtldm->delta_power_index[RF90_PATH_A] = - delta_swing_table_idx_tup_a[delta]; - - rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] = - delta_swing_table_idx_tup_a[delta]; - /*Record delta swing for mix mode power tracking*/ - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", - rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "delta_swing_table_idx_tdown_a[%d] = %d\n", - delta, delta_swing_table_idx_tdown_a[delta]); - - rtldm->delta_power_index_last[RF90_PATH_A] = - rtldm->delta_power_index[RF90_PATH_A]; - rtldm->delta_power_index[RF90_PATH_A] = - -1 * delta_swing_table_idx_tdown_a[delta]; - - rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] = - -1 * delta_swing_table_idx_tdown_a[delta]; - /* Record delta swing for mix mode power tracking*/ - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", - rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); - } - - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "\n\n================================ [Path-%c]Calculating PowerIndexOffset ================================\n", - (p == RF90_PATH_A ? 'A' : 'B')); - /*If Thermal value changes but lookup table value - * still the same - */ - if (rtldm->delta_power_index[p] == - rtldm->delta_power_index_last[p]) - - rtldm->power_index_offset[p] = 0; - else - rtldm->power_index_offset[p] = - rtldm->delta_power_index[p] - - rtldm->delta_power_index_last[p]; - /*Power Index Diff between 2 times Power Tracking*/ - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "[Path-%c] PowerIndexOffset(%d) = DeltaPowerIndex(%d) - DeltaPowerIndexLast(%d)\n", - (p == RF90_PATH_A ? 'A' : 'B'), - rtldm->power_index_offset[p], - rtldm->delta_power_index[p] , - rtldm->delta_power_index_last[p]); - - rtldm->ofdm_index[p] = - rtldm->swing_idx_ofdm_base[p] + - rtldm->power_index_offset[p]; - rtldm->cck_index = - rtldm->swing_idx_cck_base + - rtldm->power_index_offset[p]; - - rtldm->swing_idx_cck = rtldm->cck_index; - rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p]; - - /*********Print BB Swing Base and Index Offset********/ - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n", - rtldm->swing_idx_cck, - rtldm->swing_idx_cck_base, - rtldm->power_index_offset[p]); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n", - rtldm->swing_idx_ofdm[p], - (p == RF90_PATH_A ? 'A' : 'B'), - rtldm->swing_idx_ofdm_base[p], - rtldm->power_index_offset[p]); - - /*7.1 Handle boundary conditions of index.*/ - - if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1) - rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1; - else if (rtldm->ofdm_index[p] < ofdm_min_index) - rtldm->ofdm_index[p] = ofdm_min_index; - } - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "\n\n========================================================================================================\n"); - if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1) - rtldm->cck_index = TXSCALE_TABLE_SIZE - 1; - else if (rtldm->cck_index < 0) - rtldm->cck_index = 0; - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "The thermal meter is unchanged or TxPowerTracking OFF(%d):ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n", - rtldm->txpower_track_control, - thermal_value, - rtldm->thermalvalue); - - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) - rtldm->power_index_offset[p] = 0; - } - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "TxPowerTracking: [CCK] Swing Current Index: %d, Swing Base Index: %d\n", - /*Print Swing base & current*/ - rtldm->cck_index, rtldm->swing_idx_cck_base); - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "TxPowerTracking: [OFDM] Swing Current Index: %d, Swing Base Index[%c]: %d\n", - rtldm->ofdm_index[p], - (p == RF90_PATH_A ? 'A' : 'B'), - rtldm->swing_idx_ofdm_base[p]); - } - - if ((rtldm->power_index_offset[RF90_PATH_A] != 0 || - rtldm->power_index_offset[RF90_PATH_B] != 0) && - rtldm->txpower_track_control) { - /*7.2 Configure the Swing Table to adjust Tx Power.*/ - /*Always TRUE after Tx Power is adjusted by power tracking.*/ - /* - * 2012/04/23 MH According to Luke's suggestion, - * we can not write BB digital - * to increase TX power. Otherwise, EVM will be bad. - * - * 2012/04/25 MH Add for tx power tracking to - * set tx power in tx agc for 88E. - */ - if (thermal_value > rtldm->thermalvalue) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Temperature Increasing(A): delta_pi: %d , delta_t: %d,Now_t: %d, EFUSE_t: %d, Last_t: %d\n", - rtldm->power_index_offset[RF90_PATH_A], - delta, thermal_value, - rtlefuse->eeprom_thermalmeter, - rtldm->thermalvalue); - } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/ - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n", - rtldm->power_index_offset[RF90_PATH_A], - delta, thermal_value, - rtlefuse->eeprom_thermalmeter, - rtldm->thermalvalue); - } - - if (thermal_value > rtlefuse->eeprom_thermalmeter) { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Temperature(%d) higher than PG value(%d)\n", - thermal_value, rtlefuse->eeprom_thermalmeter); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "****Enter POWER Tracking MIX_MODE****\n"); - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) - rtl8821ae_dm_txpwr_track_set_pwr(hw, - MIX_MODE, p, index_for_channel); - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Temperature(%d) lower than PG value(%d)\n", - thermal_value, rtlefuse->eeprom_thermalmeter); - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "*****Enter POWER Tracking MIX_MODE*****\n"); - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) - rtl8812ae_dm_txpwr_track_set_pwr(hw, - MIX_MODE, p, index_for_channel); - } - /*Record last time Power Tracking result as base.*/ - rtldm->swing_idx_cck_base = rtldm->swing_idx_cck; - for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) - rtldm->swing_idx_ofdm_base[p] = rtldm->swing_idx_ofdm[p]; - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n", - rtldm->thermalvalue, thermal_value); - /*Record last Power Tracking Thermal Value*/ - rtldm->thermalvalue = thermal_value; - } - /* Delta temperature is equal to or larger than - * 20 centigrade (When threshold is 8). - */ - if (delta_iqk >= IQK_THRESHOLD) { - if (!rtlphy->lck_inprogress) { - spin_lock(&rtlpriv->locks.iqk_lock); - rtlphy->lck_inprogress = true; - spin_unlock(&rtlpriv->locks.iqk_lock); - - rtl8821ae_do_iqk(hw, delta_iqk, thermal_value, 8); - - spin_lock(&rtlpriv->locks.iqk_lock); - rtlphy->lck_inprogress = false; - spin_unlock(&rtlpriv->locks.iqk_lock); - } - } - - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===%s\n", __func__); -} - -void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (!rtlpriv->dm.tm_trigger) { - rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16), - 0x03); - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Trigger 8821ae Thermal Meter!!\n"); - rtlpriv->dm.tm_trigger = 1; - return; - } else { - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Schedule TxPowerTracking !!\n"); - - rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw); - rtlpriv->dm.tm_trigger = 0; - } -} - -static void rtl8821ae_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rate_adaptive *p_ra = &rtlpriv->ra; - u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m; - u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra; - u8 go_up_gap = 5; - struct ieee80211_sta *sta = NULL; - - if (is_hal_stop(rtlhal)) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "driver is going to unload\n"); - return; - } - - if (!rtlpriv->dm.useramask) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "driver does not control rate adaptive mask\n"); - return; - } - - if (mac->link_state == MAC80211_LINKED && - mac->opmode == NL80211_IFTYPE_STATION) { - switch (p_ra->pre_ratr_state) { - case DM_RATR_STA_MIDDLE: - high_rssithresh_for_ra += go_up_gap; - break; - case DM_RATR_STA_LOW: - high_rssithresh_for_ra += go_up_gap; - low_rssithresh_for_ra += go_up_gap; - break; - default: - break; - } - - if (rtlpriv->dm.undec_sm_pwdb > - (long)high_rssithresh_for_ra) - p_ra->ratr_state = DM_RATR_STA_HIGH; - else if (rtlpriv->dm.undec_sm_pwdb > - (long)low_rssithresh_for_ra) - p_ra->ratr_state = DM_RATR_STA_MIDDLE; - else - p_ra->ratr_state = DM_RATR_STA_LOW; - - if (p_ra->pre_ratr_state != p_ra->ratr_state) { - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "RSSI = %ld\n", - rtlpriv->dm.undec_sm_pwdb); - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "RSSI_LEVEL = %d\n", p_ra->ratr_state); - RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, - "PreState = %d, CurState = %d\n", - p_ra->pre_ratr_state, p_ra->ratr_state); - - rcu_read_lock(); - sta = rtl_find_sta(hw, mac->bssid); - if (sta) - rtlpriv->cfg->ops->update_rate_tbl(hw, - sta, p_ra->ratr_state); - rcu_read_unlock(); - - p_ra->pre_ratr_state = p_ra->ratr_state; - } - } -} - -static void rtl8821ae_dm_refresh_basic_rate_mask(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - struct rtl_mac *mac = &rtlpriv->mac80211; - static u8 stage; - u8 cur_stage = 0; - u16 basic_rate = RRSR_1M | RRSR_2M | RRSR_5_5M | RRSR_11M | RRSR_6M; - - if (mac->link_state < MAC80211_LINKED) - cur_stage = 0; - else if (dm_digtable->rssi_val_min < 25) - cur_stage = 1; - else if (dm_digtable->rssi_val_min > 30) - cur_stage = 3; - else - cur_stage = 2; - - if (cur_stage != stage) { - if (cur_stage == 1) { - basic_rate &= (!(basic_rate ^ mac->basic_rates)); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_BASIC_RATE, (u8 *)&basic_rate); - } else if (cur_stage == 3 && (stage == 1 || stage == 2)) { - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_BASIC_RATE, (u8 *)&mac->basic_rates); - } - } - stage = cur_stage; -} - -static void rtl8821ae_dm_edca_choose_traffic_idx( - struct ieee80211_hw *hw, u64 cur_tx_bytes, - u64 cur_rx_bytes, bool b_bias_on_rx, - bool *pb_is_cur_rdl_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (b_bias_on_rx) { - if (cur_tx_bytes > (cur_rx_bytes*4)) { - *pb_is_cur_rdl_state = false; - RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, - "Uplink Traffic\n "); - } else { - *pb_is_cur_rdl_state = true; - RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, - "Balance Traffic\n"); - } - } else { - if (cur_rx_bytes > (cur_tx_bytes*4)) { - *pb_is_cur_rdl_state = true; - RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, - "Downlink Traffic\n"); - } else { - *pb_is_cur_rdl_state = false; - RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, - "Balance Traffic\n"); - } - } - return; -} - -static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - - /*Keep past Tx/Rx packet count for RT-to-RT EDCA turbo.*/ - u64 cur_tx_ok_cnt = 0; - u64 cur_rx_ok_cnt = 0; - u32 edca_be_ul = 0x5ea42b; - u32 edca_be_dl = 0x5ea42b; - u32 edca_be = 0x5ea42b; - u8 iot_peer = 0; - bool *pb_is_cur_rdl_state = NULL; - bool b_last_is_cur_rdl_state = false; - bool b_bias_on_rx = false; - bool b_edca_turbo_on = false; - - RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, - "rtl8821ae_dm_check_edca_turbo=====>"); - RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, - "Orginial BE PARAM: 0x%x\n", - rtl_read_dword(rtlpriv, DM_REG_EDCA_BE_11N)); - - if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100) - rtlpriv->dm.is_any_nonbepkts = true; - rtlpriv->dm.dbginfo.num_non_be_pkt = 0; - - /*=============================== - * list paramter for different platform - *=============================== - */ - b_last_is_cur_rdl_state = rtlpriv->dm.is_cur_rdlstate; - pb_is_cur_rdl_state = &rtlpriv->dm.is_cur_rdlstate; - - cur_tx_ok_cnt = rtlpriv->stats.txbytesunicast - rtldm->last_tx_ok_cnt; - cur_rx_ok_cnt = rtlpriv->stats.rxbytesunicast - rtldm->last_rx_ok_cnt; - - rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast; - rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast; - - iot_peer = rtlpriv->mac80211.vendor; - b_bias_on_rx = false; - b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) && - (!rtlpriv->dm.disable_framebursting)) ? - true : false; - - if (rtlpriv->rtlhal.hw_type != HARDWARE_TYPE_RTL8812AE) { - if ((iot_peer == PEER_CISCO) && - (mac->mode == WIRELESS_MODE_N_24G)) { - edca_be_dl = edca_setting_dl[iot_peer]; - edca_be_ul = edca_setting_ul[iot_peer]; - } - } - - RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, - "bIsAnyNonBEPkts : 0x%x bDisableFrameBursting : 0x%x\n", - rtlpriv->dm.is_any_nonbepkts, - rtlpriv->dm.disable_framebursting); - - RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, - "bEdcaTurboOn : 0x%x bBiasOnRx : 0x%x\n", - b_edca_turbo_on, b_bias_on_rx); - - if (b_edca_turbo_on) { - RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, - "curTxOkCnt : 0x%llx\n", cur_tx_ok_cnt); - RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, - "curRxOkCnt : 0x%llx\n", cur_rx_ok_cnt); - if (b_bias_on_rx) - rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt, - cur_rx_ok_cnt, true, pb_is_cur_rdl_state); - else - rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt, - cur_rx_ok_cnt, false, pb_is_cur_rdl_state); - - edca_be = (*pb_is_cur_rdl_state) ? edca_be_dl : edca_be_ul; - - rtl_write_dword(rtlpriv, DM_REG_EDCA_BE_11N, edca_be); - - RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, - "EDCA Turbo on: EDCA_BE:0x%x\n", edca_be); - - rtlpriv->dm.current_turbo_edca = true; - - RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD, - "EDCA_BE_DL : 0x%x EDCA_BE_UL : 0x%x EDCA_BE : 0x%x\n", - edca_be_dl, edca_be_ul, edca_be); - } else { - if (rtlpriv->dm.current_turbo_edca) { - u8 tmp = AC0_BE; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, - (u8 *)(&tmp)); - } - rtlpriv->dm.current_turbo_edca = false; - } - - rtlpriv->dm.is_any_nonbepkts = false; - rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast; - rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast; -} - -static void rtl8821ae_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - u8 cur_cck_cca_thresh; - - if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) { - if (dm_digtable->rssi_val_min > 25) { - cur_cck_cca_thresh = 0xcd; - } else if ((dm_digtable->rssi_val_min <= 25) && - (dm_digtable->rssi_val_min > 10)) { - cur_cck_cca_thresh = 0x83; - } else { - if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) - cur_cck_cca_thresh = 0x83; - else - cur_cck_cca_thresh = 0x40; - } - } else { - if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) - cur_cck_cca_thresh = 0x83; - else - cur_cck_cca_thresh = 0x40; - } - - if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh) - rtl_write_byte(rtlpriv, ODM_REG_CCK_CCA_11AC, - cur_cck_cca_thresh); - - dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres; - dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh; - RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, - "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres); -} - -static void rtl8821ae_dm_dynamic_atc_switch(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - u8 crystal_cap; - u32 packet_count; - int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0; - int cfo_ave_diff; - - if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { - /*1.Enable ATC*/ - if (rtldm->atc_status == ATC_STATUS_OFF) { - rtl_set_bbreg(hw, RFC_AREA, BIT(14), ATC_STATUS_ON); - rtldm->atc_status = ATC_STATUS_ON; - } - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "No link!!\n"); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "atc_status = %d\n", rtldm->atc_status); - - if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) { - rtldm->crystal_cap = rtlpriv->efuse.crystalcap; - crystal_cap = rtldm->crystal_cap & 0x3f; - crystal_cap = crystal_cap & 0x3f; - if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE) - rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, - 0x7ff80000, (crystal_cap | - (crystal_cap << 6))); - else - rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, - 0xfff000, (crystal_cap | - (crystal_cap << 6))); - } - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "crystal_cap = 0x%x\n", - rtldm->crystal_cap); - } else{ - /*1. Calculate CFO for path-A & path-B*/ - cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280; - cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280; - packet_count = rtldm->packet_count; - - /*2.No new packet*/ - if (packet_count == rtldm->packet_count_pre) { - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "packet counter doesn't change\n"); - return; - } - - rtldm->packet_count_pre = packet_count; - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "packet counter = %d\n", - rtldm->packet_count); - - /*3.Average CFO*/ - if (rtlpriv->phy.rf_type == RF_1T1R) - cfo_ave = cfo_khz_a; - else - cfo_ave = (cfo_khz_a + cfo_khz_b) >> 1; - - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "cfo_khz_a = %dkHz, cfo_khz_b = %dkHz, cfo_ave = %dkHz\n", - cfo_khz_a, cfo_khz_b, cfo_ave); - - /*4.Avoid abnormal large CFO*/ - cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ? - (rtldm->cfo_ave_pre - cfo_ave) : - (cfo_ave - rtldm->cfo_ave_pre); - - if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) { - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "first large CFO hit\n"); - rtldm->large_cfo_hit = 1; - return; - } else - rtldm->large_cfo_hit = 0; - - rtldm->cfo_ave_pre = cfo_ave; - - /*CFO tracking by adjusting Xtal cap.*/ - - /*1.Dynamic Xtal threshold*/ - if (cfo_ave >= -rtldm->cfo_threshold && - cfo_ave <= rtldm->cfo_threshold && - rtldm->is_freeze == 0) { - if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) { - rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10; - rtldm->is_freeze = 1; - } else { - rtldm->cfo_threshold = CFO_THRESHOLD_XTAL; - } - } - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Dynamic threshold = %d\n", - rtldm->cfo_threshold); - - /* 2.Calculate Xtal offset*/ - if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f) - adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1; - else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) && - rtlpriv->dm.crystal_cap > 0) - adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1; - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "Crystal cap = 0x%x, Crystal cap offset = %d\n", - rtldm->crystal_cap, adjust_xtal); - - /*3.Adjudt Crystal Cap.*/ - if (adjust_xtal != 0) { - rtldm->is_freeze = 0; - rtldm->crystal_cap += adjust_xtal; - - if (rtldm->crystal_cap > 0x3f) - rtldm->crystal_cap = 0x3f; - else if (rtldm->crystal_cap < 0) - rtldm->crystal_cap = 0; - - crystal_cap = rtldm->crystal_cap & 0x3f; - crystal_cap = crystal_cap & 0x3f; - if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE) - rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, - 0x7ff80000, (crystal_cap | - (crystal_cap << 6))); - else - rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, - 0xfff000, (crystal_cap | - (crystal_cap << 6))); - RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, - "New crystal cap = 0x%x\n", - rtldm->crystal_cap); - } - } -} - -void rtl8821ae_dm_watchdog(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool fw_current_inpsmode = false; - bool fw_ps_awake = true; - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inpsmode)); - - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, - (u8 *)(&fw_ps_awake)); - - if (ppsc->p2p_ps_info.p2p_ps_mode) - fw_ps_awake = false; - - if ((ppsc->rfpwr_state == ERFON) && - ((!fw_current_inpsmode) && fw_ps_awake) && - (!ppsc->rfchange_inprogress)) { - rtl8821ae_dm_common_info_self_update(hw); - rtl8821ae_dm_false_alarm_counter_statistics(hw); - rtl8821ae_dm_check_rssi_monitor(hw); - rtl8821ae_dm_dig(hw); - rtl8821ae_dm_cck_packet_detection_thresh(hw); - rtl8821ae_dm_refresh_rate_adaptive_mask(hw); - rtl8821ae_dm_refresh_basic_rate_mask(hw); - rtl8821ae_dm_check_edca_turbo(hw); - rtl8821ae_dm_dynamic_atc_switch(hw); - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_dm_check_txpower_tracking_thermalmeter(hw); - else - rtl8821ae_dm_check_txpower_tracking_thermalmeter(hw); - rtl8821ae_dm_iq_calibrate(hw); - } - - rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0; - RT_TRACE(rtlpriv, COMP_DIG, DBG_DMESG, "\n"); -} - -void rtl8821ae_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, - u8 *pdesc, u32 mac_id) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct fast_ant_training *pfat_table = &rtldm->fat_table; - - if (rtlhal->hw_type != HARDWARE_TYPE_RTL8812AE) - return; - - if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV) - SET_TX_DESC_TX_ANT(pdesc, pfat_table->antsel_a[mac_id]); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.h b/drivers/net/wireless/rtlwifi/rtl8821ae/dm.h deleted file mode 100644 index 625a6bbb21fc..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.h +++ /dev/null @@ -1,315 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8821AE_DM_H__ -#define __RTL8821AE_DM_H__ - -#define MAIN_ANT 0 -#define AUX_ANT 1 -#define MAIN_ANT_CG_TRX 1 -#define AUX_ANT_CG_TRX 0 -#define MAIN_ANT_CGCS_RX 0 -#define AUX_ANT_CGCS_RX 1 - -#define TXSCALE_TABLE_SIZE 37 - -/*RF REG LIST*/ -#define DM_REG_RF_MODE_11N 0x00 -#define DM_REG_RF_0B_11N 0x0B -#define DM_REG_CHNBW_11N 0x18 -#define DM_REG_T_METER_11N 0x24 -#define DM_REG_RF_25_11N 0x25 -#define DM_REG_RF_26_11N 0x26 -#define DM_REG_RF_27_11N 0x27 -#define DM_REG_RF_2B_11N 0x2B -#define DM_REG_RF_2C_11N 0x2C -#define DM_REG_RXRF_A3_11N 0x3C -#define DM_REG_T_METER_92D_11N 0x42 -#define DM_REG_T_METER_88E_11N 0x42 - -/*BB REG LIST*/ -/*PAGE 8 */ -#define DM_REG_BB_CTRL_11N 0x800 -#define DM_REG_RF_PIN_11N 0x804 -#define DM_REG_PSD_CTRL_11N 0x808 -#define DM_REG_TX_ANT_CTRL_11N 0x80C -#define DM_REG_BB_PWR_SAV5_11N 0x818 -#define DM_REG_CCK_RPT_FORMAT_11N 0x824 -#define DM_REG_RX_DEFUALT_A_11N 0x858 -#define DM_REG_RX_DEFUALT_B_11N 0x85A -#define DM_REG_BB_PWR_SAV3_11N 0x85C -#define DM_REG_ANTSEL_CTRL_11N 0x860 -#define DM_REG_RX_ANT_CTRL_11N 0x864 -#define DM_REG_PIN_CTRL_11N 0x870 -#define DM_REG_BB_PWR_SAV1_11N 0x874 -#define DM_REG_ANTSEL_PATH_11N 0x878 -#define DM_REG_BB_3WIRE_11N 0x88C -#define DM_REG_SC_CNT_11N 0x8C4 -#define DM_REG_PSD_DATA_11N 0x8B4 -/*PAGE 9*/ -#define DM_REG_ANT_MAPPING1_11N 0x914 -#define DM_REG_ANT_MAPPING2_11N 0x918 -/*PAGE A*/ -#define DM_REG_CCK_ANTDIV_PARA1_11N 0xA00 -#define DM_REG_CCK_CCA_11N 0xA0A -#define DM_REG_CCK_CCA_11AC 0xA0A -#define DM_REG_CCK_ANTDIV_PARA2_11N 0xA0C -#define DM_REG_CCK_ANTDIV_PARA3_11N 0xA10 -#define DM_REG_CCK_ANTDIV_PARA4_11N 0xA14 -#define DM_REG_CCK_FILTER_PARA1_11N 0xA22 -#define DM_REG_CCK_FILTER_PARA2_11N 0xA23 -#define DM_REG_CCK_FILTER_PARA3_11N 0xA24 -#define DM_REG_CCK_FILTER_PARA4_11N 0xA25 -#define DM_REG_CCK_FILTER_PARA5_11N 0xA26 -#define DM_REG_CCK_FILTER_PARA6_11N 0xA27 -#define DM_REG_CCK_FILTER_PARA7_11N 0xA28 -#define DM_REG_CCK_FILTER_PARA8_11N 0xA29 -#define DM_REG_CCK_FA_RST_11N 0xA2C -#define DM_REG_CCK_FA_MSB_11N 0xA58 -#define DM_REG_CCK_FA_LSB_11N 0xA5C -#define DM_REG_CCK_CCA_CNT_11N 0xA60 -#define DM_REG_BB_PWR_SAV4_11N 0xA74 -/*PAGE B */ -#define DM_REG_LNA_SWITCH_11N 0xB2C -#define DM_REG_PATH_SWITCH_11N 0xB30 -#define DM_REG_RSSI_CTRL_11N 0xB38 -#define DM_REG_CONFIG_ANTA_11N 0xB68 -#define DM_REG_RSSI_BT_11N 0xB9C -/*PAGE C */ -#define DM_REG_OFDM_FA_HOLDC_11N 0xC00 -#define DM_REG_RX_PATH_11N 0xC04 -#define DM_REG_TRMUX_11N 0xC08 -#define DM_REG_OFDM_FA_RSTC_11N 0xC0C -#define DM_REG_RXIQI_MATRIX_11N 0xC14 -#define DM_REG_TXIQK_MATRIX_LSB1_11N 0xC4C -#define DM_REG_IGI_A_11N 0xC50 -#define DM_REG_IGI_A_11AC 0xC50 -#define DM_REG_ANTDIV_PARA2_11N 0xC54 -#define DM_REG_IGI_B_11N 0xC58 -#define DM_REG_IGI_B_11AC 0xE50 -#define DM_REG_ANTDIV_PARA3_11N 0xC5C -#define DM_REG_BB_PWR_SAV2_11N 0xC70 -#define DM_REG_RX_OFF_11N 0xC7C -#define DM_REG_TXIQK_MATRIXA_11N 0xC80 -#define DM_REG_TXIQK_MATRIXB_11N 0xC88 -#define DM_REG_TXIQK_MATRIXA_LSB2_11N 0xC94 -#define DM_REG_TXIQK_MATRIXB_LSB2_11N 0xC9C -#define DM_REG_RXIQK_MATRIX_LSB_11N 0xCA0 -#define DM_REG_ANTDIV_PARA1_11N 0xCA4 -#define DM_REG_OFDM_FA_TYPE1_11N 0xCF0 -/*PAGE D */ -#define DM_REG_OFDM_FA_RSTD_11N 0xD00 -#define DM_REG_OFDM_FA_TYPE2_11N 0xDA0 -#define DM_REG_OFDM_FA_TYPE3_11N 0xDA4 -#define DM_REG_OFDM_FA_TYPE4_11N 0xDA8 -/*PAGE E */ -#define DM_REG_TXAGC_A_6_18_11N 0xE00 -#define DM_REG_TXAGC_A_24_54_11N 0xE04 -#define DM_REG_TXAGC_A_1_MCS32_11N 0xE08 -#define DM_REG_TXAGC_A_MCS0_3_11N 0xE10 -#define DM_REG_TXAGC_A_MCS4_7_11N 0xE14 -#define DM_REG_TXAGC_A_MCS8_11_11N 0xE18 -#define DM_REG_TXAGC_A_MCS12_15_11N 0xE1C -#define DM_REG_FPGA0_IQK_11N 0xE28 -#define DM_REG_TXIQK_TONE_A_11N 0xE30 -#define DM_REG_RXIQK_TONE_A_11N 0xE34 -#define DM_REG_TXIQK_PI_A_11N 0xE38 -#define DM_REG_RXIQK_PI_A_11N 0xE3C -#define DM_REG_TXIQK_11N 0xE40 -#define DM_REG_RXIQK_11N 0xE44 -#define DM_REG_IQK_AGC_PTS_11N 0xE48 -#define DM_REG_IQK_AGC_RSP_11N 0xE4C -#define DM_REG_BLUETOOTH_11N 0xE6C -#define DM_REG_RX_WAIT_CCA_11N 0xE70 -#define DM_REG_TX_CCK_RFON_11N 0xE74 -#define DM_REG_TX_CCK_BBON_11N 0xE78 -#define DM_REG_OFDM_RFON_11N 0xE7C -#define DM_REG_OFDM_BBON_11N 0xE80 -#define DM_REG_TX2RX_11N 0xE84 -#define DM_REG_TX2TX_11N 0xE88 -#define DM_REG_RX_CCK_11N 0xE8C -#define DM_REG_RX_OFDM_11N 0xED0 -#define DM_REG_RX_WAIT_RIFS_11N 0xED4 -#define DM_REG_RX2RX_11N 0xED8 -#define DM_REG_STANDBY_11N 0xEDC -#define DM_REG_SLEEP_11N 0xEE0 -#define DM_REG_PMPD_ANAEN_11N 0xEEC - -/*MAC REG LIST*/ -#define DM_REG_BB_RST_11N 0x02 -#define DM_REG_ANTSEL_PIN_11N 0x4C -#define DM_REG_EARLY_MODE_11N 0x4D0 -#define DM_REG_RSSI_MONITOR_11N 0x4FE -#define DM_REG_EDCA_VO_11N 0x500 -#define DM_REG_EDCA_VI_11N 0x504 -#define DM_REG_EDCA_BE_11N 0x508 -#define DM_REG_EDCA_BK_11N 0x50C -#define DM_REG_TXPAUSE_11N 0x522 -#define DM_REG_RESP_TX_11N 0x6D8 -#define DM_REG_ANT_TRAIN_PARA1_11N 0x7b0 -#define DM_REG_ANT_TRAIN_PARA2_11N 0x7b4 - -/*DIG Related*/ -#define DM_BIT_IGI_11N 0x0000007F -#define DM_BIT_IGI_11AC 0xFFFFFFFF - -#define HAL_DM_DIG_DISABLE BIT(0) -#define HAL_DM_HIPWR_DISABLE BIT(1) - -#define OFDM_TABLE_LENGTH 43 -#define CCK_TABLE_LENGTH 33 - -#define OFDM_TABLE_SIZE 37 -#define CCK_TABLE_SIZE 33 - -#define BW_AUTO_SWITCH_HIGH_LOW 25 -#define BW_AUTO_SWITCH_LOW_HIGH 30 - -#define DM_DIG_FA_UPPER 0x3e -#define DM_DIG_FA_LOWER 0x1e -#define DM_DIG_FA_TH0 200 -#define DM_DIG_FA_TH1 0x300 -#define DM_DIG_FA_TH2 0x400 - -#define RXPATHSELECTION_SS_TH_LOW 30 -#define RXPATHSELECTION_DIFF_TH 18 - -#define DM_RATR_STA_INIT 0 -#define DM_RATR_STA_HIGH 1 -#define DM_RATR_STA_MIDDLE 2 -#define DM_RATR_STA_LOW 3 - -#define CTS2SELF_THVAL 30 -#define REGC38_TH 20 - -#define WAIOTTHVAL 25 - -#define TXHIGHPWRLEVEL_NORMAL 0 -#define TXHIGHPWRLEVEL_LEVEL1 1 -#define TXHIGHPWRLEVEL_LEVEL2 2 -#define TXHIGHPWRLEVEL_BT1 3 -#define TXHIGHPWRLEVEL_BT2 4 - -#define DM_TYPE_BYFW 0 -#define DM_TYPE_BYDRIVER 1 - -#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 -#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 -#define TXPWRTRACK_MAX_IDX 6 - -/* Dynamic ATC switch */ -#define ATC_STATUS_OFF 0x0 /* enable */ -#define ATC_STATUS_ON 0x1 /* disable */ -#define CFO_THRESHOLD_XTAL 10 /* kHz */ -#define CFO_THRESHOLD_ATC 80 /* kHz */ - -#define AVG_THERMAL_NUM_8812A 4 -#define TXPWR_TRACK_TABLE_SIZE 30 -#define MAX_PATH_NUM_8812A 2 -#define MAX_PATH_NUM_8821A 1 - -enum FAT_STATE { - FAT_NORMAL_STATE = 0, - FAT_TRAINING_STATE = 1, -}; - -enum tag_dynamic_init_gain_operation_type_definition { - DIG_TYPE_THRESH_HIGH = 0, - DIG_TYPE_THRESH_LOW = 1, - DIG_TYPE_BACKOFF = 2, - DIG_TYPE_RX_GAIN_MIN = 3, - DIG_TYPE_RX_GAIN_MAX = 4, - DIG_TYPE_ENABLE = 5, - DIG_TYPE_DISABLE = 6, - DIG_OP_TYPE_MAX -}; - -enum dm_1r_cca_e { - CCA_1R = 0, - CCA_2R = 1, - CCA_MAX = 2, -}; - -enum dm_rf_e { - RF_SAVE = 0, - RF_NORMAL = 1, - RF_MAX = 2, -}; - -enum dm_sw_ant_switch_e { - ANS_ANTENNA_B = 1, - ANS_ANTENNA_A = 2, - ANS_ANTENNA_MAX = 3, -}; - -enum pwr_track_control_method { - BBSWING, - TXAGC, - MIX_MODE -}; - -#define BT_RSSI_STATE_NORMAL_POWER BIT_OFFSET_LEN_MASK_32(0, 1) -#define BT_RSSI_STATE_AMDPU_OFF BIT_OFFSET_LEN_MASK_32(1, 1) -#define BT_RSSI_STATE_SPECIAL_LOW BIT_OFFSET_LEN_MASK_32(2, 1) -#define BT_RSSI_STATE_BG_EDCA_LOW BIT_OFFSET_LEN_MASK_32(3, 1) -#define BT_RSSI_STATE_TXPOWER_LOW BIT_OFFSET_LEN_MASK_32(4, 1) -#define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ - ((((struct rtl_priv *)(_priv))->mac80211.opmode == \ - NL80211_IFTYPE_ADHOC) ? \ - (((struct rtl_priv *)(_priv))->dm.entry_min_undec_sm_pwdb) : \ - (((struct rtl_priv *)(_priv))->dm.undec_sm_pwdb)) - -void rtl8821ae_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw, - u8 *pdesc, u32 mac_id); -void rtl8821ae_dm_ant_sel_statistics(struct ieee80211_hw *hw, - u8 antsel_tr_mux, u32 mac_id, - u32 rx_pwdb_all); -void rtl8821ae_dm_fast_antenna_training_callback(unsigned long data); -void rtl8821ae_dm_init(struct ieee80211_hw *hw); -void rtl8821ae_dm_watchdog(struct ieee80211_hw *hw); -void rtl8821ae_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi); -void rtl8821ae_dm_init_edca_turbo(struct ieee80211_hw *hw); -void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw); -void rtl8821ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); -void rtl8821ae_dm_txpower_track_adjust(struct ieee80211_hw *hw, - u8 type, u8 *pdirection, - u32 *poutwrite_val); -void rtl8821ae_dm_clear_txpower_tracking_state(struct ieee80211_hw *hw); -void rtl8821ae_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 current_cca); -void rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(struct ieee80211_hw *hw); -void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw, - enum pwr_track_control_method method, - u8 rf_path, - u8 channel_mapped_index); -void rtl8821ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw, - enum pwr_track_control_method method, - u8 rf_path, u8 channel_mapped_index); - -void rtl8821ae_dm_update_init_rate(struct ieee80211_hw *hw, u8 rate); -u8 rtl8821ae_hw_rate_to_mrate(struct ieee80211_hw *hw, u8 rate); -void rtl8812ae_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw *hw); -void rtl8821ae_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/fw.c b/drivers/net/wireless/rtlwifi/rtl8821ae/fw.c deleted file mode 100644 index 525eb234627c..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/fw.c +++ /dev/null @@ -1,1857 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../core.h" -#include "reg.h" -#include "def.h" -#include "fw.h" -#include "dm.h" - -static void _rtl8821ae_enable_fw_download(struct ieee80211_hw *hw, bool enable) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp; - - if (enable) { - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05); - - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); - rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); - - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); - } else { - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); - rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); - tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); - } -} - -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) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 *bufferptr = (u8 *)buffer; - u32 pagenums, remainsize; - u32 page, offset; - - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "FW size is %d bytes,\n", size); - - _rtl8821ae_fill_dummy(bufferptr, &size); - - pagenums = size / FW_8821AE_PAGE_SIZE; - remainsize = size % FW_8821AE_PAGE_SIZE; - - if (pagenums > 8) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Page numbers should not greater then 8\n"); - } - - for (page = 0; page < pagenums; page++) { - offset = page * FW_8821AE_PAGE_SIZE; - _rtl8821ae_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); - } -} - -static int _rtl8821ae_fw_free_to_go(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int err = -EIO; - u32 counter = 0; - u32 value32; - - do { - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - } while ((counter++ < FW_8821AE_POLLING_TIMEOUT_COUNT) && - (!(value32 & FWDL_CHKSUM_RPT))); - - if (counter >= FW_8821AE_POLLING_TIMEOUT_COUNT) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "chksum report faill ! REG_MCUFWDL:0x%08x .\n", - value32); - goto exit; - } - - RT_TRACE(rtlpriv, COMP_FW, DBG_EMERG, - "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32); - - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - value32 |= MCUFWDL_RDY; - value32 &= ~WINTINI_RDY; - rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); - - rtl8821ae_firmware_selfreset(hw); - - counter = 0; - do { - value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); - if (value32 & WINTINI_RDY) { - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n", - value32); - err = 0; - goto exit; - } - - udelay(FW_8821AE_POLLING_DELAY); - } while (counter++ < FW_8821AE_POLLING_TIMEOUT_COUNT); - - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", - value32); - -exit: - return err; -} - -static void _rtl8821ae_wait_for_h2c_cmd_finish(struct rtl_priv *rtlpriv) -{ - u8 val; - u16 count = 0; - - do { - val = rtl_read_byte(rtlpriv, REG_HMETFR); - mdelay(1); - count++; - } while ((val & 0x0F) && (count < 1000)); -} - -int rtl8821ae_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtlwifi_firmware_header *pfwheader; - u8 *pfwdata; - u32 fwsize; - int err; - bool support_remote_wakeup; - enum version_8821ae version = rtlhal->version; - - rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, - (u8 *)(&support_remote_wakeup)); - - if (support_remote_wakeup) - _rtl8821ae_wait_for_h2c_cmd_finish(rtlpriv); - - if (buse_wake_on_wlan_fw) { - if (!rtlhal->wowlan_firmware) - return 1; - - pfwheader = - (struct rtlwifi_firmware_header *)rtlhal->wowlan_firmware; - rtlhal->fw_version = le16_to_cpu(pfwheader->version); - rtlhal->fw_subversion = pfwheader->subversion; - pfwdata = (u8 *)rtlhal->wowlan_firmware; - fwsize = rtlhal->wowlan_fwsize; - } else { - if (!rtlhal->pfirmware) - return 1; - - pfwheader = - (struct rtlwifi_firmware_header *)rtlhal->pfirmware; - rtlhal->fw_version = le16_to_cpu(pfwheader->version); - rtlhal->fw_subversion = pfwheader->subversion; - pfwdata = (u8 *)rtlhal->pfirmware; - fwsize = rtlhal->fwsize; - } - - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "%s Firmware SIZE %d\n", - buse_wake_on_wlan_fw ? "Wowlan" : "Normal", fwsize); - - if (IS_FW_HEADER_EXIST_8812(pfwheader) || - IS_FW_HEADER_EXIST_8821(pfwheader)) { - RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, - "Firmware Version(%d), Signature(%#x)\n", - pfwheader->version, pfwheader->signature); - - pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); - fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); - } - - if (rtlhal->mac_func_enable) { - if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); - rtl8821ae_firmware_selfreset(hw); - } - } - _rtl8821ae_enable_fw_download(hw, true); - _rtl8821ae_write_fw(hw, version, pfwdata, fwsize); - _rtl8821ae_enable_fw_download(hw, false); - - err = _rtl8821ae_fw_free_to_go(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Firmware is not ready to run!\n"); - } else { - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "Firmware is ready to run!\n"); - } - - return 0; -} - -#if (USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN == 1) -void rtl8821ae_set_fw_related_for_wowlan(struct ieee80211_hw *hw, - bool used_wowlan_fw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - /* 1. Before WoWLAN or After WOWLAN we need to re-download Fw. */ - if (rtl8821ae_download_fw(hw, used_wowlan_fw)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Re-Download Firmware failed!!\n"); - rtlhal->fw_ready = false; - return; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Re-Download Firmware Success !!\n"); - rtlhal->fw_ready = true; - - /* 2. Re-Init the variables about Fw related setting. */ - ppsc->fw_current_inpsmode = false; - rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_8821AE; - rtlhal->fw_clk_change_in_progress = false; - rtlhal->allow_sw_to_change_hwclc = false; - rtlhal->last_hmeboxnum = 0; -} -#endif - -static bool _rtl8821ae_check_fw_read_last_h2c(struct ieee80211_hw *hw, - u8 boxnum) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 val_hmetfr; - bool result = false; - - val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); - if (((val_hmetfr >> boxnum) & BIT(0)) == 0) - result = true; - return result; -} - -static void _rtl8821ae_fill_h2c_command(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, - u8 *cmdbuffer) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 boxnum = 0; - u16 box_reg = 0, box_extreg = 0; - u8 u1b_tmp = 0; - bool isfw_read = false; - u8 buf_index = 0; - bool bwrite_sucess = false; - u8 wait_h2c_limmit = 100; - /*u8 wait_writeh2c_limmit = 100;*/ - u8 boxcontent[4], boxextcontent[4]; - u32 h2c_waitcounter = 0; - unsigned long flag = 0; - u8 idx = 0; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n"); - - while (true) { - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - if (rtlhal->h2c_setinprogress) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C set in progress! Wait to set..element_id(%d).\n", - element_id); - - while (rtlhal->h2c_setinprogress) { - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, - flag); - h2c_waitcounter++; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Wait 100 us (%d times)...\n", - h2c_waitcounter); - udelay(100); - - if (h2c_waitcounter > 1000) - return; - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, - flag); - } - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - } else { - rtlhal->h2c_setinprogress = true; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - break; - } - } - - while (!bwrite_sucess) { - boxnum = rtlhal->last_hmeboxnum; - switch (boxnum) { - case 0: - box_reg = REG_HMEBOX_0; - box_extreg = REG_HMEBOX_EXT_0; - break; - case 1: - box_reg = REG_HMEBOX_1; - box_extreg = REG_HMEBOX_EXT_1; - break; - case 2: - box_reg = REG_HMEBOX_2; - box_extreg = REG_HMEBOX_EXT_2; - break; - case 3: - box_reg = REG_HMEBOX_3; - box_extreg = REG_HMEBOX_EXT_3; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - - isfw_read = false; - u1b_tmp = rtl_read_byte(rtlpriv, REG_CR); - - if (u1b_tmp != 0xEA) { - isfw_read = true; - } else { - if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xEA || - rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xEA) - rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xFF); - } - - if (isfw_read) { - wait_h2c_limmit = 100; - isfw_read = - _rtl8821ae_check_fw_read_last_h2c(hw, boxnum); - while (!isfw_read) { - /*wait until Fw read*/ - wait_h2c_limmit--; - if (wait_h2c_limmit == 0) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Waiting too long for FW read clear HMEBox(%d)!\n", - boxnum); - break; - } - - udelay(10); - - isfw_read = - _rtl8821ae_check_fw_read_last_h2c(hw, boxnum); - u1b_tmp = rtl_read_byte(rtlpriv, 0x130); - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n", - boxnum, u1b_tmp); - } - } - - if (!isfw_read) { - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n", - boxnum); - break; - } - - memset(boxcontent, 0, sizeof(boxcontent)); - memset(boxextcontent, 0, sizeof(boxextcontent)); - boxcontent[0] = element_id; - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "Write element_id box_reg(%4x) = %2x\n", - box_reg, element_id); - - switch (cmd_len) { - case 1: - case 2: - case 3: - /*boxcontent[0] &= ~(BIT(7));*/ - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index, cmd_len); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - case 4: - case 5: - case 6: - case 7: - /*boxcontent[0] |= (BIT(7));*/ - memcpy((u8 *)(boxextcontent), - cmdbuffer + buf_index+3, cmd_len-3); - memcpy((u8 *)(boxcontent) + 1, - cmdbuffer + buf_index, 3); - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_extreg + idx, - boxextcontent[idx]); - } - - for (idx = 0; idx < 4; idx++) { - rtl_write_byte(rtlpriv, box_reg + idx, - boxcontent[idx]); - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - - bwrite_sucess = true; - - rtlhal->last_hmeboxnum = boxnum + 1; - if (rtlhal->last_hmeboxnum == 4) - rtlhal->last_hmeboxnum = 0; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, - "pHalData->last_hmeboxnum = %d\n", - rtlhal->last_hmeboxnum); - } - - spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); - rtlhal->h2c_setinprogress = false; - spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); - - RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n"); -} - -void rtl8821ae_fill_h2c_cmd(struct ieee80211_hw *hw, - u8 element_id, u32 cmd_len, u8 *cmdbuffer) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 tmp_cmdbuf[2]; - - if (!rtlhal->fw_ready) { - RT_ASSERT(false, - "return H2C cmd because of Fw download fail!!!\n"); - return; - } - - memset(tmp_cmdbuf, 0, 8); - memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); - _rtl8821ae_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); -} - -void rtl8821ae_firmware_selfreset(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 u1b_tmp; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp & (~BIT(3)))); - } else { - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp & (~BIT(0)))); - } - - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); - udelay(50); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp | BIT(3))); - } else { - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL+1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL+1, (u1b_tmp | BIT(0))); - } - - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp | BIT(2))); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "_8051Reset8812ae(): 8051 reset success .\n"); -} - -void rtl8821ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 u1_h2c_set_pwrmode[H2C_8821AE_PWEMODE_LENGTH] = { 0 }; - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 rlbm, power_state = 0; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode); - - SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0)); - rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/ - SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm); - SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, - (rtlpriv->mac80211.p2p) ? - ppsc->smart_ps : 1); - SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode, - ppsc->reg_max_lps_awakeintvl); - SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0); - if (mode == FW_PS_ACTIVE_MODE) - power_state |= FW_PWR_STATE_ACTIVE; - else - power_state |= FW_PWR_STATE_RF_OFF; - - SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state); - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n", - u1_h2c_set_pwrmode, H2C_8821AE_PWEMODE_LENGTH); - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_SETPWRMODE, - H2C_8821AE_PWEMODE_LENGTH, - u1_h2c_set_pwrmode); -} - -void rtl8821ae_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, - u8 mstatus) -{ - u8 parm[3] = { 0, 0, 0 }; - /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect - * bit1=0-->update Media Status to MACID - * bit1=1-->update Media Status from MACID to MACID_End - * parm[1]: MACID, if this is INFRA_STA, MacID = 0 - * parm[2]: MACID_End - */ - - SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus); - SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0); - - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_MSRRPT, 3, parm); -} - -void rtl8821ae_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, - u8 ap_offload_enable) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 u1_apoffload_parm[H2C_8821AE_AP_OFFLOAD_LENGTH] = { 0 }; - - SET_H2CCMD_AP_OFFLOAD_ON(u1_apoffload_parm, ap_offload_enable); - SET_H2CCMD_AP_OFFLOAD_HIDDEN(u1_apoffload_parm, mac->hiddenssid); - SET_H2CCMD_AP_OFFLOAD_DENYANY(u1_apoffload_parm, 0); - - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_AP_OFFLOAD, - H2C_8821AE_AP_OFFLOAD_LENGTH, - u1_apoffload_parm); -} - -void rtl8821ae_set_fw_wowlan_mode(struct ieee80211_hw *hw, bool func_en) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - u8 fw_wowlan_info[H2C_8821AE_WOWLAN_LENGTH] = {0}; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "enable(%d)\n", func_en); - - SET_8812_H2CCMD_WOWLAN_FUNC_ENABLE(fw_wowlan_info, - (func_en ? true : false)); - - SET_8812_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(fw_wowlan_info, - ((ppsc->wo_wlan_mode & WAKE_ON_PATTERN_MATCH) ? 1 : 0)); - SET_8812_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(fw_wowlan_info, - ((ppsc->wo_wlan_mode & WAKE_ON_MAGIC_PACKET) ? 1 : 0)); - - SET_8812_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(fw_wowlan_info, 0); - SET_8812_H2CCMD_WOWLAN_ALL_PKT_DROP(fw_wowlan_info, false); - SET_8812_H2CCMD_WOWLAN_GPIO_ACTIVE(fw_wowlan_info, 0); - SET_8812_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(fw_wowlan_info, 1); - SET_8812_H2CCMD_WOWLAN_GPIONUM(fw_wowlan_info, 0); - SET_8812_H2CCMD_WOWLAN_GPIO_DURATION(fw_wowlan_info, 0); - - RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_DMESG, - "wowlan mode: cmd 0x80: Content:\n", - fw_wowlan_info, H2C_8821AE_WOWLAN_LENGTH); - - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_WO_WLAN, - H2C_8821AE_WOWLAN_LENGTH, - fw_wowlan_info); -} - -void rtl8821ae_set_fw_remote_wake_ctrl_cmd(struct ieee80211_hw *hw, - u8 enable) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 remote_wake_ctrl_parm[H2C_8821AE_REMOTE_WAKE_CTRL_LEN] = {0}; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "enable=%d, ARP offload=%d, GTK offload=%d\n", - enable, ppsc->arp_offload_enable, ppsc->gtk_offload_enable); - - SET_8812_H2CCMD_REMOTE_WAKECTRL_ENABLE(remote_wake_ctrl_parm, enable); - SET_8812_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(remote_wake_ctrl_parm, - (ppsc->arp_offload_enable ? 1 : 0)); - SET_8812_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(remote_wake_ctrl_parm, - (ppsc->gtk_offload_enable ? 1 : 0)); - SET_8812_H2CCMD_REMOTE_WAKE_CTRL_REALWOWV2_EN(remote_wake_ctrl_parm, - (rtlhal->real_wow_v2_enable ? 1 : 0)); - - RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, - "remote_wake_ctrl: cmd 0x4: Content:\n", - remote_wake_ctrl_parm, H2C_8821AE_REMOTE_WAKE_CTRL_LEN); - - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_REMOTE_WAKE_CTRL, - H2C_8821AE_REMOTE_WAKE_CTRL_LEN, - remote_wake_ctrl_parm); -} - -void rtl8821ae_set_fw_keep_alive_cmd(struct ieee80211_hw *hw, - bool func_en) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 keep_alive_info[H2C_8821AE_KEEP_ALIVE_CTRL_LENGTH] = {0}; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Enable(%d)\n", func_en); - - SET_8812_H2CCMD_KEEP_ALIVE_ENABLE(keep_alive_info, func_en); - /* 1: the period is controled by driver, 0: by Fw default */ - SET_8812_H2CCMD_KEEP_ALIVE_ACCPEPT_USER_DEFINED(keep_alive_info, 1); - SET_8812_H2CCMD_KEEP_ALIVE_PERIOD(keep_alive_info, 10); /* 10 sec */ - - RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, - "keep alive: cmd 0x3: Content:\n", - keep_alive_info, H2C_8821AE_KEEP_ALIVE_CTRL); - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_KEEP_ALIVE_CTRL, - H2C_8821AE_KEEP_ALIVE_CTRL_LENGTH, - keep_alive_info); -} - -void rtl8821ae_set_fw_disconnect_decision_ctrl_cmd(struct ieee80211_hw *hw, - bool enabled) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 parm[H2C_8821AE_DISCONNECT_DECISION_CTRL_LEN] = {0}; - - SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_ENABLE(parm, enabled); - SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_USER_SETTING(parm, 1); - SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_CHECK_PERIOD(parm, 30); - SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_TRYPKT_NUM(parm, 3); - - RT_PRINT_DATA(rtlpriv, COMP_POWER, DBG_TRACE, - "disconnect_decision_ctrl: cmd 0x4: Content:\n", - parm, H2C_8821AE_DISCONNECT_DECISION_CTRL_LEN); - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_DISCONNECT_DECISION, - H2C_8821AE_DISCONNECT_DECISION_CTRL_LEN, parm); -} - -void rtl8821ae_set_fw_global_info_cmd(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_security *sec = &rtlpriv->sec; - u8 remote_wakeup_sec_info[H2C_8821AE_AOAC_GLOBAL_INFO_LEN] = {0}; - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "PairwiseEncAlgorithm=%d, GroupEncAlgorithm=%d\n", - sec->pairwise_enc_algorithm, sec->group_enc_algorithm); - - SET_8812_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG( - remote_wakeup_sec_info, - sec->pairwise_enc_algorithm); - SET_8812_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(remote_wakeup_sec_info, - sec->group_enc_algorithm); - - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_AOAC_GLOBAL_INFO, - H2C_8821AE_AOAC_GLOBAL_INFO_LEN, - remote_wakeup_sec_info); - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_TRACE, - "rtl8821ae_set_global_info: cmd 0x82:\n", - remote_wakeup_sec_info, H2C_8821AE_AOAC_GLOBAL_INFO_LEN); -} - -#define BEACON_PG 0 -#define PSPOLL_PG 1 -#define NULL_PG 2 -#define QOSNULL_PG 3 -#define ARPRESP_PG 4 -#define REMOTE_PG 5 -#define GTKEXT_PG 6 - -#define TOTAL_RESERVED_PKT_LEN_8812 3584 -#define TOTAL_RESERVED_PKT_LEN_8821 1792 - -static u8 reserved_page_packet_8821[TOTAL_RESERVED_PKT_LEN_8821] = { - /* page 0: beacon */ - 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x00, 0xe0, 0x4c, 0x02, 0xe2, 0x64, - 0x40, 0x16, 0x9f, 0x23, 0xd4, 0x46, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x20, 0x04, 0x00, 0x06, 0x64, 0x6c, - 0x69, 0x6e, 0x6b, 0x31, 0x01, 0x08, 0x82, 0x84, - 0x8b, 0x96, 0x0c, 0x18, 0x30, 0x48, 0x03, 0x01, - 0x0b, 0x06, 0x02, 0x00, 0x00, 0x2a, 0x01, 0x8b, - 0x32, 0x04, 0x12, 0x24, 0x60, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x28, 0x8c, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* page 1: ps-poll */ - 0xa4, 0x10, 0x01, 0xc0, 0x40, 0x16, 0x9f, 0x23, - 0xd4, 0x46, 0x00, 0xe0, 0x4c, 0x02, 0xe2, 0x64, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x28, 0x8c, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* page 2: null data */ - 0x48, 0x01, 0x00, 0x00, 0x40, 0x16, 0x9f, 0x23, - 0xd4, 0x46, 0x00, 0xe0, 0x4c, 0x02, 0xe2, 0x64, - 0x40, 0x16, 0x9f, 0x23, 0xd4, 0x46, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* page 3: qos null data */ - 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3C, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* page 4~6 is for wowlan */ - /* page 4: ARP resp */ - 0x08, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, - 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06, - 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, - 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* page 5: H2C_REMOTE_WAKE_CTRL_INFO */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* page 6: Rsvd GTK extend memory (zero memory) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -static u8 reserved_page_packet_8812[TOTAL_RESERVED_PKT_LEN_8812] = { - /* page 0: beacon */ - 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x60, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x20, 0x04, 0x00, 0x03, 0x32, 0x31, - 0x35, 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x0C, - 0x12, 0x18, 0x24, 0x03, 0x01, 0x01, 0x06, 0x02, - 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32, 0x04, 0x30, - 0x48, 0x60, 0x6C, 0x2D, 0x1A, 0xED, 0x09, 0x03, - 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, - 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C, 0x02, 0x02, - 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* page 1: ps-poll */ - 0xA4, 0x10, 0x09, 0xC0, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* page 2: null data */ - 0x48, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1A, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* page 3: Qos null data */ - 0xC8, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3C, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* page 4~6 is for wowlan */ - /* page 4: ARP resp */ - 0x08, 0x01, 0x00, 0x00, 0x84, 0xC9, 0xB2, 0xA7, - 0xB3, 0x6E, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x84, 0xC9, 0xB2, 0xA7, 0xB3, 0x6E, 0x00, 0x00, - 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06, - 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, - 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xE0, 0x4C, 0x02, 0x51, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* page 5: H2C_REMOTE_WAKE_CTRL_INFO */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* page 6: Rsvd GTK extend memory (zero memory) */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, - bool b_dl_finished, bool dl_whole_packets) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtlpriv); - struct sk_buff *skb = NULL; - u32 totalpacketlen; - bool rtstatus; - u8 u1RsvdPageLoc[5] = { 0 }; - u8 u1RsvdPageLoc2[7] = { 0 }; - bool b_dlok = false; - u8 *beacon; - u8 *p_pspoll; - u8 *nullfunc; - u8 *qosnull; - u8 *arpresp; - - /*--------------------------------------------------------- - * (1) beacon - *--------------------------------------------------------- - */ - beacon = &reserved_page_packet_8812[BEACON_PG * 512]; - SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); - SET_80211_HDR_ADDRESS3(beacon, mac->bssid); - - if (b_dl_finished) { - totalpacketlen = 512 - 40; - goto out; - } - /*------------------------------------------------------- - * (2) ps-poll - *-------------------------------------------------------- - */ - p_pspoll = &reserved_page_packet_8812[PSPOLL_PG * 512]; - SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); - SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); - SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); - - SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); - - /*-------------------------------------------------------- - * (3) null data - *--------------------------------------------------------- - */ - nullfunc = &reserved_page_packet_8812[NULL_PG * 512]; - SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); - SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); - SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); - - /*--------------------------------------------------------- - * (4) Qos null data - *---------------------------------------------------------- - */ - qosnull = &reserved_page_packet_8812[QOSNULL_PG * 512]; - SET_80211_HDR_ADDRESS1(qosnull, mac->bssid); - SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr); - SET_80211_HDR_ADDRESS3(qosnull, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1RsvdPageLoc, QOSNULL_PG); - - if (!dl_whole_packets) { - totalpacketlen = 512 * (QOSNULL_PG + 1) - 40; - goto out; - } - /*--------------------------------------------------------- - * (5) ARP Resp - *---------------------------------------------------------- - */ - arpresp = &reserved_page_packet_8812[ARPRESP_PG * 512]; - SET_80211_HDR_ADDRESS1(arpresp, mac->bssid); - SET_80211_HDR_ADDRESS2(arpresp, mac->mac_addr); - SET_80211_HDR_ADDRESS3(arpresp, mac->bssid); - - SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1RsvdPageLoc2, ARPRESP_PG); - - /*--------------------------------------------------------- - * (6) Remote Wake Ctrl - *---------------------------------------------------------- - */ - SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1RsvdPageLoc2, - REMOTE_PG); - - /*--------------------------------------------------------- - * (7) GTK Ext Memory - *---------------------------------------------------------- - */ - SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1RsvdPageLoc2, GTKEXT_PG); - - totalpacketlen = TOTAL_RESERVED_PKT_LEN_8812 - 40; - -out: - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "rtl8812ae_set_fw_rsvdpagepkt(): packet data\n", - &reserved_page_packet_8812[0], totalpacketlen); - - skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet_8812, totalpacketlen); - - rtstatus = rtl_cmd_send_packet(hw, skb); - - if (rtstatus) - b_dlok = true; - - if (!b_dl_finished && b_dlok) { - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 5); - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_RSVDPAGE, - sizeof(u1RsvdPageLoc), u1RsvdPageLoc); - if (dl_whole_packets) { - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "wowlan H2C_RSVDPAGE:\n", u1RsvdPageLoc2, 7); - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_AOAC_RSVDPAGE, - sizeof(u1RsvdPageLoc2), u1RsvdPageLoc2); - } - } - - if (!b_dlok) - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set RSVD page location to Fw FAIL!!!!!!.\n"); -} - -void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, - bool b_dl_finished, bool dl_whole_packets) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct sk_buff *skb = NULL; - u32 totalpacketlen; - bool rtstatus; - u8 u1RsvdPageLoc[5] = { 0 }; - u8 u1RsvdPageLoc2[7] = { 0 }; - bool b_dlok = false; - u8 *beacon; - u8 *p_pspoll; - u8 *nullfunc; - u8 *qosnull; - u8 *arpresp; - - /*--------------------------------------------------------- - * (1) beacon - *--------------------------------------------------------- - */ - beacon = &reserved_page_packet_8821[BEACON_PG * 256]; - SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); - SET_80211_HDR_ADDRESS3(beacon, mac->bssid); - - if (b_dl_finished) { - totalpacketlen = 256 - 40; - goto out; - } - /*------------------------------------------------------- - * (2) ps-poll - *-------------------------------------------------------- - */ - p_pspoll = &reserved_page_packet_8821[PSPOLL_PG * 256]; - SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); - SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); - SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); - - SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); - - /*-------------------------------------------------------- - * (3) null data - *---------------------------------------------------------i - */ - nullfunc = &reserved_page_packet_8821[NULL_PG * 256]; - SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); - SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); - SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); - - /*--------------------------------------------------------- - * (4) Qos null data - *---------------------------------------------------------- - */ - qosnull = &reserved_page_packet_8821[QOSNULL_PG * 256]; - SET_80211_HDR_ADDRESS1(qosnull, mac->bssid); - SET_80211_HDR_ADDRESS2(qosnull, mac->mac_addr); - SET_80211_HDR_ADDRESS3(qosnull, mac->bssid); - - SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1RsvdPageLoc, QOSNULL_PG); - - if (!dl_whole_packets) { - totalpacketlen = 256 * (QOSNULL_PG + 1) - 40; - goto out; - } - /*--------------------------------------------------------- - * (5) ARP Resp - *---------------------------------------------------------- - */ - arpresp = &reserved_page_packet_8821[ARPRESP_PG * 256]; - SET_80211_HDR_ADDRESS1(arpresp, mac->bssid); - SET_80211_HDR_ADDRESS2(arpresp, mac->mac_addr); - SET_80211_HDR_ADDRESS3(arpresp, mac->bssid); - - SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1RsvdPageLoc2, ARPRESP_PG); - - /*--------------------------------------------------------- - * (6) Remote Wake Ctrl - *---------------------------------------------------------- - */ - SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1RsvdPageLoc2, - REMOTE_PG); - - /*--------------------------------------------------------- - * (7) GTK Ext Memory - *---------------------------------------------------------- - */ - SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1RsvdPageLoc2, GTKEXT_PG); - - totalpacketlen = TOTAL_RESERVED_PKT_LEN_8821 - 40; - -out: - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "rtl8821ae_set_fw_rsvdpagepkt(): packet data\n", - &reserved_page_packet_8821[0], totalpacketlen); - - skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *)skb_put(skb, totalpacketlen), - &reserved_page_packet_8821, totalpacketlen); - - rtstatus = rtl_cmd_send_packet(hw, skb); - - if (rtstatus) - b_dlok = true; - - if (!b_dl_finished && b_dlok) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Set RSVD page location to Fw.\n"); - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 5); - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_RSVDPAGE, - sizeof(u1RsvdPageLoc), u1RsvdPageLoc); - if (dl_whole_packets) { - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, - "wowlan H2C_RSVDPAGE:\n", - u1RsvdPageLoc2, 7); - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_AOAC_RSVDPAGE, - sizeof(u1RsvdPageLoc2), - u1RsvdPageLoc2); - } - } - - if (!b_dlok) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set RSVD page location to Fw FAIL!!!!!!.\n"); - } -} - -/*Should check FW support p2p or not.*/ -static void rtl8821ae_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow) -{ - u8 u1_ctwindow_period[1] = { ctwindow}; - - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_P2P_PS_CTW_CMD, 1, - u1_ctwindow_period); -} - -void rtl8821ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info; - struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload; - u8 i; - u16 ctwindow; - u32 start_time, tsf_low; - - switch (p2p_ps_state) { - case P2P_PS_DISABLE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_DISABLE\n"); - memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload)); - break; - case P2P_PS_ENABLE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_ENABLE\n"); - /* update CTWindow value. */ - if (p2pinfo->ctwindow > 0) { - p2p_ps_offload->ctwindow_en = 1; - ctwindow = p2pinfo->ctwindow; - rtl8821ae_set_p2p_ctw_period_cmd(hw, ctwindow); - } - - /* hw only support 2 set of NoA */ - for (i = 0 ; i < p2pinfo->noa_num ; i++) { - /* To control the register setting for which NOA*/ - rtl_write_byte(rtlpriv, 0x5cf, (i << 4)); - if (i == 0) - p2p_ps_offload->noa0_en = 1; - else - p2p_ps_offload->noa1_en = 1; - - /* config P2P NoA Descriptor Register */ - rtl_write_dword(rtlpriv, 0x5E0, p2pinfo->noa_duration[i]); - rtl_write_dword(rtlpriv, 0x5E4, p2pinfo->noa_interval[i]); - - /*Get Current TSF value */ - tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - - start_time = p2pinfo->noa_start_time[i]; - if (p2pinfo->noa_count_type[i] != 1) { - while (start_time <= (tsf_low+(50*1024))) { - start_time += p2pinfo->noa_interval[i]; - if (p2pinfo->noa_count_type[i] != 255) - p2pinfo->noa_count_type[i]--; - } - } - rtl_write_dword(rtlpriv, 0x5E8, start_time); - rtl_write_dword(rtlpriv, 0x5EC, - p2pinfo->noa_count_type[i]); - } - - if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) { - /* rst p2p circuit */ - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4)); - - p2p_ps_offload->offload_en = 1; - - if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) { - p2p_ps_offload->role = 1; - p2p_ps_offload->allstasleep = 0; - } else { - p2p_ps_offload->role = 0; - } - - p2p_ps_offload->discovery = 0; - } - break; - case P2P_PS_SCAN: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n"); - p2p_ps_offload->discovery = 1; - break; - case P2P_PS_SCAN_DONE: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN_DONE\n"); - p2p_ps_offload->discovery = 0; - p2pinfo->p2p_ps_state = P2P_PS_ENABLE; - break; - default: - break; - } - - rtl8821ae_fill_h2c_cmd(hw, - H2C_8821AE_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload); -} - -static void rtl8821ae_c2h_ra_report_handler(struct ieee80211_hw *hw, - u8 *cmd_buf, u8 cmd_len) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 rate = cmd_buf[0] & 0x3F; - - rtlhal->current_ra_rate = rtl8821ae_hw_rate_to_mrate(hw, rate); - - rtl8821ae_dm_update_init_rate(hw, rate); -} - -static void _rtl8821ae_c2h_content_parsing(struct ieee80211_hw *hw, - u8 c2h_cmd_id, u8 c2h_cmd_len, - u8 *tmp_buf) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - switch (c2h_cmd_id) { - case C2H_8812_DBG: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "[C2H], C2H_8812_DBG!!\n"); - break; - case C2H_8812_RA_RPT: - rtl8821ae_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len); - break; - case C2H_8812_BT_INFO: - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "[C2H], C2H_8812_BT_INFO!!\n"); - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, - tmp_buf, - c2h_cmd_len); - break; - default: - break; - } -} - -void rtl8821ae_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, - u8 length) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0; - u8 *tmp_buf = NULL; - - c2h_cmd_id = buffer[0]; - c2h_cmd_seq = buffer[1]; - c2h_cmd_len = length - 2; - tmp_buf = buffer + 2; - - RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, - "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n", - c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len); - - RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_LOUD, - "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len); - _rtl8821ae_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/fw.h b/drivers/net/wireless/rtlwifi/rtl8821ae/fw.h deleted file mode 100644 index 8f5b4aade3c9..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/fw.h +++ /dev/null @@ -1,332 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8821AE__FW__H__ -#define __RTL8821AE__FW__H__ -#include "def.h" - -#define FW_8821AE_SIZE 0x8000 -#define FW_8821AE_START_ADDRESS 0x1000 -#define FW_8821AE_END_ADDRESS 0x5FFF -#define FW_8821AE_PAGE_SIZE 4096 -#define FW_8821AE_POLLING_DELAY 5 -#define FW_8821AE_POLLING_TIMEOUT_COUNT 6000 - -#define IS_FW_HEADER_EXIST_8812(_pfwhdr) \ - ((le16_to_cpu(_pfwhdr->signature) & 0xFFF0) == 0x9500) - -#define IS_FW_HEADER_EXIST_8821(_pfwhdr) \ - ((le16_to_cpu(_pfwhdr->signature) & 0xFFF0) == 0x2100) - -#define USE_OLD_WOWLAN_DEBUG_FW 0 - -#define H2C_8821AE_RSVDPAGE_LOC_LEN 5 -#define H2C_8821AE_PWEMODE_LENGTH 5 -#define H2C_8821AE_JOINBSSRPT_LENGTH 1 -#define H2C_8821AE_AP_OFFLOAD_LENGTH 3 -#define H2C_8821AE_WOWLAN_LENGTH 3 -#define H2C_8821AE_KEEP_ALIVE_CTRL_LENGTH 3 -#if (USE_OLD_WOWLAN_DEBUG_FW == 0) -#define H2C_8821AE_REMOTE_WAKE_CTRL_LEN 1 -#else -#define H2C_8821AE_REMOTE_WAKE_CTRL_LEN 3 -#endif -#define H2C_8821AE_AOAC_GLOBAL_INFO_LEN 2 -#define H2C_8821AE_AOAC_RSVDPAGE_LOC_LEN 7 -#define H2C_8821AE_DISCONNECT_DECISION_CTRL_LEN 3 - -/* Fw PS state for RPWM. -*BIT[2:0] = HW state - -*BIT[3] = Protocol PS state, -1: register active state , -0: register sleep state - -*BIT[4] = sub-state -*/ -#define FW_PS_GO_ON BIT(0) -#define FW_PS_TX_NULL BIT(1) -#define FW_PS_RF_ON BIT(2) -#define FW_PS_REGISTER_ACTIVE BIT(3) - -#define FW_PS_DPS BIT(0) -#define FW_PS_LCLK (FW_PS_DPS) -#define FW_PS_RF_OFF BIT(1) -#define FW_PS_ALL_ON BIT(2) -#define FW_PS_ST_ACTIVE BIT(3) -#define FW_PS_ISR_ENABLE BIT(4) -#define FW_PS_IMR_ENABLE BIT(5) - -#define FW_PS_ACK BIT(6) -#define FW_PS_TOGGLE BIT(7) - - /* 8821AE RPWM value*/ - /* BIT[0] = 1: 32k, 0: 40M*/ - /* 32k*/ -#define FW_PS_CLOCK_OFF BIT(0) -/*40M*/ -#define FW_PS_CLOCK_ON 0 - -#define FW_PS_STATE_MASK (0x0F) -#define FW_PS_STATE_HW_MASK (0x07) -/*ISR_ENABLE, IMR_ENABLE, and PS mode should be inherited.*/ -#define FW_PS_STATE_INT_MASK (0x3F) - -#define FW_PS_STATE(x) (FW_PS_STATE_MASK & (x)) -#define FW_PS_STATE_HW(x) (FW_PS_STATE_HW_MASK & (x)) -#define FW_PS_STATE_INT(x) (FW_PS_STATE_INT_MASK & (x)) -#define FW_PS_ISR_VAL(x) ((x) & 0x70) -#define FW_PS_IMR_MASK(x) ((x) & 0xDF) -#define FW_PS_KEEP_IMR(x) ((x) & 0x20) - -#define FW_PS_STATE_S0 (FW_PS_DPS) -#define FW_PS_STATE_S1 (FW_PS_LCLK) -#define FW_PS_STATE_S2 (FW_PS_RF_OFF) -#define FW_PS_STATE_S3 (FW_PS_ALL_ON) -#define FW_PS_STATE_S4 ((FW_PS_ST_ACTIVE) | (FW_PS_ALL_ON)) - /* ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE))*/ -#define FW_PS_STATE_ALL_ON_8821AE (FW_PS_CLOCK_ON) - /* (FW_PS_RF_ON)*/ -#define FW_PS_STATE_RF_ON_8821AE (FW_PS_CLOCK_ON) - /* 0x0*/ -#define FW_PS_STATE_RF_OFF_8821AE (FW_PS_CLOCK_ON) - /* (FW_PS_STATE_RF_OFF)*/ -#define FW_PS_STATE_RF_OFF_LOW_PWR_8821AE (FW_PS_CLOCK_OFF) - -#define FW_PS_STATE_ALL_ON_92C (FW_PS_STATE_S4) -#define FW_PS_STATE_RF_ON_92C (FW_PS_STATE_S3) -#define FW_PS_STATE_RF_OFF_92C (FW_PS_STATE_S2) -#define FW_PS_STATE_RF_OFF_LOW_PWR_92C (FW_PS_STATE_S1) - -/* For 8821AE H2C PwrMode Cmd ID 5.*/ -#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) -#define FW_PWR_STATE_RF_OFF 0 - -#define FW_PS_IS_ACK(x) ((x) & FW_PS_ACK) -#define FW_PS_IS_CLK_ON(x) ((x) & (FW_PS_RF_OFF | FW_PS_ALL_ON)) -#define FW_PS_IS_RF_ON(x) ((x) & (FW_PS_ALL_ON)) -#define FW_PS_IS_ACTIVE(x) ((x) & (FW_PS_ST_ACTIVE)) -#define FW_PS_IS_CPWM_INT(x) ((x) & 0x40) - -#define FW_CLR_PS_STATE(x) ((x) = ((x) & (0xF0))) - -#define IS_IN_LOW_POWER_STATE_8821AE(__state) \ - (FW_PS_STATE(__state) == FW_PS_CLOCK_OFF) - -#define FW_PWR_STATE_ACTIVE ((FW_PS_RF_ON) | (FW_PS_REGISTER_ACTIVE)) -#define FW_PWR_STATE_RF_OFF 0 - -enum rtl8812_c2h_evt { - C2H_8812_DBG = 0, - C2H_8812_LB = 1, - C2H_8812_TXBF = 2, - C2H_8812_TX_REPORT = 3, - C2H_8812_BT_INFO = 9, - C2H_8812_BT_MP = 11, - C2H_8812_RA_RPT = 12, - - C2H_8812_FW_SWCHNL = 0x10, - C2H_8812_IQK_FINISH = 0x11, - MAX_8812_C2HEVENT -}; - -enum rtl8821a_h2c_cmd { - H2C_8821AE_RSVDPAGE = 0, - H2C_8821AE_MSRRPT = 1, - H2C_8821AE_SCAN = 2, - H2C_8821AE_KEEP_ALIVE_CTRL = 3, - H2C_8821AE_DISCONNECT_DECISION = 4, - H2C_8821AE_INIT_OFFLOAD = 6, - H2C_8821AE_AP_OFFLOAD = 8, - H2C_8821AE_BCN_RSVDPAGE = 9, - H2C_8821AE_PROBERSP_RSVDPAGE = 10, - - H2C_8821AE_SETPWRMODE = 0x20, - H2C_8821AE_PS_TUNING_PARA = 0x21, - H2C_8821AE_PS_TUNING_PARA2 = 0x22, - H2C_8821AE_PS_LPS_PARA = 0x23, - H2C_8821AE_P2P_PS_OFFLOAD = 024, - - H2C_8821AE_WO_WLAN = 0x80, - H2C_8821AE_REMOTE_WAKE_CTRL = 0x81, - H2C_8821AE_AOAC_GLOBAL_INFO = 0x82, - H2C_8821AE_AOAC_RSVDPAGE = 0x83, - - H2C_RSSI_21AE_REPORT = 0x42, - H2C_8821AE_RA_MASK = 0x40, - H2C_8821AE_SELECTIVE_SUSPEND_ROF_CMD, - H2C_8821AE_P2P_PS_MODE, - H2C_8821AE_PSD_RESULT, - /*Not defined CTW CMD for P2P yet*/ - H2C_8821AE_P2P_PS_CTW_CMD, - MAX_8821AE_H2CCMD -}; - -#define pagenum_128(_len) (u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0)) - -#define SET_8812_H2CCMD_WOWLAN_FUNC_ENABLE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) -#define SET_8812_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) -#define SET_8812_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value) -#define SET_8812_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value) -#define SET_8812_H2CCMD_WOWLAN_ALL_PKT_DROP(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 4, 1, __value) -#define SET_8812_H2CCMD_WOWLAN_GPIO_ACTIVE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 5, 1, __value) -#define SET_8812_H2CCMD_WOWLAN_REKEY_WAKE_UP(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 6, 1, __value) -#define SET_8812_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 7, 1, __value) -#define SET_8812_H2CCMD_WOWLAN_GPIONUM(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd) + 1, 0, 8, __value) -#define SET_8812_H2CCMD_WOWLAN_GPIO_DURATION(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd) + 2, 0, 8, __value) - -#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_PWRMODE_PARM_RLBM(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 4, __value) -#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 4, 4, __value) -#define SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) -#define SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) -#define SET_H2CCMD_PWRMODE_PARM_PWR_STATE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value) -#define GET_8821AE_H2CCMD_PWRMODE_PARM_MODE(__cmd) \ - LE_BITS_TO_1BYTE(__cmd, 0, 8) - -#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val) -#define SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(__ph2ccmd, __val) \ - SET_BITS_TO_LE_1BYTE((__ph2ccmd)+3, 0, 8, __val) - -/* _MEDIA_STATUS_RPT_PARM_CMD1 */ -#define SET_H2CCMD_MSRRPT_PARM_OPMODE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) -#define SET_H2CCMD_MSRRPT_PARM_MACID_IND(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) -#define SET_H2CCMD_MSRRPT_PARM_MACID(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd+1, 0, 8, __value) -#define SET_H2CCMD_MSRRPT_PARM_MACID_END(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd+2, 0, 8, __value) - -/* AP_OFFLOAD */ -#define SET_H2CCMD_AP_OFFLOAD_ON(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value) -#define SET_H2CCMD_AP_OFFLOAD_HIDDEN(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) -#define SET_H2CCMD_AP_OFFLOAD_DENYANY(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) -#define SET_H2CCMD_AP_OFFLOAD_WAKEUP_EVT_RPT(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) - -/* Keep Alive Control*/ -#define SET_8812_H2CCMD_KEEP_ALIVE_ENABLE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) -#define SET_8812_H2CCMD_KEEP_ALIVE_ACCPEPT_USER_DEFINED(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) -#define SET_8812_H2CCMD_KEEP_ALIVE_PERIOD(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) - -/*REMOTE_WAKE_CTRL */ -#define SET_8812_H2CCMD_REMOTE_WAKECTRL_ENABLE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) -#define SET_8812_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(__cmd, __value)\ - SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) -#define SET_8812_H2CCMD_REMOTE_WAKE_CTRL_NDP_OFFLOAD_EN(__cmd, __value)\ - SET_BITS_TO_LE_1BYTE(__cmd, 2, 1, __value) -#define SET_8812_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(__cmd, __value)\ - SET_BITS_TO_LE_1BYTE(__cmd, 3, 1, __value) -#define SET_8812_H2CCMD_REMOTE_WAKE_CTRL_REALWOWV2_EN(__cmd, __value)\ - SET_BITS_TO_LE_1BYTE(__cmd, 6, 1, __value) - -/* GTK_OFFLOAD */ -#define SET_8812_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(__cmd, __value)\ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 8, __value) -#define SET_8812_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) - -/* AOAC_RSVDPAGE_LOC */ -#define SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd), 0, 8, __value) -#define SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) -#define SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(__cmd, __value)\ - SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) -#define SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+3, 0, 8, __value) -#define SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+4, 0, 8, __value) -#define SET_8821AE_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE((__cmd)+5, 0, 8, __value) - -/* Disconnect_Decision_Control */ -#define SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_ENABLE(__cmd, __value) \ - SET_BITS_TO_LE_1BYTE(__cmd, 0, 1, __value) -#define SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_USER_SETTING(__cmd, __value)\ - SET_BITS_TO_LE_1BYTE(__cmd, 1, 1, __value) -#define SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_CHECK_PERIOD(__cmd, __value)\ - SET_BITS_TO_LE_1BYTE((__cmd)+1, 0, 8, __value) /* unit: beacon period */ -#define SET_8812_H2CCMD_DISCONNECT_DECISION_CTRL_TRYPKT_NUM(__cmd, __value)\ - SET_BITS_TO_LE_1BYTE((__cmd)+2, 0, 8, __value) - -int rtl8821ae_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw); -#if (USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN == 1) -void rtl8821ae_set_fw_related_for_wowlan(struct ieee80211_hw *hw, - bool used_wowlan_fw); - -#endif -void rtl8821ae_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *cmdbuffer); -void rtl8821ae_firmware_selfreset(struct ieee80211_hw *hw); -void rtl8821ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); -void rtl8821ae_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, - u8 mstatus); -void rtl8821ae_set_fw_ap_off_load_cmd(struct ieee80211_hw *hw, - u8 ap_offload_enable); -void rtl8821ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, - bool b_dl_finished, bool dl_whole_packet); -void rtl8812ae_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, - bool b_dl_finished, bool dl_whole_packet); -void rtl8821ae_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, - u8 p2p_ps_state); -void rtl8821ae_set_fw_wowlan_mode(struct ieee80211_hw *hw, bool func_en); -void rtl8821ae_set_fw_remote_wake_ctrl_cmd(struct ieee80211_hw *hw, - u8 enable); -void rtl8821ae_set_fw_keep_alive_cmd(struct ieee80211_hw *hw, bool func_en); -void rtl8821ae_set_fw_disconnect_decision_ctrl_cmd(struct ieee80211_hw *hw, - bool enabled); -void rtl8821ae_set_fw_global_info_cmd(struct ieee80211_hw *hw); -void rtl8821ae_c2h_packet_handler(struct ieee80211_hw *hw, - u8 *buffer, u8 length); -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c deleted file mode 100644 index b7f18e2155eb..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c +++ /dev/null @@ -1,4199 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../efuse.h" -#include "../base.h" -#include "../regd.h" -#include "../cam.h" -#include "../ps.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "fw.h" -#include "led.h" -#include "hw.h" -#include "../pwrseqcmd.h" -#include "pwrseq.h" -#include "../btcoexist/rtl_btc.h" - -#define LLT_CONFIG 5 - -static void _rtl8821ae_return_beacon_queue_skb(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[BEACON_QUEUE]; - unsigned long flags; - - spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); - while (skb_queue_len(&ring->queue)) { - struct rtl_tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb = __skb_dequeue(&ring->queue); - - pci_unmap_single(rtlpci->pdev, - rtlpriv->cfg->ops->get_desc( - (u8 *)entry, true, HW_DESC_TXBUFF_ADDR), - skb->len, PCI_DMA_TODEVICE); - kfree_skb(skb); - ring->idx = (ring->idx + 1) % ring->entries; - } - spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); -} - -static void _rtl8821ae_set_bcn_ctrl_reg(struct ieee80211_hw *hw, - u8 set_bits, u8 clear_bits) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpci->reg_bcn_ctrl_val |= set_bits; - rtlpci->reg_bcn_ctrl_val &= ~clear_bits; - - rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); -} - -void _rtl8821ae_stop_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp1byte; - - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); -} - -void _rtl8821ae_resume_tx_beacon(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp1byte; - - tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); - tmp1byte |= BIT(0); - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); -} - -static void _rtl8821ae_enable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(1)); -} - -static void _rtl8821ae_disable_bcn_sub_func(struct ieee80211_hw *hw) -{ - _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(1), 0); -} - -static void _rtl8821ae_set_fw_clock_on(struct ieee80211_hw *hw, - u8 rpwm_val, bool b_need_turn_off_ckk) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool b_support_remote_wake_up; - u32 count = 0, isr_regaddr, content; - bool b_schedule_timer = b_need_turn_off_ckk; - - rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, - (u8 *)(&b_support_remote_wake_up)); - - if (!rtlhal->fw_ready) - return; - if (!rtlpriv->psc.fw_current_inpsmode) - return; - - while (1) { - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - if (rtlhal->fw_clk_change_in_progress) { - while (rtlhal->fw_clk_change_in_progress) { - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - count++; - udelay(100); - if (count > 1000) - goto change_done; - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - } - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - } else { - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - goto change_done; - } - } -change_done: - if (IS_IN_LOW_POWER_STATE_8821AE(rtlhal->fw_ps_state)) { - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - if (FW_PS_IS_ACK(rpwm_val)) { - isr_regaddr = REG_HISR; - content = rtl_read_dword(rtlpriv, isr_regaddr); - while (!(content & IMR_CPWM) && (count < 500)) { - udelay(50); - count++; - content = rtl_read_dword(rtlpriv, isr_regaddr); - } - - if (content & IMR_CPWM) { - rtl_write_word(rtlpriv, isr_regaddr, 0x0100); - rtlhal->fw_ps_state = FW_PS_STATE_RF_ON_8821AE; - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Receive CPWM INT!!! Set rtlhal->FwPSState = %X\n", - rtlhal->fw_ps_state); - } - } - - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - if (b_schedule_timer) - mod_timer(&rtlpriv->works.fw_clockoff_timer, - jiffies + MSECS(10)); - } else { - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - } -} - -static void _rtl8821ae_set_fw_clock_off(struct ieee80211_hw *hw, - u8 rpwm_val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring; - enum rf_pwrstate rtstate; - bool b_schedule_timer = false; - u8 queue; - - if (!rtlhal->fw_ready) - return; - if (!rtlpriv->psc.fw_current_inpsmode) - return; - if (!rtlhal->allow_sw_to_change_hwclc) - return; - rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, (u8 *)(&rtstate)); - if (rtstate == ERFOFF || rtlpriv->psc.inactive_pwrstate == ERFOFF) - return; - - for (queue = 0; queue < RTL_PCI_MAX_TX_QUEUE_COUNT; queue++) { - ring = &rtlpci->tx_ring[queue]; - if (skb_queue_len(&ring->queue)) { - b_schedule_timer = true; - break; - } - } - - if (b_schedule_timer) { - mod_timer(&rtlpriv->works.fw_clockoff_timer, - jiffies + MSECS(10)); - return; - } - - if (FW_PS_STATE(rtlhal->fw_ps_state) != - FW_PS_STATE_RF_OFF_LOW_PWR_8821AE) { - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - if (!rtlhal->fw_clk_change_in_progress) { - rtlhal->fw_clk_change_in_progress = true; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_ps_state = FW_PS_STATE(rpwm_val); - rtl_write_word(rtlpriv, REG_HISR, 0x0100); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - spin_lock_bh(&rtlpriv->locks.fw_ps_lock); - rtlhal->fw_clk_change_in_progress = false; - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - } else { - spin_unlock_bh(&rtlpriv->locks.fw_ps_lock); - mod_timer(&rtlpriv->works.fw_clockoff_timer, - jiffies + MSECS(10)); - } - } -} - -static void _rtl8821ae_set_fw_ps_rf_on(struct ieee80211_hw *hw) -{ - u8 rpwm_val = 0; - - rpwm_val |= (FW_PS_STATE_RF_OFF_8821AE | FW_PS_ACK); - _rtl8821ae_set_fw_clock_on(hw, rpwm_val, true); -} - -static void _rtl8821ae_fwlps_leave(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool fw_current_inps = false; - u8 rpwm_val = 0, fw_pwrmode = FW_PS_ACTIVE_MODE; - - if (ppsc->low_power_enable) { - rpwm_val = (FW_PS_STATE_ALL_ON_8821AE|FW_PS_ACK);/* RF on */ - _rtl8821ae_set_fw_clock_on(hw, rpwm_val, false); - rtlhal->allow_sw_to_change_hwclc = false; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - } else { - rpwm_val = FW_PS_STATE_ALL_ON_8821AE; /* RF on */ - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&fw_pwrmode)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - } -} - -static void _rtl8821ae_fwlps_enter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool fw_current_inps = true; - u8 rpwm_val; - - if (ppsc->low_power_enable) { - rpwm_val = FW_PS_STATE_RF_OFF_LOW_PWR_8821AE; /* RF off */ - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); - rtlhal->allow_sw_to_change_hwclc = true; - _rtl8821ae_set_fw_clock_off(hw, rpwm_val); - } else { - rpwm_val = FW_PS_STATE_RF_OFF_8821AE; /* RF off */ - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_FW_PSMODE_STATUS, - (u8 *)(&fw_current_inps)); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_PWRMODE, - (u8 *)(&ppsc->fwctrl_psmode)); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_SET_RPWM, - (u8 *)(&rpwm_val)); - } -} - -static void _rtl8821ae_download_rsvd_page(struct ieee80211_hw *hw, - bool dl_whole_packets) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 tmp_regcr, tmp_reg422, bcnvalid_reg; - u8 count = 0, dlbcn_count = 0; - bool send_beacon = false; - - tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr | BIT(0))); - - _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(3)); - _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(4), 0); - - tmp_reg422 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, - tmp_reg422 & (~BIT(6))); - if (tmp_reg422 & BIT(6)) - send_beacon = true; - - do { - bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); - rtl_write_byte(rtlpriv, REG_TDECTRL + 2, - (bcnvalid_reg | BIT(0))); - _rtl8821ae_return_beacon_queue_skb(hw); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_set_fw_rsvdpagepkt(hw, false, - dl_whole_packets); - else - rtl8821ae_set_fw_rsvdpagepkt(hw, false, - dl_whole_packets); - - bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); - count = 0; - while (!(bcnvalid_reg & BIT(0)) && count < 20) { - count++; - udelay(10); - bcnvalid_reg = rtl_read_byte(rtlpriv, REG_TDECTRL + 2); - } - dlbcn_count++; - } while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5); - - if (!(bcnvalid_reg & BIT(0))) - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Download RSVD page failed!\n"); - if (bcnvalid_reg & BIT(0) && rtlhal->enter_pnp_sleep) { - rtl_write_byte(rtlpriv, REG_TDECTRL + 2, bcnvalid_reg | BIT(0)); - _rtl8821ae_return_beacon_queue_skb(hw); - if (send_beacon) { - dlbcn_count = 0; - do { - rtl_write_byte(rtlpriv, REG_TDECTRL + 2, - bcnvalid_reg | BIT(0)); - - _rtl8821ae_return_beacon_queue_skb(hw); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_set_fw_rsvdpagepkt(hw, true, - false); - else - rtl8821ae_set_fw_rsvdpagepkt(hw, true, - false); - - /* check rsvd page download OK. */ - bcnvalid_reg = rtl_read_byte(rtlpriv, - REG_TDECTRL + 2); - count = 0; - while (!(bcnvalid_reg & BIT(0)) && count < 20) { - count++; - udelay(10); - bcnvalid_reg = - rtl_read_byte(rtlpriv, - REG_TDECTRL + 2); - } - dlbcn_count++; - } while (!(bcnvalid_reg & BIT(0)) && dlbcn_count < 5); - - if (!(bcnvalid_reg & BIT(0))) - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "2 Download RSVD page failed!\n"); - } - } - - if (bcnvalid_reg & BIT(0)) - rtl_write_byte(rtlpriv, REG_TDECTRL + 2, BIT(0)); - - _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(3), 0); - _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(4)); - - if (send_beacon) - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422); - - if (!rtlhal->enter_pnp_sleep) { - tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr & ~(BIT(0)))); - } -} - -void rtl8821ae_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - - switch (variable) { - case HW_VAR_ETHER_ADDR: - *((u32 *)(val)) = rtl_read_dword(rtlpriv, REG_MACID); - *((u16 *)(val+4)) = rtl_read_word(rtlpriv, REG_MACID + 4); - break; - case HW_VAR_BSSID: - *((u32 *)(val)) = rtl_read_dword(rtlpriv, REG_BSSID); - *((u16 *)(val+4)) = rtl_read_word(rtlpriv, REG_BSSID+4); - break; - case HW_VAR_MEDIA_STATUS: - val[0] = rtl_read_byte(rtlpriv, MSR) & 0x3; - break; - case HW_VAR_SLOT_TIME: - *((u8 *)(val)) = mac->slot_time; - break; - case HW_VAR_BEACON_INTERVAL: - *((u16 *)(val)) = rtl_read_word(rtlpriv, REG_BCN_INTERVAL); - break; - case HW_VAR_ATIM_WINDOW: - *((u16 *)(val)) = rtl_read_word(rtlpriv, REG_ATIMWND); - break; - case HW_VAR_RCR: - *((u32 *)(val)) = rtlpci->receive_config; - break; - case HW_VAR_RF_STATE: - *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; - break; - case HW_VAR_FWLPS_RF_ON:{ - enum rf_pwrstate rfstate; - u32 val_rcr; - - rtlpriv->cfg->ops->get_hw_reg(hw, - HW_VAR_RF_STATE, - (u8 *)(&rfstate)); - if (rfstate == ERFOFF) { - *((bool *)(val)) = true; - } else { - val_rcr = rtl_read_dword(rtlpriv, REG_RCR); - val_rcr &= 0x00070000; - if (val_rcr) - *((bool *)(val)) = false; - else - *((bool *)(val)) = true; - } - break; } - case HW_VAR_FW_PSMODE_STATUS: - *((bool *)(val)) = ppsc->fw_current_inpsmode; - break; - case HW_VAR_CORRECT_TSF:{ - u64 tsf; - u32 *ptsf_low = (u32 *)&tsf; - u32 *ptsf_high = ((u32 *)&tsf) + 1; - - *ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); - *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); - - *((u64 *)(val)) = tsf; - - break; } - case HAL_DEF_WOWLAN: - if (ppsc->wo_wlan_mode) - *((bool *)(val)) = true; - else - *((bool *)(val)) = false; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process %x\n", variable); - break; - } -} - -void rtl8821ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 idx; - - switch (variable) { - case HW_VAR_ETHER_ADDR:{ - for (idx = 0; idx < ETH_ALEN; idx++) { - rtl_write_byte(rtlpriv, (REG_MACID + idx), - val[idx]); - } - break; - } - case HW_VAR_BASIC_RATE:{ - u16 b_rate_cfg = ((u16 *)val)[0]; - b_rate_cfg = b_rate_cfg & 0x15f; - rtl_write_word(rtlpriv, REG_RRSR, b_rate_cfg); - break; - } - case HW_VAR_BSSID:{ - for (idx = 0; idx < ETH_ALEN; idx++) { - rtl_write_byte(rtlpriv, (REG_BSSID + idx), - val[idx]); - } - break; - } - case HW_VAR_SIFS: - rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); - rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[0]); - - rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); - rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); - - rtl_write_byte(rtlpriv, REG_RESP_SIFS_OFDM + 1, val[0]); - rtl_write_byte(rtlpriv, REG_RESP_SIFS_OFDM, val[0]); - break; - case HW_VAR_R2T_SIFS: - rtl_write_byte(rtlpriv, REG_RESP_SIFS_OFDM + 1, val[0]); - break; - case HW_VAR_SLOT_TIME:{ - u8 e_aci; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "HW_VAR_SLOT_TIME %x\n", val[0]); - - rtl_write_byte(rtlpriv, REG_SLOT, val[0]); - - for (e_aci = 0; e_aci < AC_MAX; e_aci++) { - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_AC_PARAM, - (u8 *)(&e_aci)); - } - break; } - case HW_VAR_ACK_PREAMBLE:{ - u8 reg_tmp; - u8 short_preamble = (bool)(*(u8 *)val); - - reg_tmp = rtl_read_byte(rtlpriv, REG_TRXPTCL_CTL+2); - if (short_preamble) { - reg_tmp |= BIT(1); - rtl_write_byte(rtlpriv, REG_TRXPTCL_CTL + 2, - reg_tmp); - } else { - reg_tmp &= (~BIT(1)); - rtl_write_byte(rtlpriv, - REG_TRXPTCL_CTL + 2, - reg_tmp); - } - break; } - case HW_VAR_WPA_CONFIG: - rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *)val)); - break; - case HW_VAR_AMPDU_MIN_SPACE:{ - u8 min_spacing_to_set; - u8 sec_min_space; - - min_spacing_to_set = *((u8 *)val); - if (min_spacing_to_set <= 7) { - sec_min_space = 0; - - if (min_spacing_to_set < sec_min_space) - min_spacing_to_set = sec_min_space; - - mac->min_space_cfg = ((mac->min_space_cfg & - 0xf8) | - min_spacing_to_set); - - *val = min_spacing_to_set; - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", - mac->min_space_cfg); - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - } - break; } - case HW_VAR_SHORTGI_DENSITY:{ - u8 density_to_set; - - density_to_set = *((u8 *)val); - mac->min_space_cfg |= (density_to_set << 3); - - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "Set HW_VAR_SHORTGI_DENSITY: %#x\n", - mac->min_space_cfg); - - rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, - mac->min_space_cfg); - - break; } - case HW_VAR_AMPDU_FACTOR:{ - u32 ampdu_len = (*((u8 *)val)); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - if (ampdu_len < VHT_AGG_SIZE_128K) - ampdu_len = - (0x2000 << (*((u8 *)val))) - 1; - else - ampdu_len = 0x1ffff; - } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - if (ampdu_len < HT_AGG_SIZE_64K) - ampdu_len = - (0x2000 << (*((u8 *)val))) - 1; - else - ampdu_len = 0xffff; - } - ampdu_len |= BIT(31); - - rtl_write_dword(rtlpriv, - REG_AMPDU_MAX_LENGTH_8812, ampdu_len); - break; } - case HW_VAR_AC_PARAM:{ - u8 e_aci = *((u8 *)val); - - rtl8821ae_dm_init_edca_turbo(hw); - if (rtlpci->acm_method != EACMWAY2_SW) - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_ACM_CTRL, - (u8 *)(&e_aci)); - break; } - case HW_VAR_ACM_CTRL:{ - u8 e_aci = *((u8 *)val); - union aci_aifsn *p_aci_aifsn = - (union aci_aifsn *)(&mac->ac[0].aifs); - u8 acm = p_aci_aifsn->f.acm; - u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); - - acm_ctrl = - acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); - - if (acm) { - switch (e_aci) { - case AC0_BE: - acm_ctrl |= ACMHW_BEQEN; - break; - case AC2_VI: - acm_ctrl |= ACMHW_VIQEN; - break; - case AC3_VO: - acm_ctrl |= ACMHW_VOQEN; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", - acm); - break; - } - } else { - switch (e_aci) { - case AC0_BE: - acm_ctrl &= (~ACMHW_BEQEN); - break; - case AC2_VI: - acm_ctrl &= (~ACMHW_VIQEN); - break; - case AC3_VO: - acm_ctrl &= (~ACMHW_VOQEN); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - } - - RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, - "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", - acm_ctrl); - rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); - break; } - case HW_VAR_RCR: - rtl_write_dword(rtlpriv, REG_RCR, ((u32 *)(val))[0]); - rtlpci->receive_config = ((u32 *)(val))[0]; - break; - case HW_VAR_RETRY_LIMIT:{ - u8 retry_limit = ((u8 *)(val))[0]; - - rtl_write_word(rtlpriv, REG_RL, - retry_limit << RETRY_LIMIT_SHORT_SHIFT | - retry_limit << RETRY_LIMIT_LONG_SHIFT); - break; } - case HW_VAR_DUAL_TSF_RST: - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); - break; - case HW_VAR_EFUSE_BYTES: - rtlefuse->efuse_usedbytes = *((u16 *)val); - break; - case HW_VAR_EFUSE_USAGE: - rtlefuse->efuse_usedpercentage = *((u8 *)val); - break; - case HW_VAR_IO_CMD: - rtl8821ae_phy_set_io_cmd(hw, (*(enum io_type *)val)); - break; - case HW_VAR_SET_RPWM:{ - u8 rpwm_val; - - rpwm_val = rtl_read_byte(rtlpriv, REG_PCIE_HRPWM); - udelay(1); - - if (rpwm_val & BIT(7)) { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, - (*(u8 *)val)); - } else { - rtl_write_byte(rtlpriv, REG_PCIE_HRPWM, - ((*(u8 *)val) | BIT(7))); - } - - break; } - case HW_VAR_H2C_FW_PWRMODE: - rtl8821ae_set_fw_pwrmode_cmd(hw, (*(u8 *)val)); - break; - case HW_VAR_FW_PSMODE_STATUS: - ppsc->fw_current_inpsmode = *((bool *)val); - break; - case HW_VAR_INIT_RTS_RATE: - break; - case HW_VAR_RESUME_CLK_ON: - _rtl8821ae_set_fw_ps_rf_on(hw); - break; - case HW_VAR_FW_LPS_ACTION:{ - bool b_enter_fwlps = *((bool *)val); - - if (b_enter_fwlps) - _rtl8821ae_fwlps_enter(hw); - else - _rtl8821ae_fwlps_leave(hw); - break; } - case HW_VAR_H2C_FW_JOINBSSRPT:{ - u8 mstatus = (*(u8 *)val); - - if (mstatus == RT_MEDIA_CONNECT) { - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, - NULL); - _rtl8821ae_download_rsvd_page(hw, false); - } - rtl8821ae_set_fw_media_status_rpt_cmd(hw, mstatus); - - break; } - case HW_VAR_H2C_FW_P2P_PS_OFFLOAD: - rtl8821ae_set_p2p_ps_offload_cmd(hw, (*(u8 *)val)); - break; - case HW_VAR_AID:{ - u16 u2btmp; - u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); - u2btmp &= 0xC000; - rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | - mac->assoc_id)); - break; } - case HW_VAR_CORRECT_TSF:{ - u8 btype_ibss = ((u8 *)(val))[0]; - - if (btype_ibss) - _rtl8821ae_stop_tx_beacon(hw); - - _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(3)); - - rtl_write_dword(rtlpriv, REG_TSFTR, - (u32)(mac->tsf & 0xffffffff)); - rtl_write_dword(rtlpriv, REG_TSFTR + 4, - (u32)((mac->tsf >> 32) & 0xffffffff)); - - _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(3), 0); - - if (btype_ibss) - _rtl8821ae_resume_tx_beacon(hw); - break; } - case HW_VAR_NAV_UPPER: { - u32 us_nav_upper = ((u32)*val); - - if (us_nav_upper > HAL_92C_NAV_UPPER_UNIT * 0xFF) { - RT_TRACE(rtlpriv, COMP_INIT , DBG_WARNING, - "The setting value (0x%08X us) of NAV_UPPER is larger than (%d * 0xFF)!!!\n", - us_nav_upper, HAL_92C_NAV_UPPER_UNIT); - break; - } - rtl_write_byte(rtlpriv, REG_NAV_UPPER, - ((u8)((us_nav_upper + - HAL_92C_NAV_UPPER_UNIT - 1) / - HAL_92C_NAV_UPPER_UNIT))); - break; } - case HW_VAR_KEEP_ALIVE: { - u8 array[2]; - array[0] = 0xff; - array[1] = *((u8 *)val); - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_KEEP_ALIVE_CTRL, 2, - array); - break; } - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process %x\n", variable); - break; - } -} - -static bool _rtl8821ae_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - bool status = true; - long count = 0; - u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) | - _LLT_OP(_LLT_WRITE_ACCESS); - - rtl_write_dword(rtlpriv, REG_LLT_INIT, value); - - do { - value = rtl_read_dword(rtlpriv, REG_LLT_INIT); - if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) - break; - - if (count > POLLING_LLT_THRESHOLD) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to polling write LLT done at address %d!\n", - address); - status = false; - break; - } - } while (++count); - - return status; -} - -static bool _rtl8821ae_llt_table_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - unsigned short i; - u8 txpktbuf_bndy; - u32 rqpn; - u8 maxpage; - bool status; - - maxpage = 255; - txpktbuf_bndy = 0xF8; - rqpn = 0x80e70808; - if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE) { - txpktbuf_bndy = 0xFA; - rqpn = 0x80e90808; - } - - rtl_write_byte(rtlpriv, REG_TRXFF_BNDY, txpktbuf_bndy); - rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, MAX_RX_DMA_BUFFER_SIZE - 1); - - rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); - rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); - - rtl_write_byte(rtlpriv, REG_PBP, 0x31); - rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); - - for (i = 0; i < (txpktbuf_bndy - 1); i++) { - status = _rtl8821ae_llt_write(hw, i, i + 1); - if (!status) - return status; - } - - status = _rtl8821ae_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); - if (!status) - return status; - - for (i = txpktbuf_bndy; i < maxpage; i++) { - status = _rtl8821ae_llt_write(hw, i, (i + 1)); - if (!status) - return status; - } - - status = _rtl8821ae_llt_write(hw, maxpage, txpktbuf_bndy); - if (!status) - return status; - - rtl_write_dword(rtlpriv, REG_RQPN, rqpn); - - rtl_write_byte(rtlpriv, REG_RQPN_NPQ, 0x00); - - return true; -} - -static void _rtl8821ae_gen_refresh_led_state(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_led *pled0 = &pcipriv->ledctl.sw_led0; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - if (rtlpriv->rtlhal.up_first_time) - return; - - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_sw_led_on(hw, pled0); - else - rtl8821ae_sw_led_on(hw, pled0); - else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_sw_led_on(hw, pled0); - else - rtl8821ae_sw_led_on(hw, pled0); - else - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_sw_led_off(hw, pled0); - else - rtl8821ae_sw_led_off(hw, pled0); -} - -static bool _rtl8821ae_init_mac(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - u8 bytetmp = 0; - u16 wordtmp = 0; - bool mac_func_enable = rtlhal->mac_func_enable; - - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); - - /*Auto Power Down to CHIP-off State*/ - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) & (~BIT(7)); - rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - /* HW Power on sequence*/ - if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, - PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, - RTL8812_NIC_ENABLE_FLOW)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "init 8812 MAC Fail as power on failure\n"); - return false; - } - } else { - /* HW Power on sequence */ - if (!rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_A_MSK, - PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK, - RTL8821A_NIC_ENABLE_FLOW)){ - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "init 8821 MAC Fail as power on failure\n"); - return false; - } - } - - bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO) | BIT(4); - rtl_write_byte(rtlpriv, REG_APS_FSMCO, bytetmp); - - bytetmp = rtl_read_byte(rtlpriv, REG_CR); - bytetmp = 0xff; - rtl_write_byte(rtlpriv, REG_CR, bytetmp); - mdelay(2); - - bytetmp = 0xff; - rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, bytetmp); - mdelay(2); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - bytetmp = rtl_read_byte(rtlpriv, REG_SYS_CFG + 3); - if (bytetmp & BIT(0)) { - bytetmp = rtl_read_byte(rtlpriv, 0x7c); - bytetmp |= BIT(6); - rtl_write_byte(rtlpriv, 0x7c, bytetmp); - } - } - - bytetmp = rtl_read_byte(rtlpriv, REG_GPIO_MUXCFG + 1); - bytetmp &= ~BIT(4); - rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG + 1, bytetmp); - - rtl_write_word(rtlpriv, REG_CR, 0x2ff); - - if (!mac_func_enable) { - if (!_rtl8821ae_llt_table_init(hw)) - return false; - } - - rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); - rtl_write_dword(rtlpriv, REG_HISRE, 0xffffffff); - - /* Enable FW Beamformer Interrupt */ - bytetmp = rtl_read_byte(rtlpriv, REG_FWIMR + 3); - rtl_write_byte(rtlpriv, REG_FWIMR + 3, bytetmp | BIT(6)); - - wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); - wordtmp &= 0xf; - wordtmp |= 0xF5B1; - rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); - - rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - rtl_write_word(rtlpriv, REG_RXFLTMAP2, 0xFFFF); - /*low address*/ - rtl_write_dword(rtlpriv, REG_BCNQ_DESA, - rtlpci->tx_ring[BEACON_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_MGQ_DESA, - rtlpci->tx_ring[MGNT_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VOQ_DESA, - rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VIQ_DESA, - rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_BEQ_DESA, - rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_BKQ_DESA, - rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_HQ_DESA, - rtlpci->tx_ring[HIGH_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_RX_DESA, - rtlpci->rx_ring[RX_MPDU_QUEUE].dma & DMA_BIT_MASK(32)); - - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x77); - - rtl_write_dword(rtlpriv, REG_INT_MIG, 0); - - rtl_write_dword(rtlpriv, REG_MCUTST_1, 0); - - rtl_write_byte(rtlpriv, REG_SECONDARY_CCA_CTRL, 0x3); - _rtl8821ae_gen_refresh_led_state(hw); - - return true; -} - -static void _rtl8821ae_hw_configure(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u32 reg_rrsr; - - reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; - - rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr); - /* ARFB table 9 for 11ac 5G 2SS */ - rtl_write_dword(rtlpriv, REG_ARFR0 + 4, 0xfffff000); - /* ARFB table 10 for 11ac 5G 1SS */ - rtl_write_dword(rtlpriv, REG_ARFR1 + 4, 0x003ff000); - /* ARFB table 11 for 11ac 24G 1SS */ - rtl_write_dword(rtlpriv, REG_ARFR2, 0x00000015); - rtl_write_dword(rtlpriv, REG_ARFR2 + 4, 0x003ff000); - /* ARFB table 12 for 11ac 24G 1SS */ - rtl_write_dword(rtlpriv, REG_ARFR3, 0x00000015); - rtl_write_dword(rtlpriv, REG_ARFR3 + 4, 0xffcff000); - /* 0x420[7] = 0 , enable retry AMPDU in new AMPD not singal MPDU. */ - rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F00); - rtl_write_byte(rtlpriv, REG_AMPDU_MAX_TIME, 0x70); - - /*Set retry limit*/ - rtl_write_word(rtlpriv, REG_RL, 0x0707); - - /* Set Data / Response auto rate fallack retry count*/ - rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); - rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); - rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); - - rtlpci->reg_bcn_ctrl_val = 0x1d; - rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); - - /* TBTT prohibit hold time. Suggested by designer TimChen. */ - rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); - - /* AGGR_BK_TIME Reg51A 0x16 */ - rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040); - - /*For Rx TP. Suggested by SD1 Richard. Added by tynli. 2010.04.12.*/ - rtl_write_dword(rtlpriv, REG_FAST_EDCA_CTRL, 0x03086666); - - rtl_write_byte(rtlpriv, REG_HT_SINGLE_AMPDU, 0x80); - rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x20); - rtl_write_word(rtlpriv, REG_MAX_AGGR_NUM, 0x1F1F); -} - -static u16 _rtl8821ae_mdio_read(struct rtl_priv *rtlpriv, u8 addr) -{ - u16 ret = 0; - u8 tmp = 0, count = 0; - - rtl_write_byte(rtlpriv, REG_MDIO_CTL, addr | BIT(6)); - tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(6); - count = 0; - while (tmp && count < 20) { - udelay(10); - tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(6); - count++; - } - if (0 == tmp) - ret = rtl_read_word(rtlpriv, REG_MDIO_RDATA); - - return ret; -} - -static void _rtl8821ae_mdio_write(struct rtl_priv *rtlpriv, u8 addr, u16 data) -{ - u8 tmp = 0, count = 0; - - rtl_write_word(rtlpriv, REG_MDIO_WDATA, data); - rtl_write_byte(rtlpriv, REG_MDIO_CTL, addr | BIT(5)); - tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(5); - count = 0; - while (tmp && count < 20) { - udelay(10); - tmp = rtl_read_byte(rtlpriv, REG_MDIO_CTL) & BIT(5); - count++; - } -} - -static u8 _rtl8821ae_dbi_read(struct rtl_priv *rtlpriv, u16 addr) -{ - u16 read_addr = addr & 0xfffc; - u8 tmp = 0, count = 0, ret = 0; - - rtl_write_word(rtlpriv, REG_DBI_ADDR, read_addr); - rtl_write_byte(rtlpriv, REG_DBI_FLAG, 0x2); - tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); - count = 0; - while (tmp && count < 20) { - udelay(10); - tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); - count++; - } - if (0 == tmp) { - read_addr = REG_DBI_RDATA + addr % 4; - ret = rtl_read_word(rtlpriv, read_addr); - } - return ret; -} - -static void _rtl8821ae_dbi_write(struct rtl_priv *rtlpriv, u16 addr, u8 data) -{ - u8 tmp = 0, count = 0; - u16 wrtie_addr, remainder = addr % 4; - - wrtie_addr = REG_DBI_WDATA + remainder; - rtl_write_byte(rtlpriv, wrtie_addr, data); - - wrtie_addr = (addr & 0xfffc) | (BIT(0) << (remainder + 12)); - rtl_write_word(rtlpriv, REG_DBI_ADDR, wrtie_addr); - - rtl_write_byte(rtlpriv, REG_DBI_FLAG, 0x1); - - tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); - count = 0; - while (tmp && count < 20) { - udelay(10); - tmp = rtl_read_byte(rtlpriv, REG_DBI_FLAG); - count++; - } -} - -static void _rtl8821ae_enable_aspm_back_door(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - if (_rtl8821ae_mdio_read(rtlpriv, 0x04) != 0x8544) - _rtl8821ae_mdio_write(rtlpriv, 0x04, 0x8544); - - if (_rtl8821ae_mdio_read(rtlpriv, 0x0b) != 0x0070) - _rtl8821ae_mdio_write(rtlpriv, 0x0b, 0x0070); - } - - tmp = _rtl8821ae_dbi_read(rtlpriv, 0x70f); - _rtl8821ae_dbi_write(rtlpriv, 0x70f, tmp | BIT(7)); - - tmp = _rtl8821ae_dbi_read(rtlpriv, 0x719); - _rtl8821ae_dbi_write(rtlpriv, 0x719, tmp | BIT(3) | BIT(4)); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - tmp = _rtl8821ae_dbi_read(rtlpriv, 0x718); - _rtl8821ae_dbi_write(rtlpriv, 0x718, tmp|BIT(4)); - } -} - -void rtl8821ae_enable_hw_security_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 sec_reg_value; - u8 tmp; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", - rtlpriv->sec.pairwise_enc_algorithm, - rtlpriv->sec.group_enc_algorithm); - - if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "not open hw encryption\n"); - return; - } - - sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; - - if (rtlpriv->sec.use_defaultkey) { - sec_reg_value |= SCR_TXUSEDK; - sec_reg_value |= SCR_RXUSEDK; - } - - sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); - - tmp = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, tmp | BIT(1)); - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "The SECR-value %x\n", sec_reg_value); - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); -} - -/* Static MacID Mapping (cf. Used in MacIdDoStaticMapping) ---------- */ -#define MAC_ID_STATIC_FOR_DEFAULT_PORT 0 -#define MAC_ID_STATIC_FOR_BROADCAST_MULTICAST 1 -#define MAC_ID_STATIC_FOR_BT_CLIENT_START 2 -#define MAC_ID_STATIC_FOR_BT_CLIENT_END 3 -/* ----------------------------------------------------------- */ - -static void rtl8821ae_macid_initialize_mediastatus(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 media_rpt[4] = {RT_MEDIA_CONNECT, 1, - MAC_ID_STATIC_FOR_BROADCAST_MULTICAST, - MAC_ID_STATIC_FOR_BT_CLIENT_END}; - - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_H2C_FW_MEDIASTATUSRPT, media_rpt); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Initialize MacId media status: from %d to %d\n", - MAC_ID_STATIC_FOR_BROADCAST_MULTICAST, - MAC_ID_STATIC_FOR_BT_CLIENT_END); -} - -static bool _rtl8821ae_check_pcie_dma_hang(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp; - - /* write reg 0x350 Bit[26]=1. Enable debug port. */ - tmp = rtl_read_byte(rtlpriv, REG_DBI_CTRL + 3); - if (!(tmp & BIT(2))) { - rtl_write_byte(rtlpriv, REG_DBI_CTRL + 3, (tmp | BIT(2))); - mdelay(100); - } - - /* read reg 0x350 Bit[25] if 1 : RX hang */ - /* read reg 0x350 Bit[24] if 1 : TX hang */ - tmp = rtl_read_byte(rtlpriv, REG_DBI_CTRL + 3); - if ((tmp & BIT(0)) || (tmp & BIT(1))) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "CheckPcieDMAHang8821AE(): true! Reset PCIE DMA!\n"); - return true; - } else { - return false; - } -} - -static bool _rtl8821ae_reset_pcie_interface_dma(struct ieee80211_hw *hw, - bool mac_power_on, - bool in_watchdog) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp; - bool release_mac_rx_pause; - u8 backup_pcie_dma_pause; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); - - /* 1. Disable register write lock. 0x1c[1] = 0 */ - tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL); - tmp &= ~(BIT(1)); - rtl_write_byte(rtlpriv, REG_RSV_CTRL, tmp); - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - /* write 0xCC bit[2] = 1'b1 */ - tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); - tmp |= BIT(2); - rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); - } - - /* 2. Check and pause TRX DMA */ - /* write 0x284 bit[18] = 1'b1 */ - /* write 0x301 = 0xFF */ - tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - if (tmp & BIT(2)) { - /* Already pause before the function for another purpose. */ - release_mac_rx_pause = false; - } else { - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2))); - release_mac_rx_pause = true; - } - backup_pcie_dma_pause = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG + 1); - if (backup_pcie_dma_pause != 0xFF) - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFF); - - if (mac_power_on) { - /* 3. reset TRX function */ - /* write 0x100 = 0x00 */ - rtl_write_byte(rtlpriv, REG_CR, 0); - } - - /* 4. Reset PCIe DMA. 0x3[0] = 0 */ - tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - tmp &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); - - /* 5. Enable PCIe DMA. 0x3[0] = 1 */ - tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); - tmp |= BIT(0); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp); - - if (mac_power_on) { - /* 6. enable TRX function */ - /* write 0x100 = 0xFF */ - rtl_write_byte(rtlpriv, REG_CR, 0xFF); - - /* We should init LLT & RQPN and - * prepare Tx/Rx descrptor address later - * because MAC function is reset.*/ - } - - /* 7. Restore PCIe autoload down bit */ - /* 8812AE does not has the defination. */ - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - /* write 0xF8 bit[17] = 1'b1 */ - tmp = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2); - tmp |= BIT(1); - rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL + 2, tmp); - } - - /* In MAC power on state, BB and RF maybe in ON state, - * if we release TRx DMA here. - * it will cause packets to be started to Tx/Rx, - * so we release Tx/Rx DMA later.*/ - if (!mac_power_on/* || in_watchdog*/) { - /* 8. release TRX DMA */ - /* write 0x284 bit[18] = 1'b0 */ - /* write 0x301 = 0x00 */ - if (release_mac_rx_pause) { - tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, - tmp & (~BIT(2))); - } - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, - backup_pcie_dma_pause); - } - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - /* 9. lock system register */ - /* write 0xCC bit[2] = 1'b0 */ - tmp = rtl_read_byte(rtlpriv, REG_PMC_DBG_CTRL2); - tmp &= ~(BIT(2)); - rtl_write_byte(rtlpriv, REG_PMC_DBG_CTRL2, tmp); - } - return true; -} - -static void _rtl8821ae_get_wakeup_reason(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); - u8 fw_reason = 0; - struct timeval ts; - - fw_reason = rtl_read_byte(rtlpriv, REG_MCUTST_WOWLAN); - - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "WOL Read 0x1c7 = %02X\n", - fw_reason); - - ppsc->wakeup_reason = 0; - - rtlhal->last_suspend_sec = ts.tv_sec; - - switch (fw_reason) { - case FW_WOW_V2_PTK_UPDATE_EVENT: - ppsc->wakeup_reason = WOL_REASON_PTK_UPDATE; - do_gettimeofday(&ts); - ppsc->last_wakeup_time = ts.tv_sec*1000 + ts.tv_usec/1000; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "It's a WOL PTK Key update event!\n"); - break; - case FW_WOW_V2_GTK_UPDATE_EVENT: - ppsc->wakeup_reason = WOL_REASON_GTK_UPDATE; - do_gettimeofday(&ts); - ppsc->last_wakeup_time = ts.tv_sec*1000 + ts.tv_usec/1000; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "It's a WOL GTK Key update event!\n"); - break; - case FW_WOW_V2_DISASSOC_EVENT: - ppsc->wakeup_reason = WOL_REASON_DISASSOC; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "It's a disassociation event!\n"); - break; - case FW_WOW_V2_DEAUTH_EVENT: - ppsc->wakeup_reason = WOL_REASON_DEAUTH; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "It's a deauth event!\n"); - break; - case FW_WOW_V2_FW_DISCONNECT_EVENT: - ppsc->wakeup_reason = WOL_REASON_AP_LOST; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "It's a Fw disconnect decision (AP lost) event!\n"); - break; - case FW_WOW_V2_MAGIC_PKT_EVENT: - ppsc->wakeup_reason = WOL_REASON_MAGIC_PKT; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "It's a magic packet event!\n"); - break; - case FW_WOW_V2_UNICAST_PKT_EVENT: - ppsc->wakeup_reason = WOL_REASON_UNICAST_PKT; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "It's an unicast packet event!\n"); - break; - case FW_WOW_V2_PATTERN_PKT_EVENT: - ppsc->wakeup_reason = WOL_REASON_PATTERN_PKT; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "It's a pattern match event!\n"); - break; - case FW_WOW_V2_RTD3_SSID_MATCH_EVENT: - ppsc->wakeup_reason = WOL_REASON_RTD3_SSID_MATCH; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "It's an RTD3 Ssid match event!\n"); - break; - case FW_WOW_V2_REALWOW_V2_WAKEUPPKT: - ppsc->wakeup_reason = WOL_REASON_REALWOW_V2_WAKEUPPKT; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "It's an RealWoW wake packet event!\n"); - break; - case FW_WOW_V2_REALWOW_V2_ACKLOST: - ppsc->wakeup_reason = WOL_REASON_REALWOW_V2_ACKLOST; - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "It's an RealWoW ack lost event!\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, - "WOL Read 0x1c7 = %02X, Unknown reason!\n", - fw_reason); - break; - } -} - -static void _rtl8821ae_init_trx_desc_hw_address(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - /*low address*/ - rtl_write_dword(rtlpriv, REG_BCNQ_DESA, - rtlpci->tx_ring[BEACON_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_MGQ_DESA, - rtlpci->tx_ring[MGNT_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VOQ_DESA, - rtlpci->tx_ring[VO_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_VIQ_DESA, - rtlpci->tx_ring[VI_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_BEQ_DESA, - rtlpci->tx_ring[BE_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_BKQ_DESA, - rtlpci->tx_ring[BK_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_HQ_DESA, - rtlpci->tx_ring[HIGH_QUEUE].dma & DMA_BIT_MASK(32)); - rtl_write_dword(rtlpriv, REG_RX_DESA, - rtlpci->rx_ring[RX_MPDU_QUEUE].dma & DMA_BIT_MASK(32)); -} - -static bool _rtl8821ae_init_llt_table(struct ieee80211_hw *hw, u32 boundary) -{ - bool status = true; - u32 i; - u32 txpktbuf_bndy = boundary; - u32 last_entry_of_txpktbuf = LAST_ENTRY_OF_TX_PKT_BUFFER; - - for (i = 0 ; i < (txpktbuf_bndy - 1) ; i++) { - status = _rtl8821ae_llt_write(hw, i , i + 1); - if (!status) - return status; - } - - status = _rtl8821ae_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); - if (!status) - return status; - - for (i = txpktbuf_bndy ; i < last_entry_of_txpktbuf ; i++) { - status = _rtl8821ae_llt_write(hw, i, (i + 1)); - if (!status) - return status; - } - - status = _rtl8821ae_llt_write(hw, last_entry_of_txpktbuf, - txpktbuf_bndy); - if (!status) - return status; - - return status; -} - -static bool _rtl8821ae_dynamic_rqpn(struct ieee80211_hw *hw, u32 boundary, - u16 npq_rqpn_value, u32 rqpn_val) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 tmp; - bool ret = true; - u16 count = 0, tmp16; - bool support_remote_wakeup; - - rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, - (u8 *)(&support_remote_wakeup)); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "boundary=%#X, NPQ_RQPNValue=%#X, RQPNValue=%#X\n", - boundary, npq_rqpn_value, rqpn_val); - - /* stop PCIe DMA - * 1. 0x301[7:0] = 0xFE */ - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE); - - /* wait TXFF empty - * 2. polling till 0x41A[15:0]=0x07FF */ - tmp16 = rtl_read_word(rtlpriv, REG_TXPKT_EMPTY); - while ((tmp16 & 0x07FF) != 0x07FF) { - udelay(100); - tmp16 = rtl_read_word(rtlpriv, REG_TXPKT_EMPTY); - count++; - if ((count % 200) == 0) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Tx queue is not empty for 20ms!\n"); - } - if (count >= 1000) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Wait for Tx FIFO empty timeout!\n"); - break; - } - } - - /* TX pause - * 3. reg 0x522=0xFF */ - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); - - /* Wait TX State Machine OK - * 4. polling till reg 0x5FB~0x5F8 = 0x00000000 for 50ms */ - count = 0; - while (rtl_read_byte(rtlpriv, REG_SCH_TXCMD) != 0) { - udelay(100); - count++; - if (count >= 500) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Wait for TX State Machine ready timeout !!\n"); - break; - } - } - - /* stop RX DMA path - * 5. 0x284[18] = 1 - * 6. wait till 0x284[17] == 1 - * wait RX DMA idle */ - count = 0; - tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp | BIT(2))); - do { - tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - udelay(10); - count++; - } while (!(tmp & BIT(1)) && count < 100); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Wait until Rx DMA Idle. count=%d REG[0x286]=0x%x\n", - count, tmp); - - /* reset BB - * 7. 0x02 [0] = 0 */ - tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); - tmp &= ~(BIT(0)); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, tmp); - - /* Reset TRX MAC - * 8. 0x100 = 0x00 - * Delay (1ms) */ - rtl_write_byte(rtlpriv, REG_CR, 0x00); - udelay(1000); - - /* Disable MAC Security Engine - * 9. 0x100 bit[9]=0 */ - tmp = rtl_read_byte(rtlpriv, REG_CR + 1); - tmp &= ~(BIT(1)); - rtl_write_byte(rtlpriv, REG_CR + 1, tmp); - - /* To avoid DD-Tim Circuit hang - * 10. 0x553 bit[5]=1 */ - tmp = rtl_read_byte(rtlpriv, REG_DUAL_TSF_RST); - rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (tmp | BIT(5))); - - /* Enable MAC Security Engine - * 11. 0x100 bit[9]=1 */ - tmp = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, (tmp | BIT(1))); - - /* Enable TRX MAC - * 12. 0x100 = 0xFF - * Delay (1ms) */ - rtl_write_byte(rtlpriv, REG_CR, 0xFF); - udelay(1000); - - /* Enable BB - * 13. 0x02 [0] = 1 */ - tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, (tmp | BIT(0))); - - /* beacon setting - * 14,15. set beacon head page (reg 0x209 and 0x424) */ - rtl_write_byte(rtlpriv, REG_TDECTRL + 1, (u8)boundary); - rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, (u8)boundary); - rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, (u8)boundary); - - /* 16. WMAC_LBK_BF_HD 0x45D[7:0] - * WMAC_LBK_BF_HD */ - rtl_write_byte(rtlpriv, REG_TXPKTBUF_WMAC_LBK_BF_HD, - (u8)boundary); - - rtl_write_word(rtlpriv, REG_TRXFF_BNDY, boundary); - - /* init LLT - * 17. init LLT */ - if (!_rtl8821ae_init_llt_table(hw, boundary)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, - "Failed to init LLT table!\n"); - return false; - } - - /* reallocate RQPN - * 18. reallocate RQPN and init LLT */ - rtl_write_word(rtlpriv, REG_RQPN_NPQ, npq_rqpn_value); - rtl_write_dword(rtlpriv, REG_RQPN, rqpn_val); - - /* release Tx pause - * 19. 0x522=0x00 */ - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); - - /* enable PCIE DMA - * 20. 0x301[7:0] = 0x00 - * 21. 0x284[18] = 0 */ - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x00); - tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, (tmp&~BIT(2))); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "End.\n"); - return ret; -} - -static void _rtl8821ae_simple_initialize_adapter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); - -#if (USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN == 1) - /* Re-download normal Fw. */ - rtl8821ae_set_fw_related_for_wowlan(hw, false); -#endif - - /* Re-Initialize LLT table. */ - if (rtlhal->re_init_llt_table) { - u32 rqpn = 0x80e70808; - u8 rqpn_npq = 0, boundary = 0xF8; - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - rqpn = 0x80e90808; - boundary = 0xFA; - } - if (_rtl8821ae_dynamic_rqpn(hw, boundary, rqpn_npq, rqpn)) - rtlhal->re_init_llt_table = false; - } - - ppsc->rfpwr_state = ERFON; -} - -static void _rtl8821ae_enable_l1off(struct ieee80211_hw *hw) -{ - u8 tmp = 0; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "--->\n"); - - tmp = _rtl8821ae_dbi_read(rtlpriv, 0x160); - if (!(tmp & (BIT(2) | BIT(3)))) { - RT_TRACE(rtlpriv, COMP_POWER | COMP_INIT, DBG_LOUD, - "0x160(%#x)return!!\n", tmp); - return; - } - - tmp = _rtl8821ae_mdio_read(rtlpriv, 0x1b); - _rtl8821ae_mdio_write(rtlpriv, 0x1b, (tmp | BIT(4))); - - tmp = _rtl8821ae_dbi_read(rtlpriv, 0x718); - _rtl8821ae_dbi_write(rtlpriv, 0x718, tmp | BIT(5)); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "<---\n"); -} - -static void _rtl8821ae_enable_ltr(struct ieee80211_hw *hw) -{ - u8 tmp = 0; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "--->\n"); - - /* Check 0x98[10] */ - tmp = _rtl8821ae_dbi_read(rtlpriv, 0x99); - if (!(tmp & BIT(2))) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "<---0x99(%#x) return!!\n", tmp); - return; - } - - /* LTR idle latency, 0x90 for 144us */ - rtl_write_dword(rtlpriv, 0x798, 0x88908890); - - /* LTR active latency, 0x3c for 60us */ - rtl_write_dword(rtlpriv, 0x79c, 0x883c883c); - - tmp = rtl_read_byte(rtlpriv, 0x7a4); - rtl_write_byte(rtlpriv, 0x7a4, (tmp | BIT(4))); - - tmp = rtl_read_byte(rtlpriv, 0x7a4); - rtl_write_byte(rtlpriv, 0x7a4, (tmp & (~BIT(0)))); - rtl_write_byte(rtlpriv, 0x7a4, (tmp | BIT(0))); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "<---\n"); -} - -static bool _rtl8821ae_wowlan_initialize_adapter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - bool init_finished = true; - u8 tmp = 0; - - /* Get Fw wake up reason. */ - _rtl8821ae_get_wakeup_reason(hw); - - /* Patch Pcie Rx DMA hang after S3/S4 several times. - * The root cause has not be found. */ - if (_rtl8821ae_check_pcie_dma_hang(hw)) - _rtl8821ae_reset_pcie_interface_dma(hw, true, false); - - /* Prepare Tx/Rx Desc Hw address. */ - _rtl8821ae_init_trx_desc_hw_address(hw); - - /* Release Pcie Interface Rx DMA to allow wake packet DMA. */ - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE); - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Enable PCIE Rx DMA.\n"); - - /* Check wake up event. - * We should check wake packet bit before disable wowlan by H2C or - * Fw will clear the bit. */ - tmp = rtl_read_byte(rtlpriv, REG_FTISR + 3); - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Read REG_FTISR 0x13f = %#X\n", tmp); - - /* Set the WoWLAN related function control disable. */ - rtl8821ae_set_fw_wowlan_mode(hw, false); - rtl8821ae_set_fw_remote_wake_ctrl_cmd(hw, 0); - - if (rtlhal->hw_rof_enable) { - tmp = rtl_read_byte(rtlpriv, REG_HSISR + 3); - if (tmp & BIT(1)) { - /* Clear GPIO9 ISR */ - rtl_write_byte(rtlpriv, REG_HSISR + 3, tmp | BIT(1)); - init_finished = false; - } else { - init_finished = true; - } - } - - if (init_finished) { - _rtl8821ae_simple_initialize_adapter(hw); - - /* Release Pcie Interface Tx DMA. */ - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x00); - /* Release Pcie RX DMA */ - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, 0x02); - - tmp = rtl_read_byte(rtlpriv, REG_CR + 1); - rtl_write_byte(rtlpriv, REG_CR + 1, (tmp & (~BIT(0)))); - - _rtl8821ae_enable_l1off(hw); - _rtl8821ae_enable_ltr(hw); - } - - return init_finished; -} - -static void _rtl8812ae_bb8812_config_1t(struct ieee80211_hw *hw) -{ - /* BB OFDM RX Path_A */ - rtl_set_bbreg(hw, 0x808, 0xff, 0x11); - /* BB OFDM TX Path_A */ - rtl_set_bbreg(hw, 0x80c, MASKLWORD, 0x1111); - /* BB CCK R/Rx Path_A */ - rtl_set_bbreg(hw, 0xa04, 0x0c000000, 0x0); - /* MCS support */ - rtl_set_bbreg(hw, 0x8bc, 0xc0000060, 0x4); - /* RF Path_B HSSI OFF */ - rtl_set_bbreg(hw, 0xe00, 0xf, 0x4); - /* RF Path_B Power Down */ - rtl_set_bbreg(hw, 0xe90, MASKDWORD, 0); - /* ADDA Path_B OFF */ - rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0); - rtl_set_bbreg(hw, 0xe64, MASKDWORD, 0); -} - -static void _rtl8821ae_poweroff_adapter(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 u1b_tmp; - - rtlhal->mac_func_enable = false; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - /* Combo (PCIe + USB) Card and PCIe-MF Card */ - /* 1. Run LPS WL RFOFF flow */ - /* RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "=====>CardDisableRTL8812E,RTL8821A_NIC_LPS_ENTER_FLOW\n"); - */ - rtl_hal_pwrseqcmdparsing(rtlpriv, - PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, RTL8821A_NIC_LPS_ENTER_FLOW); - } - /* 2. 0x1F[7:0] = 0 */ - /* turn off RF */ - /* rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); */ - if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && - rtlhal->fw_ready) { - rtl8821ae_firmware_selfreset(hw); - } - - /* Reset MCU. Suggested by Filen. */ - u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN+1); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN+1, (u1b_tmp & (~BIT(2)))); - - /* g. MCUFWDL 0x80[1:0]=0 */ - /* reset MCU ready status */ - rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - /* HW card disable configuration. */ - rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, RTL8821A_NIC_DISABLE_FLOW); - } else { - /* HW card disable configuration. */ - rtl_hal_pwrseqcmdparsing(rtlpriv, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, - PWR_INTF_PCI_MSK, RTL8812_NIC_DISABLE_FLOW); - } - - /* Reset MCU IO Wrapper */ - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); - u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); - rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, u1b_tmp | BIT(0)); - - /* 7. RSV_CTRL 0x1C[7:0] = 0x0E */ - /* lock ISO/CLK/Power control register */ - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); -} - -int rtl8821ae_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool rtstatus = true; - int err; - u8 tmp_u1b; - bool support_remote_wakeup; - u32 nav_upper = WIFI_NAV_UPPER_US; - - rtlhal->being_init_adapter = true; - rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, - (u8 *)(&support_remote_wakeup)); - rtlpriv->intf_ops->disable_aspm(hw); - - /*YP wowlan not considered*/ - - tmp_u1b = rtl_read_byte(rtlpriv, REG_CR); - if (tmp_u1b != 0 && tmp_u1b != 0xEA) { - rtlhal->mac_func_enable = true; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "MAC has already power on.\n"); - } else { - rtlhal->mac_func_enable = false; - rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_8821AE; - } - - if (support_remote_wakeup && - rtlhal->wake_from_pnp_sleep && - rtlhal->mac_func_enable) { - if (_rtl8821ae_wowlan_initialize_adapter(hw)) { - rtlhal->being_init_adapter = false; - return 0; - } - } - - if (_rtl8821ae_check_pcie_dma_hang(hw)) { - _rtl8821ae_reset_pcie_interface_dma(hw, - rtlhal->mac_func_enable, - false); - rtlhal->mac_func_enable = false; - } - - /* Reset MAC/BB/RF status if it is not powered off - * before calling initialize Hw flow to prevent - * from interface and MAC status mismatch. - * 2013.06.21, by tynli. Suggested by SD1 JackieLau. */ - if (rtlhal->mac_func_enable) { - _rtl8821ae_poweroff_adapter(hw); - rtlhal->mac_func_enable = false; - } - - rtstatus = _rtl8821ae_init_mac(hw); - if (rtstatus != true) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Init MAC failed\n"); - err = 1; - return err; - } - - tmp_u1b = rtl_read_byte(rtlpriv, REG_SYS_CFG); - tmp_u1b &= 0x7F; - rtl_write_byte(rtlpriv, REG_SYS_CFG, tmp_u1b); - - err = rtl8821ae_download_fw(hw, false); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Failed to download FW. Init HW without FW now\n"); - err = 1; - rtlhal->fw_ready = false; - return err; - } else { - rtlhal->fw_ready = true; - } - ppsc->fw_current_inpsmode = false; - rtlhal->fw_ps_state = FW_PS_STATE_ALL_ON_8821AE; - rtlhal->fw_clk_change_in_progress = false; - rtlhal->allow_sw_to_change_hwclc = false; - rtlhal->last_hmeboxnum = 0; - - /*SIC_Init(Adapter); - if(rtlhal->AMPDUBurstMode) - rtl_write_byte(rtlpriv,REG_AMPDU_BURST_MODE_8812, 0x7F);*/ - - rtl8821ae_phy_mac_config(hw); - /* because last function modify RCR, so we update - * rcr var here, or TP will unstable for receive_config - * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx - * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252 - rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); - rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);*/ - rtl8821ae_phy_bb_config(hw); - - rtl8821ae_phy_rf_config(hw); - - if (rtlpriv->phy.rf_type == RF_1T1R && - rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - _rtl8812ae_bb8812_config_1t(hw); - - _rtl8821ae_hw_configure(hw); - - rtl8821ae_phy_switch_wirelessband(hw, BAND_ON_2_4G); - - /*set wireless mode*/ - - rtlhal->mac_func_enable = true; - - rtl_cam_reset_all_entry(hw); - - rtl8821ae_enable_hw_security_config(hw); - - ppsc->rfpwr_state = ERFON; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); - _rtl8821ae_enable_aspm_back_door(hw); - rtlpriv->intf_ops->enable_aspm(hw); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE && - (rtlhal->rfe_type == 1 || rtlhal->rfe_type == 5)) - rtl_set_bbreg(hw, 0x900, 0x00000303, 0x0302); - - rtl8821ae_bt_hw_init(hw); - rtlpriv->rtlhal.being_init_adapter = false; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_NAV_UPPER, (u8 *)&nav_upper); - - /* rtl8821ae_dm_check_txpower_tracking(hw); */ - /* rtl8821ae_phy_lc_calibrate(hw); */ - if (support_remote_wakeup) - rtl_write_byte(rtlpriv, REG_WOW_CTRL, 0); - - /* Release Rx DMA*/ - tmp_u1b = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - if (tmp_u1b & BIT(2)) { - /* Release Rx DMA if needed*/ - tmp_u1b &= ~BIT(2); - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, tmp_u1b); - } - - /* Release Tx/Rx PCIE DMA if*/ - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0); - - rtl8821ae_dm_init(hw); - rtl8821ae_macid_initialize_mediastatus(hw); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "rtl8821ae_hw_init() <====\n"); - return err; -} - -static enum version_8821ae _rtl8821ae_read_chip_version(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - enum version_8821ae version = VERSION_UNKNOWN; - u32 value32; - - value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "ReadChipVersion8812A 0xF0 = 0x%x\n", value32); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtlphy->rf_type = RF_2T2R; - else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) - rtlphy->rf_type = RF_1T1R; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "RF_Type is %x!!\n", rtlphy->rf_type); - - if (value32 & TRP_VAUX_EN) { - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - if (rtlphy->rf_type == RF_2T2R) - version = VERSION_TEST_CHIP_2T2R_8812; - else - version = VERSION_TEST_CHIP_1T1R_8812; - } else - version = VERSION_TEST_CHIP_8821; - } else { - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - u32 rtl_id = ((value32 & CHIP_VER_RTL_MASK) >> 12) + 1; - - if (rtlphy->rf_type == RF_2T2R) - version = - (enum version_8821ae)(CHIP_8812 - | NORMAL_CHIP | - RF_TYPE_2T2R); - else - version = (enum version_8821ae)(CHIP_8812 - | NORMAL_CHIP); - - version = (enum version_8821ae)(version | (rtl_id << 12)); - } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - u32 rtl_id = value32 & CHIP_VER_RTL_MASK; - - version = (enum version_8821ae)(CHIP_8821 - | NORMAL_CHIP | rtl_id); - } - } - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - /*WL_HWROF_EN.*/ - value32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL); - rtlhal->hw_rof_enable = ((value32 & WL_HWROF_EN) ? 1 : 0); - } - - switch (version) { - case VERSION_TEST_CHIP_1T1R_8812: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip Version ID: VERSION_TEST_CHIP_1T1R_8812\n"); - break; - case VERSION_TEST_CHIP_2T2R_8812: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip Version ID: VERSION_TEST_CHIP_2T2R_8812\n"); - break; - case VERSION_NORMAL_TSMC_CHIP_1T1R_8812: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip Version ID:VERSION_NORMAL_TSMC_CHIP_1T1R_8812\n"); - break; - case VERSION_NORMAL_TSMC_CHIP_2T2R_8812: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_2T2R_8812\n"); - break; - case VERSION_NORMAL_TSMC_CHIP_1T1R_8812_C_CUT: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_1T1R_8812 C CUT\n"); - break; - case VERSION_NORMAL_TSMC_CHIP_2T2R_8812_C_CUT: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_2T2R_8812 C CUT\n"); - break; - case VERSION_TEST_CHIP_8821: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip Version ID: VERSION_TEST_CHIP_8821\n"); - break; - case VERSION_NORMAL_TSMC_CHIP_8821: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_8821 A CUT\n"); - break; - case VERSION_NORMAL_TSMC_CHIP_8821_B_CUT: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip Version ID: VERSION_NORMAL_TSMC_CHIP_8821 B CUT\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Chip Version ID: Unknow (0x%X)\n", version); - break; - } - - return version; -} - -static int _rtl8821ae_set_media_status(struct ieee80211_hw *hw, - enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 bt_msr = rtl_read_byte(rtlpriv, MSR); - enum led_ctl_mode ledaction = LED_CTL_NO_LINK; - bt_msr &= 0xfc; - - rtl_write_dword(rtlpriv, REG_BCN_CTRL, 0); - RT_TRACE(rtlpriv, COMP_BEACON, DBG_LOUD, - "clear 0x550 when set HW_VAR_MEDIA_STATUS\n"); - - if (type == NL80211_IFTYPE_UNSPECIFIED || - type == NL80211_IFTYPE_STATION) { - _rtl8821ae_stop_tx_beacon(hw); - _rtl8821ae_enable_bcn_sub_func(hw); - } else if (type == NL80211_IFTYPE_ADHOC || - type == NL80211_IFTYPE_AP) { - _rtl8821ae_resume_tx_beacon(hw); - _rtl8821ae_disable_bcn_sub_func(hw); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "Set HW_VAR_MEDIA_STATUS: No such media status(%x).\n", - type); - } - - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - bt_msr |= MSR_NOLINK; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to NO LINK!\n"); - break; - case NL80211_IFTYPE_ADHOC: - bt_msr |= MSR_ADHOC; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to Ad Hoc!\n"); - break; - case NL80211_IFTYPE_STATION: - bt_msr |= MSR_INFRA; - ledaction = LED_CTL_LINK; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to STA!\n"); - break; - case NL80211_IFTYPE_AP: - bt_msr |= MSR_AP; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Set Network type to AP!\n"); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Network type %d not support!\n", type); - return 1; - } - - rtl_write_byte(rtlpriv, MSR, bt_msr); - rtlpriv->cfg->ops->led_control(hw, ledaction); - if ((bt_msr & MSR_MASK) == MSR_AP) - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); - else - rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); - - return 0; -} - -void rtl8821ae_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u32 reg_rcr = rtlpci->receive_config; - - if (rtlpriv->psc.rfpwr_state != ERFON) - return; - - if (check_bssid) { - reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *)(®_rcr)); - _rtl8821ae_set_bcn_ctrl_reg(hw, 0, BIT(4)); - } else if (!check_bssid) { - reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); - _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(4), 0); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_RCR, (u8 *)(®_rcr)); - } -} - -int rtl8821ae_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "rtl8821ae_set_network_type!\n"); - - if (_rtl8821ae_set_media_status(hw, type)) - return -EOPNOTSUPP; - - if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { - if (type != NL80211_IFTYPE_AP) - rtl8821ae_set_check_bssid(hw, true); - } else { - rtl8821ae_set_check_bssid(hw, false); - } - - return 0; -} - -/* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ -void rtl8821ae_set_qos(struct ieee80211_hw *hw, int aci) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - rtl8821ae_dm_init_edca_turbo(hw); - switch (aci) { - case AC1_BK: - rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); - break; - case AC0_BE: - /* rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param); */ - break; - case AC2_VI: - rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); - break; - case AC3_VO: - rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); - break; - default: - RT_ASSERT(false, "invalid aci: %d !\n", aci); - break; - } -} - -void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); - rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); - rtlpci->irq_enabled = true; - /* there are some C2H CMDs have been sent before - system interrupt is enabled, e.g., C2H, CPWM. - *So we need to clear all C2H events that FW has - notified, otherwise FW won't schedule any commands anymore. - */ - /* rtl_write_byte(rtlpriv, REG_C2HEVT_CLEAR, 0); */ - /*enable system interrupt*/ - rtl_write_dword(rtlpriv, REG_HSIMR, rtlpci->sys_irq_mask & 0xFFFFFFFF); -} - -void rtl8821ae_disable_interrupt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - rtl_write_dword(rtlpriv, REG_HIMR, IMR_DISABLED); - rtl_write_dword(rtlpriv, REG_HIMRE, IMR_DISABLED); - rtlpci->irq_enabled = false; - /*synchronize_irq(rtlpci->pdev->irq);*/ -} - -static void _rtl8821ae_clear_pci_pme_status(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u16 cap_hdr; - u8 cap_pointer; - u8 cap_id = 0xff; - u8 pmcs_reg; - u8 cnt = 0; - - /* Get the Capability pointer first, - * the Capability Pointer is located at - * offset 0x34 from the Function Header */ - - pci_read_config_byte(rtlpci->pdev, 0x34, &cap_pointer); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "PCI configration 0x34 = 0x%2x\n", cap_pointer); - - do { - pci_read_config_word(rtlpci->pdev, cap_pointer, &cap_hdr); - cap_id = cap_hdr & 0xFF; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "in pci configration, cap_pointer%x = %x\n", - cap_pointer, cap_id); - - if (cap_id == 0x01) { - break; - } else { - /* point to next Capability */ - cap_pointer = (cap_hdr >> 8) & 0xFF; - /* 0: end of pci capability, 0xff: invalid value */ - if (cap_pointer == 0x00 || cap_pointer == 0xff) { - cap_id = 0xff; - break; - } - } - } while (cnt++ < 200); - - if (cap_id == 0x01) { - /* Get the PM CSR (Control/Status Register), - * The PME_Status is located at PM Capatibility offset 5, bit 7 - */ - pci_read_config_byte(rtlpci->pdev, cap_pointer + 5, &pmcs_reg); - - if (pmcs_reg & BIT(7)) { - /* PME event occured, clear the PM_Status by write 1 */ - pmcs_reg = pmcs_reg | BIT(7); - - pci_write_config_byte(rtlpci->pdev, cap_pointer + 5, - pmcs_reg); - /* Read it back to check */ - pci_read_config_byte(rtlpci->pdev, cap_pointer + 5, - &pmcs_reg); - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Clear PME status 0x%2x to 0x%2x\n", - cap_pointer + 5, pmcs_reg); - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "PME status(0x%2x) = 0x%2x\n", - cap_pointer + 5, pmcs_reg); - } - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, - "Cannot find PME Capability\n"); - } -} - -void rtl8821ae_card_disable(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); - struct rtl_mac *mac = rtl_mac(rtlpriv); - enum nl80211_iftype opmode; - bool support_remote_wakeup; - u8 tmp; - u32 count = 0; - - rtlpriv->cfg->ops->get_hw_reg(hw, HAL_DEF_WOWLAN, - (u8 *)(&support_remote_wakeup)); - - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - - if (!(support_remote_wakeup && mac->opmode == NL80211_IFTYPE_STATION) - || !rtlhal->enter_pnp_sleep) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Normal Power off\n"); - mac->link_state = MAC80211_NOLINK; - opmode = NL80211_IFTYPE_UNSPECIFIED; - _rtl8821ae_set_media_status(hw, opmode); - _rtl8821ae_poweroff_adapter(hw); - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Wowlan Supported.\n"); - /* 3 <1> Prepare for configuring wowlan related infomations */ - /* Clear Fw WoWLAN event. */ - rtl_write_byte(rtlpriv, REG_MCUTST_WOWLAN, 0x0); - -#if (USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN == 1) - rtl8821ae_set_fw_related_for_wowlan(hw, true); -#endif - /* Dynamically adjust Tx packet boundary - * for download reserved page packet. - * reserve 30 pages for rsvd page */ - if (_rtl8821ae_dynamic_rqpn(hw, 0xE0, 0x3, 0x80c20d0d)) - rtlhal->re_init_llt_table = true; - - /* 3 <2> Set Fw releted H2C cmd. */ - - /* Set WoWLAN related security information. */ - rtl8821ae_set_fw_global_info_cmd(hw); - - _rtl8821ae_download_rsvd_page(hw, true); - - /* Just enable AOAC related functions when we connect to AP. */ - printk("mac->link_state = %d\n", mac->link_state); - if (mac->link_state >= MAC80211_LINKED && - mac->opmode == NL80211_IFTYPE_STATION) { - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL); - rtl8821ae_set_fw_media_status_rpt_cmd(hw, - RT_MEDIA_CONNECT); - - rtl8821ae_set_fw_wowlan_mode(hw, true); - /* Enable Fw Keep alive mechanism. */ - rtl8821ae_set_fw_keep_alive_cmd(hw, true); - - /* Enable disconnect decision control. */ - rtl8821ae_set_fw_disconnect_decision_ctrl_cmd(hw, true); - } - - /* 3 <3> Hw Configutations */ - - /* Wait untill Rx DMA Finished before host sleep. - * FW Pause Rx DMA may happens when received packet doing dma. - */ - rtl_write_byte(rtlpriv, REG_RXDMA_CONTROL, BIT(2)); - - tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - count = 0; - while (!(tmp & BIT(1)) && (count++ < 100)) { - udelay(10); - tmp = rtl_read_byte(rtlpriv, REG_RXDMA_CONTROL); - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Wait Rx DMA Finished before host sleep. count=%d\n", - count); - - /* reset trx ring */ - rtlpriv->intf_ops->reset_trx_ring(hw); - - rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x0); - - _rtl8821ae_clear_pci_pme_status(hw); - tmp = rtl_read_byte(rtlpriv, REG_SYS_CLKR); - rtl_write_byte(rtlpriv, REG_SYS_CLKR, tmp | BIT(3)); - /* prevent 8051 to be reset by PERST */ - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x20); - rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x60); - } - - if (rtlpriv->rtlhal.driver_is_goingto_unload || - ppsc->rfoff_reason > RF_CHANGE_BY_PS) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); - /* For wowlan+LPS+32k. */ - if (support_remote_wakeup && rtlhal->enter_pnp_sleep) { - /* Set the WoWLAN related function control enable. - * It should be the last H2C cmd in the WoWLAN flow. */ - rtl8821ae_set_fw_remote_wake_ctrl_cmd(hw, 1); - - /* Stop Pcie Interface Tx DMA. */ - rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xff); - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Stop PCIE Tx DMA.\n"); - - /* Wait for TxDMA idle. */ - count = 0; - do { - tmp = rtl_read_byte(rtlpriv, REG_PCIE_CTRL_REG); - udelay(10); - count++; - } while ((tmp != 0) && (count < 100)); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Wait Tx DMA Finished before host sleep. count=%d\n", - count); - - if (rtlhal->hw_rof_enable) { - printk("hw_rof_enable\n"); - tmp = rtl_read_byte(rtlpriv, REG_HSISR + 3); - rtl_write_byte(rtlpriv, REG_HSISR + 3, tmp | BIT(1)); - } - } - /* after power off we should do iqk again */ - rtlpriv->phy.iqk_initialized = false; -} - -void rtl8821ae_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; - rtl_write_dword(rtlpriv, ISR, *p_inta); - - *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; - rtl_write_dword(rtlpriv, REG_HISRE, *p_intb); -} - -void rtl8821ae_set_beacon_related_registers(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u16 bcn_interval, atim_window; - - bcn_interval = mac->beacon_interval; - atim_window = 2; /*FIX MERGE */ - rtl8821ae_disable_interrupt(hw); - rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x18); - rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x18); - rtl_write_byte(rtlpriv, 0x606, 0x30); - rtlpci->reg_bcn_ctrl_val |= BIT(3); - rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlpci->reg_bcn_ctrl_val); - rtl8821ae_enable_interrupt(hw); -} - -void rtl8821ae_set_beacon_interval(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u16 bcn_interval = mac->beacon_interval; - - RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, - "beacon_interval:%d\n", bcn_interval); - rtl8821ae_disable_interrupt(hw); - rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); - rtl8821ae_enable_interrupt(hw); -} - -void rtl8821ae_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, - "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); - - if (add_msr) - rtlpci->irq_mask[0] |= add_msr; - if (rm_msr) - rtlpci->irq_mask[0] &= (~rm_msr); - rtl8821ae_disable_interrupt(hw); - rtl8821ae_enable_interrupt(hw); -} - -static u8 _rtl8821ae_get_chnl_group(u8 chnl) -{ - u8 group = 0; - - if (chnl <= 14) { - if (1 <= chnl && chnl <= 2) - group = 0; - else if (3 <= chnl && chnl <= 5) - group = 1; - else if (6 <= chnl && chnl <= 8) - group = 2; - else if (9 <= chnl && chnl <= 11) - group = 3; - else /*if (12 <= chnl && chnl <= 14)*/ - group = 4; - } else { - if (36 <= chnl && chnl <= 42) - group = 0; - else if (44 <= chnl && chnl <= 48) - group = 1; - else if (50 <= chnl && chnl <= 58) - group = 2; - else if (60 <= chnl && chnl <= 64) - group = 3; - else if (100 <= chnl && chnl <= 106) - group = 4; - else if (108 <= chnl && chnl <= 114) - group = 5; - else if (116 <= chnl && chnl <= 122) - group = 6; - else if (124 <= chnl && chnl <= 130) - group = 7; - else if (132 <= chnl && chnl <= 138) - group = 8; - else if (140 <= chnl && chnl <= 144) - group = 9; - else if (149 <= chnl && chnl <= 155) - group = 10; - else if (157 <= chnl && chnl <= 161) - group = 11; - else if (165 <= chnl && chnl <= 171) - group = 12; - else if (173 <= chnl && chnl <= 177) - group = 13; - else - /*RT_TRACE(rtlpriv, COMP_EFUSE,DBG_LOUD, - "5G, Channel %d in Group not found\n",chnl);*/ - RT_ASSERT(!COMP_EFUSE, - "5G, Channel %d in Group not found\n", chnl); - } - return group; -} - -static void _rtl8821ae_read_power_value_fromprom(struct ieee80211_hw *hw, - struct txpower_info_2g *pwrinfo24g, - struct txpower_info_5g *pwrinfo5g, - bool autoload_fail, - u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 rfPath, eeAddr = EEPROM_TX_PWR_INX, group, TxCount = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "hal_ReadPowerValueFromPROM8821ae(): hwinfo[0x%x]=0x%x\n", - (eeAddr+1), hwinfo[eeAddr+1]); - if (0xFF == hwinfo[eeAddr+1]) /*YJ,add,120316*/ - autoload_fail = true; - - if (autoload_fail) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "auto load fail : Use Default value!\n"); - for (rfPath = 0 ; rfPath < MAX_RF_PATH ; rfPath++) { - /*2.4G default value*/ - for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { - pwrinfo24g->index_cck_base[rfPath][group] = 0x2D; - pwrinfo24g->index_bw40_base[rfPath][group] = 0x2D; - } - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - if (TxCount == 0) { - pwrinfo24g->bw20_diff[rfPath][0] = 0x02; - pwrinfo24g->ofdm_diff[rfPath][0] = 0x04; - } else { - pwrinfo24g->bw20_diff[rfPath][TxCount] = 0xFE; - pwrinfo24g->bw40_diff[rfPath][TxCount] = 0xFE; - pwrinfo24g->cck_diff[rfPath][TxCount] = 0xFE; - pwrinfo24g->ofdm_diff[rfPath][TxCount] = 0xFE; - } - } - /*5G default value*/ - for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) - pwrinfo5g->index_bw40_base[rfPath][group] = 0x2A; - - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - if (TxCount == 0) { - pwrinfo5g->ofdm_diff[rfPath][0] = 0x04; - pwrinfo5g->bw20_diff[rfPath][0] = 0x00; - pwrinfo5g->bw80_diff[rfPath][0] = 0xFE; - pwrinfo5g->bw160_diff[rfPath][0] = 0xFE; - } else { - pwrinfo5g->ofdm_diff[rfPath][0] = 0xFE; - pwrinfo5g->bw20_diff[rfPath][0] = 0xFE; - pwrinfo5g->bw40_diff[rfPath][0] = 0xFE; - pwrinfo5g->bw80_diff[rfPath][0] = 0xFE; - pwrinfo5g->bw160_diff[rfPath][0] = 0xFE; - } - } - } - return; - } - - rtl_priv(hw)->efuse.txpwr_fromeprom = true; - - for (rfPath = 0 ; rfPath < MAX_RF_PATH ; rfPath++) { - /*2.4G default value*/ - for (group = 0 ; group < MAX_CHNL_GROUP_24G; group++) { - pwrinfo24g->index_cck_base[rfPath][group] = hwinfo[eeAddr++]; - if (pwrinfo24g->index_cck_base[rfPath][group] == 0xFF) - pwrinfo24g->index_cck_base[rfPath][group] = 0x2D; - } - for (group = 0 ; group < MAX_CHNL_GROUP_24G - 1; group++) { - pwrinfo24g->index_bw40_base[rfPath][group] = hwinfo[eeAddr++]; - if (pwrinfo24g->index_bw40_base[rfPath][group] == 0xFF) - pwrinfo24g->index_bw40_base[rfPath][group] = 0x2D; - } - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - if (TxCount == 0) { - pwrinfo24g->bw40_diff[rfPath][TxCount] = 0; - /*bit sign number to 8 bit sign number*/ - pwrinfo24g->bw20_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4; - if (pwrinfo24g->bw20_diff[rfPath][TxCount] & BIT(3)) - pwrinfo24g->bw20_diff[rfPath][TxCount] |= 0xF0; - /*bit sign number to 8 bit sign number*/ - pwrinfo24g->ofdm_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); - if (pwrinfo24g->ofdm_diff[rfPath][TxCount] & BIT(3)) - pwrinfo24g->ofdm_diff[rfPath][TxCount] |= 0xF0; - - pwrinfo24g->cck_diff[rfPath][TxCount] = 0; - eeAddr++; - } else { - pwrinfo24g->bw40_diff[rfPath][TxCount] = (hwinfo[eeAddr]&0xf0) >> 4; - if (pwrinfo24g->bw40_diff[rfPath][TxCount] & BIT(3)) - pwrinfo24g->bw40_diff[rfPath][TxCount] |= 0xF0; - - pwrinfo24g->bw20_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); - if (pwrinfo24g->bw20_diff[rfPath][TxCount] & BIT(3)) - pwrinfo24g->bw20_diff[rfPath][TxCount] |= 0xF0; - - eeAddr++; - - pwrinfo24g->ofdm_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4; - if (pwrinfo24g->ofdm_diff[rfPath][TxCount] & BIT(3)) - pwrinfo24g->ofdm_diff[rfPath][TxCount] |= 0xF0; - - pwrinfo24g->cck_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); - if (pwrinfo24g->cck_diff[rfPath][TxCount] & BIT(3)) - pwrinfo24g->cck_diff[rfPath][TxCount] |= 0xF0; - - eeAddr++; - } - } - - /*5G default value*/ - for (group = 0 ; group < MAX_CHNL_GROUP_5G; group++) { - pwrinfo5g->index_bw40_base[rfPath][group] = hwinfo[eeAddr++]; - if (pwrinfo5g->index_bw40_base[rfPath][group] == 0xFF) - pwrinfo5g->index_bw40_base[rfPath][group] = 0xFE; - } - - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - if (TxCount == 0) { - pwrinfo5g->bw40_diff[rfPath][TxCount] = 0; - - pwrinfo5g->bw20_diff[rfPath][0] = (hwinfo[eeAddr] & 0xf0) >> 4; - if (pwrinfo5g->bw20_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->bw20_diff[rfPath][TxCount] |= 0xF0; - - pwrinfo5g->ofdm_diff[rfPath][0] = (hwinfo[eeAddr] & 0x0f); - if (pwrinfo5g->ofdm_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->ofdm_diff[rfPath][TxCount] |= 0xF0; - - eeAddr++; - } else { - pwrinfo5g->bw40_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4; - if (pwrinfo5g->bw40_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->bw40_diff[rfPath][TxCount] |= 0xF0; - - pwrinfo5g->bw20_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); - if (pwrinfo5g->bw20_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->bw20_diff[rfPath][TxCount] |= 0xF0; - - eeAddr++; - } - } - - pwrinfo5g->ofdm_diff[rfPath][1] = (hwinfo[eeAddr] & 0xf0) >> 4; - pwrinfo5g->ofdm_diff[rfPath][2] = (hwinfo[eeAddr] & 0x0f); - - eeAddr++; - - pwrinfo5g->ofdm_diff[rfPath][3] = (hwinfo[eeAddr] & 0x0f); - - eeAddr++; - - for (TxCount = 1; TxCount < MAX_TX_COUNT; TxCount++) { - if (pwrinfo5g->ofdm_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->ofdm_diff[rfPath][TxCount] |= 0xF0; - } - for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) { - pwrinfo5g->bw80_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0xf0) >> 4; - /* 4bit sign number to 8 bit sign number */ - if (pwrinfo5g->bw80_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->bw80_diff[rfPath][TxCount] |= 0xF0; - /* 4bit sign number to 8 bit sign number */ - pwrinfo5g->bw160_diff[rfPath][TxCount] = (hwinfo[eeAddr] & 0x0f); - if (pwrinfo5g->bw160_diff[rfPath][TxCount] & BIT(3)) - pwrinfo5g->bw160_diff[rfPath][TxCount] |= 0xF0; - - eeAddr++; - } - } -} -#if 0 -static void _rtl8812ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct txpower_info_2g pwrinfo24g; - struct txpower_info_5g pwrinfo5g; - u8 channel5g[CHANNEL_MAX_NUMBER_5G] = { - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, - 56, 58, 60, 62, 64, 100, 102, 104, 106, - 108, 110, 112, 114, 116, 118, 120, 122, - 124, 126, 128, 130, 132, 134, 136, 138, - 140, 142, 144, 149, 151, 153, 155, 157, - 159, 161, 163, 165, 167, 168, 169, 171, 173, 175, 177}; - u8 channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = {42, 58, 106, 122, 138, 155, 171}; - u8 rf_path, index; - u8 i; - - _rtl8821ae_read_power_value_fromprom(hw, &pwrinfo24g, - &pwrinfo5g, autoload_fail, hwinfo); - - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < CHANNEL_MAX_NUMBER_2G; i++) { - index = _rtl8821ae_get_chnl_group(i + 1); - - if (i == CHANNEL_MAX_NUMBER_2G - 1) { - rtlefuse->txpwrlevel_cck[rf_path][i] = - pwrinfo24g.index_cck_base[rf_path][5]; - rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = - pwrinfo24g.index_bw40_base[rf_path][index]; - } else { - rtlefuse->txpwrlevel_cck[rf_path][i] = - pwrinfo24g.index_cck_base[rf_path][index]; - rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = - pwrinfo24g.index_bw40_base[rf_path][index]; - } - } - - for (i = 0; i < CHANNEL_MAX_NUMBER_5G; i++) { - index = _rtl8821ae_get_chnl_group(channel5g[i]); - rtlefuse->txpwr_5g_bw40base[rf_path][i] = - pwrinfo5g.index_bw40_base[rf_path][index]; - } - for (i = 0; i < CHANNEL_MAX_NUMBER_5G_80M; i++) { - u8 upper, lower; - index = _rtl8821ae_get_chnl_group(channel5g_80m[i]); - upper = pwrinfo5g.index_bw40_base[rf_path][index]; - lower = pwrinfo5g.index_bw40_base[rf_path][index + 1]; - - rtlefuse->txpwr_5g_bw80base[rf_path][i] = (upper + lower) / 2; - } - for (i = 0; i < MAX_TX_COUNT; i++) { - rtlefuse->txpwr_cckdiff[rf_path][i] = - pwrinfo24g.cck_diff[rf_path][i]; - rtlefuse->txpwr_legacyhtdiff[rf_path][i] = - pwrinfo24g.ofdm_diff[rf_path][i]; - rtlefuse->txpwr_ht20diff[rf_path][i] = - pwrinfo24g.bw20_diff[rf_path][i]; - rtlefuse->txpwr_ht40diff[rf_path][i] = - pwrinfo24g.bw40_diff[rf_path][i]; - - rtlefuse->txpwr_5g_ofdmdiff[rf_path][i] = - pwrinfo5g.ofdm_diff[rf_path][i]; - rtlefuse->txpwr_5g_bw20diff[rf_path][i] = - pwrinfo5g.bw20_diff[rf_path][i]; - rtlefuse->txpwr_5g_bw40diff[rf_path][i] = - pwrinfo5g.bw40_diff[rf_path][i]; - rtlefuse->txpwr_5g_bw80diff[rf_path][i] = - pwrinfo5g.bw80_diff[rf_path][i]; - } - } - - if (!autoload_fail) { - rtlefuse->eeprom_regulatory = - hwinfo[EEPROM_RF_BOARD_OPTION] & 0x07;/*bit0~2*/ - if (hwinfo[EEPROM_RF_BOARD_OPTION] == 0xFF) - rtlefuse->eeprom_regulatory = 0; - } else { - rtlefuse->eeprom_regulatory = 0; - } - - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); -} -#endif -static void _rtl8821ae_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, - bool autoload_fail, - u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct txpower_info_2g pwrinfo24g; - struct txpower_info_5g pwrinfo5g; - u8 channel5g[CHANNEL_MAX_NUMBER_5G] = { - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, - 56, 58, 60, 62, 64, 100, 102, 104, 106, - 108, 110, 112, 114, 116, 118, 120, 122, - 124, 126, 128, 130, 132, 134, 136, 138, - 140, 142, 144, 149, 151, 153, 155, 157, - 159, 161, 163, 165, 167, 168, 169, 171, - 173, 175, 177}; - u8 channel5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = { - 42, 58, 106, 122, 138, 155, 171}; - u8 rf_path, index; - u8 i; - - _rtl8821ae_read_power_value_fromprom(hw, &pwrinfo24g, - &pwrinfo5g, autoload_fail, hwinfo); - - for (rf_path = 0; rf_path < 2; rf_path++) { - for (i = 0; i < CHANNEL_MAX_NUMBER_2G; i++) { - index = _rtl8821ae_get_chnl_group(i + 1); - - if (i == CHANNEL_MAX_NUMBER_2G - 1) { - rtlefuse->txpwrlevel_cck[rf_path][i] = - pwrinfo24g.index_cck_base[rf_path][5]; - rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = - pwrinfo24g.index_bw40_base[rf_path][index]; - } else { - rtlefuse->txpwrlevel_cck[rf_path][i] = - pwrinfo24g.index_cck_base[rf_path][index]; - rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = - pwrinfo24g.index_bw40_base[rf_path][index]; - } - } - - for (i = 0; i < CHANNEL_MAX_NUMBER_5G; i++) { - index = _rtl8821ae_get_chnl_group(channel5g[i]); - rtlefuse->txpwr_5g_bw40base[rf_path][i] = - pwrinfo5g.index_bw40_base[rf_path][index]; - } - for (i = 0; i < CHANNEL_MAX_NUMBER_5G_80M; i++) { - u8 upper, lower; - index = _rtl8821ae_get_chnl_group(channel5g_80m[i]); - upper = pwrinfo5g.index_bw40_base[rf_path][index]; - lower = pwrinfo5g.index_bw40_base[rf_path][index + 1]; - - rtlefuse->txpwr_5g_bw80base[rf_path][i] = (upper + lower) / 2; - } - for (i = 0; i < MAX_TX_COUNT; i++) { - rtlefuse->txpwr_cckdiff[rf_path][i] = - pwrinfo24g.cck_diff[rf_path][i]; - rtlefuse->txpwr_legacyhtdiff[rf_path][i] = - pwrinfo24g.ofdm_diff[rf_path][i]; - rtlefuse->txpwr_ht20diff[rf_path][i] = - pwrinfo24g.bw20_diff[rf_path][i]; - rtlefuse->txpwr_ht40diff[rf_path][i] = - pwrinfo24g.bw40_diff[rf_path][i]; - - rtlefuse->txpwr_5g_ofdmdiff[rf_path][i] = - pwrinfo5g.ofdm_diff[rf_path][i]; - rtlefuse->txpwr_5g_bw20diff[rf_path][i] = - pwrinfo5g.bw20_diff[rf_path][i]; - rtlefuse->txpwr_5g_bw40diff[rf_path][i] = - pwrinfo5g.bw40_diff[rf_path][i]; - rtlefuse->txpwr_5g_bw80diff[rf_path][i] = - pwrinfo5g.bw80_diff[rf_path][i]; - } - } - /*bit0~2*/ - if (!autoload_fail) { - rtlefuse->eeprom_regulatory = hwinfo[EEPROM_RF_BOARD_OPTION] & 0x07; - if (hwinfo[EEPROM_RF_BOARD_OPTION] == 0xFF) - rtlefuse->eeprom_regulatory = 0; - } else { - rtlefuse->eeprom_regulatory = 0; - } - - RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, - "eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory); -} - -static void _rtl8812ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo, - bool autoload_fail) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - - if (!autoload_fail) { - rtlhal->pa_type_2g = hwinfo[0xBC]; - rtlhal->lna_type_2g = hwinfo[0xBD]; - if (rtlhal->pa_type_2g == 0xFF && rtlhal->lna_type_2g == 0xFF) { - rtlhal->pa_type_2g = 0; - rtlhal->lna_type_2g = 0; - } - rtlhal->external_pa_2g = ((rtlhal->pa_type_2g & BIT(5)) && - (rtlhal->pa_type_2g & BIT(4))) ? - 1 : 0; - rtlhal->external_lna_2g = ((rtlhal->lna_type_2g & BIT(7)) && - (rtlhal->lna_type_2g & BIT(3))) ? - 1 : 0; - - rtlhal->pa_type_5g = hwinfo[0xBC]; - rtlhal->lna_type_5g = hwinfo[0xBF]; - if (rtlhal->pa_type_5g == 0xFF && rtlhal->lna_type_5g == 0xFF) { - rtlhal->pa_type_5g = 0; - rtlhal->lna_type_5g = 0; - } - rtlhal->external_pa_5g = ((rtlhal->pa_type_5g & BIT(1)) && - (rtlhal->pa_type_5g & BIT(0))) ? - 1 : 0; - rtlhal->external_lna_5g = ((rtlhal->lna_type_5g & BIT(7)) && - (rtlhal->lna_type_5g & BIT(3))) ? - 1 : 0; - } else { - rtlhal->external_pa_2g = 0; - rtlhal->external_lna_2g = 0; - rtlhal->external_pa_5g = 0; - rtlhal->external_lna_5g = 0; - } -} - -static void _rtl8821ae_read_pa_type(struct ieee80211_hw *hw, u8 *hwinfo, - bool autoload_fail) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - - if (!autoload_fail) { - rtlhal->pa_type_2g = hwinfo[0xBC]; - rtlhal->lna_type_2g = hwinfo[0xBD]; - if (rtlhal->pa_type_2g == 0xFF && rtlhal->lna_type_2g == 0xFF) { - rtlhal->pa_type_2g = 0; - rtlhal->lna_type_2g = 0; - } - rtlhal->external_pa_2g = (rtlhal->pa_type_2g & BIT(5)) ? 1 : 0; - rtlhal->external_lna_2g = (rtlhal->lna_type_2g & BIT(7)) ? 1 : 0; - - rtlhal->pa_type_5g = hwinfo[0xBC]; - rtlhal->lna_type_5g = hwinfo[0xBF]; - if (rtlhal->pa_type_5g == 0xFF && rtlhal->lna_type_5g == 0xFF) { - rtlhal->pa_type_5g = 0; - rtlhal->lna_type_5g = 0; - } - rtlhal->external_pa_5g = (rtlhal->pa_type_5g & BIT(1)) ? 1 : 0; - rtlhal->external_lna_5g = (rtlhal->lna_type_5g & BIT(7)) ? 1 : 0; - } else { - rtlhal->external_pa_2g = 0; - rtlhal->external_lna_2g = 0; - rtlhal->external_pa_5g = 0; - rtlhal->external_lna_5g = 0; - } -} - -static void _rtl8821ae_read_rfe_type(struct ieee80211_hw *hw, u8 *hwinfo, - bool autoload_fail) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - - if (!autoload_fail) { - if (hwinfo[EEPROM_RFE_OPTION] & BIT(7)) { - if (rtlhal->external_lna_5g) { - if (rtlhal->external_pa_5g) { - if (rtlhal->external_lna_2g && - rtlhal->external_pa_2g) - rtlhal->rfe_type = 3; - else - rtlhal->rfe_type = 0; - } else { - rtlhal->rfe_type = 2; - } - } else { - rtlhal->rfe_type = 4; - } - } else { - rtlhal->rfe_type = hwinfo[EEPROM_RFE_OPTION] & 0x3F; - - if (rtlhal->rfe_type == 4 && - (rtlhal->external_pa_5g || - rtlhal->external_pa_2g || - rtlhal->external_lna_5g || - rtlhal->external_lna_2g)) { - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtlhal->rfe_type = 2; - } - } - } else { - rtlhal->rfe_type = 0x04; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "RFE Type: 0x%2x\n", rtlhal->rfe_type); -} - -static void _rtl8812ae_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool auto_load_fail, u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value; - - if (!auto_load_fail) { - value = *(u8 *)&hwinfo[EEPROM_RF_BOARD_OPTION]; - if (((value & 0xe0) >> 5) == 0x1) - rtlpriv->btcoexist.btc_info.btcoexist = 1; - else - rtlpriv->btcoexist.btc_info.btcoexist = 0; - rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8812A; - - value = hwinfo[EEPROM_RF_BT_SETTING]; - rtlpriv->btcoexist.btc_info.ant_num = (value & 0x1); - } else { - rtlpriv->btcoexist.btc_info.btcoexist = 0; - rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8812A; - rtlpriv->btcoexist.btc_info.ant_num = ANT_X2; - } - /*move BT_InitHalVars() to init_sw_vars*/ -} - -static void _rtl8821ae_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, - bool auto_load_fail, u8 *hwinfo) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 value; - u32 tmpu_32; - - if (!auto_load_fail) { - tmpu_32 = rtl_read_dword(rtlpriv, REG_MULTI_FUNC_CTRL); - if (tmpu_32 & BIT(18)) - rtlpriv->btcoexist.btc_info.btcoexist = 1; - else - rtlpriv->btcoexist.btc_info.btcoexist = 0; - rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8821A; - - value = hwinfo[EEPROM_RF_BT_SETTING]; - rtlpriv->btcoexist.btc_info.ant_num = (value & 0x1); - } else { - rtlpriv->btcoexist.btc_info.btcoexist = 0; - rtlpriv->btcoexist.btc_info.bt_type = BT_RTL8821A; - rtlpriv->btcoexist.btc_info.ant_num = ANT_X2; - } - /*move BT_InitHalVars() to init_sw_vars*/ -} - -static void _rtl8821ae_read_adapter_info(struct ieee80211_hw *hw, bool b_pseudo_test) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - u16 i, usvalue; - u8 hwinfo[HWSET_MAX_SIZE]; - u16 eeprom_id; - - if (b_pseudo_test) { - ;/* need add */ - } - - if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { - rtl_efuse_shadow_map_update(hw); - memcpy(hwinfo, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], - HWSET_MAX_SIZE); - } else if (rtlefuse->epromtype == EEPROM_93C46) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "RTL819X Not boot from eeprom, check it !!"); - } - - RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "MAP\n", - hwinfo, HWSET_MAX_SIZE); - - eeprom_id = *((u16 *)&hwinfo[0]); - if (eeprom_id != RTL_EEPROM_ID) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "EEPROM ID(%#x) is invalid!!\n", eeprom_id); - rtlefuse->autoload_failflag = true; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - } - - if (rtlefuse->autoload_failflag) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "RTL8812AE autoload_failflag, check it !!"); - return; - } - - rtlefuse->eeprom_version = *(u8 *)&hwinfo[EEPROM_VERSION]; - if (rtlefuse->eeprom_version == 0xff) - rtlefuse->eeprom_version = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM version: 0x%2x\n", rtlefuse->eeprom_version); - - rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; - rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; - rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; - rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROMId = 0x%4x\n", eeprom_id); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid); - - /*customer ID*/ - rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID]; - if (rtlefuse->eeprom_oemid == 0xFF) - rtlefuse->eeprom_oemid = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid); - - for (i = 0; i < 6; i += 2) { - usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; - *((u16 *)(&rtlefuse->dev_addr[i])) = usvalue; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "dev_addr: %pM\n", rtlefuse->dev_addr); - - _rtl8821ae_read_txpower_info_from_hwpg(hw, rtlefuse->autoload_failflag, - hwinfo); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - _rtl8812ae_read_pa_type(hw, hwinfo, rtlefuse->autoload_failflag); - _rtl8812ae_read_bt_coexist_info_from_hwpg(hw, - rtlefuse->autoload_failflag, hwinfo); - } else { - _rtl8821ae_read_pa_type(hw, hwinfo, rtlefuse->autoload_failflag); - _rtl8821ae_read_bt_coexist_info_from_hwpg(hw, - rtlefuse->autoload_failflag, hwinfo); - } - - _rtl8821ae_read_rfe_type(hw, hwinfo, rtlefuse->autoload_failflag); - /*board type*/ - rtlefuse->board_type = ODM_BOARD_DEFAULT; - if (rtlhal->external_lna_2g != 0) - rtlefuse->board_type |= ODM_BOARD_EXT_LNA; - if (rtlhal->external_lna_5g != 0) - rtlefuse->board_type |= ODM_BOARD_EXT_LNA_5G; - if (rtlhal->external_pa_2g != 0) - rtlefuse->board_type |= ODM_BOARD_EXT_PA; - if (rtlhal->external_pa_5g != 0) - rtlefuse->board_type |= ODM_BOARD_EXT_PA_5G; - - if (rtlpriv->btcoexist.btc_info.btcoexist == 1) - rtlefuse->board_type |= ODM_BOARD_BT; - - rtlhal->board_type = rtlefuse->board_type; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "board_type = 0x%x\n", rtlefuse->board_type); - - rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; - if (rtlefuse->eeprom_channelplan == 0xff) - rtlefuse->eeprom_channelplan = 0x7F; - - /* set channel plan from efuse */ - rtlefuse->channel_plan = rtlefuse->eeprom_channelplan; - - /*parse xtal*/ - rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_8821AE]; - if (rtlefuse->crystalcap == 0xFF) - rtlefuse->crystalcap = 0x20; - - rtlefuse->eeprom_thermalmeter = *(u8 *)&hwinfo[EEPROM_THERMAL_METER]; - if ((rtlefuse->eeprom_thermalmeter == 0xff) || - rtlefuse->autoload_failflag) { - rtlefuse->apk_thermalmeterignore = true; - rtlefuse->eeprom_thermalmeter = 0xff; - } - - rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter); - - if (!rtlefuse->autoload_failflag) { - rtlefuse->antenna_div_cfg = - (hwinfo[EEPROM_RF_BOARD_OPTION] & 0x18) >> 3; - if (hwinfo[EEPROM_RF_BOARD_OPTION] == 0xff) - rtlefuse->antenna_div_cfg = 0; - - if (rtlpriv->btcoexist.btc_info.btcoexist == 1 && - rtlpriv->btcoexist.btc_info.ant_num == ANT_X1) - rtlefuse->antenna_div_cfg = 0; - - rtlefuse->antenna_div_type = hwinfo[EEPROM_RF_ANTENNA_OPT_88E]; - if (rtlefuse->antenna_div_type == 0xff) - rtlefuse->antenna_div_type = FIXED_HW_ANTDIV; - } else { - rtlefuse->antenna_div_cfg = 0; - rtlefuse->antenna_div_type = 0; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "SWAS: bHwAntDiv = %x, TRxAntDivType = %x\n", - rtlefuse->antenna_div_cfg, rtlefuse->antenna_div_type); - - pcipriv->ledctl.led_opendrain = true; - - if (rtlhal->oem_id == RT_CID_DEFAULT) { - switch (rtlefuse->eeprom_oemid) { - case RT_CID_DEFAULT: - break; - case EEPROM_CID_TOSHIBA: - rtlhal->oem_id = RT_CID_TOSHIBA; - break; - case EEPROM_CID_CCX: - rtlhal->oem_id = RT_CID_CCX; - break; - case EEPROM_CID_QMI: - rtlhal->oem_id = RT_CID_819X_QMI; - break; - case EEPROM_CID_WHQL: - break; - default: - break; - } - } -} - -/*static void _rtl8821ae_hal_customized_behavior(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - pcipriv->ledctl.led_opendrain = true; - switch (rtlhal->oem_id) { - case RT_CID_819X_HP: - pcipriv->ledctl.led_opendrain = true; - break; - case RT_CID_819X_LENOVO: - case RT_CID_DEFAULT: - case RT_CID_TOSHIBA: - case RT_CID_CCX: - case RT_CID_819X_ACER: - case RT_CID_WHQL: - default: - break; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "RT Customized ID: 0x%02X\n", rtlhal->oem_id); -}*/ - -void rtl8821ae_read_eeprom_info(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_u1b; - - rtlhal->version = _rtl8821ae_read_chip_version(hw); - if (get_rf_type(rtlphy) == RF_1T1R) - rtlpriv->dm.rfpath_rxenable[0] = true; - else - rtlpriv->dm.rfpath_rxenable[0] = - rtlpriv->dm.rfpath_rxenable[1] = true; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "VersionID = 0x%4x\n", - rtlhal->version); - - tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); - if (tmp_u1b & BIT(4)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n"); - rtlefuse->epromtype = EEPROM_93C46; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n"); - rtlefuse->epromtype = EEPROM_BOOT_EFUSE; - } - - if (tmp_u1b & BIT(5)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n"); - rtlefuse->autoload_failflag = false; - _rtl8821ae_read_adapter_info(hw, false); - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Autoload ERR!!\n"); - } - /*hal_ReadRFType_8812A()*/ - /* _rtl8821ae_hal_customized_behavior(hw); */ -} - -static void rtl8821ae_update_hal_rate_table(struct ieee80211_hw *hw, - struct ieee80211_sta *sta) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 ratr_value; - u8 ratr_index = 0; - u8 b_nmode = mac->ht_enable; - u8 mimo_ps = IEEE80211_SMPS_OFF; - u16 shortgi_rate; - u32 tmp_ratr_value; - u8 curtxbw_40mhz = mac->bw_40; - u8 b_curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 b_curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - enum wireless_mode wirelessmode = mac->mode; - - if (rtlhal->current_bandtype == BAND_ON_5G) - ratr_value = sta->supp_rates[1] << 4; - else - ratr_value = sta->supp_rates[0]; - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_value = 0xfff; - ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - switch (wirelessmode) { - case WIRELESS_MODE_B: - if (ratr_value & 0x0000000c) - ratr_value &= 0x0000000d; - else - ratr_value &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_value &= 0x00000FF5; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - b_nmode = 1; - if (mimo_ps == IEEE80211_SMPS_STATIC) { - ratr_value &= 0x0007F005; - } else { - u32 ratr_mask; - - if (get_rf_type(rtlphy) == RF_1T2R || - get_rf_type(rtlphy) == RF_1T1R) - ratr_mask = 0x000ff005; - else - ratr_mask = 0x0f0ff005; - - ratr_value &= ratr_mask; - } - break; - default: - if (rtlphy->rf_type == RF_1T2R) - ratr_value &= 0x000ff0ff; - else - ratr_value &= 0x0f0ff0ff; - - break; - } - - if ((rtlpriv->btcoexist.bt_coexistence) && - (rtlpriv->btcoexist.bt_coexist_type == BT_CSR_BC4) && - (rtlpriv->btcoexist.bt_cur_state) && - (rtlpriv->btcoexist.bt_ant_isolation) && - ((rtlpriv->btcoexist.bt_service == BT_SCO) || - (rtlpriv->btcoexist.bt_service == BT_BUSY))) - ratr_value &= 0x0fffcfc0; - else - ratr_value &= 0x0FFFFFFF; - - if (b_nmode && ((curtxbw_40mhz && - b_curshortgi_40mhz) || (!curtxbw_40mhz && - b_curshortgi_20mhz))) { - ratr_value |= 0x10000000; - tmp_ratr_value = (ratr_value >> 12); - - for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { - if ((1 << shortgi_rate) & tmp_ratr_value) - break; - } - - shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | - (shortgi_rate << 4) | (shortgi_rate); - } - - rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "%x\n", rtl_read_dword(rtlpriv, REG_ARFR0)); -} - -static u8 _rtl8821ae_mrate_idx_to_arfr_id( - struct ieee80211_hw *hw, u8 rate_index, - enum wireless_mode wirelessmode) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 ret = 0; - switch (rate_index) { - case RATR_INX_WIRELESS_NGB: - if (rtlphy->rf_type == RF_1T1R) - ret = 1; - else - ret = 0; - ; break; - case RATR_INX_WIRELESS_N: - case RATR_INX_WIRELESS_NG: - if (rtlphy->rf_type == RF_1T1R) - ret = 5; - else - ret = 4; - ; break; - case RATR_INX_WIRELESS_NB: - if (rtlphy->rf_type == RF_1T1R) - ret = 3; - else - ret = 2; - ; break; - case RATR_INX_WIRELESS_GB: - ret = 6; - break; - case RATR_INX_WIRELESS_G: - ret = 7; - break; - case RATR_INX_WIRELESS_B: - ret = 8; - break; - case RATR_INX_WIRELESS_MC: - if ((wirelessmode == WIRELESS_MODE_B) - || (wirelessmode == WIRELESS_MODE_G) - || (wirelessmode == WIRELESS_MODE_N_24G) - || (wirelessmode == WIRELESS_MODE_AC_24G)) - ret = 6; - else - ret = 7; - case RATR_INX_WIRELESS_AC_5N: - if (rtlphy->rf_type == RF_1T1R) - ret = 10; - else - ret = 9; - break; - case RATR_INX_WIRELESS_AC_24N: - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) { - if (rtlphy->rf_type == RF_1T1R) - ret = 10; - else - ret = 9; - } else { - if (rtlphy->rf_type == RF_1T1R) - ret = 11; - else - ret = 12; - } - break; - default: - ret = 0; break; - } - return ret; -} - -static u32 _rtl8821ae_rate_to_bitmap_2ssvht(__le16 vht_rate) -{ - u8 i, j, tmp_rate; - u32 rate_bitmap = 0; - - for (i = j = 0; i < 4; i += 2, j += 10) { - tmp_rate = (le16_to_cpu(vht_rate) >> i) & 3; - - switch (tmp_rate) { - case 2: - rate_bitmap = rate_bitmap | (0x03ff << j); - break; - case 1: - rate_bitmap = rate_bitmap | (0x01ff << j); - break; - case 0: - rate_bitmap = rate_bitmap | (0x00ff << j); - break; - default: - break; - } - } - - return rate_bitmap; -} - -static u32 _rtl8821ae_set_ra_vht_ratr_bitmap(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - u32 ratr_bitmap) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 ret_bitmap = ratr_bitmap; - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40 - || rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) - ret_bitmap = ratr_bitmap; - else if (wirelessmode == WIRELESS_MODE_AC_5G - || wirelessmode == WIRELESS_MODE_AC_24G) { - if (rtlphy->rf_type == RF_1T1R) - ret_bitmap = ratr_bitmap & (~BIT21); - else - ret_bitmap = ratr_bitmap & (~(BIT31|BIT21)); - } - - return ret_bitmap; -} - -static u8 _rtl8821ae_get_vht_eni(enum wireless_mode wirelessmode, - u32 ratr_bitmap) -{ - u8 ret = 0; - if (wirelessmode < WIRELESS_MODE_N_24G) - ret = 0; - else if (wirelessmode == WIRELESS_MODE_AC_24G) { - if (ratr_bitmap & 0xfff00000) /* Mix , 2SS */ - ret = 3; - else /* Mix, 1SS */ - ret = 2; - } else if (wirelessmode == WIRELESS_MODE_AC_5G) { - ret = 1; - } /* VHT */ - - return ret << 4; -} - -static u8 _rtl8821ae_get_ra_ldpc(struct ieee80211_hw *hw, - u8 mac_id, struct rtl_sta_info *sta_entry, - enum wireless_mode wirelessmode) -{ - u8 b_ldpc = 0; - /*not support ldpc, do not open*/ - return b_ldpc << 2; -} - -static u8 _rtl8821ae_get_ra_rftype(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - u32 ratr_bitmap) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 rf_type = RF_1T1R; - - if (rtlphy->rf_type == RF_1T1R) - rf_type = RF_1T1R; - else if (wirelessmode == WIRELESS_MODE_AC_5G - || wirelessmode == WIRELESS_MODE_AC_24G - || wirelessmode == WIRELESS_MODE_AC_ONLY) { - if (ratr_bitmap & 0xffc00000) - rf_type = RF_2T2R; - } else if (wirelessmode == WIRELESS_MODE_N_5G - || wirelessmode == WIRELESS_MODE_N_24G) { - if (ratr_bitmap & 0xfff00000) - rf_type = RF_2T2R; - } - - return rf_type; -} - -static bool _rtl8821ae_get_ra_shortgi(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - u8 mac_id) -{ - bool b_short_gi = false; - u8 b_curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - 1 : 0; - u8 b_curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? - 1 : 0; - u8 b_curshortgi_80mhz = 0; - b_curshortgi_80mhz = (sta->vht_cap.cap & - IEEE80211_VHT_CAP_SHORT_GI_80) ? 1 : 0; - - if (mac_id == MAC_ID_STATIC_FOR_BROADCAST_MULTICAST) - b_short_gi = false; - - if (b_curshortgi_40mhz || b_curshortgi_80mhz - || b_curshortgi_20mhz) - b_short_gi = true; - - return b_short_gi; -} - -static void rtl8821ae_update_hal_rate_mask(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_sta_info *sta_entry = NULL; - u32 ratr_bitmap; - u8 ratr_index; - enum wireless_mode wirelessmode = 0; - u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) - ? 1 : 0; - bool b_shortgi = false; - u8 rate_mask[7]; - u8 macid = 0; - u8 mimo_ps = IEEE80211_SMPS_OFF; - u8 rf_type; - - sta_entry = (struct rtl_sta_info *)sta->drv_priv; - wirelessmode = sta_entry->wireless_mode; - - RT_TRACE(rtlpriv, COMP_RATR, DBG_LOUD, - "wireless mode = 0x%x\n", wirelessmode); - if (mac->opmode == NL80211_IFTYPE_STATION || - mac->opmode == NL80211_IFTYPE_MESH_POINT) { - curtxbw_40mhz = mac->bw_40; - } else if (mac->opmode == NL80211_IFTYPE_AP || - mac->opmode == NL80211_IFTYPE_ADHOC) - macid = sta->aid + 1; - if (wirelessmode == WIRELESS_MODE_N_5G || - wirelessmode == WIRELESS_MODE_AC_5G || - wirelessmode == WIRELESS_MODE_A) - ratr_bitmap = sta->supp_rates[NL80211_BAND_5GHZ] << 4; - else - ratr_bitmap = sta->supp_rates[NL80211_BAND_2GHZ]; - - if (mac->opmode == NL80211_IFTYPE_ADHOC) - ratr_bitmap = 0xfff; - - if (wirelessmode == WIRELESS_MODE_N_24G - || wirelessmode == WIRELESS_MODE_N_5G) - ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | - sta->ht_cap.mcs.rx_mask[0] << 12); - else if (wirelessmode == WIRELESS_MODE_AC_24G - || wirelessmode == WIRELESS_MODE_AC_5G - || wirelessmode == WIRELESS_MODE_AC_ONLY) - ratr_bitmap |= _rtl8821ae_rate_to_bitmap_2ssvht( - sta->vht_cap.vht_mcs.rx_mcs_map) << 12; - - b_shortgi = _rtl8821ae_get_ra_shortgi(hw, sta, macid); - rf_type = _rtl8821ae_get_ra_rftype(hw, wirelessmode, ratr_bitmap); - -/*mac id owner*/ - switch (wirelessmode) { - case WIRELESS_MODE_B: - ratr_index = RATR_INX_WIRELESS_B; - if (ratr_bitmap & 0x0000000c) - ratr_bitmap &= 0x0000000d; - else - ratr_bitmap &= 0x0000000f; - break; - case WIRELESS_MODE_G: - ratr_index = RATR_INX_WIRELESS_GB; - - if (rssi_level == 1) - ratr_bitmap &= 0x00000f00; - else if (rssi_level == 2) - ratr_bitmap &= 0x00000ff0; - else - ratr_bitmap &= 0x00000ff5; - break; - case WIRELESS_MODE_A: - ratr_index = RATR_INX_WIRELESS_G; - ratr_bitmap &= 0x00000ff0; - break; - case WIRELESS_MODE_N_24G: - case WIRELESS_MODE_N_5G: - if (wirelessmode == WIRELESS_MODE_N_24G) - ratr_index = RATR_INX_WIRELESS_NGB; - else - ratr_index = RATR_INX_WIRELESS_NG; - - if (mimo_ps == IEEE80211_SMPS_STATIC - || mimo_ps == IEEE80211_SMPS_DYNAMIC) { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff005; - } else { - if (rf_type == RF_1T1R) { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x000f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x000ff000; - else - ratr_bitmap &= 0x000ff005; - } - } else { - if (curtxbw_40mhz) { - if (rssi_level == 1) - ratr_bitmap &= 0x0fff0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0ffff000; - else - ratr_bitmap &= 0x0ffff015; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0x0fff0000; - else if (rssi_level == 2) - ratr_bitmap &= 0x0ffff000; - else - ratr_bitmap &= 0x0ffff005; - } - } - } - break; - - case WIRELESS_MODE_AC_24G: - ratr_index = RATR_INX_WIRELESS_AC_24N; - if (rssi_level == 1) - ratr_bitmap &= 0xfc3f0000; - else if (rssi_level == 2) - ratr_bitmap &= 0xfffff000; - else - ratr_bitmap &= 0xffffffff; - break; - - case WIRELESS_MODE_AC_5G: - ratr_index = RATR_INX_WIRELESS_AC_5N; - - if (rf_type == RF_1T1R) { - if (rssi_level == 1) /*add by Gary for ac-series*/ - ratr_bitmap &= 0x003f8000; - else if (rssi_level == 2) - ratr_bitmap &= 0x003ff000; - else - ratr_bitmap &= 0x003ff010; - } else { - if (rssi_level == 1) - ratr_bitmap &= 0xfe3f8000; - else if (rssi_level == 2) - ratr_bitmap &= 0xfffff000; - else - ratr_bitmap &= 0xfffff010; - } - break; - - default: - ratr_index = RATR_INX_WIRELESS_NGB; - - if (rf_type == RF_1T2R) - ratr_bitmap &= 0x000ff0ff; - else - ratr_bitmap &= 0x0f8ff0ff; - break; - } - - ratr_index = _rtl8821ae_mrate_idx_to_arfr_id(hw, ratr_index, wirelessmode); - sta_entry->ratr_index = ratr_index; - ratr_bitmap = _rtl8821ae_set_ra_vht_ratr_bitmap(hw, wirelessmode, - ratr_bitmap); - - RT_TRACE(rtlpriv, COMP_RATR, DBG_LOUD, - "ratr_bitmap :%x\n", ratr_bitmap); - - /* *(u32 *)& rate_mask = EF4BYTE((ratr_bitmap & 0x0fffffff) | - (ratr_index << 28)); */ - - rate_mask[0] = macid; - rate_mask[1] = ratr_index | (b_shortgi ? 0x80 : 0x00); - rate_mask[2] = rtlphy->current_chan_bw - | _rtl8821ae_get_vht_eni(wirelessmode, ratr_bitmap) - | _rtl8821ae_get_ra_ldpc(hw, macid, sta_entry, wirelessmode); - - rate_mask[3] = (u8)(ratr_bitmap & 0x000000ff); - rate_mask[4] = (u8)((ratr_bitmap & 0x0000ff00) >> 8); - rate_mask[5] = (u8)((ratr_bitmap & 0x00ff0000) >> 16); - rate_mask[6] = (u8)((ratr_bitmap & 0xff000000) >> 24); - - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, - "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x:%x:%x\n", - ratr_index, ratr_bitmap, - rate_mask[0], rate_mask[1], - rate_mask[2], rate_mask[3], - rate_mask[4], rate_mask[5], - rate_mask[6]); - rtl8821ae_fill_h2c_cmd(hw, H2C_8821AE_RA_MASK, 7, rate_mask); - _rtl8821ae_set_bcn_ctrl_reg(hw, BIT(3), 0); -} - -void rtl8821ae_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - if (rtlpriv->dm.useramask) - rtl8821ae_update_hal_rate_mask(hw, sta, rssi_level); - else - /*RT_TRACE(rtlpriv, COMP_RATR,DBG_LOUD, - "rtl8821ae_update_hal_rate_tbl() Error! 8821ae FW RA Only");*/ - rtl8821ae_update_hal_rate_table(hw, sta); -} - -void rtl8821ae_update_channel_access_setting(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - u8 wireless_mode = mac->mode; - u8 sifs_timer, r2t_sifs; - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, - (u8 *)&mac->slot_time); - if (wireless_mode == WIRELESS_MODE_G) - sifs_timer = 0x0a; - else - sifs_timer = 0x0e; - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); - - r2t_sifs = 0xa; - - if (wireless_mode == WIRELESS_MODE_AC_5G && - (mac->vht_ldpc_cap & LDPC_VHT_ENABLE_RX) && - (mac->vht_stbc_cap & STBC_VHT_ENABLE_RX)) { - if (mac->vendor == PEER_ATH) - r2t_sifs = 0x8; - else - r2t_sifs = 0xa; - } else if (wireless_mode == WIRELESS_MODE_AC_5G) { - r2t_sifs = 0xa; - } - - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_R2T_SIFS, (u8 *)&r2t_sifs); -} - -bool rtl8821ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; - u8 u1tmp = 0; - bool b_actuallyset = false; - - if (rtlpriv->rtlhal.being_init_adapter) - return false; - - if (ppsc->swrf_processing) - return false; - - spin_lock(&rtlpriv->locks.rf_ps_lock); - if (ppsc->rfchange_inprogress) { - spin_unlock(&rtlpriv->locks.rf_ps_lock); - return false; - } else { - ppsc->rfchange_inprogress = true; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } - - cur_rfstate = ppsc->rfpwr_state; - - rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL_2, - rtl_read_byte(rtlpriv, - REG_GPIO_IO_SEL_2) & ~(BIT(1))); - - u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL_2); - - if (rtlphy->polarity_ctl) - e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFOFF : ERFON; - else - e_rfpowerstate_toset = (u1tmp & BIT(1)) ? ERFON : ERFOFF; - - if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "GPIOChangeRF - HW Radio ON, RF ON\n"); - - e_rfpowerstate_toset = ERFON; - ppsc->hwradiooff = false; - b_actuallyset = true; - } else if ((!ppsc->hwradiooff) - && (e_rfpowerstate_toset == ERFOFF)) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "GPIOChangeRF - HW Radio OFF, RF OFF\n"); - - e_rfpowerstate_toset = ERFOFF; - ppsc->hwradiooff = true; - b_actuallyset = true; - } - - if (b_actuallyset) { - spin_lock(&rtlpriv->locks.rf_ps_lock); - ppsc->rfchange_inprogress = false; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } else { - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - - spin_lock(&rtlpriv->locks.rf_ps_lock); - ppsc->rfchange_inprogress = false; - spin_unlock(&rtlpriv->locks.rf_ps_lock); - } - - *valid = 1; - return !ppsc->hwradiooff; -} - -void rtl8821ae_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 *macaddr = p_macaddr; - u32 entry_id = 0; - bool is_pairwise = false; - - static u8 cam_const_addr[4][6] = { - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} - }; - static u8 cam_const_broad[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - - if (clear_all) { - u8 idx = 0; - u8 cam_offset = 0; - u8 clear_number = 5; - - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n"); - - for (idx = 0; idx < clear_number; idx++) { - rtl_cam_mark_invalid(hw, cam_offset + idx); - rtl_cam_empty_entry(hw, cam_offset + idx); - - if (idx < 5) { - memset(rtlpriv->sec.key_buf[idx], 0, - MAX_KEY_LEN); - rtlpriv->sec.key_len[idx] = 0; - } - } - } else { - switch (enc_algo) { - case WEP40_ENCRYPTION: - enc_algo = CAM_WEP40; - break; - case WEP104_ENCRYPTION: - enc_algo = CAM_WEP104; - break; - case TKIP_ENCRYPTION: - enc_algo = CAM_TKIP; - break; - case AESCCMP_ENCRYPTION: - enc_algo = CAM_AES; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - enc_algo = CAM_TKIP; - break; - } - - if (is_wepkey || rtlpriv->sec.use_defaultkey) { - macaddr = cam_const_addr[key_index]; - entry_id = key_index; - } else { - if (is_group) { - macaddr = cam_const_broad; - entry_id = key_index; - } else { - if (mac->opmode == NL80211_IFTYPE_AP) { - entry_id = rtl_cam_get_free_entry(hw, p_macaddr); - if (entry_id >= TOTAL_CAM_ENTRY) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, - "Can not find free hwsecurity cam entry\n"); - return; - } - } else { - entry_id = CAM_PAIRWISE_KEY_POSITION; - } - - key_index = PAIRWISE_KEYIDX; - is_pairwise = true; - } - } - - if (rtlpriv->sec.key_len[key_index] == 0) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "delete one entry, entry_id is %d\n", - entry_id); - if (mac->opmode == NL80211_IFTYPE_AP) - rtl_cam_del_entry(hw, p_macaddr); - rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "add one entry\n"); - if (is_pairwise) { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set Pairwise key\n"); - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[key_index]); - } else { - RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, - "set group key\n"); - - if (mac->opmode == NL80211_IFTYPE_ADHOC) { - rtl_cam_add_one_entry(hw, - rtlefuse->dev_addr, - PAIRWISE_KEYIDX, - CAM_PAIRWISE_KEY_POSITION, - enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf - [entry_id]); - } - - rtl_cam_add_one_entry(hw, macaddr, key_index, - entry_id, enc_algo, - CAM_CONFIG_NO_USEDK, - rtlpriv->sec.key_buf[entry_id]); - } - } - } -} - -void rtl8821ae_bt_reg_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - /* 0:Low, 1:High, 2:From Efuse. */ - rtlpriv->btcoexist.reg_bt_iso = 2; - /* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter. */ - rtlpriv->btcoexist.reg_bt_sco = 3; - /* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */ - rtlpriv->btcoexist.reg_bt_sco = 0; -} - -void rtl8821ae_bt_hw_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_init_hw_config(rtlpriv); -} - -void rtl8821ae_suspend(struct ieee80211_hw *hw) -{ -} - -void rtl8821ae_resume(struct ieee80211_hw *hw) -{ -} - -/* Turn on AAP (RCR:bit 0) for promicuous mode. */ -void rtl8821ae_allow_all_destaddr(struct ieee80211_hw *hw, - bool allow_all_da, bool write_into_reg) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - if (allow_all_da) /* Set BIT0 */ - rtlpci->receive_config |= RCR_AAP; - else /* Clear BIT0 */ - rtlpci->receive_config &= ~RCR_AAP; - - if (write_into_reg) - rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); - - RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD, - "receive_config=0x%08X, write_into_reg=%d\n", - rtlpci->receive_config, write_into_reg); -} - -/* WKFMCAMAddAllEntry8812 */ -void rtl8821ae_add_wowlan_pattern(struct ieee80211_hw *hw, - struct rtl_wow_pattern *rtl_pattern, - u8 index) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 cam = 0; - u8 addr = 0; - u16 rxbuf_addr; - u8 tmp, count = 0; - u16 cam_start; - u16 offset; - - /* Count the WFCAM entry start offset. */ - - /* RX page size = 128 byte */ - offset = MAX_RX_DMA_BUFFER_SIZE_8812 / 128; - /* We should start from the boundry */ - cam_start = offset * 128; - - /* Enable Rx packet buffer access. */ - rtl_write_byte(rtlpriv, REG_PKT_BUFF_ACCESS_CTRL, RXPKT_BUF_SELECT); - for (addr = 0; addr < WKFMCAM_ADDR_NUM; addr++) { - /* Set Rx packet buffer offset. - * RxBufer pointer increases 1, - * we can access 8 bytes in Rx packet buffer. - * CAM start offset (unit: 1 byte) = index*WKFMCAM_SIZE - * RxBufer addr = (CAM start offset + - * per entry offset of a WKFM CAM)/8 - * * index: The index of the wake up frame mask - * * WKFMCAM_SIZE: the total size of one WKFM CAM - * * per entry offset of a WKFM CAM: Addr*4 bytes - */ - rxbuf_addr = (cam_start + index * WKFMCAM_SIZE + addr * 4) >> 3; - /* Set R/W start offset */ - rtl_write_word(rtlpriv, REG_PKTBUF_DBG_CTRL, rxbuf_addr); - - if (addr == 0) { - cam = BIT(31) | rtl_pattern->crc; - - if (rtl_pattern->type == UNICAST_PATTERN) - cam |= BIT(24); - else if (rtl_pattern->type == MULTICAST_PATTERN) - cam |= BIT(25); - else if (rtl_pattern->type == BROADCAST_PATTERN) - cam |= BIT(26); - - rtl_write_dword(rtlpriv, REG_PKTBUF_DBG_DATA_L, cam); - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "WRITE entry[%d] 0x%x: %x\n", addr, - REG_PKTBUF_DBG_DATA_L, cam); - - /* Write to Rx packet buffer. */ - rtl_write_word(rtlpriv, REG_RXPKTBUF_CTRL, 0x0f01); - } else if (addr == 2 || addr == 4) {/* WKFM[127:0] */ - cam = rtl_pattern->mask[addr - 2]; - - rtl_write_dword(rtlpriv, REG_PKTBUF_DBG_DATA_L, cam); - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "WRITE entry[%d] 0x%x: %x\n", addr, - REG_PKTBUF_DBG_DATA_L, cam); - - rtl_write_word(rtlpriv, REG_RXPKTBUF_CTRL, 0x0f01); - } else if (addr == 3 || addr == 5) {/* WKFM[127:0] */ - cam = rtl_pattern->mask[addr - 2]; - - rtl_write_dword(rtlpriv, REG_PKTBUF_DBG_DATA_H, cam); - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "WRITE entry[%d] 0x%x: %x\n", addr, - REG_PKTBUF_DBG_DATA_H, cam); - - rtl_write_word(rtlpriv, REG_RXPKTBUF_CTRL, 0xf001); - } - - count = 0; - do { - tmp = rtl_read_byte(rtlpriv, REG_RXPKTBUF_CTRL); - udelay(2); - count++; - } while (tmp && count < 100); - - RT_ASSERT((count < 100), - "Write wake up frame mask FAIL %d value!\n", tmp); - } - /* Disable Rx packet buffer access. */ - rtl_write_byte(rtlpriv, REG_PKT_BUFF_ACCESS_CTRL, - DISABLE_TRXPKT_BUF_ACCESS); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.h b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.h deleted file mode 100644 index a3553e3abaa1..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.h +++ /dev/null @@ -1,70 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8821AE_HW_H__ -#define __RTL8821AE_HW_H__ - -void rtl8821ae_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl8821ae_read_eeprom_info(struct ieee80211_hw *hw); - -void rtl8821ae_interrupt_recognized(struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb); -int rtl8821ae_hw_init(struct ieee80211_hw *hw); -void rtl8821ae_card_disable(struct ieee80211_hw *hw); -void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw); -void rtl8821ae_disable_interrupt(struct ieee80211_hw *hw); -int rtl8821ae_set_network_type(struct ieee80211_hw *hw, - enum nl80211_iftype type); -void rtl8821ae_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); -void rtl8821ae_set_qos(struct ieee80211_hw *hw, int aci); -void rtl8821ae_set_beacon_related_registers(struct ieee80211_hw *hw); -void rtl8821ae_set_beacon_interval(struct ieee80211_hw *hw); -void rtl8821ae_update_interrupt_mask(struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr); -void rtl8821ae_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); -void rtl8821ae_update_hal_rate_tbl(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - u8 rssi_level); -void rtl8821ae_update_channel_access_setting(struct ieee80211_hw *hw); -bool rtl8821ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); -void rtl8821ae_enable_hw_security_config(struct ieee80211_hw *hw); -void rtl8821ae_set_key(struct ieee80211_hw *hw, u32 key_index, - u8 *p_macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all); - -void rtl8821ae_bt_reg_init(struct ieee80211_hw *hw); -void rtl8821ae_bt_hw_init(struct ieee80211_hw *hw); -void rtl8821ae_suspend(struct ieee80211_hw *hw); -void rtl8821ae_resume(struct ieee80211_hw *hw); -void rtl8821ae_allow_all_destaddr(struct ieee80211_hw *hw, - bool allow_all_da, - bool write_into_reg); -void _rtl8821ae_stop_tx_beacon(struct ieee80211_hw *hw); -void _rtl8821ae_resume_tx_beacon(struct ieee80211_hw *hw); -void rtl8821ae_add_wowlan_pattern(struct ieee80211_hw *hw, - struct rtl_wow_pattern *rtl_pattern, - u8 index); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/led.c b/drivers/net/wireless/rtlwifi/rtl8821ae/led.c deleted file mode 100644 index ba1946a0280e..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/led.c +++ /dev/null @@ -1,237 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "reg.h" -#include "led.h" - -static void _rtl8821ae_init_led(struct ieee80211_hw *hw, - struct rtl_led *pled, - enum rtl_led_pin ledpin) -{ - pled->hw = hw; - pled->ledpin = ledpin; - pled->ledon = false; -} - -void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - u8 ledcfg; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - ledcfg &= ~BIT(6); - rtl_write_byte(rtlpriv, - REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5)); - break; - case LED_PIN_LED1: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); - rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg & 0x10); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - pled->ledon = true; -} - -void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - u16 ledreg = REG_LEDCFG1; - u8 ledcfg = 0; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - switch (pled->ledpin) { - case LED_PIN_LED0: - ledreg = REG_LEDCFG1; - break; - - case LED_PIN_LED1: - ledreg = REG_LEDCFG2; - break; - - case LED_PIN_GPIO0: - default: - break; - } - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, - "In SwLedOn, LedAddr:%X LEDPIN=%d\n", - ledreg, pled->ledpin); - - ledcfg = rtl_read_byte(rtlpriv, ledreg); - ledcfg |= BIT(5); /*Set 0x4c[21]*/ - ledcfg &= ~(BIT(7) | BIT(6) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); - /*Clear 0x4c[23:22] and 0x4c[19:16]*/ - rtl_write_byte(rtlpriv, ledreg, ledcfg); /*SW control led0 on.*/ - pled->ledon = true; -} - -void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - u8 ledcfg; - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, - "LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin); - - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); - - switch (pled->ledpin) { - case LED_PIN_GPIO0: - break; - case LED_PIN_LED0: - ledcfg &= 0xf0; - if (pcipriv->ledctl.led_opendrain) { - ledcfg &= 0x90; /* Set to software control. */ - rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg|BIT(3))); - ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); - ledcfg &= 0xFE; - rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg); - } else { - ledcfg &= ~BIT(6); - rtl_write_byte(rtlpriv, REG_LEDCFG2, - (ledcfg | BIT(3) | BIT(5))); - } - break; - case LED_PIN_LED1: - ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); - ledcfg &= 0x10; /* Set to software control. */ - rtl_write_byte(rtlpriv, REG_LEDCFG1, ledcfg|BIT(3)); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, - "switch case not process\n"); - break; - } - pled->ledon = false; -} - -void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) -{ - u16 ledreg = REG_LEDCFG1; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - - switch (pled->ledpin) { - case LED_PIN_LED0: - ledreg = REG_LEDCFG1; - break; - - case LED_PIN_LED1: - ledreg = REG_LEDCFG2; - break; - - case LED_PIN_GPIO0: - default: - break; - } - - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, - "In SwLedOff,LedAddr:%X LEDPIN=%d\n", - ledreg, pled->ledpin); - /*Open-drain arrangement for controlling the LED*/ - if (pcipriv->ledctl.led_opendrain) { - u8 ledcfg = rtl_read_byte(rtlpriv, ledreg); - - ledreg &= 0xd0; /* Set to software control.*/ - rtl_write_byte(rtlpriv, ledreg, (ledcfg | BIT(3))); - - /*Open-drain arrangement*/ - ledcfg = rtl_read_byte(rtlpriv, REG_MAC_PINMUX_CFG); - ledcfg &= 0xFE;/*Set GPIO[8] to input mode*/ - rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, ledcfg); - } else { - rtl_write_byte(rtlpriv, ledreg, 0x28); - } - - pled->ledon = false; -} - -void rtl8821ae_init_sw_leds(struct ieee80211_hw *hw) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - - _rtl8821ae_init_led(hw, &pcipriv->ledctl.sw_led0, LED_PIN_LED0); - _rtl8821ae_init_led(hw, &pcipriv->ledctl.sw_led1, LED_PIN_LED1); -} - -static void _rtl8821ae_sw_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_led *pLed0 = &pcipriv->ledctl.sw_led0; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - switch (ledaction) { - case LED_CTL_POWER_ON: - case LED_CTL_LINK: - case LED_CTL_NO_LINK: - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_sw_led_on(hw, pLed0); - else - rtl8821ae_sw_led_on(hw, pLed0); - break; - case LED_CTL_POWER_OFF: - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtl8812ae_sw_led_off(hw, pLed0); - else - rtl8821ae_sw_led_off(hw, pLed0); - break; - default: - break; - } -} - -void rtl8821ae_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && - (ledaction == LED_CTL_TX || - ledaction == LED_CTL_RX || - ledaction == LED_CTL_SITE_SURVEY || - ledaction == LED_CTL_LINK || - ledaction == LED_CTL_NO_LINK || - ledaction == LED_CTL_START_TO_LINK || - ledaction == LED_CTL_POWER_ON)) { - return; - } - RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d,\n", - ledaction); - _rtl8821ae_sw_led_control(hw, ledaction); -} diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/led.h b/drivers/net/wireless/rtlwifi/rtl8821ae/led.h deleted file mode 100644 index 038e64e18ae8..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/led.h +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8821AE_LED_H__ -#define __RTL8821AE_LED_H__ - -void rtl8821ae_init_sw_leds(struct ieee80211_hw *hw); -void rtl8821ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8812ae_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8821ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8812ae_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); -void rtl8821ae_led_control(struct ieee80211_hw *hw, - enum led_ctl_mode ledaction); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c deleted file mode 100644 index 9b4d8a637915..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c +++ /dev/null @@ -1,4858 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../ps.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" -#include "table.h" -#include "trx.h" -#include "../btcoexist/halbt_precomp.h" -#include "hw.h" -#include "../efuse.h" - -#define READ_NEXT_PAIR(array_table, v1, v2, i) \ - do { \ - i += 2; \ - v1 = array_table[i]; \ - v2 = array_table[i+1]; \ - } while (0) - -static u32 _rtl8821ae_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset); -static void _rtl8821ae_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data); -static u32 _rtl8821ae_phy_calculate_bit_shift(u32 bitmask); -static bool _rtl8821ae_phy_bb8821a_config_parafile(struct ieee80211_hw *hw); -/*static bool _rtl8812ae_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);*/ -static bool _rtl8821ae_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); -static bool _rtl8821ae_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype); -static bool _rtl8821ae_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype); -static void phy_init_bb_rf_register_definition(struct ieee80211_hw *hw); - -static long _rtl8821ae_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - u8 txpwridx); -static void rtl8821ae_phy_set_rf_on(struct ieee80211_hw *hw); -static void rtl8821ae_phy_set_io(struct ieee80211_hw *hw); - -static void rtl8812ae_fixspur(struct ieee80211_hw *hw, - enum ht_channel_width band_width, u8 channel) -{ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - /*C cut Item12 ADC FIFO CLOCK*/ - if (IS_VENDOR_8812A_C_CUT(rtlhal->version)) { - if (band_width == HT_CHANNEL_WIDTH_20_40 && channel == 11) - rtl_set_bbreg(hw, RRFMOD, 0xC00, 0x3); - /* 0x8AC[11:10] = 2'b11*/ - else - rtl_set_bbreg(hw, RRFMOD, 0xC00, 0x2); - /* 0x8AC[11:10] = 2'b10*/ - - /* <20120914, Kordan> A workarould to resolve - * 2480Mhz spur by setting ADC clock as 160M. (Asked by Binson) - */ - if (band_width == HT_CHANNEL_WIDTH_20 && - (channel == 13 || channel == 14)) { - rtl_set_bbreg(hw, RRFMOD, 0x300, 0x3); - /*0x8AC[9:8] = 2'b11*/ - rtl_set_bbreg(hw, RADC_BUF_CLK, BIT(30), 1); - /* 0x8C4[30] = 1*/ - } else if (band_width == HT_CHANNEL_WIDTH_20_40 && - channel == 11) { - rtl_set_bbreg(hw, RADC_BUF_CLK, BIT(30), 1); - /*0x8C4[30] = 1*/ - } else if (band_width != HT_CHANNEL_WIDTH_80) { - rtl_set_bbreg(hw, RRFMOD, 0x300, 0x2); - /*0x8AC[9:8] = 2'b10*/ - rtl_set_bbreg(hw, RADC_BUF_CLK, BIT(30), 0); - /*0x8C4[30] = 0*/ - } - } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - /* <20120914, Kordan> A workarould to resolve - * 2480Mhz spur by setting ADC clock as 160M. - */ - if (band_width == HT_CHANNEL_WIDTH_20 && - (channel == 13 || channel == 14)) - rtl_set_bbreg(hw, RRFMOD, 0x300, 0x3); - /*0x8AC[9:8] = 11*/ - else if (channel <= 14) /*2.4G only*/ - rtl_set_bbreg(hw, RRFMOD, 0x300, 0x2); - /*0x8AC[9:8] = 10*/ - } -} - -u32 rtl8821ae_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, - u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 returnvalue, originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x)\n", - regaddr, bitmask); - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = _rtl8821ae_phy_calculate_bit_shift(bitmask); - returnvalue = (originalvalue & bitmask) >> bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "BBR MASK=0x%x Addr[0x%x]=0x%x\n", - bitmask, regaddr, originalvalue); - return returnvalue; -} - -void rtl8821ae_phy_set_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 originalvalue, bitshift; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); - - if (bitmask != MASKDWORD) { - originalvalue = rtl_read_dword(rtlpriv, regaddr); - bitshift = _rtl8821ae_phy_calculate_bit_shift(bitmask); - data = ((originalvalue & (~bitmask)) | - ((data << bitshift) & bitmask)); - } - - rtl_write_dword(rtlpriv, regaddr, data); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x)\n", - regaddr, bitmask, data); -} - -u32 rtl8821ae_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, readback_value, bitshift; - unsigned long flags; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", - regaddr, rfpath, bitmask); - - spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); - - original_value = _rtl8821ae_phy_rf_serial_read(hw, rfpath, regaddr); - bitshift = _rtl8821ae_phy_calculate_bit_shift(bitmask); - readback_value = (original_value & bitmask) >> bitshift; - - spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", - regaddr, rfpath, bitmask, original_value); - - return readback_value; -} - -void rtl8821ae_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 original_value, bitshift; - unsigned long flags; - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); - - spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); - - if (bitmask != RFREG_OFFSET_MASK) { - original_value = - _rtl8821ae_phy_rf_serial_read(hw, rfpath, regaddr); - bitshift = _rtl8821ae_phy_calculate_bit_shift(bitmask); - data = ((original_value & (~bitmask)) | (data << bitshift)); - } - - _rtl8821ae_phy_rf_serial_write(hw, rfpath, regaddr, data); - - spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); - - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", - regaddr, bitmask, data, rfpath); -} - -static u32 _rtl8821ae_phy_rf_serial_read(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - bool is_pi_mode = false; - u32 retvalue = 0; - - /* 2009/06/17 MH We can not execute IO for power - save or other accident mode.*/ - if (RT_CANNOT_IO(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "return all one\n"); - return 0xFFFFFFFF; - } - /* <20120809, Kordan> CCA OFF(when entering), - asked by James to avoid reading the wrong value. - <20120828, Kordan> Toggling CCA would affect RF 0x0, skip it!*/ - if (offset != 0x0 && - !((rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) || - (IS_VENDOR_8812A_C_CUT(rtlhal->version)))) - rtl_set_bbreg(hw, RCCAONSEC, 0x8, 1); - offset &= 0xff; - - if (rfpath == RF90_PATH_A) - is_pi_mode = (bool)rtl_get_bbreg(hw, 0xC00, 0x4); - else if (rfpath == RF90_PATH_B) - is_pi_mode = (bool)rtl_get_bbreg(hw, 0xE00, 0x4); - - rtl_set_bbreg(hw, RHSSIREAD_8821AE, 0xff, offset); - - if ((rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) || - (IS_VENDOR_8812A_C_CUT(rtlhal->version))) - udelay(20); - - if (is_pi_mode) { - if (rfpath == RF90_PATH_A) - retvalue = - rtl_get_bbreg(hw, RA_PIREAD_8821A, BLSSIREADBACKDATA); - else if (rfpath == RF90_PATH_B) - retvalue = - rtl_get_bbreg(hw, RB_PIREAD_8821A, BLSSIREADBACKDATA); - } else { - if (rfpath == RF90_PATH_A) - retvalue = - rtl_get_bbreg(hw, RA_SIREAD_8821A, BLSSIREADBACKDATA); - else if (rfpath == RF90_PATH_B) - retvalue = - rtl_get_bbreg(hw, RB_SIREAD_8821A, BLSSIREADBACKDATA); - } - - /*<20120809, Kordan> CCA ON(when exiting), - * asked by James to avoid reading the wrong value. - * <20120828, Kordan> Toggling CCA would affect RF 0x0, skip it! - */ - if (offset != 0x0 && - !((rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) || - (IS_VENDOR_8812A_C_CUT(rtlhal->version)))) - rtl_set_bbreg(hw, RCCAONSEC, 0x8, 0); - return retvalue; -} - -static void _rtl8821ae_phy_rf_serial_write(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 offset, - u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; - u32 data_and_addr; - u32 newoffset; - - if (RT_CANNOT_IO(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "stop\n"); - return; - } - offset &= 0xff; - newoffset = offset; - data_and_addr = ((newoffset << 20) | - (data & 0x000fffff)) & 0x0fffffff; - rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); - RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, - "RFW-%d Addr[0x%x]=0x%x\n", - rfpath, pphyreg->rf3wire_offset, data_and_addr); -} - -static u32 _rtl8821ae_phy_calculate_bit_shift(u32 bitmask) -{ - u32 i; - - for (i = 0; i <= 31; i++) { - if (((bitmask >> i) & 0x1) == 1) - break; - } - return i; -} - -bool rtl8821ae_phy_mac_config(struct ieee80211_hw *hw) -{ - bool rtstatus = 0; - - rtstatus = _rtl8821ae_phy_config_mac_with_headerfile(hw); - - return rtstatus; -} - -bool rtl8821ae_phy_bb_config(struct ieee80211_hw *hw) -{ - bool rtstatus = true; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 regval; - u8 crystal_cap; - - phy_init_bb_rf_register_definition(hw); - - regval = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); - regval |= FEN_PCIEA; - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, regval); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, - regval | FEN_BB_GLB_RSTN | FEN_BBRSTB); - - rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x7); - rtl_write_byte(rtlpriv, REG_OPT_CTRL + 2, 0x7); - - rtstatus = _rtl8821ae_phy_bb8821a_config_parafile(hw); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - crystal_cap = rtlefuse->crystalcap & 0x3F; - rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0x7FF80000, - (crystal_cap | (crystal_cap << 6))); - } else { - crystal_cap = rtlefuse->crystalcap & 0x3F; - rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, - (crystal_cap | (crystal_cap << 6))); - } - rtlphy->reg_837 = rtl_read_byte(rtlpriv, 0x837); - - return rtstatus; -} - -bool rtl8821ae_phy_rf_config(struct ieee80211_hw *hw) -{ - return rtl8821ae_phy_rf6052_config(hw); -} - -u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band, - u8 rf_path) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtlpriv); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - char reg_swing_2g = -1;/* 0xff; */ - char reg_swing_5g = -1;/* 0xff; */ - char swing_2g = -1 * reg_swing_2g; - char swing_5g = -1 * reg_swing_5g; - u32 out = 0x200; - const char auto_temp = -1; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, - "===> PHY_GetTxBBSwing_8812A, bbSwing_2G: %d, bbSwing_5G: %d,autoload_failflag=%d.\n", - (int)swing_2g, (int)swing_5g, - (int)rtlefuse->autoload_failflag); - - if (rtlefuse->autoload_failflag) { - if (band == BAND_ON_2_4G) { - rtldm->swing_diff_2g = swing_2g; - if (swing_2g == 0) { - out = 0x200; /* 0 dB */ - } else if (swing_2g == -3) { - out = 0x16A; /* -3 dB */ - } else if (swing_2g == -6) { - out = 0x101; /* -6 dB */ - } else if (swing_2g == -9) { - out = 0x0B6; /* -9 dB */ - } else { - rtldm->swing_diff_2g = 0; - out = 0x200; - } - } else if (band == BAND_ON_5G) { - rtldm->swing_diff_5g = swing_5g; - if (swing_5g == 0) { - out = 0x200; /* 0 dB */ - } else if (swing_5g == -3) { - out = 0x16A; /* -3 dB */ - } else if (swing_5g == -6) { - out = 0x101; /* -6 dB */ - } else if (swing_5g == -9) { - out = 0x0B6; /* -9 dB */ - } else { - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - rtldm->swing_diff_5g = -3; - out = 0x16A; - } else { - rtldm->swing_diff_5g = 0; - out = 0x200; - } - } - } else { - rtldm->swing_diff_2g = -3; - rtldm->swing_diff_5g = -3; - out = 0x16A; /* -3 dB */ - } - } else { - u32 swing = 0, swing_a = 0, swing_b = 0; - - if (band == BAND_ON_2_4G) { - if (reg_swing_2g == auto_temp) { - efuse_shadow_read(hw, 1, 0xC6, (u32 *)&swing); - swing = (swing == 0xFF) ? 0x00 : swing; - } else if (swing_2g == 0) { - swing = 0x00; /* 0 dB */ - } else if (swing_2g == -3) { - swing = 0x05; /* -3 dB */ - } else if (swing_2g == -6) { - swing = 0x0A; /* -6 dB */ - } else if (swing_2g == -9) { - swing = 0xFF; /* -9 dB */ - } else { - swing = 0x00; - } - } else { - if (reg_swing_5g == auto_temp) { - efuse_shadow_read(hw, 1, 0xC7, (u32 *)&swing); - swing = (swing == 0xFF) ? 0x00 : swing; - } else if (swing_5g == 0) { - swing = 0x00; /* 0 dB */ - } else if (swing_5g == -3) { - swing = 0x05; /* -3 dB */ - } else if (swing_5g == -6) { - swing = 0x0A; /* -6 dB */ - } else if (swing_5g == -9) { - swing = 0xFF; /* -9 dB */ - } else { - swing = 0x00; - } - } - - swing_a = (swing & 0x3) >> 0; /* 0xC6/C7[1:0] */ - swing_b = (swing & 0xC) >> 2; /* 0xC6/C7[3:2] */ - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, - "===> PHY_GetTxBBSwing_8812A, swingA: 0x%X, swingB: 0x%X\n", - swing_a, swing_b); - - /* 3 Path-A */ - if (swing_a == 0x0) { - if (band == BAND_ON_2_4G) - rtldm->swing_diff_2g = 0; - else - rtldm->swing_diff_5g = 0; - out = 0x200; /* 0 dB */ - } else if (swing_a == 0x1) { - if (band == BAND_ON_2_4G) - rtldm->swing_diff_2g = -3; - else - rtldm->swing_diff_5g = -3; - out = 0x16A; /* -3 dB */ - } else if (swing_a == 0x2) { - if (band == BAND_ON_2_4G) - rtldm->swing_diff_2g = -6; - else - rtldm->swing_diff_5g = -6; - out = 0x101; /* -6 dB */ - } else if (swing_a == 0x3) { - if (band == BAND_ON_2_4G) - rtldm->swing_diff_2g = -9; - else - rtldm->swing_diff_5g = -9; - out = 0x0B6; /* -9 dB */ - } - /* 3 Path-B */ - if (swing_b == 0x0) { - if (band == BAND_ON_2_4G) - rtldm->swing_diff_2g = 0; - else - rtldm->swing_diff_5g = 0; - out = 0x200; /* 0 dB */ - } else if (swing_b == 0x1) { - if (band == BAND_ON_2_4G) - rtldm->swing_diff_2g = -3; - else - rtldm->swing_diff_5g = -3; - out = 0x16A; /* -3 dB */ - } else if (swing_b == 0x2) { - if (band == BAND_ON_2_4G) - rtldm->swing_diff_2g = -6; - else - rtldm->swing_diff_5g = -6; - out = 0x101; /* -6 dB */ - } else if (swing_b == 0x3) { - if (band == BAND_ON_2_4G) - rtldm->swing_diff_2g = -9; - else - rtldm->swing_diff_5g = -9; - out = 0x0B6; /* -9 dB */ - } - } - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, - "<=== PHY_GetTxBBSwing_8812A, out = 0x%X\n", out); - return out; -} - -void rtl8821ae_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_dm *rtldm = rtl_dm(rtlpriv); - u8 current_band = rtlhal->current_bandtype; - u32 txpath, rxpath; - char bb_diff_between_band; - - txpath = rtl8821ae_phy_query_bb_reg(hw, RTXPATH, 0xf0); - rxpath = rtl8821ae_phy_query_bb_reg(hw, RCCK_RX, 0x0f000000); - rtlhal->current_bandtype = (enum band_type) band; - /* reconfig BB/RF according to wireless mode */ - if (rtlhal->current_bandtype == BAND_ON_2_4G) { - /* BB & RF Config */ - rtl_set_bbreg(hw, ROFDMCCKEN, BOFDMEN|BCCKEN, 0x03); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - /* 0xCB0[15:12] = 0x7 (LNA_On)*/ - rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xF000, 0x7); - /* 0xCB0[7:4] = 0x7 (PAPE_A)*/ - rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xF0, 0x7); - } - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - /*0x834[1:0] = 0x1*/ - rtl_set_bbreg(hw, 0x834, 0x3, 0x1); - } - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - /* 0xC1C[11:8] = 0 */ - rtl_set_bbreg(hw, RA_TXSCALE, 0xF00, 0); - } else { - /* 0x82C[1:0] = 2b'00 */ - rtl_set_bbreg(hw, 0x82c, 0x3, 0); - } - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, - 0x77777777); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, - 0x77777777); - rtl_set_bbreg(hw, RA_RFE_INV, 0x3ff00000, 0x000); - rtl_set_bbreg(hw, RB_RFE_INV, 0x3ff00000, 0x000); - } - - rtl_set_bbreg(hw, RTXPATH, 0xf0, 0x1); - rtl_set_bbreg(hw, RCCK_RX, 0x0f000000, 0x1); - - rtl_write_byte(rtlpriv, REG_CCK_CHECK, 0x0); - } else {/* 5G band */ - u16 count, reg_41a; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - /*0xCB0[15:12] = 0x5 (LNA_On)*/ - rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xF000, 0x5); - /*0xCB0[7:4] = 0x4 (PAPE_A)*/ - rtl_set_bbreg(hw, RA_RFE_PINMUX, 0xF0, 0x4); - } - /*CCK_CHECK_en*/ - rtl_write_byte(rtlpriv, REG_CCK_CHECK, 0x80); - - count = 0; - reg_41a = rtl_read_word(rtlpriv, REG_TXPKT_EMPTY); - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, - "Reg41A value %d", reg_41a); - reg_41a &= 0x30; - while ((reg_41a != 0x30) && (count < 50)) { - udelay(50); - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "Delay 50us\n"); - - reg_41a = rtl_read_word(rtlpriv, REG_TXPKT_EMPTY); - reg_41a &= 0x30; - count++; - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, - "Reg41A value %d", reg_41a); - } - if (count != 0) - RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, - "PHY_SwitchWirelessBand8812(): Switch to 5G Band. Count = %d reg41A=0x%x\n", - count, reg_41a); - - /* 2012/02/01, Sinda add registry to switch workaround - without long-run verification for scan issue. */ - rtl_set_bbreg(hw, ROFDMCCKEN, BOFDMEN|BCCKEN, 0x03); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - /*0x834[1:0] = 0x2*/ - rtl_set_bbreg(hw, 0x834, 0x3, 0x2); - } - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - /* AGC table select */ - /* 0xC1C[11:8] = 1*/ - rtl_set_bbreg(hw, RA_TXSCALE, 0xF00, 1); - } else - /* 0x82C[1:0] = 2'b00 */ - rtl_set_bbreg(hw, 0x82c, 0x3, 1); - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - rtl_set_bbreg(hw, RA_RFE_PINMUX, BMASKDWORD, - 0x77337777); - rtl_set_bbreg(hw, RB_RFE_PINMUX, BMASKDWORD, - 0x77337777); - rtl_set_bbreg(hw, RA_RFE_INV, 0x3ff00000, 0x010); - rtl_set_bbreg(hw, RB_RFE_INV, 0x3ff00000, 0x010); - } - - rtl_set_bbreg(hw, RTXPATH, 0xf0, 0); - rtl_set_bbreg(hw, RCCK_RX, 0x0f000000, 0xf); - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, - "==>PHY_SwitchWirelessBand8812() BAND_ON_5G settings OFDM index 0x%x\n", - rtlpriv->dm.ofdm_index[RF90_PATH_A]); - } - - if ((rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) || - (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)) { - /* 0xC1C[31:21] */ - rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000, - phy_get_tx_swing_8812A(hw, band, RF90_PATH_A)); - /* 0xE1C[31:21] */ - rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000, - phy_get_tx_swing_8812A(hw, band, RF90_PATH_B)); - - /* <20121005, Kordan> When TxPowerTrack is ON, - * we should take care of the change of BB swing. - * That is, reset all info to trigger Tx power tracking. - */ - if (band != current_band) { - bb_diff_between_band = - (rtldm->swing_diff_2g - rtldm->swing_diff_5g); - bb_diff_between_band = (band == BAND_ON_2_4G) ? - bb_diff_between_band : - (-1 * bb_diff_between_band); - rtldm->default_ofdm_index += bb_diff_between_band * 2; - } - rtl8821ae_dm_clear_txpower_tracking_state(hw); - } - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "<==rtl8821ae_phy_switch_wirelessband():Switch Band OK.\n"); - return; -} - -static bool _rtl8821ae_check_condition(struct ieee80211_hw *hw, - const u32 condition) -{ - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 _board = rtlefuse->board_type; /*need efuse define*/ - u32 _interface = 0x01; /* ODM_ITRF_PCIE */ - u32 _platform = 0x08;/* ODM_WIN */ - u32 cond = condition; - - if (condition == 0xCDCDCDCD) - return true; - - cond = condition & 0xFF; - if ((_board != cond) && cond != 0xFF) - return false; - - cond = condition & 0xFF00; - cond = cond >> 8; - if ((_interface & cond) == 0 && cond != 0x07) - return false; - - cond = condition & 0xFF0000; - cond = cond >> 16; - if ((_platform & cond) == 0 && cond != 0x0F) - return false; - return true; -} - -static void _rtl8821ae_config_rf_reg(struct ieee80211_hw *hw, - u32 addr, u32 data, - enum radio_path rfpath, u32 regaddr) -{ - if (addr == 0xfe || addr == 0xffe) { - /* In order not to disturb BT music when - * wifi init.(1ant NIC only) - */ - mdelay(50); - } else { - rtl_set_rfreg(hw, rfpath, regaddr, RFREG_OFFSET_MASK, data); - udelay(1); - } -} - -static void _rtl8821ae_config_rf_radio_a(struct ieee80211_hw *hw, - u32 addr, u32 data) -{ - u32 content = 0x1000; /*RF Content: radio_a_txt*/ - u32 maskforphyset = (u32)(content & 0xE000); - - _rtl8821ae_config_rf_reg(hw, addr, data, - RF90_PATH_A, addr | maskforphyset); -} - -static void _rtl8821ae_config_rf_radio_b(struct ieee80211_hw *hw, - u32 addr, u32 data) -{ - u32 content = 0x1001; /*RF Content: radio_b_txt*/ - u32 maskforphyset = (u32)(content & 0xE000); - - _rtl8821ae_config_rf_reg(hw, addr, data, - RF90_PATH_B, addr | maskforphyset); -} - -static void _rtl8821ae_config_bb_reg(struct ieee80211_hw *hw, - u32 addr, u32 data) -{ - if (addr == 0xfe) - mdelay(50); - else if (addr == 0xfd) - mdelay(5); - else if (addr == 0xfc) - mdelay(1); - else if (addr == 0xfb) - udelay(50); - else if (addr == 0xfa) - udelay(5); - else if (addr == 0xf9) - udelay(1); - else - rtl_set_bbreg(hw, addr, MASKDWORD, data); - - udelay(1); -} - -static void _rtl8821ae_phy_init_tx_power_by_rate(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 band, rfpath, txnum, rate_section; - - for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band) - for (rfpath = 0; rfpath < TX_PWR_BY_RATE_NUM_RF; ++rfpath) - for (txnum = 0; txnum < TX_PWR_BY_RATE_NUM_RF; ++txnum) - for (rate_section = 0; - rate_section < TX_PWR_BY_RATE_NUM_SECTION; - ++rate_section) - rtlphy->tx_power_by_rate_offset[band] - [rfpath][txnum][rate_section] = 0; -} - -static void _rtl8821ae_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw, - u8 band, u8 path, - u8 rate_section, - u8 txnum, u8 value) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - if (path > RF90_PATH_D) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid Rf Path %d in phy_SetTxPowerByRatBase()\n", path); - return; - } - - if (band == BAND_ON_2_4G) { - switch (rate_section) { - case CCK: - rtlphy->txpwr_by_rate_base_24g[path][txnum][0] = value; - break; - case OFDM: - rtlphy->txpwr_by_rate_base_24g[path][txnum][1] = value; - break; - case HT_MCS0_MCS7: - rtlphy->txpwr_by_rate_base_24g[path][txnum][2] = value; - break; - case HT_MCS8_MCS15: - rtlphy->txpwr_by_rate_base_24g[path][txnum][3] = value; - break; - case VHT_1SSMCS0_1SSMCS9: - rtlphy->txpwr_by_rate_base_24g[path][txnum][4] = value; - break; - case VHT_2SSMCS0_2SSMCS9: - rtlphy->txpwr_by_rate_base_24g[path][txnum][5] = value; - break; - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid RateSection %d in Band 2.4G,Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", - rate_section, path, txnum); - break; - } - } else if (band == BAND_ON_5G) { - switch (rate_section) { - case OFDM: - rtlphy->txpwr_by_rate_base_5g[path][txnum][0] = value; - break; - case HT_MCS0_MCS7: - rtlphy->txpwr_by_rate_base_5g[path][txnum][1] = value; - break; - case HT_MCS8_MCS15: - rtlphy->txpwr_by_rate_base_5g[path][txnum][2] = value; - break; - case VHT_1SSMCS0_1SSMCS9: - rtlphy->txpwr_by_rate_base_5g[path][txnum][3] = value; - break; - case VHT_2SSMCS0_2SSMCS9: - rtlphy->txpwr_by_rate_base_5g[path][txnum][4] = value; - break; - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", - rate_section, path, txnum); - break; - } - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid Band %d in PHY_SetTxPowerByRateBase()\n", band); - } -} - -static u8 _rtl8821ae_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw, - u8 band, u8 path, - u8 txnum, u8 rate_section) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 value = 0; - - if (path > RF90_PATH_D) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid Rf Path %d in PHY_GetTxPowerByRateBase()\n", - path); - return 0; - } - - if (band == BAND_ON_2_4G) { - switch (rate_section) { - case CCK: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][0]; - break; - case OFDM: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][1]; - break; - case HT_MCS0_MCS7: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][2]; - break; - case HT_MCS8_MCS15: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][3]; - break; - case VHT_1SSMCS0_1SSMCS9: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][4]; - break; - case VHT_2SSMCS0_2SSMCS9: - value = rtlphy->txpwr_by_rate_base_24g[path][txnum][5]; - break; - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", - rate_section, path, txnum); - break; - } - } else if (band == BAND_ON_5G) { - switch (rate_section) { - case OFDM: - value = rtlphy->txpwr_by_rate_base_5g[path][txnum][0]; - break; - case HT_MCS0_MCS7: - value = rtlphy->txpwr_by_rate_base_5g[path][txnum][1]; - break; - case HT_MCS8_MCS15: - value = rtlphy->txpwr_by_rate_base_5g[path][txnum][2]; - break; - case VHT_1SSMCS0_1SSMCS9: - value = rtlphy->txpwr_by_rate_base_5g[path][txnum][3]; - break; - case VHT_2SSMCS0_2SSMCS9: - value = rtlphy->txpwr_by_rate_base_5g[path][txnum][4]; - break; - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", - rate_section, path, txnum); - break; - } - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Invalid Band %d in PHY_GetTxPowerByRateBase()\n", band); - } - - return value; -} - -static void _rtl8821ae_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u16 rawValue = 0; - u8 base = 0, path = 0; - - for (path = RF90_PATH_A; path <= RF90_PATH_B; ++path) { - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][0] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); - _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, CCK, RF_1TX, base); - - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][2] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); - _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, OFDM, RF_1TX, base); - - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][4] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); - _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, HT_MCS0_MCS7, RF_1TX, base); - - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_2TX][6] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); - _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, HT_MCS8_MCS15, RF_2TX, base); - - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_1TX][8] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); - _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, VHT_1SSMCS0_1SSMCS9, RF_1TX, base); - - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][path][RF_2TX][11] >> 8) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); - _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G, path, VHT_2SSMCS0_2SSMCS9, RF_2TX, base); - - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][2] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); - _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, OFDM, RF_1TX, base); - - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][4] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); - _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, HT_MCS0_MCS7, RF_1TX, base); - - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_2TX][6] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); - _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, HT_MCS8_MCS15, RF_2TX, base); - - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_1TX][8] >> 24) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); - _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, VHT_1SSMCS0_1SSMCS9, RF_1TX, base); - - rawValue = (u16)(rtlphy->tx_power_by_rate_offset[BAND_ON_5G][path][RF_2TX][11] >> 8) & 0xFF; - base = (rawValue >> 4) * 10 + (rawValue & 0xF); - _rtl8821ae_phy_set_txpower_by_rate_base(hw, BAND_ON_5G, path, VHT_2SSMCS0_2SSMCS9, RF_2TX, base); - } -} - -static void _phy_convert_txpower_dbm_to_relative_value(u32 *data, u8 start, - u8 end, u8 base_val) -{ - char i = 0; - u8 temp_value = 0; - u32 temp_data = 0; - - for (i = 3; i >= 0; --i) { - if (i >= start && i <= end) { - /* Get the exact value */ - temp_value = (u8)(*data >> (i * 8)) & 0xF; - temp_value += ((u8)((*data >> (i * 8 + 4)) & 0xF)) * 10; - - /* Change the value to a relative value */ - temp_value = (temp_value > base_val) ? temp_value - - base_val : base_val - temp_value; - } else { - temp_value = (u8)(*data >> (i * 8)) & 0xFF; - } - temp_data <<= 8; - temp_data |= temp_value; - } - *data = temp_data; -} - -static void _rtl8812ae_phy_cross_reference_ht_and_vht_txpower_limit(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 regulation, bw, channel, rate_section; - char temp_pwrlmt = 0; - - for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) { - for (bw = 0; bw < MAX_5G_BANDWITH_NUM; ++bw) { - for (channel = 0; channel < CHANNEL_MAX_NUMBER_5G; ++channel) { - for (rate_section = 0; rate_section < MAX_RATE_SECTION_NUM; ++rate_section) { - temp_pwrlmt = rtlphy->txpwr_limit_5g[regulation] - [bw][rate_section][channel][RF90_PATH_A]; - if (temp_pwrlmt == MAX_POWER_INDEX) { - if (bw == 0 || bw == 1) { /*5G 20M 40M VHT and HT can cross reference*/ - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "No power limit table of the specified band %d, bandwidth %d, ratesection %d, channel %d, rf path %d\n", - 1, bw, rate_section, channel, RF90_PATH_A); - if (rate_section == 2) { - rtlphy->txpwr_limit_5g[regulation][bw][2][channel][RF90_PATH_A] = - rtlphy->txpwr_limit_5g[regulation][bw][4][channel][RF90_PATH_A]; - } else if (rate_section == 4) { - rtlphy->txpwr_limit_5g[regulation][bw][4][channel][RF90_PATH_A] = - rtlphy->txpwr_limit_5g[regulation][bw][2][channel][RF90_PATH_A]; - } else if (rate_section == 3) { - rtlphy->txpwr_limit_5g[regulation][bw][3][channel][RF90_PATH_A] = - rtlphy->txpwr_limit_5g[regulation][bw][5][channel][RF90_PATH_A]; - } else if (rate_section == 5) { - rtlphy->txpwr_limit_5g[regulation][bw][5][channel][RF90_PATH_A] = - rtlphy->txpwr_limit_5g[regulation][bw][3][channel][RF90_PATH_A]; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "use other value %d", temp_pwrlmt); - } - } - } - } - } - } -} - -static u8 _rtl8812ae_phy_get_txpower_by_rate_base_index(struct ieee80211_hw *hw, - enum band_type band, u8 rate) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 index = 0; - if (band == BAND_ON_2_4G) { - switch (rate) { - case MGN_1M: - case MGN_2M: - case MGN_5_5M: - case MGN_11M: - index = 0; - break; - - case MGN_6M: - case MGN_9M: - case MGN_12M: - case MGN_18M: - case MGN_24M: - case MGN_36M: - case MGN_48M: - case MGN_54M: - index = 1; - break; - - case MGN_MCS0: - case MGN_MCS1: - case MGN_MCS2: - case MGN_MCS3: - case MGN_MCS4: - case MGN_MCS5: - case MGN_MCS6: - case MGN_MCS7: - index = 2; - break; - - case MGN_MCS8: - case MGN_MCS9: - case MGN_MCS10: - case MGN_MCS11: - case MGN_MCS12: - case MGN_MCS13: - case MGN_MCS14: - case MGN_MCS15: - index = 3; - break; - - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Wrong rate 0x%x to obtain index in 2.4G in PHY_GetTxPowerByRateBaseIndex()\n", - rate); - break; - } - } else if (band == BAND_ON_5G) { - switch (rate) { - case MGN_6M: - case MGN_9M: - case MGN_12M: - case MGN_18M: - case MGN_24M: - case MGN_36M: - case MGN_48M: - case MGN_54M: - index = 0; - break; - - case MGN_MCS0: - case MGN_MCS1: - case MGN_MCS2: - case MGN_MCS3: - case MGN_MCS4: - case MGN_MCS5: - case MGN_MCS6: - case MGN_MCS7: - index = 1; - break; - - case MGN_MCS8: - case MGN_MCS9: - case MGN_MCS10: - case MGN_MCS11: - case MGN_MCS12: - case MGN_MCS13: - case MGN_MCS14: - case MGN_MCS15: - index = 2; - break; - - case MGN_VHT1SS_MCS0: - case MGN_VHT1SS_MCS1: - case MGN_VHT1SS_MCS2: - case MGN_VHT1SS_MCS3: - case MGN_VHT1SS_MCS4: - case MGN_VHT1SS_MCS5: - case MGN_VHT1SS_MCS6: - case MGN_VHT1SS_MCS7: - case MGN_VHT1SS_MCS8: - case MGN_VHT1SS_MCS9: - index = 3; - break; - - case MGN_VHT2SS_MCS0: - case MGN_VHT2SS_MCS1: - case MGN_VHT2SS_MCS2: - case MGN_VHT2SS_MCS3: - case MGN_VHT2SS_MCS4: - case MGN_VHT2SS_MCS5: - case MGN_VHT2SS_MCS6: - case MGN_VHT2SS_MCS7: - case MGN_VHT2SS_MCS8: - case MGN_VHT2SS_MCS9: - index = 4; - break; - - default: - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Wrong rate 0x%x to obtain index in 5G in PHY_GetTxPowerByRateBaseIndex()\n", - rate); - break; - } - } - - return index; -} - -static void _rtl8812ae_phy_convert_txpower_limit_to_power_index(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 bw40_pwr_base_dbm2_4G, bw40_pwr_base_dbm5G; - u8 regulation, bw, channel, rate_section; - u8 base_index2_4G = 0; - u8 base_index5G = 0; - char temp_value = 0, temp_pwrlmt = 0; - u8 rf_path = 0; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "=====> _rtl8812ae_phy_convert_txpower_limit_to_power_index()\n"); - - _rtl8812ae_phy_cross_reference_ht_and_vht_txpower_limit(hw); - - for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) { - for (bw = 0; bw < MAX_2_4G_BANDWITH_NUM; ++bw) { - for (channel = 0; channel < CHANNEL_MAX_NUMBER_2G; ++channel) { - for (rate_section = 0; rate_section < MAX_RATE_SECTION_NUM; ++rate_section) { - /* obtain the base dBm values in 2.4G band - CCK => 11M, OFDM => 54M, HT 1T => MCS7, HT 2T => MCS15*/ - if (rate_section == 0) { /*CCK*/ - base_index2_4G = - _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, - BAND_ON_2_4G, MGN_11M); - } else if (rate_section == 1) { /*OFDM*/ - base_index2_4G = - _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, - BAND_ON_2_4G, MGN_54M); - } else if (rate_section == 2) { /*HT IT*/ - base_index2_4G = - _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, - BAND_ON_2_4G, MGN_MCS7); - } else if (rate_section == 3) { /*HT 2T*/ - base_index2_4G = - _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, - BAND_ON_2_4G, MGN_MCS15); - } - - temp_pwrlmt = rtlphy->txpwr_limit_2_4g[regulation] - [bw][rate_section][channel][RF90_PATH_A]; - - for (rf_path = RF90_PATH_A; - rf_path < MAX_RF_PATH_NUM; - ++rf_path) { - if (rate_section == 3) - bw40_pwr_base_dbm2_4G = - rtlphy->txpwr_by_rate_base_24g[rf_path][RF_2TX][base_index2_4G]; - else - bw40_pwr_base_dbm2_4G = - rtlphy->txpwr_by_rate_base_24g[rf_path][RF_1TX][base_index2_4G]; - - if (temp_pwrlmt != MAX_POWER_INDEX) { - temp_value = temp_pwrlmt - bw40_pwr_base_dbm2_4G; - rtlphy->txpwr_limit_2_4g[regulation] - [bw][rate_section][channel][rf_path] = - temp_value; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "TxPwrLimit_2_4G[regulation %d][bw %d][rateSection %d][channel %d] = %d\n(TxPwrLimit in dBm %d - BW40PwrLmt2_4G[channel %d][rfPath %d] %d)\n", - regulation, bw, rate_section, channel, - rtlphy->txpwr_limit_2_4g[regulation][bw] - [rate_section][channel][rf_path], (temp_pwrlmt == 63) - ? 0 : temp_pwrlmt/2, channel, rf_path, - bw40_pwr_base_dbm2_4G); - } - } - } - } - } - for (regulation = 0; regulation < MAX_REGULATION_NUM; ++regulation) { - for (bw = 0; bw < MAX_5G_BANDWITH_NUM; ++bw) { - for (channel = 0; channel < CHANNEL_MAX_NUMBER_5G; ++channel) { - for (rate_section = 0; rate_section < MAX_RATE_SECTION_NUM; ++rate_section) { - /* obtain the base dBm values in 5G band - OFDM => 54M, HT 1T => MCS7, HT 2T => MCS15, - VHT => 1SSMCS7, VHT 2T => 2SSMCS7*/ - if (rate_section == 1) { /*OFDM*/ - base_index5G = - _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, - BAND_ON_5G, MGN_54M); - } else if (rate_section == 2) { /*HT 1T*/ - base_index5G = - _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, - BAND_ON_5G, MGN_MCS7); - } else if (rate_section == 3) { /*HT 2T*/ - base_index5G = - _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, - BAND_ON_5G, MGN_MCS15); - } else if (rate_section == 4) { /*VHT 1T*/ - base_index5G = - _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, - BAND_ON_5G, MGN_VHT1SS_MCS7); - } else if (rate_section == 5) { /*VHT 2T*/ - base_index5G = - _rtl8812ae_phy_get_txpower_by_rate_base_index(hw, - BAND_ON_5G, MGN_VHT2SS_MCS7); - } - - temp_pwrlmt = rtlphy->txpwr_limit_5g[regulation] - [bw][rate_section][channel] - [RF90_PATH_A]; - - for (rf_path = RF90_PATH_A; - rf_path < MAX_RF_PATH_NUM; - ++rf_path) { - if (rate_section == 3 || rate_section == 5) - bw40_pwr_base_dbm5G = - rtlphy->txpwr_by_rate_base_5g[rf_path] - [RF_2TX][base_index5G]; - else - bw40_pwr_base_dbm5G = - rtlphy->txpwr_by_rate_base_5g[rf_path] - [RF_1TX][base_index5G]; - - if (temp_pwrlmt != MAX_POWER_INDEX) { - temp_value = - temp_pwrlmt - bw40_pwr_base_dbm5G; - rtlphy->txpwr_limit_5g[regulation] - [bw][rate_section][channel] - [rf_path] = temp_value; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "TxPwrLimit_5G[regulation %d][bw %d][rateSection %d][channel %d] =%d\n(TxPwrLimit in dBm %d - BW40PwrLmt5G[chnl group %d][rfPath %d] %d)\n", - regulation, bw, rate_section, - channel, rtlphy->txpwr_limit_5g[regulation] - [bw][rate_section][channel][rf_path], - temp_pwrlmt, channel, rf_path, bw40_pwr_base_dbm5G); - } - } - } - } - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "<===== _rtl8812ae_phy_convert_txpower_limit_to_power_index()\n"); -} - -static void _rtl8821ae_phy_init_txpower_limit(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 i, j, k, l, m; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "=====> _rtl8821ae_phy_init_txpower_limit()!\n"); - - for (i = 0; i < MAX_REGULATION_NUM; ++i) { - for (j = 0; j < MAX_2_4G_BANDWITH_NUM; ++j) - for (k = 0; k < MAX_RATE_SECTION_NUM; ++k) - for (m = 0; m < CHANNEL_MAX_NUMBER_2G; ++m) - for (l = 0; l < MAX_RF_PATH_NUM; ++l) - rtlphy->txpwr_limit_2_4g - [i][j][k][m][l] - = MAX_POWER_INDEX; - } - for (i = 0; i < MAX_REGULATION_NUM; ++i) { - for (j = 0; j < MAX_5G_BANDWITH_NUM; ++j) - for (k = 0; k < MAX_RATE_SECTION_NUM; ++k) - for (m = 0; m < CHANNEL_MAX_NUMBER_5G; ++m) - for (l = 0; l < MAX_RF_PATH_NUM; ++l) - rtlphy->txpwr_limit_5g - [i][j][k][m][l] - = MAX_POWER_INDEX; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "<===== _rtl8821ae_phy_init_txpower_limit()!\n"); -} - -static void _rtl8821ae_phy_convert_txpower_dbm_to_relative_value(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 base = 0, rfPath = 0; - - for (rfPath = RF90_PATH_A; rfPath <= RF90_PATH_B; ++rfPath) { - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, CCK); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][0], - 0, 3, base); - - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, OFDM); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][1], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][2], - 0, 3, base); - - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, HT_MCS0_MCS7); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][3], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][4], - 0, 3, base); - - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_2TX, HT_MCS8_MCS15); - - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][5], - 0, 3, base); - - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][6], - 0, 3, base); - - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_1TX, VHT_1SSMCS0_1SSMCS9); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][7], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][8], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][9], - 0, 1, base); - - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfPath, RF_2TX, VHT_2SSMCS0_2SSMCS9); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_1TX][9], - 2, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][10], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfPath][RF_2TX][11], - 0, 3, base); - - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_1TX, OFDM); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][1], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][2], - 0, 3, base); - - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_1TX, HT_MCS0_MCS7); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][3], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][4], - 0, 3, base); - - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_2TX, HT_MCS8_MCS15); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][5], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][6], - 0, 3, base); - - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_1TX, VHT_1SSMCS0_1SSMCS9); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][7], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][8], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][9], - 0, 1, base); - - base = _rtl8821ae_phy_get_txpower_by_rate_base(hw, BAND_ON_5G, rfPath, RF_2TX, VHT_2SSMCS0_2SSMCS9); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_1TX][9], - 2, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][10], - 0, 3, base); - _phy_convert_txpower_dbm_to_relative_value( - &rtlphy->tx_power_by_rate_offset[BAND_ON_5G][rfPath][RF_2TX][11], - 0, 3, base); - } - - RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, - "<===_rtl8821ae_phy_convert_txpower_dbm_to_relative_value()\n"); -} - -static void _rtl8821ae_phy_txpower_by_rate_configuration(struct ieee80211_hw *hw) -{ - _rtl8821ae_phy_store_txpower_by_rate_base(hw); - _rtl8821ae_phy_convert_txpower_dbm_to_relative_value(hw); -} - -/* string is in decimal */ -static bool _rtl8812ae_get_integer_from_string(char *str, u8 *pint) -{ - u16 i = 0; - *pint = 0; - - while (str[i] != '\0') { - if (str[i] >= '0' && str[i] <= '9') { - *pint *= 10; - *pint += (str[i] - '0'); - } else { - return false; - } - ++i; - } - - return true; -} - -static bool _rtl8812ae_eq_n_byte(u8 *str1, u8 *str2, u32 num) -{ - if (num == 0) - return false; - while (num > 0) { - num--; - if (str1[num] != str2[num]) - return false; - } - return true; -} - -static char _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(struct ieee80211_hw *hw, - u8 band, u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - char channel_index = -1; - u8 channel_5g[CHANNEL_MAX_NUMBER_5G] = { - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, - 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, - 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 149, - 151, 153, 155, 157, 159, 161, 163, 165, 167, 168, 169, 171, - 173, 175, 177}; - u8 i = 0; - if (band == BAND_ON_2_4G) - channel_index = channel - 1; - else if (band == BAND_ON_5G) { - for (i = 0; i < sizeof(channel_5g)/sizeof(u8); ++i) { - if (channel_5g[i] == channel) - channel_index = i; - } - } else - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Invalid Band %d in %s", - band, __func__); - - if (channel_index == -1) - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Invalid Channel %d of Band %d in %s", channel, - band, __func__); - - return channel_index; -} - -static void _rtl8812ae_phy_set_txpower_limit(struct ieee80211_hw *hw, u8 *pregulation, - u8 *pband, u8 *pbandwidth, - u8 *prate_section, u8 *prf_path, - u8 *pchannel, u8 *ppower_limit) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 regulation = 0, bandwidth = 0, rate_section = 0, channel; - u8 channel_index; - char power_limit = 0, prev_power_limit, ret; - - if (!_rtl8812ae_get_integer_from_string((char *)pchannel, &channel) || - !_rtl8812ae_get_integer_from_string((char *)ppower_limit, - &power_limit)) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Illegal index of pwr_lmt table [chnl %d][val %d]\n", - channel, power_limit); - } - - power_limit = power_limit > MAX_POWER_INDEX ? - MAX_POWER_INDEX : power_limit; - - if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("FCC"), 3)) - regulation = 0; - else if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("MKK"), 3)) - regulation = 1; - else if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("ETSI"), 4)) - regulation = 2; - else if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("WW13"), 4)) - regulation = 3; - - if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("CCK"), 3)) - rate_section = 0; - else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("OFDM"), 4)) - rate_section = 1; - else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("HT"), 2) && - _rtl8812ae_eq_n_byte(prf_path, (u8 *)("1T"), 2)) - rate_section = 2; - else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("HT"), 2) && - _rtl8812ae_eq_n_byte(prf_path, (u8 *)("2T"), 2)) - rate_section = 3; - else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("VHT"), 3) && - _rtl8812ae_eq_n_byte(prf_path, (u8 *)("1T"), 2)) - rate_section = 4; - else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("VHT"), 3) && - _rtl8812ae_eq_n_byte(prf_path, (u8 *)("2T"), 2)) - rate_section = 5; - - if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("20M"), 3)) - bandwidth = 0; - else if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("40M"), 3)) - bandwidth = 1; - else if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("80M"), 3)) - bandwidth = 2; - else if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("160M"), 4)) - bandwidth = 3; - - if (_rtl8812ae_eq_n_byte(pband, (u8 *)("2.4G"), 4)) { - ret = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw, - BAND_ON_2_4G, - channel); - - if (ret == -1) - return; - - channel_index = ret; - - prev_power_limit = rtlphy->txpwr_limit_2_4g[regulation] - [bandwidth][rate_section] - [channel_index][RF90_PATH_A]; - - if (power_limit < prev_power_limit) - rtlphy->txpwr_limit_2_4g[regulation][bandwidth] - [rate_section][channel_index][RF90_PATH_A] = - power_limit; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "2.4G [regula %d][bw %d][sec %d][chnl %d][val %d]\n", - regulation, bandwidth, rate_section, channel_index, - rtlphy->txpwr_limit_2_4g[regulation][bandwidth] - [rate_section][channel_index][RF90_PATH_A]); - } else if (_rtl8812ae_eq_n_byte(pband, (u8 *)("5G"), 2)) { - ret = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw, - BAND_ON_5G, - channel); - - if (ret == -1) - return; - - channel_index = ret; - - prev_power_limit = rtlphy->txpwr_limit_5g[regulation][bandwidth] - [rate_section][channel_index] - [RF90_PATH_A]; - - if (power_limit < prev_power_limit) - rtlphy->txpwr_limit_5g[regulation][bandwidth] - [rate_section][channel_index][RF90_PATH_A] = power_limit; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "5G: [regul %d][bw %d][sec %d][chnl %d][val %d]\n", - regulation, bandwidth, rate_section, channel, - rtlphy->txpwr_limit_5g[regulation][bandwidth] - [rate_section][channel_index][RF90_PATH_A]); - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Cannot recognize the band info in %s\n", pband); - return; - } -} - -static void _rtl8812ae_phy_config_bb_txpwr_lmt(struct ieee80211_hw *hw, - u8 *regulation, u8 *band, - u8 *bandwidth, u8 *rate_section, - u8 *rf_path, u8 *channel, - u8 *power_limit) -{ - _rtl8812ae_phy_set_txpower_limit(hw, regulation, band, bandwidth, - rate_section, rf_path, channel, - power_limit); -} - -static void _rtl8821ae_phy_read_and_config_txpwr_lmt(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u32 i = 0; - u32 array_len; - u8 **array; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - array_len = RTL8812AE_TXPWR_LMT_ARRAY_LEN; - array = RTL8812AE_TXPWR_LMT; - } else { - array_len = RTL8821AE_TXPWR_LMT_ARRAY_LEN; - array = RTL8821AE_TXPWR_LMT; - } - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "\n"); - - for (i = 0; i < array_len; i += 7) { - u8 *regulation = array[i]; - u8 *band = array[i+1]; - u8 *bandwidth = array[i+2]; - u8 *rate = array[i+3]; - u8 *rf_path = array[i+4]; - u8 *chnl = array[i+5]; - u8 *val = array[i+6]; - - _rtl8812ae_phy_config_bb_txpwr_lmt(hw, regulation, band, - bandwidth, rate, rf_path, - chnl, val); - } -} - -static bool _rtl8821ae_phy_bb8821a_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - bool rtstatus; - - _rtl8821ae_phy_init_txpower_limit(hw); - - /* RegEnableTxPowerLimit == 1 for 8812a & 8821a */ - if (rtlefuse->eeprom_regulatory != 2) - _rtl8821ae_phy_read_and_config_txpwr_lmt(hw); - - rtstatus = _rtl8821ae_phy_config_bb_with_headerfile(hw, - BASEBAND_CONFIG_PHY_REG); - if (rtstatus != true) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); - return false; - } - _rtl8821ae_phy_init_tx_power_by_rate(hw); - if (rtlefuse->autoload_failflag == false) { - rtstatus = _rtl8821ae_phy_config_bb_with_pgheaderfile(hw, - BASEBAND_CONFIG_PHY_REG); - } - if (rtstatus != true) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); - return false; - } - - _rtl8821ae_phy_txpower_by_rate_configuration(hw); - - /* RegEnableTxPowerLimit == 1 for 8812a & 8821a */ - if (rtlefuse->eeprom_regulatory != 2) - _rtl8812ae_phy_convert_txpower_limit_to_power_index(hw); - - rtstatus = _rtl8821ae_phy_config_bb_with_headerfile(hw, - BASEBAND_CONFIG_AGC_TAB); - - if (rtstatus != true) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); - return false; - } - rtlphy->cck_high_power = (bool)(rtl_get_bbreg(hw, - RFPGA0_XA_HSSIPARAMETER2, 0x200)); - return true; -} - -static bool _rtl8821ae_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u32 i, v1, v2; - u32 arraylength; - u32 *ptrarray; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read MAC_REG_Array\n"); - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - arraylength = RTL8821AEMAC_1T_ARRAYLEN; - ptrarray = RTL8821AE_MAC_REG_ARRAY; - } else { - arraylength = RTL8812AEMAC_1T_ARRAYLEN; - ptrarray = RTL8812AE_MAC_REG_ARRAY; - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Img: MAC_REG_ARRAY LEN %d\n", arraylength); - for (i = 0; i < arraylength; i += 2) { - v1 = ptrarray[i]; - v2 = (u8)ptrarray[i + 1]; - if (v1 < 0xCDCDCDCD) { - rtl_write_byte(rtlpriv, v1, (u8)v2); - continue; - } else { - if (!_rtl8821ae_check_condition(hw, v1)) { - /*Discard the following (offset, data) pairs*/ - READ_NEXT_PAIR(ptrarray, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < arraylength - 2) { - READ_NEXT_PAIR(ptrarray, v1, v2, i); - } - i -= 2; /* prevent from for-loop += 2*/ - } else {/*Configure matched pairs and skip to end of if-else.*/ - READ_NEXT_PAIR(ptrarray, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < arraylength - 2) { - rtl_write_byte(rtlpriv, v1, v2); - READ_NEXT_PAIR(ptrarray, v1, v2, i); - } - - while (v2 != 0xDEAD && i < arraylength - 2) - READ_NEXT_PAIR(ptrarray, v1, v2, i); - } - } - } - return true; -} - -static bool _rtl8821ae_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, - u8 configtype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - int i; - u32 *array_table; - u16 arraylen; - u32 v1 = 0, v2 = 0; - - if (configtype == BASEBAND_CONFIG_PHY_REG) { - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - arraylen = RTL8812AEPHY_REG_1TARRAYLEN; - array_table = RTL8812AE_PHY_REG_ARRAY; - } else { - arraylen = RTL8821AEPHY_REG_1TARRAYLEN; - array_table = RTL8821AE_PHY_REG_ARRAY; - } - - for (i = 0; i < arraylen; i += 2) { - v1 = array_table[i]; - v2 = array_table[i + 1]; - if (v1 < 0xCDCDCDCD) { - _rtl8821ae_config_bb_reg(hw, v1, v2); - continue; - } else {/*This line is the start line of branch.*/ - if (!_rtl8821ae_check_condition(hw, v1)) { - /*Discard the following (offset, data) pairs*/ - READ_NEXT_PAIR(array_table, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < arraylen - 2) { - READ_NEXT_PAIR(array_table, v1, - v2, i); - } - - i -= 2; /* prevent from for-loop += 2*/ - } else {/*Configure matched pairs and skip to end of if-else.*/ - READ_NEXT_PAIR(array_table, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < arraylen - 2) { - _rtl8821ae_config_bb_reg(hw, v1, - v2); - READ_NEXT_PAIR(array_table, v1, - v2, i); - } - - while (v2 != 0xDEAD && - i < arraylen - 2) { - READ_NEXT_PAIR(array_table, v1, - v2, i); - } - } - } - } - } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - arraylen = RTL8812AEAGCTAB_1TARRAYLEN; - array_table = RTL8812AE_AGC_TAB_ARRAY; - } else { - arraylen = RTL8821AEAGCTAB_1TARRAYLEN; - array_table = RTL8821AE_AGC_TAB_ARRAY; - } - - for (i = 0; i < arraylen; i = i + 2) { - v1 = array_table[i]; - v2 = array_table[i+1]; - if (v1 < 0xCDCDCDCD) { - rtl_set_bbreg(hw, v1, MASKDWORD, v2); - udelay(1); - continue; - } else {/*This line is the start line of branch.*/ - if (!_rtl8821ae_check_condition(hw, v1)) { - /*Discard the following (offset, data) pairs*/ - READ_NEXT_PAIR(array_table, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < arraylen - 2) { - READ_NEXT_PAIR(array_table, v1, - v2, i); - } - i -= 2; /* prevent from for-loop += 2*/ - } else {/*Configure matched pairs and skip to end of if-else.*/ - READ_NEXT_PAIR(array_table, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && - i < arraylen - 2) { - rtl_set_bbreg(hw, v1, MASKDWORD, - v2); - udelay(1); - READ_NEXT_PAIR(array_table, v1, - v2, i); - } - - while (v2 != 0xDEAD && - i < arraylen - 2) { - READ_NEXT_PAIR(array_table, v1, - v2, i); - } - } - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "The agctab_array_table[0] is %x Rtl818EEPHY_REGArray[1] is %x\n", - array_table[i], array_table[i + 1]); - } - } - } - return true; -} - -static u8 _rtl8821ae_get_rate_section_index(u32 regaddr) -{ - u8 index = 0; - regaddr &= 0xFFF; - if (regaddr >= 0xC20 && regaddr <= 0xC4C) - index = (u8)((regaddr - 0xC20) / 4); - else if (regaddr >= 0xE20 && regaddr <= 0xE4C) - index = (u8)((regaddr - 0xE20) / 4); - else - RT_ASSERT(!COMP_INIT, - "Invalid RegAddr 0x%x\n", regaddr); - return index; -} - -static void _rtl8821ae_store_tx_power_by_rate(struct ieee80211_hw *hw, - u32 band, u32 rfpath, - u32 txnum, u32 regaddr, - u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 rate_section = _rtl8821ae_get_rate_section_index(regaddr); - - if (band != BAND_ON_2_4G && band != BAND_ON_5G) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid Band %d\n", band); - band = BAND_ON_2_4G; - } - if (rfpath >= MAX_RF_PATH) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid RfPath %d\n", rfpath); - rfpath = MAX_RF_PATH - 1; - } - if (txnum >= MAX_RF_PATH) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid TxNum %d\n", txnum); - txnum = MAX_RF_PATH - 1; - } - rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "TxPwrByRateOffset[Band %d][RfPath %d][TxNum %d][RateSection %d] = 0x%x\n", - band, rfpath, txnum, rate_section, - rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section]); -} - -static bool _rtl8821ae_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, - u8 configtype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - int i; - u32 *array; - u16 arraylen; - u32 v1, v2, v3, v4, v5, v6; - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - arraylen = RTL8812AEPHY_REG_ARRAY_PGLEN; - array = RTL8812AE_PHY_REG_ARRAY_PG; - } else { - arraylen = RTL8821AEPHY_REG_ARRAY_PGLEN; - array = RTL8821AE_PHY_REG_ARRAY_PG; - } - - if (configtype != BASEBAND_CONFIG_PHY_REG) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "configtype != BaseBand_Config_PHY_REG\n"); - return true; - } - for (i = 0; i < arraylen; i += 6) { - v1 = array[i]; - v2 = array[i+1]; - v3 = array[i+2]; - v4 = array[i+3]; - v5 = array[i+4]; - v6 = array[i+5]; - - if (v1 < 0xCDCDCDCD) { - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE && - (v4 == 0xfe || v4 == 0xffe)) { - msleep(50); - continue; - } - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - if (v4 == 0xfe) - msleep(50); - else if (v4 == 0xfd) - mdelay(5); - else if (v4 == 0xfc) - mdelay(1); - else if (v4 == 0xfb) - udelay(50); - else if (v4 == 0xfa) - udelay(5); - else if (v4 == 0xf9) - udelay(1); - } - _rtl8821ae_store_tx_power_by_rate(hw, v1, v2, v3, - v4, v5, v6); - continue; - } else { - /*don't need the hw_body*/ - if (!_rtl8821ae_check_condition(hw, v1)) { - i += 2; /* skip the pair of expression*/ - v1 = array[i]; - v2 = array[i+1]; - v3 = array[i+2]; - while (v2 != 0xDEAD) { - i += 3; - v1 = array[i]; - v2 = array[i+1]; - v3 = array[i+2]; - } - } - } - } - - return true; -} - -bool rtl8812ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath) -{ - int i; - bool rtstatus = true; - u32 *radioa_array_table_a, *radioa_array_table_b; - u16 radioa_arraylen_a, radioa_arraylen_b; - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 v1 = 0, v2 = 0; - - radioa_arraylen_a = RTL8812AE_RADIOA_1TARRAYLEN; - radioa_array_table_a = RTL8812AE_RADIOA_ARRAY; - radioa_arraylen_b = RTL8812AE_RADIOB_1TARRAYLEN; - radioa_array_table_b = RTL8812AE_RADIOB_ARRAY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Radio_A:RTL8821AE_RADIOA_ARRAY %d\n", radioa_arraylen_a); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); - rtstatus = true; - switch (rfpath) { - case RF90_PATH_A: - for (i = 0; i < radioa_arraylen_a; i = i + 2) { - v1 = radioa_array_table_a[i]; - v2 = radioa_array_table_a[i+1]; - if (v1 < 0xcdcdcdcd) { - _rtl8821ae_config_rf_radio_a(hw, v1, v2); - continue; - } else{/*This line is the start line of branch.*/ - if (!_rtl8821ae_check_condition(hw, v1)) { - /*Discard the following (offset, data) pairs*/ - READ_NEXT_PAIR(radioa_array_table_a, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < radioa_arraylen_a-2) - READ_NEXT_PAIR(radioa_array_table_a, v1, v2, i); - - i -= 2; /* prevent from for-loop += 2*/ - } else {/*Configure matched pairs and skip to end of if-else.*/ - READ_NEXT_PAIR(radioa_array_table_a, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < radioa_arraylen_a - 2) { - _rtl8821ae_config_rf_radio_a(hw, v1, v2); - READ_NEXT_PAIR(radioa_array_table_a, v1, v2, i); - } - - while (v2 != 0xDEAD && i < radioa_arraylen_a-2) - READ_NEXT_PAIR(radioa_array_table_a, v1, v2, i); - - } - } - } - break; - case RF90_PATH_B: - for (i = 0; i < radioa_arraylen_b; i = i + 2) { - v1 = radioa_array_table_b[i]; - v2 = radioa_array_table_b[i+1]; - if (v1 < 0xcdcdcdcd) { - _rtl8821ae_config_rf_radio_b(hw, v1, v2); - continue; - } else{/*This line is the start line of branch.*/ - if (!_rtl8821ae_check_condition(hw, v1)) { - /*Discard the following (offset, data) pairs*/ - READ_NEXT_PAIR(radioa_array_table_b, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < radioa_arraylen_b-2) - READ_NEXT_PAIR(radioa_array_table_b, v1, v2, i); - - i -= 2; /* prevent from for-loop += 2*/ - } else {/*Configure matched pairs and skip to end of if-else.*/ - READ_NEXT_PAIR(radioa_array_table_b, v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < radioa_arraylen_b-2) { - _rtl8821ae_config_rf_radio_b(hw, v1, v2); - READ_NEXT_PAIR(radioa_array_table_b, v1, v2, i); - } - - while (v2 != 0xDEAD && i < radioa_arraylen_b-2) - READ_NEXT_PAIR(radioa_array_table_b, v1, v2, i); - } - } - } - break; - case RF90_PATH_C: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - case RF90_PATH_D: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - return true; -} - -bool rtl8821ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath) -{ - #define READ_NEXT_RF_PAIR(v1, v2, i) \ - do { \ - i += 2; \ - v1 = radioa_array_table[i]; \ - v2 = radioa_array_table[i+1]; \ - } \ - while (0) - - int i; - bool rtstatus = true; - u32 *radioa_array_table; - u16 radioa_arraylen; - struct rtl_priv *rtlpriv = rtl_priv(hw); - /* struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); */ - u32 v1 = 0, v2 = 0; - - radioa_arraylen = RTL8821AE_RADIOA_1TARRAYLEN; - radioa_array_table = RTL8821AE_RADIOA_ARRAY; - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "Radio_A:RTL8821AE_RADIOA_ARRAY %d\n", radioa_arraylen); - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); - rtstatus = true; - switch (rfpath) { - case RF90_PATH_A: - for (i = 0; i < radioa_arraylen; i = i + 2) { - v1 = radioa_array_table[i]; - v2 = radioa_array_table[i+1]; - if (v1 < 0xcdcdcdcd) - _rtl8821ae_config_rf_radio_a(hw, v1, v2); - else{/*This line is the start line of branch.*/ - if (!_rtl8821ae_check_condition(hw, v1)) { - /*Discard the following (offset, data) pairs*/ - READ_NEXT_RF_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < radioa_arraylen - 2) - READ_NEXT_RF_PAIR(v1, v2, i); - - i -= 2; /* prevent from for-loop += 2*/ - } else {/*Configure matched pairs and skip to end of if-else.*/ - READ_NEXT_RF_PAIR(v1, v2, i); - while (v2 != 0xDEAD && - v2 != 0xCDEF && - v2 != 0xCDCD && i < radioa_arraylen - 2) { - _rtl8821ae_config_rf_radio_a(hw, v1, v2); - READ_NEXT_RF_PAIR(v1, v2, i); - } - - while (v2 != 0xDEAD && i < radioa_arraylen - 2) - READ_NEXT_RF_PAIR(v1, v2, i); - } - } - } - break; - - case RF90_PATH_B: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - case RF90_PATH_C: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - case RF90_PATH_D: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - return true; -} - -void rtl8821ae_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - rtlphy->default_initialgain[0] = - (u8)rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[1] = - (u8)rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[2] = - (u8)rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); - rtlphy->default_initialgain[3] = - (u8)rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", - rtlphy->default_initialgain[0], - rtlphy->default_initialgain[1], - rtlphy->default_initialgain[2], - rtlphy->default_initialgain[3]); - - rtlphy->framesync = (u8)rtl_get_bbreg(hw, - ROFDM0_RXDETECTOR3, MASKBYTE0); - rtlphy->framesync_c34 = rtl_get_bbreg(hw, - ROFDM0_RXDETECTOR2, MASKDWORD); - - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Default framesync (0x%x) = 0x%x\n", - ROFDM0_RXDETECTOR3, rtlphy->framesync); -} - -static void phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; - rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; - - rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; - rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; - - rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = RA_LSSIWRITE_8821A; - rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = RB_LSSIWRITE_8821A; - - rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RHSSIREAD_8821AE; - rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RHSSIREAD_8821AE; - - rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RA_SIREAD_8821A; - rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RB_SIREAD_8821A; - - rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = RA_PIREAD_8821A; - rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = RB_PIREAD_8821A; -} - -void rtl8821ae_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 txpwr_level; - long txpwr_dbm; - - txpwr_level = rtlphy->cur_cck_txpwridx; - txpwr_dbm = _rtl8821ae_phy_txpwr_idx_to_dbm(hw, - WIRELESS_MODE_B, txpwr_level); - txpwr_level = rtlphy->cur_ofdm24g_txpwridx; - if (_rtl8821ae_phy_txpwr_idx_to_dbm(hw, - WIRELESS_MODE_G, - txpwr_level) > txpwr_dbm) - txpwr_dbm = - _rtl8821ae_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, - txpwr_level); - txpwr_level = rtlphy->cur_ofdm24g_txpwridx; - if (_rtl8821ae_phy_txpwr_idx_to_dbm(hw, - WIRELESS_MODE_N_24G, - txpwr_level) > txpwr_dbm) - txpwr_dbm = - _rtl8821ae_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, - txpwr_level); - *powerlevel = txpwr_dbm; -} - -static bool _rtl8821ae_phy_get_chnl_index(u8 channel, u8 *chnl_index) -{ - u8 channel_5g[CHANNEL_MAX_NUMBER_5G] = { - 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, - 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, - 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, - 142, 144, 149, 151, 153, 155, 157, 159, 161, 163, 165, - 167, 168, 169, 171, 173, 175, 177 - }; - u8 i = 0; - bool in_24g = true; - - if (channel <= 14) { - in_24g = true; - *chnl_index = channel - 1; - } else { - in_24g = false; - - for (i = 0; i < CHANNEL_MAX_NUMBER_5G; ++i) { - if (channel_5g[i] == channel) { - *chnl_index = i; - return in_24g; - } - } - } - return in_24g; -} - -static char _rtl8821ae_phy_get_ratesection_intxpower_byrate(u8 path, u8 rate) -{ - char rate_section = 0; - switch (rate) { - case DESC_RATE1M: - case DESC_RATE2M: - case DESC_RATE5_5M: - case DESC_RATE11M: - rate_section = 0; - break; - case DESC_RATE6M: - case DESC_RATE9M: - case DESC_RATE12M: - case DESC_RATE18M: - rate_section = 1; - break; - case DESC_RATE24M: - case DESC_RATE36M: - case DESC_RATE48M: - case DESC_RATE54M: - rate_section = 2; - break; - case DESC_RATEMCS0: - case DESC_RATEMCS1: - case DESC_RATEMCS2: - case DESC_RATEMCS3: - rate_section = 3; - break; - case DESC_RATEMCS4: - case DESC_RATEMCS5: - case DESC_RATEMCS6: - case DESC_RATEMCS7: - rate_section = 4; - break; - case DESC_RATEMCS8: - case DESC_RATEMCS9: - case DESC_RATEMCS10: - case DESC_RATEMCS11: - rate_section = 5; - break; - case DESC_RATEMCS12: - case DESC_RATEMCS13: - case DESC_RATEMCS14: - case DESC_RATEMCS15: - rate_section = 6; - break; - case DESC_RATEVHT1SS_MCS0: - case DESC_RATEVHT1SS_MCS1: - case DESC_RATEVHT1SS_MCS2: - case DESC_RATEVHT1SS_MCS3: - rate_section = 7; - break; - case DESC_RATEVHT1SS_MCS4: - case DESC_RATEVHT1SS_MCS5: - case DESC_RATEVHT1SS_MCS6: - case DESC_RATEVHT1SS_MCS7: - rate_section = 8; - break; - case DESC_RATEVHT1SS_MCS8: - case DESC_RATEVHT1SS_MCS9: - case DESC_RATEVHT2SS_MCS0: - case DESC_RATEVHT2SS_MCS1: - rate_section = 9; - break; - case DESC_RATEVHT2SS_MCS2: - case DESC_RATEVHT2SS_MCS3: - case DESC_RATEVHT2SS_MCS4: - case DESC_RATEVHT2SS_MCS5: - rate_section = 10; - break; - case DESC_RATEVHT2SS_MCS6: - case DESC_RATEVHT2SS_MCS7: - case DESC_RATEVHT2SS_MCS8: - case DESC_RATEVHT2SS_MCS9: - rate_section = 11; - break; - default: - RT_ASSERT(true, "Rate_Section is Illegal\n"); - break; - } - - return rate_section; -} - -static char _rtl8812ae_phy_get_world_wide_limit(char *limit_table) -{ - char min = limit_table[0]; - u8 i = 0; - - for (i = 0; i < MAX_REGULATION_NUM; ++i) { - if (limit_table[i] < min) - min = limit_table[i]; - } - return min; -} - -static char _rtl8812ae_phy_get_txpower_limit(struct ieee80211_hw *hw, - u8 band, - enum ht_channel_width bandwidth, - enum radio_path rf_path, - u8 rate, u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); - struct rtl_phy *rtlphy = &rtlpriv->phy; - short band_temp = -1, regulation = -1, bandwidth_temp = -1, - rate_section = -1, channel_temp = -1; - u16 bd, regu, bdwidth, sec, chnl; - char power_limit = MAX_POWER_INDEX; - - if (rtlefuse->eeprom_regulatory == 2) - return MAX_POWER_INDEX; - - regulation = TXPWR_LMT_WW; - - if (band == BAND_ON_2_4G) - band_temp = 0; - else if (band == BAND_ON_5G) - band_temp = 1; - - if (bandwidth == HT_CHANNEL_WIDTH_20) - bandwidth_temp = 0; - else if (bandwidth == HT_CHANNEL_WIDTH_20_40) - bandwidth_temp = 1; - else if (bandwidth == HT_CHANNEL_WIDTH_80) - bandwidth_temp = 2; - - switch (rate) { - case DESC_RATE1M: - case DESC_RATE2M: - case DESC_RATE5_5M: - case DESC_RATE11M: - rate_section = 0; - break; - case DESC_RATE6M: - case DESC_RATE9M: - case DESC_RATE12M: - case DESC_RATE18M: - case DESC_RATE24M: - case DESC_RATE36M: - case DESC_RATE48M: - case DESC_RATE54M: - rate_section = 1; - break; - case DESC_RATEMCS0: - case DESC_RATEMCS1: - case DESC_RATEMCS2: - case DESC_RATEMCS3: - case DESC_RATEMCS4: - case DESC_RATEMCS5: - case DESC_RATEMCS6: - case DESC_RATEMCS7: - rate_section = 2; - break; - case DESC_RATEMCS8: - case DESC_RATEMCS9: - case DESC_RATEMCS10: - case DESC_RATEMCS11: - case DESC_RATEMCS12: - case DESC_RATEMCS13: - case DESC_RATEMCS14: - case DESC_RATEMCS15: - rate_section = 3; - break; - case DESC_RATEVHT1SS_MCS0: - case DESC_RATEVHT1SS_MCS1: - case DESC_RATEVHT1SS_MCS2: - case DESC_RATEVHT1SS_MCS3: - case DESC_RATEVHT1SS_MCS4: - case DESC_RATEVHT1SS_MCS5: - case DESC_RATEVHT1SS_MCS6: - case DESC_RATEVHT1SS_MCS7: - case DESC_RATEVHT1SS_MCS8: - case DESC_RATEVHT1SS_MCS9: - rate_section = 4; - break; - case DESC_RATEVHT2SS_MCS0: - case DESC_RATEVHT2SS_MCS1: - case DESC_RATEVHT2SS_MCS2: - case DESC_RATEVHT2SS_MCS3: - case DESC_RATEVHT2SS_MCS4: - case DESC_RATEVHT2SS_MCS5: - case DESC_RATEVHT2SS_MCS6: - case DESC_RATEVHT2SS_MCS7: - case DESC_RATEVHT2SS_MCS8: - case DESC_RATEVHT2SS_MCS9: - rate_section = 5; - break; - default: - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Wrong rate 0x%x\n", rate); - break; - } - - if (band_temp == BAND_ON_5G && rate_section == 0) - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Wrong rate 0x%x: No CCK in 5G Band\n", rate); - - /*workaround for wrong index combination to obtain tx power limit, - OFDM only exists in BW 20M*/ - if (rate_section == 1) - bandwidth_temp = 0; - - /*workaround for wrong index combination to obtain tx power limit, - *HT on 80M will reference to HT on 40M - */ - if ((rate_section == 2 || rate_section == 3) && band == BAND_ON_5G && - bandwidth_temp == 2) - bandwidth_temp = 1; - - if (band == BAND_ON_2_4G) - channel_temp = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw, - BAND_ON_2_4G, channel); - else if (band == BAND_ON_5G) - channel_temp = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw, - BAND_ON_5G, channel); - else if (band == BAND_ON_BOTH) - ;/* BAND_ON_BOTH don't care temporarily */ - - if (band_temp == -1 || regulation == -1 || bandwidth_temp == -1 || - rate_section == -1 || channel_temp == -1) { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Wrong index value to access power limit table [band %d][regulation %d][bandwidth %d][rf_path %d][rate_section %d][chnl %d]\n", - band_temp, regulation, bandwidth_temp, rf_path, - rate_section, channel_temp); - return MAX_POWER_INDEX; - } - - bd = band_temp; - regu = regulation; - bdwidth = bandwidth_temp; - sec = rate_section; - chnl = channel_temp; - - if (band == BAND_ON_2_4G) { - char limits[10] = {0}; - u8 i; - - for (i = 0; i < 4; ++i) - limits[i] = rtlphy->txpwr_limit_2_4g[i][bdwidth] - [sec][chnl][rf_path]; - - power_limit = (regulation == TXPWR_LMT_WW) ? - _rtl8812ae_phy_get_world_wide_limit(limits) : - rtlphy->txpwr_limit_2_4g[regu][bdwidth] - [sec][chnl][rf_path]; - } else if (band == BAND_ON_5G) { - char limits[10] = {0}; - u8 i; - - for (i = 0; i < MAX_REGULATION_NUM; ++i) - limits[i] = rtlphy->txpwr_limit_5g[i][bdwidth] - [sec][chnl][rf_path]; - - power_limit = (regulation == TXPWR_LMT_WW) ? - _rtl8812ae_phy_get_world_wide_limit(limits) : - rtlphy->txpwr_limit_5g[regu][chnl] - [sec][chnl][rf_path]; - } else { - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, - "No power limit table of the specified band\n"); - } - return power_limit; -} - -static char _rtl8821ae_phy_get_txpower_by_rate(struct ieee80211_hw *hw, - u8 band, u8 path, u8 rate) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 shift = 0, rate_section, tx_num; - char tx_pwr_diff = 0; - char limit = 0; - - rate_section = _rtl8821ae_phy_get_ratesection_intxpower_byrate(path, rate); - tx_num = RF_TX_NUM_NONIMPLEMENT; - - if (tx_num == RF_TX_NUM_NONIMPLEMENT) { - if ((rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) || - (rate >= DESC_RATEVHT2SS_MCS2 && rate <= DESC_RATEVHT2SS_MCS9)) - tx_num = RF_2TX; - else - tx_num = RF_1TX; - } - - switch (rate) { - case DESC_RATE1M: - case DESC_RATE6M: - case DESC_RATE24M: - case DESC_RATEMCS0: - case DESC_RATEMCS4: - case DESC_RATEMCS8: - case DESC_RATEMCS12: - case DESC_RATEVHT1SS_MCS0: - case DESC_RATEVHT1SS_MCS4: - case DESC_RATEVHT1SS_MCS8: - case DESC_RATEVHT2SS_MCS2: - case DESC_RATEVHT2SS_MCS6: - shift = 0; - break; - case DESC_RATE2M: - case DESC_RATE9M: - case DESC_RATE36M: - case DESC_RATEMCS1: - case DESC_RATEMCS5: - case DESC_RATEMCS9: - case DESC_RATEMCS13: - case DESC_RATEVHT1SS_MCS1: - case DESC_RATEVHT1SS_MCS5: - case DESC_RATEVHT1SS_MCS9: - case DESC_RATEVHT2SS_MCS3: - case DESC_RATEVHT2SS_MCS7: - shift = 8; - break; - case DESC_RATE5_5M: - case DESC_RATE12M: - case DESC_RATE48M: - case DESC_RATEMCS2: - case DESC_RATEMCS6: - case DESC_RATEMCS10: - case DESC_RATEMCS14: - case DESC_RATEVHT1SS_MCS2: - case DESC_RATEVHT1SS_MCS6: - case DESC_RATEVHT2SS_MCS0: - case DESC_RATEVHT2SS_MCS4: - case DESC_RATEVHT2SS_MCS8: - shift = 16; - break; - case DESC_RATE11M: - case DESC_RATE18M: - case DESC_RATE54M: - case DESC_RATEMCS3: - case DESC_RATEMCS7: - case DESC_RATEMCS11: - case DESC_RATEMCS15: - case DESC_RATEVHT1SS_MCS3: - case DESC_RATEVHT1SS_MCS7: - case DESC_RATEVHT2SS_MCS1: - case DESC_RATEVHT2SS_MCS5: - case DESC_RATEVHT2SS_MCS9: - shift = 24; - break; - default: - RT_ASSERT(true, "Rate_Section is Illegal\n"); - break; - } - - tx_pwr_diff = (u8)(rtlphy->tx_power_by_rate_offset[band][path] - [tx_num][rate_section] >> shift) & 0xff; - - /* RegEnableTxPowerLimit == 1 for 8812a & 8821a */ - if (rtlpriv->efuse.eeprom_regulatory != 2) { - limit = _rtl8812ae_phy_get_txpower_limit(hw, band, - rtlphy->current_chan_bw, path, rate, - rtlphy->current_channel); - - if (rate == DESC_RATEVHT1SS_MCS8 || rate == DESC_RATEVHT1SS_MCS9 || - rate == DESC_RATEVHT2SS_MCS8 || rate == DESC_RATEVHT2SS_MCS9) { - if (limit < 0) { - if (tx_pwr_diff < (-limit)) - tx_pwr_diff = -limit; - } - } else { - if (limit < 0) - tx_pwr_diff = limit; - else - tx_pwr_diff = tx_pwr_diff > limit ? limit : tx_pwr_diff; - } - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Maximum power by rate %d, final power by rate %d\n", - limit, tx_pwr_diff); - } - - return tx_pwr_diff; -} - -static u8 _rtl8821ae_get_txpower_index(struct ieee80211_hw *hw, u8 path, - u8 rate, u8 bandwidth, u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 index = (channel - 1); - u8 txpower = 0; - bool in_24g = false; - char powerdiff_byrate = 0; - - if (((rtlhal->current_bandtype == BAND_ON_2_4G) && - (channel > 14 || channel < 1)) || - ((rtlhal->current_bandtype == BAND_ON_5G) && (channel <= 14))) { - index = 0; - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "Illegal channel!!\n"); - } - - in_24g = _rtl8821ae_phy_get_chnl_index(channel, &index); - if (in_24g) { - if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) - txpower = rtlefuse->txpwrlevel_cck[path][index]; - else if (DESC_RATE6M <= rate) - txpower = rtlefuse->txpwrlevel_ht40_1s[path][index]; - else - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "invalid rate\n"); - - if (DESC_RATE6M <= rate && rate <= DESC_RATE54M && - !RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) - txpower += rtlefuse->txpwr_legacyhtdiff[path][TX_1S]; - - if (bandwidth == HT_CHANNEL_WIDTH_20) { - if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || - (DESC_RATEVHT1SS_MCS0 <= rate && rate <= DESC_RATEVHT2SS_MCS9)) - txpower += rtlefuse->txpwr_ht20diff[path][TX_1S]; - if ((DESC_RATEMCS8 <= rate && rate <= DESC_RATEMCS15) || - (DESC_RATEVHT2SS_MCS0 <= rate && rate <= DESC_RATEVHT2SS_MCS9)) - txpower += rtlefuse->txpwr_ht20diff[path][TX_2S]; - } else if (bandwidth == HT_CHANNEL_WIDTH_20_40) { - if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || - (DESC_RATEVHT1SS_MCS0 <= rate && rate <= DESC_RATEVHT2SS_MCS9)) - txpower += rtlefuse->txpwr_ht40diff[path][TX_1S]; - if ((DESC_RATEMCS8 <= rate && rate <= DESC_RATEMCS15) || - (DESC_RATEVHT2SS_MCS0 <= rate && rate <= DESC_RATEVHT2SS_MCS9)) - txpower += rtlefuse->txpwr_ht40diff[path][TX_2S]; - } else if (bandwidth == HT_CHANNEL_WIDTH_80) { - if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || - (DESC_RATEVHT1SS_MCS0 <= rate && - rate <= DESC_RATEVHT2SS_MCS9)) - txpower += rtlefuse->txpwr_ht40diff[path][TX_1S]; - if ((DESC_RATEMCS8 <= rate && rate <= DESC_RATEMCS15) || - (DESC_RATEVHT2SS_MCS0 <= rate && - rate <= DESC_RATEVHT2SS_MCS9)) - txpower += rtlefuse->txpwr_ht40diff[path][TX_2S]; - } - } else { - if (DESC_RATE6M <= rate) - txpower = rtlefuse->txpwr_5g_bw40base[path][index]; - else - RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_WARNING, - "INVALID Rate.\n"); - - if (DESC_RATE6M <= rate && rate <= DESC_RATE54M && - !RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) - txpower += rtlefuse->txpwr_5g_ofdmdiff[path][TX_1S]; - - if (bandwidth == HT_CHANNEL_WIDTH_20) { - if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || - (DESC_RATEVHT1SS_MCS0 <= rate && - rate <= DESC_RATEVHT2SS_MCS9)) - txpower += rtlefuse->txpwr_5g_bw20diff[path][TX_1S]; - if ((DESC_RATEMCS8 <= rate && rate <= DESC_RATEMCS15) || - (DESC_RATEVHT2SS_MCS0 <= rate && - rate <= DESC_RATEVHT2SS_MCS9)) - txpower += rtlefuse->txpwr_5g_bw20diff[path][TX_2S]; - } else if (bandwidth == HT_CHANNEL_WIDTH_20_40) { - if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || - (DESC_RATEVHT1SS_MCS0 <= rate && - rate <= DESC_RATEVHT2SS_MCS9)) - txpower += rtlefuse->txpwr_5g_bw40diff[path][TX_1S]; - if ((DESC_RATEMCS8 <= rate && rate <= DESC_RATEMCS15) || - (DESC_RATEVHT2SS_MCS0 <= rate && - rate <= DESC_RATEVHT2SS_MCS9)) - txpower += rtlefuse->txpwr_5g_bw40diff[path][TX_2S]; - } else if (bandwidth == HT_CHANNEL_WIDTH_80) { - u8 channel_5g_80m[CHANNEL_MAX_NUMBER_5G_80M] = { - 42, 58, 106, 122, 138, 155, 171 - }; - u8 i; - - for (i = 0; i < sizeof(channel_5g_80m) / sizeof(u8); ++i) - if (channel_5g_80m[i] == channel) - index = i; - - if ((DESC_RATEMCS0 <= rate && rate <= DESC_RATEMCS15) || - (DESC_RATEVHT1SS_MCS0 <= rate && - rate <= DESC_RATEVHT2SS_MCS9)) - txpower = rtlefuse->txpwr_5g_bw80base[path][index] - + rtlefuse->txpwr_5g_bw80diff[path][TX_1S]; - if ((DESC_RATEMCS8 <= rate && rate <= DESC_RATEMCS15) || - (DESC_RATEVHT2SS_MCS0 <= rate && - rate <= DESC_RATEVHT2SS_MCS9)) - txpower = rtlefuse->txpwr_5g_bw80base[path][index] - + rtlefuse->txpwr_5g_bw80diff[path][TX_1S] - + rtlefuse->txpwr_5g_bw80diff[path][TX_2S]; - } - } - if (rtlefuse->eeprom_regulatory != 2) - powerdiff_byrate = - _rtl8821ae_phy_get_txpower_by_rate(hw, (u8)(!in_24g), - path, rate); - - if (rate == DESC_RATEVHT1SS_MCS8 || rate == DESC_RATEVHT1SS_MCS9 || - rate == DESC_RATEVHT2SS_MCS8 || rate == DESC_RATEVHT2SS_MCS9) - txpower -= powerdiff_byrate; - else - txpower += powerdiff_byrate; - - if (rate > DESC_RATE11M) - txpower += rtlpriv->dm.remnant_ofdm_swing_idx[path]; - else - txpower += rtlpriv->dm.remnant_cck_idx; - - if (txpower > MAX_POWER_INDEX) - txpower = MAX_POWER_INDEX; - - return txpower; -} - -static void _rtl8821ae_phy_set_txpower_index(struct ieee80211_hw *hw, - u8 power_index, u8 path, u8 rate) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (path == RF90_PATH_A) { - switch (rate) { - case DESC_RATE1M: - rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, - MASKBYTE0, power_index); - break; - case DESC_RATE2M: - rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, - MASKBYTE1, power_index); - break; - case DESC_RATE5_5M: - rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, - MASKBYTE2, power_index); - break; - case DESC_RATE11M: - rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, - MASKBYTE3, power_index); - break; - case DESC_RATE6M: - rtl_set_bbreg(hw, RTXAGC_A_OFDM18_OFDM6, - MASKBYTE0, power_index); - break; - case DESC_RATE9M: - rtl_set_bbreg(hw, RTXAGC_A_OFDM18_OFDM6, - MASKBYTE1, power_index); - break; - case DESC_RATE12M: - rtl_set_bbreg(hw, RTXAGC_A_OFDM18_OFDM6, - MASKBYTE2, power_index); - break; - case DESC_RATE18M: - rtl_set_bbreg(hw, RTXAGC_A_OFDM18_OFDM6, - MASKBYTE3, power_index); - break; - case DESC_RATE24M: - rtl_set_bbreg(hw, RTXAGC_A_OFDM54_OFDM24, - MASKBYTE0, power_index); - break; - case DESC_RATE36M: - rtl_set_bbreg(hw, RTXAGC_A_OFDM54_OFDM24, - MASKBYTE1, power_index); - break; - case DESC_RATE48M: - rtl_set_bbreg(hw, RTXAGC_A_OFDM54_OFDM24, - MASKBYTE2, power_index); - break; - case DESC_RATE54M: - rtl_set_bbreg(hw, RTXAGC_A_OFDM54_OFDM24, - MASKBYTE3, power_index); - break; - case DESC_RATEMCS0: - rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, - MASKBYTE0, power_index); - break; - case DESC_RATEMCS1: - rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, - MASKBYTE1, power_index); - break; - case DESC_RATEMCS2: - rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, - MASKBYTE2, power_index); - break; - case DESC_RATEMCS3: - rtl_set_bbreg(hw, RTXAGC_A_MCS03_MCS00, - MASKBYTE3, power_index); - break; - case DESC_RATEMCS4: - rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, - MASKBYTE0, power_index); - break; - case DESC_RATEMCS5: - rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, - MASKBYTE1, power_index); - break; - case DESC_RATEMCS6: - rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, - MASKBYTE2, power_index); - break; - case DESC_RATEMCS7: - rtl_set_bbreg(hw, RTXAGC_A_MCS07_MCS04, - MASKBYTE3, power_index); - break; - case DESC_RATEMCS8: - rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, - MASKBYTE0, power_index); - break; - case DESC_RATEMCS9: - rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, - MASKBYTE1, power_index); - break; - case DESC_RATEMCS10: - rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, - MASKBYTE2, power_index); - break; - case DESC_RATEMCS11: - rtl_set_bbreg(hw, RTXAGC_A_MCS11_MCS08, - MASKBYTE3, power_index); - break; - case DESC_RATEMCS12: - rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, - MASKBYTE0, power_index); - break; - case DESC_RATEMCS13: - rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, - MASKBYTE1, power_index); - break; - case DESC_RATEMCS14: - rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, - MASKBYTE2, power_index); - break; - case DESC_RATEMCS15: - rtl_set_bbreg(hw, RTXAGC_A_MCS15_MCS12, - MASKBYTE3, power_index); - break; - case DESC_RATEVHT1SS_MCS0: - rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX3_NSS1INDEX0, - MASKBYTE0, power_index); - break; - case DESC_RATEVHT1SS_MCS1: - rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX3_NSS1INDEX0, - MASKBYTE1, power_index); - break; - case DESC_RATEVHT1SS_MCS2: - rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX3_NSS1INDEX0, - MASKBYTE2, power_index); - break; - case DESC_RATEVHT1SS_MCS3: - rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX3_NSS1INDEX0, - MASKBYTE3, power_index); - break; - case DESC_RATEVHT1SS_MCS4: - rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX7_NSS1INDEX4, - MASKBYTE0, power_index); - break; - case DESC_RATEVHT1SS_MCS5: - rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX7_NSS1INDEX4, - MASKBYTE1, power_index); - break; - case DESC_RATEVHT1SS_MCS6: - rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX7_NSS1INDEX4, - MASKBYTE2, power_index); - break; - case DESC_RATEVHT1SS_MCS7: - rtl_set_bbreg(hw, RTXAGC_A_NSS1INDEX7_NSS1INDEX4, - MASKBYTE3, power_index); - break; - case DESC_RATEVHT1SS_MCS8: - rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX1_NSS1INDEX8, - MASKBYTE0, power_index); - break; - case DESC_RATEVHT1SS_MCS9: - rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX1_NSS1INDEX8, - MASKBYTE1, power_index); - break; - case DESC_RATEVHT2SS_MCS0: - rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX1_NSS1INDEX8, - MASKBYTE2, power_index); - break; - case DESC_RATEVHT2SS_MCS1: - rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX1_NSS1INDEX8, - MASKBYTE3, power_index); - break; - case DESC_RATEVHT2SS_MCS2: - rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX5_NSS2INDEX2, - MASKBYTE0, power_index); - break; - case DESC_RATEVHT2SS_MCS3: - rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX5_NSS2INDEX2, - MASKBYTE1, power_index); - break; - case DESC_RATEVHT2SS_MCS4: - rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX5_NSS2INDEX2, - MASKBYTE2, power_index); - break; - case DESC_RATEVHT2SS_MCS5: - rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX5_NSS2INDEX2, - MASKBYTE3, power_index); - break; - case DESC_RATEVHT2SS_MCS6: - rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX9_NSS2INDEX6, - MASKBYTE0, power_index); - break; - case DESC_RATEVHT2SS_MCS7: - rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX9_NSS2INDEX6, - MASKBYTE1, power_index); - break; - case DESC_RATEVHT2SS_MCS8: - rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX9_NSS2INDEX6, - MASKBYTE2, power_index); - break; - case DESC_RATEVHT2SS_MCS9: - rtl_set_bbreg(hw, RTXAGC_A_NSS2INDEX9_NSS2INDEX6, - MASKBYTE3, power_index); - break; - default: - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Invalid Rate!!\n"); - break; - } - } else if (path == RF90_PATH_B) { - switch (rate) { - case DESC_RATE1M: - rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, - MASKBYTE0, power_index); - break; - case DESC_RATE2M: - rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, - MASKBYTE1, power_index); - break; - case DESC_RATE5_5M: - rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, - MASKBYTE2, power_index); - break; - case DESC_RATE11M: - rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, - MASKBYTE3, power_index); - break; - case DESC_RATE6M: - rtl_set_bbreg(hw, RTXAGC_B_OFDM18_OFDM6, - MASKBYTE0, power_index); - break; - case DESC_RATE9M: - rtl_set_bbreg(hw, RTXAGC_B_OFDM18_OFDM6, - MASKBYTE1, power_index); - break; - case DESC_RATE12M: - rtl_set_bbreg(hw, RTXAGC_B_OFDM18_OFDM6, - MASKBYTE2, power_index); - break; - case DESC_RATE18M: - rtl_set_bbreg(hw, RTXAGC_B_OFDM18_OFDM6, - MASKBYTE3, power_index); - break; - case DESC_RATE24M: - rtl_set_bbreg(hw, RTXAGC_B_OFDM54_OFDM24, - MASKBYTE0, power_index); - break; - case DESC_RATE36M: - rtl_set_bbreg(hw, RTXAGC_B_OFDM54_OFDM24, - MASKBYTE1, power_index); - break; - case DESC_RATE48M: - rtl_set_bbreg(hw, RTXAGC_B_OFDM54_OFDM24, - MASKBYTE2, power_index); - break; - case DESC_RATE54M: - rtl_set_bbreg(hw, RTXAGC_B_OFDM54_OFDM24, - MASKBYTE3, power_index); - break; - case DESC_RATEMCS0: - rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, - MASKBYTE0, power_index); - break; - case DESC_RATEMCS1: - rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, - MASKBYTE1, power_index); - break; - case DESC_RATEMCS2: - rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, - MASKBYTE2, power_index); - break; - case DESC_RATEMCS3: - rtl_set_bbreg(hw, RTXAGC_B_MCS03_MCS00, - MASKBYTE3, power_index); - break; - case DESC_RATEMCS4: - rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, - MASKBYTE0, power_index); - break; - case DESC_RATEMCS5: - rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, - MASKBYTE1, power_index); - break; - case DESC_RATEMCS6: - rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, - MASKBYTE2, power_index); - break; - case DESC_RATEMCS7: - rtl_set_bbreg(hw, RTXAGC_B_MCS07_MCS04, - MASKBYTE3, power_index); - break; - case DESC_RATEMCS8: - rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, - MASKBYTE0, power_index); - break; - case DESC_RATEMCS9: - rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, - MASKBYTE1, power_index); - break; - case DESC_RATEMCS10: - rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, - MASKBYTE2, power_index); - break; - case DESC_RATEMCS11: - rtl_set_bbreg(hw, RTXAGC_B_MCS11_MCS08, - MASKBYTE3, power_index); - break; - case DESC_RATEMCS12: - rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, - MASKBYTE0, power_index); - break; - case DESC_RATEMCS13: - rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, - MASKBYTE1, power_index); - break; - case DESC_RATEMCS14: - rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, - MASKBYTE2, power_index); - break; - case DESC_RATEMCS15: - rtl_set_bbreg(hw, RTXAGC_B_MCS15_MCS12, - MASKBYTE3, power_index); - break; - case DESC_RATEVHT1SS_MCS0: - rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX3_NSS1INDEX0, - MASKBYTE0, power_index); - break; - case DESC_RATEVHT1SS_MCS1: - rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX3_NSS1INDEX0, - MASKBYTE1, power_index); - break; - case DESC_RATEVHT1SS_MCS2: - rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX3_NSS1INDEX0, - MASKBYTE2, power_index); - break; - case DESC_RATEVHT1SS_MCS3: - rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX3_NSS1INDEX0, - MASKBYTE3, power_index); - break; - case DESC_RATEVHT1SS_MCS4: - rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX7_NSS1INDEX4, - MASKBYTE0, power_index); - break; - case DESC_RATEVHT1SS_MCS5: - rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX7_NSS1INDEX4, - MASKBYTE1, power_index); - break; - case DESC_RATEVHT1SS_MCS6: - rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX7_NSS1INDEX4, - MASKBYTE2, power_index); - break; - case DESC_RATEVHT1SS_MCS7: - rtl_set_bbreg(hw, RTXAGC_B_NSS1INDEX7_NSS1INDEX4, - MASKBYTE3, power_index); - break; - case DESC_RATEVHT1SS_MCS8: - rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX1_NSS1INDEX8, - MASKBYTE0, power_index); - break; - case DESC_RATEVHT1SS_MCS9: - rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX1_NSS1INDEX8, - MASKBYTE1, power_index); - break; - case DESC_RATEVHT2SS_MCS0: - rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX1_NSS1INDEX8, - MASKBYTE2, power_index); - break; - case DESC_RATEVHT2SS_MCS1: - rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX1_NSS1INDEX8, - MASKBYTE3, power_index); - break; - case DESC_RATEVHT2SS_MCS2: - rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX5_NSS2INDEX2, - MASKBYTE0, power_index); - break; - case DESC_RATEVHT2SS_MCS3: - rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX5_NSS2INDEX2, - MASKBYTE1, power_index); - break; - case DESC_RATEVHT2SS_MCS4: - rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX5_NSS2INDEX2, - MASKBYTE2, power_index); - break; - case DESC_RATEVHT2SS_MCS5: - rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX5_NSS2INDEX2, - MASKBYTE3, power_index); - break; - case DESC_RATEVHT2SS_MCS6: - rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX9_NSS2INDEX6, - MASKBYTE0, power_index); - break; - case DESC_RATEVHT2SS_MCS7: - rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX9_NSS2INDEX6, - MASKBYTE1, power_index); - break; - case DESC_RATEVHT2SS_MCS8: - rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX9_NSS2INDEX6, - MASKBYTE2, power_index); - break; - case DESC_RATEVHT2SS_MCS9: - rtl_set_bbreg(hw, RTXAGC_B_NSS2INDEX9_NSS2INDEX6, - MASKBYTE3, power_index); - break; - default: - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Invalid Rate!!\n"); - break; - } - } else { - RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, - "Invalid RFPath!!\n"); - } -} - -static void _rtl8821ae_phy_set_txpower_level_by_path(struct ieee80211_hw *hw, - u8 *array, u8 path, - u8 channel, u8 size) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 i; - u8 power_index; - - for (i = 0; i < size; i++) { - power_index = - _rtl8821ae_get_txpower_index(hw, path, array[i], - rtlphy->current_chan_bw, - channel); - _rtl8821ae_phy_set_txpower_index(hw, power_index, path, - array[i]); - } -} - -static void _rtl8821ae_phy_txpower_training_by_path(struct ieee80211_hw *hw, - u8 bw, u8 channel, u8 path) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - u8 i; - u32 power_level, data, offset; - - if (path >= rtlphy->num_total_rfpath) - return; - - data = 0; - if (path == RF90_PATH_A) { - power_level = - _rtl8821ae_get_txpower_index(hw, RF90_PATH_A, - DESC_RATEMCS7, bw, channel); - offset = RA_TXPWRTRAING; - } else { - power_level = - _rtl8821ae_get_txpower_index(hw, RF90_PATH_B, - DESC_RATEMCS7, bw, channel); - offset = RB_TXPWRTRAING; - } - - for (i = 0; i < 3; i++) { - if (i == 0) - power_level = power_level - 10; - else if (i == 1) - power_level = power_level - 8; - else - power_level = power_level - 6; - - data |= (((power_level > 2) ? (power_level) : 2) << (i * 8)); - } - rtl_set_bbreg(hw, offset, 0xffffff, data); -} - -void rtl8821ae_phy_set_txpower_level_by_path(struct ieee80211_hw *hw, - u8 channel, u8 path) -{ - /* struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); */ - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 cck_rates[] = {DESC_RATE1M, DESC_RATE2M, DESC_RATE5_5M, - DESC_RATE11M}; - u8 sizes_of_cck_retes = 4; - u8 ofdm_rates[] = {DESC_RATE6M, DESC_RATE9M, DESC_RATE12M, - DESC_RATE18M, DESC_RATE24M, DESC_RATE36M, - DESC_RATE48M, DESC_RATE54M}; - u8 sizes_of_ofdm_retes = 8; - u8 ht_rates_1t[] = {DESC_RATEMCS0, DESC_RATEMCS1, DESC_RATEMCS2, - DESC_RATEMCS3, DESC_RATEMCS4, DESC_RATEMCS5, - DESC_RATEMCS6, DESC_RATEMCS7}; - u8 sizes_of_ht_retes_1t = 8; - u8 ht_rates_2t[] = {DESC_RATEMCS8, DESC_RATEMCS9, - DESC_RATEMCS10, DESC_RATEMCS11, - DESC_RATEMCS12, DESC_RATEMCS13, - DESC_RATEMCS14, DESC_RATEMCS15}; - u8 sizes_of_ht_retes_2t = 8; - u8 vht_rates_1t[] = {DESC_RATEVHT1SS_MCS0, DESC_RATEVHT1SS_MCS1, - DESC_RATEVHT1SS_MCS2, DESC_RATEVHT1SS_MCS3, - DESC_RATEVHT1SS_MCS4, DESC_RATEVHT1SS_MCS5, - DESC_RATEVHT1SS_MCS6, DESC_RATEVHT1SS_MCS7, - DESC_RATEVHT1SS_MCS8, DESC_RATEVHT1SS_MCS9}; - u8 vht_rates_2t[] = {DESC_RATEVHT2SS_MCS0, DESC_RATEVHT2SS_MCS1, - DESC_RATEVHT2SS_MCS2, DESC_RATEVHT2SS_MCS3, - DESC_RATEVHT2SS_MCS4, DESC_RATEVHT2SS_MCS5, - DESC_RATEVHT2SS_MCS6, DESC_RATEVHT2SS_MCS7, - DESC_RATEVHT2SS_MCS8, DESC_RATEVHT2SS_MCS9}; - u8 sizes_of_vht_retes = 10; - - if (rtlhal->current_bandtype == BAND_ON_2_4G) - _rtl8821ae_phy_set_txpower_level_by_path(hw, cck_rates, path, channel, - sizes_of_cck_retes); - - _rtl8821ae_phy_set_txpower_level_by_path(hw, ofdm_rates, path, channel, - sizes_of_ofdm_retes); - _rtl8821ae_phy_set_txpower_level_by_path(hw, ht_rates_1t, path, channel, - sizes_of_ht_retes_1t); - _rtl8821ae_phy_set_txpower_level_by_path(hw, vht_rates_1t, path, channel, - sizes_of_vht_retes); - - if (rtlphy->num_total_rfpath >= 2) { - _rtl8821ae_phy_set_txpower_level_by_path(hw, ht_rates_2t, path, - channel, - sizes_of_ht_retes_2t); - _rtl8821ae_phy_set_txpower_level_by_path(hw, vht_rates_2t, path, - channel, - sizes_of_vht_retes); - } - - _rtl8821ae_phy_txpower_training_by_path(hw, rtlphy->current_chan_bw, - channel, path); -} - -/*just in case, write txpower in DW, to reduce time*/ -void rtl8821ae_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 path = 0; - - for (path = RF90_PATH_A; path < rtlphy->num_total_rfpath; ++path) - rtl8821ae_phy_set_txpower_level_by_path(hw, channel, path); -} - -static long _rtl8821ae_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw, - enum wireless_mode wirelessmode, - u8 txpwridx) -{ - long offset; - long pwrout_dbm; - - switch (wirelessmode) { - case WIRELESS_MODE_B: - offset = -7; - break; - case WIRELESS_MODE_G: - case WIRELESS_MODE_N_24G: - offset = -8; - break; - default: - offset = -8; - break; - } - pwrout_dbm = txpwridx / 2 + offset; - return pwrout_dbm; -} - -void rtl8821ae_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - enum io_type iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; - - if (!is_hal_stop(rtlhal)) { - switch (operation) { - case SCAN_OPT_BACKUP_BAND0: - iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_IO_CMD, - (u8 *)&iotype); - - break; - case SCAN_OPT_BACKUP_BAND1: - iotype = IO_CMD_PAUSE_BAND1_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_IO_CMD, - (u8 *)&iotype); - - break; - case SCAN_OPT_RESTORE: - iotype = IO_CMD_RESUME_DM_BY_SCAN; - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_IO_CMD, - (u8 *)&iotype); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Unknown Scan Backup operation.\n"); - break; - } - } -} - -static void _rtl8821ae_phy_set_reg_bw(struct rtl_priv *rtlpriv, u8 bw) -{ - u16 reg_rf_mode_bw, tmp = 0; - - reg_rf_mode_bw = rtl_read_word(rtlpriv, REG_TRXPTCL_CTL); - switch (bw) { - case HT_CHANNEL_WIDTH_20: - rtl_write_word(rtlpriv, REG_TRXPTCL_CTL, reg_rf_mode_bw & 0xFE7F); - break; - case HT_CHANNEL_WIDTH_20_40: - tmp = reg_rf_mode_bw | BIT(7); - rtl_write_word(rtlpriv, REG_TRXPTCL_CTL, tmp & 0xFEFF); - break; - case HT_CHANNEL_WIDTH_80: - tmp = reg_rf_mode_bw | BIT(8); - rtl_write_word(rtlpriv, REG_TRXPTCL_CTL, tmp & 0xFF7F); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "unknown Bandwidth: 0x%x\n", bw); - break; - } -} - -static u8 _rtl8821ae_phy_get_secondary_chnl(struct rtl_priv *rtlpriv) -{ - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_mac *mac = rtl_mac(rtlpriv); - u8 sc_set_40 = 0, sc_set_20 = 0; - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) { - if (mac->cur_80_prime_sc == PRIME_CHNL_OFFSET_LOWER) - sc_set_40 = VHT_DATA_SC_40_LOWER_OF_80MHZ; - else if (mac->cur_80_prime_sc == PRIME_CHNL_OFFSET_UPPER) - sc_set_40 = VHT_DATA_SC_40_UPPER_OF_80MHZ; - else - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "SCMapping: Not Correct Primary40MHz Setting\n"); - - if ((mac->cur_40_prime_sc == PRIME_CHNL_OFFSET_LOWER) && - (mac->cur_80_prime_sc == HAL_PRIME_CHNL_OFFSET_LOWER)) - sc_set_20 = VHT_DATA_SC_20_LOWEST_OF_80MHZ; - else if ((mac->cur_40_prime_sc == PRIME_CHNL_OFFSET_UPPER) && - (mac->cur_80_prime_sc == HAL_PRIME_CHNL_OFFSET_LOWER)) - sc_set_20 = VHT_DATA_SC_20_LOWER_OF_80MHZ; - else if ((mac->cur_40_prime_sc == PRIME_CHNL_OFFSET_LOWER) && - (mac->cur_80_prime_sc == HAL_PRIME_CHNL_OFFSET_UPPER)) - sc_set_20 = VHT_DATA_SC_20_UPPER_OF_80MHZ; - else if ((mac->cur_40_prime_sc == PRIME_CHNL_OFFSET_UPPER) && - (mac->cur_80_prime_sc == HAL_PRIME_CHNL_OFFSET_UPPER)) - sc_set_20 = VHT_DATA_SC_20_UPPERST_OF_80MHZ; - else - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "SCMapping: Not Correct Primary40MHz Setting\n"); - } else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - if (mac->cur_40_prime_sc == PRIME_CHNL_OFFSET_UPPER) - sc_set_20 = VHT_DATA_SC_20_UPPER_OF_80MHZ; - else if (mac->cur_40_prime_sc == PRIME_CHNL_OFFSET_LOWER) - sc_set_20 = VHT_DATA_SC_20_LOWER_OF_80MHZ; - else - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "SCMapping: Not Correct Primary40MHz Setting\n"); - } - return (sc_set_40 << 4) | sc_set_20; -} - -void rtl8821ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 sub_chnl = 0; - u8 l1pk_val = 0; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "Switch to %s bandwidth\n", - (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? - "20MHz" : - (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40 ? - "40MHz" : "80MHz"))); - - _rtl8821ae_phy_set_reg_bw(rtlpriv, rtlphy->current_chan_bw); - sub_chnl = _rtl8821ae_phy_get_secondary_chnl(rtlpriv); - rtl_write_byte(rtlpriv, 0x0483, sub_chnl); - - switch (rtlphy->current_chan_bw) { - case HT_CHANNEL_WIDTH_20: - rtl_set_bbreg(hw, RRFMOD, 0x003003C3, 0x00300200); - rtl_set_bbreg(hw, RADC_BUF_CLK, BIT(30), 0); - - if (rtlphy->rf_type == RF_2T2R) - rtl_set_bbreg(hw, RL1PEAKTH, 0x03C00000, 7); - else - rtl_set_bbreg(hw, RL1PEAKTH, 0x03C00000, 8); - break; - case HT_CHANNEL_WIDTH_20_40: - rtl_set_bbreg(hw, RRFMOD, 0x003003C3, 0x00300201); - rtl_set_bbreg(hw, RADC_BUF_CLK, BIT(30), 0); - rtl_set_bbreg(hw, RRFMOD, 0x3C, sub_chnl); - rtl_set_bbreg(hw, RCCAONSEC, 0xf0000000, sub_chnl); - - if (rtlphy->reg_837 & BIT(2)) - l1pk_val = 6; - else { - if (rtlphy->rf_type == RF_2T2R) - l1pk_val = 7; - else - l1pk_val = 8; - } - /* 0x848[25:22] = 0x6 */ - rtl_set_bbreg(hw, RL1PEAKTH, 0x03C00000, l1pk_val); - - if (sub_chnl == VHT_DATA_SC_20_UPPER_OF_80MHZ) - rtl_set_bbreg(hw, RCCK_SYSTEM, BCCK_SYSTEM, 1); - else - rtl_set_bbreg(hw, RCCK_SYSTEM, BCCK_SYSTEM, 0); - break; - - case HT_CHANNEL_WIDTH_80: - /* 0x8ac[21,20,9:6,1,0]=8'b11100010 */ - rtl_set_bbreg(hw, RRFMOD, 0x003003C3, 0x00300202); - /* 0x8c4[30] = 1 */ - rtl_set_bbreg(hw, RADC_BUF_CLK, BIT(30), 1); - rtl_set_bbreg(hw, RRFMOD, 0x3C, sub_chnl); - rtl_set_bbreg(hw, RCCAONSEC, 0xf0000000, sub_chnl); - - if (rtlphy->reg_837 & BIT(2)) - l1pk_val = 5; - else { - if (rtlphy->rf_type == RF_2T2R) - l1pk_val = 6; - else - l1pk_val = 7; - } - rtl_set_bbreg(hw, RL1PEAKTH, 0x03C00000, l1pk_val); - - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); - break; - } - - rtl8812ae_fixspur(hw, rtlphy->current_chan_bw, rtlphy->current_channel); - - rtl8821ae_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); - rtlphy->set_bwmode_inprogress = false; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n"); -} - -void rtl8821ae_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 tmp_bw = rtlphy->current_chan_bw; - - if (rtlphy->set_bwmode_inprogress) - return; - rtlphy->set_bwmode_inprogress = true; - if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) - rtl8821ae_phy_set_bw_mode_callback(hw); - else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "FALSE driver sleep or unload\n"); - rtlphy->set_bwmode_inprogress = false; - rtlphy->current_chan_bw = tmp_bw; - } -} - -void rtl8821ae_phy_sw_chnl_callback(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 channel = rtlphy->current_channel; - u8 path; - u32 data; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "switch to channel%d\n", rtlphy->current_channel); - if (is_hal_stop(rtlhal)) - return; - - if (36 <= channel && channel <= 48) - data = 0x494; - else if (50 <= channel && channel <= 64) - data = 0x453; - else if (100 <= channel && channel <= 116) - data = 0x452; - else if (118 <= channel) - data = 0x412; - else - data = 0x96a; - rtl_set_bbreg(hw, RFC_AREA, 0x1ffe0000, data); - - for (path = RF90_PATH_A; path < rtlphy->num_total_rfpath; path++) { - if (36 <= channel && channel <= 64) - data = 0x101; - else if (100 <= channel && channel <= 140) - data = 0x301; - else if (140 < channel) - data = 0x501; - else - data = 0x000; - rtl8821ae_phy_set_rf_reg(hw, path, RF_CHNLBW, - BIT(18)|BIT(17)|BIT(16)|BIT(9)|BIT(8), data); - - rtl8821ae_phy_set_rf_reg(hw, path, RF_CHNLBW, - BMASKBYTE0, channel); - - if (channel > 14) { - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) { - if (36 <= channel && channel <= 64) - data = 0x114E9; - else if (100 <= channel && channel <= 140) - data = 0x110E9; - else - data = 0x110E9; - rtl8821ae_phy_set_rf_reg(hw, path, RF_APK, - BRFREGOFFSETMASK, data); - } - } - } - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); -} - -u8 rtl8821ae_phy_sw_chnl(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u32 timeout = 1000, timecount = 0; - u8 channel = rtlphy->current_channel; - - if (rtlphy->sw_chnl_inprogress) - return 0; - if (rtlphy->set_bwmode_inprogress) - return 0; - - if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) { - RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false driver sleep or unload\n"); - return 0; - } - while (rtlphy->lck_inprogress && timecount < timeout) { - mdelay(50); - timecount += 50; - } - - if (rtlphy->current_channel > 14 && rtlhal->current_bandtype != BAND_ON_5G) - rtl8821ae_phy_switch_wirelessband(hw, BAND_ON_5G); - else if (rtlphy->current_channel <= 14 && rtlhal->current_bandtype != BAND_ON_2_4G) - rtl8821ae_phy_switch_wirelessband(hw, BAND_ON_2_4G); - - rtlphy->sw_chnl_inprogress = true; - if (channel == 0) - channel = 1; - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, - "switch to channel%d, band type is %d\n", - rtlphy->current_channel, rtlhal->current_bandtype); - - rtl8821ae_phy_sw_chnl_callback(hw); - - rtl8821ae_dm_clear_txpower_tracking_state(hw); - rtl8821ae_phy_set_txpower_level(hw, rtlphy->current_channel); - - RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); - rtlphy->sw_chnl_inprogress = false; - return 1; -} - -u8 _rtl8812ae_get_right_chnl_place_for_iqk(u8 chnl) -{ - u8 channel_all[TARGET_CHNL_NUM_2G_5G_8812] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, - 56, 58, 60, 62, 64, 100, 102, 104, 106, 108, - 110, 112, 114, 116, 118, 120, 122, 124, 126, - 128, 130, 132, 134, 136, 138, 140, 149, 151, - 153, 155, 157, 159, 161, 163, 165}; - u8 place = chnl; - - if (chnl > 14) { - for (place = 14; place < sizeof(channel_all); place++) - if (channel_all[place] == chnl) - return place-13; - } - - return 0; -} - -#define MACBB_REG_NUM 10 -#define AFE_REG_NUM 14 -#define RF_REG_NUM 3 - -static void _rtl8821ae_iqk_backup_macbb(struct ieee80211_hw *hw, - u32 *macbb_backup, - u32 *backup_macbb_reg, u32 mac_bb_num) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /*[31] = 0 --> Page C*/ - /*save MACBB default value*/ - for (i = 0; i < mac_bb_num; i++) - macbb_backup[i] = rtl_read_dword(rtlpriv, backup_macbb_reg[i]); - - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "BackupMacBB Success!!!!\n"); -} - -static void _rtl8821ae_iqk_backup_afe(struct ieee80211_hw *hw, u32 *afe_backup, - u32 *backup_afe_REG, u32 afe_num) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /*[31] = 0 --> Page C*/ - /*Save AFE Parameters */ - for (i = 0; i < afe_num; i++) - afe_backup[i] = rtl_read_dword(rtlpriv, backup_afe_REG[i]); - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "BackupAFE Success!!!!\n"); -} - -static void _rtl8821ae_iqk_backup_rf(struct ieee80211_hw *hw, u32 *rfa_backup, - u32 *rfb_backup, u32 *backup_rf_reg, - u32 rf_num) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /*[31] = 0 --> Page C*/ - /*Save RF Parameters*/ - for (i = 0; i < rf_num; i++) { - rfa_backup[i] = rtl_get_rfreg(hw, RF90_PATH_A, backup_rf_reg[i], - BMASKDWORD); - rfb_backup[i] = rtl_get_rfreg(hw, RF90_PATH_B, backup_rf_reg[i], - BMASKDWORD); - } - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "BackupRF Success!!!!\n"); -} - -static void _rtl8821ae_iqk_configure_mac( - struct ieee80211_hw *hw - ) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - /* ========MAC register setting========*/ - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /*[31] = 0 --> Page C*/ - rtl_write_byte(rtlpriv, 0x522, 0x3f); - rtl_set_bbreg(hw, 0x550, BIT(11) | BIT(3), 0x0); - rtl_write_byte(rtlpriv, 0x808, 0x00); /*RX ante off*/ - rtl_set_bbreg(hw, 0x838, 0xf, 0xc); /*CCA off*/ -} - -static void _rtl8821ae_iqk_tx_fill_iqc(struct ieee80211_hw *hw, - enum radio_path path, u32 tx_x, u32 tx_y) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - switch (path) { - case RF90_PATH_A: - /* [31] = 1 --> Page C1 */ - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); - rtl_write_dword(rtlpriv, 0xc90, 0x00000080); - rtl_write_dword(rtlpriv, 0xcc4, 0x20040000); - rtl_write_dword(rtlpriv, 0xcc8, 0x20000000); - rtl_set_bbreg(hw, 0xccc, 0x000007ff, tx_y); - rtl_set_bbreg(hw, 0xcd4, 0x000007ff, tx_x); - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "TX_X = %x;;TX_Y = %x =====> fill to IQC\n", - tx_x, tx_y); - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "0xcd4 = %x;;0xccc = %x ====>fill to IQC\n", - rtl_get_bbreg(hw, 0xcd4, 0x000007ff), - rtl_get_bbreg(hw, 0xccc, 0x000007ff)); - break; - default: - break; - } -} - -static void _rtl8821ae_iqk_rx_fill_iqc(struct ieee80211_hw *hw, - enum radio_path path, u32 rx_x, u32 rx_y) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - switch (path) { - case RF90_PATH_A: - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ - rtl_set_bbreg(hw, 0xc10, 0x000003ff, rx_x>>1); - rtl_set_bbreg(hw, 0xc10, 0x03ff0000, rx_y>>1); - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "rx_x = %x;;rx_y = %x ====>fill to IQC\n", - rx_x>>1, rx_y>>1); - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "0xc10 = %x ====>fill to IQC\n", - rtl_read_dword(rtlpriv, 0xc10)); - break; - default: - break; - } -} - -#define cal_num 10 - -static void _rtl8821ae_iqk_tx(struct ieee80211_hw *hw, enum radio_path path) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - u32 tx_fail, rx_fail, delay_count, iqk_ready, cal_retry, cal = 0, temp_reg65; - int tx_x = 0, tx_y = 0, rx_x = 0, rx_y = 0, tx_average = 0, rx_average = 0; - int tx_x0[cal_num], tx_y0[cal_num], tx_x0_rxk[cal_num], - tx_y0_rxk[cal_num], rx_x0[cal_num], rx_y0[cal_num]; - bool tx0iqkok = false, rx0iqkok = false; - bool vdf_enable = false; - int i, k, vdf_y[3], vdf_x[3], tx_dt[3], rx_dt[3], - ii, dx = 0, dy = 0, tx_finish = 0, rx_finish = 0; - - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "BandWidth = %d.\n", - rtlphy->current_chan_bw); - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) - vdf_enable = true; - - while (cal < cal_num) { - switch (path) { - case RF90_PATH_A: - temp_reg65 = rtl_get_rfreg(hw, path, 0x65, 0xffffffff); - /* Path-A LOK */ - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /*[31] = 0 --> Page C*/ - /*========Path-A AFE all on========*/ - /*Port 0 DAC/ADC on*/ - rtl_write_dword(rtlpriv, 0xc60, 0x77777777); - rtl_write_dword(rtlpriv, 0xc64, 0x77777777); - rtl_write_dword(rtlpriv, 0xc68, 0x19791979); - rtl_write_dword(rtlpriv, 0xc6c, 0x19791979); - rtl_write_dword(rtlpriv, 0xc70, 0x19791979); - rtl_write_dword(rtlpriv, 0xc74, 0x19791979); - rtl_write_dword(rtlpriv, 0xc78, 0x19791979); - rtl_write_dword(rtlpriv, 0xc7c, 0x19791979); - rtl_write_dword(rtlpriv, 0xc80, 0x19791979); - rtl_write_dword(rtlpriv, 0xc84, 0x19791979); - - rtl_set_bbreg(hw, 0xc00, 0xf, 0x4); /*hardware 3-wire off*/ - - /* LOK Setting */ - /* ====== LOK ====== */ - /*DAC/ADC sampling rate (160 MHz)*/ - rtl_set_bbreg(hw, 0xc5c, BIT(26) | BIT(25) | BIT(24), 0x7); - - /* 2. LoK RF Setting (at BW = 20M) */ - rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x80002); - rtl_set_rfreg(hw, path, 0x18, 0x00c00, 0x3); /* BW 20M */ - rtl_set_rfreg(hw, path, 0x30, RFREG_OFFSET_MASK, 0x20000); - rtl_set_rfreg(hw, path, 0x31, RFREG_OFFSET_MASK, 0x0003f); - rtl_set_rfreg(hw, path, 0x32, RFREG_OFFSET_MASK, 0xf3fc3); - rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, 0x931d5); - rtl_set_rfreg(hw, path, 0x8f, RFREG_OFFSET_MASK, 0x8a001); - rtl_set_bbreg(hw, 0xcb8, 0xf, 0xd); - rtl_write_dword(rtlpriv, 0x90c, 0x00008000); - rtl_write_dword(rtlpriv, 0xb00, 0x03000100); - rtl_set_bbreg(hw, 0xc94, BIT(0), 0x1); - rtl_write_dword(rtlpriv, 0x978, 0x29002000);/* TX (X,Y) */ - rtl_write_dword(rtlpriv, 0x97c, 0xa9002000);/* RX (X,Y) */ - rtl_write_dword(rtlpriv, 0x984, 0x00462910);/* [0]:AGC_en, [15]:idac_K_Mask */ - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ - rtl_write_dword(rtlpriv, 0xc88, 0x821403f4); - - if (rtlhal->current_bandtype) - rtl_write_dword(rtlpriv, 0xc8c, 0x68163e96); - else - rtl_write_dword(rtlpriv, 0xc8c, 0x28163e96); - - rtl_write_dword(rtlpriv, 0xc80, 0x18008c10);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ - rtl_write_dword(rtlpriv, 0xc84, 0x38008c10);/* RX_TONE_idx[9:0], RxK_Mask[29] */ - rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ - rtl_write_dword(rtlpriv, 0x980, 0xfa000000); - rtl_write_dword(rtlpriv, 0x980, 0xf8000000); - - mdelay(10); /* Delay 10ms */ - rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ - rtl_set_rfreg(hw, path, 0x58, 0x7fe00, rtl_get_rfreg(hw, path, 0x8, 0xffc00)); /* Load LOK */ - - switch (rtlphy->current_chan_bw) { - case 1: - rtl_set_rfreg(hw, path, 0x18, 0x00c00, 0x1); - break; - case 2: - rtl_set_rfreg(hw, path, 0x18, 0x00c00, 0x0); - break; - default: - break; - } - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ - - /* 3. TX RF Setting */ - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ - rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x80000); - rtl_set_rfreg(hw, path, 0x30, RFREG_OFFSET_MASK, 0x20000); - rtl_set_rfreg(hw, path, 0x31, RFREG_OFFSET_MASK, 0x0003f); - rtl_set_rfreg(hw, path, 0x32, RFREG_OFFSET_MASK, 0xf3fc3); - rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, 0x931d5); - rtl_set_rfreg(hw, path, 0x8f, RFREG_OFFSET_MASK, 0x8a001); - rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x00000); - /* ODM_SetBBReg(pDM_Odm, 0xcb8, 0xf, 0xd); */ - rtl_write_dword(rtlpriv, 0x90c, 0x00008000); - rtl_write_dword(rtlpriv, 0xb00, 0x03000100); - rtl_set_bbreg(hw, 0xc94, BIT(0), 0x1); - rtl_write_dword(rtlpriv, 0x978, 0x29002000);/* TX (X,Y) */ - rtl_write_dword(rtlpriv, 0x97c, 0xa9002000);/* RX (X,Y) */ - rtl_write_dword(rtlpriv, 0x984, 0x0046a910);/* [0]:AGC_en, [15]:idac_K_Mask */ - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ - rtl_write_dword(rtlpriv, 0xc88, 0x821403f1); - if (rtlhal->current_bandtype) - rtl_write_dword(rtlpriv, 0xc8c, 0x40163e96); - else - rtl_write_dword(rtlpriv, 0xc8c, 0x00163e96); - - if (vdf_enable == 1) { - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "VDF_enable\n"); - for (k = 0; k <= 2; k++) { - switch (k) { - case 0: - rtl_write_dword(rtlpriv, 0xc80, 0x18008c38);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ - rtl_write_dword(rtlpriv, 0xc84, 0x38008c38);/* RX_TONE_idx[9:0], RxK_Mask[29] */ - rtl_set_bbreg(hw, 0xce8, BIT(31), 0x0); - break; - case 1: - rtl_set_bbreg(hw, 0xc80, BIT(28), 0x0); - rtl_set_bbreg(hw, 0xc84, BIT(28), 0x0); - rtl_set_bbreg(hw, 0xce8, BIT(31), 0x0); - break; - case 2: - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "vdf_y[1] = %x;;;vdf_y[0] = %x\n", vdf_y[1]>>21 & 0x00007ff, vdf_y[0]>>21 & 0x00007ff); - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "vdf_x[1] = %x;;;vdf_x[0] = %x\n", vdf_x[1]>>21 & 0x00007ff, vdf_x[0]>>21 & 0x00007ff); - tx_dt[cal] = (vdf_y[1]>>20)-(vdf_y[0]>>20); - tx_dt[cal] = ((16*tx_dt[cal])*10000/15708); - tx_dt[cal] = (tx_dt[cal] >> 1)+(tx_dt[cal] & BIT(0)); - rtl_write_dword(rtlpriv, 0xc80, 0x18008c20);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ - rtl_write_dword(rtlpriv, 0xc84, 0x38008c20);/* RX_TONE_idx[9:0], RxK_Mask[29] */ - rtl_set_bbreg(hw, 0xce8, BIT(31), 0x1); - rtl_set_bbreg(hw, 0xce8, 0x3fff0000, tx_dt[cal] & 0x00003fff); - break; - default: - break; - } - rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ - cal_retry = 0; - while (1) { - /* one shot */ - rtl_write_dword(rtlpriv, 0x980, 0xfa000000); - rtl_write_dword(rtlpriv, 0x980, 0xf8000000); - - mdelay(10); /* Delay 10ms */ - rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); - delay_count = 0; - while (1) { - iqk_ready = rtl_get_bbreg(hw, 0xd00, BIT(10)); - if ((~iqk_ready) || (delay_count > 20)) - break; - else{ - mdelay(1); - delay_count++; - } - } - - if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ - /* ============TXIQK Check============== */ - tx_fail = rtl_get_bbreg(hw, 0xd00, BIT(12)); - - if (~tx_fail) { - rtl_write_dword(rtlpriv, 0xcb8, 0x02000000); - vdf_x[k] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; - rtl_write_dword(rtlpriv, 0xcb8, 0x04000000); - vdf_y[k] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; - tx0iqkok = true; - break; - } else { - rtl_set_bbreg(hw, 0xccc, 0x000007ff, 0x0); - rtl_set_bbreg(hw, 0xcd4, 0x000007ff, 0x200); - tx0iqkok = false; - cal_retry++; - if (cal_retry == 10) - break; - } - } else { - tx0iqkok = false; - cal_retry++; - if (cal_retry == 10) - break; - } - } - } - if (k == 3) { - tx_x0[cal] = vdf_x[k-1]; - tx_y0[cal] = vdf_y[k-1]; - } - } else { - rtl_write_dword(rtlpriv, 0xc80, 0x18008c10);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ - rtl_write_dword(rtlpriv, 0xc84, 0x38008c10);/* RX_TONE_idx[9:0], RxK_Mask[29] */ - rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ - cal_retry = 0; - while (1) { - /* one shot */ - rtl_write_dword(rtlpriv, 0x980, 0xfa000000); - rtl_write_dword(rtlpriv, 0x980, 0xf8000000); - - mdelay(10); /* Delay 10ms */ - rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); - delay_count = 0; - while (1) { - iqk_ready = rtl_get_bbreg(hw, 0xd00, BIT(10)); - if ((~iqk_ready) || (delay_count > 20)) - break; - else{ - mdelay(1); - delay_count++; - } - } - - if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ - /* ============TXIQK Check============== */ - tx_fail = rtl_get_bbreg(hw, 0xd00, BIT(12)); - - if (~tx_fail) { - rtl_write_dword(rtlpriv, 0xcb8, 0x02000000); - tx_x0[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; - rtl_write_dword(rtlpriv, 0xcb8, 0x04000000); - tx_y0[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; - tx0iqkok = true; - break; - } else { - rtl_set_bbreg(hw, 0xccc, 0x000007ff, 0x0); - rtl_set_bbreg(hw, 0xcd4, 0x000007ff, 0x200); - tx0iqkok = false; - cal_retry++; - if (cal_retry == 10) - break; - } - } else { - tx0iqkok = false; - cal_retry++; - if (cal_retry == 10) - break; - } - } - } - - if (tx0iqkok == false) - break; /* TXK fail, Don't do RXK */ - - if (vdf_enable == 1) { - rtl_set_bbreg(hw, 0xce8, BIT(31), 0x0); /* TX VDF Disable */ - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "RXVDF Start\n"); - for (k = 0; k <= 2; k++) { - /* ====== RX mode TXK (RXK Step 1) ====== */ - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ - /* 1. TX RF Setting */ - rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x80000); - rtl_set_rfreg(hw, path, 0x30, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, path, 0x31, RFREG_OFFSET_MASK, 0x00029); - rtl_set_rfreg(hw, path, 0x32, RFREG_OFFSET_MASK, 0xd7ffb); - rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, temp_reg65); - rtl_set_rfreg(hw, path, 0x8f, RFREG_OFFSET_MASK, 0x8a001); - rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x00000); - - rtl_set_bbreg(hw, 0xcb8, 0xf, 0xd); - rtl_write_dword(rtlpriv, 0x978, 0x29002000);/* TX (X,Y) */ - rtl_write_dword(rtlpriv, 0x97c, 0xa9002000);/* RX (X,Y) */ - rtl_write_dword(rtlpriv, 0x984, 0x0046a910);/* [0]:AGC_en, [15]:idac_K_Mask */ - rtl_write_dword(rtlpriv, 0x90c, 0x00008000); - rtl_write_dword(rtlpriv, 0xb00, 0x03000100); - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ - switch (k) { - case 0: - { - rtl_write_dword(rtlpriv, 0xc80, 0x18008c38);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ - rtl_write_dword(rtlpriv, 0xc84, 0x38008c38);/* RX_TONE_idx[9:0], RxK_Mask[29] */ - rtl_set_bbreg(hw, 0xce8, BIT(30), 0x0); - } - break; - case 1: - { - rtl_write_dword(rtlpriv, 0xc80, 0x08008c38);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ - rtl_write_dword(rtlpriv, 0xc84, 0x28008c38);/* RX_TONE_idx[9:0], RxK_Mask[29] */ - rtl_set_bbreg(hw, 0xce8, BIT(30), 0x0); - } - break; - case 2: - { - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "VDF_Y[1] = %x;;;VDF_Y[0] = %x\n", - vdf_y[1]>>21 & 0x00007ff, vdf_y[0]>>21 & 0x00007ff); - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "VDF_X[1] = %x;;;VDF_X[0] = %x\n", - vdf_x[1]>>21 & 0x00007ff, vdf_x[0]>>21 & 0x00007ff); - rx_dt[cal] = (vdf_y[1]>>20)-(vdf_y[0]>>20); - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "Rx_dt = %d\n", rx_dt[cal]); - rx_dt[cal] = ((16*rx_dt[cal])*10000/13823); - rx_dt[cal] = (rx_dt[cal] >> 1)+(rx_dt[cal] & BIT(0)); - rtl_write_dword(rtlpriv, 0xc80, 0x18008c20);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ - rtl_write_dword(rtlpriv, 0xc84, 0x38008c20);/* RX_TONE_idx[9:0], RxK_Mask[29] */ - rtl_set_bbreg(hw, 0xce8, 0x00003fff, rx_dt[cal] & 0x00003fff); - } - break; - default: - break; - } - rtl_write_dword(rtlpriv, 0xc88, 0x821603e0); - rtl_write_dword(rtlpriv, 0xc8c, 0x68163e96); - rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ - cal_retry = 0; - while (1) { - /* one shot */ - rtl_write_dword(rtlpriv, 0x980, 0xfa000000); - rtl_write_dword(rtlpriv, 0x980, 0xf8000000); - - mdelay(10); /* Delay 10ms */ - rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); - delay_count = 0; - while (1) { - iqk_ready = rtl_get_bbreg(hw, 0xd00, BIT(10)); - if ((~iqk_ready) || (delay_count > 20)) - break; - else{ - mdelay(1); - delay_count++; - } - } - - if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ - /* ============TXIQK Check============== */ - tx_fail = rtl_get_bbreg(hw, 0xd00, BIT(12)); - - if (~tx_fail) { - rtl_write_dword(rtlpriv, 0xcb8, 0x02000000); - tx_x0_rxk[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; - rtl_write_dword(rtlpriv, 0xcb8, 0x04000000); - tx_y0_rxk[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; - tx0iqkok = true; - break; - } else{ - tx0iqkok = false; - cal_retry++; - if (cal_retry == 10) - break; - } - } else { - tx0iqkok = false; - cal_retry++; - if (cal_retry == 10) - break; - } - } - - if (tx0iqkok == false) { /* If RX mode TXK fail, then take TXK Result */ - tx_x0_rxk[cal] = tx_x0[cal]; - tx_y0_rxk[cal] = tx_y0[cal]; - tx0iqkok = true; - RT_TRACE(rtlpriv, - COMP_IQK, - DBG_LOUD, - "RXK Step 1 fail\n"); - } - - /* ====== RX IQK ====== */ - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ - /* 1. RX RF Setting */ - rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x80000); - rtl_set_rfreg(hw, path, 0x30, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, path, 0x31, RFREG_OFFSET_MASK, 0x0002f); - rtl_set_rfreg(hw, path, 0x32, RFREG_OFFSET_MASK, 0xfffbb); - rtl_set_rfreg(hw, path, 0x8f, RFREG_OFFSET_MASK, 0x88001); - rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, 0x931d8); - rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x00000); - - rtl_set_bbreg(hw, 0x978, 0x03FF8000, (tx_x0_rxk[cal])>>21&0x000007ff); - rtl_set_bbreg(hw, 0x978, 0x000007FF, (tx_y0_rxk[cal])>>21&0x000007ff); - rtl_set_bbreg(hw, 0x978, BIT(31), 0x1); - rtl_set_bbreg(hw, 0x97c, BIT(31), 0x0); - rtl_set_bbreg(hw, 0xcb8, 0xF, 0xe); - rtl_write_dword(rtlpriv, 0x90c, 0x00008000); - rtl_write_dword(rtlpriv, 0x984, 0x0046a911); - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ - rtl_set_bbreg(hw, 0xc80, BIT(29), 0x1); - rtl_set_bbreg(hw, 0xc84, BIT(29), 0x0); - rtl_write_dword(rtlpriv, 0xc88, 0x02140119); - - rtl_write_dword(rtlpriv, 0xc8c, 0x28160d00); /* pDM_Odm->SupportInterface == 1 */ - - if (k == 2) - rtl_set_bbreg(hw, 0xce8, BIT(30), 0x1); /* RX VDF Enable */ - rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ - - cal_retry = 0; - while (1) { - /* one shot */ - rtl_write_dword(rtlpriv, 0x980, 0xfa000000); - rtl_write_dword(rtlpriv, 0x980, 0xf8000000); - - mdelay(10); /* Delay 10ms */ - rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); - delay_count = 0; - while (1) { - iqk_ready = rtl_get_bbreg(hw, 0xd00, BIT(10)); - if ((~iqk_ready) || (delay_count > 20)) - break; - else{ - mdelay(1); - delay_count++; - } - } - - if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ - /* ============RXIQK Check============== */ - rx_fail = rtl_get_bbreg(hw, 0xd00, BIT(11)); - if (rx_fail == 0) { - rtl_write_dword(rtlpriv, 0xcb8, 0x06000000); - vdf_x[k] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; - rtl_write_dword(rtlpriv, 0xcb8, 0x08000000); - vdf_y[k] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; - rx0iqkok = true; - break; - } else { - rtl_set_bbreg(hw, 0xc10, 0x000003ff, 0x200>>1); - rtl_set_bbreg(hw, 0xc10, 0x03ff0000, 0x0>>1); - rx0iqkok = false; - cal_retry++; - if (cal_retry == 10) - break; - - } - } else{ - rx0iqkok = false; - cal_retry++; - if (cal_retry == 10) - break; - } - } - - } - if (k == 3) { - rx_x0[cal] = vdf_x[k-1]; - rx_y0[cal] = vdf_y[k-1]; - } - rtl_set_bbreg(hw, 0xce8, BIT(31), 0x1); /* TX VDF Enable */ - } - - else{ - /* ====== RX mode TXK (RXK Step 1) ====== */ - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ - /* 1. TX RF Setting */ - rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x80000); - rtl_set_rfreg(hw, path, 0x30, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, path, 0x31, RFREG_OFFSET_MASK, 0x00029); - rtl_set_rfreg(hw, path, 0x32, RFREG_OFFSET_MASK, 0xd7ffb); - rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, temp_reg65); - rtl_set_rfreg(hw, path, 0x8f, RFREG_OFFSET_MASK, 0x8a001); - rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x00000); - rtl_write_dword(rtlpriv, 0x90c, 0x00008000); - rtl_write_dword(rtlpriv, 0xb00, 0x03000100); - rtl_write_dword(rtlpriv, 0x984, 0x0046a910);/* [0]:AGC_en, [15]:idac_K_Mask */ - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ - rtl_write_dword(rtlpriv, 0xc80, 0x18008c10);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ - rtl_write_dword(rtlpriv, 0xc84, 0x38008c10);/* RX_TONE_idx[9:0], RxK_Mask[29] */ - rtl_write_dword(rtlpriv, 0xc88, 0x821603e0); - /* ODM_Write4Byte(pDM_Odm, 0xc8c, 0x68163e96); */ - rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ - cal_retry = 0; - while (1) { - /* one shot */ - rtl_write_dword(rtlpriv, 0x980, 0xfa000000); - rtl_write_dword(rtlpriv, 0x980, 0xf8000000); - - mdelay(10); /* Delay 10ms */ - rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); - delay_count = 0; - while (1) { - iqk_ready = rtl_get_bbreg(hw, 0xd00, BIT(10)); - if ((~iqk_ready) || (delay_count > 20)) - break; - else{ - mdelay(1); - delay_count++; - } - } - - if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ - /* ============TXIQK Check============== */ - tx_fail = rtl_get_bbreg(hw, 0xd00, BIT(12)); - - if (~tx_fail) { - rtl_write_dword(rtlpriv, 0xcb8, 0x02000000); - tx_x0_rxk[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; - rtl_write_dword(rtlpriv, 0xcb8, 0x04000000); - tx_y0_rxk[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; - tx0iqkok = true; - break; - } else { - tx0iqkok = false; - cal_retry++; - if (cal_retry == 10) - break; - } - } else{ - tx0iqkok = false; - cal_retry++; - if (cal_retry == 10) - break; - } - } - - if (tx0iqkok == false) { /* If RX mode TXK fail, then take TXK Result */ - tx_x0_rxk[cal] = tx_x0[cal]; - tx_y0_rxk[cal] = tx_y0[cal]; - tx0iqkok = true; - RT_TRACE(rtlpriv, COMP_IQK, - DBG_LOUD, "1"); - } - - /* ====== RX IQK ====== */ - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ - /* 1. RX RF Setting */ - rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x80000); - rtl_set_rfreg(hw, path, 0x30, RFREG_OFFSET_MASK, 0x30000); - rtl_set_rfreg(hw, path, 0x31, RFREG_OFFSET_MASK, 0x0002f); - rtl_set_rfreg(hw, path, 0x32, RFREG_OFFSET_MASK, 0xfffbb); - rtl_set_rfreg(hw, path, 0x8f, RFREG_OFFSET_MASK, 0x88001); - rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, 0x931d8); - rtl_set_rfreg(hw, path, 0xef, RFREG_OFFSET_MASK, 0x00000); - - rtl_set_bbreg(hw, 0x978, 0x03FF8000, (tx_x0_rxk[cal])>>21&0x000007ff); - rtl_set_bbreg(hw, 0x978, 0x000007FF, (tx_y0_rxk[cal])>>21&0x000007ff); - rtl_set_bbreg(hw, 0x978, BIT(31), 0x1); - rtl_set_bbreg(hw, 0x97c, BIT(31), 0x0); - /* ODM_SetBBReg(pDM_Odm, 0xcb8, 0xF, 0xe); */ - rtl_write_dword(rtlpriv, 0x90c, 0x00008000); - rtl_write_dword(rtlpriv, 0x984, 0x0046a911); - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ - rtl_write_dword(rtlpriv, 0xc80, 0x38008c10);/* TX_TONE_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ - rtl_write_dword(rtlpriv, 0xc84, 0x18008c10);/* RX_TONE_idx[9:0], RxK_Mask[29] */ - rtl_write_dword(rtlpriv, 0xc88, 0x02140119); - - rtl_write_dword(rtlpriv, 0xc8c, 0x28160d00); /*pDM_Odm->SupportInterface == 1*/ - - rtl_write_dword(rtlpriv, 0xcb8, 0x00100000);/* cb8[20] \B1N SI/PI \A8ϥ\CE\C5v\A4\C1\B5\B9 iqk_dpk module */ - - cal_retry = 0; - while (1) { - /* one shot */ - rtl_write_dword(rtlpriv, 0x980, 0xfa000000); - rtl_write_dword(rtlpriv, 0x980, 0xf8000000); - - mdelay(10); /* Delay 10ms */ - rtl_write_dword(rtlpriv, 0xcb8, 0x00000000); - delay_count = 0; - while (1) { - iqk_ready = rtl_get_bbreg(hw, 0xd00, BIT(10)); - if ((~iqk_ready) || (delay_count > 20)) - break; - else{ - mdelay(1); - delay_count++; - } - } - - if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ - /* ============RXIQK Check============== */ - rx_fail = rtl_get_bbreg(hw, 0xd00, BIT(11)); - if (rx_fail == 0) { - rtl_write_dword(rtlpriv, 0xcb8, 0x06000000); - rx_x0[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; - rtl_write_dword(rtlpriv, 0xcb8, 0x08000000); - rx_y0[cal] = rtl_get_bbreg(hw, 0xd00, 0x07ff0000)<<21; - rx0iqkok = true; - break; - } else{ - rtl_set_bbreg(hw, 0xc10, 0x000003ff, 0x200>>1); - rtl_set_bbreg(hw, 0xc10, 0x03ff0000, 0x0>>1); - rx0iqkok = false; - cal_retry++; - if (cal_retry == 10) - break; - - } - } else{ - rx0iqkok = false; - cal_retry++; - if (cal_retry == 10) - break; - } - } - } - - if (tx0iqkok) - tx_average++; - if (rx0iqkok) - rx_average++; - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ - rtl_set_rfreg(hw, path, 0x65, RFREG_OFFSET_MASK, temp_reg65); - break; - default: - break; - } - cal++; - } - - /* FillIQK Result */ - switch (path) { - case RF90_PATH_A: - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "========Path_A =======\n"); - if (tx_average == 0) - break; - - for (i = 0; i < tx_average; i++) { - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "TX_X0_RXK[%d] = %x ;; TX_Y0_RXK[%d] = %x\n", i, - (tx_x0_rxk[i])>>21&0x000007ff, i, - (tx_y0_rxk[i])>>21&0x000007ff); - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "TX_X0[%d] = %x ;; TX_Y0[%d] = %x\n", i, - (tx_x0[i])>>21&0x000007ff, i, - (tx_y0[i])>>21&0x000007ff); - } - for (i = 0; i < tx_average; i++) { - for (ii = i+1; ii < tx_average; ii++) { - dx = (tx_x0[i]>>21) - (tx_x0[ii]>>21); - if (dx < 3 && dx > -3) { - dy = (tx_y0[i]>>21) - (tx_y0[ii]>>21); - if (dy < 3 && dy > -3) { - tx_x = ((tx_x0[i]>>21) + (tx_x0[ii]>>21))/2; - tx_y = ((tx_y0[i]>>21) + (tx_y0[ii]>>21))/2; - tx_finish = 1; - break; - } - } - } - if (tx_finish == 1) - break; - } - - if (tx_finish == 1) - _rtl8821ae_iqk_tx_fill_iqc(hw, path, tx_x, tx_y); /* ? */ - else - _rtl8821ae_iqk_tx_fill_iqc(hw, path, 0x200, 0x0); - - if (rx_average == 0) - break; - - for (i = 0; i < rx_average; i++) - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "RX_X0[%d] = %x ;; RX_Y0[%d] = %x\n", i, - (rx_x0[i])>>21&0x000007ff, i, - (rx_y0[i])>>21&0x000007ff); - for (i = 0; i < rx_average; i++) { - for (ii = i+1; ii < rx_average; ii++) { - dx = (rx_x0[i]>>21) - (rx_x0[ii]>>21); - if (dx < 4 && dx > -4) { - dy = (rx_y0[i]>>21) - (rx_y0[ii]>>21); - if (dy < 4 && dy > -4) { - rx_x = ((rx_x0[i]>>21) + (rx_x0[ii]>>21))/2; - rx_y = ((rx_y0[i]>>21) + (rx_y0[ii]>>21))/2; - rx_finish = 1; - break; - } - } - } - if (rx_finish == 1) - break; - } - - if (rx_finish == 1) - _rtl8821ae_iqk_rx_fill_iqc(hw, path, rx_x, rx_y); - else - _rtl8821ae_iqk_rx_fill_iqc(hw, path, 0x200, 0x0); - break; - default: - break; - } -} - -static void _rtl8821ae_iqk_restore_rf(struct ieee80211_hw *hw, - enum radio_path path, - u32 *backup_rf_reg, - u32 *rf_backup, u32 rf_reg_num) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 i; - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ - for (i = 0; i < RF_REG_NUM; i++) - rtl_set_rfreg(hw, path, backup_rf_reg[i], RFREG_OFFSET_MASK, - rf_backup[i]); - - switch (path) { - case RF90_PATH_A: - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "RestoreRF Path A Success!!!!\n"); - break; - default: - break; - } -} - -static void _rtl8821ae_iqk_restore_afe(struct ieee80211_hw *hw, - u32 *afe_backup, u32 *backup_afe_reg, - u32 afe_num) -{ - u32 i; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ - /* Reload AFE Parameters */ - for (i = 0; i < afe_num; i++) - rtl_write_dword(rtlpriv, backup_afe_reg[i], afe_backup[i]); - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x1); /* [31] = 1 --> Page C1 */ - rtl_write_dword(rtlpriv, 0xc80, 0x0); - rtl_write_dword(rtlpriv, 0xc84, 0x0); - rtl_write_dword(rtlpriv, 0xc88, 0x0); - rtl_write_dword(rtlpriv, 0xc8c, 0x3c000000); - rtl_write_dword(rtlpriv, 0xc90, 0x00000080); - rtl_write_dword(rtlpriv, 0xc94, 0x00000000); - rtl_write_dword(rtlpriv, 0xcc4, 0x20040000); - rtl_write_dword(rtlpriv, 0xcc8, 0x20000000); - rtl_write_dword(rtlpriv, 0xcb8, 0x0); - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "RestoreAFE Success!!!!\n"); -} - -static void _rtl8821ae_iqk_restore_macbb(struct ieee80211_hw *hw, - u32 *macbb_backup, - u32 *backup_macbb_reg, - u32 macbb_num) -{ - u32 i; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_set_bbreg(hw, 0x82c, BIT(31), 0x0); /* [31] = 0 --> Page C */ - /* Reload MacBB Parameters */ - for (i = 0; i < macbb_num; i++) - rtl_write_dword(rtlpriv, backup_macbb_reg[i], macbb_backup[i]); - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, "RestoreMacBB Success!!!!\n"); -} - -#undef MACBB_REG_NUM -#undef AFE_REG_NUM -#undef RF_REG_NUM - -#define MACBB_REG_NUM 11 -#define AFE_REG_NUM 12 -#define RF_REG_NUM 3 - -static void _rtl8821ae_phy_iq_calibrate(struct ieee80211_hw *hw) -{ - u32 macbb_backup[MACBB_REG_NUM]; - u32 afe_backup[AFE_REG_NUM]; - u32 rfa_backup[RF_REG_NUM]; - u32 rfb_backup[RF_REG_NUM]; - u32 backup_macbb_reg[MACBB_REG_NUM] = { - 0xb00, 0x520, 0x550, 0x808, 0x90c, 0xc00, 0xc50, - 0xe00, 0xe50, 0x838, 0x82c - }; - u32 backup_afe_reg[AFE_REG_NUM] = { - 0xc5c, 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70, 0xc74, - 0xc78, 0xc7c, 0xc80, 0xc84, 0xcb8 - }; - u32 backup_rf_reg[RF_REG_NUM] = {0x65, 0x8f, 0x0}; - - _rtl8821ae_iqk_backup_macbb(hw, macbb_backup, backup_macbb_reg, - MACBB_REG_NUM); - _rtl8821ae_iqk_backup_afe(hw, afe_backup, backup_afe_reg, AFE_REG_NUM); - _rtl8821ae_iqk_backup_rf(hw, rfa_backup, rfb_backup, backup_rf_reg, - RF_REG_NUM); - - _rtl8821ae_iqk_configure_mac(hw); - _rtl8821ae_iqk_tx(hw, RF90_PATH_A); - _rtl8821ae_iqk_restore_rf(hw, RF90_PATH_A, backup_rf_reg, rfa_backup, - RF_REG_NUM); - - _rtl8821ae_iqk_restore_afe(hw, afe_backup, backup_afe_reg, AFE_REG_NUM); - _rtl8821ae_iqk_restore_macbb(hw, macbb_backup, backup_macbb_reg, - MACBB_REG_NUM); -} - -static void _rtl8821ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool main) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - /* struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); */ - /* struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); */ - RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); - - if (main) - rtl_set_bbreg(hw, RA_RFE_PINMUX + 4, BIT(29) | BIT(28), 0x1); - else - rtl_set_bbreg(hw, RA_RFE_PINMUX + 4, BIT(29) | BIT(28), 0x2); -} - -#undef IQK_ADDA_REG_NUM -#undef IQK_DELAY_TIME - -void rtl8812ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) -{ -} - -void rtl8812ae_do_iqk(struct ieee80211_hw *hw, u8 delta_thermal_index, - u8 thermal_value, u8 threshold) -{ - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - - rtldm->thermalvalue_iqk = thermal_value; - rtl8812ae_phy_iq_calibrate(hw, false); -} - -void rtl8821ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - if (!rtlphy->lck_inprogress) { - spin_lock(&rtlpriv->locks.iqk_lock); - rtlphy->lck_inprogress = true; - spin_unlock(&rtlpriv->locks.iqk_lock); - - _rtl8821ae_phy_iq_calibrate(hw); - - spin_lock(&rtlpriv->locks.iqk_lock); - rtlphy->lck_inprogress = false; - spin_unlock(&rtlpriv->locks.iqk_lock); - } -} - -void rtl8821ae_reset_iqk_result(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 i; - - RT_TRACE(rtlpriv, COMP_IQK, DBG_LOUD, - "rtl8812ae_dm_reset_iqk_result:: settings regs %d default regs %d\n", - (int)(sizeof(rtlphy->iqk_matrix) / - sizeof(struct iqk_matrix_regs)), - IQK_MATRIX_SETTINGS_NUM); - - for (i = 0; i < IQK_MATRIX_SETTINGS_NUM; i++) { - rtlphy->iqk_matrix[i].value[0][0] = 0x100; - rtlphy->iqk_matrix[i].value[0][2] = 0x100; - rtlphy->iqk_matrix[i].value[0][4] = 0x100; - rtlphy->iqk_matrix[i].value[0][6] = 0x100; - - rtlphy->iqk_matrix[i].value[0][1] = 0x0; - rtlphy->iqk_matrix[i].value[0][3] = 0x0; - rtlphy->iqk_matrix[i].value[0][5] = 0x0; - rtlphy->iqk_matrix[i].value[0][7] = 0x0; - - rtlphy->iqk_matrix[i].iqk_done = false; - } -} - -void rtl8821ae_do_iqk(struct ieee80211_hw *hw, u8 delta_thermal_index, - u8 thermal_value, u8 threshold) -{ - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - - rtl8821ae_reset_iqk_result(hw); - - rtldm->thermalvalue_iqk = thermal_value; - rtl8821ae_phy_iq_calibrate(hw, false); -} - -void rtl8821ae_phy_lc_calibrate(struct ieee80211_hw *hw) -{ -} - -void rtl8821ae_phy_ap_calibrate(struct ieee80211_hw *hw, char delta) -{ -} - -void rtl8821ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) -{ - _rtl8821ae_phy_set_rfpath_switch(hw, bmain); -} - -bool rtl8821ae_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - bool postprocessing = false; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "-->IO Cmd(%#x), set_io_inprogress(%d)\n", - iotype, rtlphy->set_io_inprogress); - do { - switch (iotype) { - case IO_CMD_RESUME_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Resume DM after scan.\n"); - postprocessing = true; - break; - case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: - case IO_CMD_PAUSE_BAND1_DM_BY_SCAN: - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "[IO CMD] Pause DM before scan.\n"); - postprocessing = true; - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - } while (false); - if (postprocessing && !rtlphy->set_io_inprogress) { - rtlphy->set_io_inprogress = true; - rtlphy->current_io_type = iotype; - } else { - return false; - } - rtl8821ae_phy_set_io(hw); - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); - return true; -} - -static void rtl8821ae_phy_set_io(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct dig_t *dm_digtable = &rtlpriv->dm_digtable; - struct rtl_phy *rtlphy = &rtlpriv->phy; - - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "--->Cmd(%#x), set_io_inprogress(%d)\n", - rtlphy->current_io_type, rtlphy->set_io_inprogress); - switch (rtlphy->current_io_type) { - case IO_CMD_RESUME_DM_BY_SCAN: - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) - _rtl8821ae_resume_tx_beacon(hw); - rtl8821ae_dm_write_dig(hw, rtlphy->initgain_backup.xaagccore1); - rtl8821ae_dm_write_cck_cca_thres(hw, - rtlphy->initgain_backup.cca); - break; - case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: - if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) - _rtl8821ae_stop_tx_beacon(hw); - rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; - rtl8821ae_dm_write_dig(hw, 0x17); - rtlphy->initgain_backup.cca = dm_digtable->cur_cck_cca_thres; - rtl8821ae_dm_write_cck_cca_thres(hw, 0x40); - break; - case IO_CMD_PAUSE_BAND1_DM_BY_SCAN: - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - break; - } - rtlphy->set_io_inprogress = false; - RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, - "(%#x)\n", rtlphy->current_io_type); -} - -static void rtl8821ae_phy_set_rf_on(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); - rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); - rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); -} - -static bool _rtl8821ae_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - bool bresult = true; - u8 i, queue_id; - struct rtl8192_tx_ring *ring = NULL; - - switch (rfpwr_state) { - case ERFON: - if ((ppsc->rfpwr_state == ERFOFF) && - RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { - bool rtstatus = false; - u32 initializecount = 0; - - do { - initializecount++; - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic enable\n"); - rtstatus = rtl_ps_enable_nic(hw); - } while (!rtstatus && (initializecount < 10)); - RT_CLEAR_PS_LEVEL(ppsc, - RT_RF_OFF_LEVL_HALT_NIC); - } else { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "Set ERFON sleeped:%d ms\n", - jiffies_to_msecs(jiffies - - ppsc-> - last_sleep_jiffies)); - ppsc->last_awake_jiffies = jiffies; - rtl8821ae_phy_set_rf_on(hw); - } - if (mac->link_state == MAC80211_LINKED) { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_LINK); - } else { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - } - break; - case ERFOFF: - for (queue_id = 0, i = 0; - queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { - ring = &pcipriv->dev.tx_ring[queue_id]; - if (queue_id == BEACON_QUEUE || - skb_queue_len(&ring->queue) == 0) { - queue_id++; - continue; - } else { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", - (i + 1), queue_id, - skb_queue_len(&ring->queue)); - - udelay(10); - i++; - } - if (i >= MAX_DOZE_WAITING_TIMES_9x) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, - "\n ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", - MAX_DOZE_WAITING_TIMES_9x, - queue_id, - skb_queue_len(&ring->queue)); - break; - } - } - - if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { - RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, - "IPS Set eRf nic disable\n"); - rtl_ps_disable_nic(hw); - RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); - } else { - if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_NO_LINK); - } else { - rtlpriv->cfg->ops->led_control(hw, - LED_CTL_POWER_OFF); - } - } - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "switch case not process\n"); - bresult = false; - break; - } - if (bresult) - ppsc->rfpwr_state = rfpwr_state; - return bresult; -} - -bool rtl8821ae_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state) -{ - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - - bool bresult = false; - - if (rfpwr_state == ppsc->rfpwr_state) - return bresult; - bresult = _rtl8821ae_phy_set_rf_power_state(hw, rfpwr_state); - return bresult; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.h b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.h deleted file mode 100644 index c411f0a95cc4..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.h +++ /dev/null @@ -1,259 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8821AE_PHY_H__ -#define __RTL8821AE_PHY_H__ - -/* MAX_TX_COUNT must always be set to 4, otherwise read - * efuse table sequence will be wrong. - */ -#define MAX_TX_COUNT 4 -#define TX_1S 0 -#define TX_2S 1 -#define TX_3S 2 -#define TX_4S 3 - -#define MAX_POWER_INDEX 0x3F - -#define MAX_PRECMD_CNT 16 -#define MAX_RFDEPENDCMD_CNT 16 -#define MAX_POSTCMD_CNT 16 - -#define MAX_DOZE_WAITING_TIMES_9x 64 - -#define RT_CANNOT_IO(hw) false -#define HIGHPOWER_RADIOA_ARRAYLEN 22 - -#define IQK_ADDA_REG_NUM 16 -#define IQK_BB_REG_NUM 9 -#define MAX_TOLERANCE 5 -#define IQK_DELAY_TIME 10 -#define index_mapping_NUM 15 - -#define APK_BB_REG_NUM 5 -#define APK_AFE_REG_NUM 16 -#define APK_CURVE_REG_NUM 4 -#define PATH_NUM 2 - -#define LOOP_LIMIT 5 -#define MAX_STALL_TIME 50 -#define AntennaDiversityValue 0x80 -#define MAX_TXPWR_IDX_NMODE_92S 63 -#define Reset_Cnt_Limit 3 - -#define IQK_ADDA_REG_NUM 16 -#define IQK_MAC_REG_NUM 4 - -#define RF6052_MAX_PATH 2 - -#define CT_OFFSET_MAC_ADDR 0X16 - -#define CT_OFFSET_CCK_TX_PWR_IDX 0x5A -#define CT_OFFSET_HT401S_TX_PWR_IDX 0x60 -#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF 0x66 -#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF 0x69 -#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF 0x6C - -#define CT_OFFSET_HT40_MAX_PWR_OFFSET 0x6F -#define CT_OFFSET_HT20_MAX_PWR_OFFSET 0x72 - -#define CT_OFFSET_CHANNEL_PLAH 0x75 -#define CT_OFFSET_THERMAL_METER 0x78 -#define CT_OFFSET_RF_OPTION 0x79 -#define CT_OFFSET_VERSION 0x7E -#define CT_OFFSET_CUSTOMER_ID 0x7F - -#define RTL8821AE_MAX_PATH_NUM 2 - -#define TARGET_CHNL_NUM_2G_5G_8812 59 - -enum swchnlcmd_id { - CMDID_END, - CMDID_SET_TXPOWEROWER_LEVEL, - CMDID_BBREGWRITE10, - CMDID_WRITEPORT_ULONG, - CMDID_WRITEPORT_USHORT, - CMDID_WRITEPORT_UCHAR, - CMDID_RF_WRITEREG, -}; - -struct swchnlcmd { - enum swchnlcmd_id cmdid; - u32 para1; - u32 para2; - u32 msdelay; -}; - -enum hw90_block_e { - HW90_BLOCK_MAC = 0, - HW90_BLOCK_PHY0 = 1, - HW90_BLOCK_PHY1 = 2, - HW90_BLOCK_RF = 3, - HW90_BLOCK_MAXIMUM = 4, -}; - -enum baseband_config_type { - BASEBAND_CONFIG_PHY_REG = 0, - BASEBAND_CONFIG_AGC_TAB = 1, -}; - -enum ra_offset_area { - RA_OFFSET_LEGACY_OFDM1, - RA_OFFSET_LEGACY_OFDM2, - RA_OFFSET_HT_OFDM1, - RA_OFFSET_HT_OFDM2, - RA_OFFSET_HT_OFDM3, - RA_OFFSET_HT_OFDM4, - RA_OFFSET_HT_CCK, -}; - -enum antenna_path { - ANTENNA_NONE, - ANTENNA_D, - ANTENNA_C, - ANTENNA_CD, - ANTENNA_B, - ANTENNA_BD, - ANTENNA_BC, - ANTENNA_BCD, - ANTENNA_A, - ANTENNA_AD, - ANTENNA_AC, - ANTENNA_ACD, - ANTENNA_AB, - ANTENNA_ABD, - ANTENNA_ABC, - ANTENNA_ABCD -}; - -struct r_antenna_select_ofdm { - u32 r_tx_antenna:4; - u32 r_ant_l:4; - u32 r_ant_non_ht:4; - u32 r_ant_ht1:4; - u32 r_ant_ht2:4; - u32 r_ant_ht_s1:4; - u32 r_ant_non_ht_s1:4; - u32 ofdm_txsc:2; - u32 reserved:2; -}; - -struct r_antenna_select_cck { - u8 r_cckrx_enable_2:2; - u8 r_cckrx_enable:2; - u8 r_ccktx_enable:4; -}; - -struct efuse_contents { - u8 mac_addr[ETH_ALEN]; - u8 cck_tx_power_idx[6]; - u8 ht40_1s_tx_power_idx[6]; - u8 ht40_2s_tx_power_idx_diff[3]; - u8 ht20_tx_power_idx_diff[3]; - u8 ofdm_tx_power_idx_diff[3]; - u8 ht40_max_power_offset[3]; - u8 ht20_max_power_offset[3]; - u8 channel_plan; - u8 thermal_meter; - u8 rf_option[5]; - u8 version; - u8 oem_id; - u8 regulatory; -}; - -struct tx_power_struct { - u8 cck[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 ht40_1s[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 ht40_2s[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 ht20_diff[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 legacy_ht_diff[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 legacy_ht_txpowerdiff; - u8 groupht20[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 groupht40[RTL8821AE_MAX_PATH_NUM][CHANNEL_MAX_NUMBER]; - u8 pwrgroup_cnt; - u32 mcs_original_offset[4][16]; -}; -enum _ANT_DIV_TYPE { - NO_ANTDIV = 0xFF, - CG_TRX_HW_ANTDIV = 0x01, - CGCS_RX_HW_ANTDIV = 0x02, - FIXED_HW_ANTDIV = 0x03, - CG_TRX_SMART_ANTDIV = 0x04, - CGCS_RX_SW_ANTDIV = 0x05, - -}; - -u32 rtl8821ae_phy_query_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask); -void rtl8821ae_phy_set_bb_reg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask, u32 data); -u32 rtl8821ae_phy_query_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask); -void rtl8821ae_phy_set_rf_reg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask, u32 data); -bool rtl8821ae_phy_mac_config(struct ieee80211_hw *hw); -bool rtl8821ae_phy_bb_config(struct ieee80211_hw *hw); -bool rtl8821ae_phy_rf_config(struct ieee80211_hw *hw); -void rtl8821ae_phy_switch_wirelessband(struct ieee80211_hw *hw, - u8 band); -void rtl8821ae_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); -void rtl8821ae_phy_get_txpower_level(struct ieee80211_hw *hw, - long *powerlevel); -void rtl8821ae_phy_set_txpower_level(struct ieee80211_hw *hw, - u8 channel); -void rtl8821ae_phy_scan_operation_backup(struct ieee80211_hw *hw, - u8 operation); -void rtl8821ae_phy_set_bw_mode_callback(struct ieee80211_hw *hw); -void rtl8821ae_phy_set_bw_mode(struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); -void rtl8821ae_phy_sw_chnl_callback(struct ieee80211_hw *hw); -u8 rtl8821ae_phy_sw_chnl(struct ieee80211_hw *hw); -void rtl8821ae_phy_iq_calibrate(struct ieee80211_hw *hw, - bool b_recovery); -void rtl8812ae_phy_iq_calibrate(struct ieee80211_hw *hw, - bool b_recovery); -void rtl8821ae_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); -void rtl8821ae_phy_lc_calibrate(struct ieee80211_hw *hw); -void rtl8821ae_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain); -bool rtl8812ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -bool rtl8821ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, - enum radio_path rfpath); -bool rtl8821ae_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); -bool rtl8821ae_phy_set_rf_power_state(struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); -u8 _rtl8812ae_get_right_chnl_place_for_iqk(u8 chnl); -void rtl8821ae_phy_set_txpower_level_by_path(struct ieee80211_hw *hw, - u8 channel, u8 path); -void rtl8812ae_do_iqk(struct ieee80211_hw *hw, u8 delta_thermal_index, - u8 thermal_value, u8 threshold); -void rtl8821ae_do_iqk(struct ieee80211_hw *hw, u8 delta_thermal_index, - u8 thermal_value, u8 threshold); -void rtl8821ae_reset_iqk_result(struct ieee80211_hw *hw); -u32 phy_get_tx_swing_8812A(struct ieee80211_hw *hw, u8 band, u8 rf_path); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.c b/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.c deleted file mode 100644 index 9ddf78a187dd..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.c +++ /dev/null @@ -1,182 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../pwrseqcmd.h" -#include "pwrseq.h" - -/* drivers should parse below arrays and do the corresponding actions */ -/* 3 Power on Array */ -struct wlan_pwr_cfg rtl8812_power_on_flow[RTL8812_TRANS_CARDEMU_TO_ACT_STEPS + - RTL8812_TRANS_END_STEPS] = { - RTL8812_TRANS_CARDEMU_TO_ACT - RTL8812_TRANS_END -}; - -/* 3Radio off GPIO Array */ -struct wlan_pwr_cfg rtl8812_radio_off_flow[RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8812_TRANS_END_STEPS] = { - RTL8812_TRANS_ACT_TO_CARDEMU - RTL8812_TRANS_END -}; - -/* 3Card Disable Array */ -struct wlan_pwr_cfg rtl8812_card_disable_flow[RTL8812_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8812_TRANS_CARDEMU_TO_PDN_STEPS - + RTL8812_TRANS_END_STEPS] = { - RTL8812_TRANS_ACT_TO_CARDEMU - RTL8812_TRANS_CARDEMU_TO_CARDDIS - RTL8812_TRANS_END -}; - -/* 3 Card Enable Array */ -struct wlan_pwr_cfg rtl8812_card_enable_flow[RTL8812_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8812_TRANS_CARDEMU_TO_PDN_STEPS - + RTL8812_TRANS_END_STEPS] = { - RTL8812_TRANS_CARDDIS_TO_CARDEMU - RTL8812_TRANS_CARDEMU_TO_ACT - RTL8812_TRANS_END -}; - -/* 3Suspend Array */ -struct wlan_pwr_cfg rtl8812_suspend_flow[RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8812_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8812_TRANS_END_STEPS] = { - RTL8812_TRANS_ACT_TO_CARDEMU - RTL8812_TRANS_CARDEMU_TO_SUS - RTL8812_TRANS_END -}; - -/* 3 Resume Array */ -struct wlan_pwr_cfg rtl8812_resume_flow[RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8812_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8812_TRANS_END_STEPS] = { - RTL8812_TRANS_SUS_TO_CARDEMU - RTL8812_TRANS_CARDEMU_TO_ACT - RTL8812_TRANS_END -}; - -/* 3HWPDN Array */ -struct wlan_pwr_cfg rtl8812_hwpdn_flow[RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8812_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8812_TRANS_END_STEPS] = { - RTL8812_TRANS_ACT_TO_CARDEMU - RTL8812_TRANS_CARDEMU_TO_PDN - RTL8812_TRANS_END -}; - -/* 3 Enter LPS */ -struct wlan_pwr_cfg rtl8812_enter_lps_flow[RTL8812_TRANS_ACT_TO_LPS_STEPS + - RTL8812_TRANS_END_STEPS] = { - /* FW behavior */ - RTL8812_TRANS_ACT_TO_LPS - RTL8812_TRANS_END -}; - -/* 3 Leave LPS */ -struct wlan_pwr_cfg rtl8812_leave_lps_flow[RTL8812_TRANS_LPS_TO_ACT_STEPS + - RTL8812_TRANS_END_STEPS] = { - /* FW behavior */ - RTL8812_TRANS_LPS_TO_ACT - RTL8812_TRANS_END -}; - -/* drivers should parse below arrays and do the corresponding actions */ -/*3 Power on Array*/ -struct wlan_pwr_cfg rtl8821A_power_on_flow[RTL8821A_TRANS_CARDEMU_TO_ACT_STEPS - + RTL8821A_TRANS_END_STEPS] = { - RTL8821A_TRANS_CARDEMU_TO_ACT - RTL8821A_TRANS_END -}; - -/*3Radio off GPIO Array */ -struct wlan_pwr_cfg rtl8821A_radio_off_flow[RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8821A_TRANS_END_STEPS] = { - RTL8821A_TRANS_ACT_TO_CARDEMU - RTL8821A_TRANS_END -}; - -/*3Card Disable Array*/ -struct wlan_pwr_cfg rtl8821A_card_disable_flow - [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8821A_TRANS_CARDEMU_TO_PDN_STEPS - + RTL8821A_TRANS_END_STEPS] = { - RTL8821A_TRANS_ACT_TO_CARDEMU - RTL8821A_TRANS_CARDEMU_TO_CARDDIS - RTL8821A_TRANS_END -}; - -/*3 Card Enable Array*/ -/*RTL8821A_TRANS_CARDEMU_TO_PDN_STEPS*/ -struct wlan_pwr_cfg rtl8821A_card_enable_flow - [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8821A_TRANS_CARDEMU_TO_ACT_STEPS - + RTL8821A_TRANS_END_STEPS] = { - RTL8821A_TRANS_CARDDIS_TO_CARDEMU - RTL8821A_TRANS_CARDEMU_TO_ACT - RTL8821A_TRANS_END -}; - -/*3Suspend Array*/ -struct wlan_pwr_cfg rtl8821A_suspend_flow[RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8821A_TRANS_CARDEMU_TO_SUS_STEPS - + RTL8821A_TRANS_END_STEPS] = { - RTL8821A_TRANS_ACT_TO_CARDEMU - RTL8821A_TRANS_CARDEMU_TO_SUS - RTL8821A_TRANS_END -}; - -/*3 Resume Array*/ -struct wlan_pwr_cfg rtl8821A_resume_flow[RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8821A_TRANS_CARDEMU_TO_SUS_STEPS - + RTL8821A_TRANS_END_STEPS] = { - RTL8821A_TRANS_SUS_TO_CARDEMU - RTL8821A_TRANS_CARDEMU_TO_ACT - RTL8821A_TRANS_END -}; - -/*3HWPDN Array*/ -struct wlan_pwr_cfg rtl8821A_hwpdn_flow[RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS - + RTL8821A_TRANS_CARDEMU_TO_PDN_STEPS - + RTL8821A_TRANS_END_STEPS] = { - RTL8821A_TRANS_ACT_TO_CARDEMU - RTL8821A_TRANS_CARDEMU_TO_PDN - RTL8821A_TRANS_END -}; - -/*3 Enter LPS */ -struct wlan_pwr_cfg rtl8821A_enter_lps_flow[RTL8821A_TRANS_ACT_TO_LPS_STEPS - + RTL8821A_TRANS_END_STEPS] = { - /*FW behavior*/ - RTL8821A_TRANS_ACT_TO_LPS - RTL8821A_TRANS_END -}; - -/*3 Leave LPS */ -struct wlan_pwr_cfg rtl8821A_leave_lps_flow[RTL8821A_TRANS_LPS_TO_ACT_STEPS - + RTL8821A_TRANS_END_STEPS] = { - /*FW behavior*/ - RTL8821A_TRANS_LPS_TO_ACT - RTL8821A_TRANS_END -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.h b/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.h deleted file mode 100644 index 36b3e91d996e..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/pwrseq.h +++ /dev/null @@ -1,738 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8821AE_PWRSEQ_H__ -#define __RTL8821AE_PWRSEQ_H__ - -#include "../pwrseqcmd.h" -#include "../btcoexist/halbt_precomp.h" - -#define RTL8812_TRANS_CARDEMU_TO_ACT_STEPS 15 -#define RTL8812_TRANS_ACT_TO_CARDEMU_STEPS 15 -#define RTL8812_TRANS_CARDEMU_TO_SUS_STEPS 15 -#define RTL8812_TRANS_SUS_TO_CARDEMU_STEPS 15 -#define RTL8812_TRANS_CARDEMU_TO_PDN_STEPS 25 -#define RTL8812_TRANS_PDN_TO_CARDEMU_STEPS 15 -#define RTL8812_TRANS_ACT_TO_LPS_STEPS 15 -#define RTL8812_TRANS_LPS_TO_ACT_STEPS 15 -#define RTL8812_TRANS_END_STEPS 1 - -/* The following macros have the following format: - * { offset, cut_msk, fab_msk|interface_msk, base|cmd, msk, value - * comments }, - */ -#define RTL8812_TRANS_CARDEMU_TO_ACT \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT2, 0 \ - /* disable SW LPS 0x04[10]=0*/}, \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, BIT1 \ - /* wait till 0x04[17] = 1 power ready*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0 \ - /* disable HWPDN 0x04[15]=0*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3, 0 \ - /* disable WL suspend*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ - /* polling until return 0*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT0, 0}, - -#define RTL8812_TRANS_ACT_TO_CARDEMU \ - {0x0c00, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x04 \ - /* 0xc00[7:0] = 4 turn off 3-wire */}, \ - {0x0e00, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x04 \ - /* 0xe00[7:0] = 4 turn off 3-wire */}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ - /* 0x2[0] = 0 RESET BB, CLOSE RF */}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US \ - /*Delay 1us*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ - /* Whole BB is reset*/}, \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x2A \ - /* 0x07[7:0] = 0x28 sps pwm mode 0x2a for BT coex*/}, \ - {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x02, 0 \ - /*0x8[1] = 0 ANA clk =500k */}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ - /*0x04[9] = 1 turn off MAC by HW state machine*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, 0 \ - /*wait till 0x04[9] = 0 polling until return 0 to disable*/}, - -#define RTL8812_TRANS_CARDEMU_TO_SUS \ - {0x0042, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xF0, 0xc0}, \ - {0x0042, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xF0, 0xE0}, \ - {0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x07 \ - /* gpio11 input mode, gpio10~8 output mode */}, \ - {0x0045, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ - /* gpio 0~7 output same value as input ?? */}, \ - {0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xff \ - /* gpio0~7 output mode */}, \ - {0x0047, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ - /* 0x47[7:0] = 00 gpio mode */}, \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ - /* suspend option all off */}, \ - {0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x80, BIT7 \ - /*0x14[7] = 1 turn on ZCD */}, \ - {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x01, BIT0 \ - /* 0x15[0] =1 trun on ZCD */}, \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x10, BIT4 \ - /*0x23[4] = 1 hpon LDO sleep mode */}, \ - {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x02, 0 \ - /*0x8[1] = 0 ANA clk =500k */}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3, BIT3 \ - /*0x04[11] = 2b'11 enable WL suspend for PCIe*/}, - -#define RTL8812_TRANS_SUS_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3, 0 \ - /*0x04[11] = 2b'01enable WL suspend*/}, \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x10, 0 \ - /*0x23[4] = 0 hpon LDO sleep mode leave */}, \ - {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x01, 0 \ - /* 0x15[0] =0 trun off ZCD */}, \ - {0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x80, 0 \ - /*0x14[7] = 0 turn off ZCD */}, \ - {0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ - /* gpio0~7 input mode */}, \ - {0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ - /* gpio11 input mode, gpio10~8 input mode */}, - -#define RTL8812_TRANS_CARDEMU_TO_CARDDIS \ - {0x0003, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT2, 0 \ - /*0x03[2] = 0, reset 8051*/}, \ - {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x05 \ - /*0x80=05h if reload fw, fill the default value of host_CPU handshake field*/}, \ - {0x0042, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xF0, 0xcc}, \ - {0x0042, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xF0, 0xEC}, \ - {0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x07 \ - /* gpio11 input mode, gpio10~8 output mode */}, \ - {0x0045, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ - /* gpio 0~7 output same value as input ?? */}, \ - {0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xff \ - /* gpio0~7 output mode */}, \ - {0x0047, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ - /* 0x47[7:0] = 00 gpio mode */}, \ - {0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x80, BIT7 \ - /*0x14[7] = 1 turn on ZCD */}, \ - {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x01, BIT0 \ - /* 0x15[0] =1 trun on ZCD */}, \ - {0x0012, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x01, 0 \ - /*0x12[0] = 0 force PFM mode */}, \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x10, BIT4 \ - /*0x23[4] = 1 hpon LDO sleep mode */}, \ - {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x02, 0 \ - /*0x8[1] = 0 ANA clk =500k */}, \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20 \ - /*0x07=0x20 , SOP option to disable BG/MB*/}, \ - {0x001f, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ - /*0x01f[1]=0 , disable RFC_0 control REG_RF_CTRL_8812 */}, \ - {0x0076, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ - /*0x076[1]=0 , disable RFC_1 control REG_OPT_CTRL_8812 +2 */}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3, BIT3 \ - /*0x04[11] = 2b'01 enable WL suspend*/}, - -#define RTL8812_TRANS_CARDDIS_TO_CARDEMU \ - {0x0012, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ - /*0x12[0] = 1 force PWM mode */}, \ - {0x0014, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x80, 0 \ - /*0x14[7] = 0 turn off ZCD */}, \ - {0x0015, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x01, 0 \ - /* 0x15[0] =0 trun off ZCD */}, \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0x10, 0 \ - /*0x23[4] = 0 hpon LDO leave sleep mode */}, \ - {0x0046, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ - /* gpio0~7 input mode */}, \ - {0x0043, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ - /* gpio11 input mode, gpio10~8 input mode */}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT2, 0 \ - /*0x04[10] = 0, enable SW LPS PCIE only*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3, 0 \ - /*0x04[11] = 2b'01enable WL suspend*/}, \ - {0x0003, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT2, BIT2 \ - /*0x03[2] = 1, enable 8051*/}, \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ - /*PCIe DMA start*/}, - -#define RTL8812_TRANS_CARDEMU_TO_PDN \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, BIT7 \ - /* 0x04[15] = 1*/}, - -#define RTL8812_TRANS_PDN_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0 \ - /* 0x04[15] = 0*/}, - -#define RTL8812_TRANS_ACT_TO_LPS \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF \ - /*PCIe DMA stop*/}, \ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x7F \ - /*Tx Pause*/}, \ - {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ - /*Should be zero if no packet is transmitting*/}, \ - {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ - /*Should be zero if no packet is transmitting*/}, \ - {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ - /*Should be zero if no packet is transmitting*/}, \ - {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ - /*Should be zero if no packet is transmitting*/}, \ - {0x0c00, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x04 \ - /* 0xc00[7:0] = 4 turn off 3-wire */}, \ - {0x0e00, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x04 \ - /* 0xe00[7:0] = 4 turn off 3-wire */}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ - /*CCK and OFDM are disabled,and clock are gated,and RF closed*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US \ - /*Delay 1us*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ - /* Whole BB is reset*/}, \ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x03 \ - /*Reset MAC TRX*/}, \ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ - /*check if removed later*/}, \ - {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, BIT5 \ - /*Respond TxOK to scheduler*/}, - -#define RTL8812_TRANS_LPS_TO_ACT \ - {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84 \ - /*SDIO RPWM*/}, \ - {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84 \ - /*USB RPWM*/}, \ - {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84 \ - /*PCIe RPWM*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS \ - /*Delay*/}, \ - {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0 \ - /*. 0x08[4] = 0 switch TSF to 40M*/}, \ - {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT7, 0 \ - /*Polling 0x109[7]=0 TSF in 40M*/}, \ - {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT6|BIT7, 0 \ - /*. 0x29[7:6] = 2b'00 enable BB clock*/}, \ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ - /*. 0x101[1] = 1*/}, \ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF \ - /*. 0x100[7:0] = 0xFF enable WMAC TRX*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1|BIT0, BIT1|BIT0 \ - /*. 0x02[1:0] = 2b'11 enable BB macro*/}, \ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ - /*. 0x522 = 0*/}, - -#define RTL8812_TRANS_END \ - {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ - 0, PWR_CMD_END, 0, 0}, - -extern struct wlan_pwr_cfg rtl8812_power_on_flow - [RTL8812_TRANS_CARDEMU_TO_ACT_STEPS + - RTL8812_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8812_radio_off_flow - [RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8812_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8812_card_disable_flow - [RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8812_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8812_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8812_card_enable_flow - [RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8812_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8812_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8812_suspend_flow - [RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8812_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8812_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8812_resume_flow - [RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8812_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8812_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8812_hwpdn_flow - [RTL8812_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8812_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8812_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8812_enter_lps_flow - [RTL8812_TRANS_ACT_TO_LPS_STEPS + - RTL8812_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8812_leave_lps_flow - [RTL8812_TRANS_LPS_TO_ACT_STEPS + - RTL8812_TRANS_END_STEPS]; - -/* Check document WM-20130516-JackieLau-RTL8821A_Power_Architecture-R10.vsd - * There are 6 HW Power States: - * 0: POFF--Power Off - * 1: PDN--Power Down - * 2: CARDEMU--Card Emulation - * 3: ACT--Active Mode - * 4: LPS--Low Power State - * 5: SUS--Suspend - * - * The transision from different states are defined below - * TRANS_CARDEMU_TO_ACT - * TRANS_ACT_TO_CARDEMU - * TRANS_CARDEMU_TO_SUS - * TRANS_SUS_TO_CARDEMU - * TRANS_CARDEMU_TO_PDN - * TRANS_ACT_TO_LPS - * TRANS_LPS_TO_ACT - * - * TRANS_END - */ -#define RTL8821A_TRANS_CARDEMU_TO_ACT_STEPS 25 -#define RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS 15 -#define RTL8821A_TRANS_CARDEMU_TO_SUS_STEPS 15 -#define RTL8821A_TRANS_SUS_TO_CARDEMU_STEPS 15 -#define RTL8821A_TRANS_CARDDIS_TO_CARDEMU_STEPS 15 -#define RTL8821A_TRANS_CARDEMU_TO_PDN_STEPS 15 -#define RTL8821A_TRANS_PDN_TO_CARDEMU_STEPS 15 -#define RTL8821A_TRANS_ACT_TO_LPS_STEPS 15 -#define RTL8821A_TRANS_LPS_TO_ACT_STEPS 15 -#define RTL8821A_TRANS_END_STEPS 1 - -#define RTL8821A_TRANS_CARDEMU_TO_ACT \ - {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ - /*0x20[0] = 1b'1 enable LDOA12 MACRO block for all interface*/}, \ - {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0 \ - /*0x67[0] = 0 to disable BT_GPS_SEL pins*/}, \ - {0x0001, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_DELAY, 1, PWRSEQ_DELAY_MS \ - /*Delay 1ms*/}, \ - {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, 0 \ - /*0x00[5] = 1b'0 release analog Ips to digital ,1:isolation*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT4|BIT3|BIT2), 0 \ - /* disable SW LPS 0x04[10]=0 and WLSUS_EN 0x04[12:11]=0*/}, \ - {0x0075, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0 , BIT0 \ - /* Disable USB suspend */}, \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, BIT1 \ - /* wait till 0x04[17] = 1 power ready*/}, \ - {0x0075, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0 , 0 \ - /* Enable USB suspend */}, \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ - /* release WLON reset 0x04[16]=1*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0 \ - /* disable HWPDN 0x04[15]=0*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT4|BIT3), 0 \ - /* disable WL suspend*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ - /* polling until return 0*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT0, 0 \ - /**/}, \ - {0x004F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ - /*0x4C[24] = 0x4F[0] = 1, switch DPDT_SEL_P output from WL BB */},\ - {0x0067, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, (BIT5|BIT4), (BIT5|BIT4) \ - /*0x66[13] = 0x67[5] = 1, switch for PAPE_G/PAPE_A \ - from WL BB ; 0x66[12] = 0x67[4] = 1, switch LNAON from WL BB */},\ - {0x0025, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT6, 0 \ - /*anapar_mac<118> , 0x25[6]=0 by wlan single function*/},\ - {0x0049, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ - /*Enable falling edge triggering interrupt*/},\ - {0x0063, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ - /*Enable GPIO9 interrupt mode*/},\ - {0x0062, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ - /*Enable GPIO9 input mode*/},\ - {0x0058, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, BIT0 \ - /*Enable HSISR GPIO[C:0] interrupt*/},\ - {0x005A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ - /*Enable HSISR GPIO9 interrupt*/},\ - {0x007A, PWR_CUT_TESTCHIP_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x3A \ - /*0x7A = 0x3A start BT*/},\ - {0x002E, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF , 0x82 \ - /* 0x2C[23:12]=0x820 ; XTAL trim */}, \ - {0x0010, PWR_CUT_A_MSK , PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT6 , BIT6 \ - /* 0x10[6]=1 */}, - -#define RTL8821A_TRANS_ACT_TO_CARDEMU \ - {0x001F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ - /*0x1F[7:0] = 0 turn off RF*/}, \ - {0x004F, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ - /*0x4C[24] = 0x4F[0] = 0, switch DPDT_SEL_P output from \ - register 0x65[2] */},\ - {0x0049, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ - /*Enable rising edge triggering interrupt*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ - /*0x04[9] = 1 turn off MAC by HW state machine*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT1, 0 \ - /*wait till 0x04[9] = 0 polling until return 0 to disable*/}, \ - {0x0000, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, BIT5 \ - /*0x00[5] = 1b'1 analog Ips to digital ,1:isolation*/}, \ - {0x0020, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ - /*0x20[0] = 1b'0 disable LDOA12 MACRO block*/}, - -#define RTL8821A_TRANS_CARDEMU_TO_SUS \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4|BIT3, (BIT4|BIT3) \ - /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, BIT3 \ - /*0x04[12:11] = 2b'01 enable WL suspend*/}, \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4 \ - /*0x23[4] = 1b'1 12H LDO enter sleep mode*/}, \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20 \ - /*0x07[7:0] = 0x20 SDIO SOP option to disable BG/MB/ACK/SWR*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, BIT3|BIT4 \ - /*0x04[12:11] = 2b'11 enable WL suspend for PCIe*/}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, BIT0 \ - /*Set SDIO suspend local register*/}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, 0 \ - /*wait power state to suspend*/}, - -#define RTL8821A_TRANS_SUS_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3 | BIT7, 0 \ - /*clear suspend enable and power down enable*/}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, 0 \ - /*Set SDIO suspend local register*/}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, BIT1 \ - /*wait power state to suspend*/},\ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0 \ - /*0x23[4] = 1b'0 12H LDO enter normal mode*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, 0 \ - /*0x04[12:11] = 2b'01enable WL suspend*/}, - -#define RTL8821A_TRANS_CARDEMU_TO_CARDDIS \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20 \ - /*0x07=0x20 , SOP option to disable BG/MB*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_USB_MSK|PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, BIT3 \ - /*0x04[12:11] = 2b'01 enable WL suspend*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT2, BIT2 \ - /*0x04[10] = 1, enable SW LPS*/}, \ - {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 1 \ - /*0x48[16] = 1 to enable GPIO9 as EXT WAKEUP*/}, \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4 \ - /*0x23[4] = 1b'1 12H LDO enter sleep mode*/}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, BIT0 \ - /*Set SDIO suspend local register*/}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, 0 \ - /*wait power state to suspend*/}, - -#define RTL8821A_TRANS_CARDDIS_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3 | BIT7, 0 \ - /*clear suspend enable and power down enable*/}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, BIT0, 0 \ - /*Set SDIO suspend local register*/}, \ - {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT1, BIT1 \ - /*wait power state to suspend*/},\ - {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ - /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/}, \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, 0 \ - /*0x04[12:11] = 2b'01enable WL suspend*/},\ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0 \ - /*0x23[4] = 1b'0 12H LDO enter normal mode*/}, \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ - /*PCIe DMA start*/}, - -#define RTL8821A_TRANS_CARDEMU_TO_PDN \ - {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, BIT4 \ - /*0x23[4] = 1b'1 12H LDO enter sleep mode*/}, \ - {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ - PWR_INTF_SDIO_MSK|PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x20 \ - /*0x07[7:0] = 0x20 SOP option to disable BG/MB/ACK/SWR*/}, \ - {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ - /* 0x04[16] = 0*/},\ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, BIT7 \ - /* 0x04[15] = 1*/}, - -#define RTL8821A_TRANS_PDN_TO_CARDEMU \ - {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT7, 0 \ - /* 0x04[15] = 0*/}, - -#define RTL8821A_TRANS_ACT_TO_LPS \ - {0x0301, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF \ - /*PCIe DMA stop*/}, \ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF \ - /*Tx Pause*/}, \ - {0x05F8, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ - /*Should be zero if no packet is transmitting*/}, \ - {0x05F9, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ - /*Should be zero if no packet is transmitting*/}, \ - {0x05FA, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ - /*Should be zero if no packet is transmitting*/}, \ - {0x05FB, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, 0xFF, 0 \ - /*Should be zero if no packet is transmitting*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT0, 0 \ - /*CCK and OFDM are disabled,and clock are gated*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_US \ - /*Delay 1us*/}, \ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ - /*Whole BB is reset*/}, \ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x03 \ - /*Reset MAC TRX*/}, \ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, 0 \ - /*check if removed later*/}, \ - {0x0093, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x00 \ - /*When driver enter Sus/ Disable, enable LOP for BT*/}, \ - {0x0553, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT5, BIT5 \ - /*Respond TxOK to scheduler*/}, - -#define RTL8821A_TRANS_LPS_TO_ACT \ - {0x0080, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ - PWR_BASEADDR_SDIO, PWR_CMD_WRITE, 0xFF, 0x84 \ - /*SDIO RPWM*/},\ - {0xFE58, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84 \ - /*USB RPWM*/},\ - {0x0361, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_PCI_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0x84 \ - /*PCIe RPWM*/},\ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_DELAY, 0, PWRSEQ_DELAY_MS \ - /*Delay*/},\ - {0x0008, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0 \ - /*. 0x08[4] = 0 switch TSF to 40M*/},\ - {0x0109, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_POLLING, BIT7, 0 \ - /*Polling 0x109[7]=0 TSF in 40M*/},\ - {0x0029, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT6|BIT7, 0 \ - /*. 0x29[7:6] = 2b'00 enable BB clock*/},\ - {0x0101, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1, BIT1 \ - /*. 0x101[1] = 1*/},\ - {0x0100, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0xFF \ - /*. 0x100[7:0] = 0xFF enable WMAC TRX*/},\ - {0x0002, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT1|BIT0, BIT1|BIT0 \ - /*. 0x02[1:0] = 2b'11 enable BB macro*/},\ - {0x0522, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - PWR_BASEADDR_MAC, PWR_CMD_WRITE, 0xFF, 0 \ - /*. 0x522 = 0*/}, - -#define RTL8821A_TRANS_END \ - {0xFFFF, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ - 0, PWR_CMD_END, 0, 0}, - -extern struct wlan_pwr_cfg rtl8821A_power_on_flow - [RTL8821A_TRANS_CARDEMU_TO_ACT_STEPS + - RTL8821A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8821A_radio_off_flow - [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8821A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8821A_card_disable_flow - [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8821A_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8821A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8821A_card_enable_flow - [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8821A_TRANS_CARDEMU_TO_ACT_STEPS + - RTL8821A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8821A_suspend_flow - [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8821A_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8821A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8821A_resume_flow - [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8821A_TRANS_CARDEMU_TO_SUS_STEPS + - RTL8821A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8821A_hwpdn_flow - [RTL8821A_TRANS_ACT_TO_CARDEMU_STEPS + - RTL8821A_TRANS_CARDEMU_TO_PDN_STEPS + - RTL8821A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8821A_enter_lps_flow - [RTL8821A_TRANS_ACT_TO_LPS_STEPS + - RTL8821A_TRANS_END_STEPS]; -extern struct wlan_pwr_cfg rtl8821A_leave_lps_flow - [RTL8821A_TRANS_LPS_TO_ACT_STEPS + - RTL8821A_TRANS_END_STEPS]; - -/*RTL8812 Power Configuration CMDs for PCIe interface*/ -#define RTL8812_NIC_PWR_ON_FLOW rtl8812_power_on_flow -#define RTL8812_NIC_RF_OFF_FLOW rtl8812_radio_off_flow -#define RTL8812_NIC_DISABLE_FLOW rtl8812_card_disable_flow -#define RTL8812_NIC_ENABLE_FLOW rtl8812_card_enable_flow -#define RTL8812_NIC_SUSPEND_FLOW rtl8812_suspend_flow -#define RTL8812_NIC_RESUME_FLOW rtl8812_resume_flow -#define RTL8812_NIC_PDN_FLOW rtl8812_hwpdn_flow -#define RTL8812_NIC_LPS_ENTER_FLOW rtl8812_enter_lps_flow -#define RTL8812_NIC_LPS_LEAVE_FLOW rtl8812_leave_lps_flow - -/* RTL8821 Power Configuration CMDs for PCIe interface */ -#define RTL8821A_NIC_PWR_ON_FLOW rtl8821A_power_on_flow -#define RTL8821A_NIC_RF_OFF_FLOW rtl8821A_radio_off_flow -#define RTL8821A_NIC_DISABLE_FLOW rtl8821A_card_disable_flow -#define RTL8821A_NIC_ENABLE_FLOW rtl8821A_card_enable_flow -#define RTL8821A_NIC_SUSPEND_FLOW rtl8821A_suspend_flow -#define RTL8821A_NIC_RESUME_FLOW rtl8821A_resume_flow -#define RTL8821A_NIC_PDN_FLOW rtl8821A_hwpdn_flow -#define RTL8821A_NIC_LPS_ENTER_FLOW rtl8821A_enter_lps_flow -#define RTL8821A_NIC_LPS_LEAVE_FLOW rtl8821A_leave_lps_flow - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/reg.h b/drivers/net/wireless/rtlwifi/rtl8821ae/reg.h deleted file mode 100644 index 1d6110f9c1fb..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/reg.h +++ /dev/null @@ -1,2465 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8821AE_REG_H__ -#define __RTL8821AE_REG_H__ - -#define TXPKT_BUF_SELECT 0x69 -#define RXPKT_BUF_SELECT 0xA5 -#define DISABLE_TRXPKT_BUF_ACCESS 0x0 - -#define REG_SYS_ISO_CTRL 0x0000 -#define REG_SYS_FUNC_EN 0x0002 -#define REG_APS_FSMCO 0x0004 -#define REG_SYS_CLKR 0x0008 -#define REG_9346CR 0x000A -#define REG_EE_VPD 0x000C -#define REG_AFE_MISC 0x0010 -#define REG_SPS0_CTRL 0x0011 -#define REG_SPS_OCP_CFG 0x0018 -#define REG_RSV_CTRL 0x001C -#define REG_RF_CTRL 0x001F -#define REG_LDOA15_CTRL 0x0020 -#define REG_LDOV12D_CTRL 0x0021 -#define REG_LDOHCI12_CTRL 0x0022 -#define REG_LPLDO_CTRL 0x0023 -#define REG_AFE_XTAL_CTRL 0x0024 - /* 1.5v for 8188EE test chip, 1.4v for MP chip */ -#define REG_AFE_LDO_CTRL 0x0027 -#define REG_AFE_PLL_CTRL 0x0028 -#define REG_MAC_PHY_CTRL 0x002c -#define REG_EFUSE_CTRL 0x0030 -#define REG_EFUSE_TEST 0x0034 -#define REG_PWR_DATA 0x0038 -#define REG_CAL_TIMER 0x003C -#define REG_ACLK_MON 0x003E -#define REG_GPIO_MUXCFG 0x0040 -#define REG_GPIO_IO_SEL 0x0042 -#define REG_MAC_PINMUX_CFG 0x0043 -#define REG_GPIO_PIN_CTRL 0x0044 -#define REG_GPIO_INTM 0x0048 -#define REG_LEDCFG0 0x004C -#define REG_LEDCFG1 0x004D -#define REG_LEDCFG2 0x004E -#define REG_LEDCFG3 0x004F -#define REG_FSIMR 0x0050 -#define REG_FSISR 0x0054 -#define REG_HSIMR 0x0058 -#define REG_HSISR 0x005c -#define REG_GPIO_PIN_CTRL_2 0x0060 -#define REG_GPIO_IO_SEL_2 0x0062 -#define REG_MULTI_FUNC_CTRL 0x0068 -#define REG_GPIO_OUTPUT 0x006c -#define REG_OPT_CTRL 0x0074 -#define REG_AFE_XTAL_CTRL_EXT 0x0078 -#define REG_XCK_OUT_CTRL 0x007c -#define REG_MCUFWDL 0x0080 -#define REG_WOL_EVENT 0x0081 -#define REG_MCUTSTCFG 0x0084 - -#define REG_HIMR 0x00B0 -#define REG_HISR 0x00B4 -#define REG_HIMRE 0x00B8 -#define REG_HISRE 0x00BC - -#define REG_PMC_DBG_CTRL2 0x00CC - -#define REG_EFUSE_ACCESS 0x00CF - -#define REG_BIST_SCAN 0x00D0 -#define REG_BIST_RPT 0x00D4 -#define REG_BIST_ROM_RPT 0x00D8 -#define REG_USB_SIE_INTF 0x00E0 -#define REG_PCIE_MIO_INTF 0x00E4 -#define REG_PCIE_MIO_INTD 0x00E8 -#define REG_HPON_FSM 0x00EC -#define REG_SYS_CFG 0x00F0 -#define REG_GPIO_OUTSTS 0x00F4 -#define REG_MAC_PHY_CTRL_NORMAL 0x00F8 -#define REG_SYS_CFG1 0x00FC -#define REG_ROM_VERSION 0x00FD - -#define REG_CR 0x0100 -#define REG_PBP 0x0104 -#define REG_PKT_BUFF_ACCESS_CTRL 0x0106 -#define REG_TRXDMA_CTRL 0x010C -#define REG_TRXFF_BNDY 0x0114 -#define REG_TRXFF_STATUS 0x0118 -#define REG_RXFF_PTR 0x011C - -#define REG_CPWM 0x012F -#define REG_FWIMR 0x0130 -#define REG_FWISR 0x0134 -#define REG_FTISR 0x013C -#define REG_PKTBUF_DBG_CTRL 0x0140 -#define REG_PKTBUF_DBG_DATA_L 0x0144 -#define REG_PKTBUF_DBG_DATA_H 0x0148 -#define REG_RXPKTBUF_CTRL (REG_PKTBUF_DBG_CTRL+2) - -#define REG_TC0_CTRL 0x0150 -#define REG_TC1_CTRL 0x0154 -#define REG_TC2_CTRL 0x0158 -#define REG_TC3_CTRL 0x015C -#define REG_TC4_CTRL 0x0160 -#define REG_TCUNIT_BASE 0x0164 -#define REG_MBIST_START 0x0174 -#define REG_MBIST_DONE 0x0178 -#define REG_MBIST_FAIL 0x017C -#define REG_32K_CTRL 0x0194 -#define REG_C2HEVT_MSG_NORMAL 0x01A0 -#define REG_C2HEVT_CLEAR 0x01AF -#define REG_C2HEVT_MSG_TEST 0x01B8 -#define REG_MCUTST_1 0x01c0 -#define REG_MCUTST_WOWLAN 0x01C7 -#define REG_FMETHR 0x01C8 -#define REG_HMETFR 0x01CC -#define REG_HMEBOX_0 0x01D0 -#define REG_HMEBOX_1 0x01D4 -#define REG_HMEBOX_2 0x01D8 -#define REG_HMEBOX_3 0x01DC - -#define REG_LLT_INIT 0x01E0 -#define REG_BB_ACCEESS_CTRL 0x01E8 -#define REG_BB_ACCESS_DATA 0x01EC - -#define REG_HMEBOX_EXT_0 0x01F0 -#define REG_HMEBOX_EXT_1 0x01F4 -#define REG_HMEBOX_EXT_2 0x01F8 -#define REG_HMEBOX_EXT_3 0x01FC - -#define REG_RQPN 0x0200 -#define REG_FIFOPAGE 0x0204 -#define REG_TDECTRL 0x0208 -#define REG_TXDMA_OFFSET_CHK 0x020C -#define REG_TXDMA_STATUS 0x0210 -#define REG_RQPN_NPQ 0x0214 - -#define REG_RXDMA_AGG_PG_TH 0x0280 - /* FW shall update this register before FW write RXPKT_RELEASE_POLL to 1 */ -#define REG_FW_UPD_RDPTR 0x0284 - /* Control the RX DMA.*/ -#define REG_RXDMA_CONTROL 0x0286 -/* The number of packets in RXPKTBUF. */ -#define REG_RXPKT_NUM 0x0287 - -#define REG_PCIE_CTRL_REG 0x0300 -#define REG_INT_MIG 0x0304 -#define REG_BCNQ_DESA 0x0308 -#define REG_HQ_DESA 0x0310 -#define REG_MGQ_DESA 0x0318 -#define REG_VOQ_DESA 0x0320 -#define REG_VIQ_DESA 0x0328 -#define REG_BEQ_DESA 0x0330 -#define REG_BKQ_DESA 0x0338 -#define REG_RX_DESA 0x0340 - -#define REG_DBI_WDATA 0x0348 -#define REG_DBI_RDATA 0x034C -#define REG_DBI_CTRL 0x0350 -#define REG_DBI_ADDR 0x0350 -#define REG_DBI_FLAG 0x0352 -#define REG_MDIO_WDATA 0x0354 -#define REG_MDIO_RDATA 0x0356 -#define REG_MDIO_CTL 0x0358 -#define REG_DBG_SEL 0x0360 -#define REG_PCIE_HRPWM 0x0361 -#define REG_PCIE_HCPWM 0x0363 -#define REG_UART_CTRL 0x0364 -#define REG_WATCH_DOG 0x0368 -#define REG_UART_TX_DESA 0x0370 -#define REG_UART_RX_DESA 0x0378 - -#define REG_HDAQ_DESA_NODEF 0x0000 -#define REG_CMDQ_DESA_NODEF 0x0000 - -#define REG_VOQ_INFORMATION 0x0400 -#define REG_VIQ_INFORMATION 0x0404 -#define REG_BEQ_INFORMATION 0x0408 -#define REG_BKQ_INFORMATION 0x040C -#define REG_MGQ_INFORMATION 0x0410 -#define REG_HGQ_INFORMATION 0x0414 -#define REG_BCNQ_INFORMATION 0x0418 -#define REG_TXPKT_EMPTY 0x041A - -#define REG_CPU_MGQ_INFORMATION 0x041C -#define REG_FWHW_TXQ_CTRL 0x0420 -#define REG_HWSEQ_CTRL 0x0423 -#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 -#define REG_TXPKTBUF_MGQ_BDNY 0x0425 -#define REG_MULTI_BCNQ_EN 0x0426 -#define REG_MULTI_BCNQ_OFFSET 0x0427 -#define REG_SPEC_SIFS 0x0428 -#define REG_RL 0x042A -#define REG_DARFRC 0x0430 -#define REG_RARFRC 0x0438 -#define REG_RRSR 0x0440 -#define REG_ARFR0 0x0444 -#define REG_ARFR1 0x044C -#define REG_CCK_CHECK 0x0454 -#define REG_AMPDU_MAX_TIME 0x0456 -#define REG_AGGLEN_LMT 0x0458 -#define REG_AMPDU_MIN_SPACE 0x045C -#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045D -#define REG_FAST_EDCA_CTRL 0x0460 -#define REG_RD_RESP_PKT_TH 0x0463 -#define REG_INIRTS_RATE_SEL 0x0480 -#define REG_INIDATA_RATE_SEL 0x0484 -#define REG_ARFR2 0x048C -#define REG_ARFR3 0x0494 -#define REG_POWER_STATUS 0x04A4 -#define REG_POWER_STAGE1 0x04B4 -#define REG_POWER_STAGE2 0x04B8 -#define REG_PKT_LIFE_TIME 0x04C0 -#define REG_STBC_SETTING 0x04C4 -#define REG_HT_SINGLE_AMPDU 0x04C7 -#define REG_PROT_MODE_CTRL 0x04C8 -#define REG_MAX_AGGR_NUM 0x04CA -#define REG_BAR_MODE_CTRL 0x04CC -#define REG_RA_TRY_RATE_AGG_LMT 0x04CF -#define REG_EARLY_MODE_CONTROL 0x04D0 -#define REG_NQOS_SEQ 0x04DC -#define REG_QOS_SEQ 0x04DE -#define REG_NEED_CPU_HANDLE 0x04E0 -#define REG_PKT_LOSE_RPT 0x04E1 -#define REG_PTCL_ERR_STATUS 0x04E2 -#define REG_TX_RPT_CTRL 0x04EC -#define REG_TX_RPT_TIME 0x04F0 -#define REG_DUMMY 0x04FC - -#define REG_EDCA_VO_PARAM 0x0500 -#define REG_EDCA_VI_PARAM 0x0504 -#define REG_EDCA_BE_PARAM 0x0508 -#define REG_EDCA_BK_PARAM 0x050C -#define REG_BCNTCFG 0x0510 -#define REG_PIFS 0x0512 -#define REG_RDG_PIFS 0x0513 -#define REG_SIFS_CTX 0x0514 -#define REG_SIFS_TRX 0x0516 -#define REG_AGGR_BREAK_TIME 0x051A -#define REG_SLOT 0x051B -#define REG_TX_PTCL_CTRL 0x0520 -#define REG_TXPAUSE 0x0522 -#define REG_DIS_TXREQ_CLR 0x0523 -#define REG_RD_CTRL 0x0524 -#define REG_TBTT_PROHIBIT 0x0540 -#define REG_RD_NAV_NXT 0x0544 -#define REG_NAV_PROT_LEN 0x0546 -#define REG_BCN_CTRL 0x0550 -#define REG_USTIME_TSF 0x0551 -#define REG_MBID_NUM 0x0552 -#define REG_DUAL_TSF_RST 0x0553 -#define REG_BCN_INTERVAL 0x0554 -#define REG_MBSSID_BCN_SPACE 0x0554 -#define REG_DRVERLYINT 0x0558 -#define REG_BCNDMATIM 0x0559 -#define REG_ATIMWND 0x055A -#define REG_BCN_MAX_ERR 0x055D -#define REG_RXTSF_OFFSET_CCK 0x055E -#define REG_RXTSF_OFFSET_OFDM 0x055F -#define REG_TSFTR 0x0560 -#define REG_INIT_TSFTR 0x0564 -#define REG_SECONDARY_CCA_CTRL 0x0577 -#define REG_PSTIMER 0x0580 -#define REG_TIMER0 0x0584 -#define REG_TIMER1 0x0588 -#define REG_ACMHWCTRL 0x05C0 -#define REG_ACMRSTCTRL 0x05C1 -#define REG_ACMAVG 0x05C2 -#define REG_VO_ADMTIME 0x05C4 -#define REG_VI_ADMTIME 0x05C6 -#define REG_BE_ADMTIME 0x05C8 -#define REG_EDCA_RANDOM_GEN 0x05CC -#define REG_NOA_DESC_SEL 0x05CF -#define REG_NOA_DESC_DURATION 0x05E0 -#define REG_NOA_DESC_INTERVAL 0x05E4 -#define REG_NOA_DESC_START 0x05E8 -#define REG_NOA_DESC_COUNT 0x05EC -#define REG_SCH_TXCMD 0x05F8 - -#define REG_APSD_CTRL 0x0600 -#define REG_BWOPMODE 0x0603 -#define REG_TCR 0x0604 -#define REG_RCR 0x0608 -#define REG_RX_PKT_LIMIT 0x060C -#define REG_RX_DLK_TIME 0x060D -#define REG_RX_DRVINFO_SZ 0x060F - -#define REG_MACID 0x0610 -#define REG_BSSID 0x0618 -#define REG_MAR 0x0620 -#define REG_MBIDCAMCFG 0x0628 - -#define REG_USTIME_EDCA 0x0638 -#define REG_MAC_SPEC_SIFS 0x063A -#define REG_RESP_SIFS_CCK 0x063C -#define REG_RESP_SIFS_OFDM 0x063E -#define REG_ACKTO 0x0640 -#define REG_CTS2TO 0x0641 -#define REG_EIFS 0x0642 - -#define REG_NAV_CTRL 0x0650 -#define REG_NAV_UPPER 0x0652 -#define REG_BACAMCMD 0x0654 -#define REG_BACAMCONTENT 0x0658 -#define REG_LBDLY 0x0660 -#define REG_FWDLY 0x0661 -#define REG_RXERR_RPT 0x0664 -#define REG_TRXPTCL_CTL 0x0668 - -#define REG_CAMCMD 0x0670 -#define REG_CAMWRITE 0x0674 -#define REG_CAMREAD 0x0678 -#define REG_CAMDBG 0x067C -#define REG_SECCFG 0x0680 - -#define REG_WOW_CTRL 0x0690 -#define REG_PSSTATUS 0x0691 -#define REG_PS_RX_INFO 0x0692 -#define REG_UAPSD_TID 0x0693 -#define REG_LPNAV_CTRL 0x0694 -#define REG_WKFMCAM_NUM 0x0698 -#define REG_WKFMCAM_RWD 0x069C -#define REG_RXFLTMAP0 0x06A0 -#define REG_RXFLTMAP1 0x06A2 -#define REG_RXFLTMAP2 0x06A4 -#define REG_BCN_PSR_RPT 0x06A8 -#define REG_CALB32K_CTRL 0x06AC -#define REG_PKT_MON_CTRL 0x06B4 -#define REG_BT_COEX_TABLE 0x06C0 -#define REG_WMAC_RESP_TXINFO 0x06D8 - -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_TEST_USB_TXQS 0xFE48 -#define REG_TEST_SIE_VID 0xFE60 -#define REG_TEST_SIE_PID 0xFE62 -#define REG_TEST_SIE_OPTIONAL 0xFE64 -#define REG_TEST_SIE_CHIRP_K 0xFE65 -#define REG_TEST_SIE_PHY 0xFE66 -#define REG_TEST_SIE_MAC_ADDR 0xFE70 -#define REG_TEST_SIE_STRING 0xFE80 - -#define REG_NORMAL_SIE_VID 0xFE60 -#define REG_NORMAL_SIE_PID 0xFE62 -#define REG_NORMAL_SIE_OPTIONAL 0xFE64 -#define REG_NORMAL_SIE_EP 0xFE65 -#define REG_NORMAL_SIE_PHY 0xFE68 -#define REG_NORMAL_SIE_MAC_ADDR 0xFE70 -#define REG_NORMAL_SIE_STRING 0xFE80 - -#define CR9346 REG_9346CR -#define MSR (REG_CR + 2) -#define ISR REG_HISR -#define TSFR REG_TSFTR - -#define MACIDR0 REG_MACID -#define MACIDR4 (REG_MACID + 4) - -#define PBP REG_PBP - -#define IDR0 MACIDR0 -#define IDR4 MACIDR4 - -#define UNUSED_REGISTER 0x1BF -#define DCAM UNUSED_REGISTER -#define PSR UNUSED_REGISTER -#define BBADDR UNUSED_REGISTER -#define PHYDATAR UNUSED_REGISTER - -#define INVALID_BBRF_VALUE 0x12345678 - -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -#define CMDEEPROM_EN BIT(5) -#define CMDEEPROM_SEL BIT(4) -#define CMD9346CR_9356SEL BIT(4) -#define AUTOLOAD_EEPROM (CMDEEPROM_EN|CMDEEPROM_SEL) -#define AUTOLOAD_EFUSE CMDEEPROM_EN - -#define GPIOSEL_GPIO 0 -#define GPIOSEL_ENBT BIT(5) - -#define GPIO_IN REG_GPIO_PIN_CTRL -#define GPIO_OUT (REG_GPIO_PIN_CTRL+1) -#define GPIO_IO_SEL (REG_GPIO_PIN_CTRL+2) -#define GPIO_MOD (REG_GPIO_PIN_CTRL+3) - -/* 8723/8188E Host System Interrupt Mask Register (offset 0x58, 32 byte) */ -#define HSIMR_GPIO12_0_INT_EN BIT(0) -#define HSIMR_SPS_OCP_INT_EN BIT(5) -#define HSIMR_RON_INT_EN BIT(6) -#define HSIMR_PDN_INT_EN BIT(7) -#define HSIMR_GPIO9_INT_EN BIT(25) - -/* 8723/8188E Host System Interrupt Status Register (offset 0x5C, 32 byte) */ -#define HSISR_GPIO12_0_INT BIT(0) -#define HSISR_SPS_OCP_INT BIT(5) -#define HSISR_RON_INT_EN BIT(6) -#define HSISR_PDNINT BIT(7) -#define HSISR_GPIO9_INT BIT(25) - -#define MSR_NOLINK 0x00 -#define MSR_ADHOC 0x01 -#define MSR_INFRA 0x02 -#define MSR_AP 0x03 -#define MSR_MASK 0x03 - -#define RRSR_RSC_OFFSET 21 -#define RRSR_SHORT_OFFSET 23 -#define RRSR_RSC_BW_40M 0x600000 -#define RRSR_RSC_UPSUBCHNL 0x400000 -#define RRSR_RSC_LOWSUBCHNL 0x200000 -#define RRSR_SHORT 0x800000 -#define RRSR_1M BIT(0) -#define RRSR_2M BIT(1) -#define RRSR_5_5M BIT(2) -#define RRSR_11M BIT(3) -#define RRSR_6M BIT(4) -#define RRSR_9M BIT(5) -#define RRSR_12M BIT(6) -#define RRSR_18M BIT(7) -#define RRSR_24M BIT(8) -#define RRSR_36M BIT(9) -#define RRSR_48M BIT(10) -#define RRSR_54M BIT(11) -#define RRSR_MCS0 BIT(12) -#define RRSR_MCS1 BIT(13) -#define RRSR_MCS2 BIT(14) -#define RRSR_MCS3 BIT(15) -#define RRSR_MCS4 BIT(16) -#define RRSR_MCS5 BIT(17) -#define RRSR_MCS6 BIT(18) -#define RRSR_MCS7 BIT(19) -#define BRSR_ACKSHORTPMB BIT(23) - -#define RATR_1M 0x00000001 -#define RATR_2M 0x00000002 -#define RATR_55M 0x00000004 -#define RATR_11M 0x00000008 -#define RATR_6M 0x00000010 -#define RATR_9M 0x00000020 -#define RATR_12M 0x00000040 -#define RATR_18M 0x00000080 -#define RATR_24M 0x00000100 -#define RATR_36M 0x00000200 -#define RATR_48M 0x00000400 -#define RATR_54M 0x00000800 -#define RATR_MCS0 0x00001000 -#define RATR_MCS1 0x00002000 -#define RATR_MCS2 0x00004000 -#define RATR_MCS3 0x00008000 -#define RATR_MCS4 0x00010000 -#define RATR_MCS5 0x00020000 -#define RATR_MCS6 0x00040000 -#define RATR_MCS7 0x00080000 -#define RATR_MCS8 0x00100000 -#define RATR_MCS9 0x00200000 -#define RATR_MCS10 0x00400000 -#define RATR_MCS11 0x00800000 -#define RATR_MCS12 0x01000000 -#define RATR_MCS13 0x02000000 -#define RATR_MCS14 0x04000000 -#define RATR_MCS15 0x08000000 - -#define RATE_1M BIT(0) -#define RATE_2M BIT(1) -#define RATE_5_5M BIT(2) -#define RATE_11M BIT(3) -#define RATE_6M BIT(4) -#define RATE_9M BIT(5) -#define RATE_12M BIT(6) -#define RATE_18M BIT(7) -#define RATE_24M BIT(8) -#define RATE_36M BIT(9) -#define RATE_48M BIT(10) -#define RATE_54M BIT(11) -#define RATE_MCS0 BIT(12) -#define RATE_MCS1 BIT(13) -#define RATE_MCS2 BIT(14) -#define RATE_MCS3 BIT(15) -#define RATE_MCS4 BIT(16) -#define RATE_MCS5 BIT(17) -#define RATE_MCS6 BIT(18) -#define RATE_MCS7 BIT(19) -#define RATE_MCS8 BIT(20) -#define RATE_MCS9 BIT(21) -#define RATE_MCS10 BIT(22) -#define RATE_MCS11 BIT(23) -#define RATE_MCS12 BIT(24) -#define RATE_MCS13 BIT(25) -#define RATE_MCS14 BIT(26) -#define RATE_MCS15 BIT(27) - -#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M) -#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M |\ - RATR_24M | RATR_36M | RATR_48M | RATR_54M) -#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 |\ - RATR_MCS3 | RATR_MCS4 | RATR_MCS5 |\ - RATR_MCS6 | RATR_MCS7) -#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 |\ - RATR_MCS11 | RATR_MCS12 | RATR_MCS13 |\ - RATR_MCS14 | RATR_MCS15) - -#define BW_OPMODE_20MHZ BIT(2) -#define BW_OPMODE_5G BIT(1) -#define BW_OPMODE_11J BIT(0) - -#define CAM_VALID BIT(15) -#define CAM_NOTVALID 0x0000 -#define CAM_USEDK BIT(5) - -#define CAM_NONE 0x0 -#define CAM_WEP40 0x01 -#define CAM_TKIP 0x02 -#define CAM_AES 0x04 -#define CAM_WEP104 0x05 - -#define TOTAL_CAM_ENTRY 32 -#define HALF_CAM_ENTRY 16 - -#define CAM_WRITE BIT(16) -#define CAM_READ 0x00000000 -#define CAM_POLLINIG BIT(31) - -#define SCR_USEDK 0x01 -#define SCR_TXSEC_ENABLE 0x02 -#define SCR_RXSEC_ENABLE 0x04 - -#define WOW_PMEN BIT(0) -#define WOW_WOMEN BIT(1) -#define WOW_MAGIC BIT(2) -#define WOW_UWF BIT(3) - -/********************************************* -* 8188 IMR/ISR bits -**********************************************/ -#define IMR_DISABLED 0x0 -/* IMR DW0(0x0060-0063) Bit 0-31 */ -/* TXRPT interrupt when CCX bit of the packet is set */ -#define IMR_TXCCK BIT(30) -/* Power Save Time Out Interrupt */ -#define IMR_PSTIMEOUT BIT(29) -/* When GTIMER4 expires, this bit is set to 1 */ -#define IMR_GTINT4 BIT(28) -/* When GTIMER3 expires, this bit is set to 1 */ -#define IMR_GTINT3 BIT(27) -/* Transmit Beacon0 Error */ -#define IMR_TBDER BIT(26) -/* Transmit Beacon0 OK */ -#define IMR_TBDOK BIT(25) -/* TSF Timer BIT32 toggle indication interrupt */ -#define IMR_TSF_BIT32_TOGGLE BIT(24) -/* Beacon DMA Interrupt 0 */ -#define IMR_BCNDMAINT0 BIT(20) -/* Beacon Queue DMA OK0 */ -#define IMR_BCNDOK0 BIT(16) -/* HSISR Indicator (HSIMR & HSISR is true, this bit is set to 1) */ -#define IMR_HSISR_IND_ON_INT BIT(15) -/* Beacon DMA Interrupt Extension for Win7 */ -#define IMR_BCNDMAINT_E BIT(14) -/* CTWidnow End or ATIM Window End */ -#define IMR_ATIMEND BIT(12) -/* HISR1 Indicator (HISR1 & HIMR1 is true, this bit is set to 1)*/ -#define IMR_HISR1_IND_INT BIT(11) -/* CPU to Host Command INT Status, Write 1 clear */ -#define IMR_C2HCMD BIT(10) -/* CPU power Mode exchange INT Status, Write 1 clear */ -#define IMR_CPWM2 BIT(9) -/* CPU power Mode exchange INT Status, Write 1 clear */ -#define IMR_CPWM BIT(8) -/* High Queue DMA OK */ -#define IMR_HIGHDOK BIT(7) -/* Management Queue DMA OK */ -#define IMR_MGNTDOK BIT(6) -/* AC_BK DMA OK */ -#define IMR_BKDOK BIT(5) -/* AC_BE DMA OK */ -#define IMR_BEDOK BIT(4) -/* AC_VI DMA OK */ -#define IMR_VIDOK BIT(3) -/* AC_VO DMA OK */ -#define IMR_VODOK BIT(2) -/* Rx Descriptor Unavailable */ -#define IMR_RDU BIT(1) -#define IMR_ROK BIT(0) /* Receive DMA OK */ - -/* IMR DW1(0x00B4-00B7) Bit 0-31 */ -/* Beacon DMA Interrupt 7 */ -#define IMR_BCNDMAINT7 BIT(27) -/* Beacon DMA Interrupt 6 */ -#define IMR_BCNDMAINT6 BIT(26) -/* Beacon DMA Interrupt 5 */ -#define IMR_BCNDMAINT5 BIT(25) -/* Beacon DMA Interrupt 4 */ -#define IMR_BCNDMAINT4 BIT(24) -/* Beacon DMA Interrupt 3 */ -#define IMR_BCNDMAINT3 BIT(23) -/* Beacon DMA Interrupt 2 */ -#define IMR_BCNDMAINT2 BIT(22) -/* Beacon DMA Interrupt 1 */ -#define IMR_BCNDMAINT1 BIT(21) -/* Beacon Queue DMA OK Interrup 7 */ -#define IMR_BCNDOK7 BIT(20) -/* Beacon Queue DMA OK Interrup 6 */ -#define IMR_BCNDOK6 BIT(19) -/* Beacon Queue DMA OK Interrup 5 */ -#define IMR_BCNDOK5 BIT(18) -/* Beacon Queue DMA OK Interrup 4 */ -#define IMR_BCNDOK4 BIT(17) -/* Beacon Queue DMA OK Interrup 3 */ -#define IMR_BCNDOK3 BIT(16) -/* Beacon Queue DMA OK Interrup 2 */ -#define IMR_BCNDOK2 BIT(15) -/* Beacon Queue DMA OK Interrup 1 */ -#define IMR_BCNDOK1 BIT(14) -/* ATIM Window End Extension for Win7 */ -#define IMR_ATIMEND_E BIT(13) -/* Tx Error Flag Interrupt Status, write 1 clear. */ -#define IMR_TXERR BIT(11) -/* Rx Error Flag INT Status, Write 1 clear */ -#define IMR_RXERR BIT(10) -/* Transmit FIFO Overflow */ -#define IMR_TXFOVW BIT(9) -/* Receive FIFO Overflow */ -#define IMR_RXFOVW BIT(8) - -#define HWSET_MAX_SIZE 512 -#define EFUSE_MAX_SECTION 64 -#define EFUSE_REAL_CONTENT_LEN 256 -/* PG data exclude header, dummy 7 bytes frome CP test and reserved 1byte.*/ -#define EFUSE_OOB_PROTECT_BYTES 18 - -#define EEPROM_DEFAULT_TSSI 0x0 -#define EEPROM_DEFAULT_TXPOWERDIFF 0x0 -#define EEPROM_DEFAULT_CRYSTALCAP 0x5 -#define EEPROM_DEFAULT_BOARDTYPE 0x02 -#define EEPROM_DEFAULT_TXPOWER 0x1010 -#define EEPROM_DEFAULT_HT2T_TXPWR 0x10 - -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 -#define EEPROM_DEFAULT_THERMALMETER 0x18 -#define EEPROM_DEFAULT_ANTTXPOWERDIFF 0x0 -#define EEPROM_DEFAULT_TXPWDIFF_CRYSTALCAP 0x5 -#define EEPROM_DEFAULT_TXPOWERLEVEL 0x22 -#define EEPROM_DEFAULT_HT40_2SDIFF 0x0 -#define EEPROM_DEFAULT_HT20_DIFF 2 -#define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 -#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET 0 -#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET 0 - -#define RF_OPTION1 0x79 -#define RF_OPTION2 0x7A -#define RF_OPTION3 0x7B -#define RF_OPTION4 0xC3 - -#define EEPROM_DEFAULT_PID 0x1234 -#define EEPROM_DEFAULT_VID 0x5678 -#define EEPROM_DEFAULT_CUSTOMERID 0xAB -#define EEPROM_DEFAULT_SUBCUSTOMERID 0xCD -#define EEPROM_DEFAULT_VERSION 0 - -#define EEPROM_CHANNEL_PLAN_FCC 0x0 -#define EEPROM_CHANNEL_PLAN_IC 0x1 -#define EEPROM_CHANNEL_PLAN_ETSI 0x2 -#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 -#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 -#define EEPROM_CHANNEL_PLAN_MKK 0x5 -#define EEPROM_CHANNEL_PLAN_MKK1 0x6 -#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 -#define EEPROM_CHANNEL_PLAN_TELEC 0x8 -#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 -#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA -#define EEPROM_CHANNEL_PLAN_NCC 0xB -#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 - -#define EEPROM_CID_DEFAULT 0x0 -#define EEPROM_CID_TOSHIBA 0x4 -#define EEPROM_CID_CCX 0x10 -#define EEPROM_CID_QMI 0x0D -#define EEPROM_CID_WHQL 0xFE - -#define RTL_EEPROM_ID 0x8129 - -#define EEPROM_HPON 0x02 -#define EEPROM_CLK 0x06 -#define EEPROM_TESTR 0x08 - -#define EEPROM_TXPOWERCCK 0x10 -#define EEPROM_TXPOWERHT40_1S 0x16 -#define EEPROM_TXPOWERHT20DIFF 0x1B -#define EEPROM_TXPOWER_OFDMDIFF 0x1B - -#define EEPROM_TX_PWR_INX 0x10 - -#define EEPROM_CHANNELPLAN 0xB8 -#define EEPROM_XTAL_8821AE 0xB9 -#define EEPROM_THERMAL_METER 0xBA -#define EEPROM_IQK_LCK_88E 0xBB - -#define EEPROM_RF_BOARD_OPTION 0xC1 -#define EEPROM_RF_FEATURE_OPTION_88E 0xC2 -#define EEPROM_RF_BT_SETTING 0xC3 -#define EEPROM_VERSION 0xC4 -#define EEPROM_CUSTOMER_ID 0xC5 -#define EEPROM_RF_ANTENNA_OPT_88E 0xC9 -#define EEPROM_RFE_OPTION 0xCA - -#define EEPROM_MAC_ADDR 0xD0 -#define EEPROM_VID 0xD6 -#define EEPROM_DID 0xD8 -#define EEPROM_SVID 0xDA -#define EEPROM_SMID 0xDC - -#define STOPBECON BIT(6) -#define STOPHIGHT BIT(5) -#define STOPMGT BIT(4) -#define STOPVO BIT(3) -#define STOPVI BIT(2) -#define STOPBE BIT(1) -#define STOPBK BIT(0) - -#define RCR_APPFCS BIT(31) -#define RCR_APP_MIC BIT(30) -#define RCR_APP_ICV BIT(29) -#define RCR_APP_PHYST_RXFF BIT(28) -#define RCR_APP_BA_SSN BIT(27) -#define RCR_NONQOS_VHT BIT(26) -#define RCR_ENMBID BIT(24) -#define RCR_LSIGEN BIT(23) -#define RCR_MFBEN BIT(22) -#define RCR_HTC_LOC_CTRL BIT(14) -#define RCR_AMF BIT(13) -#define RCR_ACF BIT(12) -#define RCR_ADF BIT(11) -#define RCR_AICV BIT(9) -#define RCR_ACRC32 BIT(8) -#define RCR_CBSSID_BCN BIT(7) -#define RCR_CBSSID_DATA BIT(6) -#define RCR_CBSSID RCR_CBSSID_DATA -#define RCR_APWRMGT BIT(5) -#define RCR_ADD3 BIT(4) -#define RCR_AB BIT(3) -#define RCR_AM BIT(2) -#define RCR_APM BIT(1) -#define RCR_AAP BIT(0) -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - -#define RSV_CTRL 0x001C -#define RD_CTRL 0x0524 - -#define REG_USB_INFO 0xFE17 -#define REG_USB_SPECIAL_OPTION 0xFE55 -#define REG_USB_DMA_AGG_TO 0xFE5B -#define REG_USB_AGG_TO 0xFE5C -#define REG_USB_AGG_TH 0xFE5D - -#define REG_USB_VID 0xFE60 -#define REG_USB_PID 0xFE62 -#define REG_USB_OPTIONAL 0xFE64 -#define REG_USB_CHIRP_K 0xFE65 -#define REG_USB_PHY 0xFE66 -#define REG_USB_MAC_ADDR 0xFE70 -#define REG_USB_HRPWM 0xFE58 -#define REG_USB_HCPWM 0xFE57 - -#define SW18_FPWM BIT(3) - -#define ISO_MD2PP BIT(0) -#define ISO_UA2USB BIT(1) -#define ISO_UD2CORE BIT(2) -#define ISO_PA2PCIE BIT(3) -#define ISO_PD2CORE BIT(4) -#define ISO_IP2MAC BIT(5) -#define ISO_DIOP BIT(6) -#define ISO_DIOE BIT(7) -#define ISO_EB2CORE BIT(8) -#define ISO_DIOR BIT(9) - -#define PWC_EV25V BIT(14) -#define PWC_EV12V BIT(15) - -#define FEN_BBRSTB BIT(0) -#define FEN_BB_GLB_RSTN BIT(1) -#define FEN_USBA BIT(2) -#define FEN_UPLL BIT(3) -#define FEN_USBD BIT(4) -#define FEN_DIO_PCIE BIT(5) -#define FEN_PCIEA BIT(6) -#define FEN_PPLL BIT(7) -#define FEN_PCIED BIT(8) -#define FEN_DIOE BIT(9) -#define FEN_CPUEN BIT(10) -#define FEN_DCORE BIT(11) -#define FEN_ELDR BIT(12) -#define FEN_DIO_RF BIT(13) -#define FEN_HWPDN BIT(14) -#define FEN_MREGEN BIT(15) - -#define PFM_LDALL BIT(0) -#define PFM_ALDN BIT(1) -#define PFM_LDKP BIT(2) -#define PFM_WOWL BIT(3) -#define ENPDN BIT(4) -#define PDN_PL BIT(5) -#define APFM_ONMAC BIT(8) -#define APFM_OFF BIT(9) -#define APFM_RSM BIT(10) -#define AFSM_HSUS BIT(11) -#define AFSM_PCIE BIT(12) -#define APDM_MAC BIT(13) -#define APDM_HOST BIT(14) -#define APDM_HPDN BIT(15) -#define RDY_MACON BIT(16) -#define SUS_HOST BIT(17) -#define ROP_ALD BIT(20) -#define ROP_PWR BIT(21) -#define ROP_SPS BIT(22) -#define SOP_MRST BIT(25) -#define SOP_FUSE BIT(26) -#define SOP_ABG BIT(27) -#define SOP_AMB BIT(28) -#define SOP_RCK BIT(29) -#define SOP_A8M BIT(30) -#define XOP_BTCK BIT(31) - -#define ANAD16V_EN BIT(0) -#define ANA8M BIT(1) -#define MACSLP BIT(4) -#define LOADER_CLK_EN BIT(5) -#define _80M_SSC_DIS BIT(7) -#define _80M_SSC_EN_HO BIT(8) -#define PHY_SSC_RSTB BIT(9) -#define SEC_CLK_EN BIT(10) -#define MAC_CLK_EN BIT(11) -#define SYS_CLK_EN BIT(12) -#define RING_CLK_EN BIT(13) - -#define BOOT_FROM_EEPROM BIT(4) -#define EEPROM_EN BIT(5) - -#define AFE_BGEN BIT(0) -#define AFE_MBEN BIT(1) -#define MAC_ID_EN BIT(7) - -#define WLOCK_ALL BIT(0) -#define WLOCK_00 BIT(1) -#define WLOCK_04 BIT(2) -#define WLOCK_08 BIT(3) -#define WLOCK_40 BIT(4) -#define R_DIS_PRST_0 BIT(5) -#define R_DIS_PRST_1 BIT(6) -#define LOCK_ALL_EN BIT(7) - -#define RF_EN BIT(0) -#define RF_RSTB BIT(1) -#define RF_SDMRSTB BIT(2) - -#define LDA15_EN BIT(0) -#define LDA15_STBY BIT(1) -#define LDA15_OBUF BIT(2) -#define LDA15_REG_VOS BIT(3) -#define _LDA15_VOADJ(x) (((x) & 0x7) << 4) - -#define LDV12_EN BIT(0) -#define LDV12_SDBY BIT(1) -#define LPLDO_HSM BIT(2) -#define LPLDO_LSM_DIS BIT(3) -#define _LDV12_VADJ(x) (((x) & 0xF) << 4) - -#define XTAL_EN BIT(0) -#define XTAL_BSEL BIT(1) -#define _XTAL_BOSC(x) (((x) & 0x3) << 2) -#define _XTAL_CADJ(x) (((x) & 0xF) << 4) -#define XTAL_GATE_USB BIT(8) -#define _XTAL_USB_DRV(x) (((x) & 0x3) << 9) -#define XTAL_GATE_AFE BIT(11) -#define _XTAL_AFE_DRV(x) (((x) & 0x3) << 12) -#define XTAL_RF_GATE BIT(14) -#define _XTAL_RF_DRV(x) (((x) & 0x3) << 15) -#define XTAL_GATE_DIG BIT(17) -#define _XTAL_DIG_DRV(x) (((x) & 0x3) << 18) -#define XTAL_BT_GATE BIT(20) -#define _XTAL_BT_DRV(x) (((x) & 0x3) << 21) -#define _XTAL_GPIO(x) (((x) & 0x7) << 23) - -#define CKDLY_AFE BIT(26) -#define CKDLY_USB BIT(27) -#define CKDLY_DIG BIT(28) -#define CKDLY_BT BIT(29) - -#define APLL_EN BIT(0) -#define APLL_320_EN BIT(1) -#define APLL_FREF_SEL BIT(2) -#define APLL_EDGE_SEL BIT(3) -#define APLL_WDOGB BIT(4) -#define APLL_LPFEN BIT(5) - -#define APLL_REF_CLK_13MHZ 0x1 -#define APLL_REF_CLK_19_2MHZ 0x2 -#define APLL_REF_CLK_20MHZ 0x3 -#define APLL_REF_CLK_25MHZ 0x4 -#define APLL_REF_CLK_26MHZ 0x5 -#define APLL_REF_CLK_38_4MHZ 0x6 -#define APLL_REF_CLK_40MHZ 0x7 - -#define APLL_320EN BIT(14) -#define APLL_80EN BIT(15) -#define APLL_1MEN BIT(24) - -#define ALD_EN BIT(18) -#define EF_PD BIT(19) -#define EF_FLAG BIT(31) - -#define EF_TRPT BIT(7) -#define LDOE25_EN BIT(31) - -#define RSM_EN BIT(0) -#define TIMER_EN BIT(4) - -#define TRSW0EN BIT(2) -#define TRSW1EN BIT(3) -#define EROM_EN BIT(4) -#define ENBT BIT(5) -#define ENUART BIT(8) -#define UART_910 BIT(9) -#define ENPMAC BIT(10) -#define SIC_SWRST BIT(11) -#define ENSIC BIT(12) -#define SIC_23 BIT(13) -#define ENHDP BIT(14) -#define SIC_LBK BIT(15) - -#define LED0PL BIT(4) -#define LED1PL BIT(12) -#define LED0DIS BIT(7) - -#define MCUFWDL_EN BIT(0) -#define MCUFWDL_RDY BIT(1) -#define FWDL_CHKSUM_RPT BIT(2) -#define MACINI_RDY BIT(3) -#define BBINI_RDY BIT(4) -#define RFINI_RDY BIT(5) -#define WINTINI_RDY BIT(6) -#define CPRST BIT(23) - -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define TRP_B15V_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define VENDOR_ID BIT(19) -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) - -#define CHIP_VER_RTL_MASK 0xF000 -#define CHIP_VER_RTL_SHIFT 12 - -#define REG_LBMODE (REG_CR + 3) - -#define HCI_TXDMA_EN BIT(0) -#define HCI_RXDMA_EN BIT(1) -#define TXDMA_EN BIT(2) -#define RXDMA_EN BIT(3) -#define PROTOCOL_EN BIT(4) -#define SCHEDULE_EN BIT(5) -#define MACTXEN BIT(6) -#define MACRXEN BIT(7) -#define ENSWBCN BIT(8) -#define ENSEC BIT(9) - -#define _NETTYPE(x) (((x) & 0x3) << 16) -#define MASK_NETTYPE 0x30000 -#define NT_NO_LINK 0x0 -#define NT_LINK_AD_HOC 0x1 -#define NT_LINK_AP 0x2 -#define NT_AS_AP 0x3 - -#define _LBMODE(x) (((x) & 0xF) << 24) -#define MASK_LBMODE 0xF000000 -#define LOOPBACK_NORMAL 0x0 -#define LOOPBACK_IMMEDIATELY 0xB -#define LOOPBACK_MAC_DELAY 0x3 -#define LOOPBACK_PHY 0x1 -#define LOOPBACK_DMA 0x7 - -#define GET_RX_PAGE_SIZE(value) ((value) & 0xF) -#define GET_TX_PAGE_SIZE(value) (((value) & 0xF0) >> 4) -#define _PSRX_MASK 0xF -#define _PSTX_MASK 0xF0 -#define _PSRX(x) (x) -#define _PSTX(x) ((x) << 4) - -#define PBP_64 0x0 -#define PBP_128 0x1 -#define PBP_256 0x2 -#define PBP_512 0x3 -#define PBP_1024 0x4 - -#define RXDMA_ARBBW_EN BIT(0) -#define RXSHFT_EN BIT(1) -#define RXDMA_AGG_EN BIT(2) -#define QS_VO_QUEUE BIT(8) -#define QS_VI_QUEUE BIT(9) -#define QS_BE_QUEUE BIT(10) -#define QS_BK_QUEUE BIT(11) -#define QS_MANAGER_QUEUE BIT(12) -#define QS_HIGH_QUEUE BIT(13) - -#define HQSEL_VOQ BIT(0) -#define HQSEL_VIQ BIT(1) -#define HQSEL_BEQ BIT(2) -#define HQSEL_BKQ BIT(3) -#define HQSEL_MGTQ BIT(4) -#define HQSEL_HIQ BIT(5) - -#define _TXDMA_HIQ_MAP(x) (((x)&0x3) << 14) -#define _TXDMA_MGQ_MAP(x) (((x)&0x3) << 12) -#define _TXDMA_BKQ_MAP(x) (((x)&0x3) << 10) -#define _TXDMA_BEQ_MAP(x) (((x)&0x3) << 8) -#define _TXDMA_VIQ_MAP(x) (((x)&0x3) << 6) -#define _TXDMA_VOQ_MAP(x) (((x)&0x3) << 4) - -#define QUEUE_LOW 1 -#define QUEUE_NORMAL 2 -#define QUEUE_HIGH 3 - -#define _LLT_NO_ACTIVE 0x0 -#define _LLT_WRITE_ACCESS 0x1 -#define _LLT_READ_ACCESS 0x2 - -#define _LLT_INIT_DATA(x) ((x) & 0xFF) -#define _LLT_INIT_ADDR(x) (((x) & 0xFF) << 8) -#define _LLT_OP(x) (((x) & 0x3) << 30) -#define _LLT_OP_VALUE(x) (((x) >> 30) & 0x3) - -#define BB_WRITE_READ_MASK (BIT(31) | BIT(30)) -#define BB_WRITE_EN BIT(30) -#define BB_READ_EN BIT(31) - -#define _HPQ(x) ((x) & 0xFF) -#define _LPQ(x) (((x) & 0xFF) << 8) -#define _PUBQ(x) (((x) & 0xFF) << 16) -#define _NPQ(x) ((x) & 0xFF) - -#define HPQ_PUBLIC_DIS BIT(24) -#define LPQ_PUBLIC_DIS BIT(25) -#define LD_RQPN BIT(31) - -#define BCN_VALID BIT(16) -#define BCN_HEAD(x) (((x) & 0xFF) << 8) -#define BCN_HEAD_MASK 0xFF00 - -#define BLK_DESC_NUM_SHIFT 4 -#define BLK_DESC_NUM_MASK 0xF - -#define DROP_DATA_EN BIT(9) - -#define EN_AMPDU_RTY_NEW BIT(7) - -#define _INIRTSMCS_SEL(x) ((x) & 0x3F) - -#define _SPEC_SIFS_CCK(x) ((x) & 0xFF) -#define _SPEC_SIFS_OFDM(x) (((x) & 0xFF) << 8) - -#define RATE_REG_BITMAP_ALL 0xFFFFF - -#define _RRSC_BITMAP(x) ((x) & 0xFFFFF) - -#define _RRSR_RSC(x) (((x) & 0x3) << 21) -#define RRSR_RSC_RESERVED 0x0 -#define RRSR_RSC_UPPER_SUBCHANNEL 0x1 -#define RRSR_RSC_LOWER_SUBCHANNEL 0x2 -#define RRSR_RSC_DUPLICATE_MODE 0x3 - -#define USE_SHORT_G1 BIT(20) - -#define _AGGLMT_MCS0(x) ((x) & 0xF) -#define _AGGLMT_MCS1(x) (((x) & 0xF) << 4) -#define _AGGLMT_MCS2(x) (((x) & 0xF) << 8) -#define _AGGLMT_MCS3(x) (((x) & 0xF) << 12) -#define _AGGLMT_MCS4(x) (((x) & 0xF) << 16) -#define _AGGLMT_MCS5(x) (((x) & 0xF) << 20) -#define _AGGLMT_MCS6(x) (((x) & 0xF) << 24) -#define _AGGLMT_MCS7(x) (((x) & 0xF) << 28) - -#define RETRY_LIMIT_SHORT_SHIFT 8 -#define RETRY_LIMIT_LONG_SHIFT 0 - -#define _DARF_RC1(x) ((x) & 0x1F) -#define _DARF_RC2(x) (((x) & 0x1F) << 8) -#define _DARF_RC3(x) (((x) & 0x1F) << 16) -#define _DARF_RC4(x) (((x) & 0x1F) << 24) -#define _DARF_RC5(x) ((x) & 0x1F) -#define _DARF_RC6(x) (((x) & 0x1F) << 8) -#define _DARF_RC7(x) (((x) & 0x1F) << 16) -#define _DARF_RC8(x) (((x) & 0x1F) << 24) - -#define _RARF_RC1(x) ((x) & 0x1F) -#define _RARF_RC2(x) (((x) & 0x1F) << 8) -#define _RARF_RC3(x) (((x) & 0x1F) << 16) -#define _RARF_RC4(x) (((x) & 0x1F) << 24) -#define _RARF_RC5(x) ((x) & 0x1F) -#define _RARF_RC6(x) (((x) & 0x1F) << 8) -#define _RARF_RC7(x) (((x) & 0x1F) << 16) -#define _RARF_RC8(x) (((x) & 0x1F) << 24) - -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - -#define _AIFS(x) (x) -#define _ECW_MAX_MIN(x) ((x) << 8) -#define _TXOP_LIMIT(x) ((x) << 16) - -#define _BCNIFS(x) ((x) & 0xFF) -#define _BCNECW(x) ((((x) & 0xF)) << 8) - -#define _LRL(x) ((x) & 0x3F) -#define _SRL(x) (((x) & 0x3F) << 8) - -#define _SIFS_CCK_CTX(x) ((x) & 0xFF) -#define _SIFS_CCK_TRX(x) (((x) & 0xFF) << 8) - -#define _SIFS_OFDM_CTX(x) ((x) & 0xFF) -#define _SIFS_OFDM_TRX(x) (((x) & 0xFF) << 8) - -#define _TBTT_PROHIBIT_HOLD(x) (((x) & 0xFF) << 8) - -#define DIS_EDCA_CNT_DWN BIT(11) - -#define EN_MBSSID BIT(1) -#define EN_TXBCN_RPT BIT(2) -#define EN_BCN_FUNCTION BIT(3) - -#define TSFTR_RST BIT(0) -#define TSFTR1_RST BIT(1) - -#define STOP_BCNQ BIT(6) - -#define DIS_TSF_UDT0_NORMAL_CHIP BIT(4) -#define DIS_TSF_UDT0_TEST_CHIP BIT(5) - -#define ACMHW_HWEN BIT(0) -#define ACMHW_BEQEN BIT(1) -#define ACMHW_VIQEN BIT(2) -#define ACMHW_VOQEN BIT(3) -#define ACMHW_BEQSTATUS BIT(4) -#define ACMHW_VIQSTATUS BIT(5) -#define ACMHW_VOQSTATUS BIT(6) - -#define APSDOFF BIT(6) -#define APSDOFF_STATUS BIT(7) - -#define BW_20MHZ BIT(2) - -#define RATE_BITMAP_ALL 0xFFFFF - -#define RATE_RRSR_CCK_ONLY_1M 0xFFFF1 - -#define TSFRST BIT(0) -#define DIS_GCLK BIT(1) -#define PAD_SEL BIT(2) -#define PWR_ST BIT(6) -#define PWRBIT_OW_EN BIT(7) -#define ACRC BIT(8) -#define CFENDFORM BIT(9) -#define ICV BIT(10) - -#define AAP BIT(0) -#define APM BIT(1) -#define AM BIT(2) -#define AB BIT(3) -#define ADD3 BIT(4) -#define APWRMGT BIT(5) -#define CBSSID BIT(6) -#define CBSSID_DATA BIT(6) -#define CBSSID_BCN BIT(7) -#define ACRC32 BIT(8) -#define AICV BIT(9) -#define ADF BIT(11) -#define ACF BIT(12) -#define AMF BIT(13) -#define HTC_LOC_CTRL BIT(14) -#define UC_DATA_EN BIT(16) -#define BM_DATA_EN BIT(17) -#define MFBEN BIT(22) -#define LSIGEN BIT(23) -#define ENMBID BIT(24) -#define APP_BASSN BIT(27) -#define APP_PHYSTS BIT(28) -#define APP_ICV BIT(29) -#define APP_MIC BIT(30) -#define APP_FCS BIT(31) - -#define _MIN_SPACE(x) ((x) & 0x7) -#define _SHORT_GI_PADDING(x) (((x) & 0x1F) << 3) - -#define RXERR_TYPE_OFDM_PPDU 0 -#define RXERR_TYPE_OFDM_FALSE_ALARM 1 -#define RXERR_TYPE_OFDM_MPDU_OK 2 -#define RXERR_TYPE_OFDM_MPDU_FAIL 3 -#define RXERR_TYPE_CCK_PPDU 4 -#define RXERR_TYPE_CCK_FALSE_ALARM 5 -#define RXERR_TYPE_CCK_MPDU_OK 6 -#define RXERR_TYPE_CCK_MPDU_FAIL 7 -#define RXERR_TYPE_HT_PPDU 8 -#define RXERR_TYPE_HT_FALSE_ALARM 9 -#define RXERR_TYPE_HT_MPDU_TOTAL 10 -#define RXERR_TYPE_HT_MPDU_OK 11 -#define RXERR_TYPE_HT_MPDU_FAIL 12 -#define RXERR_TYPE_RX_FULL_DROP 15 - -#define RXERR_COUNTER_MASK 0xFFFFF -#define RXERR_RPT_RST BIT(27) -#define _RXERR_RPT_SEL(type) ((type) << 28) - -#define SCR_TXUSEDK BIT(0) -#define SCR_RXUSEDK BIT(1) -#define SCR_TXENCENABLE BIT(2) -#define SCR_RXDECENABLE BIT(3) -#define SCR_SKBYA2 BIT(4) -#define SCR_NOSKMC BIT(5) -#define SCR_TXBCUSEDK BIT(6) -#define SCR_RXBCUSEDK BIT(7) - -#define XCLK_VLD BIT(0) -#define ACLK_VLD BIT(1) -#define UCLK_VLD BIT(2) -#define PCLK_VLD BIT(3) -#define PCIRSTB BIT(4) -#define V15_VLD BIT(5) -#define TRP_B15V_EN BIT(7) -#define SIC_IDLE BIT(8) -#define BD_MAC2 BIT(9) -#define BD_MAC1 BIT(10) -#define IC_MACPHY_MODE BIT(11) -#define BT_FUNC BIT(16) -#define VENDOR_ID BIT(19) -#define PAD_HWPD_IDN BIT(22) -#define TRP_VAUX_EN BIT(23) -#define TRP_BT_EN BIT(24) -#define BD_PKG_SEL BIT(25) -#define BD_HCI_SEL BIT(26) -#define TYPE_ID BIT(27) - -#define USB_IS_HIGH_SPEED 0 -#define USB_IS_FULL_SPEED 1 -#define USB_SPEED_MASK BIT(5) - -#define USB_NORMAL_SIE_EP_MASK 0xF -#define USB_NORMAL_SIE_EP_SHIFT 4 - -#define USB_TEST_EP_MASK 0x30 -#define USB_TEST_EP_SHIFT 4 - -#define USB_AGG_EN BIT(3) - -#define MAC_ADDR_LEN 6 -#define LAST_ENTRY_OF_TX_PKT_BUFFER 255 - -#define POLLING_LLT_THRESHOLD 20 -#define POLLING_READY_TIMEOUT_COUNT 3000 - -#define MAX_MSS_DENSITY_2T 0x13 -#define MAX_MSS_DENSITY_1T 0x0A - -#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) -#define EPROM_CMD_CONFIG 0x3 -#define EPROM_CMD_LOAD 1 - -#define HWSET_MAX_SIZE_92S HWSET_MAX_SIZE - -#define HAL_8192C_HW_GPIO_WPS_BIT BIT(2) - -#define RA_LSSIWRITE_8821A 0xc90 -#define RB_LSSIWRITE_8821A 0xe90 - -#define RA_PIREAD_8821A 0xd04 -#define RB_PIREAD_8821A 0xd44 -#define RA_SIREAD_8821A 0xd08 -#define RB_SIREAD_8821A 0xd48 - -#define RPMAC_RESET 0x100 -#define RPMAC_TXSTART 0x104 -#define RPMAC_TXLEGACYSIG 0x108 -#define RPMAC_TXHTSIG1 0x10c -#define RPMAC_TXHTSIG2 0x110 -#define RPMAC_PHYDEBUG 0x114 -#define RPMAC_TXPACKETNUM 0x118 -#define RPMAC_TXIDLE 0x11c -#define RPMAC_TXMACHEADER0 0x120 -#define RPMAC_TXMACHEADER1 0x124 -#define RPMAC_TXMACHEADER2 0x128 -#define RPMAC_TXMACHEADER3 0x12c -#define RPMAC_TXMACHEADER4 0x130 -#define RPMAC_TXMACHEADER5 0x134 -#define RPMAC_TXDADATYPE 0x138 -#define RPMAC_TXRANDOMSEED 0x13c -#define RPMAC_CCKPLCPPREAMBLE 0x140 -#define RPMAC_CCKPLCPHEADER 0x144 -#define RPMAC_CCKCRC16 0x148 -#define RPMAC_OFDMRXCRC32OK 0x170 -#define RPMAC_OFDMRXCRC32ER 0x174 -#define RPMAC_OFDMRXPARITYER 0x178 -#define RPMAC_OFDMRXCRC8ER 0x17c -#define RPMAC_CCKCRXRC16ER 0x180 -#define RPMAC_CCKCRXRC32ER 0x184 -#define RPMAC_CCKCRXRC32OK 0x188 -#define RPMAC_TXSTATUS 0x18c - -#define RFPGA0_RFMOD 0x800 - -#define RFPGA0_TXINFO 0x804 -#define RFPGA0_PSDFUNCTION 0x808 - -#define RFPGA0_TXGAINSTAGE 0x80c - -#define RFPGA0_RFTIMING1 0x810 -#define RFPGA0_RFTIMING2 0x814 - -#define RFPGA0_XA_HSSIPARAMETER1 0x820 -#define RFPGA0_XA_HSSIPARAMETER2 0x824 -#define RFPGA0_XB_HSSIPARAMETER1 0x828 -#define RFPGA0_XB_HSSIPARAMETER2 0x82c -#define RCCAONSEC 0x838 - -#define RFPGA0_XA_LSSIPARAMETER 0x840 -#define RFPGA0_XB_LSSIPARAMETER 0x844 -#define RL1PEAKTH 0x848 - -#define RFPGA0_RFWAKEUPPARAMETER 0x850 -#define RFPGA0_RFSLEEPUPPARAMETER 0x854 - -#define RFPGA0_XAB_SWITCHCONTROL 0x858 -#define RFPGA0_XCD_SWITCHCONTROL 0x85c - -#define RFPGA0_XA_RFINTERFACEOE 0x860 -#define RFC_AREA 0x860 -#define RFPGA0_XB_RFINTERFACEOE 0x864 - -#define RFPGA0_XAB_RFINTERFACESW 0x870 -#define RFPGA0_XCD_RFINTERFACESW 0x874 - -#define RFPGA0_XAB_RFPARAMETER 0x878 -#define RFPGA0_XCD_RFPARAMETER 0x87c - -#define RFPGA0_ANALOGPARAMETER1 0x880 -#define RFPGA0_ANALOGPARAMETER2 0x884 -#define RFPGA0_ANALOGPARAMETER3 0x888 -#define RFPGA0_ANALOGPARAMETER4 0x88c - -#define RFPGA0_XA_LSSIREADBACK 0x8a0 -#define RFPGA0_XB_LSSIREADBACK 0x8a4 -#define RFPGA0_XC_LSSIREADBACK 0x8a8 -#define RRFMOD 0x8ac -#define RHSSIREAD_8821AE 0x8b0 - -#define RFPGA0_PSDREPORT 0x8b4 -#define TRANSCEIVEA_HSPI_READBACK 0x8b8 -#define TRANSCEIVEB_HSPI_READBACK 0x8bc -#define RADC_BUF_CLK 0x8c4 -#define RFPGA0_XAB_RFINTERFACERB 0x8e0 -#define RFPGA0_XCD_RFINTERFACERB 0x8e4 - -#define RFPGA1_RFMOD 0x900 - -#define RFPGA1_TXBLOCK 0x904 -#define RFPGA1_DEBUGSELECT 0x908 -#define RFPGA1_TXINFO 0x90c - -#define RCCK_SYSTEM 0xa00 -#define BCCK_SYSTEM 0x10 - -#define RCCK0_AFESETTING 0xa04 -#define RCCK0_CCA 0xa08 - -#define RCCK0_RXAGC1 0xa0c -#define RCCK0_RXAGC2 0xa10 - -#define RCCK0_RXHP 0xa14 - -#define RCCK0_DSPPARAMETER1 0xa18 -#define RCCK0_DSPPARAMETER2 0xa1c - -#define RCCK0_TXFILTER1 0xa20 -#define RCCK0_TXFILTER2 0xa24 -#define RCCK0_DEBUGPORT 0xa28 -#define RCCK0_FALSEALARMREPORT 0xa2c -#define RCCK0_TRSSIREPORT 0xa50 -#define RCCK0_RXREPORT 0xa54 -#define RCCK0_FACOUNTERLOWER 0xa5c -#define RCCK0_FACOUNTERUPPER 0xa58 -#define RCCK0_CCA_CNT 0xa60 - -/* PageB(0xB00) */ -#define RPDP_ANTA 0xb00 -#define RPDP_ANTA_4 0xb04 -#define RPDP_ANTA_8 0xb08 -#define RPDP_ANTA_C 0xb0c -#define RPDP_ANTA_10 0xb10 -#define RPDP_ANTA_14 0xb14 -#define RPDP_ANTA_18 0xb18 -#define RPDP_ANTA_1C 0xb1c -#define RPDP_ANTA_20 0xb20 -#define RPDP_ANTA_24 0xb24 - -#define RCONFIG_PMPD_ANTA 0xb28 -#define RCONFIG_RAM64x16 0xb2c - -#define RBNDA 0xb30 -#define RHSSIPAR 0xb34 - -#define RCONFIG_ANTA 0xb68 -#define RCONFIG_ANTB 0xb6c - -#define RPDP_ANTB 0xb70 -#define RPDP_ANTB_4 0xb74 -#define RPDP_ANTB_8 0xb78 -#define RPDP_ANTB_C 0xb7c -#define RPDP_ANTB_10 0xb80 -#define RPDP_ANTB_14 0xb84 -#define RPDP_ANTB_18 0xb88 -#define RPDP_ANTB_1C 0xb8c -#define RPDP_ANTB_20 0xb90 -#define RPDP_ANTB_24 0xb94 - -#define RCONFIG_PMPD_ANTB 0xb98 - -#define RBNDB 0xba0 - -#define RAPK 0xbd8 -#define RPM_RX0_ANTA 0xbdc -#define RPM_RX1_ANTA 0xbe0 -#define RPM_RX2_ANTA 0xbe4 -#define RPM_RX3_ANTA 0xbe8 -#define RPM_RX0_ANTB 0xbec -#define RPM_RX1_ANTB 0xbf0 -#define RPM_RX2_ANTB 0xbf4 -#define RPM_RX3_ANTB 0xbf8 - -/*RSSI Dump*/ -#define RA_RSSI_DUMP 0xBF0 -#define RB_RSSI_DUMP 0xBF1 -#define RS1_RX_EVM_DUMP 0xBF4 -#define RS2_RX_EVM_DUMP 0xBF5 -#define RA_RX_SNR_DUMP 0xBF6 -#define RB_RX_SNR_DUMP 0xBF7 -#define RA_CFO_SHORT_DUMP 0xBF8 -#define RB_CFO_SHORT_DUMP 0xBFA -#define RA_CFO_LONG_DUMP 0xBEC -#define RB_CFO_LONG_DUMP 0xBEE - -/*Page C*/ -#define ROFDM0_LSTF 0xc00 - -#define ROFDM0_TRXPATHENABLE 0xc04 -#define ROFDM0_TRMUXPAR 0xc08 -#define ROFDM0_TRSWISOLATION 0xc0c - -#define ROFDM0_XARXAFE 0xc10 -#define ROFDM0_XARXIQIMBALANCE 0xc14 -#define ROFDM0_XBRXAFE 0xc18 -#define ROFDM0_XBRXIQIMBALANCE 0xc1c -#define ROFDM0_XCRXAFE 0xc20 -#define ROFDM0_XCRXIQIMBANLANCE 0xc24 -#define ROFDM0_XDRXAFE 0xc28 -#define ROFDM0_XDRXIQIMBALANCE 0xc2c - -#define ROFDM0_RXDETECTOR1 0xc30 -#define ROFDM0_RXDETECTOR2 0xc34 -#define ROFDM0_RXDETECTOR3 0xc38 -#define ROFDM0_RXDETECTOR4 0xc3c - -#define ROFDM0_RXDSP 0xc40 -#define ROFDM0_CFOANDDAGC 0xc44 -#define ROFDM0_CCADROPTHRESHOLD 0xc48 -#define ROFDM0_ECCATHRESHOLD 0xc4c - -#define ROFDM0_XAAGCCORE1 0xc50 -#define ROFDM0_XAAGCCORE2 0xc54 -#define ROFDM0_XBAGCCORE1 0xc58 -#define ROFDM0_XBAGCCORE2 0xc5c -#define ROFDM0_XCAGCCORE1 0xc60 -#define ROFDM0_XCAGCCORE2 0xc64 -#define ROFDM0_XDAGCCORE1 0xc68 -#define ROFDM0_XDAGCCORE2 0xc6c - -#define ROFDM0_AGCPARAMETER1 0xc70 -#define ROFDM0_AGCPARAMETER2 0xc74 -#define ROFDM0_AGCRSSITABLE 0xc78 -#define ROFDM0_HTSTFAGC 0xc7c - -#define ROFDM0_XATXIQIMBALANCE 0xc80 -#define ROFDM0_XATXAFE 0xc84 -#define ROFDM0_XBTXIQIMBALANCE 0xc88 -#define ROFDM0_XBTXAFE 0xc8c -#define ROFDM0_XCTXIQIMBALANCE 0xc90 -#define ROFDM0_XCTXAFE 0xc94 -#define ROFDM0_XDTXIQIMBALANCE 0xc98 -#define ROFDM0_XDTXAFE 0xc9c - -#define ROFDM0_RXIQEXTANTA 0xca0 -#define ROFDM0_TXCOEFF1 0xca4 -#define ROFDM0_TXCOEFF2 0xca8 -#define ROFDM0_TXCOEFF3 0xcac -#define ROFDM0_TXCOEFF4 0xcb0 -#define ROFDM0_TXCOEFF5 0xcb4 -#define ROFDM0_TXCOEFF6 0xcb8 - -/*Path_A RFE cotrol */ -#define RA_RFE_CTRL_8812 0xcb8 -/*Path_B RFE control*/ -#define RB_RFE_CTRL_8812 0xeb8 - -#define ROFDM0_RXHPPARAMETER 0xce0 -#define ROFDM0_TXPSEUDONOISEWGT 0xce4 -#define ROFDM0_FRAMESYNC 0xcf0 -#define ROFDM0_DFSREPORT 0xcf4 - -#define ROFDM1_LSTF 0xd00 -#define ROFDM1_TRXPATHENABLE 0xd04 - -#define ROFDM1_CF0 0xd08 -#define ROFDM1_CSI1 0xd10 -#define ROFDM1_SBD 0xd14 -#define ROFDM1_CSI2 0xd18 -#define ROFDM1_CFOTRACKING 0xd2c -#define ROFDM1_TRXMESAURE1 0xd34 -#define ROFDM1_INTFDET 0xd3c -#define ROFDM1_PSEUDONOISESTATEAB 0xd50 -#define ROFDM1_PSEUDONOISESTATECD 0xd54 -#define ROFDM1_RXPSEUDONOISEWGT 0xd58 - -#define ROFDM_PHYCOUNTER1 0xda0 -#define ROFDM_PHYCOUNTER2 0xda4 -#define ROFDM_PHYCOUNTER3 0xda8 - -#define ROFDM_SHORTCFOAB 0xdac -#define ROFDM_SHORTCFOCD 0xdb0 -#define ROFDM_LONGCFOAB 0xdb4 -#define ROFDM_LONGCFOCD 0xdb8 -#define ROFDM_TAILCF0AB 0xdbc -#define ROFDM_TAILCF0CD 0xdc0 -#define ROFDM_PWMEASURE1 0xdc4 -#define ROFDM_PWMEASURE2 0xdc8 -#define ROFDM_BWREPORT 0xdcc -#define ROFDM_AGCREPORT 0xdd0 -#define ROFDM_RXSNR 0xdd4 -#define ROFDM_RXEVMCSI 0xdd8 -#define ROFDM_SIGREPORT 0xddc - -#define RTXAGC_A_CCK11_CCK1 0xc20 -#define RTXAGC_A_OFDM18_OFDM6 0xc24 -#define RTXAGC_A_OFDM54_OFDM24 0xc28 -#define RTXAGC_A_MCS03_MCS00 0xc2c -#define RTXAGC_A_MCS07_MCS04 0xc30 -#define RTXAGC_A_MCS11_MCS08 0xc34 -#define RTXAGC_A_MCS15_MCS12 0xc38 -#define RTXAGC_A_NSS1INDEX3_NSS1INDEX0 0xc3c -#define RTXAGC_A_NSS1INDEX7_NSS1INDEX4 0xc40 -#define RTXAGC_A_NSS2INDEX1_NSS1INDEX8 0xc44 -#define RTXAGC_A_NSS2INDEX5_NSS2INDEX2 0xc48 -#define RTXAGC_A_NSS2INDEX9_NSS2INDEX6 0xc4c -#define RTXAGC_B_CCK11_CCK1 0xe20 -#define RTXAGC_B_OFDM18_OFDM6 0xe24 -#define RTXAGC_B_OFDM54_OFDM24 0xe28 -#define RTXAGC_B_MCS03_MCS00 0xe2c -#define RTXAGC_B_MCS07_MCS04 0xe30 -#define RTXAGC_B_MCS11_MCS08 0xe34 -#define RTXAGC_B_MCS15_MCS12 0xe38 -#define RTXAGC_B_NSS1INDEX3_NSS1INDEX0 0xe3c -#define RTXAGC_B_NSS1INDEX7_NSS1INDEX4 0xe40 -#define RTXAGC_B_NSS2INDEX1_NSS1INDEX8 0xe44 -#define RTXAGC_B_NSS2INDEX5_NSS2INDEX2 0xe48 -#define RTXAGC_B_NSS2INDEX9_NSS2INDEX6 0xe4c - -#define RA_TXPWRTRAING 0xc54 -#define RB_TXPWRTRAING 0xe54 - -#define RFPGA0_IQK 0xe28 -#define RTX_IQK_TONE_A 0xe30 -#define RRX_IQK_TONE_A 0xe34 -#define RTX_IQK_PI_A 0xe38 -#define RRX_IQK_PI_A 0xe3c - -#define RTX_IQK 0xe40 -#define RRX_IQK 0xe44 -#define RIQK_AGC_PTS 0xe48 -#define RIQK_AGC_RSP 0xe4c -#define RTX_IQK_TONE_B 0xe50 -#define RRX_IQK_TONE_B 0xe54 -#define RTX_IQK_PI_B 0xe58 -#define RRX_IQK_PI_B 0xe5c -#define RIQK_AGC_CONT 0xe60 - -#define RBLUE_TOOTH 0xe6c -#define RRX_WAIT_CCA 0xe70 -#define RTX_CCK_RFON 0xe74 -#define RTX_CCK_BBON 0xe78 -#define RTX_OFDM_RFON 0xe7c -#define RTX_OFDM_BBON 0xe80 -#define RTX_TO_RX 0xe84 -#define RTX_TO_TX 0xe88 -#define RRX_CCK 0xe8c - -#define RTX_POWER_BEFORE_IQK_A 0xe94 -#define RTX_POWER_AFTER_IQK_A 0xe9c - -#define RRX_POWER_BEFORE_IQK_A 0xea0 -#define RRX_POWER_BEFORE_IQK_A_2 0xea4 -#define RRX_POWER_AFTER_IQK_A 0xea8 -#define RRX_POWER_AFTER_IQK_A_2 0xeac - -#define RTX_POWER_BEFORE_IQK_B 0xeb4 -#define RTX_POWER_AFTER_IQK_B 0xebc - -#define RRX_POER_BEFORE_IQK_B 0xec0 -#define RRX_POER_BEFORE_IQK_B_2 0xec4 -#define RRX_POWER_AFTER_IQK_B 0xec8 -#define RRX_POWER_AFTER_IQK_B_2 0xecc - -#define RRX_OFDM 0xed0 -#define RRX_WAIT_RIFS 0xed4 -#define RRX_TO_RX 0xed8 -#define RSTANDBY 0xedc -#define RSLEEP 0xee0 -#define RPMPD_ANAEN 0xeec - -#define RZEBRA1_HSSIENABLE 0x0 -#define RZEBRA1_TRXENABLE1 0x1 -#define RZEBRA1_TRXENABLE2 0x2 -#define RZEBRA1_AGC 0x4 -#define RZEBRA1_CHARGEPUMP 0x5 -#define RZEBRA1_CHANNEL 0x7 - -#define RZEBRA1_TXGAIN 0x8 -#define RZEBRA1_TXLPF 0x9 -#define RZEBRA1_RXLPF 0xb -#define RZEBRA1_RXHPFCORNER 0xc - -#define RGLOBALCTRL 0 -#define RRTL8256_TXLPF 19 -#define RRTL8256_RXLPF 11 -#define RRTL8258_TXLPF 0x11 -#define RRTL8258_RXLPF 0x13 -#define RRTL8258_RSSILPF 0xa - -#define RF_AC 0x00 - -#define RF_IQADJ_G1 0x01 -#define RF_IQADJ_G2 0x02 -#define RF_POW_TRSW 0x05 - -#define RF_GAIN_RX 0x06 -#define RF_GAIN_TX 0x07 - -#define RF_TXM_IDAC 0x08 -#define RF_BS_IQGEN 0x0F - -#define RF_MODE1 0x10 -#define RF_MODE2 0x11 - -#define RF_RX_AGC_HP 0x12 -#define RF_TX_AGC 0x13 -#define RF_BIAS 0x14 -#define RF_IPA 0x15 -#define RF_POW_ABILITY 0x17 -#define RF_MODE_AG 0x18 -#define RRFCHANNEL 0x18 -#define RF_CHNLBW 0x18 -#define RF_TOP 0x19 - -#define RF_RX_G1 0x1A -#define RF_RX_G2 0x1B - -#define RF_RX_BB2 0x1C -#define RF_RX_BB1 0x1D - -#define RF_RCK1 0x1E -#define RF_RCK2 0x1F - -#define RF_TX_G1 0x20 -#define RF_TX_G2 0x21 -#define RF_TX_G3 0x22 - -#define RF_TX_BB1 0x23 -#define RF_T_METER 0x24 -#define RF_T_METER_88E 0x42 -#define RF_T_METER_8812A 0x42 - -#define RF_SYN_G1 0x25 -#define RF_SYN_G2 0x26 -#define RF_SYN_G3 0x27 -#define RF_SYN_G4 0x28 -#define RF_SYN_G5 0x29 -#define RF_SYN_G6 0x2A -#define RF_SYN_G7 0x2B -#define RF_SYN_G8 0x2C - -#define RF_RCK_OS 0x30 -#define RF_TXPA_G1 0x31 -#define RF_TXPA_G2 0x32 -#define RF_TXPA_G3 0x33 - -#define RF_TX_BIAS_A 0x35 -#define RF_TX_BIAS_D 0x36 -#define RF_LOBF_9 0x38 -#define RF_RXRF_A3 0x3C -#define RF_TRSW 0x3F - -#define RF_TXRF_A2 0x41 -#define RF_TXPA_G4 0x46 -#define RF_TXPA_A4 0x4B - -#define RF_APK 0x63 - -#define RF_WE_LUT 0xEF - -#define BBBRESETB 0x100 -#define BGLOBALRESETB 0x200 -#define BOFDMTXSTART 0x4 -#define BCCKTXSTART 0x8 -#define BCRC32DEBUG 0x100 -#define BPMACLOOPBACK 0x10 -#define BTXLSIG 0xffffff -#define BOFDMTXRATE 0xf -#define BOFDMTXRESERVED 0x10 -#define BOFDMTXLENGTH 0x1ffe0 -#define BOFDMTXPARITY 0x20000 -#define BTXHTSIG1 0xffffff -#define BTXHTMCSRATE 0x7f -#define BTXHTBW 0x80 -#define BTXHTLENGTH 0xffff00 -#define BTXHTSIG2 0xffffff -#define BTXHTSMOOTHING 0x1 -#define BTXHTSOUNDING 0x2 -#define BTXHTRESERVED 0x4 -#define BTXHTAGGREATION 0x8 -#define BTXHTSTBC 0x30 -#define BTXHTADVANCECODING 0x40 -#define BTXHTSHORTGI 0x80 -#define BTXHTNUMBERHT_LTF 0x300 -#define BTXHTCRC8 0x3fc00 -#define BCOUNTERRESET 0x10000 -#define BNUMOFOFDMTX 0xffff -#define BNUMOFCCKTX 0xffff0000 -#define BTXIDLEINTERVAL 0xffff -#define BOFDMSERVICE 0xffff0000 -#define BTXMACHEADER 0xffffffff -#define BTXDATAINIT 0xff -#define BTXHTMODE 0x100 -#define BTXDATATYPE 0x30000 -#define BTXRANDOMSEED 0xffffffff -#define BCCKTXPREAMBLE 0x1 -#define BCCKTXSFD 0xffff0000 -#define BCCKTXSIG 0xff -#define BCCKTXSERVICE 0xff00 -#define BCCKLENGTHEXT 0x8000 -#define BCCKTXLENGHT 0xffff0000 -#define BCCKTXCRC16 0xffff -#define BCCKTXSTATUS 0x1 -#define BOFDMTXSTATUS 0x2 -#define IS_BB_REG_OFFSET_92S(__offset) \ - ((__offset >= 0x800) && (__offset <= 0xfff)) - -#define BRFMOD 0x1 -#define BJAPANMODE 0x2 -#define BCCKTXSC 0x30 -/* Block & Path enable*/ -#define ROFDMCCKEN 0x808 -#define BCCKEN 0x10000000 -#define BOFDMEN 0x20000000 -/* Rx antenna*/ -#define RRXPATH 0x808 -#define BRXPATH 0xff -/* Tx antenna*/ -#define RTXPATH 0x80c -#define BTXPATH 0x0fffffff -/* for cck rx path selection*/ -#define RCCK_RX 0xa04 -#define BCCK_RX 0x0c000000 -/* Use LSIG for VHT length*/ -#define RVHTLEN_USE_LSIG 0x8c3 - -#define BOFDMRXADCPHASE 0x10000 -#define BOFDMTXDACPHASE 0x40000 -#define BXATXAGC 0x3f - -#define BXBTXAGC 0xf00 -#define BXCTXAGC 0xf000 -#define BXDTXAGC 0xf0000 - -#define BPASTART 0xf0000000 -#define BTRSTART 0x00f00000 -#define BRFSTART 0x0000f000 -#define BBBSTART 0x000000f0 -#define BBBCCKSTART 0x0000000f -#define BPAEND 0xf -#define BTREND 0x0f000000 -#define BRFEND 0x000f0000 -#define BCCAMASK 0x000000f0 -#define BR2RCCAMASK 0x00000f00 -#define BHSSI_R2TDELAY 0xf8000000 -#define BHSSI_T2RDELAY 0xf80000 -#define BCONTXHSSI 0x400 -#define BIGFROMCCK 0x200 -#define BAGCADDRESS 0x3f -#define BRXHPTX 0x7000 -#define BRXHP2RX 0x38000 -#define BRXHPCCKINI 0xc0000 -#define BAGCTXCODE 0xc00000 -#define BAGCRXCODE 0x300000 - -#define B3WIREDATALENGTH 0x800 -#define B3WIREADDREAALENGTH 0x400 - -#define B3WIRERFPOWERDOWN 0x1 -#define B5GPAPEPOLARITY 0x40000000 -#define B2GPAPEPOLARITY 0x80000000 -#define BRFSW_TXDEFAULTANT 0x3 -#define BRFSW_TXOPTIONANT 0x30 -#define BRFSW_RXDEFAULTANT 0x300 -#define BRFSW_RXOPTIONANT 0x3000 -#define BRFSI_3WIREDATA 0x1 -#define BRFSI_3WIRECLOCK 0x2 -#define BRFSI_3WIRELOAD 0x4 -#define BRFSI_3WIRERW 0x8 -#define BRFSI_3WIRE 0xf - -#define BRFSI_RFENV 0x10 - -#define BRFSI_TRSW 0x20 -#define BRFSI_TRSWB 0x40 -#define BRFSI_ANTSW 0x100 -#define BRFSI_ANTSWB 0x200 -#define BRFSI_PAPE 0x400 -#define BRFSI_PAPE5G 0x800 -#define BBANDSELECT 0x1 -#define BHTSIG2_GI 0x80 -#define BHTSIG2_SMOOTHING 0x01 -#define BHTSIG2_SOUNDING 0x02 -#define BHTSIG2_AGGREATON 0x08 -#define BHTSIG2_STBC 0x30 -#define BHTSIG2_ADVCODING 0x40 -#define BHTSIG2_NUMOFHTLTF 0x300 -#define BHTSIG2_CRC8 0x3fc -#define BHTSIG1_MCS 0x7f -#define BHTSIG1_BANDWIDTH 0x80 -#define BHTSIG1_HTLENGTH 0xffff -#define BLSIG_RATE 0xf -#define BLSIG_RESERVED 0x10 -#define BLSIG_LENGTH 0x1fffe -#define BLSIG_PARITY 0x20 -#define BCCKRXPHASE 0x4 - -#define BLSSIREADADDRESS 0x7f800000 -#define BLSSIREADEDGE 0x80000000 - -#define BLSSIREADBACKDATA 0xfffff - -#define BLSSIREADOKFLAG 0x1000 -#define BCCKSAMPLERATE 0x8 -#define BREGULATOR0STANDBY 0x1 -#define BREGULATORPLLSTANDBY 0x2 -#define BREGULATOR1STANDBY 0x4 -#define BPLLPOWERUP 0x8 -#define BDPLLPOWERUP 0x10 -#define BDA10POWERUP 0x20 -#define BAD7POWERUP 0x200 -#define BDA6POWERUP 0x2000 -#define BXTALPOWERUP 0x4000 -#define B40MDCLKPOWERUP 0x8000 -#define BDA6DEBUGMODE 0x20000 -#define BDA6SWING 0x380000 - -#define BADCLKPHASE 0x4000000 -#define B80MCLKDELAY 0x18000000 -#define BAFEWATCHDOGENABLE 0x20000000 - -#define BXTALCAP01 0xc0000000 -#define BXTALCAP23 0x3 -#define BXTALCAP92X 0x0f000000 -#define BXTALCAP 0x0f000000 - -#define BINTDIFCLKENABLE 0x400 -#define BEXTSIGCLKENABLE 0x800 -#define BBANDGAP_MBIAS_POWERUP 0x10000 -#define BAD11SH_GAIN 0xc0000 -#define BAD11NPUT_RANGE 0x700000 -#define BAD110P_CURRENT 0x3800000 -#define BLPATH_LOOPBACK 0x4000000 -#define BQPATH_LOOPBACK 0x8000000 -#define BAFE_LOOPBACK 0x10000000 -#define BDA10_SWING 0x7e0 -#define BDA10_REVERSE 0x800 -#define BDA_CLK_SOURCE 0x1000 -#define BDA7INPUT_RANGE 0x6000 -#define BDA7_GAIN 0x38000 -#define BDA7OUTPUT_CM_MODE 0x40000 -#define BDA7INPUT_CM_MODE 0x380000 -#define BDA7CURRENT 0xc00000 -#define BREGULATOR_ADJUST 0x7000000 -#define BAD11POWERUP_ATTX 0x1 -#define BDA10PS_ATTX 0x10 -#define BAD11POWERUP_ATRX 0x100 -#define BDA10PS_ATRX 0x1000 -#define BCCKRX_AGC_FORMAT 0x200 -#define BPSDFFT_SAMPLE_POINT 0xc000 -#define BPSD_AVERAGE_NUM 0x3000 -#define BIQPATH_CONTROL 0xc00 -#define BPSD_FREQ 0x3ff -#define BPSD_ANTENNA_PATH 0x30 -#define BPSD_IQ_SWITCH 0x40 -#define BPSD_RX_TRIGGER 0x400000 -#define BPSD_TX_TRIGGER 0x80000000 -#define BPSD_SINE_TONE_SCALE 0x7f000000 -#define BPSD_REPORT 0xffff - -#define BOFDM_TXSC 0x30000000 -#define BCCK_TXON 0x1 -#define BOFDM_TXON 0x2 -#define BDEBUG_PAGE 0xfff -#define BDEBUG_ITEM 0xff -#define BANTL 0x10 -#define BANT_NONHT 0x100 -#define BANT_HT1 0x1000 -#define BANT_HT2 0x10000 -#define BANT_HT1S1 0x100000 -#define BANT_NONHTS1 0x1000000 - -#define BCCK_BBMODE 0x3 -#define BCCK_TXPOWERSAVING 0x80 -#define BCCK_RXPOWERSAVING 0x40 - -#define BCCK_SIDEBAND 0x10 - -#define BCCK_SCRAMBLE 0x8 -#define BCCK_ANTDIVERSITY 0x8000 -#define BCCK_CARRIER_RECOVERY 0x4000 -#define BCCK_TXRATE 0x3000 -#define BCCK_DCCANCEL 0x0800 -#define BCCK_ISICANCEL 0x0400 -#define BCCK_MATCH_FILTER 0x0200 -#define BCCK_EQUALIZER 0x0100 -#define BCCK_PREAMBLE_DETECT 0x800000 -#define BCCK_FAST_FALSECCA 0x400000 -#define BCCK_CH_ESTSTART 0x300000 -#define BCCK_CCA_COUNT 0x080000 -#define BCCK_CS_LIM 0x070000 -#define BCCK_BIST_MODE 0x80000000 -#define BCCK_CCAMASK 0x40000000 -#define BCCK_TX_DAC_PHASE 0x4 -#define BCCK_RX_ADC_PHASE 0x20000000 -#define BCCKR_CP_MODE 0x0100 -#define BCCK_TXDC_OFFSET 0xf0 -#define BCCK_RXDC_OFFSET 0xf -#define BCCK_CCA_MODE 0xc000 -#define BCCK_FALSECS_LIM 0x3f00 -#define BCCK_CS_RATIO 0xc00000 -#define BCCK_CORGBIT_SEL 0x300000 -#define BCCK_PD_LIM 0x0f0000 -#define BCCK_NEWCCA 0x80000000 -#define BCCK_RXHP_OF_IG 0x8000 -#define BCCK_RXIG 0x7f00 -#define BCCK_LNA_POLARITY 0x800000 -#define BCCK_RX1ST_BAIN 0x7f0000 -#define BCCK_RF_EXTEND 0x20000000 -#define BCCK_RXAGC_SATLEVEL 0x1f000000 -#define BCCK_RXAGC_SATCOUNT 0xe0 -#define BCCKRXRFSETTLE 0x1f -#define BCCK_FIXED_RXAGC 0x8000 -#define BCCK_ANTENNA_POLARITY 0x2000 -#define BCCK_TXFILTER_TYPE 0x0c00 -#define BCCK_RXAGC_REPORTTYPE 0x0300 -#define BCCK_RXDAGC_EN 0x80000000 -#define BCCK_RXDAGC_PERIOD 0x20000000 -#define BCCK_RXDAGC_SATLEVEL 0x1f000000 -#define BCCK_TIMING_RECOVERY 0x800000 -#define BCCK_TXC0 0x3f0000 -#define BCCK_TXC1 0x3f000000 -#define BCCK_TXC2 0x3f -#define BCCK_TXC3 0x3f00 -#define BCCK_TXC4 0x3f0000 -#define BCCK_TXC5 0x3f000000 -#define BCCK_TXC6 0x3f -#define BCCK_TXC7 0x3f00 -#define BCCK_DEBUGPORT 0xff0000 -#define BCCK_DAC_DEBUG 0x0f000000 -#define BCCK_FALSEALARM_ENABLE 0x8000 -#define BCCK_FALSEALARM_READ 0x4000 -#define BCCK_TRSSI 0x7f -#define BCCK_RXAGC_REPORT 0xfe -#define BCCK_RXREPORT_ANTSEL 0x80000000 -#define BCCK_RXREPORT_MFOFF 0x40000000 -#define BCCK_RXREPORT_SQLOSS 0x20000000 -#define BCCK_RXREPORT_PKTLOSS 0x10000000 -#define BCCK_RXREPORT_LOCKEDBIT 0x08000000 -#define BCCK_RXREPORT_RATEERROR 0x04000000 -#define BCCK_RXREPORT_RXRATE 0x03000000 -#define BCCK_RXFA_COUNTER_LOWER 0xff -#define BCCK_RXFA_COUNTER_UPPER 0xff000000 -#define BCCK_RXHPAGC_START 0xe000 -#define BCCK_RXHPAGC_FINAL 0x1c00 -#define BCCK_RXFALSEALARM_ENABLE 0x8000 -#define BCCK_FACOUNTER_FREEZE 0x4000 -#define BCCK_TXPATH_SEL 0x10000000 -#define BCCK_DEFAULT_RXPATH 0xc000000 -#define BCCK_OPTION_RXPATH 0x3000000 - -#define BNUM_OFSTF 0x3 -#define BSHIFT_L 0xc0 -#define BGI_TH 0xc -#define BRXPATH_A 0x1 -#define BRXPATH_B 0x2 -#define BRXPATH_C 0x4 -#define BRXPATH_D 0x8 -#define BTXPATH_A 0x1 -#define BTXPATH_B 0x2 -#define BTXPATH_C 0x4 -#define BTXPATH_D 0x8 -#define BTRSSI_FREQ 0x200 -#define BADC_BACKOFF 0x3000 -#define BDFIR_BACKOFF 0xc000 -#define BTRSSI_LATCH_PHASE 0x10000 -#define BRX_LDC_OFFSET 0xff -#define BRX_QDC_OFFSET 0xff00 -#define BRX_DFIR_MODE 0x1800000 -#define BRX_DCNF_TYPE 0xe000000 -#define BRXIQIMB_A 0x3ff -#define BRXIQIMB_B 0xfc00 -#define BRXIQIMB_C 0x3f0000 -#define BRXIQIMB_D 0xffc00000 -#define BDC_DC_NOTCH 0x60000 -#define BRXNB_NOTCH 0x1f000000 -#define BPD_TH 0xf -#define BPD_TH_OPT2 0xc000 -#define BPWED_TH 0x700 -#define BIFMF_WIN_L 0x800 -#define BPD_OPTION 0x1000 -#define BMF_WIN_L 0xe000 -#define BBW_SEARCH_L 0x30000 -#define BWIN_ENH_L 0xc0000 -#define BBW_TH 0x700000 -#define BED_TH2 0x3800000 -#define BBW_OPTION 0x4000000 -#define BRADIO_TH 0x18000000 -#define BWINDOW_L 0xe0000000 -#define BSBD_OPTION 0x1 -#define BFRAME_TH 0x1c -#define BFS_OPTION 0x60 -#define BDC_SLOPE_CHECK 0x80 -#define BFGUARD_COUNTER_DC_L 0xe00 -#define BFRAME_WEIGHT_SHORT 0x7000 -#define BSUB_TUNE 0xe00000 -#define BFRAME_DC_LENGTH 0xe000000 -#define BSBD_START_OFFSET 0x30000000 -#define BFRAME_TH_2 0x7 -#define BFRAME_GI2_TH 0x38 -#define BGI2_SYNC_EN 0x40 -#define BSARCH_SHORT_EARLY 0x300 -#define BSARCH_SHORT_LATE 0xc00 -#define BSARCH_GI2_LATE 0x70000 -#define BCFOANTSUM 0x1 -#define BCFOACC 0x2 -#define BCFOSTARTOFFSET 0xc -#define BCFOLOOPBACK 0x70 -#define BCFOSUMWEIGHT 0x80 -#define BDAGCENABLE 0x10000 -#define BTXIQIMB_A 0x3ff -#define BTXIQIMB_b 0xfc00 -#define BTXIQIMB_C 0x3f0000 -#define BTXIQIMB_D 0xffc00000 -#define BTXIDCOFFSET 0xff -#define BTXIQDCOFFSET 0xff00 -#define BTXDFIRMODE 0x10000 -#define BTXPESUDO_NOISEON 0x4000000 -#define BTXPESUDO_NOISE_A 0xff -#define BTXPESUDO_NOISE_B 0xff00 -#define BTXPESUDO_NOISE_C 0xff0000 -#define BTXPESUDO_NOISE_D 0xff000000 -#define BCCA_DROPOPTION 0x20000 -#define BCCA_DROPTHRES 0xfff00000 -#define BEDCCA_H 0xf -#define BEDCCA_L 0xf0 -#define BLAMBDA_ED 0x300 -#define BRX_INITIALGAIN 0x7f -#define BRX_ANTDIV_EN 0x80 -#define BRX_AGC_ADDRESS_FOR_LNA 0x7f00 -#define BRX_HIGHPOWER_FLOW 0x8000 -#define BRX_AGC_FREEZE_THRES 0xc0000 -#define BRX_FREEZESTEP_AGC1 0x300000 -#define BRX_FREEZESTEP_AGC2 0xc00000 -#define BRX_FREEZESTEP_AGC3 0x3000000 -#define BRX_FREEZESTEP_AGC0 0xc000000 -#define BRXRSSI_CMP_EN 0x10000000 -#define BRXQUICK_AGCEN 0x20000000 -#define BRXAGC_FREEZE_THRES_MODE 0x40000000 -#define BRX_OVERFLOW_CHECKTYPE 0x80000000 -#define BRX_AGCSHIFT 0x7f -#define BTRSW_TRI_ONLY 0x80 -#define BPOWER_THRES 0x300 -#define BRXAGC_EN 0x1 -#define BRXAGC_TOGETHER_EN 0x2 -#define BRXAGC_MIN 0x4 -#define BRXHP_INI 0x7 -#define BRXHP_TRLNA 0x70 -#define BRXHP_RSSI 0x700 -#define BRXHP_BBP1 0x7000 -#define BRXHP_BBP2 0x70000 -#define BRXHP_BBP3 0x700000 -#define BRSSI_H 0x7f0000 -#define BRSSI_GEN 0x7f000000 -#define BRXSETTLE_TRSW 0x7 -#define BRXSETTLE_LNA 0x38 -#define BRXSETTLE_RSSI 0x1c0 -#define BRXSETTLE_BBP 0xe00 -#define BRXSETTLE_RXHP 0x7000 -#define BRXSETTLE_ANTSW_RSSI 0x38000 -#define BRXSETTLE_ANTSW 0xc0000 -#define BRXPROCESS_TIME_DAGC 0x300000 -#define BRXSETTLE_HSSI 0x400000 -#define BRXPROCESS_TIME_BBPPW 0x800000 -#define BRXANTENNA_POWER_SHIFT 0x3000000 -#define BRSSI_TABLE_SELECT 0xc000000 -#define BRXHP_FINAL 0x7000000 -#define BRXHPSETTLE_BBP 0x7 -#define BRXHTSETTLE_HSSI 0x8 -#define BRXHTSETTLE_RXHP 0x70 -#define BRXHTSETTLE_BBPPW 0x80 -#define BRXHTSETTLE_IDLE 0x300 -#define BRXHTSETTLE_RESERVED 0x1c00 -#define BRXHT_RXHP_EN 0x8000 -#define BRXAGC_FREEZE_THRES 0x30000 -#define BRXAGC_TOGETHEREN 0x40000 -#define BRXHTAGC_MIN 0x80000 -#define BRXHTAGC_EN 0x100000 -#define BRXHTDAGC_EN 0x200000 -#define BRXHT_RXHP_BBP 0x1c00000 -#define BRXHT_RXHP_FINAL 0xe0000000 -#define BRXPW_RADIO_TH 0x3 -#define BRXPW_RADIO_EN 0x4 -#define BRXMF_HOLD 0x3800 -#define BRXPD_DELAY_TH1 0x38 -#define BRXPD_DELAY_TH2 0x1c0 -#define BRXPD_DC_COUNT_MAX 0x600 -#define BRXPD_DELAY_TH 0x8000 -#define BRXPROCESS_DELAY 0xf0000 -#define BRXSEARCHRANGE_GI2_EARLY 0x700000 -#define BRXFRAME_FUARD_COUNTER_L 0x3800000 -#define BRXSGI_GUARD_L 0xc000000 -#define BRXSGI_SEARCH_L 0x30000000 -#define BRXSGI_TH 0xc0000000 -#define BDFSCNT0 0xff -#define BDFSCNT1 0xff00 -#define BDFSFLAG 0xf0000 -#define BMF_WEIGHT_SUM 0x300000 -#define BMINIDX_TH 0x7f000000 -#define BDAFORMAT 0x40000 -#define BTXCH_EMU_ENABLE 0x01000000 -#define BTRSW_ISOLATION_A 0x7f -#define BTRSW_ISOLATION_B 0x7f00 -#define BTRSW_ISOLATION_C 0x7f0000 -#define BTRSW_ISOLATION_D 0x7f000000 -#define BEXT_LNA_GAIN 0x7c00 - -#define BSTBC_EN 0x4 -#define BANTENNA_MAPPING 0x10 -#define BNSS 0x20 -#define BCFO_ANTSUM_ID 0x200 -#define BPHY_COUNTER_RESET 0x8000000 -#define BCFO_REPORT_GET 0x4000000 -#define BOFDM_CONTINUE_TX 0x10000000 -#define BOFDM_SINGLE_CARRIER 0x20000000 -#define BOFDM_SINGLE_TONE 0x40000000 -#define BHT_DETECT 0x100 -#define BCFOEN 0x10000 -#define BCFOVALUE 0xfff00000 -#define BSIGTONE_RE 0x3f -#define BSIGTONE_IM 0x7f00 -#define BCOUNTER_CCA 0xffff -#define BCOUNTER_PARITYFAIL 0xffff0000 -#define BCOUNTER_RATEILLEGAL 0xffff -#define BCOUNTER_CRC8FAIL 0xffff0000 -#define BCOUNTER_MCSNOSUPPORT 0xffff -#define BCOUNTER_FASTSYNC 0xffff -#define BSHORTCFO 0xfff -#define BSHORTCFOT_LENGTH 12 -#define BSHORTCFOF_LENGTH 11 -#define BLONGCFO 0x7ff -#define BLONGCFOT_LENGTH 11 -#define BLONGCFOF_LENGTH 11 -#define BTAILCFO 0x1fff -#define BTAILCFOT_LENGTH 13 -#define BTAILCFOF_LENGTH 12 -#define BNOISE_EN_PWDB 0xffff -#define BCC_POWER_DB 0xffff0000 -#define BMOISE_PWDB 0xffff -#define BPOWERMEAST_LENGTH 10 -#define BPOWERMEASF_LENGTH 3 -#define BRX_HT_BW 0x1 -#define BRXSC 0x6 -#define BRX_HT 0x8 -#define BNB_INTF_DET_ON 0x1 -#define BINTF_WIN_LEN_CFG 0x30 -#define BNB_INTF_TH_CFG 0x1c0 -#define BRFGAIN 0x3f -#define BTABLESEL 0x40 -#define BTRSW 0x80 -#define BRXSNR_A 0xff -#define BRXSNR_B 0xff00 -#define BRXSNR_C 0xff0000 -#define BRXSNR_D 0xff000000 -#define BSNR_EVMT_LENGTH 8 -#define BSNR_EVMF_LENGTH 1 -#define BCSI1ST 0xff -#define BCSI2ND 0xff00 -#define BRXEVM1ST 0xff0000 -#define BRXEVM2ND 0xff000000 -#define BSIGEVM 0xff -#define BPWDB 0xff00 -#define BSGIEN 0x10000 - -#define BSFACTOR_QMA1 0xf -#define BSFACTOR_QMA2 0xf0 -#define BSFACTOR_QMA3 0xf00 -#define BSFACTOR_QMA4 0xf000 -#define BSFACTOR_QMA5 0xf0000 -#define BSFACTOR_QMA6 0xf0000 -#define BSFACTOR_QMA7 0xf00000 -#define BSFACTOR_QMA8 0xf000000 -#define BSFACTOR_QMA9 0xf0000000 -#define BCSI_SCHEME 0x100000 - -#define BNOISE_LVL_TOP_SET 0x3 -#define BCHSMOOTH 0x4 -#define BCHSMOOTH_CFG1 0x38 -#define BCHSMOOTH_CFG2 0x1c0 -#define BCHSMOOTH_CFG3 0xe00 -#define BCHSMOOTH_CFG4 0x7000 -#define BMRCMODE 0x800000 -#define BTHEVMCFG 0x7000000 - -#define BLOOP_FIT_TYPE 0x1 -#define BUPD_CFO 0x40 -#define BUPD_CFO_OFFDATA 0x80 -#define BADV_UPD_CFO 0x100 -#define BADV_TIME_CTRL 0x800 -#define BUPD_CLKO 0x1000 -#define BFC 0x6000 -#define BTRACKING_MODE 0x8000 -#define BPHCMP_ENABLE 0x10000 -#define BUPD_CLKO_LTF 0x20000 -#define BCOM_CH_CFO 0x40000 -#define BCSI_ESTI_MODE 0x80000 -#define BADV_UPD_EQZ 0x100000 -#define BUCHCFG 0x7000000 -#define BUPDEQZ 0x8000000 - -#define BRX_PESUDO_NOISE_ON 0x20000000 -#define BRX_PESUDO_NOISE_A 0xff -#define BRX_PESUDO_NOISE_B 0xff00 -#define BRX_PESUDO_NOISE_C 0xff0000 -#define BRX_PESUDO_NOISE_D 0xff000000 -#define BRX_PESUDO_NOISESTATE_A 0xffff -#define BRX_PESUDO_NOISESTATE_B 0xffff0000 -#define BRX_PESUDO_NOISESTATE_C 0xffff -#define BRX_PESUDO_NOISESTATE_D 0xffff0000 - -#define BZEBRA1_HSSIENABLE 0x8 -#define BZEBRA1_TRXCONTROL 0xc00 -#define BZEBRA1_TRXGAINSETTING 0x07f -#define BZEBRA1_RXCOUNTER 0xc00 -#define BZEBRA1_TXCHANGEPUMP 0x38 -#define BZEBRA1_RXCHANGEPUMP 0x7 -#define BZEBRA1_CHANNEL_NUM 0xf80 -#define BZEBRA1_TXLPFBW 0x400 -#define BZEBRA1_RXLPFBW 0x600 - -#define BRTL8256REG_MODE_CTRL1 0x100 -#define BRTL8256REG_MODE_CTRL0 0x40 -#define BRTL8256REG_TXLPFBW 0x18 -#define BRTL8256REG_RXLPFBW 0x600 - -#define BRTL8258_TXLPFBW 0xc -#define BRTL8258_RXLPFBW 0xc00 -#define BRTL8258_RSSILPFBW 0xc0 - -#define BBYTE0 0x1 -#define BBYTE1 0x2 -#define BBYTE2 0x4 -#define BBYTE3 0x8 -#define BWORD0 0x3 -#define BWORD1 0xc -#define BWORD 0xf - -#define MASKBYTE0 0xff -#define MASKBYTE1 0xff00 -#define MASKBYTE2 0xff0000 -#define MASKBYTE3 0xff000000 -#define MASKHWORD 0xffff0000 -#define MASKLWORD 0x0000ffff -#define MASKDWORD 0xffffffff -#define MASK12BITS 0xfff -#define MASKH4BITS 0xf0000000 -#define MASKOFDM_D 0xffc00000 -#define MASKCCK 0x3f3f3f3f - -#define MASK4BITS 0x0f -#define MASK20BITS 0xfffff -#define RFREG_OFFSET_MASK 0xfffff - -#define BENABLE 0x1 -#define BDISABLE 0x0 - -#define LEFT_ANTENNA 0x0 -#define RIGHT_ANTENNA 0x1 - -#define TCHECK_TXSTATUS 500 -#define TUPDATE_RXCOUNTER 100 - -#define REG_UN_used_register 0x01bf - -/* Path_A RFE cotrol pinmux*/ -#define RA_RFE_PINMUX 0xcb0 -/* Path_B RFE control pinmux*/ -#define RB_RFE_PINMUX 0xeb0 - -#define RA_RFE_INV 0xcb4 -#define RB_RFE_INV 0xeb4 - -/* RXIQC */ -/*RxIQ imblance matrix coeff. A & B*/ -#define RA_RXIQC_AB 0xc10 -/*RxIQ imblance matrix coeff. C & D*/ -#define RA_RXIQC_CD 0xc14 -/* Pah_A TX scaling factor*/ -#define RA_TXSCALE 0xc1c -/* Path_B TX scaling factor*/ -#define RB_TXSCALE 0xe1c -/*RxIQ imblance matrix coeff. A & B*/ -#define RB_RXIQC_AB 0xe10 -/*RxIQ imblance matrix coeff. C & D*/ -#define RB_RXIQC_CD 0xe14 -/*bit mask for IQC matrix element A & C*/ -#define RXIQC_AC 0x02ff - /*bit mask for IQC matrix element A & C*/ -#define RXIQC_BD 0x02ff0000 - -/* 2 EFUSE_TEST (For RTL8723 partially) */ -#define EFUSE_SEL(x) (((x) & 0x3) << 8) -#define EFUSE_SEL_MASK 0x300 -#define EFUSE_WIFI_SEL_0 0x0 - -/*REG_MULTI_FUNC_CTRL(For RTL8723 Only)*/ -/* Enable GPIO[9] as WiFi HW PDn source*/ -#define WL_HWPDN_EN BIT(0) -/* WiFi HW PDn polarity control*/ -#define WL_HWPDN_SL BIT(1) -/* WiFi function enable */ -#define WL_FUNC_EN BIT(2) -/* Enable GPIO[9] as WiFi RF HW PDn source */ -#define WL_HWROF_EN BIT(3) -/* Enable GPIO[11] as BT HW PDn source */ -#define BT_HWPDN_EN BIT(16) -/* BT HW PDn polarity control */ -#define BT_HWPDN_SL BIT(17) -/* BT function enable */ -#define BT_FUNC_EN BIT(18) -/* Enable GPIO[11] as BT/GPS RF HW PDn source */ -#define BT_HWROF_EN BIT(19) -/* Enable GPIO[10] as GPS HW PDn source */ -#define GPS_HWPDN_EN BIT(20) -/* GPS HW PDn polarity control */ -#define GPS_HWPDN_SL BIT(21) -/* GPS function enable */ -#define GPS_FUNC_EN BIT(22) - -#define BMASKBYTE0 0xff -#define BMASKBYTE1 0xff00 -#define BMASKBYTE2 0xff0000 -#define BMASKBYTE3 0xff000000 -#define BMASKHWORD 0xffff0000 -#define BMASKLWORD 0x0000ffff -#define BMASKDWORD 0xffffffff -#define BMASK12BITS 0xfff -#define BMASKH4BITS 0xf0000000 -#define BMASKOFDM_D 0xffc00000 -#define BMASKCCK 0x3f3f3f3f - -#define BRFREGOFFSETMASK 0xfffff - -#define ODM_REG_CCK_RPT_FORMAT_11AC 0x804 -#define ODM_REG_BB_RX_PATH_11AC 0x808 -/*PAGE 9*/ -#define ODM_REG_OFDM_FA_RST_11AC 0x9A4 -/*PAGE A*/ -#define ODM_REG_CCK_CCA_11AC 0xA0A -#define ODM_REG_CCK_FA_RST_11AC 0xA2C -#define ODM_REG_CCK_FA_11AC 0xA5C -/*PAGE C*/ -#define ODM_REG_IGI_A_11AC 0xC50 -/*PAGE E*/ -#define ODM_REG_IGI_B_11AC 0xE50 -/*PAGE F*/ -#define ODM_REG_OFDM_FA_11AC 0xF48 - -/* 2 MAC REG LIST */ - -/* DIG Related */ -#define ODM_BIT_IGI_11AC 0xFFFFFFFF -#define ODM_BIT_CCK_RPT_FORMAT_11AC BIT16 -#define ODM_BIT_BB_RX_PATH_11AC 0xF - -enum AGGRE_SIZE { - HT_AGG_SIZE_8K = 0, - HT_AGG_SIZE_16K = 1, - HT_AGG_SIZE_32K = 2, - HT_AGG_SIZE_64K = 3, - VHT_AGG_SIZE_128K = 4, - VHT_AGG_SIZE_256K = 5, - VHT_AGG_SIZE_512K = 6, - VHT_AGG_SIZE_1024K = 7, -}; - -#define REG_AMPDU_MAX_LENGTH_8812 0x0458 - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/rf.c b/drivers/net/wireless/rtlwifi/rtl8821ae/rf.c deleted file mode 100644 index 2922538160e5..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/rf.c +++ /dev/null @@ -1,465 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "rf.h" -#include "dm.h" - -static bool _rtl8821ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw); - -void rtl8821ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - switch (bandwidth) { - case HT_CHANNEL_WIDTH_20: - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 3); - rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 3); - break; - case HT_CHANNEL_WIDTH_20_40: - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 1); - rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 1); - break; - case HT_CHANNEL_WIDTH_80: - rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 0); - rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 0); - break; - default: - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "unknown bandwidth: %#X\n", bandwidth); - break; - } -} - -void rtl8821ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u32 tx_agc[2] = {0, 0}, tmpval; - bool turbo_scanoff = false; - u8 idx1, idx2; - u8 *ptr; - u8 direction; - u32 pwrtrac_value; - - if (rtlefuse->eeprom_regulatory != 0) - turbo_scanoff = true; - - if (mac->act_scanning) { - tx_agc[RF90_PATH_A] = 0x3f3f3f3f; - tx_agc[RF90_PATH_B] = 0x3f3f3f3f; - - if (turbo_scanoff) { - for (idx1 = RF90_PATH_A; - idx1 <= RF90_PATH_B; - idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - } - } else { - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - tx_agc[idx1] = ppowerlevel[idx1] | - (ppowerlevel[idx1] << 8) | - (ppowerlevel[idx1] << 16) | - (ppowerlevel[idx1] << 24); - } - - if (rtlefuse->eeprom_regulatory == 0) { - tmpval = - (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + - (rtlphy->mcs_txpwrlevel_origoffset[0][7] << - 8); - tx_agc[RF90_PATH_A] += tmpval; - - tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + - (rtlphy->mcs_txpwrlevel_origoffset[0][15] << - 24); - tx_agc[RF90_PATH_B] += tmpval; - } - } - - for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { - ptr = (u8 *)(&tx_agc[idx1]); - for (idx2 = 0; idx2 < 4; idx2++) { - if (*ptr > RF6052_MAX_TX_PWR) - *ptr = RF6052_MAX_TX_PWR; - ptr++; - } - } - rtl8821ae_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); - if (direction == 1) { - tx_agc[0] += pwrtrac_value; - tx_agc[1] += pwrtrac_value; - } else if (direction == 2) { - tx_agc[0] -= pwrtrac_value; - tx_agc[1] -= pwrtrac_value; - } - tmpval = tx_agc[RF90_PATH_A]; - rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, MASKDWORD, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 1~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_A_CCK11_CCK1); - - tmpval = tx_agc[RF90_PATH_B]; - rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, MASKDWORD, tmpval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, - RTXAGC_B_CCK11_CCK1); -} - -static void rtl8821ae_phy_get_power_base(struct ieee80211_hw *hw, - u8 *ppowerlevel_ofdm, - u8 *ppowerlevel_bw20, - u8 *ppowerlevel_bw40, u8 channel, - u32 *ofdmbase, u32 *mcsbase) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u32 powerbase0, powerbase1; - u8 i, powerlevel[2]; - - for (i = 0; i < 2; i++) { - powerbase0 = ppowerlevel_ofdm[i]; - - powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | - (powerbase0 << 8) | powerbase0; - *(ofdmbase + i) = powerbase0; - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [OFDM power base index rf(%c) = 0x%x]\n", - ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)); - } - - for (i = 0; i < 2; i++) { - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) - powerlevel[i] = ppowerlevel_bw20[i]; - else - powerlevel[i] = ppowerlevel_bw40[i]; - - powerbase1 = powerlevel[i]; - powerbase1 = (powerbase1 << 24) | - (powerbase1 << 16) | (powerbase1 << 8) | powerbase1; - - *(mcsbase + i) = powerbase1; - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - " [MCS power base index rf(%c) = 0x%x]\n", - ((i == 0) ? 'A' : 'B'), *(mcsbase + i)); - } -} - -static void get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, - u8 channel, u8 index, - u32 *powerbase0, - u32 *powerbase1, - u32 *p_outwriteval) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff; - u32 writeval, customer_limit, rf; - - for (rf = 0; rf < 2; rf++) { - switch (rtlefuse->eeprom_regulatory) { - case 0: - chnlgroup = 0; - - writeval = - rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index + - (rf ? 8 : 0)] - + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - case 1: - if (rtlphy->pwrgroup_cnt == 1) { - chnlgroup = 0; - } else { - if (channel < 3) - chnlgroup = 0; - else if (channel < 6) - chnlgroup = 1; - else if (channel < 9) - chnlgroup = 2; - else if (channel < 12) - chnlgroup = 3; - else if (channel < 14) - chnlgroup = 4; - else if (channel == 14) - chnlgroup = 5; - } - - writeval = - rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] - [index + (rf ? 8 : 0)] + ((index < 2) ? - powerbase0[rf] : - powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - - break; - case 2: - writeval = - ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Better regulatory, writeval(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - case 3: - chnlgroup = 0; - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 40MHz rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), - rtlefuse->pwrgroup_ht40[rf][channel - - 1]); - } else { - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "customer's limit, 20MHz rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), - rtlefuse->pwrgroup_ht20[rf][channel - - 1]); - } - - if (index < 2) - pwr_diff = rtlefuse->txpwr_legacyhtdiff[rf][channel-1]; - else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) - pwr_diff = - rtlefuse->txpwr_ht20diff[rf][channel-1]; - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) - customer_pwr_diff = - rtlefuse->pwrgroup_ht40[rf][channel-1]; - else - customer_pwr_diff = - rtlefuse->pwrgroup_ht20[rf][channel-1]; - - if (pwr_diff > customer_pwr_diff) - pwr_diff = 0; - else - pwr_diff = customer_pwr_diff - pwr_diff; - - for (i = 0; i < 4; i++) { - pwr_diff_limit[i] = - (u8)((rtlphy->mcs_txpwrlevel_origoffset - [chnlgroup][index + (rf ? 8 : 0)] & - (0x7f << (i * 8))) >> (i * 8)); - - if (pwr_diff_limit[i] > pwr_diff) - pwr_diff_limit[i] = pwr_diff; - } - - customer_limit = (pwr_diff_limit[3] << 24) | - (pwr_diff_limit[2] << 16) | - (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer's limit rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), customer_limit); - - writeval = customer_limit + - ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Customer, writeval rf(%c)= 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - default: - chnlgroup = 0; - writeval = - rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] - [index + (rf ? 8 : 0)] - + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "RTK better performance, writeval rf(%c) = 0x%x\n", - ((rf == 0) ? 'A' : 'B'), writeval); - break; - } - - if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) - writeval = writeval - 0x06060606; - else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_BT2) - writeval = writeval - 0x0c0c0c0c; - *(p_outwriteval + rf) = writeval; - } -} - -static void _rtl8821ae_write_ofdm_power_reg(struct ieee80211_hw *hw, - u8 index, u32 *pvalue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u16 regoffset_a[6] = { - RTXAGC_A_OFDM18_OFDM6, RTXAGC_A_OFDM54_OFDM24, - RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, - RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 - }; - u16 regoffset_b[6] = { - RTXAGC_B_OFDM18_OFDM6, RTXAGC_B_OFDM54_OFDM24, - RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, - RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 - }; - u8 i, rf, pwr_val[4]; - u32 writeval; - u16 regoffset; - - for (rf = 0; rf < 2; rf++) { - writeval = pvalue[rf]; - for (i = 0; i < 4; i++) { - pwr_val[i] = (u8)((writeval & (0x7f << - (i * 8))) >> (i * 8)); - - if (pwr_val[i] > RF6052_MAX_TX_PWR) - pwr_val[i] = RF6052_MAX_TX_PWR; - } - writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | - (pwr_val[1] << 8) | pwr_val[0]; - - if (rf == 0) - regoffset = regoffset_a[index]; - else - regoffset = regoffset_b[index]; - rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); - - RTPRINT(rtlpriv, FPHY, PHY_TXPWR, - "Set 0x%x = %08x\n", regoffset, writeval); - } -} - -void rtl8821ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel_ofdm, - u8 *ppowerlevel_bw20, - u8 *ppowerlevel_bw40, - u8 channel) -{ - u32 writeval[2], powerbase0[2], powerbase1[2]; - u8 index; - u8 direction; - u32 pwrtrac_value; - - rtl8821ae_phy_get_power_base(hw, ppowerlevel_ofdm, - ppowerlevel_bw20, - ppowerlevel_bw40, - channel, - &powerbase0[0], - &powerbase1[0]); - - rtl8821ae_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); - - for (index = 0; index < 6; index++) { - get_txpower_writeval_by_regulatory(hw, channel, index, - &powerbase0[0], - &powerbase1[0], - &writeval[0]); - if (direction == 1) { - writeval[0] += pwrtrac_value; - writeval[1] += pwrtrac_value; - } else if (direction == 2) { - writeval[0] -= pwrtrac_value; - writeval[1] -= pwrtrac_value; - } - _rtl8821ae_write_ofdm_power_reg(hw, index, &writeval[0]); - } -} - -bool rtl8821ae_phy_rf6052_config(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - - if (rtlphy->rf_type == RF_1T1R) - rtlphy->num_total_rfpath = 1; - else - rtlphy->num_total_rfpath = 2; - - return _rtl8821ae_phy_rf6052_config_parafile(hw); -} - -static bool _rtl8821ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - u8 rfpath; - bool rtstatus = true; - - for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { - switch (rfpath) { - case RF90_PATH_A: { - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtstatus = - rtl8812ae_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - else - rtstatus = - rtl8821ae_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - break; - } - case RF90_PATH_B: - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) - rtstatus = - rtl8812ae_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - else - rtstatus = - rtl8821ae_phy_config_rf_with_headerfile(hw, - (enum radio_path)rfpath); - break; - case RF90_PATH_C: - break; - case RF90_PATH_D: - break; - } - - if (!rtstatus) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "Radio[%d] Fail!!", rfpath); - return false; - } - } - - /*put arrays in dm.c*/ - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); - return rtstatus; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/rf.h b/drivers/net/wireless/rtlwifi/rtl8821ae/rf.h deleted file mode 100644 index efd22bd0b139..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/rf.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8821AE_RF_H__ -#define __RTL8821AE_RF_H__ - -#define RF6052_MAX_TX_PWR 0x3F - -void rtl8821ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, - u8 bandwidth); -void rtl8821ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel); -void rtl8821ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, - u8 *ppowerlevel_ofdm, - u8 *ppowerlevel_bw20, - u8 *ppowerlevel_bw40, - u8 channel); -bool rtl8821ae_phy_rf6052_config(struct ieee80211_hw *hw); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c deleted file mode 100644 index a4988121e1ab..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c +++ /dev/null @@ -1,458 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../core.h" -#include "../pci.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "dm.h" -#include "hw.h" -#include "fw.h" -#include "sw.h" -#include "trx.h" -#include "led.h" -#include "table.h" -#include "../btcoexist/rtl_btc.h" - -#include -#include - -static void rtl8821ae_init_aspm_vars(struct ieee80211_hw *hw) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - - /*close ASPM for AMD defaultly */ - rtlpci->const_amdpci_aspm = 0; - - /** - * ASPM PS mode. - * 0 - Disable ASPM, - * 1 - Enable ASPM without Clock Req, - * 2 - Enable ASPM with Clock Req, - * 3 - Alwyas Enable ASPM with Clock Req, - * 4 - Always Enable ASPM without Clock Req. - * set defult to RTL8192CE:3 RTL8192E:2 - */ - rtlpci->const_pci_aspm = 3; - - /*Setting for PCI-E device */ - rtlpci->const_devicepci_aspm_setting = 0x03; - - /*Setting for PCI-E bridge */ - rtlpci->const_hostpci_aspm_setting = 0x02; - - /** - * In Hw/Sw Radio Off situation. - * 0 - Default, - * 1 - From ASPM setting without low Mac Pwr, - * 2 - From ASPM setting with low Mac Pwr, - * 3 - Bus D3 - * set default to RTL8192CE:0 RTL8192SE:2 - */ - rtlpci->const_hwsw_rfoff_d3 = 0; - - /** - * This setting works for those device with - * backdoor ASPM setting such as EPHY setting. - * 0 - Not support ASPM, - * 1 - Support ASPM, - * 2 - According to chipset. - */ - rtlpci->const_support_pciaspm = 1; -} - -/*InitializeVariables8812E*/ -int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw) -{ - int err = 0; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - - rtl8821ae_bt_reg_init(hw); - rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; - rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer(); - - rtlpriv->dm.dm_initialgain_enable = 1; - rtlpriv->dm.dm_flag = 0; - rtlpriv->dm.disable_framebursting = 0; - rtlpriv->dm.thermalvalue = 0; - rtlpci->transmit_config = CFENDFORM | BIT(15) | BIT(24) | BIT(25); - - mac->ht_enable = true; - mac->ht_cur_stbc = 0; - mac->ht_stbc_cap = 0; - mac->vht_cur_ldpc = 0; - mac->vht_ldpc_cap = 0; - mac->vht_cur_stbc = 0; - mac->vht_stbc_cap = 0; - - rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; - /*following 2 is for register 5G band, refer to _rtl_init_mac80211()*/ - rtlpriv->rtlhal.bandset = BAND_ON_BOTH; - rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; - - rtlpci->receive_config = (RCR_APPFCS | - RCR_APP_MIC | - RCR_APP_ICV | - RCR_APP_PHYST_RXFF | - RCR_NONQOS_VHT | - RCR_HTC_LOC_CTRL | - RCR_AMF | - RCR_ACF | - /*This bit controls the PS-Poll packet filter.*/ - RCR_ADF | - RCR_AICV | - RCR_ACRC32 | - RCR_AB | - RCR_AM | - RCR_APM | - 0); - - rtlpci->irq_mask[0] = - (u32)(IMR_PSTIMEOUT | - IMR_GTINT3 | - IMR_HSISR_IND_ON_INT | - IMR_C2HCMD | - IMR_HIGHDOK | - IMR_MGNTDOK | - IMR_BKDOK | - IMR_BEDOK | - IMR_VIDOK | - IMR_VODOK | - IMR_RDU | - IMR_ROK | - 0); - - rtlpci->irq_mask[1] = - (u32)(IMR_RXFOVW | - IMR_TXFOVW | - 0); - rtlpci->sys_irq_mask = (u32)(HSIMR_PDN_INT_EN | - HSIMR_RON_INT_EN | - 0); - /* for WOWLAN */ - 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; - rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; - rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; - if (rtlpriv->cfg->mod_params->disable_watchdog) - pr_info("watchdog disabled\n"); - rtlpriv->psc.reg_fwctrl_lps = 3; - rtlpriv->psc.reg_max_lps_awakeintvl = 5; - rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support; - - /* for ASPM, you can close aspm through - * set const_support_pciaspm = 0 - */ - rtl8821ae_init_aspm_vars(hw); - - if (rtlpriv->psc.reg_fwctrl_lps == 1) - rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 2) - rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; - else if (rtlpriv->psc.reg_fwctrl_lps == 3) - rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; - - /* for firmware buf */ - rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); - if (!rtlpriv->rtlhal.pfirmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't alloc buffer for fw.\n"); - return 1; - } - rtlpriv->rtlhal.wowlan_firmware = vzalloc(0x8000); - if (!rtlpriv->rtlhal.wowlan_firmware) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't alloc buffer for wowlan fw.\n"); - return 1; - } - - if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) { - rtlpriv->cfg->fw_name = "rtlwifi/rtl8812aefw.bin"; - rtlpriv->cfg->wowlan_fw_name = "rtlwifi/rtl8812aefw_wowlan.bin"; - } else { - rtlpriv->cfg->fw_name = "rtlwifi/rtl8821aefw.bin"; - rtlpriv->cfg->wowlan_fw_name = "rtlwifi/rtl8821aefw_wowlan.bin"; - } - - rtlpriv->max_fw_size = 0x8000; - /*load normal firmware*/ - pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); - err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, - rtlpriv->io.dev, GFP_KERNEL, hw, - rtl_fw_cb); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to request normal firmware!\n"); - return 1; - } - /*load wowlan firmware*/ - pr_info("Using firmware %s\n", rtlpriv->cfg->wowlan_fw_name); - err = request_firmware_nowait(THIS_MODULE, 1, - rtlpriv->cfg->wowlan_fw_name, - rtlpriv->io.dev, GFP_KERNEL, hw, - rtl_wowlan_fw_cb); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Failed to request wowlan firmware!\n"); - return 1; - } - return 0; -} - -void rtl8821ae_deinit_sw_vars(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (rtlpriv->rtlhal.pfirmware) { - vfree(rtlpriv->rtlhal.pfirmware); - rtlpriv->rtlhal.pfirmware = NULL; - } -#if (USE_SPECIFIC_FW_TO_SUPPORT_WOWLAN == 1) - if (rtlpriv->rtlhal.wowlan_firmware) { - vfree(rtlpriv->rtlhal.wowlan_firmware); - rtlpriv->rtlhal.wowlan_firmware = NULL; - } -#endif -} - -/* get bt coexist status */ -bool rtl8821ae_get_btc_status(void) -{ - return true; -} - -static struct rtl_hal_ops rtl8821ae_hal_ops = { - .init_sw_vars = rtl8821ae_init_sw_vars, - .deinit_sw_vars = rtl8821ae_deinit_sw_vars, - .read_eeprom_info = rtl8821ae_read_eeprom_info, - .interrupt_recognized = rtl8821ae_interrupt_recognized, - .hw_init = rtl8821ae_hw_init, - .hw_disable = rtl8821ae_card_disable, - .hw_suspend = rtl8821ae_suspend, - .hw_resume = rtl8821ae_resume, - .enable_interrupt = rtl8821ae_enable_interrupt, - .disable_interrupt = rtl8821ae_disable_interrupt, - .set_network_type = rtl8821ae_set_network_type, - .set_chk_bssid = rtl8821ae_set_check_bssid, - .set_qos = rtl8821ae_set_qos, - .set_bcn_reg = rtl8821ae_set_beacon_related_registers, - .set_bcn_intv = rtl8821ae_set_beacon_interval, - .update_interrupt_mask = rtl8821ae_update_interrupt_mask, - .get_hw_reg = rtl8821ae_get_hw_reg, - .set_hw_reg = rtl8821ae_set_hw_reg, - .update_rate_tbl = rtl8821ae_update_hal_rate_tbl, - .fill_tx_desc = rtl8821ae_tx_fill_desc, - .fill_tx_cmddesc = rtl8821ae_tx_fill_cmddesc, - .query_rx_desc = rtl8821ae_rx_query_desc, - .set_channel_access = rtl8821ae_update_channel_access_setting, - .radio_onoff_checking = rtl8821ae_gpio_radio_on_off_checking, - .set_bw_mode = rtl8821ae_phy_set_bw_mode, - .switch_channel = rtl8821ae_phy_sw_chnl, - .dm_watchdog = rtl8821ae_dm_watchdog, - .scan_operation_backup = rtl8821ae_phy_scan_operation_backup, - .set_rf_power_state = rtl8821ae_phy_set_rf_power_state, - .led_control = rtl8821ae_led_control, - .set_desc = rtl8821ae_set_desc, - .get_desc = rtl8821ae_get_desc, - .is_tx_desc_closed = rtl8821ae_is_tx_desc_closed, - .tx_polling = rtl8821ae_tx_polling, - .enable_hw_sec = rtl8821ae_enable_hw_security_config, - .set_key = rtl8821ae_set_key, - .init_sw_leds = rtl8821ae_init_sw_leds, - .get_bbreg = rtl8821ae_phy_query_bb_reg, - .set_bbreg = rtl8821ae_phy_set_bb_reg, - .get_rfreg = rtl8821ae_phy_query_rf_reg, - .set_rfreg = rtl8821ae_phy_set_rf_reg, - .fill_h2c_cmd = rtl8821ae_fill_h2c_cmd, - .get_btc_status = rtl8821ae_get_btc_status, - .rx_command_packet = rtl8821ae_rx_command_packet, - .add_wowlan_pattern = rtl8821ae_add_wowlan_pattern, -}; - -static struct rtl_mod_params rtl8821ae_mod_params = { - .sw_crypto = false, - .inactiveps = true, - .swctrl_lps = false, - .fwctrl_lps = true, - .msi_support = true, - .debug = DBG_EMERG, - .disable_watchdog = 0, -}; - -static struct rtl_hal_cfg rtl8821ae_hal_cfg = { - .bar_id = 2, - .write_readback = true, - .name = "rtl8821ae_pci", - .fw_name = "rtlwifi/rtl8821aefw.bin", - .ops = &rtl8821ae_hal_ops, - .mod_params = &rtl8821ae_mod_params, - .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, - .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, - .maps[SYS_CLK] = REG_SYS_CLKR, - .maps[MAC_RCR_AM] = AM, - .maps[MAC_RCR_AB] = AB, - .maps[MAC_RCR_ACRC32] = ACRC32, - .maps[MAC_RCR_ACF] = ACF, - .maps[MAC_RCR_AAP] = AAP, - .maps[MAC_HIMR] = REG_HIMR, - .maps[MAC_HIMRE] = REG_HIMRE, - - .maps[EFUSE_ACCESS] = REG_EFUSE_ACCESS, - - .maps[EFUSE_TEST] = REG_EFUSE_TEST, - .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_CLK] = 0, - .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, - .maps[EFUSE_PWC_EV12V] = PWC_EV12V, - .maps[EFUSE_FEN_ELDR] = FEN_ELDR, - .maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, - .maps[EFUSE_ANA8M] = ANA8M, - .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, - .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, - .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, - .maps[EFUSE_OOB_PROTECT_BYTES_LEN] = EFUSE_OOB_PROTECT_BYTES, - - .maps[RWCAM] = REG_CAMCMD, - .maps[WCAMI] = REG_CAMWRITE, - .maps[RCAMO] = REG_CAMREAD, - .maps[CAMDBG] = REG_CAMDBG, - .maps[SECR] = REG_SECCFG, - .maps[SEC_CAM_NONE] = CAM_NONE, - .maps[SEC_CAM_WEP40] = CAM_WEP40, - .maps[SEC_CAM_TKIP] = CAM_TKIP, - .maps[SEC_CAM_AES] = CAM_AES, - .maps[SEC_CAM_WEP104] = CAM_WEP104, - - .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, - .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, - .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, - .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, - .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, - .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, -/* .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, */ /*need check*/ - .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, - .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, - .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, - .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, - .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, - .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, - .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, -/* .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,*/ -/* .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,*/ - - .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, - .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, - .maps[RTL_IMR_BCNINT] = IMR_BCNDMAINT0, - .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, - .maps[RTL_IMR_RDU] = IMR_RDU, - .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, - .maps[RTL_IMR_BDOK] = IMR_BCNDOK0, - .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, - .maps[RTL_IMR_TBDER] = IMR_TBDER, - .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, - .maps[RTL_IMR_TBDOK] = IMR_TBDOK, - .maps[RTL_IMR_BKDOK] = IMR_BKDOK, - .maps[RTL_IMR_BEDOK] = IMR_BEDOK, - .maps[RTL_IMR_VIDOK] = IMR_VIDOK, - .maps[RTL_IMR_VODOK] = IMR_VODOK, - .maps[RTL_IMR_ROK] = IMR_ROK, - .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNDMAINT0 | IMR_TBDOK | IMR_TBDER), - - .maps[RTL_RC_CCK_RATE1M] = DESC_RATE1M, - .maps[RTL_RC_CCK_RATE2M] = DESC_RATE2M, - .maps[RTL_RC_CCK_RATE5_5M] = DESC_RATE5_5M, - .maps[RTL_RC_CCK_RATE11M] = DESC_RATE11M, - .maps[RTL_RC_OFDM_RATE6M] = DESC_RATE6M, - .maps[RTL_RC_OFDM_RATE9M] = DESC_RATE9M, - .maps[RTL_RC_OFDM_RATE12M] = DESC_RATE12M, - .maps[RTL_RC_OFDM_RATE18M] = DESC_RATE18M, - .maps[RTL_RC_OFDM_RATE24M] = DESC_RATE24M, - .maps[RTL_RC_OFDM_RATE36M] = DESC_RATE36M, - .maps[RTL_RC_OFDM_RATE48M] = DESC_RATE48M, - .maps[RTL_RC_OFDM_RATE54M] = DESC_RATE54M, - - .maps[RTL_RC_HT_RATEMCS7] = DESC_RATEMCS7, - .maps[RTL_RC_HT_RATEMCS15] = DESC_RATEMCS15, - - /*VHT hightest rate*/ - .maps[RTL_RC_VHT_RATE_1SS_MCS7] = DESC_RATEVHT1SS_MCS7, - .maps[RTL_RC_VHT_RATE_1SS_MCS8] = DESC_RATEVHT1SS_MCS8, - .maps[RTL_RC_VHT_RATE_1SS_MCS9] = DESC_RATEVHT1SS_MCS9, - .maps[RTL_RC_VHT_RATE_2SS_MCS7] = DESC_RATEVHT2SS_MCS7, - .maps[RTL_RC_VHT_RATE_2SS_MCS8] = DESC_RATEVHT2SS_MCS8, - .maps[RTL_RC_VHT_RATE_2SS_MCS9] = DESC_RATEVHT2SS_MCS9, -}; - -static struct pci_device_id rtl8821ae_pci_ids[] = { - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8812, rtl8821ae_hal_cfg)}, - {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8821, rtl8821ae_hal_cfg)}, - {}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8821ae_pci_ids); - -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_LICENSE("GPL"); -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(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); -module_param_named(msi, rtl8821ae_mod_params.msi_support, bool, 0444); -module_param_named(disable_watchdog, rtl8821ae_mod_params.disable_watchdog, - bool, 0444); -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(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(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); - -static struct pci_driver rtl8821ae_driver = { - .name = KBUILD_MODNAME, - .id_table = rtl8821ae_pci_ids, - .probe = rtl_pci_probe, - .remove = rtl_pci_disconnect, - .driver.pm = &rtlwifi_pm_ops, -}; - -module_pci_driver(rtl8821ae_driver); diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.h b/drivers/net/wireless/rtlwifi/rtl8821ae/sw.h deleted file mode 100644 index d001e7ce3052..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.h +++ /dev/null @@ -1,34 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8821AE_SW_H__ -#define __RTL8821AE_SW_H__ - -int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw); -void rtl8821ae_deinit_sw_vars(struct ieee80211_hw *hw); -void rtl8821ae_init_var_map(struct ieee80211_hw *hw); -bool rtl8821ae_get_btc_status(void); - -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/table.c b/drivers/net/wireless/rtlwifi/rtl8821ae/table.c deleted file mode 100644 index 62a0fb76f080..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/table.c +++ /dev/null @@ -1,4572 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ - -#include "table.h" -u32 RTL8812AE_PHY_REG_ARRAY[] = { - 0x800, 0x8020D010, - 0x804, 0x080112E0, - 0x808, 0x0E028233, - 0x80C, 0x12131113, - 0x810, 0x20101263, - 0x814, 0x020C3D10, - 0x818, 0x03A00385, - 0x820, 0x00000000, - 0x824, 0x00030FE0, - 0x828, 0x00000000, - 0x82C, 0x002083DD, - 0x830, 0x2AAA6C86, - 0x834, 0x0037A706, - 0x838, 0x06C89B44, - 0x83C, 0x0000095B, - 0x840, 0xC0000001, - 0x844, 0x40003CDE, - 0x848, 0x6210FF8B, - 0x84C, 0x6CFDFFB8, - 0x850, 0x28874706, - 0x854, 0x0001520C, - 0x858, 0x8060E000, - 0x85C, 0x74210168, - 0x860, 0x6929C321, - 0x864, 0x79727432, - 0x868, 0x8CA7A314, - 0x86C, 0x338C2878, - 0x870, 0x03333333, - 0x874, 0x31602C2E, - 0x878, 0x00003152, - 0x87C, 0x000FC000, - 0x8A0, 0x00000013, - 0x8A4, 0x7F7F7F7F, - 0x8A8, 0xA202033E, - 0x8AC, 0x0FF0FA0A, - 0x8B0, 0x00000600, - 0x8B4, 0x000FC080, - 0x8B8, 0x6C0057FF, - 0x8BC, 0x4CA520A3, - 0x8C0, 0x27F00020, - 0x8C4, 0x00000000, - 0x8C8, 0x00013169, - 0x8CC, 0x08248492, - 0x8D0, 0x0000B800, - 0x8DC, 0x00000000, - 0x8D4, 0x940008A0, - 0x8D8, 0x290B5612, - 0x8F8, 0x400002C0, - 0x8FC, 0x00000000, - 0xFF0F07D8, 0xABCD, - 0x900, 0x00000701, - 0xFF0F07D0, 0xCDEF, - 0x900, 0x00000701, - 0xCDCDCDCD, 0xCDCD, - 0x900, 0x00000700, - 0xFF0F07D8, 0xDEAD, - 0x90C, 0x00000000, - 0x910, 0x0000FC00, - 0x914, 0x00000404, - 0x918, 0x1C1028C0, - 0x91C, 0x64B11A1C, - 0x920, 0xE0767233, - 0x924, 0x055AA500, - 0x928, 0x00000004, - 0x92C, 0xFFFE0000, - 0x930, 0xFFFFFFFE, - 0x934, 0x001FFFFF, - 0x960, 0x00000000, - 0x964, 0x00000000, - 0x968, 0x00000000, - 0x96C, 0x00000000, - 0x970, 0x801FFFFF, - 0x978, 0x00000000, - 0x97C, 0x00000000, - 0x980, 0x00000000, - 0x984, 0x00000000, - 0x988, 0x00000000, - 0x990, 0x27100000, - 0x994, 0xFFFF0100, - 0x998, 0xFFFFFF5C, - 0x99C, 0xFFFFFFFF, - 0x9A0, 0x000000FF, - 0x9A4, 0x00080080, - 0x9A8, 0x00000000, - 0x9AC, 0x00000000, - 0x9B0, 0x81081008, - 0x9B4, 0x00000000, - 0x9B8, 0x01081008, - 0x9BC, 0x01081008, - 0x9D0, 0x00000000, - 0x9D4, 0x00000000, - 0x9D8, 0x00000000, - 0x9DC, 0x00000000, - 0x9E4, 0x00000002, - 0x9E8, 0x000002D5, - 0xA00, 0x00D047C8, - 0xA04, 0x01FF000C, - 0xA08, 0x8C838300, - 0xA0C, 0x2E7F000F, - 0xA10, 0x9500BB78, - 0xA14, 0x11144028, - 0xA18, 0x00881117, - 0xA1C, 0x89140F00, - 0xA20, 0x1A1B0000, - 0xA24, 0x090E1317, - 0xA28, 0x00000204, - 0xA2C, 0x00900000, - 0xA70, 0x101FFF00, - 0xA74, 0x00000008, - 0xA78, 0x00000900, - 0xA7C, 0x225B0606, - 0xA80, 0x218075B2, - 0xA84, 0x001F8C80, - 0xB00, 0x03100000, - 0xB04, 0x0000B000, - 0xB08, 0xAE0201EB, - 0xB0C, 0x01003207, - 0xB10, 0x00009807, - 0xB14, 0x01000000, - 0xB18, 0x00000002, - 0xB1C, 0x00000002, - 0xB20, 0x0000001F, - 0xB24, 0x03020100, - 0xB28, 0x07060504, - 0xB2C, 0x0B0A0908, - 0xB30, 0x0F0E0D0C, - 0xB34, 0x13121110, - 0xB38, 0x17161514, - 0xB3C, 0x0000003A, - 0xB40, 0x00000000, - 0xB44, 0x00000000, - 0xB48, 0x13000032, - 0xB4C, 0x48080000, - 0xB50, 0x00000000, - 0xB54, 0x00000000, - 0xB58, 0x00000000, - 0xB5C, 0x00000000, - 0xC00, 0x00000007, - 0xC04, 0x00042020, - 0xC08, 0x80410231, - 0xC0C, 0x00000000, - 0xC10, 0x00000100, - 0xC14, 0x01000000, - 0xC1C, 0x40000003, - 0xC20, 0x12121212, - 0xC24, 0x12121212, - 0xC28, 0x12121212, - 0xC2C, 0x12121212, - 0xC30, 0x12121212, - 0xC34, 0x12121212, - 0xC38, 0x12121212, - 0xC3C, 0x12121212, - 0xC40, 0x12121212, - 0xC44, 0x12121212, - 0xC48, 0x12121212, - 0xC4C, 0x12121212, - 0xC50, 0x00000020, - 0xC54, 0x0008121C, - 0xC58, 0x30000C1C, - 0xC5C, 0x00000058, - 0xC60, 0x34344443, - 0xC64, 0x07003333, - 0xC68, 0x59791979, - 0xC6C, 0x59795979, - 0xC70, 0x19795979, - 0xC74, 0x19795979, - 0xC78, 0x19791979, - 0xC7C, 0x19791979, - 0xC80, 0x19791979, - 0xC84, 0x19791979, - 0xC94, 0x0100005C, - 0xC98, 0x00000000, - 0xC9C, 0x00000000, - 0xCA0, 0x00000029, - 0xCA4, 0x08040201, - 0xCA8, 0x80402010, - 0xFF0F0740, 0xABCD, - 0xCB0, 0x77547717, - 0xFF0F01C0, 0xCDEF, - 0xCB0, 0x77547717, - 0xFF0F02C0, 0xCDEF, - 0xCB0, 0x77547717, - 0xFF0F07D8, 0xCDEF, - 0xCB0, 0x54547710, - 0xFF0F07D0, 0xCDEF, - 0xCB0, 0x54547710, - 0xCDCDCDCD, 0xCDCD, - 0xCB0, 0x77547777, - 0xFF0F0740, 0xDEAD, - 0xCB4, 0x00000077, - 0xCB8, 0x00508242, - 0xE00, 0x00000007, - 0xE04, 0x00042020, - 0xE08, 0x80410231, - 0xE0C, 0x00000000, - 0xE10, 0x00000100, - 0xE14, 0x01000000, - 0xE1C, 0x40000003, - 0xE20, 0x12121212, - 0xE24, 0x12121212, - 0xE28, 0x12121212, - 0xE2C, 0x12121212, - 0xE30, 0x12121212, - 0xE34, 0x12121212, - 0xE38, 0x12121212, - 0xE3C, 0x12121212, - 0xE40, 0x12121212, - 0xE44, 0x12121212, - 0xE48, 0x12121212, - 0xE4C, 0x12121212, - 0xE50, 0x00000020, - 0xE54, 0x0008121C, - 0xE58, 0x30000C1C, - 0xE5C, 0x00000058, - 0xE60, 0x34344443, - 0xE64, 0x07003333, - 0xE68, 0x59791979, - 0xE6C, 0x59795979, - 0xE70, 0x19795979, - 0xE74, 0x19795979, - 0xE78, 0x19791979, - 0xE7C, 0x19791979, - 0xE80, 0x19791979, - 0xE84, 0x19791979, - 0xE94, 0x0100005C, - 0xE98, 0x00000000, - 0xE9C, 0x00000000, - 0xEA0, 0x00000029, - 0xEA4, 0x08040201, - 0xEA8, 0x80402010, - 0xFF0F0740, 0xABCD, - 0xEB0, 0x77547717, - 0xFF0F01C0, 0xCDEF, - 0xEB0, 0x77547717, - 0xFF0F02C0, 0xCDEF, - 0xEB0, 0x77547717, - 0xFF0F07D8, 0xCDEF, - 0xEB0, 0x54547710, - 0xFF0F07D0, 0xCDEF, - 0xEB0, 0x54547710, - 0xCDCDCDCD, 0xCDCD, - 0xEB0, 0x77547777, - 0xFF0F0740, 0xDEAD, - 0xEB4, 0x00000077, - 0xEB8, 0x00508242, -}; - -u32 RTL8821AE_PHY_REG_ARRAY[] = { - 0x800, 0x0020D090, - 0x804, 0x080112E0, - 0x808, 0x0E028211, - 0x80C, 0x92131111, - 0x810, 0x20101261, - 0x814, 0x020C3D10, - 0x818, 0x03A00385, - 0x820, 0x00000000, - 0x824, 0x00030FE0, - 0x828, 0x00000000, - 0x82C, 0x002081DD, - 0x830, 0x2AAA8E24, - 0x834, 0x0037A706, - 0x838, 0x06489B44, - 0x83C, 0x0000095B, - 0x840, 0xC0000001, - 0x844, 0x40003CDE, - 0x848, 0x62103F8B, - 0x84C, 0x6CFDFFB8, - 0x850, 0x28874706, - 0x854, 0x0001520C, - 0x858, 0x8060E000, - 0x85C, 0x74210168, - 0x860, 0x6929C321, - 0x864, 0x79727432, - 0x868, 0x8CA7A314, - 0x86C, 0x888C2878, - 0x870, 0x08888888, - 0x874, 0x31612C2E, - 0x878, 0x00000152, - 0x87C, 0x000FD000, - 0x8A0, 0x00000013, - 0x8A4, 0x7F7F7F7F, - 0x8A8, 0xA2000338, - 0x8AC, 0x0FF0FA0A, - 0x8B4, 0x000FC080, - 0x8B8, 0x6C10D7FF, - 0x8BC, 0x0CA52090, - 0x8C0, 0x1BF00020, - 0x8C4, 0x00000000, - 0x8C8, 0x00013169, - 0x8CC, 0x08248492, - 0x8D4, 0x940008A0, - 0x8D8, 0x290B5612, - 0x8F8, 0x400002C0, - 0x8FC, 0x00000000, - 0x900, 0x00000700, - 0x90C, 0x00000000, - 0x910, 0x0000FC00, - 0x914, 0x00000404, - 0x918, 0x1C1028C0, - 0x91C, 0x64B11A1C, - 0x920, 0xE0767233, - 0x924, 0x055AA500, - 0x928, 0x00000004, - 0x92C, 0xFFFE0000, - 0x930, 0xFFFFFFFE, - 0x934, 0x001FFFFF, - 0x960, 0x00000000, - 0x964, 0x00000000, - 0x968, 0x00000000, - 0x96C, 0x00000000, - 0x970, 0x801FFFFF, - 0x974, 0x000003FF, - 0x978, 0x00000000, - 0x97C, 0x00000000, - 0x980, 0x00000000, - 0x984, 0x00000000, - 0x988, 0x00000000, - 0x990, 0x27100000, - 0x994, 0xFFFF0100, - 0x998, 0xFFFFFF5C, - 0x99C, 0xFFFFFFFF, - 0x9A0, 0x000000FF, - 0x9A4, 0x00480080, - 0x9A8, 0x00000000, - 0x9AC, 0x00000000, - 0x9B0, 0x81081008, - 0x9B4, 0x01081008, - 0x9B8, 0x01081008, - 0x9BC, 0x01081008, - 0x9D0, 0x00000000, - 0x9D4, 0x00000000, - 0x9D8, 0x00000000, - 0x9DC, 0x00000000, - 0x9E0, 0x00005D00, - 0x9E4, 0x00000002, - 0x9E8, 0x00000001, - 0xA00, 0x00D047C8, - 0xA04, 0x01FF000C, - 0xA08, 0x8C8A8300, - 0xA0C, 0x2E68000F, - 0xA10, 0x9500BB78, - 0xA14, 0x11144028, - 0xA18, 0x00881117, - 0xA1C, 0x89140F00, - 0xA20, 0x1A1B0000, - 0xA24, 0x090E1317, - 0xA28, 0x00000204, - 0xA2C, 0x00900000, - 0xA70, 0x101FFF00, - 0xA74, 0x00000008, - 0xA78, 0x00000900, - 0xA7C, 0x225B0606, - 0xA80, 0x21805490, - 0xA84, 0x001F0000, - 0xB00, 0x03100040, - 0xB04, 0x0000B000, - 0xB08, 0xAE0201EB, - 0xB0C, 0x01003207, - 0xB10, 0x00009807, - 0xB14, 0x01000000, - 0xB18, 0x00000002, - 0xB1C, 0x00000002, - 0xB20, 0x0000001F, - 0xB24, 0x03020100, - 0xB28, 0x07060504, - 0xB2C, 0x0B0A0908, - 0xB30, 0x0F0E0D0C, - 0xB34, 0x13121110, - 0xB38, 0x17161514, - 0xB3C, 0x0000003A, - 0xB40, 0x00000000, - 0xB44, 0x00000000, - 0xB48, 0x13000032, - 0xB4C, 0x48080000, - 0xB50, 0x00000000, - 0xB54, 0x00000000, - 0xB58, 0x00000000, - 0xB5C, 0x00000000, - 0xC00, 0x00000007, - 0xC04, 0x00042020, - 0xC08, 0x80410231, - 0xC0C, 0x00000000, - 0xC10, 0x00000100, - 0xC14, 0x01000000, - 0xC1C, 0x40000003, - 0xC20, 0x2C2C2C2C, - 0xC24, 0x30303030, - 0xC28, 0x30303030, - 0xC2C, 0x2C2C2C2C, - 0xC30, 0x2C2C2C2C, - 0xC34, 0x2C2C2C2C, - 0xC38, 0x2C2C2C2C, - 0xC3C, 0x2A2A2A2A, - 0xC40, 0x2A2A2A2A, - 0xC44, 0x2A2A2A2A, - 0xC48, 0x2A2A2A2A, - 0xC4C, 0x2A2A2A2A, - 0xC50, 0x00000020, - 0xC54, 0x001C1208, - 0xC58, 0x30000C1C, - 0xC5C, 0x00000058, - 0xC60, 0x34344443, - 0xC64, 0x07003333, - 0xC68, 0x19791979, - 0xC6C, 0x19791979, - 0xC70, 0x19791979, - 0xC74, 0x19791979, - 0xC78, 0x19791979, - 0xC7C, 0x19791979, - 0xC80, 0x19791979, - 0xC84, 0x19791979, - 0xC94, 0x0100005C, - 0xC98, 0x00000000, - 0xC9C, 0x00000000, - 0xCA0, 0x00000029, - 0xCA4, 0x08040201, - 0xCA8, 0x80402010, - 0xCB0, 0x77775747, - 0xCB4, 0x10000077, - 0xCB8, 0x00508240, -}; - -u32 RTL8812AE_PHY_REG_ARRAY_PG[] = { - 0, 0, 0, 0x00000c20, 0xffffffff, 0x34363840, - 0, 0, 0, 0x00000c24, 0xffffffff, 0x42424444, - 0, 0, 0, 0x00000c28, 0xffffffff, 0x30323638, - 0, 0, 0, 0x00000c2c, 0xffffffff, 0x40424444, - 0, 0, 0, 0x00000c30, 0xffffffff, 0x28303236, - 0, 0, 1, 0x00000c34, 0xffffffff, 0x38404242, - 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283034, - 0, 0, 0, 0x00000c3c, 0xffffffff, 0x40424444, - 0, 0, 0, 0x00000c40, 0xffffffff, 0x28303236, - 0, 0, 0, 0x00000c44, 0xffffffff, 0x42422426, - 0, 0, 1, 0x00000c48, 0xffffffff, 0x30343840, - 0, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, - 0, 1, 0, 0x00000e20, 0xffffffff, 0x34363840, - 0, 1, 0, 0x00000e24, 0xffffffff, 0x42424444, - 0, 1, 0, 0x00000e28, 0xffffffff, 0x30323638, - 0, 1, 0, 0x00000e2c, 0xffffffff, 0x40424444, - 0, 1, 0, 0x00000e30, 0xffffffff, 0x28303236, - 0, 1, 1, 0x00000e34, 0xffffffff, 0x38404242, - 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283034, - 0, 1, 0, 0x00000e3c, 0xffffffff, 0x40424444, - 0, 1, 0, 0x00000e40, 0xffffffff, 0x28303236, - 0, 1, 0, 0x00000e44, 0xffffffff, 0x42422426, - 0, 1, 1, 0x00000e48, 0xffffffff, 0x30343840, - 0, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, - 1, 0, 0, 0x00000c24, 0xffffffff, 0x42424444, - 1, 0, 0, 0x00000c28, 0xffffffff, 0x30323640, - 1, 0, 0, 0x00000c2c, 0xffffffff, 0x40424444, - 1, 0, 0, 0x00000c30, 0xffffffff, 0x28303236, - 1, 0, 1, 0x00000c34, 0xffffffff, 0x38404242, - 1, 0, 1, 0x00000c38, 0xffffffff, 0x26283034, - 1, 0, 0, 0x00000c3c, 0xffffffff, 0x40424444, - 1, 0, 0, 0x00000c40, 0xffffffff, 0x28303236, - 1, 0, 0, 0x00000c44, 0xffffffff, 0x42422426, - 1, 0, 1, 0x00000c48, 0xffffffff, 0x30343840, - 1, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, - 1, 1, 0, 0x00000e24, 0xffffffff, 0x42424444, - 1, 1, 0, 0x00000e28, 0xffffffff, 0x30323640, - 1, 1, 0, 0x00000e2c, 0xffffffff, 0x40424444, - 1, 1, 0, 0x00000e30, 0xffffffff, 0x28303236, - 1, 1, 1, 0x00000e34, 0xffffffff, 0x38404242, - 1, 1, 1, 0x00000e38, 0xffffffff, 0x26283034, - 1, 1, 0, 0x00000e3c, 0xffffffff, 0x40424444, - 1, 1, 0, 0x00000e40, 0xffffffff, 0x28303236, - 1, 1, 0, 0x00000e44, 0xffffffff, 0x42422426, - 1, 1, 1, 0x00000e48, 0xffffffff, 0x30343840, - 1, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628 -}; - -u32 RTL8821AE_PHY_REG_ARRAY_PG[] = { - 0, 0, 0, 0x00000c20, 0xffffffff, 0x32343638, - 0, 0, 0, 0x00000c24, 0xffffffff, 0x36363838, - 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303234, - 0, 0, 0, 0x00000c2c, 0xffffffff, 0x34363838, - 0, 0, 0, 0x00000c30, 0xffffffff, 0x26283032, - 0, 0, 0, 0x00000c3c, 0xffffffff, 0x32343636, - 0, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, - 0, 0, 0, 0x00000c44, 0x0000ffff, 0x00002022, - 1, 0, 0, 0x00000c24, 0xffffffff, 0x34343636, - 1, 0, 0, 0x00000c28, 0xffffffff, 0x26283032, - 1, 0, 0, 0x00000c2c, 0xffffffff, 0x32343636, - 1, 0, 0, 0x00000c30, 0xffffffff, 0x24262830, - 1, 0, 0, 0x00000c3c, 0xffffffff, 0x32343636, - 1, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, - 1, 0, 0, 0x00000c44, 0x0000ffff, 0x00002022 -}; - -u32 RTL8812AE_RADIOA_ARRAY[] = { - 0x000, 0x00010000, - 0x018, 0x0001712A, - 0x056, 0x00051CF2, - 0x066, 0x00040000, - 0x01E, 0x00080000, - 0x089, 0x00000080, - 0xFF0F0740, 0xABCD, - 0x086, 0x00014B38, - 0xFF0F02C0, 0xCDEF, - 0x086, 0x00014B38, - 0xFF0F01C0, 0xCDEF, - 0x086, 0x00014B38, - 0xFF0F07D8, 0xCDEF, - 0x086, 0x00014B3A, - 0xFF0F07D0, 0xCDEF, - 0x086, 0x00014B3A, - 0xCDCDCDCD, 0xCDCD, - 0x086, 0x00014B38, - 0xFF0F0740, 0xDEAD, - 0x0B1, 0x0001FC1A, - 0x0B3, 0x000F0810, - 0x0B4, 0x0001A78D, - 0x0BA, 0x00086180, - 0x018, 0x00000006, - 0x0EF, 0x00002000, - 0xFF0F07D8, 0xABCD, - 0x03B, 0x0003F218, - 0x03B, 0x00030A58, - 0x03B, 0x0002FA58, - 0x03B, 0x00022590, - 0x03B, 0x0001FA50, - 0x03B, 0x00010248, - 0x03B, 0x00008240, - 0xFF0F07D0, 0xCDEF, - 0x03B, 0x0003F218, - 0x03B, 0x00030A58, - 0x03B, 0x0002FA58, - 0x03B, 0x00022590, - 0x03B, 0x0001FA50, - 0x03B, 0x00010248, - 0x03B, 0x00008240, - 0xCDCDCDCD, 0xCDCD, - 0x03B, 0x00038A58, - 0x03B, 0x00037A58, - 0x03B, 0x0002A590, - 0x03B, 0x00027A50, - 0x03B, 0x00018248, - 0x03B, 0x00010240, - 0x03B, 0x00008240, - 0xFF0F07D8, 0xDEAD, - 0x0EF, 0x00000100, - 0xFF0F07D8, 0xABCD, - 0x034, 0x0000A4EE, - 0x034, 0x00009076, - 0x034, 0x00008073, - 0x034, 0x00007070, - 0x034, 0x0000606D, - 0x034, 0x0000506A, - 0x034, 0x00004049, - 0x034, 0x00003046, - 0x034, 0x00002028, - 0x034, 0x00001025, - 0x034, 0x00000022, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0000ADF4, - 0x034, 0x00009DF1, - 0x034, 0x00008DEE, - 0x034, 0x00007DEB, - 0x034, 0x00006DE8, - 0x034, 0x00005CEC, - 0x034, 0x00004CE9, - 0x034, 0x000034EA, - 0x034, 0x000024E7, - 0x034, 0x0000146B, - 0x034, 0x0000006D, - 0xFF0F07D8, 0xDEAD, - 0x0EF, 0x00000000, - 0x0EF, 0x000020A2, - 0x0DF, 0x00000080, - 0x035, 0x00000192, - 0x035, 0x00008192, - 0x035, 0x00010192, - 0x036, 0x00000024, - 0x036, 0x00008024, - 0x036, 0x00010024, - 0x036, 0x00018024, - 0x0EF, 0x00000000, - 0x051, 0x00000C21, - 0x052, 0x000006D9, - 0x053, 0x000FC649, - 0x054, 0x0000017E, - 0x0EF, 0x00000002, - 0x008, 0x00008400, - 0x018, 0x0001712A, - 0x0EF, 0x00001000, - 0x03A, 0x00000080, - 0x03B, 0x0003A02C, - 0x03C, 0x00004000, - 0x03A, 0x00000400, - 0x03B, 0x0003202C, - 0x03C, 0x00010000, - 0x03A, 0x000000A0, - 0x03B, 0x0002B064, - 0x03C, 0x00004000, - 0x03A, 0x000000D8, - 0x03B, 0x00023070, - 0x03C, 0x00004000, - 0x03A, 0x00000468, - 0x03B, 0x0001B870, - 0x03C, 0x00010000, - 0x03A, 0x00000098, - 0x03B, 0x00012085, - 0x03C, 0x000E4000, - 0x03A, 0x00000418, - 0x03B, 0x0000A080, - 0x03C, 0x000F0000, - 0x03A, 0x00000418, - 0x03B, 0x00002080, - 0x03C, 0x00010000, - 0x03A, 0x00000080, - 0x03B, 0x0007A02C, - 0x03C, 0x00004000, - 0x03A, 0x00000400, - 0x03B, 0x0007202C, - 0x03C, 0x00010000, - 0x03A, 0x000000A0, - 0x03B, 0x0006B064, - 0x03C, 0x00004000, - 0x03A, 0x000000D8, - 0x03B, 0x00023070, - 0x03C, 0x00004000, - 0x03A, 0x00000468, - 0x03B, 0x0005B870, - 0x03C, 0x00010000, - 0x03A, 0x00000098, - 0x03B, 0x00052085, - 0x03C, 0x000E4000, - 0x03A, 0x00000418, - 0x03B, 0x0004A080, - 0x03C, 0x000F0000, - 0x03A, 0x00000418, - 0x03B, 0x00042080, - 0x03C, 0x00010000, - 0x03A, 0x00000080, - 0x03B, 0x000BA02C, - 0x03C, 0x00004000, - 0x03A, 0x00000400, - 0x03B, 0x000B202C, - 0x03C, 0x00010000, - 0x03A, 0x000000A0, - 0x03B, 0x000AB064, - 0x03C, 0x00004000, - 0x03A, 0x000000D8, - 0x03B, 0x000A3070, - 0x03C, 0x00004000, - 0x03A, 0x00000468, - 0x03B, 0x0009B870, - 0x03C, 0x00010000, - 0x03A, 0x00000098, - 0x03B, 0x00092085, - 0x03C, 0x000E4000, - 0x03A, 0x00000418, - 0x03B, 0x0008A080, - 0x03C, 0x000F0000, - 0x03A, 0x00000418, - 0x03B, 0x00082080, - 0x03C, 0x00010000, - 0x0EF, 0x00001100, - 0xFF0F0740, 0xABCD, - 0x034, 0x0004A0B2, - 0x034, 0x000490AF, - 0x034, 0x00048070, - 0x034, 0x0004706D, - 0x034, 0x00046050, - 0x034, 0x0004504D, - 0x034, 0x0004404A, - 0x034, 0x00043047, - 0x034, 0x0004200A, - 0x034, 0x00041007, - 0x034, 0x00040004, - 0xFF0F02C0, 0xCDEF, - 0x034, 0x0004A0B2, - 0x034, 0x000490AF, - 0x034, 0x00048070, - 0x034, 0x0004706D, - 0x034, 0x00046050, - 0x034, 0x0004504D, - 0x034, 0x0004404A, - 0x034, 0x00043047, - 0x034, 0x0004200A, - 0x034, 0x00041007, - 0x034, 0x00040004, - 0xFF0F01C0, 0xCDEF, - 0x034, 0x0004A0B2, - 0x034, 0x000490AF, - 0x034, 0x00048070, - 0x034, 0x0004706D, - 0x034, 0x00046050, - 0x034, 0x0004504D, - 0x034, 0x0004404A, - 0x034, 0x00043047, - 0x034, 0x0004200A, - 0x034, 0x00041007, - 0x034, 0x00040004, - 0xFF0F07D8, 0xCDEF, - 0x034, 0x0004A0B2, - 0x034, 0x000490AF, - 0x034, 0x00048070, - 0x034, 0x0004706D, - 0x034, 0x00046050, - 0x034, 0x0004504D, - 0x034, 0x0004404A, - 0x034, 0x00043047, - 0x034, 0x0004200A, - 0x034, 0x00041007, - 0x034, 0x00040004, - 0xFF0F07D0, 0xCDEF, - 0x034, 0x0004A0B2, - 0x034, 0x000490AF, - 0x034, 0x00048070, - 0x034, 0x0004706D, - 0x034, 0x00046050, - 0x034, 0x0004504D, - 0x034, 0x0004404A, - 0x034, 0x00043047, - 0x034, 0x0004200A, - 0x034, 0x00041007, - 0x034, 0x00040004, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0004ADF5, - 0x034, 0x00049DF2, - 0x034, 0x00048DEF, - 0x034, 0x00047DEC, - 0x034, 0x00046DE9, - 0x034, 0x00045DC9, - 0x034, 0x00044CE8, - 0x034, 0x000438CA, - 0x034, 0x00042889, - 0x034, 0x0004184A, - 0x034, 0x0004044A, - 0xFF0F0740, 0xDEAD, - 0xFF0F0740, 0xABCD, - 0x034, 0x0002A0B2, - 0x034, 0x000290AF, - 0x034, 0x00028070, - 0x034, 0x0002706D, - 0x034, 0x00026050, - 0x034, 0x0002504D, - 0x034, 0x0002404A, - 0x034, 0x00023047, - 0x034, 0x0002200A, - 0x034, 0x00021007, - 0x034, 0x00020004, - 0xFF0F02C0, 0xCDEF, - 0x034, 0x0002A0B2, - 0x034, 0x000290AF, - 0x034, 0x00028070, - 0x034, 0x0002706D, - 0x034, 0x00026050, - 0x034, 0x0002504D, - 0x034, 0x0002404A, - 0x034, 0x00023047, - 0x034, 0x0002200A, - 0x034, 0x00021007, - 0x034, 0x00020004, - 0xFF0F01C0, 0xCDEF, - 0x034, 0x0002A0B2, - 0x034, 0x000290AF, - 0x034, 0x00028070, - 0x034, 0x0002706D, - 0x034, 0x00026050, - 0x034, 0x0002504D, - 0x034, 0x0002404A, - 0x034, 0x00023047, - 0x034, 0x0002200A, - 0x034, 0x00021007, - 0x034, 0x00020004, - 0xFF0F07D8, 0xCDEF, - 0x034, 0x0002A0B2, - 0x034, 0x000290AF, - 0x034, 0x00028070, - 0x034, 0x0002706D, - 0x034, 0x00026050, - 0x034, 0x0002504D, - 0x034, 0x0002404A, - 0x034, 0x00023047, - 0x034, 0x0002200A, - 0x034, 0x00021007, - 0x034, 0x00020004, - 0xFF0F07D0, 0xCDEF, - 0x034, 0x0002A0B2, - 0x034, 0x000290AF, - 0x034, 0x00028070, - 0x034, 0x0002706D, - 0x034, 0x00026050, - 0x034, 0x0002504D, - 0x034, 0x0002404A, - 0x034, 0x00023047, - 0x034, 0x0002200A, - 0x034, 0x00021007, - 0x034, 0x00020004, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0002ADF5, - 0x034, 0x00029DF2, - 0x034, 0x00028DEF, - 0x034, 0x00027DEC, - 0x034, 0x00026DE9, - 0x034, 0x00025DC9, - 0x034, 0x00024CE8, - 0x034, 0x000238CA, - 0x034, 0x00022889, - 0x034, 0x0002184A, - 0x034, 0x0002044A, - 0xFF0F0740, 0xDEAD, - 0xFF0F0740, 0xABCD, - 0x034, 0x0000A0B2, - 0x034, 0x000090AF, - 0x034, 0x00008070, - 0x034, 0x0000706D, - 0x034, 0x00006050, - 0x034, 0x0000504D, - 0x034, 0x0000404A, - 0x034, 0x00003047, - 0x034, 0x0000200A, - 0x034, 0x00001007, - 0x034, 0x00000004, - 0xFF0F02C0, 0xCDEF, - 0x034, 0x0000A0B2, - 0x034, 0x000090AF, - 0x034, 0x00008070, - 0x034, 0x0000706D, - 0x034, 0x00006050, - 0x034, 0x0000504D, - 0x034, 0x0000404A, - 0x034, 0x00003047, - 0x034, 0x0000200A, - 0x034, 0x00001007, - 0x034, 0x00000004, - 0xFF0F01C0, 0xCDEF, - 0x034, 0x0000A0B2, - 0x034, 0x000090AF, - 0x034, 0x00008070, - 0x034, 0x0000706D, - 0x034, 0x00006050, - 0x034, 0x0000504D, - 0x034, 0x0000404A, - 0x034, 0x00003047, - 0x034, 0x0000200A, - 0x034, 0x00001007, - 0x034, 0x00000004, - 0xFF0F07D8, 0xCDEF, - 0x034, 0x0000A0B2, - 0x034, 0x000090AF, - 0x034, 0x00008070, - 0x034, 0x0000706D, - 0x034, 0x00006050, - 0x034, 0x0000504D, - 0x034, 0x0000404A, - 0x034, 0x00003047, - 0x034, 0x0000200A, - 0x034, 0x00001007, - 0x034, 0x00000004, - 0xFF0F07D0, 0xCDEF, - 0x034, 0x0000A0B2, - 0x034, 0x000090AF, - 0x034, 0x00008070, - 0x034, 0x0000706D, - 0x034, 0x00006050, - 0x034, 0x0000504D, - 0x034, 0x0000404A, - 0x034, 0x00003047, - 0x034, 0x0000200A, - 0x034, 0x00001007, - 0x034, 0x00000004, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0000AFF7, - 0x034, 0x00009DF7, - 0x034, 0x00008DF4, - 0x034, 0x00007DF1, - 0x034, 0x00006DEE, - 0x034, 0x00005DCD, - 0x034, 0x00004CEB, - 0x034, 0x000038CC, - 0x034, 0x0000288B, - 0x034, 0x0000184C, - 0x034, 0x0000044C, - 0xFF0F0740, 0xDEAD, - 0x0EF, 0x00000000, - 0xFF0F0740, 0xABCD, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0x035, 0x000001D4, - 0x035, 0x000081D4, - 0x035, 0x000101D4, - 0x035, 0x000201B4, - 0x035, 0x000281B4, - 0x035, 0x000301B4, - 0x035, 0x000401B4, - 0x035, 0x000481B4, - 0x035, 0x000501B4, - 0xFF0F02C0, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0x035, 0x000001D4, - 0x035, 0x000081D4, - 0x035, 0x000101D4, - 0x035, 0x000201B4, - 0x035, 0x000281B4, - 0x035, 0x000301B4, - 0x035, 0x000401B4, - 0x035, 0x000481B4, - 0x035, 0x000501B4, - 0xFF0F01C0, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0x035, 0x000001D4, - 0x035, 0x000081D4, - 0x035, 0x000101D4, - 0x035, 0x000201B4, - 0x035, 0x000281B4, - 0x035, 0x000301B4, - 0x035, 0x000401B4, - 0x035, 0x000481B4, - 0x035, 0x000501B4, - 0xFF0F07D8, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0x035, 0x000001D4, - 0x035, 0x000081D4, - 0x035, 0x000101D4, - 0x035, 0x000201B4, - 0x035, 0x000281B4, - 0x035, 0x000301B4, - 0x035, 0x000401B4, - 0x035, 0x000481B4, - 0x035, 0x000501B4, - 0xFF0F07D0, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0x035, 0x000001D4, - 0x035, 0x000081D4, - 0x035, 0x000101D4, - 0x035, 0x000201B4, - 0x035, 0x000281B4, - 0x035, 0x000301B4, - 0x035, 0x000401B4, - 0x035, 0x000481B4, - 0x035, 0x000501B4, - 0xCDCDCDCD, 0xCDCD, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0x035, 0x00000188, - 0x035, 0x00008147, - 0x035, 0x00010147, - 0x035, 0x000201D7, - 0x035, 0x000281D7, - 0x035, 0x000301D7, - 0x035, 0x000401D8, - 0x035, 0x000481D8, - 0x035, 0x000501D8, - 0xFF0F0740, 0xDEAD, - 0x0EF, 0x00000000, - 0xFF0F0740, 0xABCD, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0x036, 0x00004BFB, - 0x036, 0x0000CBFB, - 0x036, 0x00014BFB, - 0x036, 0x0001CBFB, - 0x036, 0x00024F4B, - 0x036, 0x0002CF4B, - 0x036, 0x00034F4B, - 0x036, 0x0003CF4B, - 0x036, 0x00044F4B, - 0x036, 0x0004CF4B, - 0x036, 0x00054F4B, - 0x036, 0x0005CF4B, - 0xFF0F02C0, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0x036, 0x00004BFB, - 0x036, 0x0000CBFB, - 0x036, 0x00014BFB, - 0x036, 0x0001CBFB, - 0x036, 0x00024F4B, - 0x036, 0x0002CF4B, - 0x036, 0x00034F4B, - 0x036, 0x0003CF4B, - 0x036, 0x00044F4B, - 0x036, 0x0004CF4B, - 0x036, 0x00054F4B, - 0x036, 0x0005CF4B, - 0xFF0F01C0, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0x036, 0x00004BFB, - 0x036, 0x0000CBFB, - 0x036, 0x00014BFB, - 0x036, 0x0001CBFB, - 0x036, 0x00024F4B, - 0x036, 0x0002CF4B, - 0x036, 0x00034F4B, - 0x036, 0x0003CF4B, - 0x036, 0x00044F4B, - 0x036, 0x0004CF4B, - 0x036, 0x00054F4B, - 0x036, 0x0005CF4B, - 0xFF0F07D8, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0x036, 0x00004BFB, - 0x036, 0x0000CBFB, - 0x036, 0x00014BFB, - 0x036, 0x0001CBFB, - 0x036, 0x00024F4B, - 0x036, 0x0002CF4B, - 0x036, 0x00034F4B, - 0x036, 0x0003CF4B, - 0x036, 0x00044F4B, - 0x036, 0x0004CF4B, - 0x036, 0x00054F4B, - 0x036, 0x0005CF4B, - 0xFF0F07D0, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0x036, 0x00004BFB, - 0x036, 0x0000CBFB, - 0x036, 0x00014BFB, - 0x036, 0x0001CBFB, - 0x036, 0x00024F4B, - 0x036, 0x0002CF4B, - 0x036, 0x00034F4B, - 0x036, 0x0003CF4B, - 0x036, 0x00044F4B, - 0x036, 0x0004CF4B, - 0x036, 0x00054F4B, - 0x036, 0x0005CF4B, - 0xCDCDCDCD, 0xCDCD, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0x036, 0x00084EB4, - 0x036, 0x0008CC35, - 0x036, 0x00094C35, - 0x036, 0x0009CC35, - 0x036, 0x000A4935, - 0x036, 0x000ACC35, - 0x036, 0x000B4C35, - 0x036, 0x000BCC35, - 0x036, 0x000C4EB4, - 0x036, 0x000CCEB5, - 0x036, 0x000D4EB5, - 0x036, 0x000DCEB5, - 0xFF0F0740, 0xDEAD, - 0x0EF, 0x00000000, - 0x0EF, 0x00000008, - 0xFF0F0740, 0xABCD, - 0x03C, 0x000002CC, - 0x03C, 0x00000522, - 0x03C, 0x00000902, - 0xFF0F02C0, 0xCDEF, - 0x03C, 0x000002CC, - 0x03C, 0x00000522, - 0x03C, 0x00000902, - 0xFF0F01C0, 0xCDEF, - 0x03C, 0x000002CC, - 0x03C, 0x00000522, - 0x03C, 0x00000902, - 0xFF0F07D8, 0xCDEF, - 0x03C, 0x000002CC, - 0x03C, 0x00000522, - 0x03C, 0x00000902, - 0xFF0F07D0, 0xCDEF, - 0x03C, 0x000002CC, - 0x03C, 0x00000522, - 0x03C, 0x00000902, - 0xCDCDCDCD, 0xCDCD, - 0x03C, 0x000002A8, - 0x03C, 0x000005A2, - 0x03C, 0x00000880, - 0xFF0F0740, 0xDEAD, - 0x0EF, 0x00000000, - 0x018, 0x0001712A, - 0x0EF, 0x00000002, - 0x0DF, 0x00000080, - 0x01F, 0x00040064, - 0xFF0F0740, 0xABCD, - 0x061, 0x000FDD43, - 0x062, 0x00038F4B, - 0x063, 0x00032117, - 0x064, 0x000194AC, - 0x065, 0x000931D1, - 0xFF0F02C0, 0xCDEF, - 0x061, 0x000FDD43, - 0x062, 0x00038F4B, - 0x063, 0x00032117, - 0x064, 0x000194AC, - 0x065, 0x000931D1, - 0xFF0F01C0, 0xCDEF, - 0x061, 0x000FDD43, - 0x062, 0x00038F4B, - 0x063, 0x00032117, - 0x064, 0x000194AC, - 0x065, 0x000931D1, - 0xFF0F07D8, 0xCDEF, - 0x061, 0x000FDD43, - 0x062, 0x00038F4B, - 0x063, 0x00032117, - 0x064, 0x000194AC, - 0x065, 0x000931D1, - 0xFF0F07D0, 0xCDEF, - 0x061, 0x000FDD43, - 0x062, 0x00038F4B, - 0x063, 0x00032117, - 0x064, 0x000194AC, - 0x065, 0x000931D1, - 0xCDCDCDCD, 0xCDCD, - 0x061, 0x000E5D53, - 0x062, 0x00038FCD, - 0x063, 0x000314EB, - 0x064, 0x000196AC, - 0x065, 0x000911D7, - 0xFF0F0740, 0xDEAD, - 0x008, 0x00008400, - 0x01C, 0x000739D2, - 0x0B4, 0x0001E78D, - 0x018, 0x0001F12A, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x0B4, 0x0001A78D, - 0x018, 0x0001712A, - -}; - -u32 RTL8812AE_RADIOB_ARRAY[] = { - 0x056, 0x00051CF2, - 0x066, 0x00040000, - 0x089, 0x00000080, - 0xFF0F0740, 0xABCD, - 0x086, 0x00014B38, - 0xFF0F01C0, 0xCDEF, - 0x086, 0x00014B38, - 0xFF0F02C0, 0xCDEF, - 0x086, 0x00014B38, - 0xFF0F07D8, 0xCDEF, - 0x086, 0x00014B3A, - 0xFF0F07D0, 0xCDEF, - 0x086, 0x00014B3A, - 0xCDCDCDCD, 0xCDCD, - 0x086, 0x00014B38, - 0xFF0F0740, 0xDEAD, - 0x018, 0x00000006, - 0x0EF, 0x00002000, - 0xFF0F07D8, 0xABCD, - 0x03B, 0x0003F218, - 0x03B, 0x00030A58, - 0x03B, 0x0002FA58, - 0x03B, 0x00022590, - 0x03B, 0x0001FA50, - 0x03B, 0x00010248, - 0x03B, 0x00008240, - 0xFF0F07D0, 0xCDEF, - 0x03B, 0x0003F218, - 0x03B, 0x00030A58, - 0x03B, 0x0002FA58, - 0x03B, 0x00022590, - 0x03B, 0x0001FA50, - 0x03B, 0x00010248, - 0x03B, 0x00008240, - 0xCDCDCDCD, 0xCDCD, - 0x03B, 0x00038A58, - 0x03B, 0x00037A58, - 0x03B, 0x0002A590, - 0x03B, 0x00027A50, - 0x03B, 0x00018248, - 0x03B, 0x00010240, - 0x03B, 0x00008240, - 0xFF0F07D8, 0xDEAD, - 0x0EF, 0x00000100, - 0xFF0F07D8, 0xABCD, - 0x034, 0x0000A4EE, - 0x034, 0x00009076, - 0x034, 0x00008073, - 0x034, 0x00007070, - 0x034, 0x0000606D, - 0x034, 0x0000506A, - 0x034, 0x00004049, - 0x034, 0x00003046, - 0x034, 0x00002028, - 0x034, 0x00001025, - 0x034, 0x00000022, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0000ADF4, - 0x034, 0x00009DF1, - 0x034, 0x00008DEE, - 0x034, 0x00007DEB, - 0x034, 0x00006DE8, - 0x034, 0x00005CEC, - 0x034, 0x00004CE9, - 0x034, 0x000034EA, - 0x034, 0x000024E7, - 0x034, 0x0000146B, - 0x034, 0x0000006D, - 0xFF0F07D8, 0xDEAD, - 0x0EF, 0x00000000, - 0x0EF, 0x000020A2, - 0x0DF, 0x00000080, - 0x035, 0x00000192, - 0x035, 0x00008192, - 0x035, 0x00010192, - 0x036, 0x00000024, - 0x036, 0x00008024, - 0x036, 0x00010024, - 0x036, 0x00018024, - 0x0EF, 0x00000000, - 0x051, 0x00000C21, - 0x052, 0x000006D9, - 0x053, 0x000FC649, - 0x054, 0x0000017E, - 0x0EF, 0x00000002, - 0x008, 0x00008400, - 0x018, 0x0001712A, - 0x0EF, 0x00001000, - 0x03A, 0x00000080, - 0x03B, 0x0003A02C, - 0x03C, 0x00004000, - 0x03A, 0x00000400, - 0x03B, 0x0003202C, - 0x03C, 0x00010000, - 0x03A, 0x000000A0, - 0x03B, 0x0002B064, - 0x03C, 0x00004000, - 0x03A, 0x000000D8, - 0x03B, 0x00023070, - 0x03C, 0x00004000, - 0x03A, 0x00000468, - 0x03B, 0x0001B870, - 0x03C, 0x00010000, - 0x03A, 0x00000098, - 0x03B, 0x00012085, - 0x03C, 0x000E4000, - 0x03A, 0x00000418, - 0x03B, 0x0000A080, - 0x03C, 0x000F0000, - 0x03A, 0x00000418, - 0x03B, 0x00002080, - 0x03C, 0x00010000, - 0x03A, 0x00000080, - 0x03B, 0x0007A02C, - 0x03C, 0x00004000, - 0x03A, 0x00000400, - 0x03B, 0x0007202C, - 0x03C, 0x00010000, - 0x03A, 0x000000A0, - 0x03B, 0x0006B064, - 0x03C, 0x00004000, - 0x03A, 0x000000D8, - 0x03B, 0x00063070, - 0x03C, 0x00004000, - 0x03A, 0x00000468, - 0x03B, 0x0005B870, - 0x03C, 0x00010000, - 0x03A, 0x00000098, - 0x03B, 0x00052085, - 0x03C, 0x000E4000, - 0x03A, 0x00000418, - 0x03B, 0x0004A080, - 0x03C, 0x000F0000, - 0x03A, 0x00000418, - 0x03B, 0x00042080, - 0x03C, 0x00010000, - 0x03A, 0x00000080, - 0x03B, 0x000BA02C, - 0x03C, 0x00004000, - 0x03A, 0x00000400, - 0x03B, 0x000B202C, - 0x03C, 0x00010000, - 0x03A, 0x000000A0, - 0x03B, 0x000AB064, - 0x03C, 0x00004000, - 0x03A, 0x000000D8, - 0x03B, 0x000A3070, - 0x03C, 0x00004000, - 0x03A, 0x00000468, - 0x03B, 0x0009B870, - 0x03C, 0x00010000, - 0x03A, 0x00000098, - 0x03B, 0x00092085, - 0x03C, 0x000E4000, - 0x03A, 0x00000418, - 0x03B, 0x0008A080, - 0x03C, 0x000F0000, - 0x03A, 0x00000418, - 0x03B, 0x00082080, - 0x03C, 0x00010000, - 0x0EF, 0x00001100, - 0xFF0F0740, 0xABCD, - 0x034, 0x0004A0B2, - 0x034, 0x000490AF, - 0x034, 0x00048070, - 0x034, 0x0004706D, - 0x034, 0x00046050, - 0x034, 0x0004504D, - 0x034, 0x0004404A, - 0x034, 0x00043047, - 0x034, 0x0004200A, - 0x034, 0x00041007, - 0x034, 0x00040004, - 0xFF0F01C0, 0xCDEF, - 0x034, 0x0004A0B2, - 0x034, 0x000490AF, - 0x034, 0x00048070, - 0x034, 0x0004706D, - 0x034, 0x00046050, - 0x034, 0x0004504D, - 0x034, 0x0004404A, - 0x034, 0x00043047, - 0x034, 0x0004200A, - 0x034, 0x00041007, - 0x034, 0x00040004, - 0xFF0F02C0, 0xCDEF, - 0x034, 0x0004A0B2, - 0x034, 0x000490AF, - 0x034, 0x00048070, - 0x034, 0x0004706D, - 0x034, 0x00046050, - 0x034, 0x0004504D, - 0x034, 0x0004404A, - 0x034, 0x00043047, - 0x034, 0x0004200A, - 0x034, 0x00041007, - 0x034, 0x00040004, - 0xFF0F07D8, 0xCDEF, - 0x034, 0x0004A0B2, - 0x034, 0x000490AF, - 0x034, 0x00048070, - 0x034, 0x0004706D, - 0x034, 0x00046050, - 0x034, 0x0004504D, - 0x034, 0x0004404A, - 0x034, 0x00043047, - 0x034, 0x0004200A, - 0x034, 0x00041007, - 0x034, 0x00040004, - 0xFF0F07D0, 0xCDEF, - 0x034, 0x0004A0B2, - 0x034, 0x000490AF, - 0x034, 0x00048070, - 0x034, 0x0004706D, - 0x034, 0x00046050, - 0x034, 0x0004504D, - 0x034, 0x0004404A, - 0x034, 0x00043047, - 0x034, 0x0004200A, - 0x034, 0x00041007, - 0x034, 0x00040004, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0004ADF5, - 0x034, 0x00049DF2, - 0x034, 0x00048DEF, - 0x034, 0x00047DEC, - 0x034, 0x00046DE9, - 0x034, 0x00045DC9, - 0x034, 0x00044CE8, - 0x034, 0x000438CA, - 0x034, 0x00042889, - 0x034, 0x0004184A, - 0x034, 0x0004044A, - 0xFF0F0740, 0xDEAD, - 0xFF0F0740, 0xABCD, - 0x034, 0x0002A0B2, - 0x034, 0x000290AF, - 0x034, 0x00028070, - 0x034, 0x0002706D, - 0x034, 0x00026050, - 0x034, 0x0002504D, - 0x034, 0x0002404A, - 0x034, 0x00023047, - 0x034, 0x0002200A, - 0x034, 0x00021007, - 0x034, 0x00020004, - 0xFF0F01C0, 0xCDEF, - 0x034, 0x0002A0B2, - 0x034, 0x000290AF, - 0x034, 0x00028070, - 0x034, 0x0002706D, - 0x034, 0x00026050, - 0x034, 0x0002504D, - 0x034, 0x0002404A, - 0x034, 0x00023047, - 0x034, 0x0002200A, - 0x034, 0x00021007, - 0x034, 0x00020004, - 0xFF0F02C0, 0xCDEF, - 0x034, 0x0002A0B2, - 0x034, 0x000290AF, - 0x034, 0x00028070, - 0x034, 0x0002706D, - 0x034, 0x00026050, - 0x034, 0x0002504D, - 0x034, 0x0002404A, - 0x034, 0x00023047, - 0x034, 0x0002200A, - 0x034, 0x00021007, - 0x034, 0x00020004, - 0xFF0F07D8, 0xCDEF, - 0x034, 0x0002A0B2, - 0x034, 0x000290AF, - 0x034, 0x00028070, - 0x034, 0x0002706D, - 0x034, 0x00026050, - 0x034, 0x0002504D, - 0x034, 0x0002404A, - 0x034, 0x00023047, - 0x034, 0x0002200A, - 0x034, 0x00021007, - 0x034, 0x00020004, - 0xFF0F07D0, 0xCDEF, - 0x034, 0x0002A0B2, - 0x034, 0x000290AF, - 0x034, 0x00028070, - 0x034, 0x0002706D, - 0x034, 0x00026050, - 0x034, 0x0002504D, - 0x034, 0x0002404A, - 0x034, 0x00023047, - 0x034, 0x0002200A, - 0x034, 0x00021007, - 0x034, 0x00020004, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0002ADF5, - 0x034, 0x00029DF2, - 0x034, 0x00028DEF, - 0x034, 0x00027DEC, - 0x034, 0x00026DE9, - 0x034, 0x00025DC9, - 0x034, 0x00024CE8, - 0x034, 0x000238CA, - 0x034, 0x00022889, - 0x034, 0x0002184A, - 0x034, 0x0002044A, - 0xFF0F0740, 0xDEAD, - 0xFF0F0740, 0xABCD, - 0x034, 0x0000A0B2, - 0x034, 0x000090AF, - 0x034, 0x00008070, - 0x034, 0x0000706D, - 0x034, 0x00006050, - 0x034, 0x0000504D, - 0x034, 0x0000404A, - 0x034, 0x00003047, - 0x034, 0x0000200A, - 0x034, 0x00001007, - 0x034, 0x00000004, - 0xFF0F01C0, 0xCDEF, - 0x034, 0x0000A0B2, - 0x034, 0x000090AF, - 0x034, 0x00008070, - 0x034, 0x0000706D, - 0x034, 0x00006050, - 0x034, 0x0000504D, - 0x034, 0x0000404A, - 0x034, 0x00003047, - 0x034, 0x0000200A, - 0x034, 0x00001007, - 0x034, 0x00000004, - 0xFF0F02C0, 0xCDEF, - 0x034, 0x0000A0B2, - 0x034, 0x000090AF, - 0x034, 0x00008070, - 0x034, 0x0000706D, - 0x034, 0x00006050, - 0x034, 0x0000504D, - 0x034, 0x0000404A, - 0x034, 0x00003047, - 0x034, 0x0000200A, - 0x034, 0x00001007, - 0x034, 0x00000004, - 0xFF0F07D8, 0xCDEF, - 0x034, 0x0000A0B2, - 0x034, 0x000090AF, - 0x034, 0x00008070, - 0x034, 0x0000706D, - 0x034, 0x00006050, - 0x034, 0x0000504D, - 0x034, 0x0000404A, - 0x034, 0x00003047, - 0x034, 0x0000200A, - 0x034, 0x00001007, - 0x034, 0x00000004, - 0xFF0F07D0, 0xCDEF, - 0x034, 0x0000A0B2, - 0x034, 0x000090AF, - 0x034, 0x00008070, - 0x034, 0x0000706D, - 0x034, 0x00006050, - 0x034, 0x0000504D, - 0x034, 0x0000404A, - 0x034, 0x00003047, - 0x034, 0x0000200A, - 0x034, 0x00001007, - 0x034, 0x00000004, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0000AFF7, - 0x034, 0x00009DF7, - 0x034, 0x00008DF4, - 0x034, 0x00007DF1, - 0x034, 0x00006DEE, - 0x034, 0x00005DCD, - 0x034, 0x00004CEB, - 0x034, 0x000038CC, - 0x034, 0x0000288B, - 0x034, 0x0000184C, - 0x034, 0x0000044C, - 0xFF0F0740, 0xDEAD, - 0x0EF, 0x00000000, - 0xFF0F0740, 0xABCD, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0x035, 0x000001C5, - 0x035, 0x000081C5, - 0x035, 0x000101C5, - 0x035, 0x00020174, - 0x035, 0x00028174, - 0x035, 0x00030174, - 0x035, 0x00040185, - 0x035, 0x00048185, - 0x035, 0x00050185, - 0x0EF, 0x00000000, - 0xFF0F01C0, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0x035, 0x000001C5, - 0x035, 0x000081C5, - 0x035, 0x000101C5, - 0x035, 0x00020174, - 0x035, 0x00028174, - 0x035, 0x00030174, - 0x035, 0x00040185, - 0x035, 0x00048185, - 0x035, 0x00050185, - 0x0EF, 0x00000000, - 0xFF0F02C0, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0x035, 0x000001C5, - 0x035, 0x000081C5, - 0x035, 0x000101C5, - 0x035, 0x00020174, - 0x035, 0x00028174, - 0x035, 0x00030174, - 0x035, 0x00040185, - 0x035, 0x00048185, - 0x035, 0x00050185, - 0x0EF, 0x00000000, - 0xFF0F07D8, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0x035, 0x000001C5, - 0x035, 0x000081C5, - 0x035, 0x000101C5, - 0x035, 0x00020174, - 0x035, 0x00028174, - 0x035, 0x00030174, - 0x035, 0x00040185, - 0x035, 0x00048185, - 0x035, 0x00050185, - 0x0EF, 0x00000000, - 0xFF0F07D0, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0x035, 0x000001C5, - 0x035, 0x000081C5, - 0x035, 0x000101C5, - 0x035, 0x00020174, - 0x035, 0x00028174, - 0x035, 0x00030174, - 0x035, 0x00040185, - 0x035, 0x00048185, - 0x035, 0x00050185, - 0x0EF, 0x00000000, - 0xCDCDCDCD, 0xCDCD, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0x035, 0x00000186, - 0x035, 0x00008186, - 0x035, 0x00010185, - 0x035, 0x000201D5, - 0x035, 0x000281D5, - 0x035, 0x000301D5, - 0x035, 0x000401D5, - 0x035, 0x000481D5, - 0x035, 0x000501D5, - 0x0EF, 0x00000000, - 0xFF0F0740, 0xDEAD, - 0xFF0F0740, 0xABCD, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0x036, 0x00005B8B, - 0x036, 0x0000DB8B, - 0x036, 0x00015B8B, - 0x036, 0x0001DB8B, - 0x036, 0x000262DB, - 0x036, 0x0002E2DB, - 0x036, 0x000362DB, - 0x036, 0x0003E2DB, - 0x036, 0x0004553B, - 0x036, 0x0004D53B, - 0x036, 0x0005553B, - 0x036, 0x0005D53B, - 0xFF0F01C0, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0x036, 0x00005B8B, - 0x036, 0x0000DB8B, - 0x036, 0x00015B8B, - 0x036, 0x0001DB8B, - 0x036, 0x000262DB, - 0x036, 0x0002E2DB, - 0x036, 0x000362DB, - 0x036, 0x0003E2DB, - 0x036, 0x0004553B, - 0x036, 0x0004D53B, - 0x036, 0x0005553B, - 0x036, 0x0005D53B, - 0xFF0F02C0, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0x036, 0x00005B8B, - 0x036, 0x0000DB8B, - 0x036, 0x00015B8B, - 0x036, 0x0001DB8B, - 0x036, 0x000262DB, - 0x036, 0x0002E2DB, - 0x036, 0x000362DB, - 0x036, 0x0003E2DB, - 0x036, 0x0004553B, - 0x036, 0x0004D53B, - 0x036, 0x0005553B, - 0x036, 0x0005D53B, - 0xFF0F07D8, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0x036, 0x00005B8B, - 0x036, 0x0000DB8B, - 0x036, 0x00015B8B, - 0x036, 0x0001DB8B, - 0x036, 0x000262DB, - 0x036, 0x0002E2DB, - 0x036, 0x000362DB, - 0x036, 0x0003E2DB, - 0x036, 0x0004553B, - 0x036, 0x0004D53B, - 0x036, 0x0005553B, - 0x036, 0x0005D53B, - 0xFF0F07D0, 0xCDEF, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0x036, 0x00005B8B, - 0x036, 0x0000DB8B, - 0x036, 0x00015B8B, - 0x036, 0x0001DB8B, - 0x036, 0x000262DB, - 0x036, 0x0002E2DB, - 0x036, 0x000362DB, - 0x036, 0x0003E2DB, - 0x036, 0x0004553B, - 0x036, 0x0004D53B, - 0x036, 0x0005553B, - 0x036, 0x0005D53B, - 0xCDCDCDCD, 0xCDCD, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0x036, 0x00084EB4, - 0x036, 0x0008C9B4, - 0x036, 0x000949B4, - 0x036, 0x0009C9B4, - 0x036, 0x000A4935, - 0x036, 0x000AC935, - 0x036, 0x000B4935, - 0x036, 0x000BC935, - 0x036, 0x000C4EB4, - 0x036, 0x000CCEB4, - 0x036, 0x000D4EB4, - 0x036, 0x000DCEB4, - 0xFF0F0740, 0xDEAD, - 0x0EF, 0x00000000, - 0x0EF, 0x00000008, - 0xFF0F0740, 0xABCD, - 0x03C, 0x000002DC, - 0x03C, 0x00000524, - 0x03C, 0x00000902, - 0xFF0F01C0, 0xCDEF, - 0x03C, 0x000002DC, - 0x03C, 0x00000524, - 0x03C, 0x00000902, - 0xFF0F02C0, 0xCDEF, - 0x03C, 0x000002DC, - 0x03C, 0x00000524, - 0x03C, 0x00000902, - 0xFF0F07D8, 0xCDEF, - 0x03C, 0x000002DC, - 0x03C, 0x00000524, - 0x03C, 0x00000902, - 0xFF0F07D0, 0xCDEF, - 0x03C, 0x000002DC, - 0x03C, 0x00000524, - 0x03C, 0x00000902, - 0xCDCDCDCD, 0xCDCD, - 0x03C, 0x000002AA, - 0x03C, 0x000005A2, - 0x03C, 0x00000880, - 0xFF0F0740, 0xDEAD, - 0x0EF, 0x00000000, - 0x018, 0x0001712A, - 0x0EF, 0x00000002, - 0x0DF, 0x00000080, - 0xFF0F0740, 0xABCD, - 0x061, 0x000EAC43, - 0x062, 0x00038F47, - 0x063, 0x00031157, - 0x064, 0x0001C4AC, - 0x065, 0x000931D1, - 0xFF0F01C0, 0xCDEF, - 0x061, 0x000EAC43, - 0x062, 0x00038F47, - 0x063, 0x00031157, - 0x064, 0x0001C4AC, - 0x065, 0x000931D1, - 0xFF0F02C0, 0xCDEF, - 0x061, 0x000EAC43, - 0x062, 0x00038F47, - 0x063, 0x00031157, - 0x064, 0x0001C4AC, - 0x065, 0x000931D1, - 0xFF0F07D8, 0xCDEF, - 0x061, 0x000EAC43, - 0x062, 0x00038F47, - 0x063, 0x00031157, - 0x064, 0x0001C4AC, - 0x065, 0x000931D1, - 0xFF0F07D0, 0xCDEF, - 0x061, 0x000EAC43, - 0x062, 0x00038F47, - 0x063, 0x00031157, - 0x064, 0x0001C4AC, - 0x065, 0x000931D1, - 0xCDCDCDCD, 0xCDCD, - 0x061, 0x000E5D53, - 0x062, 0x00038FCD, - 0x063, 0x000314EB, - 0x064, 0x000196AC, - 0x065, 0x000931D7, - 0xFF0F0740, 0xDEAD, - 0x008, 0x00008400, - -}; - -u32 RTL8821AE_RADIOA_ARRAY[] = { - 0x018, 0x0001712A, - 0x056, 0x00051CF2, - 0x066, 0x00040000, - 0x000, 0x00010000, - 0x01E, 0x00080000, - 0x082, 0x00000830, - 0x083, 0x00021800, - 0x084, 0x00028000, - 0x085, 0x00048000, - 0x086, 0x00094838, - 0x087, 0x00044980, - 0x088, 0x00048000, - 0x089, 0x0000D480, - 0x08A, 0x00042240, - 0x08B, 0x000F0380, - 0x08C, 0x00090000, - 0x08D, 0x00022852, - 0x08E, 0x00065540, - 0x08F, 0x00088001, - 0x0EF, 0x00020000, - 0x03E, 0x00000380, - 0x03F, 0x00090018, - 0x03E, 0x00020380, - 0x03F, 0x000A0018, - 0x03E, 0x00040308, - 0x03F, 0x000A0018, - 0x03E, 0x00060018, - 0x03F, 0x000A0018, - 0x0EF, 0x00000000, - 0x018, 0x0001712A, - 0x089, 0x00000080, - 0x08B, 0x00080180, - 0x0EF, 0x00001000, - 0x03A, 0x00000244, - 0x03B, 0x00038027, - 0x03C, 0x00082000, - 0x03A, 0x00000244, - 0x03B, 0x00030113, - 0x03C, 0x00082000, - 0x03A, 0x0000014C, - 0x03B, 0x00028027, - 0x03C, 0x00082000, - 0x03A, 0x000000CC, - 0x03B, 0x00027027, - 0x03C, 0x00042000, - 0x03A, 0x0000014C, - 0x03B, 0x0001F913, - 0x03C, 0x00042000, - 0x03A, 0x0000010C, - 0x03B, 0x00017F10, - 0x03C, 0x00012000, - 0x03A, 0x000000D0, - 0x03B, 0x00008027, - 0x03C, 0x000CA000, - 0x03A, 0x00000244, - 0x03B, 0x00078027, - 0x03C, 0x00082000, - 0x03A, 0x00000244, - 0x03B, 0x00070113, - 0x03C, 0x00082000, - 0x03A, 0x0000014C, - 0x03B, 0x00068027, - 0x03C, 0x00082000, - 0x03A, 0x000000CC, - 0x03B, 0x00067027, - 0x03C, 0x00042000, - 0x03A, 0x0000014C, - 0x03B, 0x0005F913, - 0x03C, 0x00042000, - 0x03A, 0x0000010C, - 0x03B, 0x00057F10, - 0x03C, 0x00012000, - 0x03A, 0x000000D0, - 0x03B, 0x00048027, - 0x03C, 0x000CA000, - 0x03A, 0x00000244, - 0x03B, 0x000B8027, - 0x03C, 0x00082000, - 0x03A, 0x00000244, - 0x03B, 0x000B0113, - 0x03C, 0x00082000, - 0x03A, 0x0000014C, - 0x03B, 0x000A8027, - 0x03C, 0x00082000, - 0x03A, 0x000000CC, - 0x03B, 0x000A7027, - 0x03C, 0x00042000, - 0x03A, 0x0000014C, - 0x03B, 0x0009F913, - 0x03C, 0x00042000, - 0x03A, 0x0000010C, - 0x03B, 0x00097F10, - 0x03C, 0x00012000, - 0x03A, 0x000000D0, - 0x03B, 0x00088027, - 0x03C, 0x000CA000, - 0x0EF, 0x00000000, - 0x0EF, 0x00001100, - 0xFF0F0104, 0xABCD, - 0x034, 0x0004ADF3, - 0x034, 0x00049DF0, - 0xFF0F0204, 0xCDEF, - 0x034, 0x0004ADF3, - 0x034, 0x00049DF0, - 0xFF0F0404, 0xCDEF, - 0x034, 0x0004ADF3, - 0x034, 0x00049DF0, - 0xFF0F0200, 0xCDEF, - 0x034, 0x0004ADF5, - 0x034, 0x00049DF2, - 0xFF0F02C0, 0xCDEF, - 0x034, 0x0004A0F3, - 0x034, 0x000490B1, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0004ADF7, - 0x034, 0x00049DF3, - 0xFF0F0104, 0xDEAD, - 0xFF0F0104, 0xABCD, - 0x034, 0x00048DED, - 0x034, 0x00047DEA, - 0x034, 0x00046DE7, - 0x034, 0x00045CE9, - 0x034, 0x00044CE6, - 0x034, 0x000438C6, - 0x034, 0x00042886, - 0x034, 0x00041486, - 0x034, 0x00040447, - 0xFF0F0204, 0xCDEF, - 0x034, 0x00048DED, - 0x034, 0x00047DEA, - 0x034, 0x00046DE7, - 0x034, 0x00045CE9, - 0x034, 0x00044CE6, - 0x034, 0x000438C6, - 0x034, 0x00042886, - 0x034, 0x00041486, - 0x034, 0x00040447, - 0xFF0F0404, 0xCDEF, - 0x034, 0x00048DED, - 0x034, 0x00047DEA, - 0x034, 0x00046DE7, - 0x034, 0x00045CE9, - 0x034, 0x00044CE6, - 0x034, 0x000438C6, - 0x034, 0x00042886, - 0x034, 0x00041486, - 0x034, 0x00040447, - 0xFF0F02C0, 0xCDEF, - 0x034, 0x000480AE, - 0x034, 0x000470AB, - 0x034, 0x0004608B, - 0x034, 0x00045069, - 0x034, 0x00044048, - 0x034, 0x00043045, - 0x034, 0x00042026, - 0x034, 0x00041023, - 0x034, 0x00040002, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x00048DEF, - 0x034, 0x00047DEC, - 0x034, 0x00046DE9, - 0x034, 0x00045CCB, - 0x034, 0x0004488D, - 0x034, 0x0004348D, - 0x034, 0x0004248A, - 0x034, 0x0004108D, - 0x034, 0x0004008A, - 0xFF0F0104, 0xDEAD, - 0xFF0F0200, 0xABCD, - 0x034, 0x0002ADF4, - 0xFF0F02C0, 0xCDEF, - 0x034, 0x0002A0F3, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0002ADF7, - 0xFF0F0200, 0xDEAD, - 0xFF0F0104, 0xABCD, - 0x034, 0x00029DF4, - 0xFF0F0204, 0xCDEF, - 0x034, 0x00029DF4, - 0xFF0F0404, 0xCDEF, - 0x034, 0x00029DF4, - 0xFF0F0200, 0xCDEF, - 0x034, 0x00029DF1, - 0xFF0F02C0, 0xCDEF, - 0x034, 0x000290F0, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x00029DF2, - 0xFF0F0104, 0xDEAD, - 0xFF0F0104, 0xABCD, - 0x034, 0x00028DF1, - 0x034, 0x00027DEE, - 0x034, 0x00026DEB, - 0x034, 0x00025CEC, - 0x034, 0x00024CE9, - 0x034, 0x000238CA, - 0x034, 0x00022889, - 0x034, 0x00021489, - 0x034, 0x0002044A, - 0xFF0F0204, 0xCDEF, - 0x034, 0x00028DF1, - 0x034, 0x00027DEE, - 0x034, 0x00026DEB, - 0x034, 0x00025CEC, - 0x034, 0x00024CE9, - 0x034, 0x000238CA, - 0x034, 0x00022889, - 0x034, 0x00021489, - 0x034, 0x0002044A, - 0xFF0F0404, 0xCDEF, - 0x034, 0x00028DF1, - 0x034, 0x00027DEE, - 0x034, 0x00026DEB, - 0x034, 0x00025CEC, - 0x034, 0x00024CE9, - 0x034, 0x000238CA, - 0x034, 0x00022889, - 0x034, 0x00021489, - 0x034, 0x0002044A, - 0xFF0F02C0, 0xCDEF, - 0x034, 0x000280AF, - 0x034, 0x000270AC, - 0x034, 0x0002608B, - 0x034, 0x00025069, - 0x034, 0x00024048, - 0x034, 0x00023045, - 0x034, 0x00022026, - 0x034, 0x00021023, - 0x034, 0x00020002, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x00028DEE, - 0x034, 0x00027DEB, - 0x034, 0x00026CCD, - 0x034, 0x00025CCA, - 0x034, 0x0002488C, - 0x034, 0x0002384C, - 0x034, 0x00022849, - 0x034, 0x00021449, - 0x034, 0x0002004D, - 0xFF0F0104, 0xDEAD, - 0xFF0F02C0, 0xABCD, - 0x034, 0x0000A0D7, - 0x034, 0x000090D3, - 0x034, 0x000080B1, - 0x034, 0x000070AE, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x0000ADF7, - 0x034, 0x00009DF4, - 0x034, 0x00008DF1, - 0x034, 0x00007DEE, - 0xFF0F02C0, 0xDEAD, - 0xFF0F0104, 0xABCD, - 0x034, 0x00006DEB, - 0x034, 0x00005CEC, - 0x034, 0x00004CE9, - 0x034, 0x000038CA, - 0x034, 0x00002889, - 0x034, 0x00001489, - 0x034, 0x0000044A, - 0xFF0F0204, 0xCDEF, - 0x034, 0x00006DEB, - 0x034, 0x00005CEC, - 0x034, 0x00004CE9, - 0x034, 0x000038CA, - 0x034, 0x00002889, - 0x034, 0x00001489, - 0x034, 0x0000044A, - 0xFF0F0404, 0xCDEF, - 0x034, 0x00006DEB, - 0x034, 0x00005CEC, - 0x034, 0x00004CE9, - 0x034, 0x000038CA, - 0x034, 0x00002889, - 0x034, 0x00001489, - 0x034, 0x0000044A, - 0xFF0F02C0, 0xCDEF, - 0x034, 0x0000608D, - 0x034, 0x0000506B, - 0x034, 0x0000404A, - 0x034, 0x00003047, - 0x034, 0x00002044, - 0x034, 0x00001025, - 0x034, 0x00000004, - 0xCDCDCDCD, 0xCDCD, - 0x034, 0x00006DCD, - 0x034, 0x00005CCD, - 0x034, 0x00004CCA, - 0x034, 0x0000388C, - 0x034, 0x00002888, - 0x034, 0x00001488, - 0x034, 0x00000486, - 0xFF0F0104, 0xDEAD, - 0x0EF, 0x00000000, - 0x018, 0x0001712A, - 0x0EF, 0x00000040, - 0xFF0F0104, 0xABCD, - 0x035, 0x00000187, - 0x035, 0x00008187, - 0x035, 0x00010187, - 0x035, 0x00020188, - 0x035, 0x00028188, - 0x035, 0x00030188, - 0x035, 0x00040188, - 0x035, 0x00048188, - 0x035, 0x00050188, - 0xFF0F0204, 0xCDEF, - 0x035, 0x00000187, - 0x035, 0x00008187, - 0x035, 0x00010187, - 0x035, 0x00020188, - 0x035, 0x00028188, - 0x035, 0x00030188, - 0x035, 0x00040188, - 0x035, 0x00048188, - 0x035, 0x00050188, - 0xFF0F0404, 0xCDEF, - 0x035, 0x00000187, - 0x035, 0x00008187, - 0x035, 0x00010187, - 0x035, 0x00020188, - 0x035, 0x00028188, - 0x035, 0x00030188, - 0x035, 0x00040188, - 0x035, 0x00048188, - 0x035, 0x00050188, - 0xCDCDCDCD, 0xCDCD, - 0x035, 0x00000145, - 0x035, 0x00008145, - 0x035, 0x00010145, - 0x035, 0x00020196, - 0x035, 0x00028196, - 0x035, 0x00030196, - 0x035, 0x000401C7, - 0x035, 0x000481C7, - 0x035, 0x000501C7, - 0xFF0F0104, 0xDEAD, - 0x0EF, 0x00000000, - 0x018, 0x0001712A, - 0x0EF, 0x00000010, - 0xFF0F0104, 0xABCD, - 0x036, 0x00085733, - 0x036, 0x0008D733, - 0x036, 0x00095733, - 0x036, 0x0009D733, - 0x036, 0x000A64B4, - 0x036, 0x000AE4B4, - 0x036, 0x000B64B4, - 0x036, 0x000BE4B4, - 0x036, 0x000C64B4, - 0x036, 0x000CE4B4, - 0x036, 0x000D64B4, - 0x036, 0x000DE4B4, - 0xFF0F0204, 0xCDEF, - 0x036, 0x00085733, - 0x036, 0x0008D733, - 0x036, 0x00095733, - 0x036, 0x0009D733, - 0x036, 0x000A64B4, - 0x036, 0x000AE4B4, - 0x036, 0x000B64B4, - 0x036, 0x000BE4B4, - 0x036, 0x000C64B4, - 0x036, 0x000CE4B4, - 0x036, 0x000D64B4, - 0x036, 0x000DE4B4, - 0xFF0F0404, 0xCDEF, - 0x036, 0x00085733, - 0x036, 0x0008D733, - 0x036, 0x00095733, - 0x036, 0x0009D733, - 0x036, 0x000A64B4, - 0x036, 0x000AE4B4, - 0x036, 0x000B64B4, - 0x036, 0x000BE4B4, - 0x036, 0x000C64B4, - 0x036, 0x000CE4B4, - 0x036, 0x000D64B4, - 0x036, 0x000DE4B4, - 0xCDCDCDCD, 0xCDCD, - 0x036, 0x000056B3, - 0x036, 0x0000D6B3, - 0x036, 0x000156B3, - 0x036, 0x0001D6B3, - 0x036, 0x00026634, - 0x036, 0x0002E634, - 0x036, 0x00036634, - 0x036, 0x0003E634, - 0x036, 0x000467B4, - 0x036, 0x0004E7B4, - 0x036, 0x000567B4, - 0x036, 0x0005E7B4, - 0xFF0F0104, 0xDEAD, - 0x0EF, 0x00000000, - 0x0EF, 0x00000008, - 0xFF0F0104, 0xABCD, - 0x03C, 0x000001C8, - 0x03C, 0x00000492, - 0xFF0F0204, 0xCDEF, - 0x03C, 0x000001C8, - 0x03C, 0x00000492, - 0xFF0F0404, 0xCDEF, - 0x03C, 0x000001C8, - 0x03C, 0x00000492, - 0xCDCDCDCD, 0xCDCD, - 0x03C, 0x0000022A, - 0x03C, 0x00000594, - 0xFF0F0104, 0xDEAD, - 0xFF0F0104, 0xABCD, - 0x03C, 0x00000800, - 0xFF0F0204, 0xCDEF, - 0x03C, 0x00000800, - 0xFF0F0404, 0xCDEF, - 0x03C, 0x00000800, - 0xFF0F02C0, 0xCDEF, - 0x03C, 0x00000820, - 0xCDCDCDCD, 0xCDCD, - 0x03C, 0x00000900, - 0xFF0F0104, 0xDEAD, - 0x0EF, 0x00000000, - 0x018, 0x0001712A, - 0x0EF, 0x00000002, - 0xFF0F0104, 0xABCD, - 0x008, 0x0004E400, - 0xFF0F0204, 0xCDEF, - 0x008, 0x0004E400, - 0xFF0F0404, 0xCDEF, - 0x008, 0x0004E400, - 0xCDCDCDCD, 0xCDCD, - 0x008, 0x00002000, - 0xFF0F0104, 0xDEAD, - 0x0EF, 0x00000000, - 0x0DF, 0x000000C0, - 0x01F, 0x00040064, - 0xFF0F0104, 0xABCD, - 0x058, 0x000A7284, - 0x059, 0x000600EC, - 0xFF0F0204, 0xCDEF, - 0x058, 0x000A7284, - 0x059, 0x000600EC, - 0xFF0F0404, 0xCDEF, - 0x058, 0x000A7284, - 0x059, 0x000600EC, - 0xCDCDCDCD, 0xCDCD, - 0x058, 0x00081184, - 0x059, 0x0006016C, - 0xFF0F0104, 0xDEAD, - 0xFF0F0104, 0xABCD, - 0x061, 0x000E8D73, - 0x062, 0x00093FC5, - 0xFF0F0204, 0xCDEF, - 0x061, 0x000E8D73, - 0x062, 0x00093FC5, - 0xFF0F0404, 0xCDEF, - 0x061, 0x000E8D73, - 0x062, 0x00093FC5, - 0xCDCDCDCD, 0xCDCD, - 0x061, 0x000EAD53, - 0x062, 0x00093BC4, - 0xFF0F0104, 0xDEAD, - 0xFF0F0104, 0xABCD, - 0x063, 0x000110E9, - 0xFF0F0204, 0xCDEF, - 0x063, 0x000110E9, - 0xFF0F0404, 0xCDEF, - 0x063, 0x000110E9, - 0xFF0F0200, 0xCDEF, - 0x063, 0x000710E9, - 0xFF0F02C0, 0xCDEF, - 0x063, 0x000110E9, - 0xCDCDCDCD, 0xCDCD, - 0x063, 0x000714E9, - 0xFF0F0104, 0xDEAD, - 0xFF0F0104, 0xABCD, - 0x064, 0x0001C27C, - 0xFF0F0204, 0xCDEF, - 0x064, 0x0001C27C, - 0xFF0F0404, 0xCDEF, - 0x064, 0x0001C27C, - 0xCDCDCDCD, 0xCDCD, - 0x064, 0x0001C67C, - 0xFF0F0104, 0xDEAD, - 0xFF0F0200, 0xABCD, - 0x065, 0x00093016, - 0xFF0F02C0, 0xCDEF, - 0x065, 0x00093015, - 0xCDCDCDCD, 0xCDCD, - 0x065, 0x00091016, - 0xFF0F0200, 0xDEAD, - 0x018, 0x00000006, - 0x0EF, 0x00002000, - 0x03B, 0x0003824B, - 0x03B, 0x0003024B, - 0x03B, 0x0002844B, - 0x03B, 0x00020F4B, - 0x03B, 0x00018F4B, - 0x03B, 0x000104B2, - 0x03B, 0x00008049, - 0x03B, 0x00000148, - 0x03B, 0x0007824B, - 0x03B, 0x0007024B, - 0x03B, 0x0006824B, - 0x03B, 0x00060F4B, - 0x03B, 0x00058F4B, - 0x03B, 0x000504B2, - 0x03B, 0x00048049, - 0x03B, 0x00040148, - 0x0EF, 0x00000000, - 0x0EF, 0x00000100, - 0x034, 0x0000ADF3, - 0x034, 0x00009DEF, - 0x034, 0x00008DEC, - 0x034, 0x00007DE9, - 0x034, 0x00006CED, - 0x034, 0x00005CE9, - 0x034, 0x000044E9, - 0x034, 0x000034E6, - 0x034, 0x0000246A, - 0x034, 0x00001467, - 0x034, 0x00000068, - 0x0EF, 0x00000000, - 0x0ED, 0x00000010, - 0x044, 0x0000ADF2, - 0x044, 0x00009DEF, - 0x044, 0x00008DEC, - 0x044, 0x00007DE9, - 0x044, 0x00006CEC, - 0x044, 0x00005CE9, - 0x044, 0x000044EC, - 0x044, 0x000034E9, - 0x044, 0x0000246C, - 0x044, 0x00001469, - 0x044, 0x0000006C, - 0x0ED, 0x00000000, - 0x0ED, 0x00000001, - 0x040, 0x00038DA7, - 0x040, 0x000300C2, - 0x040, 0x000288E2, - 0x040, 0x000200B8, - 0x040, 0x000188A5, - 0x040, 0x00010FBC, - 0x040, 0x00008F71, - 0x040, 0x00000240, - 0x0ED, 0x00000000, - 0x0EF, 0x000020A2, - 0x0DF, 0x00000080, - 0x035, 0x00000120, - 0x035, 0x00008120, - 0x035, 0x00010120, - 0x036, 0x00000085, - 0x036, 0x00008085, - 0x036, 0x00010085, - 0x036, 0x00018085, - 0x0EF, 0x00000000, - 0x051, 0x00000C31, - 0x052, 0x00000622, - 0x053, 0x000FC70B, - 0x054, 0x0000017E, - 0x056, 0x00051DF3, - 0x051, 0x00000C01, - 0x052, 0x000006D6, - 0x053, 0x000FC649, - 0x070, 0x00049661, - 0x071, 0x0007843E, - 0x072, 0x00000382, - 0x074, 0x00051400, - 0x035, 0x00000160, - 0x035, 0x00008160, - 0x035, 0x00010160, - 0x036, 0x00000124, - 0x036, 0x00008124, - 0x036, 0x00010124, - 0x036, 0x00018124, - 0x0ED, 0x0000000C, - 0x045, 0x00000140, - 0x045, 0x00008140, - 0x045, 0x00010140, - 0x046, 0x00000124, - 0x046, 0x00008124, - 0x046, 0x00010124, - 0x046, 0x00018124, - 0x0DF, 0x00000088, - 0x0B3, 0x000F0E18, - 0x0B4, 0x0001214C, - 0x0B7, 0x0003000C, - 0x01C, 0x000539D2, - 0x018, 0x0001F12A, - 0x0FE, 0x00000000, - 0x0FE, 0x00000000, - 0x018, 0x0001712A, -}; - -u32 RTL8812AE_MAC_REG_ARRAY[] = { - 0x010, 0x0000000C, - 0xFF0F0180, 0xABCD, - 0x025, 0x0000000F, - 0xFF0F01C0, 0xCDEF, - 0x025, 0x0000000F, - 0xCDCDCDCD, 0xCDCD, - 0x025, 0x0000006F, - 0xFF0F0180, 0xDEAD, - 0x072, 0x00000000, - 0x428, 0x0000000A, - 0x429, 0x00000010, - 0x430, 0x00000000, - 0x431, 0x00000000, - 0x432, 0x00000000, - 0x433, 0x00000001, - 0x434, 0x00000004, - 0x435, 0x00000005, - 0x436, 0x00000007, - 0x437, 0x00000008, - 0x43C, 0x00000004, - 0x43D, 0x00000005, - 0x43E, 0x00000007, - 0x43F, 0x00000008, - 0x440, 0x0000005D, - 0x441, 0x00000001, - 0x442, 0x00000000, - 0x444, 0x00000010, - 0x445, 0x00000000, - 0x446, 0x00000000, - 0x447, 0x00000000, - 0x448, 0x00000000, - 0x449, 0x000000F0, - 0x44A, 0x0000000F, - 0x44B, 0x0000003E, - 0x44C, 0x00000010, - 0x44D, 0x00000000, - 0x44E, 0x00000000, - 0x44F, 0x00000000, - 0x450, 0x00000000, - 0x451, 0x000000F0, - 0x452, 0x0000000F, - 0x453, 0x00000000, - 0x45B, 0x00000080, - 0x460, 0x00000066, - 0x461, 0x00000066, - 0x4C8, 0x000000FF, - 0x4C9, 0x00000008, - 0x4CC, 0x000000FF, - 0x4CD, 0x000000FF, - 0x4CE, 0x00000001, - 0x500, 0x00000026, - 0x501, 0x000000A2, - 0x502, 0x0000002F, - 0x503, 0x00000000, - 0x504, 0x00000028, - 0x505, 0x000000A3, - 0x506, 0x0000005E, - 0x507, 0x00000000, - 0x508, 0x0000002B, - 0x509, 0x000000A4, - 0x50A, 0x0000005E, - 0x50B, 0x00000000, - 0x50C, 0x0000004F, - 0x50D, 0x000000A4, - 0x50E, 0x00000000, - 0x50F, 0x00000000, - 0x512, 0x0000001C, - 0x514, 0x0000000A, - 0x516, 0x0000000A, - 0x525, 0x0000004F, - 0x550, 0x00000010, - 0x551, 0x00000010, - 0x559, 0x00000002, - 0x55C, 0x00000050, - 0x55D, 0x000000FF, - 0x604, 0x00000001, - 0x605, 0x00000030, - 0x607, 0x00000003, - 0x608, 0x0000000E, - 0x609, 0x0000002A, - 0x620, 0x000000FF, - 0x621, 0x000000FF, - 0x622, 0x000000FF, - 0x623, 0x000000FF, - 0x624, 0x000000FF, - 0x625, 0x000000FF, - 0x626, 0x000000FF, - 0x627, 0x000000FF, - 0x638, 0x00000050, - 0x63C, 0x0000000A, - 0x63D, 0x0000000A, - 0x63E, 0x0000000E, - 0x63F, 0x0000000E, - 0x640, 0x00000080, - 0x642, 0x00000040, - 0x643, 0x00000000, - 0x652, 0x000000C8, - 0x66E, 0x00000005, - 0x700, 0x00000021, - 0x701, 0x00000043, - 0x702, 0x00000065, - 0x703, 0x00000087, - 0x708, 0x00000021, - 0x709, 0x00000043, - 0x70A, 0x00000065, - 0x70B, 0x00000087, - 0x718, 0x00000040, - -}; - -u32 RTL8821AE_MAC_REG_ARRAY[] = { - 0x428, 0x0000000A, - 0x429, 0x00000010, - 0x430, 0x00000000, - 0x431, 0x00000000, - 0x432, 0x00000000, - 0x433, 0x00000001, - 0x434, 0x00000004, - 0x435, 0x00000005, - 0x436, 0x00000007, - 0x437, 0x00000008, - 0x43C, 0x00000004, - 0x43D, 0x00000005, - 0x43E, 0x00000007, - 0x43F, 0x00000008, - 0x440, 0x0000005D, - 0x441, 0x00000001, - 0x442, 0x00000000, - 0x444, 0x00000010, - 0x445, 0x00000000, - 0x446, 0x00000000, - 0x447, 0x00000000, - 0x448, 0x00000000, - 0x449, 0x000000F0, - 0x44A, 0x0000000F, - 0x44B, 0x0000003E, - 0x44C, 0x00000010, - 0x44D, 0x00000000, - 0x44E, 0x00000000, - 0x44F, 0x00000000, - 0x450, 0x00000000, - 0x451, 0x000000F0, - 0x452, 0x0000000F, - 0x453, 0x00000000, - 0x456, 0x0000005E, - 0x460, 0x00000066, - 0x461, 0x00000066, - 0x4C8, 0x0000003F, - 0x4C9, 0x000000FF, - 0x4CC, 0x000000FF, - 0x4CD, 0x000000FF, - 0x4CE, 0x00000001, - 0x500, 0x00000026, - 0x501, 0x000000A2, - 0x502, 0x0000002F, - 0x503, 0x00000000, - 0x504, 0x00000028, - 0x505, 0x000000A3, - 0x506, 0x0000005E, - 0x507, 0x00000000, - 0x508, 0x0000002B, - 0x509, 0x000000A4, - 0x50A, 0x0000005E, - 0x50B, 0x00000000, - 0x50C, 0x0000004F, - 0x50D, 0x000000A4, - 0x50E, 0x00000000, - 0x50F, 0x00000000, - 0x512, 0x0000001C, - 0x514, 0x0000000A, - 0x516, 0x0000000A, - 0x525, 0x0000004F, - 0x550, 0x00000010, - 0x551, 0x00000010, - 0x559, 0x00000002, - 0x55C, 0x00000050, - 0x55D, 0x000000FF, - 0x605, 0x00000030, - 0x607, 0x00000007, - 0x608, 0x0000000E, - 0x609, 0x0000002A, - 0x620, 0x000000FF, - 0x621, 0x000000FF, - 0x622, 0x000000FF, - 0x623, 0x000000FF, - 0x624, 0x000000FF, - 0x625, 0x000000FF, - 0x626, 0x000000FF, - 0x627, 0x000000FF, - 0x638, 0x00000050, - 0x63C, 0x0000000A, - 0x63D, 0x0000000A, - 0x63E, 0x0000000E, - 0x63F, 0x0000000E, - 0x640, 0x00000040, - 0x642, 0x00000040, - 0x643, 0x00000000, - 0x652, 0x000000C8, - 0x66E, 0x00000005, - 0x700, 0x00000021, - 0x701, 0x00000043, - 0x702, 0x00000065, - 0x703, 0x00000087, - 0x708, 0x00000021, - 0x709, 0x00000043, - 0x70A, 0x00000065, - 0x70B, 0x00000087, - 0x718, 0x00000040, -}; - -u32 RTL8812AE_AGC_TAB_ARRAY[] = { - 0xFF0F07D8, 0xABCD, - 0x81C, 0xFC000001, - 0x81C, 0xFB020001, - 0x81C, 0xFA040001, - 0x81C, 0xF9060001, - 0x81C, 0xF8080001, - 0x81C, 0xF70A0001, - 0x81C, 0xF60C0001, - 0x81C, 0xF50E0001, - 0x81C, 0xF4100001, - 0x81C, 0xF3120001, - 0x81C, 0xF2140001, - 0x81C, 0xF1160001, - 0x81C, 0xF0180001, - 0x81C, 0xEF1A0001, - 0x81C, 0xEE1C0001, - 0x81C, 0xED1E0001, - 0x81C, 0xEC200001, - 0x81C, 0xEB220001, - 0x81C, 0xEA240001, - 0x81C, 0xCD260001, - 0x81C, 0xCC280001, - 0x81C, 0xCB2A0001, - 0x81C, 0xCA2C0001, - 0x81C, 0xC92E0001, - 0x81C, 0xC8300001, - 0x81C, 0xA6320001, - 0x81C, 0xA5340001, - 0x81C, 0xA4360001, - 0x81C, 0xA3380001, - 0x81C, 0xA23A0001, - 0x81C, 0x883C0001, - 0x81C, 0x873E0001, - 0x81C, 0x86400001, - 0x81C, 0x85420001, - 0x81C, 0x84440001, - 0x81C, 0x83460001, - 0x81C, 0x82480001, - 0x81C, 0x814A0001, - 0x81C, 0x484C0001, - 0x81C, 0x474E0001, - 0x81C, 0x46500001, - 0x81C, 0x45520001, - 0x81C, 0x44540001, - 0x81C, 0x43560001, - 0x81C, 0x42580001, - 0x81C, 0x415A0001, - 0x81C, 0x255C0001, - 0x81C, 0x245E0001, - 0x81C, 0x23600001, - 0x81C, 0x22620001, - 0x81C, 0x21640001, - 0x81C, 0x21660001, - 0x81C, 0x21680001, - 0x81C, 0x216A0001, - 0x81C, 0x216C0001, - 0x81C, 0x216E0001, - 0x81C, 0x21700001, - 0x81C, 0x21720001, - 0x81C, 0x21740001, - 0x81C, 0x21760001, - 0x81C, 0x21780001, - 0x81C, 0x217A0001, - 0x81C, 0x217C0001, - 0x81C, 0x217E0001, - 0xFF0F07D0, 0xCDEF, - 0x81C, 0xF9000001, - 0x81C, 0xF8020001, - 0x81C, 0xF7040001, - 0x81C, 0xF6060001, - 0x81C, 0xF5080001, - 0x81C, 0xF40A0001, - 0x81C, 0xF30C0001, - 0x81C, 0xF20E0001, - 0x81C, 0xF1100001, - 0x81C, 0xF0120001, - 0x81C, 0xEF140001, - 0x81C, 0xEE160001, - 0x81C, 0xED180001, - 0x81C, 0xEC1A0001, - 0x81C, 0xEB1C0001, - 0x81C, 0xEA1E0001, - 0x81C, 0xCD200001, - 0x81C, 0xCC220001, - 0x81C, 0xCB240001, - 0x81C, 0xCA260001, - 0x81C, 0xC9280001, - 0x81C, 0xC82A0001, - 0x81C, 0xC72C0001, - 0x81C, 0xC62E0001, - 0x81C, 0xA5300001, - 0x81C, 0xA4320001, - 0x81C, 0xA3340001, - 0x81C, 0xA2360001, - 0x81C, 0x88380001, - 0x81C, 0x873A0001, - 0x81C, 0x863C0001, - 0x81C, 0x853E0001, - 0x81C, 0x84400001, - 0x81C, 0x83420001, - 0x81C, 0x82440001, - 0x81C, 0x81460001, - 0x81C, 0x48480001, - 0x81C, 0x474A0001, - 0x81C, 0x464C0001, - 0x81C, 0x454E0001, - 0x81C, 0x44500001, - 0x81C, 0x43520001, - 0x81C, 0x42540001, - 0x81C, 0x41560001, - 0x81C, 0x25580001, - 0x81C, 0x245A0001, - 0x81C, 0x235C0001, - 0x81C, 0x225E0001, - 0x81C, 0x21600001, - 0x81C, 0x21620001, - 0x81C, 0x21640001, - 0x81C, 0x21660001, - 0x81C, 0x21680001, - 0x81C, 0x216A0001, - 0x81C, 0x236C0001, - 0x81C, 0x226E0001, - 0x81C, 0x21700001, - 0x81C, 0x21720001, - 0x81C, 0x21740001, - 0x81C, 0x21760001, - 0x81C, 0x21780001, - 0x81C, 0x217A0001, - 0x81C, 0x217C0001, - 0x81C, 0x217E0001, - 0xCDCDCDCD, 0xCDCD, - 0x81C, 0xFF000001, - 0x81C, 0xFF020001, - 0x81C, 0xFF040001, - 0x81C, 0xFF060001, - 0x81C, 0xFF080001, - 0x81C, 0xFE0A0001, - 0x81C, 0xFD0C0001, - 0x81C, 0xFC0E0001, - 0x81C, 0xFB100001, - 0x81C, 0xFA120001, - 0x81C, 0xF9140001, - 0x81C, 0xF8160001, - 0x81C, 0xF7180001, - 0x81C, 0xF61A0001, - 0x81C, 0xF51C0001, - 0x81C, 0xF41E0001, - 0x81C, 0xF3200001, - 0x81C, 0xF2220001, - 0x81C, 0xF1240001, - 0x81C, 0xF0260001, - 0x81C, 0xEF280001, - 0x81C, 0xEE2A0001, - 0x81C, 0xED2C0001, - 0x81C, 0xEC2E0001, - 0x81C, 0xEB300001, - 0x81C, 0xEA320001, - 0x81C, 0xE9340001, - 0x81C, 0xE8360001, - 0x81C, 0xE7380001, - 0x81C, 0xE63A0001, - 0x81C, 0xE53C0001, - 0x81C, 0xC73E0001, - 0x81C, 0xC6400001, - 0x81C, 0xC5420001, - 0x81C, 0xC4440001, - 0x81C, 0xC3460001, - 0x81C, 0xC2480001, - 0x81C, 0xC14A0001, - 0x81C, 0xA74C0001, - 0x81C, 0xA64E0001, - 0x81C, 0xA5500001, - 0x81C, 0xA4520001, - 0x81C, 0xA3540001, - 0x81C, 0xA2560001, - 0x81C, 0xA1580001, - 0x81C, 0x675A0001, - 0x81C, 0x665C0001, - 0x81C, 0x655E0001, - 0x81C, 0x64600001, - 0x81C, 0x63620001, - 0x81C, 0x48640001, - 0x81C, 0x47660001, - 0x81C, 0x46680001, - 0x81C, 0x456A0001, - 0x81C, 0x446C0001, - 0x81C, 0x436E0001, - 0x81C, 0x42700001, - 0x81C, 0x41720001, - 0x81C, 0x41740001, - 0x81C, 0x41760001, - 0x81C, 0x41780001, - 0x81C, 0x417A0001, - 0x81C, 0x417C0001, - 0x81C, 0x417E0001, - 0xFF0F07D8, 0xDEAD, - 0xFF0F0180, 0xABCD, - 0x81C, 0xFC800001, - 0x81C, 0xFB820001, - 0x81C, 0xFA840001, - 0x81C, 0xF9860001, - 0x81C, 0xF8880001, - 0x81C, 0xF78A0001, - 0x81C, 0xF68C0001, - 0x81C, 0xF58E0001, - 0x81C, 0xF4900001, - 0x81C, 0xF3920001, - 0x81C, 0xF2940001, - 0x81C, 0xF1960001, - 0x81C, 0xF0980001, - 0x81C, 0xEF9A0001, - 0x81C, 0xEE9C0001, - 0x81C, 0xED9E0001, - 0x81C, 0xECA00001, - 0x81C, 0xEBA20001, - 0x81C, 0xEAA40001, - 0x81C, 0xE9A60001, - 0x81C, 0xE8A80001, - 0x81C, 0xE7AA0001, - 0x81C, 0xE6AC0001, - 0x81C, 0xE5AE0001, - 0x81C, 0xE4B00001, - 0x81C, 0xE3B20001, - 0x81C, 0xA8B40001, - 0x81C, 0xA7B60001, - 0x81C, 0xA6B80001, - 0x81C, 0xA5BA0001, - 0x81C, 0xA4BC0001, - 0x81C, 0xA3BE0001, - 0x81C, 0xA2C00001, - 0x81C, 0xA1C20001, - 0x81C, 0x68C40001, - 0x81C, 0x67C60001, - 0x81C, 0x66C80001, - 0x81C, 0x65CA0001, - 0x81C, 0x64CC0001, - 0x81C, 0x47CE0001, - 0x81C, 0x46D00001, - 0x81C, 0x45D20001, - 0x81C, 0x44D40001, - 0x81C, 0x43D60001, - 0x81C, 0x42D80001, - 0x81C, 0x08DA0001, - 0x81C, 0x07DC0001, - 0x81C, 0x06DE0001, - 0x81C, 0x05E00001, - 0x81C, 0x04E20001, - 0x81C, 0x03E40001, - 0x81C, 0x02E60001, - 0x81C, 0x01E80001, - 0x81C, 0x01EA0001, - 0x81C, 0x01EC0001, - 0x81C, 0x01EE0001, - 0x81C, 0x01F00001, - 0x81C, 0x01F20001, - 0x81C, 0x01F40001, - 0x81C, 0x01F60001, - 0x81C, 0x01F80001, - 0x81C, 0x01FA0001, - 0x81C, 0x01FC0001, - 0x81C, 0x01FE0001, - 0xFF0F0280, 0xCDEF, - 0x81C, 0xFC800001, - 0x81C, 0xFB820001, - 0x81C, 0xFA840001, - 0x81C, 0xF9860001, - 0x81C, 0xF8880001, - 0x81C, 0xF78A0001, - 0x81C, 0xF68C0001, - 0x81C, 0xF58E0001, - 0x81C, 0xF4900001, - 0x81C, 0xF3920001, - 0x81C, 0xF2940001, - 0x81C, 0xF1960001, - 0x81C, 0xF0980001, - 0x81C, 0xEF9A0001, - 0x81C, 0xEE9C0001, - 0x81C, 0xED9E0001, - 0x81C, 0xECA00001, - 0x81C, 0xEBA20001, - 0x81C, 0xEAA40001, - 0x81C, 0xE9A60001, - 0x81C, 0xE8A80001, - 0x81C, 0xE7AA0001, - 0x81C, 0xE6AC0001, - 0x81C, 0xE5AE0001, - 0x81C, 0xE4B00001, - 0x81C, 0xE3B20001, - 0x81C, 0xA8B40001, - 0x81C, 0xA7B60001, - 0x81C, 0xA6B80001, - 0x81C, 0xA5BA0001, - 0x81C, 0xA4BC0001, - 0x81C, 0xA3BE0001, - 0x81C, 0xA2C00001, - 0x81C, 0xA1C20001, - 0x81C, 0x68C40001, - 0x81C, 0x67C60001, - 0x81C, 0x66C80001, - 0x81C, 0x65CA0001, - 0x81C, 0x64CC0001, - 0x81C, 0x47CE0001, - 0x81C, 0x46D00001, - 0x81C, 0x45D20001, - 0x81C, 0x44D40001, - 0x81C, 0x43D60001, - 0x81C, 0x42D80001, - 0x81C, 0x08DA0001, - 0x81C, 0x07DC0001, - 0x81C, 0x06DE0001, - 0x81C, 0x05E00001, - 0x81C, 0x04E20001, - 0x81C, 0x03E40001, - 0x81C, 0x02E60001, - 0x81C, 0x01E80001, - 0x81C, 0x01EA0001, - 0x81C, 0x01EC0001, - 0x81C, 0x01EE0001, - 0x81C, 0x01F00001, - 0x81C, 0x01F20001, - 0x81C, 0x01F40001, - 0x81C, 0x01F60001, - 0x81C, 0x01F80001, - 0x81C, 0x01FA0001, - 0x81C, 0x01FC0001, - 0x81C, 0x01FE0001, - 0xFF0F01C0, 0xCDEF, - 0x81C, 0xFC800001, - 0x81C, 0xFB820001, - 0x81C, 0xFA840001, - 0x81C, 0xF9860001, - 0x81C, 0xF8880001, - 0x81C, 0xF78A0001, - 0x81C, 0xF68C0001, - 0x81C, 0xF58E0001, - 0x81C, 0xF4900001, - 0x81C, 0xF3920001, - 0x81C, 0xF2940001, - 0x81C, 0xF1960001, - 0x81C, 0xF0980001, - 0x81C, 0xEF9A0001, - 0x81C, 0xEE9C0001, - 0x81C, 0xED9E0001, - 0x81C, 0xECA00001, - 0x81C, 0xEBA20001, - 0x81C, 0xEAA40001, - 0x81C, 0xE9A60001, - 0x81C, 0xE8A80001, - 0x81C, 0xE7AA0001, - 0x81C, 0xE6AC0001, - 0x81C, 0xE5AE0001, - 0x81C, 0xE4B00001, - 0x81C, 0xE3B20001, - 0x81C, 0xA8B40001, - 0x81C, 0xA7B60001, - 0x81C, 0xA6B80001, - 0x81C, 0xA5BA0001, - 0x81C, 0xA4BC0001, - 0x81C, 0xA3BE0001, - 0x81C, 0xA2C00001, - 0x81C, 0xA1C20001, - 0x81C, 0x68C40001, - 0x81C, 0x67C60001, - 0x81C, 0x66C80001, - 0x81C, 0x65CA0001, - 0x81C, 0x64CC0001, - 0x81C, 0x47CE0001, - 0x81C, 0x46D00001, - 0x81C, 0x45D20001, - 0x81C, 0x44D40001, - 0x81C, 0x43D60001, - 0x81C, 0x42D80001, - 0x81C, 0x08DA0001, - 0x81C, 0x07DC0001, - 0x81C, 0x06DE0001, - 0x81C, 0x05E00001, - 0x81C, 0x04E20001, - 0x81C, 0x03E40001, - 0x81C, 0x02E60001, - 0x81C, 0x01E80001, - 0x81C, 0x01EA0001, - 0x81C, 0x01EC0001, - 0x81C, 0x01EE0001, - 0x81C, 0x01F00001, - 0x81C, 0x01F20001, - 0x81C, 0x01F40001, - 0x81C, 0x01F60001, - 0x81C, 0x01F80001, - 0x81C, 0x01FA0001, - 0x81C, 0x01FC0001, - 0x81C, 0x01FE0001, - 0xFF0F02C0, 0xCDEF, - 0x81C, 0xFC800001, - 0x81C, 0xFB820001, - 0x81C, 0xFA840001, - 0x81C, 0xF9860001, - 0x81C, 0xF8880001, - 0x81C, 0xF78A0001, - 0x81C, 0xF68C0001, - 0x81C, 0xF58E0001, - 0x81C, 0xF4900001, - 0x81C, 0xF3920001, - 0x81C, 0xF2940001, - 0x81C, 0xF1960001, - 0x81C, 0xF0980001, - 0x81C, 0xEF9A0001, - 0x81C, 0xEE9C0001, - 0x81C, 0xED9E0001, - 0x81C, 0xECA00001, - 0x81C, 0xEBA20001, - 0x81C, 0xEAA40001, - 0x81C, 0xE9A60001, - 0x81C, 0xE8A80001, - 0x81C, 0xE7AA0001, - 0x81C, 0xE6AC0001, - 0x81C, 0xE5AE0001, - 0x81C, 0xE4B00001, - 0x81C, 0xE3B20001, - 0x81C, 0xA8B40001, - 0x81C, 0xA7B60001, - 0x81C, 0xA6B80001, - 0x81C, 0xA5BA0001, - 0x81C, 0xA4BC0001, - 0x81C, 0xA3BE0001, - 0x81C, 0xA2C00001, - 0x81C, 0xA1C20001, - 0x81C, 0x68C40001, - 0x81C, 0x67C60001, - 0x81C, 0x66C80001, - 0x81C, 0x65CA0001, - 0x81C, 0x64CC0001, - 0x81C, 0x47CE0001, - 0x81C, 0x46D00001, - 0x81C, 0x45D20001, - 0x81C, 0x44D40001, - 0x81C, 0x43D60001, - 0x81C, 0x42D80001, - 0x81C, 0x08DA0001, - 0x81C, 0x07DC0001, - 0x81C, 0x06DE0001, - 0x81C, 0x05E00001, - 0x81C, 0x04E20001, - 0x81C, 0x03E40001, - 0x81C, 0x02E60001, - 0x81C, 0x01E80001, - 0x81C, 0x01EA0001, - 0x81C, 0x01EC0001, - 0x81C, 0x01EE0001, - 0x81C, 0x01F00001, - 0x81C, 0x01F20001, - 0x81C, 0x01F40001, - 0x81C, 0x01F60001, - 0x81C, 0x01F80001, - 0x81C, 0x01FA0001, - 0x81C, 0x01FC0001, - 0x81C, 0x01FE0001, - 0xFF0F07D8, 0xCDEF, - 0x81C, 0xFC800001, - 0x81C, 0xFB820001, - 0x81C, 0xFA840001, - 0x81C, 0xF9860001, - 0x81C, 0xF8880001, - 0x81C, 0xF78A0001, - 0x81C, 0xF68C0001, - 0x81C, 0xF58E0001, - 0x81C, 0xF4900001, - 0x81C, 0xF3920001, - 0x81C, 0xF2940001, - 0x81C, 0xF1960001, - 0x81C, 0xF0980001, - 0x81C, 0xEF9A0001, - 0x81C, 0xEE9C0001, - 0x81C, 0xED9E0001, - 0x81C, 0xECA00001, - 0x81C, 0xEBA20001, - 0x81C, 0xEAA40001, - 0x81C, 0xE9A60001, - 0x81C, 0xE8A80001, - 0x81C, 0xE7AA0001, - 0x81C, 0xE6AC0001, - 0x81C, 0xE5AE0001, - 0x81C, 0xE4B00001, - 0x81C, 0xE3B20001, - 0x81C, 0xA8B40001, - 0x81C, 0xA7B60001, - 0x81C, 0xA6B80001, - 0x81C, 0xA5BA0001, - 0x81C, 0xA4BC0001, - 0x81C, 0xA3BE0001, - 0x81C, 0xA2C00001, - 0x81C, 0xA1C20001, - 0x81C, 0x68C40001, - 0x81C, 0x67C60001, - 0x81C, 0x66C80001, - 0x81C, 0x65CA0001, - 0x81C, 0x64CC0001, - 0x81C, 0x47CE0001, - 0x81C, 0x46D00001, - 0x81C, 0x45D20001, - 0x81C, 0x44D40001, - 0x81C, 0x43D60001, - 0x81C, 0x42D80001, - 0x81C, 0x08DA0001, - 0x81C, 0x07DC0001, - 0x81C, 0x06DE0001, - 0x81C, 0x05E00001, - 0x81C, 0x04E20001, - 0x81C, 0x03E40001, - 0x81C, 0x02E60001, - 0x81C, 0x01E80001, - 0x81C, 0x01EA0001, - 0x81C, 0x01EC0001, - 0x81C, 0x01EE0001, - 0x81C, 0x01F00001, - 0x81C, 0x01F20001, - 0x81C, 0x01F40001, - 0x81C, 0x01F60001, - 0x81C, 0x01F80001, - 0x81C, 0x01FA0001, - 0x81C, 0x01FC0001, - 0x81C, 0x01FE0001, - 0xFF0F07D0, 0xCDEF, - 0x81C, 0xFC800001, - 0x81C, 0xFB820001, - 0x81C, 0xFA840001, - 0x81C, 0xF9860001, - 0x81C, 0xF8880001, - 0x81C, 0xF78A0001, - 0x81C, 0xF68C0001, - 0x81C, 0xF58E0001, - 0x81C, 0xF4900001, - 0x81C, 0xF3920001, - 0x81C, 0xF2940001, - 0x81C, 0xF1960001, - 0x81C, 0xF0980001, - 0x81C, 0xEF9A0001, - 0x81C, 0xEE9C0001, - 0x81C, 0xED9E0001, - 0x81C, 0xECA00001, - 0x81C, 0xEBA20001, - 0x81C, 0xEAA40001, - 0x81C, 0xE9A60001, - 0x81C, 0xE8A80001, - 0x81C, 0xE7AA0001, - 0x81C, 0xE6AC0001, - 0x81C, 0xE5AE0001, - 0x81C, 0xE4B00001, - 0x81C, 0xE3B20001, - 0x81C, 0xA8B40001, - 0x81C, 0xA7B60001, - 0x81C, 0xA6B80001, - 0x81C, 0xA5BA0001, - 0x81C, 0xA4BC0001, - 0x81C, 0xA3BE0001, - 0x81C, 0xA2C00001, - 0x81C, 0xA1C20001, - 0x81C, 0x68C40001, - 0x81C, 0x67C60001, - 0x81C, 0x66C80001, - 0x81C, 0x65CA0001, - 0x81C, 0x64CC0001, - 0x81C, 0x47CE0001, - 0x81C, 0x46D00001, - 0x81C, 0x45D20001, - 0x81C, 0x44D40001, - 0x81C, 0x43D60001, - 0x81C, 0x42D80001, - 0x81C, 0x08DA0001, - 0x81C, 0x07DC0001, - 0x81C, 0x06DE0001, - 0x81C, 0x05E00001, - 0x81C, 0x04E20001, - 0x81C, 0x03E40001, - 0x81C, 0x02E60001, - 0x81C, 0x01E80001, - 0x81C, 0x01EA0001, - 0x81C, 0x01EC0001, - 0x81C, 0x01EE0001, - 0x81C, 0x01F00001, - 0x81C, 0x01F20001, - 0x81C, 0x01F40001, - 0x81C, 0x01F60001, - 0x81C, 0x01F80001, - 0x81C, 0x01FA0001, - 0x81C, 0x01FC0001, - 0x81C, 0x01FE0001, - 0xCDCDCDCD, 0xCDCD, - 0x81C, 0xFF800001, - 0x81C, 0xFF820001, - 0x81C, 0xFF840001, - 0x81C, 0xFE860001, - 0x81C, 0xFD880001, - 0x81C, 0xFC8A0001, - 0x81C, 0xFB8C0001, - 0x81C, 0xFA8E0001, - 0x81C, 0xF9900001, - 0x81C, 0xF8920001, - 0x81C, 0xF7940001, - 0x81C, 0xF6960001, - 0x81C, 0xF5980001, - 0x81C, 0xF49A0001, - 0x81C, 0xF39C0001, - 0x81C, 0xF29E0001, - 0x81C, 0xF1A00001, - 0x81C, 0xF0A20001, - 0x81C, 0xEFA40001, - 0x81C, 0xEEA60001, - 0x81C, 0xEDA80001, - 0x81C, 0xECAA0001, - 0x81C, 0xEBAC0001, - 0x81C, 0xEAAE0001, - 0x81C, 0xE9B00001, - 0x81C, 0xE8B20001, - 0x81C, 0xE7B40001, - 0x81C, 0xE6B60001, - 0x81C, 0xE5B80001, - 0x81C, 0xE4BA0001, - 0x81C, 0xE3BC0001, - 0x81C, 0xA8BE0001, - 0x81C, 0xA7C00001, - 0x81C, 0xA6C20001, - 0x81C, 0xA5C40001, - 0x81C, 0xA4C60001, - 0x81C, 0xA3C80001, - 0x81C, 0xA2CA0001, - 0x81C, 0xA1CC0001, - 0x81C, 0x68CE0001, - 0x81C, 0x67D00001, - 0x81C, 0x66D20001, - 0x81C, 0x65D40001, - 0x81C, 0x64D60001, - 0x81C, 0x47D80001, - 0x81C, 0x46DA0001, - 0x81C, 0x45DC0001, - 0x81C, 0x44DE0001, - 0x81C, 0x43E00001, - 0x81C, 0x42E20001, - 0x81C, 0x08E40001, - 0x81C, 0x07E60001, - 0x81C, 0x06E80001, - 0x81C, 0x05EA0001, - 0x81C, 0x04EC0001, - 0x81C, 0x03EE0001, - 0x81C, 0x02F00001, - 0x81C, 0x01F20001, - 0x81C, 0x01F40001, - 0x81C, 0x01F60001, - 0x81C, 0x01F80001, - 0x81C, 0x01FA0001, - 0x81C, 0x01FC0001, - 0x81C, 0x01FE0001, - 0xFF0F0180, 0xDEAD, - 0xC50, 0x00000022, - 0xC50, 0x00000020, - 0xE50, 0x00000022, - 0xE50, 0x00000020, - -}; - -u32 RTL8821AE_AGC_TAB_ARRAY[] = { - 0x81C, 0xBF000001, - 0x81C, 0xBF020001, - 0x81C, 0xBF040001, - 0x81C, 0xBF060001, - 0x81C, 0xBE080001, - 0x81C, 0xBD0A0001, - 0x81C, 0xBC0C0001, - 0x81C, 0xBA0E0001, - 0x81C, 0xB9100001, - 0x81C, 0xB8120001, - 0x81C, 0xB7140001, - 0x81C, 0xB6160001, - 0x81C, 0xB5180001, - 0x81C, 0xB41A0001, - 0x81C, 0xB31C0001, - 0x81C, 0xB21E0001, - 0x81C, 0xB1200001, - 0x81C, 0xB0220001, - 0x81C, 0xAF240001, - 0x81C, 0xAE260001, - 0x81C, 0xAD280001, - 0x81C, 0xAC2A0001, - 0x81C, 0xAB2C0001, - 0x81C, 0xAA2E0001, - 0x81C, 0xA9300001, - 0x81C, 0xA8320001, - 0x81C, 0xA7340001, - 0x81C, 0xA6360001, - 0x81C, 0xA5380001, - 0x81C, 0xA43A0001, - 0x81C, 0xA33C0001, - 0x81C, 0x673E0001, - 0x81C, 0x66400001, - 0x81C, 0x65420001, - 0x81C, 0x64440001, - 0x81C, 0x63460001, - 0x81C, 0x62480001, - 0x81C, 0x614A0001, - 0x81C, 0x474C0001, - 0x81C, 0x464E0001, - 0x81C, 0x45500001, - 0x81C, 0x44520001, - 0x81C, 0x43540001, - 0x81C, 0x42560001, - 0x81C, 0x41580001, - 0x81C, 0x285A0001, - 0x81C, 0x275C0001, - 0x81C, 0x265E0001, - 0x81C, 0x25600001, - 0x81C, 0x24620001, - 0x81C, 0x0A640001, - 0x81C, 0x09660001, - 0x81C, 0x08680001, - 0x81C, 0x076A0001, - 0x81C, 0x066C0001, - 0x81C, 0x056E0001, - 0x81C, 0x04700001, - 0x81C, 0x03720001, - 0x81C, 0x02740001, - 0x81C, 0x01760001, - 0x81C, 0x01780001, - 0x81C, 0x017A0001, - 0x81C, 0x017C0001, - 0x81C, 0x017E0001, - 0xFF0F02C0, 0xABCD, - 0x81C, 0xFB000101, - 0x81C, 0xFA020101, - 0x81C, 0xF9040101, - 0x81C, 0xF8060101, - 0x81C, 0xF7080101, - 0x81C, 0xF60A0101, - 0x81C, 0xF50C0101, - 0x81C, 0xF40E0101, - 0x81C, 0xF3100101, - 0x81C, 0xF2120101, - 0x81C, 0xF1140101, - 0x81C, 0xF0160101, - 0x81C, 0xEF180101, - 0x81C, 0xEE1A0101, - 0x81C, 0xED1C0101, - 0x81C, 0xEC1E0101, - 0x81C, 0xEB200101, - 0x81C, 0xEA220101, - 0x81C, 0xE9240101, - 0x81C, 0xE8260101, - 0x81C, 0xE7280101, - 0x81C, 0xE62A0101, - 0x81C, 0xE52C0101, - 0x81C, 0xE42E0101, - 0x81C, 0xE3300101, - 0x81C, 0xA5320101, - 0x81C, 0xA4340101, - 0x81C, 0xA3360101, - 0x81C, 0x87380101, - 0x81C, 0x863A0101, - 0x81C, 0x853C0101, - 0x81C, 0x843E0101, - 0x81C, 0x69400101, - 0x81C, 0x68420101, - 0x81C, 0x67440101, - 0x81C, 0x66460101, - 0x81C, 0x49480101, - 0x81C, 0x484A0101, - 0x81C, 0x474C0101, - 0x81C, 0x2A4E0101, - 0x81C, 0x29500101, - 0x81C, 0x28520101, - 0x81C, 0x27540101, - 0x81C, 0x26560101, - 0x81C, 0x25580101, - 0x81C, 0x245A0101, - 0x81C, 0x235C0101, - 0x81C, 0x055E0101, - 0x81C, 0x04600101, - 0x81C, 0x03620101, - 0x81C, 0x02640101, - 0x81C, 0x01660101, - 0x81C, 0x01680101, - 0x81C, 0x016A0101, - 0x81C, 0x016C0101, - 0x81C, 0x016E0101, - 0x81C, 0x01700101, - 0x81C, 0x01720101, - 0xCDCDCDCD, 0xCDCD, - 0x81C, 0xFF000101, - 0x81C, 0xFF020101, - 0x81C, 0xFE040101, - 0x81C, 0xFD060101, - 0x81C, 0xFC080101, - 0x81C, 0xFD0A0101, - 0x81C, 0xFC0C0101, - 0x81C, 0xFB0E0101, - 0x81C, 0xFA100101, - 0x81C, 0xF9120101, - 0x81C, 0xF8140101, - 0x81C, 0xF7160101, - 0x81C, 0xF6180101, - 0x81C, 0xF51A0101, - 0x81C, 0xF41C0101, - 0x81C, 0xF31E0101, - 0x81C, 0xF2200101, - 0x81C, 0xF1220101, - 0x81C, 0xF0240101, - 0x81C, 0xEF260101, - 0x81C, 0xEE280101, - 0x81C, 0xED2A0101, - 0x81C, 0xEC2C0101, - 0x81C, 0xEB2E0101, - 0x81C, 0xEA300101, - 0x81C, 0xE9320101, - 0x81C, 0xE8340101, - 0x81C, 0xE7360101, - 0x81C, 0xE6380101, - 0x81C, 0xE53A0101, - 0x81C, 0xE43C0101, - 0x81C, 0xE33E0101, - 0x81C, 0xA5400101, - 0x81C, 0xA4420101, - 0x81C, 0xA3440101, - 0x81C, 0x87460101, - 0x81C, 0x86480101, - 0x81C, 0x854A0101, - 0x81C, 0x844C0101, - 0x81C, 0x694E0101, - 0x81C, 0x68500101, - 0x81C, 0x67520101, - 0x81C, 0x66540101, - 0x81C, 0x49560101, - 0x81C, 0x48580101, - 0x81C, 0x475A0101, - 0x81C, 0x2A5C0101, - 0x81C, 0x295E0101, - 0x81C, 0x28600101, - 0x81C, 0x27620101, - 0x81C, 0x26640101, - 0x81C, 0x25660101, - 0x81C, 0x24680101, - 0x81C, 0x236A0101, - 0x81C, 0x056C0101, - 0x81C, 0x046E0101, - 0x81C, 0x03700101, - 0x81C, 0x02720101, - 0xFF0F02C0, 0xDEAD, - 0x81C, 0x01740101, - 0x81C, 0x01760101, - 0x81C, 0x01780101, - 0x81C, 0x017A0101, - 0x81C, 0x017C0101, - 0x81C, 0x017E0101, - 0xC50, 0x00000022, - 0xC50, 0x00000020, - -}; - -/****************************************************************************** -* TXPWR_LMT.TXT -******************************************************************************/ - -u8 *RTL8812AE_TXPWR_LMT[] = { - "FCC", "2.4G", "20M", "CCK", "1T", "01", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "01", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "01", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "02", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "02", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "02", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "03", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "03", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "03", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "04", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "04", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "04", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "05", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "05", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "05", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "06", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "06", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "06", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "07", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "07", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "07", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "08", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "08", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "08", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "09", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "09", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "09", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "10", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "10", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "10", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "11", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "11", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "11", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "12", "63", - "ETSI", "2.4G", "20M", "CCK", "1T", "12", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "12", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "13", "63", - "ETSI", "2.4G", "20M", "CCK", "1T", "13", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "13", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "14", "63", - "ETSI", "2.4G", "20M", "CCK", "1T", "14", "63", - "MKK", "2.4G", "20M", "CCK", "1T", "14", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "01", "34", - "ETSI", "2.4G", "20M", "OFDM", "1T", "01", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "01", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "02", "36", - "ETSI", "2.4G", "20M", "OFDM", "1T", "02", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "02", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "03", "36", - "ETSI", "2.4G", "20M", "OFDM", "1T", "03", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "03", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "04", "36", - "ETSI", "2.4G", "20M", "OFDM", "1T", "04", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "04", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "05", "36", - "ETSI", "2.4G", "20M", "OFDM", "1T", "05", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "05", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "06", "36", - "ETSI", "2.4G", "20M", "OFDM", "1T", "06", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "06", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "07", "36", - "ETSI", "2.4G", "20M", "OFDM", "1T", "07", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "07", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "08", "36", - "ETSI", "2.4G", "20M", "OFDM", "1T", "08", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "08", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "09", "36", - "ETSI", "2.4G", "20M", "OFDM", "1T", "09", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "09", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "10", "36", - "ETSI", "2.4G", "20M", "OFDM", "1T", "10", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "10", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "11", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "11", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "11", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "12", "63", - "ETSI", "2.4G", "20M", "OFDM", "1T", "12", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "12", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "13", "63", - "ETSI", "2.4G", "20M", "OFDM", "1T", "13", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "13", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "14", "63", - "ETSI", "2.4G", "20M", "OFDM", "1T", "14", "63", - "MKK", "2.4G", "20M", "OFDM", "1T", "14", "63", - "FCC", "2.4G", "20M", "HT", "1T", "01", "34", - "ETSI", "2.4G", "20M", "HT", "1T", "01", "32", - "MKK", "2.4G", "20M", "HT", "1T", "01", "32", - "FCC", "2.4G", "20M", "HT", "1T", "02", "36", - "ETSI", "2.4G", "20M", "HT", "1T", "02", "32", - "MKK", "2.4G", "20M", "HT", "1T", "02", "32", - "FCC", "2.4G", "20M", "HT", "1T", "03", "36", - "ETSI", "2.4G", "20M", "HT", "1T", "03", "32", - "MKK", "2.4G", "20M", "HT", "1T", "03", "32", - "FCC", "2.4G", "20M", "HT", "1T", "04", "36", - "ETSI", "2.4G", "20M", "HT", "1T", "04", "32", - "MKK", "2.4G", "20M", "HT", "1T", "04", "32", - "FCC", "2.4G", "20M", "HT", "1T", "05", "36", - "ETSI", "2.4G", "20M", "HT", "1T", "05", "32", - "MKK", "2.4G", "20M", "HT", "1T", "05", "32", - "FCC", "2.4G", "20M", "HT", "1T", "06", "36", - "ETSI", "2.4G", "20M", "HT", "1T", "06", "32", - "MKK", "2.4G", "20M", "HT", "1T", "06", "32", - "FCC", "2.4G", "20M", "HT", "1T", "07", "36", - "ETSI", "2.4G", "20M", "HT", "1T", "07", "32", - "MKK", "2.4G", "20M", "HT", "1T", "07", "32", - "FCC", "2.4G", "20M", "HT", "1T", "08", "36", - "ETSI", "2.4G", "20M", "HT", "1T", "08", "32", - "MKK", "2.4G", "20M", "HT", "1T", "08", "32", - "FCC", "2.4G", "20M", "HT", "1T", "09", "36", - "ETSI", "2.4G", "20M", "HT", "1T", "09", "32", - "MKK", "2.4G", "20M", "HT", "1T", "09", "32", - "FCC", "2.4G", "20M", "HT", "1T", "10", "36", - "ETSI", "2.4G", "20M", "HT", "1T", "10", "32", - "MKK", "2.4G", "20M", "HT", "1T", "10", "32", - "FCC", "2.4G", "20M", "HT", "1T", "11", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "11", "32", - "MKK", "2.4G", "20M", "HT", "1T", "11", "32", - "FCC", "2.4G", "20M", "HT", "1T", "12", "63", - "ETSI", "2.4G", "20M", "HT", "1T", "12", "32", - "MKK", "2.4G", "20M", "HT", "1T", "12", "32", - "FCC", "2.4G", "20M", "HT", "1T", "13", "63", - "ETSI", "2.4G", "20M", "HT", "1T", "13", "32", - "MKK", "2.4G", "20M", "HT", "1T", "13", "32", - "FCC", "2.4G", "20M", "HT", "1T", "14", "63", - "ETSI", "2.4G", "20M", "HT", "1T", "14", "63", - "MKK", "2.4G", "20M", "HT", "1T", "14", "63", - "FCC", "2.4G", "20M", "HT", "2T", "01", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "01", "32", - "MKK", "2.4G", "20M", "HT", "2T", "01", "32", - "FCC", "2.4G", "20M", "HT", "2T", "02", "34", - "ETSI", "2.4G", "20M", "HT", "2T", "02", "32", - "MKK", "2.4G", "20M", "HT", "2T", "02", "32", - "FCC", "2.4G", "20M", "HT", "2T", "03", "34", - "ETSI", "2.4G", "20M", "HT", "2T", "03", "32", - "MKK", "2.4G", "20M", "HT", "2T", "03", "32", - "FCC", "2.4G", "20M", "HT", "2T", "04", "34", - "ETSI", "2.4G", "20M", "HT", "2T", "04", "32", - "MKK", "2.4G", "20M", "HT", "2T", "04", "32", - "FCC", "2.4G", "20M", "HT", "2T", "05", "34", - "ETSI", "2.4G", "20M", "HT", "2T", "05", "32", - "MKK", "2.4G", "20M", "HT", "2T", "05", "32", - "FCC", "2.4G", "20M", "HT", "2T", "06", "34", - "ETSI", "2.4G", "20M", "HT", "2T", "06", "32", - "MKK", "2.4G", "20M", "HT", "2T", "06", "32", - "FCC", "2.4G", "20M", "HT", "2T", "07", "34", - "ETSI", "2.4G", "20M", "HT", "2T", "07", "32", - "MKK", "2.4G", "20M", "HT", "2T", "07", "32", - "FCC", "2.4G", "20M", "HT", "2T", "08", "34", - "ETSI", "2.4G", "20M", "HT", "2T", "08", "32", - "MKK", "2.4G", "20M", "HT", "2T", "08", "32", - "FCC", "2.4G", "20M", "HT", "2T", "09", "34", - "ETSI", "2.4G", "20M", "HT", "2T", "09", "32", - "MKK", "2.4G", "20M", "HT", "2T", "09", "32", - "FCC", "2.4G", "20M", "HT", "2T", "10", "34", - "ETSI", "2.4G", "20M", "HT", "2T", "10", "32", - "MKK", "2.4G", "20M", "HT", "2T", "10", "32", - "FCC", "2.4G", "20M", "HT", "2T", "11", "30", - "ETSI", "2.4G", "20M", "HT", "2T", "11", "32", - "MKK", "2.4G", "20M", "HT", "2T", "11", "32", - "FCC", "2.4G", "20M", "HT", "2T", "12", "63", - "ETSI", "2.4G", "20M", "HT", "2T", "12", "32", - "MKK", "2.4G", "20M", "HT", "2T", "12", "32", - "FCC", "2.4G", "20M", "HT", "2T", "13", "63", - "ETSI", "2.4G", "20M", "HT", "2T", "13", "32", - "MKK", "2.4G", "20M", "HT", "2T", "13", "32", - "FCC", "2.4G", "20M", "HT", "2T", "14", "63", - "ETSI", "2.4G", "20M", "HT", "2T", "14", "63", - "MKK", "2.4G", "20M", "HT", "2T", "14", "63", - "FCC", "2.4G", "40M", "HT", "1T", "01", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "01", "63", - "MKK", "2.4G", "40M", "HT", "1T", "01", "63", - "FCC", "2.4G", "40M", "HT", "1T", "02", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "02", "63", - "MKK", "2.4G", "40M", "HT", "1T", "02", "63", - "FCC", "2.4G", "40M", "HT", "1T", "03", "32", - "ETSI", "2.4G", "40M", "HT", "1T", "03", "32", - "MKK", "2.4G", "40M", "HT", "1T", "03", "32", - "FCC", "2.4G", "40M", "HT", "1T", "04", "36", - "ETSI", "2.4G", "40M", "HT", "1T", "04", "32", - "MKK", "2.4G", "40M", "HT", "1T", "04", "32", - "FCC", "2.4G", "40M", "HT", "1T", "05", "36", - "ETSI", "2.4G", "40M", "HT", "1T", "05", "32", - "MKK", "2.4G", "40M", "HT", "1T", "05", "32", - "FCC", "2.4G", "40M", "HT", "1T", "06", "36", - "ETSI", "2.4G", "40M", "HT", "1T", "06", "32", - "MKK", "2.4G", "40M", "HT", "1T", "06", "32", - "FCC", "2.4G", "40M", "HT", "1T", "07", "36", - "ETSI", "2.4G", "40M", "HT", "1T", "07", "32", - "MKK", "2.4G", "40M", "HT", "1T", "07", "32", - "FCC", "2.4G", "40M", "HT", "1T", "08", "36", - "ETSI", "2.4G", "40M", "HT", "1T", "08", "32", - "MKK", "2.4G", "40M", "HT", "1T", "08", "32", - "FCC", "2.4G", "40M", "HT", "1T", "09", "36", - "ETSI", "2.4G", "40M", "HT", "1T", "09", "32", - "MKK", "2.4G", "40M", "HT", "1T", "09", "32", - "FCC", "2.4G", "40M", "HT", "1T", "10", "36", - "ETSI", "2.4G", "40M", "HT", "1T", "10", "32", - "MKK", "2.4G", "40M", "HT", "1T", "10", "32", - "FCC", "2.4G", "40M", "HT", "1T", "11", "32", - "ETSI", "2.4G", "40M", "HT", "1T", "11", "32", - "MKK", "2.4G", "40M", "HT", "1T", "11", "32", - "FCC", "2.4G", "40M", "HT", "1T", "12", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "12", "32", - "MKK", "2.4G", "40M", "HT", "1T", "12", "32", - "FCC", "2.4G", "40M", "HT", "1T", "13", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "13", "32", - "MKK", "2.4G", "40M", "HT", "1T", "13", "32", - "FCC", "2.4G", "40M", "HT", "1T", "14", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "14", "63", - "MKK", "2.4G", "40M", "HT", "1T", "14", "63", - "FCC", "2.4G", "40M", "HT", "2T", "01", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "01", "63", - "MKK", "2.4G", "40M", "HT", "2T", "01", "63", - "FCC", "2.4G", "40M", "HT", "2T", "02", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "02", "63", - "MKK", "2.4G", "40M", "HT", "2T", "02", "63", - "FCC", "2.4G", "40M", "HT", "2T", "03", "30", - "ETSI", "2.4G", "40M", "HT", "2T", "03", "30", - "MKK", "2.4G", "40M", "HT", "2T", "03", "30", - "FCC", "2.4G", "40M", "HT", "2T", "04", "34", - "ETSI", "2.4G", "40M", "HT", "2T", "04", "30", - "MKK", "2.4G", "40M", "HT", "2T", "04", "30", - "FCC", "2.4G", "40M", "HT", "2T", "05", "34", - "ETSI", "2.4G", "40M", "HT", "2T", "05", "30", - "MKK", "2.4G", "40M", "HT", "2T", "05", "30", - "FCC", "2.4G", "40M", "HT", "2T", "06", "34", - "ETSI", "2.4G", "40M", "HT", "2T", "06", "30", - "MKK", "2.4G", "40M", "HT", "2T", "06", "30", - "FCC", "2.4G", "40M", "HT", "2T", "07", "34", - "ETSI", "2.4G", "40M", "HT", "2T", "07", "30", - "MKK", "2.4G", "40M", "HT", "2T", "07", "30", - "FCC", "2.4G", "40M", "HT", "2T", "08", "34", - "ETSI", "2.4G", "40M", "HT", "2T", "08", "30", - "MKK", "2.4G", "40M", "HT", "2T", "08", "30", - "FCC", "2.4G", "40M", "HT", "2T", "09", "34", - "ETSI", "2.4G", "40M", "HT", "2T", "09", "30", - "MKK", "2.4G", "40M", "HT", "2T", "09", "30", - "FCC", "2.4G", "40M", "HT", "2T", "10", "34", - "ETSI", "2.4G", "40M", "HT", "2T", "10", "30", - "MKK", "2.4G", "40M", "HT", "2T", "10", "30", - "FCC", "2.4G", "40M", "HT", "2T", "11", "30", - "ETSI", "2.4G", "40M", "HT", "2T", "11", "30", - "MKK", "2.4G", "40M", "HT", "2T", "11", "30", - "FCC", "2.4G", "40M", "HT", "2T", "12", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "12", "32", - "MKK", "2.4G", "40M", "HT", "2T", "12", "32", - "FCC", "2.4G", "40M", "HT", "2T", "13", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "13", "32", - "MKK", "2.4G", "40M", "HT", "2T", "13", "32", - "FCC", "2.4G", "40M", "HT", "2T", "14", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "14", "63", - "MKK", "2.4G", "40M", "HT", "2T", "14", "63", - "FCC", "5G", "20M", "OFDM", "1T", "36", "30", - "ETSI", "5G", "20M", "OFDM", "1T", "36", "32", - "MKK", "5G", "20M", "OFDM", "1T", "36", "32", - "FCC", "5G", "20M", "OFDM", "1T", "40", "30", - "ETSI", "5G", "20M", "OFDM", "1T", "40", "32", - "MKK", "5G", "20M", "OFDM", "1T", "40", "32", - "FCC", "5G", "20M", "OFDM", "1T", "44", "30", - "ETSI", "5G", "20M", "OFDM", "1T", "44", "32", - "MKK", "5G", "20M", "OFDM", "1T", "44", "32", - "FCC", "5G", "20M", "OFDM", "1T", "48", "30", - "ETSI", "5G", "20M", "OFDM", "1T", "48", "32", - "MKK", "5G", "20M", "OFDM", "1T", "48", "32", - "FCC", "5G", "20M", "OFDM", "1T", "52", "36", - "ETSI", "5G", "20M", "OFDM", "1T", "52", "32", - "MKK", "5G", "20M", "OFDM", "1T", "52", "32", - "FCC", "5G", "20M", "OFDM", "1T", "56", "34", - "ETSI", "5G", "20M", "OFDM", "1T", "56", "32", - "MKK", "5G", "20M", "OFDM", "1T", "56", "32", - "FCC", "5G", "20M", "OFDM", "1T", "60", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "60", "32", - "MKK", "5G", "20M", "OFDM", "1T", "60", "32", - "FCC", "5G", "20M", "OFDM", "1T", "64", "28", - "ETSI", "5G", "20M", "OFDM", "1T", "64", "32", - "MKK", "5G", "20M", "OFDM", "1T", "64", "32", - "FCC", "5G", "20M", "OFDM", "1T", "100", "30", - "ETSI", "5G", "20M", "OFDM", "1T", "100", "32", - "MKK", "5G", "20M", "OFDM", "1T", "100", "32", - "FCC", "5G", "20M", "OFDM", "1T", "114", "30", - "ETSI", "5G", "20M", "OFDM", "1T", "114", "32", - "MKK", "5G", "20M", "OFDM", "1T", "114", "32", - "FCC", "5G", "20M", "OFDM", "1T", "108", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "108", "32", - "MKK", "5G", "20M", "OFDM", "1T", "108", "32", - "FCC", "5G", "20M", "OFDM", "1T", "112", "34", - "ETSI", "5G", "20M", "OFDM", "1T", "112", "32", - "MKK", "5G", "20M", "OFDM", "1T", "112", "32", - "FCC", "5G", "20M", "OFDM", "1T", "116", "34", - "ETSI", "5G", "20M", "OFDM", "1T", "116", "32", - "MKK", "5G", "20M", "OFDM", "1T", "116", "32", - "FCC", "5G", "20M", "OFDM", "1T", "120", "36", - "ETSI", "5G", "20M", "OFDM", "1T", "120", "32", - "MKK", "5G", "20M", "OFDM", "1T", "120", "32", - "FCC", "5G", "20M", "OFDM", "1T", "124", "34", - "ETSI", "5G", "20M", "OFDM", "1T", "124", "32", - "MKK", "5G", "20M", "OFDM", "1T", "124", "32", - "FCC", "5G", "20M", "OFDM", "1T", "128", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "128", "32", - "MKK", "5G", "20M", "OFDM", "1T", "128", "32", - "FCC", "5G", "20M", "OFDM", "1T", "132", "30", - "ETSI", "5G", "20M", "OFDM", "1T", "132", "32", - "MKK", "5G", "20M", "OFDM", "1T", "132", "32", - "FCC", "5G", "20M", "OFDM", "1T", "136", "30", - "ETSI", "5G", "20M", "OFDM", "1T", "136", "32", - "MKK", "5G", "20M", "OFDM", "1T", "136", "32", - "FCC", "5G", "20M", "OFDM", "1T", "140", "28", - "ETSI", "5G", "20M", "OFDM", "1T", "140", "32", - "MKK", "5G", "20M", "OFDM", "1T", "140", "32", - "FCC", "5G", "20M", "OFDM", "1T", "149", "36", - "ETSI", "5G", "20M", "OFDM", "1T", "149", "32", - "MKK", "5G", "20M", "OFDM", "1T", "149", "63", - "FCC", "5G", "20M", "OFDM", "1T", "153", "36", - "ETSI", "5G", "20M", "OFDM", "1T", "153", "32", - "MKK", "5G", "20M", "OFDM", "1T", "153", "63", - "FCC", "5G", "20M", "OFDM", "1T", "157", "36", - "ETSI", "5G", "20M", "OFDM", "1T", "157", "32", - "MKK", "5G", "20M", "OFDM", "1T", "157", "63", - "FCC", "5G", "20M", "OFDM", "1T", "161", "36", - "ETSI", "5G", "20M", "OFDM", "1T", "161", "32", - "MKK", "5G", "20M", "OFDM", "1T", "161", "63", - "FCC", "5G", "20M", "OFDM", "1T", "165", "36", - "ETSI", "5G", "20M", "OFDM", "1T", "165", "32", - "MKK", "5G", "20M", "OFDM", "1T", "165", "63", - "FCC", "5G", "20M", "HT", "1T", "36", "30", - "ETSI", "5G", "20M", "HT", "1T", "36", "32", - "MKK", "5G", "20M", "HT", "1T", "36", "32", - "FCC", "5G", "20M", "HT", "1T", "40", "30", - "ETSI", "5G", "20M", "HT", "1T", "40", "32", - "MKK", "5G", "20M", "HT", "1T", "40", "32", - "FCC", "5G", "20M", "HT", "1T", "44", "30", - "ETSI", "5G", "20M", "HT", "1T", "44", "32", - "MKK", "5G", "20M", "HT", "1T", "44", "32", - "FCC", "5G", "20M", "HT", "1T", "48", "30", - "ETSI", "5G", "20M", "HT", "1T", "48", "32", - "MKK", "5G", "20M", "HT", "1T", "48", "32", - "FCC", "5G", "20M", "HT", "1T", "52", "36", - "ETSI", "5G", "20M", "HT", "1T", "52", "32", - "MKK", "5G", "20M", "HT", "1T", "52", "32", - "FCC", "5G", "20M", "HT", "1T", "56", "34", - "ETSI", "5G", "20M", "HT", "1T", "56", "32", - "MKK", "5G", "20M", "HT", "1T", "56", "32", - "FCC", "5G", "20M", "HT", "1T", "60", "32", - "ETSI", "5G", "20M", "HT", "1T", "60", "32", - "MKK", "5G", "20M", "HT", "1T", "60", "32", - "FCC", "5G", "20M", "HT", "1T", "64", "28", - "ETSI", "5G", "20M", "HT", "1T", "64", "32", - "MKK", "5G", "20M", "HT", "1T", "64", "32", - "FCC", "5G", "20M", "HT", "1T", "100", "30", - "ETSI", "5G", "20M", "HT", "1T", "100", "32", - "MKK", "5G", "20M", "HT", "1T", "100", "32", - "FCC", "5G", "20M", "HT", "1T", "114", "30", - "ETSI", "5G", "20M", "HT", "1T", "114", "32", - "MKK", "5G", "20M", "HT", "1T", "114", "32", - "FCC", "5G", "20M", "HT", "1T", "108", "32", - "ETSI", "5G", "20M", "HT", "1T", "108", "32", - "MKK", "5G", "20M", "HT", "1T", "108", "32", - "FCC", "5G", "20M", "HT", "1T", "112", "34", - "ETSI", "5G", "20M", "HT", "1T", "112", "32", - "MKK", "5G", "20M", "HT", "1T", "112", "32", - "FCC", "5G", "20M", "HT", "1T", "116", "34", - "ETSI", "5G", "20M", "HT", "1T", "116", "32", - "MKK", "5G", "20M", "HT", "1T", "116", "32", - "FCC", "5G", "20M", "HT", "1T", "120", "36", - "ETSI", "5G", "20M", "HT", "1T", "120", "32", - "MKK", "5G", "20M", "HT", "1T", "120", "32", - "FCC", "5G", "20M", "HT", "1T", "124", "34", - "ETSI", "5G", "20M", "HT", "1T", "124", "32", - "MKK", "5G", "20M", "HT", "1T", "124", "32", - "FCC", "5G", "20M", "HT", "1T", "128", "32", - "ETSI", "5G", "20M", "HT", "1T", "128", "32", - "MKK", "5G", "20M", "HT", "1T", "128", "32", - "FCC", "5G", "20M", "HT", "1T", "132", "30", - "ETSI", "5G", "20M", "HT", "1T", "132", "32", - "MKK", "5G", "20M", "HT", "1T", "132", "32", - "FCC", "5G", "20M", "HT", "1T", "136", "30", - "ETSI", "5G", "20M", "HT", "1T", "136", "32", - "MKK", "5G", "20M", "HT", "1T", "136", "32", - "FCC", "5G", "20M", "HT", "1T", "140", "28", - "ETSI", "5G", "20M", "HT", "1T", "140", "32", - "MKK", "5G", "20M", "HT", "1T", "140", "32", - "FCC", "5G", "20M", "HT", "1T", "149", "36", - "ETSI", "5G", "20M", "HT", "1T", "149", "32", - "MKK", "5G", "20M", "HT", "1T", "149", "63", - "FCC", "5G", "20M", "HT", "1T", "153", "36", - "ETSI", "5G", "20M", "HT", "1T", "153", "32", - "MKK", "5G", "20M", "HT", "1T", "153", "63", - "FCC", "5G", "20M", "HT", "1T", "157", "36", - "ETSI", "5G", "20M", "HT", "1T", "157", "32", - "MKK", "5G", "20M", "HT", "1T", "157", "63", - "FCC", "5G", "20M", "HT", "1T", "161", "36", - "ETSI", "5G", "20M", "HT", "1T", "161", "32", - "MKK", "5G", "20M", "HT", "1T", "161", "63", - "FCC", "5G", "20M", "HT", "1T", "165", "36", - "ETSI", "5G", "20M", "HT", "1T", "165", "32", - "MKK", "5G", "20M", "HT", "1T", "165", "63", - "FCC", "5G", "20M", "HT", "2T", "36", "28", - "ETSI", "5G", "20M", "HT", "2T", "36", "30", - "MKK", "5G", "20M", "HT", "2T", "36", "30", - "FCC", "5G", "20M", "HT", "2T", "40", "28", - "ETSI", "5G", "20M", "HT", "2T", "40", "30", - "MKK", "5G", "20M", "HT", "2T", "40", "30", - "FCC", "5G", "20M", "HT", "2T", "44", "28", - "ETSI", "5G", "20M", "HT", "2T", "44", "30", - "MKK", "5G", "20M", "HT", "2T", "44", "30", - "FCC", "5G", "20M", "HT", "2T", "48", "28", - "ETSI", "5G", "20M", "HT", "2T", "48", "30", - "MKK", "5G", "20M", "HT", "2T", "48", "30", - "FCC", "5G", "20M", "HT", "2T", "52", "34", - "ETSI", "5G", "20M", "HT", "2T", "52", "30", - "MKK", "5G", "20M", "HT", "2T", "52", "30", - "FCC", "5G", "20M", "HT", "2T", "56", "32", - "ETSI", "5G", "20M", "HT", "2T", "56", "30", - "MKK", "5G", "20M", "HT", "2T", "56", "30", - "FCC", "5G", "20M", "HT", "2T", "60", "30", - "ETSI", "5G", "20M", "HT", "2T", "60", "30", - "MKK", "5G", "20M", "HT", "2T", "60", "30", - "FCC", "5G", "20M", "HT", "2T", "64", "26", - "ETSI", "5G", "20M", "HT", "2T", "64", "30", - "MKK", "5G", "20M", "HT", "2T", "64", "30", - "FCC", "5G", "20M", "HT", "2T", "100", "28", - "ETSI", "5G", "20M", "HT", "2T", "100", "30", - "MKK", "5G", "20M", "HT", "2T", "100", "30", - "FCC", "5G", "20M", "HT", "2T", "114", "28", - "ETSI", "5G", "20M", "HT", "2T", "114", "30", - "MKK", "5G", "20M", "HT", "2T", "114", "30", - "FCC", "5G", "20M", "HT", "2T", "108", "30", - "ETSI", "5G", "20M", "HT", "2T", "108", "30", - "MKK", "5G", "20M", "HT", "2T", "108", "30", - "FCC", "5G", "20M", "HT", "2T", "112", "32", - "ETSI", "5G", "20M", "HT", "2T", "112", "30", - "MKK", "5G", "20M", "HT", "2T", "112", "30", - "FCC", "5G", "20M", "HT", "2T", "116", "32", - "ETSI", "5G", "20M", "HT", "2T", "116", "30", - "MKK", "5G", "20M", "HT", "2T", "116", "30", - "FCC", "5G", "20M", "HT", "2T", "120", "34", - "ETSI", "5G", "20M", "HT", "2T", "120", "30", - "MKK", "5G", "20M", "HT", "2T", "120", "30", - "FCC", "5G", "20M", "HT", "2T", "124", "32", - "ETSI", "5G", "20M", "HT", "2T", "124", "30", - "MKK", "5G", "20M", "HT", "2T", "124", "30", - "FCC", "5G", "20M", "HT", "2T", "128", "30", - "ETSI", "5G", "20M", "HT", "2T", "128", "30", - "MKK", "5G", "20M", "HT", "2T", "128", "30", - "FCC", "5G", "20M", "HT", "2T", "132", "28", - "ETSI", "5G", "20M", "HT", "2T", "132", "30", - "MKK", "5G", "20M", "HT", "2T", "132", "30", - "FCC", "5G", "20M", "HT", "2T", "136", "28", - "ETSI", "5G", "20M", "HT", "2T", "136", "30", - "MKK", "5G", "20M", "HT", "2T", "136", "30", - "FCC", "5G", "20M", "HT", "2T", "140", "26", - "ETSI", "5G", "20M", "HT", "2T", "140", "30", - "MKK", "5G", "20M", "HT", "2T", "140", "30", - "FCC", "5G", "20M", "HT", "2T", "149", "34", - "ETSI", "5G", "20M", "HT", "2T", "149", "30", - "MKK", "5G", "20M", "HT", "2T", "149", "63", - "FCC", "5G", "20M", "HT", "2T", "153", "34", - "ETSI", "5G", "20M", "HT", "2T", "153", "30", - "MKK", "5G", "20M", "HT", "2T", "153", "63", - "FCC", "5G", "20M", "HT", "2T", "157", "34", - "ETSI", "5G", "20M", "HT", "2T", "157", "30", - "MKK", "5G", "20M", "HT", "2T", "157", "63", - "FCC", "5G", "20M", "HT", "2T", "161", "34", - "ETSI", "5G", "20M", "HT", "2T", "161", "30", - "MKK", "5G", "20M", "HT", "2T", "161", "63", - "FCC", "5G", "20M", "HT", "2T", "165", "34", - "ETSI", "5G", "20M", "HT", "2T", "165", "30", - "MKK", "5G", "20M", "HT", "2T", "165", "63", - "FCC", "5G", "40M", "HT", "1T", "38", "30", - "ETSI", "5G", "40M", "HT", "1T", "38", "32", - "MKK", "5G", "40M", "HT", "1T", "38", "32", - "FCC", "5G", "40M", "HT", "1T", "46", "30", - "ETSI", "5G", "40M", "HT", "1T", "46", "32", - "MKK", "5G", "40M", "HT", "1T", "46", "32", - "FCC", "5G", "40M", "HT", "1T", "54", "32", - "ETSI", "5G", "40M", "HT", "1T", "54", "32", - "MKK", "5G", "40M", "HT", "1T", "54", "32", - "FCC", "5G", "40M", "HT", "1T", "62", "32", - "ETSI", "5G", "40M", "HT", "1T", "62", "32", - "MKK", "5G", "40M", "HT", "1T", "62", "32", - "FCC", "5G", "40M", "HT", "1T", "102", "28", - "ETSI", "5G", "40M", "HT", "1T", "102", "32", - "MKK", "5G", "40M", "HT", "1T", "102", "32", - "FCC", "5G", "40M", "HT", "1T", "110", "32", - "ETSI", "5G", "40M", "HT", "1T", "110", "32", - "MKK", "5G", "40M", "HT", "1T", "110", "32", - "FCC", "5G", "40M", "HT", "1T", "118", "36", - "ETSI", "5G", "40M", "HT", "1T", "118", "32", - "MKK", "5G", "40M", "HT", "1T", "118", "32", - "FCC", "5G", "40M", "HT", "1T", "126", "34", - "ETSI", "5G", "40M", "HT", "1T", "126", "32", - "MKK", "5G", "40M", "HT", "1T", "126", "32", - "FCC", "5G", "40M", "HT", "1T", "134", "32", - "ETSI", "5G", "40M", "HT", "1T", "134", "32", - "MKK", "5G", "40M", "HT", "1T", "134", "32", - "FCC", "5G", "40M", "HT", "1T", "151", "36", - "ETSI", "5G", "40M", "HT", "1T", "151", "32", - "MKK", "5G", "40M", "HT", "1T", "151", "63", - "FCC", "5G", "40M", "HT", "1T", "159", "36", - "ETSI", "5G", "40M", "HT", "1T", "159", "32", - "MKK", "5G", "40M", "HT", "1T", "159", "63", - "FCC", "5G", "40M", "HT", "2T", "38", "28", - "ETSI", "5G", "40M", "HT", "2T", "38", "30", - "MKK", "5G", "40M", "HT", "2T", "38", "30", - "FCC", "5G", "40M", "HT", "2T", "46", "28", - "ETSI", "5G", "40M", "HT", "2T", "46", "30", - "MKK", "5G", "40M", "HT", "2T", "46", "30", - "FCC", "5G", "40M", "HT", "2T", "54", "30", - "ETSI", "5G", "40M", "HT", "2T", "54", "30", - "MKK", "5G", "40M", "HT", "2T", "54", "30", - "FCC", "5G", "40M", "HT", "2T", "62", "30", - "ETSI", "5G", "40M", "HT", "2T", "62", "30", - "MKK", "5G", "40M", "HT", "2T", "62", "30", - "FCC", "5G", "40M", "HT", "2T", "102", "26", - "ETSI", "5G", "40M", "HT", "2T", "102", "30", - "MKK", "5G", "40M", "HT", "2T", "102", "30", - "FCC", "5G", "40M", "HT", "2T", "110", "30", - "ETSI", "5G", "40M", "HT", "2T", "110", "30", - "MKK", "5G", "40M", "HT", "2T", "110", "30", - "FCC", "5G", "40M", "HT", "2T", "118", "34", - "ETSI", "5G", "40M", "HT", "2T", "118", "30", - "MKK", "5G", "40M", "HT", "2T", "118", "30", - "FCC", "5G", "40M", "HT", "2T", "126", "32", - "ETSI", "5G", "40M", "HT", "2T", "126", "30", - "MKK", "5G", "40M", "HT", "2T", "126", "30", - "FCC", "5G", "40M", "HT", "2T", "134", "30", - "ETSI", "5G", "40M", "HT", "2T", "134", "30", - "MKK", "5G", "40M", "HT", "2T", "134", "30", - "FCC", "5G", "40M", "HT", "2T", "151", "34", - "ETSI", "5G", "40M", "HT", "2T", "151", "30", - "MKK", "5G", "40M", "HT", "2T", "151", "63", - "FCC", "5G", "40M", "HT", "2T", "159", "34", - "ETSI", "5G", "40M", "HT", "2T", "159", "30", - "MKK", "5G", "40M", "HT", "2T", "159", "63", - "FCC", "5G", "80M", "VHT", "1T", "42", "30", - "ETSI", "5G", "80M", "VHT", "1T", "42", "32", - "MKK", "5G", "80M", "VHT", "1T", "42", "32", - "FCC", "5G", "80M", "VHT", "1T", "58", "28", - "ETSI", "5G", "80M", "VHT", "1T", "58", "32", - "MKK", "5G", "80M", "VHT", "1T", "58", "32", - "FCC", "5G", "80M", "VHT", "1T", "106", "30", - "ETSI", "5G", "80M", "VHT", "1T", "106", "32", - "MKK", "5G", "80M", "VHT", "1T", "106", "32", - "FCC", "5G", "80M", "VHT", "1T", "122", "34", - "ETSI", "5G", "80M", "VHT", "1T", "122", "32", - "MKK", "5G", "80M", "VHT", "1T", "122", "32", - "FCC", "5G", "80M", "VHT", "1T", "155", "36", - "ETSI", "5G", "80M", "VHT", "1T", "155", "32", - "MKK", "5G", "80M", "VHT", "1T", "155", "63", - "FCC", "5G", "80M", "VHT", "2T", "42", "28", - "ETSI", "5G", "80M", "VHT", "2T", "42", "30", - "MKK", "5G", "80M", "VHT", "2T", "42", "30", - "FCC", "5G", "80M", "VHT", "2T", "58", "26", - "ETSI", "5G", "80M", "VHT", "2T", "58", "30", - "MKK", "5G", "80M", "VHT", "2T", "58", "30", - "FCC", "5G", "80M", "VHT", "2T", "106", "28", - "ETSI", "5G", "80M", "VHT", "2T", "106", "30", - "MKK", "5G", "80M", "VHT", "2T", "106", "30", - "FCC", "5G", "80M", "VHT", "2T", "122", "32", - "ETSI", "5G", "80M", "VHT", "2T", "122", "30", - "MKK", "5G", "80M", "VHT", "2T", "122", "30", - "FCC", "5G", "80M", "VHT", "2T", "155", "34", - "ETSI", "5G", "80M", "VHT", "2T", "155", "30", - "MKK", "5G", "80M", "VHT", "2T", "155", "63" -}; - -u8 *RTL8821AE_TXPWR_LMT[] = { - "FCC", "2.4G", "20M", "CCK", "1T", "01", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "01", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "01", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "02", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "02", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "02", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "03", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "03", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "03", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "04", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "04", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "04", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "05", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "05", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "05", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "06", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "06", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "06", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "07", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "07", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "07", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "08", "36", - "ETSI", "2.4G", "20M", "CCK", "1T", "08", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "08", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "09", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "09", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "09", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "10", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "10", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "10", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "11", "32", - "ETSI", "2.4G", "20M", "CCK", "1T", "11", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "11", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "12", "63", - "ETSI", "2.4G", "20M", "CCK", "1T", "12", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "12", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "13", "63", - "ETSI", "2.4G", "20M", "CCK", "1T", "13", "32", - "MKK", "2.4G", "20M", "CCK", "1T", "13", "32", - "FCC", "2.4G", "20M", "CCK", "1T", "14", "63", - "ETSI", "2.4G", "20M", "CCK", "1T", "14", "63", - "MKK", "2.4G", "20M", "CCK", "1T", "14", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "01", "30", - "ETSI", "2.4G", "20M", "OFDM", "1T", "01", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "01", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "02", "30", - "ETSI", "2.4G", "20M", "OFDM", "1T", "02", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "02", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "03", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "03", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "03", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "04", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "04", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "04", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "05", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "05", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "05", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "06", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "06", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "06", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "07", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "07", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "07", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "08", "32", - "ETSI", "2.4G", "20M", "OFDM", "1T", "08", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "08", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "09", "30", - "ETSI", "2.4G", "20M", "OFDM", "1T", "09", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "09", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "10", "30", - "ETSI", "2.4G", "20M", "OFDM", "1T", "10", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "10", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "11", "30", - "ETSI", "2.4G", "20M", "OFDM", "1T", "11", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "11", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "12", "63", - "ETSI", "2.4G", "20M", "OFDM", "1T", "12", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "12", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "13", "63", - "ETSI", "2.4G", "20M", "OFDM", "1T", "13", "32", - "MKK", "2.4G", "20M", "OFDM", "1T", "13", "32", - "FCC", "2.4G", "20M", "OFDM", "1T", "14", "63", - "ETSI", "2.4G", "20M", "OFDM", "1T", "14", "63", - "MKK", "2.4G", "20M", "OFDM", "1T", "14", "63", - "FCC", "2.4G", "20M", "HT", "1T", "01", "26", - "ETSI", "2.4G", "20M", "HT", "1T", "01", "32", - "MKK", "2.4G", "20M", "HT", "1T", "01", "32", - "FCC", "2.4G", "20M", "HT", "1T", "02", "26", - "ETSI", "2.4G", "20M", "HT", "1T", "02", "32", - "MKK", "2.4G", "20M", "HT", "1T", "02", "32", - "FCC", "2.4G", "20M", "HT", "1T", "03", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "03", "32", - "MKK", "2.4G", "20M", "HT", "1T", "03", "32", - "FCC", "2.4G", "20M", "HT", "1T", "04", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "04", "32", - "MKK", "2.4G", "20M", "HT", "1T", "04", "32", - "FCC", "2.4G", "20M", "HT", "1T", "05", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "05", "32", - "MKK", "2.4G", "20M", "HT", "1T", "05", "32", - "FCC", "2.4G", "20M", "HT", "1T", "06", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "06", "32", - "MKK", "2.4G", "20M", "HT", "1T", "06", "32", - "FCC", "2.4G", "20M", "HT", "1T", "07", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "07", "32", - "MKK", "2.4G", "20M", "HT", "1T", "07", "32", - "FCC", "2.4G", "20M", "HT", "1T", "08", "32", - "ETSI", "2.4G", "20M", "HT", "1T", "08", "32", - "MKK", "2.4G", "20M", "HT", "1T", "08", "32", - "FCC", "2.4G", "20M", "HT", "1T", "09", "26", - "ETSI", "2.4G", "20M", "HT", "1T", "09", "32", - "MKK", "2.4G", "20M", "HT", "1T", "09", "32", - "FCC", "2.4G", "20M", "HT", "1T", "10", "26", - "ETSI", "2.4G", "20M", "HT", "1T", "10", "32", - "MKK", "2.4G", "20M", "HT", "1T", "10", "32", - "FCC", "2.4G", "20M", "HT", "1T", "11", "26", - "ETSI", "2.4G", "20M", "HT", "1T", "11", "32", - "MKK", "2.4G", "20M", "HT", "1T", "11", "32", - "FCC", "2.4G", "20M", "HT", "1T", "12", "63", - "ETSI", "2.4G", "20M", "HT", "1T", "12", "32", - "MKK", "2.4G", "20M", "HT", "1T", "12", "32", - "FCC", "2.4G", "20M", "HT", "1T", "13", "63", - "ETSI", "2.4G", "20M", "HT", "1T", "13", "32", - "MKK", "2.4G", "20M", "HT", "1T", "13", "32", - "FCC", "2.4G", "20M", "HT", "1T", "14", "63", - "ETSI", "2.4G", "20M", "HT", "1T", "14", "63", - "MKK", "2.4G", "20M", "HT", "1T", "14", "63", - "FCC", "2.4G", "20M", "HT", "2T", "01", "30", - "ETSI", "2.4G", "20M", "HT", "2T", "01", "32", - "MKK", "2.4G", "20M", "HT", "2T", "01", "32", - "FCC", "2.4G", "20M", "HT", "2T", "02", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "02", "32", - "MKK", "2.4G", "20M", "HT", "2T", "02", "32", - "FCC", "2.4G", "20M", "HT", "2T", "03", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "03", "32", - "MKK", "2.4G", "20M", "HT", "2T", "03", "32", - "FCC", "2.4G", "20M", "HT", "2T", "04", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "04", "32", - "MKK", "2.4G", "20M", "HT", "2T", "04", "32", - "FCC", "2.4G", "20M", "HT", "2T", "05", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "05", "32", - "MKK", "2.4G", "20M", "HT", "2T", "05", "32", - "FCC", "2.4G", "20M", "HT", "2T", "06", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "06", "32", - "MKK", "2.4G", "20M", "HT", "2T", "06", "32", - "FCC", "2.4G", "20M", "HT", "2T", "07", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "07", "32", - "MKK", "2.4G", "20M", "HT", "2T", "07", "32", - "FCC", "2.4G", "20M", "HT", "2T", "08", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "08", "32", - "MKK", "2.4G", "20M", "HT", "2T", "08", "32", - "FCC", "2.4G", "20M", "HT", "2T", "09", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "09", "32", - "MKK", "2.4G", "20M", "HT", "2T", "09", "32", - "FCC", "2.4G", "20M", "HT", "2T", "10", "32", - "ETSI", "2.4G", "20M", "HT", "2T", "10", "32", - "MKK", "2.4G", "20M", "HT", "2T", "10", "32", - "FCC", "2.4G", "20M", "HT", "2T", "11", "30", - "ETSI", "2.4G", "20M", "HT", "2T", "11", "32", - "MKK", "2.4G", "20M", "HT", "2T", "11", "32", - "FCC", "2.4G", "20M", "HT", "2T", "12", "63", - "ETSI", "2.4G", "20M", "HT", "2T", "12", "32", - "MKK", "2.4G", "20M", "HT", "2T", "12", "32", - "FCC", "2.4G", "20M", "HT", "2T", "13", "63", - "ETSI", "2.4G", "20M", "HT", "2T", "13", "32", - "MKK", "2.4G", "20M", "HT", "2T", "13", "32", - "FCC", "2.4G", "20M", "HT", "2T", "14", "63", - "ETSI", "2.4G", "20M", "HT", "2T", "14", "63", - "MKK", "2.4G", "20M", "HT", "2T", "14", "63", - "FCC", "2.4G", "40M", "HT", "1T", "01", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "01", "63", - "MKK", "2.4G", "40M", "HT", "1T", "01", "63", - "FCC", "2.4G", "40M", "HT", "1T", "02", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "02", "63", - "MKK", "2.4G", "40M", "HT", "1T", "02", "63", - "FCC", "2.4G", "40M", "HT", "1T", "03", "26", - "ETSI", "2.4G", "40M", "HT", "1T", "03", "32", - "MKK", "2.4G", "40M", "HT", "1T", "03", "32", - "FCC", "2.4G", "40M", "HT", "1T", "04", "26", - "ETSI", "2.4G", "40M", "HT", "1T", "04", "32", - "MKK", "2.4G", "40M", "HT", "1T", "04", "32", - "FCC", "2.4G", "40M", "HT", "1T", "05", "26", - "ETSI", "2.4G", "40M", "HT", "1T", "05", "32", - "MKK", "2.4G", "40M", "HT", "1T", "05", "32", - "FCC", "2.4G", "40M", "HT", "1T", "06", "32", - "ETSI", "2.4G", "40M", "HT", "1T", "06", "32", - "MKK", "2.4G", "40M", "HT", "1T", "06", "32", - "FCC", "2.4G", "40M", "HT", "1T", "07", "32", - "ETSI", "2.4G", "40M", "HT", "1T", "07", "32", - "MKK", "2.4G", "40M", "HT", "1T", "07", "32", - "FCC", "2.4G", "40M", "HT", "1T", "08", "32", - "ETSI", "2.4G", "40M", "HT", "1T", "08", "32", - "MKK", "2.4G", "40M", "HT", "1T", "08", "32", - "FCC", "2.4G", "40M", "HT", "1T", "09", "26", - "ETSI", "2.4G", "40M", "HT", "1T", "09", "32", - "MKK", "2.4G", "40M", "HT", "1T", "09", "32", - "FCC", "2.4G", "40M", "HT", "1T", "10", "26", - "ETSI", "2.4G", "40M", "HT", "1T", "10", "32", - "MKK", "2.4G", "40M", "HT", "1T", "10", "32", - "FCC", "2.4G", "40M", "HT", "1T", "11", "26", - "ETSI", "2.4G", "40M", "HT", "1T", "11", "32", - "MKK", "2.4G", "40M", "HT", "1T", "11", "32", - "FCC", "2.4G", "40M", "HT", "1T", "12", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "12", "32", - "MKK", "2.4G", "40M", "HT", "1T", "12", "32", - "FCC", "2.4G", "40M", "HT", "1T", "13", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "13", "32", - "MKK", "2.4G", "40M", "HT", "1T", "13", "32", - "FCC", "2.4G", "40M", "HT", "1T", "14", "63", - "ETSI", "2.4G", "40M", "HT", "1T", "14", "63", - "MKK", "2.4G", "40M", "HT", "1T", "14", "63", - "FCC", "2.4G", "40M", "HT", "2T", "01", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "01", "63", - "MKK", "2.4G", "40M", "HT", "2T", "01", "63", - "FCC", "2.4G", "40M", "HT", "2T", "02", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "02", "63", - "MKK", "2.4G", "40M", "HT", "2T", "02", "63", - "FCC", "2.4G", "40M", "HT", "2T", "03", "30", - "ETSI", "2.4G", "40M", "HT", "2T", "03", "30", - "MKK", "2.4G", "40M", "HT", "2T", "03", "30", - "FCC", "2.4G", "40M", "HT", "2T", "04", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "04", "30", - "MKK", "2.4G", "40M", "HT", "2T", "04", "30", - "FCC", "2.4G", "40M", "HT", "2T", "05", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "05", "30", - "MKK", "2.4G", "40M", "HT", "2T", "05", "30", - "FCC", "2.4G", "40M", "HT", "2T", "06", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "06", "30", - "MKK", "2.4G", "40M", "HT", "2T", "06", "30", - "FCC", "2.4G", "40M", "HT", "2T", "07", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "07", "30", - "MKK", "2.4G", "40M", "HT", "2T", "07", "30", - "FCC", "2.4G", "40M", "HT", "2T", "08", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "08", "30", - "MKK", "2.4G", "40M", "HT", "2T", "08", "30", - "FCC", "2.4G", "40M", "HT", "2T", "09", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "09", "30", - "MKK", "2.4G", "40M", "HT", "2T", "09", "30", - "FCC", "2.4G", "40M", "HT", "2T", "10", "32", - "ETSI", "2.4G", "40M", "HT", "2T", "10", "30", - "MKK", "2.4G", "40M", "HT", "2T", "10", "30", - "FCC", "2.4G", "40M", "HT", "2T", "11", "30", - "ETSI", "2.4G", "40M", "HT", "2T", "11", "30", - "MKK", "2.4G", "40M", "HT", "2T", "11", "30", - "FCC", "2.4G", "40M", "HT", "2T", "12", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "12", "32", - "MKK", "2.4G", "40M", "HT", "2T", "12", "32", - "FCC", "2.4G", "40M", "HT", "2T", "13", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "13", "32", - "MKK", "2.4G", "40M", "HT", "2T", "13", "32", - "FCC", "2.4G", "40M", "HT", "2T", "14", "63", - "ETSI", "2.4G", "40M", "HT", "2T", "14", "63", - "MKK", "2.4G", "40M", "HT", "2T", "14", "63", - "FCC", "5G", "20M", "OFDM", "1T", "36", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "36", "30", - "MKK", "5G", "20M", "OFDM", "1T", "36", "30", - "FCC", "5G", "20M", "OFDM", "1T", "40", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "40", "30", - "MKK", "5G", "20M", "OFDM", "1T", "40", "30", - "FCC", "5G", "20M", "OFDM", "1T", "44", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "44", "30", - "MKK", "5G", "20M", "OFDM", "1T", "44", "30", - "FCC", "5G", "20M", "OFDM", "1T", "48", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "48", "30", - "MKK", "5G", "20M", "OFDM", "1T", "48", "30", - "FCC", "5G", "20M", "OFDM", "1T", "52", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "52", "30", - "MKK", "5G", "20M", "OFDM", "1T", "52", "30", - "FCC", "5G", "20M", "OFDM", "1T", "56", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "56", "30", - "MKK", "5G", "20M", "OFDM", "1T", "56", "30", - "FCC", "5G", "20M", "OFDM", "1T", "60", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "60", "30", - "MKK", "5G", "20M", "OFDM", "1T", "60", "30", - "FCC", "5G", "20M", "OFDM", "1T", "64", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "64", "30", - "MKK", "5G", "20M", "OFDM", "1T", "64", "30", - "FCC", "5G", "20M", "OFDM", "1T", "100", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "100", "30", - "MKK", "5G", "20M", "OFDM", "1T", "100", "30", - "FCC", "5G", "20M", "OFDM", "1T", "114", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "114", "30", - "MKK", "5G", "20M", "OFDM", "1T", "114", "30", - "FCC", "5G", "20M", "OFDM", "1T", "108", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "108", "30", - "MKK", "5G", "20M", "OFDM", "1T", "108", "30", - "FCC", "5G", "20M", "OFDM", "1T", "112", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "112", "30", - "MKK", "5G", "20M", "OFDM", "1T", "112", "30", - "FCC", "5G", "20M", "OFDM", "1T", "116", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "116", "30", - "MKK", "5G", "20M", "OFDM", "1T", "116", "30", - "FCC", "5G", "20M", "OFDM", "1T", "120", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "120", "30", - "MKK", "5G", "20M", "OFDM", "1T", "120", "30", - "FCC", "5G", "20M", "OFDM", "1T", "124", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "124", "30", - "MKK", "5G", "20M", "OFDM", "1T", "124", "30", - "FCC", "5G", "20M", "OFDM", "1T", "128", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "128", "30", - "MKK", "5G", "20M", "OFDM", "1T", "128", "30", - "FCC", "5G", "20M", "OFDM", "1T", "132", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "132", "30", - "MKK", "5G", "20M", "OFDM", "1T", "132", "30", - "FCC", "5G", "20M", "OFDM", "1T", "136", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "136", "30", - "MKK", "5G", "20M", "OFDM", "1T", "136", "30", - "FCC", "5G", "20M", "OFDM", "1T", "140", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "140", "30", - "MKK", "5G", "20M", "OFDM", "1T", "140", "30", - "FCC", "5G", "20M", "OFDM", "1T", "149", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "149", "30", - "MKK", "5G", "20M", "OFDM", "1T", "149", "63", - "FCC", "5G", "20M", "OFDM", "1T", "153", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "153", "30", - "MKK", "5G", "20M", "OFDM", "1T", "153", "63", - "FCC", "5G", "20M", "OFDM", "1T", "157", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "157", "30", - "MKK", "5G", "20M", "OFDM", "1T", "157", "63", - "FCC", "5G", "20M", "OFDM", "1T", "161", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "161", "30", - "MKK", "5G", "20M", "OFDM", "1T", "161", "63", - "FCC", "5G", "20M", "OFDM", "1T", "165", "32", - "ETSI", "5G", "20M", "OFDM", "1T", "165", "30", - "MKK", "5G", "20M", "OFDM", "1T", "165", "63", - "FCC", "5G", "20M", "HT", "1T", "36", "32", - "ETSI", "5G", "20M", "HT", "1T", "36", "30", - "MKK", "5G", "20M", "HT", "1T", "36", "30", - "FCC", "5G", "20M", "HT", "1T", "40", "32", - "ETSI", "5G", "20M", "HT", "1T", "40", "30", - "MKK", "5G", "20M", "HT", "1T", "40", "30", - "FCC", "5G", "20M", "HT", "1T", "44", "32", - "ETSI", "5G", "20M", "HT", "1T", "44", "30", - "MKK", "5G", "20M", "HT", "1T", "44", "30", - "FCC", "5G", "20M", "HT", "1T", "48", "32", - "ETSI", "5G", "20M", "HT", "1T", "48", "30", - "MKK", "5G", "20M", "HT", "1T", "48", "30", - "FCC", "5G", "20M", "HT", "1T", "52", "32", - "ETSI", "5G", "20M", "HT", "1T", "52", "30", - "MKK", "5G", "20M", "HT", "1T", "52", "30", - "FCC", "5G", "20M", "HT", "1T", "56", "32", - "ETSI", "5G", "20M", "HT", "1T", "56", "30", - "MKK", "5G", "20M", "HT", "1T", "56", "30", - "FCC", "5G", "20M", "HT", "1T", "60", "32", - "ETSI", "5G", "20M", "HT", "1T", "60", "30", - "MKK", "5G", "20M", "HT", "1T", "60", "30", - "FCC", "5G", "20M", "HT", "1T", "64", "32", - "ETSI", "5G", "20M", "HT", "1T", "64", "30", - "MKK", "5G", "20M", "HT", "1T", "64", "30", - "FCC", "5G", "20M", "HT", "1T", "100", "32", - "ETSI", "5G", "20M", "HT", "1T", "100", "30", - "MKK", "5G", "20M", "HT", "1T", "100", "30", - "FCC", "5G", "20M", "HT", "1T", "114", "32", - "ETSI", "5G", "20M", "HT", "1T", "114", "30", - "MKK", "5G", "20M", "HT", "1T", "114", "30", - "FCC", "5G", "20M", "HT", "1T", "108", "32", - "ETSI", "5G", "20M", "HT", "1T", "108", "30", - "MKK", "5G", "20M", "HT", "1T", "108", "30", - "FCC", "5G", "20M", "HT", "1T", "112", "32", - "ETSI", "5G", "20M", "HT", "1T", "112", "30", - "MKK", "5G", "20M", "HT", "1T", "112", "30", - "FCC", "5G", "20M", "HT", "1T", "116", "32", - "ETSI", "5G", "20M", "HT", "1T", "116", "30", - "MKK", "5G", "20M", "HT", "1T", "116", "30", - "FCC", "5G", "20M", "HT", "1T", "120", "32", - "ETSI", "5G", "20M", "HT", "1T", "120", "30", - "MKK", "5G", "20M", "HT", "1T", "120", "30", - "FCC", "5G", "20M", "HT", "1T", "124", "32", - "ETSI", "5G", "20M", "HT", "1T", "124", "30", - "MKK", "5G", "20M", "HT", "1T", "124", "30", - "FCC", "5G", "20M", "HT", "1T", "128", "32", - "ETSI", "5G", "20M", "HT", "1T", "128", "30", - "MKK", "5G", "20M", "HT", "1T", "128", "30", - "FCC", "5G", "20M", "HT", "1T", "132", "32", - "ETSI", "5G", "20M", "HT", "1T", "132", "30", - "MKK", "5G", "20M", "HT", "1T", "132", "30", - "FCC", "5G", "20M", "HT", "1T", "136", "32", - "ETSI", "5G", "20M", "HT", "1T", "136", "30", - "MKK", "5G", "20M", "HT", "1T", "136", "30", - "FCC", "5G", "20M", "HT", "1T", "140", "32", - "ETSI", "5G", "20M", "HT", "1T", "140", "30", - "MKK", "5G", "20M", "HT", "1T", "140", "30", - "FCC", "5G", "20M", "HT", "1T", "149", "32", - "ETSI", "5G", "20M", "HT", "1T", "149", "30", - "MKK", "5G", "20M", "HT", "1T", "149", "63", - "FCC", "5G", "20M", "HT", "1T", "153", "32", - "ETSI", "5G", "20M", "HT", "1T", "153", "30", - "MKK", "5G", "20M", "HT", "1T", "153", "63", - "FCC", "5G", "20M", "HT", "1T", "157", "32", - "ETSI", "5G", "20M", "HT", "1T", "157", "30", - "MKK", "5G", "20M", "HT", "1T", "157", "63", - "FCC", "5G", "20M", "HT", "1T", "161", "32", - "ETSI", "5G", "20M", "HT", "1T", "161", "30", - "MKK", "5G", "20M", "HT", "1T", "161", "63", - "FCC", "5G", "20M", "HT", "1T", "165", "32", - "ETSI", "5G", "20M", "HT", "1T", "165", "30", - "MKK", "5G", "20M", "HT", "1T", "165", "63", - "FCC", "5G", "20M", "HT", "2T", "36", "28", - "ETSI", "5G", "20M", "HT", "2T", "36", "30", - "MKK", "5G", "20M", "HT", "2T", "36", "30", - "FCC", "5G", "20M", "HT", "2T", "40", "28", - "ETSI", "5G", "20M", "HT", "2T", "40", "30", - "MKK", "5G", "20M", "HT", "2T", "40", "30", - "FCC", "5G", "20M", "HT", "2T", "44", "28", - "ETSI", "5G", "20M", "HT", "2T", "44", "30", - "MKK", "5G", "20M", "HT", "2T", "44", "30", - "FCC", "5G", "20M", "HT", "2T", "48", "28", - "ETSI", "5G", "20M", "HT", "2T", "48", "30", - "MKK", "5G", "20M", "HT", "2T", "48", "30", - "FCC", "5G", "20M", "HT", "2T", "52", "34", - "ETSI", "5G", "20M", "HT", "2T", "52", "30", - "MKK", "5G", "20M", "HT", "2T", "52", "30", - "FCC", "5G", "20M", "HT", "2T", "56", "32", - "ETSI", "5G", "20M", "HT", "2T", "56", "30", - "MKK", "5G", "20M", "HT", "2T", "56", "30", - "FCC", "5G", "20M", "HT", "2T", "60", "30", - "ETSI", "5G", "20M", "HT", "2T", "60", "30", - "MKK", "5G", "20M", "HT", "2T", "60", "30", - "FCC", "5G", "20M", "HT", "2T", "64", "26", - "ETSI", "5G", "20M", "HT", "2T", "64", "30", - "MKK", "5G", "20M", "HT", "2T", "64", "30", - "FCC", "5G", "20M", "HT", "2T", "100", "28", - "ETSI", "5G", "20M", "HT", "2T", "100", "30", - "MKK", "5G", "20M", "HT", "2T", "100", "30", - "FCC", "5G", "20M", "HT", "2T", "114", "28", - "ETSI", "5G", "20M", "HT", "2T", "114", "30", - "MKK", "5G", "20M", "HT", "2T", "114", "30", - "FCC", "5G", "20M", "HT", "2T", "108", "30", - "ETSI", "5G", "20M", "HT", "2T", "108", "30", - "MKK", "5G", "20M", "HT", "2T", "108", "30", - "FCC", "5G", "20M", "HT", "2T", "112", "32", - "ETSI", "5G", "20M", "HT", "2T", "112", "30", - "MKK", "5G", "20M", "HT", "2T", "112", "30", - "FCC", "5G", "20M", "HT", "2T", "116", "32", - "ETSI", "5G", "20M", "HT", "2T", "116", "30", - "MKK", "5G", "20M", "HT", "2T", "116", "30", - "FCC", "5G", "20M", "HT", "2T", "120", "34", - "ETSI", "5G", "20M", "HT", "2T", "120", "30", - "MKK", "5G", "20M", "HT", "2T", "120", "30", - "FCC", "5G", "20M", "HT", "2T", "124", "32", - "ETSI", "5G", "20M", "HT", "2T", "124", "30", - "MKK", "5G", "20M", "HT", "2T", "124", "30", - "FCC", "5G", "20M", "HT", "2T", "128", "30", - "ETSI", "5G", "20M", "HT", "2T", "128", "30", - "MKK", "5G", "20M", "HT", "2T", "128", "30", - "FCC", "5G", "20M", "HT", "2T", "132", "28", - "ETSI", "5G", "20M", "HT", "2T", "132", "30", - "MKK", "5G", "20M", "HT", "2T", "132", "30", - "FCC", "5G", "20M", "HT", "2T", "136", "28", - "ETSI", "5G", "20M", "HT", "2T", "136", "30", - "MKK", "5G", "20M", "HT", "2T", "136", "30", - "FCC", "5G", "20M", "HT", "2T", "140", "26", - "ETSI", "5G", "20M", "HT", "2T", "140", "30", - "MKK", "5G", "20M", "HT", "2T", "140", "30", - "FCC", "5G", "20M", "HT", "2T", "149", "34", - "ETSI", "5G", "20M", "HT", "2T", "149", "30", - "MKK", "5G", "20M", "HT", "2T", "149", "63", - "FCC", "5G", "20M", "HT", "2T", "153", "34", - "ETSI", "5G", "20M", "HT", "2T", "153", "30", - "MKK", "5G", "20M", "HT", "2T", "153", "63", - "FCC", "5G", "20M", "HT", "2T", "157", "34", - "ETSI", "5G", "20M", "HT", "2T", "157", "30", - "MKK", "5G", "20M", "HT", "2T", "157", "63", - "FCC", "5G", "20M", "HT", "2T", "161", "34", - "ETSI", "5G", "20M", "HT", "2T", "161", "30", - "MKK", "5G", "20M", "HT", "2T", "161", "63", - "FCC", "5G", "20M", "HT", "2T", "165", "34", - "ETSI", "5G", "20M", "HT", "2T", "165", "30", - "MKK", "5G", "20M", "HT", "2T", "165", "63", - "FCC", "5G", "40M", "HT", "1T", "38", "26", - "ETSI", "5G", "40M", "HT", "1T", "38", "30", - "MKK", "5G", "40M", "HT", "1T", "38", "30", - "FCC", "5G", "40M", "HT", "1T", "46", "32", - "ETSI", "5G", "40M", "HT", "1T", "46", "30", - "MKK", "5G", "40M", "HT", "1T", "46", "30", - "FCC", "5G", "40M", "HT", "1T", "54", "32", - "ETSI", "5G", "40M", "HT", "1T", "54", "30", - "MKK", "5G", "40M", "HT", "1T", "54", "30", - "FCC", "5G", "40M", "HT", "1T", "62", "24", - "ETSI", "5G", "40M", "HT", "1T", "62", "30", - "MKK", "5G", "40M", "HT", "1T", "62", "30", - "FCC", "5G", "40M", "HT", "1T", "102", "24", - "ETSI", "5G", "40M", "HT", "1T", "102", "30", - "MKK", "5G", "40M", "HT", "1T", "102", "30", - "FCC", "5G", "40M", "HT", "1T", "110", "32", - "ETSI", "5G", "40M", "HT", "1T", "110", "30", - "MKK", "5G", "40M", "HT", "1T", "110", "30", - "FCC", "5G", "40M", "HT", "1T", "118", "32", - "ETSI", "5G", "40M", "HT", "1T", "118", "30", - "MKK", "5G", "40M", "HT", "1T", "118", "30", - "FCC", "5G", "40M", "HT", "1T", "126", "32", - "ETSI", "5G", "40M", "HT", "1T", "126", "30", - "MKK", "5G", "40M", "HT", "1T", "126", "30", - "FCC", "5G", "40M", "HT", "1T", "134", "32", - "ETSI", "5G", "40M", "HT", "1T", "134", "30", - "MKK", "5G", "40M", "HT", "1T", "134", "30", - "FCC", "5G", "40M", "HT", "1T", "151", "30", - "ETSI", "5G", "40M", "HT", "1T", "151", "30", - "MKK", "5G", "40M", "HT", "1T", "151", "63", - "FCC", "5G", "40M", "HT", "1T", "159", "32", - "ETSI", "5G", "40M", "HT", "1T", "159", "30", - "MKK", "5G", "40M", "HT", "1T", "159", "63", - "FCC", "5G", "40M", "HT", "2T", "38", "28", - "ETSI", "5G", "40M", "HT", "2T", "38", "30", - "MKK", "5G", "40M", "HT", "2T", "38", "30", - "FCC", "5G", "40M", "HT", "2T", "46", "28", - "ETSI", "5G", "40M", "HT", "2T", "46", "30", - "MKK", "5G", "40M", "HT", "2T", "46", "30", - "FCC", "5G", "40M", "HT", "2T", "54", "30", - "ETSI", "5G", "40M", "HT", "2T", "54", "30", - "MKK", "5G", "40M", "HT", "2T", "54", "30", - "FCC", "5G", "40M", "HT", "2T", "62", "30", - "ETSI", "5G", "40M", "HT", "2T", "62", "30", - "MKK", "5G", "40M", "HT", "2T", "62", "30", - "FCC", "5G", "40M", "HT", "2T", "102", "26", - "ETSI", "5G", "40M", "HT", "2T", "102", "30", - "MKK", "5G", "40M", "HT", "2T", "102", "30", - "FCC", "5G", "40M", "HT", "2T", "110", "30", - "ETSI", "5G", "40M", "HT", "2T", "110", "30", - "MKK", "5G", "40M", "HT", "2T", "110", "30", - "FCC", "5G", "40M", "HT", "2T", "118", "34", - "ETSI", "5G", "40M", "HT", "2T", "118", "30", - "MKK", "5G", "40M", "HT", "2T", "118", "30", - "FCC", "5G", "40M", "HT", "2T", "126", "32", - "ETSI", "5G", "40M", "HT", "2T", "126", "30", - "MKK", "5G", "40M", "HT", "2T", "126", "30", - "FCC", "5G", "40M", "HT", "2T", "134", "30", - "ETSI", "5G", "40M", "HT", "2T", "134", "30", - "MKK", "5G", "40M", "HT", "2T", "134", "30", - "FCC", "5G", "40M", "HT", "2T", "151", "34", - "ETSI", "5G", "40M", "HT", "2T", "151", "30", - "MKK", "5G", "40M", "HT", "2T", "151", "63", - "FCC", "5G", "40M", "HT", "2T", "159", "34", - "ETSI", "5G", "40M", "HT", "2T", "159", "30", - "MKK", "5G", "40M", "HT", "2T", "159", "63", - "FCC", "5G", "80M", "VHT", "1T", "42", "22", - "ETSI", "5G", "80M", "VHT", "1T", "42", "30", - "MKK", "5G", "80M", "VHT", "1T", "42", "30", - "FCC", "5G", "80M", "VHT", "1T", "58", "20", - "ETSI", "5G", "80M", "VHT", "1T", "58", "30", - "MKK", "5G", "80M", "VHT", "1T", "58", "30", - "FCC", "5G", "80M", "VHT", "1T", "106", "20", - "ETSI", "5G", "80M", "VHT", "1T", "106", "30", - "MKK", "5G", "80M", "VHT", "1T", "106", "30", - "FCC", "5G", "80M", "VHT", "1T", "122", "20", - "ETSI", "5G", "80M", "VHT", "1T", "122", "30", - "MKK", "5G", "80M", "VHT", "1T", "122", "30", - "FCC", "5G", "80M", "VHT", "1T", "155", "28", - "ETSI", "5G", "80M", "VHT", "1T", "155", "30", - "MKK", "5G", "80M", "VHT", "1T", "155", "63", - "FCC", "5G", "80M", "VHT", "2T", "42", "28", - "ETSI", "5G", "80M", "VHT", "2T", "42", "30", - "MKK", "5G", "80M", "VHT", "2T", "42", "30", - "FCC", "5G", "80M", "VHT", "2T", "58", "26", - "ETSI", "5G", "80M", "VHT", "2T", "58", "30", - "MKK", "5G", "80M", "VHT", "2T", "58", "30", - "FCC", "5G", "80M", "VHT", "2T", "106", "28", - "ETSI", "5G", "80M", "VHT", "2T", "106", "30", - "MKK", "5G", "80M", "VHT", "2T", "106", "30", - "FCC", "5G", "80M", "VHT", "2T", "122", "32", - "ETSI", "5G", "80M", "VHT", "2T", "122", "30", - "MKK", "5G", "80M", "VHT", "2T", "122", "30", - "FCC", "5G", "80M", "VHT", "2T", "155", "34", - "ETSI", "5G", "80M", "VHT", "2T", "155", "30", - "MKK", "5G", "80M", "VHT", "2T", "155", "63" -}; diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/table.h b/drivers/net/wireless/rtlwifi/rtl8821ae/table.h deleted file mode 100644 index 24bcff6bc507..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/table.h +++ /dev/null @@ -1,60 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Created on 2010/ 5/18, 1:41 - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8821AE_TABLE__H_ -#define __RTL8821AE_TABLE__H_ - -#include -#define RTL8821AEPHY_REG_1TARRAYLEN 344 -extern u32 RTL8821AE_PHY_REG_ARRAY[]; -#define RTL8812AEPHY_REG_1TARRAYLEN 490 -extern u32 RTL8812AE_PHY_REG_ARRAY[]; -#define RTL8821AEPHY_REG_ARRAY_PGLEN 90 -extern u32 RTL8821AE_PHY_REG_ARRAY_PG[]; -#define RTL8812AEPHY_REG_ARRAY_PGLEN 276 -extern u32 RTL8812AE_PHY_REG_ARRAY_PG[]; -/* #define RTL8723BE_RADIOA_1TARRAYLEN 206 */ -/* extern u8 *RTL8821AE_TXPWR_LMT_ARRAY[]; */ -#define RTL8812AE_RADIOA_1TARRAYLEN 1264 -extern u32 RTL8812AE_RADIOA_ARRAY[]; -#define RTL8812AE_RADIOB_1TARRAYLEN 1240 -extern u32 RTL8812AE_RADIOB_ARRAY[]; -#define RTL8821AE_RADIOA_1TARRAYLEN 1176 -extern u32 RTL8821AE_RADIOA_ARRAY[]; -#define RTL8821AEMAC_1T_ARRAYLEN 194 -extern u32 RTL8821AE_MAC_REG_ARRAY[]; -#define RTL8812AEMAC_1T_ARRAYLEN 214 -extern u32 RTL8812AE_MAC_REG_ARRAY[]; -#define RTL8821AEAGCTAB_1TARRAYLEN 382 -extern u32 RTL8821AE_AGC_TAB_ARRAY[]; -#define RTL8812AEAGCTAB_1TARRAYLEN 1312 -extern u32 RTL8812AE_AGC_TAB_ARRAY[]; -#define RTL8812AE_TXPWR_LMT_ARRAY_LEN 3948 -extern u8 *RTL8812AE_TXPWR_LMT[]; -#define RTL8821AE_TXPWR_LMT_ARRAY_LEN 3948 -extern u8 *RTL8821AE_TXPWR_LMT[]; -#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.c b/drivers/net/wireless/rtlwifi/rtl8821ae/trx.c deleted file mode 100644 index 174743aef943..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.c +++ /dev/null @@ -1,1024 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#include "../wifi.h" -#include "../pci.h" -#include "../base.h" -#include "../stats.h" -#include "reg.h" -#include "def.h" -#include "phy.h" -#include "trx.h" -#include "led.h" -#include "dm.h" -#include "phy.h" -#include "fw.h" - -static u8 _rtl8821ae_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) -{ - __le16 fc = rtl_get_fc(skb); - - if (unlikely(ieee80211_is_beacon(fc))) - return QSLT_BEACON; - if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) - return QSLT_MGNT; - - return skb->priority; -} - -static u16 odm_cfo(char value) -{ - int ret_val; - - if (value < 0) { - ret_val = 0 - value; - ret_val = (ret_val << 1) + (ret_val >> 1); - /* set bit12 as 1 for negative cfo */ - ret_val = ret_val | BIT(12); - } else { - ret_val = value; - ret_val = (ret_val << 1) + (ret_val >> 1); - } - return ret_val; -} - -static u8 _rtl8821ae_evm_dbm_jaguar(char value) -{ - char ret_val = value; - - /* -33dB~0dB to 33dB ~ 0dB*/ - if (ret_val == -128) - ret_val = 127; - else if (ret_val < 0) - ret_val = 0 - ret_val; - - ret_val = ret_val >> 1; - return ret_val; -} - -static void query_rxphystatus(struct ieee80211_hw *hw, - struct rtl_stats *pstatus, u8 *pdesc, - struct rx_fwinfo_8821ae *p_drvinfo, - bool bpacket_match_bssid, - bool bpacket_toself, bool packet_beacon) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct phy_status_rpt *p_phystrpt = (struct phy_status_rpt *)p_drvinfo; - struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); - struct rtl_phy *rtlphy = &rtlpriv->phy; - char rx_pwr_all = 0, rx_pwr[4]; - u8 rf_rx_num = 0, evm, evmdbm, pwdb_all; - u8 i, max_spatial_stream; - u32 rssi, total_rssi = 0; - bool is_cck = pstatus->is_cck; - u8 lan_idx, vga_idx; - - /* Record it for next packet processing */ - pstatus->packet_matchbssid = bpacket_match_bssid; - pstatus->packet_toself = bpacket_toself; - pstatus->packet_beacon = packet_beacon; - pstatus->rx_mimo_signalquality[0] = -1; - pstatus->rx_mimo_signalquality[1] = -1; - - if (is_cck) { - u8 cck_highpwr; - u8 cck_agc_rpt; - - cck_agc_rpt = p_phystrpt->cfosho[0]; - - /* (1)Hardware does not provide RSSI for CCK - * (2)PWDB, Average PWDB cacluated by - * hardware (for rate adaptive) - */ - cck_highpwr = (u8)rtlphy->cck_high_power; - - lan_idx = ((cck_agc_rpt & 0xE0) >> 5); - vga_idx = (cck_agc_rpt & 0x1f); - if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE) { - switch (lan_idx) { - case 7: - if (vga_idx <= 27) - /*VGA_idx = 27~2*/ - rx_pwr_all = -100 + 2*(27-vga_idx); - else - rx_pwr_all = -100; - break; - case 6: - /*VGA_idx = 2~0*/ - rx_pwr_all = -48 + 2*(2-vga_idx); - break; - case 5: - /*VGA_idx = 7~5*/ - rx_pwr_all = -42 + 2*(7-vga_idx); - break; - case 4: - /*VGA_idx = 7~4*/ - rx_pwr_all = -36 + 2*(7-vga_idx); - break; - case 3: - /*VGA_idx = 7~0*/ - rx_pwr_all = -24 + 2*(7-vga_idx); - break; - case 2: - if (cck_highpwr) - /*VGA_idx = 5~0*/ - rx_pwr_all = -12 + 2*(5-vga_idx); - else - rx_pwr_all = -6 + 2*(5-vga_idx); - break; - case 1: - rx_pwr_all = 8-2*vga_idx; - break; - case 0: - rx_pwr_all = 14-2*vga_idx; - break; - default: - break; - } - rx_pwr_all += 6; - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - if (!cck_highpwr) { - if (pwdb_all >= 80) - pwdb_all = - ((pwdb_all - 80)<<1) + - ((pwdb_all - 80)>>1) + 80; - else if ((pwdb_all <= 78) && (pwdb_all >= 20)) - pwdb_all += 3; - if (pwdb_all > 100) - pwdb_all = 100; - } - } else { /* 8821 */ - char pout = -6; - - switch (lan_idx) { - case 5: - rx_pwr_all = pout - 32 - (2*vga_idx); - break; - case 4: - rx_pwr_all = pout - 24 - (2*vga_idx); - break; - case 2: - rx_pwr_all = pout - 11 - (2*vga_idx); - break; - case 1: - rx_pwr_all = pout + 5 - (2*vga_idx); - break; - case 0: - rx_pwr_all = pout + 21 - (2*vga_idx); - break; - } - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - } - - pstatus->rx_pwdb_all = pwdb_all; - pstatus->recvsignalpower = rx_pwr_all; - - /* (3) Get Signal Quality (EVM) */ - if (bpacket_match_bssid) { - u8 sq; - - if (pstatus->rx_pwdb_all > 40) { - sq = 100; - } else { - sq = p_phystrpt->pwdb_all; - if (sq > 64) - sq = 0; - else if (sq < 20) - sq = 100; - else - sq = ((64 - sq) * 100) / 44; - } - - pstatus->signalquality = sq; - pstatus->rx_mimo_signalquality[0] = sq; - pstatus->rx_mimo_signalquality[1] = -1; - } - } else { - /* (1)Get RSSI for HT rate */ - for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { - /* we will judge RF RX path now. */ - if (rtlpriv->dm.rfpath_rxenable[i]) - rf_rx_num++; - - rx_pwr[i] = (p_phystrpt->gain_trsw[i] & 0x7f) - 110; - - /* Translate DBM to percentage. */ - rssi = rtl_query_rxpwrpercentage(rx_pwr[i]); - total_rssi += rssi; - - /* Get Rx snr value in DB */ - pstatus->rx_snr[i] = p_phystrpt->rxsnr[i] / 2; - rtlpriv->stats.rx_snr_db[i] = p_phystrpt->rxsnr[i] / 2; - - pstatus->cfo_short[i] = odm_cfo(p_phystrpt->cfosho[i]); - pstatus->cfo_tail[i] = odm_cfo(p_phystrpt->cfotail[i]); - /* Record Signal Strength for next packet */ - pstatus->rx_mimo_signalstrength[i] = (u8)rssi; - } - - /* (2)PWDB, Average PWDB cacluated by - * hardware (for rate adaptive) - */ - rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; - - pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all); - pstatus->rx_pwdb_all = pwdb_all; - pstatus->rxpower = rx_pwr_all; - pstatus->recvsignalpower = rx_pwr_all; - - /* (3)EVM of HT rate */ - if ((pstatus->is_ht && pstatus->rate >= DESC_RATEMCS8 && - pstatus->rate <= DESC_RATEMCS15) || - (pstatus->is_vht && - pstatus->rate >= DESC_RATEVHT2SS_MCS0 && - pstatus->rate <= DESC_RATEVHT2SS_MCS9)) - max_spatial_stream = 2; - else - max_spatial_stream = 1; - - for (i = 0; i < max_spatial_stream; i++) { - evm = rtl_evm_db_to_percentage(p_phystrpt->rxevm[i]); - evmdbm = _rtl8821ae_evm_dbm_jaguar(p_phystrpt->rxevm[i]); - - if (bpacket_match_bssid) { - /* Fill value in RFD, Get the first - * spatial stream only - */ - if (i == 0) - pstatus->signalquality = evm; - pstatus->rx_mimo_signalquality[i] = evm; - pstatus->rx_mimo_evm_dbm[i] = evmdbm; - } - } - if (bpacket_match_bssid) { - for (i = RF90_PATH_A; i <= RF90_PATH_B; i++) - rtl_priv(hw)->dm.cfo_tail[i] = - (char)p_phystrpt->cfotail[i]; - - rtl_priv(hw)->dm.packet_count++; - } - } - - /* UI BSS List signal strength(in percentage), - * make it good looking, from 0~100. - */ - if (is_cck) - pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, - pwdb_all)); - else if (rf_rx_num != 0) - pstatus->signalstrength = (u8)(rtl_signal_scale_mapping(hw, - total_rssi /= rf_rx_num)); - /*HW antenna diversity*/ - rtldm->fat_table.antsel_rx_keep_0 = p_phystrpt->antidx_anta; - rtldm->fat_table.antsel_rx_keep_1 = p_phystrpt->antidx_antb; -} - -static void translate_rx_signal_stuff(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct rtl_stats *pstatus, u8 *pdesc, - struct rx_fwinfo_8821ae *p_drvinfo) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); - struct ieee80211_hdr *hdr; - u8 *tmp_buf; - u8 *praddr; - u8 *psaddr; - __le16 fc; - u16 type; - bool packet_matchbssid, packet_toself, packet_beacon; - - tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift; - - hdr = (struct ieee80211_hdr *)tmp_buf; - fc = hdr->frame_control; - type = WLAN_FC_GET_TYPE(hdr->frame_control); - praddr = hdr->addr1; - psaddr = ieee80211_get_SA(hdr); - ether_addr_copy(pstatus->psaddr, psaddr); - - packet_matchbssid = (!ieee80211_is_ctl(fc) && - (ether_addr_equal(mac->bssid, - ieee80211_has_tods(fc) ? - hdr->addr1 : - ieee80211_has_fromds(fc) ? - hdr->addr2 : hdr->addr3)) && - (!pstatus->hwerror) && - (!pstatus->crc) && (!pstatus->icv)); - - packet_toself = packet_matchbssid && - (ether_addr_equal(praddr, rtlefuse->dev_addr)); - - if (ieee80211_is_beacon(hdr->frame_control)) - packet_beacon = true; - else - packet_beacon = false; - - if (packet_beacon && packet_matchbssid) - rtl_priv(hw)->dm.dbginfo.num_qry_beacon_pkt++; - - if (packet_matchbssid && - ieee80211_is_data_qos(hdr->frame_control) && - !is_multicast_ether_addr(ieee80211_get_DA(hdr))) { - struct ieee80211_qos_hdr *hdr_qos = - (struct ieee80211_qos_hdr *)tmp_buf; - u16 tid = le16_to_cpu(hdr_qos->qos_ctrl) & 0xf; - - if (tid != 0 && tid != 3) - rtl_priv(hw)->dm.dbginfo.num_non_be_pkt++; - } - - query_rxphystatus(hw, pstatus, pdesc, p_drvinfo, - packet_matchbssid, packet_toself, - packet_beacon); - /*_rtl8821ae_smart_antenna(hw, pstatus); */ - rtl_process_phyinfo(hw, tmp_buf, pstatus); -} - -static void _rtl8821ae_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, - u8 *virtualaddress) -{ - u32 dwtmp = 0; - - memset(virtualaddress, 0, 8); - - SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); - if (ptcb_desc->empkt_num == 1) { - dwtmp = ptcb_desc->empkt_len[0]; - } else { - dwtmp = ptcb_desc->empkt_len[0]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0)+4; - dwtmp += ptcb_desc->empkt_len[1]; - } - SET_EARLYMODE_LEN0(virtualaddress, dwtmp); - - if (ptcb_desc->empkt_num <= 3) { - dwtmp = ptcb_desc->empkt_len[2]; - } else { - dwtmp = ptcb_desc->empkt_len[2]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0)+4; - dwtmp += ptcb_desc->empkt_len[3]; - } - SET_EARLYMODE_LEN1(virtualaddress, dwtmp); - if (ptcb_desc->empkt_num <= 5) { - dwtmp = ptcb_desc->empkt_len[4]; - } else { - dwtmp = ptcb_desc->empkt_len[4]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0)+4; - dwtmp += ptcb_desc->empkt_len[5]; - } - SET_EARLYMODE_LEN2_1(virtualaddress, dwtmp & 0xF); - SET_EARLYMODE_LEN2_2(virtualaddress, dwtmp >> 4); - if (ptcb_desc->empkt_num <= 7) { - dwtmp = ptcb_desc->empkt_len[6]; - } else { - dwtmp = ptcb_desc->empkt_len[6]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0)+4; - dwtmp += ptcb_desc->empkt_len[7]; - } - SET_EARLYMODE_LEN3(virtualaddress, dwtmp); - if (ptcb_desc->empkt_num <= 9) { - dwtmp = ptcb_desc->empkt_len[8]; - } else { - dwtmp = ptcb_desc->empkt_len[8]; - dwtmp += ((dwtmp % 4) ? (4 - dwtmp % 4) : 0)+4; - dwtmp += ptcb_desc->empkt_len[9]; - } - SET_EARLYMODE_LEN4(virtualaddress, dwtmp); -} - -static bool rtl8821ae_get_rxdesc_is_ht(struct ieee80211_hw *hw, u8 *pdesc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 rx_rate = 0; - - rx_rate = GET_RX_DESC_RXMCS(pdesc); - - RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, "rx_rate=0x%02x.\n", rx_rate); - - if ((rx_rate >= DESC_RATEMCS0) && (rx_rate <= DESC_RATEMCS15)) - return true; - return false; -} - -static bool rtl8821ae_get_rxdesc_is_vht(struct ieee80211_hw *hw, u8 *pdesc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 rx_rate = 0; - - rx_rate = GET_RX_DESC_RXMCS(pdesc); - - RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, "rx_rate=0x%02x.\n", rx_rate); - - if (rx_rate >= DESC_RATEVHT1SS_MCS0) - return true; - return false; -} - -static u8 rtl8821ae_get_rx_vht_nss(struct ieee80211_hw *hw, u8 *pdesc) -{ - u8 rx_rate = 0; - u8 vht_nss = 0; - - rx_rate = GET_RX_DESC_RXMCS(pdesc); - if ((rx_rate >= DESC_RATEVHT1SS_MCS0) && - (rx_rate <= DESC_RATEVHT1SS_MCS9)) - vht_nss = 1; - else if ((rx_rate >= DESC_RATEVHT2SS_MCS0) && - (rx_rate <= DESC_RATEVHT2SS_MCS9)) - vht_nss = 2; - - return vht_nss; -} - -bool rtl8821ae_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *status, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rx_fwinfo_8821ae *p_drvinfo; - struct ieee80211_hdr *hdr; - - u32 phystatus = GET_RX_DESC_PHYST(pdesc); - - status->length = (u16)GET_RX_DESC_PKT_LEN(pdesc); - status->rx_drvinfo_size = (u8)GET_RX_DESC_DRV_INFO_SIZE(pdesc) * - RX_DRV_INFO_SIZE_UNIT; - status->rx_bufshift = (u8)(GET_RX_DESC_SHIFT(pdesc) & 0x03); - status->icv = (u16)GET_RX_DESC_ICV(pdesc); - status->crc = (u16)GET_RX_DESC_CRC32(pdesc); - status->hwerror = (status->crc | status->icv); - status->decrypted = !GET_RX_DESC_SWDEC(pdesc); - status->rate = (u8)GET_RX_DESC_RXMCS(pdesc); - status->shortpreamble = (u16)GET_RX_DESC_SPLCP(pdesc); - status->isampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); - status->isfirst_ampdu = (bool)(GET_RX_DESC_PAGGR(pdesc) == 1); - status->timestamp_low = GET_RX_DESC_TSFL(pdesc); - status->rx_packet_bw = GET_RX_DESC_BW(pdesc); - status->macid = GET_RX_DESC_MACID(pdesc); - status->is_short_gi = !(bool)GET_RX_DESC_SPLCP(pdesc); - status->is_ht = rtl8821ae_get_rxdesc_is_ht(hw, pdesc); - status->is_vht = rtl8821ae_get_rxdesc_is_vht(hw, pdesc); - status->vht_nss = rtl8821ae_get_rx_vht_nss(hw, pdesc); - status->is_cck = RTL8821AE_RX_HAL_IS_CCK_RATE(status->rate); - - RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, - "rx_packet_bw=%s,is_ht %d, is_vht %d, vht_nss=%d,is_short_gi %d.\n", - (status->rx_packet_bw == 2) ? "80M" : - (status->rx_packet_bw == 1) ? "40M" : "20M", - status->is_ht, status->is_vht, status->vht_nss, - status->is_short_gi); - - if (GET_RX_STATUS_DESC_RPT_SEL(pdesc)) - status->packet_report_type = C2H_PACKET; - else - status->packet_report_type = NORMAL_RX; - - if (GET_RX_STATUS_DESC_PATTERN_MATCH(pdesc)) - status->wake_match = BIT(2); - else if (GET_RX_STATUS_DESC_MAGIC_MATCH(pdesc)) - status->wake_match = BIT(1); - else if (GET_RX_STATUS_DESC_UNICAST_MATCH(pdesc)) - status->wake_match = BIT(0); - else - status->wake_match = 0; - - if (status->wake_match) - RT_TRACE(rtlpriv, COMP_RXDESC, DBG_LOUD, - "GGGGGGGGGGGGGet Wakeup Packet!! WakeMatch=%d\n", - status->wake_match); - rx_status->freq = hw->conf.chandef.chan->center_freq; - rx_status->band = hw->conf.chandef.chan->band; - - hdr = (struct ieee80211_hdr *)(skb->data + - status->rx_drvinfo_size + status->rx_bufshift); - - if (status->crc) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - - if (status->rx_packet_bw == HT_CHANNEL_WIDTH_20_40) - rx_status->flag |= RX_FLAG_40MHZ; - else if (status->rx_packet_bw == HT_CHANNEL_WIDTH_80) - rx_status->vht_flag |= RX_VHT_FLAG_80MHZ; - if (status->is_ht) - rx_status->flag |= RX_FLAG_HT; - if (status->is_vht) - rx_status->flag |= RX_FLAG_VHT; - - if (status->is_short_gi) - rx_status->flag |= RX_FLAG_SHORT_GI; - - rx_status->vht_nss = status->vht_nss; - rx_status->flag |= RX_FLAG_MACTIME_START; - - /* hw will set status->decrypted true, if it finds the - * frame is open data frame or mgmt frame. - * So hw will not decryption robust managment frame - * for IEEE80211w but still set status->decrypted - * true, so here we should set it back to undecrypted - * for IEEE80211w frame, and mac80211 sw will help - * to decrypt it - */ - if (status->decrypted) { - if ((!_ieee80211_is_robust_mgmt_frame(hdr)) && - (ieee80211_has_protected(hdr->frame_control))) - rx_status->flag |= RX_FLAG_DECRYPTED; - else - rx_status->flag &= ~RX_FLAG_DECRYPTED; - } - - /* rate_idx: index of data rate into band's - * supported rates or MCS index if HT rates - * are use (RX_FLAG_HT) - */ - rx_status->rate_idx = rtlwifi_rate_mapping(hw, status->is_ht, - status->is_vht, - status->rate); - - rx_status->mactime = status->timestamp_low; - if (phystatus) { - p_drvinfo = (struct rx_fwinfo_8821ae *)(skb->data + - status->rx_bufshift); - - translate_rx_signal_stuff(hw, skb, status, pdesc, p_drvinfo); - } - rx_status->signal = status->recvsignalpower + 10; - if (status->packet_report_type == TX_REPORT2) { - status->macid_valid_entry[0] = - GET_RX_RPT2_DESC_MACID_VALID_1(pdesc); - status->macid_valid_entry[1] = - GET_RX_RPT2_DESC_MACID_VALID_2(pdesc); - } - return true; -} - -static u8 rtl8821ae_bw_mapping(struct ieee80211_hw *hw, - struct rtl_tcb_desc *ptcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - u8 bw_setting_of_desc = 0; - - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "rtl8821ae_bw_mapping, current_chan_bw %d, packet_bw %d\n", - rtlphy->current_chan_bw, ptcb_desc->packet_bw); - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) { - if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_80) - bw_setting_of_desc = 2; - else if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) - bw_setting_of_desc = 1; - else - bw_setting_of_desc = 0; - } else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - if ((ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) || - (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_80)) - bw_setting_of_desc = 1; - else - bw_setting_of_desc = 0; - } else { - bw_setting_of_desc = 0; - } - return bw_setting_of_desc; -} - -static u8 rtl8821ae_sc_mapping(struct ieee80211_hw *hw, - struct rtl_tcb_desc *ptcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &rtlpriv->phy; - struct rtl_mac *mac = rtl_mac(rtlpriv); - u8 sc_setting_of_desc = 0; - - if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_80) { - if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_80) { - sc_setting_of_desc = VHT_DATA_SC_DONOT_CARE; - } else if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { - if (mac->cur_80_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER) - sc_setting_of_desc = - VHT_DATA_SC_40_LOWER_OF_80MHZ; - else if (mac->cur_80_prime_sc == - HAL_PRIME_CHNL_OFFSET_UPPER) - sc_setting_of_desc = - VHT_DATA_SC_40_UPPER_OF_80MHZ; - else - RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD, - "rtl8821ae_sc_mapping: Not Correct Primary40MHz Setting\n"); - } else { - if ((mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER) && - (mac->cur_80_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER)) - sc_setting_of_desc = - VHT_DATA_SC_20_LOWEST_OF_80MHZ; - else if ((mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_UPPER) && - (mac->cur_80_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER)) - sc_setting_of_desc = - VHT_DATA_SC_20_LOWER_OF_80MHZ; - else if ((mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER) && - (mac->cur_80_prime_sc == - HAL_PRIME_CHNL_OFFSET_UPPER)) - sc_setting_of_desc = - VHT_DATA_SC_20_UPPER_OF_80MHZ; - else if ((mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_UPPER) && - (mac->cur_80_prime_sc == - HAL_PRIME_CHNL_OFFSET_UPPER)) - sc_setting_of_desc = - VHT_DATA_SC_20_UPPERST_OF_80MHZ; - else - RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD, - "rtl8821ae_sc_mapping: Not Correct Primary40MHz Setting\n"); - } - } else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { - if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20_40) { - sc_setting_of_desc = VHT_DATA_SC_DONOT_CARE; - } else if (ptcb_desc->packet_bw == HT_CHANNEL_WIDTH_20) { - if (mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_UPPER) { - sc_setting_of_desc = - VHT_DATA_SC_20_UPPER_OF_80MHZ; - } else if (mac->cur_40_prime_sc == - HAL_PRIME_CHNL_OFFSET_LOWER){ - sc_setting_of_desc = - VHT_DATA_SC_20_LOWER_OF_80MHZ; - } else { - sc_setting_of_desc = VHT_DATA_SC_DONOT_CARE; - } - } - } else { - sc_setting_of_desc = VHT_DATA_SC_DONOT_CARE; - } - - return sc_setting_of_desc; -} - -void rtl8821ae_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, u8 *txbd, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - u8 *pdesc = (u8 *)pdesc_tx; - u16 seq_number; - __le16 fc = hdr->frame_control; - unsigned int buf_len = 0; - unsigned int skb_len = skb->len; - u8 fw_qsel = _rtl8821ae_map_hwqueue_to_fwqueue(skb, hw_queue); - bool firstseg = ((hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); - bool lastseg = ((hdr->frame_control & - cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); - dma_addr_t mapping; - u8 short_gi = 0; - - seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); - /* reserve 8 byte for AMPDU early mode */ - if (rtlhal->earlymode_enable) { - skb_push(skb, EM_HDR_LEN); - memset(skb->data, 0, EM_HDR_LEN); - } - buf_len = skb->len; - mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_8821ae)); - if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { - firstseg = true; - lastseg = true; - } - if (firstseg) { - if (rtlhal->earlymode_enable) { - SET_TX_DESC_PKT_OFFSET(pdesc, 1); - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + - EM_HDR_LEN); - if (ptcb_desc->empkt_num) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "Insert 8 byte.pTcb->EMPktNum:%d\n", - ptcb_desc->empkt_num); - _rtl8821ae_insert_emcontent(ptcb_desc, - (u8 *)(skb->data)); - } - } else { - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - } - - /* ptcb_desc->use_driver_rate = true; */ - SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); - if (ptcb_desc->hw_rate > DESC_RATEMCS0) - short_gi = (ptcb_desc->use_shortgi) ? 1 : 0; - else - short_gi = (ptcb_desc->use_shortpreamble) ? 1 : 0; - - SET_TX_DESC_DATA_SHORTGI(pdesc, short_gi); - - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - SET_TX_DESC_AGG_ENABLE(pdesc, 1); - SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x1f); - } - SET_TX_DESC_SEQ(pdesc, seq_number); - SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && - !ptcb_desc->cts_enable) ? 1 : 0)); - SET_TX_DESC_HW_RTS_ENABLE(pdesc, 0); - SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); - - SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); - SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); - SET_TX_DESC_RTS_SHORT(pdesc, - ((ptcb_desc->rts_rate <= DESC_RATE54M) ? - (ptcb_desc->rts_use_shortpreamble ? 1 : 0) : - (ptcb_desc->rts_use_shortgi ? 1 : 0))); - - if (ptcb_desc->tx_enable_sw_calc_duration) - SET_TX_DESC_NAV_USE_HDR(pdesc, 1); - - SET_TX_DESC_DATA_BW(pdesc, - rtl8821ae_bw_mapping(hw, ptcb_desc)); - - SET_TX_DESC_TX_SUB_CARRIER(pdesc, - rtl8821ae_sc_mapping(hw, ptcb_desc)); - - SET_TX_DESC_LINIP(pdesc, 0); - SET_TX_DESC_PKT_SIZE(pdesc, (u16)skb_len); - if (sta) { - u8 ampdu_density = sta->ht_cap.ampdu_density; - - SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); - } - if (info->control.hw_key) { - struct ieee80211_key_conf *keyconf = - info->control.hw_key; - switch (keyconf->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - case WLAN_CIPHER_SUITE_TKIP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x1); - break; - case WLAN_CIPHER_SUITE_CCMP: - SET_TX_DESC_SEC_TYPE(pdesc, 0x3); - break; - default: - SET_TX_DESC_SEC_TYPE(pdesc, 0x0); - break; - } - } - - SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); - SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); - SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); - SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ? - 1 : 0); - SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); - - if (ieee80211_is_data_qos(fc)) { - if (mac->rdg_en) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "Enable RDG function.\n"); - SET_TX_DESC_RDG_ENABLE(pdesc, 1); - SET_TX_DESC_HTC(pdesc, 1); - } - } - } - - SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); - SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)buf_len); - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - /* if (rtlpriv->dm.useramask) { */ - if (1) { - SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); - } else { - SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); - SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); - } - if (!ieee80211_is_data_qos(fc)) { - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - SET_TX_DESC_HWSEQ_SEL(pdesc, 0); - } - SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); - if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || - is_broadcast_ether_addr(ieee80211_get_DA(hdr))) { - SET_TX_DESC_BMC(pdesc, 1); - } - - rtl8821ae_dm_set_tx_ant_by_tx_info(hw, pdesc, ptcb_desc->mac_id); - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n"); -} - -void rtl8821ae_tx_fill_cmddesc(struct ieee80211_hw *hw, - u8 *pdesc, bool firstseg, - bool lastseg, struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - u8 fw_queue = QSLT_BEACON; - - dma_addr_t mapping = pci_map_single(rtlpci->pdev, - skb->data, skb->len, - PCI_DMA_TODEVICE); - - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); - - SET_TX_DESC_FIRST_SEG(pdesc, 1); - SET_TX_DESC_LAST_SEG(pdesc, 1); - - SET_TX_DESC_PKT_SIZE((u8 *)pdesc, (u16)(skb->len)); - - SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); - - SET_TX_DESC_USE_RATE(pdesc, 1); - SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M); - SET_TX_DESC_DISABLE_FB(pdesc, 1); - - SET_TX_DESC_DATA_BW(pdesc, 0); - - SET_TX_DESC_HWSEQ_EN(pdesc, 1); - - SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); - - SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); - - SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); - - SET_TX_DESC_MACID(pdesc, 0); - - SET_TX_DESC_OWN(pdesc, 1); - - RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, - "H2C Tx Cmd Content\n", - pdesc, TX_DESC_SIZE); -} - -void rtl8821ae_set_desc(struct ieee80211_hw *hw, u8 *pdesc, - bool istx, u8 desc_name, u8 *val) -{ - if (istx) { - switch (desc_name) { - case HW_DESC_OWN: - SET_TX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_TX_NEXTDESC_ADDR: - SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *)val); - break; - default: - RT_ASSERT(false, - "ERR txdesc :%d not process\n", desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_RXOWN: - SET_RX_DESC_OWN(pdesc, 1); - break; - case HW_DESC_RXBUFF_ADDR: - SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *)val); - break; - case HW_DESC_RXPKT_LEN: - SET_RX_DESC_PKT_LEN(pdesc, *(u32 *)val); - break; - case HW_DESC_RXERO: - SET_RX_DESC_EOR(pdesc, 1); - break; - default: - RT_ASSERT(false, - "ERR rxdesc :%d not process\n", desc_name); - break; - } - } -} - -u32 rtl8821ae_get_desc(u8 *pdesc, bool istx, u8 desc_name) -{ - u32 ret = 0; - - if (istx) { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_TX_DESC_OWN(pdesc); - break; - case HW_DESC_TXBUFF_ADDR: - ret = GET_TX_DESC_TX_BUFFER_ADDRESS(pdesc); - break; - default: - RT_ASSERT(false, - "ERR txdesc :%d not process\n", desc_name); - break; - } - } else { - switch (desc_name) { - case HW_DESC_OWN: - ret = GET_RX_DESC_OWN(pdesc); - break; - case HW_DESC_RXPKT_LEN: - ret = GET_RX_DESC_PKT_LEN(pdesc); - break; - case HW_DESC_RXBUFF_ADDR: - ret = GET_RX_DESC_BUFF_ADDR(pdesc); - break; - default: - RT_ASSERT(false, - "ERR rxdesc :%d not process\n", desc_name); - break; - } - } - return ret; -} - -bool rtl8821ae_is_tx_desc_closed(struct ieee80211_hw *hw, - u8 hw_queue, u16 index) -{ - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; - u8 *entry = (u8 *)(&ring->desc[ring->idx]); - u8 own = (u8)rtl8821ae_get_desc(entry, true, HW_DESC_OWN); - - /** - *beacon packet will only use the first - *descriptor defautly,and the own may not - *be cleared by the hardware - */ - if (own) - return false; - return true; -} - -void rtl8821ae_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - if (hw_queue == BEACON_QUEUE) { - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); - } else { - rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, - BIT(0) << (hw_queue)); - } -} - -u32 rtl8821ae_rx_command_packet(struct ieee80211_hw *hw, - struct rtl_stats status, - struct sk_buff *skb) -{ - u32 result = 0; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - switch (status.packet_report_type) { - case NORMAL_RX: - result = 0; - break; - case C2H_PACKET: - rtl8821ae_c2h_packet_handler(hw, skb->data, (u8)skb->len); - result = 1; - RT_TRACE(rtlpriv, COMP_RECV, DBG_LOUD, - "skb->len=%d\n\n", skb->len); - break; - default: - RT_TRACE(rtlpriv, COMP_RECV, DBG_LOUD, - "No this packet type!!\n"); - break; - } - - return result; -} diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.h b/drivers/net/wireless/rtlwifi/rtl8821ae/trx.h deleted file mode 100644 index 31409042d8dd..000000000000 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/trx.h +++ /dev/null @@ -1,620 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2010 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL8821AE_TRX_H__ -#define __RTL8821AE_TRX_H__ - -#define TX_DESC_SIZE 40 -#define TX_DESC_AGGR_SUBFRAME_SIZE 32 - -#define RX_DESC_SIZE 32 -#define RX_DRV_INFO_SIZE_UNIT 8 - -#define TX_DESC_NEXT_DESC_OFFSET 40 -#define USB_HWDESC_HEADER_LEN 40 -#define CRCLENGTH 4 - -#define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val) -#define SET_TX_DESC_OFFSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val) -#define SET_TX_DESC_BMC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val) -#define SET_TX_DESC_HTC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val) -#define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val) -#define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val) -#define SET_TX_DESC_LINIP(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val) -#define SET_TX_DESC_NO_ACM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val) -#define SET_TX_DESC_GF(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) -#define SET_TX_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) - -#define GET_TX_DESC_PKT_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 0, 16) -#define GET_TX_DESC_OFFSET(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 16, 8) -#define GET_TX_DESC_BMC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 24, 1) -#define GET_TX_DESC_HTC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 25, 1) -#define GET_TX_DESC_LAST_SEG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 26, 1) -#define GET_TX_DESC_FIRST_SEG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 27, 1) -#define GET_TX_DESC_LINIP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 28, 1) -#define GET_TX_DESC_NO_ACM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 29, 1) -#define GET_TX_DESC_GF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 30, 1) -#define GET_TX_DESC_OWN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 31, 1) - -#define SET_TX_DESC_MACID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 7, __val) -#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val) -#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val) -#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val) -#define SET_TX_DESC_PIFS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val) -#define SET_TX_DESC_RATE_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 5, __val) -#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val) -#define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val) -#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 5, __val) - -#define SET_TX_DESC_PAID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 9, __val) -#define SET_TX_DESC_CCA_RTS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 10, 2, __val) -#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 12, 1, __val) -#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 13, 1, __val) -#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val) -#define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 16, 1, __val) -#define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val) -#define SET_TX_DESC_RAW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val) -#define SET_TX_DESC_SPE_RPT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val) -#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val) -#define SET_TX_DESC_BT_INT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 23, 1, __val) -#define SET_TX_DESC_GID(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 6, __val) - -#define SET_TX_DESC_WHEADER_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 4, __val) -#define SET_TX_DESC_CHK_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 4, 1, __val) -#define SET_TX_DESC_EARLY_MODE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 5, 1, __val) -#define SET_TX_DESC_HWSEQ_SEL(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 6, 2, __val) -#define SET_TX_DESC_USE_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 1, __val) -#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 9, 1, __val) -#define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 10, 1, __val) -#define SET_TX_DESC_CTS2SELF(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 11, 1, __val) -#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 12, 1, __val) -#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 13, 1, __val) -#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 15, 1, __val) -#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 1, __val) -#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 17, 5, __val) -#define SET_TX_DESC_NDPA(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 22, 2, __val) -#define SET_TX_DESC_AMPDU_MAX_TIME(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+12, 24, 8, __val) -#define SET_TX_DESC_TX_ANT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 4, __val) - -#define SET_TX_DESC_TX_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 7, __val) -#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 5, __val) -#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 4, __val) -#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 17, 1, __val) -#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 6, __val) -#define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 5, __val) - -#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 4, __val) -#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val) \ - SET_BITS_TO_LE_1BYTE(__pdesc+20, 4, 1, __val) -#define SET_TX_DESC_DATA_BW(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 5, 2, __val) -#define SET_TX_DESC_DATA_LDPC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val) -#define SET_TX_DESC_DATA_STBC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 2, __val) -#define SET_TX_DESC_CTROL_STBC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 10, 2, __val) -#define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 12, 1, __val) -#define SET_TX_DESC_RTS_SC(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val) - -#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val) - -#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 0, 16) - -#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+32, 15, 1, __val) - -#define SET_TX_DESC_SEQ(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+36, 12, 12, __val) - -#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val) - -#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+40, 0, 32) - -#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+48, 0, 32, __val) - -#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+48, 0, 32) - -#define GET_RX_DESC_PKT_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 0, 14) -#define GET_RX_DESC_CRC32(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 14, 1) -#define GET_RX_DESC_ICV(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 15, 1) -#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 16, 4) -#define GET_RX_DESC_SECURITY(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 20, 3) -#define GET_RX_DESC_QOS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 23, 1) -#define GET_RX_DESC_SHIFT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 24, 2) -#define GET_RX_DESC_PHYST(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 26, 1) -#define GET_RX_DESC_SWDEC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 27, 1) -#define GET_RX_DESC_LS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 28, 1) -#define GET_RX_DESC_FS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 29, 1) -#define GET_RX_DESC_EOR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 30, 1) -#define GET_RX_DESC_OWN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc, 31, 1) - -#define SET_RX_DESC_PKT_LEN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val) -#define SET_RX_DESC_EOR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val) -#define SET_RX_DESC_OWN(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val) - -#define GET_RX_DESC_MACID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 0, 7) -#define GET_RX_DESC_TID(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 8, 4) -#define GET_RX_DESC_AMSDU(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 13, 1) -#define GET_RX_STATUS_DESC_RXID_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 14, 1) -#define GET_RX_DESC_PAGGR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 15, 1) -#define GET_RX_DESC_A1_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 16, 4) -#define GET_RX_DESC_CHKERR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 20, 1) -#define GET_RX_DESC_IPVER(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 21, 1) -#define GET_RX_STATUS_DESC_IS_TCPUDP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 22, 1) -#define GET_RX_STATUS_DESC_CHK_VLD(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 23, 1) -#define GET_RX_DESC_PAM(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 24, 1) -#define GET_RX_DESC_PWR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 25, 1) -#define GET_RX_DESC_MD(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 26, 1) -#define GET_RX_DESC_MF(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 27, 1) -#define GET_RX_DESC_TYPE(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 28, 2) -#define GET_RX_DESC_MC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 30, 1) -#define GET_RX_DESC_BC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+4, 31, 1) - -#define GET_RX_DESC_SEQ(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 0, 12) -#define GET_RX_DESC_FRAG(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 12, 4) -#define GET_RX_STATUS_DESC_RX_IS_QOS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 16, 1) -#define GET_RX_STATUS_DESC_WLANHD_IV_LEN(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 18, 6) -#define GET_RX_STATUS_DESC_RPT_SEL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+8, 28, 1) - -#define GET_RX_DESC_RXMCS(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 0, 7) -#define GET_RX_DESC_HTC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 10, 1) -#define GET_RX_STATUS_DESC_EOSP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 11, 1) -#define GET_RX_STATUS_DESC_BSSID_FIT(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 12, 2) - -#define GET_RX_STATUS_DESC_PATTERN_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 29, 1) -#define GET_RX_STATUS_DESC_UNICAST_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 30, 1) -#define GET_RX_STATUS_DESC_MAGIC_MATCH(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+12, 31, 1) - -#define GET_RX_DESC_SPLCP(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 0, 1) -#define GET_RX_STATUS_DESC_LDPC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 1, 1) -#define GET_RX_STATUS_DESC_STBC(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 2, 1) -#define GET_RX_DESC_BW(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+16, 4, 2) - -#define GET_RX_DESC_TSFL(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+20, 0, 32) - -#define GET_RX_DESC_BUFF_ADDR(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+24, 0, 32) -#define GET_RX_DESC_BUFF_ADDR64(__pdesc) \ - LE_BITS_TO_4BYTE(__pdesc+28, 0, 32) - -#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val) -#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) \ - SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val) - -/* TX report 2 format in Rx desc*/ - -#define GET_RX_RPT2_DESC_PKT_LEN(__status) \ - LE_BITS_TO_4BYTE(__status, 0, 9) -#define GET_RX_RPT2_DESC_MACID_VALID_1(__status) \ - LE_BITS_TO_4BYTE(__status+16, 0, 32) -#define GET_RX_RPT2_DESC_MACID_VALID_2(__status) \ - LE_BITS_TO_4BYTE(__status+20, 0, 32) - -#define SET_EARLYMODE_PKTNUM(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 0, 4, __value) -#define SET_EARLYMODE_LEN0(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 4, 12, __value) -#define SET_EARLYMODE_LEN1(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 16, 12, __value) -#define SET_EARLYMODE_LEN2_1(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr, 28, 4, __value) -#define SET_EARLYMODE_LEN2_2(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 0, 8, __value) -#define SET_EARLYMODE_LEN3(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 8, 12, __value) -#define SET_EARLYMODE_LEN4(__paddr, __value) \ - SET_BITS_TO_LE_4BYTE(__paddr+4, 20, 12, __value) - -#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ -do { \ - if (_size > TX_DESC_NEXT_DESC_OFFSET) \ - memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ - else \ - memset(__pdesc, 0, _size); \ -} while (0) - -#define RTL8821AE_RX_HAL_IS_CCK_RATE(rxmcs)\ - (rxmcs == DESC_RATE1M ||\ - rxmcs == DESC_RATE2M ||\ - rxmcs == DESC_RATE5_5M ||\ - rxmcs == DESC_RATE11M) - -struct phy_rx_agc_info_t { - #ifdef __LITTLE_ENDIAN - u8 gain:7, trsw:1; - #else - u8 trsw:1, gain:7; - #endif -}; - -struct phy_status_rpt { - /* DWORD 0 */ - u8 gain_trsw[2]; -#ifdef __LITTLE_ENDIAN - u16 chl_num:10; - u16 sub_chnl:4; - u16 r_rfmod:2; -#else /* _BIG_ENDIAN_ */ - u16 r_rfmod:2; - u16 sub_chnl:4; - u16 chl_num:10; -#endif - /* DWORD 1 */ - u8 pwdb_all; - u8 cfosho[4]; /* DW 1 byte 1 DW 2 byte 0 */ - - /* DWORD 2 */ - char cfotail[4]; /* DW 2 byte 1 DW 3 byte 0 */ - - /* DWORD 3 */ - char rxevm[2]; /* DW 3 byte 1 DW 3 byte 2 */ - char rxsnr[2]; /* DW 3 byte 3 DW 4 byte 0 */ - - /* DWORD 4 */ - u8 pcts_msk_rpt[2]; - u8 pdsnr[2]; /* DW 4 byte 3 DW 5 Byte 0 */ - - /* DWORD 5 */ - u8 csi_current[2]; - u8 rx_gain_c; - - /* DWORD 6 */ - u8 rx_gain_d; - u8 sigevm; - u8 resvd_0; - u8 antidx_anta:3; - u8 antidx_antb:3; - u8 resvd_1:2; -} __packed; - -struct rx_fwinfo_8821ae { - u8 gain_trsw[4]; - u8 pwdb_all; - u8 cfosho[4]; - u8 cfotail[4]; - char rxevm[2]; - char rxsnr[4]; - u8 pdsnr[2]; - u8 csi_current[2]; - u8 csi_target[2]; - u8 sigevm; - u8 max_ex_pwr; - u8 ex_intf_flag:1; - u8 sgi_en:1; - u8 rxsc:2; - u8 reserve:4; -} __packed; - -struct tx_desc_8821ae { - u32 pktsize:16; - u32 offset:8; - u32 bmc:1; - u32 htc:1; - u32 lastseg:1; - u32 firstseg:1; - u32 linip:1; - u32 noacm:1; - u32 gf:1; - u32 own:1; - - u32 macid:6; - u32 rsvd0:2; - u32 queuesel:5; - u32 rd_nav_ext:1; - u32 lsig_txop_en:1; - u32 pifs:1; - u32 rateid:4; - u32 nav_usehdr:1; - u32 en_descid:1; - u32 sectype:2; - u32 pktoffset:8; - - u32 rts_rc:6; - u32 data_rc:6; - u32 agg_en:1; - u32 rdg_en:1; - u32 bar_retryht:2; - u32 agg_break:1; - u32 morefrag:1; - u32 raw:1; - u32 ccx:1; - u32 ampdudensity:3; - u32 bt_int:1; - u32 ant_sela:1; - u32 ant_selb:1; - u32 txant_cck:2; - u32 txant_l:2; - u32 txant_ht:2; - - u32 nextheadpage:8; - u32 tailpage:8; - u32 seq:12; - u32 cpu_handle:1; - u32 tag1:1; - u32 trigger_int:1; - u32 hwseq_en:1; - - u32 rtsrate:5; - u32 apdcfe:1; - u32 qos:1; - u32 hwseq_ssn:1; - u32 userrate:1; - u32 dis_rtsfb:1; - u32 dis_datafb:1; - u32 cts2self:1; - u32 rts_en:1; - u32 hwrts_en:1; - u32 portid:1; - u32 pwr_status:3; - u32 waitdcts:1; - u32 cts2ap_en:1; - u32 txsc:2; - u32 stbc:2; - u32 txshort:1; - u32 txbw:1; - u32 rtsshort:1; - u32 rtsbw:1; - u32 rtssc:2; - u32 rtsstbc:2; - - u32 txrate:6; - u32 shortgi:1; - u32 ccxt:1; - u32 txrate_fb_lmt:5; - u32 rtsrate_fb_lmt:4; - u32 retrylmt_en:1; - u32 txretrylmt:6; - u32 usb_txaggnum:8; - - u32 txagca:5; - u32 txagcb:5; - u32 usemaxlen:1; - u32 maxaggnum:5; - u32 mcsg1maxlen:4; - u32 mcsg2maxlen:4; - u32 mcsg3maxlen:4; - u32 mcs7sgimaxlen:4; - - u32 txbuffersize:16; - u32 sw_offset30:8; - u32 sw_offset31:4; - u32 rsvd1:1; - u32 antsel_c:1; - u32 null_0:1; - u32 null_1:1; - - u32 txbuffaddr; - u32 txbufferaddr64; - u32 nextdescaddress; - u32 nextdescaddress64; - - u32 reserve_pass_pcie_mm_limit[4]; -} __packed; - -struct rx_desc_8821ae { - u32 length:14; - u32 crc32:1; - u32 icverror:1; - u32 drv_infosize:4; - u32 security:3; - u32 qos:1; - u32 shift:2; - u32 phystatus:1; - u32 swdec:1; - u32 lastseg:1; - u32 firstseg:1; - u32 eor:1; - u32 own:1; - - u32 macid:6; - u32 tid:4; - u32 hwrsvd:5; - u32 paggr:1; - u32 faggr:1; - u32 a1_fit:4; - u32 a2_fit:4; - u32 pam:1; - u32 pwr:1; - u32 moredata:1; - u32 morefrag:1; - u32 type:2; - u32 mc:1; - u32 bc:1; - - u32 seq:12; - u32 frag:4; - u32 nextpktlen:14; - u32 nextind:1; - u32 rsvd:1; - - u32 rxmcs:6; - u32 rxht:1; - u32 amsdu:1; - u32 splcp:1; - u32 bandwidth:1; - u32 htc:1; - u32 tcpchk_rpt:1; - u32 ipcchk_rpt:1; - u32 tcpchk_valid:1; - u32 hwpcerr:1; - u32 hwpcind:1; - u32 iv0:16; - - u32 iv1; - - u32 tsfl; - - u32 bufferaddress; - u32 bufferaddress64; - -} __packed; - -void rtl8821ae_tx_fill_desc(struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, u8 *txbd, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); -bool rtl8821ae_rx_query_desc(struct ieee80211_hw *hw, - struct rtl_stats *status, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb); -void rtl8821ae_set_desc(struct ieee80211_hw *hw, u8 *pdesc, - bool istx, u8 desc_name, u8 *val); -u32 rtl8821ae_get_desc(u8 *pdesc, bool istx, u8 desc_name); -bool rtl8821ae_is_tx_desc_closed(struct ieee80211_hw *hw, - u8 hw_queue, u16 index); -void rtl8821ae_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); -void rtl8821ae_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, - struct sk_buff *skb); -u32 rtl8821ae_rx_command_packet(struct ieee80211_hw *hw, - struct rtl_stats status, - struct sk_buff *skb); -#endif diff --git a/drivers/net/wireless/rtlwifi/stats.c b/drivers/net/wireless/rtlwifi/stats.c deleted file mode 100644 index d8b30690b00d..000000000000 --- a/drivers/net/wireless/rtlwifi/stats.c +++ /dev/null @@ -1,268 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ -#include "wifi.h" -#include "stats.h" -#include - -u8 rtl_query_rxpwrpercentage(char antpower) -{ - if ((antpower <= -100) || (antpower >= 20)) - return 0; - else if (antpower >= 0) - return 100; - else - return 100 + antpower; -} -EXPORT_SYMBOL(rtl_query_rxpwrpercentage); - -u8 rtl_evm_db_to_percentage(char value) -{ - char ret_val = clamp(-value, 0, 33) * 3; - - if (ret_val == 99) - ret_val = 100; - - return ret_val; -} -EXPORT_SYMBOL(rtl_evm_db_to_percentage); - -static long rtl_translate_todbm(struct ieee80211_hw *hw, - u8 signal_strength_index) -{ - long signal_power; - - signal_power = (long)((signal_strength_index + 1) >> 1); - signal_power -= 95; - return signal_power; -} - -long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig) -{ - long retsig; - - if (currsig >= 61 && currsig <= 100) - retsig = 90 + ((currsig - 60) / 4); - else if (currsig >= 41 && currsig <= 60) - retsig = 78 + ((currsig - 40) / 2); - else if (currsig >= 31 && currsig <= 40) - retsig = 66 + (currsig - 30); - else if (currsig >= 21 && currsig <= 30) - retsig = 54 + (currsig - 20); - else if (currsig >= 5 && currsig <= 20) - retsig = 42 + (((currsig - 5) * 2) / 3); - else if (currsig == 4) - retsig = 36; - else if (currsig == 3) - retsig = 27; - else if (currsig == 2) - retsig = 18; - else if (currsig == 1) - retsig = 9; - else - retsig = currsig; - - return retsig; -} -EXPORT_SYMBOL(rtl_signal_scale_mapping); - -static void rtl_process_ui_rssi(struct ieee80211_hw *hw, - struct rtl_stats *pstatus) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u8 rfpath; - u32 last_rssi, tmpval; - - if (!pstatus->packet_toself && !pstatus->packet_beacon) - return; - - rtlpriv->stats.pwdb_all_cnt += pstatus->rx_pwdb_all; - rtlpriv->stats.rssi_calculate_cnt++; - - if (rtlpriv->stats.ui_rssi.total_num++ >= PHY_RSSI_SLID_WIN_MAX) { - rtlpriv->stats.ui_rssi.total_num = PHY_RSSI_SLID_WIN_MAX; - last_rssi = rtlpriv->stats.ui_rssi.elements[ - rtlpriv->stats.ui_rssi.index]; - rtlpriv->stats.ui_rssi.total_val -= last_rssi; - } - rtlpriv->stats.ui_rssi.total_val += pstatus->signalstrength; - rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++] = - pstatus->signalstrength; - if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) - rtlpriv->stats.ui_rssi.index = 0; - tmpval = rtlpriv->stats.ui_rssi.total_val / - rtlpriv->stats.ui_rssi.total_num; - rtlpriv->stats.signal_strength = rtl_translate_todbm(hw, - (u8) tmpval); - pstatus->rssi = rtlpriv->stats.signal_strength; - - if (pstatus->is_cck) - return; - - for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; - rfpath++) { - if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { - rtlpriv->stats.rx_rssi_percentage[rfpath] = - pstatus->rx_mimo_signalstrength[rfpath]; - - } - if (pstatus->rx_mimo_signalstrength[rfpath] > - rtlpriv->stats.rx_rssi_percentage[rfpath]) { - rtlpriv->stats.rx_rssi_percentage[rfpath] = - ((rtlpriv->stats.rx_rssi_percentage[rfpath] * - (RX_SMOOTH_FACTOR - 1)) + - (pstatus->rx_mimo_signalstrength[rfpath])) / - (RX_SMOOTH_FACTOR); - rtlpriv->stats.rx_rssi_percentage[rfpath] = - rtlpriv->stats.rx_rssi_percentage[rfpath] + 1; - } else { - rtlpriv->stats.rx_rssi_percentage[rfpath] = - ((rtlpriv->stats.rx_rssi_percentage[rfpath] * - (RX_SMOOTH_FACTOR - 1)) + - (pstatus->rx_mimo_signalstrength[rfpath])) / - (RX_SMOOTH_FACTOR); - } - rtlpriv->stats.rx_snr_db[rfpath] = pstatus->rx_snr[rfpath]; - rtlpriv->stats.rx_evm_dbm[rfpath] = - pstatus->rx_mimo_evm_dbm[rfpath]; - rtlpriv->stats.rx_cfo_short[rfpath] = - pstatus->cfo_short[rfpath]; - rtlpriv->stats.rx_cfo_tail[rfpath] = pstatus->cfo_tail[rfpath]; - } -} - -static void rtl_update_rxsignalstatistics(struct ieee80211_hw *hw, - struct rtl_stats *pstatus) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - int weighting = 0; - - if (rtlpriv->stats.recv_signal_power == 0) - rtlpriv->stats.recv_signal_power = pstatus->recvsignalpower; - if (pstatus->recvsignalpower > rtlpriv->stats.recv_signal_power) - weighting = 5; - else if (pstatus->recvsignalpower < rtlpriv->stats.recv_signal_power) - weighting = (-5); - rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power * - 5 + pstatus->recvsignalpower + weighting) / 6; -} - -static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_sta_info *drv_priv = NULL; - struct ieee80211_sta *sta = NULL; - long undec_sm_pwdb; - - rcu_read_lock(); - if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) - sta = rtl_find_sta(hw, pstatus->psaddr); - - /* adhoc or ap mode */ - if (sta) { - drv_priv = (struct rtl_sta_info *) sta->drv_priv; - undec_sm_pwdb = drv_priv->rssi_stat.undec_sm_pwdb; - } else { - undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; - } - - if (undec_sm_pwdb < 0) - undec_sm_pwdb = pstatus->rx_pwdb_all; - if (pstatus->rx_pwdb_all > (u32) undec_sm_pwdb) { - undec_sm_pwdb = (((undec_sm_pwdb) * - (RX_SMOOTH_FACTOR - 1)) + - (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); - undec_sm_pwdb = undec_sm_pwdb + 1; - } else { - undec_sm_pwdb = (((undec_sm_pwdb) * - (RX_SMOOTH_FACTOR - 1)) + - (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); - } - - if (sta) { - drv_priv->rssi_stat.undec_sm_pwdb = undec_sm_pwdb; - } else { - rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; - } - rcu_read_unlock(); - - rtl_update_rxsignalstatistics(hw, pstatus); -} - -static void rtl_process_ui_link_quality(struct ieee80211_hw *hw, - struct rtl_stats *pstatus) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 last_evm, n_stream, tmpval; - - if (pstatus->signalquality == 0) - return; - - if (rtlpriv->stats.ui_link_quality.total_num++ >= - PHY_LINKQUALITY_SLID_WIN_MAX) { - rtlpriv->stats.ui_link_quality.total_num = - PHY_LINKQUALITY_SLID_WIN_MAX; - last_evm = rtlpriv->stats.ui_link_quality.elements[ - rtlpriv->stats.ui_link_quality.index]; - rtlpriv->stats.ui_link_quality.total_val -= last_evm; - } - rtlpriv->stats.ui_link_quality.total_val += pstatus->signalquality; - rtlpriv->stats.ui_link_quality.elements[ - rtlpriv->stats.ui_link_quality.index++] = - pstatus->signalquality; - if (rtlpriv->stats.ui_link_quality.index >= - PHY_LINKQUALITY_SLID_WIN_MAX) - rtlpriv->stats.ui_link_quality.index = 0; - tmpval = rtlpriv->stats.ui_link_quality.total_val / - rtlpriv->stats.ui_link_quality.total_num; - rtlpriv->stats.signal_quality = tmpval; - rtlpriv->stats.last_sigstrength_inpercent = tmpval; - for (n_stream = 0; n_stream < 2; n_stream++) { - if (pstatus->rx_mimo_sig_qual[n_stream] != -1) { - if (rtlpriv->stats.rx_evm_percentage[n_stream] == 0) { - rtlpriv->stats.rx_evm_percentage[n_stream] = - pstatus->rx_mimo_sig_qual[n_stream]; - } - rtlpriv->stats.rx_evm_percentage[n_stream] = - ((rtlpriv->stats.rx_evm_percentage[n_stream] - * (RX_SMOOTH_FACTOR - 1)) + - (pstatus->rx_mimo_sig_qual[n_stream] * 1)) / - (RX_SMOOTH_FACTOR); - } - } -} - -void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer, - struct rtl_stats *pstatus) -{ - - if (!pstatus->packet_matchbssid) - return; - - rtl_process_ui_rssi(hw, pstatus); - rtl_process_pwdb(hw, pstatus); - rtl_process_ui_link_quality(hw, pstatus); -} -EXPORT_SYMBOL(rtl_process_phyinfo); diff --git a/drivers/net/wireless/rtlwifi/stats.h b/drivers/net/wireless/rtlwifi/stats.h deleted file mode 100644 index 2b57dffef572..000000000000 --- a/drivers/net/wireless/rtlwifi/stats.h +++ /dev/null @@ -1,42 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL_STATS_H__ -#define __RTL_STATS_H__ - -#define PHY_RSSI_SLID_WIN_MAX 100 -#define PHY_LINKQUALITY_SLID_WIN_MAX 20 -#define PHY_BEACON_RSSI_SLID_WIN_MAX 10 - -/* Rx smooth factor */ -#define RX_SMOOTH_FACTOR 20 - -u8 rtl_query_rxpwrpercentage(char antpower); -u8 rtl_evm_db_to_percentage(char value); -long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig); -void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer, - struct rtl_stats *pstatus); - -#endif diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c deleted file mode 100644 index 2721cf89fb16..000000000000 --- a/drivers/net/wireless/rtlwifi/usb.c +++ /dev/null @@ -1,1188 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - *****************************************************************************/ - -#include "wifi.h" -#include "core.h" -#include "usb.h" -#include "base.h" -#include "ps.h" -#include "rtl8192c/fw_common.h" -#include -#include - -MODULE_AUTHOR("lizhaoming "); -MODULE_AUTHOR("Realtek WlanFAE "); -MODULE_AUTHOR("Larry Finger "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("USB basic driver for rtlwifi"); - -#define REALTEK_USB_VENQT_READ 0xC0 -#define REALTEK_USB_VENQT_WRITE 0x40 -#define REALTEK_USB_VENQT_CMD_REQ 0x05 -#define REALTEK_USB_VENQT_CMD_IDX 0x00 - -#define MAX_USBCTRL_VENDORREQ_TIMES 10 - -static void usbctrl_async_callback(struct urb *urb) -{ - if (urb) { - /* free dr */ - kfree(urb->setup_packet); - /* free databuf */ - kfree(urb->transfer_buffer); - } -} - -static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, - u16 value, u16 index, void *pdata, - u16 len) -{ - int rc; - unsigned int pipe; - u8 reqtype; - struct usb_ctrlrequest *dr; - struct urb *urb; - const u16 databuf_maxlen = REALTEK_USB_VENQT_MAX_BUF_SIZE; - u8 *databuf; - - if (WARN_ON_ONCE(len > databuf_maxlen)) - len = databuf_maxlen; - - pipe = usb_sndctrlpipe(udev, 0); /* write_out */ - reqtype = REALTEK_USB_VENQT_WRITE; - - dr = kzalloc(sizeof(*dr), GFP_ATOMIC); - if (!dr) - return -ENOMEM; - - databuf = kzalloc(databuf_maxlen, GFP_ATOMIC); - if (!databuf) { - kfree(dr); - return -ENOMEM; - } - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - kfree(databuf); - kfree(dr); - return -ENOMEM; - } - - dr->bRequestType = reqtype; - dr->bRequest = request; - dr->wValue = cpu_to_le16(value); - dr->wIndex = cpu_to_le16(index); - dr->wLength = cpu_to_le16(len); - /* data are already in little-endian order */ - memcpy(databuf, pdata, len); - usb_fill_control_urb(urb, udev, pipe, - (unsigned char *)dr, databuf, len, - usbctrl_async_callback, NULL); - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc < 0) { - kfree(databuf); - kfree(dr); - } - usb_free_urb(urb); - return rc; -} - -static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request, - u16 value, u16 index, void *pdata, - u16 len) -{ - unsigned int pipe; - int status; - u8 reqtype; - int vendorreq_times = 0; - static int count; - - pipe = usb_rcvctrlpipe(udev, 0); /* read_in */ - reqtype = REALTEK_USB_VENQT_READ; - - do { - status = usb_control_msg(udev, pipe, request, reqtype, value, - index, pdata, len, 1000); - if (status < 0) { - /* firmware download is checksumed, don't retry */ - if ((value >= FW_8192C_START_ADDRESS && - value <= FW_8192C_END_ADDRESS)) - break; - } else { - break; - } - } while (++vendorreq_times < MAX_USBCTRL_VENDORREQ_TIMES); - - if (status < 0 && count++ < 4) - pr_err("reg 0x%x, usbctrl_vendorreq TimeOut! status:0x%x value=0x%x\n", - value, status, *(u32 *)pdata); - return status; -} - -static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len) -{ - struct device *dev = rtlpriv->io.dev; - struct usb_device *udev = to_usb_device(dev); - u8 request; - u16 wvalue; - u16 index; - __le32 *data; - unsigned long flags; - - spin_lock_irqsave(&rtlpriv->locks.usb_lock, flags); - if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) - rtlpriv->usb_data_index = 0; - data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; - spin_unlock_irqrestore(&rtlpriv->locks.usb_lock, flags); - request = REALTEK_USB_VENQT_CMD_REQ; - index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ - - wvalue = (u16)addr; - _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len); - return le32_to_cpu(*data); -} - -static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr) -{ - return (u8)_usb_read_sync(rtlpriv, addr, 1); -} - -static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr) -{ - return (u16)_usb_read_sync(rtlpriv, addr, 2); -} - -static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr) -{ - return _usb_read_sync(rtlpriv, addr, 4); -} - -static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val, - u16 len) -{ - u8 request; - u16 wvalue; - u16 index; - __le32 data; - - request = REALTEK_USB_VENQT_CMD_REQ; - index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ - wvalue = (u16)(addr&0x0000ffff); - data = cpu_to_le32(val); - _usbctrl_vendorreq_async_write(udev, request, wvalue, index, &data, - len); -} - -static void _usb_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val) -{ - struct device *dev = rtlpriv->io.dev; - - _usb_write_async(to_usb_device(dev), addr, val, 1); -} - -static void _usb_write16_async(struct rtl_priv *rtlpriv, u32 addr, u16 val) -{ - struct device *dev = rtlpriv->io.dev; - - _usb_write_async(to_usb_device(dev), addr, val, 2); -} - -static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val) -{ - struct device *dev = rtlpriv->io.dev; - - _usb_write_async(to_usb_device(dev), addr, val, 4); -} - -static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data, - u16 len) -{ - struct device *dev = rtlpriv->io.dev; - struct usb_device *udev = to_usb_device(dev); - u8 request = REALTEK_USB_VENQT_CMD_REQ; - u8 reqtype = REALTEK_USB_VENQT_WRITE; - u16 wvalue; - u16 index = REALTEK_USB_VENQT_CMD_IDX; - int pipe = usb_sndctrlpipe(udev, 0); /* write_out */ - u8 *buffer; - - wvalue = (u16)(addr & 0x0000ffff); - buffer = kmemdup(data, len, GFP_ATOMIC); - if (!buffer) - return; - usb_control_msg(udev, pipe, request, reqtype, wvalue, - index, buffer, len, 50); - - kfree(buffer); -} - -static void _rtl_usb_io_handler_init(struct device *dev, - struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->io.dev = dev; - mutex_init(&rtlpriv->io.bb_mutex); - rtlpriv->io.write8_async = _usb_write8_async; - rtlpriv->io.write16_async = _usb_write16_async; - rtlpriv->io.write32_async = _usb_write32_async; - rtlpriv->io.read8_sync = _usb_read8_sync; - rtlpriv->io.read16_sync = _usb_read16_sync; - rtlpriv->io.read32_sync = _usb_read32_sync; - rtlpriv->io.writeN_sync = _usb_writeN_sync; -} - -static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw) -{ - struct rtl_priv __maybe_unused *rtlpriv = rtl_priv(hw); - - mutex_destroy(&rtlpriv->io.bb_mutex); -} - -/** - * - * Default aggregation handler. Do nothing and just return the oldest skb. - */ -static struct sk_buff *_none_usb_tx_aggregate_hdl(struct ieee80211_hw *hw, - struct sk_buff_head *list) -{ - return skb_dequeue(list); -} - -#define IS_HIGH_SPEED_USB(udev) \ - ((USB_SPEED_HIGH == (udev)->speed) ? true : false) - -static int _rtl_usb_init_tx(struct ieee80211_hw *hw) -{ - u32 i; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - - rtlusb->max_bulk_out_size = IS_HIGH_SPEED_USB(rtlusb->udev) - ? USB_HIGH_SPEED_BULK_SIZE - : USB_FULL_SPEED_BULK_SIZE; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "USB Max Bulk-out Size=%d\n", - rtlusb->max_bulk_out_size); - - for (i = 0; i < __RTL_TXQ_NUM; i++) { - u32 ep_num = rtlusb->ep_map.ep_mapping[i]; - if (!ep_num) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "Invalid endpoint map setting!\n"); - return -EINVAL; - } - } - - rtlusb->usb_tx_post_hdl = - rtlpriv->cfg->usb_interface_cfg->usb_tx_post_hdl; - rtlusb->usb_tx_cleanup = - rtlpriv->cfg->usb_interface_cfg->usb_tx_cleanup; - rtlusb->usb_tx_aggregate_hdl = - (rtlpriv->cfg->usb_interface_cfg->usb_tx_aggregate_hdl) - ? rtlpriv->cfg->usb_interface_cfg->usb_tx_aggregate_hdl - : &_none_usb_tx_aggregate_hdl; - - init_usb_anchor(&rtlusb->tx_submitted); - for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) { - skb_queue_head_init(&rtlusb->tx_skb_queue[i]); - init_usb_anchor(&rtlusb->tx_pending[i]); - } - return 0; -} - -static void _rtl_rx_work(unsigned long param); - -static int _rtl_usb_init_rx(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); - - rtlusb->rx_max_size = rtlpriv->cfg->usb_interface_cfg->rx_max_size; - rtlusb->rx_urb_num = rtlpriv->cfg->usb_interface_cfg->rx_urb_num; - rtlusb->in_ep = rtlpriv->cfg->usb_interface_cfg->in_ep_num; - rtlusb->usb_rx_hdl = rtlpriv->cfg->usb_interface_cfg->usb_rx_hdl; - rtlusb->usb_rx_segregate_hdl = - rtlpriv->cfg->usb_interface_cfg->usb_rx_segregate_hdl; - - pr_info("rx_max_size %d, rx_urb_num %d, in_ep %d\n", - rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep); - init_usb_anchor(&rtlusb->rx_submitted); - init_usb_anchor(&rtlusb->rx_cleanup_urbs); - - skb_queue_head_init(&rtlusb->rx_queue); - rtlusb->rx_work_tasklet.func = _rtl_rx_work; - rtlusb->rx_work_tasklet.data = (unsigned long)rtlusb; - - return 0; -} - -static int _rtl_usb_init(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); - int err; - u8 epidx; - struct usb_interface *usb_intf = rtlusb->intf; - u8 epnums = usb_intf->cur_altsetting->desc.bNumEndpoints; - - rtlusb->out_ep_nums = rtlusb->in_ep_nums = 0; - for (epidx = 0; epidx < epnums; epidx++) { - struct usb_endpoint_descriptor *pep_desc; - pep_desc = &usb_intf->cur_altsetting->endpoint[epidx].desc; - - if (usb_endpoint_dir_in(pep_desc)) - rtlusb->in_ep_nums++; - else if (usb_endpoint_dir_out(pep_desc)) - rtlusb->out_ep_nums++; - - RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, - "USB EP(0x%02x), MaxPacketSize=%d, Interval=%d\n", - pep_desc->bEndpointAddress, pep_desc->wMaxPacketSize, - pep_desc->bInterval); - } - if (rtlusb->in_ep_nums < rtlpriv->cfg->usb_interface_cfg->in_ep_num) { - pr_err("Too few input end points found\n"); - return -EINVAL; - } - if (rtlusb->out_ep_nums == 0) { - pr_err("No output end points found\n"); - return -EINVAL; - } - /* usb endpoint mapping */ - err = rtlpriv->cfg->usb_interface_cfg->usb_endpoint_mapping(hw); - rtlusb->usb_mq_to_hwq = rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq; - _rtl_usb_init_tx(hw); - _rtl_usb_init_rx(hw); - return err; -} - -static void rtl_usb_init_sw(struct ieee80211_hw *hw) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - - rtlhal->hw = hw; - ppsc->inactiveps = false; - ppsc->leisure_ps = false; - ppsc->fwctrl_lps = false; - ppsc->reg_fwctrl_lps = 3; - ppsc->reg_max_lps_awakeintvl = 5; - ppsc->fwctrl_psmode = FW_PS_DTIM_MODE; - - /* IBSS */ - mac->beacon_interval = 100; - - /* AMPDU */ - mac->min_space_cfg = 0; - mac->max_mss_density = 0; - - /* set sane AMPDU defaults */ - mac->current_ampdu_density = 7; - mac->current_ampdu_factor = 3; - - /* QOS */ - rtlusb->acm_method = EACMWAY2_SW; - - /* IRQ */ - /* HIMR - turn all on */ - rtlusb->irq_mask[0] = 0xFFFFFFFF; - /* HIMR_EX - turn all on */ - rtlusb->irq_mask[1] = 0xFFFFFFFF; - rtlusb->disableHWSM = true; -} - -static void _rtl_rx_completed(struct urb *urb); - -static int _rtl_prep_rx_urb(struct ieee80211_hw *hw, struct rtl_usb *rtlusb, - struct urb *urb, gfp_t gfp_mask) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - void *buf; - - buf = usb_alloc_coherent(rtlusb->udev, rtlusb->rx_max_size, gfp_mask, - &urb->transfer_dma); - if (!buf) { - RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, - "Failed to usb_alloc_coherent!!\n"); - return -ENOMEM; - } - - usb_fill_bulk_urb(urb, rtlusb->udev, - usb_rcvbulkpipe(rtlusb->udev, rtlusb->in_ep), - buf, rtlusb->rx_max_size, _rtl_rx_completed, rtlusb); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - return 0; -} - -static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 *rxdesc = skb->data; - struct ieee80211_hdr *hdr; - bool unicast = false; - __le16 fc; - struct ieee80211_rx_status rx_status = {0}; - struct rtl_stats stats = { - .signal = 0, - .rate = 0, - }; - - skb_pull(skb, RTL_RX_DESC_SIZE); - rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb); - skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift)); - hdr = (struct ieee80211_hdr *)(skb->data); - fc = hdr->frame_control; - if (!stats.crc) { - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - - if (is_broadcast_ether_addr(hdr->addr1)) { - /*TODO*/; - } else if (is_multicast_ether_addr(hdr->addr1)) { - /*TODO*/ - } else { - unicast = true; - rtlpriv->stats.rxbytesunicast += skb->len; - } - - if (ieee80211_is_data(fc)) { - rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); - - if (unicast) - rtlpriv->link_info.num_rx_inperiod++; - } - /* static bcn for roaming */ - rtl_beacon_statistic(hw, skb); - } -} - -static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - u8 *rxdesc = skb->data; - struct ieee80211_hdr *hdr; - bool unicast = false; - __le16 fc; - struct ieee80211_rx_status rx_status = {0}; - struct rtl_stats stats = { - .signal = 0, - .rate = 0, - }; - - skb_pull(skb, RTL_RX_DESC_SIZE); - rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb); - skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift)); - hdr = (struct ieee80211_hdr *)(skb->data); - fc = hdr->frame_control; - if (!stats.crc) { - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - - if (is_broadcast_ether_addr(hdr->addr1)) { - /*TODO*/; - } else if (is_multicast_ether_addr(hdr->addr1)) { - /*TODO*/ - } else { - unicast = true; - rtlpriv->stats.rxbytesunicast += skb->len; - } - - if (ieee80211_is_data(fc)) { - rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); - - if (unicast) - rtlpriv->link_info.num_rx_inperiod++; - } - - /* static bcn for roaming */ - rtl_beacon_statistic(hw, skb); - - if (likely(rtl_action_proc(hw, skb, false))) - ieee80211_rx(hw, skb); - else - dev_kfree_skb_any(skb); - } -} - -static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct sk_buff *_skb; - struct sk_buff_head rx_queue; - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - - skb_queue_head_init(&rx_queue); - if (rtlusb->usb_rx_segregate_hdl) - rtlusb->usb_rx_segregate_hdl(hw, skb, &rx_queue); - WARN_ON(skb_queue_empty(&rx_queue)); - while (!skb_queue_empty(&rx_queue)) { - _skb = skb_dequeue(&rx_queue); - _rtl_usb_rx_process_agg(hw, _skb); - ieee80211_rx(hw, _skb); - } -} - -#define __RX_SKB_MAX_QUEUED 64 - -static void _rtl_rx_work(unsigned long param) -{ - struct rtl_usb *rtlusb = (struct rtl_usb *)param; - struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf); - struct sk_buff *skb; - - while ((skb = skb_dequeue(&rtlusb->rx_queue))) { - if (unlikely(IS_USB_STOP(rtlusb))) { - dev_kfree_skb_any(skb); - continue; - } - - if (likely(!rtlusb->usb_rx_segregate_hdl)) { - _rtl_usb_rx_process_noagg(hw, skb); - } else { - /* TO DO */ - _rtl_rx_pre_process(hw, skb); - pr_err("rx agg not supported\n"); - } - } -} - -static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr, - unsigned int len) -{ -#if NET_IP_ALIGN != 0 - unsigned int padding = 0; -#endif - - /* make function no-op when possible */ - if (NET_IP_ALIGN == 0 || len < sizeof(*hdr)) - return 0; - -#if NET_IP_ALIGN != 0 - /* alignment calculation as in lbtf_rx() / carl9170_rx_copy_data() */ - /* TODO: deduplicate common code, define helper function instead? */ - - if (ieee80211_is_data_qos(hdr->frame_control)) { - u8 *qc = ieee80211_get_qos_ctl(hdr); - - padding ^= NET_IP_ALIGN; - - /* Input might be invalid, avoid accessing memory outside - * the buffer. - */ - if ((unsigned long)qc - (unsigned long)hdr < len && - *qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) - padding ^= NET_IP_ALIGN; - } - - if (ieee80211_has_a4(hdr->frame_control)) - padding ^= NET_IP_ALIGN; - - return padding; -#endif -} - -#define __RADIO_TAP_SIZE_RSV 32 - -static void _rtl_rx_completed(struct urb *_urb) -{ - struct rtl_usb *rtlusb = (struct rtl_usb *)_urb->context; - struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf); - struct rtl_priv *rtlpriv = rtl_priv(hw); - int err = 0; - - if (unlikely(IS_USB_STOP(rtlusb))) - goto free; - - if (likely(0 == _urb->status)) { - unsigned int padding; - struct sk_buff *skb; - unsigned int qlen; - unsigned int size = _urb->actual_length; - struct ieee80211_hdr *hdr; - - if (size < RTL_RX_DESC_SIZE + sizeof(struct ieee80211_hdr)) { - RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, - "Too short packet from bulk IN! (len: %d)\n", - size); - goto resubmit; - } - - qlen = skb_queue_len(&rtlusb->rx_queue); - if (qlen >= __RX_SKB_MAX_QUEUED) { - RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, - "Pending RX skbuff queue full! (qlen: %d)\n", - qlen); - goto resubmit; - } - - hdr = (void *)(_urb->transfer_buffer + RTL_RX_DESC_SIZE); - padding = _rtl_rx_get_padding(hdr, size - RTL_RX_DESC_SIZE); - - skb = dev_alloc_skb(size + __RADIO_TAP_SIZE_RSV + padding); - if (!skb) { - RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, - "Can't allocate skb for bulk IN!\n"); - goto resubmit; - } - - _rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep); - - /* Make sure the payload data is 4 byte aligned. */ - skb_reserve(skb, padding); - - /* reserve some space for mac80211's radiotap */ - skb_reserve(skb, __RADIO_TAP_SIZE_RSV); - - memcpy(skb_put(skb, size), _urb->transfer_buffer, size); - - skb_queue_tail(&rtlusb->rx_queue, skb); - tasklet_schedule(&rtlusb->rx_work_tasklet); - - goto resubmit; - } - - switch (_urb->status) { - /* disconnect */ - case -ENOENT: - case -ECONNRESET: - case -ENODEV: - case -ESHUTDOWN: - goto free; - default: - break; - } - -resubmit: - usb_anchor_urb(_urb, &rtlusb->rx_submitted); - err = usb_submit_urb(_urb, GFP_ATOMIC); - if (unlikely(err)) { - usb_unanchor_urb(_urb); - goto free; - } - return; - -free: - /* On some architectures, usb_free_coherent must not be called from - * hardirq context. Queue urb to cleanup list. - */ - usb_anchor_urb(_urb, &rtlusb->rx_cleanup_urbs); -} - -#undef __RADIO_TAP_SIZE_RSV - -static void _rtl_usb_cleanup_rx(struct ieee80211_hw *hw) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - struct urb *urb; - - 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); - destroy_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); - } -} - -static int _rtl_usb_receive(struct ieee80211_hw *hw) -{ - struct urb *urb; - int err; - int i; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - - WARN_ON(0 == rtlusb->rx_urb_num); - /* 1600 == 1514 + max WLAN header + rtk info */ - WARN_ON(rtlusb->rx_max_size < 1600); - - for (i = 0; i < rtlusb->rx_urb_num; i++) { - err = -ENOMEM; - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, - "Failed to alloc URB!!\n"); - goto err_out; - } - - err = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL); - if (err < 0) { - RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, - "Failed to prep_rx_urb!!\n"); - usb_free_urb(urb); - goto err_out; - } - - usb_anchor_urb(urb, &rtlusb->rx_submitted); - err = usb_submit_urb(urb, GFP_KERNEL); - if (err) - goto err_out; - usb_free_urb(urb); - } - return 0; - -err_out: - usb_kill_anchored_urbs(&rtlusb->rx_submitted); - _rtl_usb_cleanup_rx(hw); - return err; -} - -static int rtl_usb_start(struct ieee80211_hw *hw) -{ - int err; - 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)); - - err = rtlpriv->cfg->ops->hw_init(hw); - if (!err) { - rtl_init_rx_config(hw); - - /* Enable software */ - SET_USB_START(rtlusb); - /* should after adapter start and interrupt enable. */ - set_hal_start(rtlhal); - - /* Start bulk IN */ - err = _rtl_usb_receive(hw); - } - - return err; -} -/** - * - * - */ - -/*======================= tx =========================================*/ -static void rtl_usb_cleanup(struct ieee80211_hw *hw) -{ - u32 i; - struct sk_buff *_skb; - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - struct ieee80211_tx_info *txinfo; - - /* clean up rx stuff. */ - _rtl_usb_cleanup_rx(hw); - - /* clean up tx stuff */ - for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) { - while ((_skb = skb_dequeue(&rtlusb->tx_skb_queue[i]))) { - rtlusb->usb_tx_cleanup(hw, _skb); - txinfo = IEEE80211_SKB_CB(_skb); - ieee80211_tx_info_clear_status(txinfo); - txinfo->flags |= IEEE80211_TX_STAT_ACK; - ieee80211_tx_status_irqsafe(hw, _skb); - } - usb_kill_anchored_urbs(&rtlusb->tx_pending[i]); - } - usb_kill_anchored_urbs(&rtlusb->tx_submitted); -} - -/** - * - * We may add some struct into struct rtl_usb later. Do deinit here. - * - */ -static void rtl_usb_deinit(struct ieee80211_hw *hw) -{ - rtl_usb_cleanup(hw); -} - -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)); - - /* 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); - rtlpriv->cfg->ops->hw_disable(hw); -} - -static void _rtl_submit_tx_urb(struct ieee80211_hw *hw, struct urb *_urb) -{ - int err; - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - - usb_anchor_urb(_urb, &rtlusb->tx_submitted); - err = usb_submit_urb(_urb, GFP_ATOMIC); - if (err < 0) { - struct sk_buff *skb; - - RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, - "Failed to submit urb\n"); - usb_unanchor_urb(_urb); - skb = (struct sk_buff *)_urb->context; - kfree_skb(skb); - } - usb_free_urb(_urb); -} - -static int _usb_tx_post(struct ieee80211_hw *hw, struct urb *urb, - struct sk_buff *skb) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - struct ieee80211_tx_info *txinfo; - - rtlusb->usb_tx_post_hdl(hw, urb, skb); - skb_pull(skb, RTL_TX_HEADER_SIZE); - txinfo = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(txinfo); - txinfo->flags |= IEEE80211_TX_STAT_ACK; - - if (urb->status) { - RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, - "Urb has error status 0x%X\n", urb->status); - goto out; - } - /* TODO: statistics */ -out: - ieee80211_tx_status_irqsafe(hw, skb); - return urb->status; -} - -static void _rtl_tx_complete(struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *)urb->context; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct rtl_usb *rtlusb = (struct rtl_usb *)info->rate_driver_data[0]; - struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf); - int err; - - if (unlikely(IS_USB_STOP(rtlusb))) - return; - err = _usb_tx_post(hw, urb, skb); - if (err) { - /* Ignore error and keep issuiing other urbs */ - return; - } -} - -static struct urb *_rtl_usb_tx_urb_setup(struct ieee80211_hw *hw, - struct sk_buff *skb, u32 ep_num) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - struct urb *_urb; - - WARN_ON(NULL == skb); - _urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!_urb) { - RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, - "Can't allocate URB for bulk out!\n"); - kfree_skb(skb); - return NULL; - } - _rtl_install_trx_info(rtlusb, skb, ep_num); - usb_fill_bulk_urb(_urb, rtlusb->udev, usb_sndbulkpipe(rtlusb->udev, - ep_num), skb->data, skb->len, _rtl_tx_complete, skb); - _urb->transfer_flags |= URB_ZERO_PACKET; - return _urb; -} - -static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, - enum rtl_txq qnum) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - u32 ep_num; - struct urb *_urb = NULL; - struct sk_buff *_skb = NULL; - - WARN_ON(NULL == rtlusb->usb_tx_aggregate_hdl); - if (unlikely(IS_USB_STOP(rtlusb))) { - RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, - "USB device is stopping...\n"); - kfree_skb(skb); - return; - } - ep_num = rtlusb->ep_map.ep_mapping[qnum]; - _skb = skb; - _urb = _rtl_usb_tx_urb_setup(hw, _skb, ep_num); - if (unlikely(!_urb)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't allocate urb. Drop skb!\n"); - kfree_skb(skb); - return; - } - _rtl_submit_tx_urb(hw, _urb); -} - -static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - struct sk_buff *skb, - u16 hw_queue) -{ - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct rtl_tx_desc *pdesc = NULL; - struct rtl_tcb_desc tcb_desc; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - __le16 fc = hdr->frame_control; - u8 *pda_addr = hdr->addr1; - /* ssn */ - u8 *qc = NULL; - u8 tid = 0; - u16 seq_number = 0; - - memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); - if (ieee80211_is_auth(fc)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n"); - rtl_ips_nic_on(hw); - } - - if (rtlpriv->psc.sw_ps_enabled) { - if (ieee80211_is_data(fc) && !ieee80211_is_nullfunc(fc) && - !ieee80211_has_pm(fc)) - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - } - - rtl_action_proc(hw, skb, true); - if (is_multicast_ether_addr(pda_addr)) - rtlpriv->stats.txbytesmulticast += skb->len; - else if (is_broadcast_ether_addr(pda_addr)) - rtlpriv->stats.txbytesbroadcast += skb->len; - else - rtlpriv->stats.txbytesunicast += skb->len; - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - seq_number = (le16_to_cpu(hdr->seq_ctrl) & - IEEE80211_SCTL_SEQ) >> 4; - seq_number += 1; - seq_number <<= 4; - } - rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, NULL, info, sta, skb, - hw_queue, &tcb_desc); - if (!ieee80211_has_morefrags(hdr->frame_control)) { - if (qc) - mac->tids[tid].seq_number = seq_number; - } - if (ieee80211_is_data(fc)) - rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); -} - -static int rtl_usb_tx(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - struct sk_buff *skb, - struct rtl_tcb_desc *dummy) -{ - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); - __le16 fc = hdr->frame_control; - u16 hw_queue; - - if (unlikely(is_hal_stop(rtlhal))) - goto err_free; - hw_queue = rtlusb->usb_mq_to_hwq(fc, skb_get_queue_mapping(skb)); - _rtl_usb_tx_preprocess(hw, sta, skb, hw_queue); - _rtl_usb_transmit(hw, skb, hw_queue); - return NETDEV_TX_OK; - -err_free: - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} - -static bool rtl_usb_tx_chk_waitq_insert(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - struct sk_buff *skb) -{ - return false; -} - -static void rtl_fill_h2c_cmd_work_callback(struct work_struct *work) -{ - struct rtl_works *rtlworks = - container_of(work, struct rtl_works, fill_h2c_cmd); - struct ieee80211_hw *hw = rtlworks->hw; - struct rtl_priv *rtlpriv = rtl_priv(hw); - - rtlpriv->cfg->ops->fill_h2c_cmd(hw, H2C_RA_MASK, 5, rtlpriv->rate_mask); -} - -static struct rtl_intf_ops rtl_usb_ops = { - .adapter_start = rtl_usb_start, - .adapter_stop = rtl_usb_stop, - .adapter_tx = rtl_usb_tx, - .waitq_insert = rtl_usb_tx_chk_waitq_insert, -}; - -int rtl_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id, - struct rtl_hal_cfg *rtl_hal_cfg) -{ - int err; - struct ieee80211_hw *hw = NULL; - struct rtl_priv *rtlpriv = NULL; - struct usb_device *udev; - struct rtl_usb_priv *usb_priv; - - hw = ieee80211_alloc_hw(sizeof(struct rtl_priv) + - sizeof(struct rtl_usb_priv), &rtl_ops); - if (!hw) { - RT_ASSERT(false, "ieee80211 alloc failed\n"); - return -ENOMEM; - } - rtlpriv = hw->priv; - rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32), - GFP_KERNEL); - if (!rtlpriv->usb_data) - return -ENOMEM; - - /* this spin lock must be initialized early */ - spin_lock_init(&rtlpriv->locks.usb_lock); - INIT_WORK(&rtlpriv->works.fill_h2c_cmd, - rtl_fill_h2c_cmd_work_callback); - INIT_WORK(&rtlpriv->works.lps_change_work, - rtl_lps_change_work_callback); - - rtlpriv->usb_data_index = 0; - init_completion(&rtlpriv->firmware_loading_complete); - SET_IEEE80211_DEV(hw, &intf->dev); - udev = interface_to_usbdev(intf); - usb_get_dev(udev); - usb_priv = rtl_usbpriv(hw); - memset(usb_priv, 0, sizeof(*usb_priv)); - usb_priv->dev.intf = intf; - usb_priv->dev.udev = udev; - usb_set_intfdata(intf, hw); - /* init cfg & intf_ops */ - 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); - /*like read eeprom and so on */ - rtlpriv->cfg->ops->read_eeprom_info(hw); - err = _rtl_usb_init(hw); - if (err) - goto error_out; - rtl_usb_init_sw(hw); - /* Init mac80211 sw */ - err = rtl_init_core(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't allocate sw for mac80211\n"); - goto error_out; - } - if (rtlpriv->cfg->ops->init_sw_vars(hw)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n"); - goto error_out; - } - rtlpriv->cfg->ops->init_sw_leds(hw); - - err = ieee80211_register_hw(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - "Can't register mac80211 hw.\n"); - err = -ENODEV; - goto error_out; - } - rtlpriv->mac80211.mac80211_registered = 1; - - set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); - return 0; - -error_out: - rtl_deinit_core(hw); - _rtl_usb_io_handler_release(hw); - usb_put_dev(udev); - complete(&rtlpriv->firmware_loading_complete); - return -ENODEV; -} -EXPORT_SYMBOL(rtl_usb_probe); - -void rtl_usb_disconnect(struct usb_interface *intf) -{ - struct ieee80211_hw *hw = usb_get_intfdata(intf); - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw)); - struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); - - if (unlikely(!rtlpriv)) - return; - /* just in case driver is removed before firmware callback */ - wait_for_completion(&rtlpriv->firmware_loading_complete); - clear_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); - /*ieee80211_unregister_hw will call ops_stop */ - if (rtlmac->mac80211_registered == 1) { - ieee80211_unregister_hw(hw); - rtlmac->mac80211_registered = 0; - } else { - rtl_deinit_deferred_work(hw); - rtlpriv->intf_ops->adapter_stop(hw); - } - /*deinit rfkill */ - /* rtl_deinit_rfkill(hw); */ - rtl_usb_deinit(hw); - rtl_deinit_core(hw); - kfree(rtlpriv->usb_data); - rtlpriv->cfg->ops->deinit_sw_leds(hw); - rtlpriv->cfg->ops->deinit_sw_vars(hw); - _rtl_usb_io_handler_release(hw); - usb_put_dev(rtlusb->udev); - usb_set_intfdata(intf, NULL); - ieee80211_free_hw(hw); -} -EXPORT_SYMBOL(rtl_usb_disconnect); - -int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message) -{ - return 0; -} -EXPORT_SYMBOL(rtl_usb_suspend); - -int rtl_usb_resume(struct usb_interface *pusb_intf) -{ - return 0; -} -EXPORT_SYMBOL(rtl_usb_resume); diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/rtlwifi/usb.h deleted file mode 100644 index 685273ca9561..000000000000 --- a/drivers/net/wireless/rtlwifi/usb.h +++ /dev/null @@ -1,169 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. All rights reserved. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - *****************************************************************************/ - -#ifndef __RTL_USB_H__ -#define __RTL_USB_H__ - -#include - -#define RTL_RX_DESC_SIZE 24 - -#define RTL_USB_DEVICE(vend, prod, cfg) \ - .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \ - .idVendor = (vend), \ - .idProduct = (prod), \ - .driver_info = (kernel_ulong_t)&(cfg) - -#define USB_HIGH_SPEED_BULK_SIZE 512 -#define USB_FULL_SPEED_BULK_SIZE 64 - - -#define RTL_USB_MAX_TXQ_NUM 4 /* max tx queue */ -#define RTL_USB_MAX_EP_NUM 6 /* max ep number */ -#define RTL_USB_MAX_TX_URBS_NUM 8 - -enum rtl_txq { - /* These definitions shall be consistent with value - * returned by skb_get_queue_mapping - *------------------------------------*/ - RTL_TXQ_BK, - RTL_TXQ_BE, - RTL_TXQ_VI, - RTL_TXQ_VO, - /*------------------------------------*/ - RTL_TXQ_BCN, - RTL_TXQ_MGT, - RTL_TXQ_HI, - - /* Must be last */ - __RTL_TXQ_NUM, -}; - -struct rtl_ep_map { - u32 ep_mapping[__RTL_TXQ_NUM]; -}; - -struct _trx_info { - struct rtl_usb *rtlusb; - u32 ep_num; -}; - -static inline void _rtl_install_trx_info(struct rtl_usb *rtlusb, - struct sk_buff *skb, - u32 ep_num) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - info->rate_driver_data[0] = rtlusb; - info->rate_driver_data[1] = (void *)(__kernel_size_t)ep_num; -} - - -/* Add suspend/resume later */ -enum rtl_usb_state { - USB_STATE_STOP = 0, - USB_STATE_START = 1, -}; - -#define IS_USB_STOP(rtlusb_ptr) (USB_STATE_STOP == (rtlusb_ptr)->state) -#define IS_USB_START(rtlusb_ptr) (USB_STATE_START == (rtlusb_ptr)->state) -#define SET_USB_STOP(rtlusb_ptr) \ - do { \ - (rtlusb_ptr)->state = USB_STATE_STOP; \ - } while (0) - -#define SET_USB_START(rtlusb_ptr) \ - do { \ - (rtlusb_ptr)->state = USB_STATE_START; \ - } while (0) - -struct rtl_usb { - struct usb_device *udev; - struct usb_interface *intf; - enum rtl_usb_state state; - - /* Bcn control register setting */ - u32 reg_bcn_ctrl_val; - /* for 88/92cu card disable */ - u8 disableHWSM; - /*QOS & EDCA */ - enum acm_method acm_method; - /* irq . HIMR,HIMR_EX */ - u32 irq_mask[2]; - bool irq_enabled; - - u16 (*usb_mq_to_hwq)(__le16 fc, u16 mac80211_queue_index); - - /* Tx */ - u8 out_ep_nums ; - u8 out_queue_sel; - struct rtl_ep_map ep_map; - - u32 max_bulk_out_size; - u32 tx_submitted_urbs; - struct sk_buff_head tx_skb_queue[RTL_USB_MAX_EP_NUM]; - - struct usb_anchor tx_pending[RTL_USB_MAX_EP_NUM]; - struct usb_anchor tx_submitted; - - struct sk_buff *(*usb_tx_aggregate_hdl)(struct ieee80211_hw *, - struct sk_buff_head *); - int (*usb_tx_post_hdl)(struct ieee80211_hw *, - struct urb *, struct sk_buff *); - void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *); - - /* Rx */ - u8 in_ep_nums; - u32 in_ep; /* Bulk IN endpoint number */ - u32 rx_max_size; /* Bulk IN max buffer size */ - u32 rx_urb_num; /* How many Bulk INs are submitted to host. */ - struct usb_anchor rx_submitted; - struct usb_anchor rx_cleanup_urbs; - struct tasklet_struct rx_work_tasklet; - struct sk_buff_head rx_queue; - void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *, - struct sk_buff_head *); - void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *); -}; - -struct rtl_usb_priv { - struct rtl_usb dev; - struct rtl_led_ctl ledctl; -}; - -#define rtl_usbpriv(hw) (((struct rtl_usb_priv *)(rtl_priv(hw))->priv)) -#define rtl_usbdev(usbpriv) (&((usbpriv)->dev)) - - - -int rtl_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id, - struct rtl_hal_cfg *rtl92cu_hal_cfg); -void rtl_usb_disconnect(struct usb_interface *intf); -int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message); -int rtl_usb_resume(struct usb_interface *pusb_intf); - -#endif diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h deleted file mode 100644 index b90ca618b123..000000000000 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ /dev/null @@ -1,3032 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2009-2012 Realtek Corporation. - * - * 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 - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * wlanfae - * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, - * Hsinchu 300, Taiwan. - * - * Larry Finger - * - *****************************************************************************/ - -#ifndef __RTL_WIFI_H__ -#define __RTL_WIFI_H__ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include "debug.h" - -#define MASKBYTE0 0xff -#define MASKBYTE1 0xff00 -#define MASKBYTE2 0xff0000 -#define MASKBYTE3 0xff000000 -#define MASKHWORD 0xffff0000 -#define MASKLWORD 0x0000ffff -#define MASKDWORD 0xffffffff -#define MASK12BITS 0xfff -#define MASKH4BITS 0xf0000000 -#define MASKOFDM_D 0xffc00000 -#define MASKCCK 0x3f3f3f3f - -#define MASK4BITS 0x0f -#define MASK20BITS 0xfffff -#define RFREG_OFFSET_MASK 0xfffff - -#define MASKBYTE0 0xff -#define MASKBYTE1 0xff00 -#define MASKBYTE2 0xff0000 -#define MASKBYTE3 0xff000000 -#define MASKHWORD 0xffff0000 -#define MASKLWORD 0x0000ffff -#define MASKDWORD 0xffffffff -#define MASK12BITS 0xfff -#define MASKH4BITS 0xf0000000 -#define MASKOFDM_D 0xffc00000 -#define MASKCCK 0x3f3f3f3f - -#define MASK4BITS 0x0f -#define MASK20BITS 0xfffff -#define RFREG_OFFSET_MASK 0xfffff - -#define RF_CHANGE_BY_INIT 0 -#define RF_CHANGE_BY_IPS BIT(28) -#define RF_CHANGE_BY_PS BIT(29) -#define RF_CHANGE_BY_HW BIT(30) -#define RF_CHANGE_BY_SW BIT(31) - -#define IQK_ADDA_REG_NUM 16 -#define IQK_MAC_REG_NUM 4 -#define IQK_THRESHOLD 8 - -#define MAX_KEY_LEN 61 -#define KEY_BUF_SIZE 5 - -/* QoS related. */ -/*aci: 0x00 Best Effort*/ -/*aci: 0x01 Background*/ -/*aci: 0x10 Video*/ -/*aci: 0x11 Voice*/ -/*Max: define total number.*/ -#define AC0_BE 0 -#define AC1_BK 1 -#define AC2_VI 2 -#define AC3_VO 3 -#define AC_MAX 4 -#define QOS_QUEUE_NUM 4 -#define RTL_MAC80211_NUM_QUEUE 5 -#define REALTEK_USB_VENQT_MAX_BUF_SIZE 254 -#define RTL_USB_MAX_RX_COUNT 100 -#define QBSS_LOAD_SIZE 5 -#define MAX_WMMELE_LENGTH 64 - -#define TOTAL_CAM_ENTRY 32 - -/*slot time for 11g. */ -#define RTL_SLOT_TIME_9 9 -#define RTL_SLOT_TIME_20 20 - -/*related to tcp/ip. */ -#define SNAP_SIZE 6 -#define PROTOC_TYPE_SIZE 2 - -/*related with 802.11 frame*/ -#define MAC80211_3ADDR_LEN 24 -#define MAC80211_4ADDR_LEN 30 - -#define CHANNEL_MAX_NUMBER (14 + 24 + 21) /* 14 is the max channel no */ -#define CHANNEL_MAX_NUMBER_2G 14 -#define CHANNEL_MAX_NUMBER_5G 54 /* Please refer to - *"phy_GetChnlGroup8812A" and - * "Hal_ReadTxPowerInfo8812A" - */ -#define CHANNEL_MAX_NUMBER_5G_80M 7 -#define CHANNEL_GROUP_MAX (3 + 9) /* ch1~3, 4~9, 10~14 = three groups */ -#define CHANNEL_MAX_NUMBER_5G 54 /* Please refer to - *"phy_GetChnlGroup8812A" and - * "Hal_ReadTxPowerInfo8812A" - */ -#define CHANNEL_MAX_NUMBER_5G_80M 7 -#define MAX_PG_GROUP 13 -#define CHANNEL_GROUP_MAX_2G 3 -#define CHANNEL_GROUP_IDX_5GL 3 -#define CHANNEL_GROUP_IDX_5GM 6 -#define CHANNEL_GROUP_IDX_5GH 9 -#define CHANNEL_GROUP_MAX_5G 9 -#define CHANNEL_MAX_NUMBER_2G 14 -#define AVG_THERMAL_NUM 8 -#define AVG_THERMAL_NUM_88E 4 -#define AVG_THERMAL_NUM_8723BE 4 -#define MAX_TID_COUNT 9 - -/* for early mode */ -#define FCS_LEN 4 -#define EM_HDR_LEN 8 - -enum rtl8192c_h2c_cmd { - H2C_AP_OFFLOAD = 0, - H2C_SETPWRMODE = 1, - H2C_JOINBSSRPT = 2, - H2C_RSVDPAGE = 3, - H2C_RSSI_REPORT = 5, - H2C_RA_MASK = 6, - H2C_MACID_PS_MODE = 7, - H2C_P2P_PS_OFFLOAD = 8, - H2C_MAC_MODE_SEL = 9, - H2C_PWRM = 15, - H2C_P2P_PS_CTW_CMD = 24, - MAX_H2CCMD -}; - -#define MAX_TX_COUNT 4 -#define MAX_REGULATION_NUM 4 -#define MAX_RF_PATH_NUM 4 -#define MAX_RATE_SECTION_NUM 6 -#define MAX_2_4G_BANDWITH_NUM 4 -#define MAX_5G_BANDWITH_NUM 4 -#define MAX_RF_PATH 4 -#define MAX_CHNL_GROUP_24G 6 -#define MAX_CHNL_GROUP_5G 14 - -#define TX_PWR_BY_RATE_NUM_BAND 2 -#define TX_PWR_BY_RATE_NUM_RF 4 -#define TX_PWR_BY_RATE_NUM_SECTION 12 -#define MAX_BASE_NUM_IN_PHY_REG_PG_24G 6 -#define MAX_BASE_NUM_IN_PHY_REG_PG_5G 5 - -#define RTL8192EE_SEG_NUM 1 /* 0:2 seg, 1: 4 seg, 2: 8 seg */ - -#define DEL_SW_IDX_SZ 30 -#define BAND_NUM 3 - -/* For now, it's just for 8192ee - * but not OK yet, keep it 0 - */ -#define DMA_IS_64BIT 0 -#define RTL8192EE_SEG_NUM 1 /* 0:2 seg, 1: 4 seg, 2: 8 seg */ - -enum rf_tx_num { - RF_1TX = 0, - RF_2TX, - RF_MAX_TX_NUM, - RF_TX_NUM_NONIMPLEMENT, -}; - -#define PACKET_NORMAL 0 -#define PACKET_DHCP 1 -#define PACKET_ARP 2 -#define PACKET_EAPOL 3 - -#define MAX_SUPPORT_WOL_PATTERN_NUM 16 -#define RSVD_WOL_PATTERN_NUM 1 -#define WKFMCAM_ADDR_NUM 6 -#define WKFMCAM_SIZE 24 - -#define MAX_WOL_BIT_MASK_SIZE 16 -/* MIN LEN keeps 13 here */ -#define MIN_WOL_PATTERN_SIZE 13 -#define MAX_WOL_PATTERN_SIZE 128 - -#define WAKE_ON_MAGIC_PACKET BIT(0) -#define WAKE_ON_PATTERN_MATCH BIT(1) - -#define WOL_REASON_PTK_UPDATE BIT(0) -#define WOL_REASON_GTK_UPDATE BIT(1) -#define WOL_REASON_DISASSOC BIT(2) -#define WOL_REASON_DEAUTH BIT(3) -#define WOL_REASON_AP_LOST BIT(4) -#define WOL_REASON_MAGIC_PKT BIT(5) -#define WOL_REASON_UNICAST_PKT BIT(6) -#define WOL_REASON_PATTERN_PKT BIT(7) -#define WOL_REASON_RTD3_SSID_MATCH BIT(8) -#define WOL_REASON_REALWOW_V2_WAKEUPPKT BIT(9) -#define WOL_REASON_REALWOW_V2_ACKLOST BIT(10) - -struct rtlwifi_firmware_header { - __le16 signature; - u8 category; - u8 function; - __le16 version; - u8 subversion; - u8 rsvd1; - u8 month; - u8 date; - u8 hour; - u8 minute; - __le16 ramcodeSize; - __le16 rsvd2; - __le32 svnindex; - __le32 rsvd3; - __le32 rsvd4; - __le32 rsvd5; -}; - -struct txpower_info_2g { - u8 index_cck_base[MAX_RF_PATH][MAX_CHNL_GROUP_24G]; - u8 index_bw40_base[MAX_RF_PATH][MAX_CHNL_GROUP_24G]; - /*If only one tx, only BW20 and OFDM are used.*/ - u8 cck_diff[MAX_RF_PATH][MAX_TX_COUNT]; - u8 ofdm_diff[MAX_RF_PATH][MAX_TX_COUNT]; - u8 bw20_diff[MAX_RF_PATH][MAX_TX_COUNT]; - u8 bw40_diff[MAX_RF_PATH][MAX_TX_COUNT]; - u8 bw80_diff[MAX_RF_PATH][MAX_TX_COUNT]; - u8 bw160_diff[MAX_RF_PATH][MAX_TX_COUNT]; -}; - -struct txpower_info_5g { - u8 index_bw40_base[MAX_RF_PATH][MAX_CHNL_GROUP_5G]; - /*If only one tx, only BW20, OFDM, BW80 and BW160 are used.*/ - u8 ofdm_diff[MAX_RF_PATH][MAX_TX_COUNT]; - u8 bw20_diff[MAX_RF_PATH][MAX_TX_COUNT]; - u8 bw40_diff[MAX_RF_PATH][MAX_TX_COUNT]; - u8 bw80_diff[MAX_RF_PATH][MAX_TX_COUNT]; - u8 bw160_diff[MAX_RF_PATH][MAX_TX_COUNT]; -}; - -enum rate_section { - CCK = 0, - OFDM, - HT_MCS0_MCS7, - HT_MCS8_MCS15, - VHT_1SSMCS0_1SSMCS9, - VHT_2SSMCS0_2SSMCS9, -}; - -enum intf_type { - INTF_PCI = 0, - INTF_USB = 1, -}; - -enum radio_path { - RF90_PATH_A = 0, - RF90_PATH_B = 1, - RF90_PATH_C = 2, - RF90_PATH_D = 3, -}; - -enum regulation_txpwr_lmt { - TXPWR_LMT_FCC = 0, - TXPWR_LMT_MKK = 1, - TXPWR_LMT_ETSI = 2, - TXPWR_LMT_WW = 3, - - TXPWR_LMT_MAX_REGULATION_NUM = 4 -}; - -enum rt_eeprom_type { - EEPROM_93C46, - EEPROM_93C56, - EEPROM_BOOT_EFUSE, -}; - -enum ttl_status { - RTL_STATUS_INTERFACE_START = 0, -}; - -enum hardware_type { - HARDWARE_TYPE_RTL8192E, - HARDWARE_TYPE_RTL8192U, - HARDWARE_TYPE_RTL8192SE, - HARDWARE_TYPE_RTL8192SU, - HARDWARE_TYPE_RTL8192CE, - HARDWARE_TYPE_RTL8192CU, - HARDWARE_TYPE_RTL8192DE, - HARDWARE_TYPE_RTL8192DU, - HARDWARE_TYPE_RTL8723AE, - HARDWARE_TYPE_RTL8723U, - HARDWARE_TYPE_RTL8188EE, - HARDWARE_TYPE_RTL8723BE, - HARDWARE_TYPE_RTL8192EE, - HARDWARE_TYPE_RTL8821AE, - HARDWARE_TYPE_RTL8812AE, - - /* keep it last */ - HARDWARE_TYPE_NUM -}; - -#define IS_HARDWARE_TYPE_8192SU(rtlhal) \ - (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SU) -#define IS_HARDWARE_TYPE_8192SE(rtlhal) \ - (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE) -#define IS_HARDWARE_TYPE_8192CE(rtlhal) \ - (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) -#define IS_HARDWARE_TYPE_8192CU(rtlhal) \ - (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) -#define IS_HARDWARE_TYPE_8192DE(rtlhal) \ - (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) -#define IS_HARDWARE_TYPE_8192DU(rtlhal) \ - (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DU) -#define IS_HARDWARE_TYPE_8723E(rtlhal) \ - (rtlhal->hw_type == HARDWARE_TYPE_RTL8723E) -#define IS_HARDWARE_TYPE_8723U(rtlhal) \ - (rtlhal->hw_type == HARDWARE_TYPE_RTL8723U) -#define IS_HARDWARE_TYPE_8192S(rtlhal) \ -(IS_HARDWARE_TYPE_8192SE(rtlhal) || IS_HARDWARE_TYPE_8192SU(rtlhal)) -#define IS_HARDWARE_TYPE_8192C(rtlhal) \ -(IS_HARDWARE_TYPE_8192CE(rtlhal) || IS_HARDWARE_TYPE_8192CU(rtlhal)) -#define IS_HARDWARE_TYPE_8192D(rtlhal) \ -(IS_HARDWARE_TYPE_8192DE(rtlhal) || IS_HARDWARE_TYPE_8192DU(rtlhal)) -#define IS_HARDWARE_TYPE_8723(rtlhal) \ -(IS_HARDWARE_TYPE_8723E(rtlhal) || IS_HARDWARE_TYPE_8723U(rtlhal)) - -#define RX_HAL_IS_CCK_RATE(rxmcs) \ - ((rxmcs) == DESC_RATE1M || \ - (rxmcs) == DESC_RATE2M || \ - (rxmcs) == DESC_RATE5_5M || \ - (rxmcs) == DESC_RATE11M) - -enum scan_operation_backup_opt { - SCAN_OPT_BACKUP = 0, - SCAN_OPT_BACKUP_BAND0 = 0, - SCAN_OPT_BACKUP_BAND1, - SCAN_OPT_RESTORE, - SCAN_OPT_MAX -}; - -/*RF state.*/ -enum rf_pwrstate { - ERFON, - ERFSLEEP, - ERFOFF -}; - -struct bb_reg_def { - u32 rfintfs; - u32 rfintfi; - u32 rfintfo; - u32 rfintfe; - u32 rf3wire_offset; - u32 rflssi_select; - u32 rftxgain_stage; - u32 rfhssi_para1; - u32 rfhssi_para2; - u32 rfsw_ctrl; - u32 rfagc_control1; - u32 rfagc_control2; - u32 rfrxiq_imbal; - u32 rfrx_afe; - u32 rftxiq_imbal; - u32 rftx_afe; - u32 rf_rb; /* rflssi_readback */ - u32 rf_rbpi; /* rflssi_readbackpi */ -}; - -enum io_type { - IO_CMD_PAUSE_DM_BY_SCAN = 0, - IO_CMD_PAUSE_BAND0_DM_BY_SCAN = 0, - IO_CMD_PAUSE_BAND1_DM_BY_SCAN = 1, - IO_CMD_RESUME_DM_BY_SCAN = 2, -}; - -enum hw_variables { - HW_VAR_ETHER_ADDR, - HW_VAR_MULTICAST_REG, - HW_VAR_BASIC_RATE, - HW_VAR_BSSID, - HW_VAR_MEDIA_STATUS, - HW_VAR_SECURITY_CONF, - HW_VAR_BEACON_INTERVAL, - HW_VAR_ATIM_WINDOW, - HW_VAR_LISTEN_INTERVAL, - HW_VAR_CS_COUNTER, - HW_VAR_DEFAULTKEY0, - HW_VAR_DEFAULTKEY1, - HW_VAR_DEFAULTKEY2, - HW_VAR_DEFAULTKEY3, - HW_VAR_SIFS, - HW_VAR_R2T_SIFS, - HW_VAR_DIFS, - HW_VAR_EIFS, - HW_VAR_SLOT_TIME, - HW_VAR_ACK_PREAMBLE, - HW_VAR_CW_CONFIG, - HW_VAR_CW_VALUES, - HW_VAR_RATE_FALLBACK_CONTROL, - HW_VAR_CONTENTION_WINDOW, - HW_VAR_RETRY_COUNT, - HW_VAR_TR_SWITCH, - HW_VAR_COMMAND, - HW_VAR_WPA_CONFIG, - HW_VAR_AMPDU_MIN_SPACE, - HW_VAR_SHORTGI_DENSITY, - HW_VAR_AMPDU_FACTOR, - HW_VAR_MCS_RATE_AVAILABLE, - HW_VAR_AC_PARAM, - HW_VAR_ACM_CTRL, - HW_VAR_DIS_Req_Qsize, - HW_VAR_CCX_CHNL_LOAD, - HW_VAR_CCX_NOISE_HISTOGRAM, - HW_VAR_CCX_CLM_NHM, - HW_VAR_TxOPLimit, - HW_VAR_TURBO_MODE, - HW_VAR_RF_STATE, - HW_VAR_RF_OFF_BY_HW, - HW_VAR_BUS_SPEED, - HW_VAR_SET_DEV_POWER, - - HW_VAR_RCR, - HW_VAR_RATR_0, - HW_VAR_RRSR, - HW_VAR_CPU_RST, - HW_VAR_CHECK_BSSID, - HW_VAR_LBK_MODE, - HW_VAR_AES_11N_FIX, - HW_VAR_USB_RX_AGGR, - HW_VAR_USER_CONTROL_TURBO_MODE, - HW_VAR_RETRY_LIMIT, - HW_VAR_INIT_TX_RATE, - HW_VAR_TX_RATE_REG, - HW_VAR_EFUSE_USAGE, - HW_VAR_EFUSE_BYTES, - HW_VAR_AUTOLOAD_STATUS, - HW_VAR_RF_2R_DISABLE, - HW_VAR_SET_RPWM, - HW_VAR_H2C_FW_PWRMODE, - HW_VAR_H2C_FW_JOINBSSRPT, - HW_VAR_H2C_FW_MEDIASTATUSRPT, - HW_VAR_H2C_FW_P2P_PS_OFFLOAD, - HW_VAR_FW_PSMODE_STATUS, - HW_VAR_INIT_RTS_RATE, - HW_VAR_RESUME_CLK_ON, - HW_VAR_FW_LPS_ACTION, - HW_VAR_1X1_RECV_COMBINE, - HW_VAR_STOP_SEND_BEACON, - HW_VAR_TSF_TIMER, - HW_VAR_IO_CMD, - - HW_VAR_RF_RECOVERY, - HW_VAR_H2C_FW_UPDATE_GTK, - HW_VAR_WF_MASK, - HW_VAR_WF_CRC, - HW_VAR_WF_IS_MAC_ADDR, - HW_VAR_H2C_FW_OFFLOAD, - HW_VAR_RESET_WFCRC, - - HW_VAR_HANDLE_FW_C2H, - HW_VAR_DL_FW_RSVD_PAGE, - HW_VAR_AID, - HW_VAR_HW_SEQ_ENABLE, - HW_VAR_CORRECT_TSF, - HW_VAR_BCN_VALID, - HW_VAR_FWLPS_RF_ON, - HW_VAR_DUAL_TSF_RST, - HW_VAR_SWITCH_EPHY_WoWLAN, - HW_VAR_INT_MIGRATION, - HW_VAR_INT_AC, - HW_VAR_RF_TIMING, - - HAL_DEF_WOWLAN, - HW_VAR_MRC, - HW_VAR_KEEP_ALIVE, - HW_VAR_NAV_UPPER, - - HW_VAR_MGT_FILTER, - HW_VAR_CTRL_FILTER, - HW_VAR_DATA_FILTER, -}; - -enum rt_media_status { - RT_MEDIA_DISCONNECT = 0, - RT_MEDIA_CONNECT = 1 -}; - -enum rt_oem_id { - RT_CID_DEFAULT = 0, - RT_CID_8187_ALPHA0 = 1, - RT_CID_8187_SERCOMM_PS = 2, - RT_CID_8187_HW_LED = 3, - RT_CID_8187_NETGEAR = 4, - RT_CID_WHQL = 5, - RT_CID_819X_CAMEO = 6, - RT_CID_819X_RUNTOP = 7, - RT_CID_819X_SENAO = 8, - RT_CID_TOSHIBA = 9, - RT_CID_819X_NETCORE = 10, - RT_CID_NETTRONIX = 11, - RT_CID_DLINK = 12, - RT_CID_PRONET = 13, - RT_CID_COREGA = 14, - RT_CID_819X_ALPHA = 15, - RT_CID_819X_SITECOM = 16, - RT_CID_CCX = 17, - RT_CID_819X_LENOVO = 18, - RT_CID_819X_QMI = 19, - RT_CID_819X_EDIMAX_BELKIN = 20, - RT_CID_819X_SERCOMM_BELKIN = 21, - RT_CID_819X_CAMEO1 = 22, - RT_CID_819X_MSI = 23, - RT_CID_819X_ACER = 24, - RT_CID_819X_HP = 27, - RT_CID_819X_CLEVO = 28, - RT_CID_819X_ARCADYAN_BELKIN = 29, - RT_CID_819X_SAMSUNG = 30, - RT_CID_819X_WNC_COREGA = 31, - RT_CID_819X_FOXCOON = 32, - RT_CID_819X_DELL = 33, - RT_CID_819X_PRONETS = 34, - RT_CID_819X_EDIMAX_ASUS = 35, - RT_CID_NETGEAR = 36, - RT_CID_PLANEX = 37, - RT_CID_CC_C = 38, -}; - -enum hw_descs { - HW_DESC_OWN, - HW_DESC_RXOWN, - HW_DESC_TX_NEXTDESC_ADDR, - HW_DESC_TXBUFF_ADDR, - HW_DESC_RXBUFF_ADDR, - HW_DESC_RXPKT_LEN, - HW_DESC_RXERO, - HW_DESC_RX_PREPARE, -}; - -enum prime_sc { - PRIME_CHNL_OFFSET_DONT_CARE = 0, - PRIME_CHNL_OFFSET_LOWER = 1, - PRIME_CHNL_OFFSET_UPPER = 2, -}; - -enum rf_type { - RF_1T1R = 0, - RF_1T2R = 1, - RF_2T2R = 2, - RF_2T2R_GREEN = 3, -}; - -enum ht_channel_width { - HT_CHANNEL_WIDTH_20 = 0, - HT_CHANNEL_WIDTH_20_40 = 1, - HT_CHANNEL_WIDTH_80 = 2, -}; - -/* Ref: 802.11i sepc D10.0 7.3.2.25.1 -Cipher Suites Encryption Algorithms */ -enum rt_enc_alg { - NO_ENCRYPTION = 0, - WEP40_ENCRYPTION = 1, - TKIP_ENCRYPTION = 2, - RSERVED_ENCRYPTION = 3, - AESCCMP_ENCRYPTION = 4, - WEP104_ENCRYPTION = 5, - AESCMAC_ENCRYPTION = 6, /*IEEE802.11w */ -}; - -enum rtl_hal_state { - _HAL_STATE_STOP = 0, - _HAL_STATE_START = 1, -}; - -enum rtl_desc92_rate { - DESC_RATE1M = 0x00, - DESC_RATE2M = 0x01, - DESC_RATE5_5M = 0x02, - DESC_RATE11M = 0x03, - - DESC_RATE6M = 0x04, - DESC_RATE9M = 0x05, - DESC_RATE12M = 0x06, - DESC_RATE18M = 0x07, - DESC_RATE24M = 0x08, - DESC_RATE36M = 0x09, - DESC_RATE48M = 0x0a, - DESC_RATE54M = 0x0b, - - DESC_RATEMCS0 = 0x0c, - DESC_RATEMCS1 = 0x0d, - DESC_RATEMCS2 = 0x0e, - DESC_RATEMCS3 = 0x0f, - DESC_RATEMCS4 = 0x10, - DESC_RATEMCS5 = 0x11, - DESC_RATEMCS6 = 0x12, - DESC_RATEMCS7 = 0x13, - DESC_RATEMCS8 = 0x14, - DESC_RATEMCS9 = 0x15, - DESC_RATEMCS10 = 0x16, - DESC_RATEMCS11 = 0x17, - DESC_RATEMCS12 = 0x18, - DESC_RATEMCS13 = 0x19, - DESC_RATEMCS14 = 0x1a, - DESC_RATEMCS15 = 0x1b, - DESC_RATEMCS15_SG = 0x1c, - DESC_RATEMCS32 = 0x20, - - DESC_RATEVHT1SS_MCS0 = 0x2c, - DESC_RATEVHT1SS_MCS1 = 0x2d, - DESC_RATEVHT1SS_MCS2 = 0x2e, - DESC_RATEVHT1SS_MCS3 = 0x2f, - DESC_RATEVHT1SS_MCS4 = 0x30, - DESC_RATEVHT1SS_MCS5 = 0x31, - DESC_RATEVHT1SS_MCS6 = 0x32, - DESC_RATEVHT1SS_MCS7 = 0x33, - DESC_RATEVHT1SS_MCS8 = 0x34, - DESC_RATEVHT1SS_MCS9 = 0x35, - DESC_RATEVHT2SS_MCS0 = 0x36, - DESC_RATEVHT2SS_MCS1 = 0x37, - DESC_RATEVHT2SS_MCS2 = 0x38, - DESC_RATEVHT2SS_MCS3 = 0x39, - DESC_RATEVHT2SS_MCS4 = 0x3a, - DESC_RATEVHT2SS_MCS5 = 0x3b, - DESC_RATEVHT2SS_MCS6 = 0x3c, - DESC_RATEVHT2SS_MCS7 = 0x3d, - DESC_RATEVHT2SS_MCS8 = 0x3e, - DESC_RATEVHT2SS_MCS9 = 0x3f, -}; - -enum rtl_var_map { - /*reg map */ - SYS_ISO_CTRL = 0, - SYS_FUNC_EN, - SYS_CLK, - MAC_RCR_AM, - MAC_RCR_AB, - MAC_RCR_ACRC32, - MAC_RCR_ACF, - MAC_RCR_AAP, - MAC_HIMR, - MAC_HIMRE, - MAC_HSISR, - - /*efuse map */ - EFUSE_TEST, - EFUSE_CTRL, - EFUSE_CLK, - EFUSE_CLK_CTRL, - EFUSE_PWC_EV12V, - EFUSE_FEN_ELDR, - EFUSE_LOADER_CLK_EN, - EFUSE_ANA8M, - EFUSE_HWSET_MAX_SIZE, - EFUSE_MAX_SECTION_MAP, - EFUSE_REAL_CONTENT_SIZE, - EFUSE_OOB_PROTECT_BYTES_LEN, - EFUSE_ACCESS, - - /*CAM map */ - RWCAM, - WCAMI, - RCAMO, - CAMDBG, - SECR, - SEC_CAM_NONE, - SEC_CAM_WEP40, - SEC_CAM_TKIP, - SEC_CAM_AES, - SEC_CAM_WEP104, - - /*IMR map */ - RTL_IMR_BCNDMAINT6, /*Beacon DMA Interrupt 6 */ - RTL_IMR_BCNDMAINT5, /*Beacon DMA Interrupt 5 */ - RTL_IMR_BCNDMAINT4, /*Beacon DMA Interrupt 4 */ - RTL_IMR_BCNDMAINT3, /*Beacon DMA Interrupt 3 */ - RTL_IMR_BCNDMAINT2, /*Beacon DMA Interrupt 2 */ - RTL_IMR_BCNDMAINT1, /*Beacon DMA Interrupt 1 */ - RTL_IMR_BCNDOK8, /*Beacon Queue DMA OK Interrup 8 */ - RTL_IMR_BCNDOK7, /*Beacon Queue DMA OK Interrup 7 */ - RTL_IMR_BCNDOK6, /*Beacon Queue DMA OK Interrup 6 */ - RTL_IMR_BCNDOK5, /*Beacon Queue DMA OK Interrup 5 */ - RTL_IMR_BCNDOK4, /*Beacon Queue DMA OK Interrup 4 */ - RTL_IMR_BCNDOK3, /*Beacon Queue DMA OK Interrup 3 */ - RTL_IMR_BCNDOK2, /*Beacon Queue DMA OK Interrup 2 */ - RTL_IMR_BCNDOK1, /*Beacon Queue DMA OK Interrup 1 */ - RTL_IMR_TIMEOUT2, /*Timeout interrupt 2 */ - RTL_IMR_TIMEOUT1, /*Timeout interrupt 1 */ - RTL_IMR_TXFOVW, /*Transmit FIFO Overflow */ - RTL_IMR_PSTIMEOUT, /*Power save time out interrupt */ - RTL_IMR_BCNINT, /*Beacon DMA Interrupt 0 */ - RTL_IMR_RXFOVW, /*Receive FIFO Overflow */ - RTL_IMR_RDU, /*Receive Descriptor Unavailable */ - RTL_IMR_ATIMEND, /*For 92C,ATIM Window End Interrupt */ - RTL_IMR_BDOK, /*Beacon Queue DMA OK Interrup */ - RTL_IMR_HIGHDOK, /*High Queue DMA OK Interrupt */ - RTL_IMR_COMDOK, /*Command Queue DMA OK Interrupt*/ - RTL_IMR_TBDOK, /*Transmit Beacon OK interrup */ - RTL_IMR_MGNTDOK, /*Management Queue DMA OK Interrupt */ - RTL_IMR_TBDER, /*For 92C,Transmit Beacon Error Interrupt */ - RTL_IMR_BKDOK, /*AC_BK DMA OK Interrupt */ - RTL_IMR_BEDOK, /*AC_BE DMA OK Interrupt */ - RTL_IMR_VIDOK, /*AC_VI DMA OK Interrupt */ - RTL_IMR_VODOK, /*AC_VO DMA Interrupt */ - RTL_IMR_ROK, /*Receive DMA OK Interrupt */ - RTL_IMR_HSISR_IND, /*HSISR Interrupt*/ - RTL_IBSS_INT_MASKS, /*(RTL_IMR_BCNINT | RTL_IMR_TBDOK | - * RTL_IMR_TBDER) */ - RTL_IMR_C2HCMD, /*fw interrupt*/ - - /*CCK Rates, TxHT = 0 */ - RTL_RC_CCK_RATE1M, - RTL_RC_CCK_RATE2M, - RTL_RC_CCK_RATE5_5M, - RTL_RC_CCK_RATE11M, - - /*OFDM Rates, TxHT = 0 */ - RTL_RC_OFDM_RATE6M, - RTL_RC_OFDM_RATE9M, - RTL_RC_OFDM_RATE12M, - RTL_RC_OFDM_RATE18M, - RTL_RC_OFDM_RATE24M, - RTL_RC_OFDM_RATE36M, - RTL_RC_OFDM_RATE48M, - RTL_RC_OFDM_RATE54M, - - RTL_RC_HT_RATEMCS7, - RTL_RC_HT_RATEMCS15, - - RTL_RC_VHT_RATE_1SS_MCS7, - RTL_RC_VHT_RATE_1SS_MCS8, - RTL_RC_VHT_RATE_1SS_MCS9, - RTL_RC_VHT_RATE_2SS_MCS7, - RTL_RC_VHT_RATE_2SS_MCS8, - RTL_RC_VHT_RATE_2SS_MCS9, - - /*keep it last */ - RTL_VAR_MAP_MAX, -}; - -/*Firmware PS mode for control LPS.*/ -enum _fw_ps_mode { - FW_PS_ACTIVE_MODE = 0, - FW_PS_MIN_MODE = 1, - FW_PS_MAX_MODE = 2, - FW_PS_DTIM_MODE = 3, - FW_PS_VOIP_MODE = 4, - FW_PS_UAPSD_WMM_MODE = 5, - FW_PS_UAPSD_MODE = 6, - FW_PS_IBSS_MODE = 7, - FW_PS_WWLAN_MODE = 8, - FW_PS_PM_Radio_Off = 9, - FW_PS_PM_Card_Disable = 10, -}; - -enum rt_psmode { - EACTIVE, /*Active/Continuous access. */ - EMAXPS, /*Max power save mode. */ - EFASTPS, /*Fast power save mode. */ - EAUTOPS, /*Auto power save mode. */ -}; - -/*LED related.*/ -enum led_ctl_mode { - LED_CTL_POWER_ON = 1, - LED_CTL_LINK = 2, - LED_CTL_NO_LINK = 3, - LED_CTL_TX = 4, - LED_CTL_RX = 5, - LED_CTL_SITE_SURVEY = 6, - LED_CTL_POWER_OFF = 7, - LED_CTL_START_TO_LINK = 8, - LED_CTL_START_WPS = 9, - LED_CTL_STOP_WPS = 10, -}; - -enum rtl_led_pin { - LED_PIN_GPIO0, - LED_PIN_LED0, - LED_PIN_LED1, - LED_PIN_LED2 -}; - -/*QoS related.*/ -/*acm implementation method.*/ -enum acm_method { - eAcmWay0_SwAndHw = 0, - eAcmWay1_HW = 1, - EACMWAY2_SW = 2, -}; - -enum macphy_mode { - SINGLEMAC_SINGLEPHY = 0, - DUALMAC_DUALPHY, - DUALMAC_SINGLEPHY, -}; - -enum band_type { - BAND_ON_2_4G = 0, - BAND_ON_5G, - BAND_ON_BOTH, - BANDMAX -}; - -/*aci/aifsn Field. -Ref: WMM spec 2.2.2: WME Parameter Element, p.12.*/ -union aci_aifsn { - u8 char_data; - - struct { - u8 aifsn:4; - u8 acm:1; - u8 aci:2; - u8 reserved:1; - } f; /* Field */ -}; - -/*mlme related.*/ -enum wireless_mode { - WIRELESS_MODE_UNKNOWN = 0x00, - WIRELESS_MODE_A = 0x01, - WIRELESS_MODE_B = 0x02, - WIRELESS_MODE_G = 0x04, - WIRELESS_MODE_AUTO = 0x08, - WIRELESS_MODE_N_24G = 0x10, - WIRELESS_MODE_N_5G = 0x20, - WIRELESS_MODE_AC_5G = 0x40, - WIRELESS_MODE_AC_24G = 0x80, - WIRELESS_MODE_AC_ONLY = 0x100, - WIRELESS_MODE_MAX = 0x800 -}; - -#define IS_WIRELESS_MODE_A(wirelessmode) \ - (wirelessmode == WIRELESS_MODE_A) -#define IS_WIRELESS_MODE_B(wirelessmode) \ - (wirelessmode == WIRELESS_MODE_B) -#define IS_WIRELESS_MODE_G(wirelessmode) \ - (wirelessmode == WIRELESS_MODE_G) -#define IS_WIRELESS_MODE_N_24G(wirelessmode) \ - (wirelessmode == WIRELESS_MODE_N_24G) -#define IS_WIRELESS_MODE_N_5G(wirelessmode) \ - (wirelessmode == WIRELESS_MODE_N_5G) - -enum ratr_table_mode { - RATR_INX_WIRELESS_NGB = 0, - RATR_INX_WIRELESS_NG = 1, - RATR_INX_WIRELESS_NB = 2, - RATR_INX_WIRELESS_N = 3, - RATR_INX_WIRELESS_GB = 4, - RATR_INX_WIRELESS_G = 5, - RATR_INX_WIRELESS_B = 6, - RATR_INX_WIRELESS_MC = 7, - RATR_INX_WIRELESS_A = 8, - RATR_INX_WIRELESS_AC_5N = 8, - RATR_INX_WIRELESS_AC_24N = 9, -}; - -enum rtl_link_state { - MAC80211_NOLINK = 0, - MAC80211_LINKING = 1, - MAC80211_LINKED = 2, - MAC80211_LINKED_SCANNING = 3, -}; - -enum act_category { - ACT_CAT_QOS = 1, - ACT_CAT_DLS = 2, - ACT_CAT_BA = 3, - ACT_CAT_HT = 7, - ACT_CAT_WMM = 17, -}; - -enum ba_action { - ACT_ADDBAREQ = 0, - ACT_ADDBARSP = 1, - ACT_DELBA = 2, -}; - -enum rt_polarity_ctl { - RT_POLARITY_LOW_ACT = 0, - RT_POLARITY_HIGH_ACT = 1, -}; - -/* After 8188E, we use V2 reason define. 88C/8723A use V1 reason. */ -enum fw_wow_reason_v2 { - FW_WOW_V2_PTK_UPDATE_EVENT = 0x01, - FW_WOW_V2_GTK_UPDATE_EVENT = 0x02, - FW_WOW_V2_DISASSOC_EVENT = 0x04, - FW_WOW_V2_DEAUTH_EVENT = 0x08, - FW_WOW_V2_FW_DISCONNECT_EVENT = 0x10, - FW_WOW_V2_MAGIC_PKT_EVENT = 0x21, - FW_WOW_V2_UNICAST_PKT_EVENT = 0x22, - FW_WOW_V2_PATTERN_PKT_EVENT = 0x23, - FW_WOW_V2_RTD3_SSID_MATCH_EVENT = 0x24, - FW_WOW_V2_REALWOW_V2_WAKEUPPKT = 0x30, - FW_WOW_V2_REALWOW_V2_ACKLOST = 0x31, - FW_WOW_V2_REASON_MAX = 0xff, -}; - -enum wolpattern_type { - UNICAST_PATTERN = 0, - MULTICAST_PATTERN = 1, - BROADCAST_PATTERN = 2, - DONT_CARE_DA = 3, - UNKNOWN_TYPE = 4, -}; - -struct octet_string { - u8 *octet; - u16 length; -}; - -struct rtl_hdr_3addr { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - __le16 seq_ctl; - u8 payload[0]; -} __packed; - -struct rtl_info_element { - u8 id; - u8 len; - u8 data[0]; -} __packed; - -struct rtl_probe_rsp { - struct rtl_hdr_3addr header; - u32 time_stamp[2]; - __le16 beacon_interval; - __le16 capability; - /*SSID, supported rates, FH params, DS params, - CF params, IBSS params, TIM (if beacon), RSN */ - struct rtl_info_element info_element[0]; -} __packed; - -/*LED related.*/ -/*ledpin Identify how to implement this SW led.*/ -struct rtl_led { - void *hw; - enum rtl_led_pin ledpin; - bool ledon; -}; - -struct rtl_led_ctl { - bool led_opendrain; - struct rtl_led sw_led0; - struct rtl_led sw_led1; -}; - -struct rtl_qos_parameters { - __le16 cw_min; - __le16 cw_max; - u8 aifs; - u8 flag; - __le16 tx_op; -} __packed; - -struct rt_smooth_data { - u32 elements[100]; /*array to store values */ - u32 index; /*index to current array to store */ - u32 total_num; /*num of valid elements */ - u32 total_val; /*sum of valid elements */ -}; - -struct false_alarm_statistics { - u32 cnt_parity_fail; - u32 cnt_rate_illegal; - u32 cnt_crc8_fail; - u32 cnt_mcs_fail; - u32 cnt_fast_fsync_fail; - u32 cnt_sb_search_fail; - u32 cnt_ofdm_fail; - u32 cnt_cck_fail; - u32 cnt_all; - u32 cnt_ofdm_cca; - u32 cnt_cck_cca; - u32 cnt_cca_all; - u32 cnt_bw_usc; - u32 cnt_bw_lsc; -}; - -struct init_gain { - u8 xaagccore1; - u8 xbagccore1; - u8 xcagccore1; - u8 xdagccore1; - u8 cca; - -}; - -struct wireless_stats { - unsigned long txbytesunicast; - unsigned long txbytesmulticast; - unsigned long txbytesbroadcast; - unsigned long rxbytesunicast; - - long rx_snr_db[4]; - /*Correct smoothed ss in Dbm, only used - in driver to report real power now. */ - long recv_signal_power; - long signal_quality; - long last_sigstrength_inpercent; - - u32 rssi_calculate_cnt; - u32 pwdb_all_cnt; - - /*Transformed, in dbm. Beautified signal - strength for UI, not correct. */ - long signal_strength; - - u8 rx_rssi_percentage[4]; - u8 rx_evm_dbm[4]; - u8 rx_evm_percentage[2]; - - u16 rx_cfo_short[4]; - u16 rx_cfo_tail[4]; - - struct rt_smooth_data ui_rssi; - struct rt_smooth_data ui_link_quality; -}; - -struct rate_adaptive { - u8 rate_adaptive_disabled; - u8 ratr_state; - u16 reserve; - - u32 high_rssi_thresh_for_ra; - u32 high2low_rssi_thresh_for_ra; - u8 low2high_rssi_thresh_for_ra40m; - u32 low_rssi_thresh_for_ra40m; - u8 low2high_rssi_thresh_for_ra20m; - u32 low_rssi_thresh_for_ra20m; - u32 upper_rssi_threshold_ratr; - u32 middleupper_rssi_threshold_ratr; - u32 middle_rssi_threshold_ratr; - u32 middlelow_rssi_threshold_ratr; - u32 low_rssi_threshold_ratr; - u32 ultralow_rssi_threshold_ratr; - u32 low_rssi_threshold_ratr_40m; - u32 low_rssi_threshold_ratr_20m; - u8 ping_rssi_enable; - u32 ping_rssi_ratr; - u32 ping_rssi_thresh_for_ra; - u32 last_ratr; - u8 pre_ratr_state; - u8 ldpc_thres; - bool use_ldpc; - bool lower_rts_rate; - bool is_special_data; -}; - -struct regd_pair_mapping { - u16 reg_dmnenum; - u16 reg_5ghz_ctl; - u16 reg_2ghz_ctl; -}; - -struct dynamic_primary_cca { - u8 pricca_flag; - u8 intf_flag; - u8 intf_type; - u8 dup_rts_flag; - u8 monitor_flag; - u8 ch_offset; - u8 mf_state; -}; - -struct rtl_regulatory { - char alpha2[2]; - u16 country_code; - u16 max_power_level; - u32 tp_scale; - u16 current_rd; - u16 current_rd_ext; - int16_t power_limit; - struct regd_pair_mapping *regpair; -}; - -struct rtl_rfkill { - bool rfkill_state; /*0 is off, 1 is on */ -}; - -/*for P2P PS**/ -#define P2P_MAX_NOA_NUM 2 - -enum p2p_role { - P2P_ROLE_DISABLE = 0, - P2P_ROLE_DEVICE = 1, - P2P_ROLE_CLIENT = 2, - P2P_ROLE_GO = 3 -}; - -enum p2p_ps_state { - P2P_PS_DISABLE = 0, - P2P_PS_ENABLE = 1, - P2P_PS_SCAN = 2, - P2P_PS_SCAN_DONE = 3, - P2P_PS_ALLSTASLEEP = 4, /* for P2P GO */ -}; - -enum p2p_ps_mode { - P2P_PS_NONE = 0, - P2P_PS_CTWINDOW = 1, - P2P_PS_NOA = 2, - P2P_PS_MIX = 3, /* CTWindow and NoA */ -}; - -struct rtl_p2p_ps_info { - enum p2p_ps_mode p2p_ps_mode; /* indicate p2p ps mode */ - enum p2p_ps_state p2p_ps_state; /* indicate p2p ps state */ - u8 noa_index; /* Identifies instance of Notice of Absence timing. */ - /* Client traffic window. A period of time in TU after TBTT. */ - u8 ctwindow; - u8 opp_ps; /* opportunistic power save. */ - u8 noa_num; /* number of NoA descriptor in P2P IE. */ - /* Count for owner, Type of client. */ - u8 noa_count_type[P2P_MAX_NOA_NUM]; - /* Max duration for owner, preferred or min acceptable duration - * for client. - */ - u32 noa_duration[P2P_MAX_NOA_NUM]; - /* Length of interval for owner, preferred or max acceptable intervali - * of client. - */ - u32 noa_interval[P2P_MAX_NOA_NUM]; - /* schedule in terms of the lower 4 bytes of the TSF timer. */ - u32 noa_start_time[P2P_MAX_NOA_NUM]; -}; - -struct p2p_ps_offload_t { - u8 offload_en:1; - u8 role:1; /* 1: Owner, 0: Client */ - u8 ctwindow_en:1; - u8 noa0_en:1; - u8 noa1_en:1; - u8 allstasleep:1; - u8 discovery:1; - u8 reserved:1; -}; - -#define IQK_MATRIX_REG_NUM 8 -#define IQK_MATRIX_SETTINGS_NUM (1 + 24 + 21) - -struct iqk_matrix_regs { - bool iqk_done; - long value[1][IQK_MATRIX_REG_NUM]; -}; - -struct phy_parameters { - u16 length; - u32 *pdata; -}; - -enum hw_param_tab_index { - PHY_REG_2T, - PHY_REG_1T, - PHY_REG_PG, - RADIOA_2T, - RADIOB_2T, - RADIOA_1T, - RADIOB_1T, - MAC_REG, - AGCTAB_2T, - AGCTAB_1T, - MAX_TAB -}; - -struct rtl_phy { - struct bb_reg_def phyreg_def[4]; /*Radio A/B/C/D */ - struct init_gain initgain_backup; - enum io_type current_io_type; - - u8 rf_mode; - u8 rf_type; - u8 current_chan_bw; - u8 set_bwmode_inprogress; - u8 sw_chnl_inprogress; - u8 sw_chnl_stage; - u8 sw_chnl_step; - u8 current_channel; - u8 h2c_box_num; - u8 set_io_inprogress; - u8 lck_inprogress; - - /* record for power tracking */ - s32 reg_e94; - s32 reg_e9c; - s32 reg_ea4; - s32 reg_eac; - s32 reg_eb4; - s32 reg_ebc; - s32 reg_ec4; - s32 reg_ecc; - u8 rfpienable; - u8 reserve_0; - u16 reserve_1; - u32 reg_c04, reg_c08, reg_874; - u32 adda_backup[16]; - u32 iqk_mac_backup[IQK_MAC_REG_NUM]; - u32 iqk_bb_backup[10]; - bool iqk_initialized; - - bool rfpath_rx_enable[MAX_RF_PATH]; - u8 reg_837; - /* Dual mac */ - bool need_iqk; - struct iqk_matrix_regs iqk_matrix[IQK_MATRIX_SETTINGS_NUM]; - - bool rfpi_enable; - bool iqk_in_progress; - - u8 pwrgroup_cnt; - u8 cck_high_power; - /* this is for 88E & 8723A */ - u32 mcs_txpwrlevel_origoffset[MAX_PG_GROUP][16]; - /* MAX_PG_GROUP groups of pwr diff by rates */ - u32 mcs_offset[MAX_PG_GROUP][16]; - u32 tx_power_by_rate_offset[TX_PWR_BY_RATE_NUM_BAND] - [TX_PWR_BY_RATE_NUM_RF] - [TX_PWR_BY_RATE_NUM_RF] - [TX_PWR_BY_RATE_NUM_SECTION]; - u8 txpwr_by_rate_base_24g[TX_PWR_BY_RATE_NUM_RF] - [TX_PWR_BY_RATE_NUM_RF] - [MAX_BASE_NUM_IN_PHY_REG_PG_24G]; - u8 txpwr_by_rate_base_5g[TX_PWR_BY_RATE_NUM_RF] - [TX_PWR_BY_RATE_NUM_RF] - [MAX_BASE_NUM_IN_PHY_REG_PG_5G]; - u8 default_initialgain[4]; - - /* the current Tx power level */ - u8 cur_cck_txpwridx; - u8 cur_ofdm24g_txpwridx; - u8 cur_bw20_txpwridx; - u8 cur_bw40_txpwridx; - - char txpwr_limit_2_4g[MAX_REGULATION_NUM] - [MAX_2_4G_BANDWITH_NUM] - [MAX_RATE_SECTION_NUM] - [CHANNEL_MAX_NUMBER_2G] - [MAX_RF_PATH_NUM]; - char txpwr_limit_5g[MAX_REGULATION_NUM] - [MAX_5G_BANDWITH_NUM] - [MAX_RATE_SECTION_NUM] - [CHANNEL_MAX_NUMBER_5G] - [MAX_RF_PATH_NUM]; - - u32 rfreg_chnlval[2]; - bool apk_done; - u32 reg_rf3c[2]; /* pathA / pathB */ - - u32 backup_rf_0x1a;/*92ee*/ - /* bfsync */ - u8 framesync; - u32 framesync_c34; - - u8 num_total_rfpath; - struct phy_parameters hwparam_tables[MAX_TAB]; - u16 rf_pathmap; - - u8 hw_rof_enable; /*Enable GPIO[9] as WL RF HW PDn source*/ - enum rt_polarity_ctl polarity_ctl; -}; - -#define MAX_TID_COUNT 9 -#define RTL_AGG_STOP 0 -#define RTL_AGG_PROGRESS 1 -#define RTL_AGG_START 2 -#define RTL_AGG_OPERATIONAL 3 -#define RTL_AGG_OFF 0 -#define RTL_AGG_ON 1 -#define RTL_RX_AGG_START 1 -#define RTL_RX_AGG_STOP 0 -#define RTL_AGG_EMPTYING_HW_QUEUE_ADDBA 2 -#define RTL_AGG_EMPTYING_HW_QUEUE_DELBA 3 - -struct rtl_ht_agg { - u16 txq_id; - u16 wait_for_ba; - u16 start_idx; - u64 bitmap; - u32 rate_n_flags; - u8 agg_state; - u8 rx_agg_state; -}; - -struct rssi_sta { - long undec_sm_pwdb; - long undec_sm_cck; -}; - -struct rtl_tid_data { - u16 seq_number; - struct rtl_ht_agg agg; -}; - -struct rtl_sta_info { - struct list_head list; - u8 ratr_index; - u8 wireless_mode; - u8 mimo_ps; - u8 mac_addr[ETH_ALEN]; - struct rtl_tid_data tids[MAX_TID_COUNT]; - - /* just used for ap adhoc or mesh*/ - struct rssi_sta rssi_stat; -} __packed; - -struct rtl_priv; -struct rtl_io { - struct device *dev; - struct mutex bb_mutex; - - /*PCI MEM map */ - unsigned long pci_mem_end; /*shared mem end */ - unsigned long pci_mem_start; /*shared mem start */ - - /*PCI IO map */ - unsigned long pci_base_addr; /*device I/O address */ - - void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val); - void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val); - void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val); - void (*writeN_sync) (struct rtl_priv *rtlpriv, u32 addr, void *buf, - u16 len); - - u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr); - u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr); - u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr); - -}; - -struct rtl_mac { - u8 mac_addr[ETH_ALEN]; - u8 mac80211_registered; - u8 beacon_enabled; - - u32 tx_ss_num; - u32 rx_ss_num; - - struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; - struct ieee80211_hw *hw; - struct ieee80211_vif *vif; - enum nl80211_iftype opmode; - - /*Probe Beacon management */ - struct rtl_tid_data tids[MAX_TID_COUNT]; - enum rtl_link_state link_state; - - int n_channels; - int n_bitrates; - - bool offchan_delay; - u8 p2p; /*using p2p role*/ - bool p2p_in_use; - - /*filters */ - u32 rx_conf; - u16 rx_mgt_filter; - u16 rx_ctrl_filter; - u16 rx_data_filter; - - bool act_scanning; - u8 cnt_after_linked; - bool skip_scan; - - /* early mode */ - /* skb wait queue */ - struct sk_buff_head skb_waitq[MAX_TID_COUNT]; - - u8 ht_stbc_cap; - u8 ht_cur_stbc; - - /*vht support*/ - u8 vht_enable; - u8 bw_80; - u8 vht_cur_ldpc; - u8 vht_cur_stbc; - u8 vht_stbc_cap; - u8 vht_ldpc_cap; - - /*RDG*/ - bool rdg_en; - - /*AP*/ - u8 bssid[ETH_ALEN] __aligned(2); - u32 vendor; - u8 mcs[16]; /* 16 bytes mcs for HT rates. */ - u32 basic_rates; /* b/g rates */ - u8 ht_enable; - u8 sgi_40; - u8 sgi_20; - u8 bw_40; - u16 mode; /* wireless mode */ - u8 slot_time; - u8 short_preamble; - u8 use_cts_protect; - u8 cur_40_prime_sc; - u8 cur_40_prime_sc_bk; - u8 cur_80_prime_sc; - u64 tsf; - u8 retry_short; - u8 retry_long; - u16 assoc_id; - bool hiddenssid; - - /*IBSS*/ - int beacon_interval; - - /*AMPDU*/ - u8 min_space_cfg; /*For Min spacing configurations */ - u8 max_mss_density; - u8 current_ampdu_factor; - u8 current_ampdu_density; - - /*QOS & EDCA */ - struct ieee80211_tx_queue_params edca_param[RTL_MAC80211_NUM_QUEUE]; - struct rtl_qos_parameters ac[AC_MAX]; - - /* counters */ - u64 last_txok_cnt; - u64 last_rxok_cnt; - u32 last_bt_edca_ul; - u32 last_bt_edca_dl; -}; - -struct btdm_8723 { - bool all_off; - bool agc_table_en; - bool adc_back_off_on; - bool b2_ant_hid_en; - bool low_penalty_rate_adaptive; - bool rf_rx_lpf_shrink; - bool reject_aggre_pkt; - bool tra_tdma_on; - u8 tra_tdma_nav; - u8 tra_tdma_ant; - bool tdma_on; - u8 tdma_ant; - u8 tdma_nav; - u8 tdma_dac_swing; - u8 fw_dac_swing_lvl; - bool ps_tdma_on; - u8 ps_tdma_byte[5]; - bool pta_on; - u32 val_0x6c0; - u32 val_0x6c8; - u32 val_0x6cc; - bool sw_dac_swing_on; - u32 sw_dac_swing_lvl; - u32 wlan_act_hi; - u32 wlan_act_lo; - u32 bt_retry_index; - bool dec_bt_pwr; - bool ignore_wlan_act; -}; - -struct bt_coexist_8723 { - u32 high_priority_tx; - u32 high_priority_rx; - u32 low_priority_tx; - u32 low_priority_rx; - u8 c2h_bt_info; - bool c2h_bt_info_req_sent; - bool c2h_bt_inquiry_page; - u32 bt_inq_page_start_time; - u8 bt_retry_cnt; - u8 c2h_bt_info_original; - u8 bt_inquiry_page_cnt; - struct btdm_8723 btdm; -}; - -struct rtl_hal { - struct ieee80211_hw *hw; - bool driver_is_goingto_unload; - bool up_first_time; - bool first_init; - bool being_init_adapter; - bool bbrf_ready; - bool mac_func_enable; - bool pre_edcca_enable; - struct bt_coexist_8723 hal_coex_8723; - - enum intf_type interface; - u16 hw_type; /*92c or 92d or 92s and so on */ - u8 ic_class; - u8 oem_id; - u32 version; /*version of chip */ - u8 state; /*stop 0, start 1 */ - u8 board_type; - u8 external_pa; - - u8 pa_mode; - u8 pa_type_2g; - u8 pa_type_5g; - u8 lna_type_2g; - u8 lna_type_5g; - u8 external_pa_2g; - u8 external_lna_2g; - u8 external_pa_5g; - u8 external_lna_5g; - u8 rfe_type; - - /*firmware */ - u32 fwsize; - u8 *pfirmware; - u16 fw_version; - u16 fw_subversion; - bool h2c_setinprogress; - u8 last_hmeboxnum; - bool fw_ready; - /*Reserve page start offset except beacon in TxQ. */ - u8 fw_rsvdpage_startoffset; - u8 h2c_txcmd_seq; - u8 current_ra_rate; - - /* FW Cmd IO related */ - u16 fwcmd_iomap; - u32 fwcmd_ioparam; - bool set_fwcmd_inprogress; - u8 current_fwcmd_io; - - struct p2p_ps_offload_t p2p_ps_offload; - bool fw_clk_change_in_progress; - bool allow_sw_to_change_hwclc; - u8 fw_ps_state; - /**/ - bool driver_going2unload; - - /*AMPDU init min space*/ - u8 minspace_cfg; /*For Min spacing configurations */ - - /* Dual mac */ - enum macphy_mode macphymode; - enum band_type current_bandtype; /* 0:2.4G, 1:5G */ - enum band_type current_bandtypebackup; - enum band_type bandset; - /* dual MAC 0--Mac0 1--Mac1 */ - u32 interfaceindex; - /* just for DualMac S3S4 */ - u8 macphyctl_reg; - bool earlymode_enable; - u8 max_earlymode_num; - /* Dual mac*/ - bool during_mac0init_radiob; - bool during_mac1init_radioa; - bool reloadtxpowerindex; - /* True if IMR or IQK have done - for 2.4G in scan progress */ - bool load_imrandiqk_setting_for2g; - - bool disable_amsdu_8k; - bool master_of_dmsp; - bool slave_of_dmsp; - - u16 rx_tag;/*for 92ee*/ - u8 rts_en; - - /*for wowlan*/ - bool wow_enable; - bool enter_pnp_sleep; - bool wake_from_pnp_sleep; - bool wow_enabled; - __kernel_time_t last_suspend_sec; - u32 wowlan_fwsize; - u8 *wowlan_firmware; - - u8 hw_rof_enable; /*Enable GPIO[9] as WL RF HW PDn source*/ - - bool real_wow_v2_enable; - bool re_init_llt_table; -}; - -struct rtl_security { - /*default 0 */ - bool use_sw_sec; - - bool being_setkey; - bool use_defaultkey; - /*Encryption Algorithm for Unicast Packet */ - enum rt_enc_alg pairwise_enc_algorithm; - /*Encryption Algorithm for Brocast/Multicast */ - enum rt_enc_alg group_enc_algorithm; - /*Cam Entry Bitmap */ - u32 hwsec_cam_bitmap; - u8 hwsec_cam_sta_addr[TOTAL_CAM_ENTRY][ETH_ALEN]; - /*local Key buffer, indx 0 is for - pairwise key 1-4 is for agoup key. */ - u8 key_buf[KEY_BUF_SIZE][MAX_KEY_LEN]; - u8 key_len[KEY_BUF_SIZE]; - - /*The pointer of Pairwise Key, - it always points to KeyBuf[4] */ - u8 *pairwise_key; -}; - -#define ASSOCIATE_ENTRY_NUM 33 - -struct fast_ant_training { - u8 bssid[6]; - u8 antsel_rx_keep_0; - u8 antsel_rx_keep_1; - u8 antsel_rx_keep_2; - u32 ant_sum[7]; - u32 ant_cnt[7]; - u32 ant_ave[7]; - u8 fat_state; - u32 train_idx; - u8 antsel_a[ASSOCIATE_ENTRY_NUM]; - u8 antsel_b[ASSOCIATE_ENTRY_NUM]; - u8 antsel_c[ASSOCIATE_ENTRY_NUM]; - u32 main_ant_sum[ASSOCIATE_ENTRY_NUM]; - u32 aux_ant_sum[ASSOCIATE_ENTRY_NUM]; - u32 main_ant_cnt[ASSOCIATE_ENTRY_NUM]; - u32 aux_ant_cnt[ASSOCIATE_ENTRY_NUM]; - u8 rx_idle_ant; - bool becomelinked; -}; - -struct dm_phy_dbg_info { - char rx_snrdb[4]; - u64 num_qry_phy_status; - u64 num_qry_phy_status_cck; - u64 num_qry_phy_status_ofdm; - u16 num_qry_beacon_pkt; - u16 num_non_be_pkt; - s32 rx_evm[4]; -}; - -struct rtl_dm { - /*PHY status for Dynamic Management */ - long entry_min_undec_sm_pwdb; - long undec_sm_cck; - long undec_sm_pwdb; /*out dm */ - long entry_max_undec_sm_pwdb; - s32 ofdm_pkt_cnt; - bool dm_initialgain_enable; - bool dynamic_txpower_enable; - bool current_turbo_edca; - bool is_any_nonbepkts; /*out dm */ - bool is_cur_rdlstate; - bool txpower_trackinginit; - bool disable_framebursting; - bool cck_inch14; - bool txpower_tracking; - bool useramask; - bool rfpath_rxenable[4]; - bool inform_fw_driverctrldm; - bool current_mrc_switch; - u8 txpowercount; - u8 powerindex_backup[6]; - - u8 thermalvalue_rxgain; - u8 thermalvalue_iqk; - u8 thermalvalue_lck; - u8 thermalvalue; - u8 last_dtp_lvl; - u8 thermalvalue_avg[AVG_THERMAL_NUM]; - u8 thermalvalue_avg_index; - u8 tm_trigger; - bool done_txpower; - u8 dynamic_txhighpower_lvl; /*Tx high power level */ - u8 dm_flag; /*Indicate each dynamic mechanism's status. */ - u8 dm_flag_tmp; - u8 dm_type; - u8 dm_rssi_sel; - u8 txpower_track_control; - bool interrupt_migration; - bool disable_tx_int; - char ofdm_index[MAX_RF_PATH]; - u8 default_ofdm_index; - u8 default_cck_index; - char cck_index; - char delta_power_index[MAX_RF_PATH]; - char delta_power_index_last[MAX_RF_PATH]; - char power_index_offset[MAX_RF_PATH]; - char absolute_ofdm_swing_idx[MAX_RF_PATH]; - char remnant_ofdm_swing_idx[MAX_RF_PATH]; - char remnant_cck_idx; - bool modify_txagc_flag_path_a; - bool modify_txagc_flag_path_b; - - bool one_entry_only; - struct dm_phy_dbg_info dbginfo; - - /* Dynamic ATC switch */ - bool atc_status; - bool large_cfo_hit; - bool is_freeze; - int cfo_tail[2]; - int cfo_ave_pre; - int crystal_cap; - u8 cfo_threshold; - u32 packet_count; - u32 packet_count_pre; - u8 tx_rate; - - /*88e tx power tracking*/ - u8 swing_idx_ofdm[MAX_RF_PATH]; - u8 swing_idx_ofdm_cur; - u8 swing_idx_ofdm_base[MAX_RF_PATH]; - bool swing_flag_ofdm; - u8 swing_idx_cck; - u8 swing_idx_cck_cur; - u8 swing_idx_cck_base; - bool swing_flag_cck; - - char swing_diff_2g; - char swing_diff_5g; - - u8 delta_swing_table_idx_24gccka_p[DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_24gccka_n[DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_24gcckb_p[DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_24gcckb_n[DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_24ga_p[DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_24ga_n[DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_24gb_p[DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_24gb_n[DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_5ga_p[BAND_NUM][DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_5ga_n[BAND_NUM][DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_5gb_p[BAND_NUM][DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_5gb_n[BAND_NUM][DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_24ga_p_8188e[DEL_SW_IDX_SZ]; - u8 delta_swing_table_idx_24ga_n_8188e[DEL_SW_IDX_SZ]; - - /* DMSP */ - bool supp_phymode_switch; - - /* DulMac */ - struct fast_ant_training fat_table; - - u8 resp_tx_path; - u8 path_sel; - u32 patha_sum; - u32 pathb_sum; - u32 patha_cnt; - u32 pathb_cnt; - - u8 pre_channel; - u8 *p_channel; - u8 linked_interval; - - u64 last_tx_ok_cnt; - u64 last_rx_ok_cnt; -}; - -#define EFUSE_MAX_LOGICAL_SIZE 512 - -struct rtl_efuse { - bool autoLoad_ok; - bool bootfromefuse; - u16 max_physical_size; - - u8 efuse_map[2][EFUSE_MAX_LOGICAL_SIZE]; - u16 efuse_usedbytes; - u8 efuse_usedpercentage; -#ifdef EFUSE_REPG_WORKAROUND - bool efuse_re_pg_sec1flag; - u8 efuse_re_pg_data[8]; -#endif - - u8 autoload_failflag; - u8 autoload_status; - - short epromtype; - u16 eeprom_vid; - u16 eeprom_did; - u16 eeprom_svid; - u16 eeprom_smid; - u8 eeprom_oemid; - u16 eeprom_channelplan; - u8 eeprom_version; - u8 board_type; - u8 external_pa; - - u8 dev_addr[6]; - u8 wowlan_enable; - u8 antenna_div_cfg; - u8 antenna_div_type; - - bool txpwr_fromeprom; - u8 eeprom_crystalcap; - u8 eeprom_tssi[2]; - u8 eeprom_tssi_5g[3][2]; /* for 5GL/5GM/5GH band. */ - u8 eeprom_pwrlimit_ht20[CHANNEL_GROUP_MAX]; - u8 eeprom_pwrlimit_ht40[CHANNEL_GROUP_MAX]; - u8 eeprom_chnlarea_txpwr_cck[MAX_RF_PATH][CHANNEL_GROUP_MAX_2G]; - u8 eeprom_chnlarea_txpwr_ht40_1s[MAX_RF_PATH][CHANNEL_GROUP_MAX]; - u8 eprom_chnl_txpwr_ht40_2sdf[MAX_RF_PATH][CHANNEL_GROUP_MAX]; - - u8 internal_pa_5g[2]; /* pathA / pathB */ - u8 eeprom_c9; - u8 eeprom_cc; - - /*For power group */ - u8 eeprom_pwrgroup[2][3]; - u8 pwrgroup_ht20[2][CHANNEL_MAX_NUMBER]; - u8 pwrgroup_ht40[2][CHANNEL_MAX_NUMBER]; - - u8 txpwrlevel_cck[MAX_RF_PATH][CHANNEL_MAX_NUMBER_2G]; - /*For HT 40MHZ pwr */ - u8 txpwrlevel_ht40_1s[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; - /*For HT 40MHZ pwr */ - u8 txpwrlevel_ht40_2s[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; - - /*--------------------------------------------------------* - * 8192CE\8192SE\8192DE\8723AE use the following 4 arrays, - * other ICs (8188EE\8723BE\8192EE\8812AE...) - * define new arrays in Windows code. - * BUT, in linux code, we use the same array for all ICs. - * - * The Correspondance relation between two arrays is: - * txpwr_cckdiff[][] == CCK_24G_Diff[][] - * txpwr_ht20diff[][] == BW20_24G_Diff[][] - * txpwr_ht40diff[][] == BW40_24G_Diff[][] - * txpwr_legacyhtdiff[][] == OFDM_24G_Diff[][] - * - * Sizes of these arrays are decided by the larger ones. - */ - char txpwr_cckdiff[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; - char txpwr_ht20diff[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; - char txpwr_ht40diff[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; - char txpwr_legacyhtdiff[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; - - u8 txpwr_5g_bw40base[MAX_RF_PATH][CHANNEL_MAX_NUMBER]; - u8 txpwr_5g_bw80base[MAX_RF_PATH][CHANNEL_MAX_NUMBER_5G_80M]; - char txpwr_5g_ofdmdiff[MAX_RF_PATH][MAX_TX_COUNT]; - char txpwr_5g_bw20diff[MAX_RF_PATH][MAX_TX_COUNT]; - char txpwr_5g_bw40diff[MAX_RF_PATH][MAX_TX_COUNT]; - char txpwr_5g_bw80diff[MAX_RF_PATH][MAX_TX_COUNT]; - - u8 txpwr_safetyflag; /* Band edge enable flag */ - u16 eeprom_txpowerdiff; - u8 legacy_httxpowerdiff; /* Legacy to HT rate power diff */ - u8 antenna_txpwdiff[3]; - - u8 eeprom_regulatory; - u8 eeprom_thermalmeter; - u8 thermalmeter[2]; /*ThermalMeter, index 0 for RFIC0, 1 for RFIC1 */ - u16 tssi_13dbm; - u8 crystalcap; /* CrystalCap. */ - u8 delta_iqk; - u8 delta_lck; - - u8 legacy_ht_txpowerdiff; /*Legacy to HT rate power diff */ - bool apk_thermalmeterignore; - - bool b1x1_recvcombine; - bool b1ss_support; - - /*channel plan */ - u8 channel_plan; -}; - -struct rtl_ps_ctl { - bool pwrdomain_protect; - bool in_powersavemode; - bool rfchange_inprogress; - bool swrf_processing; - bool hwradiooff; - /* - * just for PCIE ASPM - * If it supports ASPM, Offset[560h] = 0x40, - * otherwise Offset[560h] = 0x00. - * */ - bool support_aspm; - bool support_backdoor; - - /*for LPS */ - enum rt_psmode dot11_psmode; /*Power save mode configured. */ - bool swctrl_lps; - bool leisure_ps; - bool fwctrl_lps; - u8 fwctrl_psmode; - /*For Fw control LPS mode */ - u8 reg_fwctrl_lps; - /*Record Fw PS mode status. */ - bool fw_current_inpsmode; - u8 reg_max_lps_awakeintvl; - bool report_linked; - bool low_power_enable;/*for 32k*/ - - /*for IPS */ - bool inactiveps; - - u32 rfoff_reason; - - /*RF OFF Level */ - u32 cur_ps_level; - u32 reg_rfps_level; - - /*just for PCIE ASPM */ - u8 const_amdpci_aspm; - bool pwrdown_mode; - - enum rf_pwrstate inactive_pwrstate; - enum rf_pwrstate rfpwr_state; /*cur power state */ - - /* for SW LPS*/ - bool sw_ps_enabled; - bool state; - bool state_inap; - bool multi_buffered; - u16 nullfunc_seq; - unsigned int dtim_counter; - unsigned int sleep_ms; - unsigned long last_sleep_jiffies; - unsigned long last_awake_jiffies; - unsigned long last_delaylps_stamp_jiffies; - unsigned long last_dtim; - unsigned long last_beacon; - unsigned long last_action; - unsigned long last_slept; - - /*For P2P PS */ - struct rtl_p2p_ps_info p2p_ps_info; - u8 pwr_mode; - u8 smart_ps; - - /* wake up on line */ - u8 wo_wlan_mode; - u8 arp_offload_enable; - u8 gtk_offload_enable; - /* Used for WOL, indicates the reason for waking event.*/ - u32 wakeup_reason; - /* Record the last waking time for comparison with setting key. */ - u64 last_wakeup_time; -}; - -struct rtl_stats { - u8 psaddr[ETH_ALEN]; - u32 mac_time[2]; - s8 rssi; - u8 signal; - u8 noise; - u8 rate; /* hw desc rate */ - u8 received_channel; - u8 control; - u8 mask; - u8 freq; - u16 len; - u64 tsf; - u32 beacon_time; - u8 nic_type; - u16 length; - u8 signalquality; /*in 0-100 index. */ - /* - * Real power in dBm for this packet, - * no beautification and aggregation. - * */ - s32 recvsignalpower; - s8 rxpower; /*in dBm Translate from PWdB */ - u8 signalstrength; /*in 0-100 index. */ - u16 hwerror:1; - u16 crc:1; - u16 icv:1; - u16 shortpreamble:1; - u16 antenna:1; - u16 decrypted:1; - u16 wakeup:1; - u32 timestamp_low; - u32 timestamp_high; - bool shift; - - u8 rx_drvinfo_size; - u8 rx_bufshift; - bool isampdu; - bool isfirst_ampdu; - bool rx_is40Mhzpacket; - u8 rx_packet_bw; - u32 rx_pwdb_all; - u8 rx_mimo_signalstrength[4]; /*in 0~100 index */ - s8 rx_mimo_signalquality[4]; - u8 rx_mimo_evm_dbm[4]; - u16 cfo_short[4]; /* per-path's Cfo_short */ - u16 cfo_tail[4]; - - s8 rx_mimo_sig_qual[4]; - u8 rx_pwr[4]; /* per-path's pwdb */ - u8 rx_snr[4]; /* per-path's SNR */ - u8 bandwidth; - u8 bt_coex_pwr_adjust; - bool packet_matchbssid; - bool is_cck; - bool is_ht; - bool packet_toself; - bool packet_beacon; /*for rssi */ - char cck_adc_pwdb[4]; /*for rx path selection */ - - bool is_vht; - bool is_short_gi; - u8 vht_nss; - - u8 packet_report_type; - - u32 macid; - u8 wake_match; - u32 bt_rx_rssi_percentage; - u32 macid_valid_entry[2]; -}; - - -struct rt_link_detect { - /* count for roaming */ - u32 bcn_rx_inperiod; - u32 roam_times; - - u32 num_tx_in4period[4]; - u32 num_rx_in4period[4]; - - u32 num_tx_inperiod; - u32 num_rx_inperiod; - - bool busytraffic; - bool tx_busy_traffic; - bool rx_busy_traffic; - bool higher_busytraffic; - bool higher_busyrxtraffic; - - u32 tidtx_in4period[MAX_TID_COUNT][4]; - u32 tidtx_inperiod[MAX_TID_COUNT]; - bool higher_busytxtraffic[MAX_TID_COUNT]; -}; - -struct rtl_tcb_desc { - u8 packet_bw:2; - u8 multicast:1; - u8 broadcast:1; - - u8 rts_stbc:1; - u8 rts_enable:1; - u8 cts_enable:1; - u8 rts_use_shortpreamble:1; - u8 rts_use_shortgi:1; - u8 rts_sc:1; - u8 rts_bw:1; - u8 rts_rate; - - u8 use_shortgi:1; - u8 use_shortpreamble:1; - u8 use_driver_rate:1; - u8 disable_ratefallback:1; - - u8 ratr_index; - u8 mac_id; - u8 hw_rate; - - u8 last_inipkt:1; - u8 cmd_or_init:1; - u8 queue_index; - - /* early mode */ - u8 empkt_num; - /* The max value by HW */ - u32 empkt_len[10]; - bool tx_enable_sw_calc_duration; -}; - -struct rtl_wow_pattern { - u8 type; - u16 crc; - u32 mask[4]; -}; - -struct rtl_hal_ops { - int (*init_sw_vars) (struct ieee80211_hw *hw); - void (*deinit_sw_vars) (struct ieee80211_hw *hw); - void (*read_chip_version)(struct ieee80211_hw *hw); - void (*read_eeprom_info) (struct ieee80211_hw *hw); - void (*interrupt_recognized) (struct ieee80211_hw *hw, - u32 *p_inta, u32 *p_intb); - int (*hw_init) (struct ieee80211_hw *hw); - void (*hw_disable) (struct ieee80211_hw *hw); - void (*hw_suspend) (struct ieee80211_hw *hw); - void (*hw_resume) (struct ieee80211_hw *hw); - void (*enable_interrupt) (struct ieee80211_hw *hw); - void (*disable_interrupt) (struct ieee80211_hw *hw); - int (*set_network_type) (struct ieee80211_hw *hw, - enum nl80211_iftype type); - void (*set_chk_bssid)(struct ieee80211_hw *hw, - bool check_bssid); - void (*set_bw_mode) (struct ieee80211_hw *hw, - enum nl80211_channel_type ch_type); - u8(*switch_channel) (struct ieee80211_hw *hw); - void (*set_qos) (struct ieee80211_hw *hw, int aci); - void (*set_bcn_reg) (struct ieee80211_hw *hw); - void (*set_bcn_intv) (struct ieee80211_hw *hw); - void (*update_interrupt_mask) (struct ieee80211_hw *hw, - u32 add_msr, u32 rm_msr); - void (*get_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); - void (*set_hw_reg) (struct ieee80211_hw *hw, u8 variable, u8 *val); - void (*update_rate_tbl) (struct ieee80211_hw *hw, - struct ieee80211_sta *sta, u8 rssi_level); - void (*pre_fill_tx_bd_desc)(struct ieee80211_hw *hw, u8 *tx_bd_desc, - u8 *desc, u8 queue_index, - struct sk_buff *skb, dma_addr_t addr); - void (*update_rate_mask) (struct ieee80211_hw *hw, u8 rssi_level); - u16 (*rx_desc_buff_remained_cnt)(struct ieee80211_hw *hw, - u8 queue_index); - void (*rx_check_dma_ok)(struct ieee80211_hw *hw, u8 *header_desc, - u8 queue_index); - void (*fill_tx_desc) (struct ieee80211_hw *hw, - struct ieee80211_hdr *hdr, u8 *pdesc_tx, - u8 *pbd_desc_tx, - struct ieee80211_tx_info *info, - struct ieee80211_sta *sta, - struct sk_buff *skb, u8 hw_queue, - struct rtl_tcb_desc *ptcb_desc); - void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 *pDesc, - u32 buffer_len, bool bIsPsPoll); - void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc, - bool firstseg, bool lastseg, - struct sk_buff *skb); - bool (*query_rx_desc) (struct ieee80211_hw *hw, - struct rtl_stats *stats, - struct ieee80211_rx_status *rx_status, - u8 *pdesc, struct sk_buff *skb); - void (*set_channel_access) (struct ieee80211_hw *hw); - bool (*radio_onoff_checking) (struct ieee80211_hw *hw, u8 *valid); - void (*dm_watchdog) (struct ieee80211_hw *hw); - void (*scan_operation_backup) (struct ieee80211_hw *hw, u8 operation); - bool (*set_rf_power_state) (struct ieee80211_hw *hw, - enum rf_pwrstate rfpwr_state); - void (*led_control) (struct ieee80211_hw *hw, - enum led_ctl_mode ledaction); - void (*set_desc)(struct ieee80211_hw *hw, u8 *pdesc, bool istx, - u8 desc_name, u8 *val); - u32 (*get_desc) (u8 *pdesc, bool istx, u8 desc_name); - bool (*is_tx_desc_closed) (struct ieee80211_hw *hw, - u8 hw_queue, u16 index); - void (*tx_polling) (struct ieee80211_hw *hw, u8 hw_queue); - void (*enable_hw_sec) (struct ieee80211_hw *hw); - void (*set_key) (struct ieee80211_hw *hw, u32 key_index, - u8 *macaddr, bool is_group, u8 enc_algo, - bool is_wepkey, bool clear_all); - void (*init_sw_leds) (struct ieee80211_hw *hw); - void (*deinit_sw_leds) (struct ieee80211_hw *hw); - u32 (*get_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); - void (*set_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, - u32 data); - u32 (*get_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask); - void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath, - u32 regaddr, u32 bitmask, u32 data); - void (*linked_set_reg) (struct ieee80211_hw *hw); - void (*chk_switch_dmdp) (struct ieee80211_hw *hw); - void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw); - void (*dualmac_switch_to_dmdp) (struct ieee80211_hw *hw); - bool (*phy_rf6052_config) (struct ieee80211_hw *hw); - void (*phy_rf6052_set_cck_txpower) (struct ieee80211_hw *hw, - u8 *powerlevel); - void (*phy_rf6052_set_ofdm_txpower) (struct ieee80211_hw *hw, - u8 *ppowerlevel, u8 channel); - bool (*config_bb_with_headerfile) (struct ieee80211_hw *hw, - u8 configtype); - bool (*config_bb_with_pgheaderfile) (struct ieee80211_hw *hw, - u8 configtype); - void (*phy_lc_calibrate) (struct ieee80211_hw *hw, bool is2t); - void (*phy_set_bw_mode_callback) (struct ieee80211_hw *hw); - void (*dm_dynamic_txpower) (struct ieee80211_hw *hw); - void (*c2h_command_handle) (struct ieee80211_hw *hw); - void (*bt_wifi_media_status_notify) (struct ieee80211_hw *hw, - bool mstate); - void (*bt_coex_off_before_lps) (struct ieee80211_hw *hw); - void (*fill_h2c_cmd) (struct ieee80211_hw *hw, u8 element_id, - u32 cmd_len, u8 *p_cmdbuffer); - bool (*get_btc_status) (void); - bool (*is_fw_header)(struct rtlwifi_firmware_header *hdr); - u32 (*rx_command_packet)(struct ieee80211_hw *hw, - struct rtl_stats status, struct sk_buff *skb); - void (*add_wowlan_pattern)(struct ieee80211_hw *hw, - struct rtl_wow_pattern *rtl_pattern, - u8 index); - u16 (*get_available_desc)(struct ieee80211_hw *hw, u8 q_idx); -}; - -struct rtl_intf_ops { - /*com */ - void (*read_efuse_byte)(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf); - int (*adapter_start) (struct ieee80211_hw *hw); - void (*adapter_stop) (struct ieee80211_hw *hw); - bool (*check_buddy_priv)(struct ieee80211_hw *hw, - struct rtl_priv **buddy_priv); - - int (*adapter_tx) (struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - struct sk_buff *skb, - struct rtl_tcb_desc *ptcb_desc); - void (*flush)(struct ieee80211_hw *hw, u32 queues, bool drop); - int (*reset_trx_ring) (struct ieee80211_hw *hw); - bool (*waitq_insert) (struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - struct sk_buff *skb); - - /*pci */ - void (*disable_aspm) (struct ieee80211_hw *hw); - void (*enable_aspm) (struct ieee80211_hw *hw); - - /*usb */ -}; - -struct rtl_mod_params { - /* default: 0 = using hardware encryption */ - bool sw_crypto; - - /* default: 0 = DBG_EMERG (0)*/ - int debug; - - /* default: 1 = using no linked power save */ - bool inactiveps; - - /* default: 1 = using linked sw power save */ - bool swctrl_lps; - - /* default: 1 = using linked fw power save */ - bool fwctrl_lps; - - /* default: 0 = not using MSI interrupts mode - * submodules should set their own default value - */ - bool msi_support; - - /* default 0: 1 means disable */ - bool disable_watchdog; -}; - -struct rtl_hal_usbint_cfg { - /* data - rx */ - u32 in_ep_num; - u32 rx_urb_num; - u32 rx_max_size; - - /* op - rx */ - void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *); - void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *, - struct sk_buff_head *); - - /* tx */ - void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *); - int (*usb_tx_post_hdl)(struct ieee80211_hw *, struct urb *, - struct sk_buff *); - struct sk_buff *(*usb_tx_aggregate_hdl)(struct ieee80211_hw *, - struct sk_buff_head *); - - /* endpoint mapping */ - int (*usb_endpoint_mapping)(struct ieee80211_hw *hw); - u16 (*usb_mq_to_hwq)(__le16 fc, u16 mac80211_queue_index); -}; - -struct rtl_hal_cfg { - u8 bar_id; - bool write_readback; - char *name; - char *fw_name; - char *alt_fw_name; - char *wowlan_fw_name; - struct rtl_hal_ops *ops; - struct rtl_mod_params *mod_params; - struct rtl_hal_usbint_cfg *usb_interface_cfg; - - /*this map used for some registers or vars - defined int HAL but used in MAIN */ - u32 maps[RTL_VAR_MAP_MAX]; - -}; - -struct rtl_locks { - /* mutex */ - struct mutex conf_mutex; - struct mutex ps_mutex; - - /*spin lock */ - spinlock_t ips_lock; - spinlock_t irq_th_lock; - spinlock_t irq_pci_lock; - spinlock_t tx_lock; - spinlock_t h2c_lock; - spinlock_t rf_ps_lock; - spinlock_t rf_lock; - spinlock_t lps_lock; - spinlock_t waitq_lock; - spinlock_t entry_list_lock; - spinlock_t usb_lock; - - /*FW clock change */ - spinlock_t fw_ps_lock; - - /*Dual mac*/ - spinlock_t cck_and_rw_pagea_lock; - - /*Easy concurrent*/ - spinlock_t check_sendpkt_lock; - - spinlock_t iqk_lock; -}; - -struct rtl_works { - struct ieee80211_hw *hw; - - /*timer */ - struct timer_list watchdog_timer; - struct timer_list dualmac_easyconcurrent_retrytimer; - struct timer_list fw_clockoff_timer; - struct timer_list fast_antenna_training_timer; - /*task */ - struct tasklet_struct irq_tasklet; - struct tasklet_struct irq_prepare_bcn_tasklet; - - /*work queue */ - struct workqueue_struct *rtl_wq; - struct delayed_work watchdog_wq; - struct delayed_work ips_nic_off_wq; - - /* For SW LPS */ - struct delayed_work ps_work; - struct delayed_work ps_rfon_wq; - struct delayed_work fwevt_wq; - - struct work_struct lps_change_work; - 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 - -struct rtl_dualmac_easy_concurrent_ctl { - enum band_type currentbandtype_backfordmdp; - bool close_bbandrf_for_dmsp; - bool change_to_dmdp; - bool change_to_dmsp; - bool switch_in_process; -}; - -struct rtl_dmsp_ctl { - bool activescan_for_slaveofdmsp; - bool scan_for_anothermac_fordmsp; - bool scan_for_itself_fordmsp; - bool writedig_for_anothermacofdmsp; - u32 curdigvalue_for_anothermacofdmsp; - bool changecckpdstate_for_anothermacofdmsp; - u8 curcckpdstate_for_anothermacofdmsp; - bool changetxhighpowerlvl_for_anothermacofdmsp; - u8 curtxhighlvl_for_anothermacofdmsp; - long rssivalmin_for_anothermacofdmsp; -}; - -struct ps_t { - u8 pre_ccastate; - u8 cur_ccasate; - u8 pre_rfstate; - u8 cur_rfstate; - u8 initialize; - long rssi_val_min; -}; - -struct dig_t { - u32 rssi_lowthresh; - u32 rssi_highthresh; - u32 fa_lowthresh; - u32 fa_highthresh; - long last_min_undec_pwdb_for_dm; - long rssi_highpower_lowthresh; - long rssi_highpower_highthresh; - u32 recover_cnt; - u32 pre_igvalue; - u32 cur_igvalue; - long rssi_val; - u8 dig_enable_flag; - u8 dig_ext_port_stage; - u8 dig_algorithm; - u8 dig_twoport_algorithm; - u8 dig_dbgmode; - u8 dig_slgorithm_switch; - u8 cursta_cstate; - u8 presta_cstate; - u8 curmultista_cstate; - u8 stop_dig; - char back_val; - char back_range_max; - char back_range_min; - u8 rx_gain_max; - u8 rx_gain_min; - u8 min_undec_pwdb_for_dm; - u8 rssi_val_min; - u8 pre_cck_cca_thres; - u8 cur_cck_cca_thres; - u8 pre_cck_pd_state; - u8 cur_cck_pd_state; - u8 pre_cck_fa_state; - u8 cur_cck_fa_state; - u8 pre_ccastate; - u8 cur_ccasate; - u8 large_fa_hit; - u8 forbidden_igi; - u8 dig_state; - u8 dig_highpwrstate; - u8 cur_sta_cstate; - u8 pre_sta_cstate; - u8 cur_ap_cstate; - u8 pre_ap_cstate; - u8 cur_pd_thstate; - u8 pre_pd_thstate; - u8 cur_cs_ratiostate; - u8 pre_cs_ratiostate; - u8 backoff_enable_flag; - char backoffval_range_max; - char backoffval_range_min; - u8 dig_min_0; - u8 dig_min_1; - u8 bt30_cur_igi; - bool media_connect_0; - bool media_connect_1; - - u32 antdiv_rssi_max; - u32 rssi_max; -}; - -struct rtl_global_var { - /* from this list we can get - * other adapter's rtl_priv */ - struct list_head glb_priv_list; - spinlock_t glb_list_lock; -}; - -struct rtl_btc_info { - u8 bt_type; - u8 btcoexist; - u8 ant_num; -}; - -struct bt_coexist_info { - struct rtl_btc_ops *btc_ops; - struct rtl_btc_info btc_info; - /* EEPROM BT info. */ - u8 eeprom_bt_coexist; - u8 eeprom_bt_type; - u8 eeprom_bt_ant_num; - u8 eeprom_bt_ant_isol; - u8 eeprom_bt_radio_shared; - - u8 bt_coexistence; - u8 bt_ant_num; - u8 bt_coexist_type; - u8 bt_state; - u8 bt_cur_state; /* 0:on, 1:off */ - u8 bt_ant_isolation; /* 0:good, 1:bad */ - u8 bt_pape_ctrl; /* 0:SW, 1:SW/HW dynamic */ - u8 bt_service; - u8 bt_radio_shared_type; - u8 bt_rfreg_origin_1e; - u8 bt_rfreg_origin_1f; - u8 bt_rssi_state; - u32 ratio_tx; - u32 ratio_pri; - u32 bt_edca_ul; - u32 bt_edca_dl; - - bool init_set; - bool bt_busy_traffic; - bool bt_traffic_mode_set; - bool bt_non_traffic_mode_set; - - bool fw_coexist_all_off; - bool sw_coexist_all_off; - bool hw_coexist_all_off; - u32 cstate; - u32 previous_state; - u32 cstate_h; - u32 previous_state_h; - - u8 bt_pre_rssi_state; - u8 bt_pre_rssi_state1; - - u8 reg_bt_iso; - u8 reg_bt_sco; - bool balance_on; - u8 bt_active_zero_cnt; - bool cur_bt_disabled; - bool pre_bt_disabled; - - u8 bt_profile_case; - u8 bt_profile_action; - bool bt_busy; - bool hold_for_bt_operation; - u8 lps_counter; -}; - -struct rtl_btc_ops { - void (*btc_init_variables) (struct rtl_priv *rtlpriv); - void (*btc_init_hal_vars) (struct rtl_priv *rtlpriv); - void (*btc_init_hw_config) (struct rtl_priv *rtlpriv); - void (*btc_ips_notify) (struct rtl_priv *rtlpriv, u8 type); - void (*btc_lps_notify)(struct rtl_priv *rtlpriv, u8 type); - void (*btc_scan_notify) (struct rtl_priv *rtlpriv, u8 scantype); - void (*btc_connect_notify) (struct rtl_priv *rtlpriv, u8 action); - void (*btc_mediastatus_notify) (struct rtl_priv *rtlpriv, - enum rt_media_status mstatus); - void (*btc_periodical) (struct rtl_priv *rtlpriv); - void (*btc_halt_notify) (void); - void (*btc_btinfo_notify) (struct rtl_priv *rtlpriv, - u8 *tmp_buf, u8 length); - bool (*btc_is_limited_dig) (struct rtl_priv *rtlpriv); - bool (*btc_is_disable_edca_turbo) (struct rtl_priv *rtlpriv); - bool (*btc_is_bt_disabled) (struct rtl_priv *rtlpriv); - void (*btc_special_packet_notify)(struct rtl_priv *rtlpriv, - u8 pkt_type); -}; - -struct proxim { - bool proxim_on; - - void *proximity_priv; - int (*proxim_rx)(struct ieee80211_hw *hw, struct rtl_stats *status, - struct sk_buff *skb); - u8 (*proxim_get_var)(struct ieee80211_hw *hw, u8 type); -}; - -struct rtl_priv { - struct ieee80211_hw *hw; - struct completion firmware_loading_complete; - struct list_head list; - struct rtl_priv *buddy_priv; - struct rtl_global_var *glb_var; - struct rtl_dualmac_easy_concurrent_ctl easy_concurrent_ctl; - struct rtl_dmsp_ctl dmsp_ctl; - struct rtl_locks locks; - struct rtl_works works; - struct rtl_mac mac80211; - struct rtl_hal rtlhal; - struct rtl_regulatory regd; - struct rtl_rfkill rfkill; - struct rtl_io io; - struct rtl_phy phy; - struct rtl_dm dm; - struct rtl_security sec; - struct rtl_efuse efuse; - - struct rtl_ps_ctl psc; - struct rate_adaptive ra; - struct dynamic_primary_cca primarycca; - struct wireless_stats stats; - struct rt_link_detect link_info; - struct false_alarm_statistics falsealm_cnt; - - struct rtl_rate_priv *rate_priv; - - /* sta entry list for ap adhoc or mesh */ - struct list_head entry_list; - - struct rtl_debug dbg; - int max_fw_size; - - /* - *hal_cfg : for diff cards - *intf_ops : for diff interrface usb/pcie - */ - struct rtl_hal_cfg *cfg; - struct rtl_intf_ops *intf_ops; - - /*this var will be set by set_bit, - and was used to indicate status of - interface or hardware */ - unsigned long status; - - /* tables for dm */ - struct dig_t dm_digtable; - struct ps_t dm_pstable; - - u32 reg_874; - u32 reg_c70; - u32 reg_85c; - u32 reg_a74; - bool reg_init; /* true if regs saved */ - bool bt_operation_on; - __le32 *usb_data; - int usb_data_index; - bool initialized; - bool enter_ps; /* true when entering PS */ - u8 rate_mask[5]; - - /* intel Proximity, should be alloc mem - * in intel Proximity module and can only - * be used in intel Proximity mode - */ - struct proxim proximity; - - /*for bt coexist use*/ - struct bt_coexist_info btcoexist; - - /* separate 92ee from other ICs, - * 92ee use new trx flow. - */ - bool use_new_trx_flow; - -#ifdef CONFIG_PM - struct wiphy_wowlan_support wowlan; -#endif - /*This must be the last item so - that it points to the data allocated - beyond this structure like: - rtl_pci_priv or rtl_usb_priv */ - u8 priv[0] __aligned(sizeof(void *)); -}; - -#define rtl_priv(hw) (((struct rtl_priv *)(hw)->priv)) -#define rtl_mac(rtlpriv) (&((rtlpriv)->mac80211)) -#define rtl_hal(rtlpriv) (&((rtlpriv)->rtlhal)) -#define rtl_efuse(rtlpriv) (&((rtlpriv)->efuse)) -#define rtl_psc(rtlpriv) (&((rtlpriv)->psc)) - - -/*************************************** - Bluetooth Co-existence Related -****************************************/ - -enum bt_ant_num { - ANT_X2 = 0, - ANT_X1 = 1, -}; - -enum bt_co_type { - BT_2WIRE = 0, - BT_ISSC_3WIRE = 1, - BT_ACCEL = 2, - BT_CSR_BC4 = 3, - BT_CSR_BC8 = 4, - BT_RTL8756 = 5, - BT_RTL8723A = 6, - BT_RTL8821A = 7, - BT_RTL8723B = 8, - BT_RTL8192E = 9, - BT_RTL8812A = 11, -}; - -enum bt_total_ant_num { - ANT_TOTAL_X2 = 0, - ANT_TOTAL_X1 = 1 -}; - -enum bt_cur_state { - BT_OFF = 0, - BT_ON = 1, -}; - -enum bt_service_type { - BT_SCO = 0, - BT_A2DP = 1, - BT_HID = 2, - BT_HID_IDLE = 3, - BT_SCAN = 4, - BT_IDLE = 5, - BT_OTHER_ACTION = 6, - BT_BUSY = 7, - BT_OTHERBUSY = 8, - BT_PAN = 9, -}; - -enum bt_radio_shared { - BT_RADIO_SHARED = 0, - BT_RADIO_INDIVIDUAL = 1, -}; - - -/**************************************** - mem access macro define start - Call endian free function when - 1. Read/write packet content. - 2. Before write integer to IO. - 3. After read integer from IO. -****************************************/ -/* Convert little data endian to host ordering */ -#define EF1BYTE(_val) \ - ((u8)(_val)) -#define EF2BYTE(_val) \ - (le16_to_cpu(_val)) -#define EF4BYTE(_val) \ - (le32_to_cpu(_val)) - -/* Read data from memory */ -#define READEF1BYTE(_ptr) \ - EF1BYTE(*((u8 *)(_ptr))) -/* Read le16 data from memory and convert to host ordering */ -#define READEF2BYTE(_ptr) \ - EF2BYTE(*(_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 - * BIT_LEN_MASK_32(1) => 0x00000001 - * BIT_LEN_MASK_32(2) => 0x00000003 - * BIT_LEN_MASK_32(32) => 0xFFFFFFFF - */ -#define BIT_LEN_MASK_32(__bitlen) \ - (0xFFFFFFFF >> (32 - (__bitlen))) -#define BIT_LEN_MASK_16(__bitlen) \ - (0xFFFF >> (16 - (__bitlen))) -#define BIT_LEN_MASK_8(__bitlen) \ - (0xFF >> (8 - (__bitlen))) - -/* Create an offset bit mask - * Examples: - * BIT_OFFSET_LEN_MASK_32(0, 2) => 0x00000003 - * BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000 - */ -#define BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen) \ - (BIT_LEN_MASK_32(__bitlen) << (__bitoffset)) -#define BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen) \ - (BIT_LEN_MASK_16(__bitlen) << (__bitoffset)) -#define BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen) \ - (BIT_LEN_MASK_8(__bitlen) << (__bitoffset)) - -/*Description: - * Return 4-byte value in host byte ordering from - * 4-byte pointer in little-endian system. - */ -#define LE_P4BYTE_TO_HOST_4BYTE(__pstart) \ - (EF4BYTE(*((__le32 *)(__pstart)))) -#define LE_P2BYTE_TO_HOST_2BYTE(__pstart) \ - (EF2BYTE(*((__le16 *)(__pstart)))) -#define LE_P1BYTE_TO_HOST_1BYTE(__pstart) \ - (EF1BYTE(*((u8 *)(__pstart)))) - -/*Description: -Translate subfield (continuous bits in little-endian) of 4-byte -value to host byte ordering.*/ -#define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ - ( \ - (LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset)) & \ - BIT_LEN_MASK_32(__bitlen) \ - ) -#define LE_BITS_TO_2BYTE(__pstart, __bitoffset, __bitlen) \ - ( \ - (LE_P2BYTE_TO_HOST_2BYTE(__pstart) >> (__bitoffset)) & \ - BIT_LEN_MASK_16(__bitlen) \ - ) -#define LE_BITS_TO_1BYTE(__pstart, __bitoffset, __bitlen) \ - ( \ - (LE_P1BYTE_TO_HOST_1BYTE(__pstart) >> (__bitoffset)) & \ - BIT_LEN_MASK_8(__bitlen) \ - ) - -/* Description: - * Mask subfield (continuous bits in little-endian) of 4-byte value - * and return the result in 4-byte value in host byte ordering. - */ -#define LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) \ - ( \ - LE_P4BYTE_TO_HOST_4BYTE(__pstart) & \ - (~BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen)) \ - ) -#define LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) \ - ( \ - LE_P2BYTE_TO_HOST_2BYTE(__pstart) & \ - (~BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen)) \ - ) -#define LE_BITS_CLEARED_TO_1BYTE(__pstart, __bitoffset, __bitlen) \ - ( \ - LE_P1BYTE_TO_HOST_1BYTE(__pstart) & \ - (~BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen)) \ - ) - -/* Description: - * Set subfield of little-endian 4-byte value to specified value. - */ -#define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \ - *((u32 *)(__pstart)) = \ - ( \ - 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)) = \ - ( \ - LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \ - ((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \ - ); -#define SET_BITS_TO_LE_1BYTE(__pstart, __bitoffset, __bitlen, __val) \ - *((u8 *)(__pstart)) = EF1BYTE \ - ( \ - LE_BITS_CLEARED_TO_1BYTE(__pstart, __bitoffset, __bitlen) | \ - ((((u8)__val) & BIT_LEN_MASK_8(__bitlen)) << (__bitoffset)) \ - ); - -#define N_BYTE_ALIGMENT(__value, __aligment) ((__aligment == 1) ? \ - (__value) : (((__value + __aligment - 1) / __aligment) * __aligment)) - -/**************************************** - mem access macro define end -****************************************/ - -#define byte(x, n) ((x >> (8 * n)) & 0xff) - -#define packet_get_type(_packet) (EF1BYTE((_packet).octet[0]) & 0xFC) -#define RTL_WATCH_DOG_TIME 2000 -#define MSECS(t) msecs_to_jiffies(t) -#define WLAN_FC_GET_VERS(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_VERS) -#define WLAN_FC_GET_TYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) -#define WLAN_FC_GET_STYPE(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) -#define WLAN_FC_MORE_DATA(fc) (le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA) -#define rtl_dm(rtlpriv) (&((rtlpriv)->dm)) - -#define RT_RF_OFF_LEVL_ASPM BIT(0) /*PCI ASPM */ -#define RT_RF_OFF_LEVL_CLK_REQ BIT(1) /*PCI clock request */ -#define RT_RF_OFF_LEVL_PCI_D3 BIT(2) /*PCI D3 mode */ -/*NIC halt, re-initialize hw parameters*/ -#define RT_RF_OFF_LEVL_HALT_NIC BIT(3) -#define RT_RF_OFF_LEVL_FREE_FW BIT(4) /*FW free, re-download the FW */ -#define RT_RF_OFF_LEVL_FW_32K BIT(5) /*FW in 32k */ -/*Always enable ASPM and Clock Req in initialization.*/ -#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT(6) -/* no matter RFOFF or SLEEP we set PS_ASPM_LEVL*/ -#define RT_PS_LEVEL_ASPM BIT(7) -/*When LPS is on, disable 2R if no packet is received or transmittd.*/ -#define RT_RF_LPS_DISALBE_2R BIT(30) -#define RT_RF_LPS_LEVEL_ASPM BIT(31) /*LPS with ASPM */ -#define RT_IN_PS_LEVEL(ppsc, _ps_flg) \ - ((ppsc->cur_ps_level & _ps_flg) ? true : false) -#define RT_CLEAR_PS_LEVEL(ppsc, _ps_flg) \ - (ppsc->cur_ps_level &= (~(_ps_flg))) -#define RT_SET_PS_LEVEL(ppsc, _ps_flg) \ - (ppsc->cur_ps_level |= _ps_flg) - -#define container_of_dwork_rtl(x, y, z) \ - container_of(container_of(x, struct delayed_work, work), y, z) - -#define FILL_OCTET_STRING(_os, _octet, _len) \ - (_os).octet = (u8 *)(_octet); \ - (_os).length = (_len); - -#define CP_MACADDR(des, src) \ - ((des)[0] = (src)[0], (des)[1] = (src)[1],\ - (des)[2] = (src)[2], (des)[3] = (src)[3],\ - (des)[4] = (src)[4], (des)[5] = (src)[5]) - -#define LDPC_HT_ENABLE_RX BIT(0) -#define LDPC_HT_ENABLE_TX BIT(1) -#define LDPC_HT_TEST_TX_ENABLE BIT(2) -#define LDPC_HT_CAP_TX BIT(3) - -#define STBC_HT_ENABLE_RX BIT(0) -#define STBC_HT_ENABLE_TX BIT(1) -#define STBC_HT_TEST_TX_ENABLE BIT(2) -#define STBC_HT_CAP_TX BIT(3) - -#define LDPC_VHT_ENABLE_RX BIT(0) -#define LDPC_VHT_ENABLE_TX BIT(1) -#define LDPC_VHT_TEST_TX_ENABLE BIT(2) -#define LDPC_VHT_CAP_TX BIT(3) - -#define STBC_VHT_ENABLE_RX BIT(0) -#define STBC_VHT_ENABLE_TX BIT(1) -#define STBC_VHT_TEST_TX_ENABLE BIT(2) -#define STBC_VHT_CAP_TX BIT(3) - -static inline u8 rtl_read_byte(struct rtl_priv *rtlpriv, u32 addr) -{ - return rtlpriv->io.read8_sync(rtlpriv, addr); -} - -static inline u16 rtl_read_word(struct rtl_priv *rtlpriv, u32 addr) -{ - return rtlpriv->io.read16_sync(rtlpriv, addr); -} - -static inline u32 rtl_read_dword(struct rtl_priv *rtlpriv, u32 addr) -{ - return rtlpriv->io.read32_sync(rtlpriv, addr); -} - -static inline void rtl_write_byte(struct rtl_priv *rtlpriv, u32 addr, u8 val8) -{ - rtlpriv->io.write8_async(rtlpriv, addr, val8); - - if (rtlpriv->cfg->write_readback) - rtlpriv->io.read8_sync(rtlpriv, addr); -} - -static inline void rtl_write_word(struct rtl_priv *rtlpriv, u32 addr, u16 val16) -{ - rtlpriv->io.write16_async(rtlpriv, addr, val16); - - if (rtlpriv->cfg->write_readback) - rtlpriv->io.read16_sync(rtlpriv, addr); -} - -static inline void rtl_write_dword(struct rtl_priv *rtlpriv, - u32 addr, u32 val32) -{ - rtlpriv->io.write32_async(rtlpriv, addr, val32); - - if (rtlpriv->cfg->write_readback) - rtlpriv->io.read32_sync(rtlpriv, addr); -} - -static inline u32 rtl_get_bbreg(struct ieee80211_hw *hw, - u32 regaddr, u32 bitmask) -{ - struct rtl_priv *rtlpriv = hw->priv; - - return rtlpriv->cfg->ops->get_bbreg(hw, regaddr, bitmask); -} - -static inline void rtl_set_bbreg(struct ieee80211_hw *hw, u32 regaddr, - u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = hw->priv; - - rtlpriv->cfg->ops->set_bbreg(hw, regaddr, bitmask, data); -} - -static inline u32 rtl_get_rfreg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask) -{ - struct rtl_priv *rtlpriv = hw->priv; - - return rtlpriv->cfg->ops->get_rfreg(hw, rfpath, regaddr, bitmask); -} - -static inline void rtl_set_rfreg(struct ieee80211_hw *hw, - enum radio_path rfpath, u32 regaddr, - u32 bitmask, u32 data) -{ - struct rtl_priv *rtlpriv = hw->priv; - - rtlpriv->cfg->ops->set_rfreg(hw, rfpath, regaddr, bitmask, data); -} - -static inline bool is_hal_stop(struct rtl_hal *rtlhal) -{ - return (_HAL_STATE_STOP == rtlhal->state); -} - -static inline void set_hal_start(struct rtl_hal *rtlhal) -{ - rtlhal->state = _HAL_STATE_START; -} - -static inline void set_hal_stop(struct rtl_hal *rtlhal) -{ - rtlhal->state = _HAL_STATE_STOP; -} - -static inline u8 get_rf_type(struct rtl_phy *rtlphy) -{ - return rtlphy->rf_type; -} - -static inline struct ieee80211_hdr *rtl_get_hdr(struct sk_buff *skb) -{ - return (struct ieee80211_hdr *)(skb->data); -} - -static inline __le16 rtl_get_fc(struct sk_buff *skb) -{ - return rtl_get_hdr(skb)->frame_control; -} - -static inline u16 rtl_get_tid_h(struct ieee80211_hdr *hdr) -{ - return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; -} - -static inline u16 rtl_get_tid(struct sk_buff *skb) -{ - return rtl_get_tid_h(rtl_get_hdr(skb)); -} - -static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - const u8 *bssid) -{ - return ieee80211_find_sta(vif, bssid); -} - -static inline struct ieee80211_sta *rtl_find_sta(struct ieee80211_hw *hw, - u8 *mac_addr) -{ - struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); - return ieee80211_find_sta(mac->vif, mac_addr); -} - -#endif -- cgit v1.2.3 From 406df18f1f551a7f54bc68b56cf3ceb36f50cfc4 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Wed, 22 Jul 2015 10:42:43 +0200 Subject: ath9k: Fix NF CCA limits for AR9287 and AR9227 The FreeBSD driver [0] uses the same 2G values as for the AR9280 chips. Using the same values in ath9k results in much better throughput for me. Before this patch I had a huge amount of packet loss (sometimes up to 40%) and the max transfer speed was somewhere around 5Mbit/s. With this patch applied I have zero packet loss and ten times the throughput. My device uses a AR9227 which is the PCI variant of the AR9287. [0] http://bxr.su/FreeBSD/sys/dev/ath/ath_hal/ar9002/ar9287.h Signed-off-by: Martin Blumenstingl Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9002_phy.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index 6314ae2e93e3..9d17a5375f64 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h @@ -610,8 +610,8 @@ #define AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ -127 #define AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ -116 -#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -120 +#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -112 #define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ -127 -#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -110 +#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -97 #endif -- cgit v1.2.3 From 60a188a2715f5cf9f495bd125600453b9e9b1a55 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 10 Sep 2015 07:27:33 -0700 Subject: mwifiex: remove USB8897 chipset support We don't have any customer using this chipset via USB interface. if both mwifiex_pcie and mwifiex_usb modules are enabled by user, sometimes mwifiex_usb wins the race even if user wants wlan interface to be on PCIe and USB for bluetooth. This patch solves the problem. Signed-off-by: Amitkumar Karwar Signed-off-by: Frank Huang Signed-off-by: Nishant Sarmukadam Signed-off-by: Cathy Luo Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/Kconfig | 4 ++-- drivers/net/wireless/mwifiex/usb.c | 14 -------------- drivers/net/wireless/mwifiex/usb.h | 3 --- 3 files changed, 2 insertions(+), 19 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig index 317d99189556..279167ddd293 100644 --- a/drivers/net/wireless/mwifiex/Kconfig +++ b/drivers/net/wireless/mwifiex/Kconfig @@ -33,12 +33,12 @@ config MWIFIEX_PCIE mwifiex_pcie. config MWIFIEX_USB - tristate "Marvell WiFi-Ex Driver for USB8766/8797/8897/8997" + tristate "Marvell WiFi-Ex Driver for USB8766/8797/8997" depends on MWIFIEX && USB select FW_LOADER ---help--- This adds support for wireless adapters based on Marvell - 8797/8897/8997 chipset with USB interface. + 8797/8997 chipset with USB interface. If you choose to build it as a module, it will be called mwifiex_usb. diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 9f5356ef0531..e43aff932360 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -42,11 +42,6 @@ static struct usb_device_id mwifiex_usb_table[] = { {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8801_PID_2, USB_CLASS_VENDOR_SPEC, USB_SUBCLASS_VENDOR_SPEC, 0xff)}, - /* 8897 */ - {USB_DEVICE(USB8XXX_VID, USB8897_PID_1)}, - {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8897_PID_2, - USB_CLASS_VENDOR_SPEC, - USB_SUBCLASS_VENDOR_SPEC, 0xff)}, /* 8997 */ {USB_DEVICE(USB8XXX_VID, USB8997_PID_1)}, {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8997_PID_2, @@ -403,14 +398,12 @@ static int mwifiex_usb_probe(struct usb_interface *intf, case USB8766_PID_1: case USB8797_PID_1: case USB8801_PID_1: - case USB8897_PID_1: case USB8997_PID_1: card->usb_boot_state = USB8XXX_FW_DNLD; break; case USB8766_PID_2: case USB8797_PID_2: case USB8801_PID_2: - case USB8897_PID_2: case USB8997_PID_2: card->usb_boot_state = USB8XXX_FW_READY; break; @@ -964,12 +957,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) strcpy(adapter->fw_name, USB8997_DEFAULT_FW_NAME); adapter->ext_scan = true; break; - case USB8897_PID_1: - case USB8897_PID_2: - adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; - strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); - adapter->ext_scan = true; - break; case USB8766_PID_1: case USB8766_PID_2: adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; @@ -1277,5 +1264,4 @@ MODULE_LICENSE("GPL v2"); MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME); MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME); MODULE_FIRMWARE(USB8801_DEFAULT_FW_NAME); -MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME); MODULE_FIRMWARE(USB8997_DEFAULT_FW_NAME); diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h index bab10ee41923..67be72b062cf 100644 --- a/drivers/net/wireless/mwifiex/usb.h +++ b/drivers/net/wireless/mwifiex/usb.h @@ -28,8 +28,6 @@ #define USB8766_PID_2 0x2042 #define USB8797_PID_1 0x2043 #define USB8797_PID_2 0x2044 -#define USB8897_PID_1 0x2045 -#define USB8897_PID_2 0x2046 #define USB8801_PID_1 0x2049 #define USB8801_PID_2 0x204a #define USB8997_PID_1 0x204d @@ -48,7 +46,6 @@ #define USB8766_DEFAULT_FW_NAME "mrvl/usb8766_uapsta.bin" #define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin" #define USB8801_DEFAULT_FW_NAME "mrvl/usb8801_uapsta.bin" -#define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin" #define USB8997_DEFAULT_FW_NAME "mrvl/usb8997_uapsta.bin" #define FW_DNLD_TX_BUF_SIZE 620 -- cgit v1.2.3 From ce03966a16b03e5cf1a9cbd2f42ca0fbe4118ab5 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Thu, 10 Sep 2015 07:27:34 -0700 Subject: mwifiex: correction in USB8997 chipset's product ID For 8897 chipset, mwifiex_usb unnecessarily used to come into picture when wlan is supposed to be used via PCIe interface and USB interface is for bluetooth. This problem has been resolved for newer chipset by having separate USB product ids for USB-USB8997 and PCIe-USB8997 chipset variants. This patch ensures to use wlan specific product id. Signed-off-by: Amitkumar Karwar Signed-off-by: Frank Huang Signed-off-by: Nishant Sarmukadam Signed-off-by: Cathy Luo Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/usb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h index 67be72b062cf..b4e9246bbcdc 100644 --- a/drivers/net/wireless/mwifiex/usb.h +++ b/drivers/net/wireless/mwifiex/usb.h @@ -30,7 +30,7 @@ #define USB8797_PID_2 0x2044 #define USB8801_PID_1 0x2049 #define USB8801_PID_2 0x204a -#define USB8997_PID_1 0x204d +#define USB8997_PID_1 0x2052 #define USB8997_PID_2 0x204e -- cgit v1.2.3 From 16a4ea506503343a066e9b986e4775bf472e5205 Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Tue, 15 Sep 2015 09:01:56 +0300 Subject: rtlwifi: rtl8192cu: Add missing case in rtl92cu_get_hw_reg Driver was reporting 'switch case not processed' after association, so HW_VAR_KEEP_ALIVE was added and filled similarily to other drivers. Positive side effect to this seems to be a bit more stable connection. Signed-off-by: Priit Laes Acked-by: Larry Finger Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c index 25db369b5d18..34ce06441d1b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c @@ -1946,6 +1946,14 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *)val); mac->rx_data_filter = *(u16 *)val; break; + case HW_VAR_KEEP_ALIVE:{ + u8 array[2]; + array[0] = 0xff; + array[1] = *((u8 *)val); + rtl92c_fill_h2c_cmd(hw, H2C_92C_KEEP_ALIVE_CTRL, 2, + array); + break; + } default: RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "switch case not processed\n"); -- cgit v1.2.3 From 871d0051f06030bfddd5971ef2afc1eb7291ab4e Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Tue, 29 Sep 2015 13:24:36 +0800 Subject: ath9k: rename ini_modes_rxgain_5g_xlna to ini_modes_rxgain_xlna rename the variable as preparation for using the array with 2.4 GHz band, etc. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 10 +++++----- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 4 ++-- drivers/net/wireless/ath/ath9k/hw.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 79fd3b2dcbde..8b238c15916d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -857,7 +857,7 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) qca956x_1p0_common_rx_gain_table); INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, qca956x_1p0_common_rx_gain_bounds); - INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna, qca956x_1p0_xlna_only); } else if (AR_SREV_9580(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, @@ -942,7 +942,7 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah) ar9462_2p1_baseband_core_mix_rxgain); INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble, ar9462_2p1_baseband_postamble_mix_rxgain); - INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna, ar9462_2p1_baseband_postamble_5g_xlna); } else if (AR_SREV_9462_20(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, @@ -951,7 +951,7 @@ static void ar9003_rx_gain_table_mode2(struct ath_hw *ah) ar9462_2p0_baseband_core_mix_rxgain); INIT_INI_ARRAY(&ah->ini_modes_rxgain_bb_postamble, ar9462_2p0_baseband_postamble_mix_rxgain); - INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna, ar9462_2p0_baseband_postamble_5g_xlna); } } @@ -961,12 +961,12 @@ static void ar9003_rx_gain_table_mode3(struct ath_hw *ah) if (AR_SREV_9462_21(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, ar9462_2p1_common_5g_xlna_only_rxgain); - INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna, ar9462_2p1_baseband_postamble_5g_xlna); } else if (AR_SREV_9462_20(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, ar9462_2p0_common_5g_xlna_only_rxgain); - INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + INIT_INI_ARRAY(&ah->ini_modes_rxgain_xlna, ar9462_2p0_baseband_postamble_5g_xlna); } } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 1ad66b76749b..296a69ebfbf6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -926,12 +926,12 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, */ if ((ar9003_hw_get_rx_gain_idx(ah) == 2) || (ar9003_hw_get_rx_gain_idx(ah) == 3)) { - REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + REG_WRITE_ARRAY(&ah->ini_modes_rxgain_xlna, modesIndex, regWrites); } if (AR_SREV_9561(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0)) - REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna, + REG_WRITE_ARRAY(&ah->ini_modes_rxgain_xlna, modesIndex, regWrites); } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e8454db17634..4f0a3f6b0c52 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -919,7 +919,7 @@ struct ath_hw { struct ar5416IniArray iniCckfirJapan2484; struct ar5416IniArray iniModes_9271_ANI_reg; struct ar5416IniArray ini_radio_post_sys2ant; - struct ar5416IniArray ini_modes_rxgain_5g_xlna; + struct ar5416IniArray ini_modes_rxgain_xlna; struct ar5416IniArray ini_modes_rxgain_bb_core; struct ar5416IniArray ini_modes_rxgain_bb_postamble; -- cgit v1.2.3 From cfa2b42b4d9a3dc10aa1e0c82213f3d30d5bcdf8 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Tue, 29 Sep 2015 13:24:37 +0800 Subject: ath9k: fix QCA9561 XLNA rxgain initial A small bugfix for commit ede6a5e7b859 ("ath9k: Add QCA956x HW support"). I guess I would have skipped renaming (that initial QCA956x commit has been there already for almost a year with the "5g" in the name) and move the call outside AR_SREV_9462_20_OR_LATER() to make it reachable. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 296a69ebfbf6..201425e7f9cb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -929,16 +929,15 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, REG_WRITE_ARRAY(&ah->ini_modes_rxgain_xlna, modesIndex, regWrites); } - - if (AR_SREV_9561(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0)) - REG_WRITE_ARRAY(&ah->ini_modes_rxgain_xlna, - modesIndex, regWrites); } if (AR_SREV_9550(ah) || AR_SREV_9561(ah)) REG_WRITE_ARRAY(&ah->ini_modes_rx_gain_bounds, modesIndex, regWrites); + if (AR_SREV_9561(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0)) + REG_WRITE_ARRAY(&ah->ini_modes_rxgain_xlna, + modesIndex, regWrites); /* * TXGAIN initvals. */ -- cgit v1.2.3 From a484804b3eb8de64a2497c484a08359f7ae28210 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sun, 4 Oct 2015 16:46:55 +0800 Subject: mwifiex: fix a comment typo Just fix a typo in the code comment. Signed-off-by: Geliang Tang Acked-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 30cbafbd17c6..b7ac45f324d7 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -2374,7 +2374,7 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) * CFG802.11 operation handler for scan request. * * This function issues a scan request to the firmware based upon - * the user specified scan configuration. On successfull completion, + * the user specified scan configuration. On successful completion, * it also informs the results. */ static int -- cgit v1.2.3 From 46dbe2476c93026b20ddf36c6995e678bd867000 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 9 Oct 2015 04:26:23 -0700 Subject: mwifiex: control WLAN and bluetooth coexistence modes By default our chip will be in spatial coexistence mode. This patch adds a provision to change it to timeshare mode via debugfs command. Enable timeshare coexistence mode echo 1 > /sys/kernel/debug/mwifiex/mlan0/timeshare_coex Go back to spacial coexistence mode echo 0 > /sys/kernel/debug/mwifiex/mlan0/timeshare_coex Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/debugfs.c | 52 ++++++++++++++++++++++++++++++ drivers/net/wireless/mwifiex/fw.h | 16 +++++++++ drivers/net/wireless/mwifiex/sta_cmd.c | 31 ++++++++++++++++++ drivers/net/wireless/mwifiex/sta_cmdresp.c | 25 ++++++++++++++ 4 files changed, 124 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index 5583856fc5c4..9824d8dd2b44 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -856,6 +856,56 @@ mwifiex_hscfg_read(struct file *file, char __user *ubuf, return ret; } +static ssize_t +mwifiex_timeshare_coex_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mwifiex_private *priv = file->private_data; + char buf[3]; + bool timeshare_coex; + int ret; + unsigned int len; + + if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15) + return -EOPNOTSUPP; + + ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX, + HostCmd_ACT_GEN_GET, 0, ×hare_coex, true); + if (ret) + return ret; + + len = sprintf(buf, "%d\n", timeshare_coex); + return simple_read_from_buffer(ubuf, count, ppos, buf, len); +} + +static ssize_t +mwifiex_timeshare_coex_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + bool timeshare_coex; + struct mwifiex_private *priv = file->private_data; + char kbuf[16]; + int ret; + + if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15) + return -EOPNOTSUPP; + + memset(kbuf, 0, sizeof(kbuf)); + + if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, count))) + return -EFAULT; + + if (strtobool(kbuf, ×hare_coex)) + return -EINVAL; + + ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX, + HostCmd_ACT_GEN_SET, 0, ×hare_coex, true); + if (ret) + return ret; + else + return count; +} + #define MWIFIEX_DFS_ADD_FILE(name) do { \ if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir, \ priv, &mwifiex_dfs_##name##_fops)) \ @@ -892,6 +942,7 @@ MWIFIEX_DFS_FILE_OPS(memrw); MWIFIEX_DFS_FILE_OPS(hscfg); MWIFIEX_DFS_FILE_OPS(histogram); MWIFIEX_DFS_FILE_OPS(debug_mask); +MWIFIEX_DFS_FILE_OPS(timeshare_coex); /* * This function creates the debug FS directory structure and the files. @@ -918,6 +969,7 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv) MWIFIEX_DFS_ADD_FILE(hscfg); MWIFIEX_DFS_ADD_FILE(histogram); MWIFIEX_DFS_ADD_FILE(debug_mask); + MWIFIEX_DFS_ADD_FILE(timeshare_coex); } /* diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 0e6f029458d5..1e1e81a0a8d4 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -101,6 +101,9 @@ enum KEY_TYPE_ID { #define FIRMWARE_READY_SDIO 0xfedc #define FIRMWARE_READY_PCIE 0xfedcba00 +#define MWIFIEX_COEX_MODE_TIMESHARE 0x01 +#define MWIFIEX_COEX_MODE_SPATIAL 0x82 + enum mwifiex_usb_ep { MWIFIEX_USB_EP_CMD_EVENT = 1, MWIFIEX_USB_EP_DATA = 2, @@ -163,6 +166,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_CHANRPT_11H_BASIC (PROPRIETARY_TLV_BASE_ID + 91) #define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) +#define TLV_TYPE_ROBUST_COEX (PROPRIETARY_TLV_BASE_ID + 96) #define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) #define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105) #define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) @@ -354,6 +358,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df #define HostCmd_CMD_TXPWR_CFG 0x00d1 #define HostCmd_CMD_TX_RATE_CFG 0x00d6 +#define HostCmd_CMD_ROBUST_COEX 0x00e0 #define HostCmd_CMD_802_11_PS_MODE_ENH 0x00e4 #define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5 #define HostCmd_CMD_P2P_MODE_CFG 0x00eb @@ -1877,6 +1882,11 @@ struct mwifiex_ie_types_btcoex_aggr_win_size { u8 reserved; } __packed; +struct mwifiex_ie_types_robust_coex { + struct mwifiex_ie_types_header header; + __le32 mode; +} __packed; + struct host_cmd_ds_version_ext { u8 version_str_sel; char version_str[128]; @@ -2078,6 +2088,11 @@ struct host_cmd_ds_multi_chan_policy { __le16 policy; } __packed; +struct host_cmd_ds_robust_coex { + __le16 action; + __le16 reserved; +} __packed; + struct host_cmd_ds_command { __le16 command; __le16 size; @@ -2147,6 +2162,7 @@ struct host_cmd_ds_command { struct host_cmd_ds_chan_rpt_req chan_rpt_req; struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg; struct host_cmd_ds_multi_chan_policy mc_policy; + struct host_cmd_ds_robust_coex coex; } params; } __packed; diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 504b321301ec..e486867a4c67 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -1531,6 +1531,33 @@ mwifiex_cmd_set_mc_policy(struct mwifiex_private *priv, return 0; } +static int mwifiex_cmd_robust_coex(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + u16 cmd_action, bool *is_timeshare) +{ + struct host_cmd_ds_robust_coex *coex = &cmd->params.coex; + struct mwifiex_ie_types_robust_coex *coex_tlv; + + cmd->command = cpu_to_le16(HostCmd_CMD_ROBUST_COEX); + cmd->size = cpu_to_le16(sizeof(*coex) + sizeof(*coex_tlv) + S_DS_GEN); + + coex->action = cpu_to_le16(cmd_action); + coex_tlv = (struct mwifiex_ie_types_robust_coex *) + ((u8 *)coex + sizeof(*coex)); + coex_tlv->header.type = cpu_to_le16(TLV_TYPE_ROBUST_COEX); + coex_tlv->header.len = cpu_to_le16(sizeof(coex_tlv->mode)); + + if (coex->action == HostCmd_ACT_GEN_GET) + return 0; + + if (*is_timeshare) + coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_TIMESHARE); + else + coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_SPATIAL); + + return 0; +} + static int mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, @@ -2040,6 +2067,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, ret = mwifiex_cmd_set_mc_policy(priv, cmd_ptr, cmd_action, data_buf); break; + case HostCmd_CMD_ROBUST_COEX: + ret = mwifiex_cmd_robust_coex(priv, cmd_ptr, cmd_action, + data_buf); + break; default: mwifiex_dbg(priv->adapter, ERROR, "PREP_CMD: unknown cmd- %#x\n", cmd_no); diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index d0961635c7b3..9ac7aa2431b4 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -1007,6 +1007,28 @@ static int mwifiex_ret_sdio_rx_aggr_cfg(struct mwifiex_private *priv, return 0; } +static int mwifiex_ret_robust_coex(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + bool *is_timeshare) +{ + struct host_cmd_ds_robust_coex *coex = &resp->params.coex; + struct mwifiex_ie_types_robust_coex *coex_tlv; + u16 action = le16_to_cpu(coex->action); + u32 mode; + + coex_tlv = (struct mwifiex_ie_types_robust_coex + *)((u8 *)coex + sizeof(struct host_cmd_ds_robust_coex)); + if (action == HostCmd_ACT_GEN_GET) { + mode = le32_to_cpu(coex_tlv->mode); + if (mode == MWIFIEX_COEX_MODE_TIMESHARE) + *is_timeshare = true; + else + *is_timeshare = false; + } + + return 0; +} + /* * This function handles the command responses. * @@ -1213,6 +1235,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, break; case HostCmd_CMD_TDLS_CONFIG: break; + case HostCmd_CMD_ROBUST_COEX: + ret = mwifiex_ret_robust_coex(priv, resp, data_buf); + break; default: mwifiex_dbg(adapter, ERROR, "CMD_RESP: unknown cmd response %#x\n", -- cgit v1.2.3 From 505c5cb82ddf0fb6a88d1fc2fbf2386133a9ffcd Mon Sep 17 00:00:00 2001 From: Ganapathi Bhat Date: Fri, 9 Oct 2015 04:26:33 -0700 Subject: mwifiex: fix AP VHT behaviour Even if hostapd configuration file contains VHT parameters, they were not getting reflected in beacons. The reason is we are resetting them before starting AP. This patch removes redundant BSS_STOP and SYS_RESET firmware commands before starting AP to fix the problem. Signed-off-by: Ganapathi Bhat Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/uap_cmd.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 4d5a6e3b6361..759a6ada5b0f 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c @@ -846,22 +846,6 @@ int mwifiex_config_start_uap(struct mwifiex_private *priv, { enum state_11d_t state_11d; - if (mwifiex_del_mgmt_ies(priv)) - mwifiex_dbg(priv->adapter, ERROR, - "Failed to delete mgmt IEs!\n"); - - if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, - HostCmd_ACT_GEN_SET, 0, NULL, true)) { - mwifiex_dbg(priv->adapter, ERROR, "Failed to stop the BSS\n"); - return -1; - } - - if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET, - HostCmd_ACT_GEN_SET, 0, NULL, true)) { - mwifiex_dbg(priv->adapter, ERROR, "Failed to reset BSS\n"); - return -1; - } - if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, HostCmd_ACT_GEN_SET, UAP_BSS_PARAMS_I, bss_cfg, false)) { -- cgit v1.2.3 From fe24372d1b115863905174aa3c9f988c1eb40630 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Fri, 9 Oct 2015 04:26:34 -0700 Subject: mwifiex: add ndo_validate_addr netdev ops ndo_validate_addr is set to generic eth_validate_addr() function used for MAC address validation. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 6e3faa74389c..969ca1e1f3e9 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -1199,6 +1199,7 @@ static const struct net_device_ops mwifiex_netdev_ops = { .ndo_stop = mwifiex_close, .ndo_start_xmit = mwifiex_hard_start_xmit, .ndo_set_mac_address = mwifiex_set_mac_address, + .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = mwifiex_tx_timeout, .ndo_get_stats = mwifiex_get_stats, .ndo_set_rx_mode = mwifiex_set_multicast_list, -- cgit v1.2.3 From 8785955bbc28be446bcb2ad08cfb0599246746f7 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Fri, 9 Oct 2015 04:26:35 -0700 Subject: mwifiex: remove unnecessary NULL check ra_list cannot be NULL here, so remove the unnecessary NULL check. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/wmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 57c13ec3d3de..acccd6734e3b 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -684,7 +684,7 @@ void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv, if (!memcmp(ra_list->ra, mac, ETH_ALEN)) continue; - if (ra_list && ra_list->tx_paused != tx_pause) { + if (ra_list->tx_paused != tx_pause) { pkt_cnt += ra_list->total_pkt_count; ra_list->tx_paused = tx_pause; if (tx_pause) -- cgit v1.2.3 From 4568637f7a20bbb1dcbf8ada56de08f6c940bcbd Mon Sep 17 00:00:00 2001 From: yankejian Date: Tue, 13 Oct 2015 09:53:45 +0800 Subject: net: hisilicon: supports promisc mode this patch adds support to set promisc mode. it configs the queue on init seq when it is on promisc mode.and being enabled or disabled promisc mode by upper level user. Signed-off-by: yankejian Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hnae.h | 1 + drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c | 6 +++++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 27 ++++++++++++++++++++++ drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h | 1 + drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 4 ++-- drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h | 2 ++ drivers/net/ethernet/hisilicon/hns/hns_enet.c | 17 +++++++++++++- 7 files changed, 55 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index d4a1eb1b8e54..cec95ac8687d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -430,6 +430,7 @@ struct hnae_ae_ops { void (*set_coalesce_usecs)(struct hnae_handle *handle, u32 timeout); int (*set_coalesce_frames)(struct hnae_handle *handle, u32 coalesce_frames); + void (*set_promisc_mode)(struct hnae_handle *handle, u32 en); int (*get_mac_addr)(struct hnae_handle *handle, void **p); int (*set_mac_addr)(struct hnae_handle *handle, void *p); int (*set_mc_addr)(struct hnae_handle *handle, void *addr); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index a2c72f84e397..1a16c0307b47 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -392,6 +392,11 @@ static int hns_ae_set_autoneg(struct hnae_handle *handle, u8 enable) return hns_mac_set_autoneg(hns_get_mac_cb(handle), enable); } +static void hns_ae_set_promisc_mode(struct hnae_handle *handle, u32 en) +{ + hns_dsaf_set_promisc_mode(hns_ae_get_dsaf_dev(handle->dev), en); +} + static int hns_ae_get_autoneg(struct hnae_handle *handle) { u32 auto_neg; @@ -748,6 +753,7 @@ static struct hnae_ae_ops hns_dsaf_ops = { .get_rx_max_coalesced_frames = hns_ae_get_rx_max_coalesced_frames, .set_coalesce_usecs = hns_ae_set_coalesce_usecs, .set_coalesce_frames = hns_ae_set_coalesce_frames, + .set_promisc_mode = hns_ae_set_promisc_mode, .set_mac_addr = hns_ae_set_mac_address, .set_mc_addr = hns_ae_set_multicast_one, .set_mtu = hns_ae_set_mtu, diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 26ae6c64d74c..ffc2604766b6 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -217,6 +217,25 @@ hns_dsaf_ppe_qid_cfg(struct dsaf_device *dsaf_dev, u32 qid_cfg) } } +static void hns_dsaf_mix_def_qid_cfg(struct dsaf_device *dsaf_dev) +{ + u16 max_q_per_vf, max_vfn; + u32 q_id, q_num_per_port; + u32 i; + + hns_rcb_get_queue_mode(dsaf_dev->dsaf_mode, + HNS_DSAF_COMM_SERVICE_NW_IDX, + &max_vfn, &max_q_per_vf); + q_num_per_port = max_vfn * max_q_per_vf; + + for (i = 0, q_id = 0; i < DSAF_SERVICE_NW_NUM; i++) { + dsaf_set_dev_field(dsaf_dev, + DSAF_MIX_DEF_QID_0_REG + 0x0004 * i, + 0xff, 0, q_id); + q_id += q_num_per_port; + } +} + /** * hns_dsaf_sw_port_type_cfg - cfg sw type * @dsaf_id: dsa fabric id @@ -592,6 +611,11 @@ static void hns_dsaf_tbl_tcam_data_ucast_pul( dsaf_write_dev(dsaf_dev, DSAF_TBL_PUL_0_REG, o_tbl_pul); } +void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en) +{ + dsaf_set_dev_bit(dsaf_dev, DSAF_CFG_0_REG, DSAF_CFG_MIX_MODE_S, !!en); +} + /** * hns_dsaf_tbl_stat_en - tbl * @dsaf_id: dsa fabric id @@ -920,6 +944,9 @@ static void hns_dsaf_comm_init(struct dsaf_device *dsaf_dev) /* set 22 queue per tx ppe engine, only used in switch mode */ hns_dsaf_ppe_qid_cfg(dsaf_dev, DSAF_DEFAUTL_QUEUE_NUM_PER_PPE); + /* set promisc def queue id */ + hns_dsaf_mix_def_qid_cfg(dsaf_dev); + /* in non switch mode, set all port to access mode */ hns_dsaf_sw_port_type_cfg(dsaf_dev, DSAF_SW_PORT_TYPE_NON_VLAN); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index 315b07ecd291..b2b93484995c 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -423,5 +423,6 @@ void hns_dsaf_get_strings(int stringset, u8 *data, int port); void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data); int hns_dsaf_get_regs_count(void); +void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en); #endif /* __HNS_DSAF_MAIN_H__ */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index 05ea244d999c..4db32c62f062 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -575,8 +575,8 @@ int hns_rcb_set_coalesced_frames(struct dsaf_device *dsaf_dev, *@max_vfn : max vfn number *@max_q_per_vf:max ring number per vm */ -static void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, int comm_index, - u16 *max_vfn, u16 *max_q_per_vf) +void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, int comm_index, + u16 *max_vfn, u16 *max_q_per_vf) { if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { switch (dsaf_mode) { diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h index c7db6130a3cf..3a2afe2dd8bb 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h @@ -107,6 +107,8 @@ int hns_rcb_common_init_hw(struct rcb_common_cb *rcb_common); void hns_rcb_start(struct hnae_queue *q, u32 val); void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common); void hns_rcb_common_init_commit_hw(struct rcb_common_cb *rcb_common); +void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode, int comm_index, + u16 *max_vfn, u16 *max_q_per_vf); void hns_rcb_ring_enable_hw(struct hnae_queue *q, u32 val); void hns_rcb_int_clr_hw(struct hnae_queue *q, u32 flag); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index ce7f2e0e3fd1..6f9091c29869 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1161,6 +1161,21 @@ void hns_set_multicast_list(struct net_device *ndev) } } +void hns_nic_set_rx_mode(struct net_device *ndev) +{ + struct hns_nic_priv *priv = netdev_priv(ndev); + struct hnae_handle *h = priv->ae_handle; + + if (h->dev->ops->set_promisc_mode) { + if (ndev->flags & IFF_PROMISC) + h->dev->ops->set_promisc_mode(h, 1); + else + h->dev->ops->set_promisc_mode(h, 0); + } + + hns_set_multicast_list(ndev); +} + struct rtnl_link_stats64 *hns_nic_get_stats64(struct net_device *ndev, struct rtnl_link_stats64 *stats) { @@ -1220,7 +1235,7 @@ static const struct net_device_ops hns_nic_netdev_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = hns_nic_poll_controller, #endif - .ndo_set_rx_mode = hns_set_multicast_list, + .ndo_set_rx_mode = hns_nic_set_rx_mode, }; static void hns_nic_update_link_status(struct net_device *netdev) -- cgit v1.2.3 From 4a733ef1bea705cdc69d936b95fedab4b47fbd40 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 14 Oct 2015 18:02:43 +0200 Subject: mac80211: remove PM-QoS listener As this API has never really seen any use and most drivers don't ever use the value derived from it, remove it. Change the only driver using it (rt2x00) to simply use the DTIM period instead of the "max sleep" time. Signed-off-by: Johannes Berg --- drivers/net/wireless/rt2x00/rt2x00config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 48a2cad29477..7e8bb1198ae9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -266,7 +266,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, if (beacon_diff > beacon_int) beacon_diff = 0; - autowake_timeout = (conf->max_sleep_period * beacon_int) - beacon_diff; + autowake_timeout = (conf->ps_dtim_period * beacon_int) - beacon_diff; queue_delayed_work(rt2x00dev->workqueue, &rt2x00dev->autowakeup_work, autowake_timeout - 15); -- cgit v1.2.3 From 2f8e2c877784a0b23f02b41550170a24e14f5c95 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 28 Aug 2015 09:27:14 +0200 Subject: move io-64-nonatomic*.h out of asm-generic These are not implementations of default architecture code but helpers for drivers. Move them to the place they belong to. Signed-off-by: Christoph Hellwig Acked-by: Darren Hart Acked-by: Hitoshi Mitake Signed-off-by: Arnd Bergmann --- drivers/net/ethernet/intel/i40e/i40e_osdep.h | 2 +- drivers/net/ethernet/intel/i40evf/i40e_osdep.h | 2 +- drivers/net/ethernet/rocker/rocker.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_osdep.h b/drivers/net/ethernet/intel/i40e/i40e_osdep.h index ad802dd0f67a..5b6feb7edeb1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_osdep.h +++ b/drivers/net/ethernet/intel/i40e/i40e_osdep.h @@ -35,7 +35,7 @@ #include /* get readq/writeq support for 32 bit kernels, use the low-first version */ -#include +#include /* File to be the magic between shared code and * actual OS primitives diff --git a/drivers/net/ethernet/intel/i40evf/i40e_osdep.h b/drivers/net/ethernet/intel/i40evf/i40e_osdep.h index 21a91b14bf81..5e314fd3c016 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_osdep.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_osdep.h @@ -34,7 +34,7 @@ #include /* get readq/writeq support for 32 bit kernels, use the low-first version */ -#include +#include /* File to be the magic between shared code and * actual OS primitives diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 34ac41ac9e61..7ca1abbc0d05 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include "rocker.h" -- cgit v1.2.3 From adec640e03668e42f30f3b09c0b4d60d44545f6f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 28 Aug 2015 09:27:19 +0200 Subject: mlx5: stop including is the placace the get the kmap type flags, asm-generic files are generic implementations only to be used by architecture code. Signed-off-by: Christoph Hellwig Signed-off-by: Arnd Bergmann --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/main.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 75ff58dc1ff5..594a1499cf9b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -30,7 +30,7 @@ * SOFTWARE. */ -#include +#include #include #include #include diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 03aabdd79abe..c74c72371401 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -30,7 +30,7 @@ * SOFTWARE. */ -#include +#include #include #include #include diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index 8a64542abc16..fda02eccb66e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c @@ -30,7 +30,7 @@ * SOFTWARE. */ -#include +#include #include #include #include -- cgit v1.2.3 From 7f0abb1f0f2b110ec38ade73c241fcba30f9112a Mon Sep 17 00:00:00 2001 From: lipeng Date: Wed, 14 Oct 2015 10:28:57 +0800 Subject: net: hisilicon net: fix a bug about led this patch fixes a bug in hns driver. the link led is on at the beginning, but at this time the ethernet port is on down status. it needs to reset the led status on init sequence. Signed-off-by: lipeng Signed-off-by: yankejian Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 95bf42aae24c..f8f734722891 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -744,9 +744,11 @@ int hns_mac_get_cfg(struct dsaf_device *dsaf_dev, int mac_idx) mac_cb->serdes_vaddr = dsaf_dev->sds_base; if (dsaf_dev->cpld_base && - mac_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF) + mac_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF) { mac_cb->cpld_vaddr = dsaf_dev->cpld_base + mac_cb->mac_id * CPLD_ADDR_PORT_OFFSET; + cpld_led_reset(mac_cb); + } mac_cb->sfp_prsnt = 0; mac_cb->txpkt_for_led = 0; mac_cb->rxpkt_for_led = 0; -- cgit v1.2.3 From fb0801dcc17845ef52a19f9f9fbbb88a1a93f9b6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 14 Oct 2015 18:30:48 +0800 Subject: net: phy: aquantia/teranetics: Convert to use module_phy_driver macro Use module_phy_driver macro to simplify the code a bit. Signed-off-by: Axel Lin Signed-off-by: David S. Miller --- drivers/net/phy/aquantia.c | 15 +-------------- drivers/net/phy/teranetics.c | 15 +-------------- 2 files changed, 2 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index d6111affbcb6..f1936b7a7af6 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -171,20 +171,7 @@ static struct phy_driver aquantia_driver[] = { }, }; -static int __init aquantia_init(void) -{ - return phy_drivers_register(aquantia_driver, - ARRAY_SIZE(aquantia_driver)); -} - -static void __exit aquantia_exit(void) -{ - return phy_drivers_unregister(aquantia_driver, - ARRAY_SIZE(aquantia_driver)); -} - -module_init(aquantia_init); -module_exit(aquantia_exit); +module_phy_driver(aquantia_driver); static struct mdio_device_id __maybe_unused aquantia_tbl[] = { { PHY_ID_AQ1202, 0xfffffff0 }, diff --git a/drivers/net/phy/teranetics.c b/drivers/net/phy/teranetics.c index 91e1bec6079f..07463fcca212 100644 --- a/drivers/net/phy/teranetics.c +++ b/drivers/net/phy/teranetics.c @@ -112,20 +112,7 @@ static struct phy_driver teranetics_driver[] = { }, }; -static int __init teranetics_init(void) -{ - return phy_drivers_register(teranetics_driver, - ARRAY_SIZE(teranetics_driver)); -} - -static void __exit teranetics_exit(void) -{ - return phy_drivers_unregister(teranetics_driver, - ARRAY_SIZE(teranetics_driver)); -} - -module_init(teranetics_init); -module_exit(teranetics_exit); +module_phy_driver(teranetics_driver); static struct mdio_device_id __maybe_unused teranetics_tbl[] = { { PHY_ID_TN2020, 0xffffffff }, -- cgit v1.2.3 From fd76ee4da55abb21babfc69310d321b9cb9a32e0 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Wed, 14 Oct 2015 17:43:45 +0300 Subject: net/mlx5_core: Fix internal error detection conditions The detection of a fatal condition has been updated to take into account the state reported by the device or by detecting an all ones read of the firmware version which indicates that the device is not accessible. Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/health.c | 51 ++++++++++++++++++++---- 1 file changed, 44 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 9b81e1ceb8de..f1eb686c45b1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -57,6 +57,31 @@ enum { MLX5_HEALTH_SYNDR_HIGH_TEMP = 0x10 }; +enum { + MLX5_NIC_IFC_FULL = 0, + MLX5_NIC_IFC_DISABLED = 1, + MLX5_NIC_IFC_NO_DRAM_NIC = 2 +}; + +static u8 get_nic_interface(struct mlx5_core_dev *dev) +{ + return (ioread32be(&dev->iseg->cmdq_addr_l_sz) >> 8) & 3; +} + +static int in_fatal(struct mlx5_core_dev *dev) +{ + struct mlx5_core_health *health = &dev->priv.health; + struct health_buffer __iomem *h = health->health; + + if (get_nic_interface(dev) == MLX5_NIC_IFC_DISABLED) + return 1; + + if (ioread32be(&h->fw_ver) == 0xffffffff) + return 1; + + return 0; +} + static void health_care(struct work_struct *work) { struct mlx5_core_health *health; @@ -136,11 +161,21 @@ static void print_health_info(struct mlx5_core_dev *dev) dev_err(&dev->pdev->dev, "ext_synd 0x%04x\n", ioread16be(&h->ext_synd)); } +static unsigned long get_next_poll_jiffies(void) +{ + unsigned long next; + + get_random_bytes(&next, sizeof(next)); + next %= HZ; + next += jiffies + MLX5_HEALTH_POLL_INTERVAL; + + return next; +} + static void poll_health(unsigned long data) { struct mlx5_core_dev *dev = (struct mlx5_core_dev *)data; struct mlx5_core_health *health = &dev->priv.health; - unsigned long next; u32 count; count = ioread32be(health->health_counter); @@ -151,14 +186,16 @@ static void poll_health(unsigned long data) health->prev = count; if (health->miss_counter == MAX_MISSES) { - mlx5_core_err(dev, "device's health compromised\n"); + dev_err(&dev->pdev->dev, "device's health compromised - reached miss count\n"); print_health_info(dev); - queue_work(health->wq, &health->work); } else { - get_random_bytes(&next, sizeof(next)); - next %= HZ; - next += jiffies + MLX5_HEALTH_POLL_INTERVAL; - mod_timer(&health->timer, next); + mod_timer(&health->timer, get_next_poll_jiffies()); + } + + if (in_fatal(dev) && !health->sick) { + health->sick = true; + print_health_info(dev); + queue_work(health->wq, &health->work); } } -- cgit v1.2.3 From 89d44f0a6c732db23b219be708e2fe1e03ee4842 Mon Sep 17 00:00:00 2001 From: Majd Dibbiny Date: Wed, 14 Oct 2015 17:43:46 +0300 Subject: net/mlx5_core: Add pci error handlers to mlx5_core driver This patch implement the pci_error_handlers for mlx5_core which allow the driver to recover from PCI error. Once an error is detected in the PCI, the mlx5_pci_err_detected is called and it: 1) Marks the device to be in 'Internal Error' state. 2) Dispatches an event to the mlx5_ib to flush all the outstanding cqes with error. 3) Returns all the on going commands with error. 4) Unloads the driver. Afterwards, the FW is reset and mlx5_pci_slot_reset is called and it enables the device and restore it's pci state. If the later succeeds, mlx5_pci_resume is called, and it loads the SW stack. Signed-off-by: Majd Dibbiny Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 170 +++++++++++++++++++ drivers/net/ethernet/mellanox/mlx5/core/health.c | 72 ++++++++ drivers/net/ethernet/mellanox/mlx5/core/main.c | 182 ++++++++++++++++++++- .../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 4 + .../net/ethernet/mellanox/mlx5/core/pagealloc.c | 13 +- 5 files changed, 429 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index c3e54b7e8780..fabfc9e0a948 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -256,8 +256,154 @@ static void dump_buf(void *buf, int size, int data_only, int offset) enum { MLX5_DRIVER_STATUS_ABORTED = 0xfe, + MLX5_DRIVER_SYND = 0xbadd00de, }; +static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, + u32 *synd, u8 *status) +{ + *synd = 0; + *status = 0; + + switch (op) { + case MLX5_CMD_OP_TEARDOWN_HCA: + case MLX5_CMD_OP_DISABLE_HCA: + case MLX5_CMD_OP_MANAGE_PAGES: + case MLX5_CMD_OP_DESTROY_MKEY: + case MLX5_CMD_OP_DESTROY_EQ: + case MLX5_CMD_OP_DESTROY_CQ: + case MLX5_CMD_OP_DESTROY_QP: + case MLX5_CMD_OP_DESTROY_PSV: + case MLX5_CMD_OP_DESTROY_SRQ: + case MLX5_CMD_OP_DESTROY_XRC_SRQ: + case MLX5_CMD_OP_DESTROY_DCT: + case MLX5_CMD_OP_DEALLOC_Q_COUNTER: + case MLX5_CMD_OP_DEALLOC_PD: + case MLX5_CMD_OP_DEALLOC_UAR: + case MLX5_CMD_OP_DETTACH_FROM_MCG: + case MLX5_CMD_OP_DEALLOC_XRCD: + case MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN: + case MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT: + case MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY: + case MLX5_CMD_OP_DESTROY_TIR: + case MLX5_CMD_OP_DESTROY_SQ: + case MLX5_CMD_OP_DESTROY_RQ: + case MLX5_CMD_OP_DESTROY_RMP: + case MLX5_CMD_OP_DESTROY_TIS: + case MLX5_CMD_OP_DESTROY_RQT: + case MLX5_CMD_OP_DESTROY_FLOW_TABLE: + case MLX5_CMD_OP_DESTROY_FLOW_GROUP: + case MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY: + return MLX5_CMD_STAT_OK; + + case MLX5_CMD_OP_QUERY_HCA_CAP: + case MLX5_CMD_OP_QUERY_ADAPTER: + case MLX5_CMD_OP_INIT_HCA: + case MLX5_CMD_OP_ENABLE_HCA: + case MLX5_CMD_OP_QUERY_PAGES: + case MLX5_CMD_OP_SET_HCA_CAP: + case MLX5_CMD_OP_QUERY_ISSI: + case MLX5_CMD_OP_SET_ISSI: + case MLX5_CMD_OP_CREATE_MKEY: + case MLX5_CMD_OP_QUERY_MKEY: + case MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS: + case MLX5_CMD_OP_PAGE_FAULT_RESUME: + case MLX5_CMD_OP_CREATE_EQ: + case MLX5_CMD_OP_QUERY_EQ: + case MLX5_CMD_OP_GEN_EQE: + case MLX5_CMD_OP_CREATE_CQ: + case MLX5_CMD_OP_QUERY_CQ: + case MLX5_CMD_OP_MODIFY_CQ: + case MLX5_CMD_OP_CREATE_QP: + case MLX5_CMD_OP_RST2INIT_QP: + case MLX5_CMD_OP_INIT2RTR_QP: + case MLX5_CMD_OP_RTR2RTS_QP: + case MLX5_CMD_OP_RTS2RTS_QP: + case MLX5_CMD_OP_SQERR2RTS_QP: + case MLX5_CMD_OP_2ERR_QP: + case MLX5_CMD_OP_2RST_QP: + case MLX5_CMD_OP_QUERY_QP: + case MLX5_CMD_OP_SQD_RTS_QP: + case MLX5_CMD_OP_INIT2INIT_QP: + case MLX5_CMD_OP_CREATE_PSV: + case MLX5_CMD_OP_CREATE_SRQ: + case MLX5_CMD_OP_QUERY_SRQ: + case MLX5_CMD_OP_ARM_RQ: + case MLX5_CMD_OP_CREATE_XRC_SRQ: + case MLX5_CMD_OP_QUERY_XRC_SRQ: + case MLX5_CMD_OP_ARM_XRC_SRQ: + case MLX5_CMD_OP_CREATE_DCT: + case MLX5_CMD_OP_DRAIN_DCT: + case MLX5_CMD_OP_QUERY_DCT: + case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION: + case MLX5_CMD_OP_QUERY_VPORT_STATE: + case MLX5_CMD_OP_MODIFY_VPORT_STATE: + case MLX5_CMD_OP_QUERY_ESW_VPORT_CONTEXT: + case MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT: + case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT: + case MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT: + case MLX5_CMD_OP_QUERY_ROCE_ADDRESS: + case MLX5_CMD_OP_SET_ROCE_ADDRESS: + case MLX5_CMD_OP_QUERY_HCA_VPORT_CONTEXT: + case MLX5_CMD_OP_MODIFY_HCA_VPORT_CONTEXT: + case MLX5_CMD_OP_QUERY_HCA_VPORT_GID: + case MLX5_CMD_OP_QUERY_HCA_VPORT_PKEY: + case MLX5_CMD_OP_QUERY_VPORT_COUNTER: + case MLX5_CMD_OP_ALLOC_Q_COUNTER: + case MLX5_CMD_OP_QUERY_Q_COUNTER: + case MLX5_CMD_OP_ALLOC_PD: + case MLX5_CMD_OP_ALLOC_UAR: + case MLX5_CMD_OP_CONFIG_INT_MODERATION: + case MLX5_CMD_OP_ACCESS_REG: + case MLX5_CMD_OP_ATTACH_TO_MCG: + case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG: + case MLX5_CMD_OP_MAD_IFC: + case MLX5_CMD_OP_QUERY_MAD_DEMUX: + case MLX5_CMD_OP_SET_MAD_DEMUX: + case MLX5_CMD_OP_NOP: + case MLX5_CMD_OP_ALLOC_XRCD: + case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN: + case MLX5_CMD_OP_QUERY_CONG_STATUS: + case MLX5_CMD_OP_MODIFY_CONG_STATUS: + case MLX5_CMD_OP_QUERY_CONG_PARAMS: + case MLX5_CMD_OP_MODIFY_CONG_PARAMS: + case MLX5_CMD_OP_QUERY_CONG_STATISTICS: + case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT: + case MLX5_CMD_OP_SET_L2_TABLE_ENTRY: + case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY: + case MLX5_CMD_OP_CREATE_TIR: + case MLX5_CMD_OP_MODIFY_TIR: + case MLX5_CMD_OP_QUERY_TIR: + case MLX5_CMD_OP_CREATE_SQ: + case MLX5_CMD_OP_MODIFY_SQ: + case MLX5_CMD_OP_QUERY_SQ: + case MLX5_CMD_OP_CREATE_RQ: + case MLX5_CMD_OP_MODIFY_RQ: + case MLX5_CMD_OP_QUERY_RQ: + case MLX5_CMD_OP_CREATE_RMP: + case MLX5_CMD_OP_MODIFY_RMP: + case MLX5_CMD_OP_QUERY_RMP: + case MLX5_CMD_OP_CREATE_TIS: + case MLX5_CMD_OP_MODIFY_TIS: + case MLX5_CMD_OP_QUERY_TIS: + case MLX5_CMD_OP_CREATE_RQT: + case MLX5_CMD_OP_MODIFY_RQT: + case MLX5_CMD_OP_QUERY_RQT: + case MLX5_CMD_OP_CREATE_FLOW_TABLE: + case MLX5_CMD_OP_QUERY_FLOW_TABLE: + case MLX5_CMD_OP_CREATE_FLOW_GROUP: + case MLX5_CMD_OP_QUERY_FLOW_GROUP: + case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY: + case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY: + *status = MLX5_DRIVER_STATUS_ABORTED; + *synd = MLX5_DRIVER_SYND; + return -EIO; + default: + mlx5_core_err(dev, "Unknown FW command (%d)\n", op); + return -EINVAL; + } +} + const char *mlx5_command_str(int command) { switch (command) { @@ -592,6 +738,16 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent) return err; } +static __be32 *get_synd_ptr(struct mlx5_outbox_hdr *out) +{ + return &out->syndrome; +} + +static u8 *get_status_ptr(struct mlx5_outbox_hdr *out) +{ + return &out->status; +} + /* Notes: * 1. Callback functions may not sleep * 2. page queue commands do not support asynchrous completion @@ -1200,6 +1356,11 @@ static struct mlx5_cmd_msg *alloc_msg(struct mlx5_core_dev *dev, int in_size, return msg; } +static u16 opcode_from_in(struct mlx5_inbox_hdr *in) +{ + return be16_to_cpu(in->opcode); +} + static int is_manage_pages(struct mlx5_inbox_hdr *in) { return be16_to_cpu(in->opcode) == MLX5_CMD_OP_MANAGE_PAGES; @@ -1214,6 +1375,15 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, gfp_t gfp; int err; u8 status = 0; + u32 drv_synd; + + if (pci_channel_offline(dev->pdev) || + dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { + err = mlx5_internal_err_ret_value(dev, opcode_from_in(in), &drv_synd, &status); + *get_synd_ptr(out) = cpu_to_be32(drv_synd); + *get_status_ptr(out) = status; + return err; + } pages_queue = is_manage_pages(in); gfp = callback ? GFP_ATOMIC : GFP_KERNEL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index f1eb686c45b1..f5deb642d0d6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include "mlx5_core.h" @@ -68,6 +69,29 @@ static u8 get_nic_interface(struct mlx5_core_dev *dev) return (ioread32be(&dev->iseg->cmdq_addr_l_sz) >> 8) & 3; } +static void trigger_cmd_completions(struct mlx5_core_dev *dev) +{ + unsigned long flags; + u64 vector; + + /* wait for pending handlers to complete */ + synchronize_irq(dev->priv.msix_arr[MLX5_EQ_VEC_CMD].vector); + spin_lock_irqsave(&dev->cmd.alloc_lock, flags); + vector = ~dev->cmd.bitmask & ((1ul << (1 << dev->cmd.log_sz)) - 1); + if (!vector) + goto no_trig; + + vector |= MLX5_TRIGGERED_CMD_COMP; + spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags); + + mlx5_core_dbg(dev, "vector 0x%llx\n", vector); + mlx5_cmd_comp_handler(dev, vector); + return; + +no_trig: + spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags); +} + static int in_fatal(struct mlx5_core_dev *dev) { struct mlx5_core_health *health = &dev->priv.health; @@ -82,6 +106,43 @@ static int in_fatal(struct mlx5_core_dev *dev) return 0; } +void mlx5_enter_error_state(struct mlx5_core_dev *dev) +{ + if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) + return; + + mlx5_core_err(dev, "start\n"); + if (pci_channel_offline(dev->pdev) || in_fatal(dev)) + dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; + + mlx5_core_event(dev, MLX5_DEV_EVENT_SYS_ERROR, 0); + mlx5_core_err(dev, "end\n"); +} + +static void mlx5_handle_bad_state(struct mlx5_core_dev *dev) +{ + u8 nic_interface = get_nic_interface(dev); + + switch (nic_interface) { + case MLX5_NIC_IFC_FULL: + mlx5_core_warn(dev, "Expected to see disabled NIC but it is full driver\n"); + break; + + case MLX5_NIC_IFC_DISABLED: + mlx5_core_warn(dev, "starting teardown\n"); + break; + + case MLX5_NIC_IFC_NO_DRAM_NIC: + mlx5_core_warn(dev, "Expected to see disabled NIC but it is no dram nic\n"); + break; + default: + mlx5_core_warn(dev, "Expected to see disabled NIC but it is has invalid value %d\n", + nic_interface); + } + + mlx5_disable_device(dev); +} + static void health_care(struct work_struct *work) { struct mlx5_core_health *health; @@ -92,6 +153,7 @@ static void health_care(struct work_struct *work) priv = container_of(health, struct mlx5_priv, health); dev = container_of(priv, struct mlx5_core_dev, priv); mlx5_core_warn(dev, "handling bad device here\n"); + mlx5_handle_bad_state(dev); } static const char *hsynd_str(u8 synd) @@ -147,6 +209,10 @@ static void print_health_info(struct mlx5_core_dev *dev) u32 fw; int i; + /* If the syndrom is 0, the device is OK and no need to print buffer */ + if (!ioread8(&h->synd)) + return; + for (i = 0; i < ARRAY_SIZE(h->assert_var); i++) dev_err(&dev->pdev->dev, "assert_var[%d] 0x%08x\n", i, ioread32be(h->assert_var + i)); @@ -178,6 +244,12 @@ static void poll_health(unsigned long data) struct mlx5_core_health *health = &dev->priv.health; u32 count; + if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { + trigger_cmd_completions(dev); + mod_timer(&health->timer, get_next_poll_jiffies()); + return; + } + count = ioread32be(health->health_counter); if (count == health->prev) ++health->miss_counter; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index b6edc58766ad..a103a54d6660 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include "mlx5_core.h" @@ -181,6 +182,34 @@ static int set_dma_caps(struct pci_dev *pdev) return err; } +static int mlx5_pci_enable_device(struct mlx5_core_dev *dev) +{ + struct pci_dev *pdev = dev->pdev; + int err = 0; + + mutex_lock(&dev->pci_status_mutex); + if (dev->pci_status == MLX5_PCI_STATUS_DISABLED) { + err = pci_enable_device(pdev); + if (!err) + dev->pci_status = MLX5_PCI_STATUS_ENABLED; + } + mutex_unlock(&dev->pci_status_mutex); + + return err; +} + +static void mlx5_pci_disable_device(struct mlx5_core_dev *dev) +{ + struct pci_dev *pdev = dev->pdev; + + mutex_lock(&dev->pci_status_mutex); + if (dev->pci_status == MLX5_PCI_STATUS_ENABLED) { + pci_disable_device(pdev); + dev->pci_status = MLX5_PCI_STATUS_DISABLED; + } + mutex_unlock(&dev->pci_status_mutex); +} + static int request_bar(struct pci_dev *pdev) { int err = 0; @@ -807,7 +836,7 @@ static int mlx5_pci_init(struct mlx5_core_dev *dev, struct mlx5_priv *priv) if (!priv->dbg_root) return -ENOMEM; - err = pci_enable_device(pdev); + err = mlx5_pci_enable_device(dev); if (err) { dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n"); goto err_dbg; @@ -841,7 +870,7 @@ err_clr_master: pci_clear_master(dev->pdev); release_bar(dev->pdev); err_disable: - pci_disable_device(dev->pdev); + mlx5_pci_disable_device(dev); err_dbg: debugfs_remove(priv->dbg_root); @@ -853,7 +882,7 @@ static void mlx5_pci_close(struct mlx5_core_dev *dev, struct mlx5_priv *priv) iounmap(dev->iseg); pci_clear_master(dev->pdev); release_bar(dev->pdev); - pci_disable_device(dev->pdev); + mlx5_pci_disable_device(dev); debugfs_remove(priv->dbg_root); } @@ -863,13 +892,25 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) struct pci_dev *pdev = dev->pdev; int err; + mutex_lock(&dev->intf_state_mutex); + if (dev->interface_state == MLX5_INTERFACE_STATE_UP) { + dev_warn(&dev->pdev->dev, "%s: interface is up, NOP\n", + __func__); + goto out; + } + dev_info(&pdev->dev, "firmware version: %d.%d.%d\n", fw_rev_maj(dev), fw_rev_min(dev), fw_rev_sub(dev)); + /* on load removing any previous indication of internal error, device is + * up + */ + dev->state = MLX5_DEVICE_STATE_UP; + err = mlx5_cmd_init(dev); if (err) { dev_err(&pdev->dev, "Failed initializing command interface, aborting\n"); - return err; + goto out_err; } mlx5_pagealloc_init(dev); @@ -994,6 +1035,10 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) if (err) pr_info("failed request module on %s\n", MLX5_IB_MOD); + dev->interface_state = MLX5_INTERFACE_STATE_UP; +out: + mutex_unlock(&dev->intf_state_mutex); + return 0; err_reg_dev: @@ -1024,7 +1069,7 @@ err_stop_poll: mlx5_stop_health_poll(dev); if (mlx5_cmd_teardown_hca(dev)) { dev_err(&dev->pdev->dev, "tear_down_hca failed, skip cleanup\n"); - return err; + goto out_err; } err_pagealloc_stop: @@ -1040,13 +1085,23 @@ err_pagealloc_cleanup: mlx5_pagealloc_cleanup(dev); mlx5_cmd_cleanup(dev); +out_err: + dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; + mutex_unlock(&dev->intf_state_mutex); + return err; } static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) { - int err; + int err = 0; + mutex_lock(&dev->intf_state_mutex); + if (dev->interface_state == MLX5_INTERFACE_STATE_DOWN) { + dev_warn(&dev->pdev->dev, "%s: interface is down, NOP\n", + __func__); + goto out; + } mlx5_unregister_device(dev); mlx5_cleanup_mr_table(dev); mlx5_cleanup_srq_table(dev); @@ -1072,10 +1127,12 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) mlx5_cmd_cleanup(dev); out: + dev->interface_state = MLX5_INTERFACE_STATE_DOWN; + mutex_unlock(&dev->intf_state_mutex); return err; } -static void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event, +void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event, unsigned long param) { struct mlx5_priv *priv = &dev->priv; @@ -1125,6 +1182,8 @@ static int init_one(struct pci_dev *pdev, INIT_LIST_HEAD(&priv->ctx_list); spin_lock_init(&priv->ctx_lock); + mutex_init(&dev->pci_status_mutex); + mutex_init(&dev->intf_state_mutex); err = mlx5_pci_init(dev, priv); if (err) { dev_err(&pdev->dev, "mlx5_pci_init failed with error code %d\n", err); @@ -1172,6 +1231,112 @@ static void remove_one(struct pci_dev *pdev) kfree(dev); } +static pci_ers_result_t mlx5_pci_err_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct mlx5_core_dev *dev = pci_get_drvdata(pdev); + struct mlx5_priv *priv = &dev->priv; + + dev_info(&pdev->dev, "%s was called\n", __func__); + mlx5_enter_error_state(dev); + mlx5_unload_one(dev, priv); + mlx5_pci_disable_device(dev); + return state == pci_channel_io_perm_failure ? + PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t mlx5_pci_slot_reset(struct pci_dev *pdev) +{ + struct mlx5_core_dev *dev = pci_get_drvdata(pdev); + int err = 0; + + dev_info(&pdev->dev, "%s was called\n", __func__); + + err = mlx5_pci_enable_device(dev); + if (err) { + dev_err(&pdev->dev, "%s: mlx5_pci_enable_device failed with error code: %d\n" + , __func__, err); + return PCI_ERS_RESULT_DISCONNECT; + } + pci_set_master(pdev); + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + return err ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; +} + +void mlx5_disable_device(struct mlx5_core_dev *dev) +{ + mlx5_pci_err_detected(dev->pdev, 0); +} + +/* wait for the device to show vital signs. For now we check + * that we can read the device ID and that the health buffer + * shows a non zero value which is different than 0xffffffff + */ +static void wait_vital(struct pci_dev *pdev) +{ + struct mlx5_core_dev *dev = pci_get_drvdata(pdev); + struct mlx5_core_health *health = &dev->priv.health; + const int niter = 100; + u32 count; + u16 did; + int i; + + /* Wait for firmware to be ready after reset */ + msleep(1000); + for (i = 0; i < niter; i++) { + if (pci_read_config_word(pdev, 2, &did)) { + dev_warn(&pdev->dev, "failed reading config word\n"); + break; + } + if (did == pdev->device) { + dev_info(&pdev->dev, "device ID correctly read after %d iterations\n", i); + break; + } + msleep(50); + } + if (i == niter) + dev_warn(&pdev->dev, "%s-%d: could not read device ID\n", __func__, __LINE__); + + for (i = 0; i < niter; i++) { + count = ioread32be(health->health_counter); + if (count && count != 0xffffffff) { + dev_info(&pdev->dev, "Counter value 0x%x after %d iterations\n", count, i); + break; + } + msleep(50); + } + + if (i == niter) + dev_warn(&pdev->dev, "%s-%d: could not read device ID\n", __func__, __LINE__); +} + +static void mlx5_pci_resume(struct pci_dev *pdev) +{ + struct mlx5_core_dev *dev = pci_get_drvdata(pdev); + struct mlx5_priv *priv = &dev->priv; + int err; + + dev_info(&pdev->dev, "%s was called\n", __func__); + + pci_save_state(pdev); + wait_vital(pdev); + + err = mlx5_load_one(dev, priv); + if (err) + dev_err(&pdev->dev, "%s: mlx5_load_one failed with error code: %d\n" + , __func__, err); + else + dev_info(&pdev->dev, "%s: device recovered\n", __func__); +} + +static const struct pci_error_handlers mlx5_err_handler = { + .error_detected = mlx5_pci_err_detected, + .slot_reset = mlx5_pci_slot_reset, + .resume = mlx5_pci_resume +}; + static const struct pci_device_id mlx5_core_pci_table[] = { { PCI_VDEVICE(MELLANOX, 0x1011) }, /* Connect-IB */ { PCI_VDEVICE(MELLANOX, 0x1012) }, /* Connect-IB VF */ @@ -1188,7 +1353,8 @@ static struct pci_driver mlx5_core_driver = { .name = DRIVER_NAME, .id_table = mlx5_core_pci_table, .probe = init_one, - .remove = remove_one + .remove = remove_one, + .err_handler = &mlx5_err_handler }; static int __init init(void) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 30c0be721b08..cee5b7a839bc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -86,6 +86,10 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev); int mlx5_query_board_id(struct mlx5_core_dev *dev); int mlx5_cmd_init_hca(struct mlx5_core_dev *dev); int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev); +void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event, + unsigned long param); +void mlx5_enter_error_state(struct mlx5_core_dev *dev); +void mlx5_disable_device(struct mlx5_core_dev *dev); void mlx5e_init(void); void mlx5e_cleanup(void); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index 76432a510ac2..1cda5d268ec9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c @@ -493,15 +493,20 @@ int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev) struct fw_page *fwp; struct rb_node *p; int nclaimed = 0; - int err; + int err = 0; do { p = rb_first(&dev->priv.page_root); if (p) { fwp = rb_entry(p, struct fw_page, rb_node); - err = reclaim_pages(dev, fwp->func_id, - optimal_reclaimed_pages(), - &nclaimed); + if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { + free_4k(dev, fwp->addr); + nclaimed = 1; + } else { + err = reclaim_pages(dev, fwp->func_id, + optimal_reclaimed_pages(), + &nclaimed); + } if (err) { mlx5_core_warn(dev, "failed reclaiming pages (%d)\n", err); -- cgit v1.2.3 From e3297246c2c8cf8548ba722da3e3a8104cdcd035 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Wed, 14 Oct 2015 17:43:47 +0300 Subject: net/mlx5_core: Wait for FW readiness on startup On device initialization, wait till firmware indicates that that it is done with initialization before proceeding to initialize the device. Also update initialization segment layout to match driver/firmware interface definitions. Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index a103a54d6660..2388aec208fa 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -152,6 +153,25 @@ static struct mlx5_profile profile[] = { }, }; +#define FW_INIT_TIMEOUT_MILI 2000 +#define FW_INIT_WAIT_MS 2 + +static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili) +{ + unsigned long end = jiffies + msecs_to_jiffies(max_wait_mili); + int err = 0; + + while (fw_initializing(dev)) { + if (time_after(jiffies, end)) { + err = -EBUSY; + break; + } + msleep(FW_INIT_WAIT_MS); + } + + return err; +} + static int set_dma_caps(struct pci_dev *pdev) { int err; @@ -913,6 +933,13 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) goto out_err; } + err = wait_fw_init(dev, FW_INIT_TIMEOUT_MILI); + if (err) { + dev_err(&dev->pdev->dev, "Firmware over %d MS in initializing state, aborting\n", + FW_INIT_TIMEOUT_MILI); + goto out_err; + } + mlx5_pagealloc_init(dev); err = mlx5_core_enable_hca(dev); -- cgit v1.2.3 From 2b3ddf27f48c8061f0676c5a8796008099945280 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Wed, 14 Oct 2015 17:43:48 +0300 Subject: net/mlx4_core: Replace VF zero mac with random mac in mlx4_core By design, when no default MAC addresses are set in the Hypervisor for VFs, the VFs are passed zero-macs. When such a MAC is received by the VF, it generates a random MAC address and registers that MAC address with the Hypervisor. This random mac generation is currently done in the mlx4_en module. There is a problem, though, if the mlx4_ib module is loaded by a VF before the mlx4_en module. In this case, for RoCE, mlx4_ib will see the un-replaced zero-mac and register that zero-mac as part of QP1 initialization. Having a zero-mac in the port's MAC table creates problems for a Baseboard Management Console. The BMC occasionally sends packets with a zero-mac destination MAC. If there is a zero-mac present in the port's MAC table, the FW will send such BMC packets to the host driver rather than to the wire, and BMC will stop working. To address this problem, we move the replacement of zero-mac addresses with random-mac addresses to procedure mlx4_slave_cap(), which is part of the driver startup for VFs, and is before activation of mlx4_ib and mlx4_en. As a result, zero-mac addresses will never be registered in the port MAC table by the driver. In addition, when mlx4_en does initialize the net device, it needs to set the NET_ADDR_RANDOM flag in the netdev structure if the address was randomly generated. This is done so that udev on the VM does not create a new device name after each VF probe (VM boot and such). To accomplish this, we add a per-port flag in mlx4_dev which gets set whenever mlx4_core replaces a zero-mac with a randomly-generated mac. This flag is examined when mlx4_en initializes the net-device. Fix was suggested by Matan Barak Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 23 +++++++++++------------ drivers/net/ethernet/mellanox/mlx4/fw.c | 16 ++++++++++++++++ drivers/net/ethernet/mellanox/mlx4/main.c | 2 ++ drivers/net/ethernet/mellanox/mlx4/mlx4.h | 2 ++ 4 files changed, 31 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 597d8923c8e1..886e1bc86374 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2816,7 +2816,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, struct mlx4_en_priv *priv; int i; int err; - u64 mac_u64; dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv), MAX_TX_RINGS, MAX_RX_RINGS); @@ -2908,17 +2907,17 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, dev->addr_len = ETH_ALEN; mlx4_en_u64_to_mac(dev->dev_addr, mdev->dev->caps.def_mac[priv->port]); if (!is_valid_ether_addr(dev->dev_addr)) { - if (mlx4_is_slave(priv->mdev->dev)) { - eth_hw_addr_random(dev); - en_warn(priv, "Assigned random MAC address %pM\n", dev->dev_addr); - mac_u64 = mlx4_mac_to_u64(dev->dev_addr); - mdev->dev->caps.def_mac[priv->port] = mac_u64; - } else { - en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n", - priv->port, dev->dev_addr); - err = -EINVAL; - goto out; - } + en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n", + priv->port, dev->dev_addr); + err = -EINVAL; + goto out; + } else if (mlx4_is_slave(priv->mdev->dev) && + (priv->mdev->dev->port_random_macs & 1 << priv->port)) { + /* Random MAC was assigned in mlx4_slave_cap + * in mlx4_core module + */ + dev->addr_assign_type |= NET_ADDR_RANDOM; + en_warn(priv, "Assigned random MAC address %pM\n", dev->dev_addr); } memcpy(priv->current_mac, dev->dev_addr, sizeof(priv->current_mac)); diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index e8ec1dec5789..f13a4d7bbf95 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -2840,3 +2840,19 @@ int set_phv_bit(struct mlx4_dev *dev, u8 port, int new_val) return -EOPNOTSUPP; } EXPORT_SYMBOL(set_phv_bit); + +void mlx4_replace_zero_macs(struct mlx4_dev *dev) +{ + int i; + u8 mac_addr[ETH_ALEN]; + + dev->port_random_macs = 0; + for (i = 1; i <= dev->caps.num_ports; ++i) + if (!dev->caps.def_mac[i] && + dev->caps.port_type[i] == MLX4_PORT_TYPE_ETH) { + eth_random_addr(mac_addr); + dev->port_random_macs |= 1 << i; + dev->caps.def_mac[i] = mlx4_mac_to_u64(mac_addr); + } +} +EXPORT_SYMBOL_GPL(mlx4_replace_zero_macs); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 006757f80988..bcbdfab1fe19 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -863,6 +863,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) return -ENODEV; } + mlx4_replace_zero_macs(dev); + dev->caps.qp0_qkey = kcalloc(dev->caps.num_ports, sizeof(u32), GFP_KERNEL); dev->caps.qp0_tunnel = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL); dev->caps.qp0_proxy = kcalloc(dev->caps.num_ports, sizeof (u32), GFP_KERNEL); diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 232b2b55f23b..e1cf9036af22 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -1378,6 +1378,8 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work); void mlx4_init_quotas(struct mlx4_dev *dev); +/* for VFs, replace zero MACs with randomly-generated MACs at driver start */ +void mlx4_replace_zero_macs(struct mlx4_dev *dev); int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave, int port); /* Returns the VF index of slave */ int mlx4_get_vf_indx(struct mlx4_dev *dev, int slave); -- cgit v1.2.3 From 72bfd32d2f84d26aa132dd74a8eef14d039d326f Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Mon, 24 Aug 2015 18:08:31 -0700 Subject: ixgbe: disable LRO by default This patch disables LRO by default in favor of GRO. LRO is incompatible with forwarding and is disabled when forwarding is turned on which makes the default offloads of the driver inconsistent. LRO can still be enabled via ethtool. Signed-off-by: Emil Tantilov Tested-by: Darin Miller Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index c4608f893f95..1b2ad39bbfb5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -5307,7 +5307,6 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter) rss = min_t(int, ixgbe_max_rss_indices(adapter), num_online_cpus()); adapter->ring_feature[RING_F_RSS].limit = rss; adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE; - adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; adapter->max_q_vectors = MAX_Q_VECTORS_82599; adapter->atr_sample_rate = 20; fdir = min_t(int, IXGBE_MAX_FDIR_INDICES, num_online_cpus()); @@ -5333,7 +5332,6 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter) switch (hw->mac.type) { case ixgbe_mac_82598EB: adapter->flags2 &= ~IXGBE_FLAG2_RSC_CAPABLE; - adapter->flags2 &= ~IXGBE_FLAG2_RSC_ENABLED; if (hw->device_id == IXGBE_DEV_ID_82598AT) adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE; -- cgit v1.2.3 From 8bf7a7b879985321c63e3ae46fee4e7f0d654ab1 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Wed, 26 Aug 2015 14:10:22 -0700 Subject: ixgbe: Fix CS4227-related semaphore error on reset failure If the reset never completes, it is necessary to retake the semaphore before returning, because the caller will release the semaphore. Signed-off-by: Mark Rustad Tested-by: Darin Miller Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index ed7b2899affe..06b15eddc4ae 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -198,6 +198,7 @@ static s32 ixgbe_write_pe(struct ixgbe_hw *hw, u8 reg, u8 value) * ixgbe_reset_cs4227 - Reset CS4227 using port expander * @hw: pointer to hardware structure * + * This function assumes that the caller has acquired the proper semaphore. * Returns error code */ static s32 ixgbe_reset_cs4227(struct ixgbe_hw *hw) @@ -296,6 +297,14 @@ static void ixgbe_check_cs4227(struct ixgbe_hw *hw) hw->mac.ops.release_swfw_sync(hw, swfw_mask); msleep(IXGBE_CS4227_CHECK_DELAY); } + /* If still pending, assume other instance failed. */ + if (retry == IXGBE_CS4227_RETRIES) { + status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask); + if (status) { + hw_err(hw, "semaphore failed with %d\n", status); + return; + } + } /* Reset the CS4227. */ status = ixgbe_reset_cs4227(hw); -- cgit v1.2.3 From d4b2f9fe608320604748c3cb90c99b2255782935 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 3 Sep 2015 17:18:48 -0400 Subject: i40e: Add missing parameter comment to ndo_bridge_setlink Add nlflags to the function comment for ndo_bridge_setlink. Change-ID: I34c704f307f2a3f7bac3ca4b44e2a094d3d082d6 Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index f7281400bdd1..10662f691312 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8330,6 +8330,7 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev, * @seq: RTNL message seq # * @dev: the netdev being configured * @filter_mask: unused + * @nlflags: netlink flags passed in * * Return the mode in which the hardware bridge is operating in * i.e VEB or VEPA. -- cgit v1.2.3 From ef17178cf5abe304b2098a50f580e8c19e5084d2 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 3 Sep 2015 17:18:49 -0400 Subject: i40e: use priv flags to control flow director Some customers wish to be able to control our hardware specific feature called flow director, at runtime. This patch enables ethtool priv flags to control this driver/hardware specific feature. ethtool --set-priv-flags ethX flow-director-atr off NOTE: the ethtool ntuple interface controls the flow-director sideband rules. Change-ID: Iba156350b07fa2ce66f53ded51739f9a3781fe0e Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index cfe8f83b8144..c8591b9f63e1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -102,6 +102,7 @@ /* Ethtool Private Flags */ #define I40E_PRIV_FLAGS_NPAR_FLAG BIT(0) #define I40E_PRIV_FLAGS_LINKPOLL_FLAG BIT(1) +#define I40E_PRIV_FLAGS_FD_ATR BIT(2) #define I40E_NVM_VERSION_LO_SHIFT 0 #define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 831f97125c8f..185ac91ce78f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -231,6 +231,7 @@ static const char i40e_gstrings_test[][ETH_GSTRING_LEN] = { static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = { "NPAR", "LinkPolling", + "flow-director-atr", }; #define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings) @@ -2666,6 +2667,8 @@ static u32 i40e_get_priv_flags(struct net_device *dev) I40E_PRIV_FLAGS_NPAR_FLAG : 0; ret_flags |= pf->flags & I40E_FLAG_LINK_POLLING_ENABLED ? I40E_PRIV_FLAGS_LINKPOLL_FLAG : 0; + ret_flags |= pf->flags & I40E_FLAG_FD_ATR_ENABLED ? + I40E_PRIV_FLAGS_FD_ATR : 0; return ret_flags; } @@ -2686,6 +2689,17 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags) else pf->flags &= ~I40E_FLAG_LINK_POLLING_ENABLED; + /* allow the user to control the state of the Flow + * Director ATR (Application Targeted Routing) feature + * of the driver + */ + if (flags & I40E_PRIV_FLAGS_FD_ATR) { + pf->flags |= I40E_FLAG_FD_ATR_ENABLED; + } else { + pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED; + pf->auto_disable_flags |= I40E_FLAG_FD_ATR_ENABLED; + } + return 0; } -- cgit v1.2.3 From 8279e49531f427ae7e8db894072d91bc42d3eeb5 Mon Sep 17 00:00:00 2001 From: Neerav Parikh Date: Thu, 3 Sep 2015 17:18:50 -0400 Subject: i40e: Change some messages from info to debug only There are several error messages that have been printing when there is no functional issue. These messages should be available at debug message level only. Change-ID: Id91e47bf942c483563995f30d8705fa53acd5aa3 Signed-off-by: Neerav Parikh Signed-off-by: Catherine Sullivan Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c | 7 +++---- drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 21 +++++++++++++-------- 3 files changed, 17 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c index 7c42d1340de6..886e667f2f1c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c @@ -240,10 +240,9 @@ static void i40e_dcbnl_del_app(struct i40e_pf *pf, for (v = 0; v < pf->num_alloc_vsi; v++) { if (pf->vsi[v] && pf->vsi[v]->netdev) { err = i40e_dcbnl_vsi_del_app(pf->vsi[v], app); - if (err) - dev_info(&pf->pdev->dev, "Failed deleting app for VSI seid=%d err=%d sel=%d proto=0x%x prio=%d\n", - pf->vsi[v]->seid, err, app->selector, - app->protocolid, app->priority); + dev_dbg(&pf->pdev->dev, "Deleting app for VSI seid=%d err=%d sel=%d proto=0x%x prio=%d\n", + pf->vsi[v]->seid, err, app->selector, + app->protocolid, app->priority); } } } diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index eaedc1f4c257..2ec241142e9d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -284,7 +284,7 @@ void i40e_init_pf_fcoe(struct i40e_pf *pf) pf->fcoe_hmc_filt_num = 0; if (!pf->hw.func_caps.fcoe) { - dev_info(&pf->pdev->dev, "FCoE capability is disabled\n"); + dev_dbg(&pf->pdev->dev, "FCoE capability is disabled\n"); return; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 10662f691312..7c4add81bf84 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6593,9 +6593,9 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) /* make sure our flow control settings are restored */ ret = i40e_set_fc(&pf->hw, &set_fc_aq_fail, true); if (ret) - dev_info(&pf->pdev->dev, "set fc fail, err %s aq_err %s\n", - i40e_stat_str(&pf->hw, ret), - i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); + dev_dbg(&pf->pdev->dev, "setting flow control: ret = %s last_status = %s\n", + i40e_stat_str(&pf->hw, ret), + i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); /* Rebuild the VSIs and VEBs that existed before reset. * They are still in our local switch element arrays, so only @@ -9847,8 +9847,14 @@ static void i40e_determine_queue_usage(struct i40e_pf *pf) } pf->queues_left = queues_left; + dev_dbg(&pf->pdev->dev, + "qs_avail=%d FD SB=%d lan_qs=%d lan_tc0=%d vf=%d*%d vmdq=%d*%d, remaining=%d\n", + pf->hw.func_caps.num_tx_qp, + !!(pf->flags & I40E_FLAG_FD_SB_ENABLED), + pf->num_lan_qps, pf->rss_size, pf->num_req_vfs, pf->num_vf_qps, + pf->num_vmdq_vsis, pf->num_vmdq_qps, queues_left); #ifdef I40E_FCOE - dev_info(&pf->pdev->dev, "fcoe queues = %d\n", pf->num_fcoe_qps); + dev_dbg(&pf->pdev->dev, "fcoe queues = %d\n", pf->num_fcoe_qps); #endif } @@ -10333,10 +10339,9 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* get the requested speeds from the fw */ err = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, NULL); if (err) - dev_info(&pf->pdev->dev, - "get phy capabilities failed, err %s aq_err %s, advertised speed settings may not be correct\n", - i40e_stat_str(&pf->hw, err), - i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); + dev_dbg(&pf->pdev->dev, "get requested speeds ret = %s last_status = %s\n", + i40e_stat_str(&pf->hw, err), + i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); pf->hw.phy.link_info.requested_speeds = abilities.link_speed; /* get the supported phy types from the fw */ -- cgit v1.2.3 From 3b6c2179eebf4536d08cf966c9f585dd95c72367 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Thu, 3 Sep 2015 17:18:52 -0400 Subject: i40e: Remove 100M SGMII unless hw is X722 Only the X722 device now supports 100M SGMII, and nothing supports 100M on 1000Base_T. Change-ID: I6f44dcd818944edd40041410e6de380f4a359a0c Signed-off-by: Catherine Sullivan Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 42 ++++++++++++++++---------- 1 file changed, 26 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 185ac91ce78f..b31139127616 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -255,7 +255,8 @@ static void i40e_partition_setting_complaint(struct i40e_pf *pf) **/ static void i40e_get_settings_link_up(struct i40e_hw *hw, struct ethtool_cmd *ecmd, - struct net_device *netdev) + struct net_device *netdev, + struct i40e_pf *pf) { struct i40e_link_status *hw_link_info = &hw->phy.link_info; u32 link_speed = hw_link_info->link_speed; @@ -299,16 +300,18 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, break; case I40E_PHY_TYPE_10GBASE_T: case I40E_PHY_TYPE_1000BASE_T: - case I40E_PHY_TYPE_100BASE_TX: ecmd->supported = SUPPORTED_Autoneg | SUPPORTED_10000baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_100baseT_Full; + SUPPORTED_1000baseT_Full; ecmd->advertising = ADVERTISED_Autoneg; if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) ecmd->advertising |= ADVERTISED_10000baseT_Full; if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) ecmd->advertising |= ADVERTISED_1000baseT_Full; + break; + case I40E_PHY_TYPE_100BASE_TX: + ecmd->supported = SUPPORTED_Autoneg | + SUPPORTED_100baseT_Full; if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB) ecmd->advertising |= ADVERTISED_100baseT_Full; break; @@ -328,12 +331,15 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, break; case I40E_PHY_TYPE_SGMII: ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_1000baseT_Full | - SUPPORTED_100baseT_Full; + SUPPORTED_1000baseT_Full; if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) ecmd->advertising |= ADVERTISED_1000baseT_Full; - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB) - ecmd->advertising |= ADVERTISED_100baseT_Full; + if (pf->hw.mac.type == I40E_MAC_X722) { + ecmd->supported |= SUPPORTED_100baseT_Full; + if (hw_link_info->requested_speeds & + I40E_LINK_SPEED_100MB) + ecmd->advertising |= ADVERTISED_100baseT_Full; + } break; /* Backplane is set based on supported phy types in get_settings * so don't set anything here but don't warn either @@ -381,7 +387,8 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, * Reports link settings that can be determined when link is down **/ static void i40e_get_settings_link_down(struct i40e_hw *hw, - struct ethtool_cmd *ecmd) + struct ethtool_cmd *ecmd, + struct i40e_pf *pf) { enum i40e_aq_capabilities_phy_type phy_types = hw->phy.phy_types; @@ -392,11 +399,13 @@ static void i40e_get_settings_link_down(struct i40e_hw *hw, ecmd->advertising = 0x0; if (phy_types & I40E_CAP_PHY_TYPE_SGMII) { ecmd->supported |= SUPPORTED_Autoneg | - SUPPORTED_1000baseT_Full | - SUPPORTED_100baseT_Full; + SUPPORTED_1000baseT_Full; ecmd->advertising |= ADVERTISED_Autoneg | - ADVERTISED_1000baseT_Full | - ADVERTISED_100baseT_Full; + ADVERTISED_1000baseT_Full; + if (pf->hw.mac.type == I40E_MAC_X722) { + ecmd->supported |= SUPPORTED_100baseT_Full; + ecmd->advertising |= ADVERTISED_100baseT_Full; + } } if (phy_types & I40E_CAP_PHY_TYPE_XAUI || phy_types & I40E_CAP_PHY_TYPE_XFI || @@ -425,7 +434,8 @@ static void i40e_get_settings_link_down(struct i40e_hw *hw, ecmd->advertising |= ADVERTISED_Autoneg | ADVERTISED_40000baseCR4_Full; } - if (phy_types & I40E_CAP_PHY_TYPE_100BASE_TX) { + if ((phy_types & I40E_CAP_PHY_TYPE_100BASE_TX) && + !(phy_types & I40E_CAP_PHY_TYPE_1000BASE_T)) { ecmd->supported |= SUPPORTED_Autoneg | SUPPORTED_100baseT_Full; ecmd->advertising |= ADVERTISED_Autoneg | @@ -467,9 +477,9 @@ static int i40e_get_settings(struct net_device *netdev, bool link_up = hw_link_info->link_info & I40E_AQ_LINK_UP; if (link_up) - i40e_get_settings_link_up(hw, ecmd, netdev); + i40e_get_settings_link_up(hw, ecmd, netdev, pf); else - i40e_get_settings_link_down(hw, ecmd); + i40e_get_settings_link_down(hw, ecmd, pf); /* Now set the settings that don't rely on link being up/down */ -- cgit v1.2.3 From 1f012279163af2f1bec30de42960f0312be3a52e Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Thu, 3 Sep 2015 17:18:53 -0400 Subject: i40e/i40evf: Add WB_ON_ITR offload support X722 has a way to work around the descriptor WB issue, this offload helps turn that feature on. Change-ID: I7ffa67622426bfca5a651417b63e3afcfeb60412 Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl.h | 1 + drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 4 ++++ drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h | 1 + drivers/net/ethernet/intel/i40evf/i40evf_main.c | 5 +++++ drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c | 3 ++- 5 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h index 95d0f8c5d484..ae879826084b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h @@ -150,6 +150,7 @@ struct i40e_virtchnl_vsi_resource { #define I40E_VIRTCHNL_VF_OFFLOAD_FCOE 0x00000004 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ 0x00000008 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG 0x00000010 +#define I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR 0x00000020 #define I40E_VIRTCHNL_VF_OFFLOAD_VLAN 0x00010000 #define I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING 0x00020000 diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index ae7548a5286e..fd99cd237145 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1203,6 +1203,10 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) } else { vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG; } + + if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING) + vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING; + vfres->num_vsis = num_vsis; vfres->num_queue_pairs = vf->num_queue_pairs; vfres->max_vectors = pf->hw.func_caps.num_msix_vectors_vf; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h index cadda642c98c..9f7b279b9d9c 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h @@ -150,6 +150,7 @@ struct i40e_virtchnl_vsi_resource { #define I40E_VIRTCHNL_VF_OFFLOAD_FCOE 0x00000004 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ 0x00000008 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG 0x00000010 +#define I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR 0x00000020 #define I40E_VIRTCHNL_VF_OFFLOAD_VLAN 0x00010000 #define I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING 0x00020000 diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 69767c0d9194..feb9ad58bb34 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1123,6 +1123,8 @@ static int i40evf_alloc_queues(struct i40evf_adapter *adapter) tx_ring->netdev = adapter->netdev; tx_ring->dev = &adapter->pdev->dev; tx_ring->count = adapter->tx_desc_count; + if (adapter->flags & I40E_FLAG_WB_ON_ITR_CAPABLE) + tx_ring->flags |= I40E_TXR_FLAGS_WB_ON_ITR; adapter->tx_rings[i] = tx_ring; rx_ring = &tx_ring[1]; @@ -2275,6 +2277,9 @@ static void i40evf_init_task(struct work_struct *work) if (err) goto err_sw_init; i40evf_map_rings_to_vectors(adapter); + if (adapter->vf_res->vf_offload_flags & + I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) + adapter->flags |= I40EVF_FLAG_WB_ON_ITR_CAPABLE; if (!RSS_AQ(adapter)) i40evf_configure_rss(adapter); err = i40evf_request_misc_irq(adapter); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index 4f056efecba4..32e620e1eb5c 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -156,7 +156,8 @@ int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter) caps = I40E_VIRTCHNL_VF_OFFLOAD_L2 | I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ | I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG | - I40E_VIRTCHNL_VF_OFFLOAD_VLAN; + I40E_VIRTCHNL_VF_OFFLOAD_VLAN | + I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR; adapter->current_op = I40E_VIRTCHNL_OP_GET_VF_RESOURCES; adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_CONFIG; if (PF_IS_V11(adapter)) -- cgit v1.2.3 From 9b28ef01003f815d9bbdb50c4208586c9246ad08 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 3 Sep 2015 17:18:54 -0400 Subject: i40e: remove obsolete version check This version check only applies to very, very old firmware, that only ran on A0 hardware, which we never shipped and don't support in this driver anyway. Remove it, before somebody gets hurt. Change-ID: I3752d090ff488acf98ee76b075af961e9c968ee4 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 7c4add81bf84..c4f26eb8363d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6353,12 +6353,6 @@ static int i40e_get_capabilities(struct i40e_pf *pf) } } while (err); - if (((pf->hw.aq.fw_maj_ver == 2) && (pf->hw.aq.fw_min_ver < 22)) || - (pf->hw.aq.fw_maj_ver < 2)) { - pf->hw.func_caps.num_msix_vectors++; - pf->hw.func_caps.num_msix_vectors_vf++; - } - if (pf->hw.debug_mask & I40E_DEBUG_USER) dev_info(&pf->pdev->dev, "pf=%d, num_vfs=%d, msix_pf=%d, msix_vf=%d, fd_g=%d, fd_b=%d, pf_max_q=%d num_vsi=%d\n", -- cgit v1.2.3 From 6eae9c6a3536f3a676b54ebf82244c23d3b1019f Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 3 Sep 2015 17:18:55 -0400 Subject: i40e: allow FD SB if MFP mode only has 1 partition Even though the device might be in MFP mode, if there's only one partition enabled, then we still have plenty of interrupts for managing the Flow Directory Sideband activity. This patch enables FD SB in this case. This patch also reverses the sense of the conditional in order to remove the negative logic. Change-ID: I9edf211a6219fc8d159b4be9964f9fd7f4e00bc0 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index c4f26eb8363d..0f8ab65aff67 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7949,12 +7949,12 @@ static int i40e_sw_init(struct i40e_pf *pf) (pf->hw.func_caps.fd_filters_best_effort > 0)) { pf->flags |= I40E_FLAG_FD_ATR_ENABLED; pf->atr_sample_rate = I40E_DEFAULT_ATR_SAMPLE_RATE; - if (!(pf->flags & I40E_FLAG_MFP_ENABLED)) { - pf->flags |= I40E_FLAG_FD_SB_ENABLED; - } else { + if (pf->flags & I40E_FLAG_MFP_ENABLED && + pf->hw.num_partitions > 1) dev_info(&pf->pdev->dev, "Flow Director Sideband mode Disabled in MFP mode\n"); - } + else + pf->flags |= I40E_FLAG_FD_SB_ENABLED; pf->fdir_pf_filter_count = pf->hw.func_caps.fd_filters_guaranteed; pf->hw.fdir_shared_filter_count = -- cgit v1.2.3 From 106b1941ff304ad6b6b9828b24c8545814a7a4e4 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 3 Sep 2015 17:18:56 -0400 Subject: i40e: remove FD atr control from debugfs Since the flow-director-atr priv flag was added to our ethtool interface, we don't need the on/off control in debugfs. Change-ID: Ib3b599916434ab30ccd40074e71d7a81609b5bb5 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index c1dd2483e262..d15bd62eb874 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -953,24 +953,6 @@ static void i40e_dbg_dump_veb_all(struct i40e_pf *pf) } } -/** - * i40e_dbg_cmd_fd_ctrl - Enable/disable FD sideband/ATR - * @pf: the PF that would be altered - * @flag: flag that needs enabling or disabling - * @enable: Enable/disable FD SD/ATR - **/ -static void i40e_dbg_cmd_fd_ctrl(struct i40e_pf *pf, u64 flag, bool enable) -{ - if (enable) { - pf->flags |= flag; - } else { - pf->flags &= ~flag; - pf->auto_disable_flags |= flag; - } - dev_info(&pf->pdev->dev, "requesting a PF reset\n"); - i40e_do_reset_safe(pf, BIT(__I40E_PF_RESET_REQUESTED)); -} - #define I40E_MAX_DEBUG_OUT_BUFFER (4096*4) /** * i40e_dbg_command_write - write into command datum @@ -1759,10 +1741,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp, raw_packet = NULL; kfree(asc_packet); asc_packet = NULL; - } else if (strncmp(cmd_buf, "fd-atr off", 10) == 0) { - i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, false); - } else if (strncmp(cmd_buf, "fd-atr on", 9) == 0) { - i40e_dbg_cmd_fd_ctrl(pf, I40E_FLAG_FD_ATR_ENABLED, true); } else if (strncmp(cmd_buf, "fd current cnt", 14) == 0) { dev_info(&pf->pdev->dev, "FD current total filter count for this interface: %d\n", i40e_get_current_fd_count(pf)); @@ -1989,8 +1967,6 @@ static ssize_t i40e_dbg_command_write(struct file *filp, dev_info(&pf->pdev->dev, " send indirect aq_cmd \n"); dev_info(&pf->pdev->dev, " add fd_filter \n"); dev_info(&pf->pdev->dev, " rem fd_filter \n"); - dev_info(&pf->pdev->dev, " fd-atr off\n"); - dev_info(&pf->pdev->dev, " fd-atr on\n"); dev_info(&pf->pdev->dev, " fd current cnt"); dev_info(&pf->pdev->dev, " lldp start\n"); dev_info(&pf->pdev->dev, " lldp stop\n"); -- cgit v1.2.3 From 874d1a10eb1ab466f48627cdd268335a635dde52 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 3 Sep 2015 17:18:57 -0400 Subject: i40e/i40evf: remove redundant declarations of a variable and a function Remove a variable declaration inside an if block hiding an existing declaration at the start of the function. Also remove a forward function declaration that is no longer needed due to code re-organization. Change-ID: I12954668b722718074949c93d74cd20eaacd93e4 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 3 --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index b31139127616..ed70a3f18815 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -90,9 +90,6 @@ static const struct i40e_stats i40e_gstrings_misc_stats[] = { I40E_VSI_STAT("tx_linearize", tx_linearize), }; -static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi, - struct ethtool_rxnfc *cmd); - /* These PF_STATs might look like duplicates of some NETDEV_STATs, * but they are separate. This device supports Virtualization, and * as such might have several netdevs supporting VMDq and FCoE going diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index feb9ad58bb34..f156226fac21 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1628,7 +1628,7 @@ static void i40evf_reset_task(struct work_struct *work) /* extra wait to make sure minimum wait is met */ msleep(I40EVF_RESET_WAIT_MS); if (i == I40EVF_RESET_WAIT_COUNT) { - struct i40evf_mac_filter *f, *ftmp; + struct i40evf_mac_filter *ftmp; struct i40evf_vlan_filter *fv, *fvtmp; /* reset never finished */ -- cgit v1.2.3 From 3ac67d7bfa2f35cc8a52bdff39e3bbadb6e639a9 Mon Sep 17 00:00:00 2001 From: Kevin Scott Date: Thu, 3 Sep 2015 17:18:58 -0400 Subject: i40e: Store off PHY capabilities Store off reported PHY capabilities in link_info structure. Change-ID: Ife0f037c26983ca985dbf79abf33f8f8791369e8 Signed-off-by: Kevin Scott Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index ffd1cd0642f1..d1ee1745473d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1617,6 +1617,9 @@ i40e_status i40e_aq_get_phy_capabilities(struct i40e_hw *hw, if (hw->aq.asq_last_status == I40E_AQ_RC_EIO) status = I40E_ERR_UNKNOWN_PHY; + if (report_init) + hw->phy.phy_types = le32_to_cpu(abilities->phy_type); + return status; } -- cgit v1.2.3 From 3fced535079a6aaff2d85bd5c52ad50df0558e3d Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Thu, 3 Sep 2015 17:18:59 -0400 Subject: i40e: X722 is on the IOSF bus and does not report the PCI bus info X722 will report Gen 1x1 in the PCI config space as it is on IOSF bus, so skip the PCI bus link/speed check. Change-ID: Icd5f5751dc7fb00dccf0d5dc5a0a644948e7062e Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 69 ++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index c8591b9f63e1..d587a05cc228 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -333,6 +333,7 @@ struct i40e_pf { #define I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE BIT_ULL(38) #define I40E_FLAG_LINK_POLLING_ENABLED BIT_ULL(39) #define I40E_FLAG_VEB_MODE_ENABLED BIT_ULL(40) +#define I40E_FLAG_NO_PCI_LINK_CHECK BIT_ULL(42) /* tracks features that get auto disabled by errors */ u64 auto_disable_flags; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 0f8ab65aff67..2217078635ee 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10308,26 +10308,55 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) i40e_fcoe_vsi_setup(pf); #endif - /* Get the negotiated link width and speed from PCI config space */ - pcie_capability_read_word(pf->pdev, PCI_EXP_LNKSTA, &link_status); - - i40e_set_pci_config_data(hw, link_status); - - dev_info(&pdev->dev, "PCI-Express: %s %s\n", - (hw->bus.speed == i40e_bus_speed_8000 ? "Speed 8.0GT/s" : - hw->bus.speed == i40e_bus_speed_5000 ? "Speed 5.0GT/s" : - hw->bus.speed == i40e_bus_speed_2500 ? "Speed 2.5GT/s" : - "Unknown"), - (hw->bus.width == i40e_bus_width_pcie_x8 ? "Width x8" : - hw->bus.width == i40e_bus_width_pcie_x4 ? "Width x4" : - hw->bus.width == i40e_bus_width_pcie_x2 ? "Width x2" : - hw->bus.width == i40e_bus_width_pcie_x1 ? "Width x1" : - "Unknown")); - - if (hw->bus.width < i40e_bus_width_pcie_x8 || - hw->bus.speed < i40e_bus_speed_8000) { - dev_warn(&pdev->dev, "PCI-Express bandwidth available for this device may be insufficient for optimal performance.\n"); - dev_warn(&pdev->dev, "Please move the device to a different PCI-e link with more lanes and/or higher transfer rate.\n"); +#define PCI_SPEED_SIZE 8 +#define PCI_WIDTH_SIZE 8 + /* Devices on the IOSF bus do not have this information + * and will report PCI Gen 1 x 1 by default so don't bother + * checking them. + */ + if (!(pf->flags & I40E_FLAG_NO_PCI_LINK_CHECK)) { + char speed[PCI_SPEED_SIZE] = "Unknown"; + char width[PCI_WIDTH_SIZE] = "Unknown"; + + /* Get the negotiated link width and speed from PCI config + * space + */ + pcie_capability_read_word(pf->pdev, PCI_EXP_LNKSTA, + &link_status); + + i40e_set_pci_config_data(hw, link_status); + + switch (hw->bus.speed) { + case i40e_bus_speed_8000: + strncpy(speed, "8.0", PCI_SPEED_SIZE); break; + case i40e_bus_speed_5000: + strncpy(speed, "5.0", PCI_SPEED_SIZE); break; + case i40e_bus_speed_2500: + strncpy(speed, "2.5", PCI_SPEED_SIZE); break; + default: + break; + } + switch (hw->bus.width) { + case i40e_bus_width_pcie_x8: + strncpy(width, "8", PCI_WIDTH_SIZE); break; + case i40e_bus_width_pcie_x4: + strncpy(width, "4", PCI_WIDTH_SIZE); break; + case i40e_bus_width_pcie_x2: + strncpy(width, "2", PCI_WIDTH_SIZE); break; + case i40e_bus_width_pcie_x1: + strncpy(width, "1", PCI_WIDTH_SIZE); break; + default: + break; + } + + dev_info(&pdev->dev, "PCI-Express: Speed %sGT/s Width x%s\n", + speed, width); + + if (hw->bus.width < i40e_bus_width_pcie_x8 || + hw->bus.speed < i40e_bus_speed_8000) { + dev_warn(&pdev->dev, "PCI-Express bandwidth available for this device may be insufficient for optimal performance.\n"); + dev_warn(&pdev->dev, "Please move the device to a different PCI-e link with more lanes and/or higher transfer rate.\n"); + } } /* get the requested speeds from the fw */ -- cgit v1.2.3 From a916549029848f1356bf2d797e83218de53f17b2 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 3 Sep 2015 17:19:00 -0400 Subject: i40e: remove unnecessary string copy operations Save a little stack space and remove unnecessary strncpy() with a little string pointer. Change-ID: Id2719d34710bfc273d3bb445fec085cd04276e88 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 2217078635ee..e090c9ce6c26 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -4844,8 +4844,8 @@ out: */ void i40e_print_link_message(struct i40e_vsi *vsi, bool isup) { - char speed[SPEED_SIZE] = "Unknown"; - char fc[FC_SIZE] = "RX/TX"; + char *speed = "Unknown"; + char *fc = "Unknown"; if (vsi->current_isup == isup) return; @@ -4866,19 +4866,19 @@ void i40e_print_link_message(struct i40e_vsi *vsi, bool isup) switch (vsi->back->hw.phy.link_info.link_speed) { case I40E_LINK_SPEED_40GB: - strlcpy(speed, "40 Gbps", SPEED_SIZE); + speed = "40 G"; break; case I40E_LINK_SPEED_20GB: - strncpy(speed, "20 Gbps", SPEED_SIZE); + speed = "20 G"; break; case I40E_LINK_SPEED_10GB: - strlcpy(speed, "10 Gbps", SPEED_SIZE); + speed = "10 G"; break; case I40E_LINK_SPEED_1GB: - strlcpy(speed, "1000 Mbps", SPEED_SIZE); + speed = "1000 M"; break; case I40E_LINK_SPEED_100MB: - strncpy(speed, "100 Mbps", SPEED_SIZE); + speed = "100 M"; break; default: break; @@ -4886,20 +4886,20 @@ void i40e_print_link_message(struct i40e_vsi *vsi, bool isup) switch (vsi->back->hw.fc.current_mode) { case I40E_FC_FULL: - strlcpy(fc, "RX/TX", FC_SIZE); + fc = "RX/TX"; break; case I40E_FC_TX_PAUSE: - strlcpy(fc, "TX", FC_SIZE); + fc = "TX"; break; case I40E_FC_RX_PAUSE: - strlcpy(fc, "RX", FC_SIZE); + fc = "RX"; break; default: - strlcpy(fc, "None", FC_SIZE); + fc = "None"; break; } - netdev_info(vsi->netdev, "NIC Link is Up %s Full Duplex, Flow Control: %s\n", + netdev_info(vsi->netdev, "NIC Link is Up %sbps Full Duplex, Flow Control: %s\n", speed, fc); } -- cgit v1.2.3 From 5be8308b1614947f056802cb5775307f0ad54ad2 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 3 Sep 2015 17:19:01 -0400 Subject: i40evf: speed up init Shorten up the delays in the init task, allowing the VF driver to initialize faster. This aids performance in load/unload tests and mitigates DMAR errors in VF enable/disable tests with absurdly short delays. In the real world, the VF driver will come up more quickly. The original values were set conservatively based on what we expected from the firmware in terms of performance. Now that the driver is in use and we know how well firmware responds to our requests, we can shorten these delays. Change-ID: Ibead77d34b19e8170e667c3f58bc14748bbc5bc9 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index f156226fac21..bccca50a5777 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2315,7 +2315,7 @@ static void i40evf_init_task(struct work_struct *work) } return; restart: - schedule_delayed_work(&adapter->init_task, msecs_to_jiffies(30)); + schedule_delayed_work(&adapter->init_task, msecs_to_jiffies(20)); return; err_register: @@ -2332,7 +2332,7 @@ err: adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED; return; /* do not reschedule */ } - schedule_delayed_work(&adapter->init_task, HZ * 3); + schedule_delayed_work(&adapter->init_task, HZ / 2); } /** -- cgit v1.2.3 From 164f739361c962ac63aa6f7cbd48309d1bff15fb Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Thu, 3 Sep 2015 17:19:02 -0400 Subject: i40e/i40evf: Bump i40e version to 1.3.28 and i40evf to 1.3.19 Bump. Change-ID: I8d9a99f320af43960deba8718eee2d6de50eaf46 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index e090c9ce6c26..5ed844b73057 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -39,7 +39,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 3 -#define DRV_VERSION_BUILD 25 +#define DRV_VERSION_BUILD 28 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index bccca50a5777..429a46c2a2f7 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -34,7 +34,7 @@ char i40evf_driver_name[] = "i40evf"; static const char i40evf_driver_string[] = "Intel(R) XL710/X710 Virtual Function Network Driver"; -#define DRV_VERSION "1.3.17" +#define DRV_VERSION "1.3.19" const char i40evf_driver_version[] = DRV_VERSION; static const char i40evf_copyright[] = "Copyright (c) 2013 - 2015 Intel Corporation."; -- cgit v1.2.3 From a85ce532f28efabda030d9065a0c2023a2003f36 Mon Sep 17 00:00:00 2001 From: Mark Rustad Date: Wed, 9 Sep 2015 13:37:33 -0700 Subject: ixgbe: Check for setup_internal_link method Only call the internal_setup_link method when it is provided. This check is required for newer version parts. Signed-off-by: Mark Rustad Tested-by: Darin Miller Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 06b15eddc4ae..ebe0ac950b14 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -1617,7 +1617,7 @@ static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw) if (status) return status; - if (lsc) + if (lsc && phy->ops.setup_internal_link) return phy->ops.setup_internal_link(hw); return 0; -- cgit v1.2.3 From adc9048c607a08320e87befc940955d6ffe51fac Mon Sep 17 00:00:00 2001 From: lipeng Date: Thu, 15 Oct 2015 12:40:34 +0800 Subject: net: hisilicon: fixes a bug when using ethtool -S this patch fixes a bug in hns driver. when we want to get statistic info by using ethtool -S, it shows us there are 3 wrong counters info. because the strings related to the registers are wrong. it needs to modify the strings which give us wrong info. Signed-off-by: lipeng Signed-off-by: yankejian Signed-off-by: Yisen Zhuang Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c index dab5ecf382a0..802d55457f19 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c @@ -51,9 +51,9 @@ static const struct mac_stats_string g_xgmac_stats_string[] = { {"xgmac_rx_bad_pkt_from_dsaf", MAC_STATS_FIELD_OFF(rx_bad_from_sw)}, {"xgmac_tx_bad_pkt_64tomax", MAC_STATS_FIELD_OFF(tx_bad_pkts)}, - {"xgmac_rx_not_well_pkt", MAC_STATS_FIELD_OFF(rx_fragment_err)}, - {"xgmac_rx_good_well_pkt", MAC_STATS_FIELD_OFF(rx_undersize)}, - {"xgmac_rx_total_pkt", MAC_STATS_FIELD_OFF(rx_under_min)}, + {"xgmac_rx_bad_pkts_minto64", MAC_STATS_FIELD_OFF(rx_fragment_err)}, + {"xgmac_rx_good_pkts_minto64", MAC_STATS_FIELD_OFF(rx_undersize)}, + {"xgmac_rx_total_pkts_minto64", MAC_STATS_FIELD_OFF(rx_under_min)}, {"xgmac_rx_pkt_64", MAC_STATS_FIELD_OFF(rx_64bytes)}, {"xgmac_rx_pkt_65to127", MAC_STATS_FIELD_OFF(rx_65to127)}, {"xgmac_rx_pkt_128to255", MAC_STATS_FIELD_OFF(rx_128to255)}, -- cgit v1.2.3 From 53ca376eec4eb635e2249c8e89093f499e180731 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Thu, 15 Oct 2015 08:21:55 +0200 Subject: mlxsw: core: Fix race condition in __mlxsw_emad_transmit Under certain conditions EMAD responses can be returned from the device even before setting trans_active. This will cause the EMAD Rx listener to drop the EMAD response - as there are no active transactions - and timeouts will be generated. Fix this by setting trans_active before transmitting the EMAD skb. Fixes: 4ec14b7634b2 ("mlxsw: Add interface to access registers and process events") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index dbcaf5df8967..28c19cc1a17c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -374,26 +374,31 @@ static int __mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core, int err; int ret; + mlxsw_core->emad.trans_active = true; + err = mlxsw_core_skb_transmit(mlxsw_core->driver_priv, skb, tx_info); if (err) { dev_err(mlxsw_core->bus_info->dev, "Failed to transmit EMAD (tid=%llx)\n", mlxsw_core->emad.tid); dev_kfree_skb(skb); - return err; + goto trans_inactive_out; } - mlxsw_core->emad.trans_active = true; ret = wait_event_timeout(mlxsw_core->emad.wait, !(mlxsw_core->emad.trans_active), msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_MS)); if (!ret) { dev_warn(mlxsw_core->bus_info->dev, "EMAD timed-out (tid=%llx)\n", mlxsw_core->emad.tid); - mlxsw_core->emad.trans_active = false; - return -EIO; + err = -EIO; + goto trans_inactive_out; } return 0; + +trans_inactive_out: + mlxsw_core->emad.trans_active = false; + return err; } static int mlxsw_emad_process_status(struct mlxsw_core *mlxsw_core, -- cgit v1.2.3 From f7fadf3047d005d17376da65aa9e5734f45a77d4 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 14 Oct 2015 19:40:49 +0200 Subject: switchdev: make struct switchdev_attr parameter const for attr_set calls Signed-off-by: Jiri Pirko Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index eafa907965ec..f0e820d2b8ec 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4374,7 +4374,7 @@ static int rocker_port_bridge_ageing_time(struct rocker_port *rocker_port, } static int rocker_port_attr_set(struct net_device *dev, - struct switchdev_attr *attr, + const struct switchdev_attr *attr, struct switchdev_trans *trans) { struct rocker_port *rocker_port = netdev_priv(dev); -- cgit v1.2.3 From 850d0cbc9171f63f0418afffb0d89a84db927851 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 14 Oct 2015 19:40:51 +0200 Subject: switchdev: remove pointers from switchdev objects When object is used in deferred work, we cannot use pointers in switchdev object structures because the memory they point at may be already used by someone else. So rather do local copy of the value. Signed-off-by: Jiri Pirko Acked-by: Scott Feldman Reviewed-by: John Fastabend Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index f0e820d2b8ec..2cd7435b2316 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -4469,7 +4469,7 @@ static int rocker_port_obj_add(struct net_device *dev, fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj); err = rocker_port_fib_ipv4(rocker_port, trans, htonl(fib4->dst), fib4->dst_len, - fib4->fi, fib4->tb_id, 0); + &fib4->fi, fib4->tb_id, 0); break; case SWITCHDEV_OBJ_ID_PORT_FDB: err = rocker_port_fdb_add(rocker_port, trans, @@ -4541,7 +4541,7 @@ static int rocker_port_obj_del(struct net_device *dev, fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj); err = rocker_port_fib_ipv4(rocker_port, NULL, htonl(fib4->dst), fib4->dst_len, - fib4->fi, fib4->tb_id, + &fib4->fi, fib4->tb_id, ROCKER_OP_FLAG_REMOVE); break; case SWITCHDEV_OBJ_ID_PORT_FDB: @@ -4571,7 +4571,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port, hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) { if (found->key.rocker_port != rocker_port) continue; - fdb->addr = found->key.addr; + ether_addr_copy(fdb->addr, found->key.addr); fdb->ndm_state = NUD_REACHABLE; fdb->vid = rocker_port_vlan_to_vid(rocker_port, found->key.vlan_id); -- cgit v1.2.3 From d33eeb645d59ffd14bbc6db977c3783af42dd700 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 14 Oct 2015 19:40:54 +0200 Subject: rocker: remove nowait from switchdev callbacks. No need to avoid sleeping in switchdev callbacks now, as the switchdev core allows it. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/rocker/rocker.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c index 2cd7435b2316..32a80d2df7ff 100644 --- a/drivers/net/ethernet/rocker/rocker.c +++ b/drivers/net/ethernet/rocker/rocker.c @@ -3672,7 +3672,7 @@ static int rocker_port_fdb_flush(struct rocker_port *rocker_port, rocker_port->stp_state == BR_STATE_FORWARDING) return 0; - flags |= ROCKER_OP_FLAG_REMOVE; + flags |= ROCKER_OP_FLAG_NOWAIT | ROCKER_OP_FLAG_REMOVE; spin_lock_irqsave(&rocker->fdb_tbl_lock, lock_flags); @@ -4382,8 +4382,7 @@ static int rocker_port_attr_set(struct net_device *dev, switch (attr->id) { case SWITCHDEV_ATTR_ID_PORT_STP_STATE: - err = rocker_port_stp_update(rocker_port, trans, - ROCKER_OP_FLAG_NOWAIT, + err = rocker_port_stp_update(rocker_port, trans, 0, attr->u.stp_state); break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: @@ -4517,7 +4516,7 @@ static int rocker_port_fdb_del(struct rocker_port *rocker_port, const struct switchdev_obj_port_fdb *fdb) { __be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL); - int flags = ROCKER_OP_FLAG_NOWAIT | ROCKER_OP_FLAG_REMOVE; + int flags = ROCKER_OP_FLAG_REMOVE; if (!rocker_port_is_bridged(rocker_port)) return -EINVAL; -- cgit v1.2.3 From 96aec911482246a319bf457f39fa848ce436c8fd Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Wed, 14 Oct 2015 12:37:32 -0500 Subject: amd-xgbe: Use system workqueue for device restart A previous patch switched from using the system workqueue to the device workqueue for various operations. During a device restart the device workqueue is flushed so the restart cannot use this workqueue or else a deadlock results. Move the device restart back to using the system workqueue. Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 14bad8c44c87..49f796aaad4f 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -365,7 +365,7 @@ static irqreturn_t xgbe_isr(int irq, void *data) /* Restart the device on a Fatal Bus Error */ if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, FBE)) - queue_work(pdata->dev_workqueue, &pdata->restart_work); + schedule_work(&pdata->restart_work); /* Clear all interrupt signals */ XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_ch_isr); @@ -1537,7 +1537,7 @@ static void xgbe_tx_timeout(struct net_device *netdev) struct xgbe_prv_data *pdata = netdev_priv(netdev); netdev_warn(netdev, "tx timeout, device restarting\n"); - queue_work(pdata->dev_workqueue, &pdata->restart_work); + schedule_work(&pdata->restart_work); } static struct rtnl_link_stats64 *xgbe_get_stats64(struct net_device *netdev, -- cgit v1.2.3 From 33a704a59b6618dceb4a3ec1200b879294962c88 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Thu, 15 Oct 2015 17:43:15 +0200 Subject: mlxsw: Remove multicast ID configuration With respect to a firmware change, the Switch Multicast ID (SMID) register is no longer needed, so the related configuration code can be removed. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 53 -------------------------- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 11 ------ 2 files changed, 64 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 096e1c12175a..5e0c957c7c16 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -99,57 +99,6 @@ static const struct mlxsw_reg_info mlxsw_reg_spad = { */ MLXSW_ITEM_BUF(reg, spad, base_mac, 0x02, 6); -/* SMID - Switch Multicast ID - * -------------------------- - * In multi-chip configuration, each device should maintain mapping between - * Multicast ID (MID) into a list of local ports. This mapping is used in all - * the devices other than the ingress device, and is implemented as part of the - * FDB. The MID record maps from a MID, which is a unique identi- fier of the - * multicast group within the stacking domain, into a list of local ports into - * which the packet is replicated. - */ -#define MLXSW_REG_SMID_ID 0x2007 -#define MLXSW_REG_SMID_LEN 0x420 - -static const struct mlxsw_reg_info mlxsw_reg_smid = { - .id = MLXSW_REG_SMID_ID, - .len = MLXSW_REG_SMID_LEN, -}; - -/* reg_smid_swid - * Switch partition ID. - * Access: Index - */ -MLXSW_ITEM32(reg, smid, swid, 0x00, 24, 8); - -/* reg_smid_mid - * Multicast identifier - global identifier that represents the multicast group - * across all devices - * Access: Index - */ -MLXSW_ITEM32(reg, smid, mid, 0x00, 0, 16); - -/* reg_smid_port - * Local port memebership (1 bit per port). - * Access: RW - */ -MLXSW_ITEM_BIT_ARRAY(reg, smid, port, 0x20, 0x20, 1); - -/* reg_smid_port_mask - * Local port mask (1 bit per port). - * Access: W - */ -MLXSW_ITEM_BIT_ARRAY(reg, smid, port_mask, 0x220, 0x20, 1); - -static inline void mlxsw_reg_smid_pack(char *payload, u16 mid) -{ - MLXSW_REG_ZERO(smid, payload); - mlxsw_reg_smid_swid_set(payload, 0); - mlxsw_reg_smid_mid_set(payload, mid); - mlxsw_reg_smid_port_set(payload, MLXSW_PORT_CPU_PORT, 1); - mlxsw_reg_smid_port_mask_set(payload, MLXSW_PORT_CPU_PORT, 1); -} - /* SSPR - Switch System Port Record Register * ----------------------------------------- * Configures the system port to local port mapping. @@ -1272,8 +1221,6 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SGCR"; case MLXSW_REG_SPAD_ID: return "SPAD"; - case MLXSW_REG_SMID_ID: - return "SMID"; case MLXSW_REG_SSPR_ID: return "SSPR"; case MLXSW_REG_SPMS_ID: diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index d448431bbc83..835b632fb1a6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1371,20 +1371,9 @@ static int mlxsw_sx_flood_init(struct mlxsw_sx *mlxsw_sx) { char sfgc_pl[MLXSW_REG_SFGC_LEN]; char sgcr_pl[MLXSW_REG_SGCR_LEN]; - char *smid_pl; char *sftr_pl; int err; - /* Due to FW bug, we must configure SMID. */ - smid_pl = kmalloc(MLXSW_REG_SMID_LEN, GFP_KERNEL); - if (!smid_pl) - return -ENOMEM; - mlxsw_reg_smid_pack(smid_pl, MLXSW_PORT_MID); - err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(smid), smid_pl); - kfree(smid_pl); - if (err) - return err; - /* Configure a flooding table, which includes only CPU port. */ sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL); if (!sftr_pl) -- cgit v1.2.3 From ffe053285b77e9cd87c3b8e37f35bdb8de8172d1 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 15 Oct 2015 17:43:16 +0200 Subject: mlxsw: switchx2: Use ETH_ALEN for mac address length Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 835b632fb1a6..f057d43826f1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -57,13 +57,11 @@ static const char mlxsw_sx_driver_version[] = "1.0"; struct mlxsw_sx_port; -#define MLXSW_SW_HW_ID_LEN 6 - struct mlxsw_sx { struct mlxsw_sx_port **ports; struct mlxsw_core *core; const struct mlxsw_bus_info *bus_info; - u8 hw_id[MLXSW_SW_HW_ID_LEN]; + u8 hw_id[ETH_ALEN]; }; struct mlxsw_sx_port_pcpu_stats { -- cgit v1.2.3 From e4c870b1b496c90dc4fa9cf24937c7a45e84187f Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 15 Oct 2015 17:43:17 +0200 Subject: mlxsw: pci: Use MLXSW_PCI_CQS_MAX instead of MLXSW_PCI_CQS_COUNT The count of CQs can be different for various ASICs, so just define maximal value and check for that. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/pci.c | 8 ++++---- drivers/net/ethernet/mellanox/mlxsw/pci.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 462cea31ecbb..5ba740adc2e4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -830,7 +830,8 @@ static void mlxsw_pci_eq_tasklet(unsigned long data) { struct mlxsw_pci_queue *q = (struct mlxsw_pci_queue *) data; struct mlxsw_pci *mlxsw_pci = q->pci; - unsigned long active_cqns[BITS_TO_LONGS(MLXSW_PCI_CQS_COUNT)]; + u8 cq_count = mlxsw_pci_cq_count(mlxsw_pci); + unsigned long active_cqns[BITS_TO_LONGS(MLXSW_PCI_CQS_MAX)]; char *eqe; u8 cqn; bool cq_handle = false; @@ -866,7 +867,7 @@ static void mlxsw_pci_eq_tasklet(unsigned long data) if (!cq_handle) return; - for_each_set_bit(cqn, active_cqns, MLXSW_PCI_CQS_COUNT) { + for_each_set_bit(cqn, active_cqns, cq_count) { q = mlxsw_pci_cq_get(mlxsw_pci, cqn); mlxsw_pci_queue_tasklet_schedule(q); } @@ -1069,8 +1070,7 @@ static int mlxsw_pci_aqs_init(struct mlxsw_pci *mlxsw_pci, char *mbox) if ((num_sdqs != MLXSW_PCI_SDQS_COUNT) || (num_rdqs != MLXSW_PCI_RDQS_COUNT) || - (num_cqs != MLXSW_PCI_CQS_COUNT) || - (num_eqs != MLXSW_PCI_EQS_COUNT)) { + num_cqs > MLXSW_PCI_CQS_MAX || num_eqs != MLXSW_PCI_EQS_COUNT) { dev_err(&pdev->dev, "Unsupported number of queues\n"); return -EINVAL; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.h b/drivers/net/ethernet/mellanox/mlxsw/pci.h index 1ef9664b4512..efe1b4bc62d0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.h +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.h @@ -73,7 +73,7 @@ #define MLXSW_PCI_RDQS_COUNT 24 #define MLXSW_PCI_SDQS_COUNT 24 -#define MLXSW_PCI_CQS_COUNT (MLXSW_PCI_RDQS_COUNT + MLXSW_PCI_SDQS_COUNT) +#define MLXSW_PCI_CQS_MAX 96 #define MLXSW_PCI_EQS_COUNT 2 #define MLXSW_PCI_EQ_ASYNC_NUM 0 #define MLXSW_PCI_EQ_COMP_NUM 1 -- cgit v1.2.3 From 424e1114af94a543b3126f84ddd38742c7cfbbb6 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 15 Oct 2015 17:43:18 +0200 Subject: mlxsw: pci: Do not use MLXSW_PCI_SDQS_COUNT define Use mlxsw_pci_sdq_count helper instead. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 5ba740adc2e4..946341ee661c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -497,6 +497,7 @@ static int mlxsw_pci_rdq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, struct mlxsw_pci_queue *q) { struct mlxsw_pci_queue_elem_info *elem_info; + u8 sdq_count = mlxsw_pci_sdq_count(mlxsw_pci); int i; int err; @@ -504,9 +505,9 @@ static int mlxsw_pci_rdq_init(struct mlxsw_pci *mlxsw_pci, char *mbox, q->consumer_counter = 0; /* Set CQ of same number of this RDQ with base - * above MLXSW_PCI_SDQS_MAX as the lower ones are assigned to SDQs. + * above SDQ count as the lower ones are assigned to SDQs. */ - mlxsw_cmd_mbox_sw2hw_dq_cq_set(mbox, q->num + MLXSW_PCI_SDQS_COUNT); + mlxsw_cmd_mbox_sw2hw_dq_cq_set(mbox, sdq_count + q->num); mlxsw_cmd_mbox_sw2hw_dq_log2_dq_sz_set(mbox, 3); /* 8 pages */ for (i = 0; i < MLXSW_PCI_AQ_PAGES; i++) { dma_addr_t mapaddr = __mlxsw_pci_queue_page_get(q, i); -- cgit v1.2.3 From c85c3882ad88dd36105148912cd95084b09a5676 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 15 Oct 2015 17:43:19 +0200 Subject: mlxsw: pci: Remove MLXSW_PCI_RDQS/SDQS defines and checks Remove strict number check of queues count as various ASICs have different counts. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/pci.c | 3 +-- drivers/net/ethernet/mellanox/mlxsw/pci.h | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 946341ee661c..870d44322770 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1069,8 +1069,7 @@ static int mlxsw_pci_aqs_init(struct mlxsw_pci *mlxsw_pci, char *mbox) num_eqs = mlxsw_cmd_mbox_query_aq_cap_max_num_eqs_get(mbox); eq_log2sz = mlxsw_cmd_mbox_query_aq_cap_log_max_eq_sz_get(mbox); - if ((num_sdqs != MLXSW_PCI_SDQS_COUNT) || - (num_rdqs != MLXSW_PCI_RDQS_COUNT) || + if (num_sdqs + num_rdqs > num_cqs || num_cqs > MLXSW_PCI_CQS_MAX || num_eqs != MLXSW_PCI_EQS_COUNT) { dev_err(&pdev->dev, "Unsupported number of queues\n"); return -EINVAL; diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.h b/drivers/net/ethernet/mellanox/mlxsw/pci.h index efe1b4bc62d0..5b3453b6cf5d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.h +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.h @@ -71,8 +71,6 @@ #define MLXSW_PCI_DOORBELL(offset, type_offset, num) \ ((offset) + (type_offset) + (num) * 4) -#define MLXSW_PCI_RDQS_COUNT 24 -#define MLXSW_PCI_SDQS_COUNT 24 #define MLXSW_PCI_CQS_MAX 96 #define MLXSW_PCI_EQS_COUNT 2 #define MLXSW_PCI_EQ_ASYNC_NUM 0 -- cgit v1.2.3 From 3e2206da73e37c0fc07675b5caf25d3b26e33b7d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 15 Oct 2015 17:43:20 +0200 Subject: mlxsw: pci: Limit number of entries being sent in single MAP_FA cmd Firmware accepts only limited number of mapping entries for MAP_FA command. In order to prevent overflow, introduce a limit and in case the number of entries is bigger, call MAP_FA multiple times. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/cmd.h | 2 ++ drivers/net/ethernet/mellanox/mlxsw/pci.c | 26 ++++++++++++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index 770db17eb03f..27e48b426db5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h @@ -464,6 +464,8 @@ MLXSW_ITEM32(cmd_mbox, query_aq_cap, max_sg_rq, 0x10, 0, 8); * passed in this command must be pinned. */ +#define MLXSW_CMD_MAP_FA_VPM_ENTRIES_MAX 32 + static inline int mlxsw_cmd_map_fa(struct mlxsw_core *mlxsw_core, char *in_mbox, u32 vpm_entries_count) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 870d44322770..87afa5f7ef80 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -171,8 +171,8 @@ struct mlxsw_pci { struct msix_entry msix_entry; struct mlxsw_core *core; struct { - u16 num_pages; struct mlxsw_pci_mem_item *items; + unsigned int count; } fw_area; struct { struct mlxsw_pci_mem_item out_mbox; @@ -1272,6 +1272,7 @@ static int mlxsw_pci_fw_area_init(struct mlxsw_pci *mlxsw_pci, char *mbox, u16 num_pages) { struct mlxsw_pci_mem_item *mem_item; + int nent = 0; int i; int err; @@ -1279,7 +1280,7 @@ static int mlxsw_pci_fw_area_init(struct mlxsw_pci *mlxsw_pci, char *mbox, GFP_KERNEL); if (!mlxsw_pci->fw_area.items) return -ENOMEM; - mlxsw_pci->fw_area.num_pages = num_pages; + mlxsw_pci->fw_area.count = num_pages; mlxsw_cmd_mbox_zero(mbox); for (i = 0; i < num_pages; i++) { @@ -1293,13 +1294,22 @@ static int mlxsw_pci_fw_area_init(struct mlxsw_pci *mlxsw_pci, char *mbox, err = -ENOMEM; goto err_alloc; } - mlxsw_cmd_mbox_map_fa_pa_set(mbox, i, mem_item->mapaddr); - mlxsw_cmd_mbox_map_fa_log2size_set(mbox, i, 0); /* 1 page */ + mlxsw_cmd_mbox_map_fa_pa_set(mbox, nent, mem_item->mapaddr); + mlxsw_cmd_mbox_map_fa_log2size_set(mbox, nent, 0); /* 1 page */ + if (++nent == MLXSW_CMD_MAP_FA_VPM_ENTRIES_MAX) { + err = mlxsw_cmd_map_fa(mlxsw_pci->core, mbox, nent); + if (err) + goto err_cmd_map_fa; + nent = 0; + mlxsw_cmd_mbox_zero(mbox); + } } - err = mlxsw_cmd_map_fa(mlxsw_pci->core, mbox, num_pages); - if (err) - goto err_cmd_map_fa; + if (nent) { + err = mlxsw_cmd_map_fa(mlxsw_pci->core, mbox, nent); + if (err) + goto err_cmd_map_fa; + } return 0; @@ -1322,7 +1332,7 @@ static void mlxsw_pci_fw_area_fini(struct mlxsw_pci *mlxsw_pci) mlxsw_cmd_unmap_fa(mlxsw_pci->core); - for (i = 0; i < mlxsw_pci->fw_area.num_pages; i++) { + for (i = 0; i < mlxsw_pci->fw_area.count; i++) { mem_item = &mlxsw_pci->fw_area.items[i]; pci_free_consistent(mlxsw_pci->pdev, mem_item->size, -- cgit v1.2.3 From 18ea54454ecdd516ad11bf88d86f1994548692bf Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 15 Oct 2015 17:43:21 +0200 Subject: mlxsw: core: Do not use EMADs in mlxsw_emad_fini Be symmetric with mlxsw_emad_init and don't use EMADs in mlxsw_emad_fini cleanup function. Use command interface instead. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index dbcaf5df8967..7bf51d11ffc0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -551,6 +551,7 @@ static void mlxsw_emad_fini(struct mlxsw_core *mlxsw_core) { char hpkt_pl[MLXSW_REG_HPKT_LEN]; + mlxsw_core->emad.use_emad = false; mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_DISCARD, MLXSW_REG_HTGT_TRAP_GROUP_EMAD, MLXSW_TRAP_ID_ETHEMAD); -- cgit v1.2.3 From 6cf9dc8b77918c30260bc0f2e1853eb7d1ce34e8 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 15 Oct 2015 17:43:22 +0200 Subject: mlxsw: Use dev_level_ratelimited instead of net_ratelimit & dev_level Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/pci.c | 7 +++---- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 87afa5f7ef80..974ce47cec05 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -431,8 +431,7 @@ static int mlxsw_pci_wqe_frag_map(struct mlxsw_pci *mlxsw_pci, char *wqe, mapaddr = pci_map_single(pdev, frag_data, frag_len, direction); if (unlikely(pci_dma_mapping_error(pdev, mapaddr))) { - if (net_ratelimit()) - dev_err(&pdev->dev, "failed to dma map tx frag\n"); + dev_err_ratelimited(&pdev->dev, "failed to dma map tx frag\n"); return -EIO; } mlxsw_pci_wqe_address_set(wqe, index, mapaddr); @@ -700,8 +699,8 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci, put_new_skb: memset(wqe, 0, q->elem_size); err = mlxsw_pci_rdq_skb_alloc(mlxsw_pci, elem_info); - if (err && net_ratelimit()) - dev_dbg(&pdev->dev, "Failed to alloc skb for RDQ\n"); + if (err) + dev_dbg_ratelimited(&pdev->dev, "Failed to alloc skb for RDQ\n"); /* Everything is set up, ring doorbell to pass elem to HW */ q->producer_counter++; mlxsw_pci_queue_doorbell_producer_ring(mlxsw_pci, q); diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index f057d43826f1..698b182c77a3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1210,9 +1210,8 @@ static void mlxsw_sx_rx_listener_func(struct sk_buff *skb, u8 local_port, struct mlxsw_sx_port_pcpu_stats *pcpu_stats; if (unlikely(!mlxsw_sx_port)) { - if (net_ratelimit()) - dev_warn(mlxsw_sx->bus_info->dev, "Port %d: skb received for non-existent port\n", - local_port); + dev_warn_ratelimited(mlxsw_sx->bus_info->dev, "Port %d: skb received for non-existent port\n", + local_port); return; } -- cgit v1.2.3 From 3f0effd16b69d84558f2e7eb7ccd0e27a43173f4 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 15 Oct 2015 17:43:23 +0200 Subject: mlxsw: reg: Uppercase letters in register IDs Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 5e0c957c7c16..a2ebb790c8fc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -161,7 +161,7 @@ static inline void mlxsw_reg_sspr_pack(char *payload, u8 local_port) * ------------------------------------------- * Configures the spanning tree state of a physical port. */ -#define MLXSW_REG_SPMS_ID 0x200d +#define MLXSW_REG_SPMS_ID 0x200D #define MLXSW_REG_SPMS_LEN 0x404 static const struct mlxsw_reg_info mlxsw_reg_spms = { @@ -962,7 +962,7 @@ static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port) * Controls the association of a port with a switch partition and enables * configuring ports as stacking ports. */ -#define MLXSW_REG_PSPA_ID 0x500d +#define MLXSW_REG_PSPA_ID 0x500D #define MLXSW_REG_PSPA_LEN 0x8 static const struct mlxsw_reg_info mlxsw_reg_pspa = { -- cgit v1.2.3 From 36b78e8ababe6c596680d742f20bece5e8dc9820 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 15 Oct 2015 17:43:24 +0200 Subject: mlxsw: reg: Remove extra space in SFGC ID define Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index a2ebb790c8fc..34b95a197bfb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -205,7 +205,7 @@ static inline void mlxsw_reg_spms_pack(char *payload, u8 local_port, u16 vid, * The following register controls the association of flooding tables and MIDs * to packet types used for flooding. */ -#define MLXSW_REG_SFGC_ID 0x2011 +#define MLXSW_REG_SFGC_ID 0x2011 #define MLXSW_REG_SFGC_LEN 0x10 static const struct mlxsw_reg_info mlxsw_reg_sfgc = { -- cgit v1.2.3 From fa6ad058bc77b6ae69bd4512b538245ee5db39eb Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Thu, 15 Oct 2015 17:43:25 +0200 Subject: mlxsw: reg: Adjust definition of enum mlxsw_reg_sfgc_type Define max which would be needed later on. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 34b95a197bfb..6fca13a65a75 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -214,13 +214,15 @@ static const struct mlxsw_reg_info mlxsw_reg_sfgc = { }; enum mlxsw_reg_sfgc_type { - MLXSW_REG_SFGC_TYPE_BROADCAST = 0, - MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST = 1, - MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4 = 2, - MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6 = 3, - MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP = 5, - MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL = 6, - MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST = 7, + MLXSW_REG_SFGC_TYPE_BROADCAST, + MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST, + MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV4, + MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_IPV6, + MLXSW_REG_SFGC_TYPE_RESERVED, + MLXSW_REG_SFGC_TYPE_UNREGISTERED_MULTICAST_NON_IP, + MLXSW_REG_SFGC_TYPE_IPV4_LINK_LOCAL, + MLXSW_REG_SFGC_TYPE_IPV6_ALL_HOST, + MLXSW_REG_SFGC_TYPE_MAX, }; /* reg_sfgc_type -- cgit v1.2.3 From ebb7963f9b14bbaa07b6074579225d6338318ecb Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 15 Oct 2015 17:43:26 +0200 Subject: mlxsw: Introduce mlxsw_reg_spms_vid_pack helper and use it Introduce separate helper for packing SPMS VIDs, as it can be used for multiple VIDs and not only for one as previous SPMS pack function provided. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 8 ++++++-- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 6fca13a65a75..7595cf1ce384 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -192,11 +192,15 @@ enum mlxsw_reg_spms_state { */ MLXSW_ITEM_BIT_ARRAY(reg, spms, state, 0x04, 0x400, 2); -static inline void mlxsw_reg_spms_pack(char *payload, u8 local_port, u16 vid, - enum mlxsw_reg_spms_state state) +static inline void mlxsw_reg_spms_pack(char *payload, u8 local_port) { MLXSW_REG_ZERO(spms, payload); mlxsw_reg_spms_local_port_set(payload, local_port); +} + +static inline void mlxsw_reg_spms_vid_pack(char *payload, u16 vid, + enum mlxsw_reg_spms_state state) +{ mlxsw_reg_spms_state_set(payload, vid, state); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 698b182c77a3..7d5c851a7b9b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -923,7 +923,8 @@ static int mlxsw_sx_port_stp_state_set(struct mlxsw_sx_port *mlxsw_sx_port, spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL); if (!spms_pl) return -ENOMEM; - mlxsw_reg_spms_pack(spms_pl, mlxsw_sx_port->local_port, vid, state); + mlxsw_reg_spms_pack(spms_pl, mlxsw_sx_port->local_port); + mlxsw_reg_spms_vid_pack(spms_pl, vid, state); err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(spms), spms_pl); kfree(spms_pl); return err; -- cgit v1.2.3 From f24af330159aa1afbc6670e5786856a2a99d112c Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Thu, 15 Oct 2015 17:43:27 +0200 Subject: mlxsw: Simplify traps creation The Host Trap Group Table (HTGT) register configures trap groups, which are populated with trap IDs using the Host PacKet Trap (HPKT) register. However, a trap ID can only be present inside one trap group (the last configured). Instead of passing both the trap group and ID for the function that packs HPKT, pass only the trap ID and derive from it the trap group. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 2 -- drivers/net/ethernet/mellanox/mlxsw/reg.h | 14 ++++++++++++-- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 6 +----- 3 files changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 7bf51d11ffc0..9f4a0bf01336 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -506,7 +506,6 @@ static int mlxsw_emad_traps_set(struct mlxsw_core *mlxsw_core) return err; mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, - MLXSW_REG_HTGT_TRAP_GROUP_EMAD, MLXSW_TRAP_ID_ETHEMAD); return mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); } @@ -553,7 +552,6 @@ static void mlxsw_emad_fini(struct mlxsw_core *mlxsw_core) mlxsw_core->emad.use_emad = false; mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_DISCARD, - MLXSW_REG_HTGT_TRAP_GROUP_EMAD, MLXSW_TRAP_ID_ETHEMAD); mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl); diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 7595cf1ce384..fc6f520db575 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -1209,12 +1209,22 @@ enum { */ MLXSW_ITEM32(reg, hpkt, ctrl, 0x04, 16, 2); -static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, - u8 trap_group, u16 trap_id) +static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, u16 trap_id) { + u8 trap_group; + MLXSW_REG_ZERO(hpkt, payload); mlxsw_reg_hpkt_ack_set(payload, MLXSW_REG_HPKT_ACK_NOT_REQUIRED); mlxsw_reg_hpkt_action_set(payload, action); + switch (trap_id) { + case MLXSW_TRAP_ID_ETHEMAD: + case MLXSW_TRAP_ID_PUDE: + trap_group = MLXSW_REG_HTGT_TRAP_GROUP_EMAD; + break; + default: + trap_group = MLXSW_REG_HTGT_TRAP_GROUP_RX; + break; + } mlxsw_reg_hpkt_trap_group_set(payload, trap_group); mlxsw_reg_hpkt_trap_id_set(payload, trap_id); mlxsw_reg_hpkt_ctrl_set(payload, MLXSW_REG_HPKT_CTRL_PACKET_DEFAULT); diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 7d5c851a7b9b..85dcda44d0b0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1177,8 +1177,7 @@ static int mlxsw_sx_event_register(struct mlxsw_sx *mlxsw_sx, if (err) return err; - mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, - MLXSW_REG_HTGT_TRAP_GROUP_EMAD, trap_id); + mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, trap_id); err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl); if (err) goto err_event_trap_set; @@ -1322,7 +1321,6 @@ static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx) goto err_rx_listener_register; mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, - MLXSW_REG_HTGT_TRAP_GROUP_RX, mlxsw_sx_rx_listener[i].trap_id); err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl); if (err) @@ -1337,7 +1335,6 @@ err_rx_trap_set: err_rx_listener_register: for (i--; i >= 0; i--) { mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, - MLXSW_REG_HTGT_TRAP_GROUP_RX, mlxsw_sx_rx_listener[i].trap_id); mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl); @@ -1355,7 +1352,6 @@ static void mlxsw_sx_traps_fini(struct mlxsw_sx *mlxsw_sx) for (i = 0; i < ARRAY_SIZE(mlxsw_sx_rx_listener); i++) { mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, - MLXSW_REG_HTGT_TRAP_GROUP_RX, mlxsw_sx_rx_listener[i].trap_id); mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(hpkt), hpkt_pl); -- cgit v1.2.3 From 801bd3defb2eac756e6570168d0f8187781ad8ad Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Thu, 15 Oct 2015 17:43:28 +0200 Subject: mlxsw: Add trap group for control packets Previously, we trapped flooded and control packets using the same trap group. This can cause flooded packets to overflow the PCI bus and prevent control packets (e.g. STP, LACP) from getting to the CPU. Solve this by splitting the RX trap group to RX and control, which allows us to configure a policer on the first, thereby preventing it from overflowing the PCI bus. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 26 +++++++++++++++++++------- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 5 +++++ 2 files changed, 24 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index fc6f520db575..7b245af10e42 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -1029,8 +1029,11 @@ MLXSW_ITEM32(reg, htgt, swid, 0x00, 24, 8); */ MLXSW_ITEM32(reg, htgt, type, 0x00, 8, 4); -#define MLXSW_REG_HTGT_TRAP_GROUP_EMAD 0x0 -#define MLXSW_REG_HTGT_TRAP_GROUP_RX 0x1 +enum mlxsw_reg_htgt_trap_group { + MLXSW_REG_HTGT_TRAP_GROUP_EMAD, + MLXSW_REG_HTGT_TRAP_GROUP_RX, + MLXSW_REG_HTGT_TRAP_GROUP_CTRL, +}; /* reg_htgt_trap_group * Trap group number. User defined number specifying which trap groups @@ -1097,6 +1100,7 @@ MLXSW_ITEM32(reg, htgt, local_path_cpu_tclass, 0x10, 16, 6); #define MLXSW_REG_HTGT_LOCAL_PATH_RDQ_EMAD 0x15 #define MLXSW_REG_HTGT_LOCAL_PATH_RDQ_RX 0x14 +#define MLXSW_REG_HTGT_LOCAL_PATH_RDQ_CTRL 0x13 /* reg_htgt_local_path_rdq * Receive descriptor queue (RDQ) to use for the trap group. @@ -1104,21 +1108,29 @@ MLXSW_ITEM32(reg, htgt, local_path_cpu_tclass, 0x10, 16, 6); */ MLXSW_ITEM32(reg, htgt, local_path_rdq, 0x10, 0, 6); -static inline void mlxsw_reg_htgt_pack(char *payload, u8 trap_group) +static inline void mlxsw_reg_htgt_pack(char *payload, + enum mlxsw_reg_htgt_trap_group group) { u8 swid, rdq; MLXSW_REG_ZERO(htgt, payload); - if (MLXSW_REG_HTGT_TRAP_GROUP_EMAD == trap_group) { + switch (group) { + case MLXSW_REG_HTGT_TRAP_GROUP_EMAD: swid = MLXSW_PORT_SWID_ALL_SWIDS; rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_EMAD; - } else { + break; + case MLXSW_REG_HTGT_TRAP_GROUP_RX: swid = 0; rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_RX; + break; + case MLXSW_REG_HTGT_TRAP_GROUP_CTRL: + swid = 0; + rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_CTRL; + break; } mlxsw_reg_htgt_swid_set(payload, swid); mlxsw_reg_htgt_type_set(payload, MLXSW_REG_HTGT_PATH_TYPE_LOCAL); - mlxsw_reg_htgt_trap_group_set(payload, trap_group); + mlxsw_reg_htgt_trap_group_set(payload, group); mlxsw_reg_htgt_pide_set(payload, MLXSW_REG_HTGT_POLICER_DISABLE); mlxsw_reg_htgt_pid_set(payload, 0); mlxsw_reg_htgt_mirror_action_set(payload, MLXSW_REG_HTGT_TRAP_TO_CPU); @@ -1211,7 +1223,7 @@ MLXSW_ITEM32(reg, hpkt, ctrl, 0x04, 16, 2); static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, u16 trap_id) { - u8 trap_group; + enum mlxsw_reg_htgt_trap_group trap_group; MLXSW_REG_ZERO(hpkt, payload); mlxsw_reg_hpkt_ack_set(payload, MLXSW_REG_HPKT_ACK_NOT_REQUIRED); diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 85dcda44d0b0..4f72e0a423d9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1313,6 +1313,11 @@ static int mlxsw_sx_traps_init(struct mlxsw_sx *mlxsw_sx) if (err) return err; + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_CTRL); + err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(htgt), htgt_pl); + if (err) + return err; + for (i = 0; i < ARRAY_SIZE(mlxsw_sx_rx_listener); i++) { err = mlxsw_core_rx_listener_register(mlxsw_sx->core, &mlxsw_sx_rx_listener[i], -- cgit v1.2.3 From 5cd16d8c78fd17520fff437256f0c3a4e960fd5d Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Thu, 15 Oct 2015 17:43:29 +0200 Subject: mlxsw: cmd: Update CONFIG_PROFILE command documentation The meaning of certain parameters in the profile passed to the device during initialization has changed, so update their documentation accordingly. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/cmd.h | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index 27e48b426db5..c7889f4fa0d7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h @@ -570,7 +570,7 @@ MLXSW_ITEM32(cmd_mbox, config_profile, set_max_vlan_groups, 0x0C, 6, 1); */ MLXSW_ITEM32(cmd_mbox, config_profile, set_max_regions, 0x0C, 7, 1); -/* cmd_mbox_config_profile_set_fid_based +/* cmd_mbox_config_profile_set_flood_mode * Capability bit. Setting a bit to 1 configures the profile * according to the mailbox contents. */ @@ -651,12 +651,8 @@ MLXSW_ITEM32(cmd_mbox, config_profile, max_vlan_groups, 0x28, 0, 12); MLXSW_ITEM32(cmd_mbox, config_profile, max_regions, 0x2C, 0, 16); /* cmd_mbox_config_profile_max_flood_tables - * Maximum number of Flooding Tables. Flooding Tables are associated to - * the different packet types for the different switch partitions. - * Note that the table size depends on the fid_based mode. - * In SwitchX silicon, tables are split equally between the switch - * partitions. e.g. for 2 swids and 8 tables, the first 4 are associated - * with swid-1 and the last 4 are associated with swid-2. + * Maximum number of single-entry flooding tables. Different flooding tables + * can be associated with different packet types. */ MLXSW_ITEM32(cmd_mbox, config_profile, max_flood_tables, 0x30, 16, 4); @@ -667,12 +663,14 @@ MLXSW_ITEM32(cmd_mbox, config_profile, max_flood_tables, 0x30, 16, 4); */ MLXSW_ITEM32(cmd_mbox, config_profile, max_vid_flood_tables, 0x30, 8, 4); -/* cmd_mbox_config_profile_fid_based - * FID Based Flood Mode - * 00 Do not use FID to offset the index into the Port Group Table/Multicast ID - * 01 Use FID to offset the index to the Port Group Table (pgi) - * 10 Use FID to offset the index to the Port Group Table (pgi) and - * the Multicast ID +/* cmd_mbox_config_profile_flood_mode + * Flooding mode to use. + * 0-2 - Backward compatible modes for SwitchX devices. + * 3 - Mixed mode, where: + * max_flood_tables indicates the number of single-entry tables. + * max_vid_flood_tables indicates the number of per-VID tables. + * max_fid_offset_flood_tables indicates the number of FID-offset tables. + * max_fid_flood_tables indicates the number of per-FID tables. */ MLXSW_ITEM32(cmd_mbox, config_profile, flood_mode, 0x30, 0, 2); -- cgit v1.2.3 From e87eb4051efe76b35d0a297db772f5964a001544 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 15 Oct 2015 09:22:11 -0700 Subject: bonding: support encapsulated ipv6 TSO If using a sixtofour device on top of a bonding device, skb segmentation of TCP traffic is done right before calling bonding xmit, because bonding only enables TSO for IPv4. This patch improves single flow performance by about 120 % on my hosts, because segmentation is deferred right before calling slave xmit. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 90f2615428c0..d0f23cd6e236 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1071,7 +1071,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev, NETIF_F_HIGHDMA | NETIF_F_LRO) #define BOND_ENC_FEATURES (NETIF_F_ALL_CSUM | NETIF_F_SG | NETIF_F_RXCSUM |\ - NETIF_F_TSO) + NETIF_F_ALL_TSO) static void bond_compute_features(struct bonding *bond) { -- cgit v1.2.3 From 175f8d6746aa4b1dac5ccf576bcbc5488ff21a36 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Thu, 15 Oct 2015 12:24:09 -0400 Subject: mlx4: corretly check failed allocation When allocation fails, mlx4_alloc_cmd_mailbox returns -ENOMEM. Since there is no case that mlx4_alloc_cmd_mailbox returns NULL, it needs to be checked by IS_ERR, not IS_ERR_OR_NULL Signed-off-by: Insu Yun Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/mr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index 78f51e103880..93195191f45b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -318,7 +318,7 @@ int mlx4_mr_hw_get_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr, key, NULL); } else { mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR_OR_NULL(mailbox)) + if (IS_ERR(mailbox)) return PTR_ERR(mailbox); err = mlx4_cmd_box(dev, 0, mailbox->dma, key, -- cgit v1.2.3 From 47ea0325337b166c1c8695119aa6e83cdc035ef5 Mon Sep 17 00:00:00 2001 From: Ivan Vecera Date: Thu, 15 Oct 2015 21:28:52 +0200 Subject: drivers/net: get rid of unnecessary initializations in .get_drvinfo() Many drivers initialize uselessly n_priv_flags, n_stats, testinfo_len, eedump_len & regdump_len fields in their .get_drvinfo() ethtool op. It's not necessary as these fields is filled in ethtool_get_drvinfo(). v2: removed unused variable v3: removed another unused variable Signed-off-by: Ivan Vecera Signed-off-by: David S. Miller --- drivers/net/ethernet/aeroflex/greth.c | 2 -- drivers/net/ethernet/amd/au1000_eth.c | 1 - drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 1 - drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c | 4 ---- drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c | 4 ---- drivers/net/ethernet/atheros/atlx/atl1.c | 1 - drivers/net/ethernet/atheros/atlx/atl2.c | 4 ---- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 2 -- drivers/net/ethernet/broadcom/bcmsysport.c | 1 - drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | 4 ---- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 1 - drivers/net/ethernet/cavium/liquidio/lio_ethtool.c | 1 - drivers/net/ethernet/dec/tulip/de2104x.c | 1 - drivers/net/ethernet/emulex/benet/be_ethtool.c | 3 --- drivers/net/ethernet/freescale/gianfar_ethtool.c | 2 -- drivers/net/ethernet/freescale/ucc_geth_ethtool.c | 2 -- drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 1 - drivers/net/ethernet/ibm/emac/core.c | 1 - drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 2 -- drivers/net/ethernet/intel/e1000e/ethtool.c | 2 -- drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c | 4 ---- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 1 - drivers/net/ethernet/intel/igb/igb_ethtool.c | 4 ---- drivers/net/ethernet/intel/igbvf/ethtool.c | 2 -- drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c | 3 --- drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 3 --- drivers/net/ethernet/marvell/mv643xx_eth.c | 1 - drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 3 --- drivers/net/ethernet/neterion/s2io.c | 2 -- drivers/net/ethernet/neterion/vxge/vxge-ethtool.c | 4 ---- drivers/net/ethernet/octeon/octeon_mgmt.c | 4 ---- drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c | 1 - drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c | 2 -- drivers/net/ethernet/qlogic/qla3xxx.c | 2 -- drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c | 7 ------- drivers/net/ethernet/realtek/8139too.c | 1 - drivers/net/ethernet/sun/cassini.c | 3 --- drivers/net/ethernet/tehuti/tehuti.c | 5 ----- drivers/net/ethernet/ti/cpmac.c | 1 - drivers/net/ethernet/ti/cpsw.c | 1 - drivers/net/ethernet/ti/tlan.c | 1 - drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 1 - drivers/net/fjes/fjes_ethtool.c | 2 -- drivers/net/usb/asix_common.c | 1 - drivers/net/usb/dm9601.c | 1 - drivers/net/usb/mcs7830.c | 1 - drivers/net/usb/sr9800.c | 4 ---- drivers/net/vmxnet3/vmxnet3_ethtool.c | 4 ---- drivers/net/wireless/ipw2x00/ipw2200.c | 1 - 49 files changed, 110 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c index ae89de7deb13..20bf55dbd76f 100644 --- a/drivers/net/ethernet/aeroflex/greth.c +++ b/drivers/net/ethernet/aeroflex/greth.c @@ -1141,8 +1141,6 @@ static void greth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *in strlcpy(info->version, "revision: 1.0", sizeof(info->version)); strlcpy(info->bus_info, greth->dev->bus->name, sizeof(info->bus_info)); strlcpy(info->fw_version, "N/A", sizeof(info->fw_version)); - info->eedump_len = 0; - info->regdump_len = sizeof(struct greth_regs); } static void greth_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index cb367cc59e0b..5330bcb8a944 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -714,7 +714,6 @@ au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) strlcpy(info->version, DRV_VERSION, sizeof(info->version)); snprintf(info->bus_info, sizeof(info->bus_info), "%s %d", DRV_NAME, aup->mac_id); - info->regdump_len = 0; } static void au1000_set_msglevel(struct net_device *dev, u32 value) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c index 204fb3afb182..6040293db9c1 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c @@ -375,7 +375,6 @@ static void xgbe_get_drvinfo(struct net_device *netdev, XGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER), XGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID), XGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER)); - drvinfo->n_stats = XGBE_STATS_COUNT; } static u32 xgbe_get_msglevel(struct net_device *netdev) diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c index 48694c239d5c..872b7abb0196 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c @@ -233,10 +233,6 @@ static void atl1c_get_drvinfo(struct net_device *netdev, sizeof(drvinfo->version)); strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->n_stats = 0; - drvinfo->testinfo_len = 0; - drvinfo->regdump_len = atl1c_get_regs_len(netdev); - drvinfo->eedump_len = atl1c_get_eeprom_len(netdev); } static void atl1c_get_wol(struct net_device *netdev, diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c index 1be072f4afc2..8e3dbd4d9f79 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c @@ -316,10 +316,6 @@ static void atl1e_get_drvinfo(struct net_device *netdev, strlcpy(drvinfo->fw_version, "L1e", sizeof(drvinfo->fw_version)); strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->n_stats = 0; - drvinfo->testinfo_len = 0; - drvinfo->regdump_len = atl1e_get_regs_len(netdev); - drvinfo->eedump_len = atl1e_get_eeprom_len(netdev); } static void atl1e_get_wol(struct net_device *netdev, diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c index eca1d113fee1..529bca718334 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c @@ -3388,7 +3388,6 @@ static void atl1_get_drvinfo(struct net_device *netdev, sizeof(drvinfo->version)); strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->eedump_len = ATL1_EEDUMP_LEN; } static void atl1_get_wol(struct net_device *netdev, diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index 46a535318c7a..8f76f4558a88 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c @@ -2030,10 +2030,6 @@ static void atl2_get_drvinfo(struct net_device *netdev, strlcpy(drvinfo->fw_version, "L2", sizeof(drvinfo->fw_version)); strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->n_stats = 0; - drvinfo->testinfo_len = 0; - drvinfo->regdump_len = atl2_get_regs_len(netdev); - drvinfo->eedump_len = atl2_get_eeprom_len(netdev); } static void atl2_get_wol(struct net_device *netdev, diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index a7f2cc3e485e..95af75d35bc5 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -1333,7 +1333,6 @@ static void bcm_enet_get_drvinfo(struct net_device *netdev, sizeof(drvinfo->version)); strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); strlcpy(drvinfo->bus_info, "bcm63xx", sizeof(drvinfo->bus_info)); - drvinfo->n_stats = BCM_ENET_STATS_LEN; } static int bcm_enet_get_sset_count(struct net_device *netdev, @@ -2597,7 +2596,6 @@ static void bcm_enetsw_get_drvinfo(struct net_device *netdev, strncpy(drvinfo->version, bcm_enet_driver_version, 32); strncpy(drvinfo->fw_version, "N/A", 32); strncpy(drvinfo->bus_info, "bcm63xx", 32); - drvinfo->n_stats = BCM_ENETSW_STATS_LEN; } static void bcm_enetsw_get_ethtool_stats(struct net_device *netdev, diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index f1b5364f3521..858106352ce9 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -287,7 +287,6 @@ static void bcm_sysport_get_drvinfo(struct net_device *dev, strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); strlcpy(info->version, "0.1", sizeof(info->version)); strlcpy(info->bus_info, "platform", sizeof(info->bus_info)); - info->n_stats = BCM_SYSPORT_STATS_LEN; } static u32 bcm_sysport_get_msglvl(struct net_device *dev) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index aeb7ce64452e..a2bc5314a62b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1090,10 +1090,6 @@ static void bnx2x_get_drvinfo(struct net_device *dev, bnx2x_fill_fw_str(bp, info->fw_version, sizeof(info->fw_version)); strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info)); - info->n_stats = BNX2X_NUM_STATS; - info->testinfo_len = BNX2X_NUM_TESTS(bp); - info->eedump_len = bp->common.flash_size; - info->regdump_len = bnx2x_get_regs_len(dev); } static void bnx2x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 1a3988f51305..410995cd7ea4 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -793,7 +793,6 @@ static void bcmgenet_get_drvinfo(struct net_device *dev, { strlcpy(info->driver, "bcmgenet", sizeof(info->driver)); strlcpy(info->version, "v2.0", sizeof(info->version)); - info->n_stats = BCMGENET_STATS_LEN; } static int bcmgenet_get_sset_count(struct net_device *dev, int string_set) diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c index 29f330831784..245c063ed4db 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c @@ -153,7 +153,6 @@ lio_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) strncpy(drvinfo->fw_version, oct->fw_info.liquidio_firmware_version, ETHTOOL_FWVERS_LEN); strncpy(drvinfo->bus_info, pci_name(oct->pci_dev), 32); - drvinfo->regdump_len = OCT_ETHTOOL_REGDUMP_LEN; } static void diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c index a02ecc4f9002..cadcee645f74 100644 --- a/drivers/net/ethernet/dec/tulip/de2104x.c +++ b/drivers/net/ethernet/dec/tulip/de2104x.c @@ -1597,7 +1597,6 @@ static void de_get_drvinfo (struct net_device *dev,struct ethtool_drvinfo *info) strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); strlcpy(info->version, DRV_VERSION, sizeof(info->version)); strlcpy(info->bus_info, pci_name(de->pdev), sizeof(info->bus_info)); - info->eedump_len = DE_EEPROM_SIZE; } static int de_get_regs_len(struct net_device *dev) diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 2c9ed1710ba6..f4cb8e425853 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -234,9 +234,6 @@ static void be_get_drvinfo(struct net_device *netdev, strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->testinfo_len = 0; - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; } static u32 lancer_cmd_get_file_len(struct be_adapter *adapter, u8 *file_name) diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index fb7f8d67aef4..928ca2bdd238 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -182,8 +182,6 @@ static void gfar_gdrvinfo(struct net_device *dev, sizeof(drvinfo->version)); strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); strlcpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info)); - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; } diff --git a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c index cc83350d56ba..89714f5e0dfc 100644 --- a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c +++ b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c @@ -351,8 +351,6 @@ uec_get_drvinfo(struct net_device *netdev, strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version)); strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); strlcpy(drvinfo->bus_info, "QUICC ENGINE", sizeof(drvinfo->bus_info)); - drvinfo->eedump_len = 0; - drvinfo->regdump_len = uec_get_regs_len(netdev); } #ifdef CONFIG_PM diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 2550208cb22e..7d58918abb78 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -682,7 +682,6 @@ static void hns_nic_get_drvinfo(struct net_device *net_dev, drvinfo->bus_info[ETHTOOL_BUSINFO_LEN - 1] = '\0'; strncpy(drvinfo->fw_version, "N/A", ETHTOOL_FWVERS_LEN); - drvinfo->eedump_len = 0; } /** diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index b60a34d982a9..5d7db6c01c46 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -2204,7 +2204,6 @@ static void emac_ethtool_get_drvinfo(struct net_device *ndev, strlcpy(info->version, DRV_VERSION, sizeof(info->version)); snprintf(info->bus_info, sizeof(info->bus_info), "PPC 4xx EMAC-%d %s", dev->cell_index, dev->ofdev->dev.of_node->full_name); - info->regdump_len = emac_ethtool_get_regs_len(ndev); } static const struct ethtool_ops emac_ethtool_ops = { diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c index 4270ad2d4ddf..83e557c7f279 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c +++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c @@ -559,8 +559,6 @@ static void e1000_get_drvinfo(struct net_device *netdev, strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->regdump_len = e1000_get_regs_len(netdev); - drvinfo->eedump_len = e1000_get_eeprom_len(netdev); } static void e1000_get_ringparam(struct net_device *netdev, diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index ad6daa656d3e..6cab1f30d41e 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -648,8 +648,6 @@ static void e1000_get_drvinfo(struct net_device *netdev, strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->regdump_len = e1000_get_regs_len(netdev); - drvinfo->eedump_len = e1000_get_eeprom_len(netdev); } static void e1000_get_ringparam(struct net_device *netdev, diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c index 447a5f8da42f..2ce0eba5e040 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c @@ -515,10 +515,6 @@ static void fm10k_get_drvinfo(struct net_device *dev, sizeof(info->version) - 1); strncpy(info->bus_info, pci_name(interface->pdev), sizeof(info->bus_info) - 1); - - info->n_stats = fm10k_get_sset_count(dev, ETH_SS_STATS); - - info->regdump_len = fm10k_get_regs_len(dev); } static void fm10k_get_pauseparam(struct net_device *dev, diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index ed70a3f18815..e7fd84c5b9f3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1126,7 +1126,6 @@ static void i40e_get_drvinfo(struct net_device *netdev, sizeof(drvinfo->fw_version)); strlcpy(drvinfo->bus_info, pci_name(pf->pdev), sizeof(drvinfo->bus_info)); - drvinfo->n_priv_flags = I40E_PRIV_FLAGS_STR_LEN; } static void i40e_get_ringparam(struct net_device *netdev, diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index 74262768b09b..2529bc625de4 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -842,10 +842,6 @@ static void igb_get_drvinfo(struct net_device *netdev, sizeof(drvinfo->fw_version)); strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->n_stats = IGB_STATS_LEN; - drvinfo->testinfo_len = IGB_TEST_LEN; - drvinfo->regdump_len = igb_get_regs_len(netdev); - drvinfo->eedump_len = igb_get_eeprom_len(netdev); } static void igb_get_ringparam(struct net_device *netdev, diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c index c6996feb1cb4..b74ce53d7b52 100644 --- a/drivers/net/ethernet/intel/igbvf/ethtool.c +++ b/drivers/net/ethernet/intel/igbvf/ethtool.c @@ -196,8 +196,6 @@ static void igbvf_get_drvinfo(struct net_device *netdev, sizeof(drvinfo->version)); strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->regdump_len = igbvf_get_regs_len(netdev); - drvinfo->eedump_len = igbvf_get_eeprom_len(netdev); } static void igbvf_get_ringparam(struct net_device *netdev, diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c index b311e9e710d2..d2b29b490ae0 100644 --- a/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c +++ b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c @@ -479,9 +479,6 @@ ixgb_get_drvinfo(struct net_device *netdev, sizeof(drvinfo->version)); strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->n_stats = IXGB_STATS_LEN; - drvinfo->regdump_len = ixgb_get_regs_len(netdev); - drvinfo->eedump_len = ixgb_get_eeprom_len(netdev); } static void diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 94c4912b2330..d681273bd39d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -943,9 +943,6 @@ static void ixgbe_get_drvinfo(struct net_device *netdev, strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->n_stats = IXGBE_STATS_LEN; - drvinfo->testinfo_len = IXGBE_TEST_LEN; - drvinfo->regdump_len = ixgbe_get_regs_len(netdev); } static void ixgbe_get_ringparam(struct net_device *netdev, diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index c78ae1868097..603d29df5832 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -1586,7 +1586,6 @@ static void mv643xx_eth_get_drvinfo(struct net_device *dev, sizeof(drvinfo->version)); strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); strlcpy(drvinfo->bus_info, "platform", sizeof(drvinfo->bus_info)); - drvinfo->n_stats = ARRAY_SIZE(mv643xx_eth_stats); } static int mv643xx_eth_nway_reset(struct net_device *dev) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index f79d8124321e..ddb5541882f5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -95,9 +95,6 @@ mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) (u16) (mdev->dev->caps.fw_ver & 0xffff)); strlcpy(drvinfo->bus_info, pci_name(mdev->dev->persist->pdev), sizeof(drvinfo->bus_info)); - drvinfo->n_stats = 0; - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; } static const char mlx4_en_priv_flags[][ETH_GSTRING_LEN] = { diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index 2d1b94274079..9ba975853ec6 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -5389,8 +5389,6 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev, strlcpy(info->driver, s2io_driver_name, sizeof(info->driver)); strlcpy(info->version, s2io_driver_version, sizeof(info->version)); strlcpy(info->bus_info, pci_name(sp->pdev), sizeof(info->bus_info)); - info->regdump_len = XENA_REG_SPACE; - info->eedump_len = XENA_EEPROM_SPACE; } /** diff --git a/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c b/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c index be916eb2f2e7..9a2967016c18 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-ethtool.c @@ -105,10 +105,6 @@ static void vxge_ethtool_gdrvinfo(struct net_device *dev, strlcpy(info->version, DRV_VERSION, sizeof(info->version)); strlcpy(info->fw_version, vdev->fw_version, sizeof(info->fw_version)); strlcpy(info->bus_info, pci_name(vdev->pdev), sizeof(info->bus_info)); - info->regdump_len = sizeof(struct vxge_hw_vpath_reg) - * vdev->no_of_vpath; - - info->n_stats = STAT_LEN; } /** diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c index 7bf9c028d8d7..c177c7cec13b 100644 --- a/drivers/net/ethernet/octeon/octeon_mgmt.c +++ b/drivers/net/ethernet/octeon/octeon_mgmt.c @@ -1344,10 +1344,6 @@ static void octeon_mgmt_get_drvinfo(struct net_device *netdev, strlcpy(info->version, DRV_VERSION, sizeof(info->version)); strlcpy(info->fw_version, "N/A", sizeof(info->fw_version)); strlcpy(info->bus_info, "N/A", sizeof(info->bus_info)); - info->n_stats = 0; - info->testinfo_len = 0; - info->regdump_len = 0; - info->eedump_len = 0; } static int octeon_mgmt_get_settings(struct net_device *netdev, diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c index f6fcf7450352..b19be7c6c1f4 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c @@ -164,7 +164,6 @@ static void pch_gbe_get_drvinfo(struct net_device *netdev, strlcpy(drvinfo->version, pch_driver_version, sizeof(drvinfo->version)); strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->regdump_len = pch_gbe_get_regs_len(netdev); } /** diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c index 87e073c6e291..f9034467736c 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c @@ -93,8 +93,6 @@ netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->regdump_len = NETXEN_NIC_REGS_LEN; - drvinfo->eedump_len = netxen_nic_get_eeprom_len(dev); } static int diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index 4847713211ca..b09a6b80d107 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -1736,8 +1736,6 @@ static void ql_get_drvinfo(struct net_device *ndev, sizeof(drvinfo->version)); strlcpy(drvinfo->bus_info, pci_name(qdev->pdev), sizeof(drvinfo->bus_info)); - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; } static u32 ql_get_msglevel(struct net_device *ndev) diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c index c3c514e332b5..5dade1fd08b8 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c @@ -415,13 +415,6 @@ static void ql_get_drvinfo(struct net_device *ndev, (qdev->fw_rev_id & 0x000000ff)); strlcpy(drvinfo->bus_info, pci_name(qdev->pdev), sizeof(drvinfo->bus_info)); - drvinfo->n_stats = 0; - drvinfo->testinfo_len = 0; - if (!test_bit(QL_FRC_COREDUMP, &qdev->flags)) - drvinfo->regdump_len = sizeof(struct ql_mpi_coredump); - else - drvinfo->regdump_len = sizeof(struct ql_reg_dump); - drvinfo->eedump_len = 0; } static void ql_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c index 78bb4ceb1cdd..ef668d300800 100644 --- a/drivers/net/ethernet/realtek/8139too.c +++ b/drivers/net/ethernet/realtek/8139too.c @@ -2388,7 +2388,6 @@ static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo * strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); strlcpy(info->version, DRV_VERSION, sizeof(info->version)); strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info)); - info->regdump_len = tp->regs_len; } static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index 6ce973187225..062bce9acde6 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -4529,9 +4529,6 @@ static void cas_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver)); strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); strlcpy(info->bus_info, pci_name(cp->pdev), sizeof(info->bus_info)); - info->regdump_len = cp->casreg_len < CAS_MAX_REGS ? - cp->casreg_len : CAS_MAX_REGS; - info->n_stats = CAS_NUM_STAT_KEYS; } static int cas_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index a9cac8413e49..14c9d1baa85c 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -2182,11 +2182,6 @@ bdx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); strlcpy(drvinfo->bus_info, pci_name(priv->pdev), sizeof(drvinfo->bus_info)); - - drvinfo->n_stats = ((priv->stats_flag) ? ARRAY_SIZE(bdx_stat_names) : 0); - drvinfo->testinfo_len = 0; - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; } /* diff --git a/drivers/net/ethernet/ti/cpmac.c b/drivers/net/ethernet/ti/cpmac.c index cba3d9fcb465..77d26fe286c0 100644 --- a/drivers/net/ethernet/ti/cpmac.c +++ b/drivers/net/ethernet/ti/cpmac.c @@ -899,7 +899,6 @@ static void cpmac_get_drvinfo(struct net_device *dev, strlcpy(info->driver, "cpmac", sizeof(info->driver)); strlcpy(info->version, CPMAC_VERSION, sizeof(info->version)); snprintf(info->bus_info, sizeof(info->bus_info), "%s", "cpmac"); - info->regdump_len = 0; } static const struct ethtool_ops cpmac_ethtool_ops = { diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 75584cc36339..3b75adfb3f37 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1784,7 +1784,6 @@ static void cpsw_get_drvinfo(struct net_device *ndev, strlcpy(info->driver, "cpsw", sizeof(info->driver)); strlcpy(info->version, "1.0", sizeof(info->version)); strlcpy(info->bus_info, priv->pdev->name, sizeof(info->bus_info)); - info->regdump_len = cpsw_get_regs_len(ndev); } static u32 cpsw_get_msglevel(struct net_device *ndev) diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c index 691ec936e88d..a274cd49afe9 100644 --- a/drivers/net/ethernet/ti/tlan.c +++ b/drivers/net/ethernet/ti/tlan.c @@ -791,7 +791,6 @@ static void tlan_get_drvinfo(struct net_device *dev, sizeof(info->bus_info)); else strlcpy(info->bus_info, "EISA", sizeof(info->bus_info)); - info->eedump_len = TLAN_EEPROM_SIZE; } static int tlan_get_eeprom_len(struct net_device *dev) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index d95f9aae95e7..4684644703cc 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1135,7 +1135,6 @@ static void axienet_ethtools_get_drvinfo(struct net_device *ndev, { strlcpy(ed->driver, DRIVER_NAME, sizeof(ed->driver)); strlcpy(ed->version, DRIVER_VERSION, sizeof(ed->version)); - ed->regdump_len = sizeof(u32) * AXIENET_REGS_N; } /** diff --git a/drivers/net/fjes/fjes_ethtool.c b/drivers/net/fjes/fjes_ethtool.c index 0119dd199276..9c218e140c41 100644 --- a/drivers/net/fjes/fjes_ethtool.c +++ b/drivers/net/fjes/fjes_ethtool.c @@ -105,8 +105,6 @@ static void fjes_get_drvinfo(struct net_device *netdev, strlcpy(drvinfo->fw_version, "none", sizeof(drvinfo->fw_version)); snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info), "platform:%s", plat_dev->name); - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; } static int fjes_get_settings(struct net_device *netdev, diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c index a186b0a12d50..bd9acff1eb7b 100644 --- a/drivers/net/usb/asix_common.c +++ b/drivers/net/usb/asix_common.c @@ -588,7 +588,6 @@ void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) usbnet_get_drvinfo(net, info); strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver)); strlcpy(info->version, DRIVER_VERSION, sizeof(info->version)); - info->eedump_len = AX_EEPROM_LEN; } int asix_set_mac_address(struct net_device *net, void *p) diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 6e9c344c7a20..0b4bdd39106b 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -258,7 +258,6 @@ static void dm9601_get_drvinfo(struct net_device *net, { /* Inherit standard device info */ usbnet_get_drvinfo(net, info); - info->eedump_len = DM_EEPROM_LEN; } static u32 dm9601_get_link(struct net_device *net) diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index 82d844a8ebd0..4f345bd4e6e2 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -445,7 +445,6 @@ static int mcs7830_get_regs_len(struct net_device *net) static void mcs7830_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *drvinfo) { usbnet_get_drvinfo(net, drvinfo); - drvinfo->regdump_len = mcs7830_get_regs_len(net); } static void mcs7830_get_regs(struct net_device *net, struct ethtool_regs *regs, void *data) diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c index 953de13267df..a50df0d8fb9a 100644 --- a/drivers/net/usb/sr9800.c +++ b/drivers/net/usb/sr9800.c @@ -470,14 +470,10 @@ static int sr_get_eeprom(struct net_device *net, static void sr_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) { - struct usbnet *dev = netdev_priv(net); - struct sr_data *data = (struct sr_data *)&dev->data; - /* Inherit standard device info */ usbnet_get_drvinfo(net, info); strncpy(info->driver, DRIVER_NAME, sizeof(info->driver)); strncpy(info->version, DRIVER_VERSION, sizeof(info->version)); - info->eedump_len = data->eeprom_len; } static u32 sr_get_link(struct net_device *net) diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index a681569ae0b5..9ba11d737753 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -214,10 +214,6 @@ vmxnet3_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->n_stats = vmxnet3_get_sset_count(netdev, ETH_SS_STATS); - drvinfo->testinfo_len = 0; - drvinfo->eedump_len = 0; - drvinfo->regdump_len = vmxnet3_get_regs_len(netdev); } diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 39f3e6f5cbcd..ed0adaf1eec4 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -10470,7 +10470,6 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev, vers, date); strlcpy(info->bus_info, pci_name(p->pci_dev), sizeof(info->bus_info)); - info->eedump_len = IPW_EEPROM_IMAGE_SIZE; } static u32 ipw_ethtool_get_link(struct net_device *dev) -- cgit v1.2.3 From 5f715c097965c0ad037f64393d0b95c50287775b Mon Sep 17 00:00:00 2001 From: Andrej Ota Date: Thu, 15 Oct 2015 00:14:37 +0200 Subject: via-rhine: fix VLAN receive handling regression. Because eth_type_trans() consumes ethernet header worth of bytes, a call to read TCI from end of packet using rhine_rx_vlan_tag() no longer works as it's reading from an invalid offset. Tested to be working on PCEngines Alix board. Fixes: 810f19bcb862 ("via-rhine: add consistent memory barrier in vlan receive code.") Signed-off-by: Andrej Ota Acked-by: Francois Romieu Signed-off-by: David S. Miller --- drivers/net/ethernet/via/via-rhine.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index a83263743665..2b7550c43f78 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -2134,10 +2134,11 @@ static int rhine_rx(struct net_device *dev, int limit) } skb_put(skb, pkt_len); - skb->protocol = eth_type_trans(skb, dev); rhine_rx_vlan_tag(skb, desc, data_size); + skb->protocol = eth_type_trans(skb, dev); + netif_receive_skb(skb); u64_stats_update_begin(&rp->rx_stats.syncp); -- cgit v1.2.3 From c67caceb864cf15731532ab25162166c228fa270 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 24 Sep 2015 09:04:26 -0700 Subject: i40e/i40evf: Fix handling of napi budget The polling routine for i40e was rounding up the budget for Rx cleanup to 1. This is incorrect as the netpoll poll call is expecting no Rx to be processed as the budget passed was 0. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 5 +++++ drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 01e5ece8046d..b560e0257ba6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1846,6 +1846,10 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) ring->arm_wb = false; } + /* Handle case where we are called by netpoll with a budget of 0 */ + if (budget <= 0) + goto tx_only; + /* We attempt to distribute budget to each Rx queue fairly, but don't * allow the budget to go below 1 because that would exit polling early. */ @@ -1862,6 +1866,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) /* If work not completed, return budget and polling will return */ if (!clean_complete) { +tx_only: if (arm_wb) i40e_force_wb(vsi, q_vector); return budget; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 0e71eb4633d5..1894cc8c0524 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1287,6 +1287,10 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget) ring->arm_wb = false; } + /* Handle case where we are called by netpoll with a budget of 0 */ + if (budget <= 0) + goto tx_only; + /* We attempt to distribute budget to each Rx queue fairly, but don't * allow the budget to go below 1 because that would exit polling early. */ @@ -1303,6 +1307,7 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget) /* If work not completed, return budget and polling will return */ if (!clean_complete) { +tx_only: if (arm_wb) i40evf_force_wb(vsi, q_vector); return budget; -- cgit v1.2.3 From 8b6503590510fd7a8b303feeaf8a45a192e2b8df Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 24 Sep 2015 09:04:32 -0700 Subject: i40e/i40evf: Drop useless "IN_NETPOLL" flag The code in i40e and i40evf is using an "IN_NETPOLL" flag that has never added any value due to the fact that the Rx clean-up is handled in NAPI. As such the flag was set, the queue was scheduled via NAPI, and then polled from the netpoll controller and if any Rx packets were processed the were processed in the wrong context. In addition the flag itself just added an unneeded conditional to the hot-path so it can safely be dropped and save us a few instructions. Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 - drivers/net/ethernet/intel/i40e/i40e_main.c | 2 -- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 7 +------ drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 7 +------ drivers/net/ethernet/intel/i40evf/i40evf.h | 2 -- 5 files changed, 2 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index d587a05cc228..91f8cbffa6a8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -307,7 +307,6 @@ struct i40e_pf { #ifdef I40E_FCOE #define I40E_FLAG_FCOE_ENABLED BIT_ULL(11) #endif /* I40E_FCOE */ -#define I40E_FLAG_IN_NETPOLL BIT_ULL(12) #define I40E_FLAG_16BYTE_RX_DESC_ENABLED BIT_ULL(13) #define I40E_FLAG_CLEAN_ADMINQ BIT_ULL(14) #define I40E_FLAG_FILTER_SYNC BIT_ULL(15) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 5ed844b73057..389f110ee734 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3574,14 +3574,12 @@ static void i40e_netpoll(struct net_device *netdev) if (test_bit(__I40E_DOWN, &vsi->state)) return; - pf->flags |= I40E_FLAG_IN_NETPOLL; if (pf->flags & I40E_FLAG_MSIX_ENABLED) { for (i = 0; i < vsi->num_q_vectors; i++) i40e_msix_clean_rings(0, vsi->q_vectors[i]); } else { i40e_intr(pf->pdev->irq, netdev); } - pf->flags &= ~I40E_FLAG_IN_NETPOLL; } #endif diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index b560e0257ba6..e1fac3b1e088 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1268,16 +1268,11 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring, struct sk_buff *skb, u16 vlan_tag) { struct i40e_q_vector *q_vector = rx_ring->q_vector; - struct i40e_vsi *vsi = rx_ring->vsi; - u64 flags = vsi->back->flags; if (vlan_tag & VLAN_VID_MASK) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); - if (flags & I40E_FLAG_IN_NETPOLL) - netif_rx(skb); - else - napi_gro_receive(&q_vector->napi, skb); + napi_gro_receive(&q_vector->napi, skb); } /** diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 1894cc8c0524..5d3a8bd91abf 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -742,16 +742,11 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring, struct sk_buff *skb, u16 vlan_tag) { struct i40e_q_vector *q_vector = rx_ring->q_vector; - struct i40e_vsi *vsi = rx_ring->vsi; - u64 flags = vsi->back->flags; if (vlan_tag & VLAN_VID_MASK) __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); - if (flags & I40E_FLAG_IN_NETPOLL) - netif_rx(skb); - else - napi_gro_receive(&q_vector->napi, skb); + napi_gro_receive(&q_vector->napi, skb); } /** diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index 6f427113d621..c74f614fef77 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -211,7 +211,6 @@ struct i40evf_adapter { #define I40EVF_FLAG_RX_1BUF_CAPABLE BIT(1) #define I40EVF_FLAG_RX_PS_CAPABLE BIT(2) #define I40EVF_FLAG_RX_PS_ENABLED BIT(3) -#define I40EVF_FLAG_IN_NETPOLL BIT(4) #define I40EVF_FLAG_IMIR_ENABLED BIT(5) #define I40EVF_FLAG_MQ_CAPABLE BIT(6) #define I40EVF_FLAG_NEED_LINK_UPDATE BIT(7) @@ -224,7 +223,6 @@ struct i40evf_adapter { /* duplicates for common code */ #define I40E_FLAG_FDIR_ATR_ENABLED 0 #define I40E_FLAG_DCB_ENABLED 0 -#define I40E_FLAG_IN_NETPOLL I40EVF_FLAG_IN_NETPOLL #define I40E_FLAG_RX_CSUM_ENABLED I40EVF_FLAG_RX_CSUM_ENABLED #define I40E_FLAG_WB_ON_ITR_CAPABLE I40EVF_FLAG_WB_ON_ITR_CAPABLE #define I40E_FLAG_OUTER_UDP_CSUM_CAPABLE I40EVF_FLAG_OUTER_UDP_CSUM_CAPABLE -- cgit v1.2.3 From 7709b4c1fff39972b6a1b6183b593c43f1a555fb Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 24 Sep 2015 09:04:38 -0700 Subject: i40evf: Add support for netpoll Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 429a46c2a2f7..139801f6b5e9 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -444,6 +444,29 @@ out: return err; } +#ifdef CONFIG_NET_POLL_CONTROLLER +/** + * i40evf_netpoll - A Polling 'interrupt' handler + * @netdev: network interface device structure + * + * This is used by netconsole to send skbs without having to re-enable + * interrupts. It's not called while the normal interrupt routine is executing. + **/ +static void i40evf_netpoll(struct net_device *netdev) +{ + struct i40evf_adapter *adapter = netdev_priv(netdev); + int q_vectors = adapter->num_msix_vectors - NONQ_VECS; + int i; + + /* if interface is down do nothing */ + if (test_bit(__I40E_DOWN, &adapter->vsi.state)) + return; + + for (i = 0; i < q_vectors; i++) + i40evf_msix_clean_rings(0, adapter->q_vector[i]); +} + +#endif /** * i40evf_request_traffic_irqs - Initialize MSI-X interrupts * @adapter: board private structure @@ -2049,6 +2072,9 @@ static const struct net_device_ops i40evf_netdev_ops = { .ndo_tx_timeout = i40evf_tx_timeout, .ndo_vlan_rx_add_vid = i40evf_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = i40evf_vlan_rx_kill_vid, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = i40evf_netpoll, +#endif }; /** -- cgit v1.2.3 From 32b3e08fff60494cd1d281a39b51583edfd2b18f Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 24 Sep 2015 16:35:47 -0700 Subject: drivers/net/intel: use napi_complete_done() As per Eric Dumazet's previous patches: (see commit (24d2e4a50737) - tg3: use napi_complete_done()) Quoting verbatim: Using napi_complete_done() instead of napi_complete() allows us to use /sys/class/net/ethX/gro_flush_timeout GRO layer can aggregate more packets if the flush is delayed a bit, without having to set too big coalescing parameters that impact latencies. Tested configuration: low latency via ethtool -C ethx adaptive-rx off rx-usecs 10 adaptive-tx off tx-usecs 15 workload: streaming rx using netperf TCP_MAERTS igb: MIGRATED TCP MAERTS TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 10.0.0.1 () port 0 AF_INET : demo ... Interim result: 941.48 10^6bits/s over 1.000 seconds ending at 1440193171.589 Alignment Offset Bytes Bytes Recvs Bytes Sends Local Remote Local Remote Xfered Per Per Recv Send Recv Send Recv (avg) Send (avg) 8 8 0 0 1176930056 1475.36 797726 16384.00 71905 MIGRATED TCP MAERTS TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 10.0.0.1 () port 0 AF_INET : demo ... Interim result: 941.49 10^6bits/s over 0.997 seconds ending at 1440193142.763 Alignment Offset Bytes Bytes Recvs Bytes Sends Local Remote Local Remote Xfered Per Per Recv Send Recv Send Recv (avg) Send (avg) 8 8 0 0 1175182320 50476.00 23282 16384.00 71816 i40e: Hard to test because the traffic is incoming so fast (24Gb/s) that GRO always receives 87kB, even at the highest interrupt rate. Other drivers were only compile tested. Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/e1000/e1000_main.c | 2 +- drivers/net/ethernet/intel/e1000e/netdev.c | 2 +- drivers/net/ethernet/intel/fm10k/fm10k_main.c | 21 ++++++++++++--------- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 8 ++++++-- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 8 ++++++-- drivers/net/ethernet/intel/igb/igb_main.c | 17 +++++++++++------ drivers/net/ethernet/intel/igbvf/netdev.c | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 14 +++++++++----- drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 14 ++++++++------ 9 files changed, 55 insertions(+), 33 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 74dc15055971..fd7be860c201 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -3820,7 +3820,7 @@ static int e1000_clean(struct napi_struct *napi, int budget) if (work_done < budget) { if (likely(adapter->itr_setting & 3)) e1000_set_itr(adapter); - napi_complete(napi); + napi_complete_done(napi, work_done); if (!test_bit(__E1000_DOWN, &adapter->flags)) e1000_irq_enable(adapter); } diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 2e2ddec04a50..0a854a47d31a 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -2693,7 +2693,7 @@ static int e1000e_poll(struct napi_struct *napi, int weight) if (work_done < weight) { if (adapter->itr_setting & 3) e1000_set_itr(adapter); - napi_complete(napi); + napi_complete_done(napi, work_done); if (!test_bit(__E1000_DOWN, &adapter->state)) { if (adapter->msix_entries) ew32(IMS, adapter->rx_ring->ims_val); diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c index 537d81a6d738..e76a44cf330c 100644 --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c @@ -593,9 +593,9 @@ static void fm10k_receive_skb(struct fm10k_q_vector *q_vector, napi_gro_receive(&q_vector->napi, skb); } -static bool fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector, - struct fm10k_ring *rx_ring, - int budget) +static int fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector, + struct fm10k_ring *rx_ring, + int budget) { struct sk_buff *skb = rx_ring->skb; unsigned int total_bytes = 0, total_packets = 0; @@ -662,7 +662,7 @@ static bool fm10k_clean_rx_irq(struct fm10k_q_vector *q_vector, q_vector->rx.total_packets += total_packets; q_vector->rx.total_bytes += total_bytes; - return total_packets < budget; + return total_packets; } #define VXLAN_HLEN (sizeof(struct udphdr) + 8) @@ -1422,7 +1422,7 @@ static int fm10k_poll(struct napi_struct *napi, int budget) struct fm10k_q_vector *q_vector = container_of(napi, struct fm10k_q_vector, napi); struct fm10k_ring *ring; - int per_ring_budget; + int per_ring_budget, work_done = 0; bool clean_complete = true; fm10k_for_each_ring(ring, q_vector->tx) @@ -1436,16 +1436,19 @@ static int fm10k_poll(struct napi_struct *napi, int budget) else per_ring_budget = budget; - fm10k_for_each_ring(ring, q_vector->rx) - clean_complete &= fm10k_clean_rx_irq(q_vector, ring, - per_ring_budget); + fm10k_for_each_ring(ring, q_vector->rx) { + int work = fm10k_clean_rx_irq(q_vector, ring, per_ring_budget); + + work_done += work; + clean_complete &= !!(work < per_ring_budget); + } /* If all work not completed, return budget and keep polling */ if (!clean_complete) return budget; /* all work done, exit the polling mode */ - napi_complete(napi); + napi_complete_done(napi, work_done); /* re-enable the q_vector */ fm10k_qv_enable(q_vector); diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index e1fac3b1e088..512707c2898e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1825,7 +1825,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) bool clean_complete = true; bool arm_wb = false; int budget_per_ring; - int cleaned; + int work_done = 0; if (test_bit(__I40E_DOWN, &vsi->state)) { napi_complete(napi); @@ -1851,10 +1851,14 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) budget_per_ring = max(budget/q_vector->num_ringpairs, 1); i40e_for_each_ring(ring, q_vector->rx) { + int cleaned; + if (ring_is_ps_enabled(ring)) cleaned = i40e_clean_rx_irq_ps(ring, budget_per_ring); else cleaned = i40e_clean_rx_irq_1buf(ring, budget_per_ring); + + work_done += cleaned; /* if we didn't clean as many as budgeted, we must be done */ clean_complete &= (budget_per_ring != cleaned); } @@ -1871,7 +1875,7 @@ tx_only: q_vector->arm_wb_state = false; /* Work is done so exit the polling mode and re-enable the interrupt */ - napi_complete(napi); + napi_complete_done(napi, work_done); if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) { i40e_update_enable_itr(vsi, q_vector); } else { /* Legacy mode */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 5d3a8bd91abf..97493a4164eb 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -1266,7 +1266,7 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget) bool clean_complete = true; bool arm_wb = false; int budget_per_ring; - int cleaned; + int work_done = 0; if (test_bit(__I40E_DOWN, &vsi->state)) { napi_complete(napi); @@ -1292,10 +1292,14 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget) budget_per_ring = max(budget/q_vector->num_ringpairs, 1); i40e_for_each_ring(ring, q_vector->rx) { + int cleaned; + if (ring_is_ps_enabled(ring)) cleaned = i40e_clean_rx_irq_ps(ring, budget_per_ring); else cleaned = i40e_clean_rx_irq_1buf(ring, budget_per_ring); + + work_done += cleaned; /* if we didn't clean as many as budgeted, we must be done */ clean_complete &= (budget_per_ring != cleaned); } @@ -1312,7 +1316,7 @@ tx_only: q_vector->arm_wb_state = false; /* Work is done so exit the polling mode and re-enable the interrupt */ - napi_complete(napi); + napi_complete_done(napi, work_done); i40e_update_enable_itr(vsi, q_vector); return 0; } diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 7e6267503790..ea7b09887245 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -151,7 +151,7 @@ static void igb_setup_dca(struct igb_adapter *); #endif /* CONFIG_IGB_DCA */ static int igb_poll(struct napi_struct *, int); static bool igb_clean_tx_irq(struct igb_q_vector *); -static bool igb_clean_rx_irq(struct igb_q_vector *, int); +static int igb_clean_rx_irq(struct igb_q_vector *, int); static int igb_ioctl(struct net_device *, struct ifreq *, int cmd); static void igb_tx_timeout(struct net_device *); static void igb_reset_task(struct work_struct *); @@ -6364,6 +6364,7 @@ static int igb_poll(struct napi_struct *napi, int budget) struct igb_q_vector, napi); bool clean_complete = true; + int work_done = 0; #ifdef CONFIG_IGB_DCA if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED) @@ -6372,15 +6373,19 @@ static int igb_poll(struct napi_struct *napi, int budget) if (q_vector->tx.ring) clean_complete = igb_clean_tx_irq(q_vector); - if (q_vector->rx.ring) - clean_complete &= igb_clean_rx_irq(q_vector, budget); + if (q_vector->rx.ring) { + int cleaned = igb_clean_rx_irq(q_vector, budget); + + work_done += cleaned; + clean_complete &= (cleaned < budget); + } /* If all work not completed, return budget and keep polling */ if (!clean_complete) return budget; /* If not enough Rx work done, exit the polling mode */ - napi_complete(napi); + napi_complete_done(napi, work_done); igb_ring_irq_enable(q_vector); return 0; @@ -6904,7 +6909,7 @@ static void igb_process_skb_fields(struct igb_ring *rx_ring, skb->protocol = eth_type_trans(skb, rx_ring->netdev); } -static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) +static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) { struct igb_ring *rx_ring = q_vector->rx.ring; struct sk_buff *skb = rx_ring->skb; @@ -6978,7 +6983,7 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget) if (cleaned_count) igb_alloc_rx_buffers(rx_ring, cleaned_count); - return total_packets < budget; + return total_packets; } static bool igb_alloc_mapped_page(struct igb_ring *rx_ring, diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index e86d41ed9260..297af801f051 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -1211,7 +1211,7 @@ static int igbvf_poll(struct napi_struct *napi, int budget) /* If not enough Rx work done, exit the polling mode */ if (work_done < budget) { - napi_complete(napi); + napi_complete_done(napi, work_done); if (adapter->requested_itr & 3) igbvf_set_itr(adapter); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 1b2ad39bbfb5..9f8a7fd7a195 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2775,7 +2775,7 @@ int ixgbe_poll(struct napi_struct *napi, int budget) container_of(napi, struct ixgbe_q_vector, napi); struct ixgbe_adapter *adapter = q_vector->adapter; struct ixgbe_ring *ring; - int per_ring_budget; + int per_ring_budget, work_done = 0; bool clean_complete = true; #ifdef CONFIG_IXGBE_DCA @@ -2796,9 +2796,13 @@ int ixgbe_poll(struct napi_struct *napi, int budget) else per_ring_budget = budget; - ixgbe_for_each_ring(ring, q_vector->rx) - clean_complete &= (ixgbe_clean_rx_irq(q_vector, ring, - per_ring_budget) < per_ring_budget); + ixgbe_for_each_ring(ring, q_vector->rx) { + int cleaned = ixgbe_clean_rx_irq(q_vector, ring, + per_ring_budget); + + work_done += cleaned; + clean_complete &= (cleaned < per_ring_budget); + } ixgbe_qv_unlock_napi(q_vector); /* If all work not completed, return budget and keep polling */ @@ -2806,7 +2810,7 @@ int ixgbe_poll(struct napi_struct *napi, int budget) return budget; /* all work done, exit the polling mode */ - napi_complete(napi); + napi_complete_done(napi, work_done); if (adapter->rx_itr_setting & 1) ixgbe_set_itr(q_vector); if (!test_bit(__IXGBE_DOWN, &adapter->state)) diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 35da2d74e73e..7570b5c7ccd8 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -1008,7 +1008,7 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget) container_of(napi, struct ixgbevf_q_vector, napi); struct ixgbevf_adapter *adapter = q_vector->adapter; struct ixgbevf_ring *ring; - int per_ring_budget; + int per_ring_budget, work_done = 0; bool clean_complete = true; ixgbevf_for_each_ring(ring, q_vector->tx) @@ -1027,10 +1027,12 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget) else per_ring_budget = budget; - ixgbevf_for_each_ring(ring, q_vector->rx) - clean_complete &= (ixgbevf_clean_rx_irq(q_vector, ring, - per_ring_budget) - < per_ring_budget); + ixgbevf_for_each_ring(ring, q_vector->rx) { + int cleaned = ixgbevf_clean_rx_irq(q_vector, ring, + per_ring_budget); + work_done += cleaned; + clean_complete &= (cleaned < per_ring_budget); + } #ifdef CONFIG_NET_RX_BUSY_POLL ixgbevf_qv_unlock_napi(q_vector); @@ -1040,7 +1042,7 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget) if (!clean_complete) return budget; /* all work done, exit the polling mode */ - napi_complete(napi); + napi_complete_done(napi, work_done); if (adapter->rx_itr_setting & 1) ixgbevf_set_itr(q_vector); if (!test_bit(__IXGBEVF_DOWN, &adapter->state) && -- cgit v1.2.3 From 6dec101765e442fc7f46205acdb2cf3b88879f16 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Mon, 28 Sep 2015 14:12:30 -0400 Subject: i40e: generate fewer startup messages Cut down on the number of startup log entries by putting a couple behind debug flags and combining a couple others into a single line. Change-ID: I708089f086308f84d43f8b6f0e8a634a02d058fb Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 20 ++++++++++++-------- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 4 ++-- 4 files changed, 17 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 91f8cbffa6a8..7aaead358b8c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -582,10 +582,10 @@ struct i40e_device { }; /** - * i40e_fw_version_str - format the FW and NVM version strings + * i40e_nvm_version_str - format the NVM version strings * @hw: ptr to the hardware info **/ -static inline char *i40e_fw_version_str(struct i40e_hw *hw) +static inline char *i40e_nvm_version_str(struct i40e_hw *hw) { static char buf[32]; diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index e7fd84c5b9f3..e994f4a13be1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1122,7 +1122,7 @@ static void i40e_get_drvinfo(struct net_device *netdev, strlcpy(drvinfo->driver, i40e_driver_name, sizeof(drvinfo->driver)); strlcpy(drvinfo->version, i40e_driver_version_str, sizeof(drvinfo->version)); - strlcpy(drvinfo->fw_version, i40e_fw_version_str(&pf->hw), + strlcpy(drvinfo->fw_version, i40e_nvm_version_str(&pf->hw), sizeof(drvinfo->fw_version)); strlcpy(drvinfo->bus_info, pci_name(pf->pdev), sizeof(drvinfo->bus_info)); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 389f110ee734..d7310955bcc8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6218,8 +6218,9 @@ static void i40e_config_bridge_mode(struct i40e_veb *veb) { struct i40e_pf *pf = veb->pf; - dev_info(&pf->pdev->dev, "enabling bridge mode: %s\n", - veb->bridge_mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB"); + if (pf->hw.debug_mask & I40E_DEBUG_LAN) + dev_info(&pf->pdev->dev, "enabling bridge mode: %s\n", + veb->bridge_mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB"); if (veb->bridge_mode & BRIDGE_MODE_VEPA) i40e_disable_pf_switch_lb(pf); else @@ -9923,6 +9924,10 @@ static void i40e_print_features(struct i40e_pf *pf) if (pf->flags & I40E_FLAG_FCOE_ENABLED) buf += sprintf(buf, "FCOE "); #endif + if (pf->flags & I40E_FLAG_VEB_MODE_ENABLED) + buf += sprintf(buf, "VEB "); + else + buf += sprintf(buf, "VEPA "); BUG_ON(buf > (string + INFO_STRING_LEN)); dev_info(&pf->pdev->dev, "%s\n", string); @@ -10062,13 +10067,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pf->hw.fc.requested_mode = I40E_FC_NONE; err = i40e_init_adminq(hw); - dev_info(&pdev->dev, "%s\n", i40e_fw_version_str(hw)); - /* provide additional fw info, like api and ver */ - dev_info(&pdev->dev, "fw_version:%d.%d.%05d\n", - hw->aq.fw_maj_ver, hw->aq.fw_min_ver, hw->aq.fw_build); - dev_info(&pdev->dev, "fw api version:%d.%d\n", - hw->aq.api_maj_ver, hw->aq.api_min_ver); + /* provide nvm, fw, api versions */ + dev_info(&pdev->dev, "fw %d.%d.%05d api %d.%d nvm %s\n", + hw->aq.fw_maj_ver, hw->aq.fw_min_ver, hw->aq.fw_build, + hw->aq.api_maj_ver, hw->aq.api_min_ver, + i40e_nvm_version_str(hw)); if (err) { dev_info(&pdev->dev, diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index 552c84e2e05d..565ca7c835bc 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -674,8 +674,8 @@ void i40e_ptp_init(struct i40e_pf *pf) struct timespec64 ts; u32 regval; - dev_info(&pf->pdev->dev, "%s: added PHC on %s\n", __func__, - netdev->name); + if (pf->hw.debug_mask & I40E_DEBUG_LAN) + dev_info(&pf->pdev->dev, "PHC enabled\n"); pf->flags |= I40E_FLAG_PTP; /* Ensure the clocks are running. */ -- cgit v1.2.3 From 4e68adfeb91d684e5c7a0c6305af872120c71f23 Mon Sep 17 00:00:00 2001 From: Jingjing Wu Date: Mon, 28 Sep 2015 14:12:31 -0400 Subject: i40e/i40evf: Fix compile issue related to const string Add const to functions that return strings that aren't going to be modified. This addresses some reported compile complaints. Change-ID: Ic56b1e814ab4d23a50480e7fdec652445f776ee8 Signed-off-by: Jingjing Wu Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 4 ++-- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_prototype.h | 4 ++-- drivers/net/ethernet/intel/i40evf/i40e_common.c | 4 ++-- drivers/net/ethernet/intel/i40evf/i40e_prototype.h | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index d1ee1745473d..daa6b177fdb7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -87,7 +87,7 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw) * @hw: pointer to the HW structure * @aq_err: the AQ error code to convert **/ -char *i40e_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err) +const char *i40e_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err) { switch (aq_err) { case I40E_AQ_RC_OK: @@ -147,7 +147,7 @@ char *i40e_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err) * @hw: pointer to the HW structure * @stat_err: the status error code to convert **/ -char *i40e_stat_str(struct i40e_hw *hw, i40e_status stat_err) +const char *i40e_stat_str(struct i40e_hw *hw, i40e_status stat_err) { switch (stat_err) { case 0: diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 2142e1004a2f..875a8ccc2611 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -632,7 +632,7 @@ static inline u8 i40e_nvmupd_get_transaction(u32 val) return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT); } -static char *i40e_nvm_update_state_str[] = { +static const char * const i40e_nvm_update_state_str[] = { "I40E_NVMUPD_INVALID", "I40E_NVMUPD_READ_CON", "I40E_NVMUPD_READ_SNT", diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index 4454974b27e7..10bf2ba8bc15 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -58,8 +58,8 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void i40e_idle_aq(struct i40e_hw *hw); bool i40e_check_asq_alive(struct i40e_hw *hw); i40e_status i40e_aq_queue_shutdown(struct i40e_hw *hw, bool unloading); -char *i40e_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err); -char *i40e_stat_str(struct i40e_hw *hw, i40e_status stat_err); +const char *i40e_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err); +const char *i40e_stat_str(struct i40e_hw *hw, i40e_status stat_err); i40e_status i40e_aq_get_rss_lut(struct i40e_hw *hw, u16 seid, bool pf_lut, u8 *lut, u16 lut_size); diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c index b98b642b897a..7435fb396dcd 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_common.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c @@ -87,7 +87,7 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw) * @hw: pointer to the HW structure * @aq_err: the AQ error code to convert **/ -char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err) +const char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err) { switch (aq_err) { case I40E_AQ_RC_OK: @@ -147,7 +147,7 @@ char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err) * @hw: pointer to the HW structure * @stat_err: the status error code to convert **/ -char *i40evf_stat_str(struct i40e_hw *hw, i40e_status stat_err) +const char *i40evf_stat_str(struct i40e_hw *hw, i40e_status stat_err) { switch (stat_err) { case 0: diff --git a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h index 55ae4b0f8192..8ed0edfbc125 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h @@ -60,8 +60,8 @@ void i40e_idle_aq(struct i40e_hw *hw); void i40evf_resume_aq(struct i40e_hw *hw); bool i40evf_check_asq_alive(struct i40e_hw *hw); i40e_status i40evf_aq_queue_shutdown(struct i40e_hw *hw, bool unloading); -char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err); -char *i40evf_stat_str(struct i40e_hw *hw, i40e_status stat_err); +const char *i40evf_aq_str(struct i40e_hw *hw, enum i40e_admin_queue_err aq_err); +const char *i40evf_stat_str(struct i40e_hw *hw, i40e_status stat_err); i40e_status i40evf_aq_get_rss_lut(struct i40e_hw *hw, u16 seid, bool pf_lut, u8 *lut, u16 lut_size); -- cgit v1.2.3 From 3c5c420535ab7e25a639db16f7b2b16a70e147ec Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Mon, 28 Sep 2015 14:12:32 -0400 Subject: i40e: remove read/write failed messages from nvmupdate Allow the nvmupdate application to decide when a read or write error should be exposed to the user. Since the application needs to use write probes to find the ReadOnly sections on a potentially unknown NVM version in the HW and read probes to check the status of the last write, some error messages are expected, but need not be shown to the users. The driver doesn't know which are ignorable from real errors, so needs to let the application make the decision. Change-ID: I78fca8ab672bede11c10c820b83c26adfd536d03 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index e994f4a13be1..5fe8ac07f0ec 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -993,9 +993,7 @@ static int i40e_get_eeprom(struct net_device *netdev, cmd = (struct i40e_nvm_access *)eeprom; ret_val = i40e_nvmupd_command(hw, cmd, bytes, &errno); - if (ret_val && - ((hw->aq.asq_last_status != I40E_AQ_RC_EACCES) || - (hw->debug_mask & I40E_DEBUG_NVM))) + if (ret_val && (hw->debug_mask & I40E_DEBUG_NVM)) dev_info(&pf->pdev->dev, "NVMUpdate read failed err=%d status=0x%x errno=%d module=%d offset=0x%x size=%d\n", ret_val, hw->aq.asq_last_status, errno, @@ -1099,10 +1097,7 @@ static int i40e_set_eeprom(struct net_device *netdev, cmd = (struct i40e_nvm_access *)eeprom; ret_val = i40e_nvmupd_command(hw, cmd, bytes, &errno); - if (ret_val && - ((hw->aq.asq_last_status != I40E_AQ_RC_EPERM && - hw->aq.asq_last_status != I40E_AQ_RC_EBUSY) || - (hw->debug_mask & I40E_DEBUG_NVM))) + if (ret_val && (hw->debug_mask & I40E_DEBUG_NVM)) dev_info(&pf->pdev->dev, "NVMUpdate write failed err=%d status=0x%x errno=%d module=%d offset=0x%x size=%d\n", ret_val, hw->aq.asq_last_status, errno, -- cgit v1.2.3 From d9d17cf74aed93add76c9cf648ce2f73b68ce410 Mon Sep 17 00:00:00 2001 From: Greg Rose Date: Mon, 28 Sep 2015 14:12:33 -0400 Subject: i40e: Removed unused defines Two defines that are not used are causing customer confusion - remove them. Change-ID: Icef0325aca8e0f4fcdfc519e026bdd375e791200 Signed-off-by: Greg Rose Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h index 736f6f08b4f2..7fe94e84221a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h @@ -29,8 +29,6 @@ #include "i40e.h" -#define I40E_MAX_MACVLAN_FILTERS 256 -#define I40E_MAX_VLAN_FILTERS 256 #define I40E_MAX_VLANID 4095 #define I40E_VIRTCHNL_SUPPORTED_QTYPES 2 -- cgit v1.2.3 From 1cdfd88f2de89cbfffb5813dc92b7e711920c731 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Mon, 28 Sep 2015 14:12:34 -0400 Subject: i40e: priv flag for controlling VEB stats Add an ethtool priv flag to enable and disable printing the VEB statistics. Change-ID: I7654054a3a73b08aa8310d94ee8fce6219107dd8 Signed-off-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 8 ++++++++ 2 files changed, 9 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 7aaead358b8c..11254644911b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -103,6 +103,7 @@ #define I40E_PRIV_FLAGS_NPAR_FLAG BIT(0) #define I40E_PRIV_FLAGS_LINKPOLL_FLAG BIT(1) #define I40E_PRIV_FLAGS_FD_ATR BIT(2) +#define I40E_PRIV_FLAGS_VEB_STATS BIT(3) #define I40E_NVM_VERSION_LO_SHIFT 0 #define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 5fe8ac07f0ec..cb88e7abfe8d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -229,6 +229,7 @@ static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = { "NPAR", "LinkPolling", "flow-director-atr", + "veb-stats", }; #define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings) @@ -2670,6 +2671,8 @@ static u32 i40e_get_priv_flags(struct net_device *dev) I40E_PRIV_FLAGS_LINKPOLL_FLAG : 0; ret_flags |= pf->flags & I40E_FLAG_FD_ATR_ENABLED ? I40E_PRIV_FLAGS_FD_ATR : 0; + ret_flags |= pf->flags & I40E_FLAG_VEB_STATS_ENABLED ? + I40E_PRIV_FLAGS_VEB_STATS : 0; return ret_flags; } @@ -2701,6 +2704,11 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags) pf->auto_disable_flags |= I40E_FLAG_FD_ATR_ENABLED; } + if (flags & I40E_PRIV_FLAGS_VEB_STATS) + pf->flags |= I40E_FLAG_VEB_STATS_ENABLED; + else + pf->flags &= ~I40E_FLAG_VEB_STATS_ENABLED; + return 0; } -- cgit v1.2.3 From 947570e800e2ae3cbf827918a999aa88ee1600b0 Mon Sep 17 00:00:00 2001 From: Greg Bowers Date: Mon, 28 Sep 2015 14:12:35 -0400 Subject: i40e: Add support for non-willing Apps Adds support for setting a new bit in the Set Local LLDP MIB AQ command Type field. When set to 1, the bit indicates to FW that Apps should be treated as non-willing. When 0, FW behaves as before. Change-ID: I0d2101c1606c59c7188d3e6a0c7810e0f205233a Signed-off-by: Greg Bowers Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 7 +++++++ drivers/net/ethernet/intel/i40e/i40e_type.h | 2 ++ 2 files changed, 9 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 02d52251ee7f..6584b6cd73fd 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -2132,6 +2132,13 @@ I40E_CHECK_STRUCT_LEN(0x20, i40e_aqc_get_cee_dcb_cfg_resp); struct i40e_aqc_lldp_set_local_mib { #define SET_LOCAL_MIB_AC_TYPE_DCBX_SHIFT 0 #define SET_LOCAL_MIB_AC_TYPE_DCBX_MASK (1 << SET_LOCAL_MIB_AC_TYPE_DCBX_SHIFT) +#define SET_LOCAL_MIB_AC_TYPE_DCBX_MASK (1 << \ + SET_LOCAL_MIB_AC_TYPE_DCBX_SHIFT) +#define SET_LOCAL_MIB_AC_TYPE_LOCAL_MIB 0x0 +#define SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT (1) +#define SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_MASK (1 << \ + SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS_SHIFT) +#define SET_LOCAL_MIB_AC_TYPE_NON_WILLING_APPS 0x1 u8 type; u8 reserved0; __le16 length; diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 6f69576de59d..9c4a4573c28f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -475,6 +475,8 @@ struct i40e_dcbx_config { u8 dcbx_mode; #define I40E_DCBX_MODE_CEE 0x1 #define I40E_DCBX_MODE_IEEE 0x2 + u8 app_mode; +#define I40E_DCBX_APPS_NON_WILLING 0x1 u32 numapps; u32 tlv_status; /* CEE mode TLV status */ struct i40e_dcb_ets_config etscfg; -- cgit v1.2.3 From ac26fc136c24edee53f1719e490d896fb07cd79b Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Mon, 28 Sep 2015 14:12:37 -0400 Subject: i40e/i40evf: moderate interrupts differently The XL710 hardware has a different interrupt moderation design that can support a limit of total interrupts per second per vector, in addition to the "number of interrupts per second" controls already established in the driver. This combination of hardware features allows us to set very low default latency settings but minimize the total CPU utilization by not making too many interrupts, should the user desire. The current driver implementation is still enabling the dynamic moderation in the driver, and only using the rx/tx-usecs limit in ethtool to limit the interrupt rate per second, by default. The new code implemented in this patch 2) adds init/use of the new "Interrupt Limit" register 3) adds ethtool knob to control/report the limits above Usage is ethtool -C ethx rx-usecs-high Where is number of microseconds to create a rate of 1/N interrupts per second, regardless of rx-usecs or tx-usecs values. Since there is a credit based scheme in the hardware, the rx-usecs and tx-usecs can be configured for very low latency for short bursts, but once the credit runs out the refill rate on the credits is limited by rx-usecs-high. Change-ID: I3a1075d3296123b0f4f50623c779b027af5b188d Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 24 ++++++++++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_main.c | 10 +++++++--- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 10 ++++++++++ drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 10 ++++++++++ 5 files changed, 52 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 11254644911b..ad48f52967fe 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -498,6 +498,7 @@ struct i40e_vsi { */ u16 rx_itr_setting; u16 tx_itr_setting; + u16 int_rate_limit; /* value in usecs */ u16 rss_table_size; u16 rss_size; diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index cb88e7abfe8d..1a5006806b46 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1845,6 +1845,14 @@ static int i40e_get_coalesce(struct net_device *netdev, ec->rx_coalesce_usecs = vsi->rx_itr_setting & ~I40E_ITR_DYNAMIC; ec->tx_coalesce_usecs = vsi->tx_itr_setting & ~I40E_ITR_DYNAMIC; + /* we use the _usecs_high to store/set the interrupt rate limit + * that the hardware supports, that almost but not quite + * fits the original intent of the ethtool variable, + * the rx_coalesce_usecs_high limits total interrupts + * per second from both tx/rx sources. + */ + ec->rx_coalesce_usecs_high = vsi->int_rate_limit; + ec->tx_coalesce_usecs_high = vsi->int_rate_limit; return 0; } @@ -1863,6 +1871,17 @@ static int i40e_set_coalesce(struct net_device *netdev, if (ec->tx_max_coalesced_frames_irq || ec->rx_max_coalesced_frames_irq) vsi->work_limit = ec->tx_max_coalesced_frames_irq; + /* tx_coalesce_usecs_high is ignored, use rx-usecs-high instead */ + if (ec->tx_coalesce_usecs_high != vsi->int_rate_limit) { + netif_info(pf, drv, netdev, "tx-usecs-high is not used, please program rx-usecs-high\n"); + return -EINVAL; + } + + if (ec->rx_coalesce_usecs_high >= INTRL_REG_TO_USEC(I40E_MAX_INTRL)) { + netif_info(pf, drv, netdev, "Invalid value, rx-usecs-high range is 0-235\n"); + return -EINVAL; + } + vector = vsi->base_vector; if ((ec->rx_coalesce_usecs >= (I40E_MIN_ITR << 1)) && (ec->rx_coalesce_usecs <= (I40E_MAX_ITR << 1))) { @@ -1876,6 +1895,8 @@ static int i40e_set_coalesce(struct net_device *netdev, return -EINVAL; } + vsi->int_rate_limit = ec->rx_coalesce_usecs_high; + if ((ec->tx_coalesce_usecs >= (I40E_MIN_ITR << 1)) && (ec->tx_coalesce_usecs <= (I40E_MAX_ITR << 1))) { vsi->tx_itr_setting = ec->tx_coalesce_usecs; @@ -1900,11 +1921,14 @@ static int i40e_set_coalesce(struct net_device *netdev, vsi->tx_itr_setting &= ~I40E_ITR_DYNAMIC; for (i = 0; i < vsi->num_q_vectors; i++, vector++) { + u16 intrl = INTRL_USEC_TO_REG(vsi->int_rate_limit); + q_vector = vsi->q_vectors[i]; q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting); wr32(hw, I40E_PFINT_ITRN(0, vector - 1), q_vector->rx.itr); q_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting); wr32(hw, I40E_PFINT_ITRN(1, vector - 1), q_vector->tx.itr); + wr32(hw, I40E_PFINT_RATEN(vector - 1), intrl); i40e_flush(hw); } diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d7310955bcc8..722b0a1b33b8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2901,11 +2901,9 @@ static int i40e_vsi_configure(struct i40e_vsi *vsi) static void i40e_vsi_configure_msix(struct i40e_vsi *vsi) { struct i40e_pf *pf = vsi->back; - struct i40e_q_vector *q_vector; struct i40e_hw *hw = &pf->hw; u16 vector; int i, q; - u32 val; u32 qp; /* The interrupt indexing is offset by 1 in the PFINT_ITRn @@ -2915,7 +2913,8 @@ static void i40e_vsi_configure_msix(struct i40e_vsi *vsi) qp = vsi->base_queue; vector = vsi->base_vector; for (i = 0; i < vsi->num_q_vectors; i++, vector++) { - q_vector = vsi->q_vectors[i]; + struct i40e_q_vector *q_vector = vsi->q_vectors[i]; + q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting); q_vector->rx.latency_range = I40E_LOW_LATENCY; wr32(hw, I40E_PFINT_ITRN(I40E_RX_ITR, vector - 1), @@ -2924,10 +2923,14 @@ static void i40e_vsi_configure_msix(struct i40e_vsi *vsi) q_vector->tx.latency_range = I40E_LOW_LATENCY; wr32(hw, I40E_PFINT_ITRN(I40E_TX_ITR, vector - 1), q_vector->tx.itr); + wr32(hw, I40E_PFINT_RATEN(vector - 1), + INTRL_USEC_TO_REG(vsi->int_rate_limit)); /* Linked list for the queuepairs assigned to this vector */ wr32(hw, I40E_PFINT_LNKLSTN(vector - 1), qp); for (q = 0; q < q_vector->num_ringpairs; q++) { + u32 val; + val = I40E_QINT_RQCTL_CAUSE_ENA_MASK | (I40E_RX_ITR << I40E_QINT_RQCTL_ITR_INDX_SHIFT) | (vector << I40E_QINT_RQCTL_MSIX_INDX_SHIFT) | @@ -7040,6 +7043,7 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) vsi->idx = vsi_idx; vsi->rx_itr_setting = pf->rx_itr_default; vsi->tx_itr_setting = pf->tx_itr_default; + vsi->int_rate_limit = 0; vsi->rss_table_size = (vsi->type == I40E_VSI_MAIN) ? pf->rss_table_size : 64; vsi->netdev_registered = false; diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 75cecfa6e338..7c0ed84b296d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -35,6 +35,7 @@ #define I40E_ITR_20K 0x0019 #define I40E_ITR_8K 0x003E #define I40E_ITR_4K 0x007A +#define I40E_MAX_INTRL 0x3B /* reg uses 4 usec resolution */ #define I40E_ITR_RX_DEF I40E_ITR_8K #define I40E_ITR_TX_DEF I40E_ITR_4K #define I40E_ITR_DYNAMIC 0x8000 /* use top bit as a flag */ @@ -44,6 +45,15 @@ #define ITR_TO_REG(setting) ((setting & ~I40E_ITR_DYNAMIC) >> 1) #define ITR_IS_DYNAMIC(setting) (!!(setting & I40E_ITR_DYNAMIC)) #define ITR_REG_TO_USEC(itr_reg) (itr_reg << 1) +/* 0x40 is the enable bit for interrupt rate limiting, and must be set if + * the value of the rate limit is non-zero + */ +#define INTRL_ENA BIT(6) +#define INTRL_REG_TO_USEC(intrl) ((intrl & ~INTRL_ENA) << 2) +#define INTRL_USEC_TO_REG(set) ((set) ? ((set) >> 2) | INTRL_ENA : 0) +#define I40E_INTRL_8K 125 /* 8000 ints/sec */ +#define I40E_INTRL_62K 16 /* 62500 ints/sec */ +#define I40E_INTRL_83K 12 /* 83333 ints/sec */ #define I40E_QUEUE_END_OF_LIST 0x7FF diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index 0c13ece00366..c4f5a4eb2907 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -35,6 +35,7 @@ #define I40E_ITR_20K 0x0019 #define I40E_ITR_8K 0x003E #define I40E_ITR_4K 0x007A +#define I40E_MAX_INTRL 0x3B /* reg uses 4 usec resolution */ #define I40E_ITR_RX_DEF I40E_ITR_8K #define I40E_ITR_TX_DEF I40E_ITR_4K #define I40E_ITR_DYNAMIC 0x8000 /* use top bit as a flag */ @@ -44,6 +45,15 @@ #define ITR_TO_REG(setting) ((setting & ~I40E_ITR_DYNAMIC) >> 1) #define ITR_IS_DYNAMIC(setting) (!!(setting & I40E_ITR_DYNAMIC)) #define ITR_REG_TO_USEC(itr_reg) (itr_reg << 1) +/* 0x40 is the enable bit for interrupt rate limiting, and must be set if + * the value of the rate limit is non-zero + */ +#define INTRL_ENA BIT(6) +#define INTRL_REG_TO_USEC(intrl) ((intrl & ~INTRL_ENA) << 2) +#define INTRL_USEC_TO_REG(set) ((set) ? ((set) >> 2) | INTRL_ENA : 0) +#define I40E_INTRL_8K 125 /* 8000 ints/sec */ +#define I40E_INTRL_62K 16 /* 62500 ints/sec */ +#define I40E_INTRL_83K 12 /* 83333 ints/sec */ #define I40E_QUEUE_END_OF_LIST 0x7FF -- cgit v1.2.3 From 5d38c93e7111a68fc7b9f771bf420d9e026a21de Mon Sep 17 00:00:00 2001 From: Jingjing Wu Date: Mon, 28 Sep 2015 14:12:39 -0400 Subject: i40e: reset the invalid msg counter in vf when a valid msg is received When the number of invalid messages from a VF is exceeded, the VF will be disabled, due to the invalid messages. This happens if other VF drivers (like DPDK) send a message through the driver's mailbox (aka virtchannel) interface, but the message is not supported by the i40e pf driver, such as CONFIG_PROMISCUOUS_MODE. This patch changes the num_invalid_msgs in struct i40e_vf to record the continuous invalid msgs, and it will be reset when a valid msg is received. Change-ID: Iaec42fd3dcdd281476b3518be23261dd46fc3718 Signed-off-by: Jingjing Wu Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 ++ drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index fd99cd237145..a35a204b4eeb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1102,6 +1102,8 @@ static int i40e_vc_send_msg_to_vf(struct i40e_vf *vf, u32 v_opcode, } } else { vf->num_valid_msgs++; + /* reset the invalid counter, if a valid message is received. */ + vf->num_invalid_msgs = 0; } aq_ret = i40e_aq_send_msg_to_vf(hw, abs_vf_id, v_opcode, v_retval, diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h index 7fe94e84221a..da44995def42 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h @@ -96,7 +96,8 @@ struct i40e_vf { u8 num_queue_pairs; /* num of qps assigned to VF vsis */ u64 num_mdd_events; /* num of mdd events detected */ - u64 num_invalid_msgs; /* num of malformed or invalid msgs detected */ + /* num of continuous malformed or invalid msgs detected */ + u64 num_invalid_msgs; u64 num_valid_msgs; /* num of valid msgs detected */ unsigned long vf_caps; /* vf's adv. capabilities */ -- cgit v1.2.3 From cc7e406cb967ccc84cd2141398bba24b07d68788 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Mon, 28 Sep 2015 14:12:40 -0400 Subject: i40evf: correctly populate vlan_features The vlan_features field was correctly being set to the same value as the netdev features field. However, this was being done before the features were actually being set up, leaving the vlan_features empty. Also, after a reset, vlan_features will be incorrectly assigned the previous netdev feature flags, which can contain VLAN feature bits. This makes the VLAN code angry and will cause a stack dump. To fix these issues, set up the netdev features first, then mask out the VLAN feature bits when assigning vlan_features. Change-ID: Ib0548869dc83cf6a841cb8697dd94c12359ba4d2 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 139801f6b5e9..46af35fe8f07 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2123,7 +2123,10 @@ int i40evf_process_config(struct i40evf_adapter *adapter) if (adapter->vf_res->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_VLAN) { - netdev->vlan_features = netdev->features; + netdev->vlan_features = netdev->features & + ~(NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_CTAG_FILTER); netdev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER; -- cgit v1.2.3 From 48becae60f7e461b4b204e6608dc6beebe6c8aff Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Mon, 28 Sep 2015 14:12:41 -0400 Subject: i40e: Recognize 1000Base_T_Optical phy type when link is up 1000Base_T_Optical got added to the function that figures out what is supported when link is down but not when link is up. Add it in there too so that we display the correct information. Change-ID: I85ebcdfa7c02d898c44c673b1500552a53c8042e Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 1a5006806b46..767b1db1005f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -307,6 +307,12 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) ecmd->advertising |= ADVERTISED_1000baseT_Full; break; + case I40E_PHY_TYPE_1000BASE_T_OPTICAL: + ecmd->supported = SUPPORTED_Autoneg | + SUPPORTED_1000baseT_Full; + ecmd->advertising = ADVERTISED_Autoneg | + ADVERTISED_1000baseT_Full; + break; case I40E_PHY_TYPE_100BASE_TX: ecmd->supported = SUPPORTED_Autoneg | SUPPORTED_100baseT_Full; -- cgit v1.2.3 From 3f7e5c330e19da2ac822ea1d02b744a24497e61b Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Mon, 28 Sep 2015 14:12:42 -0400 Subject: i40evf: relax and stagger init timing a bit On some devices, in some systems, in some configurations, the VFs would fail to initialize the first time you loaded the driver. To correct this, increase the delay time for the init task slightly, and wait longer before giving up. If we enable VFs and load the VF driver in the same kernel as the PF driver, we can totally overwhelm the PF driver with AQ requests because all of the instances try to initialize at the same time. To help alleviate this, stagger the initial scheduling of the init task using the PCIe function as a multiplier. We mask off the function to only three bits so no instance has to wait too long. With these two changes, initializing 128 VFs on a single device goes from four minutes to just a few seconds. Change-ID: If3d8720c1c4e838ab36d8781d9ec295a62380936 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf.h | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index c74f614fef77..22841c619f37 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -87,7 +87,7 @@ struct i40e_vsi { #define I40EVF_MAX_RXBUFFER 16384 /* largest size for single descriptor */ #define I40EVF_MAX_AQ_BUF_SIZE 4096 #define I40EVF_AQ_LEN 32 -#define I40EVF_AQ_MAX_ERR 10 /* times to try before resetting AQ */ +#define I40EVF_AQ_MAX_ERR 20 /* times to try before resetting AQ */ #define MAXIMUM_ETHERNET_VLAN_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 46af35fe8f07..4f3d5717bdeb 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2344,7 +2344,7 @@ static void i40evf_init_task(struct work_struct *work) } return; restart: - schedule_delayed_work(&adapter->init_task, msecs_to_jiffies(20)); + schedule_delayed_work(&adapter->init_task, msecs_to_jiffies(30)); return; err_register: @@ -2361,7 +2361,7 @@ err: adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED; return; /* do not reschedule */ } - schedule_delayed_work(&adapter->init_task, HZ / 2); + schedule_delayed_work(&adapter->init_task, HZ); } /** -- cgit v1.2.3 From 628f096d8d244f54c3595a478b6e672cdb6c04ed Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Mon, 28 Sep 2015 14:12:43 -0400 Subject: i40e: increase AQ work limit With 64 VFs, we can easily overwhelm the AQ on the PF if we have too low a limit on the number of AQ requests. This leads to ARQ overflow errors, and occasionally VFs that fail to initialize. Since we really only hit this condition on initial VF driver load, the requests that we process are lightweight, so this extra work doesn't cause problems for the PF driver. Change-ID: I620221520d8af987df6ace9ba938ffaf22107681 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index ad48f52967fe..7a58b1f9971f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -93,7 +93,7 @@ #endif /* I40E_FCOE */ #define I40E_MAX_AQ_BUF_SIZE 4096 #define I40E_AQ_LEN 256 -#define I40E_AQ_WORK_LIMIT 32 +#define I40E_AQ_WORK_LIMIT 66 /* max number of VFs + a little */ #define I40E_MAX_USER_PRIORITY 8 #define I40E_DEFAULT_MSG_ENABLE 4 #define I40E_QUEUE_WAIT_RETRY_LIMIT 10 -- cgit v1.2.3 From d1d39516e41d7ad107e807ebeee1519c412bb0e3 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Mon, 28 Sep 2015 14:12:44 -0400 Subject: i40e/i40evf: Bump i40e to 1.3.34 and i40evf to 1.3.21 Bump. Change-ID: I7ec818a507554648675b9b245ced9e6b6bd9ed4e Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 722b0a1b33b8..87a5d09cb087 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -39,7 +39,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 3 -#define DRV_VERSION_BUILD 28 +#define DRV_VERSION_BUILD 34 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 4f3d5717bdeb..4c4340cc4f45 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -34,7 +34,7 @@ char i40evf_driver_name[] = "i40evf"; static const char i40evf_driver_string[] = "Intel(R) XL710/X710 Virtual Function Network Driver"; -#define DRV_VERSION "1.3.19" +#define DRV_VERSION "1.3.21" const char i40evf_driver_version[] = DRV_VERSION; static const char i40evf_copyright[] = "Copyright (c) 2013 - 2015 Intel Corporation."; -- cgit v1.2.3 From aed1dc8231a035af3e7ef3f7ce1bd4ed2a13db31 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 12 Oct 2015 18:27:00 +0530 Subject: ath10k: export htc tx rx handlers Export HTC layer tx and rx handlers. This will be used by HIF layer for per-CE data processing. Instead of callback mechanism, HIF will call appropriate upper layers API directly. Reviewed-by: Michal Kazior Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htc.c | 8 ++++---- drivers/net/wireless/ath/ath10k/htc.h | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 32d9ff1b19dc..97c24b2d65a9 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -181,8 +181,7 @@ err_pull: return ret; } -static int ath10k_htc_tx_completion_handler(struct ath10k *ar, - struct sk_buff *skb) +int ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_htc *htc = &ar->htc; struct ath10k_skb_cb *skb_cb; @@ -199,6 +198,7 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar, return 0; } +EXPORT_SYMBOL(ath10k_htc_tx_completion_handler); /***********/ /* Receive */ @@ -304,8 +304,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc, return status; } -static int ath10k_htc_rx_completion_handler(struct ath10k *ar, - struct sk_buff *skb) +int ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb) { int status = 0; struct ath10k_htc *htc = &ar->htc; @@ -442,6 +441,7 @@ out: return status; } +EXPORT_SYMBOL(ath10k_htc_rx_completion_handler); static void ath10k_htc_control_rx_complete(struct ath10k *ar, struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index 527179c0edce..d1fc8e75efb7 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -355,5 +355,7 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid, struct sk_buff *packet); struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size); +int ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb); +int ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb); #endif -- cgit v1.2.3 From 0e5b2950912e2925b8fe1666c5aa14199c809810 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 12 Oct 2015 18:27:01 +0530 Subject: ath10k: register per copy engine send completion callbacks Register send completion callbacks for every copy engines (CE) separately instead of having common completion handler. Since some of the copy engines delivers different type of messages, per-CE callbacks help to service them differently. Reviewed-by: Michal Kazior Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 3 +-- drivers/net/wireless/ath/ath10k/ce.h | 3 ++- drivers/net/wireless/ath/ath10k/hif.h | 2 -- drivers/net/wireless/ath/ath10k/htc.c | 7 ++----- drivers/net/wireless/ath/ath10k/htc.h | 2 +- drivers/net/wireless/ath/ath10k/pci.c | 13 +++++++------ 6 files changed, 13 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 8d7ab1ccc005..ae85be8297e3 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1077,7 +1077,6 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id) int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, const struct ce_attr *attr, - void (*send_cb)(struct ath10k_ce_pipe *), void (*recv_cb)(struct ath10k_ce_pipe *)) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -1104,7 +1103,7 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, ce_state->src_sz_max = attr->src_sz_max; if (attr->src_nentries) - ce_state->send_cb = send_cb; + ce_state->send_cb = attr->send_cb; if (attr->dest_nentries) ce_state->recv_cb = recv_cb; diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 5c903e15dd65..3829e337b281 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -210,7 +210,6 @@ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id); int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, const struct ce_attr *attr, - void (*send_cb)(struct ath10k_ce_pipe *), void (*recv_cb)(struct ath10k_ce_pipe *)); void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id); @@ -277,6 +276,8 @@ struct ce_attr { /* #entries in destination ring - Must be a power of 2 */ unsigned int dest_nentries; + + void (*send_cb)(struct ath10k_ce_pipe *); }; #define SR_BA_ADDRESS 0x0000 diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index 0c92e0251e84..3808920dec80 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h @@ -31,8 +31,6 @@ struct ath10k_hif_sg_item { }; struct ath10k_hif_cb { - int (*tx_completion)(struct ath10k *ar, - struct sk_buff *wbuf); int (*rx_completion)(struct ath10k *ar, struct sk_buff *wbuf); }; diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 97c24b2d65a9..89c0e40214c0 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -181,22 +181,20 @@ err_pull: return ret; } -int ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb) +void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_htc *htc = &ar->htc; struct ath10k_skb_cb *skb_cb; struct ath10k_htc_ep *ep; if (WARN_ON_ONCE(!skb)) - return 0; + return; skb_cb = ATH10K_SKB_CB(skb); ep = &htc->endpoint[skb_cb->eid]; ath10k_htc_notify_tx_completion(ep, skb); /* the skb now belongs to the completion handler */ - - return 0; } EXPORT_SYMBOL(ath10k_htc_tx_completion_handler); @@ -851,7 +849,6 @@ int ath10k_htc_init(struct ath10k *ar) /* setup HIF layer callbacks */ htc_callbacks.rx_completion = ath10k_htc_rx_completion_handler; - htc_callbacks.tx_completion = ath10k_htc_tx_completion_handler; htc->ar = ar; /* Get HIF default pipe for HTC message exchange */ diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index d1fc8e75efb7..77b669ee71a0 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -355,7 +355,7 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid, struct sk_buff *packet); struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size); -int ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb); +void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb); int ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb); #endif diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 863117bd18ea..5425d85fd12b 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -104,6 +104,7 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, struct ath10k_ce_pipe *rx_pipe, struct bmi_xfer *xfer); static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar); +static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state); static const struct ce_attr host_ce_config_wlan[] = { /* CE0: host->target HTC control and raw streams */ @@ -112,6 +113,7 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_nentries = 16, .src_sz_max = 256, .dest_nentries = 0, + .send_cb = ath10k_pci_htc_tx_cb, }, /* CE1: target->host HTT + HTC control */ @@ -136,6 +138,7 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_nentries = 32, .src_sz_max = 2048, .dest_nentries = 0, + .send_cb = ath10k_pci_htc_tx_cb, }, /* CE4: host->target HTT */ @@ -144,6 +147,7 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_nentries = CE_HTT_H2T_MSG_SRC_NENTRIES, .src_sz_max = 256, .dest_nentries = 0, + .send_cb = ath10k_pci_htc_tx_cb, }, /* CE5: unused */ @@ -1095,11 +1099,9 @@ static int ath10k_pci_diag_write32(struct ath10k *ar, u32 address, u32 value) } /* Called by lower (CE) layer when a send to Target completes. */ -static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state) +static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state) { struct ath10k *ar = ce_state->ar; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current; struct sk_buff_head list; struct sk_buff *skb; u32 ce_data; @@ -1117,7 +1119,7 @@ static void ath10k_pci_ce_send_done(struct ath10k_ce_pipe *ce_state) } while ((skb = __skb_dequeue(&list))) - cb->tx_completion(ar, skb); + ath10k_htc_tx_completion_handler(ar, skb); } /* Called by lower (CE) layer when data is received from the Target. */ @@ -1573,7 +1575,7 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) ce_ring->per_transfer_context[i] = NULL; - ar_pci->msg_callbacks_current.tx_completion(ar, skb); + ath10k_htc_tx_completion_handler(ar, skb); } } @@ -1994,7 +1996,6 @@ static int ath10k_pci_alloc_pipes(struct ath10k *ar) pipe->hif_ce_state = ar; ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i], - ath10k_pci_ce_send_done, ath10k_pci_ce_recv_data); if (ret) { ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n", -- cgit v1.2.3 From 9d9bdbb0c4099fea202ceee14000704c63338cce Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 12 Oct 2015 18:27:02 +0530 Subject: ath10k: register per copy engine receive callbacks Register receive callbacks for every copy engines (CE) separately instead of having common receive handler. Some of the copy engines receives different type of messages (i.e HTT/HTC/pktlog) from target. Hence to service them accordingly, register per copy engine receive callbacks. Reviewed-by: Michal Kazior Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 5 ++--- drivers/net/wireless/ath/ath10k/ce.h | 4 ++-- drivers/net/wireless/ath/ath10k/hif.h | 14 -------------- drivers/net/wireless/ath/ath10k/htc.c | 13 +------------ drivers/net/wireless/ath/ath10k/htc.h | 2 +- drivers/net/wireless/ath/ath10k/pci.c | 23 ++++++----------------- drivers/net/wireless/ath/ath10k/pci.h | 2 -- 7 files changed, 12 insertions(+), 51 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index ae85be8297e3..84220c376308 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1076,8 +1076,7 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id) } int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, - const struct ce_attr *attr, - void (*recv_cb)(struct ath10k_ce_pipe *)) + const struct ce_attr *attr) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; @@ -1106,7 +1105,7 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, ce_state->send_cb = attr->send_cb; if (attr->dest_nentries) - ce_state->recv_cb = recv_cb; + ce_state->recv_cb = attr->recv_cb; if (attr->src_nentries) { ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr); diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 3829e337b281..dbb94fdb274b 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -209,8 +209,7 @@ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, const struct ce_attr *attr); void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id); int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, - const struct ce_attr *attr, - void (*recv_cb)(struct ath10k_ce_pipe *)); + const struct ce_attr *attr); void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id); /*==================CE Engine Shutdown=======================*/ @@ -278,6 +277,7 @@ struct ce_attr { unsigned int dest_nentries; void (*send_cb)(struct ath10k_ce_pipe *); + void (*recv_cb)(struct ath10k_ce_pipe *); }; #define SR_BA_ADDRESS 0x0000 diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index 3808920dec80..6e826bb7d4c2 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h @@ -30,11 +30,6 @@ struct ath10k_hif_sg_item { u16 len; }; -struct ath10k_hif_cb { - int (*rx_completion)(struct ath10k *ar, - struct sk_buff *wbuf); -}; - struct ath10k_hif_ops { /* send a scatter-gather list to the target */ int (*tx_sg)(struct ath10k *ar, u8 pipe_id, @@ -78,9 +73,6 @@ struct ath10k_hif_ops { */ void (*send_complete_check)(struct ath10k *ar, u8 pipe_id, int force); - void (*set_callbacks)(struct ath10k *ar, - struct ath10k_hif_cb *callbacks); - u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id); u32 (*read32)(struct ath10k *ar, u32 address); @@ -161,12 +153,6 @@ static inline void ath10k_hif_send_complete_check(struct ath10k *ar, ar->hif.ops->send_complete_check(ar, pipe_id, force); } -static inline void ath10k_hif_set_callbacks(struct ath10k *ar, - struct ath10k_hif_cb *callbacks) -{ - ar->hif.ops->set_callbacks(ar, callbacks); -} - static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar, u8 pipe_id) { diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 89c0e40214c0..13d011989585 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -302,7 +302,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc, return status; } -int ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb) +void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb) { int status = 0; struct ath10k_htc *htc = &ar->htc; @@ -323,7 +323,6 @@ int ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb) ath10k_warn(ar, "HTC Rx: invalid eid %d\n", eid); ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad header", "", hdr, sizeof(*hdr)); - status = -EINVAL; goto out; } @@ -345,7 +344,6 @@ int ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb) payload_len + sizeof(*hdr)); ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", "", hdr, sizeof(*hdr)); - status = -EINVAL; goto out; } @@ -355,7 +353,6 @@ int ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb) skb->len, payload_len); ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", "", hdr, sizeof(*hdr)); - status = -EINVAL; goto out; } @@ -371,7 +368,6 @@ int ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb) (trailer_len > payload_len)) { ath10k_warn(ar, "Invalid trailer length: %d\n", trailer_len); - status = -EPROTO; goto out; } @@ -404,7 +400,6 @@ int ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb) * sending unsolicited messages on the ep 0 */ ath10k_warn(ar, "HTC rx ctrl still processing\n"); - status = -EINVAL; complete(&htc->ctl_resp); goto out; } @@ -436,8 +431,6 @@ int ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb) skb = NULL; out: kfree_skb(skb); - - return status; } EXPORT_SYMBOL(ath10k_htc_rx_completion_handler); @@ -839,7 +832,6 @@ int ath10k_htc_start(struct ath10k_htc *htc) /* registered target arrival callback from the HIF layer */ int ath10k_htc_init(struct ath10k *ar) { - struct ath10k_hif_cb htc_callbacks; struct ath10k_htc_ep *ep = NULL; struct ath10k_htc *htc = &ar->htc; @@ -847,14 +839,11 @@ int ath10k_htc_init(struct ath10k *ar) ath10k_htc_reset_endpoint_states(htc); - /* setup HIF layer callbacks */ - htc_callbacks.rx_completion = ath10k_htc_rx_completion_handler; htc->ar = ar; /* Get HIF default pipe for HTC message exchange */ ep = &htc->endpoint[ATH10K_HTC_EP_0]; - ath10k_hif_set_callbacks(ar, &htc_callbacks); ath10k_hif_get_default_pipe(ar, &ep->ul_pipe_id, &ep->dl_pipe_id); init_completion(&htc->ctl_resp); diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index 77b669ee71a0..aed37082a9d6 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -356,6 +356,6 @@ int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid, struct sk_buff *packet); struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size); void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb); -int ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb); +void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb); #endif diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 5425d85fd12b..6023be7a8c0f 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -105,6 +105,7 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, struct bmi_xfer *xfer); static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar); static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state); +static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state); static const struct ce_attr host_ce_config_wlan[] = { /* CE0: host->target HTC control and raw streams */ @@ -122,6 +123,7 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_nentries = 0, .src_sz_max = 2048, .dest_nentries = 512, + .recv_cb = ath10k_pci_htc_rx_cb, }, /* CE2: target->host WMI */ @@ -130,6 +132,7 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_nentries = 0, .src_sz_max = 2048, .dest_nentries = 128, + .recv_cb = ath10k_pci_htc_rx_cb, }, /* CE3: host->target WMI */ @@ -1123,12 +1126,11 @@ static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state) } /* Called by lower (CE) layer when data is received from the Target. */ -static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state) +static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state) { struct ath10k *ar = ce_state->ar; struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id]; - struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current; struct sk_buff *skb; struct sk_buff_head list; void *transfer_context; @@ -1163,7 +1165,7 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state) ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ", skb->data, skb->len); - cb->rx_completion(ar, skb); + ath10k_htc_rx_completion_handler(ar, skb); } ath10k_pci_rx_post_pipe(pipe_info); @@ -1338,17 +1340,6 @@ static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, ath10k_ce_per_engine_service(ar, pipe); } -static void ath10k_pci_hif_set_callbacks(struct ath10k *ar, - struct ath10k_hif_cb *callbacks) -{ - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - - ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif set callbacks\n"); - - memcpy(&ar_pci->msg_callbacks_current, callbacks, - sizeof(ar_pci->msg_callbacks_current)); -} - static void ath10k_pci_kill_tasklet(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -1995,8 +1986,7 @@ static int ath10k_pci_alloc_pipes(struct ath10k *ar) pipe->pipe_num = i; pipe->hif_ce_state = ar; - ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i], - ath10k_pci_ce_recv_data); + ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]); if (ret) { ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n", i, ret); @@ -2416,7 +2406,6 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = { .map_service_to_pipe = ath10k_pci_hif_map_service_to_pipe, .get_default_pipe = ath10k_pci_hif_get_default_pipe, .send_complete_check = ath10k_pci_hif_send_complete_check, - .set_callbacks = ath10k_pci_hif_set_callbacks, .get_free_queue_number = ath10k_pci_hif_get_free_queue_number, .power_up = ath10k_pci_hif_power_up, .power_down = ath10k_pci_hif_power_down, diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 54af2d7fbe7b..87216b844133 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -175,8 +175,6 @@ struct ath10k_pci { struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX]; - struct ath10k_hif_cb msg_callbacks_current; - /* Copy Engine used for Diagnostic Accesses */ struct ath10k_ce_pipe *ce_diag; -- cgit v1.2.3 From 3f0f7ed420594cc6b7eb8b43294a8ac6815a4be5 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 12 Oct 2015 18:27:03 +0530 Subject: ath10k: export htt tx rx handlers Some special copy engines delivers messages directly to HTT by bypassing HTC layer. Hence exporting tx_completion and rx_handler for delivering the data to HTT layer. Reviewed-by: Michal Kazior Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 1 + drivers/net/wireless/ath/ath10k/htt_rx.c | 1 + drivers/net/wireless/ath/ath10k/htt_tx.c | 6 ++++++ 3 files changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index db0a99b4e9d9..2bad50e520b5 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1591,6 +1591,7 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt); int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, u8 max_subfrms_ampdu, u8 max_subfrms_amsdu); +void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb); void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc); int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb); diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 606c1a34f004..6060dda4e910 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2125,6 +2125,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) /* Free the indication buffer */ dev_kfree_skb_any(skb); } +EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler); static void ath10k_htt_txrx_compl_task(unsigned long ptr) { diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 555174756eb1..16823970dbfd 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -187,6 +187,12 @@ void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) dev_kfree_skb_any(skb); } +void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb) +{ + dev_kfree_skb_any(skb); +} +EXPORT_SYMBOL(ath10k_htt_hif_tx_complete); + int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt) { struct ath10k *ar = htt->ar; -- cgit v1.2.3 From a70587b3389ae4a97f2b51153cc86b4c1769dcf5 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 12 Oct 2015 18:27:04 +0530 Subject: ath10k: configure copy engine 5 for HTT messages Currently target to host (T2H) HTT messages are received at copy engine 1. These messages are processed by HTC layer in both host and target. To avoid HTC level processing overhead in both host and target, the unused copy engine 5 is being used for receiving HTT T2H messages. This will speedup the receive data processing as well as htt tx completion. Hence host and target copy engine configuration tables are updated to enable CE5 pipe. The in-direction HTT mapping is now pointing to CE5 for all HTT T2H. Moreover HTT send completion messages are polled from HTC handler as CE 4 is not interrupt-driven. For faster tx completion, CE4 polling needs to be done whenever CE pipe which transports HTT Rx (target->host) is processed. This avoids overhead of polling HTT messages from HTC layer. Servicing CE 4 faster is helping to solve "failed to transmit packet, dropping: -105". Reviewed-by: Michal Kazior Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 70 +++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 6023be7a8c0f..8d364e4d824f 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -106,6 +106,8 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar); static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state); static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state); +static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state); +static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state); static const struct ce_attr host_ce_config_wlan[] = { /* CE0: host->target HTC control and raw streams */ @@ -150,15 +152,16 @@ static const struct ce_attr host_ce_config_wlan[] = { .src_nentries = CE_HTT_H2T_MSG_SRC_NENTRIES, .src_sz_max = 256, .dest_nentries = 0, - .send_cb = ath10k_pci_htc_tx_cb, + .send_cb = ath10k_pci_htt_tx_cb, }, - /* CE5: unused */ + /* CE5: target->host HTT (HIF->HTT) */ { .flags = CE_ATTR_FLAGS, .src_nentries = 0, - .src_sz_max = 0, - .dest_nentries = 0, + .src_sz_max = 512, + .dest_nentries = 512, + .recv_cb = ath10k_pci_htt_rx_cb, }, /* CE6: target autonomous hif_memcpy */ @@ -264,12 +267,12 @@ static const struct ce_pipe_config target_ce_config_wlan[] = { /* NB: 50% of src nentries, since tx has 2 frags */ - /* CE5: unused */ + /* CE5: target->host HTT (HIF->HTT) */ { .pipenum = __cpu_to_le32(5), - .pipedir = __cpu_to_le32(PIPEDIR_OUT), + .pipedir = __cpu_to_le32(PIPEDIR_IN), .nentries = __cpu_to_le32(32), - .nbytes_max = __cpu_to_le32(2048), + .nbytes_max = __cpu_to_le32(512), .flags = __cpu_to_le32(CE_ATTR_FLAGS), .reserved = __cpu_to_le32(0), }, @@ -403,7 +406,7 @@ static const struct service_to_pipe target_service_to_ce_map_wlan[] = { { __cpu_to_le32(ATH10K_HTC_SVC_ID_HTT_DATA_MSG), __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ - __cpu_to_le32(1), + __cpu_to_le32(5), }, /* (Additions here) */ @@ -1125,8 +1128,9 @@ static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state) ath10k_htc_tx_completion_handler(ar, skb); } -/* Called by lower (CE) layer when data is received from the Target. */ -static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state) +static void ath10k_pci_process_rx_cb(struct ath10k_ce_pipe *ce_state, + void (*callback)(struct ath10k *ar, + struct sk_buff *skb)) { struct ath10k *ar = ce_state->ar; struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -1165,12 +1169,56 @@ static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state) ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ", skb->data, skb->len); - ath10k_htc_rx_completion_handler(ar, skb); + callback(ar, skb); } ath10k_pci_rx_post_pipe(pipe_info); } +/* Called by lower (CE) layer when data is received from the Target. */ +static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state) +{ + ath10k_pci_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler); +} + +/* Called by lower (CE) layer when a send to HTT Target completes. */ +static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state) +{ + struct ath10k *ar = ce_state->ar; + struct sk_buff *skb; + u32 ce_data; + unsigned int nbytes; + unsigned int transfer_id; + + while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data, + &nbytes, &transfer_id) == 0) { + /* no need to call tx completion for NULL pointers */ + if (!skb) + continue; + + dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr, + skb->len, DMA_TO_DEVICE); + ath10k_htt_hif_tx_complete(ar, skb); + } +} + +static void ath10k_pci_htt_rx_deliver(struct ath10k *ar, struct sk_buff *skb) +{ + skb_pull(skb, sizeof(struct ath10k_htc_hdr)); + ath10k_htt_t2h_msg_handler(ar, skb); +} + +/* Called by lower (CE) layer when HTT data is received from the Target. */ +static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state) +{ + /* CE4 polling needs to be done whenever CE pipe which transports + * HTT Rx (target->host) is processed. + */ + ath10k_ce_per_engine_service(ce_state->ar, 4); + + ath10k_pci_process_rx_cb(ce_state, ath10k_pci_htt_rx_deliver); +} + static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, struct ath10k_hif_sg_item *items, int n_items) { -- cgit v1.2.3 From 0da64f19f01a6dabc4a55c1ee9cef430fcb47f4a Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 12 Oct 2015 18:27:05 +0530 Subject: ath10k: remove unused dl_is_polled Since polling for received messages not supported, remove unused dl_is_polled. Reviewed-by: Michal Kazior Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/hif.h | 7 +++---- drivers/net/wireless/ath/ath10k/htc.c | 7 +++---- drivers/net/wireless/ath/ath10k/htc.h | 1 - drivers/net/wireless/ath/ath10k/pci.c | 11 +++-------- 4 files changed, 9 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index 6e826bb7d4c2..633594cd54fa 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h @@ -59,7 +59,7 @@ struct ath10k_hif_ops { int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id, u8 *ul_pipe, u8 *dl_pipe, - int *ul_is_polled, int *dl_is_polled); + int *ul_is_polled); void (*get_default_pipe)(struct ath10k *ar, u8 *ul_pipe, u8 *dl_pipe); @@ -133,12 +133,11 @@ static inline void ath10k_hif_stop(struct ath10k *ar) static inline int ath10k_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, u8 *ul_pipe, u8 *dl_pipe, - int *ul_is_polled, - int *dl_is_polled) + int *ul_is_polled) { return ar->hif.ops->map_service_to_pipe(ar, service_id, ul_pipe, dl_pipe, - ul_is_polled, dl_is_polled); + ul_is_polled); } static inline void ath10k_hif_get_default_pipe(struct ath10k *ar, diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 13d011989585..20e0c48f7eef 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -759,8 +759,7 @@ setup: ep->service_id, &ep->ul_pipe_id, &ep->dl_pipe_id, - &ep->ul_is_polled, - &ep->dl_is_polled); + &ep->ul_is_polled); if (status) return status; @@ -770,8 +769,8 @@ setup: ep->dl_pipe_id, ep->eid); ath10k_dbg(ar, ATH10K_DBG_BOOT, - "boot htc ep %d ul polled %d dl polled %d\n", - ep->eid, ep->ul_is_polled, ep->dl_is_polled); + "boot htc ep %d ul polled %d\n", + ep->eid, ep->ul_is_polled); if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) { ep->tx_credit_flow_enabled = false; diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index aed37082a9d6..2ddd41e75be7 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -313,7 +313,6 @@ struct ath10k_htc_ep { u8 ul_pipe_id; u8 dl_pipe_id; int ul_is_polled; /* call HIF to get tx completions */ - int dl_is_polled; /* call HIF to fetch rx (not implemented) */ u8 seq_no; /* for debugging */ int tx_credits; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 8d364e4d824f..c5875bb1b9cf 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1404,8 +1404,7 @@ static void ath10k_pci_kill_tasklet(struct ath10k *ar) static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, u8 *ul_pipe, - u8 *dl_pipe, int *ul_is_polled, - int *dl_is_polled) + u8 *dl_pipe, int *ul_is_polled) { const struct service_to_pipe *entry; bool ul_set = false, dl_set = false; @@ -1413,9 +1412,6 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif map service\n"); - /* polling for received messages not supported */ - *dl_is_polled = 0; - for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) { entry = &target_service_to_ce_map_wlan[i]; @@ -1458,7 +1454,7 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, u8 *ul_pipe, u8 *dl_pipe) { - int ul_is_polled, dl_is_polled; + int ul_is_polled; ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif get default pipe\n"); @@ -1466,8 +1462,7 @@ static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, ATH10K_HTC_SVC_ID_RSVD_CTRL, ul_pipe, dl_pipe, - &ul_is_polled, - &dl_is_polled); + &ul_is_polled); } static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) -- cgit v1.2.3 From 400143e45d39fcedb5106c3aa212746a80a61f7c Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 12 Oct 2015 18:27:06 +0530 Subject: ath10k: remove htc polling for tx completion Since polling for tx completion is handled whenever target to host messages are received, removing the unnecessary polling mechanism for send completion at HTC level. Reviewed-by: Michal Kazior Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/hif.h | 9 +++------ drivers/net/wireless/ath/ath10k/htc.c | 26 +------------------------- drivers/net/wireless/ath/ath10k/htc.h | 1 - drivers/net/wireless/ath/ath10k/pci.c | 14 +++----------- 4 files changed, 7 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index 633594cd54fa..89e7076c919f 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h @@ -58,8 +58,7 @@ struct ath10k_hif_ops { void (*stop)(struct ath10k *ar); int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id, - u8 *ul_pipe, u8 *dl_pipe, - int *ul_is_polled); + u8 *ul_pipe, u8 *dl_pipe); void (*get_default_pipe)(struct ath10k *ar, u8 *ul_pipe, u8 *dl_pipe); @@ -132,12 +131,10 @@ static inline void ath10k_hif_stop(struct ath10k *ar) static inline int ath10k_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, - u8 *ul_pipe, u8 *dl_pipe, - int *ul_is_polled) + u8 *ul_pipe, u8 *dl_pipe) { return ar->hif.ops->map_service_to_pipe(ar, service_id, - ul_pipe, dl_pipe, - ul_is_polled); + ul_pipe, dl_pipe); } static inline void ath10k_hif_get_default_pipe(struct ath10k *ar, diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 20e0c48f7eef..5b3c6bcf9598 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -23,16 +23,6 @@ /* Send */ /********/ -static inline void ath10k_htc_send_complete_check(struct ath10k_htc_ep *ep, - int force) -{ - /* - * Check whether HIF has any prior sends that have finished, - * have not had the post-processing done. - */ - ath10k_hif_send_complete_check(ep->htc->ar, ep->ul_pipe_id, force); -} - static void ath10k_htc_control_tx_complete(struct ath10k *ar, struct sk_buff *skb) { @@ -328,15 +318,6 @@ void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb) ep = &htc->endpoint[eid]; - /* - * If this endpoint that received a message from the target has - * a to-target HIF pipe whose send completions are polled rather - * than interrupt-driven, this is a good point to ask HIF to check - * whether it has any completed sends to handle. - */ - if (ep->ul_is_polled) - ath10k_htc_send_complete_check(ep, 1); - payload_len = __le16_to_cpu(hdr->len); if (payload_len + sizeof(*hdr) > ATH10K_HTC_MAX_LEN) { @@ -758,8 +739,7 @@ setup: status = ath10k_hif_map_service_to_pipe(htc->ar, ep->service_id, &ep->ul_pipe_id, - &ep->dl_pipe_id, - &ep->ul_is_polled); + &ep->dl_pipe_id); if (status) return status; @@ -768,10 +748,6 @@ setup: htc_service_name(ep->service_id), ep->ul_pipe_id, ep->dl_pipe_id, ep->eid); - ath10k_dbg(ar, ATH10K_DBG_BOOT, - "boot htc ep %d ul polled %d\n", - ep->eid, ep->ul_is_polled); - if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) { ep->tx_credit_flow_enabled = false; ath10k_dbg(ar, ATH10K_DBG_BOOT, diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index 2ddd41e75be7..e70aa38e6e05 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -312,7 +312,6 @@ struct ath10k_htc_ep { int max_ep_message_len; u8 ul_pipe_id; u8 dl_pipe_id; - int ul_is_polled; /* call HIF to get tx completions */ u8 seq_no; /* for debugging */ int tx_credits; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index c5875bb1b9cf..adcda2815b73 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1402,9 +1402,8 @@ static void ath10k_pci_kill_tasklet(struct ath10k *ar) del_timer_sync(&ar_pci->rx_post_retry); } -static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, - u16 service_id, u8 *ul_pipe, - u8 *dl_pipe, int *ul_is_polled) +static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, + u8 *ul_pipe, u8 *dl_pipe) { const struct service_to_pipe *entry; bool ul_set = false, dl_set = false; @@ -1445,24 +1444,17 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, if (WARN_ON(!ul_set || !dl_set)) return -ENOENT; - *ul_is_polled = - (host_ce_config_wlan[*ul_pipe].flags & CE_ATTR_DIS_INTR) != 0; - return 0; } static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, u8 *ul_pipe, u8 *dl_pipe) { - int ul_is_polled; - ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif get default pipe\n"); (void)ath10k_pci_hif_map_service_to_pipe(ar, ATH10K_HTC_SVC_ID_RSVD_CTRL, - ul_pipe, - dl_pipe, - &ul_is_polled); + ul_pipe, dl_pipe); } static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) -- cgit v1.2.3 From bc2055f878acb1fbbb3f3e7cb851f2e318def010 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 16 Oct 2015 14:01:23 +0200 Subject: mlxsw: Enable configuration of flooding domains As part of the introduction of L2 offloads, allow different ports to join/leave the flooding domain, according to user configuration. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 6 +++--- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 7b245af10e42..4099d4b39649 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -363,7 +363,7 @@ static inline void mlxsw_reg_sftr_pack(char *payload, unsigned int flood_table, unsigned int index, enum mlxsw_flood_table_type table_type, - unsigned int range) + unsigned int range, u8 port, bool set) { MLXSW_REG_ZERO(sftr, payload); mlxsw_reg_sftr_swid_set(payload, 0); @@ -371,8 +371,8 @@ static inline void mlxsw_reg_sftr_pack(char *payload, mlxsw_reg_sftr_index_set(payload, index); mlxsw_reg_sftr_table_type_set(payload, table_type); mlxsw_reg_sftr_range_set(payload, range); - mlxsw_reg_sftr_port_set(payload, MLXSW_PORT_CPU_PORT, 1); - mlxsw_reg_sftr_port_mask_set(payload, MLXSW_PORT_CPU_PORT, 1); + mlxsw_reg_sftr_port_set(payload, port, set); + mlxsw_reg_sftr_port_mask_set(payload, port, 1); } /* SPMLR - Switch Port MAC Learning Register diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 4f72e0a423d9..2fd2279b628e 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1377,7 +1377,8 @@ static int mlxsw_sx_flood_init(struct mlxsw_sx *mlxsw_sx) sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL); if (!sftr_pl) return -ENOMEM; - mlxsw_reg_sftr_pack(sftr_pl, 0, 0, MLXSW_REG_SFGC_TABLE_TYPE_SINGLE, 0); + mlxsw_reg_sftr_pack(sftr_pl, 0, 0, MLXSW_REG_SFGC_TABLE_TYPE_SINGLE, 0, + MLXSW_PORT_CPU_PORT, true); err = mlxsw_reg_write(mlxsw_sx->core, MLXSW_REG(sftr), sftr_pl); kfree(sftr_pl); if (err) -- cgit v1.2.3 From 453b6a8dd8338d692770bda89a52bc71c8fea2b8 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 16 Oct 2015 14:01:24 +0200 Subject: mlxsw: cmd: Introduce per-FID flooding tables In the newly introduced Spectrum switch ASIC, packets destined to not offloaded netdevs will be classified to special FIDs (vFIDs) in the device and flooded to the CPU port. The flooding table used is of type per-FID, which allows one to create different flooding domains for different vFIDs. While using a simple single-entry flood table is certainly sufficient at this point, we do plan to offload 802.1D bridges involving VLAN interfaces, thus making this change necessary. Add support for this flooding table type, by exposing the configuration of the number of tables from this type and their size. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/cmd.h | 13 +++++++++++++ drivers/net/ethernet/mellanox/mlxsw/core.h | 2 ++ drivers/net/ethernet/mellanox/mlxsw/pci.c | 4 ++++ 3 files changed, 19 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index c7889f4fa0d7..010eb5d40fe0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h @@ -674,6 +674,19 @@ MLXSW_ITEM32(cmd_mbox, config_profile, max_vid_flood_tables, 0x30, 8, 4); */ MLXSW_ITEM32(cmd_mbox, config_profile, flood_mode, 0x30, 0, 2); +/* cmd_mbox_config_profile_max_fid_flood_tables + * Maximum number of per-FID flooding tables. + * + * Note: This flooding tables cover special FIDs only (vFIDs), starting at + * FID value 4K and higher. + */ +MLXSW_ITEM32(cmd_mbox, config_profile, max_fid_flood_tables, 0x38, 24, 4); + +/* cmd_mbox_config_profile_fid_flood_table_size + * The size (number of entries) of each per-FID table. + */ +MLXSW_ITEM32(cmd_mbox, config_profile, fid_flood_table_size, 0x38, 0, 16); + /* cmd_mbox_config_profile_max_ib_mc * Maximum number of multicast FDB records for InfiniBand * FDB (in 512 chunks) per InfiniBand switch partition. diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 165808471188..8bb85ea34905 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -153,6 +153,8 @@ struct mlxsw_config_profile { u8 max_flood_tables; u8 max_vid_flood_tables; u8 flood_mode; + u8 max_fid_flood_tables; + u16 fid_flood_table_size; u16 max_ib_mc; u16 max_pkey; u8 ar_sec; diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 974ce47cec05..faa4f3f720b7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1214,6 +1214,10 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, mbox, profile->max_flood_tables); mlxsw_cmd_mbox_config_profile_max_vid_flood_tables_set( mbox, profile->max_vid_flood_tables); + mlxsw_cmd_mbox_config_profile_max_fid_flood_tables_set( + mbox, profile->max_fid_flood_tables); + mlxsw_cmd_mbox_config_profile_fid_flood_table_size_set( + mbox, profile->fid_flood_table_size); } if (profile->used_flood_mode) { mlxsw_cmd_mbox_config_profile_set_flood_mode_set( -- cgit v1.2.3 From 12fd35ab8af9fe32fce6b36881461d6f62408f70 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 16 Oct 2015 14:01:25 +0200 Subject: mlxsw: cmd: Introduce FID-offset flooding tables Packets destined to offloaded netdevs will be classified to FIDs in the device and flooded in case of BUM. The flooding table used is of type FID-offset, which allows one to create different flooding domains for different FIDs and specify the offset in the flooding table for each FID (not necessarily equal to FID or VID). Add support for this flooding table type, by exposing the configuration of the number of tables from this type and their size. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/cmd.h | 12 ++++++++++++ drivers/net/ethernet/mellanox/mlxsw/core.h | 2 ++ drivers/net/ethernet/mellanox/mlxsw/pci.c | 4 ++++ 3 files changed, 18 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index 010eb5d40fe0..cd63b8263688 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h @@ -674,6 +674,18 @@ MLXSW_ITEM32(cmd_mbox, config_profile, max_vid_flood_tables, 0x30, 8, 4); */ MLXSW_ITEM32(cmd_mbox, config_profile, flood_mode, 0x30, 0, 2); +/* cmd_mbox_config_profile_max_fid_offset_flood_tables + * Maximum number of FID-offset flooding tables. + */ +MLXSW_ITEM32(cmd_mbox, config_profile, + max_fid_offset_flood_tables, 0x34, 24, 4); + +/* cmd_mbox_config_profile_fid_offset_flood_table_size + * The size (number of entries) of each FID-offset flood table. + */ +MLXSW_ITEM32(cmd_mbox, config_profile, + fid_offset_flood_table_size, 0x34, 0, 16); + /* cmd_mbox_config_profile_max_fid_flood_tables * Maximum number of per-FID flooding tables. * diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 8bb85ea34905..e92ab272d9fb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -153,6 +153,8 @@ struct mlxsw_config_profile { u8 max_flood_tables; u8 max_vid_flood_tables; u8 flood_mode; + u8 max_fid_offset_flood_tables; + u16 fid_offset_flood_table_size; u8 max_fid_flood_tables; u16 fid_flood_table_size; u16 max_ib_mc; diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index faa4f3f720b7..0fa44c8e7102 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1214,6 +1214,10 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, mbox, profile->max_flood_tables); mlxsw_cmd_mbox_config_profile_max_vid_flood_tables_set( mbox, profile->max_vid_flood_tables); + mlxsw_cmd_mbox_config_profile_max_fid_offset_flood_tables_set( + mbox, profile->max_fid_offset_flood_tables); + mlxsw_cmd_mbox_config_profile_fid_offset_flood_table_size_set( + mbox, profile->fid_offset_flood_table_size); mlxsw_cmd_mbox_config_profile_max_fid_flood_tables_set( mbox, profile->max_fid_flood_tables); mlxsw_cmd_mbox_config_profile_fid_flood_table_size_set( -- cgit v1.2.3 From 7b0989b5bcac950c05d72dee5f6dcad38d355b3f Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 16 Oct 2015 14:01:26 +0200 Subject: mlxsw: item: Make src arg of memcpy_to helper const Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/item.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/item.h b/drivers/net/ethernet/mellanox/mlxsw/item.h index ffd55d030ce2..5a5e737d52bf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/item.h +++ b/drivers/net/ethernet/mellanox/mlxsw/item.h @@ -176,7 +176,7 @@ static inline void __mlxsw_item_memcpy_from(char *buf, char *dst, memcpy(dst, &buf[item->offset], item->size.bytes); } -static inline void __mlxsw_item_memcpy_to(char *buf, char *src, +static inline void __mlxsw_item_memcpy_to(char *buf, const char *src, struct mlxsw_item *item) { memcpy(&buf[item->offset], src, item->size.bytes); @@ -374,7 +374,7 @@ mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf, char *dst) \ __mlxsw_item_memcpy_from(buf, dst, &__ITEM_NAME(_type, _cname, _iname));\ } \ static inline void \ -mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf, char *src) \ +mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf, const char *src) \ { \ __mlxsw_item_memcpy_to(buf, src, &__ITEM_NAME(_type, _cname, _iname)); \ } -- cgit v1.2.3 From d64b1592535e390cdc0605a5b8d4b6665be47003 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 16 Oct 2015 14:01:27 +0200 Subject: mlxsw: item: Add MLXSW_ITEM_BUF_INDEXED helper Add missing item helper which allows to access char bufs on multiple offsets. This is needed by SFD and SFN register definitions. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/item.h | 46 ++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/item.h b/drivers/net/ethernet/mellanox/mlxsw/item.h index 5a5e737d52bf..1c5e43eb9b4f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/item.h +++ b/drivers/net/ethernet/mellanox/mlxsw/item.h @@ -171,15 +171,21 @@ static inline void __mlxsw_item_set64(char *buf, struct mlxsw_item *item, } static inline void __mlxsw_item_memcpy_from(char *buf, char *dst, - struct mlxsw_item *item) + struct mlxsw_item *item, + unsigned short index) { - memcpy(dst, &buf[item->offset], item->size.bytes); + unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char)); + + memcpy(dst, &buf[offset], item->size.bytes); } static inline void __mlxsw_item_memcpy_to(char *buf, const char *src, - struct mlxsw_item *item) + struct mlxsw_item *item, + unsigned short index) { - memcpy(&buf[item->offset], src, item->size.bytes); + unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char)); + + memcpy(&buf[offset], src, item->size.bytes); } static inline u16 @@ -371,12 +377,40 @@ static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \ static inline void \ mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf, char *dst) \ { \ - __mlxsw_item_memcpy_from(buf, dst, &__ITEM_NAME(_type, _cname, _iname));\ + __mlxsw_item_memcpy_from(buf, dst, \ + &__ITEM_NAME(_type, _cname, _iname), 0); \ } \ static inline void \ mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf, const char *src) \ { \ - __mlxsw_item_memcpy_to(buf, src, &__ITEM_NAME(_type, _cname, _iname)); \ + __mlxsw_item_memcpy_to(buf, src, \ + &__ITEM_NAME(_type, _cname, _iname), 0); \ +} + +#define MLXSW_ITEM_BUF_INDEXED(_type, _cname, _iname, _offset, _sizebytes, \ + _step, _instepoffset) \ +static struct mlxsw_item __ITEM_NAME(_type, _cname, _iname) = { \ + .offset = _offset, \ + .step = _step, \ + .in_step_offset = _instepoffset, \ + .size = {.bytes = _sizebytes,}, \ + .name = #_type "_" #_cname "_" #_iname, \ +}; \ +static inline void \ +mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf, \ + unsigned short index, \ + char *dst) \ +{ \ + __mlxsw_item_memcpy_from(buf, dst, \ + &__ITEM_NAME(_type, _cname, _iname), index); \ +} \ +static inline void \ +mlxsw_##_type##_##_cname##_##_iname##_memcpy_to(char *buf, \ + unsigned short index, \ + const char *src) \ +{ \ + __mlxsw_item_memcpy_to(buf, src, \ + &__ITEM_NAME(_type, _cname, _iname), index); \ } #define MLXSW_ITEM_BIT_ARRAY(_type, _cname, _iname, _offset, _sizebytes, \ -- cgit v1.2.3 From 236033b33c09ea9e34ce320d5cf9ef527077d7d5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 16 Oct 2015 14:01:28 +0200 Subject: mlxsw: reg: Add Switch Filtering Database register definition Add the SFD register which is responsible for filtering database manipulation, including static and dynamic FDB entries. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 216 ++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 4099d4b39649..c0cc5f102189 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -157,6 +157,220 @@ static inline void mlxsw_reg_sspr_pack(char *payload, u8 local_port) mlxsw_reg_sspr_system_port_set(payload, local_port); } +/* SFD - Switch Filtering Database + * ------------------------------- + * The following register defines the access to the filtering database. + * The register supports querying, adding, removing and modifying the database. + * The access is optimized for bulk updates in which case more than one + * FDB record is present in the same command. + */ +#define MLXSW_REG_SFD_ID 0x200A +#define MLXSW_REG_SFD_BASE_LEN 0x10 /* base length, without records */ +#define MLXSW_REG_SFD_REC_LEN 0x10 /* record length */ +#define MLXSW_REG_SFD_REC_MAX_COUNT 64 +#define MLXSW_REG_SFD_LEN (MLXSW_REG_SFD_BASE_LEN + \ + MLXSW_REG_SFD_REC_LEN * MLXSW_REG_SFD_REC_MAX_COUNT) + +static const struct mlxsw_reg_info mlxsw_reg_sfd = { + .id = MLXSW_REG_SFD_ID, + .len = MLXSW_REG_SFD_LEN, +}; + +/* reg_sfd_swid + * Switch partition ID for queries. Reserved on Write. + * Access: Index + */ +MLXSW_ITEM32(reg, sfd, swid, 0x00, 24, 8); + +enum mlxsw_reg_sfd_op { + /* Dump entire FDB a (process according to record_locator) */ + MLXSW_REG_SFD_OP_QUERY_DUMP = 0, + /* Query records by {MAC, VID/FID} value */ + MLXSW_REG_SFD_OP_QUERY_QUERY = 1, + /* Query and clear activity. Query records by {MAC, VID/FID} value */ + MLXSW_REG_SFD_OP_QUERY_QUERY_AND_CLEAR_ACTIVITY = 2, + /* Test. Response indicates if each of the records could be + * added to the FDB. + */ + MLXSW_REG_SFD_OP_WRITE_TEST = 0, + /* Add/modify. Aged-out records cannot be added. This command removes + * the learning notification of the {MAC, VID/FID}. Response includes + * the entries that were added to the FDB. + */ + MLXSW_REG_SFD_OP_WRITE_EDIT = 1, + /* Remove record by {MAC, VID/FID}. This command also removes + * the learning notification and aged-out notifications + * of the {MAC, VID/FID}. The response provides current (pre-removal) + * entries as non-aged-out. + */ + MLXSW_REG_SFD_OP_WRITE_REMOVE = 2, + /* Remove learned notification by {MAC, VID/FID}. The response provides + * the removed learning notification. + */ + MLXSW_REG_SFD_OP_WRITE_REMOVE_NOTIFICATION = 2, +}; + +/* reg_sfd_op + * Operation. + * Access: OP + */ +MLXSW_ITEM32(reg, sfd, op, 0x04, 30, 2); + +/* reg_sfd_record_locator + * Used for querying the FDB. Use record_locator=0 to initiate the + * query. When a record is returned, a new record_locator is + * returned to be used in the subsequent query. + * Reserved for database update. + * Access: Index + */ +MLXSW_ITEM32(reg, sfd, record_locator, 0x04, 0, 30); + +/* reg_sfd_num_rec + * Request: Number of records to read/add/modify/remove + * Response: Number of records read/added/replaced/removed + * See above description for more details. + * Ranges 0..64 + * Access: RW + */ +MLXSW_ITEM32(reg, sfd, num_rec, 0x08, 0, 8); + +static inline void mlxsw_reg_sfd_pack(char *payload, enum mlxsw_reg_sfd_op op, + u32 record_locator) +{ + MLXSW_REG_ZERO(sfd, payload); + mlxsw_reg_sfd_op_set(payload, op); + mlxsw_reg_sfd_record_locator_set(payload, record_locator); +} + +/* reg_sfd_rec_swid + * Switch partition ID. + * Access: Index + */ +MLXSW_ITEM32_INDEXED(reg, sfd, rec_swid, MLXSW_REG_SFD_BASE_LEN, 24, 8, + MLXSW_REG_SFD_REC_LEN, 0x00, false); + +enum mlxsw_reg_sfd_rec_type { + MLXSW_REG_SFD_REC_TYPE_UNICAST = 0x0, +}; + +/* reg_sfd_rec_type + * FDB record type. + * Access: RW + */ +MLXSW_ITEM32_INDEXED(reg, sfd, rec_type, MLXSW_REG_SFD_BASE_LEN, 20, 4, + MLXSW_REG_SFD_REC_LEN, 0x00, false); + +enum mlxsw_reg_sfd_rec_policy { + /* Replacement disabled, aging disabled. */ + MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY = 0, + /* (mlag remote): Replacement enabled, aging disabled, + * learning notification enabled on this port. + */ + MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_MLAG = 1, + /* (ingress device): Replacement enabled, aging enabled. */ + MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS = 3, +}; + +/* reg_sfd_rec_policy + * Policy. + * Access: RW + */ +MLXSW_ITEM32_INDEXED(reg, sfd, rec_policy, MLXSW_REG_SFD_BASE_LEN, 18, 2, + MLXSW_REG_SFD_REC_LEN, 0x00, false); + +/* reg_sfd_rec_a + * Activity. Set for new static entries. Set for static entries if a frame SMAC + * lookup hits on the entry. + * To clear the a bit, use "query and clear activity" op. + * Access: RO + */ +MLXSW_ITEM32_INDEXED(reg, sfd, rec_a, MLXSW_REG_SFD_BASE_LEN, 16, 1, + MLXSW_REG_SFD_REC_LEN, 0x00, false); + +/* reg_sfd_rec_mac + * MAC address. + * Access: Index + */ +MLXSW_ITEM_BUF_INDEXED(reg, sfd, rec_mac, MLXSW_REG_SFD_BASE_LEN, 6, + MLXSW_REG_SFD_REC_LEN, 0x02); + +enum mlxsw_reg_sfd_rec_action { + /* forward */ + MLXSW_REG_SFD_REC_ACTION_NOP = 0, + /* forward and trap, trap_id is FDB_TRAP */ + MLXSW_REG_SFD_REC_ACTION_MIRROR_TO_CPU = 1, + /* trap and do not forward, trap_id is FDB_TRAP */ + MLXSW_REG_SFD_REC_ACTION_TRAP = 3, + MLXSW_REG_SFD_REC_ACTION_DISCARD_ERROR = 15, +}; + +/* reg_sfd_rec_action + * Action to apply on the packet. + * Note: Dynamic entries can only be configured with NOP action. + * Access: RW + */ +MLXSW_ITEM32_INDEXED(reg, sfd, rec_action, MLXSW_REG_SFD_BASE_LEN, 28, 4, + MLXSW_REG_SFD_REC_LEN, 0x0C, false); + +/* reg_sfd_uc_sub_port + * LAG sub port. + * Must be 0 if multichannel VEPA is not enabled. + * Access: RW + */ +MLXSW_ITEM32_INDEXED(reg, sfd, uc_sub_port, MLXSW_REG_SFD_BASE_LEN, 16, 8, + MLXSW_REG_SFD_REC_LEN, 0x08, false); + +/* reg_sfd_uc_fid_vid + * Filtering ID or VLAN ID + * For SwitchX and SwitchX-2: + * - Dynamic entries (policy 2,3) use FID + * - Static entries (policy 0) use VID + * - When independent learning is configured, VID=FID + * For Spectrum: use FID for both Dynamic and Static entries. + * VID should not be used. + * Access: Index + */ +MLXSW_ITEM32_INDEXED(reg, sfd, uc_fid_vid, MLXSW_REG_SFD_BASE_LEN, 0, 16, + MLXSW_REG_SFD_REC_LEN, 0x08, false); + +/* reg_sfd_uc_system_port + * Unique port identifier for the final destination of the packet. + * Access: RW + */ +MLXSW_ITEM32_INDEXED(reg, sfd, uc_system_port, MLXSW_REG_SFD_BASE_LEN, 0, 16, + MLXSW_REG_SFD_REC_LEN, 0x0C, false); + +static inline void mlxsw_reg_sfd_uc_pack(char *payload, int rec_index, + enum mlxsw_reg_sfd_rec_policy policy, + const char *mac, u16 vid, + enum mlxsw_reg_sfd_rec_action action, + u8 local_port) +{ + u8 num_rec = mlxsw_reg_sfd_num_rec_get(payload); + + if (rec_index >= num_rec) + mlxsw_reg_sfd_num_rec_set(payload, rec_index + 1); + mlxsw_reg_sfd_rec_swid_set(payload, rec_index, 0); + mlxsw_reg_sfd_rec_type_set(payload, rec_index, + MLXSW_REG_SFD_REC_TYPE_UNICAST); + mlxsw_reg_sfd_rec_policy_set(payload, rec_index, policy); + mlxsw_reg_sfd_rec_mac_memcpy_to(payload, rec_index, mac); + mlxsw_reg_sfd_uc_sub_port_set(payload, rec_index, 0); + mlxsw_reg_sfd_uc_fid_vid_set(payload, rec_index, vid); + mlxsw_reg_sfd_rec_action_set(payload, rec_index, action); + mlxsw_reg_sfd_uc_system_port_set(payload, rec_index, local_port); +} + +static inline void +mlxsw_reg_sfd_uc_unpack(char *payload, int rec_index, + char *mac, u16 *p_vid, + u8 *p_local_port) +{ + mlxsw_reg_sfd_rec_mac_memcpy_from(payload, rec_index, mac); + *p_vid = mlxsw_reg_sfd_uc_fid_vid_get(payload, rec_index); + *p_local_port = mlxsw_reg_sfd_uc_system_port_get(payload, rec_index); +} + /* SPMS - Switch Port MSTP/RSTP State Register * ------------------------------------------- * Configures the spanning tree state of a physical port. @@ -1251,6 +1465,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SPAD"; case MLXSW_REG_SSPR_ID: return "SSPR"; + case MLXSW_REG_SFD_ID: + return "SFD"; case MLXSW_REG_SPMS_ID: return "SPMS"; case MLXSW_REG_SFGC_ID: -- cgit v1.2.3 From f5d88f589297a9b5fb110bf01d621d8c09fb7512 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 16 Oct 2015 14:01:29 +0200 Subject: mlxsw: reg: Add Switch FDB Notification register definition Add SFN register which is used to poll for newly added and aged-out FDB entries. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 101 ++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index c0cc5f102189..8afa2b6706c6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -371,6 +371,105 @@ mlxsw_reg_sfd_uc_unpack(char *payload, int rec_index, *p_local_port = mlxsw_reg_sfd_uc_system_port_get(payload, rec_index); } +/* SFN - Switch FDB Notification Register + * ------------------------------------------- + * The switch provides notifications on newly learned FDB entries and + * aged out entries. The notifications can be polled by software. + */ +#define MLXSW_REG_SFN_ID 0x200B +#define MLXSW_REG_SFN_BASE_LEN 0x10 /* base length, without records */ +#define MLXSW_REG_SFN_REC_LEN 0x10 /* record length */ +#define MLXSW_REG_SFN_REC_MAX_COUNT 64 +#define MLXSW_REG_SFN_LEN (MLXSW_REG_SFN_BASE_LEN + \ + MLXSW_REG_SFN_REC_LEN * MLXSW_REG_SFN_REC_MAX_COUNT) + +static const struct mlxsw_reg_info mlxsw_reg_sfn = { + .id = MLXSW_REG_SFN_ID, + .len = MLXSW_REG_SFN_LEN, +}; + +/* reg_sfn_swid + * Switch partition ID. + * Access: Index + */ +MLXSW_ITEM32(reg, sfn, swid, 0x00, 24, 8); + +/* reg_sfn_num_rec + * Request: Number of learned notifications and aged-out notification + * records requested. + * Response: Number of notification records returned (must be smaller + * than or equal to the value requested) + * Ranges 0..64 + * Access: OP + */ +MLXSW_ITEM32(reg, sfn, num_rec, 0x04, 0, 8); + +static inline void mlxsw_reg_sfn_pack(char *payload) +{ + MLXSW_REG_ZERO(sfn, payload); + mlxsw_reg_sfn_swid_set(payload, 0); + mlxsw_reg_sfn_num_rec_set(payload, MLXSW_REG_SFN_REC_MAX_COUNT); +} + +/* reg_sfn_rec_swid + * Switch partition ID. + * Access: RO + */ +MLXSW_ITEM32_INDEXED(reg, sfn, rec_swid, MLXSW_REG_SFN_BASE_LEN, 24, 8, + MLXSW_REG_SFN_REC_LEN, 0x00, false); + +enum mlxsw_reg_sfn_rec_type { + /* MAC addresses learned on a regular port. */ + MLXSW_REG_SFN_REC_TYPE_LEARNED_MAC = 0x5, + /* Aged-out MAC address on a regular port */ + MLXSW_REG_SFN_REC_TYPE_AGED_OUT_MAC = 0x7, +}; + +/* reg_sfn_rec_type + * Notification record type. + * Access: RO + */ +MLXSW_ITEM32_INDEXED(reg, sfn, rec_type, MLXSW_REG_SFN_BASE_LEN, 20, 4, + MLXSW_REG_SFN_REC_LEN, 0x00, false); + +/* reg_sfn_rec_mac + * MAC address. + * Access: RO + */ +MLXSW_ITEM_BUF_INDEXED(reg, sfn, rec_mac, MLXSW_REG_SFN_BASE_LEN, 6, + MLXSW_REG_SFN_REC_LEN, 0x02); + +/* reg_sfd_mac_sub_port + * VEPA channel on the local port. + * 0 if multichannel VEPA is not enabled. + * Access: RO + */ +MLXSW_ITEM32_INDEXED(reg, sfn, mac_sub_port, MLXSW_REG_SFN_BASE_LEN, 16, 8, + MLXSW_REG_SFN_REC_LEN, 0x08, false); + +/* reg_sfd_mac_fid + * Filtering identifier. + * Access: RO + */ +MLXSW_ITEM32_INDEXED(reg, sfn, mac_fid, MLXSW_REG_SFN_BASE_LEN, 0, 16, + MLXSW_REG_SFN_REC_LEN, 0x08, false); + +/* reg_sfd_mac_system_port + * Unique port identifier for the final destination of the packet. + * Access: RO + */ +MLXSW_ITEM32_INDEXED(reg, sfn, mac_system_port, MLXSW_REG_SFN_BASE_LEN, 0, 16, + MLXSW_REG_SFN_REC_LEN, 0x0C, false); + +static inline void mlxsw_reg_sfn_mac_unpack(char *payload, int rec_index, + char *mac, u16 *p_vid, + u8 *p_local_port) +{ + mlxsw_reg_sfn_rec_mac_memcpy_from(payload, rec_index, mac); + *p_vid = mlxsw_reg_sfn_mac_fid_get(payload, rec_index); + *p_local_port = mlxsw_reg_sfn_mac_system_port_get(payload, rec_index); +} + /* SPMS - Switch Port MSTP/RSTP State Register * ------------------------------------------- * Configures the spanning tree state of a physical port. @@ -1467,6 +1566,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SSPR"; case MLXSW_REG_SFD_ID: return "SFD"; + case MLXSW_REG_SFN_ID: + return "SFN"; case MLXSW_REG_SPMS_ID: return "SPMS"; case MLXSW_REG_SFGC_ID: -- cgit v1.2.3 From b2e345f9a454f6e435f1a61b02f0e4f0125b94e3 Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Fri, 16 Oct 2015 14:01:30 +0200 Subject: mlxsw: reg: Add Switch Port VID and Switch Port VLAN Membership registers definitions Add SPVID and SPVM registers responsible for default port VID configuration and VLAN membership of a port. Signed-off-by: Elad Raz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 146 ++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 8afa2b6706c6..f23f95157acc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -517,6 +517,148 @@ static inline void mlxsw_reg_spms_vid_pack(char *payload, u16 vid, mlxsw_reg_spms_state_set(payload, vid, state); } +/* SPVID - Switch Port VID + * ----------------------- + * The switch port VID configures the default VID for a port. + */ +#define MLXSW_REG_SPVID_ID 0x200E +#define MLXSW_REG_SPVID_LEN 0x08 + +static const struct mlxsw_reg_info mlxsw_reg_spvid = { + .id = MLXSW_REG_SPVID_ID, + .len = MLXSW_REG_SPVID_LEN, +}; + +/* reg_spvid_local_port + * Local port number. + * Access: Index + */ +MLXSW_ITEM32(reg, spvid, local_port, 0x00, 16, 8); + +/* reg_spvid_sub_port + * Virtual port within the physical port. + * Should be set to 0 when virtual ports are not enabled on the port. + * Access: Index + */ +MLXSW_ITEM32(reg, spvid, sub_port, 0x00, 8, 8); + +/* reg_spvid_pvid + * Port default VID + * Access: RW + */ +MLXSW_ITEM32(reg, spvid, pvid, 0x04, 0, 12); + +static inline void mlxsw_reg_spvid_pack(char *payload, u8 local_port, u16 pvid) +{ + MLXSW_REG_ZERO(spvid, payload); + mlxsw_reg_spvid_local_port_set(payload, local_port); + mlxsw_reg_spvid_pvid_set(payload, pvid); +} + +/* SPVM - Switch Port VLAN Membership + * ---------------------------------- + * The Switch Port VLAN Membership register configures the VLAN membership + * of a port in a VLAN denoted by VID. VLAN membership is managed per + * virtual port. The register can be used to add and remove VID(s) from a port. + */ +#define MLXSW_REG_SPVM_ID 0x200F +#define MLXSW_REG_SPVM_BASE_LEN 0x04 /* base length, without records */ +#define MLXSW_REG_SPVM_REC_LEN 0x04 /* record length */ +#define MLXSW_REG_SPVM_REC_MAX_COUNT 256 +#define MLXSW_REG_SPVM_LEN (MLXSW_REG_SPVM_BASE_LEN + \ + MLXSW_REG_SPVM_REC_LEN * MLXSW_REG_SPVM_REC_MAX_COUNT) + +static const struct mlxsw_reg_info mlxsw_reg_spvm = { + .id = MLXSW_REG_SPVM_ID, + .len = MLXSW_REG_SPVM_LEN, +}; + +/* reg_spvm_pt + * Priority tagged. If this bit is set, packets forwarded to the port with + * untagged VLAN membership (u bit is set) will be tagged with priority tag + * (VID=0) + * Access: RW + */ +MLXSW_ITEM32(reg, spvm, pt, 0x00, 31, 1); + +/* reg_spvm_pte + * Priority Tagged Update Enable. On Write operations, if this bit is cleared, + * the pt bit will NOT be updated. To update the pt bit, pte must be set. + * Access: WO + */ +MLXSW_ITEM32(reg, spvm, pte, 0x00, 30, 1); + +/* reg_spvm_local_port + * Local port number. + * Access: Index + */ +MLXSW_ITEM32(reg, spvm, local_port, 0x00, 16, 8); + +/* reg_spvm_sub_port + * Virtual port within the physical port. + * Should be set to 0 when virtual ports are not enabled on the port. + * Access: Index + */ +MLXSW_ITEM32(reg, spvm, sub_port, 0x00, 8, 8); + +/* reg_spvm_num_rec + * Number of records to update. Each record contains: i, e, u, vid. + * Access: OP + */ +MLXSW_ITEM32(reg, spvm, num_rec, 0x00, 0, 8); + +/* reg_spvm_rec_i + * Ingress membership in VLAN ID. + * Access: Index + */ +MLXSW_ITEM32_INDEXED(reg, spvm, rec_i, + MLXSW_REG_SPVM_BASE_LEN, 14, 1, + MLXSW_REG_SPVM_REC_LEN, 0, false); + +/* reg_spvm_rec_e + * Egress membership in VLAN ID. + * Access: Index + */ +MLXSW_ITEM32_INDEXED(reg, spvm, rec_e, + MLXSW_REG_SPVM_BASE_LEN, 13, 1, + MLXSW_REG_SPVM_REC_LEN, 0, false); + +/* reg_spvm_rec_u + * Untagged - port is an untagged member - egress transmission uses untagged + * frames on VID + * Access: Index + */ +MLXSW_ITEM32_INDEXED(reg, spvm, rec_u, + MLXSW_REG_SPVM_BASE_LEN, 12, 1, + MLXSW_REG_SPVM_REC_LEN, 0, false); + +/* reg_spvm_rec_vid + * Egress membership in VLAN ID. + * Access: Index + */ +MLXSW_ITEM32_INDEXED(reg, spvm, rec_vid, + MLXSW_REG_SPVM_BASE_LEN, 0, 12, + MLXSW_REG_SPVM_REC_LEN, 0, false); + +static inline void mlxsw_reg_spvm_pack(char *payload, u8 local_port, + u16 vid_begin, u16 vid_end, + bool is_member, bool untagged) +{ + int size = vid_end - vid_begin + 1; + int i; + + MLXSW_REG_ZERO(spvm, payload); + mlxsw_reg_spvm_local_port_set(payload, local_port); + mlxsw_reg_spvm_num_rec_set(payload, size); + + for (i = 0; i < size; i++) { + mlxsw_reg_spvm_rec_i_set(payload, i, is_member); + mlxsw_reg_spvm_rec_e_set(payload, i, is_member); + mlxsw_reg_spvm_rec_u_set(payload, i, untagged); + mlxsw_reg_spvm_rec_vid_set(payload, i, vid_begin + i); + } +} + /* SFGC - Switch Flooding Group Configuration * ------------------------------------------ * The following register controls the association of flooding tables and MIDs @@ -1570,6 +1712,10 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SFN"; case MLXSW_REG_SPMS_ID: return "SPMS"; + case MLXSW_REG_SPVID_ID: + return "SPVID"; + case MLXSW_REG_SPVM_ID: + return "SPVM"; case MLXSW_REG_SFGC_ID: return "SFGC"; case MLXSW_REG_SFTR_ID: -- cgit v1.2.3 From e059436999d797bbdb36ec41b6f6890a569cbf94 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 16 Oct 2015 14:01:31 +0200 Subject: mlxsw: reg: Add shared buffer configuration registers definitions Add definitions of SBPR, SBCM, SBPM, SBMM and PBMC registers that are used to configure shared buffers. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 349 ++++++++++++++++++++++++++++++ 1 file changed, 349 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index f23f95157acc..bb0ad09cb2cd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -1418,6 +1418,82 @@ static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port) mlxsw_reg_ppcnt_prio_tc_set(payload, 0); } +/* PBMC - Port Buffer Management Control Register + * ---------------------------------------------- + * The PBMC register configures and retrieves the port packet buffer + * allocation for different Prios, and the Pause threshold management. + */ +#define MLXSW_REG_PBMC_ID 0x500C +#define MLXSW_REG_PBMC_LEN 0x68 + +static const struct mlxsw_reg_info mlxsw_reg_pbmc = { + .id = MLXSW_REG_PBMC_ID, + .len = MLXSW_REG_PBMC_LEN, +}; + +/* reg_pbmc_local_port + * Local port number. + * Access: Index + */ +MLXSW_ITEM32(reg, pbmc, local_port, 0x00, 16, 8); + +/* reg_pbmc_xoff_timer_value + * When device generates a pause frame, it uses this value as the pause + * timer (time for the peer port to pause in quota-512 bit time). + * Access: RW + */ +MLXSW_ITEM32(reg, pbmc, xoff_timer_value, 0x04, 16, 16); + +/* reg_pbmc_xoff_refresh + * The time before a new pause frame should be sent to refresh the pause RW + * state. Using the same units as xoff_timer_value above (in quota-512 bit + * time). + * Access: RW + */ +MLXSW_ITEM32(reg, pbmc, xoff_refresh, 0x04, 0, 16); + +/* reg_pbmc_buf_lossy + * The field indicates if the buffer is lossy. + * 0 - Lossless + * 1 - Lossy + * Access: RW + */ +MLXSW_ITEM32_INDEXED(reg, pbmc, buf_lossy, 0x0C, 25, 1, 0x08, 0x00, false); + +/* reg_pbmc_buf_epsb + * Eligible for Port Shared buffer. + * If epsb is set, packets assigned to buffer are allowed to insert the port + * shared buffer. + * When buf_lossy is MLXSW_REG_PBMC_LOSSY_LOSSY this field is reserved. + * Access: RW + */ +MLXSW_ITEM32_INDEXED(reg, pbmc, buf_epsb, 0x0C, 24, 1, 0x08, 0x00, false); + +/* reg_pbmc_buf_size + * The part of the packet buffer array is allocated for the specific buffer. + * Units are represented in cells. + * Access: RW + */ +MLXSW_ITEM32_INDEXED(reg, pbmc, buf_size, 0x0C, 0, 16, 0x08, 0x00, false); + +static inline void mlxsw_reg_pbmc_pack(char *payload, u8 local_port, + u16 xoff_timer_value, u16 xoff_refresh) +{ + MLXSW_REG_ZERO(pbmc, payload); + mlxsw_reg_pbmc_local_port_set(payload, local_port); + mlxsw_reg_pbmc_xoff_timer_value_set(payload, xoff_timer_value); + mlxsw_reg_pbmc_xoff_refresh_set(payload, xoff_refresh); +} + +static inline void mlxsw_reg_pbmc_lossy_buffer_pack(char *payload, + int buf_index, + u16 size) +{ + mlxsw_reg_pbmc_buf_lossy_set(payload, buf_index, 1); + mlxsw_reg_pbmc_buf_epsb_set(payload, buf_index, 0); + mlxsw_reg_pbmc_buf_size_set(payload, buf_index, size); +} + /* PSPA - Port Switch Partition Allocation * --------------------------------------- * Controls the association of a port with a switch partition and enables @@ -1697,6 +1773,269 @@ static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, u16 trap_id) mlxsw_reg_hpkt_ctrl_set(payload, MLXSW_REG_HPKT_CTRL_PACKET_DEFAULT); } +/* SBPR - Shared Buffer Pools Register + * ----------------------------------- + * The SBPR configures and retrieves the shared buffer pools and configuration. + */ +#define MLXSW_REG_SBPR_ID 0xB001 +#define MLXSW_REG_SBPR_LEN 0x14 + +static const struct mlxsw_reg_info mlxsw_reg_sbpr = { + .id = MLXSW_REG_SBPR_ID, + .len = MLXSW_REG_SBPR_LEN, +}; + +enum mlxsw_reg_sbpr_dir { + MLXSW_REG_SBPR_DIR_INGRESS, + MLXSW_REG_SBPR_DIR_EGRESS, +}; + +/* reg_sbpr_dir + * Direction. + * Access: Index + */ +MLXSW_ITEM32(reg, sbpr, dir, 0x00, 24, 2); + +/* reg_sbpr_pool + * Pool index. + * Access: Index + */ +MLXSW_ITEM32(reg, sbpr, pool, 0x00, 0, 4); + +/* reg_sbpr_size + * Pool size in buffer cells. + * Access: RW + */ +MLXSW_ITEM32(reg, sbpr, size, 0x04, 0, 24); + +enum mlxsw_reg_sbpr_mode { + MLXSW_REG_SBPR_MODE_STATIC, + MLXSW_REG_SBPR_MODE_DYNAMIC, +}; + +/* reg_sbpr_mode + * Pool quota calculation mode. + * Access: RW + */ +MLXSW_ITEM32(reg, sbpr, mode, 0x08, 0, 4); + +static inline void mlxsw_reg_sbpr_pack(char *payload, u8 pool, + enum mlxsw_reg_sbpr_dir dir, + enum mlxsw_reg_sbpr_mode mode, u32 size) +{ + MLXSW_REG_ZERO(sbpr, payload); + mlxsw_reg_sbpr_pool_set(payload, pool); + mlxsw_reg_sbpr_dir_set(payload, dir); + mlxsw_reg_sbpr_mode_set(payload, mode); + mlxsw_reg_sbpr_size_set(payload, size); +} + +/* SBCM - Shared Buffer Class Management Register + * ---------------------------------------------- + * The SBCM register configures and retrieves the shared buffer allocation + * and configuration according to Port-PG, including the binding to pool + * and definition of the associated quota. + */ +#define MLXSW_REG_SBCM_ID 0xB002 +#define MLXSW_REG_SBCM_LEN 0x28 + +static const struct mlxsw_reg_info mlxsw_reg_sbcm = { + .id = MLXSW_REG_SBCM_ID, + .len = MLXSW_REG_SBCM_LEN, +}; + +/* reg_sbcm_local_port + * Local port number. + * For Ingress: excludes CPU port and Router port + * For Egress: excludes IP Router + * Access: Index + */ +MLXSW_ITEM32(reg, sbcm, local_port, 0x00, 16, 8); + +/* reg_sbcm_pg_buff + * PG buffer - Port PG (dir=ingress) / traffic class (dir=egress) + * For PG buffer: range is 0..cap_max_pg_buffers - 1 + * For traffic class: range is 0..cap_max_tclass - 1 + * Note that when traffic class is in MC aware mode then the traffic + * classes which are MC aware cannot be configured. + * Access: Index + */ +MLXSW_ITEM32(reg, sbcm, pg_buff, 0x00, 8, 6); + +enum mlxsw_reg_sbcm_dir { + MLXSW_REG_SBCM_DIR_INGRESS, + MLXSW_REG_SBCM_DIR_EGRESS, +}; + +/* reg_sbcm_dir + * Direction. + * Access: Index + */ +MLXSW_ITEM32(reg, sbcm, dir, 0x00, 0, 2); + +/* reg_sbcm_min_buff + * Minimum buffer size for the limiter, in cells. + * Access: RW + */ +MLXSW_ITEM32(reg, sbcm, min_buff, 0x18, 0, 24); + +/* reg_sbcm_max_buff + * When the pool associated to the port-pg/tclass is configured to + * static, Maximum buffer size for the limiter configured in cells. + * When the pool associated to the port-pg/tclass is configured to + * dynamic, the max_buff holds the "alpha" parameter, supporting + * the following values: + * 0: 0 + * i: (1/128)*2^(i-1), for i=1..14 + * 0xFF: Infinity + * Access: RW + */ +MLXSW_ITEM32(reg, sbcm, max_buff, 0x1C, 0, 24); + +/* reg_sbcm_pool + * Association of the port-priority to a pool. + * Access: RW + */ +MLXSW_ITEM32(reg, sbcm, pool, 0x24, 0, 4); + +static inline void mlxsw_reg_sbcm_pack(char *payload, u8 local_port, u8 pg_buff, + enum mlxsw_reg_sbcm_dir dir, + u32 min_buff, u32 max_buff, u8 pool) +{ + MLXSW_REG_ZERO(sbcm, payload); + mlxsw_reg_sbcm_local_port_set(payload, local_port); + mlxsw_reg_sbcm_pg_buff_set(payload, pg_buff); + mlxsw_reg_sbcm_dir_set(payload, dir); + mlxsw_reg_sbcm_min_buff_set(payload, min_buff); + mlxsw_reg_sbcm_max_buff_set(payload, max_buff); + mlxsw_reg_sbcm_pool_set(payload, pool); +} + +/* SBPM - Shared Buffer Class Management Register + * ---------------------------------------------- + * The SBPM register configures and retrieves the shared buffer allocation + * and configuration according to Port-Pool, including the definition + * of the associated quota. + */ +#define MLXSW_REG_SBPM_ID 0xB003 +#define MLXSW_REG_SBPM_LEN 0x28 + +static const struct mlxsw_reg_info mlxsw_reg_sbpm = { + .id = MLXSW_REG_SBPM_ID, + .len = MLXSW_REG_SBPM_LEN, +}; + +/* reg_sbpm_local_port + * Local port number. + * For Ingress: excludes CPU port and Router port + * For Egress: excludes IP Router + * Access: Index + */ +MLXSW_ITEM32(reg, sbpm, local_port, 0x00, 16, 8); + +/* reg_sbpm_pool + * The pool associated to quota counting on the local_port. + * Access: Index + */ +MLXSW_ITEM32(reg, sbpm, pool, 0x00, 8, 4); + +enum mlxsw_reg_sbpm_dir { + MLXSW_REG_SBPM_DIR_INGRESS, + MLXSW_REG_SBPM_DIR_EGRESS, +}; + +/* reg_sbpm_dir + * Direction. + * Access: Index + */ +MLXSW_ITEM32(reg, sbpm, dir, 0x00, 0, 2); + +/* reg_sbpm_min_buff + * Minimum buffer size for the limiter, in cells. + * Access: RW + */ +MLXSW_ITEM32(reg, sbpm, min_buff, 0x18, 0, 24); + +/* reg_sbpm_max_buff + * When the pool associated to the port-pg/tclass is configured to + * static, Maximum buffer size for the limiter configured in cells. + * When the pool associated to the port-pg/tclass is configured to + * dynamic, the max_buff holds the "alpha" parameter, supporting + * the following values: + * 0: 0 + * i: (1/128)*2^(i-1), for i=1..14 + * 0xFF: Infinity + * Access: RW + */ +MLXSW_ITEM32(reg, sbpm, max_buff, 0x1C, 0, 24); + +static inline void mlxsw_reg_sbpm_pack(char *payload, u8 local_port, u8 pool, + enum mlxsw_reg_sbpm_dir dir, + u32 min_buff, u32 max_buff) +{ + MLXSW_REG_ZERO(sbpm, payload); + mlxsw_reg_sbpm_local_port_set(payload, local_port); + mlxsw_reg_sbpm_pool_set(payload, pool); + mlxsw_reg_sbpm_dir_set(payload, dir); + mlxsw_reg_sbpm_min_buff_set(payload, min_buff); + mlxsw_reg_sbpm_max_buff_set(payload, max_buff); +} + +/* SBMM - Shared Buffer Multicast Management Register + * -------------------------------------------------- + * The SBMM register configures and retrieves the shared buffer allocation + * and configuration for MC packets according to Switch-Priority, including + * the binding to pool and definition of the associated quota. + */ +#define MLXSW_REG_SBMM_ID 0xB004 +#define MLXSW_REG_SBMM_LEN 0x28 + +static const struct mlxsw_reg_info mlxsw_reg_sbmm = { + .id = MLXSW_REG_SBMM_ID, + .len = MLXSW_REG_SBMM_LEN, +}; + +/* reg_sbmm_prio + * Switch Priority. + * Access: Index + */ +MLXSW_ITEM32(reg, sbmm, prio, 0x00, 8, 4); + +/* reg_sbmm_min_buff + * Minimum buffer size for the limiter, in cells. + * Access: RW + */ +MLXSW_ITEM32(reg, sbmm, min_buff, 0x18, 0, 24); + +/* reg_sbmm_max_buff + * When the pool associated to the port-pg/tclass is configured to + * static, Maximum buffer size for the limiter configured in cells. + * When the pool associated to the port-pg/tclass is configured to + * dynamic, the max_buff holds the "alpha" parameter, supporting + * the following values: + * 0: 0 + * i: (1/128)*2^(i-1), for i=1..14 + * 0xFF: Infinity + * Access: RW + */ +MLXSW_ITEM32(reg, sbmm, max_buff, 0x1C, 0, 24); + +/* reg_sbmm_pool + * Association of the port-priority to a pool. + * Access: RW + */ +MLXSW_ITEM32(reg, sbmm, pool, 0x24, 0, 4); + +static inline void mlxsw_reg_sbmm_pack(char *payload, u8 prio, u32 min_buff, + u32 max_buff, u8 pool) +{ + MLXSW_REG_ZERO(sbmm, payload); + mlxsw_reg_sbmm_prio_set(payload, prio); + mlxsw_reg_sbmm_min_buff_set(payload, min_buff); + mlxsw_reg_sbmm_max_buff_set(payload, max_buff); + mlxsw_reg_sbmm_pool_set(payload, pool); +} + static inline const char *mlxsw_reg_id_str(u16 reg_id) { switch (reg_id) { @@ -1734,12 +2073,22 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "PAOS"; case MLXSW_REG_PPCNT_ID: return "PPCNT"; + case MLXSW_REG_PBMC_ID: + return "PBMC"; case MLXSW_REG_PSPA_ID: return "PSPA"; case MLXSW_REG_HTGT_ID: return "HTGT"; case MLXSW_REG_HPKT_ID: return "HPKT"; + case MLXSW_REG_SBPR_ID: + return "SBPR"; + case MLXSW_REG_SBCM_ID: + return "SBCM"; + case MLXSW_REG_SBPM_ID: + return "SBPM"; + case MLXSW_REG_SBMM_ID: + return "SBMM"; default: return "*UNKNOWN*"; } -- cgit v1.2.3 From f1fb693a0875d0d1510cf8e84d35df2661f5a38f Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 16 Oct 2015 14:01:32 +0200 Subject: mlxsw: reg: Add Switch FID Management register definition Filtering identifiers (FIDs) are unique identifers of bridge instances in the hardware. Add the SFMR register, which is responsible for the creation and configuration of these FIDs. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 87 +++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index bb0ad09cb2cd..6f4a7b00ca60 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -883,6 +883,91 @@ static inline void mlxsw_reg_spmlr_pack(char *payload, u8 local_port, mlxsw_reg_spmlr_learn_mode_set(payload, mode); } +/* SFMR - Switch FID Management Register + * ------------------------------------- + * Creates and configures FIDs. + */ +#define MLXSW_REG_SFMR_ID 0x201F +#define MLXSW_REG_SFMR_LEN 0x18 + +static const struct mlxsw_reg_info mlxsw_reg_sfmr = { + .id = MLXSW_REG_SFMR_ID, + .len = MLXSW_REG_SFMR_LEN, +}; + +enum mlxsw_reg_sfmr_op { + MLXSW_REG_SFMR_OP_CREATE_FID, + MLXSW_REG_SFMR_OP_DESTROY_FID, +}; + +/* reg_sfmr_op + * Operation. + * 0 - Create or edit FID. + * 1 - Destroy FID. + * Access: WO + */ +MLXSW_ITEM32(reg, sfmr, op, 0x00, 24, 4); + +/* reg_sfmr_fid + * Filtering ID. + * Access: Index + */ +MLXSW_ITEM32(reg, sfmr, fid, 0x00, 0, 16); + +/* reg_sfmr_fid_offset + * FID offset. + * Used to point into the flooding table selected by SFGC register if + * the table is of type FID-Offset. Otherwise, this field is reserved. + * Access: RW + */ +MLXSW_ITEM32(reg, sfmr, fid_offset, 0x08, 0, 16); + +/* reg_sfmr_vtfp + * Valid Tunnel Flood Pointer. + * If not set, then nve_tunnel_flood_ptr is reserved and considered NULL. + * Access: RW + * + * Note: Reserved for 802.1Q FIDs. + */ +MLXSW_ITEM32(reg, sfmr, vtfp, 0x0C, 31, 1); + +/* reg_sfmr_nve_tunnel_flood_ptr + * Underlay Flooding and BC Pointer. + * Used as a pointer to the first entry of the group based link lists of + * flooding or BC entries (for NVE tunnels). + * Access: RW + */ +MLXSW_ITEM32(reg, sfmr, nve_tunnel_flood_ptr, 0x0C, 0, 24); + +/* reg_sfmr_vv + * VNI Valid. + * If not set, then vni is reserved. + * Access: RW + * + * Note: Reserved for 802.1Q FIDs. + */ +MLXSW_ITEM32(reg, sfmr, vv, 0x10, 31, 1); + +/* reg_sfmr_vni + * Virtual Network Identifier. + * Access: RW + * + * Note: A given VNI can only be assigned to one FID. + */ +MLXSW_ITEM32(reg, sfmr, vni, 0x10, 0, 24); + +static inline void mlxsw_reg_sfmr_pack(char *payload, + enum mlxsw_reg_sfmr_op op, u16 fid, + u16 fid_offset) +{ + MLXSW_REG_ZERO(sfmr, payload); + mlxsw_reg_sfmr_op_set(payload, op); + mlxsw_reg_sfmr_fid_set(payload, fid); + mlxsw_reg_sfmr_fid_offset_set(payload, fid_offset); + mlxsw_reg_sfmr_vtfp_set(payload, false); + mlxsw_reg_sfmr_vv_set(payload, false); +} + /* PMLP - Ports Module to Local Port Register * ------------------------------------------ * Configures the assignment of modules to local ports. @@ -2061,6 +2146,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SFTR"; case MLXSW_REG_SPMLR_ID: return "SPMLR"; + case MLXSW_REG_SFMR_ID: + return "SFMR"; case MLXSW_REG_PMLP_ID: return "PMLP"; case MLXSW_REG_PMTU_ID: -- cgit v1.2.3 From 647902397663468c2feefa9cd8097e194802a0b3 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 16 Oct 2015 14:01:33 +0200 Subject: mlxsw: reg: Add Switch VID to FID Allocation register definition An incoming packet can be classified into a filtering identifer (FID) based on its VID or incoming port and VID ({Port, VID}). Add the SVFA register, which controls this mapping. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 95 +++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 6f4a7b00ca60..5a977078d601 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -883,6 +883,99 @@ static inline void mlxsw_reg_spmlr_pack(char *payload, u8 local_port, mlxsw_reg_spmlr_learn_mode_set(payload, mode); } +/* SVFA - Switch VID to FID Allocation Register + * -------------------------------------------- + * Controls the VID to FID mapping and {Port, VID} to FID mapping for + * virtualized ports. + */ +#define MLXSW_REG_SVFA_ID 0x201C +#define MLXSW_REG_SVFA_LEN 0x10 + +static const struct mlxsw_reg_info mlxsw_reg_svfa = { + .id = MLXSW_REG_SVFA_ID, + .len = MLXSW_REG_SVFA_LEN, +}; + +/* reg_svfa_swid + * Switch partition ID. + * Access: Index + */ +MLXSW_ITEM32(reg, svfa, swid, 0x00, 24, 8); + +/* reg_svfa_local_port + * Local port number. + * Access: Index + * + * Note: Reserved for 802.1Q FIDs. + */ +MLXSW_ITEM32(reg, svfa, local_port, 0x00, 16, 8); + +enum mlxsw_reg_svfa_mt { + MLXSW_REG_SVFA_MT_VID_TO_FID, + MLXSW_REG_SVFA_MT_PORT_VID_TO_FID, +}; + +/* reg_svfa_mapping_table + * Mapping table: + * 0 - VID to FID + * 1 - {Port, VID} to FID + * Access: Index + * + * Note: Reserved for SwitchX-2. + */ +MLXSW_ITEM32(reg, svfa, mapping_table, 0x00, 8, 3); + +/* reg_svfa_v + * Valid. + * Valid if set. + * Access: RW + * + * Note: Reserved for SwitchX-2. + */ +MLXSW_ITEM32(reg, svfa, v, 0x00, 0, 1); + +/* reg_svfa_fid + * Filtering ID. + * Access: RW + */ +MLXSW_ITEM32(reg, svfa, fid, 0x04, 16, 16); + +/* reg_svfa_vid + * VLAN ID. + * Access: Index + */ +MLXSW_ITEM32(reg, svfa, vid, 0x04, 0, 12); + +/* reg_svfa_counter_set_type + * Counter set type for flow counters. + * Access: RW + * + * Note: Reserved for SwitchX-2. + */ +MLXSW_ITEM32(reg, svfa, counter_set_type, 0x08, 24, 8); + +/* reg_svfa_counter_index + * Counter index for flow counters. + * Access: RW + * + * Note: Reserved for SwitchX-2. + */ +MLXSW_ITEM32(reg, svfa, counter_index, 0x08, 0, 24); + +static inline void mlxsw_reg_svfa_pack(char *payload, u8 local_port, + enum mlxsw_reg_svfa_mt mt, bool valid, + u16 fid, u16 vid) +{ + MLXSW_REG_ZERO(svfa, payload); + local_port = mt == MLXSW_REG_SVFA_MT_VID_TO_FID ? 0 : local_port; + mlxsw_reg_svfa_swid_set(payload, 0); + mlxsw_reg_svfa_local_port_set(payload, local_port); + mlxsw_reg_svfa_mapping_table_set(payload, mt); + mlxsw_reg_svfa_v_set(payload, valid); + mlxsw_reg_svfa_fid_set(payload, fid); + mlxsw_reg_svfa_vid_set(payload, vid); +} + /* SFMR - Switch FID Management Register * ------------------------------------- * Creates and configures FIDs. @@ -2146,6 +2239,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SFTR"; case MLXSW_REG_SPMLR_ID: return "SPMLR"; + case MLXSW_REG_SVFA_ID: + return "SVFA"; case MLXSW_REG_SFMR_ID: return "SFMR"; case MLXSW_REG_PMLP_ID: -- cgit v1.2.3 From 1f65da742d15462786533cf3ea58335aa32e3daa Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 16 Oct 2015 14:01:34 +0200 Subject: mlxsw: reg: Add Switch Virtual-Port Enabling register definition In order for a port to support {Port, VID} to FID mapping it needs to be configured to a virtual port mode (as opposed to VLAN mode). Add the SVPE register, which enables port virtualization. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 38 +++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 5a977078d601..8e1888b10479 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -976,6 +976,42 @@ static inline void mlxsw_reg_svfa_pack(char *payload, u8 local_port, mlxsw_reg_svfa_vid_set(payload, vid); } +/* SVPE - Switch Virtual-Port Enabling Register + * -------------------------------------------- + * Enables port virtualization. + */ +#define MLXSW_REG_SVPE_ID 0x201E +#define MLXSW_REG_SVPE_LEN 0x4 + +static const struct mlxsw_reg_info mlxsw_reg_svpe = { + .id = MLXSW_REG_SVPE_ID, + .len = MLXSW_REG_SVPE_LEN, +}; + +/* reg_svpe_local_port + * Local port number + * Access: Index + * + * Note: CPU port is not supported (uses VLAN mode only). + */ +MLXSW_ITEM32(reg, svpe, local_port, 0x00, 16, 8); + +/* reg_svpe_vp_en + * Virtual port enable. + * 0 - Disable, VLAN mode (VID to FID). + * 1 - Enable, Virtual port mode ({Port, VID} to FID). + * Access: RW + */ +MLXSW_ITEM32(reg, svpe, vp_en, 0x00, 8, 1); + +static inline void mlxsw_reg_svpe_pack(char *payload, u8 local_port, + bool enable) +{ + MLXSW_REG_ZERO(svpe, payload); + mlxsw_reg_svpe_local_port_set(payload, local_port); + mlxsw_reg_svpe_vp_en_set(payload, enable); +} + /* SFMR - Switch FID Management Register * ------------------------------------- * Creates and configures FIDs. @@ -2241,6 +2277,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SPMLR"; case MLXSW_REG_SVFA_ID: return "SVFA"; + case MLXSW_REG_SVPE_ID: + return "SVPE"; case MLXSW_REG_SFMR_ID: return "SFMR"; case MLXSW_REG_PMLP_ID: -- cgit v1.2.3 From e534a56a317fa4e55419cc255d6af2683288d71c Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 16 Oct 2015 14:01:35 +0200 Subject: mlxsw: reg: Add Switch Filtering Database Aging Time register definition Add SFDAT which is used to control switch ageing time. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 8e1888b10479..d1c8eff04899 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -157,6 +157,41 @@ static inline void mlxsw_reg_sspr_pack(char *payload, u8 local_port) mlxsw_reg_sspr_system_port_set(payload, local_port); } +/* SFDAT - Switch Filtering Database Aging Time + * -------------------------------------------- + * Controls the Switch aging time. Aging time is able to be set per Switch + * Partition. + */ +#define MLXSW_REG_SFDAT_ID 0x2009 +#define MLXSW_REG_SFDAT_LEN 0x8 + +static const struct mlxsw_reg_info mlxsw_reg_sfdat = { + .id = MLXSW_REG_SFDAT_ID, + .len = MLXSW_REG_SFDAT_LEN, +}; + +/* reg_sfdat_swid + * Switch partition ID. + * Access: Index + */ +MLXSW_ITEM32(reg, sfdat, swid, 0x00, 24, 8); + +/* reg_sfdat_age_time + * Aging time in seconds + * Min - 10 seconds + * Max - 1,000,000 seconds + * Default is 300 seconds. + * Access: RW + */ +MLXSW_ITEM32(reg, sfdat, age_time, 0x04, 0, 20); + +static inline void mlxsw_reg_sfdat_pack(char *payload, u32 age_time) +{ + MLXSW_REG_ZERO(sfdat, payload); + mlxsw_reg_sfdat_swid_set(payload, 0); + mlxsw_reg_sfdat_age_time_set(payload, age_time); +} + /* SFD - Switch Filtering Database * ------------------------------- * The following register defines the access to the filtering database. @@ -2259,6 +2294,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SPAD"; case MLXSW_REG_SSPR_ID: return "SSPR"; + case MLXSW_REG_SFDAT_ID: + return "SFDAT"; case MLXSW_REG_SFD_ID: return "SFD"; case MLXSW_REG_SFN_ID: -- cgit v1.2.3 From a4feea74cd7a8f12d9fae67014533a4220135760 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Fri, 16 Oct 2015 14:01:36 +0200 Subject: mlxsw: reg: Add Switch Port VLAN MAC Learning register definition Since we currently do not support the offloading of 802.1D bridges, we need to be able to let the device know it should not learn MAC addresses on specific {Port, VID} pairs. Add the SPVMLR register, which controls the learning enablement of {Port, VID} pairs. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 67 +++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index d1c8eff04899..4fcba46bbae0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -1132,6 +1132,71 @@ static inline void mlxsw_reg_sfmr_pack(char *payload, mlxsw_reg_sfmr_vv_set(payload, false); } +/* SPVMLR - Switch Port VLAN MAC Learning Register + * ----------------------------------------------- + * Controls the switch MAC learning policy per {Port, VID}. + */ +#define MLXSW_REG_SPVMLR_ID 0x2020 +#define MLXSW_REG_SPVMLR_BASE_LEN 0x04 /* base length, without records */ +#define MLXSW_REG_SPVMLR_REC_LEN 0x04 /* record length */ +#define MLXSW_REG_SPVMLR_REC_MAX_COUNT 256 +#define MLXSW_REG_SPVMLR_LEN (MLXSW_REG_SPVMLR_BASE_LEN + \ + MLXSW_REG_SPVMLR_REC_LEN * \ + MLXSW_REG_SPVMLR_REC_MAX_COUNT) + +static const struct mlxsw_reg_info mlxsw_reg_spvmlr = { + .id = MLXSW_REG_SPVMLR_ID, + .len = MLXSW_REG_SPVMLR_LEN, +}; + +/* reg_spvmlr_local_port + * Local ingress port. + * Access: Index + * + * Note: CPU port is not supported. + */ +MLXSW_ITEM32(reg, spvmlr, local_port, 0x00, 16, 8); + +/* reg_spvmlr_num_rec + * Number of records to update. + * Access: OP + */ +MLXSW_ITEM32(reg, spvmlr, num_rec, 0x00, 0, 8); + +/* reg_spvmlr_rec_learn_enable + * 0 - Disable learning for {Port, VID}. + * 1 - Enable learning for {Port, VID}. + * Access: RW + */ +MLXSW_ITEM32_INDEXED(reg, spvmlr, rec_learn_enable, MLXSW_REG_SPVMLR_BASE_LEN, + 31, 1, MLXSW_REG_SPVMLR_REC_LEN, 0x00, false); + +/* reg_spvmlr_rec_vid + * VLAN ID to be added/removed from port or for querying. + * Access: Index + */ +MLXSW_ITEM32_INDEXED(reg, spvmlr, rec_vid, MLXSW_REG_SPVMLR_BASE_LEN, 0, 12, + MLXSW_REG_SPVMLR_REC_LEN, 0x00, false); + +static inline void mlxsw_reg_spvmlr_pack(char *payload, u8 local_port, + u16 vid_begin, u16 vid_end, + bool learn_enable) +{ + int num_rec = vid_end - vid_begin + 1; + int i; + + WARN_ON(num_rec < 1 || num_rec > MLXSW_REG_SPVMLR_REC_MAX_COUNT); + + MLXSW_REG_ZERO(spvmlr, payload); + mlxsw_reg_spvmlr_local_port_set(payload, local_port); + mlxsw_reg_spvmlr_num_rec_set(payload, num_rec); + + for (i = 0; i < num_rec; i++) { + mlxsw_reg_spvmlr_rec_learn_enable_set(payload, i, learn_enable); + mlxsw_reg_spvmlr_rec_vid_set(payload, i, vid_begin + i); + } +} + /* PMLP - Ports Module to Local Port Register * ------------------------------------------ * Configures the assignment of modules to local ports. @@ -2318,6 +2383,8 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id) return "SVPE"; case MLXSW_REG_SFMR_ID: return "SFMR"; + case MLXSW_REG_SPVMLR_ID: + return "SPVMLR"; case MLXSW_REG_PMLP_ID: return "PMLP"; case MLXSW_REG_PMTU_ID: -- cgit v1.2.3 From 56ade8fe3fe1e134783f61d164305107ae01030f Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 16 Oct 2015 14:01:37 +0200 Subject: mlxsw: spectrum: Add initial support for Spectrum ASIC Add support for new generation Mellanox Spectrum ASIC, 10/25/40/50 and 100Gb/s Ethernet Switch. The initial driver implements bridge forwarding offload including bridge internal VLAN support, FDB static entries, FDB learning and HW ageing including their setup. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: Elad Raz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/Kconfig | 11 + drivers/net/ethernet/mellanox/mlxsw/Makefile | 3 + drivers/net/ethernet/mellanox/mlxsw/core.h | 1 + drivers/net/ethernet/mellanox/mlxsw/pci.c | 3 + drivers/net/ethernet/mellanox/mlxsw/pci.h | 1 + drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 1948 ++++++++++++++++++++ drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 121 ++ .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c | 422 +++++ .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 863 +++++++++ drivers/net/ethernet/mellanox/mlxsw/txheader.h | 1 + 10 files changed, 3374 insertions(+) create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum.c create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum.h create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig index 2941d9c5ae48..e36e12219c9b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig +++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig @@ -30,3 +30,14 @@ config MLXSW_SWITCHX2 To compile this driver as a module, choose M here: the module will be called mlxsw_switchx2. + +config MLXSW_SPECTRUM + tristate "Mellanox Technologies Spectrum support" + depends on MLXSW_CORE && NET_SWITCHDEV + default m + ---help--- + This driver supports Mellanox Technologies Spectrum Ethernet + Switch ASICs. + + To compile this driver as a module, choose M here: the + module will be called mlxsw_spectrum. diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile index 0a05f65ee814..af015818fd19 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Makefile +++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile @@ -4,3 +4,6 @@ obj-$(CONFIG_MLXSW_PCI) += mlxsw_pci.o mlxsw_pci-objs := pci.o obj-$(CONFIG_MLXSW_SWITCHX2) += mlxsw_switchx2.o mlxsw_switchx2-objs := switchx2.o +obj-$(CONFIG_MLXSW_SPECTRUM) += mlxsw_spectrum.o +mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \ + spectrum_switchdev.o diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index e92ab272d9fb..807827350a89 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -54,6 +54,7 @@ MODULE_ALIAS(MLXSW_MODULE_ALIAS_PREFIX kind) #define MLXSW_DEVICE_KIND_SWITCHX2 "switchx2" +#define MLXSW_DEVICE_KIND_SPECTRUM "spectrum" struct mlxsw_core; struct mlxsw_driver; diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 0fa44c8e7102..879e000684c3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -57,6 +57,7 @@ static const char mlxsw_pci_driver_name[] = "mlxsw_pci"; static const struct pci_device_id mlxsw_pci_id_table[] = { {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHX2), 0}, + {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0}, {0, } }; @@ -67,6 +68,8 @@ static const char *mlxsw_pci_device_kind_get(const struct pci_device_id *id) switch (id->device) { case PCI_DEVICE_ID_MELLANOX_SWITCHX2: return MLXSW_DEVICE_KIND_SWITCHX2; + case PCI_DEVICE_ID_MELLANOX_SPECTRUM: + return MLXSW_DEVICE_KIND_SPECTRUM; default: BUG(); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.h b/drivers/net/ethernet/mellanox/mlxsw/pci.h index 5b3453b6cf5d..142f33d978c5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.h +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.h @@ -40,6 +40,7 @@ #include "item.h" #define PCI_DEVICE_ID_MELLANOX_SWITCHX2 0xc738 +#define PCI_DEVICE_ID_MELLANOX_SPECTRUM 0xcb84 #define MLXSW_PCI_BAR0_SIZE (1024 * 1024) /* 1MB */ #define MLXSW_PCI_PAGE_SIZE 4096 diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c new file mode 100644 index 000000000000..6e9906d8d149 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -0,0 +1,1948 @@ +/* + * drivers/net/ethernet/mellanox/mlxsw/spectrum.c + * Copyright (c) 2015 Mellanox Technologies. All rights reserved. + * Copyright (c) 2015 Jiri Pirko + * Copyright (c) 2015 Ido Schimmel + * Copyright (c) 2015 Elad Raz + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spectrum.h" +#include "core.h" +#include "reg.h" +#include "port.h" +#include "trap.h" +#include "txheader.h" + +static const char mlxsw_sp_driver_name[] = "mlxsw_spectrum"; +static const char mlxsw_sp_driver_version[] = "1.0"; + +/* tx_hdr_version + * Tx header version. + * Must be set to 1. + */ +MLXSW_ITEM32(tx, hdr, version, 0x00, 28, 4); + +/* tx_hdr_ctl + * Packet control type. + * 0 - Ethernet control (e.g. EMADs, LACP) + * 1 - Ethernet data + */ +MLXSW_ITEM32(tx, hdr, ctl, 0x00, 26, 2); + +/* tx_hdr_proto + * Packet protocol type. Must be set to 1 (Ethernet). + */ +MLXSW_ITEM32(tx, hdr, proto, 0x00, 21, 3); + +/* tx_hdr_rx_is_router + * Packet is sent from the router. Valid for data packets only. + */ +MLXSW_ITEM32(tx, hdr, rx_is_router, 0x00, 19, 1); + +/* tx_hdr_fid_valid + * Indicates if the 'fid' field is valid and should be used for + * forwarding lookup. Valid for data packets only. + */ +MLXSW_ITEM32(tx, hdr, fid_valid, 0x00, 16, 1); + +/* tx_hdr_swid + * Switch partition ID. Must be set to 0. + */ +MLXSW_ITEM32(tx, hdr, swid, 0x00, 12, 3); + +/* tx_hdr_control_tclass + * Indicates if the packet should use the control TClass and not one + * of the data TClasses. + */ +MLXSW_ITEM32(tx, hdr, control_tclass, 0x00, 6, 1); + +/* tx_hdr_etclass + * Egress TClass to be used on the egress device on the egress port. + */ +MLXSW_ITEM32(tx, hdr, etclass, 0x00, 0, 4); + +/* tx_hdr_port_mid + * Destination local port for unicast packets. + * Destination multicast ID for multicast packets. + * + * Control packets are directed to a specific egress port, while data + * packets are transmitted through the CPU port (0) into the switch partition, + * where forwarding rules are applied. + */ +MLXSW_ITEM32(tx, hdr, port_mid, 0x04, 16, 16); + +/* tx_hdr_fid + * Forwarding ID used for L2 forwarding lookup. Valid only if 'fid_valid' is + * set, otherwise calculated based on the packet's VID using VID to FID mapping. + * Valid for data packets only. + */ +MLXSW_ITEM32(tx, hdr, fid, 0x08, 0, 16); + +/* tx_hdr_type + * 0 - Data packets + * 6 - Control packets + */ +MLXSW_ITEM32(tx, hdr, type, 0x0C, 0, 4); + +static void mlxsw_sp_txhdr_construct(struct sk_buff *skb, + const struct mlxsw_tx_info *tx_info) +{ + char *txhdr = skb_push(skb, MLXSW_TXHDR_LEN); + + memset(txhdr, 0, MLXSW_TXHDR_LEN); + + mlxsw_tx_hdr_version_set(txhdr, MLXSW_TXHDR_VERSION_1); + mlxsw_tx_hdr_ctl_set(txhdr, MLXSW_TXHDR_ETH_CTL); + mlxsw_tx_hdr_proto_set(txhdr, MLXSW_TXHDR_PROTO_ETH); + mlxsw_tx_hdr_swid_set(txhdr, 0); + mlxsw_tx_hdr_control_tclass_set(txhdr, 1); + mlxsw_tx_hdr_port_mid_set(txhdr, tx_info->local_port); + mlxsw_tx_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL); +} + +static int mlxsw_sp_base_mac_get(struct mlxsw_sp *mlxsw_sp) +{ + char spad_pl[MLXSW_REG_SPAD_LEN]; + int err; + + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(spad), spad_pl); + if (err) + return err; + mlxsw_reg_spad_base_mac_memcpy_from(spad_pl, mlxsw_sp->base_mac); + return 0; +} + +static int mlxsw_sp_port_admin_status_set(struct mlxsw_sp_port *mlxsw_sp_port, + bool is_up) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char paos_pl[MLXSW_REG_PAOS_LEN]; + + mlxsw_reg_paos_pack(paos_pl, mlxsw_sp_port->local_port, + is_up ? MLXSW_PORT_ADMIN_STATUS_UP : + MLXSW_PORT_ADMIN_STATUS_DOWN); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(paos), paos_pl); +} + +static int mlxsw_sp_port_oper_status_get(struct mlxsw_sp_port *mlxsw_sp_port, + bool *p_is_up) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char paos_pl[MLXSW_REG_PAOS_LEN]; + u8 oper_status; + int err; + + mlxsw_reg_paos_pack(paos_pl, mlxsw_sp_port->local_port, 0); + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(paos), paos_pl); + if (err) + return err; + oper_status = mlxsw_reg_paos_oper_status_get(paos_pl); + *p_is_up = oper_status == MLXSW_PORT_ADMIN_STATUS_UP ? true : false; + return 0; +} + +static int mlxsw_sp_vfid_create(struct mlxsw_sp *mlxsw_sp, u16 vfid) +{ + char sfmr_pl[MLXSW_REG_SFMR_LEN]; + int err; + + mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, + MLXSW_SP_VFID_BASE + vfid, 0); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); + + if (err) + return err; + + set_bit(vfid, mlxsw_sp->active_vfids); + return 0; +} + +static void mlxsw_sp_vfid_destroy(struct mlxsw_sp *mlxsw_sp, u16 vfid) +{ + char sfmr_pl[MLXSW_REG_SFMR_LEN]; + + clear_bit(vfid, mlxsw_sp->active_vfids); + + mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_DESTROY_FID, + MLXSW_SP_VFID_BASE + vfid, 0); + mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); +} + +static int mlxsw_sp_port_dev_addr_set(struct mlxsw_sp_port *mlxsw_sp_port, + unsigned char *addr) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char ppad_pl[MLXSW_REG_PPAD_LEN]; + + mlxsw_reg_ppad_pack(ppad_pl, true, mlxsw_sp_port->local_port); + mlxsw_reg_ppad_mac_memcpy_to(ppad_pl, addr); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ppad), ppad_pl); +} + +static int mlxsw_sp_port_dev_addr_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + unsigned char *addr = mlxsw_sp_port->dev->dev_addr; + + ether_addr_copy(addr, mlxsw_sp->base_mac); + addr[ETH_ALEN - 1] += mlxsw_sp_port->local_port; + return mlxsw_sp_port_dev_addr_set(mlxsw_sp_port, addr); +} + +static int mlxsw_sp_port_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port, + u16 vid, enum mlxsw_reg_spms_state state) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char *spms_pl; + int err; + + spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL); + if (!spms_pl) + return -ENOMEM; + mlxsw_reg_spms_pack(spms_pl, mlxsw_sp_port->local_port); + mlxsw_reg_spms_vid_pack(spms_pl, vid, state); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spms), spms_pl); + kfree(spms_pl); + return err; +} + +static int mlxsw_sp_port_mtu_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char pmtu_pl[MLXSW_REG_PMTU_LEN]; + int max_mtu; + int err; + + mtu += MLXSW_TXHDR_LEN + ETH_HLEN; + mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sp_port->local_port, 0); + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl); + if (err) + return err; + max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl); + + if (mtu > max_mtu) + return -EINVAL; + + mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sp_port->local_port, mtu); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl); +} + +static int mlxsw_sp_port_swid_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 swid) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char pspa_pl[MLXSW_REG_PSPA_LEN]; + + mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sp_port->local_port); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pspa), pspa_pl); +} + +static int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port, + bool enable) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char svpe_pl[MLXSW_REG_SVPE_LEN]; + + mlxsw_reg_svpe_pack(svpe_pl, mlxsw_sp_port->local_port, enable); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svpe), svpe_pl); +} + +int mlxsw_sp_port_vid_to_fid_set(struct mlxsw_sp_port *mlxsw_sp_port, + enum mlxsw_reg_svfa_mt mt, bool valid, u16 fid, + u16 vid) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char svfa_pl[MLXSW_REG_SVFA_LEN]; + + mlxsw_reg_svfa_pack(svfa_pl, mlxsw_sp_port->local_port, mt, valid, + fid, vid); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); +} + +static int mlxsw_sp_port_vid_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, + u16 vid, bool learn_enable) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char *spvmlr_pl; + int err; + + spvmlr_pl = kmalloc(MLXSW_REG_SPVMLR_LEN, GFP_KERNEL); + if (!spvmlr_pl) + return -ENOMEM; + mlxsw_reg_spvmlr_pack(spvmlr_pl, mlxsw_sp_port->local_port, vid, vid, + learn_enable); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvmlr), spvmlr_pl); + kfree(spvmlr_pl); + return err; +} + +static int +mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char sspr_pl[MLXSW_REG_SSPR_LEN]; + + mlxsw_reg_sspr_pack(sspr_pl, mlxsw_sp_port->local_port); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sspr), sspr_pl); +} + +static int mlxsw_sp_port_module_check(struct mlxsw_sp_port *mlxsw_sp_port, + bool *p_usable) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char pmlp_pl[MLXSW_REG_PMLP_LEN]; + int err; + + mlxsw_reg_pmlp_pack(pmlp_pl, mlxsw_sp_port->local_port); + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pmlp), pmlp_pl); + if (err) + return err; + *p_usable = mlxsw_reg_pmlp_width_get(pmlp_pl) ? true : false; + return 0; +} + +static int mlxsw_sp_port_open(struct net_device *dev) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + int err; + + err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true); + if (err) + return err; + netif_start_queue(dev); + return 0; +} + +static int mlxsw_sp_port_stop(struct net_device *dev) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + + netif_stop_queue(dev); + return mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false); +} + +static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + struct mlxsw_sp_port_pcpu_stats *pcpu_stats; + const struct mlxsw_tx_info tx_info = { + .local_port = mlxsw_sp_port->local_port, + .is_emad = false, + }; + u64 len; + int err; + + if (mlxsw_core_skb_transmit_busy(mlxsw_sp, &tx_info)) + return NETDEV_TX_BUSY; + + if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) { + struct sk_buff *skb_orig = skb; + + skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN); + if (!skb) { + this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped); + dev_kfree_skb_any(skb_orig); + return NETDEV_TX_OK; + } + } + + if (eth_skb_pad(skb)) { + this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped); + return NETDEV_TX_OK; + } + + mlxsw_sp_txhdr_construct(skb, &tx_info); + len = skb->len; + /* Due to a race we might fail here because of a full queue. In that + * unlikely case we simply drop the packet. + */ + err = mlxsw_core_skb_transmit(mlxsw_sp, skb, &tx_info); + + if (!err) { + pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats); + u64_stats_update_begin(&pcpu_stats->syncp); + pcpu_stats->tx_packets++; + pcpu_stats->tx_bytes += len; + u64_stats_update_end(&pcpu_stats->syncp); + } else { + this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped); + dev_kfree_skb_any(skb); + } + return NETDEV_TX_OK; +} + +static int mlxsw_sp_port_set_mac_address(struct net_device *dev, void *p) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct sockaddr *addr = p; + int err; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + err = mlxsw_sp_port_dev_addr_set(mlxsw_sp_port, addr->sa_data); + if (err) + return err; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + return 0; +} + +static int mlxsw_sp_port_change_mtu(struct net_device *dev, int mtu) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + int err; + + err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, mtu); + if (err) + return err; + dev->mtu = mtu; + return 0; +} + +static struct rtnl_link_stats64 * +mlxsw_sp_port_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp_port_pcpu_stats *p; + u64 rx_packets, rx_bytes, tx_packets, tx_bytes; + u32 tx_dropped = 0; + unsigned int start; + int i; + + for_each_possible_cpu(i) { + p = per_cpu_ptr(mlxsw_sp_port->pcpu_stats, i); + do { + start = u64_stats_fetch_begin_irq(&p->syncp); + rx_packets = p->rx_packets; + rx_bytes = p->rx_bytes; + tx_packets = p->tx_packets; + tx_bytes = p->tx_bytes; + } while (u64_stats_fetch_retry_irq(&p->syncp, start)); + + stats->rx_packets += rx_packets; + stats->rx_bytes += rx_bytes; + stats->tx_packets += tx_packets; + stats->tx_bytes += tx_bytes; + /* tx_dropped is u32, updated without syncp protection. */ + tx_dropped += p->tx_dropped; + } + stats->tx_dropped = tx_dropped; + return stats; +} + +int mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid_begin, + u16 vid_end, bool is_member, bool untagged) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char *spvm_pl; + int err; + + spvm_pl = kmalloc(MLXSW_REG_SPVM_LEN, GFP_KERNEL); + if (!spvm_pl) + return -ENOMEM; + + mlxsw_reg_spvm_pack(spvm_pl, mlxsw_sp_port->local_port, vid_begin, + vid_end, is_member, untagged); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvm), spvm_pl); + kfree(spvm_pl); + return err; +} + +static int mlxsw_sp_port_vp_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port) +{ + enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID; + u16 vid, last_visited_vid; + int err; + + for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) { + err = mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, true, vid, + vid); + if (err) { + last_visited_vid = vid; + goto err_port_vid_to_fid_set; + } + } + + err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, true); + if (err) { + last_visited_vid = VLAN_N_VID; + goto err_port_vid_to_fid_set; + } + + return 0; + +err_port_vid_to_fid_set: + for_each_set_bit(vid, mlxsw_sp_port->active_vlans, last_visited_vid) + mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, false, vid, + vid); + return err; +} + +static int mlxsw_sp_port_vlan_mode_trans(struct mlxsw_sp_port *mlxsw_sp_port) +{ + enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID; + u16 vid; + int err; + + err = mlxsw_sp_port_vp_mode_set(mlxsw_sp_port, false); + if (err) + return err; + + for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) { + err = mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, false, + vid, vid); + if (err) + return err; + } + + return 0; +} + +int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 __always_unused proto, + u16 vid) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char *sftr_pl; + int err; + + /* VLAN 0 is added to HW filter when device goes up, but it is + * reserved in our case, so simply return. + */ + if (!vid) + return 0; + + if (test_bit(vid, mlxsw_sp_port->active_vfids)) { + netdev_warn(dev, "VID=%d already configured\n", vid); + return 0; + } + + if (!test_bit(vid, mlxsw_sp->active_vfids)) { + err = mlxsw_sp_vfid_create(mlxsw_sp, vid); + if (err) { + netdev_err(dev, "Failed to create vFID=%d\n", + MLXSW_SP_VFID_BASE + vid); + return err; + } + + sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL); + if (!sftr_pl) { + err = -ENOMEM; + goto err_flood_table_alloc; + } + mlxsw_reg_sftr_pack(sftr_pl, 0, vid, + MLXSW_REG_SFGC_TABLE_TYPE_FID, 0, + MLXSW_PORT_CPU_PORT, true); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); + kfree(sftr_pl); + if (err) { + netdev_err(dev, "Failed to configure flood table\n"); + goto err_flood_table_config; + } + } + + /* In case we fail in the following steps, we intentionally do not + * destroy the associated vFID. + */ + + /* When adding the first VLAN interface on a bridged port we need to + * transition all the active 802.1Q bridge VLANs to use explicit + * {Port, VID} to FID mappings and set the port's mode to Virtual mode. + */ + if (!mlxsw_sp_port->nr_vfids) { + err = mlxsw_sp_port_vp_mode_trans(mlxsw_sp_port); + if (err) { + netdev_err(dev, "Failed to set to Virtual mode\n"); + return err; + } + } + + err = mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, + MLXSW_REG_SVFA_MT_PORT_VID_TO_FID, + true, MLXSW_SP_VFID_BASE + vid, vid); + if (err) { + netdev_err(dev, "Failed to map {Port, VID=%d} to vFID=%d\n", + vid, MLXSW_SP_VFID_BASE + vid); + goto err_port_vid_to_fid_set; + } + + err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, false); + if (err) { + netdev_err(dev, "Failed to disable learning for VID=%d\n", vid); + goto err_port_vid_learning_set; + } + + err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, true, false); + if (err) { + netdev_err(dev, "Failed to set VLAN membership for VID=%d\n", + vid); + goto err_port_add_vid; + } + + err = mlxsw_sp_port_stp_state_set(mlxsw_sp_port, vid, + MLXSW_REG_SPMS_STATE_FORWARDING); + if (err) { + netdev_err(dev, "Failed to set STP state for VID=%d\n", vid); + goto err_port_stp_state_set; + } + + mlxsw_sp_port->nr_vfids++; + set_bit(vid, mlxsw_sp_port->active_vfids); + + return 0; + +err_flood_table_config: +err_flood_table_alloc: + mlxsw_sp_vfid_destroy(mlxsw_sp, vid); + return err; + +err_port_stp_state_set: + mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false); +err_port_add_vid: + mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true); +err_port_vid_learning_set: + mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, + MLXSW_REG_SVFA_MT_PORT_VID_TO_FID, false, + MLXSW_SP_VFID_BASE + vid, vid); +err_port_vid_to_fid_set: + mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port); + return err; +} + +int mlxsw_sp_port_kill_vid(struct net_device *dev, + __be16 __always_unused proto, u16 vid) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + int err; + + /* VLAN 0 is removed from HW filter when device goes down, but + * it is reserved in our case, so simply return. + */ + if (!vid) + return 0; + + if (!test_bit(vid, mlxsw_sp_port->active_vfids)) { + netdev_warn(dev, "VID=%d does not exist\n", vid); + return 0; + } + + err = mlxsw_sp_port_stp_state_set(mlxsw_sp_port, vid, + MLXSW_REG_SPMS_STATE_DISCARDING); + if (err) { + netdev_err(dev, "Failed to set STP state for VID=%d\n", vid); + return err; + } + + err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid, false, false); + if (err) { + netdev_err(dev, "Failed to set VLAN membership for VID=%d\n", + vid); + return err; + } + + err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true); + if (err) { + netdev_err(dev, "Failed to enable learning for VID=%d\n", vid); + return err; + } + + err = mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, + MLXSW_REG_SVFA_MT_PORT_VID_TO_FID, + false, MLXSW_SP_VFID_BASE + vid, + vid); + if (err) { + netdev_err(dev, "Failed to invalidate {Port, VID=%d} to vFID=%d mapping\n", + vid, MLXSW_SP_VFID_BASE + vid); + return err; + } + + /* When removing the last VLAN interface on a bridged port we need to + * transition all active 802.1Q bridge VLANs to use VID to FID + * mappings and set port's mode to VLAN mode. + */ + if (mlxsw_sp_port->nr_vfids == 1) { + err = mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port); + if (err) { + netdev_err(dev, "Failed to set to VLAN mode\n"); + return err; + } + } + + mlxsw_sp_port->nr_vfids--; + clear_bit(vid, mlxsw_sp_port->active_vfids); + + return 0; +} + +static const struct net_device_ops mlxsw_sp_port_netdev_ops = { + .ndo_open = mlxsw_sp_port_open, + .ndo_stop = mlxsw_sp_port_stop, + .ndo_start_xmit = mlxsw_sp_port_xmit, + .ndo_set_mac_address = mlxsw_sp_port_set_mac_address, + .ndo_change_mtu = mlxsw_sp_port_change_mtu, + .ndo_get_stats64 = mlxsw_sp_port_get_stats64, + .ndo_vlan_rx_add_vid = mlxsw_sp_port_add_vid, + .ndo_vlan_rx_kill_vid = mlxsw_sp_port_kill_vid, + .ndo_fdb_add = switchdev_port_fdb_add, + .ndo_fdb_del = switchdev_port_fdb_del, + .ndo_fdb_dump = switchdev_port_fdb_dump, + .ndo_bridge_setlink = switchdev_port_bridge_setlink, + .ndo_bridge_getlink = switchdev_port_bridge_getlink, + .ndo_bridge_dellink = switchdev_port_bridge_dellink, +}; + +static void mlxsw_sp_port_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + + strlcpy(drvinfo->driver, mlxsw_sp_driver_name, sizeof(drvinfo->driver)); + strlcpy(drvinfo->version, mlxsw_sp_driver_version, + sizeof(drvinfo->version)); + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), + "%d.%d.%d", + mlxsw_sp->bus_info->fw_rev.major, + mlxsw_sp->bus_info->fw_rev.minor, + mlxsw_sp->bus_info->fw_rev.subminor); + strlcpy(drvinfo->bus_info, mlxsw_sp->bus_info->device_name, + sizeof(drvinfo->bus_info)); +} + +struct mlxsw_sp_port_hw_stats { + char str[ETH_GSTRING_LEN]; + u64 (*getter)(char *payload); +}; + +static const struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_stats[] = { + { + .str = "a_frames_transmitted_ok", + .getter = mlxsw_reg_ppcnt_a_frames_transmitted_ok_get, + }, + { + .str = "a_frames_received_ok", + .getter = mlxsw_reg_ppcnt_a_frames_received_ok_get, + }, + { + .str = "a_frame_check_sequence_errors", + .getter = mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get, + }, + { + .str = "a_alignment_errors", + .getter = mlxsw_reg_ppcnt_a_alignment_errors_get, + }, + { + .str = "a_octets_transmitted_ok", + .getter = mlxsw_reg_ppcnt_a_octets_transmitted_ok_get, + }, + { + .str = "a_octets_received_ok", + .getter = mlxsw_reg_ppcnt_a_octets_received_ok_get, + }, + { + .str = "a_multicast_frames_xmitted_ok", + .getter = mlxsw_reg_ppcnt_a_multicast_frames_xmitted_ok_get, + }, + { + .str = "a_broadcast_frames_xmitted_ok", + .getter = mlxsw_reg_ppcnt_a_broadcast_frames_xmitted_ok_get, + }, + { + .str = "a_multicast_frames_received_ok", + .getter = mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get, + }, + { + .str = "a_broadcast_frames_received_ok", + .getter = mlxsw_reg_ppcnt_a_broadcast_frames_received_ok_get, + }, + { + .str = "a_in_range_length_errors", + .getter = mlxsw_reg_ppcnt_a_in_range_length_errors_get, + }, + { + .str = "a_out_of_range_length_field", + .getter = mlxsw_reg_ppcnt_a_out_of_range_length_field_get, + }, + { + .str = "a_frame_too_long_errors", + .getter = mlxsw_reg_ppcnt_a_frame_too_long_errors_get, + }, + { + .str = "a_symbol_error_during_carrier", + .getter = mlxsw_reg_ppcnt_a_symbol_error_during_carrier_get, + }, + { + .str = "a_mac_control_frames_transmitted", + .getter = mlxsw_reg_ppcnt_a_mac_control_frames_transmitted_get, + }, + { + .str = "a_mac_control_frames_received", + .getter = mlxsw_reg_ppcnt_a_mac_control_frames_received_get, + }, + { + .str = "a_unsupported_opcodes_received", + .getter = mlxsw_reg_ppcnt_a_unsupported_opcodes_received_get, + }, + { + .str = "a_pause_mac_ctrl_frames_received", + .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_received_get, + }, + { + .str = "a_pause_mac_ctrl_frames_xmitted", + .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_transmitted_get, + }, +}; + +#define MLXSW_SP_PORT_HW_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_stats) + +static void mlxsw_sp_port_get_strings(struct net_device *dev, + u32 stringset, u8 *data) +{ + u8 *p = data; + int i; + + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < MLXSW_SP_PORT_HW_STATS_LEN; i++) { + memcpy(p, mlxsw_sp_port_hw_stats[i].str, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } + break; + } +} + +static void mlxsw_sp_port_get_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char ppcnt_pl[MLXSW_REG_PPCNT_LEN]; + int i; + int err; + + mlxsw_reg_ppcnt_pack(ppcnt_pl, mlxsw_sp_port->local_port); + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ppcnt), ppcnt_pl); + for (i = 0; i < MLXSW_SP_PORT_HW_STATS_LEN; i++) + data[i] = !err ? mlxsw_sp_port_hw_stats[i].getter(ppcnt_pl) : 0; +} + +static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset) +{ + switch (sset) { + case ETH_SS_STATS: + return MLXSW_SP_PORT_HW_STATS_LEN; + default: + return -EOPNOTSUPP; + } +} + +struct mlxsw_sp_port_link_mode { + u32 mask; + u32 supported; + u32 advertised; + u32 speed; +}; + +static const struct mlxsw_sp_port_link_mode mlxsw_sp_port_link_mode[] = { + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T, + .supported = SUPPORTED_100baseT_Full, + .advertised = ADVERTISED_100baseT_Full, + .speed = 100, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_TX, + .speed = 100, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_SGMII | + MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX, + .supported = SUPPORTED_1000baseKX_Full, + .advertised = ADVERTISED_1000baseKX_Full, + .speed = 1000, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_T, + .supported = SUPPORTED_10000baseT_Full, + .advertised = ADVERTISED_10000baseT_Full, + .speed = 10000, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 | + MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4, + .supported = SUPPORTED_10000baseKX4_Full, + .advertised = ADVERTISED_10000baseKX4_Full, + .speed = 10000, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR | + MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | + MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR | + MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR, + .supported = SUPPORTED_10000baseKR_Full, + .advertised = ADVERTISED_10000baseKR_Full, + .speed = 10000, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_20GBASE_KR2, + .supported = SUPPORTED_20000baseKR2_Full, + .advertised = ADVERTISED_20000baseKR2_Full, + .speed = 20000, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4, + .supported = SUPPORTED_40000baseCR4_Full, + .advertised = ADVERTISED_40000baseCR4_Full, + .speed = 40000, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4, + .supported = SUPPORTED_40000baseKR4_Full, + .advertised = ADVERTISED_40000baseKR4_Full, + .speed = 40000, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4, + .supported = SUPPORTED_40000baseSR4_Full, + .advertised = ADVERTISED_40000baseSR4_Full, + .speed = 40000, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4, + .supported = SUPPORTED_40000baseLR4_Full, + .advertised = ADVERTISED_40000baseLR4_Full, + .speed = 40000, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR | + MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR | + MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR, + .speed = 25000, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR4 | + MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2 | + MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2, + .speed = 50000, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_56GBASE_R4, + .supported = SUPPORTED_56000baseKR4_Full, + .advertised = ADVERTISED_56000baseKR4_Full, + .speed = 56000, + }, + { + .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4 | + MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 | + MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 | + MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4, + .speed = 100000, + }, +}; + +#define MLXSW_SP_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp_port_link_mode) + +static u32 mlxsw_sp_from_ptys_supported_port(u32 ptys_eth_proto) +{ + if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | + MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR | + MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 | + MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 | + MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 | + MLXSW_REG_PTYS_ETH_SPEED_SGMII)) + return SUPPORTED_FIBRE; + + if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR | + MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 | + MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 | + MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 | + MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX)) + return SUPPORTED_Backplane; + return 0; +} + +static u32 mlxsw_sp_from_ptys_supported_link(u32 ptys_eth_proto) +{ + u32 modes = 0; + int i; + + for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) { + if (ptys_eth_proto & mlxsw_sp_port_link_mode[i].mask) + modes |= mlxsw_sp_port_link_mode[i].supported; + } + return modes; +} + +static u32 mlxsw_sp_from_ptys_advert_link(u32 ptys_eth_proto) +{ + u32 modes = 0; + int i; + + for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) { + if (ptys_eth_proto & mlxsw_sp_port_link_mode[i].mask) + modes |= mlxsw_sp_port_link_mode[i].advertised; + } + return modes; +} + +static void mlxsw_sp_from_ptys_speed_duplex(bool carrier_ok, u32 ptys_eth_proto, + struct ethtool_cmd *cmd) +{ + u32 speed = SPEED_UNKNOWN; + u8 duplex = DUPLEX_UNKNOWN; + int i; + + if (!carrier_ok) + goto out; + + for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) { + if (ptys_eth_proto & mlxsw_sp_port_link_mode[i].mask) { + speed = mlxsw_sp_port_link_mode[i].speed; + duplex = DUPLEX_FULL; + break; + } + } +out: + ethtool_cmd_speed_set(cmd, speed); + cmd->duplex = duplex; +} + +static u8 mlxsw_sp_port_connector_port(u32 ptys_eth_proto) +{ + if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR | + MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 | + MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 | + MLXSW_REG_PTYS_ETH_SPEED_SGMII)) + return PORT_FIBRE; + + if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | + MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 | + MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4)) + return PORT_DA; + + if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR | + MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 | + MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 | + MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4)) + return PORT_NONE; + + return PORT_OTHER; +} + +static int mlxsw_sp_port_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char ptys_pl[MLXSW_REG_PTYS_LEN]; + u32 eth_proto_cap; + u32 eth_proto_admin; + u32 eth_proto_oper; + int err; + + mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0); + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); + if (err) { + netdev_err(dev, "Failed to get proto"); + return err; + } + mlxsw_reg_ptys_unpack(ptys_pl, ð_proto_cap, + ð_proto_admin, ð_proto_oper); + + cmd->supported = mlxsw_sp_from_ptys_supported_port(eth_proto_cap) | + mlxsw_sp_from_ptys_supported_link(eth_proto_cap) | + SUPPORTED_Pause | SUPPORTED_Asym_Pause; + cmd->advertising = mlxsw_sp_from_ptys_advert_link(eth_proto_admin); + mlxsw_sp_from_ptys_speed_duplex(netif_carrier_ok(dev), + eth_proto_oper, cmd); + + eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap; + cmd->port = mlxsw_sp_port_connector_port(eth_proto_oper); + cmd->lp_advertising = mlxsw_sp_from_ptys_advert_link(eth_proto_oper); + + cmd->transceiver = XCVR_INTERNAL; + return 0; +} + +static u32 mlxsw_sp_to_ptys_advert_link(u32 advertising) +{ + u32 ptys_proto = 0; + int i; + + for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) { + if (advertising & mlxsw_sp_port_link_mode[i].advertised) + ptys_proto |= mlxsw_sp_port_link_mode[i].mask; + } + return ptys_proto; +} + +static u32 mlxsw_sp_to_ptys_speed(u32 speed) +{ + u32 ptys_proto = 0; + int i; + + for (i = 0; i < MLXSW_SP_PORT_LINK_MODE_LEN; i++) { + if (speed == mlxsw_sp_port_link_mode[i].speed) + ptys_proto |= mlxsw_sp_port_link_mode[i].mask; + } + return ptys_proto; +} + +static int mlxsw_sp_port_set_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char ptys_pl[MLXSW_REG_PTYS_LEN]; + u32 speed; + u32 eth_proto_new; + u32 eth_proto_cap; + u32 eth_proto_admin; + bool is_up; + int err; + + speed = ethtool_cmd_speed(cmd); + + eth_proto_new = cmd->autoneg == AUTONEG_ENABLE ? + mlxsw_sp_to_ptys_advert_link(cmd->advertising) : + mlxsw_sp_to_ptys_speed(speed); + + mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0); + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); + if (err) { + netdev_err(dev, "Failed to get proto"); + return err; + } + mlxsw_reg_ptys_unpack(ptys_pl, ð_proto_cap, ð_proto_admin, NULL); + + eth_proto_new = eth_proto_new & eth_proto_cap; + if (!eth_proto_new) { + netdev_err(dev, "Not supported proto admin requested"); + return -EINVAL; + } + if (eth_proto_new == eth_proto_admin) + return 0; + + mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, eth_proto_new); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); + if (err) { + netdev_err(dev, "Failed to set proto admin"); + return err; + } + + err = mlxsw_sp_port_oper_status_get(mlxsw_sp_port, &is_up); + if (err) { + netdev_err(dev, "Failed to get oper status"); + return err; + } + if (!is_up) + return 0; + + err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false); + if (err) { + netdev_err(dev, "Failed to set admin status"); + return err; + } + + err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true); + if (err) { + netdev_err(dev, "Failed to set admin status"); + return err; + } + + return 0; +} + +static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = { + .get_drvinfo = mlxsw_sp_port_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_strings = mlxsw_sp_port_get_strings, + .get_ethtool_stats = mlxsw_sp_port_get_stats, + .get_sset_count = mlxsw_sp_port_get_sset_count, + .get_settings = mlxsw_sp_port_get_settings, + .set_settings = mlxsw_sp_port_set_settings, +}; + +static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port) +{ + struct mlxsw_sp_port *mlxsw_sp_port; + struct net_device *dev; + bool usable; + int err; + + dev = alloc_etherdev(sizeof(struct mlxsw_sp_port)); + if (!dev) + return -ENOMEM; + mlxsw_sp_port = netdev_priv(dev); + mlxsw_sp_port->dev = dev; + mlxsw_sp_port->mlxsw_sp = mlxsw_sp; + mlxsw_sp_port->local_port = local_port; + mlxsw_sp_port->learning = 1; + mlxsw_sp_port->learning_sync = 1; + mlxsw_sp_port->pvid = 1; + + mlxsw_sp_port->pcpu_stats = + netdev_alloc_pcpu_stats(struct mlxsw_sp_port_pcpu_stats); + if (!mlxsw_sp_port->pcpu_stats) { + err = -ENOMEM; + goto err_alloc_stats; + } + + dev->netdev_ops = &mlxsw_sp_port_netdev_ops; + dev->ethtool_ops = &mlxsw_sp_port_ethtool_ops; + + err = mlxsw_sp_port_dev_addr_init(mlxsw_sp_port); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Unable to init port mac address\n", + mlxsw_sp_port->local_port); + goto err_dev_addr_init; + } + + netif_carrier_off(dev); + + dev->features |= NETIF_F_NETNS_LOCAL | NETIF_F_LLTX | NETIF_F_SG | + NETIF_F_HW_VLAN_CTAG_FILTER; + + /* Each packet needs to have a Tx header (metadata) on top all other + * headers. + */ + dev->hard_header_len += MLXSW_TXHDR_LEN; + + err = mlxsw_sp_port_module_check(mlxsw_sp_port, &usable); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to check module\n", + mlxsw_sp_port->local_port); + goto err_port_module_check; + } + + if (!usable) { + dev_dbg(mlxsw_sp->bus_info->dev, "Port %d: Not usable, skipping initialization\n", + mlxsw_sp_port->local_port); + goto port_not_usable; + } + + err = mlxsw_sp_port_system_port_mapping_set(mlxsw_sp_port); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set system port mapping\n", + mlxsw_sp_port->local_port); + goto err_port_system_port_mapping_set; + } + + err = mlxsw_sp_port_swid_set(mlxsw_sp_port, 0); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set SWID\n", + mlxsw_sp_port->local_port); + goto err_port_swid_set; + } + + err = mlxsw_sp_port_mtu_set(mlxsw_sp_port, ETH_DATA_LEN); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to set MTU\n", + mlxsw_sp_port->local_port); + goto err_port_mtu_set; + } + + err = mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false); + if (err) + goto err_port_admin_status_set; + + err = mlxsw_sp_port_buffers_init(mlxsw_sp_port); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to initialize buffers\n", + mlxsw_sp_port->local_port); + goto err_port_buffers_init; + } + + mlxsw_sp_port_switchdev_init(mlxsw_sp_port); + err = register_netdev(dev); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to register netdev\n", + mlxsw_sp_port->local_port); + goto err_register_netdev; + } + + err = mlxsw_sp_port_vlan_init(mlxsw_sp_port); + if (err) + goto err_port_vlan_init; + + mlxsw_sp->ports[local_port] = mlxsw_sp_port; + return 0; + +err_port_vlan_init: + unregister_netdev(dev); +err_register_netdev: +err_port_buffers_init: +err_port_admin_status_set: +err_port_mtu_set: +err_port_swid_set: +err_port_system_port_mapping_set: +port_not_usable: +err_port_module_check: +err_dev_addr_init: + free_percpu(mlxsw_sp_port->pcpu_stats); +err_alloc_stats: + free_netdev(dev); + return err; +} + +static void mlxsw_sp_vfids_fini(struct mlxsw_sp *mlxsw_sp) +{ + u16 vfid; + + for_each_set_bit(vfid, mlxsw_sp->active_vfids, VLAN_N_VID) + mlxsw_sp_vfid_destroy(mlxsw_sp, vfid); +} + +static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) +{ + struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port]; + + if (!mlxsw_sp_port) + return; + mlxsw_sp_port_kill_vid(mlxsw_sp_port->dev, 0, 1); + unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */ + mlxsw_sp_port_switchdev_fini(mlxsw_sp_port); + free_percpu(mlxsw_sp_port->pcpu_stats); + free_netdev(mlxsw_sp_port->dev); +} + +static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp) +{ + int i; + + for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) + mlxsw_sp_port_remove(mlxsw_sp, i); + kfree(mlxsw_sp->ports); +} + +static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp) +{ + size_t alloc_size; + int i; + int err; + + alloc_size = sizeof(struct mlxsw_sp_port *) * MLXSW_PORT_MAX_PORTS; + mlxsw_sp->ports = kzalloc(alloc_size, GFP_KERNEL); + if (!mlxsw_sp->ports) + return -ENOMEM; + + for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) { + err = mlxsw_sp_port_create(mlxsw_sp, i); + if (err) + goto err_port_create; + } + return 0; + +err_port_create: + for (i--; i >= 1; i--) + mlxsw_sp_port_remove(mlxsw_sp, i); + kfree(mlxsw_sp->ports); + return err; +} + +static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg, + char *pude_pl, void *priv) +{ + struct mlxsw_sp *mlxsw_sp = priv; + struct mlxsw_sp_port *mlxsw_sp_port; + enum mlxsw_reg_pude_oper_status status; + u8 local_port; + + local_port = mlxsw_reg_pude_local_port_get(pude_pl); + mlxsw_sp_port = mlxsw_sp->ports[local_port]; + if (!mlxsw_sp_port) { + dev_warn(mlxsw_sp->bus_info->dev, "Port %d: Link event received for non-existent port\n", + local_port); + return; + } + + status = mlxsw_reg_pude_oper_status_get(pude_pl); + if (status == MLXSW_PORT_OPER_STATUS_UP) { + netdev_info(mlxsw_sp_port->dev, "link up\n"); + netif_carrier_on(mlxsw_sp_port->dev); + } else { + netdev_info(mlxsw_sp_port->dev, "link down\n"); + netif_carrier_off(mlxsw_sp_port->dev); + } +} + +static struct mlxsw_event_listener mlxsw_sp_pude_event = { + .func = mlxsw_sp_pude_event_func, + .trap_id = MLXSW_TRAP_ID_PUDE, +}; + +static int mlxsw_sp_event_register(struct mlxsw_sp *mlxsw_sp, + enum mlxsw_event_trap_id trap_id) +{ + struct mlxsw_event_listener *el; + char hpkt_pl[MLXSW_REG_HPKT_LEN]; + int err; + + switch (trap_id) { + case MLXSW_TRAP_ID_PUDE: + el = &mlxsw_sp_pude_event; + break; + } + err = mlxsw_core_event_listener_register(mlxsw_sp->core, el, mlxsw_sp); + if (err) + return err; + + mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, trap_id); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl); + if (err) + goto err_event_trap_set; + + return 0; + +err_event_trap_set: + mlxsw_core_event_listener_unregister(mlxsw_sp->core, el, mlxsw_sp); + return err; +} + +static void mlxsw_sp_event_unregister(struct mlxsw_sp *mlxsw_sp, + enum mlxsw_event_trap_id trap_id) +{ + struct mlxsw_event_listener *el; + + switch (trap_id) { + case MLXSW_TRAP_ID_PUDE: + el = &mlxsw_sp_pude_event; + break; + } + mlxsw_core_event_listener_unregister(mlxsw_sp->core, el, mlxsw_sp); +} + +static void mlxsw_sp_rx_listener_func(struct sk_buff *skb, u8 local_port, + void *priv) +{ + struct mlxsw_sp *mlxsw_sp = priv; + struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port]; + struct mlxsw_sp_port_pcpu_stats *pcpu_stats; + + if (unlikely(!mlxsw_sp_port)) { + dev_warn_ratelimited(mlxsw_sp->bus_info->dev, "Port %d: skb received for non-existent port\n", + local_port); + return; + } + + skb->dev = mlxsw_sp_port->dev; + + pcpu_stats = this_cpu_ptr(mlxsw_sp_port->pcpu_stats); + u64_stats_update_begin(&pcpu_stats->syncp); + pcpu_stats->rx_packets++; + pcpu_stats->rx_bytes += skb->len; + u64_stats_update_end(&pcpu_stats->syncp); + + skb->protocol = eth_type_trans(skb, skb->dev); + netif_receive_skb(skb); +} + +static const struct mlxsw_rx_listener mlxsw_sp_rx_listener[] = { + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_FDB_MC, + }, + /* Traps for specific L2 packet types, not trapped as FDB MC */ + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_STP, + }, + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_LACP, + }, + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_EAPOL, + }, + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_LLDP, + }, + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_MMRP, + }, + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_MVRP, + }, + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_RPVST, + }, + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_DHCP, + }, + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_IGMP_QUERY, + }, + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_IGMP_V1_REPORT, + }, + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_IGMP_V2_REPORT, + }, + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_IGMP_V2_LEAVE, + }, + { + .func = mlxsw_sp_rx_listener_func, + .local_port = MLXSW_PORT_DONT_CARE, + .trap_id = MLXSW_TRAP_ID_IGMP_V3_REPORT, + }, +}; + +static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp) +{ + char htgt_pl[MLXSW_REG_HTGT_LEN]; + char hpkt_pl[MLXSW_REG_HPKT_LEN]; + int i; + int err; + + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_RX); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl); + if (err) + return err; + + mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_CTRL); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl); + if (err) + return err; + + for (i = 0; i < ARRAY_SIZE(mlxsw_sp_rx_listener); i++) { + err = mlxsw_core_rx_listener_register(mlxsw_sp->core, + &mlxsw_sp_rx_listener[i], + mlxsw_sp); + if (err) + goto err_rx_listener_register; + + mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU, + mlxsw_sp_rx_listener[i].trap_id); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl); + if (err) + goto err_rx_trap_set; + } + return 0; + +err_rx_trap_set: + mlxsw_core_rx_listener_unregister(mlxsw_sp->core, + &mlxsw_sp_rx_listener[i], + mlxsw_sp); +err_rx_listener_register: + for (i--; i >= 0; i--) { + mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, + mlxsw_sp_rx_listener[i].trap_id); + mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl); + + mlxsw_core_rx_listener_unregister(mlxsw_sp->core, + &mlxsw_sp_rx_listener[i], + mlxsw_sp); + } + return err; +} + +static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp) +{ + char hpkt_pl[MLXSW_REG_HPKT_LEN]; + int i; + + for (i = 0; i < ARRAY_SIZE(mlxsw_sp_rx_listener); i++) { + mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, + mlxsw_sp_rx_listener[i].trap_id); + mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl); + + mlxsw_core_rx_listener_unregister(mlxsw_sp->core, + &mlxsw_sp_rx_listener[i], + mlxsw_sp); + } +} + +static int __mlxsw_sp_flood_init(struct mlxsw_core *mlxsw_core, + enum mlxsw_reg_sfgc_type type, + enum mlxsw_reg_sfgc_bridge_type bridge_type) +{ + enum mlxsw_flood_table_type table_type; + enum mlxsw_sp_flood_table flood_table; + char sfgc_pl[MLXSW_REG_SFGC_LEN]; + + if (bridge_type == MLXSW_REG_SFGC_BRIDGE_TYPE_VFID) { + table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID; + flood_table = 0; + } else { + table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST; + if (type == MLXSW_REG_SFGC_TYPE_UNKNOWN_UNICAST) + flood_table = MLXSW_SP_FLOOD_TABLE_UC; + else + flood_table = MLXSW_SP_FLOOD_TABLE_BM; + } + + mlxsw_reg_sfgc_pack(sfgc_pl, type, bridge_type, table_type, + flood_table); + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(sfgc), sfgc_pl); +} + +static int mlxsw_sp_flood_init(struct mlxsw_sp *mlxsw_sp) +{ + int type, err; + + /* For non-offloaded netdevs, flood all traffic types to CPU + * port. + */ + for (type = 0; type < MLXSW_REG_SFGC_TYPE_MAX; type++) { + if (type == MLXSW_REG_SFGC_TYPE_RESERVED) + continue; + + err = __mlxsw_sp_flood_init(mlxsw_sp->core, type, + MLXSW_REG_SFGC_BRIDGE_TYPE_VFID); + if (err) + return err; + } + + /* For bridged ports, use one flooding table for unknown unicast + * traffic and a second table for unregistered multicast and + * broadcast. + */ + for (type = 0; type < MLXSW_REG_SFGC_TYPE_MAX; type++) { + if (type == MLXSW_REG_SFGC_TYPE_RESERVED) + continue; + + err = __mlxsw_sp_flood_init(mlxsw_sp->core, type, + MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID); + if (err) + return err; + } + + return 0; +} + +static int mlxsw_sp_init(void *priv, struct mlxsw_core *mlxsw_core, + const struct mlxsw_bus_info *mlxsw_bus_info) +{ + struct mlxsw_sp *mlxsw_sp = priv; + int err; + + mlxsw_sp->core = mlxsw_core; + mlxsw_sp->bus_info = mlxsw_bus_info; + + err = mlxsw_sp_base_mac_get(mlxsw_sp); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Failed to get base mac\n"); + return err; + } + + err = mlxsw_sp_ports_create(mlxsw_sp); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Failed to create ports\n"); + goto err_ports_create; + } + + err = mlxsw_sp_event_register(mlxsw_sp, MLXSW_TRAP_ID_PUDE); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Failed to register for PUDE events\n"); + goto err_event_register; + } + + err = mlxsw_sp_traps_init(mlxsw_sp); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Failed to set traps for RX\n"); + goto err_rx_listener_register; + } + + err = mlxsw_sp_flood_init(mlxsw_sp); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize flood tables\n"); + goto err_flood_init; + } + + err = mlxsw_sp_buffers_init(mlxsw_sp); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize buffers\n"); + goto err_buffers_init; + } + + err = mlxsw_sp_switchdev_init(mlxsw_sp); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize switchdev\n"); + goto err_switchdev_init; + } + + return 0; + +err_switchdev_init: +err_buffers_init: +err_flood_init: + mlxsw_sp_traps_fini(mlxsw_sp); +err_rx_listener_register: + mlxsw_sp_event_unregister(mlxsw_sp, MLXSW_TRAP_ID_PUDE); +err_event_register: + mlxsw_sp_ports_remove(mlxsw_sp); +err_ports_create: + mlxsw_sp_vfids_fini(mlxsw_sp); + return err; +} + +static void mlxsw_sp_fini(void *priv) +{ + struct mlxsw_sp *mlxsw_sp = priv; + + mlxsw_sp_switchdev_fini(mlxsw_sp); + mlxsw_sp_traps_fini(mlxsw_sp); + mlxsw_sp_event_unregister(mlxsw_sp, MLXSW_TRAP_ID_PUDE); + mlxsw_sp_ports_remove(mlxsw_sp); + mlxsw_sp_vfids_fini(mlxsw_sp); +} + +static struct mlxsw_config_profile mlxsw_sp_config_profile = { + .used_max_vepa_channels = 1, + .max_vepa_channels = 0, + .used_max_lag = 1, + .max_lag = 64, + .used_max_port_per_lag = 1, + .max_port_per_lag = 16, + .used_max_mid = 1, + .max_mid = 7000, + .used_max_pgt = 1, + .max_pgt = 0, + .used_max_system_port = 1, + .max_system_port = 64, + .used_max_vlan_groups = 1, + .max_vlan_groups = 127, + .used_max_regions = 1, + .max_regions = 400, + .used_flood_tables = 1, + .used_flood_mode = 1, + .flood_mode = 3, + .max_fid_offset_flood_tables = 2, + .fid_offset_flood_table_size = VLAN_N_VID - 1, + .max_fid_flood_tables = 1, + .fid_flood_table_size = VLAN_N_VID, + .used_max_ib_mc = 1, + .max_ib_mc = 0, + .used_max_pkey = 1, + .max_pkey = 0, + .swid_config = { + { + .used_type = 1, + .type = MLXSW_PORT_SWID_TYPE_ETH, + } + }, +}; + +static struct mlxsw_driver mlxsw_sp_driver = { + .kind = MLXSW_DEVICE_KIND_SPECTRUM, + .owner = THIS_MODULE, + .priv_size = sizeof(struct mlxsw_sp), + .init = mlxsw_sp_init, + .fini = mlxsw_sp_fini, + .txhdr_construct = mlxsw_sp_txhdr_construct, + .txhdr_len = MLXSW_TXHDR_LEN, + .profile = &mlxsw_sp_config_profile, +}; + +static bool mlxsw_sp_port_dev_check(const struct net_device *dev) +{ + return dev->netdev_ops == &mlxsw_sp_port_netdev_ops; +} + +static int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port) +{ + struct net_device *dev = mlxsw_sp_port->dev; + int err; + + /* When port is not bridged untagged packets are tagged with + * PVID=VID=1, thereby creating an implicit VLAN interface in + * the device. Remove it and let bridge code take care of its + * own VLANs. + */ + err = mlxsw_sp_port_kill_vid(dev, 0, 1); + if (err) + netdev_err(dev, "Failed to remove VID 1\n"); + + return err; +} + +static int mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port) +{ + struct net_device *dev = mlxsw_sp_port->dev; + int err; + + /* Add implicit VLAN interface in the device, so that untagged + * packets will be classified to the default vFID. + */ + err = mlxsw_sp_port_add_vid(dev, 0, 1); + if (err) + netdev_err(dev, "Failed to add VID 1\n"); + + return err; +} + +static bool mlxsw_sp_master_bridge_check(struct mlxsw_sp *mlxsw_sp, + struct net_device *br_dev) +{ + return !mlxsw_sp->master_bridge.dev || + mlxsw_sp->master_bridge.dev == br_dev; +} + +static void mlxsw_sp_master_bridge_inc(struct mlxsw_sp *mlxsw_sp, + struct net_device *br_dev) +{ + mlxsw_sp->master_bridge.dev = br_dev; + mlxsw_sp->master_bridge.ref_count++; +} + +static void mlxsw_sp_master_bridge_dec(struct mlxsw_sp *mlxsw_sp, + struct net_device *br_dev) +{ + if (--mlxsw_sp->master_bridge.ref_count == 0) + mlxsw_sp->master_bridge.dev = NULL; +} + +static int mlxsw_sp_netdevice_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct netdev_notifier_changeupper_info *info; + struct mlxsw_sp_port *mlxsw_sp_port; + struct net_device *upper_dev; + struct mlxsw_sp *mlxsw_sp; + int err; + + if (!mlxsw_sp_port_dev_check(dev)) + return NOTIFY_DONE; + + mlxsw_sp_port = netdev_priv(dev); + mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + info = ptr; + + switch (event) { + case NETDEV_PRECHANGEUPPER: + upper_dev = info->upper_dev; + /* HW limitation forbids to put ports to multiple bridges. */ + if (info->master && info->linking && + netif_is_bridge_master(upper_dev) && + !mlxsw_sp_master_bridge_check(mlxsw_sp, upper_dev)) + return NOTIFY_BAD; + break; + case NETDEV_CHANGEUPPER: + upper_dev = info->upper_dev; + if (info->master && + netif_is_bridge_master(upper_dev)) { + if (info->linking) { + err = mlxsw_sp_port_bridge_join(mlxsw_sp_port); + if (err) + netdev_err(dev, "Failed to join bridge\n"); + mlxsw_sp_master_bridge_inc(mlxsw_sp, upper_dev); + mlxsw_sp_port->bridged = true; + } else { + err = mlxsw_sp_port_bridge_leave(mlxsw_sp_port); + if (err) + netdev_err(dev, "Failed to leave bridge\n"); + mlxsw_sp_port->bridged = false; + mlxsw_sp_master_bridge_dec(mlxsw_sp, upper_dev); + } + } + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block mlxsw_sp_netdevice_nb __read_mostly = { + .notifier_call = mlxsw_sp_netdevice_event, +}; + +static int __init mlxsw_sp_module_init(void) +{ + int err; + + register_netdevice_notifier(&mlxsw_sp_netdevice_nb); + err = mlxsw_core_driver_register(&mlxsw_sp_driver); + if (err) + goto err_core_driver_register; + return 0; + +err_core_driver_register: + unregister_netdevice_notifier(&mlxsw_sp_netdevice_nb); + return err; +} + +static void __exit mlxsw_sp_module_exit(void) +{ + mlxsw_core_driver_unregister(&mlxsw_sp_driver); + unregister_netdevice_notifier(&mlxsw_sp_netdevice_nb); +} + +module_init(mlxsw_sp_module_init); +module_exit(mlxsw_sp_module_exit); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Jiri Pirko "); +MODULE_DESCRIPTION("Mellanox Spectrum driver"); +MODULE_MLXSW_DRIVER_ALIAS(MLXSW_DEVICE_KIND_SPECTRUM); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h new file mode 100644 index 000000000000..fc0074902ab5 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -0,0 +1,121 @@ +/* + * drivers/net/ethernet/mellanox/mlxsw/spectrum.h + * Copyright (c) 2015 Mellanox Technologies. All rights reserved. + * Copyright (c) 2015 Jiri Pirko + * Copyright (c) 2015 Ido Schimmel + * Copyright (c) 2015 Elad Raz + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MLXSW_SPECTRUM_H +#define _MLXSW_SPECTRUM_H + +#include +#include +#include +#include +#include + +#include "core.h" + +#define MLXSW_SP_VFID_BASE VLAN_N_VID + +struct mlxsw_sp_port; + +struct mlxsw_sp { + unsigned long active_vfids[BITS_TO_LONGS(VLAN_N_VID)]; + unsigned long active_fids[BITS_TO_LONGS(VLAN_N_VID)]; + struct mlxsw_sp_port **ports; + struct mlxsw_core *core; + const struct mlxsw_bus_info *bus_info; + unsigned char base_mac[ETH_ALEN]; + struct { + struct delayed_work dw; +#define MLXSW_SP_DEFAULT_LEARNING_INTERVAL 100 + unsigned int interval; /* ms */ + } fdb_notify; +#define MLXSW_SP_DEFAULT_AGEING_TIME 300 + u32 ageing_time; + struct { + struct net_device *dev; + unsigned int ref_count; + } master_bridge; +}; + +struct mlxsw_sp_port_pcpu_stats { + u64 rx_packets; + u64 rx_bytes; + u64 tx_packets; + u64 tx_bytes; + struct u64_stats_sync syncp; + u32 tx_dropped; +}; + +struct mlxsw_sp_port { + struct net_device *dev; + struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats; + struct mlxsw_sp *mlxsw_sp; + u8 local_port; + u8 stp_state; + u8 learning:1; + u8 learning_sync:1; + u16 pvid; + bool bridged; + /* 802.1Q bridge VLANs */ + unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; + /* VLAN interfaces */ + unsigned long active_vfids[BITS_TO_LONGS(VLAN_N_VID)]; + u16 nr_vfids; +}; + +enum mlxsw_sp_flood_table { + MLXSW_SP_FLOOD_TABLE_UC, + MLXSW_SP_FLOOD_TABLE_BM, +}; + +int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp); +int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port); + +int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp); +void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp); +int mlxsw_sp_port_vlan_init(struct mlxsw_sp_port *mlxsw_sp_port); +void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port); +void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port); +int mlxsw_sp_port_vid_to_fid_set(struct mlxsw_sp_port *mlxsw_sp_port, + enum mlxsw_reg_svfa_mt mt, bool valid, u16 fid, + u16 vid); +int mlxsw_sp_port_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid_begin, + u16 vid_end, bool is_member, bool untagged); +int mlxsw_sp_port_add_vid(struct net_device *dev, __be16 __always_unused proto, + u16 vid); +int mlxsw_sp_port_kill_vid(struct net_device *dev, + __be16 __always_unused proto, u16 vid); + +#endif diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c new file mode 100644 index 000000000000..d59195e3f7fb --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c @@ -0,0 +1,422 @@ +/* + * drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c + * Copyright (c) 2015 Mellanox Technologies. All rights reserved. + * Copyright (c) 2015 Jiri Pirko + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "spectrum.h" +#include "core.h" +#include "port.h" +#include "reg.h" + +struct mlxsw_sp_pb { + u8 index; + u16 size; +}; + +#define MLXSW_SP_PB(_index, _size) \ + { \ + .index = _index, \ + .size = _size, \ + } + +static const struct mlxsw_sp_pb mlxsw_sp_pbs[] = { + MLXSW_SP_PB(0, 208), + MLXSW_SP_PB(1, 208), + MLXSW_SP_PB(2, 208), + MLXSW_SP_PB(3, 208), + MLXSW_SP_PB(4, 208), + MLXSW_SP_PB(5, 208), + MLXSW_SP_PB(6, 208), + MLXSW_SP_PB(7, 208), + MLXSW_SP_PB(9, 208), +}; + +#define MLXSW_SP_PBS_LEN ARRAY_SIZE(mlxsw_sp_pbs) + +static int mlxsw_sp_port_pb_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + char pbmc_pl[MLXSW_REG_PBMC_LEN]; + int i; + + mlxsw_reg_pbmc_pack(pbmc_pl, mlxsw_sp_port->local_port, + 0xffff, 0xffff / 2); + for (i = 0; i < MLXSW_SP_PBS_LEN; i++) { + const struct mlxsw_sp_pb *pb; + + pb = &mlxsw_sp_pbs[i]; + mlxsw_reg_pbmc_lossy_buffer_pack(pbmc_pl, pb->index, pb->size); + } + return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, + MLXSW_REG(pbmc), pbmc_pl); +} + +#define MLXSW_SP_SB_BYTES_PER_CELL 96 + +struct mlxsw_sp_sb_pool { + u8 pool; + enum mlxsw_reg_sbpr_dir dir; + enum mlxsw_reg_sbpr_mode mode; + u32 size; +}; + +#define MLXSW_SP_SB_POOL_INGRESS_SIZE \ + ((15000000 - (2 * 20000 * MLXSW_PORT_MAX_PORTS)) / \ + MLXSW_SP_SB_BYTES_PER_CELL) +#define MLXSW_SP_SB_POOL_EGRESS_SIZE \ + ((14000000 - (8 * 1500 * MLXSW_PORT_MAX_PORTS)) / \ + MLXSW_SP_SB_BYTES_PER_CELL) + +#define MLXSW_SP_SB_POOL(_pool, _dir, _mode, _size) \ + { \ + .pool = _pool, \ + .dir = _dir, \ + .mode = _mode, \ + .size = _size, \ + } + +#define MLXSW_SP_SB_POOL_INGRESS(_pool, _size) \ + MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBPR_DIR_INGRESS, \ + MLXSW_REG_SBPR_MODE_DYNAMIC, _size) + +#define MLXSW_SP_SB_POOL_EGRESS(_pool, _size) \ + MLXSW_SP_SB_POOL(_pool, MLXSW_REG_SBPR_DIR_EGRESS, \ + MLXSW_REG_SBPR_MODE_DYNAMIC, _size) + +static const struct mlxsw_sp_sb_pool mlxsw_sp_sb_pools[] = { + MLXSW_SP_SB_POOL_INGRESS(0, MLXSW_SP_SB_POOL_INGRESS_SIZE), + MLXSW_SP_SB_POOL_INGRESS(1, 0), + MLXSW_SP_SB_POOL_INGRESS(2, 0), + MLXSW_SP_SB_POOL_INGRESS(3, 0), + MLXSW_SP_SB_POOL_EGRESS(0, MLXSW_SP_SB_POOL_EGRESS_SIZE), + MLXSW_SP_SB_POOL_EGRESS(1, 0), + MLXSW_SP_SB_POOL_EGRESS(2, 0), + MLXSW_SP_SB_POOL_EGRESS(2, MLXSW_SP_SB_POOL_EGRESS_SIZE), +}; + +#define MLXSW_SP_SB_POOLS_LEN ARRAY_SIZE(mlxsw_sp_sb_pools) + +static int mlxsw_sp_sb_pools_init(struct mlxsw_sp *mlxsw_sp) +{ + char sbpr_pl[MLXSW_REG_SBPR_LEN]; + int i; + int err; + + for (i = 0; i < MLXSW_SP_SB_POOLS_LEN; i++) { + const struct mlxsw_sp_sb_pool *pool; + + pool = &mlxsw_sp_sb_pools[i]; + mlxsw_reg_sbpr_pack(sbpr_pl, pool->pool, pool->dir, + pool->mode, pool->size); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbpr), sbpr_pl); + if (err) + return err; + } + return 0; +} + +struct mlxsw_sp_sb_cm { + union { + u8 pg; + u8 tc; + } u; + enum mlxsw_reg_sbcm_dir dir; + u32 min_buff; + u32 max_buff; + u8 pool; +}; + +#define MLXSW_SP_SB_CM(_pg_tc, _dir, _min_buff, _max_buff, _pool) \ + { \ + .u.pg = _pg_tc, \ + .dir = _dir, \ + .min_buff = _min_buff, \ + .max_buff = _max_buff, \ + .pool = _pool, \ + } + +#define MLXSW_SP_SB_CM_INGRESS(_pg, _min_buff, _max_buff) \ + MLXSW_SP_SB_CM(_pg, MLXSW_REG_SBCM_DIR_INGRESS, \ + _min_buff, _max_buff, 0) + +#define MLXSW_SP_SB_CM_EGRESS(_tc, _min_buff, _max_buff) \ + MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBCM_DIR_EGRESS, \ + _min_buff, _max_buff, 0) + +#define MLXSW_SP_CPU_PORT_SB_CM_EGRESS(_tc) \ + MLXSW_SP_SB_CM(_tc, MLXSW_REG_SBCM_DIR_EGRESS, 104, 2, 3) + +static const struct mlxsw_sp_sb_cm mlxsw_sp_sb_cms[] = { + MLXSW_SP_SB_CM_INGRESS(0, 10000 / MLXSW_SP_SB_BYTES_PER_CELL, 8), + MLXSW_SP_SB_CM_INGRESS(1, 0, 0), + MLXSW_SP_SB_CM_INGRESS(2, 0, 0), + MLXSW_SP_SB_CM_INGRESS(3, 0, 0), + MLXSW_SP_SB_CM_INGRESS(4, 0, 0), + MLXSW_SP_SB_CM_INGRESS(5, 0, 0), + MLXSW_SP_SB_CM_INGRESS(6, 0, 0), + MLXSW_SP_SB_CM_INGRESS(7, 0, 0), + MLXSW_SP_SB_CM_INGRESS(9, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff), + MLXSW_SP_SB_CM_EGRESS(0, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), + MLXSW_SP_SB_CM_EGRESS(1, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), + MLXSW_SP_SB_CM_EGRESS(2, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), + MLXSW_SP_SB_CM_EGRESS(3, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), + MLXSW_SP_SB_CM_EGRESS(4, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), + MLXSW_SP_SB_CM_EGRESS(5, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), + MLXSW_SP_SB_CM_EGRESS(6, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), + MLXSW_SP_SB_CM_EGRESS(7, 1500 / MLXSW_SP_SB_BYTES_PER_CELL, 9), + MLXSW_SP_SB_CM_EGRESS(8, 0, 0), + MLXSW_SP_SB_CM_EGRESS(9, 0, 0), + MLXSW_SP_SB_CM_EGRESS(10, 0, 0), + MLXSW_SP_SB_CM_EGRESS(11, 0, 0), + MLXSW_SP_SB_CM_EGRESS(12, 0, 0), + MLXSW_SP_SB_CM_EGRESS(13, 0, 0), + MLXSW_SP_SB_CM_EGRESS(14, 0, 0), + MLXSW_SP_SB_CM_EGRESS(15, 0, 0), + MLXSW_SP_SB_CM_EGRESS(16, 1, 0xff), +}; + +#define MLXSW_SP_SB_CMS_LEN ARRAY_SIZE(mlxsw_sp_sb_cms) + +static const struct mlxsw_sp_sb_cm mlxsw_sp_cpu_port_sb_cms[] = { + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(0), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(1), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(2), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(3), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(4), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(5), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(6), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(7), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(8), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(9), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(10), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(11), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(12), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(13), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(14), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(15), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(16), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(17), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(18), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(19), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(20), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(21), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(22), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(23), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(24), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(25), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(26), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(27), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(28), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(29), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(30), + MLXSW_SP_CPU_PORT_SB_CM_EGRESS(31), +}; + +#define MLXSW_SP_CPU_PORT_SB_MCS_LEN \ + ARRAY_SIZE(mlxsw_sp_cpu_port_sb_cms) + +static int mlxsw_sp_sb_cms_init(struct mlxsw_sp *mlxsw_sp, u8 local_port, + const struct mlxsw_sp_sb_cm *cms, + size_t cms_len) +{ + char sbcm_pl[MLXSW_REG_SBCM_LEN]; + int i; + int err; + + for (i = 0; i < cms_len; i++) { + const struct mlxsw_sp_sb_cm *cm; + + cm = &cms[i]; + mlxsw_reg_sbcm_pack(sbcm_pl, local_port, cm->u.pg, cm->dir, + cm->min_buff, cm->max_buff, cm->pool); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbcm), sbcm_pl); + if (err) + return err; + } + return 0; +} + +static int mlxsw_sp_port_sb_cms_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + return mlxsw_sp_sb_cms_init(mlxsw_sp_port->mlxsw_sp, + mlxsw_sp_port->local_port, mlxsw_sp_sb_cms, + MLXSW_SP_SB_CMS_LEN); +} + +static int mlxsw_sp_cpu_port_sb_cms_init(struct mlxsw_sp *mlxsw_sp) +{ + return mlxsw_sp_sb_cms_init(mlxsw_sp, 0, mlxsw_sp_cpu_port_sb_cms, + MLXSW_SP_CPU_PORT_SB_MCS_LEN); +} + +struct mlxsw_sp_sb_pm { + u8 pool; + enum mlxsw_reg_sbpm_dir dir; + u32 min_buff; + u32 max_buff; +}; + +#define MLXSW_SP_SB_PM(_pool, _dir, _min_buff, _max_buff) \ + { \ + .pool = _pool, \ + .dir = _dir, \ + .min_buff = _min_buff, \ + .max_buff = _max_buff, \ + } + +#define MLXSW_SP_SB_PM_INGRESS(_pool, _min_buff, _max_buff) \ + MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBPM_DIR_INGRESS, \ + _min_buff, _max_buff) + +#define MLXSW_SP_SB_PM_EGRESS(_pool, _min_buff, _max_buff) \ + MLXSW_SP_SB_PM(_pool, MLXSW_REG_SBPM_DIR_EGRESS, \ + _min_buff, _max_buff) + +static const struct mlxsw_sp_sb_pm mlxsw_sp_sb_pms[] = { + MLXSW_SP_SB_PM_INGRESS(0, 0, 0xff), + MLXSW_SP_SB_PM_INGRESS(1, 0, 0), + MLXSW_SP_SB_PM_INGRESS(2, 0, 0), + MLXSW_SP_SB_PM_INGRESS(3, 0, 0), + MLXSW_SP_SB_PM_EGRESS(0, 0, 7), + MLXSW_SP_SB_PM_EGRESS(1, 0, 0), + MLXSW_SP_SB_PM_EGRESS(2, 0, 0), + MLXSW_SP_SB_PM_EGRESS(3, 0, 0), +}; + +#define MLXSW_SP_SB_PMS_LEN ARRAY_SIZE(mlxsw_sp_sb_pms) + +static int mlxsw_sp_port_sb_pms_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + char sbpm_pl[MLXSW_REG_SBPM_LEN]; + int i; + int err; + + for (i = 0; i < MLXSW_SP_SB_PMS_LEN; i++) { + const struct mlxsw_sp_sb_pm *pm; + + pm = &mlxsw_sp_sb_pms[i]; + mlxsw_reg_sbpm_pack(sbpm_pl, mlxsw_sp_port->local_port, + pm->pool, pm->dir, + pm->min_buff, pm->max_buff); + err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, + MLXSW_REG(sbpm), sbpm_pl); + if (err) + return err; + } + return 0; +} + +struct mlxsw_sp_sb_mm { + u8 prio; + u32 min_buff; + u32 max_buff; + u8 pool; +}; + +#define MLXSW_SP_SB_MM(_prio, _min_buff, _max_buff, _pool) \ + { \ + .prio = _prio, \ + .min_buff = _min_buff, \ + .max_buff = _max_buff, \ + .pool = _pool, \ + } + +static const struct mlxsw_sp_sb_mm mlxsw_sp_sb_mms[] = { + MLXSW_SP_SB_MM(0, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(1, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(2, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(3, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(4, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(5, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(6, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(7, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(8, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(9, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(10, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(11, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(12, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(13, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), + MLXSW_SP_SB_MM(14, 20000 / MLXSW_SP_SB_BYTES_PER_CELL, 0xff, 0), +}; + +#define MLXSW_SP_SB_MMS_LEN ARRAY_SIZE(mlxsw_sp_sb_mms) + +static int mlxsw_sp_sb_mms_init(struct mlxsw_sp *mlxsw_sp) +{ + char sbmm_pl[MLXSW_REG_SBMM_LEN]; + int i; + int err; + + for (i = 0; i < MLXSW_SP_SB_MMS_LEN; i++) { + const struct mlxsw_sp_sb_mm *mc; + + mc = &mlxsw_sp_sb_mms[i]; + mlxsw_reg_sbmm_pack(sbmm_pl, mc->prio, mc->min_buff, + mc->max_buff, mc->pool); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sbmm), sbmm_pl); + if (err) + return err; + } + return 0; +} + +int mlxsw_sp_buffers_init(struct mlxsw_sp *mlxsw_sp) +{ + int err; + + err = mlxsw_sp_sb_pools_init(mlxsw_sp); + if (err) + return err; + err = mlxsw_sp_cpu_port_sb_cms_init(mlxsw_sp); + if (err) + return err; + err = mlxsw_sp_sb_mms_init(mlxsw_sp); + + return err; +} + +int mlxsw_sp_port_buffers_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + int err; + + err = mlxsw_sp_port_pb_init(mlxsw_sp_port); + if (err) + return err; + err = mlxsw_sp_port_sb_cms_init(mlxsw_sp_port); + if (err) + return err; + err = mlxsw_sp_port_sb_pms_init(mlxsw_sp_port); + + return err; +} diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c new file mode 100644 index 000000000000..c39b7a188726 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -0,0 +1,863 @@ +/* + * drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c + * Copyright (c) 2015 Mellanox Technologies. All rights reserved. + * Copyright (c) 2015 Jiri Pirko + * Copyright (c) 2015 Ido Schimmel + * Copyright (c) 2015 Elad Raz + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spectrum.h" +#include "core.h" +#include "reg.h" + +static int mlxsw_sp_port_attr_get(struct net_device *dev, + struct switchdev_attr *attr) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + + switch (attr->id) { + case SWITCHDEV_ATTR_ID_PORT_PARENT_ID: + attr->u.ppid.id_len = sizeof(mlxsw_sp->base_mac); + memcpy(&attr->u.ppid.id, &mlxsw_sp->base_mac, + attr->u.ppid.id_len); + break; + case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: + attr->u.brport_flags = + (mlxsw_sp_port->learning ? BR_LEARNING : 0) | + (mlxsw_sp_port->learning_sync ? BR_LEARNING_SYNC : 0); + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int mlxsw_sp_port_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port, + u8 state) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + enum mlxsw_reg_spms_state spms_state; + char *spms_pl; + u16 vid; + int err; + + switch (state) { + case BR_STATE_DISABLED: /* fall-through */ + case BR_STATE_FORWARDING: + spms_state = MLXSW_REG_SPMS_STATE_FORWARDING; + break; + case BR_STATE_LISTENING: /* fall-through */ + case BR_STATE_LEARNING: + spms_state = MLXSW_REG_SPMS_STATE_LEARNING; + break; + case BR_STATE_BLOCKING: + spms_state = MLXSW_REG_SPMS_STATE_DISCARDING; + break; + default: + BUG(); + } + + spms_pl = kmalloc(MLXSW_REG_SPMS_LEN, GFP_KERNEL); + if (!spms_pl) + return -ENOMEM; + mlxsw_reg_spms_pack(spms_pl, mlxsw_sp_port->local_port); + for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) + mlxsw_reg_spms_vid_pack(spms_pl, vid, spms_state); + + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spms), spms_pl); + kfree(spms_pl); + return err; +} + +static int mlxsw_sp_port_attr_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port, + struct switchdev_trans *trans, + u8 state) +{ + if (switchdev_trans_ph_prepare(trans)) + return 0; + + mlxsw_sp_port->stp_state = state; + return mlxsw_sp_port_stp_state_set(mlxsw_sp_port, state); +} + +static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port, + struct switchdev_trans *trans, + unsigned long brport_flags) +{ + if (switchdev_trans_ph_prepare(trans)) + return 0; + + mlxsw_sp_port->learning = brport_flags & BR_LEARNING ? 1 : 0; + mlxsw_sp_port->learning_sync = brport_flags & BR_LEARNING_SYNC ? 1 : 0; + return 0; +} + +static int mlxsw_sp_ageing_set(struct mlxsw_sp *mlxsw_sp, u32 ageing_time) +{ + char sfdat_pl[MLXSW_REG_SFDAT_LEN]; + int err; + + mlxsw_reg_sfdat_pack(sfdat_pl, ageing_time); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfdat), sfdat_pl); + if (err) + return err; + mlxsw_sp->ageing_time = ageing_time; + return 0; +} + +static int mlxsw_sp_port_attr_br_ageing_set(struct mlxsw_sp_port *mlxsw_sp_port, + struct switchdev_trans *trans, + unsigned long ageing_jiffies) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u32 ageing_time = jiffies_to_msecs(ageing_jiffies) / 1000; + + if (switchdev_trans_ph_prepare(trans)) + return 0; + + return mlxsw_sp_ageing_set(mlxsw_sp, ageing_time); +} + +static int mlxsw_sp_port_attr_set(struct net_device *dev, + const struct switchdev_attr *attr, + struct switchdev_trans *trans) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + int err = 0; + + switch (attr->id) { + case SWITCHDEV_ATTR_ID_PORT_STP_STATE: + err = mlxsw_sp_port_attr_stp_state_set(mlxsw_sp_port, trans, + attr->u.stp_state); + break; + case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: + err = mlxsw_sp_port_attr_br_flags_set(mlxsw_sp_port, trans, + attr->u.brport_flags); + break; + case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: + err = mlxsw_sp_port_attr_br_ageing_set(mlxsw_sp_port, trans, + attr->u.ageing_time); + break; + default: + err = -EOPNOTSUPP; + break; + } + + return err; +} + +static int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char spvid_pl[MLXSW_REG_SPVID_LEN]; + + mlxsw_reg_spvid_pack(spvid_pl, mlxsw_sp_port->local_port, vid); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl); +} + +static int mlxsw_sp_fid_create(struct mlxsw_sp *mlxsw_sp, u16 fid) +{ + char sfmr_pl[MLXSW_REG_SFMR_LEN]; + int err; + + mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID, fid, fid); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); + + if (err) + return err; + + set_bit(fid, mlxsw_sp->active_fids); + return 0; +} + +static void mlxsw_sp_fid_destroy(struct mlxsw_sp *mlxsw_sp, u16 fid) +{ + char sfmr_pl[MLXSW_REG_SFMR_LEN]; + + clear_bit(fid, mlxsw_sp->active_fids); + + mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_DESTROY_FID, + fid, fid); + mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); +} + +static int mlxsw_sp_port_fid_map(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid) +{ + enum mlxsw_reg_svfa_mt mt; + + if (mlxsw_sp_port->nr_vfids) + mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID; + else + mt = MLXSW_REG_SVFA_MT_VID_TO_FID; + + return mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, true, fid, fid); +} + +static int mlxsw_sp_port_fid_unmap(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid) +{ + enum mlxsw_reg_svfa_mt mt; + + if (!mlxsw_sp_port->nr_vfids) + return 0; + + mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID; + return mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, false, fid, fid); +} + +static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port, + u16 fid, bool set, bool only_uc) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + char *sftr_pl; + int err; + + sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL); + if (!sftr_pl) + return -ENOMEM; + + mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, fid, + MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, 0, + mlxsw_sp_port->local_port, set); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); + if (err) + goto buffer_out; + + /* Flooding control allows one to decide whether a given port will + * flood unicast traffic for which there is no FDB entry. + */ + if (only_uc) + goto buffer_out; + + mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, fid, + MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, 0, + mlxsw_sp_port->local_port, set); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); + +buffer_out: + kfree(sftr_pl); + return err; +} + +static int mlxsw_sp_port_add_vids(struct net_device *dev, u16 vid_begin, + u16 vid_end) +{ + u16 vid; + int err; + + for (vid = vid_begin; vid <= vid_end; vid++) { + err = mlxsw_sp_port_add_vid(dev, 0, vid); + if (err) + goto err_port_add_vid; + } + return 0; + +err_port_add_vid: + for (vid--; vid >= vid_begin; vid--) + mlxsw_sp_port_kill_vid(dev, 0, vid); + return err; +} + +static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port, + u16 vid_begin, u16 vid_end, + bool flag_untagged, bool flag_pvid) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + struct net_device *dev = mlxsw_sp_port->dev; + enum mlxsw_reg_svfa_mt mt; + u16 vid, vid_e; + int err; + + /* In case this is invoked with BRIDGE_FLAGS_SELF and port is + * not bridged, then packets ingressing through the port with + * the specified VIDs will be directed to CPU. + */ + if (!mlxsw_sp_port->bridged) + return mlxsw_sp_port_add_vids(dev, vid_begin, vid_end); + + for (vid = vid_begin; vid <= vid_end; vid++) { + if (!test_bit(vid, mlxsw_sp->active_fids)) { + err = mlxsw_sp_fid_create(mlxsw_sp, vid); + if (err) { + netdev_err(dev, "Failed to create FID=%d\n", + vid); + return err; + } + + /* When creating a FID, we set a VID to FID mapping + * regardless of the port's mode. + */ + mt = MLXSW_REG_SVFA_MT_VID_TO_FID; + err = mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, + true, vid, vid); + if (err) { + netdev_err(dev, "Failed to create FID=VID=%d mapping\n", + vid); + return err; + } + } + + /* Set FID mapping according to port's mode */ + err = mlxsw_sp_port_fid_map(mlxsw_sp_port, vid); + if (err) { + netdev_err(dev, "Failed to map FID=%d", vid); + return err; + } + + err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, true, + false); + if (err) { + netdev_err(dev, "Failed to set flooding for FID=%d", + vid); + return err; + } + } + + for (vid = vid_begin; vid <= vid_end; + vid += MLXSW_REG_SPVM_REC_MAX_COUNT) { + vid_e = min((u16) (vid + MLXSW_REG_SPVM_REC_MAX_COUNT - 1), + vid_end); + + err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid_e, true, + flag_untagged); + if (err) { + netdev_err(mlxsw_sp_port->dev, "Unable to add VIDs %d-%d\n", + vid, vid_e); + return err; + } + } + + vid = vid_begin; + if (flag_pvid && mlxsw_sp_port->pvid != vid) { + err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, vid); + if (err) { + netdev_err(mlxsw_sp_port->dev, "Unable to add PVID %d\n", + vid); + return err; + } + mlxsw_sp_port->pvid = vid; + } + + /* Changing activity bits only if HW operation succeded */ + for (vid = vid_begin; vid <= vid_end; vid++) + set_bit(vid, mlxsw_sp_port->active_vlans); + + return mlxsw_sp_port_stp_state_set(mlxsw_sp_port, + mlxsw_sp_port->stp_state); +} + +static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans) +{ + bool untagged_flag = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + bool pvid_flag = vlan->flags & BRIDGE_VLAN_INFO_PVID; + + if (switchdev_trans_ph_prepare(trans)) + return 0; + + return __mlxsw_sp_port_vlans_add(mlxsw_sp_port, + vlan->vid_begin, vlan->vid_end, + untagged_flag, pvid_flag); +} + +static int mlxsw_sp_port_fdb_op(struct mlxsw_sp_port *mlxsw_sp_port, + const char *mac, u16 vid, bool adding, + bool dynamic) +{ + enum mlxsw_reg_sfd_rec_policy policy; + enum mlxsw_reg_sfd_op op; + char *sfd_pl; + int err; + + if (!vid) + vid = mlxsw_sp_port->pvid; + + sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL); + if (!sfd_pl) + return -ENOMEM; + + policy = dynamic ? MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS : + MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY; + op = adding ? MLXSW_REG_SFD_OP_WRITE_EDIT : + MLXSW_REG_SFD_OP_WRITE_REMOVE; + mlxsw_reg_sfd_pack(sfd_pl, op, 0); + mlxsw_reg_sfd_uc_pack(sfd_pl, 0, policy, + mac, vid, MLXSW_REG_SFD_REC_ACTION_NOP, + mlxsw_sp_port->local_port); + err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(sfd), + sfd_pl); + kfree(sfd_pl); + + return err; +} + +static int +mlxsw_sp_port_fdb_static_add(struct mlxsw_sp_port *mlxsw_sp_port, + const struct switchdev_obj_port_fdb *fdb, + struct switchdev_trans *trans) +{ + if (switchdev_trans_ph_prepare(trans)) + return 0; + + return mlxsw_sp_port_fdb_op(mlxsw_sp_port, fdb->addr, fdb->vid, + true, false); +} + +static int mlxsw_sp_port_obj_add(struct net_device *dev, + const struct switchdev_obj *obj, + struct switchdev_trans *trans) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + int err = 0; + + switch (obj->id) { + case SWITCHDEV_OBJ_ID_PORT_VLAN: + err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, + SWITCHDEV_OBJ_PORT_VLAN(obj), + trans); + break; + case SWITCHDEV_OBJ_ID_PORT_FDB: + err = mlxsw_sp_port_fdb_static_add(mlxsw_sp_port, + SWITCHDEV_OBJ_PORT_FDB(obj), + trans); + break; + default: + err = -EOPNOTSUPP; + break; + } + + return err; +} + +static int mlxsw_sp_port_kill_vids(struct net_device *dev, u16 vid_begin, + u16 vid_end) +{ + u16 vid; + int err; + + for (vid = vid_begin; vid <= vid_end; vid++) { + err = mlxsw_sp_port_kill_vid(dev, 0, vid); + if (err) + return err; + } + + return 0; +} + +static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port, + u16 vid_begin, u16 vid_end, bool init) +{ + struct net_device *dev = mlxsw_sp_port->dev; + u16 vid, vid_e; + int err; + + /* In case this is invoked with BRIDGE_FLAGS_SELF and port is + * not bridged, then prevent packets ingressing through the + * port with the specified VIDs from being trapped to CPU. + */ + if (!init && !mlxsw_sp_port->bridged) + return mlxsw_sp_port_kill_vids(dev, vid_begin, vid_end); + + for (vid = vid_begin; vid <= vid_end; + vid += MLXSW_REG_SPVM_REC_MAX_COUNT) { + vid_e = min((u16) (vid + MLXSW_REG_SPVM_REC_MAX_COUNT - 1), + vid_end); + err = mlxsw_sp_port_vlan_set(mlxsw_sp_port, vid, vid_e, false, + false); + if (err) { + netdev_err(mlxsw_sp_port->dev, "Unable to del VIDs %d-%d\n", + vid, vid_e); + return err; + } + } + + if ((mlxsw_sp_port->pvid >= vid_begin) && + (mlxsw_sp_port->pvid <= vid_end)) { + /* Default VLAN is always 1 */ + mlxsw_sp_port->pvid = 1; + err = mlxsw_sp_port_pvid_set(mlxsw_sp_port, + mlxsw_sp_port->pvid); + if (err) { + netdev_err(mlxsw_sp_port->dev, "Unable to del PVID %d\n", + vid); + return err; + } + } + + if (init) + goto out; + + for (vid = vid_begin; vid <= vid_end; vid++) { + err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, false, + false); + if (err) { + netdev_err(dev, "Failed to clear flooding for FID=%d", + vid); + return err; + } + + /* Remove FID mapping in case of Virtual mode */ + err = mlxsw_sp_port_fid_unmap(mlxsw_sp_port, vid); + if (err) { + netdev_err(dev, "Failed to unmap FID=%d", vid); + return err; + } + } + +out: + /* Changing activity bits only if HW operation succeded */ + for (vid = vid_begin; vid <= vid_end; vid++) + clear_bit(vid, mlxsw_sp_port->active_vlans); + + return 0; +} + +static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port, + const struct switchdev_obj_port_vlan *vlan) +{ + return __mlxsw_sp_port_vlans_del(mlxsw_sp_port, + vlan->vid_begin, vlan->vid_end, false); +} + +static int +mlxsw_sp_port_fdb_static_del(struct mlxsw_sp_port *mlxsw_sp_port, + const struct switchdev_obj_port_fdb *fdb) +{ + return mlxsw_sp_port_fdb_op(mlxsw_sp_port, fdb->addr, fdb->vid, + false, false); +} + +static int mlxsw_sp_port_obj_del(struct net_device *dev, + const struct switchdev_obj *obj) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + int err = 0; + + switch (obj->id) { + case SWITCHDEV_OBJ_ID_PORT_VLAN: + err = mlxsw_sp_port_vlans_del(mlxsw_sp_port, + SWITCHDEV_OBJ_PORT_VLAN(obj)); + break; + case SWITCHDEV_OBJ_ID_PORT_FDB: + err = mlxsw_sp_port_fdb_static_del(mlxsw_sp_port, + SWITCHDEV_OBJ_PORT_FDB(obj)); + break; + default: + err = -EOPNOTSUPP; + break; + } + + return err; +} + +static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port, + struct switchdev_obj_port_fdb *fdb, + switchdev_obj_dump_cb_t *cb) +{ + char *sfd_pl; + char mac[ETH_ALEN]; + u16 vid; + u8 local_port; + u8 num_rec; + int stored_err = 0; + int i; + int err; + + sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL); + if (!sfd_pl) + return -ENOMEM; + + mlxsw_reg_sfd_pack(sfd_pl, MLXSW_REG_SFD_OP_QUERY_DUMP, 0); + do { + mlxsw_reg_sfd_num_rec_set(sfd_pl, MLXSW_REG_SFD_REC_MAX_COUNT); + err = mlxsw_reg_query(mlxsw_sp_port->mlxsw_sp->core, + MLXSW_REG(sfd), sfd_pl); + if (err) + goto out; + + num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl); + + /* Even in case of error, we have to run the dump to the end + * so the session in firmware is finished. + */ + if (stored_err) + continue; + + for (i = 0; i < num_rec; i++) { + switch (mlxsw_reg_sfd_rec_type_get(sfd_pl, i)) { + case MLXSW_REG_SFD_REC_TYPE_UNICAST: + mlxsw_reg_sfd_uc_unpack(sfd_pl, i, mac, &vid, + &local_port); + if (local_port == mlxsw_sp_port->local_port) { + ether_addr_copy(fdb->addr, mac); + fdb->ndm_state = NUD_REACHABLE; + fdb->vid = vid; + err = cb(&fdb->obj); + if (err) + stored_err = err; + } + } + } + } while (num_rec == MLXSW_REG_SFD_REC_MAX_COUNT); + +out: + kfree(sfd_pl); + return stored_err ? stored_err : err; +} + +static int mlxsw_sp_port_vlan_dump(struct mlxsw_sp_port *mlxsw_sp_port, + struct switchdev_obj_port_vlan *vlan, + switchdev_obj_dump_cb_t *cb) +{ + u16 vid; + int err = 0; + + for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) { + vlan->flags = 0; + if (vid == mlxsw_sp_port->pvid) + vlan->flags |= BRIDGE_VLAN_INFO_PVID; + vlan->vid_begin = vid; + vlan->vid_end = vid; + err = cb(&vlan->obj); + if (err) + break; + } + return err; +} + +static int mlxsw_sp_port_obj_dump(struct net_device *dev, + struct switchdev_obj *obj, + switchdev_obj_dump_cb_t *cb) +{ + struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); + int err = 0; + + switch (obj->id) { + case SWITCHDEV_OBJ_ID_PORT_VLAN: + err = mlxsw_sp_port_vlan_dump(mlxsw_sp_port, + SWITCHDEV_OBJ_PORT_VLAN(obj), cb); + break; + case SWITCHDEV_OBJ_ID_PORT_FDB: + err = mlxsw_sp_port_fdb_dump(mlxsw_sp_port, + SWITCHDEV_OBJ_PORT_FDB(obj), cb); + break; + default: + err = -EOPNOTSUPP; + break; + } + + return err; +} + +const struct switchdev_ops mlxsw_sp_port_switchdev_ops = { + .switchdev_port_attr_get = mlxsw_sp_port_attr_get, + .switchdev_port_attr_set = mlxsw_sp_port_attr_set, + .switchdev_port_obj_add = mlxsw_sp_port_obj_add, + .switchdev_port_obj_del = mlxsw_sp_port_obj_del, + .switchdev_port_obj_dump = mlxsw_sp_port_obj_dump, +}; + +static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp, + char *sfn_pl, int rec_index, + bool adding) +{ + struct mlxsw_sp_port *mlxsw_sp_port; + char mac[ETH_ALEN]; + u8 local_port; + u16 vid; + int err; + + mlxsw_reg_sfn_mac_unpack(sfn_pl, rec_index, mac, &vid, &local_port); + mlxsw_sp_port = mlxsw_sp->ports[local_port]; + if (!mlxsw_sp_port) { + dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect local port in FDB notification\n"); + return; + } + + err = mlxsw_sp_port_fdb_op(mlxsw_sp_port, mac, vid, + adding && mlxsw_sp_port->learning, true); + if (err) { + if (net_ratelimit()) + netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n"); + return; + } + + if (mlxsw_sp_port->learning && mlxsw_sp_port->learning_sync) { + struct switchdev_notifier_fdb_info info; + unsigned long notifier_type; + + info.addr = mac; + info.vid = vid; + notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL; + call_switchdev_notifiers(notifier_type, mlxsw_sp_port->dev, + &info.info); + } +} + +static void mlxsw_sp_fdb_notify_rec_process(struct mlxsw_sp *mlxsw_sp, + char *sfn_pl, int rec_index) +{ + switch (mlxsw_reg_sfn_rec_type_get(sfn_pl, rec_index)) { + case MLXSW_REG_SFN_REC_TYPE_LEARNED_MAC: + mlxsw_sp_fdb_notify_mac_process(mlxsw_sp, sfn_pl, + rec_index, true); + break; + case MLXSW_REG_SFN_REC_TYPE_AGED_OUT_MAC: + mlxsw_sp_fdb_notify_mac_process(mlxsw_sp, sfn_pl, + rec_index, false); + break; + } +} + +static void mlxsw_sp_fdb_notify_work_schedule(struct mlxsw_sp *mlxsw_sp) +{ + schedule_delayed_work(&mlxsw_sp->fdb_notify.dw, + msecs_to_jiffies(mlxsw_sp->fdb_notify.interval)); +} + +static void mlxsw_sp_fdb_notify_work(struct work_struct *work) +{ + struct mlxsw_sp *mlxsw_sp; + char *sfn_pl; + u8 num_rec; + int i; + int err; + + sfn_pl = kmalloc(MLXSW_REG_SFN_LEN, GFP_KERNEL); + if (!sfn_pl) + return; + + mlxsw_sp = container_of(work, struct mlxsw_sp, fdb_notify.dw.work); + + do { + mlxsw_reg_sfn_pack(sfn_pl); + err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfn), sfn_pl); + if (err) { + dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to get FDB notifications\n"); + break; + } + num_rec = mlxsw_reg_sfn_num_rec_get(sfn_pl); + for (i = 0; i < num_rec; i++) + mlxsw_sp_fdb_notify_rec_process(mlxsw_sp, sfn_pl, i); + + } while (num_rec); + + kfree(sfn_pl); + mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp); +} + +static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp) +{ + int err; + + err = mlxsw_sp_ageing_set(mlxsw_sp, MLXSW_SP_DEFAULT_AGEING_TIME); + if (err) { + dev_err(mlxsw_sp->bus_info->dev, "Failed to set default ageing time\n"); + return err; + } + INIT_DELAYED_WORK(&mlxsw_sp->fdb_notify.dw, mlxsw_sp_fdb_notify_work); + mlxsw_sp->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL; + mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp); + return 0; +} + +static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp) +{ + cancel_delayed_work_sync(&mlxsw_sp->fdb_notify.dw); +} + +static void mlxsw_sp_fids_fini(struct mlxsw_sp *mlxsw_sp) +{ + u16 fid; + + for_each_set_bit(fid, mlxsw_sp->active_fids, VLAN_N_VID) + mlxsw_sp_fid_destroy(mlxsw_sp, fid); +} + +int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp) +{ + return mlxsw_sp_fdb_init(mlxsw_sp); +} + +void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp) +{ + mlxsw_sp_fdb_fini(mlxsw_sp); + mlxsw_sp_fids_fini(mlxsw_sp); +} + +int mlxsw_sp_port_vlan_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + struct net_device *dev = mlxsw_sp_port->dev; + int err; + + /* Allow only untagged packets to ingress and tag them internally + * with VID 1. + */ + mlxsw_sp_port->pvid = 1; + err = __mlxsw_sp_port_vlans_del(mlxsw_sp_port, 0, VLAN_N_VID, true); + if (err) { + netdev_err(dev, "Unable to init VLANs\n"); + return err; + } + + /* Add implicit VLAN interface in the device, so that untagged + * packets will be classified to the default vFID. + */ + err = mlxsw_sp_port_add_vid(dev, 0, 1); + if (err) + netdev_err(dev, "Failed to configure default vFID\n"); + + return err; +} + +void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port) +{ + mlxsw_sp_port->dev->switchdev_ops = &mlxsw_sp_port_switchdev_ops; +} + +void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port) +{ +} diff --git a/drivers/net/ethernet/mellanox/mlxsw/txheader.h b/drivers/net/ethernet/mellanox/mlxsw/txheader.h index 06fc46c78a0b..fdf94720ca62 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/txheader.h +++ b/drivers/net/ethernet/mellanox/mlxsw/txheader.h @@ -38,6 +38,7 @@ #define MLXSW_TXHDR_LEN 0x10 #define MLXSW_TXHDR_VERSION_0 0 +#define MLXSW_TXHDR_VERSION_1 1 enum { MLXSW_TXHDR_ETH_CTL, -- cgit v1.2.3 From b89eb1fcf2d4c068f088c39100f5e3067d8cccc9 Mon Sep 17 00:00:00 2001 From: Arun Parameswaran Date: Thu, 15 Oct 2015 10:37:13 -0700 Subject: net: phy: bcm-phy-lib: Fix module license issue The 'bcm-phy-lib.c', added as a part of the commit "net: phy: Add Broadcom phy library for common interfaces" was missing the module license. This was causing an issue when the library is built as a module; "module license 'unspecified' taints kernel". This patch fixes the issue by adding the module license, author and description to the bcm-phy-lib.c file. Fixes: a1cba5613edf5 ("net: phy: Add Broadcom phy library for common interfaces") Signed-off-by: Arun Parameswaran Acked-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/bcm-phy-lib.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c index dd79ea6ba023..ddb377e53633 100644 --- a/drivers/net/phy/bcm-phy-lib.c +++ b/drivers/net/phy/bcm-phy-lib.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #define MII_BCM_CHANNEL_WIDTH 0x2000 @@ -206,3 +207,7 @@ int bcm_phy_enable_eee(struct phy_device *phydev) return 0; } EXPORT_SYMBOL_GPL(bcm_phy_enable_eee); + +MODULE_DESCRIPTION("Broadcom PHY Library"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Broadcom Corporation"); -- cgit v1.2.3 From 80083a3c02ef4451edeef31a6f9afe130078f2bf Mon Sep 17 00:00:00 2001 From: Chia-Sheng Chang Date: Fri, 16 Oct 2015 02:00:21 +0800 Subject: net: asix: add support for the Billionton GUSB2AM-1G-B USB adapter Just another AX88178-based 10/100/1000 USB-to-Ethernet dongle. This one shows up in lsusb as: "ID 08dd:0114 Billionton Systems, Inc". Signed-off-by: Chia-Sheng Chang Cc: "David S. Miller" Cc: Luca Ceresoli Cc: Christoph Jaeger Cc: "Woojung.Huh@microchip.com" Cc: Matthew Garrett Cc: Markus Elfring Cc: Charles Keepax Cc: netdev@vger.kernel.org Cc: linux-usb@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/usb/Kconfig | 1 + drivers/net/usb/asix_devices.c | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index fbb9325d1f6e..e66805eeffb4 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -164,6 +164,7 @@ config USB_NET_AX8817X * Aten UC210T * ASIX AX88172 * Billionton Systems, USB2AR + * Billionton Systems, GUSB2AM-1G-B * Buffalo LUA-U2-KTX * Corega FEther USB2-TX * D-Link DUB-E100 diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 1173a24feda3..5cabefc23494 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c @@ -958,6 +958,10 @@ static const struct usb_device_id products [] = { // Billionton Systems, USB2AR USB_DEVICE (0x08dd, 0x90ff), .driver_info = (unsigned long) &ax8817x_info, +}, { + // Billionton Systems, GUSB2AM-1G-B + USB_DEVICE(0x08dd, 0x0114), + .driver_info = (unsigned long) &ax88178_info, }, { // ATEN UC210T USB_DEVICE (0x0557, 0x2009), -- cgit v1.2.3 From 833b8f18adfcca04070a8a42d545a4553379d36f Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Thu, 15 Oct 2015 18:02:28 +0000 Subject: xen-netback: correctly check failed allocation Since vzalloc can be failed in memory pressure, writes -ENOMEM to xenstore to indicate error. Signed-off-by: Insu Yun Acked-by: Wei Liu Signed-off-by: David S. Miller --- drivers/net/xen-netback/xenbus.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 929a6e7e5ecf..56ebd8267386 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -788,6 +788,12 @@ static void connect(struct backend_info *be) /* Use the number of queues requested by the frontend */ be->vif->queues = vzalloc(requested_num_queues * sizeof(struct xenvif_queue)); + if (!be->vif->queues) { + xenbus_dev_fatal(dev, -ENOMEM, + "allocating queues"); + return; + } + be->vif->num_queues = requested_num_queues; be->vif->stalled_queues = requested_num_queues; -- cgit v1.2.3 From 31bbd77189a82ed0b7f167d3b8b6561898fa8a80 Mon Sep 17 00:00:00 2001 From: huangdaode Date: Fri, 16 Oct 2015 11:54:16 +0800 Subject: net: hisilicon rm hnae sysfs interface This patch removes the hns driver hnae sysfs interface according to Arnd's review comments. Signed-off-by: huangdaode Reviewed-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hnae.c | 47 ------------------------------- 1 file changed, 47 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c index f52e99acf463..9d3bb8349a73 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.c +++ b/drivers/net/ethernet/hisilicon/hns/hnae.c @@ -436,59 +436,12 @@ void hnae_ae_unregister(struct hnae_ae_dev *hdev) } EXPORT_SYMBOL(hnae_ae_unregister); -static ssize_t handles_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - ssize_t s = 0; - struct hnae_ae_dev *hdev = cls_to_ae_dev(dev); - struct hnae_handle *h; - int i = 0, j; - - list_for_each_entry_rcu(h, &hdev->handle_list, node) { - s += sprintf(buf + s, "handle %d (eport_id=%u from %s):\n", - i++, h->eport_id, h->dev->name); - for (j = 0; j < h->q_num; j++) { - s += sprintf(buf + s, "\tqueue[%d] on %p\n", - j, h->qs[i]->io_base); -#define HANDEL_TX_MSG "\t\ttx_ring on %p:%u,%u,%u,%u,%u,%llu,%llu\n" - s += sprintf(buf + s, - HANDEL_TX_MSG, - h->qs[i]->tx_ring.io_base, - h->qs[i]->tx_ring.buf_size, - h->qs[i]->tx_ring.desc_num, - h->qs[i]->tx_ring.max_desc_num_per_pkt, - h->qs[i]->tx_ring.max_raw_data_sz_per_desc, - h->qs[i]->tx_ring.max_pkt_size, - h->qs[i]->tx_ring.stats.sw_err_cnt, - h->qs[i]->tx_ring.stats.io_err_cnt); - s += sprintf(buf + s, - "\t\trx_ring on %p:%u,%u,%llu,%llu,%llu\n", - h->qs[i]->rx_ring.io_base, - h->qs[i]->rx_ring.buf_size, - h->qs[i]->rx_ring.desc_num, - h->qs[i]->rx_ring.stats.sw_err_cnt, - h->qs[i]->rx_ring.stats.io_err_cnt, - h->qs[i]->rx_ring.stats.seg_pkt_cnt); - } - } - - return s; -} - -static DEVICE_ATTR_RO(handles); -static struct attribute *hnae_class_attrs[] = { - &dev_attr_handles.attr, - NULL, -}; -ATTRIBUTE_GROUPS(hnae_class); - static int __init hnae_init(void) { hnae_class = class_create(THIS_MODULE, "hnae"); if (IS_ERR(hnae_class)) return PTR_ERR(hnae_class); - hnae_class->dev_groups = hnae_class_groups; return 0; } -- cgit v1.2.3 From abc2b10eadc6587192adde6ab4050d27dda5ee8f Mon Sep 17 00:00:00 2001 From: huangdaode Date: Fri, 16 Oct 2015 11:54:17 +0800 Subject: net: hisilicon fix a bug on Hisilicon Network Subsystem This patch fixes the wrong judgement of mac_id when get port num. Signed-off-by: huangdaode Signed-off-by: yankejian Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index f8f734722891..026b38676cba 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -179,7 +179,7 @@ static int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb, return -EINVAL; } } else if (mac_cb->dsaf_dev->dsaf_mode < DSAF_MODE_MAX) { - if (mac_cb->mac_id <= DSAF_MAX_PORT_NUM_PER_CHIP) { + if (mac_cb->mac_id >= DSAF_MAX_PORT_NUM_PER_CHIP) { dev_err(mac_cb->dev, "input invalid,%s mac%d vmid%d!\n", mac_cb->dsaf_dev->ae_dev.name, -- cgit v1.2.3 From 20ddb1d3d0015ff77f83561a0ede7aaebf7417bf Mon Sep 17 00:00:00 2001 From: Chenny Xu Date: Fri, 16 Oct 2015 17:03:19 +0800 Subject: net: hns: fixes the issue by using ethtool -s before this patch, hns driver only permits user to set the net device by using ethtool -s when the device is link up. it is obviously not so good. it needs to be set no matter it is link up or down. so this patch fixes this issue. Signed-off-by: yankejian Signed-off-by: Yisen Zhuang Signed-off-by: lisheng Signed-off-by: lipeng Signed-off-by: Chenny Xu Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 39 ++++++++---------------- 1 file changed, 12 insertions(+), 27 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 7d58918abb78..a0332129970b 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -194,9 +194,7 @@ static int hns_nic_set_settings(struct net_device *net_dev, { struct hns_nic_priv *priv = netdev_priv(net_dev); struct hnae_handle *h; - int link_stat; u32 speed; - u8 duplex, autoneg; if (!netif_running(net_dev)) return -ESRCH; @@ -206,48 +204,35 @@ static int hns_nic_set_settings(struct net_device *net_dev, return -ENODEV; h = priv->ae_handle; - link_stat = hns_nic_get_link(net_dev); - duplex = cmd->duplex; speed = ethtool_cmd_speed(cmd); - autoneg = cmd->autoneg; - - if (!link_stat) { - if (duplex != (u8)DUPLEX_UNKNOWN || speed != (u32)SPEED_UNKNOWN) - return -EINVAL; - - if (h->phy_if == PHY_INTERFACE_MODE_SGMII && h->phy_node) { - priv->phy->autoneg = autoneg; - return phy_start_aneg(priv->phy); - } - } if (h->phy_if == PHY_INTERFACE_MODE_XGMII) { - if (autoneg != AUTONEG_DISABLE) - return -EINVAL; - - if (speed != SPEED_10000 || duplex != DUPLEX_FULL) + if (cmd->autoneg == AUTONEG_ENABLE || speed != SPEED_10000 || + cmd->duplex != DUPLEX_FULL) return -EINVAL; } else if (h->phy_if == PHY_INTERFACE_MODE_SGMII) { - if (!h->phy_node && autoneg != AUTONEG_DISABLE) + if (!priv->phy && cmd->autoneg == AUTONEG_ENABLE) return -EINVAL; - if (speed == SPEED_1000 && duplex == DUPLEX_HALF) + if (speed == SPEED_1000 && cmd->duplex == DUPLEX_HALF) return -EINVAL; + if (priv->phy) + return phy_ethtool_sset(priv->phy, cmd); - if (speed != SPEED_10 && speed != SPEED_100 && - speed != SPEED_1000) + if ((speed != SPEED_10 && speed != SPEED_100 && + speed != SPEED_1000) || (cmd->duplex != DUPLEX_HALF && + cmd->duplex != DUPLEX_FULL)) return -EINVAL; } else { netdev_err(net_dev, "Not supported!"); return -ENOTSUPP; } - if (priv->phy) { - return phy_ethtool_sset(priv->phy, cmd); - } else if (h->dev->ops->adjust_link && link_stat) { - h->dev->ops->adjust_link(h, speed, duplex); + if (h->dev->ops->adjust_link) { + h->dev->ops->adjust_link(h, (int)speed, cmd->duplex); return 0; } + netdev_err(net_dev, "Not supported!"); return -ENOTSUPP; } -- cgit v1.2.3 From 90a505b9f607bf09525bb8eb766b73a658675b38 Mon Sep 17 00:00:00 2001 From: lisheng Date: Fri, 16 Oct 2015 17:03:20 +0800 Subject: net: hns: fixes a bug about timeout by pause frame this patch fixes the bug triggered timeout sequence. when the connective ports cannot accept the packets with higher speed, they will send out the pause frame to the Soc's mac. At that time, the driver resets the relevant of the Soc, then it causes the packets cannot be sent out immediately. this patch fixes the issue. Signed-off-by: yankejian Signed-off-by: Yisen Zhuang Signed-off-by: lisheng Signed-off-by: lipeng Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 6f9091c29869..302d3ae8e9e5 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1315,16 +1315,15 @@ static void hns_nic_reset_subtask(struct hns_nic_priv *priv) return; hns_nic_dump(priv); - netdev_err(priv->netdev, "Reset %s port\n", - (type == HNAE_PORT_DEBUG ? "debug" : "business")); + netdev_info(priv->netdev, "Reset %s port\n", + (type == HNAE_PORT_DEBUG ? "debug" : "business")); rtnl_lock(); - if (type == HNAE_PORT_DEBUG) { + /* put off any impending NetWatchDogTimeout */ + priv->netdev->trans_start = jiffies; + + if (type == HNAE_PORT_DEBUG) hns_nic_net_reinit(priv->netdev); - } else { - hns_nic_net_down(priv->netdev); - hns_nic_net_reset(priv->netdev); - } rtnl_unlock(); } -- cgit v1.2.3 From 119c7ad8084affb64b242b7c6d9d9f84b91163cb Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 16 Oct 2015 11:30:56 +0200 Subject: net: hisilicon: include linux/vmalloc.h in dsaf Some configurations fail to build the hns dsaf code because of a missing header file: ethernet/hisilicon/hns/hns_dsaf_main.c: In function 'hns_dsaf_init': ethernet/hisilicon/hns/hns_dsaf_main.c:1096:2: error: implicit declaration of function 'vzalloc' [-Werror=implicit-function-declaration] priv->soft_mac_tbl = vzalloc(sizeof(*priv->soft_mac_tbl) This adds the correct #include. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index ffc2604766b6..2a98eba660c0 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -17,6 +17,8 @@ #include #include #include +#include + #include "hns_dsaf_main.h" #include "hns_dsaf_rcb.h" #include "hns_dsaf_ppe.h" -- cgit v1.2.3 From 876133d3161dcb743983d1f9e5bf247aea2fb0f1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 16 Oct 2015 11:33:49 +0200 Subject: net: hisilicon: add OF dependency The HNS MDIO driver fails to build on older ARM machines that are not yet converted to CONFIG_OF: drivers/net/ethernet/hisilicon/hns_mdio.c: In function 'hns_mdio_bus_name': drivers/net/ethernet/hisilicon/hns_mdio.c:405:14: error: 'OF_BAD_ADDR' undeclared (first use in this function) u64 taddr = OF_BAD_ADDR; ^ drivers/net/ethernet/hisilicon/hns_mdio.c:405:14: note: each undeclared identifier is reported only once for each function it appears in drivers/net/ethernet/hisilicon/hns_mdio.c:409:11: error: implicit declaration of function 'of_translate_address' [-Werror=implicit-function-declaration] taddr = of_translate_address(np, addr); ^ This clarifies the dependency to ensure we don't attempt to build these drivers without CONFIG_OF, but also adds a COMPILE_TEST alternative to give us better build coverage testing. Build-tested on x86 as well to ensure this actually works. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig index 8d12b587809e..f250dec488fd 100644 --- a/drivers/net/ethernet/hisilicon/Kconfig +++ b/drivers/net/ethernet/hisilicon/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_HISILICON bool "Hisilicon devices" default y - depends on ARM || ARM64 + depends on OF && (ARM || ARM64 || COMPILE_TEST) ---help--- If you have a network (Ethernet) card belonging to this class, say Y. -- cgit v1.2.3 From 951b5d959f1da4bae8910085a2d8d6a3d374c72d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 16 Oct 2015 12:00:51 +0200 Subject: net: hix5hd2_gmac: avoid integer overload warning BITS_RX_EN is an 'unsigned long' constant, so the ones complement of that has bits set that do not fit into a 32-bit variable on 64-bit architectures, which causes a harmless gcc warning: drivers/net/ethernet/hisilicon/hix5hd2_gmac.c: In function 'hix5hd2_port_disable': drivers/net/ethernet/hisilicon/hix5hd2_gmac.c:374:2: warning: large integer implicitly truncated to unsigned type [-Woverflow] writel_relaxed(~(BITS_RX_EN | BITS_TX_EN), priv->base + PORT_EN); This adds a cast to (u32) to tell gcc that the code is indeed fine. Signed-off-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hix5hd2_gmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c index a5e077eac99a..e51892d518ff 100644 --- a/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c +++ b/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c @@ -371,7 +371,7 @@ static void hix5hd2_port_enable(struct hix5hd2_priv *priv) static void hix5hd2_port_disable(struct hix5hd2_priv *priv) { - writel_relaxed(~(BITS_RX_EN | BITS_TX_EN), priv->base + PORT_EN); + writel_relaxed(~(u32)(BITS_RX_EN | BITS_TX_EN), priv->base + PORT_EN); writel_relaxed(0, priv->base + DESC_WR_RD_ENA); } -- cgit v1.2.3 From e277de5f3f7d6eed2a41920983c44c4df386b871 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Fri, 16 Oct 2015 16:36:00 -0700 Subject: tunnels: Don't require remote endpoint or ID during creation. Before lightweight tunnels existed, it really didn't make sense to create a tunnel that was not fully specified, such as without a destination IP address - the resulting packets would go nowhere. However, with lightweight tunnels, the opposite is true - it doesn't make sense to require this information when it will be provided later on by the route. This loosens the requirements for this information. An alternative would be to allow the relaxed version only when COLLECT_METADATA is enabled. However, since there are several variations on this theme (such as NBMA tunnels in GRE), just dropping the restrictions seems the most consistent across tunnels and with the existing configuration. CC: John Linville Signed-off-by: Jesse Gross Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- drivers/net/geneve.c | 12 ++++++------ drivers/net/vxlan.c | 7 +++---- 2 files changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 8f5c02eed47d..cde29f8a37bf 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -870,14 +870,14 @@ static int geneve_newlink(struct net *net, struct net_device *dev, __be16 dst_port = htons(GENEVE_UDP_PORT); __u8 ttl = 0, tos = 0; bool metadata = false; - __be32 rem_addr; - __u32 vni; + __be32 rem_addr = 0; + __u32 vni = 0; - if (!data[IFLA_GENEVE_ID] || !data[IFLA_GENEVE_REMOTE]) - return -EINVAL; + if (data[IFLA_GENEVE_ID]) + vni = nla_get_u32(data[IFLA_GENEVE_ID]); - vni = nla_get_u32(data[IFLA_GENEVE_ID]); - rem_addr = nla_get_in_addr(data[IFLA_GENEVE_REMOTE]); + if (data[IFLA_GENEVE_REMOTE]) + rem_addr = nla_get_in_addr(data[IFLA_GENEVE_REMOTE]); if (data[IFLA_GENEVE_TTL]) ttl = nla_get_u8(data[IFLA_GENEVE_TTL]); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index bbac1d35ed4e..afdc65fd5bc5 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2745,11 +2745,10 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev, struct vxlan_config conf; int err; - if (!data[IFLA_VXLAN_ID]) - return -EINVAL; - memset(&conf, 0, sizeof(conf)); - conf.vni = nla_get_u32(data[IFLA_VXLAN_ID]); + + if (data[IFLA_VXLAN_ID]) + conf.vni = nla_get_u32(data[IFLA_VXLAN_ID]); if (data[IFLA_VXLAN_GROUP]) { conf.remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]); -- cgit v1.2.3 From 37850e37fcfb4dd831bc9e33221e8c49a732956f Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Sat, 17 Oct 2015 14:22:46 -0700 Subject: net: bcmgenet: Fix early link interrupt enabling Link interrupts are enabled in init_umac(), which is too early for us to process them since we do not yet have a valid PHY device pointer. On BCM7425 chips for instance, we will crash calling phy_mac_interrupt() because phydev is NULL. Fix this by moving the link interrupts enabling in bcmgenet_netif_start(), under a specific function: bcmgenet_link_intr_enable() and while at it, update the comments surrounding the code. Fixes: 6cc8e6d4dcb36 ("net: bcmgenet: Delay PHY initialization to bcmgenet_open()") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 32 ++++++++++++++++++-------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 3bc701e4c59e..1805541b4240 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1683,6 +1683,24 @@ static void bcmgenet_intr_disable(struct bcmgenet_priv *priv) bcmgenet_intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR); } +static void bcmgenet_link_intr_enable(struct bcmgenet_priv *priv) +{ + u32 int0_enable = 0; + + /* Monitor cable plug/unplugged event for internal PHY, external PHY + * and MoCA PHY + */ + if (priv->internal_phy) { + int0_enable |= UMAC_IRQ_LINK_EVENT; + } else if (priv->ext_phy) { + int0_enable |= UMAC_IRQ_LINK_EVENT; + } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) { + if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET) + int0_enable |= UMAC_IRQ_LINK_EVENT; + } + bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR); +} + static int init_umac(struct bcmgenet_priv *priv) { struct device *kdev = &priv->pdev->dev; @@ -1723,15 +1741,8 @@ static int init_umac(struct bcmgenet_priv *priv) /* Enable Tx default queue 16 interrupts */ int0_enable |= UMAC_IRQ_TXDMA_DONE; - /* Monitor cable plug/unplugged event for internal PHY */ - if (priv->internal_phy) { - int0_enable |= UMAC_IRQ_LINK_EVENT; - } else if (priv->ext_phy) { - int0_enable |= UMAC_IRQ_LINK_EVENT; - } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) { - if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET) - int0_enable |= UMAC_IRQ_LINK_EVENT; - + /* Configure backpressure vectors for MoCA */ + if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) { reg = bcmgenet_bp_mc_get(priv); reg |= BIT(priv->hw_params->bp_in_en_shift); @@ -2645,6 +2656,9 @@ static void bcmgenet_netif_start(struct net_device *dev) netif_tx_start_all_queues(dev); + /* Monitor link interrupts now */ + bcmgenet_link_intr_enable(priv); + phy_start(priv->phydev); } -- cgit v1.2.3 From 1aaf8efba0aeb25eb5858b19472badaa54a41a38 Mon Sep 17 00:00:00 2001 From: Anilkumar Kolli Date: Fri, 16 Oct 2015 15:54:51 +0300 Subject: ath10k: disable PCI PS for QCA988X and QCA99X0 This patch disables PCI PS for QCA988X and QCA99X0, Since PCI PS is validated for QCA6174, let it be enabled only for QCA6174. It would be better to execute PCI PS related functions only for the supported devices. PCI time out issue is observed with QCA99X0 on x86 platform, We will disable PCI PS for QCA988X and QCA99X0 until PCI PS is properly implemented. Taking and releasing ps_lock is causing higher CPU consumption. Michal Kazior suggested ps_lock overhead to be reworked so that ath10k_pci_wake/sleep functions are called less often, i.e. move the powersave logic up (only during irq handling, tx path, submitting fw commands) but that's a bigger change and can be implemented later. Signed-off-by: Anilkumar Kolli Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 83 ++++++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/pci.h | 6 +++ 2 files changed, 88 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index adcda2815b73..5c05b0cf54a1 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -479,12 +479,53 @@ static int ath10k_pci_wake_wait(struct ath10k *ar) return -ETIMEDOUT; } +static int ath10k_pci_force_wake(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&ar_pci->ps_lock, flags); + + if (!ar_pci->ps_awake) { + iowrite32(PCIE_SOC_WAKE_V_MASK, + ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS); + + ret = ath10k_pci_wake_wait(ar); + if (ret == 0) + ar_pci->ps_awake = true; + } + + spin_unlock_irqrestore(&ar_pci->ps_lock, flags); + + return ret; +} + +static void ath10k_pci_force_sleep(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + unsigned long flags; + + spin_lock_irqsave(&ar_pci->ps_lock, flags); + + iowrite32(PCIE_SOC_WAKE_RESET, + ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + + PCIE_SOC_WAKE_ADDRESS); + ar_pci->ps_awake = false; + + spin_unlock_irqrestore(&ar_pci->ps_lock, flags); +} + static int ath10k_pci_wake(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); unsigned long flags; int ret = 0; + if (ar_pci->pci_ps == 0) + return ret; + spin_lock_irqsave(&ar_pci->ps_lock, flags); ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps wake refcount %lu awake %d\n", @@ -516,6 +557,9 @@ static void ath10k_pci_sleep(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); unsigned long flags; + if (ar_pci->pci_ps == 0) + return; + spin_lock_irqsave(&ar_pci->ps_lock, flags); ath10k_dbg(ar, ATH10K_DBG_PCI_PS, "pci ps sleep refcount %lu awake %d\n", @@ -558,6 +602,11 @@ static void ath10k_pci_sleep_sync(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); unsigned long flags; + if (ar_pci->pci_ps == 0) { + ath10k_pci_force_sleep(ar); + return; + } + del_timer_sync(&ar_pci->ps_timer); spin_lock_irqsave(&ar_pci->ps_lock, flags); @@ -2417,6 +2466,15 @@ static int ath10k_pci_hif_resume(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct pci_dev *pdev = ar_pci->pdev; u32 val; + int ret = 0; + + if (ar_pci->pci_ps == 0) { + ret = ath10k_pci_force_wake(ar); + if (ret) { + ath10k_err(ar, "failed to wake up target: %d\n", ret); + return ret; + } + } /* Suspend/Resume resets the PCI configuration space, so we have to * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries @@ -2427,7 +2485,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar) if ((val & 0x0000ff00) != 0) pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - return 0; + return ret; } #endif @@ -2520,6 +2578,16 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg) { struct ath10k *ar = arg; struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + + if (ar_pci->pci_ps == 0) { + ret = ath10k_pci_force_wake(ar); + if (ret) { + ath10k_warn(ar, "failed to wake device up on irq: %d\n", + ret); + return IRQ_NONE; + } + } if (ar_pci->num_msi_intrs == 0) { if (!ath10k_pci_irq_pending(ar)) @@ -2919,17 +2987,21 @@ static int ath10k_pci_probe(struct pci_dev *pdev, struct ath10k_pci *ar_pci; enum ath10k_hw_rev hw_rev; u32 chip_id; + bool pci_ps; switch (pci_dev->device) { case QCA988X_2_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA988X; + pci_ps = false; break; case QCA6164_2_1_DEVICE_ID: case QCA6174_2_1_DEVICE_ID: hw_rev = ATH10K_HW_QCA6174; + pci_ps = true; break; case QCA99X0_2_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA99X0; + pci_ps = false; break; default: WARN_ON(1); @@ -2952,6 +3024,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar_pci->dev = &pdev->dev; ar_pci->ar = ar; ar->dev_id = pci_dev->device; + ar_pci->pci_ps = pci_ps; ar->id.vendor = pdev->vendor; ar->id.device = pdev->device; @@ -2982,6 +3055,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ath10k_pci_ce_deinit(ar); ath10k_pci_irq_disable(ar); + if (ar_pci->pci_ps == 0) { + ret = ath10k_pci_force_wake(ar); + if (ret) { + ath10k_warn(ar, "failed to wake up device : %d\n", ret); + goto err_free_pipes; + } + } + ret = ath10k_pci_init_irq(ar); if (ret) { ath10k_err(ar, "failed to init irqs: %d\n", ret); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 87216b844133..f91bf333cb75 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -219,6 +219,12 @@ struct ath10k_pci { * powersave register state changes. */ bool ps_awake; + + /* pci power save, disable for QCA988X and QCA99X0. + * Writing 'false' to this variable avoids frequent locking + * on MMIO read/write. + */ + bool pci_ps; }; static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) -- cgit v1.2.3 From bc6f9ae6043a219b5afadf0391ce77db401a966f Mon Sep 17 00:00:00 2001 From: Manikanta Pubbisetty Date: Fri, 16 Oct 2015 15:54:52 +0300 Subject: ath10k: make fw stats prints specific to firmware version The patch makes debug stats prints fw specific by adding a new member in wmi_ops. That way it's easier to add fw_stats support to 10.4 firmware. Signed-off-by: Manikanta Pubbisetty Signed-off-by: Tamizh Chelvam Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/debug.c | 267 +-------------------- drivers/net/wireless/ath/ath10k/debug.h | 3 + drivers/net/wireless/ath/ath10k/wmi-ops.h | 13 + drivers/net/wireless/ath/ath10k/wmi-tlv.c | 1 + drivers/net/wireless/ath/ath10k/wmi.c | 379 ++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 10 + 6 files changed, 414 insertions(+), 259 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index eab71e2eb4d7..6cc1aa3449c8 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -291,28 +291,6 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar) spin_unlock_bh(&ar->data_lock); } -static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head) -{ - struct ath10k_fw_stats_peer *i; - size_t num = 0; - - list_for_each_entry(i, head, list) - ++num; - - return num; -} - -static size_t ath10k_debug_fw_stats_num_vdevs(struct list_head *head) -{ - struct ath10k_fw_stats_vdev *i; - size_t num = 0; - - list_for_each_entry(i, head, list) - ++num; - - return num; -} - void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_fw_stats stats = {}; @@ -349,8 +327,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) goto free; } - num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers); - num_vdevs = ath10k_debug_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs); + num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers); + num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs); is_start = (list_empty(&ar->debug.fw_stats.pdevs) && !list_empty(&stats.pdevs)); is_end = (!list_empty(&ar->debug.fw_stats.pdevs) && @@ -435,240 +413,6 @@ static int ath10k_debug_fw_stats_request(struct ath10k *ar) return 0; } -/* FIXME: How to calculate the buffer size sanely? */ -#define ATH10K_FW_STATS_BUF_SIZE (1024*1024) - -static void ath10k_fw_stats_fill(struct ath10k *ar, - struct ath10k_fw_stats *fw_stats, - char *buf) -{ - unsigned int len = 0; - unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE; - const struct ath10k_fw_stats_pdev *pdev; - const struct ath10k_fw_stats_vdev *vdev; - const struct ath10k_fw_stats_peer *peer; - size_t num_peers; - size_t num_vdevs; - int i; - - spin_lock_bh(&ar->data_lock); - - pdev = list_first_entry_or_null(&fw_stats->pdevs, - struct ath10k_fw_stats_pdev, list); - if (!pdev) { - ath10k_warn(ar, "failed to get pdev stats\n"); - goto unlock; - } - - num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers); - num_vdevs = ath10k_debug_fw_stats_num_vdevs(&fw_stats->vdevs); - - len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%30s\n", - "ath10k PDEV stats"); - len += scnprintf(buf + len, buf_len - len, "%30s\n\n", - "================="); - - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Channel noise floor", pdev->ch_noise_floor); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "Channel TX power", pdev->chan_tx_power); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "TX frame count", pdev->tx_frame_count); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "RX frame count", pdev->rx_frame_count); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "RX clear count", pdev->rx_clear_count); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "Cycle count", pdev->cycle_count); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "PHY error count", pdev->phy_err_count); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "RTS bad count", pdev->rts_bad); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "RTS good count", pdev->rts_good); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "FCS bad count", pdev->fcs_bad); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "No beacon count", pdev->no_beacons); - len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", - "MIB int count", pdev->mib_int_count); - - len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%30s\n", - "ath10k PDEV TX stats"); - len += scnprintf(buf + len, buf_len - len, "%30s\n\n", - "================="); - - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "HTT cookies queued", pdev->comp_queued); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "HTT cookies disp.", pdev->comp_delivered); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MSDU queued", pdev->msdu_enqued); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDU queued", pdev->mpdu_enqued); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MSDUs dropped", pdev->wmm_drop); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Local enqued", pdev->local_enqued); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Local freed", pdev->local_freed); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "HW queued", pdev->hw_queued); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PPDUs reaped", pdev->hw_reaped); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Num underruns", pdev->underrun); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PPDUs cleaned", pdev->tx_abort); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDUs requed", pdev->mpdus_requed); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Excessive retries", pdev->tx_ko); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "HW rate", pdev->data_rc); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Sched self tiggers", pdev->self_triggers); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Dropped due to SW retries", - pdev->sw_retry_failure); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Illegal rate phy errors", - pdev->illgl_rate_phy_err); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Pdev continous xretry", pdev->pdev_cont_xretry); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "TX timeout", pdev->pdev_tx_timeout); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PDEV resets", pdev->pdev_resets); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PHY underrun", pdev->phy_underrun); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDU is more than txop limit", pdev->txop_ovf); - - len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%30s\n", - "ath10k PDEV RX stats"); - len += scnprintf(buf + len, buf_len - len, "%30s\n\n", - "================="); - - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Mid PPDU route change", - pdev->mid_ppdu_route_change); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Tot. number of statuses", pdev->status_rcvd); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Extra frags on rings 0", pdev->r0_frags); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Extra frags on rings 1", pdev->r1_frags); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Extra frags on rings 2", pdev->r2_frags); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Extra frags on rings 3", pdev->r3_frags); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MSDUs delivered to HTT", pdev->htt_msdus); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDUs delivered to HTT", pdev->htt_mpdus); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MSDUs delivered to stack", pdev->loc_msdus); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDUs delivered to stack", pdev->loc_mpdus); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "Oversized AMSUs", pdev->oversize_amsdu); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PHY errors", pdev->phy_errs); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "PHY errors drops", pdev->phy_err_drop); - len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", - "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs); - - len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", - "ath10k VDEV stats", num_vdevs); - len += scnprintf(buf + len, buf_len - len, "%30s\n\n", - "================="); - - list_for_each_entry(vdev, &fw_stats->vdevs, list) { - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "vdev id", vdev->vdev_id); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "beacon snr", vdev->beacon_snr); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "data snr", vdev->data_snr); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "num rx frames", vdev->num_rx_frames); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "num rts fail", vdev->num_rts_fail); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "num rts success", vdev->num_rts_success); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "num rx err", vdev->num_rx_err); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "num rx discard", vdev->num_rx_discard); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "num tx not acked", vdev->num_tx_not_acked); - - for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++) - len += scnprintf(buf + len, buf_len - len, - "%25s [%02d] %u\n", - "num tx frames", i, - vdev->num_tx_frames[i]); - - for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++) - len += scnprintf(buf + len, buf_len - len, - "%25s [%02d] %u\n", - "num tx frames retries", i, - vdev->num_tx_frames_retries[i]); - - for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++) - len += scnprintf(buf + len, buf_len - len, - "%25s [%02d] %u\n", - "num tx frames failures", i, - vdev->num_tx_frames_failures[i]); - - for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++) - len += scnprintf(buf + len, buf_len - len, - "%25s [%02d] 0x%08x\n", - "tx rate history", i, - vdev->tx_rate_history[i]); - - for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++) - len += scnprintf(buf + len, buf_len - len, - "%25s [%02d] %u\n", - "beacon rssi history", i, - vdev->beacon_rssi_history[i]); - - len += scnprintf(buf + len, buf_len - len, "\n"); - } - - len += scnprintf(buf + len, buf_len - len, "\n"); - len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", - "ath10k PEER stats", num_peers); - len += scnprintf(buf + len, buf_len - len, "%30s\n\n", - "================="); - - list_for_each_entry(peer, &fw_stats->peers, list) { - len += scnprintf(buf + len, buf_len - len, "%30s %pM\n", - "Peer MAC address", peer->peer_macaddr); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "Peer RSSI", peer->peer_rssi); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "Peer TX rate", peer->peer_tx_rate); - len += scnprintf(buf + len, buf_len - len, "%30s %u\n", - "Peer RX rate", peer->peer_rx_rate); - len += scnprintf(buf + len, buf_len - len, "\n"); - } - -unlock: - spin_unlock_bh(&ar->data_lock); - - if (len >= buf_len) - buf[len - 1] = 0; - else - buf[len] = 0; -} - static int ath10k_fw_stats_open(struct inode *inode, struct file *file) { struct ath10k *ar = inode->i_private; @@ -694,7 +438,12 @@ static int ath10k_fw_stats_open(struct inode *inode, struct file *file) goto err_free; } - ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf); + ret = ath10k_wmi_fw_stats_fill(ar, &ar->debug.fw_stats, buf); + if (ret) { + ath10k_warn(ar, "failed to fill fw stats: %d\n", ret); + goto err_free; + } + file->private_data = buf; mutex_unlock(&ar->conf_mutex); diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index b07639e9b082..7de780c4ec8d 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -55,6 +55,9 @@ enum ath10k_dbg_aggr_mode { ATH10K_DBG_AGGR_MODE_MAX, }; +/* FIXME: How to calculate the buffer size sanely? */ +#define ATH10K_FW_STATS_BUF_SIZE (1024*1024) + extern unsigned int ath10k_debug_mask; __printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...); diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index d3bc6df861e4..b54aa08cb25c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -179,6 +179,9 @@ struct wmi_ops { struct sk_buff *(*gen_adaptive_qcs)(struct ath10k *ar, bool enable); struct sk_buff *(*gen_pdev_get_tpc_config)(struct ath10k *ar, u32 param); + void (*fw_stats_fill)(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf); }; int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); @@ -1289,4 +1292,14 @@ ath10k_wmi_pdev_get_tpc_config(struct ath10k *ar, u32 param) ar->wmi.cmd->pdev_get_tpc_config_cmdid); } +static inline int +ath10k_wmi_fw_stats_fill(struct ath10k *ar, struct ath10k_fw_stats *fw_stats, + char *buf) +{ + if (!ar->wmi.ops->fw_stats_fill) + return -EOPNOTSUPP; + + ar->wmi.ops->fw_stats_fill(ar, fw_stats, buf); + return 0; +} #endif diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index b5849b3fd2f0..8f835480a62c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -3468,6 +3468,7 @@ static const struct wmi_ops wmi_tlv_ops = { .gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state, .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update, .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs, + .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, }; /************/ diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 063469b69d5f..6e7d7a7f6a97 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -6621,6 +6621,381 @@ ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config(struct ath10k *ar, u32 param) return skb; } +size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head) +{ + struct ath10k_fw_stats_peer *i; + size_t num = 0; + + list_for_each_entry(i, head, list) + ++num; + + return num; +} + +size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head) +{ + struct ath10k_fw_stats_vdev *i; + size_t num = 0; + + list_for_each_entry(i, head, list) + ++num; + + return num; +} + +static void +ath10k_wmi_fw_pdev_base_stats_fill(const struct ath10k_fw_stats_pdev *pdev, + char *buf, u32 *length) +{ + u32 len = *length; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s\n", + "ath10k PDEV stats"); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Channel noise floor", pdev->ch_noise_floor); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "Channel TX power", pdev->chan_tx_power); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "TX frame count", pdev->tx_frame_count); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "RX frame count", pdev->rx_frame_count); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "RX clear count", pdev->rx_clear_count); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "Cycle count", pdev->cycle_count); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "PHY error count", pdev->phy_err_count); + + *length = len; +} + +static void +ath10k_wmi_fw_pdev_extra_stats_fill(const struct ath10k_fw_stats_pdev *pdev, + char *buf, u32 *length) +{ + u32 len = *length; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "RTS bad count", pdev->rts_bad); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "RTS good count", pdev->rts_good); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "FCS bad count", pdev->fcs_bad); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "No beacon count", pdev->no_beacons); + len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", + "MIB int count", pdev->mib_int_count); + + len += scnprintf(buf + len, buf_len - len, "\n"); + *length = len; +} + +static void +ath10k_wmi_fw_pdev_tx_stats_fill(const struct ath10k_fw_stats_pdev *pdev, + char *buf, u32 *length) +{ + u32 len = *length; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + + len += scnprintf(buf + len, buf_len - len, "\n%30s\n", + "ath10k PDEV TX stats"); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HTT cookies queued", pdev->comp_queued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HTT cookies disp.", pdev->comp_delivered); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MSDU queued", pdev->msdu_enqued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDU queued", pdev->mpdu_enqued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MSDUs dropped", pdev->wmm_drop); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Local enqued", pdev->local_enqued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Local freed", pdev->local_freed); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HW queued", pdev->hw_queued); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PPDUs reaped", pdev->hw_reaped); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Num underruns", pdev->underrun); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PPDUs cleaned", pdev->tx_abort); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs requed", pdev->mpdus_requed); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Excessive retries", pdev->tx_ko); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HW rate", pdev->data_rc); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Sched self tiggers", pdev->self_triggers); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Dropped due to SW retries", + pdev->sw_retry_failure); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Illegal rate phy errors", + pdev->illgl_rate_phy_err); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Pdev continuous xretry", pdev->pdev_cont_xretry); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "TX timeout", pdev->pdev_tx_timeout); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PDEV resets", pdev->pdev_resets); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PHY underrun", pdev->phy_underrun); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDU is more than txop limit", pdev->txop_ovf); + *length = len; +} + +static void +ath10k_wmi_fw_pdev_rx_stats_fill(const struct ath10k_fw_stats_pdev *pdev, + char *buf, u32 *length) +{ + u32 len = *length; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + + len += scnprintf(buf + len, buf_len - len, "\n%30s\n", + "ath10k PDEV RX stats"); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Mid PPDU route change", + pdev->mid_ppdu_route_change); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Tot. number of statuses", pdev->status_rcvd); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Extra frags on rings 0", pdev->r0_frags); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Extra frags on rings 1", pdev->r1_frags); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Extra frags on rings 2", pdev->r2_frags); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Extra frags on rings 3", pdev->r3_frags); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MSDUs delivered to HTT", pdev->htt_msdus); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs delivered to HTT", pdev->htt_mpdus); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MSDUs delivered to stack", pdev->loc_msdus); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs delivered to stack", pdev->loc_mpdus); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Oversized AMSUs", pdev->oversize_amsdu); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PHY errors", pdev->phy_errs); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "PHY errors drops", pdev->phy_err_drop); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs); + *length = len; +} + +static void +ath10k_wmi_fw_vdev_stats_fill(const struct ath10k_fw_stats_vdev *vdev, + char *buf, u32 *length) +{ + u32 len = *length; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + int i; + + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "vdev id", vdev->vdev_id); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "beacon snr", vdev->beacon_snr); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "data snr", vdev->data_snr); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "num rx frames", vdev->num_rx_frames); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "num rts fail", vdev->num_rts_fail); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "num rts success", vdev->num_rts_success); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "num rx err", vdev->num_rx_err); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "num rx discard", vdev->num_rx_discard); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "num tx not acked", vdev->num_tx_not_acked); + + for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames); i++) + len += scnprintf(buf + len, buf_len - len, + "%25s [%02d] %u\n", + "num tx frames", i, + vdev->num_tx_frames[i]); + + for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_retries); i++) + len += scnprintf(buf + len, buf_len - len, + "%25s [%02d] %u\n", + "num tx frames retries", i, + vdev->num_tx_frames_retries[i]); + + for (i = 0 ; i < ARRAY_SIZE(vdev->num_tx_frames_failures); i++) + len += scnprintf(buf + len, buf_len - len, + "%25s [%02d] %u\n", + "num tx frames failures", i, + vdev->num_tx_frames_failures[i]); + + for (i = 0 ; i < ARRAY_SIZE(vdev->tx_rate_history); i++) + len += scnprintf(buf + len, buf_len - len, + "%25s [%02d] 0x%08x\n", + "tx rate history", i, + vdev->tx_rate_history[i]); + + for (i = 0 ; i < ARRAY_SIZE(vdev->beacon_rssi_history); i++) + len += scnprintf(buf + len, buf_len - len, + "%25s [%02d] %u\n", + "beacon rssi history", i, + vdev->beacon_rssi_history[i]); + + len += scnprintf(buf + len, buf_len - len, "\n"); + *length = len; +} + +static void +ath10k_wmi_fw_peer_stats_fill(const struct ath10k_fw_stats_peer *peer, + char *buf, u32 *length) +{ + u32 len = *length; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + + len += scnprintf(buf + len, buf_len - len, "%30s %pM\n", + "Peer MAC address", peer->peer_macaddr); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "Peer RSSI", peer->peer_rssi); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "Peer TX rate", peer->peer_tx_rate); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "Peer RX rate", peer->peer_rx_rate); + len += scnprintf(buf + len, buf_len - len, "\n"); + *length = len; +} + +void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf) +{ + u32 len = 0; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + const struct ath10k_fw_stats_pdev *pdev; + const struct ath10k_fw_stats_vdev *vdev; + const struct ath10k_fw_stats_peer *peer; + size_t num_peers; + size_t num_vdevs; + + spin_lock_bh(&ar->data_lock); + + pdev = list_first_entry_or_null(&fw_stats->pdevs, + struct ath10k_fw_stats_pdev, list); + if (!pdev) { + ath10k_warn(ar, "failed to get pdev stats\n"); + goto unlock; + } + + num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); + num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); + + ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len); + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k VDEV stats", num_vdevs); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + list_for_each_entry(vdev, &fw_stats->vdevs, list) { + ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len); + } + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k PEER stats", num_peers); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + list_for_each_entry(peer, &fw_stats->peers, list) { + ath10k_wmi_fw_peer_stats_fill(peer, buf, &len); + } + +unlock: + spin_unlock_bh(&ar->data_lock); + + if (len >= buf_len) + buf[len - 1] = 0; + else + buf[len] = 0; +} + +void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf) +{ + unsigned int len = 0; + unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE; + const struct ath10k_fw_stats_pdev *pdev; + const struct ath10k_fw_stats_vdev *vdev; + const struct ath10k_fw_stats_peer *peer; + size_t num_peers; + size_t num_vdevs; + + spin_lock_bh(&ar->data_lock); + + pdev = list_first_entry_or_null(&fw_stats->pdevs, + struct ath10k_fw_stats_pdev, list); + if (!pdev) { + ath10k_warn(ar, "failed to get pdev stats\n"); + goto unlock; + } + + num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); + num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); + + ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len); + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k VDEV stats", num_vdevs); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + list_for_each_entry(vdev, &fw_stats->vdevs, list) { + ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len); + } + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k PEER stats", num_peers); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + list_for_each_entry(peer, &fw_stats->peers, list) { + ath10k_wmi_fw_peer_stats_fill(peer, buf, &len); + } + +unlock: + spin_unlock_bh(&ar->data_lock); + + if (len >= buf_len) + buf[len - 1] = 0; + else + buf[len] = 0; +} + static const struct wmi_ops wmi_ops = { .rx = ath10k_wmi_op_rx, .map_svc = wmi_main_svc_map, @@ -6679,6 +7054,7 @@ static const struct wmi_ops wmi_ops = { .gen_addba_send = ath10k_wmi_op_gen_addba_send, .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ @@ -6744,6 +7120,7 @@ static const struct wmi_ops wmi_10_1_ops = { .gen_addba_send = ath10k_wmi_op_gen_addba_send, .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ @@ -6810,6 +7187,7 @@ static const struct wmi_ops wmi_10_2_ops = { .gen_addba_send = ath10k_wmi_op_gen_addba_send, .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, }; static const struct wmi_ops wmi_10_2_4_ops = { @@ -6872,6 +7250,7 @@ static const struct wmi_ops wmi_10_2_4_ops = { .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, + .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 4c373b27c1a6..6e84d1c1a6ca 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -6098,6 +6098,7 @@ struct ath10k; struct ath10k_vif; struct ath10k_fw_stats_pdev; struct ath10k_fw_stats_peer; +struct ath10k_fw_stats; int ath10k_wmi_attach(struct ath10k *ar); void ath10k_wmi_detach(struct ath10k *ar); @@ -6179,4 +6180,13 @@ void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb); int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb); int ath10k_wmi_op_pull_phyerr_ev(struct ath10k *ar, const void *phyerr_buf, int left_len, struct wmi_phyerr_ev_arg *arg); +void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf); +void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf); +size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head); +size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head); + #endif /* _WMI_H_ */ -- cgit v1.2.3 From 216590355cb0e79fa36c7220176ce850f0e3d276 Mon Sep 17 00:00:00 2001 From: Kiran Patil Date: Wed, 30 Sep 2015 14:09:03 -0400 Subject: i40e: Lock for VSI's MAC filter list This patch introduces a spinlock which is to be used for synchronizing access to VSI's MAC filter list. This patch also synchronizes execution of other codepaths which are accessing VSI's MAC filter list with execution of service_task:sync_vsi_filters. In function i40e_add_vsi, copied out LAA MAC address instead of cloning MAC filter entry because only MAC address is needed to remove MAC VLAN filter from FW/HW. Change-ID: I0e10ac7c715d44aa994239642aa4d57c998573a2 Signed-off-by: Kiran Patil Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 + drivers/net/ethernet/intel/i40e/i40e_fcoe.c | 2 + drivers/net/ethernet/intel/i40e/i40e_main.c | 308 +++++++++++++++++---- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 26 +- 4 files changed, 282 insertions(+), 56 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 7a58b1f9971f..b7818be0f06d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -468,6 +468,8 @@ struct i40e_vsi { #define I40E_VSI_FLAG_VEB_OWNER BIT(1) unsigned long flags; + /* Per VSI lock to protect elements/list (MAC filter) */ + spinlock_t mac_filter_list_lock; struct list_head mac_filter_list; /* VSI stats */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c index 2ec241142e9d..fe5d9bf3ed6d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_fcoe.c +++ b/drivers/net/ethernet/intel/i40e/i40e_fcoe.c @@ -1516,10 +1516,12 @@ void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi) * same PCI function. */ netdev->dev_port = 1; + spin_lock_bh(&vsi->mac_filter_list_lock); i40e_add_filter(vsi, hw->mac.san_addr, 0, false, false); i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0, false, false); i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0, false, false); i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0, false, false); + spin_unlock_bh(&vsi->mac_filter_list_lock); /* use san mac */ ether_addr_copy(netdev->dev_addr, hw->mac.san_addr); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 87a5d09cb087..36cca7b93f36 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1355,6 +1355,9 @@ static int i40e_rm_default_mac_filter(struct i40e_vsi *vsi, u8 *macaddr) * @is_netdev: make sure its a netdev filter, else doesn't matter * * Returns ptr to the filter object or NULL when no memory available. + * + * NOTE: This function is expected to be called with mac_filter_list_lock + * being held. **/ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan, @@ -1413,6 +1416,9 @@ add_filter_out: * @vlan: the vlan * @is_vf: make sure it's a VF filter, else doesn't matter * @is_netdev: make sure it's a netdev filter, else doesn't matter + * + * NOTE: This function is expected to be called with mac_filter_list_lock + * being held. **/ void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan, @@ -1519,8 +1525,10 @@ static int i40e_set_mac(struct net_device *netdev, void *p) element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH; i40e_aq_remove_macvlan(&pf->hw, vsi->seid, &element, 1, NULL); } else { + spin_lock_bh(&vsi->mac_filter_list_lock); i40e_del_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY, false, false); + spin_unlock_bh(&vsi->mac_filter_list_lock); } if (ether_addr_equal(addr->sa_data, hw->mac.addr)) { @@ -1531,10 +1539,12 @@ static int i40e_set_mac(struct net_device *netdev, void *p) element.flags = cpu_to_le16(I40E_AQC_MACVLAN_ADD_PERFECT_MATCH); i40e_aq_add_macvlan(&pf->hw, vsi->seid, &element, 1, NULL); } else { + spin_lock_bh(&vsi->mac_filter_list_lock); f = i40e_add_filter(vsi, addr->sa_data, I40E_VLAN_ANY, false, false); if (f) f->is_laa = true; + spin_unlock_bh(&vsi->mac_filter_list_lock); } i40e_sync_vsi_filters(vsi, false); @@ -1707,6 +1717,8 @@ static void i40e_set_rx_mode(struct net_device *netdev) struct netdev_hw_addr *mca; struct netdev_hw_addr *ha; + spin_lock_bh(&vsi->mac_filter_list_lock); + /* add addr if not already in the filter list */ netdev_for_each_uc_addr(uca, netdev) { if (!i40e_find_mac(vsi, uca->addr, false, true)) { @@ -1754,6 +1766,7 @@ static void i40e_set_rx_mode(struct net_device *netdev) bottom_of_search_loop: continue; } + spin_unlock_bh(&vsi->mac_filter_list_lock); /* check for other flag changes */ if (vsi->current_netdev_flags != vsi->netdev->flags) { @@ -1762,6 +1775,79 @@ bottom_of_search_loop: } } +/** + * i40e_mac_filter_entry_clone - Clones a MAC filter entry + * @src: source MAC filter entry to be clones + * + * Returns the pointer to newly cloned MAC filter entry or NULL + * in case of error + **/ +static struct i40e_mac_filter *i40e_mac_filter_entry_clone( + struct i40e_mac_filter *src) +{ + struct i40e_mac_filter *f; + + f = kzalloc(sizeof(*f), GFP_ATOMIC); + if (!f) + return NULL; + *f = *src; + + INIT_LIST_HEAD(&f->list); + + return f; +} + +/** + * i40e_undo_del_filter_entries - Undo the changes made to MAC filter entries + * @vsi: pointer to vsi struct + * @from: Pointer to list which contains MAC filter entries - changes to + * those entries needs to be undone. + * + * MAC filter entries from list were slated to be removed from device. + **/ +static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi, + struct list_head *from) +{ + struct i40e_mac_filter *f, *ftmp; + + list_for_each_entry_safe(f, ftmp, from, list) { + f->changed = true; + /* Move the element back into MAC filter list*/ + list_move_tail(&f->list, &vsi->mac_filter_list); + } +} + +/** + * i40e_undo_add_filter_entries - Undo the changes made to MAC filter entries + * @vsi: pointer to vsi struct + * + * MAC filter entries from list were slated to be added from device. + **/ +static void i40e_undo_add_filter_entries(struct i40e_vsi *vsi) +{ + struct i40e_mac_filter *f, *ftmp; + + list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + if (!f->changed && f->counter) + f->changed = true; + } +} + +/** + * i40e_cleanup_add_list - Deletes the element from add list and release + * memory + * @add_list: Pointer to list which contains MAC filter entries + **/ +static void i40e_cleanup_add_list(struct list_head *add_list) +{ + struct i40e_mac_filter *f, *ftmp; + + list_for_each_entry_safe(f, ftmp, add_list, list) { + list_del(&f->list); + kfree(f); + } +} + /** * i40e_sync_vsi_filters - Update the VSI filter list to the HW * @vsi: ptr to the VSI @@ -1773,11 +1859,13 @@ bottom_of_search_loop: **/ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) { - struct i40e_mac_filter *f, *ftmp; + struct list_head tmp_del_list, tmp_add_list; + struct i40e_mac_filter *f, *ftmp, *fclone; bool promisc_forced_on = false; bool add_happened = false; int filter_list_len = 0; u32 changed_flags = 0; + bool err_cond = false; i40e_status ret = 0; struct i40e_pf *pf; int num_add = 0; @@ -1798,17 +1886,13 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) vsi->current_netdev_flags = vsi->netdev->flags; } + INIT_LIST_HEAD(&tmp_del_list); + INIT_LIST_HEAD(&tmp_add_list); + if (vsi->flags & I40E_VSI_FLAG_FILTER_CHANGED) { vsi->flags &= ~I40E_VSI_FLAG_FILTER_CHANGED; - filter_list_len = pf->hw.aq.asq_buf_size / - sizeof(struct i40e_aqc_remove_macvlan_element_data); - del_list = kcalloc(filter_list_len, - sizeof(struct i40e_aqc_remove_macvlan_element_data), - GFP_KERNEL); - if (!del_list) - return -ENOMEM; - + spin_lock_bh(&vsi->mac_filter_list_lock); list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { if (!f->changed) continue; @@ -1816,6 +1900,58 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) if (f->counter != 0) continue; f->changed = false; + + /* Move the element into temporary del_list */ + list_move_tail(&f->list, &tmp_del_list); + } + + list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { + if (!f->changed) + continue; + + if (f->counter == 0) + continue; + f->changed = false; + + /* Clone MAC filter entry and add into temporary list */ + fclone = i40e_mac_filter_entry_clone(f); + if (!fclone) { + err_cond = true; + break; + } + list_add_tail(&fclone->list, &tmp_add_list); + } + + /* if failed to clone MAC filter entry - undo */ + if (err_cond) { + i40e_undo_del_filter_entries(vsi, &tmp_del_list); + i40e_undo_add_filter_entries(vsi); + } + spin_unlock_bh(&vsi->mac_filter_list_lock); + + if (err_cond) + i40e_cleanup_add_list(&tmp_add_list); + } + + /* Now process 'del_list' outside the lock */ + if (!list_empty(&tmp_del_list)) { + filter_list_len = pf->hw.aq.asq_buf_size / + sizeof(struct i40e_aqc_remove_macvlan_element_data); + del_list = kcalloc(filter_list_len, + sizeof(struct i40e_aqc_remove_macvlan_element_data), + GFP_KERNEL); + if (!del_list) { + i40e_cleanup_add_list(&tmp_add_list); + + /* Undo VSI's MAC filter entry element updates */ + spin_lock_bh(&vsi->mac_filter_list_lock); + i40e_undo_del_filter_entries(vsi, &tmp_del_list); + i40e_undo_add_filter_entries(vsi); + spin_unlock_bh(&vsi->mac_filter_list_lock); + return -ENOMEM; + } + + list_for_each_entry_safe(f, ftmp, &tmp_del_list, list) { cmd_flags = 0; /* add to delete list */ @@ -1828,10 +1964,6 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) del_list[num_del].flags = cmd_flags; num_del++; - /* unlink from filter list */ - list_del(&f->list); - kfree(f); - /* flush a full buffer */ if (num_del == filter_list_len) { ret = i40e_aq_remove_macvlan(&pf->hw, @@ -1842,12 +1974,18 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) memset(del_list, 0, sizeof(*del_list)); if (ret && aq_err != I40E_AQ_RC_ENOENT) - dev_info(&pf->pdev->dev, - "ignoring delete macvlan error, err %s, aq_err %s while flushing a full buffer\n", - i40e_stat_str(&pf->hw, ret), - i40e_aq_str(&pf->hw, aq_err)); + dev_err(&pf->pdev->dev, + "ignoring delete macvlan error, err %s, aq_err %s while flushing a full buffer\n", + i40e_stat_str(&pf->hw, ret), + i40e_aq_str(&pf->hw, aq_err)); } + /* Release memory for MAC filter entries which were + * synced up with HW. + */ + list_del(&f->list); + kfree(f); } + if (num_del) { ret = i40e_aq_remove_macvlan(&pf->hw, vsi->seid, del_list, num_del, NULL); @@ -1863,6 +2001,9 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) kfree(del_list); del_list = NULL; + } + + if (!list_empty(&tmp_add_list)) { /* do all the adds now */ filter_list_len = pf->hw.aq.asq_buf_size / @@ -1870,16 +2011,19 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) add_list = kcalloc(filter_list_len, sizeof(struct i40e_aqc_add_macvlan_element_data), GFP_KERNEL); - if (!add_list) + if (!add_list) { + /* Purge element from temporary lists */ + i40e_cleanup_add_list(&tmp_add_list); + + /* Undo add filter entries from VSI MAC filter list */ + spin_lock_bh(&vsi->mac_filter_list_lock); + i40e_undo_add_filter_entries(vsi); + spin_unlock_bh(&vsi->mac_filter_list_lock); return -ENOMEM; + } - list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { - if (!f->changed) - continue; + list_for_each_entry_safe(f, ftmp, &tmp_add_list, list) { - if (f->counter == 0) - continue; - f->changed = false; add_happened = true; cmd_flags = 0; @@ -1906,7 +2050,13 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi, bool grab_rtnl) break; memset(add_list, 0, sizeof(*add_list)); } + /* Entries from tmp_add_list were cloned from MAC + * filter list, hence clean those cloned entries + */ + list_del(&f->list); + kfree(f); } + if (num_add) { ret = i40e_aq_add_macvlan(&pf->hw, vsi->seid, add_list, num_add, NULL); @@ -2158,6 +2308,9 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) is_vf = (vsi->type == I40E_VSI_SRIOV); is_netdev = !!(vsi->netdev); + /* Locked once because all functions invoked below iterates list*/ + spin_lock_bh(&vsi->mac_filter_list_lock); + if (is_netdev) { add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, vid, is_vf, is_netdev); @@ -2165,6 +2318,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) dev_info(&vsi->back->pdev->dev, "Could not add vlan filter %d for %pM\n", vid, vsi->netdev->dev_addr); + spin_unlock_bh(&vsi->mac_filter_list_lock); return -ENOMEM; } } @@ -2175,6 +2329,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) dev_info(&vsi->back->pdev->dev, "Could not add vlan filter %d for %pM\n", vid, f->macaddr); + spin_unlock_bh(&vsi->mac_filter_list_lock); return -ENOMEM; } } @@ -2196,6 +2351,7 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) dev_info(&vsi->back->pdev->dev, "Could not add filter 0 for %pM\n", vsi->netdev->dev_addr); + spin_unlock_bh(&vsi->mac_filter_list_lock); return -ENOMEM; } } @@ -2204,22 +2360,28 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) /* Do not assume that I40E_VLAN_ANY should be reset to VLAN 0 */ if (vid > 0 && !vsi->info.pvid) { list_for_each_entry(f, &vsi->mac_filter_list, list) { - if (i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY, - is_vf, is_netdev)) { - i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY, - is_vf, is_netdev); - add_f = i40e_add_filter(vsi, f->macaddr, - 0, is_vf, is_netdev); - if (!add_f) { - dev_info(&vsi->back->pdev->dev, - "Could not add filter 0 for %pM\n", - f->macaddr); - return -ENOMEM; - } + if (!i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY, + is_vf, is_netdev)) + continue; + i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY, + is_vf, is_netdev); + add_f = i40e_add_filter(vsi, f->macaddr, + 0, is_vf, is_netdev); + if (!add_f) { + dev_info(&vsi->back->pdev->dev, + "Could not add filter 0 for %pM\n", + f->macaddr); + spin_unlock_bh(&vsi->mac_filter_list_lock); + return -ENOMEM; } } } + /* Make sure to release before sync_vsi_filter because that + * function will lock/unlock as necessary + */ + spin_unlock_bh(&vsi->mac_filter_list_lock); + if (test_bit(__I40E_DOWN, &vsi->back->state) || test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state)) return 0; @@ -2244,6 +2406,9 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) is_vf = (vsi->type == I40E_VSI_SRIOV); is_netdev = !!(netdev); + /* Locked once because all functions invoked below iterates list */ + spin_lock_bh(&vsi->mac_filter_list_lock); + if (is_netdev) i40e_del_filter(vsi, netdev->dev_addr, vid, is_vf, is_netdev); @@ -2274,6 +2439,7 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) dev_info(&vsi->back->pdev->dev, "Could not add filter %d for %pM\n", I40E_VLAN_ANY, netdev->dev_addr); + spin_unlock_bh(&vsi->mac_filter_list_lock); return -ENOMEM; } } @@ -2282,16 +2448,22 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid) list_for_each_entry(f, &vsi->mac_filter_list, list) { i40e_del_filter(vsi, f->macaddr, 0, is_vf, is_netdev); add_f = i40e_add_filter(vsi, f->macaddr, I40E_VLAN_ANY, - is_vf, is_netdev); + is_vf, is_netdev); if (!add_f) { dev_info(&vsi->back->pdev->dev, "Could not add filter %d for %pM\n", I40E_VLAN_ANY, f->macaddr); + spin_unlock_bh(&vsi->mac_filter_list_lock); return -ENOMEM; } } } + /* Make sure to release before sync_vsi_filter because that + * function with lock/unlock as necessary + */ + spin_unlock_bh(&vsi->mac_filter_list_lock); + if (test_bit(__I40E_DOWN, &vsi->back->state) || test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state)) return 0; @@ -7062,6 +7234,8 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type) /* Setup default MSIX irq handler for VSI */ i40e_vsi_setup_irqhandler(vsi, i40e_msix_clean_rings); + /* Initialize VSI lock */ + spin_lock_init(&vsi->mac_filter_list_lock); pf->vsi[vsi_idx] = vsi; ret = vsi_idx; goto unlock_pf; @@ -8477,17 +8651,26 @@ static int i40e_config_netdev(struct i40e_vsi *vsi) * default a MAC-VLAN filter that accepts any tagged packet * which must be replaced by a normal filter. */ - if (!i40e_rm_default_mac_filter(vsi, mac_addr)) + if (!i40e_rm_default_mac_filter(vsi, mac_addr)) { + spin_lock_bh(&vsi->mac_filter_list_lock); i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, true); + spin_unlock_bh(&vsi->mac_filter_list_lock); + } } else { /* relate the VSI_VMDQ name to the VSI_MAIN name */ snprintf(netdev->name, IFNAMSIZ, "%sv%%d", pf->vsi[pf->lan_vsi]->netdev->name); random_ether_addr(mac_addr); + + spin_lock_bh(&vsi->mac_filter_list_lock); i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, false); + spin_unlock_bh(&vsi->mac_filter_list_lock); } + + spin_lock_bh(&vsi->mac_filter_list_lock); i40e_add_filter(vsi, brdcast, I40E_VLAN_ANY, false, false); + spin_unlock_bh(&vsi->mac_filter_list_lock); ether_addr_copy(netdev->dev_addr, mac_addr); ether_addr_copy(netdev->perm_addr, mac_addr); @@ -8561,10 +8744,13 @@ int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi) static int i40e_add_vsi(struct i40e_vsi *vsi) { int ret = -ENODEV; - struct i40e_mac_filter *f, *ftmp; + u8 laa_macaddr[ETH_ALEN]; + bool found_laa_mac_filter = false; struct i40e_pf *pf = vsi->back; struct i40e_hw *hw = &pf->hw; struct i40e_vsi_context ctxt; + struct i40e_mac_filter *f, *ftmp; + u8 enabled_tc = 0x1; /* TC0 enabled */ int f_count = 0; @@ -8736,32 +8922,41 @@ static int i40e_add_vsi(struct i40e_vsi *vsi) vsi->id = ctxt.vsi_number; } + spin_lock_bh(&vsi->mac_filter_list_lock); /* If macvlan filters already exist, force them to get loaded */ list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) { f->changed = true; f_count++; + /* Expected to have only one MAC filter entry for LAA in list */ if (f->is_laa && vsi->type == I40E_VSI_MAIN) { - struct i40e_aqc_remove_macvlan_element_data element; + ether_addr_copy(laa_macaddr, f->macaddr); + found_laa_mac_filter = true; + } + } + spin_unlock_bh(&vsi->mac_filter_list_lock); - memset(&element, 0, sizeof(element)); - ether_addr_copy(element.mac_addr, f->macaddr); - element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH; - ret = i40e_aq_remove_macvlan(hw, vsi->seid, - &element, 1, NULL); - if (ret) { - /* some older FW has a different default */ - element.flags |= - I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; - i40e_aq_remove_macvlan(hw, vsi->seid, - &element, 1, NULL); - } + if (found_laa_mac_filter) { + struct i40e_aqc_remove_macvlan_element_data element; - i40e_aq_mac_address_write(hw, - I40E_AQC_WRITE_TYPE_LAA_WOL, - f->macaddr, NULL); + memset(&element, 0, sizeof(element)); + ether_addr_copy(element.mac_addr, laa_macaddr); + element.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH; + ret = i40e_aq_remove_macvlan(hw, vsi->seid, + &element, 1, NULL); + if (ret) { + /* some older FW has a different default */ + element.flags |= + I40E_AQC_MACVLAN_DEL_IGNORE_VLAN; + i40e_aq_remove_macvlan(hw, vsi->seid, + &element, 1, NULL); } + + i40e_aq_mac_address_write(hw, + I40E_AQC_WRITE_TYPE_LAA_WOL, + laa_macaddr, NULL); } + if (f_count) { vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; pf->flags |= I40E_FLAG_FILTER_SYNC; @@ -8824,9 +9019,12 @@ int i40e_vsi_release(struct i40e_vsi *vsi) i40e_vsi_disable_irq(vsi); } + spin_lock_bh(&vsi->mac_filter_list_lock); list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) i40e_del_filter(vsi, f->macaddr, f->vlan, f->is_vf, f->is_netdev); + spin_unlock_bh(&vsi->mac_filter_list_lock); + i40e_sync_vsi_filters(vsi, false); i40e_vsi_delete(vsi); diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index a35a204b4eeb..b2d95ee7ec69 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -547,6 +547,8 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) */ if (vf->port_vlan_id) i40e_vsi_add_pvid(vsi, vf->port_vlan_id); + + spin_lock_bh(&vsi->mac_filter_list_lock); f = i40e_add_filter(vsi, vf->default_lan_addr.addr, vf->port_vlan_id ? vf->port_vlan_id : -1, true, false); @@ -559,6 +561,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type) if (!f) dev_info(&pf->pdev->dev, "Could not allocate VF broadcast filter\n"); + spin_unlock_bh(&vsi->mac_filter_list_lock); } /* program mac filter */ @@ -1598,6 +1601,11 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) } vsi = pf->vsi[vf->lan_vsi_idx]; + /* Lock once, because all function inside for loop accesses VSI's + * MAC filter list which needs to be protected using same lock. + */ + spin_lock_bh(&vsi->mac_filter_list_lock); + /* add new addresses to the list */ for (i = 0; i < al->num_elements; i++) { struct i40e_mac_filter *f; @@ -1616,9 +1624,11 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) dev_err(&pf->pdev->dev, "Unable to add VF MAC filter\n"); ret = I40E_ERR_PARAM; + spin_unlock_bh(&vsi->mac_filter_list_lock); goto error_param; } } + spin_unlock_bh(&vsi->mac_filter_list_lock); /* program the updated filter list */ if (i40e_sync_vsi_filters(vsi, false)) @@ -1666,10 +1676,12 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) } vsi = pf->vsi[vf->lan_vsi_idx]; + spin_lock_bh(&vsi->mac_filter_list_lock); /* delete addresses from the list */ for (i = 0; i < al->num_elements; i++) i40e_del_filter(vsi, al->list[i].addr, I40E_VLAN_ANY, true, false); + spin_unlock_bh(&vsi->mac_filter_list_lock); /* program the updated filter list */ if (i40e_sync_vsi_filters(vsi, false)) @@ -2066,6 +2078,11 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) goto error_param; } + /* Lock once because below invoked function add/del_filter requires + * mac_filter_list_lock to be held + */ + spin_lock_bh(&vsi->mac_filter_list_lock); + /* delete the temporary mac address */ i40e_del_filter(vsi, vf->default_lan_addr.addr, vf->port_vlan_id ? vf->port_vlan_id : -1, @@ -2077,6 +2094,8 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) list_for_each_entry(f, &vsi->mac_filter_list, list) i40e_del_filter(vsi, f->macaddr, f->vlan, true, false); + spin_unlock_bh(&vsi->mac_filter_list_lock); + dev_info(&pf->pdev->dev, "Setting MAC %pM on VF %d\n", mac, vf_id); /* program mac filter */ if (i40e_sync_vsi_filters(vsi, false)) { @@ -2109,6 +2128,7 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, u16 vlanprio = vlan_id | (qos << I40E_VLAN_PRIORITY_SHIFT); struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; + bool is_vsi_in_vlan = false; struct i40e_vsi *vsi; struct i40e_vf *vf; int ret = 0; @@ -2138,7 +2158,11 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, /* duplicate request, so just return success */ goto error_pvid; - if (le16_to_cpu(vsi->info.pvid) == 0 && i40e_is_vsi_in_vlan(vsi)) { + spin_lock_bh(&vsi->mac_filter_list_lock); + is_vsi_in_vlan = i40e_is_vsi_in_vlan(vsi); + spin_unlock_bh(&vsi->mac_filter_list_lock); + + if (le16_to_cpu(vsi->info.pvid) == 0 && is_vsi_in_vlan) { dev_err(&pf->pdev->dev, "VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\nPlease unload and reload the VF driver for this change to take effect.\n", vf_id); -- cgit v1.2.3 From d08f55585f22c38db5fcbed509a71d925e0509c1 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 16 Sep 2015 19:01:08 -0700 Subject: i40evf: fix overlong BIT defines The defines from the RSS enabling call were mistakenly missed in the patches to the i40e which should have been to i40evf as well. This is a follow up to (commit ed921559886dd40528) "fix 32 bit build warnings". Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40e_common.c | 5 ----- drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 14 +++++++------- 2 files changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c index 7435fb396dcd..a4c5a49ddbcf 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_common.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c @@ -443,9 +443,6 @@ static i40e_status i40e_aq_get_set_rss_lut(struct i40e_hw *hw, I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT) & I40E_AQC_SET_RSS_LUT_TABLE_TYPE_MASK)); - cmd_resp->addr_high = cpu_to_le32(high_16_bits((u64)lut)); - cmd_resp->addr_low = cpu_to_le32(lower_32_bits((u64)lut)); - status = i40evf_asq_send_command(hw, &desc, lut, lut_size, NULL); return status; @@ -520,8 +517,6 @@ static i40e_status i40e_aq_get_set_rss_key(struct i40e_hw *hw, I40E_AQC_SET_RSS_KEY_VSI_ID_SHIFT) & I40E_AQC_SET_RSS_KEY_VSI_ID_MASK)); cmd_resp->vsi_id |= cpu_to_le16((u16)I40E_AQC_SET_RSS_KEY_VSI_VALID); - cmd_resp->addr_high = cpu_to_le32(high_16_bits((u64)key)); - cmd_resp->addr_low = cpu_to_le32(lower_32_bits((u64)key)); status = i40evf_asq_send_command(hw, &desc, key, key_size, NULL); diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index c4f5a4eb2907..03275eb54cc4 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -89,16 +89,16 @@ enum i40e_dyn_idx_t { BIT_ULL(I40E_FILTER_PCTYPE_L2_PAYLOAD)) #define I40E_DEFAULT_RSS_HENA_EXPANDED (I40E_DEFAULT_RSS_HENA | \ - BIT(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \ - BIT(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \ - BIT(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \ - BIT(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \ - BIT(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \ - BIT(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP)) + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) | \ + BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \ + BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \ + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK) | \ + BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \ + BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP)) #define i40e_pf_get_default_rss_hena(pf) \ (((pf)->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) ? \ - I40E_DEFAULT_RSS_HENA_EXPANDED : I40E_DEFAULT_RSS_HENA) + I40E_DEFAULT_RSS_HENA_EXPANDED : I40E_DEFAULT_RSS_HENA) /* Supported Rx Buffer Sizes */ #define I40E_RXBUFFER_512 512 /* Used for packet split */ -- cgit v1.2.3 From 07f89be81fa51ec85456559d7db9bc71379a20c1 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Date: Thu, 24 Sep 2015 15:26:32 -0700 Subject: i40e: Fix basic support for X722 devices Acquire NVM, before issuing an AQ read nvm command for X722. We need to acquire the NVM before issuing an AQ read to the NVM otherwise we will get EBUSY from the FW. Also release when done. This fixes the two X722 issues with respect to eeprom checksum verify and reading NVM version info. With this patch in place, i40e driver will provide basic support for X722 devices. Signed-off-by: Anjali Singhai Jain Acked-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 3 +++ drivers/net/ethernet/intel/i40e/i40e_nvm.c | 31 +++++++++++++++++++++------ drivers/net/ethernet/intel/i40e/i40e_type.h | 3 +++ 3 files changed, 31 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index daa6b177fdb7..7f456e91cd93 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -958,6 +958,9 @@ i40e_status i40e_init_shared_code(struct i40e_hw *hw) else hw->pf_id = (u8)(func_rid & 0x7); + if (hw->mac.type == I40E_MAC_X722) + hw->flags |= I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE; + status = i40e_init_nvm(hw); return status; } diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 875a8ccc2611..58e384a372a0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -290,9 +290,18 @@ static i40e_status i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset, i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset, u16 *data) { - if (hw->mac.type == I40E_MAC_X722) - return i40e_read_nvm_word_aq(hw, offset, data); - return i40e_read_nvm_word_srctl(hw, offset, data); + enum i40e_status_code ret_code = 0; + + if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) { + ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); + if (!ret_code) { + ret_code = i40e_read_nvm_word_aq(hw, offset, data); + i40e_release_nvm(hw); + } + } else { + ret_code = i40e_read_nvm_word_srctl(hw, offset, data); + } + return ret_code; } /** @@ -397,9 +406,19 @@ read_nvm_buffer_aq_exit: i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset, u16 *words, u16 *data) { - if (hw->mac.type == I40E_MAC_X722) - return i40e_read_nvm_buffer_aq(hw, offset, words, data); - return i40e_read_nvm_buffer_srctl(hw, offset, words, data); + enum i40e_status_code ret_code = 0; + + if (hw->flags & I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE) { + ret_code = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); + if (!ret_code) { + ret_code = i40e_read_nvm_buffer_aq(hw, offset, words, + data); + i40e_release_nvm(hw); + } + } else { + ret_code = i40e_read_nvm_buffer_srctl(hw, offset, words, data); + } + return ret_code; } /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 9c4a4573c28f..f631ca017d81 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -544,6 +544,9 @@ struct i40e_hw { struct i40e_dcbx_config remote_dcbx_config; /* Peer Cfg */ struct i40e_dcbx_config desired_dcbx_config; /* CEE Desired Cfg */ +#define I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE BIT_ULL(0) + u64 flags; + /* debug mask */ u32 debug_mask; char err_str[16]; -- cgit v1.2.3 From 5d3465a1e4c01be455ef00834ec365e578942d67 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 29 Sep 2015 15:19:50 -0700 Subject: i40e/i40evf: use napi_schedule_irqoff() The i40e_intr and i40e/i40evf_msix_clean_rings functions run from hard interrupt context or with interrupts already disabled in netpoll. They can use napi_schedule_irqoff() instead of napi_schedule() Signed-off-by: Alexander Duyck Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ++++-- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 36cca7b93f36..7d52092947dc 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3267,7 +3267,7 @@ static irqreturn_t i40e_msix_clean_rings(int irq, void *data) if (!q_vector->tx.ring && !q_vector->rx.ring) return IRQ_HANDLED; - napi_schedule(&q_vector->napi); + napi_schedule_irqoff(&q_vector->napi); return IRQ_HANDLED; } @@ -3436,6 +3436,8 @@ static irqreturn_t i40e_intr(int irq, void *data) /* only q0 is used in MSI/Legacy mode, and none are used in MSIX */ if (icr0 & I40E_PFINT_ICR0_QUEUE_0_MASK) { + struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi]; + struct i40e_q_vector *q_vector = vsi->q_vectors[0]; /* temporarily disable queue cause for NAPI processing */ u32 qval = rd32(hw, I40E_QINT_RQCTL(0)); @@ -3448,7 +3450,7 @@ static irqreturn_t i40e_intr(int irq, void *data) wr32(hw, I40E_QINT_TQCTL(0), qval); if (!test_bit(__I40E_DOWN, &pf->state)) - napi_schedule(&pf->vsi[pf->lan_vsi]->q_vectors[0]->napi); + napi_schedule_irqoff(&q_vector->napi); } if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) { diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 4c4340cc4f45..1dd5245cbc94 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -334,7 +334,7 @@ static irqreturn_t i40evf_msix_clean_rings(int irq, void *data) if (!q_vector->tx.ring && !q_vector->rx.ring) return IRQ_HANDLED; - napi_schedule(&q_vector->napi); + napi_schedule_irqoff(&q_vector->napi); return IRQ_HANDLED; } -- cgit v1.2.3 From b9029e941dd66d2bc2ab529807a1eef4444f62f0 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Mon, 28 Sep 2015 14:16:50 -0400 Subject: i40evf: don't give up When the VF driver is unable to communicate with the PF, it just gives up and never tries again. Aside from the obvious character flaw that this shows, it's also a lousy user experience. When PF communications fail, wait five seconds, and try again. And again. Don't give up, little VF driver! Your prince will come! Change-ID: Ia1378a39879883563b8faffce819f375821f9585 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 1dd5245cbc94..ce997902f5a3 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2357,9 +2357,12 @@ err_alloc: err: /* Things went into the weeds, so try again later */ if (++adapter->aq_wait_count > I40EVF_AQ_MAX_ERR) { - dev_err(&pdev->dev, "Failed to communicate with PF; giving up\n"); + dev_err(&pdev->dev, "Failed to communicate with PF; waiting before retry\n"); adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED; - return; /* do not reschedule */ + i40evf_shutdown_adminq(hw); + adapter->state = __I40EVF_STARTUP; + schedule_delayed_work(&adapter->init_task, HZ * 5); + return; } schedule_delayed_work(&adapter->init_task, HZ); } -- cgit v1.2.3 From 8f5e39ce9214888464d34ef7949e56bdc999b46c Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Mon, 28 Sep 2015 14:16:51 -0400 Subject: i40e/i40evf: refactor IRQ enable function This change moves a multi-line register setting into a function which simplifies reading the flow of the enable function. This also fixes a bug where the enable function was enabling the interrupt twice while trying to update the two interrupt throttle rate thresholds for Rx and Tx. Change-ID: Ie308f9d0d48540204590cb9d7a5a7b1196f959bb Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 112 +++++++++++++++----------- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 108 ++++++++++++++----------- 2 files changed, 128 insertions(+), 92 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 512707c2898e..889d25d6fde2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -815,6 +815,8 @@ void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector) * i40e_set_new_dynamic_itr - Find new ITR level * @rc: structure containing ring performance data * + * Returns true if ITR changed, false if not + * * Stores a new ITR value based on packets and byte counts during * the last interrupt. The advantage of per interrupt computation * is faster updates and more accurate ITR for the current traffic @@ -823,14 +825,14 @@ void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector) * testing data as well as attempting to minimize response time * while increasing bulk throughput. **/ -static void i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) +static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) { enum i40e_latency_range new_latency_range = rc->latency_range; u32 new_itr = rc->itr; int bytes_per_int; if (rc->total_packets == 0 || !rc->itr) - return; + return false; /* simple throttlerate management * 0-10MB/s lowest (100000 ints/s) @@ -874,11 +876,15 @@ static void i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) break; } - if (new_itr != rc->itr) - rc->itr = new_itr; - rc->total_bytes = 0; rc->total_packets = 0; + + if (new_itr != rc->itr) { + rc->itr = new_itr; + return true; + } + + return false; } /** @@ -1747,6 +1753,21 @@ static int i40e_clean_rx_irq_1buf(struct i40e_ring *rx_ring, int budget) return total_rx_packets; } +static u32 i40e_buildreg_itr(const int type, const u16 itr) +{ + u32 val; + + val = I40E_PFINT_DYN_CTLN_INTENA_MASK | + I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | + (type << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) | + (itr << I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT); + + return val; +} + +/* a small macro to shorten up some long lines */ +#define INTREG I40E_PFINT_DYN_CTLN + /** * i40e_update_enable_itr - Update itr and re-enable MSIX interrupt * @vsi: the VSI we care about @@ -1757,54 +1778,53 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector) { struct i40e_hw *hw = &vsi->back->hw; - u16 old_itr; + bool rx = false, tx = false; + u32 rxval, txval; int vector; - u32 val; vector = (q_vector->v_idx + vsi->base_vector); + + rxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0); + if (ITR_IS_DYNAMIC(vsi->rx_itr_setting)) { - old_itr = q_vector->rx.itr; - i40e_set_new_dynamic_itr(&q_vector->rx); - if (old_itr != q_vector->rx.itr) { - val = I40E_PFINT_DYN_CTLN_INTENA_MASK | - I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | - (I40E_RX_ITR << - I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) | - (q_vector->rx.itr << - I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT); - } else { - val = I40E_PFINT_DYN_CTLN_INTENA_MASK | - I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | - (I40E_ITR_NONE << - I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT); - } - if (!test_bit(__I40E_DOWN, &vsi->state)) - wr32(hw, I40E_PFINT_DYN_CTLN(vector - 1), val); - } else { - i40e_irq_dynamic_enable(vsi, q_vector->v_idx); + rx = i40e_set_new_dynamic_itr(&q_vector->rx); + rxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr); } + if (ITR_IS_DYNAMIC(vsi->tx_itr_setting)) { - old_itr = q_vector->tx.itr; - i40e_set_new_dynamic_itr(&q_vector->tx); - if (old_itr != q_vector->tx.itr) { - val = I40E_PFINT_DYN_CTLN_INTENA_MASK | - I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | - (I40E_TX_ITR << - I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) | - (q_vector->tx.itr << - I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT); - } else { - val = I40E_PFINT_DYN_CTLN_INTENA_MASK | - I40E_PFINT_DYN_CTLN_CLEARPBA_MASK | - (I40E_ITR_NONE << - I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT); - } - if (!test_bit(__I40E_DOWN, &vsi->state)) - wr32(hw, I40E_PFINT_DYN_CTLN(q_vector->v_idx + - vsi->base_vector - 1), val); - } else { - i40e_irq_dynamic_enable(vsi, q_vector->v_idx); + tx = i40e_set_new_dynamic_itr(&q_vector->tx); + txval = i40e_buildreg_itr(I40E_TX_ITR, q_vector->tx.itr); } + + if (rx || tx) { + /* get the higher of the two ITR adjustments and + * use the same value for both ITR registers + * when in adaptive mode (Rx and/or Tx) + */ + u16 itr = max(q_vector->tx.itr, q_vector->rx.itr); + + q_vector->tx.itr = q_vector->rx.itr = itr; + txval = i40e_buildreg_itr(I40E_TX_ITR, itr); + tx = true; + rxval = i40e_buildreg_itr(I40E_RX_ITR, itr); + rx = true; + } + + /* only need to enable the interrupt once, but need + * to possibly update both ITR values + */ + if (rx) { + /* set the INTENA_MSK_MASK so that this first write + * won't actually enable the interrupt, instead just + * updating the ITR (it's bit 31 PF and VF) + */ + rxval |= BIT(31); + /* don't check _DOWN because interrupt isn't being enabled */ + wr32(hw, INTREG(vector - 1), rxval); + } + + if (!test_bit(__I40E_DOWN, &vsi->state)) + wr32(hw, INTREG(vector - 1), txval); } /** diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 97493a4164eb..597e0964c232 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -318,6 +318,8 @@ static void i40evf_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector * i40e_set_new_dynamic_itr - Find new ITR level * @rc: structure containing ring performance data * + * Returns true if ITR changed, false if not + * * Stores a new ITR value based on packets and byte counts during * the last interrupt. The advantage of per interrupt computation * is faster updates and more accurate ITR for the current traffic @@ -326,14 +328,14 @@ static void i40evf_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector * testing data as well as attempting to minimize response time * while increasing bulk throughput. **/ -static void i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) +static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) { enum i40e_latency_range new_latency_range = rc->latency_range; u32 new_itr = rc->itr; int bytes_per_int; if (rc->total_packets == 0 || !rc->itr) - return; + return false; /* simple throttlerate management * 0-10MB/s lowest (100000 ints/s) @@ -377,11 +379,15 @@ static void i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) break; } - if (new_itr != rc->itr) - rc->itr = new_itr; - rc->total_bytes = 0; rc->total_packets = 0; + + if (new_itr != rc->itr) { + rc->itr = new_itr; + return true; + } + + return false; } /* @@ -1187,6 +1193,21 @@ static int i40e_clean_rx_irq_1buf(struct i40e_ring *rx_ring, int budget) return total_rx_packets; } +static u32 i40e_buildreg_itr(const int type, const u16 itr) +{ + u32 val; + + val = I40E_VFINT_DYN_CTLN1_INTENA_MASK | + I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK | + (type << I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) | + (itr << I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT); + + return val; +} + +/* a small macro to shorten up some long lines */ +#define INTREG I40E_VFINT_DYN_CTLN1 + /** * i40e_update_enable_itr - Update itr and re-enable MSIX interrupt * @vsi: the VSI we care about @@ -1197,55 +1218,50 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector) { struct i40e_hw *hw = &vsi->back->hw; - u16 old_itr; + bool rx = false, tx = false; + u32 rxval, txval; int vector; - u32 val; vector = (q_vector->v_idx + vsi->base_vector); + rxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0); + if (ITR_IS_DYNAMIC(vsi->rx_itr_setting)) { - old_itr = q_vector->rx.itr; - i40e_set_new_dynamic_itr(&q_vector->rx); - if (old_itr != q_vector->rx.itr) { - val = I40E_VFINT_DYN_CTLN1_INTENA_MASK | - I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK | - (I40E_RX_ITR << - I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) | - (q_vector->rx.itr << - I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT); - } else { - val = I40E_VFINT_DYN_CTLN1_INTENA_MASK | - I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK | - (I40E_ITR_NONE << - I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT); - } - if (!test_bit(__I40E_DOWN, &vsi->state)) - wr32(hw, I40E_VFINT_DYN_CTLN1(vector - 1), val); - } else { - i40evf_irq_enable_queues(vsi->back, 1 - << q_vector->v_idx); + rx = i40e_set_new_dynamic_itr(&q_vector->rx); + rxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr); } if (ITR_IS_DYNAMIC(vsi->tx_itr_setting)) { - old_itr = q_vector->tx.itr; - i40e_set_new_dynamic_itr(&q_vector->tx); - if (old_itr != q_vector->tx.itr) { - val = I40E_VFINT_DYN_CTLN1_INTENA_MASK | - I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK | - (I40E_TX_ITR << - I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT) | - (q_vector->tx.itr << - I40E_VFINT_DYN_CTLN1_INTERVAL_SHIFT); + tx = i40e_set_new_dynamic_itr(&q_vector->tx); + txval = i40e_buildreg_itr(I40E_TX_ITR, q_vector->tx.itr); + } + if (rx || tx) { + /* get the higher of the two ITR adjustments and + * use the same value for both ITR registers + * when in adaptive mode (Rx and/or Tx) + */ + u16 itr = max(q_vector->tx.itr, q_vector->rx.itr); - } else { - val = I40E_VFINT_DYN_CTLN1_INTENA_MASK | - I40E_VFINT_DYN_CTLN1_CLEARPBA_MASK | - (I40E_ITR_NONE << - I40E_VFINT_DYN_CTLN1_ITR_INDX_SHIFT); - } - if (!test_bit(__I40E_DOWN, &vsi->state)) - wr32(hw, I40E_VFINT_DYN_CTLN1(vector - 1), val); - } else { - i40evf_irq_enable_queues(vsi->back, BIT(q_vector->v_idx)); + q_vector->tx.itr = q_vector->rx.itr = itr; + txval = i40e_buildreg_itr(I40E_TX_ITR, itr); + tx = true; + rxval = i40e_buildreg_itr(I40E_RX_ITR, itr); + rx = true; } + + /* only need to enable the interrupt once, but need + * to possibly update both ITR values + */ + if (rx) { + /* set the INTENA_MSK_MASK so that this first write + * won't actually enable the interrupt, instead just + * updating the ITR (it's bit 31 PF and VF) + */ + rxval |= BIT(31); + /* don't check _DOWN because interrupt isn't being enabled */ + wr32(hw, INTREG(vector - 1), rxval); + } + + if (!test_bit(__I40E_DOWN, &vsi->state)) + wr32(hw, INTREG(vector - 1), txval); } /** -- cgit v1.2.3 From 51cc6d9fccde27310b7dfba2be268ff5b8dcf52d Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Mon, 28 Sep 2015 14:16:52 -0400 Subject: i40e/i40evf: fix bug in throttle rate math The driver was using a value expressed in 2us increments for the divisor to figure out our bytes/usec values. Fix the usecs variable to contain a value in microseconds. Change-ID: I5c20493103c295d6f201947bb908add7040b7c41 Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 9 ++++++++- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 889d25d6fde2..c96e581cc2b7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -830,6 +830,7 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) enum i40e_latency_range new_latency_range = rc->latency_range; u32 new_itr = rc->itr; int bytes_per_int; + int usecs; if (rc->total_packets == 0 || !rc->itr) return false; @@ -838,8 +839,14 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) * 0-10MB/s lowest (100000 ints/s) * 10-20MB/s low (20000 ints/s) * 20-1249MB/s bulk (8000 ints/s) + * + * The math works out because the divisor is in 10^(-6) which + * turns the bytes/us input value into MB/s values, but + * make sure to use usecs, as the register values written + * are in 2 usec increments in the ITR registers. */ - bytes_per_int = rc->total_bytes / rc->itr; + usecs = (rc->itr << 1); + bytes_per_int = rc->total_bytes / usecs; switch (new_latency_range) { case I40E_LOWEST_LATENCY: if (bytes_per_int > 10) diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 597e0964c232..7d98042338e0 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -333,6 +333,7 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) enum i40e_latency_range new_latency_range = rc->latency_range; u32 new_itr = rc->itr; int bytes_per_int; + int usecs; if (rc->total_packets == 0 || !rc->itr) return false; @@ -341,8 +342,14 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) * 0-10MB/s lowest (100000 ints/s) * 10-20MB/s low (20000 ints/s) * 20-1249MB/s bulk (8000 ints/s) + * + * The math works out because the divisor is in 10^(-6) which + * turns the bytes/us input value into MB/s values, but + * make sure to use usecs, as the register values written + * are in 2 usec increments in the ITR registers. */ - bytes_per_int = rc->total_bytes / rc->itr; + usecs = (rc->itr << 1); + bytes_per_int = rc->total_bytes / usecs; switch (new_latency_range) { case I40E_LOWEST_LATENCY: if (bytes_per_int > 10) -- cgit v1.2.3 From c56625d59726ee2dc4dfd91c8b6c22098abe1ac4 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Mon, 28 Sep 2015 14:16:53 -0400 Subject: i40e/i40evf: change dynamic interrupt thresholds The dynamic algorithm, while now working, doesn't have good performance in 40G mode. One part of this patch addresses the high CPU utilization of some small streaming workloads that the driver should reduce CPU in. It also changes the minimum ITR that the dynamic algorithm will settle on, causing our minimum latency to go from 12us to about 14us, when using adaptive mode. It also changes the BULK interrupt rate to allow maximum throughput on a 40Gb connection with a single thread of transmit, clamping interrupt rate to 8000 for TX makes single thread traffic go too slow. The new ULTRA bulk setting is introduced and is used when the Rx packet rate on this queue exceeds 40000 packets per second. This value of 40000 was chosen because the automatic tuning of minimum ITR=20us means that a single queue can't quite achieve that many packets per second from a round-robin test. Change-ID: Icce8faa128688ca5fd2c4229bdd9726877a92ea2 Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 27 +++++++++++++++++++++------ drivers/net/ethernet/intel/i40e/i40e_txrx.h | 3 +++ drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 27 +++++++++++++++++++++------ drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 3 +++ 4 files changed, 48 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index c96e581cc2b7..7aea14389d7b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -828,6 +828,7 @@ void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector) static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) { enum i40e_latency_range new_latency_range = rc->latency_range; + struct i40e_q_vector *qv = rc->ring->q_vector; u32 new_itr = rc->itr; int bytes_per_int; int usecs; @@ -836,9 +837,10 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) return false; /* simple throttlerate management - * 0-10MB/s lowest (100000 ints/s) + * 0-10MB/s lowest (50000 ints/s) * 10-20MB/s low (20000 ints/s) - * 20-1249MB/s bulk (8000 ints/s) + * 20-1249MB/s bulk (18000 ints/s) + * > 40000 Rx packets per second (8000 ints/s) * * The math works out because the divisor is in 10^(-6) which * turns the bytes/us input value into MB/s values, but @@ -859,24 +861,37 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) new_latency_range = I40E_LOWEST_LATENCY; break; case I40E_BULK_LATENCY: - if (bytes_per_int <= 20) - new_latency_range = I40E_LOW_LATENCY; - break; + case I40E_ULTRA_LATENCY: default: if (bytes_per_int <= 20) new_latency_range = I40E_LOW_LATENCY; break; } + + /* this is to adjust RX more aggressively when streaming small + * packets. The value of 40000 was picked as it is just beyond + * what the hardware can receive per second if in low latency + * mode. + */ +#define RX_ULTRA_PACKET_RATE 40000 + + if ((((rc->total_packets * 1000000) / usecs) > RX_ULTRA_PACKET_RATE) && + (&qv->rx == rc)) + new_latency_range = I40E_ULTRA_LATENCY; + rc->latency_range = new_latency_range; switch (new_latency_range) { case I40E_LOWEST_LATENCY: - new_itr = I40E_ITR_100K; + new_itr = I40E_ITR_50K; break; case I40E_LOW_LATENCY: new_itr = I40E_ITR_20K; break; case I40E_BULK_LATENCY: + new_itr = I40E_ITR_18K; + break; + case I40E_ULTRA_LATENCY: new_itr = I40E_ITR_8K; break; default: diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 7c0ed84b296d..0fe7eb77cae5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -32,7 +32,9 @@ #define I40E_MAX_ITR 0x0FF0 /* reg uses 2 usec resolution */ #define I40E_MIN_ITR 0x0001 /* reg uses 2 usec resolution */ #define I40E_ITR_100K 0x0005 +#define I40E_ITR_50K 0x000A #define I40E_ITR_20K 0x0019 +#define I40E_ITR_18K 0x001B #define I40E_ITR_8K 0x003E #define I40E_ITR_4K 0x007A #define I40E_MAX_INTRL 0x3B /* reg uses 4 usec resolution */ @@ -296,6 +298,7 @@ enum i40e_latency_range { I40E_LOWEST_LATENCY = 0, I40E_LOW_LATENCY = 1, I40E_BULK_LATENCY = 2, + I40E_ULTRA_LATENCY = 3, }; struct i40e_ring_container { diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 7d98042338e0..d76fe4a948df 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -331,6 +331,7 @@ static void i40evf_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) { enum i40e_latency_range new_latency_range = rc->latency_range; + struct i40e_q_vector *qv = rc->ring->q_vector; u32 new_itr = rc->itr; int bytes_per_int; int usecs; @@ -339,9 +340,10 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) return false; /* simple throttlerate management - * 0-10MB/s lowest (100000 ints/s) + * 0-10MB/s lowest (50000 ints/s) * 10-20MB/s low (20000 ints/s) - * 20-1249MB/s bulk (8000 ints/s) + * 20-1249MB/s bulk (18000 ints/s) + * > 40000 Rx packets per second (8000 ints/s) * * The math works out because the divisor is in 10^(-6) which * turns the bytes/us input value into MB/s values, but @@ -362,24 +364,37 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) new_latency_range = I40E_LOWEST_LATENCY; break; case I40E_BULK_LATENCY: - if (bytes_per_int <= 20) - new_latency_range = I40E_LOW_LATENCY; - break; + case I40E_ULTRA_LATENCY: default: if (bytes_per_int <= 20) new_latency_range = I40E_LOW_LATENCY; break; } + + /* this is to adjust RX more aggressively when streaming small + * packets. The value of 40000 was picked as it is just beyond + * what the hardware can receive per second if in low latency + * mode. + */ +#define RX_ULTRA_PACKET_RATE 40000 + + if ((((rc->total_packets * 1000000) / usecs) > RX_ULTRA_PACKET_RATE) && + (&qv->rx == rc)) + new_latency_range = I40E_ULTRA_LATENCY; + rc->latency_range = new_latency_range; switch (new_latency_range) { case I40E_LOWEST_LATENCY: - new_itr = I40E_ITR_100K; + new_itr = I40E_ITR_50K; break; case I40E_LOW_LATENCY: new_itr = I40E_ITR_20K; break; case I40E_BULK_LATENCY: + new_itr = I40E_ITR_18K; + break; + case I40E_ULTRA_LATENCY: new_itr = I40E_ITR_8K; break; default: diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index 03275eb54cc4..e2352b886b77 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -32,7 +32,9 @@ #define I40E_MAX_ITR 0x0FF0 /* reg uses 2 usec resolution */ #define I40E_MIN_ITR 0x0001 /* reg uses 2 usec resolution */ #define I40E_ITR_100K 0x0005 +#define I40E_ITR_50K 0x000A #define I40E_ITR_20K 0x0019 +#define I40E_ITR_18K 0x001B #define I40E_ITR_8K 0x003E #define I40E_ITR_4K 0x007A #define I40E_MAX_INTRL 0x3B /* reg uses 4 usec resolution */ @@ -291,6 +293,7 @@ enum i40e_latency_range { I40E_LOWEST_LATENCY = 0, I40E_LOW_LATENCY = 1, I40E_BULK_LATENCY = 2, + I40E_ULTRA_LATENCY = 3, }; struct i40e_ring_container { -- cgit v1.2.3 From ee2319cf17ee64bbd0096f2f8f3f8390c93b1e39 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Mon, 28 Sep 2015 14:16:54 -0400 Subject: i40e/i40evf: adjust interrupt throttle less frequently The adaptive ITR (interrupt throttle rate) algorithm was adjusting the hardware's interrupt rate too frequently. This caused a lot of variation in the interrupt rate for fairly constant workloads. Change the code to have a counter and adjust only once every N number of interrupts. Change-ID: I0460f1f86571037484eca5aca36ac4d889cb8389 Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 2 ++ drivers/net/ethernet/intel/i40e/i40e_main.c | 2 ++ drivers/net/ethernet/intel/i40e/i40e_txrx.c | 22 ++++++++++++++++++++-- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 4 ++-- drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 23 +++++++++++++++++++++-- drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 4 ++-- drivers/net/ethernet/intel/i40evf/i40evf.h | 2 ++ drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 ++ 8 files changed, 53 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index b7818be0f06d..7c2b2e891f62 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -577,6 +577,8 @@ struct i40e_q_vector { struct rcu_head rcu; /* to avoid race with update stats on free */ char name[I40E_INT_NAME_STR_LEN]; bool arm_wb_state; +#define ITR_COUNTDOWN_START 100 + u8 itr_countdown; /* when 0 should adjust ITR */ } ____cacheline_internodealigned_in_smp; /* lan device */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 7d52092947dc..e0142de018e6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -3087,6 +3087,7 @@ static void i40e_vsi_configure_msix(struct i40e_vsi *vsi) for (i = 0; i < vsi->num_q_vectors; i++, vector++) { struct i40e_q_vector *q_vector = vsi->q_vectors[i]; + q_vector->itr_countdown = ITR_COUNTDOWN_START; q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting); q_vector->rx.latency_range = I40E_LOW_LATENCY; wr32(hw, I40E_PFINT_ITRN(I40E_RX_ITR, vector - 1), @@ -3182,6 +3183,7 @@ static void i40e_configure_msi_and_legacy(struct i40e_vsi *vsi) u32 val; /* set the ITR configuration */ + q_vector->itr_countdown = ITR_COUNTDOWN_START; q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting); q_vector->rx.latency_range = I40E_LOW_LATENCY; wr32(hw, I40E_PFINT_ITR0(I40E_RX_ITR), q_vector->rx.itr); diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 7aea14389d7b..006f0fb4720c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -845,10 +845,12 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) * The math works out because the divisor is in 10^(-6) which * turns the bytes/us input value into MB/s values, but * make sure to use usecs, as the register values written - * are in 2 usec increments in the ITR registers. + * are in 2 usec increments in the ITR registers, and make sure + * to use the smoothed values that the countdown timer gives us. */ - usecs = (rc->itr << 1); + usecs = (rc->itr << 1) * ITR_COUNTDOWN_START; bytes_per_int = rc->total_bytes / usecs; + switch (new_latency_range) { case I40E_LOWEST_LATENCY: if (bytes_per_int > 10) @@ -1806,8 +1808,17 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, vector = (q_vector->v_idx + vsi->base_vector); + /* avoid dynamic calculation if in countdown mode OR if + * all dynamic is disabled + */ rxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0); + if (q_vector->itr_countdown > 0 || + (!ITR_IS_DYNAMIC(vsi->rx_itr_setting) && + !ITR_IS_DYNAMIC(vsi->tx_itr_setting))) { + goto enable_int; + } + if (ITR_IS_DYNAMIC(vsi->rx_itr_setting)) { rx = i40e_set_new_dynamic_itr(&q_vector->rx); rxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr); @@ -1845,8 +1856,15 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, wr32(hw, INTREG(vector - 1), rxval); } +enable_int: if (!test_bit(__I40E_DOWN, &vsi->state)) wr32(hw, INTREG(vector - 1), txval); + + if (q_vector->itr_countdown) + q_vector->itr_countdown--; + else + q_vector->itr_countdown = ITR_COUNTDOWN_START; + } /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h index 0fe7eb77cae5..6779fb771d6a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h @@ -38,8 +38,8 @@ #define I40E_ITR_8K 0x003E #define I40E_ITR_4K 0x007A #define I40E_MAX_INTRL 0x3B /* reg uses 4 usec resolution */ -#define I40E_ITR_RX_DEF I40E_ITR_8K -#define I40E_ITR_TX_DEF I40E_ITR_4K +#define I40E_ITR_RX_DEF I40E_ITR_20K +#define I40E_ITR_TX_DEF I40E_ITR_20K #define I40E_ITR_DYNAMIC 0x8000 /* use top bit as a flag */ #define I40E_MIN_INT_RATE 250 /* ~= 1000000 / (I40E_MAX_ITR * 2) */ #define I40E_MAX_INT_RATE 500000 /* == 1000000 / (I40E_MIN_ITR * 2) */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index d76fe4a948df..47e9a90d6b10 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -348,10 +348,12 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc) * The math works out because the divisor is in 10^(-6) which * turns the bytes/us input value into MB/s values, but * make sure to use usecs, as the register values written - * are in 2 usec increments in the ITR registers. + * are in 2 usec increments in the ITR registers, and make sure + * to use the smoothed values that the countdown timer gives us. */ - usecs = (rc->itr << 1); + usecs = (rc->itr << 1) * ITR_COUNTDOWN_START; bytes_per_int = rc->total_bytes / usecs; + switch (new_latency_range) { case I40E_LOWEST_LATENCY: if (bytes_per_int > 10) @@ -1245,8 +1247,18 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, int vector; vector = (q_vector->v_idx + vsi->base_vector); + + /* avoid dynamic calculation if in countdown mode OR if + * all dynamic is disabled + */ rxval = txval = i40e_buildreg_itr(I40E_ITR_NONE, 0); + if (q_vector->itr_countdown > 0 || + (!ITR_IS_DYNAMIC(vsi->rx_itr_setting) && + !ITR_IS_DYNAMIC(vsi->tx_itr_setting))) { + goto enable_int; + } + if (ITR_IS_DYNAMIC(vsi->rx_itr_setting)) { rx = i40e_set_new_dynamic_itr(&q_vector->rx); rxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr); @@ -1282,8 +1294,15 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, wr32(hw, INTREG(vector - 1), rxval); } +enable_int: if (!test_bit(__I40E_DOWN, &vsi->state)) wr32(hw, INTREG(vector - 1), txval); + + if (q_vector->itr_countdown) + q_vector->itr_countdown--; + else + q_vector->itr_countdown = ITR_COUNTDOWN_START; + } /** diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h index e2352b886b77..ebc1bf77f036 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -38,8 +38,8 @@ #define I40E_ITR_8K 0x003E #define I40E_ITR_4K 0x007A #define I40E_MAX_INTRL 0x3B /* reg uses 4 usec resolution */ -#define I40E_ITR_RX_DEF I40E_ITR_8K -#define I40E_ITR_TX_DEF I40E_ITR_4K +#define I40E_ITR_RX_DEF I40E_ITR_20K +#define I40E_ITR_TX_DEF I40E_ITR_20K #define I40E_ITR_DYNAMIC 0x8000 /* use top bit as a flag */ #define I40E_MIN_INT_RATE 250 /* ~= 1000000 / (I40E_MAX_ITR * 2) */ #define I40E_MAX_INT_RATE 500000 /* == 1000000 / (I40E_MIN_ITR * 2) */ diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index 22841c619f37..22fc3d49c4b9 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -112,6 +112,8 @@ struct i40e_q_vector { struct i40e_ring_container tx; u32 ring_mask; u8 num_ringpairs; /* total number of ring pairs in vector */ +#define ITR_COUNTDOWN_START 100 + u8 itr_countdown; /* when 0 or 1 update ITR */ int v_idx; /* vector index in list */ char name[IFNAMSIZ + 9]; bool arm_wb_state; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index ce997902f5a3..a44a42bb83c0 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -357,6 +357,7 @@ i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx) q_vector->rx.ring = rx_ring; q_vector->rx.count++; q_vector->rx.latency_range = I40E_LOW_LATENCY; + q_vector->itr_countdown = ITR_COUNTDOWN_START; } /** @@ -377,6 +378,7 @@ i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx) q_vector->tx.ring = tx_ring; q_vector->tx.count++; q_vector->tx.latency_range = I40E_LOW_LATENCY; + q_vector->itr_countdown = ITR_COUNTDOWN_START; q_vector->num_ringpairs++; q_vector->ring_mask |= BIT(t_idx); } -- cgit v1.2.3 From bcab2db97d2423b97b248ba35eb2277168e71fcc Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Mon, 28 Sep 2015 14:16:55 -0400 Subject: i40e: Fix for Tools loopback test failing after driver load This patch fixes a problem where our Tools MAC Loopback test, after driver unbind would fail. This was because the hw was configured for multiqueue and unbind operation did not clear this configuration. The problem is fixed by resetting this configuration in i40e_remove. Change-ID: I130c05138319182ed1476d3a0b5222d6a6320af9 Signed-off-by: Carolyn Wyborny Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index e0142de018e6..5157be51e829 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10630,6 +10630,7 @@ err_dma: static void i40e_remove(struct pci_dev *pdev) { struct i40e_pf *pf = pci_get_drvdata(pdev); + struct i40e_hw *hw = &pf->hw; i40e_status ret_code; int i; @@ -10637,6 +10638,10 @@ static void i40e_remove(struct pci_dev *pdev) i40e_ptp_stop(pf); + /* Disable RSS in hw */ + wr32(hw, I40E_PFQF_HENA(0), 0); + wr32(hw, I40E_PFQF_HENA(1), 0); + /* no more scheduling of any task */ set_bit(__I40E_DOWN, &pf->state); del_timer_sync(&pf->service_timer); -- cgit v1.2.3 From 8589af70d0879a68c93ef77505a6234d22b1b1a7 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Mon, 28 Sep 2015 14:16:56 -0400 Subject: i40e: fix for PHY NVM interaction problem This patch fixes a problem where the NVMUpdate Tool, when using the PHY NVM feature, gets bad data from the PHY because of contention on the MDIO interface from get PHY capability calls from the driver during regular operations. The problem is fixed by adding a check if media is available before calling get PHY capability function because that bit is not set when device is in PHY interaction mode. Change-ID: Ib89991b0f841808dd92410f5e8683d6ee3301cd0 Signed-off-by: Carolyn Wyborny Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 7f456e91cd93..c51f2fb94716 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -2278,13 +2278,15 @@ i40e_status i40e_update_link_info(struct i40e_hw *hw) if (status) return status; - status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities, - NULL); - if (status) - return status; + if (hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) { + status = i40e_aq_get_phy_capabilities(hw, false, false, + &abilities, NULL); + if (status) + return status; - memcpy(hw->phy.link_info.module_type, &abilities.module_type, - sizeof(hw->phy.link_info.module_type)); + memcpy(hw->phy.link_info.module_type, &abilities.module_type, + sizeof(hw->phy.link_info.module_type)); + } return status; } -- cgit v1.2.3 From a03dc368547a7a4e9fcedc6f64dd64a9ff5e0593 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Mon, 28 Sep 2015 14:16:57 -0400 Subject: i40e/i40evf: Fix an accidental error with BIT_ULL replacement A mask value of 0x1FF was accidentally replaced with a bit mask causing flow director sideband to be broken. Change-ID: Id3387f67dd1b567b41692b570b383c58671e1eae Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_type.h | 4 ++-- drivers/net/ethernet/intel/i40evf/i40e_type.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index f631ca017d81..dd2da356d9a1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -1068,8 +1068,8 @@ enum i40e_filter_program_desc_fd_status { }; #define I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT 23 -#define I40E_TXD_FLTR_QW0_DEST_VSI_MASK \ - BIT_ULL(I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) +#define I40E_TXD_FLTR_QW0_DEST_VSI_MASK (0x1FFUL << \ + I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) #define I40E_TXD_FLTR_QW1_CMD_SHIFT 4 #define I40E_TXD_FLTR_QW1_CMD_MASK (0xFFFFULL << \ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h index 85af3b48effc..301fe2b6dd03 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_type.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h @@ -1055,8 +1055,8 @@ enum i40e_filter_program_desc_fd_status { }; #define I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT 23 -#define I40E_TXD_FLTR_QW0_DEST_VSI_MASK \ - BIT_ULL(I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) +#define I40E_TXD_FLTR_QW0_DEST_VSI_MASK (0x1FFUL << \ + I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) #define I40E_TXD_FLTR_QW1_CMD_SHIFT 4 #define I40E_TXD_FLTR_QW1_CMD_MASK (0xFFFFULL << \ -- cgit v1.2.3 From 3ce12ee9d8f9ae245f38e6acbd32625d8e002c5b Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Mon, 28 Sep 2015 14:16:58 -0400 Subject: i40e: Fix order of checks when enabling/disabling autoneg in ethtool We were previously checking if autoneg was allowed to change before checking if autoneg was changing. We need to do this in the other order or else we will erroneously return EINVAL when autoneg is not changing. Change-ID: Iff9f7d1c9bddc1ad1e5d227d4f42754f90155410 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 29 ++++++++++++++------------ 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 767b1db1005f..6e5f9314994b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -661,28 +661,31 @@ static int i40e_set_settings(struct net_device *netdev, /* Check autoneg */ if (autoneg == AUTONEG_ENABLE) { - /* If autoneg is not supported, return error */ - if (!(safe_ecmd.supported & SUPPORTED_Autoneg)) { - netdev_info(netdev, "Autoneg not supported on this phy\n"); - return -EINVAL; - } /* If autoneg was not already enabled */ if (!(hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED)) { + /* If autoneg is not supported, return error */ + if (!(safe_ecmd.supported & SUPPORTED_Autoneg)) { + netdev_info(netdev, "Autoneg not supported on this phy\n"); + return -EINVAL; + } + /* Autoneg is allowed to change */ config.abilities = abilities.abilities | I40E_AQ_PHY_ENABLE_AN; change = true; } } else { - /* If autoneg is supported 10GBASE_T is the only phy that - * can disable it, so otherwise return error - */ - if (safe_ecmd.supported & SUPPORTED_Autoneg && - hw->phy.link_info.phy_type != I40E_PHY_TYPE_10GBASE_T) { - netdev_info(netdev, "Autoneg cannot be disabled on this phy\n"); - return -EINVAL; - } /* If autoneg is currently enabled */ if (hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED) { + /* If autoneg is supported 10GBASE_T is the only PHY + * that can disable it, so otherwise return error + */ + if (safe_ecmd.supported & SUPPORTED_Autoneg && + hw->phy.link_info.phy_type != + I40E_PHY_TYPE_10GBASE_T) { + netdev_info(netdev, "Autoneg cannot be disabled on this phy\n"); + return -EINVAL; + } + /* Autoneg is allowed to change */ config.abilities = abilities.abilities & ~I40E_AQ_PHY_ENABLE_AN; change = true; -- cgit v1.2.3 From 52e9689e4ef070eff1e0f9e6e84a8451b86813b5 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Mon, 28 Sep 2015 14:16:59 -0400 Subject: i40e: Move error message to debug level There is an error coming back from get_phy_capabilities that does not seem to have any functional implications. We will continue looking into why this error message is occurring, but in the meantime, we will move it to debug to avoid confusion. Change-ID: I9091754bf62c066ddedeb249923d85606e2d68ed Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 6e5f9314994b..8fd26fdd7705 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -751,9 +751,9 @@ static int i40e_set_settings(struct net_device *netdev, status = i40e_update_link_info(hw); if (status) - netdev_info(netdev, "Updating link info failed with err %s aq_err %s\n", - i40e_stat_str(hw, status), - i40e_aq_str(hw, hw->aq.asq_last_status)); + netdev_dbg(netdev, "Updating link info failed with err %s aq_err %s\n", + i40e_stat_str(hw, status), + i40e_aq_str(hw, hw->aq.asq_last_status)); } else { netdev_info(netdev, "Nothing changed, exiting without setting anything.\n"); -- cgit v1.2.3 From 2bc11c634eaebb936345b136a196f555045a47ea Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Sat, 19 Sep 2015 05:08:43 -0600 Subject: i40e: fix kernel-doc argument name The second argument name in the kernel-doc argument list for i40e_features_check() was slightly off. Fix it for the kernel doc. Signed-off-by: Jean Sacren Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 5157be51e829..96b9385be469 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8542,7 +8542,7 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, /** * i40e_features_check - Validate encapsulated packet conforms to limits * @skb: skb buff - * @netdev: This physical port's netdev + * @dev: This physical port's netdev * @features: Offload features that the stack believes apply **/ static netdev_features_t i40e_features_check(struct sk_buff *skb, -- cgit v1.2.3 From 6f66a484f1ff644b4600368fe3091e31b65d3c50 Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Sat, 19 Sep 2015 05:08:45 -0600 Subject: i40e: declare rather than initialize int object 'err' would be overwritten immediately, so we should declare it only rather than initialize it to zero. Signed-off-by: Jean Sacren Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 96b9385be469..f0ba384a0291 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10159,7 +10159,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) static u16 pfs_found; u16 wol_nvm_bits; u16 link_status; - int err = 0; + int err; u32 len; u32 i; -- cgit v1.2.3 From a1f192cf70b187ab01b8b03cdeea82b8820c927a Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Mon, 28 Sep 2015 14:17:00 -0400 Subject: i40e/i40evf: Bump i40e to 1.3.38 and i40evf to 1.3.25 Bump. Change-ID: Id0a7ecaa491f88ce94c9eba4901e592a56044ee0 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index f0ba384a0291..69e9c3e2def7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -39,7 +39,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 3 -#define DRV_VERSION_BUILD 34 +#define DRV_VERSION_BUILD 38 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index a44a42bb83c0..10b2a4a33c68 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -34,7 +34,7 @@ char i40evf_driver_name[] = "i40evf"; static const char i40evf_driver_string[] = "Intel(R) XL710/X710 Virtual Function Network Driver"; -#define DRV_VERSION "1.3.21" +#define DRV_VERSION "1.3.25" const char i40evf_driver_version[] = DRV_VERSION; static const char i40evf_copyright[] = "Copyright (c) 2013 - 2015 Intel Corporation."; -- cgit v1.2.3 From 26f1fad29ad973b0fb26a9ca3dcb2a73dde781aa Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Wed, 14 Oct 2015 20:44:51 -0400 Subject: New driver: rtl8xxxu (mac80211) This is an alternate driver for a number of Realtek WiFi USB devices, including RTL8723AU, RTL8188CU, RTL8188RU, RTL8191CU, and RTL8192CU. It was written from scratch utilizing the Linux mac80211 stack. After spending months cleaning up the vendor provided rtl8723au driver, which comes with it's own 802.11 stack included, I decided to rewrite this driver from the bottom up. Many thanks to Johannes Berg for 802.11 insights and help and Larry Finger for help with the vendor driver. The full git log for the development of this driver can be found here: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git branch rtl8723au-mac80211 This driver is still under development, but has proven to be very stable for me. It currently supports station mode only. It has support for OFDM and CCK rates. It does lack certain features found in the staging driver, such as power management, AMPDU, and 40MHz channel support. In addition it does not support AD-HOC, AP, and monitor mode support at this point. The driver is known to work with the following devices: Lenovo Yoga (rtl8723au) TP-Link TL-WN823N (rtl8192cu) Etekcity 6R (rtl8188cu) Daffodil LAN03 (rtl8188cu) Alfa AWUS036NHR (rtl8188ru) Signed-off-by: Jes Sorensen Signed-off-by: Kalle Valo --- drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/realtek/Makefile | 1 + drivers/net/wireless/realtek/rtl8xxxu/Kconfig | 34 + drivers/net/wireless/realtek/rtl8xxxu/Makefile | 1 + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 5976 ++++++++++++++++++++ drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 676 +++ .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 981 ++++ 7 files changed, 7670 insertions(+) create mode 100644 drivers/net/wireless/realtek/rtl8xxxu/Kconfig create mode 100644 drivers/net/wireless/realtek/rtl8xxxu/Makefile create mode 100644 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c create mode 100644 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h create mode 100644 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h (limited to 'drivers/net') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 91907c4b8bcf..f9f94229bf1b 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -279,6 +279,7 @@ source "drivers/net/wireless/p54/Kconfig" source "drivers/net/wireless/rt2x00/Kconfig" source "drivers/net/wireless/mediatek/Kconfig" source "drivers/net/wireless/realtek/rtlwifi/Kconfig" +source "drivers/net/wireless/realtek/rtl8xxxu/Kconfig" source "drivers/net/wireless/ti/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" source "drivers/net/wireless/mwifiex/Kconfig" diff --git a/drivers/net/wireless/realtek/Makefile b/drivers/net/wireless/realtek/Makefile index 3489b98979f8..9c78deb5eea9 100644 --- a/drivers/net/wireless/realtek/Makefile +++ b/drivers/net/wireless/realtek/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_RTL8180) += rtl818x/ obj-$(CONFIG_RTL8187) += rtl818x/ obj-$(CONFIG_RTLWIFI) += rtlwifi/ +obj-$(CONFIG_RTL8XXXU) += rtl8xxxu/ diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig new file mode 100644 index 000000000000..dd4d626aecbc --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig @@ -0,0 +1,34 @@ +# +# RTL8XXXU Wireless LAN device configuration +# +config RTL8XXXU + tristate "RTL8723AU/RTL8188[CR]U/RTL819[12]CU (mac80211) support" + depends on MAC80211 && USB + ---help--- + This is an alternative driver for various Realtek RTL8XXX + parts written to utilize the Linux mac80211 stack. + The driver is known to work with a number of RTL8723AU, + RL8188CU, RTL8188RU, RTL8191CU, and RTL8192CU devices + + This driver is under development and has a limited feature + set. In particular it does not yet support 40MHz channels + and power management. However it should have a smaller + memory footprint than the vendor drivers and benetifs + from the in kernel mac80211 stack. + + It can coexist with drivers from drivers/staging/rtl8723au, + drivers/staging/rtl8192u, and drivers/net/wireless/rtlwifi, + but you will need to control which module you wish to load. + + To compile this driver as a module, choose M here: the module will + be called r8xxxu. If unsure, say N. + +config RTL8XXXU_UNTESTED + bool "Include support for untested Realtek 8xxx USB devices (EXPERIMENTAL)" + depends on RTL8XXXU + ---help--- + This option enables detection of Realtek 8723/8188/8191/8192 WiFi + USB devices which have not been tested directly by the driver + author or reported to be working by third parties. + + Please report your results! diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Makefile b/drivers/net/wireless/realtek/rtl8xxxu/Makefile new file mode 100644 index 000000000000..5dea3bb93069 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8xxxu/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_RTL8XXXU) += rtl8xxxu.o diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c new file mode 100644 index 000000000000..47e52ad56144 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -0,0 +1,5976 @@ +/* + * RTL8XXXU mac80211 USB driver + * + * Copyright (c) 2014 - 2015 Jes Sorensen + * + * Portions, notably calibration code: + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + * + * This driver was written as a replacement for the vendor provided + * rtl8723au driver. As the Realtek 8xxx chips are very similar in + * their programming interface, I have started adding support for + * additional 8xxx chips like the 8192cu, 8188cus, etc. + * + * 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rtl8xxxu.h" +#include "rtl8xxxu_regs.h" + +#define DRIVER_NAME "rtl8xxxu" + +static int rtl8xxxu_debug; +static bool rtl8xxxu_ht40_2g; + +MODULE_AUTHOR("Jes Sorensen "); +MODULE_DESCRIPTION("RTL8XXXu USB mac80211 Wireless LAN Driver"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("rtlwifi/rtl8723aufw_A.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8723aufw_B_NoBT.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_A.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_B.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192cufw_TMSC.bin"); + +module_param_named(debug, rtl8xxxu_debug, int, 0600); +MODULE_PARM_DESC(debug, "Set debug mask"); +module_param_named(ht40_2g, rtl8xxxu_ht40_2g, bool, 0600); +MODULE_PARM_DESC(ht40_2g, "Enable HT40 support on the 2.4GHz band"); + +#define USB_VENDOR_ID_REALTEK 0x0bda +/* Minimum IEEE80211_MAX_FRAME_LEN */ +#define RTL_RX_BUFFER_SIZE IEEE80211_MAX_FRAME_LEN +#define RTL8XXXU_RX_URBS 32 +#define RTL8XXXU_RX_URB_PENDING_WATER 8 +#define RTL8XXXU_TX_URBS 64 +#define RTL8XXXU_TX_URB_LOW_WATER 25 +#define RTL8XXXU_TX_URB_HIGH_WATER 32 + +static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_rx_urb *rx_urb); + +static struct ieee80211_rate rtl8xxxu_rates[] = { + { .bitrate = 10, .hw_value = DESC_RATE_1M, .flags = 0 }, + { .bitrate = 20, .hw_value = DESC_RATE_2M, .flags = 0 }, + { .bitrate = 55, .hw_value = DESC_RATE_5_5M, .flags = 0 }, + { .bitrate = 110, .hw_value = DESC_RATE_11M, .flags = 0 }, + { .bitrate = 60, .hw_value = DESC_RATE_6M, .flags = 0 }, + { .bitrate = 90, .hw_value = DESC_RATE_9M, .flags = 0 }, + { .bitrate = 120, .hw_value = DESC_RATE_12M, .flags = 0 }, + { .bitrate = 180, .hw_value = DESC_RATE_18M, .flags = 0 }, + { .bitrate = 240, .hw_value = DESC_RATE_24M, .flags = 0 }, + { .bitrate = 360, .hw_value = DESC_RATE_36M, .flags = 0 }, + { .bitrate = 480, .hw_value = DESC_RATE_48M, .flags = 0 }, + { .bitrate = 540, .hw_value = DESC_RATE_54M, .flags = 0 }, +}; + +static struct ieee80211_channel rtl8xxxu_channels_2g[] = { + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2412, + .hw_value = 1, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2417, + .hw_value = 2, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2422, + .hw_value = 3, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2427, + .hw_value = 4, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2432, + .hw_value = 5, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2437, + .hw_value = 6, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2442, + .hw_value = 7, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2447, + .hw_value = 8, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2452, + .hw_value = 9, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2457, + .hw_value = 10, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2462, + .hw_value = 11, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2467, + .hw_value = 12, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2472, + .hw_value = 13, .max_power = 30 }, + { .band = IEEE80211_BAND_2GHZ, .center_freq = 2484, + .hw_value = 14, .max_power = 30 } +}; + +static struct ieee80211_supported_band rtl8xxxu_supported_band = { + .channels = rtl8xxxu_channels_2g, + .n_channels = ARRAY_SIZE(rtl8xxxu_channels_2g), + .bitrates = rtl8xxxu_rates, + .n_bitrates = ARRAY_SIZE(rtl8xxxu_rates), +}; + +static struct rtl8xxxu_reg8val rtl8723a_mac_init_table[] = { + {0x420, 0x80}, {0x423, 0x00}, {0x430, 0x00}, {0x431, 0x00}, + {0x432, 0x00}, {0x433, 0x01}, {0x434, 0x04}, {0x435, 0x05}, + {0x436, 0x06}, {0x437, 0x07}, {0x438, 0x00}, {0x439, 0x00}, + {0x43a, 0x00}, {0x43b, 0x01}, {0x43c, 0x04}, {0x43d, 0x05}, + {0x43e, 0x06}, {0x43f, 0x07}, {0x440, 0x5d}, {0x441, 0x01}, + {0x442, 0x00}, {0x444, 0x15}, {0x445, 0xf0}, {0x446, 0x0f}, + {0x447, 0x00}, {0x458, 0x41}, {0x459, 0xa8}, {0x45a, 0x72}, + {0x45b, 0xb9}, {0x460, 0x66}, {0x461, 0x66}, {0x462, 0x08}, + {0x463, 0x03}, {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4cc, 0xff}, + {0x4cd, 0xff}, {0x4ce, 0x01}, {0x500, 0x26}, {0x501, 0xa2}, + {0x502, 0x2f}, {0x503, 0x00}, {0x504, 0x28}, {0x505, 0xa3}, + {0x506, 0x5e}, {0x507, 0x00}, {0x508, 0x2b}, {0x509, 0xa4}, + {0x50a, 0x5e}, {0x50b, 0x00}, {0x50c, 0x4f}, {0x50d, 0xa4}, + {0x50e, 0x00}, {0x50f, 0x00}, {0x512, 0x1c}, {0x514, 0x0a}, + {0x515, 0x10}, {0x516, 0x0a}, {0x517, 0x10}, {0x51a, 0x16}, + {0x524, 0x0f}, {0x525, 0x4f}, {0x546, 0x40}, {0x547, 0x00}, + {0x550, 0x10}, {0x551, 0x10}, {0x559, 0x02}, {0x55a, 0x02}, + {0x55d, 0xff}, {0x605, 0x30}, {0x608, 0x0e}, {0x609, 0x2a}, + {0x652, 0x20}, {0x63c, 0x0a}, {0x63d, 0x0a}, {0x63e, 0x0e}, + {0x63f, 0x0e}, {0x66e, 0x05}, {0x700, 0x21}, {0x701, 0x43}, + {0x702, 0x65}, {0x703, 0x87}, {0x708, 0x21}, {0x709, 0x43}, + {0x70a, 0x65}, {0x70b, 0x87}, {0xffff, 0xff}, +}; + +static struct rtl8xxxu_reg32val rtl8723a_phy_1t_init_table[] = { + {0x800, 0x80040000}, {0x804, 0x00000003}, + {0x808, 0x0000fc00}, {0x80c, 0x0000000a}, + {0x810, 0x10001331}, {0x814, 0x020c3d10}, + {0x818, 0x02200385}, {0x81c, 0x00000000}, + {0x820, 0x01000100}, {0x824, 0x00390004}, + {0x828, 0x00000000}, {0x82c, 0x00000000}, + {0x830, 0x00000000}, {0x834, 0x00000000}, + {0x838, 0x00000000}, {0x83c, 0x00000000}, + {0x840, 0x00010000}, {0x844, 0x00000000}, + {0x848, 0x00000000}, {0x84c, 0x00000000}, + {0x850, 0x00000000}, {0x854, 0x00000000}, + {0x858, 0x569a569a}, {0x85c, 0x001b25a4}, + {0x860, 0x66f60110}, {0x864, 0x061f0130}, + {0x868, 0x00000000}, {0x86c, 0x32323200}, + {0x870, 0x07000760}, {0x874, 0x22004000}, + {0x878, 0x00000808}, {0x87c, 0x00000000}, + {0x880, 0xc0083070}, {0x884, 0x000004d5}, + {0x888, 0x00000000}, {0x88c, 0xccc000c0}, + {0x890, 0x00000800}, {0x894, 0xfffffffe}, + {0x898, 0x40302010}, {0x89c, 0x00706050}, + {0x900, 0x00000000}, {0x904, 0x00000023}, + {0x908, 0x00000000}, {0x90c, 0x81121111}, + {0xa00, 0x00d047c8}, {0xa04, 0x80ff000c}, + {0xa08, 0x8c838300}, {0xa0c, 0x2e68120f}, + {0xa10, 0x9500bb78}, {0xa14, 0x11144028}, + {0xa18, 0x00881117}, {0xa1c, 0x89140f00}, + {0xa20, 0x1a1b0000}, {0xa24, 0x090e1317}, + {0xa28, 0x00000204}, {0xa2c, 0x00d30000}, + {0xa70, 0x101fbf00}, {0xa74, 0x00000007}, + {0xa78, 0x00000900}, + {0xc00, 0x48071d40}, {0xc04, 0x03a05611}, + {0xc08, 0x000000e4}, {0xc0c, 0x6c6c6c6c}, + {0xc10, 0x08800000}, {0xc14, 0x40000100}, + {0xc18, 0x08800000}, {0xc1c, 0x40000100}, + {0xc20, 0x00000000}, {0xc24, 0x00000000}, + {0xc28, 0x00000000}, {0xc2c, 0x00000000}, + {0xc30, 0x69e9ac44}, {0xc34, 0x469652af}, + {0xc38, 0x49795994}, {0xc3c, 0x0a97971c}, + {0xc40, 0x1f7c403f}, {0xc44, 0x000100b7}, + {0xc48, 0xec020107}, {0xc4c, 0x007f037f}, + {0xc50, 0x69543420}, {0xc54, 0x43bc0094}, + {0xc58, 0x69543420}, {0xc5c, 0x433c0094}, + {0xc60, 0x00000000}, {0xc64, 0x7112848b}, + {0xc68, 0x47c00bff}, {0xc6c, 0x00000036}, + {0xc70, 0x2c7f000d}, {0xc74, 0x018610db}, + {0xc78, 0x0000001f}, {0xc7c, 0x00b91612}, + {0xc80, 0x40000100}, {0xc84, 0x20f60000}, + {0xc88, 0x40000100}, {0xc8c, 0x20200000}, + {0xc90, 0x00121820}, {0xc94, 0x00000000}, + {0xc98, 0x00121820}, {0xc9c, 0x00007f7f}, + {0xca0, 0x00000000}, {0xca4, 0x00000080}, + {0xca8, 0x00000000}, {0xcac, 0x00000000}, + {0xcb0, 0x00000000}, {0xcb4, 0x00000000}, + {0xcb8, 0x00000000}, {0xcbc, 0x28000000}, + {0xcc0, 0x00000000}, {0xcc4, 0x00000000}, + {0xcc8, 0x00000000}, {0xccc, 0x00000000}, + {0xcd0, 0x00000000}, {0xcd4, 0x00000000}, + {0xcd8, 0x64b22427}, {0xcdc, 0x00766932}, + {0xce0, 0x00222222}, {0xce4, 0x00000000}, + {0xce8, 0x37644302}, {0xcec, 0x2f97d40c}, + {0xd00, 0x00080740}, {0xd04, 0x00020401}, + {0xd08, 0x0000907f}, {0xd0c, 0x20010201}, + {0xd10, 0xa0633333}, {0xd14, 0x3333bc43}, + {0xd18, 0x7a8f5b6b}, {0xd2c, 0xcc979975}, + {0xd30, 0x00000000}, {0xd34, 0x80608000}, + {0xd38, 0x00000000}, {0xd3c, 0x00027293}, + {0xd40, 0x00000000}, {0xd44, 0x00000000}, + {0xd48, 0x00000000}, {0xd4c, 0x00000000}, + {0xd50, 0x6437140a}, {0xd54, 0x00000000}, + {0xd58, 0x00000000}, {0xd5c, 0x30032064}, + {0xd60, 0x4653de68}, {0xd64, 0x04518a3c}, + {0xd68, 0x00002101}, {0xd6c, 0x2a201c16}, + {0xd70, 0x1812362e}, {0xd74, 0x322c2220}, + {0xd78, 0x000e3c24}, {0xe00, 0x2a2a2a2a}, + {0xe04, 0x2a2a2a2a}, {0xe08, 0x03902a2a}, + {0xe10, 0x2a2a2a2a}, {0xe14, 0x2a2a2a2a}, + {0xe18, 0x2a2a2a2a}, {0xe1c, 0x2a2a2a2a}, + {0xe28, 0x00000000}, {0xe30, 0x1000dc1f}, + {0xe34, 0x10008c1f}, {0xe38, 0x02140102}, + {0xe3c, 0x681604c2}, {0xe40, 0x01007c00}, + {0xe44, 0x01004800}, {0xe48, 0xfb000000}, + {0xe4c, 0x000028d1}, {0xe50, 0x1000dc1f}, + {0xe54, 0x10008c1f}, {0xe58, 0x02140102}, + {0xe5c, 0x28160d05}, {0xe60, 0x00000008}, + {0xe68, 0x001b25a4}, {0xe6c, 0x631b25a0}, + {0xe70, 0x631b25a0}, {0xe74, 0x081b25a0}, + {0xe78, 0x081b25a0}, {0xe7c, 0x081b25a0}, + {0xe80, 0x081b25a0}, {0xe84, 0x631b25a0}, + {0xe88, 0x081b25a0}, {0xe8c, 0x631b25a0}, + {0xed0, 0x631b25a0}, {0xed4, 0x631b25a0}, + {0xed8, 0x631b25a0}, {0xedc, 0x001b25a0}, + {0xee0, 0x001b25a0}, {0xeec, 0x6b1b25a0}, + {0xf14, 0x00000003}, {0xf4c, 0x00000000}, + {0xf00, 0x00000300}, + {0xffff, 0xffffffff}, +}; + +static struct rtl8xxxu_reg32val rtl8192cu_phy_2t_init_table[] = { + {0x024, 0x0011800f}, {0x028, 0x00ffdb83}, + {0x800, 0x80040002}, {0x804, 0x00000003}, + {0x808, 0x0000fc00}, {0x80c, 0x0000000a}, + {0x810, 0x10000330}, {0x814, 0x020c3d10}, + {0x818, 0x02200385}, {0x81c, 0x00000000}, + {0x820, 0x01000100}, {0x824, 0x00390004}, + {0x828, 0x01000100}, {0x82c, 0x00390004}, + {0x830, 0x27272727}, {0x834, 0x27272727}, + {0x838, 0x27272727}, {0x83c, 0x27272727}, + {0x840, 0x00010000}, {0x844, 0x00010000}, + {0x848, 0x27272727}, {0x84c, 0x27272727}, + {0x850, 0x00000000}, {0x854, 0x00000000}, + {0x858, 0x569a569a}, {0x85c, 0x0c1b25a4}, + {0x860, 0x66e60230}, {0x864, 0x061f0130}, + {0x868, 0x27272727}, {0x86c, 0x2b2b2b27}, + {0x870, 0x07000700}, {0x874, 0x22184000}, + {0x878, 0x08080808}, {0x87c, 0x00000000}, + {0x880, 0xc0083070}, {0x884, 0x000004d5}, + {0x888, 0x00000000}, {0x88c, 0xcc0000c0}, + {0x890, 0x00000800}, {0x894, 0xfffffffe}, + {0x898, 0x40302010}, {0x89c, 0x00706050}, + {0x900, 0x00000000}, {0x904, 0x00000023}, + {0x908, 0x00000000}, {0x90c, 0x81121313}, + {0xa00, 0x00d047c8}, {0xa04, 0x80ff000c}, + {0xa08, 0x8c838300}, {0xa0c, 0x2e68120f}, + {0xa10, 0x9500bb78}, {0xa14, 0x11144028}, + {0xa18, 0x00881117}, {0xa1c, 0x89140f00}, + {0xa20, 0x1a1b0000}, {0xa24, 0x090e1317}, + {0xa28, 0x00000204}, {0xa2c, 0x00d30000}, + {0xa70, 0x101fbf00}, {0xa74, 0x00000007}, + {0xc00, 0x48071d40}, {0xc04, 0x03a05633}, + {0xc08, 0x000000e4}, {0xc0c, 0x6c6c6c6c}, + {0xc10, 0x08800000}, {0xc14, 0x40000100}, + {0xc18, 0x08800000}, {0xc1c, 0x40000100}, + {0xc20, 0x00000000}, {0xc24, 0x00000000}, + {0xc28, 0x00000000}, {0xc2c, 0x00000000}, + {0xc30, 0x69e9ac44}, {0xc34, 0x469652cf}, + {0xc38, 0x49795994}, {0xc3c, 0x0a97971c}, + {0xc40, 0x1f7c403f}, {0xc44, 0x000100b7}, + {0xc48, 0xec020107}, {0xc4c, 0x007f037f}, + {0xc50, 0x69543420}, {0xc54, 0x43bc0094}, + {0xc58, 0x69543420}, {0xc5c, 0x433c0094}, + {0xc60, 0x00000000}, {0xc64, 0x5116848b}, + {0xc68, 0x47c00bff}, {0xc6c, 0x00000036}, + {0xc70, 0x2c7f000d}, {0xc74, 0x2186115b}, + {0xc78, 0x0000001f}, {0xc7c, 0x00b99612}, + {0xc80, 0x40000100}, {0xc84, 0x20f60000}, + {0xc88, 0x40000100}, {0xc8c, 0xa0e40000}, + {0xc90, 0x00121820}, {0xc94, 0x00000000}, + {0xc98, 0x00121820}, {0xc9c, 0x00007f7f}, + {0xca0, 0x00000000}, {0xca4, 0x00000080}, + {0xca8, 0x00000000}, {0xcac, 0x00000000}, + {0xcb0, 0x00000000}, {0xcb4, 0x00000000}, + {0xcb8, 0x00000000}, {0xcbc, 0x28000000}, + {0xcc0, 0x00000000}, {0xcc4, 0x00000000}, + {0xcc8, 0x00000000}, {0xccc, 0x00000000}, + {0xcd0, 0x00000000}, {0xcd4, 0x00000000}, + {0xcd8, 0x64b22427}, {0xcdc, 0x00766932}, + {0xce0, 0x00222222}, {0xce4, 0x00000000}, + {0xce8, 0x37644302}, {0xcec, 0x2f97d40c}, + {0xd00, 0x00080740}, {0xd04, 0x00020403}, + {0xd08, 0x0000907f}, {0xd0c, 0x20010201}, + {0xd10, 0xa0633333}, {0xd14, 0x3333bc43}, + {0xd18, 0x7a8f5b6b}, {0xd2c, 0xcc979975}, + {0xd30, 0x00000000}, {0xd34, 0x80608000}, + {0xd38, 0x00000000}, {0xd3c, 0x00027293}, + {0xd40, 0x00000000}, {0xd44, 0x00000000}, + {0xd48, 0x00000000}, {0xd4c, 0x00000000}, + {0xd50, 0x6437140a}, {0xd54, 0x00000000}, + {0xd58, 0x00000000}, {0xd5c, 0x30032064}, + {0xd60, 0x4653de68}, {0xd64, 0x04518a3c}, + {0xd68, 0x00002101}, {0xd6c, 0x2a201c16}, + {0xd70, 0x1812362e}, {0xd74, 0x322c2220}, + {0xd78, 0x000e3c24}, {0xe00, 0x2a2a2a2a}, + {0xe04, 0x2a2a2a2a}, {0xe08, 0x03902a2a}, + {0xe10, 0x2a2a2a2a}, {0xe14, 0x2a2a2a2a}, + {0xe18, 0x2a2a2a2a}, {0xe1c, 0x2a2a2a2a}, + {0xe28, 0x00000000}, {0xe30, 0x1000dc1f}, + {0xe34, 0x10008c1f}, {0xe38, 0x02140102}, + {0xe3c, 0x681604c2}, {0xe40, 0x01007c00}, + {0xe44, 0x01004800}, {0xe48, 0xfb000000}, + {0xe4c, 0x000028d1}, {0xe50, 0x1000dc1f}, + {0xe54, 0x10008c1f}, {0xe58, 0x02140102}, + {0xe5c, 0x28160d05}, {0xe60, 0x00000010}, + {0xe68, 0x001b25a4}, {0xe6c, 0x63db25a4}, + {0xe70, 0x63db25a4}, {0xe74, 0x0c1b25a4}, + {0xe78, 0x0c1b25a4}, {0xe7c, 0x0c1b25a4}, + {0xe80, 0x0c1b25a4}, {0xe84, 0x63db25a4}, + {0xe88, 0x0c1b25a4}, {0xe8c, 0x63db25a4}, + {0xed0, 0x63db25a4}, {0xed4, 0x63db25a4}, + {0xed8, 0x63db25a4}, {0xedc, 0x001b25a4}, + {0xee0, 0x001b25a4}, {0xeec, 0x6fdb25a4}, + {0xf14, 0x00000003}, {0xf4c, 0x00000000}, + {0xf00, 0x00000300}, + {0xffff, 0xffffffff}, +}; + +static struct rtl8xxxu_reg32val rtl8188ru_phy_1t_highpa_table[] = { + {0x024, 0x0011800f}, {0x028, 0x00ffdb83}, + {0x040, 0x000c0004}, {0x800, 0x80040000}, + {0x804, 0x00000001}, {0x808, 0x0000fc00}, + {0x80c, 0x0000000a}, {0x810, 0x10005388}, + {0x814, 0x020c3d10}, {0x818, 0x02200385}, + {0x81c, 0x00000000}, {0x820, 0x01000100}, + {0x824, 0x00390204}, {0x828, 0x00000000}, + {0x82c, 0x00000000}, {0x830, 0x00000000}, + {0x834, 0x00000000}, {0x838, 0x00000000}, + {0x83c, 0x00000000}, {0x840, 0x00010000}, + {0x844, 0x00000000}, {0x848, 0x00000000}, + {0x84c, 0x00000000}, {0x850, 0x00000000}, + {0x854, 0x00000000}, {0x858, 0x569a569a}, + {0x85c, 0x001b25a4}, {0x860, 0x66e60230}, + {0x864, 0x061f0130}, {0x868, 0x00000000}, + {0x86c, 0x20202000}, {0x870, 0x03000300}, + {0x874, 0x22004000}, {0x878, 0x00000808}, + {0x87c, 0x00ffc3f1}, {0x880, 0xc0083070}, + {0x884, 0x000004d5}, {0x888, 0x00000000}, + {0x88c, 0xccc000c0}, {0x890, 0x00000800}, + {0x894, 0xfffffffe}, {0x898, 0x40302010}, + {0x89c, 0x00706050}, {0x900, 0x00000000}, + {0x904, 0x00000023}, {0x908, 0x00000000}, + {0x90c, 0x81121111}, {0xa00, 0x00d047c8}, + {0xa04, 0x80ff000c}, {0xa08, 0x8c838300}, + {0xa0c, 0x2e68120f}, {0xa10, 0x9500bb78}, + {0xa14, 0x11144028}, {0xa18, 0x00881117}, + {0xa1c, 0x89140f00}, {0xa20, 0x15160000}, + {0xa24, 0x070b0f12}, {0xa28, 0x00000104}, + {0xa2c, 0x00d30000}, {0xa70, 0x101fbf00}, + {0xa74, 0x00000007}, {0xc00, 0x48071d40}, + {0xc04, 0x03a05611}, {0xc08, 0x000000e4}, + {0xc0c, 0x6c6c6c6c}, {0xc10, 0x08800000}, + {0xc14, 0x40000100}, {0xc18, 0x08800000}, + {0xc1c, 0x40000100}, {0xc20, 0x00000000}, + {0xc24, 0x00000000}, {0xc28, 0x00000000}, + {0xc2c, 0x00000000}, {0xc30, 0x69e9ac44}, + {0xc34, 0x469652cf}, {0xc38, 0x49795994}, + {0xc3c, 0x0a97971c}, {0xc40, 0x1f7c403f}, + {0xc44, 0x000100b7}, {0xc48, 0xec020107}, + {0xc4c, 0x007f037f}, {0xc50, 0x6954342e}, + {0xc54, 0x43bc0094}, {0xc58, 0x6954342f}, + {0xc5c, 0x433c0094}, {0xc60, 0x00000000}, + {0xc64, 0x5116848b}, {0xc68, 0x47c00bff}, + {0xc6c, 0x00000036}, {0xc70, 0x2c46000d}, + {0xc74, 0x018610db}, {0xc78, 0x0000001f}, + {0xc7c, 0x00b91612}, {0xc80, 0x24000090}, + {0xc84, 0x20f60000}, {0xc88, 0x24000090}, + {0xc8c, 0x20200000}, {0xc90, 0x00121820}, + {0xc94, 0x00000000}, {0xc98, 0x00121820}, + {0xc9c, 0x00007f7f}, {0xca0, 0x00000000}, + {0xca4, 0x00000080}, {0xca8, 0x00000000}, + {0xcac, 0x00000000}, {0xcb0, 0x00000000}, + {0xcb4, 0x00000000}, {0xcb8, 0x00000000}, + {0xcbc, 0x28000000}, {0xcc0, 0x00000000}, + {0xcc4, 0x00000000}, {0xcc8, 0x00000000}, + {0xccc, 0x00000000}, {0xcd0, 0x00000000}, + {0xcd4, 0x00000000}, {0xcd8, 0x64b22427}, + {0xcdc, 0x00766932}, {0xce0, 0x00222222}, + {0xce4, 0x00000000}, {0xce8, 0x37644302}, + {0xcec, 0x2f97d40c}, {0xd00, 0x00080740}, + {0xd04, 0x00020401}, {0xd08, 0x0000907f}, + {0xd0c, 0x20010201}, {0xd10, 0xa0633333}, + {0xd14, 0x3333bc43}, {0xd18, 0x7a8f5b6b}, + {0xd2c, 0xcc979975}, {0xd30, 0x00000000}, + {0xd34, 0x80608000}, {0xd38, 0x00000000}, + {0xd3c, 0x00027293}, {0xd40, 0x00000000}, + {0xd44, 0x00000000}, {0xd48, 0x00000000}, + {0xd4c, 0x00000000}, {0xd50, 0x6437140a}, + {0xd54, 0x00000000}, {0xd58, 0x00000000}, + {0xd5c, 0x30032064}, {0xd60, 0x4653de68}, + {0xd64, 0x04518a3c}, {0xd68, 0x00002101}, + {0xd6c, 0x2a201c16}, {0xd70, 0x1812362e}, + {0xd74, 0x322c2220}, {0xd78, 0x000e3c24}, + {0xe00, 0x24242424}, {0xe04, 0x24242424}, + {0xe08, 0x03902024}, {0xe10, 0x24242424}, + {0xe14, 0x24242424}, {0xe18, 0x24242424}, + {0xe1c, 0x24242424}, {0xe28, 0x00000000}, + {0xe30, 0x1000dc1f}, {0xe34, 0x10008c1f}, + {0xe38, 0x02140102}, {0xe3c, 0x681604c2}, + {0xe40, 0x01007c00}, {0xe44, 0x01004800}, + {0xe48, 0xfb000000}, {0xe4c, 0x000028d1}, + {0xe50, 0x1000dc1f}, {0xe54, 0x10008c1f}, + {0xe58, 0x02140102}, {0xe5c, 0x28160d05}, + {0xe60, 0x00000008}, {0xe68, 0x001b25a4}, + {0xe6c, 0x631b25a0}, {0xe70, 0x631b25a0}, + {0xe74, 0x081b25a0}, {0xe78, 0x081b25a0}, + {0xe7c, 0x081b25a0}, {0xe80, 0x081b25a0}, + {0xe84, 0x631b25a0}, {0xe88, 0x081b25a0}, + {0xe8c, 0x631b25a0}, {0xed0, 0x631b25a0}, + {0xed4, 0x631b25a0}, {0xed8, 0x631b25a0}, + {0xedc, 0x001b25a0}, {0xee0, 0x001b25a0}, + {0xeec, 0x6b1b25a0}, {0xee8, 0x31555448}, + {0xf14, 0x00000003}, {0xf4c, 0x00000000}, + {0xf00, 0x00000300}, + {0xffff, 0xffffffff}, +}; + +static struct rtl8xxxu_reg32val rtl8xxx_agc_standard_table[] = { + {0xc78, 0x7b000001}, {0xc78, 0x7b010001}, + {0xc78, 0x7b020001}, {0xc78, 0x7b030001}, + {0xc78, 0x7b040001}, {0xc78, 0x7b050001}, + {0xc78, 0x7a060001}, {0xc78, 0x79070001}, + {0xc78, 0x78080001}, {0xc78, 0x77090001}, + {0xc78, 0x760a0001}, {0xc78, 0x750b0001}, + {0xc78, 0x740c0001}, {0xc78, 0x730d0001}, + {0xc78, 0x720e0001}, {0xc78, 0x710f0001}, + {0xc78, 0x70100001}, {0xc78, 0x6f110001}, + {0xc78, 0x6e120001}, {0xc78, 0x6d130001}, + {0xc78, 0x6c140001}, {0xc78, 0x6b150001}, + {0xc78, 0x6a160001}, {0xc78, 0x69170001}, + {0xc78, 0x68180001}, {0xc78, 0x67190001}, + {0xc78, 0x661a0001}, {0xc78, 0x651b0001}, + {0xc78, 0x641c0001}, {0xc78, 0x631d0001}, + {0xc78, 0x621e0001}, {0xc78, 0x611f0001}, + {0xc78, 0x60200001}, {0xc78, 0x49210001}, + {0xc78, 0x48220001}, {0xc78, 0x47230001}, + {0xc78, 0x46240001}, {0xc78, 0x45250001}, + {0xc78, 0x44260001}, {0xc78, 0x43270001}, + {0xc78, 0x42280001}, {0xc78, 0x41290001}, + {0xc78, 0x402a0001}, {0xc78, 0x262b0001}, + {0xc78, 0x252c0001}, {0xc78, 0x242d0001}, + {0xc78, 0x232e0001}, {0xc78, 0x222f0001}, + {0xc78, 0x21300001}, {0xc78, 0x20310001}, + {0xc78, 0x06320001}, {0xc78, 0x05330001}, + {0xc78, 0x04340001}, {0xc78, 0x03350001}, + {0xc78, 0x02360001}, {0xc78, 0x01370001}, + {0xc78, 0x00380001}, {0xc78, 0x00390001}, + {0xc78, 0x003a0001}, {0xc78, 0x003b0001}, + {0xc78, 0x003c0001}, {0xc78, 0x003d0001}, + {0xc78, 0x003e0001}, {0xc78, 0x003f0001}, + {0xc78, 0x7b400001}, {0xc78, 0x7b410001}, + {0xc78, 0x7b420001}, {0xc78, 0x7b430001}, + {0xc78, 0x7b440001}, {0xc78, 0x7b450001}, + {0xc78, 0x7a460001}, {0xc78, 0x79470001}, + {0xc78, 0x78480001}, {0xc78, 0x77490001}, + {0xc78, 0x764a0001}, {0xc78, 0x754b0001}, + {0xc78, 0x744c0001}, {0xc78, 0x734d0001}, + {0xc78, 0x724e0001}, {0xc78, 0x714f0001}, + {0xc78, 0x70500001}, {0xc78, 0x6f510001}, + {0xc78, 0x6e520001}, {0xc78, 0x6d530001}, + {0xc78, 0x6c540001}, {0xc78, 0x6b550001}, + {0xc78, 0x6a560001}, {0xc78, 0x69570001}, + {0xc78, 0x68580001}, {0xc78, 0x67590001}, + {0xc78, 0x665a0001}, {0xc78, 0x655b0001}, + {0xc78, 0x645c0001}, {0xc78, 0x635d0001}, + {0xc78, 0x625e0001}, {0xc78, 0x615f0001}, + {0xc78, 0x60600001}, {0xc78, 0x49610001}, + {0xc78, 0x48620001}, {0xc78, 0x47630001}, + {0xc78, 0x46640001}, {0xc78, 0x45650001}, + {0xc78, 0x44660001}, {0xc78, 0x43670001}, + {0xc78, 0x42680001}, {0xc78, 0x41690001}, + {0xc78, 0x406a0001}, {0xc78, 0x266b0001}, + {0xc78, 0x256c0001}, {0xc78, 0x246d0001}, + {0xc78, 0x236e0001}, {0xc78, 0x226f0001}, + {0xc78, 0x21700001}, {0xc78, 0x20710001}, + {0xc78, 0x06720001}, {0xc78, 0x05730001}, + {0xc78, 0x04740001}, {0xc78, 0x03750001}, + {0xc78, 0x02760001}, {0xc78, 0x01770001}, + {0xc78, 0x00780001}, {0xc78, 0x00790001}, + {0xc78, 0x007a0001}, {0xc78, 0x007b0001}, + {0xc78, 0x007c0001}, {0xc78, 0x007d0001}, + {0xc78, 0x007e0001}, {0xc78, 0x007f0001}, + {0xc78, 0x3800001e}, {0xc78, 0x3801001e}, + {0xc78, 0x3802001e}, {0xc78, 0x3803001e}, + {0xc78, 0x3804001e}, {0xc78, 0x3805001e}, + {0xc78, 0x3806001e}, {0xc78, 0x3807001e}, + {0xc78, 0x3808001e}, {0xc78, 0x3c09001e}, + {0xc78, 0x3e0a001e}, {0xc78, 0x400b001e}, + {0xc78, 0x440c001e}, {0xc78, 0x480d001e}, + {0xc78, 0x4c0e001e}, {0xc78, 0x500f001e}, + {0xc78, 0x5210001e}, {0xc78, 0x5611001e}, + {0xc78, 0x5a12001e}, {0xc78, 0x5e13001e}, + {0xc78, 0x6014001e}, {0xc78, 0x6015001e}, + {0xc78, 0x6016001e}, {0xc78, 0x6217001e}, + {0xc78, 0x6218001e}, {0xc78, 0x6219001e}, + {0xc78, 0x621a001e}, {0xc78, 0x621b001e}, + {0xc78, 0x621c001e}, {0xc78, 0x621d001e}, + {0xc78, 0x621e001e}, {0xc78, 0x621f001e}, + {0xffff, 0xffffffff} +}; + +static struct rtl8xxxu_reg32val rtl8xxx_agc_highpa_table[] = { + {0xc78, 0x7b000001}, {0xc78, 0x7b010001}, + {0xc78, 0x7b020001}, {0xc78, 0x7b030001}, + {0xc78, 0x7b040001}, {0xc78, 0x7b050001}, + {0xc78, 0x7b060001}, {0xc78, 0x7b070001}, + {0xc78, 0x7b080001}, {0xc78, 0x7a090001}, + {0xc78, 0x790a0001}, {0xc78, 0x780b0001}, + {0xc78, 0x770c0001}, {0xc78, 0x760d0001}, + {0xc78, 0x750e0001}, {0xc78, 0x740f0001}, + {0xc78, 0x73100001}, {0xc78, 0x72110001}, + {0xc78, 0x71120001}, {0xc78, 0x70130001}, + {0xc78, 0x6f140001}, {0xc78, 0x6e150001}, + {0xc78, 0x6d160001}, {0xc78, 0x6c170001}, + {0xc78, 0x6b180001}, {0xc78, 0x6a190001}, + {0xc78, 0x691a0001}, {0xc78, 0x681b0001}, + {0xc78, 0x671c0001}, {0xc78, 0x661d0001}, + {0xc78, 0x651e0001}, {0xc78, 0x641f0001}, + {0xc78, 0x63200001}, {0xc78, 0x62210001}, + {0xc78, 0x61220001}, {0xc78, 0x60230001}, + {0xc78, 0x46240001}, {0xc78, 0x45250001}, + {0xc78, 0x44260001}, {0xc78, 0x43270001}, + {0xc78, 0x42280001}, {0xc78, 0x41290001}, + {0xc78, 0x402a0001}, {0xc78, 0x262b0001}, + {0xc78, 0x252c0001}, {0xc78, 0x242d0001}, + {0xc78, 0x232e0001}, {0xc78, 0x222f0001}, + {0xc78, 0x21300001}, {0xc78, 0x20310001}, + {0xc78, 0x06320001}, {0xc78, 0x05330001}, + {0xc78, 0x04340001}, {0xc78, 0x03350001}, + {0xc78, 0x02360001}, {0xc78, 0x01370001}, + {0xc78, 0x00380001}, {0xc78, 0x00390001}, + {0xc78, 0x003a0001}, {0xc78, 0x003b0001}, + {0xc78, 0x003c0001}, {0xc78, 0x003d0001}, + {0xc78, 0x003e0001}, {0xc78, 0x003f0001}, + {0xc78, 0x7b400001}, {0xc78, 0x7b410001}, + {0xc78, 0x7b420001}, {0xc78, 0x7b430001}, + {0xc78, 0x7b440001}, {0xc78, 0x7b450001}, + {0xc78, 0x7b460001}, {0xc78, 0x7b470001}, + {0xc78, 0x7b480001}, {0xc78, 0x7a490001}, + {0xc78, 0x794a0001}, {0xc78, 0x784b0001}, + {0xc78, 0x774c0001}, {0xc78, 0x764d0001}, + {0xc78, 0x754e0001}, {0xc78, 0x744f0001}, + {0xc78, 0x73500001}, {0xc78, 0x72510001}, + {0xc78, 0x71520001}, {0xc78, 0x70530001}, + {0xc78, 0x6f540001}, {0xc78, 0x6e550001}, + {0xc78, 0x6d560001}, {0xc78, 0x6c570001}, + {0xc78, 0x6b580001}, {0xc78, 0x6a590001}, + {0xc78, 0x695a0001}, {0xc78, 0x685b0001}, + {0xc78, 0x675c0001}, {0xc78, 0x665d0001}, + {0xc78, 0x655e0001}, {0xc78, 0x645f0001}, + {0xc78, 0x63600001}, {0xc78, 0x62610001}, + {0xc78, 0x61620001}, {0xc78, 0x60630001}, + {0xc78, 0x46640001}, {0xc78, 0x45650001}, + {0xc78, 0x44660001}, {0xc78, 0x43670001}, + {0xc78, 0x42680001}, {0xc78, 0x41690001}, + {0xc78, 0x406a0001}, {0xc78, 0x266b0001}, + {0xc78, 0x256c0001}, {0xc78, 0x246d0001}, + {0xc78, 0x236e0001}, {0xc78, 0x226f0001}, + {0xc78, 0x21700001}, {0xc78, 0x20710001}, + {0xc78, 0x06720001}, {0xc78, 0x05730001}, + {0xc78, 0x04740001}, {0xc78, 0x03750001}, + {0xc78, 0x02760001}, {0xc78, 0x01770001}, + {0xc78, 0x00780001}, {0xc78, 0x00790001}, + {0xc78, 0x007a0001}, {0xc78, 0x007b0001}, + {0xc78, 0x007c0001}, {0xc78, 0x007d0001}, + {0xc78, 0x007e0001}, {0xc78, 0x007f0001}, + {0xc78, 0x3800001e}, {0xc78, 0x3801001e}, + {0xc78, 0x3802001e}, {0xc78, 0x3803001e}, + {0xc78, 0x3804001e}, {0xc78, 0x3805001e}, + {0xc78, 0x3806001e}, {0xc78, 0x3807001e}, + {0xc78, 0x3808001e}, {0xc78, 0x3c09001e}, + {0xc78, 0x3e0a001e}, {0xc78, 0x400b001e}, + {0xc78, 0x440c001e}, {0xc78, 0x480d001e}, + {0xc78, 0x4c0e001e}, {0xc78, 0x500f001e}, + {0xc78, 0x5210001e}, {0xc78, 0x5611001e}, + {0xc78, 0x5a12001e}, {0xc78, 0x5e13001e}, + {0xc78, 0x6014001e}, {0xc78, 0x6015001e}, + {0xc78, 0x6016001e}, {0xc78, 0x6217001e}, + {0xc78, 0x6218001e}, {0xc78, 0x6219001e}, + {0xc78, 0x621a001e}, {0xc78, 0x621b001e}, + {0xc78, 0x621c001e}, {0xc78, 0x621d001e}, + {0xc78, 0x621e001e}, {0xc78, 0x621f001e}, + {0xffff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregval rtl8723au_radioa_1t_init_table[] = { + {0x00, 0x00030159}, {0x01, 0x00031284}, + {0x02, 0x00098000}, {0x03, 0x00039c63}, + {0x04, 0x000210e7}, {0x09, 0x0002044f}, + {0x0a, 0x0001a3f1}, {0x0b, 0x00014787}, + {0x0c, 0x000896fe}, {0x0d, 0x0000e02c}, + {0x0e, 0x00039ce7}, {0x0f, 0x00000451}, + {0x19, 0x00000000}, {0x1a, 0x00030355}, + {0x1b, 0x00060a00}, {0x1c, 0x000fc378}, + {0x1d, 0x000a1250}, {0x1e, 0x0000024f}, + {0x1f, 0x00000000}, {0x20, 0x0000b614}, + {0x21, 0x0006c000}, {0x22, 0x00000000}, + {0x23, 0x00001558}, {0x24, 0x00000060}, + {0x25, 0x00000483}, {0x26, 0x0004f000}, + {0x27, 0x000ec7d9}, {0x28, 0x00057730}, + {0x29, 0x00004783}, {0x2a, 0x00000001}, + {0x2b, 0x00021334}, {0x2a, 0x00000000}, + {0x2b, 0x00000054}, {0x2a, 0x00000001}, + {0x2b, 0x00000808}, {0x2b, 0x00053333}, + {0x2c, 0x0000000c}, {0x2a, 0x00000002}, + {0x2b, 0x00000808}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000003}, + {0x2b, 0x00000808}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000004}, + {0x2b, 0x00000808}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000005}, + {0x2b, 0x00000808}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000006}, + {0x2b, 0x00000709}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000007}, + {0x2b, 0x00000709}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000008}, + {0x2b, 0x0000060a}, {0x2b, 0x0004b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000009}, + {0x2b, 0x0000060a}, {0x2b, 0x00053333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000a}, + {0x2b, 0x0000060a}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000b}, + {0x2b, 0x0000060a}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000c}, + {0x2b, 0x0000060a}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000d}, + {0x2b, 0x0000060a}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000e}, + {0x2b, 0x0000050b}, {0x2b, 0x00066666}, + {0x2c, 0x0000001a}, {0x2a, 0x000e0000}, + {0x10, 0x0004000f}, {0x11, 0x000e31fc}, + {0x10, 0x0006000f}, {0x11, 0x000ff9f8}, + {0x10, 0x0002000f}, {0x11, 0x000203f9}, + {0x10, 0x0003000f}, {0x11, 0x000ff500}, + {0x10, 0x00000000}, {0x11, 0x00000000}, + {0x10, 0x0008000f}, {0x11, 0x0003f100}, + {0x10, 0x0009000f}, {0x11, 0x00023100}, + {0x12, 0x00032000}, {0x12, 0x00071000}, + {0x12, 0x000b0000}, {0x12, 0x000fc000}, + {0x13, 0x000287b3}, {0x13, 0x000244b7}, + {0x13, 0x000204ab}, {0x13, 0x0001c49f}, + {0x13, 0x00018493}, {0x13, 0x0001429b}, + {0x13, 0x00010299}, {0x13, 0x0000c29c}, + {0x13, 0x000081a0}, {0x13, 0x000040ac}, + {0x13, 0x00000020}, {0x14, 0x0001944c}, + {0x14, 0x00059444}, {0x14, 0x0009944c}, + {0x14, 0x000d9444}, {0x15, 0x0000f474}, + {0x15, 0x0004f477}, {0x15, 0x0008f455}, + {0x15, 0x000cf455}, {0x16, 0x00000339}, + {0x16, 0x00040339}, {0x16, 0x00080339}, + {0x16, 0x000c0366}, {0x00, 0x00010159}, + {0x18, 0x0000f401}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0x1f, 0x00000003}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0x1e, 0x00000247}, {0x1f, 0x00000000}, + {0x00, 0x00030159}, + {0xff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregval rtl8192cu_radioa_2t_init_table[] = { + {0x00, 0x00030159}, {0x01, 0x00031284}, + {0x02, 0x00098000}, {0x03, 0x00018c63}, + {0x04, 0x000210e7}, {0x09, 0x0002044f}, + {0x0a, 0x0001adb1}, {0x0b, 0x00054867}, + {0x0c, 0x0008992e}, {0x0d, 0x0000e52c}, + {0x0e, 0x00039ce7}, {0x0f, 0x00000451}, + {0x19, 0x00000000}, {0x1a, 0x00010255}, + {0x1b, 0x00060a00}, {0x1c, 0x000fc378}, + {0x1d, 0x000a1250}, {0x1e, 0x0004445f}, + {0x1f, 0x00080001}, {0x20, 0x0000b614}, + {0x21, 0x0006c000}, {0x22, 0x00000000}, + {0x23, 0x00001558}, {0x24, 0x00000060}, + {0x25, 0x00000483}, {0x26, 0x0004f000}, + {0x27, 0x000ec7d9}, {0x28, 0x000577c0}, + {0x29, 0x00004783}, {0x2a, 0x00000001}, + {0x2b, 0x00021334}, {0x2a, 0x00000000}, + {0x2b, 0x00000054}, {0x2a, 0x00000001}, + {0x2b, 0x00000808}, {0x2b, 0x00053333}, + {0x2c, 0x0000000c}, {0x2a, 0x00000002}, + {0x2b, 0x00000808}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000003}, + {0x2b, 0x00000808}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000004}, + {0x2b, 0x00000808}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000005}, + {0x2b, 0x00000808}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000006}, + {0x2b, 0x00000709}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000007}, + {0x2b, 0x00000709}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000008}, + {0x2b, 0x0000060a}, {0x2b, 0x0004b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000009}, + {0x2b, 0x0000060a}, {0x2b, 0x00053333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000a}, + {0x2b, 0x0000060a}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000b}, + {0x2b, 0x0000060a}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000c}, + {0x2b, 0x0000060a}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000d}, + {0x2b, 0x0000060a}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000e}, + {0x2b, 0x0000050b}, {0x2b, 0x00066666}, + {0x2c, 0x0000001a}, {0x2a, 0x000e0000}, + {0x10, 0x0004000f}, {0x11, 0x000e31fc}, + {0x10, 0x0006000f}, {0x11, 0x000ff9f8}, + {0x10, 0x0002000f}, {0x11, 0x000203f9}, + {0x10, 0x0003000f}, {0x11, 0x000ff500}, + {0x10, 0x00000000}, {0x11, 0x00000000}, + {0x10, 0x0008000f}, {0x11, 0x0003f100}, + {0x10, 0x0009000f}, {0x11, 0x00023100}, + {0x12, 0x00032000}, {0x12, 0x00071000}, + {0x12, 0x000b0000}, {0x12, 0x000fc000}, + {0x13, 0x000287b3}, {0x13, 0x000244b7}, + {0x13, 0x000204ab}, {0x13, 0x0001c49f}, + {0x13, 0x00018493}, {0x13, 0x0001429b}, + {0x13, 0x00010299}, {0x13, 0x0000c29c}, + {0x13, 0x000081a0}, {0x13, 0x000040ac}, + {0x13, 0x00000020}, {0x14, 0x0001944c}, + {0x14, 0x00059444}, {0x14, 0x0009944c}, + {0x14, 0x000d9444}, {0x15, 0x0000f424}, + {0x15, 0x0004f424}, {0x15, 0x0008f424}, + {0x15, 0x000cf424}, {0x16, 0x000e0330}, + {0x16, 0x000a0330}, {0x16, 0x00060330}, + {0x16, 0x00020330}, {0x00, 0x00010159}, + {0x18, 0x0000f401}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0x1f, 0x00080003}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0x1e, 0x00044457}, {0x1f, 0x00080000}, + {0x00, 0x00030159}, + {0xff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregval rtl8192cu_radiob_2t_init_table[] = { + {0x00, 0x00030159}, {0x01, 0x00031284}, + {0x02, 0x00098000}, {0x03, 0x00018c63}, + {0x04, 0x000210e7}, {0x09, 0x0002044f}, + {0x0a, 0x0001adb1}, {0x0b, 0x00054867}, + {0x0c, 0x0008992e}, {0x0d, 0x0000e52c}, + {0x0e, 0x00039ce7}, {0x0f, 0x00000451}, + {0x12, 0x00032000}, {0x12, 0x00071000}, + {0x12, 0x000b0000}, {0x12, 0x000fc000}, + {0x13, 0x000287af}, {0x13, 0x000244b7}, + {0x13, 0x000204ab}, {0x13, 0x0001c49f}, + {0x13, 0x00018493}, {0x13, 0x00014297}, + {0x13, 0x00010295}, {0x13, 0x0000c298}, + {0x13, 0x0000819c}, {0x13, 0x000040a8}, + {0x13, 0x0000001c}, {0x14, 0x0001944c}, + {0x14, 0x00059444}, {0x14, 0x0009944c}, + {0x14, 0x000d9444}, {0x15, 0x0000f424}, + {0x15, 0x0004f424}, {0x15, 0x0008f424}, + {0x15, 0x000cf424}, {0x16, 0x000e0330}, + {0x16, 0x000a0330}, {0x16, 0x00060330}, + {0x16, 0x00020330}, + {0xff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregval rtl8192cu_radioa_1t_init_table[] = { + {0x00, 0x00030159}, {0x01, 0x00031284}, + {0x02, 0x00098000}, {0x03, 0x00018c63}, + {0x04, 0x000210e7}, {0x09, 0x0002044f}, + {0x0a, 0x0001adb1}, {0x0b, 0x00054867}, + {0x0c, 0x0008992e}, {0x0d, 0x0000e52c}, + {0x0e, 0x00039ce7}, {0x0f, 0x00000451}, + {0x19, 0x00000000}, {0x1a, 0x00010255}, + {0x1b, 0x00060a00}, {0x1c, 0x000fc378}, + {0x1d, 0x000a1250}, {0x1e, 0x0004445f}, + {0x1f, 0x00080001}, {0x20, 0x0000b614}, + {0x21, 0x0006c000}, {0x22, 0x00000000}, + {0x23, 0x00001558}, {0x24, 0x00000060}, + {0x25, 0x00000483}, {0x26, 0x0004f000}, + {0x27, 0x000ec7d9}, {0x28, 0x000577c0}, + {0x29, 0x00004783}, {0x2a, 0x00000001}, + {0x2b, 0x00021334}, {0x2a, 0x00000000}, + {0x2b, 0x00000054}, {0x2a, 0x00000001}, + {0x2b, 0x00000808}, {0x2b, 0x00053333}, + {0x2c, 0x0000000c}, {0x2a, 0x00000002}, + {0x2b, 0x00000808}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000003}, + {0x2b, 0x00000808}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000004}, + {0x2b, 0x00000808}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000005}, + {0x2b, 0x00000808}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000006}, + {0x2b, 0x00000709}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000007}, + {0x2b, 0x00000709}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000008}, + {0x2b, 0x0000060a}, {0x2b, 0x0004b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000009}, + {0x2b, 0x0000060a}, {0x2b, 0x00053333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000a}, + {0x2b, 0x0000060a}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000b}, + {0x2b, 0x0000060a}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000c}, + {0x2b, 0x0000060a}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000d}, + {0x2b, 0x0000060a}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000e}, + {0x2b, 0x0000050b}, {0x2b, 0x00066666}, + {0x2c, 0x0000001a}, {0x2a, 0x000e0000}, + {0x10, 0x0004000f}, {0x11, 0x000e31fc}, + {0x10, 0x0006000f}, {0x11, 0x000ff9f8}, + {0x10, 0x0002000f}, {0x11, 0x000203f9}, + {0x10, 0x0003000f}, {0x11, 0x000ff500}, + {0x10, 0x00000000}, {0x11, 0x00000000}, + {0x10, 0x0008000f}, {0x11, 0x0003f100}, + {0x10, 0x0009000f}, {0x11, 0x00023100}, + {0x12, 0x00032000}, {0x12, 0x00071000}, + {0x12, 0x000b0000}, {0x12, 0x000fc000}, + {0x13, 0x000287b3}, {0x13, 0x000244b7}, + {0x13, 0x000204ab}, {0x13, 0x0001c49f}, + {0x13, 0x00018493}, {0x13, 0x0001429b}, + {0x13, 0x00010299}, {0x13, 0x0000c29c}, + {0x13, 0x000081a0}, {0x13, 0x000040ac}, + {0x13, 0x00000020}, {0x14, 0x0001944c}, + {0x14, 0x00059444}, {0x14, 0x0009944c}, + {0x14, 0x000d9444}, {0x15, 0x0000f405}, + {0x15, 0x0004f405}, {0x15, 0x0008f405}, + {0x15, 0x000cf405}, {0x16, 0x000e0330}, + {0x16, 0x000a0330}, {0x16, 0x00060330}, + {0x16, 0x00020330}, {0x00, 0x00010159}, + {0x18, 0x0000f401}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0x1f, 0x00080003}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0x1e, 0x00044457}, {0x1f, 0x00080000}, + {0x00, 0x00030159}, + {0xff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregval rtl8188ru_radioa_1t_highpa_table[] = { + {0x00, 0x00030159}, {0x01, 0x00031284}, + {0x02, 0x00098000}, {0x03, 0x00018c63}, + {0x04, 0x000210e7}, {0x09, 0x0002044f}, + {0x0a, 0x0001adb0}, {0x0b, 0x00054867}, + {0x0c, 0x0008992e}, {0x0d, 0x0000e529}, + {0x0e, 0x00039ce7}, {0x0f, 0x00000451}, + {0x19, 0x00000000}, {0x1a, 0x00000255}, + {0x1b, 0x00060a00}, {0x1c, 0x000fc378}, + {0x1d, 0x000a1250}, {0x1e, 0x0004445f}, + {0x1f, 0x00080001}, {0x20, 0x0000b614}, + {0x21, 0x0006c000}, {0x22, 0x0000083c}, + {0x23, 0x00001558}, {0x24, 0x00000060}, + {0x25, 0x00000483}, {0x26, 0x0004f000}, + {0x27, 0x000ec7d9}, {0x28, 0x000977c0}, + {0x29, 0x00004783}, {0x2a, 0x00000001}, + {0x2b, 0x00021334}, {0x2a, 0x00000000}, + {0x2b, 0x00000054}, {0x2a, 0x00000001}, + {0x2b, 0x00000808}, {0x2b, 0x00053333}, + {0x2c, 0x0000000c}, {0x2a, 0x00000002}, + {0x2b, 0x00000808}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000003}, + {0x2b, 0x00000808}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000004}, + {0x2b, 0x00000808}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000005}, + {0x2b, 0x00000808}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000006}, + {0x2b, 0x00000709}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000007}, + {0x2b, 0x00000709}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000008}, + {0x2b, 0x0000060a}, {0x2b, 0x0004b333}, + {0x2c, 0x0000000d}, {0x2a, 0x00000009}, + {0x2b, 0x0000060a}, {0x2b, 0x00053333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000a}, + {0x2b, 0x0000060a}, {0x2b, 0x0005b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000b}, + {0x2b, 0x0000060a}, {0x2b, 0x00063333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000c}, + {0x2b, 0x0000060a}, {0x2b, 0x0006b333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000d}, + {0x2b, 0x0000060a}, {0x2b, 0x00073333}, + {0x2c, 0x0000000d}, {0x2a, 0x0000000e}, + {0x2b, 0x0000050b}, {0x2b, 0x00066666}, + {0x2c, 0x0000001a}, {0x2a, 0x000e0000}, + {0x10, 0x0004000f}, {0x11, 0x000e31fc}, + {0x10, 0x0006000f}, {0x11, 0x000ff9f8}, + {0x10, 0x0002000f}, {0x11, 0x000203f9}, + {0x10, 0x0003000f}, {0x11, 0x000ff500}, + {0x10, 0x00000000}, {0x11, 0x00000000}, + {0x10, 0x0008000f}, {0x11, 0x0003f100}, + {0x10, 0x0009000f}, {0x11, 0x00023100}, + {0x12, 0x000d8000}, {0x12, 0x00090000}, + {0x12, 0x00051000}, {0x12, 0x00012000}, + {0x13, 0x00028fb4}, {0x13, 0x00024fa8}, + {0x13, 0x000207a4}, {0x13, 0x0001c3b0}, + {0x13, 0x000183a4}, {0x13, 0x00014398}, + {0x13, 0x000101a4}, {0x13, 0x0000c198}, + {0x13, 0x000080a4}, {0x13, 0x00004098}, + {0x13, 0x00000000}, {0x14, 0x0001944c}, + {0x14, 0x00059444}, {0x14, 0x0009944c}, + {0x14, 0x000d9444}, {0x15, 0x0000f405}, + {0x15, 0x0004f405}, {0x15, 0x0008f405}, + {0x15, 0x000cf405}, {0x16, 0x000e0330}, + {0x16, 0x000a0330}, {0x16, 0x00060330}, + {0x16, 0x00020330}, {0x00, 0x00010159}, + {0x18, 0x0000f401}, {0xfe, 0x00000000}, + {0xfe, 0x00000000}, {0x1f, 0x00080003}, + {0xfe, 0x00000000}, {0xfe, 0x00000000}, + {0x1e, 0x00044457}, {0x1f, 0x00080000}, + {0x00, 0x00030159}, + {0xff, 0xffffffff} +}; + +static struct rtl8xxxu_rfregs rtl8xxxu_rfregs[] = { + { /* RF_A */ + .hssiparm1 = REG_FPGA0_XA_HSSI_PARM1, + .hssiparm2 = REG_FPGA0_XA_HSSI_PARM2, + .lssiparm = REG_FPGA0_XA_LSSI_PARM, + .hspiread = REG_HSPI_XA_READBACK, + .lssiread = REG_FPGA0_XA_LSSI_READBACK, + .rf_sw_ctrl = REG_FPGA0_XA_RF_SW_CTRL, + }, + { /* RF_B */ + .hssiparm1 = REG_FPGA0_XB_HSSI_PARM1, + .hssiparm2 = REG_FPGA0_XB_HSSI_PARM2, + .lssiparm = REG_FPGA0_XB_LSSI_PARM, + .hspiread = REG_HSPI_XB_READBACK, + .lssiread = REG_FPGA0_XB_LSSI_READBACK, + .rf_sw_ctrl = REG_FPGA0_XB_RF_SW_CTRL, + }, +}; + +static const u32 rtl8723au_iqk_phy_iq_bb_reg[RTL8XXXU_BB_REGS] = { + REG_OFDM0_XA_RX_IQ_IMBALANCE, + REG_OFDM0_XB_RX_IQ_IMBALANCE, + REG_OFDM0_ENERGY_CCA_THRES, + REG_OFDM0_AGCR_SSI_TABLE, + REG_OFDM0_XA_TX_IQ_IMBALANCE, + REG_OFDM0_XB_TX_IQ_IMBALANCE, + REG_OFDM0_XC_TX_AFE, + REG_OFDM0_XD_TX_AFE, + REG_OFDM0_RX_IQ_EXT_ANTA +}; + +static u8 rtl8xxxu_read8(struct rtl8xxxu_priv *priv, u16 addr) +{ + struct usb_device *udev = priv->udev; + int len; + u8 data; + + mutex_lock(&priv->usb_buf_mutex); + len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_READ, + addr, 0, &priv->usb_buf.val8, sizeof(u8), + RTW_USB_CONTROL_MSG_TIMEOUT); + data = priv->usb_buf.val8; + mutex_unlock(&priv->usb_buf_mutex); + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_READ) + dev_info(&udev->dev, "%s(%04x) = 0x%02x, len %i\n", + __func__, addr, data, len); + return data; +} + +static u16 rtl8xxxu_read16(struct rtl8xxxu_priv *priv, u16 addr) +{ + struct usb_device *udev = priv->udev; + int len; + u16 data; + + mutex_lock(&priv->usb_buf_mutex); + len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_READ, + addr, 0, &priv->usb_buf.val16, sizeof(u16), + RTW_USB_CONTROL_MSG_TIMEOUT); + data = le16_to_cpu(priv->usb_buf.val16); + mutex_unlock(&priv->usb_buf_mutex); + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_READ) + dev_info(&udev->dev, "%s(%04x) = 0x%04x, len %i\n", + __func__, addr, data, len); + return data; +} + +static u32 rtl8xxxu_read32(struct rtl8xxxu_priv *priv, u16 addr) +{ + struct usb_device *udev = priv->udev; + int len; + u32 data; + + mutex_lock(&priv->usb_buf_mutex); + len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_READ, + addr, 0, &priv->usb_buf.val32, sizeof(u32), + RTW_USB_CONTROL_MSG_TIMEOUT); + data = le32_to_cpu(priv->usb_buf.val32); + mutex_unlock(&priv->usb_buf_mutex); + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_READ) + dev_info(&udev->dev, "%s(%04x) = 0x%08x, len %i\n", + __func__, addr, data, len); + return data; +} + +static int rtl8xxxu_write8(struct rtl8xxxu_priv *priv, u16 addr, u8 val) +{ + struct usb_device *udev = priv->udev; + int ret; + + mutex_lock(&priv->usb_buf_mutex); + priv->usb_buf.val8 = val; + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, + addr, 0, &priv->usb_buf.val8, sizeof(u8), + RTW_USB_CONTROL_MSG_TIMEOUT); + + mutex_unlock(&priv->usb_buf_mutex); + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE) + dev_info(&udev->dev, "%s(%04x) = 0x%02x\n", + __func__, addr, val); + return ret; +} + +static int rtl8xxxu_write16(struct rtl8xxxu_priv *priv, u16 addr, u16 val) +{ + struct usb_device *udev = priv->udev; + int ret; + + mutex_lock(&priv->usb_buf_mutex); + priv->usb_buf.val16 = cpu_to_le16(val); + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, + addr, 0, &priv->usb_buf.val16, sizeof(u16), + RTW_USB_CONTROL_MSG_TIMEOUT); + mutex_unlock(&priv->usb_buf_mutex); + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE) + dev_info(&udev->dev, "%s(%04x) = 0x%04x\n", + __func__, addr, val); + return ret; +} + +static int rtl8xxxu_write32(struct rtl8xxxu_priv *priv, u16 addr, u32 val) +{ + struct usb_device *udev = priv->udev; + int ret; + + mutex_lock(&priv->usb_buf_mutex); + priv->usb_buf.val32 = cpu_to_le32(val); + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, + addr, 0, &priv->usb_buf.val32, sizeof(u32), + RTW_USB_CONTROL_MSG_TIMEOUT); + mutex_unlock(&priv->usb_buf_mutex); + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_REG_WRITE) + dev_info(&udev->dev, "%s(%04x) = 0x%08x\n", + __func__, addr, val); + return ret; +} + +static int +rtl8xxxu_writeN(struct rtl8xxxu_priv *priv, u16 addr, u8 *buf, u16 len) +{ + struct usb_device *udev = priv->udev; + int blocksize = priv->fops->writeN_block_size; + int ret, i, count, remainder; + + count = len / blocksize; + remainder = len % blocksize; + + for (i = 0; i < count; i++) { + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, + addr, 0, buf, blocksize, + RTW_USB_CONTROL_MSG_TIMEOUT); + if (ret != blocksize) + goto write_error; + + addr += blocksize; + buf += blocksize; + } + + if (remainder) { + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + REALTEK_USB_CMD_REQ, REALTEK_USB_WRITE, + addr, 0, buf, remainder, + RTW_USB_CONTROL_MSG_TIMEOUT); + if (ret != remainder) + goto write_error; + } + + return len; + +write_error: + dev_info(&udev->dev, + "%s: Failed to write block at addr: %04x size: %04x\n", + __func__, addr, blocksize); + return -EAGAIN; +} + +static u32 rtl8xxxu_read_rfreg(struct rtl8xxxu_priv *priv, + enum rtl8xxxu_rfpath path, u8 reg) +{ + u32 hssia, val32, retval; + + hssia = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM2); + if (path != RF_A) + val32 = rtl8xxxu_read32(priv, rtl8xxxu_rfregs[path].hssiparm2); + else + val32 = hssia; + + val32 &= ~FPGA0_HSSI_PARM2_ADDR_MASK; + val32 |= (reg << FPGA0_HSSI_PARM2_ADDR_SHIFT); + val32 |= FPGA0_HSSI_PARM2_EDGE_READ; + hssia &= ~FPGA0_HSSI_PARM2_EDGE_READ; + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM2, hssia); + + udelay(10); + + rtl8xxxu_write32(priv, rtl8xxxu_rfregs[path].hssiparm2, val32); + udelay(100); + + hssia |= FPGA0_HSSI_PARM2_EDGE_READ; + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM2, hssia); + udelay(10); + + val32 = rtl8xxxu_read32(priv, rtl8xxxu_rfregs[path].hssiparm1); + if (val32 & FPGA0_HSSI_PARM1_PI) + retval = rtl8xxxu_read32(priv, rtl8xxxu_rfregs[path].hspiread); + else + retval = rtl8xxxu_read32(priv, rtl8xxxu_rfregs[path].lssiread); + + retval &= 0xfffff; + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_RFREG_READ) + dev_info(&priv->udev->dev, "%s(%02x) = 0x%06x\n", + __func__, reg, retval); + return retval; +} + +static int rtl8xxxu_write_rfreg(struct rtl8xxxu_priv *priv, + enum rtl8xxxu_rfpath path, u8 reg, u32 data) +{ + int ret, retval; + u32 dataaddr; + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_RFREG_WRITE) + dev_info(&priv->udev->dev, "%s(%02x) = 0x%06x\n", + __func__, reg, data); + + data &= FPGA0_LSSI_PARM_DATA_MASK; + dataaddr = (reg << FPGA0_LSSI_PARM_ADDR_SHIFT) | data; + + /* Use XB for path B */ + ret = rtl8xxxu_write32(priv, rtl8xxxu_rfregs[path].lssiparm, dataaddr); + if (ret != sizeof(dataaddr)) + retval = -EIO; + else + retval = 0; + + udelay(1); + + return retval; +} + +static int rtl8723a_h2c_cmd(struct rtl8xxxu_priv *priv, struct h2c_cmd *h2c) +{ + struct device *dev = &priv->udev->dev; + int mbox_nr, retry, retval = 0; + int mbox_reg, mbox_ext_reg; + u8 val8; + + mutex_lock(&priv->h2c_mutex); + + mbox_nr = priv->next_mbox; + mbox_reg = REG_HMBOX_0 + (mbox_nr * 4); + mbox_ext_reg = REG_HMBOX_EXT_0 + (mbox_nr * 2); + + /* + * MBOX ready? + */ + retry = 100; + do { + val8 = rtl8xxxu_read8(priv, REG_HMTFR); + if (!(val8 & BIT(mbox_nr))) + break; + } while (retry--); + + if (!retry) { + dev_dbg(dev, "%s: Mailbox busy\n", __func__); + retval = -EBUSY; + goto error; + } + + /* + * Need to swap as it's being swapped again by rtl8xxxu_write16/32() + */ + if (h2c->cmd.cmd & H2C_EXT) { + rtl8xxxu_write16(priv, mbox_ext_reg, + le16_to_cpu(h2c->raw.ext)); + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_H2C) + dev_info(dev, "H2C_EXT %04x\n", + le16_to_cpu(h2c->raw.ext)); + } + rtl8xxxu_write32(priv, mbox_reg, le32_to_cpu(h2c->raw.data)); + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_H2C) + dev_info(dev, "H2C %08x\n", le32_to_cpu(h2c->raw.data)); + + priv->next_mbox = (mbox_nr + 1) % H2C_MAX_MBOX; + +error: + mutex_unlock(&priv->h2c_mutex); + return retval; +} + +static void rtl8723a_enable_rf(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u32 val32; + + val8 = rtl8xxxu_read8(priv, REG_SPS0_CTRL); + val8 |= BIT(0) | BIT(3); + rtl8xxxu_write8(priv, REG_SPS0_CTRL, val8); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_PARM); + val32 &= ~(BIT(4) | BIT(5)); + val32 |= BIT(3); + if (priv->rf_paths == 2) { + val32 &= ~(BIT(20) | BIT(21)); + val32 |= BIT(19); + } + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_PARM, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); + val32 &= ~OFDM_RF_PATH_TX_MASK; + if (priv->tx_paths == 2) + val32 |= OFDM_RF_PATH_TX_A | OFDM_RF_PATH_TX_B; + else if (priv->rtlchip == 0x8192c || priv->rtlchip == 0x8191c) + val32 |= OFDM_RF_PATH_TX_B; + else + val32 |= OFDM_RF_PATH_TX_A; + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + val32 &= ~FPGA_RF_MODE_JAPAN; + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + + if (priv->rf_paths == 2) + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x63db25a0); + else + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x631b25a0); + + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0x32d95); + if (priv->rf_paths == 2) + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0x32d95); + + rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00); +} + +static void rtl8723a_disable_rf(struct rtl8xxxu_priv *priv) +{ + u8 sps0; + u32 val32; + + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + + sps0 = rtl8xxxu_read8(priv, REG_SPS0_CTRL); + + /* RF RX code for preamble power saving */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_PARM); + val32 &= ~(BIT(3) | BIT(4) | BIT(5)); + if (priv->rf_paths == 2) + val32 &= ~(BIT(19) | BIT(20) | BIT(21)); + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_PARM, val32); + + /* Disable TX for four paths */ + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); + val32 &= ~OFDM_RF_PATH_TX_MASK; + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32); + + /* Enable power saving */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + val32 |= FPGA_RF_MODE_JAPAN; + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + + /* AFE control register to power down bits [30:22] */ + if (priv->rf_paths == 2) + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00db25a0); + else + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x001b25a0); + + /* Power down RF module */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0); + if (priv->rf_paths == 2) + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0); + + sps0 &= ~(BIT(0) | BIT(3)); + rtl8xxxu_write8(priv, REG_SPS0_CTRL, sps0); +} + + +static void rtl8723a_stop_tx_beacon(struct rtl8xxxu_priv *priv) +{ + u8 val8; + + val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL + 2); + val8 &= ~BIT(6); + rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL + 2, val8); + + rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 1, 0x64); + val8 = rtl8xxxu_read8(priv, REG_TBTT_PROHIBIT + 2); + val8 &= ~BIT(0); + rtl8xxxu_write8(priv, REG_TBTT_PROHIBIT + 2, val8); +} + + +/* + * The rtl8723a has 3 channel groups for it's efuse settings. It only + * supports the 2.4GHz band, so channels 1 - 14: + * group 0: channels 1 - 3 + * group 1: channels 4 - 9 + * group 2: channels 10 - 14 + * + * Note: We index from 0 in the code + */ +static int rtl8723a_channel_to_group(int channel) +{ + int group; + + if (channel < 4) + group = 0; + else if (channel < 10) + group = 1; + else + group = 2; + + return group; +} + +static void rtl8723au_config_channel(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + u32 val32, rsr; + u8 val8, opmode; + bool ht = true; + int sec_ch_above, channel; + int i; + + opmode = rtl8xxxu_read8(priv, REG_BW_OPMODE); + rsr = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); + channel = hw->conf.chandef.chan->hw_value; + + switch (hw->conf.chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + ht = false; + case NL80211_CHAN_WIDTH_20: + opmode |= BW_OPMODE_20MHZ; + rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + val32 &= ~FPGA_RF_MODE; + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE); + val32 &= ~FPGA_RF_MODE; + rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_ANALOG2); + val32 |= FPGA0_ANALOG2_20MHZ; + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG2, val32); + break; + case NL80211_CHAN_WIDTH_40: + if (hw->conf.chandef.center_freq1 > + hw->conf.chandef.chan->center_freq) { + sec_ch_above = 1; + channel += 2; + } else { + sec_ch_above = 0; + channel -= 2; + } + + opmode &= ~BW_OPMODE_20MHZ; + rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode); + rsr &= ~RSR_RSC_BANDWIDTH_40M; + if (sec_ch_above) + rsr |= RSR_RSC_UPPER_SUB_CHANNEL; + else + rsr |= RSR_RSC_LOWER_SUB_CHANNEL; + rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, rsr); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + val32 |= FPGA_RF_MODE; + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE); + val32 |= FPGA_RF_MODE; + rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val32); + + /* + * Set Control channel to upper or lower. These settings + * are required only for 40MHz + */ + val32 = rtl8xxxu_read32(priv, REG_CCK0_SYSTEM); + val32 &= ~CCK0_SIDEBAND; + if (!sec_ch_above) + val32 |= CCK0_SIDEBAND; + rtl8xxxu_write32(priv, REG_CCK0_SYSTEM, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM1_LSTF); + val32 &= ~OFDM_LSTF_PRIME_CH_MASK; /* 0xc00 */ + if (sec_ch_above) + val32 |= OFDM_LSTF_PRIME_CH_LOW; + else + val32 |= OFDM_LSTF_PRIME_CH_HIGH; + rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_ANALOG2); + val32 &= ~FPGA0_ANALOG2_20MHZ; + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG2, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE); + val32 &= ~(FPGA0_PS_LOWER_CHANNEL | FPGA0_PS_UPPER_CHANNEL); + if (sec_ch_above) + val32 |= FPGA0_PS_UPPER_CHANNEL; + else + val32 |= FPGA0_PS_LOWER_CHANNEL; + rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val32); + break; + + default: + break; + } + + for (i = RF_A; i < priv->rf_paths; i++) { + val32 = rtl8xxxu_read_rfreg(priv, i, RF6052_REG_MODE_AG); + val32 &= ~MODE_AG_CHANNEL_MASK; + val32 |= channel; + rtl8xxxu_write_rfreg(priv, i, RF6052_REG_MODE_AG, val32); + } + + if (ht) + val8 = 0x0e; + else + val8 = 0x0a; + + rtl8xxxu_write8(priv, REG_SIFS_CCK + 1, val8); + rtl8xxxu_write8(priv, REG_SIFS_OFDM + 1, val8); + + rtl8xxxu_write16(priv, REG_R2T_SIFS, 0x0808); + rtl8xxxu_write16(priv, REG_T2T_SIFS, 0x0a0a); + + for (i = RF_A; i < priv->rf_paths; i++) { + val32 = rtl8xxxu_read_rfreg(priv, i, RF6052_REG_MODE_AG); + if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40) + val32 &= ~MODE_AG_CHANNEL_20MHZ; + else + val32 |= MODE_AG_CHANNEL_20MHZ; + rtl8xxxu_write_rfreg(priv, i, RF6052_REG_MODE_AG, val32); + } +} + +static void +rtl8723a_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) +{ + u8 cck[RTL8723A_MAX_RF_PATHS], ofdm[RTL8723A_MAX_RF_PATHS]; + u8 ofdmbase[RTL8723A_MAX_RF_PATHS], mcsbase[RTL8723A_MAX_RF_PATHS]; + u32 val32, ofdm_a, ofdm_b, mcs_a, mcs_b; + u8 val8; + int group, i; + + group = rtl8723a_channel_to_group(channel); + + cck[0] = priv->cck_tx_power_index_A[group]; + cck[1] = priv->cck_tx_power_index_B[group]; + + ofdm[0] = priv->ht40_1s_tx_power_index_A[group]; + ofdm[1] = priv->ht40_1s_tx_power_index_B[group]; + + ofdmbase[0] = ofdm[0] + priv->ofdm_tx_power_index_diff[group].a; + ofdmbase[1] = ofdm[1] + priv->ofdm_tx_power_index_diff[group].b; + + mcsbase[0] = ofdm[0]; + mcsbase[1] = ofdm[1]; + if (!ht40) { + mcsbase[0] += priv->ht20_tx_power_index_diff[group].a; + mcsbase[1] += priv->ht20_tx_power_index_diff[group].b; + } + + if (priv->tx_paths > 1) { + if (ofdm[0] > priv->ht40_2s_tx_power_index_diff[group].a) + ofdm[0] -= priv->ht40_2s_tx_power_index_diff[group].a; + if (ofdm[1] > priv->ht40_2s_tx_power_index_diff[group].b) + ofdm[1] -= priv->ht40_2s_tx_power_index_diff[group].b; + } + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_CHANNEL) + dev_info(&priv->udev->dev, + "%s: Setting TX power CCK A: %02x, " + "CCK B: %02x, OFDM A: %02x, OFDM B: %02x\n", + __func__, cck[0], cck[1], ofdm[0], ofdm[1]); + + for (i = 0; i < RTL8723A_MAX_RF_PATHS; i++) { + if (cck[i] > RF6052_MAX_TX_PWR) + cck[i] = RF6052_MAX_TX_PWR; + if (ofdm[i] > RF6052_MAX_TX_PWR) + ofdm[i] = RF6052_MAX_TX_PWR; + } + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_A_CCK1_MCS32); + val32 &= 0xffff00ff; + val32 |= (cck[0] << 8); + rtl8xxxu_write32(priv, REG_TX_AGC_A_CCK1_MCS32, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11); + val32 &= 0xff; + val32 |= ((cck[0] << 8) | (cck[0] << 16) | (cck[0] << 24)); + rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11); + val32 &= 0xffffff00; + val32 |= cck[1]; + rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK1_55_MCS32); + val32 &= 0xff; + val32 |= ((cck[1] << 8) | (cck[1] << 16) | (cck[1] << 24)); + rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK1_55_MCS32, val32); + + ofdm_a = ofdmbase[0] | ofdmbase[0] << 8 | + ofdmbase[0] << 16 | ofdmbase[0] << 24; + ofdm_b = ofdmbase[1] | ofdmbase[1] << 8 | + ofdmbase[1] << 16 | ofdmbase[1] << 24; + rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE18_06, ofdm_a); + rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE18_06, ofdm_b); + + rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE54_24, ofdm_a); + rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE54_24, ofdm_b); + + mcs_a = mcsbase[0] | mcsbase[0] << 8 | + mcsbase[0] << 16 | mcsbase[0] << 24; + mcs_b = mcsbase[1] | mcsbase[1] << 8 | + mcsbase[1] << 16 | mcsbase[1] << 24; + + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS03_MCS00, mcs_a); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS03_MCS00, mcs_b); + + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, mcs_a); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS07_MCS04, mcs_b); + + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS11_MCS08, mcs_a); + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS11_MCS08, mcs_b); + + rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12, mcs_a); + for (i = 0; i < 3; i++) { + if (i != 2) + val8 = (mcsbase[0] > 8) ? (mcsbase[0] - 8) : 0; + else + val8 = (mcsbase[0] > 6) ? (mcsbase[0] - 6) : 0; + rtl8xxxu_write8(priv, REG_OFDM0_XC_TX_IQ_IMBALANCE + i, val8); + } + rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS15_MCS12, mcs_b); + for (i = 0; i < 3; i++) { + if (i != 2) + val8 = (mcsbase[1] > 8) ? (mcsbase[1] - 8) : 0; + else + val8 = (mcsbase[1] > 6) ? (mcsbase[1] - 6) : 0; + rtl8xxxu_write8(priv, REG_OFDM0_XD_TX_IQ_IMBALANCE + i, val8); + } +} + +static void rtl8xxxu_set_linktype(struct rtl8xxxu_priv *priv, + enum nl80211_iftype linktype) +{ + u16 val8; + + val8 = rtl8xxxu_read16(priv, REG_MSR); + val8 &= ~MSR_LINKTYPE_MASK; + + switch (linktype) { + case NL80211_IFTYPE_UNSPECIFIED: + val8 |= MSR_LINKTYPE_NONE; + break; + case NL80211_IFTYPE_ADHOC: + val8 |= MSR_LINKTYPE_ADHOC; + break; + case NL80211_IFTYPE_STATION: + val8 |= MSR_LINKTYPE_STATION; + break; + case NL80211_IFTYPE_AP: + val8 |= MSR_LINKTYPE_AP; + break; + default: + goto out; + } + + rtl8xxxu_write8(priv, REG_MSR, val8); +out: + return; +} + +static void +rtl8xxxu_set_retry(struct rtl8xxxu_priv *priv, u16 short_retry, u16 long_retry) +{ + u16 val16; + + val16 = ((short_retry << RETRY_LIMIT_SHORT_SHIFT) & + RETRY_LIMIT_SHORT_MASK) | + ((long_retry << RETRY_LIMIT_LONG_SHIFT) & + RETRY_LIMIT_LONG_MASK); + + rtl8xxxu_write16(priv, REG_RETRY_LIMIT, val16); +} + +static void +rtl8xxxu_set_spec_sifs(struct rtl8xxxu_priv *priv, u16 cck, u16 ofdm) +{ + u16 val16; + + val16 = ((cck << SPEC_SIFS_CCK_SHIFT) & SPEC_SIFS_CCK_MASK) | + ((ofdm << SPEC_SIFS_OFDM_SHIFT) & SPEC_SIFS_OFDM_MASK); + + rtl8xxxu_write16(priv, REG_SPEC_SIFS, val16); +} + +static void rtl8xxxu_print_chipinfo(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + char *cut; + + switch (priv->chip_cut) { + case 0: + cut = "A"; + break; + case 1: + cut = "B"; + break; + default: + cut = "unknown"; + } + + dev_info(dev, + "RTL%s rev %s (%s) %iT%iR, TX queues %i, WiFi=%i, BT=%i, GPS=%i, HI PA=%i\n", + priv->chip_name, cut, priv->vendor_umc ? "UMC" : "TSMC", + priv->tx_paths, priv->rx_paths, priv->ep_tx_count, + priv->has_wifi, priv->has_bluetooth, priv->has_gps, + priv->hi_pa); + + dev_info(dev, "RTL%s MAC: %pM\n", priv->chip_name, priv->mac_addr); +} + +static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + u32 val32, bonding; + u16 val16; + + val32 = rtl8xxxu_read32(priv, REG_SYS_CFG); + priv->chip_cut = (val32 & SYS_CFG_CHIP_VERSION_MASK) >> + SYS_CFG_CHIP_VERSION_SHIFT; + if (val32 & SYS_CFG_TRP_VAUX_EN) { + dev_info(dev, "Unsupported test chip\n"); + return -ENOTSUPP; + } + + if (val32 & SYS_CFG_BT_FUNC) { + sprintf(priv->chip_name, "8723AU"); + priv->rf_paths = 1; + priv->rx_paths = 1; + priv->tx_paths = 1; + priv->rtlchip = 0x8723a; + + val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL); + if (val32 & MULTI_WIFI_FUNC_EN) + priv->has_wifi = 1; + if (val32 & MULTI_BT_FUNC_EN) + priv->has_bluetooth = 1; + if (val32 & MULTI_GPS_FUNC_EN) + priv->has_gps = 1; + } else if (val32 & SYS_CFG_TYPE_ID) { + bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); + bonding &= HPON_FSM_BONDING_MASK; + if (bonding == HPON_FSM_BONDING_1T2R) { + sprintf(priv->chip_name, "8191CU"); + priv->rf_paths = 2; + priv->rx_paths = 2; + priv->tx_paths = 1; + priv->rtlchip = 0x8191c; + } else { + sprintf(priv->chip_name, "8192CU"); + priv->rf_paths = 2; + priv->rx_paths = 2; + priv->tx_paths = 2; + priv->rtlchip = 0x8192c; + } + priv->has_wifi = 1; + } else { + sprintf(priv->chip_name, "8188CU"); + priv->rf_paths = 1; + priv->rx_paths = 1; + priv->tx_paths = 1; + priv->rtlchip = 0x8188c; + priv->has_wifi = 1; + } + + if (val32 & SYS_CFG_VENDOR_ID) + priv->vendor_umc = 1; + + val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS); + priv->rom_rev = (val32 & GPIO_RF_RL_ID) >> 28; + + val16 = rtl8xxxu_read16(priv, REG_NORMAL_SIE_EP_TX); + if (val16 & NORMAL_SIE_EP_TX_HIGH_MASK) { + priv->ep_tx_high_queue = 1; + priv->ep_tx_count++; + } + + if (val16 & NORMAL_SIE_EP_TX_NORMAL_MASK) { + priv->ep_tx_normal_queue = 1; + priv->ep_tx_count++; + } + + if (val16 & NORMAL_SIE_EP_TX_LOW_MASK) { + priv->ep_tx_low_queue = 1; + priv->ep_tx_count++; + } + + /* + * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX + */ + if (!priv->ep_tx_count) { + switch (priv->nr_out_eps) { + case 3: + priv->ep_tx_low_queue = 1; + priv->ep_tx_count++; + case 2: + priv->ep_tx_normal_queue = 1; + priv->ep_tx_count++; + case 1: + priv->ep_tx_high_queue = 1; + priv->ep_tx_count++; + break; + default: + dev_info(dev, "Unsupported USB TX end-points\n"); + return -ENOTSUPP; + } + } + + return 0; +} + +static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv) +{ + if (priv->efuse_wifi.efuse8723.rtl_id != cpu_to_le16(0x8129)) + return -EINVAL; + + ether_addr_copy(priv->mac_addr, priv->efuse_wifi.efuse8723.mac_addr); + + memcpy(priv->cck_tx_power_index_A, + priv->efuse_wifi.efuse8723.cck_tx_power_index_A, + sizeof(priv->cck_tx_power_index_A)); + memcpy(priv->cck_tx_power_index_B, + priv->efuse_wifi.efuse8723.cck_tx_power_index_B, + sizeof(priv->cck_tx_power_index_B)); + + memcpy(priv->ht40_1s_tx_power_index_A, + priv->efuse_wifi.efuse8723.ht40_1s_tx_power_index_A, + sizeof(priv->ht40_1s_tx_power_index_A)); + memcpy(priv->ht40_1s_tx_power_index_B, + priv->efuse_wifi.efuse8723.ht40_1s_tx_power_index_B, + sizeof(priv->ht40_1s_tx_power_index_B)); + + memcpy(priv->ht20_tx_power_index_diff, + priv->efuse_wifi.efuse8723.ht20_tx_power_index_diff, + sizeof(priv->ht20_tx_power_index_diff)); + memcpy(priv->ofdm_tx_power_index_diff, + priv->efuse_wifi.efuse8723.ofdm_tx_power_index_diff, + sizeof(priv->ofdm_tx_power_index_diff)); + + memcpy(priv->ht40_max_power_offset, + priv->efuse_wifi.efuse8723.ht40_max_power_offset, + sizeof(priv->ht40_max_power_offset)); + memcpy(priv->ht20_max_power_offset, + priv->efuse_wifi.efuse8723.ht20_max_power_offset, + sizeof(priv->ht20_max_power_offset)); + + dev_info(&priv->udev->dev, "Vendor: %.7s\n", + priv->efuse_wifi.efuse8723.vendor_name); + dev_info(&priv->udev->dev, "Product: %.41s\n", + priv->efuse_wifi.efuse8723.device_name); + return 0; +} + +static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv) +{ + int i; + + if (priv->efuse_wifi.efuse8192.rtl_id != cpu_to_le16(0x8129)) + return -EINVAL; + + ether_addr_copy(priv->mac_addr, priv->efuse_wifi.efuse8192.mac_addr); + + memcpy(priv->cck_tx_power_index_A, + priv->efuse_wifi.efuse8192.cck_tx_power_index_A, + sizeof(priv->cck_tx_power_index_A)); + memcpy(priv->cck_tx_power_index_B, + priv->efuse_wifi.efuse8192.cck_tx_power_index_B, + sizeof(priv->cck_tx_power_index_B)); + + memcpy(priv->ht40_1s_tx_power_index_A, + priv->efuse_wifi.efuse8192.ht40_1s_tx_power_index_A, + sizeof(priv->ht40_1s_tx_power_index_A)); + memcpy(priv->ht40_1s_tx_power_index_B, + priv->efuse_wifi.efuse8192.ht40_1s_tx_power_index_B, + sizeof(priv->ht40_1s_tx_power_index_B)); + memcpy(priv->ht40_2s_tx_power_index_diff, + priv->efuse_wifi.efuse8192.ht40_2s_tx_power_index_diff, + sizeof(priv->ht40_2s_tx_power_index_diff)); + + memcpy(priv->ht20_tx_power_index_diff, + priv->efuse_wifi.efuse8192.ht20_tx_power_index_diff, + sizeof(priv->ht20_tx_power_index_diff)); + memcpy(priv->ofdm_tx_power_index_diff, + priv->efuse_wifi.efuse8192.ofdm_tx_power_index_diff, + sizeof(priv->ofdm_tx_power_index_diff)); + + memcpy(priv->ht40_max_power_offset, + priv->efuse_wifi.efuse8192.ht40_max_power_offset, + sizeof(priv->ht40_max_power_offset)); + memcpy(priv->ht20_max_power_offset, + priv->efuse_wifi.efuse8192.ht20_max_power_offset, + sizeof(priv->ht20_max_power_offset)); + + dev_info(&priv->udev->dev, "Vendor: %.7s\n", + priv->efuse_wifi.efuse8192.vendor_name); + dev_info(&priv->udev->dev, "Product: %.20s\n", + priv->efuse_wifi.efuse8192.device_name); + + if (priv->efuse_wifi.efuse8192.rf_regulatory & 0x20) { + sprintf(priv->chip_name, "8188RU"); + priv->hi_pa = 1; + } + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) { + unsigned char *raw = priv->efuse_wifi.raw; + + dev_info(&priv->udev->dev, + "%s: dumping efuse (0x%02zx bytes):\n", + __func__, sizeof(struct rtl8192cu_efuse)); + for (i = 0; i < sizeof(struct rtl8192cu_efuse); i += 8) { + dev_info(&priv->udev->dev, "%02x: " + "%02x %02x %02x %02x %02x %02x %02x %02x\n", i, + raw[i], raw[i + 1], raw[i + 2], + raw[i + 3], raw[i + 4], raw[i + 5], + raw[i + 6], raw[i + 7]); + } + } + return 0; +} + +static int +rtl8xxxu_read_efuse8(struct rtl8xxxu_priv *priv, u16 offset, u8 *data) +{ + int i; + u8 val8; + u32 val32; + + /* Write Address */ + rtl8xxxu_write8(priv, REG_EFUSE_CTRL + 1, offset & 0xff); + val8 = rtl8xxxu_read8(priv, REG_EFUSE_CTRL + 2); + val8 &= 0xfc; + val8 |= (offset >> 8) & 0x03; + rtl8xxxu_write8(priv, REG_EFUSE_CTRL + 2, val8); + + val8 = rtl8xxxu_read8(priv, REG_EFUSE_CTRL + 3); + rtl8xxxu_write8(priv, REG_EFUSE_CTRL + 3, val8 & 0x7f); + + /* Poll for data read */ + val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL); + for (i = 0; i < RTL8XXXU_MAX_REG_POLL; i++) { + val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL); + if (val32 & BIT(31)) + break; + } + + if (i == RTL8XXXU_MAX_REG_POLL) + return -EIO; + + udelay(50); + val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL); + + *data = val32 & 0xff; + return 0; +} + +static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + int i, ret = 0; + u8 val8, word_mask, header, extheader; + u16 val16, efuse_addr, offset; + u32 val32; + + val16 = rtl8xxxu_read16(priv, REG_9346CR); + if (val16 & EEPROM_ENABLE) + priv->has_eeprom = 1; + if (val16 & EEPROM_BOOT) + priv->boot_eeprom = 1; + + val32 = rtl8xxxu_read32(priv, REG_EFUSE_TEST); + val32 = (val32 & ~EFUSE_SELECT_MASK) | EFUSE_WIFI_SELECT; + rtl8xxxu_write32(priv, REG_EFUSE_TEST, val32); + + dev_dbg(dev, "Booting from %s\n", + priv->boot_eeprom ? "EEPROM" : "EFUSE"); + + rtl8xxxu_write8(priv, REG_EFUSE_ACCESS, EFUSE_ACCESS_ENABLE); + + /* 1.2V Power: From VDDON with Power Cut(0x0000[15]), default valid */ + val16 = rtl8xxxu_read16(priv, REG_SYS_ISO_CTRL); + if (!(val16 & SYS_ISO_PWC_EV12V)) { + val16 |= SYS_ISO_PWC_EV12V; + rtl8xxxu_write16(priv, REG_SYS_ISO_CTRL, val16); + } + /* Reset: 0x0000[28], default valid */ + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + if (!(val16 & SYS_FUNC_ELDR)) { + val16 |= SYS_FUNC_ELDR; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + } + + /* + * Clock: Gated(0x0008[5]) 8M(0x0008[1]) clock from ANA, default valid + */ + val16 = rtl8xxxu_read16(priv, REG_SYS_CLKR); + if (!(val16 & SYS_CLK_LOADER_ENABLE) || !(val16 & SYS_CLK_ANA8M)) { + val16 |= (SYS_CLK_LOADER_ENABLE | SYS_CLK_ANA8M); + rtl8xxxu_write16(priv, REG_SYS_CLKR, val16); + } + + /* Default value is 0xff */ + memset(priv->efuse_wifi.raw, 0xff, EFUSE_MAP_LEN_8723A); + + efuse_addr = 0; + while (efuse_addr < EFUSE_REAL_CONTENT_LEN_8723A) { + ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &header); + if (ret || header == 0xff) + goto exit; + + if ((header & 0x1f) == 0x0f) { /* extended header */ + offset = (header & 0xe0) >> 5; + + ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, + &extheader); + if (ret) + goto exit; + /* All words disabled */ + if ((extheader & 0x0f) == 0x0f) + continue; + + offset |= ((extheader & 0xf0) >> 1); + word_mask = extheader & 0x0f; + } else { + offset = (header >> 4) & 0x0f; + word_mask = header & 0x0f; + } + + if (offset < EFUSE_MAX_SECTION_8723A) { + u16 map_addr; + /* Get word enable value from PG header */ + + /* We have 8 bits to indicate validity */ + map_addr = offset * 8; + if (map_addr >= EFUSE_MAP_LEN_8723A) { + dev_warn(dev, "%s: Illegal map_addr (%04x), " + "efuse corrupt!\n", + __func__, map_addr); + ret = -EINVAL; + goto exit; + } + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { + /* Check word enable condition in the section */ + if (!(word_mask & BIT(i))) { + ret = rtl8xxxu_read_efuse8(priv, + efuse_addr++, + &val8); + if (ret) + goto exit; + priv->efuse_wifi.raw[map_addr++] = val8; + + ret = rtl8xxxu_read_efuse8(priv, + efuse_addr++, + &val8); + if (ret) + goto exit; + priv->efuse_wifi.raw[map_addr++] = val8; + } else + map_addr += 2; + } + } else { + dev_warn(dev, + "%s: Illegal offset (%04x), efuse corrupt!\n", + __func__, offset); + ret = -EINVAL; + goto exit; + } + } + +exit: + rtl8xxxu_write8(priv, REG_EFUSE_ACCESS, EFUSE_ACCESS_DISABLE); + + return ret; +} + +static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + int ret = 0, i; + u32 val32; + + /* Poll checksum report */ + for (i = 0; i < RTL8XXXU_FIRMWARE_POLL_MAX; i++) { + val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL); + if (val32 & MCU_FW_DL_CSUM_REPORT) + break; + } + + if (i == RTL8XXXU_FIRMWARE_POLL_MAX) { + dev_warn(dev, "Firmware checksum poll timed out\n"); + ret = -EAGAIN; + goto exit; + } + + val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL); + val32 |= MCU_FW_DL_READY; + val32 &= ~MCU_WINT_INIT_READY; + rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32); + + /* Wait for firmware to become ready */ + for (i = 0; i < RTL8XXXU_FIRMWARE_POLL_MAX; i++) { + val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL); + if (val32 & MCU_WINT_INIT_READY) + break; + + udelay(100); + } + + if (i == RTL8XXXU_FIRMWARE_POLL_MAX) { + dev_warn(dev, "Firmware failed to start\n"); + ret = -EAGAIN; + goto exit; + } + +exit: + return ret; +} + +static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) +{ + int pages, remainder, i, ret; + u8 val8; + u16 val16; + u32 val32; + u8 *fwptr; + + val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC + 1); + val8 |= 4; + rtl8xxxu_write8(priv, REG_SYS_FUNC + 1, val8); + + /* 8051 enable */ + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16 | SYS_FUNC_CPU_ENABLE); + + /* MCU firmware download enable */ + val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL); + rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8 | MCU_FW_DL_ENABLE); + + /* 8051 reset */ + val32 = rtl8xxxu_read32(priv, REG_MCU_FW_DL); + rtl8xxxu_write32(priv, REG_MCU_FW_DL, val32 & ~BIT(19)); + + /* Reset firmware download checksum */ + val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL); + rtl8xxxu_write8(priv, REG_MCU_FW_DL, val8 | MCU_FW_DL_CSUM_REPORT); + + pages = priv->fw_size / RTL_FW_PAGE_SIZE; + remainder = priv->fw_size % RTL_FW_PAGE_SIZE; + + fwptr = priv->fw_data->data; + + for (i = 0; i < pages; i++) { + val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8; + rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8 | i); + + ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS, + fwptr, RTL_FW_PAGE_SIZE); + if (ret != RTL_FW_PAGE_SIZE) { + ret = -EAGAIN; + goto fw_abort; + } + + fwptr += RTL_FW_PAGE_SIZE; + } + + if (remainder) { + val8 = rtl8xxxu_read8(priv, REG_MCU_FW_DL + 2) & 0xF8; + rtl8xxxu_write8(priv, REG_MCU_FW_DL + 2, val8 | i); + ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS, + fwptr, remainder); + if (ret != remainder) { + ret = -EAGAIN; + goto fw_abort; + } + } + + ret = 0; +fw_abort: + /* MCU firmware download disable */ + val16 = rtl8xxxu_read16(priv, REG_MCU_FW_DL); + rtl8xxxu_write16(priv, REG_MCU_FW_DL, + val16 & (~MCU_FW_DL_ENABLE & 0xff)); + + return ret; +} + +static int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, char *fw_name) +{ + struct device *dev = &priv->udev->dev; + const struct firmware *fw; + int ret = 0; + u16 signature; + + dev_info(dev, "%s: Loading firmware %s\n", DRIVER_NAME, fw_name); + if (request_firmware(&fw, fw_name, &priv->udev->dev)) { + dev_warn(dev, "request_firmware(%s) failed\n", fw_name); + ret = -EAGAIN; + goto exit; + } + if (!fw) { + dev_warn(dev, "Firmware data not available\n"); + ret = -EINVAL; + goto exit; + } + + priv->fw_data = kmemdup(fw->data, fw->size, GFP_KERNEL); + priv->fw_size = fw->size - sizeof(struct rtl8xxxu_firmware_header); + + signature = le16_to_cpu(priv->fw_data->signature); + switch (signature & 0xfff0) { + case 0x92c0: + case 0x88c0: + case 0x2300: + break; + default: + ret = -EINVAL; + dev_warn(dev, "%s: Invalid firmware signature: 0x%04x\n", + __func__, signature); + } + + dev_info(dev, "Firmware revision %i.%i (signature 0x%04x)\n", + le16_to_cpu(priv->fw_data->major_version), + priv->fw_data->minor_version, signature); + +exit: + release_firmware(fw); + return ret; +} + +static int rtl8723au_load_firmware(struct rtl8xxxu_priv *priv) +{ + char *fw_name; + int ret; + + switch (priv->chip_cut) { + case 0: + fw_name = "rtlwifi/rtl8723aufw_A.bin"; + break; + case 1: + if (priv->enable_bluetooth) + fw_name = "rtlwifi/rtl8723aufw_B.bin"; + else + fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin"; + + break; + default: + return -EINVAL; + } + + ret = rtl8xxxu_load_firmware(priv, fw_name); + return ret; +} + +static int rtl8192cu_load_firmware(struct rtl8xxxu_priv *priv) +{ + char *fw_name; + int ret; + + if (!priv->vendor_umc) + fw_name = "rtlwifi/rtl8192cufw_TMSC.bin"; + else if (priv->chip_cut || priv->rtlchip == 0x8192c) + fw_name = "rtlwifi/rtl8192cufw_B.bin"; + else + fw_name = "rtlwifi/rtl8192cufw_A.bin"; + + ret = rtl8xxxu_load_firmware(priv, fw_name); + + return ret; +} + +static void rtl8xxxu_firmware_self_reset(struct rtl8xxxu_priv *priv) +{ + u16 val16; + int i = 100; + + /* Inform 8051 to perform reset */ + rtl8xxxu_write8(priv, REG_HMTFR + 3, 0x20); + + for (i = 100; i > 0; i--) { + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + + if (!(val16 & SYS_FUNC_CPU_ENABLE)) { + dev_dbg(&priv->udev->dev, + "%s: Firmware self reset success!\n", __func__); + break; + } + udelay(50); + } + + if (!i) { + /* Force firmware reset */ + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 &= ~SYS_FUNC_CPU_ENABLE; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + } +} + +static int +rtl8xxxu_init_mac(struct rtl8xxxu_priv *priv, struct rtl8xxxu_reg8val *array) +{ + int i, ret; + u16 reg; + u8 val; + + for (i = 0; ; i++) { + reg = array[i].reg; + val = array[i].val; + + if (reg == 0xffff && val == 0xff) + break; + + ret = rtl8xxxu_write8(priv, reg, val); + if (ret != 1) { + dev_warn(&priv->udev->dev, + "Failed to initialize MAC\n"); + return -EAGAIN; + } + } + + rtl8xxxu_write8(priv, REG_MAX_AGGR_NUM, 0x0a); + + return 0; +} + +static int rtl8xxxu_init_phy_regs(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_reg32val *array) +{ + int i, ret; + u16 reg; + u32 val; + + for (i = 0; ; i++) { + reg = array[i].reg; + val = array[i].val; + + if (reg == 0xffff && val == 0xffffffff) + break; + + ret = rtl8xxxu_write32(priv, reg, val); + if (ret != sizeof(val)) { + dev_warn(&priv->udev->dev, + "Failed to initialize PHY\n"); + return -EAGAIN; + } + udelay(1); + } + + return 0; +} + +/* + * Most of this is black magic retrieved from the old rtl8723au driver + */ +static int rtl8xxxu_init_phy_bb(struct rtl8xxxu_priv *priv) +{ + u8 val8, ldoa15, ldov12d, lpldo, ldohci12; + u32 val32; + + /* + * Todo: The vendor driver maintains a table of PHY register + * addresses, which is initialized here. Do we need this? + */ + + val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL); + udelay(2); + val8 |= AFE_PLL_320_ENABLE; + rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8); + udelay(2); + + rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL + 1, 0xff); + udelay(2); + + val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC); + val8 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB; + rtl8xxxu_write8(priv, REG_SYS_FUNC, val8); + + /* AFE_XTAL_RF_GATE (bit 14) if addressing as 32 bit register */ + val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); + val32 &= ~AFE_XTAL_RF_GATE; + if (priv->has_bluetooth) + val32 &= ~AFE_XTAL_BT_GATE; + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32); + + /* 6. 0x1f[7:0] = 0x07 */ + val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB; + rtl8xxxu_write8(priv, REG_RF_CTRL, val8); + + if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, rtl8188ru_phy_1t_highpa_table); + else if (priv->tx_paths == 2) + rtl8xxxu_init_phy_regs(priv, rtl8192cu_phy_2t_init_table); + else + rtl8xxxu_init_phy_regs(priv, rtl8723a_phy_1t_init_table); + + + if (priv->rtlchip == 0x8188c && priv->hi_pa && + priv->vendor_umc && priv->chip_cut == 1) + rtl8xxxu_write8(priv, REG_OFDM0_AGC_PARM1 + 2, 0x50); + + if (priv->tx_paths == 1 && priv->rx_paths == 2) { + /* + * For 1T2R boards, patch the registers. + * + * It looks like 8191/2 1T2R boards use path B for TX + */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_TX_INFO); + val32 &= ~(BIT(0) | BIT(1)); + val32 |= BIT(1); + rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA1_TX_INFO); + val32 &= ~0x300033; + val32 |= 0x200022; + rtl8xxxu_write32(priv, REG_FPGA1_TX_INFO, val32); + + val32 = rtl8xxxu_read32(priv, REG_CCK0_AFE_SETTING); + val32 &= 0xff000000; + val32 |= 0x45000000; + rtl8xxxu_write32(priv, REG_CCK0_AFE_SETTING, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); + val32 &= ~(OFDM_RF_PATH_RX_MASK | OFDM_RF_PATH_TX_MASK); + val32 |= (OFDM_RF_PATH_RX_A | OFDM_RF_PATH_RX_B | + OFDM_RF_PATH_TX_B); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGC_PARM1); + val32 &= ~(BIT(4) | BIT(5)); + val32 |= BIT(4); + rtl8xxxu_write32(priv, REG_OFDM0_AGC_PARM1, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_CCK_RFON); + val32 &= ~(BIT(27) | BIT(26)); + val32 |= BIT(27); + rtl8xxxu_write32(priv, REG_TX_CCK_RFON, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_CCK_BBON); + val32 &= ~(BIT(27) | BIT(26)); + val32 |= BIT(27); + rtl8xxxu_write32(priv, REG_TX_CCK_BBON, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_OFDM_RFON); + val32 &= ~(BIT(27) | BIT(26)); + val32 |= BIT(27); + rtl8xxxu_write32(priv, REG_TX_OFDM_RFON, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_OFDM_BBON); + val32 &= ~(BIT(27) | BIT(26)); + val32 |= BIT(27); + rtl8xxxu_write32(priv, REG_TX_OFDM_BBON, val32); + + val32 = rtl8xxxu_read32(priv, REG_TX_TO_TX); + val32 &= ~(BIT(27) | BIT(26)); + val32 |= BIT(27); + rtl8xxxu_write32(priv, REG_TX_TO_TX, val32); + } + + if (priv->hi_pa) + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_highpa_table); + else + rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_standard_table); + + if (priv->rtlchip == 0x8723a && + priv->efuse_wifi.efuse8723.version >= 0x01) { + val32 = rtl8xxxu_read32(priv, REG_MAC_PHY_CTRL); + + val8 = priv->efuse_wifi.efuse8723.xtal_k & 0x3f; + val32 &= 0xff000fff; + val32 |= ((val8 | (val8 << 6)) << 12); + + rtl8xxxu_write32(priv, REG_MAC_PHY_CTRL, val32); + } + + ldoa15 = LDOA15_ENABLE | LDOA15_OBUF; + ldov12d = LDOV12D_ENABLE | BIT(2) | (2 << LDOV12D_VADJ_SHIFT); + ldohci12 = 0x57; + lpldo = 1; + val32 = (lpldo << 24) | (ldohci12 << 16) | (ldov12d << 8) | ldoa15; + + rtl8xxxu_write32(priv, REG_LDOA15_CTRL, val32); + + return 0; +} + +static int rtl8xxxu_init_rf_regs(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_rfregval *array, + enum rtl8xxxu_rfpath path) +{ + int i, ret; + u8 reg; + u32 val; + + for (i = 0; ; i++) { + reg = array[i].reg; + val = array[i].val; + + if (reg == 0xff && val == 0xffffffff) + break; + + switch (reg) { + case 0xfe: + msleep(50); + continue; + case 0xfd: + mdelay(5); + continue; + case 0xfc: + mdelay(1); + continue; + case 0xfb: + udelay(50); + continue; + case 0xfa: + udelay(5); + continue; + case 0xf9: + udelay(1); + continue; + } + + reg &= 0x3f; + + ret = rtl8xxxu_write_rfreg(priv, path, reg, val); + if (ret) { + dev_warn(&priv->udev->dev, + "Failed to initialize RF\n"); + return -EAGAIN; + } + udelay(1); + } + + return 0; +} + +static int rtl8xxxu_init_phy_rf(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_rfregval *table, + enum rtl8xxxu_rfpath path) +{ + u32 val32; + u16 val16, rfsi_rfenv; + u16 reg_sw_ctrl, reg_int_oe, reg_hssi_parm2; + + switch (path) { + case RF_A: + reg_sw_ctrl = REG_FPGA0_XA_RF_SW_CTRL; + reg_int_oe = REG_FPGA0_XA_RF_INT_OE; + reg_hssi_parm2 = REG_FPGA0_XA_HSSI_PARM2; + break; + case RF_B: + reg_sw_ctrl = REG_FPGA0_XB_RF_SW_CTRL; + reg_int_oe = REG_FPGA0_XB_RF_INT_OE; + reg_hssi_parm2 = REG_FPGA0_XB_HSSI_PARM2; + break; + default: + dev_err(&priv->udev->dev, "%s:Unsupported RF path %c\n", + __func__, path + 'A'); + return -EINVAL; + } + /* For path B, use XB */ + rfsi_rfenv = rtl8xxxu_read16(priv, reg_sw_ctrl); + rfsi_rfenv &= FPGA0_RF_RFENV; + + /* + * These two we might be able to optimize into one + */ + val32 = rtl8xxxu_read32(priv, reg_int_oe); + val32 |= BIT(20); /* 0x10 << 16 */ + rtl8xxxu_write32(priv, reg_int_oe, val32); + udelay(1); + + val32 = rtl8xxxu_read32(priv, reg_int_oe); + val32 |= BIT(4); + rtl8xxxu_write32(priv, reg_int_oe, val32); + udelay(1); + + /* + * These two we might be able to optimize into one + */ + val32 = rtl8xxxu_read32(priv, reg_hssi_parm2); + val32 &= ~FPGA0_HSSI_3WIRE_ADDR_LEN; + rtl8xxxu_write32(priv, reg_hssi_parm2, val32); + udelay(1); + + val32 = rtl8xxxu_read32(priv, reg_hssi_parm2); + val32 &= ~FPGA0_HSSI_3WIRE_DATA_LEN; + rtl8xxxu_write32(priv, reg_hssi_parm2, val32); + udelay(1); + + rtl8xxxu_init_rf_regs(priv, table, path); + + /* For path B, use XB */ + val16 = rtl8xxxu_read16(priv, reg_sw_ctrl); + val16 &= ~FPGA0_RF_RFENV; + val16 |= rfsi_rfenv; + rtl8xxxu_write16(priv, reg_sw_ctrl, val16); + + return 0; +} + +static int rtl8xxxu_llt_write(struct rtl8xxxu_priv *priv, u8 address, u8 data) +{ + int ret = -EBUSY; + int count = 0; + u32 value; + + value = LLT_OP_WRITE | address << 8 | data; + + rtl8xxxu_write32(priv, REG_LLT_INIT, value); + + do { + value = rtl8xxxu_read32(priv, REG_LLT_INIT); + if ((value & LLT_OP_MASK) == LLT_OP_INACTIVE) { + ret = 0; + break; + } + } while (count++ < 20); + + return ret; +} + +static int rtl8xxxu_init_llt_table(struct rtl8xxxu_priv *priv, u8 last_tx_page) +{ + int ret; + int i; + + for (i = 0; i < last_tx_page; i++) { + ret = rtl8xxxu_llt_write(priv, i, i + 1); + if (ret) + goto exit; + } + + ret = rtl8xxxu_llt_write(priv, last_tx_page, 0xff); + if (ret) + goto exit; + + /* Mark remaining pages as a ring buffer */ + for (i = last_tx_page + 1; i < 0xff; i++) { + ret = rtl8xxxu_llt_write(priv, i, (i + 1)); + if (ret) + goto exit; + } + + /* Let last entry point to the start entry of ring buffer */ + ret = rtl8xxxu_llt_write(priv, 0xff, last_tx_page + 1); + if (ret) + goto exit; + +exit: + return ret; +} + +static int rtl8xxxu_init_queue_priority(struct rtl8xxxu_priv *priv) +{ + u16 val16, hi, lo; + u16 hiq, mgq, bkq, beq, viq, voq; + int hip, mgp, bkp, bep, vip, vop; + int ret = 0; + + switch (priv->ep_tx_count) { + case 1: + if (priv->ep_tx_high_queue) { + hi = TRXDMA_QUEUE_HIGH; + } else if (priv->ep_tx_low_queue) { + hi = TRXDMA_QUEUE_LOW; + } else if (priv->ep_tx_normal_queue) { + hi = TRXDMA_QUEUE_NORMAL; + } else { + hi = 0; + ret = -EINVAL; + } + + hiq = hi; + mgq = hi; + bkq = hi; + beq = hi; + viq = hi; + voq = hi; + + hip = 0; + mgp = 0; + bkp = 0; + bep = 0; + vip = 0; + vop = 0; + break; + case 2: + if (priv->ep_tx_high_queue && priv->ep_tx_low_queue) { + hi = TRXDMA_QUEUE_HIGH; + lo = TRXDMA_QUEUE_LOW; + } else if (priv->ep_tx_normal_queue && priv->ep_tx_low_queue) { + hi = TRXDMA_QUEUE_NORMAL; + lo = TRXDMA_QUEUE_LOW; + } else if (priv->ep_tx_high_queue && priv->ep_tx_normal_queue) { + hi = TRXDMA_QUEUE_HIGH; + lo = TRXDMA_QUEUE_NORMAL; + } else { + ret = -EINVAL; + hi = 0; + lo = 0; + } + + hiq = hi; + mgq = hi; + bkq = lo; + beq = lo; + viq = hi; + voq = hi; + + hip = 0; + mgp = 0; + bkp = 1; + bep = 1; + vip = 0; + vop = 0; + break; + case 3: + beq = TRXDMA_QUEUE_LOW; + bkq = TRXDMA_QUEUE_LOW; + viq = TRXDMA_QUEUE_NORMAL; + voq = TRXDMA_QUEUE_HIGH; + mgq = TRXDMA_QUEUE_HIGH; + hiq = TRXDMA_QUEUE_HIGH; + + hip = hiq ^ 3; + mgp = mgq ^ 3; + bkp = bkq ^ 3; + bep = beq ^ 3; + vip = viq ^ 3; + vop = viq ^ 3; + break; + default: + ret = -EINVAL; + } + + /* + * None of the vendor drivers are configuring the beacon + * queue here .... why? + */ + if (!ret) { + val16 = rtl8xxxu_read16(priv, REG_TRXDMA_CTRL); + val16 &= 0x7; + val16 |= (voq << TRXDMA_CTRL_VOQ_SHIFT) | + (viq << TRXDMA_CTRL_VIQ_SHIFT) | + (beq << TRXDMA_CTRL_BEQ_SHIFT) | + (bkq << TRXDMA_CTRL_BKQ_SHIFT) | + (mgq << TRXDMA_CTRL_MGQ_SHIFT) | + (hiq << TRXDMA_CTRL_HIQ_SHIFT); + rtl8xxxu_write16(priv, REG_TRXDMA_CTRL, val16); + + priv->pipe_out[TXDESC_QUEUE_VO] = + usb_sndbulkpipe(priv->udev, priv->out_ep[vop]); + priv->pipe_out[TXDESC_QUEUE_VI] = + usb_sndbulkpipe(priv->udev, priv->out_ep[vip]); + priv->pipe_out[TXDESC_QUEUE_BE] = + usb_sndbulkpipe(priv->udev, priv->out_ep[bep]); + priv->pipe_out[TXDESC_QUEUE_BK] = + usb_sndbulkpipe(priv->udev, priv->out_ep[bkp]); + priv->pipe_out[TXDESC_QUEUE_BEACON] = + usb_sndbulkpipe(priv->udev, priv->out_ep[0]); + priv->pipe_out[TXDESC_QUEUE_MGNT] = + usb_sndbulkpipe(priv->udev, priv->out_ep[mgp]); + priv->pipe_out[TXDESC_QUEUE_HIGH] = + usb_sndbulkpipe(priv->udev, priv->out_ep[hip]); + priv->pipe_out[TXDESC_QUEUE_CMD] = + usb_sndbulkpipe(priv->udev, priv->out_ep[0]); + } + + return ret; +} + +static void rtl8xxxu_fill_iqk_matrix_a(struct rtl8xxxu_priv *priv, + bool iqk_ok, int result[][8], + int candidate, bool tx_only) +{ + u32 oldval, x, tx0_a, reg; + int y, tx0_c; + u32 val32; + + if (!iqk_ok) + return; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE); + oldval = val32 >> 22; + + x = result[candidate][0]; + if ((x & 0x00000200) != 0) + x = x | 0xfffffc00; + tx0_a = (x * oldval) >> 8; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE); + val32 &= ~0x3ff; + val32 |= tx0_a; + rtl8xxxu_write32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES); + val32 &= ~BIT(31); + if ((x * oldval >> 7) & 0x1) + val32 |= BIT(31); + rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val32); + + y = result[candidate][1]; + if ((y & 0x00000200) != 0) + y = y | 0xfffffc00; + tx0_c = (y * oldval) >> 8; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XC_TX_AFE); + val32 &= ~0xf0000000; + val32 |= (((tx0_c & 0x3c0) >> 6) << 28); + rtl8xxxu_write32(priv, REG_OFDM0_XC_TX_AFE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE); + val32 &= ~0x003f0000; + val32 |= ((tx0_c & 0x3f) << 16); + rtl8xxxu_write32(priv, REG_OFDM0_XA_TX_IQ_IMBALANCE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES); + val32 &= ~BIT(29); + if ((y * oldval >> 7) & 0x1) + val32 |= BIT(29); + rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val32); + + if (tx_only) { + dev_dbg(&priv->udev->dev, "%s: only TX\n", __func__); + return; + } + + reg = result[candidate][2]; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE); + val32 &= ~0x3ff; + val32 |= (reg & 0x3ff); + rtl8xxxu_write32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE, val32); + + reg = result[candidate][3] & 0x3F; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE); + val32 &= ~0xfc00; + val32 |= ((reg << 10) & 0xfc00); + rtl8xxxu_write32(priv, REG_OFDM0_XA_RX_IQ_IMBALANCE, val32); + + reg = (result[candidate][3] >> 6) & 0xF; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_RX_IQ_EXT_ANTA); + val32 &= ~0xf0000000; + val32 |= (reg << 28); + rtl8xxxu_write32(priv, REG_OFDM0_RX_IQ_EXT_ANTA, val32); +} + +static void rtl8xxxu_fill_iqk_matrix_b(struct rtl8xxxu_priv *priv, + bool iqk_ok, int result[][8], + int candidate, bool tx_only) +{ + u32 oldval, x, tx1_a, reg; + int y, tx1_c; + u32 val32; + + if (!iqk_ok) + return; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE); + oldval = val32 >> 22; + + x = result[candidate][4]; + if ((x & 0x00000200) != 0) + x = x | 0xfffffc00; + tx1_a = (x * oldval) >> 8; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE); + val32 &= ~0x3ff; + val32 |= tx1_a; + rtl8xxxu_write32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES); + val32 &= ~BIT(27); + if ((x * oldval >> 7) & 0x1) + val32 |= BIT(27); + rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val32); + + y = result[candidate][5]; + if ((y & 0x00000200) != 0) + y = y | 0xfffffc00; + tx1_c = (y * oldval) >> 8; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XD_TX_AFE); + val32 &= ~0xf0000000; + val32 |= (((tx1_c & 0x3c0) >> 6) << 28); + rtl8xxxu_write32(priv, REG_OFDM0_XD_TX_AFE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE); + val32 &= ~0x003f0000; + val32 |= ((tx1_c & 0x3f) << 16); + rtl8xxxu_write32(priv, REG_OFDM0_XB_TX_IQ_IMBALANCE, val32); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_ENERGY_CCA_THRES); + val32 &= ~BIT(25); + if ((y * oldval >> 7) & 0x1) + val32 |= BIT(25); + rtl8xxxu_write32(priv, REG_OFDM0_ENERGY_CCA_THRES, val32); + + if (tx_only) { + dev_dbg(&priv->udev->dev, "%s: only TX\n", __func__); + return; + } + + reg = result[candidate][6]; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE); + val32 &= ~0x3ff; + val32 |= (reg & 0x3ff); + rtl8xxxu_write32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE, val32); + + reg = result[candidate][7] & 0x3f; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE); + val32 &= ~0xfc00; + val32 |= ((reg << 10) & 0xfc00); + rtl8xxxu_write32(priv, REG_OFDM0_XB_RX_IQ_IMBALANCE, val32); + + reg = (result[candidate][7] >> 6) & 0xf; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGCR_SSI_TABLE); + val32 &= ~0x0000f000; + val32 |= (reg << 12); + rtl8xxxu_write32(priv, REG_OFDM0_AGCR_SSI_TABLE, val32); +} + +#define MAX_TOLERANCE 5 + +static bool rtl8xxxu_simularity_compare(struct rtl8xxxu_priv *priv, + int result[][8], int c1, int c2) +{ + u32 i, j, diff, simubitmap, bound = 0; + int candidate[2] = {-1, -1}; /* for path A and path B */ + bool retval = true; + + if (priv->tx_paths > 1) + bound = 8; + else + bound = 4; + + simubitmap = 0; + + for (i = 0; i < bound; i++) { + diff = (result[c1][i] > result[c2][i]) ? + (result[c1][i] - result[c2][i]) : + (result[c2][i] - result[c1][i]); + if (diff > MAX_TOLERANCE) { + if ((i == 2 || i == 6) && !simubitmap) { + if (result[c1][i] + result[c1][i + 1] == 0) + candidate[(i / 4)] = c2; + else if (result[c2][i] + result[c2][i + 1] == 0) + candidate[(i / 4)] = c1; + else + simubitmap = simubitmap | (1 << i); + } else { + simubitmap = simubitmap | (1 << i); + } + } + } + + if (simubitmap == 0) { + for (i = 0; i < (bound / 4); i++) { + if (candidate[i] >= 0) { + for (j = i * 4; j < (i + 1) * 4 - 2; j++) + result[3][j] = result[candidate[i]][j]; + retval = false; + } + } + return retval; + } else if (!(simubitmap & 0x0f)) { + /* path A OK */ + for (i = 0; i < 4; i++) + result[3][i] = result[c1][i]; + } else if (!(simubitmap & 0xf0) && priv->tx_paths > 1) { + /* path B OK */ + for (i = 4; i < 8; i++) + result[3][i] = result[c1][i]; + } + + return false; +} + +static void +rtl8xxxu_save_mac_regs(struct rtl8xxxu_priv *priv, const u32 *reg, u32 *backup) +{ + int i; + + for (i = 0; i < (RTL8XXXU_MAC_REGS - 1); i++) + backup[i] = rtl8xxxu_read8(priv, reg[i]); + + backup[i] = rtl8xxxu_read32(priv, reg[i]); +} + +static void rtl8xxxu_restore_mac_regs(struct rtl8xxxu_priv *priv, + const u32 *reg, u32 *backup) +{ + int i; + + for (i = 0; i < (RTL8XXXU_MAC_REGS - 1); i++) + rtl8xxxu_write8(priv, reg[i], backup[i]); + + rtl8xxxu_write32(priv, reg[i], backup[i]); +} + +static void rtl8xxxu_save_regs(struct rtl8xxxu_priv *priv, const u32 *regs, + u32 *backup, int count) +{ + int i; + + for (i = 0; i < count; i++) + backup[i] = rtl8xxxu_read32(priv, regs[i]); +} + +static void rtl8xxxu_restore_regs(struct rtl8xxxu_priv *priv, const u32 *regs, + u32 *backup, int count) +{ + int i; + + for (i = 0; i < count; i++) + rtl8xxxu_write32(priv, regs[i], backup[i]); +} + + +static void rtl8xxxu_path_adda_on(struct rtl8xxxu_priv *priv, const u32 *regs, + bool path_a_on) +{ + u32 path_on; + int i; + + path_on = path_a_on ? 0x04db25a4 : 0x0b1b25a4; + if (priv->tx_paths == 1) { + path_on = 0x0bdb25a0; + rtl8xxxu_write32(priv, regs[0], 0x0b1b25a0); + } else { + rtl8xxxu_write32(priv, regs[0], path_on); + } + + for (i = 1 ; i < RTL8XXXU_ADDA_REGS ; i++) + rtl8xxxu_write32(priv, regs[i], path_on); +} + +static void rtl8xxxu_mac_calibration(struct rtl8xxxu_priv *priv, + const u32 *regs, u32 *backup) +{ + int i = 0; + + rtl8xxxu_write8(priv, regs[i], 0x3f); + + for (i = 1 ; i < (RTL8XXXU_MAC_REGS - 1); i++) + rtl8xxxu_write8(priv, regs[i], (u8)(backup[i] & ~BIT(3))); + + rtl8xxxu_write8(priv, regs[i], (u8)(backup[i] & ~BIT(5))); +} + +static int rtl8xxxu_iqk_path_a(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_e94, reg_e9c, reg_ea4, val32; + int result = 0; + + /* path-A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x10008c1f); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x10008c1f); + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82140102); + + val32 = (priv->rf_paths > 1) ? 0x28160202 : + /*IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)?0x28160202: */ + 0x28160502; + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, val32); + + /* path-B IQK setting */ + if (priv->rf_paths > 1) { + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x10008c22); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x10008c22); + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82140102); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28160202); + } + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x001028d1); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000); + + mdelay(1); + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); + reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); + reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); + + if (!(reg_eac & BIT(28)) && + ((reg_e94 & 0x03ff0000) != 0x01420000) && + ((reg_e9c & 0x03ff0000) != 0x00420000)) + result |= 0x01; + else /* If TX not OK, ignore RX */ + goto out; + + /* If TX is OK, check whether RX is OK */ + if (!(reg_eac & BIT(27)) && + ((reg_ea4 & 0x03ff0000) != 0x01320000) && + ((reg_eac & 0x03ff0000) != 0x00360000)) + result |= 0x02; + else + dev_warn(&priv->udev->dev, "%s: Path A RX IQK failed!\n", + __func__); +out: + return result; +} + +static int rtl8xxxu_iqk_path_b(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; + int result = 0; + + /* One shot, path B LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_CONT, 0x00000002); + rtl8xxxu_write32(priv, REG_IQK_AGC_CONT, 0x00000000); + + mdelay(1); + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); + reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); + + if (!(reg_eac & BIT(31)) && + ((reg_eb4 & 0x03ff0000) != 0x01420000) && + ((reg_ebc & 0x03ff0000) != 0x00420000)) + result |= 0x01; + else + goto out; + + if (!(reg_eac & BIT(30)) && + (((reg_ec4 & 0x03ff0000) >> 16) != 0x132) && + (((reg_ecc & 0x03ff0000) >> 16) != 0x36)) + result |= 0x02; + else + dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n", + __func__); +out: + return result; +} + +static void rtl8xxxu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, + int result[][8], int t) +{ + struct device *dev = &priv->udev->dev; + u32 i, val32; + int path_a_ok, path_b_ok; + int retry = 2; + const u32 adda_regs[RTL8XXXU_ADDA_REGS] = { + REG_FPGA0_XCD_SWITCH_CTRL, REG_BLUETOOTH, + REG_RX_WAIT_CCA, REG_TX_CCK_RFON, + REG_TX_CCK_BBON, REG_TX_OFDM_RFON, + REG_TX_OFDM_BBON, REG_TX_TO_RX, + REG_TX_TO_TX, REG_RX_CCK, + REG_RX_OFDM, REG_RX_WAIT_RIFS, + REG_RX_TO_RX, REG_STANDBY, + REG_SLEEP, REG_PMPD_ANAEN + }; + const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = { + REG_TXPAUSE, REG_BEACON_CTRL, + REG_BEACON_CTRL_1, REG_GPIO_MUXCFG + }; + const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = { + REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR, + REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B, + REG_FPGA0_XAB_RF_SW_CTRL, REG_FPGA0_XA_RF_INT_OE, + REG_FPGA0_XB_RF_INT_OE, REG_FPGA0_RF_MODE + }; + + /* + * Note: IQ calibration must be performed after loading + * PHY_REG.txt , and radio_a, radio_b.txt + */ + + if (t == 0) { + /* Save ADDA parameters, turn Path A ADDA on */ + rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup, + RTL8XXXU_ADDA_REGS); + rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup); + rtl8xxxu_save_regs(priv, iqk_bb_regs, + priv->bb_backup, RTL8XXXU_BB_REGS); + } + + rtl8xxxu_path_adda_on(priv, adda_regs, true); + + if (t == 0) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM1); + if (val32 & FPGA0_HSSI_PARM1_PI) + priv->pi_enabled = 1; + } + + if (!priv->pi_enabled) { + /* Switch BB to PI mode to do IQ Calibration. */ + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); + rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM1, 0x01000100); + } + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + val32 &= ~FPGA_RF_MODE_CCK; + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x03a05600); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000800e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x22204000); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_SW_CTRL); + val32 |= (FPGA0_RF_PAPE | (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT)); + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_RF_INT_OE); + val32 &= ~BIT(10); + rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, val32); + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_RF_INT_OE); + val32 &= ~BIT(10); + rtl8xxxu_write32(priv, REG_FPGA0_XB_RF_INT_OE, val32); + + if (priv->tx_paths > 1) { + rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, 0x00010000); + rtl8xxxu_write32(priv, REG_FPGA0_XB_LSSI_PARM, 0x00010000); + } + + /* MAC settings */ + rtl8xxxu_mac_calibration(priv, iqk_mac_regs, priv->mac_backup); + + /* Page B init */ + rtl8xxxu_write32(priv, REG_CONFIG_ANT_A, 0x00080000); + + if (priv->tx_paths > 1) + rtl8xxxu_write32(priv, REG_CONFIG_ANT_B, 0x00080000); + + /* IQ calibration setting */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + for (i = 0; i < retry; i++) { + path_a_ok = rtl8xxxu_iqk_path_a(priv); + if (path_a_ok == 0x03) { + val32 = rtl8xxxu_read32(priv, + REG_TX_POWER_BEFORE_IQK_A); + result[t][0] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_TX_POWER_AFTER_IQK_A); + result[t][1] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_RX_POWER_BEFORE_IQK_A_2); + result[t][2] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_RX_POWER_AFTER_IQK_A_2); + result[t][3] = (val32 >> 16) & 0x3ff; + break; + } else if (i == (retry - 1) && path_a_ok == 0x01) { + /* TX IQK OK */ + dev_dbg(dev, "%s: Path A IQK Only Tx Success!!\n", + __func__); + + val32 = rtl8xxxu_read32(priv, + REG_TX_POWER_BEFORE_IQK_A); + result[t][0] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, + REG_TX_POWER_AFTER_IQK_A); + result[t][1] = (val32 >> 16) & 0x3ff; + } + } + + if (!path_a_ok) + dev_dbg(dev, "%s: Path A IQK failed!\n", __func__); + + if (priv->tx_paths > 1) { + /* + * Path A into standby + */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x0); + rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, 0x00010000); + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); + + /* Turn Path B ADDA on */ + rtl8xxxu_path_adda_on(priv, adda_regs, false); + + for (i = 0; i < retry; i++) { + path_b_ok = rtl8xxxu_iqk_path_b(priv); + if (path_b_ok == 0x03) { + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + result[t][4] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + result[t][5] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); + result[t][6] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); + result[t][7] = (val32 >> 16) & 0x3ff; + break; + } else if (i == (retry - 1) && path_b_ok == 0x01) { + /* TX IQK OK */ + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + result[t][4] = (val32 >> 16) & 0x3ff; + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + result[t][5] = (val32 >> 16) & 0x3ff; + } + } + + if (!path_b_ok) + dev_dbg(dev, "%s: Path B IQK failed!\n", __func__); + } + + /* Back to BB mode, load original value */ + rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0); + + if (t) { + if (!priv->pi_enabled) { + /* + * Switch back BB to SI mode after finishing + * IQ Calibration + */ + val32 = 0x01000000; + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, val32); + rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM1, val32); + } + + /* Reload ADDA power saving parameters */ + rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup, + RTL8XXXU_ADDA_REGS); + + /* Reload MAC parameters */ + rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup); + + /* Reload BB parameters */ + rtl8xxxu_restore_regs(priv, iqk_bb_regs, + priv->bb_backup, RTL8XXXU_BB_REGS); + + /* Restore RX initial gain */ + rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, 0x00032ed3); + + if (priv->tx_paths > 1) { + rtl8xxxu_write32(priv, REG_FPGA0_XB_LSSI_PARM, + 0x00032ed3); + } + + /* Load 0xe30 IQC default value */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x01008c00); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x01008c00); + } +} + +static void rtl8723a_phy_iq_calibrate(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + int result[4][8]; /* last is final result */ + int i, candidate; + bool path_a_ok, path_b_ok; + u32 reg_e94, reg_e9c, reg_ea4, reg_eac; + u32 reg_eb4, reg_ebc, reg_ec4, reg_ecc; + s32 reg_tmp = 0; + bool simu; + + memset(result, 0, sizeof(result)); + candidate = -1; + + path_a_ok = false; + path_b_ok = false; + + rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + + for (i = 0; i < 3; i++) { + rtl8xxxu_phy_iqcalibrate(priv, result, i); + + if (i == 1) { + simu = rtl8xxxu_simularity_compare(priv, result, 0, 1); + if (simu) { + candidate = 0; + break; + } + } + + if (i == 2) { + simu = rtl8xxxu_simularity_compare(priv, result, 0, 2); + if (simu) { + candidate = 0; + break; + } + + simu = rtl8xxxu_simularity_compare(priv, result, 1, 2); + if (simu) { + candidate = 1; + } else { + for (i = 0; i < 8; i++) + reg_tmp += result[3][i]; + + if (reg_tmp) + candidate = 3; + else + candidate = -1; + } + } + } + + for (i = 0; i < 4; i++) { + reg_e94 = result[i][0]; + reg_e9c = result[i][1]; + reg_ea4 = result[i][2]; + reg_eac = result[i][3]; + reg_eb4 = result[i][4]; + reg_ebc = result[i][5]; + reg_ec4 = result[i][6]; + reg_ecc = result[i][7]; + } + + if (candidate >= 0) { + reg_e94 = result[candidate][0]; + priv->rege94 = reg_e94; + reg_e9c = result[candidate][1]; + priv->rege9c = reg_e9c; + reg_ea4 = result[candidate][2]; + reg_eac = result[candidate][3]; + reg_eb4 = result[candidate][4]; + priv->regeb4 = reg_eb4; + reg_ebc = result[candidate][5]; + priv->regebc = reg_ebc; + reg_ec4 = result[candidate][6]; + reg_ecc = result[candidate][7]; + dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate); + dev_dbg(dev, + "%s: e94 =%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x " + "ecc=%x\n ", __func__, reg_e94, reg_e9c, + reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc); + path_a_ok = true; + path_b_ok = true; + } else { + reg_e94 = reg_eb4 = priv->rege94 = priv->regeb4 = 0x100; + reg_e9c = reg_ebc = priv->rege9c = priv->regebc = 0x0; + } + + if (reg_e94 && candidate >= 0) + rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result, + candidate, (reg_ea4 == 0)); + + if (priv->tx_paths > 1 && reg_eb4) + rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, + candidate, (reg_ec4 == 0)); + + rtl8xxxu_save_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, + priv->bb_recovery_backup, RTL8XXXU_BB_REGS); +} + +static void rtl8723a_phy_lc_calibrate(struct rtl8xxxu_priv *priv) +{ + u32 val32; + u32 rf_amode, rf_bmode = 0, lstf; + + /* Check continuous TX and Packet TX */ + lstf = rtl8xxxu_read32(priv, REG_OFDM1_LSTF); + + if (lstf & OFDM_LSTF_MASK) { + /* Disable all continuous TX */ + val32 = lstf & ~OFDM_LSTF_MASK; + rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val32); + + /* Read original RF mode Path A */ + rf_amode = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_AC); + + /* Set RF mode to standby Path A */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, + (rf_amode & 0x8ffff) | 0x10000); + + /* Path-B */ + if (priv->tx_paths > 1) { + rf_bmode = rtl8xxxu_read_rfreg(priv, RF_B, + RF6052_REG_AC); + + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, + (rf_bmode & 0x8ffff) | 0x10000); + } + } else { + /* Deal with Packet TX case */ + /* block all queues */ + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + } + + /* Start LC calibration */ + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG); + val32 |= 0x08000; + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32); + + msleep(100); + + /* Restore original parameters */ + if (lstf & OFDM_LSTF_MASK) { + /* Path-A */ + rtl8xxxu_write32(priv, REG_OFDM1_LSTF, lstf); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, rf_amode); + + /* Path-B */ + if (priv->tx_paths > 1) + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, + rf_bmode); + } else /* Deal with Packet TX case */ + rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00); +} + +static int rtl8xxxu_set_mac(struct rtl8xxxu_priv *priv) +{ + int i; + u16 reg; + + reg = REG_MACID; + + for (i = 0; i < ETH_ALEN; i++) + rtl8xxxu_write8(priv, reg + i, priv->mac_addr[i]); + + return 0; +} + +static int rtl8xxxu_set_bssid(struct rtl8xxxu_priv *priv, const u8 *bssid) +{ + int i; + u16 reg; + + dev_dbg(&priv->udev->dev, "%s: (%pM)\n", __func__, bssid); + + reg = REG_BSSID; + + for (i = 0; i < ETH_ALEN; i++) + rtl8xxxu_write8(priv, reg + i, bssid[i]); + + return 0; +} + +static void +rtl8xxxu_set_ampdu_factor(struct rtl8xxxu_priv *priv, u8 ampdu_factor) +{ + u8 vals[4] = { 0x41, 0xa8, 0x72, 0xb9 }; + u8 max_agg = 0xf; + int i; + + ampdu_factor = 1 << (ampdu_factor + 2); + if (ampdu_factor > max_agg) + ampdu_factor = max_agg; + + for (i = 0; i < 4; i++) { + if ((vals[i] & 0xf0) > (ampdu_factor << 4)) + vals[i] = (vals[i] & 0x0f) | (ampdu_factor << 4); + + if ((vals[i] & 0x0f) > ampdu_factor) + vals[i] = (vals[i] & 0xf0) | ampdu_factor; + + rtl8xxxu_write8(priv, REG_AGGLEN_LMT + i, vals[i]); + } +} + +static void rtl8xxxu_set_ampdu_min_space(struct rtl8xxxu_priv *priv, u8 density) +{ + u8 val8; + + val8 = rtl8xxxu_read8(priv, REG_AMPDU_MIN_SPACE); + val8 &= 0xf8; + val8 |= density; + rtl8xxxu_write8(priv, REG_AMPDU_MIN_SPACE, val8); +} + +static int rtl8xxxu_active_to_emu(struct rtl8xxxu_priv *priv) +{ + u8 val8; + int count, ret; + + /* Start of rtl8723AU_card_enable_flow */ + /* Act to Cardemu sequence*/ + /* Turn off RF */ + rtl8xxxu_write8(priv, REG_RF_CTRL, 0); + + /* 0x004E[7] = 0, switch DPDT_SEL_P output from register 0x0065[2] */ + val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); + val8 &= ~LEDCFG2_DPDT_SELECT; + rtl8xxxu_write8(priv, REG_LEDCFG2, val8); + + /* 0x0005[1] = 1 turn off MAC by HW state machine*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 |= BIT(1); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + if ((val8 & BIT(1)) == 0) + break; + udelay(10); + } + + if (!count) { + dev_warn(&priv->udev->dev, "%s: Disabling MAC timed out\n", + __func__); + ret = -EBUSY; + goto exit; + } + + /* 0x0000[5] = 1 analog Ips to digital, 1:isolation */ + val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL); + val8 |= SYS_ISO_ANALOG_IPS; + rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8); + + /* 0x0020[0] = 0 disable LDOA12 MACRO block*/ + val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL); + val8 &= ~LDOA15_ENABLE; + rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val8); + +exit: + return ret; +} + +static int rtl8xxxu_active_to_lps(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u8 val32; + int count, ret; + + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + + /* + * Poll - wait for RX packet to complete + */ + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, 0x5f8); + if (!val32) + break; + udelay(10); + } + + if (!count) { + dev_warn(&priv->udev->dev, + "%s: RX poll timed out (0x05f8)\n", __func__); + ret = -EBUSY; + goto exit; + } + + /* Disable CCK and OFDM, clock gated */ + val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC); + val8 &= ~SYS_FUNC_BBRSTB; + rtl8xxxu_write8(priv, REG_SYS_FUNC, val8); + + udelay(2); + + /* Reset baseband */ + val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC); + val8 &= ~SYS_FUNC_BB_GLB_RSTN; + rtl8xxxu_write8(priv, REG_SYS_FUNC, val8); + + /* Reset MAC TRX */ + val8 = rtl8xxxu_read8(priv, REG_CR); + val8 = CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE; + rtl8xxxu_write8(priv, REG_CR, val8); + + /* Reset MAC TRX */ + val8 = rtl8xxxu_read8(priv, REG_CR + 1); + val8 &= ~BIT(1); /* CR_SECURITY_ENABLE */ + rtl8xxxu_write8(priv, REG_CR + 1, val8); + + /* Respond TX OK to scheduler */ + val8 = rtl8xxxu_read8(priv, REG_DUAL_TSF_RST); + val8 |= DUAL_TSF_TX_OK; + rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, val8); + +exit: + return ret; +} + +static void rtl8xxxu_disabled_to_emu(struct rtl8xxxu_priv *priv) +{ + u8 val8; + + /* Clear suspend enable and power down enable*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~(BIT(3) | BIT(7)); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* 0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ + val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2); + val8 &= ~BIT(0); + rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val8); + + /* 0x04[12:11] = 11 enable WL suspend*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~(BIT(3) | BIT(4)); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); +} + +static int rtl8xxxu_emu_to_active(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u32 val32; + int count, ret = 0; + + /* 0x20[0] = 1 enable LDOA12 MACRO block for all interface*/ + val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL); + val8 |= LDOA15_ENABLE; + rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val8); + + /* 0x67[0] = 0 to disable BT_GPS_SEL pins*/ + val8 = rtl8xxxu_read8(priv, 0x0067); + val8 &= ~BIT(4); + rtl8xxxu_write8(priv, 0x0067, val8); + + mdelay(1); + + /* 0x00[5] = 0 release analog Ips to digital, 1:isolation */ + val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL); + val8 &= ~SYS_ISO_ANALOG_IPS; + rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8); + + /* disable SW LPS 0x04[10]= 0 */ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~BIT(2); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* wait till 0x04[17] = 1 power ready*/ + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + if (val32 & BIT(17)) + break; + + udelay(10); + } + + if (!count) { + ret = -EBUSY; + goto exit; + } + + /* We should be able to optimize the following three entries into one */ + + /* release WLON reset 0x04[16]= 1*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 2); + val8 |= BIT(0); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 2, val8); + + /* disable HWPDN 0x04[15]= 0*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~BIT(7); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* disable WL suspend*/ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~(BIT(3) | BIT(4)); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* set, then poll until 0 */ + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + val32 |= APS_FSMCO_MAC_ENABLE; + rtl8xxxu_write32(priv, REG_APS_FSMCO, val32); + + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + if ((val32 & APS_FSMCO_MAC_ENABLE) == 0) { + ret = 0; + break; + } + udelay(10); + } + + if (!count) { + ret = -EBUSY; + goto exit; + } + + /* 0x4C[23] = 0x4E[7] = 1, switch DPDT_SEL_P output from WL BB */ + /* + * Note: Vendor driver actually clears this bit, despite the + * documentation claims it's being set! + */ + val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); + val8 |= LEDCFG2_DPDT_SELECT; + val8 &= ~LEDCFG2_DPDT_SELECT; + rtl8xxxu_write8(priv, REG_LEDCFG2, val8); + +exit: + return ret; +} + +static int rtl8xxxu_emu_to_disabled(struct rtl8xxxu_priv *priv) +{ + u8 val8; + + /* 0x0007[7:0] = 0x20 SOP option to disable BG/MB */ + rtl8xxxu_write8(priv, REG_APS_FSMCO + 3, 0x20); + + /* 0x04[12:11] = 01 enable WL suspend */ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 &= ~BIT(4); + val8 |= BIT(3); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1); + val8 |= BIT(7); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8); + + /* 0x48[16] = 1 to enable GPIO9 as EXT wakeup */ + val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2); + val8 |= BIT(0); + rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val8); + + return 0; +} + +static int rtl8723au_power_on(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u16 val16; + u32 val32; + int ret; + + /* + * RSV_CTRL 0x001C[7:0] = 0x00, unlock ISO/CLK/Power control register + */ + rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0); + + rtl8xxxu_disabled_to_emu(priv); + + ret = rtl8xxxu_emu_to_active(priv); + if (ret) + goto exit; + + /* + * 0x0004[19] = 1, reset 8051 + */ + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 2); + val8 |= BIT(3); + rtl8xxxu_write8(priv, REG_APS_FSMCO + 2, val8); + + /* + * Enable MAC DMA/WMAC/SCHEDULE/SEC block + * Set CR bit10 to enable 32k calibration. + */ + val16 = rtl8xxxu_read16(priv, REG_CR); + val16 |= (CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE | + CR_TXDMA_ENABLE | CR_RXDMA_ENABLE | + CR_PROTOCOL_ENABLE | CR_SCHEDULE_ENABLE | + CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE | + CR_SECURITY_ENABLE | CR_CALTIMER_ENABLE); + rtl8xxxu_write16(priv, REG_CR, val16); + + /* For EFuse PG */ + val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL); + val32 &= ~(BIT(28) | BIT(29) | BIT(30)); + val32 |= (0x06 << 28); + rtl8xxxu_write32(priv, REG_EFUSE_CTRL, val32); +exit: + return ret; +} + +static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u16 val16; + u32 val32; + int i; + + for (i = 100; i; i--) { + val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO); + if (val8 & APS_FSMCO_PFM_ALDN) + break; + } + + if (!i) { + pr_info("%s: Poll failed\n", __func__); + return -ENODEV; + } + + /* + * RSV_CTRL 0x001C[7:0] = 0x00, unlock ISO/CLK/Power control register + */ + rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0); + rtl8xxxu_write8(priv, REG_SPS0_CTRL, 0x2b); + udelay(100); + + val8 = rtl8xxxu_read8(priv, REG_LDOV12D_CTRL); + if (!(val8 & LDOV12D_ENABLE)) { + pr_info("%s: Enabling LDOV12D (%02x)\n", __func__, val8); + val8 |= LDOV12D_ENABLE; + rtl8xxxu_write8(priv, REG_LDOV12D_CTRL, val8); + + udelay(100); + + val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL); + val8 &= ~SYS_ISO_MD2PP; + rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8); + } + + /* + * Auto enable WLAN + */ + val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO); + val16 |= APS_FSMCO_MAC_ENABLE; + rtl8xxxu_write16(priv, REG_APS_FSMCO, val16); + + for (i = 1000; i; i--) { + val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO); + if (!(val16 & APS_FSMCO_MAC_ENABLE)) + break; + } + if (!i) { + pr_info("%s: FSMCO_MAC_ENABLE poll failed\n", __func__); + return -EBUSY; + } + + /* + * Enable radio, GPIO, LED + */ + val16 = APS_FSMCO_HW_SUSPEND | APS_FSMCO_ENABLE_POWERDOWN | + APS_FSMCO_PFM_ALDN; + rtl8xxxu_write16(priv, REG_APS_FSMCO, val16); + + /* + * Release RF digital isolation + */ + val16 = rtl8xxxu_read16(priv, REG_SYS_ISO_CTRL); + val16 &= ~SYS_ISO_DIOR; + rtl8xxxu_write16(priv, REG_SYS_ISO_CTRL, val16); + + val8 = rtl8xxxu_read8(priv, REG_APSD_CTRL); + val8 &= ~APSD_CTRL_OFF; + rtl8xxxu_write8(priv, REG_APSD_CTRL, val8); + for (i = 200; i; i--) { + val8 = rtl8xxxu_read8(priv, REG_APSD_CTRL); + if (!(val8 & APSD_CTRL_OFF_STATUS)) + break; + } + + if (!i) { + pr_info("%s: APSD_CTRL poll failed\n", __func__); + return -EBUSY; + } + + /* + * Enable MAC DMA/WMAC/SCHEDULE/SEC block + */ + val16 = rtl8xxxu_read16(priv, REG_CR); + val16 |= CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE | + CR_TXDMA_ENABLE | CR_RXDMA_ENABLE | CR_PROTOCOL_ENABLE | + CR_SCHEDULE_ENABLE | CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE; + rtl8xxxu_write16(priv, REG_CR, val16); + + /* + * Workaround for 8188RU LNA power leakage problem. + */ + if (priv->rtlchip == 0x8188c && priv->hi_pa) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); + val32 &= ~BIT(1); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32); + } + return 0; +} + +static void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv) +{ + u8 val8; + u16 val16; + u32 val32; + + /* + * Workaround for 8188RU LNA power leakage problem. + */ + if (priv->rtlchip == 0x8188c && priv->hi_pa) { + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM); + val32 |= BIT(1); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32); + } + + rtl8xxxu_active_to_lps(priv); + + /* Turn off RF */ + rtl8xxxu_write8(priv, REG_RF_CTRL, 0x00); + + /* Reset Firmware if running in RAM */ + if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL) + rtl8xxxu_firmware_self_reset(priv); + + /* Reset MCU */ + val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC); + val16 &= ~SYS_FUNC_CPU_ENABLE; + rtl8xxxu_write16(priv, REG_SYS_FUNC, val16); + + /* Reset MCU ready status */ + rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00); + + rtl8xxxu_active_to_emu(priv); + rtl8xxxu_emu_to_disabled(priv); + + /* Reset MCU IO Wrapper */ + val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); + val8 &= ~BIT(0); + rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8); + + val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1); + val8 |= BIT(0); + rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8); + + /* RSV_CTRL 0x1C[7:0] = 0x0e lock ISO/CLK/Power control register */ + rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0e); +} + +static void rtl8xxxu_init_bt(struct rtl8xxxu_priv *priv) +{ + if (!priv->has_bluetooth) + return; +} + +static int rtl8xxxu_init_device(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + struct rtl8xxxu_rfregval *rftable; + bool macpower; + int ret; + u8 val8; + u16 val16; + u32 val32; + + /* Check if MAC is already powered on */ + val8 = rtl8xxxu_read8(priv, REG_CR); + + /* + * Fix 92DU-VC S3 hang with the reason is that secondary mac is not + * initialized. First MAC returns 0xea, second MAC returns 0x00 + */ + if (val8 == 0xea) + macpower = false; + else + macpower = true; + + ret = priv->fops->power_on(priv); + if (ret < 0) { + dev_warn(dev, "%s: Failed power on\n", __func__); + goto exit; + } + + dev_dbg(dev, "%s: macpower %i\n", __func__, macpower); + if (!macpower) { + ret = rtl8xxxu_init_llt_table(priv, TX_TOTAL_PAGE_NUM); + if (ret) { + dev_warn(dev, "%s: LLT table init failed\n", __func__); + goto exit; + } + } + + ret = rtl8xxxu_download_firmware(priv); + dev_dbg(dev, "%s: download_fiwmare %i\n", __func__, ret); + if (ret) + goto exit; + ret = rtl8xxxu_start_firmware(priv); + dev_dbg(dev, "%s: start_fiwmare %i\n", __func__, ret); + if (ret) + goto exit; + + ret = rtl8xxxu_init_mac(priv, rtl8723a_mac_init_table); + dev_dbg(dev, "%s: init_mac %i\n", __func__, ret); + if (ret) + goto exit; + + ret = rtl8xxxu_init_phy_bb(priv); + dev_dbg(dev, "%s: init_phy_bb %i\n", __func__, ret); + if (ret) + goto exit; + + switch(priv->rtlchip) { + case 0x8723a: + rftable = rtl8723au_radioa_1t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + break; + case 0x8188c: + if (priv->hi_pa) + rftable = rtl8188ru_radioa_1t_highpa_table; + else + rftable = rtl8192cu_radioa_1t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + break; + case 0x8191c: + rftable = rtl8192cu_radioa_1t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + break; + case 0x8192c: + rftable = rtl8192cu_radioa_2t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A); + if (ret) + break; + rftable = rtl8192cu_radiob_2t_init_table; + ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B); + break; + default: + ret = -EINVAL; + } + + if (ret) + goto exit; + + /* Reduce 80M spur */ + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83); + + /* RFSW Control - clear bit 14 ?? */ + rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); + /* 0x07000760 */ + val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | + FPGA0_RF_ANTSWB | FPGA0_RF_PAPE | + ((FPGA0_RF_ANTSW | FPGA0_RF_ANTSWB | FPGA0_RF_PAPE) << + FPGA0_RF_BD_CTRL_SHIFT); + rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32); + /* 0x860[6:5]= 00 - why? - this sets antenna B */ + rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66F60210); + + priv->rf_mode_ag[0] = rtl8xxxu_read_rfreg(priv, RF_A, + RF6052_REG_MODE_AG); + + dev_dbg(dev, "%s: macpower %i\n", __func__, macpower); + if (!macpower) { + if (priv->ep_tx_normal_queue) + val8 = TX_PAGE_NUM_NORM_PQ; + else + val8 = 0; + + rtl8xxxu_write8(priv, REG_RQPN_NPQ, val8); + + val32 = (TX_PAGE_NUM_PUBQ << RQPN_NORM_PQ_SHIFT) | RQPN_LOAD; + + if (priv->ep_tx_high_queue) + val32 |= (TX_PAGE_NUM_HI_PQ << RQPN_HI_PQ_SHIFT); + if (priv->ep_tx_low_queue) + val32 |= (TX_PAGE_NUM_LO_PQ << RQPN_LO_PQ_SHIFT); + + rtl8xxxu_write32(priv, REG_RQPN, val32); + + /* + * Set TX buffer boundary + */ + val8 = TX_TOTAL_PAGE_NUM + 1; + rtl8xxxu_write8(priv, REG_TXPKTBUF_BCNQ_BDNY, val8); + rtl8xxxu_write8(priv, REG_TXPKTBUF_MGQ_BDNY, val8); + rtl8xxxu_write8(priv, REG_TXPKTBUF_WMAC_LBK_BF_HD, val8); + rtl8xxxu_write8(priv, REG_TRXFF_BNDY, val8); + rtl8xxxu_write8(priv, REG_TDECTRL + 1, val8); + } + + ret = rtl8xxxu_init_queue_priority(priv); + dev_dbg(dev, "%s: init_queue_priority %i\n", __func__, ret); + if (ret) + goto exit; + + /* + * Set RX page boundary + */ + rtl8xxxu_write16(priv, REG_TRXFF_BNDY + 2, 0x27ff); + /* + * Transfer page size is always 128 + */ + val8 = (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_RX_SHIFT) | + (PBP_PAGE_SIZE_128 << PBP_PAGE_SIZE_TX_SHIFT); + rtl8xxxu_write8(priv, REG_PBP, val8); + + /* + * Unit in 8 bytes, not obvious what it is used for + */ + rtl8xxxu_write8(priv, REG_RX_DRVINFO_SZ, 4); + + /* + * Enable all interrupts - not obvious USB needs to do this + */ + rtl8xxxu_write32(priv, REG_HISR, 0xffffffff); + rtl8xxxu_write32(priv, REG_HIMR, 0xffffffff); + + rtl8xxxu_set_mac(priv); + rtl8xxxu_set_linktype(priv, NL80211_IFTYPE_STATION); + + /* + * Configure initial WMAC settings + */ + val32 = RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_MCAST | RCR_ACCEPT_BCAST | + /* RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON | */ + RCR_ACCEPT_MGMT_FRAME | RCR_HTC_LOC_CTRL | + RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC; + rtl8xxxu_write32(priv, REG_RCR, val32); + + /* + * Accept all multicast + */ + rtl8xxxu_write32(priv, REG_MAR, 0xffffffff); + rtl8xxxu_write32(priv, REG_MAR + 4, 0xffffffff); + + /* + * Init adaptive controls + */ + val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); + val32 &= ~RESPONSE_RATE_BITMAP_ALL; + val32 |= RESPONSE_RATE_RRSR_CCK_ONLY_1M; + rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val32); + + /* CCK = 0x0a, OFDM = 0x10 */ + rtl8xxxu_set_spec_sifs(priv, 0x10, 0x10); + rtl8xxxu_set_retry(priv, 0x30, 0x30); + rtl8xxxu_set_spec_sifs(priv, 0x0a, 0x10); + + /* + * Init EDCA + */ + rtl8xxxu_write16(priv, REG_MAC_SPEC_SIFS, 0x100a); + + /* Set CCK SIFS */ + rtl8xxxu_write16(priv, REG_SIFS_CCK, 0x100a); + + /* Set OFDM SIFS */ + rtl8xxxu_write16(priv, REG_SIFS_OFDM, 0x100a); + + /* TXOP */ + rtl8xxxu_write32(priv, REG_EDCA_BE_PARAM, 0x005ea42b); + rtl8xxxu_write32(priv, REG_EDCA_BK_PARAM, 0x0000a44f); + rtl8xxxu_write32(priv, REG_EDCA_VI_PARAM, 0x005ea324); + rtl8xxxu_write32(priv, REG_EDCA_VO_PARAM, 0x002fa226); + + /* Set data auto rate fallback retry count */ + rtl8xxxu_write32(priv, REG_DARFRC, 0x00000000); + rtl8xxxu_write32(priv, REG_DARFRC + 4, 0x10080404); + rtl8xxxu_write32(priv, REG_RARFRC, 0x04030201); + rtl8xxxu_write32(priv, REG_RARFRC + 4, 0x08070605); + + val8 = rtl8xxxu_read8(priv, REG_FWHW_TXQ_CTRL); + val8 |= FWHW_TXQ_CTRL_AMPDU_RETRY; + rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, val8); + + /* Set ACK timeout */ + rtl8xxxu_write8(priv, REG_ACKTO, 0x40); + + /* + * Initialize beacon parameters + */ + val16 = BEACON_DISABLE_TSF_UPDATE | (BEACON_DISABLE_TSF_UPDATE << 8); + rtl8xxxu_write16(priv, REG_BEACON_CTRL, val16); + rtl8xxxu_write16(priv, REG_TBTT_PROHIBIT, 0x6404); + rtl8xxxu_write8(priv, REG_DRIVER_EARLY_INT, DRIVER_EARLY_INT_TIME); + rtl8xxxu_write8(priv, REG_BEACON_DMA_TIME, BEACON_DMA_ATIME_INT_TIME); + rtl8xxxu_write16(priv, REG_BEACON_TCFG, 0x660F); + + /* + * Enable CCK and OFDM block + */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + val32 |= (FPGA_RF_MODE_CCK | FPGA_RF_MODE_OFDM); + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + + /* + * Invalidate all CAM entries - bit 30 is undocumented + */ + rtl8xxxu_write32(priv, REG_CAM_CMD, CAM_CMD_POLLING | BIT(30)); + + /* + * Start out with default power levels for channel 6, 20MHz + */ + rtl8723a_set_tx_power(priv, 1, false); + + /* Let the 8051 take control of antenna setting */ + val8 = rtl8xxxu_read8(priv, REG_LEDCFG2); + val8 |= LEDCFG2_DPDT_SELECT; + rtl8xxxu_write8(priv, REG_LEDCFG2, val8); + + rtl8xxxu_write8(priv, REG_HWSEQ_CTRL, 0xff); + + /* Disable BAR - not sure if this has any effect on USB */ + rtl8xxxu_write32(priv, REG_BAR_MODE_CTRL, 0x0201ffff); + + rtl8xxxu_write16(priv, REG_FAST_EDCA_CTRL, 0); + + /* + * Not sure if we should get into this at all + */ + if (priv->iqk_initialized) { + rtl8xxxu_restore_regs(priv, rtl8723au_iqk_phy_iq_bb_reg, + priv->bb_recovery_backup, + RTL8XXXU_BB_REGS); + } else { + rtl8723a_phy_iq_calibrate(priv); + priv->iqk_initialized = true; + } + + /* + * This should enable thermal meter + */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_T_METER, 0x60); + + rtl8723a_phy_lc_calibrate(priv); + + /* fix USB interface interference issue */ + rtl8xxxu_write8(priv, 0xfe40, 0xe0); + rtl8xxxu_write8(priv, 0xfe41, 0x8d); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, 0xfd0320); + + /* Solve too many protocol error on USB bus */ + /* Can't do this for 8188/8192 UMC A cut parts */ + rtl8xxxu_write8(priv, 0xfe40, 0xe6); + rtl8xxxu_write8(priv, 0xfe41, 0x94); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + rtl8xxxu_write8(priv, 0xfe40, 0xe0); + rtl8xxxu_write8(priv, 0xfe41, 0x19); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + rtl8xxxu_write8(priv, 0xfe40, 0xe5); + rtl8xxxu_write8(priv, 0xfe41, 0x91); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + rtl8xxxu_write8(priv, 0xfe40, 0xe2); + rtl8xxxu_write8(priv, 0xfe41, 0x81); + rtl8xxxu_write8(priv, 0xfe42, 0x80); + + /* Init BT hw config. */ + rtl8xxxu_init_bt(priv); + + /* + * Not sure if we really need to save these parameters, but the + * vendor driver does + */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM2); + if (val32 & FPGA0_HSSI_PARM2_CCK_HIGH_PWR) + priv->path_a_hi_power = 1; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); + priv->path_a_rf_paths = val32 & OFDM_RF_PATH_RX_MASK; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1); + priv->path_a_ig_value = val32 & OFDM0_X_AGC_CORE1_IGI_MASK; + + /* Set NAV_UPPER to 30000us */ + val8 = ((30000 + NAV_UPPER_UNIT - 1) / NAV_UPPER_UNIT); + rtl8xxxu_write8(priv, REG_NAV_UPPER, val8); + + /* + * 2011/03/09 MH debug only, UMC-B cut pass 2500 S5 test, + * but we need to fin root cause. + */ + val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE); + if ((val32 & 0xff000000) != 0x83000000) { + val32 |= FPGA_RF_MODE_CCK; + rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32); + } + + val32 = rtl8xxxu_read32(priv, REG_FWHW_TXQ_CTRL); + val32 |= FWHW_TXQ_CTRL_XMIT_MGMT_ACK; + /* ack for xmit mgmt frames. */ + rtl8xxxu_write32(priv, REG_FWHW_TXQ_CTRL, val32); + +exit: + return ret; +} + +static void rtl8xxxu_disable_device(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + + rtl8xxxu_power_off(priv); +} + +static void rtl8xxxu_cam_write(struct rtl8xxxu_priv *priv, + struct ieee80211_key_conf *key, const u8 *mac) +{ + u32 cmd, val32, addr, ctrl; + int j, i, tmp_debug; + + tmp_debug = rtl8xxxu_debug; + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_KEY) + rtl8xxxu_debug |= RTL8XXXU_DEBUG_REG_WRITE; + + /* + * This is a bit of a hack - the lower bits of the cipher + * suite selector happens to match the cipher index in the CAM + */ + addr = key->keyidx << CAM_CMD_KEY_SHIFT; + ctrl = (key->cipher & 0x0f) << 2 | key->keyidx | CAM_WRITE_VALID; + + for (j = 5; j >= 0; j--) { + switch (j) { + case 0: + val32 = ctrl | (mac[0] << 16) | (mac[1] << 24); + break; + case 1: + val32 = mac[2] | (mac[3] << 8) | + (mac[4] << 16) | (mac[5] << 24); + break; + default: + i = (j - 2) << 2; + val32 = key->key[i] | (key->key[i + 1] << 8) | + key->key[i + 2] << 16 | key->key[i + 3] << 24; + break; + } + + rtl8xxxu_write32(priv, REG_CAM_WRITE, val32); + cmd = CAM_CMD_POLLING | CAM_CMD_WRITE | (addr + j); + rtl8xxxu_write32(priv, REG_CAM_CMD, cmd); + udelay(100); + } + + rtl8xxxu_debug = tmp_debug; +} + +static void rtl8xxxu_sw_scan_start(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, const u8* mac) +{ + struct rtl8xxxu_priv *priv = hw->priv; + u8 val8; + + val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); + val8 |= BEACON_DISABLE_TSF_UPDATE; + rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); +} + +static void rtl8xxxu_sw_scan_complete(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl8xxxu_priv *priv = hw->priv; + u8 val8; + + val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); + val8 &= ~BEACON_DISABLE_TSF_UPDATE; + rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); +} + +static void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, + u32 ramask, int sgi) +{ + struct h2c_cmd h2c; + + h2c.ramask.cmd = H2C_SET_RATE_MASK; + h2c.ramask.mask_lo = cpu_to_le16(ramask & 0xffff); + h2c.ramask.mask_hi = cpu_to_le16(ramask >> 16); + + h2c.ramask.arg = 0x80; + if (sgi) + h2c.ramask.arg |= 0x20; + + dev_dbg(&priv->udev->dev, "%s: rate mask %08x, arg %02x\n", __func__, + ramask, h2c.ramask.arg); + rtl8723a_h2c_cmd(priv, &h2c); +} + +static void rtl8xxxu_set_basic_rates(struct rtl8xxxu_priv *priv, u32 rate_cfg) +{ + u32 val32; + u8 rate_idx = 0; + + rate_cfg &= RESPONSE_RATE_BITMAP_ALL; + + val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); + val32 &= ~RESPONSE_RATE_BITMAP_ALL; + val32 |= rate_cfg; + rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val32); + + dev_dbg(&priv->udev->dev, "%s: rates %08x\n", __func__, rate_cfg); + + while (rate_cfg) { + rate_cfg = (rate_cfg >> 1); + rate_idx++; + } + rtl8xxxu_write8(priv, REG_INIRTS_RATE_SEL, rate_idx); +} + +static void +rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, u32 changed) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + struct ieee80211_sta *sta; + u32 val32; + u8 val8; + + if (changed & BSS_CHANGED_ASSOC) { + struct h2c_cmd h2c; + + dev_dbg(dev, "Changed ASSOC: %i!\n", bss_conf->assoc); + + memset(&h2c, 0, sizeof(struct h2c_cmd)); + rtl8xxxu_set_linktype(priv, vif->type); + + if (bss_conf->assoc) { + u32 ramask; + int sgi = 0; + + rcu_read_lock(); + sta = ieee80211_find_sta(vif, bss_conf->bssid); + if (!sta) { + dev_info(dev, "%s: ASSOC no sta found\n", + __func__); + rcu_read_unlock(); + goto error; + } + + if (sta->ht_cap.ht_supported) + dev_info(dev, "%s: HT supported\n", __func__); + if (sta->vht_cap.vht_supported) + dev_info(dev, "%s: VHT supported\n", __func__); + + /* TODO: Set bits 28-31 for rate adaptive id */ + ramask = (sta->supp_rates[0] & 0xfff) | + sta->ht_cap.mcs.rx_mask[0] << 12 | + sta->ht_cap.mcs.rx_mask[1] << 20; + if (sta->ht_cap.cap & + (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20)) + sgi = 1; + rcu_read_unlock(); + + rtl8xxxu_update_rate_mask(priv, ramask, sgi); + + val32 = rtl8xxxu_read32(priv, REG_RCR); + val32 |= RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON; + rtl8xxxu_write32(priv, REG_RCR, val32); + + /* Enable RX of data frames */ + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff); + + rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff); + + rtl8723a_stop_tx_beacon(priv); + + /* joinbss sequence */ + rtl8xxxu_write16(priv, REG_BCN_PSR_RPT, + 0xc000 | bss_conf->aid); + + h2c.joinbss.data = H2C_JOIN_BSS_CONNECT; + } else { + val32 = rtl8xxxu_read32(priv, REG_RCR); + val32 &= ~(RCR_CHECK_BSSID_MATCH | + RCR_CHECK_BSSID_BEACON); + rtl8xxxu_write32(priv, REG_RCR, val32); + + val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); + val8 |= BEACON_DISABLE_TSF_UPDATE; + rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); + + /* Disable RX of data frames */ + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000); + h2c.joinbss.data = H2C_JOIN_BSS_DISCONNECT; + } + h2c.joinbss.cmd = H2C_JOIN_BSS_REPORT; + rtl8723a_h2c_cmd(priv, &h2c); + } + + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + dev_dbg(dev, "Changed ERP_PREAMBLE: Use short preamble %i\n", + bss_conf->use_short_preamble); + val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET); + if (bss_conf->use_short_preamble) + val32 |= RSR_ACK_SHORT_PREAMBLE; + else + val32 &= ~RSR_ACK_SHORT_PREAMBLE; + rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val32); + } + + if (changed & BSS_CHANGED_ERP_SLOT) { + dev_dbg(dev, "Changed ERP_SLOT: short_slot_time %i\n", + bss_conf->use_short_slot); + + if (bss_conf->use_short_slot) + val8 = 9; + else + val8 = 20; + rtl8xxxu_write8(priv, REG_SLOT, val8); + } + + if (changed & BSS_CHANGED_BSSID) { + dev_dbg(dev, "Changed BSSID!\n"); + rtl8xxxu_set_bssid(priv, bss_conf->bssid); + } + + if (changed & BSS_CHANGED_BASIC_RATES) { + dev_dbg(dev, "Changed BASIC_RATES!\n"); + rtl8xxxu_set_basic_rates(priv, bss_conf->basic_rates); + } +error: + return; +} + +static u32 rtl8xxxu_80211_to_rtl_queue(u32 queue) +{ + u32 rtlqueue; + + switch (queue) { + case IEEE80211_AC_VO: + rtlqueue = TXDESC_QUEUE_VO; + break; + case IEEE80211_AC_VI: + rtlqueue = TXDESC_QUEUE_VI; + break; + case IEEE80211_AC_BE: + rtlqueue = TXDESC_QUEUE_BE; + break; + case IEEE80211_AC_BK: + rtlqueue = TXDESC_QUEUE_BK; + break; + default: + rtlqueue = TXDESC_QUEUE_BE; + } + + return rtlqueue; +} + +static u32 rtl8xxxu_queue_select(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + u32 queue; + + if (ieee80211_is_mgmt(hdr->frame_control)) + queue = TXDESC_QUEUE_MGNT; + else + queue = rtl8xxxu_80211_to_rtl_queue(skb_get_queue_mapping(skb)); + + return queue; +} + +static void rtl8xxxu_calc_tx_desc_csum(struct rtl8xxxu_tx_desc *tx_desc) +{ + __le16 *ptr = (__le16 *)tx_desc; + u16 csum = 0; + int i; + + /* + * Clear csum field before calculation, as the csum field is + * in the middle of the struct. + */ + tx_desc->csum = cpu_to_le16(0); + + for (i = 0; i < (sizeof(struct rtl8xxxu_tx_desc) / sizeof(u16)); i++) + csum = csum ^ le16_to_cpu(ptr[i]); + + tx_desc->csum |= cpu_to_le16(csum); +} + +static void rtl8xxxu_free_tx_resources(struct rtl8xxxu_priv *priv) +{ + struct rtl8xxxu_tx_urb *tx_urb, *tmp; + unsigned long flags; + + spin_lock_irqsave(&priv->tx_urb_lock, flags); + list_for_each_entry_safe(tx_urb, tmp, &priv->tx_urb_free_list, list) { + list_del(&tx_urb->list); + priv->tx_urb_free_count--; + usb_free_urb(&tx_urb->urb); + } + spin_unlock_irqrestore(&priv->tx_urb_lock, flags); +} + +static struct rtl8xxxu_tx_urb * +rtl8xxxu_alloc_tx_urb(struct rtl8xxxu_priv *priv) +{ + struct rtl8xxxu_tx_urb *tx_urb; + unsigned long flags; + + spin_lock_irqsave(&priv->tx_urb_lock, flags); + tx_urb = list_first_entry_or_null(&priv->tx_urb_free_list, + struct rtl8xxxu_tx_urb, list); + if (tx_urb) { + list_del(&tx_urb->list); + priv->tx_urb_free_count--; + if (priv->tx_urb_free_count < RTL8XXXU_TX_URB_LOW_WATER && + !priv->tx_stopped) { + priv->tx_stopped = true; + ieee80211_stop_queues(priv->hw); + } + } + + spin_unlock_irqrestore(&priv->tx_urb_lock, flags); + + return tx_urb; +} + +static void rtl8xxxu_free_tx_urb(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_tx_urb *tx_urb) +{ + unsigned long flags; + + INIT_LIST_HEAD(&tx_urb->list); + + spin_lock_irqsave(&priv->tx_urb_lock, flags); + + list_add(&tx_urb->list, &priv->tx_urb_free_list); + priv->tx_urb_free_count++; + if (priv->tx_urb_free_count > RTL8XXXU_TX_URB_HIGH_WATER && + priv->tx_stopped) { + priv->tx_stopped = false; + ieee80211_wake_queues(priv->hw); + } + + spin_unlock_irqrestore(&priv->tx_urb_lock, flags); +} + +static void rtl8xxxu_tx_complete(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *)urb->context; + struct ieee80211_tx_info *tx_info; + struct ieee80211_hw *hw; + struct rtl8xxxu_tx_urb *tx_urb = + container_of(urb, struct rtl8xxxu_tx_urb, urb); + + tx_info = IEEE80211_SKB_CB(skb); + hw = tx_info->rate_driver_data[0]; + + skb_pull(skb, sizeof(struct rtl8xxxu_tx_desc)); + + ieee80211_tx_info_clear_status(tx_info); + tx_info->status.rates[0].idx = -1; + tx_info->status.rates[0].count = 0; + + if (!urb->status) + tx_info->flags |= IEEE80211_TX_STAT_ACK; + + ieee80211_tx_status_irqsafe(hw, skb); + + rtl8xxxu_free_tx_urb(hw->priv, tx_urb); +} + +static void rtl8xxxu_dump_action(struct device *dev, + struct ieee80211_hdr *hdr) +{ + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)hdr; + u16 cap, timeout; + + if (!(rtl8xxxu_debug & RTL8XXXU_DEBUG_ACTION)) + return; + + switch (mgmt->u.action.u.addba_resp.action_code) { + case WLAN_ACTION_ADDBA_RESP: + cap = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); + timeout = le16_to_cpu(mgmt->u.action.u.addba_resp.timeout); + dev_info(dev, "WLAN_ACTION_ADDBA_RESP: " + "timeout %i, tid %02x, buf_size %02x, policy %02x, " + "status %02x\n", + timeout, + (cap & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2, + (cap & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6, + (cap >> 1) & 0x1, + le16_to_cpu(mgmt->u.action.u.addba_resp.status)); + break; + case WLAN_ACTION_ADDBA_REQ: + cap = le16_to_cpu(mgmt->u.action.u.addba_req.capab); + timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); + dev_info(dev, "WLAN_ACTION_ADDBA_REQ: " + "timeout %i, tid %02x, buf_size %02x, policy %02x\n", + timeout, + (cap & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2, + (cap & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6, + (cap >> 1) & 0x1); + break; + default: + dev_info(dev, "action frame %02x\n", + mgmt->u.action.u.addba_resp.action_code); + break; + } +} + +static void rtl8xxxu_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ieee80211_rate *tx_rate = ieee80211_get_tx_rate(hw, tx_info); + struct rtl8xxxu_priv *priv = hw->priv; + struct rtl8xxxu_tx_desc *tx_desc; + struct rtl8xxxu_tx_urb *tx_urb; + struct ieee80211_sta *sta = NULL; + struct ieee80211_vif *vif = tx_info->control.vif; + struct device *dev = &priv->udev->dev; + u32 queue, rate; + u16 pktlen = skb->len; + u16 seq_number; + u16 rate_flag = tx_info->control.rates[0].flags; + int ret; + + if (skb_headroom(skb) < sizeof(struct rtl8xxxu_tx_desc)) { + dev_warn(dev, + "%s: Not enough headroom (%i) for tx descriptor\n", + __func__, skb_headroom(skb)); + goto error; + } + + if (unlikely(skb->len > (65535 - sizeof(struct rtl8xxxu_tx_desc)))) { + dev_warn(dev, "%s: Trying to send over-sized skb (%i)\n", + __func__, skb->len); + goto error; + } + + tx_urb = rtl8xxxu_alloc_tx_urb(priv); + if (!tx_urb) { + dev_warn(dev, "%s: Unable to allocate tx urb\n", __func__); + goto error; + } + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_TX) + dev_info(dev, "%s: TX rate: %d (%d), pkt size %d\n", + __func__, tx_rate->bitrate, tx_rate->hw_value, pktlen); + + if (ieee80211_is_action(hdr->frame_control)) + rtl8xxxu_dump_action(dev, hdr); + + tx_info->rate_driver_data[0] = hw; + + if (control && control->sta) + sta = control->sta; + + tx_desc = (struct rtl8xxxu_tx_desc *) + skb_push(skb, sizeof(struct rtl8xxxu_tx_desc)); + + memset(tx_desc, 0, sizeof(struct rtl8xxxu_tx_desc)); + tx_desc->pkt_size = cpu_to_le16(pktlen); + tx_desc->pkt_offset = sizeof(struct rtl8xxxu_tx_desc); + + tx_desc->txdw0 = + TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT; + if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) + tx_desc->txdw0 |= TXDESC_BROADMULTICAST; + + queue = rtl8xxxu_queue_select(hw, skb); + tx_desc->txdw1 = cpu_to_le32(queue << TXDESC_QUEUE_SHIFT); + + if (tx_info->control.hw_key) { + switch (tx_info->control.hw_key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + tx_desc->txdw1 |= cpu_to_le32(TXDESC_SEC_RC4); + break; + case WLAN_CIPHER_SUITE_CCMP: + tx_desc->txdw1 |= cpu_to_le32(TXDESC_SEC_AES); + break; + default: + break; + } + } + + seq_number = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + tx_desc->txdw3 = cpu_to_le32((u32)seq_number << TXDESC_SEQ_SHIFT); + + if (rate_flag & IEEE80211_TX_RC_MCS) + rate = tx_info->control.rates[0].idx + DESC_RATE_MCS0; + else + rate = tx_rate->hw_value; + tx_desc->txdw5 = cpu_to_le32(rate); + + if (ieee80211_is_data(hdr->frame_control)) + tx_desc->txdw5 |= cpu_to_le32(0x0001ff00); + + /* (tx_info->flags & IEEE80211_TX_CTL_AMPDU) && */ + if (ieee80211_is_data_qos(hdr->frame_control) && sta) { + if (sta->ht_cap.ht_supported) { + u32 ampdu, val32; + + ampdu = (u32)sta->ht_cap.ampdu_density; + val32 = ampdu << TXDESC_AMPDU_DENSITY_SHIFT; + tx_desc->txdw2 |= cpu_to_le32(val32); + tx_desc->txdw1 |= cpu_to_le32(TXDESC_AGG_ENABLE); + } else + tx_desc->txdw1 |= cpu_to_le32(TXDESC_BK); + } else + tx_desc->txdw1 |= cpu_to_le32(TXDESC_BK); + + if (ieee80211_is_data_qos(hdr->frame_control)) + tx_desc->txdw4 |= cpu_to_le32(TXDESC_QOS); + if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE || + (sta && vif && vif->bss_conf.use_short_preamble)) + tx_desc->txdw4 |= cpu_to_le32(TXDESC_SHORT_PREAMBLE); + if (rate_flag & IEEE80211_TX_RC_SHORT_GI || + (ieee80211_is_data_qos(hdr->frame_control) && + sta && sta->ht_cap.cap & + (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20))) { + tx_desc->txdw5 |= cpu_to_le32(TXDESC_SHORT_GI); + } + if (ieee80211_is_mgmt(hdr->frame_control)) { + tx_desc->txdw5 = cpu_to_le32(tx_rate->hw_value); + tx_desc->txdw4 |= cpu_to_le32(TXDESC_USE_DRIVER_RATE); + tx_desc->txdw5 |= cpu_to_le32(6 << TXDESC_RETRY_LIMIT_SHIFT); + tx_desc->txdw5 |= cpu_to_le32(TXDESC_RETRY_LIMIT_ENABLE); + } + + if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) { + /* Use RTS rate 24M - does the mac80211 tell us which to use? */ + tx_desc->txdw4 |= cpu_to_le32(DESC_RATE_24M); + tx_desc->txdw4 |= cpu_to_le32(TXDESC_RTS_CTS_ENABLE); + tx_desc->txdw4 |= cpu_to_le32(TXDESC_HW_RTS_ENABLE); + } + + rtl8xxxu_calc_tx_desc_csum(tx_desc); + + usb_fill_bulk_urb(&tx_urb->urb, priv->udev, priv->pipe_out[queue], + skb->data, skb->len, rtl8xxxu_tx_complete, skb); + + usb_anchor_urb(&tx_urb->urb, &priv->tx_anchor); + ret = usb_submit_urb(&tx_urb->urb, GFP_ATOMIC); + if (ret) { + usb_unanchor_urb(&tx_urb->urb); + rtl8xxxu_free_tx_urb(priv, tx_urb); + goto error; + } + return; +error: + dev_kfree_skb(skb); +} + +static void rtl8xxxu_rx_parse_phystats(struct rtl8xxxu_priv *priv, + struct ieee80211_rx_status *rx_status, + struct rtl8xxxu_rx_desc *rx_desc, + struct rtl8723au_phy_stats *phy_stats) +{ + if (phy_stats->sgi_en) + rx_status->flag |= RX_FLAG_SHORT_GI; + + if (rx_desc->rxmcs < DESC_RATE_6M) { + /* + * Handle PHY stats for CCK rates + */ + u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a; + + switch (cck_agc_rpt & 0xc0) { + case 0xc0: + rx_status->signal = -46 - (cck_agc_rpt & 0x3e); + break; + case 0x80: + rx_status->signal = -26 - (cck_agc_rpt & 0x3e); + break; + case 0x40: + rx_status->signal = -12 - (cck_agc_rpt & 0x3e); + break; + case 0x00: + rx_status->signal = 16 - (cck_agc_rpt & 0x3e); + break; + } + } else { + rx_status->signal = + (phy_stats->cck_sig_qual_ofdm_pwdb_all >> 1) - 110; + } +} + +static void rtl8xxxu_free_rx_resources(struct rtl8xxxu_priv *priv) +{ + struct rtl8xxxu_rx_urb *rx_urb, *tmp; + unsigned long flags; + + spin_lock_irqsave(&priv->rx_urb_lock, flags); + + list_for_each_entry_safe(rx_urb, tmp, + &priv->rx_urb_pending_list, list) { + list_del(&rx_urb->list); + priv->rx_urb_pending_count--; + usb_free_urb(&rx_urb->urb); + } + + spin_unlock_irqrestore(&priv->rx_urb_lock, flags); +} + +static void rtl8xxxu_queue_rx_urb(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_rx_urb *rx_urb) +{ + struct sk_buff *skb; + unsigned long flags; + int pending = 0; + + spin_lock_irqsave(&priv->rx_urb_lock, flags); + + if (!priv->shutdown) { + list_add_tail(&rx_urb->list, &priv->rx_urb_pending_list); + priv->rx_urb_pending_count++; + pending = priv->rx_urb_pending_count; + } else { + skb = (struct sk_buff *)rx_urb->urb.context; + dev_kfree_skb(skb); + usb_free_urb(&rx_urb->urb); + } + + spin_unlock_irqrestore(&priv->rx_urb_lock, flags); + + if (pending > RTL8XXXU_RX_URB_PENDING_WATER) + schedule_work(&priv->rx_urb_wq); +} + +static void rtl8xxxu_rx_urb_work(struct work_struct *work) +{ + struct rtl8xxxu_priv *priv; + struct rtl8xxxu_rx_urb *rx_urb, *tmp; + struct list_head local; + struct sk_buff *skb; + unsigned long flags; + int ret; + + priv = container_of(work, struct rtl8xxxu_priv, rx_urb_wq); + INIT_LIST_HEAD(&local); + + spin_lock_irqsave(&priv->rx_urb_lock, flags); + + list_splice_init(&priv->rx_urb_pending_list, &local); + priv->rx_urb_pending_count = 0; + + spin_unlock_irqrestore(&priv->rx_urb_lock, flags); + + list_for_each_entry_safe(rx_urb, tmp, &local, list) { + list_del_init(&rx_urb->list); + ret = rtl8xxxu_submit_rx_urb(priv, rx_urb); + /* + * If out of memory or temporary error, put it back on the + * queue and try again. Otherwise the device is dead/gone + * and we should drop it. + */ + switch (ret) { + case 0: + break; + case -ENOMEM: + case -EAGAIN: + rtl8xxxu_queue_rx_urb(priv, rx_urb); + break; + default: + pr_info("failed to requeue urb %i\n", ret); + skb = (struct sk_buff *)rx_urb->urb.context; + dev_kfree_skb(skb); + usb_free_urb(&rx_urb->urb); + } + } +} + +static void rtl8xxxu_rx_complete(struct urb *urb) +{ + struct rtl8xxxu_rx_urb *rx_urb = + container_of(urb, struct rtl8xxxu_rx_urb, urb); + struct ieee80211_hw *hw = rx_urb->hw; + struct rtl8xxxu_priv *priv = hw->priv; + struct sk_buff *skb = (struct sk_buff *)urb->context; + struct rtl8xxxu_rx_desc *rx_desc = (struct rtl8xxxu_rx_desc *)skb->data; + struct rtl8723au_phy_stats *phy_stats; + struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); + struct ieee80211_mgmt *mgmt; + struct device *dev = &priv->udev->dev; + __le32 *_rx_desc_le = (__le32 *)skb->data; + u32 *_rx_desc = (u32 *)skb->data; + int cnt, len, drvinfo_sz, desc_shift, i; + + for (i = 0; i < (sizeof(struct rtl8xxxu_rx_desc) / sizeof(u32)); i++) + _rx_desc[i] = le32_to_cpu(_rx_desc_le[i]); + + cnt = rx_desc->frag; + len = rx_desc->pktlen; + drvinfo_sz = rx_desc->drvinfo_sz * 8; + desc_shift = rx_desc->shift; + skb_put(skb, urb->actual_length); + + if (urb->status == 0) { + skb_pull(skb, sizeof(struct rtl8xxxu_rx_desc)); + phy_stats = (struct rtl8723au_phy_stats *)skb->data; + + skb_pull(skb, drvinfo_sz + desc_shift); + + mgmt = (struct ieee80211_mgmt *)skb->data; + + memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); + + if (rx_desc->phy_stats) + rtl8xxxu_rx_parse_phystats(priv, rx_status, + rx_desc, phy_stats); + + rx_status->freq = hw->conf.chandef.chan->center_freq; + rx_status->band = hw->conf.chandef.chan->band; + + rx_status->mactime = le32_to_cpu(rx_desc->tsfl); + rx_status->flag |= RX_FLAG_MACTIME_START; + + if (!rx_desc->swdec) + rx_status->flag |= RX_FLAG_DECRYPTED; + if (rx_desc->crc32) + rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; + if (rx_desc->bw) + rx_status->flag |= RX_FLAG_40MHZ; + + if (rx_desc->rxht) { + rx_status->flag |= RX_FLAG_HT; + rx_status->rate_idx = rx_desc->rxmcs - DESC_RATE_MCS0; + } else { + rx_status->rate_idx = rx_desc->rxmcs; + } + + ieee80211_rx_irqsafe(hw, skb); + skb = NULL; + rx_urb->urb.context = NULL; + rtl8xxxu_queue_rx_urb(priv, rx_urb); + } else { + dev_dbg(dev, "%s: status %i\n", __func__, urb->status); + goto cleanup; + } + return; + +cleanup: + usb_free_urb(urb); + dev_kfree_skb(skb); + return; +} + +static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv, + struct rtl8xxxu_rx_urb *rx_urb) +{ + struct sk_buff *skb; + int skb_size; + int ret; + + skb_size = sizeof(struct rtl8xxxu_rx_desc) + RTL_RX_BUFFER_SIZE; + skb = __netdev_alloc_skb(NULL, skb_size, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + memset(skb->data, 0, sizeof(struct rtl8xxxu_rx_desc)); + usb_fill_bulk_urb(&rx_urb->urb, priv->udev, priv->pipe_in, skb->data, + skb_size, rtl8xxxu_rx_complete, skb); + usb_anchor_urb(&rx_urb->urb, &priv->rx_anchor); + ret = usb_submit_urb(&rx_urb->urb, GFP_ATOMIC); + if (ret) + usb_unanchor_urb(&rx_urb->urb); + return ret; +} + +static void rtl8xxxu_int_complete(struct urb *urb) +{ + struct rtl8xxxu_priv *priv = (struct rtl8xxxu_priv *)urb->context; + struct device *dev = &priv->udev->dev; + int ret; + + dev_dbg(dev, "%s: status %i\n", __func__, urb->status); + if (urb->status == 0) { + usb_anchor_urb(urb, &priv->int_anchor); + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + usb_unanchor_urb(urb); + } else { + dev_info(dev, "%s: Error %i\n", __func__, urb->status); + } +} + + +static int rtl8xxxu_submit_int_urb(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct urb *urb; + u32 val32; + int ret; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + return -ENOMEM; + + usb_fill_int_urb(urb, priv->udev, priv->pipe_interrupt, + priv->int_buf, USB_INTR_CONTENT_LENGTH, + rtl8xxxu_int_complete, priv, 1); + usb_anchor_urb(urb, &priv->int_anchor); + ret = usb_submit_urb(urb, GFP_KERNEL); + if (ret) { + usb_unanchor_urb(urb); + goto error; + } + + val32 = rtl8xxxu_read32(priv, REG_USB_HIMR); + val32 |= USB_HIMR_CPWM; + rtl8xxxu_write32(priv, REG_USB_HIMR, val32); + +error: + return ret; +} + +static int rtl8xxxu_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl8xxxu_priv *priv = hw->priv; + int ret; + u8 val8; + + switch (vif->type) { + case NL80211_IFTYPE_STATION: + rtl8723a_stop_tx_beacon(priv); + + val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL); + val8 |= BEACON_ATIM | BEACON_FUNCTION_ENABLE | + BEACON_DISABLE_TSF_UPDATE; + rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8); + ret = 0; + break; + default: + ret = -EOPNOTSUPP; + } + + rtl8xxxu_set_linktype(priv, vif->type); + + return ret; +} + +static void rtl8xxxu_remove_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct rtl8xxxu_priv *priv = hw->priv; + + dev_dbg(&priv->udev->dev, "%s\n", __func__); +} + +static int rtl8xxxu_config(struct ieee80211_hw *hw, u32 changed) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + u16 val16; + int ret = 0, channel; + bool ht40; + + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_CHANNEL) + dev_info(dev, + "%s: channel: %i (changed %08x chandef.width %02x)\n", + __func__, hw->conf.chandef.chan->hw_value, + changed, hw->conf.chandef.width); + + if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { + val16 = ((hw->conf.long_frame_max_tx_count << + RETRY_LIMIT_LONG_SHIFT) & RETRY_LIMIT_LONG_MASK) | + ((hw->conf.short_frame_max_tx_count << + RETRY_LIMIT_SHORT_SHIFT) & RETRY_LIMIT_SHORT_MASK); + rtl8xxxu_write16(priv, REG_RETRY_LIMIT, val16); + } + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + switch (hw->conf.chandef.width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + ht40 = false; + break; + case NL80211_CHAN_WIDTH_40: + ht40 = true; + break; + default: + ret = -ENOTSUPP; + goto exit; + } + + channel = hw->conf.chandef.chan->hw_value; + + rtl8723a_set_tx_power(priv, channel, ht40); + + rtl8723au_config_channel(hw); + } + +exit: + return ret; +} + +static int rtl8xxxu_conf_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u16 queue, + const struct ieee80211_tx_queue_params *param) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + u32 val32; + u8 aifs, acm_ctrl, acm_bit; + + aifs = param->aifs; + + val32 = aifs | + fls(param->cw_min) << EDCA_PARAM_ECW_MIN_SHIFT | + fls(param->cw_max) << EDCA_PARAM_ECW_MAX_SHIFT | + (u32)param->txop << EDCA_PARAM_TXOP_SHIFT; + + acm_ctrl = rtl8xxxu_read8(priv, REG_ACM_HW_CTRL); + dev_dbg(dev, + "%s: IEEE80211 queue %02x val %08x, acm %i, acm_ctrl %02x\n", + __func__, queue, val32, param->acm, acm_ctrl); + + switch (queue) { + case IEEE80211_AC_VO: + acm_bit = ACM_HW_CTRL_VO; + rtl8xxxu_write32(priv, REG_EDCA_VO_PARAM, val32); + break; + case IEEE80211_AC_VI: + acm_bit = ACM_HW_CTRL_VI; + rtl8xxxu_write32(priv, REG_EDCA_VI_PARAM, val32); + break; + case IEEE80211_AC_BE: + acm_bit = ACM_HW_CTRL_BE; + rtl8xxxu_write32(priv, REG_EDCA_BE_PARAM, val32); + break; + case IEEE80211_AC_BK: + acm_bit = ACM_HW_CTRL_BK; + rtl8xxxu_write32(priv, REG_EDCA_BK_PARAM, val32); + break; + default: + acm_bit = 0; + break; + } + + if (param->acm) + acm_ctrl |= acm_bit; + else + acm_ctrl &= ~acm_bit; + rtl8xxxu_write8(priv, REG_ACM_HW_CTRL, acm_ctrl); + + return 0; +} + +static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, u64 multicast) +{ + struct rtl8xxxu_priv *priv = hw->priv; + + dev_dbg(&priv->udev->dev, "%s: changed_flags %08x, total_flags %08x\n", + __func__, changed_flags, *total_flags); + + *total_flags &= (FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC); +} + +static int rtl8xxxu_set_rts_threshold(struct ieee80211_hw *hw, u32 rts) +{ + if (rts > 2347) + return -EINVAL; + + return 0; +} + +static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + u8 mac_addr[ETH_ALEN]; + u8 val8; + u16 val16; + u32 val32; + int retval = -EOPNOTSUPP; + + dev_dbg(dev, "%s: cmd %02x, cipher %08x, index %i\n", + __func__, cmd, key->cipher, key->keyidx); + + if (vif->type != NL80211_IFTYPE_STATION) + return -EOPNOTSUPP; + + if (key->keyidx > 3) + return -EOPNOTSUPP; + + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + + break; + case WLAN_CIPHER_SUITE_CCMP: + key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; + break; + case WLAN_CIPHER_SUITE_TKIP: + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + default: + return -EOPNOTSUPP; + } + + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { + dev_dbg(dev, "%s: pairwise key\n", __func__); + ether_addr_copy(mac_addr, sta->addr); + } else { + dev_dbg(dev, "%s: group key\n", __func__); + eth_broadcast_addr(mac_addr); + } + + val16 = rtl8xxxu_read16(priv, REG_CR); + val16 |= CR_SECURITY_ENABLE; + rtl8xxxu_write16(priv, REG_CR, val16); + + val8 = SEC_CFG_TX_SEC_ENABLE | SEC_CFG_TXBC_USE_DEFKEY | + SEC_CFG_RX_SEC_ENABLE | SEC_CFG_RXBC_USE_DEFKEY; + val8 |= SEC_CFG_TX_USE_DEFKEY | SEC_CFG_RX_USE_DEFKEY; + rtl8xxxu_write8(priv, REG_SECURITY_CFG, val8); + + switch (cmd) { + case SET_KEY: + key->hw_key_idx = key->keyidx; + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + rtl8xxxu_cam_write(priv, key, mac_addr); + retval = 0; + break; + case DISABLE_KEY: + rtl8xxxu_write32(priv, REG_CAM_WRITE, 0x00000000); + val32 = CAM_CMD_POLLING | CAM_CMD_WRITE | + key->keyidx << CAM_CMD_KEY_SHIFT; + rtl8xxxu_write32(priv, REG_CAM_CMD, val32); + retval = 0; + break; + default: + dev_warn(dev, "%s: Unsupported command %02x\n", __func__, cmd); + } + + return retval; +} + +static int +rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, + bool amsdu) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct device *dev = &priv->udev->dev; + u8 ampdu_factor, ampdu_density; + + switch (action) { + case IEEE80211_AMPDU_TX_START: + dev_info(dev, "%s: IEEE80211_AMPDU_TX_START\n", __func__); + ampdu_factor = sta->ht_cap.ampdu_factor; + ampdu_density = sta->ht_cap.ampdu_density; + rtl8xxxu_set_ampdu_factor(priv, ampdu_factor); + rtl8xxxu_set_ampdu_min_space(priv, ampdu_density); + dev_dbg(dev, + "Changed HT: ampdu_factor %02x, ampdu_density %02x\n", + ampdu_factor, ampdu_density); + break; + case IEEE80211_AMPDU_TX_STOP_FLUSH: + dev_info(dev, "%s: IEEE80211_AMPDU_TX_STOP_FLUSH\n", __func__); + rtl8xxxu_set_ampdu_factor(priv, 0); + rtl8xxxu_set_ampdu_min_space(priv, 0); + break; + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + dev_info(dev, "%s: IEEE80211_AMPDU_TX_STOP_FLUSH_CONT\n", + __func__); + rtl8xxxu_set_ampdu_factor(priv, 0); + rtl8xxxu_set_ampdu_min_space(priv, 0); + break; + case IEEE80211_AMPDU_RX_START: + dev_info(dev, "%s: IEEE80211_AMPDU_RX_START\n", __func__); + break; + case IEEE80211_AMPDU_RX_STOP: + dev_info(dev, "%s: IEEE80211_AMPDU_RX_STOP\n", __func__); + break; + default: + break; + } + return 0; +} + +static int rtl8xxxu_start(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + struct rtl8xxxu_rx_urb *rx_urb; + struct rtl8xxxu_tx_urb *tx_urb; + unsigned long flags; + int ret, i; + + ret = 0; + + init_usb_anchor(&priv->rx_anchor); + init_usb_anchor(&priv->tx_anchor); + init_usb_anchor(&priv->int_anchor); + + rtl8723a_enable_rf(priv); + ret = rtl8xxxu_submit_int_urb(hw); + if (ret) + goto exit; + + for (i = 0; i < RTL8XXXU_TX_URBS; i++) { + tx_urb = kmalloc(sizeof(struct rtl8xxxu_tx_urb), GFP_KERNEL); + if (!tx_urb) { + if (!i) + ret = -ENOMEM; + + goto error_out; + } + usb_init_urb(&tx_urb->urb); + INIT_LIST_HEAD(&tx_urb->list); + tx_urb->hw = hw; + list_add(&tx_urb->list, &priv->tx_urb_free_list); + priv->tx_urb_free_count++; + } + + priv->tx_stopped = false; + + spin_lock_irqsave(&priv->rx_urb_lock, flags); + priv->shutdown = false; + spin_unlock_irqrestore(&priv->rx_urb_lock, flags); + + for (i = 0; i < RTL8XXXU_RX_URBS; i++) { + rx_urb = kmalloc(sizeof(struct rtl8xxxu_rx_urb), GFP_KERNEL); + if (!rx_urb) { + if (!i) + ret = -ENOMEM; + + goto error_out; + } + usb_init_urb(&rx_urb->urb); + INIT_LIST_HEAD(&rx_urb->list); + rx_urb->hw = hw; + + ret = rtl8xxxu_submit_rx_urb(priv, rx_urb); + } +exit: + /* + * Disable all data frames + */ + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000); + /* + * Accept all mgmt frames + */ + rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0xffff); + + rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, 0x6954341e); + + return ret; + +error_out: + rtl8xxxu_free_tx_resources(priv); + /* + * Disable all data and mgmt frames + */ + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000); + rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0x0000); + + return ret; +} + +static void rtl8xxxu_stop(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + unsigned long flags; + + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + + rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0x0000); + rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000); + + spin_lock_irqsave(&priv->rx_urb_lock, flags); + priv->shutdown = true; + spin_unlock_irqrestore(&priv->rx_urb_lock, flags); + + usb_kill_anchored_urbs(&priv->rx_anchor); + usb_kill_anchored_urbs(&priv->tx_anchor); + usb_kill_anchored_urbs(&priv->int_anchor); + + rtl8723a_disable_rf(priv); + + /* + * Disable interrupts + */ + rtl8xxxu_write32(priv, REG_USB_HIMR, 0); + + rtl8xxxu_free_rx_resources(priv); + rtl8xxxu_free_tx_resources(priv); +} + +static const struct ieee80211_ops rtl8xxxu_ops = { + .tx = rtl8xxxu_tx, + .add_interface = rtl8xxxu_add_interface, + .remove_interface = rtl8xxxu_remove_interface, + .config = rtl8xxxu_config, + .conf_tx = rtl8xxxu_conf_tx, + .bss_info_changed = rtl8xxxu_bss_info_changed, + .configure_filter = rtl8xxxu_configure_filter, + .set_rts_threshold = rtl8xxxu_set_rts_threshold, + .start = rtl8xxxu_start, + .stop = rtl8xxxu_stop, + .sw_scan_start = rtl8xxxu_sw_scan_start, + .sw_scan_complete = rtl8xxxu_sw_scan_complete, + .set_key = rtl8xxxu_set_key, + .ampdu_action = rtl8xxxu_ampdu_action, +}; + +static int rtl8xxxu_parse_usb(struct rtl8xxxu_priv *priv, + struct usb_interface *interface) +{ + struct usb_interface_descriptor *interface_desc; + struct usb_host_interface *host_interface; + struct usb_endpoint_descriptor *endpoint; + struct device *dev = &priv->udev->dev; + int i, j = 0, endpoints; + u8 dir, xtype, num; + int ret = 0; + + host_interface = &interface->altsetting[0]; + interface_desc = &host_interface->desc; + endpoints = interface_desc->bNumEndpoints; + + for (i = 0; i < endpoints; i++) { + endpoint = &host_interface->endpoint[i].desc; + + dir = endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK; + num = usb_endpoint_num(endpoint); + xtype = usb_endpoint_type(endpoint); + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB) + dev_dbg(dev, + "%s: endpoint: dir %02x, # %02x, type %02x\n", + __func__, dir, num, xtype); + if (usb_endpoint_dir_in(endpoint) && + usb_endpoint_xfer_bulk(endpoint)) { + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB) + dev_dbg(dev, "%s: in endpoint num %i\n", + __func__, num); + + if (priv->pipe_in) { + dev_warn(dev, + "%s: Too many IN pipes\n", __func__); + ret = -EINVAL; + goto exit; + } + + priv->pipe_in = usb_rcvbulkpipe(priv->udev, num); + } + + if (usb_endpoint_dir_in(endpoint) && + usb_endpoint_xfer_int(endpoint)) { + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB) + dev_dbg(dev, "%s: interrupt endpoint num %i\n", + __func__, num); + + if (priv->pipe_interrupt) { + dev_warn(dev, "%s: Too many INTERRUPT pipes\n", + __func__); + ret = -EINVAL; + goto exit; + } + + priv->pipe_interrupt = usb_rcvintpipe(priv->udev, num); + } + + if (usb_endpoint_dir_out(endpoint) && + usb_endpoint_xfer_bulk(endpoint)) { + if (rtl8xxxu_debug & RTL8XXXU_DEBUG_USB) + dev_dbg(dev, "%s: out endpoint num %i\n", + __func__, num); + if (j >= RTL8XXXU_OUT_ENDPOINTS) { + dev_warn(dev, + "%s: Too many OUT pipes\n", __func__); + ret = -EINVAL; + goto exit; + } + priv->out_ep[j++] = num; + } + } +exit: + priv->nr_out_eps = j; + return ret; +} + +static int rtl8xxxu_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct rtl8xxxu_priv *priv; + struct ieee80211_hw *hw; + struct usb_device *udev; + struct ieee80211_supported_band *sband; + int ret = 0; + int untested = 1; + + udev = usb_get_dev(interface_to_usbdev(interface)); + + switch (id->idVendor) { + case USB_VENDOR_ID_REALTEK: + switch(id->idProduct) { + case 0x1724: + case 0x8176: + case 0x8178: + case 0x817f: + untested = 0; + break; + } + break; + case 0x7392: + if (id->idProduct == 0x7811) + untested = 0; + break; + default: + break; + } + + if (untested) { + rtl8xxxu_debug = RTL8XXXU_DEBUG_EFUSE; + dev_info(&udev->dev, + "This Realtek USB WiFi dongle (0x%04x:0x%04x) is untested!\n", + id->idVendor, id->idProduct); + dev_info(&udev->dev, + "Please report results to Jes.Sorensen@gmail.com\n"); + } + + hw = ieee80211_alloc_hw(sizeof(struct rtl8xxxu_priv), &rtl8xxxu_ops); + if (!hw) { + ret = -ENOMEM; + goto exit; + } + + priv = hw->priv; + priv->hw = hw; + priv->udev = udev; + priv->fops = (struct rtl8xxxu_fileops *)id->driver_info; + mutex_init(&priv->usb_buf_mutex); + mutex_init(&priv->h2c_mutex); + INIT_LIST_HEAD(&priv->tx_urb_free_list); + spin_lock_init(&priv->tx_urb_lock); + INIT_LIST_HEAD(&priv->rx_urb_pending_list); + spin_lock_init(&priv->rx_urb_lock); + INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work); + + usb_set_intfdata(interface, hw); + + ret = rtl8xxxu_parse_usb(priv, interface); + if (ret) + goto exit; + + ret = rtl8xxxu_identify_chip(priv); + if (ret) { + dev_err(&udev->dev, "Fatal - failed to identify chip\n"); + goto exit; + } + + ret = rtl8xxxu_read_efuse(priv); + if (ret) { + dev_err(&udev->dev, "Fatal - failed to read EFuse\n"); + goto exit; + } + + ret = priv->fops->parse_efuse(priv); + if (ret) { + dev_err(&udev->dev, "Fatal - failed to parse EFuse\n"); + goto exit; + } + + rtl8xxxu_print_chipinfo(priv); + + ret = priv->fops->load_firmware(priv); + if (ret) { + dev_err(&udev->dev, "Fatal - failed to load firmware\n"); + goto exit; + } + + ret = rtl8xxxu_init_device(hw); + + hw->wiphy->max_scan_ssids = 1; + hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + hw->queues = 4; + + sband = &rtl8xxxu_supported_band; + sband->ht_cap.ht_supported = true; + sband->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + sband->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; + sband->ht_cap.cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40; + memset(&sband->ht_cap.mcs, 0, sizeof(sband->ht_cap.mcs)); + sband->ht_cap.mcs.rx_mask[0] = 0xff; + sband->ht_cap.mcs.rx_mask[4] = 0x01; + if (priv->rf_paths > 1) { + sband->ht_cap.mcs.rx_mask[1] = 0xff; + sband->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + } + sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; + /* + * Some APs will negotiate HT20_40 in a noisy environment leading + * to miserable performance. Rather than defaulting to this, only + * enable it if explicitly requested at module load time. + */ + if (rtl8xxxu_ht40_2g) { + dev_info(&udev->dev, "Enabling HT_20_40 on the 2.4GHz band\n"); + sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; + } + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + + hw->wiphy->rts_threshold = 2347; + + SET_IEEE80211_DEV(priv->hw, &interface->dev); + SET_IEEE80211_PERM_ADDR(hw, priv->mac_addr); + + hw->extra_tx_headroom = sizeof(struct rtl8xxxu_tx_desc); + ieee80211_hw_set(hw, SIGNAL_DBM); + /* + * The firmware handles rate control + */ + ieee80211_hw_set(hw, HAS_RATE_CONTROL); + ieee80211_hw_set(hw, AMPDU_AGGREGATION); + + ret = ieee80211_register_hw(priv->hw); + if (ret) { + dev_err(&udev->dev, "%s: Failed to register: %i\n", + __func__, ret); + goto exit; + } + +exit: + if (ret < 0) + usb_put_dev(udev); + return ret; +} + +static void rtl8xxxu_disconnect(struct usb_interface *interface) +{ + struct rtl8xxxu_priv *priv; + struct ieee80211_hw *hw; + + hw = usb_get_intfdata(interface); + priv = hw->priv; + + rtl8xxxu_disable_device(hw); + usb_set_intfdata(interface, NULL); + + dev_info(&priv->udev->dev, "disconnecting\n"); + + ieee80211_unregister_hw(hw); + + kfree(priv->fw_data); + mutex_destroy(&priv->usb_buf_mutex); + mutex_destroy(&priv->h2c_mutex); + + usb_put_dev(priv->udev); + ieee80211_free_hw(hw); +} + +static struct rtl8xxxu_fileops rtl8723au_fops = { + .parse_efuse = rtl8723au_parse_efuse, + .load_firmware = rtl8723au_load_firmware, + .power_on = rtl8723au_power_on, + .writeN_block_size = 1024, +}; + +static struct rtl8xxxu_fileops rtl8192cu_fops = { + .parse_efuse = rtl8192cu_parse_efuse, + .load_firmware = rtl8192cu_load_firmware, + .power_on = rtl8192cu_power_on, + .writeN_block_size = 128, +}; + +static struct usb_device_id dev_table[] = { +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8724, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8723au_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x1724, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8723au_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x0724, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8723au_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8178, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817f, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +/* Tested by Larry Finger */ +{USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7811, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +#ifdef CONFIG_RTL8XXXU_UNTESTED +/* Currently untested 8188 series devices */ +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8191, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8170, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8177, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817a, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817b, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817d, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817e, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818a, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x317f, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x1058, 0x0631, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x094c, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1102, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe033, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8189, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9041, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17ba, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x1e1e, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x5088, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0052, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x005c, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0eb0, 0x9071, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x103c, 0x1629, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x13d3, 0x3357, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3308, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330b, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0x4902, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2a, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2e, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xed17, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x648b, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x4855, 0x0090, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x4856, 0x0091, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0xcdab, 0x8010, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x317f, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, /* Netcore 8188RU */ +{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff7, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff9, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaffa, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff8, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaffb, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaffc, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0x1201, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +/* Currently untested 8192 series devices */ +{USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0950, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1004, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x2102, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x2103, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0586, 0x341f, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe035, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17ab, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0061, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0070, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0789, 0x016d, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x07aa, 0x0056, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8178, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9021, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0xf001, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x2e2e, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0019, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0020, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3307, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3309, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330a, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2b, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x624d, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0100, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x4855, 0x0091, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7822, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192cu_fops}, +#endif +{ } +}; + +static struct usb_driver rtl8xxxu_driver = { + .name = DRIVER_NAME, + .probe = rtl8xxxu_probe, + .disconnect = rtl8xxxu_disconnect, + .id_table = dev_table, + .disable_hub_initiated_lpm = 1, +}; + +static int __init rtl8xxxu_module_init(void) +{ + int res; + + res = usb_register(&rtl8xxxu_driver); + if (res < 0) + pr_err(DRIVER_NAME ": usb_register() failed (%i)\n", res); + + return res; +} + +static void __exit rtl8xxxu_module_exit(void) +{ + usb_deregister(&rtl8xxxu_driver); +} + + +MODULE_DEVICE_TABLE(usb, dev_table); + +module_init(rtl8xxxu_module_init); +module_exit(rtl8xxxu_module_exit); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h new file mode 100644 index 000000000000..f2a1bac6c8ec --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -0,0 +1,676 @@ +/* + * Copyright (c) 2014 - 2015 Jes Sorensen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * Register definitions taken from original Realtek rtl8723au driver + */ + +#include + +#define RTL8XXXU_DEBUG_REG_WRITE 0x01 +#define RTL8XXXU_DEBUG_REG_READ 0x02 +#define RTL8XXXU_DEBUG_RFREG_WRITE 0x04 +#define RTL8XXXU_DEBUG_RFREG_READ 0x08 +#define RTL8XXXU_DEBUG_CHANNEL 0x10 +#define RTL8XXXU_DEBUG_TX 0x20 +#define RTL8XXXU_DEBUG_TX_DUMP 0x40 +#define RTL8XXXU_DEBUG_RX 0x80 +#define RTL8XXXU_DEBUG_RX_DUMP 0x100 +#define RTL8XXXU_DEBUG_USB 0x200 +#define RTL8XXXU_DEBUG_KEY 0x400 +#define RTL8XXXU_DEBUG_H2C 0x800 +#define RTL8XXXU_DEBUG_ACTION 0x1000 +#define RTL8XXXU_DEBUG_EFUSE 0x2000 + +#define RTW_USB_CONTROL_MSG_TIMEOUT 500 +#define RTL8XXXU_MAX_REG_POLL 500 +#define USB_INTR_CONTENT_LENGTH 56 + +#define RTL8XXXU_OUT_ENDPOINTS 3 + +#define REALTEK_USB_READ 0xc0 +#define REALTEK_USB_WRITE 0x40 +#define REALTEK_USB_CMD_REQ 0x05 +#define REALTEK_USB_CMD_IDX 0x00 + +#define TX_TOTAL_PAGE_NUM 0xf8 +/* (HPQ + LPQ + NPQ + PUBQ) = TX_TOTAL_PAGE_NUM */ +#define TX_PAGE_NUM_PUBQ 0xe7 +#define TX_PAGE_NUM_HI_PQ 0x0c +#define TX_PAGE_NUM_LO_PQ 0x02 +#define TX_PAGE_NUM_NORM_PQ 0x02 + +#define RTL_FW_PAGE_SIZE 4096 +#define RTL8XXXU_FIRMWARE_POLL_MAX 1000 + +#define RTL8723A_CHANNEL_GROUPS 3 +#define RTL8723A_MAX_RF_PATHS 2 +#define RF6052_MAX_TX_PWR 0x3f + +#define EFUSE_MAP_LEN_8723A 256 +#define EFUSE_MAX_SECTION_8723A 32 +#define EFUSE_REAL_CONTENT_LEN_8723A 512 +#define EFUSE_BT_MAP_LEN_8723A 1024 +#define EFUSE_MAX_WORD_UNIT 4 + +struct rtl8xxxu_rx_desc { +#ifdef __LITTLE_ENDIAN + u32 pktlen:14; + u32 crc32:1; + u32 icverr:1; + u32 drvinfo_sz:4; + u32 security:3; + u32 qos:1; + u32 shift:2; + u32 phy_stats:1; + u32 swdec:1; + u32 ls:1; + u32 fs:1; + u32 eor:1; + u32 own:1; + + u32 macid:5; + u32 tid:4; + u32 hwrsvd:4; + u32 amsdu:1; + u32 paggr:1; + u32 faggr:1; + u32 a1fit:4; + u32 a2fit:4; + u32 pam:1; + u32 pwr:1; + u32 md:1; + u32 mf:1; + u32 type:2; + u32 mc:1; + u32 bc:1; + + u32 seq:12; + u32 frag:4; + u32 nextpktlen:14; + u32 nextind:1; + u32 reserved0:1; + + u32 rxmcs:6; + u32 rxht:1; + u32 gf:1; + u32 splcp:1; + u32 bw:1; + u32 htc:1; + u32 eosp:1; + u32 bssidfit:2; + u32 reserved1:16; + u32 unicastwake:1; + u32 magicwake:1; + + u32 pattern0match:1; + u32 pattern1match:1; + u32 pattern2match:1; + u32 pattern3match:1; + u32 pattern4match:1; + u32 pattern5match:1; + u32 pattern6match:1; + u32 pattern7match:1; + u32 pattern8match:1; + u32 pattern9match:1; + u32 patternamatch:1; + u32 patternbmatch:1; + u32 patterncmatch:1; + u32 reserved2:19; +#else + u32 own:1; + u32 eor:1; + u32 fs:1; + u32 ls:1; + u32 swdec:1; + u32 phy_stats:1; + u32 shift:2; + u32 qos:1; + u32 security:3; + u32 drvinfo_sz:4; + u32 icverr:1; + u32 crc32:1; + u32 pktlen:14; + + u32 bc:1; + u32 mc:1; + u32 type:2; + u32 mf:1; + u32 md:1; + u32 pwr:1; + u32 pam:1; + u32 a2fit:4; + u32 a1fit:4; + u32 faggr:1; + u32 paggr:1; + u32 amsdu:1; + u32 hwrsvd:4; + u32 tid:4; + u32 macid:5; + + u32 reserved0:1; + u32 nextind:1; + u32 nextpktlen:14; + u32 frag:4; + u32 seq:12; + + u32 magicwake:1; + u32 unicastwake:1; + u32 reserved1:16; + u32 bssidfit:2; + u32 eosp:1; + u32 htc:1; + u32 bw:1; + u32 splcp:1; + u32 gf:1; + u32 rxht:1; + u32 rxmcs:6; + + u32 reserved2:19; + u32 patterncmatch:1; + u32 patternbmatch:1; + u32 patternamatch:1; + u32 pattern9match:1; + u32 pattern8match:1; + u32 pattern7match:1; + u32 pattern6match:1; + u32 pattern5match:1; + u32 pattern4match:1; + u32 pattern3match:1; + u32 pattern2match:1; + u32 pattern1match:1; + u32 pattern0match:1; +#endif + __le32 tsfl; +#if 0 + u32 bassn:12; + u32 bavld:1; + u32 reserved3:19; +#endif +}; + +struct rtl8xxxu_tx_desc { + __le16 pkt_size; + u8 pkt_offset; + u8 txdw0; + __le32 txdw1; + __le32 txdw2; + __le32 txdw3; + __le32 txdw4; + __le32 txdw5; + __le32 txdw6; + __le16 csum; + __le16 txdw7; +}; + +/* CCK Rates, TxHT = 0 */ +#define DESC_RATE_1M 0x00 +#define DESC_RATE_2M 0x01 +#define DESC_RATE_5_5M 0x02 +#define DESC_RATE_11M 0x03 + +/* OFDM Rates, TxHT = 0 */ +#define DESC_RATE_6M 0x04 +#define DESC_RATE_9M 0x05 +#define DESC_RATE_12M 0x06 +#define DESC_RATE_18M 0x07 +#define DESC_RATE_24M 0x08 +#define DESC_RATE_36M 0x09 +#define DESC_RATE_48M 0x0a +#define DESC_RATE_54M 0x0b + +/* MCS Rates, TxHT = 1 */ +#define DESC_RATE_MCS0 0x0c +#define DESC_RATE_MCS1 0x0d +#define DESC_RATE_MCS2 0x0e +#define DESC_RATE_MCS3 0x0f +#define DESC_RATE_MCS4 0x10 +#define DESC_RATE_MCS5 0x11 +#define DESC_RATE_MCS6 0x12 +#define DESC_RATE_MCS7 0x13 +#define DESC_RATE_MCS8 0x14 +#define DESC_RATE_MCS9 0x15 +#define DESC_RATE_MCS10 0x16 +#define DESC_RATE_MCS11 0x17 +#define DESC_RATE_MCS12 0x18 +#define DESC_RATE_MCS13 0x19 +#define DESC_RATE_MCS14 0x1a +#define DESC_RATE_MCS15 0x1b +#define DESC_RATE_MCS15_SG 0x1c +#define DESC_RATE_MCS32 0x20 + +#define TXDESC_OFFSET_SZ 0 +#define TXDESC_OFFSET_SHT 16 +#if 0 +#define TXDESC_BMC BIT(24) +#define TXDESC_LSG BIT(26) +#define TXDESC_FSG BIT(27) +#define TXDESC_OWN BIT(31) +#else +#define TXDESC_BROADMULTICAST BIT(0) +#define TXDESC_LAST_SEGMENT BIT(2) +#define TXDESC_FIRST_SEGMENT BIT(3) +#define TXDESC_OWN BIT(7) +#endif + +/* Word 1 */ +#define TXDESC_PKT_OFFSET_SZ 0 +#define TXDESC_AGG_ENABLE BIT(5) +#define TXDESC_BK BIT(6) +#define TXDESC_QUEUE_SHIFT 8 +#define TXDESC_QUEUE_MASK 0x1f00 +#define TXDESC_QUEUE_BK 0x2 +#define TXDESC_QUEUE_BE 0x0 +#define TXDESC_QUEUE_VI 0x5 +#define TXDESC_QUEUE_VO 0x7 +#define TXDESC_QUEUE_BEACON 0x10 +#define TXDESC_QUEUE_HIGH 0x11 +#define TXDESC_QUEUE_MGNT 0x12 +#define TXDESC_QUEUE_CMD 0x13 +#define TXDESC_QUEUE_MAX (TXDESC_QUEUE_CMD + 1) + +#define DESC_RATE_ID_SHIFT 16 +#define DESC_RATE_ID_MASK 0xf +#define TXDESC_NAVUSEHDR BIT(20) +#define TXDESC_SEC_RC4 0x00400000 +#define TXDESC_SEC_AES 0x00c00000 +#define TXDESC_PKT_OFFSET_SHIFT 26 +#define TXDESC_AGG_EN BIT(29) +#define TXDESC_HWPC BIT(31) + +/* Word 2 */ +#define TXDESC_ACK_REPORT BIT(19) +#define TXDESC_AMPDU_DENSITY_SHIFT 20 + +/* Word 3 */ +#define TXDESC_SEQ_SHIFT 16 +#define TXDESC_SEQ_MASK 0x0fff0000 + +/* Word 4 */ +#define TXDESC_QOS BIT(6) +#define TXDESC_HW_SEQ_ENABLE BIT(7) +#define TXDESC_USE_DRIVER_RATE BIT(8) +#define TXDESC_DISABLE_DATA_FB BIT(10) +#define TXDESC_CTS_SELF_ENABLE BIT(11) +#define TXDESC_RTS_CTS_ENABLE BIT(12) +#define TXDESC_HW_RTS_ENABLE BIT(13) +#define TXDESC_PRIME_CH_OFF_LOWER BIT(20) +#define TXDESC_PRIME_CH_OFF_UPPER BIT(21) +#define TXDESC_SHORT_PREAMBLE BIT(24) +#define TXDESC_DATA_BW BIT(25) +#define TXDESC_RTS_DATA_BW BIT(27) +#define TXDESC_RTS_PRIME_CH_OFF_LOWER BIT(28) +#define TXDESC_RTS_PRIME_CH_OFF_UPPER BIT(29) + +/* Word 5 */ +#define TXDESC_RTS_RATE_SHIFT 0 +#define TXDESC_RTS_RATE_MASK 0x3f +#define TXDESC_SHORT_GI BIT(6) +#define TXDESC_CCX_TAG BIT(7) +#define TXDESC_RETRY_LIMIT_ENABLE BIT(17) +#define TXDESC_RETRY_LIMIT_SHIFT 18 +#define TXDESC_RETRY_LIMIT_MASK 0x00fc0000 + +/* Word 6 */ +#define TXDESC_MAX_AGG_SHIFT 11 + +struct phy_rx_agc_info { +#ifdef __LITTLE_ENDIAN + u8 gain:7, trsw:1; +#else + u8 trsw:1, gain:7; +#endif +}; + +struct rtl8723au_phy_stats { + struct phy_rx_agc_info path_agc[RTL8723A_MAX_RF_PATHS]; + u8 ch_corr[RTL8723A_MAX_RF_PATHS]; + u8 cck_sig_qual_ofdm_pwdb_all; + u8 cck_agc_rpt_ofdm_cfosho_a; + u8 cck_rpt_b_ofdm_cfosho_b; + u8 reserved_1; + u8 noise_power_db_msb; + u8 path_cfotail[RTL8723A_MAX_RF_PATHS]; + u8 pcts_mask[RTL8723A_MAX_RF_PATHS]; + s8 stream_rxevm[RTL8723A_MAX_RF_PATHS]; + u8 path_rxsnr[RTL8723A_MAX_RF_PATHS]; + u8 noise_power_db_lsb; + u8 reserved_2[3]; + u8 stream_csi[RTL8723A_MAX_RF_PATHS]; + u8 stream_target_csi[RTL8723A_MAX_RF_PATHS]; + s8 sig_evm; + u8 reserved_3; + +#ifdef __LITTLE_ENDIAN + u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */ + u8 sgi_en:1; + u8 rxsc:2; + u8 idle_long:1; + u8 r_ant_train_en:1; + u8 antenna_select_b:1; + u8 antenna_select:1; +#else /* _BIG_ENDIAN_ */ + u8 antenna_select:1; + u8 antenna_select_b:1; + u8 r_ant_train_en:1; + u8 idle_long:1; + u8 rxsc:2; + u8 sgi_en:1; + u8 antsel_rx_keep_2:1; /* ex_intf_flg:1; */ +#endif +}; + +/* + * Regs to backup + */ +#define RTL8XXXU_ADDA_REGS 16 +#define RTL8XXXU_MAC_REGS 4 +#define RTL8XXXU_BB_REGS 9 + +struct rtl8xxxu_firmware_header { + __le16 signature; /* 92C0: test chip; 92C, + 88C0: test chip; + 88C1: MP A-cut; + 92C1: MP A-cut */ + u8 category; /* AP/NIC and USB/PCI */ + u8 function; + + __le16 major_version; /* FW Version */ + u8 minor_version; /* FW Subversion, default 0x00 */ + u8 reserved1; + + u8 month; /* Release time Month field */ + u8 date; /* Release time Date field */ + u8 hour; /* Release time Hour field */ + u8 minute; /* Release time Minute field */ + + __le16 ramcodesize; /* Size of RAM code */ + u16 reserved2; + + __le32 svn_idx; /* SVN entry index */ + u32 reserved3; + + u32 reserved4; + u32 reserved5; + + u8 data[0]; +}; + +/* + * The 8723au has 3 channel groups: 1-3, 4-9, and 10-14 + */ +struct rtl8723au_idx { +#ifdef __LITTLE_ENDIAN + int a:4; + int b:4; +#else + int b:4; + int a:4; +#endif +} __attribute__((packed)); + +struct rtl8723au_efuse { + __le16 rtl_id; + u8 res0[0xe]; + u8 cck_tx_power_index_A[3]; /* 0x10 */ + u8 cck_tx_power_index_B[3]; + u8 ht40_1s_tx_power_index_A[3]; /* 0x16 */ + u8 ht40_1s_tx_power_index_B[3]; + /* + * The following entries are half-bytes split as: + * bits 0-3: path A, bits 4-7: path B, all values 4 bits signed + */ + struct rtl8723au_idx ht20_tx_power_index_diff[3]; + struct rtl8723au_idx ofdm_tx_power_index_diff[3]; + struct rtl8723au_idx ht40_max_power_offset[3]; + struct rtl8723au_idx ht20_max_power_offset[3]; + u8 channel_plan; /* 0x28 */ + u8 tssi_a; + u8 thermal_meter; + u8 rf_regulatory; + u8 rf_option_2; + u8 rf_option_3; + u8 rf_option_4; + u8 res7; + u8 version /* 0x30 */; + u8 customer_id_major; + u8 customer_id_minor; + u8 xtal_k; + u8 chipset; /* 0x34 */ + u8 res8[0x82]; + u8 vid; /* 0xb7 */ + u8 res9; + u8 pid; /* 0xb9 */ + u8 res10[0x0c]; + u8 mac_addr[ETH_ALEN]; /* 0xc6 */ + u8 res11[2]; + u8 vendor_name[7]; + u8 res12[2]; + u8 device_name[0x29]; /* 0xd7 */ +}; + +struct rtl8192cu_efuse { + __le16 rtl_id; + __le16 hpon; + u8 res0[2]; + __le16 clk; + __le16 testr; + __le16 vid; + __le16 did; + __le16 svid; + __le16 smid; /* 0x10 */ + u8 res1[4]; + u8 mac_addr[ETH_ALEN]; /* 0x16 */ + u8 res2[2]; + u8 vendor_name[7]; + u8 res3[3]; + u8 device_name[0x14]; /* 0x28 */ + u8 res4[0x1e]; /* 0x3c */ + u8 cck_tx_power_index_A[3]; /* 0x5a */ + u8 cck_tx_power_index_B[3]; + u8 ht40_1s_tx_power_index_A[3]; /* 0x60 */ + u8 ht40_1s_tx_power_index_B[3]; + /* + * The following entries are half-bytes split as: + * bits 0-3: path A, bits 4-7: path B, all values 4 bits signed + */ + struct rtl8723au_idx ht40_2s_tx_power_index_diff[3]; + struct rtl8723au_idx ht20_tx_power_index_diff[3]; /* 0x69 */ + struct rtl8723au_idx ofdm_tx_power_index_diff[3]; + struct rtl8723au_idx ht40_max_power_offset[3]; /* 0x6f */ + struct rtl8723au_idx ht20_max_power_offset[3]; + u8 channel_plan; /* 0x75 */ + u8 tssi_a; + u8 tssi_b; + u8 thermal_meter; /* xtal_k */ /* 0x78 */ + u8 rf_regulatory; + u8 rf_option_2; + u8 rf_option_3; + u8 rf_option_4; + u8 res5[1]; /* 0x7d */ + u8 version; + u8 customer_id; +}; + +struct rtl8xxxu_reg8val { + u16 reg; + u8 val; +}; + +struct rtl8xxxu_reg32val { + u16 reg; + u32 val; +}; + +struct rtl8xxxu_rfregval { + u8 reg; + u32 val; +}; + +enum rtl8xxxu_rfpath { + RF_A = 0, + RF_B = 1, +}; + +struct rtl8xxxu_rfregs { + u16 hssiparm1; + u16 hssiparm2; + u16 lssiparm; + u16 hspiread; + u16 lssiread; + u16 rf_sw_ctrl; +}; + +#define H2C_MAX_MBOX 4 +#define H2C_EXT BIT(7) +#define H2C_SET_POWER_MODE 1 +#define H2C_JOIN_BSS_REPORT 2 +#define H2C_JOIN_BSS_DISCONNECT 0 +#define H2C_JOIN_BSS_CONNECT 1 +#define H2C_SET_RSSI 5 +#define H2C_SET_RATE_MASK (6 | H2C_EXT) + +struct h2c_cmd { + union { + struct { + u8 cmd; + u8 data[5]; + } __packed cmd; + struct { + __le32 data; + __le16 ext; + } __packed raw; + struct { + u8 cmd; + u8 data; + u8 pad[4]; + } __packed joinbss; + struct { + u8 cmd; + __le16 mask_hi; + u8 arg; + __le16 mask_lo; + } __packed ramask; + }; +}; + +struct rtl8xxxu_fileops; + +struct rtl8xxxu_priv { + struct ieee80211_hw *hw; + struct usb_device *udev; + struct rtl8xxxu_fileops *fops; + + spinlock_t tx_urb_lock; + struct list_head tx_urb_free_list; + int tx_urb_free_count; + bool tx_stopped; + + spinlock_t rx_urb_lock; + struct list_head rx_urb_pending_list; + int rx_urb_pending_count; + bool shutdown; + struct work_struct rx_urb_wq; + + u8 mac_addr[ETH_ALEN]; + char chip_name[8]; + u8 cck_tx_power_index_A[3]; /* 0x10 */ + u8 cck_tx_power_index_B[3]; + u8 ht40_1s_tx_power_index_A[3]; /* 0x16 */ + u8 ht40_1s_tx_power_index_B[3]; + /* + * The following entries are half-bytes split as: + * bits 0-3: path A, bits 4-7: path B, all values 4 bits signed + */ + struct rtl8723au_idx ht40_2s_tx_power_index_diff[3]; + struct rtl8723au_idx ht20_tx_power_index_diff[3]; + struct rtl8723au_idx ofdm_tx_power_index_diff[3]; + struct rtl8723au_idx ht40_max_power_offset[3]; + struct rtl8723au_idx ht20_max_power_offset[3]; + u32 chip_cut:4; + u32 rom_rev:4; + u32 has_wifi:1; + u32 has_bluetooth:1; + u32 enable_bluetooth:1; + u32 has_gps:1; + u32 hi_pa:1; + u32 vendor_umc:1; + u32 has_polarity_ctrl:1; + u32 has_eeprom:1; + u32 boot_eeprom:1; + u32 ep_tx_high_queue:1; + u32 ep_tx_normal_queue:1; + u32 ep_tx_low_queue:1; + u32 path_a_hi_power:1; + u32 path_a_rf_paths:4; + unsigned int pipe_interrupt; + unsigned int pipe_in; + unsigned int pipe_out[TXDESC_QUEUE_MAX]; + u8 out_ep[RTL8XXXU_OUT_ENDPOINTS]; + u8 path_a_ig_value; + u8 ep_tx_count; + u8 rf_paths; + u8 rx_paths; + u8 tx_paths; + u32 rf_mode_ag[2]; + u32 rege94; + u32 rege9c; + u32 regeb4; + u32 regebc; + int next_mbox; + int nr_out_eps; + + struct mutex h2c_mutex; + + struct usb_anchor rx_anchor; + struct usb_anchor tx_anchor; + struct usb_anchor int_anchor; + struct rtl8xxxu_firmware_header *fw_data; + size_t fw_size; + struct mutex usb_buf_mutex; + union { + __le32 val32; + __le16 val16; + u8 val8; + } usb_buf; + union { + u8 raw[EFUSE_MAP_LEN_8723A]; + struct rtl8723au_efuse efuse8723; + struct rtl8192cu_efuse efuse8192; + } efuse_wifi; + u32 adda_backup[RTL8XXXU_ADDA_REGS]; + u32 mac_backup[RTL8XXXU_MAC_REGS]; + u32 bb_backup[RTL8XXXU_BB_REGS]; + u32 bb_recovery_backup[RTL8XXXU_BB_REGS]; + u32 rtlchip; + u8 pi_enabled:1; + u8 iqk_initialized:1; + u8 int_buf[USB_INTR_CONTENT_LENGTH]; +}; + +struct rtl8xxxu_rx_urb { + struct urb urb; + struct ieee80211_hw *hw; + struct list_head list; +}; + +struct rtl8xxxu_tx_urb { + struct urb urb; + struct ieee80211_hw *hw; + struct list_head list; +}; + +struct rtl8xxxu_fileops { + int (*parse_efuse) (struct rtl8xxxu_priv *priv); + int (*load_firmware) (struct rtl8xxxu_priv *priv); + int (*power_on) (struct rtl8xxxu_priv *priv); + int writeN_block_size; +}; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h new file mode 100644 index 000000000000..23208f79b97c --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -0,0 +1,981 @@ +/* + * Copyright (c) 2014 - 2015 Jes Sorensen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * Register definitions taken from original Realtek rtl8723au driver + */ + +/* 0x0000 ~ 0x00FF System Configuration */ +#define REG_SYS_ISO_CTRL 0x0000 +#define SYS_ISO_MD2PP BIT(0) +#define SYS_ISO_ANALOG_IPS BIT(5) +#define SYS_ISO_DIOR BIT(9) +#define SYS_ISO_PWC_EV25V BIT(14) +#define SYS_ISO_PWC_EV12V BIT(15) + +#define REG_SYS_FUNC 0x0002 +#define SYS_FUNC_BBRSTB BIT(0) +#define SYS_FUNC_BB_GLB_RSTN BIT(1) +#define SYS_FUNC_USBA BIT(2) +#define SYS_FUNC_UPLL BIT(3) +#define SYS_FUNC_USBD BIT(4) +#define SYS_FUNC_DIO_PCIE BIT(5) +#define SYS_FUNC_PCIEA BIT(6) +#define SYS_FUNC_PPLL BIT(7) +#define SYS_FUNC_PCIED BIT(8) +#define SYS_FUNC_DIOE BIT(9) +#define SYS_FUNC_CPU_ENABLE BIT(10) +#define SYS_FUNC_DCORE BIT(11) +#define SYS_FUNC_ELDR BIT(12) +#define SYS_FUNC_DIO_RF BIT(13) +#define SYS_FUNC_HWPDN BIT(14) +#define SYS_FUNC_MREGEN BIT(15) + +#define REG_APS_FSMCO 0x0004 +#define APS_FSMCO_PFM_ALDN BIT(1) +#define APS_FSMCO_PFM_WOWL BIT(3) +#define APS_FSMCO_ENABLE_POWERDOWN BIT(4) +#define APS_FSMCO_MAC_ENABLE BIT(8) +#define APS_FSMCO_MAC_OFF BIT(9) +#define APS_FSMCO_HW_SUSPEND BIT(11) +#define APS_FSMCO_PCIE BIT(12) +#define APS_FSMCO_HW_POWERDOWN BIT(15) +#define APS_FSMCO_WLON_RESET BIT(16) + +#define REG_SYS_CLKR 0x0008 +#define SYS_CLK_ANAD16V_ENABLE BIT(0) +#define SYS_CLK_ANA8M BIT(1) +#define SYS_CLK_MACSLP BIT(4) +#define SYS_CLK_LOADER_ENABLE BIT(5) +#define SYS_CLK_80M_SSC_DISABLE BIT(7) +#define SYS_CLK_80M_SSC_ENABLE_HO BIT(8) +#define SYS_CLK_PHY_SSC_RSTB BIT(9) +#define SYS_CLK_SEC_CLK_ENABLE BIT(10) +#define SYS_CLK_MAC_CLK_ENABLE BIT(11) +#define SYS_CLK_ENABLE BIT(12) +#define SYS_CLK_RING_CLK_ENABLE BIT(13) + +#define REG_9346CR 0x000a +#define EEPROM_BOOT BIT(4) +#define EEPROM_ENABLE BIT(5) + +#define REG_EE_VPD 0x000c +#define REG_AFE_MISC 0x0010 +#define REG_SPS0_CTRL 0x0011 +#define REG_SPS_OCP_CFG 0x0018 +#define REG_RSV_CTRL 0x001c + +#define REG_RF_CTRL 0x001f +#define RF_ENABLE BIT(0) +#define RF_RSTB BIT(1) +#define RF_SDMRSTB BIT(2) + +#define REG_LDOA15_CTRL 0x0020 +#define LDOA15_ENABLE BIT(0) +#define LDOA15_STANDBY BIT(1) +#define LDOA15_OBUF BIT(2) +#define LDOA15_REG_VOS BIT(3) +#define LDOA15_VOADJ_SHIFT 4 + +#define REG_LDOV12D_CTRL 0x0021 +#define LDOV12D_ENABLE BIT(0) +#define LDOV12D_STANDBY BIT(1) +#define LDOV12D_VADJ_SHIFT 4 + +#define REG_LDOHCI12_CTRL 0x0022 + +#define REG_LPLDO_CTRL 0x0023 +#define LPLDO_HSM BIT(2) +#define LPLDO_LSM_DIS BIT(3) + +#define REG_AFE_XTAL_CTRL 0x0024 +#define AFE_XTAL_ENABLE BIT(0) +#define AFE_XTAL_B_SELECT BIT(1) +#define AFE_XTAL_GATE_USB BIT(8) +#define AFE_XTAL_GATE_AFE BIT(11) +#define AFE_XTAL_RF_GATE BIT(14) +#define AFE_XTAL_GATE_DIG BIT(17) +#define AFE_XTAL_BT_GATE BIT(20) + +#define REG_AFE_PLL_CTRL 0x0028 +#define AFE_PLL_ENABLE BIT(0) +#define AFE_PLL_320_ENABLE BIT(1) +#define APE_PLL_FREF_SELECT BIT(2) +#define AFE_PLL_EDGE_SELECT BIT(3) +#define AFE_PLL_WDOGB BIT(4) +#define AFE_PLL_LPF_ENABLE BIT(5) + +#define REG_MAC_PHY_CTRL 0x002c + +#define REG_EFUSE_CTRL 0x0030 +#define REG_EFUSE_TEST 0x0034 +#define EFUSE_TRPT BIT(7) + /* 00: Wifi Efuse, 01: BT Efuse0, 10: BT Efuse1, 11: BT Efuse2 */ +#define EFUSE_CELL_SEL (BIT(8) | BIT(9)) +#define EFUSE_LDOE25_ENABLE BIT(31) +#define EFUSE_SELECT_MASK 0x0300 +#define EFUSE_WIFI_SELECT 0x0000 +#define EFUSE_BT0_SELECT 0x0100 +#define EFUSE_BT1_SELECT 0x0200 +#define EFUSE_BT2_SELECT 0x0300 + +#define EFUSE_ACCESS_ENABLE 0x69 /* RTL8723 only */ +#define EFUSE_ACCESS_DISABLE 0x00 /* RTL8723 only */ + +#define REG_PWR_DATA 0x0038 +#define REG_CAL_TIMER 0x003c +#define REG_ACLK_MON 0x003e +#define REG_GPIO_MUXCFG 0x0040 +#define REG_GPIO_IO_SEL 0x0042 +#define REG_MAC_PINMUX_CFG 0x0043 +#define REG_GPIO_PIN_CTRL 0x0044 +#define REG_GPIO_INTM 0x0048 +#define REG_LEDCFG0 0x004c +#define REG_LEDCFG1 0x004d +#define REG_LEDCFG2 0x004e +#define LEDCFG2_DPDT_SELECT BIT(7) +#define REG_LEDCFG3 0x004f +#define REG_LEDCFG REG_LEDCFG2 +#define REG_FSIMR 0x0050 +#define REG_FSISR 0x0054 +#define REG_HSIMR 0x0058 +#define REG_HSISR 0x005c +/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. */ +#define REG_GPIO_PIN_CTRL_2 0x0060 +/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. */ +#define REG_GPIO_IO_SEL_2 0x0062 + +/* RTL8723 only WIFI/BT/GPS Multi-Function control source. */ +#define REG_MULTI_FUNC_CTRL 0x0068 + +#define MULTI_FN_WIFI_HW_PWRDOWN_EN BIT(0) /* Enable GPIO[9] as WiFi HW + powerdown source */ +#define MULTI_FN_WIFI_HW_PWRDOWN_SL BIT(1) /* WiFi HW powerdown polarity + control */ +#define MULTI_WIFI_FUNC_EN BIT(2) /* WiFi function enable */ + +#define MULTI_WIFI_HW_ROF_EN BIT(3) /* Enable GPIO[9] as WiFi RF HW + powerdown source */ +#define MULTI_BT_HW_PWRDOWN_EN BIT(16) /* Enable GPIO[11] as BT HW + powerdown source */ +#define MULTI_BT_HW_PWRDOWN_SL BIT(17) /* BT HW powerdown polarity + control */ +#define MULTI_BT_FUNC_EN BIT(18) /* BT function enable */ +#define MULTI_BT_HW_ROF_EN BIT(19) /* Enable GPIO[11] as BT/GPS + RF HW powerdown source */ +#define MULTI_GPS_HW_PWRDOWN_EN BIT(20) /* Enable GPIO[10] as GPS HW + powerdown source */ +#define MULTI_GPS_HW_PWRDOWN_SL BIT(21) /* GPS HW powerdown polarity + control */ +#define MULTI_GPS_FUNC_EN BIT(22) /* GPS function enable */ + +#define REG_MCU_FW_DL 0x0080 +#define MCU_FW_DL_ENABLE BIT(0) +#define MCU_FW_DL_READY BIT(1) +#define MCU_FW_DL_CSUM_REPORT BIT(2) +#define MCU_MAC_INIT_READY BIT(3) +#define MCU_BB_INIT_READY BIT(4) +#define MCU_RF_INIT_READY BIT(5) +#define MCU_WINT_INIT_READY BIT(6) +#define MCU_FW_RAM_SEL BIT(7) /* 1: RAM, 0:ROM */ +#define MCU_CP_RESET BIT(23) + +#define REG_HMBOX_EXT_0 0x0088 +#define REG_HMBOX_EXT_1 0x008a +#define REG_HMBOX_EXT_2 0x008c +#define REG_HMBOX_EXT_3 0x008e +/* Host suspend counter on FPGA platform */ +#define REG_HOST_SUSP_CNT 0x00bc +/* Efuse access protection for RTL8723 */ +#define REG_EFUSE_ACCESS 0x00cf +#define REG_BIST_SCAN 0x00d0 +#define REG_BIST_RPT 0x00d4 +#define REG_BIST_ROM_RPT 0x00d8 +#define REG_USB_SIE_INTF 0x00e0 +#define REG_PCIE_MIO_INTF 0x00e4 +#define REG_PCIE_MIO_INTD 0x00e8 +#define REG_HPON_FSM 0x00ec +#define HPON_FSM_BONDING_MASK (BIT(22) | BIT(23)) +#define HPON_FSM_BONDING_1T2R BIT(22) +#define REG_SYS_CFG 0x00f0 +#define SYS_CFG_XCLK_VLD BIT(0) +#define SYS_CFG_ACLK_VLD BIT(1) +#define SYS_CFG_UCLK_VLD BIT(2) +#define SYS_CFG_PCLK_VLD BIT(3) +#define SYS_CFG_PCIRSTB BIT(4) +#define SYS_CFG_V15_VLD BIT(5) +#define SYS_CFG_TRP_B15V_EN BIT(7) +#define SYS_CFG_SIC_IDLE BIT(8) +#define SYS_CFG_BD_MAC2 BIT(9) +#define SYS_CFG_BD_MAC1 BIT(10) +#define SYS_CFG_IC_MACPHY_MODE BIT(11) +#define SYS_CFG_CHIP_VER (BIT(12) | BIT(13) | BIT(14) | BIT(15)) +#define SYS_CFG_BT_FUNC BIT(16) +#define SYS_CFG_VENDOR_ID BIT(19) +#define SYS_CFG_PAD_HWPD_IDN BIT(22) +#define SYS_CFG_TRP_VAUX_EN BIT(23) +#define SYS_CFG_TRP_BT_EN BIT(24) +#define SYS_CFG_BD_PKG_SEL BIT(25) +#define SYS_CFG_BD_HCI_SEL BIT(26) +#define SYS_CFG_TYPE_ID BIT(27) +#define SYS_CFG_RTL_ID BIT(23) /* TestChip ID, + 1:Test(RLE); 0:MP(RL) */ +#define SYS_CFG_SPS_SEL BIT(24) /* 1:LDO regulator mode; + 0:Switching regulator mode*/ +#define SYS_CFG_CHIP_VERSION_MASK 0xf000 /* Bit 12 - 15 */ +#define SYS_CFG_CHIP_VERSION_SHIFT 12 + +#define REG_GPIO_OUTSTS 0x00f4 /* For RTL8723 only. */ +#define GPIO_EFS_HCI_SEL (BIT(0) | BIT(1)) +#define GPIO_PAD_HCI_SEL (BIT(2) | BIT(3)) +#define GPIO_HCI_SEL (BIT(4) | BIT(5)) +#define GPIO_PKG_SEL_HCI BIT(6) +#define GPIO_FEN_GPS BIT(7) +#define GPIO_FEN_BT BIT(8) +#define GPIO_FEN_WL BIT(9) +#define GPIO_FEN_PCI BIT(10) +#define GPIO_FEN_USB BIT(11) +#define GPIO_BTRF_HWPDN_N BIT(12) +#define GPIO_WLRF_HWPDN_N BIT(13) +#define GPIO_PDN_BT_N BIT(14) +#define GPIO_PDN_GPS_N BIT(15) +#define GPIO_BT_CTL_HWPDN BIT(16) +#define GPIO_GPS_CTL_HWPDN BIT(17) +#define GPIO_PPHY_SUSB BIT(20) +#define GPIO_UPHY_SUSB BIT(21) +#define GPIO_PCI_SUSEN BIT(22) +#define GPIO_USB_SUSEN BIT(23) +#define GPIO_RF_RL_ID (BIT(31) | BIT(30) | BIT(29) | BIT(28)) + +/* 0x0100 ~ 0x01FF MACTOP General Configuration */ +#define REG_CR 0x0100 +#define CR_HCI_TXDMA_ENABLE BIT(0) +#define CR_HCI_RXDMA_ENABLE BIT(1) +#define CR_TXDMA_ENABLE BIT(2) +#define CR_RXDMA_ENABLE BIT(3) +#define CR_PROTOCOL_ENABLE BIT(4) +#define CR_SCHEDULE_ENABLE BIT(5) +#define CR_MAC_TX_ENABLE BIT(6) +#define CR_MAC_RX_ENABLE BIT(7) +#define CR_SW_BEACON_ENABLE BIT(8) +#define CR_SECURITY_ENABLE BIT(9) +#define CR_CALTIMER_ENABLE BIT(10) + +/* Media Status Register */ +#define REG_MSR 0x0102 +#define MSR_LINKTYPE_MASK 0x3 +#define MSR_LINKTYPE_NONE 0x0 +#define MSR_LINKTYPE_ADHOC 0x1 +#define MSR_LINKTYPE_STATION 0x2 +#define MSR_LINKTYPE_AP 0x3 + +#define REG_PBP 0x0104 +#define PBP_PAGE_SIZE_RX_SHIFT 0 +#define PBP_PAGE_SIZE_TX_SHIFT 4 +#define PBP_PAGE_SIZE_64 0x0 +#define PBP_PAGE_SIZE_128 0x1 +#define PBP_PAGE_SIZE_256 0x2 +#define PBP_PAGE_SIZE_512 0x3 +#define PBP_PAGE_SIZE_1024 0x4 + +#define REG_TRXDMA_CTRL 0x010c +#define TRXDMA_CTRL_VOQ_SHIFT 4 +#define TRXDMA_CTRL_VIQ_SHIFT 6 +#define TRXDMA_CTRL_BEQ_SHIFT 8 +#define TRXDMA_CTRL_BKQ_SHIFT 10 +#define TRXDMA_CTRL_MGQ_SHIFT 12 +#define TRXDMA_CTRL_HIQ_SHIFT 14 +#define TRXDMA_QUEUE_LOW 1 +#define TRXDMA_QUEUE_NORMAL 2 +#define TRXDMA_QUEUE_HIGH 3 + +#define REG_TRXFF_BNDY 0x0114 +#define REG_TRXFF_STATUS 0x0118 +#define REG_RXFF_PTR 0x011c +#define REG_HIMR 0x0120 +#define REG_HISR 0x0124 +#define REG_HIMRE 0x0128 +#define REG_HISRE 0x012c +#define REG_CPWM 0x012f +#define REG_FWIMR 0x0130 +#define REG_FWISR 0x0134 +#define REG_PKTBUF_DBG_CTRL 0x0140 +#define REG_PKTBUF_DBG_DATA_L 0x0144 +#define REG_PKTBUF_DBG_DATA_H 0x0148 + +#define REG_TC0_CTRL 0x0150 +#define REG_TC1_CTRL 0x0154 +#define REG_TC2_CTRL 0x0158 +#define REG_TC3_CTRL 0x015c +#define REG_TC4_CTRL 0x0160 +#define REG_TCUNIT_BASE 0x0164 +#define REG_MBIST_START 0x0174 +#define REG_MBIST_DONE 0x0178 +#define REG_MBIST_FAIL 0x017c +#define REG_C2HEVT_MSG_NORMAL 0x01a0 +#define REG_C2HEVT_CLEAR 0x01af +#define REG_C2HEVT_MSG_TEST 0x01b8 +#define REG_MCUTST_1 0x01c0 +#define REG_FMTHR 0x01c8 +#define REG_HMTFR 0x01cc +#define REG_HMBOX_0 0x01d0 +#define REG_HMBOX_1 0x01d4 +#define REG_HMBOX_2 0x01d8 +#define REG_HMBOX_3 0x01dc + +#define REG_LLT_INIT 0x01e0 +#define LLT_OP_INACTIVE 0x0 +#define LLT_OP_WRITE (0x1 << 30) +#define LLT_OP_READ (0x2 << 30) +#define LLT_OP_MASK (0x3 << 30) + +#define REG_BB_ACCEESS_CTRL 0x01e8 +#define REG_BB_ACCESS_DATA 0x01ec + +/* 0x0200 ~ 0x027F TXDMA Configuration */ +#define REG_RQPN 0x0200 +#define RQPN_HI_PQ_SHIFT 0 +#define RQPN_LO_PQ_SHIFT 8 +#define RQPN_NORM_PQ_SHIFT 16 +#define RQPN_LOAD BIT(31) + +#define REG_FIFOPAGE 0x0204 +#define REG_TDECTRL 0x0208 +#define REG_TXDMA_OFFSET_CHK 0x020c +#define REG_TXDMA_STATUS 0x0210 +#define REG_RQPN_NPQ 0x0214 + +/* 0x0280 ~ 0x02FF RXDMA Configuration */ +#define REG_RXDMA_AGG_PG_TH 0x0280 +#define REG_RXPKT_NUM 0x0284 +#define REG_RXDMA_STATUS 0x0288 + +#define REG_RF_BB_CMD_ADDR 0x02c0 +#define REG_RF_BB_CMD_DATA 0x02c4 + +/* spec version 11 */ +/* 0x0400 ~ 0x047F Protocol Configuration */ +#define REG_VOQ_INFORMATION 0x0400 +#define REG_VIQ_INFORMATION 0x0404 +#define REG_BEQ_INFORMATION 0x0408 +#define REG_BKQ_INFORMATION 0x040c +#define REG_MGQ_INFORMATION 0x0410 +#define REG_HGQ_INFORMATION 0x0414 +#define REG_BCNQ_INFORMATION 0x0418 + +#define REG_CPU_MGQ_INFORMATION 0x041c +#define REG_FWHW_TXQ_CTRL 0x0420 +#define FWHW_TXQ_CTRL_AMPDU_RETRY BIT(7) +#define FWHW_TXQ_CTRL_XMIT_MGMT_ACK BIT(12) + +#define REG_HWSEQ_CTRL 0x0423 +#define REG_TXPKTBUF_BCNQ_BDNY 0x0424 +#define REG_TXPKTBUF_MGQ_BDNY 0x0425 +#define REG_LIFETIME_EN 0x0426 +#define REG_MULTI_BCNQ_OFFSET 0x0427 + +#define REG_SPEC_SIFS 0x0428 +#define SPEC_SIFS_CCK_MASK 0x00ff +#define SPEC_SIFS_CCK_SHIFT 0 +#define SPEC_SIFS_OFDM_MASK 0xff00 +#define SPEC_SIFS_OFDM_SHIFT 8 + +#define REG_RETRY_LIMIT 0x042a +#define RETRY_LIMIT_LONG_SHIFT 0 +#define RETRY_LIMIT_LONG_MASK 0x003f +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_SHORT_MASK 0x3f00 + +#define REG_DARFRC 0x0430 +#define REG_RARFRC 0x0438 +#define REG_RESPONSE_RATE_SET 0x0440 +#define RESPONSE_RATE_BITMAP_ALL 0xfffff +#define RESPONSE_RATE_RRSR_CCK_ONLY_1M 0xffff1 +#define RSR_1M BIT(0) +#define RSR_2M BIT(1) +#define RSR_5_5M BIT(2) +#define RSR_11M BIT(3) +#define RSR_6M BIT(4) +#define RSR_9M BIT(5) +#define RSR_12M BIT(6) +#define RSR_18M BIT(7) +#define RSR_24M BIT(8) +#define RSR_36M BIT(9) +#define RSR_48M BIT(10) +#define RSR_54M BIT(11) +#define RSR_MCS0 BIT(12) +#define RSR_MCS1 BIT(13) +#define RSR_MCS2 BIT(14) +#define RSR_MCS3 BIT(15) +#define RSR_MCS4 BIT(16) +#define RSR_MCS5 BIT(17) +#define RSR_MCS6 BIT(18) +#define RSR_MCS7 BIT(19) +#define RSR_RSC_LOWER_SUB_CHANNEL BIT(21) /* 0x200000 */ +#define RSR_RSC_UPPER_SUB_CHANNEL BIT(22) /* 0x400000 */ +#define RSR_RSC_BANDWIDTH_40M (RSR_RSC_UPPER_SUB_CHANNEL | \ + RSR_RSC_LOWER_SUB_CHANNEL) +#define RSR_ACK_SHORT_PREAMBLE BIT(23) + +#define REG_ARFR0 0x0444 +#define REG_ARFR1 0x0448 +#define REG_ARFR2 0x044c +#define REG_ARFR3 0x0450 +#define REG_AGGLEN_LMT 0x0458 +#define REG_AMPDU_MIN_SPACE 0x045c +#define REG_TXPKTBUF_WMAC_LBK_BF_HD 0x045d +#define REG_FAST_EDCA_CTRL 0x0460 +#define REG_RD_RESP_PKT_TH 0x0463 +#define REG_INIRTS_RATE_SEL 0x0480 +#define REG_INIDATA_RATE_SEL 0x0484 + +#define REG_POWER_STATUS 0x04a4 +#define REG_POWER_STAGE1 0x04b4 +#define REG_POWER_STAGE2 0x04b8 +#define REG_PKT_VO_VI_LIFE_TIME 0x04c0 +#define REG_PKT_BE_BK_LIFE_TIME 0x04c2 +#define REG_STBC_SETTING 0x04c4 +#define REG_PROT_MODE_CTRL 0x04c8 +#define REG_MAX_AGGR_NUM 0x04ca +#define REG_RTS_MAX_AGGR_NUM 0x04cb +#define REG_BAR_MODE_CTRL 0x04cc +#define REG_RA_TRY_RATE_AGG_LMT 0x04cf +#define REG_NQOS_SEQ 0x04dc +#define REG_QOS_SEQ 0x04de +#define REG_NEED_CPU_HANDLE 0x04e0 +#define REG_PKT_LOSE_RPT 0x04e1 +#define REG_PTCL_ERR_STATUS 0x04e2 +#define REG_DUMMY 0x04fc + +/* 0x0500 ~ 0x05FF EDCA Configuration */ +#define REG_EDCA_VO_PARAM 0x0500 +#define REG_EDCA_VI_PARAM 0x0504 +#define REG_EDCA_BE_PARAM 0x0508 +#define REG_EDCA_BK_PARAM 0x050c +#define EDCA_PARAM_ECW_MIN_SHIFT 8 +#define EDCA_PARAM_ECW_MAX_SHIFT 12 +#define EDCA_PARAM_TXOP_SHIFT 16 +#define REG_BEACON_TCFG 0x0510 +#define REG_PIFS 0x0512 +#define REG_RDG_PIFS 0x0513 +#define REG_SIFS_CCK 0x0514 +#define REG_SIFS_OFDM 0x0516 +#define REG_TSFTR_SYN_OFFSET 0x0518 +#define REG_AGGR_BREAK_TIME 0x051a +#define REG_SLOT 0x051b +#define REG_TX_PTCL_CTRL 0x0520 +#define REG_TXPAUSE 0x0522 +#define REG_DIS_TXREQ_CLR 0x0523 +#define REG_RD_CTRL 0x0524 +#define REG_TBTT_PROHIBIT 0x0540 +#define REG_RD_NAV_NXT 0x0544 +#define REG_NAV_PROT_LEN 0x0546 + +#define REG_BEACON_CTRL 0x0550 +#define REG_BEACON_CTRL_1 0x0551 +#define BEACON_ATIM BIT(0) +#define BEACON_CTRL_MBSSID BIT(1) +#define BEACON_CTRL_TX_BEACON_RPT BIT(2) +#define BEACON_FUNCTION_ENABLE BIT(3) +#define BEACON_DISABLE_TSF_UPDATE BIT(4) + +#define REG_MBID_NUM 0x0552 +#define REG_DUAL_TSF_RST 0x0553 +#define DUAL_TSF_RESET_TSF0 BIT(0) +#define DUAL_TSF_RESET_TSF1 BIT(1) +#define DUAL_TSF_RESET_P2P BIT(4) +#define DUAL_TSF_TX_OK BIT(5) + +/* The same as REG_MBSSID_BCN_SPACE */ +#define REG_BCN_INTERVAL 0x0554 +#define REG_MBSSID_BCN_SPACE 0x0554 + +#define REG_DRIVER_EARLY_INT 0x0558 +#define DRIVER_EARLY_INT_TIME 5 + +#define REG_BEACON_DMA_TIME 0x0559 +#define BEACON_DMA_ATIME_INT_TIME 2 + +#define REG_ATIMWND 0x055a +#define REG_BCN_MAX_ERR 0x055d +#define REG_RXTSF_OFFSET_CCK 0x055e +#define REG_RXTSF_OFFSET_OFDM 0x055f +#define REG_TSFTR 0x0560 +#define REG_TSFTR1 0x0568 +#define REG_INIT_TSFTR 0x0564 +#define REG_ATIMWND_1 0x0570 +#define REG_PSTIMER 0x0580 +#define REG_TIMER0 0x0584 +#define REG_TIMER1 0x0588 +#define REG_ACM_HW_CTRL 0x05c0 +#define ACM_HW_CTRL_BK BIT(0) +#define ACM_HW_CTRL_BE BIT(1) +#define ACM_HW_CTRL_VI BIT(2) +#define ACM_HW_CTRL_VO BIT(3) +#define REG_ACM_RST_CTRL 0x05c1 +#define REG_ACMAVG 0x05c2 +#define REG_VO_ADMTIME 0x05c4 +#define REG_VI_ADMTIME 0x05c6 +#define REG_BE_ADMTIME 0x05c8 +#define REG_EDCA_RANDOM_GEN 0x05cc +#define REG_SCH_TXCMD 0x05d0 + +/* define REG_FW_TSF_SYNC_CNT 0x04a0 */ +#define REG_FW_RESET_TSF_CNT_1 0x05fc +#define REG_FW_RESET_TSF_CNT_0 0x05fd +#define REG_FW_BCN_DIS_CNT 0x05fe + +/* 0x0600 ~ 0x07FF WMAC Configuration */ +#define REG_APSD_CTRL 0x0600 +#define APSD_CTRL_OFF BIT(6) +#define APSD_CTRL_OFF_STATUS BIT(7) +#define REG_BW_OPMODE 0x0603 +#define BW_OPMODE_20MHZ BIT(2) +#define BW_OPMODE_5G BIT(1) +#define BW_OPMODE_11J BIT(0) + +#define REG_TCR 0x0604 + +/* Receive Configuration Register */ +#define REG_RCR 0x0608 +#define RCR_ACCEPT_AP BIT(0) /* Accept all unicast packet */ +#define RCR_ACCEPT_PHYS_MATCH BIT(1) /* Accept phys match packet */ +#define RCR_ACCEPT_MCAST BIT(2) +#define RCR_ACCEPT_BCAST BIT(3) +#define RCR_ACCEPT_ADDR3 BIT(4) /* Accept address 3 match + packet */ +#define RCR_ACCEPT_PM BIT(5) /* Accept power management + packet */ +#define RCR_CHECK_BSSID_MATCH BIT(6) /* Accept BSSID match packet */ +#define RCR_CHECK_BSSID_BEACON BIT(7) /* Accept BSSID match packet + (Rx beacon, probe rsp) */ +#define RCR_ACCEPT_CRC32 BIT(8) /* Accept CRC32 error packet */ +#define RCR_ACCEPT_ICV BIT(9) /* Accept ICV error packet */ +#define RCR_ACCEPT_DATA_FRAME BIT(11) +#define RCR_ACCEPT_CTRL_FRAME BIT(12) +#define RCR_ACCEPT_MGMT_FRAME BIT(13) +#define RCR_HTC_LOC_CTRL BIT(14) /* MFC<--HTC=1 MFC-->HTC=0 */ +#define RCR_MFBEN BIT(22) +#define RCR_LSIGEN BIT(23) +#define RCR_MULTI_BSSID_ENABLE BIT(24) /* Enable Multiple BssId */ +#define RCR_ACCEPT_BA_SSN BIT(27) /* Accept BA SSN */ +#define RCR_APPEND_PHYSTAT BIT(28) +#define RCR_APPEND_ICV BIT(29) +#define RCR_APPEND_MIC BIT(30) +#define RCR_APPEND_FCS BIT(31) /* WMAC append FCS after */ + +#define REG_RX_PKT_LIMIT 0x060c +#define REG_RX_DLK_TIME 0x060d +#define REG_RX_DRVINFO_SZ 0x060f + +#define REG_MACID 0x0610 +#define REG_BSSID 0x0618 +#define REG_MAR 0x0620 +#define REG_MBIDCAMCFG 0x0628 + +#define REG_USTIME_EDCA 0x0638 +#define REG_MAC_SPEC_SIFS 0x063a + +/* 20100719 Joseph: Hardware register definition change. (HW datasheet v54) */ + /* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */ +#define REG_R2T_SIFS 0x063c + /* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */ +#define REG_T2T_SIFS 0x063e +#define REG_ACKTO 0x0640 +#define REG_CTS2TO 0x0641 +#define REG_EIFS 0x0642 + +/* WMA, BA, CCX */ +#define REG_NAV_CTRL 0x0650 +/* In units of 128us */ +#define REG_NAV_UPPER 0x0652 +#define NAV_UPPER_UNIT 128 + +#define REG_BACAMCMD 0x0654 +#define REG_BACAMCONTENT 0x0658 +#define REG_LBDLY 0x0660 +#define REG_FWDLY 0x0661 +#define REG_RXERR_RPT 0x0664 +#define REG_WMAC_TRXPTCL_CTL 0x0668 + +/* Security */ +#define REG_CAM_CMD 0x0670 +#define CAM_CMD_POLLING BIT(31) +#define CAM_CMD_WRITE BIT(16) +#define CAM_CMD_KEY_SHIFT 3 +#define REG_CAM_WRITE 0x0674 +#define CAM_WRITE_VALID BIT(15) +#define REG_CAM_READ 0x0678 +#define REG_CAM_DEBUG 0x067c +#define REG_SECURITY_CFG 0x0680 +#define SEC_CFG_TX_USE_DEFKEY BIT(0) +#define SEC_CFG_RX_USE_DEFKEY BIT(1) +#define SEC_CFG_TX_SEC_ENABLE BIT(2) +#define SEC_CFG_RX_SEC_ENABLE BIT(3) +#define SEC_CFG_SKBYA2 BIT(4) +#define SEC_CFG_NO_SKMC BIT(5) +#define SEC_CFG_TXBC_USE_DEFKEY BIT(6) +#define SEC_CFG_RXBC_USE_DEFKEY BIT(7) + +/* Power */ +#define REG_WOW_CTRL 0x0690 +#define REG_PSSTATUS 0x0691 +#define REG_PS_RX_INFO 0x0692 +#define REG_LPNAV_CTRL 0x0694 +#define REG_WKFMCAM_CMD 0x0698 +#define REG_WKFMCAM_RWD 0x069c +#define REG_RXFLTMAP0 0x06a0 +#define REG_RXFLTMAP1 0x06a2 +#define REG_RXFLTMAP2 0x06a4 +#define REG_BCN_PSR_RPT 0x06a8 +#define REG_CALB32K_CTRL 0x06ac +#define REG_PKT_MON_CTRL 0x06b4 +#define REG_BT_COEX_TABLE 0x06c0 +#define REG_WMAC_RESP_TXINFO 0x06d8 + +#define REG_MACID1 0x0700 +#define REG_BSSID1 0x0708 + +#define REG_FPGA0_RF_MODE 0x0800 +#define FPGA_RF_MODE BIT(0) +#define FPGA_RF_MODE_JAPAN BIT(1) +#define FPGA_RF_MODE_CCK BIT(24) +#define FPGA_RF_MODE_OFDM BIT(25) + +#define REG_FPGA0_TX_INFO 0x0804 +#define REG_FPGA0_PSD_FUNC 0x0808 +#define REG_FPGA0_TX_GAIN 0x080c +#define REG_FPGA0_RF_TIMING1 0x0810 +#define REG_FPGA0_RF_TIMING2 0x0814 +#define REG_FPGA0_POWER_SAVE 0x0818 +#define FPGA0_PS_LOWER_CHANNEL BIT(26) +#define FPGA0_PS_UPPER_CHANNEL BIT(27) + +#define REG_FPGA0_XA_HSSI_PARM1 0x0820 /* RF 3 wire register */ +#define FPGA0_HSSI_PARM1_PI BIT(8) +#define REG_FPGA0_XA_HSSI_PARM2 0x0824 +#define REG_FPGA0_XB_HSSI_PARM1 0x0828 +#define REG_FPGA0_XB_HSSI_PARM2 0x082c +#define FPGA0_HSSI_3WIRE_DATA_LEN 0x800 +#define FPGA0_HSSI_3WIRE_ADDR_LEN 0x400 +#define FPGA0_HSSI_PARM2_ADDR_SHIFT 23 +#define FPGA0_HSSI_PARM2_ADDR_MASK 0x7f800000 /* 0xff << 23 */ +#define FPGA0_HSSI_PARM2_CCK_HIGH_PWR BIT(9) +#define FPGA0_HSSI_PARM2_EDGE_READ BIT(31) + +#define REG_TX_AGC_B_RATE18_06 0x0830 +#define REG_TX_AGC_B_RATE54_24 0x0834 +#define REG_TX_AGC_B_CCK1_55_MCS32 0x0838 +#define REG_TX_AGC_B_MCS03_MCS00 0x083c + +#define REG_FPGA0_XA_LSSI_PARM 0x0840 +#define REG_FPGA0_XB_LSSI_PARM 0x0844 +#define FPGA0_LSSI_PARM_ADDR_SHIFT 20 +#define FPGA0_LSSI_PARM_ADDR_MASK 0x0ff00000 +#define FPGA0_LSSI_PARM_DATA_MASK 0x000fffff + +#define REG_TX_AGC_B_MCS07_MCS04 0x0848 +#define REG_TX_AGC_B_MCS11_MCS08 0x084c + +#define REG_FPGA0_XCD_SWITCH_CTRL 0x085c + +#define REG_FPGA0_XA_RF_INT_OE 0x0860 /* RF Channel switch */ +#define REG_FPGA0_XB_RF_INT_OE 0x0864 +#define FPGA0_INT_OE_ANTENNA_AB_OPEN 0x000 +#define FPGA0_INT_OE_ANTENNA_A BIT(8) +#define FPGA0_INT_OE_ANTENNA_B BIT(9) +#define FPGA0_INT_OE_ANTENNA_MASK (FPGA0_INT_OE_ANTENNA_A | \ + FPGA0_INT_OE_ANTENNA_B) + +#define REG_TX_AGC_B_MCS15_MCS12 0x0868 +#define REG_TX_AGC_B_CCK11_A_CCK2_11 0x086c + +#define REG_FPGA0_XAB_RF_SW_CTRL 0x0870 +#define REG_FPGA0_XA_RF_SW_CTRL 0x0870 /* 16 bit */ +#define REG_FPGA0_XB_RF_SW_CTRL 0x0872 /* 16 bit */ +#define REG_FPGA0_XCD_RF_SW_CTRL 0x0874 +#define REG_FPGA0_XC_RF_SW_CTRL 0x0874 /* 16 bit */ +#define REG_FPGA0_XD_RF_SW_CTRL 0x0876 /* 16 bit */ +#define FPGA0_RF_3WIRE_DATA BIT(0) +#define FPGA0_RF_3WIRE_CLOC BIT(1) +#define FPGA0_RF_3WIRE_LOAD BIT(2) +#define FPGA0_RF_3WIRE_RW BIT(3) +#define FPGA0_RF_3WIRE_MASK 0xf +#define FPGA0_RF_RFENV BIT(4) +#define FPGA0_RF_TRSW BIT(5) /* Useless now */ +#define FPGA0_RF_TRSWB BIT(6) +#define FPGA0_RF_ANTSW BIT(8) +#define FPGA0_RF_ANTSWB BIT(9) +#define FPGA0_RF_PAPE BIT(10) +#define FPGA0_RF_PAPE5G BIT(11) +#define FPGA0_RF_BD_CTRL_SHIFT 16 + +#define REG_FPGA0_XAB_RF_PARM 0x0878 /* Antenna select path in ODM */ +#define REG_FPGA0_XA_RF_PARM 0x0878 /* 16 bit */ +#define REG_FPGA0_XB_RF_PARM 0x087a /* 16 bit */ +#define REG_FPGA0_XCD_RF_PARM 0x087c +#define REG_FPGA0_XC_RF_PARM 0x087c /* 16 bit */ +#define REG_FPGA0_XD_RF_PARM 0x087e /* 16 bit */ +#define FPGA0_RF_PARM_RFA_ENABLE BIT(1) +#define FPGA0_RF_PARM_RFB_ENABLE BIT(17) +#define FPGA0_RF_PARM_CLK_GATE BIT(31) + +#define REG_FPGA0_ANALOG1 0x0880 +#define REG_FPGA0_ANALOG2 0x0884 +#define FPGA0_ANALOG2_20MHZ BIT(10) +#define REG_FPGA0_ANALOG3 0x0888 +#define REG_FPGA0_ANALOG4 0x088c + +#define REG_FPGA0_XA_LSSI_READBACK 0x08a0 /* Tranceiver LSSI Readback */ +#define REG_FPGA0_XB_LSSI_READBACK 0x08a4 +#define REG_HSPI_XA_READBACK 0x08b8 /* Transceiver A HSPI read */ +#define REG_HSPI_XB_READBACK 0x08bc /* Transceiver B HSPI read */ + +#define REG_FPGA1_RF_MODE 0x0900 + +#define REG_FPGA1_TX_INFO 0x090c + +#define REG_CCK0_SYSTEM 0x0a00 +#define CCK0_SIDEBAND BIT(4) + +#define REG_CCK0_AFE_SETTING 0x0a04 + +#define REG_CONFIG_ANT_A 0x0b68 +#define REG_CONFIG_ANT_B 0x0b6c + +#define REG_OFDM0_TRX_PATH_ENABLE 0x0c04 +#define OFDM_RF_PATH_RX_MASK 0x0f +#define OFDM_RF_PATH_RX_A BIT(0) +#define OFDM_RF_PATH_RX_B BIT(1) +#define OFDM_RF_PATH_RX_C BIT(2) +#define OFDM_RF_PATH_RX_D BIT(3) +#define OFDM_RF_PATH_TX_MASK 0xf0 +#define OFDM_RF_PATH_TX_A BIT(4) +#define OFDM_RF_PATH_TX_B BIT(5) +#define OFDM_RF_PATH_TX_C BIT(6) +#define OFDM_RF_PATH_TX_D BIT(7) + +#define REG_OFDM0_TR_MUX_PAR 0x0c08 + +#define REG_OFDM0_XA_RX_IQ_IMBALANCE 0x0c14 +#define REG_OFDM0_XB_RX_IQ_IMBALANCE 0x0c1c + +#define REG_OFDM0_ENERGY_CCA_THRES 0x0c4c + +#define REG_OFDM0_XA_AGC_CORE1 0x0c50 +#define REG_OFDM0_XA_AGC_CORE2 0x0c54 +#define REG_OFDM0_XB_AGC_CORE1 0x0c58 +#define REG_OFDM0_XB_AGC_CORE2 0x0c5c +#define REG_OFDM0_XC_AGC_CORE1 0x0c60 +#define REG_OFDM0_XC_AGC_CORE2 0x0c64 +#define REG_OFDM0_XD_AGC_CORE1 0x0c68 +#define REG_OFDM0_XD_AGC_CORE2 0x0c6c +#define OFDM0_X_AGC_CORE1_IGI_MASK 0x0000007F + +#define REG_OFDM0_AGC_PARM1 0x0c70 + +#define REG_OFDM0_AGCR_SSI_TABLE 0x0c78 + +#define REG_OFDM0_XA_TX_IQ_IMBALANCE 0x0c80 +#define REG_OFDM0_XB_TX_IQ_IMBALANCE 0x0c88 +#define REG_OFDM0_XC_TX_IQ_IMBALANCE 0x0c90 +#define REG_OFDM0_XD_TX_IQ_IMBALANCE 0x0c98 + +#define REG_OFDM0_XC_TX_AFE 0x0c94 +#define REG_OFDM0_XD_TX_AFE 0x0c9c + +#define REG_OFDM0_RX_IQ_EXT_ANTA 0x0ca0 + +#define REG_OFDM1_LSTF 0x0d00 +#define OFDM_LSTF_PRIME_CH_LOW BIT(10) +#define OFDM_LSTF_PRIME_CH_HIGH BIT(11) +#define OFDM_LSTF_PRIME_CH_MASK (OFDM_LSTF_PRIME_CH_LOW | \ + OFDM_LSTF_PRIME_CH_HIGH) +#define OFDM_LSTF_CONTINUE_TX BIT(28) +#define OFDM_LSTF_SINGLE_CARRIER BIT(29) +#define OFDM_LSTF_SINGLE_TONE BIT(30) +#define OFDM_LSTF_MASK 0x70000000 + +#define REG_OFDM1_TRX_PATH_ENABLE 0x0d04 + +#define REG_TX_AGC_A_RATE18_06 0x0e00 +#define REG_TX_AGC_A_RATE54_24 0x0e04 +#define REG_TX_AGC_A_CCK1_MCS32 0x0e08 +#define REG_TX_AGC_A_MCS03_MCS00 0x0e10 +#define REG_TX_AGC_A_MCS07_MCS04 0x0e14 +#define REG_TX_AGC_A_MCS11_MCS08 0x0e18 +#define REG_TX_AGC_A_MCS15_MCS12 0x0e1c + +#define REG_FPGA0_IQK 0x0e28 + +#define REG_TX_IQK_TONE_A 0x0e30 +#define REG_RX_IQK_TONE_A 0x0e34 +#define REG_TX_IQK_PI_A 0x0e38 +#define REG_RX_IQK_PI_A 0x0e3c + +#define REG_TX_IQK 0x0e40 +#define REG_RX_IQK 0x0e44 +#define REG_IQK_AGC_PTS 0x0e48 +#define REG_IQK_AGC_RSP 0x0e4c +#define REG_TX_IQK_TONE_B 0x0e50 +#define REG_RX_IQK_TONE_B 0x0e54 +#define REG_TX_IQK_PI_B 0x0e58 +#define REG_RX_IQK_PI_B 0x0e5c +#define REG_IQK_AGC_CONT 0x0e60 + +#define REG_BLUETOOTH 0x0e6c +#define REG_RX_WAIT_CCA 0x0e70 +#define REG_TX_CCK_RFON 0x0e74 +#define REG_TX_CCK_BBON 0x0e78 +#define REG_TX_OFDM_RFON 0x0e7c +#define REG_TX_OFDM_BBON 0x0e80 +#define REG_TX_TO_RX 0x0e84 +#define REG_TX_TO_TX 0x0e88 +#define REG_RX_CCK 0x0e8c + +#define REG_TX_POWER_BEFORE_IQK_A 0x0e94 +#define REG_TX_POWER_AFTER_IQK_A 0x0e9c + +#define REG_RX_POWER_BEFORE_IQK_A 0x0ea0 +#define REG_RX_POWER_BEFORE_IQK_A_2 0x0ea4 +#define REG_RX_POWER_AFTER_IQK_A 0x0ea8 +#define REG_RX_POWER_AFTER_IQK_A_2 0x0eac + +#define REG_TX_POWER_BEFORE_IQK_B 0x0eb4 +#define REG_TX_POWER_AFTER_IQK_B 0x0ebc + +#define REG_RX_POWER_BEFORE_IQK_B 0x0ec0 +#define REG_RX_POWER_BEFORE_IQK_B_2 0x0ec4 +#define REG_RX_POWER_AFTER_IQK_B 0x0ec8 +#define REG_RX_POWER_AFTER_IQK_B_2 0x0ecc + +#define REG_RX_OFDM 0x0ed0 +#define REG_RX_WAIT_RIFS 0x0ed4 +#define REG_RX_TO_RX 0x0ed8 +#define REG_STANDBY 0x0edc +#define REG_SLEEP 0x0ee0 +#define REG_PMPD_ANAEN 0x0eec + +#define REG_FW_START_ADDRESS 0x1000 + +#define REG_USB_INFO 0xfe17 +#define REG_USB_HIMR 0xfe38 +#define USB_HIMR_TIMEOUT2 BIT(31) +#define USB_HIMR_TIMEOUT1 BIT(30) +#define USB_HIMR_PSTIMEOUT BIT(29) +#define USB_HIMR_GTINT4 BIT(28) +#define USB_HIMR_GTINT3 BIT(27) +#define USB_HIMR_TXBCNERR BIT(26) +#define USB_HIMR_TXBCNOK BIT(25) +#define USB_HIMR_TSF_BIT32_TOGGLE BIT(24) +#define USB_HIMR_BCNDMAINT3 BIT(23) +#define USB_HIMR_BCNDMAINT2 BIT(22) +#define USB_HIMR_BCNDMAINT1 BIT(21) +#define USB_HIMR_BCNDMAINT0 BIT(20) +#define USB_HIMR_BCNDOK3 BIT(19) +#define USB_HIMR_BCNDOK2 BIT(18) +#define USB_HIMR_BCNDOK1 BIT(17) +#define USB_HIMR_BCNDOK0 BIT(16) +#define USB_HIMR_HSISR_IND BIT(15) +#define USB_HIMR_BCNDMAINT_E BIT(14) +/* RSVD BIT(13) */ +#define USB_HIMR_CTW_END BIT(12) +/* RSVD BIT(11) */ +#define USB_HIMR_C2HCMD BIT(10) +#define USB_HIMR_CPWM2 BIT(9) +#define USB_HIMR_CPWM BIT(8) +#define USB_HIMR_HIGHDOK BIT(7) /* High Queue DMA OK + Interrupt */ +#define USB_HIMR_MGNTDOK BIT(6) /* Management Queue DMA OK + Interrupt */ +#define USB_HIMR_BKDOK BIT(5) /* AC_BK DMA OK Interrupt */ +#define USB_HIMR_BEDOK BIT(4) /* AC_BE DMA OK Interrupt */ +#define USB_HIMR_VIDOK BIT(3) /* AC_VI DMA OK Interrupt */ +#define USB_HIMR_VODOK BIT(2) /* AC_VO DMA Interrupt */ +#define USB_HIMR_RDU BIT(1) /* Receive Descriptor + Unavailable */ +#define USB_HIMR_ROK BIT(0) /* Receive DMA OK Interrupt */ + +#define REG_USB_SPECIAL_OPTION 0xfe55 +#define REG_USB_DMA_AGG_TO 0xfe5b +#define REG_USB_AGG_TO 0xfe5c +#define REG_USB_AGG_TH 0xfe5d + +#define REG_NORMAL_SIE_VID 0xfe60 /* 0xfe60 - 0xfe61 */ +#define REG_NORMAL_SIE_PID 0xfe62 /* 0xfe62 - 0xfe63 */ +#define REG_NORMAL_SIE_OPTIONAL 0xfe64 +#define REG_NORMAL_SIE_EP 0xfe65 /* 0xfe65 - 0xfe67 */ +#define REG_NORMAL_SIE_EP_TX 0xfe66 +#define NORMAL_SIE_EP_TX_HIGH_MASK 0x000f +#define NORMAL_SIE_EP_TX_NORMAL_MASK 0x00f0 +#define NORMAL_SIE_EP_TX_LOW_MASK 0x0f00 + +#define REG_NORMAL_SIE_PHY 0xfe68 /* 0xfe68 - 0xfe6b */ +#define REG_NORMAL_SIE_OPTIONAL2 0xfe6c +#define REG_NORMAL_SIE_GPS_EP 0xfe6d /* RTL8723 only */ +#define REG_NORMAL_SIE_MAC_ADDR 0xfe70 /* 0xfe70 - 0xfe75 */ +#define REG_NORMAL_SIE_STRING 0xfe80 /* 0xfe80 - 0xfedf */ + +/* RF6052 registers */ +#define RF6052_REG_AC 0x00 +#define RF6052_REG_IQADJ_G1 0x01 +#define RF6052_REG_IQADJ_G2 0x02 +#define RF6052_REG_BS_PA_APSET_G1_G4 0x03 +#define RF6052_REG_BS_PA_APSET_G5_G8 0x04 +#define RF6052_REG_POW_TRSW 0x05 +#define RF6052_REG_GAIN_RX 0x06 +#define RF6052_REG_GAIN_TX 0x07 +#define RF6052_REG_TXM_IDAC 0x08 +#define RF6052_REG_IPA_G 0x09 +#define RF6052_REG_TXBIAS_G 0x0a +#define RF6052_REG_TXPA_AG 0x0b +#define RF6052_REG_IPA_A 0x0c +#define RF6052_REG_TXBIAS_A 0x0d +#define RF6052_REG_BS_PA_APSET_G9_G11 0x0e +#define RF6052_REG_BS_IQGEN 0x0f +#define RF6052_REG_MODE1 0x10 +#define RF6052_REG_MODE2 0x11 +#define RF6052_REG_RX_AGC_HP 0x12 +#define RF6052_REG_TX_AGC 0x13 +#define RF6052_REG_BIAS 0x14 +#define RF6052_REG_IPA 0x15 +#define RF6052_REG_TXBIAS 0x16 +#define RF6052_REG_POW_ABILITY 0x17 +#define RF6052_REG_MODE_AG 0x18 /* RF channel and BW switch */ +#define MODE_AG_CHANNEL_MASK 0x3ff +#define MODE_AG_CHANNEL_20MHZ BIT(10) + +#define RF6052_REG_TOP 0x19 +#define RF6052_REG_RX_G1 0x1a +#define RF6052_REG_RX_G2 0x1b +#define RF6052_REG_RX_BB2 0x1c +#define RF6052_REG_RX_BB1 0x1d +#define RF6052_REG_RCK1 0x1e +#define RF6052_REG_RCK2 0x1f +#define RF6052_REG_TX_G1 0x20 +#define RF6052_REG_TX_G2 0x21 +#define RF6052_REG_TX_G3 0x22 +#define RF6052_REG_TX_BB1 0x23 +#define RF6052_REG_T_METER 0x24 +#define RF6052_REG_SYN_G1 0x25 /* RF TX Power control */ +#define RF6052_REG_SYN_G2 0x26 /* RF TX Power control */ +#define RF6052_REG_SYN_G3 0x27 /* RF TX Power control */ +#define RF6052_REG_SYN_G4 0x28 /* RF TX Power control */ +#define RF6052_REG_SYN_G5 0x29 /* RF TX Power control */ +#define RF6052_REG_SYN_G6 0x2a /* RF TX Power control */ +#define RF6052_REG_SYN_G7 0x2b /* RF TX Power control */ +#define RF6052_REG_SYN_G8 0x2c /* RF TX Power control */ + +#define RF6052_REG_RCK_OS 0x30 /* RF TX PA control */ + +#define RF6052_REG_TXPA_G1 0x31 /* RF TX PA control */ +#define RF6052_REG_TXPA_G2 0x32 /* RF TX PA control */ +#define RF6052_REG_TXPA_G3 0x33 /* RF TX PA control */ -- cgit v1.2.3 From ff4445a8502cdf06969540c92bb201ee47e70351 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 8 Oct 2015 20:33:11 +0200 Subject: brcmfmac: expose device memory to devcoredump subsystem Upon PSM watchdog event received from firmware the driver will obtain a memory snapshot of the device and expose it to user-space through the devcoredump framework. This will trigger a uevent. Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/Kconfig | 1 + drivers/net/wireless/brcm80211/brcmfmac/bus.h | 21 ++++++++ drivers/net/wireless/brcm80211/brcmfmac/core.c | 6 +-- drivers/net/wireless/brcm80211/brcmfmac/debug.c | 42 ++++++++++++++-- drivers/net/wireless/brcm80211/brcmfmac/debug.h | 8 +-- drivers/net/wireless/brcm80211/brcmfmac/pcie.c | 65 +++++++++++++++++++++++++ drivers/net/wireless/brcm80211/brcmfmac/sdio.c | 49 ++++++++++++++++++- 7 files changed, 181 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index fe3dc126b149..ab42b1fea03c 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig @@ -82,5 +82,6 @@ config BRCM_TRACING config BRCMDBG bool "Broadcom driver debug functions" depends on BRCMSMAC || BRCMFMAC + select WANT_DEV_COREDUMP ---help--- Selecting this enables additional code for debug purposes. diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/brcm80211/brcmfmac/bus.h index 89e6a4dc105e..230cad788ace 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/bus.h @@ -65,6 +65,8 @@ struct brcmf_bus_dcmd { * @rxctl: receive a control response message from dongle. * @gettxq: obtain a reference of bus transmit queue (optional). * @wowl_config: specify if dongle is configured for wowl when going to suspend + * @get_ramsize: obtain size of device memory. + * @get_memdump: obtain device memory dump in provided buffer. * * This structure provides an abstract interface towards the * bus specific driver. For control messages to common driver @@ -79,6 +81,8 @@ struct brcmf_bus_ops { int (*rxctl)(struct device *dev, unsigned char *msg, uint len); struct pktq * (*gettxq)(struct device *dev); void (*wowl_config)(struct device *dev, bool enabled); + size_t (*get_ramsize)(struct device *dev); + int (*get_memdump)(struct device *dev, void *data, size_t len); }; @@ -185,6 +189,23 @@ void brcmf_bus_wowl_config(struct brcmf_bus *bus, bool enabled) bus->ops->wowl_config(bus->dev, enabled); } +static inline size_t brcmf_bus_get_ramsize(struct brcmf_bus *bus) +{ + if (!bus->ops->get_ramsize) + return 0; + + return bus->ops->get_ramsize(bus->dev); +} + +static inline +int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) +{ + if (!bus->ops->get_memdump) + return -EOPNOTSUPP; + + return bus->ops->get_memdump(bus->dev, data, len); +} + /* * interface functions from common layer */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 8c2a280f0c98..a1d39b1966f7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -957,8 +957,8 @@ int brcmf_attach(struct device *dev) drvr->bus_if = dev_get_drvdata(dev); drvr->bus_if->drvr = drvr; - /* create device debugfs folder */ - brcmf_debugfs_attach(drvr); + /* attach debug facilities */ + brcmf_debug_attach(drvr); /* Attach and link in the protocol */ ret = brcmf_proto_attach(drvr); @@ -1155,7 +1155,7 @@ void brcmf_detach(struct device *dev) brcmf_proto_detach(drvr); - brcmf_debugfs_detach(drvr); + brcmf_debug_detach(drvr); bus_if->drvr = NULL; kfree(drvr); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.c b/drivers/net/wireless/brcm80211/brcmfmac/debug.c index 2d6d00553858..1299dccc78b4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c @@ -16,15 +16,45 @@ #include #include #include +#include #include #include #include "core.h" #include "bus.h" +#include "fweh.h" #include "debug.h" static struct dentry *root_folder; +static int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data, + size_t len) +{ + void *dump; + size_t ramsize; + + ramsize = brcmf_bus_get_ramsize(bus); + if (ramsize) { + dump = vzalloc(len + ramsize); + if (!dump) + return -ENOMEM; + memcpy(dump, data, len); + brcmf_bus_get_memdump(bus, dump + len, ramsize); + dev_coredumpv(bus->dev, dump, len + ramsize, GFP_KERNEL); + } + return 0; +} + +static int brcmf_debug_psm_watchdog_notify(struct brcmf_if *ifp, + const struct brcmf_event_msg *evtmsg, + void *data) +{ + brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx); + + return brcmf_debug_create_memdump(ifp->drvr->bus_if, data, + evtmsg->datalen); +} + void brcmf_debugfs_init(void) { root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL); @@ -41,7 +71,7 @@ void brcmf_debugfs_exit(void) root_folder = NULL; } -int brcmf_debugfs_attach(struct brcmf_pub *drvr) +int brcmf_debug_attach(struct brcmf_pub *drvr) { struct device *dev = drvr->bus_if->dev; @@ -49,12 +79,18 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr) return -ENODEV; drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); + if (IS_ERR(drvr->dbgfs_dir)) + return PTR_ERR(drvr->dbgfs_dir); - return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); + + return brcmf_fweh_register(drvr, BRCMF_E_PSM_WATCHDOG, + brcmf_debug_psm_watchdog_notify); } -void brcmf_debugfs_detach(struct brcmf_pub *drvr) +void brcmf_debug_detach(struct brcmf_pub *drvr) { + brcmf_fweh_unregister(drvr, BRCMF_E_PSM_WATCHDOG); + if (!IS_ERR_OR_NULL(drvr->dbgfs_dir)) debugfs_remove_recursive(drvr->dbgfs_dir); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/brcm80211/brcmfmac/debug.h index 48648ca44ba8..d0d9676f7f9d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h @@ -109,8 +109,8 @@ struct brcmf_pub; #ifdef DEBUG void brcmf_debugfs_init(void); void brcmf_debugfs_exit(void); -int brcmf_debugfs_attach(struct brcmf_pub *drvr); -void brcmf_debugfs_detach(struct brcmf_pub *drvr); +int brcmf_debug_attach(struct brcmf_pub *drvr); +void brcmf_debug_detach(struct brcmf_pub *drvr); struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, int (*read_fn)(struct seq_file *seq, void *data)); @@ -121,11 +121,11 @@ static inline void brcmf_debugfs_init(void) static inline void brcmf_debugfs_exit(void) { } -static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr) +static inline int brcmf_debug_attach(struct brcmf_pub *drvr) { return 0; } -static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr) +static inline void brcmf_debug_detach(struct brcmf_pub *drvr) { } static inline diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index 30baf352e234..36b386a000ca 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c @@ -448,6 +448,47 @@ brcmf_pcie_copy_mem_todev(struct brcmf_pciedev_info *devinfo, u32 mem_offset, } +static void +brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset, + void *dstaddr, u32 len) +{ + void __iomem *address = devinfo->tcm + mem_offset; + __le32 *dst32; + __le16 *dst16; + u8 *dst8; + + if (((ulong)address & 4) || ((ulong)dstaddr & 4) || (len & 4)) { + if (((ulong)address & 2) || ((ulong)dstaddr & 2) || (len & 2)) { + dst8 = (u8 *)dstaddr; + while (len) { + *dst8 = ioread8(address); + address++; + dst8++; + len--; + } + } else { + len = len / 2; + dst16 = (__le16 *)dstaddr; + while (len) { + *dst16 = cpu_to_le16(ioread16(address)); + address += 2; + dst16++; + len--; + } + } + } else { + len = len / 4; + dst32 = (__le32 *)dstaddr; + while (len) { + *dst32 = cpu_to_le32(ioread32(address)); + address += 4; + dst32++; + len--; + } + } +} + + #define WRITECC32(devinfo, reg, value) brcmf_pcie_write_reg32(devinfo, \ CHIPCREGOFFS(reg), value) @@ -1352,12 +1393,36 @@ static void brcmf_pcie_wowl_config(struct device *dev, bool enabled) } +static size_t brcmf_pcie_get_ramsize(struct device *dev) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie; + struct brcmf_pciedev_info *devinfo = buspub->devinfo; + + return devinfo->ci->ramsize - devinfo->ci->srsize; +} + + +static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie; + struct brcmf_pciedev_info *devinfo = buspub->devinfo; + + brcmf_dbg(PCIE, "dump at 0x%08X: len=%zu\n", devinfo->ci->rambase, len); + brcmf_pcie_copy_dev_tomem(devinfo, devinfo->ci->rambase, data, len); + return 0; +} + + static struct brcmf_bus_ops brcmf_pcie_bus_ops = { .txdata = brcmf_pcie_tx, .stop = brcmf_pcie_down, .txctl = brcmf_pcie_tx_ctlpkt, .rxctl = brcmf_pcie_rx_ctlpkt, .wowl_config = brcmf_pcie_wowl_config, + .get_ramsize = brcmf_pcie_get_ramsize, + .get_memdump = brcmf_pcie_get_memdump, }; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index 7f574f26cdef..7e74ac3ad815 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c @@ -3539,6 +3539,51 @@ done: return err; } +static size_t brcmf_sdio_bus_get_ramsize(struct device *dev) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio *bus = sdiodev->bus; + + return bus->ci->ramsize - bus->ci->srsize; +} + +static int brcmf_sdio_bus_get_memdump(struct device *dev, void *data, + size_t mem_size) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio *bus = sdiodev->bus; + int err; + int address; + int offset; + int len; + + brcmf_dbg(INFO, "dump at 0x%08x: size=%zu\n", bus->ci->rambase, + mem_size); + + address = bus->ci->rambase; + offset = err = 0; + sdio_claim_host(sdiodev->func[1]); + while (offset < mem_size) { + len = ((offset + MEMBLOCK) < mem_size) ? MEMBLOCK : + mem_size - offset; + err = brcmf_sdiod_ramrw(sdiodev, false, address, data, len); + if (err) { + brcmf_err("error %d on reading %d membytes at 0x%08x\n", + err, len, address); + goto done; + } + data += len; + offset += len; + address += len; + } + +done: + sdio_release_host(sdiodev->func[1]); + return err; +} + void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus) { if (!bus->dpc_triggered) { @@ -3987,7 +4032,9 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = { .txctl = brcmf_sdio_bus_txctl, .rxctl = brcmf_sdio_bus_rxctl, .gettxq = brcmf_sdio_bus_gettxq, - .wowl_config = brcmf_sdio_wowl_config + .wowl_config = brcmf_sdio_wowl_config, + .get_ramsize = brcmf_sdio_bus_get_ramsize, + .get_memdump = brcmf_sdio_bus_get_memdump, }; static void brcmf_sdio_firmware_callback(struct device *dev, -- cgit v1.2.3 From 185f0eb0b5fab0c9bfd7c5d322e2cd05b951d6e8 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 8 Oct 2015 20:33:12 +0200 Subject: brcmfmac: Fix race condition between USB probe/load and disconnect. When a USB device gets disconnected due to for example removal then it is possible that it is still in the loading phase due to the asynchronous load routines. These routines can then possible access memory which has been freed. Fix this by mutex locking the device init phase. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 29 ++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index daba86d881bc..689e64d004bc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -144,6 +144,7 @@ struct brcmf_usbdev_info { struct usb_device *usbdev; struct device *dev; + struct mutex dev_init_lock; int ctl_in_pipe, ctl_out_pipe; struct urb *ctl_urb; /* URB for control endpoint */ @@ -1204,6 +1205,8 @@ static void brcmf_usb_probe_phase2(struct device *dev, int ret; brcmf_dbg(USB, "Start fw downloading\n"); + + devinfo = bus->bus_priv.usb->devinfo; ret = check_file(fw->data); if (ret < 0) { brcmf_err("invalid firmware\n"); @@ -1211,7 +1214,6 @@ static void brcmf_usb_probe_phase2(struct device *dev, goto error; } - devinfo = bus->bus_priv.usb->devinfo; devinfo->image = fw->data; devinfo->image_len = fw->size; @@ -1224,9 +1226,11 @@ static void brcmf_usb_probe_phase2(struct device *dev, if (ret) goto error; + mutex_unlock(&devinfo->dev_init_lock); return; error: brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret); + mutex_unlock(&devinfo->dev_init_lock); device_release_driver(dev); } @@ -1264,6 +1268,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) if (ret) goto fail; /* we are done */ + mutex_unlock(&devinfo->dev_init_lock); return 0; } bus->chip = bus_pub->devid; @@ -1317,6 +1322,12 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) devinfo->usbdev = usb; devinfo->dev = &usb->dev; + /* Take an init lock, to protect for disconnect while still loading. + * Necessary because of the asynchronous firmware load construction + */ + mutex_init(&devinfo->dev_init_lock); + mutex_lock(&devinfo->dev_init_lock); + usb_set_intfdata(intf, devinfo); /* Check that the device supports only one configuration */ @@ -1391,6 +1402,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) return 0; fail: + mutex_unlock(&devinfo->dev_init_lock); kfree(devinfo); usb_set_intfdata(intf, NULL); return ret; @@ -1403,8 +1415,19 @@ brcmf_usb_disconnect(struct usb_interface *intf) brcmf_dbg(USB, "Enter\n"); devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf); - brcmf_usb_disconnect_cb(devinfo); - kfree(devinfo); + + if (devinfo) { + mutex_lock(&devinfo->dev_init_lock); + /* Make sure that devinfo still exists. Firmware probe routines + * may have released the device and cleared the intfdata. + */ + if (!usb_get_intfdata(intf)) + goto done; + + brcmf_usb_disconnect_cb(devinfo); + kfree(devinfo); + } +done: brcmf_dbg(USB, "Exit\n"); } -- cgit v1.2.3 From 4a3462843f9f363162314ca7667e24c146c7fa71 Mon Sep 17 00:00:00 2001 From: Franky Lin Date: Thu, 8 Oct 2015 20:33:13 +0200 Subject: brcmfmac: rename firmware_path to alternative_fw_path In brcmfmac the module parameter "firmware_path" is used as an alternative relative path under the search path used by firmware_class or ueventhelper. Rename the parameter to alternative_fw_path to avoid confusion. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Arend Van Spriel Reviewed-by: Hante Meuleman Signed-off-by: Franky Lin Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c index 971920f77b68..4248f3c80e78 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c @@ -29,7 +29,7 @@ #define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */ char brcmf_firmware_path[BRCMF_FW_PATH_LEN]; -module_param_string(firmware_path, brcmf_firmware_path, +module_param_string(alternative_fw_path, brcmf_firmware_path, BRCMF_FW_PATH_LEN, 0440); enum nvram_parser_state { -- cgit v1.2.3 From 43569bfaf6ed0ee5b44533ee9ded7e8323734687 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 8 Oct 2015 20:33:14 +0200 Subject: brcmfmac: remove conversational comment Removing a comment that was only useful during the review of the change that introduced it and which should never have been submitted. Reviewed-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c index 7eff9de6885b..44e618f9d890 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c @@ -873,9 +873,6 @@ brcmf_msgbuf_process_txstatus(struct brcmf_msgbuf *msgbuf, void *buf) commonring = msgbuf->flowrings[flowid]; atomic_dec(&commonring->outstanding_tx); - /* Hante: i believe this was a bug as tx_status->msg.ifidx was used - * in brcmf_txfinalize as index in drvr->iflist. Can you confirm/deny? - */ brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx), skb, true); } -- cgit v1.2.3 From 2b76acdbc0431a7d9e87eacb27bb537a211bed16 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 8 Oct 2015 20:33:15 +0200 Subject: brcmfmac: Rework p2p attach, use single method for p2p dev creation. When module param p2pon is used a p2p device is created at init. This patch reworks how this is done by using the same method as for a dynamically (by user space) created p2p device. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky (Zhenhui) Lin Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 18 ++++++ drivers/net/wireless/brcm80211/brcmfmac/core.c | 33 ++++------ drivers/net/wireless/brcm80211/brcmfmac/fweh.c | 3 +- drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 71 +++------------------- 4 files changed, 40 insertions(+), 85 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 891f4ed8c5e3..2ee57c0415e3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -6238,6 +6238,17 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, else *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; } + /* p2p might require that "if-events" get processed by fweh. So + * activate the already registered event handlers now and activate + * the rest when initialization has completed. drvr->config needs to + * be assigned before activating events. + */ + drvr->config = cfg; + err = brcmf_fweh_activate_events(ifp); + if (err) { + brcmf_err("FWEH activation failed (%d)\n", err); + goto wiphy_unreg_out; + } err = brcmf_p2p_attach(cfg, p2pdev_forced); if (err) { @@ -6260,6 +6271,13 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, brcmf_notify_tdls_peer_event); } + /* (re-) activate FWEH event handling */ + err = brcmf_fweh_activate_events(ifp); + if (err) { + brcmf_err("FWEH activation failed (%d)\n", err); + goto wiphy_unreg_out; + } + return cfg; wiphy_unreg_out: diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index a1d39b1966f7..d3212bf5b28f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -828,8 +828,8 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, } else { brcmf_dbg(INFO, "allocate netdev interface\n"); /* Allocate netdev, including space for private structure */ - ndev = alloc_netdev(sizeof(*ifp), name, NET_NAME_UNKNOWN, - ether_setup); + ndev = alloc_netdev(sizeof(*ifp), is_p2pdev ? "p2p%d" : name, + NET_NAME_UNKNOWN, ether_setup); if (!ndev) return ERR_PTR(-ENOMEM); @@ -1021,12 +1021,7 @@ int brcmf_bus_start(struct device *dev) if (IS_ERR(ifp)) return PTR_ERR(ifp); - if (brcmf_p2p_enable) - p2p_ifp = brcmf_add_if(drvr, 1, 0, false, "p2p%d", NULL); - else - p2p_ifp = NULL; - if (IS_ERR(p2p_ifp)) - p2p_ifp = NULL; + p2p_ifp = NULL; /* signal bus ready */ brcmf_bus_change_state(bus_if, BRCMF_BUS_UP); @@ -1060,11 +1055,13 @@ int brcmf_bus_start(struct device *dev) goto fail; } - ret = brcmf_fweh_activate_events(ifp); - if (ret < 0) - goto fail; - ret = brcmf_net_attach(ifp, false); + + if ((!ret) && (brcmf_p2p_enable)) { + p2p_ifp = drvr->iflist[1]; + if (p2p_ifp) + ret = brcmf_net_p2p_attach(p2p_ifp); + } fail: if (ret < 0) { brcmf_err("failed: %d\n", ret); @@ -1076,20 +1073,12 @@ fail: brcmf_fws_del_interface(ifp); brcmf_fws_deinit(drvr); } - if (drvr->iflist[0]) { + if (ifp) brcmf_net_detach(ifp->ndev); - drvr->iflist[0] = NULL; - } - if (p2p_ifp) { + if (p2p_ifp) brcmf_net_detach(p2p_ifp->ndev); - drvr->iflist[1] = NULL; - } return ret; } - if ((brcmf_p2p_enable) && (p2p_ifp)) - if (brcmf_net_p2p_attach(p2p_ifp) < 0) - brcmf_p2p_enable = 0; - return 0; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index 383d6faf426b..3878b6f6cfce 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -213,7 +213,8 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, is_p2pdev, emsg->ifname, emsg->addr); if (IS_ERR(ifp)) return; - brcmf_fws_add_interface(ifp); + if (!is_p2pdev) + brcmf_fws_add_interface(ifp); if (!drvr->fweh.evt_handler[BRCMF_E_IF]) if (brcmf_net_attach(ifp, false) < 0) return; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index 37a8c352e077..d224b3dd72ed 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c @@ -2353,83 +2353,30 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev) * brcmf_p2p_attach() - attach for P2P. * * @cfg: driver private data for cfg80211 interface. + * @p2pdev_forced: create p2p device interface at attach. */ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced) { - struct brcmf_if *pri_ifp; - struct brcmf_if *p2p_ifp; - struct brcmf_cfg80211_vif *p2p_vif; struct brcmf_p2p_info *p2p; - struct brcmf_pub *drvr; - s32 bssidx; + struct brcmf_if *pri_ifp; s32 err = 0; + void *err_ptr; p2p = &cfg->p2p; p2p->cfg = cfg; - drvr = cfg->pub; - - pri_ifp = brcmf_get_ifp(drvr, 0); + pri_ifp = brcmf_get_ifp(cfg->pub, 0); p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif; if (p2pdev_forced) { - p2p_ifp = drvr->iflist[1]; + err_ptr = brcmf_p2p_create_p2pdev(p2p, NULL, NULL); + if (IS_ERR(err_ptr)) { + brcmf_err("P2P device creation failed.\n"); + err = PTR_ERR(err_ptr); + } } else { - p2p_ifp = NULL; p2p->p2pdev_dynamically = true; } - if (p2p_ifp) { - p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE, - false); - if (IS_ERR(p2p_vif)) { - brcmf_err("could not create discovery vif\n"); - err = -ENOMEM; - goto exit; - } - - p2p_vif->ifp = p2p_ifp; - p2p_ifp->vif = p2p_vif; - p2p_vif->wdev.netdev = p2p_ifp->ndev; - p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev; - SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy)); - - p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; - - brcmf_p2p_generate_bss_mac(p2p, NULL); - memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); - brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); - - brcmf_fweh_p2pdev_setup(pri_ifp, true); - - /* Initialize P2P Discovery in the firmware */ - err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); - if (err < 0) { - brcmf_err("set p2p_disc error\n"); - brcmf_free_vif(p2p_vif); - goto exit; - } - /* obtain bsscfg index for P2P discovery */ - err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); - if (err < 0) { - brcmf_err("retrieving discover bsscfg index failed\n"); - brcmf_free_vif(p2p_vif); - goto exit; - } - /* Verify that firmware uses same bssidx as driver !! */ - if (p2p_ifp->bssidx != bssidx) { - brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n", - bssidx, p2p_ifp->bssidx); - brcmf_free_vif(p2p_vif); - goto exit; - } - - init_completion(&p2p->send_af_done); - INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); - init_completion(&p2p->afx_hdl.act_frm_scan); - init_completion(&p2p->wait_next_af); -exit: - brcmf_fweh_p2pdev_setup(pri_ifp, false); - } return err; } -- cgit v1.2.3 From 124d517211e4322366f087774dadae136c6cec8b Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 8 Oct 2015 20:33:16 +0200 Subject: brcmfmac: Fix station info rate information. Txrate and rxrate in get_station got assigned first with value in kbps and then divided by 100 to get it in 100kbps unit. The problem with that is that type of rate is u16 which resulted in incorrect values for high data rate values. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 2ee57c0415e3..73eddaddc660 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -2478,13 +2478,13 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts); if (sinfo->tx_packets) { sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); - sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate); - sinfo->txrate.legacy /= 100; + sinfo->txrate.legacy = + le32_to_cpu(sta_info_le.tx_rate) / 100; } if (sinfo->rx_packets) { sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE); - sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate); - sinfo->rxrate.legacy /= 100; + sinfo->rxrate.legacy = + le32_to_cpu(sta_info_le.rx_rate) / 100; } if (le16_to_cpu(sta_info_le.ver) >= 4) { sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES); -- cgit v1.2.3 From cae355dc90db2bd27bf5ed5400ab2a417a185faa Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 8 Oct 2015 20:33:17 +0200 Subject: brcmfmac: Add RSSI information to get_station. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 73eddaddc660..ca9d2398d026 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -2432,6 +2432,9 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, struct brcmf_sta_info_le sta_info_le; u32 sta_flags; u32 is_tdls_peer; + s32 total_rssi; + s32 count_rssi; + u32 i; brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac); if (!check_vif_up(ifp->vif)) @@ -2492,6 +2495,26 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES); sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes); } + total_rssi = 0; + count_rssi = 0; + for (i = 0; i < BRCMF_ANT_MAX; i++) { + if (sta_info_le.rssi[i]) { + sinfo->chain_signal_avg[count_rssi] = + sta_info_le.rssi[i]; + sinfo->chain_signal[count_rssi] = + sta_info_le.rssi[i]; + total_rssi += sta_info_le.rssi[i]; + count_rssi++; + } + } + if (count_rssi) { + sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL); + sinfo->chains = count_rssi; + + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); + total_rssi /= count_rssi; + sinfo->signal = total_rssi; + } } done: brcmf_dbg(TRACE, "Exit\n"); -- cgit v1.2.3 From bf2a7e0499b922b4d2ffc073a3d14cec93c33af1 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 8 Oct 2015 20:33:18 +0200 Subject: brcmfmac: Add dump_station support to cfg80221 ops. With this feature it becomes possible to request a station assoc list. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 30 ++++++++++++++++++++++ drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h | 1 + drivers/net/wireless/brcm80211/brcmfmac/fwil.h | 1 + .../net/wireless/brcm80211/brcmfmac/fwil_types.h | 13 ++++++++++ 4 files changed, 45 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index ca9d2398d026..18293377f338 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -2521,6 +2521,35 @@ done: return err; } +static int +brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev, + int idx, u8 *mac, struct station_info *sinfo) +{ + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_if *ifp = netdev_priv(ndev); + s32 err; + + brcmf_dbg(TRACE, "Enter, idx %d\n", idx); + + if (idx == 0) { + cfg->assoclist.count = cpu_to_le32(BRCMF_MAX_ASSOCLIST); + err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_ASSOCLIST, + &cfg->assoclist, + sizeof(cfg->assoclist)); + if (err) { + brcmf_err("BRCMF_C_GET_ASSOCLIST unsupported, err=%d\n", + err); + cfg->assoclist.count = 0; + return -EOPNOTSUPP; + } + } + if (idx < le32_to_cpu(cfg->assoclist.count)) { + memcpy(mac, cfg->assoclist.mac[idx], ETH_ALEN); + return brcmf_cfg80211_get_station(wiphy, ndev, mac, sinfo); + } + return -ENOENT; +} + static s32 brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, bool enabled, s32 timeout) @@ -4620,6 +4649,7 @@ static struct cfg80211_ops wl_cfg80211_ops = { .join_ibss = brcmf_cfg80211_join_ibss, .leave_ibss = brcmf_cfg80211_leave_ibss, .get_station = brcmf_cfg80211_get_station, + .dump_station = brcmf_cfg80211_dump_station, .set_tx_power = brcmf_cfg80211_set_tx_power, .get_tx_power = brcmf_cfg80211_get_tx_power, .add_key = brcmf_cfg80211_add_key, diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h index 3f5e5505d329..4d95c6e980f1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h @@ -407,6 +407,7 @@ struct brcmf_cfg80211_info { struct brcmu_d11inf d11inf; bool wowl_enabled; u32 pre_wowl_pmmode; + struct brcmf_assoclist_le assoclist; }; /** diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h index 5434dcf64f7d..b20fc0f82a48 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h @@ -72,6 +72,7 @@ #define BRCMF_C_GET_BSS_INFO 136 #define BRCMF_C_GET_BANDLIST 140 #define BRCMF_C_SET_SCB_TIMEOUT 158 +#define BRCMF_C_GET_ASSOCLIST 159 #define BRCMF_C_GET_PHYLIST 180 #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 #define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index 297911f38fa0..daa427b46712 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h @@ -119,6 +119,8 @@ #define BRCMF_COUNTRY_BUF_SZ 4 #define BRCMF_ANT_MAX 4 +#define BRCMF_MAX_ASSOCLIST 128 + /* join preference types for join_pref iovar */ enum brcmf_join_pref_types { BRCMF_JOIN_PREF_RSSI = 1, @@ -621,4 +623,15 @@ struct brcmf_rev_info_le { __le32 nvramrev; }; +/** + * struct brcmf_assoclist_le - request assoc list. + * + * @count: indicates number of stations. + * @mac: MAC addresses of stations. + */ +struct brcmf_assoclist_le { + __le32 count; + u8 mac[BRCMF_MAX_ASSOCLIST][ETH_ALEN]; +}; + #endif /* FWIL_TYPES_H_ */ -- cgit v1.2.3 From c443e169577c2dfb8172711ef4b765919d177429 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 8 Oct 2015 20:33:19 +0200 Subject: brcmfmac: Move brcmf_c_preinit_dcmds prototype to correct file. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/common.h | 3 +++ drivers/net/wireless/brcm80211/brcmfmac/core.c | 1 + drivers/net/wireless/brcm80211/brcmfmac/core.h | 3 --- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/common.h b/drivers/net/wireless/brcm80211/brcmfmac/common.h index 0d39d80cee28..21c7488b4732 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/common.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/common.h @@ -17,4 +17,7 @@ extern const u8 ALLFFMAC[ETH_ALEN]; +/* Sets dongle media info (drv_version, mac address). */ +int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); + #endif /* BRCMFMAC_COMMON_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index d3212bf5b28f..6e39121a1f37 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -33,6 +33,7 @@ #include "feature.h" #include "proto.h" #include "pcie.h" +#include "common.h" MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h index d81ff95acab5..f10fc377baa0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h @@ -214,7 +214,4 @@ 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); -/* Sets dongle media info (drv_version, mac address). */ -int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); - #endif /* BRCMFMAC_CORE_H */ -- cgit v1.2.3 From 54b499d9ad10dd0ce9b4ac92507072cad0f37f7a Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 8 Oct 2015 20:33:20 +0200 Subject: brcmfmac: Remove unused state AP creating. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 3 --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h | 2 -- 2 files changed, 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 18293377f338..ddb4e74f839d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -840,7 +840,6 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, err = brcmf_p2p_ifchange(cfg, BRCMF_FIL_P2P_IF_GO); } if (!err) { - set_bit(BRCMF_VIF_STATUS_AP_CREATING, &vif->sme_state); brcmf_dbg(INFO, "IF Type = AP\n"); } } else { @@ -4251,7 +4250,6 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, brcmf_dbg(TRACE, "GO mode configuration complete\n"); } - clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); exit: @@ -4316,7 +4314,6 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) } brcmf_set_mpc(ifp, 1); brcmf_configure_arp_offload(ifp, true); - set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); return err; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h index 4d95c6e980f1..6a878c8f883f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h @@ -143,7 +143,6 @@ struct brcmf_cfg80211_profile { * @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress. * @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully. * @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress. - * @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation. * @BRCMF_VIF_STATUS_AP_CREATED: AP operation started. */ enum brcmf_vif_status { @@ -151,7 +150,6 @@ enum brcmf_vif_status { BRCMF_VIF_STATUS_CONNECTING, BRCMF_VIF_STATUS_CONNECTED, BRCMF_VIF_STATUS_DISCONNECTING, - BRCMF_VIF_STATUS_AP_CREATING, BRCMF_VIF_STATUS_AP_CREATED }; -- cgit v1.2.3 From 92121e69de8a982c0b33b359ce68657b3ec3c83d Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 8 Oct 2015 20:33:21 +0200 Subject: brcmfmac: Properly set carrier state of netdev. Use the netif_carrier api to correctly set carrier state on the different modes. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Franky (Zhenhui) Lin Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 4 ++++ drivers/net/wireless/brcm80211/brcmfmac/core.c | 25 ++++++++++++++++++---- drivers/net/wireless/brcm80211/brcmfmac/core.h | 8 +++++-- 3 files changed, 31 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index ddb4e74f839d..deb5f78dcacc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -4251,6 +4251,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, brcmf_dbg(TRACE, "GO mode configuration complete\n"); } set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); + brcmf_net_setcarrier(ifp, true); exit: if ((err) && (!mbss)) { @@ -4315,6 +4316,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) brcmf_set_mpc(ifp, 1); brcmf_configure_arp_offload(ifp, true); clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); + brcmf_net_setcarrier(ifp, false); return err; } @@ -5024,6 +5026,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, &ifp->vif->sme_state); } else brcmf_bss_connect_done(cfg, ndev, e, true); + brcmf_net_setcarrier(ifp, true); } else if (brcmf_is_linkdown(e)) { brcmf_dbg(CONN, "Linkdown\n"); if (!brcmf_is_ibssmode(ifp->vif)) { @@ -5033,6 +5036,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, brcmf_init_prof(ndev_to_prof(ndev)); if (ndev != cfg_to_ndev(cfg)) complete(&cfg->vif_disabled); + brcmf_net_setcarrier(ifp, false); } else if (brcmf_is_nonetwork(cfg, e)) { if (brcmf_is_ibssmode(ifp->vif)) clear_bit(BRCMF_VIF_STATUS_CONNECTING, diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index 6e39121a1f37..b5ab98ee1445 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c @@ -635,8 +635,7 @@ static int brcmf_netdev_stop(struct net_device *ndev) brcmf_cfg80211_down(ndev); - /* Set state and stop OS transmissions */ - netif_stop_queue(ndev); + brcmf_net_setcarrier(ifp, false); return 0; } @@ -670,8 +669,8 @@ static int brcmf_netdev_open(struct net_device *ndev) return -EIO; } - /* Allow transmit calls */ - netif_start_queue(ndev); + /* Clear, carrier, set when connected or AP mode. */ + netif_carrier_off(ndev); return 0; } @@ -736,6 +735,24 @@ static void brcmf_net_detach(struct net_device *ndev) brcmf_cfg80211_free_netdev(ndev); } +void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on) +{ + struct net_device *ndev; + + brcmf_dbg(TRACE, "Enter, idx=%d carrier=%d\n", ifp->bssidx, on); + + ndev = ifp->ndev; + brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_DISCONNECTED, !on); + if (on) { + if (!netif_carrier_ok(ndev)) + netif_carrier_on(ndev); + + } else { + if (netif_carrier_ok(ndev)) + netif_carrier_off(ndev); + } +} + static int brcmf_net_p2p_open(struct net_device *ndev) { brcmf_dbg(TRACE, "Enter\n"); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h index f10fc377baa0..2f9101b2ad34 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h @@ -154,10 +154,13 @@ struct brcmf_fws_mac_descriptor; * netif stopped due to firmware signalling flow control. * @BRCMF_NETIF_STOP_REASON_FLOW: * netif stopped due to flowring full. + * @BRCMF_NETIF_STOP_REASON_DISCONNECTED: + * netif stopped due to not being connected (STA mode). */ enum brcmf_netif_stop_reason { - BRCMF_NETIF_STOP_REASON_FWS_FC = 1, - BRCMF_NETIF_STOP_REASON_FLOW = 2 + BRCMF_NETIF_STOP_REASON_FWS_FC = BIT(0), + BRCMF_NETIF_STOP_REASON_FLOW = BIT(1), + BRCMF_NETIF_STOP_REASON_DISCONNECTED = BIT(2) }; /** @@ -213,5 +216,6 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, enum brcmf_netif_stop_reason reason, bool state); void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); +void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); #endif /* BRCMFMAC_CORE_H */ -- cgit v1.2.3 From f8273bafcbc1bc04d1b139144f78f25c559f10c3 Mon Sep 17 00:00:00 2001 From: Eric Caruso Date: Wed, 14 Oct 2015 12:34:11 -0700 Subject: brcm80211: Add support for brcm4371 This is a new Broadcom chip and we should be able to recognize it. Signed-off-by: Eric Caruso Acked-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/brcm80211/brcmfmac/chip.c | 1 + drivers/net/wireless/brcm80211/brcmfmac/pcie.c | 9 +++++++++ drivers/net/wireless/brcm80211/include/brcm_hw_ids.h | 2 ++ 3 files changed, 12 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index ffc3ace24903..f04833db2fd0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c @@ -682,6 +682,7 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) case BRCM_CC_43570_CHIP_ID: case BRCM_CC_4358_CHIP_ID: case BRCM_CC_43602_CHIP_ID: + case BRCM_CC_4371_CHIP_ID: return 0x180000; case BRCM_CC_4365_CHIP_ID: case BRCM_CC_4366_CHIP_ID: diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index 36b386a000ca..83d804221715 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c @@ -59,6 +59,8 @@ enum brcmf_pcie_state { #define BRCMF_PCIE_4365_NVRAM_NAME "brcm/brcmfmac4365b-pcie.txt" #define BRCMF_PCIE_4366_FW_NAME "brcm/brcmfmac4366b-pcie.bin" #define BRCMF_PCIE_4366_NVRAM_NAME "brcm/brcmfmac4366b-pcie.txt" +#define BRCMF_PCIE_4371_FW_NAME "brcm/brcmfmac4371-pcie.bin" +#define BRCMF_PCIE_4371_NVRAM_NAME "brcm/brcmfmac4371-pcie.txt" #define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */ @@ -212,6 +214,8 @@ MODULE_FIRMWARE(BRCMF_PCIE_4365_FW_NAME); MODULE_FIRMWARE(BRCMF_PCIE_4365_NVRAM_NAME); MODULE_FIRMWARE(BRCMF_PCIE_4366_FW_NAME); MODULE_FIRMWARE(BRCMF_PCIE_4366_NVRAM_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4371_FW_NAME); +MODULE_FIRMWARE(BRCMF_PCIE_4371_NVRAM_NAME); struct brcmf_pcie_console { @@ -1521,6 +1525,10 @@ static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo) fw_name = BRCMF_PCIE_4366_FW_NAME; nvram_name = BRCMF_PCIE_4366_NVRAM_NAME; break; + case BRCM_CC_4371_CHIP_ID: + fw_name = BRCMF_PCIE_4371_FW_NAME; + nvram_name = BRCMF_PCIE_4371_NVRAM_NAME; + break; default: brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip); return -ENODEV; @@ -2060,6 +2068,7 @@ static struct pci_device_id brcmf_pcie_devid_table[] = { BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID), + BRCMF_PCIE_DEVICE(BRCM_PCIE_4371_DEVICE_ID), { /* end: all zeroes */ } }; diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h index d823734a4713..aa06ea231db3 100644 --- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h @@ -50,6 +50,7 @@ #define BRCM_CC_43602_CHIP_ID 43602 #define BRCM_CC_4365_CHIP_ID 0x4365 #define BRCM_CC_4366_CHIP_ID 0x4366 +#define BRCM_CC_4371_CHIP_ID 0x4371 /* USB Device IDs */ #define BRCM_USB_43143_DEVICE_ID 0xbd1e @@ -75,6 +76,7 @@ #define BRCM_PCIE_4366_DEVICE_ID 0x43c3 #define BRCM_PCIE_4366_2G_DEVICE_ID 0x43c4 #define BRCM_PCIE_4366_5G_DEVICE_ID 0x43c5 +#define BRCM_PCIE_4371_DEVICE_ID 0x440d /* brcmsmac IDs */ -- cgit v1.2.3 From aebd99477f03950fb05b29c7248656167198bf2d Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Thu, 15 Oct 2015 21:00:22 +0100 Subject: bcm63xx_enet: check 1000BASE-T advertisement configuration If a gigabit ethernet PHY is connected to a fast ethernet MAC, then it can detect 1000 support from the partner but not use it. This results in a forced speed of 1000 and RX/TX failure. Check for 1000BASE-T support and then check the advertisement configuration before setting the MAC speed to 1000mbit. Signed-off-by: Simon Arlott Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 33 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c index a7f2cc3e485e..4183c2abeeeb 100644 --- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c +++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c @@ -2049,7 +2049,7 @@ static void swphy_poll_timer(unsigned long data) for (i = 0; i < priv->num_ports; i++) { struct bcm63xx_enetsw_port *port; - int val, j, up, advertise, lpa, lpa2, speed, duplex, media; + int val, j, up, advertise, lpa, speed, duplex, media; int external_phy = bcm_enet_port_is_rgmii(i); u8 override; @@ -2092,22 +2092,27 @@ static void swphy_poll_timer(unsigned long data) lpa = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id, MII_LPA); - lpa2 = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id, - MII_STAT1000); - /* figure out media and duplex from advertise and LPA values */ media = mii_nway_result(lpa & advertise); duplex = (media & ADVERTISE_FULL) ? 1 : 0; - if (lpa2 & LPA_1000FULL) - duplex = 1; - - if (lpa2 & (LPA_1000FULL | LPA_1000HALF)) - speed = 1000; - else { - if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)) - speed = 100; - else - speed = 10; + + if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)) + speed = 100; + else + speed = 10; + + if (val & BMSR_ESTATEN) { + advertise = bcmenet_sw_mdio_read(priv, external_phy, + port->phy_id, MII_CTRL1000); + + lpa = bcmenet_sw_mdio_read(priv, external_phy, + port->phy_id, MII_STAT1000); + + if (advertise & (ADVERTISE_1000FULL | ADVERTISE_1000HALF) + && lpa & (LPA_1000FULL | LPA_1000HALF)) { + speed = 1000; + duplex = (lpa & LPA_1000FULL); + } } dev_info(&priv->pdev->dev, -- cgit v1.2.3 From 9e42f715264ff158478fa30eaed847f6e131366b Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Sat, 17 Oct 2015 06:04:35 +0200 Subject: drivers: net: cpsw: add phy-handle parsing add the ability to parse "phy-handle". This is needed for phys, which have a DT node, and need to parse DT properties. Signed-off-by: Heiko Schocher Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 8fc90f1c872c..874fb297e96c 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -365,6 +366,7 @@ struct cpsw_priv { spinlock_t lock; struct platform_device *pdev; struct net_device *ndev; + struct device_node *phy_node; struct napi_struct napi_rx; struct napi_struct napi_tx; struct device *dev; @@ -1145,7 +1147,11 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, 1 << slave_port, 0, 0, ALE_MCAST_FWD_2); - slave->phy = phy_connect(priv->ndev, slave->data->phy_id, + if (priv->phy_node) + slave->phy = of_phy_connect(priv->ndev, priv->phy_node, + &cpsw_adjust_link, 0, slave->data->phy_if); + else + slave->phy = phy_connect(priv->ndev, slave->data->phy_id, &cpsw_adjust_link, slave->data->phy_if); if (IS_ERR(slave->phy)) { dev_err(priv->dev, "phy %s not found on slave %d\n", @@ -1934,11 +1940,12 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv, slave->port_vlan = data->dual_emac_res_vlan; } -static int cpsw_probe_dt(struct cpsw_platform_data *data, +static int cpsw_probe_dt(struct cpsw_priv *priv, struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct device_node *slave_node; + struct cpsw_platform_data *data = &priv->data; int i = 0, ret; u32 prop; @@ -2029,6 +2036,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, if (strcmp(slave_node->name, "slave")) continue; + priv->phy_node = of_parse_phandle(slave_node, "phy-handle", 0); parp = of_get_property(slave_node, "phy_id", &lenp); if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) { dev_err(&pdev->dev, "Missing slave[%d] phy_id property\n", i); @@ -2044,7 +2052,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, } snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), PHY_ID_FMT, mdio->name, phyid); - slave_data->phy_if = of_get_phy_mode(slave_node); if (slave_data->phy_if < 0) { dev_err(&pdev->dev, "Missing or malformed slave[%d] phy-mode property\n", @@ -2240,7 +2247,7 @@ static int cpsw_probe(struct platform_device *pdev) /* Select default pin state */ pinctrl_pm_select_default_state(&pdev->dev); - if (cpsw_probe_dt(&priv->data, pdev)) { + if (cpsw_probe_dt(priv, pdev)) { dev_err(&pdev->dev, "cpsw: platform data missing\n"); ret = -ENODEV; goto clean_runtime_disable_ret; -- cgit v1.2.3 From d88ecb373bd1877acc43e13311a8e0e6daffc3d2 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Sat, 17 Oct 2015 06:04:36 +0200 Subject: net: phy: smsc: disable energy detect mode On some boards the energy enable detect mode leads in trouble with some switches, so make the enabling of this mode configurable through DT. Signed-off-by: Heiko Schocher Signed-off-by: David S. Miller --- drivers/net/phy/smsc.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index 70b08958763a..dc2da8770918 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -43,16 +43,25 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev) static int smsc_phy_config_init(struct phy_device *phydev) { + int __maybe_unused len; + struct device *dev __maybe_unused = &phydev->dev; + struct device_node *of_node __maybe_unused = dev->of_node; int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS); + int enable_energy = 1; if (rc < 0) return rc; - /* Enable energy detect mode for this SMSC Transceivers */ - rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, - rc | MII_LAN83C185_EDPWRDOWN); - if (rc < 0) - return rc; + if (of_find_property(of_node, "smsc,disable-energy-detect", &len)) + enable_energy = 0; + + if (enable_energy) { + /* Enable energy detect mode for this SMSC Transceivers */ + rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, + rc | MII_LAN83C185_EDPWRDOWN); + if (rc < 0) + return rc; + } return smsc_phy_ack_interrupt(phydev); } -- cgit v1.2.3 From 91986fd3d335a2ea651bc85cf5a03f2f61a2aa34 Mon Sep 17 00:00:00 2001 From: Philipp Kirchhofer Date: Sun, 18 Oct 2015 16:02:43 +0200 Subject: net: mv643xx_eth: Ensure proper data alignment in TSO TX path The TX DMA engine requires that buffers with a size of 8 bytes or smaller must be 64 bit aligned. This requirement may be violated when doing TSO, as in this case larger skb frags can be broken up and transmitted in small parts with then inappropriate alignment. Fix this by checking for proper alignment before handing a buffer to the DMA engine. If the data is misaligned realign it by copying it into the TSO header data area. Signed-off-by: Philipp Kirchhofer Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 960169efe636..c05fb794d1ff 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -759,11 +759,23 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq, desc->l4i_chk = 0; desc->byte_cnt = length; - desc->buf_ptr = dma_map_single(dev->dev.parent, data, - length, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev->dev.parent, desc->buf_ptr))) { - WARN(1, "dma_map_single failed!\n"); - return -ENOMEM; + + if (length <= 8 && (uintptr_t)data & 0x7) { + /* Copy unaligned small data fragment to TSO header data area */ + memcpy(txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE, + data, length); + desc->buf_ptr = txq->tso_hdrs_dma + + txq->tx_curr_desc * TSO_HEADER_SIZE; + } else { + /* Alignment is okay, map buffer and hand off to hardware */ + txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE; + desc->buf_ptr = dma_map_single(dev->dev.parent, data, + length, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(dev->dev.parent, + desc->buf_ptr))) { + WARN(1, "dma_map_single failed!\n"); + return -ENOMEM; + } } cmd_sts = BUFFER_OWNED_BY_DMA; -- cgit v1.2.3 From 968200f322daccc6f08fee26fe1bb4232e460408 Mon Sep 17 00:00:00 2001 From: Philipp Kirchhofer Date: Sun, 18 Oct 2015 16:02:44 +0200 Subject: net: mv643xx_eth: Defer writing the first TX descriptor when using TSO To prevent a race between the TX DMA engine and the CPU the writing of the first transmit descriptor must be deferred until all following descriptors have been updated. The network card may otherwise start transmitting before all packet descriptors are set up correctly, which leads to data corruption or an aborted transmit operation. This deferral is already done in the non-TSO TX path, implement it also in the TSO TX path. Signed-off-by: Philipp Kirchhofer Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index c05fb794d1ff..e893a35143c5 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -791,7 +791,8 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq, } static inline void -txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length) +txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length, + u32 *first_cmd_sts, bool first_desc) { struct mv643xx_eth_private *mp = txq_to_mp(txq); int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); @@ -800,6 +801,7 @@ txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length) int ret; u32 cmd_csum = 0; u16 l4i_chk = 0; + u32 cmd_sts; tx_index = txq->tx_curr_desc; desc = &txq->tx_desc_area[tx_index]; @@ -815,9 +817,17 @@ txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length) desc->byte_cnt = hdr_len; desc->buf_ptr = txq->tso_hdrs_dma + txq->tx_curr_desc * TSO_HEADER_SIZE; - desc->cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA | TX_FIRST_DESC | + cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA | TX_FIRST_DESC | GEN_CRC; + /* Defer updating the first command descriptor until all + * following descriptors have been written. + */ + if (first_desc) + *first_cmd_sts = cmd_sts; + else + desc->cmd_sts = cmd_sts; + txq->tx_curr_desc++; if (txq->tx_curr_desc == txq->tx_ring_size) txq->tx_curr_desc = 0; @@ -831,6 +841,8 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb, int desc_count = 0; struct tso_t tso; int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + struct tx_desc *first_tx_desc; + u32 first_cmd_sts = 0; /* Count needed descriptors */ if ((txq->tx_desc_count + tso_count_descs(skb)) >= txq->tx_ring_size) { @@ -838,11 +850,14 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb, return -EBUSY; } + first_tx_desc = &txq->tx_desc_area[txq->tx_curr_desc]; + /* Initialize the TSO handler, and prepare the first payload */ tso_start(skb, &tso); total_len = skb->len - hdr_len; while (total_len > 0) { + bool first_desc = (desc_count == 0); char *hdr; data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len); @@ -852,7 +867,8 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb, /* prepare packet headers: MAC + IP + TCP */ hdr = txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE; tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0); - txq_put_hdr_tso(skb, txq, data_left); + txq_put_hdr_tso(skb, txq, data_left, &first_cmd_sts, + first_desc); while (data_left > 0) { int size; @@ -872,6 +888,10 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb, __skb_queue_tail(&txq->tx_skb, skb); skb_tx_timestamp(skb); + /* ensure all other descriptors are written before first cmd_sts */ + wmb(); + first_tx_desc->cmd_sts = first_cmd_sts; + /* clear TX_END status */ mp->work_tx_end &= ~(1 << txq->index); -- cgit v1.2.3 From ca88ea1247dfee094e2467a3578eaec9bdf0833a Mon Sep 17 00:00:00 2001 From: Joe Jin Date: Mon, 19 Oct 2015 13:37:17 +0800 Subject: xen-netfront: update num_queues to real created Sometimes xennet_create_queues() may failed to created all requested queues, we need to update num_queues to real created to avoid NULL pointer dereference. Signed-off-by: Joe Jin Cc: Boris Ostrovsky Cc: Konrad Rzeszutek Wilk Cc: Wei Liu Cc: Ian Campbell Cc: David S. Miller Reviewed-by: Boris Ostrovsky Signed-off-by: David S. Miller --- drivers/net/xen-netfront.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index f821a97d7827..6febc053a37f 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1706,19 +1706,19 @@ static void xennet_destroy_queues(struct netfront_info *info) } static int xennet_create_queues(struct netfront_info *info, - unsigned int num_queues) + unsigned int *num_queues) { unsigned int i; int ret; - info->queues = kcalloc(num_queues, sizeof(struct netfront_queue), + info->queues = kcalloc(*num_queues, sizeof(struct netfront_queue), GFP_KERNEL); if (!info->queues) return -ENOMEM; rtnl_lock(); - for (i = 0; i < num_queues; i++) { + for (i = 0; i < *num_queues; i++) { struct netfront_queue *queue = &info->queues[i]; queue->id = i; @@ -1728,7 +1728,7 @@ static int xennet_create_queues(struct netfront_info *info, if (ret < 0) { dev_warn(&info->netdev->dev, "only created %d queues\n", i); - num_queues = i; + *num_queues = i; break; } @@ -1738,11 +1738,11 @@ static int xennet_create_queues(struct netfront_info *info, napi_enable(&queue->napi); } - netif_set_real_num_tx_queues(info->netdev, num_queues); + netif_set_real_num_tx_queues(info->netdev, *num_queues); rtnl_unlock(); - if (num_queues == 0) { + if (*num_queues == 0) { dev_err(&info->netdev->dev, "no queues\n"); return -EINVAL; } @@ -1788,7 +1788,7 @@ static int talk_to_netback(struct xenbus_device *dev, if (info->queues) xennet_destroy_queues(info); - err = xennet_create_queues(info, num_queues); + err = xennet_create_queues(info, &num_queues); if (err < 0) goto destroy_ring; -- cgit v1.2.3 From 7a4264a9250fc6d555ff305aa5e5168723805bb9 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Mon, 19 Oct 2015 17:37:13 +0200 Subject: net: cavium: change NET_VENDOR_CAVIUM to bool CONFIG_NET_VENDOR_CAVIUM is only used to hide/show config options and to include subdirectories in the build, so it doesn't make sense to make it tristate. Signed-off-by: Andreas Schwab Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig index 9b35d142f47a..8fb84e69c30e 100644 --- a/drivers/net/ethernet/cavium/Kconfig +++ b/drivers/net/ethernet/cavium/Kconfig @@ -3,7 +3,7 @@ # config NET_VENDOR_CAVIUM - tristate "Cavium ethernet drivers" + bool "Cavium ethernet drivers" depends on PCI default y ---help--- -- cgit v1.2.3 From 8f3af27786913851e720bc9466d1abffcfa7aff6 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 19 Oct 2015 20:17:59 -0700 Subject: net: dummy: add more features While testing my SIT/GRO patch using netfilter TEE module and a dummy device, I found some features were missing : TSO IPv6, UFO, and encapsulated traffic. ethtool -k dummy0 now gives : ... tcp-segmentation-offload: on tx-tcp-segmentation: on tx-tcp-ecn-segmentation: on tx-tcp6-segmentation: on udp-fragmentation-offload: on ... tx-gre-segmentation: on tx-ipip-segmentation: on tx-sit-segmentation: on tx-udp_tnl-segmentation: on Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/dummy.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 815eb94990f5..69fc8409a973 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -147,8 +147,12 @@ static void dummy_setup(struct net_device *dev) dev->flags |= IFF_NOARP; dev->flags &= ~IFF_MULTICAST; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE; - dev->features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO; + dev->features |= NETIF_F_SG | NETIF_F_FRAGLIST; + dev->features |= NETIF_F_ALL_TSO | NETIF_F_UFO; dev->features |= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX; + dev->features |= NETIF_F_GSO_ENCAP_ALL; + dev->hw_features |= dev->features; + dev->hw_enc_features |= dev->features; eth_hw_addr_random(dev); } -- cgit v1.2.3 From c6aa74d546ccb94c99a1e95fb461f8b0e9410a3e Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Tue, 20 Oct 2015 14:56:00 +0800 Subject: net: hisilicon: fix ptr_ret.cocci warnings drivers/net/ethernet/hisilicon/hns/hnae.c:442:1-3: WARNING: PTR_ERR_OR_ZERO can be used Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR Generated by: scripts/coccinelle/api/ptr_ret.cocci CC: Arnd Bergmann Signed-off-by: Fengguang Wu Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hnae.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.c b/drivers/net/ethernet/hisilicon/hns/hnae.c index 9d3bb8349a73..b3645297477e 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.c +++ b/drivers/net/ethernet/hisilicon/hns/hnae.c @@ -439,10 +439,7 @@ EXPORT_SYMBOL(hnae_ae_unregister); static int __init hnae_init(void) { hnae_class = class_create(THIS_MODULE, "hnae"); - if (IS_ERR(hnae_class)) - return PTR_ERR(hnae_class); - - return 0; + return PTR_ERR_OR_ZERO(hnae_class); } static void __exit hnae_exit(void) -- cgit v1.2.3 From 104eb270e665f4fcd8cb8c8ab4c4d4538c604e92 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 20 Oct 2015 10:42:24 +0200 Subject: net: sun4i-emac: Properly free resources on probe failure and remove Fix sun4i-emac not releasing the following resources: -iomapped memory not released on probe-failure nor on remove -clock not getting disabled on probe-failure nor on remove -sram not being released on remove And while at it also add error checking to the clk_prepare_enable call done on probe. Signed-off-by: Hans de Goede Acked-by: Maxime Ripard Signed-off-by: David S. Miller --- drivers/net/ethernet/allwinner/sun4i-emac.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index 48ce83e443c2..8d50314ac3eb 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -847,21 +847,25 @@ static int emac_probe(struct platform_device *pdev) if (ndev->irq == -ENXIO) { netdev_err(ndev, "No irq resource\n"); ret = ndev->irq; - goto out; + goto out_iounmap; } db->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(db->clk)) { ret = PTR_ERR(db->clk); - goto out; + goto out_iounmap; } - clk_prepare_enable(db->clk); + ret = clk_prepare_enable(db->clk); + if (ret) { + dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret); + goto out_iounmap; + } ret = sunxi_sram_claim(&pdev->dev); if (ret) { dev_err(&pdev->dev, "Error couldn't map SRAM to device\n"); - goto out; + goto out_clk_disable_unprepare; } db->phy_node = of_parse_phandle(np, "phy", 0); @@ -910,6 +914,10 @@ static int emac_probe(struct platform_device *pdev) out_release_sram: sunxi_sram_release(&pdev->dev); +out_clk_disable_unprepare: + clk_disable_unprepare(db->clk); +out_iounmap: + iounmap(db->membase); out: dev_err(db->dev, "not found (%d).\n", ret); @@ -921,8 +929,12 @@ out: static int emac_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); + struct emac_board_info *db = netdev_priv(ndev); unregister_netdev(ndev); + sunxi_sram_release(&pdev->dev); + clk_disable_unprepare(db->clk); + iounmap(db->membase); free_netdev(ndev); dev_dbg(&pdev->dev, "released and freed device\n"); -- cgit v1.2.3 From e2aacd963a06fc558a809ecb62f5833e6c340b28 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Tue, 20 Oct 2015 10:08:59 -0400 Subject: net: mdio-gpio: move platform data header This header file only contains the platform data structure definition, so move it to the include/linux/platform_data/ directory. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/phy/mdio-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index 3bc9f03349f3..95f51d7267b3 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include -- cgit v1.2.3 From 279998059729422fc0d551b5deb266a174cbab47 Mon Sep 17 00:00:00 2001 From: Hariprasad S Date: Wed, 23 Sep 2015 17:19:26 +0530 Subject: cxgb4: T6 adapter lld support for iw_cxgb4 driver Signed-off-by: Hariprasad Shenai Signed-off-by: Doug Ledford --- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 41 +---------- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 22 ++++++ drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 2 + drivers/net/ethernet/chelsio/cxgb4/t4_chip_type.h | 85 +++++++++++++++++++++++ drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | 48 +++++++++++++ 5 files changed, 158 insertions(+), 40 deletions(-) create mode 100644 drivers/net/ethernet/chelsio/cxgb4/t4_chip_type.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index fa0c7b54ec7a..11045ec8d94c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -48,6 +48,7 @@ #include #include #include +#include "t4_chip_type.h" #include "cxgb4_uld.h" #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__) @@ -290,31 +291,6 @@ struct pci_params { unsigned char width; }; -#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision)) -#define CHELSIO_CHIP_FPGA 0x100 -#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf) -#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf) - -#define CHELSIO_T4 0x4 -#define CHELSIO_T5 0x5 -#define CHELSIO_T6 0x6 - -enum chip_type { - T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1), - T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2), - T4_FIRST_REV = T4_A1, - T4_LAST_REV = T4_A2, - - T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0), - T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1), - T5_FIRST_REV = T5_A0, - T5_LAST_REV = T5_A1, - - T6_A0 = CHELSIO_CHIP_CODE(CHELSIO_T6, 0), - T6_FIRST_REV = T6_A0, - T6_LAST_REV = T6_A0, -}; - struct devlog_params { u32 memtype; /* which memory (EDC0, EDC1, MC) */ u32 start; /* start of log in firmware memory */ @@ -905,21 +881,6 @@ static inline int is_offload(const struct adapter *adap) return adap->params.offload; } -static inline int is_t6(enum chip_type chip) -{ - return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T6; -} - -static inline int is_t5(enum chip_type chip) -{ - return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T5; -} - -static inline int is_t4(enum chip_type chip) -{ - return CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4; -} - static inline u32 t4_read_reg(struct adapter *adap, u32 reg_addr) { return readl(adap->regs + reg_addr); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index f5dcde27e402..aeeb21ff0de2 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -1935,6 +1935,28 @@ unsigned int cxgb4_best_aligned_mtu(const unsigned short *mtus, } EXPORT_SYMBOL(cxgb4_best_aligned_mtu); +/** + * cxgb4_tp_smt_idx - Get the Source Mac Table index for this VI + * @chip: chip type + * @viid: VI id of the given port + * + * Return the SMT index for this VI. + */ +unsigned int cxgb4_tp_smt_idx(enum chip_type chip, unsigned int viid) +{ + /* In T4/T5, SMT contains 256 SMAC entries organized in + * 128 rows of 2 entries each. + * In T6, SMT contains 256 SMAC entries in 256 rows. + * TODO: The below code needs to be updated when we add support + * for 256 VFs. + */ + if (CHELSIO_CHIP_VERSION(chip) <= CHELSIO_T5) + return ((viid & 0x7f) << 1); + else + return (viid & 0x7f); +} +EXPORT_SYMBOL(cxgb4_tp_smt_idx); + /** * cxgb4_port_chan - get the HW channel of a port * @dev: the net device for the port diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index c3a8be5541e7..cf711d5f15be 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -40,6 +40,7 @@ #include #include #include +#include "cxgb4.h" /* CPL message priority levels */ enum { @@ -290,6 +291,7 @@ int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb); unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo); unsigned int cxgb4_port_chan(const struct net_device *dev); unsigned int cxgb4_port_viid(const struct net_device *dev); +unsigned int cxgb4_tp_smt_idx(enum chip_type chip, unsigned int viid); unsigned int cxgb4_port_idx(const struct net_device *dev); unsigned int cxgb4_best_mtu(const unsigned short *mtus, unsigned short mtu, unsigned int *idx); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_chip_type.h b/drivers/net/ethernet/chelsio/cxgb4/t4_chip_type.h new file mode 100644 index 000000000000..54b718111e3f --- /dev/null +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_chip_type.h @@ -0,0 +1,85 @@ +/* + * This file is part of the Chelsio T4 Ethernet driver for Linux. + * + * Copyright (c) 2003-2015 Chelsio Communications, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __T4_CHIP_TYPE_H__ +#define __T4_CHIP_TYPE_H__ + +#define CHELSIO_T4 0x4 +#define CHELSIO_T5 0x5 +#define CHELSIO_T6 0x6 + +/* We code the Chelsio T4 Family "Chip Code" as a tuple: + * + * (Chip Version, Chip Revision) + * + * where: + * + * Chip Version: is T4, T5, etc. + * Chip Revision: is the FAB "spin" of the Chip Version. + */ +#define CHELSIO_CHIP_CODE(version, revision) (((version) << 4) | (revision)) +#define CHELSIO_CHIP_VERSION(code) (((code) >> 4) & 0xf) +#define CHELSIO_CHIP_RELEASE(code) ((code) & 0xf) + +enum chip_type { + T4_A1 = CHELSIO_CHIP_CODE(CHELSIO_T4, 1), + T4_A2 = CHELSIO_CHIP_CODE(CHELSIO_T4, 2), + T4_FIRST_REV = T4_A1, + T4_LAST_REV = T4_A2, + + T5_A0 = CHELSIO_CHIP_CODE(CHELSIO_T5, 0), + T5_A1 = CHELSIO_CHIP_CODE(CHELSIO_T5, 1), + T5_FIRST_REV = T5_A0, + T5_LAST_REV = T5_A1, + + T6_A0 = CHELSIO_CHIP_CODE(CHELSIO_T6, 0), + T6_FIRST_REV = T6_A0, + T6_LAST_REV = T6_A0, +}; + +static inline int is_t4(enum chip_type chip) +{ + return (CHELSIO_CHIP_VERSION(chip) == CHELSIO_T4); +} + +static inline int is_t5(enum chip_type chip) +{ + return (CHELSIO_CHIP_VERSION(chip) == CHELSIO_T5); +} + +static inline int is_t6(enum chip_type chip) +{ + return (CHELSIO_CHIP_VERSION(chip) == CHELSIO_T6); +} + +#endif /* __T4_CHIP_TYPE_H__ */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h index b99144afd4ec..a072d341e205 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h @@ -417,6 +417,21 @@ struct cpl_t5_act_open_req { __be64 params; }; +struct cpl_t6_act_open_req { + WR_HDR; + union opcode_tid ot; + __be16 local_port; + __be16 peer_port; + __be32 local_ip; + __be32 peer_ip; + __be64 opt0; + __be32 rsvd; + __be32 opt2; + __be64 params; + __be32 rsvd2; + __be32 opt3; +}; + struct cpl_act_open_req6 { WR_HDR; union opcode_tid ot; @@ -446,6 +461,23 @@ struct cpl_t5_act_open_req6 { __be64 params; }; +struct cpl_t6_act_open_req6 { + WR_HDR; + union opcode_tid ot; + __be16 local_port; + __be16 peer_port; + __be64 local_ip_hi; + __be64 local_ip_lo; + __be64 peer_ip_hi; + __be64 peer_ip_lo; + __be64 opt0; + __be32 rsvd; + __be32 opt2; + __be64 params; + __be32 rsvd2; + __be32 opt3; +}; + struct cpl_act_open_rpl { union opcode_tid ot; __be32 atid_status; @@ -504,6 +536,19 @@ struct cpl_pass_establish { #define TCPOPT_MSS_M 0xF #define TCPOPT_MSS_G(x) (((x) >> TCPOPT_MSS_S) & TCPOPT_MSS_M) +#define T6_TCP_HDR_LEN_S 8 +#define T6_TCP_HDR_LEN_V(x) ((x) << T6_TCP_HDR_LEN_S) +#define T6_TCP_HDR_LEN_G(x) (((x) >> T6_TCP_HDR_LEN_S) & TCP_HDR_LEN_M) + +#define T6_IP_HDR_LEN_S 14 +#define T6_IP_HDR_LEN_V(x) ((x) << T6_IP_HDR_LEN_S) +#define T6_IP_HDR_LEN_G(x) (((x) >> T6_IP_HDR_LEN_S) & IP_HDR_LEN_M) + +#define T6_ETH_HDR_LEN_S 24 +#define T6_ETH_HDR_LEN_M 0xFF +#define T6_ETH_HDR_LEN_V(x) ((x) << T6_ETH_HDR_LEN_S) +#define T6_ETH_HDR_LEN_G(x) (((x) >> T6_ETH_HDR_LEN_S) & T6_ETH_HDR_LEN_M) + struct cpl_act_establish { union opcode_tid ot; __be32 rsvd; @@ -833,6 +878,9 @@ struct cpl_rx_pkt { __be16 err_vec; }; +#define RX_T6_ETHHDR_LEN_M 0xFF +#define RX_T6_ETHHDR_LEN_G(x) (((x) >> RX_ETHHDR_LEN_S) & RX_T6_ETHHDR_LEN_M) + #define RXF_PSH_S 20 #define RXF_PSH_V(x) ((x) << RXF_PSH_S) #define RXF_PSH_F RXF_PSH_V(1U) -- cgit v1.2.3 From 9a8928359736ab170303ee8a2cc15db54e3a4a8f Mon Sep 17 00:00:00 2001 From: Maor Gottlieb Date: Thu, 15 Oct 2015 14:44:38 +0300 Subject: net/mlx4_core: Add support for filtering multicast loopback Update device capabilities regarding HW filtering multicast loopback support. Add MLX4_UPDATE_QP_ETH_SRC_CHECK_MC_LB attribute to mlx4_update_qp to enable changing QP context to support filtering incoming multicast loopback traffic according the sender's counter index. Set the corresponding bits in QP context to force the loopback source checks if attribute is given and HW supports it. Signed-off-by: Maor Gottlieb Signed-off-by: Eran Ben Elisha Signed-off-by: Doug Ledford --- drivers/net/ethernet/mellanox/mlx4/fw.c | 6 +++++ drivers/net/ethernet/mellanox/mlx4/qp.c | 19 +++++++++++++- .../net/ethernet/mellanox/mlx4/resource_tracker.c | 30 +++++++++++++++++----- 3 files changed, 47 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index e8ec1dec5789..b3be3a060311 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -155,6 +155,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) [27] = "Port beacon support", [28] = "RX-ALL support", [29] = "802.1ad offload support", + [31] = "Modifying loopback source checks using UPDATE_QP support", + [32] = "Loopback source checks support", }; int i; @@ -964,6 +966,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET); if (field32 & (1 << 16)) dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP; + if (field32 & (1 << 18)) + dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB; + if (field32 & (1 << 19)) + dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_LB_SRC_CHK; if (field32 & (1 << 26)) dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL; if (field32 & (1 << 20)) diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index 20268634a9ab..b16249577aa2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -436,6 +436,23 @@ int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn, cmd->qp_context.pri_path.grh_mylmc = params->smac_index; } + if (attr & MLX4_UPDATE_QP_ETH_SRC_CHECK_MC_LB) { + if (!(dev->caps.flags2 + & MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB)) { + mlx4_warn(dev, + "Trying to set src check LB, but it isn't supported\n"); + err = -ENOTSUPP; + goto out; + } + pri_addr_path_mask |= + 1ULL << MLX4_UPD_QP_PATH_MASK_ETH_SRC_CHECK_MC_LB; + if (params->flags & + MLX4_UPDATE_QP_PARAMS_FLAGS_ETH_CHECK_MC_LB) { + cmd->qp_context.pri_path.fl |= + MLX4_FL_ETH_SRC_CHECK_MC_LB; + } + } + if (attr & MLX4_UPDATE_QP_VSD) { qp_mask |= 1ULL << MLX4_UPD_QP_MASK_VSD; if (params->flags & MLX4_UPDATE_QP_PARAMS_FLAGS_VSD_ENABLE) @@ -458,7 +475,7 @@ int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn, err = mlx4_cmd(dev, mailbox->dma, qpn & 0xffffff, 0, MLX4_CMD_UPDATE_QP, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); - +out: mlx4_free_cmd_mailbox(dev, mailbox); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 731423ca575d..502f3350088e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -770,9 +770,12 @@ static int update_vport_qp_param(struct mlx4_dev *dev, } } + /* preserve IF_COUNTER flag */ + qpc->pri_path.vlan_control &= + MLX4_CTRL_ETH_SRC_CHECK_IF_COUNTER; if (vp_oper->state.link_state == IFLA_VF_LINK_STATE_DISABLE && dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP) { - qpc->pri_path.vlan_control = + qpc->pri_path.vlan_control |= MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | MLX4_VLAN_CTRL_ETH_TX_BLOCK_PRIO_TAGGED | MLX4_VLAN_CTRL_ETH_TX_BLOCK_UNTAGGED | @@ -780,12 +783,12 @@ static int update_vport_qp_param(struct mlx4_dev *dev, MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED | MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED; } else if (0 != vp_oper->state.default_vlan) { - qpc->pri_path.vlan_control = + qpc->pri_path.vlan_control |= MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED | MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED; } else { /* priority tagged */ - qpc->pri_path.vlan_control = + qpc->pri_path.vlan_control |= MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED; } @@ -3762,9 +3765,6 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave, update_gid(dev, inbox, (u8)slave); adjust_proxy_tun_qkey(dev, vhcr, qpc); orig_sched_queue = qpc->pri_path.sched_queue; - err = update_vport_qp_param(dev, inbox, slave, qpn); - if (err) - return err; err = get_res(dev, slave, qpn, RES_QP, &qp); if (err) @@ -3774,6 +3774,10 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave, goto out; } + err = update_vport_qp_param(dev, inbox, slave, qpn); + if (err) + goto out; + err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); out: /* if no error, save sched queue value passed in by VF. This is @@ -4208,7 +4212,9 @@ static int add_eth_header(struct mlx4_dev *dev, int slave, } -#define MLX4_UPD_QP_PATH_MASK_SUPPORTED (1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX) +#define MLX4_UPD_QP_PATH_MASK_SUPPORTED ( \ + 1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX |\ + 1ULL << MLX4_UPD_QP_PATH_MASK_ETH_SRC_CHECK_MC_LB) int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, @@ -4231,6 +4237,16 @@ int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave, (pri_addr_path_mask & ~MLX4_UPD_QP_PATH_MASK_SUPPORTED)) return -EPERM; + if ((pri_addr_path_mask & + (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_SRC_CHECK_MC_LB)) && + !(dev->caps.flags2 & + MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB)) { + mlx4_warn(dev, + "Src check LB for slave %d isn't supported\n", + slave); + return -ENOTSUPP; + } + /* Just change the smac for the QP */ err = get_res(dev, slave, qpn, RES_QP, &rqp); if (err) { -- cgit v1.2.3 From 74194fb9c80cedb3130d26802c52deec3caebc75 Mon Sep 17 00:00:00 2001 From: Maor Gottlieb Date: Thu, 15 Oct 2015 14:44:39 +0300 Subject: net/mlx4_en: Implement mcast loopback prevention for ETH qps Set the mcast loopback prevention bit in the QPC for ETH MLX QPs (not RSS QPs), when the firmware supports this feature. In addition, all rx ring QPs need to be updated in order not to enforce loopback checks. This prevents getting packets we sent both from the network stack and the HCA. Loopback prevention is done by comparing the counter indices of the sent and receiving QPs. If they're equal, packets aren't loopback-ed. Signed-off-by: Maor Gottlieb Signed-off-by: Eran Ben Elisha Signed-off-by: Doug Ledford --- drivers/net/ethernet/mellanox/mlx4/en_main.c | 22 ++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx4/en_resources.c | 25 +++++++++++++++++++++++ drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 3 ++- 3 files changed, 49 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c index a946e4bf71d2..005f910ec955 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c @@ -123,6 +123,28 @@ void mlx4_en_update_loopback_state(struct net_device *dev, */ if (mlx4_is_mfunc(priv->mdev->dev) || priv->validate_loopback) priv->flags |= MLX4_EN_FLAG_ENABLE_HW_LOOPBACK; + + mutex_lock(&priv->mdev->state_lock); + if (priv->mdev->dev->caps.flags2 & + MLX4_DEV_CAP_FLAG2_UPDATE_QP_SRC_CHECK_LB && + priv->rss_map.indir_qp.qpn) { + int i; + int err = 0; + int loopback = !!(features & NETIF_F_LOOPBACK); + + for (i = 0; i < priv->rx_ring_num; i++) { + int ret; + + ret = mlx4_en_change_mcast_lb(priv, + &priv->rss_map.qps[i], + loopback); + if (!err) + err = ret; + } + if (err) + mlx4_warn(priv->mdev, "failed to change mcast loopback\n"); + } + mutex_unlock(&priv->mdev->state_lock); } static int mlx4_en_get_profile(struct mlx4_en_dev *mdev) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c index e482fa1bb741..12aab5a659d3 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_resources.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c @@ -69,6 +69,15 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride, context->pri_path.counter_index = priv->counter_index; context->cqn_send = cpu_to_be32(cqn); context->cqn_recv = cpu_to_be32(cqn); + if (!rss && + (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_LB_SRC_CHK) && + context->pri_path.counter_index != + MLX4_SINK_COUNTER_INDEX(mdev->dev)) { + /* disable multicast loopback to qp with same counter */ + if (!(dev->features & NETIF_F_LOOPBACK)) + context->pri_path.fl |= MLX4_FL_ETH_SRC_CHECK_MC_LB; + context->pri_path.control |= MLX4_CTRL_ETH_SRC_CHECK_IF_COUNTER; + } context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2); if (!(dev->features & NETIF_F_HW_VLAN_CTAG_RX)) context->param3 |= cpu_to_be32(1 << 30); @@ -80,6 +89,22 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride, } } +int mlx4_en_change_mcast_lb(struct mlx4_en_priv *priv, struct mlx4_qp *qp, + int loopback) +{ + int ret; + struct mlx4_update_qp_params qp_params; + + memset(&qp_params, 0, sizeof(qp_params)); + if (!loopback) + qp_params.flags = MLX4_UPDATE_QP_PARAMS_FLAGS_ETH_CHECK_MC_LB; + + ret = mlx4_update_qp(priv->mdev->dev, qp->qpn, + MLX4_UPDATE_QP_ETH_SRC_CHECK_MC_LB, + &qp_params); + + return ret; +} int mlx4_en_map_buffer(struct mlx4_buf *buf) { diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index defcf8c395bf..c41f15102ae0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -798,7 +798,8 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride, void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event); int mlx4_en_map_buffer(struct mlx4_buf *buf); void mlx4_en_unmap_buffer(struct mlx4_buf *buf); - +int mlx4_en_change_mcast_lb(struct mlx4_en_priv *priv, struct mlx4_qp *qp, + int loopback); void mlx4_en_calc_rx_buf(struct net_device *dev); int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv); void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv); -- cgit v1.2.3 From 34e45ad9378c31ef2b59e8bd63d62f0ca8e719a3 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Tue, 20 Oct 2015 16:28:57 -0500 Subject: net: phy: dp83848: Add TI DP83848 Ethernet PHY Add support for the TI DP83848 Ethernet PHY device. The DP83848 is a highly reliable, feature rich, IEEE 802.3 compliant single port 10/100 Mb/s Ethernet Physical Layer Transceiver supporting the MII and RMII interfaces. Signed-off-by: Andrew F. Davis Signed-off-by: Dan Murphy Reviewed-by: Florian Fainelli Acked-by: Dan Murphy Signed-off-by: David S. Miller --- drivers/net/phy/Kconfig | 5 +++ drivers/net/phy/Makefile | 1 + drivers/net/phy/dp83848.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 drivers/net/phy/dp83848.c (limited to 'drivers/net') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 11e3975485c1..436972b2a746 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -122,6 +122,11 @@ config MICREL_PHY ---help--- Supports the KSZ9021, VSC8201, KS8001 PHYs. +config DP83848_PHY + tristate "Driver for Texas Instruments DP83848 PHY" + ---help--- + Supports the DP83848 PHY. + config DP83867_PHY tristate "Drivers for Texas Instruments DP83867 Gigabit PHY" ---help--- diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 87f079c4b2c7..b74822463930 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o obj-$(CONFIG_NATIONAL_PHY) += national.o obj-$(CONFIG_DP83640_PHY) += dp83640.o +obj-$(CONFIG_DP83848_PHY) += dp83848.o obj-$(CONFIG_DP83867_PHY) += dp83867.o obj-$(CONFIG_STE10XP) += ste10Xp.o obj-$(CONFIG_MICREL_PHY) += micrel.o diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c new file mode 100644 index 000000000000..5ce9bef54468 --- /dev/null +++ b/drivers/net/phy/dp83848.c @@ -0,0 +1,99 @@ +/* + * Driver for the Texas Instruments DP83848 PHY + * + * Copyright (C) 2015 Texas Instruments Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#define DP83848_PHY_ID 0x20005c90 + +/* Registers */ +#define DP83848_MICR 0x11 +#define DP83848_MISR 0x12 + +/* MICR Register Fields */ +#define DP83848_MICR_INT_OE BIT(0) /* Interrupt Output Enable */ +#define DP83848_MICR_INTEN BIT(1) /* Interrupt Enable */ + +/* MISR Register Fields */ +#define DP83848_MISR_RHF_INT_EN BIT(0) /* Receive Error Counter */ +#define DP83848_MISR_FHF_INT_EN BIT(1) /* False Carrier Counter */ +#define DP83848_MISR_ANC_INT_EN BIT(2) /* Auto-negotiation complete */ +#define DP83848_MISR_DUP_INT_EN BIT(3) /* Duplex Status */ +#define DP83848_MISR_SPD_INT_EN BIT(4) /* Speed status */ +#define DP83848_MISR_LINK_INT_EN BIT(5) /* Link status */ +#define DP83848_MISR_ED_INT_EN BIT(6) /* Energy detect */ +#define DP83848_MISR_LQM_INT_EN BIT(7) /* Link Quality Monitor */ + +static int dp83848_ack_interrupt(struct phy_device *phydev) +{ + int err = phy_read(phydev, DP83848_MISR); + + return err < 0 ? err : 0; +} + +static int dp83848_config_intr(struct phy_device *phydev) +{ + int err; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { + err = phy_write(phydev, DP83848_MICR, + DP83848_MICR_INT_OE | + DP83848_MICR_INTEN); + if (err < 0) + return err; + + return phy_write(phydev, DP83848_MISR, + DP83848_MISR_ANC_INT_EN | + DP83848_MISR_DUP_INT_EN | + DP83848_MISR_SPD_INT_EN | + DP83848_MISR_LINK_INT_EN); + } + + return phy_write(phydev, DP83848_MICR, 0x0); +} + +static struct mdio_device_id __maybe_unused dp83848_tbl[] = { + { DP83848_PHY_ID, 0xfffffff0 }, + { } +}; +MODULE_DEVICE_TABLE(mdio, dp83848_tbl); + +static struct phy_driver dp83848_driver[] = { + { + .phy_id = DP83848_PHY_ID, + .phy_id_mask = 0xfffffff0, + .name = "TI DP83848", + .features = PHY_BASIC_FEATURES, + .flags = PHY_HAS_INTERRUPT, + + .soft_reset = genphy_soft_reset, + .config_init = genphy_config_init, + .suspend = genphy_suspend, + .resume = genphy_resume, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + + /* IRQ related */ + .ack_interrupt = dp83848_ack_interrupt, + .config_intr = dp83848_config_intr, + + .driver = { .owner = THIS_MODULE, }, + }, +}; +module_phy_driver(dp83848_driver); + +MODULE_DESCRIPTION("Texas Instruments DP83848 PHY driver"); +MODULE_AUTHOR("Andrew F. Davis Date: Tue, 20 Oct 2015 16:47:33 -0700 Subject: ipvlan: read direct ifindex instead of iflink In the ipv4 outbound path of an ipvlan device in l3 mode, the ifindex is being grabbed from dev_get_iflink. This works for the physical device case, since as the documentation of that function notes: "Physical interfaces have the same 'ifindex' and 'iflink' values.". However, if the master device is a veth, and the pairs are in separate net namespaces, the route lookup will fail with -ENODEV due to outer veth pair being in a separate namespace from the ipvlan master/routing namespace. ns0 | ns1 | ns2 veth0a--|--veth0b--|--ipvl0 In ipvlan_process_v4_outbound(), a packet sent from ipvl0 in the above configuration will pass fl.flowi4_oif == veth0a to ip_route_output_flow(), but *net == ns1. Notice also that ipv6 processing is not using iflink. Since there is a discrepancy in usage, fixup both v4 and v6 case to use local dev variable. Tested this with l3 ipvlan on top of veth, as well as with single physical interface in the top namespace. Signed-off-by: Brenden Blanco Reviewed-by: Jiri Benc Acked-by: Mahesh Bandewar Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 24f8dbcf854f..d50887e3df6d 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -348,7 +348,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb) struct rtable *rt; int err, ret = NET_XMIT_DROP; struct flowi4 fl4 = { - .flowi4_oif = dev_get_iflink(dev), + .flowi4_oif = dev->ifindex, .flowi4_tos = RT_TOS(ip4h->tos), .flowi4_flags = FLOWI_FLAG_ANYSRC, .daddr = ip4h->daddr, @@ -386,7 +386,7 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb) struct dst_entry *dst; int err, ret = NET_XMIT_DROP; struct flowi6 fl6 = { - .flowi6_iif = skb->dev->ifindex, + .flowi6_iif = dev->ifindex, .daddr = ip6h->daddr, .saddr = ip6h->saddr, .flowi6_flags = FLOWI_FLAG_ANYSRC, -- cgit v1.2.3 From eed7342d4b53a697603d568ab8d10561273def42 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Wed, 21 Oct 2015 14:39:50 +0530 Subject: cxgb4: Align ethtool get stat settings Align the ethtool get stats settings with the rest so it looks uniform Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 146 ++++++++++----------- 1 file changed, 73 insertions(+), 73 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c index 02e4e028a647..1127642a2327 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c @@ -35,79 +35,79 @@ static void set_msglevel(struct net_device *dev, u32 val) } static const char stats_strings[][ETH_GSTRING_LEN] = { - "TxOctetsOK ", - "TxFramesOK ", - "TxBroadcastFrames ", - "TxMulticastFrames ", - "TxUnicastFrames ", - "TxErrorFrames ", - - "TxFrames64 ", - "TxFrames65To127 ", - "TxFrames128To255 ", - "TxFrames256To511 ", - "TxFrames512To1023 ", - "TxFrames1024To1518 ", - "TxFrames1519ToMax ", - - "TxFramesDropped ", - "TxPauseFrames ", - "TxPPP0Frames ", - "TxPPP1Frames ", - "TxPPP2Frames ", - "TxPPP3Frames ", - "TxPPP4Frames ", - "TxPPP5Frames ", - "TxPPP6Frames ", - "TxPPP7Frames ", - - "RxOctetsOK ", - "RxFramesOK ", - "RxBroadcastFrames ", - "RxMulticastFrames ", - "RxUnicastFrames ", - - "RxFramesTooLong ", - "RxJabberErrors ", - "RxFCSErrors ", - "RxLengthErrors ", - "RxSymbolErrors ", - "RxRuntFrames ", - - "RxFrames64 ", - "RxFrames65To127 ", - "RxFrames128To255 ", - "RxFrames256To511 ", - "RxFrames512To1023 ", - "RxFrames1024To1518 ", - "RxFrames1519ToMax ", - - "RxPauseFrames ", - "RxPPP0Frames ", - "RxPPP1Frames ", - "RxPPP2Frames ", - "RxPPP3Frames ", - "RxPPP4Frames ", - "RxPPP5Frames ", - "RxPPP6Frames ", - "RxPPP7Frames ", - - "RxBG0FramesDropped ", - "RxBG1FramesDropped ", - "RxBG2FramesDropped ", - "RxBG3FramesDropped ", - "RxBG0FramesTrunc ", - "RxBG1FramesTrunc ", - "RxBG2FramesTrunc ", - "RxBG3FramesTrunc ", - - "TSO ", - "TxCsumOffload ", - "RxCsumGood ", - "VLANextractions ", - "VLANinsertions ", - "GROpackets ", - "GROmerged ", + "tx_octets_ok ", + "tx_frames_ok ", + "tx_broadcast_frames ", + "tx_multicast_frames ", + "tx_unicast_frames ", + "tx_error_frames ", + + "tx_frames_64 ", + "tx_frames_65_to_127 ", + "tx_frames_128_to_255 ", + "tx_frames_256_to_511 ", + "tx_frames_512_to_1023 ", + "tx_frames_1024_to_1518 ", + "tx_frames_1519_to_max ", + + "tx_frames_dropped ", + "tx_pause_frames ", + "tx_ppp0_frames ", + "tx_ppp1_frames ", + "tx_ppp2_frames ", + "tx_ppp3_frames ", + "tx_ppp4_frames ", + "tx_ppp5_frames ", + "tx_ppp6_frames ", + "tx_ppp7_frames ", + + "rx_octets_ok ", + "rx_frames_ok ", + "rx_broadcast_frames ", + "rx_multicast_frames ", + "rx_unicast_frames ", + + "rx_frames_too_long ", + "rx_jabber_errors ", + "rx_fcs_errors ", + "rx_length_errors ", + "rx_symbol_errors ", + "rx_runt_frames ", + + "rx_frames_64 ", + "rx_frames_65_to_127 ", + "rx_frames_128_to_255 ", + "rx_frames_256_to_511 ", + "rx_frames_512_to_1023 ", + "rx_frames_1024_to_1518 ", + "rx_frames_1519_to_max ", + + "rx_pause_frames ", + "rx_ppp0_frames ", + "rx_ppp1_frames ", + "rx_ppp2_frames ", + "rx_ppp3_frames ", + "rx_ppp4_frames ", + "rx_ppp5_frames ", + "rx_ppp6_frames ", + "rx_ppp7_frames ", + + "rx_bg0_frames_dropped ", + "rx_bg1_frames_dropped ", + "rx_bg2_frames_dropped ", + "rx_bg3_frames_dropped ", + "rx_bg0_frames_trunc ", + "rx_bg1_frames_trunc ", + "rx_bg2_frames_trunc ", + "rx_bg3_frames_trunc ", + + "tso ", + "tx_csum_offload ", + "rx_csum_good ", + "vlan_extractions ", + "vlan_insertions ", + "gro_packets ", + "gro_merged ", }; static char adapter_stats_strings[][ETH_GSTRING_LEN] = { -- cgit v1.2.3 From 9bfdad5ef555d92639a8b2a9e75e1f51ea3235d6 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Wed, 21 Oct 2015 14:39:51 +0530 Subject: cxgb4: Don't disallow turning off auto-negotiation For {1, 10, 40} Gb/s. Prohibiting turning off autonegotiation isn't anywhere in the standard. Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c index 1127642a2327..1487c57ffa70 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c @@ -629,10 +629,7 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (cmd->autoneg == AUTONEG_DISABLE) { cap = speed_to_caps(speed); - if (!(lc->supported & cap) || - (speed == 1000) || - (speed == 10000) || - (speed == 40000)) + if (!(lc->supported & cap)) return -EINVAL; lc->requested_speed = cap; lc->advertising = 0; -- cgit v1.2.3 From 4116542897be9cb5eaae7fdbfd5b2ddeaaaaeaef Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Wed, 21 Oct 2015 14:39:52 +0530 Subject: cxgb4: Restore L1 cfg, if FW rejects new L1 cfg settings In the ethtool set_settings() routine we need to remember our old L1 Configuration in case the firmware rejects the request and then restore that. Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c index 1487c57ffa70..b7b8c46a27fd 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c @@ -612,6 +612,8 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) struct port_info *p = netdev_priv(dev); struct link_config *lc = &p->link_cfg; u32 speed = ethtool_cmd_speed(cmd); + struct link_config old_lc; + int ret; if (cmd->duplex != DUPLEX_FULL) /* only full-duplex supported */ return -EINVAL; @@ -626,6 +628,7 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) return -EINVAL; } + old_lc = *lc; if (cmd->autoneg == AUTONEG_DISABLE) { cap = speed_to_caps(speed); @@ -642,10 +645,14 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) } lc->autoneg = cmd->autoneg; - if (netif_running(dev)) - return t4_link_l1cfg(p->adapter, p->adapter->pf, p->tx_chan, - lc); - return 0; + /* If the firmware rejects the Link Configuration request, back out + * the changes and report the error. + */ + ret = t4_link_l1cfg(p->adapter, p->adapter->mbox, p->tx_chan, lc); + if (ret) + *lc = old_lc; + + return ret; } static void get_pauseparam(struct net_device *dev, -- cgit v1.2.3 From 43eb4e82ebf7e3442a724ab9ecd69322eccad530 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Wed, 21 Oct 2015 14:39:53 +0530 Subject: cxgb4: Add info print to display number of MSI-X vectors allocated Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index c29227ee9ee8..a40dab7892c1 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -4485,6 +4485,10 @@ static int enable_msix(struct adapter *adap) } for (i = 0; i < allocated; ++i) adap->msix_info[i].vec = entries[i].vector; + dev_info(adap->pdev_dev, "%d MSI-X vectors allocated, " + "nic %d iscsi %d rdma cpl %d rdma ciq %d\n", + allocated, s->max_ethqsets, s->ofldqsets, s->rdmaqs, + s->rdmaciqs); kfree(entries); return 0; -- cgit v1.2.3 From 52a5f8463b10e49da93190dd0ee24e7f1c4860fd Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Wed, 21 Oct 2015 14:39:54 +0530 Subject: cxgb4/cxgb4vf: Update driver desc. to include Chelsio T6 adapter Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 3 ++- drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index a40dab7892c1..2cf81857a297 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -83,7 +83,7 @@ char cxgb4_driver_name[] = KBUILD_MODNAME; #endif #define DRV_VERSION "2.0.0-ko" const char cxgb4_driver_version[] = DRV_VERSION; -#define DRV_DESC "Chelsio T4/T5 Network Driver" +#define DRV_DESC "Chelsio T4/T5/T6 Network Driver" /* Host shadow copy of ingress filter entry. This is in host native format * and doesn't match the ordering or bit order, etc. of the hardware of the @@ -151,6 +151,7 @@ MODULE_VERSION(DRV_VERSION); MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl); MODULE_FIRMWARE(FW4_FNAME); MODULE_FIRMWARE(FW5_FNAME); +MODULE_FIRMWARE(FW6_FNAME); /* * Normally we're willing to become the firmware's Master PF but will be happy diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index b2b5e5bbe04c..0cfa5d72cafd 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -56,7 +56,7 @@ * Generic information about the driver. */ #define DRV_VERSION "2.0.0-ko" -#define DRV_DESC "Chelsio T4/T5 Virtual Function (VF) Network Driver" +#define DRV_DESC "Chelsio T4/T5/T6 Virtual Function (VF) Network Driver" /* * Module Parameters. -- cgit v1.2.3 From 6ac5fe75df57299cfbd89eb35a36d979742a69d8 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Wed, 21 Oct 2015 14:39:55 +0530 Subject: cxgb4: Return error if setup_rss is called before probe Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c index b7b8c46a27fd..59374dcf22b6 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c @@ -1015,11 +1015,15 @@ static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key, if (!p) return 0; - for (i = 0; i < pi->rss_size; i++) - pi->rss[i] = p[i]; - if (pi->adapter->flags & FULL_INIT_DONE) + /* Interface must be brought up atleast once */ + if (pi->adapter->flags & FULL_INIT_DONE) { + for (i = 0; i < pi->rss_size; i++) + pi->rss[i] = p[i]; + return cxgb4_write_rss(pi, pi->rss); - return 0; + } + + return -EPERM; } static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, -- cgit v1.2.3 From 9c673d156256f427657f0114eea981aaeefa3828 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Wed, 21 Oct 2015 14:39:56 +0530 Subject: cxgb4: Use vmalloc, if kmalloc fails Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c index 59374dcf22b6..43e0bc59f3a9 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c @@ -851,7 +851,7 @@ static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e, { int i, err = 0; struct adapter *adapter = netdev2adap(dev); - u8 *buf = kmalloc(EEPROMSIZE, GFP_KERNEL); + u8 *buf = t4_alloc_mem(EEPROMSIZE); if (!buf) return -ENOMEM; @@ -862,7 +862,7 @@ static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e, if (!err) memcpy(data, buf + e->offset, e->len); - kfree(buf); + t4_free_mem(buf); return err; } @@ -891,7 +891,7 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) { /* RMW possibly needed for first or last words. */ - buf = kmalloc(aligned_len, GFP_KERNEL); + buf = t4_alloc_mem(aligned_len); if (!buf) return -ENOMEM; err = eeprom_rd_phys(adapter, aligned_offset, (u32 *)buf); @@ -919,7 +919,7 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, err = t4_seeprom_wp(adapter, true); out: if (buf != data) - kfree(buf); + t4_free_mem(buf); return err; } -- cgit v1.2.3 From b08f2b35692e640e942deb49bbabe47a264f0023 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Wed, 21 Oct 2015 14:39:57 +0530 Subject: cxgb4: Update ethtool get_drvinfo to get regdump len Update ethtool get_drvinfo to display regdump len and also update firmware string version print to display N/A in case FW isn't present Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c index 43e0bc59f3a9..a077f9476daf 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c @@ -211,8 +211,11 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) sizeof(info->version)); strlcpy(info->bus_info, pci_name(adapter->pdev), sizeof(info->bus_info)); + info->regdump_len = get_regs_len(dev); - if (adapter->params.fw_vers) + if (!adapter->params.fw_vers) + strcpy(info->fw_version, "N/A"); + else snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u.%u.%u, TP %u.%u.%u.%u", FW_HDR_FW_VER_MAJOR_G(adapter->params.fw_vers), -- cgit v1.2.3 From c7fc9eb79a89049214f9870a6cf978050aaea43a Mon Sep 17 00:00:00 2001 From: yankejian Date: Wed, 21 Oct 2015 17:57:44 +0800 Subject: net: hisilicon: deals with the sub ctrl by syscon the global Soc configuration is treated by syscon, and sub ctrl bus is Soc bus. it has to be treated by syscon. Signed-off-by: yankejian Signed-off-by: lisheng Signed-off-by: lipeng Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns_mdio.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c index e4ec52ae61ff..37491c85bc42 100644 --- a/drivers/net/ethernet/hisilicon/hns_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include #include #define MDIO_DRV_NAME "Hi-HNS_MDIO" @@ -36,7 +38,7 @@ struct hns_mdio_device { void *vbase; /* mdio reg base address */ - void *sys_vbase; + struct regmap *subctrl_vbase; }; /* mdio reg */ @@ -155,10 +157,10 @@ static int mdio_sc_cfg_reg_write(struct hns_mdio_device *mdio_dev, u32 time_cnt; u32 reg_value; - mdio_write_reg((void *)mdio_dev->sys_vbase, cfg_reg, set_val); + regmap_write(mdio_dev->subctrl_vbase, cfg_reg, set_val); for (time_cnt = MDIO_TIMEOUT; time_cnt; time_cnt--) { - reg_value = mdio_read_reg((void *)mdio_dev->sys_vbase, st_reg); + regmap_read(mdio_dev->subctrl_vbase, st_reg, ®_value); reg_value &= st_msk; if ((!!check_st) == (!!reg_value)) break; @@ -352,7 +354,7 @@ static int hns_mdio_reset(struct mii_bus *bus) struct hns_mdio_device *mdio_dev = (struct hns_mdio_device *)bus->priv; int ret; - if (!mdio_dev->sys_vbase) { + if (!mdio_dev->subctrl_vbase) { dev_err(&bus->dev, "mdio sys ctl reg has not maped\n"); return -ENODEV; } @@ -455,13 +457,12 @@ static int hns_mdio_probe(struct platform_device *pdev) return ret; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - mdio_dev->sys_vbase = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(mdio_dev->sys_vbase)) { - ret = PTR_ERR(mdio_dev->sys_vbase); - return ret; + mdio_dev->subctrl_vbase = + syscon_node_to_regmap(of_parse_phandle(np, "subctrl_vbase", 0)); + if (IS_ERR(mdio_dev->subctrl_vbase)) { + dev_warn(&pdev->dev, "no syscon hisilicon,peri-c-subctrl\n"); + mdio_dev->subctrl_vbase = NULL; } - new_bus->irq = devm_kcalloc(&pdev->dev, PHY_MAX_ADDR, sizeof(int), GFP_KERNEL); if (!new_bus->irq) -- cgit v1.2.3 From 36d04ba127eeed94b003155129c7509a2139b474 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 22 Oct 2015 09:34:39 -0400 Subject: net: dsa: mv88e6xxx: write VID outside of VTU Get Next code There is no need to write the VLAN ID before every Get Next operation, since the VTU VID register is not cleared between calls. Move the VID write call in a _mv88e6xxx_vtu_vid_write function outside of _mv88e6xxx_vtu_getnext so future code could call VTU Get Next multiple times and save a few register accesses. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 4591240eb795..4b6baa6e90cd 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1259,7 +1259,13 @@ static int _mv88e6xxx_vtu_stu_data_write(struct dsa_switch *ds, return 0; } -static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, u16 vid, +static int _mv88e6xxx_vtu_vid_write(struct dsa_switch *ds, u16 vid) +{ + return _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_VID, + vid & GLOBAL_VTU_VID_MASK); +} + +static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, struct mv88e6xxx_vtu_stu_entry *entry) { struct mv88e6xxx_vtu_stu_entry next = { 0 }; @@ -1269,11 +1275,6 @@ static int _mv88e6xxx_vtu_getnext(struct dsa_switch *ds, u16 vid, if (ret < 0) return ret; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_VTU_VID, - vid & GLOBAL_VTU_VID_MASK); - if (ret < 0) - return ret; - ret = _mv88e6xxx_vtu_cmd(ds, GLOBAL_VTU_OP_VTU_GET_NEXT); if (ret < 0) return ret; @@ -1485,7 +1486,12 @@ int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid, int err; mutex_lock(&ps->smi_mutex); - err = _mv88e6xxx_vtu_getnext(ds, vid - 1, &vlan); + + err = _mv88e6xxx_vtu_vid_write(ds, vid - 1); + if (err) + goto unlock; + + err = _mv88e6xxx_vtu_getnext(ds, &vlan); if (err) goto unlock; @@ -1514,7 +1520,11 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) mutex_lock(&ps->smi_mutex); - err = _mv88e6xxx_vtu_getnext(ds, vid - 1, &vlan); + err = _mv88e6xxx_vtu_vid_write(ds, vid - 1); + if (err) + goto unlock; + + err = _mv88e6xxx_vtu_getnext(ds, &vlan); if (err) goto unlock; @@ -1558,7 +1568,11 @@ static int _mv88e6xxx_port_vtu_getnext(struct dsa_switch *ds, int port, u16 vid, if (vid == 4095) return -ENOENT; - err = _mv88e6xxx_vtu_getnext(ds, vid, entry); + err = _mv88e6xxx_vtu_vid_write(ds, vid); + if (err) + return err; + + err = _mv88e6xxx_vtu_getnext(ds, entry); if (err) return err; @@ -1584,7 +1598,12 @@ int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid, return -ENOENT; mutex_lock(&ps->smi_mutex); - err = _mv88e6xxx_vtu_getnext(ds, *vid, &next); + err = _mv88e6xxx_vtu_vid_write(ds, *vid); + if (err) + goto unlock; + + err = _mv88e6xxx_vtu_getnext(ds, &next); +unlock: mutex_unlock(&ps->smi_mutex); if (err) -- cgit v1.2.3 From b0e1a692ff17a37031af03599fbb3666e82c777b Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 22 Oct 2015 09:34:40 -0400 Subject: net: dsa: mv88e6xxx: write MAC outside of ATU Get Next code There is no need to write the MAC address before every Get Next operation, since ATU MAC registers are not cleared between calls. Move the _mv88e6xxx_atu_mac_write call outside of _mv88e6xxx_atu_getnext so future code could call ATU Get Next multiple times and save a few register access. Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 4b6baa6e90cd..86cbb677b7a8 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1751,7 +1751,6 @@ int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, } static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, - const unsigned char *addr, struct mv88e6xxx_atu_entry *entry) { struct mv88e6xxx_atu_entry next = { 0 }; @@ -1763,10 +1762,6 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, if (ret < 0) return ret; - ret = _mv88e6xxx_atu_mac_write(ds, addr); - if (ret < 0) - return ret; - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, fid); if (ret < 0) return ret; @@ -1827,7 +1822,11 @@ int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, fid = vtu.fid; } - ret = _mv88e6xxx_atu_getnext(ds, fid, addr, &next); + ret = _mv88e6xxx_atu_mac_write(ds, addr); + if (ret < 0) + goto unlock; + + ret = _mv88e6xxx_atu_getnext(ds, fid, &next); if (ret < 0) goto unlock; -- cgit v1.2.3 From f33475bd678e3c052f585d5660373ee7e957c742 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 22 Oct 2015 09:34:41 -0400 Subject: net: dsa: mv88e6xxx: implement port_fdb_dump Implement the port_fdb_dump DSA operation. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6171.c | 1 + drivers/net/dsa/mv88e6352.c | 1 + drivers/net/dsa/mv88e6xxx.c | 65 +++++++++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx.h | 3 +++ 4 files changed, 70 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index dfca352e78e3..489deb8853b3 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -123,6 +123,7 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .port_fdb_add = mv88e6xxx_port_fdb_add, .port_fdb_del = mv88e6xxx_port_fdb_del, .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, + .port_fdb_dump = mv88e6xxx_port_fdb_dump, }; MODULE_ALIAS("platform:mv88e6171"); diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 796fdcbe3c6e..6b8fd2468d1a 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -350,6 +350,7 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .port_fdb_add = mv88e6xxx_port_fdb_add, .port_fdb_del = mv88e6xxx_port_fdb_del, .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, + .port_fdb_dump = mv88e6xxx_port_fdb_dump, }; MODULE_ALIAS("platform:mv88e6172"); diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 86cbb677b7a8..8d0acf3f64de 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1799,6 +1799,71 @@ static int _mv88e6xxx_atu_getnext(struct dsa_switch *ds, u16 fid, return 0; } +int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, + struct switchdev_obj_port_fdb *fdb, + int (*cb)(struct switchdev_obj *obj)) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + struct mv88e6xxx_vtu_stu_entry vlan = { + .vid = GLOBAL_VTU_VID_MASK, /* all ones */ + }; + int err; + + mutex_lock(&ps->smi_mutex); + + err = _mv88e6xxx_vtu_vid_write(ds, vlan.vid); + if (err) + goto unlock; + + do { + struct mv88e6xxx_atu_entry addr = { + .mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + }; + + err = _mv88e6xxx_vtu_getnext(ds, &vlan); + if (err) + goto unlock; + + if (!vlan.valid) + break; + + err = _mv88e6xxx_atu_mac_write(ds, addr.mac); + if (err) + goto unlock; + + do { + err = _mv88e6xxx_atu_getnext(ds, vlan.fid, &addr); + if (err) + goto unlock; + + if (addr.state == GLOBAL_ATU_DATA_STATE_UNUSED) + break; + + if (!addr.trunk && addr.portv_trunkid & BIT(port)) { + bool is_static = addr.state == + (is_multicast_ether_addr(addr.mac) ? + GLOBAL_ATU_DATA_STATE_MC_STATIC : + GLOBAL_ATU_DATA_STATE_UC_STATIC); + + fdb->vid = vlan.vid; + ether_addr_copy(fdb->addr, addr.mac); + fdb->ndm_state = is_static ? NUD_NOARP : + NUD_REACHABLE; + + err = cb(&fdb->obj); + if (err) + goto unlock; + } + } while (!is_broadcast_ether_addr(addr.mac)); + + } while (vlan.vid < GLOBAL_VTU_VID_MASK); + +unlock: + mutex_unlock(&ps->smi_mutex); + + return err; +} + /* get next entry for port */ int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, unsigned char *addr, u16 *vid, bool *is_static) diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 4ba69f339bfe..3c9cfde0cb0f 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -476,6 +476,9 @@ int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_fdb *fdb); int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, unsigned char *addr, u16 *vid, bool *is_static); +int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, + struct switchdev_obj_port_fdb *fdb, + int (*cb)(struct switchdev_obj *obj)); int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg); int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, int reg, int val); -- cgit v1.2.3 From 2c49471b6695c5bac0d36c30ca07b8c311cd7cc3 Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 22 Oct 2015 09:34:42 -0400 Subject: net: dsa: mv88e6xxx: remove port_fdb_getnext Now that port_fdb_dump is implemented and even simpler, get rid of port_fdb_getnext. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6171.c | 1 - drivers/net/dsa/mv88e6352.c | 1 - drivers/net/dsa/mv88e6xxx.c | 73 --------------------------------------------- drivers/net/dsa/mv88e6xxx.h | 2 -- 4 files changed, 77 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 489deb8853b3..2c8eb6f76ebe 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -122,7 +122,6 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .port_fdb_prepare = mv88e6xxx_port_fdb_prepare, .port_fdb_add = mv88e6xxx_port_fdb_add, .port_fdb_del = mv88e6xxx_port_fdb_del, - .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, .port_fdb_dump = mv88e6xxx_port_fdb_dump, }; diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 6b8fd2468d1a..cbf4dd8721a6 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -349,7 +349,6 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .port_fdb_prepare = mv88e6xxx_port_fdb_prepare, .port_fdb_add = mv88e6xxx_port_fdb_add, .port_fdb_del = mv88e6xxx_port_fdb_del, - .port_fdb_getnext = mv88e6xxx_port_fdb_getnext, .port_fdb_dump = mv88e6xxx_port_fdb_dump, }; diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 8d0acf3f64de..39664d8667af 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1559,33 +1559,6 @@ unlock: return err; } -static int _mv88e6xxx_port_vtu_getnext(struct dsa_switch *ds, int port, u16 vid, - struct mv88e6xxx_vtu_stu_entry *entry) -{ - int err; - - do { - if (vid == 4095) - return -ENOENT; - - err = _mv88e6xxx_vtu_vid_write(ds, vid); - if (err) - return err; - - err = _mv88e6xxx_vtu_getnext(ds, entry); - if (err) - return err; - - if (!entry->valid) - return -ENOENT; - - vid = entry->vid; - } while (entry->data[port] != GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED && - entry->data[port] != GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED); - - return 0; -} - int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid, unsigned long *ports, unsigned long *untagged) { @@ -1864,52 +1837,6 @@ unlock: return err; } -/* get next entry for port */ -int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, - unsigned char *addr, u16 *vid, bool *is_static) -{ - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - struct mv88e6xxx_atu_entry next; - u16 fid = *vid; /* We use one FID per VLAN */ - int ret; - - mutex_lock(&ps->smi_mutex); - - do { - if (is_broadcast_ether_addr(addr)) { - struct mv88e6xxx_vtu_stu_entry vtu; - - ret = _mv88e6xxx_port_vtu_getnext(ds, port, *vid, &vtu); - if (ret < 0) - goto unlock; - - *vid = vtu.vid; - fid = vtu.fid; - } - - ret = _mv88e6xxx_atu_mac_write(ds, addr); - if (ret < 0) - goto unlock; - - ret = _mv88e6xxx_atu_getnext(ds, fid, &next); - if (ret < 0) - goto unlock; - - ether_addr_copy(addr, next.mac); - - if (next.state == GLOBAL_ATU_DATA_STATE_UNUSED) - continue; - } while (next.trunk || (next.portv_trunkid & BIT(port)) == 0); - - *is_static = next.state == (is_multicast_ether_addr(addr) ? - GLOBAL_ATU_DATA_STATE_MC_STATIC : - GLOBAL_ATU_DATA_STATE_UC_STATIC); -unlock: - mutex_unlock(&ps->smi_mutex); - - return ret; -} - static void mv88e6xxx_bridge_work(struct work_struct *work) { struct mv88e6xxx_priv_state *ps; diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 3c9cfde0cb0f..430de4fa1fec 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -474,8 +474,6 @@ int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, struct switchdev_trans *trans); int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_fdb *fdb); -int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port, - unsigned char *addr, u16 *vid, bool *is_static); int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port, struct switchdev_obj_port_fdb *fdb, int (*cb)(struct switchdev_obj *obj)); -- cgit v1.2.3 From 0db65fcfcded76fe4f74e3ca9f4e2baf67b683ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 22 Oct 2015 14:15:58 +0200 Subject: qmi_wwan: add Sierra Wireless MC74xx/EM74xx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New device IDs shamelessly lifted from the vendor driver. Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 355842b85ee9..2a7c1be23c4f 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -765,6 +765,10 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x1199, 0x9056, 8)}, /* Sierra Wireless Modem */ {QMI_FIXED_INTF(0x1199, 0x9057, 8)}, {QMI_FIXED_INTF(0x1199, 0x9061, 8)}, /* Sierra Wireless Modem */ + {QMI_FIXED_INTF(0x1199, 0x9070, 8)}, /* Sierra Wireless MC74xx/EM74xx */ + {QMI_FIXED_INTF(0x1199, 0x9070, 10)}, /* Sierra Wireless MC74xx/EM74xx */ + {QMI_FIXED_INTF(0x1199, 0x9071, 8)}, /* Sierra Wireless MC74xx/EM74xx */ + {QMI_FIXED_INTF(0x1199, 0x9071, 10)}, /* Sierra Wireless MC74xx/EM74xx */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */ {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ -- cgit v1.2.3 From 74a6c66565f5f4eda4aaae53e2e325deeedeaca2 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 2 Oct 2015 19:09:34 -0700 Subject: i40e: fix stats offsets The code was setting up stats that were not being initialized. This caused several counters to be displayed incorrectly, due to indexing beyond the array of strings when printing stats. Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index e972b5ecbf0b..13a5d4cf494b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1344,6 +1344,12 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, data[i++] = (i40e_gstrings_veb_stats[j].sizeof_stat == sizeof(u64)) ? *(u64 *)p : *(u32 *)p; } + for (j = 0; j < I40E_MAX_TRAFFIC_CLASS; j++) { + data[i++] = veb->tc_stats.tc_tx_packets[j]; + data[i++] = veb->tc_stats.tc_tx_bytes[j]; + data[i++] = veb->tc_stats.tc_rx_packets[j]; + data[i++] = veb->tc_stats.tc_rx_bytes[j]; + } } for (j = 0; j < I40E_GLOBAL_STATS_LEN; j++) { p = (char *)pf + i40e_gstrings_stats[j].stat_offset; -- cgit v1.2.3 From e9e53662d8130dd950885e37dc1d97008e1283f9 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 2 Oct 2015 17:57:21 -0700 Subject: i40e: fix annoying message The driver was printing a message about not being able to assign VMDq because of a lack of MSI-X vectors. This was because a line was missing that initialized a variable, simply a merge error. Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index dd44fafd8798..3dd26cdd0bf2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7911,6 +7911,7 @@ static int i40e_sw_init(struct i40e_pf *pf) if (pf->hw.func_caps.vmdq) { pf->num_vmdq_vsis = I40E_DEFAULT_NUM_VMDQ_VSI; pf->flags |= I40E_FLAG_VMDQ_ENABLED; + pf->num_vmdq_qps = i40e_default_queues_per_vmdq(pf); } #ifdef I40E_FCOE -- cgit v1.2.3 From 0a31adae0b2ab70127b2d5faa6a685e2ea70cc1b Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Thu, 22 Oct 2015 16:54:31 -0400 Subject: net: dsa: mv88e6xxx: remove debugfs interface It is preferable to have a common debugfs interface for DSA or switchdev instead of a driver specific one. Thus remove the mv88e6xxx debug code. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 291 -------------------------------------------- drivers/net/dsa/mv88e6xxx.h | 2 - 2 files changed, 293 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 39664d8667af..7af96309bc07 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -11,7 +11,6 @@ * (at your option) any later version. */ -#include #include #include #include @@ -21,7 +20,6 @@ #include #include #include -#include #include #include #include "mv88e6xxx.h" @@ -876,13 +874,6 @@ static int _mv88e6xxx_atu_wait(struct dsa_switch *ds) GLOBAL_ATU_OP_BUSY); } -/* Must be called with SMI lock held */ -static int _mv88e6xxx_scratch_wait(struct dsa_switch *ds) -{ - return _mv88e6xxx_wait(ds, REG_GLOBAL2, GLOBAL2_SCRATCH_MISC, - GLOBAL2_SCRATCH_BUSY); -} - /* Must be called with SMI mutex held */ static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum) @@ -2107,273 +2098,9 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds) return 0; } -static int mv88e6xxx_regs_show(struct seq_file *s, void *p) -{ - struct dsa_switch *ds = s->private; - - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int reg, port; - - seq_puts(s, " GLOBAL GLOBAL2 "); - for (port = 0 ; port < ps->num_ports; port++) - seq_printf(s, " %2d ", port); - seq_puts(s, "\n"); - - for (reg = 0; reg < 32; reg++) { - seq_printf(s, "%2x: ", reg); - seq_printf(s, " %4x %4x ", - mv88e6xxx_reg_read(ds, REG_GLOBAL, reg), - mv88e6xxx_reg_read(ds, REG_GLOBAL2, reg)); - - for (port = 0 ; port < ps->num_ports; port++) - seq_printf(s, "%4x ", - mv88e6xxx_reg_read(ds, REG_PORT(port), reg)); - seq_puts(s, "\n"); - } - - return 0; -} - -static int mv88e6xxx_regs_open(struct inode *inode, struct file *file) -{ - return single_open(file, mv88e6xxx_regs_show, inode->i_private); -} - -static const struct file_operations mv88e6xxx_regs_fops = { - .open = mv88e6xxx_regs_open, - .read = seq_read, - .llseek = no_llseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static void mv88e6xxx_atu_show_header(struct seq_file *s) -{ - seq_puts(s, "DB T/P Vec State Addr\n"); -} - -static void mv88e6xxx_atu_show_entry(struct seq_file *s, int dbnum, - unsigned char *addr, int data) -{ - bool trunk = !!(data & GLOBAL_ATU_DATA_TRUNK); - int portvec = ((data & GLOBAL_ATU_DATA_PORT_VECTOR_MASK) >> - GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT); - int state = data & GLOBAL_ATU_DATA_STATE_MASK; - - seq_printf(s, "%03x %5s %10pb %x %pM\n", - dbnum, (trunk ? "Trunk" : "Port"), &portvec, state, addr); -} - -static int mv88e6xxx_atu_show_db(struct seq_file *s, struct dsa_switch *ds, - int dbnum) -{ - unsigned char bcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - unsigned char addr[6]; - int ret, data, state; - - ret = _mv88e6xxx_atu_mac_write(ds, bcast); - if (ret < 0) - return ret; - - do { - ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, GLOBAL_ATU_FID, - dbnum); - if (ret < 0) - return ret; - - ret = _mv88e6xxx_atu_cmd(ds, GLOBAL_ATU_OP_GET_NEXT_DB); - if (ret < 0) - return ret; - - data = _mv88e6xxx_reg_read(ds, REG_GLOBAL, GLOBAL_ATU_DATA); - if (data < 0) - return data; - - state = data & GLOBAL_ATU_DATA_STATE_MASK; - if (state == GLOBAL_ATU_DATA_STATE_UNUSED) - break; - ret = _mv88e6xxx_atu_mac_read(ds, addr); - if (ret < 0) - return ret; - mv88e6xxx_atu_show_entry(s, dbnum, addr, data); - } while (state != GLOBAL_ATU_DATA_STATE_UNUSED); - - return 0; -} - -static int mv88e6xxx_atu_show(struct seq_file *s, void *p) -{ - struct dsa_switch *ds = s->private; - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int dbnum; - - mv88e6xxx_atu_show_header(s); - - for (dbnum = 0; dbnum < 255; dbnum++) { - mutex_lock(&ps->smi_mutex); - mv88e6xxx_atu_show_db(s, ds, dbnum); - mutex_unlock(&ps->smi_mutex); - } - - return 0; -} - -static int mv88e6xxx_atu_open(struct inode *inode, struct file *file) -{ - return single_open(file, mv88e6xxx_atu_show, inode->i_private); -} - -static const struct file_operations mv88e6xxx_atu_fops = { - .open = mv88e6xxx_atu_open, - .read = seq_read, - .llseek = no_llseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static void mv88e6xxx_stats_show_header(struct seq_file *s, - struct mv88e6xxx_priv_state *ps) -{ - int port; - - seq_puts(s, " Statistic "); - for (port = 0 ; port < ps->num_ports; port++) - seq_printf(s, "Port %2d ", port); - seq_puts(s, "\n"); -} - -static int mv88e6xxx_stats_show(struct seq_file *s, void *p) -{ - struct dsa_switch *ds = s->private; - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - struct mv88e6xxx_hw_stat *stats = mv88e6xxx_hw_stats; - int port, stat, max_stats; - uint64_t value; - - if (have_sw_in_discards(ds)) - max_stats = ARRAY_SIZE(mv88e6xxx_hw_stats); - else - max_stats = ARRAY_SIZE(mv88e6xxx_hw_stats) - 3; - - mv88e6xxx_stats_show_header(s, ps); - - mutex_lock(&ps->smi_mutex); - - for (stat = 0; stat < max_stats; stat++) { - seq_printf(s, "%19s: ", stats[stat].string); - for (port = 0 ; port < ps->num_ports; port++) { - _mv88e6xxx_stats_snapshot(ds, port); - value = _mv88e6xxx_get_ethtool_stat(ds, stat, stats, - port); - seq_printf(s, "%8llu ", value); - } - seq_puts(s, "\n"); - } - mutex_unlock(&ps->smi_mutex); - - return 0; -} - -static int mv88e6xxx_stats_open(struct inode *inode, struct file *file) -{ - return single_open(file, mv88e6xxx_stats_show, inode->i_private); -} - -static const struct file_operations mv88e6xxx_stats_fops = { - .open = mv88e6xxx_stats_open, - .read = seq_read, - .llseek = no_llseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int mv88e6xxx_device_map_show(struct seq_file *s, void *p) -{ - struct dsa_switch *ds = s->private; - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int target, ret; - - seq_puts(s, "Target Port\n"); - - mutex_lock(&ps->smi_mutex); - for (target = 0; target < 32; target++) { - ret = _mv88e6xxx_reg_write( - ds, REG_GLOBAL2, GLOBAL2_DEVICE_MAPPING, - target << GLOBAL2_DEVICE_MAPPING_TARGET_SHIFT); - if (ret < 0) - goto out; - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL2, - GLOBAL2_DEVICE_MAPPING); - seq_printf(s, " %2d %2d\n", target, - ret & GLOBAL2_DEVICE_MAPPING_PORT_MASK); - } -out: - mutex_unlock(&ps->smi_mutex); - - return 0; -} - -static int mv88e6xxx_device_map_open(struct inode *inode, struct file *file) -{ - return single_open(file, mv88e6xxx_device_map_show, inode->i_private); -} - -static const struct file_operations mv88e6xxx_device_map_fops = { - .open = mv88e6xxx_device_map_open, - .read = seq_read, - .llseek = no_llseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int mv88e6xxx_scratch_show(struct seq_file *s, void *p) -{ - struct dsa_switch *ds = s->private; - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - int reg, ret; - - seq_puts(s, "Register Value\n"); - - mutex_lock(&ps->smi_mutex); - for (reg = 0; reg < 0x80; reg++) { - ret = _mv88e6xxx_reg_write( - ds, REG_GLOBAL2, GLOBAL2_SCRATCH_MISC, - reg << GLOBAL2_SCRATCH_REGISTER_SHIFT); - if (ret < 0) - goto out; - - ret = _mv88e6xxx_scratch_wait(ds); - if (ret < 0) - goto out; - - ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL2, - GLOBAL2_SCRATCH_MISC); - seq_printf(s, " %2x %2x\n", reg, - ret & GLOBAL2_SCRATCH_VALUE_MASK); - } -out: - mutex_unlock(&ps->smi_mutex); - - return 0; -} - -static int mv88e6xxx_scratch_open(struct inode *inode, struct file *file) -{ - return single_open(file, mv88e6xxx_scratch_show, inode->i_private); -} - -static const struct file_operations mv88e6xxx_scratch_fops = { - .open = mv88e6xxx_scratch_open, - .read = seq_read, - .llseek = no_llseek, - .release = single_release, - .owner = THIS_MODULE, -}; - int mv88e6xxx_setup_common(struct dsa_switch *ds) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); - char *name; mutex_init(&ps->smi_mutex); @@ -2381,24 +2108,6 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds) INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work); - name = kasprintf(GFP_KERNEL, "dsa%d", ds->index); - ps->dbgfs = debugfs_create_dir(name, NULL); - kfree(name); - - debugfs_create_file("regs", S_IRUGO, ps->dbgfs, ds, - &mv88e6xxx_regs_fops); - - debugfs_create_file("atu", S_IRUGO, ps->dbgfs, ds, - &mv88e6xxx_atu_fops); - - debugfs_create_file("stats", S_IRUGO, ps->dbgfs, ds, - &mv88e6xxx_stats_fops); - - debugfs_create_file("device_map", S_IRUGO, ps->dbgfs, ds, - &mv88e6xxx_device_map_fops); - - debugfs_create_file("scratch", S_IRUGO, ps->dbgfs, ds, - &mv88e6xxx_scratch_fops); return 0; } diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 430de4fa1fec..6f9ed5d45012 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -406,8 +406,6 @@ struct mv88e6xxx_priv_state { u8 port_state[DSA_MAX_PORTS]; struct work_struct bridge_work; - - struct dentry *dbgfs; }; struct mv88e6xxx_hw_stat { -- cgit v1.2.3 From c0c050c58d840994ba842ad1c338a98e7c12b764 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 22 Oct 2015 16:01:17 -0400 Subject: bnxt_en: New Broadcom ethernet driver. Broadcom ethernet driver for the new family of NetXtreme-C/E ethernet devices. v5: - Removed empty blank lines at end of files (noted by David Miller). - Moved busy poll helper functions to bnxt.h to at least make the .c file look less cluttered with #ifdef (noted by Stephen Hemminger). v4: - Broke up 2 long message strings with "\n" (suggested by John Linville) - Constify an array of strings (suggested by Stephen Hemminger) - Improve bnxt_vf_pciid() (suggested by Stephen Hemminger) - Use PCI_VDEVICE() to populate pci_device_id table for more compact source. v3: - Fixed 2 more sparse warnings. - Removed some unused structures in .h files. v2: - Fixed all kbuild test robot reported warnings. - Fixed many of the checkpatch.pl errors and warnings. - Fixed the Kconfig description (noted by Dmitry Kravkov). Acked-by: Eddie Wai Acked-by: Jeffrey Huang Signed-off-by: Prashant Sreedharan Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/Kconfig | 19 + drivers/net/ethernet/broadcom/Makefile | 1 + drivers/net/ethernet/broadcom/bnxt/Makefile | 3 + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 5746 ++++++++++++++++++++ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 1081 ++++ drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 1149 ++++ drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h | 17 + drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h | 104 + drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h | 4046 ++++++++++++++ drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h | 59 + drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c | 787 +++ drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h | 22 + 12 files changed, 13034 insertions(+) create mode 100644 drivers/net/ethernet/broadcom/bnxt/Makefile create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt.c create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt.h create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c create mode 100644 drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index e930aa9a3cfb..67a7d520d9f5 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -170,4 +170,23 @@ config SYSTEMPORT Broadcom BCM7xxx Set Top Box family chipset using an internal Ethernet switch. +config BNXT + tristate "Broadcom NetXtreme-C/E support" + depends on PCI + select FW_LOADER + select LIBCRC32C + ---help--- + This driver supports Broadcom NetXtreme-C/E 10/25/40/50 gigabit + Ethernet cards. To compile this driver as a module, choose M here: + the module will be called bnxt_en. This is recommended. + +config BNXT_SRIOV + bool "Broadcom NetXtreme-C/E SR-IOV support" + depends on BNXT && PCI_IOV + default y + ---help--- + This configuration parameter enables Single Root Input Output + Virtualization support in the NetXtreme-C/E products. This + allows for virtual function acceleration in virtual environments. + endif # NET_VENDOR_BROADCOM diff --git a/drivers/net/ethernet/broadcom/Makefile b/drivers/net/ethernet/broadcom/Makefile index e2a958a657e0..00584d78b3e0 100644 --- a/drivers/net/ethernet/broadcom/Makefile +++ b/drivers/net/ethernet/broadcom/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o obj-$(CONFIG_TIGON3) += tg3.o obj-$(CONFIG_BGMAC) += bgmac.o obj-$(CONFIG_SYSTEMPORT) += bcmsysport.o +obj-$(CONFIG_BNXT) += bnxt/ diff --git a/drivers/net/ethernet/broadcom/bnxt/Makefile b/drivers/net/ethernet/broadcom/bnxt/Makefile new file mode 100644 index 000000000000..97e78e217928 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnxt/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_BNXT) += bnxt_en.o + +bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c new file mode 100644 index 000000000000..94b11a59e703 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -0,0 +1,5746 @@ +/* Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2014-2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_VXLAN) || defined(CONFIG_VXLAN_MODULE) +#include +#endif +#ifdef CONFIG_NET_RX_BUSY_POLL +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "bnxt_hsi.h" +#include "bnxt.h" +#include "bnxt_sriov.h" +#include "bnxt_ethtool.h" + +#define BNXT_TX_TIMEOUT (5 * HZ) + +static const char version[] = + "Broadcom NetXtreme-C/E driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION "\n"; + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Broadcom BCM573xx network driver"); +MODULE_VERSION(DRV_MODULE_VERSION); + +#define BNXT_RX_OFFSET (NET_SKB_PAD + NET_IP_ALIGN) +#define BNXT_RX_DMA_OFFSET NET_SKB_PAD +#define BNXT_RX_COPY_THRESH 256 + +#define BNXT_TX_PUSH_THRESH 92 + +enum board_idx { + BCM57302, + BCM57304, + BCM57404, + BCM57406, + BCM57304_VF, + BCM57404_VF, +}; + +/* indexed by enum above */ +static const struct { + char *name; +} board_info[] = { + { "Broadcom BCM57302 NetXtreme-C Single-port 10Gb/25Gb/40Gb/50Gb Ethernet" }, + { "Broadcom BCM57304 NetXtreme-C Dual-port 10Gb/25Gb/40Gb/50Gb Ethernet" }, + { "Broadcom BCM57404 NetXtreme-E Dual-port 10Gb/25Gb Ethernet" }, + { "Broadcom BCM57406 NetXtreme-E Dual-port 10Gb Ethernet" }, + { "Broadcom BCM57304 NetXtreme-C Ethernet Virtual Function" }, + { "Broadcom BCM57404 NetXtreme-E Ethernet Virtual Function" }, +}; + +static const struct pci_device_id bnxt_pci_tbl[] = { + { PCI_VDEVICE(BROADCOM, 0x16c9), .driver_data = BCM57302 }, + { PCI_VDEVICE(BROADCOM, 0x16ca), .driver_data = BCM57304 }, + { PCI_VDEVICE(BROADCOM, 0x16d1), .driver_data = BCM57404 }, + { PCI_VDEVICE(BROADCOM, 0x16d2), .driver_data = BCM57406 }, +#ifdef CONFIG_BNXT_SRIOV + { PCI_VDEVICE(BROADCOM, 0x16cb), .driver_data = BCM57304_VF }, + { PCI_VDEVICE(BROADCOM, 0x16d3), .driver_data = BCM57404_VF }, +#endif + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, bnxt_pci_tbl); + +static const u16 bnxt_vf_req_snif[] = { + HWRM_FUNC_CFG, + HWRM_PORT_PHY_QCFG, + HWRM_CFA_L2_FILTER_ALLOC, +}; + +static bool bnxt_vf_pciid(enum board_idx idx) +{ + return (idx == BCM57304_VF || idx == BCM57404_VF); +} + +#define DB_CP_REARM_FLAGS (DB_KEY_CP | DB_IDX_VALID) +#define DB_CP_FLAGS (DB_KEY_CP | DB_IDX_VALID | DB_IRQ_DIS) +#define DB_CP_IRQ_DIS_FLAGS (DB_KEY_CP | DB_IRQ_DIS) + +#define BNXT_CP_DB_REARM(db, raw_cons) \ + writel(DB_CP_REARM_FLAGS | RING_CMP(raw_cons), db) + +#define BNXT_CP_DB(db, raw_cons) \ + writel(DB_CP_FLAGS | RING_CMP(raw_cons), db) + +#define BNXT_CP_DB_IRQ_DIS(db) \ + writel(DB_CP_IRQ_DIS_FLAGS, db) + +static inline u32 bnxt_tx_avail(struct bnxt *bp, struct bnxt_tx_ring_info *txr) +{ + /* Tell compiler to fetch tx indices from memory. */ + barrier(); + + return bp->tx_ring_size - + ((txr->tx_prod - txr->tx_cons) & bp->tx_ring_mask); +} + +static const u16 bnxt_lhint_arr[] = { + TX_BD_FLAGS_LHINT_512_AND_SMALLER, + TX_BD_FLAGS_LHINT_512_TO_1023, + TX_BD_FLAGS_LHINT_1024_TO_2047, + TX_BD_FLAGS_LHINT_1024_TO_2047, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, + TX_BD_FLAGS_LHINT_2048_AND_LARGER, +}; + +static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct bnxt *bp = netdev_priv(dev); + struct tx_bd *txbd; + struct tx_bd_ext *txbd1; + struct netdev_queue *txq; + int i; + dma_addr_t mapping; + unsigned int length, pad = 0; + u32 len, free_size, vlan_tag_flags, cfa_action, flags; + u16 prod, last_frag; + struct pci_dev *pdev = bp->pdev; + struct bnxt_napi *bnapi; + struct bnxt_tx_ring_info *txr; + struct bnxt_sw_tx_bd *tx_buf; + + i = skb_get_queue_mapping(skb); + if (unlikely(i >= bp->tx_nr_rings)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + bnapi = bp->bnapi[i]; + txr = &bnapi->tx_ring; + txq = netdev_get_tx_queue(dev, i); + prod = txr->tx_prod; + + free_size = bnxt_tx_avail(bp, txr); + if (unlikely(free_size < skb_shinfo(skb)->nr_frags + 2)) { + netif_tx_stop_queue(txq); + return NETDEV_TX_BUSY; + } + + length = skb->len; + len = skb_headlen(skb); + last_frag = skb_shinfo(skb)->nr_frags; + + txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)]; + + txbd->tx_bd_opaque = prod; + + tx_buf = &txr->tx_buf_ring[prod]; + tx_buf->skb = skb; + tx_buf->nr_frags = last_frag; + + vlan_tag_flags = 0; + cfa_action = 0; + if (skb_vlan_tag_present(skb)) { + vlan_tag_flags = TX_BD_CFA_META_KEY_VLAN | + skb_vlan_tag_get(skb); + /* Currently supports 8021Q, 8021AD vlan offloads + * QINQ1, QINQ2, QINQ3 vlan headers are deprecated + */ + if (skb->vlan_proto == htons(ETH_P_8021Q)) + vlan_tag_flags |= 1 << TX_BD_CFA_META_TPID_SHIFT; + } + + if (free_size == bp->tx_ring_size && length <= bp->tx_push_thresh) { + struct tx_push_bd *push = txr->tx_push; + struct tx_bd *tx_push = &push->txbd1; + struct tx_bd_ext *tx_push1 = &push->txbd2; + void *pdata = tx_push1 + 1; + int j; + + /* Set COAL_NOW to be ready quickly for the next push */ + tx_push->tx_bd_len_flags_type = + cpu_to_le32((length << TX_BD_LEN_SHIFT) | + TX_BD_TYPE_LONG_TX_BD | + TX_BD_FLAGS_LHINT_512_AND_SMALLER | + TX_BD_FLAGS_COAL_NOW | + TX_BD_FLAGS_PACKET_END | + (2 << TX_BD_FLAGS_BD_CNT_SHIFT)); + + if (skb->ip_summed == CHECKSUM_PARTIAL) + tx_push1->tx_bd_hsize_lflags = + cpu_to_le32(TX_BD_FLAGS_TCP_UDP_CHKSUM); + else + tx_push1->tx_bd_hsize_lflags = 0; + + tx_push1->tx_bd_cfa_meta = cpu_to_le32(vlan_tag_flags); + tx_push1->tx_bd_cfa_action = cpu_to_le32(cfa_action); + + skb_copy_from_linear_data(skb, pdata, len); + pdata += len; + for (j = 0; j < last_frag; j++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[j]; + void *fptr; + + fptr = skb_frag_address_safe(frag); + if (!fptr) + goto normal_tx; + + memcpy(pdata, fptr, skb_frag_size(frag)); + pdata += skb_frag_size(frag); + } + + memcpy(txbd, tx_push, sizeof(*txbd)); + prod = NEXT_TX(prod); + txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)]; + memcpy(txbd, tx_push1, sizeof(*txbd)); + prod = NEXT_TX(prod); + push->doorbell = + cpu_to_le32(DB_KEY_TX_PUSH | DB_LONG_TX_PUSH | prod); + txr->tx_prod = prod; + + netdev_tx_sent_queue(txq, skb->len); + + __iowrite64_copy(txr->tx_doorbell, push, + (length + sizeof(*push) + 8) / 8); + + tx_buf->is_push = 1; + + goto tx_done; + } + +normal_tx: + if (length < BNXT_MIN_PKT_SIZE) { + pad = BNXT_MIN_PKT_SIZE - length; + if (skb_pad(skb, pad)) { + /* SKB already freed. */ + tx_buf->skb = NULL; + return NETDEV_TX_OK; + } + length = BNXT_MIN_PKT_SIZE; + } + + mapping = dma_map_single(&pdev->dev, skb->data, len, DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(&pdev->dev, mapping))) { + dev_kfree_skb_any(skb); + tx_buf->skb = NULL; + return NETDEV_TX_OK; + } + + dma_unmap_addr_set(tx_buf, mapping, mapping); + flags = (len << TX_BD_LEN_SHIFT) | TX_BD_TYPE_LONG_TX_BD | + ((last_frag + 2) << TX_BD_FLAGS_BD_CNT_SHIFT); + + txbd->tx_bd_haddr = cpu_to_le64(mapping); + + prod = NEXT_TX(prod); + txbd1 = (struct tx_bd_ext *) + &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)]; + + txbd1->tx_bd_hsize_lflags = 0; + if (skb_is_gso(skb)) { + u32 hdr_len; + + if (skb->encapsulation) + hdr_len = skb_inner_network_offset(skb) + + skb_inner_network_header_len(skb) + + inner_tcp_hdrlen(skb); + else + hdr_len = skb_transport_offset(skb) + + tcp_hdrlen(skb); + + txbd1->tx_bd_hsize_lflags = cpu_to_le32(TX_BD_FLAGS_LSO | + TX_BD_FLAGS_T_IPID | + (hdr_len << (TX_BD_HSIZE_SHIFT - 1))); + length = skb_shinfo(skb)->gso_size; + txbd1->tx_bd_mss = cpu_to_le32(length); + length += hdr_len; + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + txbd1->tx_bd_hsize_lflags = + cpu_to_le32(TX_BD_FLAGS_TCP_UDP_CHKSUM); + txbd1->tx_bd_mss = 0; + } + + length >>= 9; + flags |= bnxt_lhint_arr[length]; + txbd->tx_bd_len_flags_type = cpu_to_le32(flags); + + txbd1->tx_bd_cfa_meta = cpu_to_le32(vlan_tag_flags); + txbd1->tx_bd_cfa_action = cpu_to_le32(cfa_action); + for (i = 0; i < last_frag; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + prod = NEXT_TX(prod); + txbd = &txr->tx_desc_ring[TX_RING(prod)][TX_IDX(prod)]; + + len = skb_frag_size(frag); + mapping = skb_frag_dma_map(&pdev->dev, frag, 0, len, + DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(&pdev->dev, mapping))) + goto tx_dma_error; + + tx_buf = &txr->tx_buf_ring[prod]; + dma_unmap_addr_set(tx_buf, mapping, mapping); + + txbd->tx_bd_haddr = cpu_to_le64(mapping); + + flags = len << TX_BD_LEN_SHIFT; + txbd->tx_bd_len_flags_type = cpu_to_le32(flags); + } + + flags &= ~TX_BD_LEN; + txbd->tx_bd_len_flags_type = + cpu_to_le32(((len + pad) << TX_BD_LEN_SHIFT) | flags | + TX_BD_FLAGS_PACKET_END); + + netdev_tx_sent_queue(txq, skb->len); + + /* Sync BD data before updating doorbell */ + wmb(); + + prod = NEXT_TX(prod); + txr->tx_prod = prod; + + writel(DB_KEY_TX | prod, txr->tx_doorbell); + writel(DB_KEY_TX | prod, txr->tx_doorbell); + +tx_done: + + mmiowb(); + + if (unlikely(bnxt_tx_avail(bp, txr) <= MAX_SKB_FRAGS + 1)) { + netif_tx_stop_queue(txq); + + /* netif_tx_stop_queue() must be done before checking + * tx index in bnxt_tx_avail() below, because in + * bnxt_tx_int(), we update tx index before checking for + * netif_tx_queue_stopped(). + */ + smp_mb(); + if (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh) + netif_tx_wake_queue(txq); + } + return NETDEV_TX_OK; + +tx_dma_error: + last_frag = i; + + /* start back at beginning and unmap skb */ + prod = txr->tx_prod; + tx_buf = &txr->tx_buf_ring[prod]; + tx_buf->skb = NULL; + dma_unmap_single(&pdev->dev, dma_unmap_addr(tx_buf, mapping), + skb_headlen(skb), PCI_DMA_TODEVICE); + prod = NEXT_TX(prod); + + /* unmap remaining mapped pages */ + for (i = 0; i < last_frag; i++) { + prod = NEXT_TX(prod); + tx_buf = &txr->tx_buf_ring[prod]; + dma_unmap_page(&pdev->dev, dma_unmap_addr(tx_buf, mapping), + skb_frag_size(&skb_shinfo(skb)->frags[i]), + PCI_DMA_TODEVICE); + } + + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} + +static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts) +{ + struct bnxt_tx_ring_info *txr = &bnapi->tx_ring; + int index = bnapi->index; + struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, index); + u16 cons = txr->tx_cons; + struct pci_dev *pdev = bp->pdev; + int i; + unsigned int tx_bytes = 0; + + for (i = 0; i < nr_pkts; i++) { + struct bnxt_sw_tx_bd *tx_buf; + struct sk_buff *skb; + int j, last; + + tx_buf = &txr->tx_buf_ring[cons]; + cons = NEXT_TX(cons); + skb = tx_buf->skb; + tx_buf->skb = NULL; + + if (tx_buf->is_push) { + tx_buf->is_push = 0; + goto next_tx_int; + } + + dma_unmap_single(&pdev->dev, dma_unmap_addr(tx_buf, mapping), + skb_headlen(skb), PCI_DMA_TODEVICE); + last = tx_buf->nr_frags; + + for (j = 0; j < last; j++) { + cons = NEXT_TX(cons); + tx_buf = &txr->tx_buf_ring[cons]; + dma_unmap_page( + &pdev->dev, + dma_unmap_addr(tx_buf, mapping), + skb_frag_size(&skb_shinfo(skb)->frags[j]), + PCI_DMA_TODEVICE); + } + +next_tx_int: + cons = NEXT_TX(cons); + + tx_bytes += skb->len; + dev_kfree_skb_any(skb); + } + + netdev_tx_completed_queue(txq, nr_pkts, tx_bytes); + txr->tx_cons = cons; + + /* Need to make the tx_cons update visible to bnxt_start_xmit() + * before checking for netif_tx_queue_stopped(). Without the + * memory barrier, there is a small possibility that bnxt_start_xmit() + * will miss it and cause the queue to be stopped forever. + */ + smp_mb(); + + if (unlikely(netif_tx_queue_stopped(txq)) && + (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh)) { + __netif_tx_lock(txq, smp_processor_id()); + if (netif_tx_queue_stopped(txq) && + bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh && + txr->dev_state != BNXT_DEV_STATE_CLOSING) + netif_tx_wake_queue(txq); + __netif_tx_unlock(txq); + } +} + +static inline u8 *__bnxt_alloc_rx_data(struct bnxt *bp, dma_addr_t *mapping, + gfp_t gfp) +{ + u8 *data; + struct pci_dev *pdev = bp->pdev; + + data = kmalloc(bp->rx_buf_size, gfp); + if (!data) + return NULL; + + *mapping = dma_map_single(&pdev->dev, data + BNXT_RX_DMA_OFFSET, + bp->rx_buf_use_size, PCI_DMA_FROMDEVICE); + + if (dma_mapping_error(&pdev->dev, *mapping)) { + kfree(data); + data = NULL; + } + return data; +} + +static inline int bnxt_alloc_rx_data(struct bnxt *bp, + struct bnxt_rx_ring_info *rxr, + u16 prod, gfp_t gfp) +{ + struct rx_bd *rxbd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)]; + struct bnxt_sw_rx_bd *rx_buf = &rxr->rx_buf_ring[prod]; + u8 *data; + dma_addr_t mapping; + + data = __bnxt_alloc_rx_data(bp, &mapping, gfp); + if (!data) + return -ENOMEM; + + rx_buf->data = data; + dma_unmap_addr_set(rx_buf, mapping, mapping); + + rxbd->rx_bd_haddr = cpu_to_le64(mapping); + + return 0; +} + +static void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons, + u8 *data) +{ + u16 prod = rxr->rx_prod; + struct bnxt_sw_rx_bd *cons_rx_buf, *prod_rx_buf; + struct rx_bd *cons_bd, *prod_bd; + + prod_rx_buf = &rxr->rx_buf_ring[prod]; + cons_rx_buf = &rxr->rx_buf_ring[cons]; + + prod_rx_buf->data = data; + + dma_unmap_addr_set(prod_rx_buf, mapping, + dma_unmap_addr(cons_rx_buf, mapping)); + + prod_bd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)]; + cons_bd = &rxr->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)]; + + prod_bd->rx_bd_haddr = cons_bd->rx_bd_haddr; +} + +static inline u16 bnxt_find_next_agg_idx(struct bnxt_rx_ring_info *rxr, u16 idx) +{ + u16 next, max = rxr->rx_agg_bmap_size; + + next = find_next_zero_bit(rxr->rx_agg_bmap, max, idx); + if (next >= max) + next = find_first_zero_bit(rxr->rx_agg_bmap, max); + return next; +} + +static inline int bnxt_alloc_rx_page(struct bnxt *bp, + struct bnxt_rx_ring_info *rxr, + u16 prod, gfp_t gfp) +{ + struct rx_bd *rxbd = + &rxr->rx_agg_desc_ring[RX_RING(prod)][RX_IDX(prod)]; + struct bnxt_sw_rx_agg_bd *rx_agg_buf; + struct pci_dev *pdev = bp->pdev; + struct page *page; + dma_addr_t mapping; + u16 sw_prod = rxr->rx_sw_agg_prod; + + page = alloc_page(gfp); + if (!page) + return -ENOMEM; + + mapping = dma_map_page(&pdev->dev, page, 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + if (dma_mapping_error(&pdev->dev, mapping)) { + __free_page(page); + return -EIO; + } + + if (unlikely(test_bit(sw_prod, rxr->rx_agg_bmap))) + sw_prod = bnxt_find_next_agg_idx(rxr, sw_prod); + + __set_bit(sw_prod, rxr->rx_agg_bmap); + rx_agg_buf = &rxr->rx_agg_ring[sw_prod]; + rxr->rx_sw_agg_prod = NEXT_RX_AGG(sw_prod); + + rx_agg_buf->page = page; + rx_agg_buf->mapping = mapping; + rxbd->rx_bd_haddr = cpu_to_le64(mapping); + rxbd->rx_bd_opaque = sw_prod; + return 0; +} + +static void bnxt_reuse_rx_agg_bufs(struct bnxt_napi *bnapi, u16 cp_cons, + u32 agg_bufs) +{ + struct bnxt *bp = bnapi->bp; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring; + u16 prod = rxr->rx_agg_prod; + u16 sw_prod = rxr->rx_sw_agg_prod; + u32 i; + + for (i = 0; i < agg_bufs; i++) { + u16 cons; + struct rx_agg_cmp *agg; + struct bnxt_sw_rx_agg_bd *cons_rx_buf, *prod_rx_buf; + struct rx_bd *prod_bd; + struct page *page; + + agg = (struct rx_agg_cmp *) + &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + cons = agg->rx_agg_cmp_opaque; + __clear_bit(cons, rxr->rx_agg_bmap); + + if (unlikely(test_bit(sw_prod, rxr->rx_agg_bmap))) + sw_prod = bnxt_find_next_agg_idx(rxr, sw_prod); + + __set_bit(sw_prod, rxr->rx_agg_bmap); + prod_rx_buf = &rxr->rx_agg_ring[sw_prod]; + cons_rx_buf = &rxr->rx_agg_ring[cons]; + + /* It is possible for sw_prod to be equal to cons, so + * set cons_rx_buf->page to NULL first. + */ + page = cons_rx_buf->page; + cons_rx_buf->page = NULL; + prod_rx_buf->page = page; + + prod_rx_buf->mapping = cons_rx_buf->mapping; + + prod_bd = &rxr->rx_agg_desc_ring[RX_RING(prod)][RX_IDX(prod)]; + + prod_bd->rx_bd_haddr = cpu_to_le64(cons_rx_buf->mapping); + prod_bd->rx_bd_opaque = sw_prod; + + prod = NEXT_RX_AGG(prod); + sw_prod = NEXT_RX_AGG(sw_prod); + cp_cons = NEXT_CMP(cp_cons); + } + rxr->rx_agg_prod = prod; + rxr->rx_sw_agg_prod = sw_prod; +} + +static struct sk_buff *bnxt_rx_skb(struct bnxt *bp, + struct bnxt_rx_ring_info *rxr, u16 cons, + u16 prod, u8 *data, dma_addr_t dma_addr, + unsigned int len) +{ + int err; + struct sk_buff *skb; + + err = bnxt_alloc_rx_data(bp, rxr, prod, GFP_ATOMIC); + if (unlikely(err)) { + bnxt_reuse_rx_data(rxr, cons, data); + return NULL; + } + + skb = build_skb(data, 0); + dma_unmap_single(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size, + PCI_DMA_FROMDEVICE); + if (!skb) { + kfree(data); + return NULL; + } + + skb_reserve(skb, BNXT_RX_OFFSET); + skb_put(skb, len); + return skb; +} + +static struct sk_buff *bnxt_rx_pages(struct bnxt *bp, struct bnxt_napi *bnapi, + struct sk_buff *skb, u16 cp_cons, + u32 agg_bufs) +{ + struct pci_dev *pdev = bp->pdev; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring; + u16 prod = rxr->rx_agg_prod; + u32 i; + + for (i = 0; i < agg_bufs; i++) { + u16 cons, frag_len; + struct rx_agg_cmp *agg; + struct bnxt_sw_rx_agg_bd *cons_rx_buf; + struct page *page; + dma_addr_t mapping; + + agg = (struct rx_agg_cmp *) + &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + cons = agg->rx_agg_cmp_opaque; + frag_len = (le32_to_cpu(agg->rx_agg_cmp_len_flags_type) & + RX_AGG_CMP_LEN) >> RX_AGG_CMP_LEN_SHIFT; + + cons_rx_buf = &rxr->rx_agg_ring[cons]; + skb_fill_page_desc(skb, i, cons_rx_buf->page, 0, frag_len); + __clear_bit(cons, rxr->rx_agg_bmap); + + /* It is possible for bnxt_alloc_rx_page() to allocate + * a sw_prod index that equals the cons index, so we + * need to clear the cons entry now. + */ + mapping = dma_unmap_addr(cons_rx_buf, mapping); + page = cons_rx_buf->page; + cons_rx_buf->page = NULL; + + if (bnxt_alloc_rx_page(bp, rxr, prod, GFP_ATOMIC) != 0) { + struct skb_shared_info *shinfo; + unsigned int nr_frags; + + shinfo = skb_shinfo(skb); + nr_frags = --shinfo->nr_frags; + __skb_frag_set_page(&shinfo->frags[nr_frags], NULL); + + dev_kfree_skb(skb); + + cons_rx_buf->page = page; + + /* Update prod since possibly some pages have been + * allocated already. + */ + rxr->rx_agg_prod = prod; + bnxt_reuse_rx_agg_bufs(bnapi, cp_cons, agg_bufs - i); + return NULL; + } + + dma_unmap_page(&pdev->dev, mapping, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + + skb->data_len += frag_len; + skb->len += frag_len; + skb->truesize += PAGE_SIZE; + + prod = NEXT_RX_AGG(prod); + cp_cons = NEXT_CMP(cp_cons); + } + rxr->rx_agg_prod = prod; + return skb; +} + +static int bnxt_agg_bufs_valid(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, + u8 agg_bufs, u32 *raw_cons) +{ + u16 last; + struct rx_agg_cmp *agg; + + *raw_cons = ADV_RAW_CMP(*raw_cons, agg_bufs); + last = RING_CMP(*raw_cons); + agg = (struct rx_agg_cmp *) + &cpr->cp_desc_ring[CP_RING(last)][CP_IDX(last)]; + return RX_AGG_CMP_VALID(agg, *raw_cons); +} + +static inline struct sk_buff *bnxt_copy_skb(struct bnxt_napi *bnapi, u8 *data, + unsigned int len, + dma_addr_t mapping) +{ + struct bnxt *bp = bnapi->bp; + struct pci_dev *pdev = bp->pdev; + struct sk_buff *skb; + + skb = napi_alloc_skb(&bnapi->napi, len); + if (!skb) + return NULL; + + dma_sync_single_for_cpu(&pdev->dev, mapping, + bp->rx_copy_thresh, PCI_DMA_FROMDEVICE); + + memcpy(skb->data - BNXT_RX_OFFSET, data, len + BNXT_RX_OFFSET); + + dma_sync_single_for_device(&pdev->dev, mapping, + bp->rx_copy_thresh, + PCI_DMA_FROMDEVICE); + + skb_put(skb, len); + return skb; +} + +static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, + struct rx_tpa_start_cmp *tpa_start, + struct rx_tpa_start_cmp_ext *tpa_start1) +{ + u8 agg_id = TPA_START_AGG_ID(tpa_start); + u16 cons, prod; + struct bnxt_tpa_info *tpa_info; + struct bnxt_sw_rx_bd *cons_rx_buf, *prod_rx_buf; + struct rx_bd *prod_bd; + dma_addr_t mapping; + + cons = tpa_start->rx_tpa_start_cmp_opaque; + prod = rxr->rx_prod; + cons_rx_buf = &rxr->rx_buf_ring[cons]; + prod_rx_buf = &rxr->rx_buf_ring[prod]; + tpa_info = &rxr->rx_tpa[agg_id]; + + prod_rx_buf->data = tpa_info->data; + + mapping = tpa_info->mapping; + dma_unmap_addr_set(prod_rx_buf, mapping, mapping); + + prod_bd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)]; + + prod_bd->rx_bd_haddr = cpu_to_le64(mapping); + + tpa_info->data = cons_rx_buf->data; + cons_rx_buf->data = NULL; + tpa_info->mapping = dma_unmap_addr(cons_rx_buf, mapping); + + tpa_info->len = + le32_to_cpu(tpa_start->rx_tpa_start_cmp_len_flags_type) >> + RX_TPA_START_CMP_LEN_SHIFT; + if (likely(TPA_START_HASH_VALID(tpa_start))) { + u32 hash_type = TPA_START_HASH_TYPE(tpa_start); + + tpa_info->hash_type = PKT_HASH_TYPE_L4; + tpa_info->gso_type = SKB_GSO_TCPV4; + /* RSS profiles 1 and 3 with extract code 0 for inner 4-tuple */ + if (hash_type == 3) + tpa_info->gso_type = SKB_GSO_TCPV6; + tpa_info->rss_hash = + le32_to_cpu(tpa_start->rx_tpa_start_cmp_rss_hash); + } else { + tpa_info->hash_type = PKT_HASH_TYPE_NONE; + tpa_info->gso_type = 0; + if (netif_msg_rx_err(bp)) + netdev_warn(bp->dev, "TPA packet without valid hash\n"); + } + tpa_info->flags2 = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_flags2); + tpa_info->metadata = le32_to_cpu(tpa_start1->rx_tpa_start_cmp_metadata); + + rxr->rx_prod = NEXT_RX(prod); + cons = NEXT_RX(cons); + cons_rx_buf = &rxr->rx_buf_ring[cons]; + + bnxt_reuse_rx_data(rxr, cons, cons_rx_buf->data); + rxr->rx_prod = NEXT_RX(rxr->rx_prod); + cons_rx_buf->data = NULL; +} + +static void bnxt_abort_tpa(struct bnxt *bp, struct bnxt_napi *bnapi, + u16 cp_cons, u32 agg_bufs) +{ + if (agg_bufs) + bnxt_reuse_rx_agg_bufs(bnapi, cp_cons, agg_bufs); +} + +#define BNXT_IPV4_HDR_SIZE (sizeof(struct iphdr) + sizeof(struct tcphdr)) +#define BNXT_IPV6_HDR_SIZE (sizeof(struct ipv6hdr) + sizeof(struct tcphdr)) + +static inline struct sk_buff *bnxt_gro_skb(struct bnxt_tpa_info *tpa_info, + struct rx_tpa_end_cmp *tpa_end, + struct rx_tpa_end_cmp_ext *tpa_end1, + struct sk_buff *skb) +{ + struct tcphdr *th; + int payload_off, tcp_opt_len = 0; + int len, nw_off; + + NAPI_GRO_CB(skb)->count = TPA_END_TPA_SEGS(tpa_end); + skb_shinfo(skb)->gso_size = + le32_to_cpu(tpa_end1->rx_tpa_end_cmp_seg_len); + skb_shinfo(skb)->gso_type = tpa_info->gso_type; + payload_off = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) & + RX_TPA_END_CMP_PAYLOAD_OFFSET) >> + RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT; + if (TPA_END_GRO_TS(tpa_end)) + tcp_opt_len = 12; + +#ifdef CONFIG_INET + if (tpa_info->gso_type == SKB_GSO_TCPV4) { + struct iphdr *iph; + + nw_off = payload_off - BNXT_IPV4_HDR_SIZE - tcp_opt_len - + ETH_HLEN; + skb_set_network_header(skb, nw_off); + iph = ip_hdr(skb); + skb_set_transport_header(skb, nw_off + sizeof(struct iphdr)); + len = skb->len - skb_transport_offset(skb); + th = tcp_hdr(skb); + th->check = ~tcp_v4_check(len, iph->saddr, iph->daddr, 0); + } else if (tpa_info->gso_type == SKB_GSO_TCPV6) { + struct ipv6hdr *iph; + + nw_off = payload_off - BNXT_IPV6_HDR_SIZE - tcp_opt_len - + ETH_HLEN; + skb_set_network_header(skb, nw_off); + iph = ipv6_hdr(skb); + skb_set_transport_header(skb, nw_off + sizeof(struct ipv6hdr)); + len = skb->len - skb_transport_offset(skb); + th = tcp_hdr(skb); + th->check = ~tcp_v6_check(len, &iph->saddr, &iph->daddr, 0); + } else { + dev_kfree_skb_any(skb); + return NULL; + } + tcp_gro_complete(skb); + + if (nw_off) { /* tunnel */ + struct udphdr *uh = NULL; + + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *iph = (struct iphdr *)skb->data; + + if (iph->protocol == IPPROTO_UDP) + uh = (struct udphdr *)(iph + 1); + } else { + struct ipv6hdr *iph = (struct ipv6hdr *)skb->data; + + if (iph->nexthdr == IPPROTO_UDP) + uh = (struct udphdr *)(iph + 1); + } + if (uh) { + if (uh->check) + skb_shinfo(skb)->gso_type |= + SKB_GSO_UDP_TUNNEL_CSUM; + else + skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; + } + } +#endif + return skb; +} + +static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, + struct bnxt_napi *bnapi, + u32 *raw_cons, + struct rx_tpa_end_cmp *tpa_end, + struct rx_tpa_end_cmp_ext *tpa_end1, + bool *agg_event) +{ + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring; + u8 agg_id = TPA_END_AGG_ID(tpa_end); + u8 *data, agg_bufs; + u16 cp_cons = RING_CMP(*raw_cons); + unsigned int len; + struct bnxt_tpa_info *tpa_info; + dma_addr_t mapping; + struct sk_buff *skb; + + tpa_info = &rxr->rx_tpa[agg_id]; + data = tpa_info->data; + prefetch(data); + len = tpa_info->len; + mapping = tpa_info->mapping; + + agg_bufs = (le32_to_cpu(tpa_end->rx_tpa_end_cmp_misc_v1) & + RX_TPA_END_CMP_AGG_BUFS) >> RX_TPA_END_CMP_AGG_BUFS_SHIFT; + + if (agg_bufs) { + if (!bnxt_agg_bufs_valid(bp, cpr, agg_bufs, raw_cons)) + return ERR_PTR(-EBUSY); + + *agg_event = true; + cp_cons = NEXT_CMP(cp_cons); + } + + if (unlikely(agg_bufs > MAX_SKB_FRAGS)) { + bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs); + netdev_warn(bp->dev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n", + agg_bufs, (int)MAX_SKB_FRAGS); + return NULL; + } + + if (len <= bp->rx_copy_thresh) { + skb = bnxt_copy_skb(bnapi, data, len, mapping); + if (!skb) { + bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs); + return NULL; + } + } else { + u8 *new_data; + dma_addr_t new_mapping; + + new_data = __bnxt_alloc_rx_data(bp, &new_mapping, GFP_ATOMIC); + if (!new_data) { + bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs); + return NULL; + } + + tpa_info->data = new_data; + tpa_info->mapping = new_mapping; + + skb = build_skb(data, 0); + dma_unmap_single(&bp->pdev->dev, mapping, bp->rx_buf_use_size, + PCI_DMA_FROMDEVICE); + + if (!skb) { + kfree(data); + bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs); + return NULL; + } + skb_reserve(skb, BNXT_RX_OFFSET); + skb_put(skb, len); + } + + if (agg_bufs) { + skb = bnxt_rx_pages(bp, bnapi, skb, cp_cons, agg_bufs); + if (!skb) { + /* Page reuse already handled by bnxt_rx_pages(). */ + return NULL; + } + } + skb->protocol = eth_type_trans(skb, bp->dev); + + if (tpa_info->hash_type != PKT_HASH_TYPE_NONE) + skb_set_hash(skb, tpa_info->rss_hash, tpa_info->hash_type); + + if (tpa_info->flags2 & RX_CMP_FLAGS2_META_FORMAT_VLAN) { + netdev_features_t features = skb->dev->features; + u16 vlan_proto = tpa_info->metadata >> + RX_CMP_FLAGS2_METADATA_TPID_SFT; + + if (((features & NETIF_F_HW_VLAN_CTAG_RX) && + vlan_proto == ETH_P_8021Q) || + ((features & NETIF_F_HW_VLAN_STAG_RX) && + vlan_proto == ETH_P_8021AD)) { + __vlan_hwaccel_put_tag(skb, htons(vlan_proto), + tpa_info->metadata & + RX_CMP_FLAGS2_METADATA_VID_MASK); + } + } + + skb_checksum_none_assert(skb); + if (likely(tpa_info->flags2 & RX_TPA_START_CMP_FLAGS2_L4_CS_CALC)) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->csum_level = + (tpa_info->flags2 & RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3; + } + + if (TPA_END_GRO(tpa_end)) + skb = bnxt_gro_skb(tpa_info, tpa_end, tpa_end1, skb); + + return skb; +} + +/* returns the following: + * 1 - 1 packet successfully received + * 0 - successful TPA_START, packet not completed yet + * -EBUSY - completion ring does not have all the agg buffers yet + * -ENOMEM - packet aborted due to out of memory + * -EIO - packet aborted due to hw error indicated in BD + */ +static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons, + bool *agg_event) +{ + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring; + struct net_device *dev = bp->dev; + struct rx_cmp *rxcmp; + struct rx_cmp_ext *rxcmp1; + u32 tmp_raw_cons = *raw_cons; + u16 cons, prod, cp_cons = RING_CMP(tmp_raw_cons); + struct bnxt_sw_rx_bd *rx_buf; + unsigned int len; + u8 *data, agg_bufs, cmp_type; + dma_addr_t dma_addr; + struct sk_buff *skb; + int rc = 0; + + rxcmp = (struct rx_cmp *) + &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + + tmp_raw_cons = NEXT_RAW_CMP(tmp_raw_cons); + cp_cons = RING_CMP(tmp_raw_cons); + rxcmp1 = (struct rx_cmp_ext *) + &cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)]; + + if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons)) + return -EBUSY; + + cmp_type = RX_CMP_TYPE(rxcmp); + + prod = rxr->rx_prod; + + if (cmp_type == CMP_TYPE_RX_L2_TPA_START_CMP) { + bnxt_tpa_start(bp, rxr, (struct rx_tpa_start_cmp *)rxcmp, + (struct rx_tpa_start_cmp_ext *)rxcmp1); + + goto next_rx_no_prod; + + } else if (cmp_type == CMP_TYPE_RX_L2_TPA_END_CMP) { + skb = bnxt_tpa_end(bp, bnapi, &tmp_raw_cons, + (struct rx_tpa_end_cmp *)rxcmp, + (struct rx_tpa_end_cmp_ext *)rxcmp1, + agg_event); + + if (unlikely(IS_ERR(skb))) + return -EBUSY; + + rc = -ENOMEM; + if (likely(skb)) { + skb_record_rx_queue(skb, bnapi->index); + skb_mark_napi_id(skb, &bnapi->napi); + if (bnxt_busy_polling(bnapi)) + netif_receive_skb(skb); + else + napi_gro_receive(&bnapi->napi, skb); + rc = 1; + } + goto next_rx_no_prod; + } + + cons = rxcmp->rx_cmp_opaque; + rx_buf = &rxr->rx_buf_ring[cons]; + data = rx_buf->data; + prefetch(data); + + agg_bufs = (le32_to_cpu(rxcmp->rx_cmp_misc_v1) & RX_CMP_AGG_BUFS) >> + RX_CMP_AGG_BUFS_SHIFT; + + if (agg_bufs) { + if (!bnxt_agg_bufs_valid(bp, cpr, agg_bufs, &tmp_raw_cons)) + return -EBUSY; + + cp_cons = NEXT_CMP(cp_cons); + *agg_event = true; + } + + rx_buf->data = NULL; + if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L2_ERRORS) { + bnxt_reuse_rx_data(rxr, cons, data); + if (agg_bufs) + bnxt_reuse_rx_agg_bufs(bnapi, cp_cons, agg_bufs); + + rc = -EIO; + goto next_rx; + } + + len = le32_to_cpu(rxcmp->rx_cmp_len_flags_type) >> RX_CMP_LEN_SHIFT; + dma_addr = dma_unmap_addr(rx_buf, mapping); + + if (len <= bp->rx_copy_thresh) { + skb = bnxt_copy_skb(bnapi, data, len, dma_addr); + bnxt_reuse_rx_data(rxr, cons, data); + if (!skb) { + rc = -ENOMEM; + goto next_rx; + } + } else { + skb = bnxt_rx_skb(bp, rxr, cons, prod, data, dma_addr, len); + if (!skb) { + rc = -ENOMEM; + goto next_rx; + } + } + + if (agg_bufs) { + skb = bnxt_rx_pages(bp, bnapi, skb, cp_cons, agg_bufs); + if (!skb) { + rc = -ENOMEM; + goto next_rx; + } + } + + if (RX_CMP_HASH_VALID(rxcmp)) { + u32 hash_type = RX_CMP_HASH_TYPE(rxcmp); + enum pkt_hash_types type = PKT_HASH_TYPE_L4; + + /* RSS profiles 1 and 3 with extract code 0 for inner 4-tuple */ + if (hash_type != 1 && hash_type != 3) + type = PKT_HASH_TYPE_L3; + skb_set_hash(skb, le32_to_cpu(rxcmp->rx_cmp_rss_hash), type); + } + + skb->protocol = eth_type_trans(skb, dev); + + if (rxcmp1->rx_cmp_flags2 & + cpu_to_le32(RX_CMP_FLAGS2_META_FORMAT_VLAN)) { + netdev_features_t features = skb->dev->features; + u32 meta_data = le32_to_cpu(rxcmp1->rx_cmp_meta_data); + u16 vlan_proto = meta_data >> RX_CMP_FLAGS2_METADATA_TPID_SFT; + + if (((features & NETIF_F_HW_VLAN_CTAG_RX) && + vlan_proto == ETH_P_8021Q) || + ((features & NETIF_F_HW_VLAN_STAG_RX) && + vlan_proto == ETH_P_8021AD)) + __vlan_hwaccel_put_tag(skb, htons(vlan_proto), + meta_data & + RX_CMP_FLAGS2_METADATA_VID_MASK); + } + + skb_checksum_none_assert(skb); + if (RX_CMP_L4_CS_OK(rxcmp1)) { + if (dev->features & NETIF_F_RXCSUM) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->csum_level = RX_CMP_ENCAP(rxcmp1); + } + } else { + if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L4_CS_ERR_BITS) + cpr->rx_l4_csum_errors++; + } + + skb_record_rx_queue(skb, bnapi->index); + skb_mark_napi_id(skb, &bnapi->napi); + if (bnxt_busy_polling(bnapi)) + netif_receive_skb(skb); + else + napi_gro_receive(&bnapi->napi, skb); + rc = 1; + +next_rx: + rxr->rx_prod = NEXT_RX(prod); + +next_rx_no_prod: + *raw_cons = tmp_raw_cons; + + return rc; +} + +static int bnxt_async_event_process(struct bnxt *bp, + struct hwrm_async_event_cmpl *cmpl) +{ + u16 event_id = le16_to_cpu(cmpl->event_id); + + /* TODO CHIMP_FW: Define event id's for link change, error etc */ + switch (event_id) { + case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: + set_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event); + schedule_work(&bp->sp_task); + break; + default: + netdev_err(bp->dev, "unhandled ASYNC event (id 0x%x)\n", + event_id); + break; + } + return 0; +} + +static int bnxt_hwrm_handler(struct bnxt *bp, struct tx_cmp *txcmp) +{ + u16 cmpl_type = TX_CMP_TYPE(txcmp), vf_id, seq_id; + struct hwrm_cmpl *h_cmpl = (struct hwrm_cmpl *)txcmp; + struct hwrm_fwd_req_cmpl *fwd_req_cmpl = + (struct hwrm_fwd_req_cmpl *)txcmp; + + switch (cmpl_type) { + case CMPL_BASE_TYPE_HWRM_DONE: + seq_id = le16_to_cpu(h_cmpl->sequence_id); + if (seq_id == bp->hwrm_intr_seq_id) + bp->hwrm_intr_seq_id = HWRM_SEQ_ID_INVALID; + else + netdev_err(bp->dev, "Invalid hwrm seq id %d\n", seq_id); + break; + + case CMPL_BASE_TYPE_HWRM_FWD_REQ: + vf_id = le16_to_cpu(fwd_req_cmpl->source_id); + + if ((vf_id < bp->pf.first_vf_id) || + (vf_id >= bp->pf.first_vf_id + bp->pf.active_vfs)) { + netdev_err(bp->dev, "Msg contains invalid VF id %x\n", + vf_id); + return -EINVAL; + } + + set_bit(vf_id - bp->pf.first_vf_id, bp->pf.vf_event_bmap); + set_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event); + schedule_work(&bp->sp_task); + break; + + case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT: + bnxt_async_event_process(bp, + (struct hwrm_async_event_cmpl *)txcmp); + + default: + break; + } + + return 0; +} + +static irqreturn_t bnxt_msix(int irq, void *dev_instance) +{ + struct bnxt_napi *bnapi = dev_instance; + struct bnxt *bp = bnapi->bp; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + u32 cons = RING_CMP(cpr->cp_raw_cons); + + prefetch(&cpr->cp_desc_ring[CP_RING(cons)][CP_IDX(cons)]); + napi_schedule(&bnapi->napi); + return IRQ_HANDLED; +} + +static inline int bnxt_has_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr) +{ + u32 raw_cons = cpr->cp_raw_cons; + u16 cons = RING_CMP(raw_cons); + struct tx_cmp *txcmp; + + txcmp = &cpr->cp_desc_ring[CP_RING(cons)][CP_IDX(cons)]; + + return TX_CMP_VALID(txcmp, raw_cons); +} + +#define CAG_LEGACY_INT_STATUS 0x2014 + +static irqreturn_t bnxt_inta(int irq, void *dev_instance) +{ + struct bnxt_napi *bnapi = dev_instance; + struct bnxt *bp = bnapi->bp; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + u32 cons = RING_CMP(cpr->cp_raw_cons); + u32 int_status; + + prefetch(&cpr->cp_desc_ring[CP_RING(cons)][CP_IDX(cons)]); + + if (!bnxt_has_work(bp, cpr)) { + int_status = readl(bp->bar0 + CAG_LEGACY_INT_STATUS); + /* return if erroneous interrupt */ + if (!(int_status & (0x10000 << cpr->cp_ring_struct.fw_ring_id))) + return IRQ_NONE; + } + + /* disable ring IRQ */ + BNXT_CP_DB_IRQ_DIS(cpr->cp_doorbell); + + /* Return here if interrupt is shared and is disabled. */ + if (unlikely(atomic_read(&bp->intr_sem) != 0)) + return IRQ_HANDLED; + + napi_schedule(&bnapi->napi); + return IRQ_HANDLED; +} + +static int bnxt_poll_work(struct bnxt *bp, struct bnxt_napi *bnapi, int budget) +{ + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + u32 raw_cons = cpr->cp_raw_cons; + u32 cons; + int tx_pkts = 0; + int rx_pkts = 0; + bool rx_event = false; + bool agg_event = false; + struct tx_cmp *txcmp; + + while (1) { + int rc; + + cons = RING_CMP(raw_cons); + txcmp = &cpr->cp_desc_ring[CP_RING(cons)][CP_IDX(cons)]; + + if (!TX_CMP_VALID(txcmp, raw_cons)) + break; + + if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) { + tx_pkts++; + /* return full budget so NAPI will complete. */ + if (unlikely(tx_pkts > bp->tx_wake_thresh)) + rx_pkts = budget; + } else if ((TX_CMP_TYPE(txcmp) & 0x30) == 0x10) { + rc = bnxt_rx_pkt(bp, bnapi, &raw_cons, &agg_event); + if (likely(rc >= 0)) + rx_pkts += rc; + else if (rc == -EBUSY) /* partial completion */ + break; + rx_event = true; + } else if (unlikely((TX_CMP_TYPE(txcmp) == + CMPL_BASE_TYPE_HWRM_DONE) || + (TX_CMP_TYPE(txcmp) == + CMPL_BASE_TYPE_HWRM_FWD_REQ) || + (TX_CMP_TYPE(txcmp) == + CMPL_BASE_TYPE_HWRM_ASYNC_EVENT))) { + bnxt_hwrm_handler(bp, txcmp); + } + raw_cons = NEXT_RAW_CMP(raw_cons); + + if (rx_pkts == budget) + break; + } + + cpr->cp_raw_cons = raw_cons; + /* ACK completion ring before freeing tx ring and producing new + * buffers in rx/agg rings to prevent overflowing the completion + * ring. + */ + BNXT_CP_DB(cpr->cp_doorbell, cpr->cp_raw_cons); + + if (tx_pkts) + bnxt_tx_int(bp, bnapi, tx_pkts); + + if (rx_event) { + struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring; + + writel(DB_KEY_RX | rxr->rx_prod, rxr->rx_doorbell); + writel(DB_KEY_RX | rxr->rx_prod, rxr->rx_doorbell); + if (agg_event) { + writel(DB_KEY_RX | rxr->rx_agg_prod, + rxr->rx_agg_doorbell); + writel(DB_KEY_RX | rxr->rx_agg_prod, + rxr->rx_agg_doorbell); + } + } + return rx_pkts; +} + +static int bnxt_poll(struct napi_struct *napi, int budget) +{ + struct bnxt_napi *bnapi = container_of(napi, struct bnxt_napi, napi); + struct bnxt *bp = bnapi->bp; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + int work_done = 0; + + if (!bnxt_lock_napi(bnapi)) + return budget; + + while (1) { + work_done += bnxt_poll_work(bp, bnapi, budget - work_done); + + if (work_done >= budget) + break; + + if (!bnxt_has_work(bp, cpr)) { + napi_complete(napi); + BNXT_CP_DB_REARM(cpr->cp_doorbell, cpr->cp_raw_cons); + break; + } + } + mmiowb(); + bnxt_unlock_napi(bnapi); + return work_done; +} + +#ifdef CONFIG_NET_RX_BUSY_POLL +static int bnxt_busy_poll(struct napi_struct *napi) +{ + struct bnxt_napi *bnapi = container_of(napi, struct bnxt_napi, napi); + struct bnxt *bp = bnapi->bp; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + int rx_work, budget = 4; + + if (atomic_read(&bp->intr_sem) != 0) + return LL_FLUSH_FAILED; + + if (!bnxt_lock_poll(bnapi)) + return LL_FLUSH_BUSY; + + rx_work = bnxt_poll_work(bp, bnapi, budget); + + BNXT_CP_DB_REARM(cpr->cp_doorbell, cpr->cp_raw_cons); + + bnxt_unlock_poll(bnapi); + return rx_work; +} +#endif + +static void bnxt_free_tx_skbs(struct bnxt *bp) +{ + int i, max_idx; + struct pci_dev *pdev = bp->pdev; + + if (!bp->bnapi) + return; + + max_idx = bp->tx_nr_pages * TX_DESC_CNT; + for (i = 0; i < bp->tx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_tx_ring_info *txr; + int j; + + if (!bnapi) + continue; + + txr = &bnapi->tx_ring; + for (j = 0; j < max_idx;) { + struct bnxt_sw_tx_bd *tx_buf = &txr->tx_buf_ring[j]; + struct sk_buff *skb = tx_buf->skb; + int k, last; + + if (!skb) { + j++; + continue; + } + + tx_buf->skb = NULL; + + if (tx_buf->is_push) { + dev_kfree_skb(skb); + j += 2; + continue; + } + + dma_unmap_single(&pdev->dev, + dma_unmap_addr(tx_buf, mapping), + skb_headlen(skb), + PCI_DMA_TODEVICE); + + last = tx_buf->nr_frags; + j += 2; + for (k = 0; k < last; k++, j = NEXT_TX(j)) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[k]; + + tx_buf = &txr->tx_buf_ring[j]; + dma_unmap_page( + &pdev->dev, + dma_unmap_addr(tx_buf, mapping), + skb_frag_size(frag), PCI_DMA_TODEVICE); + } + dev_kfree_skb(skb); + } + netdev_tx_reset_queue(netdev_get_tx_queue(bp->dev, i)); + } +} + +static void bnxt_free_rx_skbs(struct bnxt *bp) +{ + int i, max_idx, max_agg_idx; + struct pci_dev *pdev = bp->pdev; + + if (!bp->bnapi) + return; + + max_idx = bp->rx_nr_pages * RX_DESC_CNT; + max_agg_idx = bp->rx_agg_nr_pages * RX_DESC_CNT; + for (i = 0; i < bp->rx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_rx_ring_info *rxr; + int j; + + if (!bnapi) + continue; + + rxr = &bnapi->rx_ring; + + if (rxr->rx_tpa) { + for (j = 0; j < MAX_TPA; j++) { + struct bnxt_tpa_info *tpa_info = + &rxr->rx_tpa[j]; + u8 *data = tpa_info->data; + + if (!data) + continue; + + dma_unmap_single( + &pdev->dev, + dma_unmap_addr(tpa_info, mapping), + bp->rx_buf_use_size, + PCI_DMA_FROMDEVICE); + + tpa_info->data = NULL; + + kfree(data); + } + } + + for (j = 0; j < max_idx; j++) { + struct bnxt_sw_rx_bd *rx_buf = &rxr->rx_buf_ring[j]; + u8 *data = rx_buf->data; + + if (!data) + continue; + + dma_unmap_single(&pdev->dev, + dma_unmap_addr(rx_buf, mapping), + bp->rx_buf_use_size, + PCI_DMA_FROMDEVICE); + + rx_buf->data = NULL; + + kfree(data); + } + + for (j = 0; j < max_agg_idx; j++) { + struct bnxt_sw_rx_agg_bd *rx_agg_buf = + &rxr->rx_agg_ring[j]; + struct page *page = rx_agg_buf->page; + + if (!page) + continue; + + dma_unmap_page(&pdev->dev, + dma_unmap_addr(rx_agg_buf, mapping), + PAGE_SIZE, PCI_DMA_FROMDEVICE); + + rx_agg_buf->page = NULL; + __clear_bit(j, rxr->rx_agg_bmap); + + __free_page(page); + } + } +} + +static void bnxt_free_skbs(struct bnxt *bp) +{ + bnxt_free_tx_skbs(bp); + bnxt_free_rx_skbs(bp); +} + +static void bnxt_free_ring(struct bnxt *bp, struct bnxt_ring_struct *ring) +{ + struct pci_dev *pdev = bp->pdev; + int i; + + for (i = 0; i < ring->nr_pages; i++) { + if (!ring->pg_arr[i]) + continue; + + dma_free_coherent(&pdev->dev, ring->page_size, + ring->pg_arr[i], ring->dma_arr[i]); + + ring->pg_arr[i] = NULL; + } + if (ring->pg_tbl) { + dma_free_coherent(&pdev->dev, ring->nr_pages * 8, + ring->pg_tbl, ring->pg_tbl_map); + ring->pg_tbl = NULL; + } + if (ring->vmem_size && *ring->vmem) { + vfree(*ring->vmem); + *ring->vmem = NULL; + } +} + +static int bnxt_alloc_ring(struct bnxt *bp, struct bnxt_ring_struct *ring) +{ + int i; + struct pci_dev *pdev = bp->pdev; + + if (ring->nr_pages > 1) { + ring->pg_tbl = dma_alloc_coherent(&pdev->dev, + ring->nr_pages * 8, + &ring->pg_tbl_map, + GFP_KERNEL); + if (!ring->pg_tbl) + return -ENOMEM; + } + + for (i = 0; i < ring->nr_pages; i++) { + ring->pg_arr[i] = dma_alloc_coherent(&pdev->dev, + ring->page_size, + &ring->dma_arr[i], + GFP_KERNEL); + if (!ring->pg_arr[i]) + return -ENOMEM; + + if (ring->nr_pages > 1) + ring->pg_tbl[i] = cpu_to_le64(ring->dma_arr[i]); + } + + if (ring->vmem_size) { + *ring->vmem = vzalloc(ring->vmem_size); + if (!(*ring->vmem)) + return -ENOMEM; + } + return 0; +} + +static void bnxt_free_rx_rings(struct bnxt *bp) +{ + int i; + + if (!bp->bnapi) + return; + + for (i = 0; i < bp->rx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_rx_ring_info *rxr; + struct bnxt_ring_struct *ring; + + if (!bnapi) + continue; + + rxr = &bnapi->rx_ring; + + kfree(rxr->rx_tpa); + rxr->rx_tpa = NULL; + + kfree(rxr->rx_agg_bmap); + rxr->rx_agg_bmap = NULL; + + ring = &rxr->rx_ring_struct; + bnxt_free_ring(bp, ring); + + ring = &rxr->rx_agg_ring_struct; + bnxt_free_ring(bp, ring); + } +} + +static int bnxt_alloc_rx_rings(struct bnxt *bp) +{ + int i, rc, agg_rings = 0, tpa_rings = 0; + + if (bp->flags & BNXT_FLAG_AGG_RINGS) + agg_rings = 1; + + if (bp->flags & BNXT_FLAG_TPA) + tpa_rings = 1; + + for (i = 0; i < bp->rx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_rx_ring_info *rxr; + struct bnxt_ring_struct *ring; + + if (!bnapi) + continue; + + rxr = &bnapi->rx_ring; + ring = &rxr->rx_ring_struct; + + rc = bnxt_alloc_ring(bp, ring); + if (rc) + return rc; + + if (agg_rings) { + u16 mem_size; + + ring = &rxr->rx_agg_ring_struct; + rc = bnxt_alloc_ring(bp, ring); + if (rc) + return rc; + + rxr->rx_agg_bmap_size = bp->rx_agg_ring_mask + 1; + mem_size = rxr->rx_agg_bmap_size / 8; + rxr->rx_agg_bmap = kzalloc(mem_size, GFP_KERNEL); + if (!rxr->rx_agg_bmap) + return -ENOMEM; + + if (tpa_rings) { + rxr->rx_tpa = kcalloc(MAX_TPA, + sizeof(struct bnxt_tpa_info), + GFP_KERNEL); + if (!rxr->rx_tpa) + return -ENOMEM; + } + } + } + return 0; +} + +static void bnxt_free_tx_rings(struct bnxt *bp) +{ + int i; + struct pci_dev *pdev = bp->pdev; + + if (!bp->bnapi) + return; + + for (i = 0; i < bp->tx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_tx_ring_info *txr; + struct bnxt_ring_struct *ring; + + if (!bnapi) + continue; + + txr = &bnapi->tx_ring; + + if (txr->tx_push) { + dma_free_coherent(&pdev->dev, bp->tx_push_size, + txr->tx_push, txr->tx_push_mapping); + txr->tx_push = NULL; + } + + ring = &txr->tx_ring_struct; + + bnxt_free_ring(bp, ring); + } +} + +static int bnxt_alloc_tx_rings(struct bnxt *bp) +{ + int i, j, rc; + struct pci_dev *pdev = bp->pdev; + + bp->tx_push_size = 0; + if (bp->tx_push_thresh) { + int push_size; + + push_size = L1_CACHE_ALIGN(sizeof(struct tx_push_bd) + + bp->tx_push_thresh); + + if (push_size > 128) { + push_size = 0; + bp->tx_push_thresh = 0; + } + + bp->tx_push_size = push_size; + } + + for (i = 0, j = 0; i < bp->tx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_tx_ring_info *txr; + struct bnxt_ring_struct *ring; + + if (!bnapi) + continue; + + txr = &bnapi->tx_ring; + ring = &txr->tx_ring_struct; + + rc = bnxt_alloc_ring(bp, ring); + if (rc) + return rc; + + if (bp->tx_push_size) { + struct tx_bd *txbd; + dma_addr_t mapping; + + /* One pre-allocated DMA buffer to backup + * TX push operation + */ + txr->tx_push = dma_alloc_coherent(&pdev->dev, + bp->tx_push_size, + &txr->tx_push_mapping, + GFP_KERNEL); + + if (!txr->tx_push) + return -ENOMEM; + + txbd = &txr->tx_push->txbd1; + + mapping = txr->tx_push_mapping + + sizeof(struct tx_push_bd); + txbd->tx_bd_haddr = cpu_to_le64(mapping); + + memset(txbd + 1, 0, sizeof(struct tx_bd_ext)); + } + ring->queue_id = bp->q_info[j].queue_id; + if (i % bp->tx_nr_rings_per_tc == (bp->tx_nr_rings_per_tc - 1)) + j++; + } + return 0; +} + +static void bnxt_free_cp_rings(struct bnxt *bp) +{ + int i; + + if (!bp->bnapi) + return; + + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr; + struct bnxt_ring_struct *ring; + + if (!bnapi) + continue; + + cpr = &bnapi->cp_ring; + ring = &cpr->cp_ring_struct; + + bnxt_free_ring(bp, ring); + } +} + +static int bnxt_alloc_cp_rings(struct bnxt *bp) +{ + int i, rc; + + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr; + struct bnxt_ring_struct *ring; + + if (!bnapi) + continue; + + cpr = &bnapi->cp_ring; + ring = &cpr->cp_ring_struct; + + rc = bnxt_alloc_ring(bp, ring); + if (rc) + return rc; + } + return 0; +} + +static void bnxt_init_ring_struct(struct bnxt *bp) +{ + int i; + + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr; + struct bnxt_rx_ring_info *rxr; + struct bnxt_tx_ring_info *txr; + struct bnxt_ring_struct *ring; + + if (!bnapi) + continue; + + cpr = &bnapi->cp_ring; + ring = &cpr->cp_ring_struct; + ring->nr_pages = bp->cp_nr_pages; + ring->page_size = HW_CMPD_RING_SIZE; + ring->pg_arr = (void **)cpr->cp_desc_ring; + ring->dma_arr = cpr->cp_desc_mapping; + ring->vmem_size = 0; + + rxr = &bnapi->rx_ring; + ring = &rxr->rx_ring_struct; + ring->nr_pages = bp->rx_nr_pages; + ring->page_size = HW_RXBD_RING_SIZE; + ring->pg_arr = (void **)rxr->rx_desc_ring; + ring->dma_arr = rxr->rx_desc_mapping; + ring->vmem_size = SW_RXBD_RING_SIZE * bp->rx_nr_pages; + ring->vmem = (void **)&rxr->rx_buf_ring; + + ring = &rxr->rx_agg_ring_struct; + ring->nr_pages = bp->rx_agg_nr_pages; + ring->page_size = HW_RXBD_RING_SIZE; + ring->pg_arr = (void **)rxr->rx_agg_desc_ring; + ring->dma_arr = rxr->rx_agg_desc_mapping; + ring->vmem_size = SW_RXBD_AGG_RING_SIZE * bp->rx_agg_nr_pages; + ring->vmem = (void **)&rxr->rx_agg_ring; + + txr = &bnapi->tx_ring; + ring = &txr->tx_ring_struct; + ring->nr_pages = bp->tx_nr_pages; + ring->page_size = HW_RXBD_RING_SIZE; + ring->pg_arr = (void **)txr->tx_desc_ring; + ring->dma_arr = txr->tx_desc_mapping; + ring->vmem_size = SW_TXBD_RING_SIZE * bp->tx_nr_pages; + ring->vmem = (void **)&txr->tx_buf_ring; + } +} + +static void bnxt_init_rxbd_pages(struct bnxt_ring_struct *ring, u32 type) +{ + int i; + u32 prod; + struct rx_bd **rx_buf_ring; + + rx_buf_ring = (struct rx_bd **)ring->pg_arr; + for (i = 0, prod = 0; i < ring->nr_pages; i++) { + int j; + struct rx_bd *rxbd; + + rxbd = rx_buf_ring[i]; + if (!rxbd) + continue; + + for (j = 0; j < RX_DESC_CNT; j++, rxbd++, prod++) { + rxbd->rx_bd_len_flags_type = cpu_to_le32(type); + rxbd->rx_bd_opaque = prod; + } + } +} + +static int bnxt_init_one_rx_ring(struct bnxt *bp, int ring_nr) +{ + struct net_device *dev = bp->dev; + struct bnxt_napi *bnapi = bp->bnapi[ring_nr]; + struct bnxt_rx_ring_info *rxr; + struct bnxt_ring_struct *ring; + u32 prod, type; + int i; + + if (!bnapi) + return -EINVAL; + + type = (bp->rx_buf_use_size << RX_BD_LEN_SHIFT) | + RX_BD_TYPE_RX_PACKET_BD | RX_BD_FLAGS_EOP; + + if (NET_IP_ALIGN == 2) + type |= RX_BD_FLAGS_SOP; + + rxr = &bnapi->rx_ring; + ring = &rxr->rx_ring_struct; + bnxt_init_rxbd_pages(ring, type); + + prod = rxr->rx_prod; + for (i = 0; i < bp->rx_ring_size; i++) { + if (bnxt_alloc_rx_data(bp, rxr, prod, GFP_KERNEL) != 0) { + netdev_warn(dev, "init'ed rx ring %d with %d/%d skbs only\n", + ring_nr, i, bp->rx_ring_size); + break; + } + prod = NEXT_RX(prod); + } + rxr->rx_prod = prod; + ring->fw_ring_id = INVALID_HW_RING_ID; + + if (!(bp->flags & BNXT_FLAG_AGG_RINGS)) + return 0; + + ring = &rxr->rx_agg_ring_struct; + + type = ((u32)PAGE_SIZE << RX_BD_LEN_SHIFT) | + RX_BD_TYPE_RX_AGG_BD | RX_BD_FLAGS_SOP; + + bnxt_init_rxbd_pages(ring, type); + + prod = rxr->rx_agg_prod; + for (i = 0; i < bp->rx_agg_ring_size; i++) { + if (bnxt_alloc_rx_page(bp, rxr, prod, GFP_KERNEL) != 0) { + netdev_warn(dev, "init'ed rx ring %d with %d/%d pages only\n", + ring_nr, i, bp->rx_ring_size); + break; + } + prod = NEXT_RX_AGG(prod); + } + rxr->rx_agg_prod = prod; + ring->fw_ring_id = INVALID_HW_RING_ID; + + if (bp->flags & BNXT_FLAG_TPA) { + if (rxr->rx_tpa) { + u8 *data; + dma_addr_t mapping; + + for (i = 0; i < MAX_TPA; i++) { + data = __bnxt_alloc_rx_data(bp, &mapping, + GFP_KERNEL); + if (!data) + return -ENOMEM; + + rxr->rx_tpa[i].data = data; + rxr->rx_tpa[i].mapping = mapping; + } + } else { + netdev_err(bp->dev, "No resource allocated for LRO/GRO\n"); + return -ENOMEM; + } + } + + return 0; +} + +static int bnxt_init_rx_rings(struct bnxt *bp) +{ + int i, rc = 0; + + for (i = 0; i < bp->rx_nr_rings; i++) { + rc = bnxt_init_one_rx_ring(bp, i); + if (rc) + break; + } + + return rc; +} + +static int bnxt_init_tx_rings(struct bnxt *bp) +{ + u16 i; + + bp->tx_wake_thresh = max_t(int, bp->tx_ring_size / 2, + MAX_SKB_FRAGS + 1); + + for (i = 0; i < bp->tx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_tx_ring_info *txr = &bnapi->tx_ring; + struct bnxt_ring_struct *ring = &txr->tx_ring_struct; + + ring->fw_ring_id = INVALID_HW_RING_ID; + } + + return 0; +} + +static void bnxt_free_ring_grps(struct bnxt *bp) +{ + kfree(bp->grp_info); + bp->grp_info = NULL; +} + +static int bnxt_init_ring_grps(struct bnxt *bp, bool irq_re_init) +{ + int i; + + if (irq_re_init) { + bp->grp_info = kcalloc(bp->cp_nr_rings, + sizeof(struct bnxt_ring_grp_info), + GFP_KERNEL); + if (!bp->grp_info) + return -ENOMEM; + } + for (i = 0; i < bp->cp_nr_rings; i++) { + if (irq_re_init) + bp->grp_info[i].fw_stats_ctx = INVALID_HW_RING_ID; + bp->grp_info[i].fw_grp_id = INVALID_HW_RING_ID; + bp->grp_info[i].rx_fw_ring_id = INVALID_HW_RING_ID; + bp->grp_info[i].agg_fw_ring_id = INVALID_HW_RING_ID; + bp->grp_info[i].cp_fw_ring_id = INVALID_HW_RING_ID; + } + return 0; +} + +static void bnxt_free_vnics(struct bnxt *bp) +{ + kfree(bp->vnic_info); + bp->vnic_info = NULL; + bp->nr_vnics = 0; +} + +static int bnxt_alloc_vnics(struct bnxt *bp) +{ + int num_vnics = 1; + +#ifdef CONFIG_RFS_ACCEL + if (bp->flags & BNXT_FLAG_RFS) + num_vnics += bp->rx_nr_rings; +#endif + + bp->vnic_info = kcalloc(num_vnics, sizeof(struct bnxt_vnic_info), + GFP_KERNEL); + if (!bp->vnic_info) + return -ENOMEM; + + bp->nr_vnics = num_vnics; + return 0; +} + +static void bnxt_init_vnics(struct bnxt *bp) +{ + int i; + + for (i = 0; i < bp->nr_vnics; i++) { + struct bnxt_vnic_info *vnic = &bp->vnic_info[i]; + + vnic->fw_vnic_id = INVALID_HW_RING_ID; + vnic->fw_rss_cos_lb_ctx = INVALID_HW_RING_ID; + vnic->fw_l2_ctx_id = INVALID_HW_RING_ID; + + if (bp->vnic_info[i].rss_hash_key) { + if (i == 0) + prandom_bytes(vnic->rss_hash_key, + HW_HASH_KEY_SIZE); + else + memcpy(vnic->rss_hash_key, + bp->vnic_info[0].rss_hash_key, + HW_HASH_KEY_SIZE); + } + } +} + +static int bnxt_calc_nr_ring_pages(u32 ring_size, int desc_per_pg) +{ + int pages; + + pages = ring_size / desc_per_pg; + + if (!pages) + return 1; + + pages++; + + while (pages & (pages - 1)) + pages++; + + return pages; +} + +static void bnxt_set_tpa_flags(struct bnxt *bp) +{ + bp->flags &= ~BNXT_FLAG_TPA; + if (bp->dev->features & NETIF_F_LRO) + bp->flags |= BNXT_FLAG_LRO; + if ((bp->dev->features & NETIF_F_GRO) && (bp->pdev->revision > 0)) + bp->flags |= BNXT_FLAG_GRO; +} + +/* bp->rx_ring_size, bp->tx_ring_size, dev->mtu, BNXT_FLAG_{G|L}RO flags must + * be set on entry. + */ +void bnxt_set_ring_params(struct bnxt *bp) +{ + u32 ring_size, rx_size, rx_space; + u32 agg_factor = 0, agg_ring_size = 0; + + /* 8 for CRC and VLAN */ + rx_size = SKB_DATA_ALIGN(bp->dev->mtu + ETH_HLEN + NET_IP_ALIGN + 8); + + rx_space = rx_size + NET_SKB_PAD + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + + bp->rx_copy_thresh = BNXT_RX_COPY_THRESH; + ring_size = bp->rx_ring_size; + bp->rx_agg_ring_size = 0; + bp->rx_agg_nr_pages = 0; + + if (bp->flags & BNXT_FLAG_TPA) + agg_factor = 4; + + bp->flags &= ~BNXT_FLAG_JUMBO; + if (rx_space > PAGE_SIZE) { + u32 jumbo_factor; + + bp->flags |= BNXT_FLAG_JUMBO; + jumbo_factor = PAGE_ALIGN(bp->dev->mtu - 40) >> PAGE_SHIFT; + if (jumbo_factor > agg_factor) + agg_factor = jumbo_factor; + } + agg_ring_size = ring_size * agg_factor; + + if (agg_ring_size) { + bp->rx_agg_nr_pages = bnxt_calc_nr_ring_pages(agg_ring_size, + RX_DESC_CNT); + if (bp->rx_agg_nr_pages > MAX_RX_AGG_PAGES) { + u32 tmp = agg_ring_size; + + bp->rx_agg_nr_pages = MAX_RX_AGG_PAGES; + agg_ring_size = MAX_RX_AGG_PAGES * RX_DESC_CNT - 1; + netdev_warn(bp->dev, "rx agg ring size %d reduced to %d.\n", + tmp, agg_ring_size); + } + bp->rx_agg_ring_size = agg_ring_size; + bp->rx_agg_ring_mask = (bp->rx_agg_nr_pages * RX_DESC_CNT) - 1; + rx_size = SKB_DATA_ALIGN(BNXT_RX_COPY_THRESH + NET_IP_ALIGN); + rx_space = rx_size + NET_SKB_PAD + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + } + + bp->rx_buf_use_size = rx_size; + bp->rx_buf_size = rx_space; + + bp->rx_nr_pages = bnxt_calc_nr_ring_pages(ring_size, RX_DESC_CNT); + bp->rx_ring_mask = (bp->rx_nr_pages * RX_DESC_CNT) - 1; + + ring_size = bp->tx_ring_size; + bp->tx_nr_pages = bnxt_calc_nr_ring_pages(ring_size, TX_DESC_CNT); + bp->tx_ring_mask = (bp->tx_nr_pages * TX_DESC_CNT) - 1; + + ring_size = bp->rx_ring_size * (2 + agg_factor) + bp->tx_ring_size; + bp->cp_ring_size = ring_size; + + bp->cp_nr_pages = bnxt_calc_nr_ring_pages(ring_size, CP_DESC_CNT); + if (bp->cp_nr_pages > MAX_CP_PAGES) { + bp->cp_nr_pages = MAX_CP_PAGES; + bp->cp_ring_size = MAX_CP_PAGES * CP_DESC_CNT - 1; + netdev_warn(bp->dev, "completion ring size %d reduced to %d.\n", + ring_size, bp->cp_ring_size); + } + bp->cp_bit = bp->cp_nr_pages * CP_DESC_CNT; + bp->cp_ring_mask = bp->cp_bit - 1; +} + +static void bnxt_free_vnic_attributes(struct bnxt *bp) +{ + int i; + struct bnxt_vnic_info *vnic; + struct pci_dev *pdev = bp->pdev; + + if (!bp->vnic_info) + return; + + for (i = 0; i < bp->nr_vnics; i++) { + vnic = &bp->vnic_info[i]; + + kfree(vnic->fw_grp_ids); + vnic->fw_grp_ids = NULL; + + kfree(vnic->uc_list); + vnic->uc_list = NULL; + + if (vnic->mc_list) { + dma_free_coherent(&pdev->dev, vnic->mc_list_size, + vnic->mc_list, vnic->mc_list_mapping); + vnic->mc_list = NULL; + } + + if (vnic->rss_table) { + dma_free_coherent(&pdev->dev, PAGE_SIZE, + vnic->rss_table, + vnic->rss_table_dma_addr); + vnic->rss_table = NULL; + } + + vnic->rss_hash_key = NULL; + vnic->flags = 0; + } +} + +static int bnxt_alloc_vnic_attributes(struct bnxt *bp) +{ + int i, rc = 0, size; + struct bnxt_vnic_info *vnic; + struct pci_dev *pdev = bp->pdev; + int max_rings; + + for (i = 0; i < bp->nr_vnics; i++) { + vnic = &bp->vnic_info[i]; + + if (vnic->flags & BNXT_VNIC_UCAST_FLAG) { + int mem_size = (BNXT_MAX_UC_ADDRS - 1) * ETH_ALEN; + + if (mem_size > 0) { + vnic->uc_list = kmalloc(mem_size, GFP_KERNEL); + if (!vnic->uc_list) { + rc = -ENOMEM; + goto out; + } + } + } + + if (vnic->flags & BNXT_VNIC_MCAST_FLAG) { + vnic->mc_list_size = BNXT_MAX_MC_ADDRS * ETH_ALEN; + vnic->mc_list = + dma_alloc_coherent(&pdev->dev, + vnic->mc_list_size, + &vnic->mc_list_mapping, + GFP_KERNEL); + if (!vnic->mc_list) { + rc = -ENOMEM; + goto out; + } + } + + if (vnic->flags & BNXT_VNIC_RSS_FLAG) + max_rings = bp->rx_nr_rings; + else + max_rings = 1; + + vnic->fw_grp_ids = kcalloc(max_rings, sizeof(u16), GFP_KERNEL); + if (!vnic->fw_grp_ids) { + rc = -ENOMEM; + goto out; + } + + /* Allocate rss table and hash key */ + vnic->rss_table = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, + &vnic->rss_table_dma_addr, + GFP_KERNEL); + if (!vnic->rss_table) { + rc = -ENOMEM; + goto out; + } + + size = L1_CACHE_ALIGN(HW_HASH_INDEX_SIZE * sizeof(u16)); + + vnic->rss_hash_key = ((void *)vnic->rss_table) + size; + vnic->rss_hash_key_dma_addr = vnic->rss_table_dma_addr + size; + } + return 0; + +out: + return rc; +} + +static void bnxt_free_hwrm_resources(struct bnxt *bp) +{ + struct pci_dev *pdev = bp->pdev; + + dma_free_coherent(&pdev->dev, PAGE_SIZE, bp->hwrm_cmd_resp_addr, + bp->hwrm_cmd_resp_dma_addr); + + bp->hwrm_cmd_resp_addr = NULL; + if (bp->hwrm_dbg_resp_addr) { + dma_free_coherent(&pdev->dev, HWRM_DBG_REG_BUF_SIZE, + bp->hwrm_dbg_resp_addr, + bp->hwrm_dbg_resp_dma_addr); + + bp->hwrm_dbg_resp_addr = NULL; + } +} + +static int bnxt_alloc_hwrm_resources(struct bnxt *bp) +{ + struct pci_dev *pdev = bp->pdev; + + bp->hwrm_cmd_resp_addr = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, + &bp->hwrm_cmd_resp_dma_addr, + GFP_KERNEL); + if (!bp->hwrm_cmd_resp_addr) + return -ENOMEM; + bp->hwrm_dbg_resp_addr = dma_alloc_coherent(&pdev->dev, + HWRM_DBG_REG_BUF_SIZE, + &bp->hwrm_dbg_resp_dma_addr, + GFP_KERNEL); + if (!bp->hwrm_dbg_resp_addr) + netdev_warn(bp->dev, "fail to alloc debug register dma mem\n"); + + return 0; +} + +static void bnxt_free_stats(struct bnxt *bp) +{ + u32 size, i; + struct pci_dev *pdev = bp->pdev; + + if (!bp->bnapi) + return; + + size = sizeof(struct ctx_hw_stats); + + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + + if (cpr->hw_stats) { + dma_free_coherent(&pdev->dev, size, cpr->hw_stats, + cpr->hw_stats_map); + cpr->hw_stats = NULL; + } + } +} + +static int bnxt_alloc_stats(struct bnxt *bp) +{ + u32 size, i; + struct pci_dev *pdev = bp->pdev; + + size = sizeof(struct ctx_hw_stats); + + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + + cpr->hw_stats = dma_alloc_coherent(&pdev->dev, size, + &cpr->hw_stats_map, + GFP_KERNEL); + if (!cpr->hw_stats) + return -ENOMEM; + + cpr->hw_stats_ctx_id = INVALID_STATS_CTX_ID; + } + return 0; +} + +static void bnxt_clear_ring_indices(struct bnxt *bp) +{ + int i; + + if (!bp->bnapi) + return; + + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr; + struct bnxt_rx_ring_info *rxr; + struct bnxt_tx_ring_info *txr; + + if (!bnapi) + continue; + + cpr = &bnapi->cp_ring; + cpr->cp_raw_cons = 0; + + txr = &bnapi->tx_ring; + txr->tx_prod = 0; + txr->tx_cons = 0; + + rxr = &bnapi->rx_ring; + rxr->rx_prod = 0; + rxr->rx_agg_prod = 0; + rxr->rx_sw_agg_prod = 0; + } +} + +static void bnxt_free_ntp_fltrs(struct bnxt *bp, bool irq_reinit) +{ +#ifdef CONFIG_RFS_ACCEL + int i; + + /* Under rtnl_lock and all our NAPIs have been disabled. It's + * safe to delete the hash table. + */ + for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) { + struct hlist_head *head; + struct hlist_node *tmp; + struct bnxt_ntuple_filter *fltr; + + head = &bp->ntp_fltr_hash_tbl[i]; + hlist_for_each_entry_safe(fltr, tmp, head, hash) { + hlist_del(&fltr->hash); + kfree(fltr); + } + } + if (irq_reinit) { + kfree(bp->ntp_fltr_bmap); + bp->ntp_fltr_bmap = NULL; + } + bp->ntp_fltr_count = 0; +#endif +} + +static int bnxt_alloc_ntp_fltrs(struct bnxt *bp) +{ +#ifdef CONFIG_RFS_ACCEL + int i, rc = 0; + + if (!(bp->flags & BNXT_FLAG_RFS)) + return 0; + + for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) + INIT_HLIST_HEAD(&bp->ntp_fltr_hash_tbl[i]); + + bp->ntp_fltr_count = 0; + bp->ntp_fltr_bmap = kzalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR), + GFP_KERNEL); + + if (!bp->ntp_fltr_bmap) + rc = -ENOMEM; + + return rc; +#else + return 0; +#endif +} + +static void bnxt_free_mem(struct bnxt *bp, bool irq_re_init) +{ + bnxt_free_vnic_attributes(bp); + bnxt_free_tx_rings(bp); + bnxt_free_rx_rings(bp); + bnxt_free_cp_rings(bp); + bnxt_free_ntp_fltrs(bp, irq_re_init); + if (irq_re_init) { + bnxt_free_stats(bp); + bnxt_free_ring_grps(bp); + bnxt_free_vnics(bp); + kfree(bp->bnapi); + bp->bnapi = NULL; + } else { + bnxt_clear_ring_indices(bp); + } +} + +static int bnxt_alloc_mem(struct bnxt *bp, bool irq_re_init) +{ + int i, rc, size, arr_size; + void *bnapi; + + if (irq_re_init) { + /* Allocate bnapi mem pointer array and mem block for + * all queues + */ + arr_size = L1_CACHE_ALIGN(sizeof(struct bnxt_napi *) * + bp->cp_nr_rings); + size = L1_CACHE_ALIGN(sizeof(struct bnxt_napi)); + bnapi = kzalloc(arr_size + size * bp->cp_nr_rings, GFP_KERNEL); + if (!bnapi) + return -ENOMEM; + + bp->bnapi = bnapi; + bnapi += arr_size; + for (i = 0; i < bp->cp_nr_rings; i++, bnapi += size) { + bp->bnapi[i] = bnapi; + bp->bnapi[i]->index = i; + bp->bnapi[i]->bp = bp; + } + + rc = bnxt_alloc_stats(bp); + if (rc) + goto alloc_mem_err; + + rc = bnxt_alloc_ntp_fltrs(bp); + if (rc) + goto alloc_mem_err; + + rc = bnxt_alloc_vnics(bp); + if (rc) + goto alloc_mem_err; + } + + bnxt_init_ring_struct(bp); + + rc = bnxt_alloc_rx_rings(bp); + if (rc) + goto alloc_mem_err; + + rc = bnxt_alloc_tx_rings(bp); + if (rc) + goto alloc_mem_err; + + rc = bnxt_alloc_cp_rings(bp); + if (rc) + goto alloc_mem_err; + + bp->vnic_info[0].flags |= BNXT_VNIC_RSS_FLAG | BNXT_VNIC_MCAST_FLAG | + BNXT_VNIC_UCAST_FLAG; + rc = bnxt_alloc_vnic_attributes(bp); + if (rc) + goto alloc_mem_err; + return 0; + +alloc_mem_err: + bnxt_free_mem(bp, true); + return rc; +} + +void bnxt_hwrm_cmd_hdr_init(struct bnxt *bp, void *request, u16 req_type, + u16 cmpl_ring, u16 target_id) +{ + struct hwrm_cmd_req_hdr *req = request; + + req->cmpl_ring_req_type = + cpu_to_le32(req_type | (cmpl_ring << HWRM_CMPL_RING_SFT)); + req->target_id_seq_id = cpu_to_le32(target_id << HWRM_TARGET_FID_SFT); + req->resp_addr = cpu_to_le64(bp->hwrm_cmd_resp_dma_addr); +} + +int _hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout) +{ + int i, intr_process, rc; + struct hwrm_cmd_req_hdr *req = msg; + u32 *data = msg; + __le32 *resp_len, *valid; + u16 cp_ring_id, len = 0; + struct hwrm_err_output *resp = bp->hwrm_cmd_resp_addr; + + req->target_id_seq_id |= cpu_to_le32(bp->hwrm_cmd_seq++); + memset(resp, 0, PAGE_SIZE); + cp_ring_id = (le32_to_cpu(req->cmpl_ring_req_type) & + HWRM_CMPL_RING_MASK) >> + HWRM_CMPL_RING_SFT; + intr_process = (cp_ring_id == INVALID_HW_RING_ID) ? 0 : 1; + + /* Write request msg to hwrm channel */ + __iowrite32_copy(bp->bar0, data, msg_len / 4); + + /* currently supports only one outstanding message */ + if (intr_process) + bp->hwrm_intr_seq_id = le32_to_cpu(req->target_id_seq_id) & + HWRM_SEQ_ID_MASK; + + /* Ring channel doorbell */ + writel(1, bp->bar0 + 0x100); + + i = 0; + if (intr_process) { + /* Wait until hwrm response cmpl interrupt is processed */ + while (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID && + i++ < timeout) { + usleep_range(600, 800); + } + + if (bp->hwrm_intr_seq_id != HWRM_SEQ_ID_INVALID) { + netdev_err(bp->dev, "Resp cmpl intr err msg: 0x%x\n", + req->cmpl_ring_req_type); + return -1; + } + } else { + /* Check if response len is updated */ + resp_len = bp->hwrm_cmd_resp_addr + HWRM_RESP_LEN_OFFSET; + for (i = 0; i < timeout; i++) { + len = (le32_to_cpu(*resp_len) & HWRM_RESP_LEN_MASK) >> + HWRM_RESP_LEN_SFT; + if (len) + break; + usleep_range(600, 800); + } + + if (i >= timeout) { + netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d\n", + timeout, req->cmpl_ring_req_type, + req->target_id_seq_id, *resp_len); + return -1; + } + + /* Last word of resp contains valid bit */ + valid = bp->hwrm_cmd_resp_addr + len - 4; + for (i = 0; i < timeout; i++) { + if (le32_to_cpu(*valid) & HWRM_RESP_VALID_MASK) + break; + usleep_range(600, 800); + } + + if (i >= timeout) { + netdev_err(bp->dev, "Error (timeout: %d) msg {0x%x 0x%x} len:%d v:%d\n", + timeout, req->cmpl_ring_req_type, + req->target_id_seq_id, len, *valid); + return -1; + } + } + + rc = le16_to_cpu(resp->error_code); + if (rc) { + netdev_err(bp->dev, "hwrm req_type 0x%x seq id 0x%x error 0x%x\n", + le16_to_cpu(resp->req_type), + le16_to_cpu(resp->seq_id), rc); + return rc; + } + return 0; +} + +int hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout) +{ + int rc; + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, msg, msg_len, timeout); + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp) +{ + struct hwrm_func_drv_rgtr_input req = {0}; + int i; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_DRV_RGTR, -1, -1); + + req.enables = + cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE | + FUNC_DRV_RGTR_REQ_ENABLES_VER | + FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD); + + /* TODO: current async event fwd bits are not defined and the firmware + * only checks if it is non-zero to enable async event forwarding + */ + req.async_event_fwd[0] |= cpu_to_le32(1); + req.os_type = cpu_to_le16(1); + req.ver_maj = DRV_VER_MAJ; + req.ver_min = DRV_VER_MIN; + req.ver_upd = DRV_VER_UPD; + + if (BNXT_PF(bp)) { + unsigned long vf_req_snif_bmap[4]; + u32 *data = (u32 *)vf_req_snif_bmap; + + memset(vf_req_snif_bmap, 0, 32); + for (i = 0; i < ARRAY_SIZE(bnxt_vf_req_snif); i++) + __set_bit(bnxt_vf_req_snif[i], vf_req_snif_bmap); + + for (i = 0; i < 8; i++) { + req.vf_req_fwd[i] = cpu_to_le32(*data); + data++; + } + req.enables |= + cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_VF_REQ_FWD); + } + + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + +static int bnxt_hwrm_tunnel_dst_port_free(struct bnxt *bp, u8 tunnel_type) +{ + u32 rc = 0; + struct hwrm_tunnel_dst_port_free_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_TUNNEL_DST_PORT_FREE, -1, -1); + req.tunnel_type = tunnel_type; + + switch (tunnel_type) { + case TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN: + req.tunnel_dst_port_id = bp->vxlan_fw_dst_port_id; + break; + case TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE: + req.tunnel_dst_port_id = bp->nge_fw_dst_port_id; + break; + default: + break; + } + + rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc) + netdev_err(bp->dev, "hwrm_tunnel_dst_port_free failed. rc:%d\n", + rc); + return rc; +} + +static int bnxt_hwrm_tunnel_dst_port_alloc(struct bnxt *bp, __be16 port, + u8 tunnel_type) +{ + u32 rc = 0; + struct hwrm_tunnel_dst_port_alloc_input req = {0}; + struct hwrm_tunnel_dst_port_alloc_output *resp = bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_TUNNEL_DST_PORT_ALLOC, -1, -1); + + req.tunnel_type = tunnel_type; + req.tunnel_dst_port_val = port; + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc) { + netdev_err(bp->dev, "hwrm_tunnel_dst_port_alloc failed. rc:%d\n", + rc); + goto err_out; + } + + if (tunnel_type & TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_VXLAN) + bp->vxlan_fw_dst_port_id = resp->tunnel_dst_port_id; + + else if (tunnel_type & TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_GENEVE) + bp->nge_fw_dst_port_id = resp->tunnel_dst_port_id; +err_out: + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp, u16 vnic_id) +{ + struct hwrm_cfa_l2_set_rx_mask_input req = {0}; + struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id]; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_L2_SET_RX_MASK, -1, -1); + req.dflt_vnic_id = cpu_to_le32(vnic->fw_vnic_id); + + req.num_mc_entries = cpu_to_le32(vnic->mc_list_count); + req.mc_tbl_addr = cpu_to_le64(vnic->mc_list_mapping); + req.mask = cpu_to_le32(vnic->rx_mask); + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + +#ifdef CONFIG_RFS_ACCEL +static int bnxt_hwrm_cfa_ntuple_filter_free(struct bnxt *bp, + struct bnxt_ntuple_filter *fltr) +{ + struct hwrm_cfa_ntuple_filter_free_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_NTUPLE_FILTER_FREE, -1, -1); + req.ntuple_filter_id = fltr->filter_id; + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + +#define BNXT_NTP_FLTR_FLAGS \ + (CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_L2_FILTER_ID | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_ETHERTYPE | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_MACADDR | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_IPADDR_TYPE | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_IPADDR | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_IPADDR_MASK | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_IPADDR | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_IPADDR_MASK | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_IP_PROTOCOL | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_PORT | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_PORT_MASK | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_PORT | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_PORT_MASK | \ + CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_VNIC_ID) + +static int bnxt_hwrm_cfa_ntuple_filter_alloc(struct bnxt *bp, + struct bnxt_ntuple_filter *fltr) +{ + int rc = 0; + struct hwrm_cfa_ntuple_filter_alloc_input req = {0}; + struct hwrm_cfa_ntuple_filter_alloc_output *resp = + bp->hwrm_cmd_resp_addr; + struct flow_keys *keys = &fltr->fkeys; + struct bnxt_vnic_info *vnic = &bp->vnic_info[fltr->rxq + 1]; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_NTUPLE_FILTER_ALLOC, -1, -1); + req.l2_filter_id = bp->vnic_info[0].fw_l2_filter_id[0]; + + req.enables = cpu_to_le32(BNXT_NTP_FLTR_FLAGS); + + req.ethertype = htons(ETH_P_IP); + memcpy(req.src_macaddr, fltr->src_mac_addr, ETH_ALEN); + req.ipaddr_type = 4; + req.ip_protocol = keys->basic.ip_proto; + + req.src_ipaddr[0] = keys->addrs.v4addrs.src; + req.src_ipaddr_mask[0] = cpu_to_be32(0xffffffff); + req.dst_ipaddr[0] = keys->addrs.v4addrs.dst; + req.dst_ipaddr_mask[0] = cpu_to_be32(0xffffffff); + + req.src_port = keys->ports.src; + req.src_port_mask = cpu_to_be16(0xffff); + req.dst_port = keys->ports.dst; + req.dst_port_mask = cpu_to_be16(0xffff); + + req.dst_vnic_id = cpu_to_le16(vnic->fw_vnic_id); + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (!rc) + fltr->filter_id = resp->ntuple_filter_id; + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} +#endif + +static int bnxt_hwrm_set_vnic_filter(struct bnxt *bp, u16 vnic_id, u16 idx, + u8 *mac_addr) +{ + u32 rc = 0; + struct hwrm_cfa_l2_filter_alloc_input req = {0}; + struct hwrm_cfa_l2_filter_alloc_output *resp = bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_L2_FILTER_ALLOC, -1, -1); + req.flags = cpu_to_le32(CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH_RX | + CFA_L2_FILTER_ALLOC_REQ_FLAGS_OUTERMOST); + req.dst_vnic_id = cpu_to_le16(bp->vnic_info[vnic_id].fw_vnic_id); + req.enables = + cpu_to_le32(CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_ADDR | + CFA_L2_FILTER_ALLOC_REQ_ENABLES_DST_VNIC_ID | + CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_ADDR_MASK); + memcpy(req.l2_addr, mac_addr, ETH_ALEN); + req.l2_addr_mask[0] = 0xff; + req.l2_addr_mask[1] = 0xff; + req.l2_addr_mask[2] = 0xff; + req.l2_addr_mask[3] = 0xff; + req.l2_addr_mask[4] = 0xff; + req.l2_addr_mask[5] = 0xff; + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (!rc) + bp->vnic_info[vnic_id].fw_l2_filter_id[idx] = + resp->l2_filter_id; + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_hwrm_clear_vnic_filter(struct bnxt *bp) +{ + u16 i, j, num_of_vnics = 1; /* only vnic 0 supported */ + int rc = 0; + + /* Any associated ntuple filters will also be cleared by firmware. */ + mutex_lock(&bp->hwrm_cmd_lock); + for (i = 0; i < num_of_vnics; i++) { + struct bnxt_vnic_info *vnic = &bp->vnic_info[i]; + + for (j = 0; j < vnic->uc_filter_count; j++) { + struct hwrm_cfa_l2_filter_free_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, + HWRM_CFA_L2_FILTER_FREE, -1, -1); + + req.l2_filter_id = vnic->fw_l2_filter_id[j]; + + rc = _hwrm_send_message(bp, &req, sizeof(req), + HWRM_CMD_TIMEOUT); + } + vnic->uc_filter_count = 0; + } + mutex_unlock(&bp->hwrm_cmd_lock); + + return rc; +} + +static int bnxt_hwrm_vnic_set_tpa(struct bnxt *bp, u16 vnic_id, u32 tpa_flags) +{ + struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id]; + struct hwrm_vnic_tpa_cfg_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_TPA_CFG, -1, -1); + + if (tpa_flags) { + u16 mss = bp->dev->mtu - 40; + u32 nsegs, n, segs = 0, flags; + + flags = VNIC_TPA_CFG_REQ_FLAGS_TPA | + VNIC_TPA_CFG_REQ_FLAGS_ENCAP_TPA | + VNIC_TPA_CFG_REQ_FLAGS_RSC_WND_UPDATE | + VNIC_TPA_CFG_REQ_FLAGS_AGG_WITH_ECN | + VNIC_TPA_CFG_REQ_FLAGS_AGG_WITH_SAME_GRE_SEQ; + if (tpa_flags & BNXT_FLAG_GRO) + flags |= VNIC_TPA_CFG_REQ_FLAGS_GRO; + + req.flags = cpu_to_le32(flags); + + req.enables = + cpu_to_le32(VNIC_TPA_CFG_REQ_ENABLES_MAX_AGG_SEGS | + VNIC_TPA_CFG_REQ_ENABLES_MAX_AGGS); + + /* Number of segs are log2 units, and first packet is not + * included as part of this units. + */ + if (mss <= PAGE_SIZE) { + n = PAGE_SIZE / mss; + nsegs = (MAX_SKB_FRAGS - 1) * n; + } else { + n = mss / PAGE_SIZE; + if (mss & (PAGE_SIZE - 1)) + n++; + nsegs = (MAX_SKB_FRAGS - n) / n; + } + + segs = ilog2(nsegs); + req.max_agg_segs = cpu_to_le16(segs); + req.max_aggs = cpu_to_le16(VNIC_TPA_CFG_REQ_MAX_AGGS_MAX); + } + req.vnic_id = cpu_to_le16(vnic->fw_vnic_id); + + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + +static int bnxt_hwrm_vnic_set_rss(struct bnxt *bp, u16 vnic_id, bool set_rss) +{ + u32 i, j, max_rings; + struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id]; + struct hwrm_vnic_rss_cfg_input req = {0}; + + if (vnic->fw_rss_cos_lb_ctx == INVALID_HW_RING_ID) + return 0; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_RSS_CFG, -1, -1); + if (set_rss) { + vnic->hash_type = BNXT_RSS_HASH_TYPE_FLAG_IPV4 | + BNXT_RSS_HASH_TYPE_FLAG_TCP_IPV4 | + BNXT_RSS_HASH_TYPE_FLAG_IPV6 | + BNXT_RSS_HASH_TYPE_FLAG_TCP_IPV6; + + req.hash_type = cpu_to_le32(vnic->hash_type); + + if (vnic->flags & BNXT_VNIC_RSS_FLAG) + max_rings = bp->rx_nr_rings; + else + max_rings = 1; + + /* Fill the RSS indirection table with ring group ids */ + for (i = 0, j = 0; i < HW_HASH_INDEX_SIZE; i++, j++) { + if (j == max_rings) + j = 0; + vnic->rss_table[i] = cpu_to_le16(vnic->fw_grp_ids[j]); + } + + req.ring_grp_tbl_addr = cpu_to_le64(vnic->rss_table_dma_addr); + req.hash_key_tbl_addr = + cpu_to_le64(vnic->rss_hash_key_dma_addr); + } + req.rss_ctx_idx = cpu_to_le16(vnic->fw_rss_cos_lb_ctx); + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + +static int bnxt_hwrm_vnic_set_hds(struct bnxt *bp, u16 vnic_id) +{ + struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id]; + struct hwrm_vnic_plcmodes_cfg_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_PLCMODES_CFG, -1, -1); + req.flags = cpu_to_le32(VNIC_PLCMODES_CFG_REQ_FLAGS_JUMBO_PLACEMENT | + VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV4 | + VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV6); + req.enables = + cpu_to_le32(VNIC_PLCMODES_CFG_REQ_ENABLES_JUMBO_THRESH_VALID | + VNIC_PLCMODES_CFG_REQ_ENABLES_HDS_THRESHOLD_VALID); + /* thresholds not implemented in firmware yet */ + req.jumbo_thresh = cpu_to_le16(bp->rx_copy_thresh); + req.hds_threshold = cpu_to_le16(bp->rx_copy_thresh); + req.vnic_id = cpu_to_le32(vnic->fw_vnic_id); + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + +static void bnxt_hwrm_vnic_ctx_free_one(struct bnxt *bp, u16 vnic_id) +{ + struct hwrm_vnic_rss_cos_lb_ctx_free_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_RSS_COS_LB_CTX_FREE, -1, -1); + req.rss_cos_lb_ctx_id = + cpu_to_le16(bp->vnic_info[vnic_id].fw_rss_cos_lb_ctx); + + hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + bp->vnic_info[vnic_id].fw_rss_cos_lb_ctx = INVALID_HW_RING_ID; +} + +static void bnxt_hwrm_vnic_ctx_free(struct bnxt *bp) +{ + int i; + + for (i = 0; i < bp->nr_vnics; i++) { + struct bnxt_vnic_info *vnic = &bp->vnic_info[i]; + + if (vnic->fw_rss_cos_lb_ctx != INVALID_HW_RING_ID) + bnxt_hwrm_vnic_ctx_free_one(bp, i); + } + bp->rsscos_nr_ctxs = 0; +} + +static int bnxt_hwrm_vnic_ctx_alloc(struct bnxt *bp, u16 vnic_id) +{ + int rc; + struct hwrm_vnic_rss_cos_lb_ctx_alloc_input req = {0}; + struct hwrm_vnic_rss_cos_lb_ctx_alloc_output *resp = + bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_RSS_COS_LB_CTX_ALLOC, -1, + -1); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (!rc) + bp->vnic_info[vnic_id].fw_rss_cos_lb_ctx = + le16_to_cpu(resp->rss_cos_lb_ctx_id); + mutex_unlock(&bp->hwrm_cmd_lock); + + return rc; +} + +static int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id) +{ + int grp_idx = 0; + struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id]; + struct hwrm_vnic_cfg_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_CFG, -1, -1); + /* Only RSS support for now TBD: COS & LB */ + req.enables = cpu_to_le32(VNIC_CFG_REQ_ENABLES_DFLT_RING_GRP | + VNIC_CFG_REQ_ENABLES_RSS_RULE); + req.rss_rule = cpu_to_le16(vnic->fw_rss_cos_lb_ctx); + req.cos_rule = cpu_to_le16(0xffff); + if (vnic->flags & BNXT_VNIC_RSS_FLAG) + grp_idx = 0; + else if (vnic->flags & BNXT_VNIC_RFS_FLAG) + grp_idx = vnic_id - 1; + + req.vnic_id = cpu_to_le16(vnic->fw_vnic_id); + req.dflt_ring_grp = cpu_to_le16(bp->grp_info[grp_idx].fw_grp_id); + + req.lb_rule = cpu_to_le16(0xffff); + req.mru = cpu_to_le16(bp->dev->mtu + ETH_HLEN + ETH_FCS_LEN + + VLAN_HLEN); + + if (bp->flags & BNXT_FLAG_STRIP_VLAN) + req.flags |= cpu_to_le32(VNIC_CFG_REQ_FLAGS_VLAN_STRIP_MODE); + + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + +static int bnxt_hwrm_vnic_free_one(struct bnxt *bp, u16 vnic_id) +{ + u32 rc = 0; + + if (bp->vnic_info[vnic_id].fw_vnic_id != INVALID_HW_RING_ID) { + struct hwrm_vnic_free_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_FREE, -1, -1); + req.vnic_id = + cpu_to_le32(bp->vnic_info[vnic_id].fw_vnic_id); + + rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc) + return rc; + bp->vnic_info[vnic_id].fw_vnic_id = INVALID_HW_RING_ID; + } + return rc; +} + +static void bnxt_hwrm_vnic_free(struct bnxt *bp) +{ + u16 i; + + for (i = 0; i < bp->nr_vnics; i++) + bnxt_hwrm_vnic_free_one(bp, i); +} + +static int bnxt_hwrm_vnic_alloc(struct bnxt *bp, u16 vnic_id, u16 start_grp_id, + u16 end_grp_id) +{ + u32 rc = 0, i, j; + struct hwrm_vnic_alloc_input req = {0}; + struct hwrm_vnic_alloc_output *resp = bp->hwrm_cmd_resp_addr; + + /* map ring groups to this vnic */ + for (i = start_grp_id, j = 0; i < end_grp_id; i++, j++) { + if (bp->grp_info[i].fw_grp_id == INVALID_HW_RING_ID) { + netdev_err(bp->dev, "Not enough ring groups avail:%x req:%x\n", + j, (end_grp_id - start_grp_id)); + break; + } + bp->vnic_info[vnic_id].fw_grp_ids[j] = + bp->grp_info[i].fw_grp_id; + } + + bp->vnic_info[vnic_id].fw_rss_cos_lb_ctx = INVALID_HW_RING_ID; + if (vnic_id == 0) + req.flags = cpu_to_le32(VNIC_ALLOC_REQ_FLAGS_DEFAULT); + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_ALLOC, -1, -1); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (!rc) + bp->vnic_info[vnic_id].fw_vnic_id = le32_to_cpu(resp->vnic_id); + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_hwrm_ring_grp_alloc(struct bnxt *bp) +{ + u16 i; + u32 rc = 0; + + mutex_lock(&bp->hwrm_cmd_lock); + for (i = 0; i < bp->rx_nr_rings; i++) { + struct hwrm_ring_grp_alloc_input req = {0}; + struct hwrm_ring_grp_alloc_output *resp = + bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_GRP_ALLOC, -1, -1); + + req.cr = cpu_to_le16(bp->grp_info[i].cp_fw_ring_id); + req.rr = cpu_to_le16(bp->grp_info[i].rx_fw_ring_id); + req.ar = cpu_to_le16(bp->grp_info[i].agg_fw_ring_id); + req.sc = cpu_to_le16(bp->grp_info[i].fw_stats_ctx); + + rc = _hwrm_send_message(bp, &req, sizeof(req), + HWRM_CMD_TIMEOUT); + if (rc) + break; + + bp->grp_info[i].fw_grp_id = le32_to_cpu(resp->ring_group_id); + } + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_hwrm_ring_grp_free(struct bnxt *bp) +{ + u16 i; + u32 rc = 0; + struct hwrm_ring_grp_free_input req = {0}; + + if (!bp->grp_info) + return 0; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_GRP_FREE, -1, -1); + + mutex_lock(&bp->hwrm_cmd_lock); + for (i = 0; i < bp->cp_nr_rings; i++) { + if (bp->grp_info[i].fw_grp_id == INVALID_HW_RING_ID) + continue; + req.ring_group_id = + cpu_to_le32(bp->grp_info[i].fw_grp_id); + + rc = _hwrm_send_message(bp, &req, sizeof(req), + HWRM_CMD_TIMEOUT); + if (rc) + break; + bp->grp_info[i].fw_grp_id = INVALID_HW_RING_ID; + } + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int hwrm_ring_alloc_send_msg(struct bnxt *bp, + struct bnxt_ring_struct *ring, + u32 ring_type, u32 map_index, + u32 stats_ctx_id) +{ + int rc = 0, err = 0; + struct hwrm_ring_alloc_input req = {0}; + struct hwrm_ring_alloc_output *resp = bp->hwrm_cmd_resp_addr; + u16 ring_id; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_ALLOC, -1, -1); + + req.enables = 0; + if (ring->nr_pages > 1) { + req.page_tbl_addr = cpu_to_le64(ring->pg_tbl_map); + /* Page size is in log2 units */ + req.page_size = BNXT_PAGE_SHIFT; + req.page_tbl_depth = 1; + } else { + req.page_tbl_addr = cpu_to_le64(ring->dma_arr[0]); + } + req.fbo = 0; + /* Association of ring index with doorbell index and MSIX number */ + req.logical_id = cpu_to_le16(map_index); + + switch (ring_type) { + case HWRM_RING_ALLOC_TX: + req.ring_type = RING_ALLOC_REQ_RING_TYPE_TX; + /* Association of transmit ring with completion ring */ + req.cmpl_ring_id = + cpu_to_le16(bp->grp_info[map_index].cp_fw_ring_id); + req.length = cpu_to_le32(bp->tx_ring_mask + 1); + req.stat_ctx_id = cpu_to_le32(stats_ctx_id); + req.queue_id = cpu_to_le16(ring->queue_id); + break; + case HWRM_RING_ALLOC_RX: + req.ring_type = RING_ALLOC_REQ_RING_TYPE_RX; + req.length = cpu_to_le32(bp->rx_ring_mask + 1); + break; + case HWRM_RING_ALLOC_AGG: + req.ring_type = RING_ALLOC_REQ_RING_TYPE_RX; + req.length = cpu_to_le32(bp->rx_agg_ring_mask + 1); + break; + case HWRM_RING_ALLOC_CMPL: + req.ring_type = RING_ALLOC_REQ_RING_TYPE_CMPL; + req.length = cpu_to_le32(bp->cp_ring_mask + 1); + if (bp->flags & BNXT_FLAG_USING_MSIX) + req.int_mode = RING_ALLOC_REQ_INT_MODE_MSIX; + break; + default: + netdev_err(bp->dev, "hwrm alloc invalid ring type %d\n", + ring_type); + return -1; + } + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + err = le16_to_cpu(resp->error_code); + ring_id = le16_to_cpu(resp->ring_id); + mutex_unlock(&bp->hwrm_cmd_lock); + + if (rc || err) { + switch (ring_type) { + case RING_FREE_REQ_RING_TYPE_CMPL: + netdev_err(bp->dev, "hwrm_ring_alloc cp failed. rc:%x err:%x\n", + rc, err); + return -1; + + case RING_FREE_REQ_RING_TYPE_RX: + netdev_err(bp->dev, "hwrm_ring_alloc rx failed. rc:%x err:%x\n", + rc, err); + return -1; + + case RING_FREE_REQ_RING_TYPE_TX: + netdev_err(bp->dev, "hwrm_ring_alloc tx failed. rc:%x err:%x\n", + rc, err); + return -1; + + default: + netdev_err(bp->dev, "Invalid ring\n"); + return -1; + } + } + ring->fw_ring_id = ring_id; + return rc; +} + +static int bnxt_hwrm_ring_alloc(struct bnxt *bp) +{ + int i, rc = 0; + + if (bp->cp_nr_rings) { + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + struct bnxt_ring_struct *ring = &cpr->cp_ring_struct; + + rc = hwrm_ring_alloc_send_msg(bp, ring, + HWRM_RING_ALLOC_CMPL, i, + INVALID_STATS_CTX_ID); + if (rc) + goto err_out; + cpr->cp_doorbell = bp->bar1 + i * 0x80; + BNXT_CP_DB(cpr->cp_doorbell, cpr->cp_raw_cons); + bp->grp_info[i].cp_fw_ring_id = ring->fw_ring_id; + } + } + + if (bp->tx_nr_rings) { + for (i = 0; i < bp->tx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_tx_ring_info *txr = &bnapi->tx_ring; + struct bnxt_ring_struct *ring = &txr->tx_ring_struct; + u16 fw_stats_ctx = bp->grp_info[i].fw_stats_ctx; + + rc = hwrm_ring_alloc_send_msg(bp, ring, + HWRM_RING_ALLOC_TX, i, + fw_stats_ctx); + if (rc) + goto err_out; + txr->tx_doorbell = bp->bar1 + i * 0x80; + } + } + + if (bp->rx_nr_rings) { + for (i = 0; i < bp->rx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring; + struct bnxt_ring_struct *ring = &rxr->rx_ring_struct; + + rc = hwrm_ring_alloc_send_msg(bp, ring, + HWRM_RING_ALLOC_RX, i, + INVALID_STATS_CTX_ID); + if (rc) + goto err_out; + rxr->rx_doorbell = bp->bar1 + i * 0x80; + writel(DB_KEY_RX | rxr->rx_prod, rxr->rx_doorbell); + bp->grp_info[i].rx_fw_ring_id = ring->fw_ring_id; + } + } + + if (bp->flags & BNXT_FLAG_AGG_RINGS) { + for (i = 0; i < bp->rx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring; + struct bnxt_ring_struct *ring = + &rxr->rx_agg_ring_struct; + + rc = hwrm_ring_alloc_send_msg(bp, ring, + HWRM_RING_ALLOC_AGG, + bp->rx_nr_rings + i, + INVALID_STATS_CTX_ID); + if (rc) + goto err_out; + + rxr->rx_agg_doorbell = + bp->bar1 + (bp->rx_nr_rings + i) * 0x80; + writel(DB_KEY_RX | rxr->rx_agg_prod, + rxr->rx_agg_doorbell); + bp->grp_info[i].agg_fw_ring_id = ring->fw_ring_id; + } + } +err_out: + return rc; +} + +static int hwrm_ring_free_send_msg(struct bnxt *bp, + struct bnxt_ring_struct *ring, + u32 ring_type, int cmpl_ring_id) +{ + int rc; + struct hwrm_ring_free_input req = {0}; + struct hwrm_ring_free_output *resp = bp->hwrm_cmd_resp_addr; + u16 error_code; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_FREE, -1, -1); + req.ring_type = ring_type; + req.ring_id = cpu_to_le16(ring->fw_ring_id); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + error_code = le16_to_cpu(resp->error_code); + mutex_unlock(&bp->hwrm_cmd_lock); + + if (rc || error_code) { + switch (ring_type) { + case RING_FREE_REQ_RING_TYPE_CMPL: + netdev_err(bp->dev, "hwrm_ring_free cp failed. rc:%d\n", + rc); + return rc; + case RING_FREE_REQ_RING_TYPE_RX: + netdev_err(bp->dev, "hwrm_ring_free rx failed. rc:%d\n", + rc); + return rc; + case RING_FREE_REQ_RING_TYPE_TX: + netdev_err(bp->dev, "hwrm_ring_free tx failed. rc:%d\n", + rc); + return rc; + default: + netdev_err(bp->dev, "Invalid ring\n"); + return -1; + } + } + return 0; +} + +static int bnxt_hwrm_ring_free(struct bnxt *bp, bool close_path) +{ + int i, rc = 0; + + if (!bp->bnapi) + return 0; + + if (bp->tx_nr_rings) { + for (i = 0; i < bp->tx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_tx_ring_info *txr = &bnapi->tx_ring; + struct bnxt_ring_struct *ring = &txr->tx_ring_struct; + u32 cmpl_ring_id = bp->grp_info[i].cp_fw_ring_id; + + if (ring->fw_ring_id != INVALID_HW_RING_ID) { + hwrm_ring_free_send_msg( + bp, ring, + RING_FREE_REQ_RING_TYPE_TX, + close_path ? cmpl_ring_id : + INVALID_HW_RING_ID); + ring->fw_ring_id = INVALID_HW_RING_ID; + } + } + } + + if (bp->rx_nr_rings) { + for (i = 0; i < bp->rx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring; + struct bnxt_ring_struct *ring = &rxr->rx_ring_struct; + u32 cmpl_ring_id = bp->grp_info[i].cp_fw_ring_id; + + if (ring->fw_ring_id != INVALID_HW_RING_ID) { + hwrm_ring_free_send_msg( + bp, ring, + RING_FREE_REQ_RING_TYPE_RX, + close_path ? cmpl_ring_id : + INVALID_HW_RING_ID); + ring->fw_ring_id = INVALID_HW_RING_ID; + bp->grp_info[i].rx_fw_ring_id = + INVALID_HW_RING_ID; + } + } + } + + if (bp->rx_agg_nr_pages) { + for (i = 0; i < bp->rx_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_rx_ring_info *rxr = &bnapi->rx_ring; + struct bnxt_ring_struct *ring = + &rxr->rx_agg_ring_struct; + u32 cmpl_ring_id = bp->grp_info[i].cp_fw_ring_id; + + if (ring->fw_ring_id != INVALID_HW_RING_ID) { + hwrm_ring_free_send_msg( + bp, ring, + RING_FREE_REQ_RING_TYPE_RX, + close_path ? cmpl_ring_id : + INVALID_HW_RING_ID); + ring->fw_ring_id = INVALID_HW_RING_ID; + bp->grp_info[i].agg_fw_ring_id = + INVALID_HW_RING_ID; + } + } + } + + if (bp->cp_nr_rings) { + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + struct bnxt_ring_struct *ring = &cpr->cp_ring_struct; + + if (ring->fw_ring_id != INVALID_HW_RING_ID) { + hwrm_ring_free_send_msg( + bp, ring, + RING_FREE_REQ_RING_TYPE_CMPL, + INVALID_HW_RING_ID); + ring->fw_ring_id = INVALID_HW_RING_ID; + bp->grp_info[i].cp_fw_ring_id = + INVALID_HW_RING_ID; + } + } + } + + return rc; +} + +int bnxt_hwrm_set_coal(struct bnxt *bp) +{ + int i, rc = 0; + struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req = {0}; + u16 max_buf, max_buf_irq; + u16 buf_tmr, buf_tmr_irq; + u32 flags; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS, + -1, -1); + + /* Each rx completion (2 records) should be DMAed immediately */ + max_buf = min_t(u16, bp->coal_bufs / 4, 2); + /* max_buf must not be zero */ + max_buf = clamp_t(u16, max_buf, 1, 63); + max_buf_irq = clamp_t(u16, bp->coal_bufs_irq, 1, 63); + buf_tmr = max_t(u16, bp->coal_ticks / 4, 1); + buf_tmr_irq = max_t(u16, bp->coal_ticks_irq, 1); + + flags = RING_CMPL_RING_CFG_AGGINT_PARAMS_REQ_FLAGS_TIMER_RESET; + + /* RING_IDLE generates more IRQs for lower latency. Enable it only + * if coal_ticks is less than 25 us. + */ + if (BNXT_COAL_TIMER_TO_USEC(bp->coal_ticks) < 25) + flags |= RING_CMPL_RING_CFG_AGGINT_PARAMS_REQ_FLAGS_RING_IDLE; + + req.flags = cpu_to_le16(flags); + req.num_cmpl_dma_aggr = cpu_to_le16(max_buf); + req.num_cmpl_dma_aggr_during_int = cpu_to_le16(max_buf_irq); + req.cmpl_aggr_dma_tmr = cpu_to_le16(buf_tmr); + req.cmpl_aggr_dma_tmr_during_int = cpu_to_le16(buf_tmr_irq); + req.int_lat_tmr_min = cpu_to_le16(buf_tmr); + req.int_lat_tmr_max = cpu_to_le16(bp->coal_ticks); + req.num_cmpl_aggr_int = cpu_to_le16(bp->coal_bufs); + + mutex_lock(&bp->hwrm_cmd_lock); + for (i = 0; i < bp->cp_nr_rings; i++) { + req.ring_id = cpu_to_le16(bp->grp_info[i].cp_fw_ring_id); + + rc = _hwrm_send_message(bp, &req, sizeof(req), + HWRM_CMD_TIMEOUT); + if (rc) + break; + } + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_hwrm_stat_ctx_free(struct bnxt *bp) +{ + int rc = 0, i; + struct hwrm_stat_ctx_free_input req = {0}; + + if (!bp->bnapi) + return 0; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_STAT_CTX_FREE, -1, -1); + + mutex_lock(&bp->hwrm_cmd_lock); + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + + if (cpr->hw_stats_ctx_id != INVALID_STATS_CTX_ID) { + req.stat_ctx_id = cpu_to_le32(cpr->hw_stats_ctx_id); + + rc = _hwrm_send_message(bp, &req, sizeof(req), + HWRM_CMD_TIMEOUT); + if (rc) + break; + + cpr->hw_stats_ctx_id = INVALID_STATS_CTX_ID; + } + } + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_hwrm_stat_ctx_alloc(struct bnxt *bp) +{ + int rc = 0, i; + struct hwrm_stat_ctx_alloc_input req = {0}; + struct hwrm_stat_ctx_alloc_output *resp = bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_STAT_CTX_ALLOC, -1, -1); + + req.update_period_ms = cpu_to_le32(1000); + + mutex_lock(&bp->hwrm_cmd_lock); + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + + req.stats_dma_addr = cpu_to_le64(cpr->hw_stats_map); + + rc = _hwrm_send_message(bp, &req, sizeof(req), + HWRM_CMD_TIMEOUT); + if (rc) + break; + + cpr->hw_stats_ctx_id = le32_to_cpu(resp->stat_ctx_id); + + bp->grp_info[i].fw_stats_ctx = cpr->hw_stats_ctx_id; + } + mutex_unlock(&bp->hwrm_cmd_lock); + return 0; +} + +static int bnxt_hwrm_func_qcaps(struct bnxt *bp) +{ + int rc = 0; + struct hwrm_func_qcaps_input req = {0}; + struct hwrm_func_qcaps_output *resp = bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCAPS, -1, -1); + req.fid = cpu_to_le16(0xffff); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc) + goto hwrm_func_qcaps_exit; + + if (BNXT_PF(bp)) { + struct bnxt_pf_info *pf = &bp->pf; + + pf->fw_fid = le16_to_cpu(resp->fid); + pf->port_id = le16_to_cpu(resp->port_id); + memcpy(pf->mac_addr, resp->perm_mac_address, ETH_ALEN); + pf->max_rsscos_ctxs = le16_to_cpu(resp->max_rsscos_ctx); + pf->max_cp_rings = le16_to_cpu(resp->max_cmpl_rings); + pf->max_tx_rings = le16_to_cpu(resp->max_tx_rings); + pf->max_pf_tx_rings = pf->max_tx_rings; + pf->max_rx_rings = le16_to_cpu(resp->max_rx_rings); + pf->max_pf_rx_rings = pf->max_rx_rings; + pf->max_l2_ctxs = le16_to_cpu(resp->max_l2_ctxs); + pf->max_vnics = le16_to_cpu(resp->max_vnics); + pf->max_stat_ctxs = le16_to_cpu(resp->max_stat_ctx); + pf->first_vf_id = le16_to_cpu(resp->first_vf_id); + pf->max_vfs = le16_to_cpu(resp->max_vfs); + pf->max_encap_records = le32_to_cpu(resp->max_encap_records); + pf->max_decap_records = le32_to_cpu(resp->max_decap_records); + pf->max_tx_em_flows = le32_to_cpu(resp->max_tx_em_flows); + pf->max_tx_wm_flows = le32_to_cpu(resp->max_tx_wm_flows); + pf->max_rx_em_flows = le32_to_cpu(resp->max_rx_em_flows); + pf->max_rx_wm_flows = le32_to_cpu(resp->max_rx_wm_flows); + } else { + struct bnxt_vf_info *vf = &bp->vf; + + vf->fw_fid = le16_to_cpu(resp->fid); + memcpy(vf->mac_addr, resp->perm_mac_address, ETH_ALEN); + if (!is_valid_ether_addr(vf->mac_addr)) + random_ether_addr(vf->mac_addr); + + vf->max_rsscos_ctxs = le16_to_cpu(resp->max_rsscos_ctx); + vf->max_cp_rings = le16_to_cpu(resp->max_cmpl_rings); + vf->max_tx_rings = le16_to_cpu(resp->max_tx_rings); + vf->max_rx_rings = le16_to_cpu(resp->max_rx_rings); + vf->max_l2_ctxs = le16_to_cpu(resp->max_l2_ctxs); + vf->max_vnics = le16_to_cpu(resp->max_vnics); + vf->max_stat_ctxs = le16_to_cpu(resp->max_stat_ctx); + } + + bp->tx_push_thresh = 0; + if (resp->flags & + cpu_to_le32(FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED)) + bp->tx_push_thresh = BNXT_TX_PUSH_THRESH; + +hwrm_func_qcaps_exit: + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_hwrm_func_reset(struct bnxt *bp) +{ + struct hwrm_func_reset_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_RESET, -1, -1); + req.enables = 0; + + return hwrm_send_message(bp, &req, sizeof(req), HWRM_RESET_TIMEOUT); +} + +static int bnxt_hwrm_queue_qportcfg(struct bnxt *bp) +{ + int rc = 0; + struct hwrm_queue_qportcfg_input req = {0}; + struct hwrm_queue_qportcfg_output *resp = bp->hwrm_cmd_resp_addr; + u8 i, *qptr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_QPORTCFG, -1, -1); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc) + goto qportcfg_exit; + + if (!resp->max_configurable_queues) { + rc = -EINVAL; + goto qportcfg_exit; + } + bp->max_tc = resp->max_configurable_queues; + if (bp->max_tc > BNXT_MAX_QUEUE) + bp->max_tc = BNXT_MAX_QUEUE; + + qptr = &resp->queue_id0; + for (i = 0; i < bp->max_tc; i++) { + bp->q_info[i].queue_id = *qptr++; + bp->q_info[i].queue_profile = *qptr++; + } + +qportcfg_exit: + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_hwrm_ver_get(struct bnxt *bp) +{ + int rc; + struct hwrm_ver_get_input req = {0}; + struct hwrm_ver_get_output *resp = bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VER_GET, -1, -1); + req.hwrm_intf_maj = HWRM_VERSION_MAJOR; + req.hwrm_intf_min = HWRM_VERSION_MINOR; + req.hwrm_intf_upd = HWRM_VERSION_UPDATE; + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc) + goto hwrm_ver_get_exit; + + memcpy(&bp->ver_resp, resp, sizeof(struct hwrm_ver_get_output)); + + if (req.hwrm_intf_maj != resp->hwrm_intf_maj || + req.hwrm_intf_min != resp->hwrm_intf_min || + req.hwrm_intf_upd != resp->hwrm_intf_upd) { + netdev_warn(bp->dev, "HWRM interface %d.%d.%d does not match driver interface %d.%d.%d.\n", + resp->hwrm_intf_maj, resp->hwrm_intf_min, + resp->hwrm_intf_upd, req.hwrm_intf_maj, + req.hwrm_intf_min, req.hwrm_intf_upd); + netdev_warn(bp->dev, "Please update driver or firmware with matching interface versions.\n"); + } + snprintf(bp->fw_ver_str, BC_HWRM_STR_LEN, "bc %d.%d.%d rm %d.%d.%d", + resp->hwrm_fw_maj, resp->hwrm_fw_min, resp->hwrm_fw_bld, + resp->hwrm_intf_maj, resp->hwrm_intf_min, resp->hwrm_intf_upd); + +hwrm_ver_get_exit: + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static void bnxt_hwrm_free_tunnel_ports(struct bnxt *bp) +{ + if (bp->vxlan_port_cnt) { + bnxt_hwrm_tunnel_dst_port_free( + bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN); + } + bp->vxlan_port_cnt = 0; + if (bp->nge_port_cnt) { + bnxt_hwrm_tunnel_dst_port_free( + bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE); + } + bp->nge_port_cnt = 0; +} + +static int bnxt_set_tpa(struct bnxt *bp, bool set_tpa) +{ + int rc, i; + u32 tpa_flags = 0; + + if (set_tpa) + tpa_flags = bp->flags & BNXT_FLAG_TPA; + for (i = 0; i < bp->nr_vnics; i++) { + rc = bnxt_hwrm_vnic_set_tpa(bp, i, tpa_flags); + if (rc) { + netdev_err(bp->dev, "hwrm vnic set tpa failure rc for vnic %d: %x\n", + rc, i); + return rc; + } + } + return 0; +} + +static void bnxt_hwrm_clear_vnic_rss(struct bnxt *bp) +{ + int i; + + for (i = 0; i < bp->nr_vnics; i++) + bnxt_hwrm_vnic_set_rss(bp, i, false); +} + +static void bnxt_hwrm_resource_free(struct bnxt *bp, bool close_path, + bool irq_re_init) +{ + if (bp->vnic_info) { + bnxt_hwrm_clear_vnic_filter(bp); + /* clear all RSS setting before free vnic ctx */ + bnxt_hwrm_clear_vnic_rss(bp); + bnxt_hwrm_vnic_ctx_free(bp); + /* before free the vnic, undo the vnic tpa settings */ + if (bp->flags & BNXT_FLAG_TPA) + bnxt_set_tpa(bp, false); + bnxt_hwrm_vnic_free(bp); + } + bnxt_hwrm_ring_free(bp, close_path); + bnxt_hwrm_ring_grp_free(bp); + if (irq_re_init) { + bnxt_hwrm_stat_ctx_free(bp); + bnxt_hwrm_free_tunnel_ports(bp); + } +} + +static int bnxt_setup_vnic(struct bnxt *bp, u16 vnic_id) +{ + int rc; + + /* allocate context for vnic */ + rc = bnxt_hwrm_vnic_ctx_alloc(bp, vnic_id); + if (rc) { + netdev_err(bp->dev, "hwrm vnic %d alloc failure rc: %x\n", + vnic_id, rc); + goto vnic_setup_err; + } + bp->rsscos_nr_ctxs++; + + /* configure default vnic, ring grp */ + rc = bnxt_hwrm_vnic_cfg(bp, vnic_id); + if (rc) { + netdev_err(bp->dev, "hwrm vnic %d cfg failure rc: %x\n", + vnic_id, rc); + goto vnic_setup_err; + } + + /* Enable RSS hashing on vnic */ + rc = bnxt_hwrm_vnic_set_rss(bp, vnic_id, true); + if (rc) { + netdev_err(bp->dev, "hwrm vnic %d set rss failure rc: %x\n", + vnic_id, rc); + goto vnic_setup_err; + } + + if (bp->flags & BNXT_FLAG_AGG_RINGS) { + rc = bnxt_hwrm_vnic_set_hds(bp, vnic_id); + if (rc) { + netdev_err(bp->dev, "hwrm vnic %d set hds failure rc: %x\n", + vnic_id, rc); + } + } + +vnic_setup_err: + return rc; +} + +static int bnxt_alloc_rfs_vnics(struct bnxt *bp) +{ +#ifdef CONFIG_RFS_ACCEL + int i, rc = 0; + + for (i = 0; i < bp->rx_nr_rings; i++) { + u16 vnic_id = i + 1; + u16 ring_id = i; + + if (vnic_id >= bp->nr_vnics) + break; + + bp->vnic_info[vnic_id].flags |= BNXT_VNIC_RFS_FLAG; + rc = bnxt_hwrm_vnic_alloc(bp, vnic_id, ring_id, ring_id + 1); + if (rc) { + netdev_err(bp->dev, "hwrm vnic %d alloc failure rc: %x\n", + vnic_id, rc); + break; + } + rc = bnxt_setup_vnic(bp, vnic_id); + if (rc) + break; + } + return rc; +#else + return 0; +#endif +} + +static void bnxt_update_vf_mac(struct bnxt *bp) +{ + struct hwrm_func_qcaps_input req = {0}; + struct hwrm_func_qcaps_output *resp = bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCAPS, -1, -1); + req.fid = cpu_to_le16(0xffff); + + mutex_lock(&bp->hwrm_cmd_lock); + if (_hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT)) + goto update_vf_mac_exit; + + if (!is_valid_ether_addr(resp->perm_mac_address)) + goto update_vf_mac_exit; + + if (ether_addr_equal(resp->perm_mac_address, bp->vf.mac_addr)) + goto update_vf_mac_exit; + + memcpy(bp->vf.mac_addr, resp->perm_mac_address, ETH_ALEN); + memcpy(bp->dev->dev_addr, bp->vf.mac_addr, ETH_ALEN); +update_vf_mac_exit: + mutex_unlock(&bp->hwrm_cmd_lock); +} + +static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init) +{ + int rc = 0; + + if (irq_re_init) { + rc = bnxt_hwrm_stat_ctx_alloc(bp); + if (rc) { + netdev_err(bp->dev, "hwrm stat ctx alloc failure rc: %x\n", + rc); + goto err_out; + } + } + + rc = bnxt_hwrm_ring_alloc(bp); + if (rc) { + netdev_err(bp->dev, "hwrm ring alloc failure rc: %x\n", rc); + goto err_out; + } + + rc = bnxt_hwrm_ring_grp_alloc(bp); + if (rc) { + netdev_err(bp->dev, "hwrm_ring_grp alloc failure: %x\n", rc); + goto err_out; + } + + /* default vnic 0 */ + rc = bnxt_hwrm_vnic_alloc(bp, 0, 0, bp->rx_nr_rings); + if (rc) { + netdev_err(bp->dev, "hwrm vnic alloc failure rc: %x\n", rc); + goto err_out; + } + + rc = bnxt_setup_vnic(bp, 0); + if (rc) + goto err_out; + + if (bp->flags & BNXT_FLAG_RFS) { + rc = bnxt_alloc_rfs_vnics(bp); + if (rc) + goto err_out; + } + + if (bp->flags & BNXT_FLAG_TPA) { + rc = bnxt_set_tpa(bp, true); + if (rc) + goto err_out; + } + + if (BNXT_VF(bp)) + bnxt_update_vf_mac(bp); + + /* Filter for default vnic 0 */ + rc = bnxt_hwrm_set_vnic_filter(bp, 0, 0, bp->dev->dev_addr); + if (rc) { + netdev_err(bp->dev, "HWRM vnic filter failure rc: %x\n", rc); + goto err_out; + } + bp->vnic_info[0].uc_filter_count = 1; + + bp->vnic_info[0].rx_mask = CFA_L2_SET_RX_MASK_REQ_MASK_UNICAST | + CFA_L2_SET_RX_MASK_REQ_MASK_BCAST; + + if ((bp->dev->flags & IFF_PROMISC) && BNXT_PF(bp)) + bp->vnic_info[0].rx_mask |= + CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; + + rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0); + if (rc) { + netdev_err(bp->dev, "HWRM cfa l2 rx mask failure rc: %x\n", rc); + goto err_out; + } + + rc = bnxt_hwrm_set_coal(bp); + if (rc) + netdev_warn(bp->dev, "HWRM set coalescing failure rc: %x\n", + rc); + + return 0; + +err_out: + bnxt_hwrm_resource_free(bp, 0, true); + + return rc; +} + +static int bnxt_shutdown_nic(struct bnxt *bp, bool irq_re_init) +{ + bnxt_hwrm_resource_free(bp, 1, irq_re_init); + return 0; +} + +static int bnxt_init_nic(struct bnxt *bp, bool irq_re_init) +{ + bnxt_init_rx_rings(bp); + bnxt_init_tx_rings(bp); + bnxt_init_ring_grps(bp, irq_re_init); + bnxt_init_vnics(bp); + + return bnxt_init_chip(bp, irq_re_init); +} + +static void bnxt_disable_int(struct bnxt *bp) +{ + int i; + + if (!bp->bnapi) + return; + + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + + BNXT_CP_DB(cpr->cp_doorbell, cpr->cp_raw_cons); + } +} + +static void bnxt_enable_int(struct bnxt *bp) +{ + int i; + + atomic_set(&bp->intr_sem, 0); + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + + BNXT_CP_DB_REARM(cpr->cp_doorbell, cpr->cp_raw_cons); + } +} + +static int bnxt_set_real_num_queues(struct bnxt *bp) +{ + int rc; + struct net_device *dev = bp->dev; + + rc = netif_set_real_num_tx_queues(dev, bp->tx_nr_rings); + if (rc) + return rc; + + rc = netif_set_real_num_rx_queues(dev, bp->rx_nr_rings); + if (rc) + return rc; + +#ifdef CONFIG_RFS_ACCEL + if (bp->rx_nr_rings) + dev->rx_cpu_rmap = alloc_irq_cpu_rmap(bp->rx_nr_rings); + if (!dev->rx_cpu_rmap) + rc = -ENOMEM; +#endif + + return rc; +} + +static int bnxt_setup_msix(struct bnxt *bp) +{ + struct msix_entry *msix_ent; + struct net_device *dev = bp->dev; + int i, total_vecs, rc = 0; + const int len = sizeof(bp->irq_tbl[0].name); + + bp->flags &= ~BNXT_FLAG_USING_MSIX; + total_vecs = bp->cp_nr_rings; + + msix_ent = kcalloc(total_vecs, sizeof(struct msix_entry), GFP_KERNEL); + if (!msix_ent) + return -ENOMEM; + + for (i = 0; i < total_vecs; i++) { + msix_ent[i].entry = i; + msix_ent[i].vector = 0; + } + + total_vecs = pci_enable_msix_range(bp->pdev, msix_ent, 1, total_vecs); + if (total_vecs < 0) { + rc = -ENODEV; + goto msix_setup_exit; + } + + bp->irq_tbl = kcalloc(total_vecs, sizeof(struct bnxt_irq), GFP_KERNEL); + if (bp->irq_tbl) { + int tcs; + + /* Trim rings based upon num of vectors allocated */ + bp->rx_nr_rings = min_t(int, total_vecs, bp->rx_nr_rings); + bp->tx_nr_rings = min_t(int, total_vecs, bp->tx_nr_rings); + bp->tx_nr_rings_per_tc = bp->tx_nr_rings; + tcs = netdev_get_num_tc(dev); + if (tcs > 1) { + bp->tx_nr_rings_per_tc = bp->tx_nr_rings / tcs; + if (bp->tx_nr_rings_per_tc == 0) { + netdev_reset_tc(dev); + bp->tx_nr_rings_per_tc = bp->tx_nr_rings; + } else { + int i, off, count; + + bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs; + for (i = 0; i < tcs; i++) { + count = bp->tx_nr_rings_per_tc; + off = i * count; + netdev_set_tc_queue(dev, i, count, off); + } + } + } + bp->cp_nr_rings = max_t(int, bp->rx_nr_rings, bp->tx_nr_rings); + + for (i = 0; i < bp->cp_nr_rings; i++) { + bp->irq_tbl[i].vector = msix_ent[i].vector; + snprintf(bp->irq_tbl[i].name, len, + "%s-%s-%d", dev->name, "TxRx", i); + bp->irq_tbl[i].handler = bnxt_msix; + } + rc = bnxt_set_real_num_queues(bp); + if (rc) + goto msix_setup_exit; + } else { + rc = -ENOMEM; + goto msix_setup_exit; + } + bp->flags |= BNXT_FLAG_USING_MSIX; + kfree(msix_ent); + return 0; + +msix_setup_exit: + netdev_err(bp->dev, "bnxt_setup_msix err: %x\n", rc); + pci_disable_msix(bp->pdev); + kfree(msix_ent); + return rc; +} + +static int bnxt_setup_inta(struct bnxt *bp) +{ + int rc; + const int len = sizeof(bp->irq_tbl[0].name); + + if (netdev_get_num_tc(bp->dev)) + netdev_reset_tc(bp->dev); + + bp->irq_tbl = kcalloc(1, sizeof(struct bnxt_irq), GFP_KERNEL); + if (!bp->irq_tbl) { + rc = -ENOMEM; + return rc; + } + bp->rx_nr_rings = 1; + bp->tx_nr_rings = 1; + bp->cp_nr_rings = 1; + bp->tx_nr_rings_per_tc = bp->tx_nr_rings; + bp->irq_tbl[0].vector = bp->pdev->irq; + snprintf(bp->irq_tbl[0].name, len, + "%s-%s-%d", bp->dev->name, "TxRx", 0); + bp->irq_tbl[0].handler = bnxt_inta; + rc = bnxt_set_real_num_queues(bp); + return rc; +} + +static int bnxt_setup_int_mode(struct bnxt *bp) +{ + int rc = 0; + + if (bp->flags & BNXT_FLAG_MSIX_CAP) + rc = bnxt_setup_msix(bp); + + if (!(bp->flags & BNXT_FLAG_USING_MSIX)) { + /* fallback to INTA */ + rc = bnxt_setup_inta(bp); + } + return rc; +} + +static void bnxt_free_irq(struct bnxt *bp) +{ + struct bnxt_irq *irq; + int i; + +#ifdef CONFIG_RFS_ACCEL + free_irq_cpu_rmap(bp->dev->rx_cpu_rmap); + bp->dev->rx_cpu_rmap = NULL; +#endif + if (!bp->irq_tbl) + return; + + for (i = 0; i < bp->cp_nr_rings; i++) { + irq = &bp->irq_tbl[i]; + if (irq->requested) + free_irq(irq->vector, bp->bnapi[i]); + irq->requested = 0; + } + if (bp->flags & BNXT_FLAG_USING_MSIX) + pci_disable_msix(bp->pdev); + kfree(bp->irq_tbl); + bp->irq_tbl = NULL; +} + +static int bnxt_request_irq(struct bnxt *bp) +{ + int i, rc = 0; + unsigned long flags = 0; +#ifdef CONFIG_RFS_ACCEL + struct cpu_rmap *rmap = bp->dev->rx_cpu_rmap; +#endif + + if (!(bp->flags & BNXT_FLAG_USING_MSIX)) + flags = IRQF_SHARED; + + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_irq *irq = &bp->irq_tbl[i]; +#ifdef CONFIG_RFS_ACCEL + if (rmap && (i < bp->rx_nr_rings)) { + rc = irq_cpu_rmap_add(rmap, irq->vector); + if (rc) + netdev_warn(bp->dev, "failed adding irq rmap for ring %d\n", + i); + } +#endif + rc = request_irq(irq->vector, irq->handler, flags, irq->name, + bp->bnapi[i]); + if (rc) + break; + + irq->requested = 1; + } + return rc; +} + +static void bnxt_del_napi(struct bnxt *bp) +{ + int i; + + if (!bp->bnapi) + return; + + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + + napi_hash_del(&bnapi->napi); + netif_napi_del(&bnapi->napi); + } +} + +static void bnxt_init_napi(struct bnxt *bp) +{ + int i; + struct bnxt_napi *bnapi; + + if (bp->flags & BNXT_FLAG_USING_MSIX) { + for (i = 0; i < bp->cp_nr_rings; i++) { + bnapi = bp->bnapi[i]; + netif_napi_add(bp->dev, &bnapi->napi, + bnxt_poll, 64); + napi_hash_add(&bnapi->napi); + } + } else { + bnapi = bp->bnapi[0]; + netif_napi_add(bp->dev, &bnapi->napi, bnxt_poll, 64); + napi_hash_add(&bnapi->napi); + } +} + +static void bnxt_disable_napi(struct bnxt *bp) +{ + int i; + + if (!bp->bnapi) + return; + + for (i = 0; i < bp->cp_nr_rings; i++) { + napi_disable(&bp->bnapi[i]->napi); + bnxt_disable_poll(bp->bnapi[i]); + } +} + +static void bnxt_enable_napi(struct bnxt *bp) +{ + int i; + + for (i = 0; i < bp->cp_nr_rings; i++) { + bnxt_enable_poll(bp->bnapi[i]); + napi_enable(&bp->bnapi[i]->napi); + } +} + +static void bnxt_tx_disable(struct bnxt *bp) +{ + int i; + struct bnxt_napi *bnapi; + struct bnxt_tx_ring_info *txr; + struct netdev_queue *txq; + + if (bp->bnapi) { + for (i = 0; i < bp->tx_nr_rings; i++) { + bnapi = bp->bnapi[i]; + txr = &bnapi->tx_ring; + txq = netdev_get_tx_queue(bp->dev, i); + __netif_tx_lock(txq, smp_processor_id()); + txr->dev_state = BNXT_DEV_STATE_CLOSING; + __netif_tx_unlock(txq); + } + } + /* Stop all TX queues */ + netif_tx_disable(bp->dev); + netif_carrier_off(bp->dev); +} + +static void bnxt_tx_enable(struct bnxt *bp) +{ + int i; + struct bnxt_napi *bnapi; + struct bnxt_tx_ring_info *txr; + struct netdev_queue *txq; + + for (i = 0; i < bp->tx_nr_rings; i++) { + bnapi = bp->bnapi[i]; + txr = &bnapi->tx_ring; + txq = netdev_get_tx_queue(bp->dev, i); + txr->dev_state = 0; + } + netif_tx_wake_all_queues(bp->dev); + if (bp->link_info.link_up) + netif_carrier_on(bp->dev); +} + +static void bnxt_report_link(struct bnxt *bp) +{ + if (bp->link_info.link_up) { + const char *duplex; + const char *flow_ctrl; + u16 speed; + + netif_carrier_on(bp->dev); + if (bp->link_info.duplex == BNXT_LINK_DUPLEX_FULL) + duplex = "full"; + else + duplex = "half"; + if (bp->link_info.pause == BNXT_LINK_PAUSE_BOTH) + flow_ctrl = "ON - receive & transmit"; + else if (bp->link_info.pause == BNXT_LINK_PAUSE_TX) + flow_ctrl = "ON - transmit"; + else if (bp->link_info.pause == BNXT_LINK_PAUSE_RX) + flow_ctrl = "ON - receive"; + else + flow_ctrl = "none"; + speed = bnxt_fw_to_ethtool_speed(bp->link_info.link_speed); + netdev_info(bp->dev, "NIC Link is Up, %d Mbps %s duplex, Flow control: %s\n", + speed, duplex, flow_ctrl); + } else { + netif_carrier_off(bp->dev); + netdev_err(bp->dev, "NIC Link is Down\n"); + } +} + +static int bnxt_update_link(struct bnxt *bp, bool chng_link_state) +{ + int rc = 0; + struct bnxt_link_info *link_info = &bp->link_info; + struct hwrm_port_phy_qcfg_input req = {0}; + struct hwrm_port_phy_qcfg_output *resp = bp->hwrm_cmd_resp_addr; + u8 link_up = link_info->link_up; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_QCFG, -1, -1); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc) { + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; + } + + memcpy(&link_info->phy_qcfg_resp, resp, sizeof(*resp)); + link_info->phy_link_status = resp->link; + link_info->duplex = resp->duplex; + link_info->pause = resp->pause; + link_info->auto_mode = resp->auto_mode; + link_info->auto_pause_setting = resp->auto_pause; + link_info->force_pause_setting = resp->force_pause; + link_info->duplex_setting = resp->duplex_setting; + if (link_info->phy_link_status == BNXT_LINK_LINK) + link_info->link_speed = le16_to_cpu(resp->link_speed); + else + link_info->link_speed = 0; + link_info->force_link_speed = le16_to_cpu(resp->force_link_speed); + link_info->auto_link_speed = le16_to_cpu(resp->auto_link_speed); + link_info->support_speeds = le16_to_cpu(resp->support_speeds); + link_info->auto_link_speeds = le16_to_cpu(resp->auto_link_speed_mask); + link_info->preemphasis = le32_to_cpu(resp->preemphasis); + link_info->phy_ver[0] = resp->phy_maj; + link_info->phy_ver[1] = resp->phy_min; + link_info->phy_ver[2] = resp->phy_bld; + link_info->media_type = resp->media_type; + link_info->transceiver = resp->transceiver_type; + link_info->phy_addr = resp->phy_addr; + + /* TODO: need to add more logic to report VF link */ + if (chng_link_state) { + if (link_info->phy_link_status == BNXT_LINK_LINK) + link_info->link_up = 1; + else + link_info->link_up = 0; + if (link_up != link_info->link_up) + bnxt_report_link(bp); + } else { + /* alwasy link down if not require to update link state */ + link_info->link_up = 0; + } + mutex_unlock(&bp->hwrm_cmd_lock); + return 0; +} + +static void +bnxt_hwrm_set_pause_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req) +{ + if (bp->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL) { + if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_RX) + req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_RX; + if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_TX) + req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_RX; + req->enables |= + cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE); + } else { + if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_RX) + req->force_pause |= PORT_PHY_CFG_REQ_FORCE_PAUSE_RX; + if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_TX) + req->force_pause |= PORT_PHY_CFG_REQ_FORCE_PAUSE_TX; + req->enables |= + cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_FORCE_PAUSE); + } +} + +static void bnxt_hwrm_set_link_common(struct bnxt *bp, + struct hwrm_port_phy_cfg_input *req) +{ + u8 autoneg = bp->link_info.autoneg; + u16 fw_link_speed = bp->link_info.req_link_speed; + u32 advertising = bp->link_info.advertising; + + if (autoneg & BNXT_AUTONEG_SPEED) { + req->auto_mode |= + PORT_PHY_CFG_REQ_AUTO_MODE_MASK; + + req->enables |= cpu_to_le32( + PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEED_MASK); + req->auto_link_speed_mask = cpu_to_le16(advertising); + + req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_MODE); + req->flags |= + cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG); + } else { + req->force_link_speed = cpu_to_le16(fw_link_speed); + req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE); + } + + /* currently don't support half duplex */ + req->auto_duplex = PORT_PHY_CFG_REQ_AUTO_DUPLEX_FULL; + req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_DUPLEX); + /* tell chimp that the setting takes effect immediately */ + req->flags |= cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_RESET_PHY); +} + +int bnxt_hwrm_set_pause(struct bnxt *bp) +{ + struct hwrm_port_phy_cfg_input req = {0}; + int rc; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_CFG, -1, -1); + bnxt_hwrm_set_pause_common(bp, &req); + + if ((bp->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL) || + bp->link_info.force_link_chng) + bnxt_hwrm_set_link_common(bp, &req); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (!rc && !(bp->link_info.autoneg & BNXT_AUTONEG_FLOW_CTRL)) { + /* since changing of pause setting doesn't trigger any link + * change event, the driver needs to update the current pause + * result upon successfully return of the phy_cfg command + */ + bp->link_info.pause = + bp->link_info.force_pause_setting = bp->link_info.req_flow_ctrl; + bp->link_info.auto_pause_setting = 0; + if (!bp->link_info.force_link_chng) + bnxt_report_link(bp); + } + bp->link_info.force_link_chng = false; + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +int bnxt_hwrm_set_link_setting(struct bnxt *bp, bool set_pause) +{ + struct hwrm_port_phy_cfg_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_CFG, -1, -1); + if (set_pause) + bnxt_hwrm_set_pause_common(bp, &req); + + bnxt_hwrm_set_link_common(bp, &req); + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + +static int bnxt_update_phy_setting(struct bnxt *bp) +{ + int rc; + bool update_link = false; + bool update_pause = false; + struct bnxt_link_info *link_info = &bp->link_info; + + rc = bnxt_update_link(bp, true); + if (rc) { + netdev_err(bp->dev, "failed to update link (rc: %x)\n", + rc); + return rc; + } + if ((link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) && + link_info->auto_pause_setting != link_info->req_flow_ctrl) + update_pause = true; + if (!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) && + link_info->force_pause_setting != link_info->req_flow_ctrl) + update_pause = true; + if (link_info->req_duplex != link_info->duplex_setting) + update_link = true; + if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) { + if (BNXT_AUTO_MODE(link_info->auto_mode)) + update_link = true; + if (link_info->req_link_speed != link_info->force_link_speed) + update_link = true; + } else { + if (link_info->auto_mode == BNXT_LINK_AUTO_NONE) + update_link = true; + if (link_info->advertising != link_info->auto_link_speeds) + update_link = true; + if (link_info->req_link_speed != link_info->auto_link_speed) + update_link = true; + } + + if (update_link) + rc = bnxt_hwrm_set_link_setting(bp, update_pause); + else if (update_pause) + rc = bnxt_hwrm_set_pause(bp); + if (rc) { + netdev_err(bp->dev, "failed to update phy setting (rc: %x)\n", + rc); + return rc; + } + + return rc; +} + +static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) +{ + int rc = 0; + + netif_carrier_off(bp->dev); + if (irq_re_init) { + rc = bnxt_setup_int_mode(bp); + if (rc) { + netdev_err(bp->dev, "bnxt_setup_int_mode err: %x\n", + rc); + return rc; + } + } + if ((bp->flags & BNXT_FLAG_RFS) && + !(bp->flags & BNXT_FLAG_USING_MSIX)) { + /* disable RFS if falling back to INTA */ + bp->dev->hw_features &= ~NETIF_F_NTUPLE; + bp->flags &= ~BNXT_FLAG_RFS; + } + + rc = bnxt_alloc_mem(bp, irq_re_init); + if (rc) { + netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc); + goto open_err_free_mem; + } + + if (irq_re_init) { + bnxt_init_napi(bp); + rc = bnxt_request_irq(bp); + if (rc) { + netdev_err(bp->dev, "bnxt_request_irq err: %x\n", rc); + goto open_err; + } + } + + bnxt_enable_napi(bp); + + rc = bnxt_init_nic(bp, irq_re_init); + if (rc) { + netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc); + goto open_err; + } + + if (link_re_init) { + rc = bnxt_update_phy_setting(bp); + if (rc) + goto open_err; + } + + if (irq_re_init) { +#if defined(CONFIG_VXLAN) || defined(CONFIG_VXLAN_MODULE) + vxlan_get_rx_port(bp->dev); +#endif + if (!bnxt_hwrm_tunnel_dst_port_alloc( + bp, htons(0x17c1), + TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE)) + bp->nge_port_cnt = 1; + } + + bp->state = BNXT_STATE_OPEN; + bnxt_enable_int(bp); + /* Enable TX queues */ + bnxt_tx_enable(bp); + mod_timer(&bp->timer, jiffies + bp->current_interval); + + return 0; + +open_err: + bnxt_disable_napi(bp); + bnxt_del_napi(bp); + +open_err_free_mem: + bnxt_free_skbs(bp); + bnxt_free_irq(bp); + bnxt_free_mem(bp, true); + return rc; +} + +/* rtnl_lock held */ +int bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) +{ + int rc = 0; + + rc = __bnxt_open_nic(bp, irq_re_init, link_re_init); + if (rc) { + netdev_err(bp->dev, "nic open fail (rc: %x)\n", rc); + dev_close(bp->dev); + } + return rc; +} + +static int bnxt_open(struct net_device *dev) +{ + struct bnxt *bp = netdev_priv(dev); + int rc = 0; + + rc = bnxt_hwrm_func_reset(bp); + if (rc) { + netdev_err(bp->dev, "hwrm chip reset failure rc: %x\n", + rc); + rc = -1; + return rc; + } + return __bnxt_open_nic(bp, true, true); +} + +static void bnxt_disable_int_sync(struct bnxt *bp) +{ + int i; + + atomic_inc(&bp->intr_sem); + if (!netif_running(bp->dev)) + return; + + bnxt_disable_int(bp); + for (i = 0; i < bp->cp_nr_rings; i++) + synchronize_irq(bp->irq_tbl[i].vector); +} + +int bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) +{ + int rc = 0; + +#ifdef CONFIG_BNXT_SRIOV + if (bp->sriov_cfg) { + rc = wait_event_interruptible_timeout(bp->sriov_cfg_wait, + !bp->sriov_cfg, + BNXT_SRIOV_CFG_WAIT_TMO); + if (rc) + netdev_warn(bp->dev, "timeout waiting for SRIOV config operation to complete!\n"); + } +#endif + /* Change device state to avoid TX queue wake up's */ + bnxt_tx_disable(bp); + + bp->state = BNXT_STATE_CLOSED; + cancel_work_sync(&bp->sp_task); + + /* Flush rings before disabling interrupts */ + bnxt_shutdown_nic(bp, irq_re_init); + + /* TODO CHIMP_FW: Link/PHY related cleanup if (link_re_init) */ + + bnxt_disable_napi(bp); + bnxt_disable_int_sync(bp); + del_timer_sync(&bp->timer); + bnxt_free_skbs(bp); + + if (irq_re_init) { + bnxt_free_irq(bp); + bnxt_del_napi(bp); + } + bnxt_free_mem(bp, irq_re_init); + return rc; +} + +static int bnxt_close(struct net_device *dev) +{ + struct bnxt *bp = netdev_priv(dev); + + bnxt_close_nic(bp, true, true); + return 0; +} + +/* rtnl_lock held */ +static int bnxt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + switch (cmd) { + case SIOCGMIIPHY: + /* fallthru */ + case SIOCGMIIREG: { + if (!netif_running(dev)) + return -EAGAIN; + + return 0; + } + + case SIOCSMIIREG: + if (!netif_running(dev)) + return -EAGAIN; + + return 0; + + default: + /* do nothing */ + break; + } + return -EOPNOTSUPP; +} + +static struct rtnl_link_stats64 * +bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) +{ + u32 i; + struct bnxt *bp = netdev_priv(dev); + + memset(stats, 0, sizeof(struct rtnl_link_stats64)); + + if (!bp->bnapi) + return stats; + + /* TODO check if we need to synchronize with bnxt_close path */ + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + struct ctx_hw_stats *hw_stats = cpr->hw_stats; + + stats->rx_packets += le64_to_cpu(hw_stats->rx_ucast_pkts); + stats->rx_packets += le64_to_cpu(hw_stats->rx_mcast_pkts); + stats->rx_packets += le64_to_cpu(hw_stats->rx_bcast_pkts); + + stats->tx_packets += le64_to_cpu(hw_stats->tx_ucast_pkts); + stats->tx_packets += le64_to_cpu(hw_stats->tx_mcast_pkts); + stats->tx_packets += le64_to_cpu(hw_stats->tx_bcast_pkts); + + stats->rx_bytes += le64_to_cpu(hw_stats->rx_ucast_bytes); + stats->rx_bytes += le64_to_cpu(hw_stats->rx_mcast_bytes); + stats->rx_bytes += le64_to_cpu(hw_stats->rx_bcast_bytes); + + stats->tx_bytes += le64_to_cpu(hw_stats->tx_ucast_bytes); + stats->tx_bytes += le64_to_cpu(hw_stats->tx_mcast_bytes); + stats->tx_bytes += le64_to_cpu(hw_stats->tx_bcast_bytes); + + stats->rx_missed_errors += + le64_to_cpu(hw_stats->rx_discard_pkts); + + stats->multicast += le64_to_cpu(hw_stats->rx_mcast_pkts); + + stats->rx_dropped += le64_to_cpu(hw_stats->rx_drop_pkts); + + stats->tx_dropped += le64_to_cpu(hw_stats->tx_drop_pkts); + } + + return stats; +} + +static bool bnxt_mc_list_updated(struct bnxt *bp, u32 *rx_mask) +{ + struct net_device *dev = bp->dev; + struct bnxt_vnic_info *vnic = &bp->vnic_info[0]; + struct netdev_hw_addr *ha; + u8 *haddr; + int mc_count = 0; + bool update = false; + int off = 0; + + netdev_for_each_mc_addr(ha, dev) { + if (mc_count >= BNXT_MAX_MC_ADDRS) { + *rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; + vnic->mc_list_count = 0; + return false; + } + haddr = ha->addr; + if (!ether_addr_equal(haddr, vnic->mc_list + off)) { + memcpy(vnic->mc_list + off, haddr, ETH_ALEN); + update = true; + } + off += ETH_ALEN; + mc_count++; + } + if (mc_count) + *rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_MCAST; + + if (mc_count != vnic->mc_list_count) { + vnic->mc_list_count = mc_count; + update = true; + } + return update; +} + +static bool bnxt_uc_list_updated(struct bnxt *bp) +{ + struct net_device *dev = bp->dev; + struct bnxt_vnic_info *vnic = &bp->vnic_info[0]; + struct netdev_hw_addr *ha; + int off = 0; + + if (netdev_uc_count(dev) != (vnic->uc_filter_count - 1)) + return true; + + netdev_for_each_uc_addr(ha, dev) { + if (!ether_addr_equal(ha->addr, vnic->uc_list + off)) + return true; + + off += ETH_ALEN; + } + return false; +} + +static void bnxt_set_rx_mode(struct net_device *dev) +{ + struct bnxt *bp = netdev_priv(dev); + struct bnxt_vnic_info *vnic = &bp->vnic_info[0]; + u32 mask = vnic->rx_mask; + bool mc_update = false; + bool uc_update; + + if (!netif_running(dev)) + return; + + mask &= ~(CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS | + CFA_L2_SET_RX_MASK_REQ_MASK_MCAST | + CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST); + + /* Only allow PF to be in promiscuous mode */ + if ((dev->flags & IFF_PROMISC) && BNXT_PF(bp)) + mask |= CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; + + uc_update = bnxt_uc_list_updated(bp); + + if (dev->flags & IFF_ALLMULTI) { + mask |= CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST; + vnic->mc_list_count = 0; + } else { + mc_update = bnxt_mc_list_updated(bp, &mask); + } + + if (mask != vnic->rx_mask || uc_update || mc_update) { + vnic->rx_mask = mask; + + set_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event); + schedule_work(&bp->sp_task); + } +} + +static void bnxt_cfg_rx_mode(struct bnxt *bp) +{ + struct net_device *dev = bp->dev; + struct bnxt_vnic_info *vnic = &bp->vnic_info[0]; + struct netdev_hw_addr *ha; + int i, off = 0, rc; + bool uc_update; + + netif_addr_lock_bh(dev); + uc_update = bnxt_uc_list_updated(bp); + netif_addr_unlock_bh(dev); + + if (!uc_update) + goto skip_uc; + + mutex_lock(&bp->hwrm_cmd_lock); + for (i = 1; i < vnic->uc_filter_count; i++) { + struct hwrm_cfa_l2_filter_free_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_L2_FILTER_FREE, -1, + -1); + + req.l2_filter_id = vnic->fw_l2_filter_id[i]; + + rc = _hwrm_send_message(bp, &req, sizeof(req), + HWRM_CMD_TIMEOUT); + } + mutex_unlock(&bp->hwrm_cmd_lock); + + vnic->uc_filter_count = 1; + + netif_addr_lock_bh(dev); + if (netdev_uc_count(dev) > (BNXT_MAX_UC_ADDRS - 1)) { + vnic->rx_mask |= CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS; + } else { + netdev_for_each_uc_addr(ha, dev) { + memcpy(vnic->uc_list + off, ha->addr, ETH_ALEN); + off += ETH_ALEN; + vnic->uc_filter_count++; + } + } + netif_addr_unlock_bh(dev); + + for (i = 1, off = 0; i < vnic->uc_filter_count; i++, off += ETH_ALEN) { + rc = bnxt_hwrm_set_vnic_filter(bp, 0, i, vnic->uc_list + off); + if (rc) { + netdev_err(bp->dev, "HWRM vnic filter failure rc: %x\n", + rc); + vnic->uc_filter_count = i; + } + } + +skip_uc: + rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, 0); + if (rc) + netdev_err(bp->dev, "HWRM cfa l2 rx mask failure rc: %x\n", + rc); +} + +static netdev_features_t bnxt_fix_features(struct net_device *dev, + netdev_features_t features) +{ + return features; +} + +static int bnxt_set_features(struct net_device *dev, netdev_features_t features) +{ + struct bnxt *bp = netdev_priv(dev); + u32 flags = bp->flags; + u32 changes; + int rc = 0; + bool re_init = false; + bool update_tpa = false; + + flags &= ~BNXT_FLAG_ALL_CONFIG_FEATS; + if ((features & NETIF_F_GRO) && (bp->pdev->revision > 0)) + flags |= BNXT_FLAG_GRO; + if (features & NETIF_F_LRO) + flags |= BNXT_FLAG_LRO; + + if (features & NETIF_F_HW_VLAN_CTAG_RX) + flags |= BNXT_FLAG_STRIP_VLAN; + + if (features & NETIF_F_NTUPLE) + flags |= BNXT_FLAG_RFS; + + changes = flags ^ bp->flags; + if (changes & BNXT_FLAG_TPA) { + update_tpa = true; + if ((bp->flags & BNXT_FLAG_TPA) == 0 || + (flags & BNXT_FLAG_TPA) == 0) + re_init = true; + } + + if (changes & ~BNXT_FLAG_TPA) + re_init = true; + + if (flags != bp->flags) { + u32 old_flags = bp->flags; + + bp->flags = flags; + + if (!netif_running(dev)) { + if (update_tpa) + bnxt_set_ring_params(bp); + return rc; + } + + if (re_init) { + bnxt_close_nic(bp, false, false); + if (update_tpa) + bnxt_set_ring_params(bp); + + return bnxt_open_nic(bp, false, false); + } + if (update_tpa) { + rc = bnxt_set_tpa(bp, + (flags & BNXT_FLAG_TPA) ? + true : false); + if (rc) + bp->flags = old_flags; + } + } + return rc; +} + +static void bnxt_dbg_dump_states(struct bnxt *bp) +{ + int i; + struct bnxt_napi *bnapi; + struct bnxt_tx_ring_info *txr; + struct bnxt_rx_ring_info *rxr; + struct bnxt_cp_ring_info *cpr; + + for (i = 0; i < bp->cp_nr_rings; i++) { + bnapi = bp->bnapi[i]; + txr = &bnapi->tx_ring; + rxr = &bnapi->rx_ring; + cpr = &bnapi->cp_ring; + if (netif_msg_drv(bp)) { + netdev_info(bp->dev, "[%d]: tx{fw_ring: %d prod: %x cons: %x}\n", + i, txr->tx_ring_struct.fw_ring_id, + txr->tx_prod, txr->tx_cons); + netdev_info(bp->dev, "[%d]: rx{fw_ring: %d prod: %x} rx_agg{fw_ring: %d agg_prod: %x sw_agg_prod: %x}\n", + i, rxr->rx_ring_struct.fw_ring_id, + rxr->rx_prod, + rxr->rx_agg_ring_struct.fw_ring_id, + rxr->rx_agg_prod, rxr->rx_sw_agg_prod); + netdev_info(bp->dev, "[%d]: cp{fw_ring: %d raw_cons: %x}\n", + i, cpr->cp_ring_struct.fw_ring_id, + cpr->cp_raw_cons); + } + } +} + +static void bnxt_reset_task(struct bnxt *bp) +{ + bnxt_dbg_dump_states(bp); + if (netif_running(bp->dev)) + bnxt_tx_disable(bp); /* prevent tx timout again */ +} + +static void bnxt_tx_timeout(struct net_device *dev) +{ + struct bnxt *bp = netdev_priv(dev); + + netdev_err(bp->dev, "TX timeout detected, starting reset task!\n"); + set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event); + schedule_work(&bp->sp_task); +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void bnxt_poll_controller(struct net_device *dev) +{ + struct bnxt *bp = netdev_priv(dev); + int i; + + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_irq *irq = &bp->irq_tbl[i]; + + disable_irq(irq->vector); + irq->handler(irq->vector, bp->bnapi[i]); + enable_irq(irq->vector); + } +} +#endif + +static void bnxt_timer(unsigned long data) +{ + struct bnxt *bp = (struct bnxt *)data; + struct net_device *dev = bp->dev; + + if (!netif_running(dev)) + return; + + if (atomic_read(&bp->intr_sem) != 0) + goto bnxt_restart_timer; + +bnxt_restart_timer: + mod_timer(&bp->timer, jiffies + bp->current_interval); +} + +static void bnxt_cfg_ntp_filters(struct bnxt *); + +static void bnxt_sp_task(struct work_struct *work) +{ + struct bnxt *bp = container_of(work, struct bnxt, sp_task); + int rc; + + if (bp->state != BNXT_STATE_OPEN) + return; + + if (test_and_clear_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event)) + bnxt_cfg_rx_mode(bp); + + if (test_and_clear_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event)) + bnxt_cfg_ntp_filters(bp); + if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) { + rc = bnxt_update_link(bp, true); + if (rc) + netdev_err(bp->dev, "SP task can't update link (rc: %x)\n", + rc); + } + if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event)) + bnxt_hwrm_exec_fwd_req(bp); + if (test_and_clear_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event)) { + bnxt_hwrm_tunnel_dst_port_alloc( + bp, bp->vxlan_port, + TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN); + } + if (test_and_clear_bit(BNXT_VXLAN_DEL_PORT_SP_EVENT, &bp->sp_event)) { + bnxt_hwrm_tunnel_dst_port_free( + bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN); + } + if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event)) + bnxt_reset_task(bp); +} + +static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev) +{ + int rc; + struct bnxt *bp = netdev_priv(dev); + + SET_NETDEV_DEV(dev, &pdev->dev); + + /* enable device (incl. PCI PM wakeup), and bus-mastering */ + rc = pci_enable_device(pdev); + if (rc) { + dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n"); + goto init_err; + } + + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { + dev_err(&pdev->dev, + "Cannot find PCI device base address, aborting\n"); + rc = -ENODEV; + goto init_err_disable; + } + + rc = pci_request_regions(pdev, DRV_MODULE_NAME); + if (rc) { + dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting\n"); + goto init_err_disable; + } + + if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) != 0 && + dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) { + dev_err(&pdev->dev, "System does not support DMA, aborting\n"); + goto init_err_disable; + } + + pci_set_master(pdev); + + bp->dev = dev; + bp->pdev = pdev; + + bp->bar0 = pci_ioremap_bar(pdev, 0); + if (!bp->bar0) { + dev_err(&pdev->dev, "Cannot map device registers, aborting\n"); + rc = -ENOMEM; + goto init_err_release; + } + + bp->bar1 = pci_ioremap_bar(pdev, 2); + if (!bp->bar1) { + dev_err(&pdev->dev, "Cannot map doorbell registers, aborting\n"); + rc = -ENOMEM; + goto init_err_release; + } + + bp->bar2 = pci_ioremap_bar(pdev, 4); + if (!bp->bar2) { + dev_err(&pdev->dev, "Cannot map bar4 registers, aborting\n"); + rc = -ENOMEM; + goto init_err_release; + } + + INIT_WORK(&bp->sp_task, bnxt_sp_task); + + spin_lock_init(&bp->ntp_fltr_lock); + + bp->rx_ring_size = BNXT_DEFAULT_RX_RING_SIZE; + bp->tx_ring_size = BNXT_DEFAULT_TX_RING_SIZE; + + bp->coal_ticks = BNXT_USEC_TO_COAL_TIMER(4); + bp->coal_bufs = 20; + bp->coal_ticks_irq = BNXT_USEC_TO_COAL_TIMER(1); + bp->coal_bufs_irq = 2; + + init_timer(&bp->timer); + bp->timer.data = (unsigned long)bp; + bp->timer.function = bnxt_timer; + bp->current_interval = BNXT_TIMER_INTERVAL; + + bp->state = BNXT_STATE_CLOSED; + + return 0; + +init_err_release: + if (bp->bar2) { + pci_iounmap(pdev, bp->bar2); + bp->bar2 = NULL; + } + + if (bp->bar1) { + pci_iounmap(pdev, bp->bar1); + bp->bar1 = NULL; + } + + if (bp->bar0) { + pci_iounmap(pdev, bp->bar0); + bp->bar0 = NULL; + } + + pci_release_regions(pdev); + +init_err_disable: + pci_disable_device(pdev); + +init_err: + return rc; +} + +/* rtnl_lock held */ +static int bnxt_change_mac_addr(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + return 0; +} + +/* rtnl_lock held */ +static int bnxt_change_mtu(struct net_device *dev, int new_mtu) +{ + struct bnxt *bp = netdev_priv(dev); + + if (new_mtu < 60 || new_mtu > 9000) + return -EINVAL; + + if (netif_running(dev)) + bnxt_close_nic(bp, false, false); + + dev->mtu = new_mtu; + bnxt_set_ring_params(bp); + + if (netif_running(dev)) + return bnxt_open_nic(bp, false, false); + + return 0; +} + +static int bnxt_setup_tc(struct net_device *dev, u8 tc) +{ + struct bnxt *bp = netdev_priv(dev); + + if (tc > bp->max_tc) { + netdev_err(dev, "too many traffic classes requested: %d Max supported is %d\n", + tc, bp->max_tc); + return -EINVAL; + } + + if (netdev_get_num_tc(dev) == tc) + return 0; + + if (tc) { + int max_rx_rings, max_tx_rings; + + bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings); + if (bp->tx_nr_rings_per_tc * tc > max_tx_rings) + return -ENOMEM; + } + + /* Needs to close the device and do hw resource re-allocations */ + if (netif_running(bp->dev)) + bnxt_close_nic(bp, true, false); + + if (tc) { + bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tc; + netdev_set_num_tc(dev, tc); + } else { + bp->tx_nr_rings = bp->tx_nr_rings_per_tc; + netdev_reset_tc(dev); + } + bp->cp_nr_rings = max_t(int, bp->tx_nr_rings, bp->rx_nr_rings); + bp->num_stat_ctxs = bp->cp_nr_rings; + + if (netif_running(bp->dev)) + return bnxt_open_nic(bp, true, false); + + return 0; +} + +#ifdef CONFIG_RFS_ACCEL +static bool bnxt_fltr_match(struct bnxt_ntuple_filter *f1, + struct bnxt_ntuple_filter *f2) +{ + struct flow_keys *keys1 = &f1->fkeys; + struct flow_keys *keys2 = &f2->fkeys; + + if (keys1->addrs.v4addrs.src == keys2->addrs.v4addrs.src && + keys1->addrs.v4addrs.dst == keys2->addrs.v4addrs.dst && + keys1->ports.ports == keys2->ports.ports && + keys1->basic.ip_proto == keys2->basic.ip_proto && + keys1->basic.n_proto == keys2->basic.n_proto && + ether_addr_equal(f1->src_mac_addr, f2->src_mac_addr)) + return true; + + return false; +} + +static int bnxt_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, + u16 rxq_index, u32 flow_id) +{ + struct bnxt *bp = netdev_priv(dev); + struct bnxt_ntuple_filter *fltr, *new_fltr; + struct flow_keys *fkeys; + struct ethhdr *eth = (struct ethhdr *)skb_mac_header(skb); + int rc = 0, idx; + struct hlist_head *head; + + if (skb->encapsulation) + return -EPROTONOSUPPORT; + + new_fltr = kzalloc(sizeof(*new_fltr), GFP_ATOMIC); + if (!new_fltr) + return -ENOMEM; + + fkeys = &new_fltr->fkeys; + if (!skb_flow_dissect_flow_keys(skb, fkeys, 0)) { + rc = -EPROTONOSUPPORT; + goto err_free; + } + + if ((fkeys->basic.n_proto != htons(ETH_P_IP)) || + ((fkeys->basic.ip_proto != IPPROTO_TCP) && + (fkeys->basic.ip_proto != IPPROTO_UDP))) { + rc = -EPROTONOSUPPORT; + goto err_free; + } + + memcpy(new_fltr->src_mac_addr, eth->h_source, ETH_ALEN); + + idx = skb_get_hash_raw(skb) & BNXT_NTP_FLTR_HASH_MASK; + head = &bp->ntp_fltr_hash_tbl[idx]; + rcu_read_lock(); + hlist_for_each_entry_rcu(fltr, head, hash) { + if (bnxt_fltr_match(fltr, new_fltr)) { + rcu_read_unlock(); + rc = 0; + goto err_free; + } + } + rcu_read_unlock(); + + spin_lock_bh(&bp->ntp_fltr_lock); + new_fltr->sw_id = bitmap_find_free_region(bp->ntp_fltr_bmap, + BNXT_NTP_FLTR_MAX_FLTR, 0); + if (new_fltr->sw_id < 0) { + spin_unlock_bh(&bp->ntp_fltr_lock); + rc = -ENOMEM; + goto err_free; + } + + new_fltr->flow_id = flow_id; + new_fltr->rxq = rxq_index; + hlist_add_head_rcu(&new_fltr->hash, head); + bp->ntp_fltr_count++; + spin_unlock_bh(&bp->ntp_fltr_lock); + + set_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event); + schedule_work(&bp->sp_task); + + return new_fltr->sw_id; + +err_free: + kfree(new_fltr); + return rc; +} + +static void bnxt_cfg_ntp_filters(struct bnxt *bp) +{ + int i; + + for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) { + struct hlist_head *head; + struct hlist_node *tmp; + struct bnxt_ntuple_filter *fltr; + int rc; + + head = &bp->ntp_fltr_hash_tbl[i]; + hlist_for_each_entry_safe(fltr, tmp, head, hash) { + bool del = false; + + if (test_bit(BNXT_FLTR_VALID, &fltr->state)) { + if (rps_may_expire_flow(bp->dev, fltr->rxq, + fltr->flow_id, + fltr->sw_id)) { + bnxt_hwrm_cfa_ntuple_filter_free(bp, + fltr); + del = true; + } + } else { + rc = bnxt_hwrm_cfa_ntuple_filter_alloc(bp, + fltr); + if (rc) + del = true; + else + set_bit(BNXT_FLTR_VALID, &fltr->state); + } + + if (del) { + spin_lock_bh(&bp->ntp_fltr_lock); + hlist_del_rcu(&fltr->hash); + bp->ntp_fltr_count--; + spin_unlock_bh(&bp->ntp_fltr_lock); + synchronize_rcu(); + clear_bit(fltr->sw_id, bp->ntp_fltr_bmap); + kfree(fltr); + } + } + } +} + +#else + +static void bnxt_cfg_ntp_filters(struct bnxt *bp) +{ +} + +#endif /* CONFIG_RFS_ACCEL */ + +static void bnxt_add_vxlan_port(struct net_device *dev, sa_family_t sa_family, + __be16 port) +{ + struct bnxt *bp = netdev_priv(dev); + + if (!netif_running(dev)) + return; + + if (sa_family != AF_INET6 && sa_family != AF_INET) + return; + + if (bp->vxlan_port_cnt && bp->vxlan_port != port) + return; + + bp->vxlan_port_cnt++; + if (bp->vxlan_port_cnt == 1) { + bp->vxlan_port = port; + set_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event); + schedule_work(&bp->sp_task); + } +} + +static void bnxt_del_vxlan_port(struct net_device *dev, sa_family_t sa_family, + __be16 port) +{ + struct bnxt *bp = netdev_priv(dev); + + if (!netif_running(dev)) + return; + + if (sa_family != AF_INET6 && sa_family != AF_INET) + return; + + if (bp->vxlan_port_cnt && bp->vxlan_port == port) { + bp->vxlan_port_cnt--; + + if (bp->vxlan_port_cnt == 0) { + set_bit(BNXT_VXLAN_DEL_PORT_SP_EVENT, &bp->sp_event); + schedule_work(&bp->sp_task); + } + } +} + +static const struct net_device_ops bnxt_netdev_ops = { + .ndo_open = bnxt_open, + .ndo_start_xmit = bnxt_start_xmit, + .ndo_stop = bnxt_close, + .ndo_get_stats64 = bnxt_get_stats64, + .ndo_set_rx_mode = bnxt_set_rx_mode, + .ndo_do_ioctl = bnxt_ioctl, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = bnxt_change_mac_addr, + .ndo_change_mtu = bnxt_change_mtu, + .ndo_fix_features = bnxt_fix_features, + .ndo_set_features = bnxt_set_features, + .ndo_tx_timeout = bnxt_tx_timeout, +#ifdef CONFIG_BNXT_SRIOV + .ndo_get_vf_config = bnxt_get_vf_config, + .ndo_set_vf_mac = bnxt_set_vf_mac, + .ndo_set_vf_vlan = bnxt_set_vf_vlan, + .ndo_set_vf_rate = bnxt_set_vf_bw, + .ndo_set_vf_link_state = bnxt_set_vf_link_state, + .ndo_set_vf_spoofchk = bnxt_set_vf_spoofchk, +#endif +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = bnxt_poll_controller, +#endif + .ndo_setup_tc = bnxt_setup_tc, +#ifdef CONFIG_RFS_ACCEL + .ndo_rx_flow_steer = bnxt_rx_flow_steer, +#endif + .ndo_add_vxlan_port = bnxt_add_vxlan_port, + .ndo_del_vxlan_port = bnxt_del_vxlan_port, +#ifdef CONFIG_NET_RX_BUSY_POLL + .ndo_busy_poll = bnxt_busy_poll, +#endif +}; + +static void bnxt_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct bnxt *bp = netdev_priv(dev); + + if (BNXT_PF(bp)) + bnxt_sriov_disable(bp); + + unregister_netdev(dev); + cancel_work_sync(&bp->sp_task); + bp->sp_event = 0; + + bnxt_free_hwrm_resources(bp); + pci_iounmap(pdev, bp->bar2); + pci_iounmap(pdev, bp->bar1); + pci_iounmap(pdev, bp->bar0); + free_netdev(dev); + + pci_release_regions(pdev); + pci_disable_device(pdev); +} + +static int bnxt_probe_phy(struct bnxt *bp) +{ + int rc = 0; + struct bnxt_link_info *link_info = &bp->link_info; + char phy_ver[PHY_VER_STR_LEN]; + + rc = bnxt_update_link(bp, false); + if (rc) { + netdev_err(bp->dev, "Probe phy can't update link (rc: %x)\n", + rc); + return rc; + } + + /*initialize the ethool setting copy with NVM settings */ + if (BNXT_AUTO_MODE(link_info->auto_mode)) + link_info->autoneg |= BNXT_AUTONEG_SPEED; + + if (link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) { + if (link_info->auto_pause_setting == BNXT_LINK_PAUSE_BOTH) + link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL; + link_info->req_flow_ctrl = link_info->auto_pause_setting; + } else if (link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) { + link_info->req_flow_ctrl = link_info->force_pause_setting; + } + link_info->req_duplex = link_info->duplex_setting; + if (link_info->autoneg & BNXT_AUTONEG_SPEED) + link_info->req_link_speed = link_info->auto_link_speed; + else + link_info->req_link_speed = link_info->force_link_speed; + link_info->advertising = link_info->auto_link_speeds; + snprintf(phy_ver, PHY_VER_STR_LEN, " ph %d.%d.%d", + link_info->phy_ver[0], + link_info->phy_ver[1], + link_info->phy_ver[2]); + strcat(bp->fw_ver_str, phy_ver); + return rc; +} + +static int bnxt_get_max_irq(struct pci_dev *pdev) +{ + u16 ctrl; + + if (!pdev->msix_cap) + return 1; + + pci_read_config_word(pdev, pdev->msix_cap + PCI_MSIX_FLAGS, &ctrl); + return (ctrl & PCI_MSIX_FLAGS_QSIZE) + 1; +} + +void bnxt_get_max_rings(struct bnxt *bp, int *max_rx, int *max_tx) +{ + int max_rings; + + if (BNXT_PF(bp)) { + *max_tx = bp->pf.max_pf_tx_rings; + *max_rx = bp->pf.max_pf_rx_rings; + max_rings = min_t(int, bp->pf.max_irqs, bp->pf.max_cp_rings); + max_rings = min_t(int, max_rings, bp->pf.max_stat_ctxs); + } else { + *max_tx = bp->vf.max_tx_rings; + *max_rx = bp->vf.max_rx_rings; + max_rings = min_t(int, bp->vf.max_irqs, bp->vf.max_cp_rings); + max_rings = min_t(int, max_rings, bp->vf.max_stat_ctxs); + } + if (bp->flags & BNXT_FLAG_AGG_RINGS) + *max_rx >>= 1; + + *max_rx = min_t(int, *max_rx, max_rings); + *max_tx = min_t(int, *max_tx, max_rings); +} + +static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int version_printed; + struct net_device *dev; + struct bnxt *bp; + int rc, max_rx_rings, max_tx_rings, max_irqs, dflt_rings; + + if (version_printed++ == 0) + pr_info("%s", version); + + max_irqs = bnxt_get_max_irq(pdev); + dev = alloc_etherdev_mq(sizeof(*bp), max_irqs); + if (!dev) + return -ENOMEM; + + bp = netdev_priv(dev); + + if (bnxt_vf_pciid(ent->driver_data)) + bp->flags |= BNXT_FLAG_VF; + + if (pdev->msix_cap) { + bp->flags |= BNXT_FLAG_MSIX_CAP; + if (BNXT_PF(bp)) + bp->flags |= BNXT_FLAG_RFS; + } + + rc = bnxt_init_board(pdev, dev); + if (rc < 0) + goto init_err_free; + + dev->netdev_ops = &bnxt_netdev_ops; + dev->watchdog_timeo = BNXT_TX_TIMEOUT; + dev->ethtool_ops = &bnxt_ethtool_ops; + + pci_set_drvdata(pdev, dev); + + dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG | + NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE | + NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT | + NETIF_F_RXHASH | + NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_GRO; + + if (bp->flags & BNXT_FLAG_RFS) + dev->hw_features |= NETIF_F_NTUPLE; + + dev->hw_enc_features = + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG | + NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE | + NETIF_F_GSO_IPIP | NETIF_F_GSO_SIT; + dev->vlan_features = dev->hw_features | NETIF_F_HIGHDMA; + dev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX; + dev->features |= dev->hw_features | NETIF_F_HIGHDMA; + dev->priv_flags |= IFF_UNICAST_FLT; + +#ifdef CONFIG_BNXT_SRIOV + init_waitqueue_head(&bp->sriov_cfg_wait); +#endif + rc = bnxt_alloc_hwrm_resources(bp); + if (rc) + goto init_err; + + mutex_init(&bp->hwrm_cmd_lock); + bnxt_hwrm_ver_get(bp); + + rc = bnxt_hwrm_func_drv_rgtr(bp); + if (rc) + goto init_err; + + /* Get the MAX capabilities for this function */ + rc = bnxt_hwrm_func_qcaps(bp); + if (rc) { + netdev_err(bp->dev, "hwrm query capability failure rc: %x\n", + rc); + rc = -1; + goto init_err; + } + + rc = bnxt_hwrm_queue_qportcfg(bp); + if (rc) { + netdev_err(bp->dev, "hwrm query qportcfg failure rc: %x\n", + rc); + rc = -1; + goto init_err; + } + + bnxt_set_tpa_flags(bp); + bnxt_set_ring_params(bp); + dflt_rings = netif_get_num_default_rss_queues(); + if (BNXT_PF(bp)) { + memcpy(dev->dev_addr, bp->pf.mac_addr, ETH_ALEN); + bp->pf.max_irqs = max_irqs; + } else { + memcpy(dev->dev_addr, bp->vf.mac_addr, ETH_ALEN); + bp->vf.max_irqs = max_irqs; + } + bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings); + bp->rx_nr_rings = min_t(int, dflt_rings, max_rx_rings); + bp->tx_nr_rings_per_tc = min_t(int, dflt_rings, max_tx_rings); + bp->tx_nr_rings = bp->tx_nr_rings_per_tc; + bp->cp_nr_rings = max_t(int, bp->rx_nr_rings, bp->tx_nr_rings); + bp->num_stat_ctxs = bp->cp_nr_rings; + + if (dev->hw_features & NETIF_F_HW_VLAN_CTAG_RX) + bp->flags |= BNXT_FLAG_STRIP_VLAN; + + rc = bnxt_probe_phy(bp); + if (rc) + goto init_err; + + rc = register_netdev(dev); + if (rc) + goto init_err; + + netdev_info(dev, "%s found at mem %lx, node addr %pM\n", + board_info[ent->driver_data].name, + (long)pci_resource_start(pdev, 0), dev->dev_addr); + + return 0; + +init_err: + pci_iounmap(pdev, bp->bar0); + pci_release_regions(pdev); + pci_disable_device(pdev); + +init_err_free: + free_netdev(dev); + return rc; +} + +static struct pci_driver bnxt_pci_driver = { + .name = DRV_MODULE_NAME, + .id_table = bnxt_pci_tbl, + .probe = bnxt_init_one, + .remove = bnxt_remove_one, +#if defined(CONFIG_BNXT_SRIOV) + .sriov_configure = bnxt_sriov_configure, +#endif +}; + +module_pci_driver(bnxt_pci_driver); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h new file mode 100644 index 000000000000..7c89367634d0 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -0,0 +1,1081 @@ +/* Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2014-2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + */ + +#ifndef BNXT_H +#define BNXT_H + +#define DRV_MODULE_NAME "bnxt_en" +#define DRV_MODULE_VERSION "0.1.24" + +#define DRV_VER_MAJ 0 +#define DRV_VER_MIN 1 +#define DRV_VER_UPD 24 + +struct tx_bd { + __le32 tx_bd_len_flags_type; + #define TX_BD_TYPE (0x3f << 0) + #define TX_BD_TYPE_SHORT_TX_BD (0x00 << 0) + #define TX_BD_TYPE_LONG_TX_BD (0x10 << 0) + #define TX_BD_FLAGS_PACKET_END (1 << 6) + #define TX_BD_FLAGS_NO_CMPL (1 << 7) + #define TX_BD_FLAGS_BD_CNT (0x1f << 8) + #define TX_BD_FLAGS_BD_CNT_SHIFT 8 + #define TX_BD_FLAGS_LHINT (3 << 13) + #define TX_BD_FLAGS_LHINT_SHIFT 13 + #define TX_BD_FLAGS_LHINT_512_AND_SMALLER (0 << 13) + #define TX_BD_FLAGS_LHINT_512_TO_1023 (1 << 13) + #define TX_BD_FLAGS_LHINT_1024_TO_2047 (2 << 13) + #define TX_BD_FLAGS_LHINT_2048_AND_LARGER (3 << 13) + #define TX_BD_FLAGS_COAL_NOW (1 << 15) + #define TX_BD_LEN (0xffff << 16) + #define TX_BD_LEN_SHIFT 16 + + u32 tx_bd_opaque; + __le64 tx_bd_haddr; +} __packed; + +struct tx_bd_ext { + __le32 tx_bd_hsize_lflags; + #define TX_BD_FLAGS_TCP_UDP_CHKSUM (1 << 0) + #define TX_BD_FLAGS_IP_CKSUM (1 << 1) + #define TX_BD_FLAGS_NO_CRC (1 << 2) + #define TX_BD_FLAGS_STAMP (1 << 3) + #define TX_BD_FLAGS_T_IP_CHKSUM (1 << 4) + #define TX_BD_FLAGS_LSO (1 << 5) + #define TX_BD_FLAGS_IPID_FMT (1 << 6) + #define TX_BD_FLAGS_T_IPID (1 << 7) + #define TX_BD_HSIZE (0xff << 16) + #define TX_BD_HSIZE_SHIFT 16 + + __le32 tx_bd_mss; + __le32 tx_bd_cfa_action; + #define TX_BD_CFA_ACTION (0xffff << 16) + #define TX_BD_CFA_ACTION_SHIFT 16 + + __le32 tx_bd_cfa_meta; + #define TX_BD_CFA_META_MASK 0xfffffff + #define TX_BD_CFA_META_VID_MASK 0xfff + #define TX_BD_CFA_META_PRI_MASK (0xf << 12) + #define TX_BD_CFA_META_PRI_SHIFT 12 + #define TX_BD_CFA_META_TPID_MASK (3 << 16) + #define TX_BD_CFA_META_TPID_SHIFT 16 + #define TX_BD_CFA_META_KEY (0xf << 28) + #define TX_BD_CFA_META_KEY_SHIFT 28 + #define TX_BD_CFA_META_KEY_VLAN (1 << 28) +}; + +struct rx_bd { + __le32 rx_bd_len_flags_type; + #define RX_BD_TYPE (0x3f << 0) + #define RX_BD_TYPE_RX_PACKET_BD 0x4 + #define RX_BD_TYPE_RX_BUFFER_BD 0x5 + #define RX_BD_TYPE_RX_AGG_BD 0x6 + #define RX_BD_TYPE_16B_BD_SIZE (0 << 4) + #define RX_BD_TYPE_32B_BD_SIZE (1 << 4) + #define RX_BD_TYPE_48B_BD_SIZE (2 << 4) + #define RX_BD_TYPE_64B_BD_SIZE (3 << 4) + #define RX_BD_FLAGS_SOP (1 << 6) + #define RX_BD_FLAGS_EOP (1 << 7) + #define RX_BD_FLAGS_BUFFERS (3 << 8) + #define RX_BD_FLAGS_1_BUFFER_PACKET (0 << 8) + #define RX_BD_FLAGS_2_BUFFER_PACKET (1 << 8) + #define RX_BD_FLAGS_3_BUFFER_PACKET (2 << 8) + #define RX_BD_FLAGS_4_BUFFER_PACKET (3 << 8) + #define RX_BD_LEN (0xffff << 16) + #define RX_BD_LEN_SHIFT 16 + + u32 rx_bd_opaque; + __le64 rx_bd_haddr; +}; + +struct tx_cmp { + __le32 tx_cmp_flags_type; + #define CMP_TYPE (0x3f << 0) + #define CMP_TYPE_TX_L2_CMP 0 + #define CMP_TYPE_RX_L2_CMP 17 + #define CMP_TYPE_RX_AGG_CMP 18 + #define CMP_TYPE_RX_L2_TPA_START_CMP 19 + #define CMP_TYPE_RX_L2_TPA_END_CMP 21 + #define CMP_TYPE_STATUS_CMP 32 + #define CMP_TYPE_REMOTE_DRIVER_REQ 34 + #define CMP_TYPE_REMOTE_DRIVER_RESP 36 + #define CMP_TYPE_ERROR_STATUS 48 + #define CMPL_BASE_TYPE_STAT_EJECT (0x1aUL << 0) + #define CMPL_BASE_TYPE_HWRM_DONE (0x20UL << 0) + #define CMPL_BASE_TYPE_HWRM_FWD_REQ (0x22UL << 0) + #define CMPL_BASE_TYPE_HWRM_FWD_RESP (0x24UL << 0) + #define CMPL_BASE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + + #define TX_CMP_FLAGS_ERROR (1 << 6) + #define TX_CMP_FLAGS_PUSH (1 << 7) + + u32 tx_cmp_opaque; + __le32 tx_cmp_errors_v; + #define TX_CMP_V (1 << 0) + #define TX_CMP_ERRORS_BUFFER_ERROR (7 << 1) + #define TX_CMP_ERRORS_BUFFER_ERROR_NO_ERROR 0 + #define TX_CMP_ERRORS_BUFFER_ERROR_BAD_FORMAT 2 + #define TX_CMP_ERRORS_BUFFER_ERROR_INVALID_STAG 4 + #define TX_CMP_ERRORS_BUFFER_ERROR_STAG_BOUNDS 5 + #define TX_CMP_ERRORS_ZERO_LENGTH_PKT (1 << 4) + #define TX_CMP_ERRORS_EXCESSIVE_BD_LEN (1 << 5) + #define TX_CMP_ERRORS_DMA_ERROR (1 << 6) + #define TX_CMP_ERRORS_HINT_TOO_SHORT (1 << 7) + + __le32 tx_cmp_unsed_3; +}; + +struct rx_cmp { + __le32 rx_cmp_len_flags_type; + #define RX_CMP_CMP_TYPE (0x3f << 0) + #define RX_CMP_FLAGS_ERROR (1 << 6) + #define RX_CMP_FLAGS_PLACEMENT (7 << 7) + #define RX_CMP_FLAGS_RSS_VALID (1 << 10) + #define RX_CMP_FLAGS_UNUSED (1 << 11) + #define RX_CMP_FLAGS_ITYPES_SHIFT 12 + #define RX_CMP_FLAGS_ITYPE_UNKNOWN (0 << 12) + #define RX_CMP_FLAGS_ITYPE_IP (1 << 12) + #define RX_CMP_FLAGS_ITYPE_TCP (2 << 12) + #define RX_CMP_FLAGS_ITYPE_UDP (3 << 12) + #define RX_CMP_FLAGS_ITYPE_FCOE (4 << 12) + #define RX_CMP_FLAGS_ITYPE_ROCE (5 << 12) + #define RX_CMP_FLAGS_ITYPE_PTP_WO_TS (8 << 12) + #define RX_CMP_FLAGS_ITYPE_PTP_W_TS (9 << 12) + #define RX_CMP_LEN (0xffff << 16) + #define RX_CMP_LEN_SHIFT 16 + + u32 rx_cmp_opaque; + __le32 rx_cmp_misc_v1; + #define RX_CMP_V1 (1 << 0) + #define RX_CMP_AGG_BUFS (0x1f << 1) + #define RX_CMP_AGG_BUFS_SHIFT 1 + #define RX_CMP_RSS_HASH_TYPE (0x7f << 9) + #define RX_CMP_RSS_HASH_TYPE_SHIFT 9 + #define RX_CMP_PAYLOAD_OFFSET (0xff << 16) + #define RX_CMP_PAYLOAD_OFFSET_SHIFT 16 + + __le32 rx_cmp_rss_hash; +}; + +#define RX_CMP_HASH_VALID(rxcmp) \ + ((rxcmp)->rx_cmp_len_flags_type & cpu_to_le32(RX_CMP_FLAGS_RSS_VALID)) + +#define RX_CMP_HASH_TYPE(rxcmp) \ + ((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_RSS_HASH_TYPE) >>\ + RX_CMP_RSS_HASH_TYPE_SHIFT) + +struct rx_cmp_ext { + __le32 rx_cmp_flags2; + #define RX_CMP_FLAGS2_IP_CS_CALC 0x1 + #define RX_CMP_FLAGS2_L4_CS_CALC (0x1 << 1) + #define RX_CMP_FLAGS2_T_IP_CS_CALC (0x1 << 2) + #define RX_CMP_FLAGS2_T_L4_CS_CALC (0x1 << 3) + #define RX_CMP_FLAGS2_META_FORMAT_VLAN (0x1 << 4) + __le32 rx_cmp_meta_data; + #define RX_CMP_FLAGS2_METADATA_VID_MASK 0xfff + #define RX_CMP_FLAGS2_METADATA_TPID_MASK 0xffff0000 + #define RX_CMP_FLAGS2_METADATA_TPID_SFT 16 + __le32 rx_cmp_cfa_code_errors_v2; + #define RX_CMP_V (1 << 0) + #define RX_CMPL_ERRORS_MASK (0x7fff << 1) + #define RX_CMPL_ERRORS_SFT 1 + #define RX_CMPL_ERRORS_BUFFER_ERROR_MASK (0x7 << 1) + #define RX_CMPL_ERRORS_BUFFER_ERROR_NO_BUFFER (0x0 << 1) + #define RX_CMPL_ERRORS_BUFFER_ERROR_DID_NOT_FIT (0x1 << 1) + #define RX_CMPL_ERRORS_BUFFER_ERROR_NOT_ON_CHIP (0x2 << 1) + #define RX_CMPL_ERRORS_BUFFER_ERROR_BAD_FORMAT (0x3 << 1) + #define RX_CMPL_ERRORS_IP_CS_ERROR (0x1 << 4) + #define RX_CMPL_ERRORS_L4_CS_ERROR (0x1 << 5) + #define RX_CMPL_ERRORS_T_IP_CS_ERROR (0x1 << 6) + #define RX_CMPL_ERRORS_T_L4_CS_ERROR (0x1 << 7) + #define RX_CMPL_ERRORS_CRC_ERROR (0x1 << 8) + #define RX_CMPL_ERRORS_T_PKT_ERROR_MASK (0x7 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_NO_ERROR (0x0 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_VERSION (0x1 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_HDR_LEN (0x2 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_TUNNEL_TOTAL_ERROR (0x3 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_T_IP_TOTAL_ERROR (0x4 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_T_UDP_TOTAL_ERROR (0x5 << 9) + #define RX_CMPL_ERRORS_T_PKT_ERROR_T_L3_BAD_TTL (0x6 << 9) + #define RX_CMPL_ERRORS_PKT_ERROR_MASK (0xf << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_NO_ERROR (0x0 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_L3_BAD_VERSION (0x1 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_L3_BAD_HDR_LEN (0x2 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_L3_BAD_TTL (0x3 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_IP_TOTAL_ERROR (0x4 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_UDP_TOTAL_ERROR (0x5 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN (0x6 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_HDR_LEN_TOO_SMALL (0x7 << 12) + #define RX_CMPL_ERRORS_PKT_ERROR_L4_BAD_OPT_LEN (0x8 << 12) + + #define RX_CMPL_CFA_CODE_MASK (0xffff << 16) + #define RX_CMPL_CFA_CODE_SFT 16 + + __le32 rx_cmp_unused3; +}; + +#define RX_CMP_L2_ERRORS \ + cpu_to_le32(RX_CMPL_ERRORS_BUFFER_ERROR_MASK | RX_CMPL_ERRORS_CRC_ERROR) + +#define RX_CMP_L4_CS_BITS \ + (cpu_to_le32(RX_CMP_FLAGS2_L4_CS_CALC | RX_CMP_FLAGS2_T_L4_CS_CALC)) + +#define RX_CMP_L4_CS_ERR_BITS \ + (cpu_to_le32(RX_CMPL_ERRORS_L4_CS_ERROR | RX_CMPL_ERRORS_T_L4_CS_ERROR)) + +#define RX_CMP_L4_CS_OK(rxcmp1) \ + (((rxcmp1)->rx_cmp_flags2 & RX_CMP_L4_CS_BITS) && \ + !((rxcmp1)->rx_cmp_cfa_code_errors_v2 & RX_CMP_L4_CS_ERR_BITS)) + +#define RX_CMP_ENCAP(rxcmp1) \ + ((le32_to_cpu((rxcmp1)->rx_cmp_flags2) & \ + RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3) + +struct rx_agg_cmp { + __le32 rx_agg_cmp_len_flags_type; + #define RX_AGG_CMP_TYPE (0x3f << 0) + #define RX_AGG_CMP_LEN (0xffff << 16) + #define RX_AGG_CMP_LEN_SHIFT 16 + u32 rx_agg_cmp_opaque; + __le32 rx_agg_cmp_v; + #define RX_AGG_CMP_V (1 << 0) + __le32 rx_agg_cmp_unused; +}; + +struct rx_tpa_start_cmp { + __le32 rx_tpa_start_cmp_len_flags_type; + #define RX_TPA_START_CMP_TYPE (0x3f << 0) + #define RX_TPA_START_CMP_FLAGS (0x3ff << 6) + #define RX_TPA_START_CMP_FLAGS_SHIFT 6 + #define RX_TPA_START_CMP_FLAGS_PLACEMENT (0x7 << 7) + #define RX_TPA_START_CMP_FLAGS_PLACEMENT_SHIFT 7 + #define RX_TPA_START_CMP_FLAGS_PLACEMENT_JUMBO (0x1 << 7) + #define RX_TPA_START_CMP_FLAGS_PLACEMENT_HDS (0x2 << 7) + #define RX_TPA_START_CMP_FLAGS_PLACEMENT_GRO_JUMBO (0x5 << 7) + #define RX_TPA_START_CMP_FLAGS_PLACEMENT_GRO_HDS (0x6 << 7) + #define RX_TPA_START_CMP_FLAGS_RSS_VALID (0x1 << 10) + #define RX_TPA_START_CMP_FLAGS_ITYPES (0xf << 12) + #define RX_TPA_START_CMP_FLAGS_ITYPES_SHIFT 12 + #define RX_TPA_START_CMP_FLAGS_ITYPE_TCP (0x2 << 12) + #define RX_TPA_START_CMP_LEN (0xffff << 16) + #define RX_TPA_START_CMP_LEN_SHIFT 16 + + u32 rx_tpa_start_cmp_opaque; + __le32 rx_tpa_start_cmp_misc_v1; + #define RX_TPA_START_CMP_V1 (0x1 << 0) + #define RX_TPA_START_CMP_RSS_HASH_TYPE (0x7f << 9) + #define RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT 9 + #define RX_TPA_START_CMP_AGG_ID (0x7f << 25) + #define RX_TPA_START_CMP_AGG_ID_SHIFT 25 + + __le32 rx_tpa_start_cmp_rss_hash; +}; + +#define TPA_START_HASH_VALID(rx_tpa_start) \ + ((rx_tpa_start)->rx_tpa_start_cmp_len_flags_type & \ + cpu_to_le32(RX_TPA_START_CMP_FLAGS_RSS_VALID)) + +#define TPA_START_HASH_TYPE(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_CMP_RSS_HASH_TYPE) >> \ + RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT) + +#define TPA_START_AGG_ID(rx_tpa_start) \ + ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_CMP_AGG_ID) >> RX_TPA_START_CMP_AGG_ID_SHIFT) + +struct rx_tpa_start_cmp_ext { + __le32 rx_tpa_start_cmp_flags2; + #define RX_TPA_START_CMP_FLAGS2_IP_CS_CALC (0x1 << 0) + #define RX_TPA_START_CMP_FLAGS2_L4_CS_CALC (0x1 << 1) + #define RX_TPA_START_CMP_FLAGS2_T_IP_CS_CALC (0x1 << 2) + #define RX_TPA_START_CMP_FLAGS2_T_L4_CS_CALC (0x1 << 3) + + __le32 rx_tpa_start_cmp_metadata; + __le32 rx_tpa_start_cmp_cfa_code_v2; + #define RX_TPA_START_CMP_V2 (0x1 << 0) + #define RX_TPA_START_CMP_CFA_CODE (0xffff << 16) + #define RX_TPA_START_CMPL_CFA_CODE_SHIFT 16 + __le32 rx_tpa_start_cmp_unused5; +}; + +struct rx_tpa_end_cmp { + __le32 rx_tpa_end_cmp_len_flags_type; + #define RX_TPA_END_CMP_TYPE (0x3f << 0) + #define RX_TPA_END_CMP_FLAGS (0x3ff << 6) + #define RX_TPA_END_CMP_FLAGS_SHIFT 6 + #define RX_TPA_END_CMP_FLAGS_PLACEMENT (0x7 << 7) + #define RX_TPA_END_CMP_FLAGS_PLACEMENT_SHIFT 7 + #define RX_TPA_END_CMP_FLAGS_PLACEMENT_JUMBO (0x1 << 7) + #define RX_TPA_END_CMP_FLAGS_PLACEMENT_HDS (0x2 << 7) + #define RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_JUMBO (0x5 << 7) + #define RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_HDS (0x6 << 7) + #define RX_TPA_END_CMP_FLAGS_RSS_VALID (0x1 << 10) + #define RX_TPA_END_CMP_FLAGS_ITYPES (0xf << 12) + #define RX_TPA_END_CMP_FLAGS_ITYPES_SHIFT 12 + #define RX_TPA_END_CMP_FLAGS_ITYPE_TCP (0x2 << 12) + #define RX_TPA_END_CMP_LEN (0xffff << 16) + #define RX_TPA_END_CMP_LEN_SHIFT 16 + + u32 rx_tpa_end_cmp_opaque; + __le32 rx_tpa_end_cmp_misc_v1; + #define RX_TPA_END_CMP_V1 (0x1 << 0) + #define RX_TPA_END_CMP_AGG_BUFS (0x3f << 1) + #define RX_TPA_END_CMP_AGG_BUFS_SHIFT 1 + #define RX_TPA_END_CMP_TPA_SEGS (0xff << 8) + #define RX_TPA_END_CMP_TPA_SEGS_SHIFT 8 + #define RX_TPA_END_CMP_PAYLOAD_OFFSET (0xff << 16) + #define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT 16 + #define RX_TPA_END_CMP_AGG_ID (0x7f << 25) + #define RX_TPA_END_CMP_AGG_ID_SHIFT 25 + + __le32 rx_tpa_end_cmp_tsdelta; + #define RX_TPA_END_GRO_TS (0x1 << 31) +}; + +#define TPA_END_AGG_ID(rx_tpa_end) \ + ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ + RX_TPA_END_CMP_AGG_ID) >> RX_TPA_END_CMP_AGG_ID_SHIFT) + +#define TPA_END_TPA_SEGS(rx_tpa_end) \ + ((le32_to_cpu((rx_tpa_end)->rx_tpa_end_cmp_misc_v1) & \ + RX_TPA_END_CMP_TPA_SEGS) >> RX_TPA_END_CMP_TPA_SEGS_SHIFT) + +#define RX_TPA_END_CMP_FLAGS_PLACEMENT_ANY_GRO \ + cpu_to_le32(RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_JUMBO & \ + RX_TPA_END_CMP_FLAGS_PLACEMENT_GRO_HDS) + +#define TPA_END_GRO(rx_tpa_end) \ + ((rx_tpa_end)->rx_tpa_end_cmp_len_flags_type & \ + RX_TPA_END_CMP_FLAGS_PLACEMENT_ANY_GRO) + +#define TPA_END_GRO_TS(rx_tpa_end) \ + ((rx_tpa_end)->rx_tpa_end_cmp_tsdelta & cpu_to_le32(RX_TPA_END_GRO_TS)) + +struct rx_tpa_end_cmp_ext { + __le32 rx_tpa_end_cmp_dup_acks; + #define RX_TPA_END_CMP_TPA_DUP_ACKS (0xf << 0) + + __le32 rx_tpa_end_cmp_seg_len; + #define RX_TPA_END_CMP_TPA_SEG_LEN (0xffff << 0) + + __le32 rx_tpa_end_cmp_errors_v2; + #define RX_TPA_END_CMP_V2 (0x1 << 0) + #define RX_TPA_END_CMP_ERRORS (0x7fff << 1) + #define RX_TPA_END_CMPL_ERRORS_SHIFT 1 + + u32 rx_tpa_end_cmp_start_opaque; +}; + +#define DB_IDX_MASK 0xffffff +#define DB_IDX_VALID (0x1 << 26) +#define DB_IRQ_DIS (0x1 << 27) +#define DB_KEY_TX (0x0 << 28) +#define DB_KEY_RX (0x1 << 28) +#define DB_KEY_CP (0x2 << 28) +#define DB_KEY_ST (0x3 << 28) +#define DB_KEY_TX_PUSH (0x4 << 28) +#define DB_LONG_TX_PUSH (0x2 << 24) + +#define INVALID_HW_RING_ID ((u16)-1) + +#define BNXT_RSS_HASH_TYPE_FLAG_IPV4 0x01 +#define BNXT_RSS_HASH_TYPE_FLAG_TCP_IPV4 0x02 +#define BNXT_RSS_HASH_TYPE_FLAG_IPV6 0x04 +#define BNXT_RSS_HASH_TYPE_FLAG_TCP_IPV6 0x08 + +/* The hardware supports certain page sizes. Use the supported page sizes + * to allocate the rings. + */ +#if (PAGE_SHIFT < 12) +#define BNXT_PAGE_SHIFT 12 +#elif (PAGE_SHIFT <= 13) +#define BNXT_PAGE_SHIFT PAGE_SHIFT +#elif (PAGE_SHIFT < 16) +#define BNXT_PAGE_SHIFT 13 +#else +#define BNXT_PAGE_SHIFT 16 +#endif + +#define BNXT_PAGE_SIZE (1 << BNXT_PAGE_SHIFT) + +#define BNXT_MIN_PKT_SIZE 45 + +#define BNXT_NUM_TESTS(bp) 0 + +#define BNXT_DEFAULT_RX_RING_SIZE 1023 +#define BNXT_DEFAULT_TX_RING_SIZE 512 + +#define MAX_TPA 64 + +#define MAX_RX_PAGES 8 +#define MAX_RX_AGG_PAGES 32 +#define MAX_TX_PAGES 8 +#define MAX_CP_PAGES 64 + +#define RX_DESC_CNT (BNXT_PAGE_SIZE / sizeof(struct rx_bd)) +#define TX_DESC_CNT (BNXT_PAGE_SIZE / sizeof(struct tx_bd)) +#define CP_DESC_CNT (BNXT_PAGE_SIZE / sizeof(struct tx_cmp)) + +#define SW_RXBD_RING_SIZE (sizeof(struct bnxt_sw_rx_bd) * RX_DESC_CNT) +#define HW_RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT) + +#define SW_RXBD_AGG_RING_SIZE (sizeof(struct bnxt_sw_rx_agg_bd) * RX_DESC_CNT) + +#define SW_TXBD_RING_SIZE (sizeof(struct bnxt_sw_tx_bd) * TX_DESC_CNT) +#define HW_TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT) + +#define HW_CMPD_RING_SIZE (sizeof(struct tx_cmp) * CP_DESC_CNT) + +#define BNXT_MAX_RX_DESC_CNT (RX_DESC_CNT * MAX_RX_PAGES - 1) +#define BNXT_MAX_RX_JUM_DESC_CNT (RX_DESC_CNT * MAX_RX_AGG_PAGES - 1) +#define BNXT_MAX_TX_DESC_CNT (TX_DESC_CNT * MAX_TX_PAGES - 1) + +#define RX_RING(x) (((x) & ~(RX_DESC_CNT - 1)) >> (BNXT_PAGE_SHIFT - 4)) +#define RX_IDX(x) ((x) & (RX_DESC_CNT - 1)) + +#define TX_RING(x) (((x) & ~(TX_DESC_CNT - 1)) >> (BNXT_PAGE_SHIFT - 4)) +#define TX_IDX(x) ((x) & (TX_DESC_CNT - 1)) + +#define CP_RING(x) (((x) & ~(CP_DESC_CNT - 1)) >> (BNXT_PAGE_SHIFT - 4)) +#define CP_IDX(x) ((x) & (CP_DESC_CNT - 1)) + +#define TX_CMP_VALID(txcmp, raw_cons) \ + (!!((txcmp)->tx_cmp_errors_v & cpu_to_le32(TX_CMP_V)) == \ + !((raw_cons) & bp->cp_bit)) + +#define RX_CMP_VALID(rxcmp1, raw_cons) \ + (!!((rxcmp1)->rx_cmp_cfa_code_errors_v2 & cpu_to_le32(RX_CMP_V)) ==\ + !((raw_cons) & bp->cp_bit)) + +#define RX_AGG_CMP_VALID(agg, raw_cons) \ + (!!((agg)->rx_agg_cmp_v & cpu_to_le32(RX_AGG_CMP_V)) == \ + !((raw_cons) & bp->cp_bit)) + +#define TX_CMP_TYPE(txcmp) \ + (le32_to_cpu((txcmp)->tx_cmp_flags_type) & CMP_TYPE) + +#define RX_CMP_TYPE(rxcmp) \ + (le32_to_cpu((rxcmp)->rx_cmp_len_flags_type) & RX_CMP_CMP_TYPE) + +#define NEXT_RX(idx) (((idx) + 1) & bp->rx_ring_mask) + +#define NEXT_RX_AGG(idx) (((idx) + 1) & bp->rx_agg_ring_mask) + +#define NEXT_TX(idx) (((idx) + 1) & bp->tx_ring_mask) + +#define ADV_RAW_CMP(idx, n) ((idx) + (n)) +#define NEXT_RAW_CMP(idx) ADV_RAW_CMP(idx, 1) +#define RING_CMP(idx) ((idx) & bp->cp_ring_mask) +#define NEXT_CMP(idx) RING_CMP(ADV_RAW_CMP(idx, 1)) + +#define HWRM_CMD_TIMEOUT 500 +#define HWRM_RESET_TIMEOUT ((HWRM_CMD_TIMEOUT) * 4) +#define HWRM_RESP_ERR_CODE_MASK 0xffff +#define HWRM_RESP_LEN_MASK 0xffff0000 +#define HWRM_RESP_LEN_SFT 16 +#define HWRM_RESP_VALID_MASK 0xff000000 +#define BNXT_HWRM_REQ_MAX_SIZE 128 +#define BNXT_HWRM_REQS_PER_PAGE (BNXT_PAGE_SIZE / \ + BNXT_HWRM_REQ_MAX_SIZE) + +struct bnxt_sw_tx_bd { + struct sk_buff *skb; + DEFINE_DMA_UNMAP_ADDR(mapping); + u8 is_gso; + u8 is_push; + unsigned short nr_frags; +}; + +struct bnxt_sw_rx_bd { + u8 *data; + DEFINE_DMA_UNMAP_ADDR(mapping); +}; + +struct bnxt_sw_rx_agg_bd { + struct page *page; + dma_addr_t mapping; +}; + +struct bnxt_ring_struct { + int nr_pages; + int page_size; + void **pg_arr; + dma_addr_t *dma_arr; + + __le64 *pg_tbl; + dma_addr_t pg_tbl_map; + + int vmem_size; + void **vmem; + + u16 fw_ring_id; /* Ring id filled by Chimp FW */ + u8 queue_id; +}; + +struct tx_push_bd { + __le32 doorbell; + struct tx_bd txbd1; + struct tx_bd_ext txbd2; +}; + +struct bnxt_tx_ring_info { + u16 tx_prod; + u16 tx_cons; + void __iomem *tx_doorbell; + + struct tx_bd *tx_desc_ring[MAX_TX_PAGES]; + struct bnxt_sw_tx_bd *tx_buf_ring; + + dma_addr_t tx_desc_mapping[MAX_TX_PAGES]; + + struct tx_push_bd *tx_push; + dma_addr_t tx_push_mapping; + +#define BNXT_DEV_STATE_CLOSING 0x1 + u32 dev_state; + + struct bnxt_ring_struct tx_ring_struct; +}; + +struct bnxt_tpa_info { + u8 *data; + dma_addr_t mapping; + u16 len; + unsigned short gso_type; + u32 flags2; + u32 metadata; + enum pkt_hash_types hash_type; + u32 rss_hash; +}; + +struct bnxt_rx_ring_info { + u16 rx_prod; + u16 rx_agg_prod; + u16 rx_sw_agg_prod; + void __iomem *rx_doorbell; + void __iomem *rx_agg_doorbell; + + struct rx_bd *rx_desc_ring[MAX_RX_PAGES]; + struct bnxt_sw_rx_bd *rx_buf_ring; + + struct rx_bd *rx_agg_desc_ring[MAX_RX_AGG_PAGES]; + struct bnxt_sw_rx_agg_bd *rx_agg_ring; + + unsigned long *rx_agg_bmap; + u16 rx_agg_bmap_size; + + dma_addr_t rx_desc_mapping[MAX_RX_PAGES]; + dma_addr_t rx_agg_desc_mapping[MAX_RX_AGG_PAGES]; + + struct bnxt_tpa_info *rx_tpa; + + struct bnxt_ring_struct rx_ring_struct; + struct bnxt_ring_struct rx_agg_ring_struct; +}; + +struct bnxt_cp_ring_info { + u32 cp_raw_cons; + void __iomem *cp_doorbell; + + struct tx_cmp *cp_desc_ring[MAX_CP_PAGES]; + + dma_addr_t cp_desc_mapping[MAX_CP_PAGES]; + + struct ctx_hw_stats *hw_stats; + dma_addr_t hw_stats_map; + u32 hw_stats_ctx_id; + u64 rx_l4_csum_errors; + + struct bnxt_ring_struct cp_ring_struct; +}; + +struct bnxt_napi { + struct napi_struct napi; + struct bnxt *bp; + + int index; + struct bnxt_cp_ring_info cp_ring; + struct bnxt_rx_ring_info rx_ring; + struct bnxt_tx_ring_info tx_ring; + +#ifdef CONFIG_NET_RX_BUSY_POLL + atomic_t poll_state; +#endif +}; + +#ifdef CONFIG_NET_RX_BUSY_POLL +enum bnxt_poll_state_t { + BNXT_STATE_IDLE = 0, + BNXT_STATE_NAPI, + BNXT_STATE_POLL, + BNXT_STATE_DISABLE, +}; +#endif + +struct bnxt_irq { + irq_handler_t handler; + unsigned int vector; + u8 requested; + char name[IFNAMSIZ + 2]; +}; + +#define HWRM_RING_ALLOC_TX 0x1 +#define HWRM_RING_ALLOC_RX 0x2 +#define HWRM_RING_ALLOC_AGG 0x4 +#define HWRM_RING_ALLOC_CMPL 0x8 + +#define INVALID_STATS_CTX_ID -1 + +struct hwrm_cmd_req_hdr { +#define HWRM_CMPL_RING_MASK 0xffff0000 +#define HWRM_CMPL_RING_SFT 16 + __le32 cmpl_ring_req_type; +#define HWRM_SEQ_ID_MASK 0xffff +#define HWRM_SEQ_ID_INVALID -1 +#define HWRM_RESP_LEN_OFFSET 4 +#define HWRM_TARGET_FID_MASK 0xffff0000 +#define HWRM_TARGET_FID_SFT 16 + __le32 target_id_seq_id; + __le64 resp_addr; +}; + +struct bnxt_ring_grp_info { + u16 fw_stats_ctx; + u16 fw_grp_id; + u16 rx_fw_ring_id; + u16 agg_fw_ring_id; + u16 cp_fw_ring_id; +}; + +struct bnxt_vnic_info { + u16 fw_vnic_id; /* returned by Chimp during alloc */ + u16 fw_rss_cos_lb_ctx; + u16 fw_l2_ctx_id; +#define BNXT_MAX_UC_ADDRS 4 + __le64 fw_l2_filter_id[BNXT_MAX_UC_ADDRS]; + /* index 0 always dev_addr */ + u16 uc_filter_count; + u8 *uc_list; + + u16 *fw_grp_ids; + u16 hash_type; + dma_addr_t rss_table_dma_addr; + __le16 *rss_table; + dma_addr_t rss_hash_key_dma_addr; + u64 *rss_hash_key; + u32 rx_mask; + + u8 *mc_list; + int mc_list_size; + int mc_list_count; + dma_addr_t mc_list_mapping; +#define BNXT_MAX_MC_ADDRS 16 + + u32 flags; +#define BNXT_VNIC_RSS_FLAG 1 +#define BNXT_VNIC_RFS_FLAG 2 +#define BNXT_VNIC_MCAST_FLAG 4 +#define BNXT_VNIC_UCAST_FLAG 8 +}; + +#if defined(CONFIG_BNXT_SRIOV) +struct bnxt_vf_info { + u16 fw_fid; + u8 mac_addr[ETH_ALEN]; + u16 max_rsscos_ctxs; + u16 max_cp_rings; + u16 max_tx_rings; + u16 max_rx_rings; + u16 max_l2_ctxs; + u16 max_irqs; + u16 max_vnics; + u16 max_stat_ctxs; + u16 vlan; + u32 flags; +#define BNXT_VF_QOS 0x1 +#define BNXT_VF_SPOOFCHK 0x2 +#define BNXT_VF_LINK_FORCED 0x4 +#define BNXT_VF_LINK_UP 0x8 + u32 func_flags; /* func cfg flags */ + u32 min_tx_rate; + u32 max_tx_rate; + void *hwrm_cmd_req_addr; + dma_addr_t hwrm_cmd_req_dma_addr; +}; + +struct bnxt_pf_info { +#define BNXT_FIRST_PF_FID 1 +#define BNXT_FIRST_VF_FID 128 + u32 fw_fid; + u8 port_id; + u8 mac_addr[ETH_ALEN]; + u16 max_rsscos_ctxs; + u16 max_cp_rings; + u16 max_tx_rings; /* HW assigned max tx rings for this PF */ + u16 max_pf_tx_rings; /* runtime max tx rings owned by PF */ + u16 max_rx_rings; /* HW assigned max rx rings for this PF */ + u16 max_pf_rx_rings; /* runtime max rx rings owned by PF */ + u16 max_irqs; + u16 max_l2_ctxs; + u16 max_vnics; + u16 max_stat_ctxs; + u32 first_vf_id; + u16 active_vfs; + u16 max_vfs; + u32 max_encap_records; + u32 max_decap_records; + u32 max_tx_em_flows; + u32 max_tx_wm_flows; + u32 max_rx_em_flows; + u32 max_rx_wm_flows; + unsigned long *vf_event_bmap; + u16 hwrm_cmd_req_pages; + void *hwrm_cmd_req_addr[4]; + dma_addr_t hwrm_cmd_req_dma_addr[4]; + struct bnxt_vf_info *vf; +}; +#endif + +struct bnxt_ntuple_filter { + struct hlist_node hash; + u8 src_mac_addr[ETH_ALEN]; + struct flow_keys fkeys; + __le64 filter_id; + u16 sw_id; + u16 rxq; + u32 flow_id; + unsigned long state; +#define BNXT_FLTR_VALID 0 +#define BNXT_FLTR_UPDATE 1 +}; + +#define BNXT_ALL_COPPER_ETHTOOL_SPEED \ + (ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full | \ + ADVERTISED_10000baseT_Full) + +struct bnxt_link_info { + u8 media_type; + u8 transceiver; + u8 phy_addr; + u8 phy_link_status; +#define BNXT_LINK_NO_LINK PORT_PHY_QCFG_RESP_LINK_NO_LINK +#define BNXT_LINK_SIGNAL PORT_PHY_QCFG_RESP_LINK_SIGNAL +#define BNXT_LINK_LINK PORT_PHY_QCFG_RESP_LINK_LINK + u8 wire_speed; + u8 loop_back; + u8 link_up; + u8 duplex; +#define BNXT_LINK_DUPLEX_HALF PORT_PHY_QCFG_RESP_DUPLEX_HALF +#define BNXT_LINK_DUPLEX_FULL PORT_PHY_QCFG_RESP_DUPLEX_FULL + u8 pause; +#define BNXT_LINK_PAUSE_TX PORT_PHY_QCFG_RESP_PAUSE_TX +#define BNXT_LINK_PAUSE_RX PORT_PHY_QCFG_RESP_PAUSE_RX +#define BNXT_LINK_PAUSE_BOTH (PORT_PHY_QCFG_RESP_PAUSE_RX | \ + PORT_PHY_QCFG_RESP_PAUSE_TX) + u8 auto_pause_setting; + u8 force_pause_setting; + u8 duplex_setting; + u8 auto_mode; +#define BNXT_AUTO_MODE(mode) ((mode) > BNXT_LINK_AUTO_NONE && \ + (mode) <= BNXT_LINK_AUTO_MSK) +#define BNXT_LINK_AUTO_NONE PORT_PHY_QCFG_RESP_AUTO_MODE_NONE +#define BNXT_LINK_AUTO_ALLSPDS PORT_PHY_QCFG_RESP_AUTO_MODE_ALL_SPEEDS +#define BNXT_LINK_AUTO_ONESPD PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_SPEED +#define BNXT_LINK_AUTO_ONEORBELOW PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_OR_BELOW +#define BNXT_LINK_AUTO_MSK PORT_PHY_QCFG_RESP_AUTO_MODE_MASK +#define PHY_VER_LEN 3 + u8 phy_ver[PHY_VER_LEN]; + u16 link_speed; +#define BNXT_LINK_SPEED_100MB PORT_PHY_QCFG_RESP_LINK_SPEED_100MB +#define BNXT_LINK_SPEED_1GB PORT_PHY_QCFG_RESP_LINK_SPEED_1GB +#define BNXT_LINK_SPEED_2GB PORT_PHY_QCFG_RESP_LINK_SPEED_2GB +#define BNXT_LINK_SPEED_2_5GB PORT_PHY_QCFG_RESP_LINK_SPEED_2_5GB +#define BNXT_LINK_SPEED_10GB PORT_PHY_QCFG_RESP_LINK_SPEED_10GB +#define BNXT_LINK_SPEED_20GB PORT_PHY_QCFG_RESP_LINK_SPEED_20GB +#define BNXT_LINK_SPEED_25GB PORT_PHY_QCFG_RESP_LINK_SPEED_25GB +#define BNXT_LINK_SPEED_40GB PORT_PHY_QCFG_RESP_LINK_SPEED_40GB +#define BNXT_LINK_SPEED_50GB PORT_PHY_QCFG_RESP_LINK_SPEED_50GB + u16 support_speeds; + u16 auto_link_speeds; +#define BNXT_LINK_SPEED_MSK_100MB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100MB +#define BNXT_LINK_SPEED_MSK_1GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_1GB +#define BNXT_LINK_SPEED_MSK_2GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_2GB +#define BNXT_LINK_SPEED_MSK_10GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_10GB +#define BNXT_LINK_SPEED_MSK_2_5GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_2_5GB +#define BNXT_LINK_SPEED_MSK_20GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_20GB +#define BNXT_LINK_SPEED_MSK_25GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_25GB +#define BNXT_LINK_SPEED_MSK_40GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_40GB +#define BNXT_LINK_SPEED_MSK_50GB PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB + u16 auto_link_speed; + u16 force_link_speed; + u32 preemphasis; + + /* copy of requested setting from ethtool cmd */ + u8 autoneg; +#define BNXT_AUTONEG_SPEED 1 +#define BNXT_AUTONEG_FLOW_CTRL 2 + u8 req_duplex; + u8 req_flow_ctrl; + u16 req_link_speed; + u32 advertising; + bool force_link_chng; + /* a copy of phy_qcfg output used to report link + * info to VF + */ + struct hwrm_port_phy_qcfg_output phy_qcfg_resp; +}; + +#define BNXT_MAX_QUEUE 8 + +struct bnxt_queue_info { + u8 queue_id; + u8 queue_profile; +}; + +struct bnxt { + void __iomem *bar0; + void __iomem *bar1; + void __iomem *bar2; + + u32 reg_base; + + struct net_device *dev; + struct pci_dev *pdev; + + atomic_t intr_sem; + + u32 flags; + #define BNXT_FLAG_DCB_ENABLED 0x1 + #define BNXT_FLAG_VF 0x2 + #define BNXT_FLAG_LRO 0x4 + #define BNXT_FLAG_GRO 0x8 + #define BNXT_FLAG_TPA (BNXT_FLAG_LRO | BNXT_FLAG_GRO) + #define BNXT_FLAG_JUMBO 0x10 + #define BNXT_FLAG_STRIP_VLAN 0x20 + #define BNXT_FLAG_AGG_RINGS (BNXT_FLAG_JUMBO | BNXT_FLAG_GRO | \ + BNXT_FLAG_LRO) + #define BNXT_FLAG_USING_MSIX 0x40 + #define BNXT_FLAG_MSIX_CAP 0x80 + #define BNXT_FLAG_RFS 0x100 + #define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA | \ + BNXT_FLAG_RFS | \ + BNXT_FLAG_STRIP_VLAN) + +#define BNXT_PF(bp) (!((bp)->flags & BNXT_FLAG_VF)) +#define BNXT_VF(bp) ((bp)->flags & BNXT_FLAG_VF) + + struct bnxt_napi **bnapi; + + u32 rx_buf_size; + u32 rx_buf_use_size; /* useable size */ + u32 rx_ring_size; + u32 rx_agg_ring_size; + u32 rx_copy_thresh; + u32 rx_ring_mask; + u32 rx_agg_ring_mask; + int rx_nr_pages; + int rx_agg_nr_pages; + int rx_nr_rings; + int rsscos_nr_ctxs; + + u32 tx_ring_size; + u32 tx_ring_mask; + int tx_nr_pages; + int tx_nr_rings; + int tx_nr_rings_per_tc; + + int tx_wake_thresh; + int tx_push_thresh; + int tx_push_size; + + u32 cp_ring_size; + u32 cp_ring_mask; + u32 cp_bit; + int cp_nr_pages; + int cp_nr_rings; + + int num_stat_ctxs; + struct bnxt_ring_grp_info *grp_info; + struct bnxt_vnic_info *vnic_info; + int nr_vnics; + + u8 max_tc; + struct bnxt_queue_info q_info[BNXT_MAX_QUEUE]; + + unsigned int current_interval; +#define BNXT_TIMER_INTERVAL (HZ / 2) + + struct timer_list timer; + + int state; +#define BNXT_STATE_CLOSED 0 +#define BNXT_STATE_OPEN 1 + + struct bnxt_irq *irq_tbl; + u8 mac_addr[ETH_ALEN]; + + u32 msg_enable; + + u16 hwrm_cmd_seq; + u32 hwrm_intr_seq_id; + void *hwrm_cmd_resp_addr; + dma_addr_t hwrm_cmd_resp_dma_addr; + void *hwrm_dbg_resp_addr; + dma_addr_t hwrm_dbg_resp_dma_addr; +#define HWRM_DBG_REG_BUF_SIZE 128 + struct mutex hwrm_cmd_lock; /* serialize hwrm messages */ + struct hwrm_ver_get_output ver_resp; +#define FW_VER_STR_LEN 32 +#define BC_HWRM_STR_LEN 21 +#define PHY_VER_STR_LEN (FW_VER_STR_LEN - BC_HWRM_STR_LEN) + char fw_ver_str[FW_VER_STR_LEN]; + __be16 vxlan_port; + u8 vxlan_port_cnt; + __le16 vxlan_fw_dst_port_id; + u8 nge_port_cnt; + __le16 nge_fw_dst_port_id; + u16 coal_ticks; + u16 coal_ticks_irq; + u16 coal_bufs; + u16 coal_bufs_irq; + +#define BNXT_USEC_TO_COAL_TIMER(x) ((x) * 25 / 2) +#define BNXT_COAL_TIMER_TO_USEC(x) ((x) * 2 / 25) + + struct work_struct sp_task; + unsigned long sp_event; +#define BNXT_RX_MASK_SP_EVENT 0 +#define BNXT_RX_NTP_FLTR_SP_EVENT 1 +#define BNXT_LINK_CHNG_SP_EVENT 2 +#define BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT 4 +#define BNXT_VXLAN_ADD_PORT_SP_EVENT 8 +#define BNXT_VXLAN_DEL_PORT_SP_EVENT 16 +#define BNXT_RESET_TASK_SP_EVENT 32 +#define BNXT_RST_RING_SP_EVENT 64 + +#ifdef CONFIG_BNXT_SRIOV + int nr_vfs; + struct bnxt_pf_info pf; + struct bnxt_vf_info vf; + wait_queue_head_t sriov_cfg_wait; + bool sriov_cfg; +#define BNXT_SRIOV_CFG_WAIT_TMO msecs_to_jiffies(10000) +#endif + +#define BNXT_NTP_FLTR_MAX_FLTR 4096 +#define BNXT_NTP_FLTR_HASH_SIZE 512 +#define BNXT_NTP_FLTR_HASH_MASK (BNXT_NTP_FLTR_HASH_SIZE - 1) + struct hlist_head ntp_fltr_hash_tbl[BNXT_NTP_FLTR_HASH_SIZE]; + spinlock_t ntp_fltr_lock; /* for hash table add, del */ + + unsigned long *ntp_fltr_bmap; + int ntp_fltr_count; + + struct bnxt_link_info link_info; +}; + +#ifdef CONFIG_NET_RX_BUSY_POLL +static inline void bnxt_enable_poll(struct bnxt_napi *bnapi) +{ + atomic_set(&bnapi->poll_state, BNXT_STATE_IDLE); +} + +/* called from the NAPI poll routine to get ownership of a bnapi */ +static inline bool bnxt_lock_napi(struct bnxt_napi *bnapi) +{ + int rc = atomic_cmpxchg(&bnapi->poll_state, BNXT_STATE_IDLE, + BNXT_STATE_NAPI); + + return rc == BNXT_STATE_IDLE; +} + +static inline void bnxt_unlock_napi(struct bnxt_napi *bnapi) +{ + atomic_set(&bnapi->poll_state, BNXT_STATE_IDLE); +} + +/* called from the busy poll routine to get ownership of a bnapi */ +static inline bool bnxt_lock_poll(struct bnxt_napi *bnapi) +{ + int rc = atomic_cmpxchg(&bnapi->poll_state, BNXT_STATE_IDLE, + BNXT_STATE_POLL); + + return rc == BNXT_STATE_IDLE; +} + +static inline void bnxt_unlock_poll(struct bnxt_napi *bnapi) +{ + atomic_set(&bnapi->poll_state, BNXT_STATE_IDLE); +} + +static inline bool bnxt_busy_polling(struct bnxt_napi *bnapi) +{ + return atomic_read(&bnapi->poll_state) == BNXT_STATE_POLL; +} + +static inline void bnxt_disable_poll(struct bnxt_napi *bnapi) +{ + int old; + + while (1) { + old = atomic_cmpxchg(&bnapi->poll_state, BNXT_STATE_IDLE, + BNXT_STATE_DISABLE); + if (old == BNXT_STATE_IDLE) + break; + usleep_range(500, 5000); + } +} + +#else + +static inline void bnxt_enable_poll(struct bnxt_napi *bnapi) +{ +} + +static inline bool bnxt_lock_napi(struct bnxt_napi *bnapi) +{ + return true; +} + +static inline void bnxt_unlock_napi(struct bnxt_napi *bnapi) +{ +} + +static inline bool bnxt_lock_poll(struct bnxt_napi *bnapi) +{ + return false; +} + +static inline void bnxt_unlock_poll(struct bnxt_napi *bnapi) +{ +} + +static inline bool bnxt_busy_polling(struct bnxt_napi *bnapi) +{ + return false; +} + +static inline void bnxt_disable_poll(struct bnxt_napi *bnapi) +{ +} + +#endif + +void bnxt_set_ring_params(struct bnxt *); +void bnxt_hwrm_cmd_hdr_init(struct bnxt *, void *, u16, u16, u16); +int _hwrm_send_message(struct bnxt *, void *, u32, int); +int hwrm_send_message(struct bnxt *, void *, u32, int); +int bnxt_hwrm_set_coal(struct bnxt *); +int bnxt_hwrm_set_pause(struct bnxt *); +int bnxt_hwrm_set_link_setting(struct bnxt *, bool); +int bnxt_open_nic(struct bnxt *, bool, bool); +int bnxt_close_nic(struct bnxt *, bool, bool); +void bnxt_get_max_rings(struct bnxt *, int *, int *); +#endif diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c new file mode 100644 index 000000000000..45bd628eaf3a --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -0,0 +1,1149 @@ +/* Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2014-2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include "bnxt_hsi.h" +#include "bnxt.h" +#include "bnxt_ethtool.h" +#include "bnxt_nvm_defs.h" /* NVRAM content constant and structure defs */ +#include "bnxt_fw_hdr.h" /* Firmware hdr constant and structure defs */ +#define FLASH_NVRAM_TIMEOUT ((HWRM_CMD_TIMEOUT) * 100) + +static u32 bnxt_get_msglevel(struct net_device *dev) +{ + struct bnxt *bp = netdev_priv(dev); + + return bp->msg_enable; +} + +static void bnxt_set_msglevel(struct net_device *dev, u32 value) +{ + struct bnxt *bp = netdev_priv(dev); + + bp->msg_enable = value; +} + +static int bnxt_get_coalesce(struct net_device *dev, + struct ethtool_coalesce *coal) +{ + struct bnxt *bp = netdev_priv(dev); + + memset(coal, 0, sizeof(*coal)); + + coal->rx_coalesce_usecs = + max_t(u16, BNXT_COAL_TIMER_TO_USEC(bp->coal_ticks), 1); + coal->rx_max_coalesced_frames = bp->coal_bufs / 2; + coal->rx_coalesce_usecs_irq = + max_t(u16, BNXT_COAL_TIMER_TO_USEC(bp->coal_ticks_irq), 1); + coal->rx_max_coalesced_frames_irq = bp->coal_bufs_irq / 2; + + return 0; +} + +static int bnxt_set_coalesce(struct net_device *dev, + struct ethtool_coalesce *coal) +{ + struct bnxt *bp = netdev_priv(dev); + int rc = 0; + + bp->coal_ticks = BNXT_USEC_TO_COAL_TIMER(coal->rx_coalesce_usecs); + bp->coal_bufs = coal->rx_max_coalesced_frames * 2; + bp->coal_ticks_irq = + BNXT_USEC_TO_COAL_TIMER(coal->rx_coalesce_usecs_irq); + bp->coal_bufs_irq = coal->rx_max_coalesced_frames_irq * 2; + + if (netif_running(dev)) + rc = bnxt_hwrm_set_coal(bp); + + return rc; +} + +#define BNXT_NUM_STATS 21 + +static int bnxt_get_sset_count(struct net_device *dev, int sset) +{ + struct bnxt *bp = netdev_priv(dev); + + switch (sset) { + case ETH_SS_STATS: + return BNXT_NUM_STATS * bp->cp_nr_rings; + default: + return -EOPNOTSUPP; + } +} + +static void bnxt_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *buf) +{ + u32 i, j = 0; + struct bnxt *bp = netdev_priv(dev); + u32 buf_size = sizeof(struct ctx_hw_stats) * bp->cp_nr_rings; + u32 stat_fields = sizeof(struct ctx_hw_stats) / 8; + + memset(buf, 0, buf_size); + + if (!bp->bnapi) + return; + + for (i = 0; i < bp->cp_nr_rings; i++) { + struct bnxt_napi *bnapi = bp->bnapi[i]; + struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; + __le64 *hw_stats = (__le64 *)cpr->hw_stats; + int k; + + for (k = 0; k < stat_fields; j++, k++) + buf[j] = le64_to_cpu(hw_stats[k]); + buf[j++] = cpr->rx_l4_csum_errors; + } +} + +static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf) +{ + struct bnxt *bp = netdev_priv(dev); + u32 i; + + switch (stringset) { + /* The number of strings must match BNXT_NUM_STATS defined above. */ + case ETH_SS_STATS: + for (i = 0; i < bp->cp_nr_rings; i++) { + sprintf(buf, "[%d]: rx_ucast_packets", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: rx_mcast_packets", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: rx_bcast_packets", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: rx_discards", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: rx_drops", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: rx_ucast_bytes", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: rx_mcast_bytes", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: rx_bcast_bytes", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: tx_ucast_packets", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: tx_mcast_packets", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: tx_bcast_packets", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: tx_discards", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: tx_drops", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: tx_ucast_bytes", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: tx_mcast_bytes", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: tx_bcast_bytes", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: tpa_packets", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: tpa_bytes", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: tpa_events", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: tpa_aborts", i); + buf += ETH_GSTRING_LEN; + sprintf(buf, "[%d]: rx_l4_csum_errors", i); + buf += ETH_GSTRING_LEN; + } + break; + default: + netdev_err(bp->dev, "bnxt_get_strings invalid request %x\n", + stringset); + break; + } +} + +static void bnxt_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ering) +{ + struct bnxt *bp = netdev_priv(dev); + + ering->rx_max_pending = BNXT_MAX_RX_DESC_CNT; + ering->rx_jumbo_max_pending = BNXT_MAX_RX_JUM_DESC_CNT; + ering->tx_max_pending = BNXT_MAX_TX_DESC_CNT; + + ering->rx_pending = bp->rx_ring_size; + ering->rx_jumbo_pending = bp->rx_agg_ring_size; + ering->tx_pending = bp->tx_ring_size; +} + +static int bnxt_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ering) +{ + struct bnxt *bp = netdev_priv(dev); + + if ((ering->rx_pending > BNXT_MAX_RX_DESC_CNT) || + (ering->tx_pending > BNXT_MAX_TX_DESC_CNT) || + (ering->tx_pending <= MAX_SKB_FRAGS)) + return -EINVAL; + + if (netif_running(dev)) + bnxt_close_nic(bp, false, false); + + bp->rx_ring_size = ering->rx_pending; + bp->tx_ring_size = ering->tx_pending; + bnxt_set_ring_params(bp); + + if (netif_running(dev)) + return bnxt_open_nic(bp, false, false); + + return 0; +} + +static void bnxt_get_channels(struct net_device *dev, + struct ethtool_channels *channel) +{ + struct bnxt *bp = netdev_priv(dev); + int max_rx_rings, max_tx_rings, tcs; + + bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings); + tcs = netdev_get_num_tc(dev); + if (tcs > 1) + max_tx_rings /= tcs; + + channel->max_rx = max_rx_rings; + channel->max_tx = max_tx_rings; + channel->max_other = 0; + channel->max_combined = 0; + channel->rx_count = bp->rx_nr_rings; + channel->tx_count = bp->tx_nr_rings_per_tc; +} + +static int bnxt_set_channels(struct net_device *dev, + struct ethtool_channels *channel) +{ + struct bnxt *bp = netdev_priv(dev); + int max_rx_rings, max_tx_rings, tcs; + u32 rc = 0; + + if (channel->other_count || channel->combined_count || + !channel->rx_count || !channel->tx_count) + return -EINVAL; + + bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings); + tcs = netdev_get_num_tc(dev); + if (tcs > 1) + max_tx_rings /= tcs; + + if (channel->rx_count > max_rx_rings || + channel->tx_count > max_tx_rings) + return -EINVAL; + + if (netif_running(dev)) { + if (BNXT_PF(bp)) { + /* TODO CHIMP_FW: Send message to all VF's + * before PF unload + */ + } + rc = bnxt_close_nic(bp, true, false); + if (rc) { + netdev_err(bp->dev, "Set channel failure rc :%x\n", + rc); + return rc; + } + } + + bp->rx_nr_rings = channel->rx_count; + bp->tx_nr_rings_per_tc = channel->tx_count; + bp->tx_nr_rings = bp->tx_nr_rings_per_tc; + if (tcs > 1) + bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs; + bp->cp_nr_rings = max_t(int, bp->tx_nr_rings, bp->rx_nr_rings); + bp->num_stat_ctxs = bp->cp_nr_rings; + + if (netif_running(dev)) { + rc = bnxt_open_nic(bp, true, false); + if ((!rc) && BNXT_PF(bp)) { + /* TODO CHIMP_FW: Send message to all VF's + * to renable + */ + } + } + + return rc; +} + +#ifdef CONFIG_RFS_ACCEL +static int bnxt_grxclsrlall(struct bnxt *bp, struct ethtool_rxnfc *cmd, + u32 *rule_locs) +{ + int i, j = 0; + + cmd->data = bp->ntp_fltr_count; + for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) { + struct hlist_head *head; + struct bnxt_ntuple_filter *fltr; + + head = &bp->ntp_fltr_hash_tbl[i]; + rcu_read_lock(); + hlist_for_each_entry_rcu(fltr, head, hash) { + if (j == cmd->rule_cnt) + break; + rule_locs[j++] = fltr->sw_id; + } + rcu_read_unlock(); + if (j == cmd->rule_cnt) + break; + } + cmd->rule_cnt = j; + return 0; +} + +static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd) +{ + struct ethtool_rx_flow_spec *fs = + (struct ethtool_rx_flow_spec *)&cmd->fs; + struct bnxt_ntuple_filter *fltr; + struct flow_keys *fkeys; + int i, rc = -EINVAL; + + if (fs->location < 0 || fs->location >= BNXT_NTP_FLTR_MAX_FLTR) + return rc; + + for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) { + struct hlist_head *head; + + head = &bp->ntp_fltr_hash_tbl[i]; + rcu_read_lock(); + hlist_for_each_entry_rcu(fltr, head, hash) { + if (fltr->sw_id == fs->location) + goto fltr_found; + } + rcu_read_unlock(); + } + return rc; + +fltr_found: + fkeys = &fltr->fkeys; + if (fkeys->basic.ip_proto == IPPROTO_TCP) + fs->flow_type = TCP_V4_FLOW; + else if (fkeys->basic.ip_proto == IPPROTO_UDP) + fs->flow_type = UDP_V4_FLOW; + else + goto fltr_err; + + fs->h_u.tcp_ip4_spec.ip4src = fkeys->addrs.v4addrs.src; + fs->m_u.tcp_ip4_spec.ip4src = cpu_to_be32(~0); + + fs->h_u.tcp_ip4_spec.ip4dst = fkeys->addrs.v4addrs.dst; + fs->m_u.tcp_ip4_spec.ip4dst = cpu_to_be32(~0); + + fs->h_u.tcp_ip4_spec.psrc = fkeys->ports.src; + fs->m_u.tcp_ip4_spec.psrc = cpu_to_be16(~0); + + fs->h_u.tcp_ip4_spec.pdst = fkeys->ports.dst; + fs->m_u.tcp_ip4_spec.pdst = cpu_to_be16(~0); + + fs->ring_cookie = fltr->rxq; + rc = 0; + +fltr_err: + rcu_read_unlock(); + + return rc; +} + +static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + u32 *rule_locs) +{ + struct bnxt *bp = netdev_priv(dev); + int rc = 0; + + switch (cmd->cmd) { + case ETHTOOL_GRXRINGS: + cmd->data = bp->rx_nr_rings; + break; + + case ETHTOOL_GRXCLSRLCNT: + cmd->rule_cnt = bp->ntp_fltr_count; + cmd->data = BNXT_NTP_FLTR_MAX_FLTR; + break; + + case ETHTOOL_GRXCLSRLALL: + rc = bnxt_grxclsrlall(bp, cmd, (u32 *)rule_locs); + break; + + case ETHTOOL_GRXCLSRULE: + rc = bnxt_grxclsrule(bp, cmd); + break; + + default: + rc = -EOPNOTSUPP; + break; + } + + return rc; +} +#endif + +static u32 bnxt_get_rxfh_indir_size(struct net_device *dev) +{ + return HW_HASH_INDEX_SIZE; +} + +static u32 bnxt_get_rxfh_key_size(struct net_device *dev) +{ + return HW_HASH_KEY_SIZE; +} + +static int bnxt_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, + u8 *hfunc) +{ + struct bnxt *bp = netdev_priv(dev); + struct bnxt_vnic_info *vnic = &bp->vnic_info[0]; + int i = 0; + + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + + if (indir) + for (i = 0; i < HW_HASH_INDEX_SIZE; i++) + indir[i] = le16_to_cpu(vnic->rss_table[i]); + + if (key) + memcpy(key, vnic->rss_hash_key, HW_HASH_KEY_SIZE); + + return 0; +} + +static void bnxt_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct bnxt *bp = netdev_priv(dev); + + strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver)); + strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); + strlcpy(info->fw_version, bp->fw_ver_str, sizeof(info->fw_version)); + strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info)); + info->n_stats = BNXT_NUM_STATS * bp->cp_nr_rings; + info->testinfo_len = BNXT_NUM_TESTS(bp); + /* TODO CHIMP_FW: eeprom dump details */ + info->eedump_len = 0; + /* TODO CHIMP FW: reg dump details */ + info->regdump_len = 0; +} + +static u32 bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info) +{ + u16 fw_speeds = link_info->support_speeds; + u32 speed_mask = 0; + + if (fw_speeds & BNXT_LINK_SPEED_MSK_100MB) + speed_mask |= SUPPORTED_100baseT_Full; + if (fw_speeds & BNXT_LINK_SPEED_MSK_1GB) + speed_mask |= SUPPORTED_1000baseT_Full; + if (fw_speeds & BNXT_LINK_SPEED_MSK_2_5GB) + speed_mask |= SUPPORTED_2500baseX_Full; + if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB) + speed_mask |= SUPPORTED_10000baseT_Full; + /* TODO: support 25GB, 50GB with different cable type */ + if (fw_speeds & BNXT_LINK_SPEED_MSK_20GB) + speed_mask |= SUPPORTED_20000baseMLD2_Full | + SUPPORTED_20000baseKR2_Full; + if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB) + speed_mask |= SUPPORTED_40000baseKR4_Full | + SUPPORTED_40000baseCR4_Full | + SUPPORTED_40000baseSR4_Full | + SUPPORTED_40000baseLR4_Full; + + return speed_mask; +} + +static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info) +{ + u16 fw_speeds = link_info->auto_link_speeds; + u32 speed_mask = 0; + + /* TODO: support 25GB, 40GB, 50GB with different cable type */ + /* set the advertised speeds */ + if (fw_speeds & BNXT_LINK_SPEED_MSK_100MB) + speed_mask |= ADVERTISED_100baseT_Full; + if (fw_speeds & BNXT_LINK_SPEED_MSK_1GB) + speed_mask |= ADVERTISED_1000baseT_Full; + if (fw_speeds & BNXT_LINK_SPEED_MSK_2_5GB) + speed_mask |= ADVERTISED_2500baseX_Full; + if (fw_speeds & BNXT_LINK_SPEED_MSK_10GB) + speed_mask |= ADVERTISED_10000baseT_Full; + /* TODO: how to advertise 20, 25, 40, 50GB with different cable type ?*/ + if (fw_speeds & BNXT_LINK_SPEED_MSK_20GB) + speed_mask |= ADVERTISED_20000baseMLD2_Full | + ADVERTISED_20000baseKR2_Full; + if (fw_speeds & BNXT_LINK_SPEED_MSK_40GB) + speed_mask |= ADVERTISED_40000baseKR4_Full | + ADVERTISED_40000baseCR4_Full | + ADVERTISED_40000baseSR4_Full | + ADVERTISED_40000baseLR4_Full; + return speed_mask; +} + +u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed) +{ + switch (fw_link_speed) { + case BNXT_LINK_SPEED_100MB: + return SPEED_100; + case BNXT_LINK_SPEED_1GB: + return SPEED_1000; + case BNXT_LINK_SPEED_2_5GB: + return SPEED_2500; + case BNXT_LINK_SPEED_10GB: + return SPEED_10000; + case BNXT_LINK_SPEED_20GB: + return SPEED_20000; + case BNXT_LINK_SPEED_25GB: + return SPEED_25000; + case BNXT_LINK_SPEED_40GB: + return SPEED_40000; + case BNXT_LINK_SPEED_50GB: + return SPEED_50000; + default: + return SPEED_UNKNOWN; + } +} + +static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct bnxt *bp = netdev_priv(dev); + struct bnxt_link_info *link_info = &bp->link_info; + u16 ethtool_speed; + + cmd->supported = bnxt_fw_to_ethtool_support_spds(link_info); + + if (link_info->auto_link_speeds) + cmd->supported |= SUPPORTED_Autoneg; + + if (BNXT_AUTO_MODE(link_info->auto_mode)) { + cmd->advertising = + bnxt_fw_to_ethtool_advertised_spds(link_info); + cmd->advertising |= ADVERTISED_Autoneg; + cmd->autoneg = AUTONEG_ENABLE; + } else { + cmd->autoneg = AUTONEG_DISABLE; + cmd->advertising = 0; + } + if (link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) { + if ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_BOTH) == + BNXT_LINK_PAUSE_BOTH) { + cmd->advertising |= ADVERTISED_Pause; + cmd->supported |= SUPPORTED_Pause; + } else { + cmd->advertising |= ADVERTISED_Asym_Pause; + cmd->supported |= SUPPORTED_Asym_Pause; + if (link_info->auto_pause_setting & + BNXT_LINK_PAUSE_RX) + cmd->advertising |= ADVERTISED_Pause; + } + } else if (link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) { + if ((link_info->force_pause_setting & BNXT_LINK_PAUSE_BOTH) == + BNXT_LINK_PAUSE_BOTH) { + cmd->supported |= SUPPORTED_Pause; + } else { + cmd->supported |= SUPPORTED_Asym_Pause; + if (link_info->force_pause_setting & + BNXT_LINK_PAUSE_RX) + cmd->supported |= SUPPORTED_Pause; + } + } + + cmd->port = PORT_NONE; + if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) { + cmd->port = PORT_TP; + cmd->supported |= SUPPORTED_TP; + cmd->advertising |= ADVERTISED_TP; + } else { + cmd->supported |= SUPPORTED_FIBRE; + cmd->advertising |= ADVERTISED_FIBRE; + + if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC) + cmd->port = PORT_DA; + else if (link_info->media_type == + PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE) + cmd->port = PORT_FIBRE; + } + + if (link_info->phy_link_status == BNXT_LINK_LINK) { + if (link_info->duplex & BNXT_LINK_DUPLEX_FULL) + cmd->duplex = DUPLEX_FULL; + } else { + cmd->duplex = DUPLEX_UNKNOWN; + } + ethtool_speed = bnxt_fw_to_ethtool_speed(link_info->link_speed); + ethtool_cmd_speed_set(cmd, ethtool_speed); + if (link_info->transceiver == + PORT_PHY_QCFG_RESP_TRANSCEIVER_TYPE_XCVR_INTERNAL) + cmd->transceiver = XCVR_INTERNAL; + else + cmd->transceiver = XCVR_EXTERNAL; + cmd->phy_address = link_info->phy_addr; + + return 0; +} + +static u32 bnxt_get_fw_speed(struct net_device *dev, u16 ethtool_speed) +{ + switch (ethtool_speed) { + case SPEED_100: + return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_100MB; + case SPEED_1000: + return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_1GB; + case SPEED_2500: + return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_2_5GB; + case SPEED_10000: + return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_10GB; + case SPEED_20000: + return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_20GB; + case SPEED_25000: + return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_25GB; + case SPEED_40000: + return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_40GB; + case SPEED_50000: + return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_50GB; + default: + netdev_err(dev, "unsupported speed!\n"); + break; + } + return 0; +} + +static u16 bnxt_get_fw_auto_link_speeds(u32 advertising) +{ + u16 fw_speed_mask = 0; + + /* only support autoneg at speed 100, 1000, and 10000 */ + if (advertising & (ADVERTISED_100baseT_Full | + ADVERTISED_100baseT_Half)) { + fw_speed_mask |= BNXT_LINK_SPEED_MSK_100MB; + } + if (advertising & (ADVERTISED_1000baseT_Full | + ADVERTISED_1000baseT_Half)) { + fw_speed_mask |= BNXT_LINK_SPEED_MSK_1GB; + } + if (advertising & ADVERTISED_10000baseT_Full) + fw_speed_mask |= BNXT_LINK_SPEED_MSK_10GB; + + return fw_speed_mask; +} + +static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + int rc = 0; + struct bnxt *bp = netdev_priv(dev); + struct bnxt_link_info *link_info = &bp->link_info; + u32 speed, fw_advertising = 0; + bool set_pause = false; + + if (BNXT_VF(bp)) + return rc; + + if (cmd->autoneg == AUTONEG_ENABLE) { + if (link_info->media_type != PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) { + netdev_err(dev, "Media type doesn't support autoneg\n"); + rc = -EINVAL; + goto set_setting_exit; + } + if (cmd->advertising & ~(BNXT_ALL_COPPER_ETHTOOL_SPEED | + ADVERTISED_Autoneg | + ADVERTISED_TP | + ADVERTISED_Pause | + ADVERTISED_Asym_Pause)) { + netdev_err(dev, "Unsupported advertising mask (adv: 0x%x)\n", + cmd->advertising); + rc = -EINVAL; + goto set_setting_exit; + } + fw_advertising = bnxt_get_fw_auto_link_speeds(cmd->advertising); + if (fw_advertising & ~link_info->support_speeds) { + netdev_err(dev, "Advertising parameters are not supported! (adv: 0x%x)\n", + cmd->advertising); + rc = -EINVAL; + goto set_setting_exit; + } + link_info->autoneg |= BNXT_AUTONEG_SPEED; + if (!fw_advertising) + link_info->advertising = link_info->support_speeds; + else + link_info->advertising = fw_advertising; + /* any change to autoneg will cause link change, therefore the + * driver should put back the original pause setting in autoneg + */ + set_pause = true; + } else { + /* TODO: currently don't support half duplex */ + if (cmd->duplex == DUPLEX_HALF) { + netdev_err(dev, "HALF DUPLEX is not supported!\n"); + rc = -EINVAL; + goto set_setting_exit; + } + /* If received a request for an unknown duplex, assume full*/ + if (cmd->duplex == DUPLEX_UNKNOWN) + cmd->duplex = DUPLEX_FULL; + speed = ethtool_cmd_speed(cmd); + link_info->req_link_speed = bnxt_get_fw_speed(dev, speed); + link_info->req_duplex = BNXT_LINK_DUPLEX_FULL; + link_info->autoneg &= ~BNXT_AUTONEG_SPEED; + link_info->advertising = 0; + } + + if (netif_running(dev)) + rc = bnxt_hwrm_set_link_setting(bp, set_pause); + +set_setting_exit: + return rc; +} + +static void bnxt_get_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *epause) +{ + struct bnxt *bp = netdev_priv(dev); + struct bnxt_link_info *link_info = &bp->link_info; + + if (BNXT_VF(bp)) + return; + epause->autoneg = !!(link_info->auto_pause_setting & + BNXT_LINK_PAUSE_BOTH); + epause->rx_pause = ((link_info->pause & BNXT_LINK_PAUSE_RX) != 0); + epause->tx_pause = ((link_info->pause & BNXT_LINK_PAUSE_TX) != 0); +} + +static int bnxt_set_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *epause) +{ + int rc = 0; + struct bnxt *bp = netdev_priv(dev); + struct bnxt_link_info *link_info = &bp->link_info; + + if (BNXT_VF(bp)) + return rc; + + if (epause->autoneg) { + link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL; + link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_BOTH; + } else { + /* when transition from auto pause to force pause, + * force a link change + */ + if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) + link_info->force_link_chng = true; + link_info->autoneg &= ~BNXT_AUTONEG_FLOW_CTRL; + link_info->req_flow_ctrl &= ~BNXT_LINK_PAUSE_BOTH; + } + if (epause->rx_pause) + link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_RX; + else + link_info->req_flow_ctrl &= ~BNXT_LINK_PAUSE_RX; + + if (epause->tx_pause) + link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_TX; + else + link_info->req_flow_ctrl &= ~BNXT_LINK_PAUSE_TX; + + if (netif_running(dev)) + rc = bnxt_hwrm_set_pause(bp); + return rc; +} + +static u32 bnxt_get_link(struct net_device *dev) +{ + struct bnxt *bp = netdev_priv(dev); + + /* TODO: handle MF, VF, driver close case */ + return bp->link_info.link_up; +} + +static int bnxt_flash_nvram(struct net_device *dev, + u16 dir_type, + u16 dir_ordinal, + u16 dir_ext, + u16 dir_attr, + const u8 *data, + size_t data_len) +{ + struct bnxt *bp = netdev_priv(dev); + int rc; + struct hwrm_nvm_write_input req = {0}; + dma_addr_t dma_handle; + u8 *kmem; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_WRITE, -1, -1); + + req.dir_type = cpu_to_le16(dir_type); + req.dir_ordinal = cpu_to_le16(dir_ordinal); + req.dir_ext = cpu_to_le16(dir_ext); + req.dir_attr = cpu_to_le16(dir_attr); + req.dir_data_length = cpu_to_le32(data_len); + + kmem = dma_alloc_coherent(&bp->pdev->dev, data_len, &dma_handle, + GFP_KERNEL); + if (!kmem) { + netdev_err(dev, "dma_alloc_coherent failure, length = %u\n", + (unsigned)data_len); + return -ENOMEM; + } + memcpy(kmem, data, data_len); + req.host_src_addr = cpu_to_le64(dma_handle); + + rc = hwrm_send_message(bp, &req, sizeof(req), FLASH_NVRAM_TIMEOUT); + dma_free_coherent(&bp->pdev->dev, data_len, kmem, dma_handle); + + return rc; +} + +static int bnxt_flash_firmware(struct net_device *dev, + u16 dir_type, + const u8 *fw_data, + size_t fw_size) +{ + int rc = 0; + u16 code_type; + u32 stored_crc; + u32 calculated_crc; + struct bnxt_fw_header *header = (struct bnxt_fw_header *)fw_data; + + switch (dir_type) { + case BNX_DIR_TYPE_BOOTCODE: + case BNX_DIR_TYPE_BOOTCODE_2: + code_type = CODE_BOOT; + break; + default: + netdev_err(dev, "Unsupported directory entry type: %u\n", + dir_type); + return -EINVAL; + } + if (fw_size < sizeof(struct bnxt_fw_header)) { + netdev_err(dev, "Invalid firmware file size: %u\n", + (unsigned int)fw_size); + return -EINVAL; + } + if (header->signature != cpu_to_le32(BNXT_FIRMWARE_BIN_SIGNATURE)) { + netdev_err(dev, "Invalid firmware signature: %08X\n", + le32_to_cpu(header->signature)); + return -EINVAL; + } + if (header->code_type != code_type) { + netdev_err(dev, "Expected firmware type: %d, read: %d\n", + code_type, header->code_type); + return -EINVAL; + } + if (header->device != DEVICE_CUMULUS_FAMILY) { + netdev_err(dev, "Expected firmware device family %d, read: %d\n", + DEVICE_CUMULUS_FAMILY, header->device); + return -EINVAL; + } + /* Confirm the CRC32 checksum of the file: */ + stored_crc = le32_to_cpu(*(__le32 *)(fw_data + fw_size - + sizeof(stored_crc))); + calculated_crc = ~crc32(~0, fw_data, fw_size - sizeof(stored_crc)); + if (calculated_crc != stored_crc) { + netdev_err(dev, "Firmware file CRC32 checksum (%08lX) does not match calculated checksum (%08lX)\n", + (unsigned long)stored_crc, + (unsigned long)calculated_crc); + return -EINVAL; + } + /* TODO: Validate digital signature (RSA-encrypted SHA-256 hash) here */ + rc = bnxt_flash_nvram(dev, dir_type, BNX_DIR_ORDINAL_FIRST, + 0, 0, fw_data, fw_size); + if (rc == 0) { /* Firmware update successful */ + /* TODO: Notify processor it needs to reset itself + */ + } + return rc; +} + +static bool bnxt_dir_type_is_ape_bin_format(u16 dir_type) +{ + switch (dir_type) { + case BNX_DIR_TYPE_CHIMP_PATCH: + case BNX_DIR_TYPE_BOOTCODE: + case BNX_DIR_TYPE_BOOTCODE_2: + case BNX_DIR_TYPE_APE_FW: + case BNX_DIR_TYPE_APE_PATCH: + case BNX_DIR_TYPE_KONG_FW: + case BNX_DIR_TYPE_KONG_PATCH: + return true; + } + + return false; +} + +static bool bnxt_dir_type_is_unprotected_exec_format(u16 dir_type) +{ + switch (dir_type) { + case BNX_DIR_TYPE_AVS: + case BNX_DIR_TYPE_EXP_ROM_MBA: + case BNX_DIR_TYPE_PCIE: + case BNX_DIR_TYPE_TSCF_UCODE: + case BNX_DIR_TYPE_EXT_PHY: + case BNX_DIR_TYPE_CCM: + case BNX_DIR_TYPE_ISCSI_BOOT: + case BNX_DIR_TYPE_ISCSI_BOOT_IPV6: + case BNX_DIR_TYPE_ISCSI_BOOT_IPV4N6: + return true; + } + + return false; +} + +static bool bnxt_dir_type_is_executable(u16 dir_type) +{ + return bnxt_dir_type_is_ape_bin_format(dir_type) || + bnxt_dir_type_is_unprotected_exec_format(dir_type); +} + +static int bnxt_flash_firmware_from_file(struct net_device *dev, + u16 dir_type, + const char *filename) +{ + const struct firmware *fw; + int rc; + + if (bnxt_dir_type_is_executable(dir_type) == false) + return -EINVAL; + + rc = request_firmware(&fw, filename, &dev->dev); + if (rc != 0) { + netdev_err(dev, "Error %d requesting firmware file: %s\n", + rc, filename); + return rc; + } + if (bnxt_dir_type_is_ape_bin_format(dir_type) == true) + rc = bnxt_flash_firmware(dev, dir_type, fw->data, fw->size); + else + rc = bnxt_flash_nvram(dev, dir_type, BNX_DIR_ORDINAL_FIRST, + 0, 0, fw->data, fw->size); + release_firmware(fw); + return rc; +} + +static int bnxt_flash_package_from_file(struct net_device *dev, + char *filename) +{ + netdev_err(dev, "packages are not yet supported\n"); + return -EINVAL; +} + +static int bnxt_flash_device(struct net_device *dev, + struct ethtool_flash *flash) +{ + if (!BNXT_PF((struct bnxt *)netdev_priv(dev))) { + netdev_err(dev, "flashdev not supported from a virtual function\n"); + return -EINVAL; + } + + if (flash->region == ETHTOOL_FLASH_ALL_REGIONS) + return bnxt_flash_package_from_file(dev, flash->data); + + return bnxt_flash_firmware_from_file(dev, flash->region, flash->data); +} + +static int nvm_get_dir_info(struct net_device *dev, u32 *entries, u32 *length) +{ + struct bnxt *bp = netdev_priv(dev); + int rc; + struct hwrm_nvm_get_dir_info_input req = {0}; + struct hwrm_nvm_get_dir_info_output *output = bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_DIR_INFO, -1, -1); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (!rc) { + *entries = le32_to_cpu(output->entries); + *length = le32_to_cpu(output->entry_length); + } + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_get_eeprom_len(struct net_device *dev) +{ + /* The -1 return value allows the entire 32-bit range of offsets to be + * passed via the ethtool command-line utility. + */ + return -1; +} + +static int bnxt_get_nvram_directory(struct net_device *dev, u32 len, u8 *data) +{ + struct bnxt *bp = netdev_priv(dev); + int rc; + u32 dir_entries; + u32 entry_length; + u8 *buf; + size_t buflen; + dma_addr_t dma_handle; + struct hwrm_nvm_get_dir_entries_input req = {0}; + + rc = nvm_get_dir_info(dev, &dir_entries, &entry_length); + if (rc != 0) + return rc; + + /* Insert 2 bytes of directory info (count and size of entries) */ + if (len < 2) + return -EINVAL; + + *data++ = dir_entries; + *data++ = entry_length; + len -= 2; + memset(data, 0xff, len); + + buflen = dir_entries * entry_length; + buf = dma_alloc_coherent(&bp->pdev->dev, buflen, &dma_handle, + GFP_KERNEL); + if (!buf) { + netdev_err(dev, "dma_alloc_coherent failure, length = %u\n", + (unsigned)buflen); + return -ENOMEM; + } + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_DIR_ENTRIES, -1, -1); + req.host_dest_addr = cpu_to_le64(dma_handle); + rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc == 0) + memcpy(data, buf, len > buflen ? buflen : len); + dma_free_coherent(&bp->pdev->dev, buflen, buf, dma_handle); + return rc; +} + +static int bnxt_get_nvram_item(struct net_device *dev, u32 index, u32 offset, + u32 length, u8 *data) +{ + struct bnxt *bp = netdev_priv(dev); + int rc; + u8 *buf; + dma_addr_t dma_handle; + struct hwrm_nvm_read_input req = {0}; + + buf = dma_alloc_coherent(&bp->pdev->dev, length, &dma_handle, + GFP_KERNEL); + if (!buf) { + netdev_err(dev, "dma_alloc_coherent failure, length = %u\n", + (unsigned)length); + return -ENOMEM; + } + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_READ, -1, -1); + req.host_dest_addr = cpu_to_le64(dma_handle); + req.dir_idx = cpu_to_le16(index); + req.offset = cpu_to_le32(offset); + req.len = cpu_to_le32(length); + + rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc == 0) + memcpy(data, buf, length); + dma_free_coherent(&bp->pdev->dev, length, buf, dma_handle); + return rc; +} + +static int bnxt_get_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, + u8 *data) +{ + u32 index; + u32 offset; + + if (eeprom->offset == 0) /* special offset value to get directory */ + return bnxt_get_nvram_directory(dev, eeprom->len, data); + + index = eeprom->offset >> 24; + offset = eeprom->offset & 0xffffff; + + if (index == 0) { + netdev_err(dev, "unsupported index value: %d\n", index); + return -EINVAL; + } + + return bnxt_get_nvram_item(dev, index - 1, offset, eeprom->len, data); +} + +static int bnxt_erase_nvram_directory(struct net_device *dev, u8 index) +{ + struct bnxt *bp = netdev_priv(dev); + struct hwrm_nvm_erase_dir_entry_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_ERASE_DIR_ENTRY, -1, -1); + req.dir_idx = cpu_to_le16(index); + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + +static int bnxt_set_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, + u8 *data) +{ + struct bnxt *bp = netdev_priv(dev); + u8 index, dir_op; + u16 type, ext, ordinal, attr; + + if (!BNXT_PF(bp)) { + netdev_err(dev, "NVM write not supported from a virtual function\n"); + return -EINVAL; + } + + type = eeprom->magic >> 16; + + if (type == 0xffff) { /* special value for directory operations */ + index = eeprom->magic & 0xff; + dir_op = eeprom->magic >> 8; + if (index == 0) + return -EINVAL; + switch (dir_op) { + case 0x0e: /* erase */ + if (eeprom->offset != ~eeprom->magic) + return -EINVAL; + return bnxt_erase_nvram_directory(dev, index - 1); + default: + return -EINVAL; + } + } + + /* Create or re-write an NVM item: */ + if (bnxt_dir_type_is_executable(type) == true) + return -EINVAL; + ext = eeprom->magic & 0xffff; + ordinal = eeprom->offset >> 16; + attr = eeprom->offset & 0xffff; + + return bnxt_flash_nvram(dev, type, ordinal, ext, attr, data, + eeprom->len); +} + +const struct ethtool_ops bnxt_ethtool_ops = { + .get_settings = bnxt_get_settings, + .set_settings = bnxt_set_settings, + .get_pauseparam = bnxt_get_pauseparam, + .set_pauseparam = bnxt_set_pauseparam, + .get_drvinfo = bnxt_get_drvinfo, + .get_coalesce = bnxt_get_coalesce, + .set_coalesce = bnxt_set_coalesce, + .get_msglevel = bnxt_get_msglevel, + .set_msglevel = bnxt_set_msglevel, + .get_sset_count = bnxt_get_sset_count, + .get_strings = bnxt_get_strings, + .get_ethtool_stats = bnxt_get_ethtool_stats, + .set_ringparam = bnxt_set_ringparam, + .get_ringparam = bnxt_get_ringparam, + .get_channels = bnxt_get_channels, + .set_channels = bnxt_set_channels, +#ifdef CONFIG_RFS_ACCEL + .get_rxnfc = bnxt_get_rxnfc, +#endif + .get_rxfh_indir_size = bnxt_get_rxfh_indir_size, + .get_rxfh_key_size = bnxt_get_rxfh_key_size, + .get_rxfh = bnxt_get_rxfh, + .flash_device = bnxt_flash_device, + .get_eeprom_len = bnxt_get_eeprom_len, + .get_eeprom = bnxt_get_eeprom, + .set_eeprom = bnxt_set_eeprom, + .get_link = bnxt_get_link, +}; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h new file mode 100644 index 000000000000..98fa81e08b58 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h @@ -0,0 +1,17 @@ +/* Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2014-2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + */ + +#ifndef BNXT_ETHTOOL_H +#define BNXT_ETHTOOL_H + +extern const struct ethtool_ops bnxt_ethtool_ops; + +u32 bnxt_fw_to_ethtool_speed(u16); + +#endif diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h new file mode 100644 index 000000000000..e0aac65c6d82 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_fw_hdr.h @@ -0,0 +1,104 @@ +/* Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2014-2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + */ + +#ifndef __BNXT_FW_HDR_H__ +#define __BNXT_FW_HDR_H__ + +#define BNXT_FIRMWARE_BIN_SIGNATURE 0x1a4d4342 /* "BCM"+0x1a */ + +enum SUPPORTED_FAMILY { + DEVICE_5702_3_4_FAMILY, /* 0 - Denali, Vinson, K2 */ + DEVICE_5705_FAMILY, /* 1 - Bachelor */ + DEVICE_SHASTA_FAMILY, /* 2 - 5751 */ + DEVICE_5706_FAMILY, /* 3 - Teton */ + DEVICE_5714_FAMILY, /* 4 - Hamilton */ + DEVICE_STANFORD_FAMILY, /* 5 - 5755 */ + DEVICE_STANFORD_ME_FAMILY, /* 6 - 5756 */ + DEVICE_SOLEDAD_FAMILY, /* 7 - 5761[E] */ + DEVICE_CILAI_FAMILY, /* 8 - 57780/60/90/91 */ + DEVICE_ASPEN_FAMILY, /* 9 - 57781/85/61/65/91/95 */ + DEVICE_ASPEN_PLUS_FAMILY, /* 10 - 57786 */ + DEVICE_LOGAN_FAMILY, /* 11 - Any device in the Logan family + */ + DEVICE_LOGAN_5762, /* 12 - Logan Enterprise (aka Columbia) + */ + DEVICE_LOGAN_57767, /* 13 - Logan Client */ + DEVICE_LOGAN_57787, /* 14 - Logan Consumer */ + DEVICE_LOGAN_5725, /* 15 - Logan Server (TruManage-enabled) + */ + DEVICE_SAWTOOTH_FAMILY, /* 16 - 5717/18 */ + DEVICE_COTOPAXI_FAMILY, /* 17 - 5719 */ + DEVICE_SNAGGLETOOTH_FAMILY, /* 18 - 5720 */ + DEVICE_CUMULUS_FAMILY, /* 19 - Cumulus/Whitney */ + MAX_DEVICE_FAMILY +}; + +enum SUPPORTED_CODE { + CODE_ASF1, /* 0 - ASF VERSION 1.03 */ + CODE_ASF2, /* 1 - ASF VERSION 2.00 */ + CODE_PASSTHRU, /* 2 - PassThru */ + CODE_PT_SEC, /* 3 - PassThru with security */ + CODE_UMP, /* 4 - UMP */ + CODE_BOOT, /* 5 - Bootcode */ + CODE_DASH, /* 6 - TruManage (DASH + ASF + PMCI) + * Management firmwares + */ + CODE_MCTP_PASSTHRU, /* 7 - NCSI / MCTP Passt-hrough firmware */ + CODE_PM_OFFLOAD, /* 8 - Power-Management Proxy Offload firmwares + */ + CODE_MDNS_SD_OFFLOAD, /* 9 - Multicast DNS Service Discovery Proxys + * Offload firmware + */ + CODE_DISC_OFFLOAD, /* 10 - Discovery Offload firmware */ + CODE_MUSTANG, /* 11 - I2C Error reporting APE firmwares + * + */ + CODE_ARP_BATCH, /* 12 - ARP Batch firmware */ + CODE_SMASH, /* 13 - TruManage (SMASH + DCMI/IPMI + PMCI) + * Management firmware + */ + CODE_APE_DIAG, /* 14 - APE Test Diag firmware */ + CODE_APE_PATCH, /* 15 - APE Patch firmware */ + CODE_TANG_PATCH, /* 16 - TANG Patch firmware */ + CODE_KONG_FW, /* 17 - KONG firmware */ + CODE_KONG_PATCH, /* 18 - KONG Patch firmware */ + CODE_BONO_FW, /* 19 - BONO firmware */ + CODE_BONO_PATCH, /* 20 - BONO Patch firmware */ + + MAX_CODE_TYPE, +}; + +enum SUPPORTED_MEDIA { + MEDIA_COPPER, /* 0 */ + MEDIA_FIBER, /* 1 */ + MEDIA_NONE, /* 2 */ + MEDIA_COPPER_FIBER, /* 3 */ + MAX_MEDIA_TYPE, +}; + +struct bnxt_fw_header { + __le32 signature; /* constains the constant value of + * BNXT_Firmware_Bin_Signatures + */ + u8 flags; /* reserved for ChiMP use */ + u8 code_type; /* enum SUPPORTED_CODE */ + u8 device; /* enum SUPPORTED_FAMILY */ + u8 media; /* enum SUPPORTED_MEDIA */ + u8 version[16]; /* the null terminated version string to + * indicate the version of the + * file, this will be copied from the binary + * file version string + */ + u8 build; + u8 revision; + u8 minor_ver; + u8 major_ver; +}; + +#endif diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h new file mode 100644 index 000000000000..70fc8253c07f --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h @@ -0,0 +1,4046 @@ +/* Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2014-2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + */ + +#ifndef BNXT_HSI_H +#define BNXT_HSI_H + +/* per-context HW statistics -- chip view */ +struct ctx_hw_stats { + __le64 rx_ucast_pkts; + __le64 rx_mcast_pkts; + __le64 rx_bcast_pkts; + __le64 rx_discard_pkts; + __le64 rx_drop_pkts; + __le64 rx_ucast_bytes; + __le64 rx_mcast_bytes; + __le64 rx_bcast_bytes; + __le64 tx_ucast_pkts; + __le64 tx_mcast_pkts; + __le64 tx_bcast_pkts; + __le64 tx_discard_pkts; + __le64 tx_drop_pkts; + __le64 tx_ucast_bytes; + __le64 tx_mcast_bytes; + __le64 tx_bcast_bytes; + __le64 tpa_pkts; + __le64 tpa_bytes; + __le64 tpa_events; + __le64 tpa_aborts; +}; + +/* Statistics Ejection Buffer Completion Record (16 bytes) */ +struct eject_cmpl { + __le16 type; + #define EJECT_CMPL_TYPE_MASK 0x3fUL + #define EJECT_CMPL_TYPE_SFT 0 + #define EJECT_CMPL_TYPE_STAT_EJECT (0x1aUL << 0) + __le16 len; + __le32 opaque; + __le32 v; + #define EJECT_CMPL_V 0x1UL + __le32 unused_2; +}; + +/* HWRM Completion Record (16 bytes) */ +struct hwrm_cmpl { + __le16 type; + #define HWRM_CMPL_TYPE_MASK 0x3fUL + #define HWRM_CMPL_TYPE_SFT 0 + #define HWRM_CMPL_TYPE_HWRM_DONE (0x20UL << 0) + __le16 sequence_id; + __le32 unused_1; + __le32 v; + #define HWRM_CMPL_V 0x1UL + __le32 unused_3; +}; + +/* HWRM Forwarded Request (16 bytes) */ +struct hwrm_fwd_req_cmpl { + __le16 req_len_type; + #define HWRM_FWD_REQ_CMPL_TYPE_MASK 0x3fUL + #define HWRM_FWD_REQ_CMPL_TYPE_SFT 0 + #define HWRM_FWD_REQ_CMPL_TYPE_HWRM_FWD_REQ (0x22UL << 0) + #define HWRM_FWD_REQ_CMPL_REQ_LEN_MASK 0xffc0UL + #define HWRM_FWD_REQ_CMPL_REQ_LEN_SFT 6 + __le16 source_id; + __le32 unused_0; + __le32 req_buf_addr_v[2]; + #define HWRM_FWD_REQ_CMPL_V 0x1UL + #define HWRM_FWD_REQ_CMPL_REQ_BUF_ADDR_MASK 0xfffffffeUL + #define HWRM_FWD_REQ_CMPL_REQ_BUF_ADDR_SFT 1 +}; + +/* HWRM Forwarded Response (16 bytes) */ +struct hwrm_fwd_resp_cmpl { + __le16 type; + #define HWRM_FWD_RESP_CMPL_TYPE_MASK 0x3fUL + #define HWRM_FWD_RESP_CMPL_TYPE_SFT 0 + #define HWRM_FWD_RESP_CMPL_TYPE_HWRM_FWD_RESP (0x24UL << 0) + __le16 source_id; + __le16 resp_len; + __le16 unused_1; + __le32 resp_buf_addr_v[2]; + #define HWRM_FWD_RESP_CMPL_V 0x1UL + #define HWRM_FWD_RESP_CMPL_RESP_BUF_ADDR_MASK 0xfffffffeUL + #define HWRM_FWD_RESP_CMPL_RESP_BUF_ADDR_SFT 1 +}; + +/* HWRM Asynchronous Event Completion Record (16 bytes) */ +struct hwrm_async_event_cmpl { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE (0x0UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE (0x1UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE (0x2UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE (0x3UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED (0x4UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD (0x10UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD (0x11UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD (0x20UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD (0x20UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR (0x30UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE (0x31UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR (0xffUL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; +}; + +/* HWRM Asynchronous Event Completion Record for link status change (16 bytes) */ +struct hwrm_async_event_cmpl_link_status_change { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_ID_LINK_STATUS_CHANGE (0x0UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_UP 0x1UL +}; + +/* HWRM Asynchronous Event Completion Record for link MTU change (16 bytes) */ +struct hwrm_async_event_cmpl_link_mtu_change { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_ID_LINK_MTU_CHANGE (0x1UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_MASK 0xffffUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_SFT 0 +}; + +/* HWRM Asynchronous Event Completion Record for link speed change (16 bytes) */ +struct hwrm_async_event_cmpl_link_speed_change { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_ID_LINK_SPEED_CHANGE (0x2UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_FORCE 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_MASK 0xfffeUL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_SFT 1 + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100MB (0x1UL << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_1GB (0xaUL << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2GB (0x14UL << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2_5GB (0x19UL << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_10GB (0x64UL << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_20GB (0xc8UL << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_25GB (0xfaUL << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_40GB (0x190UL << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_50GB (0x1f4UL << 1) + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffff0000UL + #define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_SFT 16 +}; + +/* HWRM Asynchronous Event Completion Record for DCB Config change (16 bytes) */ +struct hwrm_async_event_cmpl_dcb_config_change { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_ID_DCB_CONFIG_CHANGE (0x3UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffffUL + #define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0 +}; + +/* HWRM Asynchronous Event Completion Record for port connection not allowed (16 bytes) */ +struct hwrm_async_event_cmpl_port_conn_not_allowed { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_ID_PORT_CONN_NOT_ALLOWED (0x4UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK 0xffffUL + #define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0 +}; + +/* HWRM Asynchronous Event Completion Record for Function Driver Unload (16 bytes) */ +struct hwrm_async_event_cmpl_func_drvr_unload { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_ID_FUNC_DRVR_UNLOAD (0x10UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0 +}; + +/* HWRM Asynchronous Event Completion Record for Function Driver load (16 bytes) */ +struct hwrm_async_event_cmpl_func_drvr_load { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_ID_FUNC_DRVR_LOAD (0x11UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL + #define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0 +}; + +/* HWRM Asynchronous Event Completion Record for PF Driver Unload (16 bytes) */ +struct hwrm_async_event_cmpl_pf_drvr_unload { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_ID_PF_DRVR_UNLOAD (0x20UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0 +}; + +/* HWRM Asynchronous Event Completion Record for PF Driver load (16 bytes) */ +struct hwrm_async_event_cmpl_pf_drvr_load { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_ID_PF_DRVR_LOAD (0x20UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL + #define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0 +}; + +/* HWRM Asynchronous Event Completion Record for VF FLR (16 bytes) */ +struct hwrm_async_event_cmpl_vf_flr { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_ID_VF_FLR (0x30UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_MASK 0xffffUL + #define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_SFT 0 +}; + +/* HWRM Asynchronous Event Completion Record for VF MAC Addr change (16 bytes) */ +struct hwrm_async_event_cmpl_vf_mac_addr_change { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_ID_VF_MAC_ADDR_CHANGE (0x31UL << 0) + __le32 event_data2; + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_MASK 0xffffUL + #define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_SFT 0 +}; + +/* HWRM Asynchronous Event Completion Record for HWRM Error (16 bytes) */ +struct hwrm_async_event_cmpl_hwrm_error { + __le16 type; + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_MASK 0x3fUL + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_HWRM_ASYNC_EVENT (0x2eUL << 0) + __le16 event_id; + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_ID_HWRM_ERROR (0xffUL << 0) + __le32 event_data2; + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_MASK 0xffUL + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_SFT 0 + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_WARNING (0x0UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_NONFATAL (0x1UL << 0) + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL (0x2UL << 0) + u8 opaque_v; + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_V 0x1UL + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_MASK 0xfeUL + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_SFT 1 + u8 unused_1[3]; + __le32 event_data1; + #define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA1_TIMESTAMP 0x1UL +}; + +/* HW Resource Manager Specification 0.7.8 */ +#define HWRM_VERSION_MAJOR 0 +#define HWRM_VERSION_MINOR 7 +#define HWRM_VERSION_UPDATE 8 + +#define HWRM_VERSION_STR "0.7.8" +/* Following is the signature for HWRM message field that indicates not + * applicable (All F's). Need to cast it the size of the field if needed. + */ +#define HWRM_NA_SIGNATURE ((__le32)(-1)) +#define HWRM_MAX_REQ_LEN (128) /* hwrm_func_buf_rgtr */ +#define HWRM_MAX_RESP_LEN (176) /* hwrm_func_qstats */ +#define HW_HASH_INDEX_SIZE 0x80 /* 7 bit indirection table index. */ +#define HW_HASH_KEY_SIZE 40 +#define HWRM_RESP_VALID_KEY 1 /* valid key for HWRM response */ +/* Input (16 bytes) */ +struct input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; +}; + +/* Output (8 bytes) */ +struct output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; +}; + +/* Command numbering (8 bytes) */ +struct cmd_nums { + __le16 req_type; + #define HWRM_VER_GET (0x0UL) + #define HWRM_FUNC_DISABLE (0x10UL) + #define HWRM_FUNC_RESET (0x11UL) + #define HWRM_FUNC_GETFID (0x12UL) + #define HWRM_FUNC_VF_ALLOC (0x13UL) + #define HWRM_FUNC_VF_FREE (0x14UL) + #define HWRM_FUNC_QCAPS (0x15UL) + #define HWRM_FUNC_QCFG (0x16UL) + #define HWRM_FUNC_CFG (0x17UL) + #define HWRM_FUNC_QSTATS (0x18UL) + #define HWRM_FUNC_CLR_STATS (0x19UL) + #define HWRM_FUNC_DRV_UNRGTR (0x1aUL) + #define HWRM_FUNC_VF_RESC_FREE (0x1bUL) + #define HWRM_FUNC_VF_VNIC_IDS_QUERY (0x1cUL) + #define HWRM_FUNC_DRV_RGTR (0x1dUL) + #define HWRM_FUNC_DRV_QVER (0x1eUL) + #define HWRM_FUNC_BUF_RGTR (0x1fUL) + #define HWRM_FUNC_VF_CFG (0x20UL) + #define HWRM_PORT_PHY_CFG (0x20UL) + #define HWRM_PORT_MAC_CFG (0x21UL) + #define HWRM_PORT_ENABLE (0x22UL) + #define HWRM_PORT_QSTATS (0x23UL) + #define HWRM_PORT_LPBK_QSTATS (0x24UL) + #define HWRM_PORT_CLR_STATS (0x25UL) + #define HWRM_PORT_LPBK_CLR_STATS (0x26UL) + #define HWRM_PORT_PHY_QCFG (0x27UL) + #define HWRM_PORT_MAC_QCFG (0x28UL) + #define HWRM_PORT_BLINK_LED (0x29UL) + #define HWRM_QUEUE_QPORTCFG (0x30UL) + #define HWRM_QUEUE_QCFG (0x31UL) + #define HWRM_QUEUE_CFG (0x32UL) + #define HWRM_QUEUE_BUFFERS_QCFG (0x33UL) + #define HWRM_QUEUE_BUFFERS_CFG (0x34UL) + #define HWRM_QUEUE_PFCENABLE_QCFG (0x35UL) + #define HWRM_QUEUE_PFCENABLE_CFG (0x36UL) + #define HWRM_QUEUE_PRI2COS_QCFG (0x37UL) + #define HWRM_QUEUE_PRI2COS_CFG (0x38UL) + #define HWRM_QUEUE_COS2BW_QCFG (0x39UL) + #define HWRM_QUEUE_COS2BW_CFG (0x3aUL) + #define HWRM_VNIC_ALLOC (0x40UL) + #define HWRM_VNIC_FREE (0x41UL) + #define HWRM_VNIC_CFG (0x42UL) + #define HWRM_VNIC_QCFG (0x43UL) + #define HWRM_VNIC_TPA_CFG (0x44UL) + #define HWRM_VNIC_TPA_QCFG (0x45UL) + #define HWRM_VNIC_RSS_CFG (0x46UL) + #define HWRM_VNIC_RSS_QCFG (0x47UL) + #define HWRM_VNIC_PLCMODES_CFG (0x48UL) + #define HWRM_VNIC_PLCMODES_QCFG (0x49UL) + #define HWRM_RING_ALLOC (0x50UL) + #define HWRM_RING_FREE (0x51UL) + #define HWRM_RING_CMPL_RING_QAGGINT_PARAMS (0x52UL) + #define HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS (0x53UL) + #define HWRM_RING_RESET (0x5eUL) + #define HWRM_RING_GRP_ALLOC (0x60UL) + #define HWRM_RING_GRP_FREE (0x61UL) + #define HWRM_VNIC_RSS_COS_LB_CTX_ALLOC (0x70UL) + #define HWRM_VNIC_RSS_COS_LB_CTX_FREE (0x71UL) + #define HWRM_ARB_GRP_ALLOC (0x80UL) + #define HWRM_ARB_GRP_CFG (0x81UL) + #define HWRM_CFA_L2_FILTER_ALLOC (0x90UL) + #define HWRM_CFA_L2_FILTER_FREE (0x91UL) + #define HWRM_CFA_L2_FILTER_CFG (0x92UL) + #define HWRM_CFA_L2_SET_RX_MASK (0x93UL) + #define HWRM_CFA_L2_SET_BCASTMCAST_MIRRORING (0x94UL) + #define HWRM_CFA_TUNNEL_FILTER_ALLOC (0x95UL) + #define HWRM_CFA_TUNNEL_FILTER_FREE (0x96UL) + #define HWRM_CFA_ENCAP_RECORD_ALLOC (0x97UL) + #define HWRM_CFA_ENCAP_RECORD_FREE (0x98UL) + #define HWRM_CFA_NTUPLE_FILTER_ALLOC (0x99UL) + #define HWRM_CFA_NTUPLE_FILTER_FREE (0x9aUL) + #define HWRM_CFA_NTUPLE_FILTER_CFG (0x9bUL) + #define HWRM_TUNNEL_DST_PORT_QUERY (0xa0UL) + #define HWRM_TUNNEL_DST_PORT_ALLOC (0xa1UL) + #define HWRM_TUNNEL_DST_PORT_FREE (0xa2UL) + #define HWRM_STAT_CTX_ALLOC (0xb0UL) + #define HWRM_STAT_CTX_FREE (0xb1UL) + #define HWRM_STAT_CTX_QUERY (0xb2UL) + #define HWRM_STAT_CTX_CLR_STATS (0xb3UL) + #define HWRM_FW_RESET (0xc0UL) + #define HWRM_FW_QSTATUS (0xc1UL) + #define HWRM_EXEC_FWD_RESP (0xd0UL) + #define HWRM_REJECT_FWD_RESP (0xd1UL) + #define HWRM_FWD_RESP (0xd2UL) + #define HWRM_FWD_ASYNC_EVENT_CMPL (0xd3UL) + #define HWRM_TEMP_MONITOR_QUERY (0xe0UL) + #define HWRM_MGMT_L2_FILTER_ALLOC (0x100UL) + #define HWRM_MGMT_L2_FILTER_FREE (0x101UL) + #define HWRM_DBG_READ_DIRECT (0xff10UL) + #define HWRM_DBG_READ_INDIRECT (0xff11UL) + #define HWRM_DBG_WRITE_DIRECT (0xff12UL) + #define HWRM_DBG_WRITE_INDIRECT (0xff13UL) + #define HWRM_DBG_DUMP (0xff14UL) + #define HWRM_NVM_MODIFY (0xfff4UL) + #define HWRM_NVM_VERIFY_UPDATE (0xfff5UL) + #define HWRM_NVM_GET_DEV_INFO (0xfff6UL) + #define HWRM_NVM_ERASE_DIR_ENTRY (0xfff7UL) + #define HWRM_NVM_MOD_DIR_ENTRY (0xfff8UL) + #define HWRM_NVM_FIND_DIR_ENTRY (0xfff9UL) + #define HWRM_NVM_GET_DIR_ENTRIES (0xfffaUL) + #define HWRM_NVM_GET_DIR_INFO (0xfffbUL) + #define HWRM_NVM_RAW_DUMP (0xfffcUL) + #define HWRM_NVM_READ (0xfffdUL) + #define HWRM_NVM_WRITE (0xfffeUL) + #define HWRM_NVM_RAW_WRITE_BLK (0xffffUL) + __le16 unused_0[3]; +}; + +/* Return Codes (8 bytes) */ +struct ret_codes { + __le16 error_code; + #define HWRM_ERR_CODE_SUCCESS (0x0UL) + #define HWRM_ERR_CODE_FAIL (0x1UL) + #define HWRM_ERR_CODE_INVALID_PARAMS (0x2UL) + #define HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED (0x3UL) + #define HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR (0x4UL) + #define HWRM_ERR_CODE_INVALID_FLAGS (0x5UL) + #define HWRM_ERR_CODE_INVALID_ENABLES (0x6UL) + #define HWRM_ERR_CODE_HWRM_ERROR (0xfUL) + #define HWRM_ERR_CODE_UNKNOWN_ERR (0xfffeUL) + #define HWRM_ERR_CODE_CMD_NOT_SUPPORTED (0xffffUL) + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_err_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 opaque_0; + __le16 opaque_1; + u8 opaque_2; + u8 valid; +}; + +/* Port Tx Statistics Formats (408 bytes) */ +struct tx_port_stats { + __le64 tx_64b_frames; + __le64 tx_65b_127b_frames; + __le64 tx_128b_255b_frames; + __le64 tx_256b_511b_frames; + __le64 tx_512b_1023b_frames; + __le64 tx_1024b_1518_frames; + __le64 tx_good_vlan_frames; + __le64 tx_1519b_2047_frames; + __le64 tx_2048b_4095b_frames; + __le64 tx_4096b_9216b_frames; + __le64 tx_9217b_16383b_frames; + __le64 tx_good_frames; + __le64 tx_total_frames; + __le64 tx_ucast_frames; + __le64 tx_mcast_frames; + __le64 tx_bcast_frames; + __le64 tx_pause_frames; + __le64 tx_pfc_frames; + __le64 tx_jabber_frames; + __le64 tx_fcs_err_frames; + __le64 tx_control_frames; + __le64 tx_oversz_frames; + __le64 tx_single_dfrl_frames; + __le64 tx_multi_dfrl_frames; + __le64 tx_single_coll_frames; + __le64 tx_multi_coll_frames; + __le64 tx_late_coll_frames; + __le64 tx_excessive_coll_frames; + __le64 tx_frag_frames; + __le64 tx_err; + __le64 tx_tagged_frames; + __le64 tx_dbl_tagged_frames; + __le64 tx_runt_frames; + __le64 tx_fifo_underruns; + __le64 tx_pfc_ena_frames_pri0; + __le64 tx_pfc_ena_frames_pri1; + __le64 tx_pfc_ena_frames_pri2; + __le64 tx_pfc_ena_frames_pri3; + __le64 tx_pfc_ena_frames_pri4; + __le64 tx_pfc_ena_frames_pri5; + __le64 tx_pfc_ena_frames_pri6; + __le64 tx_pfc_ena_frames_pri7; + __le64 tx_eee_lpi_events; + __le64 tx_eee_lpi_duration; + __le64 tx_llfc_logical_msgs; + __le64 tx_hcfc_msgs; + __le64 tx_total_collisions; + __le64 tx_bytes; + __le64 tx_xthol_frames; + __le64 tx_stat_discard; + __le64 tx_stat_error; +}; + +/* Port Rx Statistics Formats (528 bytes) */ +struct rx_port_stats { + __le64 rx_64b_frames; + __le64 rx_65b_127b_frames; + __le64 rx_128b_255b_frames; + __le64 rx_256b_511b_frames; + __le64 rx_512b_1023b_frames; + __le64 rx_1024b_1518_frames; + __le64 rx_good_vlan_frames; + __le64 rx_1519b_2047b_frames; + __le64 rx_2048b_4095b_frames; + __le64 rx_4096b_9216b_frames; + __le64 rx_9217b_16383b_frames; + __le64 rx_total_frames; + __le64 rx_ucast_frames; + __le64 rx_mcast_frames; + __le64 rx_bcast_frames; + __le64 rx_fcs_err_frames; + __le64 rx_ctrl_frames; + __le64 rx_pause_frames; + __le64 rx_pfc_frames; + __le64 rx_unsupported_opcode_frames; + __le64 rx_unsupported_da_pausepfc_frames; + __le64 rx_wrong_sa_frames; + __le64 rx_align_err_frames; + __le64 rx_oor_len_frames; + __le64 rx_code_err_frames; + __le64 rx_false_carrier_frames; + __le64 rx_ovrsz_frames; + __le64 rx_jbr_frames; + __le64 rx_mtu_err_frames; + __le64 rx_match_crc_frames; + __le64 rx_promiscuous_frames; + __le64 rx_tagged_frames; + __le64 rx_double_tagged_frames; + __le64 rx_trunc_frames; + __le64 rx_good_frames; + __le64 rx_pfc_xon2xoff_frames_pri0; + __le64 rx_pfc_xon2xoff_frames_pri1; + __le64 rx_pfc_xon2xoff_frames_pri2; + __le64 rx_pfc_xon2xoff_frames_pri3; + __le64 rx_pfc_xon2xoff_frames_pri4; + __le64 rx_pfc_xon2xoff_frames_pri5; + __le64 rx_pfc_xon2xoff_frames_pri6; + __le64 rx_pfc_xon2xoff_frames_pri7; + __le64 rx_pfc_ena_frames_pri0; + __le64 rx_pfc_ena_frames_pri1; + __le64 rx_pfc_ena_frames_pri2; + __le64 rx_pfc_ena_frames_pri3; + __le64 rx_pfc_ena_frames_pri4; + __le64 rx_pfc_ena_frames_pri5; + __le64 rx_pfc_ena_frames_pri6; + __le64 rx_pfc_ena_frames_pri7; + __le64 rx_sch_crc_err_frames; + __le64 rx_undrsz_frames; + __le64 rx_frag_frames; + __le64 rx_eee_lpi_events; + __le64 rx_eee_lpi_duration; + __le64 rx_llfc_physical_msgs; + __le64 rx_llfc_logical_msgs; + __le64 rx_llfc_msgs_with_crc_err; + __le64 rx_hcfc_msgs; + __le64 rx_hcfc_msgs_with_crc_err; + __le64 rx_bytes; + __le64 rx_runt_bytes; + __le64 rx_runt_frames; + __le64 rx_stat_discard; + __le64 rx_stat_err; +}; + +/* hwrm_ver_get */ +/* Input (24 bytes) */ +struct hwrm_ver_get_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + u8 hwrm_intf_maj; + u8 hwrm_intf_min; + u8 hwrm_intf_upd; + u8 unused_0[5]; +}; + +/* Output (128 bytes) */ +struct hwrm_ver_get_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + u8 hwrm_intf_maj; + u8 hwrm_intf_min; + u8 hwrm_intf_upd; + u8 hwrm_intf_rsvd; + u8 hwrm_fw_maj; + u8 hwrm_fw_min; + u8 hwrm_fw_bld; + u8 hwrm_fw_rsvd; + u8 ape_fw_maj; + u8 ape_fw_min; + u8 ape_fw_bld; + u8 ape_fw_rsvd; + u8 kong_fw_maj; + u8 kong_fw_min; + u8 kong_fw_bld; + u8 kong_fw_rsvd; + u8 tang_fw_maj; + u8 tang_fw_min; + u8 tang_fw_bld; + u8 tang_fw_rsvd; + u8 bono_fw_maj; + u8 bono_fw_min; + u8 bono_fw_bld; + u8 bono_fw_rsvd; + char hwrm_fw_name[16]; + char ape_fw_name[16]; + char kong_fw_name[16]; + char tang_fw_name[16]; + char bono_fw_name[16]; + __le16 chip_num; + u8 chip_rev; + u8 chip_metal; + u8 chip_bond_id; + u8 unused_0; + __le16 max_req_win_len; + __le16 max_resp_len; + __le16 def_req_timeout; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_func_disable */ +/* Input (24 bytes) */ +struct hwrm_func_disable_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define FUNC_DISABLE_REQ_ENABLES_VF_ID_VALID 0x1UL + __le16 vf_id; + __le16 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_func_disable_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_func_reset */ +/* Input (24 bytes) */ +struct hwrm_func_reset_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define FUNC_RESET_REQ_ENABLES_VF_ID_VALID 0x1UL + __le16 vf_id; + __le16 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_func_reset_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_func_getfid */ +/* Input (24 bytes) */ +struct hwrm_func_getfid_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define FUNC_GETFID_REQ_ENABLES_PCI_ID 0x1UL + __le16 pci_id; + __le16 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_func_getfid_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 fid; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 unused_4; + u8 valid; +}; + +/* hwrm_func_vf_alloc */ +/* Input (24 bytes) */ +struct hwrm_func_vf_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define FUNC_VF_ALLOC_REQ_ENABLES_FIRST_VF_ID 0x1UL + __le16 first_vf_id; + __le16 num_vfs; +}; + +/* Output (16 bytes) */ +struct hwrm_func_vf_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 first_vf_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 unused_4; + u8 valid; +}; + +/* hwrm_func_vf_free */ +/* Input (24 bytes) */ +struct hwrm_func_vf_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define FUNC_VF_FREE_REQ_ENABLES_FIRST_VF_ID 0x1UL + __le16 first_vf_id; + __le16 num_vfs; +}; + +/* Output (16 bytes) */ +struct hwrm_func_vf_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_func_vf_cfg */ +/* Input (24 bytes) */ +struct hwrm_func_vf_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define FUNC_VF_CFG_REQ_ENABLES_MTU 0x1UL + #define FUNC_VF_CFG_REQ_ENABLES_GUEST_VLAN 0x2UL + __le16 mtu; + __le16 guest_vlan; +}; + +/* Output (16 bytes) */ +struct hwrm_func_vf_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_func_qcaps */ +/* Input (24 bytes) */ +struct hwrm_func_qcaps_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 fid; + __le16 unused_0[3]; +}; + +/* Output (80 bytes) */ +struct hwrm_func_qcaps_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 fid; + __le16 port_id; + __le32 flags; + #define FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED 0x1UL + #define FUNC_QCAPS_RESP_FLAGS_GLOBAL_MSIX_AUTOMASKING 0x2UL + u8 perm_mac_address[6]; + __le16 max_rsscos_ctx; + __le16 max_cmpl_rings; + __le16 max_tx_rings; + __le16 max_rx_rings; + __le16 max_l2_ctxs; + __le16 max_vnics; + __le16 first_vf_id; + __le16 max_vfs; + __le16 max_stat_ctx; + __le32 max_encap_records; + __le32 max_decap_records; + __le32 max_tx_em_flows; + __le32 max_tx_wm_flows; + __le32 max_rx_em_flows; + __le32 max_rx_wm_flows; + __le32 max_mcast_filters; + __le32 max_flow_id; + __le32 max_hw_ring_grps; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 valid; +}; + +/* hwrm_func_cfg */ +/* Input (88 bytes) */ +struct hwrm_func_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 vf_id; + u8 unused_0; + u8 unused_1; + __le32 flags; + #define FUNC_CFG_REQ_FLAGS_PROM_MODE 0x1UL + #define FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK 0x2UL + #define FUNC_CFG_REQ_FLAGS_SRC_IP_ADDR_CHECK 0x4UL + #define FUNC_CFG_REQ_FLAGS_VLAN_PRI_MATCH 0x8UL + #define FUNC_CFG_REQ_FLAGS_DFLT_PRI_NOMATCH 0x10UL + #define FUNC_CFG_REQ_FLAGS_DISABLE_PAUSE 0x20UL + #define FUNC_CFG_REQ_FLAGS_DISABLE_STP 0x40UL + #define FUNC_CFG_REQ_FLAGS_DISABLE_LLDP 0x80UL + #define FUNC_CFG_REQ_FLAGS_DISABLE_PTPV2 0x100UL + __le32 enables; + #define FUNC_CFG_REQ_ENABLES_MTU 0x1UL + #define FUNC_CFG_REQ_ENABLES_MRU 0x2UL + #define FUNC_CFG_REQ_ENABLES_NUM_RSSCOS_CTXS 0x4UL + #define FUNC_CFG_REQ_ENABLES_NUM_CMPL_RINGS 0x8UL + #define FUNC_CFG_REQ_ENABLES_NUM_TX_RINGS 0x10UL + #define FUNC_CFG_REQ_ENABLES_NUM_RX_RINGS 0x20UL + #define FUNC_CFG_REQ_ENABLES_NUM_L2_CTXS 0x40UL + #define FUNC_CFG_REQ_ENABLES_NUM_VNICS 0x80UL + #define FUNC_CFG_REQ_ENABLES_NUM_STAT_CTXS 0x100UL + #define FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR 0x200UL + #define FUNC_CFG_REQ_ENABLES_DFLT_VLAN 0x400UL + #define FUNC_CFG_REQ_ENABLES_DFLT_IP_ADDR 0x800UL + #define FUNC_CFG_REQ_ENABLES_MIN_BW 0x1000UL + #define FUNC_CFG_REQ_ENABLES_MAX_BW 0x2000UL + #define FUNC_CFG_REQ_ENABLES_ASYNC_EVENT_CR 0x4000UL + #define FUNC_CFG_REQ_ENABLES_VLAN_ANTISPOOF_MODE 0x8000UL + #define FUNC_CFG_REQ_ENABLES_ALLOWED_VLAN_PRIS 0x10000UL + #define FUNC_CFG_REQ_ENABLES_EVB_MODE 0x20000UL + #define FUNC_CFG_REQ_ENABLES_NUM_MCAST_FILTERS 0x40000UL + #define FUNC_CFG_REQ_ENABLES_NUM_HW_RING_GRPS 0x80000UL + __le16 mtu; + __le16 mru; + __le16 num_rsscos_ctxs; + __le16 num_cmpl_rings; + __le16 num_tx_rings; + __le16 num_rx_rings; + __le16 num_l2_ctxs; + __le16 num_vnics; + __le16 num_stat_ctxs; + __le16 num_hw_ring_grps; + u8 dflt_mac_addr[6]; + __le16 dflt_vlan; + __be32 dflt_ip_addr[4]; + __le32 min_bw; + __le32 max_bw; + __le16 async_event_cr; + u8 vlan_antispoof_mode; + #define FUNC_CFG_REQ_VLAN_ANTISPOOF_MODE_NOCHECK (0x0UL << 0) + #define FUNC_CFG_REQ_VLAN_ANTISPOOF_MODE_VALIDATE_VLAN (0x1UL << 0) + #define FUNC_CFG_REQ_VLAN_ANTISPOOF_MODE_INSERT_IF_VLANDNE (0x2UL << 0) + #define FUNC_CFG_REQ_VLAN_ANTISPOOF_MODE_INSERT_OR_OVERRIDE_VLAN (0x3UL << 0) + u8 allowed_vlan_pris; + #define FUNC_CFG_REQ_ALLOWED_VLAN_PRIS_NOCHECK (0x0UL << 0) + #define FUNC_CFG_REQ_ALLOWED_VLAN_PRIS_VALIDATE_VLAN (0x1UL << 0) + #define FUNC_CFG_REQ_ALLOWED_VLAN_PRIS_INSERT_IF_VLANDNE (0x2UL << 0) + #define FUNC_CFG_REQ_ALLOWED_VLAN_PRIS_INSERT_OR_OVERRIDE_VLAN (0x3UL << 0) + u8 evb_mode; + #define FUNC_CFG_REQ_EVB_MODE_NO_EVB (0x0UL << 0) + #define FUNC_CFG_REQ_EVB_MODE_VEB (0x1UL << 0) + #define FUNC_CFG_REQ_EVB_MODE_VEPA (0x2UL << 0) + u8 unused_2; + __le16 num_mcast_filters; +}; + +/* Output (16 bytes) */ +struct hwrm_func_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_func_qstats */ +/* Input (24 bytes) */ +struct hwrm_func_qstats_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 fid; + __le16 unused_0[3]; +}; + +/* Output (176 bytes) */ +struct hwrm_func_qstats_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le64 tx_ucast_pkts; + __le64 tx_mcast_pkts; + __le64 tx_bcast_pkts; + __le64 tx_err_pkts; + __le64 tx_drop_pkts; + __le64 tx_ucast_bytes; + __le64 tx_mcast_bytes; + __le64 tx_bcast_bytes; + __le64 rx_ucast_pkts; + __le64 rx_mcast_pkts; + __le64 rx_bcast_pkts; + __le64 rx_err_pkts; + __le64 rx_drop_pkts; + __le64 rx_ucast_bytes; + __le64 rx_mcast_bytes; + __le64 rx_bcast_bytes; + __le64 rx_agg_pkts; + __le64 rx_agg_bytes; + __le64 rx_agg_events; + __le64 rx_agg_aborts; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_func_clr_stats */ +/* Input (24 bytes) */ +struct hwrm_func_clr_stats_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 fid; + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_func_clr_stats_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_func_vf_resc_free */ +/* Input (24 bytes) */ +struct hwrm_func_vf_resc_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 vf_id; + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_func_vf_resc_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_func_vf_vnic_ids_query */ +/* Input (32 bytes) */ +struct hwrm_func_vf_vnic_ids_query_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 vf_id; + u8 unused_0; + u8 unused_1; + __le32 max_vnic_id_cnt; + __le64 vnic_id_tbl_addr; +}; + +/* Output (16 bytes) */ +struct hwrm_func_vf_vnic_ids_query_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 vnic_id_cnt; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 valid; +}; + +/* hwrm_func_drv_rgtr */ +/* Input (80 bytes) */ +struct hwrm_func_drv_rgtr_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define FUNC_DRV_RGTR_REQ_FLAGS_FWD_ALL_MODE 0x1UL + #define FUNC_DRV_RGTR_REQ_FLAGS_FWD_NONE_MODE 0x2UL + __le32 enables; + #define FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE 0x1UL + #define FUNC_DRV_RGTR_REQ_ENABLES_VER 0x2UL + #define FUNC_DRV_RGTR_REQ_ENABLES_TIMESTAMP 0x4UL + #define FUNC_DRV_RGTR_REQ_ENABLES_VF_REQ_FWD 0x8UL + #define FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD 0x10UL + __le16 os_type; + u8 ver_maj; + u8 ver_min; + u8 ver_upd; + u8 unused_0; + __le16 unused_1; + __le32 timestamp; + __le32 unused_2; + __le32 vf_req_fwd[8]; + __le32 async_event_fwd[8]; +}; + +/* Output (16 bytes) */ +struct hwrm_func_drv_rgtr_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_func_drv_unrgtr */ +/* Input (24 bytes) */ +struct hwrm_func_drv_unrgtr_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define FUNC_DRV_UNRGTR_REQ_FLAGS_PREPARE_FOR_SHUTDOWN 0x1UL + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_func_drv_unrgtr_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_func_buf_rgtr */ +/* Input (128 bytes) */ +struct hwrm_func_buf_rgtr_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define FUNC_BUF_RGTR_REQ_ENABLES_VF_ID 0x1UL + #define FUNC_BUF_RGTR_REQ_ENABLES_ERR_BUF_ADDR 0x2UL + __le16 vf_id; + __le16 req_buf_num_pages; + __le16 req_buf_page_size; + #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_16B (0x4UL << 0) + #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_4K (0xcUL << 0) + #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_8K (0xdUL << 0) + #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_64K (0x10UL << 0) + #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_2M (0x16UL << 0) + #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_4M (0x17UL << 0) + #define FUNC_BUF_RGTR_REQ_REQ_BUF_PAGE_SIZE_1G (0x1eUL << 0) + __le16 req_buf_len; + __le16 resp_buf_len; + u8 unused_0; + u8 unused_1; + __le64 req_buf_page_addr0; + __le64 req_buf_page_addr1; + __le64 req_buf_page_addr2; + __le64 req_buf_page_addr3; + __le64 req_buf_page_addr4; + __le64 req_buf_page_addr5; + __le64 req_buf_page_addr6; + __le64 req_buf_page_addr7; + __le64 req_buf_page_addr8; + __le64 req_buf_page_addr9; + __le64 error_buf_addr; + __le64 resp_buf_addr; +}; + +/* Output (16 bytes) */ +struct hwrm_func_buf_rgtr_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_func_drv_qver */ +/* Input (24 bytes) */ +struct hwrm_func_drv_qver_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define FUNC_DRV_QVER_REQ_ENABLES_OS_TYPE_VALID 0x1UL + #define FUNC_DRV_QVER_REQ_ENABLES_VER_VALID 0x2UL + __le16 fid; + __le16 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_func_drv_qver_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 os_type; + u8 ver_maj; + u8 ver_min; + u8 ver_upd; + u8 unused_0; + u8 unused_1; + u8 valid; +}; + +/* hwrm_port_phy_cfg */ +/* Input (48 bytes) */ +struct hwrm_port_phy_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define PORT_PHY_CFG_REQ_FLAGS_RESET_PHY 0x1UL + #define PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DOWN 0x2UL + #define PORT_PHY_CFG_REQ_FLAGS_FORCE 0x4UL + #define PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG 0x8UL + __le32 enables; + #define PORT_PHY_CFG_REQ_ENABLES_AUTO_MODE 0x1UL + #define PORT_PHY_CFG_REQ_ENABLES_AUTO_DUPLEX 0x2UL + #define PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE 0x4UL + #define PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEED 0x8UL + #define PORT_PHY_CFG_REQ_ENABLES_AUTO_LINK_SPEED_MASK 0x10UL + #define PORT_PHY_CFG_REQ_ENABLES_WIRESPEED 0x20UL + #define PORT_PHY_CFG_REQ_ENABLES_LPBK 0x40UL + #define PORT_PHY_CFG_REQ_ENABLES_PREEMPHASIS 0x80UL + #define PORT_PHY_CFG_REQ_ENABLES_FORCE_PAUSE 0x100UL + __le16 port_id; + __le16 force_link_speed; + #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_100MB (0x1UL << 0) + #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_1GB (0xaUL << 0) + #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_2GB (0x14UL << 0) + #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_2_5GB (0x19UL << 0) + #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_10GB (0x64UL << 0) + #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_20GB (0xc8UL << 0) + #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_25GB (0xfaUL << 0) + #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_40GB (0x190UL << 0) + #define PORT_PHY_CFG_REQ_FORCE_LINK_SPEED_50GB (0x1f4UL << 0) + u8 auto_mode; + #define PORT_PHY_CFG_REQ_AUTO_MODE_NONE (0x0UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_MODE_ALL_SPEEDS (0x1UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_MODE_ONE_SPEED (0x2UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_MODE_ONE_OR_BELOW (0x3UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_MODE_MASK (0x4UL << 0) + u8 auto_duplex; + #define PORT_PHY_CFG_REQ_AUTO_DUPLEX_HALF (0x0UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_DUPLEX_FULL (0x1UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_DUPLEX_BOTH (0x2UL << 0) + u8 auto_pause; + #define PORT_PHY_CFG_REQ_AUTO_PAUSE_TX 0x1UL + #define PORT_PHY_CFG_REQ_AUTO_PAUSE_RX 0x2UL + u8 unused_0; + __le16 auto_link_speed; + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_100MB (0x1UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_1GB (0xaUL << 0) + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_2GB (0x14UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_2_5GB (0x19UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_10GB (0x64UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_20GB (0xc8UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_25GB (0xfaUL << 0) + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_40GB (0x190UL << 0) + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_50GB (0x1f4UL << 0) + __le16 auto_link_speed_mask; + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_100MBHD 0x1UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_100MB 0x2UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_1GBHD 0x4UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_1GB 0x8UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_2GB 0x10UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_2_5GB 0x20UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_10GB 0x40UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_20GB 0x80UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_25GB 0x100UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_40GB 0x200UL + #define PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_MASK_50GB 0x400UL + u8 wirespeed; + #define PORT_PHY_CFG_REQ_WIRESPEED_OFF (0x0UL << 0) + #define PORT_PHY_CFG_REQ_WIRESPEED_ON (0x1UL << 0) + u8 lpbk; + #define PORT_PHY_CFG_REQ_LPBK_NONE (0x0UL << 0) + #define PORT_PHY_CFG_REQ_LPBK_LOCAL (0x1UL << 0) + #define PORT_PHY_CFG_REQ_LPBK_REMOTE (0x2UL << 0) + u8 force_pause; + #define PORT_PHY_CFG_REQ_FORCE_PAUSE_TX 0x1UL + #define PORT_PHY_CFG_REQ_FORCE_PAUSE_RX 0x2UL + u8 unused_1; + __le32 preemphasis; + __le32 unused_2; +}; + +/* Output (16 bytes) */ +struct hwrm_port_phy_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_port_phy_qcfg */ +/* Input (24 bytes) */ +struct hwrm_port_phy_qcfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 port_id; + __le16 unused_0[3]; +}; + +/* Output (48 bytes) */ +struct hwrm_port_phy_qcfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + u8 link; + #define PORT_PHY_QCFG_RESP_LINK_NO_LINK (0x0UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_SIGNAL (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_LINK (0x2UL << 0) + u8 unused_0; + __le16 link_speed; + #define PORT_PHY_QCFG_RESP_LINK_SPEED_100MB (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_SPEED_1GB (0xaUL << 0) + #define PORT_PHY_QCFG_RESP_LINK_SPEED_2GB (0x14UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_SPEED_2_5GB (0x19UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_SPEED_10GB (0x64UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_SPEED_20GB (0xc8UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_SPEED_25GB (0xfaUL << 0) + #define PORT_PHY_QCFG_RESP_LINK_SPEED_40GB (0x190UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_SPEED_50GB (0x1f4UL << 0) + u8 duplex; + #define PORT_PHY_QCFG_RESP_DUPLEX_HALF (0x0UL << 0) + #define PORT_PHY_QCFG_RESP_DUPLEX_FULL (0x1UL << 0) + u8 pause; + #define PORT_PHY_QCFG_RESP_PAUSE_TX 0x1UL + #define PORT_PHY_QCFG_RESP_PAUSE_RX 0x2UL + __le16 support_speeds; + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100MBHD 0x1UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_100MB 0x2UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_1GBHD 0x4UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_1GB 0x8UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_2GB 0x10UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_2_5GB 0x20UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_10GB 0x40UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_20GB 0x80UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_25GB 0x100UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_40GB 0x200UL + #define PORT_PHY_QCFG_RESP_SUPPORT_SPEEDS_50GB 0x400UL + __le16 force_link_speed; + #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_100MB (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_1GB (0xaUL << 0) + #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_2GB (0x14UL << 0) + #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_2_5GB (0x19UL << 0) + #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_10GB (0x64UL << 0) + #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_20GB (0xc8UL << 0) + #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_25GB (0xfaUL << 0) + #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_40GB (0x190UL << 0) + #define PORT_PHY_QCFG_RESP_FORCE_LINK_SPEED_50GB (0x1f4UL << 0) + u8 auto_mode; + #define PORT_PHY_QCFG_RESP_AUTO_MODE_NONE (0x0UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_MODE_ALL_SPEEDS (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_SPEED (0x2UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_MODE_ONE_OR_BELOW (0x3UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_MODE_MASK (0x4UL << 0) + u8 auto_pause; + #define PORT_PHY_QCFG_RESP_AUTO_PAUSE_TX 0x1UL + #define PORT_PHY_QCFG_RESP_AUTO_PAUSE_RX 0x2UL + __le16 auto_link_speed; + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_100MB (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_1GB (0xaUL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_2GB (0x14UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_2_5GB (0x19UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_10GB (0x64UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_20GB (0xc8UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_25GB (0xfaUL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_40GB (0x190UL << 0) + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_50GB (0x1f4UL << 0) + __le16 auto_link_speed_mask; + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_100MBHD 0x1UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_100MB 0x2UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_1GBHD 0x4UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_1GB 0x8UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_2GB 0x10UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_2_5GB 0x20UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_10GB 0x40UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_20GB 0x80UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_25GB 0x100UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_40GB 0x200UL + #define PORT_PHY_QCFG_RESP_AUTO_LINK_SPEED_MASK_50GB 0x400UL + u8 wirespeed; + #define PORT_PHY_QCFG_RESP_WIRESPEED_OFF (0x0UL << 0) + #define PORT_PHY_QCFG_RESP_WIRESPEED_ON (0x1UL << 0) + u8 lpbk; + #define PORT_PHY_QCFG_RESP_LPBK_NONE (0x0UL << 0) + #define PORT_PHY_QCFG_RESP_LPBK_LOCAL (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_LPBK_REMOTE (0x2UL << 0) + u8 force_pause; + #define PORT_PHY_QCFG_RESP_FORCE_PAUSE_TX 0x1UL + #define PORT_PHY_QCFG_RESP_FORCE_PAUSE_RX 0x2UL + u8 duplex_setting; + #define PORT_PHY_QCFG_RESP_DUPLEX_SETTING_HALF (0x0UL << 0) + #define PORT_PHY_QCFG_RESP_DUPLEX_SETTING_FULL (0x1UL << 0) + __le32 preemphasis; + u8 phy_maj; + u8 phy_min; + u8 phy_bld; + u8 phy_type; + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASECR4 (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR4 (0x2UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASELR4 (0x3UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASESR4 (0x4UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR2 (0x5UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKX4 (0x6UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR (0x7UL << 0) + #define PORT_PHY_QCFG_RESP_PHY_TYPE_BASET (0x8UL << 0) + u8 media_type; + #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC (0x2UL << 0) + #define PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE (0x3UL << 0) + u8 transceiver_type; + #define PORT_PHY_QCFG_RESP_TRANSCEIVER_TYPE_XCVR_INTERNAL (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_TRANSCEIVER_TYPE_XCVR_EXTERNAL (0x2UL << 0) + u8 phy_addr; + #define PORT_PHY_QCFG_RESP_PHY_ADDR_MASK 0x1fUL + #define PORT_PHY_QCFG_RESP_PHY_ADDR_SFT 0 + u8 unused_2; + __le16 link_partner_adv_speeds; + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_100MBHD 0x1UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_100MB 0x2UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_1GBHD 0x4UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_1GB 0x8UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_2GB 0x10UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_2_5GB 0x20UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_10GB 0x40UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_20GB 0x80UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_25GB 0x100UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_40GB 0x200UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_SPEEDS_50GB 0x400UL + u8 link_partner_adv_auto_mode; + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_NONE (0x0UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_ALL_SPEEDS (0x1UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_ONE_SPEED (0x2UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_ONE_OR_BELOW (0x3UL << 0) + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_AUTO_MODE_MASK (0x4UL << 0) + u8 link_partner_adv_pause; + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_PAUSE_TX 0x1UL + #define PORT_PHY_QCFG_RESP_LINK_PARTNER_ADV_PAUSE_RX 0x2UL + u8 unused_3; + u8 unused_4; + u8 unused_5; + u8 valid; +}; + +/* hwrm_port_mac_cfg */ +/* Input (32 bytes) */ +struct hwrm_port_mac_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define PORT_MAC_CFG_REQ_FLAGS_MATCH_LINK 0x1UL + #define PORT_MAC_CFG_REQ_FLAGS_COS_ASSIGNMENT_ENABLE 0x2UL + #define PORT_MAC_CFG_REQ_FLAGS_TUNNEL_PRI2COS_ENABLE 0x4UL + #define PORT_MAC_CFG_REQ_FLAGS_IP_DSCP2COS_ENABLE 0x8UL + __le32 enables; + #define PORT_MAC_CFG_REQ_ENABLES_IPG 0x1UL + #define PORT_MAC_CFG_REQ_ENABLES_LPBK 0x2UL + #define PORT_MAC_CFG_REQ_ENABLES_IVLAN_PRI2COS_MAP_PRI 0x4UL + #define PORT_MAC_CFG_REQ_ENABLES_LCOS_MAP_PRI 0x8UL + #define PORT_MAC_CFG_REQ_ENABLES_TUNNEL_PRI2COS_MAP_PRI 0x10UL + #define PORT_MAC_CFG_REQ_ENABLES_DSCP2COS_MAP_PRI 0x20UL + __le16 port_id; + u8 ipg; + u8 lpbk; + #define PORT_MAC_CFG_REQ_LPBK_NONE (0x0UL << 0) + #define PORT_MAC_CFG_REQ_LPBK_LOCAL (0x1UL << 0) + #define PORT_MAC_CFG_REQ_LPBK_REMOTE (0x2UL << 0) + u8 ivlan_pri2cos_map_pri; + u8 lcos_map_pri; + u8 tunnel_pri2cos_map_pri; + u8 dscp2pri_map_pri; +}; + +/* Output (16 bytes) */ +struct hwrm_port_mac_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 mru; + __le16 mtu; + u8 ipg; + u8 lpbk; + #define PORT_MAC_CFG_RESP_LPBK_NONE (0x0UL << 0) + #define PORT_MAC_CFG_RESP_LPBK_LOCAL (0x1UL << 0) + #define PORT_MAC_CFG_RESP_LPBK_REMOTE (0x2UL << 0) + u8 unused_0; + u8 valid; +}; + +/* hwrm_port_enable */ +/* Input (24 bytes) */ +struct hwrm_port_enable_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define PORT_ENABLE_REQ_FLAGS_FORWARD_TRAFFIC 0x1UL + __le16 port_id; + __le16 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_port_enable_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_port_qstats */ +/* Input (40 bytes) */ +struct hwrm_port_qstats_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 port_id; + u8 unused_0; + u8 unused_1; + u8 unused_2[3]; + u8 unused_3; + __le64 tx_stat_host_addr; + __le64 rx_stat_host_addr; +}; + +/* Output (16 bytes) */ +struct hwrm_port_qstats_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_port_lpbk_qstats */ +/* Input (16 bytes) */ +struct hwrm_port_lpbk_qstats_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; +}; + +/* Output (64 bytes) */ +struct hwrm_port_lpbk_qstats_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le64 lpbk_ucast_frames; + __le64 lpbk_mcast_frames; + __le64 lpbk_bcast_frames; + __le64 lpbk_ucast_bytes; + __le64 lpbk_mcast_bytes; + __le64 lpbk_bcast_bytes; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_port_clr_stats */ +/* Input (24 bytes) */ +struct hwrm_port_clr_stats_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 port_id; + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_port_clr_stats_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_port_lpbk_clr_stats */ +/* Input (16 bytes) */ +struct hwrm_port_lpbk_clr_stats_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; +}; + +/* Output (16 bytes) */ +struct hwrm_port_lpbk_clr_stats_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_port_blink_led */ +/* Input (24 bytes) */ +struct hwrm_port_blink_led_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 num_blinks; + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_port_blink_led_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_queue_qportcfg */ +/* Input (24 bytes) */ +struct hwrm_queue_qportcfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define QUEUE_QPORTCFG_REQ_FLAGS_PATH 0x1UL + #define QUEUE_QPORTCFG_REQ_FLAGS_PATH_TX (0x0UL << 0) + #define QUEUE_QPORTCFG_REQ_FLAGS_PATH_RX (0x1UL << 0) + __le16 port_id; + __le16 unused_0; +}; + +/* Output (32 bytes) */ +struct hwrm_queue_qportcfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + u8 max_configurable_queues; + u8 max_configurable_lossless_queues; + u8 queue_cfg_allowed; + u8 queue_buffers_cfg_allowed; + u8 queue_pfcenable_cfg_allowed; + u8 queue_pri2cos_cfg_allowed; + u8 queue_cos2bw_cfg_allowed; + u8 queue_id0; + u8 queue_id0_service_profile; + #define QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSY (0x0UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS (0x1UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_UNKNOWN (0xffUL << 0) + u8 queue_id1; + u8 queue_id1_service_profile; + #define QUEUE_QPORTCFG_RESP_QUEUE_ID1_SERVICE_PROFILE_LOSSY (0x0UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID1_SERVICE_PROFILE_LOSSLESS (0x1UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID1_SERVICE_PROFILE_UNKNOWN (0xffUL << 0) + u8 queue_id2; + u8 queue_id2_service_profile; + #define QUEUE_QPORTCFG_RESP_QUEUE_ID2_SERVICE_PROFILE_LOSSY (0x0UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID2_SERVICE_PROFILE_LOSSLESS (0x1UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID2_SERVICE_PROFILE_UNKNOWN (0xffUL << 0) + u8 queue_id3; + u8 queue_id3_service_profile; + #define QUEUE_QPORTCFG_RESP_QUEUE_ID3_SERVICE_PROFILE_LOSSY (0x0UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID3_SERVICE_PROFILE_LOSSLESS (0x1UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID3_SERVICE_PROFILE_UNKNOWN (0xffUL << 0) + u8 queue_id4; + u8 queue_id4_service_profile; + #define QUEUE_QPORTCFG_RESP_QUEUE_ID4_SERVICE_PROFILE_LOSSY (0x0UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID4_SERVICE_PROFILE_LOSSLESS (0x1UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID4_SERVICE_PROFILE_UNKNOWN (0xffUL << 0) + u8 queue_id5; + u8 queue_id5_service_profile; + #define QUEUE_QPORTCFG_RESP_QUEUE_ID5_SERVICE_PROFILE_LOSSY (0x0UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID5_SERVICE_PROFILE_LOSSLESS (0x1UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID5_SERVICE_PROFILE_UNKNOWN (0xffUL << 0) + u8 queue_id6; + u8 queue_id6_service_profile; + #define QUEUE_QPORTCFG_RESP_QUEUE_ID6_SERVICE_PROFILE_LOSSY (0x0UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID6_SERVICE_PROFILE_LOSSLESS (0x1UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID6_SERVICE_PROFILE_UNKNOWN (0xffUL << 0) + u8 queue_id7; + u8 queue_id7_service_profile; + #define QUEUE_QPORTCFG_RESP_QUEUE_ID7_SERVICE_PROFILE_LOSSY (0x0UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID7_SERVICE_PROFILE_LOSSLESS (0x1UL << 0) + #define QUEUE_QPORTCFG_RESP_QUEUE_ID7_SERVICE_PROFILE_UNKNOWN (0xffUL << 0) + u8 valid; +}; + +/* hwrm_queue_cfg */ +/* Input (40 bytes) */ +struct hwrm_queue_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define QUEUE_CFG_REQ_FLAGS_PATH 0x1UL + #define QUEUE_CFG_REQ_FLAGS_PATH_TX (0x0UL << 0) + #define QUEUE_CFG_REQ_FLAGS_PATH_RX (0x1UL << 0) + __le32 enables; + #define QUEUE_CFG_REQ_ENABLES_DFLT_LEN 0x1UL + #define QUEUE_CFG_REQ_ENABLES_SERVICE_PROFILE 0x2UL + __le32 queue_id; + __le32 dflt_len; + u8 service_profile; + #define QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSY (0x0UL << 0) + #define QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSLESS (0x1UL << 0) + #define QUEUE_CFG_REQ_SERVICE_PROFILE_UNKNOWN (0xffUL << 0) + u8 unused_0[7]; +}; + +/* Output (16 bytes) */ +struct hwrm_queue_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_queue_buffers_cfg */ +/* Input (56 bytes) */ +struct hwrm_queue_buffers_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define QUEUE_BUFFERS_CFG_REQ_FLAGS_PATH 0x1UL + #define QUEUE_BUFFERS_CFG_REQ_FLAGS_PATH_TX (0x0UL << 0) + #define QUEUE_BUFFERS_CFG_REQ_FLAGS_PATH_RX (0x1UL << 0) + __le32 enables; + #define QUEUE_BUFFERS_CFG_REQ_ENABLES_RESERVED 0x1UL + #define QUEUE_BUFFERS_CFG_REQ_ENABLES_SHARED 0x2UL + #define QUEUE_BUFFERS_CFG_REQ_ENABLES_GROUP 0x4UL + #define QUEUE_BUFFERS_CFG_REQ_ENABLES_XOFF 0x8UL + #define QUEUE_BUFFERS_CFG_REQ_ENABLES_XON 0x10UL + #define QUEUE_BUFFERS_CFG_REQ_ENABLES_FULL 0x20UL + #define QUEUE_BUFFERS_CFG_REQ_ENABLES_NOTFULL 0x40UL + #define QUEUE_BUFFERS_CFG_REQ_ENABLES_MAX 0x80UL + __le32 queue_id; + __le32 reserved; + __le32 shared; + __le32 xoff; + __le32 xon; + __le32 full; + __le32 notfull; + __le32 max; +}; + +/* Output (16 bytes) */ +struct hwrm_queue_buffers_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_queue_pfcenable_cfg */ +/* Input (24 bytes) */ +struct hwrm_queue_pfcenable_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI0_PFC_ENABLED 0x1UL + #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI1_PFC_ENABLED 0x2UL + #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI2_PFC_ENABLED 0x4UL + #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI3_PFC_ENABLED 0x8UL + #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI4_PFC_ENABLED 0x10UL + #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI5_PFC_ENABLED 0x20UL + #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI6_PFC_ENABLED 0x40UL + #define QUEUE_PFCENABLE_CFG_REQ_ENABLES_PRI7_PFC_ENABLED 0x80UL + __le16 port_id; + __le16 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_queue_pfcenable_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_queue_pri2cos_cfg */ +/* Input (40 bytes) */ +struct hwrm_queue_pri2cos_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH 0x1UL + #define QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_TX (0x0UL << 0) + #define QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_RX (0x1UL << 0) + #define QUEUE_PRI2COS_CFG_REQ_FLAGS_IVLAN 0x2UL + __le32 enables; + u8 port_id; + u8 pri0_cos; + u8 pri1_cos; + u8 pri2_cos; + u8 pri3_cos; + u8 pri4_cos; + u8 pri5_cos; + u8 pri6_cos; + u8 pri7_cos; + u8 unused_0[7]; +}; + +/* Output (16 bytes) */ +struct hwrm_queue_pri2cos_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_queue_cos2bw_cfg */ +/* Input (128 bytes) */ +struct hwrm_queue_cos2bw_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + __le32 enables; + #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID0_VALID 0x1UL + #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID1_VALID 0x2UL + #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID2_VALID 0x4UL + #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID3_VALID 0x8UL + #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID4_VALID 0x10UL + #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID5_VALID 0x20UL + #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID6_VALID 0x40UL + #define QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID7_VALID 0x80UL + __le16 port_id; + u8 queue_id0; + u8 unused_0; + __le32 queue_id0_min_bw; + __le32 queue_id0_max_bw; + u8 queue_id0_tsa_assign; + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID0_TSA_ASSIGN_SP (0x0UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID0_TSA_ASSIGN_ETS (0x1UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID0_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID0_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0) + u8 queue_id0_pri_lvl; + u8 queue_id0_bw_weight; + u8 queue_id1; + __le32 queue_id1_min_bw; + __le32 queue_id1_max_bw; + u8 queue_id1_tsa_assign; + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_TSA_ASSIGN_SP (0x0UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_TSA_ASSIGN_ETS (0x1UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID1_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0) + u8 queue_id1_pri_lvl; + u8 queue_id1_bw_weight; + u8 queue_id2; + __le32 queue_id2_min_bw; + __le32 queue_id2_max_bw; + u8 queue_id2_tsa_assign; + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_TSA_ASSIGN_SP (0x0UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_TSA_ASSIGN_ETS (0x1UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID2_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0) + u8 queue_id2_pri_lvl; + u8 queue_id2_bw_weight; + u8 queue_id3; + __le32 queue_id3_min_bw; + __le32 queue_id3_max_bw; + u8 queue_id3_tsa_assign; + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_TSA_ASSIGN_SP (0x0UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_TSA_ASSIGN_ETS (0x1UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID3_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0) + u8 queue_id3_pri_lvl; + u8 queue_id3_bw_weight; + u8 queue_id4; + __le32 queue_id4_min_bw; + __le32 queue_id4_max_bw; + u8 queue_id4_tsa_assign; + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_TSA_ASSIGN_SP (0x0UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_TSA_ASSIGN_ETS (0x1UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID4_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0) + u8 queue_id4_pri_lvl; + u8 queue_id4_bw_weight; + u8 queue_id5; + __le32 queue_id5_min_bw; + __le32 queue_id5_max_bw; + u8 queue_id5_tsa_assign; + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_TSA_ASSIGN_SP (0x0UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_TSA_ASSIGN_ETS (0x1UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID5_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0) + u8 queue_id5_pri_lvl; + u8 queue_id5_bw_weight; + u8 queue_id6; + __le32 queue_id6_min_bw; + __le32 queue_id6_max_bw; + u8 queue_id6_tsa_assign; + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_TSA_ASSIGN_SP (0x0UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_TSA_ASSIGN_ETS (0x1UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID6_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0) + u8 queue_id6_pri_lvl; + u8 queue_id6_bw_weight; + u8 queue_id7; + __le32 queue_id7_min_bw; + __le32 queue_id7_max_bw; + u8 queue_id7_tsa_assign; + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_TSA_ASSIGN_SP (0x0UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_TSA_ASSIGN_ETS (0x1UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_TSA_ASSIGN_RESERVED_FIRST (0x2UL << 0) + #define QUEUE_COS2BW_CFG_REQ_QUEUE_ID7_TSA_ASSIGN_RESERVED_LAST (0xffffUL << 0) + u8 queue_id7_pri_lvl; + u8 queue_id7_bw_weight; + u8 unused_1[5]; +}; + +/* Output (16 bytes) */ +struct hwrm_queue_cos2bw_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_vnic_alloc */ +/* Input (24 bytes) */ +struct hwrm_vnic_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define VNIC_ALLOC_REQ_FLAGS_DEFAULT 0x1UL + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_vnic_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 vnic_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 valid; +}; + +/* hwrm_vnic_free */ +/* Input (24 bytes) */ +struct hwrm_vnic_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 vnic_id; + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_vnic_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_vnic_cfg */ +/* Input (40 bytes) */ +struct hwrm_vnic_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define VNIC_CFG_REQ_FLAGS_DEFAULT 0x1UL + #define VNIC_CFG_REQ_FLAGS_VLAN_STRIP_MODE 0x2UL + __le32 enables; + #define VNIC_CFG_REQ_ENABLES_DFLT_RING_GRP 0x1UL + #define VNIC_CFG_REQ_ENABLES_RSS_RULE 0x2UL + #define VNIC_CFG_REQ_ENABLES_COS_RULE 0x4UL + #define VNIC_CFG_REQ_ENABLES_LB_RULE 0x8UL + #define VNIC_CFG_REQ_ENABLES_MRU 0x10UL + __le16 vnic_id; + __le16 dflt_ring_grp; + __le16 rss_rule; + __le16 cos_rule; + __le16 lb_rule; + __le16 mru; + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_vnic_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_vnic_tpa_cfg */ +/* Input (40 bytes) */ +struct hwrm_vnic_tpa_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define VNIC_TPA_CFG_REQ_FLAGS_TPA 0x1UL + #define VNIC_TPA_CFG_REQ_FLAGS_ENCAP_TPA 0x2UL + #define VNIC_TPA_CFG_REQ_FLAGS_RSC_WND_UPDATE 0x4UL + #define VNIC_TPA_CFG_REQ_FLAGS_GRO 0x8UL + #define VNIC_TPA_CFG_REQ_FLAGS_AGG_WITH_ECN 0x10UL + #define VNIC_TPA_CFG_REQ_FLAGS_AGG_WITH_SAME_GRE_SEQ 0x20UL + #define VNIC_TPA_CFG_REQ_FLAGS_GRO_IPID_CHECK 0x40UL + #define VNIC_TPA_CFG_REQ_FLAGS_GRO_TTL_CHECK 0x80UL + __le32 enables; + #define VNIC_TPA_CFG_REQ_ENABLES_MAX_AGG_SEGS 0x1UL + #define VNIC_TPA_CFG_REQ_ENABLES_MAX_AGGS 0x2UL + #define VNIC_TPA_CFG_REQ_ENABLES_MAX_AGG_TIMER 0x4UL + #define VNIC_TPA_CFG_REQ_ENABLES_MIN_AGG_LEN 0x8UL + __le16 vnic_id; + __le16 max_agg_segs; + #define VNIC_TPA_CFG_REQ_MAX_AGG_SEGS_1 (0x0UL << 0) + #define VNIC_TPA_CFG_REQ_MAX_AGG_SEGS_2 (0x1UL << 0) + #define VNIC_TPA_CFG_REQ_MAX_AGG_SEGS_4 (0x2UL << 0) + #define VNIC_TPA_CFG_REQ_MAX_AGG_SEGS_8 (0x3UL << 0) + #define VNIC_TPA_CFG_REQ_MAX_AGG_SEGS_MAX (0x1fUL << 0) + __le16 max_aggs; + #define VNIC_TPA_CFG_REQ_MAX_AGGS_1 (0x0UL << 0) + #define VNIC_TPA_CFG_REQ_MAX_AGGS_2 (0x1UL << 0) + #define VNIC_TPA_CFG_REQ_MAX_AGGS_4 (0x2UL << 0) + #define VNIC_TPA_CFG_REQ_MAX_AGGS_8 (0x3UL << 0) + #define VNIC_TPA_CFG_REQ_MAX_AGGS_16 (0x4UL << 0) + #define VNIC_TPA_CFG_REQ_MAX_AGGS_MAX (0x7UL << 0) + u8 unused_0; + u8 unused_1; + __le32 max_agg_timer; + __le32 min_agg_len; +}; + +/* Output (16 bytes) */ +struct hwrm_vnic_tpa_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_vnic_rss_cfg */ +/* Input (48 bytes) */ +struct hwrm_vnic_rss_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 hash_type; + #define VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4 0x1UL + #define VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 0x2UL + #define VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4 0x4UL + #define VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 0x8UL + #define VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6 0x10UL + #define VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6 0x20UL + __le32 unused_0; + __le64 ring_grp_tbl_addr; + __le64 hash_key_tbl_addr; + __le16 rss_ctx_idx; + __le16 unused_1[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_vnic_rss_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_vnic_plcmodes_cfg */ +/* Input (40 bytes) */ +struct hwrm_vnic_plcmodes_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define VNIC_PLCMODES_CFG_REQ_FLAGS_REGULAR_PLACEMENT 0x1UL + #define VNIC_PLCMODES_CFG_REQ_FLAGS_JUMBO_PLACEMENT 0x2UL + #define VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV4 0x4UL + #define VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV6 0x8UL + #define VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_FCOE 0x10UL + #define VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_ROCE 0x20UL + __le32 enables; + #define VNIC_PLCMODES_CFG_REQ_ENABLES_JUMBO_THRESH_VALID 0x1UL + #define VNIC_PLCMODES_CFG_REQ_ENABLES_HDS_OFFSET_VALID 0x2UL + #define VNIC_PLCMODES_CFG_REQ_ENABLES_HDS_THRESHOLD_VALID 0x4UL + __le32 vnic_id; + __le16 jumbo_thresh; + __le16 hds_offset; + __le16 hds_threshold; + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_vnic_plcmodes_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_vnic_rss_cos_lb_ctx_alloc */ +/* Input (16 bytes) */ +struct hwrm_vnic_rss_cos_lb_ctx_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; +}; + +/* Output (16 bytes) */ +struct hwrm_vnic_rss_cos_lb_ctx_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 rss_cos_lb_ctx_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 unused_4; + u8 valid; +}; + +/* hwrm_vnic_rss_cos_lb_ctx_free */ +/* Input (24 bytes) */ +struct hwrm_vnic_rss_cos_lb_ctx_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 rss_cos_lb_ctx_id; + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_vnic_rss_cos_lb_ctx_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_ring_alloc */ +/* Input (80 bytes) */ +struct hwrm_ring_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define RING_ALLOC_REQ_ENABLES_ARB_GRP_ID_VALID 0x1UL + #define RING_ALLOC_REQ_ENABLES_INPUT_NUM_VALID 0x2UL + #define RING_ALLOC_REQ_ENABLES_WEIGHT_VALID 0x4UL + #define RING_ALLOC_REQ_ENABLES_STAT_CTX_ID_VALID 0x8UL + #define RING_ALLOC_REQ_ENABLES_MIN_BW_VALID 0x10UL + #define RING_ALLOC_REQ_ENABLES_MAX_BW_VALID 0x20UL + u8 ring_type; + #define RING_ALLOC_REQ_RING_TYPE_CMPL (0x0UL << 0) + #define RING_ALLOC_REQ_RING_TYPE_TX (0x1UL << 0) + #define RING_ALLOC_REQ_RING_TYPE_RX (0x2UL << 0) + #define RING_ALLOC_REQ_RING_TYPE_STATUS (0x3UL << 0) + #define RING_ALLOC_REQ_RING_TYPE_CMD (0x4UL << 0) + u8 unused_0; + __le16 unused_1; + __le64 page_tbl_addr; + __le32 fbo; + u8 page_size; + u8 page_tbl_depth; + u8 unused_2; + u8 unused_3; + __le32 length; + __le16 logical_id; + __le16 cmpl_ring_id; + __le16 queue_id; + u8 unused_4; + u8 unused_5; + __le32 arb_grp_id; + __le16 input_number; + u8 unused_6; + u8 unused_7; + __le32 weight; + __le32 stat_ctx_id; + __le32 min_bw; + __le32 max_bw; + u8 int_mode; + #define RING_ALLOC_REQ_INT_MODE_LEGACY (0x0UL << 0) + #define RING_ALLOC_REQ_INT_MODE_MSI (0x1UL << 0) + #define RING_ALLOC_REQ_INT_MODE_MSIX (0x2UL << 0) + #define RING_ALLOC_REQ_INT_MODE_POLL (0x3UL << 0) + u8 unused_8[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_ring_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 ring_id; + __le16 logical_ring_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 valid; +}; + +/* hwrm_ring_free */ +/* Input (24 bytes) */ +struct hwrm_ring_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + u8 ring_type; + #define RING_FREE_REQ_RING_TYPE_CMPL (0x0UL << 0) + #define RING_FREE_REQ_RING_TYPE_TX (0x1UL << 0) + #define RING_FREE_REQ_RING_TYPE_RX (0x2UL << 0) + #define RING_FREE_REQ_RING_TYPE_STATUS (0x3UL << 0) + #define RING_FREE_REQ_RING_TYPE_CMD (0x4UL << 0) + u8 unused_0; + __le16 ring_id; + __le32 unused_1; +}; + +/* Output (16 bytes) */ +struct hwrm_ring_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_ring_cmpl_ring_qaggint_params */ +/* Input (24 bytes) */ +struct hwrm_ring_cmpl_ring_qaggint_params_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 ring_id; + __le16 unused_0[3]; +}; + +/* Output (32 bytes) */ +struct hwrm_ring_cmpl_ring_qaggint_params_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 flags; + #define RING_CMPL_RING_QAGGINT_PARAMS_RESP_FLAGS_TIMER_RESET 0x1UL + #define RING_CMPL_RING_QAGGINT_PARAMS_RESP_FLAGS_RING_IDLE 0x2UL + __le16 num_cmpl_dma_aggr; + __le16 num_cmpl_dma_aggr_during_int; + __le16 cmpl_aggr_dma_tmr; + __le16 cmpl_aggr_dma_tmr_during_int; + __le16 int_lat_tmr_min; + __le16 int_lat_tmr_max; + __le16 num_cmpl_aggr_int; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_ring_cmpl_ring_cfg_aggint_params */ +/* Input (40 bytes) */ +struct hwrm_ring_cmpl_ring_cfg_aggint_params_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 ring_id; + __le16 flags; + #define RING_CMPL_RING_CFG_AGGINT_PARAMS_REQ_FLAGS_TIMER_RESET 0x1UL + #define RING_CMPL_RING_CFG_AGGINT_PARAMS_REQ_FLAGS_RING_IDLE 0x2UL + __le16 num_cmpl_dma_aggr; + __le16 num_cmpl_dma_aggr_during_int; + __le16 cmpl_aggr_dma_tmr; + __le16 cmpl_aggr_dma_tmr_during_int; + __le16 int_lat_tmr_min; + __le16 int_lat_tmr_max; + __le16 num_cmpl_aggr_int; + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_ring_cmpl_ring_cfg_aggint_params_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_ring_reset */ +/* Input (24 bytes) */ +struct hwrm_ring_reset_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + u8 ring_type; + #define RING_RESET_REQ_RING_TYPE_CMPL (0x0UL << 0) + #define RING_RESET_REQ_RING_TYPE_TX (0x1UL << 0) + #define RING_RESET_REQ_RING_TYPE_RX (0x2UL << 0) + #define RING_RESET_REQ_RING_TYPE_STATUS (0x3UL << 0) + #define RING_RESET_REQ_RING_TYPE_CMD (0x4UL << 0) + u8 unused_0; + __le16 ring_id; + __le32 unused_1; +}; + +/* Output (16 bytes) */ +struct hwrm_ring_reset_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_ring_grp_alloc */ +/* Input (24 bytes) */ +struct hwrm_ring_grp_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 cr; + __le16 rr; + __le16 ar; + __le16 sc; +}; + +/* Output (16 bytes) */ +struct hwrm_ring_grp_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 ring_group_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 valid; +}; + +/* hwrm_ring_grp_free */ +/* Input (24 bytes) */ +struct hwrm_ring_grp_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 ring_group_id; + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_ring_grp_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_arb_grp_alloc */ +/* Input (24 bytes) */ +struct hwrm_arb_grp_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 input_number; + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_arb_grp_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 arb_grp_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 unused_4; + u8 valid; +}; + +/* hwrm_arb_grp_cfg */ +/* Input (32 bytes) */ +struct hwrm_arb_grp_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 arb_grp_id; + __le16 input_number; + __le16 tx_ring; + __le32 weight; + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_arb_grp_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_cfa_l2_filter_alloc */ +/* Input (96 bytes) */ +struct hwrm_cfa_l2_filter_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH 0x1UL + #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH_TX (0x0UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_PATH_RX (0x1UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_LOOPBACK 0x2UL + #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_DROP 0x4UL + #define CFA_L2_FILTER_ALLOC_REQ_FLAGS_OUTERMOST 0x8UL + __le32 enables; + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_ADDR 0x1UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_ADDR_MASK 0x2UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_OVLAN 0x4UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_OVLAN_MASK 0x8UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_IVLAN 0x10UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_L2_IVLAN_MASK 0x20UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_L2_ADDR 0x40UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_L2_ADDR_MASK 0x80UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_L2_OVLAN 0x100UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_L2_OVLAN_MASK 0x200UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_L2_IVLAN 0x400UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_T_L2_IVLAN_MASK 0x800UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_SRC_TYPE 0x1000UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_SRC_ID 0x2000UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_TUNNEL_TYPE 0x4000UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_DST_VNIC_ID 0x8000UL + #define CFA_L2_FILTER_ALLOC_REQ_ENABLES_MIRROR_VNIC_ID 0x10000UL + u8 l2_addr[6]; + u8 unused_0; + u8 unused_1; + u8 l2_addr_mask[6]; + __le16 l2_ovlan; + __le16 l2_ovlan_mask; + __le16 l2_ivlan; + __le16 l2_ivlan_mask; + u8 unused_2; + u8 unused_3; + u8 t_l2_addr[6]; + u8 unused_4; + u8 unused_5; + u8 t_l2_addr_mask[6]; + __le16 t_l2_ovlan; + __le16 t_l2_ovlan_mask; + __le16 t_l2_ivlan; + __le16 t_l2_ivlan_mask; + u8 src_type; + #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_NPORT (0x0UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_PF (0x1UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_VF (0x2UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_VNIC (0x3UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_KONG (0x4UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_APE (0x5UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_BONO (0x6UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_SRC_TYPE_TANG (0x7UL << 0) + u8 unused_6; + __le32 src_id; + u8 tunnel_type; + #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_NONTUNNEL (0x0UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN (0x1UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_NVGRE (0x2UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_L2GRE (0x3UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPIP (0x4UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_GENEVE (0x5UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_MPLS (0x6UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_STT (0x7UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPGRE (0x8UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_TUNNEL_TYPE_ANYTUNNEL (0xffUL << 0) + u8 unused_7; + __le16 dst_vnic_id; + __le16 mirror_vnic_id; + u8 pri_hint; + #define CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_NO_PREFER (0x0UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_ABOVE_FILTER (0x1UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_BELOW_FILTER (0x2UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_MAX (0x3UL << 0) + #define CFA_L2_FILTER_ALLOC_REQ_PRI_HINT_MIN (0x4UL << 0) + u8 unused_8; + __le32 unused_9; + __le64 l2_filter_id_hint; +}; + +/* Output (24 bytes) */ +struct hwrm_cfa_l2_filter_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le64 l2_filter_id; + __le32 flow_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 valid; +}; + +/* hwrm_cfa_l2_filter_free */ +/* Input (24 bytes) */ +struct hwrm_cfa_l2_filter_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le64 l2_filter_id; +}; + +/* Output (16 bytes) */ +struct hwrm_cfa_l2_filter_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_cfa_l2_filter_cfg */ +/* Input (40 bytes) */ +struct hwrm_cfa_l2_filter_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define CFA_L2_FILTER_CFG_REQ_FLAGS_PATH 0x1UL + #define CFA_L2_FILTER_CFG_REQ_FLAGS_PATH_TX (0x0UL << 0) + #define CFA_L2_FILTER_CFG_REQ_FLAGS_PATH_RX (0x1UL << 0) + #define CFA_L2_FILTER_CFG_REQ_FLAGS_DROP 0x2UL + __le32 enables; + #define CFA_L2_FILTER_CFG_REQ_ENABLES_DST_VNIC_ID_VALID 0x1UL + __le64 l2_filter_id; + __le32 dst_vnic_id; + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_cfa_l2_filter_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_cfa_l2_set_rx_mask */ +/* Input (40 bytes) */ +struct hwrm_cfa_l2_set_rx_mask_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 dflt_vnic_id; + __le32 mask; + #define CFA_L2_SET_RX_MASK_REQ_MASK_UNICAST 0x1UL + #define CFA_L2_SET_RX_MASK_REQ_MASK_MCAST 0x2UL + #define CFA_L2_SET_RX_MASK_REQ_MASK_ALL_MCAST 0x4UL + #define CFA_L2_SET_RX_MASK_REQ_MASK_BCAST 0x8UL + #define CFA_L2_SET_RX_MASK_REQ_MASK_PROMISCUOUS 0x10UL + #define CFA_L2_SET_RX_MASK_REQ_MASK_OUTERMOST 0x20UL + __le64 mc_tbl_addr; + __le32 num_mc_entries; + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_cfa_l2_set_rx_mask_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_cfa_l2_set_bcastmcast_mirroring */ +/* Input (32 bytes) */ +struct hwrm_cfa_l2_set_bcastmcast_mirroring_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 dflt_vnic_id; + __le32 mirroring_flags; + #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MIRRORING_FLAGS_BCAST_MIRRORING 0x1UL + #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MIRRORING_FLAGS_MCAST_MIRRORING 0x2UL + #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MIRRORING_FLAGS_BCAST_SRC_KNOCKOUT 0x4UL + #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MIRRORING_FLAGS_MCAST_SRC_KNOCKOUT 0x8UL + #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MIRRORING_FLAGS_VLAN_ID_VALID 0x10UL + __le16 vlan_id; + u8 bcast_domain; + #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_BCAST_DOMAIN_PFONLY (0x0UL << 0) + #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_BCAST_DOMAIN_ALLPFS (0x1UL << 0) + #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_BCAST_DOMAIN_ALLPFSVFS (0x2UL << 0) + u8 mcast_domain; + #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MCAST_DOMAIN_PFONLY (0x0UL << 0) + #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MCAST_DOMAIN_ALLPFS (0x1UL << 0) + #define CFA_L2_SET_BCASTMCAST_MIRRORING_REQ_MCAST_DOMAIN_ALLPFSVFS (0x2UL << 0) + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_cfa_l2_set_bcastmcast_mirroring_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_cfa_tunnel_filter_alloc */ +/* Input (88 bytes) */ +struct hwrm_cfa_tunnel_filter_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define CFA_TUNNEL_FILTER_ALLOC_REQ_FLAGS_LOOPBACK 0x1UL + __le32 enables; + #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_L2_FILTER_ID 0x1UL + #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_L2_ADDR 0x2UL + #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_L2_IVLAN 0x4UL + #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_L3_ADDR 0x8UL + #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_L3_ADDR_TYPE 0x10UL + #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_T_L3_ADDR_TYPE 0x20UL + #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_T_L3_ADDR 0x40UL + #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_TUNNEL_TYPE 0x80UL + #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_VNI 0x100UL + #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_DST_VNIC_ID 0x200UL + #define CFA_TUNNEL_FILTER_ALLOC_REQ_ENABLES_MIRROR_VNIC_ID 0x400UL + __le64 l2_filter_id; + u8 l2_addr[6]; + __le16 l2_ivlan; + __le32 l3_addr[4]; + __le32 t_l3_addr[4]; + u8 l3_addr_type; + u8 t_l3_addr_type; + u8 tunnel_type; + #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_NONTUNNEL (0x0UL << 0) + #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN (0x1UL << 0) + #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_NVGRE (0x2UL << 0) + #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_L2GRE (0x3UL << 0) + #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPIP (0x4UL << 0) + #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_GENEVE (0x5UL << 0) + #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_MPLS (0x6UL << 0) + #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_STT (0x7UL << 0) + #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPGRE (0x8UL << 0) + #define CFA_TUNNEL_FILTER_ALLOC_REQ_TUNNEL_TYPE_ANYTUNNEL (0xffUL << 0) + u8 unused_0; + __le32 vni; + __le32 dst_vnic_id; + __le32 mirror_vnic_id; +}; + +/* Output (24 bytes) */ +struct hwrm_cfa_tunnel_filter_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le64 tunnel_filter_id; + __le32 flow_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 valid; +}; + +/* hwrm_cfa_tunnel_filter_free */ +/* Input (24 bytes) */ +struct hwrm_cfa_tunnel_filter_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le64 tunnel_filter_id; +}; + +/* Output (16 bytes) */ +struct hwrm_cfa_tunnel_filter_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_cfa_encap_record_alloc */ +/* Input (32 bytes) */ +struct hwrm_cfa_encap_record_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define CFA_ENCAP_RECORD_ALLOC_REQ_FLAGS_LOOPBACK 0x1UL + u8 encap_type; + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VXLAN (0x1UL << 0) + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_NVGRE (0x2UL << 0) + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_L2GRE (0x3UL << 0) + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPIP (0x4UL << 0) + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_GENEVE (0x5UL << 0) + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_MPLS (0x6UL << 0) + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_VLAN (0x7UL << 0) + #define CFA_ENCAP_RECORD_ALLOC_REQ_ENCAP_TYPE_IPGRE (0x8UL << 0) + u8 unused_0; + __le16 unused_1; + __le32 encap_data[16]; +}; + +/* Output (24 bytes) */ +struct hwrm_cfa_encap_record_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le64 encap_record_id; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_cfa_encap_record_free */ +/* Input (24 bytes) */ +struct hwrm_cfa_encap_record_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le64 encap_record_id; +}; + +/* Output (16 bytes) */ +struct hwrm_cfa_encap_record_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_cfa_ntuple_filter_alloc */ +/* Input (128 bytes) */ +struct hwrm_cfa_ntuple_filter_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_LOOPBACK 0x1UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_DROP 0x2UL + __le32 enables; + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_L2_FILTER_ID 0x1UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_ETHERTYPE 0x2UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_TUNNEL_TYPE 0x4UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_MACADDR 0x8UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_IPADDR_TYPE 0x10UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_IPADDR 0x20UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_IPADDR_MASK 0x40UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_IPADDR 0x80UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_IPADDR_MASK 0x100UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_IP_PROTOCOL 0x200UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_PORT 0x400UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_SRC_PORT_MASK 0x800UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_PORT 0x1000UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_PORT_MASK 0x2000UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_PRI_HINT 0x4000UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_NTUPLE_FILTER_ID 0x8000UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_DST_VNIC_ID 0x10000UL + #define CFA_NTUPLE_FILTER_ALLOC_REQ_ENABLES_MIRROR_VNIC_ID 0x20000UL + __le64 l2_filter_id; + u8 src_macaddr[6]; + __be16 ethertype; + u8 ipaddr_type; + u8 ip_protocol; + __le16 dst_vnic_id; + __le16 mirror_vnic_id; + u8 tunnel_type; + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_NONTUNNEL (0x0UL << 0) + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN (0x1UL << 0) + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_NVGRE (0x2UL << 0) + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_L2GRE (0x3UL << 0) + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPIP (0x4UL << 0) + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_GENEVE (0x5UL << 0) + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_MPLS (0x6UL << 0) + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_STT (0x7UL << 0) + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_IPGRE (0x8UL << 0) + #define CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_ANYTUNNEL (0xffUL << 0) + u8 pri_hint; + __be32 src_ipaddr[4]; + __be32 src_ipaddr_mask[4]; + __be32 dst_ipaddr[4]; + __be32 dst_ipaddr_mask[4]; + __be16 src_port; + __be16 src_port_mask; + __be16 dst_port; + __be16 dst_port_mask; + __le64 ntuple_filter_id_hint; +}; + +/* Output (24 bytes) */ +struct hwrm_cfa_ntuple_filter_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le64 ntuple_filter_id; + __le32 flow_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 valid; +}; + +/* hwrm_cfa_ntuple_filter_free */ +/* Input (24 bytes) */ +struct hwrm_cfa_ntuple_filter_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le64 ntuple_filter_id; +}; + +/* Output (16 bytes) */ +struct hwrm_cfa_ntuple_filter_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_cfa_ntuple_filter_cfg */ +/* Input (40 bytes) */ +struct hwrm_cfa_ntuple_filter_cfg_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define CFA_NTUPLE_FILTER_CFG_REQ_ENABLES_NEW_DST_VNIC_ID_VALID 0x1UL + #define CFA_NTUPLE_FILTER_CFG_REQ_ENABLES_NEW_MIRROR_VNIC_ID_VALID 0x2UL + __le32 unused_0; + __le64 ntuple_filter_id; + __le32 new_dst_vnic_id; + __le32 new_mirror_vnic_id; +}; + +/* Output (16 bytes) */ +struct hwrm_cfa_ntuple_filter_cfg_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_tunnel_dst_port_query */ +/* Input (24 bytes) */ +struct hwrm_tunnel_dst_port_query_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + u8 tunnel_type; + #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_NONTUNNEL (0x0UL << 0) + #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_VXLAN (0x1UL << 0) + #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_NVGRE (0x2UL << 0) + #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_L2GRE (0x3UL << 0) + #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_IPIP (0x4UL << 0) + #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_GENEVE (0x5UL << 0) + #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_MPLS (0x6UL << 0) + #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_STT (0x7UL << 0) + #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_IPGRE (0x8UL << 0) + #define TUNNEL_DST_PORT_QUERY_REQ_TUNNEL_TYPE_ANYTUNNEL (0xffUL << 0) + u8 unused_0[7]; +}; + +/* Output (16 bytes) */ +struct hwrm_tunnel_dst_port_query_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 tunnel_dst_port_id; + __be16 tunnel_dst_port_val; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 valid; +}; + +/* hwrm_tunnel_dst_port_alloc */ +/* Input (24 bytes) */ +struct hwrm_tunnel_dst_port_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + u8 tunnel_type; + #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_NONTUNNEL (0x0UL << 0) + #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_VXLAN (0x1UL << 0) + #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_NVGRE (0x2UL << 0) + #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_L2GRE (0x3UL << 0) + #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_IPIP (0x4UL << 0) + #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_GENEVE (0x5UL << 0) + #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_MPLS (0x6UL << 0) + #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_STT (0x7UL << 0) + #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_IPGRE (0x8UL << 0) + #define TUNNEL_DST_PORT_ALLOC_REQ_TUNNEL_TYPE_ANYTUNNEL (0xffUL << 0) + u8 unused_0; + __be16 tunnel_dst_port_val; + __le32 unused_1; +}; + +/* Output (16 bytes) */ +struct hwrm_tunnel_dst_port_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 tunnel_dst_port_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 unused_4; + u8 valid; +}; + +/* hwrm_tunnel_dst_port_free */ +/* Input (24 bytes) */ +struct hwrm_tunnel_dst_port_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + u8 tunnel_type; + #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_NONTUNNEL (0x0UL << 0) + #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN (0x1UL << 0) + #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_NVGRE (0x2UL << 0) + #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_L2GRE (0x3UL << 0) + #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_IPIP (0x4UL << 0) + #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE (0x5UL << 0) + #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_MPLS (0x6UL << 0) + #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_STT (0x7UL << 0) + #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_IPGRE (0x8UL << 0) + #define TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_ANYTUNNEL (0xffUL << 0) + u8 unused_0; + __le16 tunnel_dst_port_id; + __le32 unused_1; +}; + +/* Output (16 bytes) */ +struct hwrm_tunnel_dst_port_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_stat_ctx_alloc */ +/* Input (32 bytes) */ +struct hwrm_stat_ctx_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le64 stats_dma_addr; + __le32 update_period_ms; + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_stat_ctx_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 stat_ctx_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 valid; +}; + +/* hwrm_stat_ctx_free */ +/* Input (24 bytes) */ +struct hwrm_stat_ctx_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 stat_ctx_id; + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_stat_ctx_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 stat_ctx_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 valid; +}; + +/* hwrm_stat_ctx_query */ +/* Input (24 bytes) */ +struct hwrm_stat_ctx_query_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 stat_ctx_id; + __le32 unused_0; +}; + +/* Output (176 bytes) */ +struct hwrm_stat_ctx_query_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le64 tx_ucast_pkts; + __le64 tx_mcast_pkts; + __le64 tx_bcast_pkts; + __le64 tx_err_pkts; + __le64 tx_drop_pkts; + __le64 tx_ucast_bytes; + __le64 tx_mcast_bytes; + __le64 tx_bcast_bytes; + __le64 rx_ucast_pkts; + __le64 rx_mcast_pkts; + __le64 rx_bcast_pkts; + __le64 rx_err_pkts; + __le64 rx_drop_pkts; + __le64 rx_ucast_bytes; + __le64 rx_mcast_bytes; + __le64 rx_bcast_bytes; + __le64 rx_agg_pkts; + __le64 rx_agg_bytes; + __le64 rx_agg_events; + __le64 rx_agg_aborts; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_stat_ctx_clr_stats */ +/* Input (24 bytes) */ +struct hwrm_stat_ctx_clr_stats_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 stat_ctx_id; + __le32 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_stat_ctx_clr_stats_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_mgmt_l2_filter_alloc */ +/* Input (56 bytes) */ +struct hwrm_mgmt_l2_filter_alloc_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 flags; + #define MGMT_L2_FILTER_ALLOC_REQ_FLAGS_PATH 0x1UL + #define MGMT_L2_FILTER_ALLOC_REQ_FLAGS_PATH_TX (0x0UL << 0) + #define MGMT_L2_FILTER_ALLOC_REQ_FLAGS_PATH_RX (0x1UL << 0) + __le32 enables; + #define MGMT_L2_FILTER_ALLOC_REQ_ENABLES_L2_ADDRESS 0x1UL + #define MGMT_L2_FILTER_ALLOC_REQ_ENABLES_OVLAN 0x2UL + #define MGMT_L2_FILTER_ALLOC_REQ_ENABLES_IVLAN 0x4UL + #define MGMT_L2_FILTER_ALLOC_REQ_ENABLES_ACTION_ID 0x8UL + u8 l2_address[6]; + u8 unused_0; + u8 unused_1; + u8 l2_address_mask[6]; + __le16 ovlan; + __le16 ovlan_mask; + __le16 ivlan; + __le16 ivlan_mask; + u8 unused_2; + u8 unused_3; + __le32 action_id; + u8 action_bypass; + #define MGMT_L2_FILTER_ALLOC_REQ_ACTION_BYPASS 0x1UL + u8 unused_5[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_mgmt_l2_filter_alloc_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 mgmt_l2_filter_id; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 unused_4; + u8 valid; +}; + +/* hwrm_mgmt_l2_filter_free */ +/* Input (24 bytes) */ +struct hwrm_mgmt_l2_filter_free_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 mgmt_l2_filter_id; + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_mgmt_l2_filter_free_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_nvm_raw_write_blk */ +/* Input (32 bytes) */ +struct hwrm_nvm_raw_write_blk_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le64 host_src_addr; + __le32 dest_addr; + __le32 len; +}; + +/* Output (16 bytes) */ +struct hwrm_nvm_raw_write_blk_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_nvm_read */ +/* Input (40 bytes) */ +struct hwrm_nvm_read_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le64 host_dest_addr; + __le16 dir_idx; + u8 unused_0; + u8 unused_1; + __le32 offset; + __le32 len; + __le32 unused_2; +}; + +/* Output (16 bytes) */ +struct hwrm_nvm_read_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_nvm_raw_dump */ +/* Input (32 bytes) */ +struct hwrm_nvm_raw_dump_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le64 host_dest_addr; + __le32 offset; + __le32 len; +}; + +/* Output (16 bytes) */ +struct hwrm_nvm_raw_dump_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_nvm_get_dir_entries */ +/* Input (24 bytes) */ +struct hwrm_nvm_get_dir_entries_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le64 host_dest_addr; +}; + +/* Output (16 bytes) */ +struct hwrm_nvm_get_dir_entries_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_nvm_get_dir_info */ +/* Input (16 bytes) */ +struct hwrm_nvm_get_dir_info_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; +}; + +/* Output (24 bytes) */ +struct hwrm_nvm_get_dir_info_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 entries; + __le32 entry_length; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_nvm_write */ +/* Input (40 bytes) */ +struct hwrm_nvm_write_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le64 host_src_addr; + __le16 dir_type; + __le16 dir_ordinal; + __le16 dir_ext; + __le16 dir_attr; + __le32 dir_data_length; + __le16 option; + __le16 flags; + #define NVM_WRITE_REQ_FLAGS_KEEP_ORIG_ACTIVE_IMG 0x1UL +}; + +/* Output (16 bytes) */ +struct hwrm_nvm_write_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_nvm_modify */ +/* Input (40 bytes) */ +struct hwrm_nvm_modify_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le64 host_src_addr; + __le16 dir_idx; + u8 unused_0; + u8 unused_1; + __le32 offset; + __le32 len; + __le32 unused_2; +}; + +/* Output (16 bytes) */ +struct hwrm_nvm_modify_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_nvm_find_dir_entry */ +/* Input (32 bytes) */ +struct hwrm_nvm_find_dir_entry_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define NVM_FIND_DIR_ENTRY_REQ_ENABLES_DIR_IDX_VALID 0x1UL + __le16 dir_idx; + __le16 dir_type; + __le16 dir_ordinal; + __le16 dir_ext; + u8 opt_ordinal; + #define NVM_FIND_DIR_ENTRY_REQ_OPT_ORDINAL_MASK 0x3UL + #define NVM_FIND_DIR_ENTRY_REQ_OPT_ORDINAL_SFT 0 + #define NVM_FIND_DIR_ENTRY_REQ_OPT_ORDINAL_EQ (0x0UL << 0) + #define NVM_FIND_DIR_ENTRY_REQ_OPT_ORDINAL_GE (0x1UL << 0) + #define NVM_FIND_DIR_ENTRY_REQ_OPT_ORDINAL_GT (0x2UL << 0) + u8 unused_1[3]; +}; + +/* Output (32 bytes) */ +struct hwrm_nvm_find_dir_entry_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 dir_item_length; + __le32 dir_data_length; + __le32 fw_ver; + __le16 dir_ordinal; + __le16 dir_idx; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_nvm_erase_dir_entry */ +/* Input (24 bytes) */ +struct hwrm_nvm_erase_dir_entry_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 dir_idx; + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_nvm_erase_dir_entry_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_nvm_get_dev_info */ +/* Input (16 bytes) */ +struct hwrm_nvm_get_dev_info_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; +}; + +/* Output (32 bytes) */ +struct hwrm_nvm_get_dev_info_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le16 manufacturer_id; + __le16 device_id; + __le32 sector_size; + __le32 nvram_size; + __le32 reserved_size; + __le32 available_size; + u8 unused_0; + u8 unused_1; + u8 unused_2; + u8 valid; +}; + +/* hwrm_nvm_mod_dir_entry */ +/* Input (32 bytes) */ +struct hwrm_nvm_mod_dir_entry_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 enables; + #define NVM_MOD_DIR_ENTRY_REQ_ENABLES_CHECKSUM 0x1UL + __le16 dir_idx; + __le16 dir_ordinal; + __le16 dir_ext; + __le16 dir_attr; + __le32 checksum; +}; + +/* Output (16 bytes) */ +struct hwrm_nvm_mod_dir_entry_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_nvm_verify_update */ +/* Input (24 bytes) */ +struct hwrm_nvm_verify_update_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 dir_type; + __le16 dir_ordinal; + __le16 dir_ext; + __le16 unused_0; +}; + +/* Output (16 bytes) */ +struct hwrm_nvm_verify_update_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_exec_fwd_resp */ +/* Input (120 bytes) */ +struct hwrm_exec_fwd_resp_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 encap_request[24]; + __le16 encap_resp_target_id; + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_exec_fwd_resp_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_reject_fwd_resp */ +/* Input (120 bytes) */ +struct hwrm_reject_fwd_resp_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le32 encap_request[24]; + __le16 encap_resp_target_id; + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_reject_fwd_resp_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_fwd_resp */ +/* Input (40 bytes) */ +struct hwrm_fwd_resp_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 encap_resp_target_id; + __le16 encap_resp_cmpl_ring; + __le16 encap_resp_len; + u8 unused_0; + u8 unused_1; + __le64 encap_resp_addr; + __le32 encap_resp[24]; +}; + +/* Output (16 bytes) */ +struct hwrm_fwd_resp_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_fwd_async_event_cmpl */ +/* Input (32 bytes) */ +struct hwrm_fwd_async_event_cmpl_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + __le16 encap_async_event_target_id; + u8 unused_0; + u8 unused_1; + u8 unused_2[3]; + u8 unused_3; + __le32 encap_async_event_cmpl[4]; +}; + +/* Output (16 bytes) */ +struct hwrm_fwd_async_event_cmpl_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + __le32 unused_0; + u8 unused_1; + u8 unused_2; + u8 unused_3; + u8 valid; +}; + +/* hwrm_fw_reset */ +/* Input (24 bytes) */ +struct hwrm_fw_reset_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + u8 embedded_proc_type; + #define FW_RESET_REQ_EMBEDDED_PROC_TYPE_CHIMP (0x0UL << 0) + #define FW_RESET_REQ_EMBEDDED_PROC_TYPE_APE (0x1UL << 0) + #define FW_RESET_REQ_EMBEDDED_PROC_TYPE_KONG (0x2UL << 0) + #define FW_RESET_REQ_EMBEDDED_PROC_TYPE_BONO (0x3UL << 0) + #define FW_RESET_REQ_EMBEDDED_PROC_TYPE_TANG (0x4UL << 0) + u8 selfrst_status; + #define FW_RESET_REQ_SELFRST_STATUS_SELFRSTNONE (0x0UL << 0) + #define FW_RESET_REQ_SELFRST_STATUS_SELFRSTASAP (0x1UL << 0) + #define FW_RESET_REQ_SELFRST_STATUS_SELFRSTPCIERST (0x2UL << 0) + __le16 unused_0[3]; +}; + +/* Output (16 bytes) */ +struct hwrm_fw_reset_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + u8 selfrst_status; + #define FW_RESET_RESP_SELFRST_STATUS_SELFRSTNONE (0x0UL << 0) + #define FW_RESET_RESP_SELFRST_STATUS_SELFRSTASAP (0x1UL << 0) + #define FW_RESET_RESP_SELFRST_STATUS_SELFRSTPCIERST (0x2UL << 0) + u8 unused_0; + __le16 unused_1; + u8 unused_2; + u8 unused_3; + u8 unused_4; + u8 valid; +}; + +/* hwrm_fw_qstatus */ +/* Input (24 bytes) */ +struct hwrm_fw_qstatus_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; + u8 embedded_proc_type; + #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_CHIMP (0x0UL << 0) + #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_APE (0x1UL << 0) + #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_KONG (0x2UL << 0) + #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_BONO (0x3UL << 0) + #define FW_QSTATUS_REQ_EMBEDDED_PROC_TYPE_TANG (0x4UL << 0) + u8 unused_0[7]; +}; + +/* Output (16 bytes) */ +struct hwrm_fw_qstatus_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + u8 selfrst_status; + #define FW_QSTATUS_RESP_SELFRST_STATUS_SELFRSTNONE (0x0UL << 0) + #define FW_QSTATUS_RESP_SELFRST_STATUS_SELFRSTASAP (0x1UL << 0) + #define FW_QSTATUS_RESP_SELFRST_STATUS_SELFRSTPCIERST (0x2UL << 0) + u8 unused_0; + __le16 unused_1; + u8 unused_2; + u8 unused_3; + u8 unused_4; + u8 valid; +}; + +/* hwrm_temp_monitor_query */ +/* Input (16 bytes) */ +struct hwrm_temp_monitor_query_input { + __le16 req_type; + __le16 cmpl_ring; + __le16 seq_id; + __le16 target_id; + __le64 resp_addr; +}; + +/* Output (16 bytes) */ +struct hwrm_temp_monitor_query_output { + __le16 error_code; + __le16 req_type; + __le16 seq_id; + __le16 resp_len; + u8 temp; + u8 unused_0; + __le16 unused_1; + u8 unused_2; + u8 unused_3; + u8 unused_4; + u8 valid; +}; + +#endif diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h new file mode 100644 index 000000000000..3cf3e1b70b64 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_nvm_defs.h @@ -0,0 +1,59 @@ +/* Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2014-2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + */ + +#ifndef _BNXT_NVM_DEFS_H_ +#define _BNXT_NVM_DEFS_H_ + +enum bnxt_nvm_directory_type { + BNX_DIR_TYPE_UNUSED = 0, + BNX_DIR_TYPE_PKG_LOG = 1, + BNX_DIR_TYPE_CHIMP_PATCH = 3, + BNX_DIR_TYPE_BOOTCODE = 4, + BNX_DIR_TYPE_VPD = 5, + BNX_DIR_TYPE_EXP_ROM_MBA = 6, + BNX_DIR_TYPE_AVS = 7, + BNX_DIR_TYPE_PCIE = 8, + BNX_DIR_TYPE_PORT_MACRO = 9, + BNX_DIR_TYPE_APE_FW = 10, + BNX_DIR_TYPE_APE_PATCH = 11, + BNX_DIR_TYPE_KONG_FW = 12, + BNX_DIR_TYPE_KONG_PATCH = 13, + BNX_DIR_TYPE_BONO_FW = 14, + BNX_DIR_TYPE_BONO_PATCH = 15, + BNX_DIR_TYPE_TANG_FW = 16, + BNX_DIR_TYPE_TANG_PATCH = 17, + BNX_DIR_TYPE_BOOTCODE_2 = 18, + BNX_DIR_TYPE_CCM = 19, + BNX_DIR_TYPE_PCI_CFG = 20, + BNX_DIR_TYPE_TSCF_UCODE = 21, + BNX_DIR_TYPE_ISCSI_BOOT = 22, + BNX_DIR_TYPE_ISCSI_BOOT_IPV6 = 24, + BNX_DIR_TYPE_ISCSI_BOOT_IPV4N6 = 25, + BNX_DIR_TYPE_ISCSI_BOOT_CFG6 = 26, + BNX_DIR_TYPE_EXT_PHY = 27, + BNX_DIR_TYPE_SHARED_CFG = 40, + BNX_DIR_TYPE_PORT_CFG = 41, + BNX_DIR_TYPE_FUNC_CFG = 42, + BNX_DIR_TYPE_MGMT_CFG = 48, + BNX_DIR_TYPE_MGMT_DATA = 49, + BNX_DIR_TYPE_MGMT_WEB_DATA = 50, + BNX_DIR_TYPE_MGMT_WEB_META = 51, + BNX_DIR_TYPE_MGMT_EVENT_LOG = 52, + BNX_DIR_TYPE_MGMT_AUDIT_LOG = 53 +}; + +#define BNX_DIR_ORDINAL_FIRST 0 + +#define BNX_DIR_EXT_INACTIVE (1 << 0) +#define BNX_DIR_EXT_UPDATE (1 << 1) + +#define BNX_DIR_ATTR_NO_CHKSUM (1 << 0) +#define BNX_DIR_ATTR_PROP_STREAM (1 << 1) + +#endif /* Don't add anything after this line */ diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c new file mode 100644 index 000000000000..3422147a65f4 --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c @@ -0,0 +1,787 @@ +/* Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2014-2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include "bnxt_hsi.h" +#include "bnxt.h" +#include "bnxt_sriov.h" +#include "bnxt_ethtool.h" + +#ifdef CONFIG_BNXT_SRIOV +static int bnxt_vf_ndo_prep(struct bnxt *bp, int vf_id) +{ + if (bp->state != BNXT_STATE_OPEN) { + netdev_err(bp->dev, "vf ndo called though PF is down\n"); + return -EINVAL; + } + if (!bp->pf.active_vfs) { + netdev_err(bp->dev, "vf ndo called though sriov is disabled\n"); + return -EINVAL; + } + if (vf_id >= bp->pf.max_vfs) { + netdev_err(bp->dev, "Invalid VF id %d\n", vf_id); + return -EINVAL; + } + return 0; +} + +int bnxt_set_vf_spoofchk(struct net_device *dev, int vf_id, bool setting) +{ + struct hwrm_func_cfg_input req = {0}; + struct bnxt *bp = netdev_priv(dev); + struct bnxt_vf_info *vf; + bool old_setting = false; + u32 func_flags; + int rc; + + rc = bnxt_vf_ndo_prep(bp, vf_id); + if (rc) + return rc; + + vf = &bp->pf.vf[vf_id]; + if (vf->flags & BNXT_VF_SPOOFCHK) + old_setting = true; + if (old_setting == setting) + return 0; + + func_flags = vf->func_flags; + if (setting) + func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK; + else + func_flags &= ~FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK; + /*TODO: if the driver supports VLAN filter on guest VLAN, + * the spoof check should also include vlan anti-spoofing + */ + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); + req.vf_id = cpu_to_le16(vf->fw_fid); + req.flags = cpu_to_le32(func_flags); + rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (!rc) { + vf->func_flags = func_flags; + if (setting) + vf->flags |= BNXT_VF_SPOOFCHK; + else + vf->flags &= ~BNXT_VF_SPOOFCHK; + } + return rc; +} + +int bnxt_get_vf_config(struct net_device *dev, int vf_id, + struct ifla_vf_info *ivi) +{ + struct bnxt *bp = netdev_priv(dev); + struct bnxt_vf_info *vf; + int rc; + + rc = bnxt_vf_ndo_prep(bp, vf_id); + if (rc) + return rc; + + ivi->vf = vf_id; + vf = &bp->pf.vf[vf_id]; + + memcpy(&ivi->mac, vf->mac_addr, ETH_ALEN); + ivi->max_tx_rate = vf->max_tx_rate; + ivi->min_tx_rate = vf->min_tx_rate; + ivi->vlan = vf->vlan; + ivi->qos = vf->flags & BNXT_VF_QOS; + ivi->spoofchk = vf->flags & BNXT_VF_SPOOFCHK; + if (!(vf->flags & BNXT_VF_LINK_FORCED)) + ivi->linkstate = IFLA_VF_LINK_STATE_AUTO; + else if (vf->flags & BNXT_VF_LINK_UP) + ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE; + else + ivi->linkstate = IFLA_VF_LINK_STATE_DISABLE; + + return 0; +} + +int bnxt_set_vf_mac(struct net_device *dev, int vf_id, u8 *mac) +{ + struct hwrm_func_cfg_input req = {0}; + struct bnxt *bp = netdev_priv(dev); + struct bnxt_vf_info *vf; + int rc; + + rc = bnxt_vf_ndo_prep(bp, vf_id); + if (rc) + return rc; + /* reject bc or mc mac addr, zero mac addr means allow + * VF to use its own mac addr + */ + if (is_multicast_ether_addr(mac)) { + netdev_err(dev, "Invalid VF ethernet address\n"); + return -EINVAL; + } + vf = &bp->pf.vf[vf_id]; + + memcpy(vf->mac_addr, mac, ETH_ALEN); + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); + req.vf_id = cpu_to_le16(vf->fw_fid); + req.flags = cpu_to_le32(vf->func_flags); + req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR); + memcpy(req.dflt_mac_addr, mac, ETH_ALEN); + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + +int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos) +{ + struct hwrm_func_cfg_input req = {0}; + struct bnxt *bp = netdev_priv(dev); + struct bnxt_vf_info *vf; + u16 vlan_tag; + int rc; + + rc = bnxt_vf_ndo_prep(bp, vf_id); + if (rc) + return rc; + + /* TODO: needed to implement proper handling of user priority, + * currently fail the command if there is valid priority + */ + if (vlan_id > 4095 || qos) + return -EINVAL; + + vf = &bp->pf.vf[vf_id]; + vlan_tag = vlan_id; + if (vlan_tag == vf->vlan) + return 0; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); + req.vf_id = cpu_to_le16(vf->fw_fid); + req.flags = cpu_to_le32(vf->func_flags); + req.dflt_vlan = cpu_to_le16(vlan_tag); + req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_VLAN); + rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (!rc) + vf->vlan = vlan_tag; + return rc; +} + +int bnxt_set_vf_bw(struct net_device *dev, int vf_id, int min_tx_rate, + int max_tx_rate) +{ + struct hwrm_func_cfg_input req = {0}; + struct bnxt *bp = netdev_priv(dev); + struct bnxt_vf_info *vf; + u32 pf_link_speed; + int rc; + + rc = bnxt_vf_ndo_prep(bp, vf_id); + if (rc) + return rc; + + vf = &bp->pf.vf[vf_id]; + pf_link_speed = bnxt_fw_to_ethtool_speed(bp->link_info.link_speed); + if (max_tx_rate > pf_link_speed) { + netdev_info(bp->dev, "max tx rate %d exceed PF link speed for VF %d\n", + max_tx_rate, vf_id); + return -EINVAL; + } + + if (min_tx_rate > pf_link_speed || min_tx_rate > max_tx_rate) { + netdev_info(bp->dev, "min tx rate %d is invalid for VF %d\n", + min_tx_rate, vf_id); + return -EINVAL; + } + if (min_tx_rate == vf->min_tx_rate && max_tx_rate == vf->max_tx_rate) + return 0; + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); + req.vf_id = cpu_to_le16(vf->fw_fid); + req.flags = cpu_to_le32(vf->func_flags); + req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_MAX_BW); + req.max_bw = cpu_to_le32(max_tx_rate); + req.enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_MIN_BW); + req.min_bw = cpu_to_le32(min_tx_rate); + rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (!rc) { + vf->min_tx_rate = min_tx_rate; + vf->max_tx_rate = max_tx_rate; + } + return rc; +} + +int bnxt_set_vf_link_state(struct net_device *dev, int vf_id, int link) +{ + struct bnxt *bp = netdev_priv(dev); + struct bnxt_vf_info *vf; + int rc; + + rc = bnxt_vf_ndo_prep(bp, vf_id); + if (rc) + return rc; + + vf = &bp->pf.vf[vf_id]; + + vf->flags &= ~(BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED); + switch (link) { + case IFLA_VF_LINK_STATE_AUTO: + vf->flags |= BNXT_VF_LINK_UP; + break; + case IFLA_VF_LINK_STATE_DISABLE: + vf->flags |= BNXT_VF_LINK_FORCED; + break; + case IFLA_VF_LINK_STATE_ENABLE: + vf->flags |= BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED; + break; + default: + netdev_err(bp->dev, "Invalid link option\n"); + rc = -EINVAL; + break; + } + /* CHIMP TODO: send msg to VF to update new link state */ + + return rc; +} + +static int bnxt_set_vf_attr(struct bnxt *bp, int num_vfs) +{ + int i; + struct bnxt_vf_info *vf; + + for (i = 0; i < num_vfs; i++) { + vf = &bp->pf.vf[i]; + memset(vf, 0, sizeof(*vf)); + vf->flags = BNXT_VF_QOS | BNXT_VF_LINK_UP; + } + return 0; +} + +static int bnxt_hwrm_func_vf_resource_free(struct bnxt *bp) +{ + int i, rc = 0; + struct bnxt_pf_info *pf = &bp->pf; + struct hwrm_func_vf_resc_free_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_VF_RESC_FREE, -1, -1); + + mutex_lock(&bp->hwrm_cmd_lock); + for (i = pf->first_vf_id; i < pf->first_vf_id + pf->active_vfs; i++) { + req.vf_id = cpu_to_le16(i); + rc = _hwrm_send_message(bp, &req, sizeof(req), + HWRM_CMD_TIMEOUT); + if (rc) + break; + } + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static void bnxt_free_vf_resources(struct bnxt *bp) +{ + struct pci_dev *pdev = bp->pdev; + int i; + + kfree(bp->pf.vf_event_bmap); + bp->pf.vf_event_bmap = NULL; + + for (i = 0; i < 4; i++) { + if (bp->pf.hwrm_cmd_req_addr[i]) { + dma_free_coherent(&pdev->dev, BNXT_PAGE_SIZE, + bp->pf.hwrm_cmd_req_addr[i], + bp->pf.hwrm_cmd_req_dma_addr[i]); + bp->pf.hwrm_cmd_req_addr[i] = NULL; + } + } + + kfree(bp->pf.vf); + bp->pf.vf = NULL; +} + +static int bnxt_alloc_vf_resources(struct bnxt *bp, int num_vfs) +{ + struct pci_dev *pdev = bp->pdev; + u32 nr_pages, size, i, j, k = 0; + + bp->pf.vf = kcalloc(num_vfs, sizeof(struct bnxt_vf_info), GFP_KERNEL); + if (!bp->pf.vf) + return -ENOMEM; + + bnxt_set_vf_attr(bp, num_vfs); + + size = num_vfs * BNXT_HWRM_REQ_MAX_SIZE; + nr_pages = size / BNXT_PAGE_SIZE; + if (size & (BNXT_PAGE_SIZE - 1)) + nr_pages++; + + for (i = 0; i < nr_pages; i++) { + bp->pf.hwrm_cmd_req_addr[i] = + dma_alloc_coherent(&pdev->dev, BNXT_PAGE_SIZE, + &bp->pf.hwrm_cmd_req_dma_addr[i], + GFP_KERNEL); + + if (!bp->pf.hwrm_cmd_req_addr[i]) + return -ENOMEM; + + for (j = 0; j < BNXT_HWRM_REQS_PER_PAGE && k < num_vfs; j++) { + struct bnxt_vf_info *vf = &bp->pf.vf[k]; + + vf->hwrm_cmd_req_addr = bp->pf.hwrm_cmd_req_addr[i] + + j * BNXT_HWRM_REQ_MAX_SIZE; + vf->hwrm_cmd_req_dma_addr = + bp->pf.hwrm_cmd_req_dma_addr[i] + j * + BNXT_HWRM_REQ_MAX_SIZE; + k++; + } + } + + /* Max 128 VF's */ + bp->pf.vf_event_bmap = kzalloc(16, GFP_KERNEL); + if (!bp->pf.vf_event_bmap) + return -ENOMEM; + + bp->pf.hwrm_cmd_req_pages = nr_pages; + return 0; +} + +static int bnxt_hwrm_func_buf_rgtr(struct bnxt *bp) +{ + struct hwrm_func_buf_rgtr_input req = {0}; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_BUF_RGTR, -1, -1); + + req.req_buf_num_pages = cpu_to_le16(bp->pf.hwrm_cmd_req_pages); + req.req_buf_page_size = cpu_to_le16(BNXT_PAGE_SHIFT); + req.req_buf_len = cpu_to_le16(BNXT_HWRM_REQ_MAX_SIZE); + req.req_buf_page_addr0 = cpu_to_le64(bp->pf.hwrm_cmd_req_dma_addr[0]); + req.req_buf_page_addr1 = cpu_to_le64(bp->pf.hwrm_cmd_req_dma_addr[1]); + req.req_buf_page_addr2 = cpu_to_le64(bp->pf.hwrm_cmd_req_dma_addr[2]); + req.req_buf_page_addr3 = cpu_to_le64(bp->pf.hwrm_cmd_req_dma_addr[3]); + + return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +} + +/* only call by PF to reserve resources for VF */ +static int bnxt_hwrm_func_cfg(struct bnxt *bp, int *num_vfs) +{ + u32 rc = 0, mtu, i; + u16 vf_tx_rings, vf_rx_rings, vf_cp_rings, vf_stat_ctx, vf_vnics; + struct hwrm_func_cfg_input req = {0}; + struct bnxt_pf_info *pf = &bp->pf; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1); + + /* Remaining rings are distributed equally amongs VF's for now */ + /* TODO: the following workaroud is needed to restrict total number + * of vf_cp_rings not exceed number of HW ring groups. This WA should + * be removed once new HWRM provides HW ring groups capability in + * hwrm_func_qcap. + */ + vf_cp_rings = min_t(u16, bp->pf.max_cp_rings, bp->pf.max_stat_ctxs); + vf_cp_rings = (vf_cp_rings - bp->cp_nr_rings) / *num_vfs; + /* TODO: restore this logic below once the WA above is removed */ + /* vf_cp_rings = (bp->pf.max_cp_rings - bp->cp_nr_rings) / *num_vfs; */ + vf_stat_ctx = (bp->pf.max_stat_ctxs - bp->num_stat_ctxs) / *num_vfs; + if (bp->flags & BNXT_FLAG_AGG_RINGS) + vf_rx_rings = (bp->pf.max_rx_rings - bp->rx_nr_rings * 2) / + *num_vfs; + else + vf_rx_rings = (bp->pf.max_rx_rings - bp->rx_nr_rings) / + *num_vfs; + vf_tx_rings = (bp->pf.max_tx_rings - bp->tx_nr_rings) / *num_vfs; + + req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_MTU | + FUNC_CFG_REQ_ENABLES_MRU | + FUNC_CFG_REQ_ENABLES_NUM_RSSCOS_CTXS | + FUNC_CFG_REQ_ENABLES_NUM_STAT_CTXS | + FUNC_CFG_REQ_ENABLES_NUM_CMPL_RINGS | + FUNC_CFG_REQ_ENABLES_NUM_TX_RINGS | + FUNC_CFG_REQ_ENABLES_NUM_RX_RINGS | + FUNC_CFG_REQ_ENABLES_NUM_L2_CTXS | + FUNC_CFG_REQ_ENABLES_NUM_VNICS); + + mtu = bp->dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; + req.mru = cpu_to_le16(mtu); + req.mtu = cpu_to_le16(mtu); + + req.num_rsscos_ctxs = cpu_to_le16(1); + req.num_cmpl_rings = cpu_to_le16(vf_cp_rings); + req.num_tx_rings = cpu_to_le16(vf_tx_rings); + req.num_rx_rings = cpu_to_le16(vf_rx_rings); + req.num_l2_ctxs = cpu_to_le16(4); + vf_vnics = 1; + + req.num_vnics = cpu_to_le16(vf_vnics); + /* FIXME spec currently uses 1 bit for stats ctx */ + req.num_stat_ctxs = cpu_to_le16(vf_stat_ctx); + + mutex_lock(&bp->hwrm_cmd_lock); + for (i = 0; i < *num_vfs; i++) { + req.vf_id = cpu_to_le16(pf->first_vf_id + i); + rc = _hwrm_send_message(bp, &req, sizeof(req), + HWRM_CMD_TIMEOUT); + if (rc) + break; + bp->pf.active_vfs = i + 1; + bp->pf.vf[i].fw_fid = le16_to_cpu(req.vf_id); + } + mutex_unlock(&bp->hwrm_cmd_lock); + if (!rc) { + bp->pf.max_pf_tx_rings = bp->tx_nr_rings; + if (bp->flags & BNXT_FLAG_AGG_RINGS) + bp->pf.max_pf_rx_rings = bp->rx_nr_rings * 2; + else + bp->pf.max_pf_rx_rings = bp->rx_nr_rings; + } + return rc; +} + +static int bnxt_sriov_enable(struct bnxt *bp, int *num_vfs) +{ + int rc = 0, vfs_supported; + int min_rx_rings, min_tx_rings, min_rss_ctxs; + int tx_ok = 0, rx_ok = 0, rss_ok = 0; + + /* Check if we can enable requested num of vf's. At a mininum + * we require 1 RX 1 TX rings for each VF. In this minimum conf + * features like TPA will not be available. + */ + vfs_supported = *num_vfs; + + while (vfs_supported) { + min_rx_rings = vfs_supported; + min_tx_rings = vfs_supported; + min_rss_ctxs = vfs_supported; + + if (bp->flags & BNXT_FLAG_AGG_RINGS) { + if (bp->pf.max_rx_rings - bp->rx_nr_rings * 2 >= + min_rx_rings) + rx_ok = 1; + } else { + if (bp->pf.max_rx_rings - bp->rx_nr_rings >= + min_rx_rings) + rx_ok = 1; + } + + if (bp->pf.max_tx_rings - bp->tx_nr_rings >= min_tx_rings) + tx_ok = 1; + + if (bp->pf.max_rsscos_ctxs - bp->rsscos_nr_ctxs >= min_rss_ctxs) + rss_ok = 1; + + if (tx_ok && rx_ok && rss_ok) + break; + + vfs_supported--; + } + + if (!vfs_supported) { + netdev_err(bp->dev, "Cannot enable VF's as all resources are used by PF\n"); + return -EINVAL; + } + + if (vfs_supported != *num_vfs) { + netdev_info(bp->dev, "Requested VFs %d, can enable %d\n", + *num_vfs, vfs_supported); + *num_vfs = vfs_supported; + } + + rc = bnxt_alloc_vf_resources(bp, *num_vfs); + if (rc) + goto err_out1; + + /* Reserve resources for VFs */ + rc = bnxt_hwrm_func_cfg(bp, num_vfs); + if (rc) + goto err_out2; + + /* Register buffers for VFs */ + rc = bnxt_hwrm_func_buf_rgtr(bp); + if (rc) + goto err_out2; + + rc = pci_enable_sriov(bp->pdev, *num_vfs); + if (rc) + goto err_out2; + + return 0; + +err_out2: + /* Free the resources reserved for various VF's */ + bnxt_hwrm_func_vf_resource_free(bp); + +err_out1: + bnxt_free_vf_resources(bp); + + return rc; +} + +void bnxt_sriov_disable(struct bnxt *bp) +{ + if (!bp->pf.active_vfs) + return; + + pci_disable_sriov(bp->pdev); + + /* Free the resources reserved for various VF's */ + bnxt_hwrm_func_vf_resource_free(bp); + + bnxt_free_vf_resources(bp); + + bp->pf.active_vfs = 0; + bp->pf.max_pf_rx_rings = bp->pf.max_rx_rings; + bp->pf.max_pf_tx_rings = bp->pf.max_tx_rings; +} + +int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct bnxt *bp = netdev_priv(dev); + + if (!(bp->flags & BNXT_FLAG_USING_MSIX)) { + netdev_warn(dev, "Not allow SRIOV if the irq mode is not MSIX\n"); + return 0; + } + + rtnl_lock(); + if (!netif_running(dev)) { + netdev_warn(dev, "Reject SRIOV config request since if is down!\n"); + rtnl_unlock(); + return 0; + } + bp->sriov_cfg = true; + rtnl_unlock(); + if (!num_vfs) { + bnxt_sriov_disable(bp); + return 0; + } + + /* Check if enabled VFs is same as requested */ + if (num_vfs == bp->pf.active_vfs) + return 0; + + bnxt_sriov_enable(bp, &num_vfs); + + bp->sriov_cfg = false; + wake_up(&bp->sriov_cfg_wait); + + return num_vfs; +} + +static int bnxt_hwrm_fwd_resp(struct bnxt *bp, struct bnxt_vf_info *vf, + void *encap_resp, __le64 encap_resp_addr, + __le16 encap_resp_cpr, u32 msg_size) +{ + int rc = 0; + struct hwrm_fwd_resp_input req = {0}; + struct hwrm_fwd_resp_output *resp = bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FWD_RESP, -1, -1); + + /* Set the new target id */ + req.target_id = cpu_to_le16(vf->fw_fid); + req.encap_resp_len = cpu_to_le16(msg_size); + req.encap_resp_addr = encap_resp_addr; + req.encap_resp_cmpl_ring = encap_resp_cpr; + memcpy(req.encap_resp, encap_resp, msg_size); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + + if (rc) { + netdev_err(bp->dev, "hwrm_fwd_resp failed. rc:%d\n", rc); + goto fwd_resp_exit; + } + + if (resp->error_code) { + netdev_err(bp->dev, "hwrm_fwd_resp error %d\n", + resp->error_code); + rc = -1; + } + +fwd_resp_exit: + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_hwrm_fwd_err_resp(struct bnxt *bp, struct bnxt_vf_info *vf, + u32 msg_size) +{ + int rc = 0; + struct hwrm_reject_fwd_resp_input req = {0}; + struct hwrm_reject_fwd_resp_output *resp = bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_REJECT_FWD_RESP, -1, -1); + /* Set the new target id */ + req.target_id = cpu_to_le16(vf->fw_fid); + memcpy(req.encap_request, vf->hwrm_cmd_req_addr, msg_size); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + + if (rc) { + netdev_err(bp->dev, "hwrm_fwd_err_resp failed. rc:%d\n", rc); + goto fwd_err_resp_exit; + } + + if (resp->error_code) { + netdev_err(bp->dev, "hwrm_fwd_err_resp error %d\n", + resp->error_code); + rc = -1; + } + +fwd_err_resp_exit: + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_hwrm_exec_fwd_resp(struct bnxt *bp, struct bnxt_vf_info *vf, + u32 msg_size) +{ + int rc = 0; + struct hwrm_exec_fwd_resp_input req = {0}; + struct hwrm_exec_fwd_resp_output *resp = bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_EXEC_FWD_RESP, -1, -1); + /* Set the new target id */ + req.target_id = cpu_to_le16(vf->fw_fid); + memcpy(req.encap_request, vf->hwrm_cmd_req_addr, msg_size); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + + if (rc) { + netdev_err(bp->dev, "hwrm_exec_fw_resp failed. rc:%d\n", rc); + goto exec_fwd_resp_exit; + } + + if (resp->error_code) { + netdev_err(bp->dev, "hwrm_exec_fw_resp error %d\n", + resp->error_code); + rc = -1; + } + +exec_fwd_resp_exit: + mutex_unlock(&bp->hwrm_cmd_lock); + return rc; +} + +static int bnxt_vf_validate_set_mac(struct bnxt *bp, struct bnxt_vf_info *vf) +{ + u32 msg_size = sizeof(struct hwrm_cfa_l2_filter_alloc_input); + struct hwrm_cfa_l2_filter_alloc_input *req = + (struct hwrm_cfa_l2_filter_alloc_input *)vf->hwrm_cmd_req_addr; + + if (!is_valid_ether_addr(vf->mac_addr) || + ether_addr_equal((const u8 *)req->l2_addr, vf->mac_addr)) + return bnxt_hwrm_exec_fwd_resp(bp, vf, msg_size); + else + return bnxt_hwrm_fwd_err_resp(bp, vf, msg_size); +} + +static int bnxt_vf_set_link(struct bnxt *bp, struct bnxt_vf_info *vf) +{ + int rc = 0; + + if (!(vf->flags & BNXT_VF_LINK_FORCED)) { + /* real link */ + rc = bnxt_hwrm_exec_fwd_resp( + bp, vf, sizeof(struct hwrm_port_phy_qcfg_input)); + } else { + struct hwrm_port_phy_qcfg_output phy_qcfg_resp; + struct hwrm_port_phy_qcfg_input *phy_qcfg_req; + + phy_qcfg_req = + (struct hwrm_port_phy_qcfg_input *)vf->hwrm_cmd_req_addr; + mutex_lock(&bp->hwrm_cmd_lock); + memcpy(&phy_qcfg_resp, &bp->link_info.phy_qcfg_resp, + sizeof(phy_qcfg_resp)); + mutex_unlock(&bp->hwrm_cmd_lock); + phy_qcfg_resp.seq_id = phy_qcfg_req->seq_id; + + if (vf->flags & BNXT_VF_LINK_UP) { + /* if physical link is down, force link up on VF */ + if (phy_qcfg_resp.link == + PORT_PHY_QCFG_RESP_LINK_NO_LINK) { + phy_qcfg_resp.link = + PORT_PHY_QCFG_RESP_LINK_LINK; + if (phy_qcfg_resp.auto_link_speed) + phy_qcfg_resp.link_speed = + phy_qcfg_resp.auto_link_speed; + else + phy_qcfg_resp.link_speed = + phy_qcfg_resp.force_link_speed; + phy_qcfg_resp.duplex = + PORT_PHY_QCFG_RESP_DUPLEX_FULL; + phy_qcfg_resp.pause = + (PORT_PHY_QCFG_RESP_PAUSE_TX | + PORT_PHY_QCFG_RESP_PAUSE_RX); + } + } else { + /* force link down */ + phy_qcfg_resp.link = PORT_PHY_QCFG_RESP_LINK_NO_LINK; + phy_qcfg_resp.link_speed = 0; + phy_qcfg_resp.duplex = PORT_PHY_QCFG_RESP_DUPLEX_HALF; + phy_qcfg_resp.pause = 0; + } + rc = bnxt_hwrm_fwd_resp(bp, vf, &phy_qcfg_resp, + phy_qcfg_req->resp_addr, + phy_qcfg_req->cmpl_ring, + sizeof(phy_qcfg_resp)); + } + return rc; +} + +static int bnxt_vf_req_validate_snd(struct bnxt *bp, struct bnxt_vf_info *vf) +{ + int rc = 0; + struct hwrm_cmd_req_hdr *encap_req = vf->hwrm_cmd_req_addr; + u32 req_type = le32_to_cpu(encap_req->cmpl_ring_req_type) & 0xffff; + + switch (req_type) { + case HWRM_CFA_L2_FILTER_ALLOC: + rc = bnxt_vf_validate_set_mac(bp, vf); + break; + case HWRM_FUNC_CFG: + /* TODO Validate if VF is allowed to change mac address, + * mtu, num of rings etc + */ + rc = bnxt_hwrm_exec_fwd_resp( + bp, vf, sizeof(struct hwrm_func_cfg_input)); + break; + case HWRM_PORT_PHY_QCFG: + rc = bnxt_vf_set_link(bp, vf); + break; + default: + break; + } + return rc; +} + +void bnxt_hwrm_exec_fwd_req(struct bnxt *bp) +{ + u32 i = 0, active_vfs = bp->pf.active_vfs, vf_id; + + /* Scan through VF's and process commands */ + while (1) { + vf_id = find_next_bit(bp->pf.vf_event_bmap, active_vfs, i); + if (vf_id >= active_vfs) + break; + + clear_bit(vf_id, bp->pf.vf_event_bmap); + bnxt_vf_req_validate_snd(bp, &bp->pf.vf[vf_id]); + i = vf_id + 1; + } +} +#else + +void bnxt_sriov_disable(struct bnxt *bp) +{ +} + +void bnxt_hwrm_exec_fwd_req(struct bnxt *bp) +{ + netdev_err(dev, "Invalid VF message received when SRIOV is not enable\n"); +} +#endif diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h new file mode 100644 index 000000000000..0b430f157b9e --- /dev/null +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h @@ -0,0 +1,22 @@ +/* Broadcom NetXtreme-C/E network driver. + * + * Copyright (c) 2014-2015 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + */ + +#ifndef BNXT_SRIOV_H +#define BNXT_SRIOV_H + +int bnxt_get_vf_config(struct net_device *, int, struct ifla_vf_info *); +int bnxt_set_vf_mac(struct net_device *, int, u8 *); +int bnxt_set_vf_vlan(struct net_device *, int, u16, u8); +int bnxt_set_vf_bw(struct net_device *, int, int, int); +int bnxt_set_vf_link_state(struct net_device *, int, int); +int bnxt_set_vf_spoofchk(struct net_device *, int, bool); +int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs); +void bnxt_sriov_disable(struct bnxt *); +void bnxt_hwrm_exec_fwd_req(struct bnxt *); +#endif -- cgit v1.2.3 From fc4099f17240767554ff3a73977acb78ef615404 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Thu, 22 Oct 2015 18:17:16 -0700 Subject: openvswitch: Fix egress tunnel info. While transitioning to netdev based vport we broke OVS feature which allows user to retrieve tunnel packet egress information for lwtunnel devices. Following patch fixes it by introducing ndo operation to get the tunnel egress info. Same ndo operation can be used for lwtunnel devices and compat ovs-tnl-vport devices. So after adding such device operation we can remove similar operation from ovs-vport. Fixes: 614732eaa12d ("openvswitch: Use regular VXLAN net_device device"). Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller --- drivers/net/geneve.c | 40 +++++++++++++++++++++++++++++++++------- drivers/net/vxlan.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index cde29f8a37bf..445071c163cb 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -594,14 +594,12 @@ static struct rtable *geneve_get_rt(struct sk_buff *skb, rt = ip_route_output_key(geneve->net, fl4); if (IS_ERR(rt)) { netdev_dbg(dev, "no route to %pI4\n", &fl4->daddr); - dev->stats.tx_carrier_errors++; - return rt; + return ERR_PTR(-ENETUNREACH); } if (rt->dst.dev == dev) { /* is this necessary? */ netdev_dbg(dev, "circular route to %pI4\n", &fl4->daddr); - dev->stats.collisions++; ip_rt_put(rt); - return ERR_PTR(-EINVAL); + return ERR_PTR(-ELOOP); } return rt; } @@ -627,12 +625,12 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) struct ip_tunnel_info *info = NULL; struct rtable *rt = NULL; const struct iphdr *iip; /* interior IP header */ + int err = -EINVAL; struct flowi4 fl4; __u8 tos, ttl; __be16 sport; bool udp_csum; __be16 df; - int err; if (geneve->collect_md) { info = skb_tunnel_info(skb); @@ -647,7 +645,7 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) rt = geneve_get_rt(skb, dev, &fl4, info); if (IS_ERR(rt)) { netdev_dbg(dev, "no route to %pI4\n", &fl4.daddr); - dev->stats.tx_carrier_errors++; + err = PTR_ERR(rt); goto tx_error; } @@ -699,10 +697,37 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) tx_error: dev_kfree_skb(skb); err: - dev->stats.tx_errors++; + if (err == -ELOOP) + dev->stats.collisions++; + else if (err == -ENETUNREACH) + dev->stats.tx_carrier_errors++; + else + dev->stats.tx_errors++; return NETDEV_TX_OK; } +static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) +{ + struct ip_tunnel_info *info = skb_tunnel_info(skb); + struct geneve_dev *geneve = netdev_priv(dev); + struct rtable *rt; + struct flowi4 fl4; + + if (ip_tunnel_info_af(info) != AF_INET) + return -EINVAL; + + rt = geneve_get_rt(skb, dev, &fl4, info); + if (IS_ERR(rt)) + return PTR_ERR(rt); + + ip_rt_put(rt); + info->key.u.ipv4.src = fl4.saddr; + info->key.tp_src = udp_flow_src_port(geneve->net, skb, + 1, USHRT_MAX, true); + info->key.tp_dst = geneve->dst_port; + return 0; +} + static const struct net_device_ops geneve_netdev_ops = { .ndo_init = geneve_init, .ndo_uninit = geneve_uninit, @@ -713,6 +738,7 @@ static const struct net_device_ops geneve_netdev_ops = { .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, + .ndo_fill_metadata_dst = geneve_fill_metadata_dst, }; static void geneve_get_drvinfo(struct net_device *dev, diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index afdc65fd5bc5..c1587ece28cf 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2337,6 +2337,46 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu) return 0; } +static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb, + struct ip_tunnel_info *info, + __be16 sport, __be16 dport) +{ + struct vxlan_dev *vxlan = netdev_priv(dev); + struct rtable *rt; + struct flowi4 fl4; + + memset(&fl4, 0, sizeof(fl4)); + fl4.flowi4_tos = RT_TOS(info->key.tos); + fl4.flowi4_mark = skb->mark; + fl4.flowi4_proto = IPPROTO_UDP; + fl4.daddr = info->key.u.ipv4.dst; + + rt = ip_route_output_key(vxlan->net, &fl4); + if (IS_ERR(rt)) + return PTR_ERR(rt); + ip_rt_put(rt); + + info->key.u.ipv4.src = fl4.saddr; + info->key.tp_src = sport; + info->key.tp_dst = dport; + return 0; +} + +static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) +{ + struct vxlan_dev *vxlan = netdev_priv(dev); + struct ip_tunnel_info *info = skb_tunnel_info(skb); + __be16 sport, dport; + + sport = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min, + vxlan->cfg.port_max, true); + dport = info->key.tp_dst ? : vxlan->cfg.dst_port; + + if (ip_tunnel_info_af(info) == AF_INET) + return egress_ipv4_tun_info(dev, skb, info, sport, dport); + return -EINVAL; +} + static const struct net_device_ops vxlan_netdev_ops = { .ndo_init = vxlan_init, .ndo_uninit = vxlan_uninit, @@ -2351,6 +2391,7 @@ static const struct net_device_ops vxlan_netdev_ops = { .ndo_fdb_add = vxlan_fdb_add, .ndo_fdb_del = vxlan_fdb_delete, .ndo_fdb_dump = vxlan_fdb_dump, + .ndo_fill_metadata_dst = vxlan_fill_metadata_dst, }; /* Info for udev, that this is a virtual tunnel endpoint */ -- cgit v1.2.3 From f23d538bc24a83c16127c2eb82c9cf1adc2b5149 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Fri, 23 Oct 2015 00:57:05 -0400 Subject: macvtap: unbreak receiving of gro skb with frag list We don't have fraglist support in TAP_FEATURES. This will lead software segmentation of gro skb with frag list. Fixes by having frag list support in TAP_FEATURES. With this patch single session of netperf receiving were restored from about 5Gb/s to about 12Gb/s on mlx4. Fixes a567dd6252 ("macvtap: simplify usage of tap_features") Cc: Vlad Yasevich Cc: Michael S. Tsirkin Signed-off-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 248478c6f6e4..197c93937c2d 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -137,7 +137,7 @@ static const struct proto_ops macvtap_socket_ops; #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ NETIF_F_TSO6 | NETIF_F_UFO) #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO) -#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG) +#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG | NETIF_F_FRAGLIST) static struct macvlan_dev *macvtap_get_vlan_rcu(const struct net_device *dev) { -- cgit v1.2.3 From d2fd719bcb0e83cb39cfee22ee800f98a56eceb3 Mon Sep 17 00:00:00 2001 From: Nathan Sullivan Date: Wed, 21 Oct 2015 14:17:04 -0500 Subject: net/phy: micrel: Add workaround for bad autoneg Very rarely, the KSZ9031 will appear to complete autonegotiation, but will drop all traffic afterwards. When this happens, the idle error count will read 0xFF after autonegotiation completes. Reset the PHY when in that state. Signed-off-by: Nathan Sullivan Signed-off-by: David S. Miller --- drivers/net/phy/micrel.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 499185eaf413..cf6312fafea5 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -514,6 +514,27 @@ static int ksz8873mll_read_status(struct phy_device *phydev) return 0; } +static int ksz9031_read_status(struct phy_device *phydev) +{ + int err; + int regval; + + err = genphy_read_status(phydev); + if (err) + return err; + + /* Make sure the PHY is not broken. Read idle error count, + * and reset the PHY if it is maxed out. + */ + regval = phy_read(phydev, MII_STAT1000); + if ((regval & 0xFF) == 0xFF) { + phy_init_hw(phydev); + phydev->link = 0; + } + + return 0; +} + static int ksz8873mll_config_aneg(struct phy_device *phydev) { return 0; @@ -772,7 +793,7 @@ static struct phy_driver ksphy_driver[] = { .driver_data = &ksz9021_type, .config_init = ksz9031_config_init, .config_aneg = genphy_config_aneg, - .read_status = genphy_read_status, + .read_status = ksz9031_read_status, .ack_interrupt = kszphy_ack_interrupt, .config_intr = kszphy_config_intr, .suspend = genphy_suspend, -- cgit v1.2.3 From 20a41fba679d665cdae2808e2b9cae97c073351f Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Wed, 21 Oct 2015 15:37:05 -0500 Subject: amd-xgbe: Use wmb before updating current descriptor count The code currently uses the lightweight dma_wmb barrier before updating the current descriptor count. Under heavy load, the Tx cleanup routine was seeing the updated current descriptor count before the updated descriptor information. As a result, the Tx descriptor was being cleaned up before it was used because it was not "owned" by the hardware yet, resulting in a Tx queue hang. Using the wmb barrier insures that the descriptor is updated before the descriptor counter preventing the Tx queue hang. For extra insurance, the Tx cleanup routine is changed to grab the current decriptor count on entry and uses that initial value in the processing loop rather than trying to chase the current value. Signed-off-by: Tom Lendacky Tested-by: Christoffer Dall Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 2 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index a4473d8ff4fa..e9ab8b9f3b9c 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -1595,7 +1595,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) packet->rdesc_count, 1); /* Make sure ownership is written to the descriptor */ - dma_wmb(); + wmb(); ring->cur = cur_index + 1; if (!packet->skb->xmit_more || diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index aae9d5ecd182..d2b77d985441 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -1807,6 +1807,7 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) struct netdev_queue *txq; int processed = 0; unsigned int tx_packets = 0, tx_bytes = 0; + unsigned int cur; DBGPR("-->xgbe_tx_poll\n"); @@ -1814,10 +1815,11 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) if (!ring) return 0; + cur = ring->cur; txq = netdev_get_tx_queue(netdev, channel->queue_index); while ((processed < XGBE_TX_DESC_MAX_PROC) && - (ring->dirty != ring->cur)) { + (ring->dirty != cur)) { rdata = XGBE_GET_DESC_DATA(ring, ring->dirty); rdesc = rdata->rdesc; -- cgit v1.2.3 From 1acea4f6ce1b1c0941438aca75dd2e5c6b09db60 Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Thu, 22 Oct 2015 16:57:10 +0200 Subject: ppp: fix pppoe_dev deletion condition in pppoe_release() We can't rely on PPPOX_ZOMBIE to decide whether to clear po->pppoe_dev. PPPOX_ZOMBIE can be set by pppoe_disc_rcv() even when po->pppoe_dev is NULL. So we have no guarantee that (sk->sk_state & PPPOX_ZOMBIE) implies (po->pppoe_dev != NULL). Since we're releasing a PPPoE socket, we want to release the pppoe_dev if it exists and reset sk_state to PPPOX_DEAD, no matter the previous value of sk_state. So we can just check for po->pppoe_dev and avoid any assumption on sk->sk_state. Fixes: 2b018d57ff18 ("pppoe: drop PPPOX_ZOMBIEs in pppoe_release") Signed-off-by: Guillaume Nault Signed-off-by: David S. Miller --- drivers/net/ppp/pppoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index 2ed75060da50..5e0b43283bce 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -589,7 +589,7 @@ static int pppoe_release(struct socket *sock) po = pppox_sk(sk); - if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { + if (po->pppoe_dev) { dev_put(po->pppoe_dev); po->pppoe_dev = NULL; } -- cgit v1.2.3 From e7358f54a3954df16d4f87e3cad35063f1c17de5 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Thu, 1 Oct 2015 14:37:34 -0400 Subject: i40e/i40evf: Add a workaround to drop all flow control frames This patch adds a workaround to drop any flow control frames from being transmitted from any VSI. FW can still send flow control frames if flow control is enabled. With this patch in place a malicious VF cannot send flow control or PFC packets out on the wire. Change-ID: I4303b24e98b93066d2767fec24dfe78be591c277 Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 22 ++++++++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_main.c | 18 ++++++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_prototype.h | 2 ++ drivers/net/ethernet/intel/i40evf/i40e_prototype.h | 2 ++ 4 files changed, 44 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index c51f2fb94716..5d533d12a045 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -3828,6 +3828,28 @@ i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw, return status; } +/** + * i40e_add_filter_to_drop_tx_flow_control_frames- filter to drop flow control + * @hw: pointer to the hw struct + * @seid: VSI seid to add ethertype filter from + **/ +#define I40E_FLOW_CONTROL_ETHTYPE 0x8808 +void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw, + u16 seid) +{ + u16 flag = I40E_AQC_ADD_CONTROL_PACKET_FLAGS_IGNORE_MAC | + I40E_AQC_ADD_CONTROL_PACKET_FLAGS_DROP | + I40E_AQC_ADD_CONTROL_PACKET_FLAGS_TX; + u16 ethtype = I40E_FLOW_CONTROL_ETHTYPE; + i40e_status status; + + status = i40e_aq_add_rem_control_packet_filter(hw, NULL, ethtype, flag, + seid, 0, true, NULL, + NULL); + if (status) + hw_dbg(hw, "Ethtype Filter Add failed: Error pruning Tx flow control frames\n"); +} + /** * i40e_aq_alternate_read * @hw: pointer to the hardware structure diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index cc8c0aeab9bb..d05254c741d0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6837,6 +6837,15 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) if (pf->flags & I40E_FLAG_MSIX_ENABLED) ret = i40e_setup_misc_vector(pf); + /* Add a filter to drop all Flow control frames from any VSI from being + * transmitted. By doing so we stop a malicious VF from sending out + * PAUSE or PFC frames and potentially controlling traffic for other + * PF/VF VSIs. + * The FW can still send Flow control frames if enabled. + */ + i40e_add_filter_to_drop_tx_flow_control_frames(&pf->hw, + pf->main_vsi_seid); + /* restart the VSIs that were rebuilt and running before the reset */ i40e_pf_unquiesce_all_vsi(pf); @@ -10585,6 +10594,15 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); pf->hw.phy.phy_types = le32_to_cpu(abilities.phy_type); + /* Add a filter to drop all Flow control frames from any VSI from being + * transmitted. By doing so we stop a malicious VF from sending out + * PAUSE or PFC frames and potentially controlling traffic for other + * PF/VF VSIs. + * The FW can still send Flow control frames if enabled. + */ + i40e_add_filter_to_drop_tx_flow_control_frames(&pf->hw, + pf->main_vsi_seid); + /* print a string summarizing features */ i40e_print_features(pf); diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index 10bf2ba8bc15..bb9d583e5416 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -322,4 +322,6 @@ i40e_status i40e_aq_debug_dump(struct i40e_hw *hw, u8 cluster_id, void *buff, u16 *ret_buff_size, u8 *ret_next_table, u32 *ret_next_index, struct i40e_asq_cmd_details *cmd_details); +void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw, + u16 vsi_seid); #endif /* _I40E_PROTOTYPE_H_ */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h index 8ed0edfbc125..cbd9a1b078ab 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h @@ -101,4 +101,6 @@ i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw, u16 vsi_seid, u16 queue, bool is_add, struct i40e_control_filter_stats *stats, struct i40e_asq_cmd_details *cmd_details); +void i40e_add_filter_to_drop_tx_flow_control_frames(struct i40e_hw *hw, + u16 vsi_seid); #endif /* _I40E_PROTOTYPE_H_ */ -- cgit v1.2.3 From 10dc0358e802ea60f95432f89c8dd051767fc06f Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Thu, 1 Oct 2015 14:37:35 -0400 Subject: i40e: fix a bug in debugfs with add/del macaddr The new code flow requires us to grab the filter list lock before adding/deleting the filter. Change-ID: I4eaef508ab4da2d1b2e23f20f2a78d931d5b6aeb Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index d15bd62eb874..d4b7af9a2fc8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -1137,7 +1137,9 @@ static ssize_t i40e_dbg_command_write(struct file *filp, goto command_write_done; } + spin_lock_bh(&vsi->mac_filter_list_lock); f = i40e_add_filter(vsi, ma, vlan, false, false); + spin_unlock_bh(&vsi->mac_filter_list_lock); ret = i40e_sync_vsi_filters(vsi, true); if (f && !ret) dev_info(&pf->pdev->dev, @@ -1174,7 +1176,9 @@ static ssize_t i40e_dbg_command_write(struct file *filp, goto command_write_done; } + spin_lock_bh(&vsi->mac_filter_list_lock); i40e_del_filter(vsi, ma, vlan, false, false); + spin_unlock_bh(&vsi->mac_filter_list_lock); ret = i40e_sync_vsi_filters(vsi, true); if (!ret) dev_info(&pf->pdev->dev, -- cgit v1.2.3 From 09603eaa5ca91dd9a318d8722ff5de8feb1e36ab Mon Sep 17 00:00:00 2001 From: Akeem G Abodunrin Date: Thu, 1 Oct 2015 14:37:36 -0400 Subject: i40e: Fix VEB/VEPA bridge mode mismatch issue Fix i40e_is_vsi_uplink_mode_veb to check if bridge is actually in VEB mode before allowing LB in the add VSI routine, instead of unconditionally returning VEB bridge mode. Change-ID: I162397b1bdd02367735fe9baaeb51465be2a3ce9 Signed-off-by: Akeem G Abodunrin Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d05254c741d0..f22ded573a6e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8741,12 +8741,22 @@ int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi) return 1; veb = pf->veb[vsi->veb_idx]; + if (!veb) { + dev_info(&pf->pdev->dev, + "There is no veb associated with the bridge\n"); + return -ENOENT; + } + /* Uplink is a bridge in VEPA mode */ - if (veb && (veb->bridge_mode & BRIDGE_MODE_VEPA)) + if (veb->bridge_mode & BRIDGE_MODE_VEPA) { return 0; + } else { + /* Uplink is a bridge in VEB mode */ + return 1; + } - /* Uplink is a bridge in VEB mode */ - return 1; + /* VEPA is now default bridge, so return 0 */ + return 0; } /** -- cgit v1.2.3 From 40d01366e6dd5ef1cb3505f11b2d208cfa3632f3 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Thu, 1 Oct 2015 14:37:37 -0400 Subject: i40evf: use correct struct for list manipulation Not sure how this compiles at all. Use the correct struct for manipulating the VLAN filter list. Without this, the VLAN filter list doesn't get processed correctly, and VLAN filters will not be re-enabled after any kind of reset. Change-ID: Iceff2dc089f303058fb71ecb08419eed471e0e90 Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 10b2a4a33c68..040938385140 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1609,6 +1609,7 @@ static void i40evf_reset_task(struct work_struct *work) reset_task); struct net_device *netdev = adapter->netdev; struct i40e_hw *hw = &adapter->hw; + struct i40evf_vlan_filter *vlf; struct i40evf_mac_filter *f; u32 reg_val; int i = 0, err; @@ -1732,8 +1733,8 @@ continue_reset: f->add = true; } /* re-add all VLAN filters */ - list_for_each_entry(f, &adapter->vlan_filter_list, list) { - f->add = true; + list_for_each_entry(vlf, &adapter->vlan_filter_list, list) { + vlf->add = true; } adapter->aq_required |= I40EVF_FLAG_AQ_ADD_MAC_FILTER; adapter->aq_required |= I40EVF_FLAG_AQ_ADD_VLAN_FILTER; -- cgit v1.2.3 From 58fc3267f151f6facfc94c6982bef09a53bb5219 Mon Sep 17 00:00:00 2001 From: Helin Zhang Date: Thu, 1 Oct 2015 14:37:38 -0400 Subject: i40e: fix inconsistent statuses after a PF reset This patch fixes a problem of possibly getting inconsistent flow control statuses after a PF reset. Requested_mode was being set with a default value during probing, but the initial HW state could be different from this mode. Change-ID: I772bf07b78616e87086418d4bd87954b66fa17cd Signed-off-by: Helin Zhang Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index f22ded573a6e..2f117d92e11e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10183,6 +10183,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int err; u32 len; u32 i; + u8 set_fc_aq_fail; err = pci_enable_device_mem(pdev); if (err) @@ -10447,6 +10448,25 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(&pdev->dev, "setup_pf_switch failed: %d\n", err); goto err_vsis; } + + /* Make sure flow control is set according to current settings */ + err = i40e_set_fc(hw, &set_fc_aq_fail, true); + if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_GET) + dev_dbg(&pf->pdev->dev, + "Set fc with err %s aq_err %s on get_phy_cap\n", + i40e_stat_str(hw, err), + i40e_aq_str(hw, hw->aq.asq_last_status)); + if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_SET) + dev_dbg(&pf->pdev->dev, + "Set fc with err %s aq_err %s on set_phy_config\n", + i40e_stat_str(hw, err), + i40e_aq_str(hw, hw->aq.asq_last_status)); + if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_UPDATE) + dev_dbg(&pf->pdev->dev, + "Set fc with err %s aq_err %s on get_link_info\n", + i40e_stat_str(hw, err), + i40e_aq_str(hw, hw->aq.asq_last_status)); + /* if FDIR VSI was set up, start it now */ for (i = 0; i < pf->num_alloc_vsi; i++) { if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) { -- cgit v1.2.3 From 2efaad86b5cdd0f6d70436fa304a567df8a3cf6c Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Thu, 1 Oct 2015 14:37:39 -0400 Subject: i40e: Fix an incorrect OEM version string This patch fixes a problem where the driver output of the OEM version string varied from the other tools. The mask value and the order of operations were incorrect, per the original change request. Without this patch, the version string will appear incorrect from the driver. Change-ID: Ie1ca6485284b4ce3b57e5a99b18b7641617c7ef7 Signed-off-by: Carolyn Wyborny Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 7c2b2e891f62..4dd3e26129b4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -109,8 +109,10 @@ #define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT) #define I40E_NVM_VERSION_HI_SHIFT 12 #define I40E_NVM_VERSION_HI_MASK (0xf << I40E_NVM_VERSION_HI_SHIFT) -#define I40E_OEM_VER_BUILD_MASK 0xff00 +#define I40E_OEM_VER_BUILD_MASK 0xffff #define I40E_OEM_VER_PATCH_MASK 0xff +#define I40E_OEM_VER_BUILD_SHIFT 8 +#define I40E_OEM_VER_SHIFT 24 /* The values in here are decimal coded as hex as is the case in the NVM map*/ #define I40E_CURRENT_NVM_VERSION_HI 0x2 @@ -594,6 +596,15 @@ struct i40e_device { static inline char *i40e_nvm_version_str(struct i40e_hw *hw) { static char buf[32]; + u32 full_ver; + u8 ver, patch; + u16 build; + + full_ver = hw->nvm.oem_ver; + ver = (u8)(full_ver >> I40E_OEM_VER_SHIFT); + build = (u16)((full_ver >> I40E_OEM_VER_BUILD_SHIFT) + & I40E_OEM_VER_BUILD_MASK); + patch = (u8)(full_ver & I40E_OEM_VER_PATCH_MASK); snprintf(buf, sizeof(buf), "%x.%02x 0x%x %d.%d.%d", @@ -601,9 +612,7 @@ static inline char *i40e_nvm_version_str(struct i40e_hw *hw) I40E_NVM_VERSION_HI_SHIFT, (hw->nvm.version & I40E_NVM_VERSION_LO_MASK) >> I40E_NVM_VERSION_LO_SHIFT, - hw->nvm.eetrack, (hw->nvm.oem_ver >> 24), - (hw->nvm.oem_ver & I40E_OEM_VER_BUILD_MASK) >> 8, - hw->nvm.oem_ver & I40E_OEM_VER_PATCH_MASK); + hw->nvm.eetrack, ver, build, patch); return buf; } -- cgit v1.2.3 From de445b3dc29835ae840f202bc62fd3ae42da12ad Mon Sep 17 00:00:00 2001 From: Akeem G Abodunrin Date: Thu, 1 Oct 2015 14:37:40 -0400 Subject: i40e: Disable VEB bridge mode with SR-IOV failure If a call to enable SR-IOV in the kernel failed, we need to disable I40E_FLAG_VEB_MODE_ENABLED, so that bridge mode could fall back to VEPA, which is a default. Change-ID: I12b6f776769506db85b29bea94b9c88d0b5ee65e Signed-off-by: Akeem G Abodunrin Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index b2d95ee7ec69..44462b40f2d7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -944,6 +944,7 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs) if (pci_num_vf(pf->pdev) != num_alloc_vfs) { ret = pci_enable_sriov(pf->pdev, num_alloc_vfs); if (ret) { + pf->flags &= ~I40E_FLAG_VEB_MODE_ENABLED; pf->num_alloc_vfs = 0; goto err_iov; } -- cgit v1.2.3 From 0e320516b280a8cf7258d9d41e7140563dd7c027 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Thu, 1 Oct 2015 14:37:41 -0400 Subject: i40e/i40evf: Bump i40e to 1.3.46 and i40evf to 1.3.33 Bump up the version... Change-ID: Ib8d501021671ba20250115ed54330e2c182255b7 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 2f117d92e11e..3e595adfb0bf 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -39,7 +39,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 3 -#define DRV_VERSION_BUILD 38 +#define DRV_VERSION_BUILD 46 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 040938385140..76cd1ae2686a 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -34,7 +34,7 @@ char i40evf_driver_name[] = "i40evf"; static const char i40evf_driver_string[] = "Intel(R) XL710/X710 Virtual Function Network Driver"; -#define DRV_VERSION "1.3.25" +#define DRV_VERSION "1.3.33" const char i40evf_driver_version[] = DRV_VERSION; static const char i40evf_copyright[] = "Copyright (c) 2013 - 2015 Intel Corporation."; -- cgit v1.2.3 From a3524e95ac5339e9b65dba2228f3f7efd27648cf Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 2 Oct 2015 12:18:16 +0300 Subject: i40e: re-use %*ph specifier to hexdump a data Instead of using a custom approach change the code to use %*ph format specifier. Signed-off-by: Andy Shevchenko Tested-by: Andrew Bowers Acked-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 22 ++++------------------ drivers/net/ethernet/intel/i40evf/i40e_common.c | 22 ++++------------------ 2 files changed, 8 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 5d533d12a045..2d74c6e4d7b6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -331,25 +331,11 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc, len = buf_len; /* write the full 16-byte chunks */ for (i = 0; i < (len - 16); i += 16) - i40e_debug(hw, mask, - "\t0x%04X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - i, buf[i], buf[i + 1], buf[i + 2], - buf[i + 3], buf[i + 4], buf[i + 5], - buf[i + 6], buf[i + 7], buf[i + 8], - buf[i + 9], buf[i + 10], buf[i + 11], - buf[i + 12], buf[i + 13], buf[i + 14], - buf[i + 15]); + i40e_debug(hw, mask, "\t0x%04X %16ph\n", i, buf + i); /* write whatever's left over without overrunning the buffer */ - if (i < len) { - char d_buf[80]; - int j = 0; - - memset(d_buf, 0, sizeof(d_buf)); - j += sprintf(d_buf, "\t0x%04X ", i); - while (i < len) - j += sprintf(&d_buf[j], " %02X", buf[i++]); - i40e_debug(hw, mask, "%s\n", d_buf); - } + if (i < len) + i40e_debug(hw, mask, "\t0x%04X %*ph\n", + i, len - i, buf + i); } } diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c index a4c5a49ddbcf..72b1942a94aa 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_common.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c @@ -331,25 +331,11 @@ void i40evf_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc, len = buf_len; /* write the full 16-byte chunks */ for (i = 0; i < (len - 16); i += 16) - i40e_debug(hw, mask, - "\t0x%04X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - i, buf[i], buf[i + 1], buf[i + 2], - buf[i + 3], buf[i + 4], buf[i + 5], - buf[i + 6], buf[i + 7], buf[i + 8], - buf[i + 9], buf[i + 10], buf[i + 11], - buf[i + 12], buf[i + 13], buf[i + 14], - buf[i + 15]); + i40e_debug(hw, mask, "\t0x%04X %16ph\n", i, buf + i); /* write whatever's left over without overrunning the buffer */ - if (i < len) { - char d_buf[80]; - int j = 0; - - memset(d_buf, 0, sizeof(d_buf)); - j += sprintf(d_buf, "\t0x%04X ", i); - while (i < len) - j += sprintf(&d_buf[j], " %02X", buf[i++]); - i40e_debug(hw, mask, "%s\n", d_buf); - } + if (i < len) + i40e_debug(hw, mask, "\t0x%04X %*ph\n", + i, len - i, buf + i); } } -- cgit v1.2.3 From 69c1d70ab6b5b53ec21919f4f8de84041d3f6cdd Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Tue, 13 Oct 2015 01:06:27 -0600 Subject: i40evf: add missing kernel-doc argument @flush has been missing since the inception of i40evf_irq_enable(). Add it for the kernel doc. Signed-off-by: Jean Sacren Tested-by: Andrew Bowers Acked-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 76cd1ae2686a..f358366efe00 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -282,6 +282,7 @@ static void i40evf_fire_sw_int(struct i40evf_adapter *adapter, u32 mask) /** * i40evf_irq_enable - Enable default interrupt generation settings * @adapter: board private structure + * @flush: boolean value whether to run rd32() **/ void i40evf_irq_enable(struct i40evf_adapter *adapter, bool flush) { -- cgit v1.2.3 From 554f4544afa541b25882cd0ca5fd6b01b4e2ce07 Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Tue, 13 Oct 2015 01:06:28 -0600 Subject: i40e: add missing kernel-doc argument The following kernel-doc arguments for their respective functions are missing: 1) @cd_type_cmd_tso_mss for i40e_tso(); 2) @cd_type_cmd_tso_mss for i40e_tsyn(); 3) @tx_ring for i40e_tx_enable_csum(). Add them all for the kernel-doc requirement. Signed-off-by: Jean Sacren Tested-by: Andrew Bowers Acked-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 006f0fb4720c..635b3ac17877 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2187,6 +2187,7 @@ out: * @tx_ring: ptr to the ring to send * @skb: ptr to the skb we're sending * @hdr_len: ptr to the size of the packet header + * @cd_type_cmd_tso_mss: ptr to u64 object * @cd_tunneling: ptr to context descriptor bits * * Returns 0 if no TSO can happen, 1 if tso is going, or error @@ -2246,6 +2247,7 @@ static int i40e_tso(struct i40e_ring *tx_ring, struct sk_buff *skb, * @tx_ring: ptr to the ring to send * @skb: ptr to the skb we're sending * @tx_flags: the collected send information + * @cd_type_cmd_tso_mss: ptr to u64 object * * Returns 0 if no Tx timestamp can happen and 1 if the timestamp will happen **/ @@ -2288,6 +2290,7 @@ static int i40e_tsyn(struct i40e_ring *tx_ring, struct sk_buff *skb, * @tx_flags: pointer to Tx flags currently set * @td_cmd: Tx descriptor command bits to set * @td_offset: Tx descriptor header offsets to set + * @tx_ring: Tx descriptor ring * @cd_tunneling: ptr to context desc bits **/ static void i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, -- cgit v1.2.3 From ed17f7e5d7918adb487debe49fadf57fd2b98d1c Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Tue, 13 Oct 2015 01:06:30 -0600 Subject: i40evf: clean up local variable initialization In i40evf_msix_aq(), the first two lines of rd32() are mainly to clear the registers. If we initialize 'val' at this point, it will be overwritten immediately. We shall simply discard the return value here. When we initialize 'val', we might as well include the mask in one step. Signed-off-by: Jean Sacren Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index f358366efe00..d962164dfb0f 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -306,15 +306,14 @@ static irqreturn_t i40evf_msix_aq(int irq, void *data) struct i40evf_adapter *adapter = netdev_priv(netdev); struct i40e_hw *hw = &adapter->hw; u32 val; - u32 ena_mask; /* handle non-queue interrupts */ - val = rd32(hw, I40E_VFINT_ICR01); - ena_mask = rd32(hw, I40E_VFINT_ICR0_ENA1); + rd32(hw, I40E_VFINT_ICR01); + rd32(hw, I40E_VFINT_ICR0_ENA1); - val = rd32(hw, I40E_VFINT_DYN_CTL01); - val = val | I40E_VFINT_DYN_CTL01_CLEARPBA_MASK; + val = rd32(hw, I40E_VFINT_DYN_CTL01) | + I40E_VFINT_DYN_CTL01_CLEARPBA_MASK; wr32(hw, I40E_VFINT_DYN_CTL01, val); /* schedule work on the private workqueue */ -- cgit v1.2.3 From 0e5229c6c576969bf8f89f8ca74fa7ea355b434e Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Tue, 13 Oct 2015 01:06:31 -0600 Subject: i40e: clean up local variable initialization In both i40e_calc_nvm_checksum() and i40e_update_nvm_checksum(), the local variables designated by 'ret_code' are overwritten immediately. As such, they should merely be declared. Signed-off-by: Jean Sacren Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 58e384a372a0..1715358a8a6c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -484,7 +484,7 @@ static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer, static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw, u16 *checksum) { - i40e_status ret_code = 0; + i40e_status ret_code; struct i40e_virt_mem vmem; u16 pcie_alt_module = 0; u16 checksum_local = 0; @@ -564,7 +564,7 @@ i40e_calc_nvm_checksum_exit: **/ i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw) { - i40e_status ret_code = 0; + i40e_status ret_code; u16 checksum; __le16 le_sum; -- cgit v1.2.3 From 2fc4cd52fa7ed86e9d1df94e459b6a2435bfa9c7 Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Tue, 13 Oct 2015 01:06:32 -0600 Subject: i40e: fix unconditional execution of cpu_to_le16() The commit 3092e5e4cc79 ("i40e: add little endian conversion for checksum") fixed the checksum bug on big-endian architecture. But we should not execute cpu_to_le16() unconditionally. Thus, put cpu_to_le16() under certain condition. Cc: Jesse Brandeburg Cc: Paul M Stillwell Jr Signed-off-by: Jean Sacren Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_nvm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 1715358a8a6c..6100cdd9ad13 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -569,10 +569,11 @@ i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw) __le16 le_sum; ret_code = i40e_calc_nvm_checksum(hw, &checksum); - le_sum = cpu_to_le16(checksum); - if (!ret_code) + if (!ret_code) { + le_sum = cpu_to_le16(checksum); ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD, 1, &le_sum, true); + } return ret_code; } -- cgit v1.2.3 From 6fb3b6b57ae444d7723088656dce86b1be92498d Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Fri, 23 Oct 2015 14:41:12 +0300 Subject: drivers: net: cpsw: use module_platform_driver There is no reasons to probe cpsw from late_initcall level and it's not recommended. Hence, use module_platform_driver() to register and probe cpsw driver from module_init() level. Cc: Tony Lindgren Acked-by: Mugunthan V N Signed-off-by: Grygorii Strashko Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 3b75adfb3f37..55d2d8577d07 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -2583,17 +2583,7 @@ static struct platform_driver cpsw_driver = { .remove = cpsw_remove, }; -static int __init cpsw_init(void) -{ - return platform_driver_register(&cpsw_driver); -} -late_initcall(cpsw_init); - -static void __exit cpsw_exit(void) -{ - platform_driver_unregister(&cpsw_driver); -} -module_exit(cpsw_exit); +module_platform_driver(cpsw_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Cyril Chemparathy "); -- cgit v1.2.3 From 54011e4db839504791cf8317fc48949c683587d4 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 28 Aug 2015 06:58:33 +0000 Subject: ixgbe: Add new ndo to trust VF Implements the new netdev op to trust VF in ixgbe. The administrator can turn on and off VF trusted by ip command which supports trust message. # ip link set dev eth0 vf 1 trust on or # ip link set dev eth0 vf 1 trust off Send a ping to reset VF on changing the status of trusting. VF driver will reconfigure its features on reset. Signed-off-by: Hiroshi Shimamoto Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 37 ++++++++++++++++++++++++++ drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h | 1 + 4 files changed, 40 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index dda0f678339a..920de986296c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -152,6 +152,7 @@ struct vf_data_storage { u16 vlan_count; u8 spoofchk_enabled; bool rss_query_enabled; + u8 trusted; unsigned int vf_api; }; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 9f8a7fd7a195..47395ff5d908 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -8407,6 +8407,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_set_vf_rate = ixgbe_ndo_set_vf_bw, .ndo_set_vf_spoofchk = ixgbe_ndo_set_vf_spoofchk, .ndo_set_vf_rss_query_en = ixgbe_ndo_set_vf_rss_query_en, + .ndo_set_vf_trust = ixgbe_ndo_set_vf_trust, .ndo_get_vf_config = ixgbe_ndo_get_vf_config, .ndo_get_stats64 = ixgbe_get_stats64, #ifdef CONFIG_IXGBE_DCB diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 1d17b5872dd1..65aeb5853252 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -116,6 +116,9 @@ static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter) * we want to disable the querying by default. */ adapter->vfinfo[i].rss_query_enabled = 0; + + /* Untrust all VFs */ + adapter->vfinfo[i].trusted = false; } return 0; @@ -1124,6 +1127,17 @@ void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), 0); } +static inline void ixgbe_ping_vf(struct ixgbe_adapter *adapter, int vf) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 ping; + + ping = IXGBE_PF_CONTROL_MSG; + if (adapter->vfinfo[vf].clear_to_send) + ping |= IXGBE_VT_MSGTYPE_CTS; + ixgbe_write_mbx(hw, &ping, 1, vf); +} + void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; @@ -1416,6 +1430,28 @@ int ixgbe_ndo_set_vf_rss_query_en(struct net_device *netdev, int vf, return 0; } +int ixgbe_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting) +{ + struct ixgbe_adapter *adapter = netdev_priv(netdev); + + if (vf >= adapter->num_vfs) + return -EINVAL; + + /* nothing to do */ + if (adapter->vfinfo[vf].trusted == setting) + return 0; + + adapter->vfinfo[vf].trusted = setting; + + /* reset VF to reconfigure features */ + adapter->vfinfo[vf].clear_to_send = false; + ixgbe_ping_vf(adapter, vf); + + e_info(drv, "VF %u is %strusted\n", vf, setting ? "" : "not "); + + return 0; +} + int ixgbe_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi) { @@ -1430,5 +1466,6 @@ int ixgbe_ndo_get_vf_config(struct net_device *netdev, ivi->qos = adapter->vfinfo[vf].pf_qos; ivi->spoofchk = adapter->vfinfo[vf].spoofchk_enabled; ivi->rss_query_en = adapter->vfinfo[vf].rss_query_enabled; + ivi->trusted = adapter->vfinfo[vf].trusted; return 0; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h index 2c197e6d1fe7..dad925706f4c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h @@ -49,6 +49,7 @@ int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate, int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting); int ixgbe_ndo_set_vf_rss_query_en(struct net_device *netdev, int vf, bool setting); +int ixgbe_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting); int ixgbe_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi); void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter); -- cgit v1.2.3 From 8443c1a4b192089e62642d847ebac3e4d15134c3 Mon Sep 17 00:00:00 2001 From: Hiroshi Shimamoto Date: Fri, 28 Aug 2015 06:59:03 +0000 Subject: ixgbe, ixgbevf: Add new mbox API xcast mode The limitation of the number of multicast address for VF is not enough for the large scale server with SR-IOV feature. IPv6 requires the multicast MAC address for each IP address to handle the Neighbor Solicitation message. We couldn't assign over 30 IPv6 addresses to a single VF. This patch introduces the new mailbox API, IXGBE_VF_UPDATE_XCAST_MODE, to update multicast mode of VF. This adds 3 modes; - NONE only L2 exact match addresses or Flow Director enabled - MULTI BAM and ROMPE set - ALLMULTI BAM, ROMPE and MPE set If a guest VF user wants over 30 MAC multicast addresses, set IFF_ALLMULTI to request PF to update xcast mode to enable VF multicast promiscuous mode. On the other hand, enabling VF multicast promiscuous mode may affect security and performance in the network of the NIC. Only trusted VF can enable multicast promiscuous mode. The behavior of untrusted VF is the same as previous version. Signed-off-by: Hiroshi Shimamoto Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 7 +++ drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h | 2 + drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c | 59 +++++++++++++++++++++++ drivers/net/ethernet/intel/ixgbevf/ixgbevf.h | 6 +++ drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 8 +++ drivers/net/ethernet/intel/ixgbevf/mbx.h | 2 + drivers/net/ethernet/intel/ixgbevf/vf.c | 41 ++++++++++++++++ drivers/net/ethernet/intel/ixgbevf/vf.h | 1 + 8 files changed, 126 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 920de986296c..1d2174526a4c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -153,9 +153,16 @@ struct vf_data_storage { u8 spoofchk_enabled; bool rss_query_enabled; u8 trusted; + int xcast_mode; unsigned int vf_api; }; +enum ixgbevf_xcast_modes { + IXGBEVF_XCAST_MODE_NONE = 0, + IXGBEVF_XCAST_MODE_MULTI, + IXGBEVF_XCAST_MODE_ALLMULTI, +}; + struct vf_macvlans { struct list_head l; int vf; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h index b1e4703ff2a5..8daa95f74548 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h @@ -102,6 +102,8 @@ enum ixgbe_pfvf_api_rev { #define IXGBE_VF_GET_RETA 0x0a /* VF request for RETA */ #define IXGBE_VF_GET_RSS_KEY 0x0b /* get RSS key */ +#define IXGBE_VF_UPDATE_XCAST_MODE 0x0c + /* length of permanent address message returned from PF */ #define IXGBE_VF_PERMADDR_MSG_LEN 4 /* word in permanent address message with the current multicast type */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c index 65aeb5853252..fcd8b27a0ccb 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c @@ -119,6 +119,9 @@ static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter) /* Untrust all VFs */ adapter->vfinfo[i].trusted = false; + + /* set the default xcast mode */ + adapter->vfinfo[i].xcast_mode = IXGBEVF_XCAST_MODE_NONE; } return 0; @@ -1004,6 +1007,59 @@ static int ixgbe_get_vf_rss_key(struct ixgbe_adapter *adapter, return 0; } +static int ixgbe_update_vf_xcast_mode(struct ixgbe_adapter *adapter, + u32 *msgbuf, u32 vf) +{ + struct ixgbe_hw *hw = &adapter->hw; + int xcast_mode = msgbuf[1]; + u32 vmolr, disable, enable; + + /* verify the PF is supporting the correct APIs */ + switch (adapter->vfinfo[vf].vf_api) { + case ixgbe_mbox_api_12: + break; + default: + return -EOPNOTSUPP; + } + + if (xcast_mode > IXGBEVF_XCAST_MODE_MULTI && + !adapter->vfinfo[vf].trusted) { + xcast_mode = IXGBEVF_XCAST_MODE_MULTI; + } + + if (adapter->vfinfo[vf].xcast_mode == xcast_mode) + goto out; + + switch (xcast_mode) { + case IXGBEVF_XCAST_MODE_NONE: + disable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_MPE; + enable = 0; + break; + case IXGBEVF_XCAST_MODE_MULTI: + disable = IXGBE_VMOLR_MPE; + enable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE; + break; + case IXGBEVF_XCAST_MODE_ALLMULTI: + disable = 0; + enable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE | IXGBE_VMOLR_MPE; + break; + default: + return -EOPNOTSUPP; + } + + vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf)); + vmolr &= ~disable; + vmolr |= enable; + IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr); + + adapter->vfinfo[vf].xcast_mode = xcast_mode; + +out: + msgbuf[1] = xcast_mode; + + return 0; +} + static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) { u32 mbx_size = IXGBE_VFMAILBOX_SIZE; @@ -1066,6 +1122,9 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) case IXGBE_VF_GET_RSS_KEY: retval = ixgbe_get_vf_rss_key(adapter, msgbuf, vf); break; + case IXGBE_VF_UPDATE_XCAST_MODE: + retval = ixgbe_update_vf_xcast_mode(adapter, msgbuf, vf); + break; default: e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]); retval = IXGBE_ERR_MBX; diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index 04c7ec8446e0..ec3147279621 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -471,6 +471,12 @@ enum ixgbevf_boards { board_X550EM_x_vf, }; +enum ixgbevf_xcast_modes { + IXGBEVF_XCAST_MODE_NONE = 0, + IXGBEVF_XCAST_MODE_MULTI, + IXGBEVF_XCAST_MODE_ALLMULTI, +}; + extern const struct ixgbevf_info ixgbevf_82599_vf_info; extern const struct ixgbevf_info ixgbevf_X540_vf_info; extern const struct ixgbevf_info ixgbevf_X550_vf_info; diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 7570b5c7ccd8..592ff237d692 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -1894,9 +1894,17 @@ static void ixgbevf_set_rx_mode(struct net_device *netdev) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; + unsigned int flags = netdev->flags; + int xcast_mode; + + xcast_mode = (flags & IFF_ALLMULTI) ? IXGBEVF_XCAST_MODE_ALLMULTI : + (flags & (IFF_BROADCAST | IFF_MULTICAST)) ? + IXGBEVF_XCAST_MODE_MULTI : IXGBEVF_XCAST_MODE_NONE; spin_lock_bh(&adapter->mbx_lock); + hw->mac.ops.update_xcast_mode(hw, netdev, xcast_mode); + /* reprogram multicast list */ hw->mac.ops.update_mc_addr_list(hw, netdev); diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.h b/drivers/net/ethernet/intel/ixgbevf/mbx.h index 82f44e06e5fc..340cdd469455 100644 --- a/drivers/net/ethernet/intel/ixgbevf/mbx.h +++ b/drivers/net/ethernet/intel/ixgbevf/mbx.h @@ -112,6 +112,8 @@ enum ixgbe_pfvf_api_rev { #define IXGBE_VF_GET_RETA 0x0a /* VF request for RETA */ #define IXGBE_VF_GET_RSS_KEY 0x0b /* get RSS hash key */ +#define IXGBE_VF_UPDATE_XCAST_MODE 0x0c + /* length of permanent address message returned from PF */ #define IXGBE_VF_PERMADDR_MSG_LEN 4 /* word in permanent address message with the current multicast type */ diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c index d1339b050627..427f3605cbfc 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.c +++ b/drivers/net/ethernet/intel/ixgbevf/vf.c @@ -468,6 +468,46 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw, return 0; } +/** + * ixgbevf_update_xcast_mode - Update Multicast mode + * @hw: pointer to the HW structure + * @netdev: pointer to net device structure + * @xcast_mode: new multicast mode + * + * Updates the Multicast Mode of VF. + **/ +static s32 ixgbevf_update_xcast_mode(struct ixgbe_hw *hw, + struct net_device *netdev, int xcast_mode) +{ + struct ixgbe_mbx_info *mbx = &hw->mbx; + u32 msgbuf[2]; + s32 err; + + switch (hw->api_version) { + case ixgbe_mbox_api_12: + break; + default: + return -EOPNOTSUPP; + } + + msgbuf[0] = IXGBE_VF_UPDATE_XCAST_MODE; + msgbuf[1] = xcast_mode; + + err = mbx->ops.write_posted(hw, msgbuf, 2); + if (err) + return err; + + err = mbx->ops.read_posted(hw, msgbuf, 2); + if (err) + return err; + + msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS; + if (msgbuf[0] == (IXGBE_VF_UPDATE_XCAST_MODE | IXGBE_VT_MSGTYPE_NACK)) + return -EPERM; + + return 0; +} + /** * ixgbevf_set_vfta_vf - Set/Unset VLAN filter table address * @hw: pointer to the HW structure @@ -727,6 +767,7 @@ static const struct ixgbe_mac_operations ixgbevf_mac_ops = { .check_link = ixgbevf_check_mac_link_vf, .set_rar = ixgbevf_set_rar_vf, .update_mc_addr_list = ixgbevf_update_mc_addr_list_vf, + .update_xcast_mode = ixgbevf_update_xcast_mode, .set_uc_addr = ixgbevf_set_uc_addr_vf, .set_vfta = ixgbevf_set_vfta_vf, }; diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h index d40f036b6df0..ef9f7736b4dc 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.h +++ b/drivers/net/ethernet/intel/ixgbevf/vf.h @@ -63,6 +63,7 @@ struct ixgbe_mac_operations { s32 (*set_uc_addr)(struct ixgbe_hw *, u32, u8 *); s32 (*init_rx_addrs)(struct ixgbe_hw *); s32 (*update_mc_addr_list)(struct ixgbe_hw *, struct net_device *); + s32 (*update_xcast_mode)(struct ixgbe_hw *, struct net_device *, int); s32 (*enable_mc)(struct ixgbe_hw *); s32 (*disable_mc)(struct ixgbe_hw *); s32 (*clear_vfta)(struct ixgbe_hw *); -- cgit v1.2.3 From 21dd19fed3c3eb42a3877600f4a97a774323e562 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 22 Oct 2015 10:37:49 +0200 Subject: net: phy: Add nested variants of mdiobus read/write Since nested variants of mdiobus_read/write are used in multiple drivers, add nested variants in the mdiobus core. Suggested-by: Andrew Lunn Signed-off-by: Neil Armstrong Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 12f44c53cc8e..88cb4592b6fb 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -371,6 +371,33 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr) } EXPORT_SYMBOL(mdiobus_scan); +/** + * mdiobus_read_nested - Nested version of the mdiobus_read function + * @bus: the mii_bus struct + * @addr: the phy address + * @regnum: register number to read + * + * In case of nested MDIO bus access avoid lockdep false positives by + * using mutex_lock_nested(). + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum) +{ + int retval; + + BUG_ON(in_interrupt()); + + mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING); + retval = bus->read(bus, addr, regnum); + mutex_unlock(&bus->mdio_lock); + + return retval; +} +EXPORT_SYMBOL(mdiobus_read_nested); + /** * mdiobus_read - Convenience function for reading a given MII mgmt register * @bus: the mii_bus struct @@ -395,6 +422,34 @@ int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) } EXPORT_SYMBOL(mdiobus_read); +/** + * mdiobus_write_nested - Nested version of the mdiobus_write function + * @bus: the mii_bus struct + * @addr: the phy address + * @regnum: register number to write + * @val: value to write to @regnum + * + * In case of nested MDIO bus access avoid lockdep false positives by + * using mutex_lock_nested(). + * + * NOTE: MUST NOT be called from interrupt context, + * because the bus read/write functions may wait for an interrupt + * to conclude the operation. + */ +int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val) +{ + int err; + + BUG_ON(in_interrupt()); + + mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING); + err = bus->write(bus, addr, regnum, val); + mutex_unlock(&bus->mdio_lock); + + return err; +} +EXPORT_SYMBOL(mdiobus_write_nested); + /** * mdiobus_write - Convenience function for writing a given MII mgmt register * @bus: the mii_bus struct -- cgit v1.2.3 From 6e899e6c51320dd340ccc7a3d4391cedd0ba275b Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 22 Oct 2015 10:37:53 +0200 Subject: net: dsa: Make mv88e6xxx use nested mdiobus read/write Make the mv88e6xxx driver use the previously introduced nested variants of mdiobus_read/write functions. Signed-off-by: Neil Armstrong Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 46 +++++++++------------------------------------ 1 file changed, 9 insertions(+), 37 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 7af96309bc07..b1b14f519d8b 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -24,34 +24,6 @@ #include #include "mv88e6xxx.h" -/* MDIO bus access can be nested in the case of PHYs connected to the - * internal MDIO bus of the switch, which is accessed via MDIO bus of - * the Ethernet interface. Avoid lockdep false positives by using - * mutex_lock_nested(). - */ -static int mv88e6xxx_mdiobus_read(struct mii_bus *bus, int addr, u32 regnum) -{ - int ret; - - mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING); - ret = bus->read(bus, addr, regnum); - mutex_unlock(&bus->mdio_lock); - - return ret; -} - -static int mv88e6xxx_mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, - u16 val) -{ - int ret; - - mutex_lock_nested(&bus->mdio_lock, SINGLE_DEPTH_NESTING); - ret = bus->write(bus, addr, regnum, val); - mutex_unlock(&bus->mdio_lock); - - return ret; -} - /* If the switch's ADDR[4:0] strap pins are strapped to zero, it will * use all 32 SMI bus addresses on its SMI bus, and all switch registers * will be directly accessible on some {device address,register address} @@ -66,7 +38,7 @@ static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr) int i; for (i = 0; i < 16; i++) { - ret = mv88e6xxx_mdiobus_read(bus, sw_addr, SMI_CMD); + ret = mdiobus_read_nested(bus, sw_addr, SMI_CMD); if (ret < 0) return ret; @@ -82,7 +54,7 @@ int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg) int ret; if (sw_addr == 0) - return mv88e6xxx_mdiobus_read(bus, addr, reg); + return mdiobus_read_nested(bus, addr, reg); /* Wait for the bus to become free. */ ret = mv88e6xxx_reg_wait_ready(bus, sw_addr); @@ -90,8 +62,8 @@ int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg) return ret; /* Transmit the read command. */ - ret = mv88e6xxx_mdiobus_write(bus, sw_addr, SMI_CMD, - SMI_CMD_OP_22_READ | (addr << 5) | reg); + ret = mdiobus_write_nested(bus, sw_addr, SMI_CMD, + SMI_CMD_OP_22_READ | (addr << 5) | reg); if (ret < 0) return ret; @@ -101,7 +73,7 @@ int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg) return ret; /* Read the data. */ - ret = mv88e6xxx_mdiobus_read(bus, sw_addr, SMI_DATA); + ret = mdiobus_read_nested(bus, sw_addr, SMI_DATA); if (ret < 0) return ret; @@ -145,7 +117,7 @@ int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, int ret; if (sw_addr == 0) - return mv88e6xxx_mdiobus_write(bus, addr, reg, val); + return mdiobus_write_nested(bus, addr, reg, val); /* Wait for the bus to become free. */ ret = mv88e6xxx_reg_wait_ready(bus, sw_addr); @@ -153,13 +125,13 @@ int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, return ret; /* Transmit the data to write. */ - ret = mv88e6xxx_mdiobus_write(bus, sw_addr, SMI_DATA, val); + ret = mdiobus_write_nested(bus, sw_addr, SMI_DATA, val); if (ret < 0) return ret; /* Transmit the write command. */ - ret = mv88e6xxx_mdiobus_write(bus, sw_addr, SMI_CMD, - SMI_CMD_OP_22_WRITE | (addr << 5) | reg); + ret = mdiobus_write_nested(bus, sw_addr, SMI_CMD, + SMI_CMD_OP_22_WRITE | (addr << 5) | reg); if (ret < 0) return ret; -- cgit v1.2.3 From f0505610505caf8443cd5ea269a7936b64711fee Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 22 Oct 2015 10:37:57 +0200 Subject: net: dsa: Make mv88e6060 use nested mdiobus read/write Like mv88e6xxx and mdio-mux, to avoid lockdep give false positives because of nested MDIO busses, switch to previously introduced nested mdiobus_read/write variants. Signed-off-by: Neil Armstrong Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6060.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index c29aebe1e62b..9093577755f6 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -26,7 +26,7 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg) if (bus == NULL) return -EINVAL; - return mdiobus_read(bus, ds->pd->sw_addr + addr, reg); + return mdiobus_read_nested(bus, ds->pd->sw_addr + addr, reg); } #define REG_READ(addr, reg) \ @@ -47,7 +47,7 @@ static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) if (bus == NULL) return -EINVAL; - return mdiobus_write(bus, ds->pd->sw_addr + addr, reg, val); + return mdiobus_write_nested(bus, ds->pd->sw_addr + addr, reg, val); } #define REG_WRITE(addr, reg, val) \ -- cgit v1.2.3 From a0f2e80fcd3b6b1369527828b02caab01af60c36 Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Wed, 24 Jun 2015 18:03:14 +0100 Subject: net/xen-netback: xenvif_gop_frag_copy: move GSO check out of the loop The skb doesn't change within the function. Therefore it's only necessary to check if we need GSO once at the beginning. Signed-off-by: Julien Grall Acked-by: Wei Liu Signed-off-by: David Vrabel --- drivers/net/xen-netback/netback.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index ec98d43916a8..c4e6c025d64d 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -288,6 +288,13 @@ static void xenvif_gop_frag_copy(struct xenvif_queue *queue, struct sk_buff *skb unsigned long bytes; int gso_type = XEN_NETIF_GSO_TYPE_NONE; + if (skb_is_gso(skb)) { + if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) + gso_type = XEN_NETIF_GSO_TYPE_TCPV4; + else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) + gso_type = XEN_NETIF_GSO_TYPE_TCPV6; + } + /* Data must not cross a page boundary. */ BUG_ON(size + offset > PAGE_SIZE<gso_type & SKB_GSO_TCPV4) - gso_type = XEN_NETIF_GSO_TYPE_TCPV4; - else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - gso_type = XEN_NETIF_GSO_TYPE_TCPV6; - } - if (*head && ((1 << gso_type) & queue->vif->gso_mask)) queue->rx.req_cons++; -- cgit v1.2.3 From 30c5d7f0da82f55c86c0a09bf21c0623474bb17f Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Fri, 10 Apr 2015 14:42:21 +0100 Subject: net/xen-netfront: Make it running on 64KB page granularity The PV network protocol is using 4KB page granularity. The goal of this patch is to allow a Linux using 64KB page granularity using network device on a non-modified Xen. It's only necessary to adapt the ring size and break skb data in small chunk of 4KB. The rest of the code is relying on the grant table code. Note that we allocate a Linux page for each rx skb but only the first 4KB is used. We may improve the memory usage by extending the size of the rx skb. Signed-off-by: Julien Grall Reviewed-by: David Vrabel Signed-off-by: David Vrabel --- drivers/net/xen-netfront.c | 122 ++++++++++++++++++++++++++++++++------------- 1 file changed, 86 insertions(+), 36 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index f821a97d7827..badca3101b62 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -74,8 +74,8 @@ struct netfront_cb { #define GRANT_INVALID_REF 0 -#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) -#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) +#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, XEN_PAGE_SIZE) +#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, XEN_PAGE_SIZE) /* Minimum number of Rx slots (includes slot for GSO metadata). */ #define NET_RX_SLOTS_MIN (XEN_NETIF_NR_SLOTS_MIN + 1) @@ -291,7 +291,7 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue) struct sk_buff *skb; unsigned short id; grant_ref_t ref; - unsigned long gfn; + struct page *page; struct xen_netif_rx_request *req; skb = xennet_alloc_one_rx_buffer(queue); @@ -307,14 +307,13 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue) BUG_ON((signed short)ref < 0); queue->grant_rx_ref[id] = ref; - gfn = xen_page_to_gfn(skb_frag_page(&skb_shinfo(skb)->frags[0])); + page = skb_frag_page(&skb_shinfo(skb)->frags[0]); req = RING_GET_REQUEST(&queue->rx, req_prod); - gnttab_grant_foreign_access_ref(ref, - queue->info->xbdev->otherend_id, - gfn, - 0); - + gnttab_page_grant_foreign_access_ref_one(ref, + queue->info->xbdev->otherend_id, + page, + 0); req->id = id; req->gref = ref; } @@ -415,25 +414,33 @@ static void xennet_tx_buf_gc(struct netfront_queue *queue) xennet_maybe_wake_tx(queue); } -static struct xen_netif_tx_request *xennet_make_one_txreq( - struct netfront_queue *queue, struct sk_buff *skb, - struct page *page, unsigned int offset, unsigned int len) +struct xennet_gnttab_make_txreq { + struct netfront_queue *queue; + struct sk_buff *skb; + struct page *page; + struct xen_netif_tx_request *tx; /* Last request */ + unsigned int size; +}; + +static void xennet_tx_setup_grant(unsigned long gfn, unsigned int offset, + unsigned int len, void *data) { + struct xennet_gnttab_make_txreq *info = data; unsigned int id; struct xen_netif_tx_request *tx; grant_ref_t ref; - - len = min_t(unsigned int, PAGE_SIZE - offset, len); + /* convenient aliases */ + struct page *page = info->page; + struct netfront_queue *queue = info->queue; + struct sk_buff *skb = info->skb; id = get_id_from_freelist(&queue->tx_skb_freelist, queue->tx_skbs); tx = RING_GET_REQUEST(&queue->tx, queue->tx.req_prod_pvt++); ref = gnttab_claim_grant_reference(&queue->gref_tx_head); BUG_ON((signed short)ref < 0); - gnttab_grant_foreign_access_ref(ref, - queue->info->xbdev->otherend_id, - xen_page_to_gfn(page), - GNTMAP_readonly); + gnttab_grant_foreign_access_ref(ref, queue->info->xbdev->otherend_id, + gfn, GNTMAP_readonly); queue->tx_skbs[id].skb = skb; queue->grant_tx_page[id] = page; @@ -445,7 +452,34 @@ static struct xen_netif_tx_request *xennet_make_one_txreq( tx->size = len; tx->flags = 0; - return tx; + info->tx = tx; + info->size += tx->size; +} + +static struct xen_netif_tx_request *xennet_make_first_txreq( + struct netfront_queue *queue, struct sk_buff *skb, + struct page *page, unsigned int offset, unsigned int len) +{ + struct xennet_gnttab_make_txreq info = { + .queue = queue, + .skb = skb, + .page = page, + .size = 0, + }; + + gnttab_for_one_grant(page, offset, len, xennet_tx_setup_grant, &info); + + return info.tx; +} + +static void xennet_make_one_txreq(unsigned long gfn, unsigned int offset, + unsigned int len, void *data) +{ + struct xennet_gnttab_make_txreq *info = data; + + info->tx->flags |= XEN_NETTXF_more_data; + skb_get(info->skb); + xennet_tx_setup_grant(gfn, offset, len, data); } static struct xen_netif_tx_request *xennet_make_txreqs( @@ -453,20 +487,30 @@ static struct xen_netif_tx_request *xennet_make_txreqs( struct sk_buff *skb, struct page *page, unsigned int offset, unsigned int len) { + struct xennet_gnttab_make_txreq info = { + .queue = queue, + .skb = skb, + .tx = tx, + }; + /* Skip unused frames from start of page */ page += offset >> PAGE_SHIFT; offset &= ~PAGE_MASK; while (len) { - tx->flags |= XEN_NETTXF_more_data; - tx = xennet_make_one_txreq(queue, skb_get(skb), - page, offset, len); + info.page = page; + info.size = 0; + + gnttab_foreach_grant_in_range(page, offset, len, + xennet_make_one_txreq, + &info); + page++; offset = 0; - len -= tx->size; + len -= info.size; } - return tx; + return info.tx; } /* @@ -476,9 +520,10 @@ static struct xen_netif_tx_request *xennet_make_txreqs( static int xennet_count_skb_slots(struct sk_buff *skb) { int i, frags = skb_shinfo(skb)->nr_frags; - int pages; + int slots; - pages = PFN_UP(offset_in_page(skb->data) + skb_headlen(skb)); + slots = gnttab_count_grant(offset_in_page(skb->data), + skb_headlen(skb)); for (i = 0; i < frags; i++) { skb_frag_t *frag = skb_shinfo(skb)->frags + i; @@ -488,10 +533,10 @@ static int xennet_count_skb_slots(struct sk_buff *skb) /* Skip unused frames from start of page */ offset &= ~PAGE_MASK; - pages += PFN_UP(offset + size); + slots += gnttab_count_grant(offset, size); } - return pages; + return slots; } static u16 xennet_select_queue(struct net_device *dev, struct sk_buff *skb, @@ -512,6 +557,8 @@ static u16 xennet_select_queue(struct net_device *dev, struct sk_buff *skb, return queue_idx; } +#define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1) + static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct netfront_info *np = netdev_priv(dev); @@ -546,7 +593,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) } slots = xennet_count_skb_slots(skb); - if (unlikely(slots > MAX_SKB_FRAGS + 1)) { + if (unlikely(slots > MAX_XEN_SKB_FRAGS + 1)) { net_dbg_ratelimited("xennet: skb rides the rocket: %d slots, %d bytes\n", slots, skb->len); if (skb_linearize(skb)) @@ -567,10 +614,13 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) } /* First request for the linear area. */ - first_tx = tx = xennet_make_one_txreq(queue, skb, - page, offset, len); - page++; - offset = 0; + first_tx = tx = xennet_make_first_txreq(queue, skb, + page, offset, len); + offset += tx->size; + if (offset == PAGE_SIZE) { + page++; + offset = 0; + } len -= tx->size; if (skb->ip_summed == CHECKSUM_PARTIAL) @@ -732,7 +782,7 @@ static int xennet_get_responses(struct netfront_queue *queue, for (;;) { if (unlikely(rx->status < 0 || - rx->offset + rx->status > PAGE_SIZE)) { + rx->offset + rx->status > XEN_PAGE_SIZE)) { if (net_ratelimit()) dev_warn(dev, "rx->offset: %u, size: %d\n", rx->offset, rx->status); @@ -1496,7 +1546,7 @@ static int setup_netfront(struct xenbus_device *dev, goto fail; } SHARED_RING_INIT(txs); - FRONT_RING_INIT(&queue->tx, txs, PAGE_SIZE); + FRONT_RING_INIT(&queue->tx, txs, XEN_PAGE_SIZE); err = xenbus_grant_ring(dev, txs, 1, &gref); if (err < 0) @@ -1510,7 +1560,7 @@ static int setup_netfront(struct xenbus_device *dev, goto alloc_rx_ring_fail; } SHARED_RING_INIT(rxs); - FRONT_RING_INIT(&queue->rx, rxs, PAGE_SIZE); + FRONT_RING_INIT(&queue->rx, rxs, XEN_PAGE_SIZE); err = xenbus_grant_ring(dev, rxs, 1, &gref); if (err < 0) -- cgit v1.2.3 From d0089e8a0e4c9723d85b01713671358e3d6960df Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Tue, 5 May 2015 13:15:29 +0100 Subject: net/xen-netback: Make it running on 64KB page granularity The PV network protocol is using 4KB page granularity. The goal of this patch is to allow a Linux using 64KB page granularity working as a network backend on a non-modified Xen. It's only necessary to adapt the ring size and break skb data in small chunk of 4KB. The rest of the code is relying on the grant table code. Signed-off-by: Julien Grall Reviewed-by: Wei Liu Signed-off-by: David Vrabel --- drivers/net/xen-netback/common.h | 16 ++-- drivers/net/xen-netback/netback.c | 157 ++++++++++++++++++++++++-------------- 2 files changed, 111 insertions(+), 62 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index a7bf74727116..0333ab0fd926 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -44,6 +44,7 @@ #include #include #include +#include #include typedef unsigned int pending_ring_idx_t; @@ -64,8 +65,8 @@ struct pending_tx_info { struct ubuf_info callback_struct; }; -#define XEN_NETIF_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) -#define XEN_NETIF_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) +#define XEN_NETIF_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, XEN_PAGE_SIZE) +#define XEN_NETIF_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, XEN_PAGE_SIZE) struct xenvif_rx_meta { int id; @@ -80,16 +81,21 @@ struct xenvif_rx_meta { /* Discriminate from any valid pending_idx value. */ #define INVALID_PENDING_IDX 0xFFFF -#define MAX_BUFFER_OFFSET PAGE_SIZE +#define MAX_BUFFER_OFFSET XEN_PAGE_SIZE #define MAX_PENDING_REQS XEN_NETIF_TX_RING_SIZE +/* The maximum number of frags is derived from the size of a grant (same + * as a Xen page size for now). + */ +#define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1) + /* It's possible for an skb to have a maximal number of frags * but still be less than MAX_BUFFER_OFFSET in size. Thus the - * worst-case number of copy operations is MAX_SKB_FRAGS per + * worst-case number of copy operations is MAX_XEN_SKB_FRAGS per * ring slot. */ -#define MAX_GRANT_COPY_OPS (MAX_SKB_FRAGS * XEN_NETIF_RX_RING_SIZE) +#define MAX_GRANT_COPY_OPS (MAX_XEN_SKB_FRAGS * XEN_NETIF_RX_RING_SIZE) #define NETBACK_INVALID_HANDLE -1 diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index c4e6c025d64d..e481f3710bd3 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -152,9 +152,9 @@ static inline pending_ring_idx_t pending_index(unsigned i) static int xenvif_rx_ring_slots_needed(struct xenvif *vif) { if (vif->gso_mask) - return DIV_ROUND_UP(vif->dev->gso_max_size, PAGE_SIZE) + 1; + return DIV_ROUND_UP(vif->dev->gso_max_size, XEN_PAGE_SIZE) + 1; else - return DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE); + return DIV_ROUND_UP(vif->dev->mtu, XEN_PAGE_SIZE); } static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue) @@ -274,6 +274,80 @@ static struct xenvif_rx_meta *get_next_rx_buffer(struct xenvif_queue *queue, return meta; } +struct gop_frag_copy { + struct xenvif_queue *queue; + struct netrx_pending_operations *npo; + struct xenvif_rx_meta *meta; + int head; + int gso_type; + + struct page *page; +}; + +static void xenvif_setup_copy_gop(unsigned long gfn, + unsigned int offset, + unsigned int *len, + struct gop_frag_copy *info) +{ + struct gnttab_copy *copy_gop; + struct xen_page_foreign *foreign; + /* Convenient aliases */ + struct xenvif_queue *queue = info->queue; + struct netrx_pending_operations *npo = info->npo; + struct page *page = info->page; + + BUG_ON(npo->copy_off > MAX_BUFFER_OFFSET); + + if (npo->copy_off == MAX_BUFFER_OFFSET) + info->meta = get_next_rx_buffer(queue, npo); + + if (npo->copy_off + *len > MAX_BUFFER_OFFSET) + *len = MAX_BUFFER_OFFSET - npo->copy_off; + + copy_gop = npo->copy + npo->copy_prod++; + copy_gop->flags = GNTCOPY_dest_gref; + copy_gop->len = *len; + + foreign = xen_page_foreign(page); + if (foreign) { + copy_gop->source.domid = foreign->domid; + copy_gop->source.u.ref = foreign->gref; + copy_gop->flags |= GNTCOPY_source_gref; + } else { + copy_gop->source.domid = DOMID_SELF; + copy_gop->source.u.gmfn = gfn; + } + copy_gop->source.offset = offset; + + copy_gop->dest.domid = queue->vif->domid; + copy_gop->dest.offset = npo->copy_off; + copy_gop->dest.u.ref = npo->copy_gref; + + npo->copy_off += *len; + info->meta->size += *len; + + /* Leave a gap for the GSO descriptor. */ + if (info->head && ((1 << info->gso_type) & queue->vif->gso_mask)) + queue->rx.req_cons++; + + info->head = 0; /* There must be something in this buffer now */ +} + +static void xenvif_gop_frag_copy_grant(unsigned long gfn, + unsigned offset, + unsigned int len, + void *data) +{ + unsigned int bytes; + + while (len) { + bytes = len; + xenvif_setup_copy_gop(gfn, offset, &bytes, data); + offset += bytes; + len -= bytes; + } +} + /* * Set up the grant operations for this fragment. If it's a flipping * interface, we also set up the unmap request from here. @@ -283,83 +357,52 @@ static void xenvif_gop_frag_copy(struct xenvif_queue *queue, struct sk_buff *skb struct page *page, unsigned long size, unsigned long offset, int *head) { - struct gnttab_copy *copy_gop; - struct xenvif_rx_meta *meta; + struct gop_frag_copy info = { + .queue = queue, + .npo = npo, + .head = *head, + .gso_type = XEN_NETIF_GSO_TYPE_NONE, + }; unsigned long bytes; - int gso_type = XEN_NETIF_GSO_TYPE_NONE; if (skb_is_gso(skb)) { if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) - gso_type = XEN_NETIF_GSO_TYPE_TCPV4; + info.gso_type = XEN_NETIF_GSO_TYPE_TCPV4; else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - gso_type = XEN_NETIF_GSO_TYPE_TCPV6; + info.gso_type = XEN_NETIF_GSO_TYPE_TCPV6; } /* Data must not cross a page boundary. */ BUG_ON(size + offset > PAGE_SIZE<meta + npo->meta_prod - 1; + info.meta = npo->meta + npo->meta_prod - 1; /* Skip unused frames from start of page */ page += offset >> PAGE_SHIFT; offset &= ~PAGE_MASK; while (size > 0) { - struct xen_page_foreign *foreign; - BUG_ON(offset >= PAGE_SIZE); - BUG_ON(npo->copy_off > MAX_BUFFER_OFFSET); - - if (npo->copy_off == MAX_BUFFER_OFFSET) - meta = get_next_rx_buffer(queue, npo); bytes = PAGE_SIZE - offset; if (bytes > size) bytes = size; - if (npo->copy_off + bytes > MAX_BUFFER_OFFSET) - bytes = MAX_BUFFER_OFFSET - npo->copy_off; - - copy_gop = npo->copy + npo->copy_prod++; - copy_gop->flags = GNTCOPY_dest_gref; - copy_gop->len = bytes; - - foreign = xen_page_foreign(page); - if (foreign) { - copy_gop->source.domid = foreign->domid; - copy_gop->source.u.ref = foreign->gref; - copy_gop->flags |= GNTCOPY_source_gref; - } else { - copy_gop->source.domid = DOMID_SELF; - copy_gop->source.u.gmfn = - virt_to_gfn(page_address(page)); - } - copy_gop->source.offset = offset; - - copy_gop->dest.domid = queue->vif->domid; - copy_gop->dest.offset = npo->copy_off; - copy_gop->dest.u.ref = npo->copy_gref; - - npo->copy_off += bytes; - meta->size += bytes; - - offset += bytes; + info.page = page; + gnttab_foreach_grant_in_range(page, offset, bytes, + xenvif_gop_frag_copy_grant, + &info); size -= bytes; + offset = 0; - /* Next frame */ - if (offset == PAGE_SIZE && size) { + /* Next page */ + if (size) { BUG_ON(!PageCompound(page)); page++; - offset = 0; } - - /* Leave a gap for the GSO descriptor. */ - if (*head && ((1 << gso_type) & queue->vif->gso_mask)) - queue->rx.req_cons++; - - *head = 0; /* There must be something in this buffer now. */ - } + + *head = info.head; } /* @@ -758,7 +801,7 @@ static int xenvif_count_requests(struct xenvif_queue *queue, first->size -= txp->size; slots++; - if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { + if (unlikely((txp->offset + txp->size) > XEN_PAGE_SIZE)) { netdev_err(queue->vif->dev, "Cross page boundary, txp->offset: %u, size: %u\n", txp->offset, txp->size); xenvif_fatal_tx_err(queue->vif); @@ -1339,11 +1382,11 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, } /* No crossing a page as the payload mustn't fragment. */ - if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { + if (unlikely((txreq.offset + txreq.size) > XEN_PAGE_SIZE)) { netdev_err(queue->vif->dev, "txreq.offset: %u, size: %u, end: %lu\n", txreq.offset, txreq.size, - (unsigned long)(txreq.offset&~PAGE_MASK) + txreq.size); + (unsigned long)(txreq.offset&~XEN_PAGE_MASK) + txreq.size); xenvif_fatal_tx_err(queue->vif); break; } @@ -1409,7 +1452,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, virt_to_gfn(skb->data); queue->tx_copy_ops[*copy_ops].dest.domid = DOMID_SELF; queue->tx_copy_ops[*copy_ops].dest.offset = - offset_in_page(skb->data); + offset_in_page(skb->data) & ~XEN_PAGE_MASK; queue->tx_copy_ops[*copy_ops].len = data_len; queue->tx_copy_ops[*copy_ops].flags = GNTCOPY_source_gref; @@ -1894,7 +1937,7 @@ int xenvif_map_frontend_rings(struct xenvif_queue *queue, goto err; txs = (struct xen_netif_tx_sring *)addr; - BACK_RING_INIT(&queue->tx, txs, PAGE_SIZE); + BACK_RING_INIT(&queue->tx, txs, XEN_PAGE_SIZE); err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(queue->vif), &rx_ring_ref, 1, &addr); @@ -1902,7 +1945,7 @@ int xenvif_map_frontend_rings(struct xenvif_queue *queue, goto err; rxs = (struct xen_netif_rx_sring *)addr; - BACK_RING_INIT(&queue->rx, rxs, PAGE_SIZE); + BACK_RING_INIT(&queue->rx, rxs, XEN_PAGE_SIZE); return 0; -- cgit v1.2.3 From 379a80a1d048dcacfc2011d5d32e16d5c804b9f4 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 23 Oct 2015 15:06:19 -0400 Subject: bnxt_en: Fix compile errors when CONFIG_BNXT_SRIOV is not set. struct bnxt_pf_info needs to be always defined. Move bnxt_update_vf_mac() to bnxt_sriov.c and add some missing #ifdef CONFIG_BNXT_SRIOV. Reported-by: Jim Hull Tested-by: Jim Hull Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 32 ++++++------------------- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 4 ++-- drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c | 31 +++++++++++++++++++++++- drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h | 1 + 4 files changed, 40 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 94b11a59e703..9e36f83e68f0 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -3645,6 +3645,7 @@ static int bnxt_hwrm_func_qcaps(struct bnxt *bp) pf->max_rx_em_flows = le32_to_cpu(resp->max_rx_em_flows); pf->max_rx_wm_flows = le32_to_cpu(resp->max_rx_wm_flows); } else { +#ifdef CONFIG_BNXT_SRIOV struct bnxt_vf_info *vf = &bp->vf; vf->fw_fid = le16_to_cpu(resp->fid); @@ -3659,6 +3660,7 @@ static int bnxt_hwrm_func_qcaps(struct bnxt *bp) vf->max_l2_ctxs = le16_to_cpu(resp->max_l2_ctxs); vf->max_vnics = le16_to_cpu(resp->max_vnics); vf->max_stat_ctxs = le16_to_cpu(resp->max_stat_ctx); +#endif } bp->tx_push_thresh = 0; @@ -3880,30 +3882,6 @@ static int bnxt_alloc_rfs_vnics(struct bnxt *bp) #endif } -static void bnxt_update_vf_mac(struct bnxt *bp) -{ - struct hwrm_func_qcaps_input req = {0}; - struct hwrm_func_qcaps_output *resp = bp->hwrm_cmd_resp_addr; - - bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCAPS, -1, -1); - req.fid = cpu_to_le16(0xffff); - - mutex_lock(&bp->hwrm_cmd_lock); - if (_hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT)) - goto update_vf_mac_exit; - - if (!is_valid_ether_addr(resp->perm_mac_address)) - goto update_vf_mac_exit; - - if (ether_addr_equal(resp->perm_mac_address, bp->vf.mac_addr)) - goto update_vf_mac_exit; - - memcpy(bp->vf.mac_addr, resp->perm_mac_address, ETH_ALEN); - memcpy(bp->dev->dev_addr, bp->vf.mac_addr, ETH_ALEN); -update_vf_mac_exit: - mutex_unlock(&bp->hwrm_cmd_lock); -} - static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init) { int rc = 0; @@ -5581,7 +5559,7 @@ static int bnxt_get_max_irq(struct pci_dev *pdev) void bnxt_get_max_rings(struct bnxt *bp, int *max_rx, int *max_tx) { - int max_rings; + int max_rings = 0; if (BNXT_PF(bp)) { *max_tx = bp->pf.max_pf_tx_rings; @@ -5589,10 +5567,12 @@ void bnxt_get_max_rings(struct bnxt *bp, int *max_rx, int *max_tx) max_rings = min_t(int, bp->pf.max_irqs, bp->pf.max_cp_rings); max_rings = min_t(int, max_rings, bp->pf.max_stat_ctxs); } else { +#ifdef CONFIG_BNXT_SRIOV *max_tx = bp->vf.max_tx_rings; *max_rx = bp->vf.max_rx_rings; max_rings = min_t(int, bp->vf.max_irqs, bp->vf.max_cp_rings); max_rings = min_t(int, max_rings, bp->vf.max_stat_ctxs); +#endif } if (bp->flags & BNXT_FLAG_AGG_RINGS) *max_rx >>= 1; @@ -5696,8 +5676,10 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) memcpy(dev->dev_addr, bp->pf.mac_addr, ETH_ALEN); bp->pf.max_irqs = max_irqs; } else { +#if defined(CONFIG_BNXT_SRIOV) memcpy(dev->dev_addr, bp->vf.mac_addr, ETH_ALEN); bp->vf.max_irqs = max_irqs; +#endif } bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings); bp->rx_nr_rings = min_t(int, dflt_rings, max_rx_rings); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 7c89367634d0..5ee3cc28a421 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -709,6 +709,7 @@ struct bnxt_vf_info { void *hwrm_cmd_req_addr; dma_addr_t hwrm_cmd_req_dma_addr; }; +#endif struct bnxt_pf_info { #define BNXT_FIRST_PF_FID 1 @@ -741,7 +742,6 @@ struct bnxt_pf_info { dma_addr_t hwrm_cmd_req_dma_addr[4]; struct bnxt_vf_info *vf; }; -#endif struct bnxt_ntuple_filter { struct hlist_node hash; @@ -960,9 +960,9 @@ struct bnxt { #define BNXT_RESET_TASK_SP_EVENT 32 #define BNXT_RST_RING_SP_EVENT 64 + struct bnxt_pf_info pf; #ifdef CONFIG_BNXT_SRIOV int nr_vfs; - struct bnxt_pf_info pf; struct bnxt_vf_info vf; wait_queue_head_t sriov_cfg_wait; bool sriov_cfg; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c index 3422147a65f4..60989e7e266a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c @@ -774,6 +774,31 @@ void bnxt_hwrm_exec_fwd_req(struct bnxt *bp) i = vf_id + 1; } } + +void bnxt_update_vf_mac(struct bnxt *bp) +{ + struct hwrm_func_qcaps_input req = {0}; + struct hwrm_func_qcaps_output *resp = bp->hwrm_cmd_resp_addr; + + bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_QCAPS, -1, -1); + req.fid = cpu_to_le16(0xffff); + + mutex_lock(&bp->hwrm_cmd_lock); + if (_hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT)) + goto update_vf_mac_exit; + + if (!is_valid_ether_addr(resp->perm_mac_address)) + goto update_vf_mac_exit; + + if (ether_addr_equal(resp->perm_mac_address, bp->vf.mac_addr)) + goto update_vf_mac_exit; + + memcpy(bp->vf.mac_addr, resp->perm_mac_address, ETH_ALEN); + memcpy(bp->dev->dev_addr, bp->vf.mac_addr, ETH_ALEN); +update_vf_mac_exit: + mutex_unlock(&bp->hwrm_cmd_lock); +} + #else void bnxt_sriov_disable(struct bnxt *bp) @@ -782,6 +807,10 @@ void bnxt_sriov_disable(struct bnxt *bp) void bnxt_hwrm_exec_fwd_req(struct bnxt *bp) { - netdev_err(dev, "Invalid VF message received when SRIOV is not enable\n"); + netdev_err(bp->dev, "Invalid VF message received when SRIOV is not enable\n"); +} + +void bnxt_update_vf_mac(struct bnxt *bp) +{ } #endif diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h index 0b430f157b9e..c151280e3980 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.h @@ -19,4 +19,5 @@ int bnxt_set_vf_spoofchk(struct net_device *, int, bool); int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs); void bnxt_sriov_disable(struct bnxt *); void bnxt_hwrm_exec_fwd_req(struct bnxt *); +void bnxt_update_vf_mac(struct bnxt *); #endif -- cgit v1.2.3 From 033695bdf6d79180f74893830053fcf3e8bc9d24 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Fri, 23 Oct 2015 20:27:58 +0300 Subject: rtl8xxxu: move devices supported by rtlwifi under UNTESTED config There are still four devices which are currently supported both by the new rtl8xxxu driver and rtlwifi. To not break existing setups enable the support for these four devices only when CONFIG_RTL8XXXU_UNTESTED is turned on. Once rtl8xxxu support is found to be good enough the devices can be removed from rtlwifi and enabled by default in rtl8xxxu. Reported-by: Xose Vazquez Perez Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 47e52ad56144..86d864af3a32 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -5797,6 +5797,8 @@ static struct usb_device_id dev_table[] = { .driver_info = (unsigned long)&rtl8723au_fops}, {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x0724, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8723au_fops}, +#ifdef CONFIG_RTL8XXXU_UNTESTED +/* Still supported by rtlwifi */ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8178, 0xff, 0xff, 0xff), @@ -5806,7 +5808,6 @@ static struct usb_device_id dev_table[] = { /* Tested by Larry Finger */ {USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0x7811, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, -#ifdef CONFIG_RTL8XXXU_UNTESTED /* Currently untested 8188 series devices */ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8191, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8192cu_fops}, -- cgit v1.2.3 From e621c2282e310aa83a50db4da3e16dfc5945db08 Mon Sep 17 00:00:00 2001 From: Alexander Bondar Date: Thu, 3 Sep 2015 15:42:09 +0300 Subject: iwlwifi: rs: Remove workaround that disables MIMO on P2P Remove an old workaround that's no longer needed and enable MIMO on P2P interfaces. Signed-off-by: Alexander Bondar Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/constants.h | 1 - drivers/net/wireless/iwlwifi/mvm/rs.c | 6 ------ 2 files changed, 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index a3ca6db0f303..aa9ae1d83508 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h @@ -101,7 +101,6 @@ #define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 #define IWL_MVM_QUOTA_THRESHOLD 4 #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 -#define IWL_MVM_RS_DISABLE_P2P_MIMO 0 #define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1 #define IWL_MVM_TOF_IS_RESPONDER 0 #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 34d98b26a215..d1ad10391b47 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -177,9 +177,6 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, mvmsta = iwl_mvm_sta_from_mac80211(sta); mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif); - if (IWL_MVM_RS_DISABLE_P2P_MIMO && - iwl_mvm_vif_low_latency(mvmvif) && mvmsta->vif->p2p) - return false; if (mvm->nvm_data->sku_cap_mimo_disabled) return false; @@ -3071,9 +3068,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, else rs_vht_init(mvm, sta, lq_sta, vht_cap); - if (IWL_MVM_RS_DISABLE_P2P_MIMO && sta_priv->vif->p2p) - lq_sta->active_mimo2_rate = 0; - lq_sta->max_legacy_rate_idx = rs_get_max_rate_from_mask(lq_sta->active_legacy_rate); lq_sta->max_siso_rate_idx = -- cgit v1.2.3 From f0afea54ee0dd212186de0291ec025c63016fa39 Mon Sep 17 00:00:00 2001 From: Matti Gottlieb Date: Mon, 20 Jul 2015 17:55:51 +0300 Subject: iwlwifi: mvm: Dump FW's virtual image in the case of a NIC error When paging is enabled the driver stores part of the FW's image in the DRAM. Dump FW's virtual image in the case of a NIC error. Signed-off-by: Golan Ben-Ami Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h | 16 ++++++++++++++ drivers/net/wireless/iwlwifi/mvm/mac80211.c | 27 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h index af5b3201492c..9dbe19cbb4dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h @@ -86,6 +86,8 @@ * Structured as &struct iwl_fw_error_dump_trigger_desc. * @IWL_FW_ERROR_DUMP_RB: the content of an RB structured as * &struct iwl_fw_error_dump_rb + * @IWL_FW_ERROR_PAGING: UMAC's image memory segments which were + * paged to the DRAM. */ enum iwl_fw_error_dump_type { /* 0 is deprecated */ @@ -100,6 +102,7 @@ enum iwl_fw_error_dump_type { IWL_FW_ERROR_DUMP_MEM = 9, IWL_FW_ERROR_DUMP_ERROR_INFO = 10, IWL_FW_ERROR_DUMP_RB = 11, + IWL_FW_ERROR_DUMP_PAGING = 12, IWL_FW_ERROR_DUMP_MAX, }; @@ -239,6 +242,19 @@ struct iwl_fw_error_dump_rb { u8 data[]; }; +/** + * struct iwl_fw_error_dump_paging - content of the UMAC's image page + * block on DRAM + * @index: the index of the page block + * @reserved: + * @data: the content of the page block + */ +struct iwl_fw_error_dump_paging { + __le32 index; + __le32 reserved; + u8 data[]; +}; + /** * iwl_fw_error_next_data - advance fw error dump data pointer * @data: previous data block diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 8443e14101cf..aaffb54e8f78 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1192,6 +1192,13 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) if (sram2_len) file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len; + /* Make room for fw's virtual image pages, if it exists */ + if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) + file_len += mvm->num_of_paging_blk * + (sizeof(*dump_data) + + sizeof(struct iwl_fw_error_dump_paging) + + PAGING_BLOCK_SIZE); + /* If we only want a monitor dump, reset the file length */ if (monitor_dump_only) { file_len = sizeof(*dump_file) + sizeof(*dump_data) + @@ -1302,6 +1309,26 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) dump_mem->data, IWL8260_ICCM_LEN); } + /* Dump fw's virtual image */ + if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) { + u32 i; + + for (i = 1; i < mvm->num_of_paging_blk + 1; i++) { + struct iwl_fw_error_dump_paging *paging; + struct page *pages = + mvm->fw_paging_db[i].fw_paging_block; + + dump_data = iwl_fw_error_next_data(dump_data); + dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING); + dump_data->len = cpu_to_le32(sizeof(*paging) + + PAGING_BLOCK_SIZE); + paging = (void *)dump_data->data; + paging->index = cpu_to_le32(i); + memcpy(paging->data, page_address(pages), + PAGING_BLOCK_SIZE); + } + } + dump_trans_data: fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans, mvm->fw_dump_trig); -- cgit v1.2.3 From 03a19cbb91994212be72ce15ac3406fa9f8ba079 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 21 Oct 2015 19:55:32 +0300 Subject: iwlwifi: pcie: fix (again) prepare card flow The hardware bug in the commit mentioned below forces us not to re-enable the clock gating in the Host Cluster. The impact on the power consumption is minimal and it allows the WAKE_ME interrupt to propagate. CC: [4.1+] Fixes: c9fdec9f3970 ("iwlwifi: pcie: fix prepare card flow") Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/pcie/trans.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 6ba7d300b08f..90283453073c 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -592,10 +592,8 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) do { ret = iwl_pcie_set_hw_ready(trans); - if (ret >= 0) { - ret = 0; - goto out; - } + if (ret >= 0) + return 0; usleep_range(200, 1000); t += 200; @@ -605,10 +603,6 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) IWL_ERR(trans, "Couldn't prepare the card\n"); -out: - iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, - CSR_RESET_LINK_PWR_MGMT_DISABLED); - return ret; } -- cgit v1.2.3 From 78efc702c8b6ddd6563d836f0d9844bf1f288f9b Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Tue, 6 Oct 2015 12:22:47 +0300 Subject: iwlwifi: mvm: correctly request DTS-measure for new cards Since the 8000 series, the DTS measurement request command has been changed. Use an ucode capability flag to determine which version is supported and send the extended command when needed. Signed-off-by: Arik Nemtsov Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/iwl-fw-file.h | 2 + drivers/net/wireless/iwlwifi/mvm/fw-api.h | 63 ++++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/mvm/tt.c | 11 +++++- 3 files changed, 74 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 72ddd4a163e6..847d58b4e73a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h @@ -306,6 +306,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * is supported. * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan + * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ @@ -330,6 +331,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, + IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, NUM_IWL_UCODE_TLV_CAPA #ifdef __CHECKER__ diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 44ff6849b7a5..181590fbd3b3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h @@ -1523,6 +1523,69 @@ struct iwl_dts_measurement_cmd { __le32 flags; } __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_CMD_S */ +/** +* enum iwl_dts_control_measurement_mode - DTS measurement type +* @DTS_AUTOMATIC: Automatic mode (full SW control). Provide temperature read +* back (latest value. Not waiting for new value). Use automatic +* SW DTS configuration. +* @DTS_REQUEST_READ: Request DTS read. Configure DTS with manual settings, +* trigger DTS reading and provide read back temperature read +* when available. +* @DTS_OVER_WRITE: over-write the DTS temperatures in the SW until next read +* @DTS_DIRECT_WITHOUT_MEASURE: DTS returns its latest temperature result, +* without measurement trigger. +*/ +enum iwl_dts_control_measurement_mode { + DTS_AUTOMATIC = 0, + DTS_REQUEST_READ = 1, + DTS_OVER_WRITE = 2, + DTS_DIRECT_WITHOUT_MEASURE = 3, +}; + +/** +* enum iwl_dts_used - DTS to use or used for measurement in the DTS request +* @DTS_USE_TOP: Top +* @DTS_USE_CHAIN_A: chain A +* @DTS_USE_CHAIN_B: chain B +* @DTS_USE_CHAIN_C: chain C +* @XTAL_TEMPERATURE - read temperature from xtal +*/ +enum iwl_dts_used { + DTS_USE_TOP = 0, + DTS_USE_CHAIN_A = 1, + DTS_USE_CHAIN_B = 2, + DTS_USE_CHAIN_C = 3, + XTAL_TEMPERATURE = 4, +}; + +/** +* enum iwl_dts_bit_mode - bit-mode to use in DTS request read mode +* @DTS_BIT6_MODE: bit 6 mode +* @DTS_BIT8_MODE: bit 8 mode +*/ +enum iwl_dts_bit_mode { + DTS_BIT6_MODE = 0, + DTS_BIT8_MODE = 1, +}; + +/** + * iwl_ext_dts_measurement_cmd - request extended DTS temperature measurements + * @control_mode: see &enum iwl_dts_control_measurement_mode + * @temperature: used when over write DTS mode is selected + * @sensor: set temperature sensor to use. See &enum iwl_dts_used + * @avg_factor: average factor to DTS in request DTS read mode + * @bit_mode: value defines the DTS bit mode to use. See &enum iwl_dts_bit_mode + * @step_duration: step duration for the DTS + */ +struct iwl_ext_dts_measurement_cmd { + __le32 control_mode; + __le32 temperature; + __le32 sensor; + __le32 avg_factor; + __le32 bit_mode; + __le32 step_duration; +} __packed; /* XVT_FW_DTS_CONTROL_MEASUREMENT_REQUEST_API_S */ + /** * iwl_dts_measurement_notif - notification received with the measurements * diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index 58b762f1e0b5..cadfc0460597 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c @@ -176,6 +176,9 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm) struct iwl_dts_measurement_cmd cmd = { .flags = cpu_to_le32(DTS_TRIGGER_CMD_FLAGS_TEMP), }; + struct iwl_ext_dts_measurement_cmd extcmd = { + .control_mode = cpu_to_le32(DTS_AUTOMATIC), + }; u32 cmdid; if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR)) @@ -183,8 +186,12 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm) PHY_OPS_GROUP, 0); else cmdid = CMD_DTS_MEASUREMENT_TRIGGER; - return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, - sizeof(cmd), &cmd); + + if (!fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE)) + return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(cmd), &cmd); + + return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(extcmd), &extcmd); } int iwl_mvm_get_temp(struct iwl_mvm *mvm) -- cgit v1.2.3 From 9645edb607427a9728b9269dfded74e8c42a9d48 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Oct 2015 13:28:48 +0200 Subject: iwlwifi: mvm: use wowlan RX/TX timeouts in D0i3 In "hostless" mode (D3 or D0i3) the same parameters were intended to be used, but the code doesn't do that properly. Fix it. Signed-off-by: Johannes Berg Signed-off-by: Avri Altman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/power.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 723b537341c4..7c354feb9be2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -348,7 +348,8 @@ static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm, static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct iwl_mac_power_cmd *cmd) + struct iwl_mac_power_cmd *cmd, + bool host_awake) { int dtimper, bi; int keep_alive; @@ -389,10 +390,9 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD; } - iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, - mvm->cur_ucode != IWL_UCODE_WOWLAN); + iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, host_awake); - if (mvm->cur_ucode != IWL_UCODE_WOWLAN) { + if (host_awake) { cmd->rx_data_timeout = cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT); cmd->tx_data_timeout = @@ -458,7 +458,8 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, { struct iwl_mac_power_cmd cmd = {}; - iwl_mvm_power_build_cmd(mvm, vif, &cmd); + iwl_mvm_power_build_cmd(mvm, vif, &cmd, + mvm->cur_ucode != IWL_UCODE_WOWLAN); iwl_mvm_power_log(mvm, &cmd); #ifdef CONFIG_IWLWIFI_DEBUGFS memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd)); @@ -994,11 +995,7 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, if (!vif->bss_conf.assoc) return 0; - iwl_mvm_power_build_cmd(mvm, vif, &cmd); - - /* when enabling D0i3, override the skip-over-dtim configuration */ - if (enable) - iwl_mvm_power_config_skip_dtim(mvm, vif, &cmd, false); + iwl_mvm_power_build_cmd(mvm, vif, &cmd, !enable); iwl_mvm_power_log(mvm, &cmd); #ifdef CONFIG_IWLWIFI_DEBUGFS -- cgit v1.2.3 From b08dbed71a876d982e3506a97702535fd5cff48c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Oct 2015 14:07:44 +0200 Subject: iwlwifi: mvm: use short timeouts in P2P low latency if supported Those timeouts are used for AM-to-PSM transition. We already have those pairs defined for default and WOWLAN use cases. We expect that by using shorter threshold for low latency P2P, e.g. for Miracast video scenario, we might save a considerable amount of power. Signed-off-by: Johannes Berg Signed-off-by: Avri Altman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/iwl-fw-file.h | 2 ++ drivers/net/wireless/iwlwifi/mvm/constants.h | 3 +++ drivers/net/wireless/iwlwifi/mvm/power.c | 26 +++++++++++++++++++------- 3 files changed, 24 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 847d58b4e73a..08303db0000f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h @@ -307,6 +307,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement + * @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used */ @@ -332,6 +333,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, + IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, NUM_IWL_UCODE_TLV_CAPA #ifdef __CHECKER__ diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index aa9ae1d83508..5c21231e195d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h @@ -71,6 +71,9 @@ #define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) #define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC) #define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC) +#define IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */ +#define IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */ +#define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE 0 #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) #define IWL_MVM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\ diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 7c354feb9be2..bed9696ee410 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -377,8 +377,13 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); - if (!vif->bss_conf.ps || !mvmvif->pm_enabled || - (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p)) + if (!vif->bss_conf.ps || !mvmvif->pm_enabled) + return; + + if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p && + (!fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) || + !IWL_MVM_P2P_LOWLATENCY_PS_ENABLE)) return; cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); @@ -392,16 +397,23 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, host_awake); - if (host_awake) { + if (!host_awake) { cmd->rx_data_timeout = - cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT); + cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); cmd->tx_data_timeout = - cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT); + cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); + } else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p && + fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) { + cmd->tx_data_timeout = + cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT); + cmd->rx_data_timeout = + cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT); } else { cmd->rx_data_timeout = - cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); + cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT); cmd->tx_data_timeout = - cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); + cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT); } if (iwl_mvm_power_allow_uapsd(mvm, vif)) -- cgit v1.2.3 From c84af35de612fb45db6b5c5968b575813f5daa3b Mon Sep 17 00:00:00 2001 From: Assaf Krauss Date: Wed, 12 Aug 2015 17:52:12 +0300 Subject: iwlwifi: mvm: Allow setting ctrl-chnl-position in FTM responder This patch enables the debugfs user to configure an FTM responder with the appropriate control channel position. Signed-off-by: Assaf Krauss Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 398bef6f4f61..7904b41a04c6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c @@ -715,11 +715,30 @@ static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif, goto out; } - data = iwl_dbgfs_is_match("ctrl_ch_position=", buf); + data = iwl_dbgfs_is_match("center_freq=", buf); if (data) { + struct iwl_tof_responder_config_cmd *cmd = + &mvm->tof_data.responder_cfg; + ret = kstrtou32(data, 10, &value); - if (ret == 0) - mvm->tof_data.responder_cfg.ctrl_ch_position = value; + if (ret == 0 && value) { + enum ieee80211_band band = (cmd->channel_num <= 14) ? + IEEE80211_BAND_2GHZ : + IEEE80211_BAND_5GHZ; + struct ieee80211_channel chn = { + .band = band, + .center_freq = ieee80211_channel_to_frequency( + cmd->channel_num, band), + }; + struct cfg80211_chan_def chandef = { + .chan = &chn, + .center_freq1 = + ieee80211_channel_to_frequency(value, + band), + }; + + cmd->ctrl_ch_position = iwl_mvm_get_ctrl_pos(&chandef); + } goto out; } -- cgit v1.2.3 From 5888a40c50b181bab6737167cfc1bf653945e2a1 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 6 Oct 2015 09:54:57 +0300 Subject: iwlwifi: mvm: let any command flag be passed to iwl_mvm_flushtx_path() Instead of only allowing the caller to decide whether the CMD_ASYNC flag is set, let it pass the entire flags bitmask. This allows more flexibility and will be needed when we call this function in the suspend flow (where other flags are needed). Signed-off-by: Luca Coelho Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/debugfs.c | 2 +- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 4 ++-- drivers/net/wireless/iwlwifi/mvm/mvm.h | 2 +- drivers/net/wireless/iwlwifi/mvm/sta.c | 4 ++-- drivers/net/wireless/iwlwifi/mvm/time-event.c | 2 +- drivers/net/wireless/iwlwifi/mvm/tx.c | 4 +--- 6 files changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 9b4fbb8b483a..05928fb4021d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c @@ -85,7 +85,7 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk); mutex_lock(&mvm->mutex); - ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, true) ? : count; + ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, 0) ? : count; mutex_unlock(&mvm->mutex); return ret; diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index aaffb54e8f78..adfcce48d863 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1781,7 +1781,7 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, * Flush them here. */ mutex_lock(&mvm->mutex); - iwl_mvm_flush_tx_path(mvm, tfd_msk, true); + iwl_mvm_flush_tx_path(mvm, tfd_msk, 0); mutex_unlock(&mvm->mutex); /* @@ -3924,7 +3924,7 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, } if (drop) { - if (iwl_mvm_flush_tx_path(mvm, msk, true)) + if (iwl_mvm_flush_tx_path(mvm, msk, 0)) IWL_ERR(mvm, "flush request fail\n"); mutex_unlock(&mvm->mutex); } else { diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 0d3aff1b4bad..4485bdb56b34 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h @@ -1031,7 +1031,7 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status); #else static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; } #endif -int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync); +int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags); void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm); static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info, diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index a9a3eb6a1f8a..04d0cb3b69a1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -501,7 +501,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, if (ret) return ret; /* flush its queues here since we are freeing mvm_sta */ - ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true); + ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, 0); if (ret) return ret; ret = iwl_trans_wait_tx_queue_empty(mvm->trans, @@ -1155,7 +1155,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (old_state >= IWL_AGG_ON) { iwl_mvm_drain_sta(mvm, mvmsta, true); - if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true)) + if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), 0)) IWL_ERR(mvm, "Couldn't flush the AGG queue\n"); iwl_trans_wait_tx_queue_empty(mvm->trans, mvmsta->tfd_queue_msk); diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index dbd7d544575d..7530eb23035d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c @@ -129,7 +129,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) * issue as it will have to complete before the next command is * executed, and a new time event means a new command. */ - iwl_mvm_flush_tx_path(mvm, queues, false); + iwl_mvm_flush_tx_path(mvm, queues, CMD_ASYNC); } static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index ff8b9bdef7e8..c652a66be803 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -1099,7 +1099,7 @@ out: * 2) flush the Tx path * 3) wait for the transport queues to be empty */ -int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync) +int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags) { int ret; struct iwl_tx_path_flush_cmd flush_cmd = { @@ -1107,8 +1107,6 @@ int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync) .flush_ctl = cpu_to_le16(DUMP_TX_FIFO_FLUSH), }; - u32 flags = sync ? 0 : CMD_ASYNC; - ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags, sizeof(flush_cmd), &flush_cmd); if (ret) -- cgit v1.2.3 From cd55ccea5978d7e87852be3ea5daf89c95b7e78a Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Wed, 19 Aug 2015 12:46:12 +0300 Subject: iwlwifi: mvm: Add support for two scheduled scan plans Add support for two scan plans for scheduled scan. The first plan will run for a limited number of iterations, then the second plan will run infinitely. Signed-off-by: Avraham Stern Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | 5 +- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 8 ++ drivers/net/wireless/iwlwifi/mvm/scan.c | 116 ++++++++++++++++--------- 3 files changed, 87 insertions(+), 42 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 660cc1c93e19..3a657e4b60ac 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h @@ -101,6 +101,7 @@ struct iwl_ssid_ie { #define IWL_FULL_SCAN_MULTIPLIER 5 #define IWL_FAST_SCHED_SCAN_ITERATIONS 3 +#define IWL_MAX_SCHED_SCAN_PLANS 2 enum scan_framework_client { SCAN_CLIENT_SCHED_SCAN = BIT(0), @@ -359,7 +360,7 @@ struct iwl_scan_req_lmac { /* SCAN_REQ_PERIODIC_PARAMS_API_S */ __le32 iter_num; __le32 delay; - struct iwl_scan_schedule_lmac schedule[2]; + struct iwl_scan_schedule_lmac schedule[IWL_MAX_SCHED_SCAN_PLANS]; struct iwl_scan_channel_opt channel_opt[2]; u8 data[]; } __packed; @@ -582,7 +583,7 @@ struct iwl_scan_umac_schedule { */ struct iwl_scan_req_umac_tail { /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */ - struct iwl_scan_umac_schedule schedule[2]; + struct iwl_scan_umac_schedule schedule[IWL_MAX_SCHED_SCAN_PLANS]; __le16 delay; __le16 reserved; /* SCAN_PROBE_PARAMS_API_S_VER_1 */ diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index adfcce48d863..5ce29ff36ed1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -572,6 +572,14 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) /* we create the 802.11 header and zero length SSID IE. */ hw->wiphy->max_sched_scan_ie_len = SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; + hw->wiphy->max_sched_scan_plans = IWL_MAX_SCHED_SCAN_PLANS; + hw->wiphy->max_sched_scan_plan_interval = U16_MAX; + + /* + * the firmware uses u8 for num of iterations, but 0xff is saved for + * infinite loop, so the maximum number of iterations is actually 254. + */ + hw->wiphy->max_sched_scan_plan_iterations = 254; hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | NL80211_FEATURE_LOW_PRIORITY_SCAN | diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index cee4f267ca66..ed15b50dced7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -131,7 +131,6 @@ struct iwl_mvm_scan_params { int n_ssids; struct cfg80211_ssid *ssids; struct ieee80211_channel **channels; - u16 interval; /* interval between scans (in secs) */ u32 flags; u8 *mac_addr; u8 *mac_addr_mask; @@ -140,7 +139,8 @@ struct iwl_mvm_scan_params { int n_match_sets; struct iwl_scan_probe_req preq; struct cfg80211_match_set *match_sets; - u8 iterations[2]; + int n_scan_plans; + struct cfg80211_sched_scan_plan *scan_plans; }; static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm) @@ -737,8 +737,7 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids, } static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - int n_iterations) + struct ieee80211_vif *vif) { const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa; @@ -753,11 +752,6 @@ static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, vif->type != NL80211_IFTYPE_P2P_DEVICE); } -static int iwl_mvm_scan_total_iterations(struct iwl_mvm_scan_params *params) -{ - return params->iterations[0] + params->iterations[1]; -} - static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, struct iwl_mvm_scan_params *params) { @@ -796,12 +790,15 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) * mvm->fw->ucode_capa.n_scan_channels); u32 ssid_bitmap = 0; - int n_iterations = iwl_mvm_scan_total_iterations(params); + int i; lockdep_assert_held(&mvm->mutex); memset(cmd, 0, ksize(cmd)); + if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) + return -EINVAL; + iwl_mvm_scan_lmac_dwell(mvm, cmd, params); cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm); @@ -821,14 +818,33 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, /* this API uses bits 1-20 instead of 0-19 */ ssid_bitmap <<= 1; - cmd->schedule[0].delay = cpu_to_le16(params->interval); - cmd->schedule[0].iterations = params->iterations[0]; - cmd->schedule[0].full_scan_mul = 1; - cmd->schedule[1].delay = cpu_to_le16(params->interval); - cmd->schedule[1].iterations = params->iterations[1]; - cmd->schedule[1].full_scan_mul = 1; + for (i = 0; i < params->n_scan_plans; i++) { + struct wiphy *wiphy = mvm->hw->wiphy; + struct cfg80211_sched_scan_plan *scan_plan = + ¶ms->scan_plans[i]; + + if (WARN_ON(scan_plan->iterations > + wiphy->max_sched_scan_plan_iterations || + scan_plan->interval > + wiphy->max_sched_scan_plan_interval)) + return -EINVAL; + + cmd->schedule[i].delay = + cpu_to_le16(scan_plan->interval); + cmd->schedule[i].iterations = scan_plan->iterations; + cmd->schedule[i].full_scan_mul = 1; + } + + /* + * If the number of iterations of the last scan plan is set to + * zero, it should run infinitely. However, this is not always the case. + * For example, when regular scan is requested the driver sets one scan + * plan with one iteration. + */ + if (!cmd->schedule[i - 1].iterations) + cmd->schedule[i - 1].iterations = 0xff; - if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) { + if (iwl_mvm_scan_use_ebs(mvm, vif)) { cmd->channel_opt[0].flags = cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | @@ -968,6 +984,12 @@ static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status) return -ENOENT; } +static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params) +{ + return params->n_scan_plans == 1 && + params->scan_plans[0].iterations == 1; +} + static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, struct iwl_scan_req_umac *cmd, struct iwl_mvm_scan_params *params) @@ -980,7 +1002,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, cmd->scan_priority = iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); - if (iwl_mvm_scan_total_iterations(params) == 1) + if (iwl_mvm_is_regular_scan(params)) cmd->ooc_priority = iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); else @@ -1027,7 +1049,7 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, else flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH; - if (iwl_mvm_scan_total_iterations(params) > 1) + if (!iwl_mvm_is_regular_scan(params)) flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC; #ifdef CONFIG_IWLWIFI_DEBUGFS @@ -1045,12 +1067,14 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data + sizeof(struct iwl_scan_channel_cfg_umac) * mvm->fw->ucode_capa.n_scan_channels; - int uid; + int uid, i; u32 ssid_bitmap = 0; - int n_iterations = iwl_mvm_scan_total_iterations(params); lockdep_assert_held(&mvm->mutex); + if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) + return -EINVAL; + uid = iwl_mvm_scan_uid_by_status(mvm, 0); if (uid < 0) return uid; @@ -1067,7 +1091,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (type == IWL_MVM_SCAN_SCHED) cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); - if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) + if (iwl_mvm_scan_use_ebs(mvm, vif)) cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD; @@ -1079,12 +1103,30 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, iwl_mvm_umac_scan_cfg_channels(mvm, params->channels, params->n_channels, ssid_bitmap, cmd); - /* With UMAC we use only one schedule for now, so use the sum - * of the iterations (with a a maximum of 255). + for (i = 0; i < params->n_scan_plans; i++) { + struct wiphy *wiphy = mvm->hw->wiphy; + struct cfg80211_sched_scan_plan *scan_plan = + ¶ms->scan_plans[i]; + + if (WARN_ON(scan_plan->iterations > + wiphy->max_sched_scan_plan_iterations || + scan_plan->interval > + wiphy->max_sched_scan_plan_interval)) + return -EINVAL; + + sec_part->schedule[i].iter_count = scan_plan->iterations; + sec_part->schedule[i].interval = + cpu_to_le16(scan_plan->interval); + } + + /* + * If the number of iterations of the last scan plan is set to + * zero, it should run infinitely. However, this is not always the case. + * For example, when regular scan is requested the driver sets one scan + * plan with one iteration. */ - sec_part->schedule[0].iter_count = - (n_iterations > 255) ? 255 : n_iterations; - sec_part->schedule[0].interval = cpu_to_le16(params->interval); + if (!sec_part->schedule[i - 1].iter_count) + sec_part->schedule[i - 1].iter_count = 0xff; sec_part->delay = cpu_to_le16(params->delay); sec_part->preq = params->preq; @@ -1150,6 +1192,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, }; struct iwl_mvm_scan_params params = {}; int ret; + struct cfg80211_sched_scan_plan scan_plan = { .iterations = 1 }; lockdep_assert_held(&mvm->mutex); @@ -1175,7 +1218,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, params.flags = req->flags; params.n_channels = req->n_channels; params.delay = 0; - params.interval = 0; params.ssids = req->ssids; params.channels = req->channels; params.mac_addr = req->mac_addr; @@ -1185,8 +1227,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, params.n_match_sets = 0; params.match_sets = NULL; - params.iterations[0] = 1; - params.iterations[1] = 0; + params.scan_plans = &scan_plan; + params.n_scan_plans = 1; params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); @@ -1265,20 +1307,14 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, params.pass_all = iwl_mvm_scan_pass_all(mvm, req); params.n_match_sets = req->n_match_sets; params.match_sets = req->match_sets; + if (!req->n_scan_plans) + return -EINVAL; - params.iterations[0] = 0; - params.iterations[1] = 0xff; + params.n_scan_plans = req->n_scan_plans; + params.scan_plans = req->scan_plans; params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); - if (req->scan_plans[0].interval > U16_MAX) { - IWL_DEBUG_SCAN(mvm, - "interval value is > 16-bits, set to max possible\n"); - params.interval = U16_MAX; - } else { - params.interval = req->scan_plans[0].interval; - } - /* In theory, LMAC scans can handle a 32-bit delay, but since * waiting for over 18 hours to start the scan is a bit silly * and to keep it aligned with UMAC scans (which only support -- cgit v1.2.3 From 053225de121a950b94a1989802c22895797ffbfc Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 10 Sep 2015 15:00:22 +0300 Subject: iwlwifi: avoid read/write operations if the bus is dead Recovery takes too much time if the bus is dead (each timeout is 2000ms, etc.). Explicitly skip fw dump in this case, as it will result in garbage data (and might take signifcant time) Signed-off-by: Eliad Peller Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/iwl-trans.h | 2 ++ drivers/net/wireless/iwlwifi/mvm/mac80211.c | 6 ++++++ 2 files changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index bb51b6f8002c..6f76525088f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -409,6 +409,7 @@ enum iwl_d3_status { * @STATUS_TRANS_GOING_IDLE: shutting down the trans, only special commands * are sent * @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent + * @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation */ enum iwl_trans_status { STATUS_SYNC_HCMD_ACTIVE, @@ -419,6 +420,7 @@ enum iwl_trans_status { STATUS_FW_ERROR, STATUS_TRANS_GOING_IDLE, STATUS_TRANS_IDLE, + STATUS_TRANS_DEAD, }; /** diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 5ce29ff36ed1..8e69ab22b0e0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1137,6 +1137,12 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) lockdep_assert_held(&mvm->mutex); + /* there's no point in fw dump if the bus is dead */ + if (test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) { + IWL_ERR(mvm, "Skip fw error dump since bus is dead\n"); + return; + } + if (mvm->fw_dump_trig && mvm->fw_dump_trig->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY) monitor_dump_only = true; -- cgit v1.2.3 From effd19298c7767457772d489c88f1b7ffa6e7bd9 Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Tue, 30 Jun 2015 12:08:28 +0300 Subject: iwlwifi: mvm: Implement per vif frame registration API Implement config_iface_filter() driver op. Currently support only probe request registration for p2p client vifs, by setting MAC_FILTER_IN_PROBE_REQUEST flag in MAC_CONTEXT_CMD. This is needed since WFDS spec and certification require a P2P client to be discoverable on its operating channel. Signed-off-by: Andrei Otcheretianski Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | 3 +++ drivers/net/wireless/iwlwifi/mvm/mac80211.c | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 9d36ba7295a5..ad7ad720d2e7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -843,6 +843,9 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval); ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid); + if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p) + cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); + return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); } diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 8e69ab22b0e0..1d21e380ca11 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1996,6 +1996,27 @@ out: *total_flags = 0; } +static void iwl_mvm_config_iface_filter(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + unsigned int filter_flags, + unsigned int changed_flags) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + + /* We support only filter for probe requests */ + if (!(changed_flags & FIF_PROBE_REQ)) + return; + + /* Supported only for p2p client interfaces */ + if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc || + !vif->p2p) + return; + + mutex_lock(&mvm->mutex); + iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); + mutex_unlock(&mvm->mutex); +} + #ifdef CONFIG_IWLWIFI_BCAST_FILTERING struct iwl_bcast_iter_data { struct iwl_mvm *mvm; @@ -4175,6 +4196,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { .config = iwl_mvm_mac_config, .prepare_multicast = iwl_mvm_prepare_multicast, .configure_filter = iwl_mvm_configure_filter, + .config_iface_filter = iwl_mvm_config_iface_filter, .bss_info_changed = iwl_mvm_bss_info_changed, .hw_scan = iwl_mvm_mac_hw_scan, .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan, -- cgit v1.2.3 From 46eebec9794e47ebad0352285db50a10de595bb5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 11 Sep 2015 12:09:22 +0200 Subject: iwlwifi: mvm: clean up some whitespace in scan code Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/scan.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index ed15b50dced7..a8e11ccb8dc1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -474,7 +474,7 @@ iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, int ret; if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES)) - return -EIO; + return -EIO; if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL) blacklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN; @@ -842,7 +842,7 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, * plan with one iteration. */ if (!cmd->schedule[i - 1].iterations) - cmd->schedule[i - 1].iterations = 0xff; + cmd->schedule[i - 1].iterations = 0xff; if (iwl_mvm_scan_use_ebs(mvm, vif)) { cmd->channel_opt[0].flags = @@ -908,7 +908,6 @@ static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm) int iwl_mvm_config_scan(struct iwl_mvm *mvm) { - struct iwl_scan_config *scan_config; struct ieee80211_supported_band *band; int num_channels = -- cgit v1.2.3 From c8f423159e3e53d30e5b36a455797ee2072b09d0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 11 Sep 2015 12:07:21 +0200 Subject: iwlwifi: mvm: remove pointless scan plan checks As cfg80211 already enforces these limits, there's little point in having them again here in our code. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/scan.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index a8e11ccb8dc1..0e9d28c23023 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -819,16 +819,9 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ssid_bitmap <<= 1; for (i = 0; i < params->n_scan_plans; i++) { - struct wiphy *wiphy = mvm->hw->wiphy; struct cfg80211_sched_scan_plan *scan_plan = ¶ms->scan_plans[i]; - if (WARN_ON(scan_plan->iterations > - wiphy->max_sched_scan_plan_iterations || - scan_plan->interval > - wiphy->max_sched_scan_plan_interval)) - return -EINVAL; - cmd->schedule[i].delay = cpu_to_le16(scan_plan->interval); cmd->schedule[i].iterations = scan_plan->iterations; @@ -1103,16 +1096,9 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, params->n_channels, ssid_bitmap, cmd); for (i = 0; i < params->n_scan_plans; i++) { - struct wiphy *wiphy = mvm->hw->wiphy; struct cfg80211_sched_scan_plan *scan_plan = ¶ms->scan_plans[i]; - if (WARN_ON(scan_plan->iterations > - wiphy->max_sched_scan_plan_iterations || - scan_plan->interval > - wiphy->max_sched_scan_plan_interval)) - return -EINVAL; - sec_part->schedule[i].iter_count = scan_plan->iterations; sec_part->schedule[i].interval = cpu_to_le16(scan_plan->interval); -- cgit v1.2.3 From 78ba82f777f3ab41f10afa3694c9c7633bf595d4 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 15 Oct 2015 10:58:48 +0300 Subject: iwlwifi: mvm: take scan ref only on success In some cases, scan reference was taken, but wasn't released even though scan command wasn't actually issued. Change the current code to simply take the reference only on success. Signed-off-by: Eliad Peller Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/scan.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 0e9d28c23023..d6e0c1b5c20c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c @@ -1190,8 +1190,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (ret) return ret; - iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); - /* we should have failed registration if scan_cmd was NULL */ if (WARN_ON(!mvm->scan_cmd)) return -ENOMEM; @@ -1232,21 +1230,20 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return ret; ret = iwl_mvm_send_cmd(mvm, &hcmd); - if (!ret) { - IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); - mvm->scan_status |= IWL_MVM_SCAN_REGULAR; - } else { + if (ret) { /* If the scan failed, it usually means that the FW was unable * to allocate the time events. Warn on it, but maybe we * should try to send the command again with different params. */ IWL_ERR(mvm, "Scan failed! ret %d\n", ret); + return ret; } - if (ret) - iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); + IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); + mvm->scan_status |= IWL_MVM_SCAN_REGULAR; + iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); - return ret; + return 0; } int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, -- cgit v1.2.3 From 06ecdba319e2b389c94c7b6a9c936d09ec188359 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 12 Oct 2015 14:47:11 +0300 Subject: iwlwifi: mvm: disable TDLS ac queues correctly The iwl_mvm_disable_queue function requires the TID to be set to IWL_MAX_TID_COUNT when disabling an AC queue. Call it correctly for TDLS scenarios. Fixes: 4ecafae9e568 ("iwlwifi: mvm: support using multiple ACs on single HW queue") Signed-off-by: Arik Nemtsov Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/sta.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 04d0cb3b69a1..300a249486e4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c @@ -255,7 +255,7 @@ static void iwl_mvm_tdls_sta_deinit(struct iwl_mvm *mvm, /* disable the TDLS STA-specific queues */ sta_msk = mvmsta->tfd_queue_msk; for_each_set_bit(i, &sta_msk, sizeof(sta_msk) * BITS_PER_BYTE) - iwl_mvm_disable_txq(mvm, i, i, 0, 0); + iwl_mvm_disable_txq(mvm, i, i, IWL_MAX_TID_COUNT, 0); } int iwl_mvm_add_sta(struct iwl_mvm *mvm, @@ -474,7 +474,8 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk) unsigned long i, msk = mvm->tfd_drained[sta_id]; for_each_set_bit(i, &msk, sizeof(msk) * BITS_PER_BYTE) - iwl_mvm_disable_txq(mvm, i, i, 0, 0); + iwl_mvm_disable_txq(mvm, i, i, + IWL_MAX_TID_COUNT, 0); mvm->tfd_drained[sta_id] = 0; IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n", -- cgit v1.2.3 From 2edb7a3372c76c9379d0fc00e4274ea8f018248a Mon Sep 17 00:00:00 2001 From: Moshe Harel Date: Thu, 10 Sep 2015 15:29:09 +0300 Subject: iwlwifi: nvm: free old section data when reading nvm file When reading external NVM file, if a section exists both in OTP and in the external file, the memory that was allocated at OTP reading is not freed. This is possible only on systems that have an external NVM file which is typically the case on embedded systems. Signed-off-by: Moshe Harel Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/nvm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 4e4a680f274a..2ee0f6fe56a1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c @@ -483,6 +483,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) ret = -ENOMEM; break; } + kfree(mvm->nvm_sections[section_id].data); mvm->nvm_sections[section_id].data = temp; mvm->nvm_sections[section_id].length = section_size; -- cgit v1.2.3 From f9bf45e08ef36b6726a5744f0029325e81b3248a Mon Sep 17 00:00:00 2001 From: Sunil Goutham Date: Fri, 23 Oct 2015 17:14:07 -0700 Subject: net: thunderx: Remove PF soft reset. In some silicon revisions, the soft reset clobbers PCI config space, so quit doing the reset. Signed-off-by: Sunil Goutham Signed-off-by: David Daney Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/nic_main.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c index b3a5947a2cc0..d6e3219ddeb3 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_main.c +++ b/drivers/net/ethernet/cavium/thunder/nic_main.c @@ -305,9 +305,6 @@ static void nic_init_hw(struct nicpf *nic) { int i; - /* Reset NIC, in case the driver is repeatedly inserted and removed */ - nic_reg_write(nic, NIC_PF_SOFT_RESET, 1); - /* Enable NIC HW block */ nic_reg_write(nic, NIC_PF_CFG, 0x3); -- cgit v1.2.3 From 4e85777ff071b51f500b130b6d036922af32be25 Mon Sep 17 00:00:00 2001 From: Sunil Goutham Date: Fri, 23 Oct 2015 17:14:08 -0700 Subject: net: thunderx: Fix incorrect subsystem devid of VF on pass2 silicon Signed-off-by: Sunil Goutham Signed-off-by: David Daney Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/nicvf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index b63e579aeb12..a9377727c11c 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -29,7 +29,7 @@ static const struct pci_device_id nicvf_id_table[] = { { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_NIC_VF, - PCI_VENDOR_ID_CAVIUM, 0xA11E) }, + PCI_VENDOR_ID_CAVIUM, 0xA134) }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_PASS1_NIC_VF, PCI_VENDOR_ID_CAVIUM, 0xA11E) }, -- cgit v1.2.3 From 88ed237720bd618240439714a57fb69ea96428e7 Mon Sep 17 00:00:00 2001 From: David Daney Date: Fri, 23 Oct 2015 17:14:09 -0700 Subject: net: thunderx: Rewrite silicon revision tests. The test for pass-1 silicon was incorrect, it should be for all revisions less than 8. Also the revision is already present in the pci_dev, so there is no need to read and keep a private copy. Remove rev_id and code to read it from struct nicpf. Create new static inline function pass1_silicon() to be used to testing the silicon version. Use pass1_silicon() for revision checks, this will be more widely used in follow on patches. Signed-off-by: David Daney Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/nic_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c index d6e3219ddeb3..52e1acb69562 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_main.c +++ b/drivers/net/ethernet/cavium/thunder/nic_main.c @@ -22,7 +22,6 @@ struct nicpf { struct pci_dev *pdev; - u8 rev_id; u8 node; unsigned int flags; u8 num_vf_en; /* No of VF enabled */ @@ -54,6 +53,11 @@ struct nicpf { bool irq_allocated[NIC_PF_MSIX_VECTORS]; }; +static inline bool pass1_silicon(struct nicpf *nic) +{ + return nic->pdev->revision < 8; +} + /* Supported devices */ static const struct pci_device_id nic_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_NIC_PF) }, @@ -117,7 +121,7 @@ static void nic_send_msg_to_vf(struct nicpf *nic, int vf, union nic_mbx *mbx) * when PF writes to MBOX(1), in next revisions when * PF writes to MBOX(0) */ - if (nic->rev_id == 0) { + if (pass1_silicon(nic)) { /* see the comment for nic_reg_write()/nic_reg_read() * functions above */ @@ -998,8 +1002,6 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_release_regions; } - pci_read_config_byte(pdev, PCI_REVISION_ID, &nic->rev_id); - nic->node = nic_get_node_id(pdev); nic_set_lmac_vf_mapping(nic); -- cgit v1.2.3 From 34411b68b132e403ddf395419e986475a9993d9b Mon Sep 17 00:00:00 2001 From: Thanneeru Srinivasulu Date: Fri, 23 Oct 2015 17:14:10 -0700 Subject: net: thunderx: Incorporate pass2 silicon CPI index configuration changes Add support for ThunderX pass2 CPI and MPI configuration changes. MPI_ALG is not enabled i.e MCAM parsing is disabled. Signed-off-by: Thanneeru Srinivasulu Signed-off-by: Sunil Goutham Signed-off-by: David Daney Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/nic_main.c | 29 ++++++++++++++++++++------ drivers/net/ethernet/cavium/thunder/nic_reg.h | 4 ++++ 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c index 52e1acb69562..c561fdcb79a7 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_main.c +++ b/drivers/net/ethernet/cavium/thunder/nic_main.c @@ -43,6 +43,7 @@ struct nicpf { u8 duplex[MAX_LMAC]; u32 speed[MAX_LMAC]; u16 cpi_base[MAX_NUM_VFS_SUPPORTED]; + u16 rssi_base[MAX_NUM_VFS_SUPPORTED]; u16 rss_ind_tbl_size; bool mbx_lock[MAX_NUM_VFS_SUPPORTED]; @@ -396,8 +397,18 @@ static void nic_config_cpi(struct nicpf *nic, struct cpi_cfg_msg *cfg) padd = cpi % 8; /* 3 bits CS out of 6bits DSCP */ /* Leave RSS_SIZE as '0' to disable RSS */ - nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3), - (vnic << 24) | (padd << 16) | (rssi_base + rssi)); + if (pass1_silicon(nic)) { + nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3), + (vnic << 24) | (padd << 16) | + (rssi_base + rssi)); + } else { + /* Set MPI_ALG to '0' to disable MCAM parsing */ + nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3), + (padd << 16)); + /* MPI index is same as CPI if MPI_ALG is not enabled */ + nic_reg_write(nic, NIC_PF_MPI_0_2047_CFG | (cpi << 3), + (vnic << 24) | (rssi_base + rssi)); + } if ((rssi + 1) >= cfg->rq_cnt) continue; @@ -410,6 +421,7 @@ static void nic_config_cpi(struct nicpf *nic, struct cpi_cfg_msg *cfg) rssi = ((cpi - cpi_base) & 0x38) >> 3; } nic->cpi_base[cfg->vf_id] = cpi_base; + nic->rssi_base[cfg->vf_id] = rssi_base; } /* Responsds to VF with its RSS indirection table size */ @@ -435,10 +447,9 @@ static void nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg) { u8 qset, idx = 0; u64 cpi_cfg, cpi_base, rssi_base, rssi; + u64 idx_addr; - cpi_base = nic->cpi_base[cfg->vf_id]; - cpi_cfg = nic_reg_read(nic, NIC_PF_CPI_0_2047_CFG | (cpi_base << 3)); - rssi_base = (cpi_cfg & 0x0FFF) + cfg->tbl_offset; + rssi_base = nic->rssi_base[cfg->vf_id] + cfg->tbl_offset; rssi = rssi_base; qset = cfg->vf_id; @@ -455,9 +466,15 @@ static void nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg) idx++; } + cpi_base = nic->cpi_base[cfg->vf_id]; + if (pass1_silicon(nic)) + idx_addr = NIC_PF_CPI_0_2047_CFG; + else + idx_addr = NIC_PF_MPI_0_2047_CFG; + cpi_cfg = nic_reg_read(nic, idx_addr | (cpi_base << 3)); cpi_cfg &= ~(0xFULL << 20); cpi_cfg |= (cfg->hash_bits << 20); - nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi_base << 3), cpi_cfg); + nic_reg_write(nic, idx_addr | (cpi_base << 3), cpi_cfg); } /* 4 level transmit side scheduler configutation diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h index 58197bb2f805..dd536be20193 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_reg.h +++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h @@ -85,7 +85,11 @@ #define NIC_PF_ECC3_DBE_INT_W1S (0x2708) #define NIC_PF_ECC3_DBE_ENA_W1C (0x2710) #define NIC_PF_ECC3_DBE_ENA_W1S (0x2718) +#define NIC_PF_MCAM_0_191_ENA (0x100000) +#define NIC_PF_MCAM_0_191_M_0_5_DATA (0x110000) +#define NIC_PF_MCAM_CTRL (0x120000) #define NIC_PF_CPI_0_2047_CFG (0x200000) +#define NIC_PF_MPI_0_2047_CFG (0x210000) #define NIC_PF_RSSI_0_4097_RQ (0x220000) #define NIC_PF_LMAC_0_7_CFG (0x240000) #define NIC_PF_LMAC_0_7_SW_XOFF (0x242000) -- cgit v1.2.3 From 9b0cdefa4cd5dca85967f66da8ab376c0321b845 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 22 Oct 2015 18:37:30 +0100 Subject: net: mvneta: add ethtool statistics Add support for the ethtool statistic interface, returning the full set of statistics which both Armada 370, 38x and Armada XP can support. Tested-by: Andrew Lunn Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 108 ++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index dd6fe942acf9..05816acc79a1 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -278,6 +278,50 @@ #define MVNETA_RX_BUF_SIZE(pkt_size) ((pkt_size) + NET_SKB_PAD) +struct mvneta_statistic { + unsigned short offset; + unsigned short type; + const char name[ETH_GSTRING_LEN]; +}; + +#define T_REG_32 32 +#define T_REG_64 64 + +static const struct mvneta_statistic mvneta_statistics[] = { + { 0x3000, T_REG_64, "good_octets_received", }, + { 0x3010, T_REG_32, "good_frames_received", }, + { 0x3008, T_REG_32, "bad_octets_received", }, + { 0x3014, T_REG_32, "bad_frames_received", }, + { 0x3018, T_REG_32, "broadcast_frames_received", }, + { 0x301c, T_REG_32, "multicast_frames_received", }, + { 0x3050, T_REG_32, "unrec_mac_control_received", }, + { 0x3058, T_REG_32, "good_fc_received", }, + { 0x305c, T_REG_32, "bad_fc_received", }, + { 0x3060, T_REG_32, "undersize_received", }, + { 0x3064, T_REG_32, "fragments_received", }, + { 0x3068, T_REG_32, "oversize_received", }, + { 0x306c, T_REG_32, "jabber_received", }, + { 0x3070, T_REG_32, "mac_receive_error", }, + { 0x3074, T_REG_32, "bad_crc_event", }, + { 0x3078, T_REG_32, "collision", }, + { 0x307c, T_REG_32, "late_collision", }, + { 0x2484, T_REG_32, "rx_discard", }, + { 0x2488, T_REG_32, "rx_overrun", }, + { 0x3020, T_REG_32, "frames_64_octets", }, + { 0x3024, T_REG_32, "frames_65_to_127_octets", }, + { 0x3028, T_REG_32, "frames_128_to_255_octets", }, + { 0x302c, T_REG_32, "frames_256_to_511_octets", }, + { 0x3030, T_REG_32, "frames_512_to_1023_octets", }, + { 0x3034, T_REG_32, "frames_1024_to_max_octets", }, + { 0x3038, T_REG_64, "good_octets_sent", }, + { 0x3040, T_REG_32, "good_frames_sent", }, + { 0x3044, T_REG_32, "excessive_collision", }, + { 0x3048, T_REG_32, "multicast_frames_sent", }, + { 0x304c, T_REG_32, "broadcast_frames_sent", }, + { 0x3054, T_REG_32, "fc_sent", }, + { 0x300c, T_REG_32, "internal_mac_transmit_err", }, +}; + struct mvneta_pcpu_stats { struct u64_stats_sync syncp; u64 rx_packets; @@ -324,6 +368,8 @@ struct mvneta_port { unsigned int speed; unsigned int tx_csum_limit; int use_inband_status:1; + + u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)]; }; /* The mvneta_tx_desc and mvneta_rx_desc structures describe the @@ -2982,6 +3028,65 @@ static int mvneta_ethtool_set_ringparam(struct net_device *dev, return 0; } +static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset, + u8 *data) +{ + if (sset == ETH_SS_STATS) { + int i; + + for (i = 0; i < ARRAY_SIZE(mvneta_statistics); i++) + memcpy(data + i * ETH_GSTRING_LEN, + mvneta_statistics[i].name, ETH_GSTRING_LEN); + } +} + +static void mvneta_ethtool_update_stats(struct mvneta_port *pp) +{ + const struct mvneta_statistic *s; + void __iomem *base = pp->base; + u32 high, low, val; + int i; + + for (i = 0, s = mvneta_statistics; + s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics); + s++, i++) { + val = 0; + + switch (s->type) { + case T_REG_32: + val = readl_relaxed(base + s->offset); + break; + case T_REG_64: + /* Docs say to read low 32-bit then high */ + low = readl_relaxed(base + s->offset); + high = readl_relaxed(base + s->offset + 4); + val = (u64)high << 32 | low; + break; + } + + pp->ethtool_stats[i] += val; + } +} + +static void mvneta_ethtool_get_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct mvneta_port *pp = netdev_priv(dev); + int i; + + mvneta_ethtool_update_stats(pp); + + for (i = 0; i < ARRAY_SIZE(mvneta_statistics); i++) + *data++ = pp->ethtool_stats[i]; +} + +static int mvneta_ethtool_get_sset_count(struct net_device *dev, int sset) +{ + if (sset == ETH_SS_STATS) + return ARRAY_SIZE(mvneta_statistics); + return -EOPNOTSUPP; +} + static const struct net_device_ops mvneta_netdev_ops = { .ndo_open = mvneta_open, .ndo_stop = mvneta_stop, @@ -3003,6 +3108,9 @@ const struct ethtool_ops mvneta_eth_tool_ops = { .get_drvinfo = mvneta_ethtool_get_drvinfo, .get_ringparam = mvneta_ethtool_get_ringparam, .set_ringparam = mvneta_ethtool_set_ringparam, + .get_strings = mvneta_ethtool_get_strings, + .get_ethtool_stats = mvneta_ethtool_get_stats, + .get_sset_count = mvneta_ethtool_get_sset_count, }; /* Initialize hw */ -- cgit v1.2.3 From e483911f9f16d508dd2652ac860977533b96e34e Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Thu, 22 Oct 2015 18:37:36 +0100 Subject: net: mvneta: Fix clearing of MIB statistics The existing function to clear the MIB statatistics was using the wrong address for the registers. Also, the counters would of been cleared when the interface was brought up, not during the probe. Fix both of these. Signed-off-by: Andrew Lunn Signed-off-by: Russell King Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 05816acc79a1..a47496a020d9 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -101,6 +101,8 @@ #define MVNETA_TXQ_CMD 0x2448 #define MVNETA_TXQ_DISABLE_SHIFT 8 #define MVNETA_TXQ_ENABLE_MASK 0x000000ff +#define MVNETA_RX_DISCARD_FRAME_COUNT 0x2484 +#define MVNETA_OVERRUN_FRAME_COUNT 0x2488 #define MVNETA_GMAC_CLOCK_DIVIDER 0x24f4 #define MVNETA_GMAC_1MS_CLOCK_ENABLE BIT(31) #define MVNETA_ACC_MODE 0x2500 @@ -192,7 +194,7 @@ #define MVNETA_GMAC_AN_FLOW_CTRL_EN BIT(11) #define MVNETA_GMAC_CONFIG_FULL_DUPLEX BIT(12) #define MVNETA_GMAC_AN_DUPLEX_EN BIT(13) -#define MVNETA_MIB_COUNTERS_BASE 0x3080 +#define MVNETA_MIB_COUNTERS_BASE 0x3000 #define MVNETA_MIB_LATE_COLLISION 0x7c #define MVNETA_DA_FILT_SPEC_MCAST 0x3400 #define MVNETA_DA_FILT_OTH_MCAST 0x3500 @@ -576,6 +578,8 @@ static void mvneta_mib_counters_clear(struct mvneta_port *pp) /* Perform dummy reads from MIB counters */ for (i = 0; i < MVNETA_MIB_LATE_COLLISION; i += 4) dummy = mvreg_read(pp, (MVNETA_MIB_COUNTERS_BASE + i)); + dummy = mvreg_read(pp, MVNETA_RX_DISCARD_FRAME_COUNT); + dummy = mvreg_read(pp, MVNETA_OVERRUN_FRAME_COUNT); } /* Get System Network Statistics */ @@ -804,7 +808,6 @@ static void mvneta_port_up(struct mvneta_port *pp) u32 q_map; /* Enable all initialized TXs. */ - mvneta_mib_counters_clear(pp); q_map = 0; for (queue = 0; queue < txq_number; queue++) { struct mvneta_tx_queue *txq = &pp->txqs[queue]; @@ -1081,6 +1084,8 @@ static void mvneta_defaults_set(struct mvneta_port *pp) mvreg_write(pp, MVNETA_INTR_ENABLE, (MVNETA_RXQ_INTR_ENABLE_ALL_MASK | MVNETA_TXQ_INTR_ENABLE_ALL_MASK)); + + mvneta_mib_counters_clear(pp); } /* Set max sizes for tx queues */ -- cgit v1.2.3 From 3ed770f60317a02a5a5e4a7345dc13d8819f56e8 Mon Sep 17 00:00:00 2001 From: Jon Ringle Date: Thu, 22 Oct 2015 15:09:04 -0400 Subject: net: encx24j600: Fix mask to update LED configuration This fixes the mask used to update the LED configuration so that it clears the necessary bits as well as setting the bits according to the mask. Also reverse the LED configuration to show the Link state + collisions in LEDA and the Link state + TX/RX events in LEDB. Signed-off-by: Jon Ringle Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/encx24j600.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c index e1329d9c2acc..bf08ce2baf8d 100644 --- a/drivers/net/ethernet/microchip/encx24j600.c +++ b/drivers/net/ethernet/microchip/encx24j600.c @@ -617,10 +617,10 @@ static int encx24j600_hw_init(struct encx24j600_priv *priv) (eidled & REVID_MASK) >> REVID_SHIFT); /* PHY Leds: link status, - * LEDA: Link + transmit/receive events - * LEDB: Link State + colision events + * LEDA: Link State + collision events + * LEDB: Link State + transmit/receive events */ - encx24j600_update_reg(priv, EIDLED, 0xbc00, 0xbc00); + encx24j600_update_reg(priv, EIDLED, 0xff00, 0xcb00); /* Loopback disabled */ encx24j600_write_reg(priv, MACON1, 0x9); -- cgit v1.2.3 From 5188f7e5a7175975f8b943a4b25e499c98a7b9d6 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Fri, 23 Oct 2015 11:41:58 +0300 Subject: gianfar: Remove duplicated argument to bitwise OR RQFCR_AND is duplicated. Add missing space as well. Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar_ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index 6bdc89179b72..a33e4a829601 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c @@ -676,14 +676,14 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) u32 fcr = 0x0, fpr = FPR_FILER_MASK; if (ethflow & RXH_L2DA) { - fcr = RQFCR_PID_DAH |RQFCR_CMP_NOMATCH | + fcr = RQFCR_PID_DAH | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); priv->cur_filer_idx = priv->cur_filer_idx - 1; - fcr = RQFCR_PID_DAL | RQFCR_AND | RQFCR_CMP_NOMATCH | + fcr = RQFCR_PID_DAL | RQFCR_CMP_NOMATCH | RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; -- cgit v1.2.3 From 15bf176db1fb00333af7050c0c699fc7b4e4a960 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Fri, 23 Oct 2015 11:41:59 +0300 Subject: gianfar: Don't enable the Filer w/o the Parser Under one unusual circumstance it's possible to wrongly set FILREN without enabling PRSDEP as well in the RCTRL register, against the hardware specifications. With the default config this does not happen because the default Rx offloads (Rx csum and Rx VLAN) properly enable PRSDEP. But if anyone disables all these offloads (via ethtool), we get a wrong configuration were the Rx flow classification and hashing, and other Filer based features (e.g. wake-on-filer interrupt) won't work. This patch fixes the issue. Also, account for Rx FCB insertion which happens every time PRSDEP is set. Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 710715fcb23d..939ed8fe6318 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -341,7 +341,7 @@ static void gfar_rx_offload_en(struct gfar_private *priv) if (priv->ndev->features & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX)) priv->uses_rxfcb = 1; - if (priv->hwts_rx_en) + if (priv->hwts_rx_en || priv->rx_filer_enable) priv->uses_rxfcb = 1; } @@ -351,7 +351,7 @@ static void gfar_mac_rx_config(struct gfar_private *priv) u32 rctrl = 0; if (priv->rx_filer_enable) { - rctrl |= RCTRL_FILREN; + rctrl |= RCTRL_FILREN | RCTRL_PRSDEP_INIT; /* Program the RIR0 reg with the required distribution */ if (priv->poll_mode == GFAR_SQ_POLLING) gfar_write(®s->rir0, DEFAULT_2RXQ_RIR0); -- cgit v1.2.3 From 1de65a5ea32de7b335ab505366d45cefadbbdf71 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Fri, 23 Oct 2015 11:42:00 +0300 Subject: gianfar: Fix Rx BSY error handling The Rx BSY error interrupt indicates that a frame was received and discarded due to lack of buffers, so it's a rx ring overflow condition and has nothing to do with with bad rx packets. Use the right counter. BSY conditions happen when the SoC is under performance stress. Doing *more* work in stress situations by trying to schedule NAPI is not a good idea as the stressed system becomes still more stressed. The Rx interrupt is already at work making sure the NAPI is scheduled. So calling gfar_receive() here does not help. This issue was present since day 1. Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 939ed8fe6318..ce38d266f931 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -3462,11 +3462,9 @@ static irqreturn_t gfar_error(int irq, void *grp_id) netif_dbg(priv, tx_err, dev, "Transmit Error\n"); } if (events & IEVENT_BSY) { - dev->stats.rx_errors++; + dev->stats.rx_over_errors++; atomic64_inc(&priv->extra_stats.rx_bsy); - gfar_receive(irq, grp_id); - netif_dbg(priv, rx_err, dev, "busy error (rstat: %x)\n", gfar_read(®s->rstat)); } -- cgit v1.2.3 From d1611c3aba11ffa281bdd027aace52f5a370b8c5 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 25 Oct 2015 22:27:57 -0400 Subject: bnxt_en: Fix compile warnings when CONFIG_INET is not set. bnxt_gro_skb() has unused variables when CONFIG_INET is not set. We really cannot support hardware GRO if CONFIG_INET is not set, so compile out bnxt_gro_skb() completely and define BNXT_FLAG_GRO to be 0 if CONFIG_INET is not set. This will effectively always disable hardware GRO if CONFIG_INET is not set. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 9e36f83e68f0..6c2e0c622831 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -852,6 +852,7 @@ static inline struct sk_buff *bnxt_gro_skb(struct bnxt_tpa_info *tpa_info, struct rx_tpa_end_cmp_ext *tpa_end1, struct sk_buff *skb) { +#ifdef CONFIG_INET struct tcphdr *th; int payload_off, tcp_opt_len = 0; int len, nw_off; @@ -866,7 +867,6 @@ static inline struct sk_buff *bnxt_gro_skb(struct bnxt_tpa_info *tpa_info, if (TPA_END_GRO_TS(tpa_end)) tcp_opt_len = 12; -#ifdef CONFIG_INET if (tpa_info->gso_type == SKB_GSO_TCPV4) { struct iphdr *iph; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 5ee3cc28a421..4f2267ca482d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -855,7 +855,12 @@ struct bnxt { #define BNXT_FLAG_DCB_ENABLED 0x1 #define BNXT_FLAG_VF 0x2 #define BNXT_FLAG_LRO 0x4 +#ifdef CONFIG_INET #define BNXT_FLAG_GRO 0x8 +#else + /* Cannot support hardware GRO if CONFIG_INET is not set */ + #define BNXT_FLAG_GRO 0x0 +#endif #define BNXT_FLAG_TPA (BNXT_FLAG_LRO | BNXT_FLAG_GRO) #define BNXT_FLAG_JUMBO 0x10 #define BNXT_FLAG_STRIP_VLAN 0x20 -- cgit v1.2.3 From b82de0e28ccac15e1a0c3b4f6f20dfd230049041 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 22 Apr 2015 16:41:46 +0200 Subject: arcnet: move dev_free_skb to its only user The call for dev_free_skb is done only once. This patch moves its call to its only user and removes the obsolete condition variable. Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arcnet.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index e41dd36fe832..542e2b46b9eb 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -515,7 +515,7 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, struct ArcProto *proto; int txbuf; unsigned long flags; - int freeskb, retval; + int retval; arc_printk(D_DURING, dev, "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n", @@ -554,15 +554,13 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, * the package later - forget about it now */ dev->stats.tx_bytes += skb->len; - freeskb = 1; + dev_kfree_skb(skb); } else { /* do it the 'split' way */ lp->outgoing.proto = proto; lp->outgoing.skb = skb; lp->outgoing.pkt = pkt; - freeskb = 0; - if (proto->continue_tx && proto->continue_tx(dev, txbuf)) { arc_printk(D_NORMAL, dev, @@ -574,7 +572,6 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, lp->next_tx = txbuf; } else { retval = NETDEV_TX_BUSY; - freeskb = 0; } arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n", @@ -589,9 +586,6 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, __FILE__, __LINE__, __func__, lp->hw.status(dev)); spin_unlock_irqrestore(&lp->lock, flags); - if (freeskb) - dev_kfree_skb(skb); - return retval; /* no need to try again */ } EXPORT_SYMBOL(arcnet_send_packet); -- cgit v1.2.3 From 27daf6ed5c1fbeca9029c59c7f4f70a5c7e13531 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Fri, 20 Mar 2015 15:20:59 +0100 Subject: arcnet: com20020: add enable and disable device on open/close This patch changes the driver to properly work with the linux netif interface. The controller gets enabled on open and disabled on close. Therefor it removes every bogus start of the xceiver. It only gets enabled on com20020_open and disabled on com20020_close. Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/com20020.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index c82f323a8c2b..13d9ad4b3f5c 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -118,7 +118,7 @@ int com20020_check(struct net_device *dev) arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND); } - lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE; + lp->config = (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE; /* set node ID to 0x42 (but transmitter is disabled, so it's okay) */ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); arcnet_outb(0x42, ioaddr, COM20020_REG_W_XREG); @@ -131,11 +131,6 @@ int com20020_check(struct net_device *dev) } arc_printk(D_INIT_REASONS, dev, "status after reset: %X\n", status); - /* Enable TX */ - lp->config |= TXENcfg; - arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); - arcnet_outb(arcnet_inb(ioaddr, 8), ioaddr, COM20020_REG_W_XREG); - arcnet_outb(CFLAGScmd | RESETclear | CONFIGclear, ioaddr, COM20020_REG_W_COMMAND); status = arcnet_inb(ioaddr, COM20020_REG_R_STATUS); @@ -169,9 +164,33 @@ static int com20020_set_hwaddr(struct net_device *dev, void *addr) return 0; } +static int com20020_netdev_open(struct net_device *dev) +{ + int ioaddr = dev->base_addr; + struct arcnet_local *lp = netdev_priv(dev); + + lp->config |= TXENcfg; + arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); + + return arcnet_open(dev); +} + +static int com20020_netdev_close(struct net_device *dev) +{ + int ioaddr = dev->base_addr; + struct arcnet_local *lp = netdev_priv(dev); + + arcnet_close(dev); + + /* disable transmitter */ + lp->config &= ~TXENcfg; + arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); + return 0; +} + const struct net_device_ops com20020_netdev_ops = { - .ndo_open = arcnet_open, - .ndo_stop = arcnet_close, + .ndo_open = com20020_netdev_open, + .ndo_stop = com20020_netdev_close, .ndo_start_xmit = arcnet_send_packet, .ndo_tx_timeout = arcnet_timeout, .ndo_set_mac_address = com20020_set_hwaddr, @@ -215,7 +234,7 @@ int com20020_found(struct net_device *dev, int shared) arcnet_outb(STARTIOcmd, ioaddr, COM20020_REG_W_COMMAND); } - lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE; + lp->config = (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE; /* Default 0x38 + register: Node ID */ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); arcnet_outb(dev->dev_addr[0], ioaddr, COM20020_REG_W_XREG); @@ -274,7 +293,7 @@ static int com20020_reset(struct net_device *dev, int really_reset) dev->name, arcnet_inb(ioaddr, COM20020_REG_R_STATUS)); arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); - lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2); + lp->config |= (lp->timeout << 3) | (lp->backplane << 2); /* power-up defaults */ arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG); arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); -- cgit v1.2.3 From ae8ede6a0cdcf3b21596f44dff30bbd02265bb41 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Fri, 20 Mar 2015 15:22:24 +0100 Subject: arcnet: com20020-pci: set dev_port to the subdevice index This patch sets the dev_port according to the index of the card. This can be used by udev to name the ports in userspace. Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/com20020-pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index a12bf83be750..e3b7c14e619f 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -96,6 +96,7 @@ static int com20020pci_probe(struct pci_dev *pdev, ret = -ENOMEM; goto out_port; } + dev->dev_port = i; dev->netdev_ops = &com20020_netdev_ops; -- cgit v1.2.3 From 5ef216c1f84825c6942fdd6c24d12a08ac2df135 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Thu, 18 Sep 2014 00:12:50 +0200 Subject: arcnet: com20020-pci: add rotary index support The EAE PLX-PCI card has a special rotary encoder to configure the address of every card individually. We take this information for the initial setup of the cards dev_id. Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/com20020-pci.c | 33 +++++++++++++++++++++++++++++++++ drivers/net/arcnet/com20020.h | 4 ++++ 2 files changed, 37 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index e3b7c14e619f..637a6110cec6 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -68,6 +68,7 @@ static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct com20020_pci_card_info *ci; + struct com20020_pci_channel_map *mm; struct net_device *dev; struct arcnet_local *lp; struct com20020_priv *priv; @@ -84,9 +85,22 @@ static int com20020pci_probe(struct pci_dev *pdev, ci = (struct com20020_pci_card_info *)id->driver_data; priv->ci = ci; + mm = &ci->misc_map; INIT_LIST_HEAD(&priv->list_dev); + if (mm->size) { + ioaddr = pci_resource_start(pdev, mm->bar) + mm->offset; + r = devm_request_region(&pdev->dev, ioaddr, mm->size, + "com20020-pci"); + if (!r) { + pr_err("IO region %xh-%xh already allocated.\n", + ioaddr, ioaddr + mm->size - 1); + return -EBUSY; + } + priv->misc = ioaddr; + } + for (i = 0; i < ci->devcount; i++) { struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i]; struct com20020_dev *card; @@ -132,6 +146,13 @@ static int com20020pci_probe(struct pci_dev *pdev, lp->timeout = timeout; lp->hw.owner = THIS_MODULE; + /* Get the dev_id from the PLX rotary coder */ + if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15)) + dev->dev_id = 0xc; + dev->dev_id ^= inb(priv->misc + ci->rotary) >> 4; + + snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i); + if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) { pr_err("IO address %Xh is empty!\n", ioaddr); ret = -EIO; @@ -235,6 +256,12 @@ static struct com20020_pci_card_info card_info_eae_arc1 = { .size = 0x08, }, }, + .misc_map = { + .bar = 2, + .offset = 0x10, + .size = 0x04, + }, + .rotary = 0x0, .flags = ARC_CAN_10MBIT, }; @@ -252,6 +279,12 @@ static struct com20020_pci_card_info card_info_eae_ma1 = { .size = 0x08, } }, + .misc_map = { + .bar = 2, + .offset = 0x10, + .size = 0x04, + }, + .rotary = 0x0, .flags = ARC_CAN_10MBIT, }; diff --git a/drivers/net/arcnet/com20020.h b/drivers/net/arcnet/com20020.h index 22a460f39fb9..f2ed2eff3ae3 100644 --- a/drivers/net/arcnet/com20020.h +++ b/drivers/net/arcnet/com20020.h @@ -47,6 +47,9 @@ struct com20020_pci_card_info { int devcount; struct com20020_pci_channel_map chan_map_tbl[PLX_PCI_MAX_CARDS]; + struct com20020_pci_channel_map misc_map; + + int rotary; unsigned int flags; }; @@ -54,6 +57,7 @@ struct com20020_pci_card_info { struct com20020_priv { struct com20020_pci_card_info *ci; struct list_head list_dev; + resource_size_t misc; }; struct com20020_dev { -- cgit v1.2.3 From 8890624a4e8c2c7046d63bfd15d7331af9f55f10 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Thu, 18 Sep 2014 00:12:50 +0200 Subject: arcnet: com20020-pci: add led trigger support The EAE PLX-PCI card has special leds on the the main io pci resource bar. This patch adds support to trigger the conflict and data leds with the packages. Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arcdevice.h | 19 ++++++++++ drivers/net/arcnet/arcnet.c | 72 ++++++++++++++++++++++++++++++++++++++ drivers/net/arcnet/com20020-pci.c | 73 +++++++++++++++++++++++++++++++++++++++ drivers/net/arcnet/com20020.h | 10 ++++++ 4 files changed, 174 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h index d7fdea11e694..2edc0c0ab7c7 100644 --- a/drivers/net/arcnet/arcdevice.h +++ b/drivers/net/arcnet/arcdevice.h @@ -237,6 +237,8 @@ struct Outgoing { numsegs; /* number of segments */ }; +#define ARCNET_LED_NAME_SZ (IFNAMSIZ + 6) + struct arcnet_local { uint8_t config, /* current value of CONFIG register */ timeout, /* Extended timeout for COM20020 */ @@ -260,6 +262,11 @@ struct arcnet_local { /* On preemtive and SMB a lock is needed */ spinlock_t lock; + struct led_trigger *tx_led_trig; + char tx_led_trig_name[ARCNET_LED_NAME_SZ]; + struct led_trigger *recon_led_trig; + char recon_led_trig_name[ARCNET_LED_NAME_SZ]; + /* * Buffer management: an ARCnet card has 4 x 512-byte buffers, each of * which can be used for either sending or receiving. The new dynamic @@ -309,6 +316,8 @@ struct arcnet_local { int (*reset)(struct net_device *dev, int really_reset); void (*open)(struct net_device *dev); void (*close)(struct net_device *dev); + void (*datatrigger) (struct net_device * dev, int enable); + void (*recontrigger) (struct net_device * dev, int enable); void (*copy_to_card)(struct net_device *dev, int bufnum, int offset, void *buf, int count); @@ -319,6 +328,16 @@ struct arcnet_local { void __iomem *mem_start; /* pointer to ioremap'ed MMIO */ }; +enum arcnet_led_event { + ARCNET_LED_EVENT_RECON, + ARCNET_LED_EVENT_OPEN, + ARCNET_LED_EVENT_STOP, + ARCNET_LED_EVENT_TX, +}; + +void arcnet_led_event(struct net_device *netdev, enum arcnet_led_event event); +void devm_arcnet_led_init(struct net_device *netdev, int index, int subid); + #if ARCNET_DEBUG_MAX & D_SKB void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); #else diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 542e2b46b9eb..4242522ae86b 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -52,6 +52,8 @@ #include #include +#include + #include "arcdevice.h" #include "com9026.h" @@ -189,6 +191,71 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, #endif +/* Trigger a LED event in response to a ARCNET device event */ +void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event) +{ + struct arcnet_local *lp = netdev_priv(dev); + unsigned long led_delay = 350; + unsigned long tx_delay = 50; + + switch (event) { + case ARCNET_LED_EVENT_RECON: + led_trigger_blink_oneshot(lp->recon_led_trig, + &led_delay, &led_delay, 0); + break; + case ARCNET_LED_EVENT_OPEN: + led_trigger_event(lp->tx_led_trig, LED_OFF); + led_trigger_event(lp->recon_led_trig, LED_OFF); + break; + case ARCNET_LED_EVENT_STOP: + led_trigger_event(lp->tx_led_trig, LED_OFF); + led_trigger_event(lp->recon_led_trig, LED_OFF); + break; + case ARCNET_LED_EVENT_TX: + led_trigger_blink_oneshot(lp->tx_led_trig, + &tx_delay, &tx_delay, 0); + break; + } +} +EXPORT_SYMBOL_GPL(arcnet_led_event); + +static void arcnet_led_release(struct device *gendev, void *res) +{ + struct arcnet_local *lp = netdev_priv(to_net_dev(gendev)); + + led_trigger_unregister_simple(lp->tx_led_trig); + led_trigger_unregister_simple(lp->recon_led_trig); +} + +/* Register ARCNET LED triggers for a arcnet device + * + * This is normally called from a driver's probe function + */ +void devm_arcnet_led_init(struct net_device *netdev, int index, int subid) +{ + struct arcnet_local *lp = netdev_priv(netdev); + void *res; + + res = devres_alloc(arcnet_led_release, 0, GFP_KERNEL); + if (!res) { + netdev_err(netdev, "cannot register LED triggers\n"); + return; + } + + snprintf(lp->tx_led_trig_name, sizeof(lp->tx_led_trig_name), + "arc%d-%d-tx", index, subid); + snprintf(lp->recon_led_trig_name, sizeof(lp->recon_led_trig_name), + "arc%d-%d-recon", index, subid); + + led_trigger_register_simple(lp->tx_led_trig_name, + &lp->tx_led_trig); + led_trigger_register_simple(lp->recon_led_trig_name, + &lp->recon_led_trig); + + devres_add(&netdev->dev, res); +} +EXPORT_SYMBOL_GPL(devm_arcnet_led_init); + /* Unregister a protocol driver from the arc_proto_map. Protocol drivers * are responsible for registering themselves, but the unregister routine * is pretty generic so we'll do it here. @@ -425,6 +492,7 @@ int arcnet_open(struct net_device *dev) netif_start_queue(dev); + arcnet_led_event(dev, ARCNET_LED_EVENT_OPEN); return 0; out_module_put: @@ -438,6 +506,7 @@ int arcnet_close(struct net_device *dev) { struct arcnet_local *lp = netdev_priv(dev); + arcnet_led_event(dev, ARCNET_LED_EVENT_STOP); netif_stop_queue(dev); /* flush TX and disable RX */ @@ -585,6 +654,8 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, lp->hw.status(dev)); + arcnet_led_event(dev, ARCNET_LED_EVENT_TX); + spin_unlock_irqrestore(&lp->lock, flags); return retval; /* no need to try again */ } @@ -837,6 +908,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n", status); + arcnet_led_event(dev, ARCNET_LED_EVENT_RECON); /* MYRECON bit is at bit 7 of diagstatus */ if (diagstatus & 0x80) arc_printk(D_RECON, dev, "Put out that recon myself\n"); diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 637a6110cec6..239de38fbd6a 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "arcdevice.h" #include "com20020.h" @@ -62,6 +63,36 @@ module_param(clockp, int, 0); module_param(clockm, int, 0); MODULE_LICENSE("GPL"); +static void led_tx_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct com20020_dev *card; + struct com20020_priv *priv; + struct com20020_pci_card_info *ci; + + card = container_of(led_cdev, struct com20020_dev, tx_led); + + priv = card->pci_priv; + ci = priv->ci; + + outb(!!value, priv->misc + ci->leds[card->index].green); +} + +static void led_recon_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct com20020_dev *card; + struct com20020_priv *priv; + struct com20020_pci_card_info *ci; + + card = container_of(led_cdev, struct com20020_dev, recon_led); + + priv = card->pci_priv; + ci = priv->ci; + + outb(!!value, priv->misc + ci->leds[card->index].red); +} + static void com20020pci_remove(struct pci_dev *pdev); static int com20020pci_probe(struct pci_dev *pdev, @@ -170,14 +201,41 @@ static int com20020pci_probe(struct pci_dev *pdev, card->index = i; card->pci_priv = priv; + card->tx_led.brightness_set = led_tx_set; + card->tx_led.default_trigger = devm_kasprintf(&pdev->dev, + GFP_KERNEL, "arc%d-%d-tx", + dev->dev_id, i); + card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "pci:green:tx:%d-%d", + dev->dev_id, i); + + card->tx_led.dev = &dev->dev; + card->recon_led.brightness_set = led_recon_set; + card->recon_led.default_trigger = devm_kasprintf(&pdev->dev, + GFP_KERNEL, "arc%d-%d-recon", + dev->dev_id, i); + card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, + "pci:red:recon:%d-%d", + dev->dev_id, i); + card->recon_led.dev = &dev->dev; card->dev = dev; + ret = devm_led_classdev_register(&pdev->dev, &card->tx_led); + if (ret) + goto out_port; + + ret = devm_led_classdev_register(&pdev->dev, &card->recon_led); + if (ret) + goto out_port; + dev_set_drvdata(&dev->dev, card); ret = com20020_found(dev, IRQF_SHARED); if (ret) goto out_port; + devm_arcnet_led_init(dev, dev->dev_id, i); + list_add(&card->list, &priv->list_dev); } @@ -261,6 +319,12 @@ static struct com20020_pci_card_info card_info_eae_arc1 = { .offset = 0x10, .size = 0x04, }, + .leds = { + { + .green = 0x0, + .red = 0x1, + }, + }, .rotary = 0x0, .flags = ARC_CAN_10MBIT, }; @@ -284,6 +348,15 @@ static struct com20020_pci_card_info card_info_eae_ma1 = { .offset = 0x10, .size = 0x04, }, + .leds = { + { + .green = 0x0, + .red = 0x1, + }, { + .green = 0x2, + .red = 0x3, + }, + }, .rotary = 0x0, .flags = ARC_CAN_10MBIT, }; diff --git a/drivers/net/arcnet/com20020.h b/drivers/net/arcnet/com20020.h index f2ed2eff3ae3..0bcc5d0a6903 100644 --- a/drivers/net/arcnet/com20020.h +++ b/drivers/net/arcnet/com20020.h @@ -26,6 +26,7 @@ */ #ifndef __COM20020_H #define __COM20020_H +#include int com20020_check(struct net_device *dev); int com20020_found(struct net_device *dev, int shared); @@ -36,6 +37,11 @@ extern const struct net_device_ops com20020_netdev_ops; #define PLX_PCI_MAX_CARDS 2 +struct ledoffsets { + int green; + int red; +}; + struct com20020_pci_channel_map { u32 bar; u32 offset; @@ -49,6 +55,7 @@ struct com20020_pci_card_info { struct com20020_pci_channel_map chan_map_tbl[PLX_PCI_MAX_CARDS]; struct com20020_pci_channel_map misc_map; + struct ledoffsets leds[PLX_PCI_MAX_CARDS]; int rotary; unsigned int flags; @@ -64,6 +71,9 @@ struct com20020_dev { struct list_head list; struct net_device *dev; + struct led_classdev tx_led; + struct led_classdev recon_led; + struct com20020_priv *pci_priv; int index; }; -- cgit v1.2.3 From 59fbcbc61e1f0fd9acdf3efb09faca0320049718 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Wed, 16 Sep 2015 10:15:45 +0200 Subject: arcnet: add netif_carrier_on/off for reconnect The arcnet device has no interrupt to detect if the link has changed from disconnected to connected. This patch adds an timer to toggle the link detection. The timer will get retriggered as long as the reconnection interrupts accure. If the recon interrupts hold off for >1s we define the connection stable again. Signed-off-by: Michael Grzeschik --- drivers/net/arcnet/arcdevice.h | 2 ++ drivers/net/arcnet/arcnet.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h index 2edc0c0ab7c7..20bfb9ba83ea 100644 --- a/drivers/net/arcnet/arcdevice.h +++ b/drivers/net/arcnet/arcdevice.h @@ -267,6 +267,8 @@ struct arcnet_local { struct led_trigger *recon_led_trig; char recon_led_trig_name[ARCNET_LED_NAME_SZ]; + struct timer_list timer; + /* * Buffer management: an ARCnet card has 4 x 512-byte buffers, each of * which can be used for either sending or receiving. The new dynamic diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 4242522ae86b..6ea963e3b89a 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -381,6 +381,16 @@ static void arcdev_setup(struct net_device *dev) dev->flags = IFF_BROADCAST; } +static void arcnet_timer(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + + if (!netif_carrier_ok(dev)) { + netif_carrier_on(dev); + netdev_info(dev, "link up\n"); + } +} + struct net_device *alloc_arcdev(const char *name) { struct net_device *dev; @@ -392,6 +402,9 @@ struct net_device *alloc_arcdev(const char *name) struct arcnet_local *lp = netdev_priv(dev); spin_lock_init(&lp->lock); + init_timer(&lp->timer); + lp->timer.data = (unsigned long) dev; + lp->timer.function = arcnet_timer; } return dev; @@ -490,7 +503,9 @@ int arcnet_open(struct net_device *dev) lp->hw.intmask(dev, lp->intmask); arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); + netif_carrier_off(dev); netif_start_queue(dev); + mod_timer(&lp->timer, jiffies + msecs_to_jiffies(1000)); arcnet_led_event(dev, ARCNET_LED_EVENT_OPEN); return 0; @@ -507,7 +522,10 @@ int arcnet_close(struct net_device *dev) struct arcnet_local *lp = netdev_priv(dev); arcnet_led_event(dev, ARCNET_LED_EVENT_STOP); + del_timer_sync(&lp->timer); + netif_stop_queue(dev); + netif_carrier_off(dev); /* flush TX and disable RX */ lp->hw.intmask(dev, 0); @@ -908,6 +926,12 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n", status); + if (netif_carrier_ok(dev)) { + netif_carrier_off(dev); + netdev_info(dev, "link down\n"); + } + mod_timer(&lp->timer, jiffies + msecs_to_jiffies(1000)); + arcnet_led_event(dev, ARCNET_LED_EVENT_RECON); /* MYRECON bit is at bit 7 of diagstatus */ if (diagstatus & 0x80) @@ -959,6 +983,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) lp->num_recons = lp->network_down = 0; arc_printk(D_DURING, dev, "not recon: clearing counters anyway.\n"); + netif_carrier_on(dev); } if (didsomething) -- cgit v1.2.3 From c0963772cbbf1b7dc9fad4497f3aba8526bb07d6 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 25 Oct 2015 18:24:38 +0200 Subject: rtl8xxxu: fix unused rtl8192cu_fops compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kbuild reported: rtl8xxxu.c:5786:32: warning: ‘rtl8192cu_fops’ defined but not used [-Wunused-variable] Fix it by adding temporary ifdefs around the static functions. Fixes: 033695bdf6d7 ("rtl8xxxu: move devices supported by rtlwifi under UNTESTED config") Reported-by: kbuild test robot Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 86d864af3a32..6aed923a709a 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -1818,6 +1818,8 @@ static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv) return 0; } +#ifdef CONFIG_RTL8XXXU_UNTESTED + static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv) { int i; @@ -1885,6 +1887,8 @@ static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv) return 0; } +#endif + static int rtl8xxxu_read_efuse8(struct rtl8xxxu_priv *priv, u16 offset, u8 *data) { @@ -2217,6 +2221,8 @@ static int rtl8723au_load_firmware(struct rtl8xxxu_priv *priv) return ret; } +#ifdef CONFIG_RTL8XXXU_UNTESTED + static int rtl8192cu_load_firmware(struct rtl8xxxu_priv *priv) { char *fw_name; @@ -2234,6 +2240,8 @@ static int rtl8192cu_load_firmware(struct rtl8xxxu_priv *priv) return ret; } +#endif + static void rtl8xxxu_firmware_self_reset(struct rtl8xxxu_priv *priv) { u16 val16; @@ -3815,6 +3823,8 @@ exit: return ret; } +#ifdef CONFIG_RTL8XXXU_UNTESTED + static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) { u8 val8; @@ -3918,6 +3928,8 @@ static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv) return 0; } +#endif + static void rtl8xxxu_power_off(struct rtl8xxxu_priv *priv) { u8 val8; @@ -5783,6 +5795,8 @@ static struct rtl8xxxu_fileops rtl8723au_fops = { .writeN_block_size = 1024, }; +#ifdef CONFIG_RTL8XXXU_UNTESTED + static struct rtl8xxxu_fileops rtl8192cu_fops = { .parse_efuse = rtl8192cu_parse_efuse, .load_firmware = rtl8192cu_load_firmware, @@ -5790,6 +5804,8 @@ static struct rtl8xxxu_fileops rtl8192cu_fops = { .writeN_block_size = 128, }; +#endif + static struct usb_device_id dev_table[] = { {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8724, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8723au_fops}, -- cgit v1.2.3 From 680060d3e02d175516832e9af058ffe96ecc4cdc Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 23 Oct 2015 11:38:07 -0700 Subject: net: dsa: bcm_sf2: Implement FDB operations Add support for the FDB add, delete, and dump operations. The add and delete operations are implemented using directed ARL operations using the specified MAC address and consist in a read operation, write and readback operation. The dump operation consists in using the ARL search and software filtering entries which are not for the desired port. Signed-off-by: Florian Fainelli Reviewed-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 236 +++++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/bcm_sf2.h | 56 ++++++++++ drivers/net/dsa/bcm_sf2_regs.h | 43 ++++++++ 3 files changed, 335 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 9d56515f4c4d..4f32b8a530bf 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include "bcm_sf2.h" #include "bcm_sf2_regs.h" @@ -555,6 +557,236 @@ static int bcm_sf2_sw_br_set_stp_state(struct dsa_switch *ds, int port, return 0; } +/* Address Resolution Logic routines */ +static int bcm_sf2_arl_op_wait(struct bcm_sf2_priv *priv) +{ + unsigned int timeout = 10; + u32 reg; + + do { + reg = core_readl(priv, CORE_ARLA_RWCTL); + if (!(reg & ARL_STRTDN)) + return 0; + + usleep_range(1000, 2000); + } while (timeout--); + + return -ETIMEDOUT; +} + +static int bcm_sf2_arl_rw_op(struct bcm_sf2_priv *priv, unsigned int op) +{ + u32 cmd; + + if (op > ARL_RW) + return -EINVAL; + + cmd = core_readl(priv, CORE_ARLA_RWCTL); + cmd &= ~IVL_SVL_SELECT; + cmd |= ARL_STRTDN; + if (op) + cmd |= ARL_RW; + else + cmd &= ~ARL_RW; + core_writel(priv, cmd, CORE_ARLA_RWCTL); + + return bcm_sf2_arl_op_wait(priv); +} + +static int bcm_sf2_arl_read(struct bcm_sf2_priv *priv, u64 mac, + u16 vid, struct bcm_sf2_arl_entry *ent, u8 *idx, + bool is_valid) +{ + unsigned int i; + int ret; + + ret = bcm_sf2_arl_op_wait(priv); + if (ret) + return ret; + + /* Read the 4 bins */ + for (i = 0; i < 4; i++) { + u64 mac_vid; + u32 fwd_entry; + + mac_vid = core_readq(priv, CORE_ARLA_MACVID_ENTRY(i)); + fwd_entry = core_readl(priv, CORE_ARLA_FWD_ENTRY(i)); + bcm_sf2_arl_to_entry(ent, mac_vid, fwd_entry); + + if (ent->is_valid && is_valid) { + *idx = i; + return 0; + } + + /* This is the MAC we just deleted */ + if (!is_valid && (mac_vid & mac)) + return 0; + } + + return -ENOENT; +} + +static int bcm_sf2_arl_op(struct bcm_sf2_priv *priv, int op, int port, + const unsigned char *addr, u16 vid, bool is_valid) +{ + struct bcm_sf2_arl_entry ent; + u32 fwd_entry; + u64 mac, mac_vid = 0; + u8 idx = 0; + int ret; + + /* Convert the array into a 64-bit MAC */ + mac = bcm_sf2_mac_to_u64(addr); + + /* Perform a read for the given MAC and VID */ + core_writeq(priv, mac, CORE_ARLA_MAC); + core_writel(priv, vid, CORE_ARLA_VID); + + /* Issue a read operation for this MAC */ + ret = bcm_sf2_arl_rw_op(priv, 1); + if (ret) + return ret; + + ret = bcm_sf2_arl_read(priv, mac, vid, &ent, &idx, is_valid); + /* If this is a read, just finish now */ + if (op) + return ret; + + /* We could not find a matching MAC, so reset to a new entry */ + if (ret) { + fwd_entry = 0; + idx = 0; + } + + memset(&ent, 0, sizeof(ent)); + ent.port = port; + ent.is_valid = is_valid; + ent.vid = vid; + ent.is_static = true; + memcpy(ent.mac, addr, ETH_ALEN); + bcm_sf2_arl_from_entry(&mac_vid, &fwd_entry, &ent); + + core_writeq(priv, mac_vid, CORE_ARLA_MACVID_ENTRY(idx)); + core_writel(priv, fwd_entry, CORE_ARLA_FWD_ENTRY(idx)); + + ret = bcm_sf2_arl_rw_op(priv, 0); + if (ret) + return ret; + + /* Re-read the entry to check */ + return bcm_sf2_arl_read(priv, mac, vid, &ent, &idx, is_valid); +} + +static int bcm_sf2_sw_fdb_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_fdb *fdb, + struct switchdev_trans *trans) +{ + /* We do not need to do anything specific here yet */ + return 0; +} + +static int bcm_sf2_sw_fdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_fdb *fdb, + struct switchdev_trans *trans) +{ + struct bcm_sf2_priv *priv = ds_to_priv(ds); + + return bcm_sf2_arl_op(priv, 0, port, fdb->addr, fdb->vid, true); +} + +static int bcm_sf2_sw_fdb_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_fdb *fdb) +{ + struct bcm_sf2_priv *priv = ds_to_priv(ds); + + return bcm_sf2_arl_op(priv, 0, port, fdb->addr, fdb->vid, false); +} + +static int bcm_sf2_arl_search_wait(struct bcm_sf2_priv *priv) +{ + unsigned timeout = 1000; + u32 reg; + + do { + reg = core_readl(priv, CORE_ARLA_SRCH_CTL); + if (!(reg & ARLA_SRCH_STDN)) + return 0; + + if (reg & ARLA_SRCH_VLID) + return 0; + + usleep_range(1000, 2000); + } while (timeout--); + + return -ETIMEDOUT; +} + +static void bcm_sf2_arl_search_rd(struct bcm_sf2_priv *priv, u8 idx, + struct bcm_sf2_arl_entry *ent) +{ + u64 mac_vid; + u32 fwd_entry; + + mac_vid = core_readq(priv, CORE_ARLA_SRCH_RSLT_MACVID(idx)); + fwd_entry = core_readl(priv, CORE_ARLA_SRCH_RSLT(idx)); + bcm_sf2_arl_to_entry(ent, mac_vid, fwd_entry); +} + +static int bcm_sf2_sw_fdb_copy(struct net_device *dev, int port, + const struct bcm_sf2_arl_entry *ent, + struct switchdev_obj_port_fdb *fdb, + int (*cb)(struct switchdev_obj *obj)) +{ + if (!ent->is_valid) + return 0; + + if (port != ent->port) + return 0; + + ether_addr_copy(fdb->addr, ent->mac); + fdb->vid = ent->vid; + fdb->ndm_state = ent->is_static ? NUD_NOARP : NUD_REACHABLE; + + return cb(&fdb->obj); +} + +static int bcm_sf2_sw_fdb_dump(struct dsa_switch *ds, int port, + struct switchdev_obj_port_fdb *fdb, + int (*cb)(struct switchdev_obj *obj)) +{ + struct bcm_sf2_priv *priv = ds_to_priv(ds); + struct net_device *dev = ds->ports[port]; + struct bcm_sf2_arl_entry results[2]; + unsigned int count = 0; + int ret; + + /* Start search operation */ + core_writel(priv, ARLA_SRCH_STDN, CORE_ARLA_SRCH_CTL); + + do { + ret = bcm_sf2_arl_search_wait(priv); + if (ret) + return ret; + + /* Read both entries, then return their values back */ + bcm_sf2_arl_search_rd(priv, 0, &results[0]); + ret = bcm_sf2_sw_fdb_copy(dev, port, &results[0], fdb, cb); + if (ret) + return ret; + + bcm_sf2_arl_search_rd(priv, 1, &results[1]); + ret = bcm_sf2_sw_fdb_copy(dev, port, &results[1], fdb, cb); + if (ret) + return ret; + + if (!results[0].is_valid && !results[1].is_valid) + break; + + } while (count++ < CORE_ARLA_NUM_ENTRIES); + + return 0; +} + static irqreturn_t bcm_sf2_switch_0_isr(int irq, void *dev_id) { struct bcm_sf2_priv *priv = dev_id; @@ -1076,6 +1308,10 @@ static struct dsa_switch_driver bcm_sf2_switch_driver = { .port_join_bridge = bcm_sf2_sw_br_join, .port_leave_bridge = bcm_sf2_sw_br_leave, .port_stp_update = bcm_sf2_sw_br_set_stp_state, + .port_fdb_prepare = bcm_sf2_sw_fdb_prepare, + .port_fdb_add = bcm_sf2_sw_fdb_add, + .port_fdb_del = bcm_sf2_sw_fdb_del, + .port_fdb_dump = bcm_sf2_sw_fdb_dump, }; static int __init bcm_sf2_init(void) diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h index 789d7b7737da..cc98abc0aaf3 100644 --- a/drivers/net/dsa/bcm_sf2.h +++ b/drivers/net/dsa/bcm_sf2.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include @@ -50,6 +52,60 @@ struct bcm_sf2_port_status { u32 vlan_ctl_mask; }; +struct bcm_sf2_arl_entry { + u8 port; + u8 mac[ETH_ALEN]; + u16 vid; + u8 is_valid:1; + u8 is_age:1; + u8 is_static:1; +}; + +static inline void bcm_sf2_mac_from_u64(u64 src, u8 *dst) +{ + unsigned int i; + + for (i = 0; i < ETH_ALEN; i++) + dst[ETH_ALEN - 1 - i] = (src >> (8 * i)) & 0xff; +} + +static inline u64 bcm_sf2_mac_to_u64(const u8 *src) +{ + unsigned int i; + u64 dst = 0; + + for (i = 0; i < ETH_ALEN; i++) + dst |= (u64)src[ETH_ALEN - 1 - i] << (8 * i); + + return dst; +} + +static inline void bcm_sf2_arl_to_entry(struct bcm_sf2_arl_entry *ent, + u64 mac_vid, u32 fwd_entry) +{ + memset(ent, 0, sizeof(*ent)); + ent->port = fwd_entry & PORTID_MASK; + ent->is_valid = !!(fwd_entry & ARL_VALID); + ent->is_age = !!(fwd_entry & ARL_AGE); + ent->is_static = !!(fwd_entry & ARL_STATIC); + bcm_sf2_mac_from_u64(mac_vid, ent->mac); + ent->vid = mac_vid >> VID_SHIFT; +} + +static inline void bcm_sf2_arl_from_entry(u64 *mac_vid, u32 *fwd_entry, + const struct bcm_sf2_arl_entry *ent) +{ + *mac_vid = bcm_sf2_mac_to_u64(ent->mac); + *mac_vid |= (u64)(ent->vid & VID_MASK) << VID_SHIFT; + *fwd_entry = ent->port & PORTID_MASK; + if (ent->is_valid) + *fwd_entry |= ARL_VALID; + if (ent->is_static) + *fwd_entry |= ARL_STATIC; + if (ent->is_age) + *fwd_entry |= ARL_AGE; +} + struct bcm_sf2_priv { /* Base registers, keep those in order with BCM_SF2_REGS_NAME */ void __iomem *core; diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h index fa4e6e78c9ea..97780d43b5c0 100644 --- a/drivers/net/dsa/bcm_sf2_regs.h +++ b/drivers/net/dsa/bcm_sf2_regs.h @@ -231,6 +231,49 @@ #define CORE_BRCM_HDR_RX_DIS 0x0980 #define CORE_BRCM_HDR_TX_DIS 0x0988 +#define CORE_ARLA_NUM_ENTRIES 1024 + +#define CORE_ARLA_RWCTL 0x1400 +#define ARL_RW (1 << 0) +#define IVL_SVL_SELECT (1 << 6) +#define ARL_STRTDN (1 << 7) + +#define CORE_ARLA_MAC 0x1408 +#define CORE_ARLA_VID 0x1420 +#define ARLA_VIDTAB_INDX_MASK 0x1fff + +#define CORE_ARLA_MACVID0 0x1440 +#define MAC_MASK 0xffffffffff +#define VID_SHIFT 48 +#define VID_MASK 0xfff + +#define CORE_ARLA_FWD_ENTRY0 0x1460 +#define PORTID_MASK 0x1ff +#define ARL_CON_SHIFT 9 +#define ARL_CON_MASK 0x3 +#define ARL_PRI_SHIFT 11 +#define ARL_PRI_MASK 0x7 +#define ARL_AGE (1 << 14) +#define ARL_STATIC (1 << 15) +#define ARL_VALID (1 << 16) + +#define CORE_ARLA_MACVID_ENTRY(x) (CORE_ARLA_MACVID0 + ((x) * 0x40)) +#define CORE_ARLA_FWD_ENTRY(x) (CORE_ARLA_FWD_ENTRY0 + ((x) * 0x40)) + +#define CORE_ARLA_SRCH_CTL 0x1540 +#define ARLA_SRCH_VLID (1 << 0) +#define IVL_SVL_SELECT (1 << 6) +#define ARLA_SRCH_STDN (1 << 7) + +#define CORE_ARLA_SRCH_ADR 0x1544 +#define ARLA_SRCH_ADR_VALID (1 << 15) + +#define CORE_ARLA_SRCH_RSLT_0_MACVID 0x1580 +#define CORE_ARLA_SRCH_RSLT_0 0x15a0 + +#define CORE_ARLA_SRCH_RSLT_MACVID(x) (CORE_ARLA_SRCH_RSLT_0_MACVID + ((x) * 0x40)) +#define CORE_ARLA_SRCH_RSLT(x) (CORE_ARLA_SRCH_RSLT_0 + ((x) * 0x40)) + #define CORE_MEM_PSM_VDD_CTRL 0x2380 #define P_TXQ_PSM_VDD_SHIFT 2 #define P_TXQ_PSM_VDD_MASK 0x3 -- cgit v1.2.3 From 8b7c94e3478dbb0296293b43a974c3561d01e9fb Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 23 Oct 2015 12:11:08 -0700 Subject: net: dsa: bcm_sf2: Unhardcode port numbers While the current driver mostly supports BCM7445 which has a hardcoded location for its MoCA port on port 7 and port 0 for its internal PHY, this is not necessarily true for all other chips out there such as BCM3390 for instance. Walk the list of ports from Device Tree, get their port number ("reg" property), and then parse the "phy-mode" property and initialize two internal variables: moca_port and a bitmask of internal PHYs. Since we use interrupts for the MoCA port, we introduce two helper functions to enable/disable interrupts and do this at the appropriate bank (INTRL2_0 or INTRL2_1). Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/bcm_sf2.c | 102 +++++++++++++++++++++++++++++++++++++++++----- drivers/net/dsa/bcm_sf2.h | 6 +++ 2 files changed, 97 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 4f32b8a530bf..6f946fedbb77 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -266,6 +267,50 @@ static void bcm_sf2_gphy_enable_set(struct dsa_switch *ds, bool enable) } } +static inline void bcm_sf2_port_intr_enable(struct bcm_sf2_priv *priv, + int port) +{ + unsigned int off; + + switch (port) { + case 7: + off = P7_IRQ_OFF; + break; + case 0: + /* Port 0 interrupts are located on the first bank */ + intrl2_0_mask_clear(priv, P_IRQ_MASK(P0_IRQ_OFF)); + return; + default: + off = P_IRQ_OFF(port); + break; + } + + intrl2_1_mask_clear(priv, P_IRQ_MASK(off)); +} + +static inline void bcm_sf2_port_intr_disable(struct bcm_sf2_priv *priv, + int port) +{ + unsigned int off; + + switch (port) { + case 7: + off = P7_IRQ_OFF; + break; + case 0: + /* Port 0 interrupts are located on the first bank */ + intrl2_0_mask_set(priv, P_IRQ_MASK(P0_IRQ_OFF)); + intrl2_0_writel(priv, P_IRQ_MASK(P0_IRQ_OFF), INTRL2_CPU_CLEAR); + return; + default: + off = P_IRQ_OFF(port); + break; + } + + intrl2_1_mask_set(priv, P_IRQ_MASK(off)); + intrl2_1_writel(priv, P_IRQ_MASK(off), INTRL2_CPU_CLEAR); +} + static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, struct phy_device *phy) { @@ -282,7 +327,7 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, core_writel(priv, 0, CORE_G_PCTL_PORT(port)); /* Re-enable the GPHY and re-apply workarounds */ - if (port == 0 && priv->hw_params.num_gphy == 1) { + if (priv->int_phy_mask & 1 << port && priv->hw_params.num_gphy == 1) { bcm_sf2_gphy_enable_set(ds, true); if (phy) { /* if phy_stop() has been called before, phy @@ -299,9 +344,9 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, } } - /* Enable port 7 interrupts to get notified */ - if (port == 7) - intrl2_1_mask_clear(priv, P_IRQ_MASK(P7_IRQ_OFF)); + /* Enable MoCA port interrupts to get notified */ + if (port == priv->moca_port) + bcm_sf2_port_intr_enable(priv, port); /* Set this port, and only this one to be in the default VLAN, * if member of a bridge, restore its membership prior to @@ -331,12 +376,10 @@ static void bcm_sf2_port_disable(struct dsa_switch *ds, int port, if (priv->wol_ports_mask & (1 << port)) return; - if (port == 7) { - intrl2_1_mask_set(priv, P_IRQ_MASK(P7_IRQ_OFF)); - intrl2_1_writel(priv, P_IRQ_MASK(P7_IRQ_OFF), INTRL2_CPU_CLEAR); - } + if (port == priv->moca_port) + bcm_sf2_port_intr_disable(priv, port); - if (port == 0 && priv->hw_params.num_gphy == 1) + if (priv->int_phy_mask & 1 << port && priv->hw_params.num_gphy == 1) bcm_sf2_gphy_enable_set(ds, false); if (dsa_is_cpu_port(ds, port)) @@ -847,6 +890,42 @@ static void bcm_sf2_intr_disable(struct bcm_sf2_priv *priv) intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR); } +static void bcm_sf2_identify_ports(struct bcm_sf2_priv *priv, + struct device_node *dn) +{ + struct device_node *port; + const char *phy_mode_str; + int mode; + unsigned int port_num; + int ret; + + priv->moca_port = -1; + + for_each_available_child_of_node(dn, port) { + if (of_property_read_u32(port, "reg", &port_num)) + continue; + + /* Internal PHYs get assigned a specific 'phy-mode' property + * value: "internal" to help flag them before MDIO probing + * has completed, since they might be turned off at that + * time + */ + mode = of_get_phy_mode(port); + if (mode < 0) { + ret = of_property_read_string(port, "phy-mode", + &phy_mode_str); + if (ret < 0) + continue; + + if (!strcasecmp(phy_mode_str, "internal")) + priv->int_phy_mask |= 1 << port_num; + } + + if (mode == PHY_INTERFACE_MODE_MOCA) + priv->moca_port = port_num; + } +} + static int bcm_sf2_sw_setup(struct dsa_switch *ds) { const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME; @@ -865,6 +944,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) * level */ dn = ds->pd->of_node->parent; + bcm_sf2_identify_ports(priv, ds->pd->of_node); priv->irq0 = irq_of_parse_and_map(dn, 0); priv->irq1 = irq_of_parse_and_map(dn, 1); @@ -1145,7 +1225,7 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, status->link = 0; - /* Port 7 is special as we do not get link status from CORE_LNKSTS, + /* MoCA port is special as we do not get link status from CORE_LNKSTS, * which means that we need to force the link at the port override * level to get the data to flow. We do use what the interrupt handler * did determine before. @@ -1153,7 +1233,7 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, * For the other ports, we just force the link status, since this is * a fixed PHY device. */ - if (port == 7) { + if (port == priv->moca_port) { status->link = priv->port_sts[port].link; /* For MoCA interfaces, also force a link down notification * since some version of the user-space daemon (mocad) use diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h index cc98abc0aaf3..6bba1c98d764 100644 --- a/drivers/net/dsa/bcm_sf2.h +++ b/drivers/net/dsa/bcm_sf2.h @@ -134,6 +134,12 @@ struct bcm_sf2_priv { /* Mask of ports enabled for Wake-on-LAN */ u32 wol_ports_mask; + + /* MoCA port location */ + int moca_port; + + /* Bitmask of ports having an integrated PHY */ + unsigned int int_phy_mask; }; struct bcm_sf2_hw_stats { -- cgit v1.2.3 From ab8579169b79c062935dade949287113c7c1ba73 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 24 Oct 2015 00:46:03 +0300 Subject: sh_eth: fix RX buffer size alignment Both Renesas R-Car and RZ/A1 manuals state that RX buffer length must be a multiple of 32 bytes, while the driver only uses 16 byte granularity... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 257ea713b4c1..d8334d8a53b3 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1148,8 +1148,8 @@ static void sh_eth_ring_format(struct net_device *ndev) /* RX descriptor */ rxdesc = &mdp->rx_ring[i]; - /* The size of the buffer is a multiple of 16 bytes. */ - rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); + /* The size of the buffer is a multiple of 32 bytes. */ + rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 32); dma_addr = dma_map_single(&ndev->dev, skb->data, rxdesc->buffer_length, DMA_FROM_DEVICE); @@ -1506,7 +1506,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) if (mdp->cd->rpadir) skb_reserve(skb, NET_IP_ALIGN); dma_unmap_single(&ndev->dev, rxdesc->addr, - ALIGN(mdp->rx_buf_sz, 16), + ALIGN(mdp->rx_buf_sz, 32), DMA_FROM_DEVICE); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, ndev); @@ -1524,8 +1524,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) { entry = mdp->dirty_rx % mdp->num_rx_ring; rxdesc = &mdp->rx_ring[entry]; - /* The size of the buffer is 16 byte boundary. */ - rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16); + /* The size of the buffer is 32 byte boundary. */ + rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 32); if (mdp->rx_skbuff[entry] == NULL) { skb = netdev_alloc_skb(ndev, skbuff_size); -- cgit v1.2.3 From cb3685958dd4c46d7646d244063ea3ec8adf3618 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 24 Oct 2015 00:46:40 +0300 Subject: sh_eth: fix RX buffer size calculation The RX buffer size calulation failed to account for the length granularity (which is now 32 bytes)... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index d8334d8a53b3..a484d8beb855 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1127,7 +1127,7 @@ static void sh_eth_ring_format(struct net_device *ndev) struct sh_eth_txdesc *txdesc = NULL; int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring; int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring; - int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1; + int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1; dma_addr_t dma_addr; mdp->cur_rx = 0; @@ -1450,7 +1450,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) struct sk_buff *skb; u16 pkt_len = 0; u32 desc_status; - int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1; + int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1; dma_addr_t dma_addr; boguscnt = min(boguscnt, *quota); -- cgit v1.2.3 From 8c387ebbaff8652943a1cbcab496aecadc6a8875 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 25 Oct 2015 14:57:00 +0100 Subject: net: thunderx: add missing of_node_put for_each_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ local idexpression r.n; expression r,e; @@ for_each_child_of_node(r,n) { ... ( of_node_put(n); | e = n | + of_node_put(n); ? break; ) ... } ... when != n // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index 574c49278900..180aa9fabf48 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -977,8 +977,10 @@ static int bgx_init_of_phy(struct bgx *bgx) SET_NETDEV_DEV(&bgx->lmac[lmac].netdev, &bgx->pdev->dev); bgx->lmac[lmac].lmacid = lmac; lmac++; - if (lmac == MAX_LMAC_PER_BGX) + if (lmac == MAX_LMAC_PER_BGX) { + of_node_put(np_child); break; + } } return 0; } -- cgit v1.2.3 From bd252796852193277a07da505601a2f407c70e0b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 25 Oct 2015 14:57:01 +0100 Subject: net: netcp: add missing of_node_put for_each_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ local idexpression r.n; expression r,e; @@ for_each_child_of_node(r,n) { ... ( of_node_put(n); | e = n | + of_node_put(n); ? break; ) ... } ... when != n // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/netcp_ethss.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 6bff8d82ceab..4e70e7586a09 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c @@ -2637,8 +2637,10 @@ static void init_secondary_ports(struct gbe_priv *gbe_dev, mac_phy_link = true; slave->open = true; - if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) + if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) { + of_node_put(port); break; + } } /* of_phy_connect() is needed only for MAC-PHY interface */ @@ -3137,8 +3139,10 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, continue; } gbe_dev->num_slaves++; - if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) + if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) { + of_node_put(interface); break; + } } of_node_put(interfaces); -- cgit v1.2.3 From 447ed7360037b6e38c0206ddcbd04a256ec94099 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 25 Oct 2015 14:57:02 +0100 Subject: netdev/phy: add missing of_node_put for_each_available_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ local idexpression r.n; expression r,e; @@ for_each_available_child_of_node(r,n) { ... ( of_node_put(n); | e = n | + of_node_put(n); ? break; ) ... } ... when != n // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/phy/mdio-mux.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c index 280c7c311f72..908e8d486342 100644 --- a/drivers/net/phy/mdio-mux.c +++ b/drivers/net/phy/mdio-mux.c @@ -144,6 +144,7 @@ int mdio_mux_init(struct device *dev, dev_err(dev, "Error: Failed to allocate memory for child\n"); ret_val = -ENOMEM; + of_node_put(child_bus_node); break; } cb->bus_number = v; -- cgit v1.2.3 From 028623418766ea64f4256035b06ac6cbc0a67892 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 25 Oct 2015 14:57:03 +0100 Subject: net: phy: mdio: add missing of_node_put for_each_available_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ expression root,e; local idexpression child; @@ for_each_available_child_of_node(root, child) { ... when != of_node_put(child) when != e = child ( return child; | + of_node_put(child); ? return ...; ) ... } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/phy/mdio-mux-mmioreg.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/mdio-mux-mmioreg.c b/drivers/net/phy/mdio-mux-mmioreg.c index 2377c1341172..7fde454fbc4f 100644 --- a/drivers/net/phy/mdio-mux-mmioreg.c +++ b/drivers/net/phy/mdio-mux-mmioreg.c @@ -113,12 +113,14 @@ static int mdio_mux_mmioreg_probe(struct platform_device *pdev) if (!iprop || len != sizeof(uint32_t)) { dev_err(&pdev->dev, "mdio-mux child node %s is " "missing a 'reg' property\n", np2->full_name); + of_node_put(np2); return -ENODEV; } if (be32_to_cpup(iprop) & ~s->mask) { dev_err(&pdev->dev, "mdio-mux child node %s has " "a 'reg' value with unmasked bits\n", np2->full_name); + of_node_put(np2); return -ENODEV; } } -- cgit v1.2.3 From 81a577034b000964ca791281a975f0ba9a9d7eed Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 25 Oct 2015 14:57:06 +0100 Subject: ath6kl: add missing of_node_put for_each_compatible_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ expression e; local idexpression n; @@ for_each_compatible_node(n,...) { ... when != of_node_put(n) when != e = n ( return n; | + of_node_put(n); ? return ...; ) ... } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/wireless/ath/ath6kl/init.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 6e473fa4b13c..12241b1c57cd 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -715,6 +715,7 @@ static bool check_device_tree(struct ath6kl *ar) board_filename, ret); continue; } + of_node_put(node); return true; } return false; -- cgit v1.2.3 From 26b7974d9ad7f93891ee8c39ee63bd2515da7744 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 25 Oct 2015 14:57:07 +0100 Subject: net: mv643xx_eth: add missing of_node_put for_each_available_child_of_node performs an of_node_get on each iteration, so a break out of the loop requires an of_node_put. A simplified version of the semantic patch that fixes this problem is as follows (http://coccinelle.lip6.fr): // @@ expression root,e; local idexpression child; @@ for_each_available_child_of_node(root, child) { ... when != of_node_put(child) when != e = child ( return child; | + of_node_put(child); ? return ...; ) ... } // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mv643xx_eth.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index e893a35143c5..dfb6d5f79a10 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -2817,8 +2817,10 @@ static int mv643xx_eth_shared_of_probe(struct platform_device *pdev) for_each_available_child_of_node(np, pnp) { ret = mv643xx_eth_shared_of_add_port(pdev, pnp); - if (ret) + if (ret) { + of_node_put(pnp); return ret; + } } return 0; } -- cgit v1.2.3 From 3821a065f5672c430a088ae68b4da2a2d2b34106 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Fri, 23 Oct 2015 08:59:11 -0500 Subject: spi: Drop owner assignment from spi_drivers An spi_driver does not need to set an owner, it will be populated by the driver core. Signed-off-by: Andrew F. Davis Acked-by: Jonathan Cameron Signed-off-by: Mark Brown --- drivers/net/can/spi/mcp251x.c | 1 - drivers/net/ethernet/micrel/ks8851.c | 1 - drivers/net/ethernet/microchip/enc28j60.c | 1 - drivers/net/ethernet/qualcomm/qca_spi.c | 1 - drivers/net/ieee802154/at86rf230.c | 1 - drivers/net/ieee802154/cc2520.c | 1 - drivers/net/ieee802154/mrf24j40.c | 1 - drivers/net/phy/spi_ks8995.c | 1 - drivers/net/wireless/cw1200/cw1200_spi.c | 1 - drivers/net/wireless/libertas/if_spi.c | 1 - drivers/net/wireless/p54/p54spi.c | 1 - drivers/net/wireless/ti/wl1251/spi.c | 1 - drivers/net/wireless/ti/wlcore/spi.c | 1 - 13 files changed, 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index b7e83c212023..575790e8a75a 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -1243,7 +1243,6 @@ static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend, static struct spi_driver mcp251x_can_driver = { .driver = { .name = DEVICE_NAME, - .owner = THIS_MODULE, .of_match_table = mcp251x_of_match, .pm = &mcp251x_can_pm_ops, }, diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index 66d4ab703f45..37b466a4841d 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -1606,7 +1606,6 @@ static struct spi_driver ks8851_driver = { .driver = { .name = "ks8851", .of_match_table = ks8851_match_table, - .owner = THIS_MODULE, .pm = &ks8851_pm_ops, }, .probe = ks8851_probe, diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c index b1b5f66b8b69..86ea17e7ba7b 100644 --- a/drivers/net/ethernet/microchip/enc28j60.c +++ b/drivers/net/ethernet/microchip/enc28j60.c @@ -1633,7 +1633,6 @@ static int enc28j60_remove(struct spi_device *spi) static struct spi_driver enc28j60_driver = { .driver = { .name = DRV_NAME, - .owner = THIS_MODULE, }, .probe = enc28j60_probe, .remove = enc28j60_remove, diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 2f87909f5186..ddb2c6c6ec94 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -974,7 +974,6 @@ MODULE_DEVICE_TABLE(spi, qca_spi_id); static struct spi_driver qca_spi_driver = { .driver = { .name = QCASPI_DRV_NAME, - .owner = THIS_MODULE, .of_match_table = qca_spi_of_match, }, .id_table = qca_spi_id, diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 6422caac8d40..46805ab0764f 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1763,7 +1763,6 @@ static struct spi_driver at86rf230_driver = { .driver = { .of_match_table = of_match_ptr(at86rf230_of_match), .name = "at86rf230", - .owner = THIS_MODULE, }, .probe = at86rf230_probe, .remove = at86rf230_remove, diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c index c5b54a15fc4c..e65b60591317 100644 --- a/drivers/net/ieee802154/cc2520.c +++ b/drivers/net/ieee802154/cc2520.c @@ -1152,7 +1152,6 @@ MODULE_DEVICE_TABLE(of, cc2520_of_ids); static struct spi_driver cc2520_driver = { .driver = { .name = "cc2520", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(cc2520_of_ids), }, .id_table = cc2520_ids, diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index 997724b8e434..e4c37d48add1 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -812,7 +812,6 @@ MODULE_DEVICE_TABLE(spi, mrf24j40_ids); static struct spi_driver mrf24j40_driver = { .driver = { .name = "mrf24j40", - .owner = THIS_MODULE, }, .id_table = mrf24j40_ids, .probe = mrf24j40_probe, diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index f091d691cf6f..c72c42206850 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -343,7 +343,6 @@ static int ks8995_remove(struct spi_device *spi) static struct spi_driver ks8995_driver = { .driver = { .name = "spi-ks8995", - .owner = THIS_MODULE, }, .probe = ks8995_probe, .remove = ks8995_remove, diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c index 29185aeccba8..a740083634d8 100644 --- a/drivers/net/wireless/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/cw1200/cw1200_spi.c @@ -467,7 +467,6 @@ static struct spi_driver spi_driver = { .remove = cw1200_spi_disconnect, .driver = { .name = "cw1200_wlan_spi", - .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &cw1200_pm_ops, #endif diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index f11728a866ff..82c0796377aa 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -1283,7 +1283,6 @@ static struct spi_driver libertas_spi_driver = { .remove = libertas_spi_remove, .driver = { .name = "libertas_spi", - .owner = THIS_MODULE, .pm = &if_spi_pm_ops, }, }; diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 63de5eed25cf..7ab2f43ab425 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -705,7 +705,6 @@ static int p54spi_remove(struct spi_device *spi) static struct spi_driver p54spi_driver = { .driver = { .name = "p54spi", - .owner = THIS_MODULE, }, .probe = p54spi_probe, diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c index 735be5352143..8de9d4444a6a 100644 --- a/drivers/net/wireless/ti/wl1251/spi.c +++ b/drivers/net/wireless/ti/wl1251/spi.c @@ -354,7 +354,6 @@ static int wl1251_spi_remove(struct spi_device *spi) static struct spi_driver wl1251_spi_driver = { .driver = { .name = DRIVER_NAME, - .owner = THIS_MODULE, }, .probe = wl1251_spi_probe, diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index f1ac2839d97c..236b41090827 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -408,7 +408,6 @@ static int wl1271_remove(struct spi_device *spi) static struct spi_driver wl1271_spi_driver = { .driver = { .name = "wl1271_spi", - .owner = THIS_MODULE, }, .probe = wl1271_probe, -- cgit v1.2.3 From fe56b9e6a8d957d6a20729d626027f800c17a2da Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Mon, 26 Oct 2015 11:02:25 +0200 Subject: qed: Add module with basic common support The Qlogic Everest Driver is the backend module for the QL4xxx ethernet products by Qlogic. This module serves two main purposes: 1. It's responsible to contain all the common code that will be shared between the various drivers that would be used with said line of products. Flows such as chip initialization and de-initialization fall under this category. 2. It would abstract the protocol-specific HW & FW components, allowing the protocol drivers to have a clean APIs which is detached in its slowpath configuration from the actual HSI. This adds a very basic module without any protocol-specific bits. I.e., this adds a basic implementation that almost entirely falls under the first category. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/Kconfig | 6 + drivers/net/ethernet/qlogic/Makefile | 1 + drivers/net/ethernet/qlogic/qed/Makefile | 4 + drivers/net/ethernet/qlogic/qed/qed.h | 448 ++ drivers/net/ethernet/qlogic/qed/qed_cxt.c | 847 ++++ drivers/net/ethernet/qlogic/qed/qed_cxt.h | 139 + drivers/net/ethernet/qlogic/qed/qed_dev.c | 1277 +++++ drivers/net/ethernet/qlogic/qed/qed_dev_api.h | 222 + drivers/net/ethernet/qlogic/qed/qed_hsi.h | 4966 ++++++++++++++++++++ drivers/net/ethernet/qlogic/qed/qed_hw.c | 776 +++ drivers/net/ethernet/qlogic/qed/qed_hw.h | 263 ++ .../net/ethernet/qlogic/qed/qed_init_fw_funcs.c | 798 ++++ drivers/net/ethernet/qlogic/qed/qed_init_ops.c | 531 +++ drivers/net/ethernet/qlogic/qed/qed_init_ops.h | 110 + drivers/net/ethernet/qlogic/qed/qed_int.c | 802 ++++ drivers/net/ethernet/qlogic/qed/qed_int.h | 391 ++ drivers/net/ethernet/qlogic/qed/qed_main.c | 948 ++++ drivers/net/ethernet/qlogic/qed/qed_mcp.c | 549 +++ drivers/net/ethernet/qlogic/qed/qed_mcp.h | 232 + drivers/net/ethernet/qlogic/qed/qed_reg_addr.h | 366 ++ drivers/net/ethernet/qlogic/qed/qed_sp.h | 333 ++ drivers/net/ethernet/qlogic/qed/qed_sp_commands.c | 170 + drivers/net/ethernet/qlogic/qed/qed_spq.c | 831 ++++ 23 files changed, 15010 insertions(+) create mode 100644 drivers/net/ethernet/qlogic/qed/Makefile create mode 100644 drivers/net/ethernet/qlogic/qed/qed.h create mode 100644 drivers/net/ethernet/qlogic/qed/qed_cxt.c create mode 100644 drivers/net/ethernet/qlogic/qed/qed_cxt.h create mode 100644 drivers/net/ethernet/qlogic/qed/qed_dev.c create mode 100644 drivers/net/ethernet/qlogic/qed/qed_dev_api.h create mode 100644 drivers/net/ethernet/qlogic/qed/qed_hsi.h create mode 100644 drivers/net/ethernet/qlogic/qed/qed_hw.c create mode 100644 drivers/net/ethernet/qlogic/qed/qed_hw.h create mode 100644 drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c create mode 100644 drivers/net/ethernet/qlogic/qed/qed_init_ops.c create mode 100644 drivers/net/ethernet/qlogic/qed/qed_init_ops.h create mode 100644 drivers/net/ethernet/qlogic/qed/qed_int.c create mode 100644 drivers/net/ethernet/qlogic/qed/qed_int.h create mode 100644 drivers/net/ethernet/qlogic/qed/qed_main.c create mode 100644 drivers/net/ethernet/qlogic/qed/qed_mcp.c create mode 100644 drivers/net/ethernet/qlogic/qed/qed_mcp.h create mode 100644 drivers/net/ethernet/qlogic/qed/qed_reg_addr.h create mode 100644 drivers/net/ethernet/qlogic/qed/qed_sp.h create mode 100644 drivers/net/ethernet/qlogic/qed/qed_sp_commands.c create mode 100644 drivers/net/ethernet/qlogic/qed/qed_spq.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig index f1f0108c275d..58c3fb388f46 100644 --- a/drivers/net/ethernet/qlogic/Kconfig +++ b/drivers/net/ethernet/qlogic/Kconfig @@ -91,4 +91,10 @@ config NETXEN_NIC ---help--- This enables the support for NetXen's Gigabit Ethernet card. +config QED + tristate "QLogic QED 25/40/100Gb core driver" + depends on PCI + ---help--- + This enables the support for ... + endif # NET_VENDOR_QLOGIC diff --git a/drivers/net/ethernet/qlogic/Makefile b/drivers/net/ethernet/qlogic/Makefile index b2a283d9ae60..7600138268ee 100644 --- a/drivers/net/ethernet/qlogic/Makefile +++ b/drivers/net/ethernet/qlogic/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_QLA3XXX) += qla3xxx.o obj-$(CONFIG_QLCNIC) += qlcnic/ obj-$(CONFIG_QLGE) += qlge/ obj-$(CONFIG_NETXEN_NIC) += netxen/ +obj-$(CONFIG_QED) += qed/ diff --git a/drivers/net/ethernet/qlogic/qed/Makefile b/drivers/net/ethernet/qlogic/qed/Makefile new file mode 100644 index 000000000000..6969b5c66929 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_QED) := qed.o + +qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o qed_init_ops.o \ + qed_int.o qed_main.o qed_mcp.o qed_sp_commands.o qed_spq.o diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h new file mode 100644 index 000000000000..a63ef3120d78 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -0,0 +1,448 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#ifndef _QED_H +#define _QED_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qed_hsi.h" + +#define DRV_MODULE_VERSION "8.4.0.0" + +#define MAX_HWFNS_PER_DEVICE (4) +#define NAME_SIZE 16 +#define VER_SIZE 16 + +/* cau states */ +enum qed_coalescing_mode { + QED_COAL_MODE_DISABLE, + QED_COAL_MODE_ENABLE +}; + +struct qed_eth_cb_ops; +struct qed_dev_info; + +/* helpers */ +static inline u32 qed_db_addr(u32 cid, u32 DEMS) +{ + u32 db_addr = FIELD_VALUE(DB_LEGACY_ADDR_DEMS, DEMS) | + FIELD_VALUE(DB_LEGACY_ADDR_ICID, cid); + + return db_addr; +} + +#define ALIGNED_TYPE_SIZE(type_name, p_hwfn) \ + ((sizeof(type_name) + (u32)(1 << (p_hwfn->cdev->cache_shift)) - 1) & \ + ~((1 << (p_hwfn->cdev->cache_shift)) - 1)) + +#define for_each_hwfn(cdev, i) for (i = 0; i < cdev->num_hwfns; i++) + +#define D_TRINE(val, cond1, cond2, true1, true2, def) \ + (val == (cond1) ? true1 : \ + (val == (cond2) ? true2 : def)) + +/* forward */ +struct qed_ptt_pool; +struct qed_spq; +struct qed_sb_info; +struct qed_sb_attn_info; +struct qed_cxt_mngr; +struct qed_sb_sp_info; +struct qed_mcp_info; + +struct qed_rt_data { + u32 init_val; + bool b_valid; +}; + +/* The PCI personality is not quite synonymous to protocol ID: + * 1. All personalities need CORE connections + * 2. The Ethernet personality may support also the RoCE protocol + */ +enum qed_pci_personality { + QED_PCI_ETH, + QED_PCI_DEFAULT /* default in shmem */ +}; + +/* All VFs are symmetric, all counters are PF + all VFs */ +struct qed_qm_iids { + u32 cids; + u32 vf_cids; + u32 tids; +}; + +enum QED_RESOURCES { + QED_SB, + QED_VPORT, + QED_PQ, + QED_RL, + QED_ILT, + QED_MAX_RESC, +}; + +struct qed_hw_info { + /* PCI personality */ + enum qed_pci_personality personality; + + /* Resource Allocation scheme results */ + u32 resc_start[QED_MAX_RESC]; + u32 resc_num[QED_MAX_RESC]; + +#define RESC_START(_p_hwfn, resc) ((_p_hwfn)->hw_info.resc_start[resc]) +#define RESC_NUM(_p_hwfn, resc) ((_p_hwfn)->hw_info.resc_num[resc]) +#define FEAT_NUM(_p_hwfn, resc) ((_p_hwfn)->hw_info.feat_num[resc]) + + u8 num_tc; + u8 offload_tc; + u8 non_offload_tc; + + u32 concrete_fid; + u16 opaque_fid; + u16 ovlan; + u32 part_num[4]; + + u32 vendor_id; + u32 device_id; + + unsigned char hw_mac_addr[ETH_ALEN]; + + struct qed_igu_info *p_igu_info; + + u32 port_mode; + u32 hw_mode; +}; + +struct qed_hw_cid_data { + u32 cid; + bool b_cid_allocated; + + /* Additional identifiers */ + u16 opaque_fid; + u8 vport_id; +}; + +/* maximun size of read/write commands (HW limit) */ +#define DMAE_MAX_RW_SIZE 0x2000 + +struct qed_dmae_info { + /* Mutex for synchronizing access to functions */ + struct mutex mutex; + + u8 channel; + + dma_addr_t completion_word_phys_addr; + + /* The memory location where the DMAE writes the completion + * value when an operation is finished on this context. + */ + u32 *p_completion_word; + + dma_addr_t intermediate_buffer_phys_addr; + + /* An intermediate buffer for DMAE operations that use virtual + * addresses - data is DMA'd to/from this buffer and then + * memcpy'd to/from the virtual address + */ + u32 *p_intermediate_buffer; + + dma_addr_t dmae_cmd_phys_addr; + struct dmae_cmd *p_dmae_cmd; +}; + +struct qed_qm_info { + struct init_qm_pq_params *qm_pq_params; + struct init_qm_vport_params *qm_vport_params; + struct init_qm_port_params *qm_port_params; + u16 start_pq; + u8 start_vport; + u8 pure_lb_pq; + u8 offload_pq; + u8 pure_ack_pq; + u8 vf_queues_offset; + u16 num_pqs; + u16 num_vf_pqs; + u8 num_vports; + u8 max_phys_tcs_per_port; + bool pf_rl_en; + bool pf_wfq_en; + bool vport_rl_en; + bool vport_wfq_en; + u8 pf_wfq; + u32 pf_rl; +}; + +struct qed_fw_data { + const u8 *modes_tree_buf; + union init_op *init_ops; + const u32 *arr_data; + u32 init_ops_size; +}; + +struct qed_simd_fp_handler { + void *token; + void (*func)(void *); +}; + +struct qed_hwfn { + struct qed_dev *cdev; + u8 my_id; /* ID inside the PF */ +#define IS_LEAD_HWFN(edev) (!((edev)->my_id)) + u8 rel_pf_id; /* Relative to engine*/ + u8 abs_pf_id; +#define QED_PATH_ID(_p_hwfn) ((_p_hwfn)->abs_pf_id & 1) + u8 port_id; + bool b_active; + + u32 dp_module; + u8 dp_level; + char name[NAME_SIZE]; + + bool first_on_engine; + bool hw_init_done; + + /* BAR access */ + void __iomem *regview; + void __iomem *doorbells; + u64 db_phys_addr; + unsigned long db_size; + + /* PTT pool */ + struct qed_ptt_pool *p_ptt_pool; + + /* HW info */ + struct qed_hw_info hw_info; + + /* rt_array (for init-tool) */ + struct qed_rt_data *rt_data; + + /* SPQ */ + struct qed_spq *p_spq; + + /* EQ */ + struct qed_eq *p_eq; + + /* Consolidate Q*/ + struct qed_consq *p_consq; + + /* Slow-Path definitions */ + struct tasklet_struct *sp_dpc; + bool b_sp_dpc_enabled; + + struct qed_ptt *p_main_ptt; + struct qed_ptt *p_dpc_ptt; + + struct qed_sb_sp_info *p_sp_sb; + struct qed_sb_attn_info *p_sb_attn; + + /* Protocol related */ + struct qed_pf_params pf_params; + + /* Array of sb_info of all status blocks */ + struct qed_sb_info *sbs_info[MAX_SB_PER_PF_MIMD]; + u16 num_sbs; + + struct qed_cxt_mngr *p_cxt_mngr; + + /* Flag indicating whether interrupts are enabled or not*/ + bool b_int_enabled; + + struct qed_mcp_info *mcp_info; + + struct qed_dmae_info dmae_info; + + /* QM init */ + struct qed_qm_info qm_info; + + /* Buffer for unzipping firmware data */ + void *unzip_buf; + + struct qed_simd_fp_handler simd_proto_handler[64]; + + struct z_stream_s *stream; +}; + +struct pci_params { + int pm_cap; + + unsigned long mem_start; + unsigned long mem_end; + unsigned int irq; + u8 pf_num; +}; + +struct qed_int_param { + u32 int_mode; + u8 num_vectors; + u8 min_msix_cnt; /* for minimal functionality */ +}; + +struct qed_int_params { + struct qed_int_param in; + struct qed_int_param out; + struct msix_entry *msix_table; + bool fp_initialized; + u8 fp_msix_base; + u8 fp_msix_cnt; +}; + +struct qed_dev { + u32 dp_module; + u8 dp_level; + char name[NAME_SIZE]; + + u8 type; +#define QED_DEV_TYPE_BB_A0 (0 << 0) +#define QED_DEV_TYPE_MASK (0x3) +#define QED_DEV_TYPE_SHIFT (0) + + u16 chip_num; +#define CHIP_NUM_MASK 0xffff +#define CHIP_NUM_SHIFT 16 + + u16 chip_rev; +#define CHIP_REV_MASK 0xf +#define CHIP_REV_SHIFT 12 + + u16 chip_metal; +#define CHIP_METAL_MASK 0xff +#define CHIP_METAL_SHIFT 4 + + u16 chip_bond_id; +#define CHIP_BOND_ID_MASK 0xf +#define CHIP_BOND_ID_SHIFT 0 + + u8 num_engines; + u8 num_ports_in_engines; + u8 num_funcs_in_port; + + u8 path_id; + enum mf_mode mf_mode; +#define IS_MF(_p_hwfn) (((_p_hwfn)->cdev)->mf_mode != SF) +#define IS_MF_SI(_p_hwfn) (((_p_hwfn)->cdev)->mf_mode == MF_NPAR) +#define IS_MF_SD(_p_hwfn) (((_p_hwfn)->cdev)->mf_mode == MF_OVLAN) + + int pcie_width; + int pcie_speed; + u8 ver_str[VER_SIZE]; + + /* Add MF related configuration */ + u8 mcp_rev; + u8 boot_mode; + + u8 wol; + + u32 int_mode; + enum qed_coalescing_mode int_coalescing_mode; + u8 rx_coalesce_usecs; + u8 tx_coalesce_usecs; + + /* Start Bar offset of first hwfn */ + void __iomem *regview; + void __iomem *doorbells; + u64 db_phys_addr; + unsigned long db_size; + + /* PCI */ + u8 cache_shift; + + /* Init */ + const struct iro *iro_arr; +#define IRO (p_hwfn->cdev->iro_arr) + + /* HW functions */ + u8 num_hwfns; + struct qed_hwfn hwfns[MAX_HWFNS_PER_DEVICE]; + + u32 drv_type; + + struct qed_eth_stats *reset_stats; + struct qed_fw_data *fw_data; + + u32 mcp_nvm_resp; + + /* Linux specific here */ + struct qede_dev *edev; + struct pci_dev *pdev; + int msg_enable; + + struct pci_params pci_params; + + struct qed_int_params int_params; + + u8 protocol; +#define IS_QED_ETH_IF(cdev) ((cdev)->protocol == QED_PROTOCOL_ETH) + + const struct firmware *firmware; +}; + +#define QED_GET_TYPE(dev) (((dev)->type & QED_DEV_TYPE_MASK) >> \ + QED_DEV_TYPE_SHIFT) +#define QED_IS_BB_A0(dev) (QED_GET_TYPE(dev) == QED_DEV_TYPE_BB_A0) +#define QED_IS_BB(dev) (QED_IS_BB_A0(dev)) + +#define NUM_OF_SBS(dev) MAX_SB_PER_PATH_BB +#define NUM_OF_ENG_PFS(dev) MAX_NUM_PFS_BB + +/** + * @brief qed_concrete_to_sw_fid - get the sw function id from + * the concrete value. + * + * @param concrete_fid + * + * @return inline u8 + */ +static inline u8 qed_concrete_to_sw_fid(struct qed_dev *cdev, + u32 concrete_fid) +{ + u8 pfid = GET_FIELD(concrete_fid, PXP_CONCRETE_FID_PFID); + + return pfid; +} + +#define PURE_LB_TC 8 + +#define QED_LEADING_HWFN(dev) (&dev->hwfns[0]) + +/* Other Linux specific common definitions */ +#define DP_NAME(cdev) ((cdev)->name) + +#define REG_ADDR(cdev, offset) (void __iomem *)((u8 __iomem *)\ + (cdev->regview) + \ + (offset)) + +#define REG_RD(cdev, offset) readl(REG_ADDR(cdev, offset)) +#define REG_WR(cdev, offset, val) writel((u32)val, REG_ADDR(cdev, offset)) +#define REG_WR16(cdev, offset, val) writew((u16)val, REG_ADDR(cdev, offset)) + +#define DOORBELL(cdev, db_addr, val) \ + writel((u32)val, (void __iomem *)((u8 __iomem *)\ + (cdev->doorbells) + (db_addr))) + +/* Prototypes */ +int qed_fill_dev_info(struct qed_dev *cdev, + struct qed_dev_info *dev_info); +u32 qed_unzip_data(struct qed_hwfn *p_hwfn, + u32 input_len, u8 *input_buf, + u32 max_size, u8 *unzip_buf); + +#define QED_ETH_INTERFACE_VERSION 300 + +#endif /* _QED_H */ diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c new file mode 100644 index 000000000000..7ccdb46c6764 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c @@ -0,0 +1,847 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qed.h" +#include "qed_cxt.h" +#include "qed_dev_api.h" +#include "qed_hsi.h" +#include "qed_hw.h" +#include "qed_init_ops.h" +#include "qed_reg_addr.h" + +/* Max number of connection types in HW (DQ/CDU etc.) */ +#define MAX_CONN_TYPES PROTOCOLID_COMMON +#define NUM_TASK_TYPES 2 +#define NUM_TASK_PF_SEGMENTS 4 + +/* QM constants */ +#define QM_PQ_ELEMENT_SIZE 4 /* in bytes */ + +/* Doorbell-Queue constants */ +#define DQ_RANGE_SHIFT 4 +#define DQ_RANGE_ALIGN BIT(DQ_RANGE_SHIFT) + +/* ILT constants */ +#define ILT_DEFAULT_HW_P_SIZE 3 +#define ILT_PAGE_IN_BYTES(hw_p_size) (1U << ((hw_p_size) + 12)) +#define ILT_CFG_REG(cli, reg) PSWRQ2_REG_ ## cli ## _ ## reg ## _RT_OFFSET + +/* ILT entry structure */ +#define ILT_ENTRY_PHY_ADDR_MASK 0x000FFFFFFFFFFFULL +#define ILT_ENTRY_PHY_ADDR_SHIFT 0 +#define ILT_ENTRY_VALID_MASK 0x1ULL +#define ILT_ENTRY_VALID_SHIFT 52 +#define ILT_ENTRY_IN_REGS 2 +#define ILT_REG_SIZE_IN_BYTES 4 + +/* connection context union */ +union conn_context { + struct core_conn_context core_ctx; + struct eth_conn_context eth_ctx; +}; + +#define CONN_CXT_SIZE(p_hwfn) \ + ALIGNED_TYPE_SIZE(union conn_context, p_hwfn) + +/* PF per protocl configuration object */ +struct qed_conn_type_cfg { + u32 cid_count; + u32 cid_start; +}; + +/* ILT Client configuration, Per connection type (protocol) resources. */ +#define ILT_CLI_PF_BLOCKS (1 + NUM_TASK_PF_SEGMENTS * 2) +#define CDUC_BLK (0) + +enum ilt_clients { + ILT_CLI_CDUC, + ILT_CLI_QM, + ILT_CLI_MAX +}; + +struct ilt_cfg_pair { + u32 reg; + u32 val; +}; + +struct qed_ilt_cli_blk { + u32 total_size; /* 0 means not active */ + u32 real_size_in_page; + u32 start_line; +}; + +struct qed_ilt_client_cfg { + bool active; + + /* ILT boundaries */ + struct ilt_cfg_pair first; + struct ilt_cfg_pair last; + struct ilt_cfg_pair p_size; + + /* ILT client blocks for PF */ + struct qed_ilt_cli_blk pf_blks[ILT_CLI_PF_BLOCKS]; + u32 pf_total_lines; +}; + +/* Per Path - + * ILT shadow table + * Protocol acquired CID lists + * PF start line in ILT + */ +struct qed_dma_mem { + dma_addr_t p_phys; + void *p_virt; + size_t size; +}; + +struct qed_cid_acquired_map { + u32 start_cid; + u32 max_count; + unsigned long *cid_map; +}; + +struct qed_cxt_mngr { + /* Per protocl configuration */ + struct qed_conn_type_cfg conn_cfg[MAX_CONN_TYPES]; + + /* computed ILT structure */ + struct qed_ilt_client_cfg clients[ILT_CLI_MAX]; + + /* Acquired CIDs */ + struct qed_cid_acquired_map acquired[MAX_CONN_TYPES]; + + /* ILT shadow table */ + struct qed_dma_mem *ilt_shadow; + u32 pf_start_line; +}; + +static u32 qed_cxt_cdu_iids(struct qed_cxt_mngr *p_mngr) +{ + u32 type, pf_cids = 0; + + for (type = 0; type < MAX_CONN_TYPES; type++) + pf_cids += p_mngr->conn_cfg[type].cid_count; + + return pf_cids; +} + +static void qed_cxt_qm_iids(struct qed_hwfn *p_hwfn, + struct qed_qm_iids *iids) +{ + struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; + int type; + + for (type = 0; type < MAX_CONN_TYPES; type++) + iids->cids += p_mngr->conn_cfg[type].cid_count; + + DP_VERBOSE(p_hwfn, QED_MSG_ILT, "iids: CIDS %08x\n", iids->cids); +} + +/* set the iids count per protocol */ +static void qed_cxt_set_proto_cid_count(struct qed_hwfn *p_hwfn, + enum protocol_type type, + u32 cid_count) +{ + struct qed_cxt_mngr *p_mgr = p_hwfn->p_cxt_mngr; + struct qed_conn_type_cfg *p_conn = &p_mgr->conn_cfg[type]; + + p_conn->cid_count = roundup(cid_count, DQ_RANGE_ALIGN); +} + +static void qed_ilt_cli_blk_fill(struct qed_ilt_client_cfg *p_cli, + struct qed_ilt_cli_blk *p_blk, + u32 start_line, u32 total_size, + u32 elem_size) +{ + u32 ilt_size = ILT_PAGE_IN_BYTES(p_cli->p_size.val); + + /* verify thatits called only once for each block */ + if (p_blk->total_size) + return; + + p_blk->total_size = total_size; + p_blk->real_size_in_page = 0; + if (elem_size) + p_blk->real_size_in_page = (ilt_size / elem_size) * elem_size; + p_blk->start_line = start_line; +} + +static void qed_ilt_cli_adv_line(struct qed_hwfn *p_hwfn, + struct qed_ilt_client_cfg *p_cli, + struct qed_ilt_cli_blk *p_blk, + u32 *p_line, enum ilt_clients client_id) +{ + if (!p_blk->total_size) + return; + + if (!p_cli->active) + p_cli->first.val = *p_line; + + p_cli->active = true; + *p_line += DIV_ROUND_UP(p_blk->total_size, + p_blk->real_size_in_page); + p_cli->last.val = *p_line - 1; + + DP_VERBOSE(p_hwfn, QED_MSG_ILT, + "ILT[Client %d] - Lines: [%08x - %08x]. Block - Size %08x [Real %08x] Start line %d\n", + client_id, p_cli->first.val, + p_cli->last.val, p_blk->total_size, + p_blk->real_size_in_page, p_blk->start_line); +} + +int qed_cxt_cfg_ilt_compute(struct qed_hwfn *p_hwfn) +{ + struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; + struct qed_ilt_client_cfg *p_cli; + struct qed_ilt_cli_blk *p_blk; + u32 curr_line, total, pf_cids; + struct qed_qm_iids qm_iids; + + memset(&qm_iids, 0, sizeof(qm_iids)); + + p_mngr->pf_start_line = RESC_START(p_hwfn, QED_ILT); + + DP_VERBOSE(p_hwfn, QED_MSG_ILT, + "hwfn [%d] - Set context manager starting line to be 0x%08x\n", + p_hwfn->my_id, p_hwfn->p_cxt_mngr->pf_start_line); + + /* CDUC */ + p_cli = &p_mngr->clients[ILT_CLI_CDUC]; + curr_line = p_mngr->pf_start_line; + p_cli->pf_total_lines = 0; + + /* get the counters for the CDUC and QM clients */ + pf_cids = qed_cxt_cdu_iids(p_mngr); + + p_blk = &p_cli->pf_blks[CDUC_BLK]; + + total = pf_cids * CONN_CXT_SIZE(p_hwfn); + + qed_ilt_cli_blk_fill(p_cli, p_blk, curr_line, + total, CONN_CXT_SIZE(p_hwfn)); + + qed_ilt_cli_adv_line(p_hwfn, p_cli, p_blk, &curr_line, ILT_CLI_CDUC); + p_cli->pf_total_lines = curr_line - p_blk->start_line; + + /* QM */ + p_cli = &p_mngr->clients[ILT_CLI_QM]; + p_blk = &p_cli->pf_blks[0]; + + qed_cxt_qm_iids(p_hwfn, &qm_iids); + total = qed_qm_pf_mem_size(p_hwfn->rel_pf_id, qm_iids.cids, 0, 0, + p_hwfn->qm_info.num_pqs, 0); + + DP_VERBOSE(p_hwfn, QED_MSG_ILT, + "QM ILT Info, (cids=%d, num_pqs=%d, memory_size=%d)\n", + qm_iids.cids, p_hwfn->qm_info.num_pqs, total); + + qed_ilt_cli_blk_fill(p_cli, p_blk, + curr_line, total * 0x1000, + QM_PQ_ELEMENT_SIZE); + + qed_ilt_cli_adv_line(p_hwfn, p_cli, p_blk, &curr_line, ILT_CLI_QM); + p_cli->pf_total_lines = curr_line - p_blk->start_line; + + if (curr_line - p_hwfn->p_cxt_mngr->pf_start_line > + RESC_NUM(p_hwfn, QED_ILT)) { + DP_ERR(p_hwfn, "too many ilt lines...#lines=%d\n", + curr_line - p_hwfn->p_cxt_mngr->pf_start_line); + return -EINVAL; + } + + return 0; +} + +#define for_each_ilt_valid_client(pos, clients) \ + for (pos = 0; pos < ILT_CLI_MAX; pos++) + +/* Total number of ILT lines used by this PF */ +static u32 qed_cxt_ilt_shadow_size(struct qed_ilt_client_cfg *ilt_clients) +{ + u32 size = 0; + u32 i; + + for_each_ilt_valid_client(i, ilt_clients) { + if (!ilt_clients[i].active) + continue; + size += (ilt_clients[i].last.val - + ilt_clients[i].first.val + 1); + } + + return size; +} + +static void qed_ilt_shadow_free(struct qed_hwfn *p_hwfn) +{ + struct qed_ilt_client_cfg *p_cli = p_hwfn->p_cxt_mngr->clients; + struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; + u32 ilt_size, i; + + ilt_size = qed_cxt_ilt_shadow_size(p_cli); + + for (i = 0; p_mngr->ilt_shadow && i < ilt_size; i++) { + struct qed_dma_mem *p_dma = &p_mngr->ilt_shadow[i]; + + if (p_dma->p_virt) + dma_free_coherent(&p_hwfn->cdev->pdev->dev, + p_dma->size, p_dma->p_virt, + p_dma->p_phys); + p_dma->p_virt = NULL; + } + kfree(p_mngr->ilt_shadow); +} + +static int qed_ilt_blk_alloc(struct qed_hwfn *p_hwfn, + struct qed_ilt_cli_blk *p_blk, + enum ilt_clients ilt_client, + u32 start_line_offset) +{ + struct qed_dma_mem *ilt_shadow = p_hwfn->p_cxt_mngr->ilt_shadow; + u32 lines, line, sz_left; + + if (!p_blk->total_size) + return 0; + + sz_left = p_blk->total_size; + lines = DIV_ROUND_UP(sz_left, p_blk->real_size_in_page); + line = p_blk->start_line + start_line_offset - + p_hwfn->p_cxt_mngr->pf_start_line; + + for (; lines; lines--) { + dma_addr_t p_phys; + void *p_virt; + u32 size; + + size = min_t(u32, sz_left, + p_blk->real_size_in_page); + p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, + size, + &p_phys, + GFP_KERNEL); + if (!p_virt) + return -ENOMEM; + memset(p_virt, 0, size); + + ilt_shadow[line].p_phys = p_phys; + ilt_shadow[line].p_virt = p_virt; + ilt_shadow[line].size = size; + + DP_VERBOSE(p_hwfn, QED_MSG_ILT, + "ILT shadow: Line [%d] Physical 0x%llx Virtual %p Size %d\n", + line, (u64)p_phys, p_virt, size); + + sz_left -= size; + line++; + } + + return 0; +} + +static int qed_ilt_shadow_alloc(struct qed_hwfn *p_hwfn) +{ + struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; + struct qed_ilt_client_cfg *clients = p_mngr->clients; + struct qed_ilt_cli_blk *p_blk; + u32 size, i, j; + int rc; + + size = qed_cxt_ilt_shadow_size(clients); + p_mngr->ilt_shadow = kcalloc(size, sizeof(struct qed_dma_mem), + GFP_KERNEL); + if (!p_mngr->ilt_shadow) { + DP_NOTICE(p_hwfn, "Failed to allocate ilt shadow table\n"); + rc = -ENOMEM; + goto ilt_shadow_fail; + } + + DP_VERBOSE(p_hwfn, QED_MSG_ILT, + "Allocated 0x%x bytes for ilt shadow\n", + (u32)(size * sizeof(struct qed_dma_mem))); + + for_each_ilt_valid_client(i, clients) { + if (!clients[i].active) + continue; + for (j = 0; j < ILT_CLI_PF_BLOCKS; j++) { + p_blk = &clients[i].pf_blks[j]; + rc = qed_ilt_blk_alloc(p_hwfn, p_blk, i, 0); + if (rc != 0) + goto ilt_shadow_fail; + } + } + + return 0; + +ilt_shadow_fail: + qed_ilt_shadow_free(p_hwfn); + return rc; +} + +static void qed_cid_map_free(struct qed_hwfn *p_hwfn) +{ + struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; + u32 type; + + for (type = 0; type < MAX_CONN_TYPES; type++) { + kfree(p_mngr->acquired[type].cid_map); + p_mngr->acquired[type].max_count = 0; + p_mngr->acquired[type].start_cid = 0; + } +} + +static int qed_cid_map_alloc(struct qed_hwfn *p_hwfn) +{ + struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; + u32 start_cid = 0; + u32 type; + + for (type = 0; type < MAX_CONN_TYPES; type++) { + u32 cid_cnt = p_hwfn->p_cxt_mngr->conn_cfg[type].cid_count; + u32 size; + + if (cid_cnt == 0) + continue; + + size = DIV_ROUND_UP(cid_cnt, + sizeof(unsigned long) * BITS_PER_BYTE) * + sizeof(unsigned long); + p_mngr->acquired[type].cid_map = kzalloc(size, GFP_KERNEL); + if (!p_mngr->acquired[type].cid_map) + goto cid_map_fail; + + p_mngr->acquired[type].max_count = cid_cnt; + p_mngr->acquired[type].start_cid = start_cid; + + p_hwfn->p_cxt_mngr->conn_cfg[type].cid_start = start_cid; + + DP_VERBOSE(p_hwfn, QED_MSG_CXT, + "Type %08x start: %08x count %08x\n", + type, p_mngr->acquired[type].start_cid, + p_mngr->acquired[type].max_count); + start_cid += cid_cnt; + } + + return 0; + +cid_map_fail: + qed_cid_map_free(p_hwfn); + return -ENOMEM; +} + +int qed_cxt_mngr_alloc(struct qed_hwfn *p_hwfn) +{ + struct qed_cxt_mngr *p_mngr; + u32 i; + + p_mngr = kzalloc(sizeof(*p_mngr), GFP_ATOMIC); + if (!p_mngr) { + DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_cxt_mngr'\n"); + return -ENOMEM; + } + + /* Initialize ILT client registers */ + p_mngr->clients[ILT_CLI_CDUC].first.reg = ILT_CFG_REG(CDUC, FIRST_ILT); + p_mngr->clients[ILT_CLI_CDUC].last.reg = ILT_CFG_REG(CDUC, LAST_ILT); + p_mngr->clients[ILT_CLI_CDUC].p_size.reg = ILT_CFG_REG(CDUC, P_SIZE); + + p_mngr->clients[ILT_CLI_QM].first.reg = ILT_CFG_REG(QM, FIRST_ILT); + p_mngr->clients[ILT_CLI_QM].last.reg = ILT_CFG_REG(QM, LAST_ILT); + p_mngr->clients[ILT_CLI_QM].p_size.reg = ILT_CFG_REG(QM, P_SIZE); + + /* default ILT page size for all clients is 32K */ + for (i = 0; i < ILT_CLI_MAX; i++) + p_mngr->clients[i].p_size.val = ILT_DEFAULT_HW_P_SIZE; + + /* Set the cxt mangr pointer priori to further allocations */ + p_hwfn->p_cxt_mngr = p_mngr; + + return 0; +} + +int qed_cxt_tables_alloc(struct qed_hwfn *p_hwfn) +{ + int rc; + + /* Allocate the ILT shadow table */ + rc = qed_ilt_shadow_alloc(p_hwfn); + if (rc) { + DP_NOTICE(p_hwfn, "Failed to allocate ilt memory\n"); + goto tables_alloc_fail; + } + + /* Allocate and initialize the acquired cids bitmaps */ + rc = qed_cid_map_alloc(p_hwfn); + if (rc) { + DP_NOTICE(p_hwfn, "Failed to allocate cid maps\n"); + goto tables_alloc_fail; + } + + return 0; + +tables_alloc_fail: + qed_cxt_mngr_free(p_hwfn); + return rc; +} + +void qed_cxt_mngr_free(struct qed_hwfn *p_hwfn) +{ + if (!p_hwfn->p_cxt_mngr) + return; + + qed_cid_map_free(p_hwfn); + qed_ilt_shadow_free(p_hwfn); + kfree(p_hwfn->p_cxt_mngr); + + p_hwfn->p_cxt_mngr = NULL; +} + +void qed_cxt_mngr_setup(struct qed_hwfn *p_hwfn) +{ + struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; + int type; + + /* Reset acquired cids */ + for (type = 0; type < MAX_CONN_TYPES; type++) { + u32 cid_cnt = p_hwfn->p_cxt_mngr->conn_cfg[type].cid_count; + + if (cid_cnt == 0) + continue; + + memset(p_mngr->acquired[type].cid_map, 0, + DIV_ROUND_UP(cid_cnt, + sizeof(unsigned long) * BITS_PER_BYTE) * + sizeof(unsigned long)); + } +} + +/* CDU Common */ +#define CDUC_CXT_SIZE_SHIFT \ + CDU_REG_CID_ADDR_PARAMS_CONTEXT_SIZE_SHIFT + +#define CDUC_CXT_SIZE_MASK \ + (CDU_REG_CID_ADDR_PARAMS_CONTEXT_SIZE >> CDUC_CXT_SIZE_SHIFT) + +#define CDUC_BLOCK_WASTE_SHIFT \ + CDU_REG_CID_ADDR_PARAMS_BLOCK_WASTE_SHIFT + +#define CDUC_BLOCK_WASTE_MASK \ + (CDU_REG_CID_ADDR_PARAMS_BLOCK_WASTE >> CDUC_BLOCK_WASTE_SHIFT) + +#define CDUC_NCIB_SHIFT \ + CDU_REG_CID_ADDR_PARAMS_NCIB_SHIFT + +#define CDUC_NCIB_MASK \ + (CDU_REG_CID_ADDR_PARAMS_NCIB >> CDUC_NCIB_SHIFT) + +static void qed_cdu_init_common(struct qed_hwfn *p_hwfn) +{ + u32 page_sz, elems_per_page, block_waste, cxt_size, cdu_params = 0; + + /* CDUC - connection configuration */ + page_sz = p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUC].p_size.val; + cxt_size = CONN_CXT_SIZE(p_hwfn); + elems_per_page = ILT_PAGE_IN_BYTES(page_sz) / cxt_size; + block_waste = ILT_PAGE_IN_BYTES(page_sz) - elems_per_page * cxt_size; + + SET_FIELD(cdu_params, CDUC_CXT_SIZE, cxt_size); + SET_FIELD(cdu_params, CDUC_BLOCK_WASTE, block_waste); + SET_FIELD(cdu_params, CDUC_NCIB, elems_per_page); + STORE_RT_REG(p_hwfn, CDU_REG_CID_ADDR_PARAMS_RT_OFFSET, cdu_params); +} + +void qed_qm_init_pf(struct qed_hwfn *p_hwfn) +{ + struct qed_qm_pf_rt_init_params params; + struct qed_qm_info *qm_info = &p_hwfn->qm_info; + struct qed_qm_iids iids; + + memset(&iids, 0, sizeof(iids)); + qed_cxt_qm_iids(p_hwfn, &iids); + + memset(¶ms, 0, sizeof(params)); + params.port_id = p_hwfn->port_id; + params.pf_id = p_hwfn->rel_pf_id; + params.max_phys_tcs_per_port = qm_info->max_phys_tcs_per_port; + params.is_first_pf = p_hwfn->first_on_engine; + params.num_pf_cids = iids.cids; + params.start_pq = qm_info->start_pq; + params.num_pf_pqs = qm_info->num_pqs; + params.start_vport = qm_info->num_vports; + params.pf_wfq = qm_info->pf_wfq; + params.pf_rl = qm_info->pf_rl; + params.pq_params = qm_info->qm_pq_params; + params.vport_params = qm_info->qm_vport_params; + + qed_qm_pf_rt_init(p_hwfn, p_hwfn->p_main_ptt, ¶ms); +} + +/* CM PF */ +static int qed_cm_init_pf(struct qed_hwfn *p_hwfn) +{ + union qed_qm_pq_params pq_params; + u16 pq; + + /* XCM pure-LB queue */ + memset(&pq_params, 0, sizeof(pq_params)); + pq_params.core.tc = LB_TC; + pq = qed_get_qm_pq(p_hwfn, PROTOCOLID_CORE, &pq_params); + STORE_RT_REG(p_hwfn, XCM_REG_CON_PHY_Q3_RT_OFFSET, pq); + + return 0; +} + +/* DQ PF */ +static void qed_dq_init_pf(struct qed_hwfn *p_hwfn) +{ + struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; + u32 dq_pf_max_cid = 0; + + dq_pf_max_cid += (p_mngr->conn_cfg[0].cid_count >> DQ_RANGE_SHIFT); + STORE_RT_REG(p_hwfn, DORQ_REG_PF_MAX_ICID_0_RT_OFFSET, dq_pf_max_cid); + + dq_pf_max_cid += (p_mngr->conn_cfg[1].cid_count >> DQ_RANGE_SHIFT); + STORE_RT_REG(p_hwfn, DORQ_REG_PF_MAX_ICID_1_RT_OFFSET, dq_pf_max_cid); + + dq_pf_max_cid += (p_mngr->conn_cfg[2].cid_count >> DQ_RANGE_SHIFT); + STORE_RT_REG(p_hwfn, DORQ_REG_PF_MAX_ICID_2_RT_OFFSET, dq_pf_max_cid); + + dq_pf_max_cid += (p_mngr->conn_cfg[3].cid_count >> DQ_RANGE_SHIFT); + STORE_RT_REG(p_hwfn, DORQ_REG_PF_MAX_ICID_3_RT_OFFSET, dq_pf_max_cid); + + dq_pf_max_cid += (p_mngr->conn_cfg[4].cid_count >> DQ_RANGE_SHIFT); + STORE_RT_REG(p_hwfn, DORQ_REG_PF_MAX_ICID_4_RT_OFFSET, dq_pf_max_cid); + + /* 5 - PF */ + dq_pf_max_cid += (p_mngr->conn_cfg[5].cid_count >> DQ_RANGE_SHIFT); + STORE_RT_REG(p_hwfn, DORQ_REG_PF_MAX_ICID_5_RT_OFFSET, dq_pf_max_cid); +} + +static void qed_ilt_bounds_init(struct qed_hwfn *p_hwfn) +{ + struct qed_ilt_client_cfg *ilt_clients; + int i; + + ilt_clients = p_hwfn->p_cxt_mngr->clients; + for_each_ilt_valid_client(i, ilt_clients) { + if (!ilt_clients[i].active) + continue; + STORE_RT_REG(p_hwfn, + ilt_clients[i].first.reg, + ilt_clients[i].first.val); + STORE_RT_REG(p_hwfn, + ilt_clients[i].last.reg, + ilt_clients[i].last.val); + STORE_RT_REG(p_hwfn, + ilt_clients[i].p_size.reg, + ilt_clients[i].p_size.val); + } +} + +/* ILT (PSWRQ2) PF */ +static void qed_ilt_init_pf(struct qed_hwfn *p_hwfn) +{ + struct qed_ilt_client_cfg *clients; + struct qed_cxt_mngr *p_mngr; + struct qed_dma_mem *p_shdw; + u32 line, rt_offst, i; + + qed_ilt_bounds_init(p_hwfn); + + p_mngr = p_hwfn->p_cxt_mngr; + p_shdw = p_mngr->ilt_shadow; + clients = p_hwfn->p_cxt_mngr->clients; + + for_each_ilt_valid_client(i, clients) { + if (!clients[i].active) + continue; + + /** Client's 1st val and RT array are absolute, ILT shadows' + * lines are relative. + */ + line = clients[i].first.val - p_mngr->pf_start_line; + rt_offst = PSWRQ2_REG_ILT_MEMORY_RT_OFFSET + + clients[i].first.val * ILT_ENTRY_IN_REGS; + + for (; line <= clients[i].last.val - p_mngr->pf_start_line; + line++, rt_offst += ILT_ENTRY_IN_REGS) { + u64 ilt_hw_entry = 0; + + /** p_virt could be NULL incase of dynamic + * allocation + */ + if (p_shdw[line].p_virt) { + SET_FIELD(ilt_hw_entry, ILT_ENTRY_VALID, 1ULL); + SET_FIELD(ilt_hw_entry, ILT_ENTRY_PHY_ADDR, + (p_shdw[line].p_phys >> 12)); + + DP_VERBOSE(p_hwfn, QED_MSG_ILT, + "Setting RT[0x%08x] from ILT[0x%08x] [Client is %d] to Physical addr: 0x%llx\n", + rt_offst, line, i, + (u64)(p_shdw[line].p_phys >> 12)); + } + + STORE_RT_REG_AGG(p_hwfn, rt_offst, ilt_hw_entry); + } + } +} + +void qed_cxt_hw_init_common(struct qed_hwfn *p_hwfn) +{ + qed_cdu_init_common(p_hwfn); +} + +void qed_cxt_hw_init_pf(struct qed_hwfn *p_hwfn) +{ + qed_qm_init_pf(p_hwfn); + qed_cm_init_pf(p_hwfn); + qed_dq_init_pf(p_hwfn); + qed_ilt_init_pf(p_hwfn); +} + +int qed_cxt_acquire_cid(struct qed_hwfn *p_hwfn, + enum protocol_type type, + u32 *p_cid) +{ + struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; + u32 rel_cid; + + if (type >= MAX_CONN_TYPES || !p_mngr->acquired[type].cid_map) { + DP_NOTICE(p_hwfn, "Invalid protocol type %d", type); + return -EINVAL; + } + + rel_cid = find_first_zero_bit(p_mngr->acquired[type].cid_map, + p_mngr->acquired[type].max_count); + + if (rel_cid >= p_mngr->acquired[type].max_count) { + DP_NOTICE(p_hwfn, "no CID available for protocol %d\n", + type); + return -EINVAL; + } + + __set_bit(rel_cid, p_mngr->acquired[type].cid_map); + + *p_cid = rel_cid + p_mngr->acquired[type].start_cid; + + return 0; +} + +static bool qed_cxt_test_cid_acquired(struct qed_hwfn *p_hwfn, + u32 cid, + enum protocol_type *p_type) +{ + struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; + struct qed_cid_acquired_map *p_map; + enum protocol_type p; + u32 rel_cid; + + /* Iterate over protocols and find matching cid range */ + for (p = 0; p < MAX_CONN_TYPES; p++) { + p_map = &p_mngr->acquired[p]; + + if (!p_map->cid_map) + continue; + if (cid >= p_map->start_cid && + cid < p_map->start_cid + p_map->max_count) + break; + } + *p_type = p; + + if (p == MAX_CONN_TYPES) { + DP_NOTICE(p_hwfn, "Invalid CID %d", cid); + return false; + } + + rel_cid = cid - p_map->start_cid; + if (!test_bit(rel_cid, p_map->cid_map)) { + DP_NOTICE(p_hwfn, "CID %d not acquired", cid); + return false; + } + return true; +} + +void qed_cxt_release_cid(struct qed_hwfn *p_hwfn, + u32 cid) +{ + struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; + enum protocol_type type; + bool b_acquired; + u32 rel_cid; + + /* Test acquired and find matching per-protocol map */ + b_acquired = qed_cxt_test_cid_acquired(p_hwfn, cid, &type); + + if (!b_acquired) + return; + + rel_cid = cid - p_mngr->acquired[type].start_cid; + __clear_bit(rel_cid, p_mngr->acquired[type].cid_map); +} + +int qed_cxt_get_cid_info(struct qed_hwfn *p_hwfn, + struct qed_cxt_info *p_info) +{ + struct qed_cxt_mngr *p_mngr = p_hwfn->p_cxt_mngr; + u32 conn_cxt_size, hw_p_size, cxts_per_p, line; + enum protocol_type type; + bool b_acquired; + + /* Test acquired and find matching per-protocol map */ + b_acquired = qed_cxt_test_cid_acquired(p_hwfn, p_info->iid, &type); + + if (!b_acquired) + return -EINVAL; + + /* set the protocl type */ + p_info->type = type; + + /* compute context virtual pointer */ + hw_p_size = p_hwfn->p_cxt_mngr->clients[ILT_CLI_CDUC].p_size.val; + + conn_cxt_size = CONN_CXT_SIZE(p_hwfn); + cxts_per_p = ILT_PAGE_IN_BYTES(hw_p_size) / conn_cxt_size; + line = p_info->iid / cxts_per_p; + + /* Make sure context is allocated (dynamic allocation) */ + if (!p_mngr->ilt_shadow[line].p_virt) + return -EINVAL; + + p_info->p_cxt = p_mngr->ilt_shadow[line].p_virt + + p_info->iid % cxts_per_p * conn_cxt_size; + + DP_VERBOSE(p_hwfn, (QED_MSG_ILT | QED_MSG_CXT), + "Accessing ILT shadow[%d]: CXT pointer is at %p (for iid %d)\n", + p_info->iid / cxts_per_p, p_info->p_cxt, p_info->iid); + + return 0; +} + +int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn) +{ + struct qed_eth_pf_params *p_params = &p_hwfn->pf_params.eth_pf_params; + + /* Set the number of required CORE connections */ + u32 core_cids = 1; /* SPQ */ + + qed_cxt_set_proto_cid_count(p_hwfn, PROTOCOLID_CORE, core_cids); + + qed_cxt_set_proto_cid_count(p_hwfn, PROTOCOLID_ETH, + p_params->num_cons); + + return 0; +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.h b/drivers/net/ethernet/qlogic/qed/qed_cxt.h new file mode 100644 index 000000000000..c8e1f5e5c42b --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.h @@ -0,0 +1,139 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#ifndef _QED_CXT_H +#define _QED_CXT_H + +#include +#include +#include +#include "qed_hsi.h" +#include "qed.h" + +struct qed_cxt_info { + void *p_cxt; + u32 iid; + enum protocol_type type; +}; + +/** + * @brief qed_cxt_acquire - Acquire a new cid of a specific protocol type + * + * @param p_hwfn + * @param type + * @param p_cid + * + * @return int + */ +int qed_cxt_acquire_cid(struct qed_hwfn *p_hwfn, + enum protocol_type type, + u32 *p_cid); + +/** + * @brief qedo_cid_get_cxt_info - Returns the context info for a specific cid + * + * + * @param p_hwfn + * @param p_info in/out + * + * @return int + */ +int qed_cxt_get_cid_info(struct qed_hwfn *p_hwfn, + struct qed_cxt_info *p_info); + +enum qed_cxt_elem_type { + QED_ELEM_CXT, + QED_ELEM_TASK +}; + +/** + * @brief qed_cxt_set_pf_params - Set the PF params for cxt init + * + * @param p_hwfn + * + * @return int + */ +int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_cxt_cfg_ilt_compute - compute ILT init parameters + * + * @param p_hwfn + * + * @return int + */ +int qed_cxt_cfg_ilt_compute(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_cxt_mngr_alloc - Allocate and init the context manager struct + * + * @param p_hwfn + * + * @return int + */ +int qed_cxt_mngr_alloc(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_cxt_mngr_free + * + * @param p_hwfn + */ +void qed_cxt_mngr_free(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_cxt_tables_alloc - Allocate ILT shadow, Searcher T2, acquired map + * + * @param p_hwfn + * + * @return int + */ +int qed_cxt_tables_alloc(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_cxt_mngr_setup - Reset the acquired CIDs + * + * @param p_hwfn + */ +void qed_cxt_mngr_setup(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_cxt_hw_init_common - Initailze ILT and DQ, common phase, per path. + * + * + * + * @param p_hwfn + */ +void qed_cxt_hw_init_common(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_cxt_hw_init_pf - Initailze ILT and DQ, PF phase, per path. + * + * + * + * @param p_hwfn + */ +void qed_cxt_hw_init_pf(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_qm_init_pf - Initailze the QM PF phase, per path + * + * @param p_hwfn + */ + +void qed_qm_init_pf(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_cxt_release - Release a cid + * + * @param p_hwfn + * @param cid + */ +void qed_cxt_release_cid(struct qed_hwfn *p_hwfn, + u32 cid); + +#endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c new file mode 100644 index 000000000000..5b845220ae8c --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -0,0 +1,1277 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qed.h" +#include "qed_cxt.h" +#include "qed_dev_api.h" +#include "qed_hsi.h" +#include "qed_hw.h" +#include "qed_init_ops.h" +#include "qed_int.h" +#include "qed_mcp.h" +#include "qed_reg_addr.h" +#include "qed_sp.h" + +/* API common to all protocols */ +void qed_init_dp(struct qed_dev *cdev, + u32 dp_module, u8 dp_level) +{ + u32 i; + + cdev->dp_level = dp_level; + cdev->dp_module = dp_module; + for (i = 0; i < MAX_HWFNS_PER_DEVICE; i++) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + p_hwfn->dp_level = dp_level; + p_hwfn->dp_module = dp_module; + } +} + +void qed_init_struct(struct qed_dev *cdev) +{ + u8 i; + + for (i = 0; i < MAX_HWFNS_PER_DEVICE; i++) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + p_hwfn->cdev = cdev; + p_hwfn->my_id = i; + p_hwfn->b_active = false; + + mutex_init(&p_hwfn->dmae_info.mutex); + } + + /* hwfn 0 is always active */ + cdev->hwfns[0].b_active = true; + + /* set the default cache alignment to 128 */ + cdev->cache_shift = 7; +} + +static void qed_qm_info_free(struct qed_hwfn *p_hwfn) +{ + struct qed_qm_info *qm_info = &p_hwfn->qm_info; + + kfree(qm_info->qm_pq_params); + qm_info->qm_pq_params = NULL; + kfree(qm_info->qm_vport_params); + qm_info->qm_vport_params = NULL; + kfree(qm_info->qm_port_params); + qm_info->qm_port_params = NULL; +} + +void qed_resc_free(struct qed_dev *cdev) +{ + int i; + + kfree(cdev->fw_data); + cdev->fw_data = NULL; + + kfree(cdev->reset_stats); + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + qed_cxt_mngr_free(p_hwfn); + qed_qm_info_free(p_hwfn); + qed_spq_free(p_hwfn); + qed_eq_free(p_hwfn, p_hwfn->p_eq); + qed_consq_free(p_hwfn, p_hwfn->p_consq); + qed_int_free(p_hwfn); + qed_dmae_info_free(p_hwfn); + } +} + +static int qed_init_qm_info(struct qed_hwfn *p_hwfn) +{ + struct qed_qm_info *qm_info = &p_hwfn->qm_info; + struct init_qm_port_params *p_qm_port; + u8 num_vports, i, vport_id, num_ports; + u16 num_pqs, multi_cos_tcs = 1; + + memset(qm_info, 0, sizeof(*qm_info)); + + num_pqs = multi_cos_tcs + 1; /* The '1' is for pure-LB */ + num_vports = (u8)RESC_NUM(p_hwfn, QED_VPORT); + + /* Sanity checking that setup requires legal number of resources */ + if (num_pqs > RESC_NUM(p_hwfn, QED_PQ)) { + DP_ERR(p_hwfn, + "Need too many Physical queues - 0x%04x when only %04x are available\n", + num_pqs, RESC_NUM(p_hwfn, QED_PQ)); + return -EINVAL; + } + + /* PQs will be arranged as follows: First per-TC PQ then pure-LB quete. + */ + qm_info->qm_pq_params = kzalloc(sizeof(*qm_info->qm_pq_params) * + num_pqs, GFP_ATOMIC); + if (!qm_info->qm_pq_params) + goto alloc_err; + + qm_info->qm_vport_params = kzalloc(sizeof(*qm_info->qm_vport_params) * + num_vports, GFP_ATOMIC); + if (!qm_info->qm_vport_params) + goto alloc_err; + + qm_info->qm_port_params = kzalloc(sizeof(*qm_info->qm_port_params) * + MAX_NUM_PORTS, GFP_ATOMIC); + if (!qm_info->qm_port_params) + goto alloc_err; + + vport_id = (u8)RESC_START(p_hwfn, QED_VPORT); + + /* First init per-TC PQs */ + for (i = 0; i < multi_cos_tcs; i++) { + struct init_qm_pq_params *params = &qm_info->qm_pq_params[i]; + + params->vport_id = vport_id; + params->tc_id = p_hwfn->hw_info.non_offload_tc; + params->wrr_group = 1; + } + + /* Then init pure-LB PQ */ + qm_info->pure_lb_pq = i; + qm_info->qm_pq_params[i].vport_id = (u8)RESC_START(p_hwfn, QED_VPORT); + qm_info->qm_pq_params[i].tc_id = PURE_LB_TC; + qm_info->qm_pq_params[i].wrr_group = 1; + i++; + + qm_info->offload_pq = 0; + qm_info->num_pqs = num_pqs; + qm_info->num_vports = num_vports; + + /* Initialize qm port parameters */ + num_ports = p_hwfn->cdev->num_ports_in_engines; + for (i = 0; i < num_ports; i++) { + p_qm_port = &qm_info->qm_port_params[i]; + p_qm_port->active = 1; + p_qm_port->num_active_phys_tcs = 4; + p_qm_port->num_pbf_cmd_lines = PBF_MAX_CMD_LINES / num_ports; + p_qm_port->num_btb_blocks = BTB_MAX_BLOCKS / num_ports; + } + + qm_info->max_phys_tcs_per_port = NUM_OF_PHYS_TCS; + + qm_info->start_pq = (u16)RESC_START(p_hwfn, QED_PQ); + + qm_info->start_vport = (u8)RESC_START(p_hwfn, QED_VPORT); + + qm_info->pf_wfq = 0; + qm_info->pf_rl = 0; + qm_info->vport_rl_en = 1; + + return 0; + +alloc_err: + DP_NOTICE(p_hwfn, "Failed to allocate memory for QM params\n"); + kfree(qm_info->qm_pq_params); + kfree(qm_info->qm_vport_params); + kfree(qm_info->qm_port_params); + + return -ENOMEM; +} + +int qed_resc_alloc(struct qed_dev *cdev) +{ + struct qed_consq *p_consq; + struct qed_eq *p_eq; + int i, rc = 0; + + cdev->fw_data = kzalloc(sizeof(*cdev->fw_data), GFP_KERNEL); + if (!cdev->fw_data) + return -ENOMEM; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + /* First allocate the context manager structure */ + rc = qed_cxt_mngr_alloc(p_hwfn); + if (rc) + goto alloc_err; + + /* Set the HW cid/tid numbers (in the contest manager) + * Must be done prior to any further computations. + */ + rc = qed_cxt_set_pf_params(p_hwfn); + if (rc) + goto alloc_err; + + /* Prepare and process QM requirements */ + rc = qed_init_qm_info(p_hwfn); + if (rc) + goto alloc_err; + + /* Compute the ILT client partition */ + rc = qed_cxt_cfg_ilt_compute(p_hwfn); + if (rc) + goto alloc_err; + + /* CID map / ILT shadow table / T2 + * The talbes sizes are determined by the computations above + */ + rc = qed_cxt_tables_alloc(p_hwfn); + if (rc) + goto alloc_err; + + /* SPQ, must follow ILT because initializes SPQ context */ + rc = qed_spq_alloc(p_hwfn); + if (rc) + goto alloc_err; + + /* SP status block allocation */ + p_hwfn->p_dpc_ptt = qed_get_reserved_ptt(p_hwfn, + RESERVED_PTT_DPC); + + rc = qed_int_alloc(p_hwfn, p_hwfn->p_main_ptt); + if (rc) + goto alloc_err; + + /* EQ */ + p_eq = qed_eq_alloc(p_hwfn, 256); + + if (!p_eq) + goto alloc_err; + p_hwfn->p_eq = p_eq; + + p_consq = qed_consq_alloc(p_hwfn); + if (!p_consq) + goto alloc_err; + p_hwfn->p_consq = p_consq; + + /* DMA info initialization */ + rc = qed_dmae_info_alloc(p_hwfn); + if (rc) { + DP_NOTICE(p_hwfn, + "Failed to allocate memory for dmae_info structure\n"); + goto alloc_err; + } + } + + cdev->reset_stats = kzalloc(sizeof(*cdev->reset_stats), GFP_KERNEL); + if (!cdev->reset_stats) { + DP_NOTICE(cdev, "Failed to allocate reset statistics\n"); + goto alloc_err; + } + + return 0; + +alloc_err: + qed_resc_free(cdev); + return rc; +} + +void qed_resc_setup(struct qed_dev *cdev) +{ + int i; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + qed_cxt_mngr_setup(p_hwfn); + qed_spq_setup(p_hwfn); + qed_eq_setup(p_hwfn, p_hwfn->p_eq); + qed_consq_setup(p_hwfn, p_hwfn->p_consq); + + /* Read shadow of current MFW mailbox */ + qed_mcp_read_mb(p_hwfn, p_hwfn->p_main_ptt); + memcpy(p_hwfn->mcp_info->mfw_mb_shadow, + p_hwfn->mcp_info->mfw_mb_cur, + p_hwfn->mcp_info->mfw_mb_length); + + qed_int_setup(p_hwfn, p_hwfn->p_main_ptt); + } +} + +#define FINAL_CLEANUP_CMD_OFFSET (0) +#define FINAL_CLEANUP_CMD (0x1) +#define FINAL_CLEANUP_VALID_OFFSET (6) +#define FINAL_CLEANUP_VFPF_ID_SHIFT (7) +#define FINAL_CLEANUP_COMP (0x2) +#define FINAL_CLEANUP_POLL_CNT (100) +#define FINAL_CLEANUP_POLL_TIME (10) +int qed_final_cleanup(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u16 id) +{ + u32 command = 0, addr, count = FINAL_CLEANUP_POLL_CNT; + int rc = -EBUSY; + + addr = GTT_BAR0_MAP_REG_USDM_RAM + USTORM_FLR_FINAL_ACK_OFFSET; + + command |= FINAL_CLEANUP_CMD << FINAL_CLEANUP_CMD_OFFSET; + command |= 1 << FINAL_CLEANUP_VALID_OFFSET; + command |= id << FINAL_CLEANUP_VFPF_ID_SHIFT; + command |= FINAL_CLEANUP_COMP << SDM_OP_GEN_COMP_TYPE_SHIFT; + + /* Make sure notification is not set before initiating final cleanup */ + if (REG_RD(p_hwfn, addr)) { + DP_NOTICE( + p_hwfn, + "Unexpected; Found final cleanup notification before initiating final cleanup\n"); + REG_WR(p_hwfn, addr, 0); + } + + DP_VERBOSE(p_hwfn, QED_MSG_IOV, + "Sending final cleanup for PFVF[%d] [Command %08x\n]", + id, command); + + qed_wr(p_hwfn, p_ptt, XSDM_REG_OPERATION_GEN, command); + + /* Poll until completion */ + while (!REG_RD(p_hwfn, addr) && count--) + msleep(FINAL_CLEANUP_POLL_TIME); + + if (REG_RD(p_hwfn, addr)) + rc = 0; + else + DP_NOTICE(p_hwfn, + "Failed to receive FW final cleanup notification\n"); + + /* Cleanup afterwards */ + REG_WR(p_hwfn, addr, 0); + + return rc; +} + +static void qed_calc_hw_mode(struct qed_hwfn *p_hwfn) +{ + int hw_mode = 0; + + hw_mode = (1 << MODE_BB_A0); + + switch (p_hwfn->cdev->num_ports_in_engines) { + case 1: + hw_mode |= 1 << MODE_PORTS_PER_ENG_1; + break; + case 2: + hw_mode |= 1 << MODE_PORTS_PER_ENG_2; + break; + case 4: + hw_mode |= 1 << MODE_PORTS_PER_ENG_4; + break; + default: + DP_NOTICE(p_hwfn, "num_ports_in_engine = %d not supported\n", + p_hwfn->cdev->num_ports_in_engines); + return; + } + + switch (p_hwfn->cdev->mf_mode) { + case SF: + hw_mode |= 1 << MODE_SF; + break; + case MF_OVLAN: + hw_mode |= 1 << MODE_MF_SD; + break; + case MF_NPAR: + hw_mode |= 1 << MODE_MF_SI; + break; + default: + DP_NOTICE(p_hwfn, "Unsupported MF mode, init as SF\n"); + hw_mode |= 1 << MODE_SF; + } + + hw_mode |= 1 << MODE_ASIC; + + p_hwfn->hw_info.hw_mode = hw_mode; +} + +/* Init run time data for all PFs on an engine. */ +static void qed_init_cau_rt_data(struct qed_dev *cdev) +{ + u32 offset = CAU_REG_SB_VAR_MEMORY_RT_OFFSET; + int i, sb_id; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + struct qed_igu_info *p_igu_info; + struct qed_igu_block *p_block; + struct cau_sb_entry sb_entry; + + p_igu_info = p_hwfn->hw_info.p_igu_info; + + for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(cdev); + sb_id++) { + p_block = &p_igu_info->igu_map.igu_blocks[sb_id]; + if (!p_block->is_pf) + continue; + + qed_init_cau_sb_entry(p_hwfn, &sb_entry, + p_block->function_id, + 0, 0); + STORE_RT_REG_AGG(p_hwfn, offset + sb_id * 2, + sb_entry); + } + } +} + +static int qed_hw_init_common(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + int hw_mode) +{ + struct qed_qm_info *qm_info = &p_hwfn->qm_info; + struct qed_qm_common_rt_init_params params; + struct qed_dev *cdev = p_hwfn->cdev; + int rc = 0; + + qed_init_cau_rt_data(cdev); + + /* Program GTT windows */ + qed_gtt_init(p_hwfn); + + if (p_hwfn->mcp_info) { + if (p_hwfn->mcp_info->func_info.bandwidth_max) + qm_info->pf_rl_en = 1; + if (p_hwfn->mcp_info->func_info.bandwidth_min) + qm_info->pf_wfq_en = 1; + } + + memset(¶ms, 0, sizeof(params)); + params.max_ports_per_engine = p_hwfn->cdev->num_ports_in_engines; + params.max_phys_tcs_per_port = qm_info->max_phys_tcs_per_port; + params.pf_rl_en = qm_info->pf_rl_en; + params.pf_wfq_en = qm_info->pf_wfq_en; + params.vport_rl_en = qm_info->vport_rl_en; + params.vport_wfq_en = qm_info->vport_wfq_en; + params.port_params = qm_info->qm_port_params; + + qed_qm_common_rt_init(p_hwfn, ¶ms); + + qed_cxt_hw_init_common(p_hwfn); + + /* Close gate from NIG to BRB/Storm; By default they are open, but + * we close them to prevent NIG from passing data to reset blocks. + * Should have been done in the ENGINE phase, but init-tool lacks + * proper port-pretend capabilities. + */ + qed_wr(p_hwfn, p_ptt, NIG_REG_RX_BRB_OUT_EN, 0); + qed_wr(p_hwfn, p_ptt, NIG_REG_STORM_OUT_EN, 0); + qed_port_pretend(p_hwfn, p_ptt, p_hwfn->port_id ^ 1); + qed_wr(p_hwfn, p_ptt, NIG_REG_RX_BRB_OUT_EN, 0); + qed_wr(p_hwfn, p_ptt, NIG_REG_STORM_OUT_EN, 0); + qed_port_unpretend(p_hwfn, p_ptt); + + rc = qed_init_run(p_hwfn, p_ptt, PHASE_ENGINE, ANY_PHASE_ID, hw_mode); + if (rc != 0) + return rc; + + qed_wr(p_hwfn, p_ptt, PSWRQ2_REG_L2P_VALIDATE_VFID, 0); + qed_wr(p_hwfn, p_ptt, PGLUE_B_REG_USE_CLIENTID_IN_TAG, 1); + + /* Disable relaxed ordering in the PCI config space */ + qed_wr(p_hwfn, p_ptt, 0x20b4, + qed_rd(p_hwfn, p_ptt, 0x20b4) & ~0x10); + + return rc; +} + +static int qed_hw_init_port(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + int hw_mode) +{ + int rc = 0; + + rc = qed_init_run(p_hwfn, p_ptt, PHASE_PORT, p_hwfn->port_id, + hw_mode); + return rc; +} + +static int qed_hw_init_pf(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + int hw_mode, + bool b_hw_start, + enum qed_int_mode int_mode, + bool allow_npar_tx_switch) +{ + u8 rel_pf_id = p_hwfn->rel_pf_id; + int rc = 0; + + if (p_hwfn->mcp_info) { + struct qed_mcp_function_info *p_info; + + p_info = &p_hwfn->mcp_info->func_info; + if (p_info->bandwidth_min) + p_hwfn->qm_info.pf_wfq = p_info->bandwidth_min; + + /* Update rate limit once we'll actually have a link */ + p_hwfn->qm_info.pf_rl = 100; + } + + qed_cxt_hw_init_pf(p_hwfn); + + qed_int_igu_init_rt(p_hwfn); + + /* Set VLAN in NIG if needed */ + if (hw_mode & (1 << MODE_MF_SD)) { + DP_VERBOSE(p_hwfn, NETIF_MSG_HW, "Configuring LLH_FUNC_TAG\n"); + STORE_RT_REG(p_hwfn, NIG_REG_LLH_FUNC_TAG_EN_RT_OFFSET, 1); + STORE_RT_REG(p_hwfn, NIG_REG_LLH_FUNC_TAG_VALUE_RT_OFFSET, + p_hwfn->hw_info.ovlan); + } + + /* Enable classification by MAC if needed */ + if (hw_mode & MODE_MF_SI) { + DP_VERBOSE(p_hwfn, NETIF_MSG_HW, + "Configuring TAGMAC_CLS_TYPE\n"); + STORE_RT_REG(p_hwfn, + NIG_REG_LLH_FUNC_TAGMAC_CLS_TYPE_RT_OFFSET, 1); + } + + /* Protocl Configuration */ + STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_TCP_RT_OFFSET, 0); + STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_FCOE_RT_OFFSET, 0); + STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_ROCE_RT_OFFSET, 0); + + /* Cleanup chip from previous driver if such remains exist */ + rc = qed_final_cleanup(p_hwfn, p_ptt, rel_pf_id); + if (rc != 0) + return rc; + + /* PF Init sequence */ + rc = qed_init_run(p_hwfn, p_ptt, PHASE_PF, rel_pf_id, hw_mode); + if (rc) + return rc; + + /* QM_PF Init sequence (may be invoked separately e.g. for DCB) */ + rc = qed_init_run(p_hwfn, p_ptt, PHASE_QM_PF, rel_pf_id, hw_mode); + if (rc) + return rc; + + /* Pure runtime initializations - directly to the HW */ + qed_int_igu_init_pure_rt(p_hwfn, p_ptt, true, true); + + if (b_hw_start) { + /* enable interrupts */ + qed_int_igu_enable(p_hwfn, p_ptt, int_mode); + + /* send function start command */ + rc = qed_sp_pf_start(p_hwfn, p_hwfn->cdev->mf_mode); + if (rc) + DP_NOTICE(p_hwfn, "Function start ramrod failed\n"); + } + return rc; +} + +static int qed_change_pci_hwfn(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u8 enable) +{ + u32 delay_idx = 0, val, set_val = enable ? 1 : 0; + + /* Change PF in PXP */ + qed_wr(p_hwfn, p_ptt, + PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, set_val); + + /* wait until value is set - try for 1 second every 50us */ + for (delay_idx = 0; delay_idx < 20000; delay_idx++) { + val = qed_rd(p_hwfn, p_ptt, + PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER); + if (val == set_val) + break; + + usleep_range(50, 60); + } + + if (val != set_val) { + DP_NOTICE(p_hwfn, + "PFID_ENABLE_MASTER wasn't changed after a second\n"); + return -EAGAIN; + } + + return 0; +} + +static void qed_reset_mb_shadow(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_main_ptt) +{ + /* Read shadow of current MFW mailbox */ + qed_mcp_read_mb(p_hwfn, p_main_ptt); + memcpy(p_hwfn->mcp_info->mfw_mb_shadow, + p_hwfn->mcp_info->mfw_mb_cur, + p_hwfn->mcp_info->mfw_mb_length); +} + +int qed_hw_init(struct qed_dev *cdev, + bool b_hw_start, + enum qed_int_mode int_mode, + bool allow_npar_tx_switch, + const u8 *bin_fw_data) +{ + u32 load_code, param; + int rc, mfw_rc, i; + + rc = qed_init_fw_data(cdev, bin_fw_data); + if (rc != 0) + return rc; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + /* Enable DMAE in PXP */ + rc = qed_change_pci_hwfn(p_hwfn, p_hwfn->p_main_ptt, true); + + qed_calc_hw_mode(p_hwfn); + + rc = qed_mcp_load_req(p_hwfn, p_hwfn->p_main_ptt, + &load_code); + if (rc) { + DP_NOTICE(p_hwfn, "Failed sending LOAD_REQ command\n"); + return rc; + } + + qed_reset_mb_shadow(p_hwfn, p_hwfn->p_main_ptt); + + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "Load request was sent. Resp:0x%x, Load code: 0x%x\n", + rc, load_code); + + p_hwfn->first_on_engine = (load_code == + FW_MSG_CODE_DRV_LOAD_ENGINE); + + switch (load_code) { + case FW_MSG_CODE_DRV_LOAD_ENGINE: + rc = qed_hw_init_common(p_hwfn, p_hwfn->p_main_ptt, + p_hwfn->hw_info.hw_mode); + if (rc) + break; + /* Fall into */ + case FW_MSG_CODE_DRV_LOAD_PORT: + rc = qed_hw_init_port(p_hwfn, p_hwfn->p_main_ptt, + p_hwfn->hw_info.hw_mode); + if (rc) + break; + + /* Fall into */ + case FW_MSG_CODE_DRV_LOAD_FUNCTION: + rc = qed_hw_init_pf(p_hwfn, p_hwfn->p_main_ptt, + p_hwfn->hw_info.hw_mode, + b_hw_start, int_mode, + allow_npar_tx_switch); + break; + default: + rc = -EINVAL; + break; + } + + if (rc) + DP_NOTICE(p_hwfn, + "init phase failed for loadcode 0x%x (rc %d)\n", + load_code, rc); + + /* ACK mfw regardless of success or failure of initialization */ + mfw_rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt, + DRV_MSG_CODE_LOAD_DONE, + 0, &load_code, ¶m); + if (rc) + return rc; + if (mfw_rc) { + DP_NOTICE(p_hwfn, "Failed sending LOAD_DONE command\n"); + return mfw_rc; + } + + p_hwfn->hw_init_done = true; + } + + return 0; +} + +#define QED_HW_STOP_RETRY_LIMIT (10) +int qed_hw_stop(struct qed_dev *cdev) +{ + int rc = 0, t_rc; + int i, j; + + for_each_hwfn(cdev, j) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[j]; + struct qed_ptt *p_ptt = p_hwfn->p_main_ptt; + + DP_VERBOSE(p_hwfn, NETIF_MSG_IFDOWN, "Stopping hw/fw\n"); + + /* mark the hw as uninitialized... */ + p_hwfn->hw_init_done = false; + + rc = qed_sp_pf_stop(p_hwfn); + if (rc) + return rc; + + qed_wr(p_hwfn, p_ptt, + NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF, 0x1); + + qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_TCP, 0x0); + qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_UDP, 0x0); + qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_FCOE, 0x0); + qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_ROCE, 0x0); + qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_OPENFLOW, 0x0); + + qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_CONN, 0x0); + qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK, 0x0); + for (i = 0; i < QED_HW_STOP_RETRY_LIMIT; i++) { + if ((!qed_rd(p_hwfn, p_ptt, + TM_REG_PF_SCAN_ACTIVE_CONN)) && + (!qed_rd(p_hwfn, p_ptt, + TM_REG_PF_SCAN_ACTIVE_TASK))) + break; + + usleep_range(1000, 2000); + } + if (i == QED_HW_STOP_RETRY_LIMIT) + DP_NOTICE(p_hwfn, + "Timers linear scans are not over [Connection %02x Tasks %02x]\n", + (u8)qed_rd(p_hwfn, p_ptt, + TM_REG_PF_SCAN_ACTIVE_CONN), + (u8)qed_rd(p_hwfn, p_ptt, + TM_REG_PF_SCAN_ACTIVE_TASK)); + + /* Disable Attention Generation */ + qed_int_igu_disable_int(p_hwfn, p_ptt); + + qed_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0); + qed_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0); + + qed_int_igu_init_pure_rt(p_hwfn, p_ptt, false, true); + + /* Need to wait 1ms to guarantee SBs are cleared */ + usleep_range(1000, 2000); + } + + /* Disable DMAE in PXP - in CMT, this should only be done for + * first hw-function, and only after all transactions have + * stopped for all active hw-functions. + */ + t_rc = qed_change_pci_hwfn(&cdev->hwfns[0], + cdev->hwfns[0].p_main_ptt, + false); + if (t_rc != 0) + rc = t_rc; + + return rc; +} + +static int qed_reg_assert(struct qed_hwfn *hwfn, + struct qed_ptt *ptt, u32 reg, + bool expected) +{ + u32 assert_val = qed_rd(hwfn, ptt, reg); + + if (assert_val != expected) { + DP_NOTICE(hwfn, "Value at address 0x%x != 0x%08x\n", + reg, expected); + return -EINVAL; + } + + return 0; +} + +int qed_hw_reset(struct qed_dev *cdev) +{ + int rc = 0; + u32 unload_resp, unload_param; + int i; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + DP_VERBOSE(p_hwfn, NETIF_MSG_IFDOWN, "Resetting hw/fw\n"); + + /* Check for incorrect states */ + qed_reg_assert(p_hwfn, p_hwfn->p_main_ptt, + QM_REG_USG_CNT_PF_TX, 0); + qed_reg_assert(p_hwfn, p_hwfn->p_main_ptt, + QM_REG_USG_CNT_PF_OTHER, 0); + + /* Disable PF in HW blocks */ + qed_wr(p_hwfn, p_hwfn->p_main_ptt, DORQ_REG_PF_DB_ENABLE, 0); + qed_wr(p_hwfn, p_hwfn->p_main_ptt, QM_REG_PF_EN, 0); + qed_wr(p_hwfn, p_hwfn->p_main_ptt, + TCFC_REG_STRONG_ENABLE_PF, 0); + qed_wr(p_hwfn, p_hwfn->p_main_ptt, + CCFC_REG_STRONG_ENABLE_PF, 0); + + /* Send unload command to MCP */ + rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt, + DRV_MSG_CODE_UNLOAD_REQ, + DRV_MB_PARAM_UNLOAD_WOL_MCP, + &unload_resp, &unload_param); + if (rc) { + DP_NOTICE(p_hwfn, "qed_hw_reset: UNLOAD_REQ failed\n"); + unload_resp = FW_MSG_CODE_DRV_UNLOAD_ENGINE; + } + + rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt, + DRV_MSG_CODE_UNLOAD_DONE, + 0, &unload_resp, &unload_param); + if (rc) { + DP_NOTICE(p_hwfn, "qed_hw_reset: UNLOAD_DONE failed\n"); + return rc; + } + } + + return rc; +} + +/* Free hwfn memory and resources acquired in hw_hwfn_prepare */ +static void qed_hw_hwfn_free(struct qed_hwfn *p_hwfn) +{ + qed_ptt_pool_free(p_hwfn); + kfree(p_hwfn->hw_info.p_igu_info); +} + +/* Setup bar access */ +static int qed_hw_hwfn_prepare(struct qed_hwfn *p_hwfn) +{ + int rc; + + /* Allocate PTT pool */ + rc = qed_ptt_pool_alloc(p_hwfn); + if (rc) + return rc; + + /* Allocate the main PTT */ + p_hwfn->p_main_ptt = qed_get_reserved_ptt(p_hwfn, RESERVED_PTT_MAIN); + + /* clear indirect access */ + qed_wr(p_hwfn, p_hwfn->p_main_ptt, PGLUE_B_REG_PGL_ADDR_88_F0, 0); + qed_wr(p_hwfn, p_hwfn->p_main_ptt, PGLUE_B_REG_PGL_ADDR_8C_F0, 0); + qed_wr(p_hwfn, p_hwfn->p_main_ptt, PGLUE_B_REG_PGL_ADDR_90_F0, 0); + qed_wr(p_hwfn, p_hwfn->p_main_ptt, PGLUE_B_REG_PGL_ADDR_94_F0, 0); + + /* Clean Previous errors if such exist */ + qed_wr(p_hwfn, p_hwfn->p_main_ptt, + PGLUE_B_REG_WAS_ERROR_PF_31_0_CLR, + 1 << p_hwfn->abs_pf_id); + + /* enable internal target-read */ + qed_wr(p_hwfn, p_hwfn->p_main_ptt, + PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); + + return 0; +} + +static void get_function_id(struct qed_hwfn *p_hwfn) +{ + /* ME Register */ + p_hwfn->hw_info.opaque_fid = (u16)REG_RD(p_hwfn, PXP_PF_ME_OPAQUE_ADDR); + + p_hwfn->hw_info.concrete_fid = REG_RD(p_hwfn, PXP_PF_ME_CONCRETE_ADDR); + + p_hwfn->abs_pf_id = (p_hwfn->hw_info.concrete_fid >> 16) & 0xf; + p_hwfn->rel_pf_id = GET_FIELD(p_hwfn->hw_info.concrete_fid, + PXP_CONCRETE_FID_PFID); + p_hwfn->port_id = GET_FIELD(p_hwfn->hw_info.concrete_fid, + PXP_CONCRETE_FID_PORT); +} + +static void qed_hw_get_resc(struct qed_hwfn *p_hwfn) +{ + u32 *resc_start = p_hwfn->hw_info.resc_start; + u32 *resc_num = p_hwfn->hw_info.resc_num; + int num_funcs, i; + + num_funcs = IS_MF(p_hwfn) ? MAX_NUM_PFS_BB + : p_hwfn->cdev->num_ports_in_engines; + + resc_num[QED_SB] = min_t(u32, + (MAX_SB_PER_PATH_BB / num_funcs), + qed_int_get_num_sbs(p_hwfn, NULL)); + resc_num[QED_VPORT] = MAX_NUM_VPORTS_BB / num_funcs; + resc_num[QED_PQ] = MAX_QM_TX_QUEUES_BB / num_funcs; + resc_num[QED_RL] = 8; + resc_num[QED_ILT] = 950; + + for (i = 0; i < QED_MAX_RESC; i++) + resc_start[i] = resc_num[i] * p_hwfn->rel_pf_id; + + DP_VERBOSE(p_hwfn, NETIF_MSG_PROBE, + "The numbers for each resource are:\n" + "SB = %d start = %d\n" + "VPORT = %d start = %d\n" + "PQ = %d start = %d\n" + "RL = %d start = %d\n" + "ILT = %d start = %d\n", + p_hwfn->hw_info.resc_num[QED_SB], + p_hwfn->hw_info.resc_start[QED_SB], + p_hwfn->hw_info.resc_num[QED_VPORT], + p_hwfn->hw_info.resc_start[QED_VPORT], + p_hwfn->hw_info.resc_num[QED_PQ], + p_hwfn->hw_info.resc_start[QED_PQ], + p_hwfn->hw_info.resc_num[QED_RL], + p_hwfn->hw_info.resc_start[QED_RL], + p_hwfn->hw_info.resc_num[QED_ILT], + p_hwfn->hw_info.resc_start[QED_ILT]); +} + +static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, nvm_cfg_addr; + u32 val; + + /* Read global nvm_cfg address */ + nvm_cfg_addr = qed_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0); + + /* Verify MCP has initialized it */ + if (!nvm_cfg_addr) { + DP_NOTICE(p_hwfn, "Shared memory not initialized\n"); + return -EINVAL; + } + + /* Read nvm_cfg1 (Notice this is just offset, and not offsize (TBD) */ + nvm_cfg1_offset = qed_rd(p_hwfn, p_ptt, nvm_cfg_addr + 4); + + /* Read Vendor Id / Device Id */ + addr = MCP_REG_SCRATCH + nvm_cfg1_offset + + offsetof(struct nvm_cfg1, glob) + + offsetof(struct nvm_cfg1_glob, pci_id); + p_hwfn->hw_info.vendor_id = qed_rd(p_hwfn, p_ptt, addr) & + NVM_CFG1_GLOB_VENDOR_ID_MASK; + addr = MCP_REG_SCRATCH + nvm_cfg1_offset + + offsetof(struct nvm_cfg1, func[MCP_PF_ID(p_hwfn)]) + + offsetof(struct nvm_cfg1_func, device_id); + val = qed_rd(p_hwfn, p_ptt, addr); + + if (IS_MF(p_hwfn)) { + p_hwfn->hw_info.device_id = + (val & NVM_CFG1_FUNC_MF_VENDOR_DEVICE_ID_MASK) >> + NVM_CFG1_FUNC_MF_VENDOR_DEVICE_ID_OFFSET; + } else { + p_hwfn->hw_info.device_id = + (val & NVM_CFG1_FUNC_VENDOR_DEVICE_ID_MASK) >> + NVM_CFG1_FUNC_VENDOR_DEVICE_ID_OFFSET; + } + + /* Read Multi-function information from shmem */ + addr = MCP_REG_SCRATCH + nvm_cfg1_offset + + offsetof(struct nvm_cfg1, glob) + + offsetof(struct nvm_cfg1_glob, generic_cont0); + + generic_cont0 = qed_rd(p_hwfn, p_ptt, addr); + + mf_mode = (generic_cont0 & NVM_CFG1_GLOB_MF_MODE_MASK) >> + NVM_CFG1_GLOB_MF_MODE_OFFSET; + + switch (mf_mode) { + case NVM_CFG1_GLOB_MF_MODE_MF_ALLOWED: + p_hwfn->cdev->mf_mode = MF_OVLAN; + break; + case NVM_CFG1_GLOB_MF_MODE_NPAR1_0: + p_hwfn->cdev->mf_mode = MF_NPAR; + break; + case NVM_CFG1_GLOB_MF_MODE_FORCED_SF: + p_hwfn->cdev->mf_mode = SF; + break; + } + DP_INFO(p_hwfn, "Multi function mode is %08x\n", + p_hwfn->cdev->mf_mode); + + return qed_mcp_fill_shmem_func_info(p_hwfn, p_ptt); +} + +static int +qed_get_hw_info(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_pci_personality personality) +{ + u32 port_mode; + int rc; + + /* Read the port mode */ + port_mode = qed_rd(p_hwfn, p_ptt, + CNIG_REG_NW_PORT_MODE_BB_B0); + + if (port_mode < 3) { + p_hwfn->cdev->num_ports_in_engines = 1; + } else if (port_mode <= 5) { + p_hwfn->cdev->num_ports_in_engines = 2; + } else { + DP_NOTICE(p_hwfn, "PORT MODE: %d not supported\n", + p_hwfn->cdev->num_ports_in_engines); + + /* Default num_ports_in_engines to something */ + p_hwfn->cdev->num_ports_in_engines = 1; + } + + qed_hw_get_nvm_info(p_hwfn, p_ptt); + + rc = qed_int_igu_read_cam(p_hwfn, p_ptt); + if (rc) + return rc; + + if (qed_mcp_is_init(p_hwfn)) + ether_addr_copy(p_hwfn->hw_info.hw_mac_addr, + p_hwfn->mcp_info->func_info.mac); + else + eth_random_addr(p_hwfn->hw_info.hw_mac_addr); + + if (qed_mcp_is_init(p_hwfn)) { + if (p_hwfn->mcp_info->func_info.ovlan != QED_MCP_VLAN_UNSET) + p_hwfn->hw_info.ovlan = + p_hwfn->mcp_info->func_info.ovlan; + + qed_mcp_cmd_port_init(p_hwfn, p_ptt); + } + + if (qed_mcp_is_init(p_hwfn)) { + enum qed_pci_personality protocol; + + protocol = p_hwfn->mcp_info->func_info.protocol; + p_hwfn->hw_info.personality = protocol; + } + + qed_hw_get_resc(p_hwfn); + + return rc; +} + +static void qed_get_dev_info(struct qed_dev *cdev) +{ + u32 tmp; + + cdev->chip_num = (u16)qed_rd(cdev->hwfns, cdev->hwfns[0].p_main_ptt, + MISCS_REG_CHIP_NUM); + cdev->chip_rev = (u16)qed_rd(cdev->hwfns, cdev->hwfns[0].p_main_ptt, + MISCS_REG_CHIP_REV); + MASK_FIELD(CHIP_REV, cdev->chip_rev); + + /* Learn number of HW-functions */ + tmp = qed_rd(cdev->hwfns, cdev->hwfns[0].p_main_ptt, + MISCS_REG_CMT_ENABLED_FOR_PAIR); + + if (tmp & (1 << cdev->hwfns[0].rel_pf_id)) { + DP_NOTICE(cdev->hwfns, "device in CMT mode\n"); + cdev->num_hwfns = 2; + } else { + cdev->num_hwfns = 1; + } + + cdev->chip_bond_id = qed_rd(cdev->hwfns, cdev->hwfns[0].p_main_ptt, + MISCS_REG_CHIP_TEST_REG) >> 4; + MASK_FIELD(CHIP_BOND_ID, cdev->chip_bond_id); + cdev->chip_metal = (u16)qed_rd(cdev->hwfns, cdev->hwfns[0].p_main_ptt, + MISCS_REG_CHIP_METAL); + MASK_FIELD(CHIP_METAL, cdev->chip_metal); + + DP_INFO(cdev->hwfns, + "Chip details - Num: %04x Rev: %04x Bond id: %04x Metal: %04x\n", + cdev->chip_num, cdev->chip_rev, + cdev->chip_bond_id, cdev->chip_metal); +} + +static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn, + void __iomem *p_regview, + void __iomem *p_doorbells, + enum qed_pci_personality personality) +{ + int rc = 0; + + /* Split PCI bars evenly between hwfns */ + p_hwfn->regview = p_regview; + p_hwfn->doorbells = p_doorbells; + + /* Validate that chip access is feasible */ + if (REG_RD(p_hwfn, PXP_PF_ME_OPAQUE_ADDR) == 0xffffffff) { + DP_ERR(p_hwfn, + "Reading the ME register returns all Fs; Preventing further chip access\n"); + return -EINVAL; + } + + get_function_id(p_hwfn); + + rc = qed_hw_hwfn_prepare(p_hwfn); + if (rc) { + DP_NOTICE(p_hwfn, "Failed to prepare hwfn's hw\n"); + goto err0; + } + + /* First hwfn learns basic information, e.g., number of hwfns */ + if (!p_hwfn->my_id) + qed_get_dev_info(p_hwfn->cdev); + + /* Initialize MCP structure */ + rc = qed_mcp_cmd_init(p_hwfn, p_hwfn->p_main_ptt); + if (rc) { + DP_NOTICE(p_hwfn, "Failed initializing mcp command\n"); + goto err1; + } + + /* Read the device configuration information from the HW and SHMEM */ + rc = qed_get_hw_info(p_hwfn, p_hwfn->p_main_ptt, personality); + if (rc) { + DP_NOTICE(p_hwfn, "Failed to get HW information\n"); + goto err2; + } + + /* Allocate the init RT array and initialize the init-ops engine */ + rc = qed_init_alloc(p_hwfn); + if (rc) { + DP_NOTICE(p_hwfn, "Failed to allocate the init array\n"); + goto err2; + } + + return rc; +err2: + qed_mcp_free(p_hwfn); +err1: + qed_hw_hwfn_free(p_hwfn); +err0: + return rc; +} + +static u32 qed_hw_bar_size(struct qed_dev *cdev, + u8 bar_id) +{ + u32 size = pci_resource_len(cdev->pdev, (bar_id > 0) ? 2 : 0); + + return size / cdev->num_hwfns; +} + +int qed_hw_prepare(struct qed_dev *cdev, + int personality) +{ + int rc, i; + + /* Store the precompiled init data ptrs */ + qed_init_iro_array(cdev); + + /* Initialize the first hwfn - will learn number of hwfns */ + rc = qed_hw_prepare_single(&cdev->hwfns[0], cdev->regview, + cdev->doorbells, personality); + if (rc) + return rc; + + personality = cdev->hwfns[0].hw_info.personality; + + /* Initialize the rest of the hwfns */ + for (i = 1; i < cdev->num_hwfns; i++) { + void __iomem *p_regview, *p_doorbell; + + p_regview = cdev->regview + + i * qed_hw_bar_size(cdev, 0); + p_doorbell = cdev->doorbells + + i * qed_hw_bar_size(cdev, 1); + rc = qed_hw_prepare_single(&cdev->hwfns[i], p_regview, + p_doorbell, personality); + if (rc) { + /* Cleanup previously initialized hwfns */ + while (--i >= 0) { + qed_init_free(&cdev->hwfns[i]); + qed_mcp_free(&cdev->hwfns[i]); + qed_hw_hwfn_free(&cdev->hwfns[i]); + } + return rc; + } + } + + return 0; +} + +void qed_hw_remove(struct qed_dev *cdev) +{ + int i; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + qed_init_free(p_hwfn); + qed_hw_hwfn_free(p_hwfn); + qed_mcp_free(p_hwfn); + } +} + +int qed_chain_alloc(struct qed_dev *cdev, + enum qed_chain_use_mode intended_use, + enum qed_chain_mode mode, + u16 num_elems, + size_t elem_size, + struct qed_chain *p_chain) +{ + dma_addr_t p_pbl_phys = 0; + void *p_pbl_virt = NULL; + dma_addr_t p_phys = 0; + void *p_virt = NULL; + u16 page_cnt = 0; + size_t size; + + if (mode == QED_CHAIN_MODE_SINGLE) + page_cnt = 1; + else + page_cnt = QED_CHAIN_PAGE_CNT(num_elems, elem_size, mode); + + size = page_cnt * QED_CHAIN_PAGE_SIZE; + p_virt = dma_alloc_coherent(&cdev->pdev->dev, + size, &p_phys, GFP_KERNEL); + if (!p_virt) { + DP_NOTICE(cdev, "Failed to allocate chain mem\n"); + goto nomem; + } + + if (mode == QED_CHAIN_MODE_PBL) { + size = page_cnt * QED_CHAIN_PBL_ENTRY_SIZE; + p_pbl_virt = dma_alloc_coherent(&cdev->pdev->dev, + size, &p_pbl_phys, + GFP_KERNEL); + if (!p_pbl_virt) { + DP_NOTICE(cdev, "Failed to allocate chain pbl mem\n"); + goto nomem; + } + + qed_chain_pbl_init(p_chain, p_virt, p_phys, page_cnt, + (u8)elem_size, intended_use, + p_pbl_phys, p_pbl_virt); + } else { + qed_chain_init(p_chain, p_virt, p_phys, page_cnt, + (u8)elem_size, intended_use, mode); + } + + return 0; + +nomem: + dma_free_coherent(&cdev->pdev->dev, + page_cnt * QED_CHAIN_PAGE_SIZE, + p_virt, p_phys); + dma_free_coherent(&cdev->pdev->dev, + page_cnt * QED_CHAIN_PBL_ENTRY_SIZE, + p_pbl_virt, p_pbl_phys); + + return -ENOMEM; +} + +void qed_chain_free(struct qed_dev *cdev, + struct qed_chain *p_chain) +{ + size_t size; + + if (!p_chain->p_virt_addr) + return; + + if (p_chain->mode == QED_CHAIN_MODE_PBL) { + size = p_chain->page_cnt * QED_CHAIN_PBL_ENTRY_SIZE; + dma_free_coherent(&cdev->pdev->dev, size, + p_chain->pbl.p_virt_table, + p_chain->pbl.p_phys_table); + } + + size = p_chain->page_cnt * QED_CHAIN_PAGE_SIZE; + dma_free_coherent(&cdev->pdev->dev, size, + p_chain->p_virt_addr, + p_chain->p_phys_addr); +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h new file mode 100644 index 000000000000..5051af5f378e --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h @@ -0,0 +1,222 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#ifndef _QED_DEV_API_H +#define _QED_DEV_API_H + +#include +#include +#include +#include +#include +#include "qed_int.h" + +/** + * @brief qed_init_dp - initialize the debug level + * + * @param cdev + * @param dp_module + * @param dp_level + */ +void qed_init_dp(struct qed_dev *cdev, + u32 dp_module, + u8 dp_level); + +/** + * @brief qed_init_struct - initialize the device structure to + * its defaults + * + * @param cdev + */ +void qed_init_struct(struct qed_dev *cdev); + +/** + * @brief qed_resc_free - + * + * @param cdev + */ +void qed_resc_free(struct qed_dev *cdev); + +/** + * @brief qed_resc_alloc - + * + * @param cdev + * + * @return int + */ +int qed_resc_alloc(struct qed_dev *cdev); + +/** + * @brief qed_resc_setup - + * + * @param cdev + */ +void qed_resc_setup(struct qed_dev *cdev); + +/** + * @brief qed_hw_init - + * + * @param cdev + * @param b_hw_start + * @param int_mode - interrupt mode [msix, inta, etc.] to use. + * @param allow_npar_tx_switch - npar tx switching to be used + * for vports configured for tx-switching. + * @param bin_fw_data - binary fw data pointer in binary fw file. + * Pass NULL if not using binary fw file. + * + * @return int + */ +int qed_hw_init(struct qed_dev *cdev, + bool b_hw_start, + enum qed_int_mode int_mode, + bool allow_npar_tx_switch, + const u8 *bin_fw_data); + +/** + * @brief qed_hw_stop - + * + * @param cdev + * + * @return int + */ +int qed_hw_stop(struct qed_dev *cdev); + +/** + * @brief qed_hw_reset - + * + * @param cdev + * + * @return int + */ +int qed_hw_reset(struct qed_dev *cdev); + +/** + * @brief qed_hw_prepare - + * + * @param cdev + * @param personality - personality to initialize + * + * @return int + */ +int qed_hw_prepare(struct qed_dev *cdev, + int personality); + +/** + * @brief qed_hw_remove - + * + * @param cdev + */ +void qed_hw_remove(struct qed_dev *cdev); + +/** + * @brief qed_ptt_acquire - Allocate a PTT window + * + * Should be called at the entry point to the driver (at the beginning of an + * exported function) + * + * @param p_hwfn + * + * @return struct qed_ptt + */ +struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_ptt_release - Release PTT Window + * + * Should be called at the end of a flow - at the end of the function that + * acquired the PTT. + * + * + * @param p_hwfn + * @param p_ptt + */ +void qed_ptt_release(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +enum qed_dmae_address_type_t { + QED_DMAE_ADDRESS_HOST_VIRT, + QED_DMAE_ADDRESS_HOST_PHYS, + QED_DMAE_ADDRESS_GRC +}; + +/* value of flags If QED_DMAE_FLAG_RW_REPL_SRC flag is set and the + * source is a block of length DMAE_MAX_RW_SIZE and the + * destination is larger, the source block will be duplicated as + * many times as required to fill the destination block. This is + * used mostly to write a zeroed buffer to destination address + * using DMA + */ +#define QED_DMAE_FLAG_RW_REPL_SRC 0x00000001 +#define QED_DMAE_FLAG_COMPLETION_DST 0x00000008 + +struct qed_dmae_params { + u32 flags; /* consists of QED_DMAE_FLAG_* values */ +}; + +/** + * @brief qed_dmae_host2grc - copy data from source addr to + * dmae registers using the given ptt + * + * @param p_hwfn + * @param p_ptt + * @param source_addr + * @param grc_addr (dmae_data_offset) + * @param size_in_dwords + * @param flags (one of the flags defined above) + */ +int +qed_dmae_host2grc(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u64 source_addr, + u32 grc_addr, + u32 size_in_dwords, + u32 flags); + +/** + * @brief qed_chain_alloc - Allocate and initialize a chain + * + * @param p_hwfn + * @param intended_use + * @param mode + * @param num_elems + * @param elem_size + * @param p_chain + * + * @return int + */ +int +qed_chain_alloc(struct qed_dev *cdev, + enum qed_chain_use_mode intended_use, + enum qed_chain_mode mode, + u16 num_elems, + size_t elem_size, + struct qed_chain *p_chain); + +/** + * @brief qed_chain_free - Free chain DMA memory + * + * @param p_hwfn + * @param p_chain + */ +void qed_chain_free(struct qed_dev *cdev, + struct qed_chain *p_chain); + +/** + * *@brief Cleanup of previous driver remains prior to load + * + * @param p_hwfn + * @param p_ptt + * @param id - For PF, engine-relative. For VF, PF-relative. + * + * @return int + */ +int qed_final_cleanup(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u16 id); + +#endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h new file mode 100644 index 000000000000..61c15a57c267 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -0,0 +1,4966 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#ifndef _QED_HSI_H +#define _QED_HSI_H + +#include +#include +#include +#include +#include +#include +#include +#include + +struct qed_hwfn; +struct qed_ptt; +/********************************/ +/* Add include to common target */ +/********************************/ + +/* opcodes for the event ring */ +enum common_event_opcode { + COMMON_EVENT_PF_START, + COMMON_EVENT_PF_STOP, + COMMON_EVENT_RESERVED, + COMMON_EVENT_RESERVED2, + COMMON_EVENT_RESERVED3, + COMMON_EVENT_RESERVED4, + COMMON_EVENT_RESERVED5, + MAX_COMMON_EVENT_OPCODE +}; + +/* Common Ramrod Command IDs */ +enum common_ramrod_cmd_id { + COMMON_RAMROD_UNUSED, + COMMON_RAMROD_PF_START /* PF Function Start Ramrod */, + COMMON_RAMROD_PF_STOP /* PF Function Stop Ramrod */, + COMMON_RAMROD_RESERVED, + COMMON_RAMROD_RESERVED2, + COMMON_RAMROD_RESERVED3, + MAX_COMMON_RAMROD_CMD_ID +}; + +/* The core storm context for the Ystorm */ +struct ystorm_core_conn_st_ctx { + __le32 reserved[4]; +}; + +/* The core storm context for the Pstorm */ +struct pstorm_core_conn_st_ctx { + __le32 reserved[4]; +}; + +/* Core Slowpath Connection storm context of Xstorm */ +struct xstorm_core_conn_st_ctx { + __le32 spq_base_lo /* SPQ Ring Base Address low dword */; + __le32 spq_base_hi /* SPQ Ring Base Address high dword */; + struct regpair consolid_base_addr; + __le16 spq_cons /* SPQ Ring Consumer */; + __le16 consolid_cons /* Consolidation Ring Consumer */; + __le32 reserved0[55] /* Pad to 15 cycles */; +}; + +struct xstorm_core_conn_ag_ctx { + u8 reserved0 /* cdu_validation */; + u8 core_state /* state */; + u8 flags0; +#define XSTORM_CORE_CONN_AG_CTX_EXIST_IN_QM0_MASK 0x1 +#define XSTORM_CORE_CONN_AG_CTX_EXIST_IN_QM0_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED1_MASK 0x1 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED1_SHIFT 1 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED2_MASK 0x1 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED2_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_EXIST_IN_QM3_MASK 0x1 +#define XSTORM_CORE_CONN_AG_CTX_EXIST_IN_QM3_SHIFT 3 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED3_MASK 0x1 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED3_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED4_MASK 0x1 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED4_SHIFT 5 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED5_MASK 0x1 /* bit6 */ +#define XSTORM_CORE_CONN_AG_CTX_RESERVED5_SHIFT 6 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED6_MASK 0x1 /* bit7 */ +#define XSTORM_CORE_CONN_AG_CTX_RESERVED6_SHIFT 7 + u8 flags1; +#define XSTORM_CORE_CONN_AG_CTX_RESERVED7_MASK 0x1 /* bit8 */ +#define XSTORM_CORE_CONN_AG_CTX_RESERVED7_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED8_MASK 0x1 /* bit9 */ +#define XSTORM_CORE_CONN_AG_CTX_RESERVED8_SHIFT 1 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED9_MASK 0x1 /* bit10 */ +#define XSTORM_CORE_CONN_AG_CTX_RESERVED9_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_BIT11_MASK 0x1 /* bit11 */ +#define XSTORM_CORE_CONN_AG_CTX_BIT11_SHIFT 3 +#define XSTORM_CORE_CONN_AG_CTX_BIT12_MASK 0x1 /* bit12 */ +#define XSTORM_CORE_CONN_AG_CTX_BIT12_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_BIT13_MASK 0x1 /* bit13 */ +#define XSTORM_CORE_CONN_AG_CTX_BIT13_SHIFT 5 +#define XSTORM_CORE_CONN_AG_CTX_TX_RULE_ACTIVE_MASK 0x1 /* bit14 */ +#define XSTORM_CORE_CONN_AG_CTX_TX_RULE_ACTIVE_SHIFT 6 +#define XSTORM_CORE_CONN_AG_CTX_DQ_CF_ACTIVE_MASK 0x1 /* bit15 */ +#define XSTORM_CORE_CONN_AG_CTX_DQ_CF_ACTIVE_SHIFT 7 + u8 flags2; +#define XSTORM_CORE_CONN_AG_CTX_CF0_MASK 0x3 /* timer0cf */ +#define XSTORM_CORE_CONN_AG_CTX_CF0_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_CF1_MASK 0x3 /* timer1cf */ +#define XSTORM_CORE_CONN_AG_CTX_CF1_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_CF2_MASK 0x3 /* timer2cf */ +#define XSTORM_CORE_CONN_AG_CTX_CF2_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_CF3_MASK 0x3 +#define XSTORM_CORE_CONN_AG_CTX_CF3_SHIFT 6 + u8 flags3; +#define XSTORM_CORE_CONN_AG_CTX_CF4_MASK 0x3 /* cf4 */ +#define XSTORM_CORE_CONN_AG_CTX_CF4_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_CF5_MASK 0x3 /* cf5 */ +#define XSTORM_CORE_CONN_AG_CTX_CF5_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_CF6_MASK 0x3 /* cf6 */ +#define XSTORM_CORE_CONN_AG_CTX_CF6_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_CF7_MASK 0x3 /* cf7 */ +#define XSTORM_CORE_CONN_AG_CTX_CF7_SHIFT 6 + u8 flags4; +#define XSTORM_CORE_CONN_AG_CTX_CF8_MASK 0x3 /* cf8 */ +#define XSTORM_CORE_CONN_AG_CTX_CF8_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_CF9_MASK 0x3 /* cf9 */ +#define XSTORM_CORE_CONN_AG_CTX_CF9_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_CF10_MASK 0x3 /* cf10 */ +#define XSTORM_CORE_CONN_AG_CTX_CF10_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_CF11_MASK 0x3 /* cf11 */ +#define XSTORM_CORE_CONN_AG_CTX_CF11_SHIFT 6 + u8 flags5; +#define XSTORM_CORE_CONN_AG_CTX_CF12_MASK 0x3 /* cf12 */ +#define XSTORM_CORE_CONN_AG_CTX_CF12_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_CF13_MASK 0x3 /* cf13 */ +#define XSTORM_CORE_CONN_AG_CTX_CF13_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_CF14_MASK 0x3 /* cf14 */ +#define XSTORM_CORE_CONN_AG_CTX_CF14_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_CF15_MASK 0x3 /* cf15 */ +#define XSTORM_CORE_CONN_AG_CTX_CF15_SHIFT 6 + u8 flags6; +#define XSTORM_CORE_CONN_AG_CTX_CONSOLID_PROD_CF_MASK 0x3 /* cf16 */ +#define XSTORM_CORE_CONN_AG_CTX_CONSOLID_PROD_CF_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_CF17_MASK 0x3 +#define XSTORM_CORE_CONN_AG_CTX_CF17_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_DQ_CF_MASK 0x3 /* cf18 */ +#define XSTORM_CORE_CONN_AG_CTX_DQ_CF_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_TERMINATE_CF_MASK 0x3 /* cf19 */ +#define XSTORM_CORE_CONN_AG_CTX_TERMINATE_CF_SHIFT 6 + u8 flags7; +#define XSTORM_CORE_CONN_AG_CTX_FLUSH_Q0_MASK 0x3 /* cf20 */ +#define XSTORM_CORE_CONN_AG_CTX_FLUSH_Q0_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED10_MASK 0x3 /* cf21 */ +#define XSTORM_CORE_CONN_AG_CTX_RESERVED10_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_SLOW_PATH_MASK 0x3 /* cf22 */ +#define XSTORM_CORE_CONN_AG_CTX_SLOW_PATH_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */ +#define XSTORM_CORE_CONN_AG_CTX_CF0EN_SHIFT 6 +#define XSTORM_CORE_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */ +#define XSTORM_CORE_CONN_AG_CTX_CF1EN_SHIFT 7 + u8 flags8; +#define XSTORM_CORE_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */ +#define XSTORM_CORE_CONN_AG_CTX_CF2EN_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_CF3EN_MASK 0x1 /* cf3en */ +#define XSTORM_CORE_CONN_AG_CTX_CF3EN_SHIFT 1 +#define XSTORM_CORE_CONN_AG_CTX_CF4EN_MASK 0x1 /* cf4en */ +#define XSTORM_CORE_CONN_AG_CTX_CF4EN_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_CF5EN_MASK 0x1 /* cf5en */ +#define XSTORM_CORE_CONN_AG_CTX_CF5EN_SHIFT 3 +#define XSTORM_CORE_CONN_AG_CTX_CF6EN_MASK 0x1 /* cf6en */ +#define XSTORM_CORE_CONN_AG_CTX_CF6EN_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_CF7EN_MASK 0x1 /* cf7en */ +#define XSTORM_CORE_CONN_AG_CTX_CF7EN_SHIFT 5 +#define XSTORM_CORE_CONN_AG_CTX_CF8EN_MASK 0x1 /* cf8en */ +#define XSTORM_CORE_CONN_AG_CTX_CF8EN_SHIFT 6 +#define XSTORM_CORE_CONN_AG_CTX_CF9EN_MASK 0x1 /* cf9en */ +#define XSTORM_CORE_CONN_AG_CTX_CF9EN_SHIFT 7 + u8 flags9; +#define XSTORM_CORE_CONN_AG_CTX_CF10EN_MASK 0x1 /* cf10en */ +#define XSTORM_CORE_CONN_AG_CTX_CF10EN_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_CF11EN_MASK 0x1 /* cf11en */ +#define XSTORM_CORE_CONN_AG_CTX_CF11EN_SHIFT 1 +#define XSTORM_CORE_CONN_AG_CTX_CF12EN_MASK 0x1 /* cf12en */ +#define XSTORM_CORE_CONN_AG_CTX_CF12EN_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_CF13EN_MASK 0x1 /* cf13en */ +#define XSTORM_CORE_CONN_AG_CTX_CF13EN_SHIFT 3 +#define XSTORM_CORE_CONN_AG_CTX_CF14EN_MASK 0x1 /* cf14en */ +#define XSTORM_CORE_CONN_AG_CTX_CF14EN_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_CF15EN_MASK 0x1 /* cf15en */ +#define XSTORM_CORE_CONN_AG_CTX_CF15EN_SHIFT 5 +#define XSTORM_CORE_CONN_AG_CTX_CONSOLID_PROD_CF_EN_MASK 0x1 /* cf16en */ +#define XSTORM_CORE_CONN_AG_CTX_CONSOLID_PROD_CF_EN_SHIFT 6 +#define XSTORM_CORE_CONN_AG_CTX_CF17EN_MASK 0x1 +#define XSTORM_CORE_CONN_AG_CTX_CF17EN_SHIFT 7 + u8 flags10; +#define XSTORM_CORE_CONN_AG_CTX_DQ_CF_EN_MASK 0x1 /* cf18en */ +#define XSTORM_CORE_CONN_AG_CTX_DQ_CF_EN_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_TERMINATE_CF_EN_MASK 0x1 /* cf19en */ +#define XSTORM_CORE_CONN_AG_CTX_TERMINATE_CF_EN_SHIFT 1 +#define XSTORM_CORE_CONN_AG_CTX_FLUSH_Q0_EN_MASK 0x1 /* cf20en */ +#define XSTORM_CORE_CONN_AG_CTX_FLUSH_Q0_EN_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED11_MASK 0x1 /* cf21en */ +#define XSTORM_CORE_CONN_AG_CTX_RESERVED11_SHIFT 3 +#define XSTORM_CORE_CONN_AG_CTX_SLOW_PATH_EN_MASK 0x1 /* cf22en */ +#define XSTORM_CORE_CONN_AG_CTX_SLOW_PATH_EN_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_CF23EN_MASK 0x1 /* cf23en */ +#define XSTORM_CORE_CONN_AG_CTX_CF23EN_SHIFT 5 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED12_MASK 0x1 /* rule0en */ +#define XSTORM_CORE_CONN_AG_CTX_RESERVED12_SHIFT 6 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED13_MASK 0x1 /* rule1en */ +#define XSTORM_CORE_CONN_AG_CTX_RESERVED13_SHIFT 7 + u8 flags11; +#define XSTORM_CORE_CONN_AG_CTX_RESERVED14_MASK 0x1 /* rule2en */ +#define XSTORM_CORE_CONN_AG_CTX_RESERVED14_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_RESERVED15_MASK 0x1 /* rule3en */ +#define XSTORM_CORE_CONN_AG_CTX_RESERVED15_SHIFT 1 +#define XSTORM_CORE_CONN_AG_CTX_TX_DEC_RULE_EN_MASK 0x1 /* rule4en */ +#define XSTORM_CORE_CONN_AG_CTX_TX_DEC_RULE_EN_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_RULE5EN_MASK 0x1 /* rule5en */ +#define XSTORM_CORE_CONN_AG_CTX_RULE5EN_SHIFT 3 +#define XSTORM_CORE_CONN_AG_CTX_RULE6EN_MASK 0x1 /* rule6en */ +#define XSTORM_CORE_CONN_AG_CTX_RULE6EN_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_RULE7EN_MASK 0x1 /* rule7en */ +#define XSTORM_CORE_CONN_AG_CTX_RULE7EN_SHIFT 5 +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED1_MASK 0x1 /* rule8en */ +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED1_SHIFT 6 +#define XSTORM_CORE_CONN_AG_CTX_RULE9EN_MASK 0x1 /* rule9en */ +#define XSTORM_CORE_CONN_AG_CTX_RULE9EN_SHIFT 7 + u8 flags12; +#define XSTORM_CORE_CONN_AG_CTX_RULE10EN_MASK 0x1 /* rule10en */ +#define XSTORM_CORE_CONN_AG_CTX_RULE10EN_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_RULE11EN_MASK 0x1 /* rule11en */ +#define XSTORM_CORE_CONN_AG_CTX_RULE11EN_SHIFT 1 +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED2_MASK 0x1 /* rule12en */ +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED2_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED3_MASK 0x1 /* rule13en */ +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED3_SHIFT 3 +#define XSTORM_CORE_CONN_AG_CTX_RULE14EN_MASK 0x1 /* rule14en */ +#define XSTORM_CORE_CONN_AG_CTX_RULE14EN_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_RULE15EN_MASK 0x1 /* rule15en */ +#define XSTORM_CORE_CONN_AG_CTX_RULE15EN_SHIFT 5 +#define XSTORM_CORE_CONN_AG_CTX_RULE16EN_MASK 0x1 /* rule16en */ +#define XSTORM_CORE_CONN_AG_CTX_RULE16EN_SHIFT 6 +#define XSTORM_CORE_CONN_AG_CTX_RULE17EN_MASK 0x1 /* rule17en */ +#define XSTORM_CORE_CONN_AG_CTX_RULE17EN_SHIFT 7 + u8 flags13; +#define XSTORM_CORE_CONN_AG_CTX_RULE18EN_MASK 0x1 /* rule18en */ +#define XSTORM_CORE_CONN_AG_CTX_RULE18EN_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_RULE19EN_MASK 0x1 /* rule19en */ +#define XSTORM_CORE_CONN_AG_CTX_RULE19EN_SHIFT 1 +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED4_MASK 0x1 /* rule20en */ +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED4_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED5_MASK 0x1 /* rule21en */ +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED5_SHIFT 3 +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED6_MASK 0x1 /* rule22en */ +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED6_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED7_MASK 0x1 /* rule23en */ +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED7_SHIFT 5 +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED8_MASK 0x1 /* rule24en */ +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED8_SHIFT 6 +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED9_MASK 0x1 /* rule25en */ +#define XSTORM_CORE_CONN_AG_CTX_A0_RESERVED9_SHIFT 7 + u8 flags14; +#define XSTORM_CORE_CONN_AG_CTX_BIT16_MASK 0x1 /* bit16 */ +#define XSTORM_CORE_CONN_AG_CTX_BIT16_SHIFT 0 +#define XSTORM_CORE_CONN_AG_CTX_BIT17_MASK 0x1 /* bit17 */ +#define XSTORM_CORE_CONN_AG_CTX_BIT17_SHIFT 1 +#define XSTORM_CORE_CONN_AG_CTX_BIT18_MASK 0x1 /* bit18 */ +#define XSTORM_CORE_CONN_AG_CTX_BIT18_SHIFT 2 +#define XSTORM_CORE_CONN_AG_CTX_BIT19_MASK 0x1 /* bit19 */ +#define XSTORM_CORE_CONN_AG_CTX_BIT19_SHIFT 3 +#define XSTORM_CORE_CONN_AG_CTX_BIT20_MASK 0x1 /* bit20 */ +#define XSTORM_CORE_CONN_AG_CTX_BIT20_SHIFT 4 +#define XSTORM_CORE_CONN_AG_CTX_BIT21_MASK 0x1 /* bit21 */ +#define XSTORM_CORE_CONN_AG_CTX_BIT21_SHIFT 5 +#define XSTORM_CORE_CONN_AG_CTX_CF23_MASK 0x3 /* cf23 */ +#define XSTORM_CORE_CONN_AG_CTX_CF23_SHIFT 6 + u8 byte2 /* byte2 */; + __le16 physical_q0 /* physical_q0 */; + __le16 consolid_prod /* physical_q1 */; + __le16 reserved16 /* physical_q2 */; + __le16 tx_bd_cons /* word3 */; + __le16 tx_bd_or_spq_prod /* word4 */; + __le16 word5 /* word5 */; + __le16 conn_dpi /* conn_dpi */; + u8 byte3 /* byte3 */; + u8 byte4 /* byte4 */; + u8 byte5 /* byte5 */; + u8 byte6 /* byte6 */; + __le32 reg0 /* reg0 */; + __le32 reg1 /* reg1 */; + __le32 reg2 /* reg2 */; + __le32 reg3 /* reg3 */; + __le32 reg4 /* reg4 */; + __le32 reg5 /* cf_array0 */; + __le32 reg6 /* cf_array1 */; + __le16 word7 /* word7 */; + __le16 word8 /* word8 */; + __le16 word9 /* word9 */; + __le16 word10 /* word10 */; + __le32 reg7 /* reg7 */; + __le32 reg8 /* reg8 */; + __le32 reg9 /* reg9 */; + u8 byte7 /* byte7 */; + u8 byte8 /* byte8 */; + u8 byte9 /* byte9 */; + u8 byte10 /* byte10 */; + u8 byte11 /* byte11 */; + u8 byte12 /* byte12 */; + u8 byte13 /* byte13 */; + u8 byte14 /* byte14 */; + u8 byte15 /* byte15 */; + u8 byte16 /* byte16 */; + __le16 word11 /* word11 */; + __le32 reg10 /* reg10 */; + __le32 reg11 /* reg11 */; + __le32 reg12 /* reg12 */; + __le32 reg13 /* reg13 */; + __le32 reg14 /* reg14 */; + __le32 reg15 /* reg15 */; + __le32 reg16 /* reg16 */; + __le32 reg17 /* reg17 */; + __le32 reg18 /* reg18 */; + __le32 reg19 /* reg19 */; + __le16 word12 /* word12 */; + __le16 word13 /* word13 */; + __le16 word14 /* word14 */; + __le16 word15 /* word15 */; +}; + +/* The core storm context for the Mstorm */ +struct mstorm_core_conn_st_ctx { + __le32 reserved[24]; +}; + +/* The core storm context for the Ustorm */ +struct ustorm_core_conn_st_ctx { + __le32 reserved[4]; +}; + +/* core connection context */ +struct core_conn_context { + struct ystorm_core_conn_st_ctx ystorm_st_context; + struct regpair ystorm_st_padding[2] /* padding */; + struct pstorm_core_conn_st_ctx pstorm_st_context; + struct regpair pstorm_st_padding[2]; + struct xstorm_core_conn_st_ctx xstorm_st_context; + struct xstorm_core_conn_ag_ctx xstorm_ag_context; + struct mstorm_core_conn_st_ctx mstorm_st_context; + struct regpair mstorm_st_padding[2]; + struct ustorm_core_conn_st_ctx ustorm_st_context; + struct regpair ustorm_st_padding[2] /* padding */; +}; + +/* Event Ring Next Page Address */ +struct event_ring_next_addr { + struct regpair addr /* Next Page Address */; + __le32 reserved[2] /* Reserved */; +}; + +union event_ring_element { + struct event_ring_entry entry /* Event Ring Entry */; + struct event_ring_next_addr next_addr; +}; + +enum personality_type { + PERSONALITY_RESERVED, + PERSONALITY_RESERVED2, + PERSONALITY_RDMA_AND_ETH /* Roce or Iwarp */, + PERSONALITY_RESERVED3, + PERSONALITY_ETH /* Ethernet */, + PERSONALITY_RESERVED4, + MAX_PERSONALITY_TYPE +}; + +struct pf_start_tunnel_config { + u8 set_vxlan_udp_port_flg; + u8 set_geneve_udp_port_flg; + u8 tx_enable_vxlan /* If set, enable VXLAN tunnel in TX path. */; + u8 tx_enable_l2geneve; + u8 tx_enable_ipgeneve; + u8 tx_enable_l2gre /* If set, enable l2 GRE tunnel in TX path. */; + u8 tx_enable_ipgre /* If set, enable IP GRE tunnel in TX path. */; + u8 tunnel_clss_vxlan /* Classification scheme for VXLAN tunnel. */; + u8 tunnel_clss_l2geneve; + u8 tunnel_clss_ipgeneve; + u8 tunnel_clss_l2gre; + u8 tunnel_clss_ipgre; + __le16 vxlan_udp_port /* VXLAN tunnel UDP destination port. */; + __le16 geneve_udp_port /* GENEVE tunnel UDP destination port. */; +}; + +/* Ramrod data for PF start ramrod */ +struct pf_start_ramrod_data { + struct regpair event_ring_pbl_addr; + struct regpair consolid_q_pbl_addr; + struct pf_start_tunnel_config tunnel_config; + __le16 event_ring_sb_id; + u8 base_vf_id; + u8 num_vfs; + u8 event_ring_num_pages; + u8 event_ring_sb_index; + u8 path_id; + u8 warning_as_error; + u8 dont_log_ramrods; + u8 personality; + __le16 log_type_mask; + u8 mf_mode /* Multi function mode */; + u8 integ_phase /* Integration phase */; + u8 allow_npar_tx_switching; + u8 inner_to_outer_pri_map[8]; + u8 pri_map_valid; + u32 outer_tag; + u8 reserved0[4]; +}; + +enum ports_mode { + ENGX2_PORTX1 /* 2 engines x 1 port */, + ENGX2_PORTX2 /* 2 engines x 2 ports */, + ENGX1_PORTX1 /* 1 engine x 1 port */, + ENGX1_PORTX2 /* 1 engine x 2 ports */, + ENGX1_PORTX4 /* 1 engine x 4 ports */, + MAX_PORTS_MODE +}; + +/* Ramrod Header of SPQE */ +struct ramrod_header { + __le32 cid /* Slowpath Connection CID */; + u8 cmd_id /* Ramrod Cmd (Per Protocol Type) */; + u8 protocol_id /* Ramrod Protocol ID */; + __le16 echo /* Ramrod echo */; +}; + +/* Slowpath Element (SPQE) */ +struct slow_path_element { + struct ramrod_header hdr /* Ramrod Header */; + struct regpair data_ptr; +}; + +struct tstorm_per_port_stat { + struct regpair trunc_error_discard; + struct regpair mac_error_discard; + struct regpair mftag_filter_discard; + struct regpair eth_mac_filter_discard; + struct regpair ll2_mac_filter_discard; + struct regpair ll2_conn_disabled_discard; + struct regpair iscsi_irregular_pkt; + struct regpair fcoe_irregular_pkt; + struct regpair roce_irregular_pkt; + struct regpair eth_irregular_pkt; + struct regpair toe_irregular_pkt; + struct regpair preroce_irregular_pkt; +}; + +struct atten_status_block { + __le32 atten_bits; + __le32 atten_ack; + __le16 reserved0; + __le16 sb_index /* status block running index */; + __le32 reserved1; +}; + +enum block_addr { + GRCBASE_GRC = 0x50000, + GRCBASE_MISCS = 0x9000, + GRCBASE_MISC = 0x8000, + GRCBASE_DBU = 0xa000, + GRCBASE_PGLUE_B = 0x2a8000, + GRCBASE_CNIG = 0x218000, + GRCBASE_CPMU = 0x30000, + GRCBASE_NCSI = 0x40000, + GRCBASE_OPTE = 0x53000, + GRCBASE_BMB = 0x540000, + GRCBASE_PCIE = 0x54000, + GRCBASE_MCP = 0xe00000, + GRCBASE_MCP2 = 0x52000, + GRCBASE_PSWHST = 0x2a0000, + GRCBASE_PSWHST2 = 0x29e000, + GRCBASE_PSWRD = 0x29c000, + GRCBASE_PSWRD2 = 0x29d000, + GRCBASE_PSWWR = 0x29a000, + GRCBASE_PSWWR2 = 0x29b000, + GRCBASE_PSWRQ = 0x280000, + GRCBASE_PSWRQ2 = 0x240000, + GRCBASE_PGLCS = 0x0, + GRCBASE_PTU = 0x560000, + GRCBASE_DMAE = 0xc000, + GRCBASE_TCM = 0x1180000, + GRCBASE_MCM = 0x1200000, + GRCBASE_UCM = 0x1280000, + GRCBASE_XCM = 0x1000000, + GRCBASE_YCM = 0x1080000, + GRCBASE_PCM = 0x1100000, + GRCBASE_QM = 0x2f0000, + GRCBASE_TM = 0x2c0000, + GRCBASE_DORQ = 0x100000, + GRCBASE_BRB = 0x340000, + GRCBASE_SRC = 0x238000, + GRCBASE_PRS = 0x1f0000, + GRCBASE_TSDM = 0xfb0000, + GRCBASE_MSDM = 0xfc0000, + GRCBASE_USDM = 0xfd0000, + GRCBASE_XSDM = 0xf80000, + GRCBASE_YSDM = 0xf90000, + GRCBASE_PSDM = 0xfa0000, + GRCBASE_TSEM = 0x1700000, + GRCBASE_MSEM = 0x1800000, + GRCBASE_USEM = 0x1900000, + GRCBASE_XSEM = 0x1400000, + GRCBASE_YSEM = 0x1500000, + GRCBASE_PSEM = 0x1600000, + GRCBASE_RSS = 0x238800, + GRCBASE_TMLD = 0x4d0000, + GRCBASE_MULD = 0x4e0000, + GRCBASE_YULD = 0x4c8000, + GRCBASE_XYLD = 0x4c0000, + GRCBASE_PRM = 0x230000, + GRCBASE_PBF_PB1 = 0xda0000, + GRCBASE_PBF_PB2 = 0xda4000, + GRCBASE_RPB = 0x23c000, + GRCBASE_BTB = 0xdb0000, + GRCBASE_PBF = 0xd80000, + GRCBASE_RDIF = 0x300000, + GRCBASE_TDIF = 0x310000, + GRCBASE_CDU = 0x580000, + GRCBASE_CCFC = 0x2e0000, + GRCBASE_TCFC = 0x2d0000, + GRCBASE_IGU = 0x180000, + GRCBASE_CAU = 0x1c0000, + GRCBASE_UMAC = 0x51000, + GRCBASE_XMAC = 0x210000, + GRCBASE_DBG = 0x10000, + GRCBASE_NIG = 0x500000, + GRCBASE_WOL = 0x600000, + GRCBASE_BMBN = 0x610000, + GRCBASE_IPC = 0x20000, + GRCBASE_NWM = 0x800000, + GRCBASE_NWS = 0x700000, + GRCBASE_MS = 0x6a0000, + GRCBASE_PHY_PCIE = 0x618000, + GRCBASE_MISC_AEU = 0x8000, + GRCBASE_BAR0_MAP = 0x1c00000, + MAX_BLOCK_ADDR +}; + +enum block_id { + BLOCK_GRC, + BLOCK_MISCS, + BLOCK_MISC, + BLOCK_DBU, + BLOCK_PGLUE_B, + BLOCK_CNIG, + BLOCK_CPMU, + BLOCK_NCSI, + BLOCK_OPTE, + BLOCK_BMB, + BLOCK_PCIE, + BLOCK_MCP, + BLOCK_MCP2, + BLOCK_PSWHST, + BLOCK_PSWHST2, + BLOCK_PSWRD, + BLOCK_PSWRD2, + BLOCK_PSWWR, + BLOCK_PSWWR2, + BLOCK_PSWRQ, + BLOCK_PSWRQ2, + BLOCK_PGLCS, + BLOCK_PTU, + BLOCK_DMAE, + BLOCK_TCM, + BLOCK_MCM, + BLOCK_UCM, + BLOCK_XCM, + BLOCK_YCM, + BLOCK_PCM, + BLOCK_QM, + BLOCK_TM, + BLOCK_DORQ, + BLOCK_BRB, + BLOCK_SRC, + BLOCK_PRS, + BLOCK_TSDM, + BLOCK_MSDM, + BLOCK_USDM, + BLOCK_XSDM, + BLOCK_YSDM, + BLOCK_PSDM, + BLOCK_TSEM, + BLOCK_MSEM, + BLOCK_USEM, + BLOCK_XSEM, + BLOCK_YSEM, + BLOCK_PSEM, + BLOCK_RSS, + BLOCK_TMLD, + BLOCK_MULD, + BLOCK_YULD, + BLOCK_XYLD, + BLOCK_PRM, + BLOCK_PBF_PB1, + BLOCK_PBF_PB2, + BLOCK_RPB, + BLOCK_BTB, + BLOCK_PBF, + BLOCK_RDIF, + BLOCK_TDIF, + BLOCK_CDU, + BLOCK_CCFC, + BLOCK_TCFC, + BLOCK_IGU, + BLOCK_CAU, + BLOCK_UMAC, + BLOCK_XMAC, + BLOCK_DBG, + BLOCK_NIG, + BLOCK_WOL, + BLOCK_BMBN, + BLOCK_IPC, + BLOCK_NWM, + BLOCK_NWS, + BLOCK_MS, + BLOCK_PHY_PCIE, + BLOCK_MISC_AEU, + BLOCK_BAR0_MAP, + MAX_BLOCK_ID +}; + +enum command_type_bit { + IGU_COMMAND_TYPE_NOP = 0, + IGU_COMMAND_TYPE_SET = 1, + MAX_COMMAND_TYPE_BIT +}; + +struct dmae_cmd { + __le32 opcode; +#define DMAE_CMD_SRC_MASK 0x1 +#define DMAE_CMD_SRC_SHIFT 0 +#define DMAE_CMD_DST_MASK 0x3 +#define DMAE_CMD_DST_SHIFT 1 +#define DMAE_CMD_C_DST_MASK 0x1 +#define DMAE_CMD_C_DST_SHIFT 3 +#define DMAE_CMD_CRC_RESET_MASK 0x1 +#define DMAE_CMD_CRC_RESET_SHIFT 4 +#define DMAE_CMD_SRC_ADDR_RESET_MASK 0x1 +#define DMAE_CMD_SRC_ADDR_RESET_SHIFT 5 +#define DMAE_CMD_DST_ADDR_RESET_MASK 0x1 +#define DMAE_CMD_DST_ADDR_RESET_SHIFT 6 +#define DMAE_CMD_COMP_FUNC_MASK 0x1 +#define DMAE_CMD_COMP_FUNC_SHIFT 7 +#define DMAE_CMD_COMP_WORD_EN_MASK 0x1 +#define DMAE_CMD_COMP_WORD_EN_SHIFT 8 +#define DMAE_CMD_COMP_CRC_EN_MASK 0x1 +#define DMAE_CMD_COMP_CRC_EN_SHIFT 9 +#define DMAE_CMD_COMP_CRC_OFFSET_MASK 0x7 +#define DMAE_CMD_COMP_CRC_OFFSET_SHIFT 10 +#define DMAE_CMD_RESERVED1_MASK 0x1 +#define DMAE_CMD_RESERVED1_SHIFT 13 +#define DMAE_CMD_ENDIANITY_MODE_MASK 0x3 +#define DMAE_CMD_ENDIANITY_MODE_SHIFT 14 +#define DMAE_CMD_ERR_HANDLING_MASK 0x3 +#define DMAE_CMD_ERR_HANDLING_SHIFT 16 +#define DMAE_CMD_PORT_ID_MASK 0x3 +#define DMAE_CMD_PORT_ID_SHIFT 18 +#define DMAE_CMD_SRC_PF_ID_MASK 0xF +#define DMAE_CMD_SRC_PF_ID_SHIFT 20 +#define DMAE_CMD_DST_PF_ID_MASK 0xF +#define DMAE_CMD_DST_PF_ID_SHIFT 24 +#define DMAE_CMD_SRC_VF_ID_VALID_MASK 0x1 +#define DMAE_CMD_SRC_VF_ID_VALID_SHIFT 28 +#define DMAE_CMD_DST_VF_ID_VALID_MASK 0x1 +#define DMAE_CMD_DST_VF_ID_VALID_SHIFT 29 +#define DMAE_CMD_RESERVED2_MASK 0x3 +#define DMAE_CMD_RESERVED2_SHIFT 30 + __le32 src_addr_lo; + __le32 src_addr_hi; + __le32 dst_addr_lo; + __le32 dst_addr_hi; + __le16 length /* Length in DW */; + __le16 opcode_b; +#define DMAE_CMD_SRC_VF_ID_MASK 0xFF /* Source VF id */ +#define DMAE_CMD_SRC_VF_ID_SHIFT 0 +#define DMAE_CMD_DST_VF_ID_MASK 0xFF /* Destination VF id */ +#define DMAE_CMD_DST_VF_ID_SHIFT 8 + __le32 comp_addr_lo /* PCIe completion address low or grc address */; + __le32 comp_addr_hi; + __le32 comp_val /* Value to write to copmletion address */; + __le32 crc32 /* crc16 result */; + __le32 crc_32_c /* crc32_c result */; + __le16 crc16 /* crc16 result */; + __le16 crc16_c /* crc16_c result */; + __le16 crc10 /* crc_t10 result */; + __le16 reserved; + __le16 xsum16 /* checksum16 result */; + __le16 xsum8 /* checksum8 result */; +}; + +struct igu_cleanup { + __le32 sb_id_and_flags; +#define IGU_CLEANUP_RESERVED0_MASK 0x7FFFFFF +#define IGU_CLEANUP_RESERVED0_SHIFT 0 +#define IGU_CLEANUP_CLEANUP_SET_MASK 0x1 /* cleanup clear - 0, set - 1 */ +#define IGU_CLEANUP_CLEANUP_SET_SHIFT 27 +#define IGU_CLEANUP_CLEANUP_TYPE_MASK 0x7 +#define IGU_CLEANUP_CLEANUP_TYPE_SHIFT 28 +#define IGU_CLEANUP_COMMAND_TYPE_MASK 0x1 +#define IGU_CLEANUP_COMMAND_TYPE_SHIFT 31 + __le32 reserved1; +}; + +union igu_command { + struct igu_prod_cons_update prod_cons_update; + struct igu_cleanup cleanup; +}; + +struct igu_command_reg_ctrl { + __le16 opaque_fid; + __le16 igu_command_reg_ctrl_fields; +#define IGU_COMMAND_REG_CTRL_PXP_BAR_ADDR_MASK 0xFFF +#define IGU_COMMAND_REG_CTRL_PXP_BAR_ADDR_SHIFT 0 +#define IGU_COMMAND_REG_CTRL_RESERVED_MASK 0x7 +#define IGU_COMMAND_REG_CTRL_RESERVED_SHIFT 12 +#define IGU_COMMAND_REG_CTRL_COMMAND_TYPE_MASK 0x1 +#define IGU_COMMAND_REG_CTRL_COMMAND_TYPE_SHIFT 15 +}; + +struct igu_mapping_line { + __le32 igu_mapping_line_fields; +#define IGU_MAPPING_LINE_VALID_MASK 0x1 +#define IGU_MAPPING_LINE_VALID_SHIFT 0 +#define IGU_MAPPING_LINE_VECTOR_NUMBER_MASK 0xFF +#define IGU_MAPPING_LINE_VECTOR_NUMBER_SHIFT 1 +#define IGU_MAPPING_LINE_FUNCTION_NUMBER_MASK 0xFF +#define IGU_MAPPING_LINE_FUNCTION_NUMBER_SHIFT 9 +#define IGU_MAPPING_LINE_PF_VALID_MASK 0x1 /* PF-1, VF-0 */ +#define IGU_MAPPING_LINE_PF_VALID_SHIFT 17 +#define IGU_MAPPING_LINE_IPS_GROUP_MASK 0x3F +#define IGU_MAPPING_LINE_IPS_GROUP_SHIFT 18 +#define IGU_MAPPING_LINE_RESERVED_MASK 0xFF +#define IGU_MAPPING_LINE_RESERVED_SHIFT 24 +}; + +struct igu_msix_vector { + struct regpair address; + __le32 data; + __le32 msix_vector_fields; +#define IGU_MSIX_VECTOR_MASK_BIT_MASK 0x1 +#define IGU_MSIX_VECTOR_MASK_BIT_SHIFT 0 +#define IGU_MSIX_VECTOR_RESERVED0_MASK 0x7FFF +#define IGU_MSIX_VECTOR_RESERVED0_SHIFT 1 +#define IGU_MSIX_VECTOR_STEERING_TAG_MASK 0xFF +#define IGU_MSIX_VECTOR_STEERING_TAG_SHIFT 16 +#define IGU_MSIX_VECTOR_RESERVED1_MASK 0xFF +#define IGU_MSIX_VECTOR_RESERVED1_SHIFT 24 +}; + +enum init_modes { + MODE_BB_A0, + MODE_RESERVED, + MODE_RESERVED2, + MODE_ASIC, + MODE_RESERVED3, + MODE_RESERVED4, + MODE_RESERVED5, + MODE_SF, + MODE_MF_SD, + MODE_MF_SI, + MODE_PORTS_PER_ENG_1, + MODE_PORTS_PER_ENG_2, + MODE_PORTS_PER_ENG_4, + MODE_40G, + MODE_100G, + MODE_EAGLE_ENG1_WORKAROUND, + MAX_INIT_MODES +}; + +enum init_phases { + PHASE_ENGINE, + PHASE_PORT, + PHASE_PF, + PHASE_RESERVED, + PHASE_QM_PF, + MAX_INIT_PHASES +}; + +struct mstorm_core_conn_ag_ctx { + u8 byte0 /* cdu_validation */; + u8 byte1 /* state */; + u8 flags0; +#define MSTORM_CORE_CONN_AG_CTX_BIT0_MASK 0x1 /* exist_in_qm0 */ +#define MSTORM_CORE_CONN_AG_CTX_BIT0_SHIFT 0 +#define MSTORM_CORE_CONN_AG_CTX_BIT1_MASK 0x1 /* exist_in_qm1 */ +#define MSTORM_CORE_CONN_AG_CTX_BIT1_SHIFT 1 +#define MSTORM_CORE_CONN_AG_CTX_CF0_MASK 0x3 /* cf0 */ +#define MSTORM_CORE_CONN_AG_CTX_CF0_SHIFT 2 +#define MSTORM_CORE_CONN_AG_CTX_CF1_MASK 0x3 /* cf1 */ +#define MSTORM_CORE_CONN_AG_CTX_CF1_SHIFT 4 +#define MSTORM_CORE_CONN_AG_CTX_CF2_MASK 0x3 /* cf2 */ +#define MSTORM_CORE_CONN_AG_CTX_CF2_SHIFT 6 + u8 flags1; +#define MSTORM_CORE_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */ +#define MSTORM_CORE_CONN_AG_CTX_CF0EN_SHIFT 0 +#define MSTORM_CORE_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */ +#define MSTORM_CORE_CONN_AG_CTX_CF1EN_SHIFT 1 +#define MSTORM_CORE_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */ +#define MSTORM_CORE_CONN_AG_CTX_CF2EN_SHIFT 2 +#define MSTORM_CORE_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */ +#define MSTORM_CORE_CONN_AG_CTX_RULE0EN_SHIFT 3 +#define MSTORM_CORE_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */ +#define MSTORM_CORE_CONN_AG_CTX_RULE1EN_SHIFT 4 +#define MSTORM_CORE_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */ +#define MSTORM_CORE_CONN_AG_CTX_RULE2EN_SHIFT 5 +#define MSTORM_CORE_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */ +#define MSTORM_CORE_CONN_AG_CTX_RULE3EN_SHIFT 6 +#define MSTORM_CORE_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */ +#define MSTORM_CORE_CONN_AG_CTX_RULE4EN_SHIFT 7 + __le16 word0 /* word0 */; + __le16 word1 /* word1 */; + __le32 reg0 /* reg0 */; + __le32 reg1 /* reg1 */; +}; + +/* per encapsulation type enabling flags */ +struct prs_reg_encapsulation_type_en { + u8 flags; +#define PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GRE_ENABLE_MASK 0x1 +#define PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GRE_ENABLE_SHIFT 0 +#define PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GRE_ENABLE_MASK 0x1 +#define PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GRE_ENABLE_SHIFT 1 +#define PRS_REG_ENCAPSULATION_TYPE_EN_VXLAN_ENABLE_MASK 0x1 +#define PRS_REG_ENCAPSULATION_TYPE_EN_VXLAN_ENABLE_SHIFT 2 +#define PRS_REG_ENCAPSULATION_TYPE_EN_T_TAG_ENABLE_MASK 0x1 +#define PRS_REG_ENCAPSULATION_TYPE_EN_T_TAG_ENABLE_SHIFT 3 +#define PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GENEVE_ENABLE_MASK 0x1 +#define PRS_REG_ENCAPSULATION_TYPE_EN_ETH_OVER_GENEVE_ENABLE_SHIFT 4 +#define PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GENEVE_ENABLE_MASK 0x1 +#define PRS_REG_ENCAPSULATION_TYPE_EN_IP_OVER_GENEVE_ENABLE_SHIFT 5 +#define PRS_REG_ENCAPSULATION_TYPE_EN_RESERVED_MASK 0x3 +#define PRS_REG_ENCAPSULATION_TYPE_EN_RESERVED_SHIFT 6 +}; + +enum pxp_tph_st_hint { + TPH_ST_HINT_BIDIR /* Read/Write access by Host and Device */, + TPH_ST_HINT_REQUESTER /* Read/Write access by Device */, + TPH_ST_HINT_TARGET, + TPH_ST_HINT_TARGET_PRIO, + MAX_PXP_TPH_ST_HINT +}; + +/* QM hardware structure of enable bypass credit mask */ +struct qm_rf_bypass_mask { + u8 flags; +#define QM_RF_BYPASS_MASK_LINEVOQ_MASK 0x1 +#define QM_RF_BYPASS_MASK_LINEVOQ_SHIFT 0 +#define QM_RF_BYPASS_MASK_RESERVED0_MASK 0x1 +#define QM_RF_BYPASS_MASK_RESERVED0_SHIFT 1 +#define QM_RF_BYPASS_MASK_PFWFQ_MASK 0x1 +#define QM_RF_BYPASS_MASK_PFWFQ_SHIFT 2 +#define QM_RF_BYPASS_MASK_VPWFQ_MASK 0x1 +#define QM_RF_BYPASS_MASK_VPWFQ_SHIFT 3 +#define QM_RF_BYPASS_MASK_PFRL_MASK 0x1 +#define QM_RF_BYPASS_MASK_PFRL_SHIFT 4 +#define QM_RF_BYPASS_MASK_VPQCNRL_MASK 0x1 +#define QM_RF_BYPASS_MASK_VPQCNRL_SHIFT 5 +#define QM_RF_BYPASS_MASK_FWPAUSE_MASK 0x1 +#define QM_RF_BYPASS_MASK_FWPAUSE_SHIFT 6 +#define QM_RF_BYPASS_MASK_RESERVED1_MASK 0x1 +#define QM_RF_BYPASS_MASK_RESERVED1_SHIFT 7 +}; + +/* QM hardware structure of opportunistic credit mask */ +struct qm_rf_opportunistic_mask { + __le16 flags; +#define QM_RF_OPPORTUNISTIC_MASK_LINEVOQ_MASK 0x1 +#define QM_RF_OPPORTUNISTIC_MASK_LINEVOQ_SHIFT 0 +#define QM_RF_OPPORTUNISTIC_MASK_BYTEVOQ_MASK 0x1 +#define QM_RF_OPPORTUNISTIC_MASK_BYTEVOQ_SHIFT 1 +#define QM_RF_OPPORTUNISTIC_MASK_PFWFQ_MASK 0x1 +#define QM_RF_OPPORTUNISTIC_MASK_PFWFQ_SHIFT 2 +#define QM_RF_OPPORTUNISTIC_MASK_VPWFQ_MASK 0x1 +#define QM_RF_OPPORTUNISTIC_MASK_VPWFQ_SHIFT 3 +#define QM_RF_OPPORTUNISTIC_MASK_PFRL_MASK 0x1 +#define QM_RF_OPPORTUNISTIC_MASK_PFRL_SHIFT 4 +#define QM_RF_OPPORTUNISTIC_MASK_VPQCNRL_MASK 0x1 +#define QM_RF_OPPORTUNISTIC_MASK_VPQCNRL_SHIFT 5 +#define QM_RF_OPPORTUNISTIC_MASK_FWPAUSE_MASK 0x1 +#define QM_RF_OPPORTUNISTIC_MASK_FWPAUSE_SHIFT 6 +#define QM_RF_OPPORTUNISTIC_MASK_RESERVED0_MASK 0x1 +#define QM_RF_OPPORTUNISTIC_MASK_RESERVED0_SHIFT 7 +#define QM_RF_OPPORTUNISTIC_MASK_QUEUEEMPTY_MASK 0x1 +#define QM_RF_OPPORTUNISTIC_MASK_QUEUEEMPTY_SHIFT 8 +#define QM_RF_OPPORTUNISTIC_MASK_RESERVED1_MASK 0x7F +#define QM_RF_OPPORTUNISTIC_MASK_RESERVED1_SHIFT 9 +}; + +/* QM hardware structure of QM map memory */ +struct qm_rf_pq_map { + u32 reg; +#define QM_RF_PQ_MAP_PQ_VALID_MASK 0x1 /* PQ active */ +#define QM_RF_PQ_MAP_PQ_VALID_SHIFT 0 +#define QM_RF_PQ_MAP_RL_ID_MASK 0xFF /* RL ID */ +#define QM_RF_PQ_MAP_RL_ID_SHIFT 1 +#define QM_RF_PQ_MAP_VP_PQ_ID_MASK 0x1FF +#define QM_RF_PQ_MAP_VP_PQ_ID_SHIFT 9 +#define QM_RF_PQ_MAP_VOQ_MASK 0x1F /* VOQ */ +#define QM_RF_PQ_MAP_VOQ_SHIFT 18 +#define QM_RF_PQ_MAP_WRR_WEIGHT_GROUP_MASK 0x3 /* WRR weight */ +#define QM_RF_PQ_MAP_WRR_WEIGHT_GROUP_SHIFT 23 +#define QM_RF_PQ_MAP_RL_VALID_MASK 0x1 /* RL active */ +#define QM_RF_PQ_MAP_RL_VALID_SHIFT 25 +#define QM_RF_PQ_MAP_RESERVED_MASK 0x3F +#define QM_RF_PQ_MAP_RESERVED_SHIFT 26 +}; + +/* SDM operation gen command (generate aggregative interrupt) */ +struct sdm_op_gen { + __le32 command; +#define SDM_OP_GEN_COMP_PARAM_MASK 0xFFFF /* completion parameters 0-15 */ +#define SDM_OP_GEN_COMP_PARAM_SHIFT 0 +#define SDM_OP_GEN_COMP_TYPE_MASK 0xF /* completion type 16-19 */ +#define SDM_OP_GEN_COMP_TYPE_SHIFT 16 +#define SDM_OP_GEN_RESERVED_MASK 0xFFF /* reserved 20-31 */ +#define SDM_OP_GEN_RESERVED_SHIFT 20 +}; + +struct tstorm_core_conn_ag_ctx { + u8 byte0 /* cdu_validation */; + u8 byte1 /* state */; + u8 flags0; +#define TSTORM_CORE_CONN_AG_CTX_BIT0_MASK 0x1 /* exist_in_qm0 */ +#define TSTORM_CORE_CONN_AG_CTX_BIT0_SHIFT 0 +#define TSTORM_CORE_CONN_AG_CTX_BIT1_MASK 0x1 /* exist_in_qm1 */ +#define TSTORM_CORE_CONN_AG_CTX_BIT1_SHIFT 1 +#define TSTORM_CORE_CONN_AG_CTX_BIT2_MASK 0x1 /* bit2 */ +#define TSTORM_CORE_CONN_AG_CTX_BIT2_SHIFT 2 +#define TSTORM_CORE_CONN_AG_CTX_BIT3_MASK 0x1 /* bit3 */ +#define TSTORM_CORE_CONN_AG_CTX_BIT3_SHIFT 3 +#define TSTORM_CORE_CONN_AG_CTX_BIT4_MASK 0x1 /* bit4 */ +#define TSTORM_CORE_CONN_AG_CTX_BIT4_SHIFT 4 +#define TSTORM_CORE_CONN_AG_CTX_BIT5_MASK 0x1 /* bit5 */ +#define TSTORM_CORE_CONN_AG_CTX_BIT5_SHIFT 5 +#define TSTORM_CORE_CONN_AG_CTX_CF0_MASK 0x3 /* timer0cf */ +#define TSTORM_CORE_CONN_AG_CTX_CF0_SHIFT 6 + u8 flags1; +#define TSTORM_CORE_CONN_AG_CTX_CF1_MASK 0x3 /* timer1cf */ +#define TSTORM_CORE_CONN_AG_CTX_CF1_SHIFT 0 +#define TSTORM_CORE_CONN_AG_CTX_CF2_MASK 0x3 /* timer2cf */ +#define TSTORM_CORE_CONN_AG_CTX_CF2_SHIFT 2 +#define TSTORM_CORE_CONN_AG_CTX_CF3_MASK 0x3 /* timer_stop_all */ +#define TSTORM_CORE_CONN_AG_CTX_CF3_SHIFT 4 +#define TSTORM_CORE_CONN_AG_CTX_CF4_MASK 0x3 /* cf4 */ +#define TSTORM_CORE_CONN_AG_CTX_CF4_SHIFT 6 + u8 flags2; +#define TSTORM_CORE_CONN_AG_CTX_CF5_MASK 0x3 /* cf5 */ +#define TSTORM_CORE_CONN_AG_CTX_CF5_SHIFT 0 +#define TSTORM_CORE_CONN_AG_CTX_CF6_MASK 0x3 /* cf6 */ +#define TSTORM_CORE_CONN_AG_CTX_CF6_SHIFT 2 +#define TSTORM_CORE_CONN_AG_CTX_CF7_MASK 0x3 /* cf7 */ +#define TSTORM_CORE_CONN_AG_CTX_CF7_SHIFT 4 +#define TSTORM_CORE_CONN_AG_CTX_CF8_MASK 0x3 /* cf8 */ +#define TSTORM_CORE_CONN_AG_CTX_CF8_SHIFT 6 + u8 flags3; +#define TSTORM_CORE_CONN_AG_CTX_CF9_MASK 0x3 /* cf9 */ +#define TSTORM_CORE_CONN_AG_CTX_CF9_SHIFT 0 +#define TSTORM_CORE_CONN_AG_CTX_CF10_MASK 0x3 /* cf10 */ +#define TSTORM_CORE_CONN_AG_CTX_CF10_SHIFT 2 +#define TSTORM_CORE_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */ +#define TSTORM_CORE_CONN_AG_CTX_CF0EN_SHIFT 4 +#define TSTORM_CORE_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */ +#define TSTORM_CORE_CONN_AG_CTX_CF1EN_SHIFT 5 +#define TSTORM_CORE_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */ +#define TSTORM_CORE_CONN_AG_CTX_CF2EN_SHIFT 6 +#define TSTORM_CORE_CONN_AG_CTX_CF3EN_MASK 0x1 /* cf3en */ +#define TSTORM_CORE_CONN_AG_CTX_CF3EN_SHIFT 7 + u8 flags4; +#define TSTORM_CORE_CONN_AG_CTX_CF4EN_MASK 0x1 /* cf4en */ +#define TSTORM_CORE_CONN_AG_CTX_CF4EN_SHIFT 0 +#define TSTORM_CORE_CONN_AG_CTX_CF5EN_MASK 0x1 /* cf5en */ +#define TSTORM_CORE_CONN_AG_CTX_CF5EN_SHIFT 1 +#define TSTORM_CORE_CONN_AG_CTX_CF6EN_MASK 0x1 /* cf6en */ +#define TSTORM_CORE_CONN_AG_CTX_CF6EN_SHIFT 2 +#define TSTORM_CORE_CONN_AG_CTX_CF7EN_MASK 0x1 /* cf7en */ +#define TSTORM_CORE_CONN_AG_CTX_CF7EN_SHIFT 3 +#define TSTORM_CORE_CONN_AG_CTX_CF8EN_MASK 0x1 /* cf8en */ +#define TSTORM_CORE_CONN_AG_CTX_CF8EN_SHIFT 4 +#define TSTORM_CORE_CONN_AG_CTX_CF9EN_MASK 0x1 /* cf9en */ +#define TSTORM_CORE_CONN_AG_CTX_CF9EN_SHIFT 5 +#define TSTORM_CORE_CONN_AG_CTX_CF10EN_MASK 0x1 /* cf10en */ +#define TSTORM_CORE_CONN_AG_CTX_CF10EN_SHIFT 6 +#define TSTORM_CORE_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */ +#define TSTORM_CORE_CONN_AG_CTX_RULE0EN_SHIFT 7 + u8 flags5; +#define TSTORM_CORE_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */ +#define TSTORM_CORE_CONN_AG_CTX_RULE1EN_SHIFT 0 +#define TSTORM_CORE_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */ +#define TSTORM_CORE_CONN_AG_CTX_RULE2EN_SHIFT 1 +#define TSTORM_CORE_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */ +#define TSTORM_CORE_CONN_AG_CTX_RULE3EN_SHIFT 2 +#define TSTORM_CORE_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */ +#define TSTORM_CORE_CONN_AG_CTX_RULE4EN_SHIFT 3 +#define TSTORM_CORE_CONN_AG_CTX_RULE5EN_MASK 0x1 /* rule5en */ +#define TSTORM_CORE_CONN_AG_CTX_RULE5EN_SHIFT 4 +#define TSTORM_CORE_CONN_AG_CTX_RULE6EN_MASK 0x1 /* rule6en */ +#define TSTORM_CORE_CONN_AG_CTX_RULE6EN_SHIFT 5 +#define TSTORM_CORE_CONN_AG_CTX_RULE7EN_MASK 0x1 /* rule7en */ +#define TSTORM_CORE_CONN_AG_CTX_RULE7EN_SHIFT 6 +#define TSTORM_CORE_CONN_AG_CTX_RULE8EN_MASK 0x1 /* rule8en */ +#define TSTORM_CORE_CONN_AG_CTX_RULE8EN_SHIFT 7 + __le32 reg0 /* reg0 */; + __le32 reg1 /* reg1 */; + __le32 reg2 /* reg2 */; + __le32 reg3 /* reg3 */; + __le32 reg4 /* reg4 */; + __le32 reg5 /* reg5 */; + __le32 reg6 /* reg6 */; + __le32 reg7 /* reg7 */; + __le32 reg8 /* reg8 */; + u8 byte2 /* byte2 */; + u8 byte3 /* byte3 */; + __le16 word0 /* word0 */; + u8 byte4 /* byte4 */; + u8 byte5 /* byte5 */; + __le16 word1 /* word1 */; + __le16 word2 /* conn_dpi */; + __le16 word3 /* word3 */; + __le32 reg9 /* reg9 */; + __le32 reg10 /* reg10 */; +}; + +struct ustorm_core_conn_ag_ctx { + u8 reserved /* cdu_validation */; + u8 byte1 /* state */; + u8 flags0; +#define USTORM_CORE_CONN_AG_CTX_BIT0_MASK 0x1 /* exist_in_qm0 */ +#define USTORM_CORE_CONN_AG_CTX_BIT0_SHIFT 0 +#define USTORM_CORE_CONN_AG_CTX_BIT1_MASK 0x1 /* exist_in_qm1 */ +#define USTORM_CORE_CONN_AG_CTX_BIT1_SHIFT 1 +#define USTORM_CORE_CONN_AG_CTX_CF0_MASK 0x3 /* timer0cf */ +#define USTORM_CORE_CONN_AG_CTX_CF0_SHIFT 2 +#define USTORM_CORE_CONN_AG_CTX_CF1_MASK 0x3 /* timer1cf */ +#define USTORM_CORE_CONN_AG_CTX_CF1_SHIFT 4 +#define USTORM_CORE_CONN_AG_CTX_CF2_MASK 0x3 /* timer2cf */ +#define USTORM_CORE_CONN_AG_CTX_CF2_SHIFT 6 + u8 flags1; +#define USTORM_CORE_CONN_AG_CTX_CF3_MASK 0x3 /* timer_stop_all */ +#define USTORM_CORE_CONN_AG_CTX_CF3_SHIFT 0 +#define USTORM_CORE_CONN_AG_CTX_CF4_MASK 0x3 /* cf4 */ +#define USTORM_CORE_CONN_AG_CTX_CF4_SHIFT 2 +#define USTORM_CORE_CONN_AG_CTX_CF5_MASK 0x3 /* cf5 */ +#define USTORM_CORE_CONN_AG_CTX_CF5_SHIFT 4 +#define USTORM_CORE_CONN_AG_CTX_CF6_MASK 0x3 /* cf6 */ +#define USTORM_CORE_CONN_AG_CTX_CF6_SHIFT 6 + u8 flags2; +#define USTORM_CORE_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */ +#define USTORM_CORE_CONN_AG_CTX_CF0EN_SHIFT 0 +#define USTORM_CORE_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */ +#define USTORM_CORE_CONN_AG_CTX_CF1EN_SHIFT 1 +#define USTORM_CORE_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */ +#define USTORM_CORE_CONN_AG_CTX_CF2EN_SHIFT 2 +#define USTORM_CORE_CONN_AG_CTX_CF3EN_MASK 0x1 /* cf3en */ +#define USTORM_CORE_CONN_AG_CTX_CF3EN_SHIFT 3 +#define USTORM_CORE_CONN_AG_CTX_CF4EN_MASK 0x1 /* cf4en */ +#define USTORM_CORE_CONN_AG_CTX_CF4EN_SHIFT 4 +#define USTORM_CORE_CONN_AG_CTX_CF5EN_MASK 0x1 /* cf5en */ +#define USTORM_CORE_CONN_AG_CTX_CF5EN_SHIFT 5 +#define USTORM_CORE_CONN_AG_CTX_CF6EN_MASK 0x1 /* cf6en */ +#define USTORM_CORE_CONN_AG_CTX_CF6EN_SHIFT 6 +#define USTORM_CORE_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */ +#define USTORM_CORE_CONN_AG_CTX_RULE0EN_SHIFT 7 + u8 flags3; +#define USTORM_CORE_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */ +#define USTORM_CORE_CONN_AG_CTX_RULE1EN_SHIFT 0 +#define USTORM_CORE_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */ +#define USTORM_CORE_CONN_AG_CTX_RULE2EN_SHIFT 1 +#define USTORM_CORE_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */ +#define USTORM_CORE_CONN_AG_CTX_RULE3EN_SHIFT 2 +#define USTORM_CORE_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */ +#define USTORM_CORE_CONN_AG_CTX_RULE4EN_SHIFT 3 +#define USTORM_CORE_CONN_AG_CTX_RULE5EN_MASK 0x1 /* rule5en */ +#define USTORM_CORE_CONN_AG_CTX_RULE5EN_SHIFT 4 +#define USTORM_CORE_CONN_AG_CTX_RULE6EN_MASK 0x1 /* rule6en */ +#define USTORM_CORE_CONN_AG_CTX_RULE6EN_SHIFT 5 +#define USTORM_CORE_CONN_AG_CTX_RULE7EN_MASK 0x1 /* rule7en */ +#define USTORM_CORE_CONN_AG_CTX_RULE7EN_SHIFT 6 +#define USTORM_CORE_CONN_AG_CTX_RULE8EN_MASK 0x1 /* rule8en */ +#define USTORM_CORE_CONN_AG_CTX_RULE8EN_SHIFT 7 + u8 byte2 /* byte2 */; + u8 byte3 /* byte3 */; + __le16 word0 /* conn_dpi */; + __le16 word1 /* word1 */; + __le32 rx_producers /* reg0 */; + __le32 reg1 /* reg1 */; + __le32 reg2 /* reg2 */; + __le32 reg3 /* reg3 */; + __le16 word2 /* word2 */; + __le16 word3 /* word3 */; +}; + +struct ystorm_core_conn_ag_ctx { + u8 byte0 /* cdu_validation */; + u8 byte1 /* state */; + u8 flags0; +#define YSTORM_CORE_CONN_AG_CTX_BIT0_MASK 0x1 /* exist_in_qm0 */ +#define YSTORM_CORE_CONN_AG_CTX_BIT0_SHIFT 0 +#define YSTORM_CORE_CONN_AG_CTX_BIT1_MASK 0x1 /* exist_in_qm1 */ +#define YSTORM_CORE_CONN_AG_CTX_BIT1_SHIFT 1 +#define YSTORM_CORE_CONN_AG_CTX_CF0_MASK 0x3 /* cf0 */ +#define YSTORM_CORE_CONN_AG_CTX_CF0_SHIFT 2 +#define YSTORM_CORE_CONN_AG_CTX_CF1_MASK 0x3 /* cf1 */ +#define YSTORM_CORE_CONN_AG_CTX_CF1_SHIFT 4 +#define YSTORM_CORE_CONN_AG_CTX_CF2_MASK 0x3 /* cf2 */ +#define YSTORM_CORE_CONN_AG_CTX_CF2_SHIFT 6 + u8 flags1; +#define YSTORM_CORE_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */ +#define YSTORM_CORE_CONN_AG_CTX_CF0EN_SHIFT 0 +#define YSTORM_CORE_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */ +#define YSTORM_CORE_CONN_AG_CTX_CF1EN_SHIFT 1 +#define YSTORM_CORE_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */ +#define YSTORM_CORE_CONN_AG_CTX_CF2EN_SHIFT 2 +#define YSTORM_CORE_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */ +#define YSTORM_CORE_CONN_AG_CTX_RULE0EN_SHIFT 3 +#define YSTORM_CORE_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */ +#define YSTORM_CORE_CONN_AG_CTX_RULE1EN_SHIFT 4 +#define YSTORM_CORE_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */ +#define YSTORM_CORE_CONN_AG_CTX_RULE2EN_SHIFT 5 +#define YSTORM_CORE_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */ +#define YSTORM_CORE_CONN_AG_CTX_RULE3EN_SHIFT 6 +#define YSTORM_CORE_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */ +#define YSTORM_CORE_CONN_AG_CTX_RULE4EN_SHIFT 7 + u8 byte2 /* byte2 */; + u8 byte3 /* byte3 */; + __le16 word0 /* word0 */; + __le32 reg0 /* reg0 */; + __le32 reg1 /* reg1 */; + __le16 word1 /* word1 */; + __le16 word2 /* word2 */; + __le16 word3 /* word3 */; + __le16 word4 /* word4 */; + __le32 reg2 /* reg2 */; + __le32 reg3 /* reg3 */; +}; + +/*********************************** Init ************************************/ + +/* Width of GRC address in bits (addresses are specified in dwords) */ +#define GRC_ADDR_BITS 23 +#define MAX_GRC_ADDR ((1 << GRC_ADDR_BITS) - 1) + +/* indicates an init that should be applied to any phase ID */ +#define ANY_PHASE_ID 0xffff + +/* init pattern size in bytes */ +#define INIT_PATTERN_SIZE_BITS 4 +#define MAX_INIT_PATTERN_SIZE BIT(INIT_PATTERN_SIZE_BITS) + +/* Max size in dwords of a zipped array */ +#define MAX_ZIPPED_SIZE 8192 + +/* Global PXP window */ +#define NUM_OF_PXP_WIN 19 +#define PXP_WIN_DWORD_SIZE_BITS 10 +#define PXP_WIN_DWORD_SIZE BIT(PXP_WIN_DWORD_SIZE_BITS) +#define PXP_WIN_BYTE_SIZE_BITS (PXP_WIN_DWORD_SIZE_BITS + 2) +#define PXP_WIN_BYTE_SIZE (PXP_WIN_DWORD_SIZE * 4) + +/********************************* GRC Dump **********************************/ + +/* width of GRC dump register sequence length in bits */ +#define DUMP_SEQ_LEN_BITS 8 +#define DUMP_SEQ_LEN_MAX_VAL ((1 << DUMP_SEQ_LEN_BITS) - 1) + +/* width of GRC dump memory length in bits */ +#define DUMP_MEM_LEN_BITS 18 +#define DUMP_MEM_LEN_MAX_VAL ((1 << DUMP_MEM_LEN_BITS) - 1) + +/* width of register type ID in bits */ +#define REG_TYPE_ID_BITS 6 +#define REG_TYPE_ID_MAX_VAL ((1 << REG_TYPE_ID_BITS) - 1) + +/* width of block ID in bits */ +#define BLOCK_ID_BITS 8 +#define BLOCK_ID_MAX_VAL ((1 << BLOCK_ID_BITS) - 1) + +/******************************** Idle Check *********************************/ + +/* max number of idle check predicate immediates */ +#define MAX_IDLE_CHK_PRED_IMM 3 + +/* max number of idle check argument registers */ +#define MAX_IDLE_CHK_READ_REGS 3 + +/* max number of idle check loops */ +#define MAX_IDLE_CHK_LOOPS 0x10000 + +/* max idle check address increment */ +#define MAX_IDLE_CHK_INCREMENT 0x10000 + +/* inicates an undefined idle check line index */ +#define IDLE_CHK_UNDEFINED_LINE_IDX 0xffffff + +/* max number of register values following the idle check header */ +#define IDLE_CHK_MAX_DUMP_REGS 2 + +/* arguments for IDLE_CHK_MACRO_TYPE_QM_RD_WR */ +#define IDLE_CHK_QM_RD_WR_PTR 0 +#define IDLE_CHK_QM_RD_WR_BANK 1 + +/**************************************/ +/* HSI Functions constants and macros */ +/**************************************/ + +/* Number of VLAN priorities */ +#define NUM_OF_VLAN_PRIORITIES 8 + +/* the MCP Trace meta data signautre is duplicated in the perl script that + * generats the NVRAM images. + */ +#define MCP_TRACE_META_IMAGE_SIGNATURE 0x669955aa + +/* Binary buffer header */ +struct bin_buffer_hdr { + u32 offset; + u32 length /* buffer length in bytes */; +}; + +/* binary buffer types */ +enum bin_buffer_type { + BIN_BUF_FW_VER_INFO /* fw_ver_info struct */, + BIN_BUF_INIT_CMD /* init commands */, + BIN_BUF_INIT_VAL /* init data */, + BIN_BUF_INIT_MODE_TREE /* init modes tree */, + BIN_BUF_IRO /* internal RAM offsets array */, + MAX_BIN_BUFFER_TYPE +}; + +/* Chip IDs */ +enum chip_ids { + CHIP_BB_A0 /* BB A0 chip ID */, + CHIP_BB_B0 /* BB B0 chip ID */, + CHIP_K2 /* AH chip ID */, + MAX_CHIP_IDS +}; + +enum idle_chk_severity_types { + IDLE_CHK_SEVERITY_ERROR /* idle check failure should cause an error */, + IDLE_CHK_SEVERITY_ERROR_NO_TRAFFIC, + IDLE_CHK_SEVERITY_WARNING, + MAX_IDLE_CHK_SEVERITY_TYPES +}; + +struct init_array_raw_hdr { + __le32 data; +#define INIT_ARRAY_RAW_HDR_TYPE_MASK 0xF +#define INIT_ARRAY_RAW_HDR_TYPE_SHIFT 0 +#define INIT_ARRAY_RAW_HDR_PARAMS_MASK 0xFFFFFFF /* init array params */ +#define INIT_ARRAY_RAW_HDR_PARAMS_SHIFT 4 +}; + +struct init_array_standard_hdr { + __le32 data; +#define INIT_ARRAY_STANDARD_HDR_TYPE_MASK 0xF +#define INIT_ARRAY_STANDARD_HDR_TYPE_SHIFT 0 +#define INIT_ARRAY_STANDARD_HDR_SIZE_MASK 0xFFFFFFF +#define INIT_ARRAY_STANDARD_HDR_SIZE_SHIFT 4 +}; + +struct init_array_zipped_hdr { + __le32 data; +#define INIT_ARRAY_ZIPPED_HDR_TYPE_MASK 0xF +#define INIT_ARRAY_ZIPPED_HDR_TYPE_SHIFT 0 +#define INIT_ARRAY_ZIPPED_HDR_ZIPPED_SIZE_MASK 0xFFFFFFF +#define INIT_ARRAY_ZIPPED_HDR_ZIPPED_SIZE_SHIFT 4 +}; + +struct init_array_pattern_hdr { + __le32 data; +#define INIT_ARRAY_PATTERN_HDR_TYPE_MASK 0xF +#define INIT_ARRAY_PATTERN_HDR_TYPE_SHIFT 0 +#define INIT_ARRAY_PATTERN_HDR_PATTERN_SIZE_MASK 0xF +#define INIT_ARRAY_PATTERN_HDR_PATTERN_SIZE_SHIFT 4 +#define INIT_ARRAY_PATTERN_HDR_REPETITIONS_MASK 0xFFFFFF +#define INIT_ARRAY_PATTERN_HDR_REPETITIONS_SHIFT 8 +}; + +union init_array_hdr { + struct init_array_raw_hdr raw /* raw init array header */; + struct init_array_standard_hdr standard; + struct init_array_zipped_hdr zipped /* zipped init array header */; + struct init_array_pattern_hdr pattern /* pattern init array header */; +}; + +enum init_array_types { + INIT_ARR_STANDARD /* standard init array */, + INIT_ARR_ZIPPED /* zipped init array */, + INIT_ARR_PATTERN /* a repeated pattern */, + MAX_INIT_ARRAY_TYPES +}; + +/* init operation: callback */ +struct init_callback_op { + __le32 op_data; +#define INIT_CALLBACK_OP_OP_MASK 0xF +#define INIT_CALLBACK_OP_OP_SHIFT 0 +#define INIT_CALLBACK_OP_RESERVED_MASK 0xFFFFFFF +#define INIT_CALLBACK_OP_RESERVED_SHIFT 4 + __le16 callback_id /* Callback ID */; + __le16 block_id /* Blocks ID */; +}; + +/* init comparison types */ +enum init_comparison_types { + INIT_COMPARISON_EQ /* init value is included in the init command */, + INIT_COMPARISON_OR /* init value is all zeros */, + INIT_COMPARISON_AND /* init value is an array of values */, + MAX_INIT_COMPARISON_TYPES +}; + +/* init operation: delay */ +struct init_delay_op { + __le32 op_data; +#define INIT_DELAY_OP_OP_MASK 0xF +#define INIT_DELAY_OP_OP_SHIFT 0 +#define INIT_DELAY_OP_RESERVED_MASK 0xFFFFFFF +#define INIT_DELAY_OP_RESERVED_SHIFT 4 + __le32 delay /* delay in us */; +}; + +/* init operation: if_mode */ +struct init_if_mode_op { + __le32 op_data; +#define INIT_IF_MODE_OP_OP_MASK 0xF +#define INIT_IF_MODE_OP_OP_SHIFT 0 +#define INIT_IF_MODE_OP_RESERVED1_MASK 0xFFF +#define INIT_IF_MODE_OP_RESERVED1_SHIFT 4 +#define INIT_IF_MODE_OP_CMD_OFFSET_MASK 0xFFFF +#define INIT_IF_MODE_OP_CMD_OFFSET_SHIFT 16 + __le16 reserved2; + __le16 modes_buf_offset; +}; + +/* init operation: if_phase */ +struct init_if_phase_op { + __le32 op_data; +#define INIT_IF_PHASE_OP_OP_MASK 0xF +#define INIT_IF_PHASE_OP_OP_SHIFT 0 +#define INIT_IF_PHASE_OP_DMAE_ENABLE_MASK 0x1 +#define INIT_IF_PHASE_OP_DMAE_ENABLE_SHIFT 4 +#define INIT_IF_PHASE_OP_RESERVED1_MASK 0x7FF +#define INIT_IF_PHASE_OP_RESERVED1_SHIFT 5 +#define INIT_IF_PHASE_OP_CMD_OFFSET_MASK 0xFFFF +#define INIT_IF_PHASE_OP_CMD_OFFSET_SHIFT 16 + __le32 phase_data; +#define INIT_IF_PHASE_OP_PHASE_MASK 0xFF /* Init phase */ +#define INIT_IF_PHASE_OP_PHASE_SHIFT 0 +#define INIT_IF_PHASE_OP_RESERVED2_MASK 0xFF +#define INIT_IF_PHASE_OP_RESERVED2_SHIFT 8 +#define INIT_IF_PHASE_OP_PHASE_ID_MASK 0xFFFF /* Init phase ID */ +#define INIT_IF_PHASE_OP_PHASE_ID_SHIFT 16 +}; + +/* init mode operators */ +enum init_mode_ops { + INIT_MODE_OP_NOT /* init mode not operator */, + INIT_MODE_OP_OR /* init mode or operator */, + INIT_MODE_OP_AND /* init mode and operator */, + MAX_INIT_MODE_OPS +}; + +/* init operation: raw */ +struct init_raw_op { + __le32 op_data; +#define INIT_RAW_OP_OP_MASK 0xF +#define INIT_RAW_OP_OP_SHIFT 0 +#define INIT_RAW_OP_PARAM1_MASK 0xFFFFFFF /* init param 1 */ +#define INIT_RAW_OP_PARAM1_SHIFT 4 + __le32 param2 /* Init param 2 */; +}; + +/* init array params */ +struct init_op_array_params { + __le16 size /* array size in dwords */; + __le16 offset /* array start offset in dwords */; +}; + +/* Write init operation arguments */ +union init_write_args { + __le32 inline_val; + __le32 zeros_count; + __le32 array_offset; + struct init_op_array_params runtime; +}; + +/* init operation: write */ +struct init_write_op { + __le32 data; +#define INIT_WRITE_OP_OP_MASK 0xF +#define INIT_WRITE_OP_OP_SHIFT 0 +#define INIT_WRITE_OP_SOURCE_MASK 0x7 +#define INIT_WRITE_OP_SOURCE_SHIFT 4 +#define INIT_WRITE_OP_RESERVED_MASK 0x1 +#define INIT_WRITE_OP_RESERVED_SHIFT 7 +#define INIT_WRITE_OP_WIDE_BUS_MASK 0x1 +#define INIT_WRITE_OP_WIDE_BUS_SHIFT 8 +#define INIT_WRITE_OP_ADDRESS_MASK 0x7FFFFF +#define INIT_WRITE_OP_ADDRESS_SHIFT 9 + union init_write_args args /* Write init operation arguments */; +}; + +/* init operation: read */ +struct init_read_op { + __le32 op_data; +#define INIT_READ_OP_OP_MASK 0xF +#define INIT_READ_OP_OP_SHIFT 0 +#define INIT_READ_OP_POLL_COMP_MASK 0x7 +#define INIT_READ_OP_POLL_COMP_SHIFT 4 +#define INIT_READ_OP_RESERVED_MASK 0x1 +#define INIT_READ_OP_RESERVED_SHIFT 7 +#define INIT_READ_OP_POLL_MASK 0x1 +#define INIT_READ_OP_POLL_SHIFT 8 +#define INIT_READ_OP_ADDRESS_MASK 0x7FFFFF +#define INIT_READ_OP_ADDRESS_SHIFT 9 + __le32 expected_val; +}; + +/* Init operations union */ +union init_op { + struct init_raw_op raw /* raw init operation */; + struct init_write_op write /* write init operation */; + struct init_read_op read /* read init operation */; + struct init_if_mode_op if_mode /* if_mode init operation */; + struct init_if_phase_op if_phase /* if_phase init operation */; + struct init_callback_op callback /* callback init operation */; + struct init_delay_op delay /* delay init operation */; +}; + +/* Init command operation types */ +enum init_op_types { + INIT_OP_READ /* GRC read init command */, + INIT_OP_WRITE /* GRC write init command */, + INIT_OP_IF_MODE, + INIT_OP_IF_PHASE, + INIT_OP_DELAY /* delay init command */, + INIT_OP_CALLBACK /* callback init command */, + MAX_INIT_OP_TYPES +}; + +/* init source types */ +enum init_source_types { + INIT_SRC_INLINE /* init value is included in the init command */, + INIT_SRC_ZEROS /* init value is all zeros */, + INIT_SRC_ARRAY /* init value is an array of values */, + INIT_SRC_RUNTIME /* init value is provided during runtime */, + MAX_INIT_SOURCE_TYPES +}; + +/* Internal RAM Offsets macro data */ +struct iro { + u32 base /* RAM field offset */; + u16 m1 /* multiplier 1 */; + u16 m2 /* multiplier 2 */; + u16 m3 /* multiplier 3 */; + u16 size /* RAM field size */; +}; + +/* QM per-port init parameters */ +struct init_qm_port_params { + u8 active /* Indicates if this port is active */; + u8 num_active_phys_tcs; + u16 num_pbf_cmd_lines; + u16 num_btb_blocks; + __le16 reserved; +}; + +/* QM per-PQ init parameters */ +struct init_qm_pq_params { + u8 vport_id /* VPORT ID */; + u8 tc_id /* TC ID */; + u8 wrr_group /* WRR group */; + u8 reserved; +}; + +/* QM per-vport init parameters */ +struct init_qm_vport_params { + u32 vport_rl; + u16 vport_wfq; + u16 first_tx_pq_id[NUM_OF_TCS]; +}; + +/* Win 2 */ +#define GTT_BAR0_MAP_REG_IGU_CMD \ + 0x00f000UL +/* Win 3 */ +#define GTT_BAR0_MAP_REG_TSDM_RAM \ + 0x010000UL +/* Win 4 */ +#define GTT_BAR0_MAP_REG_MSDM_RAM \ + 0x011000UL +/* Win 5 */ +#define GTT_BAR0_MAP_REG_MSDM_RAM_1024 \ + 0x012000UL +/* Win 6 */ +#define GTT_BAR0_MAP_REG_USDM_RAM \ + 0x013000UL +/* Win 7 */ +#define GTT_BAR0_MAP_REG_USDM_RAM_1024 \ + 0x014000UL +/* Win 8 */ +#define GTT_BAR0_MAP_REG_USDM_RAM_2048 \ + 0x015000UL +/* Win 9 */ +#define GTT_BAR0_MAP_REG_XSDM_RAM \ + 0x016000UL +/* Win 10 */ +#define GTT_BAR0_MAP_REG_YSDM_RAM \ + 0x017000UL +/* Win 11 */ +#define GTT_BAR0_MAP_REG_PSDM_RAM \ + 0x018000UL + +/** + * @brief qed_qm_pf_mem_size - prepare QM ILT sizes + * + * Returns the required host memory size in 4KB units. + * Must be called before all QM init HSI functions. + * + * @param pf_id - physical function ID + * @param num_pf_cids - number of connections used by this PF + * @param num_vf_cids - number of connections used by VFs of this PF + * @param num_tids - number of tasks used by this PF + * @param num_pf_pqs - number of PQs used by this PF + * @param num_vf_pqs - number of PQs used by VFs of this PF + * + * @return The required host memory size in 4KB units. + */ +u32 qed_qm_pf_mem_size(u8 pf_id, + u32 num_pf_cids, + u32 num_vf_cids, + u32 num_tids, + u16 num_pf_pqs, + u16 num_vf_pqs); + +struct qed_qm_common_rt_init_params { + u8 max_ports_per_engine; + u8 max_phys_tcs_per_port; + bool pf_rl_en; + bool pf_wfq_en; + bool vport_rl_en; + bool vport_wfq_en; + struct init_qm_port_params *port_params; +}; + +/** + * @brief qed_qm_common_rt_init - Prepare QM runtime init values for the + * engine phase. + * + * @param p_hwfn + * @param max_ports_per_engine - max number of ports per engine in HW + * @param max_phys_tcs_per_port - max number of physical TCs per port in HW + * @param pf_rl_en - enable per-PF rate limiters + * @param pf_wfq_en - enable per-PF WFQ + * @param vport_rl_en - enable per-VPORT rate limiters + * @param vport_wfq_en - enable per-VPORT WFQ + * @param port_params - array of size MAX_NUM_PORTS with + * arameters for each port + * + * @return 0 on success, -1 on error. + */ +int qed_qm_common_rt_init( + struct qed_hwfn *p_hwfn, + struct qed_qm_common_rt_init_params *p_params); + +struct qed_qm_pf_rt_init_params { + u8 port_id; + u8 pf_id; + u8 max_phys_tcs_per_port; + bool is_first_pf; + u32 num_pf_cids; + u32 num_vf_cids; + u32 num_tids; + u16 start_pq; + u16 num_pf_pqs; + u16 num_vf_pqs; + u8 start_vport; + u8 num_vports; + u8 pf_wfq; + u32 pf_rl; + struct init_qm_pq_params *pq_params; + struct init_qm_vport_params *vport_params; +}; + +int qed_qm_pf_rt_init(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_qm_pf_rt_init_params *p_params); + +/** + * @brief qed_init_pf_rl Initializes the rate limit of the specified PF + * + * @param p_hwfn + * @param p_ptt - ptt window used for writing the registers + * @param pf_id - PF ID + * @param pf_rl - rate limit in Mb/sec units + * + * @return 0 on success, -1 on error. + */ +int qed_init_pf_rl(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u8 pf_id, + u32 pf_rl); + +/** + * @brief qed_init_vport_rl Initializes the rate limit of the specified VPORT + * + * @param p_hwfn + * @param p_ptt - ptt window used for writing the registers + * @param vport_id - VPORT ID + * @param vport_rl - rate limit in Mb/sec units + * + * @return 0 on success, -1 on error. + */ + +int qed_init_vport_rl(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u8 vport_id, + u32 vport_rl); +/** + * @brief qed_send_qm_stop_cmd Sends a stop command to the QM + * + * @param p_hwfn + * @param p_ptt - ptt window used for writing the registers + * @param is_release_cmd - true for release, false for stop. + * @param is_tx_pq - true for Tx PQs, false for Other PQs. + * @param start_pq - first PQ ID to stop + * @param num_pqs - Number of PQs to stop, starting from start_pq. + * + * @return bool, true if successful, false if timeout occurred while waiting + * for QM command done. + */ + +bool qed_send_qm_stop_cmd(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + bool is_release_cmd, + bool is_tx_pq, + u16 start_pq, + u16 num_pqs); + +/* Ystorm flow control mode. Use enum fw_flow_ctrl_mode */ +#define YSTORM_FLOW_CONTROL_MODE_OFFSET (IRO[0].base) +#define YSTORM_FLOW_CONTROL_MODE_SIZE (IRO[0].size) +/* Tstorm port statistics */ +#define TSTORM_PORT_STAT_OFFSET(port_id) (IRO[1].base + \ + ((port_id) * \ + IRO[1].m1)) +#define TSTORM_PORT_STAT_SIZE (IRO[1].size) +/* Ustorm VF-PF Channel ready flag */ +#define USTORM_VF_PF_CHANNEL_READY_OFFSET(vf_id) (IRO[2].base + \ + ((vf_id) * \ + IRO[2].m1)) +#define USTORM_VF_PF_CHANNEL_READY_SIZE (IRO[2].size) +/* Ustorm Final flr cleanup ack */ +#define USTORM_FLR_FINAL_ACK_OFFSET (IRO[3].base) +#define USTORM_FLR_FINAL_ACK_SIZE (IRO[3].size) +/* Ustorm Event ring consumer */ +#define USTORM_EQE_CONS_OFFSET(pf_id) (IRO[4].base + \ + ((pf_id) * \ + IRO[4].m1)) +#define USTORM_EQE_CONS_SIZE (IRO[4].size) +/* Ustorm Completion ring consumer */ +#define USTORM_CQ_CONS_OFFSET(global_queue_id) (IRO[5].base + \ + ((global_queue_id) * \ + IRO[5].m1)) +#define USTORM_CQ_CONS_SIZE (IRO[5].size) +/* Xstorm Integration Test Data */ +#define XSTORM_INTEG_TEST_DATA_OFFSET (IRO[6].base) +#define XSTORM_INTEG_TEST_DATA_SIZE (IRO[6].size) +/* Ystorm Integration Test Data */ +#define YSTORM_INTEG_TEST_DATA_OFFSET (IRO[7].base) +#define YSTORM_INTEG_TEST_DATA_SIZE (IRO[7].size) +/* Pstorm Integration Test Data */ +#define PSTORM_INTEG_TEST_DATA_OFFSET (IRO[8].base) +#define PSTORM_INTEG_TEST_DATA_SIZE (IRO[8].size) +/* Tstorm Integration Test Data */ +#define TSTORM_INTEG_TEST_DATA_OFFSET (IRO[9].base) +#define TSTORM_INTEG_TEST_DATA_SIZE (IRO[9].size) +/* Mstorm Integration Test Data */ +#define MSTORM_INTEG_TEST_DATA_OFFSET (IRO[10].base) +#define MSTORM_INTEG_TEST_DATA_SIZE (IRO[10].size) +/* Ustorm Integration Test Data */ +#define USTORM_INTEG_TEST_DATA_OFFSET (IRO[11].base) +#define USTORM_INTEG_TEST_DATA_SIZE (IRO[11].size) +/* Tstorm producers */ +#define TSTORM_LL2_RX_PRODS_OFFSET(core_rx_queue_id) (IRO[12].base + \ + ((core_rx_queue_id) * \ + IRO[12].m1)) +#define TSTORM_LL2_RX_PRODS_SIZE (IRO[12].size) +/* Tstorm LiteL2 queue statistics */ +#define CORE_LL2_TSTORM_PER_QUEUE_STAT_OFFSET(core_rx_q_id) (IRO[13].base + \ + ((core_rx_q_id) * \ + IRO[13].m1)) +#define CORE_LL2_TSTORM_PER_QUEUE_STAT_SIZE (IRO[13].size) +/* Ustorm LiteL2 queue statistics */ +#define CORE_LL2_USTORM_PER_QUEUE_STAT_OFFSET(core_rx_q_id) (IRO[14].base + \ + ((core_rx_q_id) * \ + IRO[14].m1)) +#define CORE_LL2_USTORM_PER_QUEUE_STAT_SIZE (IRO[14].size) +/* Pstorm LiteL2 queue statistics */ +#define CORE_LL2_PSTORM_PER_QUEUE_STAT_OFFSET(core_txst_id) (IRO[15].base + \ + ((core_txst_id) * \ + IRO[15].m1)) +#define CORE_LL2_PSTORM_PER_QUEUE_STAT_SIZE (IRO[15].size) +/* Mstorm queue statistics */ +#define MSTORM_QUEUE_STAT_OFFSET(stat_counter_id) (IRO[16].base + \ + ((stat_counter_id) * \ + IRO[16].m1)) +#define MSTORM_QUEUE_STAT_SIZE (IRO[16].size) +/* Mstorm producers */ +#define MSTORM_PRODS_OFFSET(queue_id) (IRO[17].base + \ + ((queue_id) * \ + IRO[17].m1)) +#define MSTORM_PRODS_SIZE (IRO[17].size) +/* TPA agregation timeout in us resolution (on ASIC) */ +#define MSTORM_TPA_TIMEOUT_US_OFFSET (IRO[18].base) +#define MSTORM_TPA_TIMEOUT_US_SIZE (IRO[18].size) +/* Ustorm queue statistics */ +#define USTORM_QUEUE_STAT_OFFSET(stat_counter_id) (IRO[19].base + \ + ((stat_counter_id) * \ + IRO[19].m1)) +#define USTORM_QUEUE_STAT_SIZE (IRO[19].size) +/* Ustorm queue zone */ +#define USTORM_ETH_QUEUE_ZONE_OFFSET(queue_id) (IRO[20].base + \ + ((queue_id) * \ + IRO[20].m1)) +#define USTORM_ETH_QUEUE_ZONE_SIZE (IRO[20].size) +/* Pstorm queue statistics */ +#define PSTORM_QUEUE_STAT_OFFSET(stat_counter_id) (IRO[21].base + \ + ((stat_counter_id) * \ + IRO[21].m1)) +#define PSTORM_QUEUE_STAT_SIZE (IRO[21].size) +/* Tstorm last parser message */ +#define TSTORM_ETH_PRS_INPUT_OFFSET(pf_id) (IRO[22].base + \ + ((pf_id) * \ + IRO[22].m1)) +#define TSTORM_ETH_PRS_INPUT_SIZE (IRO[22].size) +/* Ystorm queue zone */ +#define YSTORM_ETH_QUEUE_ZONE_OFFSET(queue_id) (IRO[23].base + \ + ((queue_id) * \ + IRO[23].m1)) +#define YSTORM_ETH_QUEUE_ZONE_SIZE (IRO[23].size) +/* Ystorm cqe producer */ +#define YSTORM_TOE_CQ_PROD_OFFSET(rss_id) (IRO[24].base + \ + ((rss_id) * \ + IRO[24].m1)) +#define YSTORM_TOE_CQ_PROD_SIZE (IRO[24].size) +/* Ustorm cqe producer */ +#define USTORM_TOE_CQ_PROD_OFFSET(rss_id) (IRO[25].base + \ + ((rss_id) * \ + IRO[25].m1)) +#define USTORM_TOE_CQ_PROD_SIZE (IRO[25].size) +/* Ustorm grq producer */ +#define USTORM_TOE_GRQ_PROD_OFFSET(pf_id) (IRO[26].base + \ + ((pf_id) * \ + IRO[26].m1)) +#define USTORM_TOE_GRQ_PROD_SIZE (IRO[26].size) +/* Tstorm cmdq-cons of given command queue-id */ +#define TSTORM_SCSI_CMDQ_CONS_OFFSET(cmdq_queue_id) (IRO[27].base + \ + ((cmdq_queue_id) * \ + IRO[27].m1)) +#define TSTORM_SCSI_CMDQ_CONS_SIZE (IRO[27].size) +/* Mstorm rq-cons of given queue-id */ +#define MSTORM_SCSI_RQ_CONS_OFFSET(rq_queue_id) (IRO[28].base + \ + ((rq_queue_id) * \ + IRO[28].m1)) +#define MSTORM_SCSI_RQ_CONS_SIZE (IRO[28].size) +/* Pstorm RoCE statistics */ +#define PSTORM_ROCE_STAT_OFFSET(stat_counter_id) (IRO[29].base + \ + ((stat_counter_id) * \ + IRO[29].m1)) +#define PSTORM_ROCE_STAT_SIZE (IRO[29].size) +/* Tstorm RoCE statistics */ +#define TSTORM_ROCE_STAT_OFFSET(stat_counter_id) (IRO[30].base + \ + ((stat_counter_id) * \ + IRO[30].m1)) +#define TSTORM_ROCE_STAT_SIZE (IRO[30].size) + +static const struct iro iro_arr[31] = { + { 0x10, 0x0, 0x0, 0x0, 0x8 }, + { 0x4448, 0x60, 0x0, 0x0, 0x60 }, + { 0x498, 0x8, 0x0, 0x0, 0x4 }, + { 0x494, 0x0, 0x0, 0x0, 0x4 }, + { 0x10, 0x8, 0x0, 0x0, 0x2 }, + { 0x90, 0x8, 0x0, 0x0, 0x2 }, + { 0x4540, 0x0, 0x0, 0x0, 0xf8 }, + { 0x39e0, 0x0, 0x0, 0x0, 0xf8 }, + { 0x2598, 0x0, 0x0, 0x0, 0xf8 }, + { 0x4350, 0x0, 0x0, 0x0, 0xf8 }, + { 0x52d0, 0x0, 0x0, 0x0, 0xf8 }, + { 0x7a48, 0x0, 0x0, 0x0, 0xf8 }, + { 0x100, 0x8, 0x0, 0x0, 0x8 }, + { 0x5808, 0x10, 0x0, 0x0, 0x10 }, + { 0xb100, 0x30, 0x0, 0x0, 0x30 }, + { 0x95c0, 0x30, 0x0, 0x0, 0x30 }, + { 0x54f8, 0x40, 0x0, 0x0, 0x40 }, + { 0x200, 0x10, 0x0, 0x0, 0x8 }, + { 0x9e70, 0x0, 0x0, 0x0, 0x4 }, + { 0x7ca0, 0x40, 0x0, 0x0, 0x30 }, + { 0xd00, 0x8, 0x0, 0x0, 0x8 }, + { 0x2790, 0x80, 0x0, 0x0, 0x38 }, + { 0xa520, 0xf0, 0x0, 0x0, 0xf0 }, + { 0x80, 0x8, 0x0, 0x0, 0x8 }, + { 0xac0, 0x8, 0x0, 0x0, 0x8 }, + { 0x2580, 0x8, 0x0, 0x0, 0x8 }, + { 0x2500, 0x8, 0x0, 0x0, 0x8 }, + { 0x440, 0x8, 0x0, 0x0, 0x2 }, + { 0x1800, 0x8, 0x0, 0x0, 0x2 }, + { 0x27c8, 0x80, 0x0, 0x0, 0x10 }, + { 0x4710, 0x10, 0x0, 0x0, 0x10 }, +}; + +/* Runtime array offsets */ +#define DORQ_REG_PF_MAX_ICID_0_RT_OFFSET 0 +#define DORQ_REG_PF_MAX_ICID_1_RT_OFFSET 1 +#define DORQ_REG_PF_MAX_ICID_2_RT_OFFSET 2 +#define DORQ_REG_PF_MAX_ICID_3_RT_OFFSET 3 +#define DORQ_REG_PF_MAX_ICID_4_RT_OFFSET 4 +#define DORQ_REG_PF_MAX_ICID_5_RT_OFFSET 5 +#define DORQ_REG_PF_MAX_ICID_6_RT_OFFSET 6 +#define DORQ_REG_PF_MAX_ICID_7_RT_OFFSET 7 +#define DORQ_REG_VF_MAX_ICID_0_RT_OFFSET 8 +#define DORQ_REG_VF_MAX_ICID_1_RT_OFFSET 9 +#define DORQ_REG_VF_MAX_ICID_2_RT_OFFSET 10 +#define DORQ_REG_VF_MAX_ICID_3_RT_OFFSET 11 +#define DORQ_REG_VF_MAX_ICID_4_RT_OFFSET 12 +#define DORQ_REG_VF_MAX_ICID_5_RT_OFFSET 13 +#define DORQ_REG_VF_MAX_ICID_6_RT_OFFSET 14 +#define DORQ_REG_VF_MAX_ICID_7_RT_OFFSET 15 +#define DORQ_REG_PF_WAKE_ALL_RT_OFFSET 16 +#define IGU_REG_PF_CONFIGURATION_RT_OFFSET 17 +#define IGU_REG_VF_CONFIGURATION_RT_OFFSET 18 +#define IGU_REG_ATTN_MSG_ADDR_L_RT_OFFSET 19 +#define IGU_REG_ATTN_MSG_ADDR_H_RT_OFFSET 20 +#define IGU_REG_LEADING_EDGE_LATCH_RT_OFFSET 21 +#define IGU_REG_TRAILING_EDGE_LATCH_RT_OFFSET 22 +#define CAU_REG_CQE_AGG_UNIT_SIZE_RT_OFFSET 23 +#define CAU_REG_SB_VAR_MEMORY_RT_OFFSET 760 +#define CAU_REG_SB_VAR_MEMORY_RT_SIZE 736 +#define CAU_REG_SB_VAR_MEMORY_RT_OFFSET 760 +#define CAU_REG_SB_VAR_MEMORY_RT_SIZE 736 +#define CAU_REG_SB_ADDR_MEMORY_RT_OFFSET 1496 +#define CAU_REG_SB_ADDR_MEMORY_RT_SIZE 736 +#define CAU_REG_PI_MEMORY_RT_OFFSET 2232 +#define CAU_REG_PI_MEMORY_RT_SIZE 4416 +#define PRS_REG_SEARCH_RESP_INITIATOR_TYPE_RT_OFFSET 6648 +#define PRS_REG_TASK_ID_MAX_INITIATOR_PF_RT_OFFSET 6649 +#define PRS_REG_TASK_ID_MAX_INITIATOR_VF_RT_OFFSET 6650 +#define PRS_REG_TASK_ID_MAX_TARGET_PF_RT_OFFSET 6651 +#define PRS_REG_TASK_ID_MAX_TARGET_VF_RT_OFFSET 6652 +#define PRS_REG_SEARCH_TCP_RT_OFFSET 6653 +#define PRS_REG_SEARCH_FCOE_RT_OFFSET 6654 +#define PRS_REG_SEARCH_ROCE_RT_OFFSET 6655 +#define PRS_REG_ROCE_DEST_QP_MAX_VF_RT_OFFSET 6656 +#define PRS_REG_ROCE_DEST_QP_MAX_PF_RT_OFFSET 6657 +#define PRS_REG_SEARCH_OPENFLOW_RT_OFFSET 6658 +#define PRS_REG_SEARCH_NON_IP_AS_OPENFLOW_RT_OFFSET 6659 +#define PRS_REG_OPENFLOW_SUPPORT_ONLY_KNOWN_OVER_IP_RT_OFFSET 6660 +#define PRS_REG_OPENFLOW_SEARCH_KEY_MASK_RT_OFFSET 6661 +#define PRS_REG_LIGHT_L2_ETHERTYPE_EN_RT_OFFSET 6662 +#define SRC_REG_FIRSTFREE_RT_OFFSET 6663 +#define SRC_REG_FIRSTFREE_RT_SIZE 2 +#define SRC_REG_LASTFREE_RT_OFFSET 6665 +#define SRC_REG_LASTFREE_RT_SIZE 2 +#define SRC_REG_COUNTFREE_RT_OFFSET 6667 +#define SRC_REG_NUMBER_HASH_BITS_RT_OFFSET 6668 +#define PSWRQ2_REG_CDUT_P_SIZE_RT_OFFSET 6669 +#define PSWRQ2_REG_CDUC_P_SIZE_RT_OFFSET 6670 +#define PSWRQ2_REG_TM_P_SIZE_RT_OFFSET 6671 +#define PSWRQ2_REG_QM_P_SIZE_RT_OFFSET 6672 +#define PSWRQ2_REG_SRC_P_SIZE_RT_OFFSET 6673 +#define PSWRQ2_REG_TM_FIRST_ILT_RT_OFFSET 6674 +#define PSWRQ2_REG_TM_LAST_ILT_RT_OFFSET 6675 +#define PSWRQ2_REG_QM_FIRST_ILT_RT_OFFSET 6676 +#define PSWRQ2_REG_QM_LAST_ILT_RT_OFFSET 6677 +#define PSWRQ2_REG_SRC_FIRST_ILT_RT_OFFSET 6678 +#define PSWRQ2_REG_SRC_LAST_ILT_RT_OFFSET 6679 +#define PSWRQ2_REG_CDUC_FIRST_ILT_RT_OFFSET 6680 +#define PSWRQ2_REG_CDUC_LAST_ILT_RT_OFFSET 6681 +#define PSWRQ2_REG_CDUT_FIRST_ILT_RT_OFFSET 6682 +#define PSWRQ2_REG_CDUT_LAST_ILT_RT_OFFSET 6683 +#define PSWRQ2_REG_TSDM_FIRST_ILT_RT_OFFSET 6684 +#define PSWRQ2_REG_TSDM_LAST_ILT_RT_OFFSET 6685 +#define PSWRQ2_REG_TM_NUMBER_OF_PF_BLOCKS_RT_OFFSET 6686 +#define PSWRQ2_REG_CDUT_NUMBER_OF_PF_BLOCKS_RT_OFFSET 6687 +#define PSWRQ2_REG_CDUC_NUMBER_OF_PF_BLOCKS_RT_OFFSET 6688 +#define PSWRQ2_REG_TM_VF_BLOCKS_RT_OFFSET 6689 +#define PSWRQ2_REG_CDUT_VF_BLOCKS_RT_OFFSET 6690 +#define PSWRQ2_REG_CDUC_VF_BLOCKS_RT_OFFSET 6691 +#define PSWRQ2_REG_TM_BLOCKS_FACTOR_RT_OFFSET 6692 +#define PSWRQ2_REG_CDUT_BLOCKS_FACTOR_RT_OFFSET 6693 +#define PSWRQ2_REG_CDUC_BLOCKS_FACTOR_RT_OFFSET 6694 +#define PSWRQ2_REG_VF_BASE_RT_OFFSET 6695 +#define PSWRQ2_REG_VF_LAST_ILT_RT_OFFSET 6696 +#define PSWRQ2_REG_WR_MBS0_RT_OFFSET 6697 +#define PSWRQ2_REG_RD_MBS0_RT_OFFSET 6698 +#define PSWRQ2_REG_DRAM_ALIGN_WR_RT_OFFSET 6699 +#define PSWRQ2_REG_DRAM_ALIGN_RD_RT_OFFSET 6700 +#define PSWRQ2_REG_ILT_MEMORY_RT_OFFSET 6701 +#define PSWRQ2_REG_ILT_MEMORY_RT_SIZE 22000 +#define PGLUE_REG_B_VF_BASE_RT_OFFSET 28701 +#define PGLUE_REG_B_CACHE_LINE_SIZE_RT_OFFSET 28702 +#define PGLUE_REG_B_PF_BAR0_SIZE_RT_OFFSET 28703 +#define PGLUE_REG_B_PF_BAR1_SIZE_RT_OFFSET 28704 +#define PGLUE_REG_B_VF_BAR1_SIZE_RT_OFFSET 28705 +#define TM_REG_VF_ENABLE_CONN_RT_OFFSET 28706 +#define TM_REG_PF_ENABLE_CONN_RT_OFFSET 28707 +#define TM_REG_PF_ENABLE_TASK_RT_OFFSET 28708 +#define TM_REG_GROUP_SIZE_RESOLUTION_CONN_RT_OFFSET 28709 +#define TM_REG_GROUP_SIZE_RESOLUTION_TASK_RT_OFFSET 28710 +#define TM_REG_CONFIG_CONN_MEM_RT_OFFSET 28711 +#define TM_REG_CONFIG_CONN_MEM_RT_SIZE 416 +#define TM_REG_CONFIG_TASK_MEM_RT_OFFSET 29127 +#define TM_REG_CONFIG_TASK_MEM_RT_SIZE 512 +#define QM_REG_MAXPQSIZE_0_RT_OFFSET 29639 +#define QM_REG_MAXPQSIZE_1_RT_OFFSET 29640 +#define QM_REG_MAXPQSIZE_2_RT_OFFSET 29641 +#define QM_REG_MAXPQSIZETXSEL_0_RT_OFFSET 29642 +#define QM_REG_MAXPQSIZETXSEL_1_RT_OFFSET 29643 +#define QM_REG_MAXPQSIZETXSEL_2_RT_OFFSET 29644 +#define QM_REG_MAXPQSIZETXSEL_3_RT_OFFSET 29645 +#define QM_REG_MAXPQSIZETXSEL_4_RT_OFFSET 29646 +#define QM_REG_MAXPQSIZETXSEL_5_RT_OFFSET 29647 +#define QM_REG_MAXPQSIZETXSEL_6_RT_OFFSET 29648 +#define QM_REG_MAXPQSIZETXSEL_7_RT_OFFSET 29649 +#define QM_REG_MAXPQSIZETXSEL_8_RT_OFFSET 29650 +#define QM_REG_MAXPQSIZETXSEL_9_RT_OFFSET 29651 +#define QM_REG_MAXPQSIZETXSEL_10_RT_OFFSET 29652 +#define QM_REG_MAXPQSIZETXSEL_11_RT_OFFSET 29653 +#define QM_REG_MAXPQSIZETXSEL_12_RT_OFFSET 29654 +#define QM_REG_MAXPQSIZETXSEL_13_RT_OFFSET 29655 +#define QM_REG_MAXPQSIZETXSEL_14_RT_OFFSET 29656 +#define QM_REG_MAXPQSIZETXSEL_15_RT_OFFSET 29657 +#define QM_REG_MAXPQSIZETXSEL_16_RT_OFFSET 29658 +#define QM_REG_MAXPQSIZETXSEL_17_RT_OFFSET 29659 +#define QM_REG_MAXPQSIZETXSEL_18_RT_OFFSET 29660 +#define QM_REG_MAXPQSIZETXSEL_19_RT_OFFSET 29661 +#define QM_REG_MAXPQSIZETXSEL_20_RT_OFFSET 29662 +#define QM_REG_MAXPQSIZETXSEL_21_RT_OFFSET 29663 +#define QM_REG_MAXPQSIZETXSEL_22_RT_OFFSET 29664 +#define QM_REG_MAXPQSIZETXSEL_23_RT_OFFSET 29665 +#define QM_REG_MAXPQSIZETXSEL_24_RT_OFFSET 29666 +#define QM_REG_MAXPQSIZETXSEL_25_RT_OFFSET 29667 +#define QM_REG_MAXPQSIZETXSEL_26_RT_OFFSET 29668 +#define QM_REG_MAXPQSIZETXSEL_27_RT_OFFSET 29669 +#define QM_REG_MAXPQSIZETXSEL_28_RT_OFFSET 29670 +#define QM_REG_MAXPQSIZETXSEL_29_RT_OFFSET 29671 +#define QM_REG_MAXPQSIZETXSEL_30_RT_OFFSET 29672 +#define QM_REG_MAXPQSIZETXSEL_31_RT_OFFSET 29673 +#define QM_REG_MAXPQSIZETXSEL_32_RT_OFFSET 29674 +#define QM_REG_MAXPQSIZETXSEL_33_RT_OFFSET 29675 +#define QM_REG_MAXPQSIZETXSEL_34_RT_OFFSET 29676 +#define QM_REG_MAXPQSIZETXSEL_35_RT_OFFSET 29677 +#define QM_REG_MAXPQSIZETXSEL_36_RT_OFFSET 29678 +#define QM_REG_MAXPQSIZETXSEL_37_RT_OFFSET 29679 +#define QM_REG_MAXPQSIZETXSEL_38_RT_OFFSET 29680 +#define QM_REG_MAXPQSIZETXSEL_39_RT_OFFSET 29681 +#define QM_REG_MAXPQSIZETXSEL_40_RT_OFFSET 29682 +#define QM_REG_MAXPQSIZETXSEL_41_RT_OFFSET 29683 +#define QM_REG_MAXPQSIZETXSEL_42_RT_OFFSET 29684 +#define QM_REG_MAXPQSIZETXSEL_43_RT_OFFSET 29685 +#define QM_REG_MAXPQSIZETXSEL_44_RT_OFFSET 29686 +#define QM_REG_MAXPQSIZETXSEL_45_RT_OFFSET 29687 +#define QM_REG_MAXPQSIZETXSEL_46_RT_OFFSET 29688 +#define QM_REG_MAXPQSIZETXSEL_47_RT_OFFSET 29689 +#define QM_REG_MAXPQSIZETXSEL_48_RT_OFFSET 29690 +#define QM_REG_MAXPQSIZETXSEL_49_RT_OFFSET 29691 +#define QM_REG_MAXPQSIZETXSEL_50_RT_OFFSET 29692 +#define QM_REG_MAXPQSIZETXSEL_51_RT_OFFSET 29693 +#define QM_REG_MAXPQSIZETXSEL_52_RT_OFFSET 29694 +#define QM_REG_MAXPQSIZETXSEL_53_RT_OFFSET 29695 +#define QM_REG_MAXPQSIZETXSEL_54_RT_OFFSET 29696 +#define QM_REG_MAXPQSIZETXSEL_55_RT_OFFSET 29697 +#define QM_REG_MAXPQSIZETXSEL_56_RT_OFFSET 29698 +#define QM_REG_MAXPQSIZETXSEL_57_RT_OFFSET 29699 +#define QM_REG_MAXPQSIZETXSEL_58_RT_OFFSET 29700 +#define QM_REG_MAXPQSIZETXSEL_59_RT_OFFSET 29701 +#define QM_REG_MAXPQSIZETXSEL_60_RT_OFFSET 29702 +#define QM_REG_MAXPQSIZETXSEL_61_RT_OFFSET 29703 +#define QM_REG_MAXPQSIZETXSEL_62_RT_OFFSET 29704 +#define QM_REG_MAXPQSIZETXSEL_63_RT_OFFSET 29705 +#define QM_REG_BASEADDROTHERPQ_RT_OFFSET 29706 +#define QM_REG_BASEADDROTHERPQ_RT_SIZE 128 +#define QM_REG_VOQCRDLINE_RT_OFFSET 29834 +#define QM_REG_VOQCRDLINE_RT_SIZE 20 +#define QM_REG_VOQINITCRDLINE_RT_OFFSET 29854 +#define QM_REG_VOQINITCRDLINE_RT_SIZE 20 +#define QM_REG_AFULLQMBYPTHRPFWFQ_RT_OFFSET 29874 +#define QM_REG_AFULLQMBYPTHRVPWFQ_RT_OFFSET 29875 +#define QM_REG_AFULLQMBYPTHRPFRL_RT_OFFSET 29876 +#define QM_REG_AFULLQMBYPTHRGLBLRL_RT_OFFSET 29877 +#define QM_REG_AFULLOPRTNSTCCRDMASK_RT_OFFSET 29878 +#define QM_REG_WRROTHERPQGRP_0_RT_OFFSET 29879 +#define QM_REG_WRROTHERPQGRP_1_RT_OFFSET 29880 +#define QM_REG_WRROTHERPQGRP_2_RT_OFFSET 29881 +#define QM_REG_WRROTHERPQGRP_3_RT_OFFSET 29882 +#define QM_REG_WRROTHERPQGRP_4_RT_OFFSET 29883 +#define QM_REG_WRROTHERPQGRP_5_RT_OFFSET 29884 +#define QM_REG_WRROTHERPQGRP_6_RT_OFFSET 29885 +#define QM_REG_WRROTHERPQGRP_7_RT_OFFSET 29886 +#define QM_REG_WRROTHERPQGRP_8_RT_OFFSET 29887 +#define QM_REG_WRROTHERPQGRP_9_RT_OFFSET 29888 +#define QM_REG_WRROTHERPQGRP_10_RT_OFFSET 29889 +#define QM_REG_WRROTHERPQGRP_11_RT_OFFSET 29890 +#define QM_REG_WRROTHERPQGRP_12_RT_OFFSET 29891 +#define QM_REG_WRROTHERPQGRP_13_RT_OFFSET 29892 +#define QM_REG_WRROTHERPQGRP_14_RT_OFFSET 29893 +#define QM_REG_WRROTHERPQGRP_15_RT_OFFSET 29894 +#define QM_REG_WRROTHERGRPWEIGHT_0_RT_OFFSET 29895 +#define QM_REG_WRROTHERGRPWEIGHT_1_RT_OFFSET 29896 +#define QM_REG_WRROTHERGRPWEIGHT_2_RT_OFFSET 29897 +#define QM_REG_WRROTHERGRPWEIGHT_3_RT_OFFSET 29898 +#define QM_REG_WRRTXGRPWEIGHT_0_RT_OFFSET 29899 +#define QM_REG_WRRTXGRPWEIGHT_1_RT_OFFSET 29900 +#define QM_REG_PQTX2PF_0_RT_OFFSET 29901 +#define QM_REG_PQTX2PF_1_RT_OFFSET 29902 +#define QM_REG_PQTX2PF_2_RT_OFFSET 29903 +#define QM_REG_PQTX2PF_3_RT_OFFSET 29904 +#define QM_REG_PQTX2PF_4_RT_OFFSET 29905 +#define QM_REG_PQTX2PF_5_RT_OFFSET 29906 +#define QM_REG_PQTX2PF_6_RT_OFFSET 29907 +#define QM_REG_PQTX2PF_7_RT_OFFSET 29908 +#define QM_REG_PQTX2PF_8_RT_OFFSET 29909 +#define QM_REG_PQTX2PF_9_RT_OFFSET 29910 +#define QM_REG_PQTX2PF_10_RT_OFFSET 29911 +#define QM_REG_PQTX2PF_11_RT_OFFSET 29912 +#define QM_REG_PQTX2PF_12_RT_OFFSET 29913 +#define QM_REG_PQTX2PF_13_RT_OFFSET 29914 +#define QM_REG_PQTX2PF_14_RT_OFFSET 29915 +#define QM_REG_PQTX2PF_15_RT_OFFSET 29916 +#define QM_REG_PQTX2PF_16_RT_OFFSET 29917 +#define QM_REG_PQTX2PF_17_RT_OFFSET 29918 +#define QM_REG_PQTX2PF_18_RT_OFFSET 29919 +#define QM_REG_PQTX2PF_19_RT_OFFSET 29920 +#define QM_REG_PQTX2PF_20_RT_OFFSET 29921 +#define QM_REG_PQTX2PF_21_RT_OFFSET 29922 +#define QM_REG_PQTX2PF_22_RT_OFFSET 29923 +#define QM_REG_PQTX2PF_23_RT_OFFSET 29924 +#define QM_REG_PQTX2PF_24_RT_OFFSET 29925 +#define QM_REG_PQTX2PF_25_RT_OFFSET 29926 +#define QM_REG_PQTX2PF_26_RT_OFFSET 29927 +#define QM_REG_PQTX2PF_27_RT_OFFSET 29928 +#define QM_REG_PQTX2PF_28_RT_OFFSET 29929 +#define QM_REG_PQTX2PF_29_RT_OFFSET 29930 +#define QM_REG_PQTX2PF_30_RT_OFFSET 29931 +#define QM_REG_PQTX2PF_31_RT_OFFSET 29932 +#define QM_REG_PQTX2PF_32_RT_OFFSET 29933 +#define QM_REG_PQTX2PF_33_RT_OFFSET 29934 +#define QM_REG_PQTX2PF_34_RT_OFFSET 29935 +#define QM_REG_PQTX2PF_35_RT_OFFSET 29936 +#define QM_REG_PQTX2PF_36_RT_OFFSET 29937 +#define QM_REG_PQTX2PF_37_RT_OFFSET 29938 +#define QM_REG_PQTX2PF_38_RT_OFFSET 29939 +#define QM_REG_PQTX2PF_39_RT_OFFSET 29940 +#define QM_REG_PQTX2PF_40_RT_OFFSET 29941 +#define QM_REG_PQTX2PF_41_RT_OFFSET 29942 +#define QM_REG_PQTX2PF_42_RT_OFFSET 29943 +#define QM_REG_PQTX2PF_43_RT_OFFSET 29944 +#define QM_REG_PQTX2PF_44_RT_OFFSET 29945 +#define QM_REG_PQTX2PF_45_RT_OFFSET 29946 +#define QM_REG_PQTX2PF_46_RT_OFFSET 29947 +#define QM_REG_PQTX2PF_47_RT_OFFSET 29948 +#define QM_REG_PQTX2PF_48_RT_OFFSET 29949 +#define QM_REG_PQTX2PF_49_RT_OFFSET 29950 +#define QM_REG_PQTX2PF_50_RT_OFFSET 29951 +#define QM_REG_PQTX2PF_51_RT_OFFSET 29952 +#define QM_REG_PQTX2PF_52_RT_OFFSET 29953 +#define QM_REG_PQTX2PF_53_RT_OFFSET 29954 +#define QM_REG_PQTX2PF_54_RT_OFFSET 29955 +#define QM_REG_PQTX2PF_55_RT_OFFSET 29956 +#define QM_REG_PQTX2PF_56_RT_OFFSET 29957 +#define QM_REG_PQTX2PF_57_RT_OFFSET 29958 +#define QM_REG_PQTX2PF_58_RT_OFFSET 29959 +#define QM_REG_PQTX2PF_59_RT_OFFSET 29960 +#define QM_REG_PQTX2PF_60_RT_OFFSET 29961 +#define QM_REG_PQTX2PF_61_RT_OFFSET 29962 +#define QM_REG_PQTX2PF_62_RT_OFFSET 29963 +#define QM_REG_PQTX2PF_63_RT_OFFSET 29964 +#define QM_REG_PQOTHER2PF_0_RT_OFFSET 29965 +#define QM_REG_PQOTHER2PF_1_RT_OFFSET 29966 +#define QM_REG_PQOTHER2PF_2_RT_OFFSET 29967 +#define QM_REG_PQOTHER2PF_3_RT_OFFSET 29968 +#define QM_REG_PQOTHER2PF_4_RT_OFFSET 29969 +#define QM_REG_PQOTHER2PF_5_RT_OFFSET 29970 +#define QM_REG_PQOTHER2PF_6_RT_OFFSET 29971 +#define QM_REG_PQOTHER2PF_7_RT_OFFSET 29972 +#define QM_REG_PQOTHER2PF_8_RT_OFFSET 29973 +#define QM_REG_PQOTHER2PF_9_RT_OFFSET 29974 +#define QM_REG_PQOTHER2PF_10_RT_OFFSET 29975 +#define QM_REG_PQOTHER2PF_11_RT_OFFSET 29976 +#define QM_REG_PQOTHER2PF_12_RT_OFFSET 29977 +#define QM_REG_PQOTHER2PF_13_RT_OFFSET 29978 +#define QM_REG_PQOTHER2PF_14_RT_OFFSET 29979 +#define QM_REG_PQOTHER2PF_15_RT_OFFSET 29980 +#define QM_REG_RLGLBLPERIOD_0_RT_OFFSET 29981 +#define QM_REG_RLGLBLPERIOD_1_RT_OFFSET 29982 +#define QM_REG_RLGLBLPERIODTIMER_0_RT_OFFSET 29983 +#define QM_REG_RLGLBLPERIODTIMER_1_RT_OFFSET 29984 +#define QM_REG_RLGLBLPERIODSEL_0_RT_OFFSET 29985 +#define QM_REG_RLGLBLPERIODSEL_1_RT_OFFSET 29986 +#define QM_REG_RLGLBLPERIODSEL_2_RT_OFFSET 29987 +#define QM_REG_RLGLBLPERIODSEL_3_RT_OFFSET 29988 +#define QM_REG_RLGLBLPERIODSEL_4_RT_OFFSET 29989 +#define QM_REG_RLGLBLPERIODSEL_5_RT_OFFSET 29990 +#define QM_REG_RLGLBLPERIODSEL_6_RT_OFFSET 29991 +#define QM_REG_RLGLBLPERIODSEL_7_RT_OFFSET 29992 +#define QM_REG_RLGLBLINCVAL_RT_OFFSET 29993 +#define QM_REG_RLGLBLINCVAL_RT_SIZE 256 +#define QM_REG_RLGLBLUPPERBOUND_RT_OFFSET 30249 +#define QM_REG_RLGLBLUPPERBOUND_RT_SIZE 256 +#define QM_REG_RLGLBLCRD_RT_OFFSET 30505 +#define QM_REG_RLGLBLCRD_RT_SIZE 256 +#define QM_REG_RLGLBLENABLE_RT_OFFSET 30761 +#define QM_REG_RLPFPERIOD_RT_OFFSET 30762 +#define QM_REG_RLPFPERIODTIMER_RT_OFFSET 30763 +#define QM_REG_RLPFINCVAL_RT_OFFSET 30764 +#define QM_REG_RLPFINCVAL_RT_SIZE 16 +#define QM_REG_RLPFUPPERBOUND_RT_OFFSET 30780 +#define QM_REG_RLPFUPPERBOUND_RT_SIZE 16 +#define QM_REG_RLPFCRD_RT_OFFSET 30796 +#define QM_REG_RLPFCRD_RT_SIZE 16 +#define QM_REG_RLPFENABLE_RT_OFFSET 30812 +#define QM_REG_RLPFVOQENABLE_RT_OFFSET 30813 +#define QM_REG_WFQPFWEIGHT_RT_OFFSET 30814 +#define QM_REG_WFQPFWEIGHT_RT_SIZE 16 +#define QM_REG_WFQPFUPPERBOUND_RT_OFFSET 30830 +#define QM_REG_WFQPFUPPERBOUND_RT_SIZE 16 +#define QM_REG_WFQPFCRD_RT_OFFSET 30846 +#define QM_REG_WFQPFCRD_RT_SIZE 160 +#define QM_REG_WFQPFENABLE_RT_OFFSET 31006 +#define QM_REG_WFQVPENABLE_RT_OFFSET 31007 +#define QM_REG_BASEADDRTXPQ_RT_OFFSET 31008 +#define QM_REG_BASEADDRTXPQ_RT_SIZE 512 +#define QM_REG_TXPQMAP_RT_OFFSET 31520 +#define QM_REG_TXPQMAP_RT_SIZE 512 +#define QM_REG_WFQVPWEIGHT_RT_OFFSET 32032 +#define QM_REG_WFQVPWEIGHT_RT_SIZE 512 +#define QM_REG_WFQVPUPPERBOUND_RT_OFFSET 32544 +#define QM_REG_WFQVPUPPERBOUND_RT_SIZE 512 +#define QM_REG_WFQVPCRD_RT_OFFSET 33056 +#define QM_REG_WFQVPCRD_RT_SIZE 512 +#define QM_REG_WFQVPMAP_RT_OFFSET 33568 +#define QM_REG_WFQVPMAP_RT_SIZE 512 +#define QM_REG_WFQPFCRD_MSB_RT_OFFSET 34080 +#define QM_REG_WFQPFCRD_MSB_RT_SIZE 160 +#define NIG_REG_LLH_CLS_TYPE_DUALMODE_RT_OFFSET 34240 +#define NIG_REG_OUTER_TAG_VALUE_LIST0_RT_OFFSET 34241 +#define NIG_REG_OUTER_TAG_VALUE_LIST1_RT_OFFSET 34242 +#define NIG_REG_OUTER_TAG_VALUE_LIST2_RT_OFFSET 34243 +#define NIG_REG_OUTER_TAG_VALUE_LIST3_RT_OFFSET 34244 +#define NIG_REG_OUTER_TAG_VALUE_MASK_RT_OFFSET 34245 +#define NIG_REG_LLH_FUNC_TAGMAC_CLS_TYPE_RT_OFFSET 34246 +#define NIG_REG_LLH_FUNC_TAG_EN_RT_OFFSET 34247 +#define NIG_REG_LLH_FUNC_TAG_EN_RT_SIZE 4 +#define NIG_REG_LLH_FUNC_TAG_HDR_SEL_RT_OFFSET 34251 +#define NIG_REG_LLH_FUNC_TAG_HDR_SEL_RT_SIZE 4 +#define NIG_REG_LLH_FUNC_TAG_VALUE_RT_OFFSET 34255 +#define NIG_REG_LLH_FUNC_TAG_VALUE_RT_SIZE 4 +#define NIG_REG_LLH_FUNC_NO_TAG_RT_OFFSET 34259 +#define NIG_REG_LLH_FUNC_FILTER_VALUE_RT_OFFSET 34260 +#define NIG_REG_LLH_FUNC_FILTER_VALUE_RT_SIZE 32 +#define NIG_REG_LLH_FUNC_FILTER_EN_RT_OFFSET 34292 +#define NIG_REG_LLH_FUNC_FILTER_EN_RT_SIZE 16 +#define NIG_REG_LLH_FUNC_FILTER_MODE_RT_OFFSET 34308 +#define NIG_REG_LLH_FUNC_FILTER_MODE_RT_SIZE 16 +#define NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_RT_OFFSET 34324 +#define NIG_REG_LLH_FUNC_FILTER_PROTOCOL_TYPE_RT_SIZE 16 +#define NIG_REG_LLH_FUNC_FILTER_HDR_SEL_RT_OFFSET 34340 +#define NIG_REG_LLH_FUNC_FILTER_HDR_SEL_RT_SIZE 16 +#define NIG_REG_TX_EDPM_CTRL_RT_OFFSET 34356 +#define CDU_REG_CID_ADDR_PARAMS_RT_OFFSET 34357 +#define CDU_REG_SEGMENT0_PARAMS_RT_OFFSET 34358 +#define CDU_REG_SEGMENT1_PARAMS_RT_OFFSET 34359 +#define CDU_REG_PF_SEG0_TYPE_OFFSET_RT_OFFSET 34360 +#define CDU_REG_PF_SEG1_TYPE_OFFSET_RT_OFFSET 34361 +#define CDU_REG_PF_SEG2_TYPE_OFFSET_RT_OFFSET 34362 +#define CDU_REG_PF_SEG3_TYPE_OFFSET_RT_OFFSET 34363 +#define CDU_REG_PF_FL_SEG0_TYPE_OFFSET_RT_OFFSET 34364 +#define CDU_REG_PF_FL_SEG1_TYPE_OFFSET_RT_OFFSET 34365 +#define CDU_REG_PF_FL_SEG2_TYPE_OFFSET_RT_OFFSET 34366 +#define CDU_REG_PF_FL_SEG3_TYPE_OFFSET_RT_OFFSET 34367 +#define CDU_REG_VF_SEG_TYPE_OFFSET_RT_OFFSET 34368 +#define CDU_REG_VF_FL_SEG_TYPE_OFFSET_RT_OFFSET 34369 +#define PBF_REG_BTB_SHARED_AREA_SIZE_RT_OFFSET 34370 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ0_RT_OFFSET 34371 +#define PBF_REG_BTB_GUARANTEED_VOQ0_RT_OFFSET 34372 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ0_RT_OFFSET 34373 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ1_RT_OFFSET 34374 +#define PBF_REG_BTB_GUARANTEED_VOQ1_RT_OFFSET 34375 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ1_RT_OFFSET 34376 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ2_RT_OFFSET 34377 +#define PBF_REG_BTB_GUARANTEED_VOQ2_RT_OFFSET 34378 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ2_RT_OFFSET 34379 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ3_RT_OFFSET 34380 +#define PBF_REG_BTB_GUARANTEED_VOQ3_RT_OFFSET 34381 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ3_RT_OFFSET 34382 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ4_RT_OFFSET 34383 +#define PBF_REG_BTB_GUARANTEED_VOQ4_RT_OFFSET 34384 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ4_RT_OFFSET 34385 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ5_RT_OFFSET 34386 +#define PBF_REG_BTB_GUARANTEED_VOQ5_RT_OFFSET 34387 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ5_RT_OFFSET 34388 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ6_RT_OFFSET 34389 +#define PBF_REG_BTB_GUARANTEED_VOQ6_RT_OFFSET 34390 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ6_RT_OFFSET 34391 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ7_RT_OFFSET 34392 +#define PBF_REG_BTB_GUARANTEED_VOQ7_RT_OFFSET 34393 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ7_RT_OFFSET 34394 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ8_RT_OFFSET 34395 +#define PBF_REG_BTB_GUARANTEED_VOQ8_RT_OFFSET 34396 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ8_RT_OFFSET 34397 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ9_RT_OFFSET 34398 +#define PBF_REG_BTB_GUARANTEED_VOQ9_RT_OFFSET 34399 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ9_RT_OFFSET 34400 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ10_RT_OFFSET 34401 +#define PBF_REG_BTB_GUARANTEED_VOQ10_RT_OFFSET 34402 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ10_RT_OFFSET 34403 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ11_RT_OFFSET 34404 +#define PBF_REG_BTB_GUARANTEED_VOQ11_RT_OFFSET 34405 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ11_RT_OFFSET 34406 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ12_RT_OFFSET 34407 +#define PBF_REG_BTB_GUARANTEED_VOQ12_RT_OFFSET 34408 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ12_RT_OFFSET 34409 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ13_RT_OFFSET 34410 +#define PBF_REG_BTB_GUARANTEED_VOQ13_RT_OFFSET 34411 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ13_RT_OFFSET 34412 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ14_RT_OFFSET 34413 +#define PBF_REG_BTB_GUARANTEED_VOQ14_RT_OFFSET 34414 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ14_RT_OFFSET 34415 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ15_RT_OFFSET 34416 +#define PBF_REG_BTB_GUARANTEED_VOQ15_RT_OFFSET 34417 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ15_RT_OFFSET 34418 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ16_RT_OFFSET 34419 +#define PBF_REG_BTB_GUARANTEED_VOQ16_RT_OFFSET 34420 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ16_RT_OFFSET 34421 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ17_RT_OFFSET 34422 +#define PBF_REG_BTB_GUARANTEED_VOQ17_RT_OFFSET 34423 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ17_RT_OFFSET 34424 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ18_RT_OFFSET 34425 +#define PBF_REG_BTB_GUARANTEED_VOQ18_RT_OFFSET 34426 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ18_RT_OFFSET 34427 +#define PBF_REG_YCMD_QS_NUM_LINES_VOQ19_RT_OFFSET 34428 +#define PBF_REG_BTB_GUARANTEED_VOQ19_RT_OFFSET 34429 +#define PBF_REG_BTB_SHARED_AREA_SETUP_VOQ19_RT_OFFSET 34430 +#define XCM_REG_CON_PHY_Q3_RT_OFFSET 34431 + +#define RUNTIME_ARRAY_SIZE 34432 + +/* The eth storm context for the Ystorm */ +struct ystorm_eth_conn_st_ctx { + __le32 reserved[4]; +}; + +/* The eth storm context for the Pstorm */ +struct pstorm_eth_conn_st_ctx { + __le32 reserved[8]; +}; + +/* The eth storm context for the Xstorm */ +struct xstorm_eth_conn_st_ctx { + __le32 reserved[60]; +}; + +struct xstorm_eth_conn_ag_ctx { + u8 reserved0 /* cdu_validation */; + u8 eth_state /* state */; + u8 flags0; +#define XSTORM_ETH_CONN_AG_CTX_EXIST_IN_QM0_MASK 0x1 +#define XSTORM_ETH_CONN_AG_CTX_EXIST_IN_QM0_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED1_MASK 0x1 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED1_SHIFT 1 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED2_MASK 0x1 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED2_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_EXIST_IN_QM3_MASK 0x1 +#define XSTORM_ETH_CONN_AG_CTX_EXIST_IN_QM3_SHIFT 3 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED3_MASK 0x1 /* bit4 */ +#define XSTORM_ETH_CONN_AG_CTX_RESERVED3_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED4_MASK 0x1 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED4_SHIFT 5 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED5_MASK 0x1 /* bit6 */ +#define XSTORM_ETH_CONN_AG_CTX_RESERVED5_SHIFT 6 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED6_MASK 0x1 /* bit7 */ +#define XSTORM_ETH_CONN_AG_CTX_RESERVED6_SHIFT 7 + u8 flags1; +#define XSTORM_ETH_CONN_AG_CTX_RESERVED7_MASK 0x1 /* bit8 */ +#define XSTORM_ETH_CONN_AG_CTX_RESERVED7_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED8_MASK 0x1 /* bit9 */ +#define XSTORM_ETH_CONN_AG_CTX_RESERVED8_SHIFT 1 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED9_MASK 0x1 /* bit10 */ +#define XSTORM_ETH_CONN_AG_CTX_RESERVED9_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_BIT11_MASK 0x1 /* bit11 */ +#define XSTORM_ETH_CONN_AG_CTX_BIT11_SHIFT 3 +#define XSTORM_ETH_CONN_AG_CTX_BIT12_MASK 0x1 /* bit12 */ +#define XSTORM_ETH_CONN_AG_CTX_BIT12_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_BIT13_MASK 0x1 /* bit13 */ +#define XSTORM_ETH_CONN_AG_CTX_BIT13_SHIFT 5 +#define XSTORM_ETH_CONN_AG_CTX_TX_RULE_ACTIVE_MASK 0x1 /* bit14 */ +#define XSTORM_ETH_CONN_AG_CTX_TX_RULE_ACTIVE_SHIFT 6 +#define XSTORM_ETH_CONN_AG_CTX_DQ_CF_ACTIVE_MASK 0x1 /* bit15 */ +#define XSTORM_ETH_CONN_AG_CTX_DQ_CF_ACTIVE_SHIFT 7 + u8 flags2; +#define XSTORM_ETH_CONN_AG_CTX_CF0_MASK 0x3 /* timer0cf */ +#define XSTORM_ETH_CONN_AG_CTX_CF0_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_CF1_MASK 0x3 /* timer1cf */ +#define XSTORM_ETH_CONN_AG_CTX_CF1_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_CF2_MASK 0x3 /* timer2cf */ +#define XSTORM_ETH_CONN_AG_CTX_CF2_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_CF3_MASK 0x3 +#define XSTORM_ETH_CONN_AG_CTX_CF3_SHIFT 6 + u8 flags3; +#define XSTORM_ETH_CONN_AG_CTX_CF4_MASK 0x3 /* cf4 */ +#define XSTORM_ETH_CONN_AG_CTX_CF4_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_CF5_MASK 0x3 /* cf5 */ +#define XSTORM_ETH_CONN_AG_CTX_CF5_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_CF6_MASK 0x3 /* cf6 */ +#define XSTORM_ETH_CONN_AG_CTX_CF6_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_CF7_MASK 0x3 /* cf7 */ +#define XSTORM_ETH_CONN_AG_CTX_CF7_SHIFT 6 + u8 flags4; +#define XSTORM_ETH_CONN_AG_CTX_CF8_MASK 0x3 /* cf8 */ +#define XSTORM_ETH_CONN_AG_CTX_CF8_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_CF9_MASK 0x3 /* cf9 */ +#define XSTORM_ETH_CONN_AG_CTX_CF9_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_CF10_MASK 0x3 /* cf10 */ +#define XSTORM_ETH_CONN_AG_CTX_CF10_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_CF11_MASK 0x3 /* cf11 */ +#define XSTORM_ETH_CONN_AG_CTX_CF11_SHIFT 6 + u8 flags5; +#define XSTORM_ETH_CONN_AG_CTX_CF12_MASK 0x3 /* cf12 */ +#define XSTORM_ETH_CONN_AG_CTX_CF12_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_CF13_MASK 0x3 /* cf13 */ +#define XSTORM_ETH_CONN_AG_CTX_CF13_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_CF14_MASK 0x3 /* cf14 */ +#define XSTORM_ETH_CONN_AG_CTX_CF14_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_CF15_MASK 0x3 /* cf15 */ +#define XSTORM_ETH_CONN_AG_CTX_CF15_SHIFT 6 + u8 flags6; +#define XSTORM_ETH_CONN_AG_CTX_GO_TO_BD_CONS_CF_MASK 0x3 /* cf16 */ +#define XSTORM_ETH_CONN_AG_CTX_GO_TO_BD_CONS_CF_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_MULTI_UNICAST_CF_MASK 0x3 +#define XSTORM_ETH_CONN_AG_CTX_MULTI_UNICAST_CF_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_DQ_CF_MASK 0x3 /* cf18 */ +#define XSTORM_ETH_CONN_AG_CTX_DQ_CF_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_TERMINATE_CF_MASK 0x3 /* cf19 */ +#define XSTORM_ETH_CONN_AG_CTX_TERMINATE_CF_SHIFT 6 + u8 flags7; +#define XSTORM_ETH_CONN_AG_CTX_FLUSH_Q0_MASK 0x3 /* cf20 */ +#define XSTORM_ETH_CONN_AG_CTX_FLUSH_Q0_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED10_MASK 0x3 /* cf21 */ +#define XSTORM_ETH_CONN_AG_CTX_RESERVED10_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_SLOW_PATH_MASK 0x3 /* cf22 */ +#define XSTORM_ETH_CONN_AG_CTX_SLOW_PATH_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */ +#define XSTORM_ETH_CONN_AG_CTX_CF0EN_SHIFT 6 +#define XSTORM_ETH_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */ +#define XSTORM_ETH_CONN_AG_CTX_CF1EN_SHIFT 7 + u8 flags8; +#define XSTORM_ETH_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */ +#define XSTORM_ETH_CONN_AG_CTX_CF2EN_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_CF3EN_MASK 0x1 /* cf3en */ +#define XSTORM_ETH_CONN_AG_CTX_CF3EN_SHIFT 1 +#define XSTORM_ETH_CONN_AG_CTX_CF4EN_MASK 0x1 /* cf4en */ +#define XSTORM_ETH_CONN_AG_CTX_CF4EN_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_CF5EN_MASK 0x1 /* cf5en */ +#define XSTORM_ETH_CONN_AG_CTX_CF5EN_SHIFT 3 +#define XSTORM_ETH_CONN_AG_CTX_CF6EN_MASK 0x1 /* cf6en */ +#define XSTORM_ETH_CONN_AG_CTX_CF6EN_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_CF7EN_MASK 0x1 /* cf7en */ +#define XSTORM_ETH_CONN_AG_CTX_CF7EN_SHIFT 5 +#define XSTORM_ETH_CONN_AG_CTX_CF8EN_MASK 0x1 /* cf8en */ +#define XSTORM_ETH_CONN_AG_CTX_CF8EN_SHIFT 6 +#define XSTORM_ETH_CONN_AG_CTX_CF9EN_MASK 0x1 /* cf9en */ +#define XSTORM_ETH_CONN_AG_CTX_CF9EN_SHIFT 7 + u8 flags9; +#define XSTORM_ETH_CONN_AG_CTX_CF10EN_MASK 0x1 /* cf10en */ +#define XSTORM_ETH_CONN_AG_CTX_CF10EN_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_CF11EN_MASK 0x1 /* cf11en */ +#define XSTORM_ETH_CONN_AG_CTX_CF11EN_SHIFT 1 +#define XSTORM_ETH_CONN_AG_CTX_CF12EN_MASK 0x1 /* cf12en */ +#define XSTORM_ETH_CONN_AG_CTX_CF12EN_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_CF13EN_MASK 0x1 /* cf13en */ +#define XSTORM_ETH_CONN_AG_CTX_CF13EN_SHIFT 3 +#define XSTORM_ETH_CONN_AG_CTX_CF14EN_MASK 0x1 /* cf14en */ +#define XSTORM_ETH_CONN_AG_CTX_CF14EN_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_CF15EN_MASK 0x1 /* cf15en */ +#define XSTORM_ETH_CONN_AG_CTX_CF15EN_SHIFT 5 +#define XSTORM_ETH_CONN_AG_CTX_GO_TO_BD_CONS_CF_EN_MASK 0x1 /* cf16en */ +#define XSTORM_ETH_CONN_AG_CTX_GO_TO_BD_CONS_CF_EN_SHIFT 6 +#define XSTORM_ETH_CONN_AG_CTX_MULTI_UNICAST_CF_EN_MASK 0x1 +#define XSTORM_ETH_CONN_AG_CTX_MULTI_UNICAST_CF_EN_SHIFT 7 + u8 flags10; +#define XSTORM_ETH_CONN_AG_CTX_DQ_CF_EN_MASK 0x1 /* cf18en */ +#define XSTORM_ETH_CONN_AG_CTX_DQ_CF_EN_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_TERMINATE_CF_EN_MASK 0x1 /* cf19en */ +#define XSTORM_ETH_CONN_AG_CTX_TERMINATE_CF_EN_SHIFT 1 +#define XSTORM_ETH_CONN_AG_CTX_FLUSH_Q0_EN_MASK 0x1 /* cf20en */ +#define XSTORM_ETH_CONN_AG_CTX_FLUSH_Q0_EN_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED11_MASK 0x1 /* cf21en */ +#define XSTORM_ETH_CONN_AG_CTX_RESERVED11_SHIFT 3 +#define XSTORM_ETH_CONN_AG_CTX_SLOW_PATH_EN_MASK 0x1 /* cf22en */ +#define XSTORM_ETH_CONN_AG_CTX_SLOW_PATH_EN_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_TPH_ENABLE_EN_RESERVED_MASK 0x1 /* cf23en */ +#define XSTORM_ETH_CONN_AG_CTX_TPH_ENABLE_EN_RESERVED_SHIFT 5 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED12_MASK 0x1 /* rule0en */ +#define XSTORM_ETH_CONN_AG_CTX_RESERVED12_SHIFT 6 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED13_MASK 0x1 /* rule1en */ +#define XSTORM_ETH_CONN_AG_CTX_RESERVED13_SHIFT 7 + u8 flags11; +#define XSTORM_ETH_CONN_AG_CTX_RESERVED14_MASK 0x1 /* rule2en */ +#define XSTORM_ETH_CONN_AG_CTX_RESERVED14_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_RESERVED15_MASK 0x1 /* rule3en */ +#define XSTORM_ETH_CONN_AG_CTX_RESERVED15_SHIFT 1 +#define XSTORM_ETH_CONN_AG_CTX_TX_DEC_RULE_EN_MASK 0x1 /* rule4en */ +#define XSTORM_ETH_CONN_AG_CTX_TX_DEC_RULE_EN_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_RULE5EN_MASK 0x1 /* rule5en */ +#define XSTORM_ETH_CONN_AG_CTX_RULE5EN_SHIFT 3 +#define XSTORM_ETH_CONN_AG_CTX_RULE6EN_MASK 0x1 /* rule6en */ +#define XSTORM_ETH_CONN_AG_CTX_RULE6EN_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_RULE7EN_MASK 0x1 /* rule7en */ +#define XSTORM_ETH_CONN_AG_CTX_RULE7EN_SHIFT 5 +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED1_MASK 0x1 /* rule8en */ +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED1_SHIFT 6 +#define XSTORM_ETH_CONN_AG_CTX_RULE9EN_MASK 0x1 /* rule9en */ +#define XSTORM_ETH_CONN_AG_CTX_RULE9EN_SHIFT 7 + u8 flags12; +#define XSTORM_ETH_CONN_AG_CTX_RULE10EN_MASK 0x1 /* rule10en */ +#define XSTORM_ETH_CONN_AG_CTX_RULE10EN_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_RULE11EN_MASK 0x1 /* rule11en */ +#define XSTORM_ETH_CONN_AG_CTX_RULE11EN_SHIFT 1 +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED2_MASK 0x1 /* rule12en */ +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED2_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED3_MASK 0x1 /* rule13en */ +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED3_SHIFT 3 +#define XSTORM_ETH_CONN_AG_CTX_RULE14EN_MASK 0x1 /* rule14en */ +#define XSTORM_ETH_CONN_AG_CTX_RULE14EN_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_RULE15EN_MASK 0x1 /* rule15en */ +#define XSTORM_ETH_CONN_AG_CTX_RULE15EN_SHIFT 5 +#define XSTORM_ETH_CONN_AG_CTX_RULE16EN_MASK 0x1 /* rule16en */ +#define XSTORM_ETH_CONN_AG_CTX_RULE16EN_SHIFT 6 +#define XSTORM_ETH_CONN_AG_CTX_RULE17EN_MASK 0x1 /* rule17en */ +#define XSTORM_ETH_CONN_AG_CTX_RULE17EN_SHIFT 7 + u8 flags13; +#define XSTORM_ETH_CONN_AG_CTX_RULE18EN_MASK 0x1 /* rule18en */ +#define XSTORM_ETH_CONN_AG_CTX_RULE18EN_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_RULE19EN_MASK 0x1 /* rule19en */ +#define XSTORM_ETH_CONN_AG_CTX_RULE19EN_SHIFT 1 +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED4_MASK 0x1 /* rule20en */ +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED4_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED5_MASK 0x1 /* rule21en */ +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED5_SHIFT 3 +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED6_MASK 0x1 /* rule22en */ +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED6_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED7_MASK 0x1 /* rule23en */ +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED7_SHIFT 5 +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED8_MASK 0x1 /* rule24en */ +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED8_SHIFT 6 +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED9_MASK 0x1 /* rule25en */ +#define XSTORM_ETH_CONN_AG_CTX_A0_RESERVED9_SHIFT 7 + u8 flags14; +#define XSTORM_ETH_CONN_AG_CTX_EDPM_USE_EXT_HDR_MASK 0x1 /* bit16 */ +#define XSTORM_ETH_CONN_AG_CTX_EDPM_USE_EXT_HDR_SHIFT 0 +#define XSTORM_ETH_CONN_AG_CTX_EDPM_SEND_RAW_L3L4_MASK 0x1 /* bit17 */ +#define XSTORM_ETH_CONN_AG_CTX_EDPM_SEND_RAW_L3L4_SHIFT 1 +#define XSTORM_ETH_CONN_AG_CTX_EDPM_INBAND_PROP_HDR_MASK 0x1 /* bit18 */ +#define XSTORM_ETH_CONN_AG_CTX_EDPM_INBAND_PROP_HDR_SHIFT 2 +#define XSTORM_ETH_CONN_AG_CTX_EDPM_SEND_EXT_TUNNEL_MASK 0x1 /* bit19 */ +#define XSTORM_ETH_CONN_AG_CTX_EDPM_SEND_EXT_TUNNEL_SHIFT 3 +#define XSTORM_ETH_CONN_AG_CTX_L2_EDPM_ENABLE_MASK 0x1 /* bit20 */ +#define XSTORM_ETH_CONN_AG_CTX_L2_EDPM_ENABLE_SHIFT 4 +#define XSTORM_ETH_CONN_AG_CTX_ROCE_EDPM_ENABLE_MASK 0x1 /* bit21 */ +#define XSTORM_ETH_CONN_AG_CTX_ROCE_EDPM_ENABLE_SHIFT 5 +#define XSTORM_ETH_CONN_AG_CTX_TPH_ENABLE_MASK 0x3 /* cf23 */ +#define XSTORM_ETH_CONN_AG_CTX_TPH_ENABLE_SHIFT 6 + u8 edpm_event_id /* byte2 */; + __le16 physical_q0 /* physical_q0 */; + __le16 word1 /* physical_q1 */; + __le16 edpm_num_bds /* physical_q2 */; + __le16 tx_bd_cons /* word3 */; + __le16 tx_bd_prod /* word4 */; + __le16 go_to_bd_cons /* word5 */; + __le16 conn_dpi /* conn_dpi */; + u8 byte3 /* byte3 */; + u8 byte4 /* byte4 */; + u8 byte5 /* byte5 */; + u8 byte6 /* byte6 */; + __le32 reg0 /* reg0 */; + __le32 reg1 /* reg1 */; + __le32 reg2 /* reg2 */; + __le32 reg3 /* reg3 */; + __le32 reg4 /* reg4 */; + __le32 reg5 /* cf_array0 */; + __le32 reg6 /* cf_array1 */; + __le16 word7 /* word7 */; + __le16 word8 /* word8 */; + __le16 word9 /* word9 */; + __le16 word10 /* word10 */; + __le32 reg7 /* reg7 */; + __le32 reg8 /* reg8 */; + __le32 reg9 /* reg9 */; + u8 byte7 /* byte7 */; + u8 byte8 /* byte8 */; + u8 byte9 /* byte9 */; + u8 byte10 /* byte10 */; + u8 byte11 /* byte11 */; + u8 byte12 /* byte12 */; + u8 byte13 /* byte13 */; + u8 byte14 /* byte14 */; + u8 byte15 /* byte15 */; + u8 byte16 /* byte16 */; + __le16 word11 /* word11 */; + __le32 reg10 /* reg10 */; + __le32 reg11 /* reg11 */; + __le32 reg12 /* reg12 */; + __le32 reg13 /* reg13 */; + __le32 reg14 /* reg14 */; + __le32 reg15 /* reg15 */; + __le32 reg16 /* reg16 */; + __le32 reg17 /* reg17 */; + __le32 reg18 /* reg18 */; + __le32 reg19 /* reg19 */; + __le16 word12 /* word12 */; + __le16 word13 /* word13 */; + __le16 word14 /* word14 */; + __le16 word15 /* word15 */; +}; + +/* The eth storm context for the Tstorm */ +struct tstorm_eth_conn_st_ctx { + __le32 reserved[4]; +}; + +/* The eth storm context for the Mstorm */ +struct mstorm_eth_conn_st_ctx { + __le32 reserved[8]; +}; + +/* The eth storm context for the Ustorm */ +struct ustorm_eth_conn_st_ctx { + __le32 reserved[40]; +}; + +/* eth connection context */ +struct eth_conn_context { + struct ystorm_eth_conn_st_ctx ystorm_st_context; + struct regpair ystorm_st_padding[2] /* padding */; + struct pstorm_eth_conn_st_ctx pstorm_st_context; + struct regpair pstorm_st_padding[2] /* padding */; + struct xstorm_eth_conn_st_ctx xstorm_st_context; + struct xstorm_eth_conn_ag_ctx xstorm_ag_context; + struct tstorm_eth_conn_st_ctx tstorm_st_context; + struct regpair tstorm_st_padding[2] /* padding */; + struct mstorm_eth_conn_st_ctx mstorm_st_context; + struct ustorm_eth_conn_st_ctx ustorm_st_context; +}; + +struct mstorm_eth_conn_ag_ctx { + u8 byte0 /* cdu_validation */; + u8 byte1 /* state */; + u8 flags0; +#define MSTORM_ETH_CONN_AG_CTX_EXIST_IN_QM0_MASK 0x1 /* exist_in_qm0 */ +#define MSTORM_ETH_CONN_AG_CTX_EXIST_IN_QM0_SHIFT 0 +#define MSTORM_ETH_CONN_AG_CTX_BIT1_MASK 0x1 /* exist_in_qm1 */ +#define MSTORM_ETH_CONN_AG_CTX_BIT1_SHIFT 1 +#define MSTORM_ETH_CONN_AG_CTX_CF0_MASK 0x3 /* cf0 */ +#define MSTORM_ETH_CONN_AG_CTX_CF0_SHIFT 2 +#define MSTORM_ETH_CONN_AG_CTX_CF1_MASK 0x3 /* cf1 */ +#define MSTORM_ETH_CONN_AG_CTX_CF1_SHIFT 4 +#define MSTORM_ETH_CONN_AG_CTX_CF2_MASK 0x3 /* cf2 */ +#define MSTORM_ETH_CONN_AG_CTX_CF2_SHIFT 6 + u8 flags1; +#define MSTORM_ETH_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */ +#define MSTORM_ETH_CONN_AG_CTX_CF0EN_SHIFT 0 +#define MSTORM_ETH_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */ +#define MSTORM_ETH_CONN_AG_CTX_CF1EN_SHIFT 1 +#define MSTORM_ETH_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */ +#define MSTORM_ETH_CONN_AG_CTX_CF2EN_SHIFT 2 +#define MSTORM_ETH_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */ +#define MSTORM_ETH_CONN_AG_CTX_RULE0EN_SHIFT 3 +#define MSTORM_ETH_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */ +#define MSTORM_ETH_CONN_AG_CTX_RULE1EN_SHIFT 4 +#define MSTORM_ETH_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */ +#define MSTORM_ETH_CONN_AG_CTX_RULE2EN_SHIFT 5 +#define MSTORM_ETH_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */ +#define MSTORM_ETH_CONN_AG_CTX_RULE3EN_SHIFT 6 +#define MSTORM_ETH_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */ +#define MSTORM_ETH_CONN_AG_CTX_RULE4EN_SHIFT 7 + __le16 word0 /* word0 */; + __le16 word1 /* word1 */; + __le32 reg0 /* reg0 */; + __le32 reg1 /* reg1 */; +}; + +struct tstorm_eth_conn_ag_ctx { + u8 byte0 /* cdu_validation */; + u8 byte1 /* state */; + u8 flags0; +#define TSTORM_ETH_CONN_AG_CTX_BIT0_MASK 0x1 /* exist_in_qm0 */ +#define TSTORM_ETH_CONN_AG_CTX_BIT0_SHIFT 0 +#define TSTORM_ETH_CONN_AG_CTX_BIT1_MASK 0x1 /* exist_in_qm1 */ +#define TSTORM_ETH_CONN_AG_CTX_BIT1_SHIFT 1 +#define TSTORM_ETH_CONN_AG_CTX_BIT2_MASK 0x1 /* bit2 */ +#define TSTORM_ETH_CONN_AG_CTX_BIT2_SHIFT 2 +#define TSTORM_ETH_CONN_AG_CTX_BIT3_MASK 0x1 /* bit3 */ +#define TSTORM_ETH_CONN_AG_CTX_BIT3_SHIFT 3 +#define TSTORM_ETH_CONN_AG_CTX_BIT4_MASK 0x1 /* bit4 */ +#define TSTORM_ETH_CONN_AG_CTX_BIT4_SHIFT 4 +#define TSTORM_ETH_CONN_AG_CTX_BIT5_MASK 0x1 /* bit5 */ +#define TSTORM_ETH_CONN_AG_CTX_BIT5_SHIFT 5 +#define TSTORM_ETH_CONN_AG_CTX_CF0_MASK 0x3 /* timer0cf */ +#define TSTORM_ETH_CONN_AG_CTX_CF0_SHIFT 6 + u8 flags1; +#define TSTORM_ETH_CONN_AG_CTX_CF1_MASK 0x3 /* timer1cf */ +#define TSTORM_ETH_CONN_AG_CTX_CF1_SHIFT 0 +#define TSTORM_ETH_CONN_AG_CTX_CF2_MASK 0x3 /* timer2cf */ +#define TSTORM_ETH_CONN_AG_CTX_CF2_SHIFT 2 +#define TSTORM_ETH_CONN_AG_CTX_CF3_MASK 0x3 /* timer_stop_all */ +#define TSTORM_ETH_CONN_AG_CTX_CF3_SHIFT 4 +#define TSTORM_ETH_CONN_AG_CTX_CF4_MASK 0x3 /* cf4 */ +#define TSTORM_ETH_CONN_AG_CTX_CF4_SHIFT 6 + u8 flags2; +#define TSTORM_ETH_CONN_AG_CTX_CF5_MASK 0x3 /* cf5 */ +#define TSTORM_ETH_CONN_AG_CTX_CF5_SHIFT 0 +#define TSTORM_ETH_CONN_AG_CTX_CF6_MASK 0x3 /* cf6 */ +#define TSTORM_ETH_CONN_AG_CTX_CF6_SHIFT 2 +#define TSTORM_ETH_CONN_AG_CTX_CF7_MASK 0x3 /* cf7 */ +#define TSTORM_ETH_CONN_AG_CTX_CF7_SHIFT 4 +#define TSTORM_ETH_CONN_AG_CTX_CF8_MASK 0x3 /* cf8 */ +#define TSTORM_ETH_CONN_AG_CTX_CF8_SHIFT 6 + u8 flags3; +#define TSTORM_ETH_CONN_AG_CTX_CF9_MASK 0x3 /* cf9 */ +#define TSTORM_ETH_CONN_AG_CTX_CF9_SHIFT 0 +#define TSTORM_ETH_CONN_AG_CTX_CF10_MASK 0x3 /* cf10 */ +#define TSTORM_ETH_CONN_AG_CTX_CF10_SHIFT 2 +#define TSTORM_ETH_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */ +#define TSTORM_ETH_CONN_AG_CTX_CF0EN_SHIFT 4 +#define TSTORM_ETH_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */ +#define TSTORM_ETH_CONN_AG_CTX_CF1EN_SHIFT 5 +#define TSTORM_ETH_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */ +#define TSTORM_ETH_CONN_AG_CTX_CF2EN_SHIFT 6 +#define TSTORM_ETH_CONN_AG_CTX_CF3EN_MASK 0x1 /* cf3en */ +#define TSTORM_ETH_CONN_AG_CTX_CF3EN_SHIFT 7 + u8 flags4; +#define TSTORM_ETH_CONN_AG_CTX_CF4EN_MASK 0x1 /* cf4en */ +#define TSTORM_ETH_CONN_AG_CTX_CF4EN_SHIFT 0 +#define TSTORM_ETH_CONN_AG_CTX_CF5EN_MASK 0x1 /* cf5en */ +#define TSTORM_ETH_CONN_AG_CTX_CF5EN_SHIFT 1 +#define TSTORM_ETH_CONN_AG_CTX_CF6EN_MASK 0x1 /* cf6en */ +#define TSTORM_ETH_CONN_AG_CTX_CF6EN_SHIFT 2 +#define TSTORM_ETH_CONN_AG_CTX_CF7EN_MASK 0x1 /* cf7en */ +#define TSTORM_ETH_CONN_AG_CTX_CF7EN_SHIFT 3 +#define TSTORM_ETH_CONN_AG_CTX_CF8EN_MASK 0x1 /* cf8en */ +#define TSTORM_ETH_CONN_AG_CTX_CF8EN_SHIFT 4 +#define TSTORM_ETH_CONN_AG_CTX_CF9EN_MASK 0x1 /* cf9en */ +#define TSTORM_ETH_CONN_AG_CTX_CF9EN_SHIFT 5 +#define TSTORM_ETH_CONN_AG_CTX_CF10EN_MASK 0x1 /* cf10en */ +#define TSTORM_ETH_CONN_AG_CTX_CF10EN_SHIFT 6 +#define TSTORM_ETH_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */ +#define TSTORM_ETH_CONN_AG_CTX_RULE0EN_SHIFT 7 + u8 flags5; +#define TSTORM_ETH_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */ +#define TSTORM_ETH_CONN_AG_CTX_RULE1EN_SHIFT 0 +#define TSTORM_ETH_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */ +#define TSTORM_ETH_CONN_AG_CTX_RULE2EN_SHIFT 1 +#define TSTORM_ETH_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */ +#define TSTORM_ETH_CONN_AG_CTX_RULE3EN_SHIFT 2 +#define TSTORM_ETH_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */ +#define TSTORM_ETH_CONN_AG_CTX_RULE4EN_SHIFT 3 +#define TSTORM_ETH_CONN_AG_CTX_RULE5EN_MASK 0x1 /* rule5en */ +#define TSTORM_ETH_CONN_AG_CTX_RULE5EN_SHIFT 4 +#define TSTORM_ETH_CONN_AG_CTX_RX_BD_EN_MASK 0x1 /* rule6en */ +#define TSTORM_ETH_CONN_AG_CTX_RX_BD_EN_SHIFT 5 +#define TSTORM_ETH_CONN_AG_CTX_RULE7EN_MASK 0x1 /* rule7en */ +#define TSTORM_ETH_CONN_AG_CTX_RULE7EN_SHIFT 6 +#define TSTORM_ETH_CONN_AG_CTX_RULE8EN_MASK 0x1 /* rule8en */ +#define TSTORM_ETH_CONN_AG_CTX_RULE8EN_SHIFT 7 + __le32 reg0 /* reg0 */; + __le32 reg1 /* reg1 */; + __le32 reg2 /* reg2 */; + __le32 reg3 /* reg3 */; + __le32 reg4 /* reg4 */; + __le32 reg5 /* reg5 */; + __le32 reg6 /* reg6 */; + __le32 reg7 /* reg7 */; + __le32 reg8 /* reg8 */; + u8 byte2 /* byte2 */; + u8 byte3 /* byte3 */; + __le16 rx_bd_cons /* word0 */; + u8 byte4 /* byte4 */; + u8 byte5 /* byte5 */; + __le16 rx_bd_prod /* word1 */; + __le16 word2 /* conn_dpi */; + __le16 word3 /* word3 */; + __le32 reg9 /* reg9 */; + __le32 reg10 /* reg10 */; +}; + +struct ustorm_eth_conn_ag_ctx { + u8 byte0 /* cdu_validation */; + u8 byte1 /* state */; + u8 flags0; +#define USTORM_ETH_CONN_AG_CTX_BIT0_MASK 0x1 +#define USTORM_ETH_CONN_AG_CTX_BIT0_SHIFT 0 +#define USTORM_ETH_CONN_AG_CTX_BIT1_MASK 0x1 +#define USTORM_ETH_CONN_AG_CTX_BIT1_SHIFT 1 +#define USTORM_ETH_CONN_AG_CTX_CF0_MASK 0x3 /* timer0cf */ +#define USTORM_ETH_CONN_AG_CTX_CF0_SHIFT 2 +#define USTORM_ETH_CONN_AG_CTX_CF1_MASK 0x3 /* timer1cf */ +#define USTORM_ETH_CONN_AG_CTX_CF1_SHIFT 4 +#define USTORM_ETH_CONN_AG_CTX_CF2_MASK 0x3 /* timer2cf */ +#define USTORM_ETH_CONN_AG_CTX_CF2_SHIFT 6 + u8 flags1; +#define USTORM_ETH_CONN_AG_CTX_CF3_MASK 0x3 +#define USTORM_ETH_CONN_AG_CTX_CF3_SHIFT 0 +#define USTORM_ETH_CONN_AG_CTX_TX_ARM_CF_MASK 0x3 /* cf4 */ +#define USTORM_ETH_CONN_AG_CTX_TX_ARM_CF_SHIFT 2 +#define USTORM_ETH_CONN_AG_CTX_RX_ARM_CF_MASK 0x3 /* cf5 */ +#define USTORM_ETH_CONN_AG_CTX_RX_ARM_CF_SHIFT 4 +#define USTORM_ETH_CONN_AG_CTX_TX_BD_CONS_UPD_CF_MASK 0x3 /* cf6 */ +#define USTORM_ETH_CONN_AG_CTX_TX_BD_CONS_UPD_CF_SHIFT 6 + u8 flags2; +#define USTORM_ETH_CONN_AG_CTX_CF0EN_MASK 0x1 /* cf0en */ +#define USTORM_ETH_CONN_AG_CTX_CF0EN_SHIFT 0 +#define USTORM_ETH_CONN_AG_CTX_CF1EN_MASK 0x1 /* cf1en */ +#define USTORM_ETH_CONN_AG_CTX_CF1EN_SHIFT 1 +#define USTORM_ETH_CONN_AG_CTX_CF2EN_MASK 0x1 /* cf2en */ +#define USTORM_ETH_CONN_AG_CTX_CF2EN_SHIFT 2 +#define USTORM_ETH_CONN_AG_CTX_CF3EN_MASK 0x1 /* cf3en */ +#define USTORM_ETH_CONN_AG_CTX_CF3EN_SHIFT 3 +#define USTORM_ETH_CONN_AG_CTX_TX_ARM_CF_EN_MASK 0x1 /* cf4en */ +#define USTORM_ETH_CONN_AG_CTX_TX_ARM_CF_EN_SHIFT 4 +#define USTORM_ETH_CONN_AG_CTX_RX_ARM_CF_EN_MASK 0x1 /* cf5en */ +#define USTORM_ETH_CONN_AG_CTX_RX_ARM_CF_EN_SHIFT 5 +#define USTORM_ETH_CONN_AG_CTX_TX_BD_CONS_UPD_CF_EN_MASK 0x1 /* cf6en */ +#define USTORM_ETH_CONN_AG_CTX_TX_BD_CONS_UPD_CF_EN_SHIFT 6 +#define USTORM_ETH_CONN_AG_CTX_RULE0EN_MASK 0x1 /* rule0en */ +#define USTORM_ETH_CONN_AG_CTX_RULE0EN_SHIFT 7 + u8 flags3; +#define USTORM_ETH_CONN_AG_CTX_RULE1EN_MASK 0x1 /* rule1en */ +#define USTORM_ETH_CONN_AG_CTX_RULE1EN_SHIFT 0 +#define USTORM_ETH_CONN_AG_CTX_RULE2EN_MASK 0x1 /* rule2en */ +#define USTORM_ETH_CONN_AG_CTX_RULE2EN_SHIFT 1 +#define USTORM_ETH_CONN_AG_CTX_RULE3EN_MASK 0x1 /* rule3en */ +#define USTORM_ETH_CONN_AG_CTX_RULE3EN_SHIFT 2 +#define USTORM_ETH_CONN_AG_CTX_RULE4EN_MASK 0x1 /* rule4en */ +#define USTORM_ETH_CONN_AG_CTX_RULE4EN_SHIFT 3 +#define USTORM_ETH_CONN_AG_CTX_RULE5EN_MASK 0x1 /* rule5en */ +#define USTORM_ETH_CONN_AG_CTX_RULE5EN_SHIFT 4 +#define USTORM_ETH_CONN_AG_CTX_RULE6EN_MASK 0x1 /* rule6en */ +#define USTORM_ETH_CONN_AG_CTX_RULE6EN_SHIFT 5 +#define USTORM_ETH_CONN_AG_CTX_RULE7EN_MASK 0x1 /* rule7en */ +#define USTORM_ETH_CONN_AG_CTX_RULE7EN_SHIFT 6 +#define USTORM_ETH_CONN_AG_CTX_RULE8EN_MASK 0x1 /* rule8en */ +#define USTORM_ETH_CONN_AG_CTX_RULE8EN_SHIFT 7 + u8 byte2 /* byte2 */; + u8 byte3 /* byte3 */; + __le16 word0 /* conn_dpi */; + __le16 tx_bd_cons /* word1 */; + __le32 reg0 /* reg0 */; + __le32 reg1 /* reg1 */; + __le32 reg2 /* reg2 */; + __le32 reg3 /* reg3 */; + __le16 tx_drv_bd_cons /* word2 */; + __le16 rx_drv_cqe_cons /* word3 */; +}; + +struct xstorm_eth_hw_conn_ag_ctx { + u8 reserved0 /* cdu_validation */; + u8 eth_state /* state */; + u8 flags0; +#define XSTORM_ETH_HW_CONN_AG_CTX_EXIST_IN_QM0_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_EXIST_IN_QM0_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED1_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED1_SHIFT 1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED2_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED2_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_EXIST_IN_QM3_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_EXIST_IN_QM3_SHIFT 3 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED3_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED3_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED4_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED4_SHIFT 5 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED5_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED5_SHIFT 6 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED6_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED6_SHIFT 7 + u8 flags1; +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED7_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED7_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED8_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED8_SHIFT 1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED9_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED9_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_BIT11_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_BIT11_SHIFT 3 +#define XSTORM_ETH_HW_CONN_AG_CTX_BIT12_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_BIT12_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_BIT13_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_BIT13_SHIFT 5 +#define XSTORM_ETH_HW_CONN_AG_CTX_TX_RULE_ACTIVE_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_TX_RULE_ACTIVE_SHIFT 6 +#define XSTORM_ETH_HW_CONN_AG_CTX_DQ_CF_ACTIVE_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_DQ_CF_ACTIVE_SHIFT 7 + u8 flags2; +#define XSTORM_ETH_HW_CONN_AG_CTX_CF0_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF0_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF1_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF1_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF2_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF2_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF3_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF3_SHIFT 6 + u8 flags3; +#define XSTORM_ETH_HW_CONN_AG_CTX_CF4_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF4_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF5_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF5_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF6_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF6_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF7_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF7_SHIFT 6 + u8 flags4; +#define XSTORM_ETH_HW_CONN_AG_CTX_CF8_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF8_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF9_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF9_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF10_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF10_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF11_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF11_SHIFT 6 + u8 flags5; +#define XSTORM_ETH_HW_CONN_AG_CTX_CF12_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF12_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF13_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF13_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF14_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF14_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF15_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF15_SHIFT 6 + u8 flags6; +#define XSTORM_ETH_HW_CONN_AG_CTX_GO_TO_BD_CONS_CF_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_GO_TO_BD_CONS_CF_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_MULTI_UNICAST_CF_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_MULTI_UNICAST_CF_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_DQ_CF_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_DQ_CF_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_TERMINATE_CF_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_TERMINATE_CF_SHIFT 6 + u8 flags7; +#define XSTORM_ETH_HW_CONN_AG_CTX_FLUSH_Q0_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_FLUSH_Q0_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED10_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED10_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_SLOW_PATH_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_SLOW_PATH_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF0EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF0EN_SHIFT 6 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF1EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF1EN_SHIFT 7 + u8 flags8; +#define XSTORM_ETH_HW_CONN_AG_CTX_CF2EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF2EN_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF3EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF3EN_SHIFT 1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF4EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF4EN_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF5EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF5EN_SHIFT 3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF6EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF6EN_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF7EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF7EN_SHIFT 5 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF8EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF8EN_SHIFT 6 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF9EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF9EN_SHIFT 7 + u8 flags9; +#define XSTORM_ETH_HW_CONN_AG_CTX_CF10EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF10EN_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF11EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF11EN_SHIFT 1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF12EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF12EN_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF13EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF13EN_SHIFT 3 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF14EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF14EN_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF15EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_CF15EN_SHIFT 5 +#define XSTORM_ETH_HW_CONN_AG_CTX_GO_TO_BD_CONS_CF_EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_GO_TO_BD_CONS_CF_EN_SHIFT 6 +#define XSTORM_ETH_HW_CONN_AG_CTX_MULTI_UNICAST_CF_EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_MULTI_UNICAST_CF_EN_SHIFT 7 + u8 flags10; +#define XSTORM_ETH_HW_CONN_AG_CTX_DQ_CF_EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_DQ_CF_EN_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_TERMINATE_CF_EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_TERMINATE_CF_EN_SHIFT 1 +#define XSTORM_ETH_HW_CONN_AG_CTX_FLUSH_Q0_EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_FLUSH_Q0_EN_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED11_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED11_SHIFT 3 +#define XSTORM_ETH_HW_CONN_AG_CTX_SLOW_PATH_EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_SLOW_PATH_EN_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_TPH_ENABLE_EN_RESERVED_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_TPH_ENABLE_EN_RESERVED_SHIFT 5 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED12_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED12_SHIFT 6 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED13_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED13_SHIFT 7 + u8 flags11; +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED14_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED14_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED15_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RESERVED15_SHIFT 1 +#define XSTORM_ETH_HW_CONN_AG_CTX_TX_DEC_RULE_EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_TX_DEC_RULE_EN_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE5EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE5EN_SHIFT 3 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE6EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE6EN_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE7EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE7EN_SHIFT 5 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED1_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED1_SHIFT 6 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE9EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE9EN_SHIFT 7 + u8 flags12; +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE10EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE10EN_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE11EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE11EN_SHIFT 1 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED2_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED2_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED3_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED3_SHIFT 3 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE14EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE14EN_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE15EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE15EN_SHIFT 5 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE16EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE16EN_SHIFT 6 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE17EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE17EN_SHIFT 7 + u8 flags13; +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE18EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE18EN_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE19EN_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_RULE19EN_SHIFT 1 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED4_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED4_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED5_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED5_SHIFT 3 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED6_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED6_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED7_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED7_SHIFT 5 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED8_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED8_SHIFT 6 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED9_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_A0_RESERVED9_SHIFT 7 + u8 flags14; +#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_USE_EXT_HDR_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_USE_EXT_HDR_SHIFT 0 +#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_SEND_RAW_L3L4_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_SEND_RAW_L3L4_SHIFT 1 +#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_INBAND_PROP_HDR_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_INBAND_PROP_HDR_SHIFT 2 +#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_SEND_EXT_TUNNEL_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_EDPM_SEND_EXT_TUNNEL_SHIFT 3 +#define XSTORM_ETH_HW_CONN_AG_CTX_L2_EDPM_ENABLE_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_L2_EDPM_ENABLE_SHIFT 4 +#define XSTORM_ETH_HW_CONN_AG_CTX_ROCE_EDPM_ENABLE_MASK 0x1 +#define XSTORM_ETH_HW_CONN_AG_CTX_ROCE_EDPM_ENABLE_SHIFT 5 +#define XSTORM_ETH_HW_CONN_AG_CTX_TPH_ENABLE_MASK 0x3 +#define XSTORM_ETH_HW_CONN_AG_CTX_TPH_ENABLE_SHIFT 6 + u8 edpm_event_id /* byte2 */; + __le16 physical_q0 /* physical_q0 */; + __le16 word1 /* physical_q1 */; + __le16 edpm_num_bds /* physical_q2 */; + __le16 tx_bd_cons /* word3 */; + __le16 tx_bd_prod /* word4 */; + __le16 go_to_bd_cons /* word5 */; + __le16 conn_dpi /* conn_dpi */; +}; + +#define VF_MAX_STATIC 192 /* In case of K2 */ + +#define MCP_GLOB_PATH_MAX 2 +#define MCP_PORT_MAX 2 /* Global */ +#define MCP_GLOB_PORT_MAX 4 /* Global */ +#define MCP_GLOB_FUNC_MAX 16 /* Global */ + +typedef u32 offsize_t; /* In DWORDS !!! */ +/* Offset from the beginning of the MCP scratchpad */ +#define OFFSIZE_OFFSET_SHIFT 0 +#define OFFSIZE_OFFSET_MASK 0x0000ffff +/* Size of specific element (not the whole array if any) */ +#define OFFSIZE_SIZE_SHIFT 16 +#define OFFSIZE_SIZE_MASK 0xffff0000 + +/* SECTION_OFFSET is calculating the offset in bytes out of offsize */ +#define SECTION_OFFSET(_offsize) ((((_offsize & \ + OFFSIZE_OFFSET_MASK) >> \ + OFFSIZE_OFFSET_SHIFT) << 2)) + +/* QED_SECTION_SIZE is calculating the size in bytes out of offsize */ +#define QED_SECTION_SIZE(_offsize) (((_offsize & \ + OFFSIZE_SIZE_MASK) >> \ + OFFSIZE_SIZE_SHIFT) << 2) + +/* SECTION_ADDR returns the GRC addr of a section, given offsize and index + * within section. + */ +#define SECTION_ADDR(_offsize, idx) (MCP_REG_SCRATCH + \ + SECTION_OFFSET(_offsize) + \ + (QED_SECTION_SIZE(_offsize) * idx)) + +/* SECTION_OFFSIZE_ADDR returns the GRC addr to the offsize address. + * Use offsetof, since the OFFSETUP collide with the firmware definition + */ +#define SECTION_OFFSIZE_ADDR(_pub_base, _section) (_pub_base + \ + offsetof(struct \ + mcp_public_data, \ + sections[_section])) +/* PHY configuration */ +struct pmm_phy_cfg { + u32 speed; +#define PMM_SPEED_AUTONEG 0 + + u32 pause; /* bitmask */ +#define PMM_PAUSE_NONE 0x0 +#define PMM_PAUSE_AUTONEG 0x1 +#define PMM_PAUSE_RX 0x2 +#define PMM_PAUSE_TX 0x4 + + u32 adv_speed; /* Default should be the speed_cap_mask */ + u32 loopback_mode; +#define PMM_LOOPBACK_NONE 0 +#define PMM_LOOPBACK_INT_PHY 1 +#define PMM_LOOPBACK_EXT_PHY 2 +#define PMM_LOOPBACK_EXT 3 +#define PMM_LOOPBACK_MAC 4 + + /* features */ + u32 feature_config_flags; +}; + +struct port_mf_cfg { + u32 dynamic_cfg; /* device control channel */ +#define PORT_MF_CFG_OV_TAG_MASK 0x0000ffff +#define PORT_MF_CFG_OV_TAG_SHIFT 0 +#define PORT_MF_CFG_OV_TAG_DEFAULT PORT_MF_CFG_OV_TAG_MASK + + u32 reserved[1]; +}; + +/* DO NOT add new fields in the middle + * MUST be synced with struct pmm_stats_map + */ +struct pmm_stats { + u64 r64; /* 0x00 (Offset 0x00 ) RX 64-byte frame counter*/ + u64 r127; /* 0x01 (Offset 0x08 ) RX 65 to 127 byte frame counter*/ + u64 r255; + u64 r511; + u64 r1023; + u64 r1518; + u64 r1522; + u64 r2047; + u64 r4095; + u64 r9216; + u64 r16383; + u64 rfcs; /* 0x0F (Offset 0x58 ) RX FCS error frame counter*/ + u64 rxcf; /* 0x10 (Offset 0x60 ) RX control frame counter*/ + u64 rxpf; /* 0x11 (Offset 0x68 ) RX pause frame counter*/ + u64 rxpp; /* 0x12 (Offset 0x70 ) RX PFC frame counter*/ + u64 raln; /* 0x16 (Offset 0x78 ) RX alignment error counter*/ + u64 rfcr; /* 0x19 (Offset 0x80 ) RX false carrier counter */ + u64 rovr; /* 0x1A (Offset 0x88 ) RX oversized frame counter*/ + u64 rjbr; /* 0x1B (Offset 0x90 ) RX jabber frame counter */ + u64 rund; /* 0x34 (Offset 0x98 ) RX undersized frame counter */ + u64 rfrg; /* 0x35 (Offset 0xa0 ) RX fragment counter */ + u64 t64; /* 0x40 (Offset 0xa8 ) TX 64-byte frame counter */ + u64 t127; + u64 t255; + u64 t511; + u64 t1023; + u64 t1518; + u64 t2047; + u64 t4095; + u64 t9216; + u64 t16383; + u64 txpf; /* 0x50 (Offset 0xf8 ) TX pause frame counter */ + u64 txpp; /* 0x51 (Offset 0x100) TX PFC frame counter */ + u64 tlpiec; + u64 tncl; + u64 rbyte; /* 0x3d (Offset 0x118) RX byte counter */ + u64 rxuca; /* 0x0c (Offset 0x120) RX UC frame counter */ + u64 rxmca; /* 0x0d (Offset 0x128) RX MC frame counter */ + u64 rxbca; /* 0x0e (Offset 0x130) RX BC frame counter */ + u64 rxpok; + u64 tbyte; /* 0x6f (Offset 0x140) TX byte counter */ + u64 txuca; /* 0x4d (Offset 0x148) TX UC frame counter */ + u64 txmca; /* 0x4e (Offset 0x150) TX MC frame counter */ + u64 txbca; /* 0x4f (Offset 0x158) TX BC frame counter */ + u64 txcf; /* 0x54 (Offset 0x160) TX control frame counter */ +}; + +struct brb_stats { + u64 brb_truncate[8]; + u64 brb_discard[8]; +}; + +struct port_stats { + struct brb_stats brb; + struct pmm_stats pmm; +}; + +#define CMT_TEAM0 0 +#define CMT_TEAM1 1 +#define CMT_TEAM_MAX 2 + +struct couple_mode_teaming { + u8 port_cmt[MCP_GLOB_PORT_MAX]; +#define PORT_CMT_IN_TEAM BIT(0) + +#define PORT_CMT_PORT_ROLE BIT(1) +#define PORT_CMT_PORT_INACTIVE (0 << 1) +#define PORT_CMT_PORT_ACTIVE BIT(1) + +#define PORT_CMT_TEAM_MASK BIT(2) +#define PORT_CMT_TEAM0 (0 << 2) +#define PORT_CMT_TEAM1 BIT(2) +}; + +/************************************** +* LLDP and DCBX HSI structures +**************************************/ +#define LLDP_CHASSIS_ID_STAT_LEN 4 +#define LLDP_PORT_ID_STAT_LEN 4 +#define DCBX_MAX_APP_PROTOCOL 32 +#define MAX_SYSTEM_LLDP_TLV_DATA 32 + +enum lldp_agent_e { + LLDP_NEAREST_BRIDGE = 0, + LLDP_NEAREST_NON_TPMR_BRIDGE, + LLDP_NEAREST_CUSTOMER_BRIDGE, + LLDP_MAX_LLDP_AGENTS +}; + +struct lldp_config_params_s { + u32 config; +#define LLDP_CONFIG_TX_INTERVAL_MASK 0x000000ff +#define LLDP_CONFIG_TX_INTERVAL_SHIFT 0 +#define LLDP_CONFIG_HOLD_MASK 0x00000f00 +#define LLDP_CONFIG_HOLD_SHIFT 8 +#define LLDP_CONFIG_MAX_CREDIT_MASK 0x0000f000 +#define LLDP_CONFIG_MAX_CREDIT_SHIFT 12 +#define LLDP_CONFIG_ENABLE_RX_MASK 0x40000000 +#define LLDP_CONFIG_ENABLE_RX_SHIFT 30 +#define LLDP_CONFIG_ENABLE_TX_MASK 0x80000000 +#define LLDP_CONFIG_ENABLE_TX_SHIFT 31 + u32 local_chassis_id[LLDP_CHASSIS_ID_STAT_LEN]; + u32 local_port_id[LLDP_PORT_ID_STAT_LEN]; +}; + +struct lldp_status_params_s { + u32 prefix_seq_num; + u32 status; /* TBD */ + + /* Holds remote Chassis ID TLV header, subtype and 9B of payload. */ + u32 peer_chassis_id[LLDP_CHASSIS_ID_STAT_LEN]; + + /* Holds remote Port ID TLV header, subtype and 9B of payload. */ + u32 peer_port_id[LLDP_PORT_ID_STAT_LEN]; + u32 suffix_seq_num; +}; + +struct dcbx_ets_feature { + u32 flags; +#define DCBX_ETS_ENABLED_MASK 0x00000001 +#define DCBX_ETS_ENABLED_SHIFT 0 +#define DCBX_ETS_WILLING_MASK 0x00000002 +#define DCBX_ETS_WILLING_SHIFT 1 +#define DCBX_ETS_ERROR_MASK 0x00000004 +#define DCBX_ETS_ERROR_SHIFT 2 +#define DCBX_ETS_CBS_MASK 0x00000008 +#define DCBX_ETS_CBS_SHIFT 3 +#define DCBX_ETS_MAX_TCS_MASK 0x000000f0 +#define DCBX_ETS_MAX_TCS_SHIFT 4 + u32 pri_tc_tbl[1]; +#define DCBX_ISCSI_OOO_TC 4 +#define NIG_ETS_ISCSI_OOO_CLIENT_OFFSET (DCBX_ISCSI_OOO_TC + 1) + u32 tc_bw_tbl[2]; + u32 tc_tsa_tbl[2]; +#define DCBX_ETS_TSA_STRICT 0 +#define DCBX_ETS_TSA_CBS 1 +#define DCBX_ETS_TSA_ETS 2 +}; + +struct dcbx_app_priority_entry { + u32 entry; +#define DCBX_APP_PRI_MAP_MASK 0x000000ff +#define DCBX_APP_PRI_MAP_SHIFT 0 +#define DCBX_APP_PRI_0 0x01 +#define DCBX_APP_PRI_1 0x02 +#define DCBX_APP_PRI_2 0x04 +#define DCBX_APP_PRI_3 0x08 +#define DCBX_APP_PRI_4 0x10 +#define DCBX_APP_PRI_5 0x20 +#define DCBX_APP_PRI_6 0x40 +#define DCBX_APP_PRI_7 0x80 +#define DCBX_APP_SF_MASK 0x00000300 +#define DCBX_APP_SF_SHIFT 8 +#define DCBX_APP_SF_ETHTYPE 0 +#define DCBX_APP_SF_PORT 1 +#define DCBX_APP_PROTOCOL_ID_MASK 0xffff0000 +#define DCBX_APP_PROTOCOL_ID_SHIFT 16 +}; + +/* FW structure in BE */ +struct dcbx_app_priority_feature { + u32 flags; +#define DCBX_APP_ENABLED_MASK 0x00000001 +#define DCBX_APP_ENABLED_SHIFT 0 +#define DCBX_APP_WILLING_MASK 0x00000002 +#define DCBX_APP_WILLING_SHIFT 1 +#define DCBX_APP_ERROR_MASK 0x00000004 +#define DCBX_APP_ERROR_SHIFT 2 +/* Not in use + * #define DCBX_APP_DEFAULT_PRI_MASK 0x00000f00 + * #define DCBX_APP_DEFAULT_PRI_SHIFT 8 + */ +#define DCBX_APP_MAX_TCS_MASK 0x0000f000 +#define DCBX_APP_MAX_TCS_SHIFT 12 +#define DCBX_APP_NUM_ENTRIES_MASK 0x00ff0000 +#define DCBX_APP_NUM_ENTRIES_SHIFT 16 + struct dcbx_app_priority_entry app_pri_tbl[DCBX_MAX_APP_PROTOCOL]; +}; + +/* FW structure in BE */ +struct dcbx_features { + /* PG feature */ + struct dcbx_ets_feature ets; + + /* PFC feature */ + u32 pfc; +#define DCBX_PFC_PRI_EN_BITMAP_MASK 0x000000ff +#define DCBX_PFC_PRI_EN_BITMAP_SHIFT 0 +#define DCBX_PFC_PRI_EN_BITMAP_PRI_0 0x01 +#define DCBX_PFC_PRI_EN_BITMAP_PRI_1 0x02 +#define DCBX_PFC_PRI_EN_BITMAP_PRI_2 0x04 +#define DCBX_PFC_PRI_EN_BITMAP_PRI_3 0x08 +#define DCBX_PFC_PRI_EN_BITMAP_PRI_4 0x10 +#define DCBX_PFC_PRI_EN_BITMAP_PRI_5 0x20 +#define DCBX_PFC_PRI_EN_BITMAP_PRI_6 0x40 +#define DCBX_PFC_PRI_EN_BITMAP_PRI_7 0x80 + +#define DCBX_PFC_FLAGS_MASK 0x0000ff00 +#define DCBX_PFC_FLAGS_SHIFT 8 +#define DCBX_PFC_CAPS_MASK 0x00000f00 +#define DCBX_PFC_CAPS_SHIFT 8 +#define DCBX_PFC_MBC_MASK 0x00004000 +#define DCBX_PFC_MBC_SHIFT 14 +#define DCBX_PFC_WILLING_MASK 0x00008000 +#define DCBX_PFC_WILLING_SHIFT 15 +#define DCBX_PFC_ENABLED_MASK 0x00010000 +#define DCBX_PFC_ENABLED_SHIFT 16 +#define DCBX_PFC_ERROR_MASK 0x00020000 +#define DCBX_PFC_ERROR_SHIFT 17 + + /* APP feature */ + struct dcbx_app_priority_feature app; +}; + +struct dcbx_local_params { + u32 config; +#define DCBX_CONFIG_VERSION_MASK 0x00000003 +#define DCBX_CONFIG_VERSION_SHIFT 0 +#define DCBX_CONFIG_VERSION_DISABLED 0 +#define DCBX_CONFIG_VERSION_IEEE 1 +#define DCBX_CONFIG_VERSION_CEE 2 + + u32 flags; + struct dcbx_features features; +}; + +struct dcbx_mib { + u32 prefix_seq_num; + u32 flags; + struct dcbx_features features; + u32 suffix_seq_num; +}; + +struct lldp_system_tlvs_buffer_s { + u16 valid; + u16 length; + u32 data[MAX_SYSTEM_LLDP_TLV_DATA]; +}; + +/**************************************/ +/* */ +/* P U B L I C G L O B A L */ +/* */ +/**************************************/ +struct public_global { + u32 max_path; +#define MAX_PATH_BIG_BEAR 2 +#define MAX_PATH_K2 1 + u32 max_ports; +#define MODE_1P 1 +#define MODE_2P 2 +#define MODE_3P 3 +#define MODE_4P 4 + u32 debug_mb_offset; + u32 phymod_dbg_mb_offset; + struct couple_mode_teaming cmt; + s32 internal_temperature; + u32 mfw_ver; + u32 running_bundle_id; +}; + +/**************************************/ +/* */ +/* P U B L I C P A T H */ +/* */ +/**************************************/ + +/**************************************************************************** +* Shared Memory 2 Region * +****************************************************************************/ +/* The fw_flr_ack is actually built in the following way: */ +/* 8 bit: PF ack */ +/* 128 bit: VF ack */ +/* 8 bit: ios_dis_ack */ +/* In order to maintain endianity in the mailbox hsi, we want to keep using */ +/* u32. The fw must have the VF right after the PF since this is how it */ +/* access arrays(it expects always the VF to reside after the PF, and that */ +/* makes the calculation much easier for it. ) */ +/* In order to answer both limitations, and keep the struct small, the code */ +/* will abuse the structure defined here to achieve the actual partition */ +/* above */ +/****************************************************************************/ +struct fw_flr_mb { + u32 aggint; + u32 opgen_addr; + u32 accum_ack; /* 0..15:PF, 16..207:VF, 256..271:IOV_DIS */ +#define ACCUM_ACK_PF_BASE 0 +#define ACCUM_ACK_PF_SHIFT 0 + +#define ACCUM_ACK_VF_BASE 8 +#define ACCUM_ACK_VF_SHIFT 3 + +#define ACCUM_ACK_IOV_DIS_BASE 256 +#define ACCUM_ACK_IOV_DIS_SHIFT 8 +}; + +struct public_path { + struct fw_flr_mb flr_mb; + u32 mcp_vf_disabled[VF_MAX_STATIC / 32]; + + u32 process_kill; +#define PROCESS_KILL_COUNTER_MASK 0x0000ffff +#define PROCESS_KILL_COUNTER_SHIFT 0 +#define PROCESS_KILL_GLOB_AEU_BIT_MASK 0xffff0000 +#define PROCESS_KILL_GLOB_AEU_BIT_SHIFT 16 +#define GLOBAL_AEU_BIT(aeu_reg_id, aeu_bit) (aeu_reg_id * 32 + aeu_bit) +}; + +/**************************************/ +/* */ +/* P U B L I C P O R T */ +/* */ +/**************************************/ + +/**************************************************************************** +* Driver <-> FW Mailbox * +****************************************************************************/ + +struct public_port { + u32 validity_map; /* 0x0 (4*2 = 0x8) */ + + /* validity bits */ +#define MCP_VALIDITY_PCI_CFG 0x00100000 +#define MCP_VALIDITY_MB 0x00200000 +#define MCP_VALIDITY_DEV_INFO 0x00400000 +#define MCP_VALIDITY_RESERVED 0x00000007 + + /* One licensing bit should be set */ +#define MCP_VALIDITY_LIC_KEY_IN_EFFECT_MASK 0x00000038 +#define MCP_VALIDITY_LIC_MANUF_KEY_IN_EFFECT 0x00000008 +#define MCP_VALIDITY_LIC_UPGRADE_KEY_IN_EFFECT 0x00000010 +#define MCP_VALIDITY_LIC_NO_KEY_IN_EFFECT 0x00000020 + + /* Active MFW */ +#define MCP_VALIDITY_ACTIVE_MFW_UNKNOWN 0x00000000 +#define MCP_VALIDITY_ACTIVE_MFW_MASK 0x000001c0 +#define MCP_VALIDITY_ACTIVE_MFW_NCSI 0x00000040 +#define MCP_VALIDITY_ACTIVE_MFW_NONE 0x000001c0 + + u32 link_status; +#define LINK_STATUS_LINK_UP \ + 0x00000001 +#define LINK_STATUS_SPEED_AND_DUPLEX_MASK 0x0000001e +#define LINK_STATUS_SPEED_AND_DUPLEX_1000THD BIT(1) +#define LINK_STATUS_SPEED_AND_DUPLEX_1000TFD (2 << 1) +#define LINK_STATUS_SPEED_AND_DUPLEX_10G (3 << 1) +#define LINK_STATUS_SPEED_AND_DUPLEX_20G (4 << 1) +#define LINK_STATUS_SPEED_AND_DUPLEX_40G (5 << 1) +#define LINK_STATUS_SPEED_AND_DUPLEX_50G (6 << 1) +#define LINK_STATUS_SPEED_AND_DUPLEX_100G (7 << 1) +#define LINK_STATUS_SPEED_AND_DUPLEX_25G (8 << 1) + +#define LINK_STATUS_AUTO_NEGOTIATE_ENABLED 0x00000020 + +#define LINK_STATUS_AUTO_NEGOTIATE_COMPLETE 0x00000040 +#define LINK_STATUS_PARALLEL_DETECTION_USED 0x00000080 + +#define LINK_STATUS_PFC_ENABLED \ + 0x00000100 +#define LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE 0x00000200 +#define LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE 0x00000400 +#define LINK_STATUS_LINK_PARTNER_10G_CAPABLE 0x00000800 +#define LINK_STATUS_LINK_PARTNER_20G_CAPABLE 0x00001000 +#define LINK_STATUS_LINK_PARTNER_40G_CAPABLE 0x00002000 +#define LINK_STATUS_LINK_PARTNER_50G_CAPABLE 0x00004000 +#define LINK_STATUS_LINK_PARTNER_100G_CAPABLE 0x00008000 +#define LINK_STATUS_LINK_PARTNER_25G_CAPABLE 0x00010000 + +#define LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK 0x000C0000 +#define LINK_STATUS_LINK_PARTNER_NOT_PAUSE_CAPABLE (0 << 18) +#define LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE BIT(18) +#define LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE (2 << 18) +#define LINK_STATUS_LINK_PARTNER_BOTH_PAUSE (3 << 18) + +#define LINK_STATUS_SFP_TX_FAULT \ + 0x00100000 +#define LINK_STATUS_TX_FLOW_CONTROL_ENABLED 0x00200000 +#define LINK_STATUS_RX_FLOW_CONTROL_ENABLED 0x00400000 + + u32 link_status1; + u32 ext_phy_fw_version; + u32 drv_phy_cfg_addr; + + u32 port_stx; + + u32 stat_nig_timer; + + struct port_mf_cfg port_mf_config; + struct port_stats stats; + + u32 media_type; +#define MEDIA_UNSPECIFIED 0x0 +#define MEDIA_SFPP_10G_FIBER 0x1 +#define MEDIA_XFP_FIBER 0x2 +#define MEDIA_DA_TWINAX 0x3 +#define MEDIA_BASE_T 0x4 +#define MEDIA_SFP_1G_FIBER 0x5 +#define MEDIA_KR 0xf0 +#define MEDIA_NOT_PRESENT 0xff + + u32 lfa_status; +#define LFA_LINK_FLAP_REASON_OFFSET 0 +#define LFA_LINK_FLAP_REASON_MASK 0x000000ff +#define LFA_NO_REASON (0 << 0) +#define LFA_LINK_DOWN BIT(0) +#define LFA_FORCE_INIT BIT(1) +#define LFA_LOOPBACK_MISMATCH BIT(2) +#define LFA_SPEED_MISMATCH BIT(3) +#define LFA_FLOW_CTRL_MISMATCH BIT(4) +#define LFA_ADV_SPEED_MISMATCH BIT(5) +#define LINK_FLAP_AVOIDANCE_COUNT_OFFSET 8 +#define LINK_FLAP_AVOIDANCE_COUNT_MASK 0x0000ff00 +#define LINK_FLAP_COUNT_OFFSET 16 +#define LINK_FLAP_COUNT_MASK 0x00ff0000 + + u32 link_change_count; + + /* LLDP params */ + struct lldp_config_params_s lldp_config_params[ + LLDP_MAX_LLDP_AGENTS]; + struct lldp_status_params_s lldp_status_params[ + LLDP_MAX_LLDP_AGENTS]; + struct lldp_system_tlvs_buffer_s system_lldp_tlvs_buf; + + /* DCBX related MIB */ + struct dcbx_local_params local_admin_dcbx_mib; + struct dcbx_mib remote_dcbx_mib; + struct dcbx_mib operational_dcbx_mib; +}; + +/**************************************/ +/* */ +/* P U B L I C F U N C */ +/* */ +/**************************************/ + +struct public_func { + u32 iscsi_boot_signature; + u32 iscsi_boot_block_offset; + + u32 reserved[8]; + + u32 config; + + /* E/R/I/D */ + /* function 0 of each port cannot be hidden */ +#define FUNC_MF_CFG_FUNC_HIDE 0x00000001 +#define FUNC_MF_CFG_PAUSE_ON_HOST_RING 0x00000002 +#define FUNC_MF_CFG_PAUSE_ON_HOST_RING_SHIFT 0x00000001 + +#define FUNC_MF_CFG_PROTOCOL_MASK 0x000000f0 +#define FUNC_MF_CFG_PROTOCOL_SHIFT 4 +#define FUNC_MF_CFG_PROTOCOL_ETHERNET 0x00000000 +#define FUNC_MF_CFG_PROTOCOL_ISCSI 0x00000010 +#define FUNC_MF_CFG_PROTOCOL_FCOE 0x00000020 +#define FUNC_MF_CFG_PROTOCOL_ROCE 0x00000030 +#define FUNC_MF_CFG_PROTOCOL_MAX 0x00000030 + + /* MINBW, MAXBW */ + /* value range - 0..100, increments in 1 % */ +#define FUNC_MF_CFG_MIN_BW_MASK 0x0000ff00 +#define FUNC_MF_CFG_MIN_BW_SHIFT 8 +#define FUNC_MF_CFG_MIN_BW_DEFAULT 0x00000000 +#define FUNC_MF_CFG_MAX_BW_MASK 0x00ff0000 +#define FUNC_MF_CFG_MAX_BW_SHIFT 16 +#define FUNC_MF_CFG_MAX_BW_DEFAULT 0x00640000 + + u32 status; +#define FUNC_STATUS_VLINK_DOWN 0x00000001 + + u32 mac_upper; /* MAC */ +#define FUNC_MF_CFG_UPPERMAC_MASK 0x0000ffff +#define FUNC_MF_CFG_UPPERMAC_SHIFT 0 +#define FUNC_MF_CFG_UPPERMAC_DEFAULT FUNC_MF_CFG_UPPERMAC_MASK + u32 mac_lower; +#define FUNC_MF_CFG_LOWERMAC_DEFAULT 0xffffffff + + u32 fcoe_wwn_port_name_upper; + u32 fcoe_wwn_port_name_lower; + + u32 fcoe_wwn_node_name_upper; + u32 fcoe_wwn_node_name_lower; + + u32 ovlan_stag; /* tags */ +#define FUNC_MF_CFG_OV_STAG_MASK 0x0000ffff +#define FUNC_MF_CFG_OV_STAG_SHIFT 0 +#define FUNC_MF_CFG_OV_STAG_DEFAULT FUNC_MF_CFG_OV_STAG_MASK + + u32 pf_allocation; /* vf per pf */ + + u32 preserve_data; /* Will be used bt CCM */ + + u32 driver_last_activity_ts; + + u32 drv_ack_vf_disabled[VF_MAX_STATIC / 32]; /* 0x0044 */ + + u32 drv_id; +#define DRV_ID_PDA_COMP_VER_MASK 0x0000ffff +#define DRV_ID_PDA_COMP_VER_SHIFT 0 + +#define DRV_ID_MCP_HSI_VER_MASK 0x00ff0000 +#define DRV_ID_MCP_HSI_VER_SHIFT 16 +#define DRV_ID_MCP_HSI_VER_CURRENT BIT(DRV_ID_MCP_HSI_VER_SHIFT) + +#define DRV_ID_DRV_TYPE_MASK 0xff000000 +#define DRV_ID_DRV_TYPE_SHIFT 24 +#define DRV_ID_DRV_TYPE_UNKNOWN (0 << DRV_ID_DRV_TYPE_SHIFT) +#define DRV_ID_DRV_TYPE_LINUX BIT(DRV_ID_DRV_TYPE_SHIFT) +#define DRV_ID_DRV_TYPE_WINDOWS (2 << DRV_ID_DRV_TYPE_SHIFT) +#define DRV_ID_DRV_TYPE_DIAG (3 << DRV_ID_DRV_TYPE_SHIFT) +#define DRV_ID_DRV_TYPE_PREBOOT (4 << DRV_ID_DRV_TYPE_SHIFT) +#define DRV_ID_DRV_TYPE_SOLARIS (5 << DRV_ID_DRV_TYPE_SHIFT) +#define DRV_ID_DRV_TYPE_VMWARE (6 << DRV_ID_DRV_TYPE_SHIFT) +#define DRV_ID_DRV_TYPE_FREEBSD (7 << DRV_ID_DRV_TYPE_SHIFT) +#define DRV_ID_DRV_TYPE_AIX (8 << DRV_ID_DRV_TYPE_SHIFT) +}; + +/**************************************/ +/* */ +/* P U B L I C M B */ +/* */ +/**************************************/ +/* This is the only section that the driver can write to, and each */ +/* Basically each driver request to set feature parameters, + * will be done using a different command, which will be linked + * to a specific data structure from the union below. + * For huge strucuture, the common blank structure should be used. + */ + +struct mcp_mac { + u32 mac_upper; /* Upper 16 bits are always zeroes */ + u32 mac_lower; +}; + +struct mcp_val64 { + u32 lo; + u32 hi; +}; + +struct mcp_file_att { + u32 nvm_start_addr; + u32 len; +}; + +#define MCP_DRV_VER_STR_SIZE 16 +#define MCP_DRV_VER_STR_SIZE_DWORD (MCP_DRV_VER_STR_SIZE / sizeof(u32)) +#define MCP_DRV_NVM_BUF_LEN 32 +struct drv_version_stc { + u32 version; + u8 name[MCP_DRV_VER_STR_SIZE - 4]; +}; + +union drv_union_data { + u32 ver_str[MCP_DRV_VER_STR_SIZE_DWORD]; + struct mcp_mac wol_mac; + + struct pmm_phy_cfg drv_phy_cfg; + + struct mcp_val64 val64; /* For PHY / AVS commands */ + + u8 raw_data[MCP_DRV_NVM_BUF_LEN]; + + struct mcp_file_att file_att; + + u32 ack_vf_disabled[VF_MAX_STATIC / 32]; + + struct drv_version_stc drv_version; +}; + +struct public_drv_mb { + u32 drv_mb_header; +#define DRV_MSG_CODE_MASK 0xffff0000 +#define DRV_MSG_CODE_LOAD_REQ 0x10000000 +#define DRV_MSG_CODE_LOAD_DONE 0x11000000 +#define DRV_MSG_CODE_UNLOAD_REQ 0x20000000 +#define DRV_MSG_CODE_UNLOAD_DONE 0x21000000 +#define DRV_MSG_CODE_INIT_PHY 0x22000000 + /* Params - FORCE - Reinitialize the link regardless of LFA */ + /* - DONT_CARE - Don't flap the link if up */ +#define DRV_MSG_CODE_LINK_RESET 0x23000000 + +#define DRV_MSG_CODE_SET_LLDP 0x24000000 +#define DRV_MSG_CODE_SET_DCBX 0x25000000 + +#define DRV_MSG_CODE_NIG_DRAIN 0x30000000 + +#define DRV_MSG_CODE_INITIATE_FLR 0x02000000 +#define DRV_MSG_CODE_VF_DISABLED_DONE 0xc0000000 +#define DRV_MSG_CODE_CFG_VF_MSIX 0xc0010000 +#define DRV_MSG_CODE_NVM_PUT_FILE_BEGIN 0x00010000 +#define DRV_MSG_CODE_NVM_PUT_FILE_DATA 0x00020000 +#define DRV_MSG_CODE_NVM_GET_FILE_ATT 0x00030000 +#define DRV_MSG_CODE_NVM_READ_NVRAM 0x00050000 +#define DRV_MSG_CODE_NVM_WRITE_NVRAM 0x00060000 +#define DRV_MSG_CODE_NVM_DEL_FILE 0x00080000 +#define DRV_MSG_CODE_MCP_RESET 0x00090000 +#define DRV_MSG_CODE_SET_SECURE_MODE 0x000a0000 +#define DRV_MSG_CODE_PHY_RAW_READ 0x000b0000 +#define DRV_MSG_CODE_PHY_RAW_WRITE 0x000c0000 +#define DRV_MSG_CODE_PHY_CORE_READ 0x000d0000 +#define DRV_MSG_CODE_PHY_CORE_WRITE 0x000e0000 +#define DRV_MSG_CODE_SET_VERSION 0x000f0000 + +#define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff + + u32 drv_mb_param; + + /* UNLOAD_REQ params */ +#define DRV_MB_PARAM_UNLOAD_WOL_UNKNOWN 0x00000000 +#define DRV_MB_PARAM_UNLOAD_WOL_MCP 0x00000001 +#define DRV_MB_PARAM_UNLOAD_WOL_DISABLED 0x00000002 +#define DRV_MB_PARAM_UNLOAD_WOL_ENABLED 0x00000003 + + /* UNLOAD_DONE_params */ +#define DRV_MB_PARAM_UNLOAD_NON_D3_POWER 0x00000001 + + /* INIT_PHY params */ +#define DRV_MB_PARAM_INIT_PHY_FORCE 0x00000001 +#define DRV_MB_PARAM_INIT_PHY_DONT_CARE 0x00000002 + + /* LLDP / DCBX params*/ +#define DRV_MB_PARAM_LLDP_SEND_MASK 0x00000001 +#define DRV_MB_PARAM_LLDP_SEND_SHIFT 0 +#define DRV_MB_PARAM_LLDP_AGENT_MASK 0x00000006 +#define DRV_MB_PARAM_LLDP_AGENT_SHIFT 1 +#define DRV_MB_PARAM_DCBX_NOTIFY_MASK 0x00000008 +#define DRV_MB_PARAM_DCBX_NOTIFY_SHIFT 3 + +#define DRV_MB_PARAM_NIG_DRAIN_PERIOD_MS_MASK 0x000000FF +#define DRV_MB_PARAM_NIG_DRAIN_PERIOD_MS_SHIFT 0 + +#define DRV_MB_PARAM_NVM_PUT_FILE_BEGIN_MFW 0x1 +#define DRV_MB_PARAM_NVM_PUT_FILE_BEGIN_IMAGE 0x2 + +#define DRV_MB_PARAM_NVM_OFFSET_SHIFT 0 +#define DRV_MB_PARAM_NVM_OFFSET_MASK 0x00FFFFFF +#define DRV_MB_PARAM_NVM_LEN_SHIFT 24 +#define DRV_MB_PARAM_NVM_LEN_MASK 0xFF000000 + +#define DRV_MB_PARAM_PHY_ADDR_SHIFT 0 +#define DRV_MB_PARAM_PHY_ADDR_MASK 0x1FF0FFFF +#define DRV_MB_PARAM_PHY_LANE_SHIFT 16 +#define DRV_MB_PARAM_PHY_LANE_MASK 0x000F0000 +#define DRV_MB_PARAM_PHY_SELECT_PORT_SHIFT 29 +#define DRV_MB_PARAM_PHY_SELECT_PORT_MASK 0x20000000 +#define DRV_MB_PARAM_PHY_PORT_SHIFT 30 +#define DRV_MB_PARAM_PHY_PORT_MASK 0xc0000000 + +/* configure vf MSIX params*/ +#define DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_SHIFT 0 +#define DRV_MB_PARAM_CFG_VF_MSIX_VF_ID_MASK 0x000000FF +#define DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_SHIFT 8 +#define DRV_MB_PARAM_CFG_VF_MSIX_SB_NUM_MASK 0x0000FF00 + + u32 fw_mb_header; +#define FW_MSG_CODE_MASK 0xffff0000 +#define FW_MSG_CODE_DRV_LOAD_ENGINE 0x10100000 +#define FW_MSG_CODE_DRV_LOAD_PORT 0x10110000 +#define FW_MSG_CODE_DRV_LOAD_FUNCTION 0x10120000 +#define FW_MSG_CODE_DRV_LOAD_REFUSED_PDA 0x10200000 +#define FW_MSG_CODE_DRV_LOAD_REFUSED_HSI 0x10210000 +#define FW_MSG_CODE_DRV_LOAD_REFUSED_DIAG 0x10220000 +#define FW_MSG_CODE_DRV_LOAD_DONE 0x11100000 +#define FW_MSG_CODE_DRV_UNLOAD_ENGINE 0x20110000 +#define FW_MSG_CODE_DRV_UNLOAD_PORT 0x20120000 +#define FW_MSG_CODE_DRV_UNLOAD_FUNCTION 0x20130000 +#define FW_MSG_CODE_DRV_UNLOAD_DONE 0x21100000 +#define FW_MSG_CODE_INIT_PHY_DONE 0x21200000 +#define FW_MSG_CODE_INIT_PHY_ERR_INVALID_ARGS 0x21300000 +#define FW_MSG_CODE_LINK_RESET_DONE 0x23000000 +#define FW_MSG_CODE_SET_LLDP_DONE 0x24000000 +#define FW_MSG_CODE_SET_LLDP_UNSUPPORTED_AGENT 0x24010000 +#define FW_MSG_CODE_SET_DCBX_DONE 0x25000000 +#define FW_MSG_CODE_NIG_DRAIN_DONE 0x30000000 +#define FW_MSG_CODE_VF_DISABLED_DONE 0xb0000000 +#define FW_MSG_CODE_DRV_CFG_VF_MSIX_DONE 0xb0010000 +#define FW_MSG_CODE_FLR_ACK 0x02000000 +#define FW_MSG_CODE_FLR_NACK 0x02100000 + +#define FW_MSG_CODE_NVM_OK 0x00010000 +#define FW_MSG_CODE_NVM_INVALID_MODE 0x00020000 +#define FW_MSG_CODE_NVM_PREV_CMD_WAS_NOT_FINISHED 0x00030000 +#define FW_MSG_CODE_NVM_FAILED_TO_ALLOCATE_PAGE 0x00040000 +#define FW_MSG_CODE_NVM_INVALID_DIR_FOUND 0x00050000 +#define FW_MSG_CODE_NVM_PAGE_NOT_FOUND 0x00060000 +#define FW_MSG_CODE_NVM_FAILED_PARSING_BNDLE_HEADER 0x00070000 +#define FW_MSG_CODE_NVM_FAILED_PARSING_IMAGE_HEADER 0x00080000 +#define FW_MSG_CODE_NVM_PARSING_OUT_OF_SYNC 0x00090000 +#define FW_MSG_CODE_NVM_FAILED_UPDATING_DIR 0x000a0000 +#define FW_MSG_CODE_NVM_FAILED_TO_FREE_PAGE 0x000b0000 +#define FW_MSG_CODE_NVM_FILE_NOT_FOUND 0x000c0000 +#define FW_MSG_CODE_NVM_OPERATION_FAILED 0x000d0000 +#define FW_MSG_CODE_NVM_FAILED_UNALIGNED 0x000e0000 +#define FW_MSG_CODE_NVM_BAD_OFFSET 0x000f0000 +#define FW_MSG_CODE_NVM_BAD_SIGNATURE 0x00100000 +#define FW_MSG_CODE_NVM_FILE_READ_ONLY 0x00200000 +#define FW_MSG_CODE_NVM_UNKNOWN_FILE 0x00300000 +#define FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK 0x00400000 +#define FW_MSG_CODE_MCP_RESET_REJECT 0x00600000 +#define FW_MSG_CODE_PHY_OK 0x00110000 +#define FW_MSG_CODE_PHY_ERROR 0x00120000 +#define FW_MSG_CODE_SET_SECURE_MODE_ERROR 0x00130000 +#define FW_MSG_CODE_SET_SECURE_MODE_OK 0x00140000 +#define FW_MSG_MODE_PHY_PRIVILEGE_ERROR 0x00150000 + +#define FW_MSG_SEQ_NUMBER_MASK 0x0000ffff + + u32 fw_mb_param; + + u32 drv_pulse_mb; +#define DRV_PULSE_SEQ_MASK 0x00007fff +#define DRV_PULSE_SYSTEM_TIME_MASK 0xffff0000 +#define DRV_PULSE_ALWAYS_ALIVE 0x00008000 + u32 mcp_pulse_mb; +#define MCP_PULSE_SEQ_MASK 0x00007fff +#define MCP_PULSE_ALWAYS_ALIVE 0x00008000 +#define MCP_EVENT_MASK 0xffff0000 +#define MCP_EVENT_OTHER_DRIVER_RESET_REQ 0x00010000 + + union drv_union_data union_data; +}; + +/* MFW - DRV MB */ +/********************************************************************** +* Description +* Incremental Aggregative +* 8-bit MFW counter per message +* 8-bit ack-counter per message +* Capabilities +* Provides up to 256 aggregative message per type +* Provides 4 message types in dword +* Message type pointers to byte offset +* Backward Compatibility by using sizeof for the counters. +* No lock requires for 32bit messages +* Limitations: +* In case of messages greater than 32bit, a dedicated mechanism(e.g lock) +* is required to prevent data corruption. +**********************************************************************/ +enum MFW_DRV_MSG_TYPE { + MFW_DRV_MSG_LINK_CHANGE, + MFW_DRV_MSG_FLR_FW_ACK_FAILED, + MFW_DRV_MSG_VF_DISABLED, + MFW_DRV_MSG_LLDP_DATA_UPDATED, + MFW_DRV_MSG_DCBX_REMOTE_MIB_UPDATED, + MFW_DRV_MSG_DCBX_OPERATIONAL_MIB_UPDATED, + MFW_DRV_MSG_ERROR_RECOVERY, + MFW_DRV_MSG_MAX +}; + +#define MFW_DRV_MSG_MAX_DWORDS(msgs) (((msgs - 1) >> 2) + 1) +#define MFW_DRV_MSG_DWORD(msg_id) (msg_id >> 2) +#define MFW_DRV_MSG_OFFSET(msg_id) ((msg_id & 0x3) << 3) +#define MFW_DRV_MSG_MASK(msg_id) (0xff << MFW_DRV_MSG_OFFSET(msg_id)) + +struct public_mfw_mb { + u32 sup_msgs; + u32 msg[MFW_DRV_MSG_MAX_DWORDS(MFW_DRV_MSG_MAX)]; + u32 ack[MFW_DRV_MSG_MAX_DWORDS(MFW_DRV_MSG_MAX)]; +}; + +/**************************************/ +/* */ +/* P U B L I C D A T A */ +/* */ +/**************************************/ +enum public_sections { + PUBLIC_DRV_MB, /* Points to the first drv_mb of path0 */ + PUBLIC_MFW_MB, /* Points to the first mfw_mb of path0 */ + PUBLIC_GLOBAL, + PUBLIC_PATH, + PUBLIC_PORT, + PUBLIC_FUNC, + PUBLIC_MAX_SECTIONS +}; + +struct drv_ver_info_stc { + u32 ver; + u8 name[32]; +}; + +struct mcp_public_data { + /* The sections fields is an array */ + u32 num_sections; + offsize_t sections[PUBLIC_MAX_SECTIONS]; + struct public_drv_mb drv_mb[MCP_GLOB_FUNC_MAX]; + struct public_mfw_mb mfw_mb[MCP_GLOB_FUNC_MAX]; + struct public_global global; + struct public_path path[MCP_GLOB_PATH_MAX]; + struct public_port port[MCP_GLOB_PORT_MAX]; + struct public_func func[MCP_GLOB_FUNC_MAX]; + struct drv_ver_info_stc drv_info; +}; + +struct nvm_cfg_mac_address { + u32 mac_addr_hi; +#define NVM_CFG_MAC_ADDRESS_HI_MASK 0x0000FFFF +#define NVM_CFG_MAC_ADDRESS_HI_OFFSET 0 + + u32 mac_addr_lo; +}; + +/****************************************** +* nvm_cfg1 structs +******************************************/ + +struct nvm_cfg1_glob { + u32 generic_cont0; /* 0x0 */ +#define NVM_CFG1_GLOB_BOARD_SWAP_MASK 0x0000000F +#define NVM_CFG1_GLOB_BOARD_SWAP_OFFSET 0 +#define NVM_CFG1_GLOB_BOARD_SWAP_NONE 0x0 +#define NVM_CFG1_GLOB_BOARD_SWAP_PATH 0x1 +#define NVM_CFG1_GLOB_BOARD_SWAP_PORT 0x2 +#define NVM_CFG1_GLOB_BOARD_SWAP_BOTH 0x3 +#define NVM_CFG1_GLOB_MF_MODE_MASK 0x00000FF0 +#define NVM_CFG1_GLOB_MF_MODE_OFFSET 4 +#define NVM_CFG1_GLOB_MF_MODE_MF_ALLOWED 0x0 +#define NVM_CFG1_GLOB_MF_MODE_FORCED_SF 0x1 +#define NVM_CFG1_GLOB_MF_MODE_SPIO4 0x2 +#define NVM_CFG1_GLOB_MF_MODE_NPAR1_0 0x3 +#define NVM_CFG1_GLOB_MF_MODE_NPAR1_5 0x4 +#define NVM_CFG1_GLOB_MF_MODE_NPAR2_0 0x5 +#define NVM_CFG1_GLOB_MF_MODE_BD 0x6 +#define NVM_CFG1_GLOB_MF_MODE_UFP 0x7 +#define NVM_CFG1_GLOB_FAN_FAILURE_ENFORCEMENT_MASK 0x00001000 +#define NVM_CFG1_GLOB_FAN_FAILURE_ENFORCEMENT_OFFSET 12 +#define NVM_CFG1_GLOB_FAN_FAILURE_ENFORCEMENT_DISABLED 0x0 +#define NVM_CFG1_GLOB_FAN_FAILURE_ENFORCEMENT_ENABLED 0x1 +#define NVM_CFG1_GLOB_AVS_MARGIN_LOW_MASK 0x001FE000 +#define NVM_CFG1_GLOB_AVS_MARGIN_LOW_OFFSET 13 +#define NVM_CFG1_GLOB_AVS_MARGIN_HIGH_MASK 0x1FE00000 +#define NVM_CFG1_GLOB_AVS_MARGIN_HIGH_OFFSET 21 +#define NVM_CFG1_GLOB_ENABLE_SRIOV_MASK 0x20000000 +#define NVM_CFG1_GLOB_ENABLE_SRIOV_OFFSET 29 +#define NVM_CFG1_GLOB_ENABLE_SRIOV_DISABLED 0x0 +#define NVM_CFG1_GLOB_ENABLE_SRIOV_ENABLED 0x1 +#define NVM_CFG1_GLOB_ENABLE_ATC_MASK 0x40000000 +#define NVM_CFG1_GLOB_ENABLE_ATC_OFFSET 30 +#define NVM_CFG1_GLOB_ENABLE_ATC_DISABLED 0x0 +#define NVM_CFG1_GLOB_ENABLE_ATC_ENABLED 0x1 +#define NVM_CFG1_GLOB_CLOCK_SLOWDOWN_MASK 0x80000000 +#define NVM_CFG1_GLOB_CLOCK_SLOWDOWN_OFFSET 31 +#define NVM_CFG1_GLOB_CLOCK_SLOWDOWN_DISABLED 0x0 +#define NVM_CFG1_GLOB_CLOCK_SLOWDOWN_ENABLED 0x1 + + u32 engineering_change[3]; /* 0x4 */ + + u32 manufacturing_id; /* 0x10 */ + + u32 serial_number[4]; /* 0x14 */ + + u32 pcie_cfg; /* 0x24 */ +#define NVM_CFG1_GLOB_PCI_GEN_MASK 0x00000003 +#define NVM_CFG1_GLOB_PCI_GEN_OFFSET 0 +#define NVM_CFG1_GLOB_PCI_GEN_PCI_GEN1 0x0 +#define NVM_CFG1_GLOB_PCI_GEN_PCI_GEN2 0x1 +#define NVM_CFG1_GLOB_PCI_GEN_PCI_GEN3 0x2 +#define NVM_CFG1_GLOB_BEACON_WOL_ENABLED_MASK 0x00000004 +#define NVM_CFG1_GLOB_BEACON_WOL_ENABLED_OFFSET 2 +#define NVM_CFG1_GLOB_BEACON_WOL_ENABLED_DISABLED 0x0 +#define NVM_CFG1_GLOB_BEACON_WOL_ENABLED_ENABLED 0x1 +#define NVM_CFG1_GLOB_ASPM_SUPPORT_MASK 0x00000018 +#define NVM_CFG1_GLOB_ASPM_SUPPORT_OFFSET 3 +#define NVM_CFG1_GLOB_ASPM_SUPPORT_L0S_L1_ENABLED 0x0 +#define NVM_CFG1_GLOB_ASPM_SUPPORT_L0S_DISABLED 0x1 +#define NVM_CFG1_GLOB_ASPM_SUPPORT_L1_DISABLED 0x2 +#define NVM_CFG1_GLOB_ASPM_SUPPORT_L0S_L1_DISABLED 0x3 +#define NVM_CFG1_GLOB_PREVENT_PCIE_L1_MENTRY_MASK 0x00000020 +#define NVM_CFG1_GLOB_PREVENT_PCIE_L1_MENTRY_OFFSET 5 +#define NVM_CFG1_GLOB_PREVENT_PCIE_L1_MENTRY_DISABLED 0x0 +#define NVM_CFG1_GLOB_PREVENT_PCIE_L1_MENTRY_ENABLED 0x1 +#define NVM_CFG1_GLOB_PCIE_G2_TX_AMPLITUDE_MASK 0x000003C0 +#define NVM_CFG1_GLOB_PCIE_G2_TX_AMPLITUDE_OFFSET 6 +#define NVM_CFG1_GLOB_PCIE_PREEMPHASIS_MASK 0x00001C00 +#define NVM_CFG1_GLOB_PCIE_PREEMPHASIS_OFFSET 10 +#define NVM_CFG1_GLOB_PCIE_PREEMPHASIS_HW 0x0 +#define NVM_CFG1_GLOB_PCIE_PREEMPHASIS_0DB 0x1 +#define NVM_CFG1_GLOB_PCIE_PREEMPHASIS_3_5DB 0x2 +#define NVM_CFG1_GLOB_PCIE_PREEMPHASIS_6_0DB 0x3 +#define NVM_CFG1_GLOB_WWN_NODE_PREFIX0_MASK 0x001FE000 +#define NVM_CFG1_GLOB_WWN_NODE_PREFIX0_OFFSET 13 +#define NVM_CFG1_GLOB_WWN_NODE_PREFIX1_MASK 0x1FE00000 +#define NVM_CFG1_GLOB_WWN_NODE_PREFIX1_OFFSET 21 +#define NVM_CFG1_GLOB_NCSI_PACKAGE_ID_MASK 0x60000000 +#define NVM_CFG1_GLOB_NCSI_PACKAGE_ID_OFFSET 29 + + u32 mgmt_traffic; /* 0x28 */ +#define NVM_CFG1_GLOB_RESERVED60_MASK 0x00000001 +#define NVM_CFG1_GLOB_RESERVED60_OFFSET 0 +#define NVM_CFG1_GLOB_RESERVED60_100KHZ 0x0 +#define NVM_CFG1_GLOB_RESERVED60_400KHZ 0x1 +#define NVM_CFG1_GLOB_WWN_PORT_PREFIX0_MASK 0x000001FE +#define NVM_CFG1_GLOB_WWN_PORT_PREFIX0_OFFSET 1 +#define NVM_CFG1_GLOB_WWN_PORT_PREFIX1_MASK 0x0001FE00 +#define NVM_CFG1_GLOB_WWN_PORT_PREFIX1_OFFSET 9 +#define NVM_CFG1_GLOB_SMBUS_ADDRESS_MASK 0x01FE0000 +#define NVM_CFG1_GLOB_SMBUS_ADDRESS_OFFSET 17 +#define NVM_CFG1_GLOB_SIDEBAND_MODE_MASK 0x06000000 +#define NVM_CFG1_GLOB_SIDEBAND_MODE_OFFSET 25 +#define NVM_CFG1_GLOB_SIDEBAND_MODE_DISABLED 0x0 +#define NVM_CFG1_GLOB_SIDEBAND_MODE_RMII 0x1 +#define NVM_CFG1_GLOB_SIDEBAND_MODE_SGMII 0x2 + + u32 core_cfg; /* 0x2C */ +#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_MASK 0x000000FF +#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_OFFSET 0 +#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X40G 0x0 +#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X50G 0x1 +#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X100G 0x2 +#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X10G_F 0x3 +#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X10G_E 0x4 +#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X20G 0x5 +#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X40G 0xB +#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X25G 0xC +#define NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X25G 0xD +#define NVM_CFG1_GLOB_EAGLE_ENFORCE_TX_FIR_CFG_MASK 0x00000100 +#define NVM_CFG1_GLOB_EAGLE_ENFORCE_TX_FIR_CFG_OFFSET 8 +#define NVM_CFG1_GLOB_EAGLE_ENFORCE_TX_FIR_CFG_DISABLED 0x0 +#define NVM_CFG1_GLOB_EAGLE_ENFORCE_TX_FIR_CFG_ENABLED 0x1 +#define NVM_CFG1_GLOB_FALCON_ENFORCE_TX_FIR_CFG_MASK 0x00000200 +#define NVM_CFG1_GLOB_FALCON_ENFORCE_TX_FIR_CFG_OFFSET 9 +#define NVM_CFG1_GLOB_FALCON_ENFORCE_TX_FIR_CFG_DISABLED 0x0 +#define NVM_CFG1_GLOB_FALCON_ENFORCE_TX_FIR_CFG_ENABLED 0x1 +#define NVM_CFG1_GLOB_EAGLE_CORE_ADDR_MASK 0x0003FC00 +#define NVM_CFG1_GLOB_EAGLE_CORE_ADDR_OFFSET 10 +#define NVM_CFG1_GLOB_FALCON_CORE_ADDR_MASK 0x03FC0000 +#define NVM_CFG1_GLOB_FALCON_CORE_ADDR_OFFSET 18 +#define NVM_CFG1_GLOB_AVS_MODE_MASK 0x1C000000 +#define NVM_CFG1_GLOB_AVS_MODE_OFFSET 26 +#define NVM_CFG1_GLOB_AVS_MODE_CLOSE_LOOP 0x0 +#define NVM_CFG1_GLOB_AVS_MODE_OPEN_LOOP 0x1 +#define NVM_CFG1_GLOB_AVS_MODE_DISABLED 0x3 +#define NVM_CFG1_GLOB_OVERRIDE_SECURE_MODE_MASK 0x60000000 +#define NVM_CFG1_GLOB_OVERRIDE_SECURE_MODE_OFFSET 29 +#define NVM_CFG1_GLOB_OVERRIDE_SECURE_MODE_DISABLED 0x0 +#define NVM_CFG1_GLOB_OVERRIDE_SECURE_MODE_ENABLED 0x1 + + u32 e_lane_cfg1; /* 0x30 */ +#define NVM_CFG1_GLOB_RX_LANE0_SWAP_MASK 0x0000000F +#define NVM_CFG1_GLOB_RX_LANE0_SWAP_OFFSET 0 +#define NVM_CFG1_GLOB_RX_LANE1_SWAP_MASK 0x000000F0 +#define NVM_CFG1_GLOB_RX_LANE1_SWAP_OFFSET 4 +#define NVM_CFG1_GLOB_RX_LANE2_SWAP_MASK 0x00000F00 +#define NVM_CFG1_GLOB_RX_LANE2_SWAP_OFFSET 8 +#define NVM_CFG1_GLOB_RX_LANE3_SWAP_MASK 0x0000F000 +#define NVM_CFG1_GLOB_RX_LANE3_SWAP_OFFSET 12 +#define NVM_CFG1_GLOB_TX_LANE0_SWAP_MASK 0x000F0000 +#define NVM_CFG1_GLOB_TX_LANE0_SWAP_OFFSET 16 +#define NVM_CFG1_GLOB_TX_LANE1_SWAP_MASK 0x00F00000 +#define NVM_CFG1_GLOB_TX_LANE1_SWAP_OFFSET 20 +#define NVM_CFG1_GLOB_TX_LANE2_SWAP_MASK 0x0F000000 +#define NVM_CFG1_GLOB_TX_LANE2_SWAP_OFFSET 24 +#define NVM_CFG1_GLOB_TX_LANE3_SWAP_MASK 0xF0000000 +#define NVM_CFG1_GLOB_TX_LANE3_SWAP_OFFSET 28 + + u32 e_lane_cfg2; /* 0x34 */ +#define NVM_CFG1_GLOB_RX_LANE0_POL_FLIP_MASK 0x00000001 +#define NVM_CFG1_GLOB_RX_LANE0_POL_FLIP_OFFSET 0 +#define NVM_CFG1_GLOB_RX_LANE1_POL_FLIP_MASK 0x00000002 +#define NVM_CFG1_GLOB_RX_LANE1_POL_FLIP_OFFSET 1 +#define NVM_CFG1_GLOB_RX_LANE2_POL_FLIP_MASK 0x00000004 +#define NVM_CFG1_GLOB_RX_LANE2_POL_FLIP_OFFSET 2 +#define NVM_CFG1_GLOB_RX_LANE3_POL_FLIP_MASK 0x00000008 +#define NVM_CFG1_GLOB_RX_LANE3_POL_FLIP_OFFSET 3 +#define NVM_CFG1_GLOB_TX_LANE0_POL_FLIP_MASK 0x00000010 +#define NVM_CFG1_GLOB_TX_LANE0_POL_FLIP_OFFSET 4 +#define NVM_CFG1_GLOB_TX_LANE1_POL_FLIP_MASK 0x00000020 +#define NVM_CFG1_GLOB_TX_LANE1_POL_FLIP_OFFSET 5 +#define NVM_CFG1_GLOB_TX_LANE2_POL_FLIP_MASK 0x00000040 +#define NVM_CFG1_GLOB_TX_LANE2_POL_FLIP_OFFSET 6 +#define NVM_CFG1_GLOB_TX_LANE3_POL_FLIP_MASK 0x00000080 +#define NVM_CFG1_GLOB_TX_LANE3_POL_FLIP_OFFSET 7 +#define NVM_CFG1_GLOB_SMBUS_MODE_MASK 0x00000F00 +#define NVM_CFG1_GLOB_SMBUS_MODE_OFFSET 8 +#define NVM_CFG1_GLOB_SMBUS_MODE_DISABLED 0x0 +#define NVM_CFG1_GLOB_SMBUS_MODE_100KHZ 0x1 +#define NVM_CFG1_GLOB_SMBUS_MODE_400KHZ 0x2 +#define NVM_CFG1_GLOB_NCSI_MASK 0x0000F000 +#define NVM_CFG1_GLOB_NCSI_OFFSET 12 +#define NVM_CFG1_GLOB_NCSI_DISABLED 0x0 +#define NVM_CFG1_GLOB_NCSI_ENABLED 0x1 + + u32 f_lane_cfg1; /* 0x38 */ +#define NVM_CFG1_GLOB_RX_LANE0_SWAP_MASK 0x0000000F +#define NVM_CFG1_GLOB_RX_LANE0_SWAP_OFFSET 0 +#define NVM_CFG1_GLOB_RX_LANE1_SWAP_MASK 0x000000F0 +#define NVM_CFG1_GLOB_RX_LANE1_SWAP_OFFSET 4 +#define NVM_CFG1_GLOB_RX_LANE2_SWAP_MASK 0x00000F00 +#define NVM_CFG1_GLOB_RX_LANE2_SWAP_OFFSET 8 +#define NVM_CFG1_GLOB_RX_LANE3_SWAP_MASK 0x0000F000 +#define NVM_CFG1_GLOB_RX_LANE3_SWAP_OFFSET 12 +#define NVM_CFG1_GLOB_TX_LANE0_SWAP_MASK 0x000F0000 +#define NVM_CFG1_GLOB_TX_LANE0_SWAP_OFFSET 16 +#define NVM_CFG1_GLOB_TX_LANE1_SWAP_MASK 0x00F00000 +#define NVM_CFG1_GLOB_TX_LANE1_SWAP_OFFSET 20 +#define NVM_CFG1_GLOB_TX_LANE2_SWAP_MASK 0x0F000000 +#define NVM_CFG1_GLOB_TX_LANE2_SWAP_OFFSET 24 +#define NVM_CFG1_GLOB_TX_LANE3_SWAP_MASK 0xF0000000 +#define NVM_CFG1_GLOB_TX_LANE3_SWAP_OFFSET 28 + + u32 f_lane_cfg2; /* 0x3C */ +#define NVM_CFG1_GLOB_RX_LANE0_POL_FLIP_MASK 0x00000001 +#define NVM_CFG1_GLOB_RX_LANE0_POL_FLIP_OFFSET 0 +#define NVM_CFG1_GLOB_RX_LANE1_POL_FLIP_MASK 0x00000002 +#define NVM_CFG1_GLOB_RX_LANE1_POL_FLIP_OFFSET 1 +#define NVM_CFG1_GLOB_RX_LANE2_POL_FLIP_MASK 0x00000004 +#define NVM_CFG1_GLOB_RX_LANE2_POL_FLIP_OFFSET 2 +#define NVM_CFG1_GLOB_RX_LANE3_POL_FLIP_MASK 0x00000008 +#define NVM_CFG1_GLOB_RX_LANE3_POL_FLIP_OFFSET 3 +#define NVM_CFG1_GLOB_TX_LANE0_POL_FLIP_MASK 0x00000010 +#define NVM_CFG1_GLOB_TX_LANE0_POL_FLIP_OFFSET 4 +#define NVM_CFG1_GLOB_TX_LANE1_POL_FLIP_MASK 0x00000020 +#define NVM_CFG1_GLOB_TX_LANE1_POL_FLIP_OFFSET 5 +#define NVM_CFG1_GLOB_TX_LANE2_POL_FLIP_MASK 0x00000040 +#define NVM_CFG1_GLOB_TX_LANE2_POL_FLIP_OFFSET 6 +#define NVM_CFG1_GLOB_TX_LANE3_POL_FLIP_MASK 0x00000080 +#define NVM_CFG1_GLOB_TX_LANE3_POL_FLIP_OFFSET 7 + + u32 eagle_preemphasis; /* 0x40 */ +#define NVM_CFG1_GLOB_LANE0_PREEMP_MASK 0x000000FF +#define NVM_CFG1_GLOB_LANE0_PREEMP_OFFSET 0 +#define NVM_CFG1_GLOB_LANE1_PREEMP_MASK 0x0000FF00 +#define NVM_CFG1_GLOB_LANE1_PREEMP_OFFSET 8 +#define NVM_CFG1_GLOB_LANE2_PREEMP_MASK 0x00FF0000 +#define NVM_CFG1_GLOB_LANE2_PREEMP_OFFSET 16 +#define NVM_CFG1_GLOB_LANE3_PREEMP_MASK 0xFF000000 +#define NVM_CFG1_GLOB_LANE3_PREEMP_OFFSET 24 + + u32 eagle_driver_current; /* 0x44 */ +#define NVM_CFG1_GLOB_LANE0_AMP_MASK 0x000000FF +#define NVM_CFG1_GLOB_LANE0_AMP_OFFSET 0 +#define NVM_CFG1_GLOB_LANE1_AMP_MASK 0x0000FF00 +#define NVM_CFG1_GLOB_LANE1_AMP_OFFSET 8 +#define NVM_CFG1_GLOB_LANE2_AMP_MASK 0x00FF0000 +#define NVM_CFG1_GLOB_LANE2_AMP_OFFSET 16 +#define NVM_CFG1_GLOB_LANE3_AMP_MASK 0xFF000000 +#define NVM_CFG1_GLOB_LANE3_AMP_OFFSET 24 + + u32 falcon_preemphasis; /* 0x48 */ +#define NVM_CFG1_GLOB_LANE0_PREEMP_MASK 0x000000FF +#define NVM_CFG1_GLOB_LANE0_PREEMP_OFFSET 0 +#define NVM_CFG1_GLOB_LANE1_PREEMP_MASK 0x0000FF00 +#define NVM_CFG1_GLOB_LANE1_PREEMP_OFFSET 8 +#define NVM_CFG1_GLOB_LANE2_PREEMP_MASK 0x00FF0000 +#define NVM_CFG1_GLOB_LANE2_PREEMP_OFFSET 16 +#define NVM_CFG1_GLOB_LANE3_PREEMP_MASK 0xFF000000 +#define NVM_CFG1_GLOB_LANE3_PREEMP_OFFSET 24 + + u32 falcon_driver_current; /* 0x4C */ +#define NVM_CFG1_GLOB_LANE0_AMP_MASK 0x000000FF +#define NVM_CFG1_GLOB_LANE0_AMP_OFFSET 0 +#define NVM_CFG1_GLOB_LANE1_AMP_MASK 0x0000FF00 +#define NVM_CFG1_GLOB_LANE1_AMP_OFFSET 8 +#define NVM_CFG1_GLOB_LANE2_AMP_MASK 0x00FF0000 +#define NVM_CFG1_GLOB_LANE2_AMP_OFFSET 16 +#define NVM_CFG1_GLOB_LANE3_AMP_MASK 0xFF000000 +#define NVM_CFG1_GLOB_LANE3_AMP_OFFSET 24 + + u32 pci_id; /* 0x50 */ +#define NVM_CFG1_GLOB_VENDOR_ID_MASK 0x0000FFFF +#define NVM_CFG1_GLOB_VENDOR_ID_OFFSET 0 + + u32 pci_subsys_id; /* 0x54 */ +#define NVM_CFG1_GLOB_SUBSYSTEM_VENDOR_ID_MASK 0x0000FFFF +#define NVM_CFG1_GLOB_SUBSYSTEM_VENDOR_ID_OFFSET 0 +#define NVM_CFG1_GLOB_SUBSYSTEM_DEVICE_ID_MASK 0xFFFF0000 +#define NVM_CFG1_GLOB_SUBSYSTEM_DEVICE_ID_OFFSET 16 + + u32 bar; /* 0x58 */ +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_MASK 0x0000000F +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_OFFSET 0 +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_DISABLED 0x0 +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_2K 0x1 +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_4K 0x2 +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_8K 0x3 +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_16K 0x4 +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_32K 0x5 +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_64K 0x6 +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_128K 0x7 +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_256K 0x8 +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_512K 0x9 +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_1M 0xA +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_2M 0xB +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_4M 0xC +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_8M 0xD +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_16M 0xE +#define NVM_CFG1_GLOB_EXPANSION_ROM_SIZE_32M 0xF +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_MASK 0x000000F0 +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_OFFSET 4 +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_DISABLED 0x0 +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_4K 0x1 +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_8K 0x2 +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_16K 0x3 +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_32K 0x4 +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_64K 0x5 +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_128K 0x6 +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_256K 0x7 +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_512K 0x8 +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_1M 0x9 +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_2M 0xA +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_4M 0xB +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_8M 0xC +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_16M 0xD +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_32M 0xE +#define NVM_CFG1_GLOB_VF_PCI_BAR2_SIZE_64M 0xF +#define NVM_CFG1_GLOB_BAR2_SIZE_MASK 0x00000F00 +#define NVM_CFG1_GLOB_BAR2_SIZE_OFFSET 8 +#define NVM_CFG1_GLOB_BAR2_SIZE_DISABLED 0x0 +#define NVM_CFG1_GLOB_BAR2_SIZE_64K 0x1 +#define NVM_CFG1_GLOB_BAR2_SIZE_128K 0x2 +#define NVM_CFG1_GLOB_BAR2_SIZE_256K 0x3 +#define NVM_CFG1_GLOB_BAR2_SIZE_512K 0x4 +#define NVM_CFG1_GLOB_BAR2_SIZE_1M 0x5 +#define NVM_CFG1_GLOB_BAR2_SIZE_2M 0x6 +#define NVM_CFG1_GLOB_BAR2_SIZE_4M 0x7 +#define NVM_CFG1_GLOB_BAR2_SIZE_8M 0x8 +#define NVM_CFG1_GLOB_BAR2_SIZE_16M 0x9 +#define NVM_CFG1_GLOB_BAR2_SIZE_32M 0xA +#define NVM_CFG1_GLOB_BAR2_SIZE_64M 0xB +#define NVM_CFG1_GLOB_BAR2_SIZE_128M 0xC +#define NVM_CFG1_GLOB_BAR2_SIZE_256M 0xD +#define NVM_CFG1_GLOB_BAR2_SIZE_512M 0xE +#define NVM_CFG1_GLOB_BAR2_SIZE_1G 0xF + + u32 eagle_txfir_main; /* 0x5C */ +#define NVM_CFG1_GLOB_LANE0_TXFIR_MAIN_MASK 0x000000FF +#define NVM_CFG1_GLOB_LANE0_TXFIR_MAIN_OFFSET 0 +#define NVM_CFG1_GLOB_LANE1_TXFIR_MAIN_MASK 0x0000FF00 +#define NVM_CFG1_GLOB_LANE1_TXFIR_MAIN_OFFSET 8 +#define NVM_CFG1_GLOB_LANE2_TXFIR_MAIN_MASK 0x00FF0000 +#define NVM_CFG1_GLOB_LANE2_TXFIR_MAIN_OFFSET 16 +#define NVM_CFG1_GLOB_LANE3_TXFIR_MAIN_MASK 0xFF000000 +#define NVM_CFG1_GLOB_LANE3_TXFIR_MAIN_OFFSET 24 + + u32 eagle_txfir_post; /* 0x60 */ +#define NVM_CFG1_GLOB_LANE0_TXFIR_POST_MASK 0x000000FF +#define NVM_CFG1_GLOB_LANE0_TXFIR_POST_OFFSET 0 +#define NVM_CFG1_GLOB_LANE1_TXFIR_POST_MASK 0x0000FF00 +#define NVM_CFG1_GLOB_LANE1_TXFIR_POST_OFFSET 8 +#define NVM_CFG1_GLOB_LANE2_TXFIR_POST_MASK 0x00FF0000 +#define NVM_CFG1_GLOB_LANE2_TXFIR_POST_OFFSET 16 +#define NVM_CFG1_GLOB_LANE3_TXFIR_POST_MASK 0xFF000000 +#define NVM_CFG1_GLOB_LANE3_TXFIR_POST_OFFSET 24 + + u32 falcon_txfir_main; /* 0x64 */ +#define NVM_CFG1_GLOB_LANE0_TXFIR_MAIN_MASK 0x000000FF +#define NVM_CFG1_GLOB_LANE0_TXFIR_MAIN_OFFSET 0 +#define NVM_CFG1_GLOB_LANE1_TXFIR_MAIN_MASK 0x0000FF00 +#define NVM_CFG1_GLOB_LANE1_TXFIR_MAIN_OFFSET 8 +#define NVM_CFG1_GLOB_LANE2_TXFIR_MAIN_MASK 0x00FF0000 +#define NVM_CFG1_GLOB_LANE2_TXFIR_MAIN_OFFSET 16 +#define NVM_CFG1_GLOB_LANE3_TXFIR_MAIN_MASK 0xFF000000 +#define NVM_CFG1_GLOB_LANE3_TXFIR_MAIN_OFFSET 24 + + u32 falcon_txfir_post; /* 0x68 */ +#define NVM_CFG1_GLOB_LANE0_TXFIR_POST_MASK 0x000000FF +#define NVM_CFG1_GLOB_LANE0_TXFIR_POST_OFFSET 0 +#define NVM_CFG1_GLOB_LANE1_TXFIR_POST_MASK 0x0000FF00 +#define NVM_CFG1_GLOB_LANE1_TXFIR_POST_OFFSET 8 +#define NVM_CFG1_GLOB_LANE2_TXFIR_POST_MASK 0x00FF0000 +#define NVM_CFG1_GLOB_LANE2_TXFIR_POST_OFFSET 16 +#define NVM_CFG1_GLOB_LANE3_TXFIR_POST_MASK 0xFF000000 +#define NVM_CFG1_GLOB_LANE3_TXFIR_POST_OFFSET 24 + + u32 manufacture_ver; /* 0x6C */ +#define NVM_CFG1_GLOB_MANUF0_VER_MASK 0x0000003F +#define NVM_CFG1_GLOB_MANUF0_VER_OFFSET 0 +#define NVM_CFG1_GLOB_MANUF1_VER_MASK 0x00000FC0 +#define NVM_CFG1_GLOB_MANUF1_VER_OFFSET 6 +#define NVM_CFG1_GLOB_MANUF2_VER_MASK 0x0003F000 +#define NVM_CFG1_GLOB_MANUF2_VER_OFFSET 12 +#define NVM_CFG1_GLOB_MANUF3_VER_MASK 0x00FC0000 +#define NVM_CFG1_GLOB_MANUF3_VER_OFFSET 18 +#define NVM_CFG1_GLOB_MANUF4_VER_MASK 0x3F000000 +#define NVM_CFG1_GLOB_MANUF4_VER_OFFSET 24 + + u32 manufacture_time; /* 0x70 */ +#define NVM_CFG1_GLOB_MANUF0_TIME_MASK 0x0000003F +#define NVM_CFG1_GLOB_MANUF0_TIME_OFFSET 0 +#define NVM_CFG1_GLOB_MANUF1_TIME_MASK 0x00000FC0 +#define NVM_CFG1_GLOB_MANUF1_TIME_OFFSET 6 +#define NVM_CFG1_GLOB_MANUF2_TIME_MASK 0x0003F000 +#define NVM_CFG1_GLOB_MANUF2_TIME_OFFSET 12 + + u32 led_global_settings; /* 0x74 */ +#define NVM_CFG1_GLOB_LED_SWAP_0_MASK 0x0000000F +#define NVM_CFG1_GLOB_LED_SWAP_0_OFFSET 0 +#define NVM_CFG1_GLOB_LED_SWAP_1_MASK 0x000000F0 +#define NVM_CFG1_GLOB_LED_SWAP_1_OFFSET 4 +#define NVM_CFG1_GLOB_LED_SWAP_2_MASK 0x00000F00 +#define NVM_CFG1_GLOB_LED_SWAP_2_OFFSET 8 +#define NVM_CFG1_GLOB_LED_SWAP_3_MASK 0x0000F000 +#define NVM_CFG1_GLOB_LED_SWAP_3_OFFSET 12 + + u32 generic_cont1; /* 0x78 */ +#define NVM_CFG1_GLOB_AVS_DAC_CODE_MASK 0x000003FF +#define NVM_CFG1_GLOB_AVS_DAC_CODE_OFFSET 0 + + u32 mbi_version; /* 0x7C */ +#define NVM_CFG1_GLOB_MBI_VERSION_0_MASK 0x000000FF +#define NVM_CFG1_GLOB_MBI_VERSION_0_OFFSET 0 +#define NVM_CFG1_GLOB_MBI_VERSION_1_MASK 0x0000FF00 +#define NVM_CFG1_GLOB_MBI_VERSION_1_OFFSET 8 +#define NVM_CFG1_GLOB_MBI_VERSION_2_MASK 0x00FF0000 +#define NVM_CFG1_GLOB_MBI_VERSION_2_OFFSET 16 + + u32 mbi_date; /* 0x80 */ + + u32 misc_sig; /* 0x84 */ + + /* Define the GPIO mapping to switch i2c mux */ +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO_0_MASK 0x000000FF +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO_0_OFFSET 0 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO_1_MASK 0x0000FF00 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO_1_OFFSET 8 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__NA 0x0 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO0 0x1 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO1 0x2 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO2 0x3 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO3 0x4 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO4 0x5 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO5 0x6 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO6 0x7 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO7 0x8 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO8 0x9 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO9 0xA +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO10 0xB +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO11 0xC +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO12 0xD +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO13 0xE +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO14 0xF +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO15 0x10 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO16 0x11 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO17 0x12 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO18 0x13 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO19 0x14 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO20 0x15 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO21 0x16 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO22 0x17 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO23 0x18 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO24 0x19 +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO25 0x1A +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO26 0x1B +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO27 0x1C +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO28 0x1D +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO29 0x1E +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO30 0x1F +#define NVM_CFG1_GLOB_I2C_MUX_SEL_GPIO__GPIO31 0x20 + + u32 reserved[46]; /* 0x88 */ +}; + +struct nvm_cfg1_path { + u32 reserved[30]; /* 0x0 */ +}; + +struct nvm_cfg1_port { + u32 power_dissipated; /* 0x0 */ +#define NVM_CFG1_PORT_POWER_DIS_D0_MASK 0x000000FF +#define NVM_CFG1_PORT_POWER_DIS_D0_OFFSET 0 +#define NVM_CFG1_PORT_POWER_DIS_D1_MASK 0x0000FF00 +#define NVM_CFG1_PORT_POWER_DIS_D1_OFFSET 8 +#define NVM_CFG1_PORT_POWER_DIS_D2_MASK 0x00FF0000 +#define NVM_CFG1_PORT_POWER_DIS_D2_OFFSET 16 +#define NVM_CFG1_PORT_POWER_DIS_D3_MASK 0xFF000000 +#define NVM_CFG1_PORT_POWER_DIS_D3_OFFSET 24 + + u32 power_consumed; /* 0x4 */ +#define NVM_CFG1_PORT_POWER_CONS_D0_MASK 0x000000FF +#define NVM_CFG1_PORT_POWER_CONS_D0_OFFSET 0 +#define NVM_CFG1_PORT_POWER_CONS_D1_MASK 0x0000FF00 +#define NVM_CFG1_PORT_POWER_CONS_D1_OFFSET 8 +#define NVM_CFG1_PORT_POWER_CONS_D2_MASK 0x00FF0000 +#define NVM_CFG1_PORT_POWER_CONS_D2_OFFSET 16 +#define NVM_CFG1_PORT_POWER_CONS_D3_MASK 0xFF000000 +#define NVM_CFG1_PORT_POWER_CONS_D3_OFFSET 24 + + u32 generic_cont0; /* 0x8 */ +#define NVM_CFG1_PORT_LED_MODE_MASK 0x000000FF +#define NVM_CFG1_PORT_LED_MODE_OFFSET 0 +#define NVM_CFG1_PORT_LED_MODE_MAC1 0x0 +#define NVM_CFG1_PORT_LED_MODE_PHY1 0x1 +#define NVM_CFG1_PORT_LED_MODE_PHY2 0x2 +#define NVM_CFG1_PORT_LED_MODE_PHY3 0x3 +#define NVM_CFG1_PORT_LED_MODE_MAC2 0x4 +#define NVM_CFG1_PORT_LED_MODE_PHY4 0x5 +#define NVM_CFG1_PORT_LED_MODE_PHY5 0x6 +#define NVM_CFG1_PORT_LED_MODE_PHY6 0x7 +#define NVM_CFG1_PORT_LED_MODE_MAC3 0x8 +#define NVM_CFG1_PORT_LED_MODE_PHY7 0x9 +#define NVM_CFG1_PORT_LED_MODE_PHY8 0xA +#define NVM_CFG1_PORT_LED_MODE_PHY9 0xB +#define NVM_CFG1_PORT_LED_MODE_MAC4 0xC +#define NVM_CFG1_PORT_LED_MODE_PHY10 0xD +#define NVM_CFG1_PORT_LED_MODE_PHY11 0xE +#define NVM_CFG1_PORT_LED_MODE_PHY12 0xF +#define NVM_CFG1_PORT_ROCE_PRIORITY_MASK 0x0000FF00 +#define NVM_CFG1_PORT_ROCE_PRIORITY_OFFSET 8 +#define NVM_CFG1_PORT_DCBX_MODE_MASK 0x000F0000 +#define NVM_CFG1_PORT_DCBX_MODE_OFFSET 16 +#define NVM_CFG1_PORT_DCBX_MODE_DISABLED 0x0 +#define NVM_CFG1_PORT_DCBX_MODE_IEEE 0x1 +#define NVM_CFG1_PORT_DCBX_MODE_CEE 0x2 +#define NVM_CFG1_PORT_DCBX_MODE_DYNAMIC 0x3 + + u32 pcie_cfg; /* 0xC */ +#define NVM_CFG1_PORT_RESERVED15_MASK 0x00000007 +#define NVM_CFG1_PORT_RESERVED15_OFFSET 0 + + u32 features; /* 0x10 */ +#define NVM_CFG1_PORT_ENABLE_WOL_ON_ACPI_PATTERN_MASK 0x00000001 +#define NVM_CFG1_PORT_ENABLE_WOL_ON_ACPI_PATTERN_OFFSET 0 +#define NVM_CFG1_PORT_ENABLE_WOL_ON_ACPI_PATTERN_DISABLED 0x0 +#define NVM_CFG1_PORT_ENABLE_WOL_ON_ACPI_PATTERN_ENABLED 0x1 +#define NVM_CFG1_PORT_MAGIC_PACKET_WOL_MASK 0x00000002 +#define NVM_CFG1_PORT_MAGIC_PACKET_WOL_OFFSET 1 +#define NVM_CFG1_PORT_MAGIC_PACKET_WOL_DISABLED 0x0 +#define NVM_CFG1_PORT_MAGIC_PACKET_WOL_ENABLED 0x1 + + u32 speed_cap_mask; /* 0x14 */ +#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_MASK 0x0000FFFF +#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_OFFSET 0 +#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G 0x1 +#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G 0x2 +#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_25G 0x8 +#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G 0x10 +#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G 0x20 +#define NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_100G 0x40 +#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_MASK 0xFFFF0000 +#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_OFFSET 16 +#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_1G 0x1 +#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_10G 0x2 +#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_25G 0x8 +#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_40G 0x10 +#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_50G 0x20 +#define NVM_CFG1_PORT_MFW_SPEED_CAPABILITY_MASK_100G 0x40 + + u32 link_settings; /* 0x18 */ +#define NVM_CFG1_PORT_DRV_LINK_SPEED_MASK 0x0000000F +#define NVM_CFG1_PORT_DRV_LINK_SPEED_OFFSET 0 +#define NVM_CFG1_PORT_DRV_LINK_SPEED_AUTONEG 0x0 +#define NVM_CFG1_PORT_DRV_LINK_SPEED_1G 0x1 +#define NVM_CFG1_PORT_DRV_LINK_SPEED_10G 0x2 +#define NVM_CFG1_PORT_DRV_LINK_SPEED_25G 0x4 +#define NVM_CFG1_PORT_DRV_LINK_SPEED_40G 0x5 +#define NVM_CFG1_PORT_DRV_LINK_SPEED_50G 0x6 +#define NVM_CFG1_PORT_DRV_LINK_SPEED_100G 0x7 +#define NVM_CFG1_PORT_DRV_FLOW_CONTROL_MASK 0x00000070 +#define NVM_CFG1_PORT_DRV_FLOW_CONTROL_OFFSET 4 +#define NVM_CFG1_PORT_DRV_FLOW_CONTROL_AUTONEG 0x1 +#define NVM_CFG1_PORT_DRV_FLOW_CONTROL_RX 0x2 +#define NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX 0x4 +#define NVM_CFG1_PORT_MFW_LINK_SPEED_MASK 0x00000780 +#define NVM_CFG1_PORT_MFW_LINK_SPEED_OFFSET 7 +#define NVM_CFG1_PORT_MFW_LINK_SPEED_AUTONEG 0x0 +#define NVM_CFG1_PORT_MFW_LINK_SPEED_1G 0x1 +#define NVM_CFG1_PORT_MFW_LINK_SPEED_10G 0x2 +#define NVM_CFG1_PORT_MFW_LINK_SPEED_25G 0x4 +#define NVM_CFG1_PORT_MFW_LINK_SPEED_40G 0x5 +#define NVM_CFG1_PORT_MFW_LINK_SPEED_50G 0x6 +#define NVM_CFG1_PORT_MFW_LINK_SPEED_100G 0x7 +#define NVM_CFG1_PORT_MFW_FLOW_CONTROL_MASK 0x00003800 +#define NVM_CFG1_PORT_MFW_FLOW_CONTROL_OFFSET 11 +#define NVM_CFG1_PORT_MFW_FLOW_CONTROL_AUTONEG 0x1 +#define NVM_CFG1_PORT_MFW_FLOW_CONTROL_RX 0x2 +#define NVM_CFG1_PORT_MFW_FLOW_CONTROL_TX 0x4 +#define NVM_CFG1_PORT_OPTIC_MODULE_VENDOR_ENFORCEMENT_MASK 0x00004000 +#define NVM_CFG1_PORT_OPTIC_MODULE_VENDOR_ENFORCEMENT_OFFSET 14 +#define NVM_CFG1_PORT_OPTIC_MODULE_VENDOR_ENFORCEMENT_DISABLED 0x0 +#define NVM_CFG1_PORT_OPTIC_MODULE_VENDOR_ENFORCEMENT_ENABLED 0x1 + + u32 phy_cfg; /* 0x1C */ +#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_MASK 0x0000FFFF +#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_OFFSET 0 +#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_HIGIG 0x1 +#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_SCRAMBLER 0x2 +#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_FIBER 0x4 +#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_DISABLE_CL72_AN 0x8 +#define NVM_CFG1_PORT_OPTIONAL_LINK_MODES_DISABLE_FEC_AN 0x10 +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_MASK 0x00FF0000 +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_OFFSET 16 +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_BYPASS 0x0 +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_KR 0x2 +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_KR2 0x3 +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_KR4 0x4 +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_XFI 0x8 +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_SFI 0x9 +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_1000X 0xB +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_SGMII 0xC +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_XLAUI 0xD +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_CAUI 0xE +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_XLPPI 0xF +#define NVM_CFG1_PORT_SERDES_NET_INTERFACE_CPPI 0x10 +#define NVM_CFG1_PORT_AN_MODE_MASK 0xFF000000 +#define NVM_CFG1_PORT_AN_MODE_OFFSET 24 +#define NVM_CFG1_PORT_AN_MODE_NONE 0x0 +#define NVM_CFG1_PORT_AN_MODE_CL73 0x1 +#define NVM_CFG1_PORT_AN_MODE_CL37 0x2 +#define NVM_CFG1_PORT_AN_MODE_CL73_BAM 0x3 +#define NVM_CFG1_PORT_AN_MODE_CL37_BAM 0x4 +#define NVM_CFG1_PORT_AN_MODE_HPAM 0x5 +#define NVM_CFG1_PORT_AN_MODE_SGMII 0x6 + + u32 mgmt_traffic; /* 0x20 */ +#define NVM_CFG1_PORT_RESERVED61_MASK 0x0000000F +#define NVM_CFG1_PORT_RESERVED61_OFFSET 0 +#define NVM_CFG1_PORT_RESERVED61_DISABLED 0x0 +#define NVM_CFG1_PORT_RESERVED61_NCSI_OVER_RMII 0x1 +#define NVM_CFG1_PORT_RESERVED61_NCSI_OVER_SMBUS 0x2 + + u32 ext_phy; /* 0x24 */ +#define NVM_CFG1_PORT_EXTERNAL_PHY_TYPE_MASK 0x000000FF +#define NVM_CFG1_PORT_EXTERNAL_PHY_TYPE_OFFSET 0 +#define NVM_CFG1_PORT_EXTERNAL_PHY_TYPE_NONE 0x0 +#define NVM_CFG1_PORT_EXTERNAL_PHY_TYPE_BCM84844 0x1 +#define NVM_CFG1_PORT_EXTERNAL_PHY_ADDRESS_MASK 0x0000FF00 +#define NVM_CFG1_PORT_EXTERNAL_PHY_ADDRESS_OFFSET 8 + + u32 mba_cfg1; /* 0x28 */ +#define NVM_CFG1_PORT_MBA_MASK 0x00000001 +#define NVM_CFG1_PORT_MBA_OFFSET 0 +#define NVM_CFG1_PORT_MBA_DISABLED 0x0 +#define NVM_CFG1_PORT_MBA_ENABLED 0x1 +#define NVM_CFG1_PORT_MBA_BOOT_TYPE_MASK 0x00000006 +#define NVM_CFG1_PORT_MBA_BOOT_TYPE_OFFSET 1 +#define NVM_CFG1_PORT_MBA_BOOT_TYPE_AUTO 0x0 +#define NVM_CFG1_PORT_MBA_BOOT_TYPE_BBS 0x1 +#define NVM_CFG1_PORT_MBA_BOOT_TYPE_INT18H 0x2 +#define NVM_CFG1_PORT_MBA_BOOT_TYPE_INT19H 0x3 +#define NVM_CFG1_PORT_MBA_DELAY_TIME_MASK 0x00000078 +#define NVM_CFG1_PORT_MBA_DELAY_TIME_OFFSET 3 +#define NVM_CFG1_PORT_MBA_SETUP_HOT_KEY_MASK 0x00000080 +#define NVM_CFG1_PORT_MBA_SETUP_HOT_KEY_OFFSET 7 +#define NVM_CFG1_PORT_MBA_SETUP_HOT_KEY_CTRL_S 0x0 +#define NVM_CFG1_PORT_MBA_SETUP_HOT_KEY_CTRL_B 0x1 +#define NVM_CFG1_PORT_MBA_HIDE_SETUP_PROMPT_MASK 0x00000100 +#define NVM_CFG1_PORT_MBA_HIDE_SETUP_PROMPT_OFFSET 8 +#define NVM_CFG1_PORT_MBA_HIDE_SETUP_PROMPT_DISABLED 0x0 +#define NVM_CFG1_PORT_MBA_HIDE_SETUP_PROMPT_ENABLED 0x1 +#define NVM_CFG1_PORT_RESERVED5_MASK 0x0001FE00 +#define NVM_CFG1_PORT_RESERVED5_OFFSET 9 +#define NVM_CFG1_PORT_RESERVED5_DISABLED 0x0 +#define NVM_CFG1_PORT_RESERVED5_2K 0x1 +#define NVM_CFG1_PORT_RESERVED5_4K 0x2 +#define NVM_CFG1_PORT_RESERVED5_8K 0x3 +#define NVM_CFG1_PORT_RESERVED5_16K 0x4 +#define NVM_CFG1_PORT_RESERVED5_32K 0x5 +#define NVM_CFG1_PORT_RESERVED5_64K 0x6 +#define NVM_CFG1_PORT_RESERVED5_128K 0x7 +#define NVM_CFG1_PORT_RESERVED5_256K 0x8 +#define NVM_CFG1_PORT_RESERVED5_512K 0x9 +#define NVM_CFG1_PORT_RESERVED5_1M 0xA +#define NVM_CFG1_PORT_RESERVED5_2M 0xB +#define NVM_CFG1_PORT_RESERVED5_4M 0xC +#define NVM_CFG1_PORT_RESERVED5_8M 0xD +#define NVM_CFG1_PORT_RESERVED5_16M 0xE +#define NVM_CFG1_PORT_RESERVED5_32M 0xF +#define NVM_CFG1_PORT_MBA_LINK_SPEED_MASK 0x001E0000 +#define NVM_CFG1_PORT_MBA_LINK_SPEED_OFFSET 17 +#define NVM_CFG1_PORT_MBA_LINK_SPEED_AUTONEG 0x0 +#define NVM_CFG1_PORT_MBA_LINK_SPEED_1G 0x1 +#define NVM_CFG1_PORT_MBA_LINK_SPEED_10G 0x2 +#define NVM_CFG1_PORT_MBA_LINK_SPEED_25G 0x4 +#define NVM_CFG1_PORT_MBA_LINK_SPEED_40G 0x5 +#define NVM_CFG1_PORT_MBA_LINK_SPEED_50G 0x6 +#define NVM_CFG1_PORT_MBA_LINK_SPEED_100G 0x7 +#define NVM_CFG1_PORT_MBA_BOOT_RETRY_COUNT_MASK 0x00E00000 +#define NVM_CFG1_PORT_MBA_BOOT_RETRY_COUNT_OFFSET 21 + + u32 mba_cfg2; /* 0x2C */ +#define NVM_CFG1_PORT_MBA_VLAN_VALUE_MASK 0x0000FFFF +#define NVM_CFG1_PORT_MBA_VLAN_VALUE_OFFSET 0 +#define NVM_CFG1_PORT_MBA_VLAN_MASK 0x00010000 +#define NVM_CFG1_PORT_MBA_VLAN_OFFSET 16 + + u32 vf_cfg; /* 0x30 */ +#define NVM_CFG1_PORT_RESERVED8_MASK 0x0000FFFF +#define NVM_CFG1_PORT_RESERVED8_OFFSET 0 +#define NVM_CFG1_PORT_RESERVED6_MASK 0x000F0000 +#define NVM_CFG1_PORT_RESERVED6_OFFSET 16 +#define NVM_CFG1_PORT_RESERVED6_DISABLED 0x0 +#define NVM_CFG1_PORT_RESERVED6_4K 0x1 +#define NVM_CFG1_PORT_RESERVED6_8K 0x2 +#define NVM_CFG1_PORT_RESERVED6_16K 0x3 +#define NVM_CFG1_PORT_RESERVED6_32K 0x4 +#define NVM_CFG1_PORT_RESERVED6_64K 0x5 +#define NVM_CFG1_PORT_RESERVED6_128K 0x6 +#define NVM_CFG1_PORT_RESERVED6_256K 0x7 +#define NVM_CFG1_PORT_RESERVED6_512K 0x8 +#define NVM_CFG1_PORT_RESERVED6_1M 0x9 +#define NVM_CFG1_PORT_RESERVED6_2M 0xA +#define NVM_CFG1_PORT_RESERVED6_4M 0xB +#define NVM_CFG1_PORT_RESERVED6_8M 0xC +#define NVM_CFG1_PORT_RESERVED6_16M 0xD +#define NVM_CFG1_PORT_RESERVED6_32M 0xE +#define NVM_CFG1_PORT_RESERVED6_64M 0xF + + struct nvm_cfg_mac_address lldp_mac_address; /* 0x34 */ + + u32 led_port_settings; /* 0x3C */ +#define NVM_CFG1_PORT_LANE_LED_SPD_0_SEL_MASK 0x000000FF +#define NVM_CFG1_PORT_LANE_LED_SPD_0_SEL_OFFSET 0 +#define NVM_CFG1_PORT_LANE_LED_SPD_1_SEL_MASK 0x0000FF00 +#define NVM_CFG1_PORT_LANE_LED_SPD_1_SEL_OFFSET 8 +#define NVM_CFG1_PORT_LANE_LED_SPD_2_SEL_MASK 0x00FF0000 +#define NVM_CFG1_PORT_LANE_LED_SPD_2_SEL_OFFSET 16 +#define NVM_CFG1_PORT_LANE_LED_SPD__SEL_1G 0x1 +#define NVM_CFG1_PORT_LANE_LED_SPD__SEL_10G 0x2 +#define NVM_CFG1_PORT_LANE_LED_SPD__SEL_25G 0x8 +#define NVM_CFG1_PORT_LANE_LED_SPD__SEL_40G 0x10 +#define NVM_CFG1_PORT_LANE_LED_SPD__SEL_50G 0x20 +#define NVM_CFG1_PORT_LANE_LED_SPD__SEL_100G 0x40 + + u32 transceiver_00; /* 0x40 */ + + /* Define for mapping of transceiver signal module absent */ +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_MASK 0x000000FF +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_OFFSET 0 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_NA 0x0 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO0 0x1 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO1 0x2 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO2 0x3 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO3 0x4 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO4 0x5 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO5 0x6 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO6 0x7 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO7 0x8 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO8 0x9 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO9 0xA +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO10 0xB +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO11 0xC +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO12 0xD +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO13 0xE +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO14 0xF +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO15 0x10 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO16 0x11 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO17 0x12 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO18 0x13 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO19 0x14 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO20 0x15 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO21 0x16 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO22 0x17 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO23 0x18 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO24 0x19 +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO25 0x1A +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO26 0x1B +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO27 0x1C +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO28 0x1D +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO29 0x1E +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO30 0x1F +#define NVM_CFG1_PORT_TRANS_MODULE_ABS_GPIO31 0x20 + /* Define the GPIO mux settings to switch i2c mux to this port */ +#define NVM_CFG1_PORT_I2C_MUX_SEL_VALUE_0_MASK 0x00000F00 +#define NVM_CFG1_PORT_I2C_MUX_SEL_VALUE_0_OFFSET 8 +#define NVM_CFG1_PORT_I2C_MUX_SEL_VALUE_1_MASK 0x0000F000 +#define NVM_CFG1_PORT_I2C_MUX_SEL_VALUE_1_OFFSET 12 + + u32 reserved[133]; /* 0x44 */ +}; + +struct nvm_cfg1_func { + struct nvm_cfg_mac_address mac_address; /* 0x0 */ + + u32 rsrv1; /* 0x8 */ +#define NVM_CFG1_FUNC_RESERVED1_MASK 0x0000FFFF +#define NVM_CFG1_FUNC_RESERVED1_OFFSET 0 +#define NVM_CFG1_FUNC_RESERVED2_MASK 0xFFFF0000 +#define NVM_CFG1_FUNC_RESERVED2_OFFSET 16 + + u32 rsrv2; /* 0xC */ +#define NVM_CFG1_FUNC_RESERVED3_MASK 0x0000FFFF +#define NVM_CFG1_FUNC_RESERVED3_OFFSET 0 +#define NVM_CFG1_FUNC_RESERVED4_MASK 0xFFFF0000 +#define NVM_CFG1_FUNC_RESERVED4_OFFSET 16 + + u32 device_id; /* 0x10 */ +#define NVM_CFG1_FUNC_MF_VENDOR_DEVICE_ID_MASK 0x0000FFFF +#define NVM_CFG1_FUNC_MF_VENDOR_DEVICE_ID_OFFSET 0 +#define NVM_CFG1_FUNC_VENDOR_DEVICE_ID_MASK 0xFFFF0000 +#define NVM_CFG1_FUNC_VENDOR_DEVICE_ID_OFFSET 16 + + u32 cmn_cfg; /* 0x14 */ +#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_MASK 0x00000007 +#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_OFFSET 0 +#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_PXE 0x0 +#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_RPL 0x1 +#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_BOOTP 0x2 +#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_ISCSI_BOOT 0x3 +#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_FCOE_BOOT 0x4 +#define NVM_CFG1_FUNC_MBA_BOOT_PROTOCOL_NONE 0x7 +#define NVM_CFG1_FUNC_VF_PCI_DEVICE_ID_MASK 0x0007FFF8 +#define NVM_CFG1_FUNC_VF_PCI_DEVICE_ID_OFFSET 3 +#define NVM_CFG1_FUNC_PERSONALITY_MASK 0x00780000 +#define NVM_CFG1_FUNC_PERSONALITY_OFFSET 19 +#define NVM_CFG1_FUNC_PERSONALITY_ETHERNET 0x0 +#define NVM_CFG1_FUNC_PERSONALITY_ISCSI 0x1 +#define NVM_CFG1_FUNC_PERSONALITY_FCOE 0x2 +#define NVM_CFG1_FUNC_PERSONALITY_ROCE 0x3 +#define NVM_CFG1_FUNC_BANDWIDTH_WEIGHT_MASK 0x7F800000 +#define NVM_CFG1_FUNC_BANDWIDTH_WEIGHT_OFFSET 23 +#define NVM_CFG1_FUNC_PAUSE_ON_HOST_RING_MASK 0x80000000 +#define NVM_CFG1_FUNC_PAUSE_ON_HOST_RING_OFFSET 31 +#define NVM_CFG1_FUNC_PAUSE_ON_HOST_RING_DISABLED 0x0 +#define NVM_CFG1_FUNC_PAUSE_ON_HOST_RING_ENABLED 0x1 + + u32 pci_cfg; /* 0x18 */ +#define NVM_CFG1_FUNC_NUMBER_OF_VFS_PER_PF_MASK 0x0000007F +#define NVM_CFG1_FUNC_NUMBER_OF_VFS_PER_PF_OFFSET 0 +#define NVM_CFG1_FUNC_RESERVESD12_MASK 0x00003F80 +#define NVM_CFG1_FUNC_RESERVESD12_OFFSET 7 +#define NVM_CFG1_FUNC_BAR1_SIZE_MASK 0x0003C000 +#define NVM_CFG1_FUNC_BAR1_SIZE_OFFSET 14 +#define NVM_CFG1_FUNC_BAR1_SIZE_DISABLED 0x0 +#define NVM_CFG1_FUNC_BAR1_SIZE_64K 0x1 +#define NVM_CFG1_FUNC_BAR1_SIZE_128K 0x2 +#define NVM_CFG1_FUNC_BAR1_SIZE_256K 0x3 +#define NVM_CFG1_FUNC_BAR1_SIZE_512K 0x4 +#define NVM_CFG1_FUNC_BAR1_SIZE_1M 0x5 +#define NVM_CFG1_FUNC_BAR1_SIZE_2M 0x6 +#define NVM_CFG1_FUNC_BAR1_SIZE_4M 0x7 +#define NVM_CFG1_FUNC_BAR1_SIZE_8M 0x8 +#define NVM_CFG1_FUNC_BAR1_SIZE_16M 0x9 +#define NVM_CFG1_FUNC_BAR1_SIZE_32M 0xA +#define NVM_CFG1_FUNC_BAR1_SIZE_64M 0xB +#define NVM_CFG1_FUNC_BAR1_SIZE_128M 0xC +#define NVM_CFG1_FUNC_BAR1_SIZE_256M 0xD +#define NVM_CFG1_FUNC_BAR1_SIZE_512M 0xE +#define NVM_CFG1_FUNC_BAR1_SIZE_1G 0xF +#define NVM_CFG1_FUNC_MAX_BANDWIDTH_MASK 0x03FC0000 +#define NVM_CFG1_FUNC_MAX_BANDWIDTH_OFFSET 18 + + struct nvm_cfg_mac_address fcoe_node_wwn_mac_addr; /* 0x1C */ + + struct nvm_cfg_mac_address fcoe_port_wwn_mac_addr; /* 0x24 */ + + u32 reserved[9]; /* 0x2C */ +}; + +struct nvm_cfg1 { + struct nvm_cfg1_glob glob; /* 0x0 */ + + struct nvm_cfg1_path path[MCP_GLOB_PATH_MAX]; /* 0x140 */ + + struct nvm_cfg1_port port[MCP_GLOB_PORT_MAX]; /* 0x230 */ + + struct nvm_cfg1_func func[MCP_GLOB_FUNC_MAX]; /* 0xB90 */ +}; + +/****************************************** +* nvm_cfg structs +******************************************/ + +enum nvm_cfg_sections { + NVM_CFG_SECTION_NVM_CFG1, + NVM_CFG_SECTION_MAX +}; + +struct nvm_cfg { + u32 num_sections; + u32 sections_offset[NVM_CFG_SECTION_MAX]; + struct nvm_cfg1 cfg1; +}; + +#define PORT_0 0 +#define PORT_1 1 +#define PORT_2 2 +#define PORT_3 3 + +extern struct spad_layout g_spad; + +#define MCP_SPAD_SIZE 0x00028000 /* 160 KB */ + +#define SPAD_OFFSET(addr) (((u32)addr - (u32)CPU_SPAD_BASE)) + +#define TO_OFFSIZE(_offset, _size) \ + (u32)((((u32)(_offset) >> 2) << OFFSIZE_OFFSET_SHIFT) | \ + (((u32)(_size) >> 2) << OFFSIZE_SIZE_SHIFT)) + +enum spad_sections { + SPAD_SECTION_TRACE, + SPAD_SECTION_NVM_CFG, + SPAD_SECTION_PUBLIC, + SPAD_SECTION_PRIVATE, + SPAD_SECTION_MAX +}; + +struct spad_layout { + struct nvm_cfg nvm_cfg; + struct mcp_public_data public_data; +}; + +#define CRC_MAGIC_VALUE 0xDEBB20E3 +#define CRC32_POLYNOMIAL 0xEDB88320 +#define NVM_CRC_SIZE (sizeof(u32)) + +enum nvm_sw_arbitrator { + NVM_SW_ARB_HOST, + NVM_SW_ARB_MCP, + NVM_SW_ARB_UART, + NVM_SW_ARB_RESERVED +}; + +/**************************************************************************** +* Boot Strap Region * +****************************************************************************/ +struct legacy_bootstrap_region { + u32 magic_value; +#define NVM_MAGIC_VALUE 0x669955aa + u32 sram_start_addr; + u32 code_len; /* boot code length (in dwords) */ + u32 code_start_addr; + u32 crc; /* 32-bit CRC */ +}; + +/**************************************************************************** +* Directories Region * +****************************************************************************/ +struct nvm_code_entry { + u32 image_type; /* Image type */ + u32 nvm_start_addr; /* NVM address of the image */ + u32 len; /* Include CRC */ + u32 sram_start_addr; + u32 sram_run_addr; /* Relevant in case of MIM only */ +}; + +enum nvm_image_type { + NVM_TYPE_TIM1 = 0x01, + NVM_TYPE_TIM2 = 0x02, + NVM_TYPE_MIM1 = 0x03, + NVM_TYPE_MIM2 = 0x04, + NVM_TYPE_MBA = 0x05, + NVM_TYPE_MODULES_PN = 0x06, + NVM_TYPE_VPD = 0x07, + NVM_TYPE_MFW_TRACE1 = 0x08, + NVM_TYPE_MFW_TRACE2 = 0x09, + NVM_TYPE_NVM_CFG1 = 0x0a, + NVM_TYPE_L2B = 0x0b, + NVM_TYPE_DIR1 = 0x0c, + NVM_TYPE_EAGLE_FW1 = 0x0d, + NVM_TYPE_FALCON_FW1 = 0x0e, + NVM_TYPE_PCIE_FW1 = 0x0f, + NVM_TYPE_HW_SET = 0x10, + NVM_TYPE_LIM = 0x11, + NVM_TYPE_AVS_FW1 = 0x12, + NVM_TYPE_DIR2 = 0x13, + NVM_TYPE_CCM = 0x14, + NVM_TYPE_EAGLE_FW2 = 0x15, + NVM_TYPE_FALCON_FW2 = 0x16, + NVM_TYPE_PCIE_FW2 = 0x17, + NVM_TYPE_AVS_FW2 = 0x18, + + NVM_TYPE_MAX, +}; + +#define MAX_NVM_DIR_ENTRIES 200 + +struct nvm_dir { + s32 seq; +#define NVM_DIR_NEXT_MFW_MASK 0x00000001 +#define NVM_DIR_SEQ_MASK 0xfffffffe +#define NVM_DIR_NEXT_MFW(seq) ((seq) & NVM_DIR_NEXT_MFW_MASK) + +#define IS_DIR_SEQ_VALID(seq) ((seq & NVM_DIR_SEQ_MASK) != NVM_DIR_SEQ_MASK) + + u32 num_images; + u32 rsrv; + struct nvm_code_entry code[1]; /* Up to MAX_NVM_DIR_ENTRIES */ +}; + +#define NVM_DIR_SIZE(_num_images) (sizeof(struct nvm_dir) + \ + (_num_images - \ + 1) * sizeof(struct nvm_code_entry) + \ + NVM_CRC_SIZE) + +struct nvm_vpd_image { + u32 format_revision; +#define VPD_IMAGE_VERSION 1 + + /* This array length depends on the number of VPD fields */ + u8 vpd_data[1]; +}; + +/**************************************************************************** +* NVRAM FULL MAP * +****************************************************************************/ +#define DIR_ID_1 (0) +#define DIR_ID_2 (1) +#define MAX_DIR_IDS (2) + +#define MFW_BUNDLE_1 (0) +#define MFW_BUNDLE_2 (1) +#define MAX_MFW_BUNDLES (2) + +#define FLASH_PAGE_SIZE 0x1000 +#define NVM_DIR_MAX_SIZE (FLASH_PAGE_SIZE) /* 4Kb */ +#define ASIC_MIM_MAX_SIZE (300 * FLASH_PAGE_SIZE) /* 1.2Mb */ +#define FPGA_MIM_MAX_SIZE (25 * FLASH_PAGE_SIZE) /* 60Kb */ + +#define LIM_MAX_SIZE ((2 * \ + FLASH_PAGE_SIZE) - \ + sizeof(struct legacy_bootstrap_region) - \ + NVM_RSV_SIZE) +#define LIM_OFFSET (NVM_OFFSET(lim_image)) +#define NVM_RSV_SIZE (44) +#define MIM_MAX_SIZE(is_asic) ((is_asic) ? ASIC_MIM_MAX_SIZE : \ + FPGA_MIM_MAX_SIZE) +#define MIM_OFFSET(idx, is_asic) (NVM_OFFSET(dir[MAX_MFW_BUNDLES]) + \ + ((idx == \ + NVM_TYPE_MIM2) ? MIM_MAX_SIZE(is_asic) : 0)) +#define NVM_FIXED_AREA_SIZE(is_asic) (sizeof(struct nvm_image) + \ + MIM_MAX_SIZE(is_asic) * 2) + +union nvm_dir_union { + struct nvm_dir dir; + u8 page[FLASH_PAGE_SIZE]; +}; + +/* Address + * +-------------------+ 0x000000 + * | Bootstrap: | + * | magic_number | + * | sram_start_addr | + * | code_len | + * | code_start_addr | + * | crc | + * +-------------------+ 0x000014 + * | rsrv | + * +-------------------+ 0x000040 + * | LIM | + * +-------------------+ 0x002000 + * | Dir1 | + * +-------------------+ 0x003000 + * | Dir2 | + * +-------------------+ 0x004000 + * | MIM1 | + * +-------------------+ 0x130000 + * | MIM2 | + * +-------------------+ 0x25C000 + * | Rest Images: | + * | TIM1/2 | + * | MFW_TRACE1/2 | + * | Eagle/Falcon FW | + * | PCIE/AVS FW | + * | MBA/CCM/L2B | + * | VPD | + * | optic_modules | + * | ... | + * +-------------------+ 0x400000 + */ +struct nvm_image { +/*********** !!! FIXED SECTIONS !!! DO NOT MODIFY !!! **********************/ + /* NVM Offset (size) */ + struct legacy_bootstrap_region bootstrap; + u8 rsrv[NVM_RSV_SIZE]; + u8 lim_image[LIM_MAX_SIZE]; + union nvm_dir_union dir[MAX_MFW_BUNDLES]; + + /* MIM1_IMAGE 0x004000 (0x12c000) */ + /* MIM2_IMAGE 0x130000 (0x12c000) */ +/*********** !!! FIXED SECTIONS !!! DO NOT MODIFY !!! **********************/ +}; /* 0x134 */ + +#define NVM_OFFSET(f) ((u32_t)((int_ptr_t)(&(((struct nvm_image *)0)->f)))) + +struct hw_set_info { + u32 reg_type; +#define GRC_REG_TYPE 1 +#define PHY_REG_TYPE 2 +#define PCI_REG_TYPE 4 + + u32 bank_num; + u32 pf_num; + u32 operation; +#define READ_OP 1 +#define WRITE_OP 2 +#define RMW_SET_OP 3 +#define RMW_CLR_OP 4 + + u32 reg_addr; + u32 reg_data; + + u32 reset_type; +#define POR_RESET_TYPE BIT(0) +#define HARD_RESET_TYPE BIT(1) +#define CORE_RESET_TYPE BIT(2) +#define MCP_RESET_TYPE BIT(3) +#define PERSET_ASSERT BIT(4) +#define PERSET_DEASSERT BIT(5) +}; + +struct hw_set_image { + u32 format_version; +#define HW_SET_IMAGE_VERSION 1 + u32 no_hw_sets; + + /* This array length depends on the no_hw_sets */ + struct hw_set_info hw_sets[1]; +}; + +#endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_hw.c b/drivers/net/ethernet/qlogic/qed/qed_hw.c new file mode 100644 index 000000000000..ffa99273b353 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_hw.c @@ -0,0 +1,776 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qed.h" +#include "qed_hsi.h" +#include "qed_hw.h" +#include "qed_reg_addr.h" + +#define QED_BAR_ACQUIRE_TIMEOUT 1000 + +/* Invalid values */ +#define QED_BAR_INVALID_OFFSET (cpu_to_le32(-1)) + +struct qed_ptt { + struct list_head list_entry; + unsigned int idx; + struct pxp_ptt_entry pxp; +}; + +struct qed_ptt_pool { + struct list_head free_list; + spinlock_t lock; /* ptt synchronized access */ + struct qed_ptt ptts[PXP_EXTERNAL_BAR_PF_WINDOW_NUM]; +}; + +int qed_ptt_pool_alloc(struct qed_hwfn *p_hwfn) +{ + struct qed_ptt_pool *p_pool = kmalloc(sizeof(*p_pool), + GFP_ATOMIC); + int i; + + if (!p_pool) + return -ENOMEM; + + INIT_LIST_HEAD(&p_pool->free_list); + for (i = 0; i < PXP_EXTERNAL_BAR_PF_WINDOW_NUM; i++) { + p_pool->ptts[i].idx = i; + p_pool->ptts[i].pxp.offset = QED_BAR_INVALID_OFFSET; + p_pool->ptts[i].pxp.pretend.control = 0; + if (i >= RESERVED_PTT_MAX) + list_add(&p_pool->ptts[i].list_entry, + &p_pool->free_list); + } + + p_hwfn->p_ptt_pool = p_pool; + spin_lock_init(&p_pool->lock); + + return 0; +} + +void qed_ptt_invalidate(struct qed_hwfn *p_hwfn) +{ + struct qed_ptt *p_ptt; + int i; + + for (i = 0; i < PXP_EXTERNAL_BAR_PF_WINDOW_NUM; i++) { + p_ptt = &p_hwfn->p_ptt_pool->ptts[i]; + p_ptt->pxp.offset = QED_BAR_INVALID_OFFSET; + } +} + +void qed_ptt_pool_free(struct qed_hwfn *p_hwfn) +{ + kfree(p_hwfn->p_ptt_pool); + p_hwfn->p_ptt_pool = NULL; +} + +struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn) +{ + struct qed_ptt *p_ptt; + unsigned int i; + + /* Take the free PTT from the list */ + for (i = 0; i < QED_BAR_ACQUIRE_TIMEOUT; i++) { + spin_lock_bh(&p_hwfn->p_ptt_pool->lock); + + if (!list_empty(&p_hwfn->p_ptt_pool->free_list)) { + p_ptt = list_first_entry(&p_hwfn->p_ptt_pool->free_list, + struct qed_ptt, list_entry); + list_del(&p_ptt->list_entry); + + spin_unlock_bh(&p_hwfn->p_ptt_pool->lock); + + DP_VERBOSE(p_hwfn, NETIF_MSG_HW, + "allocated ptt %d\n", p_ptt->idx); + return p_ptt; + } + + spin_unlock_bh(&p_hwfn->p_ptt_pool->lock); + usleep_range(1000, 2000); + } + + DP_NOTICE(p_hwfn, "PTT acquire timeout - failed to allocate PTT\n"); + return NULL; +} + +void qed_ptt_release(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + spin_lock_bh(&p_hwfn->p_ptt_pool->lock); + list_add(&p_ptt->list_entry, &p_hwfn->p_ptt_pool->free_list); + spin_unlock_bh(&p_hwfn->p_ptt_pool->lock); +} + +u32 qed_ptt_get_hw_addr(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + /* The HW is using DWORDS and we need to translate it to Bytes */ + return le32_to_cpu(p_ptt->pxp.offset) << 2; +} + +static u32 qed_ptt_config_addr(struct qed_ptt *p_ptt) +{ + return PXP_PF_WINDOW_ADMIN_PER_PF_START + + p_ptt->idx * sizeof(struct pxp_ptt_entry); +} + +u32 qed_ptt_get_bar_addr(struct qed_ptt *p_ptt) +{ + return PXP_EXTERNAL_BAR_PF_WINDOW_START + + p_ptt->idx * PXP_EXTERNAL_BAR_PF_WINDOW_SINGLE_SIZE; +} + +void qed_ptt_set_win(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 new_hw_addr) +{ + u32 prev_hw_addr; + + prev_hw_addr = qed_ptt_get_hw_addr(p_hwfn, p_ptt); + + if (new_hw_addr == prev_hw_addr) + return; + + /* Update PTT entery in admin window */ + DP_VERBOSE(p_hwfn, NETIF_MSG_HW, + "Updating PTT entry %d to offset 0x%x\n", + p_ptt->idx, new_hw_addr); + + /* The HW is using DWORDS and the address is in Bytes */ + p_ptt->pxp.offset = cpu_to_le32(new_hw_addr >> 2); + + REG_WR(p_hwfn, + qed_ptt_config_addr(p_ptt) + + offsetof(struct pxp_ptt_entry, offset), + le32_to_cpu(p_ptt->pxp.offset)); +} + +static u32 qed_set_ptt(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 hw_addr) +{ + u32 win_hw_addr = qed_ptt_get_hw_addr(p_hwfn, p_ptt); + u32 offset; + + offset = hw_addr - win_hw_addr; + + /* Verify the address is within the window */ + if (hw_addr < win_hw_addr || + offset >= PXP_EXTERNAL_BAR_PF_WINDOW_SINGLE_SIZE) { + qed_ptt_set_win(p_hwfn, p_ptt, hw_addr); + offset = 0; + } + + return qed_ptt_get_bar_addr(p_ptt) + offset; +} + +struct qed_ptt *qed_get_reserved_ptt(struct qed_hwfn *p_hwfn, + enum reserved_ptts ptt_idx) +{ + if (ptt_idx >= RESERVED_PTT_MAX) { + DP_NOTICE(p_hwfn, + "Requested PTT %d is out of range\n", ptt_idx); + return NULL; + } + + return &p_hwfn->p_ptt_pool->ptts[ptt_idx]; +} + +void qed_wr(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 hw_addr, u32 val) +{ + u32 bar_addr = qed_set_ptt(p_hwfn, p_ptt, hw_addr); + + REG_WR(p_hwfn, bar_addr, val); + DP_VERBOSE(p_hwfn, NETIF_MSG_HW, + "bar_addr 0x%x, hw_addr 0x%x, val 0x%x\n", + bar_addr, hw_addr, val); +} + +u32 qed_rd(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 hw_addr) +{ + u32 bar_addr = qed_set_ptt(p_hwfn, p_ptt, hw_addr); + u32 val = REG_RD(p_hwfn, bar_addr); + + DP_VERBOSE(p_hwfn, NETIF_MSG_HW, + "bar_addr 0x%x, hw_addr 0x%x, val 0x%x\n", + bar_addr, hw_addr, val); + + return val; +} + +static void qed_memcpy_hw(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + void *addr, + u32 hw_addr, + size_t n, + bool to_device) +{ + u32 dw_count, *host_addr, hw_offset; + size_t quota, done = 0; + u32 __iomem *reg_addr; + + while (done < n) { + quota = min_t(size_t, n - done, + PXP_EXTERNAL_BAR_PF_WINDOW_SINGLE_SIZE); + + qed_ptt_set_win(p_hwfn, p_ptt, hw_addr + done); + hw_offset = qed_ptt_get_bar_addr(p_ptt); + + dw_count = quota / 4; + host_addr = (u32 *)((u8 *)addr + done); + reg_addr = (u32 __iomem *)REG_ADDR(p_hwfn, hw_offset); + if (to_device) + while (dw_count--) + DIRECT_REG_WR(reg_addr++, *host_addr++); + else + while (dw_count--) + *host_addr++ = DIRECT_REG_RD(reg_addr++); + + done += quota; + } +} + +void qed_memcpy_from(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + void *dest, u32 hw_addr, size_t n) +{ + DP_VERBOSE(p_hwfn, NETIF_MSG_HW, + "hw_addr 0x%x, dest %p hw_addr 0x%x, size %lu\n", + hw_addr, dest, hw_addr, (unsigned long)n); + + qed_memcpy_hw(p_hwfn, p_ptt, dest, hw_addr, n, false); +} + +void qed_memcpy_to(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 hw_addr, void *src, size_t n) +{ + DP_VERBOSE(p_hwfn, NETIF_MSG_HW, + "hw_addr 0x%x, hw_addr 0x%x, src %p size %lu\n", + hw_addr, hw_addr, src, (unsigned long)n); + + qed_memcpy_hw(p_hwfn, p_ptt, src, hw_addr, n, true); +} + +void qed_fid_pretend(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u16 fid) +{ + u16 control = 0; + + SET_FIELD(control, PXP_PRETEND_CMD_IS_CONCRETE, 1); + SET_FIELD(control, PXP_PRETEND_CMD_PRETEND_FUNCTION, 1); + + /* Every pretend undos previous pretends, including + * previous port pretend. + */ + SET_FIELD(control, PXP_PRETEND_CMD_PORT, 0); + SET_FIELD(control, PXP_PRETEND_CMD_USE_PORT, 0); + SET_FIELD(control, PXP_PRETEND_CMD_PRETEND_PORT, 1); + + if (!GET_FIELD(fid, PXP_CONCRETE_FID_VFVALID)) + fid = GET_FIELD(fid, PXP_CONCRETE_FID_PFID); + + p_ptt->pxp.pretend.control = cpu_to_le16(control); + p_ptt->pxp.pretend.fid.concrete_fid.fid = cpu_to_le16(fid); + + REG_WR(p_hwfn, + qed_ptt_config_addr(p_ptt) + + offsetof(struct pxp_ptt_entry, pretend), + *(u32 *)&p_ptt->pxp.pretend); +} + +void qed_port_pretend(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u8 port_id) +{ + u16 control = 0; + + SET_FIELD(control, PXP_PRETEND_CMD_PORT, port_id); + SET_FIELD(control, PXP_PRETEND_CMD_USE_PORT, 1); + SET_FIELD(control, PXP_PRETEND_CMD_PRETEND_PORT, 1); + + p_ptt->pxp.pretend.control = cpu_to_le16(control); + + REG_WR(p_hwfn, + qed_ptt_config_addr(p_ptt) + + offsetof(struct pxp_ptt_entry, pretend), + *(u32 *)&p_ptt->pxp.pretend); +} + +void qed_port_unpretend(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + u16 control = 0; + + SET_FIELD(control, PXP_PRETEND_CMD_PORT, 0); + SET_FIELD(control, PXP_PRETEND_CMD_USE_PORT, 0); + SET_FIELD(control, PXP_PRETEND_CMD_PRETEND_PORT, 1); + + p_ptt->pxp.pretend.control = cpu_to_le16(control); + + REG_WR(p_hwfn, + qed_ptt_config_addr(p_ptt) + + offsetof(struct pxp_ptt_entry, pretend), + *(u32 *)&p_ptt->pxp.pretend); +} + +/* DMAE */ +static void qed_dmae_opcode(struct qed_hwfn *p_hwfn, + const u8 is_src_type_grc, + const u8 is_dst_type_grc, + struct qed_dmae_params *p_params) +{ + u32 opcode = 0; + u16 opcodeB = 0; + + /* Whether the source is the PCIe or the GRC. + * 0- The source is the PCIe + * 1- The source is the GRC. + */ + opcode |= (is_src_type_grc ? DMAE_CMD_SRC_MASK_GRC + : DMAE_CMD_SRC_MASK_PCIE) << + DMAE_CMD_SRC_SHIFT; + opcode |= ((p_hwfn->rel_pf_id & DMAE_CMD_SRC_PF_ID_MASK) << + DMAE_CMD_SRC_PF_ID_SHIFT); + + /* The destination of the DMA can be: 0-None 1-PCIe 2-GRC 3-None */ + opcode |= (is_dst_type_grc ? DMAE_CMD_DST_MASK_GRC + : DMAE_CMD_DST_MASK_PCIE) << + DMAE_CMD_DST_SHIFT; + opcode |= ((p_hwfn->rel_pf_id & DMAE_CMD_DST_PF_ID_MASK) << + DMAE_CMD_DST_PF_ID_SHIFT); + + /* Whether to write a completion word to the completion destination: + * 0-Do not write a completion word + * 1-Write the completion word + */ + opcode |= (DMAE_CMD_COMP_WORD_EN_MASK << DMAE_CMD_COMP_WORD_EN_SHIFT); + opcode |= (DMAE_CMD_SRC_ADDR_RESET_MASK << + DMAE_CMD_SRC_ADDR_RESET_SHIFT); + + if (p_params->flags & QED_DMAE_FLAG_COMPLETION_DST) + opcode |= (1 << DMAE_CMD_COMP_FUNC_SHIFT); + + opcode |= (DMAE_CMD_ENDIANITY << DMAE_CMD_ENDIANITY_MODE_SHIFT); + + opcode |= ((p_hwfn->port_id) << DMAE_CMD_PORT_ID_SHIFT); + + /* reset source address in next go */ + opcode |= (DMAE_CMD_SRC_ADDR_RESET_MASK << + DMAE_CMD_SRC_ADDR_RESET_SHIFT); + + /* reset dest address in next go */ + opcode |= (DMAE_CMD_DST_ADDR_RESET_MASK << + DMAE_CMD_DST_ADDR_RESET_SHIFT); + + opcodeB |= (DMAE_CMD_SRC_VF_ID_MASK << + DMAE_CMD_SRC_VF_ID_SHIFT); + + opcodeB |= (DMAE_CMD_DST_VF_ID_MASK << + DMAE_CMD_DST_VF_ID_SHIFT); + + p_hwfn->dmae_info.p_dmae_cmd->opcode = cpu_to_le32(opcode); + p_hwfn->dmae_info.p_dmae_cmd->opcode_b = cpu_to_le16(opcodeB); +} + +u32 qed_dmae_idx_to_go_cmd(u8 idx) +{ + /* All the DMAE 'go' registers form an array in internal memory */ + return DMAE_REG_GO_C0 + (idx << 2); +} + +static int +qed_dmae_post_command(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + struct dmae_cmd *command = p_hwfn->dmae_info.p_dmae_cmd; + u8 idx_cmd = p_hwfn->dmae_info.channel, i; + int qed_status = 0; + + /* verify address is not NULL */ + if ((((command->dst_addr_lo == 0) && (command->dst_addr_hi == 0)) || + ((command->src_addr_lo == 0) && (command->src_addr_hi == 0)))) { + DP_NOTICE(p_hwfn, + "source or destination address 0 idx_cmd=%d\n" + "opcode = [0x%08x,0x%04x] len=0x%x src=0x%x:%x dst=0x%x:%x\n", + idx_cmd, + le32_to_cpu(command->opcode), + le16_to_cpu(command->opcode_b), + le16_to_cpu(command->length), + le32_to_cpu(command->src_addr_hi), + le32_to_cpu(command->src_addr_lo), + le32_to_cpu(command->dst_addr_hi), + le32_to_cpu(command->dst_addr_lo)); + + return -EINVAL; + } + + DP_VERBOSE(p_hwfn, + NETIF_MSG_HW, + "Posting DMAE command [idx %d]: opcode = [0x%08x,0x%04x] len=0x%x src=0x%x:%x dst=0x%x:%x\n", + idx_cmd, + le32_to_cpu(command->opcode), + le16_to_cpu(command->opcode_b), + le16_to_cpu(command->length), + le32_to_cpu(command->src_addr_hi), + le32_to_cpu(command->src_addr_lo), + le32_to_cpu(command->dst_addr_hi), + le32_to_cpu(command->dst_addr_lo)); + + /* Copy the command to DMAE - need to do it before every call + * for source/dest address no reset. + * The first 9 DWs are the command registers, the 10 DW is the + * GO register, and the rest are result registers + * (which are read only by the client). + */ + for (i = 0; i < DMAE_CMD_SIZE; i++) { + u32 data = (i < DMAE_CMD_SIZE_TO_FILL) ? + *(((u32 *)command) + i) : 0; + + qed_wr(p_hwfn, p_ptt, + DMAE_REG_CMD_MEM + + (idx_cmd * DMAE_CMD_SIZE * sizeof(u32)) + + (i * sizeof(u32)), data); + } + + qed_wr(p_hwfn, p_ptt, + qed_dmae_idx_to_go_cmd(idx_cmd), + DMAE_GO_VALUE); + + return qed_status; +} + +int qed_dmae_info_alloc(struct qed_hwfn *p_hwfn) +{ + dma_addr_t *p_addr = &p_hwfn->dmae_info.completion_word_phys_addr; + struct dmae_cmd **p_cmd = &p_hwfn->dmae_info.p_dmae_cmd; + u32 **p_buff = &p_hwfn->dmae_info.p_intermediate_buffer; + u32 **p_comp = &p_hwfn->dmae_info.p_completion_word; + + *p_comp = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, + sizeof(u32), + p_addr, + GFP_KERNEL); + if (!*p_comp) { + DP_NOTICE(p_hwfn, "Failed to allocate `p_completion_word'\n"); + goto err; + } + + p_addr = &p_hwfn->dmae_info.dmae_cmd_phys_addr; + *p_cmd = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, + sizeof(struct dmae_cmd), + p_addr, GFP_KERNEL); + if (!*p_cmd) { + DP_NOTICE(p_hwfn, "Failed to allocate `struct dmae_cmd'\n"); + goto err; + } + + p_addr = &p_hwfn->dmae_info.intermediate_buffer_phys_addr; + *p_buff = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, + sizeof(u32) * DMAE_MAX_RW_SIZE, + p_addr, GFP_KERNEL); + if (!*p_buff) { + DP_NOTICE(p_hwfn, "Failed to allocate `intermediate_buffer'\n"); + goto err; + } + + p_hwfn->dmae_info.channel = p_hwfn->rel_pf_id; + + return 0; +err: + qed_dmae_info_free(p_hwfn); + return -ENOMEM; +} + +void qed_dmae_info_free(struct qed_hwfn *p_hwfn) +{ + dma_addr_t p_phys; + + /* Just make sure no one is in the middle */ + mutex_lock(&p_hwfn->dmae_info.mutex); + + if (p_hwfn->dmae_info.p_completion_word) { + p_phys = p_hwfn->dmae_info.completion_word_phys_addr; + dma_free_coherent(&p_hwfn->cdev->pdev->dev, + sizeof(u32), + p_hwfn->dmae_info.p_completion_word, + p_phys); + p_hwfn->dmae_info.p_completion_word = NULL; + } + + if (p_hwfn->dmae_info.p_dmae_cmd) { + p_phys = p_hwfn->dmae_info.dmae_cmd_phys_addr; + dma_free_coherent(&p_hwfn->cdev->pdev->dev, + sizeof(struct dmae_cmd), + p_hwfn->dmae_info.p_dmae_cmd, + p_phys); + p_hwfn->dmae_info.p_dmae_cmd = NULL; + } + + if (p_hwfn->dmae_info.p_intermediate_buffer) { + p_phys = p_hwfn->dmae_info.intermediate_buffer_phys_addr; + dma_free_coherent(&p_hwfn->cdev->pdev->dev, + sizeof(u32) * DMAE_MAX_RW_SIZE, + p_hwfn->dmae_info.p_intermediate_buffer, + p_phys); + p_hwfn->dmae_info.p_intermediate_buffer = NULL; + } + + mutex_unlock(&p_hwfn->dmae_info.mutex); +} + +static int qed_dmae_operation_wait(struct qed_hwfn *p_hwfn) +{ + u32 wait_cnt = 0; + u32 wait_cnt_limit = 10000; + + int qed_status = 0; + + barrier(); + while (*p_hwfn->dmae_info.p_completion_word != DMAE_COMPLETION_VAL) { + udelay(DMAE_MIN_WAIT_TIME); + if (++wait_cnt > wait_cnt_limit) { + DP_NOTICE(p_hwfn->cdev, + "Timed-out waiting for operation to complete. Completion word is 0x%08x expected 0x%08x.\n", + *p_hwfn->dmae_info.p_completion_word, + DMAE_COMPLETION_VAL); + qed_status = -EBUSY; + break; + } + + /* to sync the completion_word since we are not + * using the volatile keyword for p_completion_word + */ + barrier(); + } + + if (qed_status == 0) + *p_hwfn->dmae_info.p_completion_word = 0; + + return qed_status; +} + +static int qed_dmae_execute_sub_operation(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u64 src_addr, + u64 dst_addr, + u8 src_type, + u8 dst_type, + u32 length) +{ + dma_addr_t phys = p_hwfn->dmae_info.intermediate_buffer_phys_addr; + struct dmae_cmd *cmd = p_hwfn->dmae_info.p_dmae_cmd; + int qed_status = 0; + + switch (src_type) { + case QED_DMAE_ADDRESS_GRC: + case QED_DMAE_ADDRESS_HOST_PHYS: + cmd->src_addr_hi = cpu_to_le32(upper_32_bits(src_addr)); + cmd->src_addr_lo = cpu_to_le32(lower_32_bits(src_addr)); + break; + /* for virtual source addresses we use the intermediate buffer. */ + case QED_DMAE_ADDRESS_HOST_VIRT: + cmd->src_addr_hi = cpu_to_le32(upper_32_bits(phys)); + cmd->src_addr_lo = cpu_to_le32(lower_32_bits(phys)); + memcpy(&p_hwfn->dmae_info.p_intermediate_buffer[0], + (void *)(uintptr_t)src_addr, + length * sizeof(u32)); + break; + default: + return -EINVAL; + } + + switch (dst_type) { + case QED_DMAE_ADDRESS_GRC: + case QED_DMAE_ADDRESS_HOST_PHYS: + cmd->dst_addr_hi = cpu_to_le32(upper_32_bits(dst_addr)); + cmd->dst_addr_lo = cpu_to_le32(lower_32_bits(dst_addr)); + break; + /* for virtual source addresses we use the intermediate buffer. */ + case QED_DMAE_ADDRESS_HOST_VIRT: + cmd->dst_addr_hi = cpu_to_le32(upper_32_bits(phys)); + cmd->dst_addr_lo = cpu_to_le32(lower_32_bits(phys)); + break; + default: + return -EINVAL; + } + + cmd->length = cpu_to_le16((u16)length); + + qed_dmae_post_command(p_hwfn, p_ptt); + + qed_status = qed_dmae_operation_wait(p_hwfn); + + if (qed_status) { + DP_NOTICE(p_hwfn, + "qed_dmae_host2grc: Wait Failed. source_addr 0x%llx, grc_addr 0x%llx, size_in_dwords 0x%x\n", + src_addr, + dst_addr, + length); + return qed_status; + } + + if (dst_type == QED_DMAE_ADDRESS_HOST_VIRT) + memcpy((void *)(uintptr_t)(dst_addr), + &p_hwfn->dmae_info.p_intermediate_buffer[0], + length * sizeof(u32)); + + return 0; +} + +static int qed_dmae_execute_command(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u64 src_addr, u64 dst_addr, + u8 src_type, u8 dst_type, + u32 size_in_dwords, + struct qed_dmae_params *p_params) +{ + dma_addr_t phys = p_hwfn->dmae_info.completion_word_phys_addr; + u16 length_cur = 0, i = 0, cnt_split = 0, length_mod = 0; + struct dmae_cmd *cmd = p_hwfn->dmae_info.p_dmae_cmd; + u64 src_addr_split = 0, dst_addr_split = 0; + u16 length_limit = DMAE_MAX_RW_SIZE; + int qed_status = 0; + u32 offset = 0; + + qed_dmae_opcode(p_hwfn, + (src_type == QED_DMAE_ADDRESS_GRC), + (dst_type == QED_DMAE_ADDRESS_GRC), + p_params); + + cmd->comp_addr_lo = cpu_to_le32(lower_32_bits(phys)); + cmd->comp_addr_hi = cpu_to_le32(upper_32_bits(phys)); + cmd->comp_val = cpu_to_le32(DMAE_COMPLETION_VAL); + + /* Check if the grc_addr is valid like < MAX_GRC_OFFSET */ + cnt_split = size_in_dwords / length_limit; + length_mod = size_in_dwords % length_limit; + + src_addr_split = src_addr; + dst_addr_split = dst_addr; + + for (i = 0; i <= cnt_split; i++) { + offset = length_limit * i; + + if (!(p_params->flags & QED_DMAE_FLAG_RW_REPL_SRC)) { + if (src_type == QED_DMAE_ADDRESS_GRC) + src_addr_split = src_addr + offset; + else + src_addr_split = src_addr + (offset * 4); + } + + if (dst_type == QED_DMAE_ADDRESS_GRC) + dst_addr_split = dst_addr + offset; + else + dst_addr_split = dst_addr + (offset * 4); + + length_cur = (cnt_split == i) ? length_mod : length_limit; + + /* might be zero on last iteration */ + if (!length_cur) + continue; + + qed_status = qed_dmae_execute_sub_operation(p_hwfn, + p_ptt, + src_addr_split, + dst_addr_split, + src_type, + dst_type, + length_cur); + if (qed_status) { + DP_NOTICE(p_hwfn, + "qed_dmae_execute_sub_operation Failed with error 0x%x. source_addr 0x%llx, destination addr 0x%llx, size_in_dwords 0x%x\n", + qed_status, + src_addr, + dst_addr, + length_cur); + break; + } + } + + return qed_status; +} + +int qed_dmae_host2grc(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u64 source_addr, + u32 grc_addr, + u32 size_in_dwords, + u32 flags) +{ + u32 grc_addr_in_dw = grc_addr / sizeof(u32); + struct qed_dmae_params params; + int rc; + + memset(¶ms, 0, sizeof(struct qed_dmae_params)); + params.flags = flags; + + mutex_lock(&p_hwfn->dmae_info.mutex); + + rc = qed_dmae_execute_command(p_hwfn, p_ptt, source_addr, + grc_addr_in_dw, + QED_DMAE_ADDRESS_HOST_VIRT, + QED_DMAE_ADDRESS_GRC, + size_in_dwords, ¶ms); + + mutex_unlock(&p_hwfn->dmae_info.mutex); + + return rc; +} + +u16 qed_get_qm_pq(struct qed_hwfn *p_hwfn, + enum protocol_type proto, + union qed_qm_pq_params *p_params) +{ + u16 pq_id = 0; + + if ((proto == PROTOCOLID_CORE || proto == PROTOCOLID_ETH) && + !p_params) { + DP_NOTICE(p_hwfn, + "Protocol %d received NULL PQ params\n", + proto); + return 0; + } + + switch (proto) { + case PROTOCOLID_CORE: + if (p_params->core.tc == LB_TC) + pq_id = p_hwfn->qm_info.pure_lb_pq; + else + pq_id = p_hwfn->qm_info.offload_pq; + break; + case PROTOCOLID_ETH: + pq_id = p_params->eth.tc; + break; + default: + pq_id = 0; + } + + pq_id = CM_TX_PQ_BASE + pq_id + RESC_START(p_hwfn, QED_PQ); + + return pq_id; +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_hw.h b/drivers/net/ethernet/qlogic/qed/qed_hw.h new file mode 100644 index 000000000000..e56d433793be --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_hw.h @@ -0,0 +1,263 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#ifndef _QED_HW_H +#define _QED_HW_H + +#include +#include +#include +#include +#include "qed.h" +#include "qed_dev_api.h" + +/* Forward decleration */ +struct qed_ptt; + +enum reserved_ptts { + RESERVED_PTT_EDIAG, + RESERVED_PTT_USER_SPACE, + RESERVED_PTT_MAIN, + RESERVED_PTT_DPC, + RESERVED_PTT_MAX +}; + +enum _dmae_cmd_dst_mask { + DMAE_CMD_DST_MASK_NONE = 0, + DMAE_CMD_DST_MASK_PCIE = 1, + DMAE_CMD_DST_MASK_GRC = 2 +}; + +enum _dmae_cmd_src_mask { + DMAE_CMD_SRC_MASK_PCIE = 0, + DMAE_CMD_SRC_MASK_GRC = 1 +}; + +enum _dmae_cmd_crc_mask { + DMAE_CMD_COMP_CRC_EN_MASK_NONE = 0, + DMAE_CMD_COMP_CRC_EN_MASK_SET = 1 +}; + +/* definitions for DMA constants */ +#define DMAE_GO_VALUE 0x1 + +#define DMAE_COMPLETION_VAL 0xD1AE +#define DMAE_CMD_ENDIANITY 0x2 + +#define DMAE_CMD_SIZE 14 +#define DMAE_CMD_SIZE_TO_FILL (DMAE_CMD_SIZE - 5) +#define DMAE_MIN_WAIT_TIME 0x2 +#define DMAE_MAX_CLIENTS 32 + +/** + * @brief qed_gtt_init - Initialize GTT windows + * + * @param p_hwfn + */ +void qed_gtt_init(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_ptt_invalidate - Forces all ptt entries to be re-configured + * + * @param p_hwfn + */ +void qed_ptt_invalidate(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_ptt_pool_alloc - Allocate and initialize PTT pool + * + * @param p_hwfn + * + * @return struct _qed_status - success (0), negative - error. + */ +int qed_ptt_pool_alloc(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_ptt_pool_free - + * + * @param p_hwfn + */ +void qed_ptt_pool_free(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_ptt_get_hw_addr - Get PTT's GRC/HW address + * + * @param p_hwfn + * @param p_ptt + * + * @return u32 + */ +u32 qed_ptt_get_hw_addr(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +/** + * @brief qed_ptt_get_bar_addr - Get PPT's external BAR address + * + * @param p_hwfn + * @param p_ptt + * + * @return u32 + */ +u32 qed_ptt_get_bar_addr(struct qed_ptt *p_ptt); + +/** + * @brief qed_ptt_set_win - Set PTT Window's GRC BAR address + * + * @param p_hwfn + * @param new_hw_addr + * @param p_ptt + */ +void qed_ptt_set_win(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 new_hw_addr); + +/** + * @brief qed_get_reserved_ptt - Get a specific reserved PTT + * + * @param p_hwfn + * @param ptt_idx + * + * @return struct qed_ptt * + */ +struct qed_ptt *qed_get_reserved_ptt(struct qed_hwfn *p_hwfn, + enum reserved_ptts ptt_idx); + +/** + * @brief qed_wr - Write value to BAR using the given ptt + * + * @param p_hwfn + * @param p_ptt + * @param val + * @param hw_addr + */ +void qed_wr(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 hw_addr, + u32 val); + +/** + * @brief qed_rd - Read value from BAR using the given ptt + * + * @param p_hwfn + * @param p_ptt + * @param val + * @param hw_addr + */ +u32 qed_rd(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 hw_addr); + +/** + * @brief qed_memcpy_from - copy n bytes from BAR using the given + * ptt + * + * @param p_hwfn + * @param p_ptt + * @param dest + * @param hw_addr + * @param n + */ +void qed_memcpy_from(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + void *dest, + u32 hw_addr, + size_t n); + +/** + * @brief qed_memcpy_to - copy n bytes to BAR using the given + * ptt + * + * @param p_hwfn + * @param p_ptt + * @param hw_addr + * @param src + * @param n + */ +void qed_memcpy_to(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 hw_addr, + void *src, + size_t n); +/** + * @brief qed_fid_pretend - pretend to another function when + * accessing the ptt window. There is no way to unpretend + * a function. The only way to cancel a pretend is to + * pretend back to the original function. + * + * @param p_hwfn + * @param p_ptt + * @param fid - fid field of pxp_pretend structure. Can contain + * either pf / vf, port/path fields are don't care. + */ +void qed_fid_pretend(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u16 fid); + +/** + * @brief qed_port_pretend - pretend to another port when + * accessing the ptt window + * + * @param p_hwfn + * @param p_ptt + * @param port_id - the port to pretend to + */ +void qed_port_pretend(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u8 port_id); + +/** + * @brief qed_port_unpretend - cancel any previously set port + * pretend + * + * @param p_hwfn + * @param p_ptt + */ +void qed_port_unpretend(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +/** + * @brief qed_dmae_idx_to_go_cmd - map the idx to dmae cmd + * this is declared here since other files will require it. + * @param idx + */ +u32 qed_dmae_idx_to_go_cmd(u8 idx); + +/** + * @brief qed_dmae_info_alloc - Init the dmae_info structure + * which is part of p_hwfn. + * @param p_hwfn + */ +int qed_dmae_info_alloc(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_dmae_info_free - Free the dmae_info structure + * which is part of p_hwfn + * + * @param p_hwfn + */ +void qed_dmae_info_free(struct qed_hwfn *p_hwfn); + +union qed_qm_pq_params { + struct { + u8 tc; + } core; + + struct { + u8 is_vf; + u8 vf_id; + u8 tc; + } eth; +}; + +u16 qed_get_qm_pq(struct qed_hwfn *p_hwfn, + enum protocol_type proto, + union qed_qm_pq_params *params); + +int qed_init_fw_data(struct qed_dev *cdev, + const u8 *fw_data); +#endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c new file mode 100644 index 000000000000..0b21a553cc7d --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c @@ -0,0 +1,798 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#include +#include +#include +#include +#include +#include "qed_hsi.h" +#include "qed_hw.h" +#include "qed_init_ops.h" +#include "qed_reg_addr.h" + +enum cminterface { + MCM_SEC, + MCM_PRI, + UCM_SEC, + UCM_PRI, + TCM_SEC, + TCM_PRI, + YCM_SEC, + YCM_PRI, + XCM_SEC, + XCM_PRI, + NUM_OF_CM_INTERFACES +}; + +/* general constants */ +#define QM_PQ_ELEMENT_SIZE 4 /* in bytes */ +#define QM_PQ_MEM_4KB(pq_size) (pq_size ? DIV_ROUND_UP((pq_size + 1) * \ + QM_PQ_ELEMENT_SIZE, \ + 0x1000) : 0) +#define QM_PQ_SIZE_256B(pq_size) (pq_size ? DIV_ROUND_UP(pq_size, \ + 0x100) - 1 : 0) +#define QM_INVALID_PQ_ID 0xffff +/* feature enable */ +#define QM_BYPASS_EN 1 +#define QM_BYTE_CRD_EN 1 +/* other PQ constants */ +#define QM_OTHER_PQS_PER_PF 4 +/* WFQ constants */ +#define QM_WFQ_UPPER_BOUND 6250000 +#define QM_WFQ_VP_PQ_VOQ_SHIFT 0 +#define QM_WFQ_VP_PQ_PF_SHIFT 5 +#define QM_WFQ_INC_VAL(weight) ((weight) * 0x9000) +#define QM_WFQ_MAX_INC_VAL 4375000 +#define QM_WFQ_INIT_CRD(inc_val) (2 * (inc_val)) +/* RL constants */ +#define QM_RL_UPPER_BOUND 6250000 +#define QM_RL_PERIOD 5 /* in us */ +#define QM_RL_PERIOD_CLK_25M (25 * QM_RL_PERIOD) +#define QM_RL_INC_VAL(rate) max_t(u32, \ + (((rate ? rate : 1000000) \ + * QM_RL_PERIOD) / 8), 1) +#define QM_RL_MAX_INC_VAL 4375000 +/* AFullOprtnstcCrdMask constants */ +#define QM_OPPOR_LINE_VOQ_DEF 1 +#define QM_OPPOR_FW_STOP_DEF 0 +#define QM_OPPOR_PQ_EMPTY_DEF 1 +#define EAGLE_WORKAROUND_TC 7 +/* Command Queue constants */ +#define PBF_CMDQ_PURE_LB_LINES 150 +#define PBF_CMDQ_EAGLE_WORKAROUND_LINES 8 +#define PBF_CMDQ_LINES_RT_OFFSET(voq) ( \ + PBF_REG_YCMD_QS_NUM_LINES_VOQ0_RT_OFFSET + voq * \ + (PBF_REG_YCMD_QS_NUM_LINES_VOQ1_RT_OFFSET - \ + PBF_REG_YCMD_QS_NUM_LINES_VOQ0_RT_OFFSET)) +#define PBF_BTB_GUARANTEED_RT_OFFSET(voq) ( \ + PBF_REG_BTB_GUARANTEED_VOQ0_RT_OFFSET + voq * \ + (PBF_REG_BTB_GUARANTEED_VOQ1_RT_OFFSET - \ + PBF_REG_BTB_GUARANTEED_VOQ0_RT_OFFSET)) +#define QM_VOQ_LINE_CRD(pbf_cmd_lines) ((((pbf_cmd_lines) - \ + 4) * \ + 2) | QM_LINE_CRD_REG_SIGN_BIT) +/* BTB: blocks constants (block size = 256B) */ +#define BTB_JUMBO_PKT_BLOCKS 38 +#define BTB_HEADROOM_BLOCKS BTB_JUMBO_PKT_BLOCKS +#define BTB_EAGLE_WORKAROUND_BLOCKS 4 +#define BTB_PURE_LB_FACTOR 10 +#define BTB_PURE_LB_RATIO 7 +/* QM stop command constants */ +#define QM_STOP_PQ_MASK_WIDTH 32 +#define QM_STOP_CMD_ADDR 0x2 +#define QM_STOP_CMD_STRUCT_SIZE 2 +#define QM_STOP_CMD_PAUSE_MASK_OFFSET 0 +#define QM_STOP_CMD_PAUSE_MASK_SHIFT 0 +#define QM_STOP_CMD_PAUSE_MASK_MASK -1 +#define QM_STOP_CMD_GROUP_ID_OFFSET 1 +#define QM_STOP_CMD_GROUP_ID_SHIFT 16 +#define QM_STOP_CMD_GROUP_ID_MASK 15 +#define QM_STOP_CMD_PQ_TYPE_OFFSET 1 +#define QM_STOP_CMD_PQ_TYPE_SHIFT 24 +#define QM_STOP_CMD_PQ_TYPE_MASK 1 +#define QM_STOP_CMD_MAX_POLL_COUNT 100 +#define QM_STOP_CMD_POLL_PERIOD_US 500 +/* QM command macros */ +#define QM_CMD_STRUCT_SIZE(cmd) cmd ## \ + _STRUCT_SIZE +#define QM_CMD_SET_FIELD(var, cmd, field, \ + value) SET_FIELD(var[cmd ## _ ## field ## \ + _OFFSET], \ + cmd ## _ ## field, \ + value) +/* QM: VOQ macros */ +#define PHYS_VOQ(port, tc, max_phy_tcs_pr_port) ((port) * \ + (max_phy_tcs_pr_port) \ + + (tc)) +#define LB_VOQ(port) ( \ + MAX_PHYS_VOQS + (port)) +#define VOQ(port, tc, max_phy_tcs_pr_port) \ + ((tc) < \ + LB_TC ? PHYS_VOQ(port, \ + tc, \ + max_phy_tcs_pr_port) \ + : LB_VOQ(port)) +/******************** INTERNAL IMPLEMENTATION *********************/ +/* Prepare PF RL enable/disable runtime init values */ +static void qed_enable_pf_rl(struct qed_hwfn *p_hwfn, + bool pf_rl_en) +{ + STORE_RT_REG(p_hwfn, QM_REG_RLPFENABLE_RT_OFFSET, pf_rl_en ? 1 : 0); + if (pf_rl_en) { + /* enable RLs for all VOQs */ + STORE_RT_REG(p_hwfn, QM_REG_RLPFVOQENABLE_RT_OFFSET, + (1 << MAX_NUM_VOQS) - 1); + /* write RL period */ + STORE_RT_REG(p_hwfn, + QM_REG_RLPFPERIOD_RT_OFFSET, + QM_RL_PERIOD_CLK_25M); + STORE_RT_REG(p_hwfn, + QM_REG_RLPFPERIODTIMER_RT_OFFSET, + QM_RL_PERIOD_CLK_25M); + /* set credit threshold for QM bypass flow */ + if (QM_BYPASS_EN) + STORE_RT_REG(p_hwfn, + QM_REG_AFULLQMBYPTHRPFRL_RT_OFFSET, + QM_RL_UPPER_BOUND); + } +} + +/* Prepare PF WFQ enable/disable runtime init values */ +static void qed_enable_pf_wfq(struct qed_hwfn *p_hwfn, + bool pf_wfq_en) +{ + STORE_RT_REG(p_hwfn, QM_REG_WFQPFENABLE_RT_OFFSET, pf_wfq_en ? 1 : 0); + /* set credit threshold for QM bypass flow */ + if (pf_wfq_en && QM_BYPASS_EN) + STORE_RT_REG(p_hwfn, + QM_REG_AFULLQMBYPTHRPFWFQ_RT_OFFSET, + QM_WFQ_UPPER_BOUND); +} + +/* Prepare VPORT RL enable/disable runtime init values */ +static void qed_enable_vport_rl(struct qed_hwfn *p_hwfn, + bool vport_rl_en) +{ + STORE_RT_REG(p_hwfn, QM_REG_RLGLBLENABLE_RT_OFFSET, + vport_rl_en ? 1 : 0); + if (vport_rl_en) { + /* write RL period (use timer 0 only) */ + STORE_RT_REG(p_hwfn, + QM_REG_RLGLBLPERIOD_0_RT_OFFSET, + QM_RL_PERIOD_CLK_25M); + STORE_RT_REG(p_hwfn, + QM_REG_RLGLBLPERIODTIMER_0_RT_OFFSET, + QM_RL_PERIOD_CLK_25M); + /* set credit threshold for QM bypass flow */ + if (QM_BYPASS_EN) + STORE_RT_REG(p_hwfn, + QM_REG_AFULLQMBYPTHRGLBLRL_RT_OFFSET, + QM_RL_UPPER_BOUND); + } +} + +/* Prepare VPORT WFQ enable/disable runtime init values */ +static void qed_enable_vport_wfq(struct qed_hwfn *p_hwfn, + bool vport_wfq_en) +{ + STORE_RT_REG(p_hwfn, QM_REG_WFQVPENABLE_RT_OFFSET, + vport_wfq_en ? 1 : 0); + /* set credit threshold for QM bypass flow */ + if (vport_wfq_en && QM_BYPASS_EN) + STORE_RT_REG(p_hwfn, + QM_REG_AFULLQMBYPTHRVPWFQ_RT_OFFSET, + QM_WFQ_UPPER_BOUND); +} + +/* Prepare runtime init values to allocate PBF command queue lines for + * the specified VOQ + */ +static void qed_cmdq_lines_voq_rt_init(struct qed_hwfn *p_hwfn, + u8 voq, + u16 cmdq_lines) +{ + u32 qm_line_crd; + + /* In A0 - Limit the size of pbf queue so that only 511 commands with + * the minimum size of 4 (FCoE minimum size) + */ + bool is_bb_a0 = QED_IS_BB_A0(p_hwfn->cdev); + + if (is_bb_a0) + cmdq_lines = min_t(u32, cmdq_lines, 1022); + qm_line_crd = QM_VOQ_LINE_CRD(cmdq_lines); + OVERWRITE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(voq), + (u32)cmdq_lines); + STORE_RT_REG(p_hwfn, QM_REG_VOQCRDLINE_RT_OFFSET + voq, qm_line_crd); + STORE_RT_REG(p_hwfn, QM_REG_VOQINITCRDLINE_RT_OFFSET + voq, + qm_line_crd); +} + +/* Prepare runtime init values to allocate PBF command queue lines. */ +static void qed_cmdq_lines_rt_init( + struct qed_hwfn *p_hwfn, + u8 max_ports_per_engine, + u8 max_phys_tcs_per_port, + struct init_qm_port_params port_params[MAX_NUM_PORTS]) +{ + u8 tc, voq, port_id; + + /* clear PBF lines for all VOQs */ + for (voq = 0; voq < MAX_NUM_VOQS; voq++) + STORE_RT_REG(p_hwfn, PBF_CMDQ_LINES_RT_OFFSET(voq), 0); + for (port_id = 0; port_id < max_ports_per_engine; port_id++) { + if (port_params[port_id].active) { + u16 phys_lines, phys_lines_per_tc; + u8 phys_tcs = port_params[port_id].num_active_phys_tcs; + + /* find #lines to divide between the active + * physical TCs. + */ + phys_lines = port_params[port_id].num_pbf_cmd_lines - + PBF_CMDQ_PURE_LB_LINES; + /* find #lines per active physical TC */ + phys_lines_per_tc = phys_lines / phys_tcs; + /* init registers per active TC */ + for (tc = 0; tc < phys_tcs; tc++) { + voq = PHYS_VOQ(port_id, tc, + max_phys_tcs_per_port); + qed_cmdq_lines_voq_rt_init(p_hwfn, voq, + phys_lines_per_tc); + } + /* init registers for pure LB TC */ + qed_cmdq_lines_voq_rt_init(p_hwfn, LB_VOQ(port_id), + PBF_CMDQ_PURE_LB_LINES); + } + } +} + +static void qed_btb_blocks_rt_init( + struct qed_hwfn *p_hwfn, + u8 max_ports_per_engine, + u8 max_phys_tcs_per_port, + struct init_qm_port_params port_params[MAX_NUM_PORTS]) +{ + u32 usable_blocks, pure_lb_blocks, phys_blocks; + u8 tc, voq, port_id; + + for (port_id = 0; port_id < max_ports_per_engine; port_id++) { + u32 temp; + u8 phys_tcs; + + if (!port_params[port_id].active) + continue; + + phys_tcs = port_params[port_id].num_active_phys_tcs; + + /* subtract headroom blocks */ + usable_blocks = port_params[port_id].num_btb_blocks - + BTB_HEADROOM_BLOCKS; + + /* find blocks per physical TC. use factor to avoid + * floating arithmethic. + */ + pure_lb_blocks = (usable_blocks * BTB_PURE_LB_FACTOR) / + (phys_tcs * BTB_PURE_LB_FACTOR + + BTB_PURE_LB_RATIO); + pure_lb_blocks = max_t(u32, BTB_JUMBO_PKT_BLOCKS, + pure_lb_blocks / BTB_PURE_LB_FACTOR); + phys_blocks = (usable_blocks - pure_lb_blocks) / phys_tcs; + + /* init physical TCs */ + for (tc = 0; tc < phys_tcs; tc++) { + voq = PHYS_VOQ(port_id, tc, max_phys_tcs_per_port); + STORE_RT_REG(p_hwfn, PBF_BTB_GUARANTEED_RT_OFFSET(voq), + phys_blocks); + } + + /* init pure LB TC */ + temp = LB_VOQ(port_id); + STORE_RT_REG(p_hwfn, PBF_BTB_GUARANTEED_RT_OFFSET(temp), + pure_lb_blocks); + } +} + +/* Prepare Tx PQ mapping runtime init values for the specified PF */ +static void qed_tx_pq_map_rt_init( + struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_qm_pf_rt_init_params *p_params, + u32 base_mem_addr_4kb) +{ + struct init_qm_vport_params *vport_params = p_params->vport_params; + u16 num_pqs = p_params->num_pf_pqs + p_params->num_vf_pqs; + u16 first_pq_group = p_params->start_pq / QM_PF_QUEUE_GROUP_SIZE; + u16 last_pq_group = (p_params->start_pq + num_pqs - 1) / + QM_PF_QUEUE_GROUP_SIZE; + bool is_bb_a0 = QED_IS_BB_A0(p_hwfn->cdev); + u16 i, pq_id, pq_group; + + /* a bit per Tx PQ indicating if the PQ is associated with a VF */ + u32 tx_pq_vf_mask[MAX_QM_TX_QUEUES / QM_PF_QUEUE_GROUP_SIZE] = { 0 }; + u32 tx_pq_vf_mask_width = is_bb_a0 ? 32 : QM_PF_QUEUE_GROUP_SIZE; + u32 num_tx_pq_vf_masks = MAX_QM_TX_QUEUES / tx_pq_vf_mask_width; + u32 pq_mem_4kb = QM_PQ_MEM_4KB(p_params->num_pf_cids); + u32 vport_pq_mem_4kb = QM_PQ_MEM_4KB(p_params->num_vf_cids); + u32 mem_addr_4kb = base_mem_addr_4kb; + + /* set mapping from PQ group to PF */ + for (pq_group = first_pq_group; pq_group <= last_pq_group; pq_group++) + STORE_RT_REG(p_hwfn, QM_REG_PQTX2PF_0_RT_OFFSET + pq_group, + (u32)(p_params->pf_id)); + /* set PQ sizes */ + STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_0_RT_OFFSET, + QM_PQ_SIZE_256B(p_params->num_pf_cids)); + STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_1_RT_OFFSET, + QM_PQ_SIZE_256B(p_params->num_vf_cids)); + + /* go over all Tx PQs */ + for (i = 0, pq_id = p_params->start_pq; i < num_pqs; i++, pq_id++) { + u8 voq = VOQ(p_params->port_id, p_params->pq_params[i].tc_id, + p_params->max_phys_tcs_per_port); + bool is_vf_pq = (i >= p_params->num_pf_pqs); + struct qm_rf_pq_map tx_pq_map; + + /* update first Tx PQ of VPORT/TC */ + u8 vport_id_in_pf = p_params->pq_params[i].vport_id - + p_params->start_vport; + u16 *pq_ids = &vport_params[vport_id_in_pf].first_tx_pq_id[0]; + u16 first_tx_pq_id = pq_ids[p_params->pq_params[i].tc_id]; + + if (first_tx_pq_id == QM_INVALID_PQ_ID) { + /* create new VP PQ */ + pq_ids[p_params->pq_params[i].tc_id] = pq_id; + first_tx_pq_id = pq_id; + /* map VP PQ to VOQ and PF */ + STORE_RT_REG(p_hwfn, + QM_REG_WFQVPMAP_RT_OFFSET + + first_tx_pq_id, + (voq << QM_WFQ_VP_PQ_VOQ_SHIFT) | + (p_params->pf_id << + QM_WFQ_VP_PQ_PF_SHIFT)); + } + /* fill PQ map entry */ + memset(&tx_pq_map, 0, sizeof(tx_pq_map)); + SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_PQ_VALID, 1); + SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_RL_VALID, + is_vf_pq ? 1 : 0); + SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_VP_PQ_ID, first_tx_pq_id); + SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_RL_ID, + is_vf_pq ? p_params->pq_params[i].vport_id : 0); + SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_VOQ, voq); + SET_FIELD(tx_pq_map.reg, QM_RF_PQ_MAP_WRR_WEIGHT_GROUP, + p_params->pq_params[i].wrr_group); + /* write PQ map entry to CAM */ + STORE_RT_REG(p_hwfn, QM_REG_TXPQMAP_RT_OFFSET + pq_id, + *((u32 *)&tx_pq_map)); + /* set base address */ + STORE_RT_REG(p_hwfn, + QM_REG_BASEADDRTXPQ_RT_OFFSET + pq_id, + mem_addr_4kb); + /* check if VF PQ */ + if (is_vf_pq) { + /* if PQ is associated with a VF, add indication + * to PQ VF mask + */ + tx_pq_vf_mask[pq_id / tx_pq_vf_mask_width] |= + (1 << (pq_id % tx_pq_vf_mask_width)); + mem_addr_4kb += vport_pq_mem_4kb; + } else { + mem_addr_4kb += pq_mem_4kb; + } + } + + /* store Tx PQ VF mask to size select register */ + for (i = 0; i < num_tx_pq_vf_masks; i++) { + if (tx_pq_vf_mask[i]) { + if (is_bb_a0) { + u32 curr_mask = 0, addr; + + addr = QM_REG_MAXPQSIZETXSEL_0 + (i * 4); + if (!p_params->is_first_pf) + curr_mask = qed_rd(p_hwfn, p_ptt, + addr); + + addr = QM_REG_MAXPQSIZETXSEL_0_RT_OFFSET + i; + + STORE_RT_REG(p_hwfn, addr, + curr_mask | tx_pq_vf_mask[i]); + } else { + u32 addr; + + addr = QM_REG_MAXPQSIZETXSEL_0_RT_OFFSET + i; + STORE_RT_REG(p_hwfn, addr, + tx_pq_vf_mask[i]); + } + } + } +} + +/* Prepare Other PQ mapping runtime init values for the specified PF */ +static void qed_other_pq_map_rt_init(struct qed_hwfn *p_hwfn, + u8 port_id, + u8 pf_id, + u32 num_pf_cids, + u32 num_tids, + u32 base_mem_addr_4kb) +{ + u16 i, pq_id; + + /* a single other PQ group is used in each PF, + * where PQ group i is used in PF i. + */ + u16 pq_group = pf_id; + u32 pq_size = num_pf_cids + num_tids; + u32 pq_mem_4kb = QM_PQ_MEM_4KB(pq_size); + u32 mem_addr_4kb = base_mem_addr_4kb; + + /* map PQ group to PF */ + STORE_RT_REG(p_hwfn, QM_REG_PQOTHER2PF_0_RT_OFFSET + pq_group, + (u32)(pf_id)); + /* set PQ sizes */ + STORE_RT_REG(p_hwfn, QM_REG_MAXPQSIZE_2_RT_OFFSET, + QM_PQ_SIZE_256B(pq_size)); + /* set base address */ + for (i = 0, pq_id = pf_id * QM_PF_QUEUE_GROUP_SIZE; + i < QM_OTHER_PQS_PER_PF; i++, pq_id++) { + STORE_RT_REG(p_hwfn, + QM_REG_BASEADDROTHERPQ_RT_OFFSET + pq_id, + mem_addr_4kb); + mem_addr_4kb += pq_mem_4kb; + } +} + +/* Prepare PF WFQ runtime init values for the specified PF. + * Return -1 on error. + */ +static int qed_pf_wfq_rt_init(struct qed_hwfn *p_hwfn, + struct qed_qm_pf_rt_init_params *p_params) +{ + u16 num_tx_pqs = p_params->num_pf_pqs + p_params->num_vf_pqs; + u32 crd_reg_offset; + u32 inc_val; + u16 i; + + if (p_params->pf_id < MAX_NUM_PFS_BB) + crd_reg_offset = QM_REG_WFQPFCRD_RT_OFFSET; + else + crd_reg_offset = QM_REG_WFQPFCRD_MSB_RT_OFFSET + + (p_params->pf_id % MAX_NUM_PFS_BB); + + inc_val = QM_WFQ_INC_VAL(p_params->pf_wfq); + if (inc_val > QM_WFQ_MAX_INC_VAL) { + DP_NOTICE(p_hwfn, "Invalid PF WFQ weight configuration"); + return -1; + } + STORE_RT_REG(p_hwfn, QM_REG_WFQPFWEIGHT_RT_OFFSET + p_params->pf_id, + inc_val); + STORE_RT_REG(p_hwfn, + QM_REG_WFQPFUPPERBOUND_RT_OFFSET + p_params->pf_id, + QM_WFQ_UPPER_BOUND | QM_WFQ_CRD_REG_SIGN_BIT); + + for (i = 0; i < num_tx_pqs; i++) { + u8 voq = VOQ(p_params->port_id, p_params->pq_params[i].tc_id, + p_params->max_phys_tcs_per_port); + + OVERWRITE_RT_REG(p_hwfn, + crd_reg_offset + voq * MAX_NUM_PFS_BB, + QM_WFQ_INIT_CRD(inc_val) | + QM_WFQ_CRD_REG_SIGN_BIT); + } + + return 0; +} + +/* Prepare PF RL runtime init values for the specified PF. + * Return -1 on error. + */ +static int qed_pf_rl_rt_init(struct qed_hwfn *p_hwfn, + u8 pf_id, + u32 pf_rl) +{ + u32 inc_val = QM_RL_INC_VAL(pf_rl); + + if (inc_val > QM_RL_MAX_INC_VAL) { + DP_NOTICE(p_hwfn, "Invalid PF rate limit configuration"); + return -1; + } + STORE_RT_REG(p_hwfn, QM_REG_RLPFCRD_RT_OFFSET + pf_id, + QM_RL_CRD_REG_SIGN_BIT); + STORE_RT_REG(p_hwfn, QM_REG_RLPFUPPERBOUND_RT_OFFSET + pf_id, + QM_RL_UPPER_BOUND | QM_RL_CRD_REG_SIGN_BIT); + STORE_RT_REG(p_hwfn, QM_REG_RLPFINCVAL_RT_OFFSET + pf_id, inc_val); + return 0; +} + +/* Prepare VPORT WFQ runtime init values for the specified VPORTs. + * Return -1 on error. + */ +static int qed_vp_wfq_rt_init(struct qed_hwfn *p_hwfn, + u8 start_vport, + u8 num_vports, + struct init_qm_vport_params *vport_params) +{ + u8 tc, i, vport_id; + u32 inc_val; + + /* go over all PF VPORTs */ + for (i = 0, vport_id = start_vport; i < num_vports; i++, vport_id++) { + u32 temp = QM_REG_WFQVPUPPERBOUND_RT_OFFSET; + u16 *pq_ids = &vport_params[i].first_tx_pq_id[0]; + + if (!vport_params[i].vport_wfq) + continue; + + inc_val = QM_WFQ_INC_VAL(vport_params[i].vport_wfq); + if (inc_val > QM_WFQ_MAX_INC_VAL) { + DP_NOTICE(p_hwfn, + "Invalid VPORT WFQ weight configuration"); + return -1; + } + + /* each VPORT can have several VPORT PQ IDs for + * different TCs + */ + for (tc = 0; tc < NUM_OF_TCS; tc++) { + u16 vport_pq_id = pq_ids[tc]; + + if (vport_pq_id != QM_INVALID_PQ_ID) { + STORE_RT_REG(p_hwfn, + QM_REG_WFQVPWEIGHT_RT_OFFSET + + vport_pq_id, inc_val); + STORE_RT_REG(p_hwfn, temp + vport_pq_id, + QM_WFQ_UPPER_BOUND | + QM_WFQ_CRD_REG_SIGN_BIT); + STORE_RT_REG(p_hwfn, + QM_REG_WFQVPCRD_RT_OFFSET + + vport_pq_id, + QM_WFQ_INIT_CRD(inc_val) | + QM_WFQ_CRD_REG_SIGN_BIT); + } + } + } + + return 0; +} + +static int qed_vport_rl_rt_init(struct qed_hwfn *p_hwfn, + u8 start_vport, + u8 num_vports, + struct init_qm_vport_params *vport_params) +{ + u8 i, vport_id; + + /* go over all PF VPORTs */ + for (i = 0, vport_id = start_vport; i < num_vports; i++, vport_id++) { + u32 inc_val = QM_RL_INC_VAL(vport_params[i].vport_rl); + + if (inc_val > QM_RL_MAX_INC_VAL) { + DP_NOTICE(p_hwfn, + "Invalid VPORT rate-limit configuration"); + return -1; + } + + STORE_RT_REG(p_hwfn, + QM_REG_RLGLBLCRD_RT_OFFSET + vport_id, + QM_RL_CRD_REG_SIGN_BIT); + STORE_RT_REG(p_hwfn, + QM_REG_RLGLBLUPPERBOUND_RT_OFFSET + vport_id, + QM_RL_UPPER_BOUND | QM_RL_CRD_REG_SIGN_BIT); + STORE_RT_REG(p_hwfn, + QM_REG_RLGLBLINCVAL_RT_OFFSET + vport_id, + inc_val); + } + + return 0; +} + +static bool qed_poll_on_qm_cmd_ready(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + u32 reg_val, i; + + for (i = 0, reg_val = 0; i < QM_STOP_CMD_MAX_POLL_COUNT && reg_val == 0; + i++) { + udelay(QM_STOP_CMD_POLL_PERIOD_US); + reg_val = qed_rd(p_hwfn, p_ptt, QM_REG_SDMCMDREADY); + } + + /* check if timeout while waiting for SDM command ready */ + if (i == QM_STOP_CMD_MAX_POLL_COUNT) { + DP_VERBOSE(p_hwfn, NETIF_MSG_HW, + "Timeout when waiting for QM SDM command ready signal\n"); + return false; + } + + return true; +} + +static bool qed_send_qm_cmd(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 cmd_addr, + u32 cmd_data_lsb, + u32 cmd_data_msb) +{ + if (!qed_poll_on_qm_cmd_ready(p_hwfn, p_ptt)) + return false; + + qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDADDR, cmd_addr); + qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDDATALSB, cmd_data_lsb); + qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDDATAMSB, cmd_data_msb); + qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDGO, 1); + qed_wr(p_hwfn, p_ptt, QM_REG_SDMCMDGO, 0); + + return qed_poll_on_qm_cmd_ready(p_hwfn, p_ptt); +} + +/******************** INTERFACE IMPLEMENTATION *********************/ +u32 qed_qm_pf_mem_size(u8 pf_id, + u32 num_pf_cids, + u32 num_vf_cids, + u32 num_tids, + u16 num_pf_pqs, + u16 num_vf_pqs) +{ + return QM_PQ_MEM_4KB(num_pf_cids) * num_pf_pqs + + QM_PQ_MEM_4KB(num_vf_cids) * num_vf_pqs + + QM_PQ_MEM_4KB(num_pf_cids + num_tids) * QM_OTHER_PQS_PER_PF; +} + +int qed_qm_common_rt_init( + struct qed_hwfn *p_hwfn, + struct qed_qm_common_rt_init_params *p_params) +{ + /* init AFullOprtnstcCrdMask */ + u32 mask = (QM_OPPOR_LINE_VOQ_DEF << + QM_RF_OPPORTUNISTIC_MASK_LINEVOQ_SHIFT) | + (QM_BYTE_CRD_EN << QM_RF_OPPORTUNISTIC_MASK_BYTEVOQ_SHIFT) | + (p_params->pf_wfq_en << + QM_RF_OPPORTUNISTIC_MASK_PFWFQ_SHIFT) | + (p_params->vport_wfq_en << + QM_RF_OPPORTUNISTIC_MASK_VPWFQ_SHIFT) | + (p_params->pf_rl_en << + QM_RF_OPPORTUNISTIC_MASK_PFRL_SHIFT) | + (p_params->vport_rl_en << + QM_RF_OPPORTUNISTIC_MASK_VPQCNRL_SHIFT) | + (QM_OPPOR_FW_STOP_DEF << + QM_RF_OPPORTUNISTIC_MASK_FWPAUSE_SHIFT) | + (QM_OPPOR_PQ_EMPTY_DEF << + QM_RF_OPPORTUNISTIC_MASK_QUEUEEMPTY_SHIFT); + + STORE_RT_REG(p_hwfn, QM_REG_AFULLOPRTNSTCCRDMASK_RT_OFFSET, mask); + qed_enable_pf_rl(p_hwfn, p_params->pf_rl_en); + qed_enable_pf_wfq(p_hwfn, p_params->pf_wfq_en); + qed_enable_vport_rl(p_hwfn, p_params->vport_rl_en); + qed_enable_vport_wfq(p_hwfn, p_params->vport_wfq_en); + qed_cmdq_lines_rt_init(p_hwfn, + p_params->max_ports_per_engine, + p_params->max_phys_tcs_per_port, + p_params->port_params); + qed_btb_blocks_rt_init(p_hwfn, + p_params->max_ports_per_engine, + p_params->max_phys_tcs_per_port, + p_params->port_params); + return 0; +} + +int qed_qm_pf_rt_init(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_qm_pf_rt_init_params *p_params) +{ + struct init_qm_vport_params *vport_params = p_params->vport_params; + u32 other_mem_size_4kb = QM_PQ_MEM_4KB(p_params->num_pf_cids + + p_params->num_tids) * + QM_OTHER_PQS_PER_PF; + u8 tc, i; + + /* clear first Tx PQ ID array for each VPORT */ + for (i = 0; i < p_params->num_vports; i++) + for (tc = 0; tc < NUM_OF_TCS; tc++) + vport_params[i].first_tx_pq_id[tc] = QM_INVALID_PQ_ID; + + /* map Other PQs (if any) */ + qed_other_pq_map_rt_init(p_hwfn, p_params->port_id, p_params->pf_id, + p_params->num_pf_cids, p_params->num_tids, 0); + + /* map Tx PQs */ + qed_tx_pq_map_rt_init(p_hwfn, p_ptt, p_params, other_mem_size_4kb); + + if (p_params->pf_wfq) + if (qed_pf_wfq_rt_init(p_hwfn, p_params)) + return -1; + + if (qed_pf_rl_rt_init(p_hwfn, p_params->pf_id, p_params->pf_rl)) + return -1; + + if (qed_vp_wfq_rt_init(p_hwfn, p_params->start_vport, + p_params->num_vports, vport_params)) + return -1; + + if (qed_vport_rl_rt_init(p_hwfn, p_params->start_vport, + p_params->num_vports, vport_params)) + return -1; + + return 0; +} + +int qed_init_pf_rl(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u8 pf_id, + u32 pf_rl) +{ + u32 inc_val = QM_RL_INC_VAL(pf_rl); + + if (inc_val > QM_RL_MAX_INC_VAL) { + DP_NOTICE(p_hwfn, "Invalid PF rate limit configuration"); + return -1; + } + + qed_wr(p_hwfn, p_ptt, + QM_REG_RLPFCRD + pf_id * 4, + QM_RL_CRD_REG_SIGN_BIT); + qed_wr(p_hwfn, p_ptt, QM_REG_RLPFINCVAL + pf_id * 4, inc_val); + + return 0; +} + +int qed_init_vport_rl(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u8 vport_id, + u32 vport_rl) +{ + u32 inc_val = QM_RL_INC_VAL(vport_rl); + + if (inc_val > QM_RL_MAX_INC_VAL) { + DP_NOTICE(p_hwfn, "Invalid VPORT rate-limit configuration"); + return -1; + } + + qed_wr(p_hwfn, p_ptt, + QM_REG_RLGLBLCRD + vport_id * 4, + QM_RL_CRD_REG_SIGN_BIT); + qed_wr(p_hwfn, p_ptt, QM_REG_RLGLBLINCVAL + vport_id * 4, inc_val); + + return 0; +} + +bool qed_send_qm_stop_cmd(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + bool is_release_cmd, + bool is_tx_pq, + u16 start_pq, + u16 num_pqs) +{ + u32 cmd_arr[QM_CMD_STRUCT_SIZE(QM_STOP_CMD)] = { 0 }; + u32 pq_mask = 0, last_pq = start_pq + num_pqs - 1, pq_id; + + /* set command's PQ type */ + QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD, PQ_TYPE, is_tx_pq ? 0 : 1); + + for (pq_id = start_pq; pq_id <= last_pq; pq_id++) { + /* set PQ bit in mask (stop command only) */ + if (!is_release_cmd) + pq_mask |= (1 << (pq_id % QM_STOP_PQ_MASK_WIDTH)); + + /* if last PQ or end of PQ mask, write command */ + if ((pq_id == last_pq) || + (pq_id % QM_STOP_PQ_MASK_WIDTH == + (QM_STOP_PQ_MASK_WIDTH - 1))) { + QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD, + PAUSE_MASK, pq_mask); + QM_CMD_SET_FIELD(cmd_arr, QM_STOP_CMD, + GROUP_ID, + pq_id / QM_STOP_PQ_MASK_WIDTH); + if (!qed_send_qm_cmd(p_hwfn, p_ptt, QM_STOP_CMD_ADDR, + cmd_arr[0], cmd_arr[1])) + return false; + pq_mask = 0; + } + } + + return true; +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_ops.c b/drivers/net/ethernet/qlogic/qed/qed_init_ops.c new file mode 100644 index 000000000000..796f1390e598 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_init_ops.c @@ -0,0 +1,531 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "qed.h" +#include "qed_hsi.h" +#include "qed_hw.h" +#include "qed_init_ops.h" +#include "qed_reg_addr.h" + +#define QED_INIT_MAX_POLL_COUNT 100 +#define QED_INIT_POLL_PERIOD_US 500 + +static u32 pxp_global_win[] = { + 0, + 0, + 0x1c02, /* win 2: addr=0x1c02000, size=4096 bytes */ + 0x1c80, /* win 3: addr=0x1c80000, size=4096 bytes */ + 0x1d00, /* win 4: addr=0x1d00000, size=4096 bytes */ + 0x1d01, /* win 5: addr=0x1d01000, size=4096 bytes */ + 0x1d80, /* win 6: addr=0x1d80000, size=4096 bytes */ + 0x1d81, /* win 7: addr=0x1d81000, size=4096 bytes */ + 0x1d82, /* win 8: addr=0x1d82000, size=4096 bytes */ + 0x1e00, /* win 9: addr=0x1e00000, size=4096 bytes */ + 0x1e80, /* win 10: addr=0x1e80000, size=4096 bytes */ + 0x1f00, /* win 11: addr=0x1f00000, size=4096 bytes */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, +}; + +void qed_init_iro_array(struct qed_dev *cdev) +{ + cdev->iro_arr = iro_arr; +} + +/* Runtime configuration helpers */ +void qed_init_clear_rt_data(struct qed_hwfn *p_hwfn) +{ + int i; + + for (i = 0; i < RUNTIME_ARRAY_SIZE; i++) + p_hwfn->rt_data[i].b_valid = false; +} + +void qed_init_store_rt_reg(struct qed_hwfn *p_hwfn, + u32 rt_offset, + u32 val) +{ + p_hwfn->rt_data[rt_offset].init_val = val; + p_hwfn->rt_data[rt_offset].b_valid = true; +} + +void qed_init_store_rt_agg(struct qed_hwfn *p_hwfn, + u32 rt_offset, + u32 *val, + size_t size) +{ + size_t i; + + for (i = 0; i < size / sizeof(u32); i++) { + p_hwfn->rt_data[rt_offset + i].init_val = val[i]; + p_hwfn->rt_data[rt_offset + i].b_valid = true; + } +} + +static void qed_init_rt(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 addr, + u32 rt_offset, + u32 size) +{ + struct qed_rt_data *rt_data = p_hwfn->rt_data + rt_offset; + u32 i; + + for (i = 0; i < size; i++) { + if (!rt_data[i].b_valid) + continue; + qed_wr(p_hwfn, p_ptt, addr + (i << 2), rt_data[i].init_val); + } +} + +int qed_init_alloc(struct qed_hwfn *p_hwfn) +{ + struct qed_rt_data *rt_data; + + rt_data = kzalloc(sizeof(*rt_data) * RUNTIME_ARRAY_SIZE, GFP_ATOMIC); + if (!rt_data) + return -ENOMEM; + + p_hwfn->rt_data = rt_data; + + return 0; +} + +void qed_init_free(struct qed_hwfn *p_hwfn) +{ + kfree(p_hwfn->rt_data); + p_hwfn->rt_data = NULL; +} + +static int qed_init_array_dmae(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 addr, + u32 dmae_data_offset, + u32 size, + const u32 *buf, + bool b_must_dmae, + bool b_can_dmae) +{ + int rc = 0; + + /* Perform DMAE only for lengthy enough sections or for wide-bus */ + if (!b_can_dmae || (!b_must_dmae && (size < 16))) { + const u32 *data = buf + dmae_data_offset; + u32 i; + + for (i = 0; i < size; i++) + qed_wr(p_hwfn, p_ptt, addr + (i << 2), data[i]); + } else { + rc = qed_dmae_host2grc(p_hwfn, p_ptt, + (uintptr_t)(buf + dmae_data_offset), + addr, size, 0); + } + + return rc; +} + +static int qed_init_fill_dmae(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 addr, + u32 fill, + u32 fill_count) +{ + static u32 zero_buffer[DMAE_MAX_RW_SIZE]; + + memset(zero_buffer, 0, sizeof(u32) * DMAE_MAX_RW_SIZE); + + /* invoke the DMAE virtual/physical buffer API with + * 1. DMAE init channel + * 2. addr, + * 3. p_hwfb->temp_data, + * 4. fill_count + */ + + return qed_dmae_host2grc(p_hwfn, p_ptt, + (uintptr_t)(&zero_buffer[0]), + addr, fill_count, + QED_DMAE_FLAG_RW_REPL_SRC); +} + +static void qed_init_fill(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 addr, + u32 fill, + u32 fill_count) +{ + u32 i; + + for (i = 0; i < fill_count; i++, addr += sizeof(u32)) + qed_wr(p_hwfn, p_ptt, addr, fill); +} + +static int qed_init_cmd_array(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct init_write_op *cmd, + bool b_must_dmae, + bool b_can_dmae) +{ + u32 data = le32_to_cpu(cmd->data); + u32 addr = GET_FIELD(data, INIT_WRITE_OP_ADDRESS) << 2; + u32 dmae_array_offset = le32_to_cpu(cmd->args.array_offset); + u32 offset, output_len, input_len, max_size; + struct qed_dev *cdev = p_hwfn->cdev; + union init_array_hdr *hdr; + const u32 *array_data; + int rc = 0; + u32 size; + + array_data = cdev->fw_data->arr_data; + + hdr = (union init_array_hdr *)(array_data + + dmae_array_offset); + data = le32_to_cpu(hdr->raw.data); + switch (GET_FIELD(data, INIT_ARRAY_RAW_HDR_TYPE)) { + case INIT_ARR_ZIPPED: + offset = dmae_array_offset + 1; + input_len = GET_FIELD(data, + INIT_ARRAY_ZIPPED_HDR_ZIPPED_SIZE); + max_size = MAX_ZIPPED_SIZE * 4; + memset(p_hwfn->unzip_buf, 0, max_size); + + output_len = qed_unzip_data(p_hwfn, input_len, + (u8 *)&array_data[offset], + max_size, (u8 *)p_hwfn->unzip_buf); + if (output_len) { + rc = qed_init_array_dmae(p_hwfn, p_ptt, addr, 0, + output_len, + p_hwfn->unzip_buf, + b_must_dmae, b_can_dmae); + } else { + DP_NOTICE(p_hwfn, "Failed to unzip dmae data\n"); + rc = -EINVAL; + } + break; + case INIT_ARR_PATTERN: + { + u32 repeats = GET_FIELD(data, + INIT_ARRAY_PATTERN_HDR_REPETITIONS); + u32 i; + + size = GET_FIELD(data, INIT_ARRAY_PATTERN_HDR_PATTERN_SIZE); + + for (i = 0; i < repeats; i++, addr += size << 2) { + rc = qed_init_array_dmae(p_hwfn, p_ptt, addr, + dmae_array_offset + 1, + size, array_data, + b_must_dmae, b_can_dmae); + if (rc) + break; + } + break; + } + case INIT_ARR_STANDARD: + size = GET_FIELD(data, INIT_ARRAY_STANDARD_HDR_SIZE); + rc = qed_init_array_dmae(p_hwfn, p_ptt, addr, + dmae_array_offset + 1, + size, array_data, + b_must_dmae, b_can_dmae); + break; + } + + return rc; +} + +/* init_ops write command */ +static int qed_init_cmd_wr(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct init_write_op *cmd, + bool b_can_dmae) +{ + u32 data = le32_to_cpu(cmd->data); + u32 addr = GET_FIELD(data, INIT_WRITE_OP_ADDRESS) << 2; + bool b_must_dmae = GET_FIELD(data, INIT_WRITE_OP_WIDE_BUS); + union init_write_args *arg = &cmd->args; + int rc = 0; + + /* Sanitize */ + if (b_must_dmae && !b_can_dmae) { + DP_NOTICE(p_hwfn, + "Need to write to %08x for Wide-bus but DMAE isn't allowed\n", + addr); + return -EINVAL; + } + + switch (GET_FIELD(data, INIT_WRITE_OP_SOURCE)) { + case INIT_SRC_INLINE: + qed_wr(p_hwfn, p_ptt, addr, + le32_to_cpu(arg->inline_val)); + break; + case INIT_SRC_ZEROS: + if (b_must_dmae || + (b_can_dmae && (le32_to_cpu(arg->zeros_count) >= 64))) + rc = qed_init_fill_dmae(p_hwfn, p_ptt, addr, 0, + le32_to_cpu(arg->zeros_count)); + else + qed_init_fill(p_hwfn, p_ptt, addr, 0, + le32_to_cpu(arg->zeros_count)); + break; + case INIT_SRC_ARRAY: + rc = qed_init_cmd_array(p_hwfn, p_ptt, cmd, + b_must_dmae, b_can_dmae); + break; + case INIT_SRC_RUNTIME: + qed_init_rt(p_hwfn, p_ptt, addr, + le16_to_cpu(arg->runtime.offset), + le16_to_cpu(arg->runtime.size)); + break; + } + + return rc; +} + +static inline bool comp_eq(u32 val, u32 expected_val) +{ + return val == expected_val; +} + +static inline bool comp_and(u32 val, u32 expected_val) +{ + return (val & expected_val) == expected_val; +} + +static inline bool comp_or(u32 val, u32 expected_val) +{ + return (val | expected_val) > 0; +} + +/* init_ops read/poll commands */ +static void qed_init_cmd_rd(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct init_read_op *cmd) +{ + u32 data = le32_to_cpu(cmd->op_data); + u32 addr = GET_FIELD(data, INIT_READ_OP_ADDRESS) << 2; + + bool (*comp_check)(u32 val, + u32 expected_val); + u32 delay = QED_INIT_POLL_PERIOD_US, val; + + val = qed_rd(p_hwfn, p_ptt, addr); + + data = le32_to_cpu(cmd->op_data); + if (GET_FIELD(data, INIT_READ_OP_POLL)) { + int i; + + switch (GET_FIELD(data, INIT_READ_OP_POLL_COMP)) { + case INIT_COMPARISON_EQ: + comp_check = comp_eq; + break; + case INIT_COMPARISON_OR: + comp_check = comp_or; + break; + case INIT_COMPARISON_AND: + comp_check = comp_and; + break; + default: + comp_check = NULL; + DP_ERR(p_hwfn, "Invalid poll comparison type %08x\n", + data); + return; + } + + for (i = 0; + i < QED_INIT_MAX_POLL_COUNT && + !comp_check(val, le32_to_cpu(cmd->expected_val)); + i++) { + udelay(delay); + val = qed_rd(p_hwfn, p_ptt, addr); + } + + if (i == QED_INIT_MAX_POLL_COUNT) + DP_ERR(p_hwfn, + "Timeout when polling reg: 0x%08x [ Waiting-for: %08x Got: %08x (comparsion %08x)]\n", + addr, le32_to_cpu(cmd->expected_val), + val, data); + } +} + +/* init_ops callbacks entry point */ +static void qed_init_cmd_cb(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct init_callback_op *p_cmd) +{ + DP_NOTICE(p_hwfn, "Currently init values have no need of callbacks\n"); +} + +static u8 qed_init_cmd_mode_match(struct qed_hwfn *p_hwfn, + u16 *offset, + int modes) +{ + struct qed_dev *cdev = p_hwfn->cdev; + const u8 *modes_tree_buf; + u8 arg1, arg2, tree_val; + + modes_tree_buf = cdev->fw_data->modes_tree_buf; + tree_val = modes_tree_buf[(*offset)++]; + switch (tree_val) { + case INIT_MODE_OP_NOT: + return qed_init_cmd_mode_match(p_hwfn, offset, modes) ^ 1; + case INIT_MODE_OP_OR: + arg1 = qed_init_cmd_mode_match(p_hwfn, offset, modes); + arg2 = qed_init_cmd_mode_match(p_hwfn, offset, modes); + return arg1 | arg2; + case INIT_MODE_OP_AND: + arg1 = qed_init_cmd_mode_match(p_hwfn, offset, modes); + arg2 = qed_init_cmd_mode_match(p_hwfn, offset, modes); + return arg1 & arg2; + default: + tree_val -= MAX_INIT_MODE_OPS; + return (modes & (1 << tree_val)) ? 1 : 0; + } +} + +static u32 qed_init_cmd_mode(struct qed_hwfn *p_hwfn, + struct init_if_mode_op *p_cmd, + int modes) +{ + u16 offset = le16_to_cpu(p_cmd->modes_buf_offset); + + if (qed_init_cmd_mode_match(p_hwfn, &offset, modes)) + return 0; + else + return GET_FIELD(le32_to_cpu(p_cmd->op_data), + INIT_IF_MODE_OP_CMD_OFFSET); +} + +static u32 qed_init_cmd_phase(struct qed_hwfn *p_hwfn, + struct init_if_phase_op *p_cmd, + u32 phase, + u32 phase_id) +{ + u32 data = le32_to_cpu(p_cmd->phase_data); + u32 op_data = le32_to_cpu(p_cmd->op_data); + + if (!(GET_FIELD(data, INIT_IF_PHASE_OP_PHASE) == phase && + (GET_FIELD(data, INIT_IF_PHASE_OP_PHASE_ID) == ANY_PHASE_ID || + GET_FIELD(data, INIT_IF_PHASE_OP_PHASE_ID) == phase_id))) + return GET_FIELD(op_data, INIT_IF_PHASE_OP_CMD_OFFSET); + else + return 0; +} + +int qed_init_run(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + int phase, + int phase_id, + int modes) +{ + struct qed_dev *cdev = p_hwfn->cdev; + u32 cmd_num, num_init_ops; + union init_op *init_ops; + bool b_dmae = false; + int rc = 0; + + num_init_ops = cdev->fw_data->init_ops_size; + init_ops = cdev->fw_data->init_ops; + + p_hwfn->unzip_buf = kzalloc(MAX_ZIPPED_SIZE * 4, GFP_ATOMIC); + if (!p_hwfn->unzip_buf) { + DP_NOTICE(p_hwfn, "Failed to allocate unzip buffer\n"); + return -ENOMEM; + } + + for (cmd_num = 0; cmd_num < num_init_ops; cmd_num++) { + union init_op *cmd = &init_ops[cmd_num]; + u32 data = le32_to_cpu(cmd->raw.op_data); + + switch (GET_FIELD(data, INIT_CALLBACK_OP_OP)) { + case INIT_OP_WRITE: + rc = qed_init_cmd_wr(p_hwfn, p_ptt, &cmd->write, + b_dmae); + break; + case INIT_OP_READ: + qed_init_cmd_rd(p_hwfn, p_ptt, &cmd->read); + break; + case INIT_OP_IF_MODE: + cmd_num += qed_init_cmd_mode(p_hwfn, &cmd->if_mode, + modes); + break; + case INIT_OP_IF_PHASE: + cmd_num += qed_init_cmd_phase(p_hwfn, &cmd->if_phase, + phase, phase_id); + b_dmae = GET_FIELD(data, INIT_IF_PHASE_OP_DMAE_ENABLE); + break; + case INIT_OP_DELAY: + /* qed_init_run is always invoked from + * sleep-able context + */ + udelay(le32_to_cpu(cmd->delay.delay)); + break; + + case INIT_OP_CALLBACK: + qed_init_cmd_cb(p_hwfn, p_ptt, &cmd->callback); + break; + } + + if (rc) + break; + } + + kfree(p_hwfn->unzip_buf); + return rc; +} + +void qed_gtt_init(struct qed_hwfn *p_hwfn) +{ + u32 gtt_base; + u32 i; + + /* Set the global windows */ + gtt_base = PXP_PF_WINDOW_ADMIN_START + PXP_PF_WINDOW_ADMIN_GLOBAL_START; + + for (i = 0; i < ARRAY_SIZE(pxp_global_win); i++) + if (pxp_global_win[i]) + REG_WR(p_hwfn, gtt_base + i * PXP_GLOBAL_ENTRY_SIZE, + pxp_global_win[i]); +} + +int qed_init_fw_data(struct qed_dev *cdev, + const u8 *data) +{ + struct qed_fw_data *fw = cdev->fw_data; + struct bin_buffer_hdr *buf_hdr; + u32 offset, len; + + if (!data) { + DP_NOTICE(cdev, "Invalid fw data\n"); + return -EINVAL; + } + + buf_hdr = (struct bin_buffer_hdr *)data; + + offset = buf_hdr[BIN_BUF_INIT_CMD].offset; + fw->init_ops = (union init_op *)(data + offset); + + offset = buf_hdr[BIN_BUF_INIT_VAL].offset; + fw->arr_data = (u32 *)(data + offset); + + offset = buf_hdr[BIN_BUF_INIT_MODE_TREE].offset; + fw->modes_tree_buf = (u8 *)(data + offset); + len = buf_hdr[BIN_BUF_INIT_CMD].length; + fw->init_ops_size = len / sizeof(struct init_raw_op); + + return 0; +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_ops.h b/drivers/net/ethernet/qlogic/qed/qed_init_ops.h new file mode 100644 index 000000000000..1e832049983d --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_init_ops.h @@ -0,0 +1,110 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#ifndef _QED_INIT_OPS_H +#define _QED_INIT_OPS_H + +#include +#include +#include "qed.h" + +/** + * @brief qed_init_iro_array - init iro_arr. + * + * + * @param cdev + */ +void qed_init_iro_array(struct qed_dev *cdev); + +/** + * @brief qed_init_run - Run the init-sequence. + * + * + * @param p_hwfn + * @param p_ptt + * @param phase + * @param phase_id + * @param modes + * @return _qed_status_t + */ +int qed_init_run(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + int phase, + int phase_id, + int modes); + +/** + * @brief qed_init_hwfn_allocate - Allocate RT array, Store 'values' ptrs. + * + * + * @param p_hwfn + * + * @return _qed_status_t + */ +int qed_init_alloc(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_init_hwfn_deallocate + * + * + * @param p_hwfn + */ +void qed_init_free(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_init_clear_rt_data - Clears the runtime init array. + * + * + * @param p_hwfn + */ +void qed_init_clear_rt_data(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_init_store_rt_reg - Store a configuration value in the RT array. + * + * + * @param p_hwfn + * @param rt_offset + * @param val + */ +void qed_init_store_rt_reg(struct qed_hwfn *p_hwfn, + u32 rt_offset, + u32 val); + +#define STORE_RT_REG(hwfn, offset, val) \ + qed_init_store_rt_reg(hwfn, offset, val) + +#define OVERWRITE_RT_REG(hwfn, offset, val) \ + qed_init_store_rt_reg(hwfn, offset, val) + +/** + * @brief + * + * + * @param p_hwfn + * @param rt_offset + * @param val + * @param size + */ +void qed_init_store_rt_agg(struct qed_hwfn *p_hwfn, + u32 rt_offset, + u32 *val, + size_t size); + +#define STORE_RT_REG_AGG(hwfn, offset, val) \ + qed_init_store_rt_agg(hwfn, offset, (u32 *)&val, sizeof(val)) + +/** + * @brief + * Initialize GTT global windows and set admin window + * related params of GTT/PTT to default values. + * + * @param p_hwfn + */ +void qed_gtt_init(struct qed_hwfn *p_hwfn); +#endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c new file mode 100644 index 000000000000..37d926a5fae5 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c @@ -0,0 +1,802 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qed.h" +#include "qed_hsi.h" +#include "qed_hw.h" +#include "qed_init_ops.h" +#include "qed_int.h" +#include "qed_mcp.h" +#include "qed_reg_addr.h" +#include "qed_sp.h" + +struct qed_pi_info { + qed_int_comp_cb_t comp_cb; + void *cookie; +}; + +struct qed_sb_sp_info { + struct qed_sb_info sb_info; + + /* per protocol index data */ + struct qed_pi_info pi_info_arr[PIS_PER_SB]; +}; + +void qed_int_sp_dpc(unsigned long hwfn_cookie) +{ + struct qed_hwfn *p_hwfn = (struct qed_hwfn *)hwfn_cookie; + struct qed_pi_info *pi_info = NULL; + struct qed_sb_info *sb_info; + int arr_size; + u16 rc = 0; + + if (!p_hwfn) { + DP_ERR(p_hwfn->cdev, "DPC called - no hwfn!\n"); + return; + } + + if (!p_hwfn->p_sp_sb) { + DP_ERR(p_hwfn->cdev, "DPC called - no p_sp_sb\n"); + return; + } + + sb_info = &p_hwfn->p_sp_sb->sb_info; + arr_size = ARRAY_SIZE(p_hwfn->p_sp_sb->pi_info_arr); + if (!sb_info) { + DP_ERR(p_hwfn->cdev, + "Status block is NULL - cannot ack interrupts\n"); + return; + } + + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "DPC Called! (hwfn %p %d)\n", + p_hwfn, p_hwfn->my_id); + + /* Disable ack for def status block. Required both for msix + + * inta in non-mask mode, in inta does no harm. + */ + qed_sb_ack(sb_info, IGU_INT_DISABLE, 0); + + /* Gather Interrupts/Attentions information */ + if (!sb_info->sb_virt) { + DP_ERR( + p_hwfn->cdev, + "Interrupt Status block is NULL - cannot check for new interrupts!\n"); + } else { + u32 tmp_index = sb_info->sb_ack; + + rc = qed_sb_update_sb_idx(sb_info); + DP_VERBOSE(p_hwfn->cdev, NETIF_MSG_INTR, + "Interrupt indices: 0x%08x --> 0x%08x\n", + tmp_index, sb_info->sb_ack); + } + + /* Check if we expect interrupts at this time. if not just ack them */ + if (!(rc & QED_SB_EVENT_MASK)) { + qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); + return; + } + + /* Check the validity of the DPC ptt. If not ack interrupts and fail */ + if (!p_hwfn->p_dpc_ptt) { + DP_NOTICE(p_hwfn->cdev, "Failed to allocate PTT\n"); + qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); + return; + } + + if (rc & QED_SB_IDX) { + int pi; + + /* Look for a free index */ + for (pi = 0; pi < arr_size; pi++) { + pi_info = &p_hwfn->p_sp_sb->pi_info_arr[pi]; + if (pi_info->comp_cb) + pi_info->comp_cb(p_hwfn, pi_info->cookie); + } + } + + qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); +} + +/* coalescing timeout = timeset << (timer_res + 1) */ +#define QED_CAU_DEF_RX_USECS 24 +#define QED_CAU_DEF_TX_USECS 48 + +void qed_init_cau_sb_entry(struct qed_hwfn *p_hwfn, + struct cau_sb_entry *p_sb_entry, + u8 pf_id, + u16 vf_number, + u8 vf_valid) +{ + u32 cau_state; + + memset(p_sb_entry, 0, sizeof(*p_sb_entry)); + + SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_PF_NUMBER, pf_id); + SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_NUMBER, vf_number); + SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_VF_VALID, vf_valid); + SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET0, 0x7F); + SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_SB_TIMESET1, 0x7F); + + /* setting the time resultion to a fixed value ( = 1) */ + SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES0, + QED_CAU_DEF_RX_TIMER_RES); + SET_FIELD(p_sb_entry->params, CAU_SB_ENTRY_TIMER_RES1, + QED_CAU_DEF_TX_TIMER_RES); + + cau_state = CAU_HC_DISABLE_STATE; + + if (p_hwfn->cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) { + cau_state = CAU_HC_ENABLE_STATE; + if (!p_hwfn->cdev->rx_coalesce_usecs) + p_hwfn->cdev->rx_coalesce_usecs = + QED_CAU_DEF_RX_USECS; + if (!p_hwfn->cdev->tx_coalesce_usecs) + p_hwfn->cdev->tx_coalesce_usecs = + QED_CAU_DEF_TX_USECS; + } + + SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE0, cau_state); + SET_FIELD(p_sb_entry->data, CAU_SB_ENTRY_STATE1, cau_state); +} + +void qed_int_cau_conf_sb(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + dma_addr_t sb_phys, + u16 igu_sb_id, + u16 vf_number, + u8 vf_valid) +{ + struct cau_sb_entry sb_entry; + u32 val; + + qed_init_cau_sb_entry(p_hwfn, &sb_entry, p_hwfn->rel_pf_id, + vf_number, vf_valid); + + if (p_hwfn->hw_init_done) { + val = CAU_REG_SB_ADDR_MEMORY + igu_sb_id * sizeof(u64); + qed_wr(p_hwfn, p_ptt, val, lower_32_bits(sb_phys)); + qed_wr(p_hwfn, p_ptt, val + sizeof(u32), + upper_32_bits(sb_phys)); + + val = CAU_REG_SB_VAR_MEMORY + igu_sb_id * sizeof(u64); + qed_wr(p_hwfn, p_ptt, val, sb_entry.data); + qed_wr(p_hwfn, p_ptt, val + sizeof(u32), sb_entry.params); + } else { + /* Initialize Status Block Address */ + STORE_RT_REG_AGG(p_hwfn, + CAU_REG_SB_ADDR_MEMORY_RT_OFFSET + + igu_sb_id * 2, + sb_phys); + + STORE_RT_REG_AGG(p_hwfn, + CAU_REG_SB_VAR_MEMORY_RT_OFFSET + + igu_sb_id * 2, + sb_entry); + } + + /* Configure pi coalescing if set */ + if (p_hwfn->cdev->int_coalescing_mode == QED_COAL_MODE_ENABLE) { + u8 timeset = p_hwfn->cdev->rx_coalesce_usecs >> + (QED_CAU_DEF_RX_TIMER_RES + 1); + u8 num_tc = 1, i; + + qed_int_cau_conf_pi(p_hwfn, p_ptt, igu_sb_id, RX_PI, + QED_COAL_RX_STATE_MACHINE, + timeset); + + timeset = p_hwfn->cdev->tx_coalesce_usecs >> + (QED_CAU_DEF_TX_TIMER_RES + 1); + + for (i = 0; i < num_tc; i++) { + qed_int_cau_conf_pi(p_hwfn, p_ptt, + igu_sb_id, TX_PI(i), + QED_COAL_TX_STATE_MACHINE, + timeset); + } + } +} + +void qed_int_cau_conf_pi(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u16 igu_sb_id, + u32 pi_index, + enum qed_coalescing_fsm coalescing_fsm, + u8 timeset) +{ + struct cau_pi_entry pi_entry; + u32 sb_offset; + u32 pi_offset; + + sb_offset = igu_sb_id * PIS_PER_SB; + memset(&pi_entry, 0, sizeof(struct cau_pi_entry)); + + SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_PI_TIMESET, timeset); + if (coalescing_fsm == QED_COAL_RX_STATE_MACHINE) + SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 0); + else + SET_FIELD(pi_entry.prod, CAU_PI_ENTRY_FSM_SEL, 1); + + pi_offset = sb_offset + pi_index; + if (p_hwfn->hw_init_done) { + qed_wr(p_hwfn, p_ptt, + CAU_REG_PI_MEMORY + pi_offset * sizeof(u32), + *((u32 *)&(pi_entry))); + } else { + STORE_RT_REG(p_hwfn, + CAU_REG_PI_MEMORY_RT_OFFSET + pi_offset, + *((u32 *)&(pi_entry))); + } +} + +void qed_int_sb_setup(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_sb_info *sb_info) +{ + /* zero status block and ack counter */ + sb_info->sb_ack = 0; + memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt)); + + qed_int_cau_conf_sb(p_hwfn, p_ptt, sb_info->sb_phys, + sb_info->igu_sb_id, 0, 0); +} + +/** + * @brief qed_get_igu_sb_id - given a sw sb_id return the + * igu_sb_id + * + * @param p_hwfn + * @param sb_id + * + * @return u16 + */ +static u16 qed_get_igu_sb_id(struct qed_hwfn *p_hwfn, + u16 sb_id) +{ + u16 igu_sb_id; + + /* Assuming continuous set of IGU SBs dedicated for given PF */ + if (sb_id == QED_SP_SB_ID) + igu_sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id; + else + igu_sb_id = sb_id + p_hwfn->hw_info.p_igu_info->igu_base_sb; + + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "SB [%s] index is 0x%04x\n", + (sb_id == QED_SP_SB_ID) ? "DSB" : "non-DSB", igu_sb_id); + + return igu_sb_id; +} + +int qed_int_sb_init(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_sb_info *sb_info, + void *sb_virt_addr, + dma_addr_t sb_phy_addr, + u16 sb_id) +{ + sb_info->sb_virt = sb_virt_addr; + sb_info->sb_phys = sb_phy_addr; + + sb_info->igu_sb_id = qed_get_igu_sb_id(p_hwfn, sb_id); + + if (sb_id != QED_SP_SB_ID) { + p_hwfn->sbs_info[sb_id] = sb_info; + p_hwfn->num_sbs++; + } + + sb_info->cdev = p_hwfn->cdev; + + /* The igu address will hold the absolute address that needs to be + * written to for a specific status block + */ + sb_info->igu_addr = (u8 __iomem *)p_hwfn->regview + + GTT_BAR0_MAP_REG_IGU_CMD + + (sb_info->igu_sb_id << 3); + + sb_info->flags |= QED_SB_INFO_INIT; + + qed_int_sb_setup(p_hwfn, p_ptt, sb_info); + + return 0; +} + +int qed_int_sb_release(struct qed_hwfn *p_hwfn, + struct qed_sb_info *sb_info, + u16 sb_id) +{ + if (sb_id == QED_SP_SB_ID) { + DP_ERR(p_hwfn, "Do Not free sp sb using this function"); + return -EINVAL; + } + + /* zero status block and ack counter */ + sb_info->sb_ack = 0; + memset(sb_info->sb_virt, 0, sizeof(*sb_info->sb_virt)); + + p_hwfn->sbs_info[sb_id] = NULL; + p_hwfn->num_sbs--; + + return 0; +} + +static void qed_int_sp_sb_free(struct qed_hwfn *p_hwfn) +{ + struct qed_sb_sp_info *p_sb = p_hwfn->p_sp_sb; + + if (p_sb) { + if (p_sb->sb_info.sb_virt) + dma_free_coherent(&p_hwfn->cdev->pdev->dev, + SB_ALIGNED_SIZE(p_hwfn), + p_sb->sb_info.sb_virt, + p_sb->sb_info.sb_phys); + kfree(p_sb); + } +} + +static int qed_int_sp_sb_alloc(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + struct qed_sb_sp_info *p_sb; + dma_addr_t p_phys = 0; + void *p_virt; + + /* SB struct */ + p_sb = kmalloc(sizeof(*p_sb), GFP_ATOMIC); + if (!p_sb) { + DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_sb_info'\n"); + return -ENOMEM; + } + + /* SB ring */ + p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, + SB_ALIGNED_SIZE(p_hwfn), + &p_phys, GFP_KERNEL); + if (!p_virt) { + DP_NOTICE(p_hwfn, "Failed to allocate status block\n"); + kfree(p_sb); + return -ENOMEM; + } + + /* Status Block setup */ + p_hwfn->p_sp_sb = p_sb; + qed_int_sb_init(p_hwfn, p_ptt, &p_sb->sb_info, p_virt, + p_phys, QED_SP_SB_ID); + + memset(p_sb->pi_info_arr, 0, sizeof(p_sb->pi_info_arr)); + + return 0; +} + +static void qed_int_sp_sb_setup(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + if (!p_hwfn) + return; + + if (p_hwfn->p_sp_sb) + qed_int_sb_setup(p_hwfn, p_ptt, &p_hwfn->p_sp_sb->sb_info); + else + DP_NOTICE(p_hwfn->cdev, + "Failed to setup Slow path status block - NULL pointer\n"); +} + +int qed_int_register_cb(struct qed_hwfn *p_hwfn, + qed_int_comp_cb_t comp_cb, + void *cookie, + u8 *sb_idx, + __le16 **p_fw_cons) +{ + struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb; + int qed_status = -ENOMEM; + u8 pi; + + /* Look for a free index */ + for (pi = 0; pi < ARRAY_SIZE(p_sp_sb->pi_info_arr); pi++) { + if (!p_sp_sb->pi_info_arr[pi].comp_cb) { + p_sp_sb->pi_info_arr[pi].comp_cb = comp_cb; + p_sp_sb->pi_info_arr[pi].cookie = cookie; + *sb_idx = pi; + *p_fw_cons = &p_sp_sb->sb_info.sb_virt->pi_array[pi]; + qed_status = 0; + break; + } + } + + return qed_status; +} + +int qed_int_unregister_cb(struct qed_hwfn *p_hwfn, u8 pi) +{ + struct qed_sb_sp_info *p_sp_sb = p_hwfn->p_sp_sb; + int qed_status = -ENOMEM; + + if (p_sp_sb->pi_info_arr[pi].comp_cb) { + p_sp_sb->pi_info_arr[pi].comp_cb = NULL; + p_sp_sb->pi_info_arr[pi].cookie = NULL; + qed_status = 0; + } + + return qed_status; +} + +u16 qed_int_get_sp_sb_id(struct qed_hwfn *p_hwfn) +{ + return p_hwfn->p_sp_sb->sb_info.igu_sb_id; +} + +void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_int_mode int_mode) +{ + u32 igu_pf_conf = IGU_PF_CONF_FUNC_EN; + + p_hwfn->cdev->int_mode = int_mode; + switch (p_hwfn->cdev->int_mode) { + case QED_INT_MODE_INTA: + igu_pf_conf |= IGU_PF_CONF_INT_LINE_EN; + igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; + break; + + case QED_INT_MODE_MSI: + igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN; + igu_pf_conf |= IGU_PF_CONF_SINGLE_ISR_EN; + break; + + case QED_INT_MODE_MSIX: + igu_pf_conf |= IGU_PF_CONF_MSI_MSIX_EN; + break; + case QED_INT_MODE_POLL: + break; + } + + qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, igu_pf_conf); +} + +void qed_int_igu_enable(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_int_mode int_mode) +{ + int i; + + p_hwfn->b_int_enabled = 1; + + /* Mask non-link attentions */ + for (i = 0; i < 9; i++) + qed_wr(p_hwfn, p_ptt, + MISC_REG_AEU_ENABLE1_IGU_OUT_0 + (i << 2), 0); + + /* Enable interrupt Generation */ + qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode); + + /* Flush the writes to IGU */ + mmiowb(); +} + +void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + p_hwfn->b_int_enabled = 0; + + qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, 0); +} + +#define IGU_CLEANUP_SLEEP_LENGTH (1000) +void qed_int_igu_cleanup_sb(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 sb_id, + bool cleanup_set, + u16 opaque_fid + ) +{ + u32 pxp_addr = IGU_CMD_INT_ACK_BASE + sb_id; + u32 sleep_cnt = IGU_CLEANUP_SLEEP_LENGTH; + u32 data = 0; + u32 cmd_ctrl = 0; + u32 val = 0; + u32 sb_bit = 0; + u32 sb_bit_addr = 0; + + /* Set the data field */ + SET_FIELD(data, IGU_CLEANUP_CLEANUP_SET, cleanup_set ? 1 : 0); + SET_FIELD(data, IGU_CLEANUP_CLEANUP_TYPE, 0); + SET_FIELD(data, IGU_CLEANUP_COMMAND_TYPE, IGU_COMMAND_TYPE_SET); + + /* Set the control register */ + SET_FIELD(cmd_ctrl, IGU_CTRL_REG_PXP_ADDR, pxp_addr); + SET_FIELD(cmd_ctrl, IGU_CTRL_REG_FID, opaque_fid); + SET_FIELD(cmd_ctrl, IGU_CTRL_REG_TYPE, IGU_CTRL_CMD_TYPE_WR); + + qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_32LSB_DATA, data); + + barrier(); + + qed_wr(p_hwfn, p_ptt, IGU_REG_COMMAND_REG_CTRL, cmd_ctrl); + + /* Flush the write to IGU */ + mmiowb(); + + /* calculate where to read the status bit from */ + sb_bit = 1 << (sb_id % 32); + sb_bit_addr = sb_id / 32 * sizeof(u32); + + sb_bit_addr += IGU_REG_CLEANUP_STATUS_0; + + /* Now wait for the command to complete */ + do { + val = qed_rd(p_hwfn, p_ptt, sb_bit_addr); + + if ((val & sb_bit) == (cleanup_set ? sb_bit : 0)) + break; + + usleep_range(5000, 10000); + } while (--sleep_cnt); + + if (!sleep_cnt) + DP_NOTICE(p_hwfn, + "Timeout waiting for clear status 0x%08x [for sb %d]\n", + val, sb_id); +} + +void qed_int_igu_init_pure_rt_single(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 sb_id, + u16 opaque, + bool b_set) +{ + int pi; + + /* Set */ + if (b_set) + qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 1, opaque); + + /* Clear */ + qed_int_igu_cleanup_sb(p_hwfn, p_ptt, sb_id, 0, opaque); + + /* Clear the CAU for the SB */ + for (pi = 0; pi < 12; pi++) + qed_wr(p_hwfn, p_ptt, + CAU_REG_PI_MEMORY + (sb_id * 12 + pi) * 4, 0); +} + +void qed_int_igu_init_pure_rt(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + bool b_set, + bool b_slowpath) +{ + u32 igu_base_sb = p_hwfn->hw_info.p_igu_info->igu_base_sb; + u32 igu_sb_cnt = p_hwfn->hw_info.p_igu_info->igu_sb_cnt; + u32 sb_id = 0; + u32 val = 0; + + val = qed_rd(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION); + val |= IGU_REG_BLOCK_CONFIGURATION_VF_CLEANUP_EN; + val &= ~IGU_REG_BLOCK_CONFIGURATION_PXP_TPH_INTERFACE_EN; + qed_wr(p_hwfn, p_ptt, IGU_REG_BLOCK_CONFIGURATION, val); + + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, + "IGU cleaning SBs [%d,...,%d]\n", + igu_base_sb, igu_base_sb + igu_sb_cnt - 1); + + for (sb_id = igu_base_sb; sb_id < igu_base_sb + igu_sb_cnt; sb_id++) + qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id, + p_hwfn->hw_info.opaque_fid, + b_set); + + if (b_slowpath) { + sb_id = p_hwfn->hw_info.p_igu_info->igu_dsb_id; + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, + "IGU cleaning slowpath SB [%d]\n", sb_id); + qed_int_igu_init_pure_rt_single(p_hwfn, p_ptt, sb_id, + p_hwfn->hw_info.opaque_fid, + b_set); + } +} + +int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + struct qed_igu_info *p_igu_info; + struct qed_igu_block *blk; + u32 val; + u16 sb_id; + u16 prev_sb_id = 0xFF; + + p_hwfn->hw_info.p_igu_info = kzalloc(sizeof(*p_igu_info), GFP_ATOMIC); + + if (!p_hwfn->hw_info.p_igu_info) + return -ENOMEM; + + p_igu_info = p_hwfn->hw_info.p_igu_info; + + /* Initialize base sb / sb cnt for PFs */ + p_igu_info->igu_base_sb = 0xffff; + p_igu_info->igu_sb_cnt = 0; + p_igu_info->igu_dsb_id = 0xffff; + p_igu_info->igu_base_sb_iov = 0xffff; + + for (sb_id = 0; sb_id < QED_MAPPING_MEMORY_SIZE(p_hwfn->cdev); + sb_id++) { + blk = &p_igu_info->igu_map.igu_blocks[sb_id]; + + val = qed_rd(p_hwfn, p_ptt, + IGU_REG_MAPPING_MEMORY + sizeof(u32) * sb_id); + + /* stop scanning when hit first invalid PF entry */ + if (!GET_FIELD(val, IGU_MAPPING_LINE_VALID) && + GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID)) + break; + + blk->status = QED_IGU_STATUS_VALID; + blk->function_id = GET_FIELD(val, + IGU_MAPPING_LINE_FUNCTION_NUMBER); + blk->is_pf = GET_FIELD(val, IGU_MAPPING_LINE_PF_VALID); + blk->vector_number = GET_FIELD(val, + IGU_MAPPING_LINE_VECTOR_NUMBER); + + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, + "IGU_BLOCK[sb_id]:%x:func_id = %d is_pf = %d vector_num = 0x%x\n", + val, blk->function_id, blk->is_pf, + blk->vector_number); + + if (blk->is_pf) { + if (blk->function_id == p_hwfn->rel_pf_id) { + blk->status |= QED_IGU_STATUS_PF; + + if (blk->vector_number == 0) { + if (p_igu_info->igu_dsb_id == 0xffff) + p_igu_info->igu_dsb_id = sb_id; + } else { + if (p_igu_info->igu_base_sb == + 0xffff) { + p_igu_info->igu_base_sb = sb_id; + } else if (prev_sb_id != sb_id - 1) { + DP_NOTICE(p_hwfn->cdev, + "consecutive igu vectors for HWFN %x broken", + p_hwfn->rel_pf_id); + break; + } + prev_sb_id = sb_id; + /* we don't count the default */ + (p_igu_info->igu_sb_cnt)++; + } + } + } + } + + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, + "IGU igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", + p_igu_info->igu_base_sb, + p_igu_info->igu_sb_cnt, + p_igu_info->igu_dsb_id); + + if (p_igu_info->igu_base_sb == 0xffff || + p_igu_info->igu_dsb_id == 0xffff || + p_igu_info->igu_sb_cnt == 0) { + DP_NOTICE(p_hwfn, + "IGU CAM returned invalid values igu_base_sb=0x%x igu_sb_cnt=%d igu_dsb_id=0x%x\n", + p_igu_info->igu_base_sb, + p_igu_info->igu_sb_cnt, + p_igu_info->igu_dsb_id); + return -EINVAL; + } + + return 0; +} + +/** + * @brief Initialize igu runtime registers + * + * @param p_hwfn + */ +void qed_int_igu_init_rt(struct qed_hwfn *p_hwfn) +{ + u32 igu_pf_conf = 0; + + igu_pf_conf |= IGU_PF_CONF_FUNC_EN; + + STORE_RT_REG(p_hwfn, IGU_REG_PF_CONFIGURATION_RT_OFFSET, igu_pf_conf); +} + +u64 qed_int_igu_read_sisr_reg(struct qed_hwfn *p_hwfn) +{ + u64 intr_status = 0; + u32 intr_status_lo = 0; + u32 intr_status_hi = 0; + u32 lsb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_LSB_UPPER - + IGU_CMD_INT_ACK_BASE; + u32 msb_igu_cmd_addr = IGU_REG_SISR_MDPC_WMASK_MSB_UPPER - + IGU_CMD_INT_ACK_BASE; + + intr_status_lo = REG_RD(p_hwfn, + GTT_BAR0_MAP_REG_IGU_CMD + + lsb_igu_cmd_addr * 8); + intr_status_hi = REG_RD(p_hwfn, + GTT_BAR0_MAP_REG_IGU_CMD + + msb_igu_cmd_addr * 8); + intr_status = ((u64)intr_status_hi << 32) + (u64)intr_status_lo; + + return intr_status; +} + +static void qed_int_sp_dpc_setup(struct qed_hwfn *p_hwfn) +{ + tasklet_init(p_hwfn->sp_dpc, + qed_int_sp_dpc, (unsigned long)p_hwfn); + p_hwfn->b_sp_dpc_enabled = true; +} + +static int qed_int_sp_dpc_alloc(struct qed_hwfn *p_hwfn) +{ + p_hwfn->sp_dpc = kmalloc(sizeof(*p_hwfn->sp_dpc), GFP_ATOMIC); + if (!p_hwfn->sp_dpc) + return -ENOMEM; + + return 0; +} + +static void qed_int_sp_dpc_free(struct qed_hwfn *p_hwfn) +{ + kfree(p_hwfn->sp_dpc); +} + +int qed_int_alloc(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + int rc = 0; + + rc = qed_int_sp_dpc_alloc(p_hwfn); + if (rc) { + DP_ERR(p_hwfn->cdev, "Failed to allocate sp dpc mem\n"); + return rc; + } + rc = qed_int_sp_sb_alloc(p_hwfn, p_ptt); + if (rc) { + DP_ERR(p_hwfn->cdev, "Failed to allocate sp sb mem\n"); + return rc; + } + + return rc; +} + +void qed_int_free(struct qed_hwfn *p_hwfn) +{ + qed_int_sp_sb_free(p_hwfn); + qed_int_sp_dpc_free(p_hwfn); +} + +void qed_int_setup(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + qed_int_sp_sb_setup(p_hwfn, p_ptt); + qed_int_sp_dpc_setup(p_hwfn); +} + +int qed_int_get_num_sbs(struct qed_hwfn *p_hwfn, + int *p_iov_blks) +{ + struct qed_igu_info *info = p_hwfn->hw_info.p_igu_info; + + if (!info) + return 0; + + if (p_iov_blks) + *p_iov_blks = info->free_blks; + + return info->igu_sb_cnt; +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.h b/drivers/net/ethernet/qlogic/qed/qed_int.h new file mode 100644 index 000000000000..16b57518e706 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_int.h @@ -0,0 +1,391 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#ifndef _QED_INT_H +#define _QED_INT_H + +#include +#include +#include "qed.h" + +/* Fields of IGU PF CONFIGRATION REGISTER */ +#define IGU_PF_CONF_FUNC_EN (0x1 << 0) /* function enable */ +#define IGU_PF_CONF_MSI_MSIX_EN (0x1 << 1) /* MSI/MSIX enable */ +#define IGU_PF_CONF_INT_LINE_EN (0x1 << 2) /* INT enable */ +#define IGU_PF_CONF_ATTN_BIT_EN (0x1 << 3) /* attention enable */ +#define IGU_PF_CONF_SINGLE_ISR_EN (0x1 << 4) /* single ISR mode enable */ +#define IGU_PF_CONF_SIMD_MODE (0x1 << 5) /* simd all ones mode */ + +/* Igu control commands + */ +enum igu_ctrl_cmd { + IGU_CTRL_CMD_TYPE_RD, + IGU_CTRL_CMD_TYPE_WR, + MAX_IGU_CTRL_CMD +}; + +/* Control register for the IGU command register + */ +struct igu_ctrl_reg { + u32 ctrl_data; +#define IGU_CTRL_REG_FID_MASK 0xFFFF /* Opaque_FID */ +#define IGU_CTRL_REG_FID_SHIFT 0 +#define IGU_CTRL_REG_PXP_ADDR_MASK 0xFFF /* Command address */ +#define IGU_CTRL_REG_PXP_ADDR_SHIFT 16 +#define IGU_CTRL_REG_RESERVED_MASK 0x1 +#define IGU_CTRL_REG_RESERVED_SHIFT 28 +#define IGU_CTRL_REG_TYPE_MASK 0x1 /* use enum igu_ctrl_cmd */ +#define IGU_CTRL_REG_TYPE_SHIFT 31 +}; + +enum qed_coalescing_fsm { + QED_COAL_RX_STATE_MACHINE, + QED_COAL_TX_STATE_MACHINE +}; + +/** + * @brief qed_int_cau_conf_pi - configure cau for a given + * status block + * + * @param p_hwfn + * @param p_ptt + * @param igu_sb_id + * @param pi_index + * @param state + * @param timeset + */ +void qed_int_cau_conf_pi(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u16 igu_sb_id, + u32 pi_index, + enum qed_coalescing_fsm coalescing_fsm, + u8 timeset); + +/** + * @brief qed_int_igu_enable_int - enable device interrupts + * + * @param p_hwfn + * @param p_ptt + * @param int_mode - interrupt mode to use + */ +void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_int_mode int_mode); + +/** + * @brief qed_int_igu_disable_int - disable device interrupts + * + * @param p_hwfn + * @param p_ptt + */ +void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +/** + * @brief qed_int_igu_read_sisr_reg - Reads the single isr multiple dpc + * register from igu. + * + * @param p_hwfn + * + * @return u64 + */ +u64 qed_int_igu_read_sisr_reg(struct qed_hwfn *p_hwfn); + +#define QED_SP_SB_ID 0xffff +/** + * @brief qed_int_sb_init - Initializes the sb_info structure. + * + * once the structure is initialized it can be passed to sb related functions. + * + * @param p_hwfn + * @param p_ptt + * @param sb_info points to an uninitialized (but + * allocated) sb_info structure + * @param sb_virt_addr + * @param sb_phy_addr + * @param sb_id the sb_id to be used (zero based in driver) + * should use QED_SP_SB_ID for SP Status block + * + * @return int + */ +int qed_int_sb_init(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_sb_info *sb_info, + void *sb_virt_addr, + dma_addr_t sb_phy_addr, + u16 sb_id); +/** + * @brief qed_int_sb_setup - Setup the sb. + * + * @param p_hwfn + * @param p_ptt + * @param sb_info initialized sb_info structure + */ +void qed_int_sb_setup(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_sb_info *sb_info); + +/** + * @brief qed_int_sb_release - releases the sb_info structure. + * + * once the structure is released, it's memory can be freed + * + * @param p_hwfn + * @param sb_info points to an allocated sb_info structure + * @param sb_id the sb_id to be used (zero based in driver) + * should never be equal to QED_SP_SB_ID + * (SP Status block) + * + * @return int + */ +int qed_int_sb_release(struct qed_hwfn *p_hwfn, + struct qed_sb_info *sb_info, + u16 sb_id); + +/** + * @brief qed_int_sp_dpc - To be called when an interrupt is received on the + * default status block. + * + * @param p_hwfn - pointer to hwfn + * + */ +void qed_int_sp_dpc(unsigned long hwfn_cookie); + +/** + * @brief qed_int_get_num_sbs - get the number of status + * blocks configured for this funciton in the igu. + * + * @param p_hwfn + * @param p_iov_blks - configured free blks for vfs + * + * @return int - number of status blocks configured + */ +int qed_int_get_num_sbs(struct qed_hwfn *p_hwfn, + int *p_iov_blks); + +/** + * @file + * + * @brief Interrupt handler + */ + +#define QED_CAU_DEF_RX_TIMER_RES 0 +#define QED_CAU_DEF_TX_TIMER_RES 0 + +#define QED_SB_ATT_IDX 0x0001 +#define QED_SB_EVENT_MASK 0x0003 + +#define SB_ALIGNED_SIZE(p_hwfn) \ + ALIGNED_TYPE_SIZE(struct status_block, p_hwfn) + +struct qed_igu_block { + u8 status; +#define QED_IGU_STATUS_FREE 0x01 +#define QED_IGU_STATUS_VALID 0x02 +#define QED_IGU_STATUS_PF 0x04 + + u8 vector_number; + u8 function_id; + u8 is_pf; +}; + +struct qed_igu_map { + struct qed_igu_block igu_blocks[MAX_TOT_SB_PER_PATH]; +}; + +struct qed_igu_info { + struct qed_igu_map igu_map; + u16 igu_dsb_id; + u16 igu_base_sb; + u16 igu_base_sb_iov; + u16 igu_sb_cnt; + u16 igu_sb_cnt_iov; + u16 free_blks; +}; + +/* TODO Names of function may change... */ +void qed_int_igu_init_pure_rt(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + bool b_set, + bool b_slowpath); + +void qed_int_igu_init_rt(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_int_igu_read_cam - Reads the IGU CAM. + * This function needs to be called during hardware + * prepare. It reads the info from igu cam to know which + * status block is the default / base status block etc. + * + * @param p_hwfn + * @param p_ptt + * + * @return int + */ +int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +typedef int (*qed_int_comp_cb_t)(struct qed_hwfn *p_hwfn, + void *cookie); +/** + * @brief qed_int_register_cb - Register callback func for + * slowhwfn statusblock. + * + * Every protocol that uses the slowhwfn status block + * should register a callback function that will be called + * once there is an update of the sp status block. + * + * @param p_hwfn + * @param comp_cb - function to be called when there is an + * interrupt on the sp sb + * + * @param cookie - passed to the callback function + * @param sb_idx - OUT parameter which gives the chosen index + * for this protocol. + * @param p_fw_cons - pointer to the actual address of the + * consumer for this protocol. + * + * @return int + */ +int qed_int_register_cb(struct qed_hwfn *p_hwfn, + qed_int_comp_cb_t comp_cb, + void *cookie, + u8 *sb_idx, + __le16 **p_fw_cons); + +/** + * @brief qed_int_unregister_cb - Unregisters callback + * function from sp sb. + * Partner of qed_int_register_cb -> should be called + * when no longer required. + * + * @param p_hwfn + * @param pi + * + * @return int + */ +int qed_int_unregister_cb(struct qed_hwfn *p_hwfn, + u8 pi); + +/** + * @brief qed_int_get_sp_sb_id - Get the slowhwfn sb id. + * + * @param p_hwfn + * + * @return u16 + */ +u16 qed_int_get_sp_sb_id(struct qed_hwfn *p_hwfn); + +/** + * @brief Status block cleanup. Should be called for each status + * block that will be used -> both PF / VF + * + * @param p_hwfn + * @param p_ptt + * @param sb_id - igu status block id + * @param cleanup_set - set(1) / clear(0) + * @param opaque_fid - the function for which to perform + * cleanup, for example a PF on behalf of + * its VFs. + */ +void qed_int_igu_cleanup_sb(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 sb_id, + bool cleanup_set, + u16 opaque_fid); + +/** + * @brief Status block cleanup. Should be called for each status + * block that will be used -> both PF / VF + * + * @param p_hwfn + * @param p_ptt + * @param sb_id - igu status block id + * @param opaque - opaque fid of the sb owner. + * @param cleanup_set - set(1) / clear(0) + */ +void qed_int_igu_init_pure_rt_single(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 sb_id, + u16 opaque, + bool b_set); + +/** + * @brief qed_int_cau_conf - configure cau for a given status + * block + * + * @param p_hwfn + * @param ptt + * @param sb_phys + * @param igu_sb_id + * @param vf_number + * @param vf_valid + */ +void qed_int_cau_conf_sb(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + dma_addr_t sb_phys, + u16 igu_sb_id, + u16 vf_number, + u8 vf_valid); + +/** + * @brief qed_int_alloc + * + * @param p_hwfn + * @param p_ptt + * + * @return int + */ +int qed_int_alloc(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +/** + * @brief qed_int_free + * + * @param p_hwfn + */ +void qed_int_free(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_int_setup + * + * @param p_hwfn + * @param p_ptt + */ +void qed_int_setup(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +/** + * @brief - Enable Interrupt & Attention for hw function + * + * @param p_hwfn + * @param p_ptt + * @param int_mode + */ +void qed_int_igu_enable(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + enum qed_int_mode int_mode); + +/** + * @brief - Initialize CAU status block entry + * + * @param p_hwfn + * @param p_sb_entry + * @param pf_id + * @param vf_number + * @param vf_valid + */ +void qed_init_cau_sb_entry(struct qed_hwfn *p_hwfn, + struct cau_sb_entry *p_sb_entry, + u8 pf_id, + u16 vf_number, + u8 vf_valid); + +#define QED_MAPPING_MEMORY_SIZE(dev) (NUM_OF_SBS(dev)) + +#endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c new file mode 100644 index 000000000000..d0b1ff0ca3c8 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -0,0 +1,948 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qed.h" +#include "qed_sp.h" +#include "qed_dev_api.h" +#include "qed_mcp.h" +#include "qed_hw.h" + +static const char version[] = + "QLogic QL4xxx 40G/100G Ethernet Driver qed " DRV_MODULE_VERSION "\n"; + +MODULE_DESCRIPTION("QLogic 25G/40G/50G/100G Core Module"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_MODULE_VERSION); + +#define FW_FILE_VERSION \ + __stringify(FW_MAJOR_VERSION) "." \ + __stringify(FW_MINOR_VERSION) "." \ + __stringify(FW_REVISION_VERSION) "." \ + __stringify(FW_ENGINEERING_VERSION) + +#define QED_FW_FILE_NAME \ + "qed/qed_init_values_zipped-" FW_FILE_VERSION ".bin" + +static int __init qed_init(void) +{ + pr_notice("qed_init called\n"); + + pr_info("%s", version); + + return 0; +} + +static void __exit qed_cleanup(void) +{ + pr_notice("qed_cleanup called\n"); +} + +module_init(qed_init); +module_exit(qed_cleanup); + +/* Check if the DMA controller on the machine can properly handle the DMA + * addressing required by the device. +*/ +static int qed_set_coherency_mask(struct qed_dev *cdev) +{ + struct device *dev = &cdev->pdev->dev; + + if (dma_set_mask(dev, DMA_BIT_MASK(64)) == 0) { + if (dma_set_coherent_mask(dev, DMA_BIT_MASK(64)) != 0) { + DP_NOTICE(cdev, + "Can't request 64-bit consistent allocations\n"); + return -EIO; + } + } else if (dma_set_mask(dev, DMA_BIT_MASK(32)) != 0) { + DP_NOTICE(cdev, "Can't request 64b/32b DMA addresses\n"); + return -EIO; + } + + return 0; +} + +static void qed_free_pci(struct qed_dev *cdev) +{ + struct pci_dev *pdev = cdev->pdev; + + if (cdev->doorbells) + iounmap(cdev->doorbells); + if (cdev->regview) + iounmap(cdev->regview); + if (atomic_read(&pdev->enable_cnt) == 1) + pci_release_regions(pdev); + + pci_disable_device(pdev); +} + +/* Performs PCI initializations as well as initializing PCI-related parameters + * in the device structrue. Returns 0 in case of success. + */ +static int qed_init_pci(struct qed_dev *cdev, + struct pci_dev *pdev) +{ + int rc; + + cdev->pdev = pdev; + + rc = pci_enable_device(pdev); + if (rc) { + DP_NOTICE(cdev, "Cannot enable PCI device\n"); + goto err0; + } + + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { + DP_NOTICE(cdev, "No memory region found in bar #0\n"); + rc = -EIO; + goto err1; + } + + if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { + DP_NOTICE(cdev, "No memory region found in bar #2\n"); + rc = -EIO; + goto err1; + } + + if (atomic_read(&pdev->enable_cnt) == 1) { + rc = pci_request_regions(pdev, "qed"); + if (rc) { + DP_NOTICE(cdev, + "Failed to request PCI memory resources\n"); + goto err1; + } + pci_set_master(pdev); + pci_save_state(pdev); + } + + if (!pci_is_pcie(pdev)) { + DP_NOTICE(cdev, "The bus is not PCI Express\n"); + rc = -EIO; + goto err2; + } + + cdev->pci_params.pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); + if (cdev->pci_params.pm_cap == 0) + DP_NOTICE(cdev, "Cannot find power management capability\n"); + + rc = qed_set_coherency_mask(cdev); + if (rc) + goto err2; + + cdev->pci_params.mem_start = pci_resource_start(pdev, 0); + cdev->pci_params.mem_end = pci_resource_end(pdev, 0); + cdev->pci_params.irq = pdev->irq; + + cdev->regview = pci_ioremap_bar(pdev, 0); + if (!cdev->regview) { + DP_NOTICE(cdev, "Cannot map register space, aborting\n"); + rc = -ENOMEM; + goto err2; + } + + cdev->db_phys_addr = pci_resource_start(cdev->pdev, 2); + cdev->db_size = pci_resource_len(cdev->pdev, 2); + cdev->doorbells = ioremap_wc(cdev->db_phys_addr, cdev->db_size); + if (!cdev->doorbells) { + DP_NOTICE(cdev, "Cannot map doorbell space\n"); + return -ENOMEM; + } + + return 0; + +err2: + pci_release_regions(pdev); +err1: + pci_disable_device(pdev); +err0: + return rc; +} + +int qed_fill_dev_info(struct qed_dev *cdev, + struct qed_dev_info *dev_info) +{ + memset(dev_info, 0, sizeof(struct qed_dev_info)); + + dev_info->num_hwfns = cdev->num_hwfns; + dev_info->pci_mem_start = cdev->pci_params.mem_start; + dev_info->pci_mem_end = cdev->pci_params.mem_end; + dev_info->pci_irq = cdev->pci_params.irq; + dev_info->is_mf = IS_MF(&cdev->hwfns[0]); + ether_addr_copy(dev_info->hw_mac, cdev->hwfns[0].hw_info.hw_mac_addr); + + dev_info->fw_major = FW_MAJOR_VERSION; + dev_info->fw_minor = FW_MINOR_VERSION; + dev_info->fw_rev = FW_REVISION_VERSION; + dev_info->fw_eng = FW_ENGINEERING_VERSION; + dev_info->mf_mode = cdev->mf_mode; + + qed_mcp_get_mfw_ver(cdev, &dev_info->mfw_rev); + + return 0; +} + +static void qed_free_cdev(struct qed_dev *cdev) +{ + kfree((void *)cdev); +} + +static struct qed_dev *qed_alloc_cdev(struct pci_dev *pdev) +{ + struct qed_dev *cdev; + + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); + if (!cdev) + return cdev; + + qed_init_struct(cdev); + + return cdev; +} + +/* Sets the requested power state */ +static int qed_set_power_state(struct qed_dev *cdev, + pci_power_t state) +{ + if (!cdev) + return -ENODEV; + + DP_VERBOSE(cdev, NETIF_MSG_DRV, "Omitting Power state change\n"); + return 0; +} + +/* probing */ +static struct qed_dev *qed_probe(struct pci_dev *pdev, + enum qed_protocol protocol, + u32 dp_module, + u8 dp_level) +{ + struct qed_dev *cdev; + int rc; + + cdev = qed_alloc_cdev(pdev); + if (!cdev) + goto err0; + + cdev->protocol = protocol; + + qed_init_dp(cdev, dp_module, dp_level); + + rc = qed_init_pci(cdev, pdev); + if (rc) { + DP_ERR(cdev, "init pci failed\n"); + goto err1; + } + DP_INFO(cdev, "PCI init completed successfully\n"); + + rc = qed_hw_prepare(cdev, QED_PCI_DEFAULT); + if (rc) { + DP_ERR(cdev, "hw prepare failed\n"); + goto err2; + } + + DP_INFO(cdev, "qed_probe completed successffuly\n"); + + return cdev; + +err2: + qed_free_pci(cdev); +err1: + qed_free_cdev(cdev); +err0: + return NULL; +} + +static void qed_remove(struct qed_dev *cdev) +{ + if (!cdev) + return; + + qed_hw_remove(cdev); + + qed_free_pci(cdev); + + qed_set_power_state(cdev, PCI_D3hot); + + qed_free_cdev(cdev); +} + +static void qed_disable_msix(struct qed_dev *cdev) +{ + if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { + pci_disable_msix(cdev->pdev); + kfree(cdev->int_params.msix_table); + } else if (cdev->int_params.out.int_mode == QED_INT_MODE_MSI) { + pci_disable_msi(cdev->pdev); + } + + memset(&cdev->int_params.out, 0, sizeof(struct qed_int_param)); +} + +static int qed_enable_msix(struct qed_dev *cdev, + struct qed_int_params *int_params) +{ + int i, rc, cnt; + + cnt = int_params->in.num_vectors; + + for (i = 0; i < cnt; i++) + int_params->msix_table[i].entry = i; + + rc = pci_enable_msix_range(cdev->pdev, int_params->msix_table, + int_params->in.min_msix_cnt, cnt); + if (rc < cnt && rc >= int_params->in.min_msix_cnt && + (rc % cdev->num_hwfns)) { + pci_disable_msix(cdev->pdev); + + /* If fastpath is initialized, we need at least one interrupt + * per hwfn [and the slow path interrupts]. New requested number + * should be a multiple of the number of hwfns. + */ + cnt = (rc / cdev->num_hwfns) * cdev->num_hwfns; + DP_NOTICE(cdev, + "Trying to enable MSI-X with less vectors (%d out of %d)\n", + cnt, int_params->in.num_vectors); + rc = pci_enable_msix_exact(cdev->pdev, + int_params->msix_table, cnt); + if (!rc) + rc = cnt; + } + + if (rc > 0) { + /* MSI-x configuration was achieved */ + int_params->out.int_mode = QED_INT_MODE_MSIX; + int_params->out.num_vectors = rc; + rc = 0; + } else { + DP_NOTICE(cdev, + "Failed to enable MSI-X [Requested %d vectors][rc %d]\n", + cnt, rc); + } + + return rc; +} + +/* This function outputs the int mode and the number of enabled msix vector */ +static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode) +{ + struct qed_int_params *int_params = &cdev->int_params; + struct msix_entry *tbl; + int rc = 0, cnt; + + switch (int_params->in.int_mode) { + case QED_INT_MODE_MSIX: + /* Allocate MSIX table */ + cnt = int_params->in.num_vectors; + int_params->msix_table = kcalloc(cnt, sizeof(*tbl), GFP_KERNEL); + if (!int_params->msix_table) { + rc = -ENOMEM; + goto out; + } + + /* Enable MSIX */ + rc = qed_enable_msix(cdev, int_params); + if (!rc) + goto out; + + DP_NOTICE(cdev, "Failed to enable MSI-X\n"); + kfree(int_params->msix_table); + if (force_mode) + goto out; + /* Fallthrough */ + + case QED_INT_MODE_MSI: + rc = pci_enable_msi(cdev->pdev); + if (!rc) { + int_params->out.int_mode = QED_INT_MODE_MSI; + goto out; + } + + DP_NOTICE(cdev, "Failed to enable MSI\n"); + if (force_mode) + goto out; + /* Fallthrough */ + + case QED_INT_MODE_INTA: + int_params->out.int_mode = QED_INT_MODE_INTA; + rc = 0; + goto out; + default: + DP_NOTICE(cdev, "Unknown int_mode value %d\n", + int_params->in.int_mode); + rc = -EINVAL; + } + +out: + cdev->int_coalescing_mode = QED_COAL_MODE_ENABLE; + + return rc; +} + +static void qed_simd_handler_config(struct qed_dev *cdev, void *token, + int index, void(*handler)(void *)) +{ + struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns]; + int relative_idx = index / cdev->num_hwfns; + + hwfn->simd_proto_handler[relative_idx].func = handler; + hwfn->simd_proto_handler[relative_idx].token = token; +} + +static void qed_simd_handler_clean(struct qed_dev *cdev, int index) +{ + struct qed_hwfn *hwfn = &cdev->hwfns[index % cdev->num_hwfns]; + int relative_idx = index / cdev->num_hwfns; + + memset(&hwfn->simd_proto_handler[relative_idx], 0, + sizeof(struct qed_simd_fp_handler)); +} + +static irqreturn_t qed_msix_sp_int(int irq, void *tasklet) +{ + tasklet_schedule((struct tasklet_struct *)tasklet); + return IRQ_HANDLED; +} + +static irqreturn_t qed_single_int(int irq, void *dev_instance) +{ + struct qed_dev *cdev = (struct qed_dev *)dev_instance; + struct qed_hwfn *hwfn; + irqreturn_t rc = IRQ_NONE; + u64 status; + int i, j; + + for (i = 0; i < cdev->num_hwfns; i++) { + status = qed_int_igu_read_sisr_reg(&cdev->hwfns[i]); + + if (!status) + continue; + + hwfn = &cdev->hwfns[i]; + + /* Slowpath interrupt */ + if (unlikely(status & 0x1)) { + tasklet_schedule(hwfn->sp_dpc); + status &= ~0x1; + rc = IRQ_HANDLED; + } + + /* Fastpath interrupts */ + for (j = 0; j < 64; j++) { + if ((0x2ULL << j) & status) { + hwfn->simd_proto_handler[j].func( + hwfn->simd_proto_handler[j].token); + status &= ~(0x2ULL << j); + rc = IRQ_HANDLED; + } + } + + if (unlikely(status)) + DP_VERBOSE(hwfn, NETIF_MSG_INTR, + "got an unknown interrupt status 0x%llx\n", + status); + } + + return rc; +} + +static int qed_slowpath_irq_req(struct qed_dev *cdev) +{ + int i = 0, rc = 0; + + if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { + /* Request all the slowpath MSI-X vectors */ + for (i = 0; i < cdev->num_hwfns; i++) { + snprintf(cdev->hwfns[i].name, NAME_SIZE, + "sp-%d-%02x:%02x.%02x", + i, cdev->pdev->bus->number, + PCI_SLOT(cdev->pdev->devfn), + cdev->hwfns[i].abs_pf_id); + + rc = request_irq(cdev->int_params.msix_table[i].vector, + qed_msix_sp_int, 0, + cdev->hwfns[i].name, + cdev->hwfns[i].sp_dpc); + if (rc) + break; + + DP_VERBOSE(&cdev->hwfns[i], + (NETIF_MSG_INTR | QED_MSG_SP), + "Requested slowpath MSI-X\n"); + } + + if (i != cdev->num_hwfns) { + /* Free already request MSI-X vectors */ + for (i--; i >= 0; i--) { + unsigned int vec = + cdev->int_params.msix_table[i].vector; + synchronize_irq(vec); + free_irq(cdev->int_params.msix_table[i].vector, + cdev->hwfns[i].sp_dpc); + } + } + } else { + unsigned long flags = 0; + + snprintf(cdev->name, NAME_SIZE, "%02x:%02x.%02x", + cdev->pdev->bus->number, PCI_SLOT(cdev->pdev->devfn), + PCI_FUNC(cdev->pdev->devfn)); + + if (cdev->int_params.out.int_mode == QED_INT_MODE_INTA) + flags |= IRQF_SHARED; + + rc = request_irq(cdev->pdev->irq, qed_single_int, + flags, cdev->name, cdev); + } + + return rc; +} + +static void qed_slowpath_irq_free(struct qed_dev *cdev) +{ + int i; + + if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { + for_each_hwfn(cdev, i) { + synchronize_irq(cdev->int_params.msix_table[i].vector); + free_irq(cdev->int_params.msix_table[i].vector, + cdev->hwfns[i].sp_dpc); + } + } else { + free_irq(cdev->pdev->irq, cdev); + } +} + +static int qed_nic_stop(struct qed_dev *cdev) +{ + int i, rc; + + rc = qed_hw_stop(cdev); + + for (i = 0; i < cdev->num_hwfns; i++) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + if (p_hwfn->b_sp_dpc_enabled) { + tasklet_disable(p_hwfn->sp_dpc); + p_hwfn->b_sp_dpc_enabled = false; + DP_VERBOSE(cdev, NETIF_MSG_IFDOWN, + "Disabled sp taskelt [hwfn %d] at %p\n", + i, p_hwfn->sp_dpc); + } + } + + return rc; +} + +static int qed_nic_reset(struct qed_dev *cdev) +{ + int rc; + + rc = qed_hw_reset(cdev); + if (rc) + return rc; + + qed_resc_free(cdev); + + return 0; +} + +static int qed_nic_setup(struct qed_dev *cdev) +{ + int rc; + + rc = qed_resc_alloc(cdev); + if (rc) + return rc; + + DP_INFO(cdev, "Allocated qed resources\n"); + + qed_resc_setup(cdev); + + return rc; +} + +static int qed_set_int_fp(struct qed_dev *cdev, u16 cnt) +{ + int limit = 0; + + /* Mark the fastpath as free/used */ + cdev->int_params.fp_initialized = cnt ? true : false; + + if (cdev->int_params.out.int_mode != QED_INT_MODE_MSIX) + limit = cdev->num_hwfns * 63; + else if (cdev->int_params.fp_msix_cnt) + limit = cdev->int_params.fp_msix_cnt; + + if (!limit) + return -ENOMEM; + + return min_t(int, cnt, limit); +} + +static int qed_get_int_fp(struct qed_dev *cdev, struct qed_int_info *info) +{ + memset(info, 0, sizeof(struct qed_int_info)); + + if (!cdev->int_params.fp_initialized) { + DP_INFO(cdev, + "Protocol driver requested interrupt information, but its support is not yet configured\n"); + return -EINVAL; + } + + /* Need to expose only MSI-X information; Single IRQ is handled solely + * by qed. + */ + if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { + int msix_base = cdev->int_params.fp_msix_base; + + info->msix_cnt = cdev->int_params.fp_msix_cnt; + info->msix = &cdev->int_params.msix_table[msix_base]; + } + + return 0; +} + +static int qed_slowpath_setup_int(struct qed_dev *cdev, + enum qed_int_mode int_mode) +{ + int rc, i; + u8 num_vectors = 0; + + memset(&cdev->int_params, 0, sizeof(struct qed_int_params)); + + cdev->int_params.in.int_mode = int_mode; + for_each_hwfn(cdev, i) + num_vectors += qed_int_get_num_sbs(&cdev->hwfns[i], NULL) + 1; + cdev->int_params.in.num_vectors = num_vectors; + + /* We want a minimum of one slowpath and one fastpath vector per hwfn */ + cdev->int_params.in.min_msix_cnt = cdev->num_hwfns * 2; + + rc = qed_set_int_mode(cdev, false); + if (rc) { + DP_ERR(cdev, "qed_slowpath_setup_int ERR\n"); + return rc; + } + + cdev->int_params.fp_msix_base = cdev->num_hwfns; + cdev->int_params.fp_msix_cnt = cdev->int_params.out.num_vectors - + cdev->num_hwfns; + + return 0; +} + +u32 qed_unzip_data(struct qed_hwfn *p_hwfn, u32 input_len, + u8 *input_buf, u32 max_size, u8 *unzip_buf) +{ + int rc; + + p_hwfn->stream->next_in = input_buf; + p_hwfn->stream->avail_in = input_len; + p_hwfn->stream->next_out = unzip_buf; + p_hwfn->stream->avail_out = max_size; + + rc = zlib_inflateInit2(p_hwfn->stream, MAX_WBITS); + + if (rc != Z_OK) { + DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "zlib init failed, rc = %d\n", + rc); + return 0; + } + + rc = zlib_inflate(p_hwfn->stream, Z_FINISH); + zlib_inflateEnd(p_hwfn->stream); + + if (rc != Z_OK && rc != Z_STREAM_END) { + DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, "FW unzip error: %s, rc=%d\n", + p_hwfn->stream->msg, rc); + return 0; + } + + return p_hwfn->stream->total_out / 4; +} + +static int qed_alloc_stream_mem(struct qed_dev *cdev) +{ + int i; + void *workspace; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + p_hwfn->stream = kzalloc(sizeof(*p_hwfn->stream), GFP_KERNEL); + if (!p_hwfn->stream) + return -ENOMEM; + + workspace = vzalloc(zlib_inflate_workspacesize()); + if (!workspace) + return -ENOMEM; + p_hwfn->stream->workspace = workspace; + } + + return 0; +} + +static void qed_free_stream_mem(struct qed_dev *cdev) +{ + int i; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + if (!p_hwfn->stream) + return; + + vfree(p_hwfn->stream->workspace); + kfree(p_hwfn->stream); + } +} + +static void qed_update_pf_params(struct qed_dev *cdev, + struct qed_pf_params *params) +{ + int i; + + for (i = 0; i < cdev->num_hwfns; i++) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + p_hwfn->pf_params = *params; + } +} + +static int qed_slowpath_start(struct qed_dev *cdev, + struct qed_slowpath_params *params) +{ + struct qed_mcp_drv_version drv_version; + const u8 *data = NULL; + struct qed_hwfn *hwfn; + int rc; + + rc = request_firmware(&cdev->firmware, QED_FW_FILE_NAME, + &cdev->pdev->dev); + if (rc) { + DP_NOTICE(cdev, + "Failed to find fw file - /lib/firmware/%s\n", + QED_FW_FILE_NAME); + goto err; + } + + rc = qed_nic_setup(cdev); + if (rc) + goto err; + + rc = qed_slowpath_setup_int(cdev, params->int_mode); + if (rc) + goto err1; + + /* Request the slowpath IRQ */ + rc = qed_slowpath_irq_req(cdev); + if (rc) + goto err2; + + /* Allocate stream for unzipping */ + rc = qed_alloc_stream_mem(cdev); + if (rc) { + DP_NOTICE(cdev, "Failed to allocate stream memory\n"); + goto err3; + } + + /* Start the slowpath */ + data = cdev->firmware->data; + + rc = qed_hw_init(cdev, true, cdev->int_params.out.int_mode, + true, data); + if (rc) + goto err3; + + DP_INFO(cdev, + "HW initialization and function start completed successfully\n"); + + hwfn = QED_LEADING_HWFN(cdev); + drv_version.version = (params->drv_major << 24) | + (params->drv_minor << 16) | + (params->drv_rev << 8) | + (params->drv_eng); + strlcpy(drv_version.name, params->name, + MCP_DRV_VER_STR_SIZE - 4); + rc = qed_mcp_send_drv_version(hwfn, hwfn->p_main_ptt, + &drv_version); + if (rc) { + DP_NOTICE(cdev, "Failed sending drv version command\n"); + return rc; + } + + return 0; + +err3: + qed_free_stream_mem(cdev); + qed_slowpath_irq_free(cdev); +err2: + qed_disable_msix(cdev); +err1: + qed_resc_free(cdev); +err: + release_firmware(cdev->firmware); + + return rc; +} + +static int qed_slowpath_stop(struct qed_dev *cdev) +{ + if (!cdev) + return -ENODEV; + + qed_free_stream_mem(cdev); + + qed_nic_stop(cdev); + qed_slowpath_irq_free(cdev); + + qed_disable_msix(cdev); + qed_nic_reset(cdev); + + release_firmware(cdev->firmware); + + return 0; +} + +static void qed_set_id(struct qed_dev *cdev, char name[NAME_SIZE], + char ver_str[VER_SIZE]) +{ + int i; + + memcpy(cdev->name, name, NAME_SIZE); + for_each_hwfn(cdev, i) + snprintf(cdev->hwfns[i].name, NAME_SIZE, "%s-%d", name, i); + + memcpy(cdev->ver_str, ver_str, VER_SIZE); + cdev->drv_type = DRV_ID_DRV_TYPE_LINUX; +} + +static u32 qed_sb_init(struct qed_dev *cdev, + struct qed_sb_info *sb_info, + void *sb_virt_addr, + dma_addr_t sb_phy_addr, u16 sb_id, + enum qed_sb_type type) +{ + struct qed_hwfn *p_hwfn; + int hwfn_index; + u16 rel_sb_id; + u8 n_hwfns; + u32 rc; + + /* RoCE uses single engine and CMT uses two engines. When using both + * we force only a single engine. Storage uses only engine 0 too. + */ + if (type == QED_SB_TYPE_L2_QUEUE) + n_hwfns = cdev->num_hwfns; + else + n_hwfns = 1; + + hwfn_index = sb_id % n_hwfns; + p_hwfn = &cdev->hwfns[hwfn_index]; + rel_sb_id = sb_id / n_hwfns; + + DP_VERBOSE(cdev, NETIF_MSG_INTR, + "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n", + hwfn_index, rel_sb_id, sb_id); + + rc = qed_int_sb_init(p_hwfn, p_hwfn->p_main_ptt, sb_info, + sb_virt_addr, sb_phy_addr, rel_sb_id); + + return rc; +} + +static u32 qed_sb_release(struct qed_dev *cdev, + struct qed_sb_info *sb_info, + u16 sb_id) +{ + struct qed_hwfn *p_hwfn; + int hwfn_index; + u16 rel_sb_id; + u32 rc; + + hwfn_index = sb_id % cdev->num_hwfns; + p_hwfn = &cdev->hwfns[hwfn_index]; + rel_sb_id = sb_id / cdev->num_hwfns; + + DP_VERBOSE(cdev, NETIF_MSG_INTR, + "hwfn [%d] <--[init]-- SB %04x [0x%04x upper]\n", + hwfn_index, rel_sb_id, sb_id); + + rc = qed_int_sb_release(p_hwfn, sb_info, rel_sb_id); + + return rc; +} + +static int qed_drain(struct qed_dev *cdev) +{ + struct qed_hwfn *hwfn; + struct qed_ptt *ptt; + int i, rc; + + for_each_hwfn(cdev, i) { + hwfn = &cdev->hwfns[i]; + ptt = qed_ptt_acquire(hwfn); + if (!ptt) { + DP_NOTICE(hwfn, "Failed to drain NIG; No PTT\n"); + return -EBUSY; + } + rc = qed_mcp_drain(hwfn, ptt); + if (rc) + return rc; + qed_ptt_release(hwfn, ptt); + } + + return 0; +} + +const struct qed_common_ops qed_common_ops_pass = { + .probe = &qed_probe, + .remove = &qed_remove, + .set_power_state = &qed_set_power_state, + .set_id = &qed_set_id, + .update_pf_params = &qed_update_pf_params, + .slowpath_start = &qed_slowpath_start, + .slowpath_stop = &qed_slowpath_stop, + .set_fp_int = &qed_set_int_fp, + .get_fp_int = &qed_get_int_fp, + .sb_init = &qed_sb_init, + .sb_release = &qed_sb_release, + .simd_handler_config = &qed_simd_handler_config, + .simd_handler_clean = &qed_simd_handler_clean, + .drain = &qed_drain, + .update_msglvl = &qed_init_dp, + .chain_alloc = &qed_chain_alloc, + .chain_free = &qed_chain_free, +}; + +u32 qed_get_protocol_version(enum qed_protocol protocol) +{ + switch (protocol) { + case QED_PROTOCOL_ETH: + return QED_ETH_INTERFACE_VERSION; + default: + return 0; + } +} +EXPORT_SYMBOL(qed_get_protocol_version); diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c new file mode 100644 index 000000000000..601d3f5daf13 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -0,0 +1,549 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "qed.h" +#include "qed_hsi.h" +#include "qed_hw.h" +#include "qed_mcp.h" +#include "qed_reg_addr.h" +#define CHIP_MCP_RESP_ITER_US 10 + +#define QED_DRV_MB_MAX_RETRIES (500 * 1000) /* Account for 5 sec */ +#define QED_MCP_RESET_RETRIES (50 * 1000) /* Account for 500 msec */ + +#define DRV_INNER_WR(_p_hwfn, _p_ptt, _ptr, _offset, _val) \ + qed_wr(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset), \ + _val) + +#define DRV_INNER_RD(_p_hwfn, _p_ptt, _ptr, _offset) \ + qed_rd(_p_hwfn, _p_ptt, (_p_hwfn->mcp_info->_ptr + _offset)) + +#define DRV_MB_WR(_p_hwfn, _p_ptt, _field, _val) \ + DRV_INNER_WR(p_hwfn, _p_ptt, drv_mb_addr, \ + offsetof(struct public_drv_mb, _field), _val) + +#define DRV_MB_RD(_p_hwfn, _p_ptt, _field) \ + DRV_INNER_RD(_p_hwfn, _p_ptt, drv_mb_addr, \ + offsetof(struct public_drv_mb, _field)) + +#define PDA_COMP (((FW_MAJOR_VERSION) + (FW_MINOR_VERSION << 8)) << \ + DRV_ID_PDA_COMP_VER_SHIFT) + +#define MCP_BYTES_PER_MBIT_SHIFT 17 + +bool qed_mcp_is_init(struct qed_hwfn *p_hwfn) +{ + if (!p_hwfn->mcp_info || !p_hwfn->mcp_info->public_base) + return false; + return true; +} + +void qed_mcp_cmd_port_init(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, + PUBLIC_PORT); + u32 mfw_mb_offsize = qed_rd(p_hwfn, p_ptt, addr); + + p_hwfn->mcp_info->port_addr = SECTION_ADDR(mfw_mb_offsize, + MFW_PORT(p_hwfn)); + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "port_addr = 0x%x, port_id 0x%02x\n", + p_hwfn->mcp_info->port_addr, MFW_PORT(p_hwfn)); +} + +void qed_mcp_read_mb(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + u32 length = MFW_DRV_MSG_MAX_DWORDS(p_hwfn->mcp_info->mfw_mb_length); + u32 tmp, i; + + if (!p_hwfn->mcp_info->public_base) + return; + + for (i = 0; i < length; i++) { + tmp = qed_rd(p_hwfn, p_ptt, + p_hwfn->mcp_info->mfw_mb_addr + + (i << 2) + sizeof(u32)); + + /* The MB data is actually BE; Need to force it to cpu */ + ((u32 *)p_hwfn->mcp_info->mfw_mb_cur)[i] = + be32_to_cpu((__force __be32)tmp); + } +} + +int qed_mcp_free(struct qed_hwfn *p_hwfn) +{ + if (p_hwfn->mcp_info) { + kfree(p_hwfn->mcp_info->mfw_mb_cur); + kfree(p_hwfn->mcp_info->mfw_mb_shadow); + } + kfree(p_hwfn->mcp_info); + + return 0; +} + +static int qed_load_mcp_offsets(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + struct qed_mcp_info *p_info = p_hwfn->mcp_info; + u32 drv_mb_offsize, mfw_mb_offsize; + u32 mcp_pf_id = MCP_PF_ID(p_hwfn); + + p_info->public_base = qed_rd(p_hwfn, p_ptt, MISC_REG_SHARED_MEM_ADDR); + if (!p_info->public_base) + return 0; + + p_info->public_base |= GRCBASE_MCP; + + /* Calculate the driver and MFW mailbox address */ + drv_mb_offsize = qed_rd(p_hwfn, p_ptt, + SECTION_OFFSIZE_ADDR(p_info->public_base, + PUBLIC_DRV_MB)); + p_info->drv_mb_addr = SECTION_ADDR(drv_mb_offsize, mcp_pf_id); + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "drv_mb_offsiz = 0x%x, drv_mb_addr = 0x%x mcp_pf_id = 0x%x\n", + drv_mb_offsize, p_info->drv_mb_addr, mcp_pf_id); + + /* Set the MFW MB address */ + mfw_mb_offsize = qed_rd(p_hwfn, p_ptt, + SECTION_OFFSIZE_ADDR(p_info->public_base, + PUBLIC_MFW_MB)); + p_info->mfw_mb_addr = SECTION_ADDR(mfw_mb_offsize, mcp_pf_id); + p_info->mfw_mb_length = (u16)qed_rd(p_hwfn, p_ptt, p_info->mfw_mb_addr); + + /* Get the current driver mailbox sequence before sending + * the first command + */ + p_info->drv_mb_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_mb_header) & + DRV_MSG_SEQ_NUMBER_MASK; + + /* Get current FW pulse sequence */ + p_info->drv_pulse_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_pulse_mb) & + DRV_PULSE_SEQ_MASK; + + p_info->mcp_hist = (u16)qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0); + + return 0; +} + +int qed_mcp_cmd_init(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + struct qed_mcp_info *p_info; + u32 size; + + /* Allocate mcp_info structure */ + p_hwfn->mcp_info = kzalloc(sizeof(*p_hwfn->mcp_info), GFP_ATOMIC); + if (!p_hwfn->mcp_info) + goto err; + p_info = p_hwfn->mcp_info; + + if (qed_load_mcp_offsets(p_hwfn, p_ptt) != 0) { + DP_NOTICE(p_hwfn, "MCP is not initialized\n"); + /* Do not free mcp_info here, since public_base indicate that + * the MCP is not initialized + */ + return 0; + } + + size = MFW_DRV_MSG_MAX_DWORDS(p_info->mfw_mb_length) * sizeof(u32); + p_info->mfw_mb_cur = kzalloc(size, GFP_ATOMIC); + p_info->mfw_mb_shadow = + kzalloc(sizeof(u32) * MFW_DRV_MSG_MAX_DWORDS( + p_info->mfw_mb_length), GFP_ATOMIC); + if (!p_info->mfw_mb_shadow || !p_info->mfw_mb_addr) + goto err; + + /* Initialize the MFW mutex */ + mutex_init(&p_info->mutex); + + return 0; + +err: + DP_NOTICE(p_hwfn, "Failed to allocate mcp memory\n"); + qed_mcp_free(p_hwfn); + return -ENOMEM; +} + +int qed_mcp_reset(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + u32 seq = ++p_hwfn->mcp_info->drv_mb_seq; + u8 delay = CHIP_MCP_RESP_ITER_US; + u32 org_mcp_reset_seq, cnt = 0; + int rc = 0; + + /* Set drv command along with the updated sequence */ + org_mcp_reset_seq = qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0); + DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, + (DRV_MSG_CODE_MCP_RESET | seq)); + + do { + /* Wait for MFW response */ + udelay(delay); + /* Give the FW up to 500 second (50*1000*10usec) */ + } while ((org_mcp_reset_seq == qed_rd(p_hwfn, p_ptt, + MISCS_REG_GENERIC_POR_0)) && + (cnt++ < QED_MCP_RESET_RETRIES)); + + if (org_mcp_reset_seq != + qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0)) { + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "MCP was reset after %d usec\n", cnt * delay); + } else { + DP_ERR(p_hwfn, "Failed to reset MCP\n"); + rc = -EAGAIN; + } + + return rc; +} + +static int qed_do_mcp_cmd(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 cmd, + u32 param, + u32 *o_mcp_resp, + u32 *o_mcp_param) +{ + u8 delay = CHIP_MCP_RESP_ITER_US; + u32 seq, cnt = 1, actual_mb_seq; + int rc = 0; + + /* Get actual driver mailbox sequence */ + actual_mb_seq = DRV_MB_RD(p_hwfn, p_ptt, drv_mb_header) & + DRV_MSG_SEQ_NUMBER_MASK; + + /* Use MCP history register to check if MCP reset occurred between + * init time and now. + */ + if (p_hwfn->mcp_info->mcp_hist != + qed_rd(p_hwfn, p_ptt, MISCS_REG_GENERIC_POR_0)) { + DP_VERBOSE(p_hwfn, QED_MSG_SP, "Rereading MCP offsets\n"); + qed_load_mcp_offsets(p_hwfn, p_ptt); + qed_mcp_cmd_port_init(p_hwfn, p_ptt); + } + seq = ++p_hwfn->mcp_info->drv_mb_seq; + + /* Set drv param */ + DRV_MB_WR(p_hwfn, p_ptt, drv_mb_param, param); + + /* Set drv command along with the updated sequence */ + DRV_MB_WR(p_hwfn, p_ptt, drv_mb_header, (cmd | seq)); + + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "wrote command (%x) to MFW MB param 0x%08x\n", + (cmd | seq), param); + + do { + /* Wait for MFW response */ + udelay(delay); + *o_mcp_resp = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_header); + + /* Give the FW up to 5 second (500*10ms) */ + } while ((seq != (*o_mcp_resp & FW_MSG_SEQ_NUMBER_MASK)) && + (cnt++ < QED_DRV_MB_MAX_RETRIES)); + + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "[after %d ms] read (%x) seq is (%x) from FW MB\n", + cnt * delay, *o_mcp_resp, seq); + + /* Is this a reply to our command? */ + if (seq == (*o_mcp_resp & FW_MSG_SEQ_NUMBER_MASK)) { + *o_mcp_resp &= FW_MSG_CODE_MASK; + /* Get the MCP param */ + *o_mcp_param = DRV_MB_RD(p_hwfn, p_ptt, fw_mb_param); + } else { + /* FW BUG! */ + DP_ERR(p_hwfn, "MFW failed to respond!\n"); + *o_mcp_resp = 0; + rc = -EAGAIN; + } + return rc; +} + +int qed_mcp_cmd(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 cmd, + u32 param, + u32 *o_mcp_resp, + u32 *o_mcp_param) +{ + int rc = 0; + + /* MCP not initialized */ + if (!qed_mcp_is_init(p_hwfn)) { + DP_NOTICE(p_hwfn, "MFW is not initialized !\n"); + return -EBUSY; + } + + /* Lock Mutex to ensure only single thread is + * accessing the MCP at one time + */ + mutex_lock(&p_hwfn->mcp_info->mutex); + rc = qed_do_mcp_cmd(p_hwfn, p_ptt, cmd, param, + o_mcp_resp, o_mcp_param); + /* Release Mutex */ + mutex_unlock(&p_hwfn->mcp_info->mutex); + + return rc; +} + +static void qed_mcp_set_drv_ver(struct qed_dev *cdev, + struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + u32 i; + + /* Copy version string to MCP */ + for (i = 0; i < MCP_DRV_VER_STR_SIZE_DWORD; i++) + DRV_MB_WR(p_hwfn, p_ptt, union_data.ver_str[i], + *(u32 *)&cdev->ver_str[i * sizeof(u32)]); +} + +int qed_mcp_load_req(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 *p_load_code) +{ + struct qed_dev *cdev = p_hwfn->cdev; + u32 param; + int rc; + + if (!qed_mcp_is_init(p_hwfn)) { + DP_NOTICE(p_hwfn, "MFW is not initialized !\n"); + return -EBUSY; + } + + /* Save driver's version to shmem */ + qed_mcp_set_drv_ver(cdev, p_hwfn, p_ptt); + + DP_VERBOSE(p_hwfn, QED_MSG_SP, "fw_seq 0x%08x, drv_pulse 0x%x\n", + p_hwfn->mcp_info->drv_mb_seq, + p_hwfn->mcp_info->drv_pulse_seq); + + /* Load Request */ + rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_LOAD_REQ, + (PDA_COMP | DRV_ID_MCP_HSI_VER_CURRENT | + cdev->drv_type), + p_load_code, ¶m); + + /* if mcp fails to respond we must abort */ + if (rc) { + DP_ERR(p_hwfn, "MCP response failure, aborting\n"); + return rc; + } + + /* If MFW refused (e.g. other port is in diagnostic mode) we + * must abort. This can happen in the following cases: + * - Other port is in diagnostic mode + * - Previously loaded function on the engine is not compliant with + * the requester. + * - MFW cannot cope with the requester's DRV_MFW_HSI_VERSION. + * - + */ + if (!(*p_load_code) || + ((*p_load_code) == FW_MSG_CODE_DRV_LOAD_REFUSED_HSI) || + ((*p_load_code) == FW_MSG_CODE_DRV_LOAD_REFUSED_PDA) || + ((*p_load_code) == FW_MSG_CODE_DRV_LOAD_REFUSED_DIAG)) { + DP_ERR(p_hwfn, "MCP refused load request, aborting\n"); + return -EBUSY; + } + + return 0; +} + +int qed_mcp_get_mfw_ver(struct qed_dev *cdev, + u32 *p_mfw_ver) +{ + struct qed_hwfn *p_hwfn = &cdev->hwfns[0]; + struct qed_ptt *p_ptt; + u32 global_offsize; + + p_ptt = qed_ptt_acquire(p_hwfn); + if (!p_ptt) + return -EBUSY; + + global_offsize = qed_rd(p_hwfn, p_ptt, + SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info-> + public_base, + PUBLIC_GLOBAL)); + *p_mfw_ver = qed_rd(p_hwfn, p_ptt, + SECTION_ADDR(global_offsize, 0) + + offsetof(struct public_global, mfw_ver)); + + qed_ptt_release(p_hwfn, p_ptt); + + return 0; +} + +static u32 qed_mcp_get_shmem_func(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct public_func *p_data, + int pfid) +{ + u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, + PUBLIC_FUNC); + u32 mfw_path_offsize = qed_rd(p_hwfn, p_ptt, addr); + u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid); + u32 i, size; + + memset(p_data, 0, sizeof(*p_data)); + + size = min_t(u32, sizeof(*p_data), + QED_SECTION_SIZE(mfw_path_offsize)); + for (i = 0; i < size / sizeof(u32); i++) + ((u32 *)p_data)[i] = qed_rd(p_hwfn, p_ptt, + func_addr + (i << 2)); + + return size; +} + +static int +qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn, + struct public_func *p_info, + enum qed_pci_personality *p_proto) +{ + int rc = 0; + + switch (p_info->config & FUNC_MF_CFG_PROTOCOL_MASK) { + case FUNC_MF_CFG_PROTOCOL_ETHERNET: + *p_proto = QED_PCI_ETH; + break; + default: + rc = -EINVAL; + } + + return rc; +} + +int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + struct qed_mcp_function_info *info; + struct public_func shmem_info; + + qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info, + MCP_PF_ID(p_hwfn)); + info = &p_hwfn->mcp_info->func_info; + + info->pause_on_host = (shmem_info.config & + FUNC_MF_CFG_PAUSE_ON_HOST_RING) ? 1 : 0; + + if (qed_mcp_get_shmem_proto(p_hwfn, &shmem_info, + &info->protocol)) { + DP_ERR(p_hwfn, "Unknown personality %08x\n", + (u32)(shmem_info.config & FUNC_MF_CFG_PROTOCOL_MASK)); + return -EINVAL; + } + + if (p_hwfn->cdev->mf_mode != SF) { + info->bandwidth_min = (shmem_info.config & + FUNC_MF_CFG_MIN_BW_MASK) >> + FUNC_MF_CFG_MIN_BW_SHIFT; + if (info->bandwidth_min < 1 || info->bandwidth_min > 100) { + DP_INFO(p_hwfn, + "bandwidth minimum out of bounds [%02x]. Set to 1\n", + info->bandwidth_min); + info->bandwidth_min = 1; + } + + info->bandwidth_max = (shmem_info.config & + FUNC_MF_CFG_MAX_BW_MASK) >> + FUNC_MF_CFG_MAX_BW_SHIFT; + if (info->bandwidth_max < 1 || info->bandwidth_max > 100) { + DP_INFO(p_hwfn, + "bandwidth maximum out of bounds [%02x]. Set to 100\n", + info->bandwidth_max); + info->bandwidth_max = 100; + } + } + + if (shmem_info.mac_upper || shmem_info.mac_lower) { + info->mac[0] = (u8)(shmem_info.mac_upper >> 8); + info->mac[1] = (u8)(shmem_info.mac_upper); + info->mac[2] = (u8)(shmem_info.mac_lower >> 24); + info->mac[3] = (u8)(shmem_info.mac_lower >> 16); + info->mac[4] = (u8)(shmem_info.mac_lower >> 8); + info->mac[5] = (u8)(shmem_info.mac_lower); + } else { + DP_NOTICE(p_hwfn, "MAC is 0 in shmem\n"); + } + + info->wwn_port = (u64)shmem_info.fcoe_wwn_port_name_upper | + (((u64)shmem_info.fcoe_wwn_port_name_lower) << 32); + info->wwn_node = (u64)shmem_info.fcoe_wwn_node_name_upper | + (((u64)shmem_info.fcoe_wwn_node_name_lower) << 32); + + info->ovlan = (u16)(shmem_info.ovlan_stag & FUNC_MF_CFG_OV_STAG_MASK); + + DP_VERBOSE(p_hwfn, (QED_MSG_SP | NETIF_MSG_IFUP), + "Read configuration from shmem: pause_on_host %02x protocol %02x BW [%02x - %02x] MAC %02x:%02x:%02x:%02x:%02x:%02x wwn port %llx node %llx ovlan %04x\n", + info->pause_on_host, info->protocol, + info->bandwidth_min, info->bandwidth_max, + info->mac[0], info->mac[1], info->mac[2], + info->mac[3], info->mac[4], info->mac[5], + info->wwn_port, info->wwn_node, info->ovlan); + + return 0; +} + +int qed_mcp_drain(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + u32 resp = 0, param = 0; + int rc; + + rc = qed_mcp_cmd(p_hwfn, p_ptt, + DRV_MSG_CODE_NIG_DRAIN, 100, + &resp, ¶m); + + /* Wait for the drain to complete before returning */ + msleep(120); + + return rc; +} + +int +qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_mcp_drv_version *p_ver) +{ + int rc = 0; + u32 param = 0, reply = 0, i; + + if (!qed_mcp_is_init(p_hwfn)) { + DP_NOTICE(p_hwfn, "MFW is not initialized !\n"); + return -EBUSY; + } + + DRV_MB_WR(p_hwfn, p_ptt, union_data.drv_version.version, + p_ver->version); + /* Copy version string to shmem */ + for (i = 0; i < (MCP_DRV_VER_STR_SIZE - 4) / 4; i++) { + DRV_MB_WR(p_hwfn, p_ptt, + union_data.drv_version.name[i * sizeof(u32)], + *(u32 *)&p_ver->name[i * sizeof(u32)]); + } + + rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_VERSION, 0, &reply, + ¶m); + if (rc) { + DP_ERR(p_hwfn, "MCP response failure, aborting\n"); + return rc; + } + + return 0; +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h new file mode 100644 index 000000000000..230c2550dc89 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -0,0 +1,232 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#ifndef _QED_MCP_H +#define _QED_MCP_H + +#include +#include +#include +#include +#include "qed_hsi.h" + +struct qed_mcp_function_info { + u8 pause_on_host; + + enum qed_pci_personality protocol; + + u8 bandwidth_min; + u8 bandwidth_max; + + u8 mac[ETH_ALEN]; + + u64 wwn_port; + u64 wwn_node; + +#define QED_MCP_VLAN_UNSET (0xffff) + u16 ovlan; +}; + +struct qed_mcp_nvm_common { + u32 offset; + u32 param; + u32 resp; + u32 cmd; +}; + +struct qed_mcp_drv_version { + u32 version; + u8 name[MCP_DRV_VER_STR_SIZE - 4]; +}; + +/** + * @brief Get the management firmware version value + * + * @param cdev - qed dev pointer + * @param mfw_ver - mfw version value + * + * @return int - 0 - operation was successul. + */ +int qed_mcp_get_mfw_ver(struct qed_dev *cdev, + u32 *mfw_ver); + +/** + * @brief General function for sending commands to the MCP + * mailbox. It acquire mutex lock for the entire + * operation, from sending the request until the MCP + * response. Waiting for MCP response will be checked up + * to 5 seconds every 5ms. + * + * @param p_hwfn - hw function + * @param p_ptt - PTT required for register access + * @param cmd - command to be sent to the MCP. + * @param param - Optional param + * @param o_mcp_resp - The MCP response code (exclude sequence). + * @param o_mcp_param- Optional parameter provided by the MCP + * response + * @return int - 0 - operation + * was successul. + */ +int qed_mcp_cmd(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 cmd, + u32 param, + u32 *o_mcp_resp, + u32 *o_mcp_param); + +/** + * @brief - drains the nig, allowing completion to pass in case of pauses. + * (Should be called only from sleepable context) + * + * @param p_hwfn + * @param p_ptt + */ +int qed_mcp_drain(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +/** + * @brief Send driver version to MFW + * + * @param p_hwfn + * @param p_ptt + * @param version - Version value + * @param name - Protocol driver name + * + * @return int - 0 - operation was successul. + */ +int +qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_mcp_drv_version *p_ver); + +/* Using hwfn number (and not pf_num) is required since in CMT mode, + * same pf_num may be used by two different hwfn + * TODO - this shouldn't really be in .h file, but until all fields + * required during hw-init will be placed in their correct place in shmem + * we need it in qed_dev.c [for readin the nvram reflection in shmem]. + */ +#define MCP_PF_ID_BY_REL(p_hwfn, rel_pfid) (QED_IS_BB((p_hwfn)->cdev) ? \ + ((rel_pfid) | \ + ((p_hwfn)->abs_pf_id & 1) << 3) : \ + rel_pfid) +#define MCP_PF_ID(p_hwfn) MCP_PF_ID_BY_REL(p_hwfn, (p_hwfn)->rel_pf_id) + +/* TODO - this is only correct as long as only BB is supported, and + * no port-swapping is implemented; Afterwards we'll need to fix it. + */ +#define MFW_PORT(_p_hwfn) ((_p_hwfn)->abs_pf_id % \ + ((_p_hwfn)->cdev->num_ports_in_engines * 2)) +struct qed_mcp_info { + struct mutex mutex; /* MCP access lock */ + u32 public_base; + u32 drv_mb_addr; + u32 mfw_mb_addr; + u32 port_addr; + u16 drv_mb_seq; + u16 drv_pulse_seq; + struct qed_mcp_function_info func_info; + + u8 *mfw_mb_cur; + u8 *mfw_mb_shadow; + u16 mfw_mb_length; + u16 mcp_hist; +}; + +/** + * @brief Initialize the interface with the MCP + * + * @param p_hwfn - HW func + * @param p_ptt - PTT required for register access + * + * @return int + */ +int qed_mcp_cmd_init(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +/** + * @brief Initialize the port interface with the MCP + * + * @param p_hwfn + * @param p_ptt + * Can only be called after `num_ports_in_engines' is set + */ +void qed_mcp_cmd_port_init(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); +/** + * @brief Releases resources allocated during the init process. + * + * @param p_hwfn - HW func + * @param p_ptt - PTT required for register access + * + * @return int + */ + +int qed_mcp_free(struct qed_hwfn *p_hwfn); + +/** + * @brief Sends a LOAD_REQ to the MFW, and in case operation + * succeed, returns whether this PF is the first on the + * chip/engine/port or function. This function should be + * called when driver is ready to accept MFW events after + * Storms initializations are done. + * + * @param p_hwfn - hw function + * @param p_ptt - PTT required for register access + * @param p_load_code - The MCP response param containing one + * of the following: + * FW_MSG_CODE_DRV_LOAD_ENGINE + * FW_MSG_CODE_DRV_LOAD_PORT + * FW_MSG_CODE_DRV_LOAD_FUNCTION + * @return int - + * 0 - Operation was successul. + * -EBUSY - Operation failed + */ +int qed_mcp_load_req(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 *p_load_code); + +/** + * @brief Read the MFW mailbox into Current buffer. + * + * @param p_hwfn + * @param p_ptt + */ +void qed_mcp_read_mb(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +/** + * @brief - calls during init to read shmem of all function-related info. + * + * @param p_hwfn + * + * @param return 0 upon success. + */ +int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +/** + * @brief - Reset the MCP using mailbox command. + * + * @param p_hwfn + * @param p_ptt + * + * @param return 0 upon success. + */ +int qed_mcp_reset(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + +/** + * @brief indicates whether the MFW objects [under mcp_info] are accessible + * + * @param p_hwfn + * + * @return true iff MFW is running and mcp_info is initialized + */ +bool qed_mcp_is_init(struct qed_hwfn *p_hwfn); + +#endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h new file mode 100644 index 000000000000..7a5ce5914ace --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h @@ -0,0 +1,366 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#ifndef REG_ADDR_H +#define REG_ADDR_H + +#define CDU_REG_CID_ADDR_PARAMS_CONTEXT_SIZE_SHIFT \ + 0 + +#define CDU_REG_CID_ADDR_PARAMS_CONTEXT_SIZE ( \ + 0xfff << 0) + +#define CDU_REG_CID_ADDR_PARAMS_BLOCK_WASTE_SHIFT \ + 12 + +#define CDU_REG_CID_ADDR_PARAMS_BLOCK_WASTE ( \ + 0xfff << 12) + +#define CDU_REG_CID_ADDR_PARAMS_NCIB_SHIFT \ + 24 + +#define CDU_REG_CID_ADDR_PARAMS_NCIB ( \ + 0xff << 24) + +#define XSDM_REG_OPERATION_GEN \ + 0xf80408UL +#define NIG_REG_RX_BRB_OUT_EN \ + 0x500e18UL +#define NIG_REG_STORM_OUT_EN \ + 0x500e08UL +#define PSWRQ2_REG_L2P_VALIDATE_VFID \ + 0x240c50UL +#define PGLUE_B_REG_USE_CLIENTID_IN_TAG \ + 0x2aae04UL +#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER \ + 0x2aa16cUL +#define BAR0_MAP_REG_MSDM_RAM \ + 0x1d00000UL +#define BAR0_MAP_REG_USDM_RAM \ + 0x1d80000UL +#define BAR0_MAP_REG_PSDM_RAM \ + 0x1f00000UL +#define BAR0_MAP_REG_TSDM_RAM \ + 0x1c80000UL +#define NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF \ + 0x5011f4UL +#define PRS_REG_SEARCH_TCP \ + 0x1f0400UL +#define PRS_REG_SEARCH_UDP \ + 0x1f0404UL +#define PRS_REG_SEARCH_FCOE \ + 0x1f0408UL +#define PRS_REG_SEARCH_ROCE \ + 0x1f040cUL +#define PRS_REG_SEARCH_OPENFLOW \ + 0x1f0434UL +#define TM_REG_PF_ENABLE_CONN \ + 0x2c043cUL +#define TM_REG_PF_ENABLE_TASK \ + 0x2c0444UL +#define TM_REG_PF_SCAN_ACTIVE_CONN \ + 0x2c04fcUL +#define TM_REG_PF_SCAN_ACTIVE_TASK \ + 0x2c0500UL +#define IGU_REG_LEADING_EDGE_LATCH \ + 0x18082cUL +#define IGU_REG_TRAILING_EDGE_LATCH \ + 0x180830UL +#define QM_REG_USG_CNT_PF_TX \ + 0x2f2eacUL +#define QM_REG_USG_CNT_PF_OTHER \ + 0x2f2eb0UL +#define DORQ_REG_PF_DB_ENABLE \ + 0x100508UL +#define QM_REG_PF_EN \ + 0x2f2ea4UL +#define TCFC_REG_STRONG_ENABLE_PF \ + 0x2d0708UL +#define CCFC_REG_STRONG_ENABLE_PF \ + 0x2e0708UL +#define PGLUE_B_REG_PGL_ADDR_88_F0 \ + 0x2aa404UL +#define PGLUE_B_REG_PGL_ADDR_8C_F0 \ + 0x2aa408UL +#define PGLUE_B_REG_PGL_ADDR_90_F0 \ + 0x2aa40cUL +#define PGLUE_B_REG_PGL_ADDR_94_F0 \ + 0x2aa410UL +#define PGLUE_B_REG_WAS_ERROR_PF_31_0_CLR \ + 0x2aa138UL +#define PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ \ + 0x2aa174UL +#define MISC_REG_GEN_PURP_CR0 \ + 0x008c80UL +#define MCP_REG_SCRATCH \ + 0xe20000UL +#define CNIG_REG_NW_PORT_MODE_BB_B0 \ + 0x218200UL +#define MISCS_REG_CHIP_NUM \ + 0x00976cUL +#define MISCS_REG_CHIP_REV \ + 0x009770UL +#define MISCS_REG_CMT_ENABLED_FOR_PAIR \ + 0x00971cUL +#define MISCS_REG_CHIP_TEST_REG \ + 0x009778UL +#define MISCS_REG_CHIP_METAL \ + 0x009774UL +#define BRB_REG_HEADER_SIZE \ + 0x340804UL +#define BTB_REG_HEADER_SIZE \ + 0xdb0804UL +#define CAU_REG_LONG_TIMEOUT_THRESHOLD \ + 0x1c0708UL +#define CCFC_REG_ACTIVITY_COUNTER \ + 0x2e8800UL +#define CDU_REG_CID_ADDR_PARAMS \ + 0x580900UL +#define DBG_REG_CLIENT_ENABLE \ + 0x010004UL +#define DMAE_REG_INIT \ + 0x00c000UL +#define DORQ_REG_IFEN \ + 0x100040UL +#define GRC_REG_TIMEOUT_EN \ + 0x050404UL +#define IGU_REG_BLOCK_CONFIGURATION \ + 0x180040UL +#define MCM_REG_INIT \ + 0x1200000UL +#define MCP2_REG_DBG_DWORD_ENABLE \ + 0x052404UL +#define MISC_REG_PORT_MODE \ + 0x008c00UL +#define MISCS_REG_CLK_100G_MODE \ + 0x009070UL +#define MSDM_REG_ENABLE_IN1 \ + 0xfc0004UL +#define MSEM_REG_ENABLE_IN \ + 0x1800004UL +#define NIG_REG_CM_HDR \ + 0x500840UL +#define NCSI_REG_CONFIG \ + 0x040200UL +#define PBF_REG_INIT \ + 0xd80000UL +#define PTU_REG_ATC_INIT_ARRAY \ + 0x560000UL +#define PCM_REG_INIT \ + 0x1100000UL +#define PGLUE_B_REG_ADMIN_PER_PF_REGION \ + 0x2a9000UL +#define PRM_REG_DISABLE_PRM \ + 0x230000UL +#define PRS_REG_SOFT_RST \ + 0x1f0000UL +#define PSDM_REG_ENABLE_IN1 \ + 0xfa0004UL +#define PSEM_REG_ENABLE_IN \ + 0x1600004UL +#define PSWRQ_REG_DBG_SELECT \ + 0x280020UL +#define PSWRQ2_REG_CDUT_P_SIZE \ + 0x24000cUL +#define PSWHST_REG_DISCARD_INTERNAL_WRITES \ + 0x2a0040UL +#define PSWHST2_REG_DBGSYN_ALMOST_FULL_THR \ + 0x29e050UL +#define PSWRD_REG_DBG_SELECT \ + 0x29c040UL +#define PSWRD2_REG_CONF11 \ + 0x29d064UL +#define PSWWR_REG_USDM_FULL_TH \ + 0x29a040UL +#define PSWWR2_REG_CDU_FULL_TH2 \ + 0x29b040UL +#define QM_REG_MAXPQSIZE_0 \ + 0x2f0434UL +#define RSS_REG_RSS_INIT_EN \ + 0x238804UL +#define RDIF_REG_STOP_ON_ERROR \ + 0x300040UL +#define SRC_REG_SOFT_RST \ + 0x23874cUL +#define TCFC_REG_ACTIVITY_COUNTER \ + 0x2d8800UL +#define TCM_REG_INIT \ + 0x1180000UL +#define TM_REG_PXP_READ_DATA_FIFO_INIT \ + 0x2c0014UL +#define TSDM_REG_ENABLE_IN1 \ + 0xfb0004UL +#define TSEM_REG_ENABLE_IN \ + 0x1700004UL +#define TDIF_REG_STOP_ON_ERROR \ + 0x310040UL +#define UCM_REG_INIT \ + 0x1280000UL +#define UMAC_REG_IPG_HD_BKP_CNTL_BB_B0 \ + 0x051004UL +#define USDM_REG_ENABLE_IN1 \ + 0xfd0004UL +#define USEM_REG_ENABLE_IN \ + 0x1900004UL +#define XCM_REG_INIT \ + 0x1000000UL +#define XSDM_REG_ENABLE_IN1 \ + 0xf80004UL +#define XSEM_REG_ENABLE_IN \ + 0x1400004UL +#define YCM_REG_INIT \ + 0x1080000UL +#define YSDM_REG_ENABLE_IN1 \ + 0xf90004UL +#define YSEM_REG_ENABLE_IN \ + 0x1500004UL +#define XYLD_REG_SCBD_STRICT_PRIO \ + 0x4c0000UL +#define TMLD_REG_SCBD_STRICT_PRIO \ + 0x4d0000UL +#define MULD_REG_SCBD_STRICT_PRIO \ + 0x4e0000UL +#define YULD_REG_SCBD_STRICT_PRIO \ + 0x4c8000UL +#define MISC_REG_SHARED_MEM_ADDR \ + 0x008c20UL +#define DMAE_REG_GO_C0 \ + 0x00c048UL +#define DMAE_REG_GO_C1 \ + 0x00c04cUL +#define DMAE_REG_GO_C2 \ + 0x00c050UL +#define DMAE_REG_GO_C3 \ + 0x00c054UL +#define DMAE_REG_GO_C4 \ + 0x00c058UL +#define DMAE_REG_GO_C5 \ + 0x00c05cUL +#define DMAE_REG_GO_C6 \ + 0x00c060UL +#define DMAE_REG_GO_C7 \ + 0x00c064UL +#define DMAE_REG_GO_C8 \ + 0x00c068UL +#define DMAE_REG_GO_C9 \ + 0x00c06cUL +#define DMAE_REG_GO_C10 \ + 0x00c070UL +#define DMAE_REG_GO_C11 \ + 0x00c074UL +#define DMAE_REG_GO_C12 \ + 0x00c078UL +#define DMAE_REG_GO_C13 \ + 0x00c07cUL +#define DMAE_REG_GO_C14 \ + 0x00c080UL +#define DMAE_REG_GO_C15 \ + 0x00c084UL +#define DMAE_REG_GO_C16 \ + 0x00c088UL +#define DMAE_REG_GO_C17 \ + 0x00c08cUL +#define DMAE_REG_GO_C18 \ + 0x00c090UL +#define DMAE_REG_GO_C19 \ + 0x00c094UL +#define DMAE_REG_GO_C20 \ + 0x00c098UL +#define DMAE_REG_GO_C21 \ + 0x00c09cUL +#define DMAE_REG_GO_C22 \ + 0x00c0a0UL +#define DMAE_REG_GO_C23 \ + 0x00c0a4UL +#define DMAE_REG_GO_C24 \ + 0x00c0a8UL +#define DMAE_REG_GO_C25 \ + 0x00c0acUL +#define DMAE_REG_GO_C26 \ + 0x00c0b0UL +#define DMAE_REG_GO_C27 \ + 0x00c0b4UL +#define DMAE_REG_GO_C28 \ + 0x00c0b8UL +#define DMAE_REG_GO_C29 \ + 0x00c0bcUL +#define DMAE_REG_GO_C30 \ + 0x00c0c0UL +#define DMAE_REG_GO_C31 \ + 0x00c0c4UL +#define DMAE_REG_CMD_MEM \ + 0x00c800UL +#define QM_REG_MAXPQSIZETXSEL_0 \ + 0x2f0440UL +#define QM_REG_SDMCMDREADY \ + 0x2f1e10UL +#define QM_REG_SDMCMDADDR \ + 0x2f1e04UL +#define QM_REG_SDMCMDDATALSB \ + 0x2f1e08UL +#define QM_REG_SDMCMDDATAMSB \ + 0x2f1e0cUL +#define QM_REG_SDMCMDGO \ + 0x2f1e14UL +#define QM_REG_RLPFCRD \ + 0x2f4d80UL +#define QM_REG_RLPFINCVAL \ + 0x2f4c80UL +#define QM_REG_RLGLBLCRD \ + 0x2f4400UL +#define QM_REG_RLGLBLINCVAL \ + 0x2f3400UL +#define IGU_REG_ATTENTION_ENABLE \ + 0x18083cUL +#define IGU_REG_ATTN_MSG_ADDR_L \ + 0x180820UL +#define IGU_REG_ATTN_MSG_ADDR_H \ + 0x180824UL +#define MISC_REG_AEU_GENERAL_ATTN_0 \ + 0x008400UL +#define CAU_REG_SB_ADDR_MEMORY \ + 0x1c8000UL +#define CAU_REG_SB_VAR_MEMORY \ + 0x1c6000UL +#define CAU_REG_PI_MEMORY \ + 0x1d0000UL +#define IGU_REG_PF_CONFIGURATION \ + 0x180800UL +#define MISC_REG_AEU_ENABLE1_IGU_OUT_0 \ + 0x00849cUL +#define MISC_REG_AEU_MASK_ATTN_IGU \ + 0x008494UL +#define IGU_REG_CLEANUP_STATUS_0 \ + 0x180980UL +#define IGU_REG_CLEANUP_STATUS_1 \ + 0x180a00UL +#define IGU_REG_CLEANUP_STATUS_2 \ + 0x180a80UL +#define IGU_REG_CLEANUP_STATUS_3 \ + 0x180b00UL +#define IGU_REG_CLEANUP_STATUS_4 \ + 0x180b80UL +#define IGU_REG_COMMAND_REG_32LSB_DATA \ + 0x180840UL +#define IGU_REG_COMMAND_REG_CTRL \ + 0x180848UL +#define IGU_REG_BLOCK_CONFIGURATION_VF_CLEANUP_EN ( \ + 0x1 << 1) +#define IGU_REG_BLOCK_CONFIGURATION_PXP_TPH_INTERFACE_EN ( \ + 0x1 << 0) +#define IGU_REG_MAPPING_MEMORY \ + 0x184000UL +#define MISCS_REG_GENERIC_POR_0 \ + 0x0096d4UL +#define MCP_REG_NVM_CFG4 \ + 0xe0642cUL +#define MCP_REG_NVM_CFG4_FLASH_SIZE ( \ + 0x7 << 0) +#define MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT \ + 0 +#endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h new file mode 100644 index 000000000000..74657d227583 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h @@ -0,0 +1,333 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#ifndef _QED_SP_H +#define _QED_SP_H + +#include +#include +#include +#include +#include +#include +#include "qed.h" +#include "qed_hsi.h" + +enum spq_mode { + QED_SPQ_MODE_BLOCK, /* Client will poll a designated mem. address */ + QED_SPQ_MODE_CB, /* Client supplies a callback */ + QED_SPQ_MODE_EBLOCK, /* QED should block until completion */ +}; + +struct qed_spq_comp_cb { + void (*function)(struct qed_hwfn *, + void *, + union event_ring_data *, + u8 fw_return_code); + void *cookie; +}; + +union ramrod_data { + struct pf_start_ramrod_data pf_start; +}; + +#define EQ_MAX_CREDIT 0xffffffff + +enum spq_priority { + QED_SPQ_PRIORITY_NORMAL, + QED_SPQ_PRIORITY_HIGH, +}; + +union qed_spq_req_comp { + struct qed_spq_comp_cb cb; + u64 *done_addr; +}; + +struct qed_spq_comp_done { + u64 done; + u8 fw_return_code; +}; + +struct qed_spq_entry { + struct list_head list; + + u8 flags; + + /* HSI slow path element */ + struct slow_path_element elem; + + union ramrod_data ramrod; + + enum spq_priority priority; + + /* pending queue for this entry */ + struct list_head *queue; + + enum spq_mode comp_mode; + struct qed_spq_comp_cb comp_cb; + struct qed_spq_comp_done comp_done; /* SPQ_MODE_EBLOCK */ +}; + +struct qed_eq { + struct qed_chain chain; + u8 eq_sb_index; /* index within the SB */ + __le16 *p_fw_cons; /* ptr to index value */ +}; + +struct qed_consq { + struct qed_chain chain; +}; + +struct qed_spq { + spinlock_t lock; /* SPQ lock */ + + struct list_head unlimited_pending; + struct list_head pending; + struct list_head completion_pending; + struct list_head free_pool; + + struct qed_chain chain; + + /* allocated dma-able memory for spq entries (+ramrod data) */ + dma_addr_t p_phys; + struct qed_spq_entry *p_virt; + + /* Used as index for completions (returns on EQ by FW) */ + u16 echo_idx; + + /* Statistics */ + u32 unlimited_pending_count; + u32 normal_count; + u32 high_count; + u32 comp_sent_count; + u32 comp_count; + + u32 cid; +}; + +/** + * @brief qed_spq_post - Posts a Slow hwfn request to FW, or lacking that + * Pends it to the future list. + * + * @param p_hwfn + * @param p_req + * + * @return int + */ +int qed_spq_post(struct qed_hwfn *p_hwfn, + struct qed_spq_entry *p_ent, + u8 *fw_return_code); + +/** + * @brief qed_spq_allocate - Alloocates & initializes the SPQ and EQ. + * + * @param p_hwfn + * + * @return int + */ +int qed_spq_alloc(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_spq_setup - Reset the SPQ to its start state. + * + * @param p_hwfn + */ +void qed_spq_setup(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_spq_deallocate - Deallocates the given SPQ struct. + * + * @param p_hwfn + */ +void qed_spq_free(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_spq_get_entry - Obtain an entrry from the spq + * free pool list. + * + * + * + * @param p_hwfn + * @param pp_ent + * + * @return int + */ +int +qed_spq_get_entry(struct qed_hwfn *p_hwfn, + struct qed_spq_entry **pp_ent); + +/** + * @brief qed_spq_return_entry - Return an entry to spq free + * pool list + * + * @param p_hwfn + * @param p_ent + */ +void qed_spq_return_entry(struct qed_hwfn *p_hwfn, + struct qed_spq_entry *p_ent); +/** + * @brief qed_eq_allocate - Allocates & initializes an EQ struct + * + * @param p_hwfn + * @param num_elem number of elements in the eq + * + * @return struct qed_eq* - a newly allocated structure; NULL upon error. + */ +struct qed_eq *qed_eq_alloc(struct qed_hwfn *p_hwfn, + u16 num_elem); + +/** + * @brief qed_eq_setup - Reset the SPQ to its start state. + * + * @param p_hwfn + * @param p_eq + */ +void qed_eq_setup(struct qed_hwfn *p_hwfn, + struct qed_eq *p_eq); + +/** + * @brief qed_eq_deallocate - deallocates the given EQ struct. + * + * @param p_hwfn + * @param p_eq + */ +void qed_eq_free(struct qed_hwfn *p_hwfn, + struct qed_eq *p_eq); + +/** + * @brief qed_eq_prod_update - update the FW with default EQ producer + * + * @param p_hwfn + * @param prod + */ +void qed_eq_prod_update(struct qed_hwfn *p_hwfn, + u16 prod); + +/** + * @brief qed_eq_completion - Completes currently pending EQ elements + * + * @param p_hwfn + * @param cookie + * + * @return int + */ +int qed_eq_completion(struct qed_hwfn *p_hwfn, + void *cookie); + +/** + * @brief qed_spq_completion - Completes a single event + * + * @param p_hwfn + * @param echo - echo value from cookie (used for determining completion) + * @param p_data - data from cookie (used in callback function if applicable) + * + * @return int + */ +int qed_spq_completion(struct qed_hwfn *p_hwfn, + __le16 echo, + u8 fw_return_code, + union event_ring_data *p_data); + +/** + * @brief qed_spq_get_cid - Given p_hwfn, return cid for the hwfn's SPQ + * + * @param p_hwfn + * + * @return u32 - SPQ CID + */ +u32 qed_spq_get_cid(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_consq_alloc - Allocates & initializes an ConsQ + * struct + * + * @param p_hwfn + * + * @return struct qed_eq* - a newly allocated structure; NULL upon error. + */ +struct qed_consq *qed_consq_alloc(struct qed_hwfn *p_hwfn); + +/** + * @brief qed_consq_setup - Reset the ConsQ to its start + * state. + * + * @param p_hwfn + * @param p_eq + */ +void qed_consq_setup(struct qed_hwfn *p_hwfn, + struct qed_consq *p_consq); + +/** + * @brief qed_consq_free - deallocates the given ConsQ struct. + * + * @param p_hwfn + * @param p_eq + */ +void qed_consq_free(struct qed_hwfn *p_hwfn, + struct qed_consq *p_consq); + +/** + * @file + * + * @brief Slow-hwfn low-level commands (Ramrods) function definitions. + */ + +#define QED_SP_EQ_COMPLETION 0x01 +#define QED_SP_CQE_COMPLETION 0x02 + +struct qed_sp_init_request_params { + size_t ramrod_data_size; + enum spq_mode comp_mode; + struct qed_spq_comp_cb *p_comp_data; +}; + +int qed_sp_init_request(struct qed_hwfn *p_hwfn, + struct qed_spq_entry **pp_ent, + u32 cid, + u16 opaque_fid, + u8 cmd, + u8 protocol, + struct qed_sp_init_request_params *p_params); + +/** + * @brief qed_sp_pf_start - PF Function Start Ramrod + * + * This ramrod is sent to initialize a physical function (PF). It will + * configure the function related parameters and write its completion to the + * event ring specified in the parameters. + * + * Ramrods complete on the common event ring for the PF. This ring is + * allocated by the driver on host memory and its parameters are written + * to the internal RAM of the UStorm by the Function Start Ramrod. + * + * @param p_hwfn + * @param mode + * + * @return int + */ + +int qed_sp_pf_start(struct qed_hwfn *p_hwfn, + enum mf_mode mode); + +/** + * @brief qed_sp_pf_stop - PF Function Stop Ramrod + * + * This ramrod is sent to close a Physical Function (PF). It is the last ramrod + * sent and the last completion written to the PFs Event Ring. This ramrod also + * deletes the context for the Slowhwfn connection on this PF. + * + * @note Not required for first packet. + * + * @param p_hwfn + * + * @return int + */ + +int qed_sp_pf_stop(struct qed_hwfn *p_hwfn); + +#endif diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c new file mode 100644 index 000000000000..6f7879136633 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c @@ -0,0 +1,170 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#include +#include +#include +#include +#include +#include +#include "qed.h" +#include +#include "qed_cxt.h" +#include "qed_hsi.h" +#include "qed_hw.h" +#include "qed_int.h" +#include "qed_reg_addr.h" +#include "qed_sp.h" + +int qed_sp_init_request(struct qed_hwfn *p_hwfn, + struct qed_spq_entry **pp_ent, + u32 cid, + u16 opaque_fid, + u8 cmd, + u8 protocol, + struct qed_sp_init_request_params *p_params) +{ + int rc = -EINVAL; + struct qed_spq_entry *p_ent = NULL; + u32 opaque_cid = opaque_fid << 16 | cid; + + if (!pp_ent) + return -ENOMEM; + + rc = qed_spq_get_entry(p_hwfn, pp_ent); + + if (rc != 0) + return rc; + + p_ent = *pp_ent; + + p_ent->elem.hdr.cid = cpu_to_le32(opaque_cid); + p_ent->elem.hdr.cmd_id = cmd; + p_ent->elem.hdr.protocol_id = protocol; + + p_ent->priority = QED_SPQ_PRIORITY_NORMAL; + p_ent->comp_mode = p_params->comp_mode; + p_ent->comp_done.done = 0; + + switch (p_ent->comp_mode) { + case QED_SPQ_MODE_EBLOCK: + p_ent->comp_cb.cookie = &p_ent->comp_done; + break; + + case QED_SPQ_MODE_BLOCK: + if (!p_params->p_comp_data) + return -EINVAL; + + p_ent->comp_cb.cookie = p_params->p_comp_data->cookie; + break; + + case QED_SPQ_MODE_CB: + if (!p_params->p_comp_data) + p_ent->comp_cb.function = NULL; + else + p_ent->comp_cb = *p_params->p_comp_data; + break; + + default: + DP_NOTICE(p_hwfn, "Unknown SPQE completion mode %d\n", + p_ent->comp_mode); + return -EINVAL; + } + + DP_VERBOSE(p_hwfn, QED_MSG_SPQ, + "Initialized: CID %08x cmd %02x protocol %02x data_addr %lu comp_mode [%s]\n", + opaque_cid, cmd, protocol, + (unsigned long)&p_ent->ramrod, + D_TRINE(p_ent->comp_mode, QED_SPQ_MODE_EBLOCK, + QED_SPQ_MODE_BLOCK, "MODE_EBLOCK", "MODE_BLOCK", + "MODE_CB")); + if (p_params->ramrod_data_size) + memset(&p_ent->ramrod, 0, p_params->ramrod_data_size); + + return 0; +} + +int qed_sp_pf_start(struct qed_hwfn *p_hwfn, + enum mf_mode mode) +{ + struct qed_sp_init_request_params params; + struct pf_start_ramrod_data *p_ramrod = NULL; + u16 sb = qed_int_get_sp_sb_id(p_hwfn); + u8 sb_index = p_hwfn->p_eq->eq_sb_index; + struct qed_spq_entry *p_ent = NULL; + int rc = -EINVAL; + + /* update initial eq producer */ + qed_eq_prod_update(p_hwfn, + qed_chain_get_prod_idx(&p_hwfn->p_eq->chain)); + + memset(¶ms, 0, sizeof(params)); + params.ramrod_data_size = sizeof(*p_ramrod); + params.comp_mode = QED_SPQ_MODE_EBLOCK; + + rc = qed_sp_init_request(p_hwfn, + &p_ent, + qed_spq_get_cid(p_hwfn), + p_hwfn->hw_info.opaque_fid, + COMMON_RAMROD_PF_START, + PROTOCOLID_COMMON, + ¶ms); + if (rc) + return rc; + + p_ramrod = &p_ent->ramrod.pf_start; + + p_ramrod->event_ring_sb_id = cpu_to_le16(sb); + p_ramrod->event_ring_sb_index = sb_index; + p_ramrod->path_id = QED_PATH_ID(p_hwfn); + p_ramrod->dont_log_ramrods = 0; + p_ramrod->log_type_mask = cpu_to_le16(0xf); + p_ramrod->mf_mode = mode; + p_ramrod->outer_tag = p_hwfn->hw_info.ovlan; + + /* Place EQ address in RAMROD */ + p_ramrod->event_ring_pbl_addr.hi = + DMA_HI_LE(p_hwfn->p_eq->chain.pbl.p_phys_table); + p_ramrod->event_ring_pbl_addr.lo = + DMA_LO_LE(p_hwfn->p_eq->chain.pbl.p_phys_table); + p_ramrod->event_ring_num_pages = (u8)p_hwfn->p_eq->chain.page_cnt; + + p_ramrod->consolid_q_pbl_addr.hi = + DMA_HI_LE(p_hwfn->p_consq->chain.pbl.p_phys_table); + p_ramrod->consolid_q_pbl_addr.lo = + DMA_LO_LE(p_hwfn->p_consq->chain.pbl.p_phys_table); + + p_hwfn->hw_info.personality = PERSONALITY_ETH; + + DP_VERBOSE(p_hwfn, QED_MSG_SPQ, + "Setting event_ring_sb [id %04x index %02x], mf [%s] outer_tag [%d]\n", + sb, sb_index, + (p_ramrod->mf_mode == SF) ? "SF" : "Multi-Pf", + p_ramrod->outer_tag); + + return qed_spq_post(p_hwfn, p_ent, NULL); +} + +int qed_sp_pf_stop(struct qed_hwfn *p_hwfn) +{ + struct qed_sp_init_request_params params; + struct qed_spq_entry *p_ent = NULL; + int rc = -EINVAL; + + memset(¶ms, 0, sizeof(params)); + params.comp_mode = QED_SPQ_MODE_EBLOCK; + + rc = qed_sp_init_request(p_hwfn, &p_ent, qed_spq_get_cid(p_hwfn), + p_hwfn->hw_info.opaque_fid, + COMMON_RAMROD_PF_STOP, PROTOCOLID_COMMON, + ¶ms); + if (rc) + return rc; + + return qed_spq_post(p_hwfn, p_ent, NULL); +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c new file mode 100644 index 000000000000..f28ecb197309 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c @@ -0,0 +1,831 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qed.h" +#include "qed_cxt.h" +#include "qed_dev_api.h" +#include "qed_hsi.h" +#include "qed_hw.h" +#include "qed_int.h" +#include "qed_mcp.h" +#include "qed_reg_addr.h" +#include "qed_sp.h" + +/*************************************************************************** +* Structures & Definitions +***************************************************************************/ + +#define SPQ_HIGH_PRI_RESERVE_DEFAULT (1) +#define SPQ_BLOCK_SLEEP_LENGTH (1000) + +/*************************************************************************** +* Blocking Imp. (BLOCK/EBLOCK mode) +***************************************************************************/ +static void qed_spq_blocking_cb(struct qed_hwfn *p_hwfn, + void *cookie, + union event_ring_data *data, + u8 fw_return_code) +{ + struct qed_spq_comp_done *comp_done; + + comp_done = (struct qed_spq_comp_done *)cookie; + + comp_done->done = 0x1; + comp_done->fw_return_code = fw_return_code; + + /* make update visible to waiting thread */ + smp_wmb(); +} + +static int qed_spq_block(struct qed_hwfn *p_hwfn, + struct qed_spq_entry *p_ent, + u8 *p_fw_ret) +{ + int sleep_count = SPQ_BLOCK_SLEEP_LENGTH; + struct qed_spq_comp_done *comp_done; + int rc; + + comp_done = (struct qed_spq_comp_done *)p_ent->comp_cb.cookie; + while (sleep_count) { + /* validate we receive completion update */ + smp_rmb(); + if (comp_done->done == 1) { + if (p_fw_ret) + *p_fw_ret = comp_done->fw_return_code; + return 0; + } + usleep_range(5000, 10000); + sleep_count--; + } + + DP_INFO(p_hwfn, "Ramrod is stuck, requesting MCP drain\n"); + rc = qed_mcp_drain(p_hwfn, p_hwfn->p_main_ptt); + if (rc != 0) + DP_NOTICE(p_hwfn, "MCP drain failed\n"); + + /* Retry after drain */ + sleep_count = SPQ_BLOCK_SLEEP_LENGTH; + while (sleep_count) { + /* validate we receive completion update */ + smp_rmb(); + if (comp_done->done == 1) { + if (p_fw_ret) + *p_fw_ret = comp_done->fw_return_code; + return 0; + } + usleep_range(5000, 10000); + sleep_count--; + } + + if (comp_done->done == 1) { + if (p_fw_ret) + *p_fw_ret = comp_done->fw_return_code; + return 0; + } + + DP_NOTICE(p_hwfn, "Ramrod is stuck, MCP drain failed\n"); + + return -EBUSY; +} + +/*************************************************************************** +* SPQ entries inner API +***************************************************************************/ +static int +qed_spq_fill_entry(struct qed_hwfn *p_hwfn, + struct qed_spq_entry *p_ent) +{ + p_ent->elem.hdr.echo = 0; + p_hwfn->p_spq->echo_idx++; + p_ent->flags = 0; + + switch (p_ent->comp_mode) { + case QED_SPQ_MODE_EBLOCK: + case QED_SPQ_MODE_BLOCK: + p_ent->comp_cb.function = qed_spq_blocking_cb; + break; + case QED_SPQ_MODE_CB: + break; + default: + DP_NOTICE(p_hwfn, "Unknown SPQE completion mode %d\n", + p_ent->comp_mode); + return -EINVAL; + } + + DP_VERBOSE(p_hwfn, QED_MSG_SPQ, + "Ramrod header: [CID 0x%08x CMD 0x%02x protocol 0x%02x] Data pointer: [%08x:%08x] Completion Mode: %s\n", + p_ent->elem.hdr.cid, + p_ent->elem.hdr.cmd_id, + p_ent->elem.hdr.protocol_id, + p_ent->elem.data_ptr.hi, + p_ent->elem.data_ptr.lo, + D_TRINE(p_ent->comp_mode, QED_SPQ_MODE_EBLOCK, + QED_SPQ_MODE_BLOCK, "MODE_EBLOCK", "MODE_BLOCK", + "MODE_CB")); + + return 0; +} + +/*************************************************************************** +* HSI access +***************************************************************************/ +static void qed_spq_hw_initialize(struct qed_hwfn *p_hwfn, + struct qed_spq *p_spq) +{ + u16 pq; + struct qed_cxt_info cxt_info; + struct core_conn_context *p_cxt; + union qed_qm_pq_params pq_params; + int rc; + + cxt_info.iid = p_spq->cid; + + rc = qed_cxt_get_cid_info(p_hwfn, &cxt_info); + + if (rc < 0) { + DP_NOTICE(p_hwfn, "Cannot find context info for cid=%d\n", + p_spq->cid); + return; + } + + p_cxt = cxt_info.p_cxt; + + SET_FIELD(p_cxt->xstorm_ag_context.flags10, + XSTORM_CORE_CONN_AG_CTX_DQ_CF_EN, 1); + SET_FIELD(p_cxt->xstorm_ag_context.flags1, + XSTORM_CORE_CONN_AG_CTX_DQ_CF_ACTIVE, 1); + SET_FIELD(p_cxt->xstorm_ag_context.flags9, + XSTORM_CORE_CONN_AG_CTX_CONSOLID_PROD_CF_EN, 1); + + /* QM physical queue */ + memset(&pq_params, 0, sizeof(pq_params)); + pq_params.core.tc = LB_TC; + pq = qed_get_qm_pq(p_hwfn, PROTOCOLID_CORE, &pq_params); + p_cxt->xstorm_ag_context.physical_q0 = cpu_to_le16(pq); + + p_cxt->xstorm_st_context.spq_base_lo = + DMA_LO_LE(p_spq->chain.p_phys_addr); + p_cxt->xstorm_st_context.spq_base_hi = + DMA_HI_LE(p_spq->chain.p_phys_addr); + + p_cxt->xstorm_st_context.consolid_base_addr.lo = + DMA_LO_LE(p_hwfn->p_consq->chain.p_phys_addr); + p_cxt->xstorm_st_context.consolid_base_addr.hi = + DMA_HI_LE(p_hwfn->p_consq->chain.p_phys_addr); +} + +static int qed_spq_hw_post(struct qed_hwfn *p_hwfn, + struct qed_spq *p_spq, + struct qed_spq_entry *p_ent) +{ + struct qed_chain *p_chain = &p_hwfn->p_spq->chain; + struct slow_path_element *elem; + struct core_db_data db; + + elem = qed_chain_produce(p_chain); + if (!elem) { + DP_NOTICE(p_hwfn, "Failed to produce from SPQ chain\n"); + return -EINVAL; + } + + *elem = p_ent->elem; /* struct assignment */ + + /* send a doorbell on the slow hwfn session */ + memset(&db, 0, sizeof(db)); + SET_FIELD(db.params, CORE_DB_DATA_DEST, DB_DEST_XCM); + SET_FIELD(db.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET); + SET_FIELD(db.params, CORE_DB_DATA_AGG_VAL_SEL, + DQ_XCM_CORE_SPQ_PROD_CMD); + db.agg_flags = DQ_XCM_CORE_DQ_CF_CMD; + + /* validate producer is up to-date */ + rmb(); + + db.spq_prod = cpu_to_le16(qed_chain_get_prod_idx(p_chain)); + + /* do not reorder */ + barrier(); + + DOORBELL(p_hwfn, qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY), *(u32 *)&db); + + /* make sure doorbell is rang */ + mmiowb(); + + DP_VERBOSE(p_hwfn, QED_MSG_SPQ, + "Doorbelled [0x%08x, CID 0x%08x] with Flags: %02x agg_params: %02x, prod: %04x\n", + qed_db_addr(p_spq->cid, DQ_DEMS_LEGACY), + p_spq->cid, db.params, db.agg_flags, + qed_chain_get_prod_idx(p_chain)); + + return 0; +} + +/*************************************************************************** +* Asynchronous events +***************************************************************************/ +static int +qed_async_event_completion(struct qed_hwfn *p_hwfn, + struct event_ring_entry *p_eqe) +{ + DP_NOTICE(p_hwfn, + "Unknown Async completion for protocol: %d\n", + p_eqe->protocol_id); + return -EINVAL; +} + +/*************************************************************************** +* EQ API +***************************************************************************/ +void qed_eq_prod_update(struct qed_hwfn *p_hwfn, + u16 prod) +{ + u32 addr = GTT_BAR0_MAP_REG_USDM_RAM + + USTORM_EQE_CONS_OFFSET(p_hwfn->rel_pf_id); + + REG_WR16(p_hwfn, addr, prod); + + /* keep prod updates ordered */ + mmiowb(); +} + +int qed_eq_completion(struct qed_hwfn *p_hwfn, + void *cookie) + +{ + struct qed_eq *p_eq = cookie; + struct qed_chain *p_chain = &p_eq->chain; + int rc = 0; + + /* take a snapshot of the FW consumer */ + u16 fw_cons_idx = le16_to_cpu(*p_eq->p_fw_cons); + + DP_VERBOSE(p_hwfn, QED_MSG_SPQ, "fw_cons_idx %x\n", fw_cons_idx); + + /* Need to guarantee the fw_cons index we use points to a usuable + * element (to comply with our chain), so our macros would comply + */ + if ((fw_cons_idx & qed_chain_get_usable_per_page(p_chain)) == + qed_chain_get_usable_per_page(p_chain)) + fw_cons_idx += qed_chain_get_unusable_per_page(p_chain); + + /* Complete current segment of eq entries */ + while (fw_cons_idx != qed_chain_get_cons_idx(p_chain)) { + struct event_ring_entry *p_eqe = qed_chain_consume(p_chain); + + if (!p_eqe) { + rc = -EINVAL; + break; + } + + DP_VERBOSE(p_hwfn, QED_MSG_SPQ, + "op %x prot %x res0 %x echo %x fwret %x flags %x\n", + p_eqe->opcode, + p_eqe->protocol_id, + p_eqe->reserved0, + le16_to_cpu(p_eqe->echo), + p_eqe->fw_return_code, + p_eqe->flags); + + if (GET_FIELD(p_eqe->flags, EVENT_RING_ENTRY_ASYNC)) { + if (qed_async_event_completion(p_hwfn, p_eqe)) + rc = -EINVAL; + } else if (qed_spq_completion(p_hwfn, + p_eqe->echo, + p_eqe->fw_return_code, + &p_eqe->data)) { + rc = -EINVAL; + } + + qed_chain_recycle_consumed(p_chain); + } + + qed_eq_prod_update(p_hwfn, qed_chain_get_prod_idx(p_chain)); + + return rc; +} + +struct qed_eq *qed_eq_alloc(struct qed_hwfn *p_hwfn, + u16 num_elem) +{ + struct qed_eq *p_eq; + + /* Allocate EQ struct */ + p_eq = kzalloc(sizeof(*p_eq), GFP_ATOMIC); + if (!p_eq) { + DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_eq'\n"); + return NULL; + } + + /* Allocate and initialize EQ chain*/ + if (qed_chain_alloc(p_hwfn->cdev, + QED_CHAIN_USE_TO_PRODUCE, + QED_CHAIN_MODE_PBL, + num_elem, + sizeof(union event_ring_element), + &p_eq->chain)) { + DP_NOTICE(p_hwfn, "Failed to allocate eq chain\n"); + goto eq_allocate_fail; + } + + /* register EQ completion on the SP SB */ + qed_int_register_cb(p_hwfn, + qed_eq_completion, + p_eq, + &p_eq->eq_sb_index, + &p_eq->p_fw_cons); + + return p_eq; + +eq_allocate_fail: + qed_eq_free(p_hwfn, p_eq); + return NULL; +} + +void qed_eq_setup(struct qed_hwfn *p_hwfn, + struct qed_eq *p_eq) +{ + qed_chain_reset(&p_eq->chain); +} + +void qed_eq_free(struct qed_hwfn *p_hwfn, + struct qed_eq *p_eq) +{ + if (!p_eq) + return; + qed_chain_free(p_hwfn->cdev, &p_eq->chain); + kfree(p_eq); +} + +/*************************************************************************** +* Slow hwfn Queue (spq) +***************************************************************************/ +void qed_spq_setup(struct qed_hwfn *p_hwfn) +{ + struct qed_spq *p_spq = p_hwfn->p_spq; + struct qed_spq_entry *p_virt = NULL; + dma_addr_t p_phys = 0; + unsigned int i = 0; + + INIT_LIST_HEAD(&p_spq->pending); + INIT_LIST_HEAD(&p_spq->completion_pending); + INIT_LIST_HEAD(&p_spq->free_pool); + INIT_LIST_HEAD(&p_spq->unlimited_pending); + spin_lock_init(&p_spq->lock); + + /* SPQ empty pool */ + p_phys = p_spq->p_phys + offsetof(struct qed_spq_entry, ramrod); + p_virt = p_spq->p_virt; + + for (i = 0; i < p_spq->chain.capacity; i++) { + p_virt->elem.data_ptr.hi = DMA_HI_LE(p_phys); + p_virt->elem.data_ptr.lo = DMA_LO_LE(p_phys); + + list_add_tail(&p_virt->list, &p_spq->free_pool); + + p_virt++; + p_phys += sizeof(struct qed_spq_entry); + } + + /* Statistics */ + p_spq->normal_count = 0; + p_spq->comp_count = 0; + p_spq->comp_sent_count = 0; + p_spq->unlimited_pending_count = 0; + p_spq->echo_idx = 0; + + /* SPQ cid, cannot fail */ + qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_CORE, &p_spq->cid); + qed_spq_hw_initialize(p_hwfn, p_spq); + + /* reset the chain itself */ + qed_chain_reset(&p_spq->chain); +} + +int qed_spq_alloc(struct qed_hwfn *p_hwfn) +{ + struct qed_spq *p_spq = NULL; + dma_addr_t p_phys = 0; + struct qed_spq_entry *p_virt = NULL; + + /* SPQ struct */ + p_spq = + kzalloc(sizeof(struct qed_spq), GFP_ATOMIC); + if (!p_spq) { + DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_spq'\n"); + return -ENOMEM; + } + + /* SPQ ring */ + if (qed_chain_alloc(p_hwfn->cdev, + QED_CHAIN_USE_TO_PRODUCE, + QED_CHAIN_MODE_SINGLE, + 0, /* N/A when the mode is SINGLE */ + sizeof(struct slow_path_element), + &p_spq->chain)) { + DP_NOTICE(p_hwfn, "Failed to allocate spq chain\n"); + goto spq_allocate_fail; + } + + /* allocate and fill the SPQ elements (incl. ramrod data list) */ + p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, + p_spq->chain.capacity * + sizeof(struct qed_spq_entry), + &p_phys, + GFP_KERNEL); + + if (!p_virt) + goto spq_allocate_fail; + + p_spq->p_virt = p_virt; + p_spq->p_phys = p_phys; + p_hwfn->p_spq = p_spq; + + return 0; + +spq_allocate_fail: + qed_chain_free(p_hwfn->cdev, &p_spq->chain); + kfree(p_spq); + return -ENOMEM; +} + +void qed_spq_free(struct qed_hwfn *p_hwfn) +{ + struct qed_spq *p_spq = p_hwfn->p_spq; + + if (!p_spq) + return; + + if (p_spq->p_virt) + dma_free_coherent(&p_hwfn->cdev->pdev->dev, + p_spq->chain.capacity * + sizeof(struct qed_spq_entry), + p_spq->p_virt, + p_spq->p_phys); + + qed_chain_free(p_hwfn->cdev, &p_spq->chain); + ; + kfree(p_spq); +} + +int +qed_spq_get_entry(struct qed_hwfn *p_hwfn, + struct qed_spq_entry **pp_ent) +{ + struct qed_spq *p_spq = p_hwfn->p_spq; + struct qed_spq_entry *p_ent = NULL; + int rc = 0; + + spin_lock_bh(&p_spq->lock); + + if (list_empty(&p_spq->free_pool)) { + p_ent = kzalloc(sizeof(*p_ent), GFP_ATOMIC); + if (!p_ent) { + rc = -ENOMEM; + goto out_unlock; + } + p_ent->queue = &p_spq->unlimited_pending; + } else { + p_ent = list_first_entry(&p_spq->free_pool, + struct qed_spq_entry, + list); + list_del(&p_ent->list); + p_ent->queue = &p_spq->pending; + } + + *pp_ent = p_ent; + +out_unlock: + spin_unlock_bh(&p_spq->lock); + return rc; +} + +/* Locked variant; Should be called while the SPQ lock is taken */ +static void __qed_spq_return_entry(struct qed_hwfn *p_hwfn, + struct qed_spq_entry *p_ent) +{ + list_add_tail(&p_ent->list, &p_hwfn->p_spq->free_pool); +} + +void qed_spq_return_entry(struct qed_hwfn *p_hwfn, + struct qed_spq_entry *p_ent) +{ + spin_lock_bh(&p_hwfn->p_spq->lock); + __qed_spq_return_entry(p_hwfn, p_ent); + spin_unlock_bh(&p_hwfn->p_spq->lock); +} + +/** + * @brief qed_spq_add_entry - adds a new entry to the pending + * list. Should be used while lock is being held. + * + * Addes an entry to the pending list is there is room (en empty + * element is available in the free_pool), or else places the + * entry in the unlimited_pending pool. + * + * @param p_hwfn + * @param p_ent + * @param priority + * + * @return int + */ +static int +qed_spq_add_entry(struct qed_hwfn *p_hwfn, + struct qed_spq_entry *p_ent, + enum spq_priority priority) +{ + struct qed_spq *p_spq = p_hwfn->p_spq; + + if (p_ent->queue == &p_spq->unlimited_pending) { + struct qed_spq_entry *p_en2; + + if (list_empty(&p_spq->free_pool)) { + list_add_tail(&p_ent->list, &p_spq->unlimited_pending); + p_spq->unlimited_pending_count++; + + return 0; + } + + p_en2 = list_first_entry(&p_spq->free_pool, + struct qed_spq_entry, + list); + list_del(&p_en2->list); + + /* Strcut assignment */ + *p_en2 = *p_ent; + + kfree(p_ent); + + p_ent = p_en2; + } + + /* entry is to be placed in 'pending' queue */ + switch (priority) { + case QED_SPQ_PRIORITY_NORMAL: + list_add_tail(&p_ent->list, &p_spq->pending); + p_spq->normal_count++; + break; + case QED_SPQ_PRIORITY_HIGH: + list_add(&p_ent->list, &p_spq->pending); + p_spq->high_count++; + break; + default: + return -EINVAL; + } + + return 0; +} + +/*************************************************************************** +* Accessor +***************************************************************************/ +u32 qed_spq_get_cid(struct qed_hwfn *p_hwfn) +{ + if (!p_hwfn->p_spq) + return 0xffffffff; /* illegal */ + return p_hwfn->p_spq->cid; +} + +/*************************************************************************** +* Posting new Ramrods +***************************************************************************/ +static int qed_spq_post_list(struct qed_hwfn *p_hwfn, + struct list_head *head, + u32 keep_reserve) +{ + struct qed_spq *p_spq = p_hwfn->p_spq; + int rc; + + while (qed_chain_get_elem_left(&p_spq->chain) > keep_reserve && + !list_empty(head)) { + struct qed_spq_entry *p_ent = + list_first_entry(head, struct qed_spq_entry, list); + list_del(&p_ent->list); + list_add_tail(&p_ent->list, &p_spq->completion_pending); + p_spq->comp_sent_count++; + + rc = qed_spq_hw_post(p_hwfn, p_spq, p_ent); + if (rc) { + list_del(&p_ent->list); + __qed_spq_return_entry(p_hwfn, p_ent); + return rc; + } + } + + return 0; +} + +static int qed_spq_pend_post(struct qed_hwfn *p_hwfn) +{ + struct qed_spq *p_spq = p_hwfn->p_spq; + struct qed_spq_entry *p_ent = NULL; + + while (!list_empty(&p_spq->free_pool)) { + if (list_empty(&p_spq->unlimited_pending)) + break; + + p_ent = list_first_entry(&p_spq->unlimited_pending, + struct qed_spq_entry, + list); + if (!p_ent) + return -EINVAL; + + list_del(&p_ent->list); + + qed_spq_add_entry(p_hwfn, p_ent, p_ent->priority); + } + + return qed_spq_post_list(p_hwfn, &p_spq->pending, + SPQ_HIGH_PRI_RESERVE_DEFAULT); +} + +int qed_spq_post(struct qed_hwfn *p_hwfn, + struct qed_spq_entry *p_ent, + u8 *fw_return_code) +{ + int rc = 0; + struct qed_spq *p_spq = p_hwfn ? p_hwfn->p_spq : NULL; + bool b_ret_ent = true; + + if (!p_hwfn) + return -EINVAL; + + if (!p_ent) { + DP_NOTICE(p_hwfn, "Got a NULL pointer\n"); + return -EINVAL; + } + + /* Complete the entry */ + rc = qed_spq_fill_entry(p_hwfn, p_ent); + + spin_lock_bh(&p_spq->lock); + + /* Check return value after LOCK is taken for cleaner error flow */ + if (rc) + goto spq_post_fail; + + /* Add the request to the pending queue */ + rc = qed_spq_add_entry(p_hwfn, p_ent, p_ent->priority); + if (rc) + goto spq_post_fail; + + rc = qed_spq_pend_post(p_hwfn); + if (rc) { + /* Since it's possible that pending failed for a different + * entry [although unlikely], the failed entry was already + * dealt with; No need to return it here. + */ + b_ret_ent = false; + goto spq_post_fail; + } + + spin_unlock_bh(&p_spq->lock); + + if (p_ent->comp_mode == QED_SPQ_MODE_EBLOCK) { + /* For entries in QED BLOCK mode, the completion code cannot + * perform the necessary cleanup - if it did, we couldn't + * access p_ent here to see whether it's successful or not. + * Thus, after gaining the answer perform the cleanup here. + */ + rc = qed_spq_block(p_hwfn, p_ent, fw_return_code); + if (rc) + goto spq_post_fail2; + + /* return to pool */ + qed_spq_return_entry(p_hwfn, p_ent); + } + return rc; + +spq_post_fail2: + spin_lock_bh(&p_spq->lock); + list_del(&p_ent->list); + qed_chain_return_produced(&p_spq->chain); + +spq_post_fail: + /* return to the free pool */ + if (b_ret_ent) + __qed_spq_return_entry(p_hwfn, p_ent); + spin_unlock_bh(&p_spq->lock); + + return rc; +} + +int qed_spq_completion(struct qed_hwfn *p_hwfn, + __le16 echo, + u8 fw_return_code, + union event_ring_data *p_data) +{ + struct qed_spq *p_spq; + struct qed_spq_entry *p_ent = NULL; + struct qed_spq_entry *tmp; + struct qed_spq_entry *found = NULL; + int rc; + + if (!p_hwfn) + return -EINVAL; + + p_spq = p_hwfn->p_spq; + if (!p_spq) + return -EINVAL; + + spin_lock_bh(&p_spq->lock); + list_for_each_entry_safe(p_ent, tmp, &p_spq->completion_pending, + list) { + if (p_ent->elem.hdr.echo == echo) { + list_del(&p_ent->list); + + qed_chain_return_produced(&p_spq->chain); + p_spq->comp_count++; + found = p_ent; + break; + } + } + + /* Release lock before callback, as callback may post + * an additional ramrod. + */ + spin_unlock_bh(&p_spq->lock); + + if (!found) { + DP_NOTICE(p_hwfn, + "Failed to find an entry this EQE completes\n"); + return -EEXIST; + } + + DP_VERBOSE(p_hwfn, QED_MSG_SPQ, "Complete: func %p cookie %p)\n", + p_ent->comp_cb.function, p_ent->comp_cb.cookie); + if (found->comp_cb.function) + found->comp_cb.function(p_hwfn, found->comp_cb.cookie, p_data, + fw_return_code); + + if (found->comp_mode != QED_SPQ_MODE_EBLOCK) + /* EBLOCK is responsible for freeing its own entry */ + qed_spq_return_entry(p_hwfn, found); + + /* Attempt to post pending requests */ + spin_lock_bh(&p_spq->lock); + rc = qed_spq_pend_post(p_hwfn); + spin_unlock_bh(&p_spq->lock); + + return rc; +} + +struct qed_consq *qed_consq_alloc(struct qed_hwfn *p_hwfn) +{ + struct qed_consq *p_consq; + + /* Allocate ConsQ struct */ + p_consq = kzalloc(sizeof(*p_consq), GFP_ATOMIC); + if (!p_consq) { + DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_consq'\n"); + return NULL; + } + + /* Allocate and initialize EQ chain*/ + if (qed_chain_alloc(p_hwfn->cdev, + QED_CHAIN_USE_TO_PRODUCE, + QED_CHAIN_MODE_PBL, + QED_CHAIN_PAGE_SIZE / 0x80, + 0x80, + &p_consq->chain)) { + DP_NOTICE(p_hwfn, "Failed to allocate consq chain"); + goto consq_allocate_fail; + } + + return p_consq; + +consq_allocate_fail: + qed_consq_free(p_hwfn, p_consq); + return NULL; +} + +void qed_consq_setup(struct qed_hwfn *p_hwfn, + struct qed_consq *p_consq) +{ + qed_chain_reset(&p_consq->chain); +} + +void qed_consq_free(struct qed_hwfn *p_hwfn, + struct qed_consq *p_consq) +{ + if (!p_consq) + return; + qed_chain_free(p_hwfn->cdev, &p_consq->chain); + kfree(p_consq); +} -- cgit v1.2.3 From 25c089d78f3833edf614fc377e75e9cf848562f5 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Mon, 26 Oct 2015 11:02:26 +0200 Subject: qed: Add basic L2 interface This patch adds a public API for a network driver to work on top of QED. The interface itself is very minimal - it's mostly infrastructure, as the only content it has after this patch is a query for HW-based information required for the creation of a network interface [I.e., no actual protocol-specific configurations are supported]. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/Makefile | 2 +- drivers/net/ethernet/qlogic/qed/qed.h | 14 +++++ drivers/net/ethernet/qlogic/qed/qed_dev.c | 62 ++++++++++++++++++++++ drivers/net/ethernet/qlogic/qed/qed_hsi.h | 1 + drivers/net/ethernet/qlogic/qed/qed_l2.c | 87 +++++++++++++++++++++++++++++++ 5 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/qlogic/qed/qed_l2.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qed/Makefile b/drivers/net/ethernet/qlogic/qed/Makefile index 6969b5c66929..5c2fd57236fe 100644 --- a/drivers/net/ethernet/qlogic/qed/Makefile +++ b/drivers/net/ethernet/qlogic/qed/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_QED) := qed.o qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o qed_init_ops.o \ - qed_int.o qed_main.o qed_mcp.o qed_sp_commands.o qed_spq.o + qed_int.o qed_main.o qed_mcp.o qed_sp_commands.o qed_spq.o qed_l2.o diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index a63ef3120d78..e03371d3e622 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -25,6 +25,7 @@ #include #include "qed_hsi.h" +extern const struct qed_common_ops qed_common_ops_pass; #define DRV_MODULE_VERSION "8.4.0.0" #define MAX_HWFNS_PER_DEVICE (4) @@ -91,13 +92,22 @@ struct qed_qm_iids { enum QED_RESOURCES { QED_SB, + QED_L2_QUEUE, QED_VPORT, + QED_RSS_ENG, QED_PQ, QED_RL, + QED_MAC, + QED_VLAN, QED_ILT, QED_MAX_RESC, }; +enum QED_FEATURE { + QED_PF_L2_QUE, + QED_MAX_FEATURES, +}; + struct qed_hw_info { /* PCI personality */ enum qed_pci_personality personality; @@ -105,6 +115,7 @@ struct qed_hw_info { /* Resource Allocation scheme results */ u32 resc_start[QED_MAX_RESC]; u32 resc_num[QED_MAX_RESC]; + u32 feat_num[QED_MAX_FEATURES]; #define RESC_START(_p_hwfn, resc) ((_p_hwfn)->hw_info.resc_start[resc]) #define RESC_NUM(_p_hwfn, resc) ((_p_hwfn)->hw_info.resc_num[resc]) @@ -266,6 +277,9 @@ struct qed_hwfn { struct qed_mcp_info *mcp_info; + struct qed_hw_cid_data *p_tx_cids; + struct qed_hw_cid_data *p_rx_cids; + struct qed_dmae_info dmae_info; /* QM init */ diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 5b845220ae8c..3243cb4160c3 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -89,6 +89,15 @@ void qed_resc_free(struct qed_dev *cdev) kfree(cdev->reset_stats); + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + kfree(p_hwfn->p_tx_cids); + p_hwfn->p_tx_cids = NULL; + kfree(p_hwfn->p_rx_cids); + p_hwfn->p_rx_cids = NULL; + } + for_each_hwfn(cdev, i) { struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; @@ -202,6 +211,29 @@ int qed_resc_alloc(struct qed_dev *cdev) if (!cdev->fw_data) return -ENOMEM; + /* Allocate Memory for the Queue->CID mapping */ + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + int tx_size = sizeof(struct qed_hw_cid_data) * + RESC_NUM(p_hwfn, QED_L2_QUEUE); + int rx_size = sizeof(struct qed_hw_cid_data) * + RESC_NUM(p_hwfn, QED_L2_QUEUE); + + p_hwfn->p_tx_cids = kzalloc(tx_size, GFP_KERNEL); + if (!p_hwfn->p_tx_cids) { + DP_NOTICE(p_hwfn, + "Failed to allocate memory for Tx Cids\n"); + goto alloc_err; + } + + p_hwfn->p_rx_cids = kzalloc(rx_size, GFP_KERNEL); + if (!p_hwfn->p_rx_cids) { + DP_NOTICE(p_hwfn, + "Failed to allocate memory for Rx Cids\n"); + goto alloc_err; + } + } + for_each_hwfn(cdev, i) { struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; @@ -881,6 +913,20 @@ static void get_function_id(struct qed_hwfn *p_hwfn) PXP_CONCRETE_FID_PORT); } +static void qed_hw_set_feat(struct qed_hwfn *p_hwfn) +{ + u32 *feat_num = p_hwfn->hw_info.feat_num; + int num_features = 1; + + feat_num[QED_PF_L2_QUE] = min_t(u32, RESC_NUM(p_hwfn, QED_SB) / + num_features, + RESC_NUM(p_hwfn, QED_L2_QUEUE)); + DP_VERBOSE(p_hwfn, NETIF_MSG_PROBE, + "#PF_L2_QUEUES=%d #SBS=%d num_features=%d\n", + feat_num[QED_PF_L2_QUE], RESC_NUM(p_hwfn, QED_SB), + num_features); +} + static void qed_hw_get_resc(struct qed_hwfn *p_hwfn) { u32 *resc_start = p_hwfn->hw_info.resc_start; @@ -893,29 +939,45 @@ static void qed_hw_get_resc(struct qed_hwfn *p_hwfn) resc_num[QED_SB] = min_t(u32, (MAX_SB_PER_PATH_BB / num_funcs), qed_int_get_num_sbs(p_hwfn, NULL)); + resc_num[QED_L2_QUEUE] = MAX_NUM_L2_QUEUES_BB / num_funcs; resc_num[QED_VPORT] = MAX_NUM_VPORTS_BB / num_funcs; + resc_num[QED_RSS_ENG] = ETH_RSS_ENGINE_NUM_BB / num_funcs; resc_num[QED_PQ] = MAX_QM_TX_QUEUES_BB / num_funcs; resc_num[QED_RL] = 8; + resc_num[QED_MAC] = ETH_NUM_MAC_FILTERS / num_funcs; + resc_num[QED_VLAN] = (ETH_NUM_VLAN_FILTERS - 1 /*For vlan0*/) / + num_funcs; resc_num[QED_ILT] = 950; for (i = 0; i < QED_MAX_RESC; i++) resc_start[i] = resc_num[i] * p_hwfn->rel_pf_id; + qed_hw_set_feat(p_hwfn); + DP_VERBOSE(p_hwfn, NETIF_MSG_PROBE, "The numbers for each resource are:\n" "SB = %d start = %d\n" + "L2_QUEUE = %d start = %d\n" "VPORT = %d start = %d\n" "PQ = %d start = %d\n" "RL = %d start = %d\n" + "MAC = %d start = %d\n" + "VLAN = %d start = %d\n" "ILT = %d start = %d\n", p_hwfn->hw_info.resc_num[QED_SB], p_hwfn->hw_info.resc_start[QED_SB], + p_hwfn->hw_info.resc_num[QED_L2_QUEUE], + p_hwfn->hw_info.resc_start[QED_L2_QUEUE], p_hwfn->hw_info.resc_num[QED_VPORT], p_hwfn->hw_info.resc_start[QED_VPORT], p_hwfn->hw_info.resc_num[QED_PQ], p_hwfn->hw_info.resc_start[QED_PQ], p_hwfn->hw_info.resc_num[QED_RL], p_hwfn->hw_info.resc_start[QED_RL], + p_hwfn->hw_info.resc_num[QED_MAC], + p_hwfn->hw_info.resc_start[QED_MAC], + p_hwfn->hw_info.resc_num[QED_VLAN], + p_hwfn->hw_info.resc_start[QED_VLAN], p_hwfn->hw_info.resc_num[QED_ILT], p_hwfn->hw_info.resc_start[QED_ILT]); } diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 61c15a57c267..27f2c005e2b0 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -17,6 +17,7 @@ #include #include #include +#include struct qed_hwfn; struct qed_ptt; diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c new file mode 100644 index 000000000000..f2e76024409a --- /dev/null +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -0,0 +1,87 @@ +/* QLogic qed NIC Driver + * Copyright (c) 2015 QLogic Corporation + * + * This software is available under the terms of the GNU General Public License + * (GPL) Version 2, available from the file COPYING in the main directory of + * this source tree. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qed.h" +#include +#include "qed_cxt.h" +#include "qed_dev_api.h" +#include +#include "qed_hsi.h" +#include "qed_hw.h" +#include "qed_int.h" +#include "qed_reg_addr.h" +#include "qed_sp.h" + +static int qed_fill_eth_dev_info(struct qed_dev *cdev, + struct qed_dev_eth_info *info) +{ + int i; + + memset(info, 0, sizeof(*info)); + + info->num_tc = 1; + + if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { + for_each_hwfn(cdev, i) + info->num_queues += FEAT_NUM(&cdev->hwfns[i], + QED_PF_L2_QUE); + if (cdev->int_params.fp_msix_cnt) + info->num_queues = min_t(u8, info->num_queues, + cdev->int_params.fp_msix_cnt); + } else { + info->num_queues = cdev->num_hwfns; + } + + info->num_vlan_filters = RESC_NUM(&cdev->hwfns[0], QED_VLAN); + ether_addr_copy(info->port_mac, + cdev->hwfns[0].hw_info.hw_mac_addr); + + qed_fill_dev_info(cdev, &info->common); + + return 0; +} + +static const struct qed_eth_ops qed_eth_ops_pass = { + .common = &qed_common_ops_pass, + .fill_dev_info = &qed_fill_eth_dev_info, +}; + +const struct qed_eth_ops *qed_get_eth_ops(u32 version) +{ + if (version != QED_ETH_INTERFACE_VERSION) { + pr_notice("Cannot supply ethtool operations [%08x != %08x]\n", + version, QED_ETH_INTERFACE_VERSION); + return NULL; + } + + return &qed_eth_ops_pass; +} +EXPORT_SYMBOL(qed_get_eth_ops); + +void qed_put_eth_ops(void) +{ + /* TODO - reference count for module? */ +} +EXPORT_SYMBOL(qed_put_eth_ops); -- cgit v1.2.3 From e712d52b9f2a8ecf14ba0a2ec9a80ed0b194c4a1 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Mon, 26 Oct 2015 11:02:27 +0200 Subject: qede: Add basic Network driver The Qlogic Everest Driver for Ethernet is the Ethernet specific module for QL4xxx ethernet products by Qlogic. This patch adds a very minimal PCI driver, one that doesn't yet register a network device, but one that does interact with qed and does a basic initialization of the HW. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/Kconfig | 5 + drivers/net/ethernet/qlogic/Makefile | 1 + drivers/net/ethernet/qlogic/qede/Makefile | 3 + drivers/net/ethernet/qlogic/qede/qede.h | 73 ++++++ drivers/net/ethernet/qlogic/qede/qede_main.c | 354 +++++++++++++++++++++++++++ 5 files changed, 436 insertions(+) create mode 100644 drivers/net/ethernet/qlogic/qede/Makefile create mode 100644 drivers/net/ethernet/qlogic/qede/qede.h create mode 100644 drivers/net/ethernet/qlogic/qede/qede_main.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig index 58c3fb388f46..30a6f246dfc9 100644 --- a/drivers/net/ethernet/qlogic/Kconfig +++ b/drivers/net/ethernet/qlogic/Kconfig @@ -97,4 +97,9 @@ config QED ---help--- This enables the support for ... +config QEDE + tristate "QLogic QED 25/40/100Gb Ethernet NIC" + depends on QED + ---help--- + This enables the support for ... endif # NET_VENDOR_QLOGIC diff --git a/drivers/net/ethernet/qlogic/Makefile b/drivers/net/ethernet/qlogic/Makefile index 7600138268ee..cee90e05beb8 100644 --- a/drivers/net/ethernet/qlogic/Makefile +++ b/drivers/net/ethernet/qlogic/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_QLCNIC) += qlcnic/ obj-$(CONFIG_QLGE) += qlge/ obj-$(CONFIG_NETXEN_NIC) += netxen/ obj-$(CONFIG_QED) += qed/ +obj-$(CONFIG_QEDE)+= qede/ diff --git a/drivers/net/ethernet/qlogic/qede/Makefile b/drivers/net/ethernet/qlogic/qede/Makefile new file mode 100644 index 000000000000..bedfe9fc736b --- /dev/null +++ b/drivers/net/ethernet/qlogic/qede/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_QEDE) := qede.o + +qede-y := qede_main.o diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h new file mode 100644 index 000000000000..7e2bcfae0db9 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -0,0 +1,73 @@ +/* QLogic qede NIC Driver +* Copyright (c) 2015 QLogic Corporation +* +* This software is available under the terms of the GNU General Public License +* (GPL) Version 2, available from the file COPYING in the main directory of +* this source tree. +*/ + +#ifndef _QEDE_H_ +#define _QEDE_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define QEDE_MAJOR_VERSION 8 +#define QEDE_MINOR_VERSION 4 +#define QEDE_REVISION_VERSION 0 +#define QEDE_ENGINEERING_VERSION 0 +#define DRV_MODULE_VERSION __stringify(QEDE_MAJOR_VERSION) "." \ + __stringify(QEDE_MINOR_VERSION) "." \ + __stringify(QEDE_REVISION_VERSION) "." \ + __stringify(QEDE_ENGINEERING_VERSION) + +#define QEDE_ETH_INTERFACE_VERSION 300 + +#define DRV_MODULE_SYM qede + +struct qede_dev { + struct qed_dev *cdev; + struct net_device *ndev; + struct pci_dev *pdev; + + u32 dp_module; + u8 dp_level; + + const struct qed_eth_ops *ops; + + struct qed_dev_eth_info dev_info; +#define QEDE_MAX_RSS_CNT(edev) ((edev)->dev_info.num_queues) +#define QEDE_MAX_TSS_CNT(edev) ((edev)->dev_info.num_queues * \ + (edev)->dev_info.num_tc) + + u16 num_rss; + u8 num_tc; +#define QEDE_RSS_CNT(edev) ((edev)->num_rss) +#define QEDE_TSS_CNT(edev) ((edev)->num_rss * \ + (edev)->num_tc) +#define QEDE_TSS_IDX(edev, txqidx) ((txqidx) % (edev)->num_rss) +#define QEDE_TC_IDX(edev, txqidx) ((txqidx) / (edev)->num_rss) + + struct qed_int_info int_info; + unsigned char primary_mac[ETH_ALEN]; + + /* Smaller private varaiant of the RTNL lock */ + struct mutex qede_lock; + u32 state; /* Protected by qede_lock */ +}; + +/* Debug print definitions */ +#define DP_NAME(edev) ((edev)->ndev->name) + +#endif /* _QEDE_H_ */ diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c new file mode 100644 index 000000000000..02ed6dbf55a7 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -0,0 +1,354 @@ +/* QLogic qede NIC Driver +* Copyright (c) 2015 QLogic Corporation +* +* This software is available under the terms of the GNU General Public License +* (GPL) Version 2, available from the file COPYING in the main directory of +* this source tree. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qede.h" + +static const char version[] = "QLogic QL4xxx 40G/100G Ethernet Driver qede " + DRV_MODULE_VERSION "\n"; + +MODULE_DESCRIPTION("QLogic 40G/100G Ethernet Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_MODULE_VERSION); + +static uint debug; +module_param(debug, uint, 0); +MODULE_PARM_DESC(debug, " Default debug msglevel"); + +static const struct qed_eth_ops *qed_ops; + +#define CHIP_NUM_57980S_40 0x1634 +#define CHIP_NUM_57980S_10 0x1635 +#define CHIP_NUM_57980S_MF 0x1636 +#define CHIP_NUM_57980S_100 0x1644 +#define CHIP_NUM_57980S_50 0x1654 +#define CHIP_NUM_57980S_25 0x1656 + +#ifndef PCI_DEVICE_ID_NX2_57980E +#define PCI_DEVICE_ID_57980S_40 CHIP_NUM_57980S_40 +#define PCI_DEVICE_ID_57980S_10 CHIP_NUM_57980S_10 +#define PCI_DEVICE_ID_57980S_MF CHIP_NUM_57980S_MF +#define PCI_DEVICE_ID_57980S_100 CHIP_NUM_57980S_100 +#define PCI_DEVICE_ID_57980S_50 CHIP_NUM_57980S_50 +#define PCI_DEVICE_ID_57980S_25 CHIP_NUM_57980S_25 +#endif + +static const struct pci_device_id qede_pci_tbl[] = { + { PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_40), 0 }, + { PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_10), 0 }, + { PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_MF), 0 }, + { PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_100), 0 }, + { PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_50), 0 }, + { PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_25), 0 }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, qede_pci_tbl); + +static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id); + +#define TX_TIMEOUT (5 * HZ) + +static void qede_remove(struct pci_dev *pdev); + +static struct pci_driver qede_pci_driver = { + .name = "qede", + .id_table = qede_pci_tbl, + .probe = qede_probe, + .remove = qede_remove, +}; + +static +int __init qede_init(void) +{ + int ret; + u32 qed_ver; + + pr_notice("qede_init: %s\n", version); + + qed_ver = qed_get_protocol_version(QED_PROTOCOL_ETH); + if (qed_ver != QEDE_ETH_INTERFACE_VERSION) { + pr_notice("Version mismatch [%08x != %08x]\n", + qed_ver, + QEDE_ETH_INTERFACE_VERSION); + return -EINVAL; + } + + qed_ops = qed_get_eth_ops(QEDE_ETH_INTERFACE_VERSION); + if (!qed_ops) { + pr_notice("Failed to get qed ethtool operations\n"); + return -EINVAL; + } + + ret = pci_register_driver(&qede_pci_driver); + if (ret) { + pr_notice("Failed to register driver\n"); + qed_put_eth_ops(); + return -EINVAL; + } + + return 0; +} + +static void __exit qede_cleanup(void) +{ + pr_notice("qede_cleanup called\n"); + + pci_unregister_driver(&qede_pci_driver); + qed_put_eth_ops(); +} + +module_init(qede_init); +module_exit(qede_cleanup); + +/* ------------------------------------------------------------------------- + * START OF PROBE / REMOVE + * ------------------------------------------------------------------------- + */ + +static struct qede_dev *qede_alloc_etherdev(struct qed_dev *cdev, + struct pci_dev *pdev, + struct qed_dev_eth_info *info, + u32 dp_module, + u8 dp_level) +{ + struct net_device *ndev; + struct qede_dev *edev; + + ndev = alloc_etherdev_mqs(sizeof(*edev), + info->num_queues, + info->num_queues); + if (!ndev) { + pr_err("etherdev allocation failed\n"); + return NULL; + } + + edev = netdev_priv(ndev); + edev->ndev = ndev; + edev->cdev = cdev; + edev->pdev = pdev; + edev->dp_module = dp_module; + edev->dp_level = dp_level; + edev->ops = qed_ops; + + DP_INFO(edev, "Allocated netdev with 64 tx queues and 64 rx queues\n"); + + SET_NETDEV_DEV(ndev, &pdev->dev); + + memcpy(&edev->dev_info, info, sizeof(*info)); + + edev->num_tc = edev->dev_info.num_tc; + + return edev; +} + +static void qede_init_ndev(struct qede_dev *edev) +{ + struct net_device *ndev = edev->ndev; + struct pci_dev *pdev = edev->pdev; + u32 hw_features; + + pci_set_drvdata(pdev, ndev); + + ndev->mem_start = edev->dev_info.common.pci_mem_start; + ndev->base_addr = ndev->mem_start; + ndev->mem_end = edev->dev_info.common.pci_mem_end; + ndev->irq = edev->dev_info.common.pci_irq; + + ndev->watchdog_timeo = TX_TIMEOUT; + + /* user-changeble features */ + hw_features = NETIF_F_GRO | NETIF_F_SG | + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_TSO | NETIF_F_TSO6; + + ndev->vlan_features = hw_features | NETIF_F_RXHASH | NETIF_F_RXCSUM | + NETIF_F_HIGHDMA; + ndev->features = hw_features | NETIF_F_RXHASH | NETIF_F_RXCSUM | + NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HIGHDMA | + NETIF_F_HW_VLAN_CTAG_TX; + + ndev->hw_features = hw_features; + + /* Set network device HW mac */ + ether_addr_copy(edev->ndev->dev_addr, edev->dev_info.common.hw_mac); +} + +/* This function converts from 32b param to two params of level and module + * Input 32b decoding: + * b31 - enable all NOTICE prints. NOTICE prints are for deviation from the + * 'happy' flow, e.g. memory allocation failed. + * b30 - enable all INFO prints. INFO prints are for major steps in the flow + * and provide important parameters. + * b29-b0 - per-module bitmap, where each bit enables VERBOSE prints of that + * module. VERBOSE prints are for tracking the specific flow in low level. + * + * Notice that the level should be that of the lowest required logs. + */ +static void qede_config_debug(uint debug, u32 *p_dp_module, u8 *p_dp_level) +{ + *p_dp_level = QED_LEVEL_NOTICE; + *p_dp_module = 0; + + if (debug & QED_LOG_VERBOSE_MASK) { + *p_dp_level = QED_LEVEL_VERBOSE; + *p_dp_module = (debug & 0x3FFFFFFF); + } else if (debug & QED_LOG_INFO_MASK) { + *p_dp_level = QED_LEVEL_INFO; + } else if (debug & QED_LOG_NOTICE_MASK) { + *p_dp_level = QED_LEVEL_NOTICE; + } +} + +static void qede_update_pf_params(struct qed_dev *cdev) +{ + struct qed_pf_params pf_params; + + /* 16 rx + 16 tx */ + memset(&pf_params, 0, sizeof(struct qed_pf_params)); + pf_params.eth_pf_params.num_cons = 32; + qed_ops->common->update_pf_params(cdev, &pf_params); +} + +enum qede_probe_mode { + QEDE_PROBE_NORMAL, +}; + +static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, + enum qede_probe_mode mode) +{ + struct qed_slowpath_params params; + struct qed_dev_eth_info dev_info; + struct qede_dev *edev; + struct qed_dev *cdev; + int rc; + + if (unlikely(dp_level & QED_LEVEL_INFO)) + pr_notice("Starting qede probe\n"); + + cdev = qed_ops->common->probe(pdev, QED_PROTOCOL_ETH, + dp_module, dp_level); + if (!cdev) { + rc = -ENODEV; + goto err0; + } + + qede_update_pf_params(cdev); + + /* Start the Slowpath-process */ + memset(¶ms, 0, sizeof(struct qed_slowpath_params)); + params.int_mode = QED_INT_MODE_MSIX; + params.drv_major = QEDE_MAJOR_VERSION; + params.drv_minor = QEDE_MINOR_VERSION; + params.drv_rev = QEDE_REVISION_VERSION; + params.drv_eng = QEDE_ENGINEERING_VERSION; + strlcpy(params.name, "qede LAN", QED_DRV_VER_STR_SIZE); + rc = qed_ops->common->slowpath_start(cdev, ¶ms); + if (rc) { + pr_notice("Cannot start slowpath\n"); + goto err1; + } + + /* Learn information crucial for qede to progress */ + rc = qed_ops->fill_dev_info(cdev, &dev_info); + if (rc) + goto err2; + + edev = qede_alloc_etherdev(cdev, pdev, &dev_info, dp_module, + dp_level); + if (!edev) { + rc = -ENOMEM; + goto err2; + } + + qede_init_ndev(edev); + + edev->ops->common->set_id(cdev, edev->ndev->name, DRV_MODULE_VERSION); + + DP_INFO(edev, "Ending successfully qede probe\n"); + + return 0; + +err2: + qed_ops->common->slowpath_stop(cdev); +err1: + qed_ops->common->remove(cdev); +err0: + return rc; +} + +static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + u32 dp_module = 0; + u8 dp_level = 0; + + qede_config_debug(debug, &dp_module, &dp_level); + + return __qede_probe(pdev, dp_module, dp_level, + QEDE_PROBE_NORMAL); +} + +enum qede_remove_mode { + QEDE_REMOVE_NORMAL, +}; + +static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) +{ + struct net_device *ndev = pci_get_drvdata(pdev); + struct qede_dev *edev = netdev_priv(ndev); + struct qed_dev *cdev = edev->cdev; + + DP_INFO(edev, "Starting qede_remove\n"); + + edev->ops->common->set_power_state(cdev, PCI_D0); + + pci_set_drvdata(pdev, NULL); + + free_netdev(ndev); + + /* Use global ops since we've freed edev */ + qed_ops->common->slowpath_stop(cdev); + qed_ops->common->remove(cdev); + + pr_notice("Ending successfully qede_remove\n"); +} + +static void qede_remove(struct pci_dev *pdev) +{ + __qede_remove(pdev, QEDE_REMOVE_NORMAL); +} -- cgit v1.2.3 From cee4d26448c1000ccc1711eb5e6ed4c15f18fa83 Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Mon, 26 Oct 2015 11:02:28 +0200 Subject: qed: Add slowpath L2 support This patch adds to the qed the support to configure various L2 elements, such as channels and basic filtering conditions. It also enhances its public API to allow qede to later utilize this functionality. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_dev.c | 114 ++ drivers/net/ethernet/qlogic/qed/qed_dev_api.h | 58 + drivers/net/ethernet/qlogic/qed/qed_hsi.h | 294 +++++ drivers/net/ethernet/qlogic/qed/qed_l2.c | 1605 +++++++++++++++++++++++++ drivers/net/ethernet/qlogic/qed/qed_main.c | 10 + drivers/net/ethernet/qlogic/qed/qed_mcp.c | 16 + drivers/net/ethernet/qlogic/qed/qed_mcp.h | 13 + drivers/net/ethernet/qlogic/qed/qed_sp.h | 27 + drivers/net/ethernet/qlogic/qed/qed_spq.c | 29 + 9 files changed, 2166 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 3243cb4160c3..3d1bdbf9ade1 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -799,6 +799,60 @@ int qed_hw_stop(struct qed_dev *cdev) return rc; } +void qed_hw_stop_fastpath(struct qed_dev *cdev) +{ + int i, j; + + for_each_hwfn(cdev, j) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[j]; + struct qed_ptt *p_ptt = p_hwfn->p_main_ptt; + + DP_VERBOSE(p_hwfn, + NETIF_MSG_IFDOWN, + "Shutting down the fastpath\n"); + + qed_wr(p_hwfn, p_ptt, + NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF, 0x1); + + qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_TCP, 0x0); + qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_UDP, 0x0); + qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_FCOE, 0x0); + qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_ROCE, 0x0); + qed_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_OPENFLOW, 0x0); + + qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_CONN, 0x0); + qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK, 0x0); + for (i = 0; i < QED_HW_STOP_RETRY_LIMIT; i++) { + if ((!qed_rd(p_hwfn, p_ptt, + TM_REG_PF_SCAN_ACTIVE_CONN)) && + (!qed_rd(p_hwfn, p_ptt, + TM_REG_PF_SCAN_ACTIVE_TASK))) + break; + + usleep_range(1000, 2000); + } + if (i == QED_HW_STOP_RETRY_LIMIT) + DP_NOTICE(p_hwfn, + "Timers linear scans are not over [Connection %02x Tasks %02x]\n", + (u8)qed_rd(p_hwfn, p_ptt, + TM_REG_PF_SCAN_ACTIVE_CONN), + (u8)qed_rd(p_hwfn, p_ptt, + TM_REG_PF_SCAN_ACTIVE_TASK)); + + qed_int_igu_init_pure_rt(p_hwfn, p_ptt, false, false); + + /* Need to wait 1ms to guarantee SBs are cleared */ + usleep_range(1000, 2000); + } +} + +void qed_hw_start_fastpath(struct qed_hwfn *p_hwfn) +{ + /* Re-open incoming traffic */ + qed_wr(p_hwfn, p_hwfn->p_main_ptt, + NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF, 0x0); +} + static int qed_reg_assert(struct qed_hwfn *hwfn, struct qed_ptt *ptt, u32 reg, bool expected) @@ -1337,3 +1391,63 @@ void qed_chain_free(struct qed_dev *cdev, p_chain->p_virt_addr, p_chain->p_phys_addr); } + +int qed_fw_l2_queue(struct qed_hwfn *p_hwfn, + u16 src_id, u16 *dst_id) +{ + if (src_id >= RESC_NUM(p_hwfn, QED_L2_QUEUE)) { + u16 min, max; + + min = (u16)RESC_START(p_hwfn, QED_L2_QUEUE); + max = min + RESC_NUM(p_hwfn, QED_L2_QUEUE); + DP_NOTICE(p_hwfn, + "l2_queue id [%d] is not valid, available indices [%d - %d]\n", + src_id, min, max); + + return -EINVAL; + } + + *dst_id = RESC_START(p_hwfn, QED_L2_QUEUE) + src_id; + + return 0; +} + +int qed_fw_vport(struct qed_hwfn *p_hwfn, + u8 src_id, u8 *dst_id) +{ + if (src_id >= RESC_NUM(p_hwfn, QED_VPORT)) { + u8 min, max; + + min = (u8)RESC_START(p_hwfn, QED_VPORT); + max = min + RESC_NUM(p_hwfn, QED_VPORT); + DP_NOTICE(p_hwfn, + "vport id [%d] is not valid, available indices [%d - %d]\n", + src_id, min, max); + + return -EINVAL; + } + + *dst_id = RESC_START(p_hwfn, QED_VPORT) + src_id; + + return 0; +} + +int qed_fw_rss_eng(struct qed_hwfn *p_hwfn, + u8 src_id, u8 *dst_id) +{ + if (src_id >= RESC_NUM(p_hwfn, QED_RSS_ENG)) { + u8 min, max; + + min = (u8)RESC_START(p_hwfn, QED_RSS_ENG); + max = min + RESC_NUM(p_hwfn, QED_RSS_ENG); + DP_NOTICE(p_hwfn, + "rss_eng id [%d] is not valid, available indices [%d - %d]\n", + src_id, min, max); + + return -EINVAL; + } + + *dst_id = RESC_START(p_hwfn, QED_RSS_ENG) + src_id; + + return 0; +} diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h index 5051af5f378e..773070d04ab8 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h +++ b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h @@ -86,6 +86,25 @@ int qed_hw_init(struct qed_dev *cdev, */ int qed_hw_stop(struct qed_dev *cdev); +/** + * @brief qed_hw_stop_fastpath -should be called incase + * slowpath is still required for the device, + * but fastpath is not. + * + * @param cdev + * + */ +void qed_hw_stop_fastpath(struct qed_dev *cdev); + +/** + * @brief qed_hw_start_fastpath -restart fastpath traffic, + * only if hw_stop_fastpath was called + * + * @param cdev + * + */ +void qed_hw_start_fastpath(struct qed_hwfn *p_hwfn); + /** * @brief qed_hw_reset - * @@ -206,6 +225,45 @@ qed_chain_alloc(struct qed_dev *cdev, void qed_chain_free(struct qed_dev *cdev, struct qed_chain *p_chain); +/** + * @@brief qed_fw_l2_queue - Get absolute L2 queue ID + * + * @param p_hwfn + * @param src_id - relative to p_hwfn + * @param dst_id - absolute per engine + * + * @return int + */ +int qed_fw_l2_queue(struct qed_hwfn *p_hwfn, + u16 src_id, + u16 *dst_id); + +/** + * @@brief qed_fw_vport - Get absolute vport ID + * + * @param p_hwfn + * @param src_id - relative to p_hwfn + * @param dst_id - absolute per engine + * + * @return int + */ +int qed_fw_vport(struct qed_hwfn *p_hwfn, + u8 src_id, + u8 *dst_id); + +/** + * @@brief qed_fw_rss_eng - Get absolute RSS engine ID + * + * @param p_hwfn + * @param src_id - relative to p_hwfn + * @param dst_id - absolute per engine + * + * @return int + */ +int qed_fw_rss_eng(struct qed_hwfn *p_hwfn, + u8 src_id, + u8 *dst_id); + /** * *@brief Cleanup of previous driver remains prior to load * diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 27f2c005e2b0..5909823463ab 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -2561,6 +2561,300 @@ struct eth_conn_context { struct ustorm_eth_conn_st_ctx ustorm_st_context; }; +enum eth_filter_action { + ETH_FILTER_ACTION_REMOVE, + ETH_FILTER_ACTION_ADD, + ETH_FILTER_ACTION_REPLACE, + MAX_ETH_FILTER_ACTION +}; + +struct eth_filter_cmd { + u8 type /* Filter Type (MAC/VLAN/Pair/VNI) */; + u8 vport_id /* the vport id */; + u8 action /* filter command action: add/remove/replace */; + u8 reserved0; + __le32 vni; + __le16 mac_lsb; + __le16 mac_mid; + __le16 mac_msb; + __le16 vlan_id; +}; + +struct eth_filter_cmd_header { + u8 rx; + u8 tx; + u8 cmd_cnt; + u8 assert_on_error; + u8 reserved1[4]; +}; + +enum eth_filter_type { + ETH_FILTER_TYPE_MAC, + ETH_FILTER_TYPE_VLAN, + ETH_FILTER_TYPE_PAIR, + ETH_FILTER_TYPE_INNER_MAC, + ETH_FILTER_TYPE_INNER_VLAN, + ETH_FILTER_TYPE_INNER_PAIR, + ETH_FILTER_TYPE_INNER_MAC_VNI_PAIR, + ETH_FILTER_TYPE_MAC_VNI_PAIR, + ETH_FILTER_TYPE_VNI, + MAX_ETH_FILTER_TYPE +}; + +enum eth_ramrod_cmd_id { + ETH_RAMROD_UNUSED, + ETH_RAMROD_VPORT_START /* VPort Start Ramrod */, + ETH_RAMROD_VPORT_UPDATE /* VPort Update Ramrod */, + ETH_RAMROD_VPORT_STOP /* VPort Stop Ramrod */, + ETH_RAMROD_RX_QUEUE_START /* RX Queue Start Ramrod */, + ETH_RAMROD_RX_QUEUE_STOP /* RX Queue Stop Ramrod */, + ETH_RAMROD_TX_QUEUE_START /* TX Queue Start Ramrod */, + ETH_RAMROD_TX_QUEUE_STOP /* TX Queue Stop Ramrod */, + ETH_RAMROD_FILTERS_UPDATE /* Add or Remove Mac/Vlan/Pair filters */, + ETH_RAMROD_RX_QUEUE_UPDATE /* RX Queue Update Ramrod */, + ETH_RAMROD_RESERVED, + ETH_RAMROD_RESERVED2, + ETH_RAMROD_RESERVED3, + ETH_RAMROD_RESERVED4, + ETH_RAMROD_RESERVED5, + ETH_RAMROD_RESERVED6, + ETH_RAMROD_RESERVED7, + ETH_RAMROD_RESERVED8, + MAX_ETH_RAMROD_CMD_ID +}; + +struct eth_vport_rss_config { + __le16 capabilities; +#define ETH_VPORT_RSS_CONFIG_IPV4_CAPABILITY_MASK 0x1 +#define ETH_VPORT_RSS_CONFIG_IPV4_CAPABILITY_SHIFT 0 +#define ETH_VPORT_RSS_CONFIG_IPV6_CAPABILITY_MASK 0x1 +#define ETH_VPORT_RSS_CONFIG_IPV6_CAPABILITY_SHIFT 1 +#define ETH_VPORT_RSS_CONFIG_IPV4_TCP_CAPABILITY_MASK 0x1 +#define ETH_VPORT_RSS_CONFIG_IPV4_TCP_CAPABILITY_SHIFT 2 +#define ETH_VPORT_RSS_CONFIG_IPV6_TCP_CAPABILITY_MASK 0x1 +#define ETH_VPORT_RSS_CONFIG_IPV6_TCP_CAPABILITY_SHIFT 3 +#define ETH_VPORT_RSS_CONFIG_IPV4_UDP_CAPABILITY_MASK 0x1 +#define ETH_VPORT_RSS_CONFIG_IPV4_UDP_CAPABILITY_SHIFT 4 +#define ETH_VPORT_RSS_CONFIG_IPV6_UDP_CAPABILITY_MASK 0x1 +#define ETH_VPORT_RSS_CONFIG_IPV6_UDP_CAPABILITY_SHIFT 5 +#define ETH_VPORT_RSS_CONFIG_EN_5_TUPLE_CAPABILITY_MASK 0x1 +#define ETH_VPORT_RSS_CONFIG_EN_5_TUPLE_CAPABILITY_SHIFT 6 +#define ETH_VPORT_RSS_CONFIG_CALC_4TUP_TCP_FRAG_MASK 0x1 +#define ETH_VPORT_RSS_CONFIG_CALC_4TUP_TCP_FRAG_SHIFT 7 +#define ETH_VPORT_RSS_CONFIG_CALC_4TUP_UDP_FRAG_MASK 0x1 +#define ETH_VPORT_RSS_CONFIG_CALC_4TUP_UDP_FRAG_SHIFT 8 +#define ETH_VPORT_RSS_CONFIG_RESERVED0_MASK 0x7F +#define ETH_VPORT_RSS_CONFIG_RESERVED0_SHIFT 9 + u8 rss_id; + u8 rss_mode; + u8 update_rss_key; + u8 update_rss_ind_table; + u8 update_rss_capabilities; + u8 tbl_size; + __le32 reserved2[2]; + __le16 indirection_table[ETH_RSS_IND_TABLE_ENTRIES_NUM]; + __le32 rss_key[ETH_RSS_KEY_SIZE_REGS]; + __le32 reserved3[2]; +}; + +enum eth_vport_rss_mode { + ETH_VPORT_RSS_MODE_DISABLED, + ETH_VPORT_RSS_MODE_REGULAR, + MAX_ETH_VPORT_RSS_MODE +}; + +struct eth_vport_rx_mode { + __le16 state; +#define ETH_VPORT_RX_MODE_UCAST_DROP_ALL_MASK 0x1 +#define ETH_VPORT_RX_MODE_UCAST_DROP_ALL_SHIFT 0 +#define ETH_VPORT_RX_MODE_UCAST_ACCEPT_ALL_MASK 0x1 +#define ETH_VPORT_RX_MODE_UCAST_ACCEPT_ALL_SHIFT 1 +#define ETH_VPORT_RX_MODE_UCAST_ACCEPT_UNMATCHED_MASK 0x1 +#define ETH_VPORT_RX_MODE_UCAST_ACCEPT_UNMATCHED_SHIFT 2 +#define ETH_VPORT_RX_MODE_MCAST_DROP_ALL_MASK 0x1 +#define ETH_VPORT_RX_MODE_MCAST_DROP_ALL_SHIFT 3 +#define ETH_VPORT_RX_MODE_MCAST_ACCEPT_ALL_MASK 0x1 +#define ETH_VPORT_RX_MODE_MCAST_ACCEPT_ALL_SHIFT 4 +#define ETH_VPORT_RX_MODE_BCAST_ACCEPT_ALL_MASK 0x1 +#define ETH_VPORT_RX_MODE_BCAST_ACCEPT_ALL_SHIFT 5 +#define ETH_VPORT_RX_MODE_RESERVED1_MASK 0x3FF +#define ETH_VPORT_RX_MODE_RESERVED1_SHIFT 6 + __le16 reserved2[3]; +}; + +struct eth_vport_tpa_param { + u64 reserved[2]; +}; + +struct eth_vport_tx_mode { + __le16 state; +#define ETH_VPORT_TX_MODE_UCAST_DROP_ALL_MASK 0x1 +#define ETH_VPORT_TX_MODE_UCAST_DROP_ALL_SHIFT 0 +#define ETH_VPORT_TX_MODE_UCAST_ACCEPT_ALL_MASK 0x1 +#define ETH_VPORT_TX_MODE_UCAST_ACCEPT_ALL_SHIFT 1 +#define ETH_VPORT_TX_MODE_MCAST_DROP_ALL_MASK 0x1 +#define ETH_VPORT_TX_MODE_MCAST_DROP_ALL_SHIFT 2 +#define ETH_VPORT_TX_MODE_MCAST_ACCEPT_ALL_MASK 0x1 +#define ETH_VPORT_TX_MODE_MCAST_ACCEPT_ALL_SHIFT 3 +#define ETH_VPORT_TX_MODE_BCAST_ACCEPT_ALL_MASK 0x1 +#define ETH_VPORT_TX_MODE_BCAST_ACCEPT_ALL_SHIFT 4 +#define ETH_VPORT_TX_MODE_RESERVED1_MASK 0x7FF +#define ETH_VPORT_TX_MODE_RESERVED1_SHIFT 5 + __le16 reserved2[3]; +}; + +struct rx_queue_start_ramrod_data { + __le16 rx_queue_id; + __le16 num_of_pbl_pages; + __le16 bd_max_bytes; + __le16 sb_id; + u8 sb_index; + u8 vport_id; + u8 default_rss_queue_flg; + u8 complete_cqe_flg; + u8 complete_event_flg; + u8 stats_counter_id; + u8 pin_context; + u8 pxp_tph_valid_bd; + u8 pxp_tph_valid_pkt; + u8 pxp_st_hint; + __le16 pxp_st_index; + u8 reserved[4]; + struct regpair cqe_pbl_addr; + struct regpair bd_base; + struct regpair sge_base; +}; + +struct rx_queue_stop_ramrod_data { + __le16 rx_queue_id; + u8 complete_cqe_flg; + u8 complete_event_flg; + u8 vport_id; + u8 reserved[3]; +}; + +struct rx_queue_update_ramrod_data { + __le16 rx_queue_id; + u8 complete_cqe_flg; + u8 complete_event_flg; + u8 init_sge_ring_flg; + u8 vport_id; + u8 pxp_tph_valid_sge; + u8 pxp_st_hint; + __le16 pxp_st_index; + u8 reserved[6]; + struct regpair sge_base; +}; + +struct tx_queue_start_ramrod_data { + __le16 sb_id; + u8 sb_index; + u8 vport_id; + u8 tc; + u8 stats_counter_id; + __le16 qm_pq_id; + u8 flags; +#define TX_QUEUE_START_RAMROD_DATA_DISABLE_OPPORTUNISTIC_MASK 0x1 +#define TX_QUEUE_START_RAMROD_DATA_DISABLE_OPPORTUNISTIC_SHIFT 0 +#define TX_QUEUE_START_RAMROD_DATA_TEST_MODE_PKT_DUP_MASK 0x1 +#define TX_QUEUE_START_RAMROD_DATA_TEST_MODE_PKT_DUP_SHIFT 1 +#define TX_QUEUE_START_RAMROD_DATA_TEST_MODE_TX_DEST_MASK 0x1 +#define TX_QUEUE_START_RAMROD_DATA_TEST_MODE_TX_DEST_SHIFT 2 +#define TX_QUEUE_START_RAMROD_DATA_RESERVED0_MASK 0x1F +#define TX_QUEUE_START_RAMROD_DATA_RESERVED0_SHIFT 3 + u8 pin_context; + u8 pxp_tph_valid_bd; + u8 pxp_tph_valid_pkt; + __le16 pxp_st_index; + u8 pxp_st_hint; + u8 reserved1[3]; + __le16 queue_zone_id; + __le16 test_dup_count; + __le16 pbl_size; + struct regpair pbl_base_addr; +}; + +struct tx_queue_stop_ramrod_data { + __le16 reserved[4]; +}; + +struct vport_filter_update_ramrod_data { + struct eth_filter_cmd_header filter_cmd_hdr; + struct eth_filter_cmd filter_cmds[ETH_FILTER_RULES_COUNT]; +}; + +struct vport_start_ramrod_data { + u8 vport_id; + u8 sw_fid; + __le16 mtu; + u8 drop_ttl0_en; + u8 inner_vlan_removal_en; + struct eth_vport_rx_mode rx_mode; + struct eth_vport_tx_mode tx_mode; + struct eth_vport_tpa_param tpa_param; + __le16 sge_buff_size; + u8 max_sges_num; + u8 tx_switching_en; + u8 anti_spoofing_en; + u8 default_vlan_en; + u8 handle_ptp_pkts; + u8 silent_vlan_removal_en; + __le16 default_vlan; + u8 untagged; + u8 reserved[7]; +}; + +struct vport_stop_ramrod_data { + u8 vport_id; + u8 reserved[7]; +}; + +struct vport_update_ramrod_data_cmn { + u8 vport_id; + u8 update_rx_active_flg; + u8 rx_active_flg; + u8 update_tx_active_flg; + u8 tx_active_flg; + u8 update_rx_mode_flg; + u8 update_tx_mode_flg; + u8 update_approx_mcast_flg; + u8 update_rss_flg; + u8 update_inner_vlan_removal_en_flg; + u8 inner_vlan_removal_en; + u8 update_tpa_param_flg; + u8 update_tpa_en_flg; + u8 update_sge_param_flg; + __le16 sge_buff_size; + u8 max_sges_num; + u8 update_tx_switching_en_flg; + u8 tx_switching_en; + u8 update_anti_spoofing_en_flg; + u8 anti_spoofing_en; + u8 update_handle_ptp_pkts; + u8 handle_ptp_pkts; + u8 update_default_vlan_en_flg; + u8 default_vlan_en; + u8 update_default_vlan_flg; + __le16 default_vlan; + u8 update_accept_any_vlan_flg; + u8 accept_any_vlan; + u8 silent_vlan_removal_en; + u8 reserved; +}; + +struct vport_update_ramrod_mcast { + __le32 bins[ETH_MULTICAST_MAC_BINS_IN_REGS]; +}; + +struct vport_update_ramrod_data { + struct vport_update_ramrod_data_cmn common; + struct eth_vport_rx_mode rx_mode; + struct eth_vport_tx_mode tx_mode; + struct eth_vport_tpa_param tpa_param; + struct vport_update_ramrod_mcast approx_mcast; + struct eth_vport_rss_config rss_config; +}; + struct mstorm_eth_conn_ag_ctx { u8 byte0 /* cdu_validation */; u8 byte1 /* state */; diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index f2e76024409a..2772573593a4 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -34,6 +34,1202 @@ #include "qed_reg_addr.h" #include "qed_sp.h" +enum qed_rss_caps { + QED_RSS_IPV4 = 0x1, + QED_RSS_IPV6 = 0x2, + QED_RSS_IPV4_TCP = 0x4, + QED_RSS_IPV6_TCP = 0x8, + QED_RSS_IPV4_UDP = 0x10, + QED_RSS_IPV6_UDP = 0x20, +}; + +/* Should be the same as ETH_RSS_IND_TABLE_ENTRIES_NUM */ +#define QED_RSS_IND_TABLE_SIZE 128 +#define QED_RSS_KEY_SIZE 10 /* size in 32b chunks */ + +struct qed_rss_params { + u8 update_rss_config; + u8 rss_enable; + u8 rss_eng_id; + u8 update_rss_capabilities; + u8 update_rss_ind_table; + u8 update_rss_key; + u8 rss_caps; + u8 rss_table_size_log; + u16 rss_ind_table[QED_RSS_IND_TABLE_SIZE]; + u32 rss_key[QED_RSS_KEY_SIZE]; +}; + +enum qed_filter_opcode { + QED_FILTER_ADD, + QED_FILTER_REMOVE, + QED_FILTER_MOVE, + QED_FILTER_REPLACE, /* Delete all MACs and add new one instead */ + QED_FILTER_FLUSH, /* Removes all filters */ +}; + +enum qed_filter_ucast_type { + QED_FILTER_MAC, + QED_FILTER_VLAN, + QED_FILTER_MAC_VLAN, + QED_FILTER_INNER_MAC, + QED_FILTER_INNER_VLAN, + QED_FILTER_INNER_PAIR, + QED_FILTER_INNER_MAC_VNI_PAIR, + QED_FILTER_MAC_VNI_PAIR, + QED_FILTER_VNI, +}; + +struct qed_filter_ucast { + enum qed_filter_opcode opcode; + enum qed_filter_ucast_type type; + u8 is_rx_filter; + u8 is_tx_filter; + u8 vport_to_add_to; + u8 vport_to_remove_from; + unsigned char mac[ETH_ALEN]; + u8 assert_on_error; + u16 vlan; + u32 vni; +}; + +struct qed_filter_mcast { + /* MOVE is not supported for multicast */ + enum qed_filter_opcode opcode; + u8 vport_to_add_to; + u8 vport_to_remove_from; + u8 num_mc_addrs; +#define QED_MAX_MC_ADDRS 64 + unsigned char mac[QED_MAX_MC_ADDRS][ETH_ALEN]; +}; + +struct qed_filter_accept_flags { + u8 update_rx_mode_config; + u8 update_tx_mode_config; + u8 rx_accept_filter; + u8 tx_accept_filter; +#define QED_ACCEPT_NONE 0x01 +#define QED_ACCEPT_UCAST_MATCHED 0x02 +#define QED_ACCEPT_UCAST_UNMATCHED 0x04 +#define QED_ACCEPT_MCAST_MATCHED 0x08 +#define QED_ACCEPT_MCAST_UNMATCHED 0x10 +#define QED_ACCEPT_BCAST 0x20 +}; + +struct qed_sp_vport_update_params { + u16 opaque_fid; + u8 vport_id; + u8 update_vport_active_rx_flg; + u8 vport_active_rx_flg; + u8 update_vport_active_tx_flg; + u8 vport_active_tx_flg; + u8 update_approx_mcast_flg; + unsigned long bins[8]; + struct qed_rss_params *rss_params; + struct qed_filter_accept_flags accept_flags; +}; + +#define QED_MAX_SGES_NUM 16 +#define CRC32_POLY 0x1edc6f41 + +static int qed_sp_vport_start(struct qed_hwfn *p_hwfn, + u32 concrete_fid, + u16 opaque_fid, + u8 vport_id, + u16 mtu, + u8 drop_ttl0_flg, + u8 inner_vlan_removal_en_flg) +{ + struct qed_sp_init_request_params params; + struct vport_start_ramrod_data *p_ramrod = NULL; + struct qed_spq_entry *p_ent = NULL; + int rc = -EINVAL; + u16 rx_mode = 0; + u8 abs_vport_id = 0; + + rc = qed_fw_vport(p_hwfn, vport_id, &abs_vport_id); + if (rc != 0) + return rc; + + memset(¶ms, 0, sizeof(params)); + params.ramrod_data_size = sizeof(*p_ramrod); + params.comp_mode = QED_SPQ_MODE_EBLOCK; + + rc = qed_sp_init_request(p_hwfn, &p_ent, + qed_spq_get_cid(p_hwfn), + opaque_fid, + ETH_RAMROD_VPORT_START, + PROTOCOLID_ETH, + ¶ms); + if (rc) + return rc; + + p_ramrod = &p_ent->ramrod.vport_start; + p_ramrod->vport_id = abs_vport_id; + + p_ramrod->mtu = cpu_to_le16(mtu); + p_ramrod->inner_vlan_removal_en = inner_vlan_removal_en_flg; + p_ramrod->drop_ttl0_en = drop_ttl0_flg; + + SET_FIELD(rx_mode, ETH_VPORT_RX_MODE_UCAST_DROP_ALL, 1); + SET_FIELD(rx_mode, ETH_VPORT_RX_MODE_MCAST_DROP_ALL, 1); + + p_ramrod->rx_mode.state = cpu_to_le16(rx_mode); + + /* TPA related fields */ + memset(&p_ramrod->tpa_param, 0, + sizeof(struct eth_vport_tpa_param)); + + /* Software Function ID in hwfn (PFs are 0 - 15, VFs are 16 - 135) */ + p_ramrod->sw_fid = qed_concrete_to_sw_fid(p_hwfn->cdev, + concrete_fid); + + return qed_spq_post(p_hwfn, p_ent, NULL); +} + +static int +qed_sp_vport_update_rss(struct qed_hwfn *p_hwfn, + struct vport_update_ramrod_data *p_ramrod, + struct qed_rss_params *p_params) +{ + struct eth_vport_rss_config *rss = &p_ramrod->rss_config; + u16 abs_l2_queue = 0, capabilities = 0; + int rc = 0, i; + + if (!p_params) { + p_ramrod->common.update_rss_flg = 0; + return rc; + } + + BUILD_BUG_ON(QED_RSS_IND_TABLE_SIZE != + ETH_RSS_IND_TABLE_ENTRIES_NUM); + + rc = qed_fw_rss_eng(p_hwfn, p_params->rss_eng_id, &rss->rss_id); + if (rc) + return rc; + + p_ramrod->common.update_rss_flg = p_params->update_rss_config; + rss->update_rss_capabilities = p_params->update_rss_capabilities; + rss->update_rss_ind_table = p_params->update_rss_ind_table; + rss->update_rss_key = p_params->update_rss_key; + + rss->rss_mode = p_params->rss_enable ? + ETH_VPORT_RSS_MODE_REGULAR : + ETH_VPORT_RSS_MODE_DISABLED; + + SET_FIELD(capabilities, + ETH_VPORT_RSS_CONFIG_IPV4_CAPABILITY, + !!(p_params->rss_caps & QED_RSS_IPV4)); + SET_FIELD(capabilities, + ETH_VPORT_RSS_CONFIG_IPV6_CAPABILITY, + !!(p_params->rss_caps & QED_RSS_IPV6)); + SET_FIELD(capabilities, + ETH_VPORT_RSS_CONFIG_IPV4_TCP_CAPABILITY, + !!(p_params->rss_caps & QED_RSS_IPV4_TCP)); + SET_FIELD(capabilities, + ETH_VPORT_RSS_CONFIG_IPV6_TCP_CAPABILITY, + !!(p_params->rss_caps & QED_RSS_IPV6_TCP)); + SET_FIELD(capabilities, + ETH_VPORT_RSS_CONFIG_IPV4_UDP_CAPABILITY, + !!(p_params->rss_caps & QED_RSS_IPV4_UDP)); + SET_FIELD(capabilities, + ETH_VPORT_RSS_CONFIG_IPV6_UDP_CAPABILITY, + !!(p_params->rss_caps & QED_RSS_IPV6_UDP)); + rss->tbl_size = p_params->rss_table_size_log; + + rss->capabilities = cpu_to_le16(capabilities); + + DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP, + "update rss flag %d, rss_mode = %d, update_caps = %d, capabilities = %d, update_ind = %d, update_rss_key = %d\n", + p_ramrod->common.update_rss_flg, + rss->rss_mode, rss->update_rss_capabilities, + capabilities, rss->update_rss_ind_table, + rss->update_rss_key); + + for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) { + rc = qed_fw_l2_queue(p_hwfn, + (u8)p_params->rss_ind_table[i], + &abs_l2_queue); + if (rc) + return rc; + + rss->indirection_table[i] = cpu_to_le16(abs_l2_queue); + DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP, "i= %d, queue = %d\n", + i, rss->indirection_table[i]); + } + + for (i = 0; i < 10; i++) + rss->rss_key[i] = cpu_to_le32(p_params->rss_key[i]); + + return rc; +} + +static void +qed_sp_update_accept_mode(struct qed_hwfn *p_hwfn, + struct vport_update_ramrod_data *p_ramrod, + struct qed_filter_accept_flags accept_flags) +{ + p_ramrod->common.update_rx_mode_flg = + accept_flags.update_rx_mode_config; + + p_ramrod->common.update_tx_mode_flg = + accept_flags.update_tx_mode_config; + + /* Set Rx mode accept flags */ + if (p_ramrod->common.update_rx_mode_flg) { + u8 accept_filter = accept_flags.rx_accept_filter; + u16 state = 0; + + SET_FIELD(state, ETH_VPORT_RX_MODE_UCAST_DROP_ALL, + !(!!(accept_filter & QED_ACCEPT_UCAST_MATCHED) || + !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED))); + + SET_FIELD(state, ETH_VPORT_RX_MODE_UCAST_ACCEPT_UNMATCHED, + !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED)); + + SET_FIELD(state, ETH_VPORT_RX_MODE_MCAST_DROP_ALL, + !(!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) || + !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED))); + + SET_FIELD(state, ETH_VPORT_RX_MODE_MCAST_ACCEPT_ALL, + (!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) && + !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED))); + + SET_FIELD(state, ETH_VPORT_RX_MODE_BCAST_ACCEPT_ALL, + !!(accept_filter & QED_ACCEPT_BCAST)); + + p_ramrod->rx_mode.state = cpu_to_le16(state); + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "p_ramrod->rx_mode.state = 0x%x\n", state); + } + + /* Set Tx mode accept flags */ + if (p_ramrod->common.update_tx_mode_flg) { + u8 accept_filter = accept_flags.tx_accept_filter; + u16 state = 0; + + SET_FIELD(state, ETH_VPORT_TX_MODE_UCAST_DROP_ALL, + !!(accept_filter & QED_ACCEPT_NONE)); + + SET_FIELD(state, ETH_VPORT_TX_MODE_UCAST_ACCEPT_ALL, + (!!(accept_filter & QED_ACCEPT_UCAST_MATCHED) && + !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED))); + + SET_FIELD(state, ETH_VPORT_TX_MODE_MCAST_DROP_ALL, + !!(accept_filter & QED_ACCEPT_NONE)); + + SET_FIELD(state, ETH_VPORT_TX_MODE_MCAST_ACCEPT_ALL, + (!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) && + !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED))); + + SET_FIELD(state, ETH_VPORT_TX_MODE_BCAST_ACCEPT_ALL, + !!(accept_filter & QED_ACCEPT_BCAST)); + + p_ramrod->tx_mode.state = cpu_to_le16(state); + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "p_ramrod->tx_mode.state = 0x%x\n", state); + } +} + +static void +qed_sp_update_mcast_bin(struct qed_hwfn *p_hwfn, + struct vport_update_ramrod_data *p_ramrod, + struct qed_sp_vport_update_params *p_params) +{ + int i; + + memset(&p_ramrod->approx_mcast.bins, 0, + sizeof(p_ramrod->approx_mcast.bins)); + + if (p_params->update_approx_mcast_flg) { + p_ramrod->common.update_approx_mcast_flg = 1; + for (i = 0; i < ETH_MULTICAST_MAC_BINS_IN_REGS; i++) { + u32 *p_bins = (u32 *)p_params->bins; + __le32 val = cpu_to_le32(p_bins[i]); + + p_ramrod->approx_mcast.bins[i] = val; + } + } +} + +static int +qed_sp_vport_update(struct qed_hwfn *p_hwfn, + struct qed_sp_vport_update_params *p_params, + enum spq_mode comp_mode, + struct qed_spq_comp_cb *p_comp_data) +{ + struct qed_rss_params *p_rss_params = p_params->rss_params; + struct vport_update_ramrod_data_cmn *p_cmn; + struct qed_sp_init_request_params sp_params; + struct vport_update_ramrod_data *p_ramrod = NULL; + struct qed_spq_entry *p_ent = NULL; + u8 abs_vport_id = 0; + int rc = -EINVAL; + + rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id); + if (rc != 0) + return rc; + + memset(&sp_params, 0, sizeof(sp_params)); + sp_params.ramrod_data_size = sizeof(*p_ramrod); + sp_params.comp_mode = comp_mode; + sp_params.p_comp_data = p_comp_data; + + rc = qed_sp_init_request(p_hwfn, &p_ent, + qed_spq_get_cid(p_hwfn), + p_params->opaque_fid, + ETH_RAMROD_VPORT_UPDATE, + PROTOCOLID_ETH, + &sp_params); + if (rc) + return rc; + + /* Copy input params to ramrod according to FW struct */ + p_ramrod = &p_ent->ramrod.vport_update; + p_cmn = &p_ramrod->common; + + p_cmn->vport_id = abs_vport_id; + p_cmn->rx_active_flg = p_params->vport_active_rx_flg; + p_cmn->update_rx_active_flg = p_params->update_vport_active_rx_flg; + p_cmn->tx_active_flg = p_params->vport_active_tx_flg; + p_cmn->update_tx_active_flg = p_params->update_vport_active_tx_flg; + + rc = qed_sp_vport_update_rss(p_hwfn, p_ramrod, p_rss_params); + if (rc) { + /* Return spq entry which is taken in qed_sp_init_request()*/ + qed_spq_return_entry(p_hwfn, p_ent); + return rc; + } + + /* Update mcast bins for VFs, PF doesn't use this functionality */ + qed_sp_update_mcast_bin(p_hwfn, p_ramrod, p_params); + + qed_sp_update_accept_mode(p_hwfn, p_ramrod, p_params->accept_flags); + return qed_spq_post(p_hwfn, p_ent, NULL); +} + +static int qed_sp_vport_stop(struct qed_hwfn *p_hwfn, + u16 opaque_fid, + u8 vport_id) +{ + struct qed_sp_init_request_params sp_params; + struct vport_stop_ramrod_data *p_ramrod; + struct qed_spq_entry *p_ent; + u8 abs_vport_id = 0; + int rc; + + rc = qed_fw_vport(p_hwfn, vport_id, &abs_vport_id); + if (rc != 0) + return rc; + + memset(&sp_params, 0, sizeof(sp_params)); + sp_params.ramrod_data_size = sizeof(*p_ramrod); + sp_params.comp_mode = QED_SPQ_MODE_EBLOCK; + + rc = qed_sp_init_request(p_hwfn, &p_ent, + qed_spq_get_cid(p_hwfn), + opaque_fid, + ETH_RAMROD_VPORT_STOP, + PROTOCOLID_ETH, + &sp_params); + if (rc) + return rc; + + p_ramrod = &p_ent->ramrod.vport_stop; + p_ramrod->vport_id = abs_vport_id; + + return qed_spq_post(p_hwfn, p_ent, NULL); +} + +static int qed_filter_accept_cmd(struct qed_dev *cdev, + u8 vport, + struct qed_filter_accept_flags accept_flags, + enum spq_mode comp_mode, + struct qed_spq_comp_cb *p_comp_data) +{ + struct qed_sp_vport_update_params vport_update_params; + int i, rc; + + /* Prepare and send the vport rx_mode change */ + memset(&vport_update_params, 0, sizeof(vport_update_params)); + vport_update_params.vport_id = vport; + vport_update_params.accept_flags = accept_flags; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + vport_update_params.opaque_fid = p_hwfn->hw_info.opaque_fid; + + rc = qed_sp_vport_update(p_hwfn, &vport_update_params, + comp_mode, p_comp_data); + if (rc != 0) { + DP_ERR(cdev, "Update rx_mode failed %d\n", rc); + return rc; + } + + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "Accept filter configured, flags = [Rx]%x [Tx]%x\n", + accept_flags.rx_accept_filter, + accept_flags.tx_accept_filter); + } + + return 0; +} + +static int qed_sp_release_queue_cid( + struct qed_hwfn *p_hwfn, + struct qed_hw_cid_data *p_cid_data) +{ + if (!p_cid_data->b_cid_allocated) + return 0; + + qed_cxt_release_cid(p_hwfn, p_cid_data->cid); + + p_cid_data->b_cid_allocated = false; + + return 0; +} + +static int +qed_sp_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn, + u16 opaque_fid, + u32 cid, + struct qed_queue_start_common_params *params, + u8 stats_id, + u16 bd_max_bytes, + dma_addr_t bd_chain_phys_addr, + dma_addr_t cqe_pbl_addr, + u16 cqe_pbl_size) +{ + struct rx_queue_start_ramrod_data *p_ramrod = NULL; + struct qed_sp_init_request_params sp_params; + struct qed_spq_entry *p_ent = NULL; + struct qed_hw_cid_data *p_rx_cid; + u16 abs_rx_q_id = 0; + u8 abs_vport_id = 0; + int rc = -EINVAL; + + /* Store information for the stop */ + p_rx_cid = &p_hwfn->p_rx_cids[params->queue_id]; + p_rx_cid->cid = cid; + p_rx_cid->opaque_fid = opaque_fid; + p_rx_cid->vport_id = params->vport_id; + + rc = qed_fw_vport(p_hwfn, params->vport_id, &abs_vport_id); + if (rc != 0) + return rc; + + rc = qed_fw_l2_queue(p_hwfn, params->queue_id, &abs_rx_q_id); + if (rc != 0) + return rc; + + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "opaque_fid=0x%x, cid=0x%x, rx_qid=0x%x, vport_id=0x%x, sb_id=0x%x\n", + opaque_fid, cid, params->queue_id, params->vport_id, + params->sb); + + memset(&sp_params, 0, sizeof(params)); + sp_params.comp_mode = QED_SPQ_MODE_EBLOCK; + sp_params.ramrod_data_size = sizeof(*p_ramrod); + + rc = qed_sp_init_request(p_hwfn, &p_ent, + cid, opaque_fid, + ETH_RAMROD_RX_QUEUE_START, + PROTOCOLID_ETH, + &sp_params); + if (rc) + return rc; + + p_ramrod = &p_ent->ramrod.rx_queue_start; + + p_ramrod->sb_id = cpu_to_le16(params->sb); + p_ramrod->sb_index = params->sb_idx; + p_ramrod->vport_id = abs_vport_id; + p_ramrod->stats_counter_id = stats_id; + p_ramrod->rx_queue_id = cpu_to_le16(abs_rx_q_id); + p_ramrod->complete_cqe_flg = 0; + p_ramrod->complete_event_flg = 1; + + p_ramrod->bd_max_bytes = cpu_to_le16(bd_max_bytes); + p_ramrod->bd_base.hi = DMA_HI_LE(bd_chain_phys_addr); + p_ramrod->bd_base.lo = DMA_LO_LE(bd_chain_phys_addr); + + p_ramrod->num_of_pbl_pages = cpu_to_le16(cqe_pbl_size); + p_ramrod->cqe_pbl_addr.hi = DMA_HI_LE(cqe_pbl_addr); + p_ramrod->cqe_pbl_addr.lo = DMA_LO_LE(cqe_pbl_addr); + + rc = qed_spq_post(p_hwfn, p_ent, NULL); + + return rc; +} + +static int +qed_sp_eth_rx_queue_start(struct qed_hwfn *p_hwfn, + u16 opaque_fid, + struct qed_queue_start_common_params *params, + u16 bd_max_bytes, + dma_addr_t bd_chain_phys_addr, + dma_addr_t cqe_pbl_addr, + u16 cqe_pbl_size, + void __iomem **pp_prod) +{ + struct qed_hw_cid_data *p_rx_cid; + u64 init_prod_val = 0; + u16 abs_l2_queue = 0; + u8 abs_stats_id = 0; + int rc; + + rc = qed_fw_l2_queue(p_hwfn, params->queue_id, &abs_l2_queue); + if (rc != 0) + return rc; + + rc = qed_fw_vport(p_hwfn, params->vport_id, &abs_stats_id); + if (rc != 0) + return rc; + + *pp_prod = (u8 __iomem *)p_hwfn->regview + + GTT_BAR0_MAP_REG_MSDM_RAM + + MSTORM_PRODS_OFFSET(abs_l2_queue); + + /* Init the rcq, rx bd and rx sge (if valid) producers to 0 */ + __internal_ram_wr(p_hwfn, *pp_prod, sizeof(u64), + (u32 *)(&init_prod_val)); + + /* Allocate a CID for the queue */ + p_rx_cid = &p_hwfn->p_rx_cids[params->queue_id]; + rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_ETH, + &p_rx_cid->cid); + if (rc) { + DP_NOTICE(p_hwfn, "Failed to acquire cid\n"); + return rc; + } + p_rx_cid->b_cid_allocated = true; + + rc = qed_sp_eth_rxq_start_ramrod(p_hwfn, + opaque_fid, + p_rx_cid->cid, + params, + abs_stats_id, + bd_max_bytes, + bd_chain_phys_addr, + cqe_pbl_addr, + cqe_pbl_size); + + if (rc != 0) + qed_sp_release_queue_cid(p_hwfn, p_rx_cid); + + return rc; +} + +static int qed_sp_eth_rx_queue_stop(struct qed_hwfn *p_hwfn, + u16 rx_queue_id, + bool eq_completion_only, + bool cqe_completion) +{ + struct qed_hw_cid_data *p_rx_cid = &p_hwfn->p_rx_cids[rx_queue_id]; + struct rx_queue_stop_ramrod_data *p_ramrod = NULL; + struct qed_sp_init_request_params sp_params; + struct qed_spq_entry *p_ent = NULL; + u16 abs_rx_q_id = 0; + int rc = -EINVAL; + + memset(&sp_params, 0, sizeof(sp_params)); + sp_params.ramrod_data_size = sizeof(*p_ramrod); + sp_params.comp_mode = QED_SPQ_MODE_EBLOCK; + + rc = qed_sp_init_request(p_hwfn, &p_ent, + p_rx_cid->cid, + p_rx_cid->opaque_fid, + ETH_RAMROD_RX_QUEUE_STOP, + PROTOCOLID_ETH, + &sp_params); + if (rc) + return rc; + + p_ramrod = &p_ent->ramrod.rx_queue_stop; + + qed_fw_vport(p_hwfn, p_rx_cid->vport_id, &p_ramrod->vport_id); + qed_fw_l2_queue(p_hwfn, rx_queue_id, &abs_rx_q_id); + p_ramrod->rx_queue_id = cpu_to_le16(abs_rx_q_id); + + /* Cleaning the queue requires the completion to arrive there. + * In addition, VFs require the answer to come as eqe to PF. + */ + p_ramrod->complete_cqe_flg = + (!!(p_rx_cid->opaque_fid == p_hwfn->hw_info.opaque_fid) && + !eq_completion_only) || cqe_completion; + p_ramrod->complete_event_flg = + !(p_rx_cid->opaque_fid == p_hwfn->hw_info.opaque_fid) || + eq_completion_only; + + rc = qed_spq_post(p_hwfn, p_ent, NULL); + if (rc) + return rc; + + return qed_sp_release_queue_cid(p_hwfn, p_rx_cid); +} + +static int +qed_sp_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn, + u16 opaque_fid, + u32 cid, + struct qed_queue_start_common_params *p_params, + u8 stats_id, + dma_addr_t pbl_addr, + u16 pbl_size, + union qed_qm_pq_params *p_pq_params) +{ + struct tx_queue_start_ramrod_data *p_ramrod = NULL; + struct qed_sp_init_request_params sp_params; + struct qed_spq_entry *p_ent = NULL; + struct qed_hw_cid_data *p_tx_cid; + u8 abs_vport_id; + int rc = -EINVAL; + u16 pq_id; + + /* Store information for the stop */ + p_tx_cid = &p_hwfn->p_tx_cids[p_params->queue_id]; + p_tx_cid->cid = cid; + p_tx_cid->opaque_fid = opaque_fid; + + rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id); + if (rc) + return rc; + + memset(&sp_params, 0, sizeof(sp_params)); + sp_params.ramrod_data_size = sizeof(*p_ramrod); + sp_params.comp_mode = QED_SPQ_MODE_EBLOCK; + + rc = qed_sp_init_request(p_hwfn, &p_ent, cid, + opaque_fid, + ETH_RAMROD_TX_QUEUE_START, + PROTOCOLID_ETH, + &sp_params); + if (rc) + return rc; + + p_ramrod = &p_ent->ramrod.tx_queue_start; + p_ramrod->vport_id = abs_vport_id; + + p_ramrod->sb_id = cpu_to_le16(p_params->sb); + p_ramrod->sb_index = p_params->sb_idx; + p_ramrod->stats_counter_id = stats_id; + p_ramrod->tc = p_pq_params->eth.tc; + + p_ramrod->pbl_size = cpu_to_le16(pbl_size); + p_ramrod->pbl_base_addr.hi = DMA_HI_LE(pbl_addr); + p_ramrod->pbl_base_addr.lo = DMA_LO_LE(pbl_addr); + + pq_id = qed_get_qm_pq(p_hwfn, + PROTOCOLID_ETH, + p_pq_params); + p_ramrod->qm_pq_id = cpu_to_le16(pq_id); + + return qed_spq_post(p_hwfn, p_ent, NULL); +} + +static int +qed_sp_eth_tx_queue_start(struct qed_hwfn *p_hwfn, + u16 opaque_fid, + struct qed_queue_start_common_params *p_params, + dma_addr_t pbl_addr, + u16 pbl_size, + void __iomem **pp_doorbell) +{ + struct qed_hw_cid_data *p_tx_cid; + union qed_qm_pq_params pq_params; + u8 abs_stats_id = 0; + int rc; + + rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_stats_id); + if (rc) + return rc; + + p_tx_cid = &p_hwfn->p_tx_cids[p_params->queue_id]; + memset(p_tx_cid, 0, sizeof(*p_tx_cid)); + memset(&pq_params, 0, sizeof(pq_params)); + + /* Allocate a CID for the queue */ + rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_ETH, + &p_tx_cid->cid); + if (rc) { + DP_NOTICE(p_hwfn, "Failed to acquire cid\n"); + return rc; + } + p_tx_cid->b_cid_allocated = true; + + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "opaque_fid=0x%x, cid=0x%x, tx_qid=0x%x, vport_id=0x%x, sb_id=0x%x\n", + opaque_fid, p_tx_cid->cid, + p_params->queue_id, p_params->vport_id, p_params->sb); + + rc = qed_sp_eth_txq_start_ramrod(p_hwfn, + opaque_fid, + p_tx_cid->cid, + p_params, + abs_stats_id, + pbl_addr, + pbl_size, + &pq_params); + + *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells + + qed_db_addr(p_tx_cid->cid, DQ_DEMS_LEGACY); + + if (rc) + qed_sp_release_queue_cid(p_hwfn, p_tx_cid); + + return rc; +} + +static int qed_sp_eth_tx_queue_stop(struct qed_hwfn *p_hwfn, + u16 tx_queue_id) +{ + struct qed_hw_cid_data *p_tx_cid = &p_hwfn->p_tx_cids[tx_queue_id]; + struct qed_sp_init_request_params sp_params; + struct qed_spq_entry *p_ent = NULL; + int rc = -EINVAL; + + memset(&sp_params, 0, sizeof(sp_params)); + sp_params.ramrod_data_size = sizeof(struct tx_queue_stop_ramrod_data); + sp_params.comp_mode = QED_SPQ_MODE_EBLOCK; + + rc = qed_sp_init_request(p_hwfn, &p_ent, + p_tx_cid->cid, + p_tx_cid->opaque_fid, + ETH_RAMROD_TX_QUEUE_STOP, + PROTOCOLID_ETH, + &sp_params); + if (rc) + return rc; + + rc = qed_spq_post(p_hwfn, p_ent, NULL); + if (rc) + return rc; + + return qed_sp_release_queue_cid(p_hwfn, p_tx_cid); +} + +static enum eth_filter_action +qed_filter_action(enum qed_filter_opcode opcode) +{ + enum eth_filter_action action = MAX_ETH_FILTER_ACTION; + + switch (opcode) { + case QED_FILTER_ADD: + action = ETH_FILTER_ACTION_ADD; + break; + case QED_FILTER_REMOVE: + action = ETH_FILTER_ACTION_REMOVE; + break; + case QED_FILTER_REPLACE: + case QED_FILTER_FLUSH: + action = ETH_FILTER_ACTION_REPLACE; + break; + default: + action = MAX_ETH_FILTER_ACTION; + } + + return action; +} + +static void qed_set_fw_mac_addr(__le16 *fw_msb, + __le16 *fw_mid, + __le16 *fw_lsb, + u8 *mac) +{ + ((u8 *)fw_msb)[0] = mac[1]; + ((u8 *)fw_msb)[1] = mac[0]; + ((u8 *)fw_mid)[0] = mac[3]; + ((u8 *)fw_mid)[1] = mac[2]; + ((u8 *)fw_lsb)[0] = mac[5]; + ((u8 *)fw_lsb)[1] = mac[4]; +} + +static int +qed_filter_ucast_common(struct qed_hwfn *p_hwfn, + u16 opaque_fid, + struct qed_filter_ucast *p_filter_cmd, + struct vport_filter_update_ramrod_data **pp_ramrod, + struct qed_spq_entry **pp_ent, + enum spq_mode comp_mode, + struct qed_spq_comp_cb *p_comp_data) +{ + u8 vport_to_add_to = 0, vport_to_remove_from = 0; + struct vport_filter_update_ramrod_data *p_ramrod; + struct qed_sp_init_request_params sp_params; + struct eth_filter_cmd *p_first_filter; + struct eth_filter_cmd *p_second_filter; + enum eth_filter_action action; + int rc; + + rc = qed_fw_vport(p_hwfn, p_filter_cmd->vport_to_remove_from, + &vport_to_remove_from); + if (rc) + return rc; + + rc = qed_fw_vport(p_hwfn, p_filter_cmd->vport_to_add_to, + &vport_to_add_to); + if (rc) + return rc; + + memset(&sp_params, 0, sizeof(sp_params)); + sp_params.ramrod_data_size = sizeof(**pp_ramrod); + sp_params.comp_mode = comp_mode; + sp_params.p_comp_data = p_comp_data; + + rc = qed_sp_init_request(p_hwfn, pp_ent, + qed_spq_get_cid(p_hwfn), + opaque_fid, + ETH_RAMROD_FILTERS_UPDATE, + PROTOCOLID_ETH, + &sp_params); + if (rc) + return rc; + + *pp_ramrod = &(*pp_ent)->ramrod.vport_filter_update; + p_ramrod = *pp_ramrod; + p_ramrod->filter_cmd_hdr.rx = p_filter_cmd->is_rx_filter ? 1 : 0; + p_ramrod->filter_cmd_hdr.tx = p_filter_cmd->is_tx_filter ? 1 : 0; + + switch (p_filter_cmd->opcode) { + case QED_FILTER_FLUSH: + p_ramrod->filter_cmd_hdr.cmd_cnt = 0; break; + case QED_FILTER_MOVE: + p_ramrod->filter_cmd_hdr.cmd_cnt = 2; break; + default: + p_ramrod->filter_cmd_hdr.cmd_cnt = 1; break; + } + + p_first_filter = &p_ramrod->filter_cmds[0]; + p_second_filter = &p_ramrod->filter_cmds[1]; + + switch (p_filter_cmd->type) { + case QED_FILTER_MAC: + p_first_filter->type = ETH_FILTER_TYPE_MAC; break; + case QED_FILTER_VLAN: + p_first_filter->type = ETH_FILTER_TYPE_VLAN; break; + case QED_FILTER_MAC_VLAN: + p_first_filter->type = ETH_FILTER_TYPE_PAIR; break; + case QED_FILTER_INNER_MAC: + p_first_filter->type = ETH_FILTER_TYPE_INNER_MAC; break; + case QED_FILTER_INNER_VLAN: + p_first_filter->type = ETH_FILTER_TYPE_INNER_VLAN; break; + case QED_FILTER_INNER_PAIR: + p_first_filter->type = ETH_FILTER_TYPE_INNER_PAIR; break; + case QED_FILTER_INNER_MAC_VNI_PAIR: + p_first_filter->type = ETH_FILTER_TYPE_INNER_MAC_VNI_PAIR; + break; + case QED_FILTER_MAC_VNI_PAIR: + p_first_filter->type = ETH_FILTER_TYPE_MAC_VNI_PAIR; break; + case QED_FILTER_VNI: + p_first_filter->type = ETH_FILTER_TYPE_VNI; break; + } + + if ((p_first_filter->type == ETH_FILTER_TYPE_MAC) || + (p_first_filter->type == ETH_FILTER_TYPE_PAIR) || + (p_first_filter->type == ETH_FILTER_TYPE_INNER_MAC) || + (p_first_filter->type == ETH_FILTER_TYPE_INNER_PAIR) || + (p_first_filter->type == ETH_FILTER_TYPE_INNER_MAC_VNI_PAIR) || + (p_first_filter->type == ETH_FILTER_TYPE_MAC_VNI_PAIR)) { + qed_set_fw_mac_addr(&p_first_filter->mac_msb, + &p_first_filter->mac_mid, + &p_first_filter->mac_lsb, + (u8 *)p_filter_cmd->mac); + } + + if ((p_first_filter->type == ETH_FILTER_TYPE_VLAN) || + (p_first_filter->type == ETH_FILTER_TYPE_PAIR) || + (p_first_filter->type == ETH_FILTER_TYPE_INNER_VLAN) || + (p_first_filter->type == ETH_FILTER_TYPE_INNER_PAIR)) + p_first_filter->vlan_id = cpu_to_le16(p_filter_cmd->vlan); + + if ((p_first_filter->type == ETH_FILTER_TYPE_INNER_MAC_VNI_PAIR) || + (p_first_filter->type == ETH_FILTER_TYPE_MAC_VNI_PAIR) || + (p_first_filter->type == ETH_FILTER_TYPE_VNI)) + p_first_filter->vni = cpu_to_le32(p_filter_cmd->vni); + + if (p_filter_cmd->opcode == QED_FILTER_MOVE) { + p_second_filter->type = p_first_filter->type; + p_second_filter->mac_msb = p_first_filter->mac_msb; + p_second_filter->mac_mid = p_first_filter->mac_mid; + p_second_filter->mac_lsb = p_first_filter->mac_lsb; + p_second_filter->vlan_id = p_first_filter->vlan_id; + p_second_filter->vni = p_first_filter->vni; + + p_first_filter->action = ETH_FILTER_ACTION_REMOVE; + + p_first_filter->vport_id = vport_to_remove_from; + + p_second_filter->action = ETH_FILTER_ACTION_ADD; + p_second_filter->vport_id = vport_to_add_to; + } else { + action = qed_filter_action(p_filter_cmd->opcode); + + if (action == MAX_ETH_FILTER_ACTION) { + DP_NOTICE(p_hwfn, + "%d is not supported yet\n", + p_filter_cmd->opcode); + return -EINVAL; + } + + p_first_filter->action = action; + p_first_filter->vport_id = (p_filter_cmd->opcode == + QED_FILTER_REMOVE) ? + vport_to_remove_from : + vport_to_add_to; + } + + return 0; +} + +static int qed_sp_eth_filter_ucast(struct qed_hwfn *p_hwfn, + u16 opaque_fid, + struct qed_filter_ucast *p_filter_cmd, + enum spq_mode comp_mode, + struct qed_spq_comp_cb *p_comp_data) +{ + struct vport_filter_update_ramrod_data *p_ramrod = NULL; + struct qed_spq_entry *p_ent = NULL; + struct eth_filter_cmd_header *p_header; + int rc; + + rc = qed_filter_ucast_common(p_hwfn, opaque_fid, p_filter_cmd, + &p_ramrod, &p_ent, + comp_mode, p_comp_data); + if (rc != 0) { + DP_ERR(p_hwfn, "Uni. filter command failed %d\n", rc); + return rc; + } + p_header = &p_ramrod->filter_cmd_hdr; + p_header->assert_on_error = p_filter_cmd->assert_on_error; + + rc = qed_spq_post(p_hwfn, p_ent, NULL); + if (rc != 0) { + DP_ERR(p_hwfn, + "Unicast filter ADD command failed %d\n", + rc); + return rc; + } + + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "Unicast filter configured, opcode = %s, type = %s, cmd_cnt = %d, is_rx_filter = %d, is_tx_filter = %d\n", + (p_filter_cmd->opcode == QED_FILTER_ADD) ? "ADD" : + ((p_filter_cmd->opcode == QED_FILTER_REMOVE) ? + "REMOVE" : + ((p_filter_cmd->opcode == QED_FILTER_MOVE) ? + "MOVE" : "REPLACE")), + (p_filter_cmd->type == QED_FILTER_MAC) ? "MAC" : + ((p_filter_cmd->type == QED_FILTER_VLAN) ? + "VLAN" : "MAC & VLAN"), + p_ramrod->filter_cmd_hdr.cmd_cnt, + p_filter_cmd->is_rx_filter, + p_filter_cmd->is_tx_filter); + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "vport_to_add_to = %d, vport_to_remove_from = %d, mac = %2x:%2x:%2x:%2x:%2x:%2x, vlan = %d\n", + p_filter_cmd->vport_to_add_to, + p_filter_cmd->vport_to_remove_from, + p_filter_cmd->mac[0], + p_filter_cmd->mac[1], + p_filter_cmd->mac[2], + p_filter_cmd->mac[3], + p_filter_cmd->mac[4], + p_filter_cmd->mac[5], + p_filter_cmd->vlan); + + return 0; +} + +/******************************************************************************* + * Description: + * Calculates crc 32 on a buffer + * Note: crc32_length MUST be aligned to 8 + * Return: + ******************************************************************************/ +static u32 qed_calc_crc32c(u8 *crc32_packet, + u32 crc32_length, + u32 crc32_seed, + u8 complement) +{ + u32 byte = 0; + u32 bit = 0; + u8 msb = 0; + u8 current_byte = 0; + u32 crc32_result = crc32_seed; + + if ((!crc32_packet) || + (crc32_length == 0) || + ((crc32_length % 8) != 0)) + return crc32_result; + for (byte = 0; byte < crc32_length; byte++) { + current_byte = crc32_packet[byte]; + for (bit = 0; bit < 8; bit++) { + msb = (u8)(crc32_result >> 31); + crc32_result = crc32_result << 1; + if (msb != (0x1 & (current_byte >> bit))) { + crc32_result = crc32_result ^ CRC32_POLY; + crc32_result |= 1; /*crc32_result[0] = 1;*/ + } + } + } + return crc32_result; +} + +static inline u32 qed_crc32c_le(u32 seed, + u8 *mac, + u32 len) +{ + u32 packet_buf[2] = { 0 }; + + memcpy((u8 *)(&packet_buf[0]), &mac[0], 6); + return qed_calc_crc32c((u8 *)packet_buf, 8, seed, 0); +} + +static u8 qed_mcast_bin_from_mac(u8 *mac) +{ + u32 crc = qed_crc32c_le(ETH_MULTICAST_BIN_FROM_MAC_SEED, + mac, ETH_ALEN); + + return crc & 0xff; +} + +static int +qed_sp_eth_filter_mcast(struct qed_hwfn *p_hwfn, + u16 opaque_fid, + struct qed_filter_mcast *p_filter_cmd, + enum spq_mode comp_mode, + struct qed_spq_comp_cb *p_comp_data) +{ + unsigned long bins[ETH_MULTICAST_MAC_BINS_IN_REGS]; + struct vport_update_ramrod_data *p_ramrod = NULL; + struct qed_sp_init_request_params sp_params; + struct qed_spq_entry *p_ent = NULL; + u8 abs_vport_id = 0; + int rc, i; + + if (p_filter_cmd->opcode == QED_FILTER_ADD) { + rc = qed_fw_vport(p_hwfn, p_filter_cmd->vport_to_add_to, + &abs_vport_id); + if (rc) + return rc; + } else { + rc = qed_fw_vport(p_hwfn, p_filter_cmd->vport_to_remove_from, + &abs_vport_id); + if (rc) + return rc; + } + + memset(&sp_params, 0, sizeof(sp_params)); + sp_params.ramrod_data_size = sizeof(*p_ramrod); + sp_params.comp_mode = comp_mode; + sp_params.p_comp_data = p_comp_data; + + rc = qed_sp_init_request(p_hwfn, &p_ent, + qed_spq_get_cid(p_hwfn), + p_hwfn->hw_info.opaque_fid, + ETH_RAMROD_VPORT_UPDATE, + PROTOCOLID_ETH, + &sp_params); + + if (rc) { + DP_ERR(p_hwfn, "Multi-cast command failed %d\n", rc); + return rc; + } + + p_ramrod = &p_ent->ramrod.vport_update; + p_ramrod->common.update_approx_mcast_flg = 1; + + /* explicitly clear out the entire vector */ + memset(&p_ramrod->approx_mcast.bins, 0, + sizeof(p_ramrod->approx_mcast.bins)); + memset(bins, 0, sizeof(unsigned long) * + ETH_MULTICAST_MAC_BINS_IN_REGS); + /* filter ADD op is explicit set op and it removes + * any existing filters for the vport + */ + if (p_filter_cmd->opcode == QED_FILTER_ADD) { + for (i = 0; i < p_filter_cmd->num_mc_addrs; i++) { + u32 bit; + + bit = qed_mcast_bin_from_mac(p_filter_cmd->mac[i]); + __set_bit(bit, bins); + } + + /* Convert to correct endianity */ + for (i = 0; i < ETH_MULTICAST_MAC_BINS_IN_REGS; i++) { + u32 *p_bins = (u32 *)bins; + struct vport_update_ramrod_mcast *approx_mcast; + + approx_mcast = &p_ramrod->approx_mcast; + approx_mcast->bins[i] = cpu_to_le32(p_bins[i]); + } + } + + p_ramrod->common.vport_id = abs_vport_id; + + return qed_spq_post(p_hwfn, p_ent, NULL); +} + +static int +qed_filter_mcast_cmd(struct qed_dev *cdev, + struct qed_filter_mcast *p_filter_cmd, + enum spq_mode comp_mode, + struct qed_spq_comp_cb *p_comp_data) +{ + int rc = 0; + int i; + + /* only ADD and REMOVE operations are supported for multi-cast */ + if ((p_filter_cmd->opcode != QED_FILTER_ADD && + (p_filter_cmd->opcode != QED_FILTER_REMOVE)) || + (p_filter_cmd->num_mc_addrs > QED_MAX_MC_ADDRS)) + return -EINVAL; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + u16 opaque_fid; + + if (rc != 0) + break; + + opaque_fid = p_hwfn->hw_info.opaque_fid; + + rc = qed_sp_eth_filter_mcast(p_hwfn, + opaque_fid, + p_filter_cmd, + comp_mode, + p_comp_data); + } + return rc; +} + +static int qed_filter_ucast_cmd(struct qed_dev *cdev, + struct qed_filter_ucast *p_filter_cmd, + enum spq_mode comp_mode, + struct qed_spq_comp_cb *p_comp_data) +{ + int rc = 0; + int i; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + u16 opaque_fid; + + if (rc != 0) + break; + + opaque_fid = p_hwfn->hw_info.opaque_fid; + + rc = qed_sp_eth_filter_ucast(p_hwfn, + opaque_fid, + p_filter_cmd, + comp_mode, + p_comp_data); + } + + return rc; +} + static int qed_fill_eth_dev_info(struct qed_dev *cdev, struct qed_dev_eth_info *info) { @@ -63,9 +1259,418 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev, return 0; } +static int qed_start_vport(struct qed_dev *cdev, + u8 vport_id, + u16 mtu, + u8 drop_ttl0_flg, + u8 inner_vlan_removal_en_flg) +{ + int rc, i; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + rc = qed_sp_vport_start(p_hwfn, + p_hwfn->hw_info.concrete_fid, + p_hwfn->hw_info.opaque_fid, + vport_id, + mtu, + drop_ttl0_flg, + inner_vlan_removal_en_flg); + + if (rc) { + DP_ERR(cdev, "Failed to start VPORT\n"); + return rc; + } + + qed_hw_start_fastpath(p_hwfn); + + DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP), + "Started V-PORT %d with MTU %d\n", + vport_id, mtu); + } + + return 0; +} + +static int qed_stop_vport(struct qed_dev *cdev, + u8 vport_id) +{ + int rc, i; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + rc = qed_sp_vport_stop(p_hwfn, + p_hwfn->hw_info.opaque_fid, + vport_id); + + if (rc) { + DP_ERR(cdev, "Failed to stop VPORT\n"); + return rc; + } + } + return 0; +} + +static int qed_update_vport(struct qed_dev *cdev, + struct qed_update_vport_params *params) +{ + struct qed_sp_vport_update_params sp_params; + struct qed_rss_params sp_rss_params; + int rc, i; + + if (!cdev) + return -ENODEV; + + memset(&sp_params, 0, sizeof(sp_params)); + memset(&sp_rss_params, 0, sizeof(sp_rss_params)); + + /* Translate protocol params into sp params */ + sp_params.vport_id = params->vport_id; + sp_params.update_vport_active_rx_flg = + params->update_vport_active_flg; + sp_params.update_vport_active_tx_flg = + params->update_vport_active_flg; + sp_params.vport_active_rx_flg = params->vport_active_flg; + sp_params.vport_active_tx_flg = params->vport_active_flg; + + /* RSS - is a bit tricky, since upper-layer isn't familiar with hwfns. + * We need to re-fix the rss values per engine for CMT. + */ + if (cdev->num_hwfns > 1 && params->update_rss_flg) { + struct qed_update_vport_rss_params *rss = + ¶ms->rss_params; + int k, max = 0; + + /* Find largest entry, since it's possible RSS needs to + * be disabled [in case only 1 queue per-hwfn] + */ + for (k = 0; k < QED_RSS_IND_TABLE_SIZE; k++) + max = (max > rss->rss_ind_table[k]) ? + max : rss->rss_ind_table[k]; + + /* Either fix RSS values or disable RSS */ + if (cdev->num_hwfns < max + 1) { + int divisor = (max + cdev->num_hwfns - 1) / + cdev->num_hwfns; + + DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP), + "CMT - fixing RSS values (modulo %02x)\n", + divisor); + + for (k = 0; k < QED_RSS_IND_TABLE_SIZE; k++) + rss->rss_ind_table[k] = + rss->rss_ind_table[k] % divisor; + } else { + DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP), + "CMT - 1 queue per-hwfn; Disabling RSS\n"); + params->update_rss_flg = 0; + } + } + + /* Now, update the RSS configuration for actual configuration */ + if (params->update_rss_flg) { + sp_rss_params.update_rss_config = 1; + sp_rss_params.rss_enable = 1; + sp_rss_params.update_rss_capabilities = 1; + sp_rss_params.update_rss_ind_table = 1; + sp_rss_params.update_rss_key = 1; + sp_rss_params.rss_caps = QED_RSS_IPV4 | + QED_RSS_IPV6 | + QED_RSS_IPV4_TCP | QED_RSS_IPV6_TCP; + sp_rss_params.rss_table_size_log = 7; /* 2^7 = 128 */ + memcpy(sp_rss_params.rss_ind_table, + params->rss_params.rss_ind_table, + QED_RSS_IND_TABLE_SIZE * sizeof(u16)); + memcpy(sp_rss_params.rss_key, params->rss_params.rss_key, + QED_RSS_KEY_SIZE * sizeof(u32)); + } + sp_params.rss_params = &sp_rss_params; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + + sp_params.opaque_fid = p_hwfn->hw_info.opaque_fid; + rc = qed_sp_vport_update(p_hwfn, &sp_params, + QED_SPQ_MODE_EBLOCK, + NULL); + if (rc) { + DP_ERR(cdev, "Failed to update VPORT\n"); + return rc; + } + + DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP), + "Updated V-PORT %d: active_flag %d [update %d]\n", + params->vport_id, params->vport_active_flg, + params->update_vport_active_flg); + } + + return 0; +} + +static int qed_start_rxq(struct qed_dev *cdev, + struct qed_queue_start_common_params *params, + u16 bd_max_bytes, + dma_addr_t bd_chain_phys_addr, + dma_addr_t cqe_pbl_addr, + u16 cqe_pbl_size, + void __iomem **pp_prod) +{ + int rc, hwfn_index; + struct qed_hwfn *p_hwfn; + + hwfn_index = params->rss_id % cdev->num_hwfns; + p_hwfn = &cdev->hwfns[hwfn_index]; + + /* Fix queue ID in 100g mode */ + params->queue_id /= cdev->num_hwfns; + + rc = qed_sp_eth_rx_queue_start(p_hwfn, + p_hwfn->hw_info.opaque_fid, + params, + bd_max_bytes, + bd_chain_phys_addr, + cqe_pbl_addr, + cqe_pbl_size, + pp_prod); + + if (rc) { + DP_ERR(cdev, "Failed to start RXQ#%d\n", params->queue_id); + return rc; + } + + DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP), + "Started RX-Q %d [rss %d] on V-PORT %d and SB %d\n", + params->queue_id, params->rss_id, params->vport_id, + params->sb); + + return 0; +} + +static int qed_stop_rxq(struct qed_dev *cdev, + struct qed_stop_rxq_params *params) +{ + int rc, hwfn_index; + struct qed_hwfn *p_hwfn; + + hwfn_index = params->rss_id % cdev->num_hwfns; + p_hwfn = &cdev->hwfns[hwfn_index]; + + rc = qed_sp_eth_rx_queue_stop(p_hwfn, + params->rx_queue_id / cdev->num_hwfns, + params->eq_completion_only, + false); + if (rc) { + DP_ERR(cdev, "Failed to stop RXQ#%d\n", params->rx_queue_id); + return rc; + } + + return 0; +} + +static int qed_start_txq(struct qed_dev *cdev, + struct qed_queue_start_common_params *p_params, + dma_addr_t pbl_addr, + u16 pbl_size, + void __iomem **pp_doorbell) +{ + struct qed_hwfn *p_hwfn; + int rc, hwfn_index; + + hwfn_index = p_params->rss_id % cdev->num_hwfns; + p_hwfn = &cdev->hwfns[hwfn_index]; + + /* Fix queue ID in 100g mode */ + p_params->queue_id /= cdev->num_hwfns; + + rc = qed_sp_eth_tx_queue_start(p_hwfn, + p_hwfn->hw_info.opaque_fid, + p_params, + pbl_addr, + pbl_size, + pp_doorbell); + + if (rc) { + DP_ERR(cdev, "Failed to start TXQ#%d\n", p_params->queue_id); + return rc; + } + + DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP), + "Started TX-Q %d [rss %d] on V-PORT %d and SB %d\n", + p_params->queue_id, p_params->rss_id, p_params->vport_id, + p_params->sb); + + return 0; +} + +#define QED_HW_STOP_RETRY_LIMIT (10) +static int qed_fastpath_stop(struct qed_dev *cdev) +{ + qed_hw_stop_fastpath(cdev); + + return 0; +} + +static int qed_stop_txq(struct qed_dev *cdev, + struct qed_stop_txq_params *params) +{ + struct qed_hwfn *p_hwfn; + int rc, hwfn_index; + + hwfn_index = params->rss_id % cdev->num_hwfns; + p_hwfn = &cdev->hwfns[hwfn_index]; + + rc = qed_sp_eth_tx_queue_stop(p_hwfn, + params->tx_queue_id / cdev->num_hwfns); + if (rc) { + DP_ERR(cdev, "Failed to stop TXQ#%d\n", params->tx_queue_id); + return rc; + } + + return 0; +} + +static int qed_configure_filter_rx_mode(struct qed_dev *cdev, + enum qed_filter_rx_mode_type type) +{ + struct qed_filter_accept_flags accept_flags; + + memset(&accept_flags, 0, sizeof(accept_flags)); + + accept_flags.update_rx_mode_config = 1; + accept_flags.update_tx_mode_config = 1; + accept_flags.rx_accept_filter = QED_ACCEPT_UCAST_MATCHED | + QED_ACCEPT_MCAST_MATCHED | + QED_ACCEPT_BCAST; + accept_flags.tx_accept_filter = QED_ACCEPT_UCAST_MATCHED | + QED_ACCEPT_MCAST_MATCHED | + QED_ACCEPT_BCAST; + + if (type == QED_FILTER_RX_MODE_TYPE_PROMISC) + accept_flags.rx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED | + QED_ACCEPT_MCAST_UNMATCHED; + else if (type == QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC) + accept_flags.rx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED; + + return qed_filter_accept_cmd(cdev, 0, accept_flags, + QED_SPQ_MODE_CB, NULL); +} + +static int qed_configure_filter_ucast(struct qed_dev *cdev, + struct qed_filter_ucast_params *params) +{ + struct qed_filter_ucast ucast; + + if (!params->vlan_valid && !params->mac_valid) { + DP_NOTICE( + cdev, + "Tried configuring a unicast filter, but both MAC and VLAN are not set\n"); + return -EINVAL; + } + + memset(&ucast, 0, sizeof(ucast)); + switch (params->type) { + case QED_FILTER_XCAST_TYPE_ADD: + ucast.opcode = QED_FILTER_ADD; + break; + case QED_FILTER_XCAST_TYPE_DEL: + ucast.opcode = QED_FILTER_REMOVE; + break; + case QED_FILTER_XCAST_TYPE_REPLACE: + ucast.opcode = QED_FILTER_REPLACE; + break; + default: + DP_NOTICE(cdev, "Unknown unicast filter type %d\n", + params->type); + } + + if (params->vlan_valid && params->mac_valid) { + ucast.type = QED_FILTER_MAC_VLAN; + ether_addr_copy(ucast.mac, params->mac); + ucast.vlan = params->vlan; + } else if (params->mac_valid) { + ucast.type = QED_FILTER_MAC; + ether_addr_copy(ucast.mac, params->mac); + } else { + ucast.type = QED_FILTER_VLAN; + ucast.vlan = params->vlan; + } + + ucast.is_rx_filter = true; + ucast.is_tx_filter = true; + + return qed_filter_ucast_cmd(cdev, &ucast, QED_SPQ_MODE_CB, NULL); +} + +static int qed_configure_filter_mcast(struct qed_dev *cdev, + struct qed_filter_mcast_params *params) +{ + struct qed_filter_mcast mcast; + int i; + + memset(&mcast, 0, sizeof(mcast)); + switch (params->type) { + case QED_FILTER_XCAST_TYPE_ADD: + mcast.opcode = QED_FILTER_ADD; + break; + case QED_FILTER_XCAST_TYPE_DEL: + mcast.opcode = QED_FILTER_REMOVE; + break; + default: + DP_NOTICE(cdev, "Unknown multicast filter type %d\n", + params->type); + } + + mcast.num_mc_addrs = params->num; + for (i = 0; i < mcast.num_mc_addrs; i++) + ether_addr_copy(mcast.mac[i], params->mac[i]); + + return qed_filter_mcast_cmd(cdev, &mcast, + QED_SPQ_MODE_CB, NULL); +} + +static int qed_configure_filter(struct qed_dev *cdev, + struct qed_filter_params *params) +{ + enum qed_filter_rx_mode_type accept_flags; + + switch (params->type) { + case QED_FILTER_TYPE_UCAST: + return qed_configure_filter_ucast(cdev, ¶ms->filter.ucast); + case QED_FILTER_TYPE_MCAST: + return qed_configure_filter_mcast(cdev, ¶ms->filter.mcast); + case QED_FILTER_TYPE_RX_MODE: + accept_flags = params->filter.accept_flags; + return qed_configure_filter_rx_mode(cdev, accept_flags); + default: + DP_NOTICE(cdev, "Unknown filter type %d\n", + (int)params->type); + return -EINVAL; + } +} + +static int qed_fp_cqe_completion(struct qed_dev *dev, + u8 rss_id, + struct eth_slow_path_rx_cqe *cqe) +{ + return qed_eth_cqe_completion(&dev->hwfns[rss_id % dev->num_hwfns], + cqe); +} + static const struct qed_eth_ops qed_eth_ops_pass = { .common = &qed_common_ops_pass, .fill_dev_info = &qed_fill_eth_dev_info, + .vport_start = &qed_start_vport, + .vport_stop = &qed_stop_vport, + .vport_update = &qed_update_vport, + .q_rx_start = &qed_start_rxq, + .q_rx_stop = &qed_stop_rxq, + .q_tx_start = &qed_start_txq, + .q_tx_stop = &qed_stop_txq, + .filter_config = &qed_configure_filter, + .fastpath_stop = &qed_fastpath_stop, + .eth_cqe_completion = &qed_fp_cqe_completion, }; const struct qed_eth_ops *qed_get_eth_ops(u32 version) diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index d0b1ff0ca3c8..1659418eec88 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -182,6 +182,8 @@ err0: int qed_fill_dev_info(struct qed_dev *cdev, struct qed_dev_info *dev_info) { + struct qed_ptt *ptt; + memset(dev_info, 0, sizeof(struct qed_dev_info)); dev_info->num_hwfns = cdev->num_hwfns; @@ -199,6 +201,14 @@ int qed_fill_dev_info(struct qed_dev *cdev, qed_mcp_get_mfw_ver(cdev, &dev_info->mfw_rev); + ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); + if (ptt) { + qed_mcp_get_flash_size(QED_LEADING_HWFN(cdev), ptt, + &dev_info->flash_size); + + qed_ptt_release(QED_LEADING_HWFN(cdev), ptt); + } + return 0; } diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 601d3f5daf13..8a5c3849bfe0 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -516,6 +516,22 @@ int qed_mcp_drain(struct qed_hwfn *p_hwfn, return rc; } +int qed_mcp_get_flash_size(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 *p_flash_size) +{ + u32 flash_size; + + flash_size = qed_rd(p_hwfn, p_ptt, MCP_REG_NVM_CFG4); + flash_size = (flash_size & MCP_REG_NVM_CFG4_FLASH_SIZE) >> + MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT; + flash_size = (1 << (flash_size + MCP_BYTES_PER_MBIT_SHIFT)); + + *p_flash_size = flash_size; + + return 0; +} + int qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index 230c2550dc89..106d78a19937 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -89,6 +89,19 @@ int qed_mcp_cmd(struct qed_hwfn *p_hwfn, int qed_mcp_drain(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); +/** + * @brief Get the flash size value + * + * @param p_hwfn + * @param p_ptt + * @param p_flash_size - flash size in bytes to be filled. + * + * @return int - 0 - operation was successul. + */ +int qed_mcp_get_flash_size(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 *p_flash_size); + /** * @brief Send driver version to MFW * diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h index 74657d227583..31a1f1eb4f56 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h @@ -32,8 +32,35 @@ struct qed_spq_comp_cb { void *cookie; }; +/** + * @brief qed_eth_cqe_completion - handles the completion of a + * ramrod on the cqe ring + * + * @param p_hwfn + * @param cqe + * + * @return int + */ +int qed_eth_cqe_completion(struct qed_hwfn *p_hwfn, + struct eth_slow_path_rx_cqe *cqe); + +/** + * @file + * + * QED Slow-hwfn queue interface + */ + union ramrod_data { struct pf_start_ramrod_data pf_start; + struct rx_queue_start_ramrod_data rx_queue_start; + struct rx_queue_update_ramrod_data rx_queue_update; + struct rx_queue_stop_ramrod_data rx_queue_stop; + struct tx_queue_start_ramrod_data tx_queue_start; + struct tx_queue_stop_ramrod_data tx_queue_stop; + struct vport_start_ramrod_data vport_start; + struct vport_stop_ramrod_data vport_stop; + struct vport_update_ramrod_data vport_update; + struct vport_filter_update_ramrod_data vport_filter_update; }; #define EQ_MAX_CREDIT 0xffffffff diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c index f28ecb197309..7c0b8459666e 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_spq.c +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c @@ -373,6 +373,35 @@ void qed_eq_free(struct qed_hwfn *p_hwfn, kfree(p_eq); } +/*************************************************************************** +* CQE API - manipulate EQ functionality +***************************************************************************/ +static int qed_cqe_completion( + struct qed_hwfn *p_hwfn, + struct eth_slow_path_rx_cqe *cqe, + enum protocol_type protocol) +{ + /* @@@tmp - it's possible we'll eventually want to handle some + * actual commands that can arrive here, but for now this is only + * used to complete the ramrod using the echo value on the cqe + */ + return qed_spq_completion(p_hwfn, cqe->echo, 0, NULL); +} + +int qed_eth_cqe_completion(struct qed_hwfn *p_hwfn, + struct eth_slow_path_rx_cqe *cqe) +{ + int rc; + + rc = qed_cqe_completion(p_hwfn, cqe, PROTOCOLID_ETH); + if (rc) + DP_NOTICE(p_hwfn, + "Failed to handle RXQ CQE [cmd 0x%02x]\n", + cqe->ramrod_cmd_id); + + return rc; +} + /*************************************************************************** * Slow hwfn Queue (spq) ***************************************************************************/ -- cgit v1.2.3 From 2950219d87b040959f23484dd4ff5856bf1bc172 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Mon, 26 Oct 2015 11:02:29 +0200 Subject: qede: Add basic network device support This patch includes the basic Rx/Tx support for the driver [although carrier will still never be turned on]. Following this patch the driver registers a network device, initializes it and prepares it for traffic. Signed-off-by: Sudarsana Kalluru Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede.h | 128 ++ drivers/net/ethernet/qlogic/qede/qede_main.c | 1807 ++++++++++++++++++++++++++ 2 files changed, 1935 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 7e2bcfae0db9..424ef4a55828 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -51,6 +51,7 @@ struct qede_dev { #define QEDE_MAX_TSS_CNT(edev) ((edev)->dev_info.num_queues * \ (edev)->dev_info.num_tc) + struct qede_fastpath *fp_array; u16 num_rss; u8 num_tc; #define QEDE_RSS_CNT(edev) ((edev)->num_rss) @@ -58,6 +59,9 @@ struct qede_dev { (edev)->num_tc) #define QEDE_TSS_IDX(edev, txqidx) ((txqidx) % (edev)->num_rss) #define QEDE_TC_IDX(edev, txqidx) ((txqidx) / (edev)->num_rss) +#define QEDE_TX_QUEUE(edev, txqidx) \ + (&(edev)->fp_array[QEDE_TSS_IDX((edev), (txqidx))].txqs[QEDE_TC_IDX( \ + (edev), (txqidx))]) struct qed_int_info int_info; unsigned char primary_mac[ETH_ALEN]; @@ -65,9 +69,133 @@ struct qede_dev { /* Smaller private varaiant of the RTNL lock */ struct mutex qede_lock; u32 state; /* Protected by qede_lock */ + u16 rx_buf_size; + /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */ +#define ETH_OVERHEAD (ETH_HLEN + 8 + 8) + /* Max supported alignment is 256 (8 shift) + * minimal alignment shift 6 is optimal for 57xxx HW performance + */ +#define QEDE_RX_ALIGN_SHIFT max(6, min(8, L1_CACHE_SHIFT)) + /* We assume skb_build() uses sizeof(struct skb_shared_info) bytes + * at the end of skb->data, to avoid wasting a full cache line. + * This reduces memory use (skb->truesize). + */ +#define QEDE_FW_RX_ALIGN_END \ + max_t(u64, 1UL << QEDE_RX_ALIGN_SHIFT, \ + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) + + struct qed_update_vport_rss_params rss_params; + u16 q_num_rx_buffers; /* Must be a power of two */ + u16 q_num_tx_buffers; /* Must be a power of two */ +}; + +enum QEDE_STATE { + QEDE_STATE_CLOSED, + QEDE_STATE_OPEN, +}; + +#define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo)) + +#define MAX_NUM_TC 8 +#define MAX_NUM_PRI 8 + +/* The driver supports the new build_skb() API: + * RX ring buffer contains pointer to kmalloc() data only, + * skb are built only after the frame was DMA-ed. + */ +struct sw_rx_data { + u8 *data; + + DEFINE_DMA_UNMAP_ADDR(mapping); +}; + +struct qede_rx_queue { + __le16 *hw_cons_ptr; + struct sw_rx_data *sw_rx_ring; + u16 sw_rx_cons; + u16 sw_rx_prod; + struct qed_chain rx_bd_ring; + struct qed_chain rx_comp_ring; + void __iomem *hw_rxq_prod_addr; + + int rx_buf_size; + + u16 num_rx_buffers; + u16 rxq_id; + + u64 rx_hw_errors; + u64 rx_alloc_errors; +}; + +union db_prod { + struct eth_db_data data; + u32 raw; +}; + +struct sw_tx_bd { + struct sk_buff *skb; + u8 flags; +/* Set on the first BD descriptor when there is a split BD */ +#define QEDE_TSO_SPLIT_BD BIT(0) +}; + +struct qede_tx_queue { + int index; /* Queue index */ + __le16 *hw_cons_ptr; + struct sw_tx_bd *sw_tx_ring; + u16 sw_tx_cons; + u16 sw_tx_prod; + struct qed_chain tx_pbl; + void __iomem *doorbell_addr; + union db_prod tx_db; + + u16 num_tx_buffers; +}; + +#define BD_UNMAP_ADDR(bd) HILO_U64(le32_to_cpu((bd)->addr.hi), \ + le32_to_cpu((bd)->addr.lo)) +#define BD_SET_UNMAP_ADDR_LEN(bd, maddr, len) \ + do { \ + (bd)->addr.hi = cpu_to_le32(upper_32_bits(maddr)); \ + (bd)->addr.lo = cpu_to_le32(lower_32_bits(maddr)); \ + (bd)->nbytes = cpu_to_le16(len); \ + } while (0) +#define BD_UNMAP_LEN(bd) (le16_to_cpu((bd)->nbytes)) + +struct qede_fastpath { + struct qede_dev *edev; + u8 rss_id; + struct napi_struct napi; + struct qed_sb_info *sb_info; + struct qede_rx_queue *rxq; + struct qede_tx_queue *txqs; + +#define VEC_NAME_SIZE (sizeof(((struct net_device *)0)->name) + 8) + char name[VEC_NAME_SIZE]; }; /* Debug print definitions */ #define DP_NAME(edev) ((edev)->ndev->name) +#define XMIT_PLAIN 0 +#define XMIT_L4_CSUM BIT(0) +#define XMIT_LSO BIT(1) +#define XMIT_ENC BIT(2) + +#define QEDE_CSUM_ERROR BIT(0) +#define QEDE_CSUM_UNNECESSARY BIT(1) +#define RX_RING_SIZE_POW 13 +#define RX_RING_SIZE BIT(RX_RING_SIZE_POW) +#define NUM_RX_BDS_MAX (RX_RING_SIZE - 1) +#define NUM_RX_BDS_MIN 128 +#define NUM_RX_BDS_DEF NUM_RX_BDS_MAX + +#define TX_RING_SIZE_POW 13 +#define TX_RING_SIZE BIT(TX_RING_SIZE_POW) +#define NUM_TX_BDS_MAX (TX_RING_SIZE - 1) +#define NUM_TX_BDS_MIN 128 +#define NUM_TX_BDS_DEF NUM_TX_BDS_MAX + +#define for_each_rss(i) for (i = 0; i < edev->num_rss; i++) + #endif /* _QEDE_H_ */ diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 02ed6dbf55a7..daba118f99ca 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -85,6 +85,8 @@ static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id); #define TX_TIMEOUT (5 * HZ) static void qede_remove(struct pci_dev *pdev); +static int qede_alloc_rx_buffer(struct qede_dev *edev, + struct qede_rx_queue *rxq); static struct pci_driver qede_pci_driver = { .name = "qede", @@ -93,6 +95,41 @@ static struct pci_driver qede_pci_driver = { .remove = qede_remove, }; +static int qede_netdev_event(struct notifier_block *this, unsigned long event, + void *ptr) +{ + struct net_device *ndev = netdev_notifier_info_to_dev(ptr); + struct ethtool_drvinfo drvinfo; + struct qede_dev *edev; + + /* Currently only support name change */ + if (event != NETDEV_CHANGENAME) + goto done; + + /* Check whether this is a qede device */ + if (!ndev || !ndev->ethtool_ops || !ndev->ethtool_ops->get_drvinfo) + goto done; + + memset(&drvinfo, 0, sizeof(drvinfo)); + ndev->ethtool_ops->get_drvinfo(ndev, &drvinfo); + if (strcmp(drvinfo.driver, "qede")) + goto done; + edev = netdev_priv(ndev); + + /* Notify qed of the name change */ + if (!edev->ops || !edev->ops->common) + goto done; + edev->ops->common->set_id(edev->cdev, edev->ndev->name, + "qede"); + +done: + return NOTIFY_DONE; +} + +static struct notifier_block qede_netdev_notifier = { + .notifier_call = qede_netdev_event, +}; + static int __init qede_init(void) { @@ -115,9 +152,20 @@ int __init qede_init(void) return -EINVAL; } + /* Must register notifier before pci ops, since we might miss + * interface rename after pci probe and netdev registeration. + */ + ret = register_netdevice_notifier(&qede_netdev_notifier); + if (ret) { + pr_notice("Failed to register netdevice_notifier\n"); + qed_put_eth_ops(); + return -EINVAL; + } + ret = pci_register_driver(&qede_pci_driver); if (ret) { pr_notice("Failed to register driver\n"); + unregister_netdevice_notifier(&qede_netdev_notifier); qed_put_eth_ops(); return -EINVAL; } @@ -129,6 +177,7 @@ static void __exit qede_cleanup(void) { pr_notice("qede_cleanup called\n"); + unregister_netdevice_notifier(&qede_netdev_notifier); pci_unregister_driver(&qede_pci_driver); qed_put_eth_ops(); } @@ -136,6 +185,858 @@ static void __exit qede_cleanup(void) module_init(qede_init); module_exit(qede_cleanup); +/* ------------------------------------------------------------------------- + * START OF FAST-PATH + * ------------------------------------------------------------------------- + */ + +/* Unmap the data and free skb */ +static int qede_free_tx_pkt(struct qede_dev *edev, + struct qede_tx_queue *txq, + int *len) +{ + u16 idx = txq->sw_tx_cons & NUM_TX_BDS_MAX; + struct sk_buff *skb = txq->sw_tx_ring[idx].skb; + struct eth_tx_1st_bd *first_bd; + struct eth_tx_bd *tx_data_bd; + int bds_consumed = 0; + int nbds; + bool data_split = txq->sw_tx_ring[idx].flags & QEDE_TSO_SPLIT_BD; + int i, split_bd_len = 0; + + if (unlikely(!skb)) { + DP_ERR(edev, + "skb is null for txq idx=%d txq->sw_tx_cons=%d txq->sw_tx_prod=%d\n", + idx, txq->sw_tx_cons, txq->sw_tx_prod); + return -1; + } + + *len = skb->len; + + first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl); + + bds_consumed++; + + nbds = first_bd->data.nbds; + + if (data_split) { + struct eth_tx_bd *split = (struct eth_tx_bd *) + qed_chain_consume(&txq->tx_pbl); + split_bd_len = BD_UNMAP_LEN(split); + bds_consumed++; + } + dma_unmap_page(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), + BD_UNMAP_LEN(first_bd) + split_bd_len, DMA_TO_DEVICE); + + /* Unmap the data of the skb frags */ + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++, bds_consumed++) { + tx_data_bd = (struct eth_tx_bd *) + qed_chain_consume(&txq->tx_pbl); + dma_unmap_page(&edev->pdev->dev, BD_UNMAP_ADDR(tx_data_bd), + BD_UNMAP_LEN(tx_data_bd), DMA_TO_DEVICE); + } + + while (bds_consumed++ < nbds) + qed_chain_consume(&txq->tx_pbl); + + /* Free skb */ + dev_kfree_skb_any(skb); + txq->sw_tx_ring[idx].skb = NULL; + txq->sw_tx_ring[idx].flags = 0; + + return 0; +} + +/* Unmap the data and free skb when mapping failed during start_xmit */ +static void qede_free_failed_tx_pkt(struct qede_dev *edev, + struct qede_tx_queue *txq, + struct eth_tx_1st_bd *first_bd, + int nbd, + bool data_split) +{ + u16 idx = txq->sw_tx_prod & NUM_TX_BDS_MAX; + struct sk_buff *skb = txq->sw_tx_ring[idx].skb; + struct eth_tx_bd *tx_data_bd; + int i, split_bd_len = 0; + + /* Return prod to its position before this skb was handled */ + qed_chain_set_prod(&txq->tx_pbl, + le16_to_cpu(txq->tx_db.data.bd_prod), + first_bd); + + first_bd = (struct eth_tx_1st_bd *)qed_chain_produce(&txq->tx_pbl); + + if (data_split) { + struct eth_tx_bd *split = (struct eth_tx_bd *) + qed_chain_produce(&txq->tx_pbl); + split_bd_len = BD_UNMAP_LEN(split); + nbd--; + } + + dma_unmap_page(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd), + BD_UNMAP_LEN(first_bd) + split_bd_len, DMA_TO_DEVICE); + + /* Unmap the data of the skb frags */ + for (i = 0; i < nbd; i++) { + tx_data_bd = (struct eth_tx_bd *) + qed_chain_produce(&txq->tx_pbl); + if (tx_data_bd->nbytes) + dma_unmap_page(&edev->pdev->dev, + BD_UNMAP_ADDR(tx_data_bd), + BD_UNMAP_LEN(tx_data_bd), DMA_TO_DEVICE); + } + + /* Return again prod to its position before this skb was handled */ + qed_chain_set_prod(&txq->tx_pbl, + le16_to_cpu(txq->tx_db.data.bd_prod), + first_bd); + + /* Free skb */ + dev_kfree_skb_any(skb); + txq->sw_tx_ring[idx].skb = NULL; + txq->sw_tx_ring[idx].flags = 0; +} + +static u32 qede_xmit_type(struct qede_dev *edev, + struct sk_buff *skb, + int *ipv6_ext) +{ + u32 rc = XMIT_L4_CSUM; + __be16 l3_proto; + + if (skb->ip_summed != CHECKSUM_PARTIAL) + return XMIT_PLAIN; + + l3_proto = vlan_get_protocol(skb); + if (l3_proto == htons(ETH_P_IPV6) && + (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6)) + *ipv6_ext = 1; + + if (skb_is_gso(skb)) + rc |= XMIT_LSO; + + return rc; +} + +static void qede_set_params_for_ipv6_ext(struct sk_buff *skb, + struct eth_tx_2nd_bd *second_bd, + struct eth_tx_3rd_bd *third_bd) +{ + u8 l4_proto; + u16 bd2_bits = 0, bd2_bits2 = 0; + + bd2_bits2 |= (1 << ETH_TX_DATA_2ND_BD_IPV6_EXT_SHIFT); + + bd2_bits |= ((((u8 *)skb_transport_header(skb) - skb->data) >> 1) & + ETH_TX_DATA_2ND_BD_L4_HDR_START_OFFSET_W_MASK) + << ETH_TX_DATA_2ND_BD_L4_HDR_START_OFFSET_W_SHIFT; + + bd2_bits2 |= (ETH_L4_PSEUDO_CSUM_CORRECT_LENGTH << + ETH_TX_DATA_2ND_BD_L4_PSEUDO_CSUM_MODE_SHIFT); + + if (vlan_get_protocol(skb) == htons(ETH_P_IPV6)) + l4_proto = ipv6_hdr(skb)->nexthdr; + else + l4_proto = ip_hdr(skb)->protocol; + + if (l4_proto == IPPROTO_UDP) + bd2_bits2 |= 1 << ETH_TX_DATA_2ND_BD_L4_UDP_SHIFT; + + if (third_bd) { + third_bd->data.bitfields |= + ((tcp_hdrlen(skb) / 4) & + ETH_TX_DATA_3RD_BD_TCP_HDR_LEN_DW_MASK) << + ETH_TX_DATA_3RD_BD_TCP_HDR_LEN_DW_SHIFT; + } + + second_bd->data.bitfields = cpu_to_le16(bd2_bits); + second_bd->data.bitfields2 = cpu_to_le16(bd2_bits2); +} + +static int map_frag_to_bd(struct qede_dev *edev, + skb_frag_t *frag, + struct eth_tx_bd *bd) +{ + dma_addr_t mapping; + + /* Map skb non-linear frag data for DMA */ + mapping = skb_frag_dma_map(&edev->pdev->dev, frag, 0, + skb_frag_size(frag), + DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) { + DP_NOTICE(edev, "Unable to map frag - dropping packet\n"); + return -ENOMEM; + } + + /* Setup the data pointer of the frag data */ + BD_SET_UNMAP_ADDR_LEN(bd, mapping, skb_frag_size(frag)); + + return 0; +} + +/* Main transmit function */ +static +netdev_tx_t qede_start_xmit(struct sk_buff *skb, + struct net_device *ndev) +{ + struct qede_dev *edev = netdev_priv(ndev); + struct netdev_queue *netdev_txq; + struct qede_tx_queue *txq; + struct eth_tx_1st_bd *first_bd; + struct eth_tx_2nd_bd *second_bd = NULL; + struct eth_tx_3rd_bd *third_bd = NULL; + struct eth_tx_bd *tx_data_bd = NULL; + u16 txq_index; + u8 nbd = 0; + dma_addr_t mapping; + int rc, frag_idx = 0, ipv6_ext = 0; + u8 xmit_type; + u16 idx; + u16 hlen; + bool data_split; + + /* Get tx-queue context and netdev index */ + txq_index = skb_get_queue_mapping(skb); + WARN_ON(txq_index >= QEDE_TSS_CNT(edev)); + txq = QEDE_TX_QUEUE(edev, txq_index); + netdev_txq = netdev_get_tx_queue(ndev, txq_index); + + /* Current code doesn't support SKB linearization, since the max number + * of skb frags can be passed in the FW HSI. + */ + BUILD_BUG_ON(MAX_SKB_FRAGS > ETH_TX_MAX_BDS_PER_NON_LSO_PACKET); + + WARN_ON(qed_chain_get_elem_left(&txq->tx_pbl) < + (MAX_SKB_FRAGS + 1)); + + xmit_type = qede_xmit_type(edev, skb, &ipv6_ext); + + /* Fill the entry in the SW ring and the BDs in the FW ring */ + idx = txq->sw_tx_prod & NUM_TX_BDS_MAX; + txq->sw_tx_ring[idx].skb = skb; + first_bd = (struct eth_tx_1st_bd *) + qed_chain_produce(&txq->tx_pbl); + memset(first_bd, 0, sizeof(*first_bd)); + first_bd->data.bd_flags.bitfields = + 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT; + + /* Map skb linear data for DMA and set in the first BD */ + mapping = dma_map_single(&edev->pdev->dev, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) { + DP_NOTICE(edev, "SKB mapping failed\n"); + qede_free_failed_tx_pkt(edev, txq, first_bd, 0, false); + return NETDEV_TX_OK; + } + nbd++; + BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb)); + + /* In case there is IPv6 with extension headers or LSO we need 2nd and + * 3rd BDs. + */ + if (unlikely((xmit_type & XMIT_LSO) | ipv6_ext)) { + second_bd = (struct eth_tx_2nd_bd *) + qed_chain_produce(&txq->tx_pbl); + memset(second_bd, 0, sizeof(*second_bd)); + + nbd++; + third_bd = (struct eth_tx_3rd_bd *) + qed_chain_produce(&txq->tx_pbl); + memset(third_bd, 0, sizeof(*third_bd)); + + nbd++; + /* We need to fill in additional data in second_bd... */ + tx_data_bd = (struct eth_tx_bd *)second_bd; + } + + if (skb_vlan_tag_present(skb)) { + first_bd->data.vlan = cpu_to_le16(skb_vlan_tag_get(skb)); + first_bd->data.bd_flags.bitfields |= + 1 << ETH_TX_1ST_BD_FLAGS_VLAN_INSERTION_SHIFT; + } + + /* Fill the parsing flags & params according to the requested offload */ + if (xmit_type & XMIT_L4_CSUM) { + /* We don't re-calculate IP checksum as it is already done by + * the upper stack + */ + first_bd->data.bd_flags.bitfields |= + 1 << ETH_TX_1ST_BD_FLAGS_L4_CSUM_SHIFT; + + /* If the packet is IPv6 with extension header, indicate that + * to FW and pass few params, since the device cracker doesn't + * support parsing IPv6 with extension header/s. + */ + if (unlikely(ipv6_ext)) + qede_set_params_for_ipv6_ext(skb, second_bd, third_bd); + } + + if (xmit_type & XMIT_LSO) { + first_bd->data.bd_flags.bitfields |= + (1 << ETH_TX_1ST_BD_FLAGS_LSO_SHIFT); + third_bd->data.lso_mss = + cpu_to_le16(skb_shinfo(skb)->gso_size); + + first_bd->data.bd_flags.bitfields |= + 1 << ETH_TX_1ST_BD_FLAGS_IP_CSUM_SHIFT; + hlen = skb_transport_header(skb) + + tcp_hdrlen(skb) - skb->data; + + /* @@@TBD - if will not be removed need to check */ + third_bd->data.bitfields |= + (1 << ETH_TX_DATA_3RD_BD_HDR_NBD_SHIFT); + + /* Make life easier for FW guys who can't deal with header and + * data on same BD. If we need to split, use the second bd... + */ + if (unlikely(skb_headlen(skb) > hlen)) { + DP_VERBOSE(edev, NETIF_MSG_TX_QUEUED, + "TSO split header size is %d (%x:%x)\n", + first_bd->nbytes, first_bd->addr.hi, + first_bd->addr.lo); + + mapping = HILO_U64(le32_to_cpu(first_bd->addr.hi), + le32_to_cpu(first_bd->addr.lo)) + + hlen; + + BD_SET_UNMAP_ADDR_LEN(tx_data_bd, mapping, + le16_to_cpu(first_bd->nbytes) - + hlen); + + /* this marks the BD as one that has no + * individual mapping + */ + txq->sw_tx_ring[idx].flags |= QEDE_TSO_SPLIT_BD; + + first_bd->nbytes = cpu_to_le16(hlen); + + tx_data_bd = (struct eth_tx_bd *)third_bd; + data_split = true; + } + } + + /* Handle fragmented skb */ + /* special handle for frags inside 2nd and 3rd bds.. */ + while (tx_data_bd && frag_idx < skb_shinfo(skb)->nr_frags) { + rc = map_frag_to_bd(edev, + &skb_shinfo(skb)->frags[frag_idx], + tx_data_bd); + if (rc) { + qede_free_failed_tx_pkt(edev, txq, first_bd, nbd, + data_split); + return NETDEV_TX_OK; + } + + if (tx_data_bd == (struct eth_tx_bd *)second_bd) + tx_data_bd = (struct eth_tx_bd *)third_bd; + else + tx_data_bd = NULL; + + frag_idx++; + } + + /* map last frags into 4th, 5th .... */ + for (; frag_idx < skb_shinfo(skb)->nr_frags; frag_idx++, nbd++) { + tx_data_bd = (struct eth_tx_bd *) + qed_chain_produce(&txq->tx_pbl); + + memset(tx_data_bd, 0, sizeof(*tx_data_bd)); + + rc = map_frag_to_bd(edev, + &skb_shinfo(skb)->frags[frag_idx], + tx_data_bd); + if (rc) { + qede_free_failed_tx_pkt(edev, txq, first_bd, nbd, + data_split); + return NETDEV_TX_OK; + } + } + + /* update the first BD with the actual num BDs */ + first_bd->data.nbds = nbd; + + netdev_tx_sent_queue(netdev_txq, skb->len); + + skb_tx_timestamp(skb); + + /* Advance packet producer only before sending the packet since mapping + * of pages may fail. + */ + txq->sw_tx_prod++; + + /* 'next page' entries are counted in the producer value */ + txq->tx_db.data.bd_prod = + cpu_to_le16(qed_chain_get_prod_idx(&txq->tx_pbl)); + + /* wmb makes sure that the BDs data is updated before updating the + * producer, otherwise FW may read old data from the BDs. + */ + wmb(); + barrier(); + writel(txq->tx_db.raw, txq->doorbell_addr); + + /* mmiowb is needed to synchronize doorbell writes from more than one + * processor. It guarantees that the write arrives to the device before + * the queue lock is released and another start_xmit is called (possibly + * on another CPU). Without this barrier, the next doorbell can bypass + * this doorbell. This is applicable to IA64/Altix systems. + */ + mmiowb(); + + if (unlikely(qed_chain_get_elem_left(&txq->tx_pbl) + < (MAX_SKB_FRAGS + 1))) { + netif_tx_stop_queue(netdev_txq); + DP_VERBOSE(edev, NETIF_MSG_TX_QUEUED, + "Stop queue was called\n"); + /* paired memory barrier is in qede_tx_int(), we have to keep + * ordering of set_bit() in netif_tx_stop_queue() and read of + * fp->bd_tx_cons + */ + smp_mb(); + + if (qed_chain_get_elem_left(&txq->tx_pbl) + >= (MAX_SKB_FRAGS + 1) && + (edev->state == QEDE_STATE_OPEN)) { + netif_tx_wake_queue(netdev_txq); + DP_VERBOSE(edev, NETIF_MSG_TX_QUEUED, + "Wake queue was called\n"); + } + } + + return NETDEV_TX_OK; +} + +static int qede_txq_has_work(struct qede_tx_queue *txq) +{ + u16 hw_bd_cons; + + /* Tell compiler that consumer and producer can change */ + barrier(); + hw_bd_cons = le16_to_cpu(*txq->hw_cons_ptr); + if (qed_chain_get_cons_idx(&txq->tx_pbl) == hw_bd_cons + 1) + return 0; + + return hw_bd_cons != qed_chain_get_cons_idx(&txq->tx_pbl); +} + +static int qede_tx_int(struct qede_dev *edev, + struct qede_tx_queue *txq) +{ + struct netdev_queue *netdev_txq; + u16 hw_bd_cons; + unsigned int pkts_compl = 0, bytes_compl = 0; + int rc; + + netdev_txq = netdev_get_tx_queue(edev->ndev, txq->index); + + hw_bd_cons = le16_to_cpu(*txq->hw_cons_ptr); + barrier(); + + while (hw_bd_cons != qed_chain_get_cons_idx(&txq->tx_pbl)) { + int len = 0; + + rc = qede_free_tx_pkt(edev, txq, &len); + if (rc) { + DP_NOTICE(edev, "hw_bd_cons = %d, chain_cons=%d\n", + hw_bd_cons, + qed_chain_get_cons_idx(&txq->tx_pbl)); + break; + } + + bytes_compl += len; + pkts_compl++; + txq->sw_tx_cons++; + } + + netdev_tx_completed_queue(netdev_txq, pkts_compl, bytes_compl); + + /* Need to make the tx_bd_cons update visible to start_xmit() + * before checking for netif_tx_queue_stopped(). Without the + * memory barrier, there is a small possibility that + * start_xmit() will miss it and cause the queue to be stopped + * forever. + * On the other hand we need an rmb() here to ensure the proper + * ordering of bit testing in the following + * netif_tx_queue_stopped(txq) call. + */ + smp_mb(); + + if (unlikely(netif_tx_queue_stopped(netdev_txq))) { + /* Taking tx_lock is needed to prevent reenabling the queue + * while it's empty. This could have happen if rx_action() gets + * suspended in qede_tx_int() after the condition before + * netif_tx_wake_queue(), while tx_action (qede_start_xmit()): + * + * stops the queue->sees fresh tx_bd_cons->releases the queue-> + * sends some packets consuming the whole queue again-> + * stops the queue + */ + + __netif_tx_lock(netdev_txq, smp_processor_id()); + + if ((netif_tx_queue_stopped(netdev_txq)) && + (edev->state == QEDE_STATE_OPEN) && + (qed_chain_get_elem_left(&txq->tx_pbl) + >= (MAX_SKB_FRAGS + 1))) { + netif_tx_wake_queue(netdev_txq); + DP_VERBOSE(edev, NETIF_MSG_TX_DONE, + "Wake queue was called\n"); + } + + __netif_tx_unlock(netdev_txq); + } + + return 0; +} + +static bool qede_has_rx_work(struct qede_rx_queue *rxq) +{ + u16 hw_comp_cons, sw_comp_cons; + + /* Tell compiler that status block fields can change */ + barrier(); + + hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr); + sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring); + + return hw_comp_cons != sw_comp_cons; +} + +static bool qede_has_tx_work(struct qede_fastpath *fp) +{ + u8 tc; + + for (tc = 0; tc < fp->edev->num_tc; tc++) + if (qede_txq_has_work(&fp->txqs[tc])) + return true; + return false; +} + +/* This function copies the Rx buffer from the CONS position to the PROD + * position, since we failed to allocate a new Rx buffer. + */ +static void qede_reuse_rx_data(struct qede_rx_queue *rxq) +{ + struct eth_rx_bd *rx_bd_cons = qed_chain_consume(&rxq->rx_bd_ring); + struct eth_rx_bd *rx_bd_prod = qed_chain_produce(&rxq->rx_bd_ring); + struct sw_rx_data *sw_rx_data_cons = + &rxq->sw_rx_ring[rxq->sw_rx_cons & NUM_RX_BDS_MAX]; + struct sw_rx_data *sw_rx_data_prod = + &rxq->sw_rx_ring[rxq->sw_rx_prod & NUM_RX_BDS_MAX]; + + dma_unmap_addr_set(sw_rx_data_prod, mapping, + dma_unmap_addr(sw_rx_data_cons, mapping)); + + sw_rx_data_prod->data = sw_rx_data_cons->data; + memcpy(rx_bd_prod, rx_bd_cons, sizeof(struct eth_rx_bd)); + + rxq->sw_rx_cons++; + rxq->sw_rx_prod++; +} + +static inline void qede_update_rx_prod(struct qede_dev *edev, + struct qede_rx_queue *rxq) +{ + u16 bd_prod = qed_chain_get_prod_idx(&rxq->rx_bd_ring); + u16 cqe_prod = qed_chain_get_prod_idx(&rxq->rx_comp_ring); + struct eth_rx_prod_data rx_prods = {0}; + + /* Update producers */ + rx_prods.bd_prod = cpu_to_le16(bd_prod); + rx_prods.cqe_prod = cpu_to_le16(cqe_prod); + + /* Make sure that the BD and SGE data is updated before updating the + * producers since FW might read the BD/SGE right after the producer + * is updated. + */ + wmb(); + + internal_ram_wr(rxq->hw_rxq_prod_addr, sizeof(rx_prods), + (u32 *)&rx_prods); + + /* mmiowb is needed to synchronize doorbell writes from more than one + * processor. It guarantees that the write arrives to the device before + * the napi lock is released and another qede_poll is called (possibly + * on another CPU). Without this barrier, the next doorbell can bypass + * this doorbell. This is applicable to IA64/Altix systems. + */ + mmiowb(); +} + +static u32 qede_get_rxhash(struct qede_dev *edev, + u8 bitfields, + __le32 rss_hash, + enum pkt_hash_types *rxhash_type) +{ + enum rss_hash_type htype; + + htype = GET_FIELD(bitfields, ETH_FAST_PATH_RX_REG_CQE_RSS_HASH_TYPE); + + if ((edev->ndev->features & NETIF_F_RXHASH) && htype) { + *rxhash_type = ((htype == RSS_HASH_TYPE_IPV4) || + (htype == RSS_HASH_TYPE_IPV6)) ? + PKT_HASH_TYPE_L3 : PKT_HASH_TYPE_L4; + return le32_to_cpu(rss_hash); + } + *rxhash_type = PKT_HASH_TYPE_NONE; + return 0; +} + +static void qede_set_skb_csum(struct sk_buff *skb, u8 csum_flag) +{ + skb_checksum_none_assert(skb); + + if (csum_flag & QEDE_CSUM_UNNECESSARY) + skb->ip_summed = CHECKSUM_UNNECESSARY; +} + +static inline void qede_skb_receive(struct qede_dev *edev, + struct qede_fastpath *fp, + struct sk_buff *skb, + u16 vlan_tag) +{ + if (vlan_tag) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + vlan_tag); + + napi_gro_receive(&fp->napi, skb); +} + +static u8 qede_check_csum(u16 flag) +{ + u16 csum_flag = 0; + u8 csum = 0; + + if ((PARSING_AND_ERR_FLAGS_L4CHKSMWASCALCULATED_MASK << + PARSING_AND_ERR_FLAGS_L4CHKSMWASCALCULATED_SHIFT) & flag) { + csum_flag |= PARSING_AND_ERR_FLAGS_L4CHKSMERROR_MASK << + PARSING_AND_ERR_FLAGS_L4CHKSMERROR_SHIFT; + csum = QEDE_CSUM_UNNECESSARY; + } + + csum_flag |= PARSING_AND_ERR_FLAGS_IPHDRERROR_MASK << + PARSING_AND_ERR_FLAGS_IPHDRERROR_SHIFT; + + if (csum_flag & flag) + return QEDE_CSUM_ERROR; + + return csum; +} + +static int qede_rx_int(struct qede_fastpath *fp, int budget) +{ + struct qede_dev *edev = fp->edev; + struct qede_rx_queue *rxq = fp->rxq; + + u16 hw_comp_cons, sw_comp_cons, sw_rx_index, parse_flag; + int rx_pkt = 0; + u8 csum_flag; + + hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr); + sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring); + + /* Memory barrier to prevent the CPU from doing speculative reads of CQE + * / BD in the while-loop before reading hw_comp_cons. If the CQE is + * read before it is written by FW, then FW writes CQE and SB, and then + * the CPU reads the hw_comp_cons, it will use an old CQE. + */ + rmb(); + + /* Loop to complete all indicated BDs */ + while (sw_comp_cons != hw_comp_cons) { + struct eth_fast_path_rx_reg_cqe *fp_cqe; + enum pkt_hash_types rxhash_type; + enum eth_rx_cqe_type cqe_type; + struct sw_rx_data *sw_rx_data; + union eth_rx_cqe *cqe; + struct sk_buff *skb; + u16 len, pad; + u32 rx_hash; + u8 *data; + + /* Get the CQE from the completion ring */ + cqe = (union eth_rx_cqe *) + qed_chain_consume(&rxq->rx_comp_ring); + cqe_type = cqe->fast_path_regular.type; + + if (unlikely(cqe_type == ETH_RX_CQE_TYPE_SLOW_PATH)) { + edev->ops->eth_cqe_completion( + edev->cdev, fp->rss_id, + (struct eth_slow_path_rx_cqe *)cqe); + goto next_cqe; + } + + /* Get the data from the SW ring */ + sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX; + sw_rx_data = &rxq->sw_rx_ring[sw_rx_index]; + data = sw_rx_data->data; + + fp_cqe = &cqe->fast_path_regular; + len = le16_to_cpu(fp_cqe->pkt_len); + pad = fp_cqe->placement_offset; + + /* For every Rx BD consumed, we allocate a new BD so the BD ring + * is always with a fixed size. If allocation fails, we take the + * consumed BD and return it to the ring in the PROD position. + * The packet that was received on that BD will be dropped (and + * not passed to the upper stack). + */ + if (likely(qede_alloc_rx_buffer(edev, rxq) == 0)) { + dma_unmap_single(&edev->pdev->dev, + dma_unmap_addr(sw_rx_data, mapping), + rxq->rx_buf_size, DMA_FROM_DEVICE); + + /* If this is an error packet then drop it */ + parse_flag = + le16_to_cpu(cqe->fast_path_regular.pars_flags.flags); + csum_flag = qede_check_csum(parse_flag); + if (csum_flag == QEDE_CSUM_ERROR) { + DP_NOTICE(edev, + "CQE in CONS = %u has error, flags = %x, dropping incoming packet\n", + sw_comp_cons, parse_flag); + rxq->rx_hw_errors++; + kfree(data); + goto next_rx; + } + + skb = build_skb(data, 0); + + if (unlikely(!skb)) { + DP_NOTICE(edev, + "Build_skb failed, dropping incoming packet\n"); + kfree(data); + rxq->rx_alloc_errors++; + goto next_rx; + } + + skb_reserve(skb, pad); + + } else { + DP_NOTICE(edev, + "New buffer allocation failed, dropping incoming packet and reusing its buffer\n"); + qede_reuse_rx_data(rxq); + rxq->rx_alloc_errors++; + goto next_cqe; + } + + sw_rx_data->data = NULL; + + skb_put(skb, len); + + skb->protocol = eth_type_trans(skb, edev->ndev); + + rx_hash = qede_get_rxhash(edev, fp_cqe->bitfields, + fp_cqe->rss_hash, + &rxhash_type); + + skb_set_hash(skb, rx_hash, rxhash_type); + + qede_set_skb_csum(skb, csum_flag); + + skb_record_rx_queue(skb, fp->rss_id); + + qede_skb_receive(edev, fp, skb, le16_to_cpu(fp_cqe->vlan_tag)); + + qed_chain_consume(&rxq->rx_bd_ring); + +next_rx: + rxq->sw_rx_cons++; + rx_pkt++; + +next_cqe: /* don't consume bd rx buffer */ + qed_chain_recycle_consumed(&rxq->rx_comp_ring); + sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring); + /* CR TPA - revisit how to handle budget in TPA perhaps + * increase on "end" + */ + if (rx_pkt == budget) + break; + } /* repeat while sw_comp_cons != hw_comp_cons... */ + + /* Update producers */ + qede_update_rx_prod(edev, rxq); + + return rx_pkt; +} + +static int qede_poll(struct napi_struct *napi, int budget) +{ + int work_done = 0; + struct qede_fastpath *fp = container_of(napi, struct qede_fastpath, + napi); + struct qede_dev *edev = fp->edev; + + while (1) { + u8 tc; + + for (tc = 0; tc < edev->num_tc; tc++) + if (qede_txq_has_work(&fp->txqs[tc])) + qede_tx_int(edev, &fp->txqs[tc]); + + if (qede_has_rx_work(fp->rxq)) { + work_done += qede_rx_int(fp, budget - work_done); + + /* must not complete if we consumed full budget */ + if (work_done >= budget) + break; + } + + /* Fall out from the NAPI loop if needed */ + if (!(qede_has_rx_work(fp->rxq) || qede_has_tx_work(fp))) { + qed_sb_update_sb_idx(fp->sb_info); + /* *_has_*_work() reads the status block, + * thus we need to ensure that status block indices + * have been actually read (qed_sb_update_sb_idx) + * prior to this check (*_has_*_work) so that + * we won't write the "newer" value of the status block + * to HW (if there was a DMA right after + * qede_has_rx_work and if there is no rmb, the memory + * reading (qed_sb_update_sb_idx) may be postponed + * to right before *_ack_sb). In this case there + * will never be another interrupt until there is + * another update of the status block, while there + * is still unhandled work. + */ + rmb(); + + if (!(qede_has_rx_work(fp->rxq) || + qede_has_tx_work(fp))) { + napi_complete(napi); + /* Update and reenable interrupts */ + qed_sb_ack(fp->sb_info, IGU_INT_ENABLE, + 1 /*update*/); + break; + } + } + } + + return work_done; +} + +static irqreturn_t qede_msix_fp_int(int irq, void *fp_cookie) +{ + struct qede_fastpath *fp = fp_cookie; + + qed_sb_ack(fp->sb_info, IGU_INT_DISABLE, 0 /*do not update*/); + + napi_schedule_irqoff(&fp->napi); + return IRQ_HANDLED; +} + +/* ------------------------------------------------------------------------- + * END OF FAST-PATH + * ------------------------------------------------------------------------- + */ + +static int qede_open(struct net_device *ndev); +static int qede_close(struct net_device *ndev); +static const struct net_device_ops qede_netdev_ops = { + .ndo_open = qede_open, + .ndo_stop = qede_close, + .ndo_start_xmit = qede_start_xmit, + .ndo_validate_addr = eth_validate_addr, +}; + /* ------------------------------------------------------------------------- * START OF PROBE / REMOVE * ------------------------------------------------------------------------- @@ -165,6 +1066,8 @@ static struct qede_dev *qede_alloc_etherdev(struct qed_dev *cdev, edev->dp_module = dp_module; edev->dp_level = dp_level; edev->ops = qed_ops; + edev->q_num_rx_buffers = NUM_RX_BDS_DEF; + edev->q_num_tx_buffers = NUM_TX_BDS_DEF; DP_INFO(edev, "Allocated netdev with 64 tx queues and 64 rx queues\n"); @@ -192,6 +1095,8 @@ static void qede_init_ndev(struct qede_dev *edev) ndev->watchdog_timeo = TX_TIMEOUT; + ndev->netdev_ops = &qede_netdev_ops; + /* user-changeble features */ hw_features = NETIF_F_GRO | NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | @@ -235,6 +1140,64 @@ static void qede_config_debug(uint debug, u32 *p_dp_module, u8 *p_dp_level) } } +static void qede_free_fp_array(struct qede_dev *edev) +{ + if (edev->fp_array) { + struct qede_fastpath *fp; + int i; + + for_each_rss(i) { + fp = &edev->fp_array[i]; + + kfree(fp->sb_info); + kfree(fp->rxq); + kfree(fp->txqs); + } + kfree(edev->fp_array); + } + edev->num_rss = 0; +} + +static int qede_alloc_fp_array(struct qede_dev *edev) +{ + struct qede_fastpath *fp; + int i; + + edev->fp_array = kcalloc(QEDE_RSS_CNT(edev), + sizeof(*edev->fp_array), GFP_KERNEL); + if (!edev->fp_array) { + DP_NOTICE(edev, "fp array allocation failed\n"); + goto err; + } + + for_each_rss(i) { + fp = &edev->fp_array[i]; + + fp->sb_info = kcalloc(1, sizeof(*fp->sb_info), GFP_KERNEL); + if (!fp->sb_info) { + DP_NOTICE(edev, "sb info struct allocation failed\n"); + goto err; + } + + fp->rxq = kcalloc(1, sizeof(*fp->rxq), GFP_KERNEL); + if (!fp->rxq) { + DP_NOTICE(edev, "RXQ struct allocation failed\n"); + goto err; + } + + fp->txqs = kcalloc(edev->num_tc, sizeof(*fp->txqs), GFP_KERNEL); + if (!fp->txqs) { + DP_NOTICE(edev, "TXQ array allocation failed\n"); + goto err; + } + } + + return 0; +err: + qede_free_fp_array(edev); + return -ENOMEM; +} + static void qede_update_pf_params(struct qed_dev *cdev) { struct qed_pf_params pf_params; @@ -298,12 +1261,20 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, qede_init_ndev(edev); + rc = register_netdev(edev->ndev); + if (rc) { + DP_NOTICE(edev, "Cannot register net-device\n"); + goto err3; + } + edev->ops->common->set_id(cdev, edev->ndev->name, DRV_MODULE_VERSION); DP_INFO(edev, "Ending successfully qede probe\n"); return 0; +err3: + free_netdev(edev->ndev); err2: qed_ops->common->slowpath_stop(cdev); err1: @@ -335,6 +1306,8 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) DP_INFO(edev, "Starting qede_remove\n"); + unregister_netdev(ndev); + edev->ops->common->set_power_state(cdev, PCI_D0); pci_set_drvdata(pdev, NULL); @@ -352,3 +1325,837 @@ static void qede_remove(struct pci_dev *pdev) { __qede_remove(pdev, QEDE_REMOVE_NORMAL); } + +/* ------------------------------------------------------------------------- + * START OF LOAD / UNLOAD + * ------------------------------------------------------------------------- + */ + +static int qede_set_num_queues(struct qede_dev *edev) +{ + int rc; + u16 rss_num; + + /* Setup queues according to possible resources*/ + rss_num = netif_get_num_default_rss_queues() * + edev->dev_info.common.num_hwfns; + + rss_num = min_t(u16, QEDE_MAX_RSS_CNT(edev), rss_num); + + rc = edev->ops->common->set_fp_int(edev->cdev, rss_num); + if (rc > 0) { + /* Managed to request interrupts for our queues */ + edev->num_rss = rc; + DP_INFO(edev, "Managed %d [of %d] RSS queues\n", + QEDE_RSS_CNT(edev), rss_num); + rc = 0; + } + return rc; +} + +static void qede_free_mem_sb(struct qede_dev *edev, + struct qed_sb_info *sb_info) +{ + if (sb_info->sb_virt) + dma_free_coherent(&edev->pdev->dev, sizeof(*sb_info->sb_virt), + (void *)sb_info->sb_virt, sb_info->sb_phys); +} + +/* This function allocates fast-path status block memory */ +static int qede_alloc_mem_sb(struct qede_dev *edev, + struct qed_sb_info *sb_info, + u16 sb_id) +{ + struct status_block *sb_virt; + dma_addr_t sb_phys; + int rc; + + sb_virt = dma_alloc_coherent(&edev->pdev->dev, + sizeof(*sb_virt), + &sb_phys, GFP_KERNEL); + if (!sb_virt) { + DP_ERR(edev, "Status block allocation failed\n"); + return -ENOMEM; + } + + rc = edev->ops->common->sb_init(edev->cdev, sb_info, + sb_virt, sb_phys, sb_id, + QED_SB_TYPE_L2_QUEUE); + if (rc) { + DP_ERR(edev, "Status block initialization failed\n"); + dma_free_coherent(&edev->pdev->dev, sizeof(*sb_virt), + sb_virt, sb_phys); + return rc; + } + + return 0; +} + +static void qede_free_rx_buffers(struct qede_dev *edev, + struct qede_rx_queue *rxq) +{ + u16 i; + + for (i = rxq->sw_rx_cons; i != rxq->sw_rx_prod; i++) { + struct sw_rx_data *rx_buf; + u8 *data; + + rx_buf = &rxq->sw_rx_ring[i & NUM_RX_BDS_MAX]; + data = rx_buf->data; + + dma_unmap_single(&edev->pdev->dev, + dma_unmap_addr(rx_buf, mapping), + rxq->rx_buf_size, DMA_FROM_DEVICE); + + rx_buf->data = NULL; + kfree(data); + } +} + +static void qede_free_mem_rxq(struct qede_dev *edev, + struct qede_rx_queue *rxq) +{ + /* Free rx buffers */ + qede_free_rx_buffers(edev, rxq); + + /* Free the parallel SW ring */ + kfree(rxq->sw_rx_ring); + + /* Free the real RQ ring used by FW */ + edev->ops->common->chain_free(edev->cdev, &rxq->rx_bd_ring); + edev->ops->common->chain_free(edev->cdev, &rxq->rx_comp_ring); +} + +static int qede_alloc_rx_buffer(struct qede_dev *edev, + struct qede_rx_queue *rxq) +{ + struct sw_rx_data *sw_rx_data; + struct eth_rx_bd *rx_bd; + dma_addr_t mapping; + u16 rx_buf_size; + u8 *data; + + rx_buf_size = rxq->rx_buf_size; + + data = kmalloc(rx_buf_size, GFP_ATOMIC); + if (unlikely(!data)) { + DP_NOTICE(edev, "Failed to allocate Rx data\n"); + return -ENOMEM; + } + + mapping = dma_map_single(&edev->pdev->dev, data, + rx_buf_size, DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) { + kfree(data); + DP_NOTICE(edev, "Failed to map Rx buffer\n"); + return -ENOMEM; + } + + sw_rx_data = &rxq->sw_rx_ring[rxq->sw_rx_prod & NUM_RX_BDS_MAX]; + sw_rx_data->data = data; + + dma_unmap_addr_set(sw_rx_data, mapping, mapping); + + /* Advance PROD and get BD pointer */ + rx_bd = (struct eth_rx_bd *)qed_chain_produce(&rxq->rx_bd_ring); + WARN_ON(!rx_bd); + rx_bd->addr.hi = cpu_to_le32(upper_32_bits(mapping)); + rx_bd->addr.lo = cpu_to_le32(lower_32_bits(mapping)); + + rxq->sw_rx_prod++; + + return 0; +} + +/* This function allocates all memory needed per Rx queue */ +static int qede_alloc_mem_rxq(struct qede_dev *edev, + struct qede_rx_queue *rxq) +{ + int i, rc, size, num_allocated; + + rxq->num_rx_buffers = edev->q_num_rx_buffers; + + rxq->rx_buf_size = NET_IP_ALIGN + + ETH_OVERHEAD + + edev->ndev->mtu + + QEDE_FW_RX_ALIGN_END; + + /* Allocate the parallel driver ring for Rx buffers */ + size = sizeof(*rxq->sw_rx_ring) * NUM_RX_BDS_MAX; + rxq->sw_rx_ring = kzalloc(size, GFP_KERNEL); + if (!rxq->sw_rx_ring) { + DP_ERR(edev, "Rx buffers ring allocation failed\n"); + goto err; + } + + /* Allocate FW Rx ring */ + rc = edev->ops->common->chain_alloc(edev->cdev, + QED_CHAIN_USE_TO_CONSUME_PRODUCE, + QED_CHAIN_MODE_NEXT_PTR, + NUM_RX_BDS_MAX, + sizeof(struct eth_rx_bd), + &rxq->rx_bd_ring); + + if (rc) + goto err; + + /* Allocate FW completion ring */ + rc = edev->ops->common->chain_alloc(edev->cdev, + QED_CHAIN_USE_TO_CONSUME, + QED_CHAIN_MODE_PBL, + NUM_RX_BDS_MAX, + sizeof(union eth_rx_cqe), + &rxq->rx_comp_ring); + if (rc) + goto err; + + /* Allocate buffers for the Rx ring */ + for (i = 0; i < rxq->num_rx_buffers; i++) { + rc = qede_alloc_rx_buffer(edev, rxq); + if (rc) + break; + } + num_allocated = i; + if (!num_allocated) { + DP_ERR(edev, "Rx buffers allocation failed\n"); + goto err; + } else if (num_allocated < rxq->num_rx_buffers) { + DP_NOTICE(edev, + "Allocated less buffers than desired (%d allocated)\n", + num_allocated); + } + + return 0; + +err: + qede_free_mem_rxq(edev, rxq); + return -ENOMEM; +} + +static void qede_free_mem_txq(struct qede_dev *edev, + struct qede_tx_queue *txq) +{ + /* Free the parallel SW ring */ + kfree(txq->sw_tx_ring); + + /* Free the real RQ ring used by FW */ + edev->ops->common->chain_free(edev->cdev, &txq->tx_pbl); +} + +/* This function allocates all memory needed per Tx queue */ +static int qede_alloc_mem_txq(struct qede_dev *edev, + struct qede_tx_queue *txq) +{ + int size, rc; + union eth_tx_bd_types *p_virt; + + txq->num_tx_buffers = edev->q_num_tx_buffers; + + /* Allocate the parallel driver ring for Tx buffers */ + size = sizeof(*txq->sw_tx_ring) * NUM_TX_BDS_MAX; + txq->sw_tx_ring = kzalloc(size, GFP_KERNEL); + if (!txq->sw_tx_ring) { + DP_NOTICE(edev, "Tx buffers ring allocation failed\n"); + goto err; + } + + rc = edev->ops->common->chain_alloc(edev->cdev, + QED_CHAIN_USE_TO_CONSUME_PRODUCE, + QED_CHAIN_MODE_PBL, + NUM_TX_BDS_MAX, + sizeof(*p_virt), + &txq->tx_pbl); + if (rc) + goto err; + + return 0; + +err: + qede_free_mem_txq(edev, txq); + return -ENOMEM; +} + +/* This function frees all memory of a single fp */ +static void qede_free_mem_fp(struct qede_dev *edev, + struct qede_fastpath *fp) +{ + int tc; + + qede_free_mem_sb(edev, fp->sb_info); + + qede_free_mem_rxq(edev, fp->rxq); + + for (tc = 0; tc < edev->num_tc; tc++) + qede_free_mem_txq(edev, &fp->txqs[tc]); +} + +/* This function allocates all memory needed for a single fp (i.e. an entity + * which contains status block, one rx queue and multiple per-TC tx queues. + */ +static int qede_alloc_mem_fp(struct qede_dev *edev, + struct qede_fastpath *fp) +{ + int rc, tc; + + rc = qede_alloc_mem_sb(edev, fp->sb_info, fp->rss_id); + if (rc) + goto err; + + rc = qede_alloc_mem_rxq(edev, fp->rxq); + if (rc) + goto err; + + for (tc = 0; tc < edev->num_tc; tc++) { + rc = qede_alloc_mem_txq(edev, &fp->txqs[tc]); + if (rc) + goto err; + } + + return 0; + +err: + qede_free_mem_fp(edev, fp); + return -ENOMEM; +} + +static void qede_free_mem_load(struct qede_dev *edev) +{ + int i; + + for_each_rss(i) { + struct qede_fastpath *fp = &edev->fp_array[i]; + + qede_free_mem_fp(edev, fp); + } +} + +/* This function allocates all qede memory at NIC load. */ +static int qede_alloc_mem_load(struct qede_dev *edev) +{ + int rc = 0, rss_id; + + for (rss_id = 0; rss_id < QEDE_RSS_CNT(edev); rss_id++) { + struct qede_fastpath *fp = &edev->fp_array[rss_id]; + + rc = qede_alloc_mem_fp(edev, fp); + if (rc) + break; + } + + if (rss_id != QEDE_RSS_CNT(edev)) { + /* Failed allocating memory for all the queues */ + if (!rss_id) { + DP_ERR(edev, + "Failed to allocate memory for the leading queue\n"); + rc = -ENOMEM; + } else { + DP_NOTICE(edev, + "Failed to allocate memory for all of RSS queues\n Desired: %d queues, allocated: %d queues\n", + QEDE_RSS_CNT(edev), rss_id); + } + edev->num_rss = rss_id; + } + + return 0; +} + +/* This function inits fp content and resets the SB, RXQ and TXQ structures */ +static void qede_init_fp(struct qede_dev *edev) +{ + int rss_id, txq_index, tc; + struct qede_fastpath *fp; + + for_each_rss(rss_id) { + fp = &edev->fp_array[rss_id]; + + fp->edev = edev; + fp->rss_id = rss_id; + + memset((void *)&fp->napi, 0, sizeof(fp->napi)); + + memset((void *)fp->sb_info, 0, sizeof(*fp->sb_info)); + + memset((void *)fp->rxq, 0, sizeof(*fp->rxq)); + fp->rxq->rxq_id = rss_id; + + memset((void *)fp->txqs, 0, (edev->num_tc * sizeof(*fp->txqs))); + for (tc = 0; tc < edev->num_tc; tc++) { + txq_index = tc * QEDE_RSS_CNT(edev) + rss_id; + fp->txqs[tc].index = txq_index; + } + + snprintf(fp->name, sizeof(fp->name), "%s-fp-%d", + edev->ndev->name, rss_id); + } +} + +static int qede_set_real_num_queues(struct qede_dev *edev) +{ + int rc = 0; + + rc = netif_set_real_num_tx_queues(edev->ndev, QEDE_TSS_CNT(edev)); + if (rc) { + DP_NOTICE(edev, "Failed to set real number of Tx queues\n"); + return rc; + } + rc = netif_set_real_num_rx_queues(edev->ndev, QEDE_RSS_CNT(edev)); + if (rc) { + DP_NOTICE(edev, "Failed to set real number of Rx queues\n"); + return rc; + } + + return 0; +} + +static void qede_napi_disable_remove(struct qede_dev *edev) +{ + int i; + + for_each_rss(i) { + napi_disable(&edev->fp_array[i].napi); + + netif_napi_del(&edev->fp_array[i].napi); + } +} + +static void qede_napi_add_enable(struct qede_dev *edev) +{ + int i; + + /* Add NAPI objects */ + for_each_rss(i) { + netif_napi_add(edev->ndev, &edev->fp_array[i].napi, + qede_poll, NAPI_POLL_WEIGHT); + napi_enable(&edev->fp_array[i].napi); + } +} + +static void qede_sync_free_irqs(struct qede_dev *edev) +{ + int i; + + for (i = 0; i < edev->int_info.used_cnt; i++) { + if (edev->int_info.msix_cnt) { + synchronize_irq(edev->int_info.msix[i].vector); + free_irq(edev->int_info.msix[i].vector, + &edev->fp_array[i]); + } else { + edev->ops->common->simd_handler_clean(edev->cdev, i); + } + } + + edev->int_info.used_cnt = 0; +} + +static int qede_req_msix_irqs(struct qede_dev *edev) +{ + int i, rc; + + /* Sanitize number of interrupts == number of prepared RSS queues */ + if (QEDE_RSS_CNT(edev) > edev->int_info.msix_cnt) { + DP_ERR(edev, + "Interrupt mismatch: %d RSS queues > %d MSI-x vectors\n", + QEDE_RSS_CNT(edev), edev->int_info.msix_cnt); + return -EINVAL; + } + + for (i = 0; i < QEDE_RSS_CNT(edev); i++) { + rc = request_irq(edev->int_info.msix[i].vector, + qede_msix_fp_int, 0, edev->fp_array[i].name, + &edev->fp_array[i]); + if (rc) { + DP_ERR(edev, "Request fp %d irq failed\n", i); + qede_sync_free_irqs(edev); + return rc; + } + DP_VERBOSE(edev, NETIF_MSG_INTR, + "Requested fp irq for %s [entry %d]. Cookie is at %p\n", + edev->fp_array[i].name, i, + &edev->fp_array[i]); + edev->int_info.used_cnt++; + } + + return 0; +} + +static void qede_simd_fp_handler(void *cookie) +{ + struct qede_fastpath *fp = (struct qede_fastpath *)cookie; + + napi_schedule_irqoff(&fp->napi); +} + +static int qede_setup_irqs(struct qede_dev *edev) +{ + int i, rc = 0; + + /* Learn Interrupt configuration */ + rc = edev->ops->common->get_fp_int(edev->cdev, &edev->int_info); + if (rc) + return rc; + + if (edev->int_info.msix_cnt) { + rc = qede_req_msix_irqs(edev); + if (rc) + return rc; + edev->ndev->irq = edev->int_info.msix[0].vector; + } else { + const struct qed_common_ops *ops; + + /* qed should learn receive the RSS ids and callbacks */ + ops = edev->ops->common; + for (i = 0; i < QEDE_RSS_CNT(edev); i++) + ops->simd_handler_config(edev->cdev, + &edev->fp_array[i], i, + qede_simd_fp_handler); + edev->int_info.used_cnt = QEDE_RSS_CNT(edev); + } + return 0; +} + +static int qede_drain_txq(struct qede_dev *edev, + struct qede_tx_queue *txq, + bool allow_drain) +{ + int rc, cnt = 1000; + + while (txq->sw_tx_cons != txq->sw_tx_prod) { + if (!cnt) { + if (allow_drain) { + DP_NOTICE(edev, + "Tx queue[%d] is stuck, requesting MCP to drain\n", + txq->index); + rc = edev->ops->common->drain(edev->cdev); + if (rc) + return rc; + return qede_drain_txq(edev, txq, false); + } + DP_NOTICE(edev, + "Timeout waiting for tx queue[%d]: PROD=%d, CONS=%d\n", + txq->index, txq->sw_tx_prod, + txq->sw_tx_cons); + return -ENODEV; + } + cnt--; + usleep_range(1000, 2000); + barrier(); + } + + /* FW finished processing, wait for HW to transmit all tx packets */ + usleep_range(1000, 2000); + + return 0; +} + +static int qede_stop_queues(struct qede_dev *edev) +{ + struct qed_update_vport_params vport_update_params; + struct qed_dev *cdev = edev->cdev; + int rc, tc, i; + + /* Disable the vport */ + memset(&vport_update_params, 0, sizeof(vport_update_params)); + vport_update_params.vport_id = 0; + vport_update_params.update_vport_active_flg = 1; + vport_update_params.vport_active_flg = 0; + vport_update_params.update_rss_flg = 0; + + rc = edev->ops->vport_update(cdev, &vport_update_params); + if (rc) { + DP_ERR(edev, "Failed to update vport\n"); + return rc; + } + + /* Flush Tx queues. If needed, request drain from MCP */ + for_each_rss(i) { + struct qede_fastpath *fp = &edev->fp_array[i]; + + for (tc = 0; tc < edev->num_tc; tc++) { + struct qede_tx_queue *txq = &fp->txqs[tc]; + + rc = qede_drain_txq(edev, txq, true); + if (rc) + return rc; + } + } + + /* Stop all Queues in reverse order*/ + for (i = QEDE_RSS_CNT(edev) - 1; i >= 0; i--) { + struct qed_stop_rxq_params rx_params; + + /* Stop the Tx Queue(s)*/ + for (tc = 0; tc < edev->num_tc; tc++) { + struct qed_stop_txq_params tx_params; + + tx_params.rss_id = i; + tx_params.tx_queue_id = tc * QEDE_RSS_CNT(edev) + i; + rc = edev->ops->q_tx_stop(cdev, &tx_params); + if (rc) { + DP_ERR(edev, "Failed to stop TXQ #%d\n", + tx_params.tx_queue_id); + return rc; + } + } + + /* Stop the Rx Queue*/ + memset(&rx_params, 0, sizeof(rx_params)); + rx_params.rss_id = i; + rx_params.rx_queue_id = i; + + rc = edev->ops->q_rx_stop(cdev, &rx_params); + if (rc) { + DP_ERR(edev, "Failed to stop RXQ #%d\n", i); + return rc; + } + } + + /* Stop the vport */ + rc = edev->ops->vport_stop(cdev, 0); + if (rc) + DP_ERR(edev, "Failed to stop VPORT\n"); + + return rc; +} + +static int qede_start_queues(struct qede_dev *edev) +{ + int rc, tc, i; + int vport_id = 0, drop_ttl0_flg = 1, vlan_removal_en = 1; + struct qed_dev *cdev = edev->cdev; + struct qed_update_vport_rss_params *rss_params = &edev->rss_params; + struct qed_update_vport_params vport_update_params; + struct qed_queue_start_common_params q_params; + + if (!edev->num_rss) { + DP_ERR(edev, + "Cannot update V-VPORT as active as there are no Rx queues\n"); + return -EINVAL; + } + + rc = edev->ops->vport_start(cdev, vport_id, + edev->ndev->mtu, + drop_ttl0_flg, + vlan_removal_en); + + if (rc) { + DP_ERR(edev, "Start V-PORT failed %d\n", rc); + return rc; + } + + DP_VERBOSE(edev, NETIF_MSG_IFUP, + "Start vport ramrod passed, vport_id = %d, MTU = %d, vlan_removal_en = %d\n", + vport_id, edev->ndev->mtu + 0xe, vlan_removal_en); + + for_each_rss(i) { + struct qede_fastpath *fp = &edev->fp_array[i]; + dma_addr_t phys_table = fp->rxq->rx_comp_ring.pbl.p_phys_table; + + memset(&q_params, 0, sizeof(q_params)); + q_params.rss_id = i; + q_params.queue_id = i; + q_params.vport_id = 0; + q_params.sb = fp->sb_info->igu_sb_id; + q_params.sb_idx = RX_PI; + + rc = edev->ops->q_rx_start(cdev, &q_params, + fp->rxq->rx_buf_size, + fp->rxq->rx_bd_ring.p_phys_addr, + phys_table, + fp->rxq->rx_comp_ring.page_cnt, + &fp->rxq->hw_rxq_prod_addr); + if (rc) { + DP_ERR(edev, "Start RXQ #%d failed %d\n", i, rc); + return rc; + } + + fp->rxq->hw_cons_ptr = &fp->sb_info->sb_virt->pi_array[RX_PI]; + + qede_update_rx_prod(edev, fp->rxq); + + for (tc = 0; tc < edev->num_tc; tc++) { + struct qede_tx_queue *txq = &fp->txqs[tc]; + int txq_index = tc * QEDE_RSS_CNT(edev) + i; + + memset(&q_params, 0, sizeof(q_params)); + q_params.rss_id = i; + q_params.queue_id = txq_index; + q_params.vport_id = 0; + q_params.sb = fp->sb_info->igu_sb_id; + q_params.sb_idx = TX_PI(tc); + + rc = edev->ops->q_tx_start(cdev, &q_params, + txq->tx_pbl.pbl.p_phys_table, + txq->tx_pbl.page_cnt, + &txq->doorbell_addr); + if (rc) { + DP_ERR(edev, "Start TXQ #%d failed %d\n", + txq_index, rc); + return rc; + } + + txq->hw_cons_ptr = + &fp->sb_info->sb_virt->pi_array[TX_PI(tc)]; + SET_FIELD(txq->tx_db.data.params, + ETH_DB_DATA_DEST, DB_DEST_XCM); + SET_FIELD(txq->tx_db.data.params, ETH_DB_DATA_AGG_CMD, + DB_AGG_CMD_SET); + SET_FIELD(txq->tx_db.data.params, + ETH_DB_DATA_AGG_VAL_SEL, + DQ_XCM_ETH_TX_BD_PROD_CMD); + + txq->tx_db.data.agg_flags = DQ_XCM_ETH_DQ_CF_CMD; + } + } + + /* Prepare and send the vport enable */ + memset(&vport_update_params, 0, sizeof(vport_update_params)); + vport_update_params.vport_id = vport_id; + vport_update_params.update_vport_active_flg = 1; + vport_update_params.vport_active_flg = 1; + + /* Fill struct with RSS params */ + if (QEDE_RSS_CNT(edev) > 1) { + vport_update_params.update_rss_flg = 1; + for (i = 0; i < 128; i++) + rss_params->rss_ind_table[i] = + ethtool_rxfh_indir_default(i, QEDE_RSS_CNT(edev)); + netdev_rss_key_fill(rss_params->rss_key, + sizeof(rss_params->rss_key)); + } else { + memset(rss_params, 0, sizeof(*rss_params)); + } + memcpy(&vport_update_params.rss_params, rss_params, + sizeof(*rss_params)); + + rc = edev->ops->vport_update(cdev, &vport_update_params); + if (rc) { + DP_ERR(edev, "Update V-PORT failed %d\n", rc); + return rc; + } + + return 0; +} + +enum qede_unload_mode { + QEDE_UNLOAD_NORMAL, +}; + +static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode) +{ + int rc; + + DP_INFO(edev, "Starting qede unload\n"); + + /* Close OS Tx */ + netif_tx_disable(edev->ndev); + netif_carrier_off(edev->ndev); + + rc = qede_stop_queues(edev); + if (rc) { + qede_sync_free_irqs(edev); + goto out; + } + + DP_INFO(edev, "Stopped Queues\n"); + + edev->ops->fastpath_stop(edev->cdev); + + /* Release the interrupts */ + qede_sync_free_irqs(edev); + edev->ops->common->set_fp_int(edev->cdev, 0); + + qede_napi_disable_remove(edev); + + qede_free_mem_load(edev); + qede_free_fp_array(edev); + +out: + mutex_unlock(&edev->qede_lock); + DP_INFO(edev, "Ending qede unload\n"); +} + +enum qede_load_mode { + QEDE_LOAD_NORMAL, +}; + +static int qede_load(struct qede_dev *edev, enum qede_load_mode mode) +{ + int rc; + + DP_INFO(edev, "Starting qede load\n"); + + rc = qede_set_num_queues(edev); + if (rc) + goto err0; + + rc = qede_alloc_fp_array(edev); + if (rc) + goto err0; + + qede_init_fp(edev); + + rc = qede_alloc_mem_load(edev); + if (rc) + goto err1; + DP_INFO(edev, "Allocated %d RSS queues on %d TC/s\n", + QEDE_RSS_CNT(edev), edev->num_tc); + + rc = qede_set_real_num_queues(edev); + if (rc) + goto err2; + + qede_napi_add_enable(edev); + DP_INFO(edev, "Napi added and enabled\n"); + + rc = qede_setup_irqs(edev); + if (rc) + goto err3; + DP_INFO(edev, "Setup IRQs succeeded\n"); + + rc = qede_start_queues(edev); + if (rc) + goto err4; + DP_INFO(edev, "Start VPORT, RXQ and TXQ succeeded\n"); + + /* Add primary mac and set Rx filters */ + ether_addr_copy(edev->primary_mac, edev->ndev->dev_addr); + + DP_INFO(edev, "Ending successfully qede load\n"); + + return 0; + +err4: + qede_sync_free_irqs(edev); + memset(&edev->int_info.msix_cnt, 0, sizeof(struct qed_int_info)); +err3: + qede_napi_disable_remove(edev); +err2: + qede_free_mem_load(edev); +err1: + edev->ops->common->set_fp_int(edev->cdev, 0); + qede_free_fp_array(edev); + edev->num_rss = 0; +err0: + return rc; +} + +/* called with rtnl_lock */ +static int qede_open(struct net_device *ndev) +{ + struct qede_dev *edev = netdev_priv(ndev); + + netif_carrier_off(ndev); + + edev->ops->common->set_power_state(edev->cdev, PCI_D0); + + return qede_load(edev, QEDE_LOAD_NORMAL); +} + +static int qede_close(struct net_device *ndev) +{ + struct qede_dev *edev = netdev_priv(ndev); + + qede_unload(edev, QEDE_UNLOAD_NORMAL); + + return 0; +} -- cgit v1.2.3 From 0d8e0aa05796c8a5652c164de5e4f16d8c9ee199 Mon Sep 17 00:00:00 2001 From: Sudarsana Kalluru Date: Mon, 26 Oct 2015 11:02:30 +0200 Subject: qede: classification configuration Add the ability to configure basic classification in driver by implementing ndo_set_mac_address() and ndo_set_rx_mode(). Signed-off-by: Sudarsana Kalluru Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede.h | 10 ++ drivers/net/ethernet/qlogic/qede/qede_main.c | 241 +++++++++++++++++++++++++++ 2 files changed, 251 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 424ef4a55828..79479427b6d4 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -87,6 +87,9 @@ struct qede_dev { struct qed_update_vport_rss_params rss_params; u16 q_num_rx_buffers; /* Must be a power of two */ u16 q_num_tx_buffers; /* Must be a power of two */ + + struct delayed_work sp_task; + unsigned long sp_flags; }; enum QEDE_STATE { @@ -184,6 +187,13 @@ struct qede_fastpath { #define QEDE_CSUM_ERROR BIT(0) #define QEDE_CSUM_UNNECESSARY BIT(1) + +#define QEDE_SP_RX_MODE 1 + +union qede_reload_args { + u16 mtu; +}; + #define RX_RING_SIZE_POW 13 #define RX_RING_SIZE BIT(RX_RING_SIZE_POW) #define NUM_RX_BDS_MAX (RX_RING_SIZE - 1) diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index daba118f99ca..0351204317e7 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -1030,10 +1030,31 @@ static irqreturn_t qede_msix_fp_int(int irq, void *fp_cookie) static int qede_open(struct net_device *ndev); static int qede_close(struct net_device *ndev); +static int qede_set_mac_addr(struct net_device *ndev, void *p); +static void qede_set_rx_mode(struct net_device *ndev); +static void qede_config_rx_mode(struct net_device *ndev); + +static int qede_set_ucast_rx_mac(struct qede_dev *edev, + enum qed_filter_xcast_params_type opcode, + unsigned char mac[ETH_ALEN]) +{ + struct qed_filter_params filter_cmd; + + memset(&filter_cmd, 0, sizeof(filter_cmd)); + filter_cmd.type = QED_FILTER_TYPE_UCAST; + filter_cmd.filter.ucast.type = opcode; + filter_cmd.filter.ucast.mac_valid = 1; + ether_addr_copy(filter_cmd.filter.ucast.mac, mac); + + return edev->ops->filter_config(edev->cdev, &filter_cmd); +} + static const struct net_device_ops qede_netdev_ops = { .ndo_open = qede_open, .ndo_stop = qede_close, .ndo_start_xmit = qede_start_xmit, + .ndo_set_rx_mode = qede_set_rx_mode, + .ndo_set_mac_address = qede_set_mac_addr, .ndo_validate_addr = eth_validate_addr, }; @@ -1198,6 +1219,20 @@ err: return -ENOMEM; } +static void qede_sp_task(struct work_struct *work) +{ + struct qede_dev *edev = container_of(work, struct qede_dev, + sp_task.work); + mutex_lock(&edev->qede_lock); + + if (edev->state == QEDE_STATE_OPEN) { + if (test_and_clear_bit(QEDE_SP_RX_MODE, &edev->sp_flags)) + qede_config_rx_mode(edev->ndev); + } + + mutex_unlock(&edev->qede_lock); +} + static void qede_update_pf_params(struct qed_dev *cdev) { struct qed_pf_params pf_params; @@ -1269,6 +1304,9 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, edev->ops->common->set_id(cdev, edev->ndev->name, DRV_MODULE_VERSION); + INIT_DELAYED_WORK(&edev->sp_task, qede_sp_task); + mutex_init(&edev->qede_lock); + DP_INFO(edev, "Ending successfully qede probe\n"); return 0; @@ -1306,6 +1344,7 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) DP_INFO(edev, "Starting qede_remove\n"); + cancel_delayed_work_sync(&edev->sp_task); unregister_netdev(ndev); edev->ops->common->set_power_state(cdev, PCI_D0); @@ -2036,6 +2075,24 @@ static int qede_start_queues(struct qede_dev *edev) return 0; } +static int qede_set_mcast_rx_mac(struct qede_dev *edev, + enum qed_filter_xcast_params_type opcode, + unsigned char *mac, int num_macs) +{ + struct qed_filter_params filter_cmd; + int i; + + memset(&filter_cmd, 0, sizeof(filter_cmd)); + filter_cmd.type = QED_FILTER_TYPE_MCAST; + filter_cmd.filter.mcast.type = opcode; + filter_cmd.filter.mcast.num = num_macs; + + for (i = 0; i < num_macs; i++, mac += ETH_ALEN) + ether_addr_copy(filter_cmd.filter.mcast.mac[i], mac); + + return edev->ops->filter_config(edev->cdev, &filter_cmd); +} + enum qede_unload_mode { QEDE_UNLOAD_NORMAL, }; @@ -2046,6 +2103,9 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode) DP_INFO(edev, "Starting qede unload\n"); + mutex_lock(&edev->qede_lock); + edev->state = QEDE_STATE_CLOSED; + /* Close OS Tx */ netif_tx_disable(edev->ndev); netif_carrier_off(edev->ndev); @@ -2120,6 +2180,9 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode) /* Add primary mac and set Rx filters */ ether_addr_copy(edev->primary_mac, edev->ndev->dev_addr); + mutex_lock(&edev->qede_lock); + edev->state = QEDE_STATE_OPEN; + mutex_unlock(&edev->qede_lock); DP_INFO(edev, "Ending successfully qede load\n"); return 0; @@ -2159,3 +2222,181 @@ static int qede_close(struct net_device *ndev) return 0; } + +static int qede_set_mac_addr(struct net_device *ndev, void *p) +{ + struct qede_dev *edev = netdev_priv(ndev); + struct sockaddr *addr = p; + int rc; + + ASSERT_RTNL(); /* @@@TBD To be removed */ + + DP_INFO(edev, "Set_mac_addr called\n"); + + if (!is_valid_ether_addr(addr->sa_data)) { + DP_NOTICE(edev, "The MAC address is not valid\n"); + return -EFAULT; + } + + ether_addr_copy(ndev->dev_addr, addr->sa_data); + + if (!netif_running(ndev)) { + DP_NOTICE(edev, "The device is currently down\n"); + return 0; + } + + /* Remove the previous primary mac */ + rc = qede_set_ucast_rx_mac(edev, QED_FILTER_XCAST_TYPE_DEL, + edev->primary_mac); + if (rc) + return rc; + + /* Add MAC filter according to the new unicast HW MAC address */ + ether_addr_copy(edev->primary_mac, ndev->dev_addr); + return qede_set_ucast_rx_mac(edev, QED_FILTER_XCAST_TYPE_ADD, + edev->primary_mac); +} + +static int +qede_configure_mcast_filtering(struct net_device *ndev, + enum qed_filter_rx_mode_type *accept_flags) +{ + struct qede_dev *edev = netdev_priv(ndev); + unsigned char *mc_macs, *temp; + struct netdev_hw_addr *ha; + int rc = 0, mc_count; + size_t size; + + size = 64 * ETH_ALEN; + + mc_macs = kzalloc(size, GFP_KERNEL); + if (!mc_macs) { + DP_NOTICE(edev, + "Failed to allocate memory for multicast MACs\n"); + rc = -ENOMEM; + goto exit; + } + + temp = mc_macs; + + /* Remove all previously configured MAC filters */ + rc = qede_set_mcast_rx_mac(edev, QED_FILTER_XCAST_TYPE_DEL, + mc_macs, 1); + if (rc) + goto exit; + + netif_addr_lock_bh(ndev); + + mc_count = netdev_mc_count(ndev); + if (mc_count < 64) { + netdev_for_each_mc_addr(ha, ndev) { + ether_addr_copy(temp, ha->addr); + temp += ETH_ALEN; + } + } + + netif_addr_unlock_bh(ndev); + + /* Check for all multicast @@@TBD resource allocation */ + if ((ndev->flags & IFF_ALLMULTI) || + (mc_count > 64)) { + if (*accept_flags == QED_FILTER_RX_MODE_TYPE_REGULAR) + *accept_flags = QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC; + } else { + /* Add all multicast MAC filters */ + rc = qede_set_mcast_rx_mac(edev, QED_FILTER_XCAST_TYPE_ADD, + mc_macs, mc_count); + } + +exit: + kfree(mc_macs); + return rc; +} + +static void qede_set_rx_mode(struct net_device *ndev) +{ + struct qede_dev *edev = netdev_priv(ndev); + + DP_INFO(edev, "qede_set_rx_mode called\n"); + + if (edev->state != QEDE_STATE_OPEN) { + DP_INFO(edev, + "qede_set_rx_mode called while interface is down\n"); + } else { + set_bit(QEDE_SP_RX_MODE, &edev->sp_flags); + schedule_delayed_work(&edev->sp_task, 0); + } +} + +/* Must be called with qede_lock held */ +static void qede_config_rx_mode(struct net_device *ndev) +{ + enum qed_filter_rx_mode_type accept_flags = QED_FILTER_TYPE_UCAST; + struct qede_dev *edev = netdev_priv(ndev); + struct qed_filter_params rx_mode; + unsigned char *uc_macs, *temp; + struct netdev_hw_addr *ha; + int rc, uc_count; + size_t size; + + netif_addr_lock_bh(ndev); + + uc_count = netdev_uc_count(ndev); + size = uc_count * ETH_ALEN; + + uc_macs = kzalloc(size, GFP_ATOMIC); + if (!uc_macs) { + DP_NOTICE(edev, "Failed to allocate memory for unicast MACs\n"); + netif_addr_unlock_bh(ndev); + return; + } + + temp = uc_macs; + netdev_for_each_uc_addr(ha, ndev) { + ether_addr_copy(temp, ha->addr); + temp += ETH_ALEN; + } + + netif_addr_unlock_bh(ndev); + + /* Configure the struct for the Rx mode */ + memset(&rx_mode, 0, sizeof(struct qed_filter_params)); + rx_mode.type = QED_FILTER_TYPE_RX_MODE; + + /* Remove all previous unicast secondary macs and multicast macs + * (configrue / leave the primary mac) + */ + rc = qede_set_ucast_rx_mac(edev, QED_FILTER_XCAST_TYPE_REPLACE, + edev->primary_mac); + if (rc) + goto out; + + /* Check for promiscuous */ + if ((ndev->flags & IFF_PROMISC) || + (uc_count > 15)) { /* @@@TBD resource allocation - 1 */ + accept_flags = QED_FILTER_RX_MODE_TYPE_PROMISC; + } else { + /* Add MAC filters according to the unicast secondary macs */ + int i; + + temp = uc_macs; + for (i = 0; i < uc_count; i++) { + rc = qede_set_ucast_rx_mac(edev, + QED_FILTER_XCAST_TYPE_ADD, + temp); + if (rc) + goto out; + + temp += ETH_ALEN; + } + + rc = qede_configure_mcast_filtering(ndev, &accept_flags); + if (rc) + goto out; + } + + rx_mode.filter.accept_flags = accept_flags; + edev->ops->filter_config(edev->cdev, &rx_mode); +out: + kfree(uc_macs); +} -- cgit v1.2.3 From cc875c2e4f34e86c2f562f18b6e917cfcc560bcb Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Mon, 26 Oct 2015 11:02:31 +0200 Subject: qed: Add link support Physical link is handled by the management Firmware. This patch lays the infrastructure for attention handling in the driver, as link change notifications arrive via async. attentions, as well the handling of such notifications. This patch also extends the API with the protocol drivers by adding registered callbacks which the protocol driver passes to qed in order to be notified of async. events originating from the FW/HW. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 20 ++ drivers/net/ethernet/qlogic/qed/qed_dev.c | 106 ++++++++- drivers/net/ethernet/qlogic/qed/qed_int.c | 336 ++++++++++++++++++++++++++++- drivers/net/ethernet/qlogic/qed/qed_l2.c | 9 + drivers/net/ethernet/qlogic/qed/qed_main.c | 211 ++++++++++++++++++ drivers/net/ethernet/qlogic/qed/qed_mcp.c | 295 +++++++++++++++++++++++++ drivers/net/ethernet/qlogic/qed/qed_mcp.h | 126 ++++++++++- 7 files changed, 1098 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index e03371d3e622..ca6cc8a7fc64 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -108,6 +108,18 @@ enum QED_FEATURE { QED_MAX_FEATURES, }; +enum QED_PORT_MODE { + QED_PORT_MODE_DE_2X40G, + QED_PORT_MODE_DE_2X50G, + QED_PORT_MODE_DE_1X100G, + QED_PORT_MODE_DE_4X10G_F, + QED_PORT_MODE_DE_4X10G_E, + QED_PORT_MODE_DE_4X20G, + QED_PORT_MODE_DE_1X40G, + QED_PORT_MODE_DE_2X25G, + QED_PORT_MODE_DE_1X25G +}; + struct qed_hw_info { /* PCI personality */ enum qed_pci_personality personality; @@ -404,6 +416,13 @@ struct qed_dev { u8 protocol; #define IS_QED_ETH_IF(cdev) ((cdev)->protocol == QED_PROTOCOL_ETH) + /* Callbacks to protocol driver */ + union { + struct qed_common_cb_ops *common; + struct qed_eth_cb_ops *eth; + } protocol_ops; + void *ops_cookie; + const struct firmware *firmware; }; @@ -453,6 +472,7 @@ static inline u8 qed_concrete_to_sw_fid(struct qed_dev *cdev, /* Prototypes */ int qed_fill_dev_info(struct qed_dev *cdev, struct qed_dev_info *dev_info); +void qed_link_update(struct qed_hwfn *hwfn); u32 qed_unzip_data(struct qed_hwfn *p_hwfn, u32 input_len, u8 *input_buf, u32 max_size, u8 *unzip_buf); diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 3d1bdbf9ade1..7fd3d78d94f1 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -1039,8 +1039,9 @@ static void qed_hw_get_resc(struct qed_hwfn *p_hwfn) static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { - u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, nvm_cfg_addr; - u32 val; + u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, core_cfg; + u32 port_cfg_addr, link_temp, val, nvm_cfg_addr; + struct qed_mcp_link_params *link; /* Read global nvm_cfg address */ nvm_cfg_addr = qed_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0); @@ -1060,6 +1061,48 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, offsetof(struct nvm_cfg1_glob, pci_id); p_hwfn->hw_info.vendor_id = qed_rd(p_hwfn, p_ptt, addr) & NVM_CFG1_GLOB_VENDOR_ID_MASK; + + addr = MCP_REG_SCRATCH + nvm_cfg1_offset + + offsetof(struct nvm_cfg1, glob) + + offsetof(struct nvm_cfg1_glob, core_cfg); + + core_cfg = qed_rd(p_hwfn, p_ptt, addr); + + switch ((core_cfg & NVM_CFG1_GLOB_NETWORK_PORT_MODE_MASK) >> + NVM_CFG1_GLOB_NETWORK_PORT_MODE_OFFSET) { + case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X40G: + p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X40G; + break; + case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X50G: + p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X50G; + break; + case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X100G: + p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X100G; + break; + case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X10G_F: + p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X10G_F; + break; + case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X10G_E: + p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X10G_E; + break; + case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_4X20G: + p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_4X20G; + break; + case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X40G: + p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X40G; + break; + case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_2X25G: + p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_2X25G; + break; + case NVM_CFG1_GLOB_NETWORK_PORT_MODE_DE_1X25G: + p_hwfn->hw_info.port_mode = QED_PORT_MODE_DE_1X25G; + break; + default: + DP_NOTICE(p_hwfn, "Unknown port mode in 0x%08x\n", + core_cfg); + break; + } + addr = MCP_REG_SCRATCH + nvm_cfg1_offset + offsetof(struct nvm_cfg1, func[MCP_PF_ID(p_hwfn)]) + offsetof(struct nvm_cfg1_func, device_id); @@ -1075,6 +1118,65 @@ static int qed_hw_get_nvm_info(struct qed_hwfn *p_hwfn, NVM_CFG1_FUNC_VENDOR_DEVICE_ID_OFFSET; } + /* Read default link configuration */ + link = &p_hwfn->mcp_info->link_input; + port_cfg_addr = MCP_REG_SCRATCH + nvm_cfg1_offset + + offsetof(struct nvm_cfg1, port[MFW_PORT(p_hwfn)]); + link_temp = qed_rd(p_hwfn, p_ptt, + port_cfg_addr + + offsetof(struct nvm_cfg1_port, speed_cap_mask)); + link->speed.advertised_speeds = + link_temp & NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_MASK; + + p_hwfn->mcp_info->link_capabilities.speed_capabilities = + link->speed.advertised_speeds; + + link_temp = qed_rd(p_hwfn, p_ptt, + port_cfg_addr + + offsetof(struct nvm_cfg1_port, link_settings)); + switch ((link_temp & NVM_CFG1_PORT_DRV_LINK_SPEED_MASK) >> + NVM_CFG1_PORT_DRV_LINK_SPEED_OFFSET) { + case NVM_CFG1_PORT_DRV_LINK_SPEED_AUTONEG: + link->speed.autoneg = true; + break; + case NVM_CFG1_PORT_DRV_LINK_SPEED_1G: + link->speed.forced_speed = 1000; + break; + case NVM_CFG1_PORT_DRV_LINK_SPEED_10G: + link->speed.forced_speed = 10000; + break; + case NVM_CFG1_PORT_DRV_LINK_SPEED_25G: + link->speed.forced_speed = 25000; + break; + case NVM_CFG1_PORT_DRV_LINK_SPEED_40G: + link->speed.forced_speed = 40000; + break; + case NVM_CFG1_PORT_DRV_LINK_SPEED_50G: + link->speed.forced_speed = 50000; + break; + case NVM_CFG1_PORT_DRV_LINK_SPEED_100G: + link->speed.forced_speed = 100000; + break; + default: + DP_NOTICE(p_hwfn, "Unknown Speed in 0x%08x\n", + link_temp); + } + + link_temp &= NVM_CFG1_PORT_DRV_FLOW_CONTROL_MASK; + link_temp >>= NVM_CFG1_PORT_DRV_FLOW_CONTROL_OFFSET; + link->pause.autoneg = !!(link_temp & + NVM_CFG1_PORT_DRV_FLOW_CONTROL_AUTONEG); + link->pause.forced_rx = !!(link_temp & + NVM_CFG1_PORT_DRV_FLOW_CONTROL_RX); + link->pause.forced_tx = !!(link_temp & + NVM_CFG1_PORT_DRV_FLOW_CONTROL_TX); + link->loopback_mode = 0; + + DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, + "Read default link: Speed 0x%08x, Adv. Speed 0x%08x, AN: 0x%02x, PAUSE AN: 0x%02x\n", + link->speed.forced_speed, link->speed.advertised_speeds, + link->speed.autoneg, link->pause.autoneg); + /* Read Multi-function information from shmem */ addr = MCP_REG_SCRATCH + nvm_cfg1_offset + offsetof(struct nvm_cfg1, glob) + diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c index 37d926a5fae5..2e399b6137a2 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.c +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c @@ -39,10 +39,214 @@ struct qed_sb_sp_info { struct qed_pi_info pi_info_arr[PIS_PER_SB]; }; +#define SB_ATTN_ALIGNED_SIZE(p_hwfn) \ + ALIGNED_TYPE_SIZE(struct atten_status_block, p_hwfn) + +#define ATTN_STATE_BITS (0xfff) +#define ATTN_BITS_MASKABLE (0x3ff) +struct qed_sb_attn_info { + /* Virtual & Physical address of the SB */ + struct atten_status_block *sb_attn; + dma_addr_t sb_phys; + + /* Last seen running index */ + u16 index; + + /* Previously asserted attentions, which are still unasserted */ + u16 known_attn; + + /* Cleanup address for the link's general hw attention */ + u32 mfw_attn_addr; +}; + +static inline u16 qed_attn_update_idx(struct qed_hwfn *p_hwfn, + struct qed_sb_attn_info *p_sb_desc) +{ + u16 rc = 0; + u16 index; + + /* Make certain HW write took affect */ + mmiowb(); + + index = le16_to_cpu(p_sb_desc->sb_attn->sb_index); + if (p_sb_desc->index != index) { + p_sb_desc->index = index; + rc = QED_SB_ATT_IDX; + } + + /* Make certain we got a consistent view with HW */ + mmiowb(); + + return rc; +} + +/** + * @brief qed_int_assertion - handles asserted attention bits + * + * @param p_hwfn + * @param asserted_bits newly asserted bits + * @return int + */ +static int qed_int_assertion(struct qed_hwfn *p_hwfn, + u16 asserted_bits) +{ + struct qed_sb_attn_info *sb_attn_sw = p_hwfn->p_sb_attn; + u32 igu_mask; + + /* Mask the source of the attention in the IGU */ + igu_mask = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + IGU_REG_ATTENTION_ENABLE); + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "IGU mask: 0x%08x --> 0x%08x\n", + igu_mask, igu_mask & ~(asserted_bits & ATTN_BITS_MASKABLE)); + igu_mask &= ~(asserted_bits & ATTN_BITS_MASKABLE); + qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, IGU_REG_ATTENTION_ENABLE, igu_mask); + + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, + "inner known ATTN state: 0x%04x --> 0x%04x\n", + sb_attn_sw->known_attn, + sb_attn_sw->known_attn | asserted_bits); + sb_attn_sw->known_attn |= asserted_bits; + + /* Handle MCP events */ + if (asserted_bits & 0x100) { + qed_mcp_handle_events(p_hwfn, p_hwfn->p_dpc_ptt); + /* Clean the MCP attention */ + qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, + sb_attn_sw->mfw_attn_addr, 0); + } + + DIRECT_REG_WR((u8 __iomem *)p_hwfn->regview + + GTT_BAR0_MAP_REG_IGU_CMD + + ((IGU_CMD_ATTN_BIT_SET_UPPER - + IGU_CMD_INT_ACK_BASE) << 3), + (u32)asserted_bits); + + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "set cmd IGU: 0x%04x\n", + asserted_bits); + + return 0; +} + +/** + * @brief - handles deassertion of previously asserted attentions. + * + * @param p_hwfn + * @param deasserted_bits - newly deasserted bits + * @return int + * + */ +static int qed_int_deassertion(struct qed_hwfn *p_hwfn, + u16 deasserted_bits) +{ + struct qed_sb_attn_info *sb_attn_sw = p_hwfn->p_sb_attn; + u32 aeu_mask; + + if (deasserted_bits != 0x100) + DP_ERR(p_hwfn, "Unexpected - non-link deassertion\n"); + + /* Clear IGU indication for the deasserted bits */ + DIRECT_REG_WR((u8 __iomem *)p_hwfn->regview + + GTT_BAR0_MAP_REG_IGU_CMD + + ((IGU_CMD_ATTN_BIT_CLR_UPPER - + IGU_CMD_INT_ACK_BASE) << 3), + ~((u32)deasserted_bits)); + + /* Unmask deasserted attentions in IGU */ + aeu_mask = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, + IGU_REG_ATTENTION_ENABLE); + aeu_mask |= (deasserted_bits & ATTN_BITS_MASKABLE); + qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, IGU_REG_ATTENTION_ENABLE, aeu_mask); + + /* Clear deassertion from inner state */ + sb_attn_sw->known_attn &= ~deasserted_bits; + + return 0; +} + +static int qed_int_attentions(struct qed_hwfn *p_hwfn) +{ + struct qed_sb_attn_info *p_sb_attn_sw = p_hwfn->p_sb_attn; + struct atten_status_block *p_sb_attn = p_sb_attn_sw->sb_attn; + u32 attn_bits = 0, attn_acks = 0; + u16 asserted_bits, deasserted_bits; + __le16 index; + int rc = 0; + + /* Read current attention bits/acks - safeguard against attentions + * by guaranting work on a synchronized timeframe + */ + do { + index = p_sb_attn->sb_index; + attn_bits = le32_to_cpu(p_sb_attn->atten_bits); + attn_acks = le32_to_cpu(p_sb_attn->atten_ack); + } while (index != p_sb_attn->sb_index); + p_sb_attn->sb_index = index; + + /* Attention / Deassertion are meaningful (and in correct state) + * only when they differ and consistent with known state - deassertion + * when previous attention & current ack, and assertion when current + * attention with no previous attention + */ + asserted_bits = (attn_bits & ~attn_acks & ATTN_STATE_BITS) & + ~p_sb_attn_sw->known_attn; + deasserted_bits = (~attn_bits & attn_acks & ATTN_STATE_BITS) & + p_sb_attn_sw->known_attn; + + if ((asserted_bits & ~0x100) || (deasserted_bits & ~0x100)) { + DP_INFO(p_hwfn, + "Attention: Index: 0x%04x, Bits: 0x%08x, Acks: 0x%08x, asserted: 0x%04x, De-asserted 0x%04x [Prev. known: 0x%04x]\n", + index, attn_bits, attn_acks, asserted_bits, + deasserted_bits, p_sb_attn_sw->known_attn); + } else if (asserted_bits == 0x100) { + DP_INFO(p_hwfn, + "MFW indication via attention\n"); + } else { + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, + "MFW indication [deassertion]\n"); + } + + if (asserted_bits) { + rc = qed_int_assertion(p_hwfn, asserted_bits); + if (rc) + return rc; + } + + if (deasserted_bits) { + rc = qed_int_deassertion(p_hwfn, deasserted_bits); + if (rc) + return rc; + } + + return rc; +} + +static void qed_sb_ack_attn(struct qed_hwfn *p_hwfn, + void __iomem *igu_addr, + u32 ack_cons) +{ + struct igu_prod_cons_update igu_ack = { 0 }; + + igu_ack.sb_id_and_flags = + ((ack_cons << IGU_PROD_CONS_UPDATE_SB_INDEX_SHIFT) | + (1 << IGU_PROD_CONS_UPDATE_UPDATE_FLAG_SHIFT) | + (IGU_INT_NOP << IGU_PROD_CONS_UPDATE_ENABLE_INT_SHIFT) | + (IGU_SEG_ACCESS_ATTN << + IGU_PROD_CONS_UPDATE_SEGMENT_ACCESS_SHIFT)); + + DIRECT_REG_WR(igu_addr, igu_ack.sb_id_and_flags); + + /* Both segments (interrupts & acks) are written to same place address; + * Need to guarantee all commands will be received (in-order) by HW. + */ + mmiowb(); + barrier(); +} + void qed_int_sp_dpc(unsigned long hwfn_cookie) { struct qed_hwfn *p_hwfn = (struct qed_hwfn *)hwfn_cookie; struct qed_pi_info *pi_info = NULL; + struct qed_sb_attn_info *sb_attn; struct qed_sb_info *sb_info; int arr_size; u16 rc = 0; @@ -65,6 +269,12 @@ void qed_int_sp_dpc(unsigned long hwfn_cookie) return; } + if (!p_hwfn->p_sb_attn) { + DP_ERR(p_hwfn->cdev, "DPC called - no p_sb_attn"); + return; + } + sb_attn = p_hwfn->p_sb_attn; + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "DPC Called! (hwfn %p %d)\n", p_hwfn, p_hwfn->my_id); @@ -87,6 +297,19 @@ void qed_int_sp_dpc(unsigned long hwfn_cookie) tmp_index, sb_info->sb_ack); } + if (!sb_attn || !sb_attn->sb_attn) { + DP_ERR( + p_hwfn->cdev, + "Attentions Status block is NULL - cannot check for new attentions!\n"); + } else { + u16 tmp_index = sb_attn->index; + + rc |= qed_attn_update_idx(p_hwfn, sb_attn); + DP_VERBOSE(p_hwfn->cdev, NETIF_MSG_INTR, + "Attention indices: 0x%08x --> 0x%08x\n", + tmp_index, sb_attn->index); + } + /* Check if we expect interrupts at this time. if not just ack them */ if (!(rc & QED_SB_EVENT_MASK)) { qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); @@ -100,6 +323,9 @@ void qed_int_sp_dpc(unsigned long hwfn_cookie) return; } + if (rc & QED_SB_ATT_IDX) + qed_int_attentions(p_hwfn); + if (rc & QED_SB_IDX) { int pi; @@ -111,9 +337,97 @@ void qed_int_sp_dpc(unsigned long hwfn_cookie) } } + if (sb_attn && (rc & QED_SB_ATT_IDX)) + /* This should be done before the interrupts are enabled, + * since otherwise a new attention will be generated. + */ + qed_sb_ack_attn(p_hwfn, sb_info->igu_addr, sb_attn->index); + qed_sb_ack(sb_info, IGU_INT_ENABLE, 1); } +static void qed_int_sb_attn_free(struct qed_hwfn *p_hwfn) +{ + struct qed_dev *cdev = p_hwfn->cdev; + struct qed_sb_attn_info *p_sb = p_hwfn->p_sb_attn; + + if (p_sb) { + if (p_sb->sb_attn) + dma_free_coherent(&cdev->pdev->dev, + SB_ATTN_ALIGNED_SIZE(p_hwfn), + p_sb->sb_attn, + p_sb->sb_phys); + kfree(p_sb); + } +} + +static void qed_int_sb_attn_setup(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + struct qed_sb_attn_info *sb_info = p_hwfn->p_sb_attn; + + memset(sb_info->sb_attn, 0, sizeof(*sb_info->sb_attn)); + + sb_info->index = 0; + sb_info->known_attn = 0; + + /* Configure Attention Status Block in IGU */ + qed_wr(p_hwfn, p_ptt, IGU_REG_ATTN_MSG_ADDR_L, + lower_32_bits(p_hwfn->p_sb_attn->sb_phys)); + qed_wr(p_hwfn, p_ptt, IGU_REG_ATTN_MSG_ADDR_H, + upper_32_bits(p_hwfn->p_sb_attn->sb_phys)); +} + +static void qed_int_sb_attn_init(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + void *sb_virt_addr, + dma_addr_t sb_phy_addr) +{ + struct qed_sb_attn_info *sb_info = p_hwfn->p_sb_attn; + + sb_info->sb_attn = sb_virt_addr; + sb_info->sb_phys = sb_phy_addr; + + /* Set the address of cleanup for the mcp attention */ + sb_info->mfw_attn_addr = (p_hwfn->rel_pf_id << 3) + + MISC_REG_AEU_GENERAL_ATTN_0; + + qed_int_sb_attn_setup(p_hwfn, p_ptt); +} + +static int qed_int_sb_attn_alloc(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + struct qed_dev *cdev = p_hwfn->cdev; + struct qed_sb_attn_info *p_sb; + void *p_virt; + dma_addr_t p_phys = 0; + + /* SB struct */ + p_sb = kmalloc(sizeof(*p_sb), GFP_ATOMIC); + if (!p_sb) { + DP_NOTICE(cdev, "Failed to allocate `struct qed_sb_attn_info'\n"); + return -ENOMEM; + } + + /* SB ring */ + p_virt = dma_alloc_coherent(&cdev->pdev->dev, + SB_ATTN_ALIGNED_SIZE(p_hwfn), + &p_phys, GFP_KERNEL); + + if (!p_virt) { + DP_NOTICE(cdev, "Failed to allocate status block (attentions)\n"); + kfree(p_sb); + return -ENOMEM; + } + + /* Attention setup */ + p_hwfn->p_sb_attn = p_sb; + qed_int_sb_attn_init(p_hwfn, p_ptt, p_virt, p_phys); + + return 0; +} + /* coalescing timeout = timeset << (timer_res + 1) */ #define QED_CAU_DEF_RX_USECS 24 #define QED_CAU_DEF_TX_USECS 48 @@ -394,6 +708,12 @@ static void qed_int_sp_sb_setup(struct qed_hwfn *p_hwfn, else DP_NOTICE(p_hwfn->cdev, "Failed to setup Slow path status block - NULL pointer\n"); + + if (p_hwfn->p_sb_attn) + qed_int_sb_attn_setup(p_hwfn, p_ptt); + else + DP_NOTICE(p_hwfn->cdev, + "Failed to setup attentions status block - NULL pointer\n"); } int qed_int_register_cb(struct qed_hwfn *p_hwfn, @@ -444,7 +764,7 @@ void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, enum qed_int_mode int_mode) { - u32 igu_pf_conf = IGU_PF_CONF_FUNC_EN; + u32 igu_pf_conf = IGU_PF_CONF_FUNC_EN | IGU_PF_CONF_ATTN_BIT_EN; p_hwfn->cdev->int_mode = int_mode; switch (p_hwfn->cdev->int_mode) { @@ -484,8 +804,15 @@ void qed_int_igu_enable(struct qed_hwfn *p_hwfn, /* Enable interrupt Generation */ qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode); + /* Configure AEU signal change to produce attentions for link */ + qed_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0xfff); + qed_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0xfff); + /* Flush the writes to IGU */ mmiowb(); + + /* Unmask AEU signals toward IGU */ + qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_MASK_ATTN_IGU, 0xff); } void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn, @@ -770,13 +1097,18 @@ int qed_int_alloc(struct qed_hwfn *p_hwfn, DP_ERR(p_hwfn->cdev, "Failed to allocate sp sb mem\n"); return rc; } - + rc = qed_int_sb_attn_alloc(p_hwfn, p_ptt); + if (rc) { + DP_ERR(p_hwfn->cdev, "Failed to allocate sb attn mem\n"); + return rc; + } return rc; } void qed_int_free(struct qed_hwfn *p_hwfn) { qed_int_sp_sb_free(p_hwfn); + qed_int_sb_attn_free(p_hwfn); qed_int_sp_dpc_free(p_hwfn); } diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 2772573593a4..7049e4139d3c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -1259,6 +1259,14 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev, return 0; } +static void qed_register_eth_ops(struct qed_dev *cdev, + struct qed_eth_cb_ops *ops, + void *cookie) +{ + cdev->protocol_ops.eth = ops; + cdev->ops_cookie = cookie; +} + static int qed_start_vport(struct qed_dev *cdev, u8 vport_id, u16 mtu, @@ -1661,6 +1669,7 @@ static int qed_fp_cqe_completion(struct qed_dev *dev, static const struct qed_eth_ops qed_eth_ops_pass = { .common = &qed_common_ops_pass, .fill_dev_info = &qed_fill_eth_dev_info, + .register_ops = &qed_register_eth_ops, .vport_start = &qed_start_vport, .vport_stop = &qed_stop_vport, .vport_update = &qed_update_vport, diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 1659418eec88..947c7af72b25 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -904,6 +904,215 @@ static u32 qed_sb_release(struct qed_dev *cdev, return rc; } +static int qed_set_link(struct qed_dev *cdev, + struct qed_link_params *params) +{ + struct qed_hwfn *hwfn; + struct qed_mcp_link_params *link_params; + struct qed_ptt *ptt; + int rc; + + if (!cdev) + return -ENODEV; + + /* The link should be set only once per PF */ + hwfn = &cdev->hwfns[0]; + + ptt = qed_ptt_acquire(hwfn); + if (!ptt) + return -EBUSY; + + link_params = qed_mcp_get_link_params(hwfn); + if (params->override_flags & QED_LINK_OVERRIDE_SPEED_AUTONEG) + link_params->speed.autoneg = params->autoneg; + if (params->override_flags & QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS) { + link_params->speed.advertised_speeds = 0; + if ((params->adv_speeds & SUPPORTED_1000baseT_Half) || + (params->adv_speeds & SUPPORTED_1000baseT_Full)) + link_params->speed.advertised_speeds |= + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G; + if (params->adv_speeds & SUPPORTED_10000baseKR_Full) + link_params->speed.advertised_speeds |= + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G; + if (params->adv_speeds & SUPPORTED_40000baseLR4_Full) + link_params->speed.advertised_speeds |= + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G; + if (params->adv_speeds & 0) + link_params->speed.advertised_speeds |= + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G; + if (params->adv_speeds & 0) + link_params->speed.advertised_speeds |= + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_100G; + } + if (params->override_flags & QED_LINK_OVERRIDE_SPEED_FORCED_SPEED) + link_params->speed.forced_speed = params->forced_speed; + + rc = qed_mcp_set_link(hwfn, ptt, params->link_up); + + qed_ptt_release(hwfn, ptt); + + return rc; +} + +static int qed_get_port_type(u32 media_type) +{ + int port_type; + + switch (media_type) { + case MEDIA_SFPP_10G_FIBER: + case MEDIA_SFP_1G_FIBER: + case MEDIA_XFP_FIBER: + case MEDIA_KR: + port_type = PORT_FIBRE; + break; + case MEDIA_DA_TWINAX: + port_type = PORT_DA; + break; + case MEDIA_BASE_T: + port_type = PORT_TP; + break; + case MEDIA_NOT_PRESENT: + port_type = PORT_NONE; + break; + case MEDIA_UNSPECIFIED: + default: + port_type = PORT_OTHER; + break; + } + return port_type; +} + +static void qed_fill_link(struct qed_hwfn *hwfn, + struct qed_link_output *if_link) +{ + struct qed_mcp_link_params params; + struct qed_mcp_link_state link; + struct qed_mcp_link_capabilities link_caps; + u32 media_type; + + memset(if_link, 0, sizeof(*if_link)); + + /* Prepare source inputs */ + memcpy(¶ms, qed_mcp_get_link_params(hwfn), sizeof(params)); + memcpy(&link, qed_mcp_get_link_state(hwfn), sizeof(link)); + memcpy(&link_caps, qed_mcp_get_link_capabilities(hwfn), + sizeof(link_caps)); + + /* Set the link parameters to pass to protocol driver */ + if (link.link_up) + if_link->link_up = true; + + /* TODO - at the moment assume supported and advertised speed equal */ + if_link->supported_caps = SUPPORTED_FIBRE; + if (params.speed.autoneg) + if_link->supported_caps |= SUPPORTED_Autoneg; + if (params.pause.autoneg || + (params.pause.forced_rx && params.pause.forced_tx)) + if_link->supported_caps |= SUPPORTED_Asym_Pause; + if (params.pause.autoneg || params.pause.forced_rx || + params.pause.forced_tx) + if_link->supported_caps |= SUPPORTED_Pause; + + if_link->advertised_caps = if_link->supported_caps; + if (params.speed.advertised_speeds & + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) + if_link->advertised_caps |= SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full; + if (params.speed.advertised_speeds & + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) + if_link->advertised_caps |= SUPPORTED_10000baseKR_Full; + if (params.speed.advertised_speeds & + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) + if_link->advertised_caps |= SUPPORTED_40000baseLR4_Full; + if (params.speed.advertised_speeds & + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) + if_link->advertised_caps |= 0; + if (params.speed.advertised_speeds & + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_100G) + if_link->advertised_caps |= 0; + + if (link_caps.speed_capabilities & + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) + if_link->supported_caps |= SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full; + if (link_caps.speed_capabilities & + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) + if_link->supported_caps |= SUPPORTED_10000baseKR_Full; + if (link_caps.speed_capabilities & + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_40G) + if_link->supported_caps |= SUPPORTED_40000baseLR4_Full; + if (link_caps.speed_capabilities & + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_50G) + if_link->supported_caps |= 0; + if (link_caps.speed_capabilities & + NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_100G) + if_link->supported_caps |= 0; + + if (link.link_up) + if_link->speed = link.speed; + + /* TODO - fill duplex properly */ + if_link->duplex = DUPLEX_FULL; + qed_mcp_get_media_type(hwfn->cdev, &media_type); + if_link->port = qed_get_port_type(media_type); + + if_link->autoneg = params.speed.autoneg; + + if (params.pause.autoneg) + if_link->pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE; + if (params.pause.forced_rx) + if_link->pause_config |= QED_LINK_PAUSE_RX_ENABLE; + if (params.pause.forced_tx) + if_link->pause_config |= QED_LINK_PAUSE_TX_ENABLE; + + /* Link partner capabilities */ + if (link.partner_adv_speed & + QED_LINK_PARTNER_SPEED_1G_HD) + if_link->lp_caps |= SUPPORTED_1000baseT_Half; + if (link.partner_adv_speed & + QED_LINK_PARTNER_SPEED_1G_FD) + if_link->lp_caps |= SUPPORTED_1000baseT_Full; + if (link.partner_adv_speed & + QED_LINK_PARTNER_SPEED_10G) + if_link->lp_caps |= SUPPORTED_10000baseKR_Full; + if (link.partner_adv_speed & + QED_LINK_PARTNER_SPEED_40G) + if_link->lp_caps |= SUPPORTED_40000baseLR4_Full; + if (link.partner_adv_speed & + QED_LINK_PARTNER_SPEED_50G) + if_link->lp_caps |= 0; + if (link.partner_adv_speed & + QED_LINK_PARTNER_SPEED_100G) + if_link->lp_caps |= 0; + + if (link.an_complete) + if_link->lp_caps |= SUPPORTED_Autoneg; + + if (link.partner_adv_pause) + if_link->lp_caps |= SUPPORTED_Pause; + if (link.partner_adv_pause == QED_LINK_PARTNER_ASYMMETRIC_PAUSE || + link.partner_adv_pause == QED_LINK_PARTNER_BOTH_PAUSE) + if_link->lp_caps |= SUPPORTED_Asym_Pause; +} + +static void qed_get_current_link(struct qed_dev *cdev, + struct qed_link_output *if_link) +{ + qed_fill_link(&cdev->hwfns[0], if_link); +} + +void qed_link_update(struct qed_hwfn *hwfn) +{ + void *cookie = hwfn->cdev->ops_cookie; + struct qed_common_cb_ops *op = hwfn->cdev->protocol_ops.common; + struct qed_link_output if_link; + + qed_fill_link(hwfn, &if_link); + + if (IS_LEAD_HWFN(hwfn) && cookie) + op->link_update(cookie, &if_link); +} + static int qed_drain(struct qed_dev *cdev) { struct qed_hwfn *hwfn; @@ -940,6 +1149,8 @@ const struct qed_common_ops qed_common_ops_pass = { .sb_release = &qed_sb_release, .simd_handler_config = &qed_simd_handler_config, .simd_handler_clean = &qed_simd_handler_clean, + .set_link = &qed_set_link, + .get_link = &qed_get_current_link, .drain = &qed_drain, .update_msglvl = &qed_init_dp, .chain_alloc = &qed_chain_alloc, diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 8a5c3849bfe0..20d048cdcb88 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -365,6 +365,252 @@ int qed_mcp_load_req(struct qed_hwfn *p_hwfn, return 0; } +static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + bool b_reset) +{ + struct qed_mcp_link_state *p_link; + u32 status = 0; + + p_link = &p_hwfn->mcp_info->link_output; + memset(p_link, 0, sizeof(*p_link)); + if (!b_reset) { + status = qed_rd(p_hwfn, p_ptt, + p_hwfn->mcp_info->port_addr + + offsetof(struct public_port, link_status)); + DP_VERBOSE(p_hwfn, (NETIF_MSG_LINK | QED_MSG_SP), + "Received link update [0x%08x] from mfw [Addr 0x%x]\n", + status, + (u32)(p_hwfn->mcp_info->port_addr + + offsetof(struct public_port, + link_status))); + } else { + DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, + "Resetting link indications\n"); + return; + } + + p_link->link_up = !!(status & LINK_STATUS_LINK_UP); + + p_link->full_duplex = true; + switch ((status & LINK_STATUS_SPEED_AND_DUPLEX_MASK)) { + case LINK_STATUS_SPEED_AND_DUPLEX_100G: + p_link->speed = 100000; + break; + case LINK_STATUS_SPEED_AND_DUPLEX_50G: + p_link->speed = 50000; + break; + case LINK_STATUS_SPEED_AND_DUPLEX_40G: + p_link->speed = 40000; + break; + case LINK_STATUS_SPEED_AND_DUPLEX_25G: + p_link->speed = 25000; + break; + case LINK_STATUS_SPEED_AND_DUPLEX_20G: + p_link->speed = 20000; + break; + case LINK_STATUS_SPEED_AND_DUPLEX_10G: + p_link->speed = 10000; + break; + case LINK_STATUS_SPEED_AND_DUPLEX_1000THD: + p_link->full_duplex = false; + /* Fall-through */ + case LINK_STATUS_SPEED_AND_DUPLEX_1000TFD: + p_link->speed = 1000; + break; + default: + p_link->speed = 0; + } + + /* Correct speed according to bandwidth allocation */ + if (p_hwfn->mcp_info->func_info.bandwidth_max && p_link->speed) { + p_link->speed = p_link->speed * + p_hwfn->mcp_info->func_info.bandwidth_max / + 100; + qed_init_pf_rl(p_hwfn, p_ptt, p_hwfn->rel_pf_id, + p_link->speed); + DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, + "Configured MAX bandwidth to be %08x Mb/sec\n", + p_link->speed); + } + + p_link->an = !!(status & LINK_STATUS_AUTO_NEGOTIATE_ENABLED); + p_link->an_complete = !!(status & + LINK_STATUS_AUTO_NEGOTIATE_COMPLETE); + p_link->parallel_detection = !!(status & + LINK_STATUS_PARALLEL_DETECTION_USED); + p_link->pfc_enabled = !!(status & LINK_STATUS_PFC_ENABLED); + + p_link->partner_adv_speed |= + (status & LINK_STATUS_LINK_PARTNER_1000TFD_CAPABLE) ? + QED_LINK_PARTNER_SPEED_1G_FD : 0; + p_link->partner_adv_speed |= + (status & LINK_STATUS_LINK_PARTNER_1000THD_CAPABLE) ? + QED_LINK_PARTNER_SPEED_1G_HD : 0; + p_link->partner_adv_speed |= + (status & LINK_STATUS_LINK_PARTNER_10G_CAPABLE) ? + QED_LINK_PARTNER_SPEED_10G : 0; + p_link->partner_adv_speed |= + (status & LINK_STATUS_LINK_PARTNER_20G_CAPABLE) ? + QED_LINK_PARTNER_SPEED_20G : 0; + p_link->partner_adv_speed |= + (status & LINK_STATUS_LINK_PARTNER_40G_CAPABLE) ? + QED_LINK_PARTNER_SPEED_40G : 0; + p_link->partner_adv_speed |= + (status & LINK_STATUS_LINK_PARTNER_50G_CAPABLE) ? + QED_LINK_PARTNER_SPEED_50G : 0; + p_link->partner_adv_speed |= + (status & LINK_STATUS_LINK_PARTNER_100G_CAPABLE) ? + QED_LINK_PARTNER_SPEED_100G : 0; + + p_link->partner_tx_flow_ctrl_en = + !!(status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED); + p_link->partner_rx_flow_ctrl_en = + !!(status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED); + + switch (status & LINK_STATUS_LINK_PARTNER_FLOW_CONTROL_MASK) { + case LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE: + p_link->partner_adv_pause = QED_LINK_PARTNER_SYMMETRIC_PAUSE; + break; + case LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE: + p_link->partner_adv_pause = QED_LINK_PARTNER_ASYMMETRIC_PAUSE; + break; + case LINK_STATUS_LINK_PARTNER_BOTH_PAUSE: + p_link->partner_adv_pause = QED_LINK_PARTNER_BOTH_PAUSE; + break; + default: + p_link->partner_adv_pause = 0; + } + + p_link->sfp_tx_fault = !!(status & LINK_STATUS_SFP_TX_FAULT); + + qed_link_update(p_hwfn); +} + +int qed_mcp_set_link(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + bool b_up) +{ + struct qed_mcp_link_params *params = &p_hwfn->mcp_info->link_input; + u32 param = 0, reply = 0, cmd; + struct pmm_phy_cfg phy_cfg; + int rc = 0; + u32 i; + + if (!qed_mcp_is_init(p_hwfn)) { + DP_NOTICE(p_hwfn, "MFW is not initialized !\n"); + return -EBUSY; + } + + /* Set the shmem configuration according to params */ + memset(&phy_cfg, 0, sizeof(phy_cfg)); + cmd = b_up ? DRV_MSG_CODE_INIT_PHY : DRV_MSG_CODE_LINK_RESET; + if (!params->speed.autoneg) + phy_cfg.speed = params->speed.forced_speed; + phy_cfg.pause |= (params->pause.autoneg) ? PMM_PAUSE_AUTONEG : 0; + phy_cfg.pause |= (params->pause.forced_rx) ? PMM_PAUSE_RX : 0; + phy_cfg.pause |= (params->pause.forced_tx) ? PMM_PAUSE_TX : 0; + phy_cfg.adv_speed = params->speed.advertised_speeds; + phy_cfg.loopback_mode = params->loopback_mode; + + /* Write the requested configuration to shmem */ + for (i = 0; i < sizeof(phy_cfg); i += 4) + qed_wr(p_hwfn, p_ptt, + p_hwfn->mcp_info->drv_mb_addr + + offsetof(struct public_drv_mb, union_data) + i, + ((u32 *)&phy_cfg)[i >> 2]); + + if (b_up) { + DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, + "Configuring Link: Speed 0x%08x, Pause 0x%08x, adv_speed 0x%08x, loopback 0x%08x, features 0x%08x\n", + phy_cfg.speed, + phy_cfg.pause, + phy_cfg.adv_speed, + phy_cfg.loopback_mode, + phy_cfg.feature_config_flags); + } else { + DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, + "Resetting link\n"); + } + + DP_VERBOSE(p_hwfn, QED_MSG_SP, "fw_seq 0x%08x, drv_pulse 0x%x\n", + p_hwfn->mcp_info->drv_mb_seq, + p_hwfn->mcp_info->drv_pulse_seq); + + /* Load Request */ + rc = qed_mcp_cmd(p_hwfn, p_ptt, cmd, 0, &reply, ¶m); + + /* if mcp fails to respond we must abort */ + if (rc) { + DP_ERR(p_hwfn, "MCP response failure, aborting\n"); + return rc; + } + + /* Reset the link status if needed */ + if (!b_up) + qed_mcp_handle_link_change(p_hwfn, p_ptt, true); + + return 0; +} + +int qed_mcp_handle_events(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt) +{ + struct qed_mcp_info *info = p_hwfn->mcp_info; + int rc = 0; + bool found = false; + u16 i; + + DP_VERBOSE(p_hwfn, QED_MSG_SP, "Received message from MFW\n"); + + /* Read Messages from MFW */ + qed_mcp_read_mb(p_hwfn, p_ptt); + + /* Compare current messages to old ones */ + for (i = 0; i < info->mfw_mb_length; i++) { + if (info->mfw_mb_cur[i] == info->mfw_mb_shadow[i]) + continue; + + found = true; + + DP_VERBOSE(p_hwfn, NETIF_MSG_LINK, + "Msg [%d] - old CMD 0x%02x, new CMD 0x%02x\n", + i, info->mfw_mb_shadow[i], info->mfw_mb_cur[i]); + + switch (i) { + case MFW_DRV_MSG_LINK_CHANGE: + qed_mcp_handle_link_change(p_hwfn, p_ptt, false); + break; + default: + DP_NOTICE(p_hwfn, "Unimplemented MFW message %d\n", i); + rc = -EINVAL; + } + } + + /* ACK everything */ + for (i = 0; i < MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length); i++) { + __be32 val = cpu_to_be32(((u32 *)info->mfw_mb_cur)[i]); + + /* MFW expect answer in BE, so we force write in that format */ + qed_wr(p_hwfn, p_ptt, + info->mfw_mb_addr + sizeof(u32) + + MFW_DRV_MSG_MAX_DWORDS(info->mfw_mb_length) * + sizeof(u32) + i * sizeof(u32), + (__force u32)val); + } + + if (!found) { + DP_NOTICE(p_hwfn, + "Received an MFW message indication but no new message!\n"); + rc = -EINVAL; + } + + /* Copy the new mfw messages into the shadow */ + memcpy(info->mfw_mb_shadow, info->mfw_mb_cur, info->mfw_mb_length); + + return rc; +} + int qed_mcp_get_mfw_ver(struct qed_dev *cdev, u32 *p_mfw_ver) { @@ -389,6 +635,31 @@ int qed_mcp_get_mfw_ver(struct qed_dev *cdev, return 0; } +int qed_mcp_get_media_type(struct qed_dev *cdev, + u32 *p_media_type) +{ + struct qed_hwfn *p_hwfn = &cdev->hwfns[0]; + struct qed_ptt *p_ptt; + + if (!qed_mcp_is_init(p_hwfn)) { + DP_NOTICE(p_hwfn, "MFW is not initialized !\n"); + return -EBUSY; + } + + *p_media_type = MEDIA_UNSPECIFIED; + + p_ptt = qed_ptt_acquire(p_hwfn); + if (!p_ptt) + return -EBUSY; + + *p_media_type = qed_rd(p_hwfn, p_ptt, p_hwfn->mcp_info->port_addr + + offsetof(struct public_port, media_type)); + + qed_ptt_release(p_hwfn, p_ptt); + + return 0; +} + static u32 qed_mcp_get_shmem_func(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, struct public_func *p_data, @@ -500,6 +771,30 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn, return 0; } +struct qed_mcp_link_params +*qed_mcp_get_link_params(struct qed_hwfn *p_hwfn) +{ + if (!p_hwfn || !p_hwfn->mcp_info) + return NULL; + return &p_hwfn->mcp_info->link_input; +} + +struct qed_mcp_link_state +*qed_mcp_get_link_state(struct qed_hwfn *p_hwfn) +{ + if (!p_hwfn || !p_hwfn->mcp_info) + return NULL; + return &p_hwfn->mcp_info->link_output; +} + +struct qed_mcp_link_capabilities +*qed_mcp_get_link_capabilities(struct qed_hwfn *p_hwfn) +{ + if (!p_hwfn || !p_hwfn->mcp_info) + return NULL; + return &p_hwfn->mcp_info->link_capabilities; +} + int qed_mcp_drain(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) { diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index 106d78a19937..dbaae586b4a7 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h @@ -15,6 +15,59 @@ #include #include "qed_hsi.h" +struct qed_mcp_link_speed_params { + bool autoneg; + u32 advertised_speeds; /* bitmask of DRV_SPEED_CAPABILITY */ + u32 forced_speed; /* In Mb/s */ +}; + +struct qed_mcp_link_pause_params { + bool autoneg; + bool forced_rx; + bool forced_tx; +}; + +struct qed_mcp_link_params { + struct qed_mcp_link_speed_params speed; + struct qed_mcp_link_pause_params pause; + u32 loopback_mode; +}; + +struct qed_mcp_link_capabilities { + u32 speed_capabilities; +}; + +struct qed_mcp_link_state { + bool link_up; + + u32 speed; /* In Mb/s */ + bool full_duplex; + + bool an; + bool an_complete; + bool parallel_detection; + bool pfc_enabled; + +#define QED_LINK_PARTNER_SPEED_1G_HD BIT(0) +#define QED_LINK_PARTNER_SPEED_1G_FD BIT(1) +#define QED_LINK_PARTNER_SPEED_10G BIT(2) +#define QED_LINK_PARTNER_SPEED_20G BIT(3) +#define QED_LINK_PARTNER_SPEED_40G BIT(4) +#define QED_LINK_PARTNER_SPEED_50G BIT(5) +#define QED_LINK_PARTNER_SPEED_100G BIT(6) + u32 partner_adv_speed; + + bool partner_tx_flow_ctrl_en; + bool partner_rx_flow_ctrl_en; + +#define QED_LINK_PARTNER_SYMMETRIC_PAUSE (1) +#define QED_LINK_PARTNER_ASYMMETRIC_PAUSE (2) +#define QED_LINK_PARTNER_BOTH_PAUSE (3) + u8 partner_adv_pause; + + bool sfp_tx_fault; +}; + struct qed_mcp_function_info { u8 pause_on_host; @@ -44,6 +97,47 @@ struct qed_mcp_drv_version { u8 name[MCP_DRV_VER_STR_SIZE - 4]; }; +/** + * @brief - returns the link params of the hw function + * + * @param p_hwfn + * + * @returns pointer to link params + */ +struct qed_mcp_link_params *qed_mcp_get_link_params(struct qed_hwfn *); + +/** + * @brief - return the link state of the hw function + * + * @param p_hwfn + * + * @returns pointer to link state + */ +struct qed_mcp_link_state *qed_mcp_get_link_state(struct qed_hwfn *); + +/** + * @brief - return the link capabilities of the hw function + * + * @param p_hwfn + * + * @returns pointer to link capabilities + */ +struct qed_mcp_link_capabilities + *qed_mcp_get_link_capabilities(struct qed_hwfn *p_hwfn); + +/** + * @brief Request the MFW to set the the link according to 'link_input'. + * + * @param p_hwfn + * @param p_ptt + * @param b_up - raise link if `true'. Reset link if `false'. + * + * @return int + */ +int qed_mcp_set_link(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + bool b_up); + /** * @brief Get the management firmware version value * @@ -55,6 +149,19 @@ struct qed_mcp_drv_version { int qed_mcp_get_mfw_ver(struct qed_dev *cdev, u32 *mfw_ver); +/** + * @brief Get media type value of the port. + * + * @param cdev - qed dev pointer + * @param mfw_ver - media type value + * + * @return int - + * 0 - Operation was successul. + * -EBUSY - Operation failed + */ +int qed_mcp_get_media_type(struct qed_dev *cdev, + u32 *media_type); + /** * @brief General function for sending commands to the MCP * mailbox. It acquire mutex lock for the entire @@ -142,8 +249,10 @@ struct qed_mcp_info { u32 port_addr; u16 drv_mb_seq; u16 drv_pulse_seq; + struct qed_mcp_link_params link_input; + struct qed_mcp_link_state link_output; + struct qed_mcp_link_capabilities link_capabilities; struct qed_mcp_function_info func_info; - u8 *mfw_mb_cur; u8 *mfw_mb_shadow; u16 mfw_mb_length; @@ -181,6 +290,21 @@ void qed_mcp_cmd_port_init(struct qed_hwfn *p_hwfn, int qed_mcp_free(struct qed_hwfn *p_hwfn); +/** + * @brief This function is called from the DPC context. After + * pointing PTT to the mfw mb, check for events sent by the MCP + * to the driver and ack them. In case a critical event + * detected, it will be handled here, otherwise the work will be + * queued to a sleepable work-queue. + * + * @param p_hwfn - HW function + * @param p_ptt - PTT required for register access + * @return int - 0 - operation + * was successul. + */ +int qed_mcp_handle_events(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt); + /** * @brief Sends a LOAD_REQ to the MFW, and in case operation * succeed, returns whether this PF is the first on the -- cgit v1.2.3 From a2ec6172d29cf3aed92e9db40e83e36329db1dd5 Mon Sep 17 00:00:00 2001 From: Sudarsana Kalluru Date: Mon, 26 Oct 2015 11:02:32 +0200 Subject: qede: Add support for link This adds basic link functionality to qede - driver still doesn't provide users with an API to change any link property, but it does request qed to initialize the link using default configuration, and registers a callback that allows it to get link notifications. This patch adds the ability of the driver to set the carrier as active and to enable traffic as a result of async. link notifications. Following this patch, driver should be capable of running traffic. Signed-off-by: Sudarsana Kalluru Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/qede_main.c | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 0351204317e7..890439cbec7e 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -87,6 +87,7 @@ static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id); static void qede_remove(struct pci_dev *pdev); static int qede_alloc_rx_buffer(struct qede_dev *edev, struct qede_rx_queue *rxq); +static void qede_link_update(void *dev, struct qed_link_output *link); static struct pci_driver qede_pci_driver = { .name = "qede", @@ -95,6 +96,12 @@ static struct pci_driver qede_pci_driver = { .remove = qede_remove, }; +static struct qed_eth_cb_ops qede_ll_ops = { + { + .link_update = qede_link_update, + }, +}; + static int qede_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { @@ -1304,6 +1311,8 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, edev->ops->common->set_id(cdev, edev->ndev->name, DRV_MODULE_VERSION); + edev->ops->register_ops(cdev, &qede_ll_ops, edev); + INIT_DELAYED_WORK(&edev->sp_task, qede_sp_task); mutex_init(&edev->qede_lock); @@ -2099,6 +2108,7 @@ enum qede_unload_mode { static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode) { + struct qed_link_params link_params; int rc; DP_INFO(edev, "Starting qede unload\n"); @@ -2110,6 +2120,10 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode) netif_tx_disable(edev->ndev); netif_carrier_off(edev->ndev); + /* Reset the link */ + memset(&link_params, 0, sizeof(link_params)); + link_params.link_up = false; + edev->ops->common->set_link(edev->cdev, &link_params); rc = qede_stop_queues(edev); if (rc) { qede_sync_free_irqs(edev); @@ -2140,6 +2154,8 @@ enum qede_load_mode { static int qede_load(struct qede_dev *edev, enum qede_load_mode mode) { + struct qed_link_params link_params; + struct qed_link_output link_output; int rc; DP_INFO(edev, "Starting qede load\n"); @@ -2183,6 +2199,17 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode) mutex_lock(&edev->qede_lock); edev->state = QEDE_STATE_OPEN; mutex_unlock(&edev->qede_lock); + + /* Ask for link-up using current configuration */ + memset(&link_params, 0, sizeof(link_params)); + link_params.link_up = true; + edev->ops->common->set_link(edev->cdev, &link_params); + + /* Query whether link is already-up */ + memset(&link_output, 0, sizeof(link_output)); + edev->ops->common->get_link(edev->cdev, &link_output); + qede_link_update(edev, &link_output); + DP_INFO(edev, "Ending successfully qede load\n"); return 0; @@ -2223,6 +2250,26 @@ static int qede_close(struct net_device *ndev) return 0; } +static void qede_link_update(void *dev, struct qed_link_output *link) +{ + struct qede_dev *edev = dev; + + if (!netif_running(edev->ndev)) { + DP_VERBOSE(edev, NETIF_MSG_LINK, "Interface is not running\n"); + return; + } + + if (link->link_up) { + DP_NOTICE(edev, "Link is up\n"); + netif_tx_start_all_queues(edev->ndev); + netif_carrier_on(edev->ndev); + } else { + DP_NOTICE(edev, "Link is down\n"); + netif_tx_disable(edev->ndev); + netif_carrier_off(edev->ndev); + } +} + static int qede_set_mac_addr(struct net_device *ndev, void *p) { struct qede_dev *edev = netdev_priv(ndev); -- cgit v1.2.3 From 9df2ed0415b13218f84262c2372323ef028310fc Mon Sep 17 00:00:00 2001 From: Manish Chopra Date: Mon, 26 Oct 2015 11:02:33 +0200 Subject: qed: Add statistics support Device statistics can be gathered on-demand. This adds the qed support for reading the statistics [both function and port] from the device, and adds to the public API a method for requesting the current statistics. Signed-off-by: Manish Chopra Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed.h | 14 ++ drivers/net/ethernet/qlogic/qed/qed_dev.c | 244 +++++++++++++++++++++++++- drivers/net/ethernet/qlogic/qed/qed_dev_api.h | 3 + drivers/net/ethernet/qlogic/qed/qed_hsi.h | 30 ++++ drivers/net/ethernet/qlogic/qed/qed_l2.c | 3 + 5 files changed, 293 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index ca6cc8a7fc64..ac17d8669b1a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h @@ -212,7 +212,20 @@ struct qed_qm_info { u32 pf_rl; }; +struct storm_stats { + u32 address; + u32 len; +}; + +struct qed_storm_stats { + struct storm_stats mstats; + struct storm_stats pstats; + struct storm_stats tstats; + struct storm_stats ustats; +}; + struct qed_fw_data { + struct fw_ver_info *fw_ver_info; const u8 *modes_tree_buf; union init_op *init_ops; const u32 *arr_data; @@ -296,6 +309,7 @@ struct qed_hwfn { /* QM init */ struct qed_qm_info qm_info; + struct qed_storm_stats storm_stats; /* Buffer for unzipping firmware data */ void *unzip_buf; diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 7fd3d78d94f1..b9b7b7e6fa53 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -649,8 +649,10 @@ int qed_hw_init(struct qed_dev *cdev, bool allow_npar_tx_switch, const u8 *bin_fw_data) { - u32 load_code, param; + struct qed_storm_stats *p_stat; + u32 load_code, param, *p_address; int rc, mfw_rc, i; + u8 fw_vport = 0; rc = qed_init_fw_data(cdev, bin_fw_data); if (rc != 0) @@ -659,6 +661,10 @@ int qed_hw_init(struct qed_dev *cdev, for_each_hwfn(cdev, i) { struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + rc = qed_fw_vport(p_hwfn, 0, &fw_vport); + if (rc != 0) + return rc; + /* Enable DMAE in PXP */ rc = qed_change_pci_hwfn(p_hwfn, p_hwfn->p_main_ptt, true); @@ -722,6 +728,25 @@ int qed_hw_init(struct qed_dev *cdev, } p_hwfn->hw_init_done = true; + + /* init PF stats */ + p_stat = &p_hwfn->storm_stats; + p_stat->mstats.address = BAR0_MAP_REG_MSDM_RAM + + MSTORM_QUEUE_STAT_OFFSET(fw_vport); + p_stat->mstats.len = sizeof(struct eth_mstorm_per_queue_stat); + + p_stat->ustats.address = BAR0_MAP_REG_USDM_RAM + + USTORM_QUEUE_STAT_OFFSET(fw_vport); + p_stat->ustats.len = sizeof(struct eth_ustorm_per_queue_stat); + + p_stat->pstats.address = BAR0_MAP_REG_PSDM_RAM + + PSTORM_QUEUE_STAT_OFFSET(fw_vport); + p_stat->pstats.len = sizeof(struct eth_pstorm_per_queue_stat); + + p_address = &p_stat->tstats.address; + *p_address = BAR0_MAP_REG_TSDM_RAM + + TSTORM_PORT_STAT_OFFSET(MFW_PORT(p_hwfn)); + p_stat->tstats.len = sizeof(struct tstorm_per_port_stat); } return 0; @@ -1494,6 +1519,223 @@ void qed_chain_free(struct qed_dev *cdev, p_chain->p_phys_addr); } +static void __qed_get_vport_stats(struct qed_dev *cdev, + struct qed_eth_stats *stats) +{ + int i, j; + + memset(stats, 0, sizeof(*stats)); + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + struct eth_mstorm_per_queue_stat mstats; + struct eth_ustorm_per_queue_stat ustats; + struct eth_pstorm_per_queue_stat pstats; + struct tstorm_per_port_stat tstats; + struct port_stats port_stats; + struct qed_ptt *p_ptt = qed_ptt_acquire(p_hwfn); + + if (!p_ptt) { + DP_ERR(p_hwfn, "Failed to acquire ptt\n"); + continue; + } + + memset(&mstats, 0, sizeof(mstats)); + qed_memcpy_from(p_hwfn, p_ptt, &mstats, + p_hwfn->storm_stats.mstats.address, + p_hwfn->storm_stats.mstats.len); + + memset(&ustats, 0, sizeof(ustats)); + qed_memcpy_from(p_hwfn, p_ptt, &ustats, + p_hwfn->storm_stats.ustats.address, + p_hwfn->storm_stats.ustats.len); + + memset(&pstats, 0, sizeof(pstats)); + qed_memcpy_from(p_hwfn, p_ptt, &pstats, + p_hwfn->storm_stats.pstats.address, + p_hwfn->storm_stats.pstats.len); + + memset(&tstats, 0, sizeof(tstats)); + qed_memcpy_from(p_hwfn, p_ptt, &tstats, + p_hwfn->storm_stats.tstats.address, + p_hwfn->storm_stats.tstats.len); + + memset(&port_stats, 0, sizeof(port_stats)); + + if (p_hwfn->mcp_info) + qed_memcpy_from(p_hwfn, p_ptt, &port_stats, + p_hwfn->mcp_info->port_addr + + offsetof(struct public_port, stats), + sizeof(port_stats)); + qed_ptt_release(p_hwfn, p_ptt); + + stats->no_buff_discards += + HILO_64_REGPAIR(mstats.no_buff_discard); + stats->packet_too_big_discard += + HILO_64_REGPAIR(mstats.packet_too_big_discard); + stats->ttl0_discard += + HILO_64_REGPAIR(mstats.ttl0_discard); + stats->tpa_coalesced_pkts += + HILO_64_REGPAIR(mstats.tpa_coalesced_pkts); + stats->tpa_coalesced_events += + HILO_64_REGPAIR(mstats.tpa_coalesced_events); + stats->tpa_aborts_num += + HILO_64_REGPAIR(mstats.tpa_aborts_num); + stats->tpa_coalesced_bytes += + HILO_64_REGPAIR(mstats.tpa_coalesced_bytes); + + stats->rx_ucast_bytes += + HILO_64_REGPAIR(ustats.rcv_ucast_bytes); + stats->rx_mcast_bytes += + HILO_64_REGPAIR(ustats.rcv_mcast_bytes); + stats->rx_bcast_bytes += + HILO_64_REGPAIR(ustats.rcv_bcast_bytes); + stats->rx_ucast_pkts += + HILO_64_REGPAIR(ustats.rcv_ucast_pkts); + stats->rx_mcast_pkts += + HILO_64_REGPAIR(ustats.rcv_mcast_pkts); + stats->rx_bcast_pkts += + HILO_64_REGPAIR(ustats.rcv_bcast_pkts); + + stats->mftag_filter_discards += + HILO_64_REGPAIR(tstats.mftag_filter_discard); + stats->mac_filter_discards += + HILO_64_REGPAIR(tstats.eth_mac_filter_discard); + + stats->tx_ucast_bytes += + HILO_64_REGPAIR(pstats.sent_ucast_bytes); + stats->tx_mcast_bytes += + HILO_64_REGPAIR(pstats.sent_mcast_bytes); + stats->tx_bcast_bytes += + HILO_64_REGPAIR(pstats.sent_bcast_bytes); + stats->tx_ucast_pkts += + HILO_64_REGPAIR(pstats.sent_ucast_pkts); + stats->tx_mcast_pkts += + HILO_64_REGPAIR(pstats.sent_mcast_pkts); + stats->tx_bcast_pkts += + HILO_64_REGPAIR(pstats.sent_bcast_pkts); + stats->tx_err_drop_pkts += + HILO_64_REGPAIR(pstats.error_drop_pkts); + stats->rx_64_byte_packets += port_stats.pmm.r64; + stats->rx_127_byte_packets += port_stats.pmm.r127; + stats->rx_255_byte_packets += port_stats.pmm.r255; + stats->rx_511_byte_packets += port_stats.pmm.r511; + stats->rx_1023_byte_packets += port_stats.pmm.r1023; + stats->rx_1518_byte_packets += port_stats.pmm.r1518; + stats->rx_1522_byte_packets += port_stats.pmm.r1522; + stats->rx_2047_byte_packets += port_stats.pmm.r2047; + stats->rx_4095_byte_packets += port_stats.pmm.r4095; + stats->rx_9216_byte_packets += port_stats.pmm.r9216; + stats->rx_16383_byte_packets += port_stats.pmm.r16383; + stats->rx_crc_errors += port_stats.pmm.rfcs; + stats->rx_mac_crtl_frames += port_stats.pmm.rxcf; + stats->rx_pause_frames += port_stats.pmm.rxpf; + stats->rx_pfc_frames += port_stats.pmm.rxpp; + stats->rx_align_errors += port_stats.pmm.raln; + stats->rx_carrier_errors += port_stats.pmm.rfcr; + stats->rx_oversize_packets += port_stats.pmm.rovr; + stats->rx_jabbers += port_stats.pmm.rjbr; + stats->rx_undersize_packets += port_stats.pmm.rund; + stats->rx_fragments += port_stats.pmm.rfrg; + stats->tx_64_byte_packets += port_stats.pmm.t64; + stats->tx_65_to_127_byte_packets += port_stats.pmm.t127; + stats->tx_128_to_255_byte_packets += port_stats.pmm.t255; + stats->tx_256_to_511_byte_packets += port_stats.pmm.t511; + stats->tx_512_to_1023_byte_packets += port_stats.pmm.t1023; + stats->tx_1024_to_1518_byte_packets += port_stats.pmm.t1518; + stats->tx_1519_to_2047_byte_packets += port_stats.pmm.t2047; + stats->tx_2048_to_4095_byte_packets += port_stats.pmm.t4095; + stats->tx_4096_to_9216_byte_packets += port_stats.pmm.t9216; + stats->tx_9217_to_16383_byte_packets += port_stats.pmm.t16383; + stats->tx_pause_frames += port_stats.pmm.txpf; + stats->tx_pfc_frames += port_stats.pmm.txpp; + stats->tx_lpi_entry_count += port_stats.pmm.tlpiec; + stats->tx_total_collisions += port_stats.pmm.tncl; + stats->rx_mac_bytes += port_stats.pmm.rbyte; + stats->rx_mac_uc_packets += port_stats.pmm.rxuca; + stats->rx_mac_mc_packets += port_stats.pmm.rxmca; + stats->rx_mac_bc_packets += port_stats.pmm.rxbca; + stats->rx_mac_frames_ok += port_stats.pmm.rxpok; + stats->tx_mac_bytes += port_stats.pmm.tbyte; + stats->tx_mac_uc_packets += port_stats.pmm.txuca; + stats->tx_mac_mc_packets += port_stats.pmm.txmca; + stats->tx_mac_bc_packets += port_stats.pmm.txbca; + stats->tx_mac_ctrl_frames += port_stats.pmm.txcf; + + for (j = 0; j < 8; j++) { + stats->brb_truncates += port_stats.brb.brb_truncate[j]; + stats->brb_discards += port_stats.brb.brb_discard[j]; + } + } +} + +void qed_get_vport_stats(struct qed_dev *cdev, + struct qed_eth_stats *stats) +{ + u32 i; + + if (!cdev) { + memset(stats, 0, sizeof(*stats)); + return; + } + + __qed_get_vport_stats(cdev, stats); + + if (!cdev->reset_stats) + return; + + /* Reduce the statistics baseline */ + for (i = 0; i < sizeof(struct qed_eth_stats) / sizeof(u64); i++) + ((u64 *)stats)[i] -= ((u64 *)cdev->reset_stats)[i]; +} + +/* zeroes V-PORT specific portion of stats (Port stats remains untouched) */ +void qed_reset_vport_stats(struct qed_dev *cdev) +{ + int i; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + struct eth_mstorm_per_queue_stat mstats; + struct eth_ustorm_per_queue_stat ustats; + struct eth_pstorm_per_queue_stat pstats; + struct qed_ptt *p_ptt = qed_ptt_acquire(p_hwfn); + + if (!p_ptt) { + DP_ERR(p_hwfn, "Failed to acquire ptt\n"); + continue; + } + + memset(&mstats, 0, sizeof(mstats)); + qed_memcpy_to(p_hwfn, p_ptt, + p_hwfn->storm_stats.mstats.address, + &mstats, + p_hwfn->storm_stats.mstats.len); + + memset(&ustats, 0, sizeof(ustats)); + qed_memcpy_to(p_hwfn, p_ptt, + p_hwfn->storm_stats.ustats.address, + &ustats, + p_hwfn->storm_stats.ustats.len); + + memset(&pstats, 0, sizeof(pstats)); + qed_memcpy_to(p_hwfn, p_ptt, + p_hwfn->storm_stats.pstats.address, + &pstats, + p_hwfn->storm_stats.pstats.len); + + qed_ptt_release(p_hwfn, p_ptt); + } + + /* PORT statistics are not necessarily reset, so we need to + * read and create a baseline for future statistics. + */ + if (!cdev->reset_stats) + DP_INFO(cdev, "Reset stats not allocated\n"); + else + __qed_get_vport_stats(cdev, cdev->reset_stats); +} + int qed_fw_l2_queue(struct qed_hwfn *p_hwfn, u16 src_id, u16 *dst_id) { diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h index 773070d04ab8..e29a3ba6c8b0 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h +++ b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h @@ -156,6 +156,9 @@ struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn); */ void qed_ptt_release(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); +void qed_get_vport_stats(struct qed_dev *cdev, + struct qed_eth_stats *stats); +void qed_reset_vport_stats(struct qed_dev *cdev); enum qed_dmae_address_type_t { QED_DMAE_ADDRESS_HOST_VIRT, diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 5909823463ab..b2f8e854dfd1 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -355,6 +355,36 @@ struct core_conn_context { struct regpair ustorm_st_padding[2] /* padding */; }; +struct eth_mstorm_per_queue_stat { + struct regpair ttl0_discard; + struct regpair packet_too_big_discard; + struct regpair no_buff_discard; + struct regpair not_active_discard; + struct regpair tpa_coalesced_pkts; + struct regpair tpa_coalesced_events; + struct regpair tpa_aborts_num; + struct regpair tpa_coalesced_bytes; +}; + +struct eth_pstorm_per_queue_stat { + struct regpair sent_ucast_bytes; + struct regpair sent_mcast_bytes; + struct regpair sent_bcast_bytes; + struct regpair sent_ucast_pkts; + struct regpair sent_mcast_pkts; + struct regpair sent_bcast_pkts; + struct regpair error_drop_pkts; +}; + +struct eth_ustorm_per_queue_stat { + struct regpair rcv_ucast_bytes; + struct regpair rcv_mcast_bytes; + struct regpair rcv_bcast_bytes; + struct regpair rcv_ucast_pkts; + struct regpair rcv_mcast_pkts; + struct regpair rcv_bcast_pkts; +}; + /* Event Ring Next Page Address */ struct event_ring_next_addr { struct regpair addr /* Next Page Address */; diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 7049e4139d3c..f72036a2ef5b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -1298,6 +1298,8 @@ static int qed_start_vport(struct qed_dev *cdev, vport_id, mtu); } + qed_reset_vport_stats(cdev); + return 0; } @@ -1680,6 +1682,7 @@ static const struct qed_eth_ops qed_eth_ops_pass = { .filter_config = &qed_configure_filter, .fastpath_stop = &qed_fastpath_stop, .eth_cqe_completion = &qed_fp_cqe_completion, + .get_vport_stats = &qed_get_vport_stats, }; const struct qed_eth_ops *qed_get_eth_ops(u32 version) -- cgit v1.2.3 From 133fac0eedc355be5cdbeb9cdfc6df59d2bbbdd1 Mon Sep 17 00:00:00 2001 From: Sudarsana Kalluru Date: Mon, 26 Oct 2015 11:02:34 +0200 Subject: qede: Add basic ethtool support This adds basic ethtool operations to the qed driver, allowing support in: - Statistics gathering [ethtool -S] - Setting of debug level [ethtool -s msglvl] - Getting basic information [ethtool, ethtool -i] In addition it adds the ability to change the MTU. Signed-off-by: Sudarsana Kalluru Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qede/Makefile | 2 +- drivers/net/ethernet/qlogic/qede/qede.h | 74 +++++ drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 385 ++++++++++++++++++++++++ drivers/net/ethernet/qlogic/qede/qede_main.c | 137 ++++++++- 4 files changed, 596 insertions(+), 2 deletions(-) create mode 100644 drivers/net/ethernet/qlogic/qede/qede_ethtool.c (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qede/Makefile b/drivers/net/ethernet/qlogic/qede/Makefile index bedfe9fc736b..06ff90d87572 100644 --- a/drivers/net/ethernet/qlogic/qede/Makefile +++ b/drivers/net/ethernet/qlogic/qede/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_QEDE) := qede.o -qede-y := qede_main.o +qede-y := qede_main.o qede_ethtool.o diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 79479427b6d4..ea00d5f3bab4 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -36,6 +36,70 @@ #define DRV_MODULE_SYM qede +struct qede_stats { + u64 no_buff_discards; + u64 rx_ucast_bytes; + u64 rx_mcast_bytes; + u64 rx_bcast_bytes; + u64 rx_ucast_pkts; + u64 rx_mcast_pkts; + u64 rx_bcast_pkts; + u64 mftag_filter_discards; + u64 mac_filter_discards; + u64 tx_ucast_bytes; + u64 tx_mcast_bytes; + u64 tx_bcast_bytes; + u64 tx_ucast_pkts; + u64 tx_mcast_pkts; + u64 tx_bcast_pkts; + u64 tx_err_drop_pkts; + u64 coalesced_pkts; + u64 coalesced_events; + u64 coalesced_aborts_num; + u64 non_coalesced_pkts; + u64 coalesced_bytes; + + /* port */ + u64 rx_64_byte_packets; + u64 rx_127_byte_packets; + u64 rx_255_byte_packets; + u64 rx_511_byte_packets; + u64 rx_1023_byte_packets; + u64 rx_1518_byte_packets; + u64 rx_1522_byte_packets; + u64 rx_2047_byte_packets; + u64 rx_4095_byte_packets; + u64 rx_9216_byte_packets; + u64 rx_16383_byte_packets; + u64 rx_crc_errors; + u64 rx_mac_crtl_frames; + u64 rx_pause_frames; + u64 rx_pfc_frames; + u64 rx_align_errors; + u64 rx_carrier_errors; + u64 rx_oversize_packets; + u64 rx_jabbers; + u64 rx_undersize_packets; + u64 rx_fragments; + u64 tx_64_byte_packets; + u64 tx_65_to_127_byte_packets; + u64 tx_128_to_255_byte_packets; + u64 tx_256_to_511_byte_packets; + u64 tx_512_to_1023_byte_packets; + u64 tx_1024_to_1518_byte_packets; + u64 tx_1519_to_2047_byte_packets; + u64 tx_2048_to_4095_byte_packets; + u64 tx_4096_to_9216_byte_packets; + u64 tx_9217_to_16383_byte_packets; + u64 tx_pause_frames; + u64 tx_pfc_frames; + u64 tx_lpi_entry_count; + u64 tx_total_collisions; + u64 brb_truncates; + u64 brb_discards; + u64 tx_mac_ctrl_frames; +}; + struct qede_dev { struct qed_dev *cdev; struct net_device *ndev; @@ -84,6 +148,7 @@ struct qede_dev { max_t(u64, 1UL << QEDE_RX_ALIGN_SHIFT, \ SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) + struct qede_stats stats; struct qed_update_vport_rss_params rss_params; u16 q_num_rx_buffers; /* Must be a power of two */ u16 q_num_tx_buffers; /* Must be a power of two */ @@ -194,6 +259,15 @@ union qede_reload_args { u16 mtu; }; +void qede_config_debug(uint debug, u32 *p_dp_module, u8 *p_dp_level); +void qede_set_ethtool_ops(struct net_device *netdev); +void qede_reload(struct qede_dev *edev, + void (*func)(struct qede_dev *edev, + union qede_reload_args *args), + union qede_reload_args *args); +int qede_change_mtu(struct net_device *dev, int new_mtu); +void qede_fill_by_demand_stats(struct qede_dev *edev); + #define RX_RING_SIZE_POW 13 #define RX_RING_SIZE BIT(RX_RING_SIZE_POW) #define NUM_RX_BDS_MAX (RX_RING_SIZE - 1) diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c new file mode 100644 index 000000000000..3a362476a22c --- /dev/null +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -0,0 +1,385 @@ +/* QLogic qede NIC Driver +* Copyright (c) 2015 QLogic Corporation +* +* This software is available under the terms of the GNU General Public License +* (GPL) Version 2, available from the file COPYING in the main directory of +* this source tree. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "qede.h" + +#define QEDE_STAT_OFFSET(stat_name) (offsetof(struct qede_stats, stat_name)) +#define QEDE_STAT_STRING(stat_name) (#stat_name) +#define _QEDE_STAT(stat_name, pf_only) \ + {QEDE_STAT_OFFSET(stat_name), QEDE_STAT_STRING(stat_name), pf_only} +#define QEDE_PF_STAT(stat_name) _QEDE_STAT(stat_name, true) +#define QEDE_STAT(stat_name) _QEDE_STAT(stat_name, false) + +#define QEDE_RQSTAT_OFFSET(stat_name) \ + (offsetof(struct qede_rx_queue, stat_name)) +#define QEDE_RQSTAT_STRING(stat_name) (#stat_name) +#define QEDE_RQSTAT(stat_name) \ + {QEDE_RQSTAT_OFFSET(stat_name), QEDE_RQSTAT_STRING(stat_name)} +static const struct { + u64 offset; + char string[ETH_GSTRING_LEN]; +} qede_rqstats_arr[] = { + QEDE_RQSTAT(rx_hw_errors), + QEDE_RQSTAT(rx_alloc_errors), +}; + +#define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr) +#define QEDE_RQSTATS_DATA(dev, sindex, rqindex) \ + (*((u64 *)(((char *)(dev->fp_array[(rqindex)].rxq)) +\ + qede_rqstats_arr[(sindex)].offset))) +static const struct { + u64 offset; + char string[ETH_GSTRING_LEN]; + bool pf_only; +} qede_stats_arr[] = { + QEDE_STAT(rx_ucast_bytes), + QEDE_STAT(rx_mcast_bytes), + QEDE_STAT(rx_bcast_bytes), + QEDE_STAT(rx_ucast_pkts), + QEDE_STAT(rx_mcast_pkts), + QEDE_STAT(rx_bcast_pkts), + + QEDE_STAT(tx_ucast_bytes), + QEDE_STAT(tx_mcast_bytes), + QEDE_STAT(tx_bcast_bytes), + QEDE_STAT(tx_ucast_pkts), + QEDE_STAT(tx_mcast_pkts), + QEDE_STAT(tx_bcast_pkts), + + QEDE_PF_STAT(rx_64_byte_packets), + QEDE_PF_STAT(rx_127_byte_packets), + QEDE_PF_STAT(rx_255_byte_packets), + QEDE_PF_STAT(rx_511_byte_packets), + QEDE_PF_STAT(rx_1023_byte_packets), + QEDE_PF_STAT(rx_1518_byte_packets), + QEDE_PF_STAT(rx_1522_byte_packets), + QEDE_PF_STAT(rx_2047_byte_packets), + QEDE_PF_STAT(rx_4095_byte_packets), + QEDE_PF_STAT(rx_9216_byte_packets), + QEDE_PF_STAT(rx_16383_byte_packets), + QEDE_PF_STAT(tx_64_byte_packets), + QEDE_PF_STAT(tx_65_to_127_byte_packets), + QEDE_PF_STAT(tx_128_to_255_byte_packets), + QEDE_PF_STAT(tx_256_to_511_byte_packets), + QEDE_PF_STAT(tx_512_to_1023_byte_packets), + QEDE_PF_STAT(tx_1024_to_1518_byte_packets), + QEDE_PF_STAT(tx_1519_to_2047_byte_packets), + QEDE_PF_STAT(tx_2048_to_4095_byte_packets), + QEDE_PF_STAT(tx_4096_to_9216_byte_packets), + QEDE_PF_STAT(tx_9217_to_16383_byte_packets), + + QEDE_PF_STAT(rx_mac_crtl_frames), + QEDE_PF_STAT(tx_mac_ctrl_frames), + QEDE_PF_STAT(rx_pause_frames), + QEDE_PF_STAT(tx_pause_frames), + QEDE_PF_STAT(rx_pfc_frames), + QEDE_PF_STAT(tx_pfc_frames), + + QEDE_PF_STAT(rx_crc_errors), + QEDE_PF_STAT(rx_align_errors), + QEDE_PF_STAT(rx_carrier_errors), + QEDE_PF_STAT(rx_oversize_packets), + QEDE_PF_STAT(rx_jabbers), + QEDE_PF_STAT(rx_undersize_packets), + QEDE_PF_STAT(rx_fragments), + QEDE_PF_STAT(tx_lpi_entry_count), + QEDE_PF_STAT(tx_total_collisions), + QEDE_PF_STAT(brb_truncates), + QEDE_PF_STAT(brb_discards), + QEDE_STAT(no_buff_discards), + QEDE_PF_STAT(mftag_filter_discards), + QEDE_PF_STAT(mac_filter_discards), + QEDE_STAT(tx_err_drop_pkts), + + QEDE_STAT(coalesced_pkts), + QEDE_STAT(coalesced_events), + QEDE_STAT(coalesced_aborts_num), + QEDE_STAT(non_coalesced_pkts), + QEDE_STAT(coalesced_bytes), +}; + +#define QEDE_STATS_DATA(dev, index) \ + (*((u64 *)(((char *)(dev)) + offsetof(struct qede_dev, stats) \ + + qede_stats_arr[(index)].offset))) + +#define QEDE_NUM_STATS ARRAY_SIZE(qede_stats_arr) + +static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf) +{ + int i, j, k; + + for (i = 0, j = 0; i < QEDE_NUM_STATS; i++) { + strcpy(buf + j * ETH_GSTRING_LEN, + qede_stats_arr[i].string); + j++; + } + + for (k = 0; k < QEDE_NUM_RQSTATS; k++, j++) + strcpy(buf + j * ETH_GSTRING_LEN, + qede_rqstats_arr[k].string); +} + +static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf) +{ + struct qede_dev *edev = netdev_priv(dev); + + switch (stringset) { + case ETH_SS_STATS: + qede_get_strings_stats(edev, buf); + break; + default: + DP_VERBOSE(edev, QED_MSG_DEBUG, + "Unsupported stringset 0x%08x\n", stringset); + } +} + +static void qede_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *buf) +{ + struct qede_dev *edev = netdev_priv(dev); + int sidx, cnt = 0; + int qid; + + qede_fill_by_demand_stats(edev); + + mutex_lock(&edev->qede_lock); + + for (sidx = 0; sidx < QEDE_NUM_STATS; sidx++) + buf[cnt++] = QEDE_STATS_DATA(edev, sidx); + + for (sidx = 0; sidx < QEDE_NUM_RQSTATS; sidx++) { + buf[cnt] = 0; + for (qid = 0; qid < edev->num_rss; qid++) + buf[cnt] += QEDE_RQSTATS_DATA(edev, sidx, qid); + cnt++; + } + + mutex_unlock(&edev->qede_lock); +} + +static int qede_get_sset_count(struct net_device *dev, int stringset) +{ + struct qede_dev *edev = netdev_priv(dev); + int num_stats = QEDE_NUM_STATS; + + switch (stringset) { + case ETH_SS_STATS: + return num_stats + QEDE_NUM_RQSTATS; + + default: + DP_VERBOSE(edev, QED_MSG_DEBUG, + "Unsupported stringset 0x%08x\n", stringset); + return -EINVAL; + } +} + +static int qede_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct qede_dev *edev = netdev_priv(dev); + struct qed_link_output current_link; + + memset(¤t_link, 0, sizeof(current_link)); + edev->ops->common->get_link(edev->cdev, ¤t_link); + + cmd->supported = current_link.supported_caps; + cmd->advertising = current_link.advertised_caps; + if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) { + ethtool_cmd_speed_set(cmd, current_link.speed); + cmd->duplex = current_link.duplex; + } else { + cmd->duplex = DUPLEX_UNKNOWN; + ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN); + } + cmd->port = current_link.port; + cmd->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE : + AUTONEG_DISABLE; + cmd->lp_advertising = current_link.lp_caps; + + return 0; +} + +static int qede_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct qede_dev *edev = netdev_priv(dev); + struct qed_link_output current_link; + struct qed_link_params params; + u32 speed; + + if (edev->dev_info.common.is_mf) { + DP_INFO(edev, + "Link parameters can not be changed in MF mode\n"); + return -EOPNOTSUPP; + } + + memset(¤t_link, 0, sizeof(current_link)); + memset(¶ms, 0, sizeof(params)); + edev->ops->common->get_link(edev->cdev, ¤t_link); + + speed = ethtool_cmd_speed(cmd); + params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS; + params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG; + if (cmd->autoneg == AUTONEG_ENABLE) { + params.autoneg = true; + params.forced_speed = 0; + params.adv_speeds = cmd->advertising; + } else { /* forced speed */ + params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED; + params.autoneg = false; + params.forced_speed = speed; + switch (speed) { + case SPEED_10000: + if (!(current_link.supported_caps & + SUPPORTED_10000baseKR_Full)) { + DP_INFO(edev, "10G speed not supported\n"); + return -EINVAL; + } + params.adv_speeds = SUPPORTED_10000baseKR_Full; + break; + case SPEED_40000: + if (!(current_link.supported_caps & + SUPPORTED_40000baseLR4_Full)) { + DP_INFO(edev, "40G speed not supported\n"); + return -EINVAL; + } + params.adv_speeds = SUPPORTED_40000baseLR4_Full; + break; + default: + DP_INFO(edev, "Unsupported speed %u\n", speed); + return -EINVAL; + } + } + + params.link_up = true; + edev->ops->common->set_link(edev->cdev, ¶ms); + + return 0; +} + +static void qede_get_drvinfo(struct net_device *ndev, + struct ethtool_drvinfo *info) +{ + char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN]; + struct qede_dev *edev = netdev_priv(ndev); + + strlcpy(info->driver, "qede", sizeof(info->driver)); + strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); + + snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", + edev->dev_info.common.fw_major, + edev->dev_info.common.fw_minor, + edev->dev_info.common.fw_rev, + edev->dev_info.common.fw_eng); + + snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d", + (edev->dev_info.common.mfw_rev >> 24) & 0xFF, + (edev->dev_info.common.mfw_rev >> 16) & 0xFF, + (edev->dev_info.common.mfw_rev >> 8) & 0xFF, + edev->dev_info.common.mfw_rev & 0xFF); + + if ((strlen(storm) + strlen(mfw) + strlen("mfw storm ")) < + sizeof(info->fw_version)) { + snprintf(info->fw_version, sizeof(info->fw_version), + "mfw %s storm %s", mfw, storm); + } else { + snprintf(info->fw_version, sizeof(info->fw_version), + "%s %s", mfw, storm); + } + + strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info)); +} + +static u32 qede_get_msglevel(struct net_device *ndev) +{ + struct qede_dev *edev = netdev_priv(ndev); + + return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | + edev->dp_module; +} + +static void qede_set_msglevel(struct net_device *ndev, u32 level) +{ + struct qede_dev *edev = netdev_priv(ndev); + u32 dp_module = 0; + u8 dp_level = 0; + + qede_config_debug(level, &dp_module, &dp_level); + + edev->dp_level = dp_level; + edev->dp_module = dp_module; + edev->ops->common->update_msglvl(edev->cdev, + dp_module, dp_level); +} + +static u32 qede_get_link(struct net_device *dev) +{ + struct qede_dev *edev = netdev_priv(dev); + struct qed_link_output current_link; + + memset(¤t_link, 0, sizeof(current_link)); + edev->ops->common->get_link(edev->cdev, ¤t_link); + + return current_link.link_up; +} + +static void qede_update_mtu(struct qede_dev *edev, union qede_reload_args *args) +{ + edev->ndev->mtu = args->mtu; +} + +/* Netdevice NDOs */ +#define ETH_MAX_JUMBO_PACKET_SIZE 9600 +#define ETH_MIN_PACKET_SIZE 60 +int qede_change_mtu(struct net_device *ndev, int new_mtu) +{ + struct qede_dev *edev = netdev_priv(ndev); + union qede_reload_args args; + + if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) || + ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE)) { + DP_ERR(edev, "Can't support requested MTU size\n"); + return -EINVAL; + } + + DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN), + "Configuring MTU size of %d\n", new_mtu); + + /* Set the mtu field and re-start the interface if needed*/ + args.mtu = new_mtu; + + if (netif_running(edev->ndev)) + qede_reload(edev, &qede_update_mtu, &args); + + qede_update_mtu(edev, &args); + + return 0; +} + +static const struct ethtool_ops qede_ethtool_ops = { + .get_settings = qede_get_settings, + .set_settings = qede_set_settings, + .get_drvinfo = qede_get_drvinfo, + .get_msglevel = qede_get_msglevel, + .set_msglevel = qede_set_msglevel, + .get_link = qede_get_link, + .get_strings = qede_get_strings, + .get_ethtool_stats = qede_get_ethtool_stats, + .get_sset_count = qede_get_sset_count, + +}; + +void qede_set_ethtool_ops(struct net_device *dev) +{ + dev->ethtool_ops = &qede_ethtool_ops; +} diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 890439cbec7e..f4657a2e730a 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -1056,6 +1056,118 @@ static int qede_set_ucast_rx_mac(struct qede_dev *edev, return edev->ops->filter_config(edev->cdev, &filter_cmd); } +void qede_fill_by_demand_stats(struct qede_dev *edev) +{ + struct qed_eth_stats stats; + + edev->ops->get_vport_stats(edev->cdev, &stats); + edev->stats.no_buff_discards = stats.no_buff_discards; + edev->stats.rx_ucast_bytes = stats.rx_ucast_bytes; + edev->stats.rx_mcast_bytes = stats.rx_mcast_bytes; + edev->stats.rx_bcast_bytes = stats.rx_bcast_bytes; + edev->stats.rx_ucast_pkts = stats.rx_ucast_pkts; + edev->stats.rx_mcast_pkts = stats.rx_mcast_pkts; + edev->stats.rx_bcast_pkts = stats.rx_bcast_pkts; + edev->stats.mftag_filter_discards = stats.mftag_filter_discards; + edev->stats.mac_filter_discards = stats.mac_filter_discards; + + edev->stats.tx_ucast_bytes = stats.tx_ucast_bytes; + edev->stats.tx_mcast_bytes = stats.tx_mcast_bytes; + edev->stats.tx_bcast_bytes = stats.tx_bcast_bytes; + edev->stats.tx_ucast_pkts = stats.tx_ucast_pkts; + edev->stats.tx_mcast_pkts = stats.tx_mcast_pkts; + edev->stats.tx_bcast_pkts = stats.tx_bcast_pkts; + edev->stats.tx_err_drop_pkts = stats.tx_err_drop_pkts; + edev->stats.coalesced_pkts = stats.tpa_coalesced_pkts; + edev->stats.coalesced_events = stats.tpa_coalesced_events; + edev->stats.coalesced_aborts_num = stats.tpa_aborts_num; + edev->stats.non_coalesced_pkts = stats.tpa_not_coalesced_pkts; + edev->stats.coalesced_bytes = stats.tpa_coalesced_bytes; + + edev->stats.rx_64_byte_packets = stats.rx_64_byte_packets; + edev->stats.rx_127_byte_packets = stats.rx_127_byte_packets; + edev->stats.rx_255_byte_packets = stats.rx_255_byte_packets; + edev->stats.rx_511_byte_packets = stats.rx_511_byte_packets; + edev->stats.rx_1023_byte_packets = stats.rx_1023_byte_packets; + edev->stats.rx_1518_byte_packets = stats.rx_1518_byte_packets; + edev->stats.rx_1522_byte_packets = stats.rx_1522_byte_packets; + edev->stats.rx_2047_byte_packets = stats.rx_2047_byte_packets; + edev->stats.rx_4095_byte_packets = stats.rx_4095_byte_packets; + edev->stats.rx_9216_byte_packets = stats.rx_9216_byte_packets; + edev->stats.rx_16383_byte_packets = stats.rx_16383_byte_packets; + edev->stats.rx_crc_errors = stats.rx_crc_errors; + edev->stats.rx_mac_crtl_frames = stats.rx_mac_crtl_frames; + edev->stats.rx_pause_frames = stats.rx_pause_frames; + edev->stats.rx_pfc_frames = stats.rx_pfc_frames; + edev->stats.rx_align_errors = stats.rx_align_errors; + edev->stats.rx_carrier_errors = stats.rx_carrier_errors; + edev->stats.rx_oversize_packets = stats.rx_oversize_packets; + edev->stats.rx_jabbers = stats.rx_jabbers; + edev->stats.rx_undersize_packets = stats.rx_undersize_packets; + edev->stats.rx_fragments = stats.rx_fragments; + edev->stats.tx_64_byte_packets = stats.tx_64_byte_packets; + edev->stats.tx_65_to_127_byte_packets = stats.tx_65_to_127_byte_packets; + edev->stats.tx_128_to_255_byte_packets = + stats.tx_128_to_255_byte_packets; + edev->stats.tx_256_to_511_byte_packets = + stats.tx_256_to_511_byte_packets; + edev->stats.tx_512_to_1023_byte_packets = + stats.tx_512_to_1023_byte_packets; + edev->stats.tx_1024_to_1518_byte_packets = + stats.tx_1024_to_1518_byte_packets; + edev->stats.tx_1519_to_2047_byte_packets = + stats.tx_1519_to_2047_byte_packets; + edev->stats.tx_2048_to_4095_byte_packets = + stats.tx_2048_to_4095_byte_packets; + edev->stats.tx_4096_to_9216_byte_packets = + stats.tx_4096_to_9216_byte_packets; + edev->stats.tx_9217_to_16383_byte_packets = + stats.tx_9217_to_16383_byte_packets; + edev->stats.tx_pause_frames = stats.tx_pause_frames; + edev->stats.tx_pfc_frames = stats.tx_pfc_frames; + edev->stats.tx_lpi_entry_count = stats.tx_lpi_entry_count; + edev->stats.tx_total_collisions = stats.tx_total_collisions; + edev->stats.brb_truncates = stats.brb_truncates; + edev->stats.brb_discards = stats.brb_discards; + edev->stats.tx_mac_ctrl_frames = stats.tx_mac_ctrl_frames; +} + +static struct rtnl_link_stats64 *qede_get_stats64( + struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + struct qede_dev *edev = netdev_priv(dev); + + qede_fill_by_demand_stats(edev); + + stats->rx_packets = edev->stats.rx_ucast_pkts + + edev->stats.rx_mcast_pkts + + edev->stats.rx_bcast_pkts; + stats->tx_packets = edev->stats.tx_ucast_pkts + + edev->stats.tx_mcast_pkts + + edev->stats.tx_bcast_pkts; + + stats->rx_bytes = edev->stats.rx_ucast_bytes + + edev->stats.rx_mcast_bytes + + edev->stats.rx_bcast_bytes; + + stats->tx_bytes = edev->stats.tx_ucast_bytes + + edev->stats.tx_mcast_bytes + + edev->stats.tx_bcast_bytes; + + stats->tx_errors = edev->stats.tx_err_drop_pkts; + stats->multicast = edev->stats.rx_mcast_pkts + + edev->stats.rx_bcast_pkts; + + stats->rx_fifo_errors = edev->stats.no_buff_discards; + + stats->collisions = edev->stats.tx_total_collisions; + stats->rx_crc_errors = edev->stats.rx_crc_errors; + stats->rx_frame_errors = edev->stats.rx_align_errors; + + return stats; +} + static const struct net_device_ops qede_netdev_ops = { .ndo_open = qede_open, .ndo_stop = qede_close, @@ -1063,6 +1175,8 @@ static const struct net_device_ops qede_netdev_ops = { .ndo_set_rx_mode = qede_set_rx_mode, .ndo_set_mac_address = qede_set_mac_addr, .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = qede_change_mtu, + .ndo_get_stats64 = qede_get_stats64, }; /* ------------------------------------------------------------------------- @@ -1101,6 +1215,7 @@ static struct qede_dev *qede_alloc_etherdev(struct qed_dev *cdev, SET_NETDEV_DEV(ndev, &pdev->dev); + memset(&edev->stats, 0, sizeof(edev->stats)); memcpy(&edev->dev_info, info, sizeof(*info)); edev->num_tc = edev->dev_info.num_tc; @@ -1125,6 +1240,8 @@ static void qede_init_ndev(struct qede_dev *edev) ndev->netdev_ops = &qede_netdev_ops; + qede_set_ethtool_ops(ndev); + /* user-changeble features */ hw_features = NETIF_F_GRO | NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | @@ -1153,7 +1270,7 @@ static void qede_init_ndev(struct qede_dev *edev) * * Notice that the level should be that of the lowest required logs. */ -static void qede_config_debug(uint debug, u32 *p_dp_module, u8 *p_dp_level) +void qede_config_debug(uint debug, u32 *p_dp_module, u8 *p_dp_level) { *p_dp_level = QED_LEVEL_NOTICE; *p_dp_module = 0; @@ -2229,6 +2346,24 @@ err0: return rc; } +void qede_reload(struct qede_dev *edev, + void (*func)(struct qede_dev *, union qede_reload_args *), + union qede_reload_args *args) +{ + qede_unload(edev, QEDE_UNLOAD_NORMAL); + /* Call function handler to update parameters + * needed for function load. + */ + if (func) + func(edev, args); + + qede_load(edev, QEDE_LOAD_NORMAL); + + mutex_lock(&edev->qede_lock); + qede_config_rx_mode(edev->ndev); + mutex_unlock(&edev->qede_lock); +} + /* called with rtnl_lock */ static int qede_open(struct net_device *ndev) { -- cgit v1.2.3 From c0f9c7e45d374ce6dc369443fa586c2fe228c345 Mon Sep 17 00:00:00 2001 From: Bert Kenward Date: Mon, 26 Oct 2015 14:23:42 +0000 Subject: sfc: replace spinlocks with bit ops for busy poll locking This patch reduces the overhead of locking for busy poll. Previously the state was protected by a lock, whereas now it's manipulated solely with atomic operations. Signed-off-by: Shradha Shah Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/efx.c | 4 +- drivers/net/ethernet/sfc/net_driver.h | 129 +++++++++++++++------------------- 2 files changed, 58 insertions(+), 75 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 974637d3ae25..6e11ee6173ce 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -2062,7 +2062,7 @@ static void efx_init_napi_channel(struct efx_channel *channel) netif_napi_add(channel->napi_dev, &channel->napi_str, efx_poll, napi_weight); napi_hash_add(&channel->napi_str); - efx_channel_init_lock(channel); + efx_channel_busy_poll_init(channel); } static void efx_init_napi(struct efx_nic *efx) @@ -2125,7 +2125,7 @@ static int efx_busy_poll(struct napi_struct *napi) if (!netif_running(efx->net_dev)) return LL_FLUSH_FAILED; - if (!efx_channel_lock_poll(channel)) + if (!efx_channel_try_lock_poll(channel)) return LL_FLUSH_BUSY; old_rx_packets = channel->rx_queue.rx_packets; diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index ad56231743a6..229e68c89634 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -431,21 +431,8 @@ struct efx_channel { struct net_device *napi_dev; struct napi_struct napi_str; #ifdef CONFIG_NET_RX_BUSY_POLL - unsigned int state; - spinlock_t state_lock; -#define EFX_CHANNEL_STATE_IDLE 0 -#define EFX_CHANNEL_STATE_NAPI (1 << 0) /* NAPI owns this channel */ -#define EFX_CHANNEL_STATE_POLL (1 << 1) /* poll owns this channel */ -#define EFX_CHANNEL_STATE_DISABLED (1 << 2) /* channel is disabled */ -#define EFX_CHANNEL_STATE_NAPI_YIELD (1 << 3) /* NAPI yielded this channel */ -#define EFX_CHANNEL_STATE_POLL_YIELD (1 << 4) /* poll yielded this channel */ -#define EFX_CHANNEL_OWNED \ - (EFX_CHANNEL_STATE_NAPI | EFX_CHANNEL_STATE_POLL) -#define EFX_CHANNEL_LOCKED \ - (EFX_CHANNEL_OWNED | EFX_CHANNEL_STATE_DISABLED) -#define EFX_CHANNEL_USER_PEND \ - (EFX_CHANNEL_STATE_POLL | EFX_CHANNEL_STATE_POLL_YIELD) -#endif /* CONFIG_NET_RX_BUSY_POLL */ + unsigned long busy_poll_state; +#endif struct efx_special_buffer eventq; unsigned int eventq_mask; unsigned int eventq_read_ptr; @@ -480,98 +467,94 @@ struct efx_channel { }; #ifdef CONFIG_NET_RX_BUSY_POLL -static inline void efx_channel_init_lock(struct efx_channel *channel) +enum efx_channel_busy_poll_state { + EFX_CHANNEL_STATE_IDLE = 0, + EFX_CHANNEL_STATE_NAPI = BIT(0), + EFX_CHANNEL_STATE_NAPI_REQ_BIT = 1, + EFX_CHANNEL_STATE_NAPI_REQ = BIT(1), + EFX_CHANNEL_STATE_POLL_BIT = 2, + EFX_CHANNEL_STATE_POLL = BIT(2), + EFX_CHANNEL_STATE_DISABLE_BIT = 3, +}; + +static inline void efx_channel_busy_poll_init(struct efx_channel *channel) { - spin_lock_init(&channel->state_lock); + WRITE_ONCE(channel->busy_poll_state, EFX_CHANNEL_STATE_IDLE); } /* Called from the device poll routine to get ownership of a channel. */ static inline bool efx_channel_lock_napi(struct efx_channel *channel) { - bool rc = true; - - spin_lock_bh(&channel->state_lock); - if (channel->state & EFX_CHANNEL_LOCKED) { - WARN_ON(channel->state & EFX_CHANNEL_STATE_NAPI); - channel->state |= EFX_CHANNEL_STATE_NAPI_YIELD; - rc = false; - } else { - /* we don't care if someone yielded */ - channel->state = EFX_CHANNEL_STATE_NAPI; + unsigned long prev, old = READ_ONCE(channel->busy_poll_state); + + while (1) { + switch (old) { + case EFX_CHANNEL_STATE_POLL: + /* Ensure efx_channel_try_lock_poll() wont starve us */ + set_bit(EFX_CHANNEL_STATE_NAPI_REQ_BIT, + &channel->busy_poll_state); + /* fallthrough */ + case EFX_CHANNEL_STATE_POLL | EFX_CHANNEL_STATE_NAPI_REQ: + return false; + default: + break; + } + prev = cmpxchg(&channel->busy_poll_state, old, + EFX_CHANNEL_STATE_NAPI); + if (unlikely(prev != old)) { + /* This is likely to mean we've just entered polling + * state. Go back round to set the REQ bit. + */ + old = prev; + continue; + } + return true; } - spin_unlock_bh(&channel->state_lock); - return rc; } static inline void efx_channel_unlock_napi(struct efx_channel *channel) { - spin_lock_bh(&channel->state_lock); - WARN_ON(channel->state & - (EFX_CHANNEL_STATE_POLL | EFX_CHANNEL_STATE_NAPI_YIELD)); - - channel->state &= EFX_CHANNEL_STATE_DISABLED; - spin_unlock_bh(&channel->state_lock); + /* Make sure write has completed from efx_channel_lock_napi() */ + smp_wmb(); + WRITE_ONCE(channel->busy_poll_state, EFX_CHANNEL_STATE_IDLE); } /* Called from efx_busy_poll(). */ -static inline bool efx_channel_lock_poll(struct efx_channel *channel) +static inline bool efx_channel_try_lock_poll(struct efx_channel *channel) { - bool rc = true; - - spin_lock_bh(&channel->state_lock); - if ((channel->state & EFX_CHANNEL_LOCKED)) { - channel->state |= EFX_CHANNEL_STATE_POLL_YIELD; - rc = false; - } else { - /* preserve yield marks */ - channel->state |= EFX_CHANNEL_STATE_POLL; - } - spin_unlock_bh(&channel->state_lock); - return rc; + return cmpxchg(&channel->busy_poll_state, EFX_CHANNEL_STATE_IDLE, + EFX_CHANNEL_STATE_POLL) == EFX_CHANNEL_STATE_IDLE; } -/* Returns true if NAPI tried to get the channel while it was locked. */ static inline void efx_channel_unlock_poll(struct efx_channel *channel) { - spin_lock_bh(&channel->state_lock); - WARN_ON(channel->state & EFX_CHANNEL_STATE_NAPI); - - /* will reset state to idle, unless channel is disabled */ - channel->state &= EFX_CHANNEL_STATE_DISABLED; - spin_unlock_bh(&channel->state_lock); + clear_bit_unlock(EFX_CHANNEL_STATE_POLL_BIT, &channel->busy_poll_state); } -/* True if a socket is polling, even if it did not get the lock. */ static inline bool efx_channel_busy_polling(struct efx_channel *channel) { - WARN_ON(!(channel->state & EFX_CHANNEL_OWNED)); - return channel->state & EFX_CHANNEL_USER_PEND; + return test_bit(EFX_CHANNEL_STATE_POLL_BIT, &channel->busy_poll_state); } static inline void efx_channel_enable(struct efx_channel *channel) { - spin_lock_bh(&channel->state_lock); - channel->state = EFX_CHANNEL_STATE_IDLE; - spin_unlock_bh(&channel->state_lock); + clear_bit_unlock(EFX_CHANNEL_STATE_DISABLE_BIT, + &channel->busy_poll_state); } -/* False if the channel is currently owned. */ +/* Stop further polling or napi access. + * Returns false if the channel is currently busy polling. + */ static inline bool efx_channel_disable(struct efx_channel *channel) { - bool rc = true; - - spin_lock_bh(&channel->state_lock); - if (channel->state & EFX_CHANNEL_OWNED) - rc = false; - channel->state |= EFX_CHANNEL_STATE_DISABLED; - spin_unlock_bh(&channel->state_lock); - - return rc; + set_bit(EFX_CHANNEL_STATE_DISABLE_BIT, &channel->busy_poll_state); + /* Implicit barrier in efx_channel_busy_polling() */ + return !efx_channel_busy_polling(channel); } #else /* CONFIG_NET_RX_BUSY_POLL */ -static inline void efx_channel_init_lock(struct efx_channel *channel) +static inline void efx_channel_busy_poll_init(struct efx_channel *channel) { } @@ -584,7 +567,7 @@ static inline void efx_channel_unlock_napi(struct efx_channel *channel) { } -static inline bool efx_channel_lock_poll(struct efx_channel *channel) +static inline bool efx_channel_try_lock_poll(struct efx_channel *channel) { return false; } -- cgit v1.2.3 From 0b7c874348ea14ec3c358fe95e56d6f830540248 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 26 Oct 2015 12:24:22 -0400 Subject: forcedeth: fix unilateral interrupt disabling in netpoll path Forcedeth currently uses disable_irq_lockdep and enable_irq_lockdep, which in some configurations simply calls local_irq_disable. This causes errant warnings in the netpoll path as in netpoll_send_skb_on_dev, where we disable irqs using local_irq_save, leading to the following warning: WARNING: at net/core/netpoll.c:352 netpoll_send_skb_on_dev+0x243/0x250() (Not tainted) Hardware name: netpoll_send_skb_on_dev(): eth0 enabled interrupts in poll (nv_start_xmit_optimized+0x0/0x860 [forcedeth]) Modules linked in: netconsole(+) configfs ipv6 iptable_filter ip_tables ppdev parport_pc parport sg microcode serio_raw edac_core edac_mce_amd k8temp snd_hda_codec_realtek snd_hda_codec_generic forcedeth snd_hda_intel snd_hda_codec snd_hwdep snd_seq snd_seq_device snd_pcm snd_timer snd soundcore snd_page_alloc i2c_nforce2 i2c_core shpchp ext4 jbd2 mbcache sr_mod cdrom sd_mod crc_t10dif pata_amd ata_generic pata_acpi sata_nv dm_mirror dm_region_hash dm_log dm_mod [last unloaded: scsi_wait_scan] Pid: 1940, comm: modprobe Not tainted 2.6.32-573.7.1.el6.x86_64.debug #1 Call Trace: [] ? warn_slowpath_common+0x91/0xe0 [] ? warn_slowpath_fmt+0x46/0x60 [] ? nv_start_xmit_optimized+0x0/0x860 [forcedeth] [] ? netpoll_send_skb_on_dev+0x243/0x250 [] ? netpoll_send_udp+0x229/0x270 [] ? write_msg+0x39/0x110 [netconsole] [] ? write_msg+0xbb/0x110 [netconsole] [] ? __call_console_drivers+0x75/0x90 [] ? _call_console_drivers+0x4a/0x80 [] ? release_console_sem+0xe5/0x250 [] ? register_console+0x190/0x3e0 [] ? init_netconsole+0x1a6/0x216 [netconsole] [] ? init_netconsole+0x0/0x216 [netconsole] [] ? do_one_initcall+0xc0/0x280 [] ? sys_init_module+0xe3/0x260 [] ? system_call_fastpath+0x16/0x1b ---[ end trace f349c7af88e6a6d5 ]--- console [netcon0] enabled netconsole: network logging started Fix it by modifying the forcedeth code to use disable_irq_nosync_lockdep_irqsavedisable_irq_nosync_lockdep_irqsave instead, which saves and restores irq state properly. This also saves us a little code in the process Tested by the reporter, with successful restuls Patch applies to the head of the net tree Signed-off-by: Neil Horman CC: "David S. Miller" Reported-by: Vasily Averin Signed-off-by: David S. Miller --- drivers/net/ethernet/nvidia/forcedeth.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index a41bb5e6b954..75e88f4c1531 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -4076,6 +4076,8 @@ static void nv_do_nic_poll(unsigned long data) struct fe_priv *np = netdev_priv(dev); u8 __iomem *base = get_hwbase(dev); u32 mask = 0; + unsigned long flags; + unsigned int irq = 0; /* * First disable irq(s) and then @@ -4085,25 +4087,27 @@ static void nv_do_nic_poll(unsigned long data) if (!using_multi_irqs(dev)) { if (np->msi_flags & NV_MSI_X_ENABLED) - disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); + irq = np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector; else - disable_irq_lockdep(np->pci_dev->irq); + irq = np->pci_dev->irq; mask = np->irqmask; } else { if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { - disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); + irq = np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector; mask |= NVREG_IRQ_RX_ALL; } if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) { - disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); + irq = np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector; mask |= NVREG_IRQ_TX_ALL; } if (np->nic_poll_irq & NVREG_IRQ_OTHER) { - disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); + irq = np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector; mask |= NVREG_IRQ_OTHER; } } - /* disable_irq() contains synchronize_irq, thus no irq handler can run now */ + + disable_irq_nosync_lockdep_irqsave(irq, &flags); + synchronize_irq(irq); if (np->recover_error) { np->recover_error = 0; @@ -4156,28 +4160,22 @@ static void nv_do_nic_poll(unsigned long data) nv_nic_irq_optimized(0, dev); else nv_nic_irq(0, dev); - if (np->msi_flags & NV_MSI_X_ENABLED) - enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); - else - enable_irq_lockdep(np->pci_dev->irq); } else { if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { np->nic_poll_irq &= ~NVREG_IRQ_RX_ALL; nv_nic_irq_rx(0, dev); - enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); } if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) { np->nic_poll_irq &= ~NVREG_IRQ_TX_ALL; nv_nic_irq_tx(0, dev); - enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); } if (np->nic_poll_irq & NVREG_IRQ_OTHER) { np->nic_poll_irq &= ~NVREG_IRQ_OTHER; nv_nic_irq_other(0, dev); - enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); } } + enable_irq_lockdep_irqrestore(irq, &flags); } #ifdef CONFIG_NET_POLL_CONTROLLER -- cgit v1.2.3 From 20986ed826cbb36bb8f2d77f872e3c52d8d30647 Mon Sep 17 00:00:00 2001 From: "Lendacky, Thomas" Date: Mon, 26 Oct 2015 17:13:54 -0500 Subject: amd-xgbe: Fix race between access of desc and desc index During Tx cleanup it's still possible for the descriptor data to be read ahead of the descriptor index. A memory barrier is required between the read of the descriptor index and the start of the Tx cleanup loop. This allows a change to a lighter-weight barrier in the Tx transmit routine just before updating the current descriptor index. Since the memory barrier does result in extra overhead on arm64, keep the previous change to not chase the current descriptor value. This prevents the execution of the barrier for each loop performed. Suggested-by: Alexander Duyck Signed-off-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 2 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index e9ab8b9f3b9c..f672dba345f7 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -1595,7 +1595,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel) packet->rdesc_count, 1); /* Make sure ownership is written to the descriptor */ - wmb(); + smp_wmb(); ring->cur = cur_index + 1; if (!packet->skb->xmit_more || diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index d2b77d985441..dde0486667e0 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -1816,6 +1816,10 @@ static int xgbe_tx_poll(struct xgbe_channel *channel) return 0; cur = ring->cur; + + /* Be sure we get ring->cur before accessing descriptor data */ + smp_rmb(); + txq = netdev_get_tx_queue(netdev, channel->queue_index); while ((processed < XGBE_TX_DESC_MAX_PROC) && -- cgit v1.2.3 From 8fcc60333ccf5622f1788ab72848e1a880667fe0 Mon Sep 17 00:00:00 2001 From: Abhimanyu Date: Tue, 27 Oct 2015 14:17:43 +0530 Subject: gianfar: Increase TX_TIMEOUT to 5HZ Increased TX_TIMEOUT to 5HZ to accommodate worst case situation for traffic and CPU intensive use cases Signed-off-by: Priyanka Jain Signed-off-by: Abhimanyu Acked-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 7f5389c3c0cf..47f0400ad020 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -107,7 +107,7 @@ #include "gianfar.h" -#define TX_TIMEOUT (1*HZ) +#define TX_TIMEOUT (5*HZ) const char gfar_driver_version[] = "2.0"; -- cgit v1.2.3 From edc9b4272e3298c4a6a86d34d03e951033566f69 Mon Sep 17 00:00:00 2001 From: Li Peng Date: Tue, 27 Oct 2015 17:17:40 +0800 Subject: net: hns: fixes the bug tested XGE by ethtool -p delete action of ETHTOOL_ID_ON/ETHTOOL_ID_OFF in XGE ethtool -p, so Hardware control the LED state instead of software. Signed-off-by: Li Peng Signed-off-by: Yisen Zhuang Signed-off-by: yankejian Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index d611388aecef..523e9b83d304 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -64,17 +64,10 @@ int cpld_set_led_id(struct hns_mac_cb *mac_cb, switch (status) { case HNAE_LED_ACTIVE: mac_cb->cpld_led_value = dsaf_read_b(mac_cb->cpld_vaddr); - return 2; - case HNAE_LED_ON: dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, CPLD_LED_ON_VALUE); dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value); - break; - case HNAE_LED_OFF: - dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, - CPLD_LED_DEFAULT_VALUE); - dsaf_write_b(mac_cb->cpld_vaddr, mac_cb->cpld_led_value); - break; + return 2; case HNAE_LED_INACTIVE: dsaf_set_bit(mac_cb->cpld_led_value, DSAF_LED_ANCHOR_B, CPLD_LED_DEFAULT_VALUE); -- cgit v1.2.3 From 092bf0fc80f5fb7928244ad63d8a2a8df8a72a3e Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Tue, 27 Oct 2015 17:36:19 +0200 Subject: net/mlx4_en: Explicitly set no vlan tags in WQE ctrl segment when no vlan is present We do not set the ins_vlan field to zero when no vlan id is present in the packet. Since WQEs in the TX ring are not zeroed out between uses, this oversight could result in having vlan flags present in the WQE ctrl segment when no vlan is preset. Fixes: e38af4faf01d ('net/mlx4_en: Add support for hardware accelerated 802.1ad vlan') Reported-by: Gideon Naim Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 494e7762fdb1..4421bf5463f6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -964,6 +964,8 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_SVLAN; else if (vlan_proto == ETH_P_8021Q) tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_CVLAN; + else + tx_desc->ctrl.ins_vlan = 0; tx_desc->ctrl.fence_size = real_size; -- cgit v1.2.3 From c02b05011fadf8e409e41910217ca689f2fc9d91 Mon Sep 17 00:00:00 2001 From: Carol L Soto Date: Tue, 27 Oct 2015 17:36:20 +0200 Subject: net/mlx4: Copy/set only sizeof struct mlx4_eqe bytes When doing memcpy/memset of EQEs, we should use sizeof struct mlx4_eqe as the base size and not caps.eqe_size which could be bigger. If caps.eqe_size is bigger than the struct mlx4_eqe then we corrupt data in the master context. When using a 64 byte stride, the memcpy copied over 63 bytes to the slave_eq structure. This resulted in copying over the entire eqe of interest, including its ownership bit -- and also 31 bytes of garbage into the next WQE in the slave EQ -- which did NOT include the ownership bit (and therefore had no impact). However, once the stride is increased to 128, we are overwriting the ownership bits of *three* eqes in the slave_eq struct. This results in an incorrect ownership bit for those eqes, which causes the eq to seem to be full. The issue therefore surfaced only once 128-byte EQEs started being used in SRIOV and (overarchitectures that have 128/256 byte cache-lines such as PPC) - e.g after commit 77507aa249ae "net/mlx4_core: Enable CQE/EQE stride support". Fixes: 08ff32352d6f ('mlx4: 64-byte CQE/EQE support') Signed-off-by: Carol L Soto Signed-off-by: Jack Morgenstein Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/cmd.c | 2 +- drivers/net/ethernet/mellanox/mlx4/eq.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 0a3202047569..2177e56ed0be 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -2398,7 +2398,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev) } } - memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size); + memset(&priv->mfunc.master.cmd_eqe, 0, sizeof(struct mlx4_eqe)); priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD; INIT_WORK(&priv->mfunc.master.comm_work, mlx4_master_comm_channel); diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index c34488479365..603d1c3d3b2e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -196,7 +196,7 @@ static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe) return; } - memcpy(s_eqe, eqe, dev->caps.eqe_size - 1); + memcpy(s_eqe, eqe, sizeof(struct mlx4_eqe) - 1); s_eqe->slave_id = slave; /* ensure all information is written before setting the ownersip bit */ dma_wmb(); -- cgit v1.2.3 From f675f93a797a18fc1f82030d56d02286039d0fb3 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 16 Oct 2015 21:04:13 +0200 Subject: airo: Track APList_rid in struct airo_info Instead of dynamically allocating APList, make it a member of struct airo_info to always track state of APList_rid. This simplifies suspend/resume and allows removal of readAPListRid. Signed-off-by: Ondrej Zary Signed-off-by: Kalle Valo --- drivers/net/wireless/airo.c | 57 +++++++++++++++------------------------------ 1 file changed, 19 insertions(+), 38 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 8ae838d96a9e..4ef2f986888b 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -1231,7 +1231,7 @@ struct airo_info { dma_addr_t shared_dma; pm_message_t power; SsidRid *SSID; - APListRid *APList; + APListRid APList; #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE char proc_name[IFNAMSIZ]; @@ -1848,11 +1848,6 @@ static int readStatusRid(struct airo_info *ai, StatusRid *statr, int lock) return PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock); } -static int readAPListRid(struct airo_info *ai, APListRid *aplr) -{ - return PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1); -} - static int writeAPListRid(struct airo_info *ai, APListRid *aplr, int lock) { return PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock); @@ -2413,7 +2408,6 @@ void stop_airo_card( struct net_device *dev, int freeres ) kfree(ai->flash); kfree(ai->rssi); - kfree(ai->APList); kfree(ai->SSID); if (freeres) { /* PCMCIA frees this stuff, so only for PCI and ISA */ @@ -2809,6 +2803,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, init_waitqueue_head (&ai->thr_wait); ai->tfm = NULL; add_airo_dev(ai); + ai->APList.len = cpu_to_le16(sizeof(struct APListRid)); if (airo_networks_allocate (ai)) goto err_out_free; @@ -3852,8 +3847,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) tdsRssiRid rssi_rid; CapabilityRid cap_rid; - kfree(ai->APList); - ai->APList = NULL; kfree(ai->SSID); ai->SSID = NULL; // general configuration (read/modify/write) @@ -5130,31 +5123,31 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) { struct proc_data *data = file->private_data; struct net_device *dev = PDE_DATA(inode); struct airo_info *ai = dev->ml_priv; - APListRid APList_rid; + APListRid *APList_rid = &ai->APList; int i; if ( !data->writelen ) return; - memset( &APList_rid, 0, sizeof(APList_rid) ); - APList_rid.len = cpu_to_le16(sizeof(APList_rid)); + memset(APList_rid, 0, sizeof(*APList_rid)); + APList_rid->len = cpu_to_le16(sizeof(*APList_rid)); for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) { int j; for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) { switch(j%3) { case 0: - APList_rid.ap[i][j/3]= + APList_rid->ap[i][j/3]= hex_to_bin(data->wbuffer[j+i*6*3])<<4; break; case 1: - APList_rid.ap[i][j/3]|= + APList_rid->ap[i][j/3]|= hex_to_bin(data->wbuffer[j+i*6*3]); break; } } } disable_MAC(ai, 1); - writeAPListRid(ai, &APList_rid, 1); + writeAPListRid(ai, APList_rid, 1); enable_MAC(ai, 1); } @@ -5408,7 +5401,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { struct airo_info *ai = dev->ml_priv; int i; char *ptr; - APListRid APList_rid; + APListRid *APList_rid = &ai->APList; if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; @@ -5426,13 +5419,12 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { } data->on_close = proc_APList_on_close; - readAPListRid(ai, &APList_rid); ptr = data->rbuffer; for( i = 0; i < 4; i++ ) { // We end when we find a zero MAC - if ( !*(int*)APList_rid.ap[i] && - !*(int*)&APList_rid.ap[i][2]) break; - ptr += sprintf(ptr, "%pM\n", APList_rid.ap[i]); + if ( !*(int*)APList_rid->ap[i] && + !*(int*)&APList_rid->ap[i][2]) break; + ptr += sprintf(ptr, "%pM\n", APList_rid->ap[i]); } if (i==0) ptr += sprintf(ptr, "Not using specific APs\n"); @@ -5596,15 +5588,10 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) Cmd cmd; Resp rsp; - if (!ai->APList) - ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL); - if (!ai->APList) - return -ENOMEM; if (!ai->SSID) ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL); if (!ai->SSID) return -ENOMEM; - readAPListRid(ai, ai->APList); readSsidRid(ai, ai->SSID); memset(&cmd, 0, sizeof(cmd)); /* the lock will be released at the end of the resume callback */ @@ -5652,11 +5639,7 @@ static int airo_pci_resume(struct pci_dev *pdev) kfree(ai->SSID); ai->SSID = NULL; } - if (ai->APList) { - writeAPListRid(ai, ai->APList, 0); - kfree(ai->APList); - ai->APList = NULL; - } + writeAPListRid(ai, &ai->APList, 0); writeConfigRid(ai, 0); enable_MAC(ai, 0); ai->power = PMSG_ON; @@ -5954,7 +5937,7 @@ static int airo_set_wap(struct net_device *dev, struct airo_info *local = dev->ml_priv; Cmd cmd; Resp rsp; - APListRid APList_rid; + APListRid *APList_rid = &local->APList; if (awrq->sa_family != ARPHRD_ETHER) return -EINVAL; @@ -5967,11 +5950,11 @@ static int airo_set_wap(struct net_device *dev, issuecommand(local, &cmd, &rsp); up(&local->sem); } else { - memset(&APList_rid, 0, sizeof(APList_rid)); - APList_rid.len = cpu_to_le16(sizeof(APList_rid)); - memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN); + memset(APList_rid, 0, sizeof(*APList_rid)); + APList_rid->len = cpu_to_le16(sizeof(*APList_rid)); + memcpy(APList_rid->ap[0], awrq->sa_data, ETH_ALEN); disable_MAC(local, 1); - writeAPListRid(local, &APList_rid, 1); + writeAPListRid(local, APList_rid, 1); enable_MAC(local, 1); } return 0; @@ -7505,10 +7488,8 @@ static int airo_config_commit(struct net_device *dev, * parameters. It's now time to commit them in the card */ disable_MAC(local, 1); if (test_bit (FLAG_RESET, &local->flags)) { - APListRid APList_rid; SsidRid SSID_rid; - readAPListRid(local, &APList_rid); readSsidRid(local, &SSID_rid); if (test_bit(FLAG_MPI,&local->flags)) setup_card(local, dev->dev_addr, 1 ); @@ -7516,7 +7497,7 @@ static int airo_config_commit(struct net_device *dev, reset_airo_card(dev); disable_MAC(local, 1); writeSsidRid(local, &SSID_rid, 1); - writeAPListRid(local, &APList_rid, 1); + writeAPListRid(local, &local->APList, 1); } if (down_interruptible(&local->sem)) return -ERESTARTSYS; -- cgit v1.2.3 From dae0412d0caa4948da07fe4ad91352b5b61a70ec Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Fri, 16 Oct 2015 21:04:14 +0200 Subject: airo: fix scan after SIOCSIWAP (airo_set_wap) SIOCSIWAP (airo_set_wap) affects scan: only the AP specified by SIOCSIWAP is present in scan results. This makes NetworkManager work for the first time but then unable to find any other APs. Clear APList before starting scan and set it back after scan completes to work-around the problem. To avoid losing packets during scan, modify disable_MAC() to omit netif_carrier_off() call when lock == 2. Signed-off-by: Ondrej Zary Signed-off-by: Kalle Valo --- drivers/net/wireless/airo.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 4ef2f986888b..17c40f06f13e 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -3037,6 +3037,11 @@ static void airo_process_scan_results (struct airo_info *ai) { } out: + /* write APList back (we cleared it in airo_set_scan) */ + disable_MAC(ai, 2); + writeAPListRid(ai, &ai->APList, 0); + enable_MAC(ai, 0); + ai->scan_timeout = 0; clear_bit(JOB_SCAN_RESULTS, &ai->jobs); up(&ai->sem); @@ -3608,17 +3613,18 @@ static void disable_MAC( struct airo_info *ai, int lock ) { Cmd cmd; Resp rsp; - if (lock && down_interruptible(&ai->sem)) + if (lock == 1 && down_interruptible(&ai->sem)) return; if (test_bit(FLAG_ENABLED, &ai->flags)) { - netif_carrier_off(ai->dev); + if (lock != 2) /* lock == 2 means don't disable carrier */ + netif_carrier_off(ai->dev); memset(&cmd, 0, sizeof(cmd)); cmd.cmd = MAC_DISABLE; // disable in case already enabled issuecommand(ai, &cmd, &rsp); clear_bit(FLAG_ENABLED, &ai->flags); } - if (lock) + if (lock == 1) up(&ai->sem); } @@ -7216,6 +7222,7 @@ static int airo_set_scan(struct net_device *dev, Cmd cmd; Resp rsp; int wake = 0; + APListRid APList_rid_empty; /* Note : you may have realised that, as this is a SET operation, * this is privileged and therefore a normal user can't @@ -7233,6 +7240,13 @@ static int airo_set_scan(struct net_device *dev, if (ai->scan_timeout > 0) goto out; + /* Clear APList as it affects scan results */ + memset(&APList_rid_empty, 0, sizeof(APList_rid_empty)); + APList_rid_empty.len = cpu_to_le16(sizeof(APList_rid_empty)); + disable_MAC(ai, 2); + writeAPListRid(ai, &APList_rid_empty, 0); + enable_MAC(ai, 0); + /* Initiate a scan command */ ai->scan_timeout = RUN_AT(3*HZ); memset(&cmd, 0, sizeof(cmd)); -- cgit v1.2.3 From 989b8376f33721f7206dd058330da05972a71384 Mon Sep 17 00:00:00 2001 From: John Linville Date: Mon, 19 Oct 2015 11:15:00 -0400 Subject: orinoco_usb: return error in ezusb_probe when alloc_orinocodev fails The current code exits after alloc_orinocodev, but fails to change the return value to something that indicates the failure. This patch changes the return value to -ENOMEM. https://bugzilla.kernel.org/show_bug.cgi?id=106181 Signed-off-by: John W. Linville Signed-off-by: Kalle Valo --- drivers/net/wireless/orinoco/orinoco_usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index 26a57d773d30..f2cd513d54b2 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c @@ -1576,6 +1576,7 @@ static int ezusb_probe(struct usb_interface *interface, ezusb_hard_reset, NULL); if (!priv) { err("Couldn't allocate orinocodev"); + retval = -ENOMEM; goto exit; } -- cgit v1.2.3 From 56bae464275ac57cbf993f3ed15e96d6e1ec00a2 Mon Sep 17 00:00:00 2001 From: Zefir Kurtisi Date: Tue, 20 Oct 2015 14:19:26 +0200 Subject: ath9k: fix phyerror codes Some of the ath9k_phyerr enums were wrong from the beginning (and even before). Most of the time the codes were used for counters to be displayed over debugfs, which made this a non-functional issue. Some (e.g. ATH9K_PHYERR_FALSE_RADAR_EXT) are used for radar detection and require the correct code to work as intended. This patch includes: a) fixes ATH9K_PHYERR_FALSE_RADAR_EXT: 24 => 36 ATH9K_PHYERR_CCK_LENGTH_ILLEGAL: 32 => 28 ATH9K_PHYERR_CCK_POWER_DROP: 33 => 29 ATH9K_PHYERR_HT_CRC_ERROR: 34 => 32 ATH9K_PHYERR_HT_LENGTH_ILLEGAL: 35 => 33 ATH9K_PHYERR_HT_RATE_ILLEGAL: 36 => 34 b) extensions ATH9K_PHYERR_CCK_BLOCKER = 24 ATH9K_PHYERR_HT_ZLF = 35 ATH9K_PHYERR_GREEN_FIELD = 37 Aside from the correction and completion made in the enum, the patch also extends the display of the related counters in the debugfs. Signed-off-by: Zefir Kurtisi Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/common-debug.c | 14 +++++++++++--- drivers/net/wireless/ath/ath9k/mac.h | 18 +++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath9k/common-debug.c b/drivers/net/wireless/ath/ath9k/common-debug.c index 3b289f933405..84afcf78151f 100644 --- a/drivers/net/wireless/ath/ath9k/common-debug.c +++ b/drivers/net/wireless/ath/ath9k/common-debug.c @@ -207,6 +207,7 @@ static ssize_t read_file_phy_err(struct file *file, char __user *user_buf, PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR); PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE); PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR); + PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING); PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); @@ -214,17 +215,24 @@ static ssize_t read_file_phy_err(struct file *file, char __user *user_buf, PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP); PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE); PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART); - PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT); + + PHY_ERR("CCK-BLOCKER ERR", ATH9K_PHYERR_CCK_BLOCKER); PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING); PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC); PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL); - PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE); - PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART); PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP); + PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE); + PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART); + PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR); PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL); + PHY_ERR("HT-ZLF ERR", ATH9K_PHYERR_HT_ZLF); + + PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT); + PHY_ERR("GREEN-FIELD ERR", ATH9K_PHYERR_GREEN_FIELD); + PHY_ERR("SPECTRAL ERR", ATH9K_PHYERR_SPECTRAL); if (len > size) len = size; diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index e55fa11894b6..7fbf7f965f61 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -209,21 +209,25 @@ enum ath9k_phyerr { ATH9K_PHYERR_OFDM_POWER_DROP = 21, ATH9K_PHYERR_OFDM_SERVICE = 22, ATH9K_PHYERR_OFDM_RESTART = 23, - ATH9K_PHYERR_FALSE_RADAR_EXT = 24, + ATH9K_PHYERR_CCK_BLOCKER = 24, ATH9K_PHYERR_CCK_TIMING = 25, ATH9K_PHYERR_CCK_HEADER_CRC = 26, ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27, + ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 28, + ATH9K_PHYERR_CCK_POWER_DROP = 29, ATH9K_PHYERR_CCK_SERVICE = 30, ATH9K_PHYERR_CCK_RESTART = 31, - ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32, - ATH9K_PHYERR_CCK_POWER_DROP = 33, - ATH9K_PHYERR_HT_CRC_ERROR = 34, - ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35, - ATH9K_PHYERR_HT_RATE_ILLEGAL = 36, + ATH9K_PHYERR_HT_CRC_ERROR = 32, + ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 33, + ATH9K_PHYERR_HT_RATE_ILLEGAL = 34, + ATH9K_PHYERR_HT_ZLF = 35, + + ATH9K_PHYERR_FALSE_RADAR_EXT = 36, + ATH9K_PHYERR_GREEN_FIELD = 37, + ATH9K_PHYERR_SPECTRAL = 38, - ATH9K_PHYERR_SPECTRAL = 38, ATH9K_PHYERR_MAX = 39, }; -- cgit v1.2.3 From 8e8e54c490032f15779d7b199548eb0143b70f0f Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Sat, 24 Oct 2015 13:42:15 -0400 Subject: wcn36xx: introduce per-channel ring buffer locks wcn36xx implements a ring buffer for transmitted frames for each (high and low priority) DMA channel. The ring buffers are lockless: new frames are inserted at the head of the queue, while finished packets are reaped from the tail. Unfortunately, the list manipulations are missing any kind of barriers so are susceptible to various races: for example, a TX completion handler might read an updated desc->ctrl before the head has actually advanced, and then null out the ctl->skb pointer while it is still being used in the TX path. Simplify things here by adding a spin lock when traversing the ring. This change increased stability for me without adding any noticeable overhead on my platform (xperia z). Signed-off-by: Bob Copeland Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/dxe.c | 27 +++++++++++++++++++-------- drivers/net/wireless/ath/wcn36xx/dxe.h | 1 + 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index 086549b732b9..26085f72fc6a 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -79,6 +79,7 @@ static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch) struct wcn36xx_dxe_ctl *cur_ctl = NULL; int i; + spin_lock_init(&ch->lock); for (i = 0; i < ch->desc_num; i++) { cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL); if (!cur_ctl) @@ -345,7 +346,7 @@ void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status) static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) { - struct wcn36xx_dxe_ctl *ctl = ch->tail_blk_ctl; + struct wcn36xx_dxe_ctl *ctl; struct ieee80211_tx_info *info; unsigned long flags; @@ -354,6 +355,8 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) * completely full head and tail are pointing to the same element * and while-do will not make any cycles. */ + spin_lock_irqsave(&ch->lock, flags); + ctl = ch->tail_blk_ctl; do { if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK) break; @@ -365,12 +368,12 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) /* Keep frame until TX status comes */ ieee80211_free_txskb(wcn->hw, ctl->skb); } - spin_lock_irqsave(&ctl->skb_lock, flags); + spin_lock(&ctl->skb_lock); if (wcn->queues_stopped) { wcn->queues_stopped = false; ieee80211_wake_queues(wcn->hw); } - spin_unlock_irqrestore(&ctl->skb_lock, flags); + spin_unlock(&ctl->skb_lock); ctl->skb = NULL; } @@ -379,6 +382,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)); ch->tail_blk_ctl = ctl; + spin_unlock_irqrestore(&ch->lock, flags); } static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) @@ -596,12 +600,14 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, struct wcn36xx_dxe_desc *desc = NULL; struct wcn36xx_dxe_ch *ch = NULL; unsigned long flags; + int ret; ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch; + spin_lock_irqsave(&ch->lock, flags); ctl = ch->head_blk_ctl; - spin_lock_irqsave(&ctl->next->skb_lock, flags); + spin_lock(&ctl->next->skb_lock); /* * If skb is not null that means that we reached the tail of the ring @@ -611,10 +617,11 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, if (NULL != ctl->next->skb) { ieee80211_stop_queues(wcn->hw); wcn->queues_stopped = true; - spin_unlock_irqrestore(&ctl->next->skb_lock, flags); + spin_unlock(&ctl->next->skb_lock); + spin_unlock_irqrestore(&ch->lock, flags); return -EBUSY; } - spin_unlock_irqrestore(&ctl->next->skb_lock, flags); + spin_unlock(&ctl->next->skb_lock); ctl->skb = NULL; desc = ctl->desc; @@ -640,7 +647,8 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, desc = ctl->desc; if (ctl->bd_cpu_addr) { wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n"); - return -EINVAL; + ret = -EINVAL; + goto unlock; } desc->src_addr_l = dma_map_single(NULL, @@ -679,7 +687,10 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, ch->reg_ctrl, ch->def_ctrl); } - return 0; + ret = 0; +unlock: + spin_unlock_irqrestore(&ch->lock, flags); + return ret; } int wcn36xx_dxe_init(struct wcn36xx *wcn) diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h index 35ee7e966bd2..3eca4f9594f2 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.h +++ b/drivers/net/wireless/ath/wcn36xx/dxe.h @@ -243,6 +243,7 @@ struct wcn36xx_dxe_ctl { }; struct wcn36xx_dxe_ch { + spinlock_t lock; /* protects head/tail ptrs */ enum wcn36xx_dxe_ch_type ch_type; void *cpu_addr; dma_addr_t dma_addr; -- cgit v1.2.3 From 072255241d2e3e9c1e23fc693f0333be72adfe2a Mon Sep 17 00:00:00 2001 From: yfw Date: Mon, 26 Oct 2015 10:36:22 +0800 Subject: wcn36xx: Remove warning message when dev is NULL for arm64 dma_alloc. arm64 has requirement that all the dma operations have actual device. Otherwise, following warnning message shown and dma allocation fails: WARNING: CPU: 0 PID: 954 at arch/arm64/mm/dma-mapping.c:106 __dma_alloc+0x24c/0x258() Use an actual device structure for DMA allocation Modules linked in: wcn36xx wcn36xx_platform CPU: 0 PID: 954 Comm: ifconfig Not tainted 4.0.0+ #14 Hardware name: Qualcomm Technologies, Inc. MSM 8916 MTP (DT) Call trace: [] dump_backtrace+0x0/0x124 [] show_stack+0x10/0x1c [] dump_stack+0x80/0xc4 [] warn_slowpath_common+0x98/0xd0 [] warn_slowpath_fmt+0x4c/0x58 [] __dma_alloc+0x248/0x258 [] wcn36xx_dxe_allocate_mem_pools+0xc4/0x108 [wcn36xx] [] wcn36xx_start+0x38/0x240 [wcn36xx] [] ieee80211_do_open+0x1b0/0x9a4 [] ieee80211_open+0x58/0x68 [] __dev_open+0xb0/0x120 [] __dev_change_flags+0x88/0x150 [] dev_change_flags+0x1c/0x5c [] devinet_ioctl+0x644/0x6f0 Signed-off-by: Yin, Fengwei Acked-by: Bjorn Andersson Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wcn36xx/dxe.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index 26085f72fc6a..f8dfa05b290a 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -170,7 +170,7 @@ void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn) wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch); } -static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch) +static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch) { struct wcn36xx_dxe_desc *cur_dxe = NULL; struct wcn36xx_dxe_desc *prev_dxe = NULL; @@ -179,7 +179,7 @@ static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch) int i; size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc); - wcn_ch->cpu_addr = dma_alloc_coherent(NULL, size, &wcn_ch->dma_addr, + wcn_ch->cpu_addr = dma_alloc_coherent(dev, size, &wcn_ch->dma_addr, GFP_KERNEL); if (!wcn_ch->cpu_addr) return -ENOMEM; @@ -271,7 +271,7 @@ static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch) return 0; } -static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl) +static int wcn36xx_dxe_fill_skb(struct device *dev, struct wcn36xx_dxe_ctl *ctl) { struct wcn36xx_dxe_desc *dxe = ctl->desc; struct sk_buff *skb; @@ -280,7 +280,7 @@ static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl) if (skb == NULL) return -ENOMEM; - dxe->dst_addr_l = dma_map_single(NULL, + dxe->dst_addr_l = dma_map_single(dev, skb_tail_pointer(skb), WCN36XX_PKT_SIZE, DMA_FROM_DEVICE); @@ -298,7 +298,7 @@ static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn, cur_ctl = wcn_ch->head_blk_ctl; for (i = 0; i < wcn_ch->desc_num; i++) { - wcn36xx_dxe_fill_skb(cur_ctl); + wcn36xx_dxe_fill_skb(wcn->dev, cur_ctl); cur_ctl = cur_ctl->next; } @@ -361,7 +361,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK) break; if (ctl->skb) { - dma_unmap_single(NULL, ctl->desc->src_addr_l, + dma_unmap_single(wcn->dev, ctl->desc->src_addr_l, ctl->skb->len, DMA_TO_DEVICE); info = IEEE80211_SKB_CB(ctl->skb); if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { @@ -478,7 +478,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) { skb = ctl->skb; dma_addr = dxe->dst_addr_l; - wcn36xx_dxe_fill_skb(ctl); + wcn36xx_dxe_fill_skb(wcn->dev, ctl); switch (ch->ch_type) { case WCN36XX_DXE_CH_RX_L: @@ -495,7 +495,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, wcn36xx_warn("Unknown channel\n"); } - dma_unmap_single(NULL, dma_addr, WCN36XX_PKT_SIZE, + dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE, DMA_FROM_DEVICE); wcn36xx_rx_skb(wcn, skb); ctl = ctl->next; @@ -544,7 +544,7 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) 16 - (WCN36XX_BD_CHUNK_SIZE % 8); s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H; - cpu_addr = dma_alloc_coherent(NULL, s, &wcn->mgmt_mem_pool.phy_addr, + cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->mgmt_mem_pool.phy_addr, GFP_KERNEL); if (!cpu_addr) goto out_err; @@ -559,7 +559,7 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) 16 - (WCN36XX_BD_CHUNK_SIZE % 8); s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L; - cpu_addr = dma_alloc_coherent(NULL, s, &wcn->data_mem_pool.phy_addr, + cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->data_mem_pool.phy_addr, GFP_KERNEL); if (!cpu_addr) goto out_err; @@ -578,13 +578,13 @@ out_err: void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn) { if (wcn->mgmt_mem_pool.virt_addr) - dma_free_coherent(NULL, wcn->mgmt_mem_pool.chunk_size * + dma_free_coherent(wcn->dev, wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H, wcn->mgmt_mem_pool.virt_addr, wcn->mgmt_mem_pool.phy_addr); if (wcn->data_mem_pool.virt_addr) { - dma_free_coherent(NULL, wcn->data_mem_pool.chunk_size * + dma_free_coherent(wcn->dev, wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L, wcn->data_mem_pool.virt_addr, wcn->data_mem_pool.phy_addr); @@ -651,7 +651,7 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, goto unlock; } - desc->src_addr_l = dma_map_single(NULL, + desc->src_addr_l = dma_map_single(wcn->dev, ctl->skb->data, ctl->skb->len, DMA_TO_DEVICE); @@ -707,7 +707,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***************************************/ /* Init descriptors for TX LOW channel */ /***************************************/ - wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch); + wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch); wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool); /* Write channel head to a NEXT register */ @@ -725,7 +725,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***************************************/ /* Init descriptors for TX HIGH channel */ /***************************************/ - wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch); + wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch); wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool); /* Write channel head to a NEXT register */ @@ -745,7 +745,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***************************************/ /* Init descriptors for RX LOW channel */ /***************************************/ - wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch); + wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch); /* For RX we need to preallocated buffers */ wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); @@ -775,7 +775,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) /***************************************/ /* Init descriptors for RX HIGH channel */ /***************************************/ - wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch); + wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch); /* For RX we need to prealocat buffers */ wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch); -- cgit v1.2.3 From 0117e78aec73f1c0869e50d11a255b28aa4db8f0 Mon Sep 17 00:00:00 2001 From: Marty Faltesek Date: Sun, 25 Oct 2015 22:54:01 -0700 Subject: mwifiex: toggle carrier state in start_ap/stop_ap. In uap mode the carrier is not enabled until after the first STA joins. The carrier triggers the bridge to start its state machine, and if STP is enabled, it takes 4 seconds as it transitions from disabled to forwarding. During this time the bridge drops all traffic, and the EAPOL handshake times out after 3 seconds, preventing stations from joining. Follow the logic used in mac80211 and start the carrier in start_ap and disable it in stop_ap. This has a nice benefit of allowing the first station connection time to be reduced by up to 75% when STP is in use. Signed-off-by: Martin Faltesek Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/mwifiex/cfg80211.c | 8 ++++++++ drivers/net/wireless/mwifiex/uap_event.c | 7 ------- 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index b7ac45f324d7..4073116e6e9f 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1821,6 +1821,10 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) return -1; } + if (netif_carrier_ok(priv->netdev)) + netif_carrier_off(priv->netdev); + mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); + return 0; } @@ -1925,6 +1929,10 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) return -1; + if (!netif_carrier_ok(priv->netdev)) + netif_carrier_on(priv->netdev); + mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter); + memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg)); kfree(bss_cfg); return 0; diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 078834cf1251..86ff54296f39 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c @@ -179,19 +179,12 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) case EVENT_UAP_BSS_IDLE: priv->media_connected = false; priv->port_open = false; - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - mwifiex_stop_net_dev_queue(priv->netdev, adapter); - mwifiex_clean_txrx(priv); mwifiex_del_all_sta_list(priv); break; case EVENT_UAP_BSS_ACTIVE: priv->media_connected = true; priv->port_open = true; - if (!netif_carrier_ok(priv->netdev)) - netif_carrier_on(priv->netdev); - mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); break; case EVENT_UAP_BSS_START: mwifiex_dbg(adapter, EVENT, -- cgit v1.2.3 From 399500da18f7fe79699c0e4f603f8874cecb3898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 15 Oct 2015 07:23:25 +0200 Subject: ssb: pick PCMCIA host code support from b43 driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ssb bus can be found on various "host" devices like PCI/PCMCIA/SDIO. Every ssb bus contains cores AKA devices. The main idea is to have ssb driver scan/initialize bus and register ready-to-use cores. This way ssb drivers can operate on a single core mostly ignoring underlaying details. For some reason PCMCIA support was split between ssb and b43. We got PCMCIA host device probing in b43, then bus scanning in ssb and then wireless core probing back in b43. The truth is it's very unlikely we will ever see PCMCIA ssb device with no 802.11 core but I still don't see any advantage of the current architecture. With proposed change we get the same functionality with a simpler architecture, less Kconfig symbols, one killed EXPORT and hopefully cleaner b43. Since b43 supports both: ssb & bcma I prefer to keep ssb specific code in ssb driver. This mostly moves code from b43's pcmcia.c to bridge_pcmcia_80211.c. We already use similar solution with b43_pci_bridge.c. I didn't use "b43" in name of this new file as in theory any driver can operate on wireless core. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/b43/Kconfig | 20 ------ drivers/net/wireless/b43/Makefile | 1 - drivers/net/wireless/b43/main.c | 9 +-- drivers/net/wireless/b43/pcmcia.c | 145 -------------------------------------- drivers/net/wireless/b43/pcmcia.h | 20 ------ 5 files changed, 1 insertion(+), 194 deletions(-) delete mode 100644 drivers/net/wireless/b43/pcmcia.c delete mode 100644 drivers/net/wireless/b43/pcmcia.h (limited to 'drivers/net') diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 759fb8d41fc9..fba856032ca5 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -71,26 +71,6 @@ config B43_PCICORE_AUTOSELECT select SSB_DRIVER_PCICORE default y -config B43_PCMCIA - bool "Broadcom 43xx PCMCIA device support" - depends on B43 && B43_SSB && SSB_PCMCIAHOST_POSSIBLE - select SSB_PCMCIAHOST - ---help--- - Broadcom 43xx PCMCIA device support. - - Support for 16bit PCMCIA devices. - Please note that most PC-CARD devices are _NOT_ 16bit PCMCIA - devices, but 32bit CardBUS devices. CardBUS devices are supported - out of the box by b43. - - With this config option you can drive b43 cards in - CompactFlash formfactor in a PCMCIA adaptor. - CF b43 cards can sometimes be found in handheld PCs. - - It's safe to select Y here, even if you don't have a B43 PCMCIA device. - - If unsure, say N. - config B43_SDIO bool "Broadcom 43xx SDIO device support" depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index c624d4d90e4f..ddc4df46656f 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -21,7 +21,6 @@ b43-y += pio.o b43-y += rfkill.o b43-y += ppr.o b43-$(CONFIG_B43_LEDS) += leds.o -b43-$(CONFIG_B43_PCMCIA) += pcmcia.o b43-$(CONFIG_B43_SDIO) += sdio.o b43-$(CONFIG_B43_DEBUG) += debugfs.o diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 71d3e9adbf3c..ec013fbd6a81 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -56,7 +56,6 @@ #include "sysfs.h" #include "xmit.h" #include "lo.h" -#include "pcmcia.h" #include "sdio.h" #include @@ -5850,12 +5849,9 @@ static int __init b43_init(void) int err; b43_debugfs_init(); - err = b43_pcmcia_init(); - if (err) - goto err_dfs_exit; err = b43_sdio_init(); if (err) - goto err_pcmcia_exit; + goto err_dfs_exit; #ifdef CONFIG_B43_BCMA err = bcma_driver_register(&b43_bcma_driver); if (err) @@ -5878,8 +5874,6 @@ err_bcma_driver_exit: err_sdio_exit: #endif b43_sdio_exit(); -err_pcmcia_exit: - b43_pcmcia_exit(); err_dfs_exit: b43_debugfs_exit(); return err; @@ -5894,7 +5888,6 @@ static void __exit b43_exit(void) bcma_driver_unregister(&b43_bcma_driver); #endif b43_sdio_exit(); - b43_pcmcia_exit(); b43_debugfs_exit(); } diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c deleted file mode 100644 index 55f2bd7f8f74..000000000000 --- a/drivers/net/wireless/b43/pcmcia.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - - Broadcom B43 wireless driver - - Copyright (c) 2007 Michael Buesch - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "pcmcia.h" - -#include -#include -#include - -#include -#include -#include -#include - - -static const struct pcmcia_device_id b43_pcmcia_tbl[] = { - PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), - PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476), - PCMCIA_DEVICE_NULL, -}; - -MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl); - -#ifdef CONFIG_PM -static int b43_pcmcia_suspend(struct pcmcia_device *dev) -{ - struct ssb_bus *ssb = dev->priv; - - return ssb_bus_suspend(ssb); -} - -static int b43_pcmcia_resume(struct pcmcia_device *dev) -{ - struct ssb_bus *ssb = dev->priv; - - return ssb_bus_resume(ssb); -} -#else /* CONFIG_PM */ -# define b43_pcmcia_suspend NULL -# define b43_pcmcia_resume NULL -#endif /* CONFIG_PM */ - -static int b43_pcmcia_probe(struct pcmcia_device *dev) -{ - struct ssb_bus *ssb; - int err = -ENOMEM; - int res = 0; - - ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); - if (!ssb) - goto out_error; - - err = -ENODEV; - - dev->config_flags |= CONF_ENABLE_IRQ; - - dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 | - WIN_USE_WAIT; - dev->resource[2]->start = 0; - dev->resource[2]->end = SSB_CORE_SIZE; - res = pcmcia_request_window(dev, dev->resource[2], 250); - if (res != 0) - goto err_kfree_ssb; - - res = pcmcia_map_mem_page(dev, dev->resource[2], 0); - if (res != 0) - goto err_disable; - - if (!dev->irq) - goto err_disable; - - res = pcmcia_enable_device(dev); - if (res != 0) - goto err_disable; - - err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start); - if (err) - goto err_disable; - dev->priv = ssb; - - return 0; - -err_disable: - pcmcia_disable_device(dev); -err_kfree_ssb: - kfree(ssb); -out_error: - printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n", - res, err); - return err; -} - -static void b43_pcmcia_remove(struct pcmcia_device *dev) -{ - struct ssb_bus *ssb = dev->priv; - - ssb_bus_unregister(ssb); - pcmcia_disable_device(dev); - kfree(ssb); - dev->priv = NULL; -} - -static struct pcmcia_driver b43_pcmcia_driver = { - .owner = THIS_MODULE, - .name = "b43-pcmcia", - .id_table = b43_pcmcia_tbl, - .probe = b43_pcmcia_probe, - .remove = b43_pcmcia_remove, - .suspend = b43_pcmcia_suspend, - .resume = b43_pcmcia_resume, -}; - -/* - * These are not module init/exit functions! - * The module_pcmcia_driver() helper cannot be used here. - */ -int b43_pcmcia_init(void) -{ - return pcmcia_register_driver(&b43_pcmcia_driver); -} - -void b43_pcmcia_exit(void) -{ - pcmcia_unregister_driver(&b43_pcmcia_driver); -} diff --git a/drivers/net/wireless/b43/pcmcia.h b/drivers/net/wireless/b43/pcmcia.h deleted file mode 100644 index 85f120a67cbe..000000000000 --- a/drivers/net/wireless/b43/pcmcia.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef B43_PCMCIA_H_ -#define B43_PCMCIA_H_ - -#ifdef CONFIG_B43_PCMCIA - -int b43_pcmcia_init(void); -void b43_pcmcia_exit(void); - -#else /* CONFIG_B43_PCMCIA */ - -static inline int b43_pcmcia_init(void) -{ - return 0; -} -static inline void b43_pcmcia_exit(void) -{ -} - -#endif /* CONFIG_B43_PCMCIA */ -#endif /* B43_PCMCIA_H_ */ -- cgit v1.2.3 From 62f77f095c27dc6b3536735aa960a8bb21e4c5eb Mon Sep 17 00:00:00 2001 From: Maharaja Date: Wed, 21 Oct 2015 11:49:18 +0300 Subject: ath10k: enable adaptive CCA European Union has made it mandatory that all devices working in 2.4 GHz has to adhere to the ETSI specification (ETSI EN 300 328 V1.9.1) beginnig this year. The standard basically speaks about interferences in 2.4Ghz band. For example, when 802.11 device detects interference, TX must be stopped as long as interference is present. Adaptive CCA is a feature, when enabled the device learns from the environment and configures CCA levels adaptively. This will improve detecting interferences and the device can stop trasmissions till the interference is present eventually leading to good performances in varying interference conditions. The patch includes code for enabling adaptive CCA for 10.2.4 firmware on QCA988X. Signed-off-by: Maharaja Signed-off-by: Manikanta Pubbisetty Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 1 + drivers/net/wireless/ath/ath10k/core.h | 3 +++ drivers/net/wireless/ath/ath10k/mac.c | 12 ++++++++++++ drivers/net/wireless/ath/ath10k/wmi-ops.h | 25 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.c | 31 +++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 13 +++++++++++++ 6 files changed, 85 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 13de3617d5ab..e70e715ae1a7 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -151,6 +151,7 @@ static const char *const ath10k_core_fw_feature_str[] = { [ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad", [ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init", [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode", + [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca", }; static unsigned int ath10k_core_get_fw_feature_str(char *buf, diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 7cc7cdd56c95..3f88aa09086b 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -497,6 +497,9 @@ enum ath10k_fw_features { */ ATH10K_FW_FEATURE_RAW_MODE_SUPPORT = 10, + /* Firmware Supports Adaptive CCA*/ + ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11, + /* keep last */ ATH10K_FW_FEATURE_COUNT, }; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 484c1a10372f..769d7d830770 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3905,6 +3905,18 @@ static int ath10k_start(struct ieee80211_hw *hw) goto err_core_stop; } + if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA, + ar->fw_features)) { + ret = ath10k_wmi_pdev_enable_adaptive_cca(ar, 1, + WMI_CCA_DETECT_LEVEL_AUTO, + WMI_CCA_DETECT_MARGIN_AUTO); + if (ret) { + ath10k_warn(ar, "failed to enable adaptive cca: %d\n", + ret); + goto err_core_stop; + } + } + ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->ani_enable, 1); if (ret) { diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index b54aa08cb25c..8f4f6a892581 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -182,6 +182,10 @@ struct wmi_ops { void (*fw_stats_fill)(struct ath10k *ar, struct ath10k_fw_stats *fw_stats, char *buf); + struct sk_buff *(*gen_pdev_enable_adaptive_cca)(struct ath10k *ar, + u8 enable, + u32 detect_level, + u32 detect_margin); }; int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); @@ -1302,4 +1306,25 @@ ath10k_wmi_fw_stats_fill(struct ath10k *ar, struct ath10k_fw_stats *fw_stats, ar->wmi.ops->fw_stats_fill(ar, fw_stats, buf); return 0; } + +static inline int +ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, + u32 detect_level, u32 detect_margin) +{ + struct sk_buff *skb; + + if (!ar->wmi.ops->gen_pdev_enable_adaptive_cca) + return -EOPNOTSUPP; + + skb = ar->wmi.ops->gen_pdev_enable_adaptive_cca(ar, enable, + detect_level, + detect_margin); + + if (IS_ERR(skb)) + return PTR_ERR(skb); + + return ath10k_wmi_cmd_send(ar, skb, + ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid); +} + #endif diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 6e7d7a7f6a97..2b32f02992f3 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -148,6 +148,7 @@ static struct wmi_cmd_map wmi_cmd_map = { .gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID, .gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID, .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, + .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED, .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, @@ -313,6 +314,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = { .gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID, .gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID, .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, + .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED, .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, @@ -477,6 +479,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = { .gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID, .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, .pdev_get_temperature_cmdid = WMI_10_2_PDEV_GET_TEMPERATURE_CMDID, + .pdev_enable_adaptive_cca_cmdid = WMI_10_2_SET_CCA_PARAMS, .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, @@ -1407,6 +1410,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = { .gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID, .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, + .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED, .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, @@ -6996,6 +7000,28 @@ unlock: buf[len] = 0; } +static struct sk_buff * +ath10k_wmi_op_gen_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, + u32 detect_level, u32 detect_margin) +{ + struct wmi_pdev_set_adaptive_cca_params *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); + if (!skb) + return ERR_PTR(-ENOMEM); + + cmd = (struct wmi_pdev_set_adaptive_cca_params *)skb->data; + cmd->enable = __cpu_to_le32(enable); + cmd->cca_detect_level = __cpu_to_le32(detect_level); + cmd->cca_detect_margin = __cpu_to_le32(detect_margin); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi pdev set adaptive cca params enable:%d detection level:%d detection margin:%d\n", + enable, detect_level, detect_margin); + return skb; +} + static const struct wmi_ops wmi_ops = { .rx = ath10k_wmi_op_rx, .map_svc = wmi_main_svc_map, @@ -7059,6 +7085,7 @@ static const struct wmi_ops wmi_ops = { /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ /* .gen_adaptive_qcs not implemented */ + /* .gen_pdev_enable_adaptive_cca not implemented */ }; static const struct wmi_ops wmi_10_1_ops = { @@ -7125,6 +7152,7 @@ static const struct wmi_ops wmi_10_1_ops = { /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ /* .gen_adaptive_qcs not implemented */ + /* .gen_pdev_enable_adaptive_cca not implemented */ }; static const struct wmi_ops wmi_10_2_ops = { @@ -7188,6 +7216,7 @@ static const struct wmi_ops wmi_10_2_ops = { .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, + /* .gen_pdev_enable_adaptive_cca not implemented */ }; static const struct wmi_ops wmi_10_2_4_ops = { @@ -7251,6 +7280,8 @@ static const struct wmi_ops wmi_10_2_4_ops = { .gen_delba_send = ath10k_wmi_op_gen_delba_send, .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, + .gen_pdev_enable_adaptive_cca = + ath10k_wmi_op_gen_pdev_enable_adaptive_cca, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 6e84d1c1a6ca..c6718e7422f5 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -772,6 +772,7 @@ struct wmi_cmd_map { u32 mu_cal_start_cmdid; u32 set_cca_params_cmdid; u32 pdev_bss_chan_info_request_cmdid; + u32 pdev_enable_adaptive_cca_cmdid; }; /* @@ -1381,6 +1382,9 @@ enum wmi_10_2_cmd_id { WMI_10_2_VDEV_ATF_REQUEST_CMDID, WMI_10_2_PEER_ATF_REQUEST_CMDID, WMI_10_2_PDEV_GET_TEMPERATURE_CMDID, + WMI_10_2_MU_CAL_START_CMDID, + WMI_10_2_SET_LTEU_CONFIG_CMDID, + WMI_10_2_SET_CCA_PARAMS, WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1, }; @@ -6094,6 +6098,15 @@ enum wmi_txbf_conf { WMI_TXBF_CONF_AFTER_ASSOC, }; +#define WMI_CCA_DETECT_LEVEL_AUTO 0 +#define WMI_CCA_DETECT_MARGIN_AUTO 0 + +struct wmi_pdev_set_adaptive_cca_params { + __le32 enable; + __le32 cca_detect_level; + __le32 cca_detect_margin; +} __packed; + struct ath10k; struct ath10k_vif; struct ath10k_fw_stats_pdev; -- cgit v1.2.3 From a81a98cee94519807e826e199bb579a546efa289 Mon Sep 17 00:00:00 2001 From: Alan Liu Date: Wed, 28 Oct 2015 21:38:32 +0200 Subject: ath10k: add FW API support to test mode Add WMI-TLV and FW API support in ath10k testmode. Ath10k can get right wmi command format from UTF image to communicate UTF firmware. Signed-off-by: Alan Liu Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 4 +- drivers/net/wireless/ath/ath10k/core.h | 5 +- drivers/net/wireless/ath/ath10k/hw.h | 1 + drivers/net/wireless/ath/ath10k/testmode.c | 202 ++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 14 ++ 5 files changed, 205 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index e70e715ae1a7..519a1b91f309 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -569,8 +569,8 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode) } break; case ATH10K_FIRMWARE_MODE_UTF: - data = ar->testmode.utf->data; - data_len = ar->testmode.utf->size; + data = ar->testmode.utf_firmware_data; + data_len = ar->testmode.utf_firmware_len; mode_name = "utf"; break; default: diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 3f88aa09086b..9bd264f3031c 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -817,9 +817,12 @@ struct ath10k { struct { /* protected by conf_mutex */ const struct firmware *utf; + char utf_version[32]; + const void *utf_firmware_data; + size_t utf_firmware_len; DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); enum ath10k_fw_wmi_op_version orig_wmi_op_version; - + enum ath10k_fw_wmi_op_version op_version; /* protected by data_lock */ bool utf_monitor; } testmode; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 2d87737e35ff..0c8ea0226684 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -94,6 +94,7 @@ enum qca6174_chip_id_rev { #define ATH10K_FW_API5_FILE "firmware-5.bin" #define ATH10K_FW_UTF_FILE "utf.bin" +#define ATH10K_FW_UTF_API2_FILE "utf-2.bin" /* includes also the null byte */ #define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K" diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index b084f88da102..1d5a2fdcbf56 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -139,11 +139,181 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[]) return cfg80211_testmode_reply(skb); } -static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) +static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) +{ + size_t len, magic_len, ie_len; + struct ath10k_fw_ie *hdr; + char filename[100]; + __le32 *version; + const u8 *data; + int ie_id, ret; + + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE); + + /* load utf firmware image */ + ret = request_firmware(&ar->testmode.utf, filename, ar->dev); + if (ret) { + ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", + filename, ret); + return ret; + } + + data = ar->testmode.utf->data; + len = ar->testmode.utf->size; + + /* FIXME: call release_firmware() in error cases */ + + /* magic also includes the null byte, check that as well */ + magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; + + if (len < magic_len) { + ath10k_err(ar, "utf firmware file is too small to contain magic\n"); + ret = -EINVAL; + goto err; + } + + if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) { + ath10k_err(ar, "invalid firmware magic\n"); + ret = -EINVAL; + goto err; + } + + /* jump over the padding */ + magic_len = ALIGN(magic_len, 4); + + len -= magic_len; + data += magic_len; + + /* loop elements */ + while (len > sizeof(struct ath10k_fw_ie)) { + hdr = (struct ath10k_fw_ie *)data; + + ie_id = le32_to_cpu(hdr->id); + ie_len = le32_to_cpu(hdr->len); + + len -= sizeof(*hdr); + data += sizeof(*hdr); + + if (len < ie_len) { + ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n", + ie_id, len, ie_len); + ret = -EINVAL; + goto err; + } + + switch (ie_id) { + case ATH10K_FW_IE_FW_VERSION: + if (ie_len > sizeof(ar->testmode.utf_version) - 1) + break; + + memcpy(ar->testmode.utf_version, data, ie_len); + ar->testmode.utf_version[ie_len] = '\0'; + + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, + "testmode found fw utf version %s\n", + ar->testmode.utf_version); + break; + case ATH10K_FW_IE_TIMESTAMP: + /* ignore timestamp, but don't warn about it either */ + break; + case ATH10K_FW_IE_FW_IMAGE: + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, + "testmode found fw image ie (%zd B)\n", + ie_len); + + ar->testmode.utf_firmware_data = data; + ar->testmode.utf_firmware_len = ie_len; + break; + case ATH10K_FW_IE_WMI_OP_VERSION: + if (ie_len != sizeof(u32)) + break; + version = (__le32 *)data; + ar->testmode.op_version = le32_to_cpup(version); + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n", + ar->testmode.op_version); + break; + default: + ath10k_warn(ar, "Unknown testmode FW IE: %u\n", + le32_to_cpu(hdr->id)); + break; + } + /* jump over the padding */ + ie_len = ALIGN(ie_len, 4); + + len -= ie_len; + data += ie_len; + } + + if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) { + ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n"); + ret = -EINVAL; + goto err; + } + + return 0; + +err: + release_firmware(ar->testmode.utf); + + return ret; +} + +static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) { char filename[100]; int ret; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); + + /* load utf firmware image */ + ret = request_firmware(&ar->testmode.utf, filename, ar->dev); + if (ret) { + ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", + filename, ret); + return ret; + } + + /* We didn't find FW UTF API 1 ("utf.bin") does not advertise + * firmware features. Do an ugly hack where we force the firmware + * features to match with 10.1 branch so that wmi.c will use the + * correct WMI interface. + */ + + ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + ar->testmode.utf_firmware_data = ar->testmode.utf->data; + ar->testmode.utf_firmware_len = ar->testmode.utf->size; + + return 0; +} + +static int ath10k_tm_fetch_firmware(struct ath10k *ar) +{ + int ret; + + ret = ath10k_tm_fetch_utf_firmware_api_2(ar); + if (ret == 0) { + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2"); + return 0; + } + + ret = ath10k_tm_fetch_utf_firmware_api_1(ar); + if (ret) { + ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret); + return ret; + } + + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1"); + + return 0; +} + +static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) +{ + const char *ver; + int ret; + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n"); mutex_lock(&ar->conf_mutex); @@ -165,36 +335,27 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) goto err; } - snprintf(filename, sizeof(filename), "%s/%s", - ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); - - /* load utf firmware image */ - ret = request_firmware(&ar->testmode.utf, filename, ar->dev); + ret = ath10k_tm_fetch_firmware(ar); if (ret) { - ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", - filename, ret); + ath10k_err(ar, "failed to fetch UTF firmware: %d", ret); goto err; } spin_lock_bh(&ar->data_lock); - ar->testmode.utf_monitor = true; - spin_unlock_bh(&ar->data_lock); - BUILD_BUG_ON(sizeof(ar->fw_features) != sizeof(ar->testmode.orig_fw_features)); memcpy(ar->testmode.orig_fw_features, ar->fw_features, sizeof(ar->fw_features)); ar->testmode.orig_wmi_op_version = ar->wmi.op_version; - - /* utf.bin firmware image does not advertise firmware features. Do - * an ugly hack where we force the firmware features so that wmi.c - * will use the correct WMI interface. - */ memset(ar->fw_features, 0, sizeof(ar->fw_features)); - ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; + + ar->wmi.op_version = ar->testmode.op_version; + + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n", + ar->wmi.op_version); ret = ath10k_hif_power_up(ar); if (ret) { @@ -212,7 +373,12 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ar->state = ATH10K_STATE_UTF; - ath10k_info(ar, "UTF firmware started\n"); + if (strlen(ar->testmode.utf_version) > 0) + ver = ar->testmode.utf_version; + else + ver = "API 1"; + + ath10k_info(ar, "UTF firmware %s started\n", ver); mutex_unlock(&ar->conf_mutex); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 8f835480a62c..6fbd17b69469 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -23,6 +23,7 @@ #include "wmi-ops.h" #include "wmi-tlv.h" #include "p2p.h" +#include "testmode.h" /***************/ /* TLV helpers */ @@ -419,6 +420,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; enum wmi_tlv_event_id id; + bool consumed; cmd_hdr = (struct wmi_cmd_hdr *)skb->data; id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); @@ -428,6 +430,18 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) trace_ath10k_wmi_event(ar, id, skb->data, skb->len); + consumed = ath10k_tm_event_wmi(ar, id, skb); + + /* Ready event must be handled normally also in UTF mode so that we + * know the UTF firmware has booted, others we are just bypass WMI + * events to testmode. + */ + if (consumed && id != WMI_TLV_READY_EVENTID) { + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi tlv testmode consumed 0x%x\n", id); + goto out; + } + switch (id) { case WMI_TLV_MGMT_RX_EVENTID: ath10k_wmi_event_mgmt_rx(ar, skb); -- cgit v1.2.3 From 98dd2b92bb591007e82fb58808f60134ee4479bf Mon Sep 17 00:00:00 2001 From: Manikanta Pubbisetty Date: Wed, 28 Oct 2015 21:38:33 +0200 Subject: ath10k: add fw_stats support to 10.4 firmware This patch adds support for getting firmware debug stats in 10.4 fw. Signed-off-by: Manikanta Pubbisetty Signed-off-by: Tamizh chelvam Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 12 ++ drivers/net/wireless/ath/ath10k/wmi.c | 211 +++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 135 +++++++++++++++++++++ 3 files changed, 358 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 9bd264f3031c..501ac568c9a6 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -214,6 +214,7 @@ struct ath10k_fw_stats_pdev { s32 hw_queued; s32 hw_reaped; s32 underrun; + u32 hw_paused; s32 tx_abort; s32 mpdus_requed; u32 tx_ko; @@ -226,6 +227,16 @@ struct ath10k_fw_stats_pdev { u32 pdev_resets; u32 phy_underrun; u32 txop_ovf; + u32 seq_posted; + u32 seq_failed_queueing; + u32 seq_completed; + u32 seq_restarted; + u32 mu_seq_posted; + u32 mpdus_sw_flush; + u32 mpdus_hw_filter; + u32 mpdus_truncated; + u32 mpdus_ack_failed; + u32 mpdus_expired; /* PDEV RX stats */ s32 mid_ppdu_route_change; @@ -242,6 +253,7 @@ struct ath10k_fw_stats_pdev { s32 phy_errs; s32 phy_err_drop; s32 mpdu_errs; + s32 rx_ovfl_errs; }; struct ath10k_fw_stats { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 2b32f02992f3..8e05e7350ee0 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2479,6 +2479,47 @@ void ath10k_wmi_pull_pdev_stats_tx(const struct wmi_pdev_stats_tx *src, dst->txop_ovf = __le32_to_cpu(src->txop_ovf); } +static void +ath10k_wmi_10_4_pull_pdev_stats_tx(const struct wmi_10_4_pdev_stats_tx *src, + struct ath10k_fw_stats_pdev *dst) +{ + dst->comp_queued = __le32_to_cpu(src->comp_queued); + dst->comp_delivered = __le32_to_cpu(src->comp_delivered); + dst->msdu_enqued = __le32_to_cpu(src->msdu_enqued); + dst->mpdu_enqued = __le32_to_cpu(src->mpdu_enqued); + dst->wmm_drop = __le32_to_cpu(src->wmm_drop); + dst->local_enqued = __le32_to_cpu(src->local_enqued); + dst->local_freed = __le32_to_cpu(src->local_freed); + dst->hw_queued = __le32_to_cpu(src->hw_queued); + dst->hw_reaped = __le32_to_cpu(src->hw_reaped); + dst->underrun = __le32_to_cpu(src->underrun); + dst->tx_abort = __le32_to_cpu(src->tx_abort); + dst->mpdus_requed = __le32_to_cpu(src->mpdus_requed); + dst->tx_ko = __le32_to_cpu(src->tx_ko); + dst->data_rc = __le32_to_cpu(src->data_rc); + dst->self_triggers = __le32_to_cpu(src->self_triggers); + dst->sw_retry_failure = __le32_to_cpu(src->sw_retry_failure); + dst->illgl_rate_phy_err = __le32_to_cpu(src->illgl_rate_phy_err); + dst->pdev_cont_xretry = __le32_to_cpu(src->pdev_cont_xretry); + dst->pdev_tx_timeout = __le32_to_cpu(src->pdev_tx_timeout); + dst->pdev_resets = __le32_to_cpu(src->pdev_resets); + dst->phy_underrun = __le32_to_cpu(src->phy_underrun); + dst->txop_ovf = __le32_to_cpu(src->txop_ovf); + dst->hw_paused = __le32_to_cpu(src->hw_paused); + dst->seq_posted = __le32_to_cpu(src->seq_posted); + dst->seq_failed_queueing = + __le32_to_cpu(src->seq_failed_queueing); + dst->seq_completed = __le32_to_cpu(src->seq_completed); + dst->seq_restarted = __le32_to_cpu(src->seq_restarted); + dst->mu_seq_posted = __le32_to_cpu(src->mu_seq_posted); + dst->mpdus_sw_flush = __le32_to_cpu(src->mpdus_sw_flush); + dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter); + dst->mpdus_truncated = __le32_to_cpu(src->mpdus_truncated); + dst->mpdus_ack_failed = __le32_to_cpu(src->mpdus_ack_failed); + dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter); + dst->mpdus_expired = __le32_to_cpu(src->mpdus_expired); +} + void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src, struct ath10k_fw_stats_pdev *dst) { @@ -2789,6 +2830,86 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, return 0; } +static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, + struct sk_buff *skb, + struct ath10k_fw_stats *stats) +{ + const struct wmi_10_2_stats_event *ev = (void *)skb->data; + u32 num_pdev_stats; + u32 num_pdev_ext_stats; + u32 num_vdev_stats; + u32 num_peer_stats; + int i; + + if (!skb_pull(skb, sizeof(*ev))) + return -EPROTO; + + num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); + num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats); + num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); + num_peer_stats = __le32_to_cpu(ev->num_peer_stats); + + for (i = 0; i < num_pdev_stats; i++) { + const struct wmi_10_4_pdev_stats *src; + struct ath10k_fw_stats_pdev *dst; + + src = (void *)skb->data; + if (!skb_pull(skb, sizeof(*src))) + return -EPROTO; + + dst = kzalloc(sizeof(*dst), GFP_ATOMIC); + if (!dst) + continue; + + ath10k_wmi_pull_pdev_stats_base(&src->base, dst); + ath10k_wmi_10_4_pull_pdev_stats_tx(&src->tx, dst); + ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst); + dst->rx_ovfl_errs = __le32_to_cpu(src->rx_ovfl_errs); + ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst); + + list_add_tail(&dst->list, &stats->pdevs); + } + + for (i = 0; i < num_pdev_ext_stats; i++) { + const struct wmi_10_2_pdev_ext_stats *src; + + src = (void *)skb->data; + if (!skb_pull(skb, sizeof(*src))) + return -EPROTO; + + /* FIXME: expose values to userspace + * + * Note: Even though this loop seems to do nothing it is + * required to parse following sub-structures properly. + */ + } + + /* fw doesn't implement vdev stats */ + + for (i = 0; i < num_peer_stats; i++) { + const struct wmi_10_4_peer_stats *src; + struct ath10k_fw_stats_peer *dst; + + src = (void *)skb->data; + if (!skb_pull(skb, sizeof(*src))) + return -EPROTO; + + dst = kzalloc(sizeof(*dst), GFP_ATOMIC); + if (!dst) + continue; + + ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr); + dst->peer_rssi = __le32_to_cpu(src->peer_rssi); + dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate); + dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); + /* FIXME: expose 10.4 specific values */ + + list_add_tail(&dst->list, &stats->peers); + } + + return 0; +} + void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb) { ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); @@ -4935,6 +5056,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb) ath10k_dbg(ar, ATH10K_DBG_WMI, "received event id %d not implemented\n", id); break; + case WMI_10_4_UPDATE_STATS_EVENTID: + ath10k_wmi_event_update_stats(ar, skb); + break; default: ath10k_warn(ar, "Unknown eventid: %d\n", id); break; @@ -7022,6 +7146,90 @@ ath10k_wmi_op_gen_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, return skb; } +void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf) +{ + u32 len = 0; + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; + const struct ath10k_fw_stats_pdev *pdev; + const struct ath10k_fw_stats_vdev *vdev; + const struct ath10k_fw_stats_peer *peer; + size_t num_peers; + size_t num_vdevs; + + spin_lock_bh(&ar->data_lock); + + pdev = list_first_entry_or_null(&fw_stats->pdevs, + struct ath10k_fw_stats_pdev, list); + if (!pdev) { + ath10k_warn(ar, "failed to get pdev stats\n"); + goto unlock; + } + + num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); + num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); + + ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len); + ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len); + + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "HW paused", pdev->hw_paused); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Seqs posted", pdev->seq_posted); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Seqs failed queueing", pdev->seq_failed_queueing); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Seqs completed", pdev->seq_completed); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Seqs restarted", pdev->seq_restarted); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MU Seqs posted", pdev->mu_seq_posted); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs SW flushed", pdev->mpdus_sw_flush); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs HW filtered", pdev->mpdus_hw_filter); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs truncated", pdev->mpdus_truncated); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs receive no ACK", pdev->mpdus_ack_failed); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "MPDUs expired", pdev->mpdus_expired); + + ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len); + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", + "Num Rx Overflow errors", pdev->rx_ovfl_errs); + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k VDEV stats", num_vdevs); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + list_for_each_entry(vdev, &fw_stats->vdevs, list) { + ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len); + } + + len += scnprintf(buf + len, buf_len - len, "\n"); + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", + "ath10k PEER stats", num_peers); + len += scnprintf(buf + len, buf_len - len, "%30s\n\n", + "================="); + + list_for_each_entry(peer, &fw_stats->peers, list) { + ath10k_wmi_fw_peer_stats_fill(peer, buf, &len); + } + +unlock: + spin_unlock_bh(&ar->data_lock); + + if (len >= buf_len) + buf[len - 1] = 0; + else + buf[len] = 0; +} + static const struct wmi_ops wmi_ops = { .rx = ath10k_wmi_op_rx, .map_svc = wmi_main_svc_map, @@ -7292,6 +7500,7 @@ static const struct wmi_ops wmi_10_4_ops = { .rx = ath10k_wmi_10_4_op_rx, .map_svc = wmi_10_4_svc_map, + .pull_fw_stats = ath10k_wmi_10_4_op_pull_fw_stats, .pull_scan = ath10k_wmi_op_pull_scan_ev, .pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev, .pull_ch_info = ath10k_wmi_10_4_op_pull_ch_info_ev, @@ -7341,9 +7550,11 @@ static const struct wmi_ops wmi_10_4_ops = { .gen_addba_send = ath10k_wmi_op_gen_addba_send, .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill, /* shared with 10.2 */ .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, + .gen_request_stats = ath10k_wmi_op_gen_request_stats, }; int ath10k_wmi_attach(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index c6718e7422f5..72a4ef709577 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -3866,6 +3866,111 @@ struct wmi_pdev_stats_tx { __le32 txop_ovf; } __packed; +struct wmi_10_4_pdev_stats_tx { + /* Num HTT cookies queued to dispatch list */ + __le32 comp_queued; + + /* Num HTT cookies dispatched */ + __le32 comp_delivered; + + /* Num MSDU queued to WAL */ + __le32 msdu_enqued; + + /* Num MPDU queue to WAL */ + __le32 mpdu_enqued; + + /* Num MSDUs dropped by WMM limit */ + __le32 wmm_drop; + + /* Num Local frames queued */ + __le32 local_enqued; + + /* Num Local frames done */ + __le32 local_freed; + + /* Num queued to HW */ + __le32 hw_queued; + + /* Num PPDU reaped from HW */ + __le32 hw_reaped; + + /* Num underruns */ + __le32 underrun; + + /* HW Paused. */ + __le32 hw_paused; + + /* Num PPDUs cleaned up in TX abort */ + __le32 tx_abort; + + /* Num MPDUs requed by SW */ + __le32 mpdus_requed; + + /* excessive retries */ + __le32 tx_ko; + + /* data hw rate code */ + __le32 data_rc; + + /* Scheduler self triggers */ + __le32 self_triggers; + + /* frames dropped due to excessive sw retries */ + __le32 sw_retry_failure; + + /* illegal rate phy errors */ + __le32 illgl_rate_phy_err; + + /* wal pdev continuous xretry */ + __le32 pdev_cont_xretry; + + /* wal pdev tx timeouts */ + __le32 pdev_tx_timeout; + + /* wal pdev resets */ + __le32 pdev_resets; + + /* frames dropped due to non-availability of stateless TIDs */ + __le32 stateless_tid_alloc_failure; + + __le32 phy_underrun; + + /* MPDU is more than txop limit */ + __le32 txop_ovf; + + /* Number of Sequences posted */ + __le32 seq_posted; + + /* Number of Sequences failed queueing */ + __le32 seq_failed_queueing; + + /* Number of Sequences completed */ + __le32 seq_completed; + + /* Number of Sequences restarted */ + __le32 seq_restarted; + + /* Number of MU Sequences posted */ + __le32 mu_seq_posted; + + /* Num MPDUs flushed by SW, HWPAUSED,SW TXABORT(Reset,channel change) */ + __le32 mpdus_sw_flush; + + /* Num MPDUs filtered by HW, all filter condition (TTL expired) */ + __le32 mpdus_hw_filter; + + /* Num MPDUs truncated by PDG + * (TXOP, TBTT, PPDU_duration based on rate, dyn_bw) + */ + __le32 mpdus_truncated; + + /* Num MPDUs that was tried but didn't receive ACK or BA */ + __le32 mpdus_ack_failed; + + /* Num MPDUs that was dropped due to expiry. */ + __le32 mpdus_expired; +} __packed; + struct wmi_pdev_stats_rx { /* Cnts any change in ring routing mid-ppdu */ __le32 mid_ppdu_route_change; @@ -4039,6 +4144,16 @@ struct wmi_10_2_pdev_stats { struct wmi_pdev_stats_extra extra; } __packed; +struct wmi_10_4_pdev_stats { + struct wmi_pdev_stats_base base; + struct wmi_10_4_pdev_stats_tx tx; + struct wmi_pdev_stats_rx rx; + __le32 rx_ovfl_errs; + struct wmi_pdev_stats_mem mem; + __le32 sram_free_size; + struct wmi_pdev_stats_extra extra; +} __packed; + /* * VDEV statistics * TODO: add all VDEV stats here @@ -4080,6 +4195,23 @@ struct wmi_10_2_4_peer_stats { __le32 unknown_value; /* FIXME: what is this word? */ } __packed; +struct wmi_10_4_peer_stats { + struct wmi_mac_addr peer_macaddr; + __le32 peer_rssi; + __le32 peer_rssi_seq_num; + __le32 peer_tx_rate; + __le32 peer_rx_rate; + __le32 current_per; + __le32 retries; + __le32 tx_rate_count; + __le32 max_4ms_frame_len; + __le32 total_sub_frames; + __le32 tx_bytes; + __le32 num_pkt_loss_overflow[4]; + __le32 num_pkt_loss_excess_retry[4]; + __le32 peer_rssi_changed; +} __packed; + struct wmi_10_2_pdev_ext_stats { __le32 rx_rssi_comb; __le32 rx_rssi[4]; @@ -6201,5 +6333,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar, char *buf); size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head); size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head); +void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf); #endif /* _WMI_H_ */ -- cgit v1.2.3 From b4e84c5606f6c91a3fff96c25b9347dc75b2002d Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 23 Oct 2015 18:01:03 +0530 Subject: ath10k: use local memory instead of shadow descriptor in ce_send Currently to avoid uncached memory access while filling up copy engine descriptors, shadow descriptors are used. This can be optimized further by removing shadow descriptors. To achieve that first shadow ring dependency in ce_send is removed by creating local copy of the descriptor on stack and make a one-shot copy into the "uncached" descriptor. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 84220c376308..f63376b3e258 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -274,7 +274,7 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, { struct ath10k *ar = ce_state->ar; struct ath10k_ce_ring *src_ring = ce_state->src_ring; - struct ce_desc *desc, *sdesc; + struct ce_desc *desc, sdesc; unsigned int nentries_mask = src_ring->nentries_mask; unsigned int sw_index = src_ring->sw_index; unsigned int write_index = src_ring->write_index; @@ -294,7 +294,6 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space, write_index); - sdesc = CE_SRC_RING_TO_DESC(src_ring->shadow_base, write_index); desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA); @@ -303,11 +302,11 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, if (flags & CE_SEND_FLAG_BYTE_SWAP) desc_flags |= CE_DESC_FLAGS_BYTE_SWAP; - sdesc->addr = __cpu_to_le32(buffer); - sdesc->nbytes = __cpu_to_le16(nbytes); - sdesc->flags = __cpu_to_le16(desc_flags); + sdesc.addr = __cpu_to_le32(buffer); + sdesc.nbytes = __cpu_to_le16(nbytes); + sdesc.flags = __cpu_to_le16(desc_flags); - *desc = *sdesc; + *desc = sdesc; src_ring->per_transfer_context[write_index] = per_transfer_context; @@ -614,7 +613,7 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, if (read_index == sw_index) return -EIO; - sbase = src_ring->shadow_base; + sbase = src_ring->base_addr_owner_space; sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index); /* Return data from completed source descriptor */ -- cgit v1.2.3 From 1e8f86d9cbe9431dcda36fdd85a9f342d639dca5 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 23 Oct 2015 18:01:04 +0530 Subject: ath10k: remove send completion validation in diag read/write CE diag window access is serialized (it has to be by design) so there's no way to get a different send completion. so there's no need for post completion validation. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 5c05b0cf54a1..6f3c3e0ad907 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -920,16 +920,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, } } - if (nbytes != completed_nbytes) { - ret = -EIO; - goto done; - } - - if (buf != (u32)address) { - ret = -EIO; - goto done; - } - i = 0; while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, &completed_nbytes, @@ -1094,16 +1084,6 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, } } - if (nbytes != completed_nbytes) { - ret = -EIO; - goto done; - } - - if (buf != ce_data) { - ret = -EIO; - goto done; - } - i = 0; while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, &completed_nbytes, -- cgit v1.2.3 From 765952e40dbadd4a74a44f55ac1344c338571bb9 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 23 Oct 2015 18:01:05 +0530 Subject: ath10k: cleanup copy engine send completion The physical address necessary to unmap DMA ('bufferp') is stored in ath10k_skb_cb as 'paddr'. ath10k doesn't rely on the meta/transfer_id when handling send completion (htc ep id is stored in sk_buff control buffer). So the unused output arguments {bufferp, nbytesp and transfer_idp} are removed from CE send completion. This change is needed before removing the shadow copy of copy engine (CE) descriptors in follow up patch. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 24 +++--------------------- drivers/net/wireless/ath/ath10k/ce.h | 10 ++-------- drivers/net/wireless/ath/ath10k/pci.c | 28 +++++++--------------------- 3 files changed, 12 insertions(+), 50 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index f63376b3e258..52021a9d28d7 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -578,17 +578,13 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, * The caller takes responsibility for any necessary locking. */ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, - void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp) + void **per_transfer_contextp) { struct ath10k_ce_ring *src_ring = ce_state->src_ring; u32 ctrl_addr = ce_state->ctrl_addr; struct ath10k *ar = ce_state->ar; unsigned int nentries_mask = src_ring->nentries_mask; unsigned int sw_index = src_ring->sw_index; - struct ce_desc *sdesc, *sbase; unsigned int read_index; if (src_ring->hw_index == sw_index) { @@ -613,15 +609,6 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, if (read_index == sw_index) return -EIO; - sbase = src_ring->base_addr_owner_space; - sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index); - - /* Return data from completed source descriptor */ - *bufferp = __le32_to_cpu(sdesc->addr); - *nbytesp = __le16_to_cpu(sdesc->nbytes); - *transfer_idp = MS(__le16_to_cpu(sdesc->flags), - CE_DESC_FLAGS_META_DATA); - if (per_transfer_contextp) *per_transfer_contextp = src_ring->per_transfer_context[sw_index]; @@ -696,10 +683,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, } int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, - void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp) + void **per_transfer_contextp) { struct ath10k *ar = ce_state->ar; struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -707,9 +691,7 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, spin_lock_bh(&ar_pci->ce_lock); ret = ath10k_ce_completed_send_next_nolock(ce_state, - per_transfer_contextp, - bufferp, nbytesp, - transfer_idp); + per_transfer_contextp); spin_unlock_bh(&ar_pci->ce_lock); return ret; diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index dbb94fdb274b..67f90ec5de53 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -192,16 +192,10 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, * Pops 1 completed send buffer from Source ring. */ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, - void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp); + void **per_transfer_contextp); int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, - void **per_transfer_contextp, - u32 *bufferp, - unsigned int *nbytesp, - unsigned int *transfer_idp); + void **per_transfer_contextp); /*==================CE Engine Initialization=======================*/ diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 6f3c3e0ad907..81000257bc1d 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -910,9 +910,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, goto done; i = 0; - while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, - &completed_nbytes, - &id) != 0) { + while (ath10k_ce_completed_send_next_nolock(ce_diag, + NULL) != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { ret = -EBUSY; @@ -1073,9 +1072,8 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, goto done; i = 0; - while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, - &completed_nbytes, - &id) != 0) { + while (ath10k_ce_completed_send_next_nolock(ce_diag, + NULL) != 0) { mdelay(1); if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { @@ -1139,13 +1137,9 @@ static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state) struct ath10k *ar = ce_state->ar; struct sk_buff_head list; struct sk_buff *skb; - u32 ce_data; - unsigned int nbytes; - unsigned int transfer_id; __skb_queue_head_init(&list); - while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data, - &nbytes, &transfer_id) == 0) { + while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) { /* no need to call tx completion for NULL pointers */ if (skb == NULL) continue; @@ -1215,12 +1209,8 @@ static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state) { struct ath10k *ar = ce_state->ar; struct sk_buff *skb; - u32 ce_data; - unsigned int nbytes; - unsigned int transfer_id; - while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data, - &nbytes, &transfer_id) == 0) { + while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) { /* no need to call tx completion for NULL pointers */ if (!skb) continue; @@ -1796,12 +1786,8 @@ err_dma: static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state) { struct bmi_xfer *xfer; - u32 ce_data; - unsigned int nbytes; - unsigned int transfer_id; - if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer, &ce_data, - &nbytes, &transfer_id)) + if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer)) return; xfer->tx_done = true; -- cgit v1.2.3 From b4c306d0c53ec1b444a4da1f1a3fefaace6b486e Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 23 Oct 2015 18:01:06 +0530 Subject: ath10k: remove shadow copy of CE descriptors for source ring For the messages from host to target, shadow copy of CE descriptors are maintained in source ring. Before writing actual CE descriptor, first shadow copy is filled and then it is copied to CE address space. To optimize in download path and to reduce d-cache pressure, removing shadow copy of CE descriptors. This will also reduce driver memory consumption by 33KB during on device probing. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ce.c | 22 ---------------------- drivers/net/wireless/ath/ath10k/ce.h | 6 ------ drivers/net/wireless/ath/ath10k/pci.c | 5 ----- 3 files changed, 33 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 52021a9d28d7..edf3629288bc 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -921,27 +921,6 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, src_ring->base_addr_ce_space_unaligned, CE_DESC_RING_ALIGN); - /* - * Also allocate a shadow src ring in regular - * mem to use for faster access. - */ - src_ring->shadow_base_unaligned = - kmalloc((nentries * sizeof(struct ce_desc) + - CE_DESC_RING_ALIGN), GFP_KERNEL); - if (!src_ring->shadow_base_unaligned) { - dma_free_coherent(ar->dev, - (nentries * sizeof(struct ce_desc) + - CE_DESC_RING_ALIGN), - src_ring->base_addr_owner_space, - src_ring->base_addr_ce_space); - kfree(src_ring); - return ERR_PTR(-ENOMEM); - } - - src_ring->shadow_base = PTR_ALIGN( - src_ring->shadow_base_unaligned, - CE_DESC_RING_ALIGN); - return src_ring; } @@ -1120,7 +1099,6 @@ void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id) struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; if (ce_state->src_ring) { - kfree(ce_state->src_ring->shadow_base_unaligned); dma_free_coherent(ar->dev, (ce_state->src_ring->nentries * sizeof(struct ce_desc) + diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 67f90ec5de53..47b734ce7ecf 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -100,12 +100,6 @@ struct ath10k_ce_ring { /* CE address space */ u32 base_addr_ce_space; - /* - * Start of shadow copy of descriptors, within regular memory. - * Aligned to descriptor-size boundary. - */ - void *shadow_base_unaligned; - struct ce_desc *shadow_base; /* keep last */ void *per_transfer_context[0]; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 81000257bc1d..4a6538508e9d 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1594,7 +1594,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) struct ath10k_pci *ar_pci; struct ath10k_ce_pipe *ce_pipe; struct ath10k_ce_ring *ce_ring; - struct ce_desc *ce_desc; struct sk_buff *skb; int i; @@ -1609,10 +1608,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) if (!pci_pipe->buf_sz) return; - ce_desc = ce_ring->shadow_base; - if (WARN_ON(!ce_desc)) - return; - for (i = 0; i < ce_ring->nentries; i++) { skb = ce_ring->per_transfer_context[i]; if (!skb) -- cgit v1.2.3 From 166de3f1895dfc49d1f16cc39fd76dab6d7961d2 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 27 Oct 2015 17:51:11 +0530 Subject: ath10k: remove supported chain mask Removing supported chainmask fields as it can be always derived from num_rf_chains. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 2 -- drivers/net/wireless/ath/ath10k/mac.c | 17 +++++------------ drivers/net/wireless/ath/ath10k/wmi.c | 6 ++++-- 3 files changed, 9 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 501ac568c9a6..4a2301589902 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -745,8 +745,6 @@ struct ath10k { int num_started_vdevs; /* Protected by conf-mutex */ - u8 supp_tx_chainmask; - u8 supp_rx_chainmask; u8 cfg_tx_chainmask; u8 cfg_rx_chainmask; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 769d7d830770..352e80bc3f16 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3736,13 +3736,8 @@ static int ath10k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) mutex_lock(&ar->conf_mutex); - if (ar->cfg_tx_chainmask) { - *tx_ant = ar->cfg_tx_chainmask; - *rx_ant = ar->cfg_rx_chainmask; - } else { - *tx_ant = ar->supp_tx_chainmask; - *rx_ant = ar->supp_rx_chainmask; - } + *tx_ant = ar->cfg_tx_chainmask; + *rx_ant = ar->cfg_rx_chainmask; mutex_unlock(&ar->conf_mutex); @@ -3884,9 +3879,7 @@ static int ath10k_start(struct ieee80211_hw *hw) } } - if (ar->cfg_tx_chainmask) - __ath10k_set_antenna(ar, ar->cfg_tx_chainmask, - ar->cfg_rx_chainmask); + __ath10k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask); /* * By default FW set ARP frames ac to voice (6). In that case ARP @@ -7169,8 +7162,8 @@ int ath10k_mac_register(struct ath10k *ar) BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MESH_POINT); - ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask; - ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask; + ar->hw->wiphy->available_antennas_rx = ar->cfg_rx_chainmask; + ar->hw->wiphy->available_antennas_tx = ar->cfg_tx_chainmask; if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features)) ar->hw->wiphy->interface_modes |= diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 8e05e7350ee0..7569db0f69b5 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -4460,8 +4460,10 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) ar->num_rf_chains = ar->max_spatial_stream; } - ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1; - ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1; + if (!ar->cfg_tx_chainmask) { + ar->cfg_tx_chainmask = (1 << ar->num_rf_chains) - 1; + ar->cfg_rx_chainmask = (1 << ar->num_rf_chains) - 1; + } if (strlen(ar->hw->wiphy->fw_version) == 0) { snprintf(ar->hw->wiphy->fw_version, -- cgit v1.2.3 From 7a1d70ab05488146d20cfc8fb9e4acfd132c7bf5 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 27 Oct 2015 17:51:12 +0530 Subject: ath10k: fill HT/VHT MCS rateset only for configured chainmask HT/VHT MCS rateset should be filled only for configured chainmask rather that max supported chainmask. Fix that by checking configured chainmask while filling HT/VHT MCS rate map. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 352e80bc3f16..c200a87d28c7 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6984,7 +6984,7 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) mcs_map = 0; for (i = 0; i < 8; i++) { - if (i < ar->num_rf_chains) + if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i))) mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2); else mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2); @@ -7051,8 +7051,10 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK) ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; - for (i = 0; i < ar->num_rf_chains; i++) - ht_cap.mcs.rx_mask[i] = 0xFF; + for (i = 0; i < ar->num_rf_chains; i++) { + if (ar->cfg_rx_chainmask & BIT(i)) + ht_cap.mcs.rx_mask[i] = 0xFF; + } ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; -- cgit v1.2.3 From f58512f336bbb166610be4a4c42ec1184edcd426 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 27 Oct 2015 17:51:13 +0530 Subject: ath10k: move static HT/VHT capability setup functions Move HT and VHT capabiltity setup static functions to avoid forward declaration. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 280 +++++++++++++++++----------------- 1 file changed, 140 insertions(+), 140 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index c200a87d28c7..4e535e2ef23f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3757,6 +3757,146 @@ static void ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char *dbg) dbg, cm); } +static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar) +{ + int nsts = ar->vht_cap_info; + + nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; + nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; + + /* If firmware does not deliver to host number of space-time + * streams supported, assume it support up to 4 BF STS and return + * the value for VHT CAP: nsts-1) + */ + if (nsts == 0) + return 3; + + return nsts; +} + +static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar) +{ + int sound_dim = ar->vht_cap_info; + + sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; + sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; + + /* If the sounding dimension is not advertised by the firmware, + * let's use a default value of 1 + */ + if (sound_dim == 0) + return 1; + + return sound_dim; +} + +static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) +{ + struct ieee80211_sta_vht_cap vht_cap = {0}; + u16 mcs_map; + u32 val; + int i; + + vht_cap.vht_supported = 1; + vht_cap.cap = ar->vht_cap_info; + + if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | + IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { + val = ath10k_mac_get_vht_cap_bf_sts(ar); + val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; + val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; + + vht_cap.cap |= val; + } + + if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | + IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) { + val = ath10k_mac_get_vht_cap_bf_sound_dim(ar); + val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; + val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; + + vht_cap.cap |= val; + } + + mcs_map = 0; + for (i = 0; i < 8; i++) { + if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i))) + mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2); + else + mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); + } + + vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); + vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); + + return vht_cap; +} + +static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) +{ + int i; + struct ieee80211_sta_ht_cap ht_cap = {0}; + + if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED)) + return ht_cap; + + ht_cap.ht_supported = 1; + ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; + ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; + ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; + ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT; + + if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI) + ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; + + if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI) + ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + + if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) { + u32 smps; + + smps = WLAN_HT_CAP_SM_PS_DYNAMIC; + smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT; + + ht_cap.cap |= smps; + } + + if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC) + ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; + + if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) { + u32 stbc; + + stbc = ar->ht_cap_info; + stbc &= WMI_HT_CAP_RX_STBC; + stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT; + stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT; + stbc &= IEEE80211_HT_CAP_RX_STBC; + + ht_cap.cap |= stbc; + } + + if (ar->ht_cap_info & WMI_HT_CAP_LDPC) + ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; + + if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT) + ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT; + + /* max AMSDU is implicitly taken from vht_cap_info */ + if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK) + ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; + + for (i = 0; i < ar->num_rf_chains; i++) { + if (ar->cfg_rx_chainmask & BIT(i)) + ht_cap.mcs.rx_mask[i] = 0xFF; + } + + ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; + + return ht_cap; +} + static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant) { int ret; @@ -4068,39 +4208,6 @@ static u32 get_nss_from_chainmask(u16 chain_mask) return 1; } -static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar) -{ - int nsts = ar->vht_cap_info; - - nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; - nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; - - /* If firmware does not deliver to host number of space-time - * streams supported, assume it support up to 4 BF STS and return - * the value for VHT CAP: nsts-1) - * */ - if (nsts == 0) - return 3; - - return nsts; -} - -static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar) -{ - int sound_dim = ar->vht_cap_info; - - sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; - sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; - - /* If the sounding dimension is not advertised by the firmware, - * let's use a default value of 1 - */ - if (sound_dim == 0) - return 1; - - return sound_dim; -} - static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif) { u32 value = 0; @@ -6954,113 +7061,6 @@ static const struct ieee80211_iface_combination ath10k_10_4_if_comb[] = { }, }; -static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) -{ - struct ieee80211_sta_vht_cap vht_cap = {0}; - u16 mcs_map; - u32 val; - int i; - - vht_cap.vht_supported = 1; - vht_cap.cap = ar->vht_cap_info; - - if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | - IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { - val = ath10k_mac_get_vht_cap_bf_sts(ar); - val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; - val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; - - vht_cap.cap |= val; - } - - if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | - IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) { - val = ath10k_mac_get_vht_cap_bf_sound_dim(ar); - val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; - val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; - - vht_cap.cap |= val; - } - - mcs_map = 0; - for (i = 0; i < 8; i++) { - if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i))) - mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2); - else - mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2); - } - - vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); - vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); - - return vht_cap; -} - -static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) -{ - int i; - struct ieee80211_sta_ht_cap ht_cap = {0}; - - if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED)) - return ht_cap; - - ht_cap.ht_supported = 1; - ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; - ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; - ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; - ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT; - - if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI) - ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; - - if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI) - ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; - - if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) { - u32 smps; - - smps = WLAN_HT_CAP_SM_PS_DYNAMIC; - smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT; - - ht_cap.cap |= smps; - } - - if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC) - ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; - - if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) { - u32 stbc; - - stbc = ar->ht_cap_info; - stbc &= WMI_HT_CAP_RX_STBC; - stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT; - stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT; - stbc &= IEEE80211_HT_CAP_RX_STBC; - - ht_cap.cap |= stbc; - } - - if (ar->ht_cap_info & WMI_HT_CAP_LDPC) - ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; - - if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT) - ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT; - - /* max AMSDU is implicitly taken from vht_cap_info */ - if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK) - ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; - - for (i = 0; i < ar->num_rf_chains; i++) { - if (ar->cfg_rx_chainmask & BIT(i)) - ht_cap.mcs.rx_mask[i] = 0xFF; - } - - ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; - - return ht_cap; -} - static void ath10k_get_arvif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { -- cgit v1.2.3 From 5036fe0f6fae8a961745f5cf8d82a2a4912ae1ef Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 27 Oct 2015 17:51:14 +0530 Subject: ath10k: reload HT/VHT capabilities on antenna change To reflect configured antenna settings in HT/VHT MCS map, reload the HT/VHT capabilities upon antenna change. Signed-off-by: Rajkumar Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 39 +++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 4e535e2ef23f..a7411fe90cc4 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3897,6 +3897,29 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) return ht_cap; } +static void ath10k_mac_setup_ht_vht_cap(struct ath10k *ar) +{ + struct ieee80211_supported_band *band; + struct ieee80211_sta_vht_cap vht_cap; + struct ieee80211_sta_ht_cap ht_cap; + + ht_cap = ath10k_get_ht_cap(ar); + vht_cap = ath10k_create_vht_cap(ar); + + if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) { + band = &ar->mac.sbands[IEEE80211_BAND_2GHZ]; + band->ht_cap = ht_cap; + + /* Enable the VHT support at 2.4 GHz */ + band->vht_cap = vht_cap; + } + if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) { + band = &ar->mac.sbands[IEEE80211_BAND_5GHZ]; + band->ht_cap = ht_cap; + band->vht_cap = vht_cap; + } +} + static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant) { int ret; @@ -3929,6 +3952,9 @@ static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant) return ret; } + /* Reload HT/VHT capability */ + ath10k_mac_setup_ht_vht_cap(ar); + return 0; } @@ -7102,8 +7128,6 @@ int ath10k_mac_register(struct ath10k *ar) WLAN_CIPHER_SUITE_AES_CMAC, }; struct ieee80211_supported_band *band; - struct ieee80211_sta_vht_cap vht_cap; - struct ieee80211_sta_ht_cap ht_cap; void *channels; int ret; @@ -7111,9 +7135,6 @@ int ath10k_mac_register(struct ath10k *ar) SET_IEEE80211_DEV(ar->hw, ar->dev); - ht_cap = ath10k_get_ht_cap(ar); - vht_cap = ath10k_create_vht_cap(ar); - BUILD_BUG_ON((ARRAY_SIZE(ath10k_2ghz_channels) + ARRAY_SIZE(ath10k_5ghz_channels)) != ATH10K_NUM_CHANS); @@ -7132,10 +7153,6 @@ int ath10k_mac_register(struct ath10k *ar) band->channels = channels; band->n_bitrates = ath10k_g_rates_size; band->bitrates = ath10k_g_rates; - band->ht_cap = ht_cap; - - /* Enable the VHT support at 2.4 GHz */ - band->vht_cap = vht_cap; ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; } @@ -7154,11 +7171,11 @@ int ath10k_mac_register(struct ath10k *ar) band->channels = channels; band->n_bitrates = ath10k_a_rates_size; band->bitrates = ath10k_a_rates; - band->ht_cap = ht_cap; - band->vht_cap = vht_cap; ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band; } + ath10k_mac_setup_ht_vht_cap(ar); + ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | -- cgit v1.2.3 From a226b519d43a2a6b37267fea051aacb4a79c9614 Mon Sep 17 00:00:00 2001 From: Bartosz Markowski Date: Wed, 28 Oct 2015 15:09:53 +0100 Subject: ath10k: add QCA9377 chipset support Add the hardware name, revision and update the pci_id table. Currently there're two HW ref. designs available I'm aware of, with 1.0.2 and 1.1 chip revisions. I've access and been using the first one so far and this patch cover only it. QCA9377 inherits most of the stuff (e.g. fw interfaces) from QCA61x4 design, so the integration was pretty straightforward. Signed-off-by: Bartosz Markowski Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 16 ++++++++++++++++ drivers/net/wireless/ath/ath10k/hw.h | 11 +++++++++++ drivers/net/wireless/ath/ath10k/pci.c | 18 ++++++++++++++++++ drivers/net/wireless/ath/ath10k/targaddrs.h | 3 +++ 4 files changed, 48 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 519a1b91f309..aa9bd92ac4ed 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -137,6 +137,21 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, }, }, + { + .id = QCA9377_HW_1_0_DEV_VERSION, + .name = "qca9377 hw1.0", + .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .otp_exe_param = 0, + .fw = { + .dir = QCA9377_HW_1_0_FW_DIR, + .fw = QCA9377_HW_1_0_FW_FILE, + .otp = QCA9377_HW_1_0_OTP_FILE, + .board = QCA9377_HW_1_0_BOARD_DATA_FILE, + .board_size = QCA9377_BOARD_DATA_SZ, + .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, + }, + }, }; static const char *const ath10k_core_fw_feature_str[] = { @@ -1901,6 +1916,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ar->hw_values = &qca988x_values; break; case ATH10K_HW_QCA6174: + case ATH10K_HW_QCA9377: ar->regs = &qca6174_regs; ar->hw_values = &qca6174_values; break; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 0c8ea0226684..39966a05c1cc 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -84,6 +84,15 @@ enum qca6174_chip_id_rev { #define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin" #define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234 +/* QCA9377 1.0 definitions */ +#define QCA9377_HW_1_0_DEV_VERSION 0x05020001 +#define QCA9377_HW_1_0_CHIP_ID_REV 0x1 +#define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0" +#define QCA9377_HW_1_0_FW_FILE "firmware.bin" +#define QCA9377_HW_1_0_OTP_FILE "otp.bin" +#define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin" +#define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234 + #define ATH10K_FW_API2_FILE "firmware-2.bin" #define ATH10K_FW_API3_FILE "firmware-3.bin" @@ -177,6 +186,7 @@ enum ath10k_hw_rev { ATH10K_HW_QCA988X, ATH10K_HW_QCA6174, ATH10K_HW_QCA99X0, + ATH10K_HW_QCA9377, }; struct ath10k_hw_regs { @@ -229,6 +239,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, #define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X) #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174) #define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0) +#define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377) /* Known pecularities: * - raw appears in nwifi decap, raw and nwifi appear in ethernet decap diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 4a6538508e9d..3fca200b986c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -61,12 +61,14 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)"); #define QCA6164_2_1_DEVICE_ID (0x0041) #define QCA6174_2_1_DEVICE_ID (0x003e) #define QCA99X0_2_0_DEVICE_ID (0x0040) +#define QCA9377_1_0_DEVICE_ID (0x0042) static const struct pci_device_id ath10k_pci_id_table[] = { { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */ { PCI_VDEVICE(ATHEROS, QCA6164_2_1_DEVICE_ID) }, /* PCI-E QCA6164 V2.1 */ { PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */ { PCI_VDEVICE(ATHEROS, QCA99X0_2_0_DEVICE_ID) }, /* PCI-E QCA99X0 V2 */ + { PCI_VDEVICE(ATHEROS, QCA9377_1_0_DEVICE_ID) }, /* PCI-E QCA9377 V1 */ {0} }; @@ -90,6 +92,7 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = { { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV }, { QCA99X0_2_0_DEVICE_ID, QCA99X0_HW_2_0_CHIP_ID_REV }, + { QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_0_CHIP_ID_REV }, }; static void ath10k_pci_buffer_cleanup(struct ath10k *ar); @@ -827,6 +830,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) switch (ar->hw_rev) { case ATH10K_HW_QCA988X: case ATH10K_HW_QCA6174: + case ATH10K_HW_QCA9377: val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS) & 0x7ff) << 21; @@ -1483,6 +1487,7 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) switch (ar->hw_rev) { case ATH10K_HW_QCA988X: case ATH10K_HW_QCA6174: + case ATH10K_HW_QCA9377: val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); val &= ~CORE_CTRL_PCIE_REG_31_MASK; @@ -1504,6 +1509,7 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar) switch (ar->hw_rev) { case ATH10K_HW_QCA988X: case ATH10K_HW_QCA6174: + case ATH10K_HW_QCA9377: val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); val |= CORE_CTRL_PCIE_REG_31_MASK; @@ -1872,6 +1878,8 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar) return 9; } break; + case QCA9377_1_0_DEVICE_ID: + return 2; } ath10k_warn(ar, "unknown number of banks, assuming 1\n"); @@ -2332,6 +2340,8 @@ static int ath10k_pci_chip_reset(struct ath10k *ar) return ath10k_pci_qca988x_chip_reset(ar); else if (QCA_REV_6174(ar)) return ath10k_pci_qca6174_chip_reset(ar); + else if (QCA_REV_9377(ar)) + return ath10k_pci_qca6174_chip_reset(ar); else if (QCA_REV_99X0(ar)) return ath10k_pci_qca99x0_chip_reset(ar); else @@ -2964,6 +2974,10 @@ static int ath10k_pci_probe(struct pci_dev *pdev, hw_rev = ATH10K_HW_QCA99X0; pci_ps = false; break; + case QCA9377_1_0_DEVICE_ID: + hw_rev = ATH10K_HW_QCA9377; + pci_ps = true; + break; default: WARN_ON(1); return -ENOTSUPP; @@ -3165,3 +3179,7 @@ MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE); MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API5_FILE); MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE); MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_BOARD_API2_FILE); + +/* QCA9377 1.0 firmware files */ +MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" ATH10K_FW_API5_FILE); +MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" QCA9377_HW_1_0_BOARD_DATA_FILE); diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h index 768bef629099..05a421bc322a 100644 --- a/drivers/net/wireless/ath/ath10k/targaddrs.h +++ b/drivers/net/wireless/ath/ath10k/targaddrs.h @@ -450,6 +450,9 @@ Fw Mode/SubMode Mask #define QCA6174_BOARD_DATA_SZ 8192 #define QCA6174_BOARD_EXT_DATA_SZ 0 +#define QCA9377_BOARD_DATA_SZ QCA6174_BOARD_DATA_SZ +#define QCA9377_BOARD_EXT_DATA_SZ 0 + #define QCA99X0_BOARD_DATA_SZ 12288 #define QCA99X0_BOARD_EXT_DATA_SZ 0 -- cgit v1.2.3 From b03fbab0c4d502510400b7ee5fb3d5bab6d859bf Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 25 Oct 2015 15:59:21 +0200 Subject: wil6210: ignore selected WMI events Some events are ignored for purpose; such events should not be treated as "unhandled events". Replace info message saying "unhandled" with debug one saying "ignore", to reduce dmesg pollution Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/wmi.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 61121892c6ca..361f3d8f7b43 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -684,6 +684,15 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) spin_unlock_bh(&sta->tid_rx_lock); } +/** + * Some events are ignored for purpose; and need not be interpreted as + * "unhandled events" + */ +static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len) +{ + wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len); +} + static const struct { int eventid; void (*handler)(struct wil6210_priv *wil, int eventid, @@ -701,6 +710,7 @@ static const struct { {WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req}, {WMI_DELBA_EVENTID, wmi_evt_delba}, {WMI_VRING_EN_EVENTID, wmi_evt_vring_en}, + {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_ignore}, }; /* -- cgit v1.2.3 From e3d2ed9434331dedb9eeece586d38aec9e29f60b Mon Sep 17 00:00:00 2001 From: Hamad Kadmany Date: Sun, 25 Oct 2015 15:59:22 +0200 Subject: wil6210: Fix TSO overflow handling When Tx ring full is encountered with TSO, printout of "DMA error" was wrongly printed. In addition, in case of Tx ring full return proper error code so that NETDEV_TX_BUSY is returned to network stack in order not to drop the packets and retry transmission of the packets when ring is emptied. Signed-off-by: Hamad Kadmany Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/txrx.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 0f8b6877497e..3bc9bc0efbac 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -1242,6 +1242,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, int tcp_hdr_len; int skb_net_hdr_len; int gso_type; + int rc = -EINVAL; wil_dbg_txrx(wil, "%s() %d bytes to vring %d\n", __func__, skb->len, vring_index); @@ -1333,8 +1334,9 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, len, rem_data, descs_used); if (descs_used == avail) { - wil_err(wil, "TSO: ring overflow\n"); - goto dma_error; + wil_err_ratelimited(wil, "TSO: ring overflow\n"); + rc = -ENOMEM; + goto mem_error; } lenmss = min_t(int, rem_data, len); @@ -1356,8 +1358,10 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, headlen -= lenmss; } - if (unlikely(dma_mapping_error(dev, pa))) - goto dma_error; + if (unlikely(dma_mapping_error(dev, pa))) { + wil_err(wil, "TSO: DMA map page error\n"); + goto mem_error; + } _desc = &vring->va[i].tx; @@ -1456,8 +1460,8 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, } /* advance swhead */ - wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead); wil_vring_advance_head(vring, descs_used); + wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead); /* make sure all writes to descriptors (shared memory) are done before * committing them to HW @@ -1467,8 +1471,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, wil_w(wil, vring->hwtail, vring->swhead); return 0; -dma_error: - wil_err(wil, "TSO: DMA map page error\n"); +mem_error: while (descs_used > 0) { struct wil_ctx *ctx; @@ -1479,14 +1482,11 @@ dma_error: _desc->dma.status = TX_DMA_STATUS_DU; ctx = &vring->ctx[i]; wil_txdesc_unmap(dev, d, ctx); - if (ctx->skb) - dev_kfree_skb_any(ctx->skb); memset(ctx, 0, sizeof(*ctx)); descs_used--; } - err_exit: - return -EINVAL; + return rc; } static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, @@ -1562,8 +1562,11 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, _d = &vring->va[i].tx; pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, pa))) + if (unlikely(dma_mapping_error(dev, pa))) { + wil_err(wil, "Tx[%2d] failed to map fragment\n", + vring_index); goto dma_error; + } vring->ctx[i].mapped_as = wil_mapped_as_page; wil_tx_desc_map(d, pa, len, vring_index); /* no need to check return code - @@ -1623,9 +1626,6 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, _d->dma.status = TX_DMA_STATUS_DU; wil_txdesc_unmap(dev, d, ctx); - if (ctx->skb) - dev_kfree_skb_any(ctx->skb); - memset(ctx, 0, sizeof(*ctx)); } -- cgit v1.2.3 From 817f18534412532198bf3da8dfd2663a1d75a7de Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 25 Oct 2015 15:59:23 +0200 Subject: wil6210: fix device ready detection Adjust driver behavior during FW boot. Proper sequence of events after reset and FW download, is as following: - FW prepares mailbox structure and reports IRQ "FW_READY" - driver caches mailbox registers, marks mailbox readiness - FW sends WMI_FW_READY event, ignore it - FW sends WMI_READY event with some data - driver stores relevant data marks FW is operational Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/interrupt.c | 6 +++--- drivers/net/wireless/ath/wil6210/wil6210.h | 4 ++-- drivers/net/wireless/ath/wil6210/wmi.c | 10 ++-------- 3 files changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 06fc46f85c85..50c136e843c4 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -236,7 +236,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH); - if (likely(test_bit(wil_status_reset_done, wil->status))) { + if (likely(test_bit(wil_status_fwready, wil->status))) { if (likely(test_bit(wil_status_napi_en, wil->status))) { wil_dbg_txrx(wil, "NAPI(Rx) schedule\n"); need_unmask = false; @@ -286,7 +286,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; /* clear also all VRING interrupts */ isr &= ~(BIT(25) - 1UL); - if (likely(test_bit(wil_status_reset_done, wil->status))) { + if (likely(test_bit(wil_status_fwready, wil->status))) { wil_dbg_txrx(wil, "NAPI(Tx) schedule\n"); need_unmask = false; napi_schedule(&wil->napi_tx); @@ -364,7 +364,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) if (isr & ISR_MISC_FW_READY) { wil_dbg_irq(wil, "IRQ: FW ready\n"); wil_cache_mbox_regs(wil); - set_bit(wil_status_reset_done, wil->status); + set_bit(wil_status_mbox_ready, wil->status); /** * Actual FW ready indicated by the * WMI_FW_READY_EVENTID diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index f619bf234353..ade5f3b8274b 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -402,11 +402,11 @@ struct vring_tx_data { }; enum { /* for wil6210_priv.status */ - wil_status_fwready = 0, + wil_status_fwready = 0, /* FW operational */ wil_status_fwconnecting, wil_status_fwconnected, wil_status_dontscan, - wil_status_reset_done, + wil_status_mbox_ready, /* MBOX structures ready */ wil_status_irqen, /* FIXME: interrupts enabled - for debug */ wil_status_napi_en, /* NAPI enabled protected by wil->mutex */ wil_status_resetting, /* reset in progress */ diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 361f3d8f7b43..6ed26baca0e5 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -293,12 +293,6 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) /* ignore MAC address, we already have it from the boot loader */ snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), "%d", wil->fw_version); -} - -static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, - int len) -{ - wil_dbg_wmi(wil, "WMI: got FW ready event\n"); wil_set_recovery_state(wil, fw_recovery_idle); set_bit(wil_status_fwready, wil->status); @@ -699,7 +693,7 @@ static const struct { void *data, int data_len); } wmi_evt_handlers[] = { {WMI_READY_EVENTID, wmi_evt_ready}, - {WMI_FW_READY_EVENTID, wmi_evt_fw_ready}, + {WMI_FW_READY_EVENTID, wmi_evt_ignore}, {WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt}, {WMI_TX_MGMT_PACKET_EVENTID, wmi_evt_tx_mgmt}, {WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete}, @@ -730,7 +724,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) ulong flags; unsigned n; - if (!test_bit(wil_status_reset_done, wil->status)) { + if (!test_bit(wil_status_mbox_ready, wil->status)) { wil_err(wil, "Reset in progress. Cannot handle WMI event\n"); return; } -- cgit v1.2.3 From 5140a5fde2b44d366338e00ad7c2a7ede8be3e65 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Sun, 25 Oct 2015 15:59:24 +0200 Subject: wil6210: handle failure in Tx vring config When configuring Tx vring for new connection, WMI call to the firmware may fail. In this case, need to clean up properly. In particular, need to call cfg80211_del_sta() in case of AP like interface. Perform full "disconnect" procedure for proper clean up Signed-off-by: Vladimir Kondratiev Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index aade16b126c4..bb69a5949aea 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -422,7 +422,7 @@ static void wil_connect_worker(struct work_struct *work) wil->sta[cid].status = wil_sta_connected; netif_tx_wake_all_queues(ndev); } else { - wil->sta[cid].status = wil_sta_unused; + wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true); } } -- cgit v1.2.3 From 9c2e90ffc97a8f45b98d81345d8f2eff192d09ef Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Wed, 21 Oct 2015 14:53:19 -0700 Subject: ath6kl: report antenna configuration This lets 'iw phy phy0 info' report antennas for the radio device: ... Available Antennas: TX 0x2 RX 0x2 Configured Antennas: TX 0x2 RX 0x2 ... Signed-off-by: Ben Greear Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 17 +++++++++++++++++ drivers/net/wireless/ath/ath6kl/core.h | 2 ++ 2 files changed, 19 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 76b682e566ab..6430ab663e37 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -3231,6 +3231,15 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, wait, buf, len, no_cck); } +static int ath6kl_get_antenna(struct wiphy *wiphy, + u32 *tx_ant, u32 *rx_ant) +{ + struct ath6kl *ar = wiphy_priv(wiphy); + *tx_ant = ar->hw.tx_ant; + *rx_ant = ar->hw.rx_ant; + return 0; +} + static void ath6kl_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, u16 frame_type, bool reg) @@ -3447,6 +3456,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, .mgmt_tx = ath6kl_mgmt_tx, .mgmt_frame_register = ath6kl_mgmt_frame_register, + .get_antenna = ath6kl_get_antenna, .sched_scan_start = ath6kl_cfg80211_sscan_start, .sched_scan_stop = ath6kl_cfg80211_sscan_stop, .set_bitrate_mask = ath6kl_cfg80211_set_bitrate, @@ -3794,11 +3804,18 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff; + ar->hw.tx_ant = 2; + ar->hw.rx_ant = 2; } else { ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; + ar->hw.tx_ant = 1; + ar->hw.rx_ant = 1; } + wiphy->available_antennas_tx = ar->hw.tx_ant; + wiphy->available_antennas_rx = ar->hw.rx_ant; + if (band_2gig) wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; if (band_5gig) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 2b78c863d030..5f3acfe6015e 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -782,6 +782,8 @@ struct ath6kl { u32 refclk_hz; u32 uarttx_pin; u32 testscript_addr; + u8 tx_ant; + u8 rx_ant; enum wmi_phy_cap cap; u32 flags; -- cgit v1.2.3 From 7fd98524560cac3a629aa1130d45260d4469d254 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Wed, 21 Oct 2015 14:53:20 -0700 Subject: ath6kl: add error message to explain lack of HT It can take a user a while to understand why their NIC that advertises 802.11n support cannot actually do 802.11n. Print out a warning in the logs to save the next poor person to use this NIC some trouble. Signed-off-by: Ben Greear Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 6430ab663e37..7a67e57f55ee 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -3796,6 +3796,9 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) ath6kl_band_2ghz.ht_cap.ht_supported = false; ath6kl_band_5ghz.ht_cap.cap = 0; ath6kl_band_5ghz.ht_cap.ht_supported = false; + + if (ht) + ath6kl_err("Firmware lacks RSN-CAP-OVERRIDE, so HT (802.11n) is disabled."); } if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES, -- cgit v1.2.3 From 53cc3291bcfbefc0b3f1e3b7b30ed028b5f1a75d Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Wed, 21 Oct 2015 14:53:21 -0700 Subject: ath6kl: fix firmware version assignment Improper use of strlcpy caused garbage to be appended to the firmware version string. Fix this by paying attention to the ie_lenth. Signed-off-by: Ben Greear Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 6e473fa4b13c..e3f3a6ae0c0a 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -994,7 +994,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) switch (ie_id) { case ATH6KL_FW_IE_FW_VERSION: strlcpy(ar->wiphy->fw_version, data, - sizeof(ar->wiphy->fw_version)); + min(sizeof(ar->wiphy->fw_version), ie_len+1)); ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw version %s\n", -- cgit v1.2.3 From 0370248379579aa0274c8f14f2d9af1f32388104 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Thu, 22 Oct 2015 09:07:38 -0700 Subject: ath6kl: break stats gathering code into separate method This will allow us to call it from elsewhere when implementing ethtool stats. Signed-off-by: Ben Greear Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/debug.c | 55 +++++++++++++++++++-------------- drivers/net/wireless/ath/ath6kl/debug.h | 2 ++ 2 files changed, 34 insertions(+), 23 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 81ba48d2938b..e2b7809d7886 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -98,6 +98,33 @@ void ath6kl_warn(const char *fmt, ...) } EXPORT_SYMBOL(ath6kl_warn); +int ath6kl_read_tgt_stats(struct ath6kl *ar, struct ath6kl_vif *vif) +{ + long left; + + if (down_interruptible(&ar->sem)) + return -EBUSY; + + set_bit(STATS_UPDATE_PEND, &vif->flags); + + if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) { + up(&ar->sem); + return -EIO; + } + + left = wait_event_interruptible_timeout(ar->event_wq, + !test_bit(STATS_UPDATE_PEND, + &vif->flags), WMI_TIMEOUT); + + up(&ar->sem); + + if (left <= 0) + return -ETIMEDOUT; + + return 0; +} +EXPORT_SYMBOL(ath6kl_read_tgt_stats); + #ifdef CONFIG_ATH6KL_DEBUG void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) @@ -544,42 +571,24 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, char *buf; unsigned int len = 0, buf_len = 1500; int i; - long left; ssize_t ret_cnt; + int rv; vif = ath6kl_vif_first(ar); if (!vif) return -EIO; - tgt_stats = &vif->target_stats; - buf = kzalloc(buf_len, GFP_KERNEL); if (!buf) return -ENOMEM; - if (down_interruptible(&ar->sem)) { + rv = ath6kl_read_tgt_stats(ar, vif); + if (rv < 0) { kfree(buf); - return -EBUSY; + return rv; } - set_bit(STATS_UPDATE_PEND, &vif->flags); - - if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) { - up(&ar->sem); - kfree(buf); - return -EIO; - } - - left = wait_event_interruptible_timeout(ar->event_wq, - !test_bit(STATS_UPDATE_PEND, - &vif->flags), WMI_TIMEOUT); - - up(&ar->sem); - - if (left <= 0) { - kfree(buf); - return -ETIMEDOUT; - } + tgt_stats = &vif->target_stats; len += scnprintf(buf + len, buf_len - len, "\n"); len += scnprintf(buf + len, buf_len - len, "%25s\n", diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 19106ed28961..0614393dd7ae 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -59,6 +59,8 @@ enum ath6kl_war { ATH6KL_WAR_INVALID_RATE, }; +int ath6kl_read_tgt_stats(struct ath6kl *ar, struct ath6kl_vif *vif); + #ifdef CONFIG_ATH6KL_DEBUG void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...); -- cgit v1.2.3 From 13eff5311382cb109725363026cdb4717714bf65 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Thu, 22 Oct 2015 09:07:39 -0700 Subject: ath6kl: implement ethtool stats This supports a way to get target stats through normal ethtool stats API. For instance: # ethtool -S wlan1 NIC statistics: tx_pkts_nic: 353 tx_bytes_nic: 25142 rx_pkts_nic: 6 rx_bytes_nic: 996 d_tx_ucast_pkts: 89 d_tx_bcast_pkts: 264 d_tx_ucast_bytes: 3020 d_tx_bcast_bytes: 22122 ... Signed-off-by: Ben Greear Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 123 +++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 7a67e57f55ee..81ac8c59f0ec 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -3644,6 +3644,127 @@ void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif) ar->num_vif--; } +static const char ath6kl_gstrings_sta_stats[][ETH_GSTRING_LEN] = { + /* Common stats names used by many drivers. */ + "tx_pkts_nic", "tx_bytes_nic", "rx_pkts_nic", "rx_bytes_nic", + + /* TX stats. */ + "d_tx_ucast_pkts", "d_tx_bcast_pkts", + "d_tx_ucast_bytes", "d_tx_bcast_bytes", + "d_tx_rts_ok", "d_tx_error", "d_tx_fail", + "d_tx_retry", "d_tx_multi_retry", "d_tx_rts_fail", + "d_tx_tkip_counter_measures", + + /* RX Stats. */ + "d_rx_ucast_pkts", "d_rx_ucast_rate", "d_rx_bcast_pkts", + "d_rx_ucast_bytes", "d_rx_bcast_bytes", "d_rx_frag_pkt", + "d_rx_error", "d_rx_crc_err", "d_rx_keycache_miss", + "d_rx_decrypt_crc_err", "d_rx_duplicate_frames", + "d_rx_mic_err", "d_rx_tkip_format_err", "d_rx_ccmp_format_err", + "d_rx_ccmp_replay_err", + + /* Misc stats. */ + "d_beacon_miss", "d_num_connects", "d_num_disconnects", + "d_beacon_avg_rssi", "d_arp_received", "d_arp_matched", + "d_arp_replied" +}; + +#define ATH6KL_STATS_LEN ARRAY_SIZE(ath6kl_gstrings_sta_stats) + +static int ath6kl_get_sset_count(struct net_device *dev, int sset) +{ + int rv = 0; + + if (sset == ETH_SS_STATS) + rv += ATH6KL_STATS_LEN; + + if (rv == 0) + return -EOPNOTSUPP; + return rv; +} + +static void ath6kl_get_stats(struct net_device *dev, + struct ethtool_stats *stats, + u64 *data) +{ + struct ath6kl_vif *vif = netdev_priv(dev); + struct ath6kl *ar = vif->ar; + int i = 0; + struct target_stats *tgt_stats; + + memset(data, 0, sizeof(u64) * ATH6KL_STATS_LEN); + + ath6kl_read_tgt_stats(ar, vif); + + tgt_stats = &vif->target_stats; + + data[i++] = tgt_stats->tx_ucast_pkt + tgt_stats->tx_bcast_pkt; + data[i++] = tgt_stats->tx_ucast_byte + tgt_stats->tx_bcast_byte; + data[i++] = tgt_stats->rx_ucast_pkt + tgt_stats->rx_bcast_pkt; + data[i++] = tgt_stats->rx_ucast_byte + tgt_stats->rx_bcast_byte; + + data[i++] = tgt_stats->tx_ucast_pkt; + data[i++] = tgt_stats->tx_bcast_pkt; + data[i++] = tgt_stats->tx_ucast_byte; + data[i++] = tgt_stats->tx_bcast_byte; + data[i++] = tgt_stats->tx_rts_success_cnt; + data[i++] = tgt_stats->tx_err; + data[i++] = tgt_stats->tx_fail_cnt; + data[i++] = tgt_stats->tx_retry_cnt; + data[i++] = tgt_stats->tx_mult_retry_cnt; + data[i++] = tgt_stats->tx_rts_fail_cnt; + data[i++] = tgt_stats->tkip_cnter_measures_invoked; + + data[i++] = tgt_stats->rx_ucast_pkt; + data[i++] = tgt_stats->rx_ucast_rate; + data[i++] = tgt_stats->rx_bcast_pkt; + data[i++] = tgt_stats->rx_ucast_byte; + data[i++] = tgt_stats->rx_bcast_byte; + data[i++] = tgt_stats->rx_frgment_pkt; + data[i++] = tgt_stats->rx_err; + data[i++] = tgt_stats->rx_crc_err; + data[i++] = tgt_stats->rx_key_cache_miss; + data[i++] = tgt_stats->rx_decrypt_err; + data[i++] = tgt_stats->rx_dupl_frame; + data[i++] = tgt_stats->tkip_local_mic_fail; + data[i++] = tgt_stats->tkip_fmt_err; + data[i++] = tgt_stats->ccmp_fmt_err; + data[i++] = tgt_stats->ccmp_replays; + + data[i++] = tgt_stats->cs_bmiss_cnt; + data[i++] = tgt_stats->cs_connect_cnt; + data[i++] = tgt_stats->cs_discon_cnt; + data[i++] = tgt_stats->cs_ave_beacon_rssi; + data[i++] = tgt_stats->arp_received; + data[i++] = tgt_stats->arp_matched; + data[i++] = tgt_stats->arp_replied; + + if (i != ATH6KL_STATS_LEN) { + WARN_ON_ONCE(1); + ath6kl_err("ethtool stats error, i: %d STATS_LEN: %d\n", + i, (int)ATH6KL_STATS_LEN); + } +} + +/* These stats are per NIC, not really per vdev, so we just ignore dev. */ +static void ath6kl_get_strings(struct net_device *dev, u32 sset, u8 *data) +{ + int sz_sta_stats = 0; + + if (sset == ETH_SS_STATS) { + sz_sta_stats = sizeof(ath6kl_gstrings_sta_stats); + memcpy(data, ath6kl_gstrings_sta_stats, sz_sta_stats); + } +} + +static const struct ethtool_ops ath6kl_ethtool_ops = { + .get_drvinfo = cfg80211_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_strings = ath6kl_get_strings, + .get_ethtool_stats = ath6kl_get_stats, + .get_sset_count = ath6kl_get_sset_count, +}; + struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, unsigned char name_assign_type, enum nl80211_iftype type, @@ -3689,6 +3810,8 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, if (ath6kl_cfg80211_vif_init(vif)) goto err; + netdev_set_default_ethtool_ops(ndev, &ath6kl_ethtool_ops); + if (register_netdevice(ndev)) goto err; -- cgit v1.2.3 From 8ed66f0e8235118a31720acdab3bbbe9debd0f6a Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 26 Oct 2015 17:01:44 -0400 Subject: geneve: implement support for IPv6-based tunnels NOTE: Link-local IPv6 addresses for remote endpoints are not supported, since the driver currently has no capacity for binding a geneve interface to a specific link. Signed-off-by: John W. Linville Reviewed-by: Jesse Gross Signed-off-by: David S. Miller --- drivers/net/geneve.c | 473 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 394 insertions(+), 79 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 445071c163cb..393b0bddf7cf 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -46,16 +46,27 @@ struct geneve_net { static int geneve_net_id; +union geneve_addr { + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr sa; +}; + +static union geneve_addr geneve_remote_unspec = { .sa.sa_family = AF_UNSPEC, }; + /* Pseudo network device */ struct geneve_dev { struct hlist_node hlist; /* vni hash table */ struct net *net; /* netns for packet i/o */ struct net_device *dev; /* netdev for geneve tunnel */ - struct geneve_sock *sock; /* socket used for geneve tunnel */ + struct geneve_sock *sock4; /* IPv4 socket used for geneve tunnel */ +#if IS_ENABLED(CONFIG_IPV6) + struct geneve_sock *sock6; /* IPv6 socket used for geneve tunnel */ +#endif u8 vni[3]; /* virtual network ID for tunnel */ u8 ttl; /* TTL override */ u8 tos; /* TOS override */ - struct sockaddr_in remote; /* IPv4 address for link partner */ + union geneve_addr remote; /* IP address for link partner */ struct list_head next; /* geneve's per namespace list */ __be16 dst_port; bool collect_md; @@ -103,11 +114,31 @@ static struct geneve_dev *geneve_lookup(struct geneve_sock *gs, vni_list_head = &gs->vni_list[hash]; hlist_for_each_entry_rcu(geneve, vni_list_head, hlist) { if (!memcmp(vni, geneve->vni, sizeof(geneve->vni)) && - addr == geneve->remote.sin_addr.s_addr) + addr == geneve->remote.sin.sin_addr.s_addr) + return geneve; + } + return NULL; +} + +#if IS_ENABLED(CONFIG_IPV6) +static struct geneve_dev *geneve6_lookup(struct geneve_sock *gs, + struct in6_addr addr6, u8 vni[]) +{ + struct hlist_head *vni_list_head; + struct geneve_dev *geneve; + __u32 hash; + + /* Find the device for this VNI */ + hash = geneve_net_vni_hash(vni); + vni_list_head = &gs->vni_list[hash]; + hlist_for_each_entry_rcu(geneve, vni_list_head, hlist) { + if (!memcmp(vni, geneve->vni, sizeof(geneve->vni)) && + ipv6_addr_equal(&addr6, &geneve->remote.sin6.sin6_addr)) return geneve; } return NULL; } +#endif static inline struct genevehdr *geneve_hdr(const struct sk_buff *skb) { @@ -121,24 +152,49 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb) struct metadata_dst *tun_dst = NULL; struct geneve_dev *geneve = NULL; struct pcpu_sw_netstats *stats; - struct iphdr *iph; - u8 *vni; + struct iphdr *iph = NULL; __be32 addr; - int err; + static u8 zero_vni[3]; + u8 *vni; + int err = 0; + sa_family_t sa_family; +#if IS_ENABLED(CONFIG_IPV6) + struct ipv6hdr *ip6h = NULL; + struct in6_addr addr6; + static struct in6_addr zero_addr6; +#endif - iph = ip_hdr(skb); /* outer IP header... */ + sa_family = gs->sock->sk->sk_family; - if (gs->collect_md) { - static u8 zero_vni[3]; + if (sa_family == AF_INET) { + iph = ip_hdr(skb); /* outer IP header... */ - vni = zero_vni; - addr = 0; - } else { - vni = gnvh->vni; - addr = iph->saddr; - } + if (gs->collect_md) { + vni = zero_vni; + addr = 0; + } else { + vni = gnvh->vni; + + addr = iph->saddr; + } + + geneve = geneve_lookup(gs, addr, vni); +#if IS_ENABLED(CONFIG_IPV6) + } else if (sa_family == AF_INET6) { + ip6h = ipv6_hdr(skb); /* outer IPv6 header... */ - geneve = geneve_lookup(gs, addr, vni); + if (gs->collect_md) { + vni = zero_vni; + addr6 = zero_addr6; + } else { + vni = gnvh->vni; + + addr6 = ip6h->saddr; + } + + geneve = geneve6_lookup(gs, addr6, vni); +#endif + } if (!geneve) goto drop; @@ -149,7 +205,7 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb) (gnvh->oam ? TUNNEL_OAM : 0) | (gnvh->critical ? TUNNEL_CRIT_OPT : 0); - tun_dst = udp_tun_rx_dst(skb, AF_INET, flags, + tun_dst = udp_tun_rx_dst(skb, sa_family, flags, vni_to_tunnel_id(gnvh->vni), gnvh->opt_len * 4); if (!tun_dst) @@ -179,12 +235,25 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb) skb_reset_network_header(skb); - err = IP_ECN_decapsulate(iph, skb); + if (iph) + err = IP_ECN_decapsulate(iph, skb); +#if IS_ENABLED(CONFIG_IPV6) + if (ip6h) + err = IP6_ECN_decapsulate(ip6h, skb); +#endif if (unlikely(err)) { - if (log_ecn_error) - net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", - &iph->saddr, iph->tos); + if (log_ecn_error) { + if (iph) + net_info_ratelimited("non-ECT from %pI4 " + "with TOS=%#x\n", + &iph->saddr, iph->tos); +#if IS_ENABLED(CONFIG_IPV6) + if (ip6h) + net_info_ratelimited("non-ECT from %pI6\n", + &ip6h->saddr); +#endif + } if (err > 1) { ++geneve->dev->stats.rx_frame_errors; ++geneve->dev->stats.rx_errors; @@ -284,6 +353,7 @@ static struct socket *geneve_create_sock(struct net *net, bool ipv6, if (ipv6) { udp_conf.family = AF_INET6; + udp_conf.ipv6_v6only = 1; } else { udp_conf.family = AF_INET; udp_conf.local_ip.s_addr = htonl(INADDR_ANY); @@ -458,9 +528,9 @@ static void geneve_notify_del_rx_port(struct geneve_sock *gs) udp_del_offload(&gs->udp_offloads); } -static void geneve_sock_release(struct geneve_sock *gs) +static void __geneve_sock_release(struct geneve_sock *gs) { - if (--gs->refcnt) + if (!gs || --gs->refcnt) return; list_del(&gs->list); @@ -469,66 +539,117 @@ static void geneve_sock_release(struct geneve_sock *gs) kfree_rcu(gs, rcu); } +static void geneve_sock_release(struct geneve_dev *geneve) +{ + __geneve_sock_release(geneve->sock4); +#if IS_ENABLED(CONFIG_IPV6) + __geneve_sock_release(geneve->sock6); +#endif +} + static struct geneve_sock *geneve_find_sock(struct geneve_net *gn, + sa_family_t family, __be16 dst_port) { struct geneve_sock *gs; list_for_each_entry(gs, &gn->sock_list, list) { if (inet_sk(gs->sock->sk)->inet_sport == dst_port && - inet_sk(gs->sock->sk)->sk.sk_family == AF_INET) { + inet_sk(gs->sock->sk)->sk.sk_family == family) { return gs; } } return NULL; } -static int geneve_open(struct net_device *dev) +static int geneve_sock_add(struct geneve_dev *geneve, bool ipv6) { - struct geneve_dev *geneve = netdev_priv(dev); struct net *net = geneve->net; struct geneve_net *gn = net_generic(net, geneve_net_id); struct geneve_sock *gs; __u32 hash; - gs = geneve_find_sock(gn, geneve->dst_port); + gs = geneve_find_sock(gn, ipv6 ? AF_INET6 : AF_INET, geneve->dst_port); if (gs) { gs->refcnt++; goto out; } - gs = geneve_socket_create(net, geneve->dst_port, false); + gs = geneve_socket_create(net, geneve->dst_port, ipv6); if (IS_ERR(gs)) return PTR_ERR(gs); out: gs->collect_md = geneve->collect_md; - geneve->sock = gs; +#if IS_ENABLED(CONFIG_IPV6) + if (ipv6) + geneve->sock6 = gs; + else +#endif + geneve->sock4 = gs; hash = geneve_net_vni_hash(geneve->vni); hlist_add_head_rcu(&geneve->hlist, &gs->vni_list[hash]); return 0; } +static int geneve_open(struct net_device *dev) +{ + struct geneve_dev *geneve = netdev_priv(dev); + bool ipv6 = geneve->remote.sa.sa_family == AF_INET6; + bool metadata = geneve->collect_md; + int ret = 0; + + geneve->sock4 = NULL; +#if IS_ENABLED(CONFIG_IPV6) + geneve->sock6 = NULL; + if (ipv6 || metadata) + ret = geneve_sock_add(geneve, true); +#endif + if (!ret && (!ipv6 || metadata)) + ret = geneve_sock_add(geneve, false); + if (ret < 0) + geneve_sock_release(geneve); + + return ret; +} + static int geneve_stop(struct net_device *dev) { struct geneve_dev *geneve = netdev_priv(dev); - struct geneve_sock *gs = geneve->sock; if (!hlist_unhashed(&geneve->hlist)) hlist_del_rcu(&geneve->hlist); - geneve_sock_release(gs); + geneve_sock_release(geneve); return 0; } +static void geneve_build_header(struct genevehdr *geneveh, + __be16 tun_flags, u8 vni[3], + u8 options_len, u8 *options) +{ + geneveh->ver = GENEVE_VER; + geneveh->opt_len = options_len / 4; + geneveh->oam = !!(tun_flags & TUNNEL_OAM); + geneveh->critical = !!(tun_flags & TUNNEL_CRIT_OPT); + geneveh->rsvd1 = 0; + memcpy(geneveh->vni, vni, 3); + geneveh->proto_type = htons(ETH_P_TEB); + geneveh->rsvd2 = 0; + + memcpy(geneveh->options, options, options_len); +} + static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb, __be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt, - bool csum) + bool csum, bool xnet) { struct genevehdr *gnvh; int min_headroom; int err; + skb_scrub_packet(skb, xnet); + min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr); err = skb_cow_head(skb, min_headroom); @@ -544,15 +665,7 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb, } gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len); - gnvh->ver = GENEVE_VER; - gnvh->opt_len = opt_len / 4; - gnvh->oam = !!(tun_flags & TUNNEL_OAM); - gnvh->critical = !!(tun_flags & TUNNEL_CRIT_OPT); - gnvh->rsvd1 = 0; - memcpy(gnvh->vni, vni, 3); - gnvh->proto_type = htons(ETH_P_TEB); - gnvh->rsvd2 = 0; - memcpy(gnvh->options, opt, opt_len); + geneve_build_header(gnvh, tun_flags, vni, opt_len, opt); skb_set_inner_protocol(skb, htons(ETH_P_TEB)); return 0; @@ -562,10 +675,47 @@ free_rt: return err; } -static struct rtable *geneve_get_rt(struct sk_buff *skb, - struct net_device *dev, - struct flowi4 *fl4, - struct ip_tunnel_info *info) +#if IS_ENABLED(CONFIG_IPV6) +static int geneve6_build_skb(struct dst_entry *dst, struct sk_buff *skb, + __be16 tun_flags, u8 vni[3], u8 opt_len, u8 *opt, + bool csum, bool xnet) +{ + struct genevehdr *gnvh; + int min_headroom; + int err; + + skb_scrub_packet(skb, xnet); + + min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len + + GENEVE_BASE_HLEN + opt_len + sizeof(struct ipv6hdr); + err = skb_cow_head(skb, min_headroom); + if (unlikely(err)) { + kfree_skb(skb); + goto free_dst; + } + + skb = udp_tunnel_handle_offloads(skb, csum); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + goto free_dst; + } + + gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len); + geneve_build_header(gnvh, tun_flags, vni, opt_len, opt); + + skb_set_inner_protocol(skb, htons(ETH_P_TEB)); + return 0; + +free_dst: + dst_release(dst); + return err; +} +#endif + +static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, + struct net_device *dev, + struct flowi4 *fl4, + struct ip_tunnel_info *info) { struct geneve_dev *geneve = netdev_priv(dev); struct rtable *rt = NULL; @@ -588,7 +738,7 @@ static struct rtable *geneve_get_rt(struct sk_buff *skb, } fl4->flowi4_tos = RT_TOS(tos); - fl4->daddr = geneve->remote.sin_addr.s_addr; + fl4->daddr = geneve->remote.sin.sin_addr.s_addr; } rt = ip_route_output_key(geneve->net, fl4); @@ -604,6 +754,41 @@ static struct rtable *geneve_get_rt(struct sk_buff *skb, return rt; } +#if IS_ENABLED(CONFIG_IPV6) +static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, + struct net_device *dev, + struct flowi6 *fl6, + struct ip_tunnel_info *info) +{ + struct geneve_dev *geneve = netdev_priv(dev); + struct geneve_sock *gs6 = geneve->sock6; + struct dst_entry *dst = NULL; + + memset(fl6, 0, sizeof(*fl6)); + fl6->flowi6_mark = skb->mark; + fl6->flowi6_proto = IPPROTO_UDP; + + if (info) { + fl6->daddr = info->key.u.ipv6.dst; + fl6->saddr = info->key.u.ipv6.src; + } else { + fl6->daddr = geneve->remote.sin6.sin6_addr; + } + + if (ipv6_stub->ipv6_dst_lookup(geneve->net, gs6->sock->sk, &dst, fl6)) { + netdev_dbg(dev, "no route to %pI6\n", &fl6->daddr); + return ERR_PTR(-ENETUNREACH); + } + if (dst->dev == dev) { /* is this necessary? */ + netdev_dbg(dev, "circular route to %pI6\n", &fl6->daddr); + dst_release(dst); + return ERR_PTR(-ELOOP); + } + + return dst; +} +#endif + /* Convert 64 bit tunnel ID to 24 bit VNI. */ static void tunnel_id_to_vni(__be64 tun_id, __u8 *vni) { @@ -618,11 +803,11 @@ static void tunnel_id_to_vni(__be64 tun_id, __u8 *vni) #endif } -static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, + struct ip_tunnel_info *info) { struct geneve_dev *geneve = netdev_priv(dev); - struct geneve_sock *gs = geneve->sock; - struct ip_tunnel_info *info = NULL; + struct geneve_sock *gs4 = geneve->sock4; struct rtable *rt = NULL; const struct iphdr *iip; /* interior IP header */ int err = -EINVAL; @@ -631,10 +816,10 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) __be16 sport; bool udp_csum; __be16 df; + bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); if (geneve->collect_md) { - info = skb_tunnel_info(skb); - if (unlikely(info && !(info->mode & IP_TUNNEL_INFO_TX))) { + if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) { netdev_dbg(dev, "no tunnel metadata\n"); goto tx_error; } @@ -642,9 +827,8 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) goto tx_error; } - rt = geneve_get_rt(skb, dev, &fl4, info); + rt = geneve_get_v4_rt(skb, dev, &fl4, info); if (IS_ERR(rt)) { - netdev_dbg(dev, "no route to %pI4\n", &fl4.daddr); err = PTR_ERR(rt); goto tx_error; } @@ -665,7 +849,7 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) udp_csum = !!(key->tun_flags & TUNNEL_CSUM); err = geneve_build_skb(rt, skb, key->tun_flags, vni, - info->options_len, opts, udp_csum); + info->options_len, opts, udp_csum, xnet); if (unlikely(err)) goto err; @@ -675,7 +859,7 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) } else { udp_csum = false; err = geneve_build_skb(rt, skb, 0, geneve->vni, - 0, NULL, udp_csum); + 0, NULL, udp_csum, xnet); if (unlikely(err)) goto err; @@ -686,7 +870,7 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); df = 0; } - err = udp_tunnel_xmit_skb(rt, gs->sock->sk, skb, fl4.saddr, fl4.daddr, + err = udp_tunnel_xmit_skb(rt, gs4->sock->sk, skb, fl4.saddr, fl4.daddr, tos, ttl, df, sport, geneve->dst_port, !net_eq(geneve->net, dev_net(geneve->dev)), !udp_csum); @@ -706,6 +890,101 @@ err: return NETDEV_TX_OK; } +#if IS_ENABLED(CONFIG_IPV6) +static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, + struct ip_tunnel_info *info) +{ + struct geneve_dev *geneve = netdev_priv(dev); + struct geneve_sock *gs6 = geneve->sock6; + struct dst_entry *dst = NULL; + int err = -EINVAL; + struct flowi6 fl6; + __u8 ttl; + __be16 sport; + bool udp_csum; + bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); + + if (geneve->collect_md) { + if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) { + netdev_dbg(dev, "no tunnel metadata\n"); + goto tx_error; + } + } + + dst = geneve_get_v6_dst(skb, dev, &fl6, info); + if (IS_ERR(dst)) { + err = PTR_ERR(dst); + goto tx_error; + } + + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); + skb_reset_mac_header(skb); + + if (info) { + const struct ip_tunnel_key *key = &info->key; + u8 *opts = NULL; + u8 vni[3]; + + tunnel_id_to_vni(key->tun_id, vni); + if (key->tun_flags & TUNNEL_GENEVE_OPT) + opts = ip_tunnel_info_opts(info); + + udp_csum = !!(key->tun_flags & TUNNEL_CSUM); + err = geneve6_build_skb(dst, skb, key->tun_flags, vni, + info->options_len, opts, + udp_csum, xnet); + if (unlikely(err)) + goto err; + + ttl = key->ttl; + } else { + udp_csum = false; + err = geneve6_build_skb(dst, skb, 0, geneve->vni, + 0, NULL, udp_csum, xnet); + if (unlikely(err)) + goto err; + + ttl = geneve->ttl; + if (!ttl && ipv6_addr_is_multicast(&fl6.daddr)) + ttl = 1; + ttl = ttl ? : ip6_dst_hoplimit(dst); + } + err = udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev, + &fl6.saddr, &fl6.daddr, 0, ttl, + sport, geneve->dst_port, !udp_csum); + + iptunnel_xmit_stats(err, &dev->stats, dev->tstats); + return NETDEV_TX_OK; + +tx_error: + dev_kfree_skb(skb); +err: + if (err == -ELOOP) + dev->stats.collisions++; + else if (err == -ENETUNREACH) + dev->stats.tx_carrier_errors++; + else + dev->stats.tx_errors++; + return NETDEV_TX_OK; +} +#endif + +static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct geneve_dev *geneve = netdev_priv(dev); + struct ip_tunnel_info *info = NULL; + + if (geneve->collect_md) + info = skb_tunnel_info(skb); + +#if IS_ENABLED(CONFIG_IPV6) + if ((info && ip_tunnel_info_af(info) == AF_INET6) || + (!info && geneve->remote.sa.sa_family == AF_INET6)) + return geneve6_xmit_skb(skb, dev, info); +#endif + return geneve_xmit_skb(skb, dev, info); +} + static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) { struct ip_tunnel_info *info = skb_tunnel_info(skb); @@ -716,7 +995,7 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) if (ip_tunnel_info_af(info) != AF_INET) return -EINVAL; - rt = geneve_get_rt(skb, dev, &fl4, info); + rt = geneve_get_v4_rt(skb, dev, &fl4, info); if (IS_ERR(rt)) return PTR_ERR(rt); @@ -785,6 +1064,7 @@ static void geneve_setup(struct net_device *dev) static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = { [IFLA_GENEVE_ID] = { .type = NLA_U32 }, [IFLA_GENEVE_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, + [IFLA_GENEVE_REMOTE6] = { .len = sizeof(struct in6_addr) }, [IFLA_GENEVE_TTL] = { .type = NLA_U8 }, [IFLA_GENEVE_TOS] = { .type = NLA_U8 }, [IFLA_GENEVE_PORT] = { .type = NLA_U16 }, @@ -816,7 +1096,7 @@ static int geneve_validate(struct nlattr *tb[], struct nlattr *data[]) static struct geneve_dev *geneve_find_dev(struct geneve_net *gn, __be16 dst_port, - __be32 rem_addr, + union geneve_addr *remote, u8 vni[], bool *tun_on_same_port, bool *tun_collect_md) @@ -832,7 +1112,7 @@ static struct geneve_dev *geneve_find_dev(struct geneve_net *gn, *tun_on_same_port = true; } if (!memcmp(vni, geneve->vni, sizeof(geneve->vni)) && - rem_addr == geneve->remote.sin_addr.s_addr && + !memcmp(remote, &geneve->remote, sizeof(geneve->remote)) && dst_port == geneve->dst_port) t = geneve; } @@ -840,18 +1120,20 @@ static struct geneve_dev *geneve_find_dev(struct geneve_net *gn, } static int geneve_configure(struct net *net, struct net_device *dev, - __be32 rem_addr, __u32 vni, __u8 ttl, __u8 tos, - __be16 dst_port, bool metadata) + union geneve_addr *remote, + __u32 vni, __u8 ttl, __u8 tos, __be16 dst_port, + bool metadata) { struct geneve_net *gn = net_generic(net, geneve_net_id); struct geneve_dev *t, *geneve = netdev_priv(dev); bool tun_collect_md, tun_on_same_port; int err; - if (metadata) { - if (rem_addr || vni || tos || ttl) - return -EINVAL; - } + if (!remote) + return -EINVAL; + if (metadata && + (remote->sa.sa_family != AF_UNSPEC || vni || tos || ttl)) + return -EINVAL; geneve->net = net; geneve->dev = dev; @@ -860,16 +1142,19 @@ static int geneve_configure(struct net *net, struct net_device *dev, geneve->vni[1] = (vni & 0x0000ff00) >> 8; geneve->vni[2] = vni & 0x000000ff; - geneve->remote.sin_addr.s_addr = rem_addr; - if (IN_MULTICAST(ntohl(geneve->remote.sin_addr.s_addr))) + if ((remote->sa.sa_family == AF_INET && + IN_MULTICAST(ntohl(remote->sin.sin_addr.s_addr))) || + (remote->sa.sa_family == AF_INET6 && + ipv6_addr_is_multicast(&remote->sin6.sin6_addr))) return -EINVAL; + geneve->remote = *remote; geneve->ttl = ttl; geneve->tos = tos; geneve->dst_port = dst_port; geneve->collect_md = metadata; - t = geneve_find_dev(gn, dst_port, rem_addr, geneve->vni, + t = geneve_find_dev(gn, dst_port, remote, geneve->vni, &tun_on_same_port, &tun_collect_md); if (t) return -EBUSY; @@ -896,15 +1181,36 @@ static int geneve_newlink(struct net *net, struct net_device *dev, __be16 dst_port = htons(GENEVE_UDP_PORT); __u8 ttl = 0, tos = 0; bool metadata = false; - __be32 rem_addr = 0; + union geneve_addr remote = geneve_remote_unspec; __u32 vni = 0; + if (data[IFLA_GENEVE_REMOTE] && data[IFLA_GENEVE_REMOTE6]) + return -EINVAL; + + if (data[IFLA_GENEVE_REMOTE]) { + remote.sa.sa_family = AF_INET; + remote.sin.sin_addr.s_addr = + nla_get_in_addr(data[IFLA_GENEVE_REMOTE]); + } + + if (data[IFLA_GENEVE_REMOTE6]) { + if (!IS_ENABLED(CONFIG_IPV6)) + return -EPFNOSUPPORT; + + remote.sa.sa_family = AF_INET6; + remote.sin6.sin6_addr = + nla_get_in6_addr(data[IFLA_GENEVE_REMOTE6]); + + if (ipv6_addr_type(&remote.sin6.sin6_addr) & + IPV6_ADDR_LINKLOCAL) { + netdev_dbg(dev, "link-local remote is unsupported\n"); + return -EINVAL; + } + } + if (data[IFLA_GENEVE_ID]) vni = nla_get_u32(data[IFLA_GENEVE_ID]); - if (data[IFLA_GENEVE_REMOTE]) - rem_addr = nla_get_in_addr(data[IFLA_GENEVE_REMOTE]); - if (data[IFLA_GENEVE_TTL]) ttl = nla_get_u8(data[IFLA_GENEVE_TTL]); @@ -917,8 +1223,8 @@ static int geneve_newlink(struct net *net, struct net_device *dev, if (data[IFLA_GENEVE_COLLECT_METADATA]) metadata = true; - return geneve_configure(net, dev, rem_addr, vni, - ttl, tos, dst_port, metadata); + return geneve_configure(net, dev, &remote, vni, ttl, tos, dst_port, + metadata); } static void geneve_dellink(struct net_device *dev, struct list_head *head) @@ -932,7 +1238,7 @@ static void geneve_dellink(struct net_device *dev, struct list_head *head) static size_t geneve_get_size(const struct net_device *dev) { return nla_total_size(sizeof(__u32)) + /* IFLA_GENEVE_ID */ - nla_total_size(sizeof(struct in_addr)) + /* IFLA_GENEVE_REMOTE */ + nla_total_size(sizeof(struct in6_addr)) + /* IFLA_GENEVE_REMOTE{6} */ nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TTL */ nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TOS */ nla_total_size(sizeof(__be16)) + /* IFLA_GENEVE_PORT */ @@ -949,9 +1255,17 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev) if (nla_put_u32(skb, IFLA_GENEVE_ID, vni)) goto nla_put_failure; - if (nla_put_in_addr(skb, IFLA_GENEVE_REMOTE, - geneve->remote.sin_addr.s_addr)) - goto nla_put_failure; + if (geneve->remote.sa.sa_family == AF_INET) { + if (nla_put_in_addr(skb, IFLA_GENEVE_REMOTE, + geneve->remote.sin.sin_addr.s_addr)) + goto nla_put_failure; +#if IS_ENABLED(CONFIG_IPV6) + } else { + if (nla_put_in6_addr(skb, IFLA_GENEVE_REMOTE6, + &geneve->remote.sin6.sin6_addr)) + goto nla_put_failure; +#endif + } if (nla_put_u8(skb, IFLA_GENEVE_TTL, geneve->ttl) || nla_put_u8(skb, IFLA_GENEVE_TOS, geneve->tos)) @@ -997,7 +1311,8 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name, if (IS_ERR(dev)) return dev; - err = geneve_configure(net, dev, 0, 0, 0, 0, htons(dst_port), true); + err = geneve_configure(net, dev, &geneve_remote_unspec, + 0, 0, 0, htons(dst_port), true); if (err) { free_netdev(dev); return ERR_PTR(err); -- cgit v1.2.3 From 3a56f86f1be6a381345800d69999eaff87e0161d Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Mon, 26 Oct 2015 17:01:45 -0400 Subject: geneve: handle ipv6 priority like ipv4 tos Other callers of udp_tunnel6_xmit_skb just pass 0 for the prio argument. Jesse Gross suggested that prio is really the same as IPv4's tos and should be handled the same, so this is my interpretation of that suggestion. Signed-off-by: John W. Linville Reported-by: Jesse Gross Reviewed-by: Jesse Gross Signed-off-by: David S. Miller --- drivers/net/geneve.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 393b0bddf7cf..44e724508c55 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -763,6 +763,7 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, struct geneve_dev *geneve = netdev_priv(dev); struct geneve_sock *gs6 = geneve->sock6; struct dst_entry *dst = NULL; + __u8 prio; memset(fl6, 0, sizeof(*fl6)); fl6->flowi6_mark = skb->mark; @@ -771,7 +772,16 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, if (info) { fl6->daddr = info->key.u.ipv6.dst; fl6->saddr = info->key.u.ipv6.src; + fl6->flowi6_tos = RT_TOS(info->key.tos); } else { + prio = geneve->tos; + if (prio == 1) { + const struct iphdr *iip = ip_hdr(skb); + + prio = ip_tunnel_get_dsfield(iip, skb); + } + + fl6->flowi6_tos = RT_TOS(prio); fl6->daddr = geneve->remote.sin6.sin6_addr; } @@ -897,9 +907,10 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, struct geneve_dev *geneve = netdev_priv(dev); struct geneve_sock *gs6 = geneve->sock6; struct dst_entry *dst = NULL; + const struct iphdr *iip; /* interior IP header */ int err = -EINVAL; struct flowi6 fl6; - __u8 ttl; + __u8 prio, ttl; __be16 sport; bool udp_csum; bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); @@ -920,6 +931,8 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); skb_reset_mac_header(skb); + iip = ip_hdr(skb); + if (info) { const struct ip_tunnel_key *key = &info->key; u8 *opts = NULL; @@ -936,6 +949,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (unlikely(err)) goto err; + prio = ip_tunnel_ecn_encap(key->tos, iip, skb); ttl = key->ttl; } else { udp_csum = false; @@ -944,13 +958,14 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (unlikely(err)) goto err; + prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, iip, skb); ttl = geneve->ttl; if (!ttl && ipv6_addr_is_multicast(&fl6.daddr)) ttl = 1; ttl = ttl ? : ip6_dst_hoplimit(dst); } err = udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev, - &fl6.saddr, &fl6.daddr, 0, ttl, + &fl6.saddr, &fl6.daddr, prio, ttl, sport, geneve->dst_port, !udp_csum); iptunnel_xmit_stats(err, &dev->stats, dev->tstats); -- cgit v1.2.3 From b8812fa88371ae567c907448d9a7ba62d09b90c9 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 27 Oct 2015 09:49:00 -0400 Subject: geneve: add IPv6 bits to geneve_fill_metadata_dst Signed-off-by: John W. Linville Reviewed-by: Jesse Gross Signed-off-by: David S. Miller --- drivers/net/geneve.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 44e724508c55..de5c30c9f059 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1006,16 +1006,31 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) struct geneve_dev *geneve = netdev_priv(dev); struct rtable *rt; struct flowi4 fl4; +#if IS_ENABLED(CONFIG_IPV6) + struct dst_entry *dst; + struct flowi6 fl6; +#endif - if (ip_tunnel_info_af(info) != AF_INET) - return -EINVAL; + if (ip_tunnel_info_af(info) == AF_INET) { + rt = geneve_get_v4_rt(skb, dev, &fl4, info); + if (IS_ERR(rt)) + return PTR_ERR(rt); - rt = geneve_get_v4_rt(skb, dev, &fl4, info); - if (IS_ERR(rt)) - return PTR_ERR(rt); + ip_rt_put(rt); + info->key.u.ipv4.src = fl4.saddr; +#if IS_ENABLED(CONFIG_IPV6) + } else if (ip_tunnel_info_af(info) == AF_INET6) { + dst = geneve_get_v6_dst(skb, dev, &fl6, info); + if (IS_ERR(dst)) + return PTR_ERR(dst); + + dst_release(dst); + info->key.u.ipv6.src = fl6.saddr; +#endif + } else { + return -EINVAL; + } - ip_rt_put(rt); - info->key.u.ipv4.src = fl4.saddr; info->key.tp_src = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); info->key.tp_dst = geneve->dst_port; -- cgit v1.2.3 From 16615a4c6f4d54d7655dff19e7061c76043f907d Mon Sep 17 00:00:00 2001 From: Iyappan Subramanian Date: Mon, 26 Oct 2015 15:25:15 -0700 Subject: drivers: net: xgene: Add support RGMII TX/RX delay configuration Add RGMII TX/RX delay configuration support. RGMII standard requires 2ns delay to help the RGMII bridge receiver to sample data correctly. If the default value does not provide proper centering of the data sample, the TX/RX delay parameters can be used to adjust accordingly. Signed-off-by: Iyappan Subramanian Signed-off-by: David S. Miller --- drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 8 +++- drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 1 + drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 49 ++++++++++++++++++++++++ drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 2 + 4 files changed, 59 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c index 652f21889a48..33850a0f7e82 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c @@ -461,6 +461,7 @@ static void xgene_gmac_reset(struct xgene_enet_pdata *pdata) static void xgene_gmac_init(struct xgene_enet_pdata *pdata) { + struct device *dev = &pdata->pdev->dev; u32 value, mc2; u32 intf_ctl, rgmii; u32 icm0, icm2; @@ -490,7 +491,12 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata) default: ENET_INTERFACE_MODE2_SET(&mc2, 2); intf_ctl |= ENET_GHD_MODE; - CFG_TXCLK_MUXSEL0_SET(&rgmii, 4); + + if (dev->of_node) { + CFG_TXCLK_MUXSEL0_SET(&rgmii, pdata->tx_delay); + CFG_RXCLK_MUXSEL0_SET(&rgmii, pdata->rx_delay); + } + xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value); value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX; xgene_enet_wr_csr(pdata, DEBUG_REG_ADDR, value); diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h index ff05bbcff26d..6dee73c3c1e1 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h @@ -144,6 +144,7 @@ enum xgene_enet_rm { #define CFG_BYPASS_UNISEC_RX BIT(1) #define CFG_CLE_BYPASS_EN0 BIT(31) #define CFG_TXCLK_MUXSEL0_SET(dst, val) xgene_set_bits(dst, val, 29, 3) +#define CFG_RXCLK_MUXSEL0_SET(dst, val) xgene_set_bits(dst, val, 26, 3) #define CFG_CLE_IP_PROTOCOL0_SET(dst, val) xgene_set_bits(dst, val, 16, 2) #define CFG_CLE_DSTQID0_SET(dst, val) xgene_set_bits(dst, val, 0, 12) diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index 6b1846df7b0c..ce1068771b32 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -1118,6 +1118,47 @@ static int xgene_get_port_id_dt(struct device *dev, struct xgene_enet_pdata *pda return ret; } +static int xgene_get_tx_delay(struct xgene_enet_pdata *pdata) +{ + struct device *dev = &pdata->pdev->dev; + int delay, ret; + + ret = of_property_read_u32(dev->of_node, "tx-delay", &delay); + if (ret) { + pdata->tx_delay = 4; + return 0; + } + + if (delay < 0 || delay > 7) { + dev_err(dev, "Invalid tx-delay specified\n"); + return -EINVAL; + } + + pdata->tx_delay = delay; + + return 0; +} + +static int xgene_get_rx_delay(struct xgene_enet_pdata *pdata) +{ + struct device *dev = &pdata->pdev->dev; + int delay, ret; + + ret = of_property_read_u32(dev->of_node, "rx-delay", &delay); + if (ret) { + pdata->rx_delay = 2; + return 0; + } + + if (delay < 0 || delay > 7) { + dev_err(dev, "Invalid rx-delay specified\n"); + return -EINVAL; + } + + pdata->rx_delay = delay; + + return 0; +} static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) { @@ -1194,6 +1235,14 @@ static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) return -ENODEV; } + ret = xgene_get_tx_delay(pdata); + if (ret) + return ret; + + ret = xgene_get_rx_delay(pdata); + if (ret) + return ret; + ret = platform_get_irq(pdev, 0); if (ret <= 0) { dev_err(dev, "Unable to get ENET Rx IRQ\n"); diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h index ff89a5d98d01..a6e56b88c0a0 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h @@ -184,6 +184,8 @@ struct xgene_enet_pdata { u8 bp_bufnum; u16 ring_num; u32 mss; + u8 tx_delay; + u8 rx_delay; }; struct xgene_indirect_ctl { -- cgit v1.2.3 From 0d9b970cee612968c6b888b93736d991762b9edb Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 28 Oct 2015 10:16:56 +0100 Subject: mlxsw: spectrum: move "bridged" bool to u8 flags It is a flag anyway, so move it to existing u8 flag and don't waste mem. Fix the flags to be in single u8 on the way. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 4 ++-- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 6e9906d8d149..e30b2da1f862 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1899,12 +1899,12 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *unused, if (err) netdev_err(dev, "Failed to join bridge\n"); mlxsw_sp_master_bridge_inc(mlxsw_sp, upper_dev); - mlxsw_sp_port->bridged = true; + mlxsw_sp_port->bridged = 1; } else { err = mlxsw_sp_port_bridge_leave(mlxsw_sp_port); if (err) netdev_err(dev, "Failed to leave bridge\n"); - mlxsw_sp_port->bridged = false; + mlxsw_sp_port->bridged = 0; mlxsw_sp_master_bridge_dec(mlxsw_sp, upper_dev); } } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index fc0074902ab5..b4d839371ac6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -84,10 +84,10 @@ struct mlxsw_sp_port { struct mlxsw_sp *mlxsw_sp; u8 local_port; u8 stp_state; - u8 learning:1; - u8 learning_sync:1; + u8 learning:1, + learning_sync:1, + bridged:1; u16 pvid; - bool bridged; /* 802.1Q bridge VLANs */ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; /* VLAN interfaces */ -- cgit v1.2.3 From 1b3433a942922953df43ef0bc0172119041364c5 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 28 Oct 2015 10:16:57 +0100 Subject: mlxsw: spectrum: Add support for VLAN ranges in flooding configuration When enabling a range of VLANs on a bridged port we can configure flooding for these VLANs by one register access instead of calling the same register for each VLAN. This is accomplished by using the 'range' field of the Switch Flooding Table Register (SFTR). Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index c39b7a188726..c3881c902756 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -248,9 +248,11 @@ static int mlxsw_sp_port_fid_unmap(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid) } static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port, - u16 fid, bool set, bool only_uc) + u16 fid_begin, u16 fid_end, bool set, + bool only_uc) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u16 range = fid_end - fid_begin + 1; char *sftr_pl; int err; @@ -258,8 +260,8 @@ static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port, if (!sftr_pl) return -ENOMEM; - mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, fid, - MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, 0, + mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, fid_begin, + MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range, mlxsw_sp_port->local_port, set); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); if (err) @@ -271,8 +273,8 @@ static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port, if (only_uc) goto buffer_out; - mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, fid, - MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, 0, + mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, fid_begin, + MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range, mlxsw_sp_port->local_port, set); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); @@ -345,14 +347,13 @@ static int __mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port, netdev_err(dev, "Failed to map FID=%d", vid); return err; } + } - err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, true, - false); - if (err) { - netdev_err(dev, "Failed to set flooding for FID=%d", - vid); - return err; - } + err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid_begin, vid_end, + true, false); + if (err) { + netdev_err(dev, "Failed to configure flooding\n"); + return err; } for (vid = vid_begin; vid <= vid_end; @@ -530,15 +531,14 @@ static int __mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port, if (init) goto out; - for (vid = vid_begin; vid <= vid_end; vid++) { - err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, false, - false); - if (err) { - netdev_err(dev, "Failed to clear flooding for FID=%d", - vid); - return err; - } + err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid_begin, vid_end, + false, false); + if (err) { + netdev_err(dev, "Failed to clear flooding\n"); + return err; + } + for (vid = vid_begin; vid <= vid_end; vid++) { /* Remove FID mapping in case of Virtual mode */ err = mlxsw_sp_port_fid_unmap(mlxsw_sp_port, vid); if (err) { -- cgit v1.2.3 From 0293038e0c36db45f2ea4e4e4a8ce0a0faa62139 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 28 Oct 2015 10:16:58 +0100 Subject: mlxsw: spectrum: Add support for flood control Add or remove a bridged port from the flooding domain of unknown unicast packets according to user configuration. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 1 + drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 1 + .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 113 ++++++++++++++------- 3 files changed, 78 insertions(+), 37 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index e30b2da1f862..3be4a2355ead 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -1227,6 +1227,7 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port) mlxsw_sp_port->local_port = local_port; mlxsw_sp_port->learning = 1; mlxsw_sp_port->learning_sync = 1; + mlxsw_sp_port->uc_flood = 1; mlxsw_sp_port->pvid = 1; mlxsw_sp_port->pcpu_stats = diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index b4d839371ac6..4365c8bccc6d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -86,6 +86,7 @@ struct mlxsw_sp_port { u8 stp_state; u8 learning:1, learning_sync:1, + uc_flood:1, bridged:1; u16 pvid; /* 802.1Q bridge VLANs */ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index c3881c902756..1f3b12e8dfb4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -66,7 +66,8 @@ static int mlxsw_sp_port_attr_get(struct net_device *dev, case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: attr->u.brport_flags = (mlxsw_sp_port->learning ? BR_LEARNING : 0) | - (mlxsw_sp_port->learning_sync ? BR_LEARNING_SYNC : 0); + (mlxsw_sp_port->learning_sync ? BR_LEARNING_SYNC : 0) | + (mlxsw_sp_port->uc_flood ? BR_FLOOD : 0); break; default: return -EOPNOTSUPP; @@ -123,15 +124,89 @@ static int mlxsw_sp_port_attr_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port, return mlxsw_sp_port_stp_state_set(mlxsw_sp_port, state); } +static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port, + u16 fid_begin, u16 fid_end, bool set, + bool only_uc) +{ + struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + u16 range = fid_end - fid_begin + 1; + char *sftr_pl; + int err; + + sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL); + if (!sftr_pl) + return -ENOMEM; + + mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, fid_begin, + MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range, + mlxsw_sp_port->local_port, set); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); + if (err) + goto buffer_out; + + /* Flooding control allows one to decide whether a given port will + * flood unicast traffic for which there is no FDB entry. + */ + if (only_uc) + goto buffer_out; + + mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, fid_begin, + MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range, + mlxsw_sp_port->local_port, set); + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); + +buffer_out: + kfree(sftr_pl); + return err; +} + +static int mlxsw_sp_port_uc_flood_set(struct mlxsw_sp_port *mlxsw_sp_port, + bool set) +{ + struct net_device *dev = mlxsw_sp_port->dev; + u16 vid, last_visited_vid; + int err; + + for_each_set_bit(vid, mlxsw_sp_port->active_vlans, VLAN_N_VID) { + err = __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, vid, set, + true); + if (err) { + last_visited_vid = vid; + goto err_port_flood_set; + } + } + + return 0; + +err_port_flood_set: + for_each_set_bit(vid, mlxsw_sp_port->active_vlans, last_visited_vid) + __mlxsw_sp_port_flood_set(mlxsw_sp_port, vid, vid, !set, true); + netdev_err(dev, "Failed to configure unicast flooding\n"); + return err; +} + static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port, struct switchdev_trans *trans, unsigned long brport_flags) { + unsigned long uc_flood = mlxsw_sp_port->uc_flood ? BR_FLOOD : 0; + bool set; + int err; + if (switchdev_trans_ph_prepare(trans)) return 0; + if ((uc_flood ^ brport_flags) & BR_FLOOD) { + set = mlxsw_sp_port->uc_flood ? false : true; + err = mlxsw_sp_port_uc_flood_set(mlxsw_sp_port, set); + if (err) + return err; + } + + mlxsw_sp_port->uc_flood = brport_flags & BR_FLOOD ? 1 : 0; mlxsw_sp_port->learning = brport_flags & BR_LEARNING ? 1 : 0; mlxsw_sp_port->learning_sync = brport_flags & BR_LEARNING_SYNC ? 1 : 0; + return 0; } @@ -247,42 +322,6 @@ static int mlxsw_sp_port_fid_unmap(struct mlxsw_sp_port *mlxsw_sp_port, u16 fid) return mlxsw_sp_port_vid_to_fid_set(mlxsw_sp_port, mt, false, fid, fid); } -static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port, - u16 fid_begin, u16 fid_end, bool set, - bool only_uc) -{ - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - u16 range = fid_end - fid_begin + 1; - char *sftr_pl; - int err; - - sftr_pl = kmalloc(MLXSW_REG_SFTR_LEN, GFP_KERNEL); - if (!sftr_pl) - return -ENOMEM; - - mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_UC, fid_begin, - MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range, - mlxsw_sp_port->local_port, set); - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); - if (err) - goto buffer_out; - - /* Flooding control allows one to decide whether a given port will - * flood unicast traffic for which there is no FDB entry. - */ - if (only_uc) - goto buffer_out; - - mlxsw_reg_sftr_pack(sftr_pl, MLXSW_SP_FLOOD_TABLE_BM, fid_begin, - MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST, range, - mlxsw_sp_port->local_port, set); - err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sftr), sftr_pl); - -buffer_out: - kfree(sftr_pl); - return err; -} - static int mlxsw_sp_port_add_vids(struct net_device *dev, u16 vid_begin, u16 vid_end) { -- cgit v1.2.3 From 4e9ec0839b4994ebc764d8067832dd079336c42f Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 28 Oct 2015 10:16:59 +0100 Subject: mlxsw: reg: Fix description for reg_sfd_uc_sub_port The original description was for LAG, so fix it. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 4fcba46bbae0..c24283a1d389 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -348,8 +348,9 @@ MLXSW_ITEM32_INDEXED(reg, sfd, rec_action, MLXSW_REG_SFD_BASE_LEN, 28, 4, MLXSW_REG_SFD_REC_LEN, 0x0C, false); /* reg_sfd_uc_sub_port - * LAG sub port. - * Must be 0 if multichannel VEPA is not enabled. + * VEPA channel on local port. + * Valid only if local port is a non-stacking port. Must be 0 if multichannel + * VEPA is not enabled. * Access: RW */ MLXSW_ITEM32_INDEXED(reg, sfd, uc_sub_port, MLXSW_REG_SFD_BASE_LEN, 16, 8, -- cgit v1.2.3 From 8316f087f7c62a2d21ec4e72926ec07ce777fe48 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 28 Oct 2015 10:17:00 +0100 Subject: mlxsw: reg: Fix desription typos of couple of SFN items Fix copy-paste errors. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index c24283a1d389..2bf230c51955 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -475,7 +475,7 @@ MLXSW_ITEM32_INDEXED(reg, sfn, rec_type, MLXSW_REG_SFN_BASE_LEN, 20, 4, MLXSW_ITEM_BUF_INDEXED(reg, sfn, rec_mac, MLXSW_REG_SFN_BASE_LEN, 6, MLXSW_REG_SFN_REC_LEN, 0x02); -/* reg_sfd_mac_sub_port +/* reg_sfn_mac_sub_port * VEPA channel on the local port. * 0 if multichannel VEPA is not enabled. * Access: RO @@ -483,14 +483,14 @@ MLXSW_ITEM_BUF_INDEXED(reg, sfn, rec_mac, MLXSW_REG_SFN_BASE_LEN, 6, MLXSW_ITEM32_INDEXED(reg, sfn, mac_sub_port, MLXSW_REG_SFN_BASE_LEN, 16, 8, MLXSW_REG_SFN_REC_LEN, 0x08, false); -/* reg_sfd_mac_fid +/* reg_sfn_mac_fid * Filtering identifier. * Access: RO */ MLXSW_ITEM32_INDEXED(reg, sfn, mac_fid, MLXSW_REG_SFN_BASE_LEN, 0, 16, MLXSW_REG_SFN_REC_LEN, 0x08, false); -/* reg_sfd_mac_system_port +/* reg_sfn_mac_system_port * Unique port identifier for the final destination of the packet. * Access: RO */ -- cgit v1.2.3 From 75c09280feddcf5c01c00aa11881c4b38559e2ef Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 28 Oct 2015 10:17:01 +0100 Subject: mlxsw: reg: Avoid unnecessary line wrap for mlxsw_reg_sfd_uc_unpack Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 2bf230c51955..236fb5d2ad69 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -397,10 +397,9 @@ static inline void mlxsw_reg_sfd_uc_pack(char *payload, int rec_index, mlxsw_reg_sfd_uc_system_port_set(payload, rec_index, local_port); } -static inline void -mlxsw_reg_sfd_uc_unpack(char *payload, int rec_index, - char *mac, u16 *p_vid, - u8 *p_local_port) +static inline void mlxsw_reg_sfd_uc_unpack(char *payload, int rec_index, + char *mac, u16 *p_vid, + u8 *p_local_port) { mlxsw_reg_sfd_rec_mac_memcpy_from(payload, rec_index, mac); *p_vid = mlxsw_reg_sfd_uc_fid_vid_get(payload, rec_index); -- cgit v1.2.3 From 135f9eceb7fa0287e535f9ec921485661e9d6667 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 28 Oct 2015 10:17:02 +0100 Subject: mlxsw: spectrum: Fix ageing time value The value passed through switchdev attr set is not in jiffies, but in clock_t, so fix the convert. Reported-by: Sagi Rotem Fixes: 56ade8fe3f ("mlxsw: spectrum: Add initial support for Spectrum ASIC") Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 1f3b12e8dfb4..c2d09699b6da 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -225,9 +225,10 @@ static int mlxsw_sp_ageing_set(struct mlxsw_sp *mlxsw_sp, u32 ageing_time) static int mlxsw_sp_port_attr_br_ageing_set(struct mlxsw_sp_port *mlxsw_sp_port, struct switchdev_trans *trans, - unsigned long ageing_jiffies) + unsigned long ageing_clock_t) { struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; + unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t); u32 ageing_time = jiffies_to_msecs(ageing_jiffies) / 1000; if (switchdev_trans_ph_prepare(trans)) -- cgit v1.2.3 From ef743fddb33f47b34c852f26fbd2057c72c70016 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Wed, 28 Oct 2015 10:17:03 +0100 Subject: mlxsw: Put constant on the right side of comparisons Fixes those places where checkpatch complains that comparisons should place the constant on the right side of the test. Signed-off-by: Or Gerlitz Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.c | 4 ++-- drivers/net/ethernet/mellanox/mlxsw/switchx2.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index bd80ac714a8a..97f0d93caf99 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -287,7 +287,7 @@ static void mlxsw_emad_pack_op_tlv(char *op_tlv, mlxsw_emad_op_tlv_status_set(op_tlv, 0); mlxsw_emad_op_tlv_register_id_set(op_tlv, reg->id); mlxsw_emad_op_tlv_r_set(op_tlv, MLXSW_EMAD_OP_TLV_REQUEST); - if (MLXSW_CORE_REG_ACCESS_TYPE_QUERY == type) + if (type == MLXSW_CORE_REG_ACCESS_TYPE_QUERY) mlxsw_emad_op_tlv_method_set(op_tlv, MLXSW_EMAD_OP_TLV_METHOD_QUERY); else @@ -362,7 +362,7 @@ static bool mlxsw_emad_is_resp(const struct sk_buff *skb) char *op_tlv; op_tlv = mlxsw_emad_op_tlv(skb); - return (MLXSW_EMAD_OP_TLV_RESPONSE == mlxsw_emad_op_tlv_r_get(op_tlv)); + return (mlxsw_emad_op_tlv_r_get(op_tlv) == MLXSW_EMAD_OP_TLV_RESPONSE); } #define MLXSW_EMAD_TIMEOUT_MS 200 diff --git a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c index 50e29c4879db..d85960cfb694 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/switchx2.c +++ b/drivers/net/ethernet/mellanox/mlxsw/switchx2.c @@ -1147,7 +1147,7 @@ static void mlxsw_sx_pude_event_func(const struct mlxsw_reg_info *reg, } status = mlxsw_reg_pude_oper_status_get(pude_pl); - if (MLXSW_PORT_OPER_STATUS_UP == status) { + if (status == MLXSW_PORT_OPER_STATUS_UP) { netdev_info(mlxsw_sx_port->dev, "link up\n"); netif_carrier_on(mlxsw_sx_port->dev); } else { -- cgit v1.2.3 From d9324f68eea7b01bde25ab4c204227f3583b92ba Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Wed, 28 Oct 2015 10:17:04 +0100 Subject: mlxsw: Put braces on all arms of branch statement Fix a place where checkpatch complains that braces should be used on all arms of this statement. Signed-off-by: Or Gerlitz Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 371ea3f56aed..de69e719dc9d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1662,8 +1662,9 @@ static int mlxsw_pci_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod, CIR_OUT_PARAM_LO)); memcpy(out_mbox + sizeof(tmp), &tmp, sizeof(tmp)); } - } else if (!err && out_mbox) + } else if (!err && out_mbox) { memcpy(out_mbox, mlxsw_pci->cmd.out_mbox.buf, out_mbox_size); + } mutex_unlock(&mlxsw_pci->cmd.lock); -- cgit v1.2.3 From c7070fc4ecb50bee801cef85483e043d0ba1dd27 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Wed, 28 Oct 2015 10:17:05 +0100 Subject: mlxsw: spectrum: Make mlxsw_sp_port_switchdev_ops static Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index c2d09699b6da..617fb22b5d81 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -732,7 +732,7 @@ static int mlxsw_sp_port_obj_dump(struct net_device *dev, return err; } -const struct switchdev_ops mlxsw_sp_port_switchdev_ops = { +static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = { .switchdev_port_attr_get = mlxsw_sp_port_attr_get, .switchdev_port_attr_set = mlxsw_sp_port_attr_set, .switchdev_port_obj_add = mlxsw_sp_port_obj_add, -- cgit v1.2.3 From 562b103a21974c2f9cd67514d110f918bb3e1796 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 30 Oct 2015 13:48:19 +0100 Subject: can: Use correct type in sizeof() in nla_put() The sizeof() is invoked on an incorrect variable, likely due to some copy-paste error, and this might result in memory corruption. Fix this. Signed-off-by: Marek Vasut Cc: Wolfgang Grandegger Cc: netdev@vger.kernel.org Cc: linux-stable Signed-off-by: Marc Kleine-Budde --- drivers/net/can/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index aede704605c6..141c2a42d7ed 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -915,7 +915,7 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) nla_put(skb, IFLA_CAN_BITTIMING_CONST, sizeof(*priv->bittiming_const), priv->bittiming_const)) || - nla_put(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock) || + nla_put(skb, IFLA_CAN_CLOCK, sizeof(priv->clock), &priv->clock) || nla_put_u32(skb, IFLA_CAN_STATE, state) || nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) || nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) || -- cgit v1.2.3 From f4444574a41430315a9c3eeb9e37cb0a36444a35 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 28 Oct 2015 10:20:30 -0200 Subject: fec: Use gpio_set_value_cansleep() We are in a context where we can sleep, and the FEC PHY reset gpio may be on an I2C expander. Use the cansleep() variant when setting the GPIO value. Based on a patch from Russell King for pci-mvebu.c. Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index dd4ca39d5d8f..1de1a18a0cac 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3262,7 +3262,7 @@ static void fec_reset_phy(struct platform_device *pdev) return; } msleep(msec); - gpio_set_value(phy_reset, 1); + gpio_set_value_cansleep(phy_reset, 1); } #else /* CONFIG_OF */ static void fec_reset_phy(struct platform_device *pdev) -- cgit v1.2.3 From b43c142f22236b37aa68faf23ac1bbd75f94c5b5 Mon Sep 17 00:00:00 2001 From: Pavel Fedin Date: Thu, 29 Oct 2015 09:45:22 +0300 Subject: net: smsc911x: Fix crash if loopback test fails On certain hardware in certain situations loopback test fails and the driver gets removed. During mdiobus_unregister() instance of PHY driver gets disposed. But by this time it has already been started using phy_connect_direct(). PHY driver uses DELAYED_WORK in order to maintain its state. Attempting to dispose the driver without calling phy_disconnect() causes deallocation of DELAYED_WORK being active. This shortly causes a bad crash in timer code. The problem can be discovered by enabling CONFIG_DEBUG_OBJECTS_TIMERS and CONFIG_DEBUG_OBJECTS_FREE Signed-off-by: Pavel Fedin Signed-off-by: David S. Miller --- drivers/net/ethernet/smsc/smsc911x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 3b4cd8a263de..c860c9007e49 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -1052,6 +1052,7 @@ static int smsc911x_mii_probe(struct net_device *dev) #ifdef USE_PHY_WORK_AROUND if (smsc911x_phy_loopbacktest(dev) < 0) { SMSC_WARN(pdata, hw, "Failed Loop Back Test"); + phy_disconnect(phydev); return -ENODEV; } SMSC_TRACE(pdata, hw, "Passed Loop Back Test"); -- cgit v1.2.3 From 5dbebbb44a6ad94aab2cd1a46f7676f255403f64 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Thu, 29 Oct 2015 18:11:35 -0700 Subject: net: bcmgenet: Software reset EPHY after power on The EPHY on GENET v1->v3 is extremely finicky, and will show occasional failures based on the timing and reset sequence, ranging from duplicate packets, to extremely high latencies. Perform an additional software reset, and re-configuration to make sure it is in a consistent and working state. Fixes: 6ac3ce8295e6 ("net: bcmgenet: Remove excessive PHY reset") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 4 +++- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 1 + drivers/net/ethernet/broadcom/genet/bcmmii.c | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 1805541b4240..5e3cd76cb69b 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -907,8 +907,10 @@ static void bcmgenet_power_up(struct bcmgenet_priv *priv, } bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT); - if (mode == GENET_POWER_PASSIVE) + if (mode == GENET_POWER_PASSIVE) { bcmgenet_phy_power_set(priv->dev, true); + bcmgenet_mii_reset(priv->dev); + } } /* ioctl handle special commands that are not present in ethtool. */ diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 7299d1075422..c739f7ebc992 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -674,6 +674,7 @@ int bcmgenet_mii_init(struct net_device *dev); int bcmgenet_mii_config(struct net_device *dev); int bcmgenet_mii_probe(struct net_device *dev); void bcmgenet_mii_exit(struct net_device *dev); +void bcmgenet_mii_reset(struct net_device *dev); void bcmgenet_phy_power_set(struct net_device *dev, bool enable); void bcmgenet_mii_setup(struct net_device *dev); diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index c8affad76f36..8bdfe53754ba 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -163,6 +163,7 @@ void bcmgenet_mii_setup(struct net_device *dev) phy_print_status(phydev); } + static int bcmgenet_fixed_phy_link_update(struct net_device *dev, struct fixed_phy_status *status) { @@ -172,6 +173,22 @@ static int bcmgenet_fixed_phy_link_update(struct net_device *dev, return 0; } +/* Perform a voluntary PHY software reset, since the EPHY is very finicky about + * not doing it and will start corrupting packets + */ +void bcmgenet_mii_reset(struct net_device *dev) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + + if (GENET_IS_V4(priv)) + return; + + if (priv->phydev) { + phy_init_hw(priv->phydev); + phy_start_aneg(priv->phydev); + } +} + void bcmgenet_phy_power_set(struct net_device *dev, bool enable) { struct bcmgenet_priv *priv = netdev_priv(dev); @@ -214,6 +231,7 @@ static void bcmgenet_internal_phy_setup(struct net_device *dev) reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT); reg |= EXT_PWR_DN_EN_LD; bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT); + bcmgenet_mii_reset(dev); } static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv) -- cgit v1.2.3 From 76e398a6271285c1f361d66445a55cdcee5c1b4b Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Sun, 1 Nov 2015 12:33:55 -0500 Subject: net: dsa: use switchdev obj for VLAN add/del ops Simplify DSA by pushing the switchdev objects for VLAN add and delete operations down to its drivers. Currently only mv88e6xxx is affected. Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6171.c | 2 +- drivers/net/dsa/mv88e6352.c | 2 +- drivers/net/dsa/mv88e6xxx.c | 108 +++++++++++++++++++++++++++++++++++--------- drivers/net/dsa/mv88e6xxx.h | 12 +++-- 4 files changed, 97 insertions(+), 27 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 2c8eb6f76ebe..1bd876e3f990 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -115,7 +115,7 @@ struct dsa_switch_driver mv88e6171_switch_driver = { .get_regs = mv88e6xxx_get_regs, .port_stp_update = mv88e6xxx_port_stp_update, .port_pvid_get = mv88e6xxx_port_pvid_get, - .port_pvid_set = mv88e6xxx_port_pvid_set, + .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, .port_vlan_add = mv88e6xxx_port_vlan_add, .port_vlan_del = mv88e6xxx_port_vlan_del, .vlan_getnext = mv88e6xxx_vlan_getnext, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index cbf4dd8721a6..4458d6ae7b69 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -342,7 +342,7 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .get_regs = mv88e6xxx_get_regs, .port_stp_update = mv88e6xxx_port_stp_update, .port_pvid_get = mv88e6xxx_port_pvid_get, - .port_pvid_set = mv88e6xxx_port_pvid_set, + .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, .port_vlan_add = mv88e6xxx_port_vlan_add, .port_vlan_del = mv88e6xxx_port_vlan_del, .vlan_getnext = mv88e6xxx_vlan_getnext, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index b1b14f519d8b..9ee1be20a946 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1121,6 +1121,19 @@ int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state) return 0; } +static int _mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid) +{ + int ret; + + ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_DEFAULT_VLAN); + if (ret < 0) + return ret; + + *pvid = ret & PORT_DEFAULT_VLAN_MASK; + + return 0; +} + int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid) { int ret; @@ -1134,9 +1147,9 @@ int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *pvid) return 0; } -int mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 pvid) +static int _mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 pvid) { - return mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_DEFAULT_VLAN, + return _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_DEFAULT_VLAN, pvid & PORT_DEFAULT_VLAN_MASK); } @@ -1441,61 +1454,87 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid, return 0; } -int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid, - bool untagged) +int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans) +{ + /* We don't need any dynamic resource from the kernel (yet), + * so skip the prepare phase. + */ + return 0; +} + +static int _mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid, + bool untagged) { - struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_vtu_stu_entry vlan; int err; - mutex_lock(&ps->smi_mutex); - err = _mv88e6xxx_vtu_vid_write(ds, vid - 1); if (err) - goto unlock; + return err; err = _mv88e6xxx_vtu_getnext(ds, &vlan); if (err) - goto unlock; + return err; if (vlan.vid != vid || !vlan.valid) { err = _mv88e6xxx_vlan_init(ds, vid, &vlan); if (err) - goto unlock; + return err; } vlan.data[port] = untagged ? GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED : GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED; - err = _mv88e6xxx_vtu_loadpurge(ds, &vlan); + return _mv88e6xxx_vtu_loadpurge(ds, &vlan); +} + +int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; + u16 vid; + int err = 0; + + mutex_lock(&ps->smi_mutex); + + for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { + err = _mv88e6xxx_port_vlan_add(ds, port, vid, untagged); + if (err) + goto unlock; + } + + /* no PVID with ranges, otherwise it's a bug */ + if (pvid) + err = _mv88e6xxx_port_pvid_set(ds, port, vid); unlock: mutex_unlock(&ps->smi_mutex); return err; } -int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) +static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); struct mv88e6xxx_vtu_stu_entry vlan; int i, err; - mutex_lock(&ps->smi_mutex); - err = _mv88e6xxx_vtu_vid_write(ds, vid - 1); if (err) - goto unlock; + return err; err = _mv88e6xxx_vtu_getnext(ds, &vlan); if (err) - goto unlock; + return err; if (vlan.vid != vid || !vlan.valid || - vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) { - err = -ENOENT; - goto unlock; - } + vlan.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) + return -ENOENT; vlan.data[port] = GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER; @@ -1512,10 +1551,37 @@ int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) } err = _mv88e6xxx_vtu_loadpurge(ds, &vlan); + if (err) + return err; + + return _mv88e6xxx_atu_remove(ds, vlan.fid, port, false); +} + +int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + u16 pvid, vid; + int err = 0; + + mutex_lock(&ps->smi_mutex); + + err = _mv88e6xxx_port_pvid_get(ds, port, &pvid); if (err) goto unlock; - err = _mv88e6xxx_atu_remove(ds, vlan.fid, port, false); + for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) { + err = _mv88e6xxx_port_vlan_del(ds, port, vid); + if (err) + goto unlock; + + if (vid == pvid) { + err = _mv88e6xxx_port_pvid_set(ds, port, 0); + if (err) + goto unlock; + } + } + unlock: mutex_unlock(&ps->smi_mutex); diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 6f9ed5d45012..e0692b95b2c9 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -457,11 +457,15 @@ int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e); int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, struct phy_device *phydev, struct ethtool_eee *e); int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state); +int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans); +int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct switchdev_trans *trans); +int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan); int mv88e6xxx_port_pvid_get(struct dsa_switch *ds, int port, u16 *vid); -int mv88e6xxx_port_pvid_set(struct dsa_switch *ds, int port, u16 vid); -int mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, u16 vid, - bool untagged); -int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid); int mv88e6xxx_vlan_getnext(struct dsa_switch *ds, u16 *vid, unsigned long *ports, unsigned long *untagged); int mv88e6xxx_port_fdb_prepare(struct dsa_switch *ds, int port, -- cgit v1.2.3 From 1cf7d8dda2bd1704ca8552c93d5475af444a986b Mon Sep 17 00:00:00 2001 From: huangdaode Date: Fri, 30 Oct 2015 10:50:54 +0800 Subject: net: hisilicon: Remove .owner assignment from platform_driver platform_driver doesn't need to set .owner, because platform_driver_register() will set it. Signed-off-by: huangdaode Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 302d3ae8e9e5..08cef0dfb5db 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1628,7 +1628,6 @@ MODULE_DEVICE_TABLE(of, hns_enet_of_match); static struct platform_driver hns_nic_dev_driver = { .driver = { .name = "hns-nic", - .owner = THIS_MODULE, .of_match_table = hns_enet_of_match, }, .probe = hns_nic_dev_probe, -- cgit v1.2.3 From e6dbe1eb2db0d7a14991c06278dd3030c45fb825 Mon Sep 17 00:00:00 2001 From: Phil Reid Date: Fri, 30 Oct 2015 16:43:55 +0800 Subject: stmmac: Correctly report PTP capabilities. priv->hwts_*_en indicate if timestamping is enabled/disabled at run time. But priv->dma_cap.time_stamp and priv->dma_cap.atime_stamp indicates HW is support for PTPv1/PTPv2. Signed-off-by: Phil Reid Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 771cda2a48b2..2e51b816a7e8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -721,10 +721,13 @@ static int stmmac_get_ts_info(struct net_device *dev, { struct stmmac_priv *priv = netdev_priv(dev); - if ((priv->hwts_tx_en) && (priv->hwts_rx_en)) { + if ((priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) { - info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE | + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_RAW_HARDWARE; if (priv->ptp_clock) -- cgit v1.2.3 From 322cf7e3a4e89236ae386cb5668ae0d787d21136 Mon Sep 17 00:00:00 2001 From: Govindarajulu Varadarajan <_govind@gmx.com> Date: Fri, 30 Oct 2015 16:52:51 +0530 Subject: enic: assign affinity hint to interrupts The affinity hint is used by the user space daemon, irqbalancer, to indicate a preferred CPU mask for irqs. This patch sets the irq affinity hint to local numa core first, when exausted we try non-local numa cores. Also set tx xps cpus mask bassed on affinity hint. v2: remove the global affinity policy. Signed-off-by: Govindarajulu Varadarajan <_govind@gmx.com> Signed-off-by: David S. Miller --- drivers/net/ethernet/cisco/enic/enic.h | 27 +++++++++++ drivers/net/ethernet/cisco/enic/enic_main.c | 72 +++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h index 6401ba99457f..1671fa3332c2 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -50,6 +50,7 @@ struct enic_msix_entry { char devname[IFNAMSIZ]; irqreturn_t (*isr)(int, void *); void *devid; + cpumask_var_t affinity_mask; }; /* Store only the lower range. Higher range is given by fw. */ @@ -263,6 +264,32 @@ static inline unsigned int enic_msix_notify_intr(struct enic *enic) return enic->rq_count + enic->wq_count + 1; } +static inline bool enic_is_err_intr(struct enic *enic, int intr) +{ + switch (vnic_dev_get_intr_mode(enic->vdev)) { + case VNIC_DEV_INTR_MODE_INTX: + return intr == enic_legacy_err_intr(); + case VNIC_DEV_INTR_MODE_MSIX: + return intr == enic_msix_err_intr(enic); + case VNIC_DEV_INTR_MODE_MSI: + default: + return false; + } +} + +static inline bool enic_is_notify_intr(struct enic *enic, int intr) +{ + switch (vnic_dev_get_intr_mode(enic->vdev)) { + case VNIC_DEV_INTR_MODE_INTX: + return intr == enic_legacy_notify_intr(); + case VNIC_DEV_INTR_MODE_MSIX: + return intr == enic_msix_notify_intr(enic); + case VNIC_DEV_INTR_MODE_MSI: + default: + return false; + } +} + static inline int enic_dma_map_check(struct enic *enic, dma_addr_t dma_addr) { if (unlikely(pci_dma_mapping_error(enic->pdev, dma_addr))) { diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 0c22fd014378..b36643ef0593 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef CONFIG_RFS_ACCEL #include #endif @@ -112,6 +113,71 @@ static struct enic_intr_mod_range mod_range[ENIC_MAX_LINK_SPEEDS] = { {3, 6}, /* 10 - 40 Gbps */ }; +static void enic_init_affinity_hint(struct enic *enic) +{ + int numa_node = dev_to_node(&enic->pdev->dev); + int i; + + for (i = 0; i < enic->intr_count; i++) { + if (enic_is_err_intr(enic, i) || enic_is_notify_intr(enic, i) || + (enic->msix[i].affinity_mask && + !cpumask_empty(enic->msix[i].affinity_mask))) + continue; + if (zalloc_cpumask_var(&enic->msix[i].affinity_mask, + GFP_KERNEL)) + cpumask_set_cpu(cpumask_local_spread(i, numa_node), + enic->msix[i].affinity_mask); + } +} + +static void enic_free_affinity_hint(struct enic *enic) +{ + int i; + + for (i = 0; i < enic->intr_count; i++) { + if (enic_is_err_intr(enic, i) || enic_is_notify_intr(enic, i)) + continue; + free_cpumask_var(enic->msix[i].affinity_mask); + } +} + +static void enic_set_affinity_hint(struct enic *enic) +{ + int i; + int err; + + for (i = 0; i < enic->intr_count; i++) { + if (enic_is_err_intr(enic, i) || + enic_is_notify_intr(enic, i) || + !enic->msix[i].affinity_mask || + cpumask_empty(enic->msix[i].affinity_mask)) + continue; + err = irq_set_affinity_hint(enic->msix_entry[i].vector, + enic->msix[i].affinity_mask); + if (err) + netdev_warn(enic->netdev, "irq_set_affinity_hint failed, err %d\n", + err); + } + + for (i = 0; i < enic->wq_count; i++) { + int wq_intr = enic_msix_wq_intr(enic, i); + + if (enic->msix[wq_intr].affinity_mask && + !cpumask_empty(enic->msix[wq_intr].affinity_mask)) + netif_set_xps_queue(enic->netdev, + enic->msix[wq_intr].affinity_mask, + i); + } +} + +static void enic_unset_affinity_hint(struct enic *enic) +{ + int i; + + for (i = 0; i < enic->intr_count; i++) + irq_set_affinity_hint(enic->msix_entry[i].vector, NULL); +} + int enic_is_dynamic(struct enic *enic) { return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_DYN; @@ -1649,6 +1715,8 @@ static int enic_open(struct net_device *netdev) netdev_err(netdev, "Unable to request irq.\n"); return err; } + enic_init_affinity_hint(enic); + enic_set_affinity_hint(enic); err = enic_dev_notify_set(enic); if (err) { @@ -1701,6 +1769,7 @@ err_out_free_rq: vnic_rq_clean(&enic->rq[i], enic_free_rq_buf); enic_dev_notify_unset(enic); err_out_free_intr: + enic_unset_affinity_hint(enic); enic_free_intr(enic); return err; @@ -1754,6 +1823,7 @@ static int enic_stop(struct net_device *netdev) } enic_dev_notify_unset(enic); + enic_unset_affinity_hint(enic); enic_free_intr(enic); for (i = 0; i < enic->wq_count; i++) @@ -2309,6 +2379,7 @@ static void enic_dev_deinit(struct enic *enic) enic_free_vnic_resources(enic); enic_clear_intr_mode(enic); + enic_free_affinity_hint(enic); } static void enic_kdump_kernel_config(struct enic *enic) @@ -2404,6 +2475,7 @@ static int enic_dev_init(struct enic *enic) return 0; err_out_free_vnic_resources: + enic_free_affinity_hint(enic); enic_clear_intr_mode(enic); enic_free_vnic_resources(enic); -- cgit v1.2.3 From d0cb48cd19ce1e249cd350aa67fbf63560292266 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 30 Oct 2015 13:49:17 +0100 Subject: net: encx24j600: Fix SPI id table definition A driver's SPI id table is expected to be an array of struct spi_device_id that ends with a zero-initialized sentinel entry. But this driver defines the table as a single struct spi_device_id and sets .id_table to a pointer to this struct. But spi_match_id() has a loop that iterates while the struct spi_device_id .name[0] is not NULL, so not having a sentinel can cause a NULL pointer deference error. This patch defines the SPI id table correctly as all other SPI drivers do. Signed-off-by: Javier Martinez Canillas Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/encx24j600.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c index bf08ce2baf8d..c2dafc1c53de 100644 --- a/drivers/net/ethernet/microchip/encx24j600.c +++ b/drivers/net/ethernet/microchip/encx24j600.c @@ -1094,8 +1094,9 @@ static int encx24j600_spi_remove(struct spi_device *spi) return 0; } -static const struct spi_device_id encx24j600_spi_id_table = { - .name = "encx24j600" +static const struct spi_device_id encx24j600_spi_id_table[] = { + { .name = "encx24j600" }, + { /* sentinel */ } }; static struct spi_driver encx24j600_spi_net_driver = { @@ -1106,7 +1107,7 @@ static struct spi_driver encx24j600_spi_net_driver = { }, .probe = encx24j600_spi_probe, .remove = encx24j600_spi_remove, - .id_table = &encx24j600_spi_id_table, + .id_table = encx24j600_spi_id_table, }; static int __init encx24j600_init(void) -- cgit v1.2.3 From 07f56c616d06b966c0a63d16172935b257a6a8d4 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 30 Oct 2015 13:49:18 +0100 Subject: net: encx24j600: Export missing SPI module alias information The driver Kconfig symbol is tristate which means that it can be built as a module but the module alias information is not added to the module info so module autoload won't work since user-space won't have the information. Signed-off-by: Javier Martinez Canillas Signed-off-by: David S. Miller --- drivers/net/ethernet/microchip/encx24j600.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c index c2dafc1c53de..2056b719c262 100644 --- a/drivers/net/ethernet/microchip/encx24j600.c +++ b/drivers/net/ethernet/microchip/encx24j600.c @@ -1098,6 +1098,7 @@ static const struct spi_device_id encx24j600_spi_id_table[] = { { .name = "encx24j600" }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(spi, encx24j600_spi_id_table); static struct spi_driver encx24j600_spi_net_driver = { .driver = { -- cgit v1.2.3 From 3996a4ffb01f57f82abe6c7e60ac9048dd0c31df Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 30 Oct 2015 18:56:45 -0400 Subject: net: dsa: mv88e6xxx: assert SMI lock It's easy to forget to lock the smi_mutex before calling the low-level _mv88e6xxx_reg_{read,write}, so add a assert_smi_lock function in them. Signed-off-by: Vivien Didelot Acked-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 9ee1be20a946..d8866988a88a 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -24,6 +24,16 @@ #include #include "mv88e6xxx.h" +static void assert_smi_lock(struct dsa_switch *ds) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + + if (unlikely(!mutex_is_locked(&ps->smi_mutex))) { + dev_err(ds->master_dev, "SMI lock not held!\n"); + dump_stack(); + } +} + /* If the switch's ADDR[4:0] strap pins are strapped to zero, it will * use all 32 SMI bus addresses on its SMI bus, and all switch registers * will be directly accessible on some {device address,register address} @@ -80,12 +90,13 @@ int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg) return ret & 0xffff; } -/* Must be called with SMI mutex held */ static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg) { struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); int ret; + assert_smi_lock(ds); + if (bus == NULL) return -EINVAL; @@ -143,12 +154,13 @@ int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, return 0; } -/* Must be called with SMI mutex held */ static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) { struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev); + assert_smi_lock(ds); + if (bus == NULL) return -EINVAL; @@ -204,7 +216,6 @@ int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr) return 0; } -/* Must be called with SMI mutex held */ static int _mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum) { if (addr >= 0) @@ -212,7 +223,6 @@ static int _mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum) return 0xffff; } -/* Must be called with SMI mutex held */ static int _mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum, u16 val) { @@ -538,7 +548,6 @@ out: mutex_unlock(&ps->smi_mutex); } -/* Must be called with SMI mutex held */ static int _mv88e6xxx_stats_wait(struct dsa_switch *ds) { int ret; @@ -553,7 +562,6 @@ static int _mv88e6xxx_stats_wait(struct dsa_switch *ds) return -ETIMEDOUT; } -/* Must be called with SMI mutex held */ static int _mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port) { int ret; @@ -576,7 +584,6 @@ static int _mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port) return 0; } -/* Must be called with SMI mutex held */ static void _mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val) { u32 _val; @@ -789,7 +796,6 @@ void mv88e6xxx_get_regs(struct dsa_switch *ds, int port, } } -/* Must be called with SMI lock held */ static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask) { @@ -839,14 +845,12 @@ int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds) GLOBAL2_EEPROM_OP_BUSY); } -/* Must be called with SMI lock held */ static int _mv88e6xxx_atu_wait(struct dsa_switch *ds) { return _mv88e6xxx_wait(ds, REG_GLOBAL, GLOBAL_ATU_OP, GLOBAL_ATU_OP_BUSY); } -/* Must be called with SMI mutex held */ static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum) { @@ -865,7 +869,6 @@ static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, return _mv88e6xxx_reg_read(ds, REG_GLOBAL2, GLOBAL2_SMI_DATA); } -/* Must be called with SMI mutex held */ static int _mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum, u16 val) { -- cgit v1.2.3 From b9b377136eb83cace5667cb6e8d53da771df6faa Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Fri, 30 Oct 2015 19:39:48 -0400 Subject: net: dsa: mv88e6xxx: lookup switch name All the mv88e6xxx drivers use the exact same code in their probe function to lookup the switch name given its ID. Thus introduce a mv88e6xxx_switch_id structure and a mv88e6xxx_lookup_name function in the common mv88e6xxx code. In the meantime make __mv88e6xxx_reg_{read,write} static since we do not need to expose these low-level r/w routines anymore. Signed-off-by: Vivien Didelot Acked-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6123_61_65.c | 45 +++++++++++------------------------ drivers/net/dsa/mv88e6131.c | 33 ++++++++------------------ drivers/net/dsa/mv88e6171.c | 28 +++++++--------------- drivers/net/dsa/mv88e6352.c | 49 +++++++++++++-------------------------- drivers/net/dsa/mv88e6xxx.c | 39 ++++++++++++++++++++++++++++--- drivers/net/dsa/mv88e6xxx.h | 13 ++++++++--- 6 files changed, 95 insertions(+), 112 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c index 4bcfd683bbea..d4fcf4570d95 100644 --- a/drivers/net/dsa/mv88e6123_61_65.c +++ b/drivers/net/dsa/mv88e6123_61_65.c @@ -17,39 +17,22 @@ #include #include "mv88e6xxx.h" +static const struct mv88e6xxx_switch_id mv88e6123_61_65_table[] = { + { PORT_SWITCH_ID_6123, "Marvell 88E6123" }, + { PORT_SWITCH_ID_6123_A1, "Marvell 88E6123 (A1)" }, + { PORT_SWITCH_ID_6123_A2, "Marvell 88E6123 (A2)" }, + { PORT_SWITCH_ID_6161, "Marvell 88E6161" }, + { PORT_SWITCH_ID_6161_A1, "Marvell 88E6161 (A1)" }, + { PORT_SWITCH_ID_6161_A2, "Marvell 88E6161 (A2)" }, + { PORT_SWITCH_ID_6165, "Marvell 88E6165" }, + { PORT_SWITCH_ID_6165_A1, "Marvell 88E6165 (A1)" }, + { PORT_SWITCH_ID_6165_A2, "Marvell 88e6165 (A2)" }, +}; + static char *mv88e6123_61_65_probe(struct device *host_dev, int sw_addr) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); - int ret; - - if (bus == NULL) - return NULL; - - ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); - if (ret >= 0) { - if (ret == PORT_SWITCH_ID_6123_A1) - return "Marvell 88E6123 (A1)"; - if (ret == PORT_SWITCH_ID_6123_A2) - return "Marvell 88E6123 (A2)"; - if ((ret & 0xfff0) == PORT_SWITCH_ID_6123) - return "Marvell 88E6123"; - - if (ret == PORT_SWITCH_ID_6161_A1) - return "Marvell 88E6161 (A1)"; - if (ret == PORT_SWITCH_ID_6161_A2) - return "Marvell 88E6161 (A2)"; - if ((ret & 0xfff0) == PORT_SWITCH_ID_6161) - return "Marvell 88E6161"; - - if (ret == PORT_SWITCH_ID_6165_A1) - return "Marvell 88E6165 (A1)"; - if (ret == PORT_SWITCH_ID_6165_A2) - return "Marvell 88e6165 (A2)"; - if ((ret & 0xfff0) == PORT_SWITCH_ID_6165) - return "Marvell 88E6165"; - } - - return NULL; + return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6123_61_65_table, + ARRAY_SIZE(mv88e6123_61_65_table)); } static int mv88e6123_61_65_setup_global(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c index c73121c8f155..a92ca651c399 100644 --- a/drivers/net/dsa/mv88e6131.c +++ b/drivers/net/dsa/mv88e6131.c @@ -17,31 +17,18 @@ #include #include "mv88e6xxx.h" +static const struct mv88e6xxx_switch_id mv88e6131_table[] = { + { PORT_SWITCH_ID_6085, "Marvell 88E6085" }, + { PORT_SWITCH_ID_6095, "Marvell 88E6095/88E6095F" }, + { PORT_SWITCH_ID_6131, "Marvell 88E6131" }, + { PORT_SWITCH_ID_6131_B2, "Marvell 88E6131 (B2)" }, + { PORT_SWITCH_ID_6185, "Marvell 88E6185" }, +}; + static char *mv88e6131_probe(struct device *host_dev, int sw_addr) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); - int ret; - - if (bus == NULL) - return NULL; - - ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); - if (ret >= 0) { - int ret_masked = ret & 0xfff0; - - if (ret_masked == PORT_SWITCH_ID_6085) - return "Marvell 88E6085"; - if (ret_masked == PORT_SWITCH_ID_6095) - return "Marvell 88E6095/88E6095F"; - if (ret == PORT_SWITCH_ID_6131_B2) - return "Marvell 88E6131 (B2)"; - if (ret_masked == PORT_SWITCH_ID_6131) - return "Marvell 88E6131"; - if (ret_masked == PORT_SWITCH_ID_6185) - return "Marvell 88E6185"; - } - - return NULL; + return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6131_table, + ARRAY_SIZE(mv88e6131_table)); } static int mv88e6131_setup_global(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 1bd876e3f990..54aa00012dd0 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -17,27 +17,17 @@ #include #include "mv88e6xxx.h" +static const struct mv88e6xxx_switch_id mv88e6171_table[] = { + { PORT_SWITCH_ID_6171, "Marvell 88E6171" }, + { PORT_SWITCH_ID_6175, "Marvell 88E6175" }, + { PORT_SWITCH_ID_6350, "Marvell 88E6350" }, + { PORT_SWITCH_ID_6351, "Marvell 88E6351" }, +}; + static char *mv88e6171_probe(struct device *host_dev, int sw_addr) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); - int ret; - - if (bus == NULL) - return NULL; - - ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); - if (ret >= 0) { - if ((ret & 0xfff0) == PORT_SWITCH_ID_6171) - return "Marvell 88E6171"; - if ((ret & 0xfff0) == PORT_SWITCH_ID_6175) - return "Marvell 88E6175"; - if ((ret & 0xfff0) == PORT_SWITCH_ID_6350) - return "Marvell 88E6350"; - if ((ret & 0xfff0) == PORT_SWITCH_ID_6351) - return "Marvell 88E6351"; - } - - return NULL; + return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6171_table, + ARRAY_SIZE(mv88e6171_table)); } static int mv88e6171_setup_global(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index 4458d6ae7b69..ff846d0cfceb 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -22,41 +22,24 @@ #include #include "mv88e6xxx.h" +static const struct mv88e6xxx_switch_id mv88e6352_table[] = { + { PORT_SWITCH_ID_6172, "Marvell 88E6172" }, + { PORT_SWITCH_ID_6176, "Marvell 88E6176" }, + { PORT_SWITCH_ID_6320, "Marvell 88E6320" }, + { PORT_SWITCH_ID_6320_A1, "Marvell 88E6320 (A1)" }, + { PORT_SWITCH_ID_6320_A2, "Marvell 88e6320 (A2)" }, + { PORT_SWITCH_ID_6321, "Marvell 88E6321" }, + { PORT_SWITCH_ID_6321_A1, "Marvell 88E6321 (A1)" }, + { PORT_SWITCH_ID_6321_A2, "Marvell 88e6321 (A2)" }, + { PORT_SWITCH_ID_6352, "Marvell 88E6352" }, + { PORT_SWITCH_ID_6352_A0, "Marvell 88E6352 (A0)" }, + { PORT_SWITCH_ID_6352_A1, "Marvell 88E6352 (A1)" }, +}; + static char *mv88e6352_probe(struct device *host_dev, int sw_addr) { - struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); - int ret; - - if (bus == NULL) - return NULL; - - ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); - if (ret >= 0) { - if ((ret & 0xfff0) == PORT_SWITCH_ID_6172) - return "Marvell 88E6172"; - if ((ret & 0xfff0) == PORT_SWITCH_ID_6176) - return "Marvell 88E6176"; - if (ret == PORT_SWITCH_ID_6320_A1) - return "Marvell 88E6320 (A1)"; - if (ret == PORT_SWITCH_ID_6320_A2) - return "Marvell 88e6320 (A2)"; - if ((ret & 0xfff0) == PORT_SWITCH_ID_6320) - return "Marvell 88E6320"; - if (ret == PORT_SWITCH_ID_6321_A1) - return "Marvell 88E6321 (A1)"; - if (ret == PORT_SWITCH_ID_6321_A2) - return "Marvell 88e6321 (A2)"; - if ((ret & 0xfff0) == PORT_SWITCH_ID_6321) - return "Marvell 88E6321"; - if (ret == PORT_SWITCH_ID_6352_A0) - return "Marvell 88E6352 (A0)"; - if (ret == PORT_SWITCH_ID_6352_A1) - return "Marvell 88E6352 (A1)"; - if ((ret & 0xfff0) == PORT_SWITCH_ID_6352) - return "Marvell 88E6352"; - } - - return NULL; + return mv88e6xxx_lookup_name(host_dev, sw_addr, mv88e6352_table, + ARRAY_SIZE(mv88e6352_table)); } static int mv88e6352_setup_global(struct dsa_switch *ds) diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index d8866988a88a..85228f44c2b5 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -59,7 +59,8 @@ static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr) return -ETIMEDOUT; } -int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg) +static int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, + int reg) { int ret; @@ -122,8 +123,8 @@ int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg) return ret; } -int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, - int reg, u16 val) +static int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, + int reg, u16 val) { int ret; @@ -2546,6 +2547,38 @@ int mv88e6xxx_get_temp_alarm(struct dsa_switch *ds, bool *alarm) } #endif /* CONFIG_NET_DSA_HWMON */ +char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, + const struct mv88e6xxx_switch_id *table, + unsigned int num) +{ + struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); + int i, ret; + + if (!bus) + return NULL; + + ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); + if (ret < 0) + return NULL; + + /* Look up the exact switch ID */ + for (i = 0; i < num; ++i) + if (table[i].id == ret) + return table[i].name; + + /* Look up only the product number */ + for (i = 0; i < num; ++i) { + if (table[i].id == (ret & PORT_SWITCH_ID_PROD_NUM_MASK)) { + dev_warn(host_dev, "unknown revision %d, using base switch 0x%x\n", + ret & PORT_SWITCH_ID_REV_MASK, + ret & PORT_SWITCH_ID_PROD_NUM_MASK); + return table[i].name; + } + } + + return NULL; +} + static int __init mv88e6xxx_init(void) { #if IS_ENABLED(CONFIG_NET_DSA_MV88E6131) diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index e0692b95b2c9..ad9958f09aa7 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -60,6 +60,8 @@ #define PORT_PCS_CTRL_UNFORCED 0x03 #define PORT_PAUSE_CTRL 0x02 #define PORT_SWITCH_ID 0x03 +#define PORT_SWITCH_ID_PROD_NUM_MASK 0xfff0 +#define PORT_SWITCH_ID_REV_MASK 0x000f #define PORT_SWITCH_ID_6031 0x0310 #define PORT_SWITCH_ID_6035 0x0350 #define PORT_SWITCH_ID_6046 0x0480 @@ -347,6 +349,11 @@ #define GLOBAL2_QOS_WEIGHT 0x1c #define GLOBAL2_MISC 0x1d +struct mv88e6xxx_switch_id { + u16 id; + char *name; +}; + struct mv88e6xxx_atu_entry { u16 fid; u8 state; @@ -415,13 +422,13 @@ struct mv88e6xxx_hw_stat { }; int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active); +char *mv88e6xxx_lookup_name(struct device *host_dev, int sw_addr, + const struct mv88e6xxx_switch_id *table, + unsigned int num); int mv88e6xxx_setup_ports(struct dsa_switch *ds); int mv88e6xxx_setup_common(struct dsa_switch *ds); int mv88e6xxx_setup_global(struct dsa_switch *ds); -int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg); int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg); -int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr, - int reg, u16 val); int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val); int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr); int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr); -- cgit v1.2.3 From 2c94e8567d7c7c9d619584da857e9f5b28f283ea Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 31 Oct 2015 02:05:56 +0300 Subject: sh_eth: fix uninitialized arrays in sh_eth_ring_init() sh_eth_ring_free() called in the sh_eth_ring_init()'s error path expects the arrays pointed to by 'sh_eth_private::[rt]x_skbuff' to be initialized with NULLs but they are allocated with just kmalloc_array() and so are left filled with random data. Use kcalloc() instead. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index a484d8beb855..6e42851e97c8 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1212,15 +1212,15 @@ static int sh_eth_ring_init(struct net_device *ndev) mdp->rx_buf_sz += NET_IP_ALIGN; /* Allocate RX and TX skb rings */ - mdp->rx_skbuff = kmalloc_array(mdp->num_rx_ring, - sizeof(*mdp->rx_skbuff), GFP_KERNEL); + mdp->rx_skbuff = kcalloc(mdp->num_rx_ring, sizeof(*mdp->rx_skbuff), + GFP_KERNEL); if (!mdp->rx_skbuff) { ret = -ENOMEM; return ret; } - mdp->tx_skbuff = kmalloc_array(mdp->num_tx_ring, - sizeof(*mdp->tx_skbuff), GFP_KERNEL); + mdp->tx_skbuff = kcalloc(mdp->num_tx_ring, sizeof(*mdp->tx_skbuff), + GFP_KERNEL); if (!mdp->tx_skbuff) { ret = -ENOMEM; goto skb_ring_free; -- cgit v1.2.3 From b61ed8fdd845340ee31e8a97403b6101ccf4e4a2 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 31 Oct 2015 02:06:29 +0300 Subject: sh_eth: fix WARNING in dma_common_free_remap() Iff the first dma_alloc_coherent() call fails in sh_eth_ring_init(), the following is printed to the kernel console: WARNING: CPU: 0 PID: 1 at drivers/base/dma-mapping.c:334 dma_common_free_remap+0x48/0x6c() trying to free invalid coherent area: (null) Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.3.0-rc7-dirty #969 Hardware name: Generic R8A7791 (Flattened Device Tree) Backtrace: [] (dump_backtrace) from [] (show_stack+0x18/0x1c) r6:c0662856 r5:00000009 r4:00000000 r3:00204140 [] (show_stack) from [] (dump_stack+0x74/0x90) [] (dump_stack) from [] (warn_slowpath_common+0x8c/0xb8) r4:ee84dce0 r3:c0712774 [] (warn_slowpath_common) from [] (warn_slowpath_fmt+0x38/0x40) r8:ee7f8000 r7:c0734520 r6:00001000 r5:20000008 r4:00000000 [] (warn_slowpath_fmt) from [] (dma_common_free_remap+0x48/0x6c) r3:00000000 r2:c0662871 [] (dma_common_free_remap) from [] (__arm_dma_free+0xb8/0xd4) r6:00000001 r5:00000000 r4:00001000 r3:ee8c5584 [] (__arm_dma_free) from [] (arm_dma_free+0x24/0x2c) r10:0000016b r8:00000000 r7:ee9bc830 r6:00000000 r5:00000400 r4:ee9bc800 [] (arm_dma_free) from [] (sh_eth_ring_init+0x110/0x138) [] (sh_eth_ring_init) from [] (sh_eth_open+0x94/0x1f4) r6:00000000 r5:ee9bcd18 r4:ee9bc800 [] (sh_eth_open) from [] (__dev_open+0x84/0x104) r6:c0565c50 r5:00000000 r4:ee9bc800 [] (__dev_open) from [] (__dev_change_flags+0x94/0x13c) r7:00001002 r6:00000001 r5:00001003 r4:ee9bc800 [] (__dev_change_flags) from [] (dev_change_flags+0x20/0x50) r7:c072c8a0 r6:00000138 r5:00001002 r4:ee9bc800 [] (dev_change_flags) from [] (ip_auto_config+0x174/0xf7c) r8:00001002 r7:c072c8a0 r6:c0700040 r5:00000001 r4:ee9bc800 r3:00000101 [] (ip_auto_config) from [] (do_one_initcall+0x100/0x1c8) r10:c06f883c r9:00000000 r8:c06e8bd8 r7:c0734000 r6:c070e918 r5:c070e918 r4:ee083640 [] (do_one_initcall) from [] (kernel_init_freeable+0x11c/0x1ec) r10:c06f883c r9:00000000 r8:00000099 r7:c0734000 r6:c070372c r5:c06f8834 r4:00000007 [] (kernel_init_freeable) from [] (kernel_init+0x14/0xec) r10:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c0514d64 r4:c0734000 [] (kernel_init) from [] (ret_from_fork+0x14/0x3c) r4:00000000 r3:ee84c000 This is because the code jumps to a wrong label and so tries to free yet unallocated coherent memory. Fix the *goto* in question. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 6e42851e97c8..459c93aff03e 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1232,7 +1232,7 @@ static int sh_eth_ring_init(struct net_device *ndev) GFP_KERNEL); if (!mdp->rx_ring) { ret = -ENOMEM; - goto desc_ring_free; + goto skb_ring_free; } mdp->dirty_rx = 0; -- cgit v1.2.3 From 70910791731b5956171e1bfcad707766b8e18fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Sun, 1 Nov 2015 01:34:50 +0100 Subject: qmi_wwan: fix entry for HP lt4112 LTE/HSPA+ Gobi 4G Module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The lt4112 is a HP branded Huawei me906e modem. Like other Huawei modems, it does not have a fixed interface to function mapping. Instead it uses a Huawei specific scheme: functions are mapped by subclass and protocol. However, the HP vendor ID is used for modems from many different manufacturers using different schemes, so we cannot apply a generic vendor rule like we do for the Huawei vendor ID. Replace the previous lt4112 entry pointing to an arbitrary interface number with a device specific subclass + protocol match. Reported-and-tested-by: Muri Nicanor Tested-by: Martin Hauke Fixes: bb2bdeb83fb1 ("qmi_wwan: Add support for HP lt4112 LTE/HSPA+ Gobi 4G Modem") Signed-off-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 2a7c1be23c4f..1ba1fdc34988 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -539,6 +539,10 @@ static const struct usb_device_id products[] = { USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&qmi_wwan_info, }, + { /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */ + USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7), + .driver_info = (unsigned long)&qmi_wwan_info, + }, /* 3. Combined interface devices matching on interface number */ {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ @@ -791,7 +795,6 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ {QMI_FIXED_INTF(0x413c, 0x81b1, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */ {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ - {QMI_FIXED_INTF(0x03f0, 0x581d, 4)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ -- cgit v1.2.3 From 4ab42d78e37a294ac7bc56901d563c642e03c4ae Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 1 Nov 2015 16:22:53 +0000 Subject: ppp, slip: Validate VJ compression slot parameters completely MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently slhc_init() treats out-of-range values of rslots and tslots as equivalent to 0, except that if tslots is too large it will dereference a null pointer (CVE-2015-7799). Add a range-check at the top of the function and make it return an ERR_PTR() on error instead of NULL. Change the callers accordingly. Compile-tested only. Reported-by: 郭永刚 References: http://article.gmane.org/gmane.comp.security.oss.general/17908 Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/ppp/ppp_generic.c | 6 ++---- drivers/net/slip/slhc.c | 12 ++++++++---- drivers/net/slip/slip.c | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index ed00446759b2..9a863c6a6a33 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -721,10 +721,8 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) val &= 0xffff; } vj = slhc_init(val2+1, val+1); - if (!vj) { - netdev_err(ppp->dev, - "PPP: no memory (VJ compressor)\n"); - err = -ENOMEM; + if (IS_ERR(vj)) { + err = PTR_ERR(vj); break; } ppp_lock(ppp); diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c index 079f7adfcde5..27ed25252aac 100644 --- a/drivers/net/slip/slhc.c +++ b/drivers/net/slip/slhc.c @@ -84,8 +84,9 @@ static long decode(unsigned char **cpp); static unsigned char * put16(unsigned char *cp, unsigned short x); static unsigned short pull16(unsigned char **cpp); -/* Initialize compression data structure +/* Allocate compression data structure * slots must be in range 0 to 255 (zero meaning no compression) + * Returns pointer to structure or ERR_PTR() on error. */ struct slcompress * slhc_init(int rslots, int tslots) @@ -94,11 +95,14 @@ slhc_init(int rslots, int tslots) register struct cstate *ts; struct slcompress *comp; + if (rslots < 0 || rslots > 255 || tslots < 0 || tslots > 255) + return ERR_PTR(-EINVAL); + comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL); if (! comp) goto out_fail; - if ( rslots > 0 && rslots < 256 ) { + if (rslots > 0) { size_t rsize = rslots * sizeof(struct cstate); comp->rstate = kzalloc(rsize, GFP_KERNEL); if (! comp->rstate) @@ -106,7 +110,7 @@ slhc_init(int rslots, int tslots) comp->rslot_limit = rslots - 1; } - if ( tslots > 0 && tslots < 256 ) { + if (tslots > 0) { size_t tsize = tslots * sizeof(struct cstate); comp->tstate = kzalloc(tsize, GFP_KERNEL); if (! comp->tstate) @@ -141,7 +145,7 @@ out_free2: out_free: kfree(comp); out_fail: - return NULL; + return ERR_PTR(-ENOMEM); } diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index 05387b1e2e95..a17d86a57734 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -164,7 +164,7 @@ static int sl_alloc_bufs(struct slip *sl, int mtu) if (cbuff == NULL) goto err_exit; slcomp = slhc_init(16, 16); - if (slcomp == NULL) + if (IS_ERR(slcomp)) goto err_exit; #endif spin_lock_bh(&sl->lock); -- cgit v1.2.3 From c451113291c193d3bfbd0682011d2979d649010c Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 2 Nov 2015 10:40:17 +0900 Subject: ravb: use pdev rather than ndev for error messages This corrects what appear to be typos, making the code consistent with itself, and allowing meaningful prefixes to be displayed with the errors in question. Before: (null): failed to initialize MDIO (null): Cannot allocate desc base address table (size 176 bytes) After: ravb e6800000.ethernet: failed to initialize MDIO ravb e6800000.ethernet: Cannot allocate desc base address table (size 176 bytes) Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 8cc5ec5ed19a..aa7b2083cb53 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1765,7 +1765,7 @@ static int ravb_probe(struct platform_device *pdev) priv->desc_bat = dma_alloc_coherent(ndev->dev.parent, priv->desc_bat_size, &priv->desc_bat_dma, GFP_KERNEL); if (!priv->desc_bat) { - dev_err(&ndev->dev, + dev_err(&pdev->dev, "Cannot allocate desc base address table (size %d bytes)\n", priv->desc_bat_size); error = -ENOMEM; @@ -1792,7 +1792,7 @@ static int ravb_probe(struct platform_device *pdev) /* MDIO bus init */ error = ravb_mdio_init(priv); if (error) { - dev_err(&ndev->dev, "failed to initialize MDIO\n"); + dev_err(&pdev->dev, "failed to initialize MDIO\n"); goto out_dma_free; } -- cgit v1.2.3 From b25c2e7d3c44aaadee55d70f70c31cbc9014c713 Mon Sep 17 00:00:00 2001 From: Mahesh Bandewar Date: Sat, 31 Oct 2015 12:45:00 -0700 Subject: bonding: Simplify __get_duplex function. Eliminate 'else' clause by simply initializing variable Signed-off-by: Mahesh Bandewar Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 3c45358844eb..3a17fd207ec6 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -327,14 +327,12 @@ static u16 __get_link_speed(struct port *port) static u8 __get_duplex(struct port *port) { struct slave *slave = port->slave; - u8 retval; + u8 retval = 0x0; /* handling a special case: when the configuration starts with * link down, it sets the duplex to 0. */ - if (slave->link != BOND_LINK_UP) { - retval = 0x0; - } else { + if (slave->link == BOND_LINK_UP) { switch (slave->duplex) { case DUPLEX_FULL: retval = 0x1; -- cgit v1.2.3 From 7bb11dc9f59ddcb33ee317da77b235235aaa582a Mon Sep 17 00:00:00 2001 From: Mahesh Bandewar Date: Sat, 31 Oct 2015 12:45:06 -0700 Subject: bonding: unify all places where actor-oper key needs to be updated. actor_admin, and actor_oper key is changed at multiple locations in the code. This patch brings all those updates into one location in an attempt to avoid possible inconsistent updates causing LACP state machine to go in weird state. The unified place is ad_update_actor_key() with simple state-machine logic - (a) If port is "duplex" then only it can participate in LACP (b) Speed change reinitializes the LACP state-machine. Signed-off-by: Mahesh Bandewar Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 87 +++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 35 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 3a17fd207ec6..b9816b7f319f 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -127,6 +127,7 @@ static void ad_marker_info_received(struct bond_marker *marker_info, struct port *port); static void ad_marker_response_received(struct bond_marker *marker, struct port *port); +static void ad_update_actor_keys(struct port *port, bool reset); /* ================= api to bonding and kernel code ================== */ @@ -1951,14 +1952,7 @@ void bond_3ad_bind_slave(struct slave *slave) * user key */ port->actor_admin_port_key = bond->params.ad_user_port_key << 6; - port->actor_admin_port_key |= __get_duplex(port); - port->actor_admin_port_key |= (__get_link_speed(port) << 1); - port->actor_oper_port_key = port->actor_admin_port_key; - /* if the port is not full duplex, then the port should be not - * lacp Enabled - */ - if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS)) - port->sm_vars &= ~AD_PORT_LACP_ENABLED; + ad_update_actor_keys(port, false); /* actor system is the bond's system */ port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr; port->actor_system_priority = @@ -2307,6 +2301,52 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, return ret; } +/** + * ad_update_actor_keys - Update the oper / admin keys for a port based on + * its current speed and duplex settings. + * + * @port: the port we'are looking at + * @reset: Boolean to just reset the speed and the duplex part of the key + * + * The logic to change the oper / admin keys is: + * (a) A full duplex port can participate in LACP with partner. + * (b) When the speed is changed, LACP need to be reinitiated. + */ +static void ad_update_actor_keys(struct port *port, bool reset) +{ + u8 duplex = 0; + u16 ospeed = 0, speed = 0; + u16 old_oper_key = port->actor_oper_port_key; + + port->actor_admin_port_key &= ~(AD_SPEED_KEY_MASKS|AD_DUPLEX_KEY_MASKS); + if (!reset) { + speed = __get_link_speed(port); + ospeed = (old_oper_key & AD_SPEED_KEY_MASKS) >> 1; + duplex = __get_duplex(port); + port->actor_admin_port_key |= (speed << 1) | duplex; + } + port->actor_oper_port_key = port->actor_admin_port_key; + + if (old_oper_key != port->actor_oper_port_key) { + /* Only 'duplex' port participates in LACP */ + if (duplex) + port->sm_vars |= AD_PORT_LACP_ENABLED; + else + port->sm_vars &= ~AD_PORT_LACP_ENABLED; + + if (!reset) { + if (!speed) { + netdev_err(port->slave->dev, + "speed changed to 0 for port %s", + port->slave->dev->name); + } else if (duplex && ospeed != speed) { + /* Speed change restarts LACP state-machine */ + port->sm_vars |= AD_PORT_BEGIN; + } + } + } +} + /** * bond_3ad_adapter_speed_changed - handle a slave's speed change indication * @slave: slave struct to work on @@ -2328,14 +2368,8 @@ void bond_3ad_adapter_speed_changed(struct slave *slave) spin_lock_bh(&slave->bond->mode_lock); - port->actor_admin_port_key &= ~AD_SPEED_KEY_MASKS; - port->actor_admin_port_key |= __get_link_speed(port) << 1; - port->actor_oper_port_key = port->actor_admin_port_key; + ad_update_actor_keys(port, false); netdev_dbg(slave->bond->dev, "Port %d changed speed\n", port->actor_port_number); - /* there is no need to reselect a new aggregator, just signal the - * state machines to reinitialize - */ - port->sm_vars |= AD_PORT_BEGIN; spin_unlock_bh(&slave->bond->mode_lock); } @@ -2361,17 +2395,9 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave) spin_lock_bh(&slave->bond->mode_lock); - port->actor_admin_port_key &= ~AD_DUPLEX_KEY_MASKS; - port->actor_admin_port_key |= __get_duplex(port); - port->actor_oper_port_key = port->actor_admin_port_key; + ad_update_actor_keys(port, false); netdev_dbg(slave->bond->dev, "Port %d slave %s changed duplex\n", port->actor_port_number, slave->dev->name); - if (port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS) - port->sm_vars |= AD_PORT_LACP_ENABLED; - /* there is no need to reselect a new aggregator, just signal the - * state machines to reinitialize - */ - port->sm_vars |= AD_PORT_BEGIN; spin_unlock_bh(&slave->bond->mode_lock); } @@ -2404,26 +2430,17 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) * on link up we are forcing recheck on the duplex and speed since * some of he adaptors(ce1000.lan) report. */ - port->actor_admin_port_key &= ~(AD_DUPLEX_KEY_MASKS|AD_SPEED_KEY_MASKS); if (link == BOND_LINK_UP) { port->is_enabled = true; - port->actor_admin_port_key |= - (__get_link_speed(port) << 1) | __get_duplex(port); - if (port->actor_admin_port_key & AD_DUPLEX_KEY_MASKS) - port->sm_vars |= AD_PORT_LACP_ENABLED; + ad_update_actor_keys(port, false); } else { /* link has failed */ port->is_enabled = false; - port->sm_vars &= ~AD_PORT_LACP_ENABLED; + ad_update_actor_keys(port, true); } - port->actor_oper_port_key = port->actor_admin_port_key; netdev_dbg(slave->bond->dev, "Port %d changed link status to %s\n", port->actor_port_number, link == BOND_LINK_UP ? "UP" : "DOWN"); - /* there is no need to reselect a new aggregator, just signal the - * state machines to reinitialize - */ - port->sm_vars |= AD_PORT_BEGIN; spin_unlock_bh(&slave->bond->mode_lock); -- cgit v1.2.3 From 52bc67168109ade61014a36feedf09f4bc53d8f1 Mon Sep 17 00:00:00 2001 From: Mahesh Bandewar Date: Sat, 31 Oct 2015 12:45:11 -0700 Subject: bonding: simplify / unify event handling code for 3ad mode. Old logic of updating state-machine is not required since ad_update_actor_keys() does it implicitly. The only loss is the notification differentiation between speed vs. duplex change. Now only one unified notification is printed. Signed-off-by: Mahesh Bandewar Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 38 ++++++-------------------------------- drivers/net/bonding/bond_main.c | 14 ++------------ 2 files changed, 8 insertions(+), 44 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index b9816b7f319f..940e2ebbdea8 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2348,39 +2348,14 @@ static void ad_update_actor_keys(struct port *port, bool reset) } /** - * bond_3ad_adapter_speed_changed - handle a slave's speed change indication - * @slave: slave struct to work on + * bond_3ad_adapter_speed_duplex_changed - handle a slave's speed / duplex + * change indication * - * Handle reselection of aggregator (if needed) for this port. - */ -void bond_3ad_adapter_speed_changed(struct slave *slave) -{ - struct port *port; - - port = &(SLAVE_AD_INFO(slave)->port); - - /* if slave is null, the whole port is not initialized */ - if (!port->slave) { - netdev_warn(slave->bond->dev, "speed changed for uninitialized port on %s\n", - slave->dev->name); - return; - } - - spin_lock_bh(&slave->bond->mode_lock); - - ad_update_actor_keys(port, false); - netdev_dbg(slave->bond->dev, "Port %d changed speed\n", port->actor_port_number); - - spin_unlock_bh(&slave->bond->mode_lock); -} - -/** - * bond_3ad_adapter_duplex_changed - handle a slave's duplex change indication * @slave: slave struct to work on * * Handle reselection of aggregator (if needed) for this port. */ -void bond_3ad_adapter_duplex_changed(struct slave *slave) +void bond_3ad_adapter_speed_duplex_changed(struct slave *slave) { struct port *port; @@ -2388,17 +2363,16 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave) /* if slave is null, the whole port is not initialized */ if (!port->slave) { - netdev_warn(slave->bond->dev, "duplex changed for uninitialized port on %s\n", + netdev_warn(slave->bond->dev, + "speed/duplex changed for uninitialized port %s\n", slave->dev->name); return; } spin_lock_bh(&slave->bond->mode_lock); - ad_update_actor_keys(port, false); - netdev_dbg(slave->bond->dev, "Port %d slave %s changed duplex\n", + netdev_dbg(slave->bond->dev, "Port %d slave %s changed speed/duplex\n", port->actor_port_number, slave->dev->name); - spin_unlock_bh(&slave->bond->mode_lock); } diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d0f23cd6e236..b4351caf8e01 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2943,8 +2943,6 @@ static int bond_slave_netdev_event(unsigned long event, struct slave *slave = bond_slave_get_rtnl(slave_dev), *primary; struct bonding *bond; struct net_device *bond_dev; - u32 old_speed; - u8 old_duplex; /* A netdev event can be generated while enslaving a device * before netdev_rx_handler_register is called in which case @@ -2965,17 +2963,9 @@ static int bond_slave_netdev_event(unsigned long event, break; case NETDEV_UP: case NETDEV_CHANGE: - old_speed = slave->speed; - old_duplex = slave->duplex; - bond_update_speed_duplex(slave); - - if (BOND_MODE(bond) == BOND_MODE_8023AD) { - if (old_speed != slave->speed) - bond_3ad_adapter_speed_changed(slave); - if (old_duplex != slave->duplex) - bond_3ad_adapter_duplex_changed(slave); - } + if (BOND_MODE(bond) == BOND_MODE_8023AD) + bond_3ad_adapter_speed_duplex_changed(slave); /* Fallthrough */ case NETDEV_DOWN: /* Refresh slave-array if applicable! -- cgit v1.2.3 From c238041f517d0a6458264582e8e2a1513766f8e7 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 3 Nov 2015 01:28:07 +0300 Subject: sh_eth: fix typo in RX descriptor bit name The correct name of the RX descriptor 0 bit 30 is RDLE (receive descriptor list end), not RDEL. Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 4 ++-- drivers/net/ethernet/renesas/sh_eth.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index a484d8beb855..e06bef5dd6a9 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1173,7 +1173,7 @@ static void sh_eth_ring_format(struct net_device *ndev) mdp->dirty_rx = (u32) (i - mdp->num_rx_ring); /* Mark the last entry as wrapping the ring. */ - rxdesc->status |= cpu_to_edmac(mdp, RD_RDEL); + rxdesc->status |= cpu_to_edmac(mdp, RD_RDLE); memset(mdp->tx_ring, 0, tx_ringsize); @@ -1547,7 +1547,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) wmb(); /* RACT bit must be set after all the above writes */ if (entry >= mdp->num_rx_ring - 1) rxdesc->status |= - cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDEL); + cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDLE); else rxdesc->status |= cpu_to_edmac(mdp, RD_RACT | RD_RFP); diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 06dbbe5201cb..50382b1c9ddc 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -285,7 +285,7 @@ enum DMAC_IM_BIT { /* Receive descriptor bit */ enum RD_STS_BIT { - RD_RACT = 0x80000000, RD_RDEL = 0x40000000, + RD_RACT = 0x80000000, RD_RDLE = 0x40000000, RD_RFP1 = 0x20000000, RD_RFP0 = 0x10000000, RD_RFE = 0x08000000, RD_RFS10 = 0x00000200, RD_RFS9 = 0x00000100, RD_RFS8 = 0x00000080, -- cgit v1.2.3 From b2663a4f30e85ec606b806f5135413e6d5c78d1e Mon Sep 17 00:00:00 2001 From: Martin Habets Date: Mon, 2 Nov 2015 12:51:31 +0000 Subject: sfc: push partner queue for skb->xmit_more When the IP stack passes SKBs the sfc driver puts them in 2 different TX queues (called partners), one for checksummed and one for not checksummed. If the SKB has xmit_more set the driver will delay pushing the work to the NIC. When later it does decide to push the buffers this patch ensures it also pushes the partner queue, if that also has any delayed work. Before this fix the work in the partner queue would be left for a long time and cause a netdev watchdog. Fixes: 70b33fb ("sfc: add support for skb->xmit_more") Reported-by: Jianlin Shi Signed-off-by: Martin Habets Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/ef10.c | 4 +++- drivers/net/ethernet/sfc/farch.c | 4 +++- drivers/net/ethernet/sfc/net_driver.h | 2 ++ drivers/net/ethernet/sfc/tx.c | 30 ++++++++++++++++++++++++++++-- 4 files changed, 36 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index ff649ebef637..286cc6b69d57 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1849,7 +1849,9 @@ static void efx_ef10_tx_write(struct efx_tx_queue *tx_queue) unsigned int write_ptr; efx_qword_t *txd; - BUG_ON(tx_queue->write_count == tx_queue->insert_count); + tx_queue->xmit_more_available = false; + if (unlikely(tx_queue->write_count == tx_queue->insert_count)) + return; do { write_ptr = tx_queue->write_count & tx_queue->ptr_mask; diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index f08266f0eca2..5a1c5a8f278a 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -321,7 +321,9 @@ void efx_farch_tx_write(struct efx_tx_queue *tx_queue) unsigned write_ptr; unsigned old_write_count = tx_queue->write_count; - BUG_ON(tx_queue->write_count == tx_queue->insert_count); + tx_queue->xmit_more_available = false; + if (unlikely(tx_queue->write_count == tx_queue->insert_count)) + return; do { write_ptr = tx_queue->write_count & tx_queue->ptr_mask; diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index c530e1c4cb4f..24038ef96d9f 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -219,6 +219,7 @@ struct efx_tx_buffer { * @tso_packets: Number of packets via the TSO xmit path * @pushes: Number of times the TX push feature has been used * @pio_packets: Number of times the TX PIO feature has been used + * @xmit_more_available: Are any packets waiting to be pushed to the NIC * @empty_read_count: If the completion path has seen the queue as empty * and the transmission path has not yet checked this, the value of * @read_count bitwise-added to %EFX_EMPTY_COUNT_VALID; otherwise 0. @@ -253,6 +254,7 @@ struct efx_tx_queue { unsigned int tso_packets; unsigned int pushes; unsigned int pio_packets; + bool xmit_more_available; /* Statistics to supplement MAC stats */ unsigned long tx_packets; diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 1833a0146571..67f6afaa022f 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -431,8 +431,20 @@ finish_packet: efx_tx_maybe_stop_queue(tx_queue); /* Pass off to hardware */ - if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) + if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) { + struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue); + + /* There could be packets left on the partner queue if those + * SKBs had skb->xmit_more set. If we do not push those they + * could be left for a long time and cause a netdev watchdog. + */ + if (txq2->xmit_more_available) + efx_nic_push_buffers(txq2); + efx_nic_push_buffers(tx_queue); + } else { + tx_queue->xmit_more_available = skb->xmit_more; + } tx_queue->tx_packets++; @@ -722,6 +734,7 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue) tx_queue->read_count = 0; tx_queue->old_read_count = 0; tx_queue->empty_read_count = 0 | EFX_EMPTY_COUNT_VALID; + tx_queue->xmit_more_available = false; /* Set up TX descriptor ring */ efx_nic_init_tx(tx_queue); @@ -747,6 +760,7 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue) ++tx_queue->read_count; } + tx_queue->xmit_more_available = false; netdev_tx_reset_queue(tx_queue->core_txq); } @@ -1302,8 +1316,20 @@ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, efx_tx_maybe_stop_queue(tx_queue); /* Pass off to hardware */ - if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) + if (!skb->xmit_more || netif_xmit_stopped(tx_queue->core_txq)) { + struct efx_tx_queue *txq2 = efx_tx_queue_partner(tx_queue); + + /* There could be packets left on the partner queue if those + * SKBs had skb->xmit_more set. If we do not push those they + * could be left for a long time and cause a netdev watchdog. + */ + if (txq2->xmit_more_available) + efx_nic_push_buffers(txq2); + efx_nic_push_buffers(tx_queue); + } else { + tx_queue->xmit_more_available = skb->xmit_more; + } tx_queue->tso_bursts++; return NETDEV_TX_OK; -- cgit v1.2.3 From 5f6c99e0ab805d8ec9eda105822912d49aa1d409 Mon Sep 17 00:00:00 2001 From: Shaohui Xie Date: Tue, 3 Nov 2015 12:27:33 +0800 Subject: net: phy: fix a bug in get_phy_c45_ids When probing devices-in-package for a c45 phy, device zero is the last device to probe, however, if driver reads 0 from device zero, c45_ids->devices_in_package is set to '0', the loop condition of probing will be matched again, see codes below: for (i = 1;i < num_ids && c45_ids->devices_in_package == 0;i++) driver will run in a dead loop. This patch restructures the bug and confusing loop, it provides a helper function get_phy_c45_devs_in_pkg which to read devices-in-package registers of a MMD, and rewrites the loop with using the helper function. Signed-off-by: Shaohui Xie Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 74 +++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 25 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index f761288abe66..0a76cc5d13da 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -205,6 +205,37 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, } EXPORT_SYMBOL(phy_device_create); +/* get_phy_c45_devs_in_pkg - reads a MMD's devices in package registers. + * @bus: the target MII bus + * @addr: PHY address on the MII bus + * @dev_addr: MMD address in the PHY. + * @devices_in_package: where to store the devices in package information. + * + * Description: reads devices in package registers of a MMD at @dev_addr + * from PHY at @addr on @bus. + * + * Returns: 0 on success, -EIO on failure. + */ +static int get_phy_c45_devs_in_pkg(struct mii_bus *bus, int addr, int dev_addr, + u32 *devices_in_package) +{ + int phy_reg, reg_addr; + + reg_addr = MII_ADDR_C45 | dev_addr << 16 | MDIO_DEVS2; + phy_reg = mdiobus_read(bus, addr, reg_addr); + if (phy_reg < 0) + return -EIO; + *devices_in_package = (phy_reg & 0xffff) << 16; + + reg_addr = MII_ADDR_C45 | dev_addr << 16 | MDIO_DEVS1; + phy_reg = mdiobus_read(bus, addr, reg_addr); + if (phy_reg < 0) + return -EIO; + *devices_in_package |= (phy_reg & 0xffff); + + return 0; +} + /** * get_phy_c45_ids - reads the specified addr for its 802.3-c45 IDs. * @bus: the target MII bus @@ -223,38 +254,31 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id, int phy_reg; int i, reg_addr; const int num_ids = ARRAY_SIZE(c45_ids->device_ids); + u32 *devs = &c45_ids->devices_in_package; - /* Find first non-zero Devices In package. Device - * zero is reserved, so don't probe it. + /* Find first non-zero Devices In package. Device zero is reserved + * for 802.3 c45 complied PHYs, so don't probe it at first. */ - for (i = 1; - i < num_ids && c45_ids->devices_in_package == 0; - i++) { -retry: reg_addr = MII_ADDR_C45 | i << 16 | MDIO_DEVS2; - phy_reg = mdiobus_read(bus, addr, reg_addr); + for (i = 1; i < num_ids && *devs == 0; i++) { + phy_reg = get_phy_c45_devs_in_pkg(bus, addr, i, devs); if (phy_reg < 0) return -EIO; - c45_ids->devices_in_package = (phy_reg & 0xffff) << 16; - reg_addr = MII_ADDR_C45 | i << 16 | MDIO_DEVS1; - phy_reg = mdiobus_read(bus, addr, reg_addr); - if (phy_reg < 0) - return -EIO; - c45_ids->devices_in_package |= (phy_reg & 0xffff); - - if ((c45_ids->devices_in_package & 0x1fffffff) == 0x1fffffff) { - if (i) { - /* If mostly Fs, there is no device there, - * then let's continue to probe more, as some - * 10G PHYs have zero Devices In package, - * e.g. Cortina CS4315/CS4340 PHY. - */ - i = 0; - goto retry; - } else { - /* no device there, let's get out of here */ + if ((*devs & 0x1fffffff) == 0x1fffffff) { + /* If mostly Fs, there is no device there, + * then let's continue to probe more, as some + * 10G PHYs have zero Devices In package, + * e.g. Cortina CS4315/CS4340 PHY. + */ + phy_reg = get_phy_c45_devs_in_pkg(bus, addr, 0, devs); + if (phy_reg < 0) + return -EIO; + /* no device there, let's get out of here */ + if ((*devs & 0x1fffffff) == 0x1fffffff) { *phy_id = 0xffffffff; return 0; + } else { + break; } } } -- cgit v1.2.3 From a1985740904342a884471348f6e038ee5d706c36 Mon Sep 17 00:00:00 2001 From: Achiad Shochat Date: Tue, 3 Nov 2015 08:07:18 +0200 Subject: net/mlx5e: Avoid NULL pointer access in case of configuration failure In case a configuration operation that involves closing and re-opening resources (e.g RX/TX queue size change) fails at the re-opening stage these resources will remain closed. So when executing (following) configuration operations (e.g ifconfig down) we cannot assume that these resources are available. Signed-off-by: Achiad Shochat Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index bb801a9bbd42..9df6f9ae9bb5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1404,6 +1404,12 @@ int mlx5e_close_locked(struct net_device *netdev) { struct mlx5e_priv *priv = netdev_priv(netdev); + /* May already be CLOSED in case a previous configuration operation + * (e.g RX/TX queue size change) that involves close&open failed. + */ + if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) + return 0; + clear_bit(MLX5E_STATE_OPENED, &priv->state); mlx5e_redirect_rqts(priv); -- cgit v1.2.3 From 01c196a2d3d1cfaab7d20879236e981104749510 Mon Sep 17 00:00:00 2001 From: Achiad Shochat Date: Tue, 3 Nov 2015 08:07:19 +0200 Subject: net/mlx5e: Wait for RX buffers initialization in a more proper manner Use jiffies rather than wait loop with msleep(). The wait loop didn't take into consideration time when the process was not executing. Signed-off-by: Achiad Shochat Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 9df6f9ae9bb5..0bab33c6cec0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -442,12 +442,12 @@ static void mlx5e_disable_rq(struct mlx5e_rq *rq) static int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq) { + unsigned long exp_time = jiffies + msecs_to_jiffies(20000); struct mlx5e_channel *c = rq->channel; struct mlx5e_priv *priv = c->priv; struct mlx5_wq_ll *wq = &rq->wq; - int i; - for (i = 0; i < 1000; i++) { + while (time_before(jiffies, exp_time)) { if (wq->cur_sz >= priv->params.min_rx_wqes) return 0; -- cgit v1.2.3 From 61d0e73e0a5ab5fc80f6cd9d54f5146e33288a8d Mon Sep 17 00:00:00 2001 From: Achiad Shochat Date: Tue, 3 Nov 2015 08:07:20 +0200 Subject: net/mlx5_core: Use the the real irqn in eq->irqn Instead of storing the msix array index in eq->irqn (vecidx), store the real irq number. Signed-off-by: Achiad Shochat Signed-off-by: Saeed Mahameed Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 1f01fe8fde42..713ead583347 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -382,10 +382,10 @@ int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 vecidx, name, pci_name(dev->pdev)); eq->eqn = out.eq_number; - eq->irqn = vecidx; + eq->irqn = priv->msix_arr[vecidx].vector; eq->dev = dev; eq->doorbell = uar->map + MLX5_EQ_DOORBEL_OFFSET; - err = request_irq(priv->msix_arr[vecidx].vector, mlx5_msix_handler, 0, + err = request_irq(eq->irqn, mlx5_msix_handler, 0, priv->irq_info[vecidx].name, eq); if (err) goto err_eq; @@ -421,12 +421,12 @@ int mlx5_destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq) int err; mlx5_debug_eq_remove(dev, eq); - free_irq(dev->priv.msix_arr[eq->irqn].vector, eq); + free_irq(eq->irqn, eq); err = mlx5_cmd_destroy_eq(dev, eq->eqn); if (err) mlx5_core_warn(dev, "failed to destroy a previously created eq: eqn %d\n", eq->eqn); - synchronize_irq(dev->priv.msix_arr[eq->irqn].vector); + synchronize_irq(eq->irqn); mlx5_buf_free(dev, &eq->buf); return err; -- cgit v1.2.3 From 3435ab59d3febe0c00af2a4d40a6df401effe3de Mon Sep 17 00:00:00 2001 From: Achiad Shochat Date: Tue, 3 Nov 2015 08:07:21 +0200 Subject: net/mlx5e: Don't allow more than max supported channels Consider MLX5E_MAX_NUM_CHANNELS @ethtool set/get_channels Signed-off-by: Achiad Shochat Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 6 ++++++ drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 5 ++--- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 3 +-- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 0983a208b299..f2ae62dd8c09 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -617,5 +617,11 @@ static inline void mlx5e_cq_arm(struct mlx5e_cq *cq) mlx5_cq_arm(mcq, MLX5_CQ_DB_REQ_NOT, mcq->uar->map, NULL, cq->wq.cc); } +static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev) +{ + return min_t(int, mdev->priv.eq_table.num_comp_vectors, + MLX5E_MAX_NUM_CHANNELS); +} + extern const struct ethtool_ops mlx5e_ethtool_ops; u16 mlx5e_get_max_inline_cap(struct mlx5_core_dev *mdev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index bce912688ca8..2e022e900939 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -345,9 +345,8 @@ static void mlx5e_get_channels(struct net_device *dev, struct ethtool_channels *ch) { struct mlx5e_priv *priv = netdev_priv(dev); - int ncv = priv->mdev->priv.eq_table.num_comp_vectors; - ch->max_combined = ncv; + ch->max_combined = mlx5e_get_max_num_channels(priv->mdev); ch->combined_count = priv->params.num_channels; } @@ -355,7 +354,7 @@ static int mlx5e_set_channels(struct net_device *dev, struct ethtool_channels *ch) { struct mlx5e_priv *priv = netdev_priv(dev); - int ncv = priv->mdev->priv.eq_table.num_comp_vectors; + int ncv = mlx5e_get_max_num_channels(priv->mdev); unsigned int count = ch->combined_count; bool was_opened; int err = 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 0bab33c6cec0..febf71185964 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2047,8 +2047,7 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev) { struct net_device *netdev; struct mlx5e_priv *priv; - int nch = min_t(int, mdev->priv.eq_table.num_comp_vectors, - MLX5E_MAX_NUM_CHANNELS); + int nch = mlx5e_get_max_num_channels(mdev); int err; if (mlx5e_check_required_hca_cap(mdev)) -- cgit v1.2.3 From fe9f4fe58d17e09b210061ed089dba6e81564652 Mon Sep 17 00:00:00 2001 From: Achiad Shochat Date: Tue, 3 Nov 2015 08:07:22 +0200 Subject: net/mlx5e: Return error in case mlx5e_set_features() fails In case mlx5e_set_features() fails, return the failure status rather than 0. Signed-off-by: Achiad Shochat Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index febf71185964..28eaed572ec4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1843,7 +1843,7 @@ static int mlx5e_set_features(struct net_device *netdev, mlx5e_disable_vlan_filter(priv); } - return 0; + return err; } static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu) -- cgit v1.2.3 From e4cf27bd9ce64d048df52a21cf162ce8b1a99362 Mon Sep 17 00:00:00 2001 From: Achiad Shochat Date: Tue, 3 Nov 2015 08:07:23 +0200 Subject: net/mlx5e: Re-eanble client vlan TX acceleration This reverts commit cd58c714acb9 "net/mlx5e: Disable client vlan TX acceleration". Bring back client vlan insertion offload, the original performance issue was found and fixed in the next patch. Signed-off-by: Achiad Shochat Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 1 + drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 28eaed572ec4..5fc4d2d78cdf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2004,6 +2004,7 @@ static void mlx5e_build_netdev(struct net_device *netdev) netdev->vlan_features |= NETIF_F_LRO; netdev->hw_features = netdev->vlan_features; + netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX; netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX; netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index b73672f32e2c..51052886c70a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -124,6 +124,21 @@ static inline u16 mlx5e_get_inline_hdr_size(struct mlx5e_sq *sq, return MLX5E_MIN_INLINE; } +static inline void mlx5e_insert_vlan(void *start, struct sk_buff *skb, u16 ihs) +{ + struct vlan_ethhdr *vhdr = (struct vlan_ethhdr *)start; + int cpy1_sz = 2 * ETH_ALEN; + int cpy2_sz = ihs - cpy1_sz - VLAN_HLEN; + + skb_copy_from_linear_data(skb, vhdr, cpy1_sz); + skb_pull_inline(skb, cpy1_sz); + vhdr->h_vlan_proto = skb->vlan_proto; + vhdr->h_vlan_TCI = cpu_to_be16(skb_vlan_tag_get(skb)); + skb_copy_from_linear_data(skb, &vhdr->h_vlan_encapsulated_proto, + cpy2_sz); + skb_pull_inline(skb, cpy2_sz); +} + static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb) { struct mlx5_wq_cyc *wq = &sq->wq; @@ -175,8 +190,12 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb) ETH_ZLEN); } - skb_copy_from_linear_data(skb, eseg->inline_hdr_start, ihs); - skb_pull_inline(skb, ihs); + if (skb_vlan_tag_present(skb)) { + mlx5e_insert_vlan(eseg->inline_hdr_start, skb, ihs); + } else { + skb_copy_from_linear_data(skb, eseg->inline_hdr_start, ihs); + skb_pull_inline(skb, ihs); + } eseg->inline_hdr_sz = cpu_to_be16(ihs); -- cgit v1.2.3 From 3ea4891db8d0d224f59b2fae0f386c8f5e68993f Mon Sep 17 00:00:00 2001 From: Achiad Shochat Date: Tue, 3 Nov 2015 08:07:24 +0200 Subject: net/mlx5e: Fix LSO vlan insertion Consider vlan insertion impact on headers copy size also for LSO packets. Signed-off-by: Achiad Shochat Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 51052886c70a..cd8f85a251d7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -116,7 +116,7 @@ static inline u16 mlx5e_get_inline_hdr_size(struct mlx5e_sq *sq, * headers and occur before the data gather. * Therefore these headers must be copied into the WQE */ -#define MLX5E_MIN_INLINE (ETH_HLEN + 2/*vlan tag*/) +#define MLX5E_MIN_INLINE ETH_HLEN if (bf && (skb_headlen(skb) <= sq->max_inline)) return skb_headlen(skb); @@ -128,7 +128,7 @@ static inline void mlx5e_insert_vlan(void *start, struct sk_buff *skb, u16 ihs) { struct vlan_ethhdr *vhdr = (struct vlan_ethhdr *)start; int cpy1_sz = 2 * ETH_ALEN; - int cpy2_sz = ihs - cpy1_sz - VLAN_HLEN; + int cpy2_sz = ihs - cpy1_sz; skb_copy_from_linear_data(skb, vhdr, cpy1_sz); skb_pull_inline(skb, cpy1_sz); @@ -192,6 +192,7 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb) if (skb_vlan_tag_present(skb)) { mlx5e_insert_vlan(eseg->inline_hdr_start, skb, ihs); + ihs += VLAN_HLEN; } else { skb_copy_from_linear_data(skb, eseg->inline_hdr_start, ihs); skb_pull_inline(skb, ihs); -- cgit v1.2.3 From 539e44d26855fdd198280ee41360a0b3adcf699b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Tue, 3 Nov 2015 09:34:04 +0100 Subject: dp83640: Include hash in timestamp/packet matching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only using the message type and sequence id for matching timestamps with packets is error prone, as multiple clients may very well be sending packets with the same messagetype and timestamp at the same time. Fix by extending the check to include the hash of bytes 20-29 (source id in PTPv2) that is provided with the timestamps. Signed-off-by: Stefan Sørensen Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 185b03c08e16..cae3b3b3ea3c 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -20,6 +20,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -787,9 +788,12 @@ static int decode_evnt(struct dp83640_private *dp83640, return parsed; } +#define DP83640_PACKET_HASH_OFFSET 20 +#define DP83640_PACKET_HASH_LEN 10 + static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts) { - u16 *seqid; + u16 *seqid, hash; unsigned int offset = 0; u8 *msgtype, *data = skb_mac_header(skb); @@ -819,11 +823,19 @@ static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts) msgtype = data + offset + OFF_PTP_CONTROL; else msgtype = data + offset; + if (rxts->msgtype != (*msgtype & 0xf)) + return 0; seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID); + if (rxts->seqid != ntohs(*seqid)) + return 0; + + hash = ether_crc(DP83640_PACKET_HASH_LEN, + data + offset + DP83640_PACKET_HASH_OFFSET) >> 20; + if (rxts->hash != hash) + return 0; - return rxts->msgtype == (*msgtype & 0xf) && - rxts->seqid == ntohs(*seqid); + return 1; } static void decode_rxts(struct dp83640_private *dp83640, -- cgit v1.2.3 From 4b063258ab9360207a4f6913d31d761bd85631ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Tue, 3 Nov 2015 09:34:05 +0100 Subject: dp83640: Delay scheduled work. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently rx_timestamp_work reschedules itself as a regular workqueue item, effectively causing it run constantly as long as there are packets left in the queue. Fix by using delayed workqueue items, limiting it to run only every two jiffies. Signed-off-by: Stefan Sørensen Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index cae3b3b3ea3c..69a2f56e4d68 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -69,6 +69,8 @@ /* phyter seems to miss the mark by 16 ns */ #define ADJTIME_FIX 16 +#define SKB_TIMESTAMP_TIMEOUT 2 /* jiffies */ + #if defined(__BIG_ENDIAN) #define ENDIAN_FLAG 0 #elif defined(__LITTLE_ENDIAN) @@ -111,7 +113,7 @@ struct dp83640_private { struct list_head list; struct dp83640_clock *clock; struct phy_device *phydev; - struct work_struct ts_work; + struct delayed_work ts_work; int hwts_tx_en; int hwts_rx_en; int layer; @@ -285,7 +287,7 @@ static void phy2rxts(struct phy_rxts *p, struct rxts *rxts) rxts->seqid = p->seqid; rxts->msgtype = (p->msgtype >> 12) & 0xf; rxts->hash = p->msgtype & 0x0fff; - rxts->tmo = jiffies + 2; + rxts->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT; } static u64 phy2txts(struct phy_txts *p) @@ -1115,7 +1117,7 @@ static int dp83640_probe(struct phy_device *phydev) goto no_memory; dp83640->phydev = phydev; - INIT_WORK(&dp83640->ts_work, rx_timestamp_work); + INIT_DELAYED_WORK(&dp83640->ts_work, rx_timestamp_work); INIT_LIST_HEAD(&dp83640->rxts); INIT_LIST_HEAD(&dp83640->rxpool); @@ -1162,7 +1164,7 @@ static void dp83640_remove(struct phy_device *phydev) return; enable_status_frames(phydev, false); - cancel_work_sync(&dp83640->ts_work); + cancel_delayed_work_sync(&dp83640->ts_work); skb_queue_purge(&dp83640->rx_queue); skb_queue_purge(&dp83640->tx_queue); @@ -1356,7 +1358,7 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr) static void rx_timestamp_work(struct work_struct *work) { struct dp83640_private *dp83640 = - container_of(work, struct dp83640_private, ts_work); + container_of(work, struct dp83640_private, ts_work.work); struct sk_buff *skb; /* Deliver expired packets. */ @@ -1373,7 +1375,7 @@ static void rx_timestamp_work(struct work_struct *work) } if (!skb_queue_empty(&dp83640->rx_queue)) - schedule_work(&dp83640->ts_work); + schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT); } static bool dp83640_rxtstamp(struct phy_device *phydev, @@ -1412,9 +1414,11 @@ static bool dp83640_rxtstamp(struct phy_device *phydev, if (!shhwtstamps) { skb_info->ptp_type = type; - skb_info->tmo = jiffies + 2; + skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT; skb_queue_tail(&dp83640->rx_queue, skb); - schedule_work(&dp83640->ts_work); + schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT); + } else { + netif_rx_ni(skb); } return true; -- cgit v1.2.3 From ccf6ee9a6980eff9ec0eeaa8f63c65bff34d9697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Tue, 3 Nov 2015 09:34:06 +0100 Subject: dp83640: Prune rx timestamp list before reading from it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The list of rx timestamps are currently only pruned of old entries when a new entry is inserted. If no new entries are added, old timestamps may survive beyond their lifetime, possible causing them to be attached to packets with the same sequence number after a rollover. Signed-off-by: Stefan Sørensen Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 69a2f56e4d68..39ac633e3ef5 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1398,6 +1398,7 @@ static bool dp83640_rxtstamp(struct phy_device *phydev, return false; spin_lock_irqsave(&dp83640->rx_lock, flags); + prune_rx_ts(dp83640); list_for_each_safe(this, next, &dp83640->rxts) { rxts = list_entry(this, struct rxts, list); if (match(skb, type, rxts)) { -- cgit v1.2.3 From a1f8723f38921a0216a63d3ec9f01ec1e2813363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Tue, 3 Nov 2015 09:34:08 +0100 Subject: dp83640: Only wait for timestamps for packets with timestamping enabled. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the packet timestamping function, check that the ptp version and protocol of the packet matches what we have configured the hardware to actually generate timestamps for, before looking/waiting for a timestamp. Signed-off-by: Stefan Sørensen Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 39ac633e3ef5..47b711739ba9 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -37,8 +37,6 @@ #define DP83640_PHY_ID 0x20005ce1 #define PAGESEL 0x13 -#define LAYER4 0x02 -#define LAYER2 0x01 #define MAX_RXTS 64 #define N_EXT_TS 6 #define N_PER_OUT 7 @@ -1296,29 +1294,29 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr) case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: dp83640->hwts_rx_en = 1; - dp83640->layer = LAYER4; - dp83640->version = 1; + dp83640->layer = PTP_CLASS_L4; + dp83640->version = PTP_CLASS_V1; break; case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: dp83640->hwts_rx_en = 1; - dp83640->layer = LAYER4; - dp83640->version = 2; + dp83640->layer = PTP_CLASS_L4; + dp83640->version = PTP_CLASS_V2; break; case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: dp83640->hwts_rx_en = 1; - dp83640->layer = LAYER2; - dp83640->version = 2; + dp83640->layer = PTP_CLASS_L2; + dp83640->version = PTP_CLASS_V2; break; case HWTSTAMP_FILTER_PTP_V2_EVENT: case HWTSTAMP_FILTER_PTP_V2_SYNC: case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: dp83640->hwts_rx_en = 1; - dp83640->layer = LAYER4|LAYER2; - dp83640->version = 2; + dp83640->layer = PTP_CLASS_L4 | PTP_CLASS_L2; + dp83640->version = PTP_CLASS_V2; break; default: return -ERANGE; @@ -1327,11 +1325,11 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr) txcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT; rxcfg0 = (dp83640->version & TX_PTP_VER_MASK) << TX_PTP_VER_SHIFT; - if (dp83640->layer & LAYER2) { + if (dp83640->layer & PTP_CLASS_L2) { txcfg0 |= TX_L2_EN; rxcfg0 |= RX_L2_EN; } - if (dp83640->layer & LAYER4) { + if (dp83640->layer & PTP_CLASS_L4) { txcfg0 |= TX_IPV6_EN | TX_IPV4_EN; rxcfg0 |= RX_IPV6_EN | RX_IPV4_EN; } @@ -1397,6 +1395,9 @@ static bool dp83640_rxtstamp(struct phy_device *phydev, if (!dp83640->hwts_rx_en) return false; + if ((type & dp83640->version) == 0 || (type & dp83640->layer) == 0) + return false; + spin_lock_irqsave(&dp83640->rx_lock, flags); prune_rx_ts(dp83640); list_for_each_safe(this, next, &dp83640->rxts) { -- cgit v1.2.3 From 754107e34165373b3696620cef344227b10eaa99 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 3 Nov 2015 14:51:29 +0100 Subject: arcnet/com20020: add LEDS_CLASS dependency The newly added led trigger support in the com20020-pci driver causes build errors when CONFIG_LEDS_CLASS is disabled: drivers/built-in.o: In function `com20020pci_probe': (.text+0x185dc4): undefined reference to `devm_led_classdev_register' (.text+0x185dd8): undefined reference to `devm_led_classdev_register' This adds a Kconfig dependency to prevent the invalid configurations. Other drivers appear to be split 50:50 between 'select' and 'depends on' for this symbol, I picked 'depends on' as I could not find a common policy and it generally causes fewer problems. Signed-off-by: Arnd Bergmann Fixes: 8890624a4e8c ("arcnet: com20020-pci: add led trigger support") Signed-off-by: David S. Miller --- drivers/net/arcnet/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig index 2a9c3c3abe9b..39bd16f3f86d 100644 --- a/drivers/net/arcnet/Kconfig +++ b/drivers/net/arcnet/Kconfig @@ -103,6 +103,7 @@ config ARCNET_RIM_I config ARCNET_COM20020 tristate "ARCnet COM20020 chipset driver" + depends on LEDS_CLASS help This is the driver for the new COM20020 chipset. It supports such things as promiscuous mode, so packet sniffing is possible, and -- cgit v1.2.3 From 4c7ea3c0791e971f05f78453a587a1640fe09a61 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Tue, 3 Nov 2015 10:52:36 -0500 Subject: net: dsa: mv88e6xxx: disable SA learning for DSA and CPU ports Frames with DSA headers passing to/from the CPU were taking place in the MAC learning on these ports, resulting in incorrect ATU entries. Disable learning on these ports. Signed-off-by: Andrew Lunn Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 8 ++++++-- drivers/net/dsa/mv88e6xxx.h | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 85228f44c2b5..3116990ccab9 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -2029,8 +2029,12 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) * a port bitmap that has only the bit for this port set and * the other bits clear. */ - ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_ASSOC_VECTOR, - 1 << port); + reg = 1 << port; + /* Disable learning for DSA and CPU ports */ + if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) + reg = PORT_ASSOC_VECTOR_LOCKED_PORT; + + ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), PORT_ASSOC_VECTOR, reg); if (ret) goto abort; diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index ad9958f09aa7..fb9a8739712f 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -159,6 +159,11 @@ #define PORT_RATE_CONTROL 0x09 #define PORT_RATE_CONTROL_2 0x0a #define PORT_ASSOC_VECTOR 0x0b +#define PORT_ASSOC_VECTOR_HOLD_AT_1 BIT(15) +#define PORT_ASSOC_VECTOR_INT_AGE_OUT BIT(14) +#define PORT_ASSOC_VECTOR_LOCKED_PORT BIT(13) +#define PORT_ASSOC_VECTOR_IGNORE_WRONG BIT(12) +#define PORT_ASSOC_VECTOR_REFRESH_LOCKED BIT(11) #define PORT_ATU_CONTROL 0x0c #define PORT_PRI_OVERRIDE 0x0d #define PORT_ETH_TYPE 0x0f -- cgit v1.2.3 From 3d131f070948e4ad93189cb379b3a45d53dce71b Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Tue, 3 Nov 2015 10:52:52 -0500 Subject: net: dsa: mv88e6xxx: include DSA ports in VLANs DSA ports must be members of a VLAN in order to ensure frame bridging between chained switch chips. Thus tag them in addition to the CPU port when adding a VLAN, and skip them when deleting a VLAN and reporting VLAN members. Also use the UNMODIFIED egress policy, so that frames egress on these ports as they ingress, tagged or untagged. Fixes: 0d3b33e60206 ("net: dsa: mv88e6xxx: add VLAN Load support") Reported-by: Andrew Lunn Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 3116990ccab9..04cff58d771b 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1418,11 +1418,11 @@ static int _mv88e6xxx_vlan_init(struct dsa_switch *ds, u16 vid, }; int i; - /* exclude all ports except the CPU */ + /* exclude all ports except the CPU and DSA ports */ for (i = 0; i < ps->num_ports; ++i) - vlan.data[i] = dsa_is_cpu_port(ds, i) ? - GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED : - GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER; + vlan.data[i] = dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i) + ? GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED + : GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER; if (mv88e6xxx_6097_family(ds) || mv88e6xxx_6165_family(ds) || mv88e6xxx_6351_family(ds) || mv88e6xxx_6352_family(ds)) { @@ -1545,7 +1545,7 @@ static int _mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, u16 vid) /* keep the VLAN unless all ports are excluded */ vlan.valid = false; for (i = 0; i < ps->num_ports; ++i) { - if (dsa_is_cpu_port(ds, i)) + if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)) continue; if (vlan.data[i] != GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) { @@ -1624,7 +1624,7 @@ unlock: clear_bit(port, ports); clear_bit(port, untagged); - if (dsa_is_cpu_port(ds, port)) + if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) continue; if (next.data[port] == GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED || -- cgit v1.2.3 From f32bfb9a8ca083f8d148ea90ae5ba66f4831836e Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 3 Nov 2015 22:36:04 +0300 Subject: sh_eth: use DMA barriers Commit 7d7355f58ba4 ("sh_eth: Ensure proper ordering of descriptor active bit write/read") did the right thing but used too "heavy" barriers while there were already "lighter" DMA barriers exactly for this case... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index dc5d34e1d01e..6150a235b72c 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1416,7 +1416,7 @@ static int sh_eth_txfree(struct net_device *ndev) if (txdesc->status & cpu_to_edmac(mdp, TD_TACT)) break; /* TACT bit must be checked before all the following reads */ - rmb(); + dma_rmb(); netif_info(mdp, tx_done, ndev, "tx entry %d status 0x%08x\n", entry, edmac_to_cpu(mdp, txdesc->status)); @@ -1458,7 +1458,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) rxdesc = &mdp->rx_ring[entry]; while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) { /* RACT bit must be checked before all the following reads */ - rmb(); + dma_rmb(); desc_status = edmac_to_cpu(mdp, rxdesc->status); pkt_len = rxdesc->frame_length; @@ -1544,7 +1544,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota) skb_checksum_none_assert(skb); rxdesc->addr = dma_addr; } - wmb(); /* RACT bit must be set after all the above writes */ + dma_wmb(); /* RACT bit must be set after all the above writes */ if (entry >= mdp->num_rx_ring - 1) rxdesc->status |= cpu_to_edmac(mdp, RD_RACT | RD_RFP | RD_RDLE); @@ -2403,7 +2403,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) } txdesc->buffer_length = skb->len; - wmb(); /* TACT bit must be set after all the above writes */ + dma_wmb(); /* TACT bit must be set after all the above writes */ if (entry >= mdp->num_tx_ring - 1) txdesc->status |= cpu_to_edmac(mdp, TD_TACT | TD_TDLE); else -- cgit v1.2.3 From 1f71e8c96fc654724723ce987e0a8b2aeb81746d Mon Sep 17 00:00:00 2001 From: Markus Brunner Date: Tue, 3 Nov 2015 22:09:51 +0100 Subject: drivers: net: cpsw: Add support for fixed-link PHY Add support for a fixed-link devicetree sub-node in case the the cpsw MAC is directly connected to a non-mdio PHY/device. Signed-off-by: Markus Brunner Acked-by: Mugunthan V N Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpsw.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 040fbc1e5508..48b92c9de12a 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -2037,6 +2037,19 @@ static int cpsw_probe_dt(struct cpsw_priv *priv, continue; priv->phy_node = of_parse_phandle(slave_node, "phy-handle", 0); + if (of_phy_is_fixed_link(slave_node)) { + struct phy_device *pd; + + ret = of_phy_register_fixed_link(slave_node); + if (ret) + return ret; + pd = of_phy_find_device(slave_node); + if (!pd) + return -ENODEV; + snprintf(slave_data->phy_id, sizeof(slave_data->phy_id), + PHY_ID_FMT, pd->bus->id, pd->phy_id); + goto no_phy_slave; + } parp = of_get_property(slave_node, "phy_id", &lenp); if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) { dev_err(&pdev->dev, "Missing slave[%d] phy_id property\n", i); -- cgit v1.2.3 From 91d80683fc1828141e87babbd01f40e408864914 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 4 Nov 2015 00:17:08 +0300 Subject: sh_eth: kill 'ret' variable in sh_eth_ring_init() The 'ret' local variable in sh_eth_ring_init() serves no useful purpose as the only values it gets assigned are 0 and -ENOMEM both of which could be returned directly... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 6150a235b72c..1477f9c7051b 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1199,7 +1199,7 @@ static void sh_eth_ring_format(struct net_device *ndev) static int sh_eth_ring_init(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); - int rx_ringsize, tx_ringsize, ret = 0; + int rx_ringsize, tx_ringsize; /* +26 gets the maximum ethernet encapsulation, +7 & ~7 because the * card needs room to do 8 byte alignment, +2 so we can reserve @@ -1214,26 +1214,20 @@ static int sh_eth_ring_init(struct net_device *ndev) /* Allocate RX and TX skb rings */ mdp->rx_skbuff = kcalloc(mdp->num_rx_ring, sizeof(*mdp->rx_skbuff), GFP_KERNEL); - if (!mdp->rx_skbuff) { - ret = -ENOMEM; - return ret; - } + if (!mdp->rx_skbuff) + return -ENOMEM; mdp->tx_skbuff = kcalloc(mdp->num_tx_ring, sizeof(*mdp->tx_skbuff), GFP_KERNEL); - if (!mdp->tx_skbuff) { - ret = -ENOMEM; + if (!mdp->tx_skbuff) goto skb_ring_free; - } /* Allocate all Rx descriptors. */ rx_ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma, GFP_KERNEL); - if (!mdp->rx_ring) { - ret = -ENOMEM; + if (!mdp->rx_ring) goto skb_ring_free; - } mdp->dirty_rx = 0; @@ -1241,11 +1235,9 @@ static int sh_eth_ring_init(struct net_device *ndev) tx_ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring; mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma, GFP_KERNEL); - if (!mdp->tx_ring) { - ret = -ENOMEM; + if (!mdp->tx_ring) goto desc_ring_free; - } - return ret; + return 0; desc_ring_free: /* free DMA buffer */ @@ -1257,7 +1249,7 @@ skb_ring_free: mdp->tx_ring = NULL; mdp->rx_ring = NULL; - return ret; + return -ENOMEM; } static void sh_eth_free_dma_buffer(struct sh_eth_private *mdp) -- cgit v1.2.3 From 8e03a5e75c517de19c26a46147b0dc28096e55ef Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 4 Nov 2015 00:55:13 +0300 Subject: sh_eth: merge sh_eth_free_dma_buffer() into sh_eth_ring_free() While the ring allocation is done by a single function, sh_eth_ring_init(), the ring deallocation was split into two functions (almost always called one after the other) for no good reason. Merge sh_eth_free_dma_buffer() into sh_eth_ring_free() which allows us to save space not only on the direct calls of the former function but also on the sh_eth_ring_init()'s simplified error path... Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/sh_eth.c | 60 +++++++++++++---------------------- 1 file changed, 22 insertions(+), 38 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 1477f9c7051b..e7bab7909ed9 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1098,7 +1098,7 @@ static struct mdiobb_ops bb_ops = { static void sh_eth_ring_free(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); - int i; + int ringsize, i; /* Free Rx skb ringbuffer */ if (mdp->rx_skbuff) { @@ -1115,6 +1115,20 @@ static void sh_eth_ring_free(struct net_device *ndev) } kfree(mdp->tx_skbuff); mdp->tx_skbuff = NULL; + + if (mdp->rx_ring) { + ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; + dma_free_coherent(NULL, ringsize, mdp->rx_ring, + mdp->rx_desc_dma); + mdp->rx_ring = NULL; + } + + if (mdp->tx_ring) { + ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring; + dma_free_coherent(NULL, ringsize, mdp->tx_ring, + mdp->tx_desc_dma); + mdp->tx_ring = NULL; + } } /* format skb and descriptor buffer */ @@ -1220,14 +1234,14 @@ static int sh_eth_ring_init(struct net_device *ndev) mdp->tx_skbuff = kcalloc(mdp->num_tx_ring, sizeof(*mdp->tx_skbuff), GFP_KERNEL); if (!mdp->tx_skbuff) - goto skb_ring_free; + goto ring_free; /* Allocate all Rx descriptors. */ rx_ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; mdp->rx_ring = dma_alloc_coherent(NULL, rx_ringsize, &mdp->rx_desc_dma, GFP_KERNEL); if (!mdp->rx_ring) - goto skb_ring_free; + goto ring_free; mdp->dirty_rx = 0; @@ -1236,41 +1250,16 @@ static int sh_eth_ring_init(struct net_device *ndev) mdp->tx_ring = dma_alloc_coherent(NULL, tx_ringsize, &mdp->tx_desc_dma, GFP_KERNEL); if (!mdp->tx_ring) - goto desc_ring_free; + goto ring_free; return 0; -desc_ring_free: - /* free DMA buffer */ - dma_free_coherent(NULL, rx_ringsize, mdp->rx_ring, mdp->rx_desc_dma); - -skb_ring_free: - /* Free Rx and Tx skb ring buffer */ +ring_free: + /* Free Rx and Tx skb ring buffer and DMA buffer */ sh_eth_ring_free(ndev); - mdp->tx_ring = NULL; - mdp->rx_ring = NULL; return -ENOMEM; } -static void sh_eth_free_dma_buffer(struct sh_eth_private *mdp) -{ - int ringsize; - - if (mdp->rx_ring) { - ringsize = sizeof(struct sh_eth_rxdesc) * mdp->num_rx_ring; - dma_free_coherent(NULL, ringsize, mdp->rx_ring, - mdp->rx_desc_dma); - mdp->rx_ring = NULL; - } - - if (mdp->tx_ring) { - ringsize = sizeof(struct sh_eth_txdesc) * mdp->num_tx_ring; - dma_free_coherent(NULL, ringsize, mdp->tx_ring, - mdp->tx_desc_dma); - mdp->tx_ring = NULL; - } -} - static int sh_eth_dev_init(struct net_device *ndev, bool start) { int ret = 0; @@ -2231,10 +2220,8 @@ static int sh_eth_set_ringparam(struct net_device *ndev, sh_eth_dev_exit(ndev); - /* Free all the skbuffs in the Rx queue. */ + /* Free all the skbuffs in the Rx queue and the DMA buffers. */ sh_eth_ring_free(ndev); - /* Free DMA buffer */ - sh_eth_free_dma_buffer(mdp); } /* Set new parameters */ @@ -2479,12 +2466,9 @@ static int sh_eth_close(struct net_device *ndev) free_irq(ndev->irq, ndev); - /* Free all the skbuffs in the Rx queue. */ + /* Free all the skbuffs in the Rx queue and the DMA buffer. */ sh_eth_ring_free(ndev); - /* free DMA buffer */ - sh_eth_free_dma_buffer(mdp); - pm_runtime_put_sync(&mdp->pdev->dev); mdp->is_opened = 0; -- cgit v1.2.3 From 8c169c28f40bd78b772c4d95306735c00f8db80d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 4 Nov 2015 16:27:16 +0300 Subject: qlogic/qed: remove bogus NULL check We check if "p_hwfn" is NULL and then dereference it in the error handling code. I read the code and it isn't NULL so let's remove the check. Signed-off-by: Dan Carpenter Acked-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_int.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c index 2e399b6137a2..de50e84902af 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.c +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c @@ -251,11 +251,6 @@ void qed_int_sp_dpc(unsigned long hwfn_cookie) int arr_size; u16 rc = 0; - if (!p_hwfn) { - DP_ERR(p_hwfn->cdev, "DPC called - no hwfn!\n"); - return; - } - if (!p_hwfn->p_sp_sb) { DP_ERR(p_hwfn->cdev, "DPC called - no p_sp_sb\n"); return; -- cgit v1.2.3 From 87aec47d173ca730d014b6b0246ca6be18b0ce94 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 4 Nov 2015 16:29:11 +0300 Subject: qlogic: qed: fix a test for MODE_MF_SI MODE_MF_SI is 9. We should be testing bit 9 instead of AND 0x9. Fixes: fe56b9e6a8d9 ('qed: Add module with basic common support') Signed-off-by: Dan Carpenter Acked-by: Yuval Mintz Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qed/qed_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index b9b7b7e6fa53..774b2231b79a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -562,7 +562,7 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn, } /* Enable classification by MAC if needed */ - if (hw_mode & MODE_MF_SI) { + if (hw_mode & (1 << MODE_MF_SI)) { DP_VERBOSE(p_hwfn, NETIF_MSG_HW, "Configuring TAGMAC_CLS_TYPE\n"); STORE_RT_REG(p_hwfn, -- cgit v1.2.3 From df761ea1f39fe1c020c31327656bce7a5a406201 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 4 Nov 2015 16:00:32 +0100 Subject: bnxt_en: add VXLAN dependency VXLAN may be a loadable module, and this driver cannot be built-in in that case, or we get a link error: drivers/built-in.o: In function `__bnxt_open_nic': drivers/net/ethernet/broadcom/bnxt/bnxt.c:4581: undefined reference to `vxlan_get_rx_port' This adds a Kconfig dependency that ensures that either VXLAN is disabled (which the driver handles correctly), or we depend on VXLAN itself and disallow built-in compilation when VXLAN is a module. Signed-off-by: Arnd Bergmann Fixes: c0c050c58d84 ("bnxt_en: New Broadcom ethernet driver.") Acked-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig index 67a7d520d9f5..8550df189ceb 100644 --- a/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig @@ -173,6 +173,7 @@ config SYSTEMPORT config BNXT tristate "Broadcom NetXtreme-C/E support" depends on PCI + depends on VXLAN || VXLAN=n select FW_LOADER select LIBCRC32C ---help--- -- cgit v1.2.3 From b3d8cf019fb9dd28389b08da7bf54ffabf453ed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Thu, 5 Nov 2015 12:55:01 +0100 Subject: USB: qmi_wwan: Add quirk for Quectel EC20 Mini PCIe module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This device has same vendor and product IDs as G2K devices, but it has different number of interfaces(4 vs 5) and also different interface layout where EC20 has QMI on interface 4 instead of 0. lsusb output: Bus 002 Device 003: ID 05c6:9215 Qualcomm, Inc. Acer Gobi 2000 Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x05c6 Qualcomm, Inc. idProduct 0x9215 Acer Gobi 2000 Wireless Modem bcdDevice 2.32 iManufacturer 1 Quectel iProduct 2 Quectel LTE Module iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 209 bNumInterfaces 5 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xa0 (Bus Powered) Remote Wakeup MaxPower 500mA Signed-off-by: Petr Štetiar Acked-by: Bjørn Mork Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index c54719984c4b..34799eaace41 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -771,6 +771,7 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x05c6, 0x9245)}, /* Samsung Gobi 2000 Modem device (VL176) */ {QMI_GOBI_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */ {QMI_GOBI_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */ + {QMI_FIXED_INTF(0x05c6, 0x9215, 4)}, /* Quectel EC20 Mini PCIe */ {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */ {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */ {QMI_GOBI_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */ @@ -802,10 +803,24 @@ static const struct usb_device_id products[] = { }; MODULE_DEVICE_TABLE(usb, products); +static bool quectel_ec20_detected(struct usb_interface *intf) +{ + struct usb_device *dev = interface_to_usbdev(intf); + + if (dev->actconfig && + le16_to_cpu(dev->descriptor.idVendor) == 0x05c6 && + le16_to_cpu(dev->descriptor.idProduct) == 0x9215 && + dev->actconfig->desc.bNumInterfaces == 5) + return true; + + return false; +} + static int qmi_wwan_probe(struct usb_interface *intf, const struct usb_device_id *prod) { struct usb_device_id *id = (struct usb_device_id *)prod; + struct usb_interface_descriptor *desc = &intf->cur_altsetting->desc; /* Workaround to enable dynamic IDs. This disables usbnet * blacklisting functionality. Which, if required, can be @@ -817,6 +832,12 @@ static int qmi_wwan_probe(struct usb_interface *intf, id->driver_info = (unsigned long)&qmi_wwan_info; } + /* Quectel EC20 quirk where we've QMI on interface 4 instead of 0 */ + if (quectel_ec20_detected(intf) && desc->bInterfaceNumber == 0) { + dev_dbg(&intf->dev, "Quectel EC20 quirk, skipping interface 0\n"); + return -ENODEV; + } + return usbnet_probe(intf, id); } -- cgit v1.2.3 From e79a8bcb780314a555897a933d16553b80dbca1f Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 4 Nov 2015 17:23:40 -0500 Subject: net: dsa: mv88e6xxx: isolate unbridged ports The DSA documentation specifies that each port must be capable of forwarding frames to the CPU port. The last changes on bridging support for the mv88e6xxx driver broke this requirement for non-bridged ports. So as for the bridged ports, reserve a few VLANs (4000+) in the switch to isolate ports that have not been bridged yet. By default, a port will be isolated with the CPU and DSA ports. When the port joins a bridge, it will leave its reserved port. When it is removed from a bridge, it will join its reserved VLAN again. Fixes: 5fe7f68016ff ("net: dsa: mv88e6xxx: fix hardware bridging") Reported-by: Andrew Lunn Signed-off-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6171.c | 2 ++ drivers/net/dsa/mv88e6352.c | 2 ++ drivers/net/dsa/mv88e6xxx.c | 42 ++++++++++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx.h | 2 ++ 4 files changed, 48 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c index 54aa00012dd0..6e18213b9c04 100644 --- a/drivers/net/dsa/mv88e6171.c +++ b/drivers/net/dsa/mv88e6171.c @@ -103,6 +103,8 @@ struct dsa_switch_driver mv88e6171_switch_driver = { #endif .get_regs_len = mv88e6xxx_get_regs_len, .get_regs = mv88e6xxx_get_regs, + .port_join_bridge = mv88e6xxx_port_bridge_join, + .port_leave_bridge = mv88e6xxx_port_bridge_leave, .port_stp_update = mv88e6xxx_port_stp_update, .port_pvid_get = mv88e6xxx_port_pvid_get, .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c index ff846d0cfceb..cc6c54553418 100644 --- a/drivers/net/dsa/mv88e6352.c +++ b/drivers/net/dsa/mv88e6352.c @@ -323,6 +323,8 @@ struct dsa_switch_driver mv88e6352_switch_driver = { .set_eeprom = mv88e6352_set_eeprom, .get_regs_len = mv88e6xxx_get_regs_len, .get_regs = mv88e6xxx_get_regs, + .port_join_bridge = mv88e6xxx_port_bridge_join, + .port_leave_bridge = mv88e6xxx_port_bridge_leave, .port_stp_update = mv88e6xxx_port_stp_update, .port_pvid_get = mv88e6xxx_port_pvid_get, .port_vlan_prepare = mv88e6xxx_port_vlan_prepare, diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index 04cff58d771b..b06dba05594a 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -1462,6 +1462,10 @@ int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan, struct switchdev_trans *trans) { + /* We reserve a few VLANs to isolate unbridged ports */ + if (vlan->vid_end >= 4000) + return -EOPNOTSUPP; + /* We don't need any dynamic resource from the kernel (yet), * so skip the prepare phase. */ @@ -1870,6 +1874,36 @@ unlock: return err; } +int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, u32 members) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + const u16 pvid = 4000 + ds->index * DSA_MAX_PORTS + port; + int err; + + /* The port joined a bridge, so leave its reserved VLAN */ + mutex_lock(&ps->smi_mutex); + err = _mv88e6xxx_port_vlan_del(ds, port, pvid); + if (!err) + err = _mv88e6xxx_port_pvid_set(ds, port, 0); + mutex_unlock(&ps->smi_mutex); + return err; +} + +int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, u32 members) +{ + struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); + const u16 pvid = 4000 + ds->index * DSA_MAX_PORTS + port; + int err; + + /* The port left the bridge, so join its reserved VLAN */ + mutex_lock(&ps->smi_mutex); + err = _mv88e6xxx_port_vlan_add(ds, port, pvid, true); + if (!err) + err = _mv88e6xxx_port_pvid_set(ds, port, pvid); + mutex_unlock(&ps->smi_mutex); + return err; +} + static void mv88e6xxx_bridge_work(struct work_struct *work) { struct mv88e6xxx_priv_state *ps; @@ -2140,6 +2174,14 @@ int mv88e6xxx_setup_ports(struct dsa_switch *ds) ret = mv88e6xxx_setup_port(ds, i); if (ret < 0) return ret; + + if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i)) + continue; + + /* setup the unbridged state */ + ret = mv88e6xxx_port_bridge_leave(ds, i, 0); + if (ret < 0) + return ret; } return 0; } diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index fb9a8739712f..21c8daa03f78 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -468,6 +468,8 @@ int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum, int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e); int mv88e6xxx_set_eee(struct dsa_switch *ds, int port, struct phy_device *phydev, struct ethtool_eee *e); +int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port, u32 members); +int mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port, u32 members); int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state); int mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan, -- cgit v1.2.3 From 9b15acbfe937f9c48a81d6aa306f9fa8b53abc13 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 5 Nov 2015 11:41:28 +0300 Subject: qlogic: qed: fix error codes in qed_resc_alloc() We accidentally return success instead of -ENOMEM here. Fixes: fe56b9e6a8d9 ('qed: Add module with basic common support') Signed-off-by: Dan Carpenter Acked-by: Yuval Mintz --- drivers/net/ethernet/qlogic/qed/qed_dev.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 774b2231b79a..803b190ccada 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -223,6 +223,7 @@ int qed_resc_alloc(struct qed_dev *cdev) if (!p_hwfn->p_tx_cids) { DP_NOTICE(p_hwfn, "Failed to allocate memory for Tx Cids\n"); + rc = -ENOMEM; goto alloc_err; } @@ -230,6 +231,7 @@ int qed_resc_alloc(struct qed_dev *cdev) if (!p_hwfn->p_rx_cids) { DP_NOTICE(p_hwfn, "Failed to allocate memory for Rx Cids\n"); + rc = -ENOMEM; goto alloc_err; } } @@ -281,14 +283,17 @@ int qed_resc_alloc(struct qed_dev *cdev) /* EQ */ p_eq = qed_eq_alloc(p_hwfn, 256); - - if (!p_eq) + if (!p_eq) { + rc = -ENOMEM; goto alloc_err; + } p_hwfn->p_eq = p_eq; p_consq = qed_consq_alloc(p_hwfn); - if (!p_consq) + if (!p_consq) { + rc = -ENOMEM; goto alloc_err; + } p_hwfn->p_consq = p_consq; /* DMA info initialization */ @@ -303,6 +308,7 @@ int qed_resc_alloc(struct qed_dev *cdev) cdev->reset_stats = kzalloc(sizeof(*cdev->reset_stats), GFP_KERNEL); if (!cdev->reset_stats) { DP_NOTICE(cdev, "Failed to allocate reset statistics\n"); + rc = -ENOMEM; goto alloc_err; } -- cgit v1.2.3 From 428ad1bc6dd766bb44171bba43a8a3219be77d2e Mon Sep 17 00:00:00 2001 From: LABBE Corentin Date: Thu, 5 Nov 2015 10:26:46 +0100 Subject: net: stmmac: fix double-initialization of phy_iface The variable phy_iface is double-initialized to itself. This patch remove that. Reported-by: coverity (CID 1271141) Signed-off-by: LABBE Corentin Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 11baa4b19779..0cd3ecff768b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -354,7 +354,7 @@ static int gmac_clk_init(struct rk_priv_data *bsp_priv) static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable) { - int phy_iface = phy_iface = bsp_priv->phy_iface; + int phy_iface = bsp_priv->phy_iface; if (enable) { if (!bsp_priv->clk_enabled) { -- cgit v1.2.3 From c5d7774db350e77f2506e36e1797c958d1b118c8 Mon Sep 17 00:00:00 2001 From: Jeffrey Huang Date: Thu, 5 Nov 2015 16:25:47 -0500 Subject: bnxt_en: Change sp events definitions to represent bit position. Fix the sp event bits to be bit positions instead of bit values since the bit helper functions are expecting the former. Signed-off-by: Jeffrey Huang Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 4f2267ca482d..4cae4928b27c 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -959,11 +959,11 @@ struct bnxt { #define BNXT_RX_MASK_SP_EVENT 0 #define BNXT_RX_NTP_FLTR_SP_EVENT 1 #define BNXT_LINK_CHNG_SP_EVENT 2 -#define BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT 4 -#define BNXT_VXLAN_ADD_PORT_SP_EVENT 8 -#define BNXT_VXLAN_DEL_PORT_SP_EVENT 16 -#define BNXT_RESET_TASK_SP_EVENT 32 -#define BNXT_RST_RING_SP_EVENT 64 +#define BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT 3 +#define BNXT_VXLAN_ADD_PORT_SP_EVENT 4 +#define BNXT_VXLAN_DEL_PORT_SP_EVENT 5 +#define BNXT_RESET_TASK_SP_EVENT 6 +#define BNXT_RST_RING_SP_EVENT 7 struct bnxt_pf_info pf; #ifdef CONFIG_BNXT_SRIOV -- cgit v1.2.3 From 614388ce39f3d61ad7f95db65f409d35d5943616 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 5 Nov 2015 16:25:48 -0500 Subject: bnxt_en: Determine tcp/ipv6 RSS hash type correctly. The profile ID in the completion record needs to be ANDed with the profile ID mask of 0x1f. This bug was causing the SKB hash type and the gso_type to be wrong in some cases. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 4cae4928b27c..5afe65d1316b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -166,9 +166,11 @@ struct rx_cmp { #define RX_CMP_HASH_VALID(rxcmp) \ ((rxcmp)->rx_cmp_len_flags_type & cpu_to_le32(RX_CMP_FLAGS_RSS_VALID)) +#define RSS_PROFILE_ID_MASK 0x1f + #define RX_CMP_HASH_TYPE(rxcmp) \ - ((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_RSS_HASH_TYPE) >>\ - RX_CMP_RSS_HASH_TYPE_SHIFT) + (((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_RSS_HASH_TYPE) >>\ + RX_CMP_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK) struct rx_cmp_ext { __le32 rx_cmp_flags2; @@ -282,9 +284,9 @@ struct rx_tpa_start_cmp { cpu_to_le32(RX_TPA_START_CMP_FLAGS_RSS_VALID)) #define TPA_START_HASH_TYPE(rx_tpa_start) \ - ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ - RX_TPA_START_CMP_RSS_HASH_TYPE) >> \ - RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT) + (((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ + RX_TPA_START_CMP_RSS_HASH_TYPE) >> \ + RX_TPA_START_CMP_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK) #define TPA_START_AGG_ID(rx_tpa_start) \ ((le32_to_cpu((rx_tpa_start)->rx_tpa_start_cmp_misc_v1) & \ -- cgit v1.2.3 From 11809490ac17810cff90c12e9f2f3e0303a72121 Mon Sep 17 00:00:00 2001 From: Jeffrey Huang Date: Thu, 5 Nov 2015 16:25:49 -0500 Subject: bnxt_en: map CAG_REG_LEGACY_INT_STATUS_MASK to GRC window #4 In order to use offset 0x4014 for reading CAG interrupt status, the actual CAG register must be mapped to GRC bar0 window #4. Otherwise, the driver is reading garbage. This patch corrects this issue. Signed-off-by: Jeffrey Huang Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 19 ++++++++++++++++--- drivers/net/ethernet/broadcom/bnxt/bnxt.h | 4 ++++ 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 6c2e0c622831..a62deff5a4ac 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1292,8 +1292,6 @@ static inline int bnxt_has_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr) return TX_CMP_VALID(txcmp, raw_cons); } -#define CAG_LEGACY_INT_STATUS 0x2014 - static irqreturn_t bnxt_inta(int irq, void *dev_instance) { struct bnxt_napi *bnapi = dev_instance; @@ -1305,7 +1303,7 @@ static irqreturn_t bnxt_inta(int irq, void *dev_instance) prefetch(&cpr->cp_desc_ring[CP_RING(cons)][CP_IDX(cons)]); if (!bnxt_has_work(bp, cpr)) { - int_status = readl(bp->bar0 + CAG_LEGACY_INT_STATUS); + int_status = readl(bp->bar0 + BNXT_CAG_REG_LEGACY_INT_STATUS); /* return if erroneous interrupt */ if (!(int_status & (0x10000 << cpr->cp_ring_struct.fw_ring_id))) return IRQ_NONE; @@ -4527,10 +4525,25 @@ static int bnxt_update_phy_setting(struct bnxt *bp) return rc; } +/* Common routine to pre-map certain register block to different GRC window. + * A PF has 16 4K windows and a VF has 4 4K windows. However, only 15 windows + * in PF and 3 windows in VF that can be customized to map in different + * register blocks. + */ +static void bnxt_preset_reg_win(struct bnxt *bp) +{ + if (BNXT_PF(bp)) { + /* CAG registers map to GRC window #4 */ + writel(BNXT_CAG_REG_BASE, + bp->bar0 + BNXT_GRCPF_REG_WINDOW_BASE_OUT + 12); + } +} + static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) { int rc = 0; + bnxt_preset_reg_win(bp); netif_carrier_off(bp->dev); if (irq_re_init) { rc = bnxt_setup_int_mode(bp); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 5afe65d1316b..674bc5159b91 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -841,6 +841,10 @@ struct bnxt_queue_info { u8 queue_profile; }; +#define BNXT_GRCPF_REG_WINDOW_BASE_OUT 0x400 +#define BNXT_CAG_REG_LEGACY_INT_STATUS 0x4014 +#define BNXT_CAG_REG_BASE 0x300000 + struct bnxt { void __iomem *bar0; void __iomem *bar1; -- cgit v1.2.3 From 84e86b98f6515aaeaac053b234be158b25457184 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 5 Nov 2015 16:25:50 -0500 Subject: bnxt_en: Fix comparison of u16 sw_id against negative value. Assign the return value from bitmap_find_free_region() to an integer variable and check for negative error codes first, before assigning the bit ID to the unsigned sw_id field. Reported-by: Dan Carpenter Cc: Dan Carpenter Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index a62deff5a4ac..db15c5ee09c5 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -5307,7 +5307,7 @@ static int bnxt_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, struct bnxt_ntuple_filter *fltr, *new_fltr; struct flow_keys *fkeys; struct ethhdr *eth = (struct ethhdr *)skb_mac_header(skb); - int rc = 0, idx; + int rc = 0, idx, bit_id; struct hlist_head *head; if (skb->encapsulation) @@ -5345,14 +5345,15 @@ static int bnxt_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, rcu_read_unlock(); spin_lock_bh(&bp->ntp_fltr_lock); - new_fltr->sw_id = bitmap_find_free_region(bp->ntp_fltr_bmap, - BNXT_NTP_FLTR_MAX_FLTR, 0); - if (new_fltr->sw_id < 0) { + bit_id = bitmap_find_free_region(bp->ntp_fltr_bmap, + BNXT_NTP_FLTR_MAX_FLTR, 0); + if (bit_id < 0) { spin_unlock_bh(&bp->ntp_fltr_lock); rc = -ENOMEM; goto err_free; } + new_fltr->sw_id = (u16)bit_id; new_fltr->flow_id = flow_id; new_fltr->rxq = rxq_index; hlist_add_head_rcu(&new_fltr->hash, head); -- cgit v1.2.3 From 4bb6cdce386d620d10d2588ea5bf4093a3b21ab9 Mon Sep 17 00:00:00 2001 From: Jeffrey Huang Date: Thu, 5 Nov 2015 16:25:51 -0500 Subject: bnxt_en: More robust SRIOV cleanup sequence. Instead of always calling pci_sriov_disable() in remove_one(), the driver should detect whether VFs are currently assigned to the VMs. If the VFs are active in VMs, then it should not disable SRIOV as it is catastrophic to the VMs. Instead, it just leaves the VFs alone and continues to unload the PF. The user can then cleanup the VMs even after the PF driver has been unloaded. Signed-off-by: Jeffrey Huang Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c | 40 +++++++++++++++++-------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c index 60989e7e266a..f4cf68861069 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c @@ -258,7 +258,7 @@ static int bnxt_set_vf_attr(struct bnxt *bp, int num_vfs) return 0; } -static int bnxt_hwrm_func_vf_resource_free(struct bnxt *bp) +static int bnxt_hwrm_func_vf_resource_free(struct bnxt *bp, int num_vfs) { int i, rc = 0; struct bnxt_pf_info *pf = &bp->pf; @@ -267,7 +267,7 @@ static int bnxt_hwrm_func_vf_resource_free(struct bnxt *bp) bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_VF_RESC_FREE, -1, -1); mutex_lock(&bp->hwrm_cmd_lock); - for (i = pf->first_vf_id; i < pf->first_vf_id + pf->active_vfs; i++) { + for (i = pf->first_vf_id; i < pf->first_vf_id + num_vfs; i++) { req.vf_id = cpu_to_le16(i); rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); @@ -509,7 +509,7 @@ static int bnxt_sriov_enable(struct bnxt *bp, int *num_vfs) err_out2: /* Free the resources reserved for various VF's */ - bnxt_hwrm_func_vf_resource_free(bp); + bnxt_hwrm_func_vf_resource_free(bp, *num_vfs); err_out1: bnxt_free_vf_resources(bp); @@ -519,13 +519,19 @@ err_out1: void bnxt_sriov_disable(struct bnxt *bp) { - if (!bp->pf.active_vfs) - return; + u16 num_vfs = pci_num_vf(bp->pdev); - pci_disable_sriov(bp->pdev); + if (!num_vfs) + return; - /* Free the resources reserved for various VF's */ - bnxt_hwrm_func_vf_resource_free(bp); + if (pci_vfs_assigned(bp->pdev)) { + netdev_warn(bp->dev, "Unable to free %d VFs because some are assigned to VMs.\n", + num_vfs); + } else { + pci_disable_sriov(bp->pdev); + /* Free the HW resources reserved for various VF's */ + bnxt_hwrm_func_vf_resource_free(bp, num_vfs); + } bnxt_free_vf_resources(bp); @@ -552,17 +558,25 @@ int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs) } bp->sriov_cfg = true; rtnl_unlock(); - if (!num_vfs) { - bnxt_sriov_disable(bp); - return 0; + + if (pci_vfs_assigned(bp->pdev)) { + netdev_warn(dev, "Unable to configure SRIOV since some VFs are assigned to VMs.\n"); + num_vfs = 0; + goto sriov_cfg_exit; } /* Check if enabled VFs is same as requested */ - if (num_vfs == bp->pf.active_vfs) - return 0; + if (num_vfs && num_vfs == bp->pf.active_vfs) + goto sriov_cfg_exit; + + /* if there are previous existing VFs, clean them up */ + bnxt_sriov_disable(bp); + if (!num_vfs) + goto sriov_cfg_exit; bnxt_sriov_enable(bp, &num_vfs); +sriov_cfg_exit: bp->sriov_cfg = false; wake_up(&bp->sriov_cfg_wait); -- cgit v1.2.3 From 1831eff876bd0bb8d64e9965a7ff47486c9a3ecd Mon Sep 17 00:00:00 2001 From: "Suthikulpanit, Suravee" Date: Wed, 28 Oct 2015 15:50:50 -0700 Subject: device property: ACPI: Make use of the new DMA Attribute APIs Now that we have the new DMA attribute APIs, we can replace the older acpi_check_dma() and device_dma_is_coherent(). Signed-off-by: Suravee Suthikulpanit Acked-by: Bjorn Helgaas Reviewed-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- drivers/net/ethernet/amd/xgbe/xgbe-main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index e83bd76abce6..c607b3f88f0b 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -342,6 +342,7 @@ static int xgbe_probe(struct platform_device *pdev) struct resource *res; const char *phy_mode; unsigned int i, phy_memnum, phy_irqnum; + enum dev_dma_attr attr; int ret; DBGPR("--> xgbe_probe\n"); @@ -609,7 +610,12 @@ static int xgbe_probe(struct platform_device *pdev) goto err_io; /* Set the DMA coherency values */ - pdata->coherent = device_dma_is_coherent(pdata->dev); + attr = device_get_dma_attr(dev); + if (attr == DEV_DMA_NOT_SUPPORTED) { + dev_err(dev, "DMA is not supported"); + goto err_io; + } + pdata->coherent = (attr == DEV_DMA_COHERENT); if (pdata->coherent) { pdata->axdomain = XGBE_DMA_OS_AXDOMAIN; pdata->arcache = XGBE_DMA_OS_ARCACHE; -- cgit v1.2.3 From d0164adc89f6bb374d304ffcc375c6d2652fe67d Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Fri, 6 Nov 2015 16:28:21 -0800 Subject: mm, page_alloc: distinguish between being unable to sleep, unwilling to sleep and avoiding waking kswapd __GFP_WAIT has been used to identify atomic context in callers that hold spinlocks or are in interrupts. They are expected to be high priority and have access one of two watermarks lower than "min" which can be referred to as the "atomic reserve". __GFP_HIGH users get access to the first lower watermark and can be called the "high priority reserve". Over time, callers had a requirement to not block when fallback options were available. Some have abused __GFP_WAIT leading to a situation where an optimisitic allocation with a fallback option can access atomic reserves. This patch uses __GFP_ATOMIC to identify callers that are truely atomic, cannot sleep and have no alternative. High priority users continue to use __GFP_HIGH. __GFP_DIRECT_RECLAIM identifies callers that can sleep and are willing to enter direct reclaim. __GFP_KSWAPD_RECLAIM to identify callers that want to wake kswapd for background reclaim. __GFP_WAIT is redefined as a caller that is willing to enter direct reclaim and wake kswapd for background reclaim. This patch then converts a number of sites o __GFP_ATOMIC is used by callers that are high priority and have memory pools for those requests. GFP_ATOMIC uses this flag. o Callers that have a limited mempool to guarantee forward progress clear __GFP_DIRECT_RECLAIM but keep __GFP_KSWAPD_RECLAIM. bio allocations fall into this category where kswapd will still be woken but atomic reserves are not used as there is a one-entry mempool to guarantee progress. o Callers that are checking if they are non-blocking should use the helper gfpflags_allow_blocking() where possible. This is because checking for __GFP_WAIT as was done historically now can trigger false positives. Some exceptions like dm-crypt.c exist where the code intent is clearer if __GFP_DIRECT_RECLAIM is used instead of the helper due to flag manipulations. o Callers that built their own GFP flags instead of starting with GFP_KERNEL and friends now also need to specify __GFP_KSWAPD_RECLAIM. The first key hazard to watch out for is callers that removed __GFP_WAIT and was depending on access to atomic reserves for inconspicuous reasons. In some cases it may be appropriate for them to use __GFP_HIGH. The second key hazard is callers that assembled their own combination of GFP flags instead of starting with something like GFP_KERNEL. They may now wish to specify __GFP_KSWAPD_RECLAIM. It's almost certainly harmless if it's missed in most cases as other activity will wake kswapd. Signed-off-by: Mel Gorman Acked-by: Vlastimil Babka Acked-by: Michal Hocko Acked-by: Johannes Weiner Cc: Christoph Lameter Cc: David Rientjes Cc: Vitaly Wool Cc: Rik van Riel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 44173be5cbf0..f8d7a2f06950 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -691,7 +691,7 @@ static void *bnx2x_frag_alloc(const struct bnx2x_fastpath *fp, gfp_t gfp_mask) { if (fp->rx_frag_size) { /* GFP_KERNEL allocations are used only during initialization */ - if (unlikely(gfp_mask & __GFP_WAIT)) + if (unlikely(gfpflags_allow_blocking(gfp_mask))) return (void *)__get_free_page(gfp_mask); return netdev_alloc_frag(fp->rx_frag_size); -- cgit v1.2.3 From f7b5964d4d0bddf429c44b457172891be000a3d3 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 6 Nov 2015 09:30:29 +0100 Subject: fjes: Delete an unnecessary check before the function call "vfree" The vfree() function performs also input parameter validation. Thus the test around the call is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_hw.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c index 2d3848c9dc35..bb8b5304d851 100644 --- a/drivers/net/fjes/fjes_hw.c +++ b/drivers/net/fjes/fjes_hw.c @@ -143,9 +143,7 @@ static int fjes_hw_alloc_epbuf(struct epbuf_handler *epbh) static void fjes_hw_free_epbuf(struct epbuf_handler *epbh) { - if (epbh->buffer) - vfree(epbh->buffer); - + vfree(epbh->buffer); epbh->buffer = NULL; epbh->size = 0; -- cgit v1.2.3 From e824de8ae2a00ee71c5bfbadd004d12c6dd85561 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Fri, 6 Nov 2015 09:25:31 -0500 Subject: net/qlcnic: fix mac address restore in bond mode 5/6 The bonding driver saves a copy of slaves' original mac address and then assigns whatever mac as needed to the slave, depending on mode. In at least modes 5 and 6 (balance-tlb, balance-alb), it often ends up being the mac address of another slave. On release from the bond, the original mac address is supposed to get restored via a dev_set_mac_address() call in the bonding driver's __bond_release_one() function, which calls the slave's ndo_set_mac_address function, which for qlcnic, is qlcnic_set_mac(). Now, this function tries to be somewhat intelligent and exit early if you're trying to set the mac address to the same thing that is already set. The problem here is that adapter->mac_addr isn't in sync with netdev->dev_addr. The qlcnic driver still has the original mac stored in adapter->mac_addr, while the bonding driver has updated netdev->dev_addr, so qlcnic thinks we're trying to set the same address it already has. I think the way to go here, since the function updates both netdev and adapter's stored mac addresses, is to check if either of them doesn't match the newly requested mac. Simply checking netdev's value only could result in a similar mismatch and non-update, so look at both. CC: Dept-GELinuxNICDev@qlogic.com CC: netdev@vger.kernel.org CC: Manish Chopra Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index d4481454b5f8..1205f6f9c941 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -353,7 +353,8 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EINVAL; - if (ether_addr_equal_unaligned(adapter->mac_addr, addr->sa_data)) + if (ether_addr_equal_unaligned(adapter->mac_addr, addr->sa_data) && + ether_addr_equal_unaligned(netdev->dev_addr, addr->sa_data)) return 0; if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { -- cgit v1.2.3 From 40baec225765c54eefa870530dd613bad9829bb7 Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Fri, 6 Nov 2015 17:23:23 -0800 Subject: bonding: fix panic on non-ARPHRD_ETHER enslave failure Since commit 7d5cd2ce529b, when bond_enslave fails on devices that are not ARPHRD_ETHER, if needed, it resets the bonding device back to ARPHRD_ETHER by calling ether_setup. Unfortunately, ether_setup clobbers dev->flags, clearing IFF_UP if the bond device is up, leaving it in a quasi-down state without having actually gone through dev_close. For bonding, if any periodic work queue items are active (miimon, arp_interval, etc), those will remain running, as they are stopped by bond_close. At this point, if the bonding module is unloaded or the bond is deleted, the system will panic when the work function is called. This panic is resolved by calling dev_close on the bond itself prior to calling ether_setup. Cc: Nikolay Aleksandrov Signed-off-by: Jay Vosburgh Fixes: 7d5cd2ce5292 ("bonding: correctly handle bonding type change on enslave failure") Acked-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b4351caf8e01..9e0f8a7ef8b1 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1749,6 +1749,7 @@ err_undo_flags: slave_dev->dev_addr)) eth_hw_addr_random(bond_dev); if (bond_dev->type != ARPHRD_ETHER) { + dev_close(bond_dev); ether_setup(bond_dev); bond_dev->flags |= IFF_MASTER; bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING; -- cgit v1.2.3 From 3694bfbdb3bd5cf6632140c7f7fdf6f31d43ee66 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sat, 7 Nov 2015 16:30:34 +0100 Subject: dwc_eth_qos: Delete an unnecessary check before the function call "of_node_put" The of_node_put() function tests whether its argument is NULL and then returns immediately. Thus the test around the call is not needed. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: David S. Miller --- drivers/net/ethernet/synopsys/dwc_eth_qos.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/synopsys/dwc_eth_qos.c b/drivers/net/ethernet/synopsys/dwc_eth_qos.c index 85b3326775b8..9066d7a8483c 100644 --- a/drivers/net/ethernet/synopsys/dwc_eth_qos.c +++ b/drivers/net/ethernet/synopsys/dwc_eth_qos.c @@ -2970,8 +2970,7 @@ err_out_unregister_netdev: err_out_clk_dis_aper: clk_disable_unprepare(lp->apb_pclk); err_out_free_netdev: - if (lp->phy_node) - of_node_put(lp->phy_node); + of_node_put(lp->phy_node); free_netdev(ndev); platform_set_drvdata(pdev, NULL); return ret; -- cgit v1.2.3 From 761d4be5cf666973db317aab944b45bb07fe0a4f Mon Sep 17 00:00:00 2001 From: Iyappan Subramanian Date: Sat, 7 Nov 2015 11:50:40 -0800 Subject: drivers: net: xgene: fix RGMII 10/100Mb mode This patch fixes the RGMII 10/100M mode by reprogramming the clock. Signed-off-by: Iyappan Subramanian Tested-by: Fushen Chen Signed-off-by: David S. Miller --- drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 49 +++++++++++++++++++++++- drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 1 + drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 1 - 3 files changed, 48 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c index 33850a0f7e82..c31e691d11fc 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c @@ -459,6 +459,45 @@ static void xgene_gmac_reset(struct xgene_enet_pdata *pdata) xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0); } +static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata) +{ + struct device *dev = &pdata->pdev->dev; + + if (dev->of_node) { + struct clk *parent = clk_get_parent(pdata->clk); + + switch (pdata->phy_speed) { + case SPEED_10: + clk_set_rate(parent, 2500000); + break; + case SPEED_100: + clk_set_rate(parent, 25000000); + break; + default: + clk_set_rate(parent, 125000000); + break; + } + } +#ifdef CONFIG_ACPI + else { + switch (pdata->phy_speed) { + case SPEED_10: + acpi_evaluate_object(ACPI_HANDLE(dev), + "S10", NULL, NULL); + break; + case SPEED_100: + acpi_evaluate_object(ACPI_HANDLE(dev), + "S100", NULL, NULL); + break; + default: + acpi_evaluate_object(ACPI_HANDLE(dev), + "S1G", NULL, NULL); + break; + } + } +#endif +} + static void xgene_gmac_init(struct xgene_enet_pdata *pdata) { struct device *dev = &pdata->pdev->dev; @@ -477,12 +516,14 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata) switch (pdata->phy_speed) { case SPEED_10: ENET_INTERFACE_MODE2_SET(&mc2, 1); + intf_ctl &= ~(ENET_LHD_MODE | ENET_GHD_MODE); CFG_MACMODE_SET(&icm0, 0); CFG_WAITASYNCRD_SET(&icm2, 500); rgmii &= ~CFG_SPEED_1250; break; case SPEED_100: ENET_INTERFACE_MODE2_SET(&mc2, 1); + intf_ctl &= ~ENET_GHD_MODE; intf_ctl |= ENET_LHD_MODE; CFG_MACMODE_SET(&icm0, 1); CFG_WAITASYNCRD_SET(&icm2, 80); @@ -490,12 +531,15 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata) break; default: ENET_INTERFACE_MODE2_SET(&mc2, 2); + intf_ctl &= ~ENET_LHD_MODE; intf_ctl |= ENET_GHD_MODE; - + CFG_MACMODE_SET(&icm0, 2); + CFG_WAITASYNCRD_SET(&icm2, 0); if (dev->of_node) { CFG_TXCLK_MUXSEL0_SET(&rgmii, pdata->tx_delay); CFG_RXCLK_MUXSEL0_SET(&rgmii, pdata->rx_delay); } + rgmii |= CFG_SPEED_1250; xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value); value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX; @@ -503,7 +547,7 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata) break; } - mc2 |= FULL_DUPLEX2; + mc2 |= FULL_DUPLEX2 | PAD_CRC; xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2); xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl); @@ -522,6 +566,7 @@ static void xgene_gmac_init(struct xgene_enet_pdata *pdata) /* Rtype should be copied from FP */ xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0); xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii); + xgene_enet_configure_clock(pdata); /* Rx-Tx traffic resume */ xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0); diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h index 6dee73c3c1e1..c153a1dc5ff7 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h @@ -181,6 +181,7 @@ enum xgene_enet_rm { #define ENET_LHD_MODE BIT(25) #define ENET_GHD_MODE BIT(26) #define FULL_DUPLEX2 BIT(0) +#define PAD_CRC BIT(2) #define SCAN_AUTO_INCR BIT(5) #define TBYT_ADDR 0x38 #define TPKT_ADDR 0x39 diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index ce1068771b32..991412ce6f48 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -698,7 +698,6 @@ static int xgene_enet_open(struct net_device *ndev) else schedule_delayed_work(&pdata->link_work, PHY_POLL_LINK_OFF); - netif_carrier_off(ndev); netif_start_queue(ndev); return ret; -- cgit v1.2.3 From 3870502a66fe26c80c034db1aa915d69850854aa Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 9 Nov 2015 10:34:30 +0100 Subject: net: hisilicon: NET_VENDOR_HISILICON should depend on HAS_DMA If NO_DMA=y: ERROR: "dma_set_mask" [drivers/net/ethernet/hisilicon/hns/hns_enet_drv.ko] undefined! ERROR: "dma_unmap_single" [drivers/net/ethernet/hisilicon/hns/hns_enet_drv.ko] undefined! ERROR: "dma_unmap_page" [drivers/net/ethernet/hisilicon/hns/hns_enet_drv.ko] undefined! ERROR: "dma_mapping_error" [drivers/net/ethernet/hisilicon/hns/hns_enet_drv.ko] undefined! ERROR: "dma_map_page" [drivers/net/ethernet/hisilicon/hns/hns_enet_drv.ko] undefined! ERROR: "dma_supported" [drivers/net/ethernet/hisilicon/hns/hns_enet_drv.ko] undefined! ERROR: "dma_map_single" [drivers/net/ethernet/hisilicon/hns/hns_enet_drv.ko] undefined! ERROR: "dma_set_mask" [drivers/net/ethernet/hisilicon/hns/hns_dsaf.ko] undefined! ERROR: "dma_supported" [drivers/net/ethernet/hisilicon/hns/hns_dsaf.ko] undefined! ERROR: "dma_unmap_single" [drivers/net/ethernet/hisilicon/hns/hnae.ko] undefined! ERROR: "dma_unmap_page" [drivers/net/ethernet/hisilicon/hns/hnae.ko] undefined! ERROR: "dma_mapping_error" [drivers/net/ethernet/hisilicon/hns/hnae.ko] undefined! ERROR: "dma_map_page" [drivers/net/ethernet/hisilicon/hns/hnae.ko] undefined! ERROR: "dma_map_single" [drivers/net/ethernet/hisilicon/hns/hnae.ko] undefined! ERROR: "dma_alloc_coherent" [drivers/net/ethernet/hisilicon/hix5hd2_gmac.ko] undefined! ERROR: "dma_mapping_error" [drivers/net/ethernet/hisilicon/hix5hd2_gmac.ko] undefined! ERROR: "dma_map_single" [drivers/net/ethernet/hisilicon/hix5hd2_gmac.ko] undefined! ERROR: "dma_unmap_single" [drivers/net/ethernet/hisilicon/hix5hd2_gmac.ko] undefined! ERROR: "dma_free_coherent" [drivers/net/ethernet/hisilicon/hix5hd2_gmac.ko] undefined! ERROR: "dma_alloc_coherent" [drivers/net/ethernet/hisilicon/hip04_eth.ko] undefined! ERROR: "dma_mapping_error" [drivers/net/ethernet/hisilicon/hip04_eth.ko] undefined! ERROR: "dma_map_single" [drivers/net/ethernet/hisilicon/hip04_eth.ko] undefined! ERROR: "dma_unmap_single" [drivers/net/ethernet/hisilicon/hip04_eth.ko] undefined! ERROR: "dma_free_coherent" [drivers/net/ethernet/hisilicon/hip04_eth.ko] undefined! As this affects all of HNS_ENET, HNS_DSAF, HNS, HIX5HD2_GMAC, and HIP04_ETH, add a dependency on HAS_DMA to the main NET_VENDOR_HISILICON symbol to fix this. Signed-off-by: Geert Uytterhoeven Acked-by: Arnd Bergmann Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/hisilicon/Kconfig b/drivers/net/ethernet/hisilicon/Kconfig index f250dec488fd..74beb1867230 100644 --- a/drivers/net/ethernet/hisilicon/Kconfig +++ b/drivers/net/ethernet/hisilicon/Kconfig @@ -5,7 +5,8 @@ config NET_VENDOR_HISILICON bool "Hisilicon devices" default y - depends on OF && (ARM || ARM64 || COMPILE_TEST) + depends on OF && HAS_DMA + depends on ARM || ARM64 || COMPILE_TEST ---help--- If you have a network (Ethernet) card belonging to this class, say Y. -- cgit v1.2.3 From cfb76d77c009b38e607c8a2adc8bdd57b5081768 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 9 Nov 2015 13:19:10 +0100 Subject: net: caif: check return value of alloc_netdev I don't know if dev can actually be NULL here, but the test should be above alloc_netdev(), to avoid leaking the struct net_device in case dev is actually NULL. And of course the return value from alloc_netdev should be tested. Signed-off-by: Rasmus Villemoes Signed-off-by: David S. Miller --- drivers/net/caif/caif_spi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c index de3962014af7..4721948a92f6 100644 --- a/drivers/net/caif/caif_spi.c +++ b/drivers/net/caif/caif_spi.c @@ -730,11 +730,14 @@ int cfspi_spi_probe(struct platform_device *pdev) int res; dev = (struct cfspi_dev *)pdev->dev.platform_data; - ndev = alloc_netdev(sizeof(struct cfspi), "cfspi%d", - NET_NAME_UNKNOWN, cfspi_setup); if (!dev) return -ENODEV; + ndev = alloc_netdev(sizeof(struct cfspi), "cfspi%d", + NET_NAME_UNKNOWN, cfspi_setup); + if (!ndev) + return -ENOMEM; + cfspi = netdev_priv(ndev); netif_stop_queue(ndev); cfspi->ndev = ndev; -- cgit v1.2.3 From 4bed5395a521b475c2164510596d9af366a3d6dc Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 9 Nov 2015 15:08:57 +0100 Subject: mvneta: add FIXED_PHY dependency The fixed_phy infrastructure is done in a way that is optional, by providing 'static inline' helper functions doing nothing in include/linux/phy_fixed.h for all its APIs. However, three out of the four users (DSA, BCMGENET, and SYSTEMPORT) always 'select FIXED_PHY', presumably because they need that. MVNETA is the fourth one, and if that is built-in but FIXED_PHY is configured as a loadable module, we get a link error: drivers/built-in.o: In function `mvneta_fixed_link_update': fpga-mgr.c:(.text+0x33ed80): undefined reference to `fixed_phy_update_state' Presumably this driver has the same dependency as the others, so this patch also uses 'select' to ensure that the fixed-phy support is built-in. Signed-off-by: Arnd Bergmann Fixes: 898b2970e2c9 ("mvneta: implement SGMII-based in-band link state signaling") Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig index 80af9ffce5ea..a1c862b4664d 100644 --- a/drivers/net/ethernet/marvell/Kconfig +++ b/drivers/net/ethernet/marvell/Kconfig @@ -44,6 +44,7 @@ config MVNETA tristate "Marvell Armada 370/38x/XP network interface support" depends on PLAT_ORION select MVMDIO + select FIXED_PHY ---help--- This driver supports the network interface units in the Marvell ARMADA XP, ARMADA 370 and ARMADA 38x SoC family. -- cgit v1.2.3 From a499a2e9d9c03fd35bd9920b629e4d5b1d6cc1f0 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Mon, 9 Nov 2015 09:14:17 -0500 Subject: macvtap: Resolve possible __might_sleep warning in macvtap_do_read() macvtap_do_read code calls macvtap_put_user while it might be set up to wait for the user. This results in the following warning: Jun 23 16:25:26 galen kernel: ------------[ cut here ]------------ Jun 23 16:25:26 galen kernel: WARNING: CPU: 0 PID: 30433 at kernel/sched/core.c: 7286 __might_sleep+0x7f/0x90() Jun 23 16:25:26 galen kernel: do not call blocking ops when !TASK_RUNNING; state =1 set at [] prepare_to_wait+0x2f/0x90 Jun 23 16:25:26 galen kernel: CPU: 0 PID: 30433 Comm: cat Not tainted 4.1.0-rc6+ #11 Jun 23 16:25:26 galen kernel: Call Trace: Jun 23 16:25:26 galen kernel: [] dump_stack+0x4c/0x65 Jun 23 16:25:26 galen kernel: [] warn_slowpath_common+0x8a/0xc 0 Jun 23 16:25:26 galen kernel: [] warn_slowpath_fmt+0x46/0x50 Jun 23 16:25:26 galen kernel: [] ? prepare_to_wait+0x2f/0x90 Jun 23 16:25:26 galen kernel: [] ? prepare_to_wait+0x2f/0x90 Jun 23 16:25:26 galen kernel: [] __might_sleep+0x7f/0x90 Jun 23 16:25:26 galen kernel: [] might_fault+0x55/0xb0 Jun 23 16:25:26 galen kernel: [] ? trace_hardirqs_on_caller+0x fd/0x1c0 Jun 23 16:25:26 galen kernel: [] copy_to_iter+0x7c/0x360 Jun 23 16:25:26 galen kernel: [] macvtap_do_read+0x256/0x3d0 [macvtap] Jun 23 16:25:26 galen kernel: [] ? prepare_to_wait_event+0x110/0x110 Jun 23 16:25:26 galen kernel: [] macvtap_read_iter+0x2b/0x50 [macvtap] Jun 23 16:25:26 galen kernel: [] __vfs_read+0xae/0xe0 Jun 23 16:25:26 galen kernel: [] vfs_read+0x86/0x140 Jun 23 16:25:26 galen kernel: [] SyS_read+0x49/0xb0 Jun 23 16:25:26 galen kernel: [] system_call_fastpath+0x12/0x76 Jun 23 16:25:26 galen kernel: ---[ end trace 22e33f67e70c0c2a ]--- Make sure thet we call finish_wait() if we have the skb to process before trying to actually process it. Signed-off-by: Vladislav Yasevich Signed-off-by: David S. Miller --- drivers/net/macvtap.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 197c93937c2d..54036ae0a388 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -935,6 +935,9 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q, /* Nothing to read, let's sleep */ schedule(); } + if (!noblock) + finish_wait(sk_sleep(&q->sk), &wait); + if (skb) { ret = macvtap_put_user(q, skb, to); if (unlikely(ret < 0)) @@ -942,8 +945,6 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q, else consume_skb(skb); } - if (!noblock) - finish_wait(sk_sleep(&q->sk), &wait); return ret; } -- cgit v1.2.3 From 79211c8ed19c055ca105502c8733800d442a0ae6 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 9 Nov 2015 14:58:13 -0800 Subject: remove abs64() Switch everything to the new and more capable implementation of abs(). Mainly to give the new abs() a bit of a workout. Cc: Michal Nazarewicz Cc: John Stultz Cc: Ingo Molnar Cc: Steven Rostedt Cc: Peter Zijlstra Cc: Masami Hiramatsu Cc: Peter Zijlstra Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/wireless/mac80211_hwsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index ee46f4647fbc..c00a7daaa4bc 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -787,7 +787,7 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw, struct mac80211_hwsim_data *data = hw->priv; u64 now = mac80211_hwsim_get_tsf(hw, vif); u32 bcn_int = data->beacon_int; - u64 delta = abs64(tsf - now); + u64 delta = abs(tsf - now); /* adjust after beaconing with new timestamp at old TBTT */ if (tsf > now) { -- cgit v1.2.3 From 8c94ddbc139bf8511d79153a81191b07f8e03eb4 Mon Sep 17 00:00:00 2001 From: Justin Maggard Date: Mon, 9 Nov 2015 17:21:05 -0800 Subject: net: mvneta: Fix memory use after free. After changing an interface's MTU, then bringing the interface down and back up again, I immediately saw tons of kernel messages like below. The reason for this bad behavior is mvneta_rxq_drop_pkts(), which calls dma_unmap_single() on already-freed memory. So we need to switch the order of those two operations. [ 152.388518] BUG: Bad page state in process ifconfig pfn:1b518 [ 152.388526] page:dff3dbc0 count:0 mapcount:0 mapping: (null) index:0x0 [ 152.395178] flags: 0x200(arch_1) [ 152.398441] page dumped because: PAGE_FLAGS_CHECK_AT_PREP flag set [ 152.398446] bad because of flags: [ 152.398450] flags: 0x200(arch_1) [ 152.401716] Modules linked in: [ 152.401728] CPU: 0 PID: 1453 Comm: ifconfig Tainted: P B O 4.1.12.armada.1 #1 [ 152.401733] Hardware name: Marvell Armada 370/XP (Device Tree) [ 152.401749] [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [ 152.401762] [] (show_stack) from [] (dump_stack+0x74/0x90) [ 152.401772] [] (dump_stack) from [] (bad_page+0xc4/0x124) [ 152.401783] [] (bad_page) from [] (get_page_from_freelist+0x4e4/0x644) [ 152.401794] [] (get_page_from_freelist) from [] (__alloc_pages_nodemask+0x148/0x784) [ 152.401805] [] (__alloc_pages_nodemask) from [] (kmalloc_order+0x10/0x20) [ 152.401818] [] (kmalloc_order) from [] (mvneta_rx_refill+0xc4/0xe8) [ 152.401830] [] (mvneta_rx_refill) from [] (mvneta_setup_rxqs+0x298/0x39c) [ 152.401842] [] (mvneta_setup_rxqs) from [] (mvneta_open+0x3c/0x150) [ 152.401853] [] (mvneta_open) from [] (__dev_open+0xac/0x124) [ 152.401864] [] (__dev_open) from [] (__dev_change_flags+0x8c/0x148) [ 152.401875] [] (__dev_change_flags) from [] (dev_change_flags+0x18/0x48) [ 152.401886] [] (dev_change_flags) from [] (devinet_ioctl+0x620/0x6d0) [ 152.401897] [] (devinet_ioctl) from [] (sock_ioctl+0x64/0x288) [ 152.401908] [] (sock_ioctl) from [] (do_vfs_ioctl+0x78/0x608) [ 152.401918] [] (do_vfs_ioctl) from [] (SyS_ioctl+0x64/0x74) [ 152.401930] [] (SyS_ioctl) from [] (ret_fast_syscall+0x0/0x3c) Signed-off-by: Justin Maggard Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index a47496a020d9..e84c7f2634d3 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -1493,9 +1493,9 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp, struct mvneta_rx_desc *rx_desc = rxq->descs + i; void *data = (void *)rx_desc->buf_cookie; - mvneta_frag_free(pp, data); dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr, MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE); + mvneta_frag_free(pp, data); } if (rx_done) -- cgit v1.2.3 From 4bdb96cb69d9e4c6038a976fa9def9f8ae024ff8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 10 Nov 2015 11:28:15 +0100 Subject: qed: select ZLIB_INFLATE The newly added qlogic qed driver uses the zlib library, but misses the dependency: drivers/built-in.o: In function `qed_alloc_stream_mem': drivers/net/ethernet/qlogic/qed/qed_main.c:707: undefined reference to `zlib_inflate_workspacesize' drivers/built-in.o: In function `qed_unzip_data': drivers/net/ethernet/qlogic/qed/qed_main.c:675: undefined reference to `zlib_inflateInit2' This changes Kconfig to always select zlib when needed. Signed-off-by: Arnd Bergmann Fixes: fe56b9e6a8d9 ("qed: Add module with basic common support") Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig index 30a6f246dfc9..ddcfcab034c2 100644 --- a/drivers/net/ethernet/qlogic/Kconfig +++ b/drivers/net/ethernet/qlogic/Kconfig @@ -94,6 +94,7 @@ config NETXEN_NIC config QED tristate "QLogic QED 25/40/100Gb core driver" depends on PCI + select ZLIB_INFLATE ---help--- This enables the support for ... -- cgit v1.2.3 From 46a7fd8a9b302116b3263bc8e47f8f08c0d3a2ca Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 10 Nov 2015 14:45:17 -0800 Subject: pcnet32: use pci_set_dma_mask insted of pci_dma_supported All drivers should be using dma_set_mask / pci_set_dma_mask to try to set the dma mask instead of just querying it. Without that some iommu implementations may not work. pci_dma_supported is removed entirely, but dma_supported stays for dma_ops implementations for now. This patch (of 15): This ensures the dma mask that is supported by the driver is recorded in the device structure. Signed-off-by: Christoph Hellwig Acked-by: Don Fry Cc: "David S. Miller" Cc: "James E.J. Bottomley" Cc: Alan Stern Cc: Alexandre Courbot Cc: Alexey Khoroshilov Cc: Ben Skeggs Cc: Christoph Hellwig Cc: Daniel Vetter Cc: Dave Airlie Cc: David Airlie Cc: Greg Kroah-Hartman Cc: Hans Verkuil Cc: Helge Deller Cc: Jiri Slaby Cc: Mauro Carvalho Chehab Cc: Pawel Osciak Cc: Sakari Ailus Cc: Sergey Kozlov Cc: Shradha Shah Cc: Solarflare linux maintainers Cc: Steven Toth Cc: Thierry Reding Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/ethernet/amd/pcnet32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index bc8b04f42882..e2afabf3a465 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c @@ -1500,7 +1500,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } - if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) { + if (!pci_set_dma_mask(pdev, PCNET32_DMA_MASK)) { if (pcnet32_debug & NETIF_MSG_PROBE) pr_err("architecture does not support 32bit PCI busmaster DMA\n"); return -ENODEV; -- cgit v1.2.3 From 8722b8fbceecfb63bdd74674fc5e49a8c511a1f6 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 10 Nov 2015 14:45:42 -0800 Subject: sfc: don't call dma_supported dma_set_mask already checks for a supported DMA mask before updating it, the call to dma_supported is redundant. Signed-off-by: Christoph Hellwig Cc: Solarflare linux maintainers Cc: Shradha Shah Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/ethernet/sfc/efx.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 6e11ee6173ce..d288f1c928de 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1247,11 +1247,9 @@ static int efx_init_io(struct efx_nic *efx) * masks event though they reject 46 bit masks. */ while (dma_mask > 0x7fffffffUL) { - if (dma_supported(&pci_dev->dev, dma_mask)) { - rc = dma_set_mask_and_coherent(&pci_dev->dev, dma_mask); - if (rc == 0) - break; - } + rc = dma_set_mask_and_coherent(&pci_dev->dev, dma_mask); + if (rc == 0) + break; dma_mask >>= 1; } if (rc) { -- cgit v1.2.3 From 21fd6c099dc0d6eb97fbd28a8c16c1b331e1d45a Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 10 Nov 2015 14:45:44 -0800 Subject: kaweth: remove ifdefed out call to dma_supported Signed-off-by: Christoph Hellwig Cc: "David S. Miller" Cc: Oliver Neukum Cc: Alexey Khoroshilov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/usb/kaweth.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 1e9cdca37014..f64b25c221e8 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -1177,12 +1177,6 @@ err_fw: INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl); usb_set_intfdata(intf, kaweth); -#if 0 -// dma_supported() is deeply broken on almost all architectures - if (dma_supported (dev, 0xffffffffffffffffULL)) - kaweth->net->features |= NETIF_F_HIGHDMA; -#endif - SET_NETDEV_DEV(netdev, dev); if (register_netdev(netdev) != 0) { dev_err(dev, "Error registering netdev.\n"); -- cgit v1.2.3 From 704c16db0e055e9a2acd4a5353e92b1ae4408a90 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 10 Nov 2015 14:45:47 -0800 Subject: usbnet: remove ifdefed out call to dma_supported Signed-off-by: Christoph Hellwig Cc: Oliver Neukum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/usb/usbnet.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 060918f49fea..0744bf2ef2d6 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -1662,12 +1662,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) * bind() should set rx_urb_size in that case. */ dev->hard_mtu = net->mtu + net->hard_header_len; -#if 0 -// dma_supported() is deeply broken on almost all architectures - // possible with some EHCI controllers - if (dma_supported (&udev->dev, DMA_BIT_MASK(64))) - net->features |= NETIF_F_HIGHDMA; -#endif net->netdev_ops = &usbnet_netdev_ops; net->watchdog_timeo = TX_TIMEOUT_JIFFIES; -- cgit v1.2.3 From 39174291d8e8acfd1113214a943263aaa03c57c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fran=C3=A7ois=20romieu?= Date: Wed, 11 Nov 2015 23:35:18 +0100 Subject: r8169: fix kasan reported skb use-after-free. Signed-off-by: Francois Romieu Reported-by: Dave Jones Fixes: d7d2d89d4b0af ("r8169: Add software counter for multicast packages") Acked-by: Eric Dumazet Acked-by: Corinna Vinschen Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index b4f21232019a..79ef799f88ab 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -7429,15 +7429,15 @@ process_pkt: rtl8169_rx_vlan_tag(desc, skb); + if (skb->pkt_type == PACKET_MULTICAST) + dev->stats.multicast++; + napi_gro_receive(&tp->napi, skb); u64_stats_update_begin(&tp->rx_stats.syncp); tp->rx_stats.packets++; tp->rx_stats.bytes += pkt_size; u64_stats_update_end(&tp->rx_stats.syncp); - - if (skb->pkt_type == PACKET_MULTICAST) - dev->stats.multicast++; } release_descriptor: desc->opts2 = 0; -- cgit v1.2.3 From 49e4a2293035b420e807e739999d59c8ec1488e9 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 12 Nov 2015 22:03:40 +0100 Subject: stmmac: avoid ipq806x constant overflow warning Building dwmac-ipq806x on a 64-bit architecture produces a harmless warning from gcc: stmmac/dwmac-ipq806x.c: In function 'ipq806x_gmac_probe': include/linux/bitops.h:6:19: warning: overflow in implicit constant conversion [-Woverflow] val = QSGMII_PHY_CDR_EN | stmmac/dwmac-ipq806x.c:333:8: note: in expansion of macro 'QSGMII_PHY_CDR_EN' #define QSGMII_PHY_CDR_EN BIT(0) #define BIT(nr) (1UL << (nr)) This is a result of the type conversion rules in C, when we take the logical OR of multiple different types. In particular, we have and unsigned long QSGMII_PHY_CDR_EN == BIT(0) == (1ul << 0) == 0x0000000000000001ul and a signed int 0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET == 0xc0000000 which together gives a signed long value 0xffffffffc0000001l and when this is passed into a function that takes an unsigned int type, gcc warns about the signed overflow and the loss of the upper 32-bits that are all ones. This patch adds 'ul' type modifiers to the literal numbers passed in here, so now the expression remains an 'unsigned long' with the upper bits all zero, and that avoids the signed overflow and the warning. Signed-off-by: Arnd Bergmann Fixes: b1c17215d718 ("stmmac: add ipq806x glue layer") Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c index 9d89bdbf029f..82de68b1a452 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c @@ -337,11 +337,11 @@ static int ipq806x_gmac_probe(struct platform_device *pdev) QSGMII_PHY_RX_SIGNAL_DETECT_EN | QSGMII_PHY_TX_DRIVER_EN | QSGMII_PHY_QSGMII_EN | - 0x4 << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET | - 0x3 << QSGMII_PHY_RX_DC_BIAS_OFFSET | - 0x1 << QSGMII_PHY_RX_INPUT_EQU_OFFSET | - 0x2 << QSGMII_PHY_CDR_PI_SLEW_OFFSET | - 0xC << QSGMII_PHY_TX_DRV_AMP_OFFSET); + 0x4ul << QSGMII_PHY_PHASE_LOOP_GAIN_OFFSET | + 0x3ul << QSGMII_PHY_RX_DC_BIAS_OFFSET | + 0x1ul << QSGMII_PHY_RX_INPUT_EQU_OFFSET | + 0x2ul << QSGMII_PHY_CDR_PI_SLEW_OFFSET | + 0xCul << QSGMII_PHY_TX_DRV_AMP_OFFSET); } plat_dat->has_gmac = true; -- cgit v1.2.3 From 9001d94dfd558f175bede9f847276f691cd9c164 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 11 Nov 2015 15:22:40 +0000 Subject: fjes: fix inconsistent indenting minor change, indenting is one tab out. Signed-off-by: Colin Ian King Signed-off-by: Taku Izumi Signed-off-by: David S. Miller --- drivers/net/fjes/fjes_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c index bb8b5304d851..b103adb8d62e 100644 --- a/drivers/net/fjes/fjes_hw.c +++ b/drivers/net/fjes/fjes_hw.c @@ -599,7 +599,7 @@ int fjes_hw_unregister_buff_addr(struct fjes_hw *hw, int dest_epid) FJES_CMD_REQ_RES_CODE_BUSY) && (timeout > 0)) { msleep(200 + hw->my_epid * 20); - timeout -= (200 + hw->my_epid * 20); + timeout -= (200 + hw->my_epid * 20); res_buf->unshare_buffer.length = 0; res_buf->unshare_buffer.code = 0; -- cgit v1.2.3 From 5883d9c6d7e680bcdc7a8a9ed2509cd10dd98206 Mon Sep 17 00:00:00 2001 From: Pavel Fedin Date: Thu, 12 Nov 2015 14:55:18 +0300 Subject: net: thunder: Fix crash upon shutdown after failed probe If device probe fails, driver remains bound to the PCI device. However, driver data has been reset to NULL. This causes crash upon dereferencing it in nicvf_remove() Signed-off-by: Pavel Fedin Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/nicvf_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index a9377727c11c..372c39e5bcbd 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -1600,6 +1600,9 @@ static void nicvf_remove(struct pci_dev *pdev) static void nicvf_shutdown(struct pci_dev *pdev) { + if (!pci_get_drvdata(pdev)) + return; + nicvf_remove(pdev); } -- cgit v1.2.3 From ba6c4c094470dc83a7275000bac2fbd46bd5ab69 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Thu, 12 Nov 2015 19:35:25 +0200 Subject: net/mlx5e: Fix inline header size calculation mlx5e_get_inline_hdr_size didn't take into account the vlan insertion into the inline WQE segment. This could lead to max inline violation in cases where skb_headlen(skb) + VLAN_HLEN >= sq->max_inline. Fixes: 3ea4891db8d0 ("net/mlx5e: Fix LSO vlan insertion") Signed-off-by: Saeed Mahameed Signed-off-by: Achiad Shochat Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index cd8f85a251d7..f687ebf20d9c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -118,8 +118,15 @@ static inline u16 mlx5e_get_inline_hdr_size(struct mlx5e_sq *sq, */ #define MLX5E_MIN_INLINE ETH_HLEN - if (bf && (skb_headlen(skb) <= sq->max_inline)) - return skb_headlen(skb); + if (bf) { + u16 ihs = skb_headlen(skb); + + if (skb_vlan_tag_present(skb)) + ihs += VLAN_HLEN; + + if (ihs <= sq->max_inline) + return skb_headlen(skb); + } return MLX5E_MIN_INLINE; } -- cgit v1.2.3 From 66189961e986e53ae39822898fc2ce88f44c61bb Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Thu, 12 Nov 2015 19:35:26 +0200 Subject: net/mlx5e: Added self loopback prevention Prevent outgoing multicast frames from looping back to the RX queue. By introducing new HW capability self_lb_en_modifiable, which indicates the support to modify self_lb_en bit in modify_tir command. When this capability is set we can prevent TIRs from sending back loopback multicast traffic to their own RQs, by "refreshing TIRs" with modify_tir command, on every time new channels (SQs/RQs) are created at device open. This is needed since TIRs are static and only allocated once on driver load, and the loopback decision is under their responsibility. Fixes issues of the kind: "IPv6: eth2: IPv6 duplicate address fe80::e61d:2dff:fe5c:f2e9 detected!" The issue is seen since the IPv6 solicitations multicast messages are loopedback and the network stack thinks they are coming from another host. Fixes: 5c50368f3831 ("net/mlx5e: Light-weight netdev open/stop") Signed-off-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 48 +++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 5fc4d2d78cdf..df001754bcd1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1332,6 +1332,42 @@ static int mlx5e_modify_tir_lro(struct mlx5e_priv *priv, int tt) return err; } +static int mlx5e_refresh_tir_self_loopback_enable(struct mlx5_core_dev *mdev, + u32 tirn) +{ + void *in; + int inlen; + int err; + + inlen = MLX5_ST_SZ_BYTES(modify_tir_in); + in = mlx5_vzalloc(inlen); + if (!in) + return -ENOMEM; + + MLX5_SET(modify_tir_in, in, bitmask.self_lb_en, 1); + + err = mlx5_core_modify_tir(mdev, tirn, in, inlen); + + kvfree(in); + + return err; +} + +static int mlx5e_refresh_tirs_self_loopback_enable(struct mlx5e_priv *priv) +{ + int err; + int i; + + for (i = 0; i < MLX5E_NUM_TT; i++) { + err = mlx5e_refresh_tir_self_loopback_enable(priv->mdev, + priv->tirn[i]); + if (err) + return err; + } + + return 0; +} + static int mlx5e_set_dev_port_mtu(struct net_device *netdev) { struct mlx5e_priv *priv = netdev_priv(netdev); @@ -1376,6 +1412,13 @@ int mlx5e_open_locked(struct net_device *netdev) goto err_clear_state_opened_flag; } + err = mlx5e_refresh_tirs_self_loopback_enable(priv); + if (err) { + netdev_err(netdev, "%s: mlx5e_refresh_tirs_self_loopback_enable failed, %d\n", + __func__, err); + goto err_close_channels; + } + mlx5e_update_carrier(priv); mlx5e_redirect_rqts(priv); @@ -1383,6 +1426,8 @@ int mlx5e_open_locked(struct net_device *netdev) return 0; +err_close_channels: + mlx5e_close_channels(priv); err_clear_state_opened_flag: clear_bit(MLX5E_STATE_OPENED, &priv->state); return err; @@ -1909,6 +1954,9 @@ static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev) "Not creating net device, some required device capabilities are missing\n"); return -ENOTSUPP; } + if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable)) + mlx5_core_warn(mdev, "Self loop back prevention is not supported\n"); + return 0; } -- cgit v1.2.3 From 50a9eea694ab8e0779069e0a4e0b12e145521468 Mon Sep 17 00:00:00 2001 From: Doron Tsur Date: Thu, 12 Nov 2015 19:35:27 +0200 Subject: net/mlx5e: Max mtu comparison fix On change mtu the driver compares between hardware queried mtu and software requested mtu. We need to compare between software representation of the queried mtu and the requested mtu. Fixes: facc9699f0fe ('net/mlx5e: Fix HW MTU settings') Signed-off-by: Doron Tsur Signed-off-by: Saeed Mahameed Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index df001754bcd1..1e52db32c73d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1901,6 +1901,8 @@ static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu) mlx5_query_port_max_mtu(mdev, &max_mtu, 1); + max_mtu = MLX5E_HW2SW_MTU(max_mtu); + if (new_mtu > max_mtu) { netdev_err(netdev, "%s: Bad MTU (%d) > (%d) Max\n", -- cgit v1.2.3 From d4e28cbd24c8cb004960ddb8b22124953f6c220c Mon Sep 17 00:00:00 2001 From: Achiad Shochat Date: Thu, 12 Nov 2015 19:35:28 +0200 Subject: net/mlx5e: Use the right DMA free function on TX path On xmit path we use skb_frag_dma_map() which is using dma_map_page(), while upon completion we dma-unmap the skb fragments using dma_unmap_single() rather than dma_unmap_page(). To fix this, we now save the dma map type on xmit path and use this info to call the right dma unmap method upon TX completion. Signed-off-by: Achiad Shochat Signed-off-by: Saeed Mahameed Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 10 +++- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 65 +++++++++++++------------ 2 files changed, 43 insertions(+), 32 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index f2ae62dd8c09..22e72bf1ae48 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -334,9 +334,15 @@ struct mlx5e_tx_skb_cb { #define MLX5E_TX_SKB_CB(__skb) ((struct mlx5e_tx_skb_cb *)__skb->cb) +enum mlx5e_dma_map_type { + MLX5E_DMA_MAP_SINGLE, + MLX5E_DMA_MAP_PAGE +}; + struct mlx5e_sq_dma { - dma_addr_t addr; - u32 size; + dma_addr_t addr; + u32 size; + enum mlx5e_dma_map_type type; }; enum { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index f687ebf20d9c..1341b1d3c421 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -61,39 +61,47 @@ void mlx5e_send_nop(struct mlx5e_sq *sq, bool notify_hw) } } -static void mlx5e_dma_pop_last_pushed(struct mlx5e_sq *sq, dma_addr_t *addr, - u32 *size) +static inline void mlx5e_tx_dma_unmap(struct device *pdev, + struct mlx5e_sq_dma *dma) { - sq->dma_fifo_pc--; - *addr = sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].addr; - *size = sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].size; -} - -static void mlx5e_dma_unmap_wqe_err(struct mlx5e_sq *sq, struct sk_buff *skb) -{ - dma_addr_t addr; - u32 size; - int i; - - for (i = 0; i < MLX5E_TX_SKB_CB(skb)->num_dma; i++) { - mlx5e_dma_pop_last_pushed(sq, &addr, &size); - dma_unmap_single(sq->pdev, addr, size, DMA_TO_DEVICE); + switch (dma->type) { + case MLX5E_DMA_MAP_SINGLE: + dma_unmap_single(pdev, dma->addr, dma->size, DMA_TO_DEVICE); + break; + case MLX5E_DMA_MAP_PAGE: + dma_unmap_page(pdev, dma->addr, dma->size, DMA_TO_DEVICE); + break; + default: + WARN_ONCE(true, "mlx5e_tx_dma_unmap unknown DMA type!\n"); } } -static inline void mlx5e_dma_push(struct mlx5e_sq *sq, dma_addr_t addr, - u32 size) +static inline void mlx5e_dma_push(struct mlx5e_sq *sq, + dma_addr_t addr, + u32 size, + enum mlx5e_dma_map_type map_type) { sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].addr = addr; sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].size = size; + sq->dma_fifo[sq->dma_fifo_pc & sq->dma_fifo_mask].type = map_type; sq->dma_fifo_pc++; } -static inline void mlx5e_dma_get(struct mlx5e_sq *sq, u32 i, dma_addr_t *addr, - u32 *size) +static inline struct mlx5e_sq_dma *mlx5e_dma_get(struct mlx5e_sq *sq, u32 i) +{ + return &sq->dma_fifo[i & sq->dma_fifo_mask]; +} + +static void mlx5e_dma_unmap_wqe_err(struct mlx5e_sq *sq, struct sk_buff *skb) { - *addr = sq->dma_fifo[i & sq->dma_fifo_mask].addr; - *size = sq->dma_fifo[i & sq->dma_fifo_mask].size; + int i; + + for (i = 0; i < MLX5E_TX_SKB_CB(skb)->num_dma; i++) { + struct mlx5e_sq_dma *last_pushed_dma = + mlx5e_dma_get(sq, --sq->dma_fifo_pc); + + mlx5e_tx_dma_unmap(sq->pdev, last_pushed_dma); + } } u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb, @@ -225,7 +233,7 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb) dseg->lkey = sq->mkey_be; dseg->byte_count = cpu_to_be32(headlen); - mlx5e_dma_push(sq, dma_addr, headlen); + mlx5e_dma_push(sq, dma_addr, headlen, MLX5E_DMA_MAP_SINGLE); MLX5E_TX_SKB_CB(skb)->num_dma++; dseg++; @@ -244,7 +252,7 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb) dseg->lkey = sq->mkey_be; dseg->byte_count = cpu_to_be32(fsz); - mlx5e_dma_push(sq, dma_addr, fsz); + mlx5e_dma_push(sq, dma_addr, fsz, MLX5E_DMA_MAP_PAGE); MLX5E_TX_SKB_CB(skb)->num_dma++; dseg++; @@ -360,13 +368,10 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq) } for (j = 0; j < MLX5E_TX_SKB_CB(skb)->num_dma; j++) { - dma_addr_t addr; - u32 size; + struct mlx5e_sq_dma *dma = + mlx5e_dma_get(sq, dma_fifo_cc++); - mlx5e_dma_get(sq, dma_fifo_cc, &addr, &size); - dma_fifo_cc++; - dma_unmap_single(sq->pdev, addr, size, - DMA_TO_DEVICE); + mlx5e_tx_dma_unmap(sq->pdev, dma); } npkts++; -- cgit v1.2.3 From f5adbfee72282bb1f456d52b04adacd4fe6ac502 Mon Sep 17 00:00:00 2001 From: Eran Ben Elisha Date: Thu, 12 Nov 2015 19:35:29 +0200 Subject: net/mlx4_core: Fix sleeping while holding spinlock at rem_slave_counters When cleaning slave's counter resources, we hold a spinlock that protects the slave's counters list. As part of the clean, we call __mlx4_clear_if_stat which calls mlx4_alloc_cmd_mailbox which is a sleepable function. In order to fix this issue, hold the spinlock, and copy all counter indices into a temporary array, and release the spinlock. Afterwards, iterate over this array and free every counter. Repeat this scenario until the original list is empty (a new counter might have been added while releasing the counters from the temporary array). Fixes: b72ca7e96acf ("net/mlx4_core: Reset counters data when freed") Reported-by: Moni Shoua Tested-by: Moni Shoua Signed-off-by: Jack Morgenstein Signed-off-by: Eran Ben Elisha Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- .../net/ethernet/mellanox/mlx4/resource_tracker.c | 39 +++++++++++++++------- 1 file changed, 27 insertions(+), 12 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 9813d34f3e5b..6fec3e993d02 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -4952,26 +4952,41 @@ static void rem_slave_counters(struct mlx4_dev *dev, int slave) struct res_counter *counter; struct res_counter *tmp; int err; - int index; + int *counters_arr = NULL; + int i, j; err = move_all_busy(dev, slave, RES_COUNTER); if (err) mlx4_warn(dev, "rem_slave_counters: Could not move all counters - too busy for slave %d\n", slave); - spin_lock_irq(mlx4_tlock(dev)); - list_for_each_entry_safe(counter, tmp, counter_list, com.list) { - if (counter->com.owner == slave) { - index = counter->com.res_id; - rb_erase(&counter->com.node, - &tracker->res_tree[RES_COUNTER]); - list_del(&counter->com.list); - kfree(counter); - __mlx4_counter_free(dev, index); + counters_arr = kmalloc_array(dev->caps.max_counters, + sizeof(*counters_arr), GFP_KERNEL); + if (!counters_arr) + return; + + do { + i = 0; + j = 0; + spin_lock_irq(mlx4_tlock(dev)); + list_for_each_entry_safe(counter, tmp, counter_list, com.list) { + if (counter->com.owner == slave) { + counters_arr[i++] = counter->com.res_id; + rb_erase(&counter->com.node, + &tracker->res_tree[RES_COUNTER]); + list_del(&counter->com.list); + kfree(counter); + } + } + spin_unlock_irq(mlx4_tlock(dev)); + + while (j < i) { + __mlx4_counter_free(dev, counters_arr[j++]); mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0); } - } - spin_unlock_irq(mlx4_tlock(dev)); + } while (i); + + kfree(counters_arr); } static void rem_slave_xrcdns(struct mlx4_dev *dev, int slave) -- cgit v1.2.3 From d49c2197fd70c37d57982804465268440a33183a Mon Sep 17 00:00:00 2001 From: Noa Osherovich Date: Thu, 12 Nov 2015 19:35:30 +0200 Subject: net/mlx4_core: Avoid returning success in case of an error flow The err variable wasn't set with the correct error value in some cases. Fixes: 47605df95398 ('mlx4: Modify proxy/tunnel QP mechanism [..]') Signed-off-by: Noa Osherovich Signed-off-by: Or Gerlitz Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 85f1b1e7e505..31c491e02e69 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -892,9 +892,10 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) dev->caps.qp1_proxy[i - 1] = func_cap.qp1_proxy_qpn; dev->caps.port_mask[i] = dev->caps.port_type[i]; dev->caps.phys_port_id[i] = func_cap.phys_port_id; - if (mlx4_get_slave_pkey_gid_tbl_len(dev, i, - &dev->caps.gid_table_len[i], - &dev->caps.pkey_table_len[i])) + err = mlx4_get_slave_pkey_gid_tbl_len(dev, i, + &dev->caps.gid_table_len[i], + &dev->caps.pkey_table_len[i]); + if (err) goto err_mem; } @@ -906,6 +907,7 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) dev->caps.uar_page_size * dev->caps.num_uars, (unsigned long long) pci_resource_len(dev->persist->pdev, 2)); + err = -ENOMEM; goto err_mem; } -- cgit v1.2.3 From dc1e7eb846ae6677426c2dcdfe5ea323cf9036e9 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 10 Nov 2015 16:51:14 +0100 Subject: net: dsa: mv88e6060: remove poll_link callback As of mv88e6xxx remove the poll_link callback since the link state change polling is now handled by the phylib. Tested on a mv88e6060 B0 device with a TI DM816X SoC. Suggested-by: Andrew Lunn Acked-by: Andrew Lunn Signed-off-by: Neil Armstrong Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6060.c | 49 --------------------------------------------- 1 file changed, 49 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 9093577755f6..6885ef5678bc 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -225,54 +225,6 @@ mv88e6060_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) return reg_write(ds, addr, regnum, val); } -static void mv88e6060_poll_link(struct dsa_switch *ds) -{ - int i; - - for (i = 0; i < DSA_MAX_PORTS; i++) { - struct net_device *dev; - int uninitialized_var(port_status); - int link; - int speed; - int duplex; - int fc; - - dev = ds->ports[i]; - if (dev == NULL) - continue; - - link = 0; - if (dev->flags & IFF_UP) { - port_status = reg_read(ds, REG_PORT(i), 0x00); - if (port_status < 0) - continue; - - link = !!(port_status & 0x1000); - } - - if (!link) { - if (netif_carrier_ok(dev)) { - netdev_info(dev, "link down\n"); - netif_carrier_off(dev); - } - continue; - } - - speed = (port_status & 0x0100) ? 100 : 10; - duplex = (port_status & 0x0200) ? 1 : 0; - fc = ((port_status & 0xc000) == 0xc000) ? 1 : 0; - - if (!netif_carrier_ok(dev)) { - netdev_info(dev, - "link up, %d Mb/s, %s duplex, flow control %sabled\n", - speed, - duplex ? "full" : "half", - fc ? "en" : "dis"); - netif_carrier_on(dev); - } - } -} - static struct dsa_switch_driver mv88e6060_switch_driver = { .tag_protocol = DSA_TAG_PROTO_TRAILER, .probe = mv88e6060_probe, @@ -280,7 +232,6 @@ static struct dsa_switch_driver mv88e6060_switch_driver = { .set_addr = mv88e6060_set_addr, .phy_read = mv88e6060_phy_read, .phy_write = mv88e6060_phy_write, - .poll_link = mv88e6060_poll_link, }; static int __init mv88e6060_init(void) -- cgit v1.2.3 From c37909b4bb24320a59f697439bc77c700ca354fe Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 10 Nov 2015 16:51:19 +0100 Subject: net: dsa: mv88e6060: use the correct InitReady bit According to the mv88e6060 datasheet, the InitReady bit position is 11 and the polarity is inverted. Use the bit correctly to detect the end of initialization. Acked-by: Andrew Lunn Signed-off-by: Neil Armstrong Acked-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6060.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 6885ef5678bc..eff5e18079a7 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -102,7 +102,7 @@ static int mv88e6060_switch_reset(struct dsa_switch *ds) timeout = jiffies + 1 * HZ; while (time_before(jiffies, timeout)) { ret = REG_READ(REG_GLOBAL, 0x00); - if ((ret & 0x8000) == 0x0000) + if (ret & 0x800) break; usleep_range(1000, 2000); -- cgit v1.2.3 From b73c774e08cf1e8877b000585e8598ecee890c7f Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 10 Nov 2015 16:51:24 +0100 Subject: net: dsa: mv88e6060: use the correct MaxFrameSize bit According to the mv88e6060 datasheet, the MaxFrameSize bit position is 10 instead of 11 which is reserved. Use the bit correctly to setup max frame size to 1536. Acked-by: Andrew Lunn Signed-off-by: Neil Armstrong Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6060.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index eff5e18079a7..10647ade2f6d 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -119,7 +119,7 @@ static int mv88e6060_setup_global(struct dsa_switch *ds) * set the maximum frame size to 1536 bytes, and mask all * interrupt sources. */ - REG_WRITE(REG_GLOBAL, 0x04, 0x0800); + REG_WRITE(REG_GLOBAL, 0x04, 0x400); /* Enable automatic address learning, set the address * database size to 1024 entries, and set the default aging -- cgit v1.2.3 From 83ea0f4cb344089b6f240d3793d8c522a8501037 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 10 Nov 2015 16:51:32 +0100 Subject: net: dsa: mv88e6060: use the correct bit shift for mac0 According to the mv88e6060 datasheet, the first mac byte must be at position 9 instead of 8 since the bit 8 is used to select if the mac address must differ for each port for Pause frames. Use the correct shift and set the same mac address for all port. Acked-by: Andrew Lunn Signed-off-by: Neil Armstrong Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6060.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index 10647ade2f6d..cd08079e84ad 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -188,7 +188,8 @@ static int mv88e6060_setup(struct dsa_switch *ds) static int mv88e6060_set_addr(struct dsa_switch *ds, u8 *addr) { - REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]); + /* Use the same MAC Address as FD Pause frames for all ports */ + REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 9) | addr[1]); REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]); REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]); -- cgit v1.2.3 From f7e3931181595cd15e22e199d1bbabb0468d5a93 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 10 Nov 2015 16:51:42 +0100 Subject: net: dsa: mv88e6060: add register defines header file To align with the mv88e6xxx code, add a similar header file with all the register defines. The file is based on the mv88e6xxx header for coherency. Acked-by: Andrew Lunn Signed-off-by: Neil Armstrong Acked-by: Vivien Didelot Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6060.h | 111 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 drivers/net/dsa/mv88e6060.h (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6060.h b/drivers/net/dsa/mv88e6060.h new file mode 100644 index 000000000000..cc9b2ed4aff4 --- /dev/null +++ b/drivers/net/dsa/mv88e6060.h @@ -0,0 +1,111 @@ +/* + * drivers/net/dsa/mv88e6060.h - Marvell 88e6060 switch chip support + * Copyright (c) 2015 Neil Armstrong + * + * Based on mv88e6xxx.h + * Copyright (c) 2008 Marvell Semiconductor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __MV88E6060_H +#define __MV88E6060_H + +#define MV88E6060_PORTS 6 + +#define REG_PORT(p) (0x8 + (p)) +#define PORT_STATUS 0x00 +#define PORT_STATUS_PAUSE_EN BIT(15) +#define PORT_STATUS_MY_PAUSE BIT(14) +#define PORT_STATUS_FC (PORT_STATUS_MY_PAUSE | PORT_STATUS_PAUSE_EN) +#define PORT_STATUS_RESOLVED BIT(13) +#define PORT_STATUS_LINK BIT(12) +#define PORT_STATUS_PORTMODE BIT(11) +#define PORT_STATUS_PHYMODE BIT(10) +#define PORT_STATUS_DUPLEX BIT(9) +#define PORT_STATUS_SPEED BIT(8) +#define PORT_SWITCH_ID 0x03 +#define PORT_SWITCH_ID_6060 0x0600 +#define PORT_SWITCH_ID_6060_MASK 0xfff0 +#define PORT_SWITCH_ID_6060_R1 0x0601 +#define PORT_SWITCH_ID_6060_R2 0x0602 +#define PORT_CONTROL 0x04 +#define PORT_CONTROL_FORCE_FLOW_CTRL BIT(15) +#define PORT_CONTROL_TRAILER BIT(14) +#define PORT_CONTROL_HEADER BIT(11) +#define PORT_CONTROL_INGRESS_MODE BIT(8) +#define PORT_CONTROL_VLAN_TUNNEL BIT(7) +#define PORT_CONTROL_STATE_MASK 0x03 +#define PORT_CONTROL_STATE_DISABLED 0x00 +#define PORT_CONTROL_STATE_BLOCKING 0x01 +#define PORT_CONTROL_STATE_LEARNING 0x02 +#define PORT_CONTROL_STATE_FORWARDING 0x03 +#define PORT_VLAN_MAP 0x06 +#define PORT_VLAN_MAP_DBNUM_SHIFT 12 +#define PORT_VLAN_MAP_TABLE_MASK 0x1f +#define PORT_ASSOC_VECTOR 0x0b +#define PORT_ASSOC_VECTOR_MONITOR BIT(15) +#define PORT_ASSOC_VECTOR_PAV_MASK 0x1f +#define PORT_RX_CNTR 0x10 +#define PORT_TX_CNTR 0x11 + +#define REG_GLOBAL 0x0f +#define GLOBAL_STATUS 0x00 +#define GLOBAL_STATUS_SW_MODE_MASK (0x3 << 12) +#define GLOBAL_STATUS_SW_MODE_0 (0x0 << 12) +#define GLOBAL_STATUS_SW_MODE_1 (0x1 << 12) +#define GLOBAL_STATUS_SW_MODE_2 (0x2 << 12) +#define GLOBAL_STATUS_SW_MODE_3 (0x3 << 12) +#define GLOBAL_STATUS_INIT_READY BIT(11) +#define GLOBAL_STATUS_ATU_FULL BIT(3) +#define GLOBAL_STATUS_ATU_DONE BIT(2) +#define GLOBAL_STATUS_PHY_INT BIT(1) +#define GLOBAL_STATUS_EEINT BIT(0) +#define GLOBAL_MAC_01 0x01 +#define GLOBAL_MAC_01_DIFF_ADDR BIT(8) +#define GLOBAL_MAC_23 0x02 +#define GLOBAL_MAC_45 0x03 +#define GLOBAL_CONTROL 0x04 +#define GLOBAL_CONTROL_DISCARD_EXCESS BIT(13) +#define GLOBAL_CONTROL_MAX_FRAME_1536 BIT(10) +#define GLOBAL_CONTROL_RELOAD_EEPROM BIT(9) +#define GLOBAL_CONTROL_CTRMODE BIT(8) +#define GLOBAL_CONTROL_ATU_FULL_EN BIT(3) +#define GLOBAL_CONTROL_ATU_DONE_EN BIT(2) +#define GLOBAL_CONTROL_PHYINT_EN BIT(1) +#define GLOBAL_CONTROL_EEPROM_DONE_EN BIT(0) +#define GLOBAL_ATU_CONTROL 0x0a +#define GLOBAL_ATU_CONTROL_SWRESET BIT(15) +#define GLOBAL_ATU_CONTROL_LEARNDIS BIT(14) +#define GLOBAL_ATU_CONTROL_ATUSIZE_256 (0x0 << 12) +#define GLOBAL_ATU_CONTROL_ATUSIZE_512 (0x1 << 12) +#define GLOBAL_ATU_CONTROL_ATUSIZE_1024 (0x2 << 12) +#define GLOBAL_ATU_CONTROL_ATE_AGE_SHIFT 4 +#define GLOBAL_ATU_CONTROL_ATE_AGE_MASK (0xff << 4) +#define GLOBAL_ATU_CONTROL_ATE_AGE_5MIN (0x13 << 4) +#define GLOBAL_ATU_OP 0x0b +#define GLOBAL_ATU_OP_BUSY BIT(15) +#define GLOBAL_ATU_OP_NOP (0 << 12) +#define GLOBAL_ATU_OP_FLUSH_ALL ((1 << 12) | GLOBAL_ATU_OP_BUSY) +#define GLOBAL_ATU_OP_FLUSH_UNLOCKED ((2 << 12) | GLOBAL_ATU_OP_BUSY) +#define GLOBAL_ATU_OP_LOAD_DB ((3 << 12) | GLOBAL_ATU_OP_BUSY) +#define GLOBAL_ATU_OP_GET_NEXT_DB ((4 << 12) | GLOBAL_ATU_OP_BUSY) +#define GLOBAL_ATU_OP_FLUSH_DB ((5 << 12) | GLOBAL_ATU_OP_BUSY) +#define GLOBAL_ATU_OP_FLUSH_UNLOCKED_DB ((6 << 12) | GLOBAL_ATU_OP_BUSY) +#define GLOBAL_ATU_DATA 0x0c +#define GLOBAL_ATU_DATA_PORT_VECTOR_MASK 0x3f0 +#define GLOBAL_ATU_DATA_PORT_VECTOR_SHIFT 4 +#define GLOBAL_ATU_DATA_STATE_MASK 0x0f +#define GLOBAL_ATU_DATA_STATE_UNUSED 0x00 +#define GLOBAL_ATU_DATA_STATE_UC_STATIC 0x0e +#define GLOBAL_ATU_DATA_STATE_UC_LOCKED 0x0f +#define GLOBAL_ATU_DATA_STATE_MC_STATIC 0x07 +#define GLOBAL_ATU_DATA_STATE_MC_LOCKED 0x0e +#define GLOBAL_ATU_MAC_01 0x0d +#define GLOBAL_ATU_MAC_23 0x0e +#define GLOBAL_ATU_MAC_45 0x0f + +#endif -- cgit v1.2.3 From 6a4b2980d18164a09734c2069ddb4ad4a3b69c71 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 10 Nov 2015 16:51:36 +0100 Subject: net: dsa: mv88e6060: replace magic values with register defines To align with the mv88e6xxx code, use the register defines to access all the register addresses and bit fields. Acked-by: Andrew Lunn Signed-off-by: Neil Armstrong Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6060.c | 64 ++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 27 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index cd08079e84ad..0527f485c3dc 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -15,9 +15,7 @@ #include #include #include - -#define REG_PORT(p) (8 + (p)) -#define REG_GLOBAL 0x0f +#include "mv88e6060.h" static int reg_read(struct dsa_switch *ds, int addr, int reg) { @@ -67,13 +65,14 @@ static char *mv88e6060_probe(struct device *host_dev, int sw_addr) if (bus == NULL) return NULL; - ret = mdiobus_read(bus, sw_addr + REG_PORT(0), 0x03); + ret = mdiobus_read(bus, sw_addr + REG_PORT(0), PORT_SWITCH_ID); if (ret >= 0) { - if (ret == 0x0600) + if (ret == PORT_SWITCH_ID_6060) return "Marvell 88E6060 (A0)"; - if (ret == 0x0601 || ret == 0x0602) + if (ret == PORT_SWITCH_ID_6060_R1 || + ret == PORT_SWITCH_ID_6060_R2) return "Marvell 88E6060 (B0)"; - if ((ret & 0xfff0) == 0x0600) + if ((ret & PORT_SWITCH_ID_6060_MASK) == PORT_SWITCH_ID_6060) return "Marvell 88E6060"; } @@ -87,22 +86,26 @@ static int mv88e6060_switch_reset(struct dsa_switch *ds) unsigned long timeout; /* Set all ports to the disabled state. */ - for (i = 0; i < 6; i++) { - ret = REG_READ(REG_PORT(i), 0x04); - REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc); + for (i = 0; i < MV88E6060_PORTS; i++) { + ret = REG_READ(REG_PORT(i), PORT_CONTROL); + REG_WRITE(REG_PORT(i), PORT_CONTROL, + ret & ~PORT_CONTROL_STATE_MASK); } /* Wait for transmit queues to drain. */ usleep_range(2000, 4000); /* Reset the switch. */ - REG_WRITE(REG_GLOBAL, 0x0a, 0xa130); + REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL, + GLOBAL_ATU_CONTROL_SWRESET | + GLOBAL_ATU_CONTROL_ATUSIZE_1024 | + GLOBAL_ATU_CONTROL_ATE_AGE_5MIN); /* Wait up to one second for reset to complete. */ timeout = jiffies + 1 * HZ; while (time_before(jiffies, timeout)) { - ret = REG_READ(REG_GLOBAL, 0x00); - if (ret & 0x800) + ret = REG_READ(REG_GLOBAL, GLOBAL_STATUS); + if (ret & GLOBAL_STATUS_INIT_READY) break; usleep_range(1000, 2000); @@ -119,13 +122,15 @@ static int mv88e6060_setup_global(struct dsa_switch *ds) * set the maximum frame size to 1536 bytes, and mask all * interrupt sources. */ - REG_WRITE(REG_GLOBAL, 0x04, 0x400); + REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, GLOBAL_CONTROL_MAX_FRAME_1536); /* Enable automatic address learning, set the address * database size to 1024 entries, and set the default aging * time to 5 minutes. */ - REG_WRITE(REG_GLOBAL, 0x0a, 0x2130); + REG_WRITE(REG_GLOBAL, GLOBAL_ATU_CONTROL, + GLOBAL_ATU_CONTROL_ATUSIZE_1024 | + GLOBAL_ATU_CONTROL_ATE_AGE_5MIN); return 0; } @@ -139,25 +144,30 @@ static int mv88e6060_setup_port(struct dsa_switch *ds, int p) * state to Forwarding. Additionally, if this is the CPU * port, enable Ingress and Egress Trailer tagging mode. */ - REG_WRITE(addr, 0x04, dsa_is_cpu_port(ds, p) ? 0x4103 : 0x0003); + REG_WRITE(addr, PORT_CONTROL, + dsa_is_cpu_port(ds, p) ? + PORT_CONTROL_TRAILER | + PORT_CONTROL_INGRESS_MODE | + PORT_CONTROL_STATE_FORWARDING : + PORT_CONTROL_STATE_FORWARDING); /* Port based VLAN map: give each port its own address * database, allow the CPU port to talk to each of the 'real' * ports, and allow each of the 'real' ports to only talk to * the CPU port. */ - REG_WRITE(addr, 0x06, - ((p & 0xf) << 12) | - (dsa_is_cpu_port(ds, p) ? - ds->phys_port_mask : - (1 << ds->dst->cpu_port))); + REG_WRITE(addr, PORT_VLAN_MAP, + ((p & 0xf) << PORT_VLAN_MAP_DBNUM_SHIFT) | + (dsa_is_cpu_port(ds, p) ? + ds->phys_port_mask : + BIT(ds->dst->cpu_port))); /* Port Association Vector: when learning source addresses * of packets, add the address to the address database using * a port bitmap that has only the bit for this port set and * the other bits clear. */ - REG_WRITE(addr, 0x0b, 1 << p); + REG_WRITE(addr, PORT_ASSOC_VECTOR, BIT(p)); return 0; } @@ -177,7 +187,7 @@ static int mv88e6060_setup(struct dsa_switch *ds) if (ret < 0) return ret; - for (i = 0; i < 6; i++) { + for (i = 0; i < MV88E6060_PORTS; i++) { ret = mv88e6060_setup_port(ds, i); if (ret < 0) return ret; @@ -189,16 +199,16 @@ static int mv88e6060_setup(struct dsa_switch *ds) static int mv88e6060_set_addr(struct dsa_switch *ds, u8 *addr) { /* Use the same MAC Address as FD Pause frames for all ports */ - REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 9) | addr[1]); - REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]); - REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]); + REG_WRITE(REG_GLOBAL, GLOBAL_MAC_01, (addr[0] << 9) | addr[1]); + REG_WRITE(REG_GLOBAL, GLOBAL_MAC_23, (addr[2] << 8) | addr[3]); + REG_WRITE(REG_GLOBAL, GLOBAL_MAC_45, (addr[4] << 8) | addr[5]); return 0; } static int mv88e6060_port_to_phy_addr(int port) { - if (port >= 0 && port <= 5) + if (port >= 0 && port < MV88E6060_PORTS) return port; return -1; } -- cgit v1.2.3 From 0eae5982a3571dc15a9e7684c02e8774ba2fb1c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5ns=20Rullg=C3=A5rd?= Date: Thu, 12 Nov 2015 17:40:20 +0000 Subject: net: phy: at803x: support interrupt on 8030 and 8035 Commit 77a993942 "phy/at8031: enable at8031 to work on interrupt mode" added interrupt support for the 8031 PHY but left out the other two chips supported by this driver. This patch sets the .ack_interrupt and .config_intr functions for the 8030 and 8035 drivers as well. Signed-off-by: Mans Rullgard Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/at803x.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index fabf11d32d27..2d020a3ec0b5 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c @@ -308,6 +308,8 @@ static struct phy_driver at803x_driver[] = { .flags = PHY_HAS_INTERRUPT, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, + .ack_interrupt = at803x_ack_interrupt, + .config_intr = at803x_config_intr, .driver = { .owner = THIS_MODULE, }, @@ -327,6 +329,8 @@ static struct phy_driver at803x_driver[] = { .flags = PHY_HAS_INTERRUPT, .config_aneg = genphy_config_aneg, .read_status = genphy_read_status, + .ack_interrupt = at803x_ack_interrupt, + .config_intr = at803x_config_intr, .driver = { .owner = THIS_MODULE, }, -- cgit v1.2.3 From 7729b053814ac91af340f5055970afc87d7fee21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5ns=20Rullg=C3=A5rd?= Date: Thu, 12 Nov 2015 18:41:12 +0000 Subject: net: phy: vitesse: add support for VSC8601 This adds support for the Vitesse VSC8601 PHY. Generic functions are used for everything except interrupt handling. Signed-off-by: Mans Rullgard Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/vitesse.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 76cad712ddb2..dd295dbaa074 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -66,6 +66,7 @@ #define PHY_ID_VSC8244 0x000fc6c0 #define PHY_ID_VSC8514 0x00070670 #define PHY_ID_VSC8574 0x000704a0 +#define PHY_ID_VSC8601 0x00070420 #define PHY_ID_VSC8662 0x00070660 #define PHY_ID_VSC8221 0x000fc550 #define PHY_ID_VSC8211 0x000fc4b0 @@ -133,7 +134,8 @@ static int vsc82xx_config_intr(struct phy_device *phydev) (phydev->drv->phy_id == PHY_ID_VSC8234 || phydev->drv->phy_id == PHY_ID_VSC8244 || phydev->drv->phy_id == PHY_ID_VSC8514 || - phydev->drv->phy_id == PHY_ID_VSC8574) ? + phydev->drv->phy_id == PHY_ID_VSC8574 || + phydev->drv->phy_id == PHY_ID_VSC8601) ? MII_VSC8244_IMASK_MASK : MII_VSC8221_IMASK_MASK); else { @@ -271,6 +273,18 @@ static struct phy_driver vsc82xx_driver[] = { .ack_interrupt = &vsc824x_ack_interrupt, .config_intr = &vsc82xx_config_intr, .driver = { .owner = THIS_MODULE,}, +}, { + .phy_id = PHY_ID_VSC8601, + .name = "Vitesse VSC8601", + .phy_id_mask = 0x000ffff0, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &genphy_config_init, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &vsc824x_ack_interrupt, + .config_intr = &vsc82xx_config_intr, + .driver = { .owner = THIS_MODULE,}, }, { .phy_id = PHY_ID_VSC8662, .name = "Vitesse VSC8662", -- cgit v1.2.3 From cd998ecd2f031cfdb88436ea12f7c6d0b09c7a80 Mon Sep 17 00:00:00 2001 From: Pavel Fedin Date: Fri, 13 Nov 2015 09:46:59 +0300 Subject: net: smsc911x: Reset PHY during initialization On certain hardware after software reboot the chip may get stuck and fail to reinitialize during reset. This can be fixed by ensuring that PHY is reset too. Old PHY resetting method required operational MDIO interface, therefore the chip should have been already set up. In order to be able to function during probe, it is changed to use PMT_CTRL register. The problem could be observed on SMDK5410 board. Signed-off-by: Pavel Fedin Signed-off-by: David S. Miller --- drivers/net/ethernet/smsc/smsc911x.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index c860c9007e49..219a99b7a631 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -809,22 +809,17 @@ static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata) static int smsc911x_phy_reset(struct smsc911x_data *pdata) { - struct phy_device *phy_dev = pdata->phy_dev; unsigned int temp; unsigned int i = 100000; - BUG_ON(!phy_dev); - BUG_ON(!phy_dev->bus); - - SMSC_TRACE(pdata, hw, "Performing PHY BCR Reset"); - smsc911x_mii_write(phy_dev->bus, phy_dev->addr, MII_BMCR, BMCR_RESET); + temp = smsc911x_reg_read(pdata, PMT_CTRL); + smsc911x_reg_write(pdata, PMT_CTRL, temp | PMT_CTRL_PHY_RST_); do { msleep(1); - temp = smsc911x_mii_read(phy_dev->bus, phy_dev->addr, - MII_BMCR); - } while ((i--) && (temp & BMCR_RESET)); + temp = smsc911x_reg_read(pdata, PMT_CTRL); + } while ((i--) && (temp & PMT_CTRL_PHY_RST_)); - if (temp & BMCR_RESET) { + if (unlikely(temp & PMT_CTRL_PHY_RST_)) { SMSC_WARN(pdata, hw, "PHY reset failed to complete"); return -EIO; } @@ -2296,7 +2291,7 @@ static int smsc911x_init(struct net_device *dev) } /* Reset the LAN911x */ - if (smsc911x_soft_reset(pdata)) + if (smsc911x_phy_reset(pdata) || smsc911x_soft_reset(pdata)) return -ENODEV; dev->flags |= IFF_MULTICAST; -- cgit v1.2.3 From 2452cb0c6503f05ab371b26c3216c5fba54d4476 Mon Sep 17 00:00:00 2001 From: Masaru Nagai Date: Fri, 13 Nov 2015 19:24:49 +0900 Subject: ravb: Fix int mask value overwritten issue When RX/TX interrupt for Network Control queue and Best Effort queue is issued at the same time, the interrupt mask of Network Control queue will be reset when the mask of Best Effort queue is set. This patch fixes this problem. Signed-off-by: Masaru Nagai Signed-off-by: Yoshihiro Kaneko Acked-by: Geert Uytterhoeven Acked-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index aa7b2083cb53..7180e26f5c67 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -733,8 +733,10 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id) ((tis & tic) & BIT(q))) { if (napi_schedule_prep(&priv->napi[q])) { /* Mask RX and TX interrupts */ - ravb_write(ndev, ric0 & ~BIT(q), RIC0); - ravb_write(ndev, tic & ~BIT(q), TIC); + ric0 &= ~BIT(q); + tic &= ~BIT(q); + ravb_write(ndev, ric0, RIC0); + ravb_write(ndev, tic, TIC); __napi_schedule(&priv->napi[q]); } else { netdev_warn(ndev, -- cgit v1.2.3 From 4114ec905de2f02b91703c484bba9b62dc3bbb87 Mon Sep 17 00:00:00 2001 From: Ivan Vecera Date: Fri, 13 Nov 2015 11:36:57 +0100 Subject: be2net: remove unused local rsstable array Remove rsstable array and its initialization from be_set_rss_hash_opts(). The array became unused after "e255787 be2net: Support for configurable RSS hash key". The initial RSS table is now filled and stored for later usage during Rx queue creation. Signed-off-by: Ivan Vecera Acked-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_ethtool.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index f4cb8e425853..7246eac5148a 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -1062,9 +1062,7 @@ static int be_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, static int be_set_rss_hash_opts(struct be_adapter *adapter, struct ethtool_rxnfc *cmd) { - struct be_rx_obj *rxo; - int status = 0, i, j; - u8 rsstable[128]; + int status; u32 rss_flags = adapter->rss_info.rss_flags; if (cmd->data != L3_RSS_FLAGS && @@ -1113,17 +1111,7 @@ static int be_set_rss_hash_opts(struct be_adapter *adapter, } if (rss_flags == adapter->rss_info.rss_flags) - return status; - - if (be_multi_rxq(adapter)) { - for (j = 0; j < 128; j += adapter->num_rss_qs) { - for_all_rss_queues(adapter, rxo, i) { - if ((j + i) >= 128) - break; - rsstable[j + i] = rxo->rss_id; - } - } - } + return 0; status = be_cmd_rss_config(adapter, adapter->rss_info.rsstable, rss_flags, 128, adapter->rss_info.rss_hkey); -- cgit v1.2.3 From d5d309815bc377ec8235df380fda6d1befbc57cc Mon Sep 17 00:00:00 2001 From: Ivan Vecera Date: Fri, 13 Nov 2015 11:36:58 +0100 Subject: be2net: replace hardcoded values with existing define Signed-off-by: Ivan Vecera Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_ethtool.c | 3 ++- drivers/net/ethernet/emulex/benet/be_main.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 7246eac5148a..734f655c99c1 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -1114,7 +1114,8 @@ static int be_set_rss_hash_opts(struct be_adapter *adapter, return 0; status = be_cmd_rss_config(adapter, adapter->rss_info.rsstable, - rss_flags, 128, adapter->rss_info.rss_hkey); + rss_flags, RSS_INDIR_TABLE_LEN, + adapter->rss_info.rss_hkey); if (!status) adapter->rss_info.rss_flags = rss_flags; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index eb48a977f8da..b6ad02909d6b 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -3518,7 +3518,7 @@ static int be_rx_qs_create(struct be_adapter *adapter) netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN); rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags, - 128, rss_key); + RSS_INDIR_TABLE_LEN, rss_key); if (rc) { rss->rss_flags = RSS_ENABLE_NONE; return rc; -- cgit v1.2.3 From 0b88393cdf6b1322522849e61f7a3328f4fd3843 Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Fri, 13 Nov 2015 18:01:21 +0100 Subject: net: usb: cdc_ether: add Dell DW5580 as a mobile broadband adapter Since Dell DW5580 is a 3G modem, this patch adds the device as a mobile broadband adapter Signed-off-by: Daniele Palmas Signed-off-by: David S. Miller --- drivers/net/usb/cdc_ether.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index c78d3cb1b464..3da70bf9936a 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -695,6 +695,11 @@ static const struct usb_device_id products[] = { USB_VENDOR_AND_INTERFACE_INFO(0x1bc7, USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (kernel_ulong_t) &wwan_info, +}, { + /* Dell DW5580 modules */ + USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x81ba, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = (kernel_ulong_t)&wwan_info, }, { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), -- cgit v1.2.3 From d37d5ec861b0d937c0bdd70f0138e2750aacccdb Mon Sep 17 00:00:00 2001 From: Shrikrishna Khare Date: Fri, 13 Nov 2015 15:42:10 -0800 Subject: Driver: Vmxnet3: Fix use of mfTableLen for big endian architectures Signed-off-by: Shrikrishna Khare Reported-by: Masao Uebayashi Signed-off-by: Bhavesh Davda Signed-off-by: David S. Miller --- drivers/net/vmxnet3/vmxnet3_drv.c | 7 ++++--- drivers/net/vmxnet3/vmxnet3_int.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 46f4caddccbe..899ea4288197 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -2157,12 +2157,13 @@ vmxnet3_set_mc(struct net_device *netdev) if (!netdev_mc_empty(netdev)) { new_table = vmxnet3_copy_mc(netdev); if (new_table) { - rxConf->mfTableLen = cpu_to_le16( - netdev_mc_count(netdev) * ETH_ALEN); + size_t sz = netdev_mc_count(netdev) * ETH_ALEN; + + rxConf->mfTableLen = cpu_to_le16(sz); new_table_pa = dma_map_single( &adapter->pdev->dev, new_table, - rxConf->mfTableLen, + sz, PCI_DMA_TODEVICE); } diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index 3f859a55c035..4c58c83dc225 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -69,10 +69,10 @@ /* * Version numbers */ -#define VMXNET3_DRIVER_VERSION_STRING "1.4.3.0-k" +#define VMXNET3_DRIVER_VERSION_STRING "1.4.4.0-k" /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ -#define VMXNET3_DRIVER_VERSION_NUM 0x01040300 +#define VMXNET3_DRIVER_VERSION_NUM 0x01040400 #if defined(CONFIG_PCI_MSI) /* RSS only makes sense if MSI-X is supported. */ -- cgit v1.2.3 From 166e23623e7482070aa124ad805f600672377019 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 14 Nov 2015 11:06:53 +0100 Subject: net: cavium: liquidio: constify pci_error_handlers structures This pci_error_handlers structure is never modified, like all the other pci_error_handlers structures, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/liquidio/lio_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index f683d97d7614..b89504405b72 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -560,7 +560,7 @@ static int liquidio_resume(struct pci_dev *pdev) #endif /* For PCI-E Advanced Error Recovery (AER) Interface */ -static struct pci_error_handlers liquidio_err_handler = { +static const struct pci_error_handlers liquidio_err_handler = { .error_detected = liquidio_pcie_error_detected, .mmio_enabled = liquidio_pcie_mmio_enabled, .slot_reset = liquidio_pcie_slot_reset, -- cgit v1.2.3 From c300366b6b978fcb84f8eeb6205e5980cc0c40c3 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 14 Nov 2015 11:06:57 +0100 Subject: sfc: constify pci_error_handlers structures This pci_error_handlers structure is never modified, like all the other pci_error_handlers structures, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/efx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index d288f1c928de..a3c42a376741 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -3422,7 +3422,7 @@ out: * with our request for slot reset the mmio_enabled callback will never be * called, and the link_reset callback is not used by AER or EEH mechanisms. */ -static struct pci_error_handlers efx_err_handlers = { +static const struct pci_error_handlers efx_err_handlers = { .error_detected = efx_io_error_detected, .slot_reset = efx_io_slot_reset, .resume = efx_io_resume, -- cgit v1.2.3 From d60cf616ec39141b3483304fde69acf0dcec80eb Mon Sep 17 00:00:00 2001 From: Masaru Nagai Date: Sun, 15 Nov 2015 21:34:42 +0900 Subject: ravb: remove unhandle int cause This driver does not handle the AVB-DMAC Receive FIFO Warning interrupt now, so the interrupt should not be enabled. Signed-off-by: Masaru Nagai Signed-off-by: Yoshihiro Kaneko Signed-off-by: David S. Miller --- drivers/net/ethernet/renesas/ravb_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 7180e26f5c67..ee8d1ec61fab 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -408,8 +408,6 @@ static int ravb_dmac_init(struct net_device *ndev) /* Interrupt enable: */ /* Frame receive */ ravb_write(ndev, RIC0_FRE0 | RIC0_FRE1, RIC0); - /* Receive FIFO full warning */ - ravb_write(ndev, RIC1_RFWE, RIC1); /* Receive FIFO full error, descriptor empty */ ravb_write(ndev, RIC2_QFE0 | RIC2_QFE1 | RIC2_RFFE, RIC2); /* Frame transmitted, timestamp FIFO updated */ -- cgit v1.2.3 From ab6d7846cf80affc43b9d412fed5e25dfcf4f35d Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Sun, 15 Nov 2015 15:02:16 +0200 Subject: bnx2x: Fix VLANs null-pointer for 57710, 57711 Commit 05cc5a39ddb7 "bnx2x: add vlan filtering offload" introduced a regression in regard for vlans for 57710, 57711 adapters - Loading 8021q module on a machine with such an adapter would cause a null pointer dereference, as the driver mistakenly publishes it has capabilities for vlan CTAG filtering. Reported-by: Otto Sabart Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index f1d62d5dbaff..c9b036789184 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -13207,7 +13207,7 @@ static int bnx2x_init_dev(struct bnx2x *bp, struct pci_dev *pdev, /* VF with OLD Hypervisor or old PF do not support filtering */ if (IS_PF(bp)) { - if (CHIP_IS_E1x(bp)) + if (chip_is_e1x) bp->accept_any_vlan = true; else dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; -- cgit v1.2.3 From 7750130d93decff06120df0d8ea024ff8a038a21 Mon Sep 17 00:00:00 2001 From: Pavel Fedin Date: Mon, 16 Nov 2015 17:51:34 +0300 Subject: net: thunder: Check for driver data in nicvf_remove() In some cases the crash is caused by nicvf_remove() being called from outside. For example, if we try to feed the device to vfio after the probe has failed for some reason. So, move the check to better place. Signed-off-by: Pavel Fedin Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/nicvf_main.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index 372c39e5bcbd..7f709cbdcd87 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -1583,8 +1583,14 @@ err_disable_device: static void nicvf_remove(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); - struct nicvf *nic = netdev_priv(netdev); - struct net_device *pnetdev = nic->pnicvf->netdev; + struct nicvf *nic; + struct net_device *pnetdev; + + if (!netdev) + return; + + nic = netdev_priv(netdev); + pnetdev = nic->pnicvf->netdev; /* Check if this Qset is assigned to different VF. * If yes, clean primary and all secondary Qsets. @@ -1600,9 +1606,6 @@ static void nicvf_remove(struct pci_dev *pdev) static void nicvf_shutdown(struct pci_dev *pdev) { - if (!pci_get_drvdata(pdev)) - return; - nicvf_remove(pdev); } -- cgit v1.2.3 From c3f45d322cbd379c46466cc2ecab7e2d719b22ed Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 15 Nov 2015 22:36:11 +0100 Subject: dl2k: Add support for IP1000A-based cards Add support for IP1000A chips to dl2k driver. IP1000A chip looks like a TC9020 with integrated PHY. This allows IP1000A chips to work reliably because the ipg driver is buggy - it loses packets under load and then completely stops transmitting data. Tested with Asus NX1101 v2.0 at 10, 100 and 1000Mbps: vendor=0x13f0 device=0x1023 (rev 0x41) subsystem vendor=0x1043 device=0x8180 MAC address registers access needed to be changed from 8-bit to 16-bit because 8-bit does not work on IP1000A. 8-bit access is not even allowed in the TC9020 datasheet (although it worked). 16-bit access works on both. Tested that it does not break D-Link DGE-550T (DL-2000 chip, probably a rebranded TC9020): vendor=0x1186 device=0x4000 (rev 0x0c) subsystem vendor=0x1186 device=0x4000 Signed-off-by: Ondrej Zary Reviewed-by: Andy Shevchenko Signed-off-by: David S. Miller --- drivers/net/ethernet/dlink/Kconfig | 5 ++-- drivers/net/ethernet/dlink/dl2k.c | 55 +++++++++++++++++++++++++++++++++++--- drivers/net/ethernet/dlink/dl2k.h | 15 ++++++++++- 3 files changed, 69 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/dlink/Kconfig b/drivers/net/ethernet/dlink/Kconfig index f6e858d0b9d4..ebdc83247bb6 100644 --- a/drivers/net/ethernet/dlink/Kconfig +++ b/drivers/net/ethernet/dlink/Kconfig @@ -17,15 +17,16 @@ config NET_VENDOR_DLINK if NET_VENDOR_DLINK config DL2K - tristate "DL2000/TC902x-based Gigabit Ethernet support" + tristate "DL2000/TC902x/IP1000A-based Gigabit Ethernet support" depends on PCI select CRC32 ---help--- - This driver supports DL2000/TC902x-based Gigabit ethernet cards, + This driver supports DL2000/TC902x/IP1000A-based Gigabit ethernet cards, which includes D-Link DGE-550T Gigabit Ethernet Adapter. D-Link DL2000-based Gigabit Ethernet Adapter. Sundance/Tamarack TC902x Gigabit Ethernet Adapter. + ICPlus IP1000A-based cards To compile this driver as a module, choose M here: the module will be called dl2k. diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c index cf0a5fcdaaaf..ccca4799c27b 100644 --- a/drivers/net/ethernet/dlink/dl2k.c +++ b/drivers/net/ethernet/dlink/dl2k.c @@ -253,6 +253,19 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) if (err) goto err_out_unmap_rx; + if (np->chip_id == CHIP_IP1000A && + (np->pdev->revision == 0x40 || np->pdev->revision == 0x41)) { + /* PHY magic taken from ipg driver, undocumented registers */ + mii_write(dev, np->phy_addr, 31, 0x0001); + mii_write(dev, np->phy_addr, 27, 0x01e0); + mii_write(dev, np->phy_addr, 31, 0x0002); + mii_write(dev, np->phy_addr, 27, 0xeb8e); + mii_write(dev, np->phy_addr, 31, 0x0000); + mii_write(dev, np->phy_addr, 30, 0x005e); + /* advertise 1000BASE-T half & full duplex, prefer MASTER */ + mii_write(dev, np->phy_addr, MII_CTRL1000, 0x0700); + } + /* Fiber device? */ np->phy_media = (dr16(ASICCtrl) & PhyMedia) ? 1 : 0; np->link_status = 0; @@ -361,6 +374,11 @@ parse_eeprom (struct net_device *dev) for (i = 0; i < 6; i++) dev->dev_addr[i] = psrom->mac_addr[i]; + if (np->chip_id == CHIP_IP1000A) { + np->led_mode = psrom->led_mode; + return 0; + } + if (np->pdev->vendor != PCI_VENDOR_ID_DLINK) { return 0; } @@ -406,6 +424,28 @@ parse_eeprom (struct net_device *dev) return 0; } +static void rio_set_led_mode(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->ioaddr; + u32 mode; + + if (np->chip_id != CHIP_IP1000A) + return; + + mode = dr32(ASICCtrl); + mode &= ~(IPG_AC_LED_MODE_BIT_1 | IPG_AC_LED_MODE | IPG_AC_LED_SPEED); + + if (np->led_mode & 0x01) + mode |= IPG_AC_LED_MODE; + if (np->led_mode & 0x02) + mode |= IPG_AC_LED_MODE_BIT_1; + if (np->led_mode & 0x08) + mode |= IPG_AC_LED_SPEED; + + dw32(ASICCtrl, mode); +} + static int rio_open (struct net_device *dev) { @@ -424,6 +464,8 @@ rio_open (struct net_device *dev) GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset); mdelay(10); + rio_set_led_mode(dev); + /* DebugCtrl bit 4, 5, 9 must set */ dw32(DebugCtrl, dr32(DebugCtrl) | 0x0230); @@ -433,9 +475,13 @@ rio_open (struct net_device *dev) alloc_list (dev); - /* Get station address */ - for (i = 0; i < 6; i++) - dw8(StationAddr0 + i, dev->dev_addr[i]); + /* Set station address */ + /* 16 or 32-bit access is required by TC9020 datasheet but 8-bit works + * too. However, it doesn't work on IP1000A so we use 16-bit access. + */ + for (i = 0; i < 3; i++) + dw16(StationAddr0 + 2 * i, + cpu_to_le16(((u16 *)dev->dev_addr)[i])); set_multicast (dev); if (np->coalesce) { @@ -780,6 +826,7 @@ tx_error (struct net_device *dev, int tx_status) break; mdelay (1); } + rio_set_led_mode(dev); rio_free_tx (dev, 1); /* Reset TFDListPtr */ dw32(TFDListPtr0, np->tx_ring_dma + @@ -799,6 +846,7 @@ tx_error (struct net_device *dev, int tx_status) break; mdelay (1); } + rio_set_led_mode(dev); /* Let TxStartThresh stay default value */ } /* Maximum Collisions */ @@ -965,6 +1013,7 @@ rio_error (struct net_device *dev, int int_status) dev->name, int_status); dw16(ASICCtrl + 2, GlobalReset | HostReset); mdelay (500); + rio_set_led_mode(dev); } } diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h index 23c07b007069..8f4f61262d5c 100644 --- a/drivers/net/ethernet/dlink/dl2k.h +++ b/drivers/net/ethernet/dlink/dl2k.h @@ -211,6 +211,10 @@ enum ASICCtrl_HiWord_bits { ResetBusy = 0x0400, }; +#define IPG_AC_LED_MODE BIT(14) +#define IPG_AC_LED_SPEED BIT(27) +#define IPG_AC_LED_MODE_BIT_1 BIT(29) + /* Transmit Frame Control bits */ enum TFC_bits { DwordAlign = 0x00000000, @@ -332,7 +336,10 @@ typedef struct t_SROM { u16 asic_ctrl; /* 0x02 */ u16 sub_vendor_id; /* 0x04 */ u16 sub_system_id; /* 0x06 */ - u16 reserved1[12]; /* 0x08-0x1f */ + u16 pci_base_1; /* 0x08 (IP1000A only) */ + u16 pci_base_2; /* 0x0a (IP1000A only) */ + u16 led_mode; /* 0x0c (IP1000A only) */ + u16 reserved1[9]; /* 0x0e-0x1f */ u8 mac_addr[6]; /* 0x20-0x25 */ u8 reserved2[10]; /* 0x26-0x2f */ u8 sib[204]; /* 0x30-0xfb */ @@ -397,6 +404,7 @@ struct netdev_private { u16 advertising; /* NWay media advertisement */ u16 negotiate; /* Negotiated media */ int phy_addr; /* PHY addresses. */ + u16 led_mode; /* LED mode read from EEPROM (IP1000A only) */ }; /* The station address location in the EEPROM. */ @@ -407,10 +415,15 @@ struct netdev_private { class_mask of the class are honored during the comparison. driver_data Data private to the driver. */ +#define CHIP_IP1000A 1 static const struct pci_device_id rio_pci_tbl[] = { {0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, }, {0x13f0, 0x1021, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VDEVICE(SUNDANCE, 0x1023), CHIP_IP1000A }, + { PCI_VDEVICE(SUNDANCE, 0x2021), CHIP_IP1000A }, + { PCI_VDEVICE(DLINK, 0x9021), CHIP_IP1000A }, + { PCI_VDEVICE(DLINK, 0x4020), CHIP_IP1000A }, { } }; MODULE_DEVICE_TABLE (pci, rio_pci_tbl); -- cgit v1.2.3 From f1a454a37618b819f2528ccd234f77a02b3a6016 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 15 Nov 2015 22:36:12 +0100 Subject: ipg: Remove ipg driver Now that IP1000A chips are supported by dl2k driver, the buggy ipg driver can be removed. Signed-off-by: Ondrej Zary Signed-off-by: David S. Miller --- drivers/net/ethernet/Kconfig | 1 - drivers/net/ethernet/Makefile | 1 - drivers/net/ethernet/icplus/Kconfig | 13 - drivers/net/ethernet/icplus/Makefile | 5 - drivers/net/ethernet/icplus/ipg.c | 2300 ---------------------------------- drivers/net/ethernet/icplus/ipg.h | 748 ----------- 6 files changed, 3068 deletions(-) delete mode 100644 drivers/net/ethernet/icplus/Kconfig delete mode 100644 drivers/net/ethernet/icplus/Makefile delete mode 100644 drivers/net/ethernet/icplus/ipg.c delete mode 100644 drivers/net/ethernet/icplus/ipg.h (limited to 'drivers/net') diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index 05aa7597dab9..955d06b9cdba 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -78,7 +78,6 @@ source "drivers/net/ethernet/ibm/Kconfig" source "drivers/net/ethernet/intel/Kconfig" source "drivers/net/ethernet/i825xx/Kconfig" source "drivers/net/ethernet/xscale/Kconfig" -source "drivers/net/ethernet/icplus/Kconfig" config JME tristate "JMicron(R) PCI-Express Gigabit Ethernet support" diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile index ddfc808110a1..4a2ee98738f0 100644 --- a/drivers/net/ethernet/Makefile +++ b/drivers/net/ethernet/Makefile @@ -41,7 +41,6 @@ obj-$(CONFIG_NET_VENDOR_IBM) += ibm/ obj-$(CONFIG_NET_VENDOR_INTEL) += intel/ obj-$(CONFIG_NET_VENDOR_I825XX) += i825xx/ obj-$(CONFIG_NET_VENDOR_XSCALE) += xscale/ -obj-$(CONFIG_IP1000) += icplus/ obj-$(CONFIG_JME) += jme.o obj-$(CONFIG_KORINA) += korina.o obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o diff --git a/drivers/net/ethernet/icplus/Kconfig b/drivers/net/ethernet/icplus/Kconfig deleted file mode 100644 index 14a66e9d2e26..000000000000 --- a/drivers/net/ethernet/icplus/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -# -# IC Plus device configuration -# - -config IP1000 - tristate "IP1000 Gigabit Ethernet support" - depends on PCI - select MII - ---help--- - This driver supports IP1000 gigabit Ethernet cards. - - To compile this driver as a module, choose M here: the module - will be called ipg. This is recommended. diff --git a/drivers/net/ethernet/icplus/Makefile b/drivers/net/ethernet/icplus/Makefile deleted file mode 100644 index 5bc87c1f36aa..000000000000 --- a/drivers/net/ethernet/icplus/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the IC Plus device drivers -# - -obj-$(CONFIG_IP1000) += ipg.o diff --git a/drivers/net/ethernet/icplus/ipg.c b/drivers/net/ethernet/icplus/ipg.c deleted file mode 100644 index c3b6af83f070..000000000000 --- a/drivers/net/ethernet/icplus/ipg.c +++ /dev/null @@ -1,2300 +0,0 @@ -/* - * ipg.c: Device Driver for the IP1000 Gigabit Ethernet Adapter - * - * Copyright (C) 2003, 2007 IC Plus Corp - * - * Original Author: - * - * Craig Rich - * Sundance Technology, Inc. - * www.sundanceti.com - * craig_rich@sundanceti.com - * - * Current Maintainer: - * - * Sorbica Shieh. - * http://www.icplus.com.tw - * sorbica@icplus.com.tw - * - * Jesse Huang - * http://www.icplus.com.tw - * jesse@icplus.com.tw - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include - -#include - -#define IPG_RX_RING_BYTES (sizeof(struct ipg_rx) * IPG_RFDLIST_LENGTH) -#define IPG_TX_RING_BYTES (sizeof(struct ipg_tx) * IPG_TFDLIST_LENGTH) -#define IPG_RESET_MASK \ - (IPG_AC_GLOBAL_RESET | IPG_AC_RX_RESET | IPG_AC_TX_RESET | \ - IPG_AC_DMA | IPG_AC_FIFO | IPG_AC_NETWORK | IPG_AC_HOST | \ - IPG_AC_AUTO_INIT) - -#define ipg_w32(val32, reg) iowrite32((val32), ioaddr + (reg)) -#define ipg_w16(val16, reg) iowrite16((val16), ioaddr + (reg)) -#define ipg_w8(val8, reg) iowrite8((val8), ioaddr + (reg)) - -#define ipg_r32(reg) ioread32(ioaddr + (reg)) -#define ipg_r16(reg) ioread16(ioaddr + (reg)) -#define ipg_r8(reg) ioread8(ioaddr + (reg)) - -enum { - netdev_io_size = 128 -}; - -#include "ipg.h" -#define DRV_NAME "ipg" - -MODULE_AUTHOR("IC Plus Corp. 2003"); -MODULE_DESCRIPTION("IC Plus IP1000 Gigabit Ethernet Adapter Linux Driver"); -MODULE_LICENSE("GPL"); - -/* - * Defaults - */ -#define IPG_MAX_RXFRAME_SIZE 0x0600 -#define IPG_RXFRAG_SIZE 0x0600 -#define IPG_RXSUPPORT_SIZE 0x0600 -#define IPG_IS_JUMBO false - -/* - * Variable record -- index by leading revision/length - * Revision/Length(=N*4), Address1, Data1, Address2, Data2,...,AddressN,DataN - */ -static const unsigned short DefaultPhyParam[] = { - /* 11/12/03 IP1000A v1-3 rev=0x40 */ - /*-------------------------------------------------------------------------- - (0x4000|(15*4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 22, 0x85bd, 24, 0xfff2, - 27, 0x0c10, 28, 0x0c10, 29, 0x2c10, 31, 0x0003, 23, 0x92f6, - 31, 0x0000, 23, 0x003d, 30, 0x00de, 20, 0x20e7, 9, 0x0700, - --------------------------------------------------------------------------*/ - /* 12/17/03 IP1000A v1-4 rev=0x40 */ - (0x4000 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, - 0x0000, - 30, 0x005e, 9, 0x0700, - /* 01/09/04 IP1000A v1-5 rev=0x41 */ - (0x4100 | (07 * 4)), 31, 0x0001, 27, 0x01e0, 31, 0x0002, 27, 0xeb8e, 31, - 0x0000, - 30, 0x005e, 9, 0x0700, - 0x0000 -}; - -static const char * const ipg_brand_name[] = { - "IC PLUS IP1000 1000/100/10 based NIC", - "Sundance Technology ST2021 based NIC", - "Tamarack Microelectronics TC9020/9021 based NIC", - "D-Link NIC IP1000A" -}; - -static const struct pci_device_id ipg_pci_tbl[] = { - { PCI_VDEVICE(SUNDANCE, 0x1023), 0 }, - { PCI_VDEVICE(SUNDANCE, 0x2021), 1 }, - { PCI_VDEVICE(DLINK, 0x9021), 2 }, - { PCI_VDEVICE(DLINK, 0x4020), 3 }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, ipg_pci_tbl); - -static inline void __iomem *ipg_ioaddr(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - return sp->ioaddr; -} - -#ifdef IPG_DEBUG -static void ipg_dump_rfdlist(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - unsigned int i; - u32 offset; - - IPG_DEBUG_MSG("_dump_rfdlist\n"); - - netdev_info(dev, "rx_current = %02x\n", sp->rx_current); - netdev_info(dev, "rx_dirty = %02x\n", sp->rx_dirty); - netdev_info(dev, "RFDList start address = %016lx\n", - (unsigned long)sp->rxd_map); - netdev_info(dev, "RFDListPtr register = %08x%08x\n", - ipg_r32(IPG_RFDLISTPTR1), ipg_r32(IPG_RFDLISTPTR0)); - - for (i = 0; i < IPG_RFDLIST_LENGTH; i++) { - offset = (u32) &sp->rxd[i].next_desc - (u32) sp->rxd; - netdev_info(dev, "%02x %04x RFDNextPtr = %016lx\n", - i, offset, (unsigned long)sp->rxd[i].next_desc); - offset = (u32) &sp->rxd[i].rfs - (u32) sp->rxd; - netdev_info(dev, "%02x %04x RFS = %016lx\n", - i, offset, (unsigned long)sp->rxd[i].rfs); - offset = (u32) &sp->rxd[i].frag_info - (u32) sp->rxd; - netdev_info(dev, "%02x %04x frag_info = %016lx\n", - i, offset, (unsigned long)sp->rxd[i].frag_info); - } -} - -static void ipg_dump_tfdlist(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - unsigned int i; - u32 offset; - - IPG_DEBUG_MSG("_dump_tfdlist\n"); - - netdev_info(dev, "tx_current = %02x\n", sp->tx_current); - netdev_info(dev, "tx_dirty = %02x\n", sp->tx_dirty); - netdev_info(dev, "TFDList start address = %016lx\n", - (unsigned long) sp->txd_map); - netdev_info(dev, "TFDListPtr register = %08x%08x\n", - ipg_r32(IPG_TFDLISTPTR1), ipg_r32(IPG_TFDLISTPTR0)); - - for (i = 0; i < IPG_TFDLIST_LENGTH; i++) { - offset = (u32) &sp->txd[i].next_desc - (u32) sp->txd; - netdev_info(dev, "%02x %04x TFDNextPtr = %016lx\n", - i, offset, (unsigned long)sp->txd[i].next_desc); - - offset = (u32) &sp->txd[i].tfc - (u32) sp->txd; - netdev_info(dev, "%02x %04x TFC = %016lx\n", - i, offset, (unsigned long) sp->txd[i].tfc); - offset = (u32) &sp->txd[i].frag_info - (u32) sp->txd; - netdev_info(dev, "%02x %04x frag_info = %016lx\n", - i, offset, (unsigned long) sp->txd[i].frag_info); - } -} -#endif - -static void ipg_write_phy_ctl(void __iomem *ioaddr, u8 data) -{ - ipg_w8(IPG_PC_RSVD_MASK & data, PHY_CTRL); - ndelay(IPG_PC_PHYCTRLWAIT_NS); -} - -static void ipg_drive_phy_ctl_low_high(void __iomem *ioaddr, u8 data) -{ - ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | data); - ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | data); -} - -static void send_three_state(void __iomem *ioaddr, u8 phyctrlpolarity) -{ - phyctrlpolarity |= (IPG_PC_MGMTDATA & 0) | IPG_PC_MGMTDIR; - - ipg_drive_phy_ctl_low_high(ioaddr, phyctrlpolarity); -} - -static void send_end(void __iomem *ioaddr, u8 phyctrlpolarity) -{ - ipg_w8((IPG_PC_MGMTCLK_LO | (IPG_PC_MGMTDATA & 0) | IPG_PC_MGMTDIR | - phyctrlpolarity) & IPG_PC_RSVD_MASK, PHY_CTRL); -} - -static u16 read_phy_bit(void __iomem *ioaddr, u8 phyctrlpolarity) -{ - u16 bit_data; - - ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | phyctrlpolarity); - - bit_data = ((ipg_r8(PHY_CTRL) & IPG_PC_MGMTDATA) >> 1) & 1; - - ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | phyctrlpolarity); - - return bit_data; -} - -/* - * Read a register from the Physical Layer device located - * on the IPG NIC, using the IPG PHYCTRL register. - */ -static int mdio_read(struct net_device *dev, int phy_id, int phy_reg) -{ - void __iomem *ioaddr = ipg_ioaddr(dev); - /* - * The GMII mangement frame structure for a read is as follows: - * - * |Preamble|st|op|phyad|regad|ta| data |idle| - * |< 32 1s>|01|10|AAAAA|RRRRR|z0|DDDDDDDDDDDDDDDD|z | - * - * <32 1s> = 32 consecutive logic 1 values - * A = bit of Physical Layer device address (MSB first) - * R = bit of register address (MSB first) - * z = High impedance state - * D = bit of read data (MSB first) - * - * Transmission order is 'Preamble' field first, bits transmitted - * left to right (first to last). - */ - struct { - u32 field; - unsigned int len; - } p[] = { - { GMII_PREAMBLE, 32 }, /* Preamble */ - { GMII_ST, 2 }, /* ST */ - { GMII_READ, 2 }, /* OP */ - { phy_id, 5 }, /* PHYAD */ - { phy_reg, 5 }, /* REGAD */ - { 0x0000, 2 }, /* TA */ - { 0x0000, 16 }, /* DATA */ - { 0x0000, 1 } /* IDLE */ - }; - unsigned int i, j; - u8 polarity, data; - - polarity = ipg_r8(PHY_CTRL); - polarity &= (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY); - - /* Create the Preamble, ST, OP, PHYAD, and REGAD field. */ - for (j = 0; j < 5; j++) { - for (i = 0; i < p[j].len; i++) { - /* For each variable length field, the MSB must be - * transmitted first. Rotate through the field bits, - * starting with the MSB, and move each bit into the - * the 1st (2^1) bit position (this is the bit position - * corresponding to the MgmtData bit of the PhyCtrl - * register for the IPG). - * - * Example: ST = 01; - * - * First write a '0' to bit 1 of the PhyCtrl - * register, then write a '1' to bit 1 of the - * PhyCtrl register. - * - * To do this, right shift the MSB of ST by the value: - * [field length - 1 - #ST bits already written] - * then left shift this result by 1. - */ - data = (p[j].field >> (p[j].len - 1 - i)) << 1; - data &= IPG_PC_MGMTDATA; - data |= polarity | IPG_PC_MGMTDIR; - - ipg_drive_phy_ctl_low_high(ioaddr, data); - } - } - - send_three_state(ioaddr, polarity); - - read_phy_bit(ioaddr, polarity); - - /* - * For a read cycle, the bits for the next two fields (TA and - * DATA) are driven by the PHY (the IPG reads these bits). - */ - for (i = 0; i < p[6].len; i++) { - p[6].field |= - (read_phy_bit(ioaddr, polarity) << (p[6].len - 1 - i)); - } - - send_three_state(ioaddr, polarity); - send_three_state(ioaddr, polarity); - send_three_state(ioaddr, polarity); - send_end(ioaddr, polarity); - - /* Return the value of the DATA field. */ - return p[6].field; -} - -/* - * Write to a register from the Physical Layer device located - * on the IPG NIC, using the IPG PHYCTRL register. - */ -static void mdio_write(struct net_device *dev, int phy_id, int phy_reg, int val) -{ - void __iomem *ioaddr = ipg_ioaddr(dev); - /* - * The GMII mangement frame structure for a read is as follows: - * - * |Preamble|st|op|phyad|regad|ta| data |idle| - * |< 32 1s>|01|10|AAAAA|RRRRR|z0|DDDDDDDDDDDDDDDD|z | - * - * <32 1s> = 32 consecutive logic 1 values - * A = bit of Physical Layer device address (MSB first) - * R = bit of register address (MSB first) - * z = High impedance state - * D = bit of write data (MSB first) - * - * Transmission order is 'Preamble' field first, bits transmitted - * left to right (first to last). - */ - struct { - u32 field; - unsigned int len; - } p[] = { - { GMII_PREAMBLE, 32 }, /* Preamble */ - { GMII_ST, 2 }, /* ST */ - { GMII_WRITE, 2 }, /* OP */ - { phy_id, 5 }, /* PHYAD */ - { phy_reg, 5 }, /* REGAD */ - { 0x0002, 2 }, /* TA */ - { val & 0xffff, 16 }, /* DATA */ - { 0x0000, 1 } /* IDLE */ - }; - unsigned int i, j; - u8 polarity, data; - - polarity = ipg_r8(PHY_CTRL); - polarity &= (IPG_PC_DUPLEX_POLARITY | IPG_PC_LINK_POLARITY); - - /* Create the Preamble, ST, OP, PHYAD, and REGAD field. */ - for (j = 0; j < 7; j++) { - for (i = 0; i < p[j].len; i++) { - /* For each variable length field, the MSB must be - * transmitted first. Rotate through the field bits, - * starting with the MSB, and move each bit into the - * the 1st (2^1) bit position (this is the bit position - * corresponding to the MgmtData bit of the PhyCtrl - * register for the IPG). - * - * Example: ST = 01; - * - * First write a '0' to bit 1 of the PhyCtrl - * register, then write a '1' to bit 1 of the - * PhyCtrl register. - * - * To do this, right shift the MSB of ST by the value: - * [field length - 1 - #ST bits already written] - * then left shift this result by 1. - */ - data = (p[j].field >> (p[j].len - 1 - i)) << 1; - data &= IPG_PC_MGMTDATA; - data |= polarity | IPG_PC_MGMTDIR; - - ipg_drive_phy_ctl_low_high(ioaddr, data); - } - } - - /* The last cycle is a tri-state, so read from the PHY. */ - ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_LO | polarity); - ipg_r8(PHY_CTRL); - ipg_write_phy_ctl(ioaddr, IPG_PC_MGMTCLK_HI | polarity); -} - -static void ipg_set_led_mode(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - u32 mode; - - mode = ipg_r32(ASIC_CTRL); - mode &= ~(IPG_AC_LED_MODE_BIT_1 | IPG_AC_LED_MODE | IPG_AC_LED_SPEED); - - if ((sp->led_mode & 0x03) > 1) - mode |= IPG_AC_LED_MODE_BIT_1; /* Write Asic Control Bit 29 */ - - if ((sp->led_mode & 0x01) == 1) - mode |= IPG_AC_LED_MODE; /* Write Asic Control Bit 14 */ - - if ((sp->led_mode & 0x08) == 8) - mode |= IPG_AC_LED_SPEED; /* Write Asic Control Bit 27 */ - - ipg_w32(mode, ASIC_CTRL); -} - -static void ipg_set_phy_set(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - int physet; - - physet = ipg_r8(PHY_SET); - physet &= ~(IPG_PS_MEM_LENB9B | IPG_PS_MEM_LEN9 | IPG_PS_NON_COMPDET); - physet |= ((sp->led_mode & 0x70) >> 4); - ipg_w8(physet, PHY_SET); -} - -static int ipg_reset(struct net_device *dev, u32 resetflags) -{ - /* Assert functional resets via the IPG AsicCtrl - * register as specified by the 'resetflags' input - * parameter. - */ - void __iomem *ioaddr = ipg_ioaddr(dev); - unsigned int timeout_count = 0; - - IPG_DEBUG_MSG("_reset\n"); - - ipg_w32(ipg_r32(ASIC_CTRL) | resetflags, ASIC_CTRL); - - /* Delay added to account for problem with 10Mbps reset. */ - mdelay(IPG_AC_RESETWAIT); - - while (IPG_AC_RESET_BUSY & ipg_r32(ASIC_CTRL)) { - mdelay(IPG_AC_RESETWAIT); - if (++timeout_count > IPG_AC_RESET_TIMEOUT) - return -ETIME; - } - /* Set LED Mode in Asic Control */ - ipg_set_led_mode(dev); - - /* Set PHYSet Register Value */ - ipg_set_phy_set(dev); - return 0; -} - -/* Find the GMII PHY address. */ -static int ipg_find_phyaddr(struct net_device *dev) -{ - unsigned int phyaddr, i; - - for (i = 0; i < 32; i++) { - u32 status; - - /* Search for the correct PHY address among 32 possible. */ - phyaddr = (IPG_NIC_PHY_ADDRESS + i) % 32; - - /* 10/22/03 Grace change verify from GMII_PHY_STATUS to - GMII_PHY_ID1 - */ - - status = mdio_read(dev, phyaddr, MII_BMSR); - - if ((status != 0xFFFF) && (status != 0)) - return phyaddr; - } - - return 0x1f; -} - -/* - * Configure IPG based on result of IEEE 802.3 PHY - * auto-negotiation. - */ -static int ipg_config_autoneg(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - unsigned int txflowcontrol; - unsigned int rxflowcontrol; - unsigned int fullduplex; - u32 mac_ctrl_val; - u32 asicctrl; - u8 phyctrl; - const char *speed; - const char *duplex; - const char *tx_desc; - const char *rx_desc; - - IPG_DEBUG_MSG("_config_autoneg\n"); - - asicctrl = ipg_r32(ASIC_CTRL); - phyctrl = ipg_r8(PHY_CTRL); - mac_ctrl_val = ipg_r32(MAC_CTRL); - - /* Set flags for use in resolving auto-negotiation, assuming - * non-1000Mbps, half duplex, no flow control. - */ - fullduplex = 0; - txflowcontrol = 0; - rxflowcontrol = 0; - - /* To accommodate a problem in 10Mbps operation, - * set a global flag if PHY running in 10Mbps mode. - */ - sp->tenmbpsmode = 0; - - /* Determine actual speed of operation. */ - switch (phyctrl & IPG_PC_LINK_SPEED) { - case IPG_PC_LINK_SPEED_10MBPS: - speed = "10Mbps"; - sp->tenmbpsmode = 1; - break; - case IPG_PC_LINK_SPEED_100MBPS: - speed = "100Mbps"; - break; - case IPG_PC_LINK_SPEED_1000MBPS: - speed = "1000Mbps"; - break; - default: - speed = "undefined!"; - return 0; - } - - netdev_info(dev, "Link speed = %s\n", speed); - if (sp->tenmbpsmode == 1) - netdev_info(dev, "10Mbps operational mode enabled\n"); - - if (phyctrl & IPG_PC_DUPLEX_STATUS) { - fullduplex = 1; - txflowcontrol = 1; - rxflowcontrol = 1; - } - - /* Configure full duplex, and flow control. */ - if (fullduplex == 1) { - - /* Configure IPG for full duplex operation. */ - - duplex = "full"; - - mac_ctrl_val |= IPG_MC_DUPLEX_SELECT_FD; - - if (txflowcontrol == 1) { - tx_desc = ""; - mac_ctrl_val |= IPG_MC_TX_FLOW_CONTROL_ENABLE; - } else { - tx_desc = "no "; - mac_ctrl_val &= ~IPG_MC_TX_FLOW_CONTROL_ENABLE; - } - - if (rxflowcontrol == 1) { - rx_desc = ""; - mac_ctrl_val |= IPG_MC_RX_FLOW_CONTROL_ENABLE; - } else { - rx_desc = "no "; - mac_ctrl_val &= ~IPG_MC_RX_FLOW_CONTROL_ENABLE; - } - } else { - duplex = "half"; - tx_desc = "no "; - rx_desc = "no "; - mac_ctrl_val &= (~IPG_MC_DUPLEX_SELECT_FD & - ~IPG_MC_TX_FLOW_CONTROL_ENABLE & - ~IPG_MC_RX_FLOW_CONTROL_ENABLE); - } - - netdev_info(dev, "setting %s duplex, %sTX, %sRX flow control\n", - duplex, tx_desc, rx_desc); - ipg_w32(mac_ctrl_val, MAC_CTRL); - - return 0; -} - -/* Determine and configure multicast operation and set - * receive mode for IPG. - */ -static void ipg_nic_set_multicast_list(struct net_device *dev) -{ - void __iomem *ioaddr = ipg_ioaddr(dev); - struct netdev_hw_addr *ha; - unsigned int hashindex; - u32 hashtable[2]; - u8 receivemode; - - IPG_DEBUG_MSG("_nic_set_multicast_list\n"); - - receivemode = IPG_RM_RECEIVEUNICAST | IPG_RM_RECEIVEBROADCAST; - - if (dev->flags & IFF_PROMISC) { - /* NIC to be configured in promiscuous mode. */ - receivemode = IPG_RM_RECEIVEALLFRAMES; - } else if ((dev->flags & IFF_ALLMULTI) || - ((dev->flags & IFF_MULTICAST) && - (netdev_mc_count(dev) > IPG_MULTICAST_HASHTABLE_SIZE))) { - /* NIC to be configured to receive all multicast - * frames. */ - receivemode |= IPG_RM_RECEIVEMULTICAST; - } else if ((dev->flags & IFF_MULTICAST) && !netdev_mc_empty(dev)) { - /* NIC to be configured to receive selected - * multicast addresses. */ - receivemode |= IPG_RM_RECEIVEMULTICASTHASH; - } - - /* Calculate the bits to set for the 64 bit, IPG HASHTABLE. - * The IPG applies a cyclic-redundancy-check (the same CRC - * used to calculate the frame data FCS) to the destination - * address all incoming multicast frames whose destination - * address has the multicast bit set. The least significant - * 6 bits of the CRC result are used as an addressing index - * into the hash table. If the value of the bit addressed by - * this index is a 1, the frame is passed to the host system. - */ - - /* Clear hashtable. */ - hashtable[0] = 0x00000000; - hashtable[1] = 0x00000000; - - /* Cycle through all multicast addresses to filter. */ - netdev_for_each_mc_addr(ha, dev) { - /* Calculate CRC result for each multicast address. */ - hashindex = crc32_le(0xffffffff, ha->addr, - ETH_ALEN); - - /* Use only the least significant 6 bits. */ - hashindex = hashindex & 0x3F; - - /* Within "hashtable", set bit number "hashindex" - * to a logic 1. - */ - set_bit(hashindex, (void *)hashtable); - } - - /* Write the value of the hashtable, to the 4, 16 bit - * HASHTABLE IPG registers. - */ - ipg_w32(hashtable[0], HASHTABLE_0); - ipg_w32(hashtable[1], HASHTABLE_1); - - ipg_w8(IPG_RM_RSVD_MASK & receivemode, RECEIVE_MODE); - - IPG_DEBUG_MSG("ReceiveMode = %x\n", ipg_r8(RECEIVE_MODE)); -} - -static int ipg_io_config(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = ipg_ioaddr(dev); - u32 origmacctrl; - u32 restoremacctrl; - - IPG_DEBUG_MSG("_io_config\n"); - - origmacctrl = ipg_r32(MAC_CTRL); - - restoremacctrl = origmacctrl | IPG_MC_STATISTICS_ENABLE; - - /* Based on compilation option, determine if FCS is to be - * stripped on receive frames by IPG. - */ - if (!IPG_STRIP_FCS_ON_RX) - restoremacctrl |= IPG_MC_RCV_FCS; - - /* Determine if transmitter and/or receiver are - * enabled so we may restore MACCTRL correctly. - */ - if (origmacctrl & IPG_MC_TX_ENABLED) - restoremacctrl |= IPG_MC_TX_ENABLE; - - if (origmacctrl & IPG_MC_RX_ENABLED) - restoremacctrl |= IPG_MC_RX_ENABLE; - - /* Transmitter and receiver must be disabled before setting - * IFSSelect. - */ - ipg_w32((origmacctrl & (IPG_MC_RX_DISABLE | IPG_MC_TX_DISABLE)) & - IPG_MC_RSVD_MASK, MAC_CTRL); - - /* Now that transmitter and receiver are disabled, write - * to IFSSelect. - */ - ipg_w32((origmacctrl & IPG_MC_IFS_96BIT) & IPG_MC_RSVD_MASK, MAC_CTRL); - - /* Set RECEIVEMODE register. */ - ipg_nic_set_multicast_list(dev); - - ipg_w16(sp->max_rxframe_size, MAX_FRAME_SIZE); - - ipg_w8(IPG_RXDMAPOLLPERIOD_VALUE, RX_DMA_POLL_PERIOD); - ipg_w8(IPG_RXDMAURGENTTHRESH_VALUE, RX_DMA_URGENT_THRESH); - ipg_w8(IPG_RXDMABURSTTHRESH_VALUE, RX_DMA_BURST_THRESH); - ipg_w8(IPG_TXDMAPOLLPERIOD_VALUE, TX_DMA_POLL_PERIOD); - ipg_w8(IPG_TXDMAURGENTTHRESH_VALUE, TX_DMA_URGENT_THRESH); - ipg_w8(IPG_TXDMABURSTTHRESH_VALUE, TX_DMA_BURST_THRESH); - ipg_w16((IPG_IE_HOST_ERROR | IPG_IE_TX_DMA_COMPLETE | - IPG_IE_TX_COMPLETE | IPG_IE_INT_REQUESTED | - IPG_IE_UPDATE_STATS | IPG_IE_LINK_EVENT | - IPG_IE_RX_DMA_COMPLETE | IPG_IE_RX_DMA_PRIORITY), INT_ENABLE); - ipg_w16(IPG_FLOWONTHRESH_VALUE, FLOW_ON_THRESH); - ipg_w16(IPG_FLOWOFFTHRESH_VALUE, FLOW_OFF_THRESH); - - /* IPG multi-frag frame bug workaround. - * Per silicon revision B3 eratta. - */ - ipg_w16(ipg_r16(DEBUG_CTRL) | 0x0200, DEBUG_CTRL); - - /* IPG TX poll now bug workaround. - * Per silicon revision B3 eratta. - */ - ipg_w16(ipg_r16(DEBUG_CTRL) | 0x0010, DEBUG_CTRL); - - /* IPG RX poll now bug workaround. - * Per silicon revision B3 eratta. - */ - ipg_w16(ipg_r16(DEBUG_CTRL) | 0x0020, DEBUG_CTRL); - - /* Now restore MACCTRL to original setting. */ - ipg_w32(IPG_MC_RSVD_MASK & restoremacctrl, MAC_CTRL); - - /* Disable unused RMON statistics. */ - ipg_w32(IPG_RZ_ALL, RMON_STATISTICS_MASK); - - /* Disable unused MIB statistics. */ - ipg_w32(IPG_SM_MACCONTROLFRAMESXMTD | IPG_SM_MACCONTROLFRAMESRCVD | - IPG_SM_BCSTOCTETXMTOK_BCSTFRAMESXMTDOK | IPG_SM_TXJUMBOFRAMES | - IPG_SM_MCSTOCTETXMTOK_MCSTFRAMESXMTDOK | IPG_SM_RXJUMBOFRAMES | - IPG_SM_BCSTOCTETRCVDOK_BCSTFRAMESRCVDOK | - IPG_SM_UDPCHECKSUMERRORS | IPG_SM_TCPCHECKSUMERRORS | - IPG_SM_IPCHECKSUMERRORS, STATISTICS_MASK); - - return 0; -} - -/* - * Create a receive buffer within system memory and update - * NIC private structure appropriately. - */ -static int ipg_get_rxbuff(struct net_device *dev, int entry) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - struct ipg_rx *rxfd = sp->rxd + entry; - struct sk_buff *skb; - u64 rxfragsize; - - IPG_DEBUG_MSG("_get_rxbuff\n"); - - skb = netdev_alloc_skb_ip_align(dev, sp->rxsupport_size); - if (!skb) { - sp->rx_buff[entry] = NULL; - return -ENOMEM; - } - - /* Save the address of the sk_buff structure. */ - sp->rx_buff[entry] = skb; - - rxfd->frag_info = cpu_to_le64(pci_map_single(sp->pdev, skb->data, - sp->rx_buf_sz, PCI_DMA_FROMDEVICE)); - - /* Set the RFD fragment length. */ - rxfragsize = sp->rxfrag_size; - rxfd->frag_info |= cpu_to_le64((rxfragsize << 48) & IPG_RFI_FRAGLEN); - - return 0; -} - -static int init_rfdlist(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - unsigned int i; - - IPG_DEBUG_MSG("_init_rfdlist\n"); - - for (i = 0; i < IPG_RFDLIST_LENGTH; i++) { - struct ipg_rx *rxfd = sp->rxd + i; - - if (sp->rx_buff[i]) { - pci_unmap_single(sp->pdev, - le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN, - sp->rx_buf_sz, PCI_DMA_FROMDEVICE); - dev_kfree_skb_irq(sp->rx_buff[i]); - sp->rx_buff[i] = NULL; - } - - /* Clear out the RFS field. */ - rxfd->rfs = 0x0000000000000000; - - if (ipg_get_rxbuff(dev, i) < 0) { - /* - * A receive buffer was not ready, break the - * RFD list here. - */ - IPG_DEBUG_MSG("Cannot allocate Rx buffer\n"); - - /* Just in case we cannot allocate a single RFD. - * Should not occur. - */ - if (i == 0) { - netdev_err(dev, "No memory available for RFD list\n"); - return -ENOMEM; - } - } - - rxfd->next_desc = cpu_to_le64(sp->rxd_map + - sizeof(struct ipg_rx)*(i + 1)); - } - sp->rxd[i - 1].next_desc = cpu_to_le64(sp->rxd_map); - - sp->rx_current = 0; - sp->rx_dirty = 0; - - /* Write the location of the RFDList to the IPG. */ - ipg_w32((u32) sp->rxd_map, RFD_LIST_PTR_0); - ipg_w32(0x00000000, RFD_LIST_PTR_1); - - return 0; -} - -static void init_tfdlist(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - unsigned int i; - - IPG_DEBUG_MSG("_init_tfdlist\n"); - - for (i = 0; i < IPG_TFDLIST_LENGTH; i++) { - struct ipg_tx *txfd = sp->txd + i; - - txfd->tfc = cpu_to_le64(IPG_TFC_TFDDONE); - - if (sp->tx_buff[i]) { - dev_kfree_skb_irq(sp->tx_buff[i]); - sp->tx_buff[i] = NULL; - } - - txfd->next_desc = cpu_to_le64(sp->txd_map + - sizeof(struct ipg_tx)*(i + 1)); - } - sp->txd[i - 1].next_desc = cpu_to_le64(sp->txd_map); - - sp->tx_current = 0; - sp->tx_dirty = 0; - - /* Write the location of the TFDList to the IPG. */ - IPG_DDEBUG_MSG("Starting TFDListPtr = %08x\n", - (u32) sp->txd_map); - ipg_w32((u32) sp->txd_map, TFD_LIST_PTR_0); - ipg_w32(0x00000000, TFD_LIST_PTR_1); - - sp->reset_current_tfd = 1; -} - -/* - * Free all transmit buffers which have already been transferred - * via DMA to the IPG. - */ -static void ipg_nic_txfree(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - unsigned int released, pending, dirty; - - IPG_DEBUG_MSG("_nic_txfree\n"); - - pending = sp->tx_current - sp->tx_dirty; - dirty = sp->tx_dirty % IPG_TFDLIST_LENGTH; - - for (released = 0; released < pending; released++) { - struct sk_buff *skb = sp->tx_buff[dirty]; - struct ipg_tx *txfd = sp->txd + dirty; - - IPG_DEBUG_MSG("TFC = %016lx\n", (unsigned long) txfd->tfc); - - /* Look at each TFD's TFC field beginning - * at the last freed TFD up to the current TFD. - * If the TFDDone bit is set, free the associated - * buffer. - */ - if (!(txfd->tfc & cpu_to_le64(IPG_TFC_TFDDONE))) - break; - - /* Free the transmit buffer. */ - if (skb) { - pci_unmap_single(sp->pdev, - le64_to_cpu(txfd->frag_info) & ~IPG_TFI_FRAGLEN, - skb->len, PCI_DMA_TODEVICE); - - dev_kfree_skb_irq(skb); - - sp->tx_buff[dirty] = NULL; - } - dirty = (dirty + 1) % IPG_TFDLIST_LENGTH; - } - - sp->tx_dirty += released; - - if (netif_queue_stopped(dev) && - (sp->tx_current != (sp->tx_dirty + IPG_TFDLIST_LENGTH))) { - netif_wake_queue(dev); - } -} - -static void ipg_tx_timeout(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - - ipg_reset(dev, IPG_AC_TX_RESET | IPG_AC_DMA | IPG_AC_NETWORK | - IPG_AC_FIFO); - - spin_lock_irq(&sp->lock); - - /* Re-configure after DMA reset. */ - if (ipg_io_config(dev) < 0) - netdev_info(dev, "Error during re-configuration\n"); - - init_tfdlist(dev); - - spin_unlock_irq(&sp->lock); - - ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) & IPG_MC_RSVD_MASK, - MAC_CTRL); -} - -/* - * For TxComplete interrupts, free all transmit - * buffers which have already been transferred via DMA - * to the IPG. - */ -static void ipg_nic_txcleanup(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - unsigned int i; - - IPG_DEBUG_MSG("_nic_txcleanup\n"); - - for (i = 0; i < IPG_TFDLIST_LENGTH; i++) { - /* Reading the TXSTATUS register clears the - * TX_COMPLETE interrupt. - */ - u32 txstatusdword = ipg_r32(TX_STATUS); - - IPG_DEBUG_MSG("TxStatus = %08x\n", txstatusdword); - - /* Check for Transmit errors. Error bits only valid if - * TX_COMPLETE bit in the TXSTATUS register is a 1. - */ - if (!(txstatusdword & IPG_TS_TX_COMPLETE)) - break; - - /* If in 10Mbps mode, indicate transmit is ready. */ - if (sp->tenmbpsmode) { - netif_wake_queue(dev); - } - - /* Transmit error, increment stat counters. */ - if (txstatusdword & IPG_TS_TX_ERROR) { - IPG_DEBUG_MSG("Transmit error\n"); - sp->stats.tx_errors++; - } - - /* Late collision, re-enable transmitter. */ - if (txstatusdword & IPG_TS_LATE_COLLISION) { - IPG_DEBUG_MSG("Late collision on transmit\n"); - ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) & - IPG_MC_RSVD_MASK, MAC_CTRL); - } - - /* Maximum collisions, re-enable transmitter. */ - if (txstatusdword & IPG_TS_TX_MAX_COLL) { - IPG_DEBUG_MSG("Maximum collisions on transmit\n"); - ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) & - IPG_MC_RSVD_MASK, MAC_CTRL); - } - - /* Transmit underrun, reset and re-enable - * transmitter. - */ - if (txstatusdword & IPG_TS_TX_UNDERRUN) { - IPG_DEBUG_MSG("Transmitter underrun\n"); - sp->stats.tx_fifo_errors++; - ipg_reset(dev, IPG_AC_TX_RESET | IPG_AC_DMA | - IPG_AC_NETWORK | IPG_AC_FIFO); - - /* Re-configure after DMA reset. */ - if (ipg_io_config(dev) < 0) { - netdev_info(dev, "Error during re-configuration\n"); - } - init_tfdlist(dev); - - ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_TX_ENABLE) & - IPG_MC_RSVD_MASK, MAC_CTRL); - } - } - - ipg_nic_txfree(dev); -} - -/* Provides statistical information about the IPG NIC. */ -static struct net_device_stats *ipg_nic_get_stats(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - u16 temp1; - u16 temp2; - - IPG_DEBUG_MSG("_nic_get_stats\n"); - - /* Check to see if the NIC has been initialized via nic_open, - * before trying to read statistic registers. - */ - if (!netif_running(dev)) - return &sp->stats; - - sp->stats.rx_packets += ipg_r32(IPG_FRAMESRCVDOK); - sp->stats.tx_packets += ipg_r32(IPG_FRAMESXMTDOK); - sp->stats.rx_bytes += ipg_r32(IPG_OCTETRCVOK); - sp->stats.tx_bytes += ipg_r32(IPG_OCTETXMTOK); - temp1 = ipg_r16(IPG_FRAMESLOSTRXERRORS); - sp->stats.rx_errors += temp1; - sp->stats.rx_missed_errors += temp1; - temp1 = ipg_r32(IPG_SINGLECOLFRAMES) + ipg_r32(IPG_MULTICOLFRAMES) + - ipg_r32(IPG_LATECOLLISIONS); - temp2 = ipg_r16(IPG_CARRIERSENSEERRORS); - sp->stats.collisions += temp1; - sp->stats.tx_dropped += ipg_r16(IPG_FRAMESABORTXSCOLLS); - sp->stats.tx_errors += ipg_r16(IPG_FRAMESWEXDEFERRAL) + - ipg_r32(IPG_FRAMESWDEFERREDXMT) + temp1 + temp2; - sp->stats.multicast += ipg_r32(IPG_MCSTOCTETRCVDOK); - - /* detailed tx_errors */ - sp->stats.tx_carrier_errors += temp2; - - /* detailed rx_errors */ - sp->stats.rx_length_errors += ipg_r16(IPG_INRANGELENGTHERRORS) + - ipg_r16(IPG_FRAMETOOLONGERRORS); - sp->stats.rx_crc_errors += ipg_r16(IPG_FRAMECHECKSEQERRORS); - - /* Unutilized IPG statistic registers. */ - ipg_r32(IPG_MCSTFRAMESRCVDOK); - - return &sp->stats; -} - -/* Restore used receive buffers. */ -static int ipg_nic_rxrestore(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - const unsigned int curr = sp->rx_current; - unsigned int dirty = sp->rx_dirty; - - IPG_DEBUG_MSG("_nic_rxrestore\n"); - - for (dirty = sp->rx_dirty; curr - dirty > 0; dirty++) { - unsigned int entry = dirty % IPG_RFDLIST_LENGTH; - - /* rx_copybreak may poke hole here and there. */ - if (sp->rx_buff[entry]) - continue; - - /* Generate a new receive buffer to replace the - * current buffer (which will be released by the - * Linux system). - */ - if (ipg_get_rxbuff(dev, entry) < 0) { - IPG_DEBUG_MSG("Cannot allocate new Rx buffer\n"); - - break; - } - - /* Reset the RFS field. */ - sp->rxd[entry].rfs = 0x0000000000000000; - } - sp->rx_dirty = dirty; - - return 0; -} - -/* use jumboindex and jumbosize to control jumbo frame status - * initial status is jumboindex=-1 and jumbosize=0 - * 1. jumboindex = -1 and jumbosize=0 : previous jumbo frame has been done. - * 2. jumboindex != -1 and jumbosize != 0 : jumbo frame is not over size and receiving - * 3. jumboindex = -1 and jumbosize != 0 : jumbo frame is over size, already dump - * previous receiving and need to continue dumping the current one - */ -enum { - NORMAL_PACKET, - ERROR_PACKET -}; - -enum { - FRAME_NO_START_NO_END = 0, - FRAME_WITH_START = 1, - FRAME_WITH_END = 10, - FRAME_WITH_START_WITH_END = 11 -}; - -static void ipg_nic_rx_free_skb(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - unsigned int entry = sp->rx_current % IPG_RFDLIST_LENGTH; - - if (sp->rx_buff[entry]) { - struct ipg_rx *rxfd = sp->rxd + entry; - - pci_unmap_single(sp->pdev, - le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN, - sp->rx_buf_sz, PCI_DMA_FROMDEVICE); - dev_kfree_skb_irq(sp->rx_buff[entry]); - sp->rx_buff[entry] = NULL; - } -} - -static int ipg_nic_rx_check_frame_type(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - struct ipg_rx *rxfd = sp->rxd + (sp->rx_current % IPG_RFDLIST_LENGTH); - int type = FRAME_NO_START_NO_END; - - if (le64_to_cpu(rxfd->rfs) & IPG_RFS_FRAMESTART) - type += FRAME_WITH_START; - if (le64_to_cpu(rxfd->rfs) & IPG_RFS_FRAMEEND) - type += FRAME_WITH_END; - return type; -} - -static int ipg_nic_rx_check_error(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - unsigned int entry = sp->rx_current % IPG_RFDLIST_LENGTH; - struct ipg_rx *rxfd = sp->rxd + entry; - - if (IPG_DROP_ON_RX_ETH_ERRORS && (le64_to_cpu(rxfd->rfs) & - (IPG_RFS_RXFIFOOVERRUN | IPG_RFS_RXRUNTFRAME | - IPG_RFS_RXALIGNMENTERROR | IPG_RFS_RXFCSERROR | - IPG_RFS_RXOVERSIZEDFRAME | IPG_RFS_RXLENGTHERROR))) { - IPG_DEBUG_MSG("Rx error, RFS = %016lx\n", - (unsigned long) rxfd->rfs); - - /* Increment general receive error statistic. */ - sp->stats.rx_errors++; - - /* Increment detailed receive error statistics. */ - if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) { - IPG_DEBUG_MSG("RX FIFO overrun occurred\n"); - - sp->stats.rx_fifo_errors++; - } - - if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) { - IPG_DEBUG_MSG("RX runt occurred\n"); - sp->stats.rx_length_errors++; - } - - /* Do nothing for IPG_RFS_RXOVERSIZEDFRAME, - * error count handled by a IPG statistic register. - */ - - if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) { - IPG_DEBUG_MSG("RX alignment error occurred\n"); - sp->stats.rx_frame_errors++; - } - - /* Do nothing for IPG_RFS_RXFCSERROR, error count - * handled by a IPG statistic register. - */ - - /* Free the memory associated with the RX - * buffer since it is erroneous and we will - * not pass it to higher layer processes. - */ - if (sp->rx_buff[entry]) { - pci_unmap_single(sp->pdev, - le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN, - sp->rx_buf_sz, PCI_DMA_FROMDEVICE); - - dev_kfree_skb_irq(sp->rx_buff[entry]); - sp->rx_buff[entry] = NULL; - } - return ERROR_PACKET; - } - return NORMAL_PACKET; -} - -static void ipg_nic_rx_with_start_and_end(struct net_device *dev, - struct ipg_nic_private *sp, - struct ipg_rx *rxfd, unsigned entry) -{ - struct ipg_jumbo *jumbo = &sp->jumbo; - struct sk_buff *skb; - int framelen; - - if (jumbo->found_start) { - dev_kfree_skb_irq(jumbo->skb); - jumbo->found_start = 0; - jumbo->current_size = 0; - jumbo->skb = NULL; - } - - /* 1: found error, 0 no error */ - if (ipg_nic_rx_check_error(dev) != NORMAL_PACKET) - return; - - skb = sp->rx_buff[entry]; - if (!skb) - return; - - /* accept this frame and send to upper layer */ - framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN; - if (framelen > sp->rxfrag_size) - framelen = sp->rxfrag_size; - - skb_put(skb, framelen); - skb->protocol = eth_type_trans(skb, dev); - skb_checksum_none_assert(skb); - netif_rx(skb); - sp->rx_buff[entry] = NULL; -} - -static void ipg_nic_rx_with_start(struct net_device *dev, - struct ipg_nic_private *sp, - struct ipg_rx *rxfd, unsigned entry) -{ - struct ipg_jumbo *jumbo = &sp->jumbo; - struct pci_dev *pdev = sp->pdev; - struct sk_buff *skb; - - /* 1: found error, 0 no error */ - if (ipg_nic_rx_check_error(dev) != NORMAL_PACKET) - return; - - /* accept this frame and send to upper layer */ - skb = sp->rx_buff[entry]; - if (!skb) - return; - - if (jumbo->found_start) - dev_kfree_skb_irq(jumbo->skb); - - pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN, - sp->rx_buf_sz, PCI_DMA_FROMDEVICE); - - skb_put(skb, sp->rxfrag_size); - - jumbo->found_start = 1; - jumbo->current_size = sp->rxfrag_size; - jumbo->skb = skb; - - sp->rx_buff[entry] = NULL; -} - -static void ipg_nic_rx_with_end(struct net_device *dev, - struct ipg_nic_private *sp, - struct ipg_rx *rxfd, unsigned entry) -{ - struct ipg_jumbo *jumbo = &sp->jumbo; - - /* 1: found error, 0 no error */ - if (ipg_nic_rx_check_error(dev) == NORMAL_PACKET) { - struct sk_buff *skb = sp->rx_buff[entry]; - - if (!skb) - return; - - if (jumbo->found_start) { - int framelen, endframelen; - - framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN; - - endframelen = framelen - jumbo->current_size; - if (framelen > sp->rxsupport_size) - dev_kfree_skb_irq(jumbo->skb); - else { - memcpy(skb_put(jumbo->skb, endframelen), - skb->data, endframelen); - - jumbo->skb->protocol = - eth_type_trans(jumbo->skb, dev); - - skb_checksum_none_assert(jumbo->skb); - netif_rx(jumbo->skb); - } - } - - jumbo->found_start = 0; - jumbo->current_size = 0; - jumbo->skb = NULL; - - ipg_nic_rx_free_skb(dev); - } else { - dev_kfree_skb_irq(jumbo->skb); - jumbo->found_start = 0; - jumbo->current_size = 0; - jumbo->skb = NULL; - } -} - -static void ipg_nic_rx_no_start_no_end(struct net_device *dev, - struct ipg_nic_private *sp, - struct ipg_rx *rxfd, unsigned entry) -{ - struct ipg_jumbo *jumbo = &sp->jumbo; - - /* 1: found error, 0 no error */ - if (ipg_nic_rx_check_error(dev) == NORMAL_PACKET) { - struct sk_buff *skb = sp->rx_buff[entry]; - - if (skb) { - if (jumbo->found_start) { - jumbo->current_size += sp->rxfrag_size; - if (jumbo->current_size <= sp->rxsupport_size) { - memcpy(skb_put(jumbo->skb, - sp->rxfrag_size), - skb->data, sp->rxfrag_size); - } - } - ipg_nic_rx_free_skb(dev); - } - } else { - dev_kfree_skb_irq(jumbo->skb); - jumbo->found_start = 0; - jumbo->current_size = 0; - jumbo->skb = NULL; - } -} - -static int ipg_nic_rx_jumbo(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - unsigned int curr = sp->rx_current; - void __iomem *ioaddr = sp->ioaddr; - unsigned int i; - - IPG_DEBUG_MSG("_nic_rx\n"); - - for (i = 0; i < IPG_MAXRFDPROCESS_COUNT; i++, curr++) { - unsigned int entry = curr % IPG_RFDLIST_LENGTH; - struct ipg_rx *rxfd = sp->rxd + entry; - - if (!(rxfd->rfs & cpu_to_le64(IPG_RFS_RFDDONE))) - break; - - switch (ipg_nic_rx_check_frame_type(dev)) { - case FRAME_WITH_START_WITH_END: - ipg_nic_rx_with_start_and_end(dev, sp, rxfd, entry); - break; - case FRAME_WITH_START: - ipg_nic_rx_with_start(dev, sp, rxfd, entry); - break; - case FRAME_WITH_END: - ipg_nic_rx_with_end(dev, sp, rxfd, entry); - break; - case FRAME_NO_START_NO_END: - ipg_nic_rx_no_start_no_end(dev, sp, rxfd, entry); - break; - } - } - - sp->rx_current = curr; - - if (i == IPG_MAXRFDPROCESS_COUNT) { - /* There are more RFDs to process, however the - * allocated amount of RFD processing time has - * expired. Assert Interrupt Requested to make - * sure we come back to process the remaining RFDs. - */ - ipg_w32(ipg_r32(ASIC_CTRL) | IPG_AC_INT_REQUEST, ASIC_CTRL); - } - - ipg_nic_rxrestore(dev); - - return 0; -} - -static int ipg_nic_rx(struct net_device *dev) -{ - /* Transfer received Ethernet frames to higher network layers. */ - struct ipg_nic_private *sp = netdev_priv(dev); - unsigned int curr = sp->rx_current; - void __iomem *ioaddr = sp->ioaddr; - struct ipg_rx *rxfd; - unsigned int i; - - IPG_DEBUG_MSG("_nic_rx\n"); - -#define __RFS_MASK \ - cpu_to_le64(IPG_RFS_RFDDONE | IPG_RFS_FRAMESTART | IPG_RFS_FRAMEEND) - - for (i = 0; i < IPG_MAXRFDPROCESS_COUNT; i++, curr++) { - unsigned int entry = curr % IPG_RFDLIST_LENGTH; - struct sk_buff *skb = sp->rx_buff[entry]; - unsigned int framelen; - - rxfd = sp->rxd + entry; - - if (((rxfd->rfs & __RFS_MASK) != __RFS_MASK) || !skb) - break; - - /* Get received frame length. */ - framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN; - - /* Check for jumbo frame arrival with too small - * RXFRAG_SIZE. - */ - if (framelen > sp->rxfrag_size) { - IPG_DEBUG_MSG - ("RFS FrameLen > allocated fragment size\n"); - - framelen = sp->rxfrag_size; - } - - if ((IPG_DROP_ON_RX_ETH_ERRORS && (le64_to_cpu(rxfd->rfs) & - (IPG_RFS_RXFIFOOVERRUN | IPG_RFS_RXRUNTFRAME | - IPG_RFS_RXALIGNMENTERROR | IPG_RFS_RXFCSERROR | - IPG_RFS_RXOVERSIZEDFRAME | IPG_RFS_RXLENGTHERROR)))) { - - IPG_DEBUG_MSG("Rx error, RFS = %016lx\n", - (unsigned long int) rxfd->rfs); - - /* Increment general receive error statistic. */ - sp->stats.rx_errors++; - - /* Increment detailed receive error statistics. */ - if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) { - IPG_DEBUG_MSG("RX FIFO overrun occurred\n"); - sp->stats.rx_fifo_errors++; - } - - if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) { - IPG_DEBUG_MSG("RX runt occurred\n"); - sp->stats.rx_length_errors++; - } - - if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXOVERSIZEDFRAME) ; - /* Do nothing, error count handled by a IPG - * statistic register. - */ - - if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) { - IPG_DEBUG_MSG("RX alignment error occurred\n"); - sp->stats.rx_frame_errors++; - } - - if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFCSERROR) ; - /* Do nothing, error count handled by a IPG - * statistic register. - */ - - /* Free the memory associated with the RX - * buffer since it is erroneous and we will - * not pass it to higher layer processes. - */ - if (skb) { - __le64 info = rxfd->frag_info; - - pci_unmap_single(sp->pdev, - le64_to_cpu(info) & ~IPG_RFI_FRAGLEN, - sp->rx_buf_sz, PCI_DMA_FROMDEVICE); - - dev_kfree_skb_irq(skb); - } - } else { - - /* Adjust the new buffer length to accommodate the size - * of the received frame. - */ - skb_put(skb, framelen); - - /* Set the buffer's protocol field to Ethernet. */ - skb->protocol = eth_type_trans(skb, dev); - - /* The IPG encountered an error with (or - * there were no) IP/TCP/UDP checksums. - * This may or may not indicate an invalid - * IP/TCP/UDP frame was received. Let the - * upper layer decide. - */ - skb_checksum_none_assert(skb); - - /* Hand off frame for higher layer processing. - * The function netif_rx() releases the sk_buff - * when processing completes. - */ - netif_rx(skb); - } - - /* Assure RX buffer is not reused by IPG. */ - sp->rx_buff[entry] = NULL; - } - - /* - * If there are more RFDs to process and the allocated amount of RFD - * processing time has expired, assert Interrupt Requested to make - * sure we come back to process the remaining RFDs. - */ - if (i == IPG_MAXRFDPROCESS_COUNT) - ipg_w32(ipg_r32(ASIC_CTRL) | IPG_AC_INT_REQUEST, ASIC_CTRL); - -#ifdef IPG_DEBUG - /* Check if the RFD list contained no receive frame data. */ - if (!i) - sp->EmptyRFDListCount++; -#endif - while ((le64_to_cpu(rxfd->rfs) & IPG_RFS_RFDDONE) && - !((le64_to_cpu(rxfd->rfs) & IPG_RFS_FRAMESTART) && - (le64_to_cpu(rxfd->rfs) & IPG_RFS_FRAMEEND))) { - unsigned int entry = curr++ % IPG_RFDLIST_LENGTH; - - rxfd = sp->rxd + entry; - - IPG_DEBUG_MSG("Frame requires multiple RFDs\n"); - - /* An unexpected event, additional code needed to handle - * properly. So for the time being, just disregard the - * frame. - */ - - /* Free the memory associated with the RX - * buffer since it is erroneous and we will - * not pass it to higher layer processes. - */ - if (sp->rx_buff[entry]) { - pci_unmap_single(sp->pdev, - le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN, - sp->rx_buf_sz, PCI_DMA_FROMDEVICE); - dev_kfree_skb_irq(sp->rx_buff[entry]); - } - - /* Assure RX buffer is not reused by IPG. */ - sp->rx_buff[entry] = NULL; - } - - sp->rx_current = curr; - - /* Check to see if there are a minimum number of used - * RFDs before restoring any (should improve performance.) - */ - if ((curr - sp->rx_dirty) >= IPG_MINUSEDRFDSTOFREE) - ipg_nic_rxrestore(dev); - - return 0; -} - -static void ipg_reset_after_host_error(struct work_struct *work) -{ - struct ipg_nic_private *sp = - container_of(work, struct ipg_nic_private, task.work); - struct net_device *dev = sp->dev; - - /* - * Acknowledge HostError interrupt by resetting - * IPG DMA and HOST. - */ - ipg_reset(dev, IPG_AC_GLOBAL_RESET | IPG_AC_HOST | IPG_AC_DMA); - - init_rfdlist(dev); - init_tfdlist(dev); - - if (ipg_io_config(dev) < 0) { - netdev_info(dev, "Cannot recover from PCI error\n"); - schedule_delayed_work(&sp->task, HZ); - } -} - -static irqreturn_t ipg_interrupt_handler(int irq, void *dev_inst) -{ - struct net_device *dev = dev_inst; - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - unsigned int handled = 0; - u16 status; - - IPG_DEBUG_MSG("_interrupt_handler\n"); - - if (sp->is_jumbo) - ipg_nic_rxrestore(dev); - - spin_lock(&sp->lock); - - /* Get interrupt source information, and acknowledge - * some (i.e. TxDMAComplete, RxDMAComplete, RxEarly, - * IntRequested, MacControlFrame, LinkEvent) interrupts - * if issued. Also, all IPG interrupts are disabled by - * reading IntStatusAck. - */ - status = ipg_r16(INT_STATUS_ACK); - - IPG_DEBUG_MSG("IntStatusAck = %04x\n", status); - - /* Shared IRQ of remove event. */ - if (!(status & IPG_IS_RSVD_MASK)) - goto out_enable; - - handled = 1; - - if (unlikely(!netif_running(dev))) - goto out_unlock; - - /* If RFDListEnd interrupt, restore all used RFDs. */ - if (status & IPG_IS_RFD_LIST_END) { - IPG_DEBUG_MSG("RFDListEnd Interrupt\n"); - - /* The RFD list end indicates an RFD was encountered - * with a 0 NextPtr, or with an RFDDone bit set to 1 - * (indicating the RFD is not read for use by the - * IPG.) Try to restore all RFDs. - */ - ipg_nic_rxrestore(dev); - -#ifdef IPG_DEBUG - /* Increment the RFDlistendCount counter. */ - sp->RFDlistendCount++; -#endif - } - - /* If RFDListEnd, RxDMAPriority, RxDMAComplete, or - * IntRequested interrupt, process received frames. */ - if ((status & IPG_IS_RX_DMA_PRIORITY) || - (status & IPG_IS_RFD_LIST_END) || - (status & IPG_IS_RX_DMA_COMPLETE) || - (status & IPG_IS_INT_REQUESTED)) { -#ifdef IPG_DEBUG - /* Increment the RFD list checked counter if interrupted - * only to check the RFD list. */ - if (status & (~(IPG_IS_RX_DMA_PRIORITY | IPG_IS_RFD_LIST_END | - IPG_IS_RX_DMA_COMPLETE | IPG_IS_INT_REQUESTED) & - (IPG_IS_HOST_ERROR | IPG_IS_TX_DMA_COMPLETE | - IPG_IS_LINK_EVENT | IPG_IS_TX_COMPLETE | - IPG_IS_UPDATE_STATS))) - sp->RFDListCheckedCount++; -#endif - - if (sp->is_jumbo) - ipg_nic_rx_jumbo(dev); - else - ipg_nic_rx(dev); - } - - /* If TxDMAComplete interrupt, free used TFDs. */ - if (status & IPG_IS_TX_DMA_COMPLETE) - ipg_nic_txfree(dev); - - /* TxComplete interrupts indicate one of numerous actions. - * Determine what action to take based on TXSTATUS register. - */ - if (status & IPG_IS_TX_COMPLETE) - ipg_nic_txcleanup(dev); - - /* If UpdateStats interrupt, update Linux Ethernet statistics */ - if (status & IPG_IS_UPDATE_STATS) - ipg_nic_get_stats(dev); - - /* If HostError interrupt, reset IPG. */ - if (status & IPG_IS_HOST_ERROR) { - IPG_DDEBUG_MSG("HostError Interrupt\n"); - - schedule_delayed_work(&sp->task, 0); - } - - /* If LinkEvent interrupt, resolve autonegotiation. */ - if (status & IPG_IS_LINK_EVENT) { - if (ipg_config_autoneg(dev) < 0) - netdev_info(dev, "Auto-negotiation error\n"); - } - - /* If MACCtrlFrame interrupt, do nothing. */ - if (status & IPG_IS_MAC_CTRL_FRAME) - IPG_DEBUG_MSG("MACCtrlFrame interrupt\n"); - - /* If RxComplete interrupt, do nothing. */ - if (status & IPG_IS_RX_COMPLETE) - IPG_DEBUG_MSG("RxComplete interrupt\n"); - - /* If RxEarly interrupt, do nothing. */ - if (status & IPG_IS_RX_EARLY) - IPG_DEBUG_MSG("RxEarly interrupt\n"); - -out_enable: - /* Re-enable IPG interrupts. */ - ipg_w16(IPG_IE_TX_DMA_COMPLETE | IPG_IE_RX_DMA_COMPLETE | - IPG_IE_HOST_ERROR | IPG_IE_INT_REQUESTED | IPG_IE_TX_COMPLETE | - IPG_IE_LINK_EVENT | IPG_IE_UPDATE_STATS, INT_ENABLE); -out_unlock: - spin_unlock(&sp->lock); - - return IRQ_RETVAL(handled); -} - -static void ipg_rx_clear(struct ipg_nic_private *sp) -{ - unsigned int i; - - for (i = 0; i < IPG_RFDLIST_LENGTH; i++) { - if (sp->rx_buff[i]) { - struct ipg_rx *rxfd = sp->rxd + i; - - dev_kfree_skb_irq(sp->rx_buff[i]); - sp->rx_buff[i] = NULL; - pci_unmap_single(sp->pdev, - le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN, - sp->rx_buf_sz, PCI_DMA_FROMDEVICE); - } - } -} - -static void ipg_tx_clear(struct ipg_nic_private *sp) -{ - unsigned int i; - - for (i = 0; i < IPG_TFDLIST_LENGTH; i++) { - if (sp->tx_buff[i]) { - struct ipg_tx *txfd = sp->txd + i; - - pci_unmap_single(sp->pdev, - le64_to_cpu(txfd->frag_info) & ~IPG_TFI_FRAGLEN, - sp->tx_buff[i]->len, PCI_DMA_TODEVICE); - - dev_kfree_skb_irq(sp->tx_buff[i]); - - sp->tx_buff[i] = NULL; - } - } -} - -static int ipg_nic_open(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - struct pci_dev *pdev = sp->pdev; - int rc; - - IPG_DEBUG_MSG("_nic_open\n"); - - sp->rx_buf_sz = sp->rxsupport_size; - - /* Check for interrupt line conflicts, and request interrupt - * line for IPG. - * - * IMPORTANT: Disable IPG interrupts prior to registering - * IRQ. - */ - ipg_w16(0x0000, INT_ENABLE); - - /* Register the interrupt line to be used by the IPG within - * the Linux system. - */ - rc = request_irq(pdev->irq, ipg_interrupt_handler, IRQF_SHARED, - dev->name, dev); - if (rc < 0) { - netdev_info(dev, "Error when requesting interrupt\n"); - goto out; - } - - dev->irq = pdev->irq; - - rc = -ENOMEM; - - sp->rxd = dma_alloc_coherent(&pdev->dev, IPG_RX_RING_BYTES, - &sp->rxd_map, GFP_KERNEL); - if (!sp->rxd) - goto err_free_irq_0; - - sp->txd = dma_alloc_coherent(&pdev->dev, IPG_TX_RING_BYTES, - &sp->txd_map, GFP_KERNEL); - if (!sp->txd) - goto err_free_rx_1; - - rc = init_rfdlist(dev); - if (rc < 0) { - netdev_info(dev, "Error during configuration\n"); - goto err_free_tx_2; - } - - init_tfdlist(dev); - - rc = ipg_io_config(dev); - if (rc < 0) { - netdev_info(dev, "Error during configuration\n"); - goto err_release_tfdlist_3; - } - - /* Resolve autonegotiation. */ - if (ipg_config_autoneg(dev) < 0) - netdev_info(dev, "Auto-negotiation error\n"); - - /* initialize JUMBO Frame control variable */ - sp->jumbo.found_start = 0; - sp->jumbo.current_size = 0; - sp->jumbo.skb = NULL; - - /* Enable transmit and receive operation of the IPG. */ - ipg_w32((ipg_r32(MAC_CTRL) | IPG_MC_RX_ENABLE | IPG_MC_TX_ENABLE) & - IPG_MC_RSVD_MASK, MAC_CTRL); - - netif_start_queue(dev); -out: - return rc; - -err_release_tfdlist_3: - ipg_tx_clear(sp); - ipg_rx_clear(sp); -err_free_tx_2: - dma_free_coherent(&pdev->dev, IPG_TX_RING_BYTES, sp->txd, sp->txd_map); -err_free_rx_1: - dma_free_coherent(&pdev->dev, IPG_RX_RING_BYTES, sp->rxd, sp->rxd_map); -err_free_irq_0: - free_irq(pdev->irq, dev); - goto out; -} - -static int ipg_nic_stop(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - struct pci_dev *pdev = sp->pdev; - - IPG_DEBUG_MSG("_nic_stop\n"); - - netif_stop_queue(dev); - - IPG_DUMPTFDLIST(dev); - - do { - (void) ipg_r16(INT_STATUS_ACK); - - ipg_reset(dev, IPG_AC_GLOBAL_RESET | IPG_AC_HOST | IPG_AC_DMA); - - synchronize_irq(pdev->irq); - } while (ipg_r16(INT_ENABLE) & IPG_IE_RSVD_MASK); - - ipg_rx_clear(sp); - - ipg_tx_clear(sp); - - pci_free_consistent(pdev, IPG_RX_RING_BYTES, sp->rxd, sp->rxd_map); - pci_free_consistent(pdev, IPG_TX_RING_BYTES, sp->txd, sp->txd_map); - - free_irq(pdev->irq, dev); - - return 0; -} - -static netdev_tx_t ipg_nic_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - unsigned int entry = sp->tx_current % IPG_TFDLIST_LENGTH; - unsigned long flags; - struct ipg_tx *txfd; - - IPG_DDEBUG_MSG("_nic_hard_start_xmit\n"); - - /* If in 10Mbps mode, stop the transmit queue so - * no more transmit frames are accepted. - */ - if (sp->tenmbpsmode) - netif_stop_queue(dev); - - if (sp->reset_current_tfd) { - sp->reset_current_tfd = 0; - entry = 0; - } - - txfd = sp->txd + entry; - - sp->tx_buff[entry] = skb; - - /* Clear all TFC fields, except TFDDONE. */ - txfd->tfc = cpu_to_le64(IPG_TFC_TFDDONE); - - /* Specify the TFC field within the TFD. */ - txfd->tfc |= cpu_to_le64(IPG_TFC_WORDALIGNDISABLED | - (IPG_TFC_FRAMEID & sp->tx_current) | - (IPG_TFC_FRAGCOUNT & (1 << 24))); - /* - * 16--17 (WordAlign) <- 3 (disable), - * 0--15 (FrameId) <- sp->tx_current, - * 24--27 (FragCount) <- 1 - */ - - /* Request TxComplete interrupts at an interval defined - * by the constant IPG_FRAMESBETWEENTXCOMPLETES. - * Request TxComplete interrupt for every frame - * if in 10Mbps mode to accommodate problem with 10Mbps - * processing. - */ - if (sp->tenmbpsmode) - txfd->tfc |= cpu_to_le64(IPG_TFC_TXINDICATE); - txfd->tfc |= cpu_to_le64(IPG_TFC_TXDMAINDICATE); - /* Based on compilation option, determine if FCS is to be - * appended to transmit frame by IPG. - */ - if (!(IPG_APPEND_FCS_ON_TX)) - txfd->tfc |= cpu_to_le64(IPG_TFC_FCSAPPENDDISABLE); - - /* Based on compilation option, determine if IP, TCP and/or - * UDP checksums are to be added to transmit frame by IPG. - */ - if (IPG_ADD_IPCHECKSUM_ON_TX) - txfd->tfc |= cpu_to_le64(IPG_TFC_IPCHECKSUMENABLE); - - if (IPG_ADD_TCPCHECKSUM_ON_TX) - txfd->tfc |= cpu_to_le64(IPG_TFC_TCPCHECKSUMENABLE); - - if (IPG_ADD_UDPCHECKSUM_ON_TX) - txfd->tfc |= cpu_to_le64(IPG_TFC_UDPCHECKSUMENABLE); - - /* Based on compilation option, determine if VLAN tag info is to be - * inserted into transmit frame by IPG. - */ - if (IPG_INSERT_MANUAL_VLAN_TAG) { - txfd->tfc |= cpu_to_le64(IPG_TFC_VLANTAGINSERT | - ((u64) IPG_MANUAL_VLAN_VID << 32) | - ((u64) IPG_MANUAL_VLAN_CFI << 44) | - ((u64) IPG_MANUAL_VLAN_USERPRIORITY << 45)); - } - - /* The fragment start location within system memory is defined - * by the sk_buff structure's data field. The physical address - * of this location within the system's virtual memory space - * is determined using the IPG_HOST2BUS_MAP function. - */ - txfd->frag_info = cpu_to_le64(pci_map_single(sp->pdev, skb->data, - skb->len, PCI_DMA_TODEVICE)); - - /* The length of the fragment within system memory is defined by - * the sk_buff structure's len field. - */ - txfd->frag_info |= cpu_to_le64(IPG_TFI_FRAGLEN & - ((u64) (skb->len & 0xffff) << 48)); - - /* Clear the TFDDone bit last to indicate the TFD is ready - * for transfer to the IPG. - */ - txfd->tfc &= cpu_to_le64(~IPG_TFC_TFDDONE); - - spin_lock_irqsave(&sp->lock, flags); - - sp->tx_current++; - - mmiowb(); - - ipg_w32(IPG_DC_TX_DMA_POLL_NOW, DMA_CTRL); - - if (sp->tx_current == (sp->tx_dirty + IPG_TFDLIST_LENGTH)) - netif_stop_queue(dev); - - spin_unlock_irqrestore(&sp->lock, flags); - - return NETDEV_TX_OK; -} - -static void ipg_set_phy_default_param(unsigned char rev, - struct net_device *dev, int phy_address) -{ - unsigned short length; - unsigned char revision; - const unsigned short *phy_param; - unsigned short address, value; - - phy_param = &DefaultPhyParam[0]; - length = *phy_param & 0x00FF; - revision = (unsigned char)((*phy_param) >> 8); - phy_param++; - while (length != 0) { - if (rev == revision) { - while (length > 1) { - address = *phy_param; - value = *(phy_param + 1); - phy_param += 2; - mdio_write(dev, phy_address, address, value); - length -= 4; - } - break; - } else { - phy_param += length / 2; - length = *phy_param & 0x00FF; - revision = (unsigned char)((*phy_param) >> 8); - phy_param++; - } - } -} - -static int read_eeprom(struct net_device *dev, int eep_addr) -{ - void __iomem *ioaddr = ipg_ioaddr(dev); - unsigned int i; - int ret = 0; - u16 value; - - value = IPG_EC_EEPROM_READOPCODE | (eep_addr & 0xff); - ipg_w16(value, EEPROM_CTRL); - - for (i = 0; i < 1000; i++) { - u16 data; - - mdelay(10); - data = ipg_r16(EEPROM_CTRL); - if (!(data & IPG_EC_EEPROM_BUSY)) { - ret = ipg_r16(EEPROM_DATA); - break; - } - } - return ret; -} - -static void ipg_init_mii(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - struct mii_if_info *mii_if = &sp->mii_if; - int phyaddr; - - mii_if->dev = dev; - mii_if->mdio_read = mdio_read; - mii_if->mdio_write = mdio_write; - mii_if->phy_id_mask = 0x1f; - mii_if->reg_num_mask = 0x1f; - - mii_if->phy_id = phyaddr = ipg_find_phyaddr(dev); - - if (phyaddr != 0x1f) { - u16 mii_phyctrl, mii_1000cr; - - mii_1000cr = mdio_read(dev, phyaddr, MII_CTRL1000); - mii_1000cr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF | - GMII_PHY_1000BASETCONTROL_PreferMaster; - mdio_write(dev, phyaddr, MII_CTRL1000, mii_1000cr); - - mii_phyctrl = mdio_read(dev, phyaddr, MII_BMCR); - - /* Set default phyparam */ - ipg_set_phy_default_param(sp->pdev->revision, dev, phyaddr); - - /* Reset PHY */ - mii_phyctrl |= BMCR_RESET | BMCR_ANRESTART; - mdio_write(dev, phyaddr, MII_BMCR, mii_phyctrl); - - } -} - -static int ipg_hw_init(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - void __iomem *ioaddr = sp->ioaddr; - unsigned int i; - int rc; - - /* Read/Write and Reset EEPROM Value */ - /* Read LED Mode Configuration from EEPROM */ - sp->led_mode = read_eeprom(dev, 6); - - /* Reset all functions within the IPG. Do not assert - * RST_OUT as not compatible with some PHYs. - */ - rc = ipg_reset(dev, IPG_RESET_MASK); - if (rc < 0) - goto out; - - ipg_init_mii(dev); - - /* Read MAC Address from EEPROM */ - for (i = 0; i < 3; i++) - sp->station_addr[i] = read_eeprom(dev, 16 + i); - - for (i = 0; i < 3; i++) - ipg_w16(sp->station_addr[i], STATION_ADDRESS_0 + 2*i); - - /* Set station address in ethernet_device structure. */ - dev->dev_addr[0] = ipg_r16(STATION_ADDRESS_0) & 0x00ff; - dev->dev_addr[1] = (ipg_r16(STATION_ADDRESS_0) & 0xff00) >> 8; - dev->dev_addr[2] = ipg_r16(STATION_ADDRESS_1) & 0x00ff; - dev->dev_addr[3] = (ipg_r16(STATION_ADDRESS_1) & 0xff00) >> 8; - dev->dev_addr[4] = ipg_r16(STATION_ADDRESS_2) & 0x00ff; - dev->dev_addr[5] = (ipg_r16(STATION_ADDRESS_2) & 0xff00) >> 8; -out: - return rc; -} - -static int ipg_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - int rc; - - mutex_lock(&sp->mii_mutex); - rc = generic_mii_ioctl(&sp->mii_if, if_mii(ifr), cmd, NULL); - mutex_unlock(&sp->mii_mutex); - - return rc; -} - -static int ipg_nic_change_mtu(struct net_device *dev, int new_mtu) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - int err; - - /* Function to accommodate changes to Maximum Transfer Unit - * (or MTU) of IPG NIC. Cannot use default function since - * the default will not allow for MTU > 1500 bytes. - */ - - IPG_DEBUG_MSG("_nic_change_mtu\n"); - - /* - * Check that the new MTU value is between 68 (14 byte header, 46 byte - * payload, 4 byte FCS) and 10 KB, which is the largest supported MTU. - */ - if (new_mtu < 68 || new_mtu > 10240) - return -EINVAL; - - err = ipg_nic_stop(dev); - if (err) - return err; - - dev->mtu = new_mtu; - - sp->max_rxframe_size = new_mtu; - - sp->rxfrag_size = new_mtu; - if (sp->rxfrag_size > 4088) - sp->rxfrag_size = 4088; - - sp->rxsupport_size = sp->max_rxframe_size; - - if (new_mtu > 0x0600) - sp->is_jumbo = true; - else - sp->is_jumbo = false; - - return ipg_nic_open(dev); -} - -static int ipg_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - int rc; - - mutex_lock(&sp->mii_mutex); - rc = mii_ethtool_gset(&sp->mii_if, cmd); - mutex_unlock(&sp->mii_mutex); - - return rc; -} - -static int ipg_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - int rc; - - mutex_lock(&sp->mii_mutex); - rc = mii_ethtool_sset(&sp->mii_if, cmd); - mutex_unlock(&sp->mii_mutex); - - return rc; -} - -static int ipg_nway_reset(struct net_device *dev) -{ - struct ipg_nic_private *sp = netdev_priv(dev); - int rc; - - mutex_lock(&sp->mii_mutex); - rc = mii_nway_restart(&sp->mii_if); - mutex_unlock(&sp->mii_mutex); - - return rc; -} - -static const struct ethtool_ops ipg_ethtool_ops = { - .get_settings = ipg_get_settings, - .set_settings = ipg_set_settings, - .nway_reset = ipg_nway_reset, -}; - -static void ipg_remove(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct ipg_nic_private *sp = netdev_priv(dev); - - IPG_DEBUG_MSG("_remove\n"); - - /* Un-register Ethernet device. */ - unregister_netdev(dev); - - pci_iounmap(pdev, sp->ioaddr); - - pci_release_regions(pdev); - - free_netdev(dev); - pci_disable_device(pdev); -} - -static const struct net_device_ops ipg_netdev_ops = { - .ndo_open = ipg_nic_open, - .ndo_stop = ipg_nic_stop, - .ndo_start_xmit = ipg_nic_hard_start_xmit, - .ndo_get_stats = ipg_nic_get_stats, - .ndo_set_rx_mode = ipg_nic_set_multicast_list, - .ndo_do_ioctl = ipg_ioctl, - .ndo_tx_timeout = ipg_tx_timeout, - .ndo_change_mtu = ipg_nic_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -static int ipg_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - unsigned int i = id->driver_data; - struct ipg_nic_private *sp; - struct net_device *dev; - void __iomem *ioaddr; - int rc; - - rc = pci_enable_device(pdev); - if (rc < 0) - goto out; - - pr_info("%s: %s\n", pci_name(pdev), ipg_brand_name[i]); - - pci_set_master(pdev); - - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(40)); - if (rc < 0) { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - pr_err("%s: DMA config failed\n", pci_name(pdev)); - goto err_disable_0; - } - } - - /* - * Initialize net device. - */ - dev = alloc_etherdev(sizeof(struct ipg_nic_private)); - if (!dev) { - rc = -ENOMEM; - goto err_disable_0; - } - - sp = netdev_priv(dev); - spin_lock_init(&sp->lock); - mutex_init(&sp->mii_mutex); - - sp->is_jumbo = IPG_IS_JUMBO; - sp->rxfrag_size = IPG_RXFRAG_SIZE; - sp->rxsupport_size = IPG_RXSUPPORT_SIZE; - sp->max_rxframe_size = IPG_MAX_RXFRAME_SIZE; - - /* Declare IPG NIC functions for Ethernet device methods. - */ - dev->netdev_ops = &ipg_netdev_ops; - SET_NETDEV_DEV(dev, &pdev->dev); - dev->ethtool_ops = &ipg_ethtool_ops; - - rc = pci_request_regions(pdev, DRV_NAME); - if (rc) - goto err_free_dev_1; - - ioaddr = pci_iomap(pdev, 1, pci_resource_len(pdev, 1)); - if (!ioaddr) { - pr_err("%s: cannot map MMIO\n", pci_name(pdev)); - rc = -EIO; - goto err_release_regions_2; - } - - /* Save the pointer to the PCI device information. */ - sp->ioaddr = ioaddr; - sp->pdev = pdev; - sp->dev = dev; - - INIT_DELAYED_WORK(&sp->task, ipg_reset_after_host_error); - - pci_set_drvdata(pdev, dev); - - rc = ipg_hw_init(dev); - if (rc < 0) - goto err_unmap_3; - - rc = register_netdev(dev); - if (rc < 0) - goto err_unmap_3; - - netdev_info(dev, "Ethernet device registered\n"); -out: - return rc; - -err_unmap_3: - pci_iounmap(pdev, ioaddr); -err_release_regions_2: - pci_release_regions(pdev); -err_free_dev_1: - free_netdev(dev); -err_disable_0: - pci_disable_device(pdev); - goto out; -} - -static struct pci_driver ipg_pci_driver = { - .name = IPG_DRIVER_NAME, - .id_table = ipg_pci_tbl, - .probe = ipg_probe, - .remove = ipg_remove, -}; - -module_pci_driver(ipg_pci_driver); diff --git a/drivers/net/ethernet/icplus/ipg.h b/drivers/net/ethernet/icplus/ipg.h deleted file mode 100644 index de606281f97b..000000000000 --- a/drivers/net/ethernet/icplus/ipg.h +++ /dev/null @@ -1,748 +0,0 @@ -/* - * Include file for Gigabit Ethernet device driver for Network - * Interface Cards (NICs) utilizing the Tamarack Microelectronics - * Inc. IPG Gigabit or Triple Speed Ethernet Media Access - * Controller. - */ -#ifndef __LINUX_IPG_H -#define __LINUX_IPG_H - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Constants - */ - -/* GMII based PHY IDs */ -#define NS 0x2000 -#define MARVELL 0x0141 -#define ICPLUS_PHY 0x243 - -/* NIC Physical Layer Device MII register fields. */ -#define MII_PHY_SELECTOR_IEEE8023 0x0001 -#define MII_PHY_TECHABILITYFIELD 0x1FE0 - -/* GMII_PHY_1000 need to set to prefer master */ -#define GMII_PHY_1000BASETCONTROL_PreferMaster 0x0400 - -/* NIC Physical Layer Device GMII constants. */ -#define GMII_PREAMBLE 0xFFFFFFFF -#define GMII_ST 0x1 -#define GMII_READ 0x2 -#define GMII_WRITE 0x1 -#define GMII_TA_READ_MASK 0x1 -#define GMII_TA_WRITE 0x2 - -/* I/O register offsets. */ -enum ipg_regs { - DMA_CTRL = 0x00, - RX_DMA_STATUS = 0x08, /* Unused + reserved */ - TFD_LIST_PTR_0 = 0x10, - TFD_LIST_PTR_1 = 0x14, - TX_DMA_BURST_THRESH = 0x18, - TX_DMA_URGENT_THRESH = 0x19, - TX_DMA_POLL_PERIOD = 0x1a, - RFD_LIST_PTR_0 = 0x1c, - RFD_LIST_PTR_1 = 0x20, - RX_DMA_BURST_THRESH = 0x24, - RX_DMA_URGENT_THRESH = 0x25, - RX_DMA_POLL_PERIOD = 0x26, - DEBUG_CTRL = 0x2c, - ASIC_CTRL = 0x30, - FIFO_CTRL = 0x38, /* Unused */ - FLOW_OFF_THRESH = 0x3c, - FLOW_ON_THRESH = 0x3e, - EEPROM_DATA = 0x48, - EEPROM_CTRL = 0x4a, - EXPROM_ADDR = 0x4c, /* Unused */ - EXPROM_DATA = 0x50, /* Unused */ - WAKE_EVENT = 0x51, /* Unused */ - COUNTDOWN = 0x54, /* Unused */ - INT_STATUS_ACK = 0x5a, - INT_ENABLE = 0x5c, - INT_STATUS = 0x5e, /* Unused */ - TX_STATUS = 0x60, - MAC_CTRL = 0x6c, - VLAN_TAG = 0x70, /* Unused */ - PHY_SET = 0x75, - PHY_CTRL = 0x76, - STATION_ADDRESS_0 = 0x78, - STATION_ADDRESS_1 = 0x7a, - STATION_ADDRESS_2 = 0x7c, - MAX_FRAME_SIZE = 0x86, - RECEIVE_MODE = 0x88, - HASHTABLE_0 = 0x8c, - HASHTABLE_1 = 0x90, - RMON_STATISTICS_MASK = 0x98, - STATISTICS_MASK = 0x9c, - RX_JUMBO_FRAMES = 0xbc, /* Unused */ - TCP_CHECKSUM_ERRORS = 0xc0, /* Unused */ - IP_CHECKSUM_ERRORS = 0xc2, /* Unused */ - UDP_CHECKSUM_ERRORS = 0xc4, /* Unused */ - TX_JUMBO_FRAMES = 0xf4 /* Unused */ -}; - -/* Ethernet MIB statistic register offsets. */ -#define IPG_OCTETRCVOK 0xA8 -#define IPG_MCSTOCTETRCVDOK 0xAC -#define IPG_BCSTOCTETRCVOK 0xB0 -#define IPG_FRAMESRCVDOK 0xB4 -#define IPG_MCSTFRAMESRCVDOK 0xB8 -#define IPG_BCSTFRAMESRCVDOK 0xBE -#define IPG_MACCONTROLFRAMESRCVD 0xC6 -#define IPG_FRAMETOOLONGERRORS 0xC8 -#define IPG_INRANGELENGTHERRORS 0xCA -#define IPG_FRAMECHECKSEQERRORS 0xCC -#define IPG_FRAMESLOSTRXERRORS 0xCE -#define IPG_OCTETXMTOK 0xD0 -#define IPG_MCSTOCTETXMTOK 0xD4 -#define IPG_BCSTOCTETXMTOK 0xD8 -#define IPG_FRAMESXMTDOK 0xDC -#define IPG_MCSTFRAMESXMTDOK 0xE0 -#define IPG_FRAMESWDEFERREDXMT 0xE4 -#define IPG_LATECOLLISIONS 0xE8 -#define IPG_MULTICOLFRAMES 0xEC -#define IPG_SINGLECOLFRAMES 0xF0 -#define IPG_BCSTFRAMESXMTDOK 0xF6 -#define IPG_CARRIERSENSEERRORS 0xF8 -#define IPG_MACCONTROLFRAMESXMTDOK 0xFA -#define IPG_FRAMESABORTXSCOLLS 0xFC -#define IPG_FRAMESWEXDEFERRAL 0xFE - -/* RMON statistic register offsets. */ -#define IPG_ETHERSTATSCOLLISIONS 0x100 -#define IPG_ETHERSTATSOCTETSTRANSMIT 0x104 -#define IPG_ETHERSTATSPKTSTRANSMIT 0x108 -#define IPG_ETHERSTATSPKTS64OCTESTSTRANSMIT 0x10C -#define IPG_ETHERSTATSPKTS65TO127OCTESTSTRANSMIT 0x110 -#define IPG_ETHERSTATSPKTS128TO255OCTESTSTRANSMIT 0x114 -#define IPG_ETHERSTATSPKTS256TO511OCTESTSTRANSMIT 0x118 -#define IPG_ETHERSTATSPKTS512TO1023OCTESTSTRANSMIT 0x11C -#define IPG_ETHERSTATSPKTS1024TO1518OCTESTSTRANSMIT 0x120 -#define IPG_ETHERSTATSCRCALIGNERRORS 0x124 -#define IPG_ETHERSTATSUNDERSIZEPKTS 0x128 -#define IPG_ETHERSTATSFRAGMENTS 0x12C -#define IPG_ETHERSTATSJABBERS 0x130 -#define IPG_ETHERSTATSOCTETS 0x134 -#define IPG_ETHERSTATSPKTS 0x138 -#define IPG_ETHERSTATSPKTS64OCTESTS 0x13C -#define IPG_ETHERSTATSPKTS65TO127OCTESTS 0x140 -#define IPG_ETHERSTATSPKTS128TO255OCTESTS 0x144 -#define IPG_ETHERSTATSPKTS256TO511OCTESTS 0x148 -#define IPG_ETHERSTATSPKTS512TO1023OCTESTS 0x14C -#define IPG_ETHERSTATSPKTS1024TO1518OCTESTS 0x150 - -/* RMON statistic register equivalents. */ -#define IPG_ETHERSTATSMULTICASTPKTSTRANSMIT 0xE0 -#define IPG_ETHERSTATSBROADCASTPKTSTRANSMIT 0xF6 -#define IPG_ETHERSTATSMULTICASTPKTS 0xB8 -#define IPG_ETHERSTATSBROADCASTPKTS 0xBE -#define IPG_ETHERSTATSOVERSIZEPKTS 0xC8 -#define IPG_ETHERSTATSDROPEVENTS 0xCE - -/* Serial EEPROM offsets */ -#define IPG_EEPROM_CONFIGPARAM 0x00 -#define IPG_EEPROM_ASICCTRL 0x01 -#define IPG_EEPROM_SUBSYSTEMVENDORID 0x02 -#define IPG_EEPROM_SUBSYSTEMID 0x03 -#define IPG_EEPROM_STATIONADDRESS0 0x10 -#define IPG_EEPROM_STATIONADDRESS1 0x11 -#define IPG_EEPROM_STATIONADDRESS2 0x12 - -/* Register & data structure bit masks */ - -/* PCI register masks. */ - -/* IOBaseAddress */ -#define IPG_PIB_RSVD_MASK 0xFFFFFE01 -#define IPG_PIB_IOBASEADDRESS 0xFFFFFF00 -#define IPG_PIB_IOBASEADDRIND 0x00000001 - -/* MemBaseAddress */ -#define IPG_PMB_RSVD_MASK 0xFFFFFE07 -#define IPG_PMB_MEMBASEADDRIND 0x00000001 -#define IPG_PMB_MEMMAPTYPE 0x00000006 -#define IPG_PMB_MEMMAPTYPE0 0x00000002 -#define IPG_PMB_MEMMAPTYPE1 0x00000004 -#define IPG_PMB_MEMBASEADDRESS 0xFFFFFE00 - -/* ConfigStatus */ -#define IPG_CS_RSVD_MASK 0xFFB0 -#define IPG_CS_CAPABILITIES 0x0010 -#define IPG_CS_66MHZCAPABLE 0x0020 -#define IPG_CS_FASTBACK2BACK 0x0080 -#define IPG_CS_DATAPARITYREPORTED 0x0100 -#define IPG_CS_DEVSELTIMING 0x0600 -#define IPG_CS_SIGNALEDTARGETABORT 0x0800 -#define IPG_CS_RECEIVEDTARGETABORT 0x1000 -#define IPG_CS_RECEIVEDMASTERABORT 0x2000 -#define IPG_CS_SIGNALEDSYSTEMERROR 0x4000 -#define IPG_CS_DETECTEDPARITYERROR 0x8000 - -/* TFD data structure masks. */ - -/* TFDList, TFC */ -#define IPG_TFC_RSVD_MASK 0x0000FFFF9FFFFFFFULL -#define IPG_TFC_FRAMEID 0x000000000000FFFFULL -#define IPG_TFC_WORDALIGN 0x0000000000030000ULL -#define IPG_TFC_WORDALIGNTODWORD 0x0000000000000000ULL -#define IPG_TFC_WORDALIGNTOWORD 0x0000000000020000ULL -#define IPG_TFC_WORDALIGNDISABLED 0x0000000000030000ULL -#define IPG_TFC_TCPCHECKSUMENABLE 0x0000000000040000ULL -#define IPG_TFC_UDPCHECKSUMENABLE 0x0000000000080000ULL -#define IPG_TFC_IPCHECKSUMENABLE 0x0000000000100000ULL -#define IPG_TFC_FCSAPPENDDISABLE 0x0000000000200000ULL -#define IPG_TFC_TXINDICATE 0x0000000000400000ULL -#define IPG_TFC_TXDMAINDICATE 0x0000000000800000ULL -#define IPG_TFC_FRAGCOUNT 0x000000000F000000ULL -#define IPG_TFC_VLANTAGINSERT 0x0000000010000000ULL -#define IPG_TFC_TFDDONE 0x0000000080000000ULL -#define IPG_TFC_VID 0x00000FFF00000000ULL -#define IPG_TFC_CFI 0x0000100000000000ULL -#define IPG_TFC_USERPRIORITY 0x0000E00000000000ULL - -/* TFDList, FragInfo */ -#define IPG_TFI_RSVD_MASK 0xFFFF00FFFFFFFFFFULL -#define IPG_TFI_FRAGADDR 0x000000FFFFFFFFFFULL -#define IPG_TFI_FRAGLEN 0xFFFF000000000000ULL - -/* RFD data structure masks. */ - -/* RFDList, RFS */ -#define IPG_RFS_RSVD_MASK 0x0000FFFFFFFFFFFFULL -#define IPG_RFS_RXFRAMELEN 0x000000000000FFFFULL -#define IPG_RFS_RXFIFOOVERRUN 0x0000000000010000ULL -#define IPG_RFS_RXRUNTFRAME 0x0000000000020000ULL -#define IPG_RFS_RXALIGNMENTERROR 0x0000000000040000ULL -#define IPG_RFS_RXFCSERROR 0x0000000000080000ULL -#define IPG_RFS_RXOVERSIZEDFRAME 0x0000000000100000ULL -#define IPG_RFS_RXLENGTHERROR 0x0000000000200000ULL -#define IPG_RFS_VLANDETECTED 0x0000000000400000ULL -#define IPG_RFS_TCPDETECTED 0x0000000000800000ULL -#define IPG_RFS_TCPERROR 0x0000000001000000ULL -#define IPG_RFS_UDPDETECTED 0x0000000002000000ULL -#define IPG_RFS_UDPERROR 0x0000000004000000ULL -#define IPG_RFS_IPDETECTED 0x0000000008000000ULL -#define IPG_RFS_IPERROR 0x0000000010000000ULL -#define IPG_RFS_FRAMESTART 0x0000000020000000ULL -#define IPG_RFS_FRAMEEND 0x0000000040000000ULL -#define IPG_RFS_RFDDONE 0x0000000080000000ULL -#define IPG_RFS_TCI 0x0000FFFF00000000ULL - -/* RFDList, FragInfo */ -#define IPG_RFI_RSVD_MASK 0xFFFF00FFFFFFFFFFULL -#define IPG_RFI_FRAGADDR 0x000000FFFFFFFFFFULL -#define IPG_RFI_FRAGLEN 0xFFFF000000000000ULL - -/* I/O Register masks. */ - -/* RMON Statistics Mask */ -#define IPG_RZ_ALL 0x0FFFFFFF - -/* Statistics Mask */ -#define IPG_SM_ALL 0x0FFFFFFF -#define IPG_SM_OCTETRCVOK_FRAMESRCVDOK 0x00000001 -#define IPG_SM_MCSTOCTETRCVDOK_MCSTFRAMESRCVDOK 0x00000002 -#define IPG_SM_BCSTOCTETRCVDOK_BCSTFRAMESRCVDOK 0x00000004 -#define IPG_SM_RXJUMBOFRAMES 0x00000008 -#define IPG_SM_TCPCHECKSUMERRORS 0x00000010 -#define IPG_SM_IPCHECKSUMERRORS 0x00000020 -#define IPG_SM_UDPCHECKSUMERRORS 0x00000040 -#define IPG_SM_MACCONTROLFRAMESRCVD 0x00000080 -#define IPG_SM_FRAMESTOOLONGERRORS 0x00000100 -#define IPG_SM_INRANGELENGTHERRORS 0x00000200 -#define IPG_SM_FRAMECHECKSEQERRORS 0x00000400 -#define IPG_SM_FRAMESLOSTRXERRORS 0x00000800 -#define IPG_SM_OCTETXMTOK_FRAMESXMTOK 0x00001000 -#define IPG_SM_MCSTOCTETXMTOK_MCSTFRAMESXMTDOK 0x00002000 -#define IPG_SM_BCSTOCTETXMTOK_BCSTFRAMESXMTDOK 0x00004000 -#define IPG_SM_FRAMESWDEFERREDXMT 0x00008000 -#define IPG_SM_LATECOLLISIONS 0x00010000 -#define IPG_SM_MULTICOLFRAMES 0x00020000 -#define IPG_SM_SINGLECOLFRAMES 0x00040000 -#define IPG_SM_TXJUMBOFRAMES 0x00080000 -#define IPG_SM_CARRIERSENSEERRORS 0x00100000 -#define IPG_SM_MACCONTROLFRAMESXMTD 0x00200000 -#define IPG_SM_FRAMESABORTXSCOLLS 0x00400000 -#define IPG_SM_FRAMESWEXDEFERAL 0x00800000 - -/* Countdown */ -#define IPG_CD_RSVD_MASK 0x0700FFFF -#define IPG_CD_COUNT 0x0000FFFF -#define IPG_CD_COUNTDOWNSPEED 0x01000000 -#define IPG_CD_COUNTDOWNMODE 0x02000000 -#define IPG_CD_COUNTINTENABLED 0x04000000 - -/* TxDMABurstThresh */ -#define IPG_TB_RSVD_MASK 0xFF - -/* TxDMAUrgentThresh */ -#define IPG_TU_RSVD_MASK 0xFF - -/* TxDMAPollPeriod */ -#define IPG_TP_RSVD_MASK 0xFF - -/* RxDMAUrgentThresh */ -#define IPG_RU_RSVD_MASK 0xFF - -/* RxDMAPollPeriod */ -#define IPG_RP_RSVD_MASK 0xFF - -/* ReceiveMode */ -#define IPG_RM_RSVD_MASK 0x3F -#define IPG_RM_RECEIVEUNICAST 0x01 -#define IPG_RM_RECEIVEMULTICAST 0x02 -#define IPG_RM_RECEIVEBROADCAST 0x04 -#define IPG_RM_RECEIVEALLFRAMES 0x08 -#define IPG_RM_RECEIVEMULTICASTHASH 0x10 -#define IPG_RM_RECEIVEIPMULTICAST 0x20 - -/* PhySet */ -#define IPG_PS_MEM_LENB9B 0x01 -#define IPG_PS_MEM_LEN9 0x02 -#define IPG_PS_NON_COMPDET 0x04 - -/* PhyCtrl */ -#define IPG_PC_RSVD_MASK 0xFF -#define IPG_PC_MGMTCLK_LO 0x00 -#define IPG_PC_MGMTCLK_HI 0x01 -#define IPG_PC_MGMTCLK 0x01 -#define IPG_PC_MGMTDATA 0x02 -#define IPG_PC_MGMTDIR 0x04 -#define IPG_PC_DUPLEX_POLARITY 0x08 -#define IPG_PC_DUPLEX_STATUS 0x10 -#define IPG_PC_LINK_POLARITY 0x20 -#define IPG_PC_LINK_SPEED 0xC0 -#define IPG_PC_LINK_SPEED_10MBPS 0x40 -#define IPG_PC_LINK_SPEED_100MBPS 0x80 -#define IPG_PC_LINK_SPEED_1000MBPS 0xC0 - -/* DMACtrl */ -#define IPG_DC_RSVD_MASK 0xC07D9818 -#define IPG_DC_RX_DMA_COMPLETE 0x00000008 -#define IPG_DC_RX_DMA_POLL_NOW 0x00000010 -#define IPG_DC_TX_DMA_COMPLETE 0x00000800 -#define IPG_DC_TX_DMA_POLL_NOW 0x00001000 -#define IPG_DC_TX_DMA_IN_PROG 0x00008000 -#define IPG_DC_RX_EARLY_DISABLE 0x00010000 -#define IPG_DC_MWI_DISABLE 0x00040000 -#define IPG_DC_TX_WRITE_BACK_DISABLE 0x00080000 -#define IPG_DC_TX_BURST_LIMIT 0x00700000 -#define IPG_DC_TARGET_ABORT 0x40000000 -#define IPG_DC_MASTER_ABORT 0x80000000 - -/* ASICCtrl */ -#define IPG_AC_RSVD_MASK 0x07FFEFF2 -#define IPG_AC_EXP_ROM_SIZE 0x00000002 -#define IPG_AC_PHY_SPEED10 0x00000010 -#define IPG_AC_PHY_SPEED100 0x00000020 -#define IPG_AC_PHY_SPEED1000 0x00000040 -#define IPG_AC_PHY_MEDIA 0x00000080 -#define IPG_AC_FORCED_CFG 0x00000700 -#define IPG_AC_D3RESETDISABLE 0x00000800 -#define IPG_AC_SPEED_UP_MODE 0x00002000 -#define IPG_AC_LED_MODE 0x00004000 -#define IPG_AC_RST_OUT_POLARITY 0x00008000 -#define IPG_AC_GLOBAL_RESET 0x00010000 -#define IPG_AC_RX_RESET 0x00020000 -#define IPG_AC_TX_RESET 0x00040000 -#define IPG_AC_DMA 0x00080000 -#define IPG_AC_FIFO 0x00100000 -#define IPG_AC_NETWORK 0x00200000 -#define IPG_AC_HOST 0x00400000 -#define IPG_AC_AUTO_INIT 0x00800000 -#define IPG_AC_RST_OUT 0x01000000 -#define IPG_AC_INT_REQUEST 0x02000000 -#define IPG_AC_RESET_BUSY 0x04000000 -#define IPG_AC_LED_SPEED 0x08000000 -#define IPG_AC_LED_MODE_BIT_1 0x20000000 - -/* EepromCtrl */ -#define IPG_EC_RSVD_MASK 0x83FF -#define IPG_EC_EEPROM_ADDR 0x00FF -#define IPG_EC_EEPROM_OPCODE 0x0300 -#define IPG_EC_EEPROM_SUBCOMMAD 0x0000 -#define IPG_EC_EEPROM_WRITEOPCODE 0x0100 -#define IPG_EC_EEPROM_READOPCODE 0x0200 -#define IPG_EC_EEPROM_ERASEOPCODE 0x0300 -#define IPG_EC_EEPROM_BUSY 0x8000 - -/* FIFOCtrl */ -#define IPG_FC_RSVD_MASK 0xC001 -#define IPG_FC_RAM_TEST_MODE 0x0001 -#define IPG_FC_TRANSMITTING 0x4000 -#define IPG_FC_RECEIVING 0x8000 - -/* TxStatus */ -#define IPG_TS_RSVD_MASK 0xFFFF00DD -#define IPG_TS_TX_ERROR 0x00000001 -#define IPG_TS_LATE_COLLISION 0x00000004 -#define IPG_TS_TX_MAX_COLL 0x00000008 -#define IPG_TS_TX_UNDERRUN 0x00000010 -#define IPG_TS_TX_IND_REQD 0x00000040 -#define IPG_TS_TX_COMPLETE 0x00000080 -#define IPG_TS_TX_FRAMEID 0xFFFF0000 - -/* WakeEvent */ -#define IPG_WE_WAKE_PKT_ENABLE 0x01 -#define IPG_WE_MAGIC_PKT_ENABLE 0x02 -#define IPG_WE_LINK_EVT_ENABLE 0x04 -#define IPG_WE_WAKE_POLARITY 0x08 -#define IPG_WE_WAKE_PKT_EVT 0x10 -#define IPG_WE_MAGIC_PKT_EVT 0x20 -#define IPG_WE_LINK_EVT 0x40 -#define IPG_WE_WOL_ENABLE 0x80 - -/* IntEnable */ -#define IPG_IE_RSVD_MASK 0x1FFE -#define IPG_IE_HOST_ERROR 0x0002 -#define IPG_IE_TX_COMPLETE 0x0004 -#define IPG_IE_MAC_CTRL_FRAME 0x0008 -#define IPG_IE_RX_COMPLETE 0x0010 -#define IPG_IE_RX_EARLY 0x0020 -#define IPG_IE_INT_REQUESTED 0x0040 -#define IPG_IE_UPDATE_STATS 0x0080 -#define IPG_IE_LINK_EVENT 0x0100 -#define IPG_IE_TX_DMA_COMPLETE 0x0200 -#define IPG_IE_RX_DMA_COMPLETE 0x0400 -#define IPG_IE_RFD_LIST_END 0x0800 -#define IPG_IE_RX_DMA_PRIORITY 0x1000 - -/* IntStatus */ -#define IPG_IS_RSVD_MASK 0x1FFF -#define IPG_IS_INTERRUPT_STATUS 0x0001 -#define IPG_IS_HOST_ERROR 0x0002 -#define IPG_IS_TX_COMPLETE 0x0004 -#define IPG_IS_MAC_CTRL_FRAME 0x0008 -#define IPG_IS_RX_COMPLETE 0x0010 -#define IPG_IS_RX_EARLY 0x0020 -#define IPG_IS_INT_REQUESTED 0x0040 -#define IPG_IS_UPDATE_STATS 0x0080 -#define IPG_IS_LINK_EVENT 0x0100 -#define IPG_IS_TX_DMA_COMPLETE 0x0200 -#define IPG_IS_RX_DMA_COMPLETE 0x0400 -#define IPG_IS_RFD_LIST_END 0x0800 -#define IPG_IS_RX_DMA_PRIORITY 0x1000 - -/* MACCtrl */ -#define IPG_MC_RSVD_MASK 0x7FE33FA3 -#define IPG_MC_IFS_SELECT 0x00000003 -#define IPG_MC_IFS_4352BIT 0x00000003 -#define IPG_MC_IFS_1792BIT 0x00000002 -#define IPG_MC_IFS_1024BIT 0x00000001 -#define IPG_MC_IFS_96BIT 0x00000000 -#define IPG_MC_DUPLEX_SELECT 0x00000020 -#define IPG_MC_DUPLEX_SELECT_FD 0x00000020 -#define IPG_MC_DUPLEX_SELECT_HD 0x00000000 -#define IPG_MC_TX_FLOW_CONTROL_ENABLE 0x00000080 -#define IPG_MC_RX_FLOW_CONTROL_ENABLE 0x00000100 -#define IPG_MC_RCV_FCS 0x00000200 -#define IPG_MC_FIFO_LOOPBACK 0x00000400 -#define IPG_MC_MAC_LOOPBACK 0x00000800 -#define IPG_MC_AUTO_VLAN_TAGGING 0x00001000 -#define IPG_MC_AUTO_VLAN_UNTAGGING 0x00002000 -#define IPG_MC_COLLISION_DETECT 0x00010000 -#define IPG_MC_CARRIER_SENSE 0x00020000 -#define IPG_MC_STATISTICS_ENABLE 0x00200000 -#define IPG_MC_STATISTICS_DISABLE 0x00400000 -#define IPG_MC_STATISTICS_ENABLED 0x00800000 -#define IPG_MC_TX_ENABLE 0x01000000 -#define IPG_MC_TX_DISABLE 0x02000000 -#define IPG_MC_TX_ENABLED 0x04000000 -#define IPG_MC_RX_ENABLE 0x08000000 -#define IPG_MC_RX_DISABLE 0x10000000 -#define IPG_MC_RX_ENABLED 0x20000000 -#define IPG_MC_PAUSED 0x40000000 - -/* - * Tune - */ - -/* Assign IPG_APPEND_FCS_ON_TX > 0 for auto FCS append on TX. */ -#define IPG_APPEND_FCS_ON_TX 1 - -/* Assign IPG_APPEND_FCS_ON_TX > 0 for auto FCS strip on RX. */ -#define IPG_STRIP_FCS_ON_RX 1 - -/* Assign IPG_DROP_ON_RX_ETH_ERRORS > 0 to drop RX frames with - * Ethernet errors. - */ -#define IPG_DROP_ON_RX_ETH_ERRORS 1 - -/* Assign IPG_INSERT_MANUAL_VLAN_TAG > 0 to insert VLAN tags manually - * (via TFC). - */ -#define IPG_INSERT_MANUAL_VLAN_TAG 0 - -/* Assign IPG_ADD_IPCHECKSUM_ON_TX > 0 for auto IP checksum on TX. */ -#define IPG_ADD_IPCHECKSUM_ON_TX 0 - -/* Assign IPG_ADD_TCPCHECKSUM_ON_TX > 0 for auto TCP checksum on TX. - * DO NOT USE FOR SILICON REVISIONS B3 AND EARLIER. - */ -#define IPG_ADD_TCPCHECKSUM_ON_TX 0 - -/* Assign IPG_ADD_UDPCHECKSUM_ON_TX > 0 for auto UDP checksum on TX. - * DO NOT USE FOR SILICON REVISIONS B3 AND EARLIER. - */ -#define IPG_ADD_UDPCHECKSUM_ON_TX 0 - -/* If inserting VLAN tags manually, assign the IPG_MANUAL_VLAN_xx - * constants as desired. - */ -#define IPG_MANUAL_VLAN_VID 0xABC -#define IPG_MANUAL_VLAN_CFI 0x1 -#define IPG_MANUAL_VLAN_USERPRIORITY 0x5 - -#define IPG_IO_REG_RANGE 0xFF -#define IPG_MEM_REG_RANGE 0x154 -#define IPG_DRIVER_NAME "Sundance Technology IPG Triple-Speed Ethernet" -#define IPG_NIC_PHY_ADDRESS 0x01 -#define IPG_DMALIST_ALIGN_PAD 0x07 -#define IPG_MULTICAST_HASHTABLE_SIZE 0x40 - -/* Number of milliseconds to wait after issuing a software reset. - * 0x05 <= IPG_AC_RESETWAIT to account for proper 10Mbps operation. - */ -#define IPG_AC_RESETWAIT 0x05 - -/* Number of IPG_AC_RESETWAIT timeperiods before declaring timeout. */ -#define IPG_AC_RESET_TIMEOUT 0x0A - -/* Minimum number of nanoseconds used to toggle MDC clock during - * MII/GMII register access. - */ -#define IPG_PC_PHYCTRLWAIT_NS 200 - -#define IPG_TFDLIST_LENGTH 0x100 - -/* Number of frames between TxDMAComplete interrupt. - * 0 < IPG_FRAMESBETWEENTXDMACOMPLETES <= IPG_TFDLIST_LENGTH - */ -#define IPG_FRAMESBETWEENTXDMACOMPLETES 0x1 - -#define IPG_RFDLIST_LENGTH 0x100 - -/* Maximum number of RFDs to process per interrupt. - * 1 < IPG_MAXRFDPROCESS_COUNT < IPG_RFDLIST_LENGTH - */ -#define IPG_MAXRFDPROCESS_COUNT 0x80 - -/* Minimum margin between last freed RFD, and current RFD. - * 1 < IPG_MINUSEDRFDSTOFREE < IPG_RFDLIST_LENGTH - */ -#define IPG_MINUSEDRFDSTOFREE 0x80 - -/* specify the jumbo frame maximum size - * per unit is 0x600 (the rx_buffer size that one RFD can carry) - */ -#define MAX_JUMBOSIZE 0x8 /* max is 12K */ - -/* Key register values loaded at driver start up. */ - -/* TXDMAPollPeriod is specified in 320ns increments. - * - * Value Time - * --------------------- - * 0x00-0x01 320ns - * 0x03 ~1us - * 0x1F ~10us - * 0xFF ~82us - */ -#define IPG_TXDMAPOLLPERIOD_VALUE 0x26 - -/* TxDMAUrgentThresh specifies the minimum amount of - * data in the transmit FIFO before asserting an - * urgent transmit DMA request. - * - * Value Min TxFIFO occupied space before urgent TX request - * --------------------------------------------------------------- - * 0x00-0x04 128 bytes (1024 bits) - * 0x27 1248 bytes (~10000 bits) - * 0x30 1536 bytes (12288 bits) - * 0xFF 8192 bytes (65535 bits) - */ -#define IPG_TXDMAURGENTTHRESH_VALUE 0x04 - -/* TxDMABurstThresh specifies the minimum amount of - * free space in the transmit FIFO before asserting an - * transmit DMA request. - * - * Value Min TxFIFO free space before TX request - * ---------------------------------------------------- - * 0x00-0x08 256 bytes - * 0x30 1536 bytes - * 0xFF 8192 bytes - */ -#define IPG_TXDMABURSTTHRESH_VALUE 0x30 - -/* RXDMAPollPeriod is specified in 320ns increments. - * - * Value Time - * --------------------- - * 0x00-0x01 320ns - * 0x03 ~1us - * 0x1F ~10us - * 0xFF ~82us - */ -#define IPG_RXDMAPOLLPERIOD_VALUE 0x01 - -/* RxDMAUrgentThresh specifies the minimum amount of - * free space within the receive FIFO before asserting - * a urgent receive DMA request. - * - * Value Min RxFIFO free space before urgent RX request - * --------------------------------------------------------------- - * 0x00-0x04 128 bytes (1024 bits) - * 0x27 1248 bytes (~10000 bits) - * 0x30 1536 bytes (12288 bits) - * 0xFF 8192 bytes (65535 bits) - */ -#define IPG_RXDMAURGENTTHRESH_VALUE 0x30 - -/* RxDMABurstThresh specifies the minimum amount of - * occupied space within the receive FIFO before asserting - * a receive DMA request. - * - * Value Min TxFIFO free space before TX request - * ---------------------------------------------------- - * 0x00-0x08 256 bytes - * 0x30 1536 bytes - * 0xFF 8192 bytes - */ -#define IPG_RXDMABURSTTHRESH_VALUE 0x30 - -/* FlowOnThresh specifies the maximum amount of occupied - * space in the receive FIFO before a PAUSE frame with - * maximum pause time transmitted. - * - * Value Max RxFIFO occupied space before PAUSE - * --------------------------------------------------- - * 0x0000 0 bytes - * 0x0740 29,696 bytes - * 0x07FF 32,752 bytes - */ -#define IPG_FLOWONTHRESH_VALUE 0x0740 - -/* FlowOffThresh specifies the minimum amount of occupied - * space in the receive FIFO before a PAUSE frame with - * zero pause time is transmitted. - * - * Value Max RxFIFO occupied space before PAUSE - * --------------------------------------------------- - * 0x0000 0 bytes - * 0x00BF 3056 bytes - * 0x07FF 32,752 bytes - */ -#define IPG_FLOWOFFTHRESH_VALUE 0x00BF - -/* - * Miscellaneous macros. - */ - -/* Macros for printing debug statements. */ -#ifdef IPG_DEBUG -# define IPG_DEBUG_MSG(fmt, args...) \ -do { \ - if (0) \ - printk(KERN_DEBUG "IPG: " fmt, ##args); \ -} while (0) -# define IPG_DDEBUG_MSG(fmt, args...) \ - printk(KERN_DEBUG "IPG: " fmt, ##args) -# define IPG_DUMPRFDLIST(args) ipg_dump_rfdlist(args) -# define IPG_DUMPTFDLIST(args) ipg_dump_tfdlist(args) -#else -# define IPG_DEBUG_MSG(fmt, args...) \ -do { \ - if (0) \ - printk(KERN_DEBUG "IPG: " fmt, ##args); \ -} while (0) -# define IPG_DDEBUG_MSG(fmt, args...) \ -do { \ - if (0) \ - printk(KERN_DEBUG "IPG: " fmt, ##args); \ -} while (0) -# define IPG_DUMPRFDLIST(args) -# define IPG_DUMPTFDLIST(args) -#endif - -/* - * End miscellaneous macros. - */ - -/* Transmit Frame Descriptor. The IPG supports 15 fragments, - * however Linux requires only a single fragment. Note, each - * TFD field is 64 bits wide. - */ -struct ipg_tx { - __le64 next_desc; - __le64 tfc; - __le64 frag_info; -}; - -/* Receive Frame Descriptor. Note, each RFD field is 64 bits wide. - */ -struct ipg_rx { - __le64 next_desc; - __le64 rfs; - __le64 frag_info; -}; - -struct ipg_jumbo { - int found_start; - int current_size; - struct sk_buff *skb; -}; - -/* Structure of IPG NIC specific data. */ -struct ipg_nic_private { - void __iomem *ioaddr; - struct ipg_tx *txd; - struct ipg_rx *rxd; - dma_addr_t txd_map; - dma_addr_t rxd_map; - struct sk_buff *tx_buff[IPG_TFDLIST_LENGTH]; - struct sk_buff *rx_buff[IPG_RFDLIST_LENGTH]; - unsigned int tx_current; - unsigned int tx_dirty; - unsigned int rx_current; - unsigned int rx_dirty; - bool is_jumbo; - struct ipg_jumbo jumbo; - unsigned long rxfrag_size; - unsigned long rxsupport_size; - unsigned long max_rxframe_size; - unsigned int rx_buf_sz; - struct pci_dev *pdev; - struct net_device *dev; - struct net_device_stats stats; - spinlock_t lock; - int tenmbpsmode; - - u16 led_mode; - u16 station_addr[3]; /* Station Address in EEPROM Reg 0x10..0x12 */ - - struct mutex mii_mutex; - struct mii_if_info mii_if; - int reset_current_tfd; -#ifdef IPG_DEBUG - int RFDlistendCount; - int RFDListCheckedCount; - int EmptyRFDListCount; -#endif - struct delayed_work task; -}; - -#endif /* __LINUX_IPG_H */ -- cgit v1.2.3 From 6c606fa32c4272894248c1abbc15257fc04250be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 16 Nov 2015 14:36:32 +0200 Subject: via-velocity: unconditionally drop frames with bad l2 length MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By default the driver allowed incorrect frames to be received. What is worse the code does not handle very short frames correctly. The FCS length is unconditionally subtracted, and the underflow can cause skb_put to be called with large number after implicit cast to unsigned. And indeed, an skb_over_panic() was observed with via-velocity. This removes the module parameter as it does not work in it's current state, and should be implemented via NETIF_F_RXALL if needed. Suggested-by: Francois Romieu Signed-off-by: Timo Teräs Signed-off-by: David S. Miller --- drivers/net/ethernet/via/via-velocity.c | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index ae68afd50a15..f38696ceee74 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -345,13 +345,6 @@ VELOCITY_PARAM(flow_control, "Enable flow control ability"); */ VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode"); -#define VAL_PKT_LEN_DEF 0 -/* ValPktLen[] is used for setting the checksum offload ability of NIC. - 0: Receive frame with invalid layer 2 length (Default) - 1: Drop frame with invalid layer 2 length -*/ -VELOCITY_PARAM(ValPktLen, "Receiving or Drop invalid 802.3 frame"); - #define WOL_OPT_DEF 0 #define WOL_OPT_MIN 0 #define WOL_OPT_MAX 7 @@ -494,7 +487,6 @@ static void velocity_get_options(struct velocity_opt *opts, int index, velocity_set_int_opt(&opts->flow_cntl, flow_control[index], FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF, "flow_control", devname); velocity_set_bool_opt(&opts->flags, IP_byte_align[index], IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align", devname); - velocity_set_bool_opt(&opts->flags, ValPktLen[index], VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen", devname); velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname); velocity_set_int_opt(&opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname); opts->numrx = (opts->numrx & ~3); @@ -2055,8 +2047,9 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) int pkt_len = le16_to_cpu(rd->rdesc0.len) & 0x3fff; struct sk_buff *skb; - if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) { - VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame spans multiple RDs.\n", vptr->netdev->name); + if (unlikely(rd->rdesc0.RSR & (RSR_STP | RSR_EDP | RSR_RL))) { + if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) + VELOCITY_PRT(MSG_LEVEL_VERBOSE, KERN_ERR " %s : the received frame spans multiple RDs.\n", vptr->netdev->name); stats->rx_length_errors++; return -EINVAL; } @@ -2069,17 +2062,6 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) dma_sync_single_for_cpu(vptr->dev, rd_info->skb_dma, vptr->rx.buf_sz, DMA_FROM_DEVICE); - /* - * Drop frame not meeting IEEE 802.3 - */ - - if (vptr->flags & VELOCITY_FLAGS_VAL_PKT_LEN) { - if (rd->rdesc0.RSR & RSR_RL) { - stats->rx_length_errors++; - return -EINVAL; - } - } - velocity_rx_csum(rd, skb); if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) { -- cgit v1.2.3 From cf554ada0be7077906aa9a17faf151ff66e3cb8e Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Mon, 16 Nov 2015 22:34:26 +0100 Subject: ipvlan: fix leak in ipvlan_rcv_frame Pass a **skb to ipvlan_rcv_frame so that if skb_share_check returns a new skb, we actually use it during further processing. It's safe to ignore the new skb in the ipvlan_xmit_* functions, because they call ipvlan_rcv_frame with local == true, so that dev_forward_skb is called and always takes ownership of the skb. Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.") Signed-off-by: Sabrina Dubroca Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_core.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index d50887e3df6d..a9148e46dad0 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -254,7 +254,7 @@ acct: } } -static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb, +static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff **pskb, bool local) { struct ipvl_dev *ipvlan = addr->master; @@ -262,6 +262,7 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb, unsigned int len; rx_handler_result_t ret = RX_HANDLER_CONSUMED; bool success = false; + struct sk_buff *skb = *pskb; len = skb->len + ETH_HLEN; if (unlikely(!(dev->flags & IFF_UP))) { @@ -273,6 +274,7 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb, if (!skb) goto out; + *pskb = skb; skb->dev = dev; skb->pkt_type = PACKET_HOST; @@ -486,7 +488,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev) addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true); if (addr) - return ipvlan_rcv_frame(addr, skb, true); + return ipvlan_rcv_frame(addr, &skb, true); out: skb->dev = ipvlan->phy_dev; @@ -506,7 +508,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) if (lyr3h) { addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true); if (addr) - return ipvlan_rcv_frame(addr, skb, true); + return ipvlan_rcv_frame(addr, &skb, true); } skb = skb_share_check(skb, GFP_ATOMIC); if (!skb) @@ -589,7 +591,7 @@ static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb, addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true); if (addr) - ret = ipvlan_rcv_frame(addr, skb, false); + ret = ipvlan_rcv_frame(addr, pskb, false); out: return ret; @@ -626,7 +628,7 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb, addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true); if (addr) - ret = ipvlan_rcv_frame(addr, skb, false); + ret = ipvlan_rcv_frame(addr, pskb, false); } return ret; -- cgit v1.2.3 From a534dc529853c69e94994aa47c1d80a03ce2c11d Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Mon, 16 Nov 2015 22:44:53 +0100 Subject: ipvlan: fix use after free of skb ipvlan_handle_frame is a rx_handler, and when it returns a value other than RX_HANDLER_CONSUMED (here, NET_RX_DROP aka RX_HANDLER_ANOTHER), __netif_receive_skb_core expects that the skb still exists and will process it further, but we just freed it. Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.") Signed-off-by: Sabrina Dubroca Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index a9148e46dad0..8c48bb2a94ea 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -653,5 +653,5 @@ rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb) WARN_ONCE(true, "ipvlan_handle_frame() called for mode = [%hx]\n", port->mode); kfree_skb(skb); - return NET_RX_DROP; + return RX_HANDLER_CONSUMED; } -- cgit v1.2.3 From e639b8d8a7a728f0b05ef2df6cb6b45dc3d4e556 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Mon, 16 Nov 2015 22:54:20 +0100 Subject: macvlan: fix leak in macvlan_handle_frame Reset pskb in macvlan_handle_frame in case skb_share_check returned a clone. Fixes: 8a4eb5734e8d ("net: introduce rx_handler results and logic around that") Signed-off-by: Sabrina Dubroca Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 86f6c6292c27..06c8bfeaccd6 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -415,6 +415,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) skb = ip_check_defrag(dev_net(skb->dev), skb, IP_DEFRAG_MACVLAN); if (!skb) return RX_HANDLER_CONSUMED; + *pskb = skb; eth = eth_hdr(skb); macvlan_forward_source(skb, port, eth->h_source); src = macvlan_hash_lookup(port, eth->h_source); @@ -456,6 +457,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) goto out; } + *pskb = skb; skb->dev = dev; skb->pkt_type = PACKET_HOST; -- cgit v1.2.3 From 819ec8e1f349f73bdf65bf33a364538e59007a9a Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Mon, 16 Nov 2015 23:34:41 +0100 Subject: phy: marvell: Add support for 88E1540 PHY The 88E1540 can be found embedded in the Marvell 88E6352 switch. It is compatible with the 88E1510, so add support for it, using the 88E1510 specific functions. Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/marvell.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 5de8d5827536..0240552b50f3 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -1153,6 +1153,21 @@ static struct phy_driver marvell_drivers[] = { .suspend = &genphy_suspend, .driver = { .owner = THIS_MODULE }, }, + { + .phy_id = MARVELL_PHY_ID_88E1540, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E1540", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &m88e1510_config_aneg, + .read_status = &marvell_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .did_interrupt = &m88e1121_did_interrupt, + .resume = &genphy_resume, + .suspend = &genphy_suspend, + .driver = { .owner = THIS_MODULE }, + }, { .phy_id = MARVELL_PHY_ID_88E3016, .phy_id_mask = MARVELL_PHY_ID_MASK, @@ -1186,6 +1201,7 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = { { MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E1116R, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK }, { } }; -- cgit v1.2.3 From 321beec5047af83db90c88114b7e664b156f49fe Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Mon, 16 Nov 2015 23:36:46 +0100 Subject: net: phy: Use interrupts when available in NOLINK state The NOLINK state will poll the phy once a second to see if the link has come up. If the phy has an interrupt line, this polling can be skipped, since the phy should interrupt when the link returns. Signed-off-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index adb48abafc87..48ce6ef400fe 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -863,6 +863,9 @@ void phy_state_machine(struct work_struct *work) needs_aneg = true; break; case PHY_NOLINK: + if (phy_interrupt_is_valid(phydev)) + break; + err = phy_read_status(phydev); if (err) break; -- cgit v1.2.3 From 1a47de6e4a8dc2aaf3c3fb544b60730b74abe0f1 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 20 Nov 2015 15:57:07 -0800 Subject: various: fix pci_set_dma_mask return value checking pci_set_dma_mask returns a negative errno value, not a bool like pci_dma_supported. This of course was just a giant test for attention :) Signed-off-by: Christoph Hellwig Reported-by: Jongman Heo Tested-by: Jongman Heo [pcnet32] Acked-by: Mauro Carvalho Chehab Cc: Hans Verkuil Cc: Antti Palosaari Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/ethernet/amd/pcnet32.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index e2afabf3a465..7ccebae9cb48 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c @@ -1500,10 +1500,11 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } - if (!pci_set_dma_mask(pdev, PCNET32_DMA_MASK)) { + err = pci_set_dma_mask(pdev, PCNET32_DMA_MASK); + if (err) { if (pcnet32_debug & NETIF_MSG_PROBE) pr_err("architecture does not support 32bit PCI busmaster DMA\n"); - return -ENODEV; + return err; } if (!request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci")) { if (pcnet32_debug & NETIF_MSG_PROBE) -- cgit v1.2.3